summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING4
-rw-r--r--Documentation/00-INDEX4
-rw-r--r--Documentation/CodingStyle3
-rw-r--r--Documentation/DMA-API.txt2
-rw-r--r--Documentation/DMA-ISA-LPC.txt151
-rw-r--r--Documentation/DocBook/journal-api.tmpl4
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl310
-rw-r--r--Documentation/DocBook/mcabook.tmpl2
-rw-r--r--Documentation/DocBook/usb.tmpl2
-rw-r--r--Documentation/IPMI.txt13
-rw-r--r--Documentation/MSI-HOWTO.txt2
-rw-r--r--Documentation/RCU/NMI-RCU.txt112
-rw-r--r--Documentation/RCU/RTFP.txt36
-rw-r--r--Documentation/RCU/UP.txt79
-rw-r--r--Documentation/RCU/checklist.txt23
-rw-r--r--Documentation/RCU/rcu.txt48
-rw-r--r--Documentation/RCU/rcuref.txt74
-rw-r--r--Documentation/RCU/whatisRCU.txt902
-rw-r--r--Documentation/acpi-hotkey.txt2
-rw-r--r--Documentation/aoe/mkshelf.sh6
-rw-r--r--Documentation/applying-patches.txt439
-rw-r--r--Documentation/cciss.txt4
-rw-r--r--Documentation/cdrom/sonycd5353
-rw-r--r--Documentation/connector/cn_test.c194
-rw-r--r--Documentation/connector/connector.txt133
-rw-r--r--Documentation/cpu-freq/cpufreq-stats.txt2
-rw-r--r--Documentation/cpusets.txt14
-rw-r--r--Documentation/crypto/api-intro.txt1
-rw-r--r--Documentation/crypto/descore-readme.txt2
-rw-r--r--Documentation/dcdbas.txt91
-rw-r--r--Documentation/dell_rbu.txt74
-rw-r--r--Documentation/dontdiff1
-rw-r--r--Documentation/dvb/bt8xx.txt89
-rw-r--r--Documentation/dvb/ci.txt9
-rw-r--r--Documentation/exception.txt2
-rw-r--r--Documentation/fb/cyblafb/bugs14
-rw-r--r--Documentation/fb/cyblafb/credits7
-rw-r--r--Documentation/fb/cyblafb/documentation17
-rw-r--r--Documentation/fb/cyblafb/fb.modes155
-rw-r--r--Documentation/fb/cyblafb/performance80
-rw-r--r--Documentation/fb/cyblafb/todo32
-rw-r--r--Documentation/fb/cyblafb/usage206
-rw-r--r--Documentation/fb/cyblafb/whycyblafb85
-rw-r--r--Documentation/fb/intel810.txt56
-rw-r--r--Documentation/fb/modedb.txt73
-rw-r--r--Documentation/feature-removal-schedule.txt64
-rw-r--r--Documentation/filesystems/files.txt123
-rw-r--r--Documentation/filesystems/fuse.txt315
-rw-r--r--Documentation/filesystems/ntfs.txt12
-rw-r--r--Documentation/filesystems/proc.txt41
-rw-r--r--Documentation/filesystems/relayfs.txt362
-rw-r--r--Documentation/filesystems/sysfs.txt28
-rw-r--r--Documentation/filesystems/v9fs.txt95
-rw-r--r--Documentation/filesystems/vfs.txt435
-rw-r--r--Documentation/firmware_class/firmware_sample_driver.c8
-rw-r--r--Documentation/hwmon/lm787
-rw-r--r--Documentation/hwmon/w83792d174
-rw-r--r--Documentation/i2c/chips/max687594
-rw-r--r--Documentation/i2c/functionality2
-rw-r--r--Documentation/i2c/porting-clients25
-rw-r--r--Documentation/i2c/writing-clients114
-rw-r--r--Documentation/i386/boot.txt35
-rw-r--r--Documentation/ibm-acpi.txt376
-rw-r--r--Documentation/input/appletouch.txt84
-rw-r--r--Documentation/input/yealink.txt203
-rw-r--r--Documentation/ioctl/cdrom.txt2
-rw-r--r--Documentation/kbuild/makefiles.txt20
-rw-r--r--Documentation/kdump/kdump.txt27
-rw-r--r--Documentation/kernel-parameters.txt15
-rw-r--r--Documentation/mono.txt2
-rw-r--r--Documentation/networking/README.ipw2100246
-rw-r--r--Documentation/networking/README.ipw2200300
-rw-r--r--Documentation/networking/bonding.txt4
-rw-r--r--Documentation/networking/cxgb.txt352
-rw-r--r--Documentation/networking/phy.txt288
-rw-r--r--Documentation/networking/wan-router.txt4
-rw-r--r--Documentation/oops-tracing.txt25
-rw-r--r--Documentation/pci.txt2
-rw-r--r--Documentation/pm.txt6
-rw-r--r--Documentation/power/swsusp-dmcrypt.txt138
-rw-r--r--Documentation/power/swsusp.txt102
-rw-r--r--Documentation/power/video.txt10
-rw-r--r--Documentation/powerpc/eeh-pci-error-recovery.txt2
-rw-r--r--Documentation/s390/s390dbf.txt2
-rw-r--r--Documentation/scsi/00-INDEX2
-rw-r--r--Documentation/scsi/aic7xxx.txt6
-rw-r--r--Documentation/scsi/ibmmca.txt2
-rw-r--r--Documentation/scsi/scsi_eh.txt479
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt41
-rw-r--r--Documentation/serial/driver15
-rw-r--r--Documentation/sonypi.txt10
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt127
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl25
-rw-r--r--Documentation/sparse.txt2
-rw-r--r--Documentation/sysrq.txt2
-rw-r--r--Documentation/uml/UserModeLinux-HOWTO.txt2
-rw-r--r--Documentation/usb/gadget_serial.txt2
-rw-r--r--Documentation/usb/proc_usb_info.txt13
-rw-r--r--Documentation/video4linux/CARDLIST.bttv4
-rw-r--r--Documentation/video4linux/CARDLIST.saa71343
-rw-r--r--Documentation/video4linux/CARDLIST.tuner1
-rw-r--r--Documentation/video4linux/Zoran2
-rw-r--r--Documentation/vm/locking15
-rw-r--r--Documentation/watchdog/watchdog-api.txt20
-rw-r--r--Documentation/x86_64/boot-options.txt5
-rw-r--r--Kbuild49
-rw-r--r--MAINTAINERS93
-rw-r--r--Makefile248
-rw-r--r--REPORTING-BUGS14
-rw-r--r--arch/alpha/Kconfig3
-rw-r--r--arch/alpha/Makefile11
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c9
-rw-r--r--arch/alpha/kernel/entry.S2
-rw-r--r--arch/alpha/kernel/head.S2
-rw-r--r--arch/alpha/kernel/module.c8
-rw-r--r--arch/alpha/kernel/osf_sys.c7
-rw-r--r--arch/alpha/kernel/signal.c11
-rw-r--r--arch/alpha/kernel/smp.c172
-rw-r--r--arch/alpha/kernel/sys_marvel.c5
-rw-r--r--arch/alpha/kernel/time.c7
-rw-r--r--arch/alpha/lib/dbg_stackcheck.S2
-rw-r--r--arch/alpha/lib/dbg_stackkill.S2
-rw-r--r--arch/arm/Kconfig51
-rw-r--r--arch/arm/Kconfig.debug2
-rw-r--r--arch/arm/Makefile11
-rw-r--r--arch/arm/boot/compressed/head-sharpsl.S111
-rw-r--r--arch/arm/common/Kconfig3
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/gic.c167
-rw-r--r--arch/arm/common/locomo.c125
-rw-r--r--arch/arm/common/sa1111.c8
-rw-r--r--arch/arm/common/scoop.c8
-rw-r--r--arch/arm/configs/omap_h2_1610_defconfig290
-rw-r--r--arch/arm/configs/s3c2410_defconfig218
-rw-r--r--arch/arm/kernel/calls.S7
-rw-r--r--arch/arm/kernel/ecard.c4
-rw-r--r--arch/arm/kernel/entry-common.S8
-rw-r--r--arch/arm/kernel/entry-header.S2
-rw-r--r--arch/arm/kernel/head.S2
-rw-r--r--arch/arm/kernel/irq.c20
-rw-r--r--arch/arm/kernel/iwmmxt.S2
-rw-r--r--arch/arm/kernel/signal.c5
-rw-r--r--arch/arm/kernel/smp.c2
-rw-r--r--arch/arm/kernel/sys_arm.c10
-rw-r--r--arch/arm/kernel/time.c17
-rw-r--r--arch/arm/lib/copy_page.S2
-rw-r--r--arch/arm/lib/csumpartialcopyuser.S2
-rw-r--r--arch/arm/lib/getuser.S2
-rw-r--r--arch/arm/lib/putuser.S2
-rw-r--r--arch/arm/mach-clps7500/core.c2
-rw-r--r--arch/arm/mach-ebsa110/core.c2
-rw-r--r--arch/arm/mach-epxa10db/arch.c2
-rw-r--r--arch/arm/mach-footbridge/Kconfig1
-rw-r--r--arch/arm/mach-footbridge/isa-irq.c2
-rw-r--r--arch/arm/mach-footbridge/isa.c2
-rw-r--r--arch/arm/mach-h720x/common.c2
-rw-r--r--arch/arm/mach-h720x/cpu-h7202.c4
-rw-r--r--arch/arm/mach-imx/irq.c4
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c2
-rw-r--r--arch/arm/mach-iop3xx/iop321-time.c2
-rw-r--r--arch/arm/mach-iop3xx/iop331-time.c2
-rw-r--r--arch/arm/mach-ixp2000/core.c12
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c2
-rw-r--r--arch/arm/mach-ixp4xx/common.c167
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c7
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c11
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-pci.c28
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c10
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c12
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c15
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c4
-rw-r--r--arch/arm/mach-lh7a40x/common.h2
-rw-r--r--arch/arm/mach-omap1/Kconfig8
-rw-r--r--arch/arm/mach-omap1/Makefile3
-rw-r--r--arch/arm/mach-omap1/board-generic.c38
-rw-r--r--arch/arm/mach-omap1/board-h2.c27
-rw-r--r--arch/arm/mach-omap1/board-h3.c17
-rw-r--r--arch/arm/mach-omap1/board-innovator.c13
-rw-r--r--arch/arm/mach-omap1/board-netstar.c9
-rw-r--r--arch/arm/mach-omap1/board-osk.c124
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c5
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c64
-rw-r--r--arch/arm/mach-omap1/devices.c351
-rw-r--r--arch/arm/mach-omap1/fpga.c6
-rw-r--r--arch/arm/mach-omap1/io.c30
-rw-r--r--arch/arm/mach-omap1/irq.c10
-rw-r--r--arch/arm/mach-omap1/leds-h2p2-debug.c3
-rw-r--r--arch/arm/mach-omap1/leds-innovator.c2
-rw-r--r--arch/arm/mach-omap1/leds-osk.c8
-rw-r--r--arch/arm/mach-omap1/leds.c12
-rw-r--r--arch/arm/mach-omap1/serial.c86
-rw-r--r--arch/arm/mach-omap1/time.c40
-rw-r--r--arch/arm/mach-pxa/Kconfig49
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/corgi.c126
-rw-r--r--arch/arm/mach-pxa/corgi_lcd.c565
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c68
-rw-r--r--arch/arm/mach-pxa/irq.c12
-rw-r--r--arch/arm/mach-pxa/lubbock.c2
-rw-r--r--arch/arm/mach-pxa/mainstone.c2
-rw-r--r--arch/arm/mach-pxa/poodle.c12
-rw-r--r--arch/arm/mach-pxa/sharpsl.h34
-rw-r--r--arch/arm/mach-pxa/spitz.c380
-rw-r--r--arch/arm/mach-pxa/time.c58
-rw-r--r--arch/arm/mach-rpc/riscpc.c2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig15
-rw-r--r--arch/arm/mach-s3c2410/Makefile5
-rw-r--r--arch/arm/mach-s3c2410/bast-irq.c77
-rw-r--r--arch/arm/mach-s3c2410/clock.c9
-rw-r--r--arch/arm/mach-s3c2410/devs.c11
-rw-r--r--arch/arm/mach-s3c2410/irq.c22
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c270
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c51
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c30
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c2
-rw-r--r--arch/arm/mach-s3c2410/pm-simtec.c2
-rw-r--r--arch/arm/mach-s3c2410/pm.c6
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c6
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-irq.c8
-rw-r--r--arch/arm/mach-s3c2410/time.c2
-rw-r--r--arch/arm/mach-sa1100/assabet.c7
-rw-r--r--arch/arm/mach-sa1100/cerf.c7
-rw-r--r--arch/arm/mach-sa1100/generic.c5
-rw-r--r--arch/arm/mach-sa1100/generic.h3
-rw-r--r--arch/arm/mach-sa1100/irq.c10
-rw-r--r--arch/arm/mach-sa1100/lart.c12
-rw-r--r--arch/arm/mach-sa1100/neponset.c6
-rw-r--r--arch/arm/mach-sa1100/shannon.c7
-rw-r--r--arch/arm/mach-sa1100/simpad.c7
-rw-r--r--arch/arm/mach-sa1100/time.c68
-rw-r--r--arch/arm/mach-shark/core.c2
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--arch/arm/mm/alignment.c70
-rw-r--r--arch/arm/mm/copypage-v3.S2
-rw-r--r--arch/arm/mm/copypage-v4wb.S2
-rw-r--r--arch/arm/mm/copypage-v4wt.S2
-rw-r--r--arch/arm/mm/flush.c52
-rw-r--r--arch/arm/mm/mm-armv.c30
-rw-r--r--arch/arm/mm/proc-arm1020.S2
-rw-r--r--arch/arm/mm/proc-arm1020e.S2
-rw-r--r--arch/arm/mm/proc-arm1022.S2
-rw-r--r--arch/arm/mm/proc-arm1026.S2
-rw-r--r--arch/arm/mm/proc-arm6_7.S10
-rw-r--r--arch/arm/mm/proc-arm720.S2
-rw-r--r--arch/arm/mm/proc-macros.S2
-rw-r--r--arch/arm/mm/proc-sa110.S2
-rw-r--r--arch/arm/mm/proc-sa1100.S2
-rw-r--r--arch/arm/mm/proc-v6.S2
-rw-r--r--arch/arm/mm/tlb-v3.S2
-rw-r--r--arch/arm/mm/tlb-v4.S2
-rw-r--r--arch/arm/mm/tlb-v4wb.S2
-rw-r--r--arch/arm/mm/tlb-v4wbi.S2
-rw-r--r--arch/arm/mm/tlb-v6.S2
-rw-r--r--arch/arm/nwfpe/entry26.S2
-rw-r--r--arch/arm/plat-omap/Kconfig16
-rw-r--r--arch/arm/plat-omap/Makefile4
-rw-r--r--arch/arm/plat-omap/clock.c39
-rw-r--r--arch/arm/plat-omap/common.c7
-rw-r--r--arch/arm/plat-omap/dma.c25
-rw-r--r--arch/arm/plat-omap/dmtimer.c260
-rw-r--r--arch/arm/plat-omap/gpio.c524
-rw-r--r--arch/arm/plat-omap/mcbsp.c9
-rw-r--r--arch/arm/plat-omap/mux.c3
-rw-r--r--arch/arm/plat-omap/ocpi.c1
-rw-r--r--arch/arm/plat-omap/pm.c255
-rw-r--r--arch/arm/plat-omap/sleep.S83
-rw-r--r--arch/arm/plat-omap/sram-fn.S58
-rw-r--r--arch/arm/plat-omap/sram.c116
-rw-r--r--arch/arm/plat-omap/sram.h21
-rw-r--r--arch/arm/plat-omap/usb.c1
-rw-r--r--arch/arm/vfp/entry.S2
-rw-r--r--arch/arm26/Kconfig4
-rw-r--r--arch/arm26/Makefile14
-rw-r--r--arch/arm26/kernel/entry.S2
-rw-r--r--arch/arm26/kernel/signal.c13
-rw-r--r--arch/arm26/kernel/time.c7
-rw-r--r--arch/arm26/lib/copy_page.S2
-rw-r--r--arch/arm26/lib/csumpartialcopyuser.S2
-rw-r--r--arch/arm26/lib/getuser.S2
-rw-r--r--arch/arm26/lib/putuser.S2
-rw-r--r--arch/arm26/mm/proc-funcs.S2
-rw-r--r--arch/arm26/nwfpe/entry.S2
-rw-r--r--arch/cris/Kconfig.debug31
-rw-r--r--arch/cris/Makefile10
-rw-r--r--arch/cris/arch-v10/kernel/entry.S2
-rw-r--r--arch/cris/arch-v10/kernel/signal.c11
-rw-r--r--arch/cris/arch-v10/kernel/time.c2
-rw-r--r--arch/cris/arch-v32/kernel/entry.S2
-rw-r--r--arch/cris/arch-v32/kernel/signal.c11
-rw-r--r--arch/cris/kernel/time.c5
-rw-r--r--arch/frv/kernel/asm-offsets.c1
-rw-r--r--arch/frv/kernel/frv_ksyms.c1
-rw-r--r--arch/frv/kernel/signal.c11
-rw-r--r--arch/frv/kernel/time.c7
-rw-r--r--arch/h8300/Makefile8
-rw-r--r--arch/h8300/kernel/signal.c11
-rw-r--r--arch/h8300/kernel/time.c5
-rw-r--r--arch/i386/Kconfig15
-rw-r--r--arch/i386/Makefile9
-rw-r--r--arch/i386/boot/setup.S2
-rw-r--r--arch/i386/boot/tools/build.c4
-rw-r--r--arch/i386/boot/video.S7
-rw-r--r--arch/i386/defconfig4
-rw-r--r--arch/i386/kernel/Makefile4
-rw-r--r--arch/i386/kernel/acpi/Makefile2
-rw-r--r--arch/i386/kernel/acpi/boot.c560
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c50
-rw-r--r--arch/i386/kernel/acpi/sleep.c35
-rw-r--r--arch/i386/kernel/acpi/wakeup.S6
-rw-r--r--arch/i386/kernel/cpu/common.c18
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c57
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c16
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c20
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c2
-rw-r--r--arch/i386/kernel/cpu/cyrix.c6
-rw-r--r--arch/i386/kernel/cpu/intel.c9
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c9
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c2
-rw-r--r--arch/i386/kernel/crash.c2
-rw-r--r--arch/i386/kernel/dmi_scan.c231
-rw-r--r--arch/i386/kernel/doublefault.c2
-rw-r--r--arch/i386/kernel/efi.c110
-rw-r--r--arch/i386/kernel/entry.S26
-rw-r--r--arch/i386/kernel/head.S50
-rw-r--r--arch/i386/kernel/i8237.c67
-rw-r--r--arch/i386/kernel/io_apic.c80
-rw-r--r--arch/i386/kernel/ioport.c7
-rw-r--r--arch/i386/kernel/kprobes.c35
-rw-r--r--arch/i386/kernel/ldt.c7
-rw-r--r--arch/i386/kernel/machine_kexec.c18
-rw-r--r--arch/i386/kernel/microcode.c7
-rw-r--r--arch/i386/kernel/mpparse.c39
-rw-r--r--arch/i386/kernel/msr.c31
-rw-r--r--arch/i386/kernel/nmi.c10
-rw-r--r--arch/i386/kernel/process.c43
-rw-r--r--arch/i386/kernel/ptrace.c79
-rw-r--r--arch/i386/kernel/reboot.c16
-rw-r--r--arch/i386/kernel/semaphore.c162
-rw-r--r--arch/i386/kernel/setup.c56
-rw-r--r--arch/i386/kernel/sigframe.h8
-rw-r--r--arch/i386/kernel/signal.c13
-rw-r--r--arch/i386/kernel/smp.c2
-rw-r--r--arch/i386/kernel/smpboot.c12
-rw-r--r--arch/i386/kernel/srat.c8
-rw-r--r--arch/i386/kernel/time.c26
-rw-r--r--arch/i386/kernel/timers/timer_hpet.c23
-rw-r--r--arch/i386/kernel/timers/timer_pit.c27
-rw-r--r--arch/i386/kernel/timers/timer_pm.c9
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c14
-rw-r--r--arch/i386/kernel/traps.c27
-rw-r--r--arch/i386/kernel/vm86.c10
-rw-r--r--arch/i386/kernel/vmlinux.lds.S12
-rw-r--r--arch/i386/kernel/vsyscall-sigreturn.S5
-rw-r--r--arch/i386/kernel/vsyscall.lds.S2
-rw-r--r--arch/i386/mach-default/topology.c4
-rw-r--r--arch/i386/mach-es7000/es7000.h5
-rw-r--r--arch/i386/mach-es7000/es7000plat.c49
-rw-r--r--arch/i386/mach-generic/bigsmp.c5
-rw-r--r--arch/i386/mach-generic/probe.c20
-rw-r--r--arch/i386/mach-voyager/voyager_basic.c14
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c5
-rw-r--r--arch/i386/math-emu/get_address.c13
-rw-r--r--arch/i386/mm/discontig.c8
-rw-r--r--arch/i386/mm/fault.c41
-rw-r--r--arch/i386/mm/hugetlbpage.c27
-rw-r--r--arch/i386/mm/init.c9
-rw-r--r--arch/i386/mm/pageattr.c7
-rw-r--r--arch/i386/mm/pgtable.c10
-rw-r--r--arch/i386/oprofile/init.c12
-rw-r--r--arch/i386/oprofile/nmi_int.c4
-rw-r--r--arch/i386/oprofile/nmi_timer_int.c2
-rw-r--r--arch/i386/pci/Makefile2
-rw-r--r--arch/i386/pci/acpi.c17
-rw-r--r--arch/i386/pci/common.c1
-rw-r--r--arch/i386/pci/i386.c55
-rw-r--r--arch/i386/pci/irq.c2
-rw-r--r--arch/i386/pci/mmconfig.c7
-rw-r--r--arch/i386/power/cpu.c43
-rw-r--r--arch/i386/power/swsusp.S2
-rw-r--r--arch/ia64/Kconfig43
-rw-r--r--arch/ia64/Makefile21
-rw-r--r--arch/ia64/configs/bigsur_defconfig6
-rw-r--r--arch/ia64/configs/sn2_defconfig8
-rw-r--r--arch/ia64/configs/tiger_defconfig8
-rw-r--r--arch/ia64/configs/zx1_defconfig8
-rw-r--r--arch/ia64/defconfig9
-rw-r--r--arch/ia64/hp/sim/boot/boot_head.S31
-rw-r--r--arch/ia64/hp/sim/boot/fw-emu.c11
-rw-r--r--arch/ia64/hp/sim/simserial.c2
-rw-r--r--arch/ia64/ia32/ia32_entry.S4
-rw-r--r--arch/ia64/ia32/ia32_signal.c1
-rw-r--r--arch/ia64/ia32/sys_ia32.c33
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/ia64/kernel/acpi-ext.c37
-rw-r--r--arch/ia64/kernel/acpi.c328
-rw-r--r--arch/ia64/kernel/asm-offsets.c40
-rw-r--r--arch/ia64/kernel/cpufreq/Kconfig29
-rw-r--r--arch/ia64/kernel/cpufreq/Makefile1
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c499
-rw-r--r--arch/ia64/kernel/domain.c396
-rw-r--r--arch/ia64/kernel/entry.S31
-rw-r--r--arch/ia64/kernel/fsys.S2
-rw-r--r--arch/ia64/kernel/gate.S2
-rw-r--r--arch/ia64/kernel/head.S2
-rw-r--r--arch/ia64/kernel/iosapic.c24
-rw-r--r--arch/ia64/kernel/irq.c39
-rw-r--r--arch/ia64/kernel/ivt.S3
-rw-r--r--arch/ia64/kernel/jprobes.S1
-rw-r--r--arch/ia64/kernel/kprobes.c124
-rw-r--r--arch/ia64/kernel/mca.c830
-rw-r--r--arch/ia64/kernel/mca_asm.S1358
-rw-r--r--arch/ia64/kernel/mca_drv.c37
-rw-r--r--arch/ia64/kernel/minstate.h88
-rw-r--r--arch/ia64/kernel/palinfo.c115
-rw-r--r--arch/ia64/kernel/perfmon.c9
-rw-r--r--arch/ia64/kernel/salinfo.c62
-rw-r--r--arch/ia64/kernel/setup.c4
-rw-r--r--arch/ia64/kernel/signal.c15
-rw-r--r--arch/ia64/kernel/sys_ia64.c2
-rw-r--r--arch/ia64/kernel/topology.c2
-rw-r--r--arch/ia64/kernel/traps.c5
-rw-r--r--arch/ia64/kernel/uncached.c4
-rw-r--r--arch/ia64/kernel/unwind.c22
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S1
-rw-r--r--arch/ia64/lib/Makefile2
-rw-r--r--arch/ia64/lib/flush.S1
-rw-r--r--arch/ia64/lib/memcpy_mck.S3
-rw-r--r--arch/ia64/lib/swiotlb.c5
-rw-r--r--arch/ia64/mm/fault.c9
-rw-r--r--arch/ia64/mm/hugetlbpage.c8
-rw-r--r--arch/ia64/mm/init.c15
-rw-r--r--arch/ia64/pci/pci.c3
-rw-r--r--arch/ia64/sn/include/tio.h6
-rw-r--r--arch/ia64/sn/include/xtalk/hubdev.h11
-rw-r--r--arch/ia64/sn/kernel/bte.c83
-rw-r--r--arch/ia64/sn/kernel/huberror.c2
-rw-r--r--arch/ia64/sn/kernel/io_init.c37
-rw-r--r--arch/ia64/sn/kernel/irq.c77
-rw-r--r--arch/ia64/sn/kernel/setup.c39
-rw-r--r--arch/ia64/sn/kernel/sn2/ptc_deadlock.S13
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c256
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c313
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c6
-rw-r--r--arch/ia64/sn/kernel/sn2/timer_interrupt.c22
-rw-r--r--arch/ia64/sn/kernel/tiocx.c2
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c4
-rw-r--r--arch/ia64/sn/kernel/xpnet.c6
-rw-r--r--arch/ia64/sn/pci/Makefile2
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c60
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c40
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c15
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c771
-rw-r--r--arch/m32r/Kconfig4
-rw-r--r--arch/m32r/kernel/asm-offsets.c1
-rw-r--r--arch/m32r/kernel/signal.c11
-rw-r--r--arch/m32r/kernel/smp.c48
-rw-r--r--arch/m32r/kernel/time.c7
-rw-r--r--arch/m68k/Kconfig5
-rw-r--r--arch/m68k/Makefile9
-rw-r--r--arch/m68k/amiga/amisound.c2
-rw-r--r--arch/m68k/bvme6000/rtc.c5
-rw-r--r--arch/m68k/fpsp040/skeleton.S2
-rw-r--r--arch/m68k/ifpsp060/iskeleton.S2
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/kernel/head.S2
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c4
-rw-r--r--arch/m68k/kernel/ptrace.c370
-rw-r--r--arch/m68k/kernel/time.c5
-rw-r--r--arch/m68k/lib/Makefile2
-rw-r--r--arch/m68k/lib/memcmp.c11
-rw-r--r--arch/m68k/lib/memcpy.c75
-rw-r--r--arch/m68k/lib/memset.c68
-rw-r--r--arch/m68k/lib/string.c237
-rw-r--r--arch/m68k/mac/macboing.c3
-rw-r--r--arch/m68k/math-emu/fp_emu.h2
-rw-r--r--arch/m68k/mm/Makefile2
-rw-r--r--arch/m68k/mm/cache.c118
-rw-r--r--arch/m68k/mm/memory.c104
-rw-r--r--arch/m68k/mvme16x/rtc.c4
-rw-r--r--arch/m68knommu/Kconfig66
-rw-r--r--arch/m68knommu/Makefile17
-rw-r--r--arch/m68knommu/defconfig452
-rw-r--r--arch/m68knommu/kernel/setup.c25
-rw-r--r--arch/m68knommu/kernel/signal.c11
-rw-r--r--arch/m68knommu/kernel/time.c7
-rw-r--r--arch/m68knommu/kernel/traps.c20
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S23
-rw-r--r--arch/m68knommu/platform/523x/Makefile19
-rw-r--r--arch/m68knommu/platform/523x/config.c82
-rw-r--r--arch/m68knommu/platform/5272/config.c6
-rw-r--r--arch/m68knommu/platform/5307/Makefile1
-rw-r--r--arch/m68knommu/platform/5307/head.S15
-rw-r--r--arch/m68knommu/platform/68328/config.c94
-rw-r--r--arch/m68knommu/platform/68328/entry.S4
-rw-r--r--arch/m68knommu/platform/68328/head-de2.S135
-rw-r--r--arch/m68knommu/platform/68328/timers.c106
-rw-r--r--arch/m68knommu/platform/68360/entry.S2
-rw-r--r--arch/m68knommu/platform/68360/head-ram.S408
-rw-r--r--arch/m68knommu/platform/68360/head-rom.S420
-rw-r--r--arch/m68knommu/platform/68EZ328/config.c80
-rw-r--r--arch/m68knommu/platform/68VZ328/config.c (renamed from arch/m68knommu/platform/68VZ328/de2/config.c)141
-rw-r--r--arch/m68knommu/platform/68VZ328/ucdimm/config.c117
-rw-r--r--arch/mips/Kconfig263
-rw-r--r--arch/mips/Makefile79
-rw-r--r--arch/mips/au1000/common/pci.c8
-rw-r--r--arch/mips/au1000/common/setup.c2
-rw-r--r--arch/mips/au1000/common/time.c14
-rw-r--r--arch/mips/au1000/csb250/board_setup.c4
-rw-r--r--arch/mips/au1000/csb250/init.c2
-rw-r--r--arch/mips/au1000/db1x00/init.c2
-rw-r--r--arch/mips/au1000/hydrogen3/init.c2
-rw-r--r--arch/mips/au1000/pb1000/board_setup.c2
-rw-r--r--arch/mips/au1000/xxs1500/board_setup.c6
-rw-r--r--arch/mips/au1000/xxs1500/init.c2
-rw-r--r--arch/mips/au1000/xxs1500/irqmap.c2
-rw-r--r--arch/mips/configs/atlas_defconfig5
-rw-r--r--arch/mips/configs/capcella_defconfig5
-rw-r--r--arch/mips/configs/cobalt_defconfig5
-rw-r--r--arch/mips/configs/db1000_defconfig5
-rw-r--r--arch/mips/configs/db1100_defconfig5
-rw-r--r--arch/mips/configs/db1500_defconfig4
-rw-r--r--arch/mips/configs/db1550_defconfig4
-rw-r--r--arch/mips/configs/ddb5476_defconfig5
-rw-r--r--arch/mips/configs/ddb5477_defconfig5
-rw-r--r--arch/mips/configs/decstation_defconfig5
-rw-r--r--arch/mips/configs/e55_defconfig5
-rw-r--r--arch/mips/configs/ev64120_defconfig5
-rw-r--r--arch/mips/configs/ev96100_defconfig5
-rw-r--r--arch/mips/configs/ip22_defconfig5
-rw-r--r--arch/mips/configs/ip27_defconfig2
-rw-r--r--arch/mips/configs/ip32_defconfig3
-rw-r--r--arch/mips/configs/it8172_defconfig5
-rw-r--r--arch/mips/configs/ivr_defconfig5
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig5
-rw-r--r--arch/mips/configs/jmr3927_defconfig5
-rw-r--r--arch/mips/configs/lasat200_defconfig5
-rw-r--r--arch/mips/configs/malta_defconfig5
-rw-r--r--arch/mips/configs/mpc30x_defconfig5
-rw-r--r--arch/mips/configs/ocelot_3_defconfig5
-rw-r--r--arch/mips/configs/ocelot_c_defconfig3
-rw-r--r--arch/mips/configs/ocelot_defconfig5
-rw-r--r--arch/mips/configs/ocelot_g_defconfig3
-rw-r--r--arch/mips/configs/pb1100_defconfig5
-rw-r--r--arch/mips/configs/pb1500_defconfig4
-rw-r--r--arch/mips/configs/pb1550_defconfig4
-rw-r--r--arch/mips/configs/qemu_defconfig (renamed from arch/mips/configs/osprey_defconfig)405
-rw-r--r--arch/mips/configs/rm200_defconfig5
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig4
-rw-r--r--arch/mips/configs/sead_defconfig5
-rw-r--r--arch/mips/configs/tb0226_defconfig5
-rw-r--r--arch/mips/configs/tb0229_defconfig5
-rw-r--r--arch/mips/configs/tb0287_defconfig1041
-rw-r--r--arch/mips/configs/workpad_defconfig5
-rw-r--r--arch/mips/configs/yosemite_defconfig4
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq.c6
-rw-r--r--arch/mips/ddb5xxx/ddb5477/setup.c22
-rw-r--r--arch/mips/dec/ecc-berr.c2
-rw-r--r--arch/mips/dec/int-handler.S6
-rw-r--r--arch/mips/dec/prom/Makefile4
-rw-r--r--arch/mips/defconfig5
-rw-r--r--arch/mips/ite-boards/generic/it8172_setup.c2
-rw-r--r--arch/mips/ite-boards/generic/time.c16
-rw-r--r--arch/mips/kernel/Makefile10
-rw-r--r--arch/mips/kernel/asm-offsets.c (renamed from arch/mips/kernel/offset.c)0
-rw-r--r--arch/mips/kernel/binfmt_elfn32.c2
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c2
-rw-r--r--arch/mips/kernel/cpu-bugs64.c4
-rw-r--r--arch/mips/kernel/cpu-probe.c6
-rw-r--r--arch/mips/kernel/gdb-low.S4
-rw-r--r--arch/mips/kernel/gdb-stub.c12
-rw-r--r--arch/mips/kernel/genex.S14
-rw-r--r--arch/mips/kernel/genrtc.c2
-rw-r--r--arch/mips/kernel/head.S6
-rw-r--r--arch/mips/kernel/i8259.c2
-rw-r--r--arch/mips/kernel/ioctl32.c2
-rw-r--r--arch/mips/kernel/irixioctl.c5
-rw-r--r--arch/mips/kernel/irixsig.c28
-rw-r--r--arch/mips/kernel/irq.c2
-rw-r--r--arch/mips/kernel/linux32.c38
-rw-r--r--arch/mips/kernel/mips_ksyms.c2
-rw-r--r--arch/mips/kernel/process.c8
-rw-r--r--arch/mips/kernel/ptrace.c12
-rw-r--r--arch/mips/kernel/r2300_fpu.S2
-rw-r--r--arch/mips/kernel/r2300_switch.S6
-rw-r--r--arch/mips/kernel/r4k_fpu.S6
-rw-r--r--arch/mips/kernel/r4k_switch.S10
-rw-r--r--arch/mips/kernel/r6000_fpu.S2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/kernel/signal.c11
-rw-r--r--arch/mips/kernel/signal32.c13
-rw-r--r--arch/mips/kernel/syscall.c2
-rw-r--r--arch/mips/kernel/sysirix.c8
-rw-r--r--arch/mips/kernel/time.c7
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/kernel/unaligned.c12
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/lasat/at93c.c16
-rw-r--r--arch/mips/lasat/at93c.h4
-rw-r--r--arch/mips/lasat/ds1603.c12
-rw-r--r--arch/mips/lasat/ds1603.h6
-rw-r--r--arch/mips/lasat/image/Makefile2
-rw-r--r--arch/mips/lasat/image/head.S2
-rw-r--r--arch/mips/lasat/interrupt.c4
-rw-r--r--arch/mips/lasat/lasat_board.c8
-rw-r--r--arch/mips/lasat/picvue.c12
-rw-r--r--arch/mips/lasat/picvue.h4
-rw-r--r--arch/mips/lasat/picvue_proc.c10
-rw-r--r--arch/mips/lasat/prom.c2
-rw-r--r--arch/mips/lasat/reset.c2
-rw-r--r--arch/mips/lasat/setup.c4
-rw-r--r--arch/mips/lasat/sysctl.c26
-rw-r--r--arch/mips/lib-32/Makefile2
-rw-r--r--arch/mips/lib-32/memset.S2
-rw-r--r--arch/mips/lib-64/Makefile2
-rw-r--r--arch/mips/lib-64/memset.S2
-rw-r--r--arch/mips/lib/dec_and_lock.c8
-rw-r--r--arch/mips/lib/memcpy.S8
-rw-r--r--arch/mips/lib/strlen_user.S2
-rw-r--r--arch/mips/lib/strncpy_user.S2
-rw-r--r--arch/mips/lib/strnlen_user.S2
-rw-r--r--arch/mips/math-emu/cp1emu.c12
-rw-r--r--arch/mips/math-emu/kernel_linkage.c2
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c2
-rw-r--r--arch/mips/mips-boards/generic/init.c6
-rw-r--r--arch/mips/mips-boards/generic/time.c2
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c6
-rw-r--r--arch/mips/mm/Makefile4
-rw-r--r--arch/mips/mm/c-r4k.c20
-rw-r--r--arch/mips/mm/c-sb1.c2
-rw-r--r--arch/mips/mm/cerr-sb1.c24
-rw-r--r--arch/mips/mm/dma-noncoherent.c10
-rw-r--r--arch/mips/mm/init.c8
-rw-r--r--arch/mips/mm/pg-sb1.c10
-rw-r--r--arch/mips/mm/tlbex.c30
-rw-r--r--arch/mips/momentum/jaguar_atx/int-handler.S12
-rw-r--r--arch/mips/momentum/jaguar_atx/prom.c12
-rw-r--r--arch/mips/momentum/jaguar_atx/reset.c2
-rw-r--r--arch/mips/momentum/jaguar_atx/setup.c4
-rw-r--r--arch/mips/momentum/ocelot_3/prom.c12
-rw-r--r--arch/mips/momentum/ocelot_c/int-handler.S8
-rw-r--r--arch/mips/momentum/ocelot_c/ocelot_c_fpga.h2
-rw-r--r--arch/mips/momentum/ocelot_c/prom.c14
-rw-r--r--arch/mips/momentum/ocelot_c/reset.c2
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c8
-rw-r--r--arch/mips/pci/Makefile1
-rw-r--r--arch/mips/pci/fixup-ddb5074.c2
-rw-r--r--arch/mips/pci/fixup-ddb5477.c2
-rw-r--r--arch/mips/pci/fixup-malta.c2
-rw-r--r--arch/mips/pci/fixup-rbtx4927.c2
-rw-r--r--arch/mips/pci/fixup-sni.c2
-rw-r--r--arch/mips/pci/fixup-tb0219.c15
-rw-r--r--arch/mips/pci/fixup-tb0287.c65
-rw-r--r--arch/mips/pci/ops-ddb5477.c4
-rw-r--r--arch/mips/pci/ops-tx4927.c6
-rw-r--r--arch/mips/pci/pci-ddb5477.c8
-rw-r--r--arch/mips/pci/pci-ip32.c2
-rw-r--r--arch/mips/pci/pci.c21
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c14
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h4
-rw-r--r--arch/mips/qemu/Makefile5
-rw-r--r--arch/mips/qemu/q-firmware.c7
-rw-r--r--arch/mips/qemu/q-int.S17
-rw-r--r--arch/mips/qemu/q-irq.c37
-rw-r--r--arch/mips/qemu/q-mem.c6
-rw-r--r--arch/mips/qemu/q-setup.c20
-rw-r--r--arch/mips/sgi-ip22/ip22-eisa.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-hpc.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c12
-rw-r--r--arch/mips/sgi-ip22/ip22-nvram.c8
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c2
-rw-r--r--arch/mips/sgi-ip32/ip32-reset.c2
-rw-r--r--arch/mips/sibyte/cfe/cfe_error.h10
-rw-r--r--arch/mips/sibyte/cfe/console.c2
-rw-r--r--arch/mips/sibyte/cfe/setup.c4
-rw-r--r--arch/mips/sibyte/cfe/smp.c2
-rw-r--r--arch/mips/sibyte/sb1250/bus_watcher.c6
-rw-r--r--arch/mips/sibyte/sb1250/irq.c4
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c10
-rw-r--r--arch/mips/sibyte/swarm/setup.c4
-rw-r--r--arch/mips/sni/irq.c2
-rw-r--r--arch/mips/sni/setup.c2
-rw-r--r--arch/mips/tx4927/common/tx4927_irq_handler.S6
-rw-r--r--arch/mips/tx4927/common/tx4927_setup.c2
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/Makefile6
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c42
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c2
-rw-r--r--arch/mips/vr4181/common/Makefile7
-rw-r--r--arch/mips/vr4181/common/int_handler.S206
-rw-r--r--arch/mips/vr4181/common/irq.c239
-rw-r--r--arch/mips/vr4181/common/serial.c51
-rw-r--r--arch/mips/vr4181/common/time.c145
-rw-r--r--arch/mips/vr4181/osprey/Makefile7
-rw-r--r--arch/mips/vr4181/osprey/dbg_io.c136
-rw-r--r--arch/mips/vr4181/osprey/prom.c49
-rw-r--r--arch/mips/vr4181/osprey/reset.c40
-rw-r--r--arch/mips/vr4181/osprey/setup.c68
-rw-r--r--arch/mips/vr41xx/casio-e55/setup.c5
-rw-r--r--arch/mips/vr41xx/common/Makefile2
-rw-r--r--arch/mips/vr41xx/common/icu.c270
-rw-r--r--arch/mips/vr41xx/common/int-handler.S10
-rw-r--r--arch/mips/vr41xx/common/irq.c94
-rw-r--r--arch/mips/vr41xx/common/type.c (renamed from arch/mips/vr41xx/tanbac-tb0226/setup.c)6
-rw-r--r--arch/mips/vr41xx/common/vrc4173.c2
-rw-r--r--arch/mips/vr41xx/ibm-workpad/setup.c5
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/init.c12
-rw-r--r--arch/mips/vr41xx/tanbac-tb0226/Makefile5
-rw-r--r--arch/mips/vr41xx/tanbac-tb0229/Makefile5
-rw-r--r--arch/mips/vr41xx/victor-mpc30x/Makefile5
-rw-r--r--arch/mips/vr41xx/victor-mpc30x/setup.c24
-rw-r--r--arch/mips/vr41xx/zao-capcella/Makefile5
-rw-r--r--arch/mips/vr41xx/zao-capcella/setup.c24
-rw-r--r--arch/parisc/Kconfig4
-rw-r--r--arch/parisc/Makefile10
-rw-r--r--arch/parisc/hpux/gate.S2
-rw-r--r--arch/parisc/hpux/wrappers.S2
-rw-r--r--arch/parisc/kernel/entry.S2
-rw-r--r--arch/parisc/kernel/head.S2
-rw-r--r--arch/parisc/kernel/process.c2
-rw-r--r--arch/parisc/kernel/ptrace.c2
-rw-r--r--arch/parisc/kernel/signal.c13
-rw-r--r--arch/parisc/kernel/syscall.S2
-rw-r--r--arch/parisc/kernel/time.c5
-rw-r--r--arch/parisc/lib/Makefile2
-rw-r--r--arch/parisc/lib/bitops.c4
-rw-r--r--arch/parisc/lib/debuglocks.c277
-rw-r--r--arch/parisc/lib/fixup.S2
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c2
-rw-r--r--arch/ppc/Kconfig86
-rw-r--r--arch/ppc/Kconfig.debug3
-rw-r--r--arch/ppc/Makefile23
-rw-r--r--arch/ppc/boot/common/ns16550.c8
-rw-r--r--arch/ppc/boot/common/util.S2
-rw-r--r--arch/ppc/boot/simple/Makefile19
-rw-r--r--arch/ppc/boot/simple/embed_config.c55
-rw-r--r--arch/ppc/boot/simple/head.S9
-rw-r--r--arch/ppc/boot/simple/misc-cpci690.c42
-rw-r--r--arch/ppc/boot/simple/misc-ev64360.c44
-rw-r--r--arch/ppc/boot/simple/misc-katana.c8
-rw-r--r--arch/ppc/boot/simple/misc-mv64x60.c27
-rw-r--r--arch/ppc/boot/simple/mv64x60_tty.c7
-rw-r--r--arch/ppc/boot/utils/addRamDisk.c203
-rw-r--r--arch/ppc/configs/SM850_defconfig522
-rw-r--r--arch/ppc/configs/SPD823TS_defconfig520
-rw-r--r--arch/ppc/configs/adir_defconfig805
-rw-r--r--arch/ppc/configs/ash_defconfig666
-rw-r--r--arch/ppc/configs/beech_defconfig615
-rw-r--r--arch/ppc/configs/cedar_defconfig534
-rw-r--r--arch/ppc/configs/cpci690_defconfig316
-rw-r--r--arch/ppc/configs/ev64360_defconfig (renamed from arch/ppc/configs/k2_defconfig)616
-rw-r--r--arch/ppc/configs/katana_defconfig336
-rw-r--r--arch/ppc/configs/mcpn765_defconfig579
-rw-r--r--arch/ppc/configs/menf1_defconfig621
-rw-r--r--arch/ppc/configs/mpc8560_ads_defconfig273
-rw-r--r--arch/ppc/configs/oak_defconfig485
-rw-r--r--arch/ppc/configs/pcore_defconfig716
-rw-r--r--arch/ppc/configs/rainier_defconfig599
-rw-r--r--arch/ppc/configs/redwood_defconfig540
-rw-r--r--arch/ppc/kernel/Makefile3
-rw-r--r--arch/ppc/kernel/cpu_setup_6xx.S12
-rw-r--r--arch/ppc/kernel/cpu_setup_power4.S3
-rw-r--r--arch/ppc/kernel/cputable.c76
-rw-r--r--arch/ppc/kernel/dma-mapping.c2
-rw-r--r--arch/ppc/kernel/entry.S2
-rw-r--r--arch/ppc/kernel/find_name.c48
-rw-r--r--arch/ppc/kernel/fpu.S2
-rw-r--r--arch/ppc/kernel/head.S30
-rw-r--r--arch/ppc/kernel/head_44x.S6
-rw-r--r--arch/ppc/kernel/head_4xx.S7
-rw-r--r--arch/ppc/kernel/head_8xx.S2
-rw-r--r--arch/ppc/kernel/head_fsl_booke.S7
-rw-r--r--arch/ppc/kernel/idle.c6
-rw-r--r--arch/ppc/kernel/idle_6xx.S2
-rw-r--r--arch/ppc/kernel/idle_power4.S2
-rw-r--r--arch/ppc/kernel/l2cr.S31
-rw-r--r--arch/ppc/kernel/misc.S2
-rw-r--r--arch/ppc/kernel/pci.c1
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c4
-rw-r--r--arch/ppc/kernel/setup.c28
-rw-r--r--arch/ppc/kernel/signal.c11
-rw-r--r--arch/ppc/kernel/smp.c44
-rw-r--r--arch/ppc/kernel/swsusp.S2
-rw-r--r--arch/ppc/kernel/syscalls.c4
-rw-r--r--arch/ppc/kernel/temp.c1
-rw-r--r--arch/ppc/kernel/time.c8
-rw-r--r--arch/ppc/kernel/traps.c43
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S4
-rw-r--r--arch/ppc/lib/Makefile1
-rw-r--r--arch/ppc/lib/dec_and_lock.c8
-rw-r--r--arch/ppc/mm/fault.c6
-rw-r--r--arch/ppc/mm/hashtable.S2
-rw-r--r--arch/ppc/mm/init.c7
-rw-r--r--arch/ppc/platforms/4xx/Kconfig15
-rw-r--r--arch/ppc/platforms/4xx/Makefile2
-rw-r--r--arch/ppc/platforms/4xx/ash.c250
-rw-r--r--arch/ppc/platforms/4xx/ash.h83
-rw-r--r--arch/ppc/platforms/4xx/bamboo.c59
-rw-r--r--arch/ppc/platforms/4xx/bamboo.h2
-rw-r--r--arch/ppc/platforms/4xx/ebony.c20
-rw-r--r--arch/ppc/platforms/4xx/ibm405ep.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm405gp.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm405gpr.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm440ep.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm440gp.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm440gx.c1
-rw-r--r--arch/ppc/platforms/4xx/ibm440sp.c1
-rw-r--r--arch/ppc/platforms/4xx/ibmnp405h.c7
-rw-r--r--arch/ppc/platforms/4xx/ibmstb4.c52
-rw-r--r--arch/ppc/platforms/4xx/ibmstb4.h4
-rw-r--r--arch/ppc/platforms/4xx/luan.c7
-rw-r--r--arch/ppc/platforms/4xx/luan.h2
-rw-r--r--arch/ppc/platforms/4xx/oak.c255
-rw-r--r--arch/ppc/platforms/4xx/oak.h96
-rw-r--r--arch/ppc/platforms/4xx/oak_setup.h50
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c7
-rw-r--r--arch/ppc/platforms/4xx/redwood5.c13
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c35
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.h40
-rw-r--r--arch/ppc/platforms/Makefile6
-rw-r--r--arch/ppc/platforms/adir.h95
-rw-r--r--arch/ppc/platforms/adir_pci.c247
-rw-r--r--arch/ppc/platforms/adir_pic.c130
-rw-r--r--arch/ppc/platforms/adir_setup.c210
-rw-r--r--arch/ppc/platforms/chrp_time.c1
-rw-r--r--arch/ppc/platforms/cpci690.c177
-rw-r--r--arch/ppc/platforms/cpci690.h2
-rw-r--r--arch/ppc/platforms/ev64360.c510
-rw-r--r--arch/ppc/platforms/ev64360.h116
-rw-r--r--arch/ppc/platforms/hdpu.c2
-rw-r--r--arch/ppc/platforms/k2.c613
-rw-r--r--arch/ppc/platforms/k2.h82
-rw-r--r--arch/ppc/platforms/katana.c253
-rw-r--r--arch/ppc/platforms/katana.h16
-rw-r--r--arch/ppc/platforms/mcpn765.c527
-rw-r--r--arch/ppc/platforms/mcpn765.h122
-rw-r--r--arch/ppc/platforms/pcore.c352
-rw-r--r--arch/ppc/platforms/pcore.h39
-rw-r--r--arch/ppc/platforms/pmac_pic.c2
-rw-r--r--arch/ppc/platforms/pmac_sleep.S4
-rw-r--r--arch/ppc/platforms/pmac_smp.c85
-rw-r--r--arch/ppc/platforms/spd8xx.h92
-rw-r--r--arch/ppc/platforms/tqm8xx.h23
-rw-r--r--arch/ppc/syslib/Makefile12
-rw-r--r--arch/ppc/syslib/cpc700_pic.c12
-rw-r--r--arch/ppc/syslib/i8259.c13
-rw-r--r--arch/ppc/syslib/ibm440gx_common.c7
-rw-r--r--arch/ppc/syslib/m8xx_setup.c6
-rw-r--r--arch/ppc/syslib/mpc10x_common.c4
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c2
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c2
-rw-r--r--arch/ppc/syslib/mv64360_pic.c31
-rw-r--r--arch/ppc/syslib/mv64x60.c248
-rw-r--r--arch/ppc/syslib/ocp.c2
-rw-r--r--arch/ppc/syslib/of_device.c2
-rw-r--r--arch/ppc/syslib/open_pic.c2
-rw-r--r--arch/ppc/syslib/open_pic2.c12
-rw-r--r--arch/ppc/syslib/ppc403_pic.c11
-rw-r--r--arch/ppc/syslib/ppc4xx_setup.c27
-rw-r--r--arch/ppc/syslib/ppc83xx_pci.h151
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.c250
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.h19
-rw-r--r--arch/ppc/syslib/ppc_sys.c52
-rw-r--r--arch/ppc/syslib/pq2_devices.c389
-rw-r--r--arch/ppc/syslib/pq2_sys.c200
-rw-r--r--arch/ppc/syslib/prep_nvram.c1
-rw-r--r--arch/ppc/syslib/qspan_pci.c2
-rw-r--r--arch/ppc/syslib/xilinx_pic.c13
-rw-r--r--arch/ppc64/Kconfig78
-rw-r--r--arch/ppc64/Kconfig.debug9
-rw-r--r--arch/ppc64/Makefile40
-rw-r--r--arch/ppc64/boot/Makefile57
-rw-r--r--arch/ppc64/boot/addnote.c4
-rw-r--r--arch/ppc64/boot/crt0.S2
-rw-r--r--arch/ppc64/boot/div64.S2
-rw-r--r--arch/ppc64/boot/elf.h149
-rw-r--r--arch/ppc64/boot/main.c86
-rw-r--r--arch/ppc64/boot/page.h34
-rw-r--r--arch/ppc64/boot/ppc32-types.h36
-rw-r--r--arch/ppc64/boot/ppc_asm.h62
-rw-r--r--arch/ppc64/boot/prom.c196
-rw-r--r--arch/ppc64/boot/prom.h18
-rw-r--r--arch/ppc64/boot/stdio.h16
-rw-r--r--arch/ppc64/boot/string.S2
-rw-r--r--arch/ppc64/boot/string.h16
-rw-r--r--arch/ppc64/boot/zlib.c2
-rw-r--r--arch/ppc64/configs/g5_defconfig6
-rw-r--r--arch/ppc64/configs/iSeries_defconfig7
-rw-r--r--arch/ppc64/configs/maple_defconfig6
-rw-r--r--arch/ppc64/configs/pSeries_defconfig6
-rw-r--r--arch/ppc64/defconfig6
-rw-r--r--arch/ppc64/kernel/LparData.c37
-rw-r--r--arch/ppc64/kernel/Makefile15
-rw-r--r--arch/ppc64/kernel/asm-offsets.c3
-rw-r--r--arch/ppc64/kernel/bpa_iic.c28
-rw-r--r--arch/ppc64/kernel/btext.c1
-rw-r--r--arch/ppc64/kernel/cpu_setup_power4.S3
-rw-r--r--arch/ppc64/kernel/cputable.c130
-rw-r--r--arch/ppc64/kernel/eeh.c86
-rw-r--r--arch/ppc64/kernel/entry.S13
-rw-r--r--arch/ppc64/kernel/firmware.c47
-rw-r--r--arch/ppc64/kernel/head.S534
-rw-r--r--arch/ppc64/kernel/iSeries_VpdInfo.c5
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c5
-rw-r--r--arch/ppc64/kernel/iSeries_pci.c2
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c30
-rw-r--r--arch/ppc64/kernel/iSeries_vio.c155
-rw-r--r--arch/ppc64/kernel/idle_power4.S2
-rw-r--r--arch/ppc64/kernel/iomap.c32
-rw-r--r--arch/ppc64/kernel/iommu.c3
-rw-r--r--arch/ppc64/kernel/kprobes.c40
-rw-r--r--arch/ppc64/kernel/lmb.c151
-rw-r--r--arch/ppc64/kernel/lparcfg.c9
-rw-r--r--arch/ppc64/kernel/maple_pci.c60
-rw-r--r--arch/ppc64/kernel/maple_setup.c3
-rw-r--r--arch/ppc64/kernel/misc.S112
-rw-r--r--arch/ppc64/kernel/of_device.c2
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c75
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c26
-rw-r--r--arch/ppc64/kernel/pSeries_reconfig.c2
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c56
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c16
-rw-r--r--arch/ppc64/kernel/pSeries_vio.c273
-rw-r--r--arch/ppc64/kernel/pacaData.c5
-rw-r--r--arch/ppc64/kernel/pci.c480
-rw-r--r--arch/ppc64/kernel/pci.h1
-rw-r--r--arch/ppc64/kernel/pci_dn.c47
-rw-r--r--arch/ppc64/kernel/pci_iommu.c2
-rw-r--r--arch/ppc64/kernel/pmac_feature.c8
-rw-r--r--arch/ppc64/kernel/pmac_pci.c66
-rw-r--r--arch/ppc64/kernel/pmac_setup.c34
-rw-r--r--arch/ppc64/kernel/pmc.c23
-rw-r--r--arch/ppc64/kernel/process.c46
-rw-r--r--arch/ppc64/kernel/prom.c186
-rw-r--r--arch/ppc64/kernel/prom_init.c94
-rw-r--r--arch/ppc64/kernel/ptrace.c28
-rw-r--r--arch/ppc64/kernel/ptrace32.c34
-rw-r--r--arch/ppc64/kernel/ras.c2
-rw-r--r--arch/ppc64/kernel/rtas_pci.c54
-rw-r--r--arch/ppc64/kernel/rtasd.c10
-rw-r--r--arch/ppc64/kernel/rtc.c7
-rw-r--r--arch/ppc64/kernel/scanlog.c17
-rw-r--r--arch/ppc64/kernel/setup.c90
-rw-r--r--arch/ppc64/kernel/signal.c14
-rw-r--r--arch/ppc64/kernel/signal32.c13
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c86
-rw-r--r--arch/ppc64/kernel/syscalls.c4
-rw-r--r--arch/ppc64/kernel/sysfs.c105
-rw-r--r--arch/ppc64/kernel/time.c15
-rw-r--r--arch/ppc64/kernel/traps.c5
-rw-r--r--arch/ppc64/kernel/u3_iommu.c4
-rw-r--r--arch/ppc64/kernel/udbg.c306
-rw-r--r--arch/ppc64/kernel/udbg_16550.c123
-rw-r--r--arch/ppc64/kernel/udbg_scc.c136
-rw-r--r--arch/ppc64/kernel/vdso32/cacheflush.S2
-rw-r--r--arch/ppc64/kernel/vdso32/datapage.S2
-rw-r--r--arch/ppc64/kernel/vdso32/gettimeofday.S2
-rw-r--r--arch/ppc64/kernel/vdso64/cacheflush.S2
-rw-r--r--arch/ppc64/kernel/vdso64/datapage.S2
-rw-r--r--arch/ppc64/kernel/vdso64/gettimeofday.S2
-rw-r--r--arch/ppc64/kernel/vio.c444
-rw-r--r--arch/ppc64/kernel/vmlinux.lds.S1
-rw-r--r--arch/ppc64/kernel/xics.c44
-rw-r--r--arch/ppc64/lib/dec_and_lock.c8
-rw-r--r--arch/ppc64/lib/locks.c14
-rw-r--r--arch/ppc64/mm/fault.c36
-rw-r--r--arch/ppc64/mm/hash_low.S6
-rw-r--r--arch/ppc64/mm/hash_native.c3
-rw-r--r--arch/ppc64/mm/hash_utils.c4
-rw-r--r--arch/ppc64/mm/hugetlbpage.c392
-rw-r--r--arch/ppc64/mm/imalloc.c2
-rw-r--r--arch/ppc64/mm/init.c112
-rw-r--r--arch/ppc64/mm/numa.c45
-rw-r--r--arch/ppc64/mm/slb.c4
-rw-r--r--arch/ppc64/mm/slb_low.S37
-rw-r--r--arch/ppc64/mm/tlb.c95
-rw-r--r--arch/ppc64/oprofile/common.c57
-rw-r--r--arch/ppc64/oprofile/op_model_power4.c12
-rw-r--r--arch/ppc64/oprofile/op_model_rs64.c3
-rw-r--r--arch/ppc64/xmon/privinst.h1
-rw-r--r--arch/ppc64/xmon/start.c6
-rw-r--r--arch/ppc64/xmon/xmon.c46
-rw-r--r--arch/s390/Makefile12
-rw-r--r--arch/s390/kernel/compat_linux.c2
-rw-r--r--arch/s390/kernel/compat_signal.c11
-rw-r--r--arch/s390/kernel/debug.c52
-rw-r--r--arch/s390/kernel/entry.S118
-rw-r--r--arch/s390/kernel/entry64.S119
-rw-r--r--arch/s390/kernel/head.S2
-rw-r--r--arch/s390/kernel/head64.S2
-rw-r--r--arch/s390/kernel/signal.c11
-rw-r--r--arch/s390/kernel/time.c5
-rw-r--r--arch/s390/lib/spinlock.c12
-rw-r--r--arch/s390/lib/uaccess.S2
-rw-r--r--arch/s390/lib/uaccess64.S2
-rw-r--r--arch/s390/mm/fault.c5
-rw-r--r--arch/sh/Kconfig4
-rw-r--r--arch/sh/Makefile13
-rw-r--r--arch/sh/boards/adx/irq_maskreg.c14
-rw-r--r--arch/sh/boards/bigsur/io.c8
-rw-r--r--arch/sh/boards/bigsur/irq.c28
-rw-r--r--arch/sh/boards/cqreek/irq.c14
-rw-r--r--arch/sh/boards/harp/irq.c14
-rw-r--r--arch/sh/boards/overdrive/irq.c14
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/irq.c14
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/irq.c14
-rw-r--r--arch/sh/boards/renesas/systemh/irq.c14
-rw-r--r--arch/sh/boards/superh/microdev/irq.c14
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/io.c8
-rw-r--r--arch/sh/cchips/voyagergx/irq.c14
-rw-r--r--arch/sh/kernel/cpu/irq_imask.c14
-rw-r--r--arch/sh/kernel/cpu/irq_ipr.c28
-rw-r--r--arch/sh/kernel/cpu/sh4/irq_intc2.c14
-rw-r--r--arch/sh/kernel/signal.c11
-rw-r--r--arch/sh/kernel/time.c11
-rw-r--r--arch/sh64/Kconfig4
-rw-r--r--arch/sh64/Makefile8
-rw-r--r--arch/sh64/kernel/irq_intc.c14
-rw-r--r--arch/sh64/kernel/signal.c11
-rw-r--r--arch/sh64/kernel/time.c11
-rw-r--r--arch/sparc/Kconfig4
-rw-r--r--arch/sparc/Makefile12
-rw-r--r--arch/sparc/kernel/entry.S2
-rw-r--r--arch/sparc/kernel/module.c9
-rw-r--r--arch/sparc/kernel/pcic.c5
-rw-r--r--arch/sparc/kernel/sclow.S2
-rw-r--r--arch/sparc/kernel/setup.c1
-rw-r--r--arch/sparc/kernel/signal.c11
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c42
-rw-r--r--arch/sparc/kernel/tick14.c1
-rw-r--r--arch/sparc/kernel/time.c8
-rw-r--r--arch/sparc/lib/Makefile2
-rw-r--r--arch/sparc/lib/atomic32.c2
-rw-r--r--arch/sparc/lib/debuglocks.c202
-rw-r--r--arch/sparc/lib/mul.S2
-rw-r--r--arch/sparc/lib/rem.S2
-rw-r--r--arch/sparc/lib/sdiv.S2
-rw-r--r--arch/sparc/lib/udiv.S2
-rw-r--r--arch/sparc/lib/umul.S2
-rw-r--r--arch/sparc/lib/urem.S2
-rw-r--r--arch/sparc/mm/fault.c1
-rw-r--r--arch/sparc/mm/generic.c57
-rw-r--r--arch/sparc/mm/hypersparc.S2
-rw-r--r--arch/sparc/mm/init.c1
-rw-r--r--arch/sparc/mm/swift.S2
-rw-r--r--arch/sparc/mm/tsunami.S2
-rw-r--r--arch/sparc/mm/viking.S2
-rw-r--r--arch/sparc64/Kconfig330
-rw-r--r--arch/sparc64/kernel/asm-offsets.c1
-rw-r--r--arch/sparc64/kernel/entry.S602
-rw-r--r--arch/sparc64/kernel/head.S3
-rw-r--r--arch/sparc64/kernel/kprobes.c36
-rw-r--r--arch/sparc64/kernel/pci.c130
-rw-r--r--arch/sparc64/kernel/pci_iommu.c2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c34
-rw-r--r--arch/sparc64/kernel/pci_sabre.c36
-rw-r--r--arch/sparc64/kernel/pci_schizo.c48
-rw-r--r--arch/sparc64/kernel/process.c7
-rw-r--r--arch/sparc64/kernel/rtrap.S13
-rw-r--r--arch/sparc64/kernel/sbus.c2
-rw-r--r--arch/sparc64/kernel/setup.c13
-rw-r--r--arch/sparc64/kernel/signal.c11
-rw-r--r--arch/sparc64/kernel/signal32.c33
-rw-r--r--arch/sparc64/kernel/smp.c30
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c31
-rw-r--r--arch/sparc64/kernel/sunos_ioctl32.c9
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c24
-rw-r--r--arch/sparc64/kernel/time.c2
-rw-r--r--arch/sparc64/kernel/traps.c269
-rw-r--r--arch/sparc64/kernel/ttable.S27
-rw-r--r--arch/sparc64/kernel/unaligned.c18
-rw-r--r--arch/sparc64/kernel/vmlinux.lds.S1
-rw-r--r--arch/sparc64/kernel/winfixup.S6
-rw-r--r--arch/sparc64/lib/Makefile1
-rw-r--r--arch/sparc64/lib/PeeCeeI.c77
-rw-r--r--arch/sparc64/lib/copy_page.S13
-rw-r--r--arch/sparc64/lib/debuglocks.c378
-rw-r--r--arch/sparc64/mm/fault.c8
-rw-r--r--arch/sparc64/mm/generic.c31
-rw-r--r--arch/sparc64/mm/init.c3
-rw-r--r--arch/sparc64/mm/ultra.S41
-rw-r--r--arch/sparc64/solaris/ioctl.c15
-rw-r--r--arch/sparc64/solaris/misc.c6
-rw-r--r--arch/sparc64/solaris/timod.c29
-rw-r--r--arch/um/Kconfig10
-rw-r--r--arch/um/Kconfig.char (renamed from arch/um/Kconfig_char)0
-rw-r--r--arch/um/Kconfig.debug11
-rw-r--r--arch/um/Kconfig.i386 (renamed from arch/um/Kconfig_i386)4
-rw-r--r--arch/um/Kconfig.net (renamed from arch/um/Kconfig_net)12
-rw-r--r--arch/um/Kconfig.scsi (renamed from arch/um/Kconfig_scsi)0
-rw-r--r--arch/um/Kconfig.x86_64 (renamed from arch/um/Kconfig_x86_64)8
-rw-r--r--arch/um/Makefile30
-rw-r--r--arch/um/Makefile-i3862
-rw-r--r--arch/um/Makefile-x86_643
-rw-r--r--arch/um/drivers/Makefile2
-rw-r--r--arch/um/drivers/chan_user.c11
-rw-r--r--arch/um/drivers/mmapper_kern.c41
-rw-r--r--arch/um/drivers/ubd_kern.c570
-rw-r--r--arch/um/include/aio.h40
-rw-r--r--arch/um/include/common-offsets.h1
-rw-r--r--arch/um/include/init.h10
-rw-r--r--arch/um/include/irq_kern.h3
-rw-r--r--arch/um/include/mem.h12
-rw-r--r--arch/um/include/os.h15
-rw-r--r--arch/um/include/syscall.h12
-rw-r--r--arch/um/include/syscall_user.h23
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h2
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h2
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h2
-rw-r--r--arch/um/include/tlb.h22
-rw-r--r--arch/um/include/um_uaccess.h7
-rw-r--r--arch/um/include/user_util.h8
-rw-r--r--arch/um/kernel/Makefile15
-rw-r--r--arch/um/kernel/asm-offsets.c1
-rw-r--r--arch/um/kernel/dyn.lds.S37
-rw-r--r--arch/um/kernel/irq.c41
-rw-r--r--arch/um/kernel/ksyms.c24
-rw-r--r--arch/um/kernel/main.c2
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c35
-rw-r--r--arch/um/kernel/signal_kern.c6
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h4
-rw-r--r--arch/um/kernel/skas/include/skas.h30
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h14
-rw-r--r--arch/um/kernel/skas/mem_user.c224
-rw-r--r--arch/um/kernel/skas/mmu.c61
-rw-r--r--arch/um/kernel/skas/process.c69
-rw-r--r--arch/um/kernel/skas/process_kern.c7
-rw-r--r--arch/um/kernel/skas/syscall.c50
-rw-r--r--arch/um/kernel/skas/syscall_kern.c43
-rw-r--r--arch/um/kernel/skas/syscall_user.c44
-rw-r--r--arch/um/kernel/skas/tlb.c28
-rw-r--r--arch/um/kernel/syscall.c36
-rw-r--r--arch/um/kernel/syscall_user.c48
-rw-r--r--arch/um/kernel/tlb.c267
-rw-r--r--arch/um/kernel/trap_kern.c61
-rw-r--r--arch/um/kernel/trap_user.c21
-rw-r--r--arch/um/kernel/tt/include/uaccess-tt.h14
-rw-r--r--arch/um/kernel/tt/syscall_kern.c47
-rw-r--r--arch/um/kernel/tt/syscall_user.c35
-rw-r--r--arch/um/kernel/tt/tlb.c26
-rw-r--r--arch/um/kernel/um_arch.c8
-rw-r--r--arch/um/kernel/uml.lds.S14
-rw-r--r--arch/um/os-Linux/Makefile14
-rw-r--r--arch/um/os-Linux/aio.c414
-rw-r--r--arch/um/os-Linux/elf_aux.c3
-rw-r--r--arch/um/os-Linux/process.c58
-rw-r--r--arch/um/os-Linux/start_up.c (renamed from arch/um/kernel/process.c)224
-rw-r--r--arch/um/os-Linux/tt.c113
-rw-r--r--arch/um/scripts/Makefile.rules5
-rw-r--r--arch/um/scripts/Makefile.unmap2
-rw-r--r--arch/um/sys-i386/Makefile8
-rw-r--r--arch/um/sys-i386/kernel-offsets.c1
-rw-r--r--arch/um/sys-i386/signal.c2
-rw-r--r--arch/um/sys-i386/stub.S47
-rw-r--r--arch/um/sys-i386/stub_segv.c3
-rw-r--r--arch/um/sys-x86_64/Makefile13
-rw-r--r--arch/um/sys-x86_64/kernel-offsets.c1
-rw-r--r--arch/um/sys-x86_64/signal.c41
-rw-r--r--arch/um/sys-x86_64/stub.S51
-rw-r--r--arch/um/sys-x86_64/stub_segv.c3
-rw-r--r--arch/v850/Makefile14
-rw-r--r--arch/v850/configs/rte-ma1-cb_defconfig108
-rw-r--r--arch/v850/configs/rte-me2-cb_defconfig21
-rw-r--r--arch/v850/configs/sim_defconfig21
-rw-r--r--arch/v850/kernel/asm-offsets.c (renamed from arch/v850/kernel/asm-consts.c)0
-rw-r--r--arch/v850/kernel/entry.S2
-rw-r--r--arch/v850/kernel/irq.c14
-rw-r--r--arch/v850/kernel/setup.c58
-rw-r--r--arch/v850/kernel/signal.c11
-rw-r--r--arch/v850/kernel/sim.c14
-rw-r--r--arch/v850/kernel/time.c7
-rw-r--r--arch/x86_64/Kconfig15
-rw-r--r--arch/x86_64/Makefile10
-rw-r--r--arch/x86_64/boot/Makefile2
-rw-r--r--arch/x86_64/boot/compressed/misc.c6
-rw-r--r--arch/x86_64/boot/setup.S2
-rw-r--r--arch/x86_64/boot/tools/build.c4
-rw-r--r--arch/x86_64/defconfig69
-rw-r--r--arch/x86_64/ia32/ia32_ioctl.c17
-rw-r--r--arch/x86_64/ia32/ia32entry.S55
-rw-r--r--arch/x86_64/ia32/sys_ia32.c28
-rw-r--r--arch/x86_64/ia32/vsyscall-syscall.S2
-rw-r--r--arch/x86_64/ia32/vsyscall-sysenter.S2
-rw-r--r--arch/x86_64/kernel/Makefile8
-rw-r--r--arch/x86_64/kernel/acpi/Makefile4
-rw-r--r--arch/x86_64/kernel/acpi/sleep.c18
-rw-r--r--arch/x86_64/kernel/aperture.c2
-rw-r--r--arch/x86_64/kernel/apic.c42
-rw-r--r--arch/x86_64/kernel/asm-offsets.c1
-rw-r--r--arch/x86_64/kernel/crash.c1
-rw-r--r--arch/x86_64/kernel/e820.c20
-rw-r--r--arch/x86_64/kernel/early_printk.c46
-rw-r--r--arch/x86_64/kernel/entry.S236
-rw-r--r--arch/x86_64/kernel/genapic.c24
-rw-r--r--arch/x86_64/kernel/genapic_cluster.c10
-rw-r--r--arch/x86_64/kernel/genapic_flat.c22
-rw-r--r--arch/x86_64/kernel/head.S2
-rw-r--r--arch/x86_64/kernel/i8259.c23
-rw-r--r--arch/x86_64/kernel/init_task.c2
-rw-r--r--arch/x86_64/kernel/io_apic.c154
-rw-r--r--arch/x86_64/kernel/irq.c1
-rw-r--r--arch/x86_64/kernel/kprobes.c41
-rw-r--r--arch/x86_64/kernel/mce.c44
-rw-r--r--arch/x86_64/kernel/mpparse.c19
-rw-r--r--arch/x86_64/kernel/msr.c279
-rw-r--r--arch/x86_64/kernel/nmi.c21
-rw-r--r--arch/x86_64/kernel/pci-gart.c8
-rw-r--r--arch/x86_64/kernel/process.c39
-rw-r--r--arch/x86_64/kernel/setup.c99
-rw-r--r--arch/x86_64/kernel/setup64.c5
-rw-r--r--arch/x86_64/kernel/signal.c5
-rw-r--r--arch/x86_64/kernel/smp.c129
-rw-r--r--arch/x86_64/kernel/smpboot.c76
-rw-r--r--arch/x86_64/kernel/suspend.c17
-rw-r--r--arch/x86_64/kernel/suspend_asm.S2
-rw-r--r--arch/x86_64/kernel/time.c10
-rw-r--r--arch/x86_64/kernel/traps.c71
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S20
-rw-r--r--arch/x86_64/kernel/vsyscall.c8
-rw-r--r--arch/x86_64/lib/copy_user.S2
-rw-r--r--arch/x86_64/lib/getuser.S2
-rw-r--r--arch/x86_64/lib/putuser.S2
-rw-r--r--arch/x86_64/mm/fault.c14
-rw-r--r--arch/x86_64/mm/init.c79
-rw-r--r--arch/x86_64/mm/k8topology.c13
-rw-r--r--arch/x86_64/mm/numa.c11
-rw-r--r--arch/x86_64/mm/srat.c68
-rw-r--r--arch/x86_64/pci/Makefile2
-rw-r--r--arch/x86_64/pci/Makefile-BUS2
-rw-r--r--arch/x86_64/pci/k8-bus.c10
-rw-r--r--arch/x86_64/pci/mmconfig.c7
-rw-r--r--arch/xtensa/Makefile10
-rw-r--r--arch/xtensa/kernel/align.S2
-rw-r--r--arch/xtensa/kernel/entry.S2
-rw-r--r--arch/xtensa/kernel/process.c2
-rw-r--r--arch/xtensa/kernel/signal.c11
-rw-r--r--arch/xtensa/kernel/time.c7
-rw-r--r--arch/xtensa/kernel/vectors.S2
-rw-r--r--crypto/Kconfig5
-rw-r--r--crypto/api.c3
-rw-r--r--crypto/cipher.c16
-rw-r--r--crypto/internal.h3
-rw-r--r--crypto/tcrypt.c11
-rw-r--r--crypto/tcrypt.h138
-rw-r--r--crypto/tea.c81
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/acorn/block/fd1772.c12
-rw-r--r--drivers/acpi/Kconfig84
-rw-r--r--drivers/acpi/Makefile14
-rw-r--r--drivers/acpi/ac.c138
-rw-r--r--drivers/acpi/acpi_memhotplug.c176
-rw-r--r--drivers/acpi/asus_acpi.c690
-rw-r--r--drivers/acpi/battery.c400
-rw-r--r--drivers/acpi/blacklist.c122
-rw-r--r--drivers/acpi/bus.c310
-rw-r--r--drivers/acpi/button.c274
-rw-r--r--drivers/acpi/container.c128
-rw-r--r--drivers/acpi/debug.c115
-rw-r--r--drivers/acpi/dispatcher/dsfield.c346
-rw-r--r--drivers/acpi/dispatcher/dsinit.c141
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c404
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c424
-rw-r--r--drivers/acpi/dispatcher/dsobject.c330
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c723
-rw-r--r--drivers/acpi/dispatcher/dsutils.c421
-rw-r--r--drivers/acpi/dispatcher/dswexec.c519
-rw-r--r--drivers/acpi/dispatcher/dswload.c522
-rw-r--r--drivers/acpi/dispatcher/dswscope.c139
-rw-r--r--drivers/acpi/dispatcher/dswstate.c668
-rw-r--r--drivers/acpi/ec.c1028
-rw-r--r--drivers/acpi/event.c76
-rw-r--r--drivers/acpi/events/evevent.c168
-rw-r--r--drivers/acpi/events/evgpe.c427
-rw-r--r--drivers/acpi/events/evgpeblk.c767
-rw-r--r--drivers/acpi/events/evmisc.c293
-rw-r--r--drivers/acpi/events/evregion.c582
-rw-r--r--drivers/acpi/events/evrgnini.c315
-rw-r--r--drivers/acpi/events/evsci.c77
-rw-r--r--drivers/acpi/events/evxface.c444
-rw-r--r--drivers/acpi/events/evxfevnt.c465
-rw-r--r--drivers/acpi/events/evxfregn.c114
-rw-r--r--drivers/acpi/executer/exconfig.c351
-rw-r--r--drivers/acpi/executer/exconvrt.c311
-rw-r--r--drivers/acpi/executer/excreate.c342
-rw-r--r--drivers/acpi/executer/exdump.c793
-rw-r--r--drivers/acpi/executer/exfield.c253
-rw-r--r--drivers/acpi/executer/exfldio.c644
-rw-r--r--drivers/acpi/executer/exmisc.c358
-rw-r--r--drivers/acpi/executer/exmutex.c160
-rw-r--r--drivers/acpi/executer/exnames.c236
-rw-r--r--drivers/acpi/executer/exoparg1.c574
-rw-r--r--drivers/acpi/executer/exoparg2.c317
-rw-r--r--drivers/acpi/executer/exoparg3.c167
-rw-r--r--drivers/acpi/executer/exoparg6.c127
-rw-r--r--drivers/acpi/executer/exprep.c381
-rw-r--r--drivers/acpi/executer/exregion.c280
-rw-r--r--drivers/acpi/executer/exresnte.c172
-rw-r--r--drivers/acpi/executer/exresolv.c284
-rw-r--r--drivers/acpi/executer/exresop.c398
-rw-r--r--drivers/acpi/executer/exstore.c417
-rw-r--r--drivers/acpi/executer/exstoren.c125
-rw-r--r--drivers/acpi/executer/exstorob.c86
-rw-r--r--drivers/acpi/executer/exsystem.c183
-rw-r--r--drivers/acpi/executer/exutils.c173
-rw-r--r--drivers/acpi/fan.c142
-rw-r--r--drivers/acpi/glue.c9
-rw-r--r--drivers/acpi/hardware/hwacpi.c116
-rw-r--r--drivers/acpi/hardware/hwgpe.c203
-rw-r--r--drivers/acpi/hardware/hwregs.c600
-rw-r--r--drivers/acpi/hardware/hwsleep.c415
-rw-r--r--drivers/acpi/hardware/hwtimer.c77
-rw-r--r--drivers/acpi/hotkey.c233
-rw-r--r--drivers/acpi/ibm_acpi.c1598
-rw-r--r--drivers/acpi/motherboard.c108
-rw-r--r--drivers/acpi/namespace/nsaccess.c355
-rw-r--r--drivers/acpi/namespace/nsalloc.c350
-rw-r--r--drivers/acpi/namespace/nsdump.c461
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c74
-rw-r--r--drivers/acpi/namespace/nseval.c274
-rw-r--r--drivers/acpi/namespace/nsinit.c257
-rw-r--r--drivers/acpi/namespace/nsload.c264
-rw-r--r--drivers/acpi/namespace/nsnames.c118
-rw-r--r--drivers/acpi/namespace/nsobject.c209
-rw-r--r--drivers/acpi/namespace/nsparse.c84
-rw-r--r--drivers/acpi/namespace/nssearch.c205
-rw-r--r--drivers/acpi/namespace/nsutils.c502
-rw-r--r--drivers/acpi/namespace/nswalk.c105
-rw-r--r--drivers/acpi/namespace/nsxfeval.c430
-rw-r--r--drivers/acpi/namespace/nsxfname.c173
-rw-r--r--drivers/acpi/namespace/nsxfobj.c91
-rw-r--r--drivers/acpi/numa.c125
-rw-r--r--drivers/acpi/osl.c695
-rw-r--r--drivers/acpi/parser/Makefile2
-rw-r--r--drivers/acpi/parser/psargs.c376
-rw-r--r--drivers/acpi/parser/psloop.c874
-rw-r--r--drivers/acpi/parser/psopcode.c739
-rw-r--r--drivers/acpi/parser/psparse.c1080
-rw-r--r--drivers/acpi/parser/psscope.c130
-rw-r--r--drivers/acpi/parser/pstree.c92
-rw-r--r--drivers/acpi/parser/psutils.c134
-rw-r--r--drivers/acpi/parser/pswalk.c26
-rw-r--r--drivers/acpi/parser/psxface.c251
-rw-r--r--drivers/acpi/pci_bind.c220
-rw-r--r--drivers/acpi/pci_irq.c275
-rw-r--r--drivers/acpi/pci_link.c482
-rw-r--r--drivers/acpi/pci_root.c130
-rw-r--r--drivers/acpi/power.c271
-rw-r--r--drivers/acpi/processor_core.c437
-rw-r--r--drivers/acpi/processor_idle.c315
-rw-r--r--drivers/acpi/processor_perflib.c297
-rw-r--r--drivers/acpi/processor_thermal.c153
-rw-r--r--drivers/acpi/processor_throttling.c133
-rw-r--r--drivers/acpi/resources/rsaddr.c873
-rw-r--r--drivers/acpi/resources/rscalc.c314
-rw-r--r--drivers/acpi/resources/rscreate.c297
-rw-r--r--drivers/acpi/resources/rsdump.c847
-rw-r--r--drivers/acpi/resources/rsio.c172
-rw-r--r--drivers/acpi/resources/rsirq.c251
-rw-r--r--drivers/acpi/resources/rslist.c279
-rw-r--r--drivers/acpi/resources/rsmemory.c218
-rw-r--r--drivers/acpi/resources/rsmisc.c230
-rw-r--r--drivers/acpi/resources/rsutils.c159
-rw-r--r--drivers/acpi/resources/rsxface.c182
-rw-r--r--drivers/acpi/scan.c437
-rw-r--r--drivers/acpi/sleep/main.c8
-rw-r--r--drivers/acpi/sleep/poweroff.c12
-rw-r--r--drivers/acpi/sleep/proc.c271
-rw-r--r--drivers/acpi/sleep/wakeup.c115
-rw-r--r--drivers/acpi/system.c76
-rw-r--r--drivers/acpi/tables.c434
-rw-r--r--drivers/acpi/tables/tbconvrt.c408
-rw-r--r--drivers/acpi/tables/tbget.c275
-rw-r--r--drivers/acpi/tables/tbgetall.c189
-rw-r--r--drivers/acpi/tables/tbinstal.c264
-rw-r--r--drivers/acpi/tables/tbrsdt.c231
-rw-r--r--drivers/acpi/tables/tbutils.c178
-rw-r--r--drivers/acpi/tables/tbxface.c253
-rw-r--r--drivers/acpi/tables/tbxfroot.c513
-rw-r--r--drivers/acpi/thermal.c801
-rw-r--r--drivers/acpi/toshiba_acpi.c174
-rw-r--r--drivers/acpi/utilities/Makefile2
-rw-r--r--drivers/acpi/utilities/utalloc.c713
-rw-r--r--drivers/acpi/utilities/utcache.c305
-rw-r--r--drivers/acpi/utilities/utcopy.c592
-rw-r--r--drivers/acpi/utilities/utdebug.c400
-rw-r--r--drivers/acpi/utilities/utdelete.c431
-rw-r--r--drivers/acpi/utilities/uteval.c396
-rw-r--r--drivers/acpi/utilities/utglobal.c653
-rw-r--r--drivers/acpi/utilities/utinit.c135
-rw-r--r--drivers/acpi/utilities/utmath.c144
-rw-r--r--drivers/acpi/utilities/utmisc.c1175
-rw-r--r--drivers/acpi/utilities/utmutex.c354
-rw-r--r--drivers/acpi/utilities/utobject.c354
-rw-r--r--drivers/acpi/utilities/utstate.c333
-rw-r--r--drivers/acpi/utilities/utxface.c278
-rw-r--r--drivers/acpi/utils.c195
-rw-r--r--drivers/acpi/video.c1076
-rw-r--r--drivers/atm/ambassador.c2
-rw-r--r--drivers/atm/atmtcp.c2
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/atm/fore200e.c2
-rw-r--r--drivers/atm/he.c2
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/atm/idt77105.c6
-rw-r--r--drivers/atm/idt77252.c8
-rw-r--r--drivers/atm/iphase.c2
-rw-r--r--drivers/atm/lanai.c2
-rw-r--r--drivers/atm/nicstar.c167
-rw-r--r--drivers/atm/nicstar.h16
-rw-r--r--drivers/atm/zatm.c10
-rw-r--r--drivers/base/attribute_container.c91
-rw-r--r--drivers/base/bus.c42
-rw-r--r--drivers/base/class.c49
-rw-r--r--drivers/base/core.c19
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/dmapool.c3
-rw-r--r--drivers/base/driver.c15
-rw-r--r--drivers/base/firmware_class.c88
-rw-r--r--drivers/base/map.c3
-rw-r--r--drivers/base/node.c24
-rw-r--r--drivers/base/platform.c3
-rw-r--r--drivers/base/power/resume.c8
-rw-r--r--drivers/base/power/runtime.c8
-rw-r--r--drivers/base/power/suspend.c12
-rw-r--r--drivers/base/power/sysfs.c8
-rw-r--r--drivers/base/sys.c110
-rw-r--r--drivers/base/transport_class.c19
-rw-r--r--drivers/block/Kconfig46
-rw-r--r--drivers/block/acsi.c2
-rw-r--r--drivers/block/acsi_slm.c2
-rw-r--r--drivers/block/aoe/aoe.h12
-rw-r--r--drivers/block/aoe/aoedev.c2
-rw-r--r--drivers/block/aoe/aoenet.c2
-rw-r--r--drivers/block/ataflop.c14
-rw-r--r--drivers/block/cciss.c646
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c69
-rw-r--r--drivers/block/cryptoloop.c6
-rw-r--r--drivers/block/deadline-iosched.c11
-rw-r--r--drivers/block/floppy.c45
-rw-r--r--drivers/block/genhd.c2
-rw-r--r--drivers/block/ll_rw_blk.c196
-rw-r--r--drivers/block/paride/pcd.c3
-rw-r--r--drivers/block/paride/pf.c3
-rw-r--r--drivers/block/paride/pg.c3
-rw-r--r--drivers/block/paride/pt.c3
-rw-r--r--drivers/block/pktcdvd.c85
-rw-r--r--drivers/block/ps2esdi.c3
-rw-r--r--drivers/block/scsi_ioctl.c61
-rw-r--r--drivers/block/swim3.c9
-rw-r--r--drivers/block/swim_iop.c3
-rw-r--r--drivers/block/ub.c273
-rw-r--r--drivers/block/umem.c11
-rw-r--r--drivers/block/viodasd.c2
-rw-r--r--drivers/block/xd.c21
-rw-r--r--drivers/block/z2ram.c2
-rw-r--r--drivers/bluetooth/bfusb.c16
-rw-r--r--drivers/bluetooth/bluecard_cs.c24
-rw-r--r--drivers/bluetooth/bpa10x.c17
-rw-r--r--drivers/bluetooth/bt3c_cs.c12
-rw-r--r--drivers/bluetooth/btuart_cs.c10
-rw-r--r--drivers/bluetooth/dtl1_cs.c10
-rw-r--r--drivers/bluetooth/hci_bcsp.c18
-rw-r--r--drivers/bluetooth/hci_h4.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c4
-rw-r--r--drivers/bluetooth/hci_usb.c23
-rw-r--r--drivers/bluetooth/hci_vhci.c386
-rw-r--r--drivers/bluetooth/hci_vhci.h50
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/cdrom/cdrom.c15
-rw-r--r--drivers/cdrom/gscd.c2
-rw-r--r--drivers/cdrom/optcd.c2
-rw-r--r--drivers/cdrom/sbpcd.c18
-rw-r--r--drivers/cdrom/sjcd.c2
-rw-r--r--drivers/cdrom/sonycd535.c3
-rw-r--r--drivers/cdrom/viocd.c2
-rw-r--r--drivers/char/Kconfig11
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/backend.c7
-rw-r--r--drivers/char/agp/generic.c33
-rw-r--r--drivers/char/amiserial.c4
-rw-r--r--drivers/char/applicom.c24
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/digi1.h38
-rw-r--r--drivers/char/digiFep1.h154
-rw-r--r--drivers/char/drm/Kconfig16
-rw-r--r--drivers/char/drm/Makefile7
-rw-r--r--drivers/char/drm/drm.h8
-rw-r--r--drivers/char/drm/drmP.h141
-rw-r--r--drivers/char/drm/drm_agpsupport.c143
-rw-r--r--drivers/char/drm/drm_bufs.c647
-rw-r--r--drivers/char/drm/drm_context.c19
-rw-r--r--drivers/char/drm/drm_drv.c79
-rw-r--r--drivers/char/drm/drm_fops.c6
-rw-r--r--drivers/char/drm/drm_ioctl.c2
-rw-r--r--drivers/char/drm/drm_memory.c8
-rw-r--r--drivers/char/drm/drm_pci.c55
-rw-r--r--drivers/char/drm/drm_pciids.h79
-rw-r--r--drivers/char/drm/drm_proc.c17
-rw-r--r--drivers/char/drm/drm_scatter.c11
-rw-r--r--drivers/char/drm/drm_stub.c8
-rw-r--r--drivers/char/drm/drm_sysfs.c1
-rw-r--r--drivers/char/drm/drm_vm.c92
-rw-r--r--drivers/char/drm/ffb_drv.c5
-rw-r--r--drivers/char/drm/gamma_context.h492
-rw-r--r--drivers/char/drm/gamma_dma.c946
-rw-r--r--drivers/char/drm/gamma_drm.h90
-rw-r--r--drivers/char/drm/gamma_drv.c59
-rw-r--r--drivers/char/drm/gamma_drv.h147
-rw-r--r--drivers/char/drm/gamma_lists.h215
-rw-r--r--drivers/char/drm/gamma_lock.h140
-rw-r--r--drivers/char/drm/gamma_old_dma.h313
-rw-r--r--drivers/char/drm/i810_dma.c22
-rw-r--r--drivers/char/drm/i810_drv.c1
-rw-r--r--drivers/char/drm/i810_drv.h1
-rw-r--r--drivers/char/drm/i830_dma.c22
-rw-r--r--drivers/char/drm/i830_drv.c1
-rw-r--r--drivers/char/drm/i830_drv.h1
-rw-r--r--drivers/char/drm/i915_dma.c31
-rw-r--r--drivers/char/drm/i915_drv.c1
-rw-r--r--drivers/char/drm/i915_drv.h4
-rw-r--r--drivers/char/drm/mga_dma.c612
-rw-r--r--drivers/char/drm/mga_drm.h98
-rw-r--r--drivers/char/drm/mga_drv.c45
-rw-r--r--drivers/char/drm/mga_drv.h94
-rw-r--r--drivers/char/drm/mga_ioc32.c67
-rw-r--r--drivers/char/drm/mga_irq.c72
-rw-r--r--drivers/char/drm/mga_state.c158
-rw-r--r--drivers/char/drm/mga_warp.c141
-rw-r--r--drivers/char/drm/r128_cce.c6
-rw-r--r--drivers/char/drm/r128_drm.h2
-rw-r--r--drivers/char/drm/r300_cmdbuf.c801
-rw-r--r--drivers/char/drm/r300_reg.h1412
-rw-r--r--drivers/char/drm/radeon_cp.c35
-rw-r--r--drivers/char/drm/radeon_drm.h46
-rw-r--r--drivers/char/drm/radeon_drv.c1
-rw-r--r--drivers/char/drm/radeon_drv.h30
-rw-r--r--drivers/char/drm/radeon_state.c75
-rw-r--r--drivers/char/drm/savage_bci.c1096
-rw-r--r--drivers/char/drm/savage_drm.h209
-rw-r--r--drivers/char/drm/savage_drv.c112
-rw-r--r--drivers/char/drm/savage_drv.h579
-rw-r--r--drivers/char/drm/savage_state.c1146
-rw-r--r--drivers/char/epca.c1588
-rw-r--r--drivers/char/epca.h108
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c6
-rw-r--r--drivers/char/hangcheck-timer.c3
-rw-r--r--drivers/char/hpet.c16
-rw-r--r--drivers/char/hvc_vio.c2
-rw-r--r--drivers/char/hvcs.c2
-rw-r--r--drivers/char/hw_random.c5
-rw-r--r--drivers/char/ip2/i2lib.c6
-rw-r--r--drivers/char/ip2main.c3
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c69
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c106
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c3
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c336
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c168
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c418
-rw-r--r--drivers/char/ipmi/ipmi_smic_sm.c3
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c52
-rw-r--r--drivers/char/istallion.c2
-rw-r--r--drivers/char/keyboard.c114
-rw-r--r--drivers/char/lcd.c7
-rw-r--r--drivers/char/lp.c3
-rw-r--r--drivers/char/mbcs.c2
-rw-r--r--drivers/char/mem.c4
-rw-r--r--drivers/char/misc.c9
-rw-r--r--drivers/char/moxa.c2
-rw-r--r--drivers/char/mwave/mwavedd.c21
-rw-r--r--drivers/char/mxser.c13
-rw-r--r--drivers/char/n_tty.c2
-rw-r--r--drivers/char/pcmcia/synclink_cs.c16
-rw-r--r--drivers/char/pty.c5
-rw-r--r--drivers/char/random.c34
-rw-r--r--drivers/char/rtc.c5
-rw-r--r--drivers/char/snsc_event.c11
-rw-r--r--drivers/char/sonypi.c118
-rw-r--r--drivers/char/synclink.c29
-rw-r--r--drivers/char/synclinkmp.c41
-rw-r--r--drivers/char/tpm/Kconfig2
-rw-r--r--drivers/char/tpm/tpm_atmel.c3
-rw-r--r--drivers/char/tpm/tpm_infineon.c76
-rw-r--r--drivers/char/tty_io.c93
-rw-r--r--drivers/char/viotape.c2
-rw-r--r--drivers/char/vt.c60
-rw-r--r--drivers/char/watchdog/Kconfig109
-rw-r--r--drivers/char/watchdog/Makefile78
-rw-r--r--drivers/char/watchdog/booke_wdt.c192
-rw-r--r--drivers/char/watchdog/i6300esb.c527
-rw-r--r--drivers/char/watchdog/ibmasr.c405
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c2
-rw-r--r--drivers/char/watchdog/mixcomwd.c2
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c434
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c252
-rw-r--r--drivers/char/watchdog/pcwd_pci.c44
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c87
-rw-r--r--drivers/char/watchdog/sbc8360.c414
-rw-r--r--drivers/char/watchdog/scx200_wdt.c2
-rw-r--r--drivers/char/watchdog/softdog.c13
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c6
-rw-r--r--drivers/char/watchdog/w83977f_wdt.c543
-rw-r--r--drivers/connector/Kconfig13
-rw-r--r--drivers/connector/Makefile3
-rw-r--r--drivers/connector/cn_queue.c173
-rw-r--r--drivers/connector/connector.c486
-rw-r--r--drivers/cpufreq/cpufreq.c6
-rw-r--r--drivers/firmware/Kconfig27
-rw-r--r--drivers/firmware/Makefile2
-rw-r--r--drivers/firmware/dcdbas.c596
-rw-r--r--drivers/firmware/dcdbas.h107
-rw-r--r--drivers/firmware/dell_rbu.c634
-rw-r--r--drivers/hwmon/Kconfig89
-rw-r--r--drivers/hwmon/Makefile5
-rw-r--r--drivers/hwmon/adm1021.c35
-rw-r--r--drivers/hwmon/adm1025.c31
-rw-r--r--drivers/hwmon/adm1026.c25
-rw-r--r--drivers/hwmon/adm1031.c24
-rw-r--r--drivers/hwmon/adm9240.c33
-rw-r--r--drivers/hwmon/asb100.c56
-rw-r--r--drivers/hwmon/atxp1.c26
-rw-r--r--drivers/hwmon/ds1621.c29
-rw-r--r--drivers/hwmon/fscher.c27
-rw-r--r--drivers/hwmon/fscpos.c27
-rw-r--r--drivers/hwmon/gl518sm.c28
-rw-r--r--drivers/hwmon/gl520sm.c31
-rw-r--r--drivers/hwmon/hdaps.c739
-rw-r--r--drivers/hwmon/hwmon-vid.c189
-rw-r--r--drivers/hwmon/hwmon.c98
-rw-r--r--drivers/hwmon/it87.c76
-rw-r--r--drivers/hwmon/lm63.c27
-rw-r--r--drivers/hwmon/lm75.c41
-rw-r--r--drivers/hwmon/lm75.h2
-rw-r--r--drivers/hwmon/lm77.c24
-rw-r--r--drivers/hwmon/lm78.c84
-rw-r--r--drivers/hwmon/lm80.c27
-rw-r--r--drivers/hwmon/lm83.c27
-rw-r--r--drivers/hwmon/lm85.c39
-rw-r--r--drivers/hwmon/lm87.c31
-rw-r--r--drivers/hwmon/lm90.c27
-rw-r--r--drivers/hwmon/lm92.c28
-rw-r--r--drivers/hwmon/max1619.c28
-rw-r--r--drivers/hwmon/pc87360.c852
-rw-r--r--drivers/hwmon/sis5595.c73
-rw-r--r--drivers/hwmon/smsc47b397.c74
-rw-r--r--drivers/hwmon/smsc47m1.c74
-rw-r--r--drivers/hwmon/via686a.c79
-rw-r--r--drivers/hwmon/w83627ehf.c64
-rw-r--r--drivers/hwmon/w83627hf.c94
-rw-r--r--drivers/hwmon/w83781d.c90
-rw-r--r--drivers/hwmon/w83792d.c1649
-rw-r--r--drivers/hwmon/w83l785ts.c27
-rw-r--r--drivers/i2c/Makefile4
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c16
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-sgi.c5
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c4
-rw-r--r--drivers/i2c/busses/Kconfig24
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c2
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c2
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c2
-rw-r--r--drivers/i2c/busses/i2c-amd756.c2
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c2
-rw-r--r--drivers/i2c/busses/i2c-au1550.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c4
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-isa.c161
-rw-r--r--drivers/i2c/busses/i2c-keywest.c16
-rw-r--r--drivers/i2c/busses/i2c-mpc.c4
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c12
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c38
-rw-r--r--drivers/i2c/busses/i2c-piix4.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c1022
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c1
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c2
-rw-r--r--drivers/i2c/busses/i2c-sis630.c2
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c2
-rw-r--r--drivers/i2c/busses/i2c-stub.c2
-rw-r--r--drivers/i2c/busses/i2c-viapro.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c4
-rw-r--r--drivers/i2c/chips/Kconfig10
-rw-r--r--drivers/i2c/chips/ds1337.c11
-rw-r--r--drivers/i2c/chips/ds1374.c3
-rw-r--r--drivers/i2c/chips/eeprom.c17
-rw-r--r--drivers/i2c/chips/isp1301_omap.c2
-rw-r--r--drivers/i2c/chips/m41t00.c3
-rw-r--r--drivers/i2c/chips/max6875.c462
-rw-r--r--drivers/i2c/chips/pca9539.c12
-rw-r--r--drivers/i2c/chips/pcf8574.c13
-rw-r--r--drivers/i2c/chips/pcf8591.c13
-rw-r--r--drivers/i2c/chips/rtc8564.c1
-rw-r--r--drivers/i2c/i2c-core.c256
-rw-r--r--drivers/i2c/i2c-dev.c5
-rw-r--r--drivers/i2c/i2c-sensor-detect.c145
-rw-r--r--drivers/i2c/i2c-sensor-vid.c98
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-io.c8
-rw-r--r--drivers/ide/ide-iops.c41
-rw-r--r--drivers/ide/ide-tape.c3
-rw-r--r--drivers/ide/ide-timing.h25
-rw-r--r--drivers/ide/ide.c4
-rw-r--r--drivers/ide/legacy/ide-cs.c10
-rw-r--r--drivers/ide/pci/cmd64x.c2
-rw-r--r--drivers/ide/pci/hpt34x.c2
-rw-r--r--drivers/ide/pci/hpt366.c8
-rw-r--r--drivers/ide/pci/sc1200.c12
-rw-r--r--drivers/ide/ppc/pmac.c16
-rw-r--r--drivers/ieee1394/ieee1394_core.c4
-rw-r--r--drivers/ieee1394/nodemgr.c8
-rw-r--r--drivers/ieee1394/pcilynx.c20
-rw-r--r--drivers/ieee1394/sbp2.c8
-rw-r--r--drivers/ieee1394/video1394.c2
-rw-r--r--drivers/infiniband/Kconfig25
-rw-r--r--drivers/infiniband/core/Makefile7
-rw-r--r--drivers/infiniband/core/agent.c13
-rw-r--r--drivers/infiniband/core/agent_priv.h10
-rw-r--r--drivers/infiniband/core/cache.c6
-rw-r--r--drivers/infiniband/core/cm.c130
-rw-r--r--drivers/infiniband/core/cm_msgs.h194
-rw-r--r--drivers/infiniband/core/core_priv.h2
-rw-r--r--drivers/infiniband/core/device.c1
-rw-r--r--drivers/infiniband/core/fmr_pool.c8
-rw-r--r--drivers/infiniband/core/mad.c15
-rw-r--r--drivers/infiniband/core/mad_priv.h10
-rw-r--r--drivers/infiniband/core/mad_rmpp.c315
-rw-r--r--drivers/infiniband/core/packer.c3
-rw-r--r--drivers/infiniband/core/sa_query.c36
-rw-r--r--drivers/infiniband/core/smi.c13
-rw-r--r--drivers/infiniband/core/sysfs.c42
-rw-r--r--drivers/infiniband/core/ucm.c647
-rw-r--r--drivers/infiniband/core/ucm.h24
-rw-r--r--drivers/infiniband/core/ud_header.c11
-rw-r--r--drivers/infiniband/core/user_mad.c10
-rw-r--r--drivers/infiniband/core/uverbs.h37
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c309
-rw-r--r--drivers/infiniband/core/uverbs_main.c112
-rw-r--r--drivers/infiniband/core/uverbs_mem.c1
-rw-r--r--drivers/infiniband/core/verbs.c65
-rw-r--r--drivers/infiniband/hw/mthca/Makefile4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c116
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c28
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c106
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h20
-rw-r--r--drivers/infiniband/hw/mthca/mthca_config_reg.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c256
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h52
-rw-r--r--drivers/infiniband/hw/mthca/mthca_doorbell.h13
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c63
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c187
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c36
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c12
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c35
-rw-r--r--drivers/infiniband/hw/mthca/mthca_pd.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c115
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h54
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c407
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c8
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c591
-rw-r--r--drivers/infiniband/hw/mthca/mthca_user.h11
-rw-r--r--drivers/infiniband/hw/mthca/mthca_wqe.h114
-rw-r--r--drivers/infiniband/ulp/ipoib/Makefile2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c35
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c1
-rw-r--r--drivers/input/evdev.c14
-rw-r--r--drivers/input/gameport/emu10k1-gp.c2
-rw-r--r--drivers/input/gameport/fm801-gp.c2
-rw-r--r--drivers/input/gameport/ns558.c4
-rw-r--r--drivers/input/input.c11
-rw-r--r--drivers/input/joystick/a3d.c2
-rw-r--r--drivers/input/joystick/adi.c2
-rw-r--r--drivers/input/joystick/analog.c2
-rw-r--r--drivers/input/joystick/cobra.c2
-rw-r--r--drivers/input/joystick/db9.c2
-rw-r--r--drivers/input/joystick/gamecon.c2
-rw-r--r--drivers/input/joystick/gf2k.c2
-rw-r--r--drivers/input/joystick/grip.c2
-rw-r--r--drivers/input/joystick/grip_mp.c2
-rw-r--r--drivers/input/joystick/guillemot.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c32
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/joystick/interact.c2
-rw-r--r--drivers/input/joystick/sidewinder.c2
-rw-r--r--drivers/input/joystick/tmdc.c2
-rw-r--r--drivers/input/joystick/turbografx.c2
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atkbd.c10
-rw-r--r--drivers/input/keyboard/corgikbd.c104
-rw-r--r--drivers/input/keyboard/spitzkbd.c478
-rw-r--r--drivers/input/keyboard/sunkbd.c2
-rw-r--r--drivers/input/mouse/Makefile2
-rw-r--r--drivers/input/mouse/alps.c2
-rw-r--r--drivers/input/mouse/logips2pp.c13
-rw-r--r--drivers/input/mouse/psmouse-base.c134
-rw-r--r--drivers/input/mouse/psmouse.h52
-rw-r--r--drivers/input/mouse/trackpoint.c304
-rw-r--r--drivers/input/mouse/trackpoint.h147
-rw-r--r--drivers/input/serio/i8042-io.h6
-rw-r--r--drivers/input/serio/i8042-ip22io.h2
-rw-r--r--drivers/input/serio/i8042-jazzio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h12
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h72
-rw-r--r--drivers/input/serio/i8042.c199
-rw-r--r--drivers/input/serio/serport.c4
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/corgi_ts.c117
-rw-r--r--drivers/isdn/act2000/capi.c2
-rw-r--r--drivers/isdn/capi/capifs.c4
-rw-r--r--drivers/isdn/hisax/hisax.h3
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c14
-rw-r--r--drivers/isdn/i4l/isdn_common.c3
-rw-r--r--drivers/isdn/i4l/isdn_net.c1
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c1
-rw-r--r--drivers/isdn/i4l/isdn_v110.c4
-rw-r--r--drivers/isdn/sc/init.c4
-rw-r--r--drivers/macintosh/mediabay.c6
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/md/bitmap.c183
-rw-r--r--drivers/md/dm-crypt.c7
-rw-r--r--drivers/md/dm-exception-store.c9
-rw-r--r--drivers/md/dm-io.c6
-rw-r--r--drivers/md/dm-raid1.c12
-rw-r--r--drivers/md/dm.c6
-rw-r--r--drivers/md/linear.c100
-rw-r--r--drivers/md/md.c227
-rw-r--r--drivers/md/multipath.c5
-rw-r--r--drivers/md/raid0.c5
-rw-r--r--drivers/md/raid1.c234
-rw-r--r--drivers/md/raid10.c46
-rw-r--r--drivers/md/raid5.c138
-rw-r--r--drivers/md/raid6main.c138
-rw-r--r--drivers/media/Makefile5
-rw-r--r--drivers/media/common/ir-common.c68
-rw-r--r--drivers/media/common/saa7146_core.c6
-rw-r--r--drivers/media/common/saa7146_fops.c1
-rw-r--r--drivers/media/common/saa7146_i2c.c10
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c102
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c3
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig6
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h2
-rw-r--r--drivers/media/dvb/bt8xx/dst.c763
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c554
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h8
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c282
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h2
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c96
-rw-r--r--drivers/media/dvb/dvb-core/demux.h36
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c20
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c532
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.h116
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c9
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig23
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c2
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c68
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h27
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c21
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c20
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c2
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c42
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c21
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c5
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h10
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c20
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h4
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c2
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c339
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c290
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h109
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c7
-rw-r--r--drivers/media/dvb/frontends/cx24110.c22
-rw-r--r--drivers/media/dvb/frontends/cx24110.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c1
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c1
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c50
-rw-r--r--drivers/media/dvb/frontends/mt352.c6
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c9
-rw-r--r--drivers/media/dvb/frontends/or51132.c29
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c162
-rw-r--r--drivers/media/dvb/frontends/s5h1420.h3
-rw-r--r--drivers/media/dvb/frontends/stv0297.c129
-rw-r--r--drivers/media/dvb/frontends/stv0297.h8
-rw-r--r--drivers/media/dvb/frontends/stv0299.c19
-rw-r--r--drivers/media/dvb/frontends/stv0299.h4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c3
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c1
-rw-r--r--drivers/media/dvb/frontends/ves1820.c15
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c1
-rw-r--r--drivers/media/dvb/ttpci/Kconfig3
-rw-r--r--drivers/media/dvb/ttpci/av7110.c201
-rw-r--r--drivers/media/dvb/ttpci/av7110.h11
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c8
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c140
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c74
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c9
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c197
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c5
-rw-r--r--drivers/media/dvb/ttpci/budget.c6
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c13
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c1
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-aztech.c2
-rw-r--r--drivers/media/radio/radio-cadet.c2
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c2
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-typhoon.c2
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
-rw-r--r--drivers/media/video/Kconfig16
-rw-r--r--drivers/media/video/Makefile4
-rw-r--r--drivers/media/video/adv7170.c2
-rw-r--r--drivers/media/video/adv7175.c2
-rw-r--r--drivers/media/video/bt819.c2
-rw-r--r--drivers/media/video/bt832.c4
-rw-r--r--drivers/media/video/bt856.c2
-rw-r--r--drivers/media/video/btcx-risc.c1
-rw-r--r--drivers/media/video/btcx-risc.h1
-rw-r--r--drivers/media/video/bttv-cards.c1180
-rw-r--r--drivers/media/video/bttv-driver.c68
-rw-r--r--drivers/media/video/bttv-gpio.c1
-rw-r--r--drivers/media/video/bttv-i2c.c14
-rw-r--r--drivers/media/video/bttv-if.c1
-rw-r--r--drivers/media/video/bttv-risc.c1
-rw-r--r--drivers/media/video/bttv-vbi.c1
-rw-r--r--drivers/media/video/bttv.h3
-rw-r--r--drivers/media/video/bttvp.h1
-rw-r--r--drivers/media/video/cpia_usb.c30
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c73
-rw-r--r--drivers/media/video/cx88/cx88-cards.c26
-rw-r--r--drivers/media/video/cx88/cx88-core.c21
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c52
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c9
-rw-r--r--drivers/media/video/cx88/cx88-input.c97
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c37
-rw-r--r--drivers/media/video/cx88/cx88-reg.h24
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c742
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c1
-rw-r--r--drivers/media/video/cx88/cx88-video.c408
-rw-r--r--drivers/media/video/cx88/cx88.h41
-rw-r--r--drivers/media/video/indycam.c412
-rw-r--r--drivers/media/video/indycam.h112
-rw-r--r--drivers/media/video/ir-kbd-gpio.c2
-rw-r--r--drivers/media/video/ir-kbd-i2c.c7
-rw-r--r--drivers/media/video/meye.c3
-rw-r--r--drivers/media/video/msp3400.c18
-rw-r--r--drivers/media/video/msp3400.h1
-rw-r--r--drivers/media/video/mt20xx.c2
-rw-r--r--drivers/media/video/ovcamchip/ov6x20.c6
-rw-r--r--drivers/media/video/ovcamchip/ov6x30.c4
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c14
-rw-r--r--drivers/media/video/rds.h48
-rw-r--r--drivers/media/video/saa6588.c534
-rw-r--r--drivers/media/video/saa7110.c1
-rw-r--r--drivers/media/video/saa7111.c2
-rw-r--r--drivers/media/video/saa7114.c2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c132
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-reg.h1
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c25
-rw-r--r--drivers/media/video/saa7134/saa7134.h4
-rw-r--r--drivers/media/video/saa7185.c2
-rw-r--r--drivers/media/video/saa7191.c512
-rw-r--r--drivers/media/video/saa7191.h139
-rw-r--r--drivers/media/video/stradis.c32
-rw-r--r--drivers/media/video/tda7432.c4
-rw-r--r--drivers/media/video/tda8290.c19
-rw-r--r--drivers/media/video/tda9840.c4
-rw-r--r--drivers/media/video/tda9875.c4
-rw-r--r--drivers/media/video/tda9887.c62
-rw-r--r--drivers/media/video/tea5767.c37
-rw-r--r--drivers/media/video/tea6415c.c4
-rw-r--r--drivers/media/video/tea6420.c4
-rw-r--r--drivers/media/video/tuner-3036.c3
-rw-r--r--drivers/media/video/tuner-core.c95
-rw-r--r--drivers/media/video/tuner-simple.c54
-rw-r--r--drivers/media/video/tvaudio.c225
-rw-r--r--drivers/media/video/tveeprom.c364
-rw-r--r--drivers/media/video/tvmixer.c15
-rw-r--r--drivers/media/video/v4l1-compat.c16
-rw-r--r--drivers/media/video/v4l2-common.c18
-rw-r--r--drivers/media/video/video-buf-dvb.c1
-rw-r--r--drivers/media/video/video-buf.c9
-rw-r--r--drivers/media/video/vino.c4273
-rw-r--r--drivers/media/video/vino.h61
-rw-r--r--drivers/media/video/vpx3220.c1
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/media/video/zoran_driver.c2
-rw-r--r--drivers/media/video/zr36120.c6
-rw-r--r--drivers/message/fusion/lsi/mpi.h19
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h85
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt67
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h203
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h11
-rw-r--r--drivers/message/fusion/lsi/mpi_targ.h74
-rw-r--r--drivers/message/fusion/mptbase.c321
-rw-r--r--drivers/message/fusion/mptbase.h5
-rw-r--r--drivers/message/fusion/mptctl.c14
-rw-r--r--drivers/message/fusion/mptscsih.c140
-rw-r--r--drivers/message/fusion/mptspi.c6
-rw-r--r--drivers/mfd/Kconfig25
-rw-r--r--drivers/mfd/Makefile12
-rw-r--r--drivers/mfd/mcp-core.c255
-rw-r--r--drivers/mfd/mcp-sa11x0.c275
-rw-r--r--drivers/mfd/mcp.h66
-rw-r--r--drivers/mfd/ucb1x00-assabet.c73
-rw-r--r--drivers/mfd/ucb1x00-core.c665
-rw-r--r--drivers/mfd/ucb1x00-ts.c399
-rw-r--r--drivers/mfd/ucb1x00.h256
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c23
-rw-r--r--drivers/misc/ibmasm/uart.c20
-rw-r--r--drivers/mmc/mmc.c565
-rw-r--r--drivers/mmc/mmc.h5
-rw-r--r--drivers/mmc/mmc_block.c9
-rw-r--r--drivers/mmc/mmc_sysfs.c113
-rw-r--r--drivers/mmc/mmci.c6
-rw-r--r--drivers/mmc/pxamci.c15
-rw-r--r--drivers/mmc/wbsd.c550
-rw-r--r--drivers/mmc/wbsd.h27
-rw-r--r--drivers/mtd/devices/mtdram.c3
-rw-r--r--drivers/mtd/ftl.c11
-rw-r--r--drivers/mtd/maps/uclinux.c13
-rw-r--r--drivers/mtd/nand/nand_base.c1
-rw-r--r--drivers/net/3c59x.c19
-rw-r--r--drivers/net/Kconfig59
-rw-r--r--drivers/net/Makefile5
-rw-r--r--drivers/net/Space.c12
-rw-r--r--drivers/net/ac3200.c2
-rw-r--r--drivers/net/arcnet/arcnet.c25
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/atari_bionet.c2
-rw-r--r--drivers/net/atari_pamsnet.c2
-rw-r--r--drivers/net/atarilance.c2
-rw-r--r--drivers/net/bnx2.c252
-rw-r--r--drivers/net/bnx2.h11
-rw-r--r--drivers/net/bonding/bond_3ad.c11
-rw-r--r--drivers/net/bonding/bond_3ad.h2
-rw-r--r--drivers/net/bonding/bond_alb.c22
-rw-r--r--drivers/net/bonding/bond_main.c58
-rw-r--r--drivers/net/bonding/bonding.h3
-rw-r--r--drivers/net/bsd_comp.c28
-rw-r--r--drivers/net/chelsio/Makefile11
-rw-r--r--drivers/net/chelsio/common.h314
-rw-r--r--drivers/net/chelsio/cphy.h148
-rw-r--r--drivers/net/chelsio/cpl5_cmd.h145
-rw-r--r--drivers/net/chelsio/cxgb2.c1256
-rw-r--r--drivers/net/chelsio/elmer0.h151
-rw-r--r--drivers/net/chelsio/espi.c346
-rw-r--r--drivers/net/chelsio/espi.h68
-rw-r--r--drivers/net/chelsio/gmac.h134
-rw-r--r--drivers/net/chelsio/mv88x201x.c252
-rw-r--r--drivers/net/chelsio/pm3393.c826
-rw-r--r--drivers/net/chelsio/regs.h468
-rw-r--r--drivers/net/chelsio/sge.c1684
-rw-r--r--drivers/net/chelsio/sge.h105
-rw-r--r--drivers/net/chelsio/subr.c812
-rw-r--r--drivers/net/chelsio/suni1x10gexp_regs.h213
-rw-r--r--drivers/net/cris/eth_v10.c6
-rw-r--r--drivers/net/cs89x0.c19
-rw-r--r--drivers/net/dm9000.c2
-rw-r--r--drivers/net/e100.c241
-rw-r--r--drivers/net/e1000/e1000_hw.h2
-rw-r--r--drivers/net/e1000/e1000_main.c18
-rw-r--r--drivers/net/eepro100.c8
-rw-r--r--drivers/net/fec.c478
-rw-r--r--drivers/net/fec.h7
-rw-r--r--drivers/net/forcedeth.c582
-rw-r--r--drivers/net/hamachi.c4
-rw-r--r--drivers/net/hamradio/6pack.c11
-rw-r--r--drivers/net/hamradio/Kconfig2
-rw-r--r--drivers/net/hamradio/baycom_epp.c20
-rw-r--r--drivers/net/hamradio/baycom_par.c3
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c3
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c3
-rw-r--r--drivers/net/hamradio/bpqether.c6
-rw-r--r--drivers/net/hamradio/dmascc.c10
-rw-r--r--drivers/net/hamradio/hdlcdrv.c16
-rw-r--r--drivers/net/hamradio/mkiss.c1088
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/hamradio/yam.c30
-rw-r--r--drivers/net/ibmveth.c2
-rw-r--r--drivers/net/irda/irda-usb.c13
-rw-r--r--drivers/net/irda/smsc-ircc2.c1179
-rw-r--r--drivers/net/irda/smsc-ircc2.h50
-rw-r--r--drivers/net/irda/vlsi_ir.c21
-rw-r--r--drivers/net/irda/vlsi_ir.h6
-rw-r--r--drivers/net/iseries_veth.c872
-rw-r--r--drivers/net/iseries_veth.h46
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_ee.c170
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c59
-rw-r--r--drivers/net/ixgb/ixgb_hw.h9
-rw-r--r--drivers/net/ixgb/ixgb_main.c53
-rw-r--r--drivers/net/jazzsonic.c186
-rw-r--r--drivers/net/loopback.c22
-rw-r--r--drivers/net/macsonic.c538
-rw-r--r--drivers/net/mv643xx_eth.c170
-rw-r--r--drivers/net/mv643xx_eth.h8
-rw-r--r--drivers/net/ne3210.c9
-rw-r--r--drivers/net/pci-skeleton.c6
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c25
-rw-r--r--drivers/net/phy/Kconfig57
-rw-r--r--drivers/net/phy/Makefile10
-rw-r--r--drivers/net/phy/cicada.c134
-rw-r--r--drivers/net/phy/davicom.c195
-rw-r--r--drivers/net/phy/lxt.c179
-rw-r--r--drivers/net/phy/marvell.c140
-rw-r--r--drivers/net/phy/mdio_bus.c176
-rw-r--r--drivers/net/phy/phy.c871
-rw-r--r--drivers/net/phy/phy_device.c696
-rw-r--r--drivers/net/phy/qsemi.c143
-rw-r--r--drivers/net/ppp_generic.c24
-rw-r--r--drivers/net/pppoe.c6
-rw-r--r--drivers/net/r8169.c1
-rw-r--r--drivers/net/rrunner.c3
-rw-r--r--drivers/net/s2io-regs.h92
-rw-r--r--drivers/net/s2io.c3137
-rw-r--r--drivers/net/s2io.h365
-rw-r--r--drivers/net/shaper.c50
-rw-r--r--drivers/net/sis190.c1884
-rw-r--r--drivers/net/skge.c65
-rw-r--r--drivers/net/skge.h19
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smc91x.h2
-rw-r--r--drivers/net/sonic.c676
-rw-r--r--drivers/net/sonic.h460
-rw-r--r--drivers/net/spider_net.c2334
-rw-r--r--drivers/net/spider_net.h469
-rw-r--r--drivers/net/spider_net_ethtool.c126
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/sungem.c37
-rw-r--r--drivers/net/sungem.h2
-rw-r--r--drivers/net/sunhme.c43
-rw-r--r--drivers/net/tg3.c533
-rw-r--r--drivers/net/tg3.h10
-rw-r--r--drivers/net/tokenring/Kconfig4
-rw-r--r--drivers/net/tokenring/abyss.c2
-rw-r--r--drivers/net/tokenring/madgemc.c521
-rw-r--r--drivers/net/tokenring/proteon.c104
-rw-r--r--drivers/net/tokenring/skisa.c104
-rw-r--r--drivers/net/tokenring/tms380tr.c46
-rw-r--r--drivers/net/tokenring/tms380tr.h9
-rw-r--r--drivers/net/tokenring/tmspci.c4
-rw-r--r--drivers/net/tulip/Kconfig12
-rw-r--r--drivers/net/tulip/Makefile1
-rw-r--r--drivers/net/tulip/de2104x.c2
-rw-r--r--drivers/net/tulip/de4x5.c4
-rw-r--r--drivers/net/tulip/media.c36
-rw-r--r--drivers/net/tulip/timer.c1
-rw-r--r--drivers/net/tulip/tulip.h8
-rw-r--r--drivers/net/tulip/tulip_core.c35
-rw-r--r--drivers/net/tulip/uli526x.c1749
-rw-r--r--drivers/net/tun.c15
-rw-r--r--drivers/net/wan/cycx_drv.c24
-rw-r--r--drivers/net/wan/hdlc_generic.c2
-rw-r--r--drivers/net/wan/lapbether.c2
-rw-r--r--drivers/net/wan/sdla_fr.c22
-rw-r--r--drivers/net/wan/syncppp.c3
-rw-r--r--drivers/net/wireless/Kconfig144
-rw-r--r--drivers/net/wireless/Makefile8
-rw-r--r--drivers/net/wireless/airo.c123
-rw-r--r--drivers/net/wireless/atmel.c79
-rw-r--r--drivers/net/wireless/hostap/Kconfig73
-rw-r--r--drivers/net/wireless/hostap/Makefile5
-rw-r--r--drivers/net/wireless/hostap/hostap.c1198
-rw-r--r--drivers/net/wireless/hostap/hostap.h57
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h96
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c1091
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c524
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c3288
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h261
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h435
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h55
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c1030
-rw-r--r--drivers/net/wireless/hostap/hostap_download.c766
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c3445
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c499
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c4102
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c473
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c645
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c448
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h1033
-rw-r--r--drivers/net/wireless/ieee802_11.h78
-rw-r--r--drivers/net/wireless/ipw2100.c8680
-rw-r--r--drivers/net/wireless/ipw2100.h1167
-rw-r--r--drivers/net/wireless/ipw2200.c7383
-rw-r--r--drivers/net/wireless/ipw2200.h1680
-rw-r--r--drivers/net/wireless/netwave_cs.c7
-rw-r--r--drivers/net/wireless/orinoco.c182
-rw-r--r--drivers/net/wireless/orinoco_cs.c2
-rw-r--r--drivers/net/wireless/orinoco_nortel.c324
-rw-r--r--drivers/net/wireless/orinoco_pci.c2
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c3
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c3
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c2
-rw-r--r--drivers/net/wireless/ray_cs.c866
-rw-r--r--drivers/net/wireless/ray_cs.h7
-rw-r--r--drivers/net/wireless/spectrum_cs.c1120
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c26
-rw-r--r--drivers/net/wireless/wavelan_cs.h6
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h17
-rw-r--r--drivers/net/wireless/wl3501.h5
-rw-r--r--drivers/net/wireless/wl3501_cs.c18
-rw-r--r--drivers/parisc/iosapic.c2
-rw-r--r--drivers/parisc/lasi.c1
-rw-r--r--drivers/parport/ieee1284.c7
-rw-r--r--drivers/parport/ieee1284_ops.c10
-rw-r--r--drivers/parport/parport_pc.c8
-rw-r--r--drivers/parport/parport_serial.c339
-rw-r--r--drivers/pci/Kconfig17
-rw-r--r--drivers/pci/Makefile22
-rw-r--r--drivers/pci/bus.c51
-rw-r--r--drivers/pci/gen-devlist.c132
-rw-r--r--drivers/pci/hotplug.c53
-rw-r--r--drivers/pci/hotplug/Kconfig4
-rw-r--r--drivers/pci/hotplug/Makefile7
-rw-r--r--drivers/pci/hotplug/pciehp.h2
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c8
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c299
-rw-r--r--drivers/pci/hotplug/rpaphp.h35
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c146
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c299
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c66
-rw-r--r--drivers/pci/hotplug/rpaphp_vio.c129
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c195
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/msi.c27
-rw-r--r--drivers/pci/msi.h5
-rw-r--r--drivers/pci/names.c137
-rw-r--r--drivers/pci/pci-driver.c37
-rw-r--r--drivers/pci/pci-sysfs.c10
-rw-r--r--drivers/pci/pci.c118
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/pci.ids10180
-rw-r--r--drivers/pci/pcie/portdrv_pci.c8
-rw-r--r--drivers/pci/probe.c60
-rw-r--r--drivers/pci/proc.c12
-rw-r--r--drivers/pci/quirks.c32
-rw-r--r--drivers/pci/rom.c24
-rw-r--r--drivers/pci/setup-bus.c6
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pcmcia/Kconfig7
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/cs.c9
-rw-r--r--drivers/pcmcia/cs_internal.h4
-rw-r--r--drivers/pcmcia/ds.c34
-rw-r--r--drivers/pcmcia/omap_cf.c373
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c12
-rw-r--r--drivers/pcmcia/pcmcia_resource.c11
-rw-r--r--drivers/pcmcia/pxa2xx_base.c2
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c2
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c116
-rw-r--r--drivers/pcmcia/sa1100_generic.c2
-rw-r--r--drivers/pcmcia/sa1111_generic.c2
-rw-r--r--drivers/pcmcia/sa11xx_base.c2
-rw-r--r--drivers/pcmcia/topic.h17
-rw-r--r--drivers/pcmcia/yenta_socket.c172
-rw-r--r--drivers/pcmcia/yenta_socket.h8
-rw-r--r--drivers/pnp/Kconfig2
-rw-r--r--drivers/pnp/card.c7
-rw-r--r--drivers/pnp/driver.c7
-rw-r--r--drivers/pnp/isapnp/core.c33
-rw-r--r--drivers/pnp/manager.c7
-rw-r--r--drivers/pnp/pnpacpi/Kconfig2
-rw-r--r--drivers/pnp/pnpacpi/core.c16
-rw-r--r--drivers/pnp/pnpacpi/pnpacpi.h1
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c93
-rw-r--r--drivers/pnp/pnpbios/core.c26
-rw-r--r--drivers/pnp/pnpbios/pnpbios.h1
-rw-r--r--drivers/pnp/pnpbios/proc.c8
-rw-r--r--drivers/pnp/pnpbios/rsparser.c16
-rw-r--r--drivers/pnp/quirks.c7
-rw-r--r--drivers/pnp/support.c7
-rw-r--r--drivers/s390/block/Kconfig2
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_devmap.c8
-rw-r--r--drivers/s390/block/dasd_diag.c334
-rw-r--r--drivers/s390/block/dasd_diag.h105
-rw-r--r--drivers/s390/block/dasd_genhd.c10
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c17
-rw-r--r--drivers/s390/block/dasd_proc.c8
-rw-r--r--drivers/s390/char/raw3270.c16
-rw-r--r--drivers/s390/cio/cio.c7
-rw-r--r--drivers/s390/cio/device_fsm.c3
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/ioasm.h26
-rw-r--r--drivers/s390/crypto/z90common.h3
-rw-r--r--drivers/s390/crypto/z90hardware.c127
-rw-r--r--drivers/s390/crypto/z90main.c246
-rw-r--r--drivers/s390/net/claw.c20
-rw-r--r--drivers/s390/s390mach.c2
-rw-r--r--drivers/s390/scsi/zfcp_aux.c28
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c10
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c25
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c1
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c25
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c2
-rw-r--r--drivers/sbus/char/Kconfig39
-rw-r--r--drivers/sbus/char/aurora.c3
-rw-r--r--drivers/sbus/char/bbc_envctrl.c3
-rw-r--r--drivers/sbus/char/bpp.c3
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/sbus/char/envctrl.c4
-rw-r--r--drivers/sbus/char/vfc_i2c.c3
-rw-r--r--drivers/scsi/3w-9xxx.c30
-rw-r--r--drivers/scsi/3w-xxxx.c57
-rw-r--r--drivers/scsi/53c7xx.c4
-rw-r--r--drivers/scsi/Kconfig24
-rw-r--r--drivers/scsi/Makefile4
-rw-r--r--drivers/scsi/NCR5380.c9
-rw-r--r--drivers/scsi/NCR53c406a.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c327
-rw-r--r--drivers/scsi/aacraid/aacraid.h55
-rw-r--r--drivers/scsi/aacraid/commctrl.c20
-rw-r--r--drivers/scsi/aacraid/comminit.c4
-rw-r--r--drivers/scsi/aacraid/commsup.c20
-rw-r--r--drivers/scsi/aacraid/linit.c106
-rw-r--r--drivers/scsi/aacraid/rkt.c20
-rw-r--r--drivers/scsi/aacraid/rx.c20
-rw-r--r--drivers/scsi/aacraid/sa.c22
-rw-r--r--drivers/scsi/advansys.c4
-rw-r--r--drivers/scsi/ahci.c120
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx1
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c1
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c104
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4570
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h288
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c82
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c88
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.seq5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_93cx6.c36
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c60
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c97
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c29
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c45
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped6
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped933
-rw-r--r--drivers/scsi/aic7xxx/aiclib.c1377
-rw-r--r--drivers/scsi/aic7xxx/aiclib.h890
-rw-r--r--drivers/scsi/ata_piix.c107
-rw-r--r--drivers/scsi/ch.c71
-rw-r--r--drivers/scsi/constants.c49
-rw-r--r--drivers/scsi/cpqfcTSinit.c3
-rw-r--r--drivers/scsi/hosts.c113
-rw-r--r--drivers/scsi/ibmmca.c1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c181
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c1
-rw-r--r--drivers/scsi/libata-core.c314
-rw-r--r--drivers/scsi/libata-scsi.c127
-rw-r--r--drivers/scsi/libata.h48
-rw-r--r--drivers/scsi/lpfc/lpfc.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c28
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h17
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c24
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h13
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/mesh.c6
-rw-r--r--drivers/scsi/osst.c13
-rw-r--r--drivers/scsi/pluto.c3
-rw-r--r--drivers/scsi/qla1280.c359
-rw-r--r--drivers/scsi/qla1280.h336
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c154
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h157
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h12
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c564
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c28
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c97
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c117
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c34
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/raid_class.c250
-rw-r--r--drivers/scsi/sata_mv.c827
-rw-r--r--drivers/scsi/sata_nv.c71
-rw-r--r--drivers/scsi/sata_promise.c113
-rw-r--r--drivers/scsi/sata_promise.h31
-rw-r--r--drivers/scsi/sata_qstor.c53
-rw-r--r--drivers/scsi/sata_sil.c81
-rw-r--r--drivers/scsi/sata_sis.c131
-rw-r--r--drivers/scsi/sata_svw.c50
-rw-r--r--drivers/scsi/sata_sx4.c233
-rw-r--r--drivers/scsi/sata_uli.c53
-rw-r--r--drivers/scsi/sata_via.c64
-rw-r--r--drivers/scsi/sata_vsc.c36
-rw-r--r--drivers/scsi/scsi.c17
-rw-r--r--drivers/scsi/scsi_devinfo.c4
-rw-r--r--drivers/scsi/scsi_error.c48
-rw-r--r--drivers/scsi/scsi_ioctl.c64
-rw-r--r--drivers/scsi/scsi_lib.c430
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_scan.c216
-rw-r--r--drivers/scsi/scsi_sysfs.c90
-rw-r--r--drivers/scsi/scsi_transport_fc.c6
-rw-r--r--drivers/scsi/scsi_transport_sas.c820
-rw-r--r--drivers/scsi/scsi_transport_spi.c168
-rw-r--r--drivers/scsi/sd.c185
-rw-r--r--drivers/scsi/sg.c26
-rw-r--r--drivers/scsi/sr.c75
-rw-r--r--drivers/scsi/sr.h1
-rw-r--r--drivers/scsi/sr_ioctl.c62
-rw-r--r--drivers/scsi/st.c156
-rw-r--r--drivers/scsi/st.h3
-rw-r--r--drivers/serial/21285.c10
-rw-r--r--drivers/serial/68328serial.c1
-rw-r--r--drivers/serial/68360serial.c8
-rw-r--r--drivers/serial/8250.c93
-rw-r--r--drivers/serial/8250.h6
-rw-r--r--drivers/serial/8250_accent.c2
-rw-r--r--drivers/serial/8250_acpi.c20
-rw-r--r--drivers/serial/8250_boca.c2
-rw-r--r--drivers/serial/8250_fourport.c2
-rw-r--r--drivers/serial/8250_hub6.c2
-rw-r--r--drivers/serial/8250_mca.c2
-rw-r--r--drivers/serial/8250_pci.c474
-rw-r--r--drivers/serial/Kconfig6
-rw-r--r--drivers/serial/amba-pl010.c8
-rw-r--r--drivers/serial/amba-pl011.c8
-rw-r--r--drivers/serial/au1x00_uart.c8
-rw-r--r--drivers/serial/clps711x.c10
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c21
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c11
-rw-r--r--drivers/serial/crisv10.c15
-rw-r--r--drivers/serial/dz.c10
-rw-r--r--drivers/serial/icom.c13
-rw-r--r--drivers/serial/imx.c28
-rw-r--r--drivers/serial/ioc4_serial.c6
-rw-r--r--drivers/serial/ip22zilog.c4
-rw-r--r--drivers/serial/jsm/jsm_tty.c4
-rw-r--r--drivers/serial/m32r_sio.c8
-rw-r--r--drivers/serial/mcfserial.c14
-rw-r--r--drivers/serial/mpc52xx_uart.c8
-rw-r--r--drivers/serial/mpsc.c8
-rw-r--r--drivers/serial/mux.c10
-rw-r--r--drivers/serial/pmac_zilog.c13
-rw-r--r--drivers/serial/pxa.c8
-rw-r--r--drivers/serial/s3c2410.c10
-rw-r--r--drivers/serial/sa1100.c8
-rw-r--r--drivers/serial/serial_core.c164
-rw-r--r--drivers/serial/serial_lh7a40x.c9
-rw-r--r--drivers/serial/serial_txx9.c126
-rw-r--r--drivers/serial/sh-sci.c12
-rw-r--r--drivers/serial/sn_console.c8
-rw-r--r--drivers/serial/sunsab.c8
-rw-r--r--drivers/serial/sunsu.c38
-rw-r--r--drivers/serial/sunzilog.c4
-rw-r--r--drivers/serial/uart00.c8
-rw-r--r--drivers/serial/v850e_uart.c6
-rw-r--r--drivers/serial/vr41xx_siu.c8
-rw-r--r--drivers/tc/zs.c2
-rw-r--r--drivers/telephony/ixj.c116
-rw-r--r--drivers/usb/atm/cxacru.c2
-rw-r--r--drivers/usb/atm/usbatm.c2
-rw-r--r--drivers/usb/class/Kconfig21
-rw-r--r--drivers/usb/class/audio.c12
-rw-r--r--drivers/usb/class/usblp.c9
-rw-r--r--drivers/usb/core/Makefile4
-rw-r--r--drivers/usb/core/devio.c102
-rw-r--r--drivers/usb/core/hcd-pci.c28
-rw-r--r--drivers/usb/core/hcd.c7
-rw-r--r--drivers/usb/core/hcd.h8
-rw-r--r--drivers/usb/core/hub.c144
-rw-r--r--drivers/usb/core/hub.h7
-rw-r--r--drivers/usb/core/inode.c9
-rw-r--r--drivers/usb/core/message.c8
-rw-r--r--drivers/usb/core/urb.c26
-rw-r--r--drivers/usb/core/usb.c37
-rw-r--r--drivers/usb/core/usb.h5
-rw-r--r--drivers/usb/gadget/ether.c33
-rw-r--r--drivers/usb/gadget/file_storage.c33
-rw-r--r--drivers/usb/gadget/gadget_chips.h55
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/serial.c51
-rw-r--r--drivers/usb/gadget/zero.c48
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c32
-rw-r--r--drivers/usb/host/ehci-hub.c27
-rw-r--r--drivers/usb/host/ehci-q.c7
-rw-r--r--drivers/usb/host/ehci-sched.c6
-rw-r--r--drivers/usb/host/ehci.h3
-rw-r--r--drivers/usb/host/hc_crisv10.c4
-rw-r--r--drivers/usb/host/isp116x-hcd.c90
-rw-r--r--drivers/usb/host/ohci-dbg.c11
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-hub.c22
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c24
-rw-r--r--drivers/usb/host/ohci-pxa27x.c48
-rw-r--r--drivers/usb/host/ohci-s3c2410.c4
-rw-r--r--drivers/usb/host/ohci.h1
-rw-r--r--drivers/usb/host/sl811-hcd.c8
-rw-r--r--drivers/usb/host/uhci-hcd.c62
-rw-r--r--drivers/usb/host/uhci-hcd.h11
-rw-r--r--drivers/usb/host/uhci-hub.c11
-rw-r--r--drivers/usb/host/uhci-q.c2
-rw-r--r--drivers/usb/input/Kconfig34
-rw-r--r--drivers/usb/input/Makefile2
-rw-r--r--drivers/usb/input/acecad.c2
-rw-r--r--drivers/usb/input/appletouch.c469
-rw-r--r--drivers/usb/input/hid-core.c81
-rw-r--r--drivers/usb/input/hid-debug.h34
-rw-r--r--drivers/usb/input/hid-input.c66
-rw-r--r--drivers/usb/input/hid.h9
-rw-r--r--drivers/usb/input/hiddev.c1
-rw-r--r--drivers/usb/input/itmtouch.c2
-rw-r--r--drivers/usb/input/keyspan_remote.c5
-rw-r--r--drivers/usb/input/map_to_7segment.h189
-rw-r--r--drivers/usb/input/pid.c2
-rw-r--r--drivers/usb/input/yealink.c1013
-rw-r--r--drivers/usb/input/yealink.h220
-rw-r--r--drivers/usb/media/stv680.c26
-rw-r--r--drivers/usb/media/w9968cf.c12
-rw-r--r--drivers/usb/misc/auerswald.c3
-rw-r--r--drivers/usb/misc/ldusb.c6
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig42
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile4
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c467
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h73
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c1658
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c1047
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h830
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_struct.h169
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/misc/uss720.c393
-rw-r--r--drivers/usb/mon/Makefile2
-rw-r--r--drivers/usb/mon/mon_dma.c55
-rw-r--r--drivers/usb/mon/mon_text.c37
-rw-r--r--drivers/usb/mon/usb_mon.h4
-rw-r--r--drivers/usb/net/Kconfig208
-rw-r--r--drivers/usb/net/Makefile10
-rw-r--r--drivers/usb/net/asix.c948
-rw-r--r--drivers/usb/net/catc.c2
-rw-r--r--drivers/usb/net/cdc_ether.c509
-rw-r--r--drivers/usb/net/cdc_subset.c335
-rw-r--r--drivers/usb/net/gl620a.c407
-rw-r--r--drivers/usb/net/kaweth.c1
-rw-r--r--drivers/usb/net/net1080.c622
-rw-r--r--drivers/usb/net/pegasus.c1
-rw-r--r--drivers/usb/net/plusb.c156
-rw-r--r--drivers/usb/net/rndis_host.c615
-rw-r--r--drivers/usb/net/rtl8150.c1
-rw-r--r--drivers/usb/net/usbnet.c3247
-rw-r--r--drivers/usb/net/usbnet.h193
-rw-r--r--drivers/usb/net/zaurus.c386
-rw-r--r--drivers/usb/net/zd1201.c17
-rw-r--r--drivers/usb/serial/cp2101.c5
-rw-r--r--drivers/usb/serial/cypress_m8.c254
-rw-r--r--drivers/usb/serial/ftdi_sio.c58
-rw-r--r--drivers/usb/serial/ftdi_sio.h54
-rw-r--r--drivers/usb/serial/keyspan.c8
-rw-r--r--drivers/usb/serial/option.c203
-rw-r--r--drivers/usb/serial/pl2303.c10
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/serial/usb-serial.c24
-rw-r--r--drivers/usb/storage/Kconfig12
-rw-r--r--drivers/usb/storage/Makefile1
-rw-r--r--drivers/usb/storage/onetouch.c210
-rw-r--r--drivers/usb/storage/onetouch.h9
-rw-r--r--drivers/usb/storage/scsiglue.c28
-rw-r--r--drivers/usb/storage/shuttle_usbat.c97
-rw-r--r--drivers/usb/storage/transport.c17
-rw-r--r--drivers/usb/storage/unusual_devs.h54
-rw-r--r--drivers/usb/storage/usb.c90
-rw-r--r--drivers/usb/storage/usb.h1
-rw-r--r--drivers/video/Kconfig83
-rw-r--r--drivers/video/Makefile7
-rw-r--r--drivers/video/aty/aty128fb.c18
-rw-r--r--drivers/video/aty/atyfb_base.c25
-rw-r--r--drivers/video/aty/radeon_base.c34
-rw-r--r--drivers/video/aty/radeon_i2c.c2
-rw-r--r--drivers/video/aty/radeon_pm.c12
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/corgi_bl.c25
-rw-r--r--drivers/video/backlight/locomolcd.c157
-rw-r--r--drivers/video/chipsfb.c4
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/Makefile4
-rw-r--r--drivers/video/console/bitblit.c148
-rw-r--r--drivers/video/console/fbcon.c203
-rw-r--r--drivers/video/console/fbcon.h5
-rw-r--r--drivers/video/console/font_10x18.c4
-rw-r--r--drivers/video/console/font_6x11.c4
-rw-r--r--drivers/video/console/font_7x14.c4
-rw-r--r--drivers/video/console/font_8x16.c4
-rw-r--r--drivers/video/console/font_8x8.c4
-rw-r--r--drivers/video/console/font_acorn_8x8.c4
-rw-r--r--drivers/video/console/font_mini_4x6.c4
-rw-r--r--drivers/video/console/font_pearl_8x8.c4
-rw-r--r--drivers/video/console/font_sun12x22.c4
-rw-r--r--drivers/video/console/font_sun8x16.c4
-rw-r--r--drivers/video/console/fonts.c9
-rw-r--r--drivers/video/console/vgacon.c71
-rw-r--r--drivers/video/cyblafb.c1456
-rw-r--r--drivers/video/fbcvt.c380
-rw-r--r--drivers/video/fbmem.c69
-rw-r--r--drivers/video/fbmon.c39
-rw-r--r--drivers/video/geode/Kconfig10
-rw-r--r--drivers/video/geode/display_gx1.c2
-rw-r--r--drivers/video/geode/geodefb.h1
-rw-r--r--drivers/video/geode/gx1fb_core.c182
-rw-r--r--drivers/video/geode/video_cs5530.c4
-rw-r--r--drivers/video/i810/Makefile5
-rw-r--r--drivers/video/i810/i810-i2c.c257
-rw-r--r--drivers/video/i810/i810.h14
-rw-r--r--drivers/video/i810/i810_main.c229
-rw-r--r--drivers/video/i810/i810_main.h16
-rw-r--r--drivers/video/intelfb/intelfb.h1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c21
-rw-r--r--drivers/video/intelfb/intelfbhw.c4
-rw-r--r--drivers/video/matrox/matroxfb_base.c13
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/matrox/matroxfb_misc.c30
-rw-r--r--drivers/video/modedb.c62
-rw-r--r--drivers/video/nvidia/nv_i2c.c19
-rw-r--r--drivers/video/nvidia/nv_local.h4
-rw-r--r--drivers/video/nvidia/nv_of.c3
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c6
-rw-r--r--drivers/video/nvidia/nvidia.c18
-rw-r--r--drivers/video/offb.c2
-rw-r--r--drivers/video/pm3fb.c3
-rw-r--r--drivers/video/pmag-aa-fb.c2
-rw-r--r--drivers/video/pmag-ba-fb.c285
-rw-r--r--drivers/video/pmagb-b-fb.c417
-rw-r--r--drivers/video/pxafb.c32
-rw-r--r--drivers/video/pxafb.h2
-rw-r--r--drivers/video/q40fb.c1
-rw-r--r--drivers/video/riva/fbdev.c4
-rw-r--r--drivers/video/riva/rivafb-i2c.c3
-rw-r--r--drivers/video/s1d13xxxfb.c2
-rw-r--r--drivers/video/s3c2410fb.c915
-rw-r--r--drivers/video/s3c2410fb.h56
-rw-r--r--drivers/video/savage/savagefb-i2c.c19
-rw-r--r--drivers/video/savage/savagefb.h13
-rw-r--r--drivers/video/savage/savagefb_driver.c153
-rw-r--r--drivers/video/sis/300vtbl.h1363
-rw-r--r--drivers/video/sis/310vtbl.h2125
-rw-r--r--drivers/video/sis/Makefile2
-rw-r--r--drivers/video/sis/init.c5603
-rw-r--r--drivers/video/sis/init.h1732
-rw-r--r--drivers/video/sis/init301.c9630
-rw-r--r--drivers/video/sis/init301.h351
-rw-r--r--drivers/video/sis/initdef.h145
-rw-r--r--drivers/video/sis/initextlfb.c238
-rw-r--r--drivers/video/sis/oem300.h335
-rw-r--r--drivers/video/sis/oem310.h421
-rw-r--r--drivers/video/sis/osdef.h27
-rw-r--r--drivers/video/sis/sis.h746
-rw-r--r--drivers/video/sis/sis_accel.c479
-rw-r--r--drivers/video/sis/sis_accel.h9
-rw-r--r--drivers/video/sis/sis_main.c7525
-rw-r--r--drivers/video/sis/sis_main.h602
-rw-r--r--drivers/video/sis/vgatypes.h155
-rw-r--r--drivers/video/sis/vstruct.h1097
-rw-r--r--drivers/video/tridentfb.c5
-rw-r--r--drivers/video/vesafb.c38
-rw-r--r--drivers/video/vgastate.c15
-rw-r--r--drivers/video/w100fb.c1912
-rw-r--r--drivers/video/w100fb.h777
-rw-r--r--drivers/w1/Kconfig16
-rw-r--r--drivers/w1/Makefile7
-rw-r--r--drivers/w1/ds_w1_bridge.c24
-rw-r--r--drivers/w1/dscore.c161
-rw-r--r--drivers/w1/dscore.h10
-rw-r--r--drivers/w1/w1.c302
-rw-r--r--drivers/w1/w1.h22
-rw-r--r--drivers/w1/w1_ds2433.c331
-rw-r--r--drivers/w1/w1_family.c11
-rw-r--r--drivers/w1/w1_family.h7
-rw-r--r--drivers/w1/w1_int.c30
-rw-r--r--drivers/w1/w1_io.c24
-rw-r--r--drivers/w1/w1_io.h1
-rw-r--r--drivers/w1/w1_netlink.c28
-rw-r--r--drivers/w1/w1_netlink.h2
-rw-r--r--drivers/w1/w1_smem.c49
-rw-r--r--drivers/w1/w1_therm.c47
-rw-r--r--fs/9p/9p.c359
-rw-r--r--fs/9p/9p.h341
-rw-r--r--fs/9p/Makefile17
-rw-r--r--fs/9p/conv.c693
-rw-r--r--fs/9p/conv.h36
-rw-r--r--fs/9p/debug.h70
-rw-r--r--fs/9p/error.c93
-rw-r--r--fs/9p/error.h178
-rw-r--r--fs/9p/fid.c241
-rw-r--r--fs/9p/fid.h57
-rw-r--r--fs/9p/mux.c475
-rw-r--r--fs/9p/mux.h41
-rw-r--r--fs/9p/trans_fd.c172
-rw-r--r--fs/9p/trans_sock.c290
-rw-r--r--fs/9p/transport.h46
-rw-r--r--fs/9p/v9fs.c452
-rw-r--r--fs/9p/v9fs.h103
-rw-r--r--fs/9p/v9fs_vfs.h53
-rw-r--r--fs/9p/vfs_dentry.c126
-rw-r--r--fs/9p/vfs_dir.c226
-rw-r--r--fs/9p/vfs_file.c401
-rw-r--r--fs/9p/vfs_inode.c1338
-rw-r--r--fs/9p/vfs_super.c280
-rw-r--r--fs/Kconfig88
-rw-r--r--fs/Makefile3
-rw-r--r--fs/adfs/adfs.h4
-rw-r--r--fs/affs/inode.c1
-rw-r--r--fs/aio.c38
-rw-r--r--fs/autofs/autofs_i.h3
-rw-r--r--fs/autofs/dirhash.c5
-rw-r--r--fs/autofs/inode.c3
-rw-r--r--fs/bfs/bfs.h1
-rw-r--r--fs/bfs/dir.c25
-rw-r--r--fs/bfs/file.c23
-rw-r--r--fs/bfs/inode.c104
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/bio.c259
-rw-r--r--fs/buffer.c41
-rw-r--r--fs/cifs/connect.c88
-rw-r--r--fs/cifs/dir.c27
-rw-r--r--fs/compat.c122
-rw-r--r--fs/compat_ioctl.c7
-rw-r--r--fs/cramfs/inode.c43
-rw-r--r--fs/cramfs/uncompress.c1
-rw-r--r--fs/dcache.c16
-rw-r--r--fs/devpts/Makefile1
-rw-r--r--fs/devpts/inode.c21
-rw-r--r--fs/devpts/xattr_security.c47
-rw-r--r--fs/exec.c8
-rw-r--r--fs/ext2/ialloc.c5
-rw-r--r--fs/ext2/inode.c2
-rw-r--r--fs/ext2/super.c59
-rw-r--r--fs/ext2/xattr.h8
-rw-r--r--fs/ext2/xattr_security.c22
-rw-r--r--fs/ext3/ialloc.c5
-rw-r--r--fs/ext3/inode.c2
-rw-r--r--fs/ext3/super.c92
-rw-r--r--fs/ext3/xattr.h11
-rw-r--r--fs/ext3/xattr_security.c22
-rw-r--r--fs/fat/dir.c28
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/fcntl.c60
-rw-r--r--fs/file.c387
-rw-r--r--fs/file_table.c41
-rw-r--r--fs/freevxfs/vxfs_super.c2
-rw-r--r--fs/fuse/Makefile7
-rw-r--r--fs/fuse/dev.c877
-rw-r--r--fs/fuse/dir.c982
-rw-r--r--fs/fuse/file.c555
-rw-r--r--fs/fuse/fuse_i.h451
-rw-r--r--fs/fuse/inode.c591
-rw-r--r--fs/hfs/bnode.c21
-rw-r--r--fs/hfs/catalog.c35
-rw-r--r--fs/hfs/dir.c11
-rw-r--r--fs/hfs/hfs.h1
-rw-r--r--fs/hfs/hfs_fs.h8
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfs/mdb.c6
-rw-r--r--fs/hfs/super.c68
-rw-r--r--fs/hfs/trans.c116
-rw-r--r--fs/hfsplus/bnode.c21
-rw-r--r--fs/hfsplus/hfsplus_fs.h5
-rw-r--r--fs/hfsplus/options.c26
-rw-r--r--fs/hfsplus/super.c11
-rw-r--r--fs/hostfs/hostfs.h1
-rw-r--r--fs/hostfs/hostfs_kern.c1
-rw-r--r--fs/hpfs/inode.c1
-rw-r--r--fs/inode.c15
-rw-r--r--fs/inotify.c16
-rw-r--r--fs/jbd/checkpoint.c2
-rw-r--r--fs/jbd/commit.c38
-rw-r--r--fs/jbd/journal.c38
-rw-r--r--fs/jbd/revoke.c5
-rw-r--r--fs/jbd/transaction.c42
-rw-r--r--fs/jffs/inode-v23.c4
-rw-r--r--fs/jffs/intrep.c22
-rw-r--r--fs/jffs2/file.c3
-rw-r--r--fs/jfs/acl.c24
-rw-r--r--fs/jfs/inode.c26
-rw-r--r--fs/jfs/jfs_acl.h12
-rw-r--r--fs/jfs/jfs_filsys.h3
-rw-r--r--fs/jfs/jfs_xattr.h14
-rw-r--r--fs/jfs/namei.c90
-rw-r--r--fs/jfs/super.c48
-rw-r--r--fs/jfs/xattr.c94
-rw-r--r--fs/lockd/clntproc.c3
-rw-r--r--fs/locks.c8
-rw-r--r--fs/minix/inode.c1
-rw-r--r--fs/namei.c78
-rw-r--r--fs/namespace.c10
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/nfs3proc.c3
-rw-r--r--fs/nfs/nfs4proc.c12
-rw-r--r--fs/nfsd/export.c3
-rw-r--r--fs/nfsd/nfs4idmap.c8
-rw-r--r--fs/nfsd/nfs4proc.c24
-rw-r--r--fs/nfsd/nfs4recover.c5
-rw-r--r--fs/nfsd/nfs4state.c90
-rw-r--r--fs/ntfs/ChangeLog71
-rw-r--r--fs/ntfs/Makefile2
-rw-r--r--fs/ntfs/aops.c294
-rw-r--r--fs/ntfs/attrib.c125
-rw-r--r--fs/ntfs/attrib.h2
-rw-r--r--fs/ntfs/compress.c8
-rw-r--r--fs/ntfs/dir.c3
-rw-r--r--fs/ntfs/file.c9
-rw-r--r--fs/ntfs/index.c1
-rw-r--r--fs/ntfs/inode.c227
-rw-r--r--fs/ntfs/lcnalloc.c39
-rw-r--r--fs/ntfs/lcnalloc.h21
-rw-r--r--fs/ntfs/logfile.c251
-rw-r--r--fs/ntfs/logfile.h8
-rw-r--r--fs/ntfs/malloc.h48
-rw-r--r--fs/ntfs/mft.c4
-rw-r--r--fs/ntfs/runlist.c374
-rw-r--r--fs/ntfs/runlist.h3
-rw-r--r--fs/ntfs/super.c30
-rw-r--r--fs/ntfs/unistr.c3
-rw-r--r--fs/open.c160
-rw-r--r--fs/pipe.c19
-rw-r--r--fs/proc/array.c5
-rw-r--r--fs/proc/base.c192
-rw-r--r--fs/proc/generic.c13
-rw-r--r--fs/proc/inode.c2
-rw-r--r--fs/proc/task_mmu.c357
-rw-r--r--fs/qnx4/inode.c1
-rw-r--r--fs/read_write.c2
-rw-r--r--fs/reiserfs/file.c11
-rw-r--r--fs/reiserfs/inode.c18
-rw-r--r--fs/reiserfs/journal.c7
-rw-r--r--fs/reiserfs/super.c3
-rw-r--r--fs/relayfs/Makefile4
-rw-r--r--fs/relayfs/buffers.c189
-rw-r--r--fs/relayfs/buffers.h12
-rw-r--r--fs/relayfs/inode.c609
-rw-r--r--fs/relayfs/relay.c431
-rw-r--r--fs/relayfs/relay.h12
-rw-r--r--fs/select.c23
-rw-r--r--fs/smbfs/inode.c1
-rw-r--r--fs/smbfs/proc.c3
-rw-r--r--fs/smbfs/sock.c2
-rw-r--r--fs/sysv/inode.c1
-rw-r--r--fs/udf/inode.c2
-rw-r--r--fs/ufs/balloc.c12
-rw-r--r--fs/ufs/ialloc.c6
-rw-r--r--fs/ufs/inode.c1
-rw-r--r--fs/ufs/truncate.c9
-rw-r--r--fs/umsdos/notes17
-rw-r--r--fs/xattr.c82
-rw-r--r--fs/xfs/Kconfig45
-rw-r--r--fs/xfs/Makefile151
-rw-r--r--fs/xfs/Makefile-linux-2.6152
-rw-r--r--fs/xfs/linux-2.6/kmem.c23
-rw-r--r--fs/xfs/linux-2.6/kmem.h23
-rw-r--r--fs/xfs/linux-2.6/spin.h3
-rw-r--r--fs/xfs/linux-2.6/time.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c259
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h50
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c123
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h12
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c90
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c18
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c65
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c15
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h13
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h7
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c178
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c251
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h60
-rw-r--r--fs/xfs/quota/Makefile1
-rw-r--r--fs/xfs/quota/Makefile-linux-2.653
-rw-r--r--fs/xfs/quota/xfs_dquot.c43
-rw-r--r--fs/xfs/quota/xfs_dquot.h16
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c1
-rw-r--r--fs/xfs/quota/xfs_qm.c26
-rw-r--r--fs/xfs/quota/xfs_qm.h2
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c44
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c16
-rw-r--r--fs/xfs/support/debug.c1
-rw-r--r--fs/xfs/support/ktrace.c2
-rw-r--r--fs/xfs/xfs_acl.c6
-rw-r--r--fs/xfs/xfs_arch.h22
-rw-r--r--fs/xfs/xfs_bmap.c12
-rw-r--r--fs/xfs/xfs_bmap_btree.c8
-rw-r--r--fs/xfs/xfs_bmap_btree.h12
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_dir_leaf.h6
-rw-r--r--fs/xfs/xfs_dmapi.h2
-rw-r--r--fs/xfs/xfs_extfree_item.c2
-rw-r--r--fs/xfs/xfs_iget.c35
-rw-r--r--fs/xfs/xfs_inode.c3
-rw-r--r--fs/xfs/xfs_inode_item.c13
-rw-r--r--fs/xfs/xfs_iomap.c22
-rw-r--r--fs/xfs/xfs_log.c215
-rw-r--r--fs/xfs/xfs_log.h38
-rw-r--r--fs/xfs/xfs_log_priv.h78
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_qmops.c78
-rw-r--r--fs/xfs/xfs_quota.h17
-rw-r--r--fs/xfs/xfs_trans.c3
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_ail.c2
-rw-r--r--fs/xfs/xfs_trans_buf.c23
-rw-r--r--fs/xfs/xfs_vfsops.c62
-rw-r--r--fs/xfs/xfs_vnodeops.c92
-rw-r--r--include/acpi/acconfig.h29
-rw-r--r--include/acpi/acdebug.h259
-rw-r--r--include/acpi/acdisasm.h322
-rw-r--r--include/acpi/acdispat.h405
-rw-r--r--include/acpi/acevents.h241
-rw-r--r--include/acpi/acexcep.h34
-rw-r--r--include/acpi/acglobal.h271
-rw-r--r--include/acpi/achware.h107
-rw-r--r--include/acpi/acinterp.h626
-rw-r--r--include/acpi/aclocal.h722
-rw-r--r--include/acpi/acmacros.h145
-rw-r--r--include/acpi/acnames.h13
-rw-r--r--include/acpi/acnamesp.h357
-rw-r--r--include/acpi/acobject.h390
-rw-r--r--include/acpi/acopcode.h6
-rw-r--r--include/acpi/acoutput.h10
-rw-r--r--include/acpi/acparser.h255
-rw-r--r--include/acpi/acpi.h35
-rw-r--r--include/acpi/acpi_bus.h334
-rw-r--r--include/acpi/acpi_drivers.h40
-rw-r--r--include/acpi/acpiosxf.h264
-rw-r--r--include/acpi/acpixf.h408
-rw-r--r--include/acpi/acresrc.h309
-rw-r--r--include/acpi/acstruct.h221
-rw-r--r--include/acpi/actables.h121
-rw-r--r--include/acpi/actbl.h282
-rw-r--r--include/acpi/actbl1.h141
-rw-r--r--include/acpi/actbl2.h260
-rw-r--r--include/acpi/actbl71.h148
-rw-r--r--include/acpi/actypes.h807
-rw-r--r--include/acpi/acutils.h718
-rw-r--r--include/acpi/amlcode.h172
-rw-r--r--include/acpi/amlresrc.h380
-rw-r--r--include/acpi/container.h3
-rw-r--r--include/acpi/pdc_intel.h4
-rw-r--r--include/acpi/platform/acenv.h70
-rw-r--r--include/acpi/platform/acgcc.h10
-rw-r--r--include/acpi/platform/aclinux.h15
-rw-r--r--include/acpi/processor.h238
-rw-r--r--include/asm-alpha/auxvec.h24
-rw-r--r--include/asm-alpha/elf.h22
-rw-r--r--include/asm-alpha/fcntl.h35
-rw-r--r--include/asm-alpha/futex.h53
-rw-r--r--include/asm-alpha/hdreg.h1
-rw-r--r--include/asm-alpha/page.h16
-rw-r--r--include/asm-alpha/pci.h13
-rw-r--r--include/asm-alpha/pgtable.h7
-rw-r--r--include/asm-alpha/socket.h2
-rw-r--r--include/asm-alpha/spinlock.h96
-rw-r--r--include/asm-alpha/spinlock_types.h20
-rw-r--r--include/asm-alpha/types.h2
-rw-r--r--include/asm-alpha/uaccess.h6
-rw-r--r--include/asm-arm/arch-ixp4xx/io.h102
-rw-r--r--include/asm-arm/arch-ixp4xx/platform.h19
-rw-r--r--include/asm-arm/arch-omap/board-h4.h3
-rw-r--r--include/asm-arm/arch-omap/board-innovator.h25
-rw-r--r--include/asm-arm/arch-omap/board-perseus2.h17
-rw-r--r--include/asm-arm/arch-omap/board-voiceblue.h5
-rw-r--r--include/asm-arm/arch-omap/board.h19
-rw-r--r--include/asm-arm/arch-omap/cpu.h187
-rw-r--r--include/asm-arm/arch-omap/debug-macro.S13
-rw-r--r--include/asm-arm/arch-omap/dma.h1
-rw-r--r--include/asm-arm/arch-omap/dmtimer.h92
-rw-r--r--include/asm-arm/arch-omap/dsp.h244
-rw-r--r--include/asm-arm/arch-omap/dsp_common.h37
-rw-r--r--include/asm-arm/arch-omap/entry-macro.S28
-rw-r--r--include/asm-arm/arch-omap/gpio.h28
-rw-r--r--include/asm-arm/arch-omap/hardware.h39
-rw-r--r--include/asm-arm/arch-omap/io.h26
-rw-r--r--include/asm-arm/arch-omap/irqs.h6
-rw-r--r--include/asm-arm/arch-omap/memory.h14
-rw-r--r--include/asm-arm/arch-omap/mtd-xip.h61
-rw-r--r--include/asm-arm/arch-omap/mux.h10
-rw-r--r--include/asm-arm/arch-omap/omap1510.h13
-rw-r--r--include/asm-arm/arch-omap/omap16xx.h16
-rw-r--r--include/asm-arm/arch-omap/omap24xx.h15
-rw-r--r--include/asm-arm/arch-omap/omap730.h4
-rw-r--r--include/asm-arm/arch-omap/pm.h55
-rw-r--r--include/asm-arm/arch-omap/serial.h37
-rw-r--r--include/asm-arm/arch-omap/uncompress.h10
-rw-r--r--include/asm-arm/arch-pxa/akita.h30
-rw-r--r--include/asm-arm/arch-pxa/corgi.h14
-rw-r--r--include/asm-arm/arch-pxa/hardware.h18
-rw-r--r--include/asm-arm/arch-pxa/i2c.h70
-rw-r--r--include/asm-arm/arch-pxa/mmc.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h29
-rw-r--r--include/asm-arm/arch-pxa/pxafb.h1
-rw-r--r--include/asm-arm/arch-pxa/sharpsl.h32
-rw-r--r--include/asm-arm/arch-pxa/spitz.h158
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-cpld.h24
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-irq.h23
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-map.h46
-rw-r--r--include/asm-arm/arch-s3c2410/fb.h69
-rw-r--r--include/asm-arm/arch-s3c2410/regs-clock.h11
-rw-r--r--include/asm-arm/arch-s3c2410/regs-lcd.h17
-rw-r--r--include/asm-arm/arch-sa1100/hardware.h18
-rw-r--r--include/asm-arm/arch-sa1100/mcp.h21
-rw-r--r--include/asm-arm/auxvec.h4
-rw-r--r--include/asm-arm/cacheflush.h7
-rw-r--r--include/asm-arm/fcntl.h78
-rw-r--r--include/asm-arm/futex.h53
-rw-r--r--include/asm-arm/hardware/gic.h41
-rw-r--r--include/asm-arm/hardware/scoop.h13
-rw-r--r--include/asm-arm/hdreg.h1
-rw-r--r--include/asm-arm/mach/irq.h12
-rw-r--r--include/asm-arm/mach/time.h2
-rw-r--r--include/asm-arm/page.h16
-rw-r--r--include/asm-arm/pci.h13
-rw-r--r--include/asm-arm/pgtable.h5
-rw-r--r--include/asm-arm/socket.h2
-rw-r--r--include/asm-arm/spinlock.h50
-rw-r--r--include/asm-arm/spinlock_types.h20
-rw-r--r--include/asm-arm/types.h2
-rw-r--r--include/asm-arm/uaccess.h6
-rw-r--r--include/asm-arm/unistd.h6
-rw-r--r--include/asm-arm26/auxvec.h4
-rw-r--r--include/asm-arm26/fcntl.h76
-rw-r--r--include/asm-arm26/futex.h53
-rw-r--r--include/asm-arm26/hardirq.h2
-rw-r--r--include/asm-arm26/hdreg.h1
-rw-r--r--include/asm-arm26/page.h16
-rw-r--r--include/asm-arm26/pgtable.h5
-rw-r--r--include/asm-arm26/socket.h2
-rw-r--r--include/asm-arm26/types.h2
-rw-r--r--include/asm-arm26/uaccess.h6
-rw-r--r--include/asm-cris/auxvec.h4
-rw-r--r--include/asm-cris/fcntl.h91
-rw-r--r--include/asm-cris/futex.h53
-rw-r--r--include/asm-cris/irq.h5
-rw-r--r--include/asm-cris/page.h15
-rw-r--r--include/asm-cris/socket.h2
-rw-r--r--include/asm-cris/types.h2
-rw-r--r--include/asm-cris/uaccess.h7
-rw-r--r--include/asm-frv/auxvec.h4
-rw-r--r--include/asm-frv/fcntl.h89
-rw-r--r--include/asm-frv/futex.h53
-rw-r--r--include/asm-frv/page.h17
-rw-r--r--include/asm-frv/pgtable.h3
-rw-r--r--include/asm-frv/socket.h2
-rw-r--r--include/asm-frv/types.h2
-rw-r--r--include/asm-frv/uaccess.h6
-rw-r--r--include/asm-generic/fcntl.h149
-rw-r--r--include/asm-generic/hdreg.h8
-rw-r--r--include/asm-generic/page.h26
-rw-r--r--include/asm-generic/pci.h13
-rw-r--r--include/asm-generic/pgtable.h16
-rw-r--r--include/asm-generic/sections.h1
-rw-r--r--include/asm-generic/tlb.h6
-rw-r--r--include/asm-generic/unaligned.h12
-rw-r--r--include/asm-generic/vmlinux.lds.h53
-rw-r--r--include/asm-h8300/auxvec.h4
-rw-r--r--include/asm-h8300/fcntl.h78
-rw-r--r--include/asm-h8300/futex.h53
-rw-r--r--include/asm-h8300/hdreg.h15
-rw-r--r--include/asm-h8300/page.h16
-rw-r--r--include/asm-h8300/pgtable.h2
-rw-r--r--include/asm-h8300/socket.h2
-rw-r--r--include/asm-h8300/types.h2
-rw-r--r--include/asm-h8300/uaccess.h6
-rw-r--r--include/asm-i386/acpi.h20
-rw-r--r--include/asm-i386/agp.h2
-rw-r--r--include/asm-i386/apic.h2
-rw-r--r--include/asm-i386/apicdef.h1
-rw-r--r--include/asm-i386/auxvec.h11
-rw-r--r--include/asm-i386/bugs.h5
-rw-r--r--include/asm-i386/checksum.h2
-rw-r--r--include/asm-i386/desc.h33
-rw-r--r--include/asm-i386/div64.h2
-rw-r--r--include/asm-i386/elf.h8
-rw-r--r--include/asm-i386/fcntl.h89
-rw-r--r--include/asm-i386/fixmap.h2
-rw-r--r--include/asm-i386/futex.h108
-rw-r--r--include/asm-i386/hdreg.h1
-rw-r--r--include/asm-i386/io_apic.h4
-rw-r--r--include/asm-i386/kdebug.h11
-rw-r--r--include/asm-i386/mach-default/mach_reboot.h10
-rw-r--r--include/asm-i386/mach-es7000/mach_mpparse.h30
-rw-r--r--include/asm-i386/mach-generic/mach_apic.h2
-rw-r--r--include/asm-i386/mmzone.h2
-rw-r--r--include/asm-i386/mpspec.h5
-rw-r--r--include/asm-i386/msr.h15
-rw-r--r--include/asm-i386/numa.h3
-rw-r--r--include/asm-i386/page.h17
-rw-r--r--include/asm-i386/pgtable-3level.h2
-rw-r--r--include/asm-i386/pgtable.h45
-rw-r--r--include/asm-i386/processor.h48
-rw-r--r--include/asm-i386/ptrace.h7
-rw-r--r--include/asm-i386/setup.h2
-rw-r--r--include/asm-i386/smp.h2
-rw-r--r--include/asm-i386/socket.h2
-rw-r--r--include/asm-i386/spinlock.h200
-rw-r--r--include/asm-i386/spinlock_types.h20
-rw-r--r--include/asm-i386/system.h36
-rw-r--r--include/asm-i386/thread_info.h7
-rw-r--r--include/asm-i386/timer.h3
-rw-r--r--include/asm-i386/topology.h2
-rw-r--r--include/asm-i386/types.h2
-rw-r--r--include/asm-i386/uaccess.h24
-rw-r--r--include/asm-i386/unistd.h12
-rw-r--r--include/asm-i386/xor.h26
-rw-r--r--include/asm-ia64/acpi-ext.h1
-rw-r--r--include/asm-ia64/acpi.h5
-rw-r--r--include/asm-ia64/auxvec.h11
-rw-r--r--include/asm-ia64/compat.h20
-rw-r--r--include/asm-ia64/elf.h8
-rw-r--r--include/asm-ia64/fcntl.h79
-rw-r--r--include/asm-ia64/futex.h53
-rw-r--r--include/asm-ia64/hdreg.h14
-rw-r--r--include/asm-ia64/hw_irq.h7
-rw-r--r--include/asm-ia64/io.h4
-rw-r--r--include/asm-ia64/iosapic.h4
-rw-r--r--include/asm-ia64/irq.h15
-rw-r--r--include/asm-ia64/kprobes.h1
-rw-r--r--include/asm-ia64/mca.h102
-rw-r--r--include/asm-ia64/mca_asm.h125
-rw-r--r--include/asm-ia64/mmu.h8
-rw-r--r--include/asm-ia64/mmu_context.h61
-rw-r--r--include/asm-ia64/page.h27
-rw-r--r--include/asm-ia64/pal.h21
-rw-r--r--include/asm-ia64/pci.h13
-rw-r--r--include/asm-ia64/pgtable.h17
-rw-r--r--include/asm-ia64/processor.h3
-rw-r--r--include/asm-ia64/ptrace.h4
-rw-r--r--include/asm-ia64/rwsem.h35
-rw-r--r--include/asm-ia64/sn/addrs.h112
-rw-r--r--include/asm-ia64/sn/geo.h3
-rw-r--r--include/asm-ia64/sn/intr.h3
-rw-r--r--include/asm-ia64/sn/nodepda.h3
-rw-r--r--include/asm-ia64/sn/pcibus_provider_defs.h8
-rw-r--r--include/asm-ia64/sn/pda.h1
-rw-r--r--include/asm-ia64/sn/sn2/sn_hwperf.h10
-rw-r--r--include/asm-ia64/sn/sn_feature_sets.h57
-rw-r--r--include/asm-ia64/sn/sn_sal.h96
-rw-r--r--include/asm-ia64/sn/tioce.h740
-rw-r--r--include/asm-ia64/sn/tioce_provider.h66
-rw-r--r--include/asm-ia64/socket.h2
-rw-r--r--include/asm-ia64/spinlock.h90
-rw-r--r--include/asm-ia64/spinlock_types.h21
-rw-r--r--include/asm-ia64/system.h6
-rw-r--r--include/asm-ia64/thread_info.h4
-rw-r--r--include/asm-ia64/topology.h23
-rw-r--r--include/asm-ia64/types.h2
-rw-r--r--include/asm-ia64/uaccess.h7
-rw-r--r--include/asm-ia64/unwind.h7
-rw-r--r--include/asm-m32r/auxvec.h4
-rw-r--r--include/asm-m32r/checksum.h2
-rw-r--r--include/asm-m32r/fcntl.h93
-rw-r--r--include/asm-m32r/futex.h53
-rw-r--r--include/asm-m32r/hdreg.h1
-rw-r--r--include/asm-m32r/page.h21
-rw-r--r--include/asm-m32r/pgtable.h3
-rw-r--r--include/asm-m32r/socket.h2
-rw-r--r--include/asm-m32r/spinlock.h127
-rw-r--r--include/asm-m32r/spinlock_types.h23
-rw-r--r--include/asm-m32r/types.h2
-rw-r--r--include/asm-m32r/uaccess.h25
-rw-r--r--include/asm-m68k/auxvec.h4
-rw-r--r--include/asm-m68k/cacheflush.h31
-rw-r--r--include/asm-m68k/fcntl.h78
-rw-r--r--include/asm-m68k/futex.h53
-rw-r--r--include/asm-m68k/hdreg.h1
-rw-r--r--include/asm-m68k/page.h16
-rw-r--r--include/asm-m68k/pgtable.h3
-rw-r--r--include/asm-m68k/socket.h2
-rw-r--r--include/asm-m68k/string.h403
-rw-r--r--include/asm-m68k/types.h2
-rw-r--r--include/asm-m68k/uaccess.h6
-rw-r--r--include/asm-m68knommu/auxvec.h4
-rw-r--r--include/asm-m68knommu/bitops.h2
-rw-r--r--include/asm-m68knommu/cacheflush.h29
-rw-r--r--include/asm-m68knommu/checksum.h7
-rw-r--r--include/asm-m68knommu/coldfire.h6
-rw-r--r--include/asm-m68knommu/futex.h53
-rw-r--r--include/asm-m68knommu/hdreg.h1
-rw-r--r--include/asm-m68knommu/m523xsim.h46
-rw-r--r--include/asm-m68knommu/m527xsim.h21
-rw-r--r--include/asm-m68knommu/m528xsim.h112
-rw-r--r--include/asm-m68knommu/mcfcache.h25
-rw-r--r--include/asm-m68knommu/mcfdma.h2
-rw-r--r--include/asm-m68knommu/mcfsim.h6
-rw-r--r--include/asm-m68knommu/mcfuart.h2
-rw-r--r--include/asm-m68knommu/page.h21
-rw-r--r--include/asm-m68knommu/pgtable.h2
-rw-r--r--include/asm-m68knommu/scatterlist.h6
-rw-r--r--include/asm-m68knommu/system.h54
-rw-r--r--include/asm-m68knommu/uaccess.h6
-rw-r--r--include/asm-mips/a.out.h4
-rw-r--r--include/asm-mips/addrspace.h2
-rw-r--r--include/asm-mips/asmmacro-32.h2
-rw-r--r--include/asm-mips/asmmacro-64.h2
-rw-r--r--include/asm-mips/asmmacro.h8
-rw-r--r--include/asm-mips/atomic.h4
-rw-r--r--include/asm-mips/auxvec.h4
-rw-r--r--include/asm-mips/bitops.h12
-rw-r--r--include/asm-mips/bugs.h2
-rw-r--r--include/asm-mips/checksum.h4
-rw-r--r--include/asm-mips/compat.h10
-rw-r--r--include/asm-mips/cpu-features.h4
-rw-r--r--include/asm-mips/ddb5xxx/ddb5477.h6
-rw-r--r--include/asm-mips/dec/prom.h12
-rw-r--r--include/asm-mips/delay.h6
-rw-r--r--include/asm-mips/elf.h16
-rw-r--r--include/asm-mips/fcntl.h75
-rw-r--r--include/asm-mips/fpregdef.h4
-rw-r--r--include/asm-mips/fpu.h8
-rw-r--r--include/asm-mips/futex.h53
-rw-r--r--include/asm-mips/hdreg.h1
-rw-r--r--include/asm-mips/hp-lj/asic.h7
-rw-r--r--include/asm-mips/ip32/mace.h8
-rw-r--r--include/asm-mips/irq.h3
-rw-r--r--include/asm-mips/lasat/serial.h4
-rw-r--r--include/asm-mips/local.h4
-rw-r--r--include/asm-mips/mach-au1x00/au1000.h2
-rw-r--r--include/asm-mips/mach-db1x00/db1x00.h2
-rw-r--r--include/asm-mips/mach-generic/spaces.h8
-rw-r--r--include/asm-mips/mach-ip22/spaces.h8
-rw-r--r--include/asm-mips/mach-ip32/cpu-feature-overrides.h2
-rw-r--r--include/asm-mips/mach-jazz/floppy.h2
-rw-r--r--include/asm-mips/mach-pb1x00/pb1500.h4
-rw-r--r--include/asm-mips/mach-qemu/cpu-feature-overrides.h31
-rw-r--r--include/asm-mips/mach-qemu/param.h13
-rw-r--r--include/asm-mips/mach-vr41xx/timex.h18
-rw-r--r--include/asm-mips/mmu_context.h6
-rw-r--r--include/asm-mips/module.h4
-rw-r--r--include/asm-mips/msgbuf.h12
-rw-r--r--include/asm-mips/paccess.h4
-rw-r--r--include/asm-mips/page.h16
-rw-r--r--include/asm-mips/pci.h21
-rw-r--r--include/asm-mips/pgalloc.h4
-rw-r--r--include/asm-mips/pgtable.h16
-rw-r--r--include/asm-mips/processor.h4
-rw-r--r--include/asm-mips/ptrace.h2
-rw-r--r--include/asm-mips/qemu.h24
-rw-r--r--include/asm-mips/r4kcache.h68
-rw-r--r--include/asm-mips/reg.h6
-rw-r--r--include/asm-mips/resource.h2
-rw-r--r--include/asm-mips/rtc.h2
-rw-r--r--include/asm-mips/sgi/gio.h2
-rw-r--r--include/asm-mips/sgi/hpc3.h4
-rw-r--r--include/asm-mips/sgi/ioc.h4
-rw-r--r--include/asm-mips/sgi/ip22.h2
-rw-r--r--include/asm-mips/sgi/mc.h6
-rw-r--r--include/asm-mips/sgiarcs.h8
-rw-r--r--include/asm-mips/sibyte/carmel.h12
-rw-r--r--include/asm-mips/sibyte/sb1250_defs.h38
-rw-r--r--include/asm-mips/sibyte/sb1250_dma.h42
-rw-r--r--include/asm-mips/sibyte/sb1250_genbus.h24
-rw-r--r--include/asm-mips/sibyte/sb1250_int.h24
-rw-r--r--include/asm-mips/sibyte/sb1250_l2c.h22
-rw-r--r--include/asm-mips/sibyte/sb1250_ldt.h32
-rw-r--r--include/asm-mips/sibyte/sb1250_mac.h26
-rw-r--r--include/asm-mips/sibyte/sb1250_mc.h28
-rw-r--r--include/asm-mips/sibyte/sb1250_regs.h68
-rw-r--r--include/asm-mips/sibyte/sb1250_scd.h36
-rw-r--r--include/asm-mips/sibyte/sb1250_smbus.h24
-rw-r--r--include/asm-mips/sibyte/sb1250_syncser.h12
-rw-r--r--include/asm-mips/sibyte/sb1250_uart.h30
-rw-r--r--include/asm-mips/sigcontext.h4
-rw-r--r--include/asm-mips/siginfo.h4
-rw-r--r--include/asm-mips/sim.h10
-rw-r--r--include/asm-mips/socket.h4
-rw-r--r--include/asm-mips/spinlock.h75
-rw-r--r--include/asm-mips/spinlock_types.h20
-rw-r--r--include/asm-mips/stackframe.h24
-rw-r--r--include/asm-mips/statfs.h2
-rw-r--r--include/asm-mips/string.h8
-rw-r--r--include/asm-mips/system.h4
-rw-r--r--include/asm-mips/thread_info.h4
-rw-r--r--include/asm-mips/titan_dep.h2
-rw-r--r--include/asm-mips/tx4927/tx4927.h52
-rw-r--r--include/asm-mips/tx4927/tx4927_pci.h4
-rw-r--r--include/asm-mips/types.h4
-rw-r--r--include/asm-mips/uaccess.h31
-rw-r--r--include/asm-mips/unistd.h2
-rw-r--r--include/asm-mips/vr4181/irq.h122
-rw-r--r--include/asm-mips/vr4181/vr4181.h413
-rw-r--r--include/asm-mips/vr41xx/tb0287.h (renamed from arch/mips/vr41xx/tanbac-tb0229/setup.c)32
-rw-r--r--include/asm-mips/vr41xx/vr41xx.h16
-rw-r--r--include/asm-mips/vr41xx/vrc4173.h4
-rw-r--r--include/asm-mips/war.h4
-rw-r--r--include/asm-mips/xxs1500.h2
-rw-r--r--include/asm-parisc/assembly.h2
-rw-r--r--include/asm-parisc/atomic.h12
-rw-r--r--include/asm-parisc/auxvec.h4
-rw-r--r--include/asm-parisc/bitops.h2
-rw-r--r--include/asm-parisc/cacheflush.h1
-rw-r--r--include/asm-parisc/compat.h10
-rw-r--r--include/asm-parisc/fcntl.h56
-rw-r--r--include/asm-parisc/futex.h53
-rw-r--r--include/asm-parisc/hdreg.h1
-rw-r--r--include/asm-parisc/irq.h5
-rw-r--r--include/asm-parisc/page.h16
-rw-r--r--include/asm-parisc/pci.h13
-rw-r--r--include/asm-parisc/pgtable.h3
-rw-r--r--include/asm-parisc/processor.h1
-rw-r--r--include/asm-parisc/socket.h2
-rw-r--r--include/asm-parisc/spinlock.h163
-rw-r--r--include/asm-parisc/spinlock_types.h21
-rw-r--r--include/asm-parisc/system.h24
-rw-r--r--include/asm-parisc/types.h2
-rw-r--r--include/asm-parisc/uaccess.h4
-rw-r--r--include/asm-powerpc/8253pit.h10
-rw-r--r--include/asm-powerpc/agp.h (renamed from include/asm-ppc/agp.h)8
-rw-r--r--include/asm-powerpc/bugs.h (renamed from include/asm-ppc64/siginfo.h)14
-rw-r--r--include/asm-powerpc/cputime.h1
-rw-r--r--include/asm-powerpc/div64.h (renamed from include/asm-ppc/div64.h)0
-rw-r--r--include/asm-powerpc/emergency-restart.h1
-rw-r--r--include/asm-powerpc/errno.h (renamed from include/asm-ppc/errno.h)6
-rw-r--r--include/asm-powerpc/fcntl.h11
-rw-r--r--include/asm-powerpc/ioctl.h (renamed from include/asm-ppc/ioctl.h)6
-rw-r--r--include/asm-powerpc/ioctls.h (renamed from include/asm-ppc/ioctls.h)6
-rw-r--r--include/asm-powerpc/ipc.h (renamed from include/asm-ppc/ipc.h)0
-rw-r--r--include/asm-powerpc/linkage.h6
-rw-r--r--include/asm-powerpc/local.h (renamed from include/asm-ppc64/local.h)0
-rw-r--r--include/asm-powerpc/mc146818rtc.h (renamed from include/asm-ppc64/mc146818rtc.h)10
-rw-r--r--include/asm-powerpc/mman.h (renamed from include/asm-ppc64/mman.h)6
-rw-r--r--include/asm-powerpc/module.h77
-rw-r--r--include/asm-powerpc/msgbuf.h (renamed from include/asm-ppc/msgbuf.h)16
-rw-r--r--include/asm-powerpc/namei.h (renamed from include/asm-ppc/namei.h)14
-rw-r--r--include/asm-powerpc/param.h (renamed from include/asm-ppc/param.h)10
-rw-r--r--include/asm-powerpc/percpu.h1
-rw-r--r--include/asm-powerpc/poll.h (renamed from include/asm-ppc/poll.h)6
-rw-r--r--include/asm-powerpc/resource.h1
-rw-r--r--include/asm-powerpc/sembuf.h (renamed from include/asm-ppc64/sembuf.h)31
-rw-r--r--include/asm-powerpc/setup.h9
-rw-r--r--include/asm-powerpc/shmbuf.h (renamed from include/asm-ppc64/shmbuf.h)42
-rw-r--r--include/asm-powerpc/shmparam.h6
-rw-r--r--include/asm-powerpc/siginfo.h26
-rw-r--r--include/asm-powerpc/socket.h (renamed from include/asm-ppc64/socket.h)14
-rw-r--r--include/asm-powerpc/sockios.h (renamed from include/asm-ppc64/sockios.h)6
-rw-r--r--include/asm-powerpc/string.h (renamed from include/asm-ppc/string.h)6
-rw-r--r--include/asm-powerpc/termbits.h (renamed from include/asm-ppc64/termbits.h)8
-rw-r--r--include/asm-powerpc/termios.h (renamed from include/asm-ppc64/termios.h)7
-rw-r--r--include/asm-powerpc/timex.h (renamed from include/asm-ppc/timex.h)37
-rw-r--r--include/asm-powerpc/topology.h (renamed from include/asm-ppc64/topology.h)9
-rw-r--r--include/asm-powerpc/unaligned.h (renamed from include/asm-ppc/unaligned.h)9
-rw-r--r--include/asm-powerpc/user.h (renamed from include/asm-ppc/user.h)15
-rw-r--r--include/asm-powerpc/xor.h (renamed from include/asm-ppc/xor.h)0
-rw-r--r--include/asm-ppc/8253pit.h10
-rw-r--r--include/asm-ppc/auxvec.h14
-rw-r--r--include/asm-ppc/bugs.h6
-rw-r--r--include/asm-ppc/cputime.h6
-rw-r--r--include/asm-ppc/dma-mapping.h3
-rw-r--r--include/asm-ppc/elf.h11
-rw-r--r--include/asm-ppc/emergency-restart.h6
-rw-r--r--include/asm-ppc/fcntl.h93
-rw-r--r--include/asm-ppc/futex.h53
-rw-r--r--include/asm-ppc/hdreg.h1
-rw-r--r--include/asm-ppc/ibm4xx.h12
-rw-r--r--include/asm-ppc/ibm_ocp.h19
-rw-r--r--include/asm-ppc/irq.h10
-rw-r--r--include/asm-ppc/kmap_types.h1
-rw-r--r--include/asm-ppc/linkage.h6
-rw-r--r--include/asm-ppc/local.h6
-rw-r--r--include/asm-ppc/mc146818rtc.h31
-rw-r--r--include/asm-ppc/mman.h44
-rw-r--r--include/asm-ppc/module.h44
-rw-r--r--include/asm-ppc/mpc8260.h18
-rw-r--r--include/asm-ppc/mpc8xx.h4
-rw-r--r--include/asm-ppc/mv64x60.h15
-rw-r--r--include/asm-ppc/mv64x60_defs.h9
-rw-r--r--include/asm-ppc/pci.h13
-rw-r--r--include/asm-ppc/percpu.h6
-rw-r--r--include/asm-ppc/pgtable.h11
-rw-r--r--include/asm-ppc/pmac_feature.h1
-rw-r--r--include/asm-ppc/ppc_sys.h5
-rw-r--r--include/asm-ppc/ptrace.h7
-rw-r--r--include/asm-ppc/reg.h6
-rw-r--r--include/asm-ppc/resource.h6
-rw-r--r--include/asm-ppc/segment.h1
-rw-r--r--include/asm-ppc/sembuf.h19
-rw-r--r--include/asm-ppc/serial.h2
-rw-r--r--include/asm-ppc/setup.h14
-rw-r--r--include/asm-ppc/shmbuf.h37
-rw-r--r--include/asm-ppc/shmparam.h6
-rw-r--r--include/asm-ppc/siginfo.h6
-rw-r--r--include/asm-ppc/smp.h6
-rw-r--r--include/asm-ppc/socket.h56
-rw-r--r--include/asm-ppc/sockios.h17
-rw-r--r--include/asm-ppc/spinlock.h91
-rw-r--r--include/asm-ppc/spinlock_types.h20
-rw-r--r--include/asm-ppc/system.h6
-rw-r--r--include/asm-ppc/termbits.h185
-rw-r--r--include/asm-ppc/termios.h232
-rw-r--r--include/asm-ppc/topology.h6
-rw-r--r--include/asm-ppc/types.h2
-rw-r--r--include/asm-ppc/uaccess.h7
-rw-r--r--include/asm-ppc64/8253pit.h10
-rw-r--r--include/asm-ppc64/abs_addr.h86
-rw-r--r--include/asm-ppc64/agp.h23
-rw-r--r--include/asm-ppc64/auxvec.h19
-rw-r--r--include/asm-ppc64/bugs.h12
-rw-r--r--include/asm-ppc64/compat.h18
-rw-r--r--include/asm-ppc64/cputable.h57
-rw-r--r--include/asm-ppc64/cputime.h6
-rw-r--r--include/asm-ppc64/div64.h1
-rw-r--r--include/asm-ppc64/eeh.h39
-rw-r--r--include/asm-ppc64/elf.h16
-rw-r--r--include/asm-ppc64/emergency-restart.h6
-rw-r--r--include/asm-ppc64/errno.h18
-rw-r--r--include/asm-ppc64/fcntl.h89
-rw-r--r--include/asm-ppc64/firmware.h101
-rw-r--r--include/asm-ppc64/futex.h83
-rw-r--r--include/asm-ppc64/hdreg.h1
-rw-r--r--include/asm-ppc64/hvcall.h6
-rw-r--r--include/asm-ppc64/imalloc.h2
-rw-r--r--include/asm-ppc64/io.h42
-rw-r--r--include/asm-ppc64/ioctl.h74
-rw-r--r--include/asm-ppc64/ioctls.h114
-rw-r--r--include/asm-ppc64/iommu.h3
-rw-r--r--include/asm-ppc64/ipc.h1
-rw-r--r--include/asm-ppc64/irq.h5
-rw-r--r--include/asm-ppc64/kprobes.h3
-rw-r--r--include/asm-ppc64/linkage.h6
-rw-r--r--include/asm-ppc64/lmb.h23
-rw-r--r--include/asm-ppc64/lppaca.h2
-rw-r--r--include/asm-ppc64/machdep.h13
-rw-r--r--include/asm-ppc64/memory.h2
-rw-r--r--include/asm-ppc64/mmu.h22
-rw-r--r--include/asm-ppc64/module.h36
-rw-r--r--include/asm-ppc64/msgbuf.h27
-rw-r--r--include/asm-ppc64/naca.h7
-rw-r--r--include/asm-ppc64/namei.h23
-rw-r--r--include/asm-ppc64/oprofile_impl.h (renamed from arch/ppc64/oprofile/op_impl.h)3
-rw-r--r--include/asm-ppc64/page.h72
-rw-r--r--include/asm-ppc64/param.h29
-rw-r--r--include/asm-ppc64/pci-bridge.h50
-rw-r--r--include/asm-ppc64/pci.h13
-rw-r--r--include/asm-ppc64/percpu.h6
-rw-r--r--include/asm-ppc64/pgalloc.h93
-rw-r--r--include/asm-ppc64/pgtable.h92
-rw-r--r--include/asm-ppc64/plpar_wrappers.h9
-rw-r--r--include/asm-ppc64/pmc.h2
-rw-r--r--include/asm-ppc64/poll.h32
-rw-r--r--include/asm-ppc64/processor.h20
-rw-r--r--include/asm-ppc64/prom.h33
-rw-r--r--include/asm-ppc64/ptrace-common.h92
-rw-r--r--include/asm-ppc64/ptrace.h128
-rw-r--r--include/asm-ppc64/resource.h6
-rw-r--r--include/asm-ppc64/segment.h6
-rw-r--r--include/asm-ppc64/setup.h6
-rw-r--r--include/asm-ppc64/shmparam.h13
-rw-r--r--include/asm-ppc64/spinlock.h191
-rw-r--r--include/asm-ppc64/spinlock_types.h20
-rw-r--r--include/asm-ppc64/string.h35
-rw-r--r--include/asm-ppc64/system.h26
-rw-r--r--include/asm-ppc64/timex.h26
-rw-r--r--include/asm-ppc64/types.h1
-rw-r--r--include/asm-ppc64/uaccess.h7
-rw-r--r--include/asm-ppc64/udbg.h27
-rw-r--r--include/asm-ppc64/unaligned.h21
-rw-r--r--include/asm-ppc64/user.h58
-rw-r--r--include/asm-ppc64/vio.h91
-rw-r--r--include/asm-ppc64/xor.h1
-rw-r--r--include/asm-s390/auxvec.h4
-rw-r--r--include/asm-s390/compat.h20
-rw-r--r--include/asm-s390/debug.h2
-rw-r--r--include/asm-s390/fcntl.h98
-rw-r--r--include/asm-s390/futex.h53
-rw-r--r--include/asm-s390/lowcore.h8
-rw-r--r--include/asm-s390/page.h16
-rw-r--r--include/asm-s390/socket.h2
-rw-r--r--include/asm-s390/spinlock.h67
-rw-r--r--include/asm-s390/spinlock_types.h21
-rw-r--r--include/asm-s390/types.h2
-rw-r--r--include/asm-s390/uaccess.h7
-rw-r--r--include/asm-sh/auxvec.h4
-rw-r--r--include/asm-sh/fcntl.h89
-rw-r--r--include/asm-sh/futex.h53
-rw-r--r--include/asm-sh/hdreg.h1
-rw-r--r--include/asm-sh/irq.h4
-rw-r--r--include/asm-sh/page.h20
-rw-r--r--include/asm-sh/pgtable.h3
-rw-r--r--include/asm-sh/socket.h2
-rw-r--r--include/asm-sh/spinlock.h61
-rw-r--r--include/asm-sh/spinlock_types.h22
-rw-r--r--include/asm-sh/types.h2
-rw-r--r--include/asm-sh/uaccess.h6
-rw-r--r--include/asm-sh64/auxvec.h4
-rw-r--r--include/asm-sh64/fcntl.h6
-rw-r--r--include/asm-sh64/futex.h53
-rw-r--r--include/asm-sh64/hdreg.h6
-rw-r--r--include/asm-sh64/page.h20
-rw-r--r--include/asm-sh64/pgtable.h3
-rw-r--r--include/asm-sh64/types.h2
-rw-r--r--include/asm-sh64/uaccess.h6
-rw-r--r--include/asm-sparc/auxvec.h4
-rw-r--r--include/asm-sparc/fcntl.h59
-rw-r--r--include/asm-sparc/futex.h53
-rw-r--r--include/asm-sparc/hdreg.h1
-rw-r--r--include/asm-sparc/page.h16
-rw-r--r--include/asm-sparc/pgtable.h3
-rw-r--r--include/asm-sparc/processor.h1
-rw-r--r--include/asm-sparc/ptrace.h4
-rw-r--r--include/asm-sparc/segment.h6
-rw-r--r--include/asm-sparc/socket.h2
-rw-r--r--include/asm-sparc/spinlock.h140
-rw-r--r--include/asm-sparc/spinlock_types.h20
-rw-r--r--include/asm-sparc/system.h1
-rw-r--r--include/asm-sparc/types.h2
-rw-r--r--include/asm-sparc/uaccess.h6
-rw-r--r--include/asm-sparc64/atomic.h8
-rw-r--r--include/asm-sparc64/auxvec.h4
-rw-r--r--include/asm-sparc64/bitops.h4
-rw-r--r--include/asm-sparc64/compat.h18
-rw-r--r--include/asm-sparc64/cpudata.h4
-rw-r--r--include/asm-sparc64/fcntl.h46
-rw-r--r--include/asm-sparc64/futex.h53
-rw-r--r--include/asm-sparc64/hardirq.h16
-rw-r--r--include/asm-sparc64/hdreg.h1
-rw-r--r--include/asm-sparc64/io.h47
-rw-r--r--include/asm-sparc64/page.h16
-rw-r--r--include/asm-sparc64/pci.h2
-rw-r--r--include/asm-sparc64/pgtable.h3
-rw-r--r--include/asm-sparc64/processor.h1
-rw-r--r--include/asm-sparc64/segment.h6
-rw-r--r--include/asm-sparc64/sfafsr.h82
-rw-r--r--include/asm-sparc64/socket.h2
-rw-r--r--include/asm-sparc64/spinlock.h152
-rw-r--r--include/asm-sparc64/spinlock_types.h20
-rw-r--r--include/asm-sparc64/system.h52
-rw-r--r--include/asm-sparc64/types.h2
-rw-r--r--include/asm-sparc64/uaccess.h6
-rw-r--r--include/asm-um/auxvec.h4
-rw-r--r--include/asm-um/futex.h53
-rw-r--r--include/asm-um/hdreg.h6
-rw-r--r--include/asm-um/mmu_context.h10
-rw-r--r--include/asm-um/page.h19
-rw-r--r--include/asm-um/pgalloc.h12
-rw-r--r--include/asm-um/pgtable-2level.h27
-rw-r--r--include/asm-um/pgtable-3level.h45
-rw-r--r--include/asm-um/pgtable.h68
-rw-r--r--include/asm-um/spinlock_types.h6
-rw-r--r--include/asm-v850/auxvec.h4
-rw-r--r--include/asm-v850/fcntl.h78
-rw-r--r--include/asm-v850/futex.h53
-rw-r--r--include/asm-v850/page.h21
-rw-r--r--include/asm-v850/socket.h2
-rw-r--r--include/asm-v850/types.h2
-rw-r--r--include/asm-v850/uaccess.h6
-rw-r--r--include/asm-x86_64/acpi.h27
-rw-r--r--include/asm-x86_64/apic.h3
-rw-r--r--include/asm-x86_64/apicdef.h1
-rw-r--r--include/asm-x86_64/auxvec.h4
-rw-r--r--include/asm-x86_64/bug.h10
-rw-r--r--include/asm-x86_64/calling.h23
-rw-r--r--include/asm-x86_64/checksum.h2
-rw-r--r--include/asm-x86_64/compat.h20
-rw-r--r--include/asm-x86_64/current.h2
-rw-r--r--include/asm-x86_64/desc.h2
-rw-r--r--include/asm-x86_64/dma-mapping.h5
-rw-r--r--include/asm-x86_64/dwarf2.h8
-rw-r--r--include/asm-x86_64/fcntl.h77
-rw-r--r--include/asm-x86_64/fixmap.h2
-rw-r--r--include/asm-x86_64/futex.h98
-rw-r--r--include/asm-x86_64/hardirq.h9
-rw-r--r--include/asm-x86_64/hdreg.h1
-rw-r--r--include/asm-x86_64/hw_irq.h18
-rw-r--r--include/asm-x86_64/io.h14
-rw-r--r--include/asm-x86_64/io_apic.h2
-rw-r--r--include/asm-x86_64/ipi.h23
-rw-r--r--include/asm-x86_64/irq.h4
-rw-r--r--include/asm-x86_64/kdebug.h4
-rw-r--r--include/asm-x86_64/local.h4
-rw-r--r--include/asm-x86_64/mmzone.h4
-rw-r--r--include/asm-x86_64/mpspec.h2
-rw-r--r--include/asm-x86_64/msr.h49
-rw-r--r--include/asm-x86_64/numa.h3
-rw-r--r--include/asm-x86_64/page.h21
-rw-r--r--include/asm-x86_64/pci.h6
-rw-r--r--include/asm-x86_64/pda.h14
-rw-r--r--include/asm-x86_64/pgalloc.h8
-rw-r--r--include/asm-x86_64/pgtable.h28
-rw-r--r--include/asm-x86_64/processor.h19
-rw-r--r--include/asm-x86_64/proto.h6
-rw-r--r--include/asm-x86_64/signal.h10
-rw-r--r--include/asm-x86_64/smp.h2
-rw-r--r--include/asm-x86_64/socket.h2
-rw-r--r--include/asm-x86_64/spinlock.h164
-rw-r--r--include/asm-x86_64/spinlock_types.h20
-rw-r--r--include/asm-x86_64/system.h8
-rw-r--r--include/asm-x86_64/timex.h1
-rw-r--r--include/asm-x86_64/tlbflush.h4
-rw-r--r--include/asm-x86_64/topology.h3
-rw-r--r--include/asm-x86_64/types.h2
-rw-r--r--include/asm-x86_64/uaccess.h7
-rw-r--r--include/asm-x86_64/vsyscall.h1
-rw-r--r--include/asm-xtensa/atomic.h12
-rw-r--r--include/asm-xtensa/auxvec.h4
-rw-r--r--include/asm-xtensa/checksum.h4
-rw-r--r--include/asm-xtensa/delay.h2
-rw-r--r--include/asm-xtensa/fcntl.h48
-rw-r--r--include/asm-xtensa/hdreg.h17
-rw-r--r--include/asm-xtensa/io.h14
-rw-r--r--include/asm-xtensa/mmu_context.h18
-rw-r--r--include/asm-xtensa/page.h2
-rw-r--r--include/asm-xtensa/page.h.n135
-rw-r--r--include/asm-xtensa/pci.h4
-rw-r--r--include/asm-xtensa/pgtable.h12
-rw-r--r--include/asm-xtensa/ptrace.h2
-rw-r--r--include/asm-xtensa/semaphore.h10
-rw-r--r--include/asm-xtensa/socket.h2
-rw-r--r--include/asm-xtensa/string.h8
-rw-r--r--include/asm-xtensa/system.h10
-rw-r--r--include/asm-xtensa/tlbflush.h40
-rw-r--r--include/asm-xtensa/types.h2
-rw-r--r--include/asm-xtensa/uaccess.h12
-rw-r--r--include/linux/8250_pci.h39
-rw-r--r--include/linux/acpi.h45
-rw-r--r--include/linux/ata.h45
-rw-r--r--include/linux/attribute_container.h12
-rw-r--r--include/linux/auxvec.h31
-rw-r--r--include/linux/bfs_fs.h23
-rw-r--r--include/linux/bio.h15
-rw-r--r--include/linux/bit_spinlock.h77
-rw-r--r--include/linux/blkdev.h12
-rw-r--r--include/linux/capability.h1
-rw-r--r--include/linux/chio.h2
-rw-r--r--include/linux/compat.h3
-rw-r--r--include/linux/connector.h158
-rw-r--r--include/linux/cpu.h2
-rw-r--r--include/linux/cpuset.h11
-rw-r--r--include/linux/crc16.h30
-rw-r--r--include/linux/crypto.h1
-rw-r--r--include/linux/dcache.h4
-rw-r--r--include/linux/dccp.h459
-rw-r--r--include/linux/dmapool.h3
-rw-r--r--include/linux/dmi.h36
-rw-r--r--include/linux/efi.h14
-rw-r--r--include/linux/elf.h24
-rw-r--r--include/linux/etherdevice.h6
-rw-r--r--include/linux/ethtool.h17
-rw-r--r--include/linux/ext2_fs.h3
-rw-r--r--include/linux/ext3_fs.h2
-rw-r--r--include/linux/fb.h30
-rw-r--r--include/linux/file.h30
-rw-r--r--include/linux/firmware.h5
-rw-r--r--include/linux/font.h10
-rw-r--r--include/linux/fs.h19
-rw-r--r--include/linux/fuse.h259
-rw-r--r--include/linux/futex.h36
-rw-r--r--include/linux/gfp.h8
-rw-r--r--include/linux/hippidevice.h8
-rw-r--r--include/linux/hugetlb.h6
-rw-r--r--include/linux/hwmon-sysfs.h15
-rw-r--r--include/linux/hwmon-vid.h45
-rw-r--r--include/linux/hwmon.h35
-rw-r--r--include/linux/i2c-id.h192
-rw-r--r--include/linux/i2c-isa.h36
-rw-r--r--include/linux/i2c-pxa.h48
-rw-r--r--include/linux/i2c-sensor.h263
-rw-r--r--include/linux/i2c-vid.h111
-rw-r--r--include/linux/i2c.h206
-rw-r--r--include/linux/if_ether.h2
-rw-r--r--include/linux/if_fc.h2
-rw-r--r--include/linux/if_fddi.h2
-rw-r--r--include/linux/if_frad.h6
-rw-r--r--include/linux/if_hippi.h6
-rw-r--r--include/linux/if_tr.h4
-rw-r--r--include/linux/if_tun.h1
-rw-r--r--include/linux/if_vlan.h1
-rw-r--r--include/linux/igmp.h3
-rw-r--r--include/linux/in.h1
-rw-r--r--include/linux/in6.h52
-rw-r--r--include/linux/inet_diag.h138
-rw-r--r--include/linux/init_task.h18
-rw-r--r--include/linux/inotify.h1
-rw-r--r--include/linux/input.h33
-rw-r--r--include/linux/interrupt.h7
-rw-r--r--include/linux/ioctl32.h22
-rw-r--r--include/linux/ip.h2
-rw-r--r--include/linux/ipmi.h34
-rw-r--r--include/linux/ipv6.h69
-rw-r--r--include/linux/irq.h130
-rw-r--r--include/linux/isdn.h1
-rw-r--r--include/linux/jbd.h2
-rw-r--r--include/linux/jiffies.h40
-rw-r--r--include/linux/kernel.h4
-rw-r--r--include/linux/klist.h16
-rw-r--r--include/linux/kprobes.h3
-rw-r--r--include/linux/libata.h51
-rw-r--r--include/linux/linkage.h7
-rw-r--r--include/linux/list.h65
-rw-r--r--include/linux/mempolicy.h4
-rw-r--r--include/linux/mii.h9
-rw-r--r--include/linux/mmc/card.h15
-rw-r--r--include/linux/mmc/host.h34
-rw-r--r--include/linux/mmc/mmc.h2
-rw-r--r--include/linux/mmc/protocol.h7
-rw-r--r--include/linux/mmzone.h25
-rw-r--r--include/linux/mod_devicetable.h17
-rw-r--r--include/linux/msg.h1
-rw-r--r--include/linux/mv643xx.h2
-rw-r--r--include/linux/net.h11
-rw-r--r--include/linux/netdevice.h35
-rw-r--r--include/linux/netfilter.h88
-rw-r--r--include/linux/netfilter/nfnetlink.h169
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h124
-rw-r--r--include/linux/netfilter/nfnetlink_log.h88
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h89
-rw-r--r--include/linux/netfilter_decnet.h17
-rw-r--r--include/linux/netfilter_ipv4.h8
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h194
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_core.h18
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_protocol.h24
-rw-r--r--include/linux/netfilter_ipv4/ip_logging.h20
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_protocol.h25
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_rule.h5
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h3
-rw-r--r--include/linux/netfilter_ipv4/ipt_LOG.h1
-rw-r--r--include/linux/netfilter_ipv4/ipt_NFQUEUE.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_TTL.h21
-rw-r--r--include/linux/netfilter_ipv4/ipt_connbytes.h25
-rw-r--r--include/linux/netfilter_ipv4/ipt_dccp.h23
-rw-r--r--include/linux/netfilter_ipv4/ipt_string.h18
-rw-r--r--include/linux/netfilter_ipv6.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6_logging.h20
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6t_HL.h22
-rw-r--r--include/linux/netfilter_ipv6/ip6t_LOG.h1
-rw-r--r--include/linux/netfilter_ipv6/ip6t_REJECT.h18
-rw-r--r--include/linux/netlink.h19
-rw-r--r--include/linux/nfsd/xdr4.h15
-rw-r--r--include/linux/page-flags.h2
-rw-r--r--include/linux/pci.h519
-rw-r--r--include/linux/pci_ids.h54
-rw-r--r--include/linux/pci_regs.h448
-rw-r--r--include/linux/phy.h377
-rw-r--r--include/linux/pipe_fs_i.h3
-rw-r--r--include/linux/pktcdvd.h3
-rw-r--r--include/linux/pm.h14
-rw-r--r--include/linux/pnp.h2
-rw-r--r--include/linux/ptrace.h3
-rw-r--r--include/linux/radix-tree.h4
-rw-r--r--include/linux/raid/bitmap.h15
-rw-r--r--include/linux/raid/linear.h4
-rw-r--r--include/linux/raid/md_k.h81
-rw-r--r--include/linux/raid/md_p.h16
-rw-r--r--include/linux/raid/raid1.h13
-rw-r--r--include/linux/raid/raid5.h14
-rw-r--r--include/linux/raid_class.h59
-rw-r--r--include/linux/random.h2
-rw-r--r--include/linux/rcupdate.h4
-rw-r--r--include/linux/rcuref.h220
-rw-r--r--include/linux/reiserfs_fs.h6
-rw-r--r--include/linux/relayfs_fs.h255
-rw-r--r--include/linux/rtnetlink.h42
-rw-r--r--include/linux/sched.h49
-rw-r--r--include/linux/security.h186
-rw-r--r--include/linux/selinux_netlink.h13
-rw-r--r--include/linux/sem.h1
-rw-r--r--include/linux/serial.h4
-rw-r--r--include/linux/serialP.h40
-rw-r--r--include/linux/serial_8250.h31
-rw-r--r--include/linux/serial_core.h17
-rw-r--r--include/linux/skbuff.h120
-rw-r--r--include/linux/slab.h19
-rw-r--r--include/linux/socket.h9
-rw-r--r--include/linux/sonypi.h2
-rw-r--r--include/linux/sound.h2
-rw-r--r--include/linux/spinlock.h627
-rw-r--r--include/linux/spinlock_api_smp.h57
-rw-r--r--include/linux/spinlock_api_up.h80
-rw-r--r--include/linux/spinlock_types.h67
-rw-r--r--include/linux/spinlock_types_up.h51
-rw-r--r--include/linux/spinlock_up.h74
-rw-r--r--include/linux/sunrpc/cache.h1
-rw-r--r--include/linux/swap.h22
-rw-r--r--include/linux/swapops.h2
-rw-r--r--include/linux/sysctl.h9
-rw-r--r--include/linux/tcp.h82
-rw-r--r--include/linux/tcp_diag.h127
-rw-r--r--include/linux/time.h10
-rw-r--r--include/linux/timer.h4
-rw-r--r--include/linux/timex.h23
-rw-r--r--include/linux/topology.h23
-rw-r--r--include/linux/transport_class.h11
-rw-r--r--include/linux/tty.h3
-rw-r--r--include/linux/types.h3
-rw-r--r--include/linux/usb.h11
-rw-r--r--include/linux/usb_isp116x.h30
-rw-r--r--include/linux/usbdevice_fs.h2
-rw-r--r--include/linux/videodev.h3
-rw-r--r--include/linux/videodev2.h113
-rw-r--r--include/linux/vmalloc.h8
-rw-r--r--include/linux/wireless.h38
-rw-r--r--include/linux/writeback.h2
-rw-r--r--include/linux/xfrm.h18
-rw-r--r--include/media/audiochip.h1
-rw-r--r--include/media/id.h6
-rw-r--r--include/media/ir-common.h4
-rw-r--r--include/media/saa7146.h13
-rw-r--r--include/media/tuner.h193
-rw-r--r--include/media/tveeprom.h9
-rw-r--r--include/media/video-buf.h1
-rw-r--r--include/net/act_api.h2
-rw-r--r--include/net/addrconf.h6
-rw-r--r--include/net/af_unix.h15
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/ax25.h37
-rw-r--r--include/net/bluetooth/bluetooth.h5
-rw-r--r--include/net/bluetooth/hci.h15
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--include/net/bluetooth/rfcomm.h14
-rw-r--r--include/net/compat.h5
-rw-r--r--include/net/datalink.h2
-rw-r--r--include/net/dn.h1
-rw-r--r--include/net/icmp.h7
-rw-r--r--include/net/ieee80211.h265
-rw-r--r--include/net/ieee80211_crypt.h86
-rw-r--r--include/net/inet6_hashtables.h130
-rw-r--r--include/net/inet_common.h6
-rw-r--r--include/net/inet_connection_sock.h276
-rw-r--r--include/net/inet_hashtables.h427
-rw-r--r--include/net/inet_timewait_sock.h219
-rw-r--r--include/net/ip.h32
-rw-r--r--include/net/ip6_route.h1
-rw-r--r--include/net/ip_fib.h5
-rw-r--r--include/net/ip_vs.h3
-rw-r--r--include/net/ipv6.h44
-rw-r--r--include/net/irda/irlan_filter.h2
-rw-r--r--include/net/iw_handler.h123
-rw-r--r--include/net/llc.h8
-rw-r--r--include/net/neighbour.h9
-rw-r--r--include/net/netrom.h32
-rw-r--r--include/net/p8022.h5
-rw-r--r--include/net/pkt_cls.h6
-rw-r--r--include/net/psnap.h2
-rw-r--r--include/net/raw.h9
-rw-r--r--include/net/rawv6.h5
-rw-r--r--include/net/request_sock.h14
-rw-r--r--include/net/route.h6
-rw-r--r--include/net/sctp/constants.h2
-rw-r--r--include/net/sock.h129
-rw-r--r--include/net/tcp.h724
-rw-r--r--include/net/tcp_ecn.h2
-rw-r--r--include/net/tcp_states.h34
-rw-r--r--include/net/transp_v6.h2
-rw-r--r--include/net/udp.h5
-rw-r--r--include/net/x25.h2
-rw-r--r--include/net/x25device.h1
-rw-r--r--include/net/xfrm.h1
-rw-r--r--include/pcmcia/ds.h2
-rw-r--r--include/rdma/ib_cache.h (renamed from drivers/infiniband/include/ib_cache.h)4
-rw-r--r--include/rdma/ib_cm.h (renamed from drivers/infiniband/include/ib_cm.h)94
-rw-r--r--include/rdma/ib_fmr_pool.h (renamed from drivers/infiniband/include/ib_fmr_pool.h)2
-rw-r--r--include/rdma/ib_mad.h (renamed from drivers/infiniband/include/ib_mad.h)47
-rw-r--r--include/rdma/ib_pack.h (renamed from drivers/infiniband/include/ib_pack.h)2
-rw-r--r--include/rdma/ib_sa.h (renamed from drivers/infiniband/include/ib_sa.h)53
-rw-r--r--include/rdma/ib_smi.h (renamed from drivers/infiniband/include/ib_smi.h)20
-rw-r--r--include/rdma/ib_user_cm.h (renamed from drivers/infiniband/include/ib_user_cm.h)100
-rw-r--r--include/rdma/ib_user_mad.h (renamed from drivers/infiniband/include/ib_user_mad.h)10
-rw-r--r--include/rdma/ib_user_verbs.h (renamed from drivers/infiniband/include/ib_user_verbs.h)60
-rw-r--r--include/rdma/ib_verbs.h (renamed from drivers/infiniband/include/ib_verbs.h)118
-rw-r--r--include/scsi/scsi_cmnd.h8
-rw-r--r--include/scsi/scsi_dbg.h2
-rw-r--r--include/scsi/scsi_device.h26
-rw-r--r--include/scsi/scsi_eh.h11
-rw-r--r--include/scsi/scsi_host.h26
-rw-r--r--include/scsi/scsi_request.h16
-rw-r--r--include/scsi/scsi_transport_fc.h8
-rw-r--r--include/scsi/scsi_transport_sas.h100
-rw-r--r--include/scsi/scsi_transport_spi.h6
-rw-r--r--include/sound/ac97_codec.h9
-rw-r--r--include/sound/ad1816a.h1
-rw-r--r--include/sound/asound.h6
-rw-r--r--include/sound/core.h10
-rw-r--r--include/sound/cs46xx.h16
-rw-r--r--include/sound/emu10k1.h9
-rw-r--r--include/sound/gus.h8
-rw-r--r--include/sound/pcm.h9
-rw-r--r--include/sound/pcm_oss.h3
-rw-r--r--include/sound/tea575x-tuner.h2
-rw-r--r--include/sound/trident.h17
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/ymfpci.h28
-rw-r--r--include/video/cyblafb.h171
-rw-r--r--include/video/pm3fb.h3
-rw-r--r--include/video/pmag-ba-fb.h41
-rw-r--r--include/video/pmagb-b-fb.h74
-rw-r--r--include/video/sisfb.h188
-rw-r--r--include/video/w100fb.h139
-rw-r--r--init/Kconfig22
-rw-r--r--init/Makefile3
-rw-r--r--init/do_mounts.c6
-rw-r--r--init/initramfs.c12
-rw-r--r--init/main.c41
-rw-r--r--ipc/compat.c12
-rw-r--r--ipc/mqueue.c2
-rw-r--r--ipc/msg.c82
-rw-r--r--ipc/sem.c73
-rw-r--r--ipc/shm.c86
-rw-r--r--ipc/util.c156
-rw-r--r--ipc/util.h8
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/acct.c45
-rw-r--r--kernel/audit.c3
-rw-r--r--kernel/compat.c9
-rw-r--r--kernel/cpuset.c226
-rw-r--r--kernel/exit.c26
-rw-r--r--kernel/fork.c104
-rw-r--r--kernel/futex.c137
-rw-r--r--kernel/intermodule.c3
-rw-r--r--kernel/irq/handle.c2
-rw-r--r--kernel/irq/manage.c4
-rw-r--r--kernel/irq/proc.c14
-rw-r--r--kernel/kprobes.c94
-rw-r--r--kernel/module.c44
-rw-r--r--kernel/params.c4
-rw-r--r--kernel/posix-timers.c28
-rw-r--r--kernel/power/Kconfig15
-rw-r--r--kernel/power/disk.c55
-rw-r--r--kernel/power/main.c5
-rw-r--r--kernel/power/pm.c3
-rw-r--r--kernel/power/process.c29
-rw-r--r--kernel/power/swsusp.c202
-rw-r--r--kernel/printk.c13
-rw-r--r--kernel/ptrace.c41
-rw-r--r--kernel/rcupdate.c14
-rw-r--r--kernel/resource.c3
-rw-r--r--kernel/sched.c617
-rw-r--r--kernel/signal.c86
-rw-r--r--kernel/softirq.c2
-rw-r--r--kernel/softlockup.c151
-rw-r--r--kernel/spinlock.c15
-rw-r--r--kernel/sys.c6
-rw-r--r--kernel/sysctl.c4
-rw-r--r--kernel/timer.c55
-rw-r--r--kernel/workqueue.c5
-rw-r--r--lib/Kconfig11
-rw-r--r--lib/Kconfig.debug27
-rw-r--r--lib/Makefile6
-rw-r--r--lib/crc16.c67
-rw-r--r--lib/dec_and_lock.c3
-rw-r--r--lib/kernel_lock.c3
-rw-r--r--lib/klist.c26
-rw-r--r--lib/kobject_uevent.c4
-rw-r--r--lib/radix-tree.c178
-rw-r--r--lib/semaphore-sleepers.c (renamed from arch/x86_64/kernel/semaphore.c)15
-rw-r--r--lib/sort.c5
-rw-r--r--lib/spinlock_debug.c257
-rw-r--r--lib/ts_bm.c185
-rw-r--r--mm/Kconfig22
-rw-r--r--mm/bootmem.c14
-rw-r--r--mm/filemap.c31
-rw-r--r--mm/hugetlb.c2
-rw-r--r--mm/madvise.c9
-rw-r--r--mm/memory.c20
-rw-r--r--mm/mempolicy.c21
-rw-r--r--mm/mmap.c9
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/nommu.c17
-rw-r--r--mm/oom_kill.c65
-rw-r--r--mm/page-writeback.c6
-rw-r--r--mm/page_alloc.c62
-rw-r--r--mm/readahead.c1
-rw-r--r--mm/rmap.c29
-rw-r--r--mm/shmem.c114
-rw-r--r--mm/slab.c1189
-rw-r--r--mm/sparse.c75
-rw-r--r--mm/swap_state.c10
-rw-r--r--mm/swapfile.c411
-rw-r--r--mm/vmalloc.c9
-rw-r--r--mm/vmscan.c24
-rw-r--r--net/802/fc.c2
-rw-r--r--net/802/fddi.c4
-rw-r--r--net/802/hippi.c6
-rw-r--r--net/802/p8022.c3
-rw-r--r--net/802/p8023.c1
-rw-r--r--net/802/psnap.c7
-rw-r--r--net/802/sysctl_net_802.c3
-rw-r--r--net/8021q/vlan.h2
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/Kconfig4
-rw-r--r--net/Makefile3
-rw-r--r--net/appletalk/aarp.c2
-rw-r--r--net/appletalk/ddp.c8
-rw-r--r--net/atm/ioctl.c1
-rw-r--r--net/atm/ipcommon.c3
-rw-r--r--net/atm/mpc.c2
-rw-r--r--net/ax25/af_ax25.c55
-rw-r--r--net/ax25/ax25_addr.c30
-rw-r--r--net/ax25/ax25_ds_in.c3
-rw-r--r--net/ax25/ax25_ds_timer.c2
-rw-r--r--net/ax25/ax25_in.c17
-rw-r--r--net/ax25/ax25_ip.c6
-rw-r--r--net/ax25/ax25_route.c7
-rw-r--r--net/ax25/ax25_std_in.c3
-rw-r--r--net/ax25/ax25_std_timer.c2
-rw-r--r--net/ax25/ax25_subr.c4
-rw-r--r--net/ax25/ax25_uid.c4
-rw-r--r--net/bluetooth/hci_core.c18
-rw-r--r--net/bluetooth/hci_event.c81
-rw-r--r--net/bluetooth/hci_sock.c26
-rw-r--r--net/bluetooth/l2cap.c2
-rw-r--r--net/bluetooth/rfcomm/core.c73
-rw-r--r--net/bluetooth/rfcomm/sock.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c206
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/bridge/netfilter/ebt_mark.c5
-rw-r--r--net/bridge/netfilter/ebt_ulog.c9
-rw-r--r--net/compat.c44
-rw-r--r--net/core/Makefile1
-rw-r--r--net/core/datagram.c6
-rw-r--r--net/core/dev.c79
-rw-r--r--net/core/dst.c3
-rw-r--r--net/core/ethtool.c49
-rw-r--r--net/core/filter.c6
-rw-r--r--net/core/flow.c2
-rw-r--r--net/core/neighbour.c15
-rw-r--r--net/core/netfilter.c648
-rw-r--r--net/core/netpoll.c4
-rw-r--r--net/core/pktgen.c15
-rw-r--r--net/core/request_sock.c28
-rw-r--r--net/core/rtnetlink.c9
-rw-r--r--net/core/skbuff.c158
-rw-r--r--net/core/sock.c142
-rw-r--r--net/core/sysctl_net_core.c9
-rw-r--r--net/core/utils.c2
-rw-r--r--net/core/wireless.c66
-rw-r--r--net/dccp/Kconfig50
-rw-r--r--net/dccp/Makefile10
-rw-r--r--net/dccp/ccid.c139
-rw-r--r--net/dccp/ccid.h180
-rw-r--r--net/dccp/ccids/Kconfig29
-rw-r--r--net/dccp/ccids/Makefile5
-rw-r--r--net/dccp/ccids/ccid3.c1214
-rw-r--r--net/dccp/ccids/ccid3.h143
-rw-r--r--net/dccp/ccids/lib/Makefile3
-rw-r--r--net/dccp/ccids/lib/loss_interval.c144
-rw-r--r--net/dccp/ccids/lib/loss_interval.h61
-rw-r--r--net/dccp/ccids/lib/packet_history.c398
-rw-r--r--net/dccp/ccids/lib/packet_history.h200
-rw-r--r--net/dccp/ccids/lib/tfrc.h22
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c644
-rw-r--r--net/dccp/dccp.h485
-rw-r--r--net/dccp/diag.c71
-rw-r--r--net/dccp/input.c600
-rw-r--r--net/dccp/ipv4.c1353
-rw-r--r--net/dccp/minisocks.c265
-rw-r--r--net/dccp/options.c887
-rw-r--r--net/dccp/output.c525
-rw-r--r--net/dccp/proto.c826
-rw-r--r--net/dccp/timer.c255
-rw-r--r--net/decnet/af_decnet.c46
-rw-r--r--net/decnet/dn_dev.c8
-rw-r--r--net/decnet/dn_nsp_in.c2
-rw-r--r--net/decnet/dn_nsp_out.c65
-rw-r--r--net/decnet/dn_route.c5
-rw-r--r--net/decnet/dn_table.c6
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c11
-rw-r--r--net/econet/af_econet.c8
-rw-r--r--net/ethernet/eth.c3
-rw-r--r--net/ethernet/sysctl_net_ether.c1
-rw-r--r--net/ieee80211/Kconfig68
-rw-r--r--net/ieee80211/Makefile11
-rw-r--r--net/ieee80211/ieee80211_crypt.c258
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c455
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c683
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c258
-rw-r--r--net/ieee80211/ieee80211_module.c297
-rw-r--r--net/ieee80211/ieee80211_rx.c1193
-rw-r--r--net/ieee80211/ieee80211_tx.c428
-rw-r--r--net/ieee80211/ieee80211_wx.c468
-rw-r--r--net/ipv4/Kconfig17
-rw-r--r--net/ipv4/Makefile8
-rw-r--r--net/ipv4/af_inet.c192
-rw-r--r--net/ipv4/ah4.c18
-rw-r--r--net/ipv4/arp.c8
-rw-r--r--net/ipv4/datagram.c3
-rw-r--r--net/ipv4/devinet.c7
-rw-r--r--net/ipv4/esp4.c36
-rw-r--r--net/ipv4/fib_frontend.c6
-rw-r--r--net/ipv4/fib_hash.c4
-rw-r--r--net/ipv4/fib_lookup.h1
-rw-r--r--net/ipv4/fib_semantics.c7
-rw-r--r--net/ipv4/fib_trie.c2028
-rw-r--r--net/ipv4/icmp.c14
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/inet_connection_sock.c641
-rw-r--r--net/ipv4/inet_diag.c868
-rw-r--r--net/ipv4/inet_hashtables.c165
-rw-r--r--net/ipv4/inet_timewait_sock.c384
-rw-r--r--net/ipv4/inetpeer.c8
-rw-r--r--net/ipv4/ip_forward.c6
-rw-r--r--net/ipv4/ip_fragment.c12
-rw-r--r--net/ipv4/ip_input.c141
-rw-r--r--net/ipv4/ip_options.c52
-rw-r--r--net/ipv4/ip_output.c24
-rw-r--r--net/ipv4/ip_sockglue.c8
-rw-r--r--net/ipv4/ipcomp.c7
-rw-r--r--net/ipv4/ipconfig.c15
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c1
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c9
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_lblc.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_lblcr.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c8
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c2
-rw-r--r--net/ipv4/multipath_drr.c2
-rw-r--r--net/ipv4/netfilter.c139
-rw-r--r--net/ipv4/netfilter/Kconfig90
-rw-r--r--net/ipv4/netfilter/Makefile10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c405
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c22
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c147
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c1584
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c73
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c9
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c49
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c14
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c49
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c1
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c104
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c24
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c23
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_unknown.c13
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c21
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c12
-rw-r--r--net/ipv4/netfilter/ip_queue.c51
-rw-r--r--net/ipv4/netfilter/ip_tables.c5
-rw-r--r--net/ipv4/netfilter/ipt_CLASSIFY.c4
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c4
-rw-r--r--net/ipv4/netfilter/ipt_CONNMARK.c15
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c3
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c6
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c86
-rw-r--r--net/ipv4/netfilter/ipt_MARK.c22
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c5
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c8
-rw-r--r--net/ipv4/netfilter/ipt_NFQUEUE.c70
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c6
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c119
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c53
-rw-r--r--net/ipv4/netfilter/ipt_connbytes.c162
-rw-r--r--net/ipv4/netfilter/ipt_connmark.c7
-rw-r--r--net/ipv4/netfilter/ipt_dccp.c176
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c2
-rw-r--r--net/ipv4/netfilter/ipt_mark.c7
-rw-r--r--net/ipv4/netfilter/ipt_owner.c133
-rw-r--r--net/ipv4/netfilter/ipt_string.c91
-rw-r--r--net/ipv4/proc.c5
-rw-r--r--net/ipv4/protocol.c1
-rw-r--r--net/ipv4/raw.c7
-rw-r--r--net/ipv4/route.c37
-rw-r--r--net/ipv4/syncookies.c4
-rw-r--r--net/ipv4/sysctl_net_ipv4.c47
-rw-r--r--net/ipv4/tcp.c419
-rw-r--r--net/ipv4/tcp_bic.c46
-rw-r--r--net/ipv4/tcp_cong.c44
-rw-r--r--net/ipv4/tcp_diag.c784
-rw-r--r--net/ipv4/tcp_highspeed.c17
-rw-r--r--net/ipv4/tcp_htcp.c53
-rw-r--r--net/ipv4/tcp_hybla.c31
-rw-r--r--net/ipv4/tcp_input.c549
-rw-r--r--net/ipv4/tcp_ipv4.c944
-rw-r--r--net/ipv4/tcp_minisocks.c605
-rw-r--r--net/ipv4/tcp_output.c201
-rw-r--r--net/ipv4/tcp_scalable.c6
-rw-r--r--net/ipv4/tcp_timer.c253
-rw-r--r--net/ipv4/tcp_vegas.c50
-rw-r--r--net/ipv4/tcp_westwood.c64
-rw-r--r--net/ipv4/udp.c39
-rw-r--r--net/ipv4/xfrm4_state.c2
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/addrconf.c41
-rw-r--r--net/ipv6/af_inet6.c62
-rw-r--r--net/ipv6/ah6.c31
-rw-r--r--net/ipv6/datagram.c144
-rw-r--r--net/ipv6/esp6.c27
-rw-r--r--net/ipv6/exthdrs.c127
-rw-r--r--net/ipv6/icmp.c45
-rw-r--r--net/ipv6/inet6_hashtables.c81
-rw-r--r--net/ipv6/ip6_fib.c4
-rw-r--r--net/ipv6/ip6_flowlabel.c16
-rw-r--r--net/ipv6/ip6_input.c6
-rw-r--r--net/ipv6/ip6_output.c78
-rw-r--r--net/ipv6/ip6_tunnel.c7
-rw-r--r--net/ipv6/ipcomp6.c3
-rw-r--r--net/ipv6/ipv6_sockglue.c211
-rw-r--r--net/ipv6/ipv6_syms.c3
-rw-r--r--net/ipv6/ndisc.c20
-rw-r--r--net/ipv6/netfilter.c104
-rw-r--r--net/ipv6/netfilter/Kconfig37
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c48
-rw-r--r--net/ipv6/netfilter/ip6_tables.c5
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c118
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c93
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c5
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c281
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c91
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c14
-rw-r--r--net/ipv6/raw.c41
-rw-r--r--net/ipv6/reassembly.c13
-rw-r--r--net/ipv6/route.c14
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/sysctl_net_ipv6.c3
-rw-r--r--net/ipv6/tcp_ipv6.c473
-rw-r--r--net/ipv6/udp.c37
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/ipx/af_ipx.c10
-rw-r--r--net/ipx/ipx_proc.c2
-rw-r--r--net/irda/af_irda.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c9
-rw-r--r--net/irda/irlan/irlan_filter.c1
-rw-r--r--net/irda/irlap_frame.c8
-rw-r--r--net/irda/irlmp.c3
-rw-r--r--net/irda/irmod.c2
-rw-r--r--net/irda/irnet/irnet.h3
-rw-r--r--net/irda/irnet/irnet_ppp.c2
-rw-r--r--net/irda/irqueue.c1
-rw-r--r--net/irda/qos.c1
-rw-r--r--net/lapb/lapb_subr.c2
-rw-r--r--net/llc/af_llc.c4
-rw-r--r--net/llc/llc_conn.c8
-rw-r--r--net/llc/llc_core.c3
-rw-r--r--net/llc/llc_if.c2
-rw-r--r--net/llc/llc_input.c4
-rw-r--r--net/llc/llc_sap.c2
-rw-r--r--net/netfilter/Kconfig24
-rw-r--r--net/netfilter/Makefile7
-rw-r--r--net/netfilter/core.c216
-rw-r--r--net/netfilter/nf_internals.h39
-rw-r--r--net/netfilter/nf_log.c178
-rw-r--r--net/netfilter/nf_queue.c343
-rw-r--r--net/netfilter/nf_sockopt.c132
-rw-r--r--net/netfilter/nfnetlink.c376
-rw-r--r--net/netfilter/nfnetlink_log.c1055
-rw-r--r--net/netfilter/nfnetlink_queue.c1127
-rw-r--r--net/netlink/af_netlink.c339
-rw-r--r--net/netrom/af_netrom.c42
-rw-r--r--net/netrom/nr_dev.c59
-rw-r--r--net/netrom/nr_in.c18
-rw-r--r--net/netrom/nr_loopback.c2
-rw-r--r--net/netrom/nr_route.c8
-rw-r--r--net/netrom/nr_subr.c11
-rw-r--r--net/netrom/nr_timer.c2
-rw-r--r--net/netrom/sysctl_net_netrom.c12
-rw-r--r--net/packet/af_packet.c20
-rw-r--r--net/rose/af_rose.c16
-rw-r--r--net/rose/rose_dev.c2
-rw-r--r--net/rose/rose_in.c3
-rw-r--r--net/rose/rose_route.c16
-rw-r--r--net/rose/rose_subr.c13
-rw-r--r--net/rose/rose_timer.c2
-rw-r--r--net/rxrpc/transport.c2
-rw-r--r--net/sched/Kconfig1
-rw-r--r--net/sched/act_api.c15
-rw-r--r--net/sched/cls_api.c2
-rw-r--r--net/sched/gact.c2
-rw-r--r--net/sched/ipt.c2
-rw-r--r--net/sched/mirred.c2
-rw-r--r--net/sched/pedit.c2
-rw-r--r--net/sched/police.c3
-rw-r--r--net/sched/sch_api.c6
-rw-r--r--net/sched/sch_generic.c16
-rw-r--r--net/sched/simple.c2
-rw-r--r--net/sctp/endpointola.c3
-rw-r--r--net/sctp/input.c4
-rw-r--r--net/sctp/ipv6.c7
-rw-r--r--net/sctp/protocol.c14
-rw-r--r--net/sctp/sm_make_chunk.c9
-rw-r--r--net/sctp/socket.c7
-rw-r--r--net/sctp/sysctl.c1
-rw-r--r--net/sctp/ulpqueue.c63
-rw-r--r--net/socket.c44
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c5
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c9
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c12
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c8
-rw-r--r--net/sunrpc/cache.c8
-rw-r--r--net/sunrpc/rpc_pipe.c6
-rw-r--r--net/sunrpc/sched.c8
-rw-r--r--net/sunrpc/stats.c16
-rw-r--r--net/sunrpc/sunrpc_syms.c6
-rw-r--r--net/sunrpc/svcauth.c1
-rw-r--r--net/sunrpc/svcauth_unix.c1
-rw-r--r--net/sunrpc/svcsock.c99
-rw-r--r--net/sysctl_net.c8
-rw-r--r--net/unix/af_unix.c10
-rw-r--r--net/unix/garbage.c14
-rw-r--r--net/unix/sysctl_net_unix.c2
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/x25/af_x25.c2
-rw-r--r--net/x25/x25_dev.c2
-rw-r--r--net/x25/x25_in.c2
-rw-r--r--net/x25/x25_subr.c4
-rw-r--r--net/x25/x25_timer.c2
-rw-r--r--net/xfrm/xfrm_input.c2
-rw-r--r--net/xfrm/xfrm_policy.c10
-rw-r--r--net/xfrm/xfrm_user.c31
-rw-r--r--scripts/Kbuild.include99
-rw-r--r--scripts/Makefile.build7
-rw-r--r--scripts/Makefile.clean14
-rw-r--r--scripts/Makefile.host3
-rw-r--r--scripts/Makefile.lib99
-rw-r--r--scripts/Makefile.modinst2
-rw-r--r--scripts/Makefile.modpost1
-rw-r--r--scripts/conmakehash.c2
-rw-r--r--scripts/kallsyms.c433
-rw-r--r--scripts/kconfig/Makefile16
-rw-r--r--scripts/kconfig/kxgettext.c16
-rw-r--r--scripts/kconfig/lkc.h2
-rw-r--r--scripts/kconfig/menu.c4
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped8
-rw-r--r--scripts/kconfig/zconf.y8
-rwxr-xr-xscripts/kernel-doc8
-rw-r--r--scripts/lxdialog/dialog.h2
-rw-r--r--scripts/lxdialog/inputbox.c4
-rwxr-xr-xscripts/mkcompile_h12
-rw-r--r--scripts/mod/file2alias.c19
-rw-r--r--scripts/mod/modpost.c6
-rw-r--r--scripts/mod/sumversion.c8
-rw-r--r--scripts/package/Makefile24
-rw-r--r--scripts/package/builddeb56
-rw-r--r--scripts/package/buildtar111
-rwxr-xr-xscripts/package/mkspec9
-rw-r--r--scripts/reference_discarded.pl6
-rw-r--r--scripts/reference_init.pl1
-rw-r--r--scripts/setlocalversion56
-rwxr-xr-xscripts/ver_linux6
-rw-r--r--security/dummy.c52
-rw-r--r--security/seclvl.c2
-rw-r--r--security/selinux/avc.c4
-rw-r--r--security/selinux/hooks.c180
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/netlink.c6
-rw-r--r--security/selinux/nlmsgtab.c3
-rw-r--r--security/selinux/ss/avtab.c196
-rw-r--r--security/selinux/ss/avtab.h37
-rw-r--r--security/selinux/ss/conditional.c215
-rw-r--r--security/selinux/ss/ebitmap.c5
-rw-r--r--security/selinux/ss/ebitmap.h30
-rw-r--r--security/selinux/ss/mls.c42
-rw-r--r--security/selinux/ss/policydb.c107
-rw-r--r--security/selinux/ss/policydb.h3
-rw-r--r--security/selinux/ss/services.c76
-rw-r--r--sound/arm/Kconfig1
-rw-r--r--sound/arm/Makefile16
-rw-r--r--sound/arm/aaci.c6
-rw-r--r--sound/arm/aaci.h6
-rw-r--r--sound/arm/pxa2xx-ac97.c12
-rw-r--r--sound/arm/sa11xx-uda1341.c7
-rw-r--r--sound/core/Kconfig14
-rw-r--r--sound/core/control.c12
-rw-r--r--sound/core/control_compat.c8
-rw-r--r--sound/core/device.c2
-rw-r--r--sound/core/hwdep.c2
-rw-r--r--sound/core/info.c8
-rw-r--r--sound/core/init.c187
-rw-r--r--sound/core/memalloc.c8
-rw-r--r--sound/core/memory.c20
-rw-r--r--sound/core/oss/mixer_oss.c26
-rw-r--r--sound/core/oss/pcm_oss.c28
-rw-r--r--sound/core/oss/pcm_plugin.c2
-rw-r--r--sound/core/pcm.c6
-rw-r--r--sound/core/pcm_compat.c49
-rw-r--r--sound/core/pcm_lib.c137
-rw-r--r--sound/core/pcm_memory.c4
-rw-r--r--sound/core/pcm_native.c25
-rw-r--r--sound/core/rawmidi.c16
-rw-r--r--sound/core/seq/instr/ainstr_gf1.c2
-rw-r--r--sound/core/seq/instr/ainstr_iw.c6
-rw-r--r--sound/core/seq/oss/seq_oss_init.c2
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c6
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c2
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c4
-rw-r--r--sound/core/seq/oss/seq_oss_timer.c2
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c2
-rw-r--r--sound/core/seq/seq.c8
-rw-r--r--sound/core/seq/seq_clientmgr.c9
-rw-r--r--sound/core/seq/seq_device.c2
-rw-r--r--sound/core/seq/seq_dummy.c2
-rw-r--r--sound/core/seq/seq_fifo.c2
-rw-r--r--sound/core/seq/seq_instr.c4
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/seq/seq_midi.c2
-rw-r--r--sound/core/seq/seq_midi_event.c2
-rw-r--r--sound/core/seq/seq_ports.c4
-rw-r--r--sound/core/seq/seq_prioq.c2
-rw-r--r--sound/core/seq/seq_queue.c2
-rw-r--r--sound/core/seq/seq_system.c4
-rw-r--r--sound/core/seq/seq_timer.c2
-rw-r--r--sound/core/seq/seq_virmidi.c6
-rw-r--r--sound/core/sound.c15
-rw-r--r--sound/core/sound_oss.c7
-rw-r--r--sound/core/timer.c26
-rw-r--r--sound/drivers/Kconfig5
-rw-r--r--sound/drivers/dummy.c8
-rw-r--r--sound/drivers/mpu401/mpu401.c26
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c2
-rw-r--r--sound/drivers/mtpav.c5
-rw-r--r--sound/drivers/opl3/opl3_lib.c2
-rw-r--r--sound/drivers/opl3/opl3_oss.c2
-rw-r--r--sound/drivers/opl4/opl4_lib.c2
-rw-r--r--sound/drivers/serial-u16550.c28
-rw-r--r--sound/drivers/virmidi.c4
-rw-r--r--sound/drivers/vx/vx_core.c2
-rw-r--r--sound/drivers/vx/vx_mixer.c4
-rw-r--r--sound/drivers/vx/vx_pcm.c10
-rw-r--r--sound/i2c/cs8427.c2
-rw-r--r--sound/i2c/i2c.c4
-rw-r--r--sound/i2c/l3/uda1341.c6
-rw-r--r--sound/i2c/other/ak4114.c2
-rw-r--r--sound/i2c/other/ak4117.c2
-rw-r--r--sound/i2c/tea6330t.c2
-rw-r--r--sound/isa/Kconfig37
-rw-r--r--sound/isa/ad1816a/ad1816a.c5
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c16
-rw-r--r--sound/isa/ad1848/ad1848.c37
-rw-r--r--sound/isa/ad1848/ad1848_lib.c3
-rw-r--r--sound/isa/cmi8330.c81
-rw-r--r--sound/isa/cs423x/cs4231.c46
-rw-r--r--sound/isa/cs423x/cs4231_lib.c4
-rw-r--r--sound/isa/cs423x/cs4236.c97
-rw-r--r--sound/isa/es1688/es1688.c61
-rw-r--r--sound/isa/es1688/es1688_lib.c2
-rw-r--r--sound/isa/es18xx.c83
-rw-r--r--sound/isa/gus/gus_io.c6
-rw-r--r--sound/isa/gus/gus_main.c2
-rw-r--r--sound/isa/gus/gus_mem_proc.c4
-rw-r--r--sound/isa/gus/gus_pcm.c2
-rw-r--r--sound/isa/gus/gusclassic.c115
-rw-r--r--sound/isa/gus/gusextreme.c49
-rw-r--r--sound/isa/gus/gusmax.c145
-rw-r--r--sound/isa/gus/interwave.c167
-rw-r--r--sound/isa/opl3sa2.c148
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c13
-rw-r--r--sound/isa/sb/emu8000.c2
-rw-r--r--sound/isa/sb/emu8000_pcm.c2
-rw-r--r--sound/isa/sb/sb16.c144
-rw-r--r--sound/isa/sb/sb16_csp.c46
-rw-r--r--sound/isa/sb/sb16_main.c2
-rw-r--r--sound/isa/sb/sb8.c62
-rw-r--r--sound/isa/sb/sb_common.c2
-rw-r--r--sound/isa/sgalaxy.c65
-rw-r--r--sound/isa/sscape.c22
-rw-r--r--sound/isa/wavefront/wavefront.c5
-rw-r--r--sound/mips/Kconfig1
-rw-r--r--sound/mips/au1x00.c5
-rw-r--r--sound/oss/midibuf.c2
-rw-r--r--sound/oss/os.h3
-rw-r--r--sound/oss/skeleton.c219
-rw-r--r--sound/oss/soundcard.c3
-rw-r--r--sound/oss/sys_timer.c3
-rw-r--r--sound/oss/uart6850.c3
-rw-r--r--sound/parisc/harmony.c2
-rw-r--r--sound/pci/Kconfig22
-rw-r--r--sound/pci/Makefile2
-rw-r--r--sound/pci/ac97/Makefile2
-rw-r--r--sound/pci/ac97/ac97_bus.c79
-rw-r--r--sound/pci/ac97/ac97_codec.c90
-rw-r--r--sound/pci/ac97/ac97_id.h1
-rw-r--r--sound/pci/ac97/ac97_patch.c473
-rw-r--r--sound/pci/ac97/ac97_patch.h1
-rw-r--r--sound/pci/ac97/ak4531_codec.c2
-rw-r--r--sound/pci/ad1889.c1090
-rw-r--r--sound/pci/ad1889.h189
-rw-r--r--sound/pci/ali5451/ali5451.c35
-rw-r--r--sound/pci/als4000.c1
-rw-r--r--sound/pci/atiixp.c18
-rw-r--r--sound/pci/atiixp_modem.c3
-rw-r--r--sound/pci/au88x0/au88x0.c29
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c10
-rw-r--r--sound/pci/azt3328.c3
-rw-r--r--sound/pci/bt87x.c13
-rw-r--r--sound/pci/ca0106/ca0106_main.c15
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c22
-rw-r--r--sound/pci/cmipci.c31
-rw-r--r--sound/pci/cs4281.c14
-rw-r--r--sound/pci/cs46xx/cs46xx.c3
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c46
-rw-r--r--sound/pci/emu10k1/emu10k1.c3
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c13
-rw-r--r--sound/pci/emu10k1/emu10k1x.c11
-rw-r--r--sound/pci/emu10k1/emufx.c46
-rw-r--r--sound/pci/emu10k1/emumixer.c23
-rw-r--r--sound/pci/emu10k1/emupcm.c17
-rw-r--r--sound/pci/emu10k1/p16v.c4
-rw-r--r--sound/pci/ens1370.c12
-rw-r--r--sound/pci/es1938.c10
-rw-r--r--sound/pci/es1968.c26
-rw-r--r--sound/pci/fm801.c11
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c103
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_generic.c9
-rw-r--r--sound/pci/hda/hda_intel.c248
-rw-r--r--sound/pci/hda/hda_patch.h3
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_analog.c10
-rw-r--r--sound/pci/hda/patch_cmedia.c3
-rw-r--r--sound/pci/hda/patch_realtek.c17
-rw-r--r--sound/pci/hda/patch_si3054.c301
-rw-r--r--sound/pci/hda/patch_sigmatel.c4
-rw-r--r--sound/pci/ice1712/aureon.c2
-rw-r--r--sound/pci/ice1712/delta.c10
-rw-r--r--sound/pci/ice1712/ice1712.c19
-rw-r--r--sound/pci/ice1712/ice1724.c15
-rw-r--r--sound/pci/ice1712/juli.c2
-rw-r--r--sound/pci/ice1712/phase.c4
-rw-r--r--sound/pci/ice1712/pontis.c2
-rw-r--r--sound/pci/intel8x0.c148
-rw-r--r--sound/pci/intel8x0m.c64
-rw-r--r--sound/pci/korg1212/korg1212.c7
-rw-r--r--sound/pci/maestro3.c32
-rw-r--r--sound/pci/mixart/mixart.c5
-rw-r--r--sound/pci/nm256/nm256.c113
-rw-r--r--sound/pci/rme32.c25
-rw-r--r--sound/pci/rme96.c30
-rw-r--r--sound/pci/rme9652/hdsp.c64
-rw-r--r--sound/pci/rme9652/hdspm.c46
-rw-r--r--sound/pci/rme9652/rme9652.c32
-rw-r--r--sound/pci/sonicvibes.c10
-rw-r--r--sound/pci/trident/trident.c1
-rw-r--r--sound/pci/trident/trident_main.c14
-rw-r--r--sound/pci/via82xx.c31
-rw-r--r--sound/pci/via82xx_modem.c6
-rw-r--r--sound/pci/vx222/vx222.c1
-rw-r--r--sound/pci/ymfpci/ymfpci.c1
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c238
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.c12
-rw-r--r--sound/ppc/Kconfig15
-rw-r--r--sound/ppc/pmac.c3
-rw-r--r--sound/ppc/powermac.c3
-rw-r--r--sound/ppc/tumbler.c23
-rw-r--r--sound/sound_core.c27
-rw-r--r--sound/sparc/Kconfig3
-rw-r--r--sound/sparc/amd7930.c5
-rw-r--r--sound/sparc/cs4231.c7
-rw-r--r--sound/sparc/dbri.c234
-rw-r--r--sound/synth/emux/emux.c2
-rw-r--r--sound/synth/emux/emux_seq.c2
-rw-r--r--sound/synth/emux/emux_synth.c1
-rw-r--r--sound/synth/emux/soundfont.c8
-rw-r--r--sound/synth/util_mem.c2
-rw-r--r--sound/usb/usbaudio.c348
-rw-r--r--sound/usb/usbmidi.c117
-rw-r--r--sound/usb/usbmixer.c10
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c2
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
-rw-r--r--usr/Kconfig46
-rw-r--r--usr/Makefile2
4622 files changed, 282324 insertions, 156136 deletions
diff --git a/COPYING b/COPYING
index 2a7e338ec2fc..ca442d313d86 100644
--- a/COPYING
+++ b/COPYING
@@ -18,7 +18,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -321,7 +321,7 @@ the "copyright" line and a pointer to where the full notice is found.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index f28a24e0279b..433cf5e9ae04 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -46,6 +46,8 @@ SubmittingPatches
- procedure to get a source patch included into the kernel tree.
VGA-softcursor.txt
- how to change your VGA cursor from a blinking underscore.
+applying-patches.txt
+ - description of various trees and how to apply their patches.
arm/
- directory with info about Linux on the ARM architecture.
basic_profiling.txt
@@ -275,7 +277,7 @@ tty.txt
unicode.txt
- info on the Unicode character/font mapping used in Linux.
uml/
- - directory with infomation about User Mode Linux.
+ - directory with information about User Mode Linux.
usb/
- directory with info regarding the Universal Serial Bus.
video4linux/
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index f25b3953f513..22e5f9036f3c 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -236,6 +236,9 @@ ugly), but try to avoid excess. Instead, put the comments at the head
of the function, telling people what it does, and possibly WHY it does
it.
+When commenting the kernel API functions, please use the kerneldoc format.
+See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
+for details.
Chapter 8: You've made a mess of it
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 6ee3cd6134df..1af0f2d50220 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -121,7 +121,7 @@ pool's device.
dma_addr_t addr);
This puts memory back into the pool. The pool is what was passed to
-the the pool allocation routine; the cpu and dma addresses are what
+the pool allocation routine; the cpu and dma addresses are what
were returned when that routine allocated the memory being freed.
diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt
new file mode 100644
index 000000000000..705f6be92bdb
--- /dev/null
+++ b/Documentation/DMA-ISA-LPC.txt
@@ -0,0 +1,151 @@
+ DMA with ISA and LPC devices
+ ============================
+
+ Pierre Ossman <drzeus@drzeus.cx>
+
+This document describes how to do DMA transfers using the old ISA DMA
+controller. Even though ISA is more or less dead today the LPC bus
+uses the same DMA system so it will be around for quite some time.
+
+Part I - Headers and dependencies
+---------------------------------
+
+To do ISA style DMA you need to include two headers:
+
+#include <linux/dma-mapping.h>
+#include <asm/dma.h>
+
+The first is the generic DMA API used to convert virtual addresses to
+physical addresses (see Documentation/DMA-API.txt for details).
+
+The second contains the routines specific to ISA DMA transfers. Since
+this is not present on all platforms make sure you construct your
+Kconfig to be dependent on ISA_DMA_API (not ISA) so that nobody tries
+to build your driver on unsupported platforms.
+
+Part II - Buffer allocation
+---------------------------
+
+The ISA DMA controller has some very strict requirements on which
+memory it can access so extra care must be taken when allocating
+buffers.
+
+(You usually need a special buffer for DMA transfers instead of
+transferring directly to and from your normal data structures.)
+
+The DMA-able address space is the lowest 16 MB of _physical_ memory.
+Also the transfer block may not cross page boundaries (which are 64
+or 128 KiB depending on which channel you use).
+
+In order to allocate a piece of memory that satisfies all these
+requirements you pass the flag GFP_DMA to kmalloc.
+
+Unfortunately the memory available for ISA DMA is scarce so unless you
+allocate the memory during boot-up it's a good idea to also pass
+__GFP_REPEAT and __GFP_NOWARN to make the allocater try a bit harder.
+
+(This scarcity also means that you should allocate the buffer as
+early as possible and not release it until the driver is unloaded.)
+
+Part III - Address translation
+------------------------------
+
+To translate the virtual address to a physical use the normal DMA
+API. Do _not_ use isa_virt_to_phys() even though it does the same
+thing. The reason for this is that the function isa_virt_to_phys()
+will require a Kconfig dependency to ISA, not just ISA_DMA_API which
+is really all you need. Remember that even though the DMA controller
+has its origins in ISA it is used elsewhere.
+
+Note: x86_64 had a broken DMA API when it came to ISA but has since
+been fixed. If your arch has problems then fix the DMA API instead of
+reverting to the ISA functions.
+
+Part IV - Channels
+------------------
+
+A normal ISA DMA controller has 8 channels. The lower four are for
+8-bit transfers and the upper four are for 16-bit transfers.
+
+(Actually the DMA controller is really two separate controllers where
+channel 4 is used to give DMA access for the second controller (0-3).
+This means that of the four 16-bits channels only three are usable.)
+
+You allocate these in a similar fashion as all basic resources:
+
+extern int request_dma(unsigned int dmanr, const char * device_id);
+extern void free_dma(unsigned int dmanr);
+
+The ability to use 16-bit or 8-bit transfers is _not_ up to you as a
+driver author but depends on what the hardware supports. Check your
+specs or test different channels.
+
+Part V - Transfer data
+----------------------
+
+Now for the good stuff, the actual DMA transfer. :)
+
+Before you use any ISA DMA routines you need to claim the DMA lock
+using claim_dma_lock(). The reason is that some DMA operations are
+not atomic so only one driver may fiddle with the registers at a
+time.
+
+The first time you use the DMA controller you should call
+clear_dma_ff(). This clears an internal register in the DMA
+controller that is used for the non-atomic operations. As long as you
+(and everyone else) uses the locking functions then you only need to
+reset this once.
+
+Next, you tell the controller in which direction you intend to do the
+transfer using set_dma_mode(). Currently you have the options
+DMA_MODE_READ and DMA_MODE_WRITE.
+
+Set the address from where the transfer should start (this needs to
+be 16-bit aligned for 16-bit transfers) and how many bytes to
+transfer. Note that it's _bytes_. The DMA routines will do all the
+required translation to values that the DMA controller understands.
+
+The final step is enabling the DMA channel and releasing the DMA
+lock.
+
+Once the DMA transfer is finished (or timed out) you should disable
+the channel again. You should also check get_dma_residue() to make
+sure that all data has been transfered.
+
+Example:
+
+int flags, residue;
+
+flags = claim_dma_lock();
+
+clear_dma_ff();
+
+set_dma_mode(channel, DMA_MODE_WRITE);
+set_dma_addr(channel, phys_addr);
+set_dma_count(channel, num_bytes);
+
+dma_enable(channel);
+
+release_dma_lock(flags);
+
+while (!device_done());
+
+flags = claim_dma_lock();
+
+dma_disable(channel);
+
+residue = dma_get_residue(channel);
+if (residue != 0)
+ printk(KERN_ERR "driver: Incomplete DMA transfer!"
+ " %d bytes left!\n", residue);
+
+release_dma_lock(flags);
+
+Part VI - Suspend/resume
+------------------------
+
+It is the driver's responsibility to make sure that the machine isn't
+suspended while a DMA transfer is in progress. Also, all DMA settings
+are lost when the system suspends so if your driver relies on the DMA
+controller being in a certain state then you have to restore these
+registers upon resume.
diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
index 1ef6f43c6d8f..341aaa4ce481 100644
--- a/Documentation/DocBook/journal-api.tmpl
+++ b/Documentation/DocBook/journal-api.tmpl
@@ -116,7 +116,7 @@ filesystem. Almost.
You still need to actually journal your filesystem changes, this
is done by wrapping them into transactions. Additionally you
-also need to wrap the modification of each of the the buffers
+also need to wrap the modification of each of the buffers
with calls to the journal layer, so it knows what the modifications
you are actually making are. To do this use journal_start() which
returns a transaction handle.
@@ -128,7 +128,7 @@ and its counterpart journal_stop(), which indicates the end of a transaction
are nestable calls, so you can reenter a transaction if necessary,
but remember you must call journal_stop() the same number of times as
journal_start() before the transaction is completed (or more accurately
-leaves the the update phase). Ext3/VFS makes use of this feature to simplify
+leaves the update phase). Ext3/VFS makes use of this feature to simplify
quota support.
</para>
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 49a9ef82d575..6367bba32d22 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -8,8 +8,7 @@
<authorgroup>
<author>
- <firstname>Paul</firstname>
- <othername>Rusty</othername>
+ <firstname>Rusty</firstname>
<surname>Russell</surname>
<affiliation>
<address>
@@ -20,7 +19,7 @@
</authorgroup>
<copyright>
- <year>2001</year>
+ <year>2005</year>
<holder>Rusty Russell</holder>
</copyright>
@@ -64,7 +63,7 @@
<chapter id="introduction">
<title>Introduction</title>
<para>
- Welcome, gentle reader, to Rusty's Unreliable Guide to Linux
+ Welcome, gentle reader, to Rusty's Remarkably Unreliable Guide to Linux
Kernel Hacking. This document describes the common routines and
general requirements for kernel code: its goal is to serve as a
primer for Linux kernel development for experienced C
@@ -96,13 +95,13 @@
<listitem>
<para>
- not associated with any process, serving a softirq, tasklet or bh;
+ not associated with any process, serving a softirq or tasklet;
</para>
</listitem>
<listitem>
<para>
- running in kernel space, associated with a process;
+ running in kernel space, associated with a process (user context);
</para>
</listitem>
@@ -114,11 +113,12 @@
</itemizedlist>
<para>
- There is a strict ordering between these: other than the last
- category (userspace) each can only be pre-empted by those above.
- For example, while a softirq is running on a CPU, no other
- softirq will pre-empt it, but a hardware interrupt can. However,
- any other CPUs in the system execute independently.
+ There is an ordering between these. The bottom two can preempt
+ each other, but above that is a strict hierarchy: each can only be
+ preempted by the ones above it. For example, while a softirq is
+ running on a CPU, no other softirq will preempt it, but a hardware
+ interrupt can. However, any other CPUs in the system execute
+ independently.
</para>
<para>
@@ -130,10 +130,10 @@
<title>User Context</title>
<para>
- User context is when you are coming in from a system call or
- other trap: you can sleep, and you own the CPU (except for
- interrupts) until you call <function>schedule()</function>.
- In other words, user context (unlike userspace) is not pre-emptable.
+ User context is when you are coming in from a system call or other
+ trap: like userspace, you can be preempted by more important tasks
+ and by interrupts. You can sleep, by calling
+ <function>schedule()</function>.
</para>
<note>
@@ -153,7 +153,7 @@
<caution>
<para>
- Beware that if you have interrupts or bottom halves disabled
+ Beware that if you have preemption or softirqs disabled
(see below), <function>in_interrupt()</function> will return a
false positive.
</para>
@@ -168,10 +168,10 @@
<hardware>keyboard</hardware> are examples of real
hardware which produce interrupts at any time. The kernel runs
interrupt handlers, which services the hardware. The kernel
- guarantees that this handler is never re-entered: if another
+ guarantees that this handler is never re-entered: if the same
interrupt arrives, it is queued (or dropped). Because it
disables interrupts, this handler has to be fast: frequently it
- simply acknowledges the interrupt, marks a `software interrupt'
+ simply acknowledges the interrupt, marks a 'software interrupt'
for execution and exits.
</para>
@@ -188,60 +188,52 @@
</sect1>
<sect1 id="basics-softirqs">
- <title>Software Interrupt Context: Bottom Halves, Tasklets, softirqs</title>
+ <title>Software Interrupt Context: Softirqs and Tasklets</title>
<para>
Whenever a system call is about to return to userspace, or a
- hardware interrupt handler exits, any `software interrupts'
+ hardware interrupt handler exits, any 'software interrupts'
which are marked pending (usually by hardware interrupts) are
run (<filename>kernel/softirq.c</filename>).
</para>
<para>
Much of the real interrupt handling work is done here. Early in
- the transition to <acronym>SMP</acronym>, there were only `bottom
+ the transition to <acronym>SMP</acronym>, there were only 'bottom
halves' (BHs), which didn't take advantage of multiple CPUs. Shortly
after we switched from wind-up computers made of match-sticks and snot,
- we abandoned this limitation.
+ we abandoned this limitation and switched to 'softirqs'.
</para>
<para>
<filename class="headerfile">include/linux/interrupt.h</filename> lists the
- different BH's. No matter how many CPUs you have, no two BHs will run at
- the same time. This made the transition to SMP simpler, but sucks hard for
- scalable performance. A very important bottom half is the timer
- BH (<filename class="headerfile">include/linux/timer.h</filename>): you
- can register to have it call functions for you in a given length of time.
+ different softirqs. A very important softirq is the
+ timer softirq (<filename
+ class="headerfile">include/linux/timer.h</filename>): you can
+ register to have it call functions for you in a given length of
+ time.
</para>
<para>
- 2.3.43 introduced softirqs, and re-implemented the (now
- deprecated) BHs underneath them. Softirqs are fully-SMP
- versions of BHs: they can run on as many CPUs at once as
- required. This means they need to deal with any races in shared
- data using their own locks. A bitmask is used to keep track of
- which are enabled, so the 32 available softirqs should not be
- used up lightly. (<emphasis>Yes</emphasis>, people will
- notice).
- </para>
-
- <para>
- tasklets (<filename class="headerfile">include/linux/interrupt.h</filename>)
- are like softirqs, except they are dynamically-registrable (meaning you
- can have as many as you want), and they also guarantee that any tasklet
- will only run on one CPU at any time, although different tasklets can
- run simultaneously (unlike different BHs).
+ Softirqs are often a pain to deal with, since the same softirq
+ will run simultaneously on more than one CPU. For this reason,
+ tasklets (<filename
+ class="headerfile">include/linux/interrupt.h</filename>) are more
+ often used: they are dynamically-registrable (meaning you can have
+ as many as you want), and they also guarantee that any tasklet
+ will only run on one CPU at any time, although different tasklets
+ can run simultaneously.
</para>
<caution>
<para>
- The name `tasklet' is misleading: they have nothing to do with `tasks',
+ The name 'tasklet' is misleading: they have nothing to do with 'tasks',
and probably more to do with some bad vodka Alexey Kuznetsov had at the
time.
</para>
</caution>
<para>
- You can tell you are in a softirq (or bottom half, or tasklet)
+ You can tell you are in a softirq (or tasklet)
using the <function>in_softirq()</function> macro
(<filename class="headerfile">include/linux/interrupt.h</filename>).
</para>
@@ -288,11 +280,10 @@
<term>A rigid stack limit</term>
<listitem>
<para>
- The kernel stack is about 6K in 2.2 (for most
- architectures: it's about 14K on the Alpha), and shared
- with interrupts so you can't use it all. Avoid deep
- recursion and huge local arrays on the stack (allocate
- them dynamically instead).
+ Depending on configuration options the kernel stack is about 3K to 6K for most 32-bit architectures: it's
+ about 14K on most 64-bit archs, and often shared with interrupts
+ so you can't use it all. Avoid deep recursion and huge local
+ arrays on the stack (allocate them dynamically instead).
</para>
</listitem>
</varlistentry>
@@ -339,7 +330,7 @@ asmlinkage long sys_mycall(int arg)
<para>
If all your routine does is read or write some parameter, consider
- implementing a <function>sysctl</function> interface instead.
+ implementing a <function>sysfs</function> interface instead.
</para>
<para>
@@ -417,7 +408,10 @@ cond_resched(); /* Will sleep */
</para>
<para>
- You will eventually lock up your box if you break these rules.
+ You should always compile your kernel
+ <symbol>CONFIG_DEBUG_SPINLOCK_SLEEP</symbol> on, and it will warn
+ you if you break these rules. If you <emphasis>do</emphasis> break
+ the rules, you will eventually lock up your box.
</para>
<para>
@@ -515,8 +509,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
success).
</para>
</caution>
- [Yes, this moronic interface makes me cringe. Please submit a
- patch and become my hero --RR.]
+ [Yes, this moronic interface makes me cringe. The flamewar comes up every year or so. --RR.]
</para>
<para>
The functions may sleep implicitly. This should never be called
@@ -587,10 +580,11 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
</variablelist>
<para>
- If you see a <errorname>kmem_grow: Called nonatomically from int
- </errorname> warning message you called a memory allocation function
- from interrupt context without <constant>GFP_ATOMIC</constant>.
- You should really fix that. Run, don't walk.
+ If you see a <errorname>sleeping function called from invalid
+ context</errorname> warning message, then maybe you called a
+ sleeping allocation function from interrupt context without
+ <constant>GFP_ATOMIC</constant>. You should really fix that.
+ Run, don't walk.
</para>
<para>
@@ -639,16 +633,16 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
</sect1>
<sect1 id="routines-udelay">
- <title><function>udelay()</function>/<function>mdelay()</function>
+ <title><function>mdelay()</function>/<function>udelay()</function>
<filename class="headerfile">include/asm/delay.h</filename>
<filename class="headerfile">include/linux/delay.h</filename>
</title>
<para>
- The <function>udelay()</function> function can be used for small pauses.
- Do not use large values with <function>udelay()</function> as you risk
+ The <function>udelay()</function> and <function>ndelay()</function> functions can be used for small pauses.
+ Do not use large values with them as you risk
overflow - the helper function <function>mdelay()</function> is useful
- here, or even consider <function>schedule_timeout()</function>.
+ here, or consider <function>msleep()</function>.
</para>
</sect1>
@@ -698,8 +692,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
These routines disable soft interrupts on the local CPU, and
restore them. They are reentrant; if soft interrupts were
disabled before, they will still be disabled after this pair
- of functions has been called. They prevent softirqs, tasklets
- and bottom halves from running on the current CPU.
+ of functions has been called. They prevent softirqs and tasklets
+ from running on the current CPU.
</para>
</sect1>
@@ -708,10 +702,16 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<filename class="headerfile">include/asm/smp.h</filename></title>
<para>
- <function>smp_processor_id()</function> returns the current
- processor number, between 0 and <symbol>NR_CPUS</symbol> (the
- maximum number of CPUs supported by Linux, currently 32). These
- values are not necessarily continuous.
+ <function>get_cpu()</function> disables preemption (so you won't
+ suddenly get moved to another CPU) and returns the current
+ processor number, between 0 and <symbol>NR_CPUS</symbol>. Note
+ that the CPU numbers are not necessarily continuous. You return
+ it again with <function>put_cpu()</function> when you are done.
+ </para>
+ <para>
+ If you know you cannot be preempted by another task (ie. you are
+ in interrupt context, or have preemption disabled) you can use
+ smp_processor_id().
</para>
</sect1>
@@ -722,19 +722,14 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<para>
After boot, the kernel frees up a special section; functions
marked with <type>__init</type> and data structures marked with
- <type>__initdata</type> are dropped after boot is complete (within
- modules this directive is currently ignored). <type>__exit</type>
+ <type>__initdata</type> are dropped after boot is complete: similarly
+ modules discard this memory after initialization. <type>__exit</type>
is used to declare a function which is only required on exit: the
function will be dropped if this file is not compiled as a module.
See the header file for use. Note that it makes no sense for a function
marked with <type>__init</type> to be exported to modules with
<function>EXPORT_SYMBOL()</function> - this will break.
</para>
- <para>
- Static data structures marked as <type>__initdata</type> must be initialised
- (as opposed to ordinary static data which is zeroed BSS) and cannot be
- <type>const</type>.
- </para>
</sect1>
@@ -762,9 +757,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<para>
The function can return a negative error number to cause
module loading to fail (unfortunately, this has no effect if
- the module is compiled into the kernel). For modules, this is
- called in user context, with interrupts enabled, and the
- kernel lock held, so it can sleep.
+ the module is compiled into the kernel). This function is
+ called in user context with interrupts enabled, so it can sleep.
</para>
</sect1>
@@ -779,6 +773,34 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
reached zero. This function can also sleep, but cannot fail:
everything must be cleaned up by the time it returns.
</para>
+
+ <para>
+ Note that this macro is optional: if it is not present, your
+ module will not be removable (except for 'rmmod -f').
+ </para>
+ </sect1>
+
+ <sect1 id="routines-module-use-counters">
+ <title> <function>try_module_get()</function>/<function>module_put()</function>
+ <filename class="headerfile">include/linux/module.h</filename></title>
+
+ <para>
+ These manipulate the module usage count, to protect against
+ removal (a module also can't be removed if another module uses one
+ of its exported symbols: see below). Before calling into module
+ code, you should call <function>try_module_get()</function> on
+ that module: if it fails, then the module is being removed and you
+ should act as if it wasn't there. Otherwise, you can safely enter
+ the module, and call <function>module_put()</function> when you're
+ finished.
+ </para>
+
+ <para>
+ Most registerable structures have an
+ <structfield>owner</structfield> field, such as in the
+ <structname>file_operations</structname> structure. Set this field
+ to the macro <symbol>THIS_MODULE</symbol>.
+ </para>
</sect1>
<!-- add info on new-style module refcounting here -->
@@ -821,7 +843,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
There is a macro to do this:
<function>wait_event_interruptible()</function>
- <filename class="headerfile">include/linux/sched.h</filename> The
+ <filename class="headerfile">include/linux/wait.h</filename> The
first argument is the wait queue head, and the second is an
expression which is evaluated; the macro returns
<returnvalue>0</returnvalue> when this expression is true, or
@@ -847,10 +869,11 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<para>
Call <function>wake_up()</function>
- <filename class="headerfile">include/linux/sched.h</filename>;,
+ <filename class="headerfile">include/linux/wait.h</filename>;,
which will wake up every process in the queue. The exception is
if one has <constant>TASK_EXCLUSIVE</constant> set, in which case
- the remainder of the queue will not be woken.
+ the remainder of the queue will not be woken. There are other variants
+ of this basic function available in the same header.
</para>
</sect1>
</chapter>
@@ -863,7 +886,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
first class of operations work on <type>atomic_t</type>
<filename class="headerfile">include/asm/atomic.h</filename>; this
- contains a signed integer (at least 24 bits long), and you must use
+ contains a signed integer (at least 32 bits long), and you must use
these functions to manipulate or read atomic_t variables.
<function>atomic_read()</function> and
<function>atomic_set()</function> get and set the counter,
@@ -882,13 +905,12 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<para>
Note that these functions are slower than normal arithmetic, and
- so should not be used unnecessarily. On some platforms they
- are much slower, like 32-bit Sparc where they use a spinlock.
+ so should not be used unnecessarily.
</para>
<para>
- The second class of atomic operations is atomic bit operations on a
- <type>long</type>, defined in
+ The second class of atomic operations is atomic bit operations on an
+ <type>unsigned long</type>, defined in
<filename class="headerfile">include/linux/bitops.h</filename>. These
operations generally take a pointer to the bit pattern, and a bit
@@ -899,7 +921,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<function>test_and_clear_bit()</function> and
<function>test_and_change_bit()</function> do the same thing,
except return true if the bit was previously set; these are
- particularly useful for very simple locking.
+ particularly useful for atomically setting flags.
</para>
<para>
@@ -907,12 +929,6 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
than BITS_PER_LONG. The resulting behavior is strange on big-endian
platforms though so it is a good idea not to do this.
</para>
-
- <para>
- Note that the order of bits depends on the architecture, and in
- particular, the bitfield passed to these operations must be at
- least as large as a <type>long</type>.
- </para>
</chapter>
<chapter id="symbols">
@@ -932,11 +948,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<filename class="headerfile">include/linux/module.h</filename></title>
<para>
- This is the classic method of exporting a symbol, and it works
- for both modules and non-modules. In the kernel all these
- declarations are often bundled into a single file to help
- genksyms (which searches source files for these declarations).
- See the comment on genksyms and Makefiles below.
+ This is the classic method of exporting a symbol: dynamically
+ loaded modules will be able to use the symbol as normal.
</para>
</sect1>
@@ -949,7 +962,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
symbols exported by <function>EXPORT_SYMBOL_GPL()</function> can
only be seen by modules with a
<function>MODULE_LICENSE()</function> that specifies a GPL
- compatible license.
+ compatible license. It implies that the function is considered
+ an internal implementation issue, and not really an interface.
</para>
</sect1>
</chapter>
@@ -962,12 +976,13 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
<filename class="headerfile">include/linux/list.h</filename></title>
<para>
- There are three sets of linked-list routines in the kernel
- headers, but this one seems to be winning out (and Linus has
- used it). If you don't have some particular pressing need for
- a single list, it's a good choice. In fact, I don't care
- whether it's a good choice or not, just use it so we can get
- rid of the others.
+ There used to be three sets of linked-list routines in the kernel
+ headers, but this one is the winner. If you don't have some
+ particular pressing need for a single list, it's a good choice.
+ </para>
+
+ <para>
+ In particular, <function>list_for_each_entry</function> is useful.
</para>
</sect1>
@@ -979,14 +994,13 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
convention, and return <returnvalue>0</returnvalue> for success,
and a negative error number
(eg. <returnvalue>-EFAULT</returnvalue>) for failure. This can be
- unintuitive at first, but it's fairly widespread in the networking
- code, for example.
+ unintuitive at first, but it's fairly widespread in the kernel.
</para>
<para>
- The filesystem code uses <function>ERR_PTR()</function>
+ Using <function>ERR_PTR()</function>
- <filename class="headerfile">include/linux/fs.h</filename>; to
+ <filename class="headerfile">include/linux/err.h</filename>; to
encode a negative error number into a pointer, and
<function>IS_ERR()</function> and <function>PTR_ERR()</function>
to get it back out again: avoids a separate pointer parameter for
@@ -1040,7 +1054,7 @@ static struct block_device_operations opt_fops = {
supported, due to lack of general use, but the following are
considered standard (see the GCC info page section "C
Extensions" for more details - Yes, really the info page, the
- man page is only a short summary of the stuff in info):
+ man page is only a short summary of the stuff in info).
</para>
<itemizedlist>
<listitem>
@@ -1091,7 +1105,7 @@ static struct block_device_operations opt_fops = {
</listitem>
<listitem>
<para>
- Function names as strings (__FUNCTION__)
+ Function names as strings (__func__).
</para>
</listitem>
<listitem>
@@ -1164,63 +1178,35 @@ static struct block_device_operations opt_fops = {
<listitem>
<para>
Usually you want a configuration option for your kernel hack.
- Edit <filename>Config.in</filename> in the appropriate directory
- (but under <filename>arch/</filename> it's called
- <filename>config.in</filename>). The Config Language used is not
- bash, even though it looks like bash; the safe way is to use only
- the constructs that you already see in
- <filename>Config.in</filename> files (see
- <filename>Documentation/kbuild/kconfig-language.txt</filename>).
- It's good to run "make xconfig" at least once to test (because
- it's the only one with a static parser).
- </para>
-
- <para>
- Variables which can be Y or N use <type>bool</type> followed by a
- tagline and the config define name (which must start with
- CONFIG_). The <type>tristate</type> function is the same, but
- allows the answer M (which defines
- <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of
- <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol>
- is enabled.
+ Edit <filename>Kconfig</filename> in the appropriate directory.
+ The Config language is simple to use by cut and paste, and there's
+ complete documentation in
+ <filename>Documentation/kbuild/kconfig-language.txt</filename>.
</para>
<para>
You may well want to make your CONFIG option only visible if
<symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
warning to users. There many other fancy things you can do: see
- the various <filename>Config.in</filename> files for ideas.
+ the various <filename>Kconfig</filename> files for ideas.
</para>
- </listitem>
- <listitem>
<para>
- Edit the <filename>Makefile</filename>: the CONFIG variables are
- exported here so you can conditionalize compilation with `ifeq'.
- If your file exports symbols then add the names to
- <varname>export-objs</varname> so that genksyms will find them.
- <caution>
- <para>
- There is a restriction on the kernel build system that objects
- which export symbols must have globally unique names.
- If your object does not have a globally unique name then the
- standard fix is to move the
- <function>EXPORT_SYMBOL()</function> statements to their own
- object with a unique name.
- This is why several systems have separate exporting objects,
- usually suffixed with ksyms.
- </para>
- </caution>
+ In your description of the option, make sure you address both the
+ expert user and the user who knows nothing about your feature. Mention
+ incompatibilities and issues here. <emphasis> Definitely
+ </emphasis> end your description with <quote> if in doubt, say N
+ </quote> (or, occasionally, `Y'); this is for people who have no
+ idea what you are talking about.
</para>
</listitem>
<listitem>
<para>
- Document your option in Documentation/Configure.help. Mention
- incompatibilities and issues here. <emphasis> Definitely
- </emphasis> end your description with <quote> if in doubt, say N
- </quote> (or, occasionally, `Y'); this is for people who have no
- idea what you are talking about.
+ Edit the <filename>Makefile</filename>: the CONFIG variables are
+ exported here so you can usually just add a "obj-$(CONFIG_xxx) +=
+ xxx.o" line. The syntax is documented in
+ <filename>Documentation/kbuild/makefiles.txt</filename>.
</para>
</listitem>
@@ -1253,20 +1239,12 @@ static struct block_device_operations opt_fops = {
</para>
<para>
- <filename>include/linux/brlock.h:</filename>
+ <filename>include/asm-i386/delay.h:</filename>
</para>
<programlisting>
-extern inline void br_read_lock (enum brlock_indices idx)
-{
- /*
- * This causes a link-time bug message if an
- * invalid index is used:
- */
- if (idx >= __BR_END)
- __br_lock_usage_bug();
-
- read_lock(&amp;__brlock_array[smp_processor_id()][idx]);
-}
+#define ndelay(n) (__builtin_constant_p(n) ? \
+ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+ __ndelay(n))
</programlisting>
<para>
diff --git a/Documentation/DocBook/mcabook.tmpl b/Documentation/DocBook/mcabook.tmpl
index 4367f4642f3d..42a760cd7467 100644
--- a/Documentation/DocBook/mcabook.tmpl
+++ b/Documentation/DocBook/mcabook.tmpl
@@ -96,7 +96,7 @@
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
-!Earch/i386/kernel/mca.c
+!Edrivers/mca/mca-legacy.c
</chapter>
<chapter id="dmafunctions">
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index f3ef0bf435e9..705c442c7bf4 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -841,7 +841,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
File modification time is not updated by this request.
</para><para>
Those struct members are from some interface descriptor
- applying to the the current configuration.
+ applying to the current configuration.
The interface number is the bInterfaceNumber value, and
the altsetting number is the bAlternateSetting value.
(This resets each endpoint in the interface.)
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 84d3d4d10c17..bf1cf98d2a27 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -605,12 +605,13 @@ is in the ipmi_poweroff module. When the system requests a powerdown,
it will send the proper IPMI commands to do this. This is supported on
several platforms.
-There is a module parameter named "poweroff_control" that may either be zero
-(do a power down) or 2 (do a power cycle, power the system off, then power
-it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
-the same thing on the kernel command line. The parameter is also available
-via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
-system does not support power cycling, it will always to the power off.
+There is a module parameter named "poweroff_powercycle" that may
+either be zero (do a power down) or non-zero (do a power cycle, power
+the system off, then power it on in a few seconds). Setting
+ipmi_poweroff.poweroff_control=x will do the same thing on the kernel
+command line. The parameter is also available via the proc filesystem
+in /proc/sys/dev/ipmi/poweroff_powercycle. Note that if the system
+does not support power cycling, it will always do the power off.
Note that if you have ACPI enabled, the system will prefer using ACPI to
power off.
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt
index d5032eb480aa..63edc5f847c4 100644
--- a/Documentation/MSI-HOWTO.txt
+++ b/Documentation/MSI-HOWTO.txt
@@ -430,7 +430,7 @@ which may result in system hang. The software driver of specific
MSI-capable hardware is responsible for whether calling
pci_enable_msi or not. A return of zero indicates the kernel
successfully initializes the MSI/MSI-X capability structure of the
-device funtion. The device function is now running on MSI/MSI-X mode.
+device function. The device function is now running on MSI/MSI-X mode.
5.6 How to tell whether MSI/MSI-X is enabled on device function
diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt
new file mode 100644
index 000000000000..d0634a5c3445
--- /dev/null
+++ b/Documentation/RCU/NMI-RCU.txt
@@ -0,0 +1,112 @@
+Using RCU to Protect Dynamic NMI Handlers
+
+
+Although RCU is usually used to protect read-mostly data structures,
+it is possible to use RCU to provide dynamic non-maskable interrupt
+handlers, as well as dynamic irq handlers. This document describes
+how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
+work in "arch/i386/oprofile/nmi_timer_int.c" and in
+"arch/i386/kernel/traps.c".
+
+The relevant pieces of code are listed below, each followed by a
+brief explanation.
+
+ static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
+ {
+ return 0;
+ }
+
+The dummy_nmi_callback() function is a "dummy" NMI handler that does
+nothing, but returns zero, thus saying that it did nothing, allowing
+the NMI handler to take the default machine-specific action.
+
+ static nmi_callback_t nmi_callback = dummy_nmi_callback;
+
+This nmi_callback variable is a global function pointer to the current
+NMI handler.
+
+ fastcall void do_nmi(struct pt_regs * regs, long error_code)
+ {
+ int cpu;
+
+ nmi_enter();
+
+ cpu = smp_processor_id();
+ ++nmi_count(cpu);
+
+ if (!rcu_dereference(nmi_callback)(regs, cpu))
+ default_do_nmi(regs);
+
+ nmi_exit();
+ }
+
+The do_nmi() function processes each NMI. It first disables preemption
+in the same way that a hardware irq would, then increments the per-CPU
+count of NMIs. It then invokes the NMI handler stored in the nmi_callback
+function pointer. If this handler returns zero, do_nmi() invokes the
+default_do_nmi() function to handle a machine-specific NMI. Finally,
+preemption is restored.
+
+Strictly speaking, rcu_dereference() is not needed, since this code runs
+only on i386, which does not need rcu_dereference() anyway. However,
+it is a good documentation aid, particularly for anyone attempting to
+do something similar on Alpha.
+
+Quick Quiz: Why might the rcu_dereference() be necessary on Alpha,
+ given that the code referenced by the pointer is read-only?
+
+
+Back to the discussion of NMI and RCU...
+
+ void set_nmi_callback(nmi_callback_t callback)
+ {
+ rcu_assign_pointer(nmi_callback, callback);
+ }
+
+The set_nmi_callback() function registers an NMI handler. Note that any
+data that is to be used by the callback must be initialized up -before-
+the call to set_nmi_callback(). On architectures that do not order
+writes, the rcu_assign_pointer() ensures that the NMI handler sees the
+initialized values.
+
+ void unset_nmi_callback(void)
+ {
+ rcu_assign_pointer(nmi_callback, dummy_nmi_callback);
+ }
+
+This function unregisters an NMI handler, restoring the original
+dummy_nmi_handler(). However, there may well be an NMI handler
+currently executing on some other CPU. We therefore cannot free
+up any data structures used by the old NMI handler until execution
+of it completes on all other CPUs.
+
+One way to accomplish this is via synchronize_sched(), perhaps as
+follows:
+
+ unset_nmi_callback();
+ synchronize_sched();
+ kfree(my_nmi_data);
+
+This works because synchronize_sched() blocks until all CPUs complete
+any preemption-disabled segments of code that they were executing.
+Since NMI handlers disable preemption, synchronize_sched() is guaranteed
+not to return until all ongoing NMI handlers exit. It is therefore safe
+to free up the handler's data as soon as synchronize_sched() returns.
+
+
+Answer to Quick Quiz
+
+ Why might the rcu_dereference() be necessary on Alpha, given
+ that the code referenced by the pointer is read-only?
+
+ Answer: The caller to set_nmi_callback() might well have
+ initialized some data that is to be used by the
+ new NMI handler. In this case, the rcu_dereference()
+ would be needed, because otherwise a CPU that received
+ an NMI just after the new handler was set might see
+ the pointer to the new NMI handler, but the old
+ pre-initialized version of the handler's data.
+
+ More important, the rcu_dereference() makes it clear
+ to someone reading the code that the pointer is being
+ protected by RCU.
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 9c6d450138ea..fcbcbc35b122 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -2,7 +2,8 @@ Read the F-ing Papers!
This document describes RCU-related publications, and is followed by
-the corresponding bibtex entries.
+the corresponding bibtex entries. A number of the publications may
+be found at http://www.rdrop.com/users/paulmck/RCU/.
The first thing resembling RCU was published in 1980, when Kung and Lehman
[Kung80] recommended use of a garbage collector to defer destruction
@@ -113,6 +114,10 @@ describing how to make RCU safe for soft-realtime applications [Sarma04c],
and a paper describing SELinux performance with RCU [JamesMorris04b].
+2005 has seen further adaptation of RCU to realtime use, permitting
+preemption of RCU realtime critical sections [PaulMcKenney05a,
+PaulMcKenney05b].
+
Bibtex Entries
@article{Kung80
@@ -410,3 +415,32 @@ Oregon Health and Sciences University"
\url{http://www.livejournal.com/users/james_morris/2153.html}
[Viewed December 10, 2004]"
}
+
+@unpublished{PaulMcKenney05a
+,Author="Paul E. McKenney"
+,Title="{[RFC]} {RCU} and {CONFIG\_PREEMPT\_RT} progress"
+,month="May"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/5/9/185}
+[Viewed May 13, 2005]"
+,annotation="
+ First publication of working lock-based deferred free patches
+ for the CONFIG_PREEMPT_RT environment.
+"
+}
+
+@conference{PaulMcKenney05b
+,Author="Paul E. McKenney and Dipankar Sarma"
+,Title="Towards Hard Realtime Response from the Linux Kernel on SMP Hardware"
+,Booktitle="linux.conf.au 2005"
+,month="April"
+,year="2005"
+,address="Canberra, Australia"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
+[Viewed May 13, 2005]"
+,annotation="
+ Realtime turns into making RCU yet more realtime friendly.
+"
+}
diff --git a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt
index 3bfb84b3b7db..aab4a9ec3931 100644
--- a/Documentation/RCU/UP.txt
+++ b/Documentation/RCU/UP.txt
@@ -8,7 +8,7 @@ is that since there is only one CPU, it should not be necessary to
wait for anything else to get done, since there are no other CPUs for
anything else to be happening on. Although this approach will -sort- -of-
work a surprising amount of the time, it is a very bad idea in general.
-This document presents two examples that demonstrate exactly how bad an
+This document presents three examples that demonstrate exactly how bad an
idea this is.
@@ -26,6 +26,9 @@ from softirq, the list scan would find itself referencing a newly freed
element B. This situation can greatly decrease the life expectancy of
your kernel.
+This same problem can occur if call_rcu() is invoked from a hardware
+interrupt handler.
+
Example 2: Function-Call Fatality
@@ -44,8 +47,37 @@ its arguments would cause it to fail to make the fundamental guarantee
underlying RCU, namely that call_rcu() defers invoking its arguments until
all RCU read-side critical sections currently executing have completed.
-Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in
-this case?
+Quick Quiz #1: why is it -not- legal to invoke synchronize_rcu() in
+ this case?
+
+
+Example 3: Death by Deadlock
+
+Suppose that call_rcu() is invoked while holding a lock, and that the
+callback function must acquire this same lock. In this case, if
+call_rcu() were to directly invoke the callback, the result would
+be self-deadlock.
+
+In some cases, it would possible to restructure to code so that
+the call_rcu() is delayed until after the lock is released. However,
+there are cases where this can be quite ugly:
+
+1. If a number of items need to be passed to call_rcu() within
+ the same critical section, then the code would need to create
+ a list of them, then traverse the list once the lock was
+ released.
+
+2. In some cases, the lock will be held across some kernel API,
+ so that delaying the call_rcu() until the lock is released
+ requires that the data item be passed up via a common API.
+ It is far better to guarantee that callbacks are invoked
+ with no locks held than to have to modify such APIs to allow
+ arbitrary data items to be passed back up through them.
+
+If call_rcu() directly invokes the callback, painful locking restrictions
+or API changes would be required.
+
+Quick Quiz #2: What locking restriction must RCU callbacks respect?
Summary
@@ -53,12 +85,35 @@ Summary
Permitting call_rcu() to immediately invoke its arguments or permitting
synchronize_rcu() to immediately return breaks RCU, even on a UP system.
So do not do it! Even on a UP system, the RCU infrastructure -must-
-respect grace periods.
-
-
-Answer to Quick Quiz
-
-The calling function is scanning an RCU-protected linked list, and
-is therefore within an RCU read-side critical section. Therefore,
-the called function has been invoked within an RCU read-side critical
-section, and is not permitted to block.
+respect grace periods, and -must- invoke callbacks from a known environment
+in which no locks are held.
+
+
+Answer to Quick Quiz #1:
+ Why is it -not- legal to invoke synchronize_rcu() in this case?
+
+ Because the calling function is scanning an RCU-protected linked
+ list, and is therefore within an RCU read-side critical section.
+ Therefore, the called function has been invoked within an RCU
+ read-side critical section, and is not permitted to block.
+
+Answer to Quick Quiz #2:
+ What locking restriction must RCU callbacks respect?
+
+ Any lock that is acquired within an RCU callback must be
+ acquired elsewhere using an _irq variant of the spinlock
+ primitive. For example, if "mylock" is acquired by an
+ RCU callback, then a process-context acquisition of this
+ lock must use something like spin_lock_irqsave() to
+ acquire the lock.
+
+ If the process-context code were to simply use spin_lock(),
+ then, since RCU callbacks can be invoked from softirq context,
+ the callback might be called from a softirq that interrupted
+ the process-context critical section. This would result in
+ self-deadlock.
+
+ This restriction might seem gratuitous, since very few RCU
+ callbacks acquire locks directly. However, a great many RCU
+ callbacks do acquire locks -indirectly-, for example, via
+ the kfree() primitive.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 8f3fb77c9cd3..e118a7c1a092 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -43,6 +43,10 @@ over a rather long period of time, but improvements are always welcome!
rcu_read_lock_bh()) in the read-side critical sections,
and are also an excellent aid to readability.
+ As a rough rule of thumb, any dereference of an RCU-protected
+ pointer must be covered by rcu_read_lock() or rcu_read_lock_bh()
+ or by the appropriate update-side lock.
+
3. Does the update code tolerate concurrent accesses?
The whole point of RCU is to permit readers to run without
@@ -90,7 +94,11 @@ over a rather long period of time, but improvements are always welcome!
The rcu_dereference() primitive is used by the various
"_rcu()" list-traversal primitives, such as the
- list_for_each_entry_rcu().
+ list_for_each_entry_rcu(). Note that it is perfectly
+ legal (if redundant) for update-side code to use
+ rcu_dereference() and the "_rcu()" list-traversal
+ primitives. This is particularly useful in code
+ that is common to readers and updaters.
b. If the list macros are being used, the list_add_tail_rcu()
and list_add_rcu() primitives must be used in order
@@ -150,16 +158,9 @@ over a rather long period of time, but improvements are always welcome!
Use of the _rcu() list-traversal primitives outside of an
RCU read-side critical section causes no harm other than
- a slight performance degradation on Alpha CPUs and some
- confusion on the part of people trying to read the code.
-
- Another way of thinking of this is "If you are holding the
- lock that prevents the data structure from changing, why do
- you also need RCU-based protection?" That said, there may
- well be situations where use of the _rcu() list-traversal
- primitives while the update-side lock is held results in
- simpler and more maintainable code. The jury is still out
- on this question.
+ a slight performance degradation on Alpha CPUs. It can
+ also be quite helpful in reducing code bloat when common
+ code is shared between readers and updaters.
10. Conversely, if you are in an RCU read-side critical section,
you -must- use the "_rcu()" variants of the list macros.
diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt
index eb444006683e..6fa092251586 100644
--- a/Documentation/RCU/rcu.txt
+++ b/Documentation/RCU/rcu.txt
@@ -64,6 +64,54 @@ o I hear that RCU is patented? What is with that?
Of these, one was allowed to lapse by the assignee, and the
others have been contributed to the Linux kernel under GPL.
+o I hear that RCU needs work in order to support realtime kernels?
+
+ Yes, work in progress.
+
o Where can I find more information on RCU?
See the RTFP.txt file in this directory.
+ Or point your browser at http://www.rdrop.com/users/paulmck/RCU/.
+
+o What are all these files in this directory?
+
+
+ NMI-RCU.txt
+
+ Describes how to use RCU to implement dynamic
+ NMI handlers, which can be revectored on the fly,
+ without rebooting.
+
+ RTFP.txt
+
+ List of RCU-related publications and web sites.
+
+ UP.txt
+
+ Discussion of RCU usage in UP kernels.
+
+ arrayRCU.txt
+
+ Describes how to use RCU to protect arrays, with
+ resizeable arrays whose elements reference other
+ data structures being of the most interest.
+
+ checklist.txt
+
+ Lists things to check for when inspecting code that
+ uses RCU.
+
+ listRCU.txt
+
+ Describes how to use RCU to protect linked lists.
+ This is the simplest and most common use of RCU
+ in the Linux kernel.
+
+ rcu.txt
+
+ You are reading it!
+
+ whatisRCU.txt
+
+ Overview of how the RCU implementation works. Along
+ the way, presents a conceptual view of RCU.
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
new file mode 100644
index 000000000000..a23fee66064d
--- /dev/null
+++ b/Documentation/RCU/rcuref.txt
@@ -0,0 +1,74 @@
+Refcounter framework for elements of lists/arrays protected by
+RCU.
+
+Refcounting on elements of lists which are protected by traditional
+reader/writer spinlocks or semaphores are straight forward as in:
+
+1. 2.
+add() search_and_reference()
+{ {
+ alloc_object read_lock(&list_lock);
+ ... search_for_element
+ atomic_set(&el->rc, 1); atomic_inc(&el->rc);
+ write_lock(&list_lock); ...
+ add_element read_unlock(&list_lock);
+ ... ...
+ write_unlock(&list_lock); }
+}
+
+3. 4.
+release_referenced() delete()
+{ {
+ ... write_lock(&list_lock);
+ atomic_dec(&el->rc, relfunc) ...
+ ... delete_element
+} write_unlock(&list_lock);
+ ...
+ if (atomic_dec_and_test(&el->rc))
+ kfree(el);
+ ...
+ }
+
+If this list/array is made lock free using rcu as in changing the
+write_lock in add() and delete() to spin_lock and changing read_lock
+in search_and_reference to rcu_read_lock(), the rcuref_get in
+search_and_reference could potentially hold reference to an element which
+has already been deleted from the list/array. rcuref_lf_get_rcu takes
+care of this scenario. search_and_reference should look as;
+
+1. 2.
+add() search_and_reference()
+{ {
+ alloc_object rcu_read_lock();
+ ... search_for_element
+ atomic_set(&el->rc, 1); if (rcuref_inc_lf(&el->rc)) {
+ write_lock(&list_lock); rcu_read_unlock();
+ return FAIL;
+ add_element }
+ ... ...
+ write_unlock(&list_lock); rcu_read_unlock();
+} }
+3. 4.
+release_referenced() delete()
+{ {
+ ... write_lock(&list_lock);
+ rcuref_dec(&el->rc, relfunc) ...
+ ... delete_element
+} write_unlock(&list_lock);
+ ...
+ if (rcuref_dec_and_test(&el->rc))
+ call_rcu(&el->head, el_free);
+ ...
+ }
+
+Sometimes, reference to the element need to be obtained in the
+update (write) stream. In such cases, rcuref_inc_lf might be an overkill
+since the spinlock serialising list updates are held. rcuref_inc
+is to be used in such cases.
+For arches which do not have cmpxchg rcuref_inc_lf
+api uses a hashed spinlock implementation and the same hashed spinlock
+is acquired in all rcuref_xxx primitives to preserve atomicity.
+Note: Use rcuref_inc api only if you need to use rcuref_inc_lf on the
+refcounter atleast at one place. Mixing rcuref_inc and atomic_xxx api
+might lead to races. rcuref_inc_lf() must be used in lockfree
+RCU critical sections only.
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
new file mode 100644
index 000000000000..354d89c78377
--- /dev/null
+++ b/Documentation/RCU/whatisRCU.txt
@@ -0,0 +1,902 @@
+What is RCU?
+
+RCU is a synchronization mechanism that was added to the Linux kernel
+during the 2.5 development effort that is optimized for read-mostly
+situations. Although RCU is actually quite simple once you understand it,
+getting there can sometimes be a challenge. Part of the problem is that
+most of the past descriptions of RCU have been written with the mistaken
+assumption that there is "one true way" to describe RCU. Instead,
+the experience has been that different people must take different paths
+to arrive at an understanding of RCU. This document provides several
+different paths, as follows:
+
+1. RCU OVERVIEW
+2. WHAT IS RCU'S CORE API?
+3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
+4. WHAT IF MY UPDATING THREAD CANNOT BLOCK?
+5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU?
+6. ANALOGY WITH READER-WRITER LOCKING
+7. FULL LIST OF RCU APIs
+8. ANSWERS TO QUICK QUIZZES
+
+People who prefer starting with a conceptual overview should focus on
+Section 1, though most readers will profit by reading this section at
+some point. People who prefer to start with an API that they can then
+experiment with should focus on Section 2. People who prefer to start
+with example uses should focus on Sections 3 and 4. People who need to
+understand the RCU implementation should focus on Section 5, then dive
+into the kernel source code. People who reason best by analogy should
+focus on Section 6. Section 7 serves as an index to the docbook API
+documentation, and Section 8 is the traditional answer key.
+
+So, start with the section that makes the most sense to you and your
+preferred method of learning. If you need to know everything about
+everything, feel free to read the whole thing -- but if you are really
+that type of person, you have perused the source code and will therefore
+never need this document anyway. ;-)
+
+
+1. RCU OVERVIEW
+
+The basic idea behind RCU is to split updates into "removal" and
+"reclamation" phases. The removal phase removes references to data items
+within a data structure (possibly by replacing them with references to
+new versions of these data items), and can run concurrently with readers.
+The reason that it is safe to run the removal phase concurrently with
+readers is the semantics of modern CPUs guarantee that readers will see
+either the old or the new version of the data structure rather than a
+partially updated reference. The reclamation phase does the work of reclaiming
+(e.g., freeing) the data items removed from the data structure during the
+removal phase. Because reclaiming data items can disrupt any readers
+concurrently referencing those data items, the reclamation phase must
+not start until readers no longer hold references to those data items.
+
+Splitting the update into removal and reclamation phases permits the
+updater to perform the removal phase immediately, and to defer the
+reclamation phase until all readers active during the removal phase have
+completed, either by blocking until they finish or by registering a
+callback that is invoked after they finish. Only readers that are active
+during the removal phase need be considered, because any reader starting
+after the removal phase will be unable to gain a reference to the removed
+data items, and therefore cannot be disrupted by the reclamation phase.
+
+So the typical RCU update sequence goes something like the following:
+
+a. Remove pointers to a data structure, so that subsequent
+ readers cannot gain a reference to it.
+
+b. Wait for all previous readers to complete their RCU read-side
+ critical sections.
+
+c. At this point, there cannot be any readers who hold references
+ to the data structure, so it now may safely be reclaimed
+ (e.g., kfree()d).
+
+Step (b) above is the key idea underlying RCU's deferred destruction.
+The ability to wait until all readers are done allows RCU readers to
+use much lighter-weight synchronization, in some cases, absolutely no
+synchronization at all. In contrast, in more conventional lock-based
+schemes, readers must use heavy-weight synchronization in order to
+prevent an updater from deleting the data structure out from under them.
+This is because lock-based updaters typically update data items in place,
+and must therefore exclude readers. In contrast, RCU-based updaters
+typically take advantage of the fact that writes to single aligned
+pointers are atomic on modern CPUs, allowing atomic insertion, removal,
+and replacement of data items in a linked structure without disrupting
+readers. Concurrent RCU readers can then continue accessing the old
+versions, and can dispense with the atomic operations, memory barriers,
+and communications cache misses that are so expensive on present-day
+SMP computer systems, even in absence of lock contention.
+
+In the three-step procedure shown above, the updater is performing both
+the removal and the reclamation step, but it is often helpful for an
+entirely different thread to do the reclamation, as is in fact the case
+in the Linux kernel's directory-entry cache (dcache). Even if the same
+thread performs both the update step (step (a) above) and the reclamation
+step (step (c) above), it is often helpful to think of them separately.
+For example, RCU readers and updaters need not communicate at all,
+but RCU provides implicit low-overhead communication between readers
+and reclaimers, namely, in step (b) above.
+
+So how the heck can a reclaimer tell when a reader is done, given
+that readers are not doing any sort of synchronization operations???
+Read on to learn about how RCU's API makes this easy.
+
+
+2. WHAT IS RCU'S CORE API?
+
+The core RCU API is quite small:
+
+a. rcu_read_lock()
+b. rcu_read_unlock()
+c. synchronize_rcu() / call_rcu()
+d. rcu_assign_pointer()
+e. rcu_dereference()
+
+There are many other members of the RCU API, but the rest can be
+expressed in terms of these five, though most implementations instead
+express synchronize_rcu() in terms of the call_rcu() callback API.
+
+The five core RCU APIs are described below, the other 18 will be enumerated
+later. See the kernel docbook documentation for more info, or look directly
+at the function header comments.
+
+rcu_read_lock()
+
+ void rcu_read_lock(void);
+
+ Used by a reader to inform the reclaimer that the reader is
+ entering an RCU read-side critical section. It is illegal
+ to block while in an RCU read-side critical section, though
+ kernels built with CONFIG_PREEMPT_RCU can preempt RCU read-side
+ critical sections. Any RCU-protected data structure accessed
+ during an RCU read-side critical section is guaranteed to remain
+ unreclaimed for the full duration of that critical section.
+ Reference counts may be used in conjunction with RCU to maintain
+ longer-term references to data structures.
+
+rcu_read_unlock()
+
+ void rcu_read_unlock(void);
+
+ Used by a reader to inform the reclaimer that the reader is
+ exiting an RCU read-side critical section. Note that RCU
+ read-side critical sections may be nested and/or overlapping.
+
+synchronize_rcu()
+
+ void synchronize_rcu(void);
+
+ Marks the end of updater code and the beginning of reclaimer
+ code. It does this by blocking until all pre-existing RCU
+ read-side critical sections on all CPUs have completed.
+ Note that synchronize_rcu() will -not- necessarily wait for
+ any subsequent RCU read-side critical sections to complete.
+ For example, consider the following sequence of events:
+
+ CPU 0 CPU 1 CPU 2
+ ----------------- ------------------------- ---------------
+ 1. rcu_read_lock()
+ 2. enters synchronize_rcu()
+ 3. rcu_read_lock()
+ 4. rcu_read_unlock()
+ 5. exits synchronize_rcu()
+ 6. rcu_read_unlock()
+
+ To reiterate, synchronize_rcu() waits only for ongoing RCU
+ read-side critical sections to complete, not necessarily for
+ any that begin after synchronize_rcu() is invoked.
+
+ Of course, synchronize_rcu() does not necessarily return
+ -immediately- after the last pre-existing RCU read-side critical
+ section completes. For one thing, there might well be scheduling
+ delays. For another thing, many RCU implementations process
+ requests in batches in order to improve efficiencies, which can
+ further delay synchronize_rcu().
+
+ Since synchronize_rcu() is the API that must figure out when
+ readers are done, its implementation is key to RCU. For RCU
+ to be useful in all but the most read-intensive situations,
+ synchronize_rcu()'s overhead must also be quite small.
+
+ The call_rcu() API is a callback form of synchronize_rcu(),
+ and is described in more detail in a later section. Instead of
+ blocking, it registers a function and argument which are invoked
+ after all ongoing RCU read-side critical sections have completed.
+ This callback variant is particularly useful in situations where
+ it is illegal to block.
+
+rcu_assign_pointer()
+
+ typeof(p) rcu_assign_pointer(p, typeof(p) v);
+
+ Yes, rcu_assign_pointer() -is- implemented as a macro, though it
+ would be cool to be able to declare a function in this manner.
+ (Compiler experts will no doubt disagree.)
+
+ The updater uses this function to assign a new value to an
+ RCU-protected pointer, in order to safely communicate the change
+ in value from the updater to the reader. This function returns
+ the new value, and also executes any memory-barrier instructions
+ required for a given CPU architecture.
+
+ Perhaps more important, it serves to document which pointers
+ are protected by RCU. That said, rcu_assign_pointer() is most
+ frequently used indirectly, via the _rcu list-manipulation
+ primitives such as list_add_rcu().
+
+rcu_dereference()
+
+ typeof(p) rcu_dereference(p);
+
+ Like rcu_assign_pointer(), rcu_dereference() must be implemented
+ as a macro.
+
+ The reader uses rcu_dereference() to fetch an RCU-protected
+ pointer, which returns a value that may then be safely
+ dereferenced. Note that rcu_deference() does not actually
+ dereference the pointer, instead, it protects the pointer for
+ later dereferencing. It also executes any needed memory-barrier
+ instructions for a given CPU architecture. Currently, only Alpha
+ needs memory barriers within rcu_dereference() -- on other CPUs,
+ it compiles to nothing, not even a compiler directive.
+
+ Common coding practice uses rcu_dereference() to copy an
+ RCU-protected pointer to a local variable, then dereferences
+ this local variable, for example as follows:
+
+ p = rcu_dereference(head.next);
+ return p->data;
+
+ However, in this case, one could just as easily combine these
+ into one statement:
+
+ return rcu_dereference(head.next)->data;
+
+ If you are going to be fetching multiple fields from the
+ RCU-protected structure, using the local variable is of
+ course preferred. Repeated rcu_dereference() calls look
+ ugly and incur unnecessary overhead on Alpha CPUs.
+
+ Note that the value returned by rcu_dereference() is valid
+ only within the enclosing RCU read-side critical section.
+ For example, the following is -not- legal:
+
+ rcu_read_lock();
+ p = rcu_dereference(head.next);
+ rcu_read_unlock();
+ x = p->address;
+ rcu_read_lock();
+ y = p->data;
+ rcu_read_unlock();
+
+ Holding a reference from one RCU read-side critical section
+ to another is just as illegal as holding a reference from
+ one lock-based critical section to another! Similarly,
+ using a reference outside of the critical section in which
+ it was acquired is just as illegal as doing so with normal
+ locking.
+
+ As with rcu_assign_pointer(), an important function of
+ rcu_dereference() is to document which pointers are protected
+ by RCU. And, again like rcu_assign_pointer(), rcu_dereference()
+ is typically used indirectly, via the _rcu list-manipulation
+ primitives, such as list_for_each_entry_rcu().
+
+The following diagram shows how each API communicates among the
+reader, updater, and reclaimer.
+
+
+ rcu_assign_pointer()
+ +--------+
+ +---------------------->| reader |---------+
+ | +--------+ |
+ | | |
+ | | | Protect:
+ | | | rcu_read_lock()
+ | | | rcu_read_unlock()
+ | rcu_dereference() | |
+ +---------+ | |
+ | updater |<---------------------+ |
+ +---------+ V
+ | +-----------+
+ +----------------------------------->| reclaimer |
+ +-----------+
+ Defer:
+ synchronize_rcu() & call_rcu()
+
+
+The RCU infrastructure observes the time sequence of rcu_read_lock(),
+rcu_read_unlock(), synchronize_rcu(), and call_rcu() invocations in
+order to determine when (1) synchronize_rcu() invocations may return
+to their callers and (2) call_rcu() callbacks may be invoked. Efficient
+implementations of the RCU infrastructure make heavy use of batching in
+order to amortize their overhead over many uses of the corresponding APIs.
+
+There are no fewer than three RCU mechanisms in the Linux kernel; the
+diagram above shows the first one, which is by far the most commonly used.
+The rcu_dereference() and rcu_assign_pointer() primitives are used for
+all three mechanisms, but different defer and protect primitives are
+used as follows:
+
+ Defer Protect
+
+a. synchronize_rcu() rcu_read_lock() / rcu_read_unlock()
+ call_rcu()
+
+b. call_rcu_bh() rcu_read_lock_bh() / rcu_read_unlock_bh()
+
+c. synchronize_sched() preempt_disable() / preempt_enable()
+ local_irq_save() / local_irq_restore()
+ hardirq enter / hardirq exit
+ NMI enter / NMI exit
+
+These three mechanisms are used as follows:
+
+a. RCU applied to normal data structures.
+
+b. RCU applied to networking data structures that may be subjected
+ to remote denial-of-service attacks.
+
+c. RCU applied to scheduler and interrupt/NMI-handler tasks.
+
+Again, most uses will be of (a). The (b) and (c) cases are important
+for specialized uses, but are relatively uncommon.
+
+
+3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
+
+This section shows a simple use of the core RCU API to protect a
+global pointer to a dynamically allocated structure. More typical
+uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
+
+ struct foo {
+ int a;
+ char b;
+ long c;
+ };
+ DEFINE_SPINLOCK(foo_mutex);
+
+ struct foo *gbl_foo;
+
+ /*
+ * Create a new struct foo that is the same as the one currently
+ * pointed to by gbl_foo, except that field "a" is replaced
+ * with "new_a". Points gbl_foo to the new structure, and
+ * frees up the old structure after a grace period.
+ *
+ * Uses rcu_assign_pointer() to ensure that concurrent readers
+ * see the initialized version of the new structure.
+ *
+ * Uses synchronize_rcu() to ensure that any readers that might
+ * have references to the old structure complete before freeing
+ * the old structure.
+ */
+ void foo_update_a(int new_a)
+ {
+ struct foo *new_fp;
+ struct foo *old_fp;
+
+ new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ spin_lock(&foo_mutex);
+ old_fp = gbl_foo;
+ *new_fp = *old_fp;
+ new_fp->a = new_a;
+ rcu_assign_pointer(gbl_foo, new_fp);
+ spin_unlock(&foo_mutex);
+ synchronize_rcu();
+ kfree(old_fp);
+ }
+
+ /*
+ * Return the value of field "a" of the current gbl_foo
+ * structure. Use rcu_read_lock() and rcu_read_unlock()
+ * to ensure that the structure does not get deleted out
+ * from under us, and use rcu_dereference() to ensure that
+ * we see the initialized version of the structure (important
+ * for DEC Alpha and for people reading the code).
+ */
+ int foo_get_a(void)
+ {
+ int retval;
+
+ rcu_read_lock();
+ retval = rcu_dereference(gbl_foo)->a;
+ rcu_read_unlock();
+ return retval;
+ }
+
+So, to sum up:
+
+o Use rcu_read_lock() and rcu_read_unlock() to guard RCU
+ read-side critical sections.
+
+o Within an RCU read-side critical section, use rcu_dereference()
+ to dereference RCU-protected pointers.
+
+o Use some solid scheme (such as locks or semaphores) to
+ keep concurrent updates from interfering with each other.
+
+o Use rcu_assign_pointer() to update an RCU-protected pointer.
+ This primitive protects concurrent readers from the updater,
+ -not- concurrent updates from each other! You therefore still
+ need to use locking (or something similar) to keep concurrent
+ rcu_assign_pointer() primitives from interfering with each other.
+
+o Use synchronize_rcu() -after- removing a data element from an
+ RCU-protected data structure, but -before- reclaiming/freeing
+ the data element, in order to wait for the completion of all
+ RCU read-side critical sections that might be referencing that
+ data item.
+
+See checklist.txt for additional rules to follow when using RCU.
+
+
+4. WHAT IF MY UPDATING THREAD CANNOT BLOCK?
+
+In the example above, foo_update_a() blocks until a grace period elapses.
+This is quite simple, but in some cases one cannot afford to wait so
+long -- there might be other high-priority work to be done.
+
+In such cases, one uses call_rcu() rather than synchronize_rcu().
+The call_rcu() API is as follows:
+
+ void call_rcu(struct rcu_head * head,
+ void (*func)(struct rcu_head *head));
+
+This function invokes func(head) after a grace period has elapsed.
+This invocation might happen from either softirq or process context,
+so the function is not permitted to block. The foo struct needs to
+have an rcu_head structure added, perhaps as follows:
+
+ struct foo {
+ int a;
+ char b;
+ long c;
+ struct rcu_head rcu;
+ };
+
+The foo_update_a() function might then be written as follows:
+
+ /*
+ * Create a new struct foo that is the same as the one currently
+ * pointed to by gbl_foo, except that field "a" is replaced
+ * with "new_a". Points gbl_foo to the new structure, and
+ * frees up the old structure after a grace period.
+ *
+ * Uses rcu_assign_pointer() to ensure that concurrent readers
+ * see the initialized version of the new structure.
+ *
+ * Uses call_rcu() to ensure that any readers that might have
+ * references to the old structure complete before freeing the
+ * old structure.
+ */
+ void foo_update_a(int new_a)
+ {
+ struct foo *new_fp;
+ struct foo *old_fp;
+
+ new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ spin_lock(&foo_mutex);
+ old_fp = gbl_foo;
+ *new_fp = *old_fp;
+ new_fp->a = new_a;
+ rcu_assign_pointer(gbl_foo, new_fp);
+ spin_unlock(&foo_mutex);
+ call_rcu(&old_fp->rcu, foo_reclaim);
+ }
+
+The foo_reclaim() function might appear as follows:
+
+ void foo_reclaim(struct rcu_head *rp)
+ {
+ struct foo *fp = container_of(rp, struct foo, rcu);
+
+ kfree(fp);
+ }
+
+The container_of() primitive is a macro that, given a pointer into a
+struct, the type of the struct, and the pointed-to field within the
+struct, returns a pointer to the beginning of the struct.
+
+The use of call_rcu() permits the caller of foo_update_a() to
+immediately regain control, without needing to worry further about the
+old version of the newly updated element. It also clearly shows the
+RCU distinction between updater, namely foo_update_a(), and reclaimer,
+namely foo_reclaim().
+
+The summary of advice is the same as for the previous section, except
+that we are now using call_rcu() rather than synchronize_rcu():
+
+o Use call_rcu() -after- removing a data element from an
+ RCU-protected data structure in order to register a callback
+ function that will be invoked after the completion of all RCU
+ read-side critical sections that might be referencing that
+ data item.
+
+Again, see checklist.txt for additional rules governing the use of RCU.
+
+
+5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU?
+
+One of the nice things about RCU is that it has extremely simple "toy"
+implementations that are a good first step towards understanding the
+production-quality implementations in the Linux kernel. This section
+presents two such "toy" implementations of RCU, one that is implemented
+in terms of familiar locking primitives, and another that more closely
+resembles "classic" RCU. Both are way too simple for real-world use,
+lacking both functionality and performance. However, they are useful
+in getting a feel for how RCU works. See kernel/rcupdate.c for a
+production-quality implementation, and see:
+
+ http://www.rdrop.com/users/paulmck/RCU
+
+for papers describing the Linux kernel RCU implementation. The OLS'01
+and OLS'02 papers are a good introduction, and the dissertation provides
+more details on the current implementation.
+
+
+5A. "TOY" IMPLEMENTATION #1: LOCKING
+
+This section presents a "toy" RCU implementation that is based on
+familiar locking primitives. Its overhead makes it a non-starter for
+real-life use, as does its lack of scalability. It is also unsuitable
+for realtime use, since it allows scheduling latency to "bleed" from
+one read-side critical section to another.
+
+However, it is probably the easiest implementation to relate to, so is
+a good starting point.
+
+It is extremely simple:
+
+ static DEFINE_RWLOCK(rcu_gp_mutex);
+
+ void rcu_read_lock(void)
+ {
+ read_lock(&rcu_gp_mutex);
+ }
+
+ void rcu_read_unlock(void)
+ {
+ read_unlock(&rcu_gp_mutex);
+ }
+
+ void synchronize_rcu(void)
+ {
+ write_lock(&rcu_gp_mutex);
+ write_unlock(&rcu_gp_mutex);
+ }
+
+[You can ignore rcu_assign_pointer() and rcu_dereference() without
+missing much. But here they are anyway. And whatever you do, don't
+forget about them when submitting patches making use of RCU!]
+
+ #define rcu_assign_pointer(p, v) ({ \
+ smp_wmb(); \
+ (p) = (v); \
+ })
+
+ #define rcu_dereference(p) ({ \
+ typeof(p) _________p1 = p; \
+ smp_read_barrier_depends(); \
+ (_________p1); \
+ })
+
+
+The rcu_read_lock() and rcu_read_unlock() primitive read-acquire
+and release a global reader-writer lock. The synchronize_rcu()
+primitive write-acquires this same lock, then immediately releases
+it. This means that once synchronize_rcu() exits, all RCU read-side
+critical sections that were in progress before synchonize_rcu() was
+called are guaranteed to have completed -- there is no way that
+synchronize_rcu() would have been able to write-acquire the lock
+otherwise.
+
+It is possible to nest rcu_read_lock(), since reader-writer locks may
+be recursively acquired. Note also that rcu_read_lock() is immune
+from deadlock (an important property of RCU). The reason for this is
+that the only thing that can block rcu_read_lock() is a synchronize_rcu().
+But synchronize_rcu() does not acquire any locks while holding rcu_gp_mutex,
+so there can be no deadlock cycle.
+
+Quick Quiz #1: Why is this argument naive? How could a deadlock
+ occur when using this algorithm in a real-world Linux
+ kernel? How could this deadlock be avoided?
+
+
+5B. "TOY" EXAMPLE #2: CLASSIC RCU
+
+This section presents a "toy" RCU implementation that is based on
+"classic RCU". It is also short on performance (but only for updates) and
+on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT
+kernels. The definitions of rcu_dereference() and rcu_assign_pointer()
+are the same as those shown in the preceding section, so they are omitted.
+
+ void rcu_read_lock(void) { }
+
+ void rcu_read_unlock(void) { }
+
+ void synchronize_rcu(void)
+ {
+ int cpu;
+
+ for_each_cpu(cpu)
+ run_on(cpu);
+ }
+
+Note that rcu_read_lock() and rcu_read_unlock() do absolutely nothing.
+This is the great strength of classic RCU in a non-preemptive kernel:
+read-side overhead is precisely zero, at least on non-Alpha CPUs.
+And there is absolutely no way that rcu_read_lock() can possibly
+participate in a deadlock cycle!
+
+The implementation of synchronize_rcu() simply schedules itself on each
+CPU in turn. The run_on() primitive can be implemented straightforwardly
+in terms of the sched_setaffinity() primitive. Of course, a somewhat less
+"toy" implementation would restore the affinity upon completion rather
+than just leaving all tasks running on the last CPU, but when I said
+"toy", I meant -toy-!
+
+So how the heck is this supposed to work???
+
+Remember that it is illegal to block while in an RCU read-side critical
+section. Therefore, if a given CPU executes a context switch, we know
+that it must have completed all preceding RCU read-side critical sections.
+Once -all- CPUs have executed a context switch, then -all- preceding
+RCU read-side critical sections will have completed.
+
+So, suppose that we remove a data item from its structure and then invoke
+synchronize_rcu(). Once synchronize_rcu() returns, we are guaranteed
+that there are no RCU read-side critical sections holding a reference
+to that data item, so we can safely reclaim it.
+
+Quick Quiz #2: Give an example where Classic RCU's read-side
+ overhead is -negative-.
+
+Quick Quiz #3: If it is illegal to block in an RCU read-side
+ critical section, what the heck do you do in
+ PREEMPT_RT, where normal spinlocks can block???
+
+
+6. ANALOGY WITH READER-WRITER LOCKING
+
+Although RCU can be used in many different ways, a very common use of
+RCU is analogous to reader-writer locking. The following unified
+diff shows how closely related RCU and reader-writer locking can be.
+
+ @@ -13,15 +14,15 @@
+ struct list_head *lp;
+ struct el *p;
+
+ - read_lock();
+ - list_for_each_entry(p, head, lp) {
+ + rcu_read_lock();
+ + list_for_each_entry_rcu(p, head, lp) {
+ if (p->key == key) {
+ *result = p->data;
+ - read_unlock();
+ + rcu_read_unlock();
+ return 1;
+ }
+ }
+ - read_unlock();
+ + rcu_read_unlock();
+ return 0;
+ }
+
+ @@ -29,15 +30,16 @@
+ {
+ struct el *p;
+
+ - write_lock(&listmutex);
+ + spin_lock(&listmutex);
+ list_for_each_entry(p, head, lp) {
+ if (p->key == key) {
+ list_del(&p->list);
+ - write_unlock(&listmutex);
+ + spin_unlock(&listmutex);
+ + synchronize_rcu();
+ kfree(p);
+ return 1;
+ }
+ }
+ - write_unlock(&listmutex);
+ + spin_unlock(&listmutex);
+ return 0;
+ }
+
+Or, for those who prefer a side-by-side listing:
+
+ 1 struct el { 1 struct el {
+ 2 struct list_head list; 2 struct list_head list;
+ 3 long key; 3 long key;
+ 4 spinlock_t mutex; 4 spinlock_t mutex;
+ 5 int data; 5 int data;
+ 6 /* Other data fields */ 6 /* Other data fields */
+ 7 }; 7 };
+ 8 spinlock_t listmutex; 8 spinlock_t listmutex;
+ 9 struct el head; 9 struct el head;
+
+ 1 int search(long key, int *result) 1 int search(long key, int *result)
+ 2 { 2 {
+ 3 struct list_head *lp; 3 struct list_head *lp;
+ 4 struct el *p; 4 struct el *p;
+ 5 5
+ 6 read_lock(); 6 rcu_read_lock();
+ 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, head, lp) {
+ 8 if (p->key == key) { 8 if (p->key == key) {
+ 9 *result = p->data; 9 *result = p->data;
+10 read_unlock(); 10 rcu_read_unlock();
+11 return 1; 11 return 1;
+12 } 12 }
+13 } 13 }
+14 read_unlock(); 14 rcu_read_unlock();
+15 return 0; 15 return 0;
+16 } 16 }
+
+ 1 int delete(long key) 1 int delete(long key)
+ 2 { 2 {
+ 3 struct el *p; 3 struct el *p;
+ 4 4
+ 5 write_lock(&listmutex); 5 spin_lock(&listmutex);
+ 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, lp) {
+ 7 if (p->key == key) { 7 if (p->key == key) {
+ 8 list_del(&p->list); 8 list_del(&p->list);
+ 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex);
+ 10 synchronize_rcu();
+10 kfree(p); 11 kfree(p);
+11 return 1; 12 return 1;
+12 } 13 }
+13 } 14 }
+14 write_unlock(&listmutex); 15 spin_unlock(&listmutex);
+15 return 0; 16 return 0;
+16 } 17 }
+
+Either way, the differences are quite small. Read-side locking moves
+to rcu_read_lock() and rcu_read_unlock, update-side locking moves from
+from a reader-writer lock to a simple spinlock, and a synchronize_rcu()
+precedes the kfree().
+
+However, there is one potential catch: the read-side and update-side
+critical sections can now run concurrently. In many cases, this will
+not be a problem, but it is necessary to check carefully regardless.
+For example, if multiple independent list updates must be seen as
+a single atomic update, converting to RCU will require special care.
+
+Also, the presence of synchronize_rcu() means that the RCU version of
+delete() can now block. If this is a problem, there is a callback-based
+mechanism that never blocks, namely call_rcu(), that can be used in
+place of synchronize_rcu().
+
+
+7. FULL LIST OF RCU APIs
+
+The RCU APIs are documented in docbook-format header comments in the
+Linux-kernel source code, but it helps to have a full list of the
+APIs, since there does not appear to be a way to categorize them
+in docbook. Here is the list, by category.
+
+Markers for RCU read-side critical sections:
+
+ rcu_read_lock
+ rcu_read_unlock
+ rcu_read_lock_bh
+ rcu_read_unlock_bh
+
+RCU pointer/list traversal:
+
+ rcu_dereference
+ list_for_each_rcu (to be deprecated in favor of
+ list_for_each_entry_rcu)
+ list_for_each_safe_rcu (deprecated, not used)
+ list_for_each_entry_rcu
+ list_for_each_continue_rcu (to be deprecated in favor of new
+ list_for_each_entry_continue_rcu)
+ hlist_for_each_rcu (to be deprecated in favor of
+ hlist_for_each_entry_rcu)
+ hlist_for_each_entry_rcu
+
+RCU pointer update:
+
+ rcu_assign_pointer
+ list_add_rcu
+ list_add_tail_rcu
+ list_del_rcu
+ list_replace_rcu
+ hlist_del_rcu
+ hlist_add_head_rcu
+
+RCU grace period:
+
+ synchronize_kernel (deprecated)
+ synchronize_net
+ synchronize_sched
+ synchronize_rcu
+ call_rcu
+ call_rcu_bh
+
+See the comment headers in the source code (or the docbook generated
+from them) for more information.
+
+
+8. ANSWERS TO QUICK QUIZZES
+
+Quick Quiz #1: Why is this argument naive? How could a deadlock
+ occur when using this algorithm in a real-world Linux
+ kernel? [Referring to the lock-based "toy" RCU
+ algorithm.]
+
+Answer: Consider the following sequence of events:
+
+ 1. CPU 0 acquires some unrelated lock, call it
+ "problematic_lock".
+
+ 2. CPU 1 enters synchronize_rcu(), write-acquiring
+ rcu_gp_mutex.
+
+ 3. CPU 0 enters rcu_read_lock(), but must wait
+ because CPU 1 holds rcu_gp_mutex.
+
+ 4. CPU 1 is interrupted, and the irq handler
+ attempts to acquire problematic_lock.
+
+ The system is now deadlocked.
+
+ One way to avoid this deadlock is to use an approach like
+ that of CONFIG_PREEMPT_RT, where all normal spinlocks
+ become blocking locks, and all irq handlers execute in
+ the context of special tasks. In this case, in step 4
+ above, the irq handler would block, allowing CPU 1 to
+ release rcu_gp_mutex, avoiding the deadlock.
+
+ Even in the absence of deadlock, this RCU implementation
+ allows latency to "bleed" from readers to other
+ readers through synchronize_rcu(). To see this,
+ consider task A in an RCU read-side critical section
+ (thus read-holding rcu_gp_mutex), task B blocked
+ attempting to write-acquire rcu_gp_mutex, and
+ task C blocked in rcu_read_lock() attempting to
+ read_acquire rcu_gp_mutex. Task A's RCU read-side
+ latency is holding up task C, albeit indirectly via
+ task B.
+
+ Realtime RCU implementations therefore use a counter-based
+ approach where tasks in RCU read-side critical sections
+ cannot be blocked by tasks executing synchronize_rcu().
+
+Quick Quiz #2: Give an example where Classic RCU's read-side
+ overhead is -negative-.
+
+Answer: Imagine a single-CPU system with a non-CONFIG_PREEMPT
+ kernel where a routing table is used by process-context
+ code, but can be updated by irq-context code (for example,
+ by an "ICMP REDIRECT" packet). The usual way of handling
+ this would be to have the process-context code disable
+ interrupts while searching the routing table. Use of
+ RCU allows such interrupt-disabling to be dispensed with.
+ Thus, without RCU, you pay the cost of disabling interrupts,
+ and with RCU you don't.
+
+ One can argue that the overhead of RCU in this
+ case is negative with respect to the single-CPU
+ interrupt-disabling approach. Others might argue that
+ the overhead of RCU is merely zero, and that replacing
+ the positive overhead of the interrupt-disabling scheme
+ with the zero-overhead RCU scheme does not constitute
+ negative overhead.
+
+ In real life, of course, things are more complex. But
+ even the theoretical possibility of negative overhead for
+ a synchronization primitive is a bit unexpected. ;-)
+
+Quick Quiz #3: If it is illegal to block in an RCU read-side
+ critical section, what the heck do you do in
+ PREEMPT_RT, where normal spinlocks can block???
+
+Answer: Just as PREEMPT_RT permits preemption of spinlock
+ critical sections, it permits preemption of RCU
+ read-side critical sections. It also permits
+ spinlocks blocking while in RCU read-side critical
+ sections.
+
+ Why the apparent inconsistency? Because it is it
+ possible to use priority boosting to keep the RCU
+ grace periods short if need be (for example, if running
+ short of memory). In contrast, if blocking waiting
+ for (say) network reception, there is no way to know
+ what should be boosted. Especially given that the
+ process we need to boost might well be a human being
+ who just went out for a pizza or something. And although
+ a computer-operated cattle prod might arouse serious
+ interest, it might also provoke serious objections.
+ Besides, how does the computer know what pizza parlor
+ the human being went to???
+
+
+ACKNOWLEDGEMENTS
+
+My thanks to the people who helped make this human-readable, including
+Jon Walpole, Josh Triplett, Serge Hallyn, and Suzanne Wood.
+
+
+For more information, see http://www.rdrop.com/users/paulmck/RCU.
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
index 0acdc80c30c2..744f1aec6553 100644
--- a/Documentation/acpi-hotkey.txt
+++ b/Documentation/acpi-hotkey.txt
@@ -35,4 +35,4 @@ created. Please use command "cat /proc/acpi/hotkey/polling_method"
to retrieve it.
Note: Use cmdline "acpi_generic_hotkey" to over-ride
-loading any platform specific drivers.
+platform-specific with generic driver.
diff --git a/Documentation/aoe/mkshelf.sh b/Documentation/aoe/mkshelf.sh
index 8bacf9f2c7cc..32615814271c 100644
--- a/Documentation/aoe/mkshelf.sh
+++ b/Documentation/aoe/mkshelf.sh
@@ -8,13 +8,15 @@ fi
n_partitions=${n_partitions:-16}
dir=$1
shelf=$2
+nslots=16
+maxslot=`echo $nslots 1 - p | dc`
MAJOR=152
set -e
-minor=`echo 10 \* $shelf \* $n_partitions | bc`
+minor=`echo $nslots \* $shelf \* $n_partitions | bc`
endp=`echo $n_partitions - 1 | bc`
-for slot in `seq 0 9`; do
+for slot in `seq 0 $maxslot`; do
for part in `seq 0 $endp`; do
name=e$shelf.$slot
test "$part" != "0" && name=${name}p$part
diff --git a/Documentation/applying-patches.txt b/Documentation/applying-patches.txt
new file mode 100644
index 000000000000..681e426e2482
--- /dev/null
+++ b/Documentation/applying-patches.txt
@@ -0,0 +1,439 @@
+
+ Applying Patches To The Linux Kernel
+ ------------------------------------
+
+ (Written by Jesper Juhl, August 2005)
+
+
+
+A frequently asked question on the Linux Kernel Mailing List is how to apply
+a patch to the kernel or, more specifically, what base kernel a patch for
+one of the many trees/branches should be applied to. Hopefully this document
+will explain this to you.
+
+In addition to explaining how to apply and revert patches, a brief
+description of the different kernel trees (and examples of how to apply
+their specific patches) is also provided.
+
+
+What is a patch?
+---
+ A patch is a small text document containing a delta of changes between two
+different versions of a source tree. Patches are created with the `diff'
+program.
+To correctly apply a patch you need to know what base it was generated from
+and what new version the patch will change the source tree into. These
+should both be present in the patch file metadata or be possible to deduce
+from the filename.
+
+
+How do I apply or revert a patch?
+---
+ You apply a patch with the `patch' program. The patch program reads a diff
+(or patch) file and makes the changes to the source tree described in it.
+
+Patches for the Linux kernel are generated relative to the parent directory
+holding the kernel source dir.
+
+This means that paths to files inside the patch file contain the name of the
+kernel source directories it was generated against (or some other directory
+names like "a/" and "b/").
+Since this is unlikely to match the name of the kernel source dir on your
+local machine (but is often useful info to see what version an otherwise
+unlabeled patch was generated against) you should change into your kernel
+source directory and then strip the first element of the path from filenames
+in the patch file when applying it (the -p1 argument to `patch' does this).
+
+To revert a previously applied patch, use the -R argument to patch.
+So, if you applied a patch like this:
+ patch -p1 < ../patch-x.y.z
+
+You can revert (undo) it like this:
+ patch -R -p1 < ../patch-x.y.z
+
+
+How do I feed a patch/diff file to `patch'?
+---
+ This (as usual with Linux and other UNIX like operating systems) can be
+done in several different ways.
+In all the examples below I feed the file (in uncompressed form) to patch
+via stdin using the following syntax:
+ patch -p1 < path/to/patch-x.y.z
+
+If you just want to be able to follow the examples below and don't want to
+know of more than one way to use patch, then you can stop reading this
+section here.
+
+Patch can also get the name of the file to use via the -i argument, like
+this:
+ patch -p1 -i path/to/patch-x.y.z
+
+If your patch file is compressed with gzip or bzip2 and you don't want to
+uncompress it before applying it, then you can feed it to patch like this
+instead:
+ zcat path/to/patch-x.y.z.gz | patch -p1
+ bzcat path/to/patch-x.y.z.bz2 | patch -p1
+
+If you wish to uncompress the patch file by hand first before applying it
+(what I assume you've done in the examples below), then you simply run
+gunzip or bunzip2 on the file - like this:
+ gunzip patch-x.y.z.gz
+ bunzip2 patch-x.y.z.bz2
+
+Which will leave you with a plain text patch-x.y.z file that you can feed to
+patch via stdin or the -i argument, as you prefer.
+
+A few other nice arguments for patch are -s which causes patch to be silent
+except for errors which is nice to prevent errors from scrolling out of the
+screen too fast, and --dry-run which causes patch to just print a listing of
+what would happen, but doesn't actually make any changes. Finally --verbose
+tells patch to print more information about the work being done.
+
+
+Common errors when patching
+---
+ When patch applies a patch file it attempts to verify the sanity of the
+file in different ways.
+Checking that the file looks like a valid patch file, checking the code
+around the bits being modified matches the context provided in the patch are
+just two of the basic sanity checks patch does.
+
+If patch encounters something that doesn't look quite right it has two
+options. It can either refuse to apply the changes and abort or it can try
+to find a way to make the patch apply with a few minor changes.
+
+One example of something that's not 'quite right' that patch will attempt to
+fix up is if all the context matches, the lines being changed match, but the
+line numbers are different. This can happen, for example, if the patch makes
+a change in the middle of the file but for some reasons a few lines have
+been added or removed near the beginning of the file. In that case
+everything looks good it has just moved up or down a bit, and patch will
+usually adjust the line numbers and apply the patch.
+
+Whenever patch applies a patch that it had to modify a bit to make it fit
+it'll tell you about it by saying the patch applied with 'fuzz'.
+You should be wary of such changes since even though patch probably got it
+right it doesn't /always/ get it right, and the result will sometimes be
+wrong.
+
+When patch encounters a change that it can't fix up with fuzz it rejects it
+outright and leaves a file with a .rej extension (a reject file). You can
+read this file to see exactely what change couldn't be applied, so you can
+go fix it up by hand if you wish.
+
+If you don't have any third party patches applied to your kernel source, but
+only patches from kernel.org and you apply the patches in the correct order,
+and have made no modifications yourself to the source files, then you should
+never see a fuzz or reject message from patch. If you do see such messages
+anyway, then there's a high risk that either your local source tree or the
+patch file is corrupted in some way. In that case you should probably try
+redownloading the patch and if things are still not OK then you'd be advised
+to start with a fresh tree downloaded in full from kernel.org.
+
+Let's look a bit more at some of the messages patch can produce.
+
+If patch stops and presents a "File to patch:" prompt, then patch could not
+find a file to be patched. Most likely you forgot to specify -p1 or you are
+in the wrong directory. Less often, you'll find patches that need to be
+applied with -p0 instead of -p1 (reading the patch file should reveal if
+this is the case - if so, then this is an error by the person who created
+the patch but is not fatal).
+
+If you get "Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines)." or a
+message similar to that, then it means that patch had to adjust the location
+of the change (in this example it needed to move 7 lines from where it
+expected to make the change to make it fit).
+The resulting file may or may not be OK, depending on the reason the file
+was different than expected.
+This often happens if you try to apply a patch that was generated against a
+different kernel version than the one you are trying to patch.
+
+If you get a message like "Hunk #3 FAILED at 2387.", then it means that the
+patch could not be applied correctly and the patch program was unable to
+fuzz its way through. This will generate a .rej file with the change that
+caused the patch to fail and also a .orig file showing you the original
+content that couldn't be changed.
+
+If you get "Reversed (or previously applied) patch detected! Assume -R? [n]"
+then patch detected that the change contained in the patch seems to have
+already been made.
+If you actually did apply this patch previously and you just re-applied it
+in error, then just say [n]o and abort this patch. If you applied this patch
+previously and actually intended to revert it, but forgot to specify -R,
+then you can say [y]es here to make patch revert it for you.
+This can also happen if the creator of the patch reversed the source and
+destination directories when creating the patch, and in that case reverting
+the patch will in fact apply it.
+
+A message similar to "patch: **** unexpected end of file in patch" or "patch
+unexpectedly ends in middle of line" means that patch could make no sense of
+the file you fed to it. Either your download is broken or you tried to feed
+patch a compressed patch file without uncompressing it first.
+
+As I already mentioned above, these errors should never happen if you apply
+a patch from kernel.org to the correct version of an unmodified source tree.
+So if you get these errors with kernel.org patches then you should probably
+assume that either your patch file or your tree is broken and I'd advice you
+to start over with a fresh download of a full kernel tree and the patch you
+wish to apply.
+
+
+Are there any alternatives to `patch'?
+---
+ Yes there are alternatives. You can use the `interdiff' program
+(http://cyberelk.net/tim/patchutils/) to generate a patch representing the
+differences between two patches and then apply the result.
+This will let you move from something like 2.6.12.2 to 2.6.12.3 in a single
+step. The -z flag to interdiff will even let you feed it patches in gzip or
+bzip2 compressed form directly without the use of zcat or bzcat or manual
+decompression.
+
+Here's how you'd go from 2.6.12.2 to 2.6.12.3 in a single step:
+ interdiff -z ../patch-2.6.12.2.bz2 ../patch-2.6.12.3.gz | patch -p1
+
+Although interdiff may save you a step or two you are generally advised to
+do the additional steps since interdiff can get things wrong in some cases.
+
+ Another alternative is `ketchup', which is a python script for automatic
+downloading and applying of patches (http://www.selenic.com/ketchup/).
+
+Other nice tools are diffstat which shows a summary of changes made by a
+patch, lsdiff which displays a short listing of affected files in a patch
+file, along with (optionally) the line numbers of the start of each patch
+and grepdiff which displays a list of the files modified by a patch where
+the patch contains a given regular expression.
+
+
+Where can I download the patches?
+---
+ The patches are available at http://kernel.org/
+Most recent patches are linked from the front page, but they also have
+specific homes.
+
+The 2.6.x.y (-stable) and 2.6.x patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
+
+The -rc patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/testing/
+
+The -git patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/snapshots/
+
+The -mm kernels live at
+ ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/
+
+In place of ftp.kernel.org you can use ftp.cc.kernel.org, where cc is a
+country code. This way you'll be downloading from a mirror site that's most
+likely geographically closer to you, resulting in faster downloads for you,
+less bandwidth used globally and less load on the main kernel.org servers -
+these are good things, do use mirrors when possible.
+
+
+The 2.6.x kernels
+---
+ These are the base stable releases released by Linus. The highest numbered
+release is the most recent.
+
+If regressions or other serious flaws are found then a -stable fix patch
+will be released (see below) on top of this base. Once a new 2.6.x base
+kernel is released, a patch is made available that is a delta between the
+previous 2.6.x kernel and the new one.
+
+To apply a patch moving from 2.6.11 to 2.6.12 you'd do the following (note
+that such patches do *NOT* apply on top of 2.6.x.y kernels but on top of the
+base 2.6.x kernel - if you need to move from 2.6.x.y to 2.6.x+1 you need to
+first revert the 2.6.x.y patch).
+
+Here are some examples:
+
+# moving from 2.6.11 to 2.6.12
+$ cd ~/linux-2.6.11 # change to kernel source dir
+$ patch -p1 < ../patch-2.6.12 # apply the 2.6.12 patch
+$ cd ..
+$ mv linux-2.6.11 linux-2.6.12 # rename source dir
+
+# moving from 2.6.11.1 to 2.6.12
+$ cd ~/linux-2.6.11.1 # change to kernel source dir
+$ patch -p1 -R < ../patch-2.6.11.1 # revert the 2.6.11.1 patch
+ # source dir is now 2.6.11
+$ patch -p1 < ../patch-2.6.12 # apply new 2.6.12 patch
+$ cd ..
+$ mv linux-2.6.11.1 inux-2.6.12 # rename source dir
+
+
+The 2.6.x.y kernels
+---
+ Kernels with 4 digit versions are -stable kernels. They contain small(ish)
+critical fixes for security problems or significant regressions discovered
+in a given 2.6.x kernel.
+
+This is the recommended branch for users who want the most recent stable
+kernel and are not interested in helping test development/experimental
+versions.
+
+If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is
+the current stable kernel.
+
+These patches are not incremental, meaning that for example the 2.6.12.3
+patch does not apply on top of the 2.6.12.2 kernel source, but rather on top
+of the base 2.6.12 kernel source.
+So, in order to apply the 2.6.12.3 patch to your existing 2.6.12.2 kernel
+source you have to first back out the 2.6.12.2 patch (so you are left with a
+base 2.6.12 kernel source) and then apply the new 2.6.12.3 patch.
+
+Here's a small example:
+
+$ cd ~/linux-2.6.12.2 # change into the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12.2 # revert the 2.6.12.2 patch
+$ patch -p1 < ../patch-2.6.12.3 # apply the new 2.6.12.3 patch
+$ cd ..
+$ mv linux-2.6.12.2 linux-2.6.12.3 # rename the kernel source dir
+
+
+The -rc kernels
+---
+ These are release-candidate kernels. These are development kernels released
+by Linus whenever he deems the current git (the kernel's source management
+tool) tree to be in a reasonably sane state adequate for testing.
+
+These kernels are not stable and you should expect occasional breakage if
+you intend to run them. This is however the most stable of the main
+development branches and is also what will eventually turn into the next
+stable kernel, so it is important that it be tested by as many people as
+possible.
+
+This is a good branch to run for people who want to help out testing
+development kernels but do not want to run some of the really experimental
+stuff (such people should see the sections about -git and -mm kernels below).
+
+The -rc patches are not incremental, they apply to a base 2.6.x kernel, just
+like the 2.6.x.y patches described above. The kernel version before the -rcN
+suffix denotes the version of the kernel that this -rc kernel will eventually
+turn into.
+So, 2.6.13-rc5 means that this is the fifth release candidate for the 2.6.13
+kernel and the patch should be applied on top of the 2.6.12 kernel source.
+
+Here are 3 examples of how to apply these patches:
+
+# first an example of moving from 2.6.12 to 2.6.13-rc3
+$ cd ~/linux-2.6.12 # change into the 2.6.12 source dir
+$ patch -p1 < ../patch-2.6.13-rc3 # apply the 2.6.13-rc3 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.13-rc3 # rename the source dir
+
+# now let's move from 2.6.13-rc3 to 2.6.13-rc5
+$ cd ~/linux-2.6.13-rc3 # change into the 2.6.13-rc3 dir
+$ patch -p1 -R < ../patch-2.6.13-rc3 # revert the 2.6.13-rc3 patch
+$ patch -p1 < ../patch-2.6.13-rc5 # apply the new 2.6.13-rc5 patch
+$ cd ..
+$ mv linux-2.6.13-rc3 linux-2.6.13-rc5 # rename the source dir
+
+# finally let's try and move from 2.6.12.3 to 2.6.13-rc5
+$ cd ~/linux-2.6.12.3 # change to the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12.3 # revert the 2.6.12.3 patch
+$ patch -p1 < ../patch-2.6.13-rc5 # apply new 2.6.13-rc5 patch
+$ cd ..
+$ mv linux-2.6.12.3 linux-2.6.13-rc5 # rename the kernel source dir
+
+
+The -git kernels
+---
+ These are daily snapshots of Linus' kernel tree (managed in a git
+repository, hence the name).
+
+These patches are usually released daily and represent the current state of
+Linus' tree. They are more experimental than -rc kernels since they are
+generated automatically without even a cursory glance to see if they are
+sane.
+
+-git patches are not incremental and apply either to a base 2.6.x kernel or
+a base 2.6.x-rc kernel - you can see which from their name.
+A patch named 2.6.12-git1 applies to the 2.6.12 kernel source and a patch
+named 2.6.13-rc3-git2 applies to the source of the 2.6.13-rc3 kernel.
+
+Here are some examples of how to apply these patches:
+
+# moving from 2.6.12 to 2.6.12-git1
+$ cd ~/linux-2.6.12 # change to the kernel source dir
+$ patch -p1 < ../patch-2.6.12-git1 # apply the 2.6.12-git1 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.12-git1 # rename the kernel source dir
+
+# moving from 2.6.12-git1 to 2.6.13-rc2-git3
+$ cd ~/linux-2.6.12-git1 # change to the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12-git1 # revert the 2.6.12-git1 patch
+ # we now have a 2.6.12 kernel
+$ patch -p1 < ../patch-2.6.13-rc2 # apply the 2.6.13-rc2 patch
+ # the kernel is now 2.6.13-rc2
+$ patch -p1 < ../patch-2.6.13-rc2-git3 # apply the 2.6.13-rc2-git3 patch
+ # the kernel is now 2.6.13-rc2-git3
+$ cd ..
+$ mv linux-2.6.12-git1 linux-2.6.13-rc2-git3 # rename source dir
+
+
+The -mm kernels
+---
+ These are experimental kernels released by Andrew Morton.
+
+The -mm tree serves as a sort of proving ground for new features and other
+experimental patches.
+Once a patch has proved its worth in -mm for a while Andrew pushes it on to
+Linus for inclusion in mainline.
+
+Although it's encouraged that patches flow to Linus via the -mm tree, this
+is not always enforced.
+Subsystem maintainers (or individuals) sometimes push their patches directly
+to Linus, even though (or after) they have been merged and tested in -mm (or
+sometimes even without prior testing in -mm).
+
+You should generally strive to get your patches into mainline via -mm to
+ensure maximum testing.
+
+This branch is in constant flux and contains many experimental features, a
+lot of debugging patches not appropriate for mainline etc and is the most
+experimental of the branches described in this document.
+
+These kernels are not appropriate for use on systems that are supposed to be
+stable and they are more risky to run than any of the other branches (make
+sure you have up-to-date backups - that goes for any experimental kernel but
+even more so for -mm kernels).
+
+These kernels in addition to all the other experimental patches they contain
+usually also contain any changes in the mainline -git kernels available at
+the time of release.
+
+Testing of -mm kernels is greatly appreciated since the whole point of the
+tree is to weed out regressions, crashes, data corruption bugs, build
+breakage (and any other bug in general) before changes are merged into the
+more stable mainline Linus tree.
+But testers of -mm should be aware that breakage in this tree is more common
+than in any other tree.
+
+The -mm kernels are not released on a fixed schedule, but usually a few -mm
+kernels are released in between each -rc kernel (1 to 3 is common).
+The -mm kernels apply to either a base 2.6.x kernel (when no -rc kernels
+have been released yet) or to a Linus -rc kernel.
+
+Here are some examples of applying the -mm patches:
+
+# moving from 2.6.12 to 2.6.12-mm1
+$ cd ~/linux-2.6.12 # change to the 2.6.12 source dir
+$ patch -p1 < ../2.6.12-mm1 # apply the 2.6.12-mm1 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.12-mm1 # rename the source appropriately
+
+# moving from 2.6.12-mm1 to 2.6.13-rc3-mm3
+$ cd ~/linux-2.6.12-mm1
+$ patch -p1 -R < ../2.6.12-mm1 # revert the 2.6.12-mm1 patch
+ # we now have a 2.6.12 source
+$ patch -p1 < ../patch-2.6.13-rc3 # apply the 2.6.13-rc3 patch
+ # we now have a 2.6.13-rc3 source
+$ patch -p1 < ../2.6.13-rc3-mm3 # apply the 2.6.13-rc3-mm3 patch
+$ cd ..
+$ mv linux-2.6.12-mm1 linux-2.6.13-rc3-mm3 # rename the source dir
+
+
+This concludes this list of explanations of the various kernel trees and I
+hope you are now crystal clear on how to apply the various patches and help
+testing the kernel.
+
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index c8f9a73111da..68a711fb82cf 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -17,7 +17,9 @@ This driver is known to work with the following cards:
* SA P600
* SA P800
* SA E400
- * SA E300
+ * SA P400i
+ * SA E200
+ * SA E200i
If nodes are not already created in the /dev/cciss directory, run as root:
diff --git a/Documentation/cdrom/sonycd535 b/Documentation/cdrom/sonycd535
index 59581a4b302a..b81e109970aa 100644
--- a/Documentation/cdrom/sonycd535
+++ b/Documentation/cdrom/sonycd535
@@ -68,7 +68,8 @@ it a better device citizen. Further thanks to Joel Katz
Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
to make the driver work with the older CDU-510/515 series, and
Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
-the verify_area() checks were ignoring the results of said checks.
+the verify_area() checks were ignoring the results of said checks
+(note: verify_area() has since been replaced by access_ok()).
(Acknowledgments from Ron Jeppesen in the 0.3 release:)
Thanks to Corey Minyard who wrote the original CDU-31A driver on which
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
new file mode 100644
index 000000000000..b7de82e9c0e0
--- /dev/null
+++ b/Documentation/connector/cn_test.c
@@ -0,0 +1,194 @@
+/*
+ * cn_test.c
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+
+#include "connector.h"
+
+static struct cb_id cn_test_id = { 0x123, 0x456 };
+static char cn_test_name[] = "cn_test";
+static struct sock *nls;
+static struct timer_list cn_test_timer;
+
+void cn_test_callback(void *data)
+{
+ struct cn_msg *msg = (struct cn_msg *)data;
+
+ printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
+ __func__, jiffies, msg->id.idx, msg->id.val,
+ msg->seq, msg->ack, msg->len, (char *)msg->data);
+}
+
+static int cn_test_want_notify(void)
+{
+ struct cn_ctl_msg *ctl;
+ struct cn_notify_req *req;
+ struct cn_msg *msg = NULL;
+ int size, size0;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ u32 group = 1;
+
+ size0 = sizeof(*msg) + sizeof(*ctl) + 3 * sizeof(*req);
+
+ size = NLMSG_SPACE(size0);
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",
+ size);
+
+ return -ENOMEM;
+ }
+
+ nlh = NLMSG_PUT(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh));
+
+ msg = (struct cn_msg *)NLMSG_DATA(nlh);
+
+ memset(msg, 0, size0);
+
+ msg->id.idx = -1;
+ msg->id.val = -1;
+ msg->seq = 0x123;
+ msg->ack = 0x345;
+ msg->len = size0 - sizeof(*msg);
+
+ ctl = (struct cn_ctl_msg *)(msg + 1);
+
+ ctl->idx_notify_num = 1;
+ ctl->val_notify_num = 2;
+ ctl->group = group;
+ ctl->len = msg->len - sizeof(*ctl);
+
+ req = (struct cn_notify_req *)(ctl + 1);
+
+ /*
+ * Idx.
+ */
+ req->first = cn_test_id.idx;
+ req->range = 10;
+
+ /*
+ * Val 0.
+ */
+ req++;
+ req->first = cn_test_id.val;
+ req->range = 10;
+
+ /*
+ * Val 1.
+ */
+ req++;
+ req->first = cn_test_id.val + 20;
+ req->range = 10;
+
+ NETLINK_CB(skb).dst_groups = ctl->group;
+ //netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
+ netlink_unicast(nls, skb, 0, 0);
+
+ printk(KERN_INFO "Request was sent. Group=0x%x.\n", ctl->group);
+
+ return 0;
+
+nlmsg_failure:
+ printk(KERN_ERR "Failed to send %u.%u\n", msg->seq, msg->ack);
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+static u32 cn_test_timer_counter;
+static void cn_test_timer_func(unsigned long __data)
+{
+ struct cn_msg *m;
+ char data[32];
+
+ m = kmalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
+ if (m) {
+ memset(m, 0, sizeof(*m) + sizeof(data));
+
+ memcpy(&m->id, &cn_test_id, sizeof(m->id));
+ m->seq = cn_test_timer_counter;
+ m->len = sizeof(data);
+
+ m->len =
+ scnprintf(data, sizeof(data), "counter = %u",
+ cn_test_timer_counter) + 1;
+
+ memcpy(m + 1, data, m->len);
+
+ cn_netlink_send(m, 0, gfp_any());
+ kfree(m);
+ }
+
+ cn_test_timer_counter++;
+
+ mod_timer(&cn_test_timer, jiffies + HZ);
+}
+
+static int cn_test_init(void)
+{
+ int err;
+
+ err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
+ if (err)
+ goto err_out;
+ cn_test_id.val++;
+ err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
+ if (err) {
+ cn_del_callback(&cn_test_id);
+ goto err_out;
+ }
+
+ init_timer(&cn_test_timer);
+ cn_test_timer.function = cn_test_timer_func;
+ cn_test_timer.expires = jiffies + HZ;
+ cn_test_timer.data = 0;
+ add_timer(&cn_test_timer);
+
+ return 0;
+
+ err_out:
+ if (nls && nls->sk_socket)
+ sock_release(nls->sk_socket);
+
+ return err;
+}
+
+static void cn_test_fini(void)
+{
+ del_timer_sync(&cn_test_timer);
+ cn_del_callback(&cn_test_id);
+ cn_test_id.val--;
+ cn_del_callback(&cn_test_id);
+ if (nls && nls->sk_socket)
+ sock_release(nls->sk_socket);
+}
+
+module_init(cn_test_init);
+module_exit(cn_test_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Connector's test module");
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
new file mode 100644
index 000000000000..54a0a14bfbe3
--- /dev/null
+++ b/Documentation/connector/connector.txt
@@ -0,0 +1,133 @@
+/*****************************************/
+Kernel Connector.
+/*****************************************/
+
+Kernel connector - new netlink based userspace <-> kernel space easy
+to use communication module.
+
+Connector driver adds possibility to connect various agents using
+netlink based network. One must register callback and
+identifier. When driver receives special netlink message with
+appropriate identifier, appropriate callback will be called.
+
+From the userspace point of view it's quite straightforward:
+
+ socket();
+ bind();
+ send();
+ recv();
+
+But if kernelspace want to use full power of such connections, driver
+writer must create special sockets, must know about struct sk_buff
+handling... Connector allows any kernelspace agents to use netlink
+based networking for inter-process communication in a significantly
+easier way:
+
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
+void cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask);
+
+struct cb_id
+{
+ __u32 idx;
+ __u32 val;
+};
+
+idx and val are unique identifiers which must be registered in
+connector.h for in-kernel usage. void (*callback) (void *) - is a
+callback function which will be called when message with above idx.val
+will be received by connector core. Argument for that function must
+be dereferenced to struct cn_msg *.
+
+struct cn_msg
+{
+ struct cb_id id;
+
+ __u32 seq;
+ __u32 ack;
+
+ __u32 len; /* Length of the following data */
+ __u8 data[0];
+};
+
+/*****************************************/
+Connector interfaces.
+/*****************************************/
+
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
+
+Registers new callback with connector core.
+
+struct cb_id *id - unique connector's user identifier.
+ It must be registered in connector.h for legal in-kernel users.
+char *name - connector's callback symbolic name.
+void (*callback) (void *) - connector's callback.
+ Argument must be dereferenced to struct cn_msg *.
+
+void cn_del_callback(struct cb_id *id);
+
+Unregisters new callback with connector core.
+
+struct cb_id *id - unique connector's user identifier.
+
+void cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
+
+Sends message to the specified groups. It can be safely called from
+any context, but may silently fail under strong memory pressure.
+
+struct cn_msg * - message header(with attached data).
+u32 __group - destination group.
+ If __group is zero, then appropriate group will
+ be searched through all registered connector users,
+ and message will be delivered to the group which was
+ created for user with the same ID as in msg.
+ If __group is not zero, then message will be delivered
+ to the specified group.
+int gfp_mask - GFP mask.
+
+Note: When registering new callback user, connector core assigns
+netlink group to the user which is equal to it's id.idx.
+
+/*****************************************/
+Protocol description.
+/*****************************************/
+
+Current offers transport layer with fixed header. Recommended
+protocol which uses such header is following:
+
+msg->seq and msg->ack are used to determine message genealogy. When
+someone sends message it puts there locally unique sequence and random
+acknowledge numbers. Sequence number may be copied into
+nlmsghdr->nlmsg_seq too.
+
+Sequence number is incremented with each message to be sent.
+
+If we expect reply to our message, then sequence number in received
+message MUST be the same as in original message, and acknowledge
+number MUST be the same + 1.
+
+If we receive message and it's sequence number is not equal to one we
+are expecting, then it is new message. If we receive message and it's
+sequence number is the same as one we are expecting, but it's
+acknowledge is not equal acknowledge number in original message + 1,
+then it is new message.
+
+Obviously, protocol header contains above id.
+
+connector allows event notification in the following form: kernel
+driver or userspace process can ask connector to notify it when
+selected id's will be turned on or off(registered or unregistered it's
+callback). It is done by sending special command to connector
+driver(it also registers itself with id={-1, -1}).
+
+As example of usage Documentation/connector now contains cn_test.c -
+testing module which uses connector to request notification and to
+send messages.
+
+/*****************************************/
+Reliability.
+/*****************************************/
+
+Netlink itself is not reliable protocol, that means that messages can
+be lost due to memory pressure or process' receiving queue overflowed,
+so caller is warned must be prepared. That is why struct cn_msg [main
+connector's message header] contains u32 seq and u32 ack fields.
diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt
index e2d1e760b4ba..6a82948ff4bd 100644
--- a/Documentation/cpu-freq/cpufreq-stats.txt
+++ b/Documentation/cpu-freq/cpufreq-stats.txt
@@ -36,7 +36,7 @@ cpufreq stats provides following statistics (explained in detail below).
All the statistics will be from the time the stats driver has been inserted
to the time when a read of a particular statistic is done. Obviously, stats
-driver will not have any information about the the frequcny transitions before
+driver will not have any information about the frequency transitions before
the stats driver insertion.
--------------------------------------------------------------------------------
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index ad944c060312..d17b7d2dd771 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -60,6 +60,18 @@ all of the cpus in the system. This removes any overhead due to
load balancing code trying to pull tasks outside of the cpu exclusive
cpuset only to be prevented by the tasks' cpus_allowed mask.
+A cpuset that is mem_exclusive restricts kernel allocations for
+page, buffer and other data commonly shared by the kernel across
+multiple users. All cpusets, whether mem_exclusive or not, restrict
+allocations of memory for user space. This enables configuring a
+system so that several independent jobs can share common kernel
+data, such as file system pages, while isolating each jobs user
+allocation in its own cpuset. To do this, construct a large
+mem_exclusive cpuset to hold all the jobs, and construct child,
+non-mem_exclusive cpusets for each individual job. Only a small
+amount of typical kernel memory, such as requests from interrupt
+handlers, is allowed to be taken outside even a mem_exclusive cpuset.
+
User level code may create and destroy cpusets by name in the cpuset
virtual file system, manage the attributes and permissions of these
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
@@ -265,7 +277,7 @@ rewritten to the 'tasks' file of its cpuset. This is done to avoid
impacting the scheduler code in the kernel with a check for changes
in a tasks processor placement.
-There is an exception to the above. If hotplug funtionality is used
+There is an exception to the above. If hotplug functionality is used
to remove all the CPUs that are currently assigned to a cpuset,
then the kernel will automatically update the cpus_allowed of all
tasks attached to CPUs in that cpuset to allow all CPUs. When memory
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
index a2d5b4900772..74dffc68ff9f 100644
--- a/Documentation/crypto/api-intro.txt
+++ b/Documentation/crypto/api-intro.txt
@@ -223,6 +223,7 @@ CAST5 algorithm contributors:
TEA/XTEA algorithm contributors:
Aaron Grothe
+ Michael Ringe
Khazad algorithm contributors:
Aaron Grothe
diff --git a/Documentation/crypto/descore-readme.txt b/Documentation/crypto/descore-readme.txt
index 166474c2ee0b..16e9e6350755 100644
--- a/Documentation/crypto/descore-readme.txt
+++ b/Documentation/crypto/descore-readme.txt
@@ -1,4 +1,4 @@
-Below is the orginal README file from the descore.shar package.
+Below is the original README file from the descore.shar package.
------------------------------------------------------------------------------
des - fast & portable DES encryption & decryption.
diff --git a/Documentation/dcdbas.txt b/Documentation/dcdbas.txt
new file mode 100644
index 000000000000..e1c52e2dc361
--- /dev/null
+++ b/Documentation/dcdbas.txt
@@ -0,0 +1,91 @@
+Overview
+
+The Dell Systems Management Base Driver provides a sysfs interface for
+systems management software such as Dell OpenManage to perform system
+management interrupts and host control actions (system power cycle or
+power off after OS shutdown) on certain Dell systems.
+
+Dell OpenManage requires this driver on the following Dell PowerEdge systems:
+300, 1300, 1400, 400SC, 500SC, 1500SC, 1550, 600SC, 1600SC, 650, 1655MC,
+700, and 750. Other Dell software such as the open source libsmbios project
+is expected to make use of this driver, and it may include the use of this
+driver on other Dell systems.
+
+The Dell libsmbios project aims towards providing access to as much BIOS
+information as possible. See http://linux.dell.com/libsmbios/main/ for
+more information about the libsmbios project.
+
+
+System Management Interrupt
+
+On some Dell systems, systems management software must access certain
+management information via a system management interrupt (SMI). The SMI data
+buffer must reside in 32-bit address space, and the physical address of the
+buffer is required for the SMI. The driver maintains the memory required for
+the SMI and provides a way for the application to generate the SMI.
+The driver creates the following sysfs entries for systems management
+software to perform these system management interrupts:
+
+/sys/devices/platform/dcdbas/smi_data
+/sys/devices/platform/dcdbas/smi_data_buf_phys_addr
+/sys/devices/platform/dcdbas/smi_data_buf_size
+/sys/devices/platform/dcdbas/smi_request
+
+Systems management software must perform the following steps to execute
+a SMI using this driver:
+
+1) Lock smi_data.
+2) Write system management command to smi_data.
+3) Write "1" to smi_request to generate a calling interface SMI or
+ "2" to generate a raw SMI.
+4) Read system management command response from smi_data.
+5) Unlock smi_data.
+
+
+Host Control Action
+
+Dell OpenManage supports a host control feature that allows the administrator
+to perform a power cycle or power off of the system after the OS has finished
+shutting down. On some Dell systems, this host control feature requires that
+a driver perform a SMI after the OS has finished shutting down.
+
+The driver creates the following sysfs entries for systems management software
+to schedule the driver to perform a power cycle or power off host control
+action after the system has finished shutting down:
+
+/sys/devices/platform/dcdbas/host_control_action
+/sys/devices/platform/dcdbas/host_control_smi_type
+/sys/devices/platform/dcdbas/host_control_on_shutdown
+
+Dell OpenManage performs the following steps to execute a power cycle or
+power off host control action using this driver:
+
+1) Write host control action to be performed to host_control_action.
+2) Write type of SMI that driver needs to perform to host_control_smi_type.
+3) Write "1" to host_control_on_shutdown to enable host control action.
+4) Initiate OS shutdown.
+ (Driver will perform host control SMI when it is notified that the OS
+ has finished shutting down.)
+
+
+Host Control SMI Type
+
+The following table shows the value to write to host_control_smi_type to
+perform a power cycle or power off host control action:
+
+PowerEdge System Host Control SMI Type
+---------------- ---------------------
+ 300 HC_SMITYPE_TYPE1
+ 1300 HC_SMITYPE_TYPE1
+ 1400 HC_SMITYPE_TYPE2
+ 500SC HC_SMITYPE_TYPE2
+ 1500SC HC_SMITYPE_TYPE2
+ 1550 HC_SMITYPE_TYPE2
+ 600SC HC_SMITYPE_TYPE2
+ 1600SC HC_SMITYPE_TYPE2
+ 650 HC_SMITYPE_TYPE2
+ 1655MC HC_SMITYPE_TYPE2
+ 700 HC_SMITYPE_TYPE3
+ 750 HC_SMITYPE_TYPE3
+
+
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
new file mode 100644
index 000000000000..bcfa5c35036b
--- /dev/null
+++ b/Documentation/dell_rbu.txt
@@ -0,0 +1,74 @@
+Purpose:
+Demonstrate the usage of the new open sourced rbu (Remote BIOS Update) driver
+for updating BIOS images on Dell servers and desktops.
+
+Scope:
+This document discusses the functionality of the rbu driver only.
+It does not cover the support needed from aplications to enable the BIOS to
+update itself with the image downloaded in to the memory.
+
+Overview:
+This driver works with Dell OpenManage or Dell Update Packages for updating
+the BIOS on Dell servers (starting from servers sold since 1999), desktops
+and notebooks (starting from those sold in 2005).
+Please go to http://support.dell.com register and you can find info on
+OpenManage and Dell Update packages (DUP).
+
+Dell_RBU driver supports BIOS update using the monilothic image and packetized
+image methods. In case of moniolithic the driver allocates a contiguous chunk
+of physical pages having the BIOS image. In case of packetized the app
+using the driver breaks the image in to packets of fixed sizes and the driver
+would place each packet in contiguous physical memory. The driver also
+maintains a link list of packets for reading them back.
+If the dell_rbu driver is unloaded all the allocated memory is freed.
+
+The rbu driver needs to have an application which will inform the BIOS to
+enable the update in the next system reboot.
+
+The user should not unload the rbu driver after downloading the BIOS image
+or updating.
+
+The driver load creates the following directories under the /sys file system.
+/sys/class/firmware/dell_rbu/loading
+/sys/class/firmware/dell_rbu/data
+/sys/devices/platform/dell_rbu/image_type
+/sys/devices/platform/dell_rbu/data
+
+The driver supports two types of update mechanism; monolithic and packetized.
+These update mechanism depends upon the BIOS currently running on the system.
+Most of the Dell systems support a monolithic update where the BIOS image is
+copied to a single contiguous block of physical memory.
+In case of packet mechanism the single memory can be broken in smaller chuks
+of contiguous memory and the BIOS image is scattered in these packets.
+
+By default the driver uses monolithic memory for the update type. This can be
+changed to contiguous during the driver load time by specifying the load
+parameter image_type=packet. This can also be changed later as below
+echo packet > /sys/devices/platform/dell_rbu/image_type
+
+Do the steps below to download the BIOS image.
+1) echo 1 > /sys/class/firmware/dell_rbu/loading
+2) cp bios_image.hdr /sys/class/firmware/dell_rbu/data
+3) echo 0 > /sys/class/firmware/dell_rbu/loading
+
+The /sys/class/firmware/dell_rbu/ entries will remain till the following is
+done.
+echo -1 > /sys/class/firmware/dell_rbu/loading
+
+Until this step is completed the drivr cannot be unloaded.
+
+Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
+read back the image downloaded. This is useful in case of packet update
+mechanism where the above steps 1,2,3 will repeated for every packet.
+By reading the /sys/devices/platform/dell_rbu/data file all packet data
+downloaded can be verified in a single file.
+The packets are arranged in this file one after the other in a FIFO order.
+
+NOTE:
+This driver requires a patch for firmware_class.c which has the addition
+of request_firmware_nowait_nohotplug function to wortk
+Also after updating the BIOS image an user mdoe application neeeds to execute
+code which message the BIOS update request to the BIOS. So on the next reboot
+the BIOS knows about the new image downloaded and it updates it self.
+Also don't unload the rbu drive if the image has to be updated.
+
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 96bea278bbf6..24adfe9af3ca 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -55,6 +55,7 @@ aic7*seq.h*
aicasm
aicdb.h*
asm
+asm-offsets.*
asm_offsets.*
autoconf.h*
bbootsect
diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt
index e6b8d05bc08d..cb63b7a93c82 100644
--- a/Documentation/dvb/bt8xx.txt
+++ b/Documentation/dvb/bt8xx.txt
@@ -1,55 +1,74 @@
-How to get the Nebula Electronics DigiTV, Pinnacle PCTV Sat, Twinhan DST + clones working
-=========================================================================================
+How to get the Nebula, PCTV and Twinhan DST cards working
+=========================================================
-1) General information
-======================
+This class of cards has a bt878a as the PCI interface, and
+require the bttv driver.
-This class of cards has a bt878a chip as the PCI interface.
-The different card drivers require the bttv driver to provide the means
-to access the i2c bus and the gpio pins of the bt8xx chipset.
+Please pay close attention to the warning about the bttv module
+options below for the DST card.
-2) Compilation rules for Kernel >= 2.6.12
-=========================================
+1) General informations
+=======================
-Enable the following options:
+These drivers require the bttv driver to provide the means to access
+the i2c bus and the gpio pins of the bt8xx chipset.
+Because of this, you need to enable
"Device drivers" => "Multimedia devices"
- => "Video For Linux" => "BT848 Video For Linux"
+ => "Video For Linux" => "BT848 Video For Linux"
+
+Furthermore you need to enable
"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
- => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
+ => "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards"
-3) Loading Modules, described by two approaches
-===============================================
+2) Loading Modules
+==================
In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us, plus the common dvb-bt8xx device driver,
-which is called the backend.
-The frontends for Nebula DigiTV (nxt6000), Pinnacle PCTV Sat (cx24110),
-TwinHan DST + clones (dst and dst-ca) are loaded automatically by the backend.
-For further details about TwinHan DST + clones see /Documentation/dvb/ci.txt.
+i2c communication for us, plus the common dvb-bt8xx device driver.
+The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
+TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
-3a) The manual approach
------------------------
+3a) Nebula / Pinnacle PCTV
+--------------------------
-Loading modules:
-modprobe bttv
-modprobe dvb-bt8xx
+ $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+ $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
-Unloading modules:
-modprobe -r dvb-bt8xx
-modprobe -r bttv
-3b) The automatic approach
+3b) TwinHan and Clones
--------------------------
-If not already done by installation, place a line either in
-/etc/modules.conf or in /etc/modprobe.conf containing this text:
-alias char-major-81 bttv
+ $ modprobe bttv i2c_hw=1 card=0x71
+ $ modprobe dvb-bt8xx
+ $ modprobe dst
+
+The value 0x71 will override the PCI type detection for dvb-bt8xx,
+which is necessary for TwinHan cards.
+
+If you're having an older card (blue color circuit) and card=0x71 locks
+your machine, try using 0x68, too. If that does not work, ask on the
+mailing list.
+
+The DST module takes a couple of useful parameters.
+
+verbose takes values 0 to 4. These values control the verbosity level,
+and can be used to debug also.
+
+verbose=0 means complete disabling of messages
+ 1 only error messages are displayed
+ 2 notifications are also displayed
+ 3 informational messages are also displayed
+ 4 debug setting
+
+dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
+0x20 means it has a Conditional Access slot.
+
+The autodected values are determined bythe cards 'response
+string' which you can see in your logs e.g.
-Then place a line in /etc/modules containing this text:
-dvb-bt8xx
+dst_get_device_id: Recognise [DSTMCI]
-Reboot your system and have fun!
--
-Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt
index 62e0701b542a..95f0e73b2135 100644
--- a/Documentation/dvb/ci.txt
+++ b/Documentation/dvb/ci.txt
@@ -23,7 +23,6 @@ This application requires the following to function properly as of now.
eg: $ szap -c channels.conf -r "TMC" -x
(b) a channels.conf containing a valid PMT PID
-
eg: TMC:11996:h:0:27500:278:512:650:321
here 278 is a valid PMT PID. the rest of the values are the
@@ -31,13 +30,7 @@ This application requires the following to function properly as of now.
(c) after running a szap, you have to run ca_zap, for the
descrambler to function,
-
- eg: $ ca_zap patched_channels.conf "TMC"
-
- The patched means a patch to apply to scan, such that scan can
- generate a channels.conf_with pmt, which has this PMT PID info
- (NOTE: szap cannot use this channels.conf with the PMT_PID)
-
+ eg: $ ca_zap channels.conf "TMC"
(d) Hopeflly Enjoy your favourite subscribed channel as you do with
a FTA card.
diff --git a/Documentation/exception.txt b/Documentation/exception.txt
index f1d436993eb1..3cb39ade290e 100644
--- a/Documentation/exception.txt
+++ b/Documentation/exception.txt
@@ -7,7 +7,7 @@ To protect itself the kernel has to verify this address.
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
-function.
+function (which has since been replaced by access_ok()).
This function verified that the memory area starting at address
addr and of size size was accessible for the operation specified
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs
new file mode 100644
index 000000000000..f90cc66ea919
--- /dev/null
+++ b/Documentation/fb/cyblafb/bugs
@@ -0,0 +1,14 @@
+Bugs
+====
+
+I currently don't know of any bug. Please do send reports to:
+ - linux-fbdev-devel@lists.sourceforge.net
+ - Knut_Petersen@t-online.de.
+
+
+Untested features
+=================
+
+All LCD stuff is untested. If it worked in tridentfb, it should work in
+cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
+
diff --git a/Documentation/fb/cyblafb/credits b/Documentation/fb/cyblafb/credits
new file mode 100644
index 000000000000..0eb3b443dc2b
--- /dev/null
+++ b/Documentation/fb/cyblafb/credits
@@ -0,0 +1,7 @@
+Thanks to
+=========
+ * Alan Hourihane, for writing the X trident driver
+ * Jani Monoses, for writing the tridentfb driver
+ * Antonino A. Daplas, for review of the first published
+ version of cyblafb and some code
+ * Jochen Hein, for testing and a helpfull bug report
diff --git a/Documentation/fb/cyblafb/documentation b/Documentation/fb/cyblafb/documentation
new file mode 100644
index 000000000000..bb1aac048425
--- /dev/null
+++ b/Documentation/fb/cyblafb/documentation
@@ -0,0 +1,17 @@
+Available Documentation
+=======================
+
+Apollo PLE 133 Chipset VT8601A North Bridge Datasheet, Rev. 1.82, October 22,
+2001, available from VIA:
+
+ http://www.viavpsd.com/product/6/15/DS8601A182.pdf
+
+The datasheet is incomplete, some registers that need to be programmed are not
+explained at all and important bits are listed as "reserved". But you really
+need the datasheet to understand the code. "p. xxx" comments refer to page
+numbers of this document.
+
+XFree/XOrg drivers are available and of good quality, looking at the code
+there is a good idea if the datasheet does not provide enough information
+or if the datasheet seems to be wrong.
+
diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes
new file mode 100644
index 000000000000..cf4351fc32ff
--- /dev/null
+++ b/Documentation/fb/cyblafb/fb.modes
@@ -0,0 +1,155 @@
+#
+# Sample fb.modes file
+#
+# Provides an incomplete list of working modes for
+# the cyberblade/i1 graphics core.
+#
+# The value 4294967256 is used instead of -40. Of course, -40 is not
+# a really reasonable value, but chip design does not always follow
+# logic. Believe me, it's ok, and it's the way the BIOS does it.
+#
+# fbset requires 4294967256 in fb.modes and -40 as an argument to
+# the -t parameter. That's also not too reasonable, and it might change
+# in the future or might even be differt for your current version.
+#
+
+mode "640x480-50"
+ geometry 640 480 640 3756 8
+ timings 47619 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-60"
+ geometry 640 480 640 3756 8
+ timings 39682 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-70"
+ geometry 640 480 640 3756 8
+ timings 34013 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-72"
+ geometry 640 480 640 3756 8
+ timings 33068 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-75"
+ geometry 640 480 640 3756 8
+ timings 31746 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-80"
+ geometry 640 480 640 3756 8
+ timings 29761 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-85"
+ geometry 640 480 640 3756 8
+ timings 28011 4294967256 24 17 0 216 3
+endmode
+
+mode "800x600-50"
+ geometry 800 600 800 3221 8
+ timings 30303 96 24 14 0 136 11
+endmode
+
+mode "800x600-60"
+ geometry 800 600 800 3221 8
+ timings 25252 96 24 14 0 136 11
+endmode
+
+mode "800x600-70"
+ geometry 800 600 800 3221 8
+ timings 21645 96 24 14 0 136 11
+endmode
+
+mode "800x600-72"
+ geometry 800 600 800 3221 8
+ timings 21043 96 24 14 0 136 11
+endmode
+
+mode "800x600-75"
+ geometry 800 600 800 3221 8
+ timings 20202 96 24 14 0 136 11
+endmode
+
+mode "800x600-80"
+ geometry 800 600 800 3221 8
+ timings 18939 96 24 14 0 136 11
+endmode
+
+mode "800x600-85"
+ geometry 800 600 800 3221 8
+ timings 17825 96 24 14 0 136 11
+endmode
+
+mode "1024x768-50"
+ geometry 1024 768 1024 2815 8
+ timings 19054 144 24 29 0 120 3
+endmode
+
+mode "1024x768-60"
+ geometry 1024 768 1024 2815 8
+ timings 15880 144 24 29 0 120 3
+endmode
+
+mode "1024x768-70"
+ geometry 1024 768 1024 2815 8
+ timings 13610 144 24 29 0 120 3
+endmode
+
+mode "1024x768-72"
+ geometry 1024 768 1024 2815 8
+ timings 13232 144 24 29 0 120 3
+endmode
+
+mode "1024x768-75"
+ geometry 1024 768 1024 2815 8
+ timings 12703 144 24 29 0 120 3
+endmode
+
+mode "1024x768-80"
+ geometry 1024 768 1024 2815 8
+ timings 11910 144 24 29 0 120 3
+endmode
+
+mode "1024x768-85"
+ geometry 1024 768 1024 2815 8
+ timings 11209 144 24 29 0 120 3
+endmode
+
+mode "1280x1024-50"
+ geometry 1280 1024 1280 2662 8
+ timings 11114 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-60"
+ geometry 1280 1024 1280 2662 8
+ timings 9262 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-70"
+ geometry 1280 1024 1280 2662 8
+ timings 7939 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-72"
+ geometry 1280 1024 1280 2662 8
+ timings 7719 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-75"
+ geometry 1280 1024 1280 2662 8
+ timings 7410 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-80"
+ geometry 1280 1024 1280 2662 8
+ timings 6946 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-85"
+ geometry 1280 1024 1280 2662 8
+ timings 6538 232 16 39 0 160 3
+endmode
+
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance
new file mode 100644
index 000000000000..eb4e47a9cea6
--- /dev/null
+++ b/Documentation/fb/cyblafb/performance
@@ -0,0 +1,80 @@
+Speed
+=====
+
+CyBlaFB is much faster than tridentfb and vesafb. Compare the performance data
+for mode 1280x1024-[8,16,32]@61 Hz.
+
+Test 1: Cat a file with 2000 lines of 0 characters.
+Test 2: Cat a file with 2000 lines of 80 characters.
+Test 3: Cat a file with 2000 lines of 160 characters.
+
+All values show system time use in seconds, kernel 2.6.12 was used for
+the measurements. 2.6.13 is a bit slower, 2.6.14 hopefully will include a
+patch that speeds up kernel bitblitting a lot ( > 20%).
+
++-----------+-----------------------------------------------------+
+| | not accelerated |
+| TRIDENTFB +-----------------+-----------------+-----------------+
+| of 2.6.12 | 8 bpp | 16 bpp | 32 bpp |
+| | noypan | ypan | noypan | ypan | noypan | ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+| Test 1 | 4.31 | 4.33 | 6.05 | 12.81 | ---- | ---- |
+| Test 2 | 67.94 | 5.44 | 123.16 | 14.79 | ---- | ---- |
+| Test 3 | 131.36 | 6.55 | 240.12 | 16.76 | ---- | ---- |
++-----------+--------+--------+--------+--------+--------+--------+
+| Comments | | | completely bro- |
+| | | | ken, monitor |
+| | | | switches off |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+| | accelerated |
+| TRIDENTFB +-----------------+-----------------+-----------------+
+| of 2.6.12 | 8 bpp | 16 bpp | 32 bpp |
+| | noypan | ypan | noypan | ypan | noypan | ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+| Test 1 | ---- | ---- | 20.62 | 1.22 | ---- | ---- |
+| Test 2 | ---- | ---- | 22.61 | 3.19 | ---- | ---- |
+| Test 3 | ---- | ---- | 24.59 | 5.16 | ---- | ---- |
++-----------+--------+--------+--------+--------+--------+--------+
+| Comments | broken, writing | broken, ok only | completely bro- |
+| | to wrong places | if bgcolor is | ken, monitor |
+| | on screen + bug | black, bug in | switches off |
+| | in fillrect() | fillrect() | |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+| | not accelerated |
+| VESAFB +-----------------+-----------------+-----------------+
+| of 2.6.12 | 8 bpp | 16 bpp | 32 bpp |
+| | noypan | ypan | noypan | ypan | noypan | ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+| Test 1 | 4.26 | 3.76 | 5.99 | 7.23 | ---- | ---- |
+| Test 2 | 65.65 | 4.89 | 120.88 | 9.08 | ---- | ---- |
+| Test 3 | 126.91 | 5.94 | 235.77 | 11.03 | ---- | ---- |
++-----------+--------+--------+--------+--------+--------+--------+
+| Comments | vga=0x307 | vga=0x31a | vga=0x31b not |
+| | fh=80kHz | fh=80kHz | supported by |
+| | fv=75kHz | fv=75kHz | video BIOS and |
+| | | | hardware |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+| | accelerated |
+| CYBLAFB +-----------------+-----------------+-----------------+
+| | 8 bpp | 16 bpp | 32 bpp |
+| | noypan | ypan | noypan | ypan | noypan | ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+| Test 1 | 8.02 | 0.23 | 19.04 | 0.61 | 57.12 | 2.74 |
+| Test 2 | 8.38 | 0.55 | 19.39 | 0.92 | 57.54 | 3.13 |
+| Test 3 | 8.73 | 0.86 | 19.74 | 1.24 | 57.95 | 3.51 |
++-----------+--------+--------+--------+--------+--------+--------+
+| Comments | | | |
+| | | | |
+| | | | |
+| | | | |
++-----------+-----------------+-----------------+-----------------+
+
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo
new file mode 100644
index 000000000000..80fb2f89b6c1
--- /dev/null
+++ b/Documentation/fb/cyblafb/todo
@@ -0,0 +1,32 @@
+TODO / Missing features
+=======================
+
+Verify LCD stuff "stretch" and "center" options are
+ completely untested ... this code needs to be
+ verified. As I don't have access to such
+ hardware, please contact me if you are
+ willing run some tests.
+
+Interlaced video modes The reason that interleaved
+ modes are disabled is that I do not know
+ the meaning of the vertical interlace
+ parameter. Also the datasheet mentions a
+ bit d8 of a horizontal interlace parameter,
+ but nowhere the lower 8 bits. Please help
+ if you can.
+
+low-res double scan modes Who needs it?
+
+accelerated color blitting Who needs it? The console driver does use color
+ blitting for nothing but drawing the penguine,
+ everything else is done using color expanding
+ blitting of 1bpp character bitmaps.
+
+xpanning Who needs it?
+
+ioctls Who needs it?
+
+TV-out Will be done later
+
+??? Feel free to contact me if you have any
+ feature requests
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage
new file mode 100644
index 000000000000..e627c8f54211
--- /dev/null
+++ b/Documentation/fb/cyblafb/usage
@@ -0,0 +1,206 @@
+CyBlaFB is a framebuffer driver for the Cyberblade/i1 graphics core integrated
+into the VIA Apollo PLE133 (aka vt8601) south bridge. It is developed and
+tested using a VIA EPIA 5000 board.
+
+Cyblafb - compiled into the kernel or as a module?
+==================================================
+
+You might compile cyblafb either as a module or compile it permanently into the
+kernel.
+
+Unless you have a real reason to do so you should not compile both vesafb and
+cyblafb permanently into the kernel. It's possible and it helps during the
+developement cycle, but it's useless and will at least block some otherwise
+usefull memory for ordinary users.
+
+Selecting Modes
+===============
+
+ Startup Mode
+ ============
+
+ First of all, you might use the "vga=???" boot parameter as it is
+ documented in vesafb.txt and svga.txt. Cyblafb will detect the video
+ mode selected and will use the geometry and timings found by
+ inspecting the hardware registers.
+
+ video=cyblafb vga=0x317
+
+ Alternatively you might use a combination of the mode, ref and bpp
+ parameters. If you compiled the driver into the kernel, add something
+ like this to the kernel command line:
+
+ video=cyblafb:1280x1024,bpp=16,ref=50 ...
+
+ If you compiled the driver as a module, the same mode would be
+ selected by the following command:
+
+ modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
+
+ None of the modes possible to select as startup modes are affected by
+ the problems described at the end of the next subsection.
+
+ Mode changes using fbset
+ ========================
+
+ You might use fbset to change the video mode, see "man fbset". Cyblafb
+ generally does assume that you know what you are doing. But it does
+ some checks, especially those that are needed to prevent you from
+ damaging your hardware.
+
+ - only 8, 16, 24 and 32 bpp video modes are accepted
+ - interlaced video modes are not accepted
+ - double scan video modes are not accepted
+ - if a flat panel is found, cyblafb does not allow you
+ to program a resolution higher than the physical
+ resolution of the flat panel monitor
+ - cyblafb does not allow xres to differ from xres_virtual
+ - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp
+ and (currently) 24 bit modes use a doubled vclk internally,
+ the dotclock limit as seen by fbset is 115 MHz for those
+ modes and 230 MHz for 8 and 16 bpp modes.
+
+ Any request that violates the rules given above will be ignored and
+ fbset will return an error.
+
+ If you program a virtual y resolution higher than the hardware limit,
+ cyblafb will silently decrease that value to the highest possible
+ value.
+
+ Attempts to disable acceleration are ignored.
+
+ Some video modes that should work do not work as expected. If you use
+ the standard fb.modes, fbset 640x480-60 will program that mode, but
+ you will see a vertical area, about two characters wide, with only
+ much darker characters than the other characters on the screen.
+ Cyblafb does allow that mode to be set, as it does not violate the
+ official specifications. It would need a lot of code to reliably sort
+ out all invalid modes, playing around with the margin values will
+ give a valid mode quickly. And if cyblafb would detect such an invalid
+ mode, should it silently alter the requested values or should it
+ report an error? Both options have some pros and cons. As stated
+ above, none of the startup modes are affected, and if you set
+ verbosity to 1 or higher, cyblafb will print the fbset command that
+ would be needed to program that mode using fbset.
+
+
+Other Parameters
+================
+
+
+crt don't autodetect, assume monitor connected to
+ standard VGA connector
+
+fp don't autodetect, assume flat panel display
+ connected to flat panel monitor interface
+
+nativex inform driver about native x resolution of
+ flat panel monitor connected to special
+ interface (should be autodetected)
+
+stretch stretch image to adapt low resolution modes to
+ higer resolutions of flat panel monitors
+ connected to special interface
+
+center center image to adapt low resolution modes to
+ higer resolutions of flat panel monitors
+ connected to special interface
+
+memsize use if autodetected memsize is wrong ...
+ should never be necessary
+
+nopcirr disable PCI read retry
+nopciwr disable PCI write retry
+nopcirb disable PCI read bursts
+nopciwb disable PCI write bursts
+
+bpp bpp for specified modes
+ valid values: 8 || 16 || 24 || 32
+
+ref refresh rate for specified mode
+ valid values: 50 <= ref <= 85
+
+mode 640x480 or 800x600 or 1024x768 or 1280x1024
+ if not specified, the startup mode will be detected
+ and used, so you might also use the vga=??? parameter
+ described in vesafb.txt. If you do not specify a mode,
+ bpp and ref parameters are ignored.
+
+verbosity 0 is the default, increase to at least 2 for every
+ bug report!
+
+vesafb allows cyblafb to be loaded after vesafb has been
+ loaded. See sections "Module unloading ...".
+
+
+Development hints
+=================
+
+It's much faster do compile a module and to load the new version after
+unloading the old module than to compile a new kernel and to reboot. So if you
+try to work on cyblafb, it might be a good idea to use cyblafb as a module.
+In real life, fast often means dangerous, and that's also the case here. If
+you introduce a serious bug when cyblafb is compiled into the kernel, the
+kernel will lock or oops with a high probability before the file system is
+mounted, and the danger for your data is low. If you load a broken own version
+of cyblafb on a running system, the danger for the integrity of the file
+system is much higher as you might need a hard reset afterwards. Decide
+yourself.
+
+Module unloading, the vfb method
+================================
+
+If you want to unload/reload cyblafb using the virtual framebuffer, you need
+to enable vfb support in the kernel first. After that, load the modules as
+shown below:
+
+ modprobe vfb vfb_enable=1
+ modprobe fbcon
+ modprobe cyblafb
+ fbset -fb /dev/fb1 1280x1024-60 -vyres 2662
+ con2fb /dev/fb1 /dev/tty1
+ ...
+
+If you now made some changes to cyblafb and want to reload it, you might do it
+as show below:
+
+ con2fb /dev/fb0 /dev/tty1
+ ...
+ rmmod cyblafb
+ modprobe cyblafb
+ con2fb /dev/fb1 /dev/tty1
+ ...
+
+Of course, you might choose another mode, and most certainly you also want to
+map some other /dev/tty* to the real framebuffer device. You might also choose
+to compile fbcon as a kernel module or place it permanently in the kernel.
+
+I do not know of any way to unload fbcon, and fbcon will prevent the
+framebuffer device loaded first from unloading. [If there is a way, then
+please add a description here!]
+
+Module unloading, the vesafb method
+===================================
+
+Configure the kernel:
+
+ <*> Support for frame buffer devices
+ [*] VESA VGA graphics support
+ <M> Cyberblade/i1 support
+
+Add e.g. "video=vesafb:ypan vga=0x307" to the kernel parameters. The ypan
+parameter is important, choose any vga parameter you like as long as it is
+a graphics mode.
+
+After booting, load cyblafb without any mode and bpp parameter and assign
+cyblafb to individual ttys using con2fb, e.g.:
+
+ modprobe cyblafb vesafb=1
+ con2fb /dev/fb1 /dev/tty1
+
+Unloading cyblafb works without problems after you assign vesafb to all
+ttys again, e.g.:
+
+ con2fb /dev/fb0 /dev/tty1
+ rmmod cyblafb
+
diff --git a/Documentation/fb/cyblafb/whycyblafb b/Documentation/fb/cyblafb/whycyblafb
new file mode 100644
index 000000000000..a123bc11e698
--- /dev/null
+++ b/Documentation/fb/cyblafb/whycyblafb
@@ -0,0 +1,85 @@
+I tried the following framebuffer drivers:
+
+ - TRIDENTFB is full of bugs. Acceleration is broken for Blade3D
+ graphics cores like the cyberblade/i1. It claims to support a great
+ number of devices, but documentation for most of these devices is
+ unfortunately not available. There is _no_ reason to use tridentfb
+ for cyberblade/i1 + CRT users. VESAFB is faster, and the one
+ advantage, mode switching, is broken in tridentfb.
+
+ - VESAFB is used by many distributions as a standard. Vesafb does
+ not support mode switching. VESAFB is a bit faster than the working
+ configurations of TRIDENTFB, but it is still too slow, even if you
+ use ypan.
+
+ - EPIAFB (you'll find it on sourceforge) supports the Cyberblade/i1
+ graphics core, but it still has serious bugs and developement seems
+ to have stopped. This is the one driver with TV-out support. If you
+ do need this feature, try epiafb.
+
+None of these drivers was a real option for me.
+
+I believe that is unreasonable to change code that announces to support 20
+devices if I only have more or less sufficient documentation for exactly one
+of these. The risk of breaking device foo while fixing device bar is too high.
+
+So I decided to start CyBlaFB as a stripped down tridentfb.
+
+All code specific to other Trident chips has been removed. After that there
+were a lot of cosmetic changes to increase the readability of the code. All
+register names were changed to those mnemonics used in the datasheet. Function
+and macro names were changed if they hindered easy understanding of the code.
+
+After that I debugged the code and implemented some new features. I'll try to
+give a little summary of the main changes:
+
+ - calculation of vertical and horizontal timings was fixed
+
+ - video signal quality has been improved dramatically
+
+ - acceleration:
+
+ - fillrect and copyarea were fixed and reenabled
+
+ - color expanding imageblit was newly implemented, color
+ imageblit (only used to draw the penguine) still uses the
+ generic code.
+
+ - init of the acceleration engine was improved and moved to a
+ place where it really works ...
+
+ - sync function has a timeout now and tries to reset and
+ reinit the accel engine if necessary
+
+ - fewer slow copyarea calls when doing ypan scrolling by using
+ undocumented bit d21 of screen start address stored in
+ CR2B[5]. BIOS does use it also, so this should be safe.
+
+ - cyblafb rejects any attempt to set modes that would cause vclk
+ values above reasonable 230 MHz. 32bit modes use a clock
+ multiplicator of 2, so fbset does show the correct values for
+ pixclock but not for vclk in this case. The fbset limit is 115 MHz
+ for 32 bpp modes.
+
+ - cyblafb rejects modes known to be broken or unimplemented (all
+ interlaced modes, all doublescan modes for now)
+
+ - cyblafb now works independant of the video mode in effect at startup
+ time (tridentfb does not init all needed registers to reasonable
+ values)
+
+ - switching between video modes does work reliably now
+
+ - the first video mode now is the one selected on startup using the
+ vga=???? mechanism or any of
+ - 640x480, 800x600, 1024x768, 1280x1024
+ - 8, 16, 24 or 32 bpp
+ - refresh between 50 Hz and 85 Hz, 1 Hz steps (1280x1024-32
+ is limited to 63Hz)
+
+ - pci retry and pci burst mode are settable (try to disable if you
+ experience latency problems)
+
+ - built as a module cyblafb might be unloaded and reloaded using
+ the vfb module and con2vt or might be used together with vesafb
+
diff --git a/Documentation/fb/intel810.txt b/Documentation/fb/intel810.txt
index fd68b162e4a1..4f0d6bc789ef 100644
--- a/Documentation/fb/intel810.txt
+++ b/Documentation/fb/intel810.txt
@@ -5,6 +5,7 @@ Intel 810/815 Framebuffer driver
March 17, 2002
First Released: July 2001
+ Last Update: September 12, 2005
================================================================
A. Introduction
@@ -44,6 +45,8 @@ B. Features
- Hardware Cursor Support
+ - Supports EDID probing either by DDC/I2C or through the BIOS
+
C. List of available options
a. "video=i810fb"
@@ -52,14 +55,17 @@ C. List of available options
Recommendation: required
b. "xres:<value>"
- select horizontal resolution in pixels
+ select horizontal resolution in pixels. (This parameter will be
+ ignored if 'mode_option' is specified. See 'o' below).
Recommendation: user preference
(default = 640)
c. "yres:<value>"
select vertical resolution in scanlines. If Discrete Video Timings
- is enabled, this will be ignored and computed as 3*xres/4.
+ is enabled, this will be ignored and computed as 3*xres/4. (This
+ parameter will be ignored if 'mode_option' is specified. See 'o'
+ below)
Recommendation: user preference
(default = 480)
@@ -86,7 +92,8 @@ C. List of available options
g. "hsync1/hsync2:<value>"
select the minimum and maximum Horizontal Sync Frequency of the
monitor in KHz. If a using a fixed frequency monitor, hsync1 must
- be equal to hsync2.
+ be equal to hsync2. If EDID probing is successful, these will be
+ ignored and values will be taken from the EDID block.
Recommendation: check monitor manual for correct values
default (29/30)
@@ -94,7 +101,8 @@ C. List of available options
h. "vsync1/vsync2:<value>"
select the minimum and maximum Vertical Sync Frequency of the monitor
in Hz. You can also use this option to lock your monitor's refresh
- rate.
+ rate. If EDID probing is successful, these will be ignored and values
+ will be taken from the EDID block.
Recommendation: check monitor manual for correct values
(default = 60/60)
@@ -154,7 +162,11 @@ C. List of available options
Recommendation: do not set
(default = not set)
-
+ o. <xres>x<yres>[-<bpp>][@<refresh>]
+ The driver will now accept specification of boot mode option. If this
+ is specified, the options 'xres' and 'yres' will be ignored. See
+ Documentation/fb/modedb.txt for usage.
+
D. Kernel booting
Separate each option/option-pair by commas (,) and the option from its value
@@ -176,7 +188,10 @@ will be computed based on the hsync1/hsync2 and vsync1/vsync2 values.
IMPORTANT:
You must include hsync1, hsync2, vsync1 and vsync2 to enable video modes
-better than 640x480 at 60Hz.
+better than 640x480 at 60Hz. HOWEVER, if your chipset/display combination
+supports I2C and has an EDID block, you can safely exclude hsync1, hsync2,
+vsync1 and vsync2 parameters. These parameters will be taken from the EDID
+block.
E. Module options
@@ -217,32 +232,21 @@ F. Setup
This is required. The option is under "Character Devices"
d. Under "Graphics Support", select "Intel 810/815" either statically
- or as a module. Choose "use VESA GTF for video timings" if you
- need to maximize the capability of your display. To be on the
+ or as a module. Choose "use VESA Generalized Timing Formula" if
+ you need to maximize the capability of your display. To be on the
safe side, you can leave this unselected.
- e. If you want a framebuffer console, enable it under "Console
+ e. If you want support for DDC/I2C probing (Plug and Play Displays),
+ set 'Enable DDC Support' to 'y'. To make this option appear, set
+ 'use VESA Generalized Timing Formula' to 'y'.
+
+ f. If you want a framebuffer console, enable it under "Console
Drivers"
- f. Compile your kernel.
+ g. Compile your kernel.
- g. Load the driver as described in section D and E.
+ h. Load the driver as described in section D and E.
- Optional:
- h. If you are going to run XFree86 with its native drivers, the
- standard XFree86 4.1.0 and 4.2.0 drivers should work as is.
- However, there's a bug in the XFree86 i810 drivers. It attempts
- to use XAA even when switched to the console. This will crash
- your server. I have a fix at this site:
-
- http://i810fb.sourceforge.net.
-
- You can either use the patch, or just replace
-
- /usr/X11R6/lib/modules/drivers/i810_drv.o
-
- with the one provided at the website.
-
i. Try the DirectFB (http://www.directfb.org) + the i810 gfxdriver
patch to see the chipset in action (or inaction :-).
diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
index e04458b319d5..4fcdb4cf4cca 100644
--- a/Documentation/fb/modedb.txt
+++ b/Documentation/fb/modedb.txt
@@ -20,12 +20,83 @@ in a video= option, fbmem considers that to be a global video mode option.
Valid mode specifiers (mode_option argument):
- <xres>x<yres>[-<bpp>][@<refresh>]
+ <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
<name>[-<bpp>][@<refresh>]
with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
Things between square brackets are optional.
+If 'M' is specified in the mode_option argument (after <yres> and before
+<bpp> and <refresh>, if specified) the timings will be calculated using
+VESA(TM) Coordinated Video Timings instead of looking up the mode from a table.
+If 'R' is specified, do a 'reduced blanking' calculation for digital displays.
+If 'i' is specified, calculate for an interlaced mode. And if 'm' is
+specified, add margins to the calculation (1.8% of xres rounded down to 8
+pixels and 1.8% of yres).
+
+ Sample usage: 1024x768M@60m - CVT timing with margins
+
+***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+
+What is the VESA(TM) Coordinated Video Timings (CVT)?
+
+From the VESA(TM) Website:
+
+ "The purpose of CVT is to provide a method for generating a consistent
+ and coordinated set of standard formats, display refresh rates, and
+ timing specifications for computer display products, both those
+ employing CRTs, and those using other display technologies. The
+ intention of CVT is to give both source and display manufacturers a
+ common set of tools to enable new timings to be developed in a
+ consistent manner that ensures greater compatibility."
+
+This is the third standard approved by VESA(TM) concerning video timings. The
+first was the Discrete Video Timings (DVT) which is a collection of
+pre-defined modes approved by VESA(TM). The second is the Generalized Timing
+Formula (GTF) which is an algorithm to calculate the timings, given the
+pixelclock, the horizontal sync frequency, or the vertical refresh rate.
+
+The GTF is limited by the fact that it is designed mainly for CRT displays.
+It artificially increases the pixelclock because of its high blanking
+requirement. This is inappropriate for digital display interface with its high
+data rate which requires that it conserves the pixelclock as much as possible.
+Also, GTF does not take into account the aspect ratio of the display.
+
+The CVT addresses these limitations. If used with CRT's, the formula used
+is a derivation of GTF with a few modifications. If used with digital
+displays, the "reduced blanking" calculation can be used.
+
+From the framebuffer subsystem perspective, new formats need not be added
+to the global mode database whenever a new mode is released by display
+manufacturers. Specifying for CVT will work for most, if not all, relatively
+new CRT displays and probably with most flatpanels, if 'reduced blanking'
+calculation is specified. (The CVT compatibility of the display can be
+determined from its EDID. The version 1.3 of the EDID has extra 128-byte
+blocks where additional timing information is placed. As of this time, there
+is no support yet in the layer to parse this additional blocks.)
+
+CVT also introduced a new naming convention (should be seen from dmesg output):
+
+ <pix>M<a>[-R]
+
+ where: pix = total amount of pixels in MB (xres x yres)
+ M = always present
+ a = aspect ratio (3 - 4:3; 4 - 5:4; 9 - 15:9, 16:9; A - 16:10)
+ -R = reduced blanking
+
+ example: .48M3-R - 800x600 with reduced blanking
+
+Note: VESA(TM) has restrictions on what is a standard CVT timing:
+
+ - aspect ratio can only be one of the above values
+ - acceptable refresh rates are 50, 60, 70 or 85 Hz only
+ - if reduced blanking, the refresh rate must be at 60Hz
+
+If one of the above are not satisfied, the kernel will print a warning but the
+timings will still be calculated.
+
+***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+
To find a suitable video mode, you just call
int __init fb_find_mode(struct fb_var_screeninfo *var,
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 8b1430b46655..b67189a8d8d4 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -17,32 +17,6 @@ Who: Greg Kroah-Hartman <greg@kroah.com>
---------------------------
-What: ACPI S4bios support
-When: May 2005
-Why: Noone uses it, and it probably does not work, anyway. swsusp is
- faster, more reliable, and people are actually using it.
-Who: Pavel Machek <pavel@suse.cz>
-
----------------------------
-
-What: PCI Name Database (CONFIG_PCI_NAMES)
-When: July 2005
-Why: It bloats the kernel unnecessarily, and is handled by userspace better
- (pciutils supports it.) Will eliminate the need to try to keep the
- pci.ids file in sync with the sf.net database all of the time.
-Who: Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
-What: io_remap_page_range() (macro or function)
-When: September 2005
-Why: Replaced by io_remap_pfn_range() which allows more memory space
- addressabilty (by using a pfn) and supports sparc & sparc64
- iospace as part of the pfn.
-Who: Randy Dunlap <rddunlap@osdl.org>
-
----------------------------
-
What: RAW driver (CONFIG_RAW_DRIVER)
When: December 2005
Why: declared obsolete since kernel 2.6.3
@@ -51,14 +25,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: register_ioctl32_conversion() / unregister_ioctl32_conversion()
-When: April 2005
-Why: Replaced by ->compat_ioctl in file_operations and other method
- vecors.
-Who: Andi Kleen <ak@muc.de>, Christoph Hellwig <hch@lst.de>
-
----------------------------
-
What: RCU API moves to EXPORT_SYMBOL_GPL
When: April 2006
Files: include/linux/rcupdate.h, kernel/rcupdate.c
@@ -74,14 +40,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
---------------------------
-What: remove verify_area()
-When: July 2006
-Files: Various uaccess.h headers.
-Why: Deprecated and redundant. access_ok() should be used instead.
-Who: Jesper Juhl <juhl-lkml@dif.dk>
-
----------------------------
-
What: IEEE1394 Audio and Music Data Transmission Protocol driver,
Connection Management Procedures driver
When: November 2005
@@ -102,16 +60,6 @@ Who: Jody McIntyre <scjody@steamballoon.com>
---------------------------
-What: register_serial/unregister_serial
-When: September 2005
-Why: This interface does not allow serial ports to be registered against
- a struct device, and as such does not allow correct power management
- of such ports. 8250-based ports should use serial8250_register_port
- and serial8250_unregister_port, or platform devices instead.
-Who: Russell King <rmk@arm.linux.org.uk>
-
----------------------------
-
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
When: November 2005
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
@@ -135,3 +83,15 @@ Why: With the 16-bit PCMCIA subsystem now behaving (almost) like a
pcmciautils package available at
http://kernel.org/pub/linux/utils/kernel/pcmcia/
Who: Dominik Brodowski <linux@brodo.de>
+
+---------------------------
+
+What: ip_queue and ip6_queue (old ipv4-only and ipv6-only netfilter queue)
+When: December 2005
+Why: This interface has been obsoleted by the new layer3-independent
+ "nfnetlink_queue". The Kernel interface is compatible, so the old
+ ip[6]tables "QUEUE" targets still work and will transparently handle
+ all packets into nfnetlink queue number 0. Userspace users will have
+ to link against API-compatible library on top of libnfnetlink_queue
+ instead of the current 'libipq'.
+Who: Harald Welte <laforge@netfilter.org>
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt
new file mode 100644
index 000000000000..8c206f4e0250
--- /dev/null
+++ b/Documentation/filesystems/files.txt
@@ -0,0 +1,123 @@
+File management in the Linux kernel
+-----------------------------------
+
+This document describes how locking for files (struct file)
+and file descriptor table (struct files) works.
+
+Up until 2.6.12, the file descriptor table has been protected
+with a lock (files->file_lock) and reference count (files->count).
+->file_lock protected accesses to all the file related fields
+of the table. ->count was used for sharing the file descriptor
+table between tasks cloned with CLONE_FILES flag. Typically
+this would be the case for posix threads. As with the common
+refcounting model in the kernel, the last task doing
+a put_files_struct() frees the file descriptor (fd) table.
+The files (struct file) themselves are protected using
+reference count (->f_count).
+
+In the new lock-free model of file descriptor management,
+the reference counting is similar, but the locking is
+based on RCU. The file descriptor table contains multiple
+elements - the fd sets (open_fds and close_on_exec, the
+array of file pointers, the sizes of the sets and the array
+etc.). In order for the updates to appear atomic to
+a lock-free reader, all the elements of the file descriptor
+table are in a separate structure - struct fdtable.
+files_struct contains a pointer to struct fdtable through
+which the actual fd table is accessed. Initially the
+fdtable is embedded in files_struct itself. On a subsequent
+expansion of fdtable, a new fdtable structure is allocated
+and files->fdtab points to the new structure. The fdtable
+structure is freed with RCU and lock-free readers either
+see the old fdtable or the new fdtable making the update
+appear atomic. Here are the locking rules for
+the fdtable structure -
+
+1. All references to the fdtable must be done through
+ the files_fdtable() macro :
+
+ struct fdtable *fdt;
+
+ rcu_read_lock();
+
+ fdt = files_fdtable(files);
+ ....
+ if (n <= fdt->max_fds)
+ ....
+ ...
+ rcu_read_unlock();
+
+ files_fdtable() uses rcu_dereference() macro which takes care of
+ the memory barrier requirements for lock-free dereference.
+ The fdtable pointer must be read within the read-side
+ critical section.
+
+2. Reading of the fdtable as described above must be protected
+ by rcu_read_lock()/rcu_read_unlock().
+
+3. For any update to the the fd table, files->file_lock must
+ be held.
+
+4. To look up the file structure given an fd, a reader
+ must use either fcheck() or fcheck_files() APIs. These
+ take care of barrier requirements due to lock-free lookup.
+ An example :
+
+ struct file *file;
+
+ rcu_read_lock();
+ file = fcheck(fd);
+ if (file) {
+ ...
+ }
+ ....
+ rcu_read_unlock();
+
+5. Handling of the file structures is special. Since the look-up
+ of the fd (fget()/fget_light()) are lock-free, it is possible
+ that look-up may race with the last put() operation on the
+ file structure. This is avoided using the rcuref APIs
+ on ->f_count :
+
+ rcu_read_lock();
+ file = fcheck_files(files, fd);
+ if (file) {
+ if (rcuref_inc_lf(&file->f_count))
+ *fput_needed = 1;
+ else
+ /* Didn't get the reference, someone's freed */
+ file = NULL;
+ }
+ rcu_read_unlock();
+ ....
+ return file;
+
+ rcuref_inc_lf() detects if refcounts is already zero or
+ goes to zero during increment. If it does, we fail
+ fget()/fget_light().
+
+6. Since both fdtable and file structures can be looked up
+ lock-free, they must be installed using rcu_assign_pointer()
+ API. If they are looked up lock-free, rcu_dereference()
+ must be used. However it is advisable to use files_fdtable()
+ and fcheck()/fcheck_files() which take care of these issues.
+
+7. While updating, the fdtable pointer must be looked up while
+ holding files->file_lock. If ->file_lock is dropped, then
+ another thread expand the files thereby creating a new
+ fdtable and making the earlier fdtable pointer stale.
+ For example :
+
+ spin_lock(&files->file_lock);
+ fd = locate_fd(files, file, start);
+ if (fd >= 0) {
+ /* locate_fd() may have expanded fdtable, load the ptr */
+ fdt = files_fdtable(files);
+ FD_SET(fd, fdt->open_fds);
+ FD_CLR(fd, fdt->close_on_exec);
+ spin_unlock(&files->file_lock);
+ .....
+
+ Since locate_fd() can drop ->file_lock (and reacquire ->file_lock),
+ the fdtable pointer (fdt) must be loaded after locate_fd().
+
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
new file mode 100644
index 000000000000..6b5741e651a2
--- /dev/null
+++ b/Documentation/filesystems/fuse.txt
@@ -0,0 +1,315 @@
+Definitions
+~~~~~~~~~~~
+
+Userspace filesystem:
+
+ A filesystem in which data and metadata are provided by an ordinary
+ userspace process. The filesystem can be accessed normally through
+ the kernel interface.
+
+Filesystem daemon:
+
+ The process(es) providing the data and metadata of the filesystem.
+
+Non-privileged mount (or user mount):
+
+ A userspace filesystem mounted by a non-privileged (non-root) user.
+ The filesystem daemon is running with the privileges of the mounting
+ user. NOTE: this is not the same as mounts allowed with the "user"
+ option in /etc/fstab, which is not discussed here.
+
+Mount owner:
+
+ The user who does the mounting.
+
+User:
+
+ The user who is performing filesystem operations.
+
+What is FUSE?
+~~~~~~~~~~~~~
+
+FUSE is a userspace filesystem framework. It consists of a kernel
+module (fuse.ko), a userspace library (libfuse.*) and a mount utility
+(fusermount).
+
+One of the most important features of FUSE is allowing secure,
+non-privileged mounts. This opens up new possibilities for the use of
+filesystems. A good example is sshfs: a secure network filesystem
+using the sftp protocol.
+
+The userspace library and utilities are available from the FUSE
+homepage:
+
+ http://fuse.sourceforge.net/
+
+Mount options
+~~~~~~~~~~~~~
+
+'fd=N'
+
+ The file descriptor to use for communication between the userspace
+ filesystem and the kernel. The file descriptor must have been
+ obtained by opening the FUSE device ('/dev/fuse').
+
+'rootmode=M'
+
+ The file mode of the filesystem's root in octal representation.
+
+'user_id=N'
+
+ The numeric user id of the mount owner.
+
+'group_id=N'
+
+ The numeric group id of the mount owner.
+
+'default_permissions'
+
+ By default FUSE doesn't check file access permissions, the
+ filesystem is free to implement it's access policy or leave it to
+ the underlying file access mechanism (e.g. in case of network
+ filesystems). This option enables permission checking, restricting
+ access based on file mode. This is option is usually useful
+ together with the 'allow_other' mount option.
+
+'allow_other'
+
+ This option overrides the security measure restricting file access
+ to the user mounting the filesystem. This option is by default only
+ allowed to root, but this restriction can be removed with a
+ (userspace) configuration option.
+
+'max_read=N'
+
+ With this option the maximum size of read operations can be set.
+ The default is infinite. Note that the size of read requests is
+ limited anyway to 32 pages (which is 128kbyte on i386).
+
+How do non-privileged mounts work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the mount() system call is a privileged operation, a helper
+program (fusermount) is needed, which is installed setuid root.
+
+The implication of providing non-privileged mounts is that the mount
+owner must not be able to use this capability to compromise the
+system. Obvious requirements arising from this are:
+
+ A) mount owner should not be able to get elevated privileges with the
+ help of the mounted filesystem
+
+ B) mount owner should not get illegitimate access to information from
+ other users' and the super user's processes
+
+ C) mount owner should not be able to induce undesired behavior in
+ other users' or the super user's processes
+
+How are requirements fulfilled?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ A) The mount owner could gain elevated privileges by either:
+
+ 1) creating a filesystem containing a device file, then opening
+ this device
+
+ 2) creating a filesystem containing a suid or sgid application,
+ then executing this application
+
+ The solution is not to allow opening device files and ignore
+ setuid and setgid bits when executing programs. To ensure this
+ fusermount always adds "nosuid" and "nodev" to the mount options
+ for non-privileged mounts.
+
+ B) If another user is accessing files or directories in the
+ filesystem, the filesystem daemon serving requests can record the
+ exact sequence and timing of operations performed. This
+ information is otherwise inaccessible to the mount owner, so this
+ counts as an information leak.
+
+ The solution to this problem will be presented in point 2) of C).
+
+ C) There are several ways in which the mount owner can induce
+ undesired behavior in other users' processes, such as:
+
+ 1) mounting a filesystem over a file or directory which the mount
+ owner could otherwise not be able to modify (or could only
+ make limited modifications).
+
+ This is solved in fusermount, by checking the access
+ permissions on the mountpoint and only allowing the mount if
+ the mount owner can do unlimited modification (has write
+ access to the mountpoint, and mountpoint is not a "sticky"
+ directory)
+
+ 2) Even if 1) is solved the mount owner can change the behavior
+ of other users' processes.
+
+ i) It can slow down or indefinitely delay the execution of a
+ filesystem operation creating a DoS against the user or the
+ whole system. For example a suid application locking a
+ system file, and then accessing a file on the mount owner's
+ filesystem could be stopped, and thus causing the system
+ file to be locked forever.
+
+ ii) It can present files or directories of unlimited length, or
+ directory structures of unlimited depth, possibly causing a
+ system process to eat up diskspace, memory or other
+ resources, again causing DoS.
+
+ The solution to this as well as B) is not to allow processes
+ to access the filesystem, which could otherwise not be
+ monitored or manipulated by the mount owner. Since if the
+ mount owner can ptrace a process, it can do all of the above
+ without using a FUSE mount, the same criteria as used in
+ ptrace can be used to check if a process is allowed to access
+ the filesystem or not.
+
+ Note that the ptrace check is not strictly necessary to
+ prevent B/2/i, it is enough to check if mount owner has enough
+ privilege to send signal to the process accessing the
+ filesystem, since SIGSTOP can be used to get a similar effect.
+
+I think these limitations are unacceptable?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a sysadmin trusts the users enough, or can ensure through other
+measures, that system processes will never enter non-privileged
+mounts, it can relax the last limitation with a "user_allow_other"
+config option. If this config option is set, the mounting user can
+add the "allow_other" mount option which disables the check for other
+users' processes.
+
+Kernel - userspace interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following diagram shows how a filesystem operation (in this
+example unlink) is performed in FUSE.
+
+NOTE: everything in this description is greatly simplified
+
+ | "rm /mnt/fuse/file" | FUSE filesystem daemon
+ | |
+ | | >sys_read()
+ | | >fuse_dev_read()
+ | | >request_wait()
+ | | [sleep on fc->waitq]
+ | |
+ | >sys_unlink() |
+ | >fuse_unlink() |
+ | [get request from |
+ | fc->unused_list] |
+ | >request_send() |
+ | [queue req on fc->pending] |
+ | [wake up fc->waitq] | [woken up]
+ | >request_wait_answer() |
+ | [sleep on req->waitq] |
+ | | <request_wait()
+ | | [remove req from fc->pending]
+ | | [copy req to read buffer]
+ | | [add req to fc->processing]
+ | | <fuse_dev_read()
+ | | <sys_read()
+ | |
+ | | [perform unlink]
+ | |
+ | | >sys_write()
+ | | >fuse_dev_write()
+ | | [look up req in fc->processing]
+ | | [remove from fc->processing]
+ | | [copy write buffer to req]
+ | [woken up] | [wake up req->waitq]
+ | | <fuse_dev_write()
+ | | <sys_write()
+ | <request_wait_answer() |
+ | <request_send() |
+ | [add request to |
+ | fc->unused_list] |
+ | <fuse_unlink() |
+ | <sys_unlink() |
+
+There are a couple of ways in which to deadlock a FUSE filesystem.
+Since we are talking about unprivileged userspace programs,
+something must be done about these.
+
+Scenario 1 - Simple deadlock
+-----------------------------
+
+ | "rm /mnt/fuse/file" | FUSE filesystem daemon
+ | |
+ | >sys_unlink("/mnt/fuse/file") |
+ | [acquire inode semaphore |
+ | for "file"] |
+ | >fuse_unlink() |
+ | [sleep on req->waitq] |
+ | | <sys_read()
+ | | >sys_unlink("/mnt/fuse/file")
+ | | [acquire inode semaphore
+ | | for "file"]
+ | | *DEADLOCK*
+
+The solution for this is to allow requests to be interrupted while
+they are in userspace:
+
+ | [interrupted by signal] |
+ | <fuse_unlink() |
+ | [release semaphore] | [semaphore acquired]
+ | <sys_unlink() |
+ | | >fuse_unlink()
+ | | [queue req on fc->pending]
+ | | [wake up fc->waitq]
+ | | [sleep on req->waitq]
+
+If the filesystem daemon was single threaded, this will stop here,
+since there's no other thread to dequeue and execute the request.
+In this case the solution is to kill the FUSE daemon as well. If
+there are multiple serving threads, you just have to kill them as
+long as any remain.
+
+Moral: a filesystem which deadlocks, can soon find itself dead.
+
+Scenario 2 - Tricky deadlock
+----------------------------
+
+This one needs a carefully crafted filesystem. It's a variation on
+the above, only the call back to the filesystem is not explicit,
+but is caused by a pagefault.
+
+ | Kamikaze filesystem thread 1 | Kamikaze filesystem thread 2
+ | |
+ | [fd = open("/mnt/fuse/file")] | [request served normally]
+ | [mmap fd to 'addr'] |
+ | [close fd] | [FLUSH triggers 'magic' flag]
+ | [read a byte from addr] |
+ | >do_page_fault() |
+ | [find or create page] |
+ | [lock page] |
+ | >fuse_readpage() |
+ | [queue READ request] |
+ | [sleep on req->waitq] |
+ | | [read request to buffer]
+ | | [create reply header before addr]
+ | | >sys_write(addr - headerlength)
+ | | >fuse_dev_write()
+ | | [look up req in fc->processing]
+ | | [remove from fc->processing]
+ | | [copy write buffer to req]
+ | | >do_page_fault()
+ | | [find or create page]
+ | | [lock page]
+ | | * DEADLOCK *
+
+Solution is again to let the the request be interrupted (not
+elaborated further).
+
+An additional problem is that while the write buffer is being
+copied to the request, the request must not be interrupted. This
+is because the destination address of the copy may not be valid
+after the request is interrupted.
+
+This is solved with doing the copy atomically, and allowing
+interruption while the page(s) belonging to the write buffer are
+faulted with get_user_pages(). The 'req->locked' flag indicates
+when the copy is taking place, and interruption is delayed until
+this flag is unset.
+
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index eef4aca0c753..a5fbc8e897fa 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -439,6 +439,18 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
+2.1.24:
+ - Support journals ($LogFile) which have been modified by chkdsk. This
+ means users can boot into Windows after we marked the volume dirty.
+ The Windows boot will run chkdsk and then reboot. The user can then
+ immediately boot into Linux rather than having to do a full Windows
+ boot first before rebooting into Linux and we will recognize such a
+ journal and empty it as it is clean by definition.
+ - Support journals ($LogFile) with only one restart page as well as
+ journals with two different restart pages. We sanity check both and
+ either use the only sane one or the more recent one of the two in the
+ case that both are valid.
+ - Lots of bug fixes and enhancements across the board.
2.1.23:
- Stamp the user space journal, aka transaction log, aka $UsnJrnl, if
it is present and active thus telling Windows and applications using
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 6c98f2bd421e..d4773565ea2f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -133,6 +133,7 @@ Table 1-1: Process specific entries in /proc
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
+ smaps Extension based on maps, presenting the rss size for each mapped file
..............................................................................
For example, to get the status information of a process, all you have to do is
@@ -1240,16 +1241,38 @@ swap-intensive.
overcommit_memory
-----------------
-This file contains one value. The following algorithm is used to decide if
-there's enough memory: if the value of overcommit_memory is positive, then
-there's always enough memory. This is a useful feature, since programs often
-malloc() huge amounts of memory 'just in case', while they only use a small
-part of it. Leaving this value at 0 will lead to the failure of such a huge
-malloc(), when in fact the system has enough memory for the program to run.
+Controls overcommit of system memory, possibly allowing processes
+to allocate (but not use) more memory than is actually available.
-On the other hand, enabling this feature can cause you to run out of memory
-and thrash the system to death, so large and/or important servers will want to
-set this value to 0.
+
+0 - Heuristic overcommit handling. Obvious overcommits of
+ address space are refused. Used for a typical system. It
+ ensures a seriously wild allocation fails while allowing
+ overcommit to reduce swap usage. root is allowed to
+ allocate slighly more memory in this mode. This is the
+ default.
+
+1 - Always overcommit. Appropriate for some scientific
+ applications.
+
+2 - Don't overcommit. The total address space commit
+ for the system is not permitted to exceed swap plus a
+ configurable percentage (default is 50) of physical RAM.
+ Depending on the percentage you use, in most situations
+ this means a process will not be killed while attempting
+ to use already-allocated memory but will receive errors
+ on memory allocation as appropriate.
+
+overcommit_ratio
+----------------
+
+Percentage of physical memory size to include in overcommit calculations
+(see above.)
+
+Memory allocation limit = swapspace + physmem * (overcommit_ratio / 100)
+
+ swapspace = total size of all swap areas
+ physmem = size of physical memory in system
nr_hugepages and hugetlb_shm_group
----------------------------------
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
new file mode 100644
index 000000000000..d24e1b0d4f39
--- /dev/null
+++ b/Documentation/filesystems/relayfs.txt
@@ -0,0 +1,362 @@
+
+relayfs - a high-speed data relay filesystem
+============================================
+
+relayfs is a filesystem designed to provide an efficient mechanism for
+tools and facilities to relay large and potentially sustained streams
+of data from kernel space to user space.
+
+The main abstraction of relayfs is the 'channel'. A channel consists
+of a set of per-cpu kernel buffers each represented by a file in the
+relayfs filesystem. Kernel clients write into a channel using
+efficient write functions which automatically log to the current cpu's
+channel buffer. User space applications mmap() the per-cpu files and
+retrieve the data as it becomes available.
+
+The format of the data logged into the channel buffers is completely
+up to the relayfs client; relayfs does however provide hooks which
+allow clients to impose some stucture on the buffer data. Nor does
+relayfs implement any form of data filtering - this also is left to
+the client. The purpose is to keep relayfs as simple as possible.
+
+This document provides an overview of the relayfs API. The details of
+the function parameters are documented along with the functions in the
+filesystem code - please see that for details.
+
+Semantics
+=========
+
+Each relayfs channel has one buffer per CPU, each buffer has one or
+more sub-buffers. Messages are written to the first sub-buffer until
+it is too full to contain a new message, in which case it it is
+written to the next (if available). Messages are never split across
+sub-buffers. At this point, userspace can be notified so it empties
+the first sub-buffer, while the kernel continues writing to the next.
+
+When notified that a sub-buffer is full, the kernel knows how many
+bytes of it are padding i.e. unused. Userspace can use this knowledge
+to copy only valid data.
+
+After copying it, userspace can notify the kernel that a sub-buffer
+has been consumed.
+
+relayfs can operate in a mode where it will overwrite data not yet
+collected by userspace, and not wait for it to consume it.
+
+relayfs itself does not provide for communication of such data between
+userspace and kernel, allowing the kernel side to remain simple and not
+impose a single interface on userspace. It does provide a separate
+helper though, described below.
+
+klog, relay-app & librelay
+==========================
+
+relayfs itself is ready to use, but to make things easier, two
+additional systems are provided. klog is a simple wrapper to make
+writing formatted text or raw data to a channel simpler, regardless of
+whether a channel to write into exists or not, or whether relayfs is
+compiled into the kernel or is configured as a module. relay-app is
+the kernel counterpart of userspace librelay.c, combined these two
+files provide glue to easily stream data to disk, without having to
+bother with housekeeping. klog and relay-app can be used together,
+with klog providing high-level logging functions to the kernel and
+relay-app taking care of kernel-user control and disk-logging chores.
+
+It is possible to use relayfs without relay-app & librelay, but you'll
+have to implement communication between userspace and kernel, allowing
+both to convey the state of buffers (full, empty, amount of padding).
+
+klog, relay-app and librelay can be found in the relay-apps tarball on
+http://relayfs.sourceforge.net
+
+The relayfs user space API
+==========================
+
+relayfs implements basic file operations for user space access to
+relayfs channel buffer data. Here are the file operations that are
+available and some comments regarding their behavior:
+
+open() enables user to open an _existing_ buffer.
+
+mmap() results in channel buffer being mapped into the caller's
+ memory space. Note that you can't do a partial mmap - you must
+ map the entire file, which is NRBUF * SUBBUFSIZE.
+
+read() read the contents of a channel buffer. The bytes read are
+ 'consumed' by the reader i.e. they won't be available again
+ to subsequent reads. If the channel is being used in
+ no-overwrite mode (the default), it can be read at any time
+ even if there's an active kernel writer. If the channel is
+ being used in overwrite mode and there are active channel
+ writers, results may be unpredictable - users should make
+ sure that all logging to the channel has ended before using
+ read() with overwrite mode.
+
+poll() POLLIN/POLLRDNORM/POLLERR supported. User applications are
+ notified when sub-buffer boundaries are crossed.
+
+close() decrements the channel buffer's refcount. When the refcount
+ reaches 0 i.e. when no process or kernel client has the buffer
+ open, the channel buffer is freed.
+
+
+In order for a user application to make use of relayfs files, the
+relayfs filesystem must be mounted. For example,
+
+ mount -t relayfs relayfs /mnt/relay
+
+NOTE: relayfs doesn't need to be mounted for kernel clients to create
+ or use channels - it only needs to be mounted when user space
+ applications need access to the buffer data.
+
+
+The relayfs kernel API
+======================
+
+Here's a summary of the API relayfs provides to in-kernel clients:
+
+
+ channel management functions:
+
+ relay_open(base_filename, parent, subbuf_size, n_subbufs,
+ callbacks)
+ relay_close(chan)
+ relay_flush(chan)
+ relay_reset(chan)
+ relayfs_create_dir(name, parent)
+ relayfs_remove_dir(dentry)
+
+ channel management typically called on instigation of userspace:
+
+ relay_subbufs_consumed(chan, cpu, subbufs_consumed)
+
+ write functions:
+
+ relay_write(chan, data, length)
+ __relay_write(chan, data, length)
+ relay_reserve(chan, length)
+
+ callbacks:
+
+ subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
+ buf_mapped(buf, filp)
+ buf_unmapped(buf, filp)
+
+ helper functions:
+
+ relay_buf_full(buf)
+ subbuf_start_reserve(buf, length)
+
+
+Creating a channel
+------------------
+
+relay_open() is used to create a channel, along with its per-cpu
+channel buffers. Each channel buffer will have an associated file
+created for it in the relayfs filesystem, which can be opened and
+mmapped from user space if desired. The files are named
+basename0...basenameN-1 where N is the number of online cpus, and by
+default will be created in the root of the filesystem. If you want a
+directory structure to contain your relayfs files, you can create it
+with relayfs_create_dir() and pass the parent directory to
+relay_open(). Clients are responsible for cleaning up any directory
+structure they create when the channel is closed - use
+relayfs_remove_dir() for that.
+
+The total size of each per-cpu buffer is calculated by multiplying the
+number of sub-buffers by the sub-buffer size passed into relay_open().
+The idea behind sub-buffers is that they're basically an extension of
+double-buffering to N buffers, and they also allow applications to
+easily implement random-access-on-buffer-boundary schemes, which can
+be important for some high-volume applications. The number and size
+of sub-buffers is completely dependent on the application and even for
+the same application, different conditions will warrant different
+values for these parameters at different times. Typically, the right
+values to use are best decided after some experimentation; in general,
+though, it's safe to assume that having only 1 sub-buffer is a bad
+idea - you're guaranteed to either overwrite data or lose events
+depending on the channel mode being used.
+
+Channel 'modes'
+---------------
+
+relayfs channels can be used in either of two modes - 'overwrite' or
+'no-overwrite'. The mode is entirely determined by the implementation
+of the subbuf_start() callback, as described below. In 'overwrite'
+mode, also known as 'flight recorder' mode, writes continuously cycle
+around the buffer and will never fail, but will unconditionally
+overwrite old data regardless of whether it's actually been consumed.
+In no-overwrite mode, writes will fail i.e. data will be lost, if the
+number of unconsumed sub-buffers equals the total number of
+sub-buffers in the channel. It should be clear that if there is no
+consumer or if the consumer can't consume sub-buffers fast enought,
+data will be lost in either case; the only difference is whether data
+is lost from the beginning or the end of a buffer.
+
+As explained above, a relayfs channel is made of up one or more
+per-cpu channel buffers, each implemented as a circular buffer
+subdivided into one or more sub-buffers. Messages are written into
+the current sub-buffer of the channel's current per-cpu buffer via the
+write functions described below. Whenever a message can't fit into
+the current sub-buffer, because there's no room left for it, the
+client is notified via the subbuf_start() callback that a switch to a
+new sub-buffer is about to occur. The client uses this callback to 1)
+initialize the next sub-buffer if appropriate 2) finalize the previous
+sub-buffer if appropriate and 3) return a boolean value indicating
+whether or not to actually go ahead with the sub-buffer switch.
+
+To implement 'no-overwrite' mode, the userspace client would provide
+an implementation of the subbuf_start() callback something like the
+following:
+
+static int subbuf_start(struct rchan_buf *buf,
+ void *subbuf,
+ void *prev_subbuf,
+ unsigned int prev_padding)
+{
+ if (prev_subbuf)
+ *((unsigned *)prev_subbuf) = prev_padding;
+
+ if (relay_buf_full(buf))
+ return 0;
+
+ subbuf_start_reserve(buf, sizeof(unsigned int));
+
+ return 1;
+}
+
+If the current buffer is full i.e. all sub-buffers remain unconsumed,
+the callback returns 0 to indicate that the buffer switch should not
+occur yet i.e. until the consumer has had a chance to read the current
+set of ready sub-buffers. For the relay_buf_full() function to make
+sense, the consumer is reponsible for notifying relayfs when
+sub-buffers have been consumed via relay_subbufs_consumed(). Any
+subsequent attempts to write into the buffer will again invoke the
+subbuf_start() callback with the same parameters; only when the
+consumer has consumed one or more of the ready sub-buffers will
+relay_buf_full() return 0, in which case the buffer switch can
+continue.
+
+The implementation of the subbuf_start() callback for 'overwrite' mode
+would be very similar:
+
+static int subbuf_start(struct rchan_buf *buf,
+ void *subbuf,
+ void *prev_subbuf,
+ unsigned int prev_padding)
+{
+ if (prev_subbuf)
+ *((unsigned *)prev_subbuf) = prev_padding;
+
+ subbuf_start_reserve(buf, sizeof(unsigned int));
+
+ return 1;
+}
+
+In this case, the relay_buf_full() check is meaningless and the
+callback always returns 1, causing the buffer switch to occur
+unconditionally. It's also meaningless for the client to use the
+relay_subbufs_consumed() function in this mode, as it's never
+consulted.
+
+The default subbuf_start() implementation, used if the client doesn't
+define any callbacks, or doesn't define the subbuf_start() callback,
+implements the simplest possible 'no-overwrite' mode i.e. it does
+nothing but return 0.
+
+Header information can be reserved at the beginning of each sub-buffer
+by calling the subbuf_start_reserve() helper function from within the
+subbuf_start() callback. This reserved area can be used to store
+whatever information the client wants. In the example above, room is
+reserved in each sub-buffer to store the padding count for that
+sub-buffer. This is filled in for the previous sub-buffer in the
+subbuf_start() implementation; the padding value for the previous
+sub-buffer is passed into the subbuf_start() callback along with a
+pointer to the previous sub-buffer, since the padding value isn't
+known until a sub-buffer is filled. The subbuf_start() callback is
+also called for the first sub-buffer when the channel is opened, to
+give the client a chance to reserve space in it. In this case the
+previous sub-buffer pointer passed into the callback will be NULL, so
+the client should check the value of the prev_subbuf pointer before
+writing into the previous sub-buffer.
+
+Writing to a channel
+--------------------
+
+kernel clients write data into the current cpu's channel buffer using
+relay_write() or __relay_write(). relay_write() is the main logging
+function - it uses local_irqsave() to protect the buffer and should be
+used if you might be logging from interrupt context. If you know
+you'll never be logging from interrupt context, you can use
+__relay_write(), which only disables preemption. These functions
+don't return a value, so you can't determine whether or not they
+failed - the assumption is that you wouldn't want to check a return
+value in the fast logging path anyway, and that they'll always succeed
+unless the buffer is full and no-overwrite mode is being used, in
+which case you can detect a failed write in the subbuf_start()
+callback by calling the relay_buf_full() helper function.
+
+relay_reserve() is used to reserve a slot in a channel buffer which
+can be written to later. This would typically be used in applications
+that need to write directly into a channel buffer without having to
+stage data in a temporary buffer beforehand. Because the actual write
+may not happen immediately after the slot is reserved, applications
+using relay_reserve() can keep a count of the number of bytes actually
+written, either in space reserved in the sub-buffers themselves or as
+a separate array. See the 'reserve' example in the relay-apps tarball
+at http://relayfs.sourceforge.net for an example of how this can be
+done. Because the write is under control of the client and is
+separated from the reserve, relay_reserve() doesn't protect the buffer
+at all - it's up to the client to provide the appropriate
+synchronization when using relay_reserve().
+
+Closing a channel
+-----------------
+
+The client calls relay_close() when it's finished using the channel.
+The channel and its associated buffers are destroyed when there are no
+longer any references to any of the channel buffers. relay_flush()
+forces a sub-buffer switch on all the channel buffers, and can be used
+to finalize and process the last sub-buffers before the channel is
+closed.
+
+Misc
+----
+
+Some applications may want to keep a channel around and re-use it
+rather than open and close a new channel for each use. relay_reset()
+can be used for this purpose - it resets a channel to its initial
+state without reallocating channel buffer memory or destroying
+existing mappings. It should however only be called when it's safe to
+do so i.e. when the channel isn't currently being written to.
+
+Finally, there are a couple of utility callbacks that can be used for
+different purposes. buf_mapped() is called whenever a channel buffer
+is mmapped from user space and buf_unmapped() is called when it's
+unmapped. The client can use this notification to trigger actions
+within the kernel application, such as enabling/disabling logging to
+the channel.
+
+
+Resources
+=========
+
+For news, example code, mailing list, etc. see the relayfs homepage:
+
+ http://relayfs.sourceforge.net
+
+
+Credits
+=======
+
+The ideas and specs for relayfs came about as a result of discussions
+on tracing involving the following:
+
+Michel Dagenais <michel.dagenais@polymtl.ca>
+Richard Moore <richardj_moore@uk.ibm.com>
+Bob Wisniewski <bob@watson.ibm.com>
+Karim Yaghmour <karim@opersys.com>
+Tom Zanussi <zanussi@us.ibm.com>
+
+Also thanks to Hubertus Franke for a lot of useful suggestions and bug
+reports.
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index dc276598a65a..c8bce82ddcac 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
It also defines this helper for defining device attributes:
-#define DEVICE_ATTR(_name,_mode,_show,_store) \
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = { \
.attr = {.name = __stringify(_name) , .mode = _mode }, \
.show = _show, \
@@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
For example, declaring
-static DEVICE_ATTR(foo,0644,show_foo,store_foo);
+static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
is equivalent to doing:
static struct device_attribute dev_attr_foo = {
.attr = {
.name = "foo",
- .mode = 0644,
+ .mode = S_IWUSR | S_IRUGO,
},
.show = show_foo,
.store = store_foo,
@@ -121,8 +121,8 @@ set of sysfs operations for forwarding read and write calls to the
show and store methods of the attribute owners.
struct sysfs_ops {
- ssize_t (*show)(struct kobject *, struct attribute *,char *);
- ssize_t (*store)(struct kobject *,struct attribute *,const char *);
+ ssize_t (*show)(struct kobject *, struct attribute *, char *);
+ ssize_t (*store)(struct kobject *, struct attribute *, const char *);
};
[ Subsystems should have already defined a struct kobj_type as a
@@ -137,7 +137,7 @@ calls the associated methods.
To illustrate:
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
#define to_dev(d) container_of(d, struct device, kobj)
static ssize_t
@@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
ssize_t ret = 0;
if (dev_attr->show)
- ret = dev_attr->show(dev,buf);
+ ret = dev_attr->show(dev, buf);
return ret;
}
@@ -216,16 +216,16 @@ A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- return sprintf(buf,"%s\n",dev->name);
+ return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
}
static ssize_t store_name(struct device * dev, const char * buf)
{
- sscanf(buf,"%20s",dev->name);
- return strlen(buf);
+ sscanf(buf, "%20s", dev->name);
+ return strnlen(buf, PAGE_SIZE);
}
-static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
+static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(Note that the real implementation doesn't allow userspace to set the
@@ -290,7 +290,7 @@ struct device_attribute {
Declaring:
-DEVICE_ATTR(_name,_str,_mode,_show,_store);
+DEVICE_ATTR(_name, _str, _mode, _show, _store);
Creation/Removal:
@@ -310,7 +310,7 @@ struct bus_attribute {
Declaring:
-BUS_ATTR(_name,_mode,_show,_store)
+BUS_ATTR(_name, _mode, _show, _store)
Creation/Removal:
@@ -331,7 +331,7 @@ struct driver_attribute {
Declaring:
-DRIVER_ATTR(_name,_mode,_show,_store)
+DRIVER_ATTR(_name, _mode, _show, _store)
Creation/Removal:
diff --git a/Documentation/filesystems/v9fs.txt b/Documentation/filesystems/v9fs.txt
new file mode 100644
index 000000000000..4e92feb6b507
--- /dev/null
+++ b/Documentation/filesystems/v9fs.txt
@@ -0,0 +1,95 @@
+ V9FS: 9P2000 for Linux
+ ======================
+
+ABOUT
+=====
+
+v9fs is a Unix implementation of the Plan 9 9p remote filesystem protocol.
+
+This software was originally developed by Ron Minnich <rminnich@lanl.gov>
+and Maya Gokhale <maya@lanl.gov>. Additional development by Greg Watson
+<gwatson@lanl.gov> and most recently Eric Van Hensbergen
+<ericvh@gmail.com> and Latchesar Ionkov <lucho@ionkov.net>.
+
+USAGE
+=====
+
+For remote file server:
+
+ mount -t 9P 10.10.1.2 /mnt/9
+
+For Plan 9 From User Space applications (http://swtch.com/plan9)
+
+ mount -t 9P `namespace`/acme /mnt/9 -o proto=unix,name=$USER
+
+OPTIONS
+=======
+
+ proto=name select an alternative transport. Valid options are
+ currently:
+ unix - specifying a named pipe mount point
+ tcp - specifying a normal TCP/IP connection
+ fd - used passed file descriptors for connection
+ (see rfdno and wfdno)
+
+ name=name user name to attempt mount as on the remote server. The
+ server may override or ignore this value. Certain user
+ names may require authentication.
+
+ aname=name aname specifies the file tree to access when the server is
+ offering several exported file systems.
+
+ debug=n specifies debug level. The debug level is a bitmask.
+ 0x01 = display verbose error messages
+ 0x02 = developer debug (DEBUG_CURRENT)
+ 0x04 = display 9P trace
+ 0x08 = display VFS trace
+ 0x10 = display Marshalling debug
+ 0x20 = display RPC debug
+ 0x40 = display transport debug
+ 0x80 = display allocation debug
+
+ rfdno=n the file descriptor for reading with proto=fd
+
+ wfdno=n the file descriptor for writing with proto=fd
+
+ maxdata=n the number of bytes to use for 9P packet payload (msize)
+
+ port=n port to connect to on the remote server
+
+ timeout=n request timeouts (in ms) (default 60000ms)
+
+ noextend force legacy mode (no 9P2000.u semantics)
+
+ uid attempt to mount as a particular uid
+
+ gid attempt to mount with a particular gid
+
+ afid security channel - used by Plan 9 authentication protocols
+
+ nodevmap do not map special files - represent them as normal files.
+ This can be used to share devices/named pipes/sockets between
+ hosts. This functionality will be expanded in later versions.
+
+RESOURCES
+=========
+
+The Linux version of the 9P server, along with some client-side utilities
+can be found at http://v9fs.sf.net (along with a CVS repository of the
+development branch of this module). There are user and developer mailing
+lists here, as well as a bug-tracker.
+
+For more information on the Plan 9 Operating System check out
+http://plan9.bell-labs.com/plan9
+
+For information on Plan 9 from User Space (Plan 9 applications and libraries
+ported to Linux/BSD/OSX/etc) check out http://swtch.com/plan9
+
+
+STATUS
+======
+
+The 2.6 kernel support is working on PPC and x86.
+
+PLEASE USE THE SOURCEFORGE BUG-TRACKER TO REPORT PROBLEMS.
+
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 3f318dd44c77..f042c12e0ed2 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -1,35 +1,27 @@
-/* -*- auto-fill -*- */
- Overview of the Virtual File System
+ Overview of the Linux Virtual File System
- Richard Gooch <rgooch@atnf.csiro.au>
+ Original author: Richard Gooch <rgooch@atnf.csiro.au>
- 5-JUL-1999
+ Last updated on August 25, 2005
+ Copyright (C) 1999 Richard Gooch
+ Copyright (C) 2005 Pekka Enberg
-Conventions used in this document <section>
-=================================
+ This file is released under the GPLv2.
-Each section in this document will have the string "<section>" at the
-right-hand side of the section title. Each subsection will have
-"<subsection>" at the right-hand side. These strings are meant to make
-it easier to search through the document.
-NOTE that the master copy of this document is available online at:
-http://www.atnf.csiro.au/~rgooch/linux/docs/vfs.txt
-
-
-What is it? <section>
+What is it?
===========
The Virtual File System (otherwise known as the Virtual Filesystem
Switch) is the software layer in the kernel that provides the
filesystem interface to userspace programs. It also provides an
abstraction within the kernel which allows different filesystem
-implementations to co-exist.
+implementations to coexist.
-A Quick Look At How It Works <section>
+A Quick Look At How It Works
============================
In this section I'll briefly describe how things work, before
@@ -38,7 +30,8 @@ when user programs open and manipulate files, and then look from the
other view which is how a filesystem is supported and subsequently
mounted.
-Opening a File <subsection>
+
+Opening a File
--------------
The VFS implements the open(2), stat(2), chmod(2) and similar system
@@ -77,7 +70,7 @@ back to userspace.
Opening a file requires another operation: allocation of a file
structure (this is the kernel-side implementation of file
-descriptors). The freshly allocated file structure is initialised with
+descriptors). The freshly allocated file structure is initialized with
a pointer to the dentry and a set of file operation member functions.
These are taken from the inode data. The open() file method is then
called so the specific filesystem implementation can do it's work. You
@@ -102,7 +95,8 @@ filesystem or driver code at the same time, on different
processors. You should ensure that access to shared resources is
protected by appropriate locks.
-Registering and Mounting a Filesystem <subsection>
+
+Registering and Mounting a Filesystem
-------------------------------------
If you want to support a new kind of filesystem in the kernel, all you
@@ -123,17 +117,21 @@ updated to point to the root inode for the new filesystem.
It's now time to look at things in more detail.
-struct file_system_type <section>
+struct file_system_type
=======================
-This describes the filesystem. As of kernel 2.1.99, the following
+This describes the filesystem. As of kernel 2.6.13, the following
members are defined:
struct file_system_type {
const char *name;
int fs_flags;
- struct super_block *(*read_super) (struct super_block *, void *, int);
- struct file_system_type * next;
+ struct super_block *(*get_sb) (struct file_system_type *, int,
+ const char *, void *);
+ void (*kill_sb) (struct super_block *);
+ struct module *owner;
+ struct file_system_type * next;
+ struct list_head fs_supers;
};
name: the name of the filesystem type, such as "ext2", "iso9660",
@@ -141,51 +139,97 @@ struct file_system_type {
fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
- read_super: the method to call when a new instance of this
+ get_sb: the method to call when a new instance of this
filesystem should be mounted
- next: for internal VFS use: you should initialise this to NULL
+ kill_sb: the method to call when an instance of this filesystem
+ should be unmounted
+
+ owner: for internal VFS use: you should initialize this to THIS_MODULE in
+ most cases.
-The read_super() method has the following arguments:
+ next: for internal VFS use: you should initialize this to NULL
+
+The get_sb() method has the following arguments:
struct super_block *sb: the superblock structure. This is partially
- initialised by the VFS and the rest must be initialised by the
- read_super() method
+ initialized by the VFS and the rest must be initialized by the
+ get_sb() method
+
+ int flags: mount flags
+
+ const char *dev_name: the device name we are mounting.
void *data: arbitrary mount options, usually comes as an ASCII
string
int silent: whether or not to be silent on error
-The read_super() method must determine if the block device specified
+The get_sb() method must determine if the block device specified
in the superblock contains a filesystem of the type the method
supports. On success the method returns the superblock pointer, on
failure it returns NULL.
The most interesting member of the superblock structure that the
-read_super() method fills in is the "s_op" field. This is a pointer to
+get_sb() method fills in is the "s_op" field. This is a pointer to
a "struct super_operations" which describes the next level of the
filesystem implementation.
+Usually, a filesystem uses generic one of the generic get_sb()
+implementations and provides a fill_super() method instead. The
+generic methods are:
+
+ get_sb_bdev: mount a filesystem residing on a block device
-struct super_operations <section>
+ get_sb_nodev: mount a filesystem that is not backed by a device
+
+ get_sb_single: mount a filesystem which shares the instance between
+ all mounts
+
+A fill_super() method implementation has the following arguments:
+
+ struct super_block *sb: the superblock structure. The method fill_super()
+ must initialize this properly.
+
+ void *data: arbitrary mount options, usually comes as an ASCII
+ string
+
+ int silent: whether or not to be silent on error
+
+
+struct super_operations
=======================
This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.1.99, the following members are defined:
+filesystem. As of kernel 2.6.13, the following members are defined:
struct super_operations {
- void (*read_inode) (struct inode *);
- int (*write_inode) (struct inode *, int);
- void (*put_inode) (struct inode *);
- void (*drop_inode) (struct inode *);
- void (*delete_inode) (struct inode *);
- int (*notify_change) (struct dentry *, struct iattr *);
- void (*put_super) (struct super_block *);
- void (*write_super) (struct super_block *);
- int (*statfs) (struct super_block *, struct statfs *, int);
- int (*remount_fs) (struct super_block *, int *, char *);
- void (*clear_inode) (struct inode *);
+ struct inode *(*alloc_inode)(struct super_block *sb);
+ void (*destroy_inode)(struct inode *);
+
+ void (*read_inode) (struct inode *);
+
+ void (*dirty_inode) (struct inode *);
+ int (*write_inode) (struct inode *, int);
+ void (*put_inode) (struct inode *);
+ void (*drop_inode) (struct inode *);
+ void (*delete_inode) (struct inode *);
+ void (*put_super) (struct super_block *);
+ void (*write_super) (struct super_block *);
+ int (*sync_fs)(struct super_block *sb, int wait);
+ void (*write_super_lockfs) (struct super_block *);
+ void (*unlockfs) (struct super_block *);
+ int (*statfs) (struct super_block *, struct kstatfs *);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ void (*clear_inode) (struct inode *);
+ void (*umount_begin) (struct super_block *);
+
+ void (*sync_inodes) (struct super_block *sb,
+ struct writeback_control *wbc);
+ int (*show_options)(struct seq_file *, struct vfsmount *);
+
+ ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+ ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
};
All methods are called without any locks being held, unless otherwise
@@ -193,43 +237,62 @@ noted. This means that most methods can block safely. All methods are
only called from a process context (i.e. not from an interrupt handler
or bottom half).
+ alloc_inode: this method is called by inode_alloc() to allocate memory
+ for struct inode and initialize it.
+
+ destroy_inode: this method is called by destroy_inode() to release
+ resources allocated for struct inode.
+
read_inode: this method is called to read a specific inode from the
- mounted filesystem. The "i_ino" member in the "struct inode"
- will be initialised by the VFS to indicate which inode to
- read. Other members are filled in by this method
+ mounted filesystem. The i_ino member in the struct inode is
+ initialized by the VFS to indicate which inode to read. Other
+ members are filled in by this method.
+
+ You can set this to NULL and use iget5_locked() instead of iget()
+ to read inodes. This is necessary for filesystems for which the
+ inode number is not sufficient to identify an inode.
+
+ dirty_inode: this method is called by the VFS to mark an inode dirty.
write_inode: this method is called when the VFS needs to write an
inode to disc. The second parameter indicates whether the write
should be synchronous or not, not all filesystems check this flag.
put_inode: called when the VFS inode is removed from the inode
- cache. This method is optional
+ cache.
drop_inode: called when the last access to the inode is dropped,
with the inode_lock spinlock held.
- This method should be either NULL (normal unix filesystem
+ This method should be either NULL (normal UNIX filesystem
semantics) or "generic_delete_inode" (for filesystems that do not
want to cache inodes - causing "delete_inode" to always be
called regardless of the value of i_nlink)
- The "generic_delete_inode()" behaviour is equivalent to the
+ The "generic_delete_inode()" behavior is equivalent to the
old practice of using "force_delete" in the put_inode() case,
but does not have the races that the "force_delete()" approach
had.
delete_inode: called when the VFS wants to delete an inode
- notify_change: called when VFS inode attributes are changed. If this
- is NULL the VFS falls back to the write_inode() method. This
- is called with the kernel lock held
-
put_super: called when the VFS wishes to free the superblock
(i.e. unmount). This is called with the superblock lock held
write_super: called when the VFS superblock needs to be written to
disc. This method is optional
+ sync_fs: called when VFS is writing out all dirty data associated with
+ a superblock. The second parameter indicates whether the method
+ should wait until the write out has been completed. Optional.
+
+ write_super_lockfs: called when VFS is locking a filesystem and forcing
+ it into a consistent state. This function is currently used by the
+ Logical Volume Manager (LVM).
+
+ unlockfs: called when VFS is unlocking a filesystem and making it writable
+ again.
+
statfs: called when the VFS needs to get filesystem statistics. This
is called with the kernel lock held
@@ -238,21 +301,31 @@ or bottom half).
clear_inode: called then the VFS clears the inode. Optional
+ umount_begin: called when the VFS is unmounting a filesystem.
+
+ sync_inodes: called when the VFS is writing out dirty data associated with
+ a superblock.
+
+ show_options: called by the VFS to show mount options for /proc/<pid>/mounts.
+
+ quota_read: called by the VFS to read from filesystem quota file.
+
+ quota_write: called by the VFS to write to filesystem quota file.
+
The read_inode() method is responsible for filling in the "i_op"
field. This is a pointer to a "struct inode_operations" which
describes the methods that can be performed on individual inodes.
-struct inode_operations <section>
+struct inode_operations
=======================
This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.1.99, the following members are defined:
+filesystem. As of kernel 2.6.13, the following members are defined:
struct inode_operations {
- struct file_operations * default_file_ops;
- int (*create) (struct inode *,struct dentry *,int);
- int (*lookup) (struct inode *,struct dentry *);
+ int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+ struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -261,25 +334,22 @@ struct inode_operations {
int (*mknod) (struct inode *,struct dentry *,int,dev_t);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- struct dentry * (*follow_link) (struct dentry *, struct dentry *);
- int (*readpage) (struct file *, struct page *);
- int (*writepage) (struct page *page, struct writeback_control *wbc);
- int (*bmap) (struct inode *,int);
+ int (*readlink) (struct dentry *, char __user *,int);
+ void * (*follow_link) (struct dentry *, struct nameidata *);
+ void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*smap) (struct inode *,int);
- int (*updatepage) (struct file *, struct page *, const char *,
- unsigned long, unsigned int, int);
- int (*revalidate) (struct dentry *);
+ int (*permission) (struct inode *, int, struct nameidata *);
+ int (*setattr) (struct dentry *, struct iattr *);
+ int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+ ssize_t (*listxattr) (struct dentry *, char *, size_t);
+ int (*removexattr) (struct dentry *, const char *);
};
Again, all methods are called without any locks being held, unless
otherwise noted.
- default_file_ops: this is a pointer to a "struct file_operations"
- which describes how to open and then manipulate open files
-
create: called by the open(2) and creat(2) system calls. Only
required if you want to support regular files. The dentry you
get should not have an inode (i.e. it should be a negative
@@ -328,31 +398,143 @@ otherwise noted.
you want to support reading symbolic links
follow_link: called by the VFS to follow a symbolic link to the
- inode it points to. Only required if you want to support
- symbolic links
+ inode it points to. Only required if you want to support
+ symbolic links. This function returns a void pointer cookie
+ that is passed to put_link().
+
+ put_link: called by the VFS to release resources allocated by
+ follow_link(). The cookie returned by follow_link() is passed to
+ to this function as the last parameter. It is used by filesystems
+ such as NFS where page cache is not stable (i.e. page that was
+ installed when the symbolic link walk started might not be in the
+ page cache at the end of the walk).
+
+ truncate: called by the VFS to change the size of a file. The i_size
+ field of the inode is set to the desired size by the VFS before
+ this function is called. This function is called by the truncate(2)
+ system call and related functionality.
+
+ permission: called by the VFS to check for access rights on a POSIX-like
+ filesystem.
+
+ setattr: called by the VFS to set attributes for a file. This function is
+ called by chmod(2) and related system calls.
+
+ getattr: called by the VFS to get attributes of a file. This function is
+ called by stat(2) and related system calls.
+
+ setxattr: called by the VFS to set an extended attribute for a file.
+ Extended attribute is a name:value pair associated with an inode. This
+ function is called by setxattr(2) system call.
+
+ getxattr: called by the VFS to retrieve the value of an extended attribute
+ name. This function is called by getxattr(2) function call.
+
+ listxattr: called by the VFS to list all extended attributes for a given
+ file. This function is called by listxattr(2) system call.
+
+ removexattr: called by the VFS to remove an extended attribute from a file.
+ This function is called by removexattr(2) system call.
+
+
+struct address_space_operations
+===============================
+
+This describes how the VFS can manipulate mapping of a file to page cache in
+your filesystem. As of kernel 2.6.13, the following members are defined:
+
+struct address_space_operations {
+ int (*writepage)(struct page *page, struct writeback_control *wbc);
+ int (*readpage)(struct file *, struct page *);
+ int (*sync_page)(struct page *);
+ int (*writepages)(struct address_space *, struct writeback_control *);
+ int (*set_page_dirty)(struct page *page);
+ int (*readpages)(struct file *filp, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages);
+ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
+ int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+ sector_t (*bmap)(struct address_space *, sector_t);
+ int (*invalidatepage) (struct page *, unsigned long);
+ int (*releasepage) (struct page *, int);
+ ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+ struct page* (*get_xip_page)(struct address_space *, sector_t,
+ int);
+};
+
+ writepage: called by the VM write a dirty page to backing store.
+
+ readpage: called by the VM to read a page from backing store.
+
+ sync_page: called by the VM to notify the backing store to perform all
+ queued I/O operations for a page. I/O operations for other pages
+ associated with this address_space object may also be performed.
+
+ writepages: called by the VM to write out pages associated with the
+ address_space object.
+
+ set_page_dirty: called by the VM to set a page dirty.
+
+ readpages: called by the VM to read pages associated with the address_space
+ object.
+ prepare_write: called by the generic write path in VM to set up a write
+ request for a page.
-struct file_operations <section>
+ commit_write: called by the generic write path in VM to write page to
+ its backing store.
+
+ bmap: called by the VFS to map a logical block offset within object to
+ physical block number. This method is use by for the legacy FIBMAP
+ ioctl. Other uses are discouraged.
+
+ invalidatepage: called by the VM on truncate to disassociate a page from its
+ address_space mapping.
+
+ releasepage: called by the VFS to release filesystem specific metadata from
+ a page.
+
+ direct_IO: called by the VM for direct I/O writes and reads.
+
+ get_xip_page: called by the VM to translate a block number to a page.
+ The page is valid until the corresponding filesystem is unmounted.
+ Filesystems that want to use execute-in-place (XIP) need to implement
+ it. An example implementation can be found in fs/ext2/xip.c.
+
+
+struct file_operations
======================
This describes how the VFS can manipulate an open file. As of kernel
-2.1.99, the following members are defined:
+2.6.13, the following members are defined:
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
- ssize_t (*read) (struct file *, char *, size_t, loff_t *);
- ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
+ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
+ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+ long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
+ int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
- int (*fsync) (struct file *, struct dentry *);
- int (*fasync) (struct file *, int);
- int (*check_media_change) (kdev_t dev);
- int (*revalidate) (kdev_t dev);
+ int (*fsync) (struct file *, struct dentry *, int datasync);
+ int (*aio_fsync) (struct kiocb *, int datasync);
+ int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
+ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
+ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
+ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
+ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
+ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+ int (*check_flags)(int);
+ int (*dir_notify)(struct file *filp, unsigned long arg);
+ int (*flock) (struct file *, int, struct file_lock *);
};
Again, all methods are called without any locks being held, unless
@@ -362,8 +544,12 @@ otherwise noted.
read: called by read(2) and related system calls
+ aio_read: called by io_submit(2) and other asynchronous I/O operations
+
write: called by write(2) and related system calls
+ aio_write: called by io_submit(2) and other asynchronous I/O operations
+
readdir: called when the VFS needs to read the directory contents
poll: called by the VFS when a process wants to check if there is
@@ -372,18 +558,25 @@ otherwise noted.
ioctl: called by the ioctl(2) system call
+ unlocked_ioctl: called by the ioctl(2) system call. Filesystems that do not
+ require the BKL should use this method instead of the ioctl() above.
+
+ compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
+ are used on 64 bit kernels.
+
mmap: called by the mmap(2) system call
open: called by the VFS when an inode should be opened. When the VFS
- opens a file, it creates a new "struct file" and initialises
- the "f_op" file operations member with the "default_file_ops"
- field in the inode structure. It then calls the open method
- for the newly allocated file structure. You might think that
- the open method really belongs in "struct inode_operations",
- and you may be right. I think it's done the way it is because
- it makes filesystems simpler to implement. The open() method
- is a good place to initialise the "private_data" member in the
- file structure if you want to point to a device structure
+ opens a file, it creates a new "struct file". It then calls the
+ open method for the newly allocated file structure. You might
+ think that the open method really belongs in
+ "struct inode_operations", and you may be right. I think it's
+ done the way it is because it makes filesystems simpler to
+ implement. The open() method is a good place to initialize the
+ "private_data" member in the file structure if you want to point
+ to a device structure
+
+ flush: called by the close(2) system call to flush a file
release: called when the last reference to an open file is closed
@@ -392,6 +585,23 @@ otherwise noted.
fasync: called by the fcntl(2) system call when asynchronous
(non-blocking) mode is enabled for a file
+ lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW
+ commands
+
+ readv: called by the readv(2) system call
+
+ writev: called by the writev(2) system call
+
+ sendfile: called by the sendfile(2) system call
+
+ get_unmapped_area: called by the mmap(2) system call
+
+ check_flags: called by the fcntl(2) system call for F_SETFL command
+
+ dir_notify: called by the fcntl(2) system call for F_NOTIFY command
+
+ flock: called by the flock(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
@@ -400,29 +610,28 @@ driver information. These support routines replace the filesystem file
operations with those for the device driver, and then proceed to call
the new open() method for the file. This is how opening a device file
in the filesystem eventually ends up calling the device driver open()
-method. Note the devfs (the Device FileSystem) has a more direct path
-from device node to device driver (this is an unofficial kernel
-patch).
+method.
-Directory Entry Cache (dcache) <section>
-------------------------------
+Directory Entry Cache (dcache)
+==============================
+
struct dentry_operations
-========================
+------------------------
This describes how a filesystem can overload the standard dentry
operations. Dentries and the dcache are the domain of the VFS and the
individual filesystem implementations. Device drivers have no business
here. These methods may be set to NULL, as they are either optional or
-the VFS uses a default. As of kernel 2.1.99, the following members are
+the VFS uses a default. As of kernel 2.6.13, the following members are
defined:
struct dentry_operations {
- int (*d_revalidate)(struct dentry *);
+ int (*d_revalidate)(struct dentry *, struct nameidata *);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
- void (*d_delete)(struct dentry *);
+ int (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
};
@@ -451,6 +660,7 @@ Each dentry has a pointer to its parent dentry, as well as a hash list
of child dentries. Child dentries are basically like files in a
directory.
+
Directory Entry Cache APIs
--------------------------
@@ -471,7 +681,7 @@ manipulate dentries:
"d_delete" method is called
d_drop: this unhashes a dentry from its parents hash list. A
- subsequent call to dput() will dellocate the dentry if its
+ subsequent call to dput() will deallocate the dentry if its
usage count drops to 0
d_delete: delete a dentry. If there are no other open references to
@@ -507,16 +717,16 @@ up by walking the tree starting with the first component
of the pathname and using that dentry along with the next
component to look up the next level and so on. Since it
is a frequent operation for workloads like multiuser
-environments and webservers, it is important to optimize
+environments and web servers, it is important to optimize
this path.
Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus
in every component during path look-up. Since 2.5.10 onwards,
-fastwalk algorithm changed this by holding the dcache_lock
+fast-walk algorithm changed this by holding the dcache_lock
at the beginning and walking as many cached path component
-dentries as possible. This signficantly decreases the number
+dentries as possible. This significantly decreases the number
of acquisition of dcache_lock. However it also increases the
-lock hold time signficantly and affects performance in large
+lock hold time significantly and affects performance in large
SMP machines. Since 2.5.62 kernel, dcache has been using
a new locking model that uses RCU to make dcache look-up
lock-free.
@@ -527,7 +737,7 @@ protected the hash chain, d_child, d_alias, d_lru lists as well
as d_inode and several other things like mount look-up. RCU-based
changes affect only the way the hash chain is protected. For everything
else the dcache_lock must be taken for both traversing as well as
-updating. The hash chain updations too take the dcache_lock.
+updating. The hash chain updates too take the dcache_lock.
The significant change is the way d_lookup traverses the hash chain,
it doesn't acquire the dcache_lock for this and rely on RCU to
ensure that the dentry has not been *freed*.
@@ -535,14 +745,15 @@ ensure that the dentry has not been *freed*.
Dcache locking details
----------------------
+
For many multi-user workloads, open() and stat() on files are
very frequently occurring operations. Both involve walking
of path names to find the dentry corresponding to the
concerned file. In 2.4 kernel, dcache_lock was held
during look-up of each path component. Contention and
-cacheline bouncing of this global lock caused significant
+cache-line bouncing of this global lock caused significant
scalability problems. With the introduction of RCU
-in linux kernel, this was worked around by making
+in Linux kernel, this was worked around by making
the look-up of path components during path walking lock-free.
@@ -562,7 +773,7 @@ Some of the important changes are :
2. Insertion of a dentry into the hash table is done using
hlist_add_head_rcu() which take care of ordering the writes -
the writes to the dentry must be visible before the dentry
- is inserted. This works in conjuction with hlist_for_each_rcu()
+ is inserted. This works in conjunction with hlist_for_each_rcu()
while walking the hash chain. The only requirement is that
all initialization to the dentry must be done before hlist_add_head_rcu()
since we don't have dcache_lock protection while traversing
@@ -584,7 +795,7 @@ Some of the important changes are :
the same. In some sense, dcache_rcu path walking looks like
the pre-2.5.10 version.
-5. All dentry hash chain updations must take the dcache_lock as well as
+5. All dentry hash chain updates must take the dcache_lock as well as
the per-dentry lock in that order. dput() does this to ensure
that a dentry that has just been looked up in another CPU
doesn't get deleted before dget() can be done on it.
@@ -640,10 +851,10 @@ handled as described below :
Since we redo the d_parent check and compare name while holding
d_lock, lock-free look-up will not race against d_move().
-4. There can be a theoritical race when a dentry keeps coming back
+4. There can be a theoretical race when a dentry keeps coming back
to original bucket due to double moves. Due to this look-up may
consider that it has never moved and can end up in a infinite loop.
- But this is not any worse that theoritical livelocks we already
+ But this is not any worse that theoretical livelocks we already
have in the kernel.
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index e1c56a7e6583..4bef8c25172c 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -32,14 +32,14 @@ static void sample_firmware_load(char *firmware, int size)
u8 buf[size+1];
memcpy(buf, firmware, size);
buf[size] = '\0';
- printk("firmware_sample_driver: firmware: %s\n", buf);
+ printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
}
static void sample_probe_default(void)
{
/* uses the default method to get the firmware */
const struct firmware *fw_entry;
- printk("firmware_sample_driver: a ghost device got inserted :)\n");
+ printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0)
{
@@ -61,7 +61,7 @@ static void sample_probe_specific(void)
/* NOTE: This currently doesn't work */
- printk("firmware_sample_driver: a ghost device got inserted :)\n");
+ printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0)
{
@@ -83,7 +83,7 @@ static void sample_probe_async_cont(const struct firmware *fw, void *context)
return;
}
- printk("firmware_sample_driver: device pointer \"%s\"\n",
+ printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
(char *)context);
sample_firmware_load(fw->data, fw->size);
}
diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78
index 357086ed7f64..fd5dc7a19f0e 100644
--- a/Documentation/hwmon/lm78
+++ b/Documentation/hwmon/lm78
@@ -2,16 +2,11 @@ Kernel driver lm78
==================
Supported chips:
- * National Semiconductor LM78
+ * National Semiconductor LM78 / LM78-J
Prefix: 'lm78'
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
- * National Semiconductor LM78-J
- Prefix: 'lm78-j'
- Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
- Datasheet: Publicly available at the National Semiconductor website
- http://www.national.com/
* National Semiconductor LM79
Prefix: 'lm79'
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
diff --git a/Documentation/hwmon/w83792d b/Documentation/hwmon/w83792d
new file mode 100644
index 000000000000..8171c285bb55
--- /dev/null
+++ b/Documentation/hwmon/w83792d
@@ -0,0 +1,174 @@
+Kernel driver w83792d
+=====================
+
+Supported chips:
+ * Winbond W83792D
+ Prefix: 'w83792d'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
+
+Author: Chunhao Huang
+Contact: DZShen <DZShen@Winbond.com.tw>
+
+
+Module Parameters
+-----------------
+
+* init int
+ (default 1)
+ Use 'init=0' to bypass initializing the chip.
+ Try this if your computer crashes when you load the module.
+
+* force_subclients=bus,caddr,saddr,saddr
+ This is used to force the i2c addresses for subclients of
+ a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
+ to force the subclients of chip 0x2f on bus 0 to i2c addresses
+ 0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for the Winbond W83792AD/D.
+
+Detection of the chip can sometimes be foiled because it can be in an
+internal state that allows no clean access (Bank with ID register is not
+currently selected). If you know the address of the chip, use a 'force'
+parameter; this will put it into a more well-behaved state first.
+
+The driver implements three temperature sensors, seven fan rotation speed
+sensors, nine voltage sensors, and two automatic fan regulation
+strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
+Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
+synchronized with selected fan (fan1-fan3). This functionality and manual PWM
+control for fan4-fan7 is not yet implemented.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
+128) to give the readings more range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+Alarms are provided as output from "realtime status register". Following bits
+are defined:
+
+bit - alarm on:
+0 - in0
+1 - in1
+2 - temp1
+3 - temp2
+4 - temp3
+5 - fan1
+6 - fan2
+7 - fan3
+8 - in2
+9 - in3
+10 - in4
+11 - in5
+12 - in6
+13 - VID change
+14 - chassis
+15 - fan7
+16 - tart1
+17 - tart2
+18 - tart3
+19 - in7
+20 - in8
+21 - fan4
+22 - fan5
+23 - fan6
+
+Tart will be asserted while target temperature cannot be achieved after 3 minutes
+of full speed rotation of corresponding fan.
+
+In addition to the alarms described above, there is a CHAS alarm on the chips
+which triggers if your computer case is open (This one is latched, contrary
+to realtime alarms).
+
+The chips only update values each 3 seconds; reading them more often will
+do no harm, but will return 'old' values.
+
+
+W83792D PROBLEMS
+----------------
+Known problems:
+ - This driver is only for Winbond W83792D C version device, there
+ are also some motherboards with B version W83792D device. The
+ calculation method to in6-in7(measured value, limits) is a little
+ different between C and B version. C or B version can be identified
+ by CR[0x49h].
+ - The function of vid and vrm has not been finished, because I'm NOT
+ very familiar with them. Adding support is welcome.
+  - The function of chassis open detection needs more tests.
+ - If you have ASUS server board and chip was not found: Then you will
+ need to upgrade to latest (or beta) BIOS. If it does not help please
+ contact us.
+
+Fan control
+-----------
+
+Manual mode
+-----------
+
+Works as expected. You just need to specify desired PWM/DC value (fan speed)
+in appropriate pwm# file.
+
+Thermal cruise
+--------------
+
+In this mode, W83792D provides the Smart Fan system to automatically control
+fan speed to keep the temperatures of CPU and the system within specific
+range. At first a wanted temperature and interval must be set. This is done
+via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
+interval. The fan speed will be lowered as long as the current temperature
+remains below the thermal_cruise# +- tolerance# value. Once the temperature
+exceeds the high limit (T+tolerance), the fan will be turned on with a
+specific speed set by pwm# and automatically controlled its PWM duty cycle
+with the temperature varying. Three conditions may occur:
+
+(1) If the temperature still exceeds the high limit, PWM duty
+cycle will increase slowly.
+
+(2) If the temperature goes below the high limit, but still above the low
+limit (T-tolerance), the fan speed will be fixed at the current speed because
+the temperature is in the target range.
+
+(3) If the temperature goes below the low limit, PWM duty cycle will decrease
+slowly to 0 or a preset stop value until the temperature exceeds the low
+limit. (The preset stop value handling is not yet implemented in driver)
+
+Smart Fan II
+------------
+
+W83792D also provides a special mode for fan. Four temperature points are
+available. When related temperature sensors detects the temperature in preset
+temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
+on programmed value from sf2_level@_fan#. You need to set four temperatures
+for each fan.
+
+
+/sys files
+----------
+
+pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
+ 0 (stop) to 255 (full)
+pwm[1-3]_enable - this file controls mode of fan/temperature control:
+ * 0 Disabled
+ * 1 Manual mode
+ * 2 Smart Fan II
+ * 3 Thermal Cruise
+pwm[1-3]_mode - Select PWM of DC mode
+ * 0 DC
+ * 1 PWM
+thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
+tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
+sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
+sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index b02002898a09..96fec562a8e9 100644
--- a/Documentation/i2c/chips/max6875
+++ b/Documentation/i2c/chips/max6875
@@ -4,22 +4,13 @@ Kernel driver max6875
Supported chips:
* Maxim MAX6874, MAX6875
Prefix: 'max6875'
- Addresses scanned: 0x50, 0x52
+ Addresses scanned: None (see below)
Datasheet:
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
Author: Ben Gardner <bgardner@wabtec.com>
-Module Parameters
------------------
-
-* allow_write int
- Set to non-zero to enable write permission:
- *0: Read only
- 1: Read and write
-
-
Description
-----------
@@ -33,34 +24,85 @@ registers.
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
and outputs:
-
vin gpi vout
MAX6874 6 4 8
MAX6875 4 3 5
-MAX6874 chips can have four different addresses (as opposed to only two for
-the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
-this driver by default, but the probe module parameter can be used if
-needed.
-
-See the datasheet for details on how to program the EEPROM.
+See the datasheet for more information.
Sysfs entries
-------------
-eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
- allow_write was set and register 0x43 is 0.
-
-eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
- loaded into register space until a power cycle or device reset.
-
-reg_config - 70 bytes of register space. Any changes take affect immediately.
+eeprom - 512 bytes of user-defined EEPROM space.
General Remarks
---------------
-A typical application will require that the EEPROMs be programmed once and
-never altered afterwards.
+Valid addresses for the MAX6875 are 0x50 and 0x52.
+Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
+The driver does not probe any address, so you must force the address.
+
+Example:
+$ modprobe max6875 force=0,0x50
+
+The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
+addresses. For example, for address 0x50, it also reserves 0x51.
+The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
+
+
+Programming the chip using i2c-dev
+----------------------------------
+
+Use the i2c-dev interface to access and program the chips.
+Reads and writes are performed differently depending on the address range.
+
+The configuration registers are at addresses 0x00 - 0x45.
+Use i2c_smbus_write_byte_data() to write a register and
+i2c_smbus_read_byte_data() to read a register.
+The command is the register number.
+
+Examples:
+To write a 1 to register 0x45:
+ i2c_smbus_write_byte_data(fd, 0x45, 1);
+
+To read register 0x45:
+ value = i2c_smbus_read_byte_data(fd, 0x45);
+
+
+The configuration EEPROM is at addresses 0x8000 - 0x8045.
+The user EEPROM is at addresses 0x8100 - 0x82ff.
+
+Use i2c_smbus_write_word_data() to write a byte to EEPROM.
+
+The command is the upper byte of the address: 0x80, 0x81, or 0x82.
+The data word is the lower part of the address or'd with data << 8.
+ cmd = address >> 8;
+ val = (address & 0xff) | (data << 8);
+
+Example:
+To write 0x5a to address 0x8003:
+ i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
+
+
+Reading data from the EEPROM is a little more complicated.
+Use i2c_smbus_write_byte_data() to set the read address and then
+i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
+
+Example:
+To read data starting at offset 0x8100, first set the address:
+ i2c_smbus_write_byte_data(fd, 0x81, 0x00);
+
+And then read the data
+ value = i2c_smbus_read_byte(fd);
+
+ or
+
+ count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+
+The block read should read 16 bytes.
+0x84 is the block read command.
+
+See the datasheet for more details.
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 8a78a95ae04e..41ffefbdc60c 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
If you try to access an adapter from a userspace program, you will have
to use the /dev interface. You will still have to check whether the
functionality you need is supported, of course. This is done using
-the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
+the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
program, is below:
int file;
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index a7adbdd9ea8a..4849dfd6961c 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -1,4 +1,4 @@
-Revision 4, 2004-03-30
+Revision 5, 2005-07-29
Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com>
@@ -17,20 +17,22 @@ yours for best results.
Technical changes:
-* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
- <linux/i2c-sensor.h>. Includes typically look like that:
+* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
+ Includes typically look like that:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
- #include <linux/i2c-sensor.h>
- #include <linux/i2c-vid.h> /* if you need VRM support */
+ #include <linux/hwmon.h> /* for hardware monitoring drivers */
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/hwmon-vid.h> /* if you need VRM support */
#include <asm/io.h> /* if you have I/O operations */
Please respect this inclusion order. Some extra headers may be
required for a given driver (e.g. "lm75.h").
-* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
- becomes I2C_CLIENT_ISA_END.
+* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
+ are no more handled by the i2c core.
+ SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
* [Client data] Get rid of sysctl_id. Try using standard names for
register values (for example, temp_os becomes temp_max). You're
@@ -66,13 +68,15 @@ Technical changes:
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
ISA-only drivers of course don't need this.
+ Call i2c_probe() instead of i2c_detect().
* [Detect] As mentioned earlier, the flags parameter is gone.
The type_name and client_name strings are replaced by a single
name string, which will be filled with a lowercase, short string
(typically the driver name, e.g. "lm75").
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
- useless.
+ useless. Same for isa-only drivers, as the test would always be
+ true. Only hybrid drivers (which are quite rare) still need it.
The errorN labels are reduced to the number needed. If that number
is 2 (i2c-only drivers), it is advised that the labels are named
exit and exit_free. For i2c+isa drivers, labels should be named
@@ -86,6 +90,8 @@ Technical changes:
device_create_file. Move the driver initialization before any
sysfs file creation.
Drop client->id.
+ Drop any 24RF08 corruption prevention you find, as this is now done
+ at the i2c-core level, and doing it twice voids it.
* [Init] Limits must not be set by the driver (can be done later in
user-space). Chip should not be reset default (although a module
@@ -93,7 +99,8 @@ Technical changes:
limited to the strictly necessary steps.
* [Detach] Get rid of data, remove the call to
- i2c_deregister_entry.
+ i2c_deregister_entry. Do not log an error message if
+ i2c_detach_client fails, as i2c-core will now do it for you.
* [Update] Don't access client->data directly, use
i2c_get_clientdata(client) instead.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 91664be91ffc..077275722a7c 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
detection algorithm.
You do not have to use this parameter interface; but don't try to use
-function i2c_probe() (or i2c_detect()) if you don't.
+function i2c_probe() if you don't.
NOTE: If you want to write a `sensors' driver, the interface is slightly
different! See below.
-Probing classes (i2c)
----------------------
+Probing classes
+---------------
All parameters are given as lists of unsigned 16-bit integers. Lists are
terminated by I2C_CLIENT_END.
@@ -171,12 +171,18 @@ The following lists are used internally:
ignore: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. These addresses are never probed.
- This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+ This parameter overrules the 'normal_i2c' list only.
force: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. A device is blindly assumed to be on
the given address, no probing is done.
+Additionally, kind-specific force lists may optionally be defined if
+the driver supports several chip kinds. They are grouped in a
+NULL-terminated list of pointers named forces, those first element if the
+generic force list mentioned above. Each additional list correspond to an
+insmod parameter of the form force_<kind>.
+
Fortunately, as a module writer, you just have to define the `normal_i2c'
parameter. The complete declaration could look like this:
@@ -186,66 +192,17 @@ parameter. The complete declaration could look like this:
/* Magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
+ /* Or, if your driver supports, say, 2 kind of devices: */
+ I2C_CLIENT_INSMOD_2(foo, bar);
+
+If you use the multi-kind form, an enum will be defined for you:
+ enum chips { any_chip, foo, bar, ... }
+You can then (and certainly should) use it in the driver code.
Note that you *have* to call the defined variable `normal_i2c',
without any prefix!
-Probing classes (sensors)
--------------------------
-
-If you write a `sensors' driver, you use a slightly different interface.
-As well as I2C addresses, we have to cope with ISA addresses. Also, we
-use a enum of chip types. Don't forget to include `sensors.h'.
-
-The following lists are used internally. They are all lists of integers.
-
- normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
- A list of I2C addresses which should normally be examined.
- normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
- A list of ISA addresses which should normally be examined.
- probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
- A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the address. These
- addresses are also probed, as if they were in the 'normal' list.
- ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
- A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the I2C address. These
- addresses are never probed. This parameter overrules 'normal' and
- 'probe', but not the 'force' lists.
-
-Also used is a list of pointers to sensors_force_data structures:
- force_data: insmod parameters. A list, ending with an element of which
- the force field is NULL.
- Each element contains the type of chip and a list of pairs.
- The first value is a bus number (SENSORS_ISA_BUS for the ISA bus,
- -1 for any I2C bus), the second is the address.
- These are automatically translated to insmod variables of the form
- force_foo.
-
-So we have a generic insmod variabled `force', and chip-specific variables
-`force_CHIPNAME'.
-
-Fortunately, as a module writer, you just have to define the `normal_i2c'
-and `normal_isa' parameters, and define what chip names are used.
-The complete declaration could look like this:
- /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
- static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
- 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
- /* Scan ISA address 0x290 */
- static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
-
- /* Define chips foo and bar, as well as all module parameters and things */
- SENSORS_INSMOD_2(foo,bar);
-
-If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
-you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
-bother with chip types, you can use SENSORS_INSMOD_0.
-
-A enum is automatically defined as follows:
- enum chips { any_chip, chip1, chip2, ... }
-
-
Attaching to an adapter
-----------------------
@@ -264,17 +221,10 @@ detected at a specific address, another callback is called.
return i2c_probe(adapter,&addr_data,&foo_detect_client);
}
-For `sensors' drivers, use the i2c_detect function instead:
-
- int foo_attach_adapter(struct i2c_adapter *adapter)
- {
- return i2c_detect(adapter,&addr_data,&foo_detect_client);
- }
-
Remember, structure `addr_data' is defined by the macros explained above,
so you do not have to define it yourself.
-The i2c_probe or i2c_detect function will call the foo_detect_client
+The i2c_probe function will call the foo_detect_client
function only for those i2c addresses that actually have a device on
them (unless a `force' parameter was used). In addition, addresses that
are already in use (by some other registered client) are skipped.
@@ -283,19 +233,18 @@ are already in use (by some other registered client) are skipped.
The detect client function
--------------------------
-The detect client function is called by i2c_probe or i2c_detect.
-The `kind' parameter contains 0 if this call is due to a `force'
-parameter, and -1 otherwise (for i2c_detect, it contains 0 if
-this call is due to the generic `force' parameter, and the chip type
-number if it is due to a specific `force' parameter).
+The detect client function is called by i2c_probe. The `kind' parameter
+contains -1 for a probed detection, 0 for a forced detection, or a positive
+number for a forced detection with a chip type forced.
Below, some things are only needed if this is a `sensors' driver. Those
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
markers.
-This function should only return an error (any value != 0) if there is
-some reason why no more detection should be done anymore. If the
-detection just fails for this address, return 0.
+Returning an error different from -ENODEV in a detect function will cause
+the detection to stop: other addresses and adapters won't be scanned.
+This should only be done on fatal or internal errors, such as a memory
+shortage or i2c_attach_client failing.
For now, you can ignore the `flags' parameter. It is there for future use.
@@ -320,11 +269,10 @@ For now, you can ignore the `flags' parameter. It is there for future use.
const char *type_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
- if (is_isa) {
+ /* Do this only if the chip can additionally be found on the ISA bus
+ (hybrid chip). */
- /* If this client can't be on the ISA bus at all, we can stop now
- (call `goto ERROR0'). But for kicks, we will assume it is all
- right. */
+ if (is_isa) {
/* Discard immediately if this ISA range is already used */
if (check_region(address,FOO_EXTENT))
@@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
/* SENSORS ONLY END */
/* Try to detach the client from i2c space */
- if ((err = i2c_detach_client(client))) {
- printk("foo.o: Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
- /* SENSORS ONLY START */
+ /* HYBRID SENSORS CHIP ONLY START */
if i2c_is_isa_client(client)
release_region(client->addr,LM78_EXTENT);
- /* SENSORS ONLY END */
+ /* HYBRID SENSORS CHIP ONLY END */
kfree(client); /* Frees client data too, if allocated at the same time */
return 0;
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index 1c48f0eba6fb..10312bebe55d 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -2,7 +2,7 @@
----------------------------
H. Peter Anvin <hpa@zytor.com>
- Last update 2002-01-01
+ Last update 2005-09-02
On the i386 platform, the Linux kernel uses a rather complicated boot
convention. This has evolved partially due to historical aspects, as
@@ -34,6 +34,8 @@ Protocol 2.02: (Kernel 2.4.0-test3-pre3) New command line protocol.
Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
initrd address available to the bootloader.
+Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
+
**** MEMORY LAYOUT
@@ -103,10 +105,9 @@ The header looks like:
Offset Proto Name Meaning
/Size
-01F1/1 ALL setup_sects The size of the setup in sectors
+01F1/1 ALL(1 setup_sects The size of the setup in sectors
01F2/2 ALL root_flags If set, the root is mounted readonly
-01F4/2 ALL syssize DO NOT USE - for bootsect.S use only
-01F6/2 ALL swap_dev DO NOT USE - obsolete
+01F4/4 2.04+(2 syssize The size of the 32-bit code in 16-byte paras
01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
01FA/2 ALL vid_mode Video mode control
01FC/2 ALL root_dev Default root device number
@@ -129,8 +130,12 @@ Offset Proto Name Meaning
0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line
022C/4 2.03+ initrd_addr_max Highest legal initrd address
-For backwards compatibility, if the setup_sects field contains 0, the
-real value is 4.
+(1) For backwards compatibility, if the setup_sects field contains 0, the
+ real value is 4.
+
+(2) For boot protocol prior to 2.04, the upper two bytes of the syssize
+ field are unusable, which means the size of a bzImage kernel
+ cannot be determined.
If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
the boot protocol version is "old". Loading an old kernel, the
@@ -230,12 +235,16 @@ loader to communicate with the kernel. Some of its options are also
relevant to the boot loader itself, see "special command line options"
below.
-The kernel command line is a null-terminated string up to 255
-characters long, plus the final null.
+The kernel command line is a null-terminated string currently up to
+255 characters long, plus the final null. A string that is too long
+will be automatically truncated by the kernel, a boot loader may allow
+a longer command line to be passed to permit future kernels to extend
+this limit.
If the boot protocol version is 2.02 or later, the address of the
kernel command line is given by the header field cmd_line_ptr (see
-above.)
+above.) This address can be anywhere between the end of the setup
+heap and 0xA0000.
If the protocol version is *not* 2.02 or higher, the kernel
command line is entered using the following protocol:
@@ -255,7 +264,7 @@ command line is entered using the following protocol:
**** SAMPLE BOOT CONFIGURATION
As a sample configuration, assume the following layout of the real
-mode segment:
+mode segment (this is a typical, and recommended layout):
0x0000-0x7FFF Real mode kernel
0x8000-0x8FFF Stack and heap
@@ -312,9 +321,9 @@ Such a boot loader should enter the following fields in the header:
**** LOADING THE REST OF THE KERNEL
-The non-real-mode kernel starts at offset (setup_sects+1)*512 in the
-kernel file (again, if setup_sects == 0 the real value is 4.) It
-should be loaded at address 0x10000 for Image/zImage kernels and
+The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
+in the kernel file (again, if setup_sects == 0 the real value is 4.)
+It should be loaded at address 0x10000 for Image/zImage kernels and
0x100000 for bzImage kernels.
The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt
index c437b1aeff55..8b3fd82b2ce7 100644
--- a/Documentation/ibm-acpi.txt
+++ b/Documentation/ibm-acpi.txt
@@ -1,16 +1,16 @@
IBM ThinkPad ACPI Extras Driver
- Version 0.8
- 8 November 2004
+ Version 0.12
+ 17 August 2005
Borislav Deianov <borislav@users.sf.net>
http://ibm-acpi.sf.net/
-This is a Linux ACPI driver for the IBM ThinkPad laptops. It aims to
-support various features of these laptops which are accessible through
-the ACPI framework but not otherwise supported by the generic Linux
-ACPI drivers.
+This is a Linux ACPI driver for the IBM ThinkPad laptops. It supports
+various features of these laptops which are accessible through the
+ACPI framework but not otherwise supported by the generic Linux ACPI
+drivers.
Status
@@ -25,9 +25,14 @@ detailed description):
- ThinkLight on and off
- limited docking and undocking
- UltraBay eject
- - Experimental: CMOS control
- - Experimental: LED control
- - Experimental: ACPI sounds
+ - CMOS control
+ - LED control
+ - ACPI sounds
+ - temperature sensors
+ - Experimental: embedded controller register dump
+ - Experimental: LCD brightness control
+ - Experimental: volume control
+ - Experimental: fan speed, fan enable/disable
A compatibility table by model and feature is maintained on the web
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -91,12 +96,12 @@ driver is still in the alpha stage, the exact proc file format and
commands supported by the various features is guaranteed to change
frequently.
-Driver Version -- /proc/acpi/ibm/driver
---------------------------------------
+Driver version -- /proc/acpi/ibm/driver
+---------------------------------------
The driver name and version. No commands can be written to this file.
-Hot Keys -- /proc/acpi/ibm/hotkey
+Hot keys -- /proc/acpi/ibm/hotkey
---------------------------------
Without this driver, only the Fn-F4 key (sleep button) generates an
@@ -188,7 +193,7 @@ and, on the X40, video corruption. By disabling automatic switching,
the flickering or video corruption can be avoided.
The video_switch command cycles through the available video outputs
-(it sumulates the behavior of Fn-F7).
+(it simulates the behavior of Fn-F7).
Video expansion can be toggled through this feature. This controls
whether the display is expanded to fill the entire LCD screen when a
@@ -201,6 +206,12 @@ Fn-F7 from working. This also disables the video output switching
features of this driver, as it uses the same ACPI methods as
Fn-F7. Video switching on the console should still work.
+UPDATE: There's now a patch for the X.org Radeon driver which
+addresses this issue. Some people are reporting success with the patch
+while others are still having problems. For more information:
+
+https://bugs.freedesktop.org/show_bug.cgi?id=2000
+
ThinkLight control -- /proc/acpi/ibm/light
------------------------------------------
@@ -211,7 +222,7 @@ models which do not make the status available will show it as
echo on > /proc/acpi/ibm/light
echo off > /proc/acpi/ibm/light
-Docking / Undocking -- /proc/acpi/ibm/dock
+Docking / undocking -- /proc/acpi/ibm/dock
------------------------------------------
Docking and undocking (e.g. with the X4 UltraBase) requires some
@@ -228,11 +239,15 @@ NOTE: These events will only be generated if the laptop was docked
when originally booted. This is due to the current lack of support for
hot plugging of devices in the Linux ACPI framework. If the laptop was
booted while not in the dock, the following message is shown in the
-logs: "ibm_acpi: dock device not present". No dock-related events are
-generated but the dock and undock commands described below still
-work. They can be executed manually or triggered by Fn key
-combinations (see the example acpid configuration files included in
-the driver tarball package available on the web site).
+logs:
+
+ Mar 17 01:42:34 aero kernel: ibm_acpi: dock device not present
+
+In this case, no dock-related events are generated but the dock and
+undock commands described below still work. They can be executed
+manually or triggered by Fn key combinations (see the example acpid
+configuration files included in the driver tarball package available
+on the web site).
When the eject request button on the dock is pressed, the first event
above is generated. The handler for this event should issue the
@@ -267,7 +282,7 @@ the only docking stations currently supported are the X-series
UltraBase docks and "dumb" port replicators like the Mini Dock (the
latter don't need any ACPI support, actually).
-UltraBay Eject -- /proc/acpi/ibm/bay
+UltraBay eject -- /proc/acpi/ibm/bay
------------------------------------
Inserting or ejecting an UltraBay device requires some actions to be
@@ -284,8 +299,11 @@ when the laptop was originally booted (on the X series, the UltraBay
is in the dock, so it may not be present if the laptop was undocked).
This is due to the current lack of support for hot plugging of devices
in the Linux ACPI framework. If the laptop was booted without the
-UltraBay, the following message is shown in the logs: "ibm_acpi: bay
-device not present". No bay-related events are generated but the eject
+UltraBay, the following message is shown in the logs:
+
+ Mar 17 01:42:34 aero kernel: ibm_acpi: bay device not present
+
+In this case, no bay-related events are generated but the eject
command described below still works. It can be executed manually or
triggered by a hot key combination.
@@ -306,22 +324,33 @@ necessary to enable the UltraBay device (e.g. call idectl).
The contents of the /proc/acpi/ibm/bay file shows the current status
of the UltraBay, as provided by the ACPI framework.
-Experimental Features
----------------------
+EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use
+this feature, you need to supply the experimental=1 parameter when
+loading the module):
+
+These models do not have a button near the UltraBay device to request
+a hot eject but rather require the laptop to be put to sleep
+(suspend-to-ram) before the bay device is ejected or inserted).
+The sequence of steps to eject the device is as follows:
+
+ echo eject > /proc/acpi/ibm/bay
+ put the ThinkPad to sleep
+ remove the drive
+ resume from sleep
+ cat /proc/acpi/ibm/bay should show that the drive was removed
+
+On the A3x, both the UltraBay 2000 and UltraBay Plus devices are
+supported. Use "eject2" instead of "eject" for the second bay.
-The following features are marked experimental because using them
-involves guessing the correct values of some parameters. Guessing
-incorrectly may have undesirable effects like crashing your
-ThinkPad. USE THESE WITH CAUTION! To activate them, you'll need to
-supply the experimental=1 parameter when loading the module.
+Note: the UltraBay eject support on the 600e/x, A22p and A3x is
+EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
-Experimental: CMOS control - /proc/acpi/ibm/cmos
-------------------------------------------------
+CMOS control -- /proc/acpi/ibm/cmos
+-----------------------------------
This feature is used internally by the ACPI firmware to control the
-ThinkLight on most newer ThinkPad models. It appears that it can also
-control LCD brightness, sounds volume and more, but only on some
-models.
+ThinkLight on most newer ThinkPad models. It may also control LCD
+brightness, sounds volume and more, but only on some models.
The commands are non-negative integer numbers:
@@ -330,10 +359,9 @@ The commands are non-negative integer numbers:
echo 2 >/proc/acpi/ibm/cmos
...
-The range of numbers which are used internally by various models is 0
-to 21, but it's possible that numbers outside this range have
-interesting behavior. Here is the behavior on the X40 (tpb is the
-ThinkPad Buttons utility):
+The range of valid numbers is 0 to 21, but not all have an effect and
+the behavior varies from model to model. Here is the behavior on the
+X40 (tpb is the ThinkPad Buttons utility):
0 - no effect but tpb reports "Volume down"
1 - no effect but tpb reports "Volume up"
@@ -346,26 +374,18 @@ ThinkPad Buttons utility):
13 - ThinkLight off
14 - no effect but tpb reports ThinkLight status change
-If you try this feature, please send me a report similar to the
-above. On models which allow control of LCD brightness or sound
-volume, I'd like to provide this functionality in an user-friendly
-way, but first I need a way to identify the models which this is
-possible.
-
-Experimental: LED control - /proc/acpi/ibm/LED
-----------------------------------------------
+LED control -- /proc/acpi/ibm/led
+---------------------------------
Some of the LED indicators can be controlled through this feature. The
available commands are:
- echo <led number> on >/proc/acpi/ibm/led
- echo <led number> off >/proc/acpi/ibm/led
- echo <led number> blink >/proc/acpi/ibm/led
+ echo '<led number> on' >/proc/acpi/ibm/led
+ echo '<led number> off' >/proc/acpi/ibm/led
+ echo '<led number> blink' >/proc/acpi/ibm/led
-The <led number> parameter is a non-negative integer. The range of LED
-numbers used internally by various models is 0 to 7 but it's possible
-that numbers outside this range are also valid. Here is the mapping on
-the X40:
+The <led number> range is 0 to 7. The set of LEDs that can be
+controlled varies from model to model. Here is the mapping on the X40:
0 - power
1 - battery (orange)
@@ -376,49 +396,224 @@ the X40:
All of the above can be turned on and off and can be made to blink.
-If you try this feature, please send me a report similar to the
-above. I'd like to provide this functionality in an user-friendly way,
-but first I need to identify the which numbers correspond to which
-LEDs on various models.
-
-Experimental: ACPI sounds - /proc/acpi/ibm/beep
------------------------------------------------
+ACPI sounds -- /proc/acpi/ibm/beep
+----------------------------------
The BEEP method is used internally by the ACPI firmware to provide
-audible alerts in various situtation. This feature allows the same
+audible alerts in various situations. This feature allows the same
sounds to be triggered manually.
The commands are non-negative integer numbers:
- echo 0 >/proc/acpi/ibm/beep
- echo 1 >/proc/acpi/ibm/beep
- echo 2 >/proc/acpi/ibm/beep
- ...
+ echo <number> >/proc/acpi/ibm/beep
-The range of numbers which are used internally by various models is 0
-to 17, but it's possible that numbers outside this range are also
-valid. Here is the behavior on the X40:
+The valid <number> range is 0 to 17. Not all numbers trigger sounds
+and the sounds vary from model to model. Here is the behavior on the
+X40:
- 2 - two beeps, pause, third beep
+ 0 - stop a sound in progress (but use 17 to stop 16)
+ 2 - two beeps, pause, third beep ("low battery")
3 - single beep
- 4 - "unable"
+ 4 - high, followed by low-pitched beep ("unable")
5 - single beep
- 6 - "AC/DC"
+ 6 - very high, followed by high-pitched beep ("AC/DC")
7 - high-pitched beep
9 - three short beeps
10 - very long beep
12 - low-pitched beep
+ 15 - three high-pitched beeps repeating constantly, stop with 0
+ 16 - one medium-pitched beep repeating constantly, stop with 17
+ 17 - stop 16
+
+Temperature sensors -- /proc/acpi/ibm/thermal
+---------------------------------------------
+
+Most ThinkPads include six or more separate temperature sensors but
+only expose the CPU temperature through the standard ACPI methods.
+This feature shows readings from up to eight different sensors. Some
+readings may not be valid, e.g. may show large negative values. For
+example, on the X40, a typical output may be:
+
+temperatures: 42 42 45 41 36 -128 33 -128
+
+Thomas Gruber took his R51 apart and traced all six active sensors in
+his laptop (the location of sensors may vary on other models):
+
+1: CPU
+2: Mini PCI Module
+3: HDD
+4: GPU
+5: Battery
+6: N/A
+7: Battery
+8: N/A
+
+No commands can be written to this file.
+
+EXPERIMENTAL: Embedded controller reigster dump -- /proc/acpi/ibm/ecdump
+------------------------------------------------------------------------
+
+This feature is marked EXPERIMENTAL because the implementation
+directly accesses hardware registers and may not work as expected. USE
+WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.
+
+This feature dumps the values of 256 embedded controller
+registers. Values which have changed since the last time the registers
+were dumped are marked with a star:
+
+[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
+EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
+EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
+EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
+EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
+EC 0x30: 01 07 1a 00 30 04 00 00 *85 00 00 10 00 50 00 00
+EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
+EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 *bc *02 *bc
+EC 0x60: *02 *bc *02 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0x70: 00 00 00 00 00 12 30 40 *24 *26 *2c *27 *20 80 *1f 80
+EC 0x80: 00 00 00 06 *37 *0e 03 00 00 00 0e 07 00 00 00 00
+EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xa0: *ff 09 ff 09 ff ff *64 00 *00 *00 *a2 41 *ff *ff *e0 00
+EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
+EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a
+
+This feature can be used to determine the register holding the fan
+speed on some models. To do that, do the following:
+
+ - make sure the battery is fully charged
+ - make sure the fan is running
+ - run 'cat /proc/acpi/ibm/ecdump' several times, once per second or so
+
+The first step makes sure various charging-related values don't
+vary. The second ensures that the fan-related values do vary, since
+the fan speed fluctuates a bit. The third will (hopefully) mark the
+fan register with a star:
+
+[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
+EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
+EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
+EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
+EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
+EC 0x30: 01 07 1a 00 30 04 00 00 85 00 00 10 00 50 00 00
+EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
+EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 bc 02 bc
+EC 0x60: 02 bc 02 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0x70: 00 00 00 00 00 12 30 40 24 27 2c 27 21 80 1f 80
+EC 0x80: 00 00 00 06 *be 0d 03 00 00 00 0e 07 00 00 00 00
+EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xa0: ff 09 ff 09 ff ff 64 00 00 00 a2 41 ff ff e0 00
+EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
+EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a
+
+Another set of values that varies often is the temperature
+readings. Since temperatures don't change vary fast, you can take
+several quick dumps to eliminate them.
+
+You can use a similar method to figure out the meaning of other
+embedded controller registers - e.g. make sure nothing else changes
+except the charging or discharging battery to determine which
+registers contain the current battery capacity, etc. If you experiment
+with this, do send me your results (including some complete dumps with
+a description of the conditions when they were taken.)
+
+EXPERIMENTAL: LCD brightness control -- /proc/acpi/ibm/brightness
+-----------------------------------------------------------------
+
+This feature is marked EXPERIMENTAL because the implementation
+directly accesses hardware registers and may not work as expected. USE
+WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.
+
+This feature allows software control of the LCD brightness on ThinkPad
+models which don't have a hardware brightness slider. The available
+commands are:
+
+ echo up >/proc/acpi/ibm/brightness
+ echo down >/proc/acpi/ibm/brightness
+ echo 'level <level>' >/proc/acpi/ibm/brightness
+
+The <level> number range is 0 to 7, although not all of them may be
+distinct. The current brightness level is shown in the file.
+
+EXPERIMENTAL: Volume control -- /proc/acpi/ibm/volume
+-----------------------------------------------------
+
+This feature is marked EXPERIMENTAL because the implementation
+directly accesses hardware registers and may not work as expected. USE
+WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.
+
+This feature allows volume control on ThinkPad models which don't have
+a hardware volume knob. The available commands are:
+
+ echo up >/proc/acpi/ibm/volume
+ echo down >/proc/acpi/ibm/volume
+ echo mute >/proc/acpi/ibm/volume
+ echo 'level <level>' >/proc/acpi/ibm/volume
+
+The <level> number range is 0 to 15 although not all of them may be
+distinct. The unmute the volume after the mute command, use either the
+up or down command (the level command will not unmute the volume).
+The current volume level and mute state is shown in the file.
+
+EXPERIMENTAL: fan speed, fan enable/disable -- /proc/acpi/ibm/fan
+-----------------------------------------------------------------
+
+This feature is marked EXPERIMENTAL because the implementation
+directly accesses hardware registers and may not work as expected. USE
+WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.
+
+This feature attempts to show the current fan speed. The speed is read
+directly from the hardware registers of the embedded controller. This
+is known to work on later R, T and X series ThinkPads but may show a
+bogus value on other models.
+
+The fan may be enabled or disabled with the following commands:
+
+ echo enable >/proc/acpi/ibm/fan
+ echo disable >/proc/acpi/ibm/fan
+
+WARNING WARNING WARNING: do not leave the fan disabled unless you are
+monitoring the temperature sensor readings and you are ready to enable
+it if necessary to avoid overheating.
+
+The fan only runs if it's enabled *and* the various temperature
+sensors which control it read high enough. On the X40, this seems to
+depend on the CPU and HDD temperatures. Specifically, the fan is
+turned on when either the CPU temperature climbs to 56 degrees or the
+HDD temperature climbs to 46 degrees. The fan is turned off when the
+CPU temperature drops to 49 degrees and the HDD temperature drops to
+41 degrees. These thresholds cannot currently be controlled.
+
+On the X31 and X40 (and ONLY on those models), the fan speed can be
+controlled to a certain degree. Once the fan is running, it can be
+forced to run faster or slower with the following command:
+
+ echo 'speed <speed>' > /proc/acpi/ibm/thermal
+
+The sustainable range of fan speeds on the X40 appears to be from
+about 3700 to about 7350. Values outside this range either do not have
+any effect or the fan speed eventually settles somewhere in that
+range. The fan cannot be stopped or started with this command.
+
+On the 570, temperature readings are not available through this
+feature and the fan control works a little differently. The fan speed
+is reported in levels from 0 (off) to 7 (max) and can be controlled
+with the following command:
-(I've only been able to identify a couple of them).
-
-If you try this feature, please send me a report similar to the
-above. I'd like to provide this functionality in an user-friendly way,
-but first I need to identify the which numbers correspond to which
-sounds on various models.
+ echo 'level <level>' > /proc/acpi/ibm/thermal
-Multiple Command, Module Parameters
------------------------------------
+Multiple Commands, Module Parameters
+------------------------------------
Multiple commands can be written to the proc files in one shot by
separating them with commas, for example:
@@ -451,24 +646,19 @@ scripts (included with ibm-acpi for completeness):
/usr/local/sbin/laptop_mode -- from the Linux kernel source
distribution, see Documentation/laptop-mode.txt
/sbin/service -- comes with Redhat/Fedora distributions
+ /usr/sbin/hibernate -- from the Software Suspend 2 distribution,
+ see http://softwaresuspend.berlios.de/
-Toan T Nguyen <ntt@control.uchicago.edu> has written a SuSE powersave
-script for the X20, included in config/usr/sbin/ibm_hotkeys_X20
+Toan T Nguyen <ntt@physics.ucla.edu> notes that Suse uses the
+powersave program to suspend ('powersave --suspend-to-ram') or
+hibernate ('powersave --suspend-to-disk'). This means that the
+hibernate script is not needed on that distribution.
Henrik Brix Andersen <brix@gentoo.org> has written a Gentoo ACPI event
handler script for the X31. You can get the latest version from
http://dev.gentoo.org/~brix/files/x31.sh
David Schweikert <dws@ee.eth.ch> has written an alternative blank.sh
-script which works on Debian systems, included in
-configs/etc/acpi/actions/blank-debian.sh
-
-
-TODO
-----
-
-I'd like to implement the following features but haven't yet found the
-time and/or I don't yet know how to implement them:
-
-- UltraBay floppy drive support
-
+script which works on Debian systems. This scripts has now been
+extended to also work on Fedora systems and included as the default
+blank.sh in the distribution.
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
new file mode 100644
index 000000000000..b48d11d0326d
--- /dev/null
+++ b/Documentation/input/appletouch.txt
@@ -0,0 +1,84 @@
+Apple Touchpad Driver (appletouch)
+----------------------------------
+ Copyright (C) 2005 Stelian Pop <stelian@popies.net>
+
+appletouch is a Linux kernel driver for the USB touchpad found on post
+February 2005 Apple Alu Powerbooks.
+
+This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
+been improved in some areas:
+ * appletouch is a full kernel driver, no userspace program is necessary
+ * appletouch can be interfaced with the synaptics X11 driver, in order
+ to have touchpad acceleration, scrolling, etc.
+
+Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
+Frank Arnold for further improvements, and Alex Harper for some additional
+information about the inner workings of the touchpad sensors.
+
+Usage:
+------
+
+In order to use the touchpad in the basic mode, compile the driver and load
+the module. A new input device will be detected and you will be able to read
+the mouse data from /dev/input/mice (using gpm, or X11).
+
+In X11, you can configure the touchpad to use the synaptics X11 driver, which
+will give additional functionalities, like acceleration, scrolling, 2 finger
+tap for middle button mouse emulation, 3 finger tap for right button mouse
+emulation, etc. In order to do this, make sure you're using a recent version of
+the synaptics driver (tested with 0.14.2, available from [2]), and configure a
+new input device in your X11 configuration file (take a look below for an
+example). For additional configuration, see the synaptics driver documentation.
+
+ Section "InputDevice"
+ Identifier "Synaptics Touchpad"
+ Driver "synaptics"
+ Option "SendCoreEvents" "true"
+ Option "Device" "/dev/input/mice"
+ Option "Protocol" "auto-dev"
+ Option "LeftEdge" "0"
+ Option "RightEdge" "850"
+ Option "TopEdge" "0"
+ Option "BottomEdge" "645"
+ Option "MinSpeed" "0.4"
+ Option "MaxSpeed" "1"
+ Option "AccelFactor" "0.02"
+ Option "FingerLow" "0"
+ Option "FingerHigh" "30"
+ Option "MaxTapMove" "20"
+ Option "MaxTapTime" "100"
+ Option "HorizScrollDelta" "0"
+ Option "VertScrollDelta" "30"
+ Option "SHMConfig" "on"
+ EndSection
+
+ Section "ServerLayout"
+ ...
+ InputDevice "Mouse"
+ InputDevice "Synaptics Touchpad"
+ ...
+ EndSection
+
+Fuzz problems:
+--------------
+
+The touchpad sensors are very sensitive to heat, and will generate a lot of
+noise when the temperature changes. This is especially true when you power-on
+the laptop for the first time.
+
+The appletouch driver tries to handle this noise and auto adapt itself, but it
+is not perfect. If finger movements are not recognized anymore, try reloading
+the driver.
+
+You can activate debugging using the 'debug' module parameter. A value of 0
+deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
+full tracing (each sample is being traced):
+ modprobe appletouch debug=1
+ or
+ echo "1" > /sys/module/appletouch/parameters/debug
+
+Links:
+------
+
+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
+[2]: http://web.telia.com/~u89404340/touchpad/index.html
diff --git a/Documentation/input/yealink.txt b/Documentation/input/yealink.txt
new file mode 100644
index 000000000000..85f095a7ad04
--- /dev/null
+++ b/Documentation/input/yealink.txt
@@ -0,0 +1,203 @@
+Driver documentation for yealink usb-p1k phones
+
+0. Status
+~~~~~~~~~
+
+The p1k is a relatively cheap usb 1.1 phone with:
+ - keyboard full support, yealink.ko / input event API
+ - LCD full support, yealink.ko / sysfs API
+ - LED full support, yealink.ko / sysfs API
+ - dialtone full support, yealink.ko / sysfs API
+ - ringtone full support, yealink.ko / sysfs API
+ - audio playback full support, snd_usb_audio.ko / alsa API
+ - audio record full support, snd_usb_audio.ko / alsa API
+
+For vendor documentation see http://www.yealink.com
+
+
+1. Compilation (stand alone version)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Currently only kernel 2.6.x.y versions are supported.
+In order to build the yealink.ko module do:
+
+ make
+
+If you encounter problems please check if in the MAKE_OPTS variable in
+the Makefile is pointing to the location where your kernel sources
+are located, default /usr/src/linux.
+
+
+
+2. keyboard features
+~~~~~~~~~~~~~~~~~~~~
+The current mapping in the kernel is provided by the map_p1k_to_key
+function:
+
+ Physical USB-P1K button layout input events
+
+
+ up up
+ IN OUT left, right
+ down down
+
+ pickup C hangup enter, backspace, escape
+ 1 2 3 1, 2, 3
+ 4 5 6 4, 5, 6,
+ 7 8 9 7, 8, 9,
+ * 0 # *, 0, #,
+
+ The "up" and "down" keys, are symbolised by arrows on the button.
+ The "pickup" and "hangup" keys are symbolised by a green and red phone
+ on the button.
+
+
+3. LCD features
+~~~~~~~~~~~~~~~
+The LCD is divided and organised as a 3 line display:
+
+ |[] [][] [][] [][] in |[][]
+ |[] M [][] D [][] : [][] out |[][]
+ store
+
+ NEW REP SU MO TU WE TH FR SA
+
+ [] [] [] [] [] [] [] [] [] [] [] []
+ [] [] [] [] [] [] [] [] [] [] [] []
+
+
+Line 1 Format (see below) : 18.e8.M8.88...188
+ Icon names : M D : IN OUT STORE
+Line 2 Format : .........
+ Icon name : NEW REP SU MO TU WE TH FR SA
+Line 3 Format : 888888888888
+
+
+Format description:
+ From a user space perspective the world is seperated in "digits" and "icons".
+ A digit can have a character set, an icon can only be ON or OFF.
+
+ Format specifier
+ '8' : Generic 7 segment digit with individual addressable segments
+
+ Reduced capabillity 7 segm digit, when segments are hard wired together.
+ '1' : 2 segments digit only able to produce a 1.
+ 'e' : Most significant day of the month digit,
+ able to produce at least 1 2 3.
+ 'M' : Most significant minute digit,
+ able to produce at least 0 1 2 3 4 5.
+
+ Icons or pictograms:
+ '.' : For example like AM, PM, SU, a 'dot' .. or other single segment
+ elements.
+
+
+4. Driver usage
+~~~~~~~~~~~~~~~
+For userland the following interfaces are available using the sysfs interface:
+ /sys/.../
+ line1 Read/Write, lcd line1
+ line2 Read/Write, lcd line2
+ line3 Read/Write, lcd line3
+
+ get_icons Read, returns a set of available icons.
+ hide_icon Write, hide the element by writing the icon name.
+ show_icon Write, display the element by writing the icon name.
+
+ map_seg7 Read/Write, the 7 segments char set, common for all
+ yealink phones. (see map_to_7segment.h)
+
+ ringtone Write, upload binary representation of a ringtone,
+ see yealink.c. status EXPERIMENTAL due to potential
+ races between async. and sync usb calls.
+
+
+4.1 lineX
+~~~~~~~~~
+Reading /sys/../lineX will return the format string with its current value:
+
+ Example:
+ cat ./line3
+ 888888888888
+ Linux Rocks!
+
+Writing to /sys/../lineX will set the coresponding LCD line.
+ - Excess characters are ignored.
+ - If less characters are written than allowed, the remaining digits are
+ unchanged.
+ - The tab '\t'and '\n' char does not overwrite the original content.
+ - Writing a space to an icon will always hide its content.
+
+ Example:
+ date +"%m.%e.%k:%M" | sed 's/^0/ /' > ./line1
+
+ Will update the LCD with the current date & time.
+
+
+4.2 get_icons
+~~~~~~~~~~~~~
+Reading will return all available icon names and its current settings:
+
+ cat ./get_icons
+ on M
+ on D
+ on :
+ IN
+ OUT
+ STORE
+ NEW
+ REP
+ SU
+ MO
+ TU
+ WE
+ TH
+ FR
+ SA
+ LED
+ DIALTONE
+ RINGTONE
+
+
+4.3 show/hide icons
+~~~~~~~~~~~~~~~~~~~
+Writing to these files will update the state of the icon.
+Only one icon at a time can be updated.
+
+If an icon is also on a ./lineX the corresponding value is
+updated with the first letter of the icon.
+
+ Example - light up the store icon:
+ echo -n "STORE" > ./show_icon
+
+ cat ./line1
+ 18.e8.M8.88...188
+ S
+
+ Example - sound the ringtone for 10 seconds:
+ echo -n RINGTONE > /sys/..../show_icon
+ sleep 10
+ echo -n RINGTONE > /sys/..../hide_icon
+
+
+5. Sound features
+~~~~~~~~~~~~~~~~~
+Sound is supported by the ALSA driver: snd_usb_audio
+
+One 16-bit channel with sample and playback rates of 8000 Hz is the practical
+limit of the device.
+
+ Example - recording test:
+ arecord -v -d 10 -r 8000 -f S16_LE -t wav foobar.wav
+
+ Example - playback test:
+ aplay foobar.wav
+
+
+6. Credits & Acknowledgments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Olivier Vandorpe, for starting the usbb2k-api project doing much of
+ the reverse engineering.
+ - Martin Diehl, for pointing out how to handle USB memory allocation.
+ - Dmitry Torokhov, for the numerous code reviews and suggestions.
+
diff --git a/Documentation/ioctl/cdrom.txt b/Documentation/ioctl/cdrom.txt
index 4ccdcc6fe364..8ec32cc49eb1 100644
--- a/Documentation/ioctl/cdrom.txt
+++ b/Documentation/ioctl/cdrom.txt
@@ -878,7 +878,7 @@ DVD_READ_STRUCT Read structure
error returns:
EINVAL physical.layer_num exceeds number of layers
- EIO Recieved invalid response from drive
+ EIO Received invalid response from drive
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 2616a58a5a4b..d802ce88bedc 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -31,7 +31,7 @@ This document describes the Linux kernel Makefiles.
=== 6 Architecture Makefiles
--- 6.1 Set variables to tweak the build to the architecture
- --- 6.2 Add prerequisites to prepare:
+ --- 6.2 Add prerequisites to archprepare:
--- 6.3 List directories to visit when descending
--- 6.4 Architecture specific boot images
--- 6.5 Building non-kbuild targets
@@ -734,18 +734,18 @@ When kbuild executes the following steps are followed (roughly):
for loadable kernel modules.
---- 6.2 Add prerequisites to prepare:
+--- 6.2 Add prerequisites to archprepare:
- The prepare: rule is used to list prerequisites that needs to be
+ The archprepare: rule is used to list prerequisites that needs to be
built before starting to descend down in the subdirectories.
This is usual header files containing assembler constants.
Example:
- #arch/s390/Makefile
- prepare: include/asm-$(ARCH)/offsets.h
+ #arch/arm/Makefile
+ archprepare: maketools
- In this example the file include/asm-$(ARCH)/offsets.h will
- be built before descending down in the subdirectories.
+ In this example the file target maketools will be processed
+ before descending down in the subdirectories.
See also chapter XXX-TODO that describe how kbuild supports
generating offset header files.
@@ -872,7 +872,13 @@ When kbuild executes the following steps are followed (roughly):
Assignments to $(targets) are without $(obj)/ prefix.
if_changed may be used in conjunction with custom commands as
defined in 6.7 "Custom kbuild commands".
+
Note: It is a typical mistake to forget the FORCE prerequisite.
+ Another common pitfall is that whitespace is sometimes
+ significant; for instance, the below will fail (note the extra space
+ after the comma):
+ target: source(s) FORCE
+ #WRONG!# $(call if_changed, ld/objcopy/gzip)
ld
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 7ff213f4becd..5f08f9ce6046 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -39,8 +39,7 @@ SETUP
and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
and after that build the source.
-2) Download and build the appropriate (latest) kexec/kdump (-mm) kernel
- patchset and apply it to the vanilla kernel tree.
+2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernel.
Two kernels need to be built in order to get this feature working.
@@ -67,11 +66,11 @@ SETUP
c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
CONFIG_PROC_VMCORE=y
d) Disable SMP support and build a UP kernel (Until it is fixed).
- CONFIG_SMP=n
+ CONFIG_SMP=n
e) Enable "Local APIC support on uniprocessors".
- CONFIG_X86_UP_APIC=y
+ CONFIG_X86_UP_APIC=y
f) Enable "IO-APIC support on uniprocessors"
- CONFIG_X86_UP_IOAPIC=y
+ CONFIG_X86_UP_IOAPIC=y
Note: i) Options a) and b) depend upon "Configure standard kernel features
(for small systems)" (under General setup).
@@ -84,17 +83,23 @@ SETUP
4) Load the second kernel to be booted using:
- kexec -p <second-kernel> --crash-dump --args-linux --append="root=<root-dev>
- init 1 irqpoll"
+ kexec -p <second-kernel> --args-linux --elf32-core-headers
+ --append="root=<root-dev> init 1 irqpoll"
Note: i) <second-kernel> has to be a vmlinux image. bzImage will not work,
as of now.
- ii) By default ELF headers are stored in ELF32 format (for i386). This
- is sufficient to represent the physical memory up to 4GB. To store
- headers in ELF64 format, specifiy "--elf64-core-headers" on the
- kexec command line additionally.
+ ii) By default ELF headers are stored in ELF64 format. Option
+ --elf32-core-headers forces generation of ELF32 headers. gdb can
+ not open ELF64 headers on 32 bit systems. So creating ELF32
+ headers can come handy for users who have got non-PAE systems and
+ hence have memory less than 4GB.
iii) Specify "irqpoll" as command line parameter. This reduces driver
initialization failures in second kernel due to shared interrupts.
+ iv) <root-dev> needs to be specified in a format corresponding to
+ the root device name in the output of mount command.
+ v) If you have built the drivers required to mount root file
+ system as modules in <second-kernel>, then, specify
+ --initrd=<initrd-for-second-kernel>.
5) System reboots into the second kernel when a panic occurs. A module can be
written to force the panic or "ALT-SysRq-c" can be used initiate a crash
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 3d5cd7a09b2f..7086f0a90d14 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -164,6 +164,15 @@ running once the system is up.
over-ride platform specific driver.
See also Documentation/acpi-hotkey.txt.
+ enable_timer_pin_1 [i386,x86-64]
+ Enable PIN 1 of APIC timer
+ Can be useful to work around chipset bugs (in particular on some ATI chipsets)
+ The kernel tries to set a reasonable default.
+
+ disable_timer_pin_1 [i386,x86-64]
+ Disable PIN 1 of APIC timer
+ Can be useful to work around chipset bugs.
+
ad1816= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>
See also Documentation/sound/oss/AD1816.
@@ -549,6 +558,7 @@ running once the system is up.
keyboard and can not control its state
(Don't attempt to blink the leds)
i8042.noaux [HW] Don't check for auxiliary (== mouse) port
+ i8042.nokbd [HW] Don't check/create keyboard port
i8042.nomux [HW] Don't check presence of an active multiplexing
controller
i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
@@ -1174,6 +1184,11 @@ running once the system is up.
New name for the ramdisk parameter.
See Documentation/ramdisk.txt.
+ rdinit= [KNL]
+ Format: <full_path>
+ Run specified binary instead of /init from the ramdisk,
+ used for early userspace startup. See initrd.
+
reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
Format: <reboot_mode>[,<reboot_mode2>[,...]]
See arch/*/kernel/reboot.c.
diff --git a/Documentation/mono.txt b/Documentation/mono.txt
index 6739ab9615ef..807a0c7b4737 100644
--- a/Documentation/mono.txt
+++ b/Documentation/mono.txt
@@ -30,7 +30,7 @@ other program after you have done the following:
Read the file 'binfmt_misc.txt' in this directory to know
more about the configuration process.
-3) Add the following enries to /etc/rc.local or similar script
+3) Add the following entries to /etc/rc.local or similar script
to be run at system startup:
# Insert BINFMT_MISC module into the kernel
diff --git a/Documentation/networking/README.ipw2100 b/Documentation/networking/README.ipw2100
new file mode 100644
index 000000000000..2046948b020d
--- /dev/null
+++ b/Documentation/networking/README.ipw2100
@@ -0,0 +1,246 @@
+
+===========================
+Intel(R) PRO/Wireless 2100 Network Connection Driver for Linux
+README.ipw2100
+
+March 14, 2005
+
+===========================
+Index
+---------------------------
+0. Introduction
+1. Release 1.1.0 Current Features
+2. Command Line Parameters
+3. Sysfs Helper Files
+4. Radio Kill Switch
+5. Dynamic Firmware
+6. Power Management
+7. Support
+8. License
+
+
+===========================
+0. Introduction
+------------ ----- ----- ---- --- -- -
+
+This document provides a brief overview of the features supported by the
+IPW2100 driver project. The main project website, where the latest
+development version of the driver can be found, is:
+
+ http://ipw2100.sourceforge.net
+
+There you can find the not only the latest releases, but also information about
+potential fixes and patches, as well as links to the development mailing list
+for the driver project.
+
+
+===========================
+1. Release 1.1.0 Current Supported Features
+---------------------------
+- Managed (BSS) and Ad-Hoc (IBSS)
+- WEP (shared key and open)
+- Wireless Tools support
+- 802.1x (tested with XSupplicant 1.0.1)
+
+Enabled (but not supported) features:
+- Monitor/RFMon mode
+- WPA/WPA2
+
+The distinction between officially supported and enabled is a reflection
+on the amount of validation and interoperability testing that has been
+performed on a given feature.
+
+
+===========================
+2. Command Line Parameters
+---------------------------
+
+If the driver is built as a module, the following optional parameters are used
+by entering them on the command line with the modprobe command using this
+syntax:
+
+ modprobe ipw2100 [<option>=<VAL1><,VAL2>...]
+
+For example, to disable the radio on driver loading, enter:
+
+ modprobe ipw2100 disable=1
+
+The ipw2100 driver supports the following module parameters:
+
+Name Value Example:
+debug 0x0-0xffffffff debug=1024
+mode 0,1,2 mode=1 /* AdHoc */
+channel int channel=3 /* Only valid in AdHoc or Monitor */
+associate boolean associate=0 /* Do NOT auto associate */
+disable boolean disable=1 /* Do not power the HW */
+
+
+===========================
+3. Sysfs Helper Files
+---------------------------
+
+There are several ways to control the behavior of the driver. Many of the
+general capabilities are exposed through the Wireless Tools (iwconfig). There
+are a few capabilities that are exposed through entries in the Linux Sysfs.
+
+
+----- Driver Level ------
+For the driver level files, look in /sys/bus/pci/drivers/ipw2100/
+
+ debug_level
+
+ This controls the same global as the 'debug' module parameter. For
+ information on the various debugging levels available, run the 'dvals'
+ script found in the driver source directory.
+
+ NOTE: 'debug_level' is only enabled if CONFIG_IPW2100_DEBUG is turn
+ on.
+
+----- Device Level ------
+For the device level files look in
+
+ /sys/bus/pci/drivers/ipw2100/{PCI-ID}/
+
+For example:
+ /sys/bus/pci/drivers/ipw2100/0000:02:01.0
+
+For the device level files, see /sys/bus/pci/drivers/ipw2100:
+
+ rf_kill
+ read -
+ 0 = RF kill not enabled (radio on)
+ 1 = SW based RF kill active (radio off)
+ 2 = HW based RF kill active (radio off)
+ 3 = Both HW and SW RF kill active (radio off)
+ write -
+ 0 = If SW based RF kill active, turn the radio back on
+ 1 = If radio is on, activate SW based RF kill
+
+ NOTE: If you enable the SW based RF kill and then toggle the HW
+ based RF kill from ON -> OFF -> ON, the radio will NOT come back on
+
+
+===========================
+4. Radio Kill Switch
+---------------------------
+Most laptops provide the ability for the user to physically disable the radio.
+Some vendors have implemented this as a physical switch that requires no
+software to turn the radio off and on. On other laptops, however, the switch
+is controlled through a button being pressed and a software driver then making
+calls to turn the radio off and on. This is referred to as a "software based
+RF kill switch"
+
+See the Sysfs helper file 'rf_kill' for determining the state of the RF switch
+on your system.
+
+
+===========================
+5. Dynamic Firmware
+---------------------------
+As the firmware is licensed under a restricted use license, it can not be
+included within the kernel sources. To enable the IPW2100 you will need a
+firmware image to load into the wireless NIC's processors.
+
+You can obtain these images from <http://ipw2100.sf.net/firmware.php>.
+
+See INSTALL for instructions on installing the firmware.
+
+
+===========================
+6. Power Management
+---------------------------
+The IPW2100 supports the configuration of the Power Save Protocol
+through a private wireless extension interface. The IPW2100 supports
+the following different modes:
+
+ off No power management. Radio is always on.
+ on Automatic power management
+ 1-5 Different levels of power management. The higher the
+ number the greater the power savings, but with an impact to
+ packet latencies.
+
+Power management works by powering down the radio after a certain
+interval of time has passed where no packets are passed through the
+radio. Once powered down, the radio remains in that state for a given
+period of time. For higher power savings, the interval between last
+packet processed to sleep is shorter and the sleep period is longer.
+
+When the radio is asleep, the access point sending data to the station
+must buffer packets at the AP until the station wakes up and requests
+any buffered packets. If you have an AP that does not correctly support
+the PSP protocol you may experience packet loss or very poor performance
+while power management is enabled. If this is the case, you will need
+to try and find a firmware update for your AP, or disable power
+management (via `iwconfig eth1 power off`)
+
+To configure the power level on the IPW2100 you use a combination of
+iwconfig and iwpriv. iwconfig is used to turn power management on, off,
+and set it to auto.
+
+ iwconfig eth1 power off Disables radio power down
+ iwconfig eth1 power on Enables radio power management to
+ last set level (defaults to AUTO)
+ iwpriv eth1 set_power 0 Sets power level to AUTO and enables
+ power management if not previously
+ enabled.
+ iwpriv eth1 set_power 1-5 Set the power level as specified,
+ enabling power management if not
+ previously enabled.
+
+You can view the current power level setting via:
+
+ iwpriv eth1 get_power
+
+It will return the current period or timeout that is configured as a string
+in the form of xxxx/yyyy (z) where xxxx is the timeout interval (amount of
+time after packet processing), yyyy is the period to sleep (amount of time to
+wait before powering the radio and querying the access point for buffered
+packets), and z is the 'power level'. If power management is turned off the
+xxxx/yyyy will be replaced with 'off' -- the level reported will be the active
+level if `iwconfig eth1 power on` is invoked.
+
+
+===========================
+7. Support
+---------------------------
+
+For general development information and support,
+go to:
+
+ http://ipw2100.sf.net/
+
+The ipw2100 1.1.0 driver and firmware can be downloaded from:
+
+ http://support.intel.com
+
+For installation support on the ipw2100 1.1.0 driver on Linux kernels
+2.6.8 or greater, email support is available from:
+
+ http://supportmail.intel.com
+
+===========================
+8. License
+---------------------------
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License (version 2) as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ License Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200
new file mode 100644
index 000000000000..6916080c5f03
--- /dev/null
+++ b/Documentation/networking/README.ipw2200
@@ -0,0 +1,300 @@
+
+Intel(R) PRO/Wireless 2915ABG Driver for Linux in support of:
+
+Intel(R) PRO/Wireless 2200BG Network Connection
+Intel(R) PRO/Wireless 2915ABG Network Connection
+
+Note: The Intel(R) PRO/Wireless 2915ABG Driver for Linux and Intel(R)
+PRO/Wireless 2200BG Driver for Linux is a unified driver that works on
+both hardware adapters listed above. In this document the Intel(R)
+PRO/Wireless 2915ABG Driver for Linux will be used to reference the
+unified driver.
+
+Copyright (C) 2004-2005, Intel Corporation
+
+README.ipw2200
+
+Version: 1.0.0
+Date : January 31, 2005
+
+
+Index
+-----------------------------------------------
+1. Introduction
+1.1. Overview of features
+1.2. Module parameters
+1.3. Wireless Extension Private Methods
+1.4. Sysfs Helper Files
+2. About the Version Numbers
+3. Support
+4. License
+
+
+1. Introduction
+-----------------------------------------------
+The following sections attempt to provide a brief introduction to using
+the Intel(R) PRO/Wireless 2915ABG Driver for Linux.
+
+This document is not meant to be a comprehensive manual on
+understanding or using wireless technologies, but should be sufficient
+to get you moving without wires on Linux.
+
+For information on building and installing the driver, see the INSTALL
+file.
+
+
+1.1. Overview of Features
+-----------------------------------------------
+The current release (1.0.0) supports the following features:
+
++ BSS mode (Infrastructure, Managed)
++ IBSS mode (Ad-Hoc)
++ WEP (OPEN and SHARED KEY mode)
++ 802.1x EAP via wpa_supplicant and xsupplicant
++ Wireless Extension support
++ Full B and G rate support (2200 and 2915)
++ Full A rate support (2915 only)
++ Transmit power control
++ S state support (ACPI suspend/resume)
++ long/short preamble support
+
+
+
+1.2. Command Line Parameters
+-----------------------------------------------
+
+Like many modules used in the Linux kernel, the Intel(R) PRO/Wireless
+2915ABG Driver for Linux allows certain configuration options to be
+provided as module parameters. The most common way to specify a module
+parameter is via the command line.
+
+The general form is:
+
+% modprobe ipw2200 parameter=value
+
+Where the supported parameter are:
+
+ associate
+ Set to 0 to disable the auto scan-and-associate functionality of the
+ driver. If disabled, the driver will not attempt to scan
+ for and associate to a network until it has been configured with
+ one or more properties for the target network, for example configuring
+ the network SSID. Default is 1 (auto-associate)
+
+ Example: % modprobe ipw2200 associate=0
+
+ auto_create
+ Set to 0 to disable the auto creation of an Ad-Hoc network
+ matching the channel and network name parameters provided.
+ Default is 1.
+
+ channel
+ channel number for association. The normal method for setting
+ the channel would be to use the standard wireless tools
+ (i.e. `iwconfig eth1 channel 10`), but it is useful sometimes
+ to set this while debugging. Channel 0 means 'ANY'
+
+ debug
+ If using a debug build, this is used to control the amount of debug
+ info is logged. See the 'dval' and 'load' script for more info on
+ how to use this (the dval and load scripts are provided as part
+ of the ipw2200 development snapshot releases available from the
+ SourceForge project at http://ipw2200.sf.net)
+
+ mode
+ Can be used to set the default mode of the adapter.
+ 0 = Managed, 1 = Ad-Hoc
+
+
+1.3. Wireless Extension Private Methods
+-----------------------------------------------
+
+As an interface designed to handle generic hardware, there are certain
+capabilities not exposed through the normal Wireless Tool interface. As
+such, a provision is provided for a driver to declare custom, or
+private, methods. The Intel(R) PRO/Wireless 2915ABG Driver for Linux
+defines several of these to configure various settings.
+
+The general form of using the private wireless methods is:
+
+ % iwpriv $IFNAME method parameters
+
+Where $IFNAME is the interface name the device is registered with
+(typically eth1, customized via one of the various network interface
+name managers, such as ifrename)
+
+The supported private methods are:
+
+ get_mode
+ Can be used to report out which IEEE mode the driver is
+ configured to support. Example:
+
+ % iwpriv eth1 get_mode
+ eth1 get_mode:802.11bg (6)
+
+ set_mode
+ Can be used to configure which IEEE mode the driver will
+ support.
+
+ Usage:
+ % iwpriv eth1 set_mode {mode}
+ Where {mode} is a number in the range 1-7:
+ 1 802.11a (2915 only)
+ 2 802.11b
+ 3 802.11ab (2915 only)
+ 4 802.11g
+ 5 802.11ag (2915 only)
+ 6 802.11bg
+ 7 802.11abg (2915 only)
+
+ get_preamble
+ Can be used to report configuration of preamble length.
+
+ set_preamble
+ Can be used to set the configuration of preamble length:
+
+ Usage:
+ % iwpriv eth1 set_preamble {mode}
+ Where {mode} is one of:
+ 1 Long preamble only
+ 0 Auto (long or short based on connection)
+
+
+1.4. Sysfs Helper Files:
+-----------------------------------------------
+
+The Linux kernel provides a pseudo file system that can be used to
+access various components of the operating system. The Intel(R)
+PRO/Wireless 2915ABG Driver for Linux exposes several configuration
+parameters through this mechanism.
+
+An entry in the sysfs can support reading and/or writing. You can
+typically query the contents of a sysfs entry through the use of cat,
+and can set the contents via echo. For example:
+
+% cat /sys/bus/pci/drivers/ipw2200/debug_level
+
+Will report the current debug level of the driver's logging subsystem
+(only available if CONFIG_IPW_DEBUG was configured when the driver was
+built).
+
+You can set the debug level via:
+
+% echo $VALUE > /sys/bus/pci/drivers/ipw2200/debug_level
+
+Where $VALUE would be a number in the case of this sysfs entry. The
+input to sysfs files does not have to be a number. For example, the
+firmware loader used by hotplug utilizes sysfs entries for transferring
+the firmware image from user space into the driver.
+
+The Intel(R) PRO/Wireless 2915ABG Driver for Linux exposes sysfs entries
+at two levels -- driver level, which apply to all instances of the
+driver (in the event that there are more than one device installed) and
+device level, which applies only to the single specific instance.
+
+
+1.4.1 Driver Level Sysfs Helper Files
+-----------------------------------------------
+
+For the driver level files, look in /sys/bus/pci/drivers/ipw2200/
+
+ debug_level
+
+ This controls the same global as the 'debug' module parameter
+
+
+1.4.2 Device Level Sysfs Helper Files
+-----------------------------------------------
+
+For the device level files, look in
+
+ /sys/bus/pci/drivers/ipw2200/{PCI-ID}/
+
+For example:
+ /sys/bus/pci/drivers/ipw2200/0000:02:01.0
+
+For the device level files, see /sys/bus/pci/[drivers/ipw2200:
+
+ rf_kill
+ read -
+ 0 = RF kill not enabled (radio on)
+ 1 = SW based RF kill active (radio off)
+ 2 = HW based RF kill active (radio off)
+ 3 = Both HW and SW RF kill active (radio off)
+ write -
+ 0 = If SW based RF kill active, turn the radio back on
+ 1 = If radio is on, activate SW based RF kill
+
+ NOTE: If you enable the SW based RF kill and then toggle the HW
+ based RF kill from ON -> OFF -> ON, the radio will NOT come back on
+
+ ucode
+ read-only access to the ucode version number
+
+
+2. About the Version Numbers
+-----------------------------------------------
+
+Due to the nature of open source development projects, there are
+frequently changes being incorporated that have not gone through
+a complete validation process. These changes are incorporated into
+development snapshot releases.
+
+Releases are numbered with a three level scheme:
+
+ major.minor.development
+
+Any version where the 'development' portion is 0 (for example
+1.0.0, 1.1.0, etc.) indicates a stable version that will be made
+available for kernel inclusion.
+
+Any version where the 'development' portion is not a 0 (for
+example 1.0.1, 1.1.5, etc.) indicates a development version that is
+being made available for testing and cutting edge users. The stability
+and functionality of the development releases are not know. We make
+efforts to try and keep all snapshots reasonably stable, but due to the
+frequency of their release, and the desire to get those releases
+available as quickly as possible, unknown anomalies should be expected.
+
+The major version number will be incremented when significant changes
+are made to the driver. Currently, there are no major changes planned.
+
+
+3. Support
+-----------------------------------------------
+
+For installation support of the 1.0.0 version, you can contact
+http://supportmail.intel.com, or you can use the open source project
+support.
+
+For general information and support, go to:
+
+ http://ipw2200.sf.net/
+
+
+4. License
+-----------------------------------------------
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 24d029455baa..a55f0f95b171 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -1241,7 +1241,7 @@ traffic while still maintaining carrier on.
If running SNMP agents, the bonding driver should be loaded
before any network drivers participating in a bond. This requirement
-is due to the the interface index (ipAdEntIfIndex) being associated to
+is due to the interface index (ipAdEntIfIndex) being associated to
the first interface found with a given IP address. That is, there is
only one ipAdEntIfIndex for each IP address. For example, if eth0 and
eth1 are slaves of bond0 and the driver for eth0 is loaded before the
@@ -1937,7 +1937,7 @@ switches currently available support 802.3ad.
If not explicitly configured (with ifconfig or ip link), the
MAC address of the bonding device is taken from its first slave
device. This MAC address is then passed to all following slaves and
-remains persistent (even if the the first slave is removed) until the
+remains persistent (even if the first slave is removed) until the
bonding device is brought down or reconfigured.
If you wish to change the MAC address, you can set it with
diff --git a/Documentation/networking/cxgb.txt b/Documentation/networking/cxgb.txt
new file mode 100644
index 000000000000..76324638626b
--- /dev/null
+++ b/Documentation/networking/cxgb.txt
@@ -0,0 +1,352 @@
+ Chelsio N210 10Gb Ethernet Network Controller
+
+ Driver Release Notes for Linux
+
+ Version 2.1.1
+
+ June 20, 2005
+
+CONTENTS
+========
+ INTRODUCTION
+ FEATURES
+ PERFORMANCE
+ DRIVER MESSAGES
+ KNOWN ISSUES
+ SUPPORT
+
+
+INTRODUCTION
+============
+
+ This document describes the Linux driver for Chelsio 10Gb Ethernet Network
+ Controller. This driver supports the Chelsio N210 NIC and is backward
+ compatible with the Chelsio N110 model 10Gb NICs.
+
+
+FEATURES
+========
+
+ Adaptive Interrupts (adaptive-rx)
+ ---------------------------------
+
+ This feature provides an adaptive algorithm that adjusts the interrupt
+ coalescing parameters, allowing the driver to dynamically adapt the latency
+ settings to achieve the highest performance during various types of network
+ load.
+
+ The interface used to control this feature is ethtool. Please see the
+ ethtool manpage for additional usage information.
+
+ By default, adaptive-rx is disabled.
+ To enable adaptive-rx:
+
+ ethtool -C <interface> adaptive-rx on
+
+ To disable adaptive-rx, use ethtool:
+
+ ethtool -C <interface> adaptive-rx off
+
+ After disabling adaptive-rx, the timer latency value will be set to 50us.
+ You may set the timer latency after disabling adaptive-rx:
+
+ ethtool -C <interface> rx-usecs <microseconds>
+
+ An example to set the timer latency value to 100us on eth0:
+
+ ethtool -C eth0 rx-usecs 100
+
+ You may also provide a timer latency value while disabling adpative-rx:
+
+ ethtool -C <interface> adaptive-rx off rx-usecs <microseconds>
+
+ If adaptive-rx is disabled and a timer latency value is specified, the timer
+ will be set to the specified value until changed by the user or until
+ adaptive-rx is enabled.
+
+ To view the status of the adaptive-rx and timer latency values:
+
+ ethtool -c <interface>
+
+
+ TCP Segmentation Offloading (TSO) Support
+ -----------------------------------------
+
+ This feature, also known as "large send", enables a system's protocol stack
+ to offload portions of outbound TCP processing to a network interface card
+ thereby reducing system CPU utilization and enhancing performance.
+
+ The interface used to control this feature is ethtool version 1.8 or higher.
+ Please see the ethtool manpage for additional usage information.
+
+ By default, TSO is enabled.
+ To disable TSO:
+
+ ethtool -K <interface> tso off
+
+ To enable TSO:
+
+ ethtool -K <interface> tso on
+
+ To view the status of TSO:
+
+ ethtool -k <interface>
+
+
+PERFORMANCE
+===========
+
+ The following information is provided as an example of how to change system
+ parameters for "performance tuning" an what value to use. You may or may not
+ want to change these system parameters, depending on your server/workstation
+ application. Doing so is not warranted in any way by Chelsio Communications,
+ and is done at "YOUR OWN RISK". Chelsio will not be held responsible for loss
+ of data or damage to equipment.
+
+ Your distribution may have a different way of doing things, or you may prefer
+ a different method. These commands are shown only to provide an example of
+ what to do and are by no means definitive.
+
+ Making any of the following system changes will only last until you reboot
+ your system. You may want to write a script that runs at boot-up which
+ includes the optimal settings for your system.
+
+ Setting PCI Latency Timer:
+ setpci -d 1425:* 0x0c.l=0x0000F800
+
+ Disabling TCP timestamp:
+ sysctl -w net.ipv4.tcp_timestamps=0
+
+ Disabling SACK:
+ sysctl -w net.ipv4.tcp_sack=0
+
+ Setting large number of incoming connection requests:
+ sysctl -w net.ipv4.tcp_max_syn_backlog=3000
+
+ Setting maximum receive socket buffer size:
+ sysctl -w net.core.rmem_max=1024000
+
+ Setting maximum send socket buffer size:
+ sysctl -w net.core.wmem_max=1024000
+
+ Set smp_affinity (on a multiprocessor system) to a single CPU:
+ echo 1 > /proc/irq/<interrupt_number>/smp_affinity
+
+ Setting default receive socket buffer size:
+ sysctl -w net.core.rmem_default=524287
+
+ Setting default send socket buffer size:
+ sysctl -w net.core.wmem_default=524287
+
+ Setting maximum option memory buffers:
+ sysctl -w net.core.optmem_max=524287
+
+ Setting maximum backlog (# of unprocessed packets before kernel drops):
+ sysctl -w net.core.netdev_max_backlog=300000
+
+ Setting TCP read buffers (min/default/max):
+ sysctl -w net.ipv4.tcp_rmem="10000000 10000000 10000000"
+
+ Setting TCP write buffers (min/pressure/max):
+ sysctl -w net.ipv4.tcp_wmem="10000000 10000000 10000000"
+
+ Setting TCP buffer space (min/pressure/max):
+ sysctl -w net.ipv4.tcp_mem="10000000 10000000 10000000"
+
+ TCP window size for single connections:
+ The receive buffer (RX_WINDOW) size must be at least as large as the
+ Bandwidth-Delay Product of the communication link between the sender and
+ receiver. Due to the variations of RTT, you may want to increase the buffer
+ size up to 2 times the Bandwidth-Delay Product. Reference page 289 of
+ "TCP/IP Illustrated, Volume 1, The Protocols" by W. Richard Stevens.
+ At 10Gb speeds, use the following formula:
+ RX_WINDOW >= 1.25MBytes * RTT(in milliseconds)
+ Example for RTT with 100us: RX_WINDOW = (1,250,000 * 0.1) = 125,000
+ RX_WINDOW sizes of 256KB - 512KB should be sufficient.
+ Setting the min, max, and default receive buffer (RX_WINDOW) size:
+ sysctl -w net.ipv4.tcp_rmem="<min> <default> <max>"
+
+ TCP window size for multiple connections:
+ The receive buffer (RX_WINDOW) size may be calculated the same as single
+ connections, but should be divided by the number of connections. The
+ smaller window prevents congestion and facilitates better pacing,
+ especially if/when MAC level flow control does not work well or when it is
+ not supported on the machine. Experimentation may be necessary to attain
+ the correct value. This method is provided as a starting point fot the
+ correct receive buffer size.
+ Setting the min, max, and default receive buffer (RX_WINDOW) size is
+ performed in the same manner as single connection.
+
+
+DRIVER MESSAGES
+===============
+
+ The following messages are the most common messages logged by syslog. These
+ may be found in /var/log/messages.
+
+ Driver up:
+ Chelsio Network Driver - version 2.1.1
+
+ NIC detected:
+ eth#: Chelsio N210 1x10GBaseX NIC (rev #), PCIX 133MHz/64-bit
+
+ Link up:
+ eth#: link is up at 10 Gbps, full duplex
+
+ Link down:
+ eth#: link is down
+
+
+KNOWN ISSUES
+============
+
+ These issues have been identified during testing. The following information
+ is provided as a workaround to the problem. In some cases, this problem is
+ inherent to Linux or to a particular Linux Distribution and/or hardware
+ platform.
+
+ 1. Large number of TCP retransmits on a multiprocessor (SMP) system.
+
+ On a system with multiple CPUs, the interrupt (IRQ) for the network
+ controller may be bound to more than one CPU. This will cause TCP
+ retransmits if the packet data were to be split across different CPUs
+ and re-assembled in a different order than expected.
+
+ To eliminate the TCP retransmits, set smp_affinity on the particular
+ interrupt to a single CPU. You can locate the interrupt (IRQ) used on
+ the N110/N210 by using ifconfig:
+ ifconfig <dev_name> | grep Interrupt
+ Set the smp_affinity to a single CPU:
+ echo 1 > /proc/irq/<interrupt_number>/smp_affinity
+
+ It is highly suggested that you do not run the irqbalance daemon on your
+ system, as this will change any smp_affinity setting you have applied.
+ The irqbalance daemon runs on a 10 second interval and binds interrupts
+ to the least loaded CPU determined by the daemon. To disable this daemon:
+ chkconfig --level 2345 irqbalance off
+
+ By default, some Linux distributions enable the kernel feature,
+ irqbalance, which performs the same function as the daemon. To disable
+ this feature, add the following line to your bootloader:
+ noirqbalance
+
+ Example using the Grub bootloader:
+ title Red Hat Enterprise Linux AS (2.4.21-27.ELsmp)
+ root (hd0,0)
+ kernel /vmlinuz-2.4.21-27.ELsmp ro root=/dev/hda3 noirqbalance
+ initrd /initrd-2.4.21-27.ELsmp.img
+
+ 2. After running insmod, the driver is loaded and the incorrect network
+ interface is brought up without running ifup.
+
+ When using 2.4.x kernels, including RHEL kernels, the Linux kernel
+ invokes a script named "hotplug". This script is primarily used to
+ automatically bring up USB devices when they are plugged in, however,
+ the script also attempts to automatically bring up a network interface
+ after loading the kernel module. The hotplug script does this by scanning
+ the ifcfg-eth# config files in /etc/sysconfig/network-scripts, looking
+ for HWADDR=<mac_address>.
+
+ If the hotplug script does not find the HWADDRR within any of the
+ ifcfg-eth# files, it will bring up the device with the next available
+ interface name. If this interface is already configured for a different
+ network card, your new interface will have incorrect IP address and
+ network settings.
+
+ To solve this issue, you can add the HWADDR=<mac_address> key to the
+ interface config file of your network controller.
+
+ To disable this "hotplug" feature, you may add the driver (module name)
+ to the "blacklist" file located in /etc/hotplug. It has been noted that
+ this does not work for network devices because the net.agent script
+ does not use the blacklist file. Simply remove, or rename, the net.agent
+ script located in /etc/hotplug to disable this feature.
+
+ 3. Transport Protocol (TP) hangs when running heavy multi-connection traffic
+ on an AMD Opteron system with HyperTransport PCI-X Tunnel chipset.
+
+ If your AMD Opteron system uses the AMD-8131 HyperTransport PCI-X Tunnel
+ chipset, you may experience the "133-Mhz Mode Split Completion Data
+ Corruption" bug identified by AMD while using a 133Mhz PCI-X card on the
+ bus PCI-X bus.
+
+ AMD states, "Under highly specific conditions, the AMD-8131 PCI-X Tunnel
+ can provide stale data via split completion cycles to a PCI-X card that
+ is operating at 133 Mhz", causing data corruption.
+
+ AMD's provides three workarounds for this problem, however, Chelsio
+ recommends the first option for best performance with this bug:
+
+ For 133Mhz secondary bus operation, limit the transaction length and
+ the number of outstanding transactions, via BIOS configuration
+ programming of the PCI-X card, to the following:
+
+ Data Length (bytes): 1k
+ Total allowed outstanding transactions: 2
+
+ Please refer to AMD 8131-HT/PCI-X Errata 26310 Rev 3.08 August 2004,
+ section 56, "133-MHz Mode Split Completion Data Corruption" for more
+ details with this bug and workarounds suggested by AMD.
+
+ It may be possible to work outside AMD's recommended PCI-X settings, try
+ increasing the Data Length to 2k bytes for increased performance. If you
+ have issues with these settings, please revert to the "safe" settings
+ and duplicate the problem before submitting a bug or asking for support.
+
+ NOTE: The default setting on most systems is 8 outstanding transactions
+ and 2k bytes data length.
+
+ 4. On multiprocessor systems, it has been noted that an application which
+ is handling 10Gb networking can switch between CPUs causing degraded
+ and/or unstable performance.
+
+ If running on an SMP system and taking performance measurements, it
+ is suggested you either run the latest netperf-2.4.0+ or use a binding
+ tool such as Tim Hockin's procstate utilities (runon)
+ <http://www.hockin.org/~thockin/procstate/>.
+
+ Binding netserver and netperf (or other applications) to particular
+ CPUs will have a significant difference in performance measurements.
+ You may need to experiment which CPU to bind the application to in
+ order to achieve the best performance for your system.
+
+ If you are developing an application designed for 10Gb networking,
+ please keep in mind you may want to look at kernel functions
+ sched_setaffinity & sched_getaffinity to bind your application.
+
+ If you are just running user-space applications such as ftp, telnet,
+ etc., you may want to try the runon tool provided by Tim Hockin's
+ procstate utility. You could also try binding the interface to a
+ particular CPU: runon 0 ifup eth0
+
+
+SUPPORT
+=======
+
+ If you have problems with the software or hardware, please contact our
+ customer support team via email at support@chelsio.com or check our website
+ at http://www.chelsio.com
+
+===============================================================================
+
+ Chelsio Communications
+ 370 San Aleso Ave.
+ Suite 100
+ Sunnyvale, CA 94085
+ http://www.chelsio.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.
+
+You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ Copyright (c) 2003-2005 Chelsio Communications. All rights reserved.
+
+===============================================================================
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
new file mode 100644
index 000000000000..29ccae409031
--- /dev/null
+++ b/Documentation/networking/phy.txt
@@ -0,0 +1,288 @@
+
+-------
+PHY Abstraction Layer
+(Updated 2005-07-21)
+
+Purpose
+
+ Most network devices consist of set of registers which provide an interface
+ to a MAC layer, which communicates with the physical connection through a
+ PHY. The PHY concerns itself with negotiating link parameters with the link
+ partner on the other side of the network connection (typically, an ethernet
+ cable), and provides a register interface to allow drivers to determine what
+ settings were chosen, and to configure what settings are allowed.
+
+ While these devices are distinct from the network devices, and conform to a
+ standard layout for the registers, it has been common practice to integrate
+ the PHY management code with the network driver. This has resulted in large
+ amounts of redundant code. Also, on embedded systems with multiple (and
+ sometimes quite different) ethernet controllers connected to the same
+ management bus, it is difficult to ensure safe use of the bus.
+
+ Since the PHYs are devices, and the management busses through which they are
+ accessed are, in fact, busses, the PHY Abstraction Layer treats them as such.
+ In doing so, it has these goals:
+
+ 1) Increase code-reuse
+ 2) Increase overall code-maintainability
+ 3) Speed development time for new network drivers, and for new systems
+
+ Basically, this layer is meant to provide an interface to PHY devices which
+ allows network driver writers to write as little code as possible, while
+ still providing a full feature set.
+
+The MDIO bus
+
+ Most network devices are connected to a PHY by means of a management bus.
+ Different devices use different busses (though some share common interfaces).
+ In order to take advantage of the PAL, each bus interface needs to be
+ registered as a distinct device.
+
+ 1) read and write functions must be implemented. Their prototypes are:
+
+ int write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+ int read(struct mii_bus *bus, int mii_id, int regnum);
+
+ mii_id is the address on the bus for the PHY, and regnum is the register
+ number. These functions are guaranteed not to be called from interrupt
+ time, so it is safe for them to block, waiting for an interrupt to signal
+ the operation is complete
+
+ 2) A reset function is necessary. This is used to return the bus to an
+ initialized state.
+
+ 3) A probe function is needed. This function should set up anything the bus
+ driver needs, setup the mii_bus structure, and register with the PAL using
+ mdiobus_register. Similarly, there's a remove function to undo all of
+ that (use mdiobus_unregister).
+
+ 4) Like any driver, the device_driver structure must be configured, and init
+ exit functions are used to register the driver.
+
+ 5) The bus must also be declared somewhere as a device, and registered.
+
+ As an example for how one driver implemented an mdio bus driver, see
+ drivers/net/gianfar_mii.c and arch/ppc/syslib/mpc85xx_devices.c
+
+Connecting to a PHY
+
+ Sometime during startup, the network driver needs to establish a connection
+ between the PHY device, and the network device. At this time, the PHY's bus
+ and drivers need to all have been loaded, so it is ready for the connection.
+ At this point, there are several ways to connect to the PHY:
+
+ 1) The PAL handles everything, and only calls the network driver when
+ the link state changes, so it can react.
+
+ 2) The PAL handles everything except interrupts (usually because the
+ controller has the interrupt registers).
+
+ 3) The PAL handles everything, but checks in with the driver every second,
+ allowing the network driver to react first to any changes before the PAL
+ does.
+
+ 4) The PAL serves only as a library of functions, with the network device
+ manually calling functions to update status, and configure the PHY
+
+
+Letting the PHY Abstraction Layer do Everything
+
+ If you choose option 1 (The hope is that every driver can, but to still be
+ useful to drivers that can't), connecting to the PHY is simple:
+
+ First, you need a function to react to changes in the link state. This
+ function follows this protocol:
+
+ static void adjust_link(struct net_device *dev);
+
+ Next, you need to know the device name of the PHY connected to this device.
+ The name will look something like, "phy0:0", where the first number is the
+ bus id, and the second is the PHY's address on that bus.
+
+ Now, to connect, just call this function:
+
+ phydev = phy_connect(dev, phy_name, &adjust_link, flags);
+
+ phydev is a pointer to the phy_device structure which represents the PHY. If
+ phy_connect is successful, it will return the pointer. dev, here, is the
+ pointer to your net_device. Once done, this function will have started the
+ PHY's software state machine, and registered for the PHY's interrupt, if it
+ has one. The phydev structure will be populated with information about the
+ current state, though the PHY will not yet be truly operational at this
+ point.
+
+ flags is a u32 which can optionally contain phy-specific flags.
+ This is useful if the system has put hardware restrictions on
+ the PHY/controller, of which the PHY needs to be aware.
+
+ Now just make sure that phydev->supported and phydev->advertising have any
+ values pruned from them which don't make sense for your controller (a 10/100
+ controller may be connected to a gigabit capable PHY, so you would need to
+ mask off SUPPORTED_1000baseT*). See include/linux/ethtool.h for definitions
+ for these bitfields. Note that you should not SET any bits, or the PHY may
+ get put into an unsupported state.
+
+ Lastly, once the controller is ready to handle network traffic, you call
+ phy_start(phydev). This tells the PAL that you are ready, and configures the
+ PHY to connect to the network. If you want to handle your own interrupts,
+ just set phydev->irq to PHY_IGNORE_INTERRUPT before you call phy_start.
+ Similarly, if you don't want to use interrupts, set phydev->irq to PHY_POLL.
+
+ When you want to disconnect from the network (even if just briefly), you call
+ phy_stop(phydev).
+
+Keeping Close Tabs on the PAL
+
+ It is possible that the PAL's built-in state machine needs a little help to
+ keep your network device and the PHY properly in sync. If so, you can
+ register a helper function when connecting to the PHY, which will be called
+ every second before the state machine reacts to any changes. To do this, you
+ need to manually call phy_attach() and phy_prepare_link(), and then call
+ phy_start_machine() with the second argument set to point to your special
+ handler.
+
+ Currently there are no examples of how to use this functionality, and testing
+ on it has been limited because the author does not have any drivers which use
+ it (they all use option 1). So Caveat Emptor.
+
+Doing it all yourself
+
+ There's a remote chance that the PAL's built-in state machine cannot track
+ the complex interactions between the PHY and your network device. If this is
+ so, you can simply call phy_attach(), and not call phy_start_machine or
+ phy_prepare_link(). This will mean that phydev->state is entirely yours to
+ handle (phy_start and phy_stop toggle between some of the states, so you
+ might need to avoid them).
+
+ An effort has been made to make sure that useful functionality can be
+ accessed without the state-machine running, and most of these functions are
+ descended from functions which did not interact with a complex state-machine.
+ However, again, no effort has been made so far to test running without the
+ state machine, so tryer beware.
+
+ Here is a brief rundown of the functions:
+
+ int phy_read(struct phy_device *phydev, u16 regnum);
+ int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
+
+ Simple read/write primitives. They invoke the bus's read/write function
+ pointers.
+
+ void phy_print_status(struct phy_device *phydev);
+
+ A convenience function to print out the PHY status neatly.
+
+ int phy_clear_interrupt(struct phy_device *phydev);
+ int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+
+ Clear the PHY's interrupt, and configure which ones are allowed,
+ respectively. Currently only supports all on, or all off.
+
+ int phy_enable_interrupts(struct phy_device *phydev);
+ int phy_disable_interrupts(struct phy_device *phydev);
+
+ Functions which enable/disable PHY interrupts, clearing them
+ before and after, respectively.
+
+ int phy_start_interrupts(struct phy_device *phydev);
+ int phy_stop_interrupts(struct phy_device *phydev);
+
+ Requests the IRQ for the PHY interrupts, then enables them for
+ start, or disables then frees them for stop.
+
+ struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
+ u32 flags);
+
+ Attaches a network device to a particular PHY, binding the PHY to a generic
+ driver if none was found during bus initialization. Passes in
+ any phy-specific flags as needed.
+
+ int phy_start_aneg(struct phy_device *phydev);
+
+ Using variables inside the phydev structure, either configures advertising
+ and resets autonegotiation, or disables autonegotiation, and configures
+ forced settings.
+
+ static inline int phy_read_status(struct phy_device *phydev);
+
+ Fills the phydev structure with up-to-date information about the current
+ settings in the PHY.
+
+ void phy_sanitize_settings(struct phy_device *phydev)
+
+ Resolves differences between currently desired settings, and
+ supported settings for the given PHY device. Does not make
+ the changes in the hardware, though.
+
+ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+
+ Ethtool convenience functions.
+
+ int phy_mii_ioctl(struct phy_device *phydev,
+ struct mii_ioctl_data *mii_data, int cmd);
+
+ The MII ioctl. Note that this function will completely screw up the state
+ machine if you write registers like BMCR, BMSR, ADVERTISE, etc. Best to
+ use this only to write registers which are not standard, and don't set off
+ a renegotiation.
+
+
+PHY Device Drivers
+
+ With the PHY Abstraction Layer, adding support for new PHYs is
+ quite easy. In some cases, no work is required at all! However,
+ many PHYs require a little hand-holding to get up-and-running.
+
+Generic PHY driver
+
+ If the desired PHY doesn't have any errata, quirks, or special
+ features you want to support, then it may be best to not add
+ support, and let the PHY Abstraction Layer's Generic PHY Driver
+ do all of the work.
+
+Writing a PHY driver
+
+ If you do need to write a PHY driver, the first thing to do is
+ make sure it can be matched with an appropriate PHY device.
+ This is done during bus initialization by reading the device's
+ UID (stored in registers 2 and 3), then comparing it to each
+ driver's phy_id field by ANDing it with each driver's
+ phy_id_mask field. Also, it needs a name. Here's an example:
+
+ static struct phy_driver dm9161_driver = {
+ .phy_id = 0x0181b880,
+ .name = "Davicom DM9161E",
+ .phy_id_mask = 0x0ffffff0,
+ ...
+ }
+
+ Next, you need to specify what features (speed, duplex, autoneg,
+ etc) your PHY device and driver support. Most PHYs support
+ PHY_BASIC_FEATURES, but you can look in include/mii.h for other
+ features.
+
+ Each driver consists of a number of function pointers:
+
+ config_init: configures PHY into a sane state after a reset.
+ For instance, a Davicom PHY requires descrambling disabled.
+ probe: Does any setup needed by the driver
+ suspend/resume: power management
+ config_aneg: Changes the speed/duplex/negotiation settings
+ read_status: Reads the current speed/duplex/negotiation settings
+ ack_interrupt: Clear a pending interrupt
+ config_intr: Enable or disable interrupts
+ remove: Does any driver take-down
+
+ Of these, only config_aneg and read_status are required to be
+ assigned by the driver code. The rest are optional. Also, it is
+ preferred to use the generic phy driver's versions of these two
+ functions if at all possible: genphy_read_status and
+ genphy_config_aneg. If this is not possible, it is likely that
+ you only need to perform some actions before and after invoking
+ these functions, and so your functions will wrap the generic
+ ones.
+
+ Feel free to look at the Marvell, Cicada, and Davicom drivers in
+ drivers/net/phy/ for examples (the lxt and qsemi drivers have
+ not been tested as of this writing)
diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
index aea20cd2a56e..c96897aa08b6 100644
--- a/Documentation/networking/wan-router.txt
+++ b/Documentation/networking/wan-router.txt
@@ -355,7 +355,7 @@ REVISION HISTORY
There is no functional difference between the two packages
2.0.7 Aug 26, 1999 o Merged X25API code into WANPIPE.
- o Fixed a memeory leak for X25API
+ o Fixed a memory leak for X25API
o Updated the X25API code for 2.2.X kernels.
o Improved NEM handling.
@@ -514,7 +514,7 @@ beta2-2.2.0 Jan 8 2001
o Patches for 2.4.0 kernel
o Patches for 2.2.18 kernel
o Minor updates to PPP and CHLDC drivers.
- Note: No functinal difference.
+ Note: No functional difference.
beta3-2.2.9 Jan 10 2001
o I missed the 2.2.18 kernel patches in beta2-2.2.0
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index da711028e5f7..66eaaab7773d 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -205,8 +205,8 @@ Phone: 701-234-7556
Tainted kernels:
Some oops reports contain the string 'Tainted: ' after the program
-counter, this indicates that the kernel has been tainted by some
-mechanism. The string is followed by a series of position sensitive
+counter. This indicates that the kernel has been tainted by some
+mechanism. The string is followed by a series of position-sensitive
characters, each representing a particular tainted value.
1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
@@ -214,16 +214,25 @@ characters, each representing a particular tainted value.
MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
insmod as GPL compatible are assumed to be proprietary.
- 2: 'F' if any module was force loaded by insmod -f, ' ' if all
+ 2: 'F' if any module was force loaded by "insmod -f", ' ' if all
modules were loaded normally.
3: 'S' if the oops occurred on an SMP kernel running on hardware that
- hasn't been certified as safe to run multiprocessor.
- Currently this occurs only on various Athlons that are not
- SMP capable.
+ hasn't been certified as safe to run multiprocessor.
+ Currently this occurs only on various Athlons that are not
+ SMP capable.
+
+ 4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
+ modules were unloaded normally.
+
+ 5: 'M' if any processor has reported a Machine Check Exception,
+ ' ' if no Machine Check Exceptions have occurred.
+
+ 6: 'B' if a page-release function has found a bad page reference or
+ some unexpected page flags.
The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has
-occurred. Tainting is permanent, even if an offending module is
-unloading the tainted value remains to indicate that the kernel is not
+occurred. Tainting is permanent: even if an offending module is
+unloaded, the tainted value remains to indicate that the kernel is not
trustworthy.
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 76d28d033657..711210b38f5f 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -84,7 +84,7 @@ Each entry consists of:
Most drivers don't need to use the driver_data field. Best practice
for use of driver_data is to use it as an index into a static list of
-equivalant device types, not to use it as a pointer.
+equivalent device types, not to use it as a pointer.
Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}
to have probe() called for every PCI device known to the system.
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index cc63ae18d147..2ea1149bf6b0 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -38,6 +38,12 @@ system the associated daemon will exit gracefully.
Driver Interface -- OBSOLETE, DO NOT USE!
----------------*************************
+
+Note: pm_register(), pm_access(), pm_dev_idle() and friends are
+obsolete. Please do not use them. Instead you should properly hook
+your driver into the driver model, and use its suspend()/resume()
+callbacks to do this kind of stuff.
+
If you are writing a new driver or maintaining an old driver, it
should include power management support. Without power management
support, a single driver may prevent a system with power management
diff --git a/Documentation/power/swsusp-dmcrypt.txt b/Documentation/power/swsusp-dmcrypt.txt
new file mode 100644
index 000000000000..59931b46ff7e
--- /dev/null
+++ b/Documentation/power/swsusp-dmcrypt.txt
@@ -0,0 +1,138 @@
+Author: Andreas Steinmetz <ast@domdv.de>
+
+
+How to use dm-crypt and swsusp together:
+========================================
+
+Some prerequisites:
+You know how dm-crypt works. If not, visit the following web page:
+http://www.saout.de/misc/dm-crypt/
+You have read Documentation/power/swsusp.txt and understand it.
+You did read Documentation/initrd.txt and know how an initrd works.
+You know how to create or how to modify an initrd.
+
+Now your system is properly set up, your disk is encrypted except for
+the swap device(s) and the boot partition which may contain a mini
+system for crypto setup and/or rescue purposes. You may even have
+an initrd that does your current crypto setup already.
+
+At this point you want to encrypt your swap, too. Still you want to
+be able to suspend using swsusp. This, however, means that you
+have to be able to either enter a passphrase or that you read
+the key(s) from an external device like a pcmcia flash disk
+or an usb stick prior to resume. So you need an initrd, that sets
+up dm-crypt and then asks swsusp to resume from the encrypted
+swap device.
+
+The most important thing is that you set up dm-crypt in such
+a way that the swap device you suspend to/resume from has
+always the same major/minor within the initrd as well as
+within your running system. The easiest way to achieve this is
+to always set up this swap device first with dmsetup, so that
+it will always look like the following:
+
+brw------- 1 root root 254, 0 Jul 28 13:37 /dev/mapper/swap0
+
+Now set up your kernel to use /dev/mapper/swap0 as the default
+resume partition, so your kernel .config contains:
+
+CONFIG_PM_STD_PARTITION="/dev/mapper/swap0"
+
+Prepare your boot loader to use the initrd you will create or
+modify. For lilo the simplest setup looks like the following
+lines:
+
+image=/boot/vmlinuz
+initrd=/boot/initrd.gz
+label=linux
+append="root=/dev/ram0 init=/linuxrc rw"
+
+Finally you need to create or modify your initrd. Lets assume
+you create an initrd that reads the required dm-crypt setup
+from a pcmcia flash disk card. The card is formatted with an ext2
+fs which resides on /dev/hde1 when the card is inserted. The
+card contains at least the encrypted swap setup in a file
+named "swapkey". /etc/fstab of your initrd contains something
+like the following:
+
+/dev/hda1 /mnt ext3 ro 0 0
+none /proc proc defaults,noatime,nodiratime 0 0
+none /sys sysfs defaults,noatime,nodiratime 0 0
+
+/dev/hda1 contains an unencrypted mini system that sets up all
+of your crypto devices, again by reading the setup from the
+pcmcia flash disk. What follows now is a /linuxrc for your
+initrd that allows you to resume from encrypted swap and that
+continues boot with your mini system on /dev/hda1 if resume
+does not happen:
+
+#!/bin/sh
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+mount /proc
+mount /sys
+mapped=0
+noresume=`grep -c noresume /proc/cmdline`
+if [ "$*" != "" ]
+then
+ noresume=1
+fi
+dmesg -n 1
+/sbin/cardmgr -q
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+ if [ -f /proc/ide/hde/media ]
+ then
+ usleep 500000
+ mount -t ext2 -o ro /dev/hde1 /mnt
+ if [ -f /mnt/swapkey ]
+ then
+ dmsetup create swap0 /mnt/swapkey > /dev/null 2>&1 && mapped=1
+ fi
+ umount /mnt
+ break
+ fi
+ usleep 500000
+done
+killproc /sbin/cardmgr
+dmesg -n 6
+if [ $mapped = 1 ]
+then
+ if [ $noresume != 0 ]
+ then
+ mkswap /dev/mapper/swap0 > /dev/null 2>&1
+ fi
+ echo 254:0 > /sys/power/resume
+ dmsetup remove swap0
+fi
+umount /sys
+mount /mnt
+umount /proc
+cd /mnt
+pivot_root . mnt
+mount /proc
+umount -l /mnt
+umount /proc
+exec chroot . /sbin/init $* < dev/console > dev/console 2>&1
+
+Please don't mind the weird loop above, busybox's msh doesn't know
+the let statement. Now, what is happening in the script?
+First we have to decide if we want to try to resume, or not.
+We will not resume if booting with "noresume" or any parameters
+for init like "single" or "emergency" as boot parameters.
+
+Then we need to set up dmcrypt with the setup data from the
+pcmcia flash disk. If this succeeds we need to reset the swap
+device if we don't want to resume. The line "echo 254:0 > /sys/power/resume"
+then attempts to resume from the first device mapper device.
+Note that it is important to set the device in /sys/power/resume,
+regardless if resuming or not, otherwise later suspend will fail.
+If resume starts, script execution terminates here.
+
+Otherwise we just remove the encrypted swap device and leave it to the
+mini system on /dev/hda1 to set the whole crypto up (it is up to
+you to modify this to your taste).
+
+What then follows is the well known process to change the root
+file system and continue booting from there. I prefer to unmount
+the initrd prior to continue booting but it is up to you to modify
+this.
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 7a6b78966459..b0d50840788e 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -1,22 +1,20 @@
-From kernel/suspend.c:
+Some warnings, first.
* BIG FAT WARNING *********************************************************
*
- * If you have unsupported (*) devices using DMA...
- * ...say goodbye to your data.
- *
* If you touch anything on disk between suspend and resume...
* ...kiss your data goodbye.
*
- * If your disk driver does not support suspend... (IDE does)
- * ...you'd better find out how to get along
- * without your data.
- *
- * If you change kernel command line between suspend and resume...
- * ...prepare for nasty fsck or worse.
+ * If you do resume from initrd after your filesystems are mounted...
+ * ...bye bye root partition.
+ * [this is actually same case as above]
*
- * If you change your hardware while system is suspended...
- * ...well, it was not good idea.
+ * If you have unsupported (*) devices using DMA, you may have some
+ * problems. If your disk driver does not support suspend... (IDE does),
+ * it may cause some problems, too. If you change kernel command line
+ * between suspend and resume, it may do something wrong. If you change
+ * your hardware while system is suspended... well, it was not good idea;
+ * but it will probably only crash.
*
* (*) suspend/resume support is needed to make it safe.
@@ -30,6 +28,13 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
echo platform > /sys/power/disk; echo disk > /sys/power/state
+Encrypted suspend image:
+------------------------
+If you want to store your suspend image encrypted with a temporary
+key to prevent data gathering after resume you must compile
+crypto and the aes algorithm into the kernel - modules won't work
+as they cannot be loaded at resume time.
+
Article about goals and implementation of Software Suspend for Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -85,11 +90,6 @@ resume.
You have your server on UPS. Power died, and UPS is indicating 30
seconds to failure. What do you do? Suspend to disk.
-Ethernet card in your server died. You want to replace it. Your
-server is not hotplug capable. What do you do? Suspend to disk,
-replace ethernet card, resume. If you are fast your users will not
-even see broken connections.
-
Q: Maybe I'm missing something, but why don't the regular I/O paths work?
@@ -117,31 +117,6 @@ Q: Does linux support ACPI S4?
A: Yes. That's what echo platform > /sys/power/disk does.
-Q: My machine doesn't work with ACPI. How can I use swsusp than ?
-
-A: Do a reboot() syscall with right parameters. Warning: glibc gets in
-its way, so check with strace:
-
-reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 0xd000fce2)
-
-(Thanks to Peter Osterlund:)
-
-#include <unistd.h>
-#include <syscall.h>
-
-#define LINUX_REBOOT_MAGIC1 0xfee1dead
-#define LINUX_REBOOT_MAGIC2 672274793
-#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
-
-int main()
-{
- syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_SW_SUSPEND, 0);
- return 0;
-}
-
-Also /sys/ interface should be still present.
-
Q: What is 'suspend2'?
A: suspend2 is 'Software Suspend 2', a forked implementation of
@@ -311,3 +286,46 @@ As a rule of thumb use encrypted swap to protect your data while your
system is shut down or suspended. Additionally use the encrypted
suspend image to prevent sensitive data from being stolen after
resume.
+
+Q: Why can't we suspend to a swap file?
+
+A: Because accessing swap file needs the filesystem mounted, and
+filesystem might do something wrong (like replaying the journal)
+during mount.
+
+There are few ways to get that fixed:
+
+1) Probably could be solved by modifying every filesystem to support
+some kind of "really read-only!" option. Patches welcome.
+
+2) suspend2 gets around that by storing absolute positions in on-disk
+image (and blocksize), with resume parameter pointing directly to
+suspend header.
+
+Q: Is there a maximum system RAM size that is supported by swsusp?
+
+A: It should work okay with highmem.
+
+Q: Does swsusp (to disk) use only one swap partition or can it use
+multiple swap partitions (aggregate them into one logical space)?
+
+A: Only one swap partition, sorry.
+
+Q: If my application(s) causes lots of memory & swap space to be used
+(over half of the total system RAM), is it correct that it is likely
+to be useless to try to suspend to disk while that app is running?
+
+A: No, it should work okay, as long as your app does not mlock()
+it. Just prepare big enough swap partition.
+
+Q: What information is usefull for debugging suspend-to-disk problems?
+
+A: Well, last messages on the screen are always useful. If something
+is broken, it is usually some kernel driver, therefore trying with as
+little as possible modules loaded helps a lot. I also prefer people to
+suspend from console, preferably without X running. Booting with
+init=/bin/bash, then swapon and starting suspend sequence manually
+usually does the trick. Then it is good idea to try with latest
+vanilla kernel.
+
+
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index 7a4a5036d123..526d6dd267ea 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -46,6 +46,12 @@ There are a few types of systems where video works after S3 resume:
POSTing bios works. Ole Rohne has patch to do just that at
http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
+(8) on some systems, you can use the video_post utility mentioned here:
+ http://bugzilla.kernel.org/show_bug.cgi?id=3670. Do echo 3 > /sys/power/state
+ && /usr/sbin/video_post - which will initialize the display in console mode.
+ If you are in X, you can switch to a virtual terminal and back to X using
+ CTRL+ALT+F1 - CTRL+ALT+F7 to get the display working in graphical mode again.
+
Now, if you pass acpi_sleep=something, and it does not work with your
bios, you'll get a hard crash during resume. Be careful. Also it is
safest to do your experiments with plain old VGA console. The vesafb
@@ -64,7 +70,8 @@ Model hack (or "how to do it")
------------------------------------------------------------------------------
Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI
Acer TM 242FX vbetool (6)
-Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6)
+Acer TM C110 video_post (8)
+Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8)
Acer TM 4052LCi s3_bios (2)
Acer TM 636Lci s3_bios vga=normal (2)
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
@@ -113,6 +120,7 @@ IBM ThinkPad T42p (2373-GTG) s3_bios (2)
IBM TP X20 ??? (*)
IBM TP X30 s3_bios (2)
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
IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
Medion MD4220 ??? (*)
Samsung P35 vbetool needed (6)
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
index 2bfe71beec5b..e75d7474322c 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.txt
+++ b/Documentation/powerpc/eeh-pci-error-recovery.txt
@@ -134,7 +134,7 @@ pci_get_device_by_addr() will find the pci device associated
with that address (if any).
The default include/asm-ppc64/io.h macros readb(), inb(), insb(),
-etc. include a check to see if the the i/o read returned all-0xff's.
+etc. include a check to see if the i/o read returned all-0xff's.
If so, these make a call to eeh_dn_check_failure(), which in turn
asks the firmware if the all-ff's value is the sign of a true EEH
error. If it is not, processing continues as normal. The grand
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index e24fdeada970..e321a8ed2a2d 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -468,7 +468,7 @@ The hex_ascii view shows the data field in hex and ascii representation
The raw view returns a bytestream as the debug areas are stored in memory.
The sprintf view formats the debug entries in the same way as the sprintf
-function would do. The sprintf event/expection fuctions write to the
+function would do. The sprintf event/expection functions write to the
debug entry a pointer to the format string (size = sizeof(long))
and for each vararg a long value. So e.g. for a debug entry with a format
string plus two varargs one would need to allocate a (3 * sizeof(long))
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index f9cb5bdcce41..fef92ebf266f 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -60,6 +60,8 @@ scsi.txt
- short blurb on using SCSI support as a module.
scsi_mid_low_api.txt
- info on API between SCSI layer and low level drivers
+scsi_eh.txt
+ - info on SCSI midlayer error handling infrastructure
st.txt
- info on scsi tape driver
sym53c500_cs.txt
diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt
index 160e7354cd1e..47e74ddc4bc9 100644
--- a/Documentation/scsi/aic7xxx.txt
+++ b/Documentation/scsi/aic7xxx.txt
@@ -1,5 +1,5 @@
====================================================================
-= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28 =
+= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 =
= README for =
= The Linux Operating System =
====================================================================
@@ -131,6 +131,10 @@ The following information is available in this file:
SCSI "stub" effects.
2. Version History
+ 7.0 (4th August, 2005)
+ - Updated driver to use SCSI transport class infrastructure
+ - Upported sequencer and core fixes from last adaptec released
+ version of the driver.
6.2.36 (June 3rd, 2003)
- Correct code that disables PCI parity error checking.
- Correct and simplify handling of the ignore wide residue
diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
index 2814491600ff..2ffb3ae0ef4d 100644
--- a/Documentation/scsi/ibmmca.txt
+++ b/Documentation/scsi/ibmmca.txt
@@ -344,7 +344,7 @@
/proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
This table is quite informative for interested users. It shows the load
- of commands on the subsystem and wether you are running the bypassed
+ of commands on the subsystem and whether you are running the bypassed
(software) or integrated (hardware) SCSI-command set (see below). The
amount of accesses is shown. Read, write, modeselect is shown separately
in order to help debugging problems with CD-ROMs or tapedrives.
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
new file mode 100644
index 000000000000..534a50922a7b
--- /dev/null
+++ b/Documentation/scsi/scsi_eh.txt
@@ -0,0 +1,479 @@
+
+SCSI EH
+======================================
+
+ This document describes SCSI midlayer error handling infrastructure.
+Please refer to Documentation/scsi/scsi_mid_low_api.txt for more
+information regarding SCSI midlayer.
+
+TABLE OF CONTENTS
+
+[1] How SCSI commands travel through the midlayer and to EH
+ [1-1] struct scsi_cmnd
+ [1-2] How do scmd's get completed?
+ [1-2-1] Completing a scmd w/ scsi_done
+ [1-2-2] Completing a scmd w/ timeout
+ [1-3] How EH takes over
+[2] How SCSI EH works
+ [2-1] EH through fine-grained callbacks
+ [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-3] Things to consider
+
+
+[1] How SCSI commands travel through the midlayer and to EH
+
+[1-1] struct scsi_cmnd
+
+ Each SCSI command is represented with struct scsi_cmnd (== scmd). A
+scmd has two list_head's to link itself into lists. The two are
+scmd->list and scmd->eh_entry. The former is used for free list or
+per-device allocated scmd list and not of much interest to this EH
+discussion. The latter is used for completion and EH lists and unless
+otherwise stated scmds are always linked using scmd->eh_entry in this
+discussion.
+
+
+[1-2] How do scmd's get completed?
+
+ Once LLDD gets hold of a scmd, either the LLDD will complete the
+command by calling scsi_done callback passed from midlayer when
+invoking hostt->queuecommand() or SCSI midlayer will time it out.
+
+
+[1-2-1] Completing a scmd w/ scsi_done
+
+ For all non-EH commands, scsi_done() is the completion callback. It
+does the following.
+
+ 1. Delete timeout timer. If it fails, it means that timeout timer
+ has expired and is going to finish the command. Just return.
+
+ 2. Link scmd to per-cpu scsi_done_q using scmd->en_entry
+
+ 3. Raise SCSI_SOFTIRQ
+
+ SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to
+determine what to do with the command. scsi_decide_disposition()
+looks at the scmd->result value and sense data to determine what to do
+with the command.
+
+ - SUCCESS
+ scsi_finish_command() is invoked for the command. The
+ function does some maintenance choirs and notify completion by
+ calling scmd->done() callback, which, for fs requests, would
+ be HLD completion callback - sd:sd_rw_intr, sr:rw_intr,
+ st:st_intr.
+
+ - NEEDS_RETRY
+ - ADD_TO_MLQUEUE
+ scmd is requeued to blk queue.
+
+ - otherwise
+ scsi_eh_scmd_add(scmd, 0) is invoked for the command. See
+ [1-3] for details of this funciton.
+
+
+[1-2-2] Completing a scmd w/ timeout
+
+ The timeout handler is scsi_times_out(). When a timeout occurs, this
+function
+
+ 1. invokes optional hostt->eh_timedout() callback. Return value can
+ be one of
+
+ - EH_HANDLED
+ This indicates that eh_timedout() dealt with the timeout. The
+ scmd is passed to __scsi_done() and thus linked into per-cpu
+ scsi_done_q. Normal command completion described in [1-2-1]
+ follows.
+
+ - EH_RESET_TIMER
+ This indicates that more time is required to finish the
+ command. Timer is restarted. This action is counted as a
+ retry and only allowed scmd->allowed + 1(!) times. Once the
+ limit is reached, action for EH_NOT_HANDLED is taken instead.
+
+ *NOTE* This action is racy as the LLDD could finish the scmd
+ after the timeout has expired but before it's added back. In
+ such cases, scsi_done() would think that timeout has occurred
+ and return without doing anything. We lose completion and the
+ command will time out again.
+
+ - EH_NOT_HANDLED
+ This is the same as when eh_timedout() callback doesn't exist.
+ Step #2 is taken.
+
+ 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
+ command. See [1-3] for more information.
+
+
+[1-3] How EH takes over
+
+ scmds enter EH via scsi_eh_scmd_add(), which does the following.
+
+ 1. Turns on scmd->eh_eflags as requested. It's 0 for error
+ completions and SCSI_EH_CANCEL_CMD for timeouts.
+
+ 2. Links scmd->eh_entry to shost->eh_cmd_q
+
+ 3. Sets SHOST_RECOVERY bit in shost->shost_state
+
+ 4. Increments shost->host_failed
+
+ 5. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed
+
+ As can be seen above, once any scmd is added to shost->eh_cmd_q,
+SHOST_RECOVERY shost_state bit is turned on. This prevents any new
+scmd to be issued from blk queue to the host; eventually, all scmds on
+the host either complete normally, fail and get added to eh_cmd_q, or
+time out and get added to shost->eh_cmd_q.
+
+ If all scmds either complete or fail, the number of in-flight scmds
+becomes equal to the number of failed scmds - i.e. shost->host_busy ==
+shost->host_failed. This wakes up SCSI EH thread. So, once woken up,
+SCSI EH thread can expect that all in-flight commands have failed and
+are linked on shost->eh_cmd_q.
+
+ Note that this does not mean lower layers are quiescent. If a LLDD
+completed a scmd with error status, the LLDD and lower layers are
+assumed to forget about the scmd at that point. However, if a scmd
+has timed out, unless hostt->eh_timedout() made lower layers forget
+about the scmd, which currently no LLDD does, the command is still
+active as long as lower layers are concerned and completion could
+occur at any time. Of course, all such completions are ignored as the
+timer has already expired.
+
+ We'll talk about how SCSI EH takes actions to abort - make LLDD
+forget about - timed out scmds later.
+
+
+[2] How SCSI EH works
+
+ LLDD's can implement SCSI EH actions in one of the following two
+ways.
+
+ - Fine-grained EH callbacks
+ LLDD can implement fine-grained EH callbacks and let SCSI
+ midlayer drive error handling and call appropriate callbacks.
+ This will be dicussed further in [2-1].
+
+ - eh_strategy_handler() callback
+ This is one big callback which should perform whole error
+ handling. As such, it should do all choirs SCSI midlayer
+ performs during recovery. This will be discussed in [2-2].
+
+ Once recovery is complete, SCSI EH resumes normal operation by
+calling scsi_restart_operations(), which
+
+ 1. Checks if door locking is needed and locks door.
+
+ 2. Clears SHOST_RECOVERY shost_state bit
+
+ 3. Wakes up waiters on shost->host_wait. This occurs if someone
+ calls scsi_block_when_processing_errors() on the host.
+ (*QUESTION* why is it needed? All operations will be blocked
+ anyway after it reaches blk queue.)
+
+ 4. Kicks queues in all devices on the host in the asses
+
+
+[2-1] EH through fine-grained callbacks
+
+[2-1-1] Overview
+
+ If eh_strategy_handler() is not present, SCSI midlayer takes charge
+of driving error handling. EH's goals are two - make LLDD, host and
+device forget about timed out scmds and make them ready for new
+commands. A scmd is said to be recovered if the scmd is forgotten by
+lower layers and lower layers are ready to process or fail the scmd
+again.
+
+ To achieve these goals, EH performs recovery actions with increasing
+severity. Some actions are performed by issueing SCSI commands and
+others are performed by invoking one of the following fine-grained
+hostt EH callbacks. Callbacks may be omitted and omitted ones are
+considered to fail always.
+
+int (* eh_abort_handler)(struct scsi_cmnd *);
+int (* eh_device_reset_handler)(struct scsi_cmnd *);
+int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+int (* eh_host_reset_handler)(struct scsi_cmnd *);
+
+ Higher-severity actions are taken only when lower-severity actions
+cannot recover some of failed scmds. Also, note that failure of the
+highest-severity action means EH failure and results in offlining of
+all unrecovered devices.
+
+ During recovery, the following rules are followed
+
+ - Recovery actions are performed on failed scmds on the to do list,
+ eh_work_q. If a recovery action succeeds for a scmd, recovered
+ scmds are removed from eh_work_q.
+
+ Note that single recovery action on a scmd can recover multiple
+ scmds. e.g. resetting a device recovers all failed scmds on the
+ device.
+
+ - Higher severity actions are taken iff eh_work_q is not empty after
+ lower severity actions are complete.
+
+ - EH reuses failed scmds to issue commands for recovery. For
+ timed-out scmds, SCSI EH ensures that LLDD forgets about a scmd
+ before reusing it for EH commands.
+
+ When a scmd is recovered, the scmd is moved from eh_work_q to EH
+local eh_done_q using scsi_eh_finish_cmd(). After all scmds are
+recovered (eh_work_q is empty), scsi_eh_flush_done_q() is invoked to
+either retry or error-finish (notify upper layer of failure) recovered
+scmds.
+
+ scmds are retried iff its sdev is still online (not offlined during
+EH), REQ_FAILFAST is not set and ++scmd->retries is less than
+scmd->allowed.
+
+
+[2-1-2] Flow of scmds through EH
+
+ 1. Error completion / time out
+ ACTION: scsi_eh_scmd_add() is invoked for scmd
+ - set scmd->eh_eflags
+ - add scmd to shost->eh_cmd_q
+ - set SHOST_RECOVERY
+ - shost->host_failed++
+ LOCKING: shost->host_lock
+
+ 2. EH starts
+ ACTION: move all scmds to EH's local eh_work_q. shost->eh_cmd_q
+ is cleared.
+ LOCKING: shost->host_lock (not strictly necessary, just for
+ consistency)
+
+ 3. scmd recovered
+ ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
+ - shost->host_failed--
+ - clear scmd->eh_eflags
+ - scsi_setup_cmd_retry()
+ - move from local eh_work_q to local eh_done_q
+ LOCKING: none
+
+ 4. EH completes
+ ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
+ layer of failure.
+ - scmd is removed from eh_done_q and scmd->eh_entry is cleared
+ - if retry is necessary, scmd is requeued using
+ scsi_queue_insert()
+ - otherwise, scsi_finish_command() is invoked for scmd
+ LOCKING: queue or finish function performs appropriate locking
+
+
+[2-1-3] Flow of control
+
+ EH through fine-grained callbacks start from scsi_unjam_host().
+
+<<scsi_unjam_host>>
+
+ 1. Lock shost->host_lock, splice_init shost->eh_cmd_q into local
+ eh_work_q and unlock host_lock. Note that shost->eh_cmd_q is
+ cleared by this action.
+
+ 2. Invoke scsi_eh_get_sense.
+
+ <<scsi_eh_get_sense>>
+
+ This action is taken for each error-completed
+ (!SCSI_EH_CANCEL_CMD) commands without valid sense data. Most
+ SCSI transports/LLDDs automatically acquire sense data on
+ command failures (autosense). Autosense is recommended for
+ performance reasons and as sense information could get out of
+ sync inbetween occurrence of CHECK CONDITION and this action.
+
+ Note that if autosense is not supported, scmd->sense_buffer
+ contains invalid sense data when error-completing the scmd
+ with scsi_done(). scsi_decide_disposition() always returns
+ FAILED in such cases thus invoking SCSI EH. When the scmd
+ reaches here, sense data is acquired and
+ scsi_decide_disposition() is called again.
+
+ 1. Invoke scsi_request_sense() which issues REQUEST_SENSE
+ command. If fails, no action. Note that taking no action
+ causes higher-severity recovery to be taken for the scmd.
+
+ 2. Invoke scsi_decide_disposition() on the scmd
+
+ - SUCCESS
+ scmd->retries is set to scmd->allowed preventing
+ scsi_eh_flush_done_q() from retrying the scmd and
+ scsi_eh_finish_cmd() is invoked.
+
+ - NEEDS_RETRY
+ scsi_eh_finish_cmd() invoked
+
+ - otherwise
+ No action.
+
+ 3. If !list_empty(&eh_work_q), invoke scsi_eh_abort_cmds().
+
+ <<scsi_eh_abort_cmds>>
+
+ This action is taken for each timed out command.
+ hostt->eh_abort_handler() is invoked for each scmd. The
+ handler returns SUCCESS if it has succeeded to make LLDD and
+ all related hardware forget about the scmd.
+
+ If a timedout scmd is successfully aborted and the sdev is
+ either offline or ready, scsi_eh_finish_cmd() is invoked for
+ the scmd. Otherwise, the scmd is left in eh_work_q for
+ higher-severity actions.
+
+ Note that both offline and ready status mean that the sdev is
+ ready to process new scmds, where processing also implies
+ immediate failing; thus, if a sdev is in one of the two
+ states, no further recovery action is needed.
+
+ Device readiness is tested using scsi_eh_tur() which issues
+ TEST_UNIT_READY command. Note that the scmd must have been
+ aborted successfully before reusing it for TEST_UNIT_READY.
+
+ 4. If !list_empty(&eh_work_q), invoke scsi_eh_ready_devs()
+
+ <<scsi_eh_ready_devs>>
+
+ This function takes four increasingly more severe measures to
+ make failed sdevs ready for new commands.
+
+ 1. Invoke scsi_eh_stu()
+
+ <<scsi_eh_stu>>
+
+ For each sdev which has failed scmds with valid sense data
+ of which scsi_check_sense()'s verdict is FAILED,
+ START_STOP_UNIT command is issued w/ start=1. Note that
+ as we explicitly choose error-completed scmds, it is known
+ that lower layers have forgotten about the scmd and we can
+ reuse it for STU.
+
+ If STU succeeds and the sdev is either offline or ready,
+ all failed scmds on the sdev are EH-finished with
+ scsi_eh_finish_cmd().
+
+ *NOTE* If hostt->eh_abort_handler() isn't implemented or
+ failed, we may still have timed out scmds at this point
+ and STU doesn't make lower layers forget about those
+ scmds. Yet, this function EH-finish all scmds on the sdev
+ if STU succeeds leaving lower layers in an inconsistent
+ state. It seems that STU action should be taken only when
+ a sdev has no timed out scmd.
+
+ 2. If !list_empty(&eh_work_q), invoke scsi_eh_bus_device_reset().
+
+ <<scsi_eh_bus_device_reset>>
+
+ This action is very similar to scsi_eh_stu() except that,
+ instead of issuing STU, hostt->eh_device_reset_handler()
+ is used. Also, as we're not issuing SCSI commands and
+ resetting clears all scmds on the sdev, there is no need
+ to choose error-completed scmds.
+
+ 3. If !list_empty(&eh_work_q), invoke scsi_eh_bus_reset()
+
+ <<scsi_eh_bus_reset>>
+
+ hostt->eh_bus_reset_handler() is invoked for each channel
+ with failed scmds. If bus reset succeeds, all failed
+ scmds on all ready or offline sdevs on the channel are
+ EH-finished.
+
+ 4. If !list_empty(&eh_work_q), invoke scsi_eh_host_reset()
+
+ <<scsi_eh_host_reset>>
+
+ This is the last resort. hostt->eh_host_reset_handler()
+ is invoked. If host reset succeeds, all failed scmds on
+ all ready or offline sdevs on the host are EH-finished.
+
+ 5. If !list_empty(&eh_work_q), invoke scsi_eh_offline_sdevs()
+
+ <<scsi_eh_offline_sdevs>>
+
+ Take all sdevs which still have unrecovered scmds offline
+ and EH-finish the scmds.
+
+ 5. Invoke scsi_eh_flush_done_q().
+
+ <<scsi_eh_flush_done_q>>
+
+ At this point all scmds are recovered (or given up) and
+ put on eh_done_q by scsi_eh_finish_cmd(). This function
+ flushes eh_done_q by either retrying or notifying upper
+ layer of failure of the scmds.
+
+
+[2-2] EH through hostt->eh_strategy_handler()
+
+ hostt->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,
+it should perform SCSI EH maintenance choirs to maintain integrity of
+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
+
+ The following conditions are true on entry to the handler.
+
+ - Each failed scmd's eh_flags field is set appropriately.
+
+ - Each failed scmd is linked on scmd->eh_cmd_q by scmd->eh_entry.
+
+ - SHOST_RECOVERY is set.
+
+ - shost->host_failed == shost->host_busy
+
+
+[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+
+ The following conditions must be true on exit from the handler.
+
+ - shost->host_failed is zero.
+
+ - Each scmd's eh_eflags field is cleared.
+
+ - Each scmd is in such a state that scsi_setup_cmd_retry() on the
+ scmd doesn't make any difference.
+
+ - shost->eh_cmd_q is cleared.
+
+ - Each scmd->eh_entry is cleared.
+
+ - Either scsi_queue_insert() or scsi_finish_command() is called on
+ each scmd. Note that the handler is free to use scmd->retries and
+ ->allowed to limit the number of retries.
+
+
+[2-2-3] Things to consider
+
+ - Know that timed out scmds are still active on lower layers. Make
+ lower layers forget about them before doing anything else with
+ those scmds.
+
+ - For consistency, when accessing/modifying shost data structure,
+ grab shost->host_lock.
+
+ - On completion, each failed sdev must have forgotten about all
+ active scmds.
+
+ - On completion, each failed sdev must be ready for new commands or
+ offline.
+
+
+--
+Tejun Heo
+htejun@gmail.com
+11th September 2005
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 7536823c0cb1..44df89c9c049 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -373,13 +373,11 @@ Summary:
scsi_activate_tcq - turn on tag command queueing
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and SCSI bus scan.
- scsi_add_timer - (re-)start timer on a SCSI command.
scsi_adjust_queue_depth - change the queue depth on a SCSI device
scsi_assign_lock - replace default host_lock with given lock
scsi_bios_ptable - return copy of block device's partition table
scsi_block_requests - prevent further commands being queued to given host
scsi_deactivate_tcq - turn off tag command queueing
- scsi_delete_timer - cancel timer on a SCSI command.
scsi_host_alloc - return a new scsi_host instance whose refcount==1
scsi_host_get - increments Scsi_Host instance's refcount
scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
@@ -458,27 +456,6 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
/**
- * scsi_add_timer - (re-)start timer on a SCSI command.
- * @scmd: pointer to scsi command instance
- * @timeout: duration of timeout in "jiffies"
- * @complete: pointer to function to call if timeout expires
- *
- * Returns nothing
- *
- * Might block: no
- *
- * Notes: Each scsi command has its own timer, and as it is added
- * to the queue, we set up the timer. When the command completes,
- * we cancel the timer. An LLD can use this function to change
- * the existing timeout value.
- *
- * Defined in: drivers/scsi/scsi_error.c
- **/
-void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
- void (*complete)(struct scsi_cmnd *))
-
-
-/**
* scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
* @sdev: pointer to SCSI device to change queue depth on
* @tagged: 0 - no tagged queuing
@@ -566,24 +543,6 @@ void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
/**
- * scsi_delete_timer - cancel timer on a SCSI command.
- * @scmd: pointer to scsi command instance
- *
- * Returns 1 if able to cancel timer else 0 (i.e. too late or already
- * cancelled).
- *
- * Might block: no [may in the future if it invokes del_timer_sync()]
- *
- * Notes: All commands issued by upper levels already have a timeout
- * associated with them. An LLD can use this function to cancel the
- * timer.
- *
- * Defined in: drivers/scsi/scsi_error.c
- **/
-int scsi_delete_timer(struct scsi_cmnd *scmd)
-
-
-/**
* scsi_host_alloc - create a scsi host adapter instance and perform basic
* initialization.
* @sht: pointer to scsi host template
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index ac7eabbf662a..87856d3cfb67 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -111,24 +111,17 @@ hardware.
Interrupts: locally disabled.
This call must not sleep
- stop_tx(port,tty_stop)
+ stop_tx(port)
Stop transmitting characters. This might be due to the CTS
line becoming inactive or the tty layer indicating we want
- to stop transmission.
-
- tty_stop: 1 if this call is due to the TTY layer issuing a
- TTY stop to the driver (equiv to rs_stop).
+ to stop transmission due to an XOFF character.
Locking: port->lock taken.
Interrupts: locally disabled.
This call must not sleep
- start_tx(port,tty_start)
- start transmitting characters. (incidentally, nonempty will
- always be nonzero, and shouldn't be used - it will be dropped).
-
- tty_start: 1 if this call was due to the TTY layer issuing
- a TTY start to the driver (equiv to rs_start)
+ start_tx(port)
+ start transmitting characters.
Locking: port->lock taken.
Interrupts: locally disabled.
diff --git a/Documentation/sonypi.txt b/Documentation/sonypi.txt
index 0f3b2405d09e..c1237a925505 100644
--- a/Documentation/sonypi.txt
+++ b/Documentation/sonypi.txt
@@ -99,6 +99,7 @@ statically linked into the kernel). Those options are:
SONYPI_MEYE_MASK 0x0400
SONYPI_MEMORYSTICK_MASK 0x0800
SONYPI_BATTERY_MASK 0x1000
+ SONYPI_WIRELESS_MASK 0x2000
useinput: if set (which is the default) two input devices are
created, one which interprets the jogdial events as
@@ -137,6 +138,15 @@ Bugs:
speed handling etc). Use ACPI instead of APM if it works on your
laptop.
+ - sonypi lacks the ability to distinguish between certain key
+ events on some models.
+
+ - some models with the nvidia card (geforce go 6200 tc) uses a
+ different way to adjust the backlighting of the screen. There
+ is a userspace utility to adjust the brightness on those models,
+ which can be downloaded from
+ http://www.acc.umu.se/~erikw/program/smartdimmer-0.1.tar.bz2
+
- since all development was done by reverse engineering, there is
_absolutely no guarantee_ that this driver will not crash your
laptop. Permanently.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index a18ecb92b356..13cba955cb5a 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -75,7 +75,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
adsp_map - PCM device number maps assigned to the 2st OSS device.
- Default: 1
nonblock_open
- - Don't block opening busy PCM devices.
+ - Don't block opening busy PCM devices. Default: 1
For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped
@@ -132,6 +132,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_irq - IRQ # for MPU-401 UART (PnP setup)
dma1 - first DMA # for AD1816A chip (PnP setup)
dma2 - second DMA # for AD1816A chip (PnP setup)
+ clockfreq - Clock frequency for AD1816A chip (default = 0, 33000Hz)
Module supports up to 8 cards, autoprobe and PnP.
@@ -147,6 +148,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports up to 8 cards. This module does not support autoprobe
thus main port must be specified!!! Other ports are optional.
+ Module snd-ad1889
+ -----------------
+
+ Module for Analog Devices AD1889 chips.
+
+ ac97_quirk - AC'97 workaround for strange hardware
+ See the description of intel8x0 module for details.
+
+ This module supports up to 8 cards.
+
Module snd-ali5451
------------------
@@ -188,15 +199,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-atiixp
-----------------
- Module for ATI IXP 150/200/250 AC97 controllers.
+ Module for ATI IXP 150/200/250/400 AC97 controllers.
- ac97_clock - AC'97 clock (defalut = 48000)
+ ac97_clock - AC'97 clock (default = 48000)
ac97_quirk - AC'97 workaround for strange hardware
- See the description of intel8x0 module for details.
+ See "AC97 Quirk Option" section below.
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
This module supports up to 8 cards and autoprobe.
+ ATI IXP has two different methods to control SPDIF output. One is
+ over AC-link and another is over the "direct" SPDIF output. The
+ implementation depends on the motherboard, and you'll need to
+ choose the correct one via spdif_aclink module option.
+
Module snd-atiixp-modem
-----------------------
@@ -229,7 +245,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The hardware EQ hardware and SPDIF is only present in the Vortex2 and
Advantage.
- Note: Some ALSA mixer applicactions don't handle the SPDIF samplerate
+ Note: Some ALSA mixer applications don't handle the SPDIF sample rate
control correctly. If you have problems regarding this, try
another ALSA compliant mixer (alsamixer works).
@@ -301,7 +317,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default)
fm_port - 0x388 (default), 0 = disable (default)
- soft_ac3 - Sofware-conversion of raw SPDIF packets (model 033 only)
+ soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only)
(default = 1)
joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
@@ -383,7 +399,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
CS4624/CS4630/CS4280 PCI chips.
- external_amp - Force to enable external amplifer.
+ external_amp - Force to enable external amplifier.
thinkpad - Force to enable Thinkpad's CLKRUN control.
mmap_valid - Support OSS mmap mode (default = 0).
@@ -619,7 +635,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
VIA VT8251/VT8237A
model - force the model name
- position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
+ position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
Module supports up to 8 cards.
@@ -655,6 +671,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
allout 5-jack in back, 2-jack in front, SPDIF out
auto auto-config reading BIOS (default)
+ If the default configuration doesn't work and one of the above
+ matches with your device, report it together with the PCI
+ subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
+ ML (see the section "Links and Addresses").
+
Note 2: If you get click noises on output, try the module option
position_fix=1 or 2. position_fix=1 will use the SD_LPIB
register value without FIFO size correction as the current
@@ -782,20 +803,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ac97_clock - AC'97 codec clock base (0 = auto-detect)
ac97_quirk - AC'97 workaround for strange hardware
- The following strings are accepted:
- default = don't override the default setting
- disable = disable the quirk
- hp_only = use headphone control as master
- swap_hp = swap headphone and master controls
- swap_surround = swap master and surround controls
- ad_sharing = for AD1985, turn on OMS bit and use headphone
- alc_jack = for ALC65x, turn on the jack sense mode
- inv_eapd = inverted EAPD implementation
- mute_led = bind EAPD bit for turning on/off mute LED
- For backward compatibility, the corresponding integer
- value -1, 0, ... are accepted, too.
+ See "AC97 Quirk Option" section below.
buggy_irq - Enable workaround for buggy interrupts on some
- motherboards (default off)
+ motherboards (default yes on nForce chips,
+ otherwise off)
+ buggy_semaphore - Enable workaround for hardwares with buggy
+ semaphores (e.g. on some ASUS laptops)
+ (default off)
Module supports autoprobe and multiple bus-master chips (max 8).
@@ -807,13 +821,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
motherboard has these devices, use the ns558 or snd-mpu401
modules, respectively.
- The ac97_quirk option is used to enable/override the workaround
- for specific devices. Some hardware have swapped output pins
- between Master and Headphone, or Surround. The driver provides
- the auto-detection of known problematic devices, but some might
- be unknown or wrongly detected. In such a case, pass the proper
- value with this option.
-
The power-management is supported.
Module snd-intel8x0m
@@ -965,7 +972,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
with machines with other (most likely CS423x or OPL3SAx) chips,
even though the device is detected in lspci. In such a case, try
other drivers, e.g. snd-cs4232 or snd-opl3sa2. Some has ISA-PnP
- but some doesn't have ISA PnP. You'll need to speicfy isapnp=0
+ but some doesn't have ISA PnP. You'll need to specify isapnp=0
and proper hardware parameters in the case without ISA PnP.
Note: some laptops need a workaround for AC97 RESET. For the
@@ -1301,7 +1308,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
channels
[VIA8233/C, 8235, 8237 only]
ac97_quirk - AC'97 workaround for strange hardware
- See the description of intel8x0 module for details.
+ See "AC97 Quirk Option" section below.
Module supports autoprobe and multiple bus-master chips (max 8).
@@ -1326,16 +1333,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
"lspci -nv").
If dxs_support=5 does not work, try dxs_support=4; if it
doesn't work too, try dxs_support=1. (dxs_support=1 is
- usually for old motherboards. The correct implementated
+ usually for old motherboards. The correct implemented
board should work with 4 or 5.) If it still doesn't
work and the default setting is ok, dxs_support=3 is the
right choice. If the default setting doesn't work at all,
try dxs_support=2 to disable the DXS channels.
In any cases, please let us know the result and the
- subsystem vendor/device ids.
+ subsystem vendor/device ids. See "Links and Addresses"
+ below.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
- additonally. The mpu_port option is for VIA686 chips only.
+ additionally. The mpu_port option is for VIA686 chips only.
Module snd-via82xx-modem
------------------------
@@ -1397,8 +1405,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports up to 8 cards. The module is compiled only when
PCMCIA is supported on kernel.
- To activate the driver via the card manager, you'll need to set
- up /etc/pcmcia/vxpocket.conf. See the sound/pcmcia/vx/vxpocket.c.
+ With the older 2.6.x kernel, to activate the driver via the card
+ manager, you'll need to set up /etc/pcmcia/vxpocket.conf. See the
+ sound/pcmcia/vx/vxpocket.c. 2.6.13 or later kernel requires no
+ longer require a config file.
When the driver is compiled as a module and the hotplug firmware
is supported, the firmware data is loaded via hotplug automatically.
@@ -1410,6 +1420,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: the driver is build only when CONFIG_ISA is set.
+ Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
+ ALSA 1.0.10.
+
Module snd-ymfpci
-----------------
@@ -1435,6 +1448,37 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: the driver is build only when CONFIG_ISA is set.
+AC97 Quirk Option
+=================
+
+The ac97_quirk option is used to enable/override the workaround for
+specific devices on drivers for on-board AC'97 controllers like
+snd-intel8x0. Some hardware have swapped output pins between Master
+and Headphone, or Surround (thanks to confusion of AC'97
+specifications from version to version :-)
+
+The driver provides the auto-detection of known problematic devices,
+but some might be unknown or wrongly detected. In such a case, pass
+the proper value with this option.
+
+The following strings are accepted:
+ - default Don't override the default setting
+ - disable Disable the quirk
+ - hp_only Bind Master and Headphone controls as a single control
+ - swap_hp Swap headphone and master controls
+ - swap_surround Swap master and surround controls
+ - ad_sharing For AD1985, turn on OMS bit and use headphone
+ - alc_jack For ALC65x, turn on the jack sense mode
+ - inv_eapd Inverted EAPD implementation
+ - mute_led Bind EAPD bit for turning on/off mute LED
+
+For backward compatibility, the corresponding integer value -1, 0,
+... are accepted, too.
+
+For example, if "Master" volume control has no effect on your device
+but only "Headphone" does, pass ac97_quirk=hp_only module option.
+
+
Configuring Non-ISAPNP Cards
============================
@@ -1458,7 +1502,7 @@ devices where %i is sound card number from zero to seven.
To auto-load an ALSA driver for OSS services, define the string
'sound-slot-%i' where %i means the slot number for OSS, which
corresponds to the card index of ALSA. Usually, define this
-as the the same card module.
+as the same card module.
An example configuration for a single emu10k1 card is like below:
----- /etc/modprobe.conf
@@ -1552,6 +1596,8 @@ Proc interfaces (/proc/asound)
- whole-frag write only whole fragments (optimization affecting
playback only)
- no-silence do not fill silence ahead to avoid clicks
+ - buggy-ptr Returns the whitespace blocks in GETOPTR ioctl
+ instead of filled blocks
Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
@@ -1588,9 +1634,14 @@ commands to the snd-page-alloc driver:
use.
-Links
-=====
+Links and Addresses
+===================
ALSA project homepage
http://www.alsa-project.org
+ ALSA Bug Tracking System
+ https://bugtrack.alsa-project.org/bugs/
+
+ ALSA Developers ML
+ mailto:alsa-devel@lists.sourceforge.net
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index db0b7d2dc477..24e85520890b 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -447,7 +447,7 @@
....
/* allocate a chip-specific data with zero filled */
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -949,7 +949,7 @@
After allocating a card instance via
<function>snd_card_new()</function> (with
<constant>NULL</constant> on the 4th arg), call
- <function>kcalloc()</function>.
+ <function>kzalloc()</function>.
<informalexample>
<programlisting>
@@ -958,7 +958,7 @@
mychip_t *chip;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
.....
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
]]>
</programlisting>
</informalexample>
@@ -1136,7 +1136,7 @@
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1292,7 +1292,7 @@
need to initialize this number as -1 before actual allocation,
since irq 0 is valid. The port address and its resource pointer
can be initialized as null by
- <function>kcalloc()</function> automatically, so you
+ <function>kzalloc()</function> automatically, so you
don't have to take care of resetting them.
</para>
@@ -3422,10 +3422,17 @@ struct _snd_pcm_runtime {
<para>
The <structfield>iface</structfield> field specifies the type of
- the control,
- <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>. There are
- <constant>MIXER</constant>, <constant>PCM</constant>,
- <constant>CARD</constant>, etc.
+ the control, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
+ is usually <constant>MIXER</constant>.
+ Use <constant>CARD</constant> for global controls that are not
+ logically part of the mixer.
+ If the control is closely associated with some specific device on
+ the sound card, use <constant>HWDEP</constant>,
+ <constant>PCM</constant>, <constant>RAWMIDI</constant>,
+ <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
+ specify the device number with the
+ <structfield>device</structfield> and
+ <structfield>subdevice</structfield> fields.
</para>
<para>
diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt
index f97841478459..5df44dc894e5 100644
--- a/Documentation/sparse.txt
+++ b/Documentation/sparse.txt
@@ -57,7 +57,7 @@ With BK, you can just get it from
and DaveJ has tar-balls at
- http://www.codemonkey.org.uk/projects/bitkeeper/sparse/
+ http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
Once you have it, just do
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 136d817c01ba..baf17b381588 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -171,7 +171,7 @@ the header 'include/linux/sysrq.h', this will define everything else you need.
Next, you must create a sysrq_key_op struct, and populate it with A) the key
handler function you will use, B) a help_msg string, that will print when SysRQ
prints help, and C) an action_msg string, that will print right before your
-handler is called. Your handler must conform to the protoype in 'sysrq.h'.
+handler is called. Your handler must conform to the prototype in 'sysrq.h'.
After the sysrq_key_op is created, you can call the macro
register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
diff --git a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt
index 0c7b654fec99..544430e39980 100644
--- a/Documentation/uml/UserModeLinux-HOWTO.txt
+++ b/Documentation/uml/UserModeLinux-HOWTO.txt
@@ -2176,7 +2176,7 @@
If you want to access files on the host machine from inside UML, you
can treat it as a separate machine and either nfs mount directories
from the host or copy files into the virtual machine with scp or rcp.
- However, since UML is running on the the host, it can access those
+ However, since UML is running on the host, it can access those
files just like any other process and make them available inside the
virtual machine without needing to use the network.
diff --git a/Documentation/usb/gadget_serial.txt b/Documentation/usb/gadget_serial.txt
index a938c3dd13d6..815f5c2301ff 100644
--- a/Documentation/usb/gadget_serial.txt
+++ b/Documentation/usb/gadget_serial.txt
@@ -20,7 +20,7 @@ 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 document and the the gadget serial driver itself are
+This document and the gadget serial driver itself are
Copyright (C) 2004 by Al Borchers (alborchers@steinerpoint.com).
If you have questions, problems, or suggestions for this driver
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index 729c72d34c89..f86550fe38ee 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -20,7 +20,7 @@ the /proc/bus/usb/BBB/DDD files.
to /etc/fstab. This will mount usbfs at each reboot.
You can then issue `cat /proc/bus/usb/devices` to extract
- USB device information, and user mode drivers can use usbfs
+ USB device information, and user mode drivers can use usbfs
to interact with USB devices.
There are a number of mount options supported by usbfs.
@@ -32,7 +32,7 @@ the /proc/bus/usb/BBB/DDD files.
still see references to the older "usbdevfs" name.
For more information on mounting the usbfs file system, see the
-"USB Device Filesystem" section of the USB Guide. The latest copy
+"USB Device Filesystem" section of the USB Guide. The latest copy
of the USB Guide can be found at http://www.linux-usb.org/
@@ -133,7 +133,7 @@ B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
are the only transfers that reserve bandwidth. Control and bulk
transfers use all other bandwidth, including reserved bandwidth that
is not used for transfers (such as for short packets).
-
+
The percentage is how much of the "reserved" bandwidth is scheduled by
those transfers. For a low or full speed bus (loosely, "USB 1.1"),
90% of the bus bandwidth is reserved. For a high speed bus (loosely,
@@ -197,7 +197,7 @@ C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
| | |__NumberOfInterfaces
| |__ "*" indicates the active configuration (others are " ")
|__Config info tag
-
+
USB devices may have multiple configurations, each of which act
rather differently. For example, a bus-powered configuration
might be much less capable than one that is self-powered. Only
@@ -228,7 +228,7 @@ I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
For example, default settings may not use more than a small
amount of periodic bandwidth. To use significant fractions
of bus bandwidth, drivers must select a non-default altsetting.
-
+
Only one setting for an interface may be active at a time, and
only one driver may bind to an interface at a time. Most devices
have only one alternate setting per interface.
@@ -297,18 +297,21 @@ S: SerialNumber=dce0
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
+
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0451 ProdID=1446 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
+
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b4 ProdID=0001 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
+
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0565 ProdID=0001 Rev= 1.08
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index 62a12a08e2ac..ec785f9f15a3 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -126,10 +126,12 @@ card=124 - AverMedia AverTV DVB-T 761
card=125 - MATRIX Vision Sigma-SQ
card=126 - MATRIX Vision Sigma-SLC
card=127 - APAC Viewcomp 878(AMAX)
-card=128 - DVICO FusionHDTV DVB-T Lite
+card=128 - DViCO FusionHDTV DVB-T Lite
card=129 - V-Gear MyVCD
card=130 - Super TV Tuner
card=131 - Tibet Systems 'Progress DVR' CS16
card=132 - Kodicom 4400R (master)
card=133 - Kodicom 4400R (slave)
card=134 - Adlink RTV24
+card=135 - DViCO FusionHDTV 5 Lite
+card=136 - Acorp Y878F
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 1b5a3a9ffbe2..dc57225f39be 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -62,3 +62,6 @@
61 -> Philips TOUGH DVB-T reference design [1131:2004]
62 -> Compro VideoMate TV Gold+II
63 -> Kworld Xpert TV PVR7134
+ 64 -> FlyTV mini Asus Digimatrix [1043:0210,1043:0210]
+ 65 -> V-Stream Studio TV Terminator
+ 66 -> Yuan TUN-900 (saa7135)
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index f3302e1b1b9c..f5876be658a6 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -64,3 +64,4 @@ tuner=62 - Philips TEA5767HN FM Radio
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
tuner=64 - LG TDVS-H062F/TUA6034
tuner=65 - Ymec TVF66T5-B/DFF
+tuner=66 - LG NTSC (TALN mini series)
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 01425c21986b..52c94bd7dca1 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -222,7 +222,7 @@ was introduced in 1991, is used in the DC10 old
can generate: PAL , NTSC , SECAM
The adv717x, should be able to produce PAL N. But you find nothing PAL N
-specific in the the registers. Seem that you have to reuse a other standard
+specific in the registers. Seem that you have to reuse a other standard
to generate PAL N, maybe it would work if you use the PAL M settings.
==========================
diff --git a/Documentation/vm/locking b/Documentation/vm/locking
index c3ef09ae3bb1..f366fa956179 100644
--- a/Documentation/vm/locking
+++ b/Documentation/vm/locking
@@ -83,19 +83,18 @@ single address space optimization, so that the zap_page_range (from
vmtruncate) does not lose sending ipi's to cloned threads that might
be spawned underneath it and go to user mode to drag in pte's into tlbs.
-swap_list_lock/swap_device_lock
--------------------------------
+swap_lock
+--------------
The swap devices are chained in priority order from the "swap_list" header.
The "swap_list" is used for the round-robin swaphandle allocation strategy.
The #free swaphandles is maintained in "nr_swap_pages". These two together
-are protected by the swap_list_lock.
+are protected by the swap_lock.
-The swap_device_lock, which is per swap device, protects the reference
-counts on the corresponding swaphandles, maintained in the "swap_map"
-array, and the "highest_bit" and "lowest_bit" fields.
+The swap_lock also protects all the device reference counts on the
+corresponding swaphandles, maintained in the "swap_map" array, and the
+"highest_bit" and "lowest_bit" fields.
-Both of these are spinlocks, and are never acquired from intr level. The
-locking hierarchy is swap_list_lock -> swap_device_lock.
+The swap_lock is a spinlock, and is never acquired from intr level.
To prevent races between swap space deletion or async readahead swapins
deciding whether a swap handle is being used, ie worthy of being read in
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index 28388aa700c6..c5beb548cfc4 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -228,6 +228,26 @@ advantechwdt.c -- Advantech Single Board Computer
The GETSTATUS call returns if the device is open or not.
[FIXME -- silliness again?]
+booke_wdt.c -- PowerPC BookE Watchdog Timer
+
+ Timeout default varies according to frequency, supports
+ SETTIMEOUT
+
+ Watchdog can not be turned off, CONFIG_WATCHDOG_NOWAYOUT
+ does not make sense
+
+ GETSUPPORT returns the watchdog_info struct, and
+ GETSTATUS returns the supported options. GETBOOTSTATUS
+ returns a 1 if the last reset was caused by the
+ watchdog and a 0 otherwise. This watchdog can not be
+ disabled once it has been started. The wdt_period kernel
+ parameter selects which bit of the time base changing
+ from 0->1 will trigger the watchdog exception. Changing
+ the timeout from the ioctl calls will change the
+ wdt_period as defined above. Finally if you would like to
+ replace the default Watchdog Handler you can implement the
+ WatchdogHandler() function in your own code.
+
eurotechwdt.c -- Eurotech CPU-1220/1410
The timeout can be set using the SETTIMEOUT ioctl and defaults
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 678e8f192db2..ffe1c062088b 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -11,6 +11,11 @@ Machine check
If your BIOS doesn't do that it's a good idea to enable though
to make sure you log even machine check events that result
in a reboot.
+ mce=tolerancelevel (number)
+ 0: always panic, 1: panic if deadlock possible,
+ 2: try to avoid panic, 3: never panic or exit (for testing)
+ default is 1
+ Can be also set using sysfs which is preferable.
nomce (for compatibility with i386): same as mce=off
diff --git a/Kbuild b/Kbuild
new file mode 100644
index 000000000000..79003918f37f
--- /dev/null
+++ b/Kbuild
@@ -0,0 +1,49 @@
+#
+# Kbuild for top-level directory of the kernel
+# This file takes care of the following:
+# 1) Generate asm-offsets.h
+
+#####
+# 1) Generate asm-offsets.h
+#
+
+offsets-file := include/asm-$(ARCH)/asm-offsets.h
+
+always := $(offsets-file)
+targets := $(offsets-file)
+targets += arch/$(ARCH)/kernel/asm-offsets.s
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+ "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
+endef
+# Override default regexp for specific architectures
+sed-$(CONFIG_MIPS) := "/^@@@/s///p"
+
+quiet_cmd_offsets = GEN $@
+define cmd_offsets
+ mkdir -p $(dir $@); \
+ cat $< | \
+ (set -e; \
+ echo "#ifndef __ASM_OFFSETS_H__"; \
+ echo "#define __ASM_OFFSETS_H__"; \
+ echo "/*"; \
+ echo " * DO NOT MODIFY."; \
+ echo " *"; \
+ echo " * This file was generated by $(srctree)/Kbuild"; \
+ echo " *"; \
+ echo " */"; \
+ echo ""; \
+ sed -ne $(sed-y); \
+ echo ""; \
+ echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+arch/$(ARCH)/kernel/asm-offsets.s: arch/$(ARCH)/kernel/asm-offsets.c FORCE
+ $(Q)mkdir -p $(dir $@)
+ $(call if_changed_dep,cc_s_c)
+
+$(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
+ $(call cmd,offsets)
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 1c5a8a5e6504..d1e0eb46d201 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -116,6 +116,12 @@ M: ajk@iehk.rwth-aachen.de
L: linux-hams@vger.kernel.org
S: Maintained
+YEALINK PHONE DRIVER
+P: Henk Vergonet
+M: Henk.Vergonet@gmail.com
+L: usbb2k-api-dev@nongnu.org
+S: Maintained
+
8139CP 10/100 FAST ETHERNET DRIVER
P: Jeff Garzik
M: jgarzik@pobox.com
@@ -202,13 +208,6 @@ P: Colin Leroy
M: colin@colino.net
S: Maintained
-ADVANSYS SCSI DRIVER
-P: Bob Frey
-M: linux@advansys.com
-W: http://www.advansys.com/linux.html
-L: linux-scsi@vger.kernel.org
-S: Maintained
-
AEDSP16 DRIVER
P: Riccardo Facchetti
M: fizban@tin.it
@@ -630,6 +629,12 @@ M: rmk@arm.linux.org.uk
W: http://www.arm.linux.org.uk/
S: Maintained
+CYBLAFB FRAMEBUFFER DRIVER
+P: Knut Petersen
+M: Knut_Petersen@t-online.de
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
+
CYCLADES 2X SYNC CARD DRIVER
P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
@@ -699,6 +704,11 @@ M: dz@debian.org
W: http://www.debian.org/~dz/i8k/
S: Maintained
+DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
+P: Doug Warzecha
+M: Douglas_Warzecha@dell.com
+S: Maintained
+
DEVICE-MAPPER
P: Alasdair Kergon
L: dm-devel@redhat.com
@@ -827,6 +837,13 @@ L: emu10k1-devel@lists.sourceforge.net
W: http://sourceforge.net/projects/emu10k1/
S: Maintained
+EMULEX LPFC FC SCSI DRIVER
+P: James Smart
+M: james.smart@emulex.com
+L: linux-scsi@vger.kernel.org
+W: http://sourceforge.net/projects/lpfcxxxx
+S: Supported
+
EPSON 1355 FRAMEBUFFER DRIVER
P: Christopher Hoover
M: ch@murgatroid.com, ch@hpl.hp.com
@@ -882,7 +899,7 @@ S: Maintained
FILESYSTEMS (VFS and infrastructure)
P: Alexander Viro
-M: viro@parcelfarce.linux.theplanet.co.uk
+M: viro@zeniv.linux.org.uk
S: Maintained
FIRMWARE LOADER (request_firmware)
@@ -917,6 +934,13 @@ L: linux-tape@vger.kernel.org
W: http://sourceforge.net/projects/ftape
S: Orphan
+FUSE: FILESYSTEM IN USERSPACE
+P: Miklos Szeredi
+M: miklos@szeredi.hu
+L: fuse-devel@lists.sourceforge.net
+W: http://fuse.sourceforge.net/
+S: Maintained
+
FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
P: Rik Faith
M: faith@cs.unc.edu
@@ -936,6 +960,20 @@ M: khc@pm.waw.pl
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
S: Maintained
+HARDWARE MONITORING
+P: Jean Delvare
+M: khali@linux-fr.org
+L: lm-sensors@lm-sensors.org
+W: http://www.lm-sensors.nu/
+S: Maintained
+
+HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
+P: Robert Love
+M: rlove@rlove.org
+M: linux-kernel@vger.kernel.org
+W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
+S: Maintained
+
HARMONY SOUND DRIVER
P: Kyle McMartin
M: kyle@parisc-linux.org
@@ -994,6 +1032,13 @@ M: mike.miller@hp.com
L: iss_storagedev@hp.com
S: Supported
+HOST AP DRIVER
+P: Jouni Malinen
+M: jkmaline@cc.hut.fi
+L: hostap@shmoo.com
+W: http://hostap.epitest.fi/
+S: Maintained
+
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
P: Jaroslav Kysela
M: perex@suse.cz
@@ -1010,7 +1055,7 @@ P: William Irwin
M: wli@holomorphy.com
S: Maintained
-I2C AND SENSORS DRIVERS
+I2C SUBSYSTEM
P: Greg Kroah-Hartman
M: greg@kroah.com
P: Jean Delvare
@@ -1797,13 +1842,6 @@ M: hch@infradead.org
L: linux-abi-devel@lists.sourceforge.net
S: Maintained
-PCI ID DATABASE
-P: Martin Mares
-M: mj@ucw.cz
-L: pciids-devel@lists.sourceforge.net
-W: http://pciids.sourceforge.net/
-S: Maintained
-
PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES)
P: Thomas Sailer
M: sailer@ife.ee.ethz.ch
@@ -1956,7 +1994,6 @@ S: Supported
ROCKETPORT DRIVER
P: Comtrol Corp.
-M: support@comtrol.com
W: http://www.comtrol.com
S: Maintained
@@ -2095,6 +2132,12 @@ M: support@simtec.co.uk
W: http://www.simtec.co.uk/products/EB2410ITX/
S: Supported
+SIS 190 ETHERNET DRIVER
+P: Francois Romieu
+M: romieu@fr.zoreil.com
+L: netdev@vger.kernel.org
+S: Maintained
+
SIS 5513 IDE CONTROLLER DRIVER
P: Lionel Bouton
M: Lionel.Bouton@inet6.fr
@@ -2640,11 +2683,6 @@ S: Maintained
UCLINUX (AND M68KNOMMU)
P: Greg Ungerer
M: gerg@uclinux.org
-M: gerg@snapgear.com
-P: David McCullough
-M: davidm@snapgear.com
-P: D. Jeff Dionne (created first uClinux port)
-M: jeff@uclinux.org
W: http://www.uclinux.org/
L: uclinux-dev@uclinux.org (subscribers-only)
S: Maintained
@@ -2669,6 +2707,17 @@ L: rio500-users@lists.sourceforge.net
W: http://rio500.sourceforge.net
S: Maintained
+V9FS FILE SYSTEM
+P: Eric Van Hensbergen
+M: ericvh@gmail.com
+P: Ron Minnich
+M: rminnich@lanl.gov
+P: Latchesar Ionkov
+M: lucho@ionkov.net
+L: v9fs-developer@lists.sourceforge.net
+W: http://v9fs.sf.net
+S: Maintained
+
VIDEO FOR LINUX
P: Mauro Carvalho Chehab
M: mchehab@brturbo.com.br
diff --git a/Makefile b/Makefile
index 300f61f6f6a2..4e0d7c68d223 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 13
-EXTRAVERSION =-rc7
-NAME=Woozy Numbat
+SUBLEVEL = 14
+EXTRAVERSION =-rc1
+NAME=Affluent Albatross
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -109,10 +109,9 @@ $(if $(KBUILD_OUTPUT),, \
.PHONY: $(MAKECMDGOALS)
$(filter-out _all,$(MAKECMDGOALS)) _all:
- $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
- KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
- KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \
- -f $(CURDIR)/Makefile $@
+ $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
+ KBUILD_SRC=$(CURDIR) \
+ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
# Leave processing to above invocation of make
skip-makefile := 1
@@ -233,7 +232,7 @@ ifeq ($(MAKECMDGOALS),)
KBUILD_MODULES := 1
endif
-export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
+export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output
@@ -309,6 +308,9 @@ cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
+# We need some generic definitions
+include $(srctree)/scripts/Kbuild.include
+
# For maximum performance (+ possibly random breakage, uncomment
# the following)
@@ -332,7 +334,7 @@ KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse
-CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
+CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ $(CF)
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
@@ -348,7 +350,7 @@ LINUXINCLUDE := -Iinclude \
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
-CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
+CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-ffreestanding
AFLAGS := -D__ASSEMBLY__
@@ -367,15 +369,10 @@ export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# even be read-only.
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
-# The temporary file to save gcc -MD generated dependencies must not
-# contain a comma
-comma := ,
-depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-
# Files to ignore in find ... statements
-RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc \) -prune -o
-RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc
+RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
+RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
# ===========================================================================
# Rules shared between *config targets and build targets
@@ -385,6 +382,9 @@ RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CV
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
+# To avoid any implicit rule to kick in, define an empty command.
+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
@@ -447,9 +447,8 @@ ifeq ($(config-targets),1)
include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
-config: scripts_basic outputmakefile FORCE
- $(Q)$(MAKE) $(build)=scripts/kconfig $@
-%config: scripts_basic outputmakefile FORCE
+config %config: scripts_basic outputmakefile FORCE
+ $(Q)mkdir -p include/linux
$(Q)$(MAKE) $(build)=scripts/kconfig $@
else
@@ -492,6 +491,7 @@ include .config
# If .config is newer than include/linux/autoconf.h, someone tinkered
# with it and forgot to run make oldconfig
include/linux/autoconf.h: .config
+ $(Q)mkdir -p include/linux
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
# Dummy target needed, because used as prerequisite
@@ -551,6 +551,26 @@ export KBUILD_IMAGE ?= vmlinux
# images. Default is /boot, but you can set it to other values
export INSTALL_PATH ?= /boot
+# If CONFIG_LOCALVERSION_AUTO is set, we automatically perform some tests
+# and try to determine if the current source tree is a release tree, of any sort,
+# or if is a pure development tree.
+#
+# A 'release tree' is any tree with a git TAG associated
+# with it. The primary goal of this is to make it safe for a native
+# git/CVS/SVN user to build a release tree (i.e, 2.6.9) and also to
+# continue developing against the current Linus tree, without having the Linus
+# tree overwrite the 2.6.9 tree when installed.
+#
+# Currently, only git is supported.
+# Other SCMs can edit scripts/setlocalversion and add the appropriate
+# checks as needed.
+
+
+ifdef CONFIG_LOCALVERSION_AUTO
+ localversion-auto := $(shell $(PERL) $(srctree)/scripts/setlocalversion $(srctree))
+ LOCALVERSION := $(LOCALVERSION)$(localversion-auto)
+endif
+
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
@@ -624,8 +644,13 @@ quiet_cmd_vmlinux__ ?= LD $@
# Generate new vmlinux version
quiet_cmd_vmlinux_version = GEN .version
cmd_vmlinux_version = set -e; \
- . $(srctree)/scripts/mkversion > .tmp_version; \
- mv -f .tmp_version .version; \
+ if [ ! -r .version ]; then \
+ rm -f .version; \
+ echo 1 >.version; \
+ else \
+ mv .version .old_version; \
+ expr 0$$(cat .old_version) + 1 >.version; \
+ fi; \
$(MAKE) $(build)=init
# Generate System.map
@@ -691,8 +716,10 @@ endef
# Update vmlinux version before link
# Use + in front of this rule to silent warning about make -j1
+# First command is ':' to allow us to use + in front of this rule
cmd_ksym_ld = $(cmd_vmlinux__)
define rule_ksym_ld
+ :
+$(call cmd,vmlinux_version)
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
@@ -722,11 +749,22 @@ quiet_cmd_kallsyms = KSYM $@
# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;
+# Generate some data for debugging strange kallsyms problems
+debug_kallsyms: .tmp_map$(last_kallsyms)
+
+.tmp_map%: .tmp_vmlinux% FORCE
+ ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
+
+.tmp_map3: .tmp_map2
+
+.tmp_map2: .tmp_map1
+
endif # ifdef CONFIG_KALLSYMS
# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
$(call if_changed_rule,vmlinux__)
+ $(Q)rm -f .old_version
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
@@ -739,25 +777,30 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
# Error messages still appears in the original language
.PHONY: $(vmlinux-dirs)
-$(vmlinux-dirs): prepare-all scripts
+$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
# Things we need to do before we recursively start building the kernel
-# or the modules are listed in "prepare-all".
-# A multi level approach is used. prepare1 is updated first, then prepare0.
-# prepare-all is the collection point for the prepare targets.
+# or the modules are listed in "prepare".
+# A multi level approach is used. prepareN is processed before prepareN-1.
+# archprepare is used in arch Makefiles and when processed asm symlink,
+# version.h and scripts_basic is processed / created.
+
+# Listed in dependency order
+.PHONY: prepare archprepare prepare0 prepare1 prepare2 prepare3
-.PHONY: prepare-all prepare prepare0 prepare1 prepare2
+# prepare-all is deprecated, use prepare as valid replacement
+.PHONY: prepare-all
-# prepare2 is used to check if we are building in a separate output directory,
+# prepare3 is used to check if we are building in a separate output directory,
# and if so do:
# 1) Check that make has not been executed in the kernel src $(srctree)
# 2) Create the include2 directory, used for the second asm symlink
-prepare2:
+prepare3:
ifneq ($(KBUILD_SRC),)
@echo ' Using $(srctree) as source for kernel'
- $(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
+ $(Q)if [ -f $(srctree)/.config ]; then \
echo " $(srctree) is not clean, please run 'make mrproper'";\
echo " in the '$(srctree)' directory.";\
/bin/false; \
@@ -766,17 +809,23 @@ ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
endif
-# prepare1 creates a makefile if using a separate output directory
-prepare1: prepare2 outputmakefile
+# prepare2 creates a makefile if using a separate output directory
+prepare2: prepare3 outputmakefile
-prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
+prepare1: prepare2 include/linux/version.h include/asm \
+ include/config/MARKER
ifneq ($(KBUILD_MODULES),)
$(Q)rm -rf $(MODVERDIR)
$(Q)mkdir -p $(MODVERDIR)
endif
+archprepare: prepare1 scripts_basic
+
+prepare0: archprepare FORCE
+ $(Q)$(MAKE) $(build)=.
+
# All the preparing..
-prepare-all: prepare0 prepare
+prepare prepare-all: prepare0
# Leave this as default for preprocessing vmlinux.lds.S, which is now
# done in arch/$(ARCH)/kernel/Makefile
@@ -815,7 +864,7 @@ include/asm:
# Split autoconf.h into include/linux/config/*
-include/config/MARKER: include/linux/autoconf.h
+include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h
@echo ' SPLIT include/linux/autoconf.h -> include/config/*'
@scripts/basic/split-include include/linux/autoconf.h include/config
@touch $@
@@ -867,7 +916,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
# Target to prepare building external modules
.PHONY: modules_prepare
-modules_prepare: prepare-all scripts
+modules_prepare: prepare scripts
# Target to install modules
.PHONY: modules_install
@@ -875,7 +924,7 @@ modules_install: _modinst_ _modinst_post
.PHONY: _modinst_
_modinst_:
- @if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \
+ @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
sleep 1; \
@@ -919,26 +968,6 @@ modules modules_install: FORCE
endif # CONFIG_MODULES
-# Generate asm-offsets.h
-# ---------------------------------------------------------------------------
-
-define filechk_gen-asm-offsets
- (set -e; \
- echo "#ifndef __ASM_OFFSETS_H__"; \
- echo "#define __ASM_OFFSETS_H__"; \
- echo "/*"; \
- echo " * DO NOT MODIFY."; \
- echo " *"; \
- echo " * This file was generated by arch/$(ARCH)/Makefile"; \
- echo " *"; \
- echo " */"; \
- echo ""; \
- sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
- echo ""; \
- echo "#endif" )
-endef
-
-
###
# Cleaning is done on three levels.
# make clean Delete most generated files
@@ -961,7 +990,7 @@ MRPROPER_FILES += .config .config.old include/asm .version \
#
clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
-clean-dirs := $(addprefix _clean_,$(vmlinux-alldirs))
+clean-dirs := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
.PHONY: $(clean-dirs) clean archclean
$(clean-dirs):
@@ -1040,6 +1069,7 @@ help:
@echo ' rpm - Build a kernel as an RPM package'
@echo ' tags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
+ @echo ' kernelrelease - Output the release version string'
@echo ''
@echo 'Static analysers'
@echo ' buildcheck - List dangling references to vmlinux discarded sections'
@@ -1159,37 +1189,49 @@ else
__srctree = $(srctree)/
endif
+ALLSOURCE_ARCHS := $(ARCH)
+
define all-sources
( find $(__srctree) $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name '*.[chS]' -print; \
- find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
+ for ARCH in $(ALLSOURCE_ARCHS) ; do \
+ find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
+ -name '*.[chS]' -print; \
+ done ; \
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find $(__srctree)include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name '*.[chS]' -print; \
- find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
- -name '*.[chS]' -print; \
+ for ARCH in $(ALLSOURCE_ARCHS) ; do \
+ find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
+ -name '*.[chS]' -print; \
+ done ; \
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print )
endef
quiet_cmd_cscope-file = FILELST cscope.files
- cmd_cscope-file = $(all-sources) > cscope.files
+ cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
quiet_cmd_cscope = MAKE cscope.out
- cmd_cscope = cscope -k -b -q
+ cmd_cscope = cscope -b
cscope: FORCE
$(call cmd,cscope-file)
$(call cmd,cscope)
quiet_cmd_TAGS = MAKE $@
-cmd_TAGS = $(all-sources) | etags -
+define cmd_TAGS
+ rm -f $@; \
+ ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
+ $(all-sources) | xargs etags $$ETAGSF -a
+endef
+
+TAGS: FORCE
+ $(call cmd,TAGS)
-# Exuberant ctags works better with -I
quiet_cmd_tags = MAKE $@
define cmd_tags
@@ -1198,9 +1240,6 @@ define cmd_tags
$(all-sources) | xargs ctags $$CTAGSF -a
endef
-TAGS: FORCE
- $(call cmd,TAGS)
-
tags: FORCE
$(call cmd,tags)
@@ -1268,82 +1307,11 @@ ifneq ($(cmd_files),)
include $(cmd_files)
endif
-# Execute command and generate cmd file
-if_changed = $(if $(strip $? \
- $(filter-out $(cmd_$(1)),$(cmd_$@))\
- $(filter-out $(cmd_$@),$(cmd_$(1)))),\
- @set -e; \
- $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
- $(cmd_$(1)); \
- echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
-
-
-# execute the command and also postprocess generated .d dependencies
-# file
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
- $(filter-out $(cmd_$(1)),$(cmd_$@))\
- $(filter-out $(cmd_$@),$(cmd_$(1)))),\
- $(Q)set -e; \
- $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
- $(cmd_$(1)); \
- scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
- rm -f $(depfile); \
- mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
-
-# Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
-
-if_changed_rule = $(if $(strip $? \
- $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
- $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
- $(Q)$(rule_$(1)))
-
-# If quiet is set, only print short version of command
-
-cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
-
-# filechk is used to check if the content of a generated file is updated.
-# Sample usage:
-# define filechk_sample
-# echo $KERNELRELEASE
-# endef
-# version.h : Makefile
-# $(call filechk,sample)
-# The rule defined shall write to stdout the content of the new file.
-# The existing file will be compared with the new one.
-# - If no file exist it is created
-# - If the content differ the new file is used
-# - If they are equal no change, and no timestamp update
-
-define filechk
- @set -e; \
- echo ' CHK $@'; \
- mkdir -p $(dir $@); \
- $(filechk_$(1)) < $< > $@.tmp; \
- if [ -r $@ ] && cmp -s $@ $@.tmp; then \
- rm -f $@.tmp; \
- else \
- echo ' UPD $@'; \
- mv -f $@.tmp $@; \
- fi
-endef
-
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir
-# Usage:
-# $(Q)$(MAKE) $(build)=dir
-build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
-
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
# Usage:
# $(Q)$(MAKE) $(clean)=dir
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
-# $(call descend,<dir>,<target>)
-# Recursively call a sub-make in <dir> with target <target>
-# Usage is deprecated, because make does not see this as an invocation of make.
-descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
-
endif # skip-makefile
FORCE:
diff --git a/REPORTING-BUGS b/REPORTING-BUGS
index 224c34741d32..f9da827a0c18 100644
--- a/REPORTING-BUGS
+++ b/REPORTING-BUGS
@@ -9,7 +9,7 @@ screen please read "Documentation/oops-tracing.txt" before posting your
bug report. This explains what you should do with the "Oops" information
to make it useful to the recipient.
- Send the output the maintainer of the kernel area that seems to
+ Send the output to the maintainer of the kernel area that seems to
be involved with the problem. Don't worry too much about getting the
wrong person. If you are unsure send it to the person responsible for the
code relevant to what you were doing. If it occurs repeatably try and
@@ -18,15 +18,15 @@ The list of maintainers is in the MAINTAINERS file in this directory.
If it is a security bug, please copy the Security Contact listed
in the MAINTAINERS file. They can help coordinate bugfix and disclosure.
-See Documentation/SecurityBugs for more infomation.
+See Documentation/SecurityBugs for more information.
If you are totally stumped as to whom to send the report, send it to
linux-kernel@vger.kernel.org. (For more information on the linux-kernel
mailing list see http://www.tux.org/lkml/).
-This is a suggested format for a bug report sent to the Linux kernel mailing
-list. Having a standardized bug report form makes it easier for you not to
-overlook things, and easier for the developers to find the pieces of
+This is a suggested format for a bug report sent to the Linux kernel mailing
+list. Having a standardized bug report form makes it easier for you not to
+overlook things, and easier for the developers to find the pieces of
information they're really interested in. Don't feel you have to follow it.
First run the ver_linux script included as scripts/ver_linux, which
@@ -35,9 +35,9 @@ the command "sh scripts/ver_linux".
Use that information to fill in all fields of the bug report form, and
post it to the mailing list with a subject of "PROBLEM: <one line
-summary from [1.]>" for easy identification by the developers
+summary from [1.]>" for easy identification by the developers.
-[1.] One line summary of the problem:
+[1.] One line summary of the problem:
[2.] Full description of the problem/report:
[3.] Keywords (i.e., modules, networking, kernel):
[4.] Kernel version (from /proc/version):
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 189d5eababa8..786491f9ceb2 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -479,6 +479,9 @@ config EISA
depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
default y
+config ARCH_MAY_HAVE_PC_FDC
+ def_bool y
+
config SMP
bool "Symmetric multi-processing support"
depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 22ebfb2be0e4..1b704ee54bf3 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -108,20 +108,9 @@ $(boot)/vmlinux.gz: vmlinux
bootimage bootpfile bootpzfile: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-
-prepare: include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
define archhelp
echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
echo ' bootimage - SRM bootable image (arch/alpha/boot/bootimage)'
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index fc5ef90c4fc9..24ae9a366073 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -185,15 +185,6 @@ EXPORT_SYMBOL(smp_num_cpus);
EXPORT_SYMBOL(smp_call_function);
EXPORT_SYMBOL(smp_call_function_on_cpu);
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#ifdef CONFIG_DEBUG_SPINLOCK
-EXPORT_SYMBOL(_raw_spin_unlock);
-EXPORT_SYMBOL(debug_spin_lock);
-EXPORT_SYMBOL(debug_spin_trylock);
-#endif
-#ifdef CONFIG_DEBUG_RWLOCK
-EXPORT_SYMBOL(_raw_write_lock);
-EXPORT_SYMBOL(_raw_read_lock);
-#endif
EXPORT_SYMBOL(cpu_present_mask);
#endif /* CONFIG_SMP */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index f0927ee53f29..76cc0cb5fc2e 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -5,7 +5,7 @@
*/
#include <linux/config.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/pal.h>
#include <asm/errno.h>
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
index 4ca2e404708a..0905721fcbca 100644
--- a/arch/alpha/kernel/head.S
+++ b/arch/alpha/kernel/head.S
@@ -9,7 +9,7 @@
#include <linux/config.h>
#include <asm/system.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.globl swapper_pg_dir
.globl _stext
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
index fc271e316a38..aac6d4b22f7a 100644
--- a/arch/alpha/kernel/module.c
+++ b/arch/alpha/kernel/module.c
@@ -47,7 +47,7 @@ module_free(struct module *mod, void *module_region)
struct got_entry {
struct got_entry *next;
- Elf64_Addr r_offset;
+ Elf64_Sxword r_addend;
int got_offset;
};
@@ -57,14 +57,14 @@ process_reloc_for_got(Elf64_Rela *rela,
{
unsigned long r_sym = ELF64_R_SYM (rela->r_info);
unsigned long r_type = ELF64_R_TYPE (rela->r_info);
- Elf64_Addr r_offset = rela->r_offset;
+ Elf64_Sxword r_addend = rela->r_addend;
struct got_entry *g;
if (r_type != R_ALPHA_LITERAL)
return;
for (g = chains + r_sym; g ; g = g->next)
- if (g->r_offset == r_offset) {
+ if (g->r_addend == r_addend) {
if (g->got_offset == 0) {
g->got_offset = *poffset;
*poffset += 8;
@@ -74,7 +74,7 @@ process_reloc_for_got(Elf64_Rela *rela,
g = kmalloc (sizeof (*g), GFP_KERNEL);
g->next = chains[r_sym].next;
- g->r_offset = r_offset;
+ g->r_addend = r_addend;
g->got_offset = *poffset;
*poffset += 8;
chains[r_sym].next = g;
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 167fd89f8707..0636116210d2 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -974,6 +974,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
size_t size;
long timeout;
int ret = -EINVAL;
+ struct fdtable *fdt;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -995,7 +996,8 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
}
}
- if (n < 0 || n > current->files->max_fdset)
+ fdt = files_fdtable(current->files);
+ if (n < 0 || n > fdt->max_fdset)
goto out_nofds;
/*
@@ -1152,8 +1154,7 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
ticks = timeval_to_jiffies(&tmp);
- current->state = TASK_INTERRUPTIBLE;
- ticks = schedule_timeout(ticks);
+ ticks = schedule_timeout_interruptible(ticks);
if (remain) {
jiffies_to_timeval(ticks, &tmp);
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 08fe8071a7f8..2e45e8604e32 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -566,13 +566,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_RESETHAND)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
static inline void
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index e211aa7404e6..da0be3465791 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -989,175 +989,3 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
preempt_enable();
}
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-void
-_raw_spin_unlock(spinlock_t * lock)
-{
- mb();
- lock->lock = 0;
-
- lock->on_cpu = -1;
- lock->previous = NULL;
- lock->task = NULL;
- lock->base_file = "none";
- lock->line_no = 0;
-}
-
-void
-debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
-{
- long tmp;
- long stuck;
- void *inline_pc = __builtin_return_address(0);
- unsigned long started = jiffies;
- int printed = 0;
- int cpu = smp_processor_id();
-
- stuck = 1L << 30;
- try_again:
-
- /* Use sub-sections to put the actual loop at the end
- of this object file's text section so as to perfect
- branch prediction. */
- __asm__ __volatile__(
- "1: ldl_l %0,%1\n"
- " subq %2,1,%2\n"
- " blbs %0,2f\n"
- " or %0,1,%0\n"
- " stl_c %0,%1\n"
- " beq %0,3f\n"
- "4: mb\n"
- ".subsection 2\n"
- "2: ldl %0,%1\n"
- " subq %2,1,%2\n"
- "3: blt %2,4b\n"
- " blbs %0,2b\n"
- " br 1b\n"
- ".previous"
- : "=r" (tmp), "=m" (lock->lock), "=r" (stuck)
- : "m" (lock->lock), "2" (stuck) : "memory");
-
- if (stuck < 0) {
- printk(KERN_WARNING
- "%s:%d spinlock stuck in %s at %p(%d)"
- " owner %s at %p(%d) %s:%d\n",
- base_file, line_no,
- current->comm, inline_pc, cpu,
- lock->task->comm, lock->previous,
- lock->on_cpu, lock->base_file, lock->line_no);
- stuck = 1L << 36;
- printed = 1;
- goto try_again;
- }
-
- /* Exiting. Got the lock. */
- lock->on_cpu = cpu;
- lock->previous = inline_pc;
- lock->task = current;
- lock->base_file = base_file;
- lock->line_no = line_no;
-
- if (printed) {
- printk(KERN_WARNING
- "%s:%d spinlock grabbed in %s at %p(%d) %ld ticks\n",
- base_file, line_no, current->comm, inline_pc,
- cpu, jiffies - started);
- }
-}
-
-int
-debug_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
-{
- int ret;
- if ((ret = !test_and_set_bit(0, lock))) {
- lock->on_cpu = smp_processor_id();
- lock->previous = __builtin_return_address(0);
- lock->task = current;
- } else {
- lock->base_file = base_file;
- lock->line_no = line_no;
- }
- return ret;
-}
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#ifdef CONFIG_DEBUG_RWLOCK
-void _raw_write_lock(rwlock_t * lock)
-{
- long regx, regy;
- int stuck_lock, stuck_reader;
- void *inline_pc = __builtin_return_address(0);
-
- try_again:
-
- stuck_lock = 1<<30;
- stuck_reader = 1<<30;
-
- __asm__ __volatile__(
- "1: ldl_l %1,%0\n"
- " blbs %1,6f\n"
- " blt %1,8f\n"
- " mov 1,%1\n"
- " stl_c %1,%0\n"
- " beq %1,6f\n"
- "4: mb\n"
- ".subsection 2\n"
- "6: blt %3,4b # debug\n"
- " subl %3,1,%3 # debug\n"
- " ldl %1,%0\n"
- " blbs %1,6b\n"
- "8: blt %4,4b # debug\n"
- " subl %4,1,%4 # debug\n"
- " ldl %1,%0\n"
- " blt %1,8b\n"
- " br 1b\n"
- ".previous"
- : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (regy),
- "=&r" (stuck_lock), "=&r" (stuck_reader)
- : "m" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
-
- if (stuck_lock < 0) {
- printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc);
- goto try_again;
- }
- if (stuck_reader < 0) {
- printk(KERN_WARNING "write_lock stuck on readers at %p\n",
- inline_pc);
- goto try_again;
- }
-}
-
-void _raw_read_lock(rwlock_t * lock)
-{
- long regx;
- int stuck_lock;
- void *inline_pc = __builtin_return_address(0);
-
- try_again:
-
- stuck_lock = 1<<30;
-
- __asm__ __volatile__(
- "1: ldl_l %1,%0;"
- " blbs %1,6f;"
- " subl %1,2,%1;"
- " stl_c %1,%0;"
- " beq %1,6f;"
- "4: mb\n"
- ".subsection 2\n"
- "6: ldl %1,%0;"
- " blt %2,4b # debug\n"
- " subl %2,1,%2 # debug\n"
- " blbs %1,6b;"
- " br 1b\n"
- ".previous"
- : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (stuck_lock)
- : "m" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
-
- if (stuck_lock < 0) {
- printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc);
- goto try_again;
- }
-}
-#endif /* CONFIG_DEBUG_RWLOCK */
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 804727853d25..e32fee505220 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -373,12 +373,11 @@ marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
irq += 0x80; /* offset for lsi */
#if 1
- printk("PCI:%d:%d:%d (hose %d) [%s] is using MSI\n",
+ printk("PCI:%d:%d:%d (hose %d) is using MSI\n",
dev->bus->number,
PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn),
- hose->index,
- pci_pretty_name (dev));
+ hose->index);
printk(" %d message(s) from 0x%04x\n",
1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
msg_dat);
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 8226c5cd788c..67be50b7d80a 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -149,7 +149,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0
+ if (ntp_synced()
&& xtime.tv_sec > state.last_rtc_update + 660
&& xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
&& xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -502,10 +502,7 @@ do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
diff --git a/arch/alpha/lib/dbg_stackcheck.S b/arch/alpha/lib/dbg_stackcheck.S
index cc5ce3a5fcad..3c1f3e6522e5 100644
--- a/arch/alpha/lib/dbg_stackcheck.S
+++ b/arch/alpha/lib/dbg_stackcheck.S
@@ -5,7 +5,7 @@
* Verify that we have not overflowed the stack. Oops if we have.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
.set noat
diff --git a/arch/alpha/lib/dbg_stackkill.S b/arch/alpha/lib/dbg_stackkill.S
index e09f2ae1e09e..e9f6a9dcf2b7 100644
--- a/arch/alpha/lib/dbg_stackkill.S
+++ b/arch/alpha/lib/dbg_stackkill.S
@@ -6,7 +6,7 @@
* uninitialized local variables in the act.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
.set noat
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c65c6eb9810d..11fff042aa81 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -64,6 +64,9 @@ config GENERIC_CALIBRATE_DELAY
config GENERIC_BUST_SPINLOCK
bool
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+
config GENERIC_ISA_DMA
bool
@@ -150,6 +153,7 @@ config ARCH_RPC
select ARCH_ACORN
select FIQ
select TIMER_ACORN
+ select ARCH_MAY_HAVE_PC_FDC
help
On the Acorn Risc-PC, Linux can support the internal IDE disk and
CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -322,8 +326,8 @@ config SMP
processor machines. On a single processor machine, the kernel will
run faster if you say N here.
- See also the <file:Documentation/smp.tex>,
- <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
+ 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.linuxdoc.org/docs.html#howto>.
@@ -365,8 +369,8 @@ config NO_IDLE_HZ
Please note that dynamic tick may affect the accuracy of
timekeeping on some platforms depending on the implementation.
- Currently at least OMAP platform is known to have accurate
- timekeeping with dynamic tick.
+ Currently at least OMAP, PXA2xx and SA11x0 platforms are known
+ to have accurate timekeeping with dynamic tick.
config ARCH_DISCONTIGMEM_ENABLE
bool
@@ -635,10 +639,6 @@ config PM
and the Battery Powered Linux mini-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- Note that, even if you say N here, Linux on the x86 architecture
- will issue the hlt instruction if nothing is to be done, thereby
- sending the processor to sleep and saving power.
-
config APM
tristate "Advanced Power Management Emulation"
depends on PM
@@ -650,12 +650,6 @@ config APM
battery status information, and user-space programs will receive
notification of APM "events" (e.g. battery status change).
- If you select "Y" here, you can disable actual use of the APM
- BIOS by passing the "apm=off" option to the kernel at boot time.
-
- Note that the APM support is almost completely disabled for
- machines with more than one CPU.
-
In order to use APM, you will need supporting software. For location
and more information, read <file:Documentation/pm.txt> and the
Battery Powered Linux mini-HOWTO, available from
@@ -665,39 +659,12 @@ config APM
manpage ("man 8 hdparm") for that), and it doesn't turn off
VESA-compliant "green" monitors.
- This driver does not support the TI 4000M TravelMate and the ACER
- 486/DX4/75 because they don't have compliant BIOSes. Many "green"
- desktop machines also don't have compliant BIOSes, and this driver
- may cause those machines to panic during the boot phase.
-
Generally, if you don't have a battery in your machine, there isn't
much point in using this driver and you should say N. If you get
random kernel OOPSes or reboots that don't seem to be related to
anything, try disabling/enabling this option (or disabling/enabling
APM in your BIOS).
- Some other things you should try when experiencing seemingly random,
- "weird" problems:
-
- 1) make sure that you have enough swap space and that it is
- enabled.
- 2) pass the "no-hlt" option to the kernel
- 3) switch on floating point emulation in the kernel and pass
- the "no387" option to the kernel
- 4) pass the "floppy=nodma" option to the kernel
- 5) pass the "mem=4M" option to the kernel (thereby disabling
- all but the first 4 MB of RAM)
- 6) make sure that the CPU is not over clocked.
- 7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
- 8) disable the cache from your BIOS settings
- 9) install a fan for the video card or exchange video RAM
- 10) install a better fan for the CPU
- 11) exchange RAM chips
- 12) exchange the motherboard.
-
- To compile this driver as a module, choose M here: the
- module will be called apm.
-
endmenu
source "net/Kconfig"
@@ -752,6 +719,8 @@ source "drivers/hwmon/Kconfig"
source "drivers/misc/Kconfig"
+source "drivers/mfd/Kconfig"
+
source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 45a5709eaaa4..5d3acff8c596 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -53,7 +53,7 @@ config DEBUG_LL
bool "Kernel low-level debugging functions"
depends on DEBUG_KERNEL
help
- Say Y here to include definitions of printascii, printchar, printhex
+ Say Y here to include definitions of printascii, printch, printhex
in the kernel. This is helpful if you are debugging code that
executes before the console is initialized.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 67f1453ade05..130e6228b587 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -175,10 +175,10 @@ else
endif
@touch $@
-prepare: maketools include/asm-arm/.arch
+archprepare: maketools include/asm-arm/.arch
.PHONY: maketools FORCE
-maketools: include/asm-arm/constants.h include/linux/version.h FORCE
+maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
# Convert bzImage to zImage
@@ -190,7 +190,7 @@ zImage Image xipImage bootpImage uImage: vmlinux
zinstall install: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
-CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h \
+CLEAN_FILES += include/asm-arm/mach-types.h \
include/asm-arm/arch include/asm-arm/.arch
# We use MRPROPER_FILES and CLEAN_FILES now
@@ -201,11 +201,6 @@ archclean:
bp:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage
i zi:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/asm-arm/.arch
-
-include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
define archhelp
echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
diff --git a/arch/arm/boot/compressed/head-sharpsl.S b/arch/arm/boot/compressed/head-sharpsl.S
index d6bf8a2b090d..59ad69640d6b 100644
--- a/arch/arm/boot/compressed/head-sharpsl.S
+++ b/arch/arm/boot/compressed/head-sharpsl.S
@@ -7,7 +7,8 @@
* so we have to figure out the machine for ourselves...
*
* Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
- * and Husky (SL-C760).
+ * Husky (SL-C760), Tosa (SL-C6000), Spitz (SL-C3000),
+ * Akita (SL-C1000) and Borzoi (SL-C3100).
*
*/
@@ -23,6 +24,22 @@
__SharpSL_start:
+/* Check for TC6393 - if found we have a Tosa */
+ ldr r7, .TOSAID
+ mov r1, #0x10000000 @ Base address of TC6393 chip
+ mov r6, #0x03
+ ldrh r3, [r1, #8] @ Load TC6393XB Revison: This is 0x0003
+ cmp r6, r3
+ beq .SHARPEND @ Success -> tosa
+
+/* Check for pxa270 - if found, branch */
+ mrc p15, 0, r4, c0, c0 @ Get Processor ID
+ and r4, r4, #0xffffff00
+ ldr r3, .PXA270ID
+ cmp r4, r3
+ beq .PXA270
+
+/* Check for w100 - if not found we have a Poodle */
ldr r1, .W100ADDR @ Base address of w100 chip + regs offset
mov r6, #0x31 @ Load Magic Init value
@@ -30,7 +47,7 @@ __SharpSL_start:
mov r5, #0x3000
.W100LOOP:
subs r5, r5, #1
- bne .W100LOOP
+ bne .W100LOOP
mov r6, #0x30 @ Load 2nd Magic Init value
str r6, [r1, #0x280] @ to SCRATCH_UMSK
@@ -40,45 +57,52 @@ __SharpSL_start:
cmp r6, r3
bne .SHARPEND @ We have no w100 - Poodle
- mrc p15, 0, r6, c0, c0 @ Get Processor ID
- and r6, r6, #0xffffff00
+/* Check for pxa250 - if found we have a Corgi */
ldr r7, .CORGIID
ldr r3, .PXA255ID
- cmp r6, r3
+ cmp r4, r3
blo .SHARPEND @ We have a PXA250 - Corgi
- mov r1, #0x0c000000 @ Base address of NAND chip
- ldrb r3, [r1, #24] @ Load FLASHCTL
- bic r3, r3, #0x11 @ SET NCE
- orr r3, r3, #0x0a @ SET CLR + FLWP
- strb r3, [r1, #24] @ Save to FLASHCTL
- mov r2, #0x90 @ Command "readid"
- strb r2, [r1, #20] @ Save to FLASHIO
- bic r3, r3, #2 @ CLR CLE
- orr r3, r3, #4 @ SET ALE
- strb r3, [r1, #24] @ Save to FLASHCTL
- mov r2, #0 @ Address 0x00
- strb r2, [r1, #20] @ Save to FLASHIO
- bic r3, r3, #4 @ CLR ALE
- strb r3, [r1, #24] @ Save to FLASHCTL
-.SHARP1:
- ldrb r3, [r1, #24] @ Load FLASHCTL
- tst r3, #32 @ Is chip ready?
- beq .SHARP1
- ldrb r2, [r1, #20] @ NAND Manufacturer ID
- ldrb r3, [r1, #20] @ NAND Chip ID
+/* Check for 64MiB flash - if found we have a Shepherd */
+ bl get_flash_ids
ldr r7, .SHEPHERDID
cmp r3, #0x76 @ 64MiB flash
beq .SHARPEND @ We have Shepherd
+
+/* Must be a Husky */
ldr r7, .HUSKYID @ Must be Husky
b .SHARPEND
+.PXA270:
+/* Check for 16MiB flash - if found we have Spitz */
+ bl get_flash_ids
+ ldr r7, .SPITZID
+ cmp r3, #0x73 @ 16MiB flash
+ beq .SHARPEND @ We have Spitz
+
+/* Check for a second SCOOP chip - if found we have Borzoi */
+ ldr r1, .SCOOP2ADDR
+ ldr r7, .BORZOIID
+ mov r6, #0x0140
+ strh r6, [r1]
+ ldrh r6, [r1]
+ cmp r6, #0x0140
+ beq .SHARPEND @ We have Borzoi
+
+/* Must be Akita */
+ ldr r7, .AKITAID
+ b .SHARPEND @ We have Borzoi
+
.PXA255ID:
.word 0x69052d00 @ PXA255 Processor ID
+.PXA270ID:
+ .word 0x69054100 @ PXA270 Processor ID
.W100ID:
.word 0x57411002 @ w100 Chip ID
.W100ADDR:
.word 0x08010000 @ w100 Chip ID Reg Address
+.SCOOP2ADDR:
+ .word 0x08800040
.POODLEID:
.word MACH_TYPE_POODLE
.CORGIID:
@@ -87,6 +111,41 @@ __SharpSL_start:
.word MACH_TYPE_SHEPHERD
.HUSKYID:
.word MACH_TYPE_HUSKY
-.SHARPEND:
+.TOSAID:
+ .word MACH_TYPE_TOSA
+.SPITZID:
+ .word MACH_TYPE_SPITZ
+.AKITAID:
+ .word MACH_TYPE_AKITA
+.BORZOIID:
+ .word MACH_TYPE_BORZOI
+/*
+ * Return: r2 - NAND Manufacturer ID
+ * r3 - NAND Chip ID
+ * Corrupts: r1
+ */
+get_flash_ids:
+ mov r1, #0x0c000000 @ Base address of NAND chip
+ ldrb r3, [r1, #24] @ Load FLASHCTL
+ bic r3, r3, #0x11 @ SET NCE
+ orr r3, r3, #0x0a @ SET CLR + FLWP
+ strb r3, [r1, #24] @ Save to FLASHCTL
+ mov r2, #0x90 @ Command "readid"
+ strb r2, [r1, #20] @ Save to FLASHIO
+ bic r3, r3, #2 @ CLR CLE
+ orr r3, r3, #4 @ SET ALE
+ strb r3, [r1, #24] @ Save to FLASHCTL
+ mov r2, #0 @ Address 0x00
+ strb r2, [r1, #20] @ Save to FLASHIO
+ bic r3, r3, #4 @ CLR ALE
+ strb r3, [r1, #24] @ Save to FLASHCTL
+.fids1:
+ ldrb r3, [r1, #24] @ Load FLASHCTL
+ tst r3, #32 @ Is chip ready?
+ beq .fids1
+ ldrb r2, [r1, #20] @ NAND Manufacturer ID
+ ldrb r3, [r1, #20] @ NAND Chip ID
+ mov pc, lr
+.SHARPEND:
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 692af6b5e8ff..666ba393575b 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,6 +1,9 @@
config ICST525
bool
+config ARM_GIC
+ bool
+
config ICST307
bool
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 11f20a43ee3a..a87886564b19 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -4,6 +4,7 @@
obj-y += rtctime.o
obj-$(CONFIG_ARM_AMBA) += amba.o
+obj-$(CONFIG_ARM_GIC) += gic.o
obj-$(CONFIG_ICST525) += icst525.o
obj-$(CONFIG_ICST307) += icst307.o
obj-$(CONFIG_SA1111) += sa1111.o
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
new file mode 100644
index 000000000000..d74990717559
--- /dev/null
+++ b/arch/arm/common/gic.c
@@ -0,0 +1,167 @@
+/*
+ * linux/arch/arm/common/gic.c
+ *
+ * Copyright (C) 2002 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.
+ *
+ * Interrupt architecture for the GIC:
+ *
+ * o There is one Interrupt Distributor, which receives interrupts
+ * from system devices and sends them to the Interrupt Controllers.
+ *
+ * o There is one CPU Interface per CPU, which sends interrupts sent
+ * by the Distributor, and interrupts generated locally, to the
+ * associated CPU.
+ *
+ * Note that IRQs 0-31 are special - they are local to each CPU.
+ * As such, the enable set/clear, pending set/clear and active bit
+ * registers are banked per-cpu for these sources.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+#include <linux/cpumask.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware/gic.h>
+
+static void __iomem *gic_dist_base;
+static void __iomem *gic_cpu_base;
+
+/*
+ * Routines to acknowledge, disable and enable interrupts
+ *
+ * Linux assumes that when we're done with an interrupt we need to
+ * unmask it, in the same way we need to unmask an interrupt when
+ * we first enable it.
+ *
+ * The GIC has a seperate notion of "end of interrupt" to re-enable
+ * an interrupt after handling, in order to support hardware
+ * prioritisation.
+ *
+ * We can make the GIC behave in the way that Linux expects by making
+ * our "acknowledge" routine disable the interrupt, then mark it as
+ * complete.
+ */
+static void gic_ack_irq(unsigned int irq)
+{
+ u32 mask = 1 << (irq % 32);
+ writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+ writel(irq, gic_cpu_base + GIC_CPU_EOI);
+}
+
+static void gic_mask_irq(unsigned int irq)
+{
+ u32 mask = 1 << (irq % 32);
+ writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+}
+
+static void gic_unmask_irq(unsigned int irq)
+{
+ u32 mask = 1 << (irq % 32);
+ writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
+}
+
+static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
+{
+ void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
+ unsigned int shift = (irq % 4) * 8;
+ u32 val;
+
+ val = readl(reg) & ~(0xff << shift);
+ val |= 1 << (cpu + shift);
+ writel(val, reg);
+}
+
+static struct irqchip gic_chip = {
+ .ack = gic_ack_irq,
+ .mask = gic_mask_irq,
+ .unmask = gic_unmask_irq,
+#ifdef CONFIG_SMP
+ .set_cpu = gic_set_cpu,
+#endif
+};
+
+void __init gic_dist_init(void __iomem *base)
+{
+ unsigned int max_irq, i;
+ u32 cpumask = 1 << smp_processor_id();
+
+ cpumask |= cpumask << 8;
+ cpumask |= cpumask << 16;
+
+ gic_dist_base = base;
+
+ writel(0, base + GIC_DIST_CTRL);
+
+ /*
+ * Find out how many interrupts are supported.
+ */
+ max_irq = readl(base + GIC_DIST_CTR) & 0x1f;
+ max_irq = (max_irq + 1) * 32;
+
+ /*
+ * The GIC only supports up to 1020 interrupt sources.
+ * Limit this to either the architected maximum, or the
+ * platform maximum.
+ */
+ if (max_irq > max(1020, NR_IRQS))
+ max_irq = max(1020, NR_IRQS);
+
+ /*
+ * Set all global interrupts to be level triggered, active low.
+ */
+ for (i = 32; i < max_irq; i += 16)
+ writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
+
+ /*
+ * Set all global interrupts to this CPU only.
+ */
+ for (i = 32; i < max_irq; i += 4)
+ writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+
+ /*
+ * Set priority on all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 4)
+ writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+ /*
+ * Disable all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 32)
+ writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+
+ /*
+ * Setup the Linux IRQ subsystem.
+ */
+ for (i = 29; i < max_irq; i++) {
+ set_irq_chip(i, &gic_chip);
+ set_irq_handler(i, do_level_IRQ);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+
+ writel(1, base + GIC_DIST_CTRL);
+}
+
+void __cpuinit gic_cpu_init(void __iomem *base)
+{
+ gic_cpu_base = base;
+ writel(0xf0, base + GIC_CPU_PRIMASK);
+ writel(1, base + GIC_CPU_CTRL);
+}
+
+#ifdef CONFIG_SMP
+void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
+{
+ unsigned long map = *cpus_addr(cpumask);
+
+ writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
+}
+#endif
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 41f12658c8b4..2786f7c34b3f 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -177,7 +177,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + irq;
for (i = 0; i <= 3; i++, d++, irq++) {
if (req & (0x0100 << i)) {
- d->handle(irq, d, regs);
+ desc_handle_irq(irq, d, regs);
}
}
@@ -220,7 +220,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
d = irq_desc + LOCOMO_IRQ_KEY_START;
- d->handle(LOCOMO_IRQ_KEY_START, d, regs);
+ desc_handle_irq(LOCOMO_IRQ_KEY_START, d, regs);
}
}
@@ -273,7 +273,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + LOCOMO_IRQ_GPIO_START;
for (i = 0; i <= 15; i++, irq++, d++) {
if (req & (0x0001 << i)) {
- d->handle(irq, d, regs);
+ desc_handle_irq(irq, d, regs);
}
}
}
@@ -328,7 +328,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc,
if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
d = irq_desc + LOCOMO_IRQ_LT_START;
- d->handle(LOCOMO_IRQ_LT_START, d, regs);
+ desc_handle_irq(LOCOMO_IRQ_LT_START, d, regs);
}
}
@@ -379,7 +379,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
for (i = 0; i <= 3; i++, irq++, d++) {
if (req & (0x0001 << i)) {
- d->handle(irq, d, regs);
+ desc_handle_irq(irq, d, regs);
}
}
}
@@ -541,6 +541,103 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
return ret;
}
+#ifdef CONFIG_PM
+
+struct locomo_save_data {
+ u16 LCM_GPO;
+ u16 LCM_SPICT;
+ u16 LCM_GPE;
+ u16 LCM_ASD;
+ u16 LCM_SPIMD;
+};
+
+static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level)
+{
+ struct locomo *lchip = dev_get_drvdata(dev);
+ struct locomo_save_data *save;
+ unsigned long flags;
+
+ if (level != SUSPEND_DISABLE)
+ return 0;
+
+ save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
+ if (!save)
+ return -ENOMEM;
+
+ dev->power.saved_state = (void *) save;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+
+ save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */
+ locomo_writel(0x00, lchip->base + LOCOMO_GPO);
+ save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPICT); /* SPI */
+ locomo_writel(0x40, lchip->base + LOCOMO_SPICT);
+ save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */
+ locomo_writel(0x00, lchip->base + LOCOMO_GPE);
+ save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */
+ locomo_writel(0x00, lchip->base + LOCOMO_ASD);
+ save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPIMD); /* SPI */
+ locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD);
+
+ locomo_writel(0x00, lchip->base + LOCOMO_PAIF);
+ locomo_writel(0x00, lchip->base + LOCOMO_DAC);
+ locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
+
+ if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) )
+ locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */
+ else
+ /* 18MHz already enabled, so no wait */
+ locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */
+
+ locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/
+ locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */
+ locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */
+
+ spin_unlock_irqrestore(&lchip->lock, flags);
+
+ return 0;
+}
+
+static int locomo_resume(struct device *dev, u32 level)
+{
+ struct locomo *lchip = dev_get_drvdata(dev);
+ struct locomo_save_data *save;
+ unsigned long r;
+ unsigned long flags;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ save = (struct locomo_save_data *) dev->power.saved_state;
+ if (!save)
+ return 0;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+
+ locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);
+ locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT);
+ locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);
+ locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);
+ locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD);
+
+ locomo_writel(0x00, lchip->base + LOCOMO_C32K);
+ locomo_writel(0x90, lchip->base + LOCOMO_TADC);
+
+ locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
+ r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
+ r &= 0xFEFF;
+ locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
+ locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
+
+ spin_unlock_irqrestore(&lchip->lock, flags);
+
+ dev->power.saved_state = NULL;
+ kfree(save);
+
+ return 0;
+}
+#endif
+
/**
* locomo_probe - probe for a single LoCoMo chip.
* @phys_addr: physical address of device.
@@ -651,15 +748,15 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
return ret;
}
-static void __locomo_remove(struct locomo *lchip)
+static int locomo_remove_child(struct device *dev, void *data)
{
- struct list_head *l, *n;
-
- list_for_each_safe(l, n, &lchip->dev->children) {
- struct device *d = list_to_dev(l);
+ device_unregister(dev);
+ return 0;
+}
- device_unregister(d);
- }
+static void __locomo_remove(struct locomo *lchip)
+{
+ device_for_each_child(lchip->dev, NULL, locomo_remove_child);
if (lchip->irq != NO_IRQ) {
set_irq_chained_handler(lchip->irq, NULL);
@@ -707,6 +804,10 @@ static struct device_driver locomo_device_driver = {
.bus = &platform_bus_type,
.probe = locomo_probe,
.remove = locomo_remove,
+#ifdef CONFIG_PM
+ .suspend = locomo_suspend,
+ .resume = locomo_resume,
+#endif
};
/*
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 38c2eb667eb9..1a47fbf9cbbc 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -268,8 +268,8 @@ static struct irqchip sa1111_low_chip = {
.mask = sa1111_mask_lowirq,
.unmask = sa1111_unmask_lowirq,
.retrigger = sa1111_retrigger_lowirq,
- .type = sa1111_type_lowirq,
- .wake = sa1111_wake_lowirq,
+ .set_type = sa1111_type_lowirq,
+ .set_wake = sa1111_wake_lowirq,
};
static void sa1111_mask_highirq(unsigned int irq)
@@ -364,8 +364,8 @@ static struct irqchip sa1111_high_chip = {
.mask = sa1111_mask_highirq,
.unmask = sa1111_unmask_highirq,
.retrigger = sa1111_retrigger_highirq,
- .type = sa1111_type_highirq,
- .wake = sa1111_wake_highirq,
+ .set_type = sa1111_type_highirq,
+ .set_wake = sa1111_wake_highirq,
};
static void sa1111_setup_irq(struct sa1111 *sachip)
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index cfd0d3e550d9..d3a04c2a2c85 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -17,6 +17,12 @@
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
+/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c
+ There is no easy way to link multiple scoop devices into one
+ single entity for the pxa2xx_pcmcia device */
+int scoop_num;
+struct scoop_pcmcia_dev *scoop_devs;
+
struct scoop_dev {
void *base;
spinlock_t scoop_lock;
@@ -85,7 +91,7 @@ EXPORT_SYMBOL(read_scoop_reg);
EXPORT_SYMBOL(write_scoop_reg);
#ifdef CONFIG_PM
-static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
+static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
{
if (level == SUSPEND_POWER_DOWN) {
struct scoop_dev *sdev = dev_get_drvdata(dev);
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index 24955263b096..4198677cd394 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Fri Jul 8 04:49:34 2005
+# Linux kernel version: 2.6.13
+# Mon Sep 5 18:07:12 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -102,9 +102,11 @@ CONFIG_OMAP_MUX_WARNINGS=y
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
+# CONFIG_OMAP_DM_TIMER is not set
CONFIG_OMAP_LL_DEBUG_UART1=y
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
#
# OMAP Core Type
@@ -166,7 +168,6 @@ CONFIG_ISA_DMA_API=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
CONFIG_PREEMPT=y
CONFIG_NO_IDLE_HZ=y
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -230,91 +231,82 @@ CONFIG_PM=y
# CONFIG_APM is not set
#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
+# Networking
#
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_NET=y
#
-# User Modules And Translation Layers
+# Networking options
#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL 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 is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
#
-# RAM/ROM/Flash chip drivers
+# SCTP Configuration (EXPERIMENTAL)
#
-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_XIP is not set
+# 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 is not set
#
-# Mapping drivers for chip access
+# Network testing
#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
#
-# Self-contained MTD device drivers
+# Device Drivers
#
-# 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
#
-# Disk-On-Chip Device Drivers
+# Generic Driver Options
#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
-# NAND Flash Device Drivers
+# Memory Technology Devices (MTD)
#
-# CONFIG_MTD_NAND is not set
+# CONFIG_MTD is not set
#
# Parallel port support
@@ -403,72 +395,8 @@ CONFIG_SCSI_PROC_FS=y
#
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_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
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
+# Network device support
#
-# 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
-#
-# 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
@@ -518,6 +446,8 @@ CONFIG_SLIP_COMPRESSED=y
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -615,77 +545,15 @@ CONFIG_WATCHDOG_NOWAYOUT=y
#
# I2C support
#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
+CONFIG_ISP1301_OMAP=y
#
-# Hardware Sensors Chip support
+# Hardware Monitoring support
#
-# CONFIG_I2C_SENSOR 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_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
-# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other 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_ISP1301_OMAP=y
-CONFIG_TPS65010=y
-# 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_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -756,15 +624,9 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
# CONFIG_SOUND_AD1980 is not set
#
@@ -810,6 +672,7 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -817,6 +680,7 @@ CONFIG_EXT2_FS=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -857,15 +721,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=2
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC 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_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -1007,4 +862,3 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 96a794d8de84..756348bf5170 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-git4
-# Wed Jun 22 15:56:42 2005
+# Linux kernel version: 2.6.13-git8
+# Thu Sep 8 19:24:02 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -22,6 +22,7 @@ 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
@@ -31,6 +32,7 @@ CONFIG_SYSCTL=y
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
@@ -88,7 +90,9 @@ CONFIG_ARCH_S3C2410=y
#
# S3C24XX Implementations
#
+CONFIG_MACH_ANUBIS=y
CONFIG_ARCH_BAST=y
+CONFIG_BAST_PC104_IRQ=y
CONFIG_ARCH_H1940=y
CONFIG_MACH_N30=y
CONFIG_ARCH_SMDK2410=y
@@ -112,6 +116,7 @@ CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
# CONFIG_S3C2410_PM_DEBUG is not set
# CONFIG_S3C2410_PM_CHECK is not set
+CONFIG_PM_SIMTEC=y
CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
#
@@ -149,7 +154,15 @@ CONFIG_ISA_DMA_API=y
#
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_NO_IDLE_HZ 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_ALIGNMENT_TRAP=y
#
@@ -186,6 +199,74 @@ CONFIG_PM=y
CONFIG_APM=y
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP 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_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_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
+# 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 is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
#
@@ -258,6 +339,7 @@ CONFIG_MTD_ROM=y
# CONFIG_MTD_IMPA7 is not set
CONFIG_MTD_BAST=y
CONFIG_MTD_BAST_MAXSIZE=4
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -312,7 +394,6 @@ 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
#
@@ -354,6 +435,7 @@ CONFIG_BLK_DEV_IDE_BAST=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -376,70 +458,8 @@ CONFIG_BLK_DEV_IDE_BAST=y
#
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
+# Network device support
#
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_FIB_TRIE is not set
-# CONFIG_IP_MULTICAST is not set
-# 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_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=y
-# 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
-#
-# 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
@@ -447,6 +467,11 @@ CONFIG_NETDEVICES=y
# CONFIG_TUN is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -480,6 +505,8 @@ CONFIG_DM9000=m
# 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
@@ -562,7 +589,6 @@ 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 is not set
# CONFIG_SERIAL_8250_RSA is not set
#
@@ -605,7 +631,6 @@ CONFIG_S3C2410_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -628,7 +653,7 @@ CONFIG_I2C_ALGOBIT=m
#
# I2C Hardware Bus support
#
-# CONFIG_I2C_ISA is not set
+CONFIG_I2C_ISA=m
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
CONFIG_I2C_S3C2410=y
@@ -636,14 +661,33 @@ CONFIG_I2C_S3C2410=y
# CONFIG_I2C_PCA_ISA is not set
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=m
+# 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
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=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_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
@@ -662,27 +706,21 @@ CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM92 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_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
#
-# Other I2C Chip support
+# Misc devices
#
-# CONFIG_SENSORS_DS1337 is not set
-CONFIG_SENSORS_EEPROM=m
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 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 Capabilities Port drivers
#
#
@@ -731,7 +769,7 @@ CONFIG_DUMMY_CONSOLE=y
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB is not set
#
@@ -749,6 +787,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
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
@@ -758,6 +797,7 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -765,6 +805,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -791,11 +832,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -812,8 +853,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_JFFS_PROC_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_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -835,6 +875,7 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -920,6 +961,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_DEBUG_KERNEL=y
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 2b6b4c786e65..949ec4427f21 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -10,7 +10,7 @@
* This file is included twice in entry-common.S
*/
#ifndef NR_syscalls
-#define NR_syscalls 320
+#define NR_syscalls 328
#else
__syscall_start:
@@ -284,7 +284,7 @@ __syscall_start:
.long sys_fstatfs64
.long sys_tgkill
.long sys_utimes
-/* 270 */ .long sys_fadvise64_64
+/* 270 */ .long sys_arm_fadvise64_64_wrapper
.long sys_pciconfig_iobase
.long sys_pciconfig_read
.long sys_pciconfig_write
@@ -333,6 +333,9 @@ __syscall_start:
.long sys_inotify_init
.long sys_inotify_add_watch
.long sys_inotify_rm_watch
+ .long sys_mbind_wrapper
+/* 320 */ .long sys_get_mempolicy
+ .long sys_set_mempolicy
__syscall_end:
.rept NR_syscalls - (__syscall_end - __syscall_start) / 4
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 6540db691338..dceb826bd216 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
if (pending) {
struct irqdesc *d = irq_desc + ec->irq;
- d->handle(ec->irq, d, regs);
+ desc_handle_irq(ec->irq, d, regs);
called ++;
}
}
@@ -632,7 +632,7 @@ ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
* Serial cards should go in 0/1, ethernet/scsi in 2/3
* otherwise you will lose serial data at high speeds!
*/
- d->handle(ec->irq, d, regs);
+ desc_handle_irq(ec->irq, d, regs);
} else {
printk(KERN_WARNING "card%d: interrupt from unclaimed "
"card???\n", slot);
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3f8d0e3aefab..db302c6e5343 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -265,6 +265,14 @@ sys_futex_wrapper:
str r5, [sp, #4] @ push sixth arg
b sys_futex
+sys_arm_fadvise64_64_wrapper:
+ str r5, [sp, #4] @ push r5 to stack
+ b sys_arm_fadvise64_64
+
+sys_mbind_wrapper:
+ str r5, [sp, #4]
+ b sys_mbind
+
/*
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
* offset, we return EINVAL.
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index afef21273963..648cfff93138 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -3,7 +3,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/errno.h>
#include <asm/thread_info.h>
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 1155cf07c871..539626351348 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -20,7 +20,7 @@
#include <asm/mach-types.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/system.h>
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 395137a8fad2..3284118f356b 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -207,8 +207,8 @@ void enable_irq_wake(unsigned int irq)
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
- if (desc->chip->wake)
- desc->chip->wake(irq, 1);
+ if (desc->chip->set_wake)
+ desc->chip->set_wake(irq, 1);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
EXPORT_SYMBOL(enable_irq_wake);
@@ -219,8 +219,8 @@ void disable_irq_wake(unsigned int irq)
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
- if (desc->chip->wake)
- desc->chip->wake(irq, 0);
+ if (desc->chip->set_wake)
+ desc->chip->set_wake(irq, 0);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
EXPORT_SYMBOL(disable_irq_wake);
@@ -517,7 +517,7 @@ static void do_pending_irqs(struct pt_regs *regs)
list_for_each_safe(l, n, &head) {
desc = list_entry(l, struct irqdesc, pend);
list_del_init(&desc->pend);
- desc->handle(desc - irq_desc, desc, regs);
+ desc_handle_irq(desc - irq_desc, desc, regs);
}
/*
@@ -545,7 +545,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
irq_enter();
spin_lock(&irq_controller_lock);
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
/*
* Now re-run any pending interrupts.
@@ -624,9 +624,9 @@ int set_irq_type(unsigned int irq, unsigned int type)
}
desc = irq_desc + irq;
- if (desc->chip->type) {
+ if (desc->chip->set_type) {
spin_lock_irqsave(&irq_controller_lock, flags);
- ret = desc->chip->type(irq, type);
+ ret = desc->chip->set_type(irq, type);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
@@ -846,8 +846,8 @@ unsigned long probe_irq_on(void)
irq_desc[i].probing = 1;
irq_desc[i].triggered = 0;
- if (irq_desc[i].chip->type)
- irq_desc[i].chip->type(i, IRQT_PROBE);
+ if (irq_desc[i].chip->set_type)
+ irq_desc[i].chip->set_type(i, IRQT_PROBE);
irq_desc[i].chip->unmask(i);
irqs += 1;
}
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index 8f74e24536ba..24c7b0477a09 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -17,7 +17,7 @@
#include <linux/linkage.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#define MMX_WR0 (0x00)
#define MMX_WR1 (0x08)
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 5e435e42dacd..a94d75fef598 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -658,11 +658,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
/*
* Block the signal if we were unsuccessful.
*/
- if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret != 0) {
spin_lock_irq(&tsk->sighand->siglock);
sigorsets(&tsk->blocked, &tsk->blocked,
&ka->sa.sa_mask);
- sigaddset(&tsk->blocked, sig);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&tsk->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&tsk->sighand->siglock);
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index b2085735a2ba..826164945747 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -110,7 +110,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
* We need to tell the secondary core where to find
* its stack and the page tables.
*/
- secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
+ secondary_data.stack = (void *)idle->thread_info + THREAD_START_SP;
secondary_data.pgdir = virt_to_phys(pgd);
wmb();
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index f897ce2ccf0d..42629ff84f5a 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
return ret;
}
EXPORT_SYMBOL(execve);
+
+/*
+ * Since loff_t is a 64 bit type we avoid a lot of ABI hastle
+ * with a different argument ordering.
+ */
+asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
+ loff_t offset, loff_t len)
+{
+ return sys_fadvise64_64(fd, offset, len, advice);
+}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 1b7fcd50c3e2..69449a818dcc 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -102,7 +102,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
- if (time_status & STA_UNSYNC || set_rtc == NULL)
+ if (!ntp_synced() || set_rtc == NULL)
return;
if (next_rtc_update &&
@@ -292,10 +292,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
@@ -433,10 +430,12 @@ void timer_dyn_reprogram(void)
{
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
- write_seqlock(&xtime_lock);
- if (dyn_tick->state & DYN_TICK_ENABLED)
- dyn_tick->reprogram(next_timer_interrupt() - jiffies);
- write_sequnlock(&xtime_lock);
+ if (dyn_tick) {
+ write_seqlock(&xtime_lock);
+ if (dyn_tick->state & DYN_TICK_ENABLED)
+ dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+ write_sequnlock(&xtime_lock);
+ }
}
static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
index 4c38abdbe497..68117968482b 100644
--- a/arch/arm/lib/copy_page.S
+++ b/arch/arm/lib/copy_page.S
@@ -11,7 +11,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S
index 46a2dc962e9d..333bca292de9 100644
--- a/arch/arm/lib/csumpartialcopyuser.S
+++ b/arch/arm/lib/csumpartialcopyuser.S
@@ -13,7 +13,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/errno.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 64aa6f4fe5e4..d204018070a4 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -26,7 +26,7 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000.
* Note also that it is intended that __get_user_bad is not global.
*/
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index b09398d95aac..4593e9c07f05 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -26,7 +26,7 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000
* Note also that it is intended that __put_user_bad is not global.
*/
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index 112f1d68fb2b..e216ab8b9e8f 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -354,7 +354,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 23c4da10101b..5aeadfd72143 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -219,7 +219,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c
index 7daa021676d0..44c56571d183 100644
--- a/arch/arm/mach-epxa10db/arch.c
+++ b/arch/arm/mach-epxa10db/arch.c
@@ -52,7 +52,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index 324d9edeec38..bdd257921cfb 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -87,6 +87,7 @@ config FOOTBRIDGE_ADDIN
# EBSA285 board in either host or addin mode
config ARCH_EBSA285
+ select ARCH_MAY_HAVE_PC_FDC
bool
endif
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
index b21016070ea3..e1c43b331d64 100644
--- a/arch/arm/mach-footbridge/isa-irq.c
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -95,7 +95,7 @@ isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
}
desc = irq_desc + isa_irq;
- desc->handle(isa_irq, desc, regs);
+ desc_handle_irq(isa_irq, desc, regs);
}
static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c
index aa3a1fef563e..28846c7edaaf 100644
--- a/arch/arm/mach-footbridge/isa.c
+++ b/arch/arm/mach-footbridge/isa.c
@@ -34,7 +34,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
index 96aa3af70d86..5110e2e65ddd 100644
--- a/arch/arm/mach-h720x/common.c
+++ b/arch/arm/mach-h720x/common.c
@@ -108,7 +108,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq,
while (mask) {
if (mask & 1) {
IRQDBG("handling irq %d\n", irq);
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
}
irq++;
desc++;
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index 593b6a2a30e1..a4a7c0125d03 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -90,7 +90,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
@@ -126,7 +126,7 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
desc = irq_desc + irq;
while (mask) {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index 0c2713426dfd..eeb8a6d4a399 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -152,7 +152,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
while (mask) {
if (mask & 1) {
DEBUG_IRQ("handling irq %d\n", irq);
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
}
irq++;
desc++;
@@ -214,7 +214,7 @@ static struct irqchip imx_gpio_chip = {
.ack = imx_gpio_ack_irq,
.mask = imx_gpio_mask_irq,
.unmask = imx_gpio_unmask_irq,
- .type = imx_gpio_irq_type,
+ .set_type = imx_gpio_irq_type,
};
void __init
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 569f328c479d..2be5c03ab87f 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -170,7 +170,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
irq += IRQ_SIC_START;
desc = irq_desc + irq;
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
} while (status);
}
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
index d53af1669502..0039793b694a 100644
--- a/arch/arm/mach-iop3xx/iop321-time.c
+++ b/arch/arm/mach-iop3xx/iop321-time.c
@@ -60,7 +60,7 @@ static unsigned long iop321_gettimeoffset(void)
/*
* Now convert them to usec.
*/
- usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+ usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
index 1a6d9d661e4b..8eddfac7e2b0 100644
--- a/arch/arm/mach-iop3xx/iop331-time.c
+++ b/arch/arm/mach-iop3xx/iop331-time.c
@@ -58,7 +58,7 @@ static unsigned long iop331_gettimeoffset(void)
/*
* Now convert them to usec.
*/
- usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+ usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 45b18658499f..74bd2fd602d4 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -174,7 +174,7 @@ static struct resource ixp2000_uart_resource = {
static struct platform_device ixp2000_serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = ixp2000_serial_port,
},
@@ -317,7 +317,7 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, str
for (i = 0; i <= 7; i++) {
if (status & (1<<i)) {
desc = irq_desc + i + IRQ_IXP2000_GPIO0;
- desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
+ desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs);
}
}
}
@@ -380,10 +380,10 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
}
static struct irqchip ixp2000_GPIO_irq_chip = {
- .type = ixp2000_GPIO_irq_type,
- .ack = ixp2000_GPIO_irq_mask_ack,
- .mask = ixp2000_GPIO_irq_mask,
- .unmask = ixp2000_GPIO_irq_unmask
+ .ack = ixp2000_GPIO_irq_mask_ack,
+ .mask = ixp2000_GPIO_irq_mask,
+ .unmask = ixp2000_GPIO_irq_unmask,
+ .set_type = ixp2000_GPIO_irq_type,
};
static void ixp2000_pci_irq_mask(unsigned int irq)
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index a43369ad876c..63ba0191aa65 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -133,7 +133,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct
struct irqdesc *cpld_desc;
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
cpld_desc = irq_desc + cpld_irq;
- cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ desc_handle_irq(cpld_irq, cpld_desc, regs);
}
}
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 43447dad1657..7a5109921287 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -82,7 +82,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct
struct irqdesc *cpld_desc;
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
cpld_desc = irq_desc + cpld_irq;
- cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ desc_handle_irq(cpld_irq, cpld_desc, regs);
}
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 04490a9f8f6e..52ad11328e96 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -38,90 +38,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-enum ixp4xx_irq_type {
- IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
-};
-static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
-
-/*************************************************************************
- * GPIO acces functions
- *************************************************************************/
-
-/*
- * Configure GPIO line for input, interrupt, or output operation
- *
- * TODO: Enable/disable the irq_desc based on interrupt or output mode.
- * TODO: Should these be named ixp4xx_gpio_?
- */
-void gpio_line_config(u8 line, u32 style)
-{
- static const int gpio2irq[] = {
- 6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
- };
- u32 enable;
- volatile u32 *int_reg;
- u32 int_style;
- enum ixp4xx_irq_type irq_type;
-
- enable = *IXP4XX_GPIO_GPOER;
-
- if (style & IXP4XX_GPIO_OUT) {
- enable &= ~((1) << line);
- } else if (style & IXP4XX_GPIO_IN) {
- enable |= ((1) << line);
-
- switch (style & IXP4XX_GPIO_INTSTYLE_MASK)
- {
- case (IXP4XX_GPIO_ACTIVE_HIGH):
- int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
- irq_type = IXP4XX_IRQ_LEVEL;
- break;
- case (IXP4XX_GPIO_ACTIVE_LOW):
- int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
- irq_type = IXP4XX_IRQ_LEVEL;
- break;
- case (IXP4XX_GPIO_RISING_EDGE):
- int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- case (IXP4XX_GPIO_FALLING_EDGE):
- int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- case (IXP4XX_GPIO_TRANSITIONAL):
- int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- default:
- int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
- irq_type = IXP4XX_IRQ_LEVEL;
- break;
- }
-
- if (style & IXP4XX_GPIO_INTSTYLE_MASK)
- ixp4xx_config_irq(gpio2irq[line], irq_type);
-
- if (line >= 8) { /* pins 8-15 */
- line -= 8;
- int_reg = IXP4XX_GPIO_GPIT2R;
- }
- else { /* pins 0-7 */
- int_reg = IXP4XX_GPIO_GPIT1R;
- }
-
- /* Clear the style for the appropriate pin */
- *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
- (line * IXP4XX_GPIO_STYLE_SIZE));
-
- /* Set the new style */
- *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
- }
-
- *IXP4XX_GPIO_GPOER = enable;
-}
-
-EXPORT_SYMBOL(gpio_line_config);
-
/*************************************************************************
* IXP4xx chipset I/O mapping
*************************************************************************/
@@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void)
* (be it PCI or something else) configures that GPIO line
* as an IRQ.
**************************************************************************/
+enum ixp4xx_irq_type {
+ IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
+};
+
+static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
+
+/*
+ * IRQ -> GPIO mapping table
+ */
+static int 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,
+ 7, 8, 9, 10, 11, 12, -1, -1,
+};
+
+static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
+{
+ int line = irq2gpio[irq];
+ u32 int_style;
+ enum ixp4xx_irq_type irq_type;
+ volatile u32 *int_reg;
+
+ /*
+ * Only for GPIO IRQs
+ */
+ if (line < 0)
+ return -EINVAL;
+
+ if (type & IRQT_BOTHEDGE) {
+ int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
+ irq_type = IXP4XX_IRQ_EDGE;
+ } else if (type & IRQT_RISING) {
+ int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
+ irq_type = IXP4XX_IRQ_EDGE;
+ } else if (type & IRQT_FALLING) {
+ int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
+ irq_type = IXP4XX_IRQ_EDGE;
+ } else if (type & IRQT_HIGH) {
+ int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+ irq_type = IXP4XX_IRQ_LEVEL;
+ } else if (type & IRQT_LOW) {
+ int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
+ irq_type = IXP4XX_IRQ_LEVEL;
+ }
+
+ ixp4xx_config_irq(irq, irq_type);
+
+ if (line >= 8) { /* pins 8-15 */
+ line -= 8;
+ int_reg = IXP4XX_GPIO_GPIT2R;
+ } else { /* pins 0-7 */
+ int_reg = IXP4XX_GPIO_GPIT1R;
+ }
+
+ /* Clear the style for the appropriate pin */
+ *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
+ (line * IXP4XX_GPIO_STYLE_SIZE));
+
+ /* Set the new style */
+ *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
+}
+
static void ixp4xx_irq_mask(unsigned int irq)
{
if (cpu_is_ixp46x() && irq >= 32)
@@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq)
static void ixp4xx_irq_ack(unsigned int irq)
{
- static int 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,
- 7, 8, 9, 10, 11, 12, -1, -1,
- };
int line = (irq < 32) ? irq2gpio[irq] : -1;
if (line >= 0)
@@ -206,15 +179,17 @@ static void ixp4xx_irq_level_unmask(unsigned int irq)
}
static struct irqchip ixp4xx_irq_level_chip = {
- .ack = ixp4xx_irq_mask,
- .mask = ixp4xx_irq_mask,
- .unmask = ixp4xx_irq_level_unmask,
+ .ack = ixp4xx_irq_mask,
+ .mask = ixp4xx_irq_mask,
+ .unmask = ixp4xx_irq_level_unmask,
+ .set_type = ixp4xx_set_irq_type,
};
static struct irqchip ixp4xx_irq_edge_chip = {
- .ack = ixp4xx_irq_ack,
- .mask = ixp4xx_irq_mask,
- .unmask = ixp4xx_irq_unmask,
+ .ack = ixp4xx_irq_ack,
+ .mask = ixp4xx_irq_mask,
+ .unmask = ixp4xx_irq_unmask,
+ .set_type = ixp4xx_set_irq_type,
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index afafb42ae129..60de8a94cff5 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
void __init coyote_pci_preinit(void)
{
- gpio_line_config(COYOTE_PCI_SLOT0_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-
- gpio_line_config(COYOTE_PCI_SLOT1_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
+ set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
+ set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 411ea9996190..050c92768913 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -24,11 +24,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-void __init coyote_map_io(void)
-{
- ixp4xx_map_io();
-}
-
static struct flash_platform_data coyote_flash_data = {
.map_name = "cfi_probe",
.width = 2,
@@ -71,7 +66,7 @@ static struct plat_serial8250_port coyote_uart_data[] = {
static struct platform_device coyote_uart = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = coyote_uart_data,
},
@@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = coyote_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
@@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = coyote_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index b18035824e3e..a66484b63d36 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void);
extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
- /*
- * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
- * Slot 0 isn't actually populated with a card connector but
- * we initialize it anyway in case a future version has the
- * slot populated or someone with good soldering skills has
- * some free time.
- */
-
-
-static void gtwx5715_init_gpio(u8 pin, u32 style)
-{
- gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW);
-
- if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin);
-}
+/*
+ * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
+ * Slot 0 isn't actually populated with a card connector but
+ * we initialize it anyway in case a future version has the
+ * slot populated or someone with good soldering skills has
+ * some free time.
+ */
void __init gtwx5715_pci_preinit(void)
{
- gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN);
- gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN);
+ set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
+ set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
+ set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
+ set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
ixp4xx_pci_preinit();
}
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 333459d6aa46..29a6d02fa851 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -93,7 +93,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
static struct platform_device gtwx5715_uart_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = gtwx5715_uart_platform_data,
},
@@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = {
.resource = gtwx5715_uart_resources,
};
-
-void __init gtwx5715_map_io(void)
-{
- ixp4xx_map_io();
-}
-
static struct flash_platform_data gtwx5715_flash_data = {
.map_name = "cfi_probe",
.width = 2,
@@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_UART2_BASE_PHYS,
.io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = gtwx5715_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index c2ab9ebb5980..f9a1d3e7d692 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -27,14 +27,10 @@
void __init ixdp425_pci_preinit(void)
{
- gpio_line_config(IXDP425_PCI_INTA_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(IXDP425_PCI_INTB_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(IXDP425_PCI_INTC_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(IXDP425_PCI_INTD_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
+ set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
+ set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
+ set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
+ set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index fa0646c8693b..ae1fa099d5fa 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -24,11 +24,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-void __init ixdp425_map_io(void)
-{
- ixp4xx_map_io();
-}
-
static struct flash_platform_data ixdp425_flash_data = {
.map_name = "cfi_probe",
.width = 2,
@@ -101,7 +96,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = {
static struct platform_device ixdp425_uart = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev.platform_data = ixdp425_uart_data,
.num_resources = 2,
.resource = ixdp425_uart_resources
@@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = ixdp425_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
@@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = ixdp425_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
@@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = ixdp425_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
@@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
.phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = ixdp425_map_io,
+ .map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
.boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index ce4563f00676..fe5e7660de1d 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
void __init ixdpg425_pci_preinit(void)
{
- gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
+ set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
gpio_line_isr_clear(6);
gpio_line_isr_clear(7);
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index beda7c2602fb..578a52461fdb 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -13,4 +13,4 @@ extern struct sys_timer lh7a40x_timer;
extern void lh7a400_init_irq (void);
extern void lh7a404_init_irq (void);
-#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
+#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 7408ac94f771..27fc2e8e5fca 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -47,6 +47,14 @@ config MACH_OMAP_OSK
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
+config OMAP_OSK_MISTRAL
+ bool "Mistral QVGA board Support"
+ depends on MACH_OMAP_OSK
+ help
+ The OSK supports an optional add-on board with a Quarter-VGA
+ touchscreen, PDA-ish buttons, a resume button, bicolor LED,
+ and camera connector. Say Y here if you have this board.
+
config MACH_OMAP_PERSEUS2
bool "TI Perseus2"
depends on ARCH_OMAP1 && ARCH_OMAP730
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index d386fd913f0c..181a93deaaee 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := io.o id.o irq.o time.o serial.o
+obj-y := io.o id.o irq.o time.o serial.o devices.o
led-y := leds.o
# Specific board support
@@ -23,6 +23,7 @@ endif
# LEDs support
led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
+led-$(CONFIG_MACH_OMAP_H3) += leds-h2p2-debug.o
led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 122796ebe8f5..c209c7172a9a 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -48,19 +48,43 @@ static struct omap_usb_config generic1510_usb_config __initdata = {
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_usb_config generic1610_usb_config __initdata = {
+#ifdef CONFIG_USB_OTG
+ .otg = 1,
+#endif
.register_host = 1,
.register_dev = 1,
.hmc_mode = 16,
.pins[0] = 6,
};
+
+static struct omap_mmc_config generic_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,
+ },
+};
+
#endif
static struct omap_board_config_kernel generic_config[] = {
{ OMAP_TAG_USB, NULL },
+ { OMAP_TAG_MMC, &generic_mmc_config },
};
static void __init omap_generic_init(void)
{
+ const struct omap_uart_config *uart_conf;
+
/*
* Make sure the serial ports are muxed on at this point.
* You have to mux them off in device drivers later on
@@ -76,6 +100,18 @@ static void __init omap_generic_init(void)
generic_config[0].data = &generic1610_usb_config;
}
#endif
+
+ uart_conf = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
+ if (uart_conf != NULL) {
+ unsigned int enabled_ports, i;
+
+ enabled_ports = uart_conf->enabled_uarts;
+ for (i = 0; i < 3; i++) {
+ if (!(enabled_ports & (1 << i)))
+ generic_serial_ports[i] = 0;
+ }
+ }
+
omap_board_config = generic_config;
omap_board_config_size = ARRAY_SIZE(generic_config);
omap_serial_init(generic_serial_ports);
@@ -83,7 +119,7 @@ static void __init omap_generic_init(void)
static void __init omap_generic_map_io(void)
{
- omap_map_common_io()
+ omap_map_common_io();
}
MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index f4983ee95ab4..d46a70063b0c 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -33,6 +33,7 @@
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
#include <asm/arch/common.h>
@@ -80,8 +81,7 @@ static struct flash_platform_data h2_flash_data = {
};
static struct resource h2_flash_resource = {
- .start = OMAP_CS2B_PHYS,
- .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
+ /* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
@@ -126,10 +126,9 @@ static void __init h2_init_smc91x(void)
printk("Error requesting gpio 0 for smc91x irq\n");
return;
}
- omap_set_gpio_edge_ctrl(0, OMAP_GPIO_FALLING_EDGE);
}
-void h2_init_irq(void)
+static void __init h2_init_irq(void)
{
omap_init_irq();
omap_gpio_init();
@@ -152,9 +151,13 @@ static struct omap_usb_config h2_usb_config __initdata = {
};
static struct omap_mmc_config h2_mmc_config __initdata = {
- .mmc_blocks = 1,
- .mmc1_power_pin = -1, /* tps65010 gpio3 */
- .mmc1_switch_pin = OMAP_MPUIO(1),
+ .mmc [0] = {
+ .enabled = 1,
+ .wire4 = 1,
+ .wp_pin = OMAP_MPUIO(3),
+ .power_pin = -1, /* tps65010 gpio3 */
+ .switch_pin = OMAP_MPUIO(1),
+ },
};
static struct omap_board_config_kernel h2_config[] = {
@@ -164,6 +167,16 @@ 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.
+ */
+ h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
+ h2_flash_resource.end += SZ_32M - 1;
+
+ /* MMC: card detect and WP */
+ // omap_cfg_reg(U19_ARMIO1); /* CD */
+ omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */
+
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 7cd419d61b40..2798613696fa 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -82,8 +82,7 @@ static struct flash_platform_data h3_flash_data = {
};
static struct resource h3_flash_resource = {
- .start = OMAP_CS2B_PHYS,
- .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
+ /* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
@@ -161,13 +160,26 @@ static struct omap_usb_config h3_usb_config __initdata = {
.pins[1] = 3,
};
+static struct omap_mmc_config h3_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 1,
+ .power_pin = -1, /* tps65010 GPIO4 */
+ .switch_pin = OMAP_MPUIO(1),
+ },
+};
+
static struct omap_board_config_kernel h3_config[] = {
{ OMAP_TAG_USB, &h3_usb_config },
+ { OMAP_TAG_MMC, &h3_mmc_config },
};
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));
+ omap_board_config = h3_config;
+ omap_board_config_size = ARRAY_SIZE(h3_config);
}
static void __init h3_init_smc91x(void)
@@ -177,7 +189,6 @@ static void __init h3_init_smc91x(void)
printk("Error requesting gpio 40 for smc91x irq\n");
return;
}
- omap_set_gpio_edge_ctrl(40, OMAP_GPIO_FALLING_EDGE);
}
void h3_init_irq(void)
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 91de60a91ef8..df0312b596e4 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -29,6 +29,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
+#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
#include <asm/arch/gpio.h>
#include <asm/arch/tc.h>
@@ -173,7 +174,6 @@ static void __init innovator_init_smc91x(void)
printk("Error requesting gpio 0 for smc91x irq\n");
return;
}
- omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE);
}
}
@@ -220,8 +220,19 @@ static struct omap_usb_config h2_usb_config __initdata = {
};
#endif
+static struct omap_mmc_config innovator_mmc_config __initdata = {
+ .mmc [0] = {
+ .enabled = 1,
+ .wire4 = 1,
+ .wp_pin = OMAP_MPUIO(3),
+ .power_pin = -1, /* FPGA F3 UIO42 */
+ .switch_pin = -1, /* FPGA F4 UIO43 */
+ },
+};
+
static struct omap_board_config_kernel innovator_config[] = {
{ OMAP_TAG_USB, NULL },
+ { OMAP_TAG_MMC, &innovator_mmc_config },
};
static void __init innovator_init(void)
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
index 6750b2014092..d904e643f5ec 100644
--- a/arch/arm/mach-omap1/board-netstar.c
+++ b/arch/arm/mach-omap1/board-netstar.c
@@ -75,16 +75,15 @@ static void __init netstar_init(void)
mdelay(50); /* 50ms until PHY ready */
/* smc91x interrupt pin */
omap_request_gpio(8);
- omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
omap_request_gpio(12);
omap_request_gpio(13);
omap_request_gpio(14);
omap_request_gpio(15);
- omap_set_gpio_edge_ctrl(12, OMAP_GPIO_FALLING_EDGE);
- omap_set_gpio_edge_ctrl(13, OMAP_GPIO_FALLING_EDGE);
- omap_set_gpio_edge_ctrl(14, OMAP_GPIO_FALLING_EDGE);
- omap_set_gpio_edge_ctrl(15, OMAP_GPIO_FALLING_EDGE);
+ 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));
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 6844e536c698..21103df50415 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -29,11 +29,16 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
#include <asm/arch/usb.h>
@@ -41,12 +46,56 @@
#include <asm/arch/tc.h>
#include <asm/arch/common.h>
-static struct map_desc osk5912_io_desc[] __initdata = {
-{ OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
- MT_DEVICE },
+static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
+
+static struct mtd_partition osk_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ }, {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
};
-static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
+static struct flash_platform_data osk_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = osk_partitions,
+ .nr_parts = ARRAY_SIZE(osk_partitions),
+};
+
+static struct resource osk_flash_resource = {
+ /* this is on CS3, wherever it's mapped */
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device osk5912_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &osk_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &osk_flash_resource,
+};
static struct resource osk5912_smc91x_resources[] = {
[0] = {
@@ -86,9 +135,16 @@ static struct platform_device osk5912_cf_device = {
.resource = osk5912_cf_resources,
};
+static struct platform_device osk5912_mcbsp1_device = {
+ .name = "omap_mcbsp",
+ .id = 1,
+};
+
static struct platform_device *osk5912_devices[] __initdata = {
+ &osk5912_flash_device,
&osk5912_smc91x_device,
&osk5912_cf_device,
+ &osk5912_mcbsp1_device,
};
static void __init osk_init_smc91x(void)
@@ -97,7 +153,6 @@ static void __init osk_init_smc91x(void)
printk("Error requesting gpio 0 for smc91x irq\n");
return;
}
- omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE);
/* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */
EMIFS_CCS(1) |= 0x2;
@@ -110,11 +165,11 @@ static void __init osk_init_cf(void)
printk("Error requesting gpio 62 for CF irq\n");
return;
}
- /* it's really active-low */
- omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE);
+ /* the CF I/O IRQ is really active-low */
+ set_irq_type(OMAP_GPIO_IRQ(62), IRQT_FALLING);
}
-void osk_init_irq(void)
+static void __init osk_init_irq(void)
{
omap_init_irq();
omap_gpio_init();
@@ -142,18 +197,69 @@ static struct omap_board_config_kernel osk_config[] = {
{ OMAP_TAG_USB, &osk_usb_config },
};
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+
+#ifdef CONFIG_PM
+static irqreturn_t
+osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+ return IRQ_HANDLED;
+}
+#endif
+
+static void __init osk_mistral_init(void)
+{
+ /* FIXME here's where to feed in framebuffer, touchpad, and
+ * keyboard setup ... not in the drivers for those devices!
+ *
+ * NOTE: we could actually tell if there's a Mistral board
+ * attached, e.g. by trying to read something from the ads7846.
+ * But this is too early for that...
+ */
+
+ /* the sideways button (SW1) is for use as a "wakeup" button */
+ omap_cfg_reg(N15_1610_MPUIO2);
+ if (omap_request_gpio(OMAP_MPUIO(2)) == 0) {
+ int ret = 0;
+ omap_set_gpio_direction(OMAP_MPUIO(2), 1);
+ set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
+#ifdef CONFIG_PM
+ /* share the IRQ in case someone wants to use the
+ * button for more than wakeup from system sleep.
+ */
+ ret = request_irq(OMAP_GPIO_IRQ(OMAP_MPUIO(2)),
+ &osk_mistral_wake_interrupt,
+ SA_SHIRQ, "mistral_wakeup",
+ &osk_mistral_wake_interrupt);
+ if (ret != 0) {
+ omap_free_gpio(OMAP_MPUIO(2));
+ printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
+ ret);
+ } else
+ enable_irq_wake(OMAP_GPIO_IRQ(OMAP_MPUIO(2)));
+#endif
+ } else
+ printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n");
+}
+#else
+static void __init osk_mistral_init(void) { }
+#endif
+
static void __init osk_init(void)
{
+ 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));
omap_board_config = osk_config;
omap_board_config_size = ARRAY_SIZE(osk_config);
USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
+
+ osk_mistral_init();
}
static void __init osk_map_io(void)
{
omap_map_common_io();
- iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
omap_serial_init(osk_serial_ports);
}
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 213317392d9b..107c68c8ab54 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -24,6 +24,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
+#include <asm/arch/tc.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
@@ -83,8 +84,8 @@ static struct flash_platform_data p2_flash_data = {
};
static struct resource p2_flash_resource = {
- .start = OMAP_FLASH_0_START,
- .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1,
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index e42281988990..bf30b1acda0b 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -25,13 +25,14 @@
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
#include <asm/mach/map.h>
+#include <asm/arch/common.h>
#include <asm/arch/gpio.h>
-#include <asm/arch/tc.h>
#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
extern void omap_init_time(void);
extern int omap_gpio_init(void);
@@ -74,7 +75,7 @@ static struct plat_serial8250_port voiceblue_ports[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 1,
+ .id = PLAT8250_DEV_PLATFORM1,
.dev = {
.platform_data = voiceblue_ports,
},
@@ -86,6 +87,27 @@ static int __init ext_uart_init(void)
}
arch_initcall(ext_uart_init);
+static struct flash_platform_data voiceblue_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+};
+
+static struct resource voiceblue_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device voiceblue_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &voiceblue_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &voiceblue_flash_resource,
+};
+
static struct resource voiceblue_smc91x_resources[] = {
[0] = {
.start = OMAP_CS2_PHYS + 0x300,
@@ -107,6 +129,7 @@ static struct platform_device voiceblue_smc91x_device = {
};
static struct platform_device *voiceblue_devices[] __initdata = {
+ &voiceblue_flash_device,
&voiceblue_smc91x_device,
};
@@ -119,8 +142,17 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
.pins[2] = 6,
};
+static struct omap_mmc_config voiceblue_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 1,
+ .power_pin = 2,
+ .switch_pin = -1,
+ },
+};
+
static struct omap_board_config_kernel voiceblue_config[] = {
{ OMAP_TAG_USB, &voiceblue_usb_config },
+ { OMAP_TAG_MMC, &voiceblue_mmc_config },
};
static void __init voiceblue_init_irq(void)
@@ -131,9 +163,6 @@ static void __init voiceblue_init_irq(void)
static void __init voiceblue_init(void)
{
- /* There is a good chance board is going up, so enable Power LED
- * (it is connected through invertor) */
- omap_writeb(0x00, OMAP_LPG1_LCR);
/* Watchdog */
omap_request_gpio(0);
/* smc91x reset */
@@ -145,7 +174,6 @@ static void __init voiceblue_init(void)
mdelay(50); /* 50ms until PHY ready */
/* smc91x interrupt pin */
omap_request_gpio(8);
- omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
/* 16C554 reset*/
omap_request_gpio(6);
omap_set_gpio_direction(6, 0);
@@ -155,14 +183,19 @@ static void __init voiceblue_init(void)
omap_request_gpio(13);
omap_request_gpio(14);
omap_request_gpio(15);
- omap_set_gpio_edge_ctrl(12, OMAP_GPIO_RISING_EDGE);
- omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
- omap_set_gpio_edge_ctrl(14, OMAP_GPIO_RISING_EDGE);
- omap_set_gpio_edge_ctrl(15, OMAP_GPIO_RISING_EDGE);
+ set_irq_type(OMAP_GPIO_IRQ(12), IRQT_RISING);
+ set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
+ set_irq_type(OMAP_GPIO_IRQ(14), IRQT_RISING);
+ set_irq_type(OMAP_GPIO_IRQ(15), IRQT_RISING);
platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
omap_board_config = voiceblue_config;
omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+
+ /* There is a good chance board is going up, so enable power LED
+ * (it is connected through invertor) */
+ omap_writeb(0x00, OMAP_LPG1_LCR);
+ omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
}
static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
@@ -184,9 +217,9 @@ static int panic_event(struct notifier_block *this, unsigned long event,
if (test_and_set_bit(MACHINE_PANICED, &machine_state))
return NOTIFY_DONE;
- /* Flash Power LED
- * (TODO: Enable clock right way (enabled in bootloader already)) */
+ /* Flash power LED */
omap_writeb(0x78, OMAP_LPG1_LCR);
+ omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
return NOTIFY_DONE;
}
@@ -195,15 +228,14 @@ static struct notifier_block panic_block = {
.notifier_call = panic_event,
};
-static int __init setup_notifier(void)
+static int __init voiceblue_setup(void)
{
/* Setup panic notifier */
notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
-
-postcore_initcall(setup_notifier);
+postcore_initcall(voiceblue_setup);
static int wdt_gpio_state;
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
new file mode 100644
index 000000000000..e8b3981444cd
--- /dev/null
+++ b/arch/arm/mach-omap1/devices.c
@@ -0,0 +1,351 @@
+/*
+ * linux/arch/arm/mach-omap1/devices.c
+ *
+ * OMAP1 platform device setup/initialization
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+
+
+static void omap_nop_release(struct device *dev)
+{
+ /* Nothing */
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+
+#define OMAP_I2C_BASE 0xfffb3800
+
+static struct resource i2c_resources[] = {
+ {
+ .start = OMAP_I2C_BASE,
+ .end = OMAP_I2C_BASE + 0x3f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* DMA not used; works around erratum writing to non-empty i2c fifo */
+
+static struct platform_device omap_i2c_device = {
+ .name = "i2c_omap",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(i2c_resources),
+ .resource = i2c_resources,
+};
+
+static void omap_init_i2c(void)
+{
+ /* FIXME define and use a boot tag, in case of boards that
+ * either don't wire up I2C, or chips that mux it differently...
+ * it can include clocking and address info, maybe more.
+ */
+ omap_cfg_reg(I2C_SCL);
+ omap_cfg_reg(I2C_SDA);
+
+ (void) platform_device_register(&omap_i2c_device);
+}
+#else
+static inline void omap_init_i2c(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
+
+static u64 irda_dmamask = 0xffffffff;
+
+static struct platform_device omap1610ir_device = {
+ .name = "omap1610-ir",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ .dma_mask = &irda_dmamask,
+ },
+};
+
+static void omap_init_irda(void)
+{
+ /* FIXME define and use a boot tag, members something like:
+ * u8 uart; // uart1, or uart3
+ * ... but driver only handles uart3 for now
+ * s16 fir_sel; // gpio for SIR vs FIR
+ * ... may prefer a callback for SIR/MIR/FIR mode select;
+ * while h2 uses a GPIO, H3 uses a gpio expander
+ */
+ if (machine_is_omap_h2()
+ || machine_is_omap_h3())
+ (void) platform_device_register(&omap1610ir_device);
+}
+#else
+static inline void omap_init_irda(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+#define OMAP_MMC1_BASE 0xfffb7800
+#define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */
+
+static struct omap_mmc_conf mmc1_conf;
+
+static u64 mmc1_dmamask = 0xffffffff;
+
+static struct resource mmc1_resources[] = {
+ {
+ .start = IO_ADDRESS(OMAP_MMC1_BASE),
+ .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_MMC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+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,
+ },
+ .num_resources = ARRAY_SIZE(mmc1_resources),
+ .resource = mmc1_resources,
+};
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+static struct omap_mmc_conf mmc2_conf;
+
+static u64 mmc2_dmamask = 0xffffffff;
+
+static struct resource mmc2_resources[] = {
+ {
+ .start = IO_ADDRESS(OMAP_MMC2_BASE),
+ .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_MMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+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,
+ },
+ .num_resources = ARRAY_SIZE(mmc2_resources),
+ .resource = mmc2_resources,
+};
+#endif
+
+static void __init omap_init_mmc(void)
+{
+ const struct omap_mmc_config *mmc_conf;
+ const struct omap_mmc_conf *mmc;
+
+ /* NOTE: assumes MMC was never (wrongly) enabled */
+ mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
+ if (!mmc_conf)
+ return;
+
+ /* block 1 is always available and has just one pinout option */
+ mmc = &mmc_conf->mmc[0];
+ if (mmc->enabled) {
+ omap_cfg_reg(MMC_CMD);
+ omap_cfg_reg(MMC_CLK);
+ omap_cfg_reg(MMC_DAT0);
+ if (cpu_is_omap1710()) {
+ omap_cfg_reg(M15_1710_MMC_CLKI);
+ omap_cfg_reg(P19_1710_MMC_CMDDIR);
+ omap_cfg_reg(P20_1710_MMC_DATDIR0);
+ }
+ if (mmc->wire4) {
+ omap_cfg_reg(MMC_DAT1);
+ /* NOTE: DAT2 can be on W10 (here) or M15 */
+ if (!mmc->nomux)
+ omap_cfg_reg(MMC_DAT2);
+ omap_cfg_reg(MMC_DAT3);
+ }
+ mmc1_conf = *mmc;
+ (void) platform_device_register(&mmc_omap_device1);
+ }
+
+#ifdef CONFIG_ARCH_OMAP16XX
+ /* block 2 is on newer chips, and has many pinout options */
+ mmc = &mmc_conf->mmc[1];
+ if (mmc->enabled) {
+ if (!mmc->nomux) {
+ omap_cfg_reg(Y8_1610_MMC2_CMD);
+ omap_cfg_reg(Y10_1610_MMC2_CLK);
+ omap_cfg_reg(R18_1610_MMC2_CLKIN);
+ omap_cfg_reg(W8_1610_MMC2_DAT0);
+ if (mmc->wire4) {
+ omap_cfg_reg(V8_1610_MMC2_DAT1);
+ omap_cfg_reg(W15_1610_MMC2_DAT2);
+ omap_cfg_reg(R10_1610_MMC2_DAT3);
+ }
+
+ /* These are needed for the level shifter */
+ omap_cfg_reg(V9_1610_MMC2_CMDDIR);
+ omap_cfg_reg(V5_1610_MMC2_DATDIR0);
+ omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+ }
+
+ /* Feedback clock must be set on OMAP-1710 MMC2 */
+ if (cpu_is_omap1710())
+ omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
+ MOD_CONF_CTRL_1);
+ mmc2_conf = *mmc;
+ (void) platform_device_register(&mmc_omap_device2);
+ }
+#endif
+ return;
+}
+#else
+static inline void omap_init_mmc(void) {}
+#endif
+
+#if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC)
+
+#define OMAP_RTC_BASE 0xfffb4800
+
+static struct resource rtc_resources[] = {
+ {
+ .start = OMAP_RTC_BASE,
+ .end = OMAP_RTC_BASE + 0x5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_RTC_TIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+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,
+};
+
+static void omap_init_rtc(void)
+{
+ (void) platform_device_register(&omap_rtc_device);
+}
+#else
+static inline void omap_init_rtc(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE)
+
+#define OMAP_WDT_BASE 0xfffeb000
+
+static struct resource wdt_resources[] = {
+ {
+ .start = OMAP_WDT_BASE,
+ .end = OMAP_WDT_BASE + 0x4f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device omap_wdt_device = {
+ .name = "omap1610_wdt",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(wdt_resources),
+ .resource = wdt_resources,
+};
+
+static void omap_init_wdt(void)
+{
+ (void) platform_device_register(&omap_wdt_device);
+}
+#else
+static inline void omap_init_wdt(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):
+ *
+ * (a) Does any "standard config" pin muxing needed. Board-specific
+ * code will have muxed GPIO pins and done "nonstandard" setup;
+ * that code could live in the boot loader.
+ * (b) Populating board-specific platform_data with the data drivers
+ * rely on to handle wiring variations.
+ * (c) Creating platform devices as meaningful on this board and
+ * with this kernel configuration.
+ *
+ * Claiming GPIOs, and setting their direction and initial values, is the
+ * responsibility of the device drivers. So is responding to probe().
+ *
+ * Board-specific knowlege like creating devices or pin setup is to be
+ * kept out of drivers as much as possible. In particular, pin setup
+ * may be handled by the boot loader, and drivers should expect it will
+ * normally have been done by the time they're probed.
+ */
+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_i2c();
+ omap_init_irda();
+ omap_init_mmc();
+ omap_init_rtc();
+ omap_init_wdt();
+
+ return 0;
+}
+arch_initcall(omap_init_devices);
+
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 7c08f6c2e1d0..aca2a120813a 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/fpga.c
+ * linux/arch/arm/mach-omap1/fpga.c
*
* Interrupt handler for OMAP-1510 Innovator FPGA
*
@@ -102,7 +102,7 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
fpga_irq++, stat >>= 1) {
if (stat & 1) {
d = irq_desc + fpga_irq;
- d->handle(fpga_irq, d, regs);
+ desc_handle_irq(fpga_irq, d, regs);
}
}
}
@@ -181,7 +181,7 @@ void omap1510_fpga_init_irq(void)
*/
omap_request_gpio(13);
omap_set_gpio_direction(13, 1);
- omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
+ set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
}
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 207df0fe934d..eb8261d7dead 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -19,6 +19,7 @@
extern int clk_init(void);
extern void omap_check_revision(void);
+extern void omap_sram_init(void);
/*
* The machine specific code may provide the extra mapping besides the
@@ -32,7 +33,6 @@ static struct map_desc omap_io_desc[] __initdata = {
static struct map_desc omap730_io_desc[] __initdata = {
{ OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE },
{ OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
- { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE }
};
#endif
@@ -40,27 +40,13 @@ static struct map_desc omap730_io_desc[] __initdata = {
static struct map_desc omap1510_io_desc[] __initdata = {
{ OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE },
{ OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
- { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE }
};
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
-static struct map_desc omap1610_io_desc[] __initdata = {
+static struct map_desc omap16xx_io_desc[] __initdata = {
{ OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
{ OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
- { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
-};
-
-static struct map_desc omap5912_io_desc[] __initdata = {
- { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
- { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
-/*
- * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
- * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
- * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
- * can be used.
- */
- { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
};
#endif
@@ -86,14 +72,13 @@ static void __init _omap_map_io(void)
}
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
- if (cpu_is_omap1610() || cpu_is_omap1710()) {
- iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
- }
- if (cpu_is_omap5912()) {
- iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
+ if (cpu_is_omap16xx()) {
+ iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
}
#endif
+ omap_sram_init();
+
/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
* on a Posted Write in the TIPB Bridge".
*/
@@ -108,8 +93,9 @@ static void __init _omap_map_io(void)
/*
* This should only get called from board specific init
*/
-void omap_map_common_io(void)
+void __init omap_map_common_io(void)
{
if (!initialized)
_omap_map_io();
}
+
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index a11b6d807352..192ce6055faa 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/irq.c
+ * linux/arch/arm/mach-omap1/irq.c
*
* Interrupt handler for all OMAP boards
*
@@ -165,10 +165,10 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
#endif
static struct irqchip omap_irq_chip = {
- .ack = omap_mask_ack_irq,
- .mask = omap_mask_irq,
- .unmask = omap_unmask_irq,
- .wake = omap_wake_irq,
+ .ack = omap_mask_ack_irq,
+ .mask = omap_mask_irq,
+ .unmask = omap_unmask_irq,
+ .set_wake = omap_wake_irq,
};
void __init omap_init_irq(void)
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c
index ec0d8285f243..be283cda63dd 100644
--- a/arch/arm/mach-omap1/leds-h2p2-debug.c
+++ b/arch/arm/mach-omap1/leds-h2p2-debug.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/leds-h2p2-debug.c
+ * linux/arch/arm/mach-omap1/leds-h2p2-debug.c
*
* Copyright 2003 by Texas Instruments Incorporated
*
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
+#include <linux/version.h>
#include <asm/io.h>
#include <asm/hardware.h>
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c
index 8043b7d0f66e..c8ffd1ddcded 100644
--- a/arch/arm/mach-omap1/leds-innovator.c
+++ b/arch/arm/mach-omap1/leds-innovator.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/leds-innovator.c
+ * linux/arch/arm/mach-omap1/leds-innovator.c
*/
#include <linux/config.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
index 4a0e8b9d4fc3..2c8bda847c18 100644
--- a/arch/arm/mach-omap1/leds-osk.c
+++ b/arch/arm/mach-omap1/leds-osk.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/leds-osk.c
+ * linux/arch/arm/mach-omap1/leds-osk.c
*
* LED driver for OSK, and optionally Mistral QVGA, boards
*/
@@ -64,7 +64,7 @@ static void tps_work(void *unused)
static DECLARE_WORK(work, tps_work, NULL);
-#ifdef CONFIG_FB_OMAP
+#ifdef CONFIG_OMAP_OSK_MISTRAL
/* For now, all system indicators require the Mistral board, since that
* LED can be manipulated without a task context. This LED is either red,
@@ -127,7 +127,7 @@ void osk_leds_event(led_event_t evt)
hw_led_state = 0;
break;
-#ifdef CONFIG_FB_OMAP
+#ifdef CONFIG_OMAP_OSK_MISTRAL
case led_timer:
hw_led_state ^= TIMER_LED;
@@ -144,7 +144,7 @@ void osk_leds_event(led_event_t evt)
mistral_setled();
break;
-#endif /* CONFIG_FB_OMAP */
+#endif /* CONFIG_OMAP_OSK_MISTRAL */
/* "green" == tps LED1 (leftmost, normally power-good)
* works only with DC adapter, not on battery power!
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c
index 8ab21fe98e1b..5c6b1bb6e722 100644
--- a/arch/arm/mach-omap1/leds.c
+++ b/arch/arm/mach-omap1/leds.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap/leds.c
+ * linux/arch/arm/mach-omap1/leds.c
*
* OMAP LEDs dispatcher
*/
@@ -20,7 +20,9 @@ omap_leds_init(void)
if (machine_is_omap_innovator())
leds_event = innovator_leds_event;
- else if (machine_is_omap_h2() || machine_is_omap_perseus2())
+ else if (machine_is_omap_h2()
+ || machine_is_omap_h3()
+ || machine_is_omap_perseus2())
leds_event = h2p2_dbg_leds_event;
else if (machine_is_omap_osk())
@@ -30,8 +32,12 @@ omap_leds_init(void)
return -1;
if (machine_is_omap_h2()
+ || machine_is_omap_h3()
|| machine_is_omap_perseus2()
- || machine_is_omap_osk()) {
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+ || machine_is_omap_osk()
+#endif
+ ) {
/* LED1/LED2 pins can be used as GPIO (as done here), or by
* the LPG (works even in deep sleep!), to drive a bicolor
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 214e5d17c8b5..40c4f7c40e73 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -24,7 +24,11 @@
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
+#ifdef CONFIG_PM
+#include <asm/arch/pm.h>
+#endif
static struct clk * uart1_ck = NULL;
static struct clk * uart2_ck = NULL;
@@ -94,7 +98,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
@@ -193,6 +197,86 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
}
}
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+
+static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ /* Need to do something with serial port right after wake-up? */
+ return IRQ_HANDLED;
+}
+
+/*
+ * Reroutes serial RX lines to GPIO lines for the duration of
+ * sleep to allow waking up the device from serial port even
+ * in deep sleep.
+ */
+void omap_serial_wake_trigger(int enable)
+{
+ if (!cpu_is_omap16xx())
+ return;
+
+ if (uart1_ck != NULL) {
+ if (enable)
+ omap_cfg_reg(V14_16XX_GPIO37);
+ else
+ omap_cfg_reg(V14_16XX_UART1_RX);
+ }
+ if (uart2_ck != NULL) {
+ if (enable)
+ omap_cfg_reg(R9_16XX_GPIO18);
+ else
+ omap_cfg_reg(R9_16XX_UART2_RX);
+ }
+ if (uart3_ck != NULL) {
+ if (enable)
+ omap_cfg_reg(L14_16XX_GPIO49);
+ else
+ omap_cfg_reg(L14_16XX_UART3_RX);
+ }
+}
+
+static void __init omap_serial_set_port_wakeup(int gpio_nr)
+{
+ int ret;
+
+ ret = omap_request_gpio(gpio_nr);
+ if (ret < 0) {
+ printk(KERN_ERR "Could not request UART wake GPIO: %i\n",
+ gpio_nr);
+ return;
+ }
+ omap_set_gpio_direction(gpio_nr, 1);
+ set_irq_type(OMAP_GPIO_IRQ(gpio_nr), IRQT_RISING);
+ ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt,
+ 0, "serial wakeup", NULL);
+ if (ret) {
+ omap_free_gpio(gpio_nr);
+ printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n",
+ gpio_nr);
+ return;
+ }
+ enable_irq_wake(OMAP_GPIO_IRQ(gpio_nr));
+}
+
+static int __init omap_serial_wakeup_init(void)
+{
+ if (!cpu_is_omap16xx())
+ return 0;
+
+ if (uart1_ck != NULL)
+ omap_serial_set_port_wakeup(37);
+ if (uart2_ck != NULL)
+ omap_serial_set_port_wakeup(18);
+ if (uart3_ck != NULL)
+ omap_serial_set_port_wakeup(49);
+
+ return 0;
+}
+late_initcall(omap_serial_wakeup_init);
+
+#endif /* CONFIG_OMAP_SERIAL_WAKE */
+
static int __init omap_init(void)
{
return platform_device_register(&serial_device);
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index d540539c9bbb..191a9b1ee9b7 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -247,13 +247,6 @@ unsigned long long sched_clock(void)
#define OMAP_32K_TIMER_TCR 0x04
#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
-#if (32768 % HZ) != 0
-/* We cannot ignore modulo.
- * Potential error can be as high as several percent.
- */
-#define OMAP_32K_TICK_MODULO (32768 % HZ)
-static unsigned modulo_count = 0; /* Counts 1/HZ units */
-#endif
/*
* TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
@@ -296,13 +289,22 @@ static inline void omap_32k_timer_stop(void)
}
/*
- * Rounds down to nearest usec
+ * 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;
/*
@@ -315,6 +317,15 @@ static unsigned long omap_32k_timer_gettimeoffset(void)
}
/*
+ * 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
@@ -330,19 +341,6 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
now = omap_32k_sync_timer_read();
while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
-#ifdef OMAP_32K_TICK_MODULO
- /* Modulo addition may put omap_32k_last_tick ahead of now
- * and cause unwanted repetition of the while loop.
- */
- if (unlikely(now - omap_32k_last_tick == ~0))
- break;
-
- modulo_count += OMAP_32K_TICK_MODULO;
- if (modulo_count > HZ) {
- ++omap_32k_last_tick;
- modulo_count -= HZ;
- }
-#endif
omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
timer_tick(regs);
}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 405a55f2287c..3e5f69bb5ac4 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -20,40 +20,66 @@ config ARCH_PXA_IDP
select PXA25x
config PXA_SHARPSL
- bool "SHARP SL-5600 and SL-C7xx Models"
- select PXA25x
+ bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models"
select SHARP_SCOOP
select SHARP_PARAM
help
Say Y here if you intend to run this kernel on a
- Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
- SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
- handheld computer.
+ Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi),
+ SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita),
+ SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer.
endchoice
+if PXA_SHARPSL
+
+choice
+ prompt "Select target Sharp Zaurus device range"
+
+config PXA_SHARPSL_25x
+ bool "Sharp PXA25x models (SL-5600 and SL-C7xx)"
+ select PXA25x
+
+config PXA_SHARPSL_27x
+ bool "Sharp PXA270 models (SL-Cxx00)"
+ select PXA27x
+
+endchoice
+
+endif
+
endmenu
config MACH_POODLE
bool "Enable Sharp SL-5600 (Poodle) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select SHARP_LOCOMO
config MACH_CORGI
bool "Enable Sharp SL-C700 (Corgi) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_SHEPHERD
bool "Enable Sharp SL-C750 (Shepherd) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_HUSKY
bool "Enable Sharp SL-C760 (Husky) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
+config MACH_SPITZ
+ bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
+ depends PXA_SHARPSL_27x
+ select PXA_SHARP_Cxx00
+
+config MACH_BORZOI
+ bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
+ depends PXA_SHARPSL_27x
+ select PXA_SHARP_Cxx00
+
config PXA25x
bool
help
@@ -74,4 +100,9 @@ config PXA_SHARP_C7xx
help
Enable support for all Sharp C7xx models
+config PXA_SHARP_Cxx00
+ bool
+ help
+ Enable common support for Sharp Cxx00 models
+
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index efc2f657184e..f609a0f232cb 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -11,7 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
+obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o
# Support for blinky lights
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 86b862f56e7e..426c2bc517eb 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -39,9 +39,9 @@
#include <asm/mach/sharpsl_param.h>
#include <asm/hardware/scoop.h>
-#include <video/w100fb.h>
#include "generic.h"
+#include "sharpsl.h"
/*
@@ -60,6 +60,15 @@ static struct scoop_config corgi_scoop_setup = {
.io_out = CORGI_SCOOP_IO_OUT,
};
+static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
+{
+ .dev = &corgiscoop_device.dev,
+ .irq = CORGI_IRQ_GPIO_CF_IRQ,
+ .cd_irq = CORGI_IRQ_GPIO_CF_CD,
+ .cd_irq_str = "PCMCIA0 CD",
+},
+};
+
struct platform_device corgiscoop_device = {
.name = "sharp-scoop",
.id = -1,
@@ -78,7 +87,7 @@ struct platform_device corgiscoop_device = {
* also use scoop functions and this makes the power up/down order
* work correctly.
*/
-static struct platform_device corgissp_device = {
+struct platform_device corgissp_device = {
.name = "corgi-ssp",
.dev = {
.parent = &corgiscoop_device.dev,
@@ -86,72 +95,82 @@ static struct platform_device corgissp_device = {
.id = -1,
};
+struct corgissp_machinfo corgi_ssp_machinfo = {
+ .port = 1,
+ .cs_lcdcon = CORGI_GPIO_LCDCON_CS,
+ .cs_ads7846 = CORGI_GPIO_ADS7846_CS,
+ .cs_max1111 = CORGI_GPIO_MAX1111_CS,
+ .clk_lcdcon = 76,
+ .clk_ads7846 = 2,
+ .clk_max1111 = 8,
+};
+
/*
- * Corgi w100 Frame Buffer Device
+ * Corgi Backlight Device
*/
-static struct w100fb_mach_info corgi_fb_info = {
- .w100fb_ssp_send = corgi_ssp_lcdtg_send,
- .comadj = -1,
- .phadadj = -1,
+static struct corgibl_machinfo corgi_bl_machinfo = {
+ .max_intensity = 0x2f,
+ .set_bl_intensity = corgi_bl_set_intensity,
};
-static struct resource corgi_fb_resources[] = {
- [0] = {
- .start = 0x08000000,
- .end = 0x08ffffff,
- .flags = IORESOURCE_MEM,
+static struct platform_device corgibl_device = {
+ .name = "corgi-bl",
+ .dev = {
+ .parent = &corgifb_device.dev,
+ .platform_data = &corgi_bl_machinfo,
},
+ .id = -1,
};
-static struct platform_device corgifb_device = {
- .name = "w100fb",
+
+/*
+ * Corgi Keyboard Device
+ */
+static struct platform_device corgikbd_device = {
+ .name = "corgi-keyboard",
.id = -1,
- .dev = {
- .platform_data = &corgi_fb_info,
- .parent = &corgissp_device.dev,
- },
- .num_resources = ARRAY_SIZE(corgi_fb_resources),
- .resource = corgi_fb_resources,
};
/*
- * Corgi Backlight Device
+ * Corgi Touch Screen Device
*/
-static struct platform_device corgibl_device = {
- .name = "corgi-bl",
+static struct resource corgits_resources[] = {
+ [0] = {
+ .start = CORGI_IRQ_GPIO_TP_INT,
+ .end = CORGI_IRQ_GPIO_TP_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct corgits_machinfo corgi_ts_machinfo = {
+ .get_hsync_len = corgi_get_hsync_len,
+ .put_hsync = corgi_put_hsync,
+ .wait_hsync = corgi_wait_hsync,
+};
+
+static struct platform_device corgits_device = {
+ .name = "corgi-ts",
.dev = {
- .parent = &corgifb_device.dev,
+ .parent = &corgissp_device.dev,
+ .platform_data = &corgi_ts_machinfo,
},
.id = -1,
+ .num_resources = ARRAY_SIZE(corgits_resources),
+ .resource = corgits_resources,
};
/*
* MMC/SD Device
*
- * The card detect interrupt isn't debounced so we delay it by HZ/4
+ * The card detect interrupt isn't debounced so we delay it by 250ms
* to give the card a chance to fully insert/eject.
*/
-static struct mmc_detect {
- struct timer_list detect_timer;
- void *devid;
-} mmc_detect;
-
-static void mmc_detect_callback(unsigned long data)
-{
- mmc_detect_change(mmc_detect.devid);
-}
-
-static irqreturn_t corgi_mmc_detect_int(int irq, void *devid, struct pt_regs *regs)
-{
- mmc_detect.devid=devid;
- mod_timer(&mmc_detect.detect_timer, jiffies + HZ/4);
- return IRQ_HANDLED;
-}
+static struct pxamci_platform_data corgi_mci_platform_data;
-static int corgi_mci_init(struct device *dev, irqreturn_t (*unused_detect_int)(int, void *, struct pt_regs *), void *data)
+static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(int, void *, struct pt_regs *), void *data)
{
int err;
@@ -161,11 +180,9 @@ static int corgi_mci_init(struct device *dev, irqreturn_t (*unused_detect_int)(i
pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN);
pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT);
- init_timer(&mmc_detect.detect_timer);
- mmc_detect.detect_timer.function = mmc_detect_callback;
- mmc_detect.detect_timer.data = (unsigned long) &mmc_detect;
+ corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250);
- err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_mmc_detect_int, SA_INTERRUPT,
+ err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, SA_INTERRUPT,
"MMC card detect", data);
if (err) {
printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
@@ -190,20 +207,26 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
}
}
+static int corgi_mci_get_ro(struct device *dev)
+{
+ return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP);
+}
+
static void corgi_mci_exit(struct device *dev, void *data)
{
free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
- del_timer(&mmc_detect.detect_timer);
}
static struct pxamci_platform_data corgi_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
.init = corgi_mci_init,
+ .get_ro = corgi_mci_get_ro,
.setpower = corgi_mci_setpower,
.exit = corgi_mci_exit,
};
+
/*
* USB Device Controller
*/
@@ -229,18 +252,23 @@ static struct platform_device *devices[] __initdata = {
&corgiscoop_device,
&corgissp_device,
&corgifb_device,
+ &corgikbd_device,
&corgibl_device,
+ &corgits_device,
};
static void __init corgi_init(void)
{
- corgi_fb_info.comadj=sharpsl_param.comadj;
- corgi_fb_info.phadadj=sharpsl_param.phadadj;
+ corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
+ pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
pxa_set_udc_info(&udc_info);
pxa_set_mci_info(&corgi_mci_platform_data);
+ scoop_num = 1;
+ scoop_devs = &corgi_pcmcia_scoop[0];
+
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
new file mode 100644
index 000000000000..c5efcd04fcbc
--- /dev/null
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -0,0 +1,565 @@
+/*
+ * linux/drivers/video/w100fb.c
+ *
+ * Corgi/Spitz LCD Specific Code
+ *
+ * Copyright (C) 2005 Richard Purdie
+ *
+ * Connectivity:
+ * Corgi - LCD to ATI Imageon w100 (Wallaby)
+ * Spitz - LCD to PXA Framebuffer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <asm/mach-types.h>
+#include <asm/arch/akita.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/arch/spitz.h>
+#include <asm/hardware/scoop.h>
+#include <asm/mach/sharpsl_param.h>
+#include "generic.h"
+
+/* Register Addresses */
+#define RESCTL_ADRS 0x00
+#define PHACTRL_ADRS 0x01
+#define DUTYCTRL_ADRS 0x02
+#define POWERREG0_ADRS 0x03
+#define POWERREG1_ADRS 0x04
+#define GPOR3_ADRS 0x05
+#define PICTRL_ADRS 0x06
+#define POLCTRL_ADRS 0x07
+
+/* Resgister Bit Definitions */
+#define RESCTL_QVGA 0x01
+#define RESCTL_VGA 0x00
+
+#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
+#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
+#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
+
+#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
+#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
+#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
+
+#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
+#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
+#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
+#define POWER0_COM_ON 0x08 /* COM Powewr Supply ON */
+#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
+
+#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
+#define POWER0_COM_OFF 0x00 /* COM Powewr Supply OFF */
+#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
+
+#define PICTRL_INIT_STATE 0x01
+#define PICTRL_INIOFF 0x02
+#define PICTRL_POWER_DOWN 0x04
+#define PICTRL_COM_SIGNAL_OFF 0x08
+#define PICTRL_DAC_SIGNAL_OFF 0x10
+
+#define POLCTRL_SYNC_POL_FALL 0x01
+#define POLCTRL_EN_POL_FALL 0x02
+#define POLCTRL_DATA_POL_FALL 0x04
+#define POLCTRL_SYNC_ACT_H 0x08
+#define POLCTRL_EN_ACT_L 0x10
+
+#define POLCTRL_SYNC_POL_RISE 0x00
+#define POLCTRL_EN_POL_RISE 0x00
+#define POLCTRL_DATA_POL_RISE 0x00
+#define POLCTRL_SYNC_ACT_L 0x00
+#define POLCTRL_EN_ACT_H 0x00
+
+#define PHACTRL_PHASE_MANUAL 0x01
+#define DEFAULT_PHAD_QVGA (9)
+#define DEFAULT_COMADJ (125)
+
+/*
+ * This is only a psuedo I2C interface. We can't use the standard kernel
+ * routines as the interface is write only. We just assume the data is acked...
+ */
+static void lcdtg_ssp_i2c_send(u8 data)
+{
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, data);
+ udelay(10);
+}
+
+static void lcdtg_i2c_send_bit(u8 data)
+{
+ lcdtg_ssp_i2c_send(data);
+ lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(data);
+}
+
+static void lcdtg_i2c_send_start(u8 base)
+{
+ lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+ lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(base);
+}
+
+static void lcdtg_i2c_send_stop(u8 base)
+{
+ lcdtg_ssp_i2c_send(base);
+ lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
+ lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
+}
+
+static void lcdtg_i2c_send_byte(u8 base, u8 data)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (data & 0x80)
+ lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
+ else
+ lcdtg_i2c_send_bit(base);
+ data <<= 1;
+ }
+}
+
+static void lcdtg_i2c_wait_ack(u8 base)
+{
+ lcdtg_i2c_send_bit(base);
+}
+
+static void lcdtg_set_common_voltage(u8 base_data, u8 data)
+{
+ /* Set Common Voltage to M62332FP via I2C */
+ lcdtg_i2c_send_start(base_data);
+ lcdtg_i2c_send_byte(base_data, 0x9c);
+ lcdtg_i2c_wait_ack(base_data);
+ lcdtg_i2c_send_byte(base_data, 0x00);
+ lcdtg_i2c_wait_ack(base_data);
+ lcdtg_i2c_send_byte(base_data, data);
+ lcdtg_i2c_wait_ack(base_data);
+ lcdtg_i2c_send_stop(base_data);
+}
+
+/* Set Phase Adjuct */
+static void lcdtg_set_phadadj(int mode)
+{
+ int adj;
+ switch(mode) {
+ case 480:
+ case 640:
+ /* Setting for VGA */
+ adj = sharpsl_param.phadadj;
+ if (adj < 0) {
+ adj = PHACTRL_PHASE_MANUAL;
+ } else {
+ adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
+ }
+ break;
+ case 240:
+ case 320:
+ default:
+ /* Setting for QVGA */
+ adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
+ break;
+ }
+
+ corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj);
+}
+
+static int lcd_inited;
+
+static void lcdtg_hw_init(int mode)
+{
+ if (!lcd_inited) {
+ int comadj;
+
+ /* Initialize Internal Logic & Port */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE
+ | PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF);
+
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF
+ | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+
+ /* VDD(+8V), SVSS(-4V) ON */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+ mdelay(3);
+
+ /* DAC ON */
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
+ | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* INIB = H, INI = L */
+ /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
+
+ /* Set Common Voltage */
+ comadj = sharpsl_param.comadj;
+ if (comadj < 0)
+ comadj = DEFAULT_COMADJ;
+ lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
+
+ /* VCC5 ON, DAC ON */
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
+ POWER0_COM_OFF | POWER0_VCC5_ON);
+
+ /* GVSS(-8V) ON, VDD ON */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+ mdelay(2);
+
+ /* COM SIGNAL ON (PICTL[3] = L) */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE);
+
+ /* COM ON, DAC ON, VCC5_ON */
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON
+ | POWER0_COM_ON | POWER0_VCC5_ON);
+
+ /* VW ON, GVSS ON, VDD ON */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+ /* Signals output enable */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
+
+ /* Set Phase Adjuct */
+ lcdtg_set_phadadj(mode);
+
+ /* Initialize for Input Signals from ATI */
+ corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
+ | POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H);
+ udelay(1000);
+
+ lcd_inited=1;
+ } else {
+ lcdtg_set_phadadj(mode);
+ }
+
+ switch(mode) {
+ case 480:
+ case 640:
+ /* Set Lcd Resolution (VGA) */
+ corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA);
+ break;
+ case 240:
+ case 320:
+ default:
+ /* Set Lcd Resolution (QVGA) */
+ corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA);
+ break;
+ }
+}
+
+static void lcdtg_suspend(void)
+{
+ /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
+ mdelay(34);
+
+ /* (1)VW OFF */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
+
+ /* (2)COM OFF */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
+
+ /* (3)Set Common Voltage Bias 0V */
+ lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
+
+ /* (4)GVSS OFF */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
+
+ /* (5)VCC5 OFF */
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* (6)Set PDWN, INIOFF, DACOFF */
+ corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
+ PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
+
+ /* (7)DAC OFF */
+ corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
+
+ /* (8)VDD OFF */
+ corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
+
+ lcd_inited = 0;
+}
+
+
+/*
+ * Corgi w100 Frame Buffer Device
+ */
+#ifdef CONFIG_PXA_SHARP_C7xx
+
+#include <video/w100fb.h>
+
+static void w100_lcdtg_suspend(struct w100fb_par *par)
+{
+ lcdtg_suspend();
+}
+
+static void w100_lcdtg_init(struct w100fb_par *par)
+{
+ lcdtg_hw_init(par->xres);
+}
+
+
+static struct w100_tg_info corgi_lcdtg_info = {
+ .change = w100_lcdtg_init,
+ .suspend = w100_lcdtg_suspend,
+ .resume = w100_lcdtg_init,
+};
+
+static struct w100_mem_info corgi_fb_mem = {
+ .ext_cntl = 0x00040003,
+ .sdram_mode_reg = 0x00650021,
+ .ext_timing_cntl = 0x10002a4a,
+ .io_cntl = 0x7ff87012,
+ .size = 0x1fffff,
+};
+
+static struct w100_gen_regs corgi_fb_regs = {
+ .lcd_format = 0x00000003,
+ .lcdd_cntl1 = 0x01CC0000,
+ .lcdd_cntl2 = 0x0003FFFF,
+ .genlcd_cntl1 = 0x00FFFF0D,
+ .genlcd_cntl2 = 0x003F3003,
+ .genlcd_cntl3 = 0x000102aa,
+};
+
+static struct w100_gpio_regs corgi_fb_gpio = {
+ .init_data1 = 0x000000bf,
+ .init_data2 = 0x00000000,
+ .gpio_dir1 = 0x00000000,
+ .gpio_oe1 = 0x03c0feff,
+ .gpio_dir2 = 0x00000000,
+ .gpio_oe2 = 0x00000000,
+};
+
+static struct w100_mode corgi_fb_modes[] = {
+{
+ .xres = 480,
+ .yres = 640,
+ .left_margin = 0x56,
+ .right_margin = 0x55,
+ .upper_margin = 0x03,
+ .lower_margin = 0x00,
+ .crtc_ss = 0x82360056,
+ .crtc_ls = 0xA0280000,
+ .crtc_gs = 0x80280028,
+ .crtc_vpos_gs = 0x02830002,
+ .crtc_rev = 0x00400008,
+ .crtc_dclk = 0xA0000000,
+ .crtc_gclk = 0x8015010F,
+ .crtc_goe = 0x80100110,
+ .crtc_ps1_active = 0x41060010,
+ .pll_freq = 75,
+ .fast_pll_freq = 100,
+ .sysclk_src = CLK_SRC_PLL,
+ .sysclk_divider = 0,
+ .pixclk_src = CLK_SRC_PLL,
+ .pixclk_divider = 2,
+ .pixclk_divider_rotated = 6,
+},{
+ .xres = 240,
+ .yres = 320,
+ .left_margin = 0x27,
+ .right_margin = 0x2e,
+ .upper_margin = 0x01,
+ .lower_margin = 0x00,
+ .crtc_ss = 0x81170027,
+ .crtc_ls = 0xA0140000,
+ .crtc_gs = 0xC0140014,
+ .crtc_vpos_gs = 0x00010141,
+ .crtc_rev = 0x00400008,
+ .crtc_dclk = 0xA0000000,
+ .crtc_gclk = 0x8015010F,
+ .crtc_goe = 0x80100110,
+ .crtc_ps1_active = 0x41060010,
+ .pll_freq = 0,
+ .fast_pll_freq = 0,
+ .sysclk_src = CLK_SRC_XTAL,
+ .sysclk_divider = 0,
+ .pixclk_src = CLK_SRC_XTAL,
+ .pixclk_divider = 1,
+ .pixclk_divider_rotated = 1,
+},
+
+};
+
+static struct w100fb_mach_info corgi_fb_info = {
+ .tg = &corgi_lcdtg_info,
+ .init_mode = INIT_MODE_ROTATED,
+ .mem = &corgi_fb_mem,
+ .regs = &corgi_fb_regs,
+ .modelist = &corgi_fb_modes[0],
+ .num_modes = 2,
+ .gpio = &corgi_fb_gpio,
+ .xtal_freq = 12500000,
+ .xtal_dbl = 0,
+};
+
+static struct resource corgi_fb_resources[] = {
+ [0] = {
+ .start = 0x08000000,
+ .end = 0x08ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device corgifb_device = {
+ .name = "w100fb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(corgi_fb_resources),
+ .resource = corgi_fb_resources,
+ .dev = {
+ .platform_data = &corgi_fb_info,
+ .parent = &corgissp_device.dev,
+ },
+
+};
+#endif
+
+
+/*
+ * Spitz PXA Frame Buffer Device
+ */
+#ifdef CONFIG_PXA_SHARP_Cxx00
+
+#include <asm/arch/pxafb.h>
+
+void spitz_lcd_power(int on)
+{
+ if (on)
+ lcdtg_hw_init(480);
+ else
+ lcdtg_suspend();
+}
+
+#endif
+
+
+/*
+ * Corgi/Spitz Touchscreen to LCD interface
+ */
+static unsigned long (*get_hsync_time)(struct device *dev);
+
+static void inline sharpsl_wait_sync(int gpio)
+{
+ while((GPLR(gpio) & GPIO_bit(gpio)) == 0);
+ while((GPLR(gpio) & GPIO_bit(gpio)) != 0);
+}
+
+#ifdef CONFIG_PXA_SHARP_C7xx
+unsigned long corgi_get_hsync_len(void)
+{
+ if (!get_hsync_time)
+ get_hsync_time = symbol_get(w100fb_get_hsynclen);
+ if (!get_hsync_time)
+ return 0;
+
+ return get_hsync_time(&corgifb_device.dev);
+}
+
+void corgi_put_hsync(void)
+{
+ if (get_hsync_time)
+ symbol_put(w100fb_get_hsynclen);
+}
+
+void corgi_wait_hsync(void)
+{
+ sharpsl_wait_sync(CORGI_GPIO_HSYNC);
+}
+#endif
+
+#ifdef CONFIG_PXA_SHARP_Cxx00
+unsigned long spitz_get_hsync_len(void)
+{
+ if (!get_hsync_time)
+ get_hsync_time = symbol_get(pxafb_get_hsync_time);
+ if (!get_hsync_time)
+ return 0;
+
+ return pxafb_get_hsync_time(&pxafb_device.dev);
+}
+
+void spitz_put_hsync(void)
+{
+ if (get_hsync_time)
+ symbol_put(pxafb_get_hsync_time);
+}
+
+void spitz_wait_hsync(void)
+{
+ sharpsl_wait_sync(SPITZ_GPIO_HSYNC);
+}
+#endif
+
+/*
+ * Corgi/Spitz Backlight Power
+ */
+#ifdef CONFIG_PXA_SHARP_C7xx
+void corgi_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via SCOOP */
+ if (intensity & 0x0020)
+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+ else
+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+}
+#endif
+
+
+#if defined(CONFIG_MACH_SPITZ) || defined(CONFIG_MACH_BORZOI)
+void spitz_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via SCOOP */
+ if (intensity & 0x0020)
+ reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+ else
+ set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+
+ if (intensity)
+ set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+ else
+ reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+}
+#endif
+
+#ifdef CONFIG_MACH_AKITA
+void akita_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via IO-Expander */
+ if (intensity & 0x0020)
+ akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+ else
+ akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+
+ if (intensity)
+ akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+ else
+ akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+}
+#endif
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 8ccffba0018f..0ef428287055 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -1,7 +1,7 @@
/*
* SSP control code for Sharp Corgi devices
*
- * Copyright (c) 2004 Richard Purdie
+ * Copyright (c) 2004-2005 Richard Purdie
*
* 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
@@ -17,14 +17,16 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/ssp.h>
-#include <asm/arch/corgi.h>
#include <asm/arch/pxa-regs.h>
+#include "sharpsl.h"
-static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(corgi_ssp_lock);
static struct ssp_dev corgi_ssp_dev;
static struct ssp_state corgi_ssp_state;
+static struct corgissp_machinfo *ssp_machinfo;
/*
* There are three devices connected to the SSP interface:
@@ -48,12 +50,12 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
unsigned long ret,flag;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
ssp_write_word(&corgi_ssp_dev,data);
ret = ssp_read_word(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
return ret;
@@ -66,12 +68,12 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
void corgi_ssp_ads7846_lock(void)
{
spin_lock(&corgi_ssp_lock);
- GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
}
void corgi_ssp_ads7846_unlock(void)
{
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
spin_unlock(&corgi_ssp_lock);
}
@@ -97,23 +99,27 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get);
*/
unsigned long corgi_ssp_dac_put(ulong data)
{
- unsigned long flag;
+ unsigned long flag, sscr1 = SSCR1_SPH;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
+ if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi())
+ sscr1 = 0;
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
ssp_enable(&corgi_ssp_dev);
+ GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_write_word(&corgi_ssp_dev,data);
/* Read null data back from device to prevent SSP overflow */
ssp_read_word(&corgi_ssp_dev);
+ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
return 0;
@@ -141,9 +147,9 @@ int corgi_ssp_max1111_get(ulong data)
int voltage,voltage1,voltage2;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
ssp_enable(&corgi_ssp_dev);
udelay(1);
@@ -161,9 +167,9 @@ int corgi_ssp_max1111_get(ulong data)
voltage2=ssp_read_word(&corgi_ssp_dev);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
if (voltage1 & 0xc0 || voltage2 & 0x3f)
@@ -179,25 +185,31 @@ EXPORT_SYMBOL(corgi_ssp_max1111_get);
/*
* Support Routines
*/
-int __init corgi_ssp_probe(struct device *dev)
+
+void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo)
+{
+ ssp_machinfo = machinfo;
+}
+
+static int __init corgi_ssp_probe(struct device *dev)
{
int ret;
/* Chip Select - Disable All */
- GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
- GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
- GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+ 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*/
- ret=ssp_init(&corgi_ssp_dev,1);
+ ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port);
if (ret)
printk(KERN_ERR "Unable to register SSP handler!\n");
else {
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
}
@@ -222,9 +234,9 @@ static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
static int corgi_ssp_resume(struct device *dev, u32 level)
{
if (level == RESUME_POWER_ON) {
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
+ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
ssp_enable(&corgi_ssp_dev);
}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index f3cac43124a5..539b596005fc 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -133,7 +133,7 @@ static struct irqchip pxa_low_gpio_chip = {
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
- .type = pxa_gpio_irq_type,
+ .set_type = pxa_gpio_irq_type,
};
/*
@@ -157,7 +157,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
mask >>= 2;
do {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@@ -172,7 +172,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@@ -187,7 +187,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@@ -203,7 +203,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
desc = irq_desc + irq;
do {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
@@ -241,7 +241,7 @@ static struct irqchip pxa_muxed_gpio_chip = {
.ack = pxa_ack_muxed_gpio,
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
- .type = pxa_gpio_irq_type,
+ .set_type = pxa_gpio_irq_type,
};
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6309853b59be..923f6eb774c0 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -84,7 +84,7 @@ static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
if (likely(pending)) {
irq = LUBBOCK_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
}
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
} while (pending);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 827b7b5a5be8..85fdb5b1470a 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -72,7 +72,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
if (likely(pending)) {
irq = MAINSTONE_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
}
pending = MST_INTSETCLR & mainstone_irq_enabled;
} while (pending);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 0e4f6fab100a..47cfb8bb8318 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -62,6 +62,15 @@ struct platform_device poodle_scoop_device = {
.resource = poodle_scoop_resources,
};
+static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = {
+{
+ .dev = &poodle_scoop_device.dev,
+ .irq = POODLE_IRQ_GPIO_CF_IRQ,
+ .cd_irq = POODLE_IRQ_GPIO_CF_CD,
+ .cd_irq_str = "PCMCIA0 CD",
+},
+};
+
/* LoCoMo device */
static struct resource locomo_resources[] = {
@@ -147,6 +156,9 @@ static void __init poodle_init(void)
set_pxa_fb_info(&poodle_fb_info);
+ scoop_num = 1;
+ scoop_devs = &poodle_pcmcia_scoop[0];
+
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if (ret) {
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
new file mode 100644
index 000000000000..3977a77aacdd
--- /dev/null
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -0,0 +1,34 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+struct corgissp_machinfo {
+ int port;
+ int cs_lcdcon;
+ int cs_ads7846;
+ int cs_max1111;
+ int clk_lcdcon;
+ int clk_ads7846;
+ int clk_max1111;
+};
+
+void corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo);
+
+/*
+ * SharpSL Backlight
+ */
+
+void corgi_bl_set_intensity(int intensity);
+void spitz_bl_set_intensity(int intensity);
+void akita_bl_set_intensity(int intensity);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+unsigned long corgi_get_hsync_len(void);
+unsigned long spitz_get_hsync_len(void);
+void corgi_put_hsync(void);
+void spitz_put_hsync(void);
+void corgi_wait_hsync(void);
+void spitz_wait_hsync(void);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
new file mode 100644
index 000000000000..568afe3d6e1a
--- /dev/null
+++ b/arch/arm/mach-pxa/spitz.c
@@ -0,0 +1,380 @@
+/*
+ * Support for Sharp SL-Cxx00 Series of PDAs
+ * Models: SL-C3000 (Spitz), SL-C1000 (Akita) and SL-C3100 (Borzoi)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches/lubbock.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/device.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/host.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/akita.h>
+#include <asm/arch/spitz.h>
+#include <asm/arch/sharpsl.h>
+
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/scoop.h>
+
+#include "generic.h"
+#include "sharpsl.h"
+
+/*
+ * Spitz SCOOP Device #1
+ */
+static struct resource spitz_scoop_resources[] = {
+ [0] = {
+ .start = 0x10800000,
+ .end = 0x10800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config spitz_scoop_setup = {
+ .io_dir = SPITZ_SCP_IO_DIR,
+ .io_out = SPITZ_SCP_IO_OUT,
+ .suspend_clr = SPITZ_SCP_SUS_CLR,
+ .suspend_set = SPITZ_SCP_SUS_SET,
+};
+
+struct platform_device spitzscoop_device = {
+ .name = "sharp-scoop",
+ .id = 0,
+ .dev = {
+ .platform_data = &spitz_scoop_setup,
+ },
+ .num_resources = ARRAY_SIZE(spitz_scoop_resources),
+ .resource = spitz_scoop_resources,
+};
+
+/*
+ * Spitz SCOOP Device #2
+ */
+static struct resource spitz_scoop2_resources[] = {
+ [0] = {
+ .start = 0x08800040,
+ .end = 0x08800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config spitz_scoop2_setup = {
+ .io_dir = SPITZ_SCP2_IO_DIR,
+ .io_out = SPITZ_SCP2_IO_OUT,
+ .suspend_clr = SPITZ_SCP2_SUS_CLR,
+ .suspend_set = SPITZ_SCP2_SUS_SET,
+};
+
+struct platform_device spitzscoop2_device = {
+ .name = "sharp-scoop",
+ .id = 1,
+ .dev = {
+ .platform_data = &spitz_scoop2_setup,
+ },
+ .num_resources = ARRAY_SIZE(spitz_scoop2_resources),
+ .resource = spitz_scoop2_resources,
+};
+
+static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = {
+{
+ .dev = &spitzscoop_device.dev,
+ .irq = SPITZ_IRQ_GPIO_CF_IRQ,
+ .cd_irq = SPITZ_IRQ_GPIO_CF_CD,
+ .cd_irq_str = "PCMCIA0 CD",
+},{
+ .dev = &spitzscoop2_device.dev,
+ .irq = SPITZ_IRQ_GPIO_CF2_IRQ,
+ .cd_irq = -1,
+},
+};
+
+
+/*
+ * Spitz SSP Device
+ *
+ * Set the parent as the scoop device because a lot of SSP devices
+ * also use scoop functions and this makes the power up/down order
+ * work correctly.
+ */
+struct platform_device spitzssp_device = {
+ .name = "corgi-ssp",
+ .dev = {
+ .parent = &spitzscoop_device.dev,
+ },
+ .id = -1,
+};
+
+struct corgissp_machinfo spitz_ssp_machinfo = {
+ .port = 2,
+ .cs_lcdcon = SPITZ_GPIO_LCDCON_CS,
+ .cs_ads7846 = SPITZ_GPIO_ADS7846_CS,
+ .cs_max1111 = SPITZ_GPIO_MAX1111_CS,
+ .clk_lcdcon = 520,
+ .clk_ads7846 = 14,
+ .clk_max1111 = 56,
+};
+
+
+/*
+ * Spitz Backlight Device
+ */
+static struct corgibl_machinfo spitz_bl_machinfo = {
+ .max_intensity = 0x2f,
+};
+
+static struct platform_device spitzbl_device = {
+ .name = "corgi-bl",
+ .dev = {
+ .platform_data = &spitz_bl_machinfo,
+ },
+ .id = -1,
+};
+
+
+/*
+ * Spitz Keyboard Device
+ */
+static struct platform_device spitzkbd_device = {
+ .name = "spitz-keyboard",
+ .id = -1,
+};
+
+
+/*
+ * Spitz Touch Screen Device
+ */
+static struct resource spitzts_resources[] = {
+ [0] = {
+ .start = SPITZ_IRQ_GPIO_TP_INT,
+ .end = SPITZ_IRQ_GPIO_TP_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct corgits_machinfo spitz_ts_machinfo = {
+ .get_hsync_len = spitz_get_hsync_len,
+ .put_hsync = spitz_put_hsync,
+ .wait_hsync = spitz_wait_hsync,
+};
+
+static struct platform_device spitzts_device = {
+ .name = "corgi-ts",
+ .dev = {
+ .parent = &spitzssp_device.dev,
+ .platform_data = &spitz_ts_machinfo,
+ },
+ .id = -1,
+ .num_resources = ARRAY_SIZE(spitzts_resources),
+ .resource = spitzts_resources,
+};
+
+
+/*
+ * MMC/SD Device
+ *
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert/eject.
+ */
+
+static struct pxamci_platform_data spitz_mci_platform_data;
+
+static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+ int err;
+
+ /* setup GPIO for PXA27x MMC controller */
+ pxa_gpio_mode(GPIO32_MMCCLK_MD);
+ pxa_gpio_mode(GPIO112_MMCCMD_MD);
+ pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+ pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+ pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+ pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+ pxa_gpio_mode(SPITZ_GPIO_nSD_DETECT | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_nSD_WP | GPIO_IN);
+
+ spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+ err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, SA_INTERRUPT,
+ "MMC card detect", data);
+ if (err) {
+ printk(KERN_ERR "spitz_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+ return -1;
+ }
+
+ set_irq_type(SPITZ_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+/* Power control is shared with one of the CF slots so we have a mess */
+static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
+{
+ struct pxamci_platform_data* p_d = dev->platform_data;
+
+ unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR);
+
+ if (( 1 << vdd) & p_d->ocr_mask) {
+ /* printk(KERN_DEBUG "%s: on\n", __FUNCTION__); */
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+ mdelay(2);
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | 0x04);
+ } else {
+ /* printk(KERN_DEBUG "%s: off\n", __FUNCTION__); */
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr & ~0x04);
+
+ if (!(cpr | 0x02)) {
+ mdelay(1);
+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+ }
+ }
+}
+
+static int spitz_mci_get_ro(struct device *dev)
+{
+ return GPLR(SPITZ_GPIO_nSD_WP) & GPIO_bit(SPITZ_GPIO_nSD_WP);
+}
+
+static void spitz_mci_exit(struct device *dev, void *data)
+{
+ free_irq(SPITZ_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data spitz_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .init = spitz_mci_init,
+ .get_ro = spitz_mci_get_ro,
+ .setpower = spitz_mci_setpower,
+ .exit = spitz_mci_exit,
+};
+
+
+/*
+ * Spitz PXA Framebuffer
+ */
+static struct pxafb_mach_info spitz_pxafb_info __initdata = {
+ .pixclock = 19231,
+ .xres = 480,
+ .yres = 640,
+ .bpp = 16,
+ .hsync_len = 40,
+ .left_margin = 46,
+ .right_margin = 125,
+ .vsync_len = 3,
+ .upper_margin = 1,
+ .lower_margin = 0,
+ .sync = 0,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act | LCCR0_LDDALT | LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM,
+ .lccr3 = LCCR3_PixRsEdg | LCCR3_OutEnH,
+ .pxafb_lcd_power = spitz_lcd_power,
+};
+
+
+static struct platform_device *devices[] __initdata = {
+ &spitzscoop_device,
+ &spitzssp_device,
+ &spitzkbd_device,
+ &spitzts_device,
+ &spitzbl_device,
+ &spitzbattery_device,
+};
+
+static void __init common_init(void)
+{
+ PMCR = 0x00;
+
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x0158C000;
+ PGSR1 = 0x00FF0080;
+ PGSR2 = 0x0001C004;
+
+ /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+ PCFR |= PCFR_OPDE;
+
+ corgi_ssp_set_machinfo(&spitz_ssp_machinfo);
+
+ pxa_gpio_mode(SPITZ_GPIO_HSYNC | GPIO_IN);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+ pxa_set_mci_info(&spitz_mci_platform_data);
+ pxafb_device.dev.parent = &spitzssp_device.dev;
+ set_pxa_fb_info(&spitz_pxafb_info);
+}
+
+static void __init spitz_init(void)
+{
+ scoop_num = 2;
+ scoop_devs = &spitz_pcmcia_scoop[0];
+ spitz_bl_machinfo.set_bl_intensity = spitz_bl_set_intensity;
+
+ common_init();
+
+ platform_device_register(&spitzscoop2_device);
+}
+
+static void __init fixup_spitz(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 = (64*1024*1024);
+}
+
+#ifdef CONFIG_MACH_SPITZ
+MACHINE_START(SPITZ, "SHARP Spitz")
+ .phys_ram = 0xa0000000,
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = fixup_spitz,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
+ .init_machine = spitz_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_BORZOI
+MACHINE_START(BORZOI, "SHARP Borzoi")
+ .phys_ram = 0xa0000000,
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = fixup_spitz,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
+ .init_machine = spitz_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6e5202154f91..7dad3f1465e0 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
return usec;
}
+#ifdef CONFIG_NO_IDLE_HZ
+static unsigned long initial_match;
+static int match_posponed;
+#endif
+
static irqreturn_t
pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
+#ifdef CONFIG_NO_IDLE_HZ
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ }
+#endif
+
/* Loop until we get ahead of the free running timer.
* This ensures an exact clock tick count and time accuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
+ * Since IRQs are disabled at this point, coherence between
+ * lost_ticks(updated in do_timer()) and the match reg value is
+ * ensured, hence we can use do_gettimeofday() from interrupt
+ * handlers.
*
* HACK ALERT: it seems that the PXA timer regs aren't updated right
* away in all cases when a write occurs. We therefore compare with
@@ -126,6 +139,42 @@ static void __init pxa_timer_init(void)
OSCR = 0; /* initialize free-running timer, force first match */
}
+#ifdef CONFIG_NO_IDLE_HZ
+static int pxa_dyn_tick_enable_disable(void)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static void pxa_dyn_tick_reprogram(unsigned long ticks)
+{
+ if (ticks > 1) {
+ initial_match = OSMR0;
+ OSMR0 = initial_match + ticks * LATCH;
+ match_posponed = 1;
+ }
+}
+
+static irqreturn_t
+pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ if ( (signed long)(initial_match - OSCR) <= 8 )
+ return pxa_timer_interrupt(irq, dev_id, regs);
+ }
+ return IRQ_NONE;
+}
+
+static struct dyn_tick_timer pxa_dyn_tick = {
+ .enable = pxa_dyn_tick_enable_disable,
+ .disable = pxa_dyn_tick_enable_disable,
+ .reprogram = pxa_dyn_tick_reprogram,
+ .handler = pxa_dyn_tick_handler,
+};
+#endif
+
#ifdef CONFIG_PM
static unsigned long osmr[4], oier;
@@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
.suspend = pxa_timer_suspend,
.resume = pxa_timer_resume,
.offset = pxa_gettimeoffset,
+#ifdef CONFIG_NO_IDLE_HZ
+ .dyn_tick = &pxa_dyn_tick,
+#endif
};
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index a10268618f74..e3587efec4bf 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -140,7 +140,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index d4d03d0daaec..06807c6ee68a 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -2,6 +2,13 @@ if ARCH_S3C2410
menu "S3C24XX Implementations"
+config MACH_ANUBIS
+ bool "Simtec Electronics ANUBIS"
+ select CPU_S3C2440
+ help
+ Say Y gere if you are using the Simtec Electronics ANUBIS
+ development system
+
config ARCH_BAST
bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
@@ -11,6 +18,14 @@ config ARCH_BAST
Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
+config BAST_PC104_IRQ
+ bool "BAST PC104 IRQ support"
+ depends on ARCH_BAST
+ default y
+ help
+ Say Y here to enable the PC104 IRQ routing on the
+ Simtec BAST (EB2410ITX)
+
config ARCH_H1940
bool "IPAQ H1940"
select CPU_S3C2410
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 55ed7c7e57da..b4f1e051c768 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -26,8 +26,13 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
+# bast extras
+
+obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
+
# machine specific support
+obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
obj-$(CONFIG_MACH_N30) += mach-n30.o
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 5e5bbe893cbb..fbbeb0553006 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/bast-irq.c
*
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2003,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://www.simtec.co.uk/products/EB2410ITX/
@@ -21,7 +21,8 @@
*
* Modifications:
* 08-Jan-2003 BJD Moved from central IRQ code
- */
+ * 21-Aug-2005 BJD Fixed missing code and compile errors
+*/
#include <linux/init.h>
@@ -30,12 +31,19 @@
#include <linux/ptrace.h>
#include <linux/sysdev.h>
+#include <asm/mach-types.h>
+
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
-#include <asm/hardware/s3c2410/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+#include "irq.h"
#if 0
#include <asm/debug-ll.h>
@@ -79,15 +87,15 @@ bast_pc104_mask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp &= ~bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
-
- if (temp == 0)
- bast_extint_mask(IRQ_ISA);
}
static void
-bast_pc104_ack(unsigned int irqno)
+bast_pc104_maskack(unsigned int irqno)
{
- bast_extint_ack(IRQ_ISA);
+ struct irqdesc *desc = irq_desc + IRQ_ISA;
+
+ bast_pc104_mask(irqno);
+ desc->chip->ack(IRQ_ISA);
}
static void
@@ -98,14 +106,12 @@ bast_pc104_unmask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp |= bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
-
- bast_extint_unmask(IRQ_ISA);
}
-static struct bast_pc104_chip = {
+static struct irqchip bast_pc104_chip = {
.mask = bast_pc104_mask,
.unmask = bast_pc104_unmask,
- .ack = bast_pc104_ack
+ .ack = bast_pc104_maskack
};
static void
@@ -119,14 +125,49 @@ bast_irq_pc104_demux(unsigned int irq,
stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
- for (i = 0; i < 4 && stat != 0; i++) {
- if (stat & 1) {
- irqno = bast_pc104_irqs[i];
- desc = irq_desc + irqno;
+ if (unlikely(stat == 0)) {
+ /* ack if we get an irq with nothing (ie, startup) */
+
+ desc = irq_desc + IRQ_ISA;
+ desc->chip->ack(IRQ_ISA);
+ } else {
+ /* handle the IRQ */
+
+ for (i = 0; stat != 0; i++, stat >>= 1) {
+ if (stat & 1) {
+ irqno = bast_pc104_irqs[i];
- desc->handle(irqno, desc, regs);
+ desc_handle_irq(irqno, irq_desc + irqno, regs);
+ }
}
+ }
+}
- stat >>= 1;
+static __init int bast_irq_init(void)
+{
+ unsigned int i;
+
+ if (machine_is_bast()) {
+ printk(KERN_INFO "BAST PC104 IRQ routing, (c) 2005 Simtec Electronics\n");
+
+ /* zap all the IRQs */
+
+ __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
+
+ set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
+
+ /* reigster our IRQs */
+
+ for (i = 0; i < 4; i++) {
+ unsigned int irqno = bast_pc104_irqs[i];
+
+ set_irq_chip(irqno, &bast_pc104_chip);
+ set_irq_handler(irqno, do_level_IRQ);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
}
+
+ return 0;
}
+
+arch_initcall(bast_irq_init);
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 9a66050e887d..f59608268751 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
unsigned long hclk,
unsigned long pclk)
{
+ unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
struct clk *clkp = init_clocks;
int ptr;
int ret;
@@ -446,5 +447,13 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
}
}
+ /* show the clock-slow value */
+
+ printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+ print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+ (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+ (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+ (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
+
return 0;
}
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index 4664bd11adc1..0077937a7ab8 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -29,7 +29,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
-
+#include <asm/arch/fb.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -103,6 +103,15 @@ struct platform_device s3c_device_lcd = {
EXPORT_SYMBOL(s3c_device_lcd);
+static struct s3c2410fb_mach_info s3c2410fb_info;
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info)
+{
+ memcpy(&s3c2410fb_info,hard_s3c2410fb_info,sizeof(struct s3c2410fb_mach_info));
+ s3c_device_lcd.dev.platform_data = &s3c2410fb_info;
+}
+EXPORT_SYMBOL(set_s3c2410fb_info);
+
/* NAND Controller */
static struct resource s3c_nand_resource[] = {
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 973a5fe6769c..66d8c068e940 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -184,14 +184,14 @@ struct irqchip s3c_irq_level_chip = {
.ack = s3c_irq_maskack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
- .wake = s3c_irq_wake
+ .set_wake = s3c_irq_wake
};
static struct irqchip s3c_irq_chip = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
- .wake = s3c_irq_wake
+ .set_wake = s3c_irq_wake
};
/* S3C2410_EINTMASK
@@ -350,16 +350,16 @@ static struct irqchip s3c_irqext_chip = {
.mask = s3c_irqext_mask,
.unmask = s3c_irqext_unmask,
.ack = s3c_irqext_ack,
- .type = s3c_irqext_type,
- .wake = s3c_irqext_wake
+ .set_type = s3c_irqext_type,
+ .set_wake = s3c_irqext_wake
};
static struct irqchip s3c_irq_eint0t4 = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
- .wake = s3c_irq_wake,
- .type = s3c_irqext_type,
+ .set_wake = s3c_irq_wake,
+ .set_type = s3c_irqext_type,
};
/* mask values for the parent registers for each of the interrupt types */
@@ -496,11 +496,11 @@ static void s3c_irq_demux_adc(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_TC;
- mydesc->handle( IRQ_TC, mydesc, regs);
+ desc_handle_irq(IRQ_TC, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_ADC;
- mydesc->handle(IRQ_ADC, mydesc, regs);
+ desc_handle_irq(IRQ_ADC, mydesc, regs);
}
}
}
@@ -529,17 +529,17 @@ static void s3c_irq_demux_uart(unsigned int start,
desc = irq_desc + start;
if (subsrc & 1)
- desc->handle(start, desc, regs);
+ desc_handle_irq(start, desc, regs);
desc++;
if (subsrc & 2)
- desc->handle(start+1, desc, regs);
+ desc_handle_irq(start+1, desc, regs);
desc++;
if (subsrc & 4)
- desc->handle(start+2, desc, regs);
+ desc_handle_irq(start+2, desc, regs);
}
}
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
new file mode 100644
index 000000000000..f87aa0b669ad
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -0,0 +1,270 @@
+/* linux/arch/arm/mach-s3c2410/mach-anubis.c
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * 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.
+ *
+ * Modifications:
+ * 02-May-2005 BJD Copied from mach-bast.c
+*/
+
+#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/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/anubis-map.h>
+#include <asm/arch/anubis-irq.h>
+#include <asm/arch/anubis-cpld.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+
+static struct map_desc anubis_iodesc[] __initdata = {
+ /* ISA IO areas */
+
+ { (u32)S3C24XX_VA_ISA_BYTE, 0x0, SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_WORD, 0x0, SZ_16M, MT_DEVICE },
+
+ /* we could possibly compress the next set down into a set of smaller tables
+ * pagetables, but that would mean using an L2 section, and it still means
+ * we cannot actually feed the same register to an LDR due to 16K spacing
+ */
+
+ /* CPLD control registers */
+
+ { (u32)ANUBIS_VA_CTRL1, ANUBIS_PA_CTRL1, SZ_4K, MT_DEVICE },
+ { (u32)ANUBIS_VA_CTRL2, ANUBIS_PA_CTRL2, SZ_4K, MT_DEVICE },
+
+ /* IDE drives */
+
+ { (u32)ANUBIS_IDEPRI, S3C2410_CS3, SZ_1M, MT_DEVICE },
+ { (u32)ANUBIS_IDEPRIAUX, S3C2410_CS3+(1<<26), SZ_1M, MT_DEVICE },
+
+ { (u32)ANUBIS_IDESEC, S3C2410_CS4, SZ_1M, MT_DEVICE },
+ { (u32)ANUBIS_IDESECAUX, S3C2410_CS4+(1<<26), SZ_1M, MT_DEVICE },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
+ [0] = {
+ .name = "uclk",
+ .divisor = 1,
+ .min_baud = 0,
+ .max_baud = 0,
+ },
+ [1] = {
+ .name = "pclk",
+ .divisor = 1,
+ .min_baud = 0,
+ .max_baud = 0.
+ }
+};
+
+
+static struct s3c2410_uartcfg anubis_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ .clocks = anubis_serial_clocks,
+ .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+ },
+ [1] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ .clocks = anubis_serial_clocks,
+ .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+ },
+};
+
+/* NAND Flash on Anubis board */
+
+static int external_map[] = { 2 };
+static int chip0_map[] = { 0 };
+static int chip1_map[] = { 1 };
+
+struct mtd_partition anubis_default_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_16K,
+ .offset = 0
+ },
+ [1] = {
+ .name = "/boot",
+ .size = SZ_4M - SZ_16K,
+ .offset = SZ_16K,
+ },
+ [2] = {
+ .name = "user1",
+ .offset = SZ_4M,
+ .size = SZ_32M - SZ_4M,
+ },
+ [3] = {
+ .name = "user2",
+ .offset = SZ_32M,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
+/* the Anubis has 3 selectable slots for nand-flash, the two
+ * on-board chip areas, as well as the external slot.
+ *
+ * Note, there is no current hot-plug support for the External
+ * socket.
+*/
+
+static struct s3c2410_nand_set anubis_nand_sets[] = {
+ [1] = {
+ .name = "External",
+ .nr_chips = 1,
+ .nr_map = external_map,
+ .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
+ .partitions = anubis_default_nand_part
+ },
+ [0] = {
+ .name = "chip0",
+ .nr_chips = 1,
+ .nr_map = chip0_map,
+ .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
+ .partitions = anubis_default_nand_part
+ },
+ [2] = {
+ .name = "chip1",
+ .nr_chips = 1,
+ .nr_map = chip1_map,
+ .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
+ .partitions = anubis_default_nand_part
+ },
+};
+
+static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
+{
+ unsigned int tmp;
+
+ slot = set->nr_map[slot] & 3;
+
+ pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
+ slot, set, set->nr_map);
+
+ tmp = __raw_readb(ANUBIS_VA_CTRL1);
+ tmp &= ~ANUBIS_CTRL1_NANDSEL;
+ tmp |= slot;
+
+ pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
+
+ __raw_writeb(tmp, ANUBIS_VA_CTRL1);
+}
+
+static struct s3c2410_platform_nand anubis_nand_info = {
+ .tacls = 25,
+ .twrph0 = 80,
+ .twrph1 = 80,
+ .nr_sets = ARRAY_SIZE(anubis_nand_sets),
+ .sets = anubis_nand_sets,
+ .select_chip = anubis_nand_select,
+};
+
+
+/* Standard Anubis devices */
+
+static struct platform_device *anubis_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_wdt,
+ &s3c_device_adc,
+ &s3c_device_i2c,
+ &s3c_device_rtc,
+ &s3c_device_nand,
+};
+
+static struct clk *anubis_clocks[] = {
+ &s3c24xx_dclk0,
+ &s3c24xx_dclk1,
+ &s3c24xx_clkout0,
+ &s3c24xx_clkout1,
+ &s3c24xx_uclk,
+};
+
+static struct s3c24xx_board anubis_board __initdata = {
+ .devices = anubis_devices,
+ .devices_count = ARRAY_SIZE(anubis_devices),
+ .clocks = anubis_clocks,
+ .clocks_count = ARRAY_SIZE(anubis_clocks)
+};
+
+void __init anubis_map_io(void)
+{
+ /* initialise the clocks */
+
+ s3c24xx_dclk0.parent = NULL;
+ s3c24xx_dclk0.rate = 12*1000*1000;
+
+ s3c24xx_dclk1.parent = NULL;
+ s3c24xx_dclk1.rate = 24*1000*1000;
+
+ s3c24xx_clkout0.parent = &s3c24xx_dclk0;
+ s3c24xx_clkout1.parent = &s3c24xx_dclk1;
+
+ s3c24xx_uclk.parent = &s3c24xx_clkout1;
+
+ s3c_device_nand.dev.platform_data = &anubis_nand_info;
+
+ s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
+ s3c24xx_init_clocks(0);
+ s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
+ s3c24xx_set_board(&anubis_board);
+
+ /* ensure that the GPIO is setup */
+ s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+}
+
+MACHINE_START(ANUBIS, "Simtec-Anubis")
+ /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
+ .phys_ram = S3C2410_SDRAM_PA,
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .map_io = anubis_map_io,
+ .init_irq = s3c24xx_init_irq,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index e9182242da95..1a3367da6408 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -381,7 +381,7 @@ static struct plat_serial8250_port bast_sio_data[] = {
static struct platform_device bast_sio = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = &bast_sio_data,
},
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index ea4fb1a97a50..6ff1889fbd21 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -45,6 +45,9 @@
//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/fb.h>
#include <linux/serial_core.h>
@@ -88,6 +91,48 @@ static struct s3c2410_uartcfg h1940_uartcfgs[] = {
+/**
+ * Set lcd on or off
+ **/
+static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
+ .fixed_syncs= 1,
+ .regs={
+ .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \
+ S3C2410_LCDCON1_TFT | \
+ S3C2410_LCDCON1_CLKVAL(0x0C),
+
+ .lcdcon2= S3C2410_LCDCON2_VBPD(7) | \
+ S3C2410_LCDCON2_LINEVAL(319) | \
+ S3C2410_LCDCON2_VFPD(6) | \
+ S3C2410_LCDCON2_VSPW(0),
+
+ .lcdcon3= S3C2410_LCDCON3_HBPD(19) | \
+ S3C2410_LCDCON3_HOZVAL(239) | \
+ S3C2410_LCDCON3_HFPD(7),
+
+ .lcdcon4= S3C2410_LCDCON4_MVAL(0) | \
+ S3C2410_LCDCON4_HSPW(3),
+
+ .lcdcon5= S3C2410_LCDCON5_FRM565 | \
+ S3C2410_LCDCON5_INVVLINE | \
+ S3C2410_LCDCON5_HWSWP,
+ },
+ .lpcsel= 0x02,
+ .gpccon= 0xaa940659,
+ .gpccon_mask= 0xffffffff,
+ .gpcup= 0x0000ffff,
+ .gpcup_mask= 0xffffffff,
+ .gpdcon= 0xaa84aaa0,
+ .gpdcon_mask= 0xffffffff,
+ .gpdup= 0x0000faff,
+ .gpdup_mask= 0xffffffff,
+
+ .width= 240,
+ .height= 320,
+ .xres= {240,240,240},
+ .yres= {320,320,320},
+ .bpp= {16,16,16},
+};
static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_usb,
@@ -116,6 +161,11 @@ void __init h1940_init_irq(void)
}
+void __init h1940_init(void)
+{
+ set_s3c2410fb_info(&h1940_lcdcfg);
+}
+
MACHINE_START(H1940, "IPAQ-H1940")
/* Maintainer: Ben Dooks <ben@fluff.org> */
.phys_ram = S3C2410_SDRAM_PA,
@@ -124,5 +174,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = h1940_map_io,
.init_irq = h1940_init_irq,
+ .init_machine = h1940_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 79044d9bce38..66bf5bb2b3db 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -110,34 +110,24 @@ void __init n30_init_irq(void)
s3c24xx_init_irq();
}
-
-static int n30_usbstart_thread(void *unused)
-{
- /* Turn off suspend on both USB ports, and switch the
- * selectable USB port to USB device mode. */
- writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
-
- /* Turn off the D+ pull up for 3 seconds so that the USB host
- * at the other end will do a rescan of the USB bus. */
- s3c2410_gpio_setpin(S3C2410_GPB3, 0);
-
- msleep_interruptible(3*HZ);
-
- s3c2410_gpio_setpin(S3C2410_GPB3, 1);
-
- return 0;
-}
-
+/* GPB3 is the line that controls the pull-up for the USB D+ line */
void __init n30_init(void)
{
s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
- kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
+ /* Turn off suspend on both USB ports, and switch the
+ * selectable USB port to USB device mode. */
+
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+ S3C2410_MISCCR_USBSUSPND0 |
+ S3C2410_MISCCR_USBSUSPND1, 0x0);
}
MACHINE_START(N30, "Acer-N30")
- /* Maintainer: Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org> */
+ /* Maintainer: Christer Weinigel <christer@weinigel.se>,
+ Ben Dooks <ben-linux@fluff.org>
+ */
.phys_ram = S3C2410_SDRAM_PA,
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 924e8464c212..8f9ab2893df4 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -221,7 +221,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 2cb798832223..4c7ccef6c207 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -48,7 +48,7 @@ static __init int pm_simtec_init(void)
/* check which machine we are running on */
- if (!machine_is_bast() && !machine_is_vr1000())
+ if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
return 0;
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index 13a48ee77484..fe57d966a34d 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -585,14 +585,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
s3c2410_pm_check_store();
- // need to make some form of time-delta
-
/* send the cpu to sleep... */
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
s3c2410_cpu_suspend(regs_save);
+ /* restore the cpu state */
+
+ cpu_init();
+
/* unset the return-from-sleep flag, to ensure reset */
tmp = __raw_readl(S3C2410_GSTATUS2);
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index b018a1f680ce..c67e0979aec3 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = {
static int s3c2440_clk_add(struct sys_device *sysdev)
{
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+ unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
struct clk *clk_h;
struct clk *clk_p;
struct clk *clk_xtal;
@@ -80,8 +81,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
- printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
- print_mhz(s3c2440_clk_upll.rate));
+ printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n",
+ print_mhz(s3c2440_clk_upll.rate),
+ (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
clk_p = clk_get(NULL, "pclk");
clk_h = clk_get(NULL, "hclk");
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index 7cb9912242a3..278d0044c85d 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -64,11 +64,11 @@ static void s3c_irq_demux_wdtac97(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_S3C2440_WDT;
- mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+ desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_S3C2440_AC97;
- mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+ desc_handle_irq(IRQ_S3C2440_AC97, mydesc, regs);
}
}
}
@@ -122,11 +122,11 @@ static void s3c_irq_demux_cam(unsigned int irq,
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
- mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+ desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
- mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+ desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
}
}
}
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 765a3a9ae032..c0acfb2ad790 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -164,7 +164,7 @@ static void s3c2410_timer_setup (void)
/* configure the system for whichever machine is in use */
- if (machine_is_bast() || machine_is_vr1000()) {
+ if (machine_is_bast() || machine_is_vr1000() || machine_is_anubis()) {
/* timer is at 12MHz, scaler is 1 */
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
tcnt = 12000000 / HZ;
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 4d4d303ee3a8..24687f511bf5 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -35,6 +35,7 @@
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
#include <asm/arch/assabet.h>
+#include <asm/arch/mcp.h>
#include "generic.h"
@@ -198,6 +199,11 @@ static struct irda_platform_data assabet_irda_data = {
.set_speed = assabet_irda_set_speed,
};
+static struct mcp_plat_data assabet_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
static void __init assabet_init(void)
{
/*
@@ -246,6 +252,7 @@ static void __init assabet_init(void)
sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources,
ARRAY_SIZE(assabet_flash_resources));
sa11x0_set_irda_data(&assabet_irda_data);
+ sa11x0_set_mcp_data(&assabet_mcp_data);
}
/*
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 0aa918e24c31..9484be7dc671 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -29,6 +29,7 @@
#include <asm/mach/serial_sa1100.h>
#include <asm/arch/cerf.h>
+#include <asm/arch/mcp.h>
#include "generic.h"
static struct resource cerfuart2_resources[] = {
@@ -116,10 +117,16 @@ static void __init cerf_map_io(void)
GPDR |= CERF_GPIO_CF_RESET;
}
+static struct mcp_plat_data cerf_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
static void __init cerf_init(void)
{
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
sa11x0_set_flash_data(&cerf_flash_data, &cerf_flash_resource, 1);
+ sa11x0_set_mcp_data(&cerf_mcp_data);
}
MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 95ae217be1bc..3f1e358455e5 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -221,6 +221,11 @@ static struct platform_device sa11x0mcp_device = {
.resource = sa11x0mcp_resources,
};
+void sa11x0_set_mcp_data(struct mcp_plat_data *data)
+{
+ sa11x0mcp_device.dev.platform_data = data;
+}
+
static struct resource sa11x0ssp_resources[] = {
[0] = {
.start = 0x80070000,
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index bfe41da9923e..279e3afa3c39 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -34,5 +34,8 @@ struct resource;
extern void sa11x0_set_flash_data(struct flash_platform_data *flash,
struct resource *res, int nr);
+struct sa11x0_ssp_plat_ops;
+extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops);
+
struct irda_platform_data;
void sa11x0_set_irda_data(struct irda_platform_data *irda);
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 66a929cb7bc5..c131a5201b5b 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -98,8 +98,8 @@ static struct irqchip sa1100_low_gpio_chip = {
.ack = sa1100_low_gpio_ack,
.mask = sa1100_low_gpio_mask,
.unmask = sa1100_low_gpio_unmask,
- .type = sa1100_gpio_type,
- .wake = sa1100_low_gpio_wake,
+ .set_type = sa1100_gpio_type,
+ .set_wake = sa1100_low_gpio_wake,
};
/*
@@ -126,7 +126,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
mask >>= 11;
do {
if (mask & 1)
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
mask >>= 1;
irq++;
desc++;
@@ -181,8 +181,8 @@ static struct irqchip sa1100_high_gpio_chip = {
.ack = sa1100_high_gpio_ack,
.mask = sa1100_high_gpio_mask,
.unmask = sa1100_high_gpio_unmask,
- .type = sa1100_gpio_type,
- .wake = sa1100_high_gpio_wake,
+ .set_type = sa1100_gpio_type,
+ .set_wake = sa1100_high_gpio_wake,
};
/*
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 870b488aeda4..ed6744d480af 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -13,12 +13,23 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
#include "generic.h"
#warning "include/asm/arch-sa1100/ide.h needs fixing for lart"
+static struct mcp_plat_data lart_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
+static void __init lart_init(void)
+{
+ sa11x0_set_mcp_data(&lart_mcp_data);
+}
+
static struct map_desc lart_io_desc[] __initdata = {
/* virtual physical length type */
{ 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */
@@ -47,5 +58,6 @@ MACHINE_START(LART, "LART")
.boot_params = 0xc0000100,
.map_io = lart_map_io,
.init_irq = sa1100_init_irq,
+ .init_machine = lart_init,
.timer = &sa1100_timer,
MACHINE_END
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 1405383463ea..fc061641b7be 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -61,12 +61,12 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
if (irr & IRR_ETHERNET) {
d = irq_desc + IRQ_NEPONSET_SMC9196;
- d->handle(IRQ_NEPONSET_SMC9196, d, regs);
+ desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
}
if (irr & IRR_USAR) {
d = irq_desc + IRQ_NEPONSET_USAR;
- d->handle(IRQ_NEPONSET_USAR, d, regs);
+ desc_handle_irq(IRQ_NEPONSET_USAR, d, regs);
}
desc->chip->unmask(irq);
@@ -74,7 +74,7 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
if (irr & IRR_SA1111) {
d = irq_desc + IRQ_NEPONSET_SA1111;
- d->handle(IRQ_NEPONSET_SA1111, d, regs);
+ desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs);
}
}
}
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 43a00359fcdd..7482288278d9 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -18,6 +18,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
#include <asm/arch/shannon.h>
#include "generic.h"
@@ -52,9 +53,15 @@ static struct resource shannon_flash_resource = {
.flags = IORESOURCE_MEM,
};
+static struct mcp_plat_data shannon_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
static void __init shannon_init(void)
{
sa11x0_set_flash_data(&shannon_flash_data, &shannon_flash_resource, 1);
+ sa11x0_set_mcp_data(&shannon_mcp_data);
}
static void __init shannon_map_io(void)
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 77978586b126..07f6d5fd7bb0 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -23,6 +23,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
+#include <asm/arch/mcp.h>
#include <asm/arch/simpad.h>
#include <linux/serial_core.h>
@@ -123,6 +124,11 @@ static struct resource simpad_flash_resources [] = {
}
};
+static struct mcp_plat_data simpad_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
static void __init simpad_map_io(void)
@@ -157,6 +163,7 @@ static void __init simpad_map_io(void)
sa11x0_set_flash_data(&simpad_flash_data, simpad_flash_resources,
ARRAY_SIZE(simpad_flash_resources));
+ sa11x0_set_mcp_data(&simpad_mcp_data);
}
static void simpad_power_off(void)
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 0eeb3616ffea..47e0420623fc 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void)
return usec;
}
-/*
- * We will be entered with IRQs enabled.
- *
- * Loop until we get ahead of the free running timer.
- * This ensures an exact clock tick count and time accuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
- */
+#ifdef CONFIG_NO_IDLE_HZ
+static unsigned long initial_match;
+static int match_posponed;
+#endif
+
static irqreturn_t
sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
+#ifdef CONFIG_NO_IDLE_HZ
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ }
+#endif
+
+ /*
+ * Loop until we get ahead of the free running timer.
+ * This ensures an exact clock tick count and time accuracy.
+ * Since IRQs are disabled at this point, coherence between
+ * lost_ticks(updated in do_timer()) and the match reg value is
+ * ensured, hence we can use do_gettimeofday() from interrupt
+ * handlers.
+ */
do {
timer_tick(regs);
OSSR = OSSR_M0; /* Clear match on timer 0 */
@@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void)
OSCR = 0; /* initialize free-running timer, force first match */
}
+#ifdef CONFIG_NO_IDLE_HZ
+static int sa1100_dyn_tick_enable_disable(void)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static void sa1100_dyn_tick_reprogram(unsigned long ticks)
+{
+ if (ticks > 1) {
+ initial_match = OSMR0;
+ OSMR0 = initial_match + ticks * LATCH;
+ match_posponed = 1;
+ }
+}
+
+static irqreturn_t
+sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (match_posponed) {
+ match_posponed = 0;
+ OSMR0 = initial_match;
+ if ((signed long)(initial_match - OSCR) <= 0)
+ return sa1100_timer_interrupt(irq, dev_id, regs);
+ }
+ return IRQ_NONE;
+}
+
+static struct dyn_tick_timer sa1100_dyn_tick = {
+ .enable = sa1100_dyn_tick_enable_disable,
+ .disable = sa1100_dyn_tick_enable_disable,
+ .reprogram = sa1100_dyn_tick_reprogram,
+ .handler = sa1100_dyn_tick_handler,
+};
+#endif
+
#ifdef CONFIG_PM
unsigned long osmr[4], oier;
@@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
.suspend = sa1100_timer_suspend,
.resume = sa1100_timer_resume,
.offset = sa1100_gettimeoffset,
+#ifdef CONFIG_NO_IDLE_HZ
+ .dyn_tick = &sa1100_dyn_tick,
+#endif
};
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index e737eae4521f..946c0d11c73b 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -41,7 +41,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index f01c0f8a2bb3..3c8862fde51a 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -108,7 +108,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
irq += IRQ_SIC_START;
desc = irq_desc + irq;
- desc->handle(irq, desc, regs);
+ desc_handle_irq(irq, desc, regs);
} while (status);
}
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 81f4a8a2d34b..4b39d867ac14 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -45,7 +45,7 @@
#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
-#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
+#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */
#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
@@ -68,6 +68,7 @@ static unsigned long ai_sys;
static unsigned long ai_skipped;
static unsigned long ai_half;
static unsigned long ai_word;
+static unsigned long ai_dword;
static unsigned long ai_multi;
static int ai_usermode;
@@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
p += sprintf(p, "Half:\t\t%lu\n", ai_half);
p += sprintf(p, "Word:\t\t%lu\n", ai_word);
+ if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
+ p += sprintf(p, "DWord:\t\t%lu\n", ai_dword);
p += sprintf(p, "Multi:\t\t%lu\n", ai_multi);
p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
usermode_action[ai_usermode]);
@@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
{
unsigned int rd = RD_BITS(instr);
- if ((instr & 0x01f00ff0) == 0x01000090)
- goto swp;
-
- if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
- goto bad;
-
ai_half += 1;
if (user_mode(regs))
@@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
return TYPE_LDST;
- swp:
- printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
- bad:
- return TYPE_ERROR;
+ fault:
+ return TYPE_FAULT;
+}
+
+static int
+do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
+ struct pt_regs *regs)
+{
+ unsigned int rd = RD_BITS(instr);
+
+ ai_dword += 1;
+
+ if (user_mode(regs))
+ goto user;
+
+ if ((instr & 0xf0) == 0xd0) {
+ unsigned long val;
+ get32_unaligned_check(val, addr);
+ regs->uregs[rd] = val;
+ get32_unaligned_check(val, addr+4);
+ regs->uregs[rd+1] = val;
+ } else {
+ put32_unaligned_check(regs->uregs[rd], addr);
+ put32_unaligned_check(regs->uregs[rd+1], addr+4);
+ }
+
+ return TYPE_LDST;
+
+ user:
+ if ((instr & 0xf0) == 0xd0) {
+ unsigned long val;
+ get32t_unaligned_check(val, addr);
+ regs->uregs[rd] = val;
+ get32t_unaligned_check(val, addr+4);
+ regs->uregs[rd+1] = val;
+ } else {
+ put32t_unaligned_check(regs->uregs[rd], addr);
+ put32t_unaligned_check(regs->uregs[rd+1], addr+4);
+ }
+
+ return TYPE_LDST;
fault:
return TYPE_FAULT;
@@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
switch (CODING_BITS(instr)) {
- case 0x00000000: /* ldrh or strh */
- if (LDSTH_I_BIT(instr))
+ case 0x00000000: /* 3.13.4 load/store instruction extensions */
+ if (LDSTHD_I_BIT(instr))
offset.un = (instr & 0xf00) >> 4 | (instr & 15);
else
offset.un = regs->uregs[RM_BITS(instr)];
- handler = do_alignment_ldrhstrh;
+
+ if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
+ (instr & 0x001000f0) == 0x001000f0) /* LDRSH */
+ handler = do_alignment_ldrhstrh;
+ else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
+ (instr & 0x001000f0) == 0x000000f0) /* STRD */
+ handler = do_alignment_ldrdstrd;
+ else
+ goto bad;
break;
case 0x04000000: /* ldr or str immediate */
diff --git a/arch/arm/mm/copypage-v3.S b/arch/arm/mm/copypage-v3.S
index 4940f1908316..3c58ebbf0359 100644
--- a/arch/arm/mm/copypage-v3.S
+++ b/arch/arm/mm/copypage-v3.S
@@ -12,7 +12,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
.text
.align 5
diff --git a/arch/arm/mm/copypage-v4wb.S b/arch/arm/mm/copypage-v4wb.S
index b94c345ceb94..83117354b1cd 100644
--- a/arch/arm/mm/copypage-v4wb.S
+++ b/arch/arm/mm/copypage-v4wb.S
@@ -11,7 +11,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
.text
.align 5
diff --git a/arch/arm/mm/copypage-v4wt.S b/arch/arm/mm/copypage-v4wt.S
index 976793937a93..e1f2af28d549 100644
--- a/arch/arm/mm/copypage-v4wt.S
+++ b/arch/arm/mm/copypage-v4wt.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
.text
.align 5
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 191788fb18d1..b0208c992576 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -16,6 +16,58 @@
#include <asm/tlbflush.h>
#ifdef CONFIG_CPU_CACHE_VIPT
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+ if (cache_is_vivt()) {
+ if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
+ __cpuc_flush_user_all();
+ return;
+ }
+
+ if (cache_is_vipt_aliasing()) {
+ asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c5, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4"
+ :
+ : "r" (0)
+ : "cc");
+ }
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+{
+ if (cache_is_vivt()) {
+ if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask))
+ __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end),
+ vma->vm_flags);
+ return;
+ }
+
+ if (cache_is_vipt_aliasing()) {
+ asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c5, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4"
+ :
+ : "r" (0)
+ : "cc");
+ }
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
+{
+ if (cache_is_vivt()) {
+ if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
+ unsigned long addr = user_addr & PAGE_MASK;
+ __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
+ }
+ return;
+ }
+
+ if (cache_is_vipt_aliasing())
+ flush_pfn_alias(pfn, user_addr);
+}
+
#define ALIAS_FLUSH_START 0xffff4000
#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 3c655c54e231..d125a3dc061c 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
int i;
for (i = 0; i < 16; i += 1) {
- alloc_init_section(virt, phys & SUPERSECTION_MASK,
- prot | PMD_SECT_SUPER);
+ alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
virt += (PGDIR_SIZE / 2);
- phys += (PGDIR_SIZE / 2);
}
}
@@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
pte_t *ptep;
if (pmd_none(*pmdp)) {
- unsigned long pmdval;
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
sizeof(pte_t));
- pmdval = __pa(ptep) | prot_l1;
- pmdp[0] = __pmd(pmdval);
- pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
- flush_pmd_entry(pmdp);
+ __pmd_populate(pmdp, __pa(ptep) | prot_l1);
}
ptep = pte_offset_kernel(pmdp, virt);
@@ -459,7 +453,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
- v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
+ v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
@@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
*/
void setup_mm_for_reboot(char mode)
{
- unsigned long pmdval;
+ unsigned long base_pmdval;
pgd_t *pgd;
- pmd_t *pmd;
int i;
- int cpu_arch = cpu_architecture();
if (current->mm && current->mm->pgd)
pgd = current->mm->pgd;
else
pgd = init_mm.pgd;
- for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
- pmdval = (i << PGDIR_SHIFT) |
- PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
- PMD_TYPE_SECT;
- if (cpu_arch <= CPU_ARCH_ARMv5TEJ)
- pmdval |= PMD_BIT4;
+ base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
+ if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
+ base_pmdval |= PMD_BIT4;
+
+ for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+ unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+ pmd_t *pmd;
+
pmd = pmd_off(pgd, i << PGDIR_SHIFT);
pmd[0] = __pmd(pmdval);
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 5c0ae5260d1c..1d739d282a45 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -28,7 +28,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index d69389c4d4ba..9b725665b5c7 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -28,7 +28,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 747ed963e1df..37b70fa21c76 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -17,7 +17,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 248110c9cf13..931b690d1be2 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -17,7 +17,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 0ee214b824ff..d0f1bbb48f6c 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -13,7 +13,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
@@ -38,8 +38,8 @@ ENTRY(cpu_arm7_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r8, [r0] @ read arm instruction
- tst r8, #1 << 20 @ L = 1 -> write?
- orreq r1, r1, #1 << 8 @ yes.
+ tst r8, #1 << 20 @ L = 0 -> write?
+ orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #15 << 24
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
nop
@@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r8, [r2] @ read arm instruction
- tst r8, #1 << 20 @ L = 1 -> write?
- orreq r1, r1, #1 << 8 @ yes.
+ tst r8, #1 << 20 @ L = 0 -> write?
+ orreq r1, r1, #1 << 11 @ yes.
and r7, r8, #14 << 24
teq r7, #8 << 24 @ was it ldm/stm
movne pc, lr
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 57cfa6a2f54f..c69c9de32391 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -33,7 +33,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 9137fe563599..7cfc2604a1ee 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -4,7 +4,7 @@
* VMA_VM_FLAGS
* VM_EXEC
*/
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
/*
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 360cae905692..34f7e7d3f419 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -15,7 +15,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/hardware.h>
#include <asm/pgtable.h>
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index d447cd5f3dd9..ca14f80d5ab4 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -20,7 +20,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/hardware.h>
#include <asm/pgtable.h>
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 139a38670c5d..eb34823c9dbf 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -11,7 +11,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/pgtable.h>
diff --git a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
index 44b0daeaff9b..c10786ec8e0a 100644
--- a/arch/arm/mm/tlb-v3.S
+++ b/arch/arm/mm/tlb-v3.S
@@ -13,7 +13,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index db82ee468248..d6c94457c2b9 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index 7908d5f1f130..cb829ca7845d 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
diff --git a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S
index efbe94bbe1a7..60cfc4a25dd5 100644
--- a/arch/arm/mm/tlb-v4wbi.S
+++ b/arch/arm/mm/tlb-v4wbi.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index 99ed26e78adf..6f76b89ef46e 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -11,7 +11,7 @@
* These assume a split I/D TLB.
*/
#include <linux/linkage.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S
index 0ed38b0913db..51940a96d6a6 100644
--- a/arch/arm/nwfpe/entry26.S
+++ b/arch/arm/nwfpe/entry26.S
@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
/* This is the kernel's entry point into the floating point emulator.
It is called from the kernel with code similar to this:
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 345365852f8c..9693e9b4ffd1 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -91,6 +91,13 @@ config OMAP_32K_TIMER_HZ
Kernel internal timer frequency should be a divisor of 32768,
such as 64 or 128.
+config OMAP_DM_TIMER
+ bool "Use dual-mode timer"
+ default n
+ depends on ARCH_OMAP16XX
+ help
+ Select this option if you want to use OMAP Dual-Mode timers.
+
choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
@@ -107,6 +114,15 @@ config OMAP_LL_DEBUG_UART3
endchoice
+config OMAP_SERIAL_WAKE
+ bool "Enable wake-up events for serial ports"
+ depends OMAP_MUX
+ default y
+ help
+ Select this option if you want to have your system wake up
+ to data on the serial RX line. This allows you to wake the
+ system from serial console.
+
endmenu
endif
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 531e11af54d4..7e144f9cad1c 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
obj-m :=
obj-n :=
obj- :=
@@ -15,3 +15,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
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 59d91b3262ba..52a58b2da288 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
#include <asm/arch/usb.h>
#include "clock.h"
+#include "sram.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
@@ -141,7 +142,7 @@ static struct clk arm_ck = {
static struct clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP730 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_PERCK,
@@ -385,7 +386,8 @@ static struct clk uart2_ck = {
.name = "uart2_ck",
/* Direct from ULPD, no parent */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
+ ALWAYS_ENABLED,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &set_uart_rate,
@@ -443,6 +445,15 @@ static struct clk usb_hhc_ck16xx = {
.enable_bit = 8 /* UHOST_EN */,
};
+static struct clk usb_dc_ck = {
+ .name = "usb_dc_ck",
+ /* Direct from ULPD, no parent */
+ .rate = 48000000,
+ .flags = CLOCK_IN_OMAP16XX | RATE_FIXED,
+ .enable_reg = SOFT_REQ_REG,
+ .enable_bit = 4,
+};
+
static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
@@ -552,6 +563,7 @@ static struct clk * onchip_clks[] = {
&uart3_16xx,
&usb_clko,
&usb_hhc_ck1510, &usb_hhc_ck16xx,
+ &usb_dc_ck,
&mclk_1510, &mclk_16xx,
&bclk_1510, &bclk_16xx,
&mmc1_ck,
@@ -946,14 +958,13 @@ static int select_table_rate(struct clk * clk, unsigned long rate)
if (!ptr->rate)
return -EINVAL;
- if (!ptr->rate)
- return -EINVAL;
+ /*
+ * In most cases we should not need to reprogram DPLL.
+ * Reprogramming the DPLL is tricky, it must be done from SRAM.
+ */
+ omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
- if (unlikely(ck_dpll1.rate == 0)) {
- omap_writew(ptr->dpllctl_val, DPLL_CTL);
- ck_dpll1.rate = ptr->pll_rate;
- }
- omap_writew(ptr->ckctl_val, ARM_CKCTL);
+ ck_dpll1.rate = ptr->pll_rate;
propagate_rate(&ck_dpll1);
return 0;
}
@@ -1224,9 +1235,11 @@ int __init clk_init(void)
#endif
/* Cache rates for clocks connected to ck_ref (not dpll1) */
propagate_rate(&ck_ref);
- printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld/%ld MHz\n",
+ printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
+ "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
- ck_dpll1.rate, arm_ck.rate);
+ ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+ arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
@@ -1271,7 +1284,9 @@ static int __init omap_late_clk_reset(void)
struct clk *p;
__u32 regval32;
- omap_writew(0, SOFT_REQ_REG);
+ /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+ regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
+ omap_writew(regval32, SOFT_REQ_REG);
omap_writew(0, SOFT_REQ_REG2);
list_for_each_entry(p, &clocks, node) {
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index ea967a8f6ce5..6cb20aea7f51 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -26,6 +26,7 @@
#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/mach-types.h>
+#include <asm/setup.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
@@ -35,11 +36,11 @@
#define NO_LENGTH_CHECK 0xffffffff
-extern int omap_bootloader_tag_len;
-extern u8 omap_bootloader_tag[];
+unsigned char omap_bootloader_tag[512];
+int omap_bootloader_tag_len;
struct omap_board_config_kernel *omap_board_config;
-int omap_board_config_size = 0;
+int omap_board_config_size;
static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
{
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c0a5c2fa42bd..da7b65145658 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -425,7 +425,7 @@ static int dma_handle_ch(int ch)
dma_chan[ch + 6].saved_csr = csr >> 7;
csr &= 0x7f;
}
- if (!csr)
+ if ((csr & 0x3f) == 0)
return 0;
if (unlikely(dma_chan[ch].dev_id == -1)) {
printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
@@ -890,11 +890,11 @@ void omap_enable_lcd_dma(void)
w |= 1 << 8;
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+ lcd_dma.active = 1;
+
w = omap_readw(OMAP1610_DMA_LCD_CCR);
w |= 1 << 7;
omap_writew(w, OMAP1610_DMA_LCD_CCR);
-
- lcd_dma.active = 1;
}
void omap_setup_lcd_dma(void)
@@ -965,8 +965,8 @@ void omap_clear_dma(int lch)
*/
dma_addr_t omap_get_dma_src_pos(int lch)
{
- return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
- (OMAP_DMA_CSSA_U(lch) << 16));
+ return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) |
+ (omap_readw(OMAP_DMA_CSSA_U(lch)) << 16));
}
/*
@@ -979,8 +979,18 @@ dma_addr_t omap_get_dma_src_pos(int lch)
*/
dma_addr_t omap_get_dma_dst_pos(int lch)
{
- return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
- (OMAP_DMA_CDSA_U(lch) << 16));
+ return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) |
+ (omap_readw(OMAP_DMA_CDSA_U(lch)) << 16));
+}
+
+/*
+ * Returns current source transfer counting for the given DMA channel.
+ * Can be used to monitor the progress of a transfer inside a block.
+ * It must be called with disabled interrupts.
+ */
+int omap_get_dma_src_addr_counter(int lch)
+{
+ return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch));
}
int omap_dma_running(void)
@@ -1076,6 +1086,7 @@ arch_initcall(omap_init_dma);
EXPORT_SYMBOL(omap_get_dma_src_pos);
EXPORT_SYMBOL(omap_get_dma_dst_pos);
+EXPORT_SYMBOL(omap_get_dma_src_addr_counter);
EXPORT_SYMBOL(omap_clear_dma);
EXPORT_SYMBOL(omap_set_dma_priority);
EXPORT_SYMBOL(omap_request_dma);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
new file mode 100644
index 000000000000..a1468d7326eb
--- /dev/null
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -0,0 +1,260 @@
+/*
+ * linux/arch/arm/plat-omap/dmtimer.c
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS 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
+ * 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/init.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/dmtimer.h>
+#include <asm/io.h>
+#include <asm/arch/irqs.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#define OMAP_TIMER_COUNT 8
+
+#define OMAP_TIMER_ID_REG 0x00
+#define OMAP_TIMER_OCP_CFG_REG 0x10
+#define OMAP_TIMER_SYS_STAT_REG 0x14
+#define OMAP_TIMER_STAT_REG 0x18
+#define OMAP_TIMER_INT_EN_REG 0x1c
+#define OMAP_TIMER_WAKEUP_EN_REG 0x20
+#define OMAP_TIMER_CTRL_REG 0x24
+#define OMAP_TIMER_COUNTER_REG 0x28
+#define OMAP_TIMER_LOAD_REG 0x2c
+#define OMAP_TIMER_TRIGGER_REG 0x30
+#define OMAP_TIMER_WRITE_PEND_REG 0x34
+#define OMAP_TIMER_MATCH_REG 0x38
+#define OMAP_TIMER_CAPTURE_REG 0x3c
+#define OMAP_TIMER_IF_CTRL_REG 0x40
+
+
+static struct dmtimer_info_struct {
+ struct list_head unused_timers;
+ struct list_head reserved_timers;
+} dm_timer_info;
+
+static struct omap_dm_timer dm_timers[] = {
+ { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },
+ { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },
+ { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },
+ { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },
+ { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },
+ { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },
+ { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },
+ { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },
+ { .base=0x0 },
+};
+
+
+static spinlock_t dm_timer_lock;
+
+
+inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
+{
+ omap_writel(value, timer->base + reg);
+ while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
+ ;
+}
+
+u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
+{
+ return omap_readl(timer->base + reg);
+}
+
+int omap_dm_timers_active(void)
+{
+ struct omap_dm_timer *timer;
+
+ for (timer = &dm_timers[0]; timer->base; ++timer)
+ if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
+ OMAP_TIMER_CTRL_ST)
+ return 1;
+
+ return 0;
+}
+
+
+void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+{
+ int n = (timer - dm_timers) << 1;
+ u32 l;
+
+ l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+ l |= source << n;
+ omap_writel(l, MOD_CONF_CTRL_1);
+}
+
+
+static void omap_dm_timer_reset(struct omap_dm_timer *timer)
+{
+ /* Reset and set posted mode */
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
+
+ omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
+}
+
+
+
+struct omap_dm_timer * omap_dm_timer_request(void)
+{
+ struct omap_dm_timer *timer = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dm_timer_lock, flags);
+ if (!list_empty(&dm_timer_info.unused_timers)) {
+ timer = (struct omap_dm_timer *)
+ dm_timer_info.unused_timers.next;
+ list_move_tail((struct list_head *)timer,
+ &dm_timer_info.reserved_timers);
+ }
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+ return timer;
+}
+
+
+void omap_dm_timer_free(struct omap_dm_timer *timer)
+{
+ unsigned long flags;
+
+ omap_dm_timer_reset(timer);
+
+ spin_lock_irqsave(&dm_timer_lock, flags);
+ list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
+}
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+ unsigned int value)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+}
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
+{
+ return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+}
+
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+}
+
+void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer)
+{
+ u32 l;
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ l |= OMAP_TIMER_CTRL_AR;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
+}
+
+void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
+{
+ u32 l;
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ l |= value & 0x3;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_start(struct omap_dm_timer *timer)
+{
+ u32 l;
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ l |= OMAP_TIMER_CTRL_ST;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+void omap_dm_timer_stop(struct omap_dm_timer *timer)
+{
+ u32 l;
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ l &= ~0x1;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
+{
+ return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+}
+
+void omap_dm_timer_reset_counter(struct omap_dm_timer *timer)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);
+}
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+}
+
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+}
+
+void omap_dm_timer_enable_compare(struct omap_dm_timer *timer)
+{
+ u32 l;
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ l |= OMAP_TIMER_CTRL_CE;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+
+
+static inline void __dm_timer_init(void)
+{
+ struct omap_dm_timer *timer;
+
+ spin_lock_init(&dm_timer_lock);
+ INIT_LIST_HEAD(&dm_timer_info.unused_timers);
+ INIT_LIST_HEAD(&dm_timer_info.reserved_timers);
+
+ timer = &dm_timers[0];
+ while (timer->base) {
+ list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
+ omap_dm_timer_reset(timer);
+ timer++;
+ }
+}
+
+static int __init omap_dm_timer_init(void)
+{
+ if (cpu_is_omap16xx())
+ __dm_timer_init();
+ return 0;
+}
+
+arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 1c85b4e536c2..55059a24ad41 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -3,7 +3,7 @@
*
* Support functions for OMAP GPIO
*
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003-2005 Nokia Corporation
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,11 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
#include <asm/hardware.h>
+#include <asm/hardware/clock.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
@@ -29,7 +32,7 @@
/*
* OMAP1510 GPIO registers
*/
-#define OMAP1510_GPIO_BASE 0xfffce000
+#define OMAP1510_GPIO_BASE (void __iomem *)0xfffce000
#define OMAP1510_GPIO_DATA_INPUT 0x00
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
#define OMAP1510_GPIO_DIR_CONTROL 0x08
@@ -43,34 +46,37 @@
/*
* OMAP1610 specific GPIO registers
*/
-#define OMAP1610_GPIO1_BASE 0xfffbe400
-#define OMAP1610_GPIO2_BASE 0xfffbec00
-#define OMAP1610_GPIO3_BASE 0xfffbb400
-#define OMAP1610_GPIO4_BASE 0xfffbbc00
+#define OMAP1610_GPIO1_BASE (void __iomem *)0xfffbe400
+#define OMAP1610_GPIO2_BASE (void __iomem *)0xfffbec00
+#define OMAP1610_GPIO3_BASE (void __iomem *)0xfffbb400
+#define OMAP1610_GPIO4_BASE (void __iomem *)0xfffbbc00
#define OMAP1610_GPIO_REVISION 0x0000
#define OMAP1610_GPIO_SYSCONFIG 0x0010
#define OMAP1610_GPIO_SYSSTATUS 0x0014
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
#define OMAP1610_GPIO_IRQENABLE1 0x001c
+#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
#define OMAP1610_GPIO_DATAIN 0x002c
#define OMAP1610_GPIO_DATAOUT 0x0030
#define OMAP1610_GPIO_DIRECTION 0x0034
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
+#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
+#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
/*
* OMAP730 specific GPIO registers
*/
-#define OMAP730_GPIO1_BASE 0xfffbc000
-#define OMAP730_GPIO2_BASE 0xfffbc800
-#define OMAP730_GPIO3_BASE 0xfffbd000
-#define OMAP730_GPIO4_BASE 0xfffbd800
-#define OMAP730_GPIO5_BASE 0xfffbe000
-#define OMAP730_GPIO6_BASE 0xfffbe800
+#define OMAP730_GPIO1_BASE (void __iomem *)0xfffbc000
+#define OMAP730_GPIO2_BASE (void __iomem *)0xfffbc800
+#define OMAP730_GPIO3_BASE (void __iomem *)0xfffbd000
+#define OMAP730_GPIO4_BASE (void __iomem *)0xfffbd800
+#define OMAP730_GPIO5_BASE (void __iomem *)0xfffbe000
+#define OMAP730_GPIO6_BASE (void __iomem *)0xfffbe800
#define OMAP730_GPIO_DATA_INPUT 0x00
#define OMAP730_GPIO_DATA_OUTPUT 0x04
#define OMAP730_GPIO_DIR_CONTROL 0x08
@@ -78,14 +84,43 @@
#define OMAP730_GPIO_INT_MASK 0x10
#define OMAP730_GPIO_INT_STATUS 0x14
+/*
+ * omap24xx specific GPIO registers
+ */
+#define OMAP24XX_GPIO1_BASE (void __iomem *)0x48018000
+#define OMAP24XX_GPIO2_BASE (void __iomem *)0x4801a000
+#define OMAP24XX_GPIO3_BASE (void __iomem *)0x4801c000
+#define OMAP24XX_GPIO4_BASE (void __iomem *)0x4801e000
+#define OMAP24XX_GPIO_REVISION 0x0000
+#define OMAP24XX_GPIO_SYSCONFIG 0x0010
+#define OMAP24XX_GPIO_SYSSTATUS 0x0014
+#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
+#define OMAP24XX_GPIO_IRQENABLE1 0x001c
+#define OMAP24XX_GPIO_CTRL 0x0030
+#define OMAP24XX_GPIO_OE 0x0034
+#define OMAP24XX_GPIO_DATAIN 0x0038
+#define OMAP24XX_GPIO_DATAOUT 0x003c
+#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
+#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
+#define OMAP24XX_GPIO_RISINGDETECT 0x0048
+#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
+#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
+#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
+#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
+#define OMAP24XX_GPIO_SETWKUENA 0x0084
+#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
+#define OMAP24XX_GPIO_SETDATAOUT 0x0094
+
#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff)
struct gpio_bank {
- u32 base;
+ void __iomem *base;
u16 irq;
u16 virtual_irq_start;
- u8 method;
+ int method;
u32 reserved_map;
+ u32 suspend_wakeup;
+ u32 saved_wakeup;
spinlock_t lock;
};
@@ -93,8 +128,9 @@ struct gpio_bank {
#define METHOD_GPIO_1510 1
#define METHOD_GPIO_1610 2
#define METHOD_GPIO_730 3
+#define METHOD_GPIO_24XX 4
-#if defined(CONFIG_ARCH_OMAP16XX)
+#ifdef CONFIG_ARCH_OMAP16XX
static struct gpio_bank gpio_bank_1610[5] = {
{ OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 },
@@ -123,6 +159,15 @@ static struct gpio_bank gpio_bank_730[7] = {
};
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+static struct gpio_bank gpio_bank_24xx[4] = {
+ { OMAP24XX_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX },
+ { OMAP24XX_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX },
+ { OMAP24XX_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX },
+ { OMAP24XX_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX },
+};
+#endif
+
static struct gpio_bank *gpio_bank;
static int gpio_bank_count;
@@ -149,14 +194,23 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
return &gpio_bank[1 + (gpio >> 5)];
}
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx())
+ return &gpio_bank[gpio >> 5];
+#endif
}
static inline int get_gpio_index(int gpio)
{
+#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730())
return gpio & 0x1f;
- else
- return gpio & 0x0f;
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx())
+ return gpio & 0x1f;
+#endif
+ return gpio & 0x0f;
}
static inline int gpio_valid(int gpio)
@@ -180,6 +234,10 @@ static inline int gpio_valid(int gpio)
if (cpu_is_omap730() && gpio < 192)
return 0;
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx() && gpio < 128)
+ return 0;
+#endif
return -1;
}
@@ -195,7 +253,7 @@ static int check_gpio(int gpio)
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
- u32 reg = bank->base;
+ void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@@ -211,6 +269,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DIR_CONTROL;
break;
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_OE;
+ break;
}
l = __raw_readl(reg);
if (is_input)
@@ -234,7 +295,7 @@ void omap_set_gpio_direction(int gpio, int is_input)
static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
{
- u32 reg = bank->base;
+ void __iomem *reg = bank->base;
u32 l = 0;
switch (bank->method) {
@@ -269,6 +330,13 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
else
l &= ~(1 << gpio);
break;
+ case METHOD_GPIO_24XX:
+ if (enable)
+ reg += OMAP24XX_GPIO_SETDATAOUT;
+ else
+ reg += OMAP24XX_GPIO_CLEARDATAOUT;
+ l = 1 << gpio;
+ break;
default:
BUG();
return;
@@ -291,7 +359,7 @@ void omap_set_gpio_dataout(int gpio, int enable)
int omap_get_gpio_datain(int gpio)
{
struct gpio_bank *bank;
- u32 reg;
+ void __iomem *reg;
if (check_gpio(gpio) < 0)
return -1;
@@ -310,109 +378,132 @@ int omap_get_gpio_datain(int gpio)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DATA_INPUT;
break;
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_DATAIN;
+ break;
default:
BUG();
return -1;
}
- return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+ return (__raw_readl(reg)
+ & (1 << get_gpio_index(gpio))) != 0;
}
-static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge)
+#define MOD_REG_BIT(reg, bit_mask, set) \
+do { \
+ int l = __raw_readl(base + reg); \
+ if (set) l |= bit_mask; \
+ else l &= ~bit_mask; \
+ __raw_writel(l, base + reg); \
+} while(0)
+
+static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger)
{
- u32 reg = bank->base;
- u32 l;
+ u32 gpio_bit = 1 << gpio;
+
+ MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+ trigger & IRQT_LOW);
+ MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+ trigger & IRQT_HIGH);
+ MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+ trigger & IRQT_RISING);
+ MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+ trigger & IRQT_FALLING);
+ /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
+ * triggering requested. */
+}
+
+static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+{
+ void __iomem *reg = bank->base;
+ u32 l = 0;
switch (bank->method) {
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
- if (edge == OMAP_GPIO_RISING_EDGE)
+ if (trigger == IRQT_RISING)
l |= 1 << gpio;
- else
+ else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
- __raw_writel(l, reg);
+ else
+ goto bad;
break;
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (edge == OMAP_GPIO_RISING_EDGE)
+ if (trigger == IRQT_RISING)
l |= 1 << gpio;
- else
+ else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
- __raw_writel(l, reg);
+ else
+ goto bad;
break;
case METHOD_GPIO_1610:
- edge &= 0x03;
if (gpio & 0x08)
reg += OMAP1610_GPIO_EDGE_CTRL2;
else
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
+ /* We allow only edge triggering, i.e. two lowest bits */
+ if (trigger & ~IRQT_BOTHEDGE)
+ BUG();
+ /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
+ trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
- l |= edge << (gpio << 1);
- __raw_writel(l, reg);
+ l |= trigger << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (edge == OMAP_GPIO_RISING_EDGE)
+ if (trigger == IRQT_RISING)
l |= 1 << gpio;
- else
+ else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
- __raw_writel(l, reg);
+ else
+ goto bad;
+ break;
+ case METHOD_GPIO_24XX:
+ set_24xx_gpio_triggering(reg, gpio, trigger);
break;
default:
BUG();
- return;
+ goto bad;
}
+ __raw_writel(l, reg);
+ return 0;
+bad:
+ return -EINVAL;
}
-void omap_set_gpio_edge_ctrl(int gpio, int edge)
+static int gpio_irq_type(unsigned irq, unsigned type)
{
struct gpio_bank *bank;
+ unsigned gpio;
+ int retval;
+
+ if (irq > IH_MPUIO_BASE)
+ gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
+ else
+ gpio = irq - IH_GPIO_BASE;
if (check_gpio(gpio) < 0)
- return;
+ return -EINVAL;
+
+ if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+ return -EINVAL;
+
bank = get_gpio_bank(gpio);
spin_lock(&bank->lock);
- _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge);
+ retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
spin_unlock(&bank->lock);
-}
-
-
-static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
-{
- u32 reg = bank->base, l;
-
- switch (bank->method) {
- case METHOD_MPUIO:
- l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE);
- return (l & (1 << gpio)) ?
- OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
- case METHOD_GPIO_1510:
- l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL);
- return (l & (1 << gpio)) ?
- OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
- case METHOD_GPIO_1610:
- if (gpio & 0x08)
- reg += OMAP1610_GPIO_EDGE_CTRL2;
- else
- reg += OMAP1610_GPIO_EDGE_CTRL1;
- return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03;
- case METHOD_GPIO_730:
- l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL);
- return (l & (1 << gpio)) ?
- OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
- default:
- BUG();
- return -1;
- }
+ return retval;
}
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
- u32 reg = bank->base;
+ void __iomem *reg = bank->base;
switch (bank->method) {
case METHOD_MPUIO:
@@ -428,6 +519,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_STATUS;
break;
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_IRQSTATUS1;
+ break;
default:
BUG();
return;
@@ -442,7 +536,7 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
- u32 reg = bank->base;
+ void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@@ -477,6 +571,13 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
else
l |= gpio_mask;
break;
+ case METHOD_GPIO_24XX:
+ if (enable)
+ reg += OMAP24XX_GPIO_SETIRQENABLE1;
+ else
+ reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
+ l = gpio_mask;
+ break;
default:
BUG();
return;
@@ -489,6 +590,50 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
_enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
}
+/*
+ * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
+ * 1510 does not seem to have a wake-up register. If JTAG is connected
+ * to the target, system will wake up always on GPIO events. While
+ * system is running all registered GPIO interrupts need to have wake-up
+ * enabled. When system is suspended, only selected GPIO interrupts need
+ * to have wake-up enabled.
+ */
+static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
+{
+ switch (bank->method) {
+ case METHOD_GPIO_1610:
+ case METHOD_GPIO_24XX:
+ spin_lock(&bank->lock);
+ if (enable)
+ bank->suspend_wakeup |= (1 << gpio);
+ else
+ bank->suspend_wakeup &= ~(1 << gpio);
+ spin_unlock(&bank->lock);
+ return 0;
+ default:
+ printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
+ bank->method);
+ return -EINVAL;
+ }
+}
+
+/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
+static int gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+ unsigned int gpio = irq - IH_GPIO_BASE;
+ struct gpio_bank *bank;
+ int retval;
+
+ if (check_gpio(gpio) < 0)
+ return -ENODEV;
+ bank = get_gpio_bank(gpio);
+ spin_lock(&bank->lock);
+ retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
+ spin_unlock(&bank->lock);
+
+ return retval;
+}
+
int omap_request_gpio(int gpio)
{
struct gpio_bank *bank;
@@ -505,15 +650,33 @@ int omap_request_gpio(int gpio)
return -1;
}
bank->reserved_map |= (1 << get_gpio_index(gpio));
+
+ /* Set trigger to none. You need to enable the trigger after request_irq */
+ _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
+
#ifdef CONFIG_ARCH_OMAP1510
if (bank->method == METHOD_GPIO_1510) {
- u32 reg;
+ void __iomem *reg;
- /* Claim the pin for the ARM */
+ /* Claim the pin for MPU */
reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
__raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
}
#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ if (bank->method == METHOD_GPIO_1610) {
+ /* Enable wake-up during idle for dynamic tick */
+ void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+ __raw_writel(1 << get_gpio_index(gpio), reg);
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (bank->method == METHOD_GPIO_24XX) {
+ /* Enable wake-up during idle for dynamic tick */
+ void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA;
+ __raw_writel(1 << get_gpio_index(gpio), reg);
+ }
+#endif
spin_unlock(&bank->lock);
return 0;
@@ -533,6 +696,20 @@ void omap_free_gpio(int gpio)
spin_unlock(&bank->lock);
return;
}
+#ifdef CONFIG_ARCH_OMAP16XX
+ if (bank->method == METHOD_GPIO_1610) {
+ /* Disable wake-up during idle for dynamic tick */
+ void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+ __raw_writel(1 << get_gpio_index(gpio), reg);
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (bank->method == METHOD_GPIO_24XX) {
+ /* Disable wake-up during idle for dynamic tick */
+ void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+ __raw_writel(1 << get_gpio_index(gpio), reg);
+ }
+#endif
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
@@ -552,7 +729,7 @@ void omap_free_gpio(int gpio)
static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
- u32 isr_reg = 0;
+ void __iomem *isr_reg = NULL;
u32 isr;
unsigned int gpio_irq;
struct gpio_bank *bank;
@@ -574,24 +751,30 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_730)
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (bank->method == METHOD_GPIO_24XX)
+ isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
+#endif
- 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);
-
- if (unlikely(!isr))
- return;
-
- gpio_irq = bank->virtual_irq_start;
- for (; isr != 0; isr >>= 1, gpio_irq++) {
- struct irqdesc *d;
- if (!(isr & 1))
- continue;
- d = irq_desc + gpio_irq;
- d->handle(gpio_irq, d, regs);
- }
+ 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);
+
+ if (!isr)
+ break;
+
+ gpio_irq = bank->virtual_irq_start;
+ for (; isr != 0; isr >>= 1, gpio_irq++) {
+ struct irqdesc *d;
+ if (!(isr & 1))
+ continue;
+ d = irq_desc + gpio_irq;
+ desc_handle_irq(gpio_irq, d, regs);
+ }
+ }
}
static void gpio_ack_irq(unsigned int irq)
@@ -613,14 +796,10 @@ static void gpio_mask_irq(unsigned int irq)
static void gpio_unmask_irq(unsigned int irq)
{
unsigned int gpio = irq - IH_GPIO_BASE;
+ unsigned int gpio_idx = get_gpio_index(gpio);
struct gpio_bank *bank = get_gpio_bank(gpio);
- if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
- printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n",
- gpio);
- _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
- }
- _set_gpio_irqenable(bank, gpio, 1);
+ _set_gpio_irqenable(bank, gpio_idx, 1);
}
static void mpuio_ack_irq(unsigned int irq)
@@ -645,9 +824,11 @@ static void mpuio_unmask_irq(unsigned int irq)
}
static struct irqchip gpio_irq_chip = {
- .ack = gpio_ack_irq,
- .mask = gpio_mask_irq,
- .unmask = gpio_unmask_irq,
+ .ack = gpio_ack_irq,
+ .mask = gpio_mask_irq,
+ .unmask = gpio_unmask_irq,
+ .set_type = gpio_irq_type,
+ .set_wake = gpio_wake_enable,
};
static struct irqchip mpuio_irq_chip = {
@@ -657,6 +838,7 @@ static struct irqchip mpuio_irq_chip = {
};
static int initialized = 0;
+static struct clk * gpio_ck = NULL;
static int __init _omap_gpio_init(void)
{
@@ -665,6 +847,14 @@ static int __init _omap_gpio_init(void)
initialized = 1;
+ if (cpu_is_omap1510()) {
+ gpio_ck = clk_get(NULL, "arm_gpio_ck");
+ if (IS_ERR(gpio_ck))
+ printk("Could not get arm_gpio_ck\n");
+ else
+ clk_use(gpio_ck);
+ }
+
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
@@ -674,7 +864,7 @@ static int __init _omap_gpio_init(void)
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
- int rev;
+ u32 rev;
gpio_bank_count = 5;
gpio_bank = gpio_bank_1610;
@@ -690,6 +880,17 @@ static int __init _omap_gpio_init(void)
gpio_bank = gpio_bank_730;
}
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx()) {
+ int rev;
+
+ gpio_bank_count = 4;
+ gpio_bank = gpio_bank_24xx;
+ rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+ printk(KERN_INFO "OMAP24xx GPIO hardware version %d.%d\n",
+ (rev >> 4) & 0x0f, rev & 0x0f);
+ }
+#endif
for (i = 0; i < gpio_bank_count; i++) {
int j, gpio_count = 16;
@@ -710,6 +911,7 @@ static int __init _omap_gpio_init(void)
if (bank->method == METHOD_GPIO_1610) {
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
+ __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
}
#endif
#ifdef CONFIG_ARCH_OMAP730
@@ -720,6 +922,14 @@ static int __init _omap_gpio_init(void)
gpio_count = 32; /* 730 has 32-bit GPIOs */
}
#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (bank->method == METHOD_GPIO_24XX) {
+ __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
+ __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
+
+ gpio_count = 32;
+ }
+#endif
for (j = bank->virtual_irq_start;
j < bank->virtual_irq_start + gpio_count; j++) {
if (bank->method == METHOD_MPUIO)
@@ -735,12 +945,97 @@ static int __init _omap_gpio_init(void)
/* Enable system clock for GPIO module.
* The CAM_CLK_CTRL *is* really the right place. */
- if (cpu_is_omap1610() || cpu_is_omap1710())
+ if (cpu_is_omap16xx())
omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
return 0;
}
+#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
+static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+{
+ int i;
+
+ if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+ return 0;
+
+ for (i = 0; i < gpio_bank_count; i++) {
+ struct gpio_bank *bank = &gpio_bank[i];
+ void __iomem *wake_status;
+ void __iomem *wake_clear;
+ void __iomem *wake_set;
+
+ switch (bank->method) {
+ case METHOD_GPIO_1610:
+ wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
+ wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+ wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+ break;
+ case METHOD_GPIO_24XX:
+ wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
+ wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+ wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+ break;
+ default:
+ continue;
+ }
+
+ spin_lock(&bank->lock);
+ bank->saved_wakeup = __raw_readl(wake_status);
+ __raw_writel(0xffffffff, wake_clear);
+ __raw_writel(bank->suspend_wakeup, wake_set);
+ spin_unlock(&bank->lock);
+ }
+
+ return 0;
+}
+
+static int omap_gpio_resume(struct sys_device *dev)
+{
+ int i;
+
+ if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+ return 0;
+
+ for (i = 0; i < gpio_bank_count; i++) {
+ struct gpio_bank *bank = &gpio_bank[i];
+ void __iomem *wake_clear;
+ void __iomem *wake_set;
+
+ switch (bank->method) {
+ case METHOD_GPIO_1610:
+ wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+ wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+ break;
+ case METHOD_GPIO_24XX:
+ wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+ wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+ break;
+ default:
+ continue;
+ }
+
+ spin_lock(&bank->lock);
+ __raw_writel(0xffffffff, wake_clear);
+ __raw_writel(bank->saved_wakeup, wake_set);
+ spin_unlock(&bank->lock);
+ }
+
+ return 0;
+}
+
+static struct sysdev_class omap_gpio_sysclass = {
+ set_kset_name("gpio"),
+ .suspend = omap_gpio_suspend,
+ .resume = omap_gpio_resume,
+};
+
+static struct sys_device omap_gpio_device = {
+ .id = 0,
+ .cls = &omap_gpio_sysclass,
+};
+#endif
+
/*
* This may get called early from board specific init
*/
@@ -752,11 +1047,30 @@ int omap_gpio_init(void)
return 0;
}
+static int __init omap_gpio_sysinit(void)
+{
+ int ret = 0;
+
+ if (!initialized)
+ ret = _omap_gpio_init();
+
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
+ if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ if (ret == 0) {
+ ret = sysdev_class_register(&omap_gpio_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&omap_gpio_device);
+ }
+ }
+#endif
+
+ return ret;
+}
+
EXPORT_SYMBOL(omap_request_gpio);
EXPORT_SYMBOL(omap_free_gpio);
EXPORT_SYMBOL(omap_set_gpio_direction);
EXPORT_SYMBOL(omap_set_gpio_dataout);
EXPORT_SYMBOL(omap_get_gpio_datain);
-EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
-arch_initcall(omap_gpio_init);
+arch_initcall(omap_gpio_sysinit);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 43567d5edddb..9c9b7df3faf6 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -27,6 +27,7 @@
#include <asm/arch/dma.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
+#include <asm/arch/dsp_common.h>
#include <asm/arch/mcbsp.h>
#include <asm/hardware/clock.h>
@@ -187,9 +188,6 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
-#define EN_XORPCK 1
-#define DSP_RSTCT2 0xe1008014
-
static void omap_mcbsp_dsp_request(void)
{
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
@@ -198,6 +196,11 @@ static void omap_mcbsp_dsp_request(void)
/* enable 12MHz clock to mcbsp 1 & 3 */
clk_use(mcbsp_dspxor_ck);
+
+ /*
+ * DSP external peripheral reset
+ * FIXME: This should be moved to dsp code
+ */
__raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
DSP_RSTCT2);
}
diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c
index ea7b955b9c81..64482040f89e 100644
--- a/arch/arm/plat-omap/mux.c
+++ b/arch/arm/plat-omap/mux.c
@@ -48,6 +48,9 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
pull_orig = 0, pull = 0;
unsigned int mask, warn = 0;
+ if (cpu_is_omap7xx())
+ return 0;
+
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
return -EINVAL;
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 2ede2ee8cae4..1fb16f9edfd5 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index e6536b16c385..e15c6c1ddec9 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -39,24 +39,32 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pm.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/mach/time.h>
-#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
-#include <asm/arch/omap16xx.h>
+#include <asm/mach-types.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/tc.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
-#include <asm/arch/tc.h>
#include <asm/arch/tps65010.h>
+#include <asm/arch/dsp_common.h>
#include "clock.h"
+#include "sram.h"
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+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
@@ -65,7 +73,6 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
*/
void omap_pm_idle(void)
{
- int (*func_ptr)(void) = 0;
unsigned int mask32 = 0;
/*
@@ -84,6 +91,13 @@ void omap_pm_idle(void)
mask32 = omap_readl(ARM_SYSST);
/*
+ * Prevent the ULPD from entering low power state by setting
+ * POWER_CTRL_REG:4 = 0
+ */
+ omap_writew(omap_readw(ULPD_POWER_CTRL) &
+ ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
+
+ /*
* 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.
@@ -92,18 +106,9 @@ void omap_pm_idle(void)
if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
- } else {
-
- if (cpu_is_omap1510()) {
- func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
- } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
- func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
- } else if (cpu_is_omap5912()) {
- func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
- }
+ } else
+ omap_sram_idle();
- func_ptr();
- }
local_fiq_enable();
local_irq_enable();
}
@@ -115,58 +120,55 @@ void omap_pm_idle(void)
*/
static void omap_pm_wakeup_setup(void)
{
- /*
- * Enable ARM XOR clock and release peripheral from reset by
- * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
- * for UART configuration to use UART2 to wake up.
- */
-
- omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
- omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
- omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
+ u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
+ u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
/*
- * Turn off all interrupts except L1-2nd level cascade,
- * and the L2 wakeup interrupts: keypad and 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_omap1510() || cpu_is_omap16xx())
+ level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
+ else if (cpu_is_omap730())
+ level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
- omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
+ omap_writel(~level1_wake, OMAP_IH1_MIR);
- if (cpu_is_omap1510()) {
- omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
- }
+ if (cpu_is_omap1510())
+ omap_writel(~level2_wake, OMAP_IH2_MIR);
+ /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
if (cpu_is_omap16xx()) {
- omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
-
- omap_writel(~0x0, OMAP_IH2_1_MIR);
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+ 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 */
+ /* New IRQ agreement, recalculate in cascade order */
+ omap_writel(1, OMAP_IH2_CONTROL);
omap_writel(1, OMAP_IH1_CONTROL);
-
- /* external PULL to down, bit 22 = 0 */
- omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
}
void omap_pm_suspend(void)
{
- unsigned int mask32 = 0;
unsigned long arg0 = 0, arg1 = 0;
- int (*func_ptr)(unsigned short, unsigned short) = 0;
- unsigned short save_dsp_idlect2;
- printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
+ 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
+ * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
*/
local_irq_disable();
@@ -207,6 +209,8 @@ void omap_pm_suspend(void)
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap1510()))
+ ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@@ -214,42 +218,12 @@ void omap_pm_suspend(void)
ULPD_SAVE(ULPD_CLOCK_CTRL);
ULPD_SAVE(ULPD_STATUS_REQ);
- /*
- * Step 3: LOW_PWR signal enabling
- *
- * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
- */
- if (cpu_is_omap1510()) {
- /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
- omap_writew(omap_readw(ULPD_POWER_CTRL) |
- OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
- } else if (cpu_is_omap16xx()) {
- /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
- omap_writew(omap_readw(ULPD_POWER_CTRL) |
- OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
- }
-
- /* configure LOW_PWR pin */
- omap_cfg_reg(T20_1610_LOW_PWR);
+ /* (Step 3 removed - we now allow deep sleep by default) */
/*
* Step 4: OMAP DSP Shutdown
*/
- /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
- omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
- ARM_RSTCT1);
-
- /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
- omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
-
- /* Set EN_DSPCK = 0, stop DSP block clock */
- omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
-
- /* Stop any DSP domain clocks */
- omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
- save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
- __raw_writew(0, DSP_IDLECT2);
/*
* Step 5: Wakeup Event Setup
@@ -258,24 +232,9 @@ void omap_pm_suspend(void)
omap_pm_wakeup_setup();
/*
- * Step 6a: ARM and Traffic controller shutdown
- *
- * Step 6 starts here with clock and watchdog disable
+ * Step 6: ARM and Traffic controller shutdown
*/
- /* stop clocks */
- mask32 = omap_readl(ARM_IDLECT2);
- mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
- mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
- mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
- mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
- mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
- mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
- mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
- mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
- mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
- omap_writel(mask32, ARM_IDLECT2);
-
/* disable ARM watchdog */
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
@@ -295,47 +254,24 @@ void omap_pm_suspend(void)
arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
- if (cpu_is_omap1510()) {
- func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
- } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
- func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
- } else if (cpu_is_omap5912()) {
- func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
- }
-
/*
* Step 6c: ARM and Traffic controller shutdown
*
* Jump to assembly code. The processor will stay there
* until wake up.
*/
-
- func_ptr(arg0, arg1);
+ omap_sram_suspend(arg0, arg1);
/*
* If we are here, processor is woken up!
*/
- if (cpu_is_omap1510()) {
- /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
- omap_writew(omap_readw(ULPD_POWER_CTRL) &
- ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
- } else if (cpu_is_omap16xx()) {
- /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
- omap_writew(omap_readw(ULPD_POWER_CTRL) &
- ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
- }
-
-
- /* Restore DSP clocks */
- omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
- __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
- ARM_RESTORE(ARM_IDLECT2);
-
/*
* Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
*/
+ if (!(cpu_is_omap1510()))
+ ARM_RESTORE(ARM_IDLECT3);
ARM_RESTORE(ARM_CKCTL);
ARM_RESTORE(ARM_EWUPCT);
ARM_RESTORE(ARM_RSTCT1);
@@ -366,6 +302,8 @@ void omap_pm_suspend(void)
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
}
+ omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
/*
* Reenable interrupts
*/
@@ -373,6 +311,8 @@ void omap_pm_suspend(void)
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()) {
@@ -401,6 +341,8 @@ static int omap_pm_read_proc(
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap1510()))
+ ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@@ -436,6 +378,7 @@ static int omap_pm_read_proc(
"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"
@@ -449,6 +392,7 @@ static int omap_pm_read_proc(
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),
@@ -507,7 +451,7 @@ static void omap_pm_init_proc(void)
entry = create_proc_read_entry("driver/omap_pm",
S_IWUSR | S_IRUGO, NULL,
- omap_pm_read_proc, 0);
+ omap_pm_read_proc, NULL);
}
#endif /* DEBUG && CONFIG_PROC_FS */
@@ -580,7 +524,21 @@ static int omap_pm_finish(suspend_state_t state)
}
-struct pm_ops omap_pm_ops ={
+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,
@@ -590,42 +548,61 @@ struct pm_ops omap_pm_ops ={
static int __init omap_pm_init(void)
{
printk("Power Management for TI OMAP.\n");
- pm_idle = omap_pm_idle;
/*
* 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.
*/
-
-#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
- memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
- omap1510_idle_loop_suspend,
- omap1510_idle_loop_suspend_sz);
- memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
- omap1510_cpu_suspend_sz);
- } else
-#endif
- if (cpu_is_omap1610() || cpu_is_omap1710()) {
- memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
- omap1610_idle_loop_suspend,
- omap1610_idle_loop_suspend_sz);
- memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
- omap1610_cpu_suspend_sz);
- } else if (cpu_is_omap5912()) {
- memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
- omap1610_idle_loop_suspend,
- omap1610_idle_loop_suspend_sz);
- memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
- omap1610_cpu_suspend_sz);
+ 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;
+
+ setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+#if 0
+ /* --- BEGIN BOARD-DEPENDENT CODE --- */
+ /* Sleepx mask direction */
+ omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+ /* Unmask sleepx signal */
+ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+ /* --- END BOARD-DEPENDENT CODE --- */
+#endif
+
+ /* 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_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
+ /* configure LOW_PWR pin */
+ omap_cfg_reg(T20_1610_LOW_PWR);
+
return 0;
}
__initcall(omap_pm_init);
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S
index 279490ce772b..9f745836f6aa 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/plat-omap/sleep.S
@@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
- orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+ orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+ orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510: subs r5, r5, #1
bne l_1510
/*
@@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1510_idle_loop_suspend_sz)
.word . - omap1510_idle_loop_suspend
@@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
@ turn off clock domains
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
- orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
+ 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
@@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+ orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610: subs r5, r5, #1
bne l_1610
/*
@@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1610_idle_loop_suspend_sz)
.word . - omap1610_idle_loop_suspend
@@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
@ turn off clock domains
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
- orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+ orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+ orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510_2:
subs r5, r5, #1
bne l_1510_2
@@ -237,7 +237,7 @@ l_1510_2:
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return
- ldmfd sp!, {r0 - r12, pc}
+ ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1510_cpu_suspend_sz)
.word . - omap1510_cpu_suspend
@@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
@ save registers on stack
stmfd sp!, {r0 - r12, lr}
+ @ Drain write cache
+ mov r4, #0
+ mcr p15, 0, r0, c7, c10, 4
+ nop
+
@ load base address of Traffic Controller
- mov r4, #TCMIF_ASM_BASE & 0xff000000
- orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
- orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
+ 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
- ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
- orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
- orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
- str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+ 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
- ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
- str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+ 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
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
@@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
- mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
- orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
- strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-
- @ work around errata of OMAP1610/5912. Enable (!) peripheral
- @ clock to let the chip go into deep sleep
- ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- orr r5,r5, #EN_PERCK_BIT & 0xff
+ @ 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
- mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
- orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
+ mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
+ orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
-l_1610_2:
- subs r5, r5, #1
- bne l_1610_2
+ @ 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
@@ -301,13 +302,21 @@ l_1610_2:
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
- * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ * stack.
*/
+ @ re-enable Icache
+ mcr p15, 0, r9, c1, c0, 0
+
+ @ reset the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+ @ Restore EMIFF controls
+ str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+ str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
@ restore regs and return
- ldmfd sp!, {r0 - r12, pc}
+ ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
.word . - omap1610_cpu_suspend
diff --git a/arch/arm/plat-omap/sram-fn.S b/arch/arm/plat-omap/sram-fn.S
new file mode 100644
index 000000000000..4bea36964a00
--- /dev/null
+++ b/arch/arm/plat-omap/sram-fn.S
@@ -0,0 +1,58 @@
+/*
+ * linux/arch/arm/plat-omap/sram.S
+ *
+ * Functions that need to be run in internal SRAM
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+
+ .text
+
+/*
+ * Reprograms ULPD and CKCTL.
+ */
+ENTRY(sram_reprogram_clock)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+
+ mov r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000
+ orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000
+ orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00
+
+ mov r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000
+ orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
+ orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
+
+ tst r0, #1 << 4 @ want lock mode?
+ beq newck @ nope
+ bic r0, r0, #1 << 4 @ else clear lock bit
+ strh r0, [r2] @ set dpll into bypass mode
+ orr r0, r0, #1 << 4 @ set lock bit again
+
+newck:
+ strh r1, [r3] @ write new ckctl value
+ strh r0, [r2] @ write new dpll value
+
+ mov r4, #0x0700 @ let the clocks settle
+ orr r4, r4, #0x00ff
+delay: sub r4, r4, #1
+ cmp r4, #0
+ bne delay
+
+lock: ldrh r4, [r2], #0 @ read back dpll value
+ tst r0, #1 << 4 @ want lock mode?
+ beq out @ nope
+ tst r4, #1 << 0 @ dpll rate locked?
+ beq lock @ try again
+
+out:
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+ENTRY(sram_reprogram_clock_sz)
+ .word . - sram_reprogram_clock
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
new file mode 100644
index 000000000000..7719a4062e3a
--- /dev/null
+++ b/arch/arm/plat-omap/sram.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/plat-omap/sram.c
+ *
+ * OMAP SRAM detection and management
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by 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/init.h>
+
+#include <asm/mach/map.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+#include "sram.h"
+
+#define OMAP1_SRAM_BASE 0xd0000000
+#define OMAP1_SRAM_START 0x20000000
+#define SRAM_BOOTLOADER_SZ 0x80
+
+static unsigned long omap_sram_base;
+static unsigned long omap_sram_size;
+static unsigned long omap_sram_ceil;
+
+/*
+ * The amount of SRAM depends on the core type:
+ * 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
+ * Note that we cannot try to test for SRAM here because writes
+ * to secure SRAM will hang the system. Also the SRAM is not
+ * yet mapped at this point.
+ */
+void __init omap_detect_sram(void)
+{
+ omap_sram_base = OMAP1_SRAM_BASE;
+
+ if (cpu_is_omap730())
+ omap_sram_size = 0x32000;
+ else if (cpu_is_omap1510())
+ omap_sram_size = 0x80000;
+ else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
+ omap_sram_size = 0x4000;
+ else if (cpu_is_omap1611())
+ omap_sram_size = 0x3e800;
+ else {
+ printk(KERN_ERR "Could not detect SRAM size\n");
+ omap_sram_size = 0x4000;
+ }
+
+ printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
+ omap_sram_ceil = omap_sram_base + omap_sram_size;
+}
+
+static struct map_desc omap_sram_io_desc[] __initdata = {
+ { OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
+};
+
+/*
+ * In order to use last 2kB of SRAM on 1611b, we must round the size
+ * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
+ * clock init needs SRAM early.
+ */
+void __init omap_map_sram(void)
+{
+ if (omap_sram_size == 0)
+ return;
+
+ omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
+ omap_sram_io_desc[0].length *= PAGE_SIZE;
+ iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
+
+ /*
+ * Looks like we need to preserve some bootloader code at the
+ * beginning of SRAM for jumping to flash for reboot to work...
+ */
+ memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
+ omap_sram_size - SRAM_BOOTLOADER_SZ);
+}
+
+static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
+
+void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
+{
+ if (_omap_sram_reprogram_clock == NULL)
+ panic("Cannot use SRAM");
+
+ return _omap_sram_reprogram_clock(dpllctl, ckctl);
+}
+
+void * omap_sram_push(void * start, unsigned long size)
+{
+ if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+ printk(KERN_ERR "Not enough space in SRAM\n");
+ return NULL;
+ }
+ omap_sram_ceil -= size;
+ omap_sram_ceil &= ~0x3;
+ memcpy((void *)omap_sram_ceil, start, size);
+
+ return (void *)omap_sram_ceil;
+}
+
+void __init omap_sram_init(void)
+{
+ omap_detect_sram();
+ omap_map_sram();
+ _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
+ sram_reprogram_clock_sz);
+}
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
new file mode 100644
index 000000000000..71984efa6ae8
--- /dev/null
+++ b/arch/arm/plat-omap/sram.h
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/arm/plat-omap/sram.h
+ *
+ * Interface for functions that need to be run in internal SRAM
+ *
+ * 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 __ARCH_ARM_OMAP_SRAM_H
+#define __ARCH_ARM_OMAP_SRAM_H
+
+extern void * omap_sram_push(void * start, unsigned long size);
+extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
+
+/* Do not use these */
+extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long sram_reprogram_clock_sz;
+
+#endif
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 25bc4a8dd763..98f1c76f8660 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -41,6 +41,7 @@
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
+ * Call omap_usb_init() once, from INIT_MACHINE().
*
* Some board-*.c files will need to set up additional mux options,
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index e73c8deca592..6f17187ab32a 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -17,7 +17,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
#include <asm/vfpmacros.h>
.globl do_vfp
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 1f0373267306..1f00b3d03a07 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -55,6 +55,10 @@ config GENERIC_BUST_SPINLOCK
config GENERIC_ISA_DMA
bool
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
diff --git a/arch/arm26/Makefile b/arch/arm26/Makefile
index ada8985530a5..844a9e46886e 100644
--- a/arch/arm26/Makefile
+++ b/arch/arm26/Makefile
@@ -17,10 +17,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS +=-fno-omit-frame-pointer -mno-sched-prolog
endif
-ifeq ($(CONFIG_DEBUG_INFO),y)
-CFLAGS +=-g
-endif
-
CFLAGS_BOOT :=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
CFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float -Uarm
AFLAGS +=-mapcs-26 -mcpu=arm3 -msoft-float
@@ -53,10 +49,6 @@ all: zImage
boot := arch/arm26/boot
-prepare: include/asm-$(ARCH)/asm_offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
-
.PHONY: maketools FORCE
maketools: FORCE
@@ -98,12 +90,6 @@ zi:; $(Q)$(MAKE) $(build)=$(boot) zinstall
fi; \
)
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
define archhelp
echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
diff --git a/arch/arm26/kernel/entry.S b/arch/arm26/kernel/entry.S
index a231dd88d0e1..6d910ea43d34 100644
--- a/arch/arm26/kernel/entry.S
+++ b/arch/arm26/kernel/entry.S
@@ -10,7 +10,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/errno.h>
#include <asm/hardware.h>
#include <asm/sysirq.h>
diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
index 356d9809cc0b..ce2055bdc9ee 100644
--- a/arch/arm26/kernel/signal.c
+++ b/arch/arm26/kernel/signal.c
@@ -454,14 +454,13 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&tsk->sighand->siglock);
- sigorsets(&tsk->blocked, &tsk->blocked,
- &ka->sa.sa_mask);
+ spin_lock_irq(&tsk->sighand->siglock);
+ sigorsets(&tsk->blocked, &tsk->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&tsk->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&tsk->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&tsk->sighand->siglock);
return;
}
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
index 549a6b2e177e..e66aedd02fad 100644
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -114,7 +114,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
- if (time_status & STA_UNSYNC || set_rtc == NULL)
+ if (!ntp_synced() || set_rtc == NULL)
return;
//FIXME - timespec.tv_sec is a time_t not unsigned long
@@ -189,10 +189,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/arm26/lib/copy_page.S b/arch/arm26/lib/copy_page.S
index 2d79ee12ea1f..c7511a2739d3 100644
--- a/arch/arm26/lib/copy_page.S
+++ b/arch/arm26/lib/copy_page.S
@@ -11,7 +11,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
.align 5
diff --git a/arch/arm26/lib/csumpartialcopyuser.S b/arch/arm26/lib/csumpartialcopyuser.S
index 5b821188e479..261dd154c1a4 100644
--- a/arch/arm26/lib/csumpartialcopyuser.S
+++ b/arch/arm26/lib/csumpartialcopyuser.S
@@ -11,7 +11,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/errno.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/arm26/lib/getuser.S b/arch/arm26/lib/getuser.S
index e6d59b334851..2b1de7fbfe1f 100644
--- a/arch/arm26/lib/getuser.S
+++ b/arch/arm26/lib/getuser.S
@@ -26,7 +26,7 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000.
* Note also that it is intended that __get_user_bad is not global.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
diff --git a/arch/arm26/lib/putuser.S b/arch/arm26/lib/putuser.S
index 87588cbe46ae..46c7f15f9f2d 100644
--- a/arch/arm26/lib/putuser.S
+++ b/arch/arm26/lib/putuser.S
@@ -26,7 +26,7 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000
* Note also that it is intended that __put_user_bad is not global.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
diff --git a/arch/arm26/mm/proc-funcs.S b/arch/arm26/mm/proc-funcs.S
index c3d4cd3f457e..f9fca524c57a 100644
--- a/arch/arm26/mm/proc-funcs.S
+++ b/arch/arm26/mm/proc-funcs.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm26/nwfpe/entry.S b/arch/arm26/nwfpe/entry.S
index 7d6dfaad80c2..e6312000d9f8 100644
--- a/arch/arm26/nwfpe/entry.S
+++ b/arch/arm26/nwfpe/entry.S
@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
/* This is the kernel's entry point into the floating point emulator.
It is called from the kernel with code similar to this:
diff --git a/arch/cris/Kconfig.debug b/arch/cris/Kconfig.debug
index cd72324935c4..0a1d62a23614 100644
--- a/arch/cris/Kconfig.debug
+++ b/arch/cris/Kconfig.debug
@@ -5,10 +5,13 @@ config PROFILING
bool "Kernel profiling support"
config SYSTEM_PROFILER
- bool "System profiling support"
+ bool "System profiling support"
+
+source "lib/Kconfig.debug"
config ETRAX_KGDB
bool "Use kernel GDB debugger"
+ depends on DEBUG_KERNEL
---help---
The CRIS version of gdb can be used to remotely debug a running
Linux kernel via the serial debug port. Provided you have gdb-cris
@@ -22,25 +25,11 @@ config ETRAX_KGDB
this option is turned on!
-config DEBUG_INFO
- bool "Compile the kernel with debug info"
- help
- If you say Y here the resulting kernel image will include
- debugging info resulting in a larger kernel image.
- Say Y here only if you plan to use gdb to debug the kernel.
- If you don't debug the kernel, you can say N.
-
-config FRAME_POINTER
- bool "Compile the kernel with frame pointers"
- help
- If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
-
config DEBUG_NMI_OOPS
- bool "NMI causes oops printout"
- help
- If the system locks up without any debug information you can say Y
- here to make it possible to dump an OOPS with an external NMI.
+ bool "NMI causes oops printout"
+ depends on DEBUG_KERNEL
+ help
+ If the system locks up without any debug information you can say Y
+ here to make it possible to dump an OOPS with an external NMI.
+
endmenu
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index 90ca8730b120..ea65d585cf5e 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -107,8 +107,7 @@ archclean:
rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img
rm -rf $(LD_SCRIPT).tmp
-prepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch \
- include/asm-$(ARCH)/$(SARCH)/offset.h
+archprepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch
# Create some links to make all tools happy
$(SRC_ARCH)/.links:
@@ -120,6 +119,7 @@ $(SRC_ARCH)/.links:
@ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
@ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
@ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
+ @ln -sfn $(SRC_ARCH)/$(SARCH)/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
@touch $@
# Create link to sub arch includes
@@ -128,9 +128,3 @@ $(srctree)/include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
@rm -f include/asm-$(ARCH)/arch
@ln -sf $(srctree)/include/asm-$(ARCH)/$(SARCH) $(srctree)/include/asm-$(ARCH)/arch
@touch $@
-
-arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/$(SARCH)/offset.h: arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index c0163bf94a50..c808005e8457 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -270,7 +270,7 @@
#include <asm/arch/sv_addr_ag.h>
#include <asm/errno.h>
#include <asm/thread_info.h>
-#include <asm/arch/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 85e0032e664f..693771961f85 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -517,13 +517,12 @@ handle_signal(int canrestart, unsigned long sig,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 6b7b4e0802e3..dc3dfe9b4a1a 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -240,7 +240,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* The division here is not time critical since it will run once in
* 11 minutes
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - (tick_nsec / 1000) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + (tick_nsec / 1000) / 2) {
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index a8ed55e5b403..3bd8503fec68 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -23,7 +23,7 @@
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/thread_info.h>
-#include <asm/arch/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/arch/hwregs/asm/reg_map_asm.h>
#include <asm/arch/hwregs/asm/intr_vect_defs_asm.h>
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index fb4c79d5b76b..0a3614dab887 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -568,13 +568,12 @@ handle_signal(int canrestart, unsigned long sig,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index fa2d4323da25..a2d99b4aedcd 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -114,10 +114,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c
new file mode 100644
index 000000000000..9e263112a6e2
--- /dev/null
+++ b/arch/frv/kernel/asm-offsets.c
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 62cfbd9b4f98..1a76d5247190 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -71,7 +71,6 @@ EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(get_wchan);
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 36a2dffc8ebd..d4ccc0728dfe 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -506,13 +506,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
else
setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
} /* end handle_signal() */
/*****************************************************************************/
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 075db6644694..8d6558b00e44 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -85,7 +85,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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
@@ -216,10 +216,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
index c9b80cffd71d..40b3f56f3666 100644
--- a/arch/h8300/Makefile
+++ b/arch/h8300/Makefile
@@ -61,12 +61,6 @@ archmrproper:
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-prepare: include/asm-$(ARCH)/asm-offsets.h
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
- include/asm include/linux/version.h
- $(call filechk,gen-asm-offsets)
-
vmlinux.srec vmlinux.bin: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
@@ -74,5 +68,3 @@ define archhelp
echo 'vmlinux.bin - Create raw binary'
echo 'vmlinux.srec - Create srec binary'
endef
-
-CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 5aab87eae1f9..f13d5e82d4b9 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -488,13 +488,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 8a600218334d..af8c5d2057dd 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -116,10 +116,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 619d843ba231..b22f003eaa6d 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -14,6 +14,10 @@ config X86
486, 586, Pentiums, and various instruction-set-compatible chips by
AMD, Cyrix, and others.
+config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
config MMU
bool
default y
@@ -33,6 +37,10 @@ config GENERIC_IOMAP
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
menu "Processor type and features"
@@ -754,6 +762,7 @@ config NUMA
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT)
+ select SPARSEMEM_STATIC
# Need comments to help the hapless user trying to turn on NUMA support
comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
@@ -1203,7 +1212,6 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool
depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
- select ACPI_BOOT
default y
source "drivers/pci/pcie/Kconfig"
@@ -1313,6 +1321,11 @@ config GENERIC_IRQ_PROBE
bool
default y
+config GENERIC_PENDING_IRQ
+ bool
+ depends on GENERIC_HARDIRQS && SMP
+ default y
+
config X86_SMP
bool
depends on SMP && !X86_VOYAGER
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index bf7c9ba709f3..09951990a622 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -156,15 +156,6 @@ install: vmlinux
install kernel_install:
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
-prepare: include/asm-$(ARCH)/asm_offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
archclean:
$(Q)$(MAKE) $(clean)=arch/i386/boot
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 8cb420f40c58..ca668d9df164 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -82,7 +82,7 @@ start:
# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
.ascii "HdrS" # header signature
- .word 0x0203 # header version number (>= 0x0105)
+ .word 0x0204 # header version number (>= 0x0105)
# or else old loadlin-1.5 will fail)
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
start_sys_seg: .word SYSSEG
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
index 6835f6d47c31..05798419a6a9 100644
--- a/arch/i386/boot/tools/build.c
+++ b/arch/i386/boot/tools/build.c
@@ -177,7 +177,9 @@ int main(int argc, char ** argv)
die("Output: seek failed");
buf[0] = (sys_size & 0xff);
buf[1] = ((sys_size >> 8) & 0xff);
- if (write(1, buf, 2) != 2)
+ buf[2] = ((sys_size >> 16) & 0xff);
+ buf[3] = ((sys_size >> 24) & 0xff);
+ if (write(1, buf, 4) != 4)
die("Write of image length failed");
return 0; /* Everything is OK */
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 0587477c99f2..92f669470142 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
@@ -1944,7 +1949,7 @@ store_edid:
movw $0x4f15, %ax # do VBE/DDC
movw $0x01, %bx
movw $0x00, %cx
- movw $0x01, %dx
+ movw $0x00, %dx
movw $0x140, %di
int $0x10
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index ca07b95c06b8..6a431b926019 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -131,8 +131,6 @@ CONFIG_SOFTWARE_SUSPEND=y
# ACPI (Advanced Configuration and Power Interface) Support
#
CONFIG_ACPI=y
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_SLEEP_PROC_FS=y
CONFIG_ACPI_AC=y
@@ -144,10 +142,8 @@ CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_ASUS is not set
# CONFIG_ACPI_TOSHIBA is not set
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_X86_PM_TIMER is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 4cc83b322b36..f10de0f2c5e6 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -7,11 +7,11 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.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 \
- doublefault.o quirks.o
+ doublefault.o quirks.o i8237.o
obj-y += cpu/
obj-y += timers/
-obj-$(CONFIG_ACPI_BOOT) += acpi/
+obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_X86_MSR) += msr.o
diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile
index 5e291a20c03d..267ca48e1b6c 100644
--- a/arch/i386/kernel/acpi/Makefile
+++ b/arch/i386/kernel/acpi/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_ACPI_BOOT) := boot.o
+obj-y := boot.o
obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index b7808a89d945..a63351c085c6 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -40,19 +40,25 @@
#ifdef CONFIG_X86_64
-static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
+static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+}
extern void __init clustered_apic_check(void);
-static inline int ioapic_setup_disabled(void) { return 0; }
+static inline int ioapic_setup_disabled(void)
+{
+ return 0;
+}
+
#include <asm/proto.h>
-#else /* X86 */
+#else /* X86 */
#ifdef CONFIG_X86_LOCAL_APIC
#include <mach_apic.h>
#include <mach_mpparse.h>
-#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_X86_LOCAL_APIC */
-#endif /* X86 */
+#endif /* X86 */
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
@@ -60,13 +66,8 @@ static inline int ioapic_setup_disabled(void) { return 0; }
#define PREFIX "ACPI: "
-#ifdef CONFIG_ACPI_PCI
int acpi_noirq __initdata; /* skip ACPI IRQ initialization */
-int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
-#else
-int acpi_noirq __initdata = 1;
-int acpi_pci_disabled __initdata = 1;
-#endif
+int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic;
@@ -88,7 +89,7 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#define MAX_MADT_ENTRIES 256
u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
- { [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+ {[0 ... MAX_MADT_ENTRIES - 1] = 0xff };
EXPORT_SYMBOL(x86_acpiid_to_apicid);
/* --------------------------------------------------------------------------
@@ -99,7 +100,7 @@ EXPORT_SYMBOL(x86_acpiid_to_apicid);
* The default interrupt routing model is PIC (8259). This gets
* overriden if IOAPICs are enumerated (below).
*/
-enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
#ifdef CONFIG_X86_64
@@ -107,7 +108,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
{
if (!phys_addr || !size)
- return NULL;
+ return NULL;
if (phys_addr < (end_pfn_map << PAGE_SHIFT))
return __va(phys_addr);
@@ -134,8 +135,8 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
unsigned long base, offset, mapped_size;
int idx;
- if (phys + size < 8*1024*1024)
- return __va(phys);
+ if (phys + size < 8 * 1024 * 1024)
+ return __va(phys);
offset = phys & (PAGE_SIZE - 1);
mapped_size = PAGE_SIZE - offset;
@@ -154,7 +155,7 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
mapped_size += PAGE_SIZE;
}
- return ((unsigned char *) base + offset);
+ return ((unsigned char *)base + offset);
}
#endif
@@ -172,7 +173,7 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
if (!phys_addr || !size)
return -EINVAL;
- mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
+ mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size);
if (!mcfg) {
printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
return -ENODEV;
@@ -209,20 +210,17 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
return 0;
}
-#endif /* CONFIG_PCI_MMCONFIG */
+#endif /* CONFIG_PCI_MMCONFIG */
#ifdef CONFIG_X86_LOCAL_APIC
-static int __init
-acpi_parse_madt (
- unsigned long phys_addr,
- unsigned long size)
+static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
{
- struct acpi_table_madt *madt = NULL;
+ struct acpi_table_madt *madt = NULL;
if (!phys_addr || !size)
return -EINVAL;
- madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
+ madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
if (!madt) {
printk(KERN_WARNING PREFIX "Unable to map MADT\n");
return -ENODEV;
@@ -232,22 +230,20 @@ acpi_parse_madt (
acpi_lapic_addr = (u64) madt->lapic_address;
printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
- madt->lapic_address);
+ madt->lapic_address);
}
acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
-
+
return 0;
}
-
static int __init
-acpi_parse_lapic (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end)
{
- struct acpi_table_lapic *processor = NULL;
+ struct acpi_table_lapic *processor = NULL;
- processor = (struct acpi_table_lapic*) header;
+ processor = (struct acpi_table_lapic *)header;
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
@@ -260,20 +256,19 @@ acpi_parse_lapic (
x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
- mp_register_lapic (
- processor->id, /* APIC ID */
- processor->flags.enabled); /* Enabled? */
+ mp_register_lapic(processor->id, /* APIC ID */
+ processor->flags.enabled); /* Enabled? */
return 0;
}
static int __init
-acpi_parse_lapic_addr_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
- lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
+ lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr *)header;
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
return -EINVAL;
@@ -284,12 +279,11 @@ acpi_parse_lapic_addr_ovr (
}
static int __init
-acpi_parse_lapic_nmi (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_lapic_nmi *lapic_nmi = NULL;
- lapic_nmi = (struct acpi_table_lapic_nmi*) header;
+ lapic_nmi = (struct acpi_table_lapic_nmi *)header;
if (BAD_MADT_ENTRY(lapic_nmi, end))
return -EINVAL;
@@ -302,37 +296,32 @@ acpi_parse_lapic_nmi (
return 0;
}
+#endif /*CONFIG_X86_LOCAL_APIC */
-#endif /*CONFIG_X86_LOCAL_APIC*/
-
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+#ifdef CONFIG_X86_IO_APIC
static int __init
-acpi_parse_ioapic (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_ioapic *ioapic = NULL;
- ioapic = (struct acpi_table_ioapic*) header;
+ ioapic = (struct acpi_table_ioapic *)header;
if (BAD_MADT_ENTRY(ioapic, end))
return -EINVAL;
-
+
acpi_table_print_madt_entry(header);
- mp_register_ioapic (
- ioapic->id,
- ioapic->address,
- ioapic->global_irq_base);
-
+ mp_register_ioapic(ioapic->id,
+ ioapic->address, ioapic->global_irq_base);
+
return 0;
}
/*
* Parse Interrupt Source Override for the ACPI SCI
*/
-static void
-acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
{
if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
@@ -348,7 +337,7 @@ acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
polarity = acpi_sci_flags.polarity;
/*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
+ * mp_config_acpi_legacy_irqs() already setup IRQs < 16
* If GSI is < 16, this will update its flags,
* else it will create a new mp_irqs[] entry.
*/
@@ -363,12 +352,12 @@ acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
}
static int __init
-acpi_parse_int_src_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_int_src_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_int_src_ovr *intsrc = NULL;
- intsrc = (struct acpi_table_int_src_ovr*) header;
+ intsrc = (struct acpi_table_int_src_ovr *)header;
if (BAD_MADT_ENTRY(intsrc, end))
return -EINVAL;
@@ -377,33 +366,30 @@ acpi_parse_int_src_ovr (
if (intsrc->bus_irq == acpi_fadt.sci_int) {
acpi_sci_ioapic_setup(intsrc->global_irq,
- intsrc->flags.polarity, intsrc->flags.trigger);
+ intsrc->flags.polarity,
+ intsrc->flags.trigger);
return 0;
}
if (acpi_skip_timer_override &&
- intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
- printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
- return 0;
+ intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
+ printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+ return 0;
}
- mp_override_legacy_irq (
- intsrc->bus_irq,
- intsrc->flags.polarity,
- intsrc->flags.trigger,
- intsrc->global_irq);
+ mp_override_legacy_irq(intsrc->bus_irq,
+ intsrc->flags.polarity,
+ intsrc->flags.trigger, intsrc->global_irq);
return 0;
}
-
static int __init
-acpi_parse_nmi_src (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_nmi_src *nmi_src = NULL;
- nmi_src = (struct acpi_table_nmi_src*) header;
+ nmi_src = (struct acpi_table_nmi_src *)header;
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
@@ -415,9 +401,7 @@ acpi_parse_nmi_src (
return 0;
}
-#endif /* CONFIG_X86_IO_APIC */
-
-#ifdef CONFIG_ACPI_BUS
+#endif /* CONFIG_X86_IO_APIC */
/*
* acpi_pic_sci_set_trigger()
@@ -433,8 +417,7 @@ acpi_parse_nmi_src (
* ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
*/
-void __init
-acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
+void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
{
unsigned int mask = 1 << irq;
unsigned int old, new;
@@ -454,10 +437,10 @@ acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
* routing tables..
*/
switch (trigger) {
- case 1: /* Edge - clear */
+ case 1: /* Edge - clear */
new &= ~mask;
break;
- case 3: /* Level - set */
+ case 3: /* Level - set */
new |= mask;
break;
}
@@ -470,21 +453,22 @@ acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}
-
-#endif /* CONFIG_ACPI_BUS */
-
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
#ifdef CONFIG_X86_IO_APIC
if (use_pci_vector() && !platform_legacy_irq(gsi))
- *irq = IO_APIC_VECTOR(gsi);
+ *irq = IO_APIC_VECTOR(gsi);
else
#endif
*irq = gsi;
return 0;
}
-unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+/*
+ * success: return IRQ number (>=0)
+ * failure: return < 0
+ */
+int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
{
unsigned int irq;
unsigned int plat_gsi = gsi;
@@ -497,7 +481,7 @@ unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
extern void eisa_set_level_irq(unsigned int irq);
if (edge_level == ACPI_LEVEL_SENSITIVE)
- eisa_set_level_irq(gsi);
+ eisa_set_level_irq(gsi);
}
#endif
@@ -509,60 +493,58 @@ unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
acpi_gsi_to_irq(plat_gsi, &irq);
return irq;
}
+
EXPORT_SYMBOL(acpi_register_gsi);
/*
* ACPI based hotplug support for CPU
*/
#ifdef CONFIG_ACPI_HOTPLUG_CPU
-int
-acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int acpi_map_lsapic(acpi_handle handle, int *pcpu)
{
/* TBD */
return -EINVAL;
}
-EXPORT_SYMBOL(acpi_map_lsapic);
+EXPORT_SYMBOL(acpi_map_lsapic);
-int
-acpi_unmap_lsapic(int cpu)
+int acpi_unmap_lsapic(int cpu)
{
/* TBD */
return -EINVAL;
}
+
EXPORT_SYMBOL(acpi_unmap_lsapic);
-#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-int
-acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
+int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
{
/* TBD */
return -EINVAL;
}
+
EXPORT_SYMBOL(acpi_register_ioapic);
-int
-acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
+int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
{
/* TBD */
return -EINVAL;
}
+
EXPORT_SYMBOL(acpi_unregister_ioapic);
static unsigned long __init
-acpi_scan_rsdp (
- unsigned long start,
- unsigned long length)
+acpi_scan_rsdp(unsigned long start, unsigned long length)
{
- unsigned long offset = 0;
- unsigned long sig_len = sizeof("RSD PTR ") - 1;
+ unsigned long offset = 0;
+ unsigned long sig_len = sizeof("RSD PTR ") - 1;
/*
* Scan all 16-byte boundaries of the physical memory region for the
* RSDP signature.
*/
for (offset = 0; offset < length; offset += 16) {
- if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
+ if (strncmp((char *)(start + offset), "RSD PTR ", sig_len))
continue;
return (start + offset);
}
@@ -575,20 +557,19 @@ static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
struct acpi_table_sbf *sb;
if (!phys_addr || !size)
- return -EINVAL;
+ return -EINVAL;
- sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size);
+ sb = (struct acpi_table_sbf *)__acpi_map_table(phys_addr, size);
if (!sb) {
printk(KERN_WARNING PREFIX "Unable to map SBF\n");
return -ENODEV;
}
- sbf_port = sb->sbf_cmos; /* Save CMOS port */
+ sbf_port = sb->sbf_cmos; /* Save CMOS port */
return 0;
}
-
#ifdef CONFIG_HPET_TIMER
static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
@@ -598,7 +579,7 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
if (!phys || !size)
return -EINVAL;
- hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size);
+ hpet_tbl = (struct acpi_table_hpet *)__acpi_map_table(phys, size);
if (!hpet_tbl) {
printk(KERN_WARNING PREFIX "Unable to map HPET\n");
return -ENODEV;
@@ -609,22 +590,21 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
"memory.\n");
return -1;
}
-
#ifdef CONFIG_X86_64
- vxtime.hpet_address = hpet_tbl->addr.addrl |
- ((long) hpet_tbl->addr.addrh << 32);
+ vxtime.hpet_address = hpet_tbl->addr.addrl |
+ ((long)hpet_tbl->addr.addrh << 32);
- printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
- hpet_tbl->id, vxtime.hpet_address);
-#else /* X86 */
+ printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
+ hpet_tbl->id, vxtime.hpet_address);
+#else /* X86 */
{
extern unsigned long hpet_address;
hpet_address = hpet_tbl->addr.addrl;
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
- hpet_tbl->id, hpet_address);
+ hpet_tbl->id, hpet_address);
}
-#endif /* X86 */
+#endif /* X86 */
return 0;
}
@@ -640,28 +620,25 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
{
struct fadt_descriptor_rev2 *fadt = NULL;
- fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
- if(!fadt) {
+ fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size);
+ if (!fadt) {
printk(KERN_WARNING PREFIX "Unable to map FADT\n");
return 0;
}
-
-#ifdef CONFIG_ACPI_INTERPRETER
/* initialize sci_int early for INT_SRC_OVR MADT parsing */
acpi_fadt.sci_int = fadt->sci_int;
-#endif
-#ifdef CONFIG_ACPI_BUS
/* initialize rev and apic_phys_dest_mode for x86_64 genapic */
acpi_fadt.revision = fadt->revision;
- acpi_fadt.force_apic_physical_destination_mode = fadt->force_apic_physical_destination_mode;
-#endif
+ acpi_fadt.force_apic_physical_destination_mode =
+ fadt->force_apic_physical_destination_mode;
#ifdef CONFIG_X86_PM_TIMER
/* detect the location of the ACPI PM Timer */
if (fadt->revision >= FADT2_REVISION_ID) {
/* FADT rev. 2 */
- if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
+ if (fadt->xpm_tmr_blk.address_space_id !=
+ ACPI_ADR_SPACE_SYSTEM_IO)
return 0;
pmtmr_ioport = fadt->xpm_tmr_blk.address;
@@ -670,16 +647,15 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
pmtmr_ioport = fadt->V1_pm_tmr_blk;
}
if (pmtmr_ioport)
- printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
+ printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
+ pmtmr_ioport);
#endif
return 0;
}
-
-unsigned long __init
-acpi_find_rsdp (void)
+unsigned long __init acpi_find_rsdp(void)
{
- unsigned long rsdp_phys = 0;
+ unsigned long rsdp_phys = 0;
if (efi_enabled) {
if (efi.acpi20)
@@ -691,9 +667,9 @@ acpi_find_rsdp (void)
* Scan memory looking for the RSDP signature. First search EBDA (low
* memory) paragraphs and then search upper memory (E0000-FFFFF).
*/
- rsdp_phys = acpi_scan_rsdp (0, 0x400);
+ rsdp_phys = acpi_scan_rsdp(0, 0x400);
if (!rsdp_phys)
- rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
+ rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
return rsdp_phys;
}
@@ -703,8 +679,7 @@ acpi_find_rsdp (void)
* Parse LAPIC entries in MADT
* returns 0 on success, < 0 on error
*/
-static int __init
-acpi_parse_madt_lapic_entries(void)
+static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
@@ -713,28 +688,31 @@ acpi_parse_madt_lapic_entries(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
+ printk(KERN_ERR PREFIX
+ "Error parsing LAPIC address override entry\n");
return count;
}
mp_register_lapic_address(acpi_lapic_addr);
count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
- MAX_APICS);
- if (!count) {
+ MAX_APICS);
+ if (!count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
return -ENODEV;
- }
- else if (count < 0) {
+ } else if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
- count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -742,15 +720,14 @@ acpi_parse_madt_lapic_entries(void)
}
return 0;
}
-#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_X86_LOCAL_APIC */
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+#ifdef CONFIG_X86_IO_APIC
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
*/
-static int __init
-acpi_parse_madt_ioapic_entries(void)
+static int __init acpi_parse_madt_ioapic_entries(void)
{
int count;
@@ -762,30 +739,34 @@ acpi_parse_madt_ioapic_entries(void)
*/
if (acpi_disabled || acpi_noirq) {
return -ENODEV;
- }
+ }
/*
- * if "noapic" boot option, don't look for IO-APICs
+ * if "noapic" boot option, don't look for IO-APICs
*/
if (skip_ioapic_setup) {
printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
- "due to 'noapic' option.\n");
+ "due to 'noapic' option.\n");
return -ENODEV;
}
- count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
- }
- else if (count < 0) {
+ } else if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
return count;
}
- count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr,
+ NR_IRQ_VECTORS);
if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
+ printk(KERN_ERR PREFIX
+ "Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -800,7 +781,9 @@ acpi_parse_madt_ioapic_entries(void)
/* Fill in identity legacy mapings where no override */
mp_config_acpi_legacy_irqs();
- count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src,
+ NR_IRQ_VECTORS);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -814,11 +797,9 @@ static inline int acpi_parse_madt_ioapic_entries(void)
{
return -1;
}
-#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */
-
+#endif /* !CONFIG_X86_IO_APIC */
-static void __init
-acpi_process_madt(void)
+static void __init acpi_process_madt(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
int count, error;
@@ -833,6 +814,9 @@ acpi_process_madt(void)
if (!error) {
acpi_lapic = 1;
+#ifdef CONFIG_X86_GENERICARCH
+ generic_bigsmp_probe();
+#endif
/*
* Parse MADT IO-APIC entries
*/
@@ -850,7 +834,8 @@ acpi_process_madt(void)
/*
* Dell Precision Workstation 410, 610 come here.
*/
- printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
+ printk(KERN_ERR PREFIX
+ "Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
}
@@ -862,7 +847,6 @@ extern int acpi_force;
#ifdef __i386__
-#ifdef CONFIG_ACPI_PCI
static int __init disable_acpi_irq(struct dmi_system_id *d)
{
if (!acpi_force) {
@@ -882,12 +866,11 @@ static int __init disable_acpi_pci(struct dmi_system_id *d)
}
return 0;
}
-#endif
static int __init dmi_disable_acpi(struct dmi_system_id *d)
{
if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: acpi off\n",d->ident);
+ printk(KERN_NOTICE "%s detected: acpi off\n", d->ident);
disable_acpi();
} else {
printk(KERN_NOTICE
@@ -902,7 +885,8 @@ static int __init dmi_disable_acpi(struct dmi_system_id *d)
static int __init force_acpi_ht(struct dmi_system_id *d)
{
if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident);
+ printk(KERN_NOTICE "%s detected: force use of acpi=ht\n",
+ d->ident);
disable_acpi();
acpi_ht = 1;
} else {
@@ -921,155 +905,155 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
* Boxes that need ACPI disabled
*/
{
- .callback = dmi_disable_acpi,
- .ident = "IBM Thinkpad",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_BOARD_NAME, "2629H1G"),
- },
- },
+ .callback = dmi_disable_acpi,
+ .ident = "IBM Thinkpad",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "2629H1G"),
+ },
+ },
/*
* Boxes that need acpi=ht
*/
{
- .callback = force_acpi_ht,
- .ident = "FSC Primergy T850",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "FSC Primergy T850",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "DELL GX240",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "DELL GX240",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "HP VISUALIZE NT Workstation",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "HP VISUALIZE NT Workstation",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "Compaq Workstation W8000",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "Compaq Workstation W8000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "ASUS P4B266",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "ASUS P4B266",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "ASUS P2B-DS",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "ASUS P2B-DS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "ASUS CUR-DLS",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "ASUS CUR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "ABIT i440BX-W83977",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
- DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "ABIT i440BX-W83977",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
+ DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "IBM Bladecenter",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "IBM Bladecenter",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "IBM eServer xSeries 360",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "IBM eServer xSeries 360",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "IBM eserver xSeries 330",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
- },
- },
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 330",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
+ },
+ },
{
- .callback = force_acpi_ht,
- .ident = "IBM eserver xSeries 440",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
- DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
- },
- },
-
-#ifdef CONFIG_ACPI_PCI
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 440",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
+ },
+ },
+
/*
* Boxes that need ACPI PCI IRQ routing disabled
*/
{
- .callback = disable_acpi_irq,
- .ident = "ASUS A7V",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
- DMI_MATCH(DMI_BOARD_NAME, "<A7V>"),
- /* newer BIOS, Revision 1011, does work */
- DMI_MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
- },
- },
+ .callback = disable_acpi_irq,
+ .ident = "ASUS A7V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+ DMI_MATCH(DMI_BOARD_NAME, "<A7V>"),
+ /* newer BIOS, Revision 1011, does work */
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "ASUS A7V ACPI BIOS Revision 1007"),
+ },
+ },
/*
* Boxes that need ACPI PCI IRQ routing and PCI scan disabled
*/
- { /* _BBN 0 bug */
- .callback = disable_acpi_pci,
- .ident = "ASUS PR-DLS",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"),
- DMI_MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
- DMI_MATCH(DMI_BIOS_DATE, "03/21/2003")
- },
- },
+ { /* _BBN 0 bug */
+ .callback = disable_acpi_pci,
+ .ident = "ASUS PR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "ASUS PR-DLS ACPI BIOS Revision 1010"),
+ DMI_MATCH(DMI_BIOS_DATE, "03/21/2003")
+ },
+ },
{
- .callback = disable_acpi_pci,
- .ident = "Acer TravelMate 36x Laptop",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
- },
- },
-#endif
- { }
+ .callback = disable_acpi_pci,
+ .ident = "Acer TravelMate 36x Laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+ },
+ },
+ {}
};
-#endif /* __i386__ */
+#endif /* __i386__ */
/*
* acpi_boot_table_init() and acpi_boot_init()
@@ -1094,8 +1078,7 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
* !0: failure
*/
-int __init
-acpi_boot_table_init(void)
+int __init acpi_boot_table_init(void)
{
int error;
@@ -1108,7 +1091,7 @@ acpi_boot_table_init(void)
* One exception: acpi=ht continues far enough to enumerate LAPICs
*/
if (acpi_disabled && !acpi_ht)
- return 1;
+ return 1;
/*
* Initialize the ACPI boot-time table parser.
@@ -1118,7 +1101,6 @@ acpi_boot_table_init(void)
disable_acpi();
return error;
}
-
#ifdef __i386__
check_acpi_pci();
#endif
@@ -1142,7 +1124,6 @@ acpi_boot_table_init(void)
return 0;
}
-
int __init acpi_boot_init(void)
{
/*
@@ -1150,7 +1131,7 @@ int __init acpi_boot_init(void)
* One exception: acpi=ht continues far enough to enumerate LAPICs
*/
if (acpi_disabled && !acpi_ht)
- return 1;
+ return 1;
acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
@@ -1168,4 +1149,3 @@ int __init acpi_boot_init(void)
return 0;
}
-
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 726a5ca4b165..1ae2aeeda18b 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -7,45 +7,55 @@
#include <linux/pci.h>
#include <asm/pci-direct.h>
#include <asm/acpi.h>
+#include <asm/apic.h>
-static int __init check_bridge(int vendor, int device)
+static int __init check_bridge(int vendor, int device)
{
/* According to Nvidia all timer overrides are bogus. Just ignore
them all. */
- if (vendor == PCI_VENDOR_ID_NVIDIA) {
- acpi_skip_timer_override = 1;
+ if (vendor == PCI_VENDOR_ID_NVIDIA) {
+ acpi_skip_timer_override = 1;
}
+#ifdef CONFIG_X86_LOCAL_APIC
+ /*
+ * ATI IXP chipsets get double timer interrupts.
+ * For now just do this for all ATI chipsets.
+ * FIXME: this needs to be checked for the non ACPI case too.
+ */
+ if (vendor == PCI_VENDOR_ID_ATI)
+ disable_timer_pin_1 = 1;
+#endif
return 0;
}
-
-void __init check_acpi_pci(void)
-{
- int num,slot,func;
+
+void __init check_acpi_pci(void)
+{
+ int num, slot, func;
/* Assume the machine supports type 1. If not it will
always read ffffffff and should not have any side effect. */
/* Poor man's PCI discovery */
- for (num = 0; num < 32; num++) {
- for (slot = 0; slot < 32; slot++) {
- for (func = 0; func < 8; func++) {
+ for (num = 0; num < 32; num++) {
+ for (slot = 0; slot < 32; slot++) {
+ for (func = 0; func < 8; func++) {
u32 class;
u32 vendor;
- class = read_pci_config(num,slot,func,
+ class = read_pci_config(num, slot, func,
PCI_CLASS_REVISION);
if (class == 0xffffffff)
- break;
+ break;
if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
- continue;
-
- vendor = read_pci_config(num, slot, func,
+ continue;
+
+ vendor = read_pci_config(num, slot, func,
PCI_VENDOR_ID);
-
- if (check_bridge(vendor&0xffff, vendor >> 16))
- return;
- }
-
+
+ if (check_bridge(vendor & 0xffff, vendor >> 16))
+ return;
+ }
+
}
}
}
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index c1af93032ff3..1cb2b186a3af 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -20,12 +20,13 @@ extern void zap_low_mappings(void);
extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
-static void init_low_mapping(pgd_t *pgd, int pgd_limit)
+static void init_low_mapping(pgd_t * pgd, int pgd_limit)
{
int pgd_ofs = 0;
- while ((pgd_ofs < pgd_limit) && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
- set_pgd(pgd, *(pgd+USER_PTRS_PER_PGD));
+ while ((pgd_ofs < pgd_limit)
+ && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
+ set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
pgd_ofs++, pgd++;
}
flush_tlb_all();
@@ -37,12 +38,13 @@ static void init_low_mapping(pgd_t *pgd, int pgd_limit)
* Create an identity mapped page table and copy the wakeup routine to
* low memory.
*/
-int acpi_save_state_mem (void)
+int acpi_save_state_mem(void)
{
if (!acpi_wakeup_address)
return 1;
init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD);
- memcpy((void *) acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);
+ memcpy((void *)acpi_wakeup_address, &wakeup_start,
+ &wakeup_end - &wakeup_start);
acpi_copy_wakeup_routine(acpi_wakeup_address);
return 0;
@@ -51,7 +53,7 @@ int acpi_save_state_mem (void)
/*
* acpi_restore_state - undo effects of acpi_save_state_mem
*/
-void acpi_restore_state_mem (void)
+void acpi_restore_state_mem(void)
{
zap_low_mappings();
}
@@ -67,7 +69,8 @@ void acpi_restore_state_mem (void)
void __init acpi_reserve_bootmem(void)
{
if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) {
- printk(KERN_ERR "ACPI: Wakeup code way too big, S3 disabled.\n");
+ printk(KERN_ERR
+ "ACPI: Wakeup code way too big, S3 disabled.\n");
return;
}
@@ -90,10 +93,8 @@ static int __init acpi_sleep_setup(char *str)
return 1;
}
-
__setup("acpi_sleep=", acpi_sleep_setup);
-
static __init int reset_videomode_after_s3(struct dmi_system_id *d)
{
acpi_video_flags |= 2;
@@ -101,14 +102,14 @@ static __init int reset_videomode_after_s3(struct dmi_system_id *d)
}
static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
- { /* Reset video mode after returning from ACPI S3 sleep */
- .callback = reset_videomode_after_s3,
- .ident = "Toshiba Satellite 4030cdt",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
- },
- },
- { }
+ { /* Reset video mode after returning from ACPI S3 sleep */
+ .callback = reset_videomode_after_s3,
+ .ident = "Toshiba Satellite 4030cdt",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+ },
+ },
+ {}
};
static int __init acpisleep_dmi_init(void)
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index 44d886c745ec..7c74fe0dc93c 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -304,12 +304,6 @@ ret_point:
call restore_processor_state
ret
-ENTRY(do_suspend_lowlevel_s4bios)
- call save_processor_state
- call save_registers
- call acpi_enter_sleep_state_s4bios
- ret
-
ALIGN
# saved registers
saved_gdt: .long 0,0
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 4553ffd94b1f..9ad43be9a01f 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -151,7 +151,7 @@ static char __devinit *table_lookup_model(struct cpuinfo_x86 *c)
}
-void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
{
char *v = c->x86_vendor_id;
int i;
@@ -613,8 +613,8 @@ void __devinit cpu_init(void)
memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
GDT_ENTRY_TLS_ENTRIES * 8);
- __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
- __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ load_gdt(&cpu_gdt_descr[cpu]);
+ load_idt(&idt_descr);
/*
* Delete NT
@@ -642,12 +642,12 @@ void __devinit cpu_init(void)
asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
/* Clear all 6 debug registers: */
-
-#define CD(register) set_debugreg(0, register)
-
- CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
-
-#undef CD
+ set_debugreg(0, 0);
+ set_debugreg(0, 1);
+ set_debugreg(0, 2);
+ set_debugreg(0, 3);
+ set_debugreg(0, 6);
+ set_debugreg(0, 7);
/*
* Force FPU initialization:
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 60a9e54dd20e..822c8ce9d1f1 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -31,6 +31,7 @@
#include <linux/cpufreq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/compiler.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
@@ -57,6 +58,8 @@ static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
static struct cpufreq_driver acpi_cpufreq_driver;
+static unsigned int acpi_pstate_strict;
+
static int
acpi_processor_write_port(
u16 port,
@@ -163,34 +166,44 @@ acpi_processor_set_performance (
}
/*
- * Then we read the 'status_register' and compare the value with the
- * target state's 'status' to make sure the transition was successful.
- * Note that we'll poll for up to 1ms (100 cycles of 10us) before
- * giving up.
+ * Assume the write went through when acpi_pstate_strict is not used.
+ * As read status_register is an expensive operation and there
+ * are no specific error cases where an IO port write will fail.
*/
-
- port = data->acpi_data.status_register.address;
- bit_width = data->acpi_data.status_register.bit_width;
-
- dprintk("Looking for 0x%08x from port 0x%04x\n",
- (u32) data->acpi_data.states[state].status, port);
-
- for (i=0; i<100; i++) {
- ret = acpi_processor_read_port(port, bit_width, &value);
- if (ret) {
- dprintk("Invalid port width 0x%04x\n", bit_width);
- retval = ret;
- goto migrate_end;
+ if (acpi_pstate_strict) {
+ /* Then we read the 'status_register' and compare the value
+ * with the target state's 'status' to make sure the
+ * transition was successful.
+ * Note that we'll poll for up to 1ms (100 cycles of 10us)
+ * before giving up.
+ */
+
+ port = data->acpi_data.status_register.address;
+ bit_width = data->acpi_data.status_register.bit_width;
+
+ dprintk("Looking for 0x%08x from port 0x%04x\n",
+ (u32) data->acpi_data.states[state].status, port);
+
+ for (i=0; i<100; i++) {
+ ret = acpi_processor_read_port(port, bit_width, &value);
+ if (ret) {
+ dprintk("Invalid port width 0x%04x\n", bit_width);
+ retval = ret;
+ goto migrate_end;
+ }
+ if (value == (u32) data->acpi_data.states[state].status)
+ break;
+ udelay(10);
}
- if (value == (u32) data->acpi_data.states[state].status)
- break;
- udelay(10);
+ } else {
+ i = 0;
+ value = (u32) data->acpi_data.states[state].status;
}
/* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
- if (value != (u32) data->acpi_data.states[state].status) {
+ if (unlikely(value != (u32) data->acpi_data.states[state].status)) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
@@ -537,6 +550,8 @@ acpi_cpufreq_exit (void)
return;
}
+module_param(acpi_pstate_strict, uint, 0644);
+MODULE_PARM_DESC(acpi_pstate_strict, "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes.");
late_initcall(acpi_cpufreq_init);
module_exit(acpi_cpufreq_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 04e3563da4fe..8ef38544453c 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -64,8 +64,6 @@ static int dont_scale_voltage;
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
-#define __hlt() __asm__ __volatile__("hlt": : :"memory")
-
/* Clock ratios multiplied by 10 */
static int clock_ratio[32];
static int eblcr_table[32];
@@ -168,11 +166,9 @@ static void do_powersaver(union msr_longhaul *longhaul,
outb(0xFE,0x21); /* TMR0 only */
outb(0xFF,0x80); /* delay */
- local_irq_enable();
-
- __hlt();
+ safe_halt();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- __hlt();
+ halt();
local_irq_disable();
@@ -251,9 +247,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
bcr2.bits.CLOCKMUL = clock_ratio_index;
local_irq_disable();
wrmsrl (MSR_VIA_BCR2, bcr2.val);
- local_irq_enable();
-
- __hlt();
+ safe_halt();
/* Disable software clock multiplier */
rdmsrl (MSR_VIA_BCR2, bcr2.val);
@@ -473,11 +467,11 @@ static void __init longhaul_setup_voltagescaling(void)
}
if (vrmrev==0) {
- dprintk ("VRM 8.5 \n");
+ dprintk ("VRM 8.5\n");
memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
} else {
- dprintk ("Mobile VRM \n");
+ dprintk ("Mobile VRM\n");
memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 327a55d4d1c6..c397b6220430 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -259,7 +259,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
if (model->op_points == NULL) {
/* Matched a non-match */
- dprintk(KERN_INFO PFX "no table support for CPU model \"%s\": \n",
+ dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n",
cpu->x86_model_id);
#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
@@ -402,7 +402,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
for (i=0; i<p.state_count; i++) {
if (p.states[i].control != p.states[i].status) {
- dprintk("Different control (%x) and status values (%x)\n",
+ dprintk("Different control (%llu) and status values (%llu)\n",
p.states[i].control, p.states[i].status);
result = -EINVAL;
goto err_unreg;
@@ -415,7 +415,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
}
if (p.states[i].core_frequency > p.states[0].core_frequency) {
- dprintk("P%u has larger frequency (%u) than P0 (%u), skipping\n", i,
+ dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
p.states[i].core_frequency, p.states[0].core_frequency);
p.states[i].core_frequency = 0;
continue;
@@ -498,13 +498,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
- for (i = 0; i < N_IDS; i++)
- if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
- break;
-
- if (i != N_IDS)
- centrino_cpu[policy->cpu] = &cpu_ids[i];
-
if (is_const_loops_cpu(policy->cpu)) {
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
}
@@ -513,6 +506,13 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -ENODEV;
+ for (i = 0; i < N_IDS; i++)
+ if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+ break;
+
+ if (i != N_IDS)
+ centrino_cpu[policy->cpu] = &cpu_ids[i];
+
if (!centrino_cpu[policy->cpu]) {
dprintk(KERN_INFO PFX "found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index b25fb6b635ae..2718fb6f6aba 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -99,7 +99,7 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
u32 function = GET_SPEEDSTEP_FREQS;
if (!(ist_info.event & 0xFFFF)) {
- dprintk("bug #1422 -- can't read freqs from BIOS\n", result);
+ dprintk("bug #1422 -- can't read freqs from BIOS\n");
return -ENODEV;
}
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index ba4b01138c8f..ff87cc22b323 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -132,11 +132,7 @@ static void __init set_cx86_memwb(void)
setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
/* set 'Not Write-through' */
cr0 = 0x20000000;
- __asm__("movl %%cr0,%%eax\n\t"
- "orl %0,%%eax\n\t"
- "movl %%eax,%%cr0\n"
- : : "r" (cr0)
- :"ax");
+ write_cr0(read_cr0() | cr0);
/* CCR2 bit 2: lock NW bit and set WT1 */
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
}
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index a2c33c1a46c5..43601de0f633 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -82,16 +82,13 @@ static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
*/
static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
{
- unsigned int eax;
+ unsigned int eax, ebx, ecx, edx;
if (c->cpuid_level < 4)
return 1;
- __asm__("cpuid"
- : "=a" (eax)
- : "0" (4), "c" (0)
- : "bx", "dx");
-
+ /* Intel has a non-standard dependency on %ecx for this CPUID level. */
+ cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
if (eax & 0x1f)
return ((eax >> 26) + 1);
else
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 6c55b50cf048..9e0d5f83cb9f 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -305,6 +305,9 @@ static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
{
struct _cpuid4_info *this_leaf;
unsigned long num_threads_sharing;
+#ifdef CONFIG_X86_HT
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+#endif
this_leaf = CPUID4_INFO_IDX(cpu, index);
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
@@ -314,10 +317,12 @@ static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
#ifdef CONFIG_X86_HT
else if (num_threads_sharing == smp_num_siblings)
this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
-#endif
+ else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings))
+ this_leaf->shared_cpu_map = cpu_core_map[cpu];
else
- printk(KERN_INFO "Number of CPUs sharing cache didn't match "
+ printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
"any known set of CPUs\n");
+#endif
}
#else
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 764cac64e211..dd4ebd6af7e4 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -561,7 +561,7 @@ struct mtrr_value {
static struct mtrr_value * mtrr_state;
-static int mtrr_save(struct sys_device * sysdev, u32 state)
+static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
{
int i;
int size = num_var_ranges * sizeof(struct mtrr_value);
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index e5fab12f7926..913be77bb844 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -153,7 +153,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
disable_local_APIC();
atomic_dec(&waiting_for_crash_ipi);
/* Assume hlt works */
- __asm__("hlt");
+ halt();
for(;;);
return 1;
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index a3cdf894302b..58516e2ac172 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -6,32 +6,28 @@
#include <linux/bootmem.h>
-struct dmi_header {
- u8 type;
- u8 length;
- u16 handle;
-};
-
-#undef DMI_DEBUG
-
-#ifdef DMI_DEBUG
-#define dmi_printk(x) printk x
-#else
-#define dmi_printk(x)
-#endif
-
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
u8 *bp = ((u8 *) dm) + dm->length;
+ char *str = "";
- if (!s)
- return "";
- s--;
- while (s > 0 && *bp) {
- bp += strlen(bp) + 1;
+ if (s) {
s--;
- }
- return bp;
+ while (s > 0 && *bp) {
+ bp += strlen(bp) + 1;
+ s--;
+ }
+
+ if (*bp != 0) {
+ str = alloc_bootmem(strlen(bp) + 1);
+ if (str != NULL)
+ strcpy(str, bp);
+ else
+ printk(KERN_ERR "dmi_string: out of memory.\n");
+ }
+ }
+
+ return str;
}
/*
@@ -84,69 +80,76 @@ static int __init dmi_checksum(u8 *buf)
return sum == 0;
}
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+static char *dmi_ident[DMI_STRING_MAX];
+static LIST_HEAD(dmi_devices);
+
+/*
+ * Save a DMI string
+ */
+static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
{
- u8 buf[15];
- char __iomem *p, *q;
+ char *p, *d = (char*) dm;
- /*
- * no iounmap() for that ioremap(); it would be a no-op, but it's
- * so early in setup that sucker gets confused into doing what
- * it shouldn't if we actually call it.
- */
- p = ioremap(0xF0000, 0x10000);
+ if (dmi_ident[slot])
+ return;
+
+ p = dmi_string(dm, d[string]);
if (p == NULL)
- return -1;
+ return;
- for (q = p; q < p + 0x10000; q += 16) {
- memcpy_fromio(buf, q, 15);
- if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
- u16 num = (buf[13] << 8) | buf[12];
- u16 len = (buf[7] << 8) | buf[6];
- u32 base = (buf[11] << 24) | (buf[10] << 16) |
- (buf[9] << 8) | buf[8];
+ dmi_ident[slot] = p;
+}
- /*
- * DMI version 0.0 means that the real version is taken from
- * the SMBIOS version, which we don't know at this point.
- */
- if (buf[14] != 0)
- printk(KERN_INFO "DMI %d.%d present.\n",
- buf[14] >> 4, buf[14] & 0xF);
- else
- printk(KERN_INFO "DMI present.\n");
+static void __init dmi_save_devices(struct dmi_header *dm)
+{
+ int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
+ struct dmi_device *dev;
+
+ for (i = 0; i < count; i++) {
+ char *d = ((char *) dm) + (i * 2);
- dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
- num, len));
- dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
+ /* Skip disabled device */
+ if ((*d & 0x80) == 0)
+ continue;
- if (dmi_table(base,len, num, decode) == 0)
- return 0;
+ dev = alloc_bootmem(sizeof(*dev));
+ if (!dev) {
+ printk(KERN_ERR "dmi_save_devices: out of memory.\n");
+ break;
}
+
+ dev->type = *d++ & 0x7f;
+ dev->name = dmi_string(dm, *d);
+ dev->device_data = NULL;
+
+ list_add(&dev->list, &dmi_devices);
}
- return -1;
}
-static char *dmi_ident[DMI_STRING_MAX];
-
-/*
- * Save a DMI string
- */
-static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
+static void __init dmi_save_ipmi_device(struct dmi_header *dm)
{
- char *d = (char*)dm;
- char *p = dmi_string(dm, d[string]);
+ struct dmi_device *dev;
+ void * data;
- if (p == NULL || *p == 0)
+ data = alloc_bootmem(dm->length);
+ if (data == NULL) {
+ printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
return;
- if (dmi_ident[slot])
+ }
+
+ memcpy(data, dm, dm->length);
+
+ dev = alloc_bootmem(sizeof(*dev));
+ if (!dev) {
+ printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
return;
+ }
- dmi_ident[slot] = alloc_bootmem(strlen(p) + 1);
- if(dmi_ident[slot])
- strcpy(dmi_ident[slot], p);
- else
- printk(KERN_ERR "dmi_save_ident: out of memory.\n");
+ dev->type = DMI_DEV_TYPE_IPMI;
+ dev->name = "IPMI controller";
+ dev->device_data = data;
+
+ list_add(&dev->list, &dmi_devices);
}
/*
@@ -156,42 +159,69 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
*/
static void __init dmi_decode(struct dmi_header *dm)
{
- u8 *data __attribute__((__unused__)) = (u8 *)dm;
-
switch(dm->type) {
- case 0:
- dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4])));
+ case 0: /* BIOS Information */
dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
- dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
- dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8])));
dmi_save_ident(dm, DMI_BIOS_DATE, 8);
break;
- case 1:
- dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4])));
+ case 1: /* System Information */
dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
- dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
- dmi_printk(("Version: %s\n", dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
- dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7])));
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
break;
- case 2:
- dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4])));
+ case 2: /* Base Board Information */
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
- dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5])));
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
- dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6])));
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
break;
+ case 10: /* Onboard Devices Information */
+ dmi_save_devices(dm);
+ break;
+ case 38: /* IPMI Device Information */
+ dmi_save_ipmi_device(dm);
}
}
void __init dmi_scan_machine(void)
{
- if (dmi_iterate(dmi_decode))
- printk(KERN_INFO "DMI not present.\n");
+ u8 buf[15];
+ char __iomem *p, *q;
+
+ /*
+ * no iounmap() for that ioremap(); it would be a no-op, but it's
+ * so early in setup that sucker gets confused into doing what
+ * it shouldn't if we actually call it.
+ */
+ p = ioremap(0xF0000, 0x10000);
+ if (p == NULL)
+ goto out;
+
+ for (q = p; q < p + 0x10000; q += 16) {
+ memcpy_fromio(buf, q, 15);
+ if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+ u16 num = (buf[13] << 8) | buf[12];
+ u16 len = (buf[7] << 8) | buf[6];
+ u32 base = (buf[11] << 24) | (buf[10] << 16) |
+ (buf[9] << 8) | buf[8];
+
+ /*
+ * DMI version 0.0 means that the real version is taken from
+ * the SMBIOS version, which we don't know at this point.
+ */
+ if (buf[14] != 0)
+ printk(KERN_INFO "DMI %d.%d present.\n",
+ buf[14] >> 4, buf[14] & 0xF);
+ else
+ printk(KERN_INFO "DMI present.\n");
+
+ if (dmi_table(base,len, num, dmi_decode) == 0)
+ return;
+ }
+ }
+
+out: printk(KERN_INFO "DMI not present.\n");
}
@@ -218,9 +248,9 @@ int dmi_check_system(struct dmi_system_id *list)
/* No match */
goto fail;
}
+ count++;
if (d->callback && d->callback(d))
break;
- count++;
fail: d++;
}
@@ -240,3 +270,32 @@ char *dmi_get_system_info(int field)
return dmi_ident[field];
}
EXPORT_SYMBOL(dmi_get_system_info);
+
+/**
+ * dmi_find_device - find onboard device by type/name
+ * @type: device type or %DMI_DEV_TYPE_ANY to match all device types
+ * @desc: device name string or %NULL to match all
+ * @from: previous device found in search, or %NULL for new search.
+ *
+ * Iterates through the list of known onboard devices. If a device is
+ * found with a matching @vendor and @device, a pointer to its device
+ * structure is returned. Otherwise, %NULL is returned.
+ * A new search is initiated by passing %NULL to the @from argument.
+ * If @from is not %NULL, searches continue from next device.
+ */
+struct dmi_device * dmi_find_device(int type, const char *name,
+ struct dmi_device *from)
+{
+ struct list_head *d, *head = from ? &from->list : &dmi_devices;
+
+ for(d = head->next; d != &dmi_devices; d = d->next) {
+ struct dmi_device *dev = list_entry(d, struct dmi_device, list);
+
+ if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
+ ((name == NULL) || (strcmp(dev->name, name) == 0)))
+ return dev;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(dmi_find_device);
diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
index 789af3e9fb1f..5edb1d379add 100644
--- a/arch/i386/kernel/doublefault.c
+++ b/arch/i386/kernel/doublefault.c
@@ -20,7 +20,7 @@ static void doublefault_fn(void)
struct Xgt_desc_struct gdt_desc = {0, 0};
unsigned long gdt, tss;
- __asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory");
+ store_gdt(&gdt_desc);
gdt = gdt_desc.address;
printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index 385883ea8c19..ecad519fd395 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -79,7 +79,7 @@ static void efi_call_phys_prelog(void)
* directory. If I have PSE, I just need to duplicate one entry in
* page directory.
*/
- __asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
+ cr4 = read_cr4();
if (cr4 & X86_CR4_PSE) {
efi_bak_pg_dir_pointer[0].pgd =
@@ -104,8 +104,7 @@ static void efi_call_phys_prelog(void)
local_flush_tlb();
cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
- __asm__ __volatile__("lgdt %0":"=m"
- (*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
+ load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
}
static void efi_call_phys_epilog(void)
@@ -114,8 +113,8 @@ static void efi_call_phys_epilog(void)
cpu_gdt_descr[0].address =
(unsigned long) __va(cpu_gdt_descr[0].address);
- __asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
- __asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
+ load_gdt(&cpu_gdt_descr[0]);
+ cr4 = read_cr4();
if (cr4 & X86_CR4_PSE) {
swapper_pg_dir[pgd_index(0)].pgd =
@@ -233,22 +232,23 @@ void __init efi_map_memmap(void)
{
memmap.map = NULL;
- memmap.map = (efi_memory_desc_t *)
- bt_ioremap((unsigned long) memmap.phys_map,
- (memmap.nr_map * sizeof(efi_memory_desc_t)));
-
+ memmap.map = bt_ioremap((unsigned long) memmap.phys_map,
+ (memmap.nr_map * memmap.desc_size));
if (memmap.map == NULL)
printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
+
+ memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
}
#if EFI_DEBUG
static void __init print_efi_memmap(void)
{
efi_memory_desc_t *md;
+ void *p;
int i;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
+ md = p;
printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
"range=[0x%016llx-0x%016llx) (%lluMB)\n",
i, md->type, md->attribute, md->phys_addr,
@@ -271,10 +271,10 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
} prev, curr;
efi_memory_desc_t *md;
unsigned long start, end;
- int i;
+ void *p;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
if ((md->num_pages == 0) || (!is_available_memory(md)))
continue;
@@ -325,6 +325,7 @@ void __init efi_init(void)
memmap.phys_map = EFI_MEMMAP;
memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
memmap.desc_version = EFI_MEMDESC_VERSION;
+ memmap.desc_size = EFI_MEMDESC_SIZE;
efi.systab = (efi_system_table_t *)
boot_ioremap((unsigned long) efi_phys.systab,
@@ -428,22 +429,30 @@ void __init efi_init(void)
printk(KERN_ERR PFX "Could not map the runtime service table!\n");
/* Map the EFI memory map for use until paging_init() */
-
- memmap.map = (efi_memory_desc_t *)
- boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
-
+ memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
if (memmap.map == NULL)
printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
- if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
- printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
- "match the one from EFI!\n");
- }
+ memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
+
#if EFI_DEBUG
print_efi_memmap();
#endif
}
+static inline void __init check_range_for_systab(efi_memory_desc_t *md)
+{
+ if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) &&
+ ((unsigned long)efi_phys.systab < md->phys_addr +
+ ((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) {
+ unsigned long addr;
+
+ addr = md->virt_addr - md->phys_addr +
+ (unsigned long)efi_phys.systab;
+ efi.systab = (efi_system_table_t *)addr;
+ }
+}
+
/*
* This function will switch the EFI runtime services to virtual mode.
* Essentially, look through the EFI memmap and map every region that
@@ -457,43 +466,32 @@ void __init efi_enter_virtual_mode(void)
{
efi_memory_desc_t *md;
efi_status_t status;
- int i;
+ void *p;
efi.systab = NULL;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
- if (md->attribute & EFI_MEMORY_RUNTIME) {
- md->virt_addr =
- (unsigned long)ioremap(md->phys_addr,
- md->num_pages << EFI_PAGE_SHIFT);
- if (!(unsigned long)md->virt_addr) {
- printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
- (unsigned long)md->phys_addr);
- }
+ if (!(md->attribute & EFI_MEMORY_RUNTIME))
+ continue;
- if (((unsigned long)md->phys_addr <=
- (unsigned long)efi_phys.systab) &&
- ((unsigned long)efi_phys.systab <
- md->phys_addr +
- ((unsigned long)md->num_pages <<
- EFI_PAGE_SHIFT))) {
- unsigned long addr;
-
- addr = md->virt_addr - md->phys_addr +
- (unsigned long)efi_phys.systab;
- efi.systab = (efi_system_table_t *)addr;
- }
+ md->virt_addr = (unsigned long)ioremap(md->phys_addr,
+ md->num_pages << EFI_PAGE_SHIFT);
+ if (!(unsigned long)md->virt_addr) {
+ printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
+ (unsigned long)md->phys_addr);
}
+ /* update the virtual address of the EFI system table */
+ check_range_for_systab(md);
}
if (!efi.systab)
BUG();
status = phys_efi_set_virtual_address_map(
- sizeof(efi_memory_desc_t) * memmap.nr_map,
- sizeof(efi_memory_desc_t),
+ memmap.desc_size * memmap.nr_map,
+ memmap.desc_size,
memmap.desc_version,
memmap.phys_map);
@@ -533,10 +531,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
{
struct resource *res;
efi_memory_desc_t *md;
- int i;
+ void *p;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
0x100000000ULL)
@@ -613,10 +611,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
u32 efi_mem_type(unsigned long phys_addr)
{
efi_memory_desc_t *md;
- int i;
+ void *p;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
if ((md->phys_addr <= phys_addr) && (phys_addr <
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
return md->type;
@@ -627,10 +625,10 @@ u32 efi_mem_type(unsigned long phys_addr)
u64 efi_mem_attributes(unsigned long phys_addr)
{
efi_memory_desc_t *md;
- int i;
+ void *p;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
if ((md->phys_addr <= phys_addr) && (phys_addr <
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
return md->attribute;
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index a991d4e5edd2..9e24f7b207ee 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -203,7 +203,7 @@ sysenter_past_esp:
GET_THREAD_INFO(%ebp)
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
- testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
+ testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -226,9 +226,9 @@ ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
- # system call tracing in operation
+ # system call tracing in operation / emulation
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
- testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
+ testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -319,7 +319,7 @@ work_notifysig: # deal with pending signals and
# vm86-space
xorl %edx, %edx
call do_notify_resume
- jmp restore_all
+ jmp resume_userspace
ALIGN
work_notifysig_v86:
@@ -329,7 +329,7 @@ work_notifysig_v86:
movl %eax, %esp
xorl %edx, %edx
call do_notify_resume
- jmp restore_all
+ jmp resume_userspace
# perform syscall exit tracing
ALIGN
@@ -338,6 +338,9 @@ syscall_trace_entry:
movl %esp, %eax
xorl %edx,%edx
call do_syscall_trace
+ cmpl $0, %eax
+ jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU,
+ # so must skip actual syscall
movl ORIG_EAX(%esp), %eax
cmpl $(nr_syscalls), %eax
jnae syscall_call
@@ -504,7 +507,7 @@ label: \
pushl $__KERNEL_CS; \
pushl $sysenter_past_esp
-ENTRY(debug)
+KPROBE_ENTRY(debug)
cmpl $sysenter_entry,(%esp)
jne debug_stack_correct
FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
@@ -515,7 +518,7 @@ debug_stack_correct:
movl %esp,%eax # pt_regs pointer
call do_debug
jmp ret_from_exception
-
+ .previous .text
/*
* NMI is doubly nasty. It can happen _while_ we're handling
* a debug fault, and the debug fault hasn't yet been able to
@@ -588,13 +591,14 @@ nmi_16bit_stack:
.long 1b,iret_exc
.previous
-ENTRY(int3)
+KPROBE_ENTRY(int3)
pushl $-1 # mark this as an int
SAVE_ALL
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_int3
jmp ret_from_exception
+ .previous .text
ENTRY(overflow)
pushl $0
@@ -628,17 +632,19 @@ ENTRY(stack_segment)
pushl $do_stack_segment
jmp error_code
-ENTRY(general_protection)
+KPROBE_ENTRY(general_protection)
pushl $do_general_protection
jmp error_code
+ .previous .text
ENTRY(alignment_check)
pushl $do_alignment_check
jmp error_code
-ENTRY(page_fault)
+KPROBE_ENTRY(page_fault)
pushl $do_page_fault
jmp error_code
+ .previous .text
#ifdef CONFIG_X86_MCE
ENTRY(machine_check)
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 4477bb107098..e437fb367498 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -17,7 +17,7 @@
#include <asm/desc.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/setup.h>
/*
@@ -77,6 +77,32 @@ ENTRY(startup_32)
subl %edi,%ecx
shrl $2,%ecx
rep ; stosl
+/*
+ * Copy bootup parameters out of the way.
+ * Note: %esi still has the pointer to the real-mode data.
+ * With the kexec as boot loader, parameter segment might be loaded beyond
+ * kernel image and might not even be addressable by early boot page tables.
+ * (kexec on panic case). Hence copy out the parameters before initializing
+ * page tables.
+ */
+ movl $(boot_params - __PAGE_OFFSET),%edi
+ movl $(PARAM_SIZE/4),%ecx
+ cld
+ rep
+ movsl
+ movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
+ andl %esi,%esi
+ jnz 2f # New command line protocol
+ cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
+ jne 1f
+ movzwl OLD_CL_OFFSET,%esi
+ addl $(OLD_CL_BASE_ADDR),%esi
+2:
+ movl $(saved_command_line - __PAGE_OFFSET),%edi
+ movl $(COMMAND_LINE_SIZE/4),%ecx
+ rep
+ movsl
+1:
/*
* Initialize page tables. This creates a PDE and a set of page
@@ -214,28 +240,6 @@ ENTRY(startup_32_smp)
*/
call setup_idt
-/*
- * Copy bootup parameters out of the way.
- * Note: %esi still has the pointer to the real-mode data.
- */
- movl $boot_params,%edi
- movl $(PARAM_SIZE/4),%ecx
- cld
- rep
- movsl
- movl boot_params+NEW_CL_POINTER,%esi
- andl %esi,%esi
- jnz 2f # New command line protocol
- cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
- jne 1f
- movzwl OLD_CL_OFFSET,%esi
- addl $(OLD_CL_BASE_ADDR),%esi
-2:
- movl $saved_command_line,%edi
- movl $(COMMAND_LINE_SIZE/4),%ecx
- rep
- movsl
-1:
checkCPUtype:
movl $-1,X86_CPUID # -1 for no CPUID initially
diff --git a/arch/i386/kernel/i8237.c b/arch/i386/kernel/i8237.c
new file mode 100644
index 000000000000..c36d1c006c2f
--- /dev/null
+++ b/arch/i386/kernel/i8237.c
@@ -0,0 +1,67 @@
+/*
+ * i8237.c: 8237A DMA controller suspend functions.
+ *
+ * Written by Pierre Ossman, 2005.
+ */
+
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+
+/*
+ * This module just handles suspend/resume issues with the
+ * 8237A DMA controller (used for ISA and LPC).
+ * Allocation is handled in kernel/dma.c and normal usage is
+ * in asm/dma.h.
+ */
+
+static int i8237A_resume(struct sys_device *dev)
+{
+ unsigned long flags;
+ int i;
+
+ flags = claim_dma_lock();
+
+ dma_outb(DMA1_RESET_REG, 0);
+ dma_outb(DMA2_RESET_REG, 0);
+
+ for (i = 0;i < 8;i++) {
+ set_dma_addr(i, 0x000000);
+ /* DMA count is a bit weird so this is not 0 */
+ set_dma_count(i, 1);
+ }
+
+ /* Enable cascade DMA or channel 0-3 won't work */
+ enable_dma(4);
+
+ release_dma_lock(flags);
+
+ return 0;
+}
+
+static int i8237A_suspend(struct sys_device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static struct sysdev_class i8237_sysdev_class = {
+ set_kset_name("i8237"),
+ .suspend = i8237A_suspend,
+ .resume = i8237A_resume,
+};
+
+static struct sys_device device_i8237A = {
+ .id = 0,
+ .cls = &i8237_sysdev_class,
+};
+
+static int __init i8237A_init_sysfs(void)
+{
+ int error = sysdev_class_register(&i8237_sysdev_class);
+ if (!error)
+ error = sysdev_register(&device_i8237A);
+ return error;
+}
+
+device_initcall(i8237A_init_sysfs);
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 6578f40bd501..378313b0cce9 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -33,6 +33,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/sysdev.h>
+
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/desc.h>
@@ -59,6 +60,8 @@ int sis_apic_bug = -1;
*/
int nr_ioapic_registers[MAX_IO_APICS];
+int disable_timer_pin_1 __initdata;
+
/*
* Rough estimation of how many shared IRQs there are, can
* be changed anytime.
@@ -77,7 +80,7 @@ static struct irq_pin_list {
int apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
-int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
#ifdef CONFIG_PCI_MSI
#define vector_to_irq(vector) \
(platform_legacy_irq(vector) ? vector : vector_irq[vector])
@@ -222,13 +225,21 @@ static void clear_IO_APIC (void)
clear_IO_APIC_pin(apic, pin);
}
+#ifdef CONFIG_SMP
static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
{
unsigned long flags;
int pin;
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int apicid_value;
+ cpumask_t tmp;
+ cpus_and(tmp, cpumask, cpu_online_map);
+ if (cpus_empty(tmp))
+ tmp = TARGET_CPUS;
+
+ cpus_and(cpumask, tmp, CPU_MASK_ALL);
+
apicid_value = cpu_mask_to_apicid(cpumask);
/* Prepare to do the io_apic_write */
apicid_value = apicid_value << 24;
@@ -242,6 +253,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
break;
entry = irq_2_pin + entry->next;
}
+ set_irq_info(irq, cpumask);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
@@ -259,7 +271,6 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
# define Dprintk(x...)
# endif
-cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
#define IRQBALANCE_CHECK_ARCH -999
static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
@@ -328,12 +339,7 @@ static inline void balance_irq(int cpu, int irq)
cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
new_cpu = move(cpu, allowed_mask, now, 1);
if (cpu != new_cpu) {
- irq_desc_t *desc = irq_desc + irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- pending_irq_balance_cpumask[irq] = cpumask_of_cpu(new_cpu);
- spin_unlock_irqrestore(&desc->lock, flags);
+ set_pending_irq(irq, cpumask_of_cpu(new_cpu));
}
}
@@ -528,16 +534,12 @@ tryanotherirq:
cpus_and(tmp, target_cpu_mask, allowed_mask);
if (!cpus_empty(tmp)) {
- irq_desc_t *desc = irq_desc + selected_irq;
- unsigned long flags;
Dprintk("irq = %d moved to cpu = %d\n",
selected_irq, min_loaded);
/* mark for change destination */
- spin_lock_irqsave(&desc->lock, flags);
- pending_irq_balance_cpumask[selected_irq] =
- cpumask_of_cpu(min_loaded);
- spin_unlock_irqrestore(&desc->lock, flags);
+ set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+
/* Since we made a change, come back sooner to
* check for more variation.
*/
@@ -568,12 +570,12 @@ static int balanced_irq(void *unused)
/* push everything to CPU 0 to give us a starting point. */
for (i = 0 ; i < NR_IRQS ; i++) {
- pending_irq_balance_cpumask[i] = cpumask_of_cpu(0);
+ pending_irq_cpumask[i] = cpumask_of_cpu(0);
+ set_pending_irq(i, cpumask_of_cpu(0));
}
for ( ; ; ) {
- set_current_state(TASK_INTERRUPTIBLE);
- time_remaining = schedule_timeout(time_remaining);
+ time_remaining = schedule_timeout_interruptible(time_remaining);
try_to_freeze();
if (time_after(jiffies,
prev_balance_time+balanced_irq_interval)) {
@@ -647,20 +649,9 @@ int __init irqbalance_disable(char *str)
__setup("noirqbalance", irqbalance_disable);
-static inline void move_irq(int irq)
-{
- /* note - we hold the desc->lock */
- if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
- set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
- cpus_clear(pending_irq_balance_cpumask[irq]);
- }
-}
-
late_initcall(balanced_irq_init);
-
-#else /* !CONFIG_IRQBALANCE */
-static inline void move_irq(int irq) { }
#endif /* CONFIG_IRQBALANCE */
+#endif /* CONFIG_SMP */
#ifndef CONFIG_SMP
void fastcall send_IPI_self(int vector)
@@ -820,6 +811,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
* we need to reprogram the ioredtbls to cater for the cpus which have come online
* so mask in all cases should simply be TARGET_CPUS
*/
+#ifdef CONFIG_SMP
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
@@ -838,6 +830,7 @@ void __init setup_ioapic_dest(void)
}
}
+#endif
/*
* EISA Edge/Level control register, ELCR
@@ -1127,7 +1120,7 @@ static inline int IO_APIC_irq_trigger(int irq)
}
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
int assign_irq_vector(int irq)
{
@@ -1249,6 +1242,7 @@ static void __init setup_IO_APIC_irqs(void)
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
}
@@ -1641,9 +1635,9 @@ void disable_IO_APIC(void)
clear_IO_APIC();
/*
- * If the i82559 is routed through an IOAPIC
+ * If the i8259 is routed through an IOAPIC
* Put that IOAPIC in virtual wire mode
- * so legacy interrups can be delivered.
+ * so legacy interrupts can be delivered.
*/
pin = find_isa_irq_pin(0, mp_ExtINT);
if (pin != -1) {
@@ -1944,6 +1938,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
{
int irq = vector_to_irq(vector);
+ move_irq(vector);
ack_edge_ioapic_irq(irq);
}
@@ -1958,6 +1953,7 @@ static void end_level_ioapic_vector (unsigned int vector)
{
int irq = vector_to_irq(vector);
+ move_irq(vector);
end_level_ioapic_irq(irq);
}
@@ -1975,14 +1971,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
unmask_IO_APIC_irq(irq);
}
+#ifdef CONFIG_SMP
static void set_ioapic_affinity_vector (unsigned int vector,
cpumask_t cpu_mask)
{
int irq = vector_to_irq(vector);
+ set_native_irq_info(vector, cpu_mask);
set_ioapic_affinity_irq(irq, cpu_mask);
}
#endif
+#endif
/*
* Level and edge triggered IO-APIC interrupts need different handling,
@@ -1992,7 +1991,7 @@ static void set_ioapic_affinity_vector (unsigned int vector,
* edge-triggered handler, without risking IRQ storms and other ugly
* races.
*/
-static struct hw_interrupt_type ioapic_edge_type = {
+static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
.typename = "IO-APIC-edge",
.startup = startup_edge_ioapic,
.shutdown = shutdown_edge_ioapic,
@@ -2000,10 +1999,12 @@ static struct hw_interrupt_type ioapic_edge_type = {
.disable = disable_edge_ioapic,
.ack = ack_edge_ioapic,
.end = end_edge_ioapic,
+#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
+#endif
};
-static struct hw_interrupt_type ioapic_level_type = {
+static struct hw_interrupt_type ioapic_level_type __read_mostly = {
.typename = "IO-APIC-level",
.startup = startup_level_ioapic,
.shutdown = shutdown_level_ioapic,
@@ -2011,7 +2012,9 @@ static struct hw_interrupt_type ioapic_level_type = {
.disable = disable_level_ioapic,
.ack = mask_and_ack_level_ioapic,
.end = end_level_ioapic,
+#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
+#endif
};
static inline void init_IO_APIC_traps(void)
@@ -2074,7 +2077,7 @@ static void ack_lapic_irq (unsigned int irq)
static void end_lapic_irq (unsigned int i) { /* nothing */ }
-static struct hw_interrupt_type lapic_irq_type = {
+static struct hw_interrupt_type lapic_irq_type __read_mostly = {
.typename = "local-APIC-edge",
.startup = NULL, /* startup_irq() not used for IRQ0 */
.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
@@ -2210,6 +2213,8 @@ static inline void check_timer(void)
setup_nmi();
enable_8259A_irq(0);
}
+ if (disable_timer_pin_1 > 0)
+ clear_IO_APIC_pin(0, pin1);
return;
}
clear_IO_APIC_pin(0, pin1);
@@ -2421,7 +2426,7 @@ device_initcall(ioapic_init_sysfs);
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
int __init io_apic_get_unique_id (int ioapic, int apic_id)
{
@@ -2569,9 +2574,10 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
return 0;
}
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /* CONFIG_ACPI */
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index 8b25160393c1..f2b37654777f 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -132,6 +132,7 @@ asmlinkage long sys_iopl(unsigned long unused)
volatile struct pt_regs * regs = (struct pt_regs *) &unused;
unsigned int level = regs->ebx;
unsigned int old = (regs->eflags >> 12) & 3;
+ struct thread_struct *t = &current->thread;
if (level > 3)
return -EINVAL;
@@ -140,8 +141,8 @@ asmlinkage long sys_iopl(unsigned long unused)
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
}
- regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
- /* Make sure we return the long way (not sysenter) */
- set_thread_flag(TIF_IRET);
+ t->iopl = level << 12;
+ regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
+ set_iopl_mask(t->iopl);
return 0;
}
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index a6d8c45961d3..6345b430b105 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -62,32 +62,32 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode)
return 0;
}
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
return 0;
}
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
{
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
}
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}
@@ -127,7 +127,8 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->eip = (unsigned long)&p->ainsn.insn;
}
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
{
unsigned long *sara = (unsigned long *)&regs->esp;
struct kretprobe_instance *ri;
@@ -150,7 +151,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
*/
-static int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
@@ -176,7 +177,8 @@ static int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS) {
+ if (kprobe_status == KPROBE_HIT_SS &&
+ *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
regs->eflags &= ~TF_MASK;
regs->eflags |= kprobe_saved_eflags;
unlock_kprobes();
@@ -220,7 +222,10 @@ static int kprobe_handler(struct pt_regs *regs)
* either a probepoint or a debugger breakpoint
* at this address. In either case, no further
* handling of this interrupt is appropriate.
+ * Back up over the (now missing) int3 and run
+ * the original instruction.
*/
+ regs->eip -= sizeof(kprobe_opcode_t);
ret = 1;
}
/* Not one of ours: let kernel handle it */
@@ -259,7 +264,7 @@ no_kprobe:
/*
* Called when we hit the probe point at kretprobe_trampoline
*/
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
@@ -338,7 +343,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* that is atop the stack is the address following the copied instruction.
* We need to make it the address following the original instruction.
*/
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
unsigned long *tos = (unsigned long *)&regs->esp;
unsigned long next_eip = 0;
@@ -444,8 +449,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
/*
* Wrapper routine to for handling exceptions.
*/
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
- void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
switch (val) {
@@ -473,7 +478,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
return NOTIFY_DONE;
}
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr;
@@ -495,7 +500,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
{
preempt_enable_no_resched();
asm volatile (" xchgl %%ebx,%%esp \n"
@@ -506,7 +511,7 @@ void jprobe_return(void)
(jprobe_saved_esp):"memory");
}
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
u8 *addr = (u8 *) (regs->eip - 1);
unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
index bb50afbee921..fe1ffa55587d 100644
--- a/arch/i386/kernel/ldt.c
+++ b/arch/i386/kernel/ldt.c
@@ -177,7 +177,7 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct * mm = current->mm;
- __u32 entry_1, entry_2, *lp;
+ __u32 entry_1, entry_2;
int error;
struct user_desc ldt_info;
@@ -205,8 +205,6 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
goto out_unlock;
}
- lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
-
/* Allow LDTs to be cleared by the user. */
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
if (oldmode || LDT_empty(&ldt_info)) {
@@ -223,8 +221,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
/* Install the new entry ... */
install:
- *lp = entry_1;
- *(lp+1) = entry_2;
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, entry_2);
error = 0;
out_unlock:
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
index cb699a2aa1f8..a912fed48482 100644
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -17,13 +17,7 @@
#include <asm/apic.h>
#include <asm/cpufeature.h>
#include <asm/desc.h>
-
-static inline unsigned long read_cr3(void)
-{
- unsigned long cr3;
- asm volatile("movl %%cr3,%0": "=r"(cr3));
- return cr3;
-}
+#include <asm/system.h>
#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
@@ -99,10 +93,7 @@ static void set_idt(void *newidt, __u16 limit)
curidt.size = limit;
curidt.address = (unsigned long)newidt;
- __asm__ __volatile__ (
- "lidtl %0\n"
- : : "m" (curidt)
- );
+ load_idt(&curidt);
};
@@ -114,10 +105,7 @@ static void set_gdt(void *newgdt, __u16 limit)
curgdt.size = limit;
curgdt.address = (unsigned long)newgdt;
- __asm__ __volatile__ (
- "lgdtl %0\n"
- : : "m" (curgdt)
- );
+ load_gdt(&curgdt);
};
static void load_segments(void)
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index a77c612aad00..165f13158c60 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -164,7 +164,8 @@ static void collect_cpu_info (void *unused)
}
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+ /* see notes above for revision 1.07. Apparent chip bug */
+ serialize_cpu();
/* get the current revision from MSR 0x8B */
rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
@@ -377,7 +378,9 @@ static void do_update_one (void * unused)
(unsigned long) uci->mc->bits >> 16 >> 16);
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+ /* see notes above for revision 1.07. Apparent chip bug */
+ serialize_cpu();
+
/* get the current revision from MSR 0x8B */
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index ce838abb27d8..15949fd08109 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -65,6 +65,8 @@ int nr_ioapics;
int pic_mode;
unsigned long mp_lapic_addr;
+unsigned int def_to_bigsmp = 0;
+
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
/* Internal processor count */
@@ -121,7 +123,7 @@ static int MP_valid_apicid(int apicid, int version)
static void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
- physid_mask_t tmp;
+ physid_mask_t phys_cpu;
if (!(m->mpc_cpuflag & CPU_ENABLED))
return;
@@ -192,27 +194,36 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
" Processor ignored.\n", maxcpus);
return;
}
- num_processors++;
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);
- --num_processors;
return;
}
- tmp = apicid_to_cpu_present(apicid);
- physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
-
+ cpu_set(num_processors, cpu_possible_map);
+ num_processors++;
+ phys_cpu = apicid_to_cpu_present(apicid);
+ physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+
/*
* Validate version
*/
if (ver == 0x0) {
- printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+ printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+ "fixing up to 0x10. (tell your hw vendor)\n",
+ m->mpc_apicid);
ver = 0x10;
}
apic_version[m->mpc_apicid] = ver;
+ if ((num_processors > 8) &&
+ APIC_XAPIC(ver) &&
+ (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+ def_to_bigsmp = 1;
+ else
+ def_to_bigsmp = 0;
+
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
@@ -653,8 +664,6 @@ void __init get_smp_config (void)
struct intel_mp_floating *mpf = mpf_found;
/*
- * ACPI may be used to obtain the entire SMP configuration or just to
- * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that
* ACPI supports both logical (e.g. Hyper-Threading) and physical
* processors, where MPS only supports physical.
*/
@@ -810,7 +819,7 @@ void __init find_smp_config (void)
ACPI-based MP Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
void __init mp_register_lapic_address (
u64 address)
@@ -856,7 +865,7 @@ void __init mp_register_lapic (
MP_processor_info(&processor);
}
-#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+#ifdef CONFIG_X86_IO_APIC
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
@@ -1071,11 +1080,9 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
*/
static int gsi_to_irq[MAX_GSI_NUM];
-#ifdef CONFIG_ACPI_BUS
/* Don't set up the ACPI SCI because it's already set up */
if (acpi_fadt.sci_int == gsi)
return gsi;
-#endif
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
@@ -1118,13 +1125,11 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
if (gsi < MAX_GSI_NUM) {
if (gsi > 15)
gsi = pci_irq++;
-#ifdef CONFIG_ACPI_BUS
/*
* Don't assign IRQ used by ACPI SCI
*/
if (gsi == acpi_fadt.sci_int)
gsi = pci_irq++;
-#endif
gsi_to_irq[irq] = gsi;
} else {
printk(KERN_ERR "GSI %u is too high\n", gsi);
@@ -1138,5 +1143,5 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
return gsi;
}
-#endif /*CONFIG_X86_IO_APIC && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)*/
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /* CONFIG_X86_IO_APIC */
+#endif /* CONFIG_ACPI */
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index b2f03c39a6fe..03100d6fc5d6 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -46,23 +46,13 @@
static struct class *msr_class;
-/* Note: "err" is handled in a funny way below. Otherwise one version
- of gcc or another breaks. */
-
static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
{
int err;
- asm volatile ("1: wrmsr\n"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- "3: movl %4,%0\n"
- " jmp 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n" " .long 1b,3b\n" ".previous":"=&bDS" (err)
- :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
-
+ err = wrmsr_safe(reg, eax, edx);
+ if (err)
+ err = -EIO;
return err;
}
@@ -70,18 +60,9 @@ static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
{
int err;
- asm volatile ("1: rdmsr\n"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- "3: movl %4,%0\n"
- " jmp 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 1b,3b\n"
- ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
- :"c"(reg), "i"(-EIO), "0"(0));
-
+ err = rdmsr_safe(reg, eax, edx);
+ if (err)
+ err = -EIO;
return err;
}
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 8c242bb1ef45..0178457db721 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -478,6 +478,11 @@ void touch_nmi_watchdog (void)
*/
for (i = 0; i < NR_CPUS; i++)
alert_counter[i] = 0;
+
+ /*
+ * Tickle the softlockup detector too:
+ */
+ touch_softlockup_watchdog();
}
extern void die_nmi(struct pt_regs *, const char *msg);
@@ -501,8 +506,11 @@ void nmi_watchdog_tick (struct pt_regs * regs)
*/
alert_counter[cpu]++;
if (alert_counter[cpu] == 5*nmi_hz)
+ /*
+ * die_nmi will return ONLY if NOTIFY_STOP happens..
+ */
die_nmi(regs, "NMI Watchdog detected LOCKUP");
- } else {
+
last_irq_sums[cpu] = sum;
alert_counter[cpu] = 0;
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index e3f362e8af5b..b45cbf93d439 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -164,7 +164,7 @@ static inline void play_dead(void)
*/
local_irq_disable();
while (1)
- __asm__ __volatile__("hlt":::"memory");
+ halt();
}
#else
static inline void play_dead(void)
@@ -313,16 +313,12 @@ void show_regs(struct pt_regs * regs)
printk(" DS: %04x ES: %04x\n",
0xffff & regs->xds,0xffff & regs->xes);
- __asm__("movl %%cr0, %0": "=r" (cr0));
- __asm__("movl %%cr2, %0": "=r" (cr2));
- __asm__("movl %%cr3, %0": "=r" (cr3));
- /* This could fault if %cr4 does not exist */
- __asm__("1: movl %%cr4, %0 \n"
- "2: \n"
- ".section __ex_table,\"a\" \n"
- ".long 1b,2b \n"
- ".previous \n"
- : "=r" (cr4): "0" (0));
+ cr0 = read_cr0();
+ cr2 = read_cr2();
+ cr3 = read_cr3();
+ if (current_cpu_data.x86 > 4) {
+ cr4 = read_cr4();
+ }
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
show_trace(NULL, &regs->esp);
}
@@ -682,21 +678,26 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
__unlazy_fpu(prev_p);
/*
- * Reload esp0, LDT and the page table pointer:
+ * Reload esp0.
*/
load_esp0(tss, next);
/*
- * Load the per-thread Thread-Local Storage descriptor.
+ * Save away %fs and %gs. No need to save %es and %ds, as
+ * those are always kernel segments while inside the kernel.
+ * Doing this before setting the new TLS descriptors avoids
+ * the situation where we temporarily have non-reloadable
+ * segments in %fs and %gs. This could be an issue if the
+ * NMI handler ever used %fs or %gs (it does not today), or
+ * if the kernel is running inside of a hypervisor layer.
*/
- load_TLS(next, cpu);
+ savesegment(fs, prev->fs);
+ savesegment(gs, prev->gs);
/*
- * Save away %fs and %gs. No need to save %es and %ds, as
- * those are always kernel segments while inside the kernel.
+ * Load the per-thread Thread-Local Storage descriptor.
*/
- asm volatile("mov %%fs,%0":"=m" (prev->fs));
- asm volatile("mov %%gs,%0":"=m" (prev->gs));
+ load_TLS(next, cpu);
/*
* Restore %fs and %gs if needed.
@@ -711,6 +712,12 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
loadsegment(gs, next->gs);
/*
+ * Restore IOPL if needed.
+ */
+ if (unlikely(prev->iopl != next->iopl))
+ set_iopl_mask(next->iopl);
+
+ /*
* Now maybe reload the debug registers
*/
if (unlikely(next->debugreg[7])) {
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0da59b42843c..7b6368bf8974 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -271,6 +271,8 @@ static void clear_singlestep(struct task_struct *child)
void ptrace_disable(struct task_struct *child)
{
clear_singlestep(child);
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
}
/*
@@ -509,15 +511,20 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
break;
+ case PTRACE_SYSEMU: /* continue and stop at next syscall, which will not be executed */
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
- if (request == PTRACE_SYSCALL) {
+ if (request == PTRACE_SYSEMU) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ } else if (request == PTRACE_SYSCALL) {
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
+ } else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
}
child->exit_code = data;
@@ -542,10 +549,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
break;
+ case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */
case PTRACE_SINGLESTEP: /* set the trap flag. */
ret = -EIO;
if (!valid_signal(data))
break;
+
+ if (request == PTRACE_SYSEMU_SINGLESTEP)
+ set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
+
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
set_singlestep(child);
child->exit_code = data;
@@ -678,27 +692,58 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
* - triggered by current->work.syscall_trace
*/
__attribute__((regparm(3)))
-void do_syscall_trace(struct pt_regs *regs, int entryexit)
+int do_syscall_trace(struct pt_regs *regs, int entryexit)
{
- /* do the secure computing check first */
- secure_computing(regs->orig_eax);
+ int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
+ /*
+ * With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP for syscall
+ * interception
+ */
+ int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
+ int ret = 0;
- if (unlikely(current->audit_context) && entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
+ /* do the secure computing check first */
+ if (!entryexit)
+ secure_computing(regs->orig_eax);
+
+ if (unlikely(current->audit_context)) {
+ if (entryexit)
+ audit_syscall_exit(current, 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
+ * not used, entry.S will call us only on syscall exit, not
+ * entry; so when TIF_SYSCALL_AUDIT is used we must avoid
+ * calling send_sigtrap() on syscall entry.
+ *
+ * Note that when PTRACE_SYSEMU_SINGLESTEP is used,
+ * is_singlestep is false, despite his name, so we will still do
+ * the correct thing.
+ */
+ else if (is_singlestep)
+ goto out;
+ }
if (!(current->ptrace & PT_PTRACED))
goto out;
+ /* If a process stops on the 1st tracepoint with SYSCALL_TRACE
+ * and then is resumed with SYSEMU_SINGLESTEP, it will come in
+ * here. We have to check this and return */
+ if (is_sysemu && entryexit)
+ return 0;
+
/* Fake a debug trap */
- if (test_thread_flag(TIF_SINGLESTEP))
+ if (is_singlestep)
send_sigtrap(current, regs, 0);
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu)
goto out;
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+ /* Note that the debugger could change the result of test_thread_flag!*/
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80:0));
/*
* this isn't the same as continuing with a signal, but it will do
@@ -709,9 +754,17 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
- out:
+ ret = is_sysemu;
+out:
if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(current, 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);
+ return 1;
}
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index c71fef31dc47..350ea6680f63 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -11,8 +11,10 @@
#include <linux/mc146818rtc.h>
#include <linux/efi.h>
#include <linux/dmi.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/apic.h>
+#include <asm/desc.h>
#include "mach_reboot.h"
#include <linux/reboot_fixups.h>
@@ -27,8 +29,6 @@ static int reboot_thru_bios;
#ifdef CONFIG_SMP
static int reboot_cpu = -1;
-/* shamelessly grabbed from lib/vsprintf.c for readability */
-#define is_digit(c) ((c) >= '0' && (c) <= '9')
#endif
static int __init reboot_setup(char *str)
{
@@ -48,9 +48,9 @@ static int __init reboot_setup(char *str)
break;
#ifdef CONFIG_SMP
case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
- if (is_digit(*(str+1))) {
+ if (isdigit(*(str+1))) {
reboot_cpu = (int) (*(str+1) - '0');
- if (is_digit(*(str+2)))
+ if (isdigit(*(str+2)))
reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
}
/* we will leave sorting out the final value
@@ -242,13 +242,13 @@ void machine_real_restart(unsigned char *code, int length)
/* Set up the IDT for real mode. */
- __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
+ load_idt(&real_mode_idt);
/* Set up a GDT from which we can load segment descriptors for real
mode. The GDT is not used in real mode; it is just needed here to
prepare the descriptors. */
- __asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
+ load_gdt(&real_mode_gdt);
/* Load the data segment registers, and thus the descriptors ready for
real mode. The base address of each segment is 0x100, 16 times the
@@ -316,7 +316,7 @@ void machine_emergency_restart(void)
if (!reboot_thru_bios) {
if (efi_enabled) {
efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
- __asm__ __volatile__("lidt %0": :"m" (no_idt));
+ load_idt(&no_idt);
__asm__ __volatile__("int3");
}
/* rebooting needs to touch the page at absolute addr 0 */
@@ -325,7 +325,7 @@ void machine_emergency_restart(void)
mach_reboot_fixups(); /* for board specific fixups */
mach_reboot();
/* That didn't work - force a triple fault.. */
- __asm__ __volatile__("lidt %0": :"m" (no_idt));
+ load_idt(&no_idt);
__asm__ __volatile__("int3");
}
}
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
index 469f496e55c0..7455ab643943 100644
--- a/arch/i386/kernel/semaphore.c
+++ b/arch/i386/kernel/semaphore.c
@@ -13,171 +13,9 @@
* rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
*/
#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/init.h>
#include <asm/semaphore.h>
/*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to acquire the semaphore, while the "sleeping"
- * variable is a count of such acquires.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * "sleeping" and the contention routine ordering is protected
- * by the spinlock in the semaphore's waitqueue head.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
- */
-
-/*
- * Logic:
- * - only on a boundary condition do we need to care. When we go
- * from a negative count to a non-negative, we wake people up.
- * - when we go from a non-negative count to a negative do we
- * (a) synchronize with the "sleeper" count and (b) make sure
- * that we're on the wakeup list before we synchronize so that
- * we cannot lose wakeup events.
- */
-
-static fastcall void __attribute_used__ __up(struct semaphore *sem)
-{
- wake_up(&sem->wait);
-}
-
-static fastcall void __attribute_used__ __sched __down(struct semaphore * sem)
-{
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
- unsigned long flags;
-
- tsk->state = TASK_UNINTERRUPTIBLE;
- spin_lock_irqsave(&sem->wait.lock, flags);
- add_wait_queue_exclusive_locked(&sem->wait, &wait);
-
- sem->sleepers++;
- for (;;) {
- int sleepers = sem->sleepers;
-
- /*
- * Add "everybody else" into it. They aren't
- * playing, because we own the spinlock in
- * the wait_queue_head.
- */
- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
- sem->sleepers = 0;
- break;
- }
- sem->sleepers = 1; /* us - see -1 above */
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- schedule();
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- tsk->state = TASK_UNINTERRUPTIBLE;
- }
- remove_wait_queue_locked(&sem->wait, &wait);
- wake_up_locked(&sem->wait);
- spin_unlock_irqrestore(&sem->wait.lock, flags);
- tsk->state = TASK_RUNNING;
-}
-
-static fastcall int __attribute_used__ __sched __down_interruptible(struct semaphore * sem)
-{
- int retval = 0;
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
- unsigned long flags;
-
- tsk->state = TASK_INTERRUPTIBLE;
- spin_lock_irqsave(&sem->wait.lock, flags);
- add_wait_queue_exclusive_locked(&sem->wait, &wait);
-
- sem->sleepers++;
- for (;;) {
- int sleepers = sem->sleepers;
-
- /*
- * With signals pending, this turns into
- * the trylock failure case - we won't be
- * sleeping, and we* can't get the lock as
- * it has contention. Just correct the count
- * and exit.
- */
- if (signal_pending(current)) {
- retval = -EINTR;
- sem->sleepers = 0;
- atomic_add(sleepers, &sem->count);
- break;
- }
-
- /*
- * Add "everybody else" into it. They aren't
- * playing, because we own the spinlock in
- * wait_queue_head. The "-1" is because we're
- * still hoping to get the semaphore.
- */
- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
- sem->sleepers = 0;
- break;
- }
- sem->sleepers = 1; /* us - see -1 above */
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- schedule();
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- tsk->state = TASK_INTERRUPTIBLE;
- }
- remove_wait_queue_locked(&sem->wait, &wait);
- wake_up_locked(&sem->wait);
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- tsk->state = TASK_RUNNING;
- return retval;
-}
-
-/*
- * Trylock failed - make sure we correct for
- * having decremented the count.
- *
- * We could have done the trylock with a
- * single "cmpxchg" without failure cases,
- * but then it wouldn't work on a 386.
- */
-static fastcall int __attribute_used__ __down_trylock(struct semaphore * sem)
-{
- int sleepers;
- unsigned long flags;
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- sleepers = sem->sleepers + 1;
- sem->sleepers = 0;
-
- /*
- * Add "everybody else" and us into it. They aren't
- * playing, because we own the spinlock in the
- * wait_queue_head.
- */
- if (!atomic_add_negative(sleepers, &sem->count)) {
- wake_up_locked(&sem->wait);
- }
-
- spin_unlock_irqrestore(&sem->wait.lock, flags);
- return 1;
-}
-
-
-/*
* The semaphore operations have a special calling sequence that
* allow us to do a simpler in-line version of them. These routines
* need to convert that sequence back into the C sequence when
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index af4de58cab54..dc39ca6a7eca 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -82,19 +82,19 @@ EXPORT_SYMBOL(efi_enabled);
/* cpu data as detected by the assembly code in head.S */
struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
/* common cpu data for all cpus */
-struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
-#ifdef CONFIG_ACPI_INTERPRETER
+#ifdef CONFIG_ACPI
int acpi_disabled = 0;
#else
int acpi_disabled = 1;
#endif
EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
int __initdata acpi_force = 0;
extern acpi_interrupt_flags acpi_sci_flags;
#endif
@@ -139,6 +139,7 @@ struct sys_desc_table_struct {
unsigned char table[0];
};
struct edid_info edid_info;
+EXPORT_SYMBOL_GPL(edid_info);
struct ist_info ist_info;
#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
@@ -370,12 +371,16 @@ static void __init limit_regions(unsigned long long size)
int i;
if (efi_enabled) {
- for (i = 0; i < memmap.nr_map; i++) {
- current_addr = memmap.map[i].phys_addr +
- (memmap.map[i].num_pages << 12);
- if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
+ efi_memory_desc_t *md;
+ void *p;
+
+ for (p = memmap.map, i = 0; p < memmap.map_end;
+ p += memmap.desc_size, i++) {
+ md = p;
+ current_addr = md->phys_addr + (md->num_pages << 12);
+ if (md->type == EFI_CONVENTIONAL_MEMORY) {
if (current_addr >= size) {
- memmap.map[i].num_pages -=
+ md->num_pages -=
(((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
memmap.nr_map = i + 1;
return;
@@ -794,7 +799,7 @@ static void __init parse_cmdline_early (char ** cmdline_p)
}
#endif
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/* "acpi=off" disables both ACPI table parsing and interpreter */
else if (!memcmp(from, "acpi=off", 8)) {
disable_acpi();
@@ -846,11 +851,16 @@ static void __init parse_cmdline_early (char ** cmdline_p)
#endif
#ifdef CONFIG_X86_LOCAL_APIC
+ if (!memcmp(from, "disable_timer_pin_1", 19))
+ disable_timer_pin_1 = 1;
+ if (!memcmp(from, "enable_timer_pin_1", 18))
+ disable_timer_pin_1 = -1;
+
/* disable IO-APIC */
else if (!memcmp(from, "noapic", 6))
disable_ioapic_setup();
#endif /* CONFIG_X86_LOCAL_APIC */
-#endif /* CONFIG_ACPI_BOOT */
+#endif /* CONFIG_ACPI */
#ifdef CONFIG_X86_LOCAL_APIC
/* enable local APIC */
@@ -1295,7 +1305,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
*/
static void __init register_memory(void)
{
- unsigned long gapstart, gapsize;
+ unsigned long gapstart, gapsize, round;
unsigned long long last;
int i;
@@ -1340,14 +1350,14 @@ static void __init register_memory(void)
}
/*
- * Start allocating dynamic PCI memory a bit into the gap,
- * aligned up to the nearest megabyte.
- *
- * Question: should we try to pad it up a bit (do something
- * like " + (gapsize >> 3)" in there too?). We now have the
- * technology.
+ * See how much we want to round up: start off with
+ * rounding to the next 1MB area.
*/
- pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+ round = 0x100000;
+ while ((gapsize >> 4) > round)
+ round += round;
+ /* Fun with two's complement */
+ pci_mem_start = (gapstart + round) & -round;
printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
pci_mem_start, gapstart, gapsize);
@@ -1575,14 +1585,20 @@ void __init setup_arch(char **cmdline_p)
if (efi_enabled)
efi_map_memmap();
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
acpi_boot_table_init();
acpi_boot_init();
-#endif
+#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
+ if (def_to_bigsmp)
+ printk(KERN_WARNING "More than 8 CPUs detected and "
+ "CONFIG_X86_PC cannot handle it.\nUse "
+ "CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
+#endif
+#endif
#ifdef CONFIG_X86_LOCAL_APIC
if (smp_found_config)
get_smp_config();
diff --git a/arch/i386/kernel/sigframe.h b/arch/i386/kernel/sigframe.h
index d21b14f5c25c..0b2221711dad 100644
--- a/arch/i386/kernel/sigframe.h
+++ b/arch/i386/kernel/sigframe.h
@@ -1,6 +1,6 @@
struct sigframe
{
- char *pretcode;
+ char __user *pretcode;
int sig;
struct sigcontext sc;
struct _fpstate fpstate;
@@ -10,10 +10,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;
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 89ef7adc63a4..61eb0c8a6e47 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -278,9 +278,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
int tmp, err = 0;
tmp = 0;
- __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
+ savesegment(gs, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
- __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
+ savesegment(fs, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
@@ -577,10 +577,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
ret = setup_frame(sig, ka, oldset, regs);
- if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- sigaddset(&current->blocked,sig);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
@@ -603,7 +604,9 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
- * if so.
+ * if so. vm86 regs switched out by assembly code
+ * before reaching here, so testing against kernel
+ * CS suffices.
*/
if (!user_mode(regs))
return 1;
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index cec4bde67161..48b55db3680f 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -576,7 +576,7 @@ static void stop_this_cpu (void * dummy)
local_irq_disable();
disable_local_APIC();
if (cpu_data[smp_processor_id()].hlt_works_ok)
- for(;;) __asm__("hlt");
+ for(;;) halt();
for (;;);
}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 8ac8e9fd5614..5f0a95d76a4f 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -88,6 +88,8 @@ EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map;
EXPORT_SYMBOL(cpu_callout_map);
+cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
static cpumask_t smp_commenced_mask;
/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
@@ -200,7 +202,7 @@ static void __devinit smp_store_cpu_info(int id)
goto valid_k7;
/* If we get here, it's not a certified SMP capable AMD system. */
- tainted |= TAINT_UNSAFE_SMP;
+ add_taint(TAINT_UNSAFE_SMP);
}
valid_k7:
@@ -1017,8 +1019,8 @@ int __devinit smp_prepare_cpu(int cpu)
tsc_sync_disabled = 1;
/* init low mem mapping */
- memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
- sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS);
+ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+ KERNEL_PGD_PTRS);
flush_tlb_all();
schedule_work(&task);
wait_for_completion(&done);
@@ -1265,6 +1267,7 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callout_map);
cpu_set(smp_processor_id(), cpu_present_map);
+ cpu_set(smp_processor_id(), cpu_possible_map);
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
}
@@ -1327,8 +1330,7 @@ void __cpu_die(unsigned int cpu)
printk ("CPU %d is now offline\n", cpu);
return;
}
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ msleep(100);
}
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 7b3b27d64409..516bf5653b02 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -213,12 +213,18 @@ static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_c
node_end_pfn[nid] = memory_chunk->end_pfn;
}
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+ return pxm_to_nid_map[pxm];
+}
+
/* Parse the ACPI Static Resource Affinity Table */
static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
{
u8 *start, *end, *p;
int i, j, nid;
- u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
start = (u8 *)(&(sratp->reserved) + 1); /* skip header */
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 0ee9dee8af06..2883a4d4f01f 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -194,10 +194,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
@@ -252,8 +249,7 @@ EXPORT_SYMBOL(profile_pc);
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static inline void do_timer_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
{
#ifdef CONFIG_X86_IO_APIC
if (timer_ack) {
@@ -307,7 +303,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
cur_timer->mark_offset();
- do_timer_interrupt(irq, NULL, regs);
+ do_timer_interrupt(irq, regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
@@ -333,8 +329,7 @@ EXPORT_SYMBOL(get_cmos_time);
static void sync_cmos_clock(unsigned long dummy);
-static struct timer_list sync_cmos_timer =
- TIMER_INITIALIZER(sync_cmos_clock, 0, 0);
+static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
static void sync_cmos_clock(unsigned long dummy)
{
@@ -348,7 +343,7 @@ static void sync_cmos_clock(unsigned long dummy)
* This code is run on a timer. If the clock is set, that timer
* may not expire at the correct time. Thus, we adjust...
*/
- if ((time_status & STA_UNSYNC) != 0)
+ if (!ntp_synced())
/*
* Not synced, exit, do not restart a timer (if one is
* running, let it run out).
@@ -383,6 +378,7 @@ void notify_arch_cmos_timer(void)
static long clock_cmos_diff, sleep_start;
+static struct timer_opts *last_timer;
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
/*
@@ -391,6 +387,10 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state)
clock_cmos_diff = -get_cmos_time();
clock_cmos_diff += get_seconds();
sleep_start = get_cmos_time();
+ last_timer = cur_timer;
+ cur_timer = &timer_none;
+ if (last_timer->suspend)
+ last_timer->suspend(state);
return 0;
}
@@ -404,6 +404,7 @@ static int timer_resume(struct sys_device *dev)
if (is_hpet_enabled())
hpet_reenable();
#endif
+ setup_pit_timer();
sec = get_cmos_time() + clock_cmos_diff;
sleep_length = (get_cmos_time() - sleep_start) * HZ;
write_seqlock_irqsave(&xtime_lock, flags);
@@ -412,6 +413,11 @@ static int timer_resume(struct sys_device *dev)
write_sequnlock_irqrestore(&xtime_lock, flags);
jiffies += sleep_length;
wall_jiffies += sleep_length;
+ if (last_timer->resume)
+ last_timer->resume();
+ cur_timer = last_timer;
+ last_timer = NULL;
+ touch_softlockup_watchdog();
return 0;
}
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index ef8dac5dd33b..d973a8b681fd 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -18,8 +18,8 @@
#include "mach_timer.h"
#include <asm/hpet.h>
-static unsigned long __read_mostly hpet_usec_quotient; /* convert hpet clks to usec */
-static unsigned long tsc_hpet_quotient; /* convert tsc to hpet clks */
+static unsigned long hpet_usec_quotient __read_mostly; /* convert hpet clks to usec */
+static unsigned long tsc_hpet_quotient __read_mostly; /* convert tsc to hpet clks */
static unsigned long hpet_last; /* hpet counter value at last tick*/
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */
@@ -136,6 +136,8 @@ static void delay_hpet(unsigned long loops)
} while ((hpet_end - hpet_start) < (loops));
}
+static struct timer_opts timer_hpet;
+
static int __init init_hpet(char* override)
{
unsigned long result, remain;
@@ -163,6 +165,8 @@ static int __init init_hpet(char* override)
}
set_cyc2ns_scale(cpu_khz/1000);
}
+ /* set this only when cpu_has_tsc */
+ timer_hpet.read_timer = read_timer_tsc;
}
/*
@@ -177,6 +181,19 @@ static int __init init_hpet(char* override)
return 0;
}
+static int hpet_resume(void)
+{
+ write_seqlock(&monotonic_lock);
+ /* Assume this is the last mark offset time */
+ rdtsc(last_tsc_low, last_tsc_high);
+
+ if (hpet_use_timer)
+ hpet_last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+ else
+ hpet_last = hpet_readl(HPET_COUNTER);
+ write_sequnlock(&monotonic_lock);
+ return 0;
+}
/************************************************************/
/* tsc timer_opts struct */
@@ -186,7 +203,7 @@ static struct timer_opts timer_hpet __read_mostly = {
.get_offset = get_offset_hpet,
.monotonic_clock = monotonic_clock_hpet,
.delay = delay_hpet,
- .read_timer = read_timer_tsc,
+ .resume = hpet_resume,
};
struct init_timer_opts __initdata timer_hpet_init = {
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
index 06de036a820c..eddb64038234 100644
--- a/arch/i386/kernel/timers/timer_pit.c
+++ b/arch/i386/kernel/timers/timer_pit.c
@@ -175,30 +175,3 @@ void setup_pit_timer(void)
outb(LATCH >> 8 , PIT_CH0); /* MSB */
spin_unlock_irqrestore(&i8253_lock, flags);
}
-
-static int timer_resume(struct sys_device *dev)
-{
- setup_pit_timer();
- return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
- set_kset_name("timer_pit"),
- .resume = timer_resume,
-};
-
-static struct sys_device device_timer = {
- .id = 0,
- .cls = &timer_sysclass,
-};
-
-static int __init init_timer_sysfs(void)
-{
- int error = sysdev_class_register(&timer_sysclass);
- if (!error)
- error = sysdev_register(&device_timer);
- return error;
-}
-
-device_initcall(init_timer_sysfs);
-
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
index 4ef20e663498..264edaaac315 100644
--- a/arch/i386/kernel/timers/timer_pm.c
+++ b/arch/i386/kernel/timers/timer_pm.c
@@ -186,6 +186,14 @@ static void mark_offset_pmtmr(void)
}
}
+static int pmtmr_resume(void)
+{
+ write_seqlock(&monotonic_lock);
+ /* Assume this is the last mark offset time */
+ offset_tick = read_pmtmr();
+ write_sequnlock(&monotonic_lock);
+ return 0;
+}
static unsigned long long monotonic_clock_pmtmr(void)
{
@@ -247,6 +255,7 @@ static struct timer_opts timer_pmtmr = {
.monotonic_clock = monotonic_clock_pmtmr,
.delay = delay_pmtmr,
.read_timer = read_timer_tsc,
+ .resume = pmtmr_resume,
};
struct init_timer_opts __initdata timer_pmtmr_init = {
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 8f4e4d5bc560..6dd470cc9f72 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -543,6 +543,19 @@ static int __init init_tsc(char* override)
return -ENODEV;
}
+static int tsc_resume(void)
+{
+ write_seqlock(&monotonic_lock);
+ /* Assume this is the last mark offset time */
+ rdtsc(last_tsc_low, last_tsc_high);
+#ifdef CONFIG_HPET_TIMER
+ if (is_hpet_enabled() && hpet_use_timer)
+ hpet_last = hpet_readl(HPET_COUNTER);
+#endif
+ write_sequnlock(&monotonic_lock);
+ return 0;
+}
+
#ifndef CONFIG_X86_TSC
/* disable flag for tsc. Takes effect by clearing the TSC cpu flag
* in cpu/common.c */
@@ -573,6 +586,7 @@ static struct timer_opts timer_tsc = {
.monotonic_clock = monotonic_clock_tsc,
.delay = delay_tsc,
.read_timer = read_timer_tsc,
+ .resume = tsc_resume,
};
struct init_timer_opts __initdata timer_tsc_init = {
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index cd2d5d5514fe..09a58cb6daa7 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -210,7 +210,7 @@ void show_registers(struct pt_regs *regs)
unsigned short ss;
esp = (unsigned long) (&regs->esp);
- ss = __KERNEL_DS;
+ savesegment(ss, ss);
if (user_mode(regs)) {
in_kernel = 0;
esp = regs->esp;
@@ -267,9 +267,6 @@ static void handle_BUG(struct pt_regs *regs)
char c;
unsigned long eip;
- if (user_mode(regs))
- goto no_bug; /* Not in kernel */
-
eip = regs->eip;
if (eip < PAGE_OFFSET)
@@ -366,8 +363,9 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
die(str, regs, err);
}
-static void do_trap(int trapnr, int signr, char *str, int vm86,
- struct pt_regs * regs, long error_code, siginfo_t *info)
+static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+ struct pt_regs * regs, long error_code,
+ siginfo_t *info)
{
struct task_struct *tsk = current;
tsk->thread.error_code = error_code;
@@ -463,7 +461,8 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
-fastcall void do_general_protection(struct pt_regs * regs, long error_code)
+fastcall void __kprobes do_general_protection(struct pt_regs * regs,
+ long error_code)
{
int cpu = get_cpu();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
@@ -568,6 +567,10 @@ static DEFINE_SPINLOCK(nmi_print_lock);
void die_nmi (struct pt_regs *regs, const char *msg)
{
+ if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 0, SIGINT) ==
+ NOTIFY_STOP)
+ return;
+
spin_lock(&nmi_print_lock);
/*
* We are in trouble anyway, lets at least try
@@ -656,7 +659,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
++nmi_count(cpu);
- if (!nmi_callback(regs, cpu))
+ if (!rcu_dereference(nmi_callback)(regs, cpu))
default_do_nmi(regs);
nmi_exit();
@@ -664,7 +667,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
void set_nmi_callback(nmi_callback_t callback)
{
- nmi_callback = callback;
+ rcu_assign_pointer(nmi_callback, callback);
}
EXPORT_SYMBOL_GPL(set_nmi_callback);
@@ -675,7 +678,7 @@ void unset_nmi_callback(void)
EXPORT_SYMBOL_GPL(unset_nmi_callback);
#ifdef CONFIG_KPROBES
-fastcall void do_int3(struct pt_regs *regs, long error_code)
+fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_STOP)
@@ -709,7 +712,7 @@ fastcall void do_int3(struct pt_regs *regs, long error_code)
* find every occurrence of the TF bit that could be saved away even
* by user code)
*/
-fastcall void do_debug(struct pt_regs * regs, long error_code)
+fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
{
unsigned int condition;
struct task_struct *tsk = current;
@@ -1008,7 +1011,7 @@ void __init trap_init_f00f_bug(void)
* it uses the read-only mapped virtual address.
*/
idt_descr.address = fix_to_virt(FIX_F00F_IDT);
- __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ load_idt(&idt_descr);
}
#endif
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index ec0f68ce6886..16b485009622 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -294,8 +294,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
*/
info->regs32->eax = 0;
tsk->thread.saved_esp0 = tsk->thread.esp0;
- asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
- asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
+ savesegment(fs, tsk->thread.saved_fs);
+ savesegment(gs, tsk->thread.saved_gs);
tss = &per_cpu(init_tss, get_cpu());
tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -542,7 +542,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
unsigned char opcode;
unsigned char __user *csp;
unsigned char __user *ssp;
- unsigned short ip, sp;
+ unsigned short ip, sp, orig_flags;
int data32, pref_done;
#define CHECK_IF_IN_TRAP \
@@ -551,8 +551,12 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
#define VM86_FAULT_RETURN do { \
if (VMPI.force_return_for_pic && (VEFLAGS & (IF_MASK | VIF_MASK))) \
return_to_32bit(regs, VM86_PICRETURN); \
+ if (orig_flags & TF_MASK) \
+ handle_vm86_trap(regs, 0, 1); \
return; } while (0)
+ orig_flags = *(unsigned short *)&regs->eflags;
+
csp = (unsigned char __user *) (regs->cs << 4);
ssp = (unsigned char __user *) (regs->ss << 4);
sp = SP(regs);
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 761972f8cb6c..4710195b6b74 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -22,6 +22,7 @@ SECTIONS
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
} = 0x9090
@@ -143,12 +144,7 @@ SECTIONS
*(.exitcall.exit)
}
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
+ STABS_DEBUG
+
+ DWARF_DEBUG
}
diff --git a/arch/i386/kernel/vsyscall-sigreturn.S b/arch/i386/kernel/vsyscall-sigreturn.S
index c8fcf75b9be3..fadb5bc3c374 100644
--- a/arch/i386/kernel/vsyscall-sigreturn.S
+++ b/arch/i386/kernel/vsyscall-sigreturn.S
@@ -7,7 +7,7 @@
*/
#include <asm/unistd.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
/* XXX
@@ -15,7 +15,7 @@
*/
.text
- .org __kernel_vsyscall+32
+ .org __kernel_vsyscall+32,0x90
.globl __kernel_sigreturn
.type __kernel_sigreturn,@function
__kernel_sigreturn:
@@ -35,6 +35,7 @@ __kernel_rt_sigreturn:
int $0x80
.LEND_rt_sigreturn:
.size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+ .balign 32
.previous
.section .eh_frame,"a",@progbits
diff --git a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
index a7977707c8e5..98699ca6e52d 100644
--- a/arch/i386/kernel/vsyscall.lds.S
+++ b/arch/i386/kernel/vsyscall.lds.S
@@ -3,7 +3,7 @@
* object prelinked to its virtual address, and with only one read-only
* segment (that fits in one page). This script controls its layout.
*/
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
SECTIONS
{
diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c
index 23395fff35d1..b64314069e78 100644
--- a/arch/i386/mach-default/topology.c
+++ b/arch/i386/mach-default/topology.c
@@ -76,7 +76,7 @@ static int __init topology_init(void)
for_each_online_node(i)
arch_register_node(i);
- for_each_cpu(i)
+ for_each_present_cpu(i)
arch_register_cpu(i);
return 0;
}
@@ -87,7 +87,7 @@ static int __init topology_init(void)
{
int i;
- for_each_cpu(i)
+ for_each_present_cpu(i)
arch_register_cpu(i);
return 0;
}
diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h
index 70691f0c4ce2..898ed905e119 100644
--- a/arch/i386/mach-es7000/es7000.h
+++ b/arch/i386/mach-es7000/es7000.h
@@ -104,7 +104,8 @@ struct mip_reg {
#define MIP_SW_APIC 0x1020b
#define MIP_FUNC(VALUE) (VALUE & 0xff)
-extern int parse_unisys_oem (char *oemptr, int oem_entries);
-extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
+extern int parse_unisys_oem (char *oemptr);
+extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+extern void setup_unisys ();
extern int es7000_start_cpu(int cpu, unsigned long eip);
extern void es7000_sw_apic(void);
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index d5936d500479..dc6660511b07 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -51,7 +51,7 @@ struct mip_reg *host_reg;
int mip_port;
unsigned long mip_addr, host_addr;
-#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI)
/*
* GSI override for ES7000 platforms.
@@ -73,14 +73,31 @@ es7000_rename_gsi(int ioapic, int gsi)
return gsi;
}
-#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)
+#endif /* (CONFIG_X86_IO_APIC) && (CONFIG_ACPI) */
+
+void __init
+setup_unisys ()
+{
+ /*
+ * Determine the generation of the ES7000 currently running.
+ *
+ * es7000_plat = 1 if the machine is a 5xx ES7000 box
+ * es7000_plat = 2 if the machine is a x86_64 ES7000 box
+ *
+ */
+ if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
+ es7000_plat = 2;
+ else
+ es7000_plat = 1;
+ ioapic_renumber_irq = es7000_rename_gsi;
+}
/*
* Parse the OEM Table
*/
int __init
-parse_unisys_oem (char *oemptr, int oem_entries)
+parse_unisys_oem (char *oemptr)
{
int i;
int success = 0;
@@ -95,7 +112,7 @@ parse_unisys_oem (char *oemptr, int oem_entries)
tp += 8;
- for (i=0; i <= oem_entries; i++) {
+ for (i=0; i <= 6; i++) {
type = *tp++;
size = *tp++;
tp -= 2;
@@ -130,34 +147,18 @@ parse_unisys_oem (char *oemptr, int oem_entries)
default:
break;
}
- if (i == 6) break;
tp += size;
}
if (success < 2) {
es7000_plat = 0;
- } else {
- printk("\nEnabling ES7000 specific features...\n");
- /*
- * Determine the generation of the ES7000 currently running.
- *
- * es7000_plat = 0 if the machine is NOT a Unisys ES7000 box
- * es7000_plat = 1 if the machine is a 5xx ES7000 box
- * es7000_plat = 2 if the machine is a x86_64 ES7000 box
- *
- */
- if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
- es7000_plat = 2;
- else
- es7000_plat = 1;
-
- ioapic_renumber_irq = es7000_rename_gsi;
- }
+ } else
+ setup_unisys();
return es7000_plat;
}
int __init
-find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
+find_unisys_acpi_oem_table(unsigned long *oem_addr)
{
struct acpi_table_rsdp *rsdp = NULL;
unsigned long rsdp_phys = 0;
@@ -201,13 +202,11 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
acpi_table_print(header, sdt.entry[i].pa);
t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length);
addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize);
- *length = header->length;
*oem_addr = (unsigned long) addr;
return 0;
}
}
}
- Dprintk("ES7000: did not find Unisys ACPI OEM table!\n");
return -1;
}
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index 25883b44f625..037b2af1a1f4 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -47,7 +47,10 @@ static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
static __init int probe_bigsmp(void)
{
- dmi_check_system(bigsmp_dmi_table);
+ if (def_to_bigsmp)
+ dmi_bigsmp = 1;
+ else
+ dmi_check_system(bigsmp_dmi_table);
return dmi_bigsmp;
}
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c
index 5497c65a8790..cea5b3ce4b57 100644
--- a/arch/i386/mach-generic/probe.c
+++ b/arch/i386/mach-generic/probe.c
@@ -30,6 +30,25 @@ struct genapic *apic_probe[] __initdata = {
NULL,
};
+static int cmdline_apic;
+
+void __init generic_bigsmp_probe(void)
+{
+ /*
+ * This routine is used to switch to bigsmp mode when
+ * - There is no apic= option specified by the user
+ * - generic_apic_probe() has choosen apic_default as the sub_arch
+ * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
+ */
+
+ if (!cmdline_apic && genapic == &apic_default)
+ if (apic_bigsmp.probe()) {
+ genapic = &apic_bigsmp;
+ printk(KERN_INFO "Overriding APIC driver with %s\n",
+ genapic->name);
+ }
+}
+
void __init generic_apic_probe(char *command_line)
{
char *s;
@@ -52,6 +71,7 @@ void __init generic_apic_probe(char *command_line)
if (!changed)
printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
*p = old;
+ cmdline_apic = changed;
}
for (i = 0; !changed && apic_probe[i]; i++) {
if (apic_probe[i]->probe()) {
diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
index c6384061328a..cc69875d979b 100644
--- a/arch/i386/mach-voyager/voyager_basic.c
+++ b/arch/i386/mach-voyager/voyager_basic.c
@@ -234,10 +234,9 @@ voyager_power_off(void)
#endif
}
/* and wait for it to happen */
- for(;;) {
- __asm("cli");
- __asm("hlt");
- }
+ local_irq_disable();
+ for(;;)
+ halt();
}
/* copied from process.c */
@@ -278,10 +277,9 @@ machine_restart(char *cmd)
outb(basebd | 0x08, VOYAGER_MC_SETUP);
outb(0x02, catbase + 0x21);
}
- for(;;) {
- asm("cli");
- asm("hlt");
- }
+ local_irq_disable();
+ for(;;)
+ halt();
}
void
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 0e1f4208b07c..46b0cf4a31e0 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -242,6 +242,8 @@ static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
cpumask_t cpu_callin_map = CPU_MASK_NONE;
cpumask_t cpu_callout_map = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_callout_map);
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_possible_map);
/* The per processor IRQ masks (these are usually kept in sync) */
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
@@ -1015,7 +1017,7 @@ smp_stop_cpu_function(void *dummy)
cpu_clear(smp_processor_id(), cpu_online_map);
local_irq_disable();
for(;;)
- __asm__("hlt");
+ halt();
}
static DEFINE_SPINLOCK(call_lock);
@@ -1910,6 +1912,7 @@ void __devinit smp_prepare_boot_cpu(void)
{
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callout_map);
+ cpu_set(smp_processor_id(), cpu_possible_map);
}
int __devinit
diff --git a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c
index 91175738e948..9819b705efa4 100644
--- a/arch/i386/math-emu/get_address.c
+++ b/arch/i386/math-emu/get_address.c
@@ -155,7 +155,6 @@ static long pm_address(u_char FPU_modrm, u_char segment,
{
struct desc_struct descriptor;
unsigned long base_address, limit, address, seg_top;
- unsigned short selector;
segment--;
@@ -173,17 +172,11 @@ static long pm_address(u_char FPU_modrm, u_char segment,
/* fs and gs aren't used by the kernel, so they still have their
user-space values. */
case PREFIX_FS_-1:
- /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
- in the assembler statement. */
-
- __asm__("mov %%fs,%0":"=r" (selector));
- addr->selector = selector;
+ /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
+ savesegment(fs, addr->selector);
break;
case PREFIX_GS_-1:
- /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
- in the assembler statement. */
- __asm__("mov %%gs,%0":"=r" (selector));
- addr->selector = selector;
+ savesegment(gs, addr->selector);
break;
default:
addr->selector = PM_REG_(segment);
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 6711ce3f6916..244d8ec66be2 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -37,7 +37,7 @@
#include <asm/mmzone.h>
#include <bios_ebda.h>
-struct pglist_data *node_data[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL(node_data);
bootmem_data_t node0_bdata;
@@ -49,8 +49,8 @@ bootmem_data_t node0_bdata;
* 2) node_start_pfn - the starting page frame number for a node
* 3) node_end_pfn - the ending page fram number for a node
*/
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
+unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
#ifdef CONFIG_DISCONTIGMEM
@@ -66,7 +66,7 @@ unsigned long node_end_pfn[MAX_NUMNODES];
* physnode_map[4-7] = 1;
* physnode_map[8- ] = -1;
*/
-s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
EXPORT_SYMBOL(physnode_map);
void memory_present(int nid, unsigned long start, unsigned long end)
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 8e90339d6eaa..9edd4485b91e 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -21,6 +21,7 @@
#include <linux/vt_kern.h> /* For unblank_screen() */
#include <linux/highmem.h>
#include <linux/module.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -199,6 +200,18 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
return 0;
}
+static noinline void force_sig_info_fault(int si_signo, int si_code,
+ unsigned long address, struct task_struct *tsk)
+{
+ siginfo_t info;
+
+ info.si_signo = si_signo;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void __user *)address;
+ force_sig_info(si_signo, &info, tsk);
+}
+
fastcall void do_invalid_op(struct pt_regs *, unsigned long);
/*
@@ -211,18 +224,18 @@ fastcall void do_invalid_op(struct pt_regs *, unsigned long);
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
*/
-fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+fastcall void __kprobes do_page_fault(struct pt_regs *regs,
+ unsigned long error_code)
{
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
unsigned long address;
unsigned long page;
- int write;
- siginfo_t info;
+ int write, si_code;
/* get the address */
- __asm__("movl %%cr2,%0":"=r" (address));
+ address = read_cr2();
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
SIGSEGV) == NOTIFY_STOP)
@@ -233,7 +246,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
tsk = current;
- info.si_code = SEGV_MAPERR;
+ si_code = SEGV_MAPERR;
/*
* We fault-in kernel-space virtual memory on-demand. The
@@ -313,7 +326,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* we can handle it..
*/
good_area:
- info.si_code = SEGV_ACCERR;
+ si_code = SEGV_ACCERR;
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
@@ -387,11 +400,7 @@ bad_area_nosemaphore:
/* Kernel addresses are always protection faults */
tsk->thread.error_code = error_code | (address >= TASK_SIZE);
tsk->thread.trap_no = 14;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- /* info.si_code has been set above */
- info.si_addr = (void __user *)address;
- force_sig_info(SIGSEGV, &info, tsk);
+ force_sig_info_fault(SIGSEGV, si_code, address, tsk);
return;
}
@@ -446,7 +455,7 @@ no_context:
printk(" at virtual address %08lx\n",address);
printk(KERN_ALERT " printing eip:\n");
printk("%08lx\n", regs->eip);
- asm("movl %%cr3,%0":"=r" (page));
+ page = read_cr3();
page = ((unsigned long *) __va(page))[address >> 22];
printk(KERN_ALERT "*pde = %08lx\n", page);
/*
@@ -500,11 +509,7 @@ do_sigbus:
tsk->thread.cr2 = address;
tsk->thread.error_code = error_code;
tsk->thread.trap_no = 14;
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRERR;
- info.si_addr = (void __user *)address;
- force_sig_info(SIGBUS, &info, tsk);
+ force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
return;
vmalloc_fault:
@@ -523,7 +528,7 @@ vmalloc_fault:
pmd_t *pmd, *pmd_k;
pte_t *pte_k;
- asm("movl %%cr3,%0":"=r" (pgd_paddr));
+ pgd_paddr = read_cr3();
pgd = index + (pgd_t *)__va(pgd_paddr);
pgd_k = init_mm.pgd + index;
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 3b099f32b948..d524127c9afc 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -22,12 +22,15 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
- pmd_t *pmd = NULL;
+ pte_t *pte = NULL;
pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
- pmd = pmd_alloc(mm, pud, addr);
- return (pte_t *) pmd;
+ if (pud)
+ pte = (pte_t *) pmd_alloc(mm, pud, addr);
+ BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
+
+ return pte;
}
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
@@ -37,8 +40,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
pmd_t *pmd = NULL;
pgd = pgd_offset(mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
+ if (pgd_present(*pgd)) {
+ pud = pud_offset(pgd, addr);
+ if (pud_present(*pud))
+ pmd = pmd_offset(pud, addr);
+ }
return (pte_t *) pmd;
}
@@ -118,17 +124,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
}
#endif
-void hugetlb_clean_stale_pgtable(pte_t *pte)
-{
- pmd_t *pmd = (pmd_t *) pte;
- struct page *page;
-
- page = pmd_page(*pmd);
- pmd_clear(pmd);
- dec_page_state(nr_page_table_pages);
- page_cache_release(page);
-}
-
/* x86_64 also uses this file */
#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 12216b52e28b..2ebaf75f732e 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -198,9 +198,10 @@ int page_is_ram(unsigned long pagenr)
if (efi_enabled) {
efi_memory_desc_t *md;
+ void *p;
- for (i = 0; i < memmap.nr_map; i++) {
- md = &memmap.map[i];
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
if (!is_available_memory(md))
continue;
addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
@@ -348,7 +349,7 @@ static void __init pagetable_init (void)
* All user-space mappings are explicitly cleared after
* SMP startup.
*/
- pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
+ set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
#endif
}
@@ -392,7 +393,7 @@ void zap_low_mappings (void)
}
static int disable_nx __initdata = 0;
-u64 __supported_pte_mask = ~_PAGE_NX;
+u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
/*
* noexec = on|off
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index cb3da6baa704..f600fc244f02 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -12,6 +12,7 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
static DEFINE_SPINLOCK(cpa_lock);
static struct list_head df_list = LIST_HEAD_INIT(df_list);
@@ -52,8 +53,8 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot)
addr = address & LARGE_PAGE_MASK;
pbase = (pte_t *)page_address(base);
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
- pbase[i] = pfn_pte(addr >> PAGE_SHIFT,
- addr == address ? prot : PAGE_KERNEL);
+ set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
+ addr == address ? prot : PAGE_KERNEL));
}
return base;
}
@@ -62,7 +63,7 @@ static void flush_kernel_map(void *dummy)
{
/* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
if (boot_cpu_data.x86_model >= 4)
- asm volatile("wbinvd":::"memory");
+ wbinvd();
/* Flush all to work around Errata in early athlons regarding
* large page flushing.
*/
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index bd2f7afc7a2a..dcdce2c6c532 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -207,19 +207,19 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
{
unsigned long flags;
- if (PTRS_PER_PMD == 1)
+ if (PTRS_PER_PMD == 1) {
+ memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
spin_lock_irqsave(&pgd_lock, flags);
+ }
- memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+ clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
swapper_pg_dir + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-
+ KERNEL_PGD_PTRS);
if (PTRS_PER_PMD > 1)
return;
pgd_list_add(pgd);
spin_unlock_irqrestore(&pgd_lock, flags);
- memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
}
/* never called when PTRS_PER_PMD > 1 */
diff --git a/arch/i386/oprofile/init.c b/arch/i386/oprofile/init.c
index c90332de582b..5341d481d92f 100644
--- a/arch/i386/oprofile/init.c
+++ b/arch/i386/oprofile/init.c
@@ -15,9 +15,9 @@
* with the NMI mode driver.
*/
-extern int nmi_init(struct oprofile_operations * ops);
-extern int nmi_timer_init(struct oprofile_operations * ops);
-extern void nmi_exit(void);
+extern int op_nmi_init(struct oprofile_operations * ops);
+extern int op_nmi_timer_init(struct oprofile_operations * ops);
+extern void op_nmi_exit(void);
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
@@ -28,11 +28,11 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
ret = -ENODEV;
#ifdef CONFIG_X86_LOCAL_APIC
- ret = nmi_init(ops);
+ ret = op_nmi_init(ops);
#endif
#ifdef CONFIG_X86_IO_APIC
if (ret < 0)
- ret = nmi_timer_init(ops);
+ ret = op_nmi_timer_init(ops);
#endif
ops->backtrace = x86_backtrace;
@@ -43,6 +43,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
void oprofile_arch_exit(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
- nmi_exit();
+ op_nmi_exit();
#endif
}
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 255e4702d185..0493e8b8ec49 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -355,7 +355,7 @@ static int __init ppro_init(char ** cpu_type)
/* in order to get driverfs right */
static int using_nmi;
-int __init nmi_init(struct oprofile_operations *ops)
+int __init op_nmi_init(struct oprofile_operations *ops)
{
__u8 vendor = boot_cpu_data.x86_vendor;
__u8 family = boot_cpu_data.x86;
@@ -420,7 +420,7 @@ int __init nmi_init(struct oprofile_operations *ops)
}
-void nmi_exit(void)
+void op_nmi_exit(void)
{
if (using_nmi)
exit_driverfs();
diff --git a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c
index c58d0c14f274..ad93cdd55d63 100644
--- a/arch/i386/oprofile/nmi_timer_int.c
+++ b/arch/i386/oprofile/nmi_timer_int.c
@@ -40,7 +40,7 @@ static void timer_stop(void)
}
-int __init nmi_timer_init(struct oprofile_operations * ops)
+int __init op_nmi_timer_init(struct oprofile_operations * ops)
{
extern int nmi_active;
diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile
index 1bff03f36965..ead6122dd06d 100644
--- a/arch/i386/pci/Makefile
+++ b/arch/i386/pci/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
obj-$(CONFIG_PCI_DIRECT) += direct.o
pci-y := fixup.o
-pci-$(CONFIG_ACPI_PCI) += acpi.o
+pci-$(CONFIG_ACPI) += acpi.o
pci-y += legacy.o irq.o
pci-$(CONFIG_X86_VISWS) := visws.o fixup.o
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
index 42913f43feb0..2941674f35eb 100644
--- a/arch/i386/pci/acpi.c
+++ b/arch/i386/pci/acpi.c
@@ -3,16 +3,31 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/hw_irq.h>
+#include <asm/numa.h>
#include "pci.h"
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
{
+ struct pci_bus *bus;
+
if (domain != 0) {
printk(KERN_WARNING "PCI: Multiple domains not supported\n");
return NULL;
}
- return pcibios_scan_root(busnum);
+ bus = pcibios_scan_root(busnum);
+#ifdef CONFIG_ACPI_NUMA
+ if (bus != NULL) {
+ int pxm = acpi_get_pxm(device->handle);
+ if (pxm >= 0) {
+ bus->sysdata = (void *)(unsigned long)pxm_to_node(pxm);
+ printk("bus %d -> pxm %d -> node %ld\n",
+ busnum, pxm, (long)(bus->sysdata));
+ }
+ }
+#endif
+
+ return bus;
}
extern int pci_routeirq;
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index ade5bc57c34c..c96bea14b98f 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -165,7 +165,6 @@ static int __init pcibios_init(void)
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
pcibios_sort();
#endif
- pci_assign_unassigned_resources();
return 0;
}
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index 93a364c82150..6d6338500c3c 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -170,43 +170,26 @@ static void __init pcibios_allocate_resources(int pass)
static int __init pcibios_assign_resources(void)
{
struct pci_dev *dev = NULL;
- int idx;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- int class = dev->class >> 8;
-
- /* Don't touch classless devices and host bridges */
- if (!class || class == PCI_CLASS_BRIDGE_HOST)
- continue;
-
- for(idx=0; idx<6; idx++) {
- r = &dev->resource[idx];
-
- /*
- * Don't touch IDE controllers and I/O ports of video cards!
- */
- if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
- (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
- continue;
-
- /*
- * We shall assign a new address to this resource, either because
- * the BIOS forgot to do so or because we have decided the old
- * address was unusable for some reason.
- */
- if (!r->start && r->end)
- pci_assign_resource(dev, idx);
- }
+ struct resource *r, *pr;
- if (pci_probe & PCI_ASSIGN_ROMS) {
+ if (!(pci_probe & PCI_ASSIGN_ROMS)) {
+ /* Try to use BIOS settings for ROMs, otherwise let
+ pci_assign_unassigned_resources() allocate the new
+ addresses. */
+ for_each_pci_dev(dev) {
r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
+ if (!r->flags || !r->start)
+ continue;
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ r->end -= r->start;
+ r->start = 0;
+ }
}
}
+
+ pci_assign_unassigned_resources();
+
return 0;
}
@@ -300,9 +283,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
/* Write-combine setting is ignored, it is changed via the mtrr
* interfaces on this platform.
*/
- if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
return -EAGAIN;
return 0;
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 86348b68fda1..326a2edc3834 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -1075,7 +1075,7 @@ static void pirq_penalize_isa_irq(int irq, int active)
void pcibios_penalize_isa_irq(int irq, int active)
{
-#ifdef CONFIG_ACPI_PCI
+#ifdef CONFIG_ACPI
if (!acpi_noirq)
acpi_penalize_isa_irq(irq, active);
else
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 60f0e7a1162a..dfbf80cff834 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -127,13 +127,6 @@ static int __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
goto out;
- /* Kludge for now. Don't use mmconfig on AMD systems because
- those have some busses where mmconfig doesn't work,
- and we don't parse ACPI MCFG well enough to handle that.
- Remove when proper handling is added. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
- goto out;
-
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 c547c1af6fa1..7b0b9ad848e5 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -42,25 +42,25 @@ void __save_processor_state(struct saved_context *ctxt)
/*
* descriptor tables
*/
- asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
- asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
- asm volatile ("str %0" : "=m" (ctxt->tr));
+ store_gdt(&ctxt->gdt_limit);
+ store_idt(&ctxt->idt_limit);
+ store_tr(ctxt->tr);
/*
* segment registers
*/
- asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
- asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
- asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
- asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
+ savesegment(es, ctxt->es);
+ savesegment(fs, ctxt->fs);
+ savesegment(gs, ctxt->gs);
+ savesegment(ss, ctxt->ss);
/*
* control registers
*/
- asm volatile ("movl %%cr0, %0" : "=r" (ctxt->cr0));
- asm volatile ("movl %%cr2, %0" : "=r" (ctxt->cr2));
- asm volatile ("movl %%cr3, %0" : "=r" (ctxt->cr3));
- asm volatile ("movl %%cr4, %0" : "=r" (ctxt->cr4));
+ ctxt->cr0 = read_cr0();
+ ctxt->cr2 = read_cr2();
+ ctxt->cr3 = read_cr3();
+ ctxt->cr4 = read_cr4();
}
void save_processor_state(void)
@@ -84,7 +84,6 @@ static void fix_processor_context(void)
struct tss_struct * t = &per_cpu(init_tss, cpu);
set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
- per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
load_TR_desc(); /* This does ltr */
load_LDT(&current->active_mm->context); /* This does lldt */
@@ -109,25 +108,25 @@ void __restore_processor_state(struct saved_context *ctxt)
/*
* control registers
*/
- asm volatile ("movl %0, %%cr4" :: "r" (ctxt->cr4));
- asm volatile ("movl %0, %%cr3" :: "r" (ctxt->cr3));
- asm volatile ("movl %0, %%cr2" :: "r" (ctxt->cr2));
- asm volatile ("movl %0, %%cr0" :: "r" (ctxt->cr0));
+ write_cr4(ctxt->cr4);
+ write_cr3(ctxt->cr3);
+ write_cr2(ctxt->cr2);
+ write_cr2(ctxt->cr0);
/*
* now restore the descriptor tables to their proper values
* ltr is done i fix_processor_context().
*/
- asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
- asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+ load_gdt(&ctxt->gdt_limit);
+ load_idt(&ctxt->idt_limit);
/*
* segment registers
*/
- asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
- asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
- asm volatile ("movw %0, %%gs" :: "r" (ctxt->gs));
- asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
+ loadsegment(es, ctxt->es);
+ loadsegment(fs, ctxt->fs);
+ loadsegment(gs, ctxt->gs);
+ loadsegment(ss, ctxt->ss);
/*
* sysenter MSRs
diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
index c4105286ff26..c893b897217f 100644
--- a/arch/i386/power/swsusp.S
+++ b/arch/i386/power/swsusp.S
@@ -12,7 +12,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 80988136f26d..ed25d66c8d50 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -60,6 +60,7 @@ choice
config IA64_GENERIC
bool "generic"
+ select ACPI
select NUMA
select ACPI_NUMA
select VIRTUAL_MEM_MAP
@@ -338,11 +339,6 @@ config IA64_PALINFO
To use this option, you have to ensure that the "/proc file system
support" (CONFIG_PROC_FS) is enabled, too.
-config ACPI_DEALLOCATE_IRQ
- bool
- depends on IOSAPIC && EXPERIMENTAL
- default y
-
source "drivers/firmware/Kconfig"
source "fs/Kconfig.binfmt"
@@ -351,36 +347,14 @@ endmenu
menu "Power management and ACPI"
-config PM
- bool "Power Management support"
- depends on !IA64_HP_SIM
- default y
- help
- "Power Management" means that parts of your computer are shut
- off or put into a power conserving "sleep" mode if they are not
- being used. There are two competing standards for doing this: APM
- and ACPI. If you want to use either one, say Y here and then also
- to the requisite support below.
-
- Power Management is most important for battery powered laptop
- computers; if you have a laptop, check out the Linux Laptop home
- page on the WWW at <http://www.linux-on-laptops.com/> and the
- Battery Powered Linux mini-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that, even if you say N here, Linux on the x86 architecture
- will issue the hlt instruction if nothing is to be done, thereby
- sending the processor to sleep and saving power.
-
-config ACPI
- bool
- depends on !IA64_HP_SIM
- default y
-
-if !IA64_HP_SIM
+source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"
+if PM
+
+source "arch/ia64/kernel/cpufreq/Kconfig"
+
endif
endmenu
@@ -428,6 +402,11 @@ config GENERIC_IRQ_PROBE
bool
default y
+config GENERIC_PENDING_IRQ
+ bool
+ depends on GENERIC_HARDIRQS && SMP
+ default y
+
source "arch/ia64/hp/sim/Kconfig"
source "arch/ia64/oprofile/Kconfig"
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index f9bd88ada708..70f8ed2748d1 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -82,25 +82,18 @@ unwcheck: vmlinux
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-CLEAN_FILES += include/asm-ia64/.offsets.h.stamp vmlinux.gz bootloader
-
-MRPROPER_FILES += include/asm-ia64/offsets.h
-
-prepare: include/asm-ia64/offsets.h
-
-arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h include/config/MARKER
-
-include/asm-ia64/offsets.h: arch/ia64/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-arch/ia64/kernel/asm-offsets.s: include/asm-ia64/.offsets.h.stamp
+archprepare: include/asm-ia64/.offsets.h.stamp
include/asm-ia64/.offsets.h.stamp:
mkdir -p include/asm-ia64
- [ -s include/asm-ia64/offsets.h ] \
- || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/offsets.h
+ [ -s include/asm-ia64/asm-offsets.h ] \
+ || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/asm-offsets.h
touch $@
+
+
+CLEAN_FILES += vmlinux.gz bootloader include/asm-ia64/.offsets.h.stamp
+
boot: lib/lib.a vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index b95fcf86ea00..3b65cbb31b1d 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -107,18 +107,12 @@ CONFIG_ACPI=y
#
# ACPI (Advanced Configuration and Power Interface) Support
#
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_THERMAL=m
-CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
#
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index dccf35c60b94..08112ab38468 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -111,7 +111,6 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
-CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -130,19 +129,12 @@ CONFIG_ACPI=y
#
# ACPI (Advanced Configuration and Power Interface) Support
#
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
# CONFIG_ACPI_BUTTON is not set
-CONFIG_ACPI_VIDEO=m
-CONFIG_ACPI_HOTKEY=m
# CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_PROCESSOR is not set
CONFIG_ACPI_NUMA=y
-CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_CONTAINER is not set
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index c853cfcd2d11..d452e18ac494 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -109,7 +109,6 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
-CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -128,20 +127,13 @@ CONFIG_ACPI=y
#
# ACPI (Advanced Configuration and Power Interface) Support
#
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_BUTTON=m
-# CONFIG_ACPI_VIDEO is not set
-# CONFIG_ACPI_HOTKEY is not set
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
# CONFIG_ACPI_HOTPLUG_CPU is not set
CONFIG_ACPI_THERMAL=m
-CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_CONTAINER is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 88e8867fa8e8..80b0e9eb7fb3 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -109,7 +109,6 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
-CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -128,19 +127,12 @@ CONFIG_ACPI=y
#
# ACPI (Advanced Configuration and Power Interface) Support
#
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_VIDEO=m
-CONFIG_ACPI_HOTKEY=m
CONFIG_ACPI_FAN=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
-CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_CONTAINER is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 8444add76380..5da208115ea1 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -99,7 +99,6 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
-CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -118,20 +117,14 @@ CONFIG_ACPI=y
#
# ACPI (Advanced Configuration and Power Interface) Support
#
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
-CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
CONFIG_ACPI_CONTAINER=m
@@ -341,7 +334,7 @@ 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=y
+# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_QLOGIC_1280_1040 is not set
diff --git a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S
index 1c8c7e6a9a5e..a9bd71ac78e2 100644
--- a/arch/ia64/hp/sim/boot/boot_head.S
+++ b/arch/ia64/hp/sim/boot/boot_head.S
@@ -4,6 +4,7 @@
*/
#include <asm/asmmacro.h>
+#include <asm/pal.h>
.bss
.align 16
@@ -49,7 +50,11 @@ GLOBAL_ENTRY(jmp_to_kernel)
br.sptk.few b7
END(jmp_to_kernel)
-
+/*
+ * r28 contains the index of the PAL function
+ * r29--31 the args
+ * Return values in ret0--3 (r8--11)
+ */
GLOBAL_ENTRY(pal_emulator_static)
mov r8=-1
mov r9=256
@@ -62,7 +67,7 @@ GLOBAL_ENTRY(pal_emulator_static)
cmp.gtu p6,p7=r9,r28
(p6) br.cond.sptk.few stacked
;;
-static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
+static: cmp.eq p6,p7=PAL_PTCE_INFO,r28
(p7) br.cond.sptk.few 1f
;;
mov r8=0 /* status = 0 */
@@ -70,21 +75,21 @@ static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
movl r10=0x0000000200000003 /* count[0], count[1] */
movl r11=0x1000000000002000 /* stride[0], stride[1] */
br.cond.sptk.few rp
-1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */
+1: cmp.eq p6,p7=PAL_FREQ_RATIOS,r28
(p7) br.cond.sptk.few 1f
mov r8=0 /* status = 0 */
movl r9 =0x100000064 /* proc_ratio (1/100) */
movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
movl r11=0x100000064 /* itc_ratio<<32 (1/100) */
;;
-1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
+1: cmp.eq p6,p7=PAL_RSE_INFO,r28
(p7) br.cond.sptk.few 1f
mov r8=0 /* status = 0 */
mov r9=96 /* num phys stacked */
mov r10=0 /* hints */
mov r11=0
br.cond.sptk.few rp
-1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */
+1: cmp.eq p6,p7=PAL_CACHE_FLUSH,r28 /* PAL_CACHE_FLUSH */
(p7) br.cond.sptk.few 1f
mov r9=ar.lc
movl r8=524288 /* flush 512k million cache lines (16MB) */
@@ -102,7 +107,7 @@ static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
mov ar.lc=r9
mov r8=r0
;;
-1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */
+1: cmp.eq p6,p7=PAL_PERF_MON_INFO,r28
(p7) br.cond.sptk.few 1f
mov r8=0 /* status = 0 */
movl r9 =0x08122f04 /* generic=4 width=47 retired=8 cycles=18 */
@@ -138,6 +143,20 @@ static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
st8 [r29]=r0,16 /* clear remaining bits */
st8 [r18]=r0,16 /* clear remaining bits */
;;
+1: cmp.eq p6,p7=PAL_VM_SUMMARY,r28
+(p7) br.cond.sptk.few 1f
+ mov r8=0 /* status = 0 */
+ movl r9=0x2044040020F1865 /* num_tc_levels=2, num_unique_tcs=4 */
+ /* max_itr_entry=64, max_dtr_entry=64 */
+ /* hash_tag_id=2, max_pkr=15 */
+ /* key_size=24, phys_add_size=50, vw=1 */
+ movl r10=0x183C /* rid_size=24, impl_va_msb=60 */
+ ;;
+1: cmp.eq p6,p7=PAL_MEM_ATTRIB,r28
+(p7) br.cond.sptk.few 1f
+ mov r8=0 /* status = 0 */
+ mov r9=0x80|0x01 /* NatPage|WB */
+ ;;
1: br.cond.sptk.few rp
stacked:
br.ret.sptk.few rp
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 5c46928e3dc6..30fdfb1d0a53 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -237,17 +237,6 @@ sal_emulator (long index, unsigned long in1, unsigned long in2,
return ((struct sal_ret_values) {status, r9, r10, r11});
}
-
-/*
- * This is here to work around a bug in egcs-1.1.1b that causes the
- * compiler to crash (seems like a bug in the new alias analysis code.
- */
-void *
-id (long addr)
-{
- return (void *) addr;
-}
-
struct ia64_boot_param *
sys_fw_init (const char *args, int arglen)
{
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 7dcb8582ae0d..b42ec37be51c 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -130,7 +130,7 @@ static void rs_stop(struct tty_struct *tty)
static void rs_start(struct tty_struct *tty)
{
-#if SIMSERIAL_DEBUG
+#ifdef SIMSERIAL_DEBUG
printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
tty->stopped, tty->hw_stopped, tty->flow_stopped);
#endif
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 829a6d80711c..494fad6bf376 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -1,6 +1,6 @@
#include <asm/asmmacro.h>
#include <asm/ia32.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/signal.h>
#include <asm/thread_info.h>
@@ -215,7 +215,7 @@ ia32_syscall_table:
data8 sys32_fork
data8 sys_read
data8 sys_write
- data8 sys32_open /* 5 */
+ data8 compat_sys_open /* 5 */
data8 sys_close
data8 sys32_waitpid
data8 sys_creat
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index ebb89be2aa2d..aa891c9bc9b6 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -29,7 +29,6 @@
#include <asm/uaccess.h>
#include <asm/rse.h>
#include <asm/sigcontext.h>
-#include <asm/segment.h>
#include "ia32priv.h"
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index c1e20d65dd6c..3fa67ecebc83 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2327,7 +2327,7 @@ sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count)
ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
set_fs(old_fs);
- if (!ret && offset && put_user(of, offset))
+ if (offset && put_user(of, offset))
return -EFAULT;
return ret;
@@ -2359,37 +2359,6 @@ sys32_brk (unsigned int brk)
return ret;
}
-/*
- * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
- */
-asmlinkage long
-sys32_open (const char __user * filename, int flags, int mode)
-{
- char * tmp;
- int fd, error;
-
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file *f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (IS_ERR(f))
- goto out_error;
- fd_install(fd, f);
- }
-out:
- putname(tmp);
- }
- return fd;
-
-out_error:
- put_unused_fd(fd);
- fd = error;
- goto out;
-}
-
/* Structure for ia32 emulation on ia64 */
struct epoll_event32
{
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index e1fb68ddec26..307514f7a282 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -16,10 +16,11 @@ obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
obj-$(CONFIG_IA64_PALINFO) += palinfo.o
obj-$(CONFIG_IOSAPIC) += iosapic.o
obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_SMP) += smp.o smpboot.o domain.o
+obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o
obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 2623df5e2633..13a5b3b49bf8 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -17,20 +17,20 @@
#include <asm/acpi-ext.h>
struct acpi_vendor_descriptor {
- u8 guid_id;
- efi_guid_t guid;
+ u8 guid_id;
+ efi_guid_t guid;
};
struct acpi_vendor_info {
- struct acpi_vendor_descriptor *descriptor;
- u8 *data;
- u32 length;
+ struct acpi_vendor_descriptor *descriptor;
+ u8 *data;
+ u32 length;
};
acpi_status
acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
{
- struct acpi_vendor_info *info = (struct acpi_vendor_info *) context;
+ struct acpi_vendor_info *info = (struct acpi_vendor_info *)context;
struct acpi_resource_vendor *vendor;
struct acpi_vendor_descriptor *descriptor;
u32 length;
@@ -38,8 +38,8 @@ acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
if (resource->id != ACPI_RSTYPE_VENDOR)
return AE_OK;
- vendor = (struct acpi_resource_vendor *) &resource->data;
- descriptor = (struct acpi_vendor_descriptor *) vendor->reserved;
+ vendor = (struct acpi_resource_vendor *)&resource->data;
+ descriptor = (struct acpi_vendor_descriptor *)vendor->reserved;
if (vendor->length <= sizeof(*info->descriptor) ||
descriptor->guid_id != info->descriptor->guid_id ||
efi_guidcmp(descriptor->guid, info->descriptor->guid))
@@ -50,21 +50,24 @@ acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
if (!info->data)
return AE_NO_MEMORY;
- memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length);
+ memcpy(info->data,
+ vendor->reserved + sizeof(struct acpi_vendor_descriptor),
+ length);
info->length = length;
return AE_CTRL_TERMINATE;
}
acpi_status
-acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
- u8 **data, u32 *length)
+acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id,
+ u8 ** data, u32 * length)
{
struct acpi_vendor_info info;
info.descriptor = id;
info.data = NULL;
- acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
+ acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match,
+ &info);
if (!info.data)
return AE_NOT_FOUND;
@@ -75,17 +78,19 @@ acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
struct acpi_vendor_descriptor hp_ccsr_descriptor = {
.guid_id = 2,
- .guid = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
+ .guid =
+ EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01,
+ 0x37, 0x0e, 0xad)
};
-acpi_status
-hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length)
{
acpi_status status;
u8 *data;
u32 length;
- status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
+ status =
+ acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
if (ACPI_FAILURE(status) || length != 16)
return AE_NOT_FOUND;
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 9609f243e5d0..28a4529fdd60 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -74,12 +74,11 @@ unsigned int acpi_cpei_override;
unsigned int acpi_cpei_phys_cpuid;
#define MAX_SAPICS 256
-u16 ia64_acpiid_to_sapicid[MAX_SAPICS] =
- { [0 ... MAX_SAPICS - 1] = -1 };
+u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = {[0 ... MAX_SAPICS - 1] = -1 };
+
EXPORT_SYMBOL(ia64_acpiid_to_sapicid);
-const char *
-acpi_get_sysname (void)
+const char *acpi_get_sysname(void)
{
#ifdef CONFIG_IA64_GENERIC
unsigned long rsdp_phys;
@@ -89,27 +88,29 @@ acpi_get_sysname (void)
rsdp_phys = acpi_find_rsdp();
if (!rsdp_phys) {
- printk(KERN_ERR "ACPI 2.0 RSDP not found, default to \"dig\"\n");
+ printk(KERN_ERR
+ "ACPI 2.0 RSDP not found, default to \"dig\"\n");
return "dig";
}
- rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys);
+ rsdp = (struct acpi20_table_rsdp *)__va(rsdp_phys);
if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) {
- printk(KERN_ERR "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
+ printk(KERN_ERR
+ "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
return "dig";
}
- xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address);
+ xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_address);
hdr = &xsdt->header;
if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) {
- printk(KERN_ERR "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
+ printk(KERN_ERR
+ "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
return "dig";
}
if (!strcmp(hdr->oem_id, "HP")) {
return "hpzx1";
- }
- else if (!strcmp(hdr->oem_id, "SGI")) {
+ } else if (!strcmp(hdr->oem_id, "SGI")) {
return "sn2";
}
@@ -131,7 +132,7 @@ acpi_get_sysname (void)
#endif
}
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
#define ACPI_MAX_PLATFORM_INTERRUPTS 256
@@ -146,8 +147,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
* Interrupt routing API for device drivers. Provides interrupt vector for
* a generic platform event. Currently only CPEI is implemented.
*/
-int
-acpi_request_vector (u32 int_type)
+int acpi_request_vector(u32 int_type)
{
int vector = -1;
@@ -155,12 +155,12 @@ acpi_request_vector (u32 int_type)
/* corrected platform error interrupt */
vector = platform_intr_list[int_type];
} else
- printk(KERN_ERR "acpi_request_vector(): invalid interrupt type\n");
+ printk(KERN_ERR
+ "acpi_request_vector(): invalid interrupt type\n");
return vector;
}
-char *
-__acpi_map_table (unsigned long phys_addr, unsigned long size)
+char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
{
return __va(phys_addr);
}
@@ -169,19 +169,18 @@ __acpi_map_table (unsigned long phys_addr, unsigned long size)
Boot-time Table Parsing
-------------------------------------------------------------------------- */
-static int total_cpus __initdata;
-static int available_cpus __initdata;
-struct acpi_table_madt * acpi_madt __initdata;
-static u8 has_8259;
-
+static int total_cpus __initdata;
+static int available_cpus __initdata;
+struct acpi_table_madt *acpi_madt __initdata;
+static u8 has_8259;
static int __init
-acpi_parse_lapic_addr_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_lapic_addr_ovr *lapic;
- lapic = (struct acpi_table_lapic_addr_ovr *) header;
+ lapic = (struct acpi_table_lapic_addr_ovr *)header;
if (BAD_MADT_ENTRY(lapic, end))
return -EINVAL;
@@ -193,22 +192,23 @@ acpi_parse_lapic_addr_ovr (
return 0;
}
-
static int __init
-acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lsapic(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_lsapic *lsapic;
- lsapic = (struct acpi_table_lsapic *) header;
+ lsapic = (struct acpi_table_lsapic *)header;
if (BAD_MADT_ENTRY(lsapic, end))
return -EINVAL;
if (lsapic->flags.enabled) {
#ifdef CONFIG_SMP
- smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid;
+ smp_boot_data.cpu_phys_id[available_cpus] =
+ (lsapic->id << 8) | lsapic->eid;
#endif
- ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid;
+ ia64_acpiid_to_sapicid[lsapic->acpi_id] =
+ (lsapic->id << 8) | lsapic->eid;
++available_cpus;
}
@@ -216,13 +216,12 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
return 0;
}
-
static int __init
-acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_lapic_nmi *lacpi_nmi;
- lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
+ lacpi_nmi = (struct acpi_table_lapic_nmi *)header;
if (BAD_MADT_ENTRY(lacpi_nmi, end))
return -EINVAL;
@@ -231,13 +230,12 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end)
return 0;
}
-
static int __init
-acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_iosapic *iosapic;
- iosapic = (struct acpi_table_iosapic *) header;
+ iosapic = (struct acpi_table_iosapic *)header;
if (BAD_MADT_ENTRY(iosapic, end))
return -EINVAL;
@@ -245,15 +243,14 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
return iosapic_init(iosapic->address, iosapic->global_irq_base);
}
-
static int __init
-acpi_parse_plat_int_src (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_plat_int_src(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_plat_int_src *plintsrc;
int vector;
- plintsrc = (struct acpi_table_plat_int_src *) header;
+ plintsrc = (struct acpi_table_plat_int_src *)header;
if (BAD_MADT_ENTRY(plintsrc, end))
return -EINVAL;
@@ -267,8 +264,12 @@ acpi_parse_plat_int_src (
plintsrc->iosapic_vector,
plintsrc->eid,
plintsrc->id,
- (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
- (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
+ (plintsrc->flags.polarity ==
+ 1) ? IOSAPIC_POL_HIGH :
+ IOSAPIC_POL_LOW,
+ (plintsrc->flags.trigger ==
+ 1) ? IOSAPIC_EDGE :
+ IOSAPIC_LEVEL);
platform_intr_list[plintsrc->type] = vector;
if (acpi_madt_rev > 1) {
@@ -283,7 +284,6 @@ acpi_parse_plat_int_src (
return 0;
}
-
unsigned int can_cpei_retarget(void)
{
extern int cpe_vector;
@@ -322,29 +322,30 @@ unsigned int get_cpei_target_cpu(void)
}
static int __init
-acpi_parse_int_src_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_int_src_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_int_src_ovr *p;
- p = (struct acpi_table_int_src_ovr *) header;
+ p = (struct acpi_table_int_src_ovr *)header;
if (BAD_MADT_ENTRY(p, end))
return -EINVAL;
iosapic_override_isa_irq(p->bus_irq, p->global_irq,
- (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
- (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
+ (p->flags.polarity ==
+ 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+ (p->flags.trigger ==
+ 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return 0;
}
-
static int __init
-acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_nmi_src *nmi_src;
- nmi_src = (struct acpi_table_nmi_src*) header;
+ nmi_src = (struct acpi_table_nmi_src *)header;
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
@@ -353,11 +354,9 @@ acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
return 0;
}
-static void __init
-acpi_madt_oem_check (char *oem_id, char *oem_table_id)
+static void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
- if (!strncmp(oem_id, "IBM", 3) &&
- (!strncmp(oem_table_id, "SERMOW", 6))) {
+ if (!strncmp(oem_id, "IBM", 3) && (!strncmp(oem_table_id, "SERMOW", 6))) {
/*
* Unfortunately ITC_DRIFT is not yet part of the
@@ -370,19 +369,18 @@ acpi_madt_oem_check (char *oem_id, char *oem_table_id)
}
}
-static int __init
-acpi_parse_madt (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
{
if (!phys_addr || !size)
return -EINVAL;
- acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
+ acpi_madt = (struct acpi_table_madt *)__va(phys_addr);
acpi_madt_rev = acpi_madt->header.revision;
/* remember the value for reference after free_initmem() */
#ifdef CONFIG_ITANIUM
- has_8259 = 1; /* Firmware on old Itanium systems is broken */
+ has_8259 = 1; /* Firmware on old Itanium systems is broken */
#else
has_8259 = acpi_madt->flags.pcat_compat;
#endif
@@ -396,19 +394,18 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
acpi_madt_oem_check(acpi_madt->header.oem_id,
- acpi_madt->header.oem_table_id);
+ acpi_madt->header.oem_table_id);
return 0;
}
-
#ifdef CONFIG_ACPI_NUMA
#undef SLIT_DEBUG
#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
-static int __initdata srat_num_cpus; /* number of cpus */
+static int __initdata srat_num_cpus; /* number of cpus */
static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
@@ -421,15 +418,15 @@ static struct acpi_table_slit __initdata *slit_table;
* ACPI 2.0 SLIT (System Locality Information Table)
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
*/
-void __init
-acpi_numa_slit_init (struct acpi_table_slit *slit)
+void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
{
u32 len;
len = sizeof(struct acpi_table_header) + 8
- + slit->localities * slit->localities;
+ + slit->localities * slit->localities;
if (slit->header.length != len) {
- printk(KERN_ERR "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
+ printk(KERN_ERR
+ "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
len, slit->header.length);
memset(numa_slit, 10, sizeof(numa_slit));
return;
@@ -438,19 +435,20 @@ acpi_numa_slit_init (struct acpi_table_slit *slit)
}
void __init
-acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa)
+acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
{
/* record this node in proximity bitmap */
pxm_bit_set(pa->proximity_domain);
- node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid);
+ node_cpuid[srat_num_cpus].phys_id =
+ (pa->apic_id << 8) | (pa->lsapic_eid);
/* nid should be overridden as logical node id later */
node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
srat_num_cpus++;
}
void __init
-acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
+acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
{
unsigned long paddr, size;
u8 pxm;
@@ -487,8 +485,7 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
num_node_memblks++;
}
-void __init
-acpi_numa_arch_fixup (void)
+void __init acpi_numa_arch_fixup(void)
{
int i, j, node_from, node_to;
@@ -534,21 +531,24 @@ acpi_numa_arch_fixup (void)
for (i = 0; i < srat_num_cpus; i++)
node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
- printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes());
- printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks);
+ printk(KERN_INFO "Number of logical nodes in system = %d\n",
+ num_online_nodes());
+ printk(KERN_INFO "Number of memory chunks in system = %d\n",
+ num_node_memblks);
- if (!slit_table) return;
+ if (!slit_table)
+ return;
memset(numa_slit, -1, sizeof(numa_slit));
- for (i=0; i<slit_table->localities; i++) {
+ for (i = 0; i < slit_table->localities; i++) {
if (!pxm_bit_test(i))
continue;
node_from = pxm_to_nid_map[i];
- for (j=0; j<slit_table->localities; j++) {
+ for (j = 0; j < slit_table->localities; j++) {
if (!pxm_bit_test(j))
continue;
node_to = pxm_to_nid_map[j];
node_distance(node_from, node_to) =
- slit_table->entry[i*slit_table->localities + j];
+ slit_table->entry[i * slit_table->localities + j];
}
}
@@ -556,36 +556,41 @@ acpi_numa_arch_fixup (void)
printk("ACPI 2.0 SLIT locality table:\n");
for_each_online_node(i) {
for_each_online_node(j)
- printk("%03d ", node_distance(i,j));
+ printk("%03d ", node_distance(i, j));
printk("\n");
}
#endif
}
-#endif /* CONFIG_ACPI_NUMA */
+#endif /* CONFIG_ACPI_NUMA */
-unsigned int
-acpi_register_gsi (u32 gsi, int edge_level, int active_high_low)
+/*
+ * success: return IRQ number (>=0)
+ * failure: return < 0
+ */
+int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
{
if (has_8259 && gsi < 16)
return isa_irq_to_vector(gsi);
return iosapic_register_intr(gsi,
- (active_high_low == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
- (edge_level == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
+ (active_high_low ==
+ ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH :
+ IOSAPIC_POL_LOW,
+ (edge_level ==
+ ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
+ IOSAPIC_LEVEL);
}
+
EXPORT_SYMBOL(acpi_register_gsi);
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
-void
-acpi_unregister_gsi (u32 gsi)
+void acpi_unregister_gsi(u32 gsi)
{
iosapic_unregister_intr(gsi);
}
+
EXPORT_SYMBOL(acpi_unregister_gsi);
-#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
-static int __init
-acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size)
{
struct acpi_table_header *fadt_header;
struct fadt_descriptor_rev2 *fadt;
@@ -593,11 +598,11 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (!phys_addr || !size)
return -EINVAL;
- fadt_header = (struct acpi_table_header *) __va(phys_addr);
+ fadt_header = (struct acpi_table_header *)__va(phys_addr);
if (fadt_header->revision != 3)
- return -ENODEV; /* Only deal with ACPI 2.0 FADT */
+ return -ENODEV; /* Only deal with ACPI 2.0 FADT */
- fadt = (struct fadt_descriptor_rev2 *) fadt_header;
+ fadt = (struct fadt_descriptor_rev2 *)fadt_header;
if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
acpi_kbd_controller_present = 0;
@@ -609,22 +614,19 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
return 0;
}
-
-unsigned long __init
-acpi_find_rsdp (void)
+unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
if (efi.acpi20)
rsdp_phys = __pa(efi.acpi20);
else if (efi.acpi)
- printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
+ printk(KERN_WARNING PREFIX
+ "v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
}
-
-int __init
-acpi_boot_init (void)
+int __init acpi_boot_init(void)
{
/*
@@ -642,31 +644,43 @@ acpi_boot_init (void)
/* Local APIC */
- if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0)
- printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
+ if (acpi_table_parse_madt
+ (ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0)
+ printk(KERN_ERR PREFIX
+ "Error parsing LAPIC address override entry\n");
- if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS) < 1)
- printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
+ if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS)
+ < 1)
+ printk(KERN_ERR PREFIX
+ "Error parsing MADT - no LAPIC entries\n");
- if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0) < 0)
+ if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0)
+ < 0)
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* I/O APIC */
- if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
- printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n");
+ if (acpi_table_parse_madt
+ (ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
+ printk(KERN_ERR PREFIX
+ "Error parsing MADT - no IOSAPIC entries\n");
/* System-Level Interrupt Routing */
- if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src, ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
- printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
+ if (acpi_table_parse_madt
+ (ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src,
+ ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
+ printk(KERN_ERR PREFIX
+ "Error parsing platform interrupt source entry\n");
- if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0)
- printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
+ if (acpi_table_parse_madt
+ (ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0)
+ printk(KERN_ERR PREFIX
+ "Error parsing interrupt source overrides entry\n");
if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, 0) < 0)
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
- skip_madt:
+ skip_madt:
/*
* FADT says whether a legacy keyboard controller is present.
@@ -681,8 +695,9 @@ acpi_boot_init (void)
if (available_cpus == 0) {
printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
- smp_boot_data.cpu_phys_id[available_cpus] = hard_smp_processor_id();
- available_cpus = 1; /* We've got at least one of these, no? */
+ smp_boot_data.cpu_phys_id[available_cpus] =
+ hard_smp_processor_id();
+ available_cpus = 1; /* We've got at least one of these, no? */
}
smp_boot_data.cpu_count = available_cpus;
@@ -691,8 +706,10 @@ acpi_boot_init (void)
if (srat_num_cpus == 0) {
int cpu, i = 1;
for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++)
- if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
- node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
+ if (smp_boot_data.cpu_phys_id[cpu] !=
+ hard_smp_processor_id())
+ node_cpuid[i++].phys_id =
+ smp_boot_data.cpu_phys_id[cpu];
}
# endif
#endif
@@ -700,12 +717,12 @@ acpi_boot_init (void)
build_cpu_to_node_map();
#endif
/* Make boot-up look pretty */
- printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
+ printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
+ total_cpus);
return 0;
}
-int
-acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
int vector;
@@ -726,11 +743,10 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
*/
#ifdef CONFIG_ACPI_HOTPLUG_CPU
static
-int
-acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
+int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
{
#ifdef CONFIG_ACPI_NUMA
- int pxm_id;
+ int pxm_id;
pxm_id = acpi_get_pxm(handle);
@@ -738,31 +754,28 @@ acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
* Assuming that the container driver would have set the proximity
* domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag
*/
- node_cpuid[cpu].nid = (pxm_id < 0) ? 0:
- pxm_to_nid_map[pxm_id];
+ node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id];
- node_cpuid[cpu].phys_id = physid;
+ node_cpuid[cpu].phys_id = physid;
#endif
- return(0);
+ return (0);
}
-
-int
-acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int acpi_map_lsapic(acpi_handle handle, int *pcpu)
{
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
struct acpi_table_lsapic *lsapic;
cpumask_t tmp_map;
long physid;
int cpu;
-
+
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
return -EINVAL;
- if (!buffer.length || !buffer.pointer)
+ if (!buffer.length || !buffer.pointer)
return -EINVAL;
-
+
obj = buffer.pointer;
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length < sizeof(*lsapic)) {
@@ -778,7 +791,7 @@ acpi_map_lsapic(acpi_handle handle, int *pcpu)
return -EINVAL;
}
- physid = ((lsapic->id <<8) | (lsapic->eid));
+ physid = ((lsapic->id << 8) | (lsapic->eid));
acpi_os_free(buffer.pointer);
buffer.length = ACPI_ALLOCATE_BUFFER;
@@ -786,50 +799,49 @@ acpi_map_lsapic(acpi_handle handle, int *pcpu)
cpus_complement(tmp_map, cpu_present_map);
cpu = first_cpu(tmp_map);
- if(cpu >= NR_CPUS)
+ if (cpu >= NR_CPUS)
return -EINVAL;
acpi_map_cpu2node(handle, cpu, physid);
- cpu_set(cpu, cpu_present_map);
+ cpu_set(cpu, cpu_present_map);
ia64_cpu_to_sapicid[cpu] = physid;
ia64_acpiid_to_sapicid[lsapic->acpi_id] = ia64_cpu_to_sapicid[cpu];
*pcpu = cpu;
- return(0);
+ return (0);
}
-EXPORT_SYMBOL(acpi_map_lsapic);
+EXPORT_SYMBOL(acpi_map_lsapic);
-int
-acpi_unmap_lsapic(int cpu)
+int acpi_unmap_lsapic(int cpu)
{
int i;
- for (i=0; i<MAX_SAPICS; i++) {
- if (ia64_acpiid_to_sapicid[i] == ia64_cpu_to_sapicid[cpu]) {
- ia64_acpiid_to_sapicid[i] = -1;
- break;
- }
- }
+ for (i = 0; i < MAX_SAPICS; i++) {
+ if (ia64_acpiid_to_sapicid[i] == ia64_cpu_to_sapicid[cpu]) {
+ ia64_acpiid_to_sapicid[i] = -1;
+ break;
+ }
+ }
ia64_cpu_to_sapicid[cpu] = -1;
- cpu_clear(cpu,cpu_present_map);
+ cpu_clear(cpu, cpu_present_map);
#ifdef CONFIG_ACPI_NUMA
/* NUMA specific cleanup's */
#endif
- return(0);
+ return (0);
}
+
EXPORT_SYMBOL(acpi_unmap_lsapic);
-#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
#ifdef CONFIG_ACPI_NUMA
acpi_status __devinit
-acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
+acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
{
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
struct acpi_table_iosapic *iosapic;
unsigned int gsi_base;
@@ -878,10 +890,9 @@ acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
map_iosapic_to_node(gsi_base, node);
return AE_OK;
}
-#endif /* CONFIG_NUMA */
+#endif /* CONFIG_NUMA */
-int
-acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base)
+int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
{
int err;
@@ -890,17 +901,18 @@ acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base)
#if CONFIG_ACPI_NUMA
acpi_map_iosapic(handle, 0, NULL, NULL);
-#endif /* CONFIG_ACPI_NUMA */
+#endif /* CONFIG_ACPI_NUMA */
return 0;
}
+
EXPORT_SYMBOL(acpi_register_ioapic);
-int
-acpi_unregister_ioapic (acpi_handle handle, u32 gsi_base)
+int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
{
return iosapic_remove(gsi_base);
}
+
EXPORT_SYMBOL(acpi_unregister_ioapic);
-#endif /* CONFIG_ACPI_BOOT */
+#endif /* CONFIG_ACPI */
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 7d1ae2982c53..f6a234289341 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -211,17 +211,41 @@ void foo(void)
#endif
BLANK();
- DEFINE(IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET,
- offsetof (struct ia64_mca_cpu, proc_state_dump));
- DEFINE(IA64_MCA_CPU_STACK_OFFSET,
- offsetof (struct ia64_mca_cpu, stack));
- DEFINE(IA64_MCA_CPU_STACKFRAME_OFFSET,
- offsetof (struct ia64_mca_cpu, stackframe));
- DEFINE(IA64_MCA_CPU_RBSTORE_OFFSET,
- offsetof (struct ia64_mca_cpu, rbstore));
+ DEFINE(IA64_MCA_CPU_MCA_STACK_OFFSET,
+ offsetof (struct ia64_mca_cpu, mca_stack));
DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
offsetof (struct ia64_mca_cpu, init_stack));
BLANK();
+ DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET,
+ offsetof (struct ia64_sal_os_state, sal_ra));
+ DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET,
+ offsetof (struct ia64_sal_os_state, os_gp));
+ DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
+ offsetof (struct ia64_sal_os_state, pal_min_state));
+ DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET,
+ offsetof (struct ia64_sal_os_state, proc_state_param));
+ DEFINE(IA64_SAL_OS_STATE_SIZE,
+ sizeof (struct ia64_sal_os_state));
+ DEFINE(IA64_PMSA_GR_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_gr));
+ DEFINE(IA64_PMSA_BANK1_GR_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_bank1_gr));
+ DEFINE(IA64_PMSA_PR_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_pr));
+ DEFINE(IA64_PMSA_BR0_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_br0));
+ DEFINE(IA64_PMSA_RSC_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_rsc));
+ DEFINE(IA64_PMSA_IIP_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_iip));
+ DEFINE(IA64_PMSA_IPSR_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_ipsr));
+ DEFINE(IA64_PMSA_IFS_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_ifs));
+ DEFINE(IA64_PMSA_XIP_OFFSET,
+ offsetof (struct pal_min_state_area_s, pmsa_xip));
+ BLANK();
+
/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
diff --git a/arch/ia64/kernel/cpufreq/Kconfig b/arch/ia64/kernel/cpufreq/Kconfig
new file mode 100644
index 000000000000..2d9d5279b981
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/Kconfig
@@ -0,0 +1,29 @@
+
+#
+# CPU Frequency scaling
+#
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+if CPU_FREQ
+
+comment "CPUFreq processor drivers"
+
+config IA64_ACPI_CPUFREQ
+ tristate "ACPI Processor P-States driver"
+ select CPU_FREQ_TABLE
+ depends on ACPI_PROCESSOR
+ help
+ This driver adds a CPUFreq driver which utilizes the ACPI
+ Processor Performance States.
+
+ For details, take a look at <file:Documentation/cpu-freq/>.
+
+ If in doubt, say N.
+
+endif # CPU_FREQ
+
+endmenu
+
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile
new file mode 100644
index 000000000000..f748d34c02f0
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
new file mode 100644
index 000000000000..da4d5cf80a48
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -0,0 +1,499 @@
+/*
+ * arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+ * This file provides the ACPI based P-state support. This
+ * module works with generic cpufreq infrastructure. Most of
+ * the code is based on i386 version
+ * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
+ *
+ * Copyright (C) 2005 Intel Corp
+ * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pal.h>
+
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
+
+MODULE_AUTHOR("Venkatesh Pallipadi");
+MODULE_DESCRIPTION("ACPI Processor P-States Driver");
+MODULE_LICENSE("GPL");
+
+
+struct cpufreq_acpi_io {
+ struct acpi_processor_performance acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int resume;
+};
+
+static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
+
+static struct cpufreq_driver acpi_cpufreq_driver;
+
+
+static int
+processor_set_pstate (
+ u32 value)
+{
+ s64 retval;
+
+ dprintk("processor_set_pstate\n");
+
+ retval = ia64_pal_set_pstate((u64)value);
+
+ if (retval) {
+ dprintk("Failed to set freq to 0x%x, with error 0x%x\n",
+ value, retval);
+ return -ENODEV;
+ }
+ return (int)retval;
+}
+
+
+static int
+processor_get_pstate (
+ u32 *value)
+{
+ u64 pstate_index = 0;
+ s64 retval;
+
+ dprintk("processor_get_pstate\n");
+
+ retval = ia64_pal_get_pstate(&pstate_index);
+ *value = (u32) pstate_index;
+
+ if (retval)
+ dprintk("Failed to get current freq with "
+ "error 0x%x, idx 0x%x\n", retval, *value);
+
+ return (int)retval;
+}
+
+
+/* To be used only after data->acpi_data is initialized */
+static unsigned
+extract_clock (
+ struct cpufreq_acpi_io *data,
+ unsigned value,
+ unsigned int cpu)
+{
+ unsigned long i;
+
+ dprintk("extract_clock\n");
+
+ for (i = 0; i < data->acpi_data.state_count; i++) {
+ if (value >= data->acpi_data.states[i].control)
+ return data->acpi_data.states[i].core_frequency;
+ }
+ return data->acpi_data.states[i-1].core_frequency;
+}
+
+
+static unsigned int
+processor_get_freq (
+ struct cpufreq_acpi_io *data,
+ unsigned int cpu)
+{
+ int ret = 0;
+ u32 value = 0;
+ cpumask_t saved_mask;
+ unsigned long clock_freq;
+
+ dprintk("processor_get_freq\n");
+
+ saved_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu) {
+ ret = -EAGAIN;
+ goto migrate_end;
+ }
+
+ /*
+ * processor_get_pstate gets the average frequency since the
+ * last get. So, do two PAL_get_freq()...
+ */
+ ret = processor_get_pstate(&value);
+ ret = processor_get_pstate(&value);
+
+ if (ret) {
+ set_cpus_allowed(current, saved_mask);
+ printk(KERN_WARNING "get performance failed with error %d\n",
+ ret);
+ ret = -EAGAIN;
+ goto migrate_end;
+ }
+ clock_freq = extract_clock(data, value, cpu);
+ ret = (clock_freq*1000);
+
+migrate_end:
+ set_cpus_allowed(current, saved_mask);
+ return ret;
+}
+
+
+static int
+processor_set_freq (
+ struct cpufreq_acpi_io *data,
+ unsigned int cpu,
+ int state)
+{
+ int ret = 0;
+ u32 value = 0;
+ struct cpufreq_freqs cpufreq_freqs;
+ cpumask_t saved_mask;
+ int retval;
+
+ dprintk("processor_set_freq\n");
+
+ saved_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu) {
+ retval = -EAGAIN;
+ goto migrate_end;
+ }
+
+ if (state == data->acpi_data.state) {
+ if (unlikely(data->resume)) {
+ dprintk("Called after resume, resetting to P%d\n", state);
+ data->resume = 0;
+ } else {
+ dprintk("Already at target state (P%d)\n", state);
+ retval = 0;
+ goto migrate_end;
+ }
+ }
+
+ dprintk("Transitioning from P%d to P%d\n",
+ data->acpi_data.state, state);
+
+ /* cpufreq frequency struct */
+ cpufreq_freqs.cpu = cpu;
+ cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
+ cpufreq_freqs.new = data->freq_table[state].frequency;
+
+ /* notify cpufreq */
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+
+ /*
+ * First we write the target state's 'control' value to the
+ * control_register.
+ */
+
+ value = (u32) data->acpi_data.states[state].control;
+
+ dprintk("Transitioning to state: 0x%08x\n", value);
+
+ ret = processor_set_pstate(value);
+ if (ret) {
+ unsigned int tmp = cpufreq_freqs.new;
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ cpufreq_freqs.new = cpufreq_freqs.old;
+ cpufreq_freqs.old = tmp;
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ printk(KERN_WARNING "Transition failed with error %d\n", ret);
+ retval = -ENODEV;
+ goto migrate_end;
+ }
+
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+
+ data->acpi_data.state = state;
+
+ retval = 0;
+
+migrate_end:
+ set_cpus_allowed(current, saved_mask);
+ return (retval);
+}
+
+
+static unsigned int
+acpi_cpufreq_get (
+ unsigned int cpu)
+{
+ struct cpufreq_acpi_io *data = acpi_io_data[cpu];
+
+ dprintk("acpi_cpufreq_get\n");
+
+ return processor_get_freq(data, cpu);
+}
+
+
+static int
+acpi_cpufreq_target (
+ struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+ unsigned int next_state = 0;
+ unsigned int result = 0;
+
+ dprintk("acpi_cpufreq_setpolicy\n");
+
+ result = cpufreq_frequency_table_target(policy,
+ data->freq_table, target_freq, relation, &next_state);
+ if (result)
+ return (result);
+
+ result = processor_set_freq(data, policy->cpu, next_state);
+
+ return (result);
+}
+
+
+static int
+acpi_cpufreq_verify (
+ struct cpufreq_policy *policy)
+{
+ unsigned int result = 0;
+ struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+
+ dprintk("acpi_cpufreq_verify\n");
+
+ result = cpufreq_frequency_table_verify(policy,
+ data->freq_table);
+
+ return (result);
+}
+
+
+/*
+ * processor_init_pdc - let BIOS know about the SMP capabilities
+ * of this driver
+ * @perf: processor-specific acpi_io_data struct
+ * @cpu: CPU being initialized
+ *
+ * To avoid issues with legacy OSes, some BIOSes require to be informed of
+ * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
+ * accordingly. Actual call to _PDC is done in driver/acpi/processor.c
+ */
+static void
+processor_init_pdc (
+ struct acpi_processor_performance *perf,
+ unsigned int cpu,
+ struct acpi_object_list *obj_list
+ )
+{
+ union acpi_object *obj;
+ u32 *buf;
+
+ dprintk("processor_init_pdc\n");
+
+ perf->pdc = NULL;
+ /* Initialize pdc. It will be used later. */
+ if (!obj_list)
+ return;
+
+ if (!(obj_list->count && obj_list->pointer))
+ return;
+
+ obj = obj_list->pointer;
+ if ((obj->buffer.length == 12) && obj->buffer.pointer) {
+ buf = (u32 *)obj->buffer.pointer;
+ buf[0] = ACPI_PDC_REVISION_ID;
+ buf[1] = 1;
+ buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+ perf->pdc = obj_list;
+ }
+ return;
+}
+
+
+static int
+acpi_cpufreq_cpu_init (
+ struct cpufreq_policy *policy)
+{
+ unsigned int i;
+ unsigned int cpu = policy->cpu;
+ struct cpufreq_acpi_io *data;
+ unsigned int result = 0;
+
+ union acpi_object arg0 = {ACPI_TYPE_BUFFER};
+ u32 arg0_buf[3];
+ struct acpi_object_list arg_list = {1, &arg0};
+
+ dprintk("acpi_cpufreq_cpu_init\n");
+ /* setup arg_list for _PDC settings */
+ arg0.buffer.length = 12;
+ arg0.buffer.pointer = (u8 *) arg0_buf;
+
+ data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+ if (!data)
+ return (-ENOMEM);
+
+ memset(data, 0, sizeof(struct cpufreq_acpi_io));
+
+ acpi_io_data[cpu] = data;
+
+ processor_init_pdc(&data->acpi_data, cpu, &arg_list);
+ result = acpi_processor_register_performance(&data->acpi_data, cpu);
+ data->acpi_data.pdc = NULL;
+
+ if (result)
+ goto err_free;
+
+ /* capability check */
+ if (data->acpi_data.state_count <= 1) {
+ dprintk("No P-States\n");
+ result = -ENODEV;
+ goto err_unreg;
+ }
+
+ if ((data->acpi_data.control_register.space_id !=
+ ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+ (data->acpi_data.status_register.space_id !=
+ ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+ dprintk("Unsupported address space [%d, %d]\n",
+ (u32) (data->acpi_data.control_register.space_id),
+ (u32) (data->acpi_data.status_register.space_id));
+ result = -ENODEV;
+ goto err_unreg;
+ }
+
+ /* alloc freq_table */
+ data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+ (data->acpi_data.state_count + 1),
+ GFP_KERNEL);
+ if (!data->freq_table) {
+ result = -ENOMEM;
+ goto err_unreg;
+ }
+
+ /* detect transition latency */
+ policy->cpuinfo.transition_latency = 0;
+ for (i=0; i<data->acpi_data.state_count; i++) {
+ if ((data->acpi_data.states[i].transition_latency * 1000) >
+ policy->cpuinfo.transition_latency) {
+ policy->cpuinfo.transition_latency =
+ data->acpi_data.states[i].transition_latency * 1000;
+ }
+ }
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+ policy->cur = processor_get_freq(data, policy->cpu);
+
+ /* table init */
+ for (i = 0; i <= data->acpi_data.state_count; i++)
+ {
+ data->freq_table[i].index = i;
+ if (i < data->acpi_data.state_count) {
+ data->freq_table[i].frequency =
+ data->acpi_data.states[i].core_frequency * 1000;
+ } else {
+ data->freq_table[i].frequency = CPUFREQ_TABLE_END;
+ }
+ }
+
+ result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+ if (result) {
+ goto err_freqfree;
+ }
+
+ /* notify BIOS that we exist */
+ acpi_processor_notify_smm(THIS_MODULE);
+
+ printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management "
+ "activated.\n", cpu);
+
+ for (i = 0; i < data->acpi_data.state_count; i++)
+ dprintk(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
+ (i == data->acpi_data.state?'*':' '), i,
+ (u32) data->acpi_data.states[i].core_frequency,
+ (u32) data->acpi_data.states[i].power,
+ (u32) data->acpi_data.states[i].transition_latency,
+ (u32) data->acpi_data.states[i].bus_master_latency,
+ (u32) data->acpi_data.states[i].status,
+ (u32) data->acpi_data.states[i].control);
+
+ cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
+
+ /* the first call to ->target() should result in us actually
+ * writing something to the appropriate registers. */
+ data->resume = 1;
+
+ return (result);
+
+ err_freqfree:
+ kfree(data->freq_table);
+ err_unreg:
+ acpi_processor_unregister_performance(&data->acpi_data, cpu);
+ err_free:
+ kfree(data);
+ acpi_io_data[cpu] = NULL;
+
+ return (result);
+}
+
+
+static int
+acpi_cpufreq_cpu_exit (
+ struct cpufreq_policy *policy)
+{
+ struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+
+ dprintk("acpi_cpufreq_cpu_exit\n");
+
+ if (data) {
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ acpi_io_data[policy->cpu] = NULL;
+ acpi_processor_unregister_performance(&data->acpi_data,
+ policy->cpu);
+ kfree(data);
+ }
+
+ return (0);
+}
+
+
+static struct freq_attr* acpi_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+
+static struct cpufreq_driver acpi_cpufreq_driver = {
+ .verify = acpi_cpufreq_verify,
+ .target = acpi_cpufreq_target,
+ .get = acpi_cpufreq_get,
+ .init = acpi_cpufreq_cpu_init,
+ .exit = acpi_cpufreq_cpu_exit,
+ .name = "acpi-cpufreq",
+ .owner = THIS_MODULE,
+ .attr = acpi_cpufreq_attr,
+};
+
+
+static int __init
+acpi_cpufreq_init (void)
+{
+ dprintk("acpi_cpufreq_init\n");
+
+ return cpufreq_register_driver(&acpi_cpufreq_driver);
+}
+
+
+static void __exit
+acpi_cpufreq_exit (void)
+{
+ dprintk("acpi_cpufreq_exit\n");
+
+ cpufreq_unregister_driver(&acpi_cpufreq_driver);
+ return;
+}
+
+
+late_initcall(acpi_cpufreq_init);
+module_exit(acpi_cpufreq_exit);
+
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
deleted file mode 100644
index bbb8efe126b7..000000000000
--- a/arch/ia64/kernel/domain.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * arch/ia64/kernel/domain.c
- * Architecture specific sched-domains builder.
- *
- * Copyright (C) 2004 Jesse Barnes
- * Copyright (C) 2004 Silicon Graphics, Inc.
- */
-
-#include <linux/sched.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-#include <linux/cpumask.h>
-#include <linux/init.h>
-#include <linux/topology.h>
-#include <linux/nodemask.h>
-
-#define SD_NODES_PER_DOMAIN 16
-
-#ifdef CONFIG_NUMA
-/**
- * find_next_best_node - find the next node to include in a sched_domain
- * @node: node whose sched_domain we're building
- * @used_nodes: nodes already in the sched_domain
- *
- * Find the next node to include in a given scheduling domain. Simply
- * finds the closest node not already in the @used_nodes map.
- *
- * Should use nodemask_t.
- */
-static int find_next_best_node(int node, unsigned long *used_nodes)
-{
- int i, n, val, min_val, best_node = 0;
-
- min_val = INT_MAX;
-
- for (i = 0; i < MAX_NUMNODES; i++) {
- /* Start at @node */
- n = (node + i) % MAX_NUMNODES;
-
- if (!nr_cpus_node(n))
- continue;
-
- /* Skip already used nodes */
- if (test_bit(n, used_nodes))
- continue;
-
- /* Simple min distance search */
- val = node_distance(node, n);
-
- if (val < min_val) {
- min_val = val;
- best_node = n;
- }
- }
-
- set_bit(best_node, used_nodes);
- return best_node;
-}
-
-/**
- * sched_domain_node_span - get a cpumask for a node's sched_domain
- * @node: node whose cpumask we're constructing
- * @size: number of nodes to include in this span
- *
- * Given a node, construct a good cpumask for its sched_domain to span. It
- * should be one that prevents unnecessary balancing, but also spreads tasks
- * out optimally.
- */
-static cpumask_t sched_domain_node_span(int node)
-{
- int i;
- cpumask_t span, nodemask;
- DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
-
- cpus_clear(span);
- bitmap_zero(used_nodes, MAX_NUMNODES);
-
- nodemask = node_to_cpumask(node);
- cpus_or(span, span, nodemask);
- set_bit(node, used_nodes);
-
- for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
- int next_node = find_next_best_node(node, used_nodes);
- nodemask = node_to_cpumask(next_node);
- cpus_or(span, span, nodemask);
- }
-
- return span;
-}
-#endif
-
-/*
- * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we
- * can switch it on easily if needed.
- */
-#ifdef CONFIG_SCHED_SMT
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static struct sched_group sched_group_cpus[NR_CPUS];
-static int cpu_to_cpu_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
- return first_cpu(cpu_sibling_map[cpu]);
-#else
- return cpu;
-#endif
-}
-
-#ifdef CONFIG_NUMA
-/*
- * The init_sched_build_groups can't handle what we want to do with node
- * groups, so roll our own. Now each node has its own list of groups which
- * gets dynamically allocated.
- */
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static struct sched_group *sched_group_nodes[MAX_NUMNODES];
-
-static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
-static struct sched_group sched_group_allnodes[MAX_NUMNODES];
-
-static int cpu_to_allnodes_group(int cpu)
-{
- return cpu_to_node(cpu);
-}
-#endif
-
-/*
- * Build sched domains for a given set of cpus and attach the sched domains
- * to the individual cpus
- */
-void build_sched_domains(const cpumask_t *cpu_map)
-{
- int i;
-
- /*
- * Set up domains for cpus specified by the cpu_map.
- */
- for_each_cpu_mask(i, *cpu_map) {
- int group;
- struct sched_domain *sd = NULL, *p;
- cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
-
- cpus_and(nodemask, nodemask, *cpu_map);
-
-#ifdef CONFIG_NUMA
- if (num_online_cpus()
- > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
- sd = &per_cpu(allnodes_domains, i);
- *sd = SD_ALLNODES_INIT;
- sd->span = *cpu_map;
- group = cpu_to_allnodes_group(i);
- sd->groups = &sched_group_allnodes[group];
- p = sd;
- } else
- p = NULL;
-
- sd = &per_cpu(node_domains, i);
- *sd = SD_NODE_INIT;
- sd->span = sched_domain_node_span(cpu_to_node(i));
- sd->parent = p;
- cpus_and(sd->span, sd->span, *cpu_map);
-#endif
-
- p = sd;
- sd = &per_cpu(phys_domains, i);
- group = cpu_to_phys_group(i);
- *sd = SD_CPU_INIT;
- sd->span = nodemask;
- sd->parent = p;
- sd->groups = &sched_group_phys[group];
-
-#ifdef CONFIG_SCHED_SMT
- p = sd;
- sd = &per_cpu(cpu_domains, i);
- group = cpu_to_cpu_group(i);
- *sd = SD_SIBLING_INIT;
- sd->span = cpu_sibling_map[i];
- cpus_and(sd->span, sd->span, *cpu_map);
- sd->parent = p;
- sd->groups = &sched_group_cpus[group];
-#endif
- }
-
-#ifdef CONFIG_SCHED_SMT
- /* Set up CPU (sibling) groups */
- for_each_cpu_mask(i, *cpu_map) {
- cpumask_t this_sibling_map = cpu_sibling_map[i];
- cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
- if (i != first_cpu(this_sibling_map))
- continue;
-
- init_sched_build_groups(sched_group_cpus, this_sibling_map,
- &cpu_to_cpu_group);
- }
-#endif
-
- /* Set up physical groups */
- for (i = 0; i < MAX_NUMNODES; i++) {
- cpumask_t nodemask = node_to_cpumask(i);
-
- cpus_and(nodemask, nodemask, *cpu_map);
- if (cpus_empty(nodemask))
- continue;
-
- init_sched_build_groups(sched_group_phys, nodemask,
- &cpu_to_phys_group);
- }
-
-#ifdef CONFIG_NUMA
- init_sched_build_groups(sched_group_allnodes, *cpu_map,
- &cpu_to_allnodes_group);
-
- for (i = 0; i < MAX_NUMNODES; i++) {
- /* Set up node groups */
- struct sched_group *sg, *prev;
- cpumask_t nodemask = node_to_cpumask(i);
- cpumask_t domainspan;
- cpumask_t covered = CPU_MASK_NONE;
- int j;
-
- cpus_and(nodemask, nodemask, *cpu_map);
- if (cpus_empty(nodemask))
- continue;
-
- domainspan = sched_domain_node_span(i);
- cpus_and(domainspan, domainspan, *cpu_map);
-
- sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
- sched_group_nodes[i] = sg;
- for_each_cpu_mask(j, nodemask) {
- struct sched_domain *sd;
- sd = &per_cpu(node_domains, j);
- sd->groups = sg;
- if (sd->groups == NULL) {
- /* Turn off balancing if we have no groups */
- sd->flags = 0;
- }
- }
- if (!sg) {
- printk(KERN_WARNING
- "Can not alloc domain group for node %d\n", i);
- continue;
- }
- sg->cpu_power = 0;
- sg->cpumask = nodemask;
- cpus_or(covered, covered, nodemask);
- prev = sg;
-
- for (j = 0; j < MAX_NUMNODES; j++) {
- cpumask_t tmp, notcovered;
- int n = (i + j) % MAX_NUMNODES;
-
- cpus_complement(notcovered, covered);
- cpus_and(tmp, notcovered, *cpu_map);
- cpus_and(tmp, tmp, domainspan);
- if (cpus_empty(tmp))
- break;
-
- nodemask = node_to_cpumask(n);
- cpus_and(tmp, tmp, nodemask);
- if (cpus_empty(tmp))
- continue;
-
- sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
- if (!sg) {
- printk(KERN_WARNING
- "Can not alloc domain group for node %d\n", j);
- break;
- }
- sg->cpu_power = 0;
- sg->cpumask = tmp;
- cpus_or(covered, covered, tmp);
- prev->next = sg;
- prev = sg;
- }
- prev->next = sched_group_nodes[i];
- }
-#endif
-
- /* Calculate CPU power for physical packages and nodes */
- for_each_cpu_mask(i, *cpu_map) {
- int power;
- struct sched_domain *sd;
-#ifdef CONFIG_SCHED_SMT
- sd = &per_cpu(cpu_domains, i);
- power = SCHED_LOAD_SCALE;
- sd->groups->cpu_power = power;
-#endif
-
- 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;
-
- 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;
- }
-#endif
-
- /* Attach the domains */
- for_each_cpu_mask(i, *cpu_map) {
- struct sched_domain *sd;
-#ifdef CONFIG_SCHED_SMT
- sd = &per_cpu(cpu_domains, i);
-#else
- sd = &per_cpu(phys_domains, i);
-#endif
- cpu_attach_domain(sd, i);
- }
-}
-/*
- * Set up scheduler domains and groups. Callers must hold the hotplug lock.
- */
-void arch_init_sched_domains(const cpumask_t *cpu_map)
-{
- cpumask_t cpu_default_map;
-
- /*
- * Setup mask for cpus without special case scheduling requirements.
- * For now this just excludes isolated cpus, but could be used to
- * exclude other special cases in the future.
- */
- cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
-
- build_sched_domains(&cpu_default_map);
-}
-
-void arch_destroy_sched_domains(const cpumask_t *cpu_map)
-{
-#ifdef CONFIG_NUMA
- int i;
- for (i = 0; i < MAX_NUMNODES; i++) {
- cpumask_t nodemask = node_to_cpumask(i);
- struct sched_group *oldsg, *sg = sched_group_nodes[i];
-
- cpus_and(nodemask, nodemask, *cpu_map);
- if (cpus_empty(nodemask))
- continue;
-
- if (sg == NULL)
- continue;
- sg = sg->next;
-next_sg:
- oldsg = sg;
- sg = sg->next;
- kfree(oldsg);
- if (oldsg != sched_group_nodes[i])
- goto next_sg;
- sched_group_nodes[i] = NULL;
- }
-#endif
-}
-
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 9be53e1ea404..ba0b6a1f429f 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -37,7 +37,7 @@
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/kregs.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/percpu.h>
#include <asm/processor.h>
@@ -204,9 +204,6 @@ GLOBAL_ENTRY(ia64_switch_to)
(p6) br.cond.dpnt .map
;;
.done:
-(p6) ssm psr.ic // if we had to map, reenable the psr.ic bit FIRST!!!
- ;;
-(p6) srlz.d
ld8 sp=[r21] // load kernel stack pointer of new task
mov IA64_KR(CURRENT)=in0 // update "current" application register
mov r8=r13 // return pointer to previously running task
@@ -234,6 +231,9 @@ GLOBAL_ENTRY(ia64_switch_to)
mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
;;
itr.d dtr[r25]=r23 // wire in new mapping...
+ ssm psr.ic // reenable the psr.ic bit
+ ;;
+ srlz.d
br.cond.sptk .done
END(ia64_switch_to)
@@ -470,6 +470,29 @@ ENTRY(load_switch_stack)
br.cond.sptk.many b7
END(load_switch_stack)
+GLOBAL_ENTRY(prefetch_stack)
+ add r14 = -IA64_SWITCH_STACK_SIZE, sp
+ add r15 = IA64_TASK_THREAD_KSP_OFFSET, in0
+ ;;
+ ld8 r16 = [r15] // load next's stack pointer
+ lfetch.fault.excl [r14], 128
+ ;;
+ lfetch.fault.excl [r14], 128
+ lfetch.fault [r16], 128
+ ;;
+ lfetch.fault.excl [r14], 128
+ lfetch.fault [r16], 128
+ ;;
+ lfetch.fault.excl [r14], 128
+ lfetch.fault [r16], 128
+ ;;
+ lfetch.fault.excl [r14], 128
+ lfetch.fault [r16], 128
+ ;;
+ lfetch.fault [r16], 128
+ br.ret.sptk.many rp
+END(prefetch_switch_stack)
+
GLOBAL_ENTRY(execve)
mov r15=__NR_execve // put syscall number in place
break __BREAK_SYSCALL
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 7d7684a369d3..2ddbac6f4999 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -14,7 +14,7 @@
#include <asm/asmmacro.h>
#include <asm/errno.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/percpu.h>
#include <asm/thread_info.h>
#include <asm/sal.h>
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index 86948ce63e43..86064ca98952 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -10,7 +10,7 @@
#include <asm/asmmacro.h>
#include <asm/errno.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/sigcontext.h>
#include <asm/system.h>
#include <asm/unistd.h>
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 8d3a9291b47f..bfe65b2e8621 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -25,7 +25,7 @@
#include <asm/fpu.h>
#include <asm/kregs.h>
#include <asm/mmu_context.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pal.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 7936b62f7a2e..574084f343fa 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -561,7 +561,7 @@ static inline int vector_is_shared (int vector)
return (iosapic_intr_info[vector].count > 1);
}
-static void
+static int
register_intr (unsigned int gsi, int vector, unsigned char delivery,
unsigned long polarity, unsigned long trigger)
{
@@ -576,7 +576,7 @@ 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);
- return;
+ return -ENODEV;
}
iosapic_address = iosapic_lists[index].addr;
@@ -587,7 +587,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
rte = iosapic_alloc_rte();
if (!rte) {
printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
- return;
+ return -ENOMEM;
}
rte_index = gsi - gsi_base;
@@ -603,7 +603,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
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__);
- return;
+ return -EINVAL;
}
}
@@ -623,6 +623,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
__FUNCTION__, vector, idesc->handler->typename, irq_type->typename);
idesc->handler = irq_type;
}
+ return 0;
}
static unsigned int
@@ -710,7 +711,7 @@ int
iosapic_register_intr (unsigned int gsi,
unsigned long polarity, unsigned long trigger)
{
- int vector, mask = 1;
+ int vector, mask = 1, err;
unsigned int dest;
unsigned long flags;
struct iosapic_rte_info *rte;
@@ -737,8 +738,8 @@ again:
vector = assign_irq_vector(AUTO_ASSIGN);
if (vector < 0) {
vector = iosapic_find_sharable_vector(trigger, polarity);
- if (vector < 0)
- panic("%s: out of interrupt vectors!\n", __FUNCTION__);
+ if (vector < 0)
+ return -ENOSPC;
}
spin_lock_irqsave(&irq_descp(vector)->lock, flags);
@@ -753,8 +754,13 @@ again:
}
dest = get_target_cpu(gsi, vector);
- register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
+ err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
polarity, trigger);
+ if (err < 0) {
+ spin_unlock(&iosapic_lock);
+ spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+ return err;
+ }
/*
* If the vector is shared and already unmasked for
@@ -776,7 +782,6 @@ again:
return vector;
}
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
void
iosapic_unregister_intr (unsigned int gsi)
{
@@ -859,7 +864,6 @@ iosapic_unregister_intr (unsigned int gsi)
spin_unlock(&iosapic_lock);
spin_unlock_irqrestore(&idesc->lock, flags);
}
-#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
/*
* ACPI calls this when it finds an entry for a platform interrupt.
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 28f2aadc38d0..205d98028261 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -91,23 +91,8 @@ skip:
}
#ifdef CONFIG_SMP
-/*
- * This is updated when the user sets irq affinity via /proc
- */
-static cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
-static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
-
static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
-/*
- * Arch specific routine for deferred write to iosapic rte to reprogram
- * intr destination.
- */
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
- pending_irq_cpumask[irq] = mask_val;
-}
-
void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
{
cpumask_t mask = CPU_MASK_NONE;
@@ -116,32 +101,10 @@ 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);
}
}
-
-
-void move_irq(int irq)
-{
- /* note - we hold desc->lock */
- cpumask_t tmp;
- irq_desc_t *desc = irq_descp(irq);
- int redir = test_bit(irq, pending_irq_redir);
-
- if (unlikely(!desc->handler->set_affinity))
- return;
-
- if (!cpus_empty(pending_irq_cpumask[irq])) {
- cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
- if (unlikely(!cpus_empty(tmp))) {
- desc->handler->set_affinity(irq | (redir ? IA64_IRQ_REDIRECTED : 0),
- pending_irq_cpumask[irq]);
- }
- cpus_clear(pending_irq_cpumask[irq]);
- }
-}
-
-
#endif /* CONFIG_SMP */
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 3bb3a13c4047..c13ca0d49c4a 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -44,7 +44,7 @@
#include <asm/break.h>
#include <asm/ia32.h>
#include <asm/kregs.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
@@ -69,7 +69,6 @@
# define DBG_FAULT(i)
#endif
-#define MINSTATE_VIRT /* needed by minstate.h */
#include "minstate.h"
#define FAULT(n) \
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index b7fa3ccd2b0f..2323377e3695 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -49,6 +49,7 @@
/*
* void jprobe_break(void)
*/
+ .section .kprobes.text, "ax"
ENTRY(jprobe_break)
break.m 0x80300
END(jprobe_break)
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 884f5cd27d8a..471086b808a4 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -87,12 +87,25 @@ static enum instruction_type bundle_encoding[32][3] = {
* is IP relative instruction and update the kprobe
* inst flag accordingly
*/
-static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode,
- unsigned long kprobe_inst, struct kprobe *p)
+static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
+ uint major_opcode,
+ unsigned long kprobe_inst,
+ struct kprobe *p)
{
p->ainsn.inst_flag = 0;
p->ainsn.target_br_reg = 0;
+ /* Check for Break instruction
+ * Bits 37:40 Major opcode to be zero
+ * Bits 27:32 X6 to be zero
+ * Bits 32:35 X3 to be zero
+ */
+ if ((!major_opcode) && (!((kprobe_inst >> 27) & 0x1FF)) ) {
+ /* is a break instruction */
+ p->ainsn.inst_flag |= INST_FLAG_BREAK_INST;
+ return;
+ }
+
if (bundle_encoding[template][slot] == B) {
switch (major_opcode) {
case INDIRECT_CALL_OPCODE:
@@ -126,8 +139,10 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode
* Returns 0 if supported
* Returns -EINVAL if unsupported
*/
-static int unsupported_inst(uint template, uint slot, uint major_opcode,
- unsigned long kprobe_inst, struct kprobe *p)
+static int __kprobes unsupported_inst(uint template, uint slot,
+ uint major_opcode,
+ unsigned long kprobe_inst,
+ struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
@@ -168,8 +183,9 @@ static int unsupported_inst(uint template, uint slot, uint major_opcode,
* on which we are inserting kprobe is cmp instruction
* with ctype as unc.
*/
-static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
-unsigned long kprobe_inst)
+static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
+ uint major_opcode,
+ unsigned long kprobe_inst)
{
cmp_inst_t cmp_inst;
uint ctype_unc = 0;
@@ -201,8 +217,10 @@ out:
* In this function we override the bundle with
* the break instruction at the given slot.
*/
-static void prepare_break_inst(uint template, uint slot, uint major_opcode,
- unsigned long kprobe_inst, struct kprobe *p)
+static void __kprobes prepare_break_inst(uint template, uint slot,
+ uint major_opcode,
+ unsigned long kprobe_inst,
+ struct kprobe *p)
{
unsigned long break_inst = BREAK_INST;
bundle_t *bundle = &p->ainsn.insn.bundle;
@@ -271,7 +289,8 @@ static inline int in_ivt_functions(unsigned long addr)
&& addr < (unsigned long)__end_ivt_text);
}
-static int valid_kprobe_addr(int template, int slot, unsigned long addr)
+static int __kprobes valid_kprobe_addr(int template, int slot,
+ unsigned long addr)
{
if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
printk(KERN_WARNING "Attempting to insert unaligned kprobe "
@@ -323,7 +342,7 @@ static void kretprobe_trampoline(void)
* - cleanup by marking the instance as unused
* - long jump back to the original return address
*/
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
@@ -381,7 +400,8 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
{
struct kretprobe_instance *ri;
@@ -399,7 +419,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
}
}
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long) p->addr;
unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
@@ -430,7 +450,7 @@ int arch_prepare_kprobe(struct kprobe *p)
return 0;
}
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;
@@ -439,7 +459,7 @@ void arch_arm_kprobe(struct kprobe *p)
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;
@@ -449,7 +469,7 @@ void arch_disarm_kprobe(struct kprobe *p)
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}
@@ -461,7 +481,7 @@ void arch_remove_kprobe(struct kprobe *p)
* to original stack address, handle the case where we need to fixup the
* relative IP address and/or fixup branch register.
*/
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
@@ -528,13 +548,16 @@ turn_ss_off:
ia64_psr(regs)->ss = 0;
}
-static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
{
unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
unsigned long slot = (unsigned long)p->addr & 0xf;
- /* Update instruction pointer (IIP) and slot number (IPSR.ri) */
- regs->cr_iip = bundle_addr & ~0xFULL;
+ /* single step inline if break instruction */
+ if (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)
+ regs->cr_iip = (unsigned long)p->addr & ~0xFULL;
+ else
+ regs->cr_iip = bundle_addr & ~0xFULL;
if (slot > 2)
slot = 0;
@@ -545,7 +568,39 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
ia64_psr(regs)->ss = 1;
}
-static int pre_kprobes_handler(struct die_args *args)
+static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
+{
+ unsigned int slot = ia64_psr(regs)->ri;
+ unsigned int template, major_opcode;
+ unsigned long kprobe_inst;
+ unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
+ bundle_t bundle;
+
+ memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
+ template = bundle.quad0.template;
+
+ /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+ if (slot == 1 && bundle_encoding[template][1] == L)
+ slot++;
+
+ /* Get Kprobe probe instruction at given slot*/
+ get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);
+
+ /* For break instruction,
+ * Bits 37:40 Major opcode to be zero
+ * Bits 27:32 X6 to be zero
+ * Bits 32:35 X3 to be zero
+ */
+ if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
+ /* Not a break instruction */
+ return 0;
+ }
+
+ /* Is a break instruction */
+ return 1;
+}
+
+static int __kprobes pre_kprobes_handler(struct die_args *args)
{
struct kprobe *p;
int ret = 0;
@@ -558,7 +613,9 @@ static int pre_kprobes_handler(struct die_args *args)
if (kprobe_running()) {
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS) {
+ if ( (kprobe_status == KPROBE_HIT_SS) &&
+ (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
+ ia64_psr(regs)->ss = 0;
unlock_kprobes();
goto no_kprobe;
}
@@ -592,6 +649,19 @@ static int pre_kprobes_handler(struct die_args *args)
p = get_kprobe(addr);
if (!p) {
unlock_kprobes();
+ if (!is_ia64_break_inst(regs)) {
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+ * either a probepoint or a debugger breakpoint
+ * at this address. In either case, no further
+ * handling of this interrupt is appropriate.
+ */
+ ret = 1;
+
+ }
+
+ /* Not one of our break, let kernel handle it */
goto no_kprobe;
}
@@ -616,7 +686,7 @@ no_kprobe:
return ret;
}
-static int post_kprobes_handler(struct pt_regs *regs)
+static int __kprobes post_kprobes_handler(struct pt_regs *regs)
{
if (!kprobe_running())
return 0;
@@ -641,7 +711,7 @@ out:
return 1;
}
-static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
{
if (!kprobe_running())
return 0;
@@ -659,8 +729,8 @@ static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
return 0;
}
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
- void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
switch(val) {
@@ -681,7 +751,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
return NOTIFY_DONE;
}
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
@@ -703,7 +773,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
*regs = jprobe_saved_regs;
return 1;
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 4ebbf3974381..6dc726ad7137 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -48,6 +48,9 @@
* Delete dead variables and functions.
* Reorder to remove the need for forward declarations and to consolidate
* related code.
+ *
+ * 2005-08-12 Keith Owens <kaos@sgi.com>
+ * Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
*/
#include <linux/config.h>
#include <linux/types.h>
@@ -77,6 +80,8 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
+#include "entry.h"
+
#if defined(IA64_MCA_DEBUG_INFO)
# define IA64_MCA_DEBUG(fmt...) printk(fmt)
#else
@@ -84,9 +89,7 @@
#endif
/* Used by mca_asm.S */
-ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state;
-ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state;
-u64 ia64_mca_serialize;
+u32 ia64_mca_serialize;
DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */
@@ -95,8 +98,10 @@ DEFINE_PER_CPU(u64, ia64_mca_pal_base); /* vaddr PAL code granule */
unsigned long __per_cpu_mca[NR_CPUS];
/* In mca_asm.S */
-extern void ia64_monarch_init_handler (void);
-extern void ia64_slave_init_handler (void);
+extern void ia64_os_init_dispatch_monarch (void);
+extern void ia64_os_init_dispatch_slave (void);
+
+static int monarch_cpu = -1;
static ia64_mc_info_t ia64_mc_info;
@@ -234,7 +239,8 @@ ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
* This function retrieves a specified error record type from SAL
* and wakes up any processes waiting for error records.
*
- * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT)
+ * Inputs : sal_info_type (Type of error record MCA/CMC/CPE)
+ * FIXME: remove MCA and irq_safe.
*/
static void
ia64_mca_log_sal_error_record(int sal_info_type)
@@ -242,7 +248,7 @@ ia64_mca_log_sal_error_record(int sal_info_type)
u8 *buffer;
sal_log_record_header_t *rh;
u64 size;
- int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;
+ int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA;
#ifdef IA64_MCA_DEBUG_INFO
static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
#endif
@@ -330,191 +336,6 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
#endif /* CONFIG_ACPI */
-static void
-show_min_state (pal_min_state_area_t *minstate)
-{
- u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri;
- u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri;
-
- printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits);
- printk("pr\t\t%016lx\n", minstate->pmsa_pr);
- printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0);
- printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc);
- printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip);
- printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr);
- printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs);
- printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip);
- printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr);
- printk("xfs\t\t%016lx\n", minstate->pmsa_xfs);
- printk("b1\t\t%016lx ", minstate->pmsa_br1);
- print_symbol("%s\n", minstate->pmsa_br1);
-
- printk("\nstatic registers r0-r15:\n");
- printk(" r0- 3 %016lx %016lx %016lx %016lx\n",
- 0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]);
- printk(" r4- 7 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_gr[3], minstate->pmsa_gr[4],
- minstate->pmsa_gr[5], minstate->pmsa_gr[6]);
- printk(" r8-11 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_gr[7], minstate->pmsa_gr[8],
- minstate->pmsa_gr[9], minstate->pmsa_gr[10]);
- printk("r12-15 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_gr[11], minstate->pmsa_gr[12],
- minstate->pmsa_gr[13], minstate->pmsa_gr[14]);
-
- printk("\nbank 0:\n");
- printk("r16-19 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1],
- minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]);
- printk("r20-23 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5],
- minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]);
- printk("r24-27 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9],
- minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]);
- printk("r28-31 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13],
- minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]);
-
- printk("\nbank 1:\n");
- printk("r16-19 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1],
- minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]);
- printk("r20-23 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5],
- minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]);
- printk("r24-27 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9],
- minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]);
- printk("r28-31 %016lx %016lx %016lx %016lx\n",
- minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13],
- minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]);
-}
-
-static void
-fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw)
-{
- u64 *dst_banked, *src_banked, bit, shift, nat_bits;
- int i;
-
- /*
- * First, update the pt-regs and switch-stack structures with the contents stored
- * in the min-state area:
- */
- if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) {
- pt->cr_ipsr = ms->pmsa_xpsr;
- pt->cr_iip = ms->pmsa_xip;
- pt->cr_ifs = ms->pmsa_xfs;
- } else {
- pt->cr_ipsr = ms->pmsa_ipsr;
- pt->cr_iip = ms->pmsa_iip;
- pt->cr_ifs = ms->pmsa_ifs;
- }
- pt->ar_rsc = ms->pmsa_rsc;
- pt->pr = ms->pmsa_pr;
- pt->r1 = ms->pmsa_gr[0];
- pt->r2 = ms->pmsa_gr[1];
- pt->r3 = ms->pmsa_gr[2];
- sw->r4 = ms->pmsa_gr[3];
- sw->r5 = ms->pmsa_gr[4];
- sw->r6 = ms->pmsa_gr[5];
- sw->r7 = ms->pmsa_gr[6];
- pt->r8 = ms->pmsa_gr[7];
- pt->r9 = ms->pmsa_gr[8];
- pt->r10 = ms->pmsa_gr[9];
- pt->r11 = ms->pmsa_gr[10];
- pt->r12 = ms->pmsa_gr[11];
- pt->r13 = ms->pmsa_gr[12];
- pt->r14 = ms->pmsa_gr[13];
- pt->r15 = ms->pmsa_gr[14];
- dst_banked = &pt->r16; /* r16-r31 are contiguous in struct pt_regs */
- src_banked = ms->pmsa_bank1_gr;
- for (i = 0; i < 16; ++i)
- dst_banked[i] = src_banked[i];
- pt->b0 = ms->pmsa_br0;
- sw->b1 = ms->pmsa_br1;
-
- /* construct the NaT bits for the pt-regs structure: */
-# define PUT_NAT_BIT(dst, addr) \
- do { \
- bit = nat_bits & 1; nat_bits >>= 1; \
- shift = ((unsigned long) addr >> 3) & 0x3f; \
- dst = ((dst) & ~(1UL << shift)) | (bit << shift); \
- } while (0)
-
- /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */
- shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f;
- nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift));
-
- PUT_NAT_BIT(sw->caller_unat, &pt->r1);
- PUT_NAT_BIT(sw->caller_unat, &pt->r2);
- PUT_NAT_BIT(sw->caller_unat, &pt->r3);
- PUT_NAT_BIT(sw->ar_unat, &sw->r4);
- PUT_NAT_BIT(sw->ar_unat, &sw->r5);
- PUT_NAT_BIT(sw->ar_unat, &sw->r6);
- PUT_NAT_BIT(sw->ar_unat, &sw->r7);
- PUT_NAT_BIT(sw->caller_unat, &pt->r8); PUT_NAT_BIT(sw->caller_unat, &pt->r9);
- PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11);
- PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13);
- PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15);
- nat_bits >>= 16; /* skip over bank0 NaT bits */
- PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17);
- PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19);
- PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21);
- PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23);
- PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25);
- PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27);
- PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29);
- PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31);
-}
-
-static void
-init_handler_platform (pal_min_state_area_t *ms,
- struct pt_regs *pt, struct switch_stack *sw)
-{
- struct unw_frame_info info;
-
- /* if a kernel debugger is available call it here else just dump the registers */
-
- /*
- * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be
- * generated via the BMC's command-line interface, but since the console is on the
- * same serial line, the user will need some time to switch out of the BMC before
- * the dump begins.
- */
- printk("Delaying for 5 seconds...\n");
- udelay(5*1000000);
- show_min_state(ms);
-
- printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);
- fetch_min_state(ms, pt, sw);
- unw_init_from_interruption(&info, current, pt, sw);
- ia64_do_show_stack(&info, NULL);
-
-#ifdef CONFIG_SMP
- /* read_trylock() would be handy... */
- if (!tasklist_lock.write_lock)
- read_lock(&tasklist_lock);
-#endif
- {
- struct task_struct *g, *t;
- do_each_thread (g, t) {
- if (t == current)
- continue;
-
- printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
- show_stack(t, NULL);
- } while_each_thread (g, t);
- }
-#ifdef CONFIG_SMP
- if (!tasklist_lock.write_lock)
- read_unlock(&tasklist_lock);
-#endif
-
- printk("\nINIT dump complete. Please reboot now.\n");
- while (1); /* hang city if no debugger */
-}
-
#ifdef CONFIG_ACPI
/*
* ia64_mca_register_cpev
@@ -657,42 +478,6 @@ ia64_mca_cmc_vector_enable_keventd(void *unused)
}
/*
- * ia64_mca_wakeup_ipi_wait
- *
- * Wait for the inter-cpu interrupt to be sent by the
- * monarch processor once it is done with handling the
- * MCA.
- *
- * Inputs : None
- * Outputs : None
- */
-static void
-ia64_mca_wakeup_ipi_wait(void)
-{
- int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
- int irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
- u64 irr = 0;
-
- do {
- switch(irr_num) {
- case 0:
- irr = ia64_getreg(_IA64_REG_CR_IRR0);
- break;
- case 1:
- irr = ia64_getreg(_IA64_REG_CR_IRR1);
- break;
- case 2:
- irr = ia64_getreg(_IA64_REG_CR_IRR2);
- break;
- case 3:
- irr = ia64_getreg(_IA64_REG_CR_IRR3);
- break;
- }
- cpu_relax();
- } while (!(irr & (1UL << irr_bit))) ;
-}
-
-/*
* ia64_mca_wakeup
*
* Send an inter-cpu interrupt to wake-up a particular cpu
@@ -757,11 +542,9 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
*/
ia64_sal_mc_rendez();
- /* Wait for the wakeup IPI from the monarch
- * This waiting is done by polling on the wakeup-interrupt
- * vector bit in the processor's IRRs
- */
- ia64_mca_wakeup_ipi_wait();
+ /* Wait for the monarch cpu to exit. */
+ while (monarch_cpu != -1)
+ cpu_relax(); /* spin until monarch leaves */
/* Enable all interrupts */
local_irq_restore(flags);
@@ -789,53 +572,13 @@ ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
return IRQ_HANDLED;
}
-/*
- * ia64_return_to_sal_check
- *
- * This is function called before going back from the OS_MCA handler
- * to the OS_MCA dispatch code which finally takes the control back
- * to the SAL.
- * The main purpose of this routine is to setup the OS_MCA to SAL
- * return state which can be used by the OS_MCA dispatch code
- * just before going back to SAL.
- *
- * Inputs : None
- * Outputs : None
- */
-
-static void
-ia64_return_to_sal_check(int recover)
-{
-
- /* Copy over some relevant stuff from the sal_to_os_mca_handoff
- * so that it can be used at the time of os_mca_to_sal_handoff
- */
- ia64_os_to_sal_handoff_state.imots_sal_gp =
- ia64_sal_to_os_handoff_state.imsto_sal_gp;
-
- ia64_os_to_sal_handoff_state.imots_sal_check_ra =
- ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
-
- if (recover)
- ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
- else
- ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
-
- /* Default = tell SAL to return to same context */
- ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
-
- ia64_os_to_sal_handoff_state.imots_new_min_state =
- (u64 *)ia64_sal_to_os_handoff_state.pal_min_state;
-
-}
-
/* Function pointer for extra MCA recovery */
int (*ia64_mca_ucmc_extension)
- (void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*)
+ (void*,struct ia64_sal_os_state*)
= NULL;
int
-ia64_reg_MCA_extension(void *fn)
+ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *))
{
if (ia64_mca_ucmc_extension)
return 1;
@@ -854,8 +597,321 @@ ia64_unreg_MCA_extension(void)
EXPORT_SYMBOL(ia64_reg_MCA_extension);
EXPORT_SYMBOL(ia64_unreg_MCA_extension);
+
+static inline void
+copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
+{
+ u64 fslot, tslot, nat;
+ *tr = *fr;
+ fslot = ((unsigned long)fr >> 3) & 63;
+ tslot = ((unsigned long)tr >> 3) & 63;
+ *tnat &= ~(1UL << tslot);
+ nat = (fnat >> fslot) & 1;
+ *tnat |= (nat << tslot);
+}
+
+/* On entry to this routine, we are running on the per cpu stack, see
+ * mca_asm.h. The original stack has not been touched by this event. Some of
+ * the original stack's registers will be in the RBS on this stack. This stack
+ * also contains a partial pt_regs and switch_stack, the rest of the data is in
+ * PAL minstate.
+ *
+ * The first thing to do is modify the original stack to look like a blocked
+ * task so we can run backtrace on the original task. Also mark the per cpu
+ * stack as current to ensure that we use the correct task state, it also means
+ * that we can do backtrace on the MCA/INIT handler code itself.
+ */
+
+static task_t *
+ia64_mca_modify_original_stack(struct pt_regs *regs,
+ const struct switch_stack *sw,
+ struct ia64_sal_os_state *sos,
+ const char *type)
+{
+ char *p, comm[sizeof(current->comm)];
+ ia64_va va;
+ extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */
+ const pal_min_state_area_t *ms = sos->pal_min_state;
+ task_t *previous_current;
+ struct pt_regs *old_regs;
+ struct switch_stack *old_sw;
+ unsigned size = sizeof(struct pt_regs) +
+ sizeof(struct switch_stack) + 16;
+ u64 *old_bspstore, *old_bsp;
+ u64 *new_bspstore, *new_bsp;
+ u64 old_unat, old_rnat, new_rnat, nat;
+ u64 slots, loadrs = regs->loadrs;
+ u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
+ u64 ar_bspstore = regs->ar_bspstore;
+ u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);
+ const u64 *bank;
+ const char *msg;
+ int cpu = smp_processor_id();
+
+ previous_current = curr_task(cpu);
+ set_curr_task(cpu, current);
+ if ((p = strchr(current->comm, ' ')))
+ *p = '\0';
+
+ /* Best effort attempt to cope with MCA/INIT delivered while in
+ * physical mode.
+ */
+ regs->cr_ipsr = ms->pmsa_ipsr;
+ if (ia64_psr(regs)->dt == 0) {
+ va.l = r12;
+ if (va.f.reg == 0) {
+ va.f.reg = 7;
+ r12 = va.l;
+ }
+ va.l = r13;
+ if (va.f.reg == 0) {
+ va.f.reg = 7;
+ r13 = va.l;
+ }
+ }
+ if (ia64_psr(regs)->rt == 0) {
+ va.l = ar_bspstore;
+ if (va.f.reg == 0) {
+ va.f.reg = 7;
+ ar_bspstore = va.l;
+ }
+ va.l = ar_bsp;
+ if (va.f.reg == 0) {
+ va.f.reg = 7;
+ ar_bsp = va.l;
+ }
+ }
+
+ /* mca_asm.S ia64_old_stack() cannot assume that the dirty registers
+ * have been copied to the old stack, the old stack may fail the
+ * validation tests below. So ia64_old_stack() must restore the dirty
+ * registers from the new stack. The old and new bspstore probably
+ * have different alignments, so loadrs calculated on the old bsp
+ * cannot be used to restore from the new bsp. Calculate a suitable
+ * loadrs for the new stack and save it in the new pt_regs, where
+ * ia64_old_stack() can get it.
+ */
+ old_bspstore = (u64 *)ar_bspstore;
+ old_bsp = (u64 *)ar_bsp;
+ slots = ia64_rse_num_regs(old_bspstore, old_bsp);
+ new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET);
+ new_bsp = ia64_rse_skip_regs(new_bspstore, slots);
+ regs->loadrs = (new_bsp - new_bspstore) * 8 << 16;
+
+ /* Verify the previous stack state before we change it */
+ if (user_mode(regs)) {
+ msg = "occurred in user space";
+ goto no_mod;
+ }
+ if (r13 != sos->prev_IA64_KR_CURRENT) {
+ msg = "inconsistent previous current and r13";
+ goto no_mod;
+ }
+ if ((r12 - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent r12 and r13";
+ goto no_mod;
+ }
+ if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent ar.bspstore and r13";
+ goto no_mod;
+ }
+ va.p = old_bspstore;
+ if (va.f.reg < 5) {
+ msg = "old_bspstore is in the wrong region";
+ goto no_mod;
+ }
+ if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent ar.bsp and r13";
+ goto no_mod;
+ }
+ size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;
+ if (ar_bspstore + size > r12) {
+ msg = "no room for blocked state";
+ goto no_mod;
+ }
+
+ /* Change the comm field on the MCA/INT task to include the pid that
+ * was interrupted, it makes for easier debugging. If that pid was 0
+ * (swapper or nested MCA/INIT) then use the start of the previous comm
+ * field suffixed with its cpu.
+ */
+ if (previous_current->pid)
+ snprintf(comm, sizeof(comm), "%s %d",
+ current->comm, previous_current->pid);
+ else {
+ int l;
+ if ((p = strchr(previous_current->comm, ' ')))
+ l = p - previous_current->comm;
+ else
+ l = strlen(previous_current->comm);
+ snprintf(comm, sizeof(comm), "%s %*s %d",
+ current->comm, l, previous_current->comm,
+ previous_current->thread_info->cpu);
+ }
+ memcpy(current->comm, comm, sizeof(current->comm));
+
+ /* Make the original task look blocked. First stack a struct pt_regs,
+ * describing the state at the time of interrupt. mca_asm.S built a
+ * partial pt_regs, copy it and fill in the blanks using minstate.
+ */
+ p = (char *)r12 - sizeof(*regs);
+ old_regs = (struct pt_regs *)p;
+ memcpy(old_regs, regs, sizeof(*regs));
+ /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
+ * pmsa_{xip,xpsr,xfs}
+ */
+ if (ia64_psr(regs)->ic) {
+ old_regs->cr_iip = ms->pmsa_iip;
+ old_regs->cr_ipsr = ms->pmsa_ipsr;
+ old_regs->cr_ifs = ms->pmsa_ifs;
+ } else {
+ old_regs->cr_iip = ms->pmsa_xip;
+ old_regs->cr_ipsr = ms->pmsa_xpsr;
+ old_regs->cr_ifs = ms->pmsa_xfs;
+ }
+ old_regs->pr = ms->pmsa_pr;
+ old_regs->b0 = ms->pmsa_br0;
+ old_regs->loadrs = loadrs;
+ old_regs->ar_rsc = ms->pmsa_rsc;
+ old_unat = old_regs->ar_unat;
+ copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &old_regs->r1, &old_unat);
+ copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &old_regs->r2, &old_unat);
+ copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &old_regs->r3, &old_unat);
+ copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &old_regs->r8, &old_unat);
+ copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &old_regs->r9, &old_unat);
+ copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &old_regs->r10, &old_unat);
+ copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &old_regs->r11, &old_unat);
+ copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &old_regs->r12, &old_unat);
+ copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &old_regs->r13, &old_unat);
+ copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &old_regs->r14, &old_unat);
+ copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &old_regs->r15, &old_unat);
+ if (ia64_psr(old_regs)->bn)
+ bank = ms->pmsa_bank1_gr;
+ else
+ bank = ms->pmsa_bank0_gr;
+ copy_reg(&bank[16-16], ms->pmsa_nat_bits, &old_regs->r16, &old_unat);
+ copy_reg(&bank[17-16], ms->pmsa_nat_bits, &old_regs->r17, &old_unat);
+ copy_reg(&bank[18-16], ms->pmsa_nat_bits, &old_regs->r18, &old_unat);
+ copy_reg(&bank[19-16], ms->pmsa_nat_bits, &old_regs->r19, &old_unat);
+ copy_reg(&bank[20-16], ms->pmsa_nat_bits, &old_regs->r20, &old_unat);
+ copy_reg(&bank[21-16], ms->pmsa_nat_bits, &old_regs->r21, &old_unat);
+ copy_reg(&bank[22-16], ms->pmsa_nat_bits, &old_regs->r22, &old_unat);
+ copy_reg(&bank[23-16], ms->pmsa_nat_bits, &old_regs->r23, &old_unat);
+ copy_reg(&bank[24-16], ms->pmsa_nat_bits, &old_regs->r24, &old_unat);
+ copy_reg(&bank[25-16], ms->pmsa_nat_bits, &old_regs->r25, &old_unat);
+ copy_reg(&bank[26-16], ms->pmsa_nat_bits, &old_regs->r26, &old_unat);
+ copy_reg(&bank[27-16], ms->pmsa_nat_bits, &old_regs->r27, &old_unat);
+ copy_reg(&bank[28-16], ms->pmsa_nat_bits, &old_regs->r28, &old_unat);
+ copy_reg(&bank[29-16], ms->pmsa_nat_bits, &old_regs->r29, &old_unat);
+ copy_reg(&bank[30-16], ms->pmsa_nat_bits, &old_regs->r30, &old_unat);
+ copy_reg(&bank[31-16], ms->pmsa_nat_bits, &old_regs->r31, &old_unat);
+
+ /* Next stack a struct switch_stack. mca_asm.S built a partial
+ * switch_stack, copy it and fill in the blanks using pt_regs and
+ * minstate.
+ *
+ * In the synthesized switch_stack, b0 points to ia64_leave_kernel,
+ * ar.pfs is set to 0.
+ *
+ * unwind.c::unw_unwind() does special processing for interrupt frames.
+ * It checks if the PRED_NON_SYSCALL predicate is set, if the predicate
+ * is clear then unw_unwind() does _not_ adjust bsp over pt_regs. Not
+ * that this is documented, of course. Set PRED_NON_SYSCALL in the
+ * switch_stack on the original stack so it will unwind correctly when
+ * unwind.c reads pt_regs.
+ *
+ * thread.ksp is updated to point to the synthesized switch_stack.
+ */
+ p -= sizeof(struct switch_stack);
+ old_sw = (struct switch_stack *)p;
+ memcpy(old_sw, sw, sizeof(*sw));
+ old_sw->caller_unat = old_unat;
+ old_sw->ar_fpsr = old_regs->ar_fpsr;
+ copy_reg(&ms->pmsa_gr[4-1], ms->pmsa_nat_bits, &old_sw->r4, &old_unat);
+ copy_reg(&ms->pmsa_gr[5-1], ms->pmsa_nat_bits, &old_sw->r5, &old_unat);
+ copy_reg(&ms->pmsa_gr[6-1], ms->pmsa_nat_bits, &old_sw->r6, &old_unat);
+ copy_reg(&ms->pmsa_gr[7-1], ms->pmsa_nat_bits, &old_sw->r7, &old_unat);
+ old_sw->b0 = (u64)ia64_leave_kernel;
+ old_sw->b1 = ms->pmsa_br1;
+ old_sw->ar_pfs = 0;
+ old_sw->ar_unat = old_unat;
+ old_sw->pr = old_regs->pr | (1UL << PRED_NON_SYSCALL);
+ previous_current->thread.ksp = (u64)p - 16;
+
+ /* Finally copy the original stack's registers back to its RBS.
+ * Registers from ar.bspstore through ar.bsp at the time of the event
+ * are in the current RBS, copy them back to the original stack. The
+ * copy must be done register by register because the original bspstore
+ * and the current one have different alignments, so the saved RNAT
+ * data occurs at different places.
+ *
+ * mca_asm does cover, so the old_bsp already includes all registers at
+ * the time of MCA/INIT. It also does flushrs, so all registers before
+ * this function have been written to backing store on the MCA/INIT
+ * stack.
+ */
+ new_rnat = ia64_get_rnat(ia64_rse_rnat_addr(new_bspstore));
+ old_rnat = regs->ar_rnat;
+ while (slots--) {
+ if (ia64_rse_is_rnat_slot(new_bspstore)) {
+ new_rnat = ia64_get_rnat(new_bspstore++);
+ }
+ if (ia64_rse_is_rnat_slot(old_bspstore)) {
+ *old_bspstore++ = old_rnat;
+ old_rnat = 0;
+ }
+ nat = (new_rnat >> ia64_rse_slot_num(new_bspstore)) & 1UL;
+ old_rnat &= ~(1UL << ia64_rse_slot_num(old_bspstore));
+ old_rnat |= (nat << ia64_rse_slot_num(old_bspstore));
+ *old_bspstore++ = *new_bspstore++;
+ }
+ old_sw->ar_bspstore = (unsigned long)old_bspstore;
+ old_sw->ar_rnat = old_rnat;
+
+ sos->prev_task = previous_current;
+ return previous_current;
+
+no_mod:
+ printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
+ smp_processor_id(), type, msg);
+ return previous_current;
+}
+
+/* The monarch/slave interaction is based on monarch_cpu and requires that all
+ * slaves have entered rendezvous before the monarch leaves. If any cpu has
+ * not entered rendezvous yet then wait a bit. The assumption is that any
+ * slave that has not rendezvoused after a reasonable time is never going to do
+ * so. In this context, slave includes cpus that respond to the MCA rendezvous
+ * interrupt, as well as cpus that receive the INIT slave event.
+ */
+
+static void
+ia64_wait_for_slaves(int monarch)
+{
+ int c, wait = 0;
+ for_each_online_cpu(c) {
+ if (c == monarch)
+ continue;
+ if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
+ udelay(1000); /* short wait first */
+ wait = 1;
+ break;
+ }
+ }
+ if (!wait)
+ return;
+ for_each_online_cpu(c) {
+ if (c == monarch)
+ continue;
+ if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
+ udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */
+ break;
+ }
+ }
+}
+
/*
- * ia64_mca_ucmc_handler
+ * ia64_mca_handler
*
* This is uncorrectable machine check handler called from OS_MCA
* dispatch code which is in turn called from SAL_CHECK().
@@ -866,16 +922,28 @@ EXPORT_SYMBOL(ia64_unreg_MCA_extension);
* further MCA logging is enabled by clearing logs.
* Monarch also has the duty of sending wakeup-IPIs to pull the
* slave processors out of rendezvous spinloop.
- *
- * Inputs : None
- * Outputs : None
*/
void
-ia64_mca_ucmc_handler(void)
+ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ struct ia64_sal_os_state *sos)
{
pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
- &ia64_sal_to_os_handoff_state.proc_state_param;
- int recover;
+ &sos->proc_state_param;
+ int recover, cpu = smp_processor_id();
+ task_t *previous_current;
+
+ oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
+ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
+ monarch_cpu = cpu;
+ ia64_wait_for_slaves(cpu);
+
+ /* Wakeup all the processors which are spinning in the rendezvous loop.
+ * They will leave SAL, then spin in the OS with interrupts disabled
+ * until this monarch cpu leaves the MCA handler. That gets control
+ * back to the OS so we can backtrace the other cpus, backtrace when
+ * spinning in SAL does not work.
+ */
+ ia64_mca_wakeup_all();
/* Get the MCA error record and log it */
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
@@ -883,25 +951,20 @@ ia64_mca_ucmc_handler(void)
/* TLB error is only exist in this SAL error record */
recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
/* other error recovery */
- || (ia64_mca_ucmc_extension
+ || (ia64_mca_ucmc_extension
&& ia64_mca_ucmc_extension(
IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
- &ia64_sal_to_os_handoff_state,
- &ia64_os_to_sal_handoff_state));
+ sos));
if (recover) {
sal_log_record_header_t *rh = IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA);
rh->severity = sal_log_severity_corrected;
ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
+ sos->os_status = IA64_MCA_CORRECTED;
}
- /*
- * Wakeup all the processors which are spinning in the rendezvous
- * loop.
- */
- ia64_mca_wakeup_all();
- /* Return to SAL */
- ia64_return_to_sal_check(recover);
+ set_curr_task(cpu, previous_current);
+ monarch_cpu = -1;
}
static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL);
@@ -1125,34 +1188,114 @@ ia64_mca_cpe_poll (unsigned long dummy)
/*
* C portion of the OS INIT handler
*
- * Called from ia64_monarch_init_handler
- *
- * Inputs: pointer to pt_regs where processor info was saved.
+ * Called from ia64_os_init_dispatch
*
- * Returns:
- * 0 if SAL must warm boot the System
- * 1 if SAL must return to interrupted context using PAL_MC_RESUME
+ * Inputs: pointer to pt_regs where processor info was saved. SAL/OS state for
+ * this event. This code is used for both monarch and slave INIT events, see
+ * sos->monarch.
*
+ * All INIT events switch to the INIT stack and change the previous process to
+ * blocked status. If one of the INIT events is the monarch then we are
+ * probably processing the nmi button/command. Use the monarch cpu to dump all
+ * the processes. The slave INIT events all spin until the monarch cpu
+ * returns. We can also get INIT slave events for MCA, in which case the MCA
+ * process is the monarch.
*/
+
void
-ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
+ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ struct ia64_sal_os_state *sos)
{
- pal_min_state_area_t *ms;
+ static atomic_t slaves;
+ static atomic_t monarchs;
+ task_t *previous_current;
+ int cpu = smp_processor_id(), c;
+ struct task_struct *g, *t;
- oops_in_progress = 1; /* avoid deadlock in printk, but it makes recovery dodgy */
+ oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
- printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
- ia64_sal_to_os_handoff_state.proc_state_param);
+ 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);
- /*
- * Address of minstate area provided by PAL is physical,
- * uncacheable (bit 63 set). Convert to Linux virtual
- * address in region 6.
+ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "INIT");
+ sos->os_status = IA64_INIT_RESUME;
+
+ /* FIXME: Workaround for broken proms that drive all INIT events as
+ * slaves. The last slave that enters is promoted to be a monarch.
+ * Remove this code in September 2006, that gives platforms a year to
+ * fix their proms and get their customers updated.
*/
- ms = (pal_min_state_area_t *)(ia64_sal_to_os_handoff_state.pal_min_state | (6ul<<61));
+ if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
+ printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
+ __FUNCTION__, cpu);
+ atomic_dec(&slaves);
+ sos->monarch = 1;
+ }
+
+ /* FIXME: Workaround for broken proms that drive all INIT events as
+ * monarchs. Second and subsequent monarchs are demoted to slaves.
+ * Remove this code in September 2006, that gives platforms a year to
+ * fix their proms and get their customers updated.
+ */
+ if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
+ printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
+ __FUNCTION__, cpu);
+ atomic_dec(&monarchs);
+ sos->monarch = 0;
+ }
- init_handler_platform(ms, pt, sw); /* call platform specific routines */
+ if (!sos->monarch) {
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
+ while (monarch_cpu == -1)
+ cpu_relax(); /* spin until monarch enters */
+ while (monarch_cpu != -1)
+ cpu_relax(); /* spin until monarch leaves */
+ printk("Slave on cpu %d returning to normal service.\n", cpu);
+ set_curr_task(cpu, previous_current);
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+ atomic_dec(&slaves);
+ return;
+ }
+
+ monarch_cpu = cpu;
+
+ /*
+ * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be
+ * generated via the BMC's command-line interface, but since the console is on the
+ * same serial line, the user will need some time to switch out of the BMC before
+ * the dump begins.
+ */
+ printk("Delaying for 5 seconds...\n");
+ udelay(5*1000000);
+ ia64_wait_for_slaves(cpu);
+ printk(KERN_ERR "Processes interrupted by INIT -");
+ for_each_online_cpu(c) {
+ struct ia64_sal_os_state *s;
+ t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);
+ s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);
+ g = s->prev_task;
+ if (g) {
+ if (g->pid)
+ printk(" %d", g->pid);
+ else
+ printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);
+ }
+ }
+ printk("\n\n");
+ if (read_trylock(&tasklist_lock)) {
+ do_each_thread (g, t) {
+ printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
+ show_stack(t, NULL);
+ } while_each_thread (g, t);
+ read_unlock(&tasklist_lock);
+ }
+ printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
+ atomic_dec(&monarchs);
+ set_curr_task(cpu, previous_current);
+ monarch_cpu = -1;
+ return;
}
static int __init
@@ -1202,6 +1345,34 @@ static struct irqaction mca_cpep_irqaction = {
};
#endif /* CONFIG_ACPI */
+/* Minimal format of the MCA/INIT stacks. The pseudo processes that run on
+ * these stacks can never sleep, they cannot return from the kernel to user
+ * space, they do not appear in a normal ps listing. So there is no need to
+ * format most of the fields.
+ */
+
+static void
+format_mca_init_stack(void *mca_data, unsigned long offset,
+ const char *type, int cpu)
+{
+ struct task_struct *p = (struct task_struct *)((char *)mca_data + offset);
+ struct thread_info *ti;
+ memset(p, 0, KERNEL_STACK_SIZE);
+ ti = (struct thread_info *)((char *)p + IA64_TASK_SIZE);
+ ti->flags = _TIF_MCA_INIT;
+ ti->preempt_count = 1;
+ ti->task = p;
+ ti->cpu = cpu;
+ p->thread_info = ti;
+ p->state = TASK_UNINTERRUPTIBLE;
+ __set_bit(cpu, &p->cpus_allowed);
+ INIT_LIST_HEAD(&p->tasks);
+ p->parent = p->real_parent = p->group_leader = p;
+ INIT_LIST_HEAD(&p->children);
+ INIT_LIST_HEAD(&p->sibling);
+ strncpy(p->comm, type, sizeof(p->comm)-1);
+}
+
/* Do per-CPU MCA-related initialization. */
void __devinit
@@ -1214,19 +1385,28 @@ ia64_mca_cpu_init(void *cpu_data)
int cpu;
mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu)
- * NR_CPUS);
+ * NR_CPUS + KERNEL_STACK_SIZE);
+ mca_data = (void *)(((unsigned long)mca_data +
+ KERNEL_STACK_SIZE - 1) &
+ (-KERNEL_STACK_SIZE));
for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ format_mca_init_stack(mca_data,
+ offsetof(struct ia64_mca_cpu, mca_stack),
+ "MCA", cpu);
+ format_mca_init_stack(mca_data,
+ offsetof(struct ia64_mca_cpu, init_stack),
+ "INIT", cpu);
__per_cpu_mca[cpu] = __pa(mca_data);
mca_data += sizeof(struct ia64_mca_cpu);
}
}
- /*
- * The MCA info structure was allocated earlier and its
- * physical address saved in __per_cpu_mca[cpu]. Copy that
- * address * to ia64_mca_data so we can access it as a per-CPU
- * variable.
- */
+ /*
+ * The MCA info structure was allocated earlier and its
+ * physical address saved in __per_cpu_mca[cpu]. Copy that
+ * address * to ia64_mca_data so we can access it as a per-CPU
+ * variable.
+ */
__get_cpu_var(ia64_mca_data) = __per_cpu_mca[smp_processor_id()];
/*
@@ -1236,11 +1416,11 @@ ia64_mca_cpu_init(void *cpu_data)
__get_cpu_var(ia64_mca_per_cpu_pte) =
pte_val(mk_pte_phys(__pa(cpu_data), PAGE_KERNEL));
- /*
- * Also, stash away a copy of the PAL address and the PTE
- * needed to map it.
- */
- pal_vaddr = efi_get_pal_addr();
+ /*
+ * Also, stash away a copy of the PAL address and the PTE
+ * needed to map it.
+ */
+ pal_vaddr = efi_get_pal_addr();
if (!pal_vaddr)
return;
__get_cpu_var(ia64_mca_pal_base) =
@@ -1272,8 +1452,8 @@ ia64_mca_cpu_init(void *cpu_data)
void __init
ia64_mca_init(void)
{
- ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
- ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
+ ia64_fptr_t *init_hldlr_ptr_monarch = (ia64_fptr_t *)ia64_os_init_dispatch_monarch;
+ ia64_fptr_t *init_hldlr_ptr_slave = (ia64_fptr_t *)ia64_os_init_dispatch_slave;
ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
int i;
s64 rc;
@@ -1351,9 +1531,9 @@ ia64_mca_init(void)
* XXX - disable SAL checksum by setting size to 0, should be
* size of the actual init handler in mca_asm.S.
*/
- ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp);
+ ia64_mc_info.imi_monarch_init_handler = ia64_tpa(init_hldlr_ptr_monarch->fp);
ia64_mc_info.imi_monarch_init_handler_size = 0;
- ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp);
+ ia64_mc_info.imi_slave_init_handler = ia64_tpa(init_hldlr_ptr_slave->fp);
ia64_mc_info.imi_slave_init_handler_size = 0;
IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__,
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index ef3fd7265b67..499a065f4e60 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -16,6 +16,9 @@
// 04/11/12 Russ Anderson <rja@sgi.com>
// Added per cpu MCA/INIT stack save areas.
//
+// 12/08/05 Keith Owens <kaos@sgi.com>
+// Use per cpu MCA/INIT stacks for all data.
+//
#include <linux/config.h>
#include <linux/threads.h>
@@ -25,96 +28,23 @@
#include <asm/mca_asm.h>
#include <asm/mca.h>
-/*
- * When we get a machine check, the kernel stack pointer is no longer
- * valid, so we need to set a new stack pointer.
- */
-#define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */
-
-/*
- * Needed for return context to SAL
- */
-#define IA64_MCA_SAME_CONTEXT 0
-#define IA64_MCA_COLD_BOOT -2
-
-#include "minstate.h"
-
-/*
- * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec)
- * 1. GR1 = OS GP
- * 2. GR8 = PAL_PROC physical address
- * 3. GR9 = SAL_PROC physical address
- * 4. GR10 = SAL GP (physical)
- * 5. GR11 = Rendez state
- * 6. GR12 = Return address to location within SAL_CHECK
- */
-#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp) \
- LOAD_PHYSICAL(p0, _tmp, ia64_sal_to_os_handoff_state);; \
- st8 [_tmp]=r1,0x08;; \
- st8 [_tmp]=r8,0x08;; \
- st8 [_tmp]=r9,0x08;; \
- st8 [_tmp]=r10,0x08;; \
- st8 [_tmp]=r11,0x08;; \
- st8 [_tmp]=r12,0x08;; \
- st8 [_tmp]=r17,0x08;; \
- st8 [_tmp]=r18,0x08
-
-/*
- * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)
- * (p6) is executed if we never entered virtual mode (TLB error)
- * (p7) is executed if we entered virtual mode as expected (normal case)
- * 1. GR8 = OS_MCA return status
- * 2. GR9 = SAL GP (physical)
- * 3. GR10 = 0/1 returning same/new context
- * 4. GR22 = New min state save area pointer
- * returns ptr to SAL rtn save loc in _tmp
- */
-#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \
- movl _tmp=ia64_os_to_sal_handoff_state;; \
- DATA_VA_TO_PA(_tmp);; \
- ld8 r8=[_tmp],0x08;; \
- ld8 r9=[_tmp],0x08;; \
- ld8 r10=[_tmp],0x08;; \
- ld8 r22=[_tmp],0x08;;
- // now _tmp is pointing to SAL rtn save location
-
-/*
- * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state
- * imots_os_status=IA64_MCA_COLD_BOOT
- * imots_sal_gp=SAL GP
- * imots_context=IA64_MCA_SAME_CONTEXT
- * imots_new_min_state=Min state save area pointer
- * imots_sal_check_ra=Return address to location within SAL_CHECK
- *
- */
-#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\
- movl tmp=IA64_MCA_COLD_BOOT; \
- movl sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state); \
- movl os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);; \
- st8 [os_to_sal_handoff]=tmp,8;; \
- ld8 tmp=[sal_to_os_handoff],48;; \
- st8 [os_to_sal_handoff]=tmp,8;; \
- movl tmp=IA64_MCA_SAME_CONTEXT;; \
- st8 [os_to_sal_handoff]=tmp,8;; \
- ld8 tmp=[sal_to_os_handoff],-8;; \
- st8 [os_to_sal_handoff]=tmp,8;; \
- ld8 tmp=[sal_to_os_handoff];; \
- st8 [os_to_sal_handoff]=tmp;;
+#include "entry.h"
#define GET_IA64_MCA_DATA(reg) \
GET_THIS_PADDR(reg, ia64_mca_data) \
;; \
ld8 reg=[reg]
- .global ia64_os_mca_dispatch
- .global ia64_os_mca_dispatch_end
- .global ia64_sal_to_os_handoff_state
- .global ia64_os_to_sal_handoff_state
.global ia64_do_tlb_purge
+ .global ia64_os_mca_dispatch
+ .global ia64_os_init_dispatch_monarch
+ .global ia64_os_init_dispatch_slave
.text
.align 16
+//StartMain////////////////////////////////////////////////////////////////////
+
/*
* Just the TLB purge part is moved to a separate function
* so we can re-use the code for cpu hotplug code as well
@@ -207,34 +137,31 @@ ia64_do_tlb_purge:
br.sptk.many b1
;;
-ia64_os_mca_dispatch:
+//EndMain//////////////////////////////////////////////////////////////////////
+
+//StartMain////////////////////////////////////////////////////////////////////
+ia64_os_mca_dispatch:
// Serialize all MCA processing
mov r3=1;;
LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
ia64_os_mca_spin:
- xchg8 r4=[r2],r3;;
+ xchg4 r4=[r2],r3;;
cmp.ne p6,p0=r4,r0
(p6) br ia64_os_mca_spin
- // Save the SAL to OS MCA handoff state as defined
- // by SAL SPEC 3.0
- // NOTE : The order in which the state gets saved
- // is dependent on the way the C-structure
- // for ia64_mca_sal_to_os_state_t has been
- // defined in include/asm/mca.h
- SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
- ;;
-
- // LOG PROCESSOR STATE INFO FROM HERE ON..
-begin_os_mca_dump:
- br ia64_os_mca_proc_state_dump;;
+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ mov r19=1 // All MCA events are treated as monarch (for now)
+ br.sptk ia64_state_save // save the state that is not in minstate
+1:
-ia64_os_mca_done_dump:
-
- LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
+ GET_IA64_MCA_DATA(r2)
+ // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param
+ ;;
+ add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2
;;
- ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK.
+ ld8 r18=[r3] // Get processor state parameter on existing PALE_CHECK.
;;
tbit.nz p6,p7=r18,60
(p7) br.spnt done_tlb_purge_and_reload
@@ -323,624 +250,775 @@ ia64_reload_tr:
itr.d dtr[r20]=r16
;;
srlz.d
- ;;
- br.sptk.many done_tlb_purge_and_reload
-err:
- COLD_BOOT_HANDOFF_STATE(r20,r21,r22)
- br.sptk.many ia64_os_mca_done_restore
done_tlb_purge_and_reload:
- // Setup new stack frame for OS_MCA handling
- GET_IA64_MCA_DATA(r2)
- ;;
- add r3 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2
- add r2 = IA64_MCA_CPU_RBSTORE_OFFSET, r2
- ;;
- rse_switch_context(r6,r3,r2);; // RSC management in this new context
+ // switch to per cpu MCA stack
+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_new_stack
+1:
+
+ // everything saved, now we can set the kernel registers
+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_set_kernel_registers
+1:
+ // This must be done in physical mode
GET_IA64_MCA_DATA(r2)
;;
- add r2 = IA64_MCA_CPU_STACK_OFFSET+IA64_MCA_STACK_SIZE-16, r2
- ;;
- mov r12=r2 // establish new stack-pointer
+ mov r7=r2
// Enter virtual mode from physical mode
VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
-ia64_os_mca_virtual_begin:
+
+ // This code returns to SAL via SOS r2, in general SAL has no unwind
+ // data. To get a clean termination when backtracing the C MCA/INIT
+ // handler, set a dummy return address of 0 in this routine. That
+ // requires that ia64_os_mca_virtual_begin be a global function.
+ENTRY(ia64_os_mca_virtual_begin)
+ .prologue
+ .save rp,r0
+ .body
+
+ mov ar.rsc=3 // set eager mode for C handler
+ mov r2=r7 // see GET_IA64_MCA_DATA above
+ ;;
// Call virtual mode handler
- movl r2=ia64_mca_ucmc_handler;;
- mov b6=r2;;
- br.call.sptk.many b0=b6;;
-.ret0:
+ alloc r14=ar.pfs,0,0,3,0
+ ;;
+ DATA_PA_TO_VA(r2,r7)
+ ;;
+ add out0=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
+ add out1=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
+ add out2=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET, r2
+ br.call.sptk.many b0=ia64_mca_handler
+
// Revert back to physical mode before going back to SAL
PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
ia64_os_mca_virtual_end:
- // restore the original stack frame here
+END(ia64_os_mca_virtual_begin)
+
+ // switch back to previous stack
+ alloc r14=ar.pfs,0,0,0,0 // remove the MCA handler frame
+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_old_stack
+1:
+
+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_state_restore // restore the SAL state
+1:
+
+ mov b0=r12 // SAL_CHECK return address
+
+ // release lock
+ LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;
+ st4.rel [r3]=r0
+
+ br b0
+
+//EndMain//////////////////////////////////////////////////////////////////////
+
+//StartMain////////////////////////////////////////////////////////////////////
+
+//
+// SAL to OS entry point for INIT on all processors. This has been defined for
+// registration purposes with SAL as a part of ia64_mca_init. Monarch and
+// slave INIT have identical processing, except for the value of the
+// sos->monarch flag in r19.
+//
+
+ia64_os_init_dispatch_monarch:
+ mov r19=1 // Bow, bow, ye lower middle classes!
+ br.sptk ia64_os_init_dispatch
+
+ia64_os_init_dispatch_slave:
+ mov r19=0 // <igor>yeth, mathter</igor>
+
+ia64_os_init_dispatch:
+
+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_state_save // save the state that is not in minstate
+1:
+
+ // switch to per cpu INIT stack
+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_new_stack
+1:
+
+ // everything saved, now we can set the kernel registers
+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_set_kernel_registers
+1:
+
+ // This must be done in physical mode
GET_IA64_MCA_DATA(r2)
;;
- add r2 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2
- ;;
- movl r4=IA64_PSR_MC
+ mov r7=r2
+
+ // Enter virtual mode from physical mode
+ VIRTUAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_begin, r4)
+
+ // This code returns to SAL via SOS r2, in general SAL has no unwind
+ // data. To get a clean termination when backtracing the C MCA/INIT
+ // handler, set a dummy return address of 0 in this routine. That
+ // requires that ia64_os_init_virtual_begin be a global function.
+ENTRY(ia64_os_init_virtual_begin)
+ .prologue
+ .save rp,r0
+ .body
+
+ mov ar.rsc=3 // set eager mode for C handler
+ mov r2=r7 // see GET_IA64_MCA_DATA above
;;
- rse_return_context(r4,r3,r2) // switch from interrupt context for RSE
- // let us restore all the registers from our PSI structure
- mov r8=gp
+ // Call virtual mode handler
+ alloc r14=ar.pfs,0,0,3,0
+ ;;
+ DATA_PA_TO_VA(r2,r7)
;;
-begin_os_mca_restore:
- br ia64_os_mca_proc_state_restore;;
+ add out0=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
+ add out1=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
+ add out2=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SOS_OFFSET, r2
+ br.call.sptk.many b0=ia64_init_handler
-ia64_os_mca_done_restore:
- OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);;
- // branch back to SALE_CHECK
- ld8 r3=[r2];;
- mov b0=r3;; // SAL_CHECK return address
+ // Revert back to physical mode before going back to SAL
+ PHYSICAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_end, r4)
+ia64_os_init_virtual_end:
- // release lock
- movl r3=ia64_mca_serialize;;
- DATA_VA_TO_PA(r3);;
- st8.rel [r3]=r0
+END(ia64_os_init_virtual_begin)
+
+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_state_restore // restore the SAL state
+1:
+ // switch back to previous stack
+ alloc r14=ar.pfs,0,0,0,0 // remove the INIT handler frame
+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack
+ LOAD_PHYSICAL(p0,r2,1f) // return address
+ br.sptk ia64_old_stack
+1:
+
+ mov b0=r12 // SAL_CHECK return address
br b0
- ;;
-ia64_os_mca_dispatch_end:
+
//EndMain//////////////////////////////////////////////////////////////////////
+// common defines for the stubs
+#define ms r4
+#define regs r5
+#define temp1 r2 /* careful, it overlaps with input registers */
+#define temp2 r3 /* careful, it overlaps with input registers */
+#define temp3 r7
+#define temp4 r14
+
//++
// Name:
-// ia64_os_mca_proc_state_dump()
+// ia64_state_save()
//
// Stub Description:
//
-// This stub dumps the processor state during MCHK to a data area
+// Save the state that is not in minstate. This is sensitive to the layout of
+// struct ia64_sal_os_state in mca.h.
+//
+// r2 contains the return address, r3 contains either
+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+// The OS to SAL section of struct ia64_sal_os_state is set to a default
+// value of cold boot (MCA) or warm boot (INIT) and return to the same
+// context. ia64_sal_os_state is also used to hold some registers that
+// need to be saved and restored across the stack switches.
+//
+// Most input registers to this stub come from PAL/SAL
+// r1 os gp, physical
+// r8 pal_proc entry point
+// r9 sal_proc entry point
+// r10 sal gp
+// r11 MCA - rendevzous state, INIT - reason code
+// r12 sal return address
+// r17 pal min_state
+// r18 processor state parameter
+// r19 monarch flag, set by the caller of this routine
+//
+// In addition to the SAL to OS state, this routine saves all the
+// registers that appear in struct pt_regs and struct switch_stack,
+// excluding those that are already in the PAL minstate area. This
+// results in a partial pt_regs and switch_stack, the C code copies the
+// remaining registers from PAL minstate to pt_regs and switch_stack. The
+// resulting structures contain all the state of the original process when
+// MCA/INIT occurred.
//
//--
-ia64_os_mca_proc_state_dump:
-// Save bank 1 GRs 16-31 which will be used by c-language code when we switch
-// to virtual addressing mode.
- GET_IA64_MCA_DATA(r2)
+ia64_state_save:
+ add regs=MCA_SOS_OFFSET, r3
+ add ms=MCA_SOS_OFFSET+8, r3
+ mov b0=r2 // save return address
+ cmp.eq p1,p2=IA64_MCA_CPU_MCA_STACK_OFFSET, r3
+ ;;
+ GET_IA64_MCA_DATA(temp2)
+ ;;
+ add temp1=temp2, regs // struct ia64_sal_os_state on MCA or INIT stack
+ add temp2=temp2, ms // struct ia64_sal_os_state+8 on MCA or INIT stack
+ ;;
+ mov regs=temp1 // save the start of sos
+ st8 [temp1]=r1,16 // os_gp
+ st8 [temp2]=r8,16 // pal_proc
+ ;;
+ st8 [temp1]=r9,16 // sal_proc
+ st8 [temp2]=r11,16 // rv_rc
+ mov r11=cr.iipa
+ ;;
+ st8 [temp1]=r18,16 // proc_state_param
+ st8 [temp2]=r19,16 // monarch
+ mov r6=IA64_KR(CURRENT)
+ ;;
+ st8 [temp1]=r12,16 // sal_ra
+ st8 [temp2]=r10,16 // sal_gp
+ mov r12=cr.isr
+ ;;
+ st8 [temp1]=r17,16 // pal_min_state
+ st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT
+ mov r6=cr.ifa
+ ;;
+ st8 [temp1]=r0,16 // prev_task, starts off as NULL
+ st8 [temp2]=r12,16 // cr.isr
+ mov r12=cr.itir
+ ;;
+ st8 [temp1]=r6,16 // cr.ifa
+ st8 [temp2]=r12,16 // cr.itir
+ mov r12=cr.iim
+ ;;
+ st8 [temp1]=r11,16 // cr.iipa
+ st8 [temp2]=r12,16 // cr.iim
+ mov r6=cr.iha
+(p1) mov r12=IA64_MCA_COLD_BOOT
+(p2) mov r12=IA64_INIT_WARM_BOOT
+ ;;
+ st8 [temp1]=r6,16 // cr.iha
+ st8 [temp2]=r12 // os_status, default is cold boot
+ mov r6=IA64_MCA_SAME_CONTEXT
+ ;;
+ st8 [temp1]=r6 // context, default is same context
+
+ // Save the pt_regs data that is not in minstate. The previous code
+ // left regs at sos.
+ add regs=MCA_PT_REGS_OFFSET-MCA_SOS_OFFSET, regs
+ ;;
+ add temp1=PT(B6), regs
+ mov temp3=b6
+ mov temp4=b7
+ add temp2=PT(B7), regs
+ ;;
+ st8 [temp1]=temp3,PT(AR_CSD)-PT(B6) // save b6
+ st8 [temp2]=temp4,PT(AR_SSD)-PT(B7) // save b7
+ mov temp3=ar.csd
+ mov temp4=ar.ssd
+ cover // must be last in group
;;
- add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2
- ;;
-// save ar.NaT
- mov r5=ar.unat // ar.unat
-
-// save banked GRs 16-31 along with NaT bits
- bsw.1;;
- st8.spill [r2]=r16,8;;
- st8.spill [r2]=r17,8;;
- st8.spill [r2]=r18,8;;
- st8.spill [r2]=r19,8;;
- st8.spill [r2]=r20,8;;
- st8.spill [r2]=r21,8;;
- st8.spill [r2]=r22,8;;
- st8.spill [r2]=r23,8;;
- st8.spill [r2]=r24,8;;
- st8.spill [r2]=r25,8;;
- st8.spill [r2]=r26,8;;
- st8.spill [r2]=r27,8;;
- st8.spill [r2]=r28,8;;
- st8.spill [r2]=r29,8;;
- st8.spill [r2]=r30,8;;
- st8.spill [r2]=r31,8;;
-
- mov r4=ar.unat;;
- st8 [r2]=r4,8 // save User NaT bits for r16-r31
- mov ar.unat=r5 // restore original unat
- bsw.0;;
-
-//save BRs
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2 // duplicate r2 in r4
-
- mov r3=b0
- mov r5=b1
- mov r7=b2;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=b3
- mov r5=b4
- mov r7=b5;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=b6
- mov r5=b7;;
- st8 [r2]=r3,2*8
- st8 [r4]=r5,2*8;;
-
-cSaveCRs:
-// save CRs
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2 // duplicate r2 in r4
-
- mov r3=cr.dcr
- mov r5=cr.itm
- mov r7=cr.iva;;
-
- st8 [r2]=r3,8*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;; // 48 byte rements
-
- mov r3=cr.pta;;
- st8 [r2]=r3,8*8;; // 64 byte rements
-
-// if PSR.ic=0, reading interruption registers causes an illegal operation fault
- mov r3=psr;;
- tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test
-(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.
-begin_skip_intr_regs:
-(p6) br SkipIntrRegs;;
-
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2 // duplicate r2 in r6
-
- mov r3=cr.ipsr
- mov r5=cr.isr
- mov r7=r0;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=cr.iip
- mov r5=cr.ifa
- mov r7=cr.itir;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=cr.iipa
- mov r5=cr.ifs
- mov r7=cr.iim;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=cr25;; // cr.iha
- st8 [r2]=r3,160;; // 160 byte rement
-
-SkipIntrRegs:
- st8 [r2]=r0,152;; // another 152 byte .
-
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2 // duplicate r2 in r6
-
- mov r3=cr.lid
-// mov r5=cr.ivr // cr.ivr, don't read it
- mov r7=cr.tpr;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=r0 // cr.eoi => cr67
- mov r5=r0 // cr.irr0 => cr68
- mov r7=r0;; // cr.irr1 => cr69
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=r0 // cr.irr2 => cr70
- mov r5=r0 // cr.irr3 => cr71
- mov r7=cr.itv;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=cr.pmv
- mov r5=cr.cmcv;;
- st8 [r2]=r3,7*8
- st8 [r4]=r5,7*8;;
-
- mov r3=r0 // cr.lrr0 => cr80
- mov r5=r0;; // cr.lrr1 => cr81
- st8 [r2]=r3,23*8
- st8 [r4]=r5,23*8;;
-
- adds r2=25*8,r2;;
-
-cSaveARs:
-// save ARs
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2 // duplicate r2 in r6
-
- mov r3=ar.k0
- mov r5=ar.k1
- mov r7=ar.k2;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=ar.k3
- mov r5=ar.k4
- mov r7=ar.k5;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=ar.k6
- mov r5=ar.k7
- mov r7=r0;; // ar.kr8
- st8 [r2]=r3,10*8
- st8 [r4]=r5,10*8
- st8 [r6]=r7,10*8;; // rement by 72 bytes
-
- mov r3=ar.rsc
- mov ar.rsc=r0 // put RSE in enforced lazy mode
- mov r5=ar.bsp
- ;;
- mov r7=ar.bspstore;;
- st8 [r2]=r3,3*8
- st8 [r4]=r5,3*8
- st8 [r6]=r7,3*8;;
-
- mov r3=ar.rnat;;
- st8 [r2]=r3,8*13 // increment by 13x8 bytes
-
- mov r3=ar.ccv;;
- st8 [r2]=r3,8*4
-
- mov r3=ar.unat;;
- st8 [r2]=r3,8*4
-
- mov r3=ar.fpsr;;
- st8 [r2]=r3,8*4
-
- mov r3=ar.itc;;
- st8 [r2]=r3,160 // 160
-
- mov r3=ar.pfs;;
- st8 [r2]=r3,8
-
- mov r3=ar.lc;;
- st8 [r2]=r3,8
-
- mov r3=ar.ec;;
- st8 [r2]=r3
- add r2=8*62,r2 //padding
-
-// save RRs
- mov ar.lc=0x08-1
- movl r4=0x00;;
-
-cStRR:
- dep.z r5=r4,61,3;;
- mov r3=rr[r5];;
- st8 [r2]=r3,8
- add r4=1,r4
- br.cloop.sptk.few cStRR
- ;;
-end_os_mca_dump:
- br ia64_os_mca_done_dump;;
+ st8 [temp1]=temp3,PT(AR_UNAT)-PT(AR_CSD) // save ar.csd
+ st8 [temp2]=temp4,PT(AR_PFS)-PT(AR_SSD) // save ar.ssd
+ mov temp3=ar.unat
+ mov temp4=ar.pfs
+ ;;
+ st8 [temp1]=temp3,PT(AR_RNAT)-PT(AR_UNAT) // save ar.unat
+ st8 [temp2]=temp4,PT(AR_BSPSTORE)-PT(AR_PFS) // save ar.pfs
+ mov temp3=ar.rnat
+ mov temp4=ar.bspstore
+ ;;
+ st8 [temp1]=temp3,PT(LOADRS)-PT(AR_RNAT) // save ar.rnat
+ st8 [temp2]=temp4,PT(AR_FPSR)-PT(AR_BSPSTORE) // save ar.bspstore
+ mov temp3=ar.bsp
+ ;;
+ sub temp3=temp3, temp4 // ar.bsp - ar.bspstore
+ mov temp4=ar.fpsr
+ ;;
+ shl temp3=temp3,16 // compute ar.rsc to be used for "loadrs"
+ ;;
+ st8 [temp1]=temp3,PT(AR_CCV)-PT(LOADRS) // save loadrs
+ st8 [temp2]=temp4,PT(F6)-PT(AR_FPSR) // save ar.fpsr
+ mov temp3=ar.ccv
+ ;;
+ st8 [temp1]=temp3,PT(F7)-PT(AR_CCV) // save ar.ccv
+ stf.spill [temp2]=f6,PT(F8)-PT(F6)
+ ;;
+ stf.spill [temp1]=f7,PT(F9)-PT(F7)
+ stf.spill [temp2]=f8,PT(F10)-PT(F8)
+ ;;
+ stf.spill [temp1]=f9,PT(F11)-PT(F9)
+ stf.spill [temp2]=f10
+ ;;
+ stf.spill [temp1]=f11
+
+ // Save the switch_stack data that is not in minstate nor pt_regs. The
+ // previous code left regs at pt_regs.
+ add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs
+ ;;
+ add temp1=SW(F2), regs
+ add temp2=SW(F3), regs
+ ;;
+ stf.spill [temp1]=f2,32
+ stf.spill [temp2]=f3,32
+ ;;
+ stf.spill [temp1]=f4,32
+ stf.spill [temp2]=f5,32
+ ;;
+ stf.spill [temp1]=f12,32
+ stf.spill [temp2]=f13,32
+ ;;
+ stf.spill [temp1]=f14,32
+ stf.spill [temp2]=f15,32
+ ;;
+ stf.spill [temp1]=f16,32
+ stf.spill [temp2]=f17,32
+ ;;
+ stf.spill [temp1]=f18,32
+ stf.spill [temp2]=f19,32
+ ;;
+ stf.spill [temp1]=f20,32
+ stf.spill [temp2]=f21,32
+ ;;
+ stf.spill [temp1]=f22,32
+ stf.spill [temp2]=f23,32
+ ;;
+ stf.spill [temp1]=f24,32
+ stf.spill [temp2]=f25,32
+ ;;
+ stf.spill [temp1]=f26,32
+ stf.spill [temp2]=f27,32
+ ;;
+ stf.spill [temp1]=f28,32
+ stf.spill [temp2]=f29,32
+ ;;
+ stf.spill [temp1]=f30,SW(B2)-SW(F30)
+ stf.spill [temp2]=f31,SW(B3)-SW(F31)
+ mov temp3=b2
+ mov temp4=b3
+ ;;
+ st8 [temp1]=temp3,16 // save b2
+ st8 [temp2]=temp4,16 // save b3
+ mov temp3=b4
+ mov temp4=b5
+ ;;
+ st8 [temp1]=temp3,SW(AR_LC)-SW(B4) // save b4
+ st8 [temp2]=temp4 // save b5
+ mov temp3=ar.lc
+ ;;
+ st8 [temp1]=temp3 // save ar.lc
+
+ // FIXME: Some proms are incorrectly accessing the minstate area as
+ // cached data. The C code uses region 6, uncached virtual. Ensure
+ // that there is no cache data lying around for the first 1K of the
+ // minstate area.
+ // Remove this code in September 2006, that gives platforms a year to
+ // fix their proms and get their customers updated.
+
+ add r1=32*1,r17
+ add r2=32*2,r17
+ add r3=32*3,r17
+ add r4=32*4,r17
+ add r5=32*5,r17
+ add r6=32*6,r17
+ add r7=32*7,r17
+ ;;
+ fc r17
+ fc r1
+ fc r2
+ fc r3
+ fc r4
+ fc r5
+ fc r6
+ fc r7
+ add r17=32*8,r17
+ add r1=32*8,r1
+ add r2=32*8,r2
+ add r3=32*8,r3
+ add r4=32*8,r4
+ add r5=32*8,r5
+ add r6=32*8,r6
+ add r7=32*8,r7
+ ;;
+ fc r17
+ fc r1
+ fc r2
+ fc r3
+ fc r4
+ fc r5
+ fc r6
+ fc r7
+ add r17=32*8,r17
+ add r1=32*8,r1
+ add r2=32*8,r2
+ add r3=32*8,r3
+ add r4=32*8,r4
+ add r5=32*8,r5
+ add r6=32*8,r6
+ add r7=32*8,r7
+ ;;
+ fc r17
+ fc r1
+ fc r2
+ fc r3
+ fc r4
+ fc r5
+ fc r6
+ fc r7
+ add r17=32*8,r17
+ add r1=32*8,r1
+ add r2=32*8,r2
+ add r3=32*8,r3
+ add r4=32*8,r4
+ add r5=32*8,r5
+ add r6=32*8,r6
+ add r7=32*8,r7
+ ;;
+ fc r17
+ fc r1
+ fc r2
+ fc r3
+ fc r4
+ fc r5
+ fc r6
+ fc r7
+
+ br.sptk b0
//EndStub//////////////////////////////////////////////////////////////////////
//++
// Name:
-// ia64_os_mca_proc_state_restore()
+// ia64_state_restore()
//
// Stub Description:
//
-// This is a stub to restore the saved processor state during MCHK
+// Restore the SAL/OS state. This is sensitive to the layout of struct
+// ia64_sal_os_state in mca.h.
+//
+// r2 contains the return address, r3 contains either
+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+// In addition to the SAL to OS state, this routine restores all the
+// registers that appear in struct pt_regs and struct switch_stack,
+// excluding those in the PAL minstate area.
//
//--
-ia64_os_mca_proc_state_restore:
+ia64_state_restore:
+ // Restore the switch_stack data that is not in minstate nor pt_regs.
+ add regs=MCA_SWITCH_STACK_OFFSET, r3
+ mov b0=r2 // save return address
+ ;;
+ GET_IA64_MCA_DATA(temp2)
+ ;;
+ add regs=temp2, regs
+ ;;
+ add temp1=SW(F2), regs
+ add temp2=SW(F3), regs
+ ;;
+ ldf.fill f2=[temp1],32
+ ldf.fill f3=[temp2],32
+ ;;
+ ldf.fill f4=[temp1],32
+ ldf.fill f5=[temp2],32
+ ;;
+ ldf.fill f12=[temp1],32
+ ldf.fill f13=[temp2],32
+ ;;
+ ldf.fill f14=[temp1],32
+ ldf.fill f15=[temp2],32
+ ;;
+ ldf.fill f16=[temp1],32
+ ldf.fill f17=[temp2],32
+ ;;
+ ldf.fill f18=[temp1],32
+ ldf.fill f19=[temp2],32
+ ;;
+ ldf.fill f20=[temp1],32
+ ldf.fill f21=[temp2],32
+ ;;
+ ldf.fill f22=[temp1],32
+ ldf.fill f23=[temp2],32
+ ;;
+ ldf.fill f24=[temp1],32
+ ldf.fill f25=[temp2],32
+ ;;
+ ldf.fill f26=[temp1],32
+ ldf.fill f27=[temp2],32
+ ;;
+ ldf.fill f28=[temp1],32
+ ldf.fill f29=[temp2],32
+ ;;
+ ldf.fill f30=[temp1],SW(B2)-SW(F30)
+ ldf.fill f31=[temp2],SW(B3)-SW(F31)
+ ;;
+ ld8 temp3=[temp1],16 // restore b2
+ ld8 temp4=[temp2],16 // restore b3
+ ;;
+ mov b2=temp3
+ mov b3=temp4
+ ld8 temp3=[temp1],SW(AR_LC)-SW(B4) // restore b4
+ ld8 temp4=[temp2] // restore b5
+ ;;
+ mov b4=temp3
+ mov b5=temp4
+ ld8 temp3=[temp1] // restore ar.lc
+ ;;
+ mov ar.lc=temp3
-// Restore bank1 GR16-31
- GET_IA64_MCA_DATA(r2)
+ // Restore the pt_regs data that is not in minstate. The previous code
+ // left regs at switch_stack.
+ add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs
+ ;;
+ add temp1=PT(B6), regs
+ add temp2=PT(B7), regs
+ ;;
+ ld8 temp3=[temp1],PT(AR_CSD)-PT(B6) // restore b6
+ ld8 temp4=[temp2],PT(AR_SSD)-PT(B7) // restore b7
+ ;;
+ mov b6=temp3
+ mov b7=temp4
+ ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD) // restore ar.csd
+ ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD) // restore ar.ssd
+ ;;
+ mov ar.csd=temp3
+ mov ar.ssd=temp4
+ ld8 temp3=[temp1] // restore ar.unat
+ add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1
+ ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS) // restore ar.pfs
+ ;;
+ mov ar.unat=temp3
+ mov ar.pfs=temp4
+ // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack.
+ ld8 temp3=[temp1],PT(F6)-PT(AR_CCV) // restore ar.ccv
+ ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR) // restore ar.fpsr
+ ;;
+ mov ar.ccv=temp3
+ mov ar.fpsr=temp4
+ ldf.fill f6=[temp1],PT(F8)-PT(F6)
+ ldf.fill f7=[temp2],PT(F9)-PT(F7)
+ ;;
+ ldf.fill f8=[temp1],PT(F10)-PT(F8)
+ ldf.fill f9=[temp2],PT(F11)-PT(F9)
+ ;;
+ ldf.fill f10=[temp1]
+ ldf.fill f11=[temp2]
+
+ // Restore the SAL to OS state. The previous code left regs at pt_regs.
+ add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs
;;
- add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2
-
-restore_GRs: // restore bank-1 GRs 16-31
- bsw.1;;
- add r3=16*8,r2;; // to get to NaT of GR 16-31
- ld8 r3=[r3];;
- mov ar.unat=r3;; // first restore NaT
-
- ld8.fill r16=[r2],8;;
- ld8.fill r17=[r2],8;;
- ld8.fill r18=[r2],8;;
- ld8.fill r19=[r2],8;;
- ld8.fill r20=[r2],8;;
- ld8.fill r21=[r2],8;;
- ld8.fill r22=[r2],8;;
- ld8.fill r23=[r2],8;;
- ld8.fill r24=[r2],8;;
- ld8.fill r25=[r2],8;;
- ld8.fill r26=[r2],8;;
- ld8.fill r27=[r2],8;;
- ld8.fill r28=[r2],8;;
- ld8.fill r29=[r2],8;;
- ld8.fill r30=[r2],8;;
- ld8.fill r31=[r2],8;;
-
- ld8 r3=[r2],8;; // increment to skip NaT
- bsw.0;;
-
-restore_BRs:
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2;; // duplicate r2 in r4
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov b0=r3
- mov b1=r5
- mov b2=r7;;
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov b3=r3
- mov b4=r5
- mov b5=r7;;
-
- ld8 r3=[r2],2*8
- ld8 r5=[r4],2*8;;
- mov b6=r3
- mov b7=r5;;
-
-restore_CRs:
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2;; // duplicate r2 in r4
-
- ld8 r3=[r2],8*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;; // 48 byte increments
- mov cr.dcr=r3
- mov cr.itm=r5
- mov cr.iva=r7;;
-
- ld8 r3=[r2],8*8;; // 64 byte increments
-// mov cr.pta=r3
-
-
-// if PSR.ic=1, reading interruption registers causes an illegal operation fault
- mov r3=psr;;
- tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test
-(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.
-
-begin_rskip_intr_regs:
-(p6) br rSkipIntrRegs;;
-
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2;; // duplicate r2 in r4
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov cr.ipsr=r3
-// mov cr.isr=r5 // cr.isr is read only
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov cr.iip=r3
- mov cr.ifa=r5
- mov cr.itir=r7;;
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov cr.iipa=r3
- mov cr.ifs=r5
- mov cr.iim=r7
-
- ld8 r3=[r2],160;; // 160 byte increment
- mov cr.iha=r3
-
-rSkipIntrRegs:
- ld8 r3=[r2],152;; // another 152 byte inc.
-
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2;; // duplicate r2 in r6
-
- ld8 r3=[r2],8*3
- ld8 r5=[r4],8*3
- ld8 r7=[r6],8*3;;
- mov cr.lid=r3
-// mov cr.ivr=r5 // cr.ivr is read only
- mov cr.tpr=r7;;
-
- ld8 r3=[r2],8*3
- ld8 r5=[r4],8*3
- ld8 r7=[r6],8*3;;
-// mov cr.eoi=r3
-// mov cr.irr0=r5 // cr.irr0 is read only
-// mov cr.irr1=r7;; // cr.irr1 is read only
-
- ld8 r3=[r2],8*3
- ld8 r5=[r4],8*3
- ld8 r7=[r6],8*3;;
-// mov cr.irr2=r3 // cr.irr2 is read only
-// mov cr.irr3=r5 // cr.irr3 is read only
- mov cr.itv=r7;;
-
- ld8 r3=[r2],8*7
- ld8 r5=[r4],8*7;;
- mov cr.pmv=r3
- mov cr.cmcv=r5;;
-
- ld8 r3=[r2],8*23
- ld8 r5=[r4],8*23;;
- adds r2=8*23,r2
- adds r4=8*23,r4;;
-// mov cr.lrr0=r3
-// mov cr.lrr1=r5
-
- adds r2=8*2,r2;;
-
-restore_ARs:
- add r4=8,r2 // duplicate r2 in r4
- add r6=2*8,r2;; // duplicate r2 in r4
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov ar.k0=r3
- mov ar.k1=r5
- mov ar.k2=r7;;
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
- mov ar.k3=r3
- mov ar.k4=r5
- mov ar.k5=r7;;
-
- ld8 r3=[r2],10*8
- ld8 r5=[r4],10*8
- ld8 r7=[r6],10*8;;
- mov ar.k6=r3
- mov ar.k7=r5
- ;;
-
- ld8 r3=[r2],3*8
- ld8 r5=[r4],3*8
- ld8 r7=[r6],3*8;;
-// mov ar.rsc=r3
-// mov ar.bsp=r5 // ar.bsp is read only
- mov ar.rsc=r0 // make sure that RSE is in enforced lazy mode
- ;;
- mov ar.bspstore=r7;;
-
- ld8 r9=[r2],8*13;;
- mov ar.rnat=r9
-
- mov ar.rsc=r3
- ld8 r3=[r2],8*4;;
- mov ar.ccv=r3
-
- ld8 r3=[r2],8*4;;
- mov ar.unat=r3
-
- ld8 r3=[r2],8*4;;
- mov ar.fpsr=r3
-
- ld8 r3=[r2],160;; // 160
-// mov ar.itc=r3
-
- ld8 r3=[r2],8;;
- mov ar.pfs=r3
-
- ld8 r3=[r2],8;;
- mov ar.lc=r3
-
- ld8 r3=[r2];;
- mov ar.ec=r3
- add r2=8*62,r2;; // padding
-
-restore_RRs:
- mov r5=ar.lc
- mov ar.lc=0x08-1
- movl r4=0x00;;
-cStRRr:
- dep.z r7=r4,61,3
- ld8 r3=[r2],8;;
- mov rr[r7]=r3 // what are its access previledges?
- add r4=1,r4
- br.cloop.sptk.few cStRRr
- ;;
- mov ar.lc=r5
- ;;
-end_os_mca_restore:
- br ia64_os_mca_done_restore;;
+ add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs
+ add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs
+ ;;
+ ld8 r12=[temp1],16 // sal_ra
+ ld8 r9=[temp2],16 // sal_gp
+ ;;
+ ld8 r22=[temp1],24 // pal_min_state, virtual. skip prev_task
+ ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT
+ ;;
+ ld8 temp3=[temp1],16 // cr.isr
+ ld8 temp4=[temp2],16 // cr.ifa
+ ;;
+ mov cr.isr=temp3
+ mov cr.ifa=temp4
+ ld8 temp3=[temp1],16 // cr.itir
+ ld8 temp4=[temp2],16 // cr.iipa
+ ;;
+ mov cr.itir=temp3
+ mov cr.iipa=temp4
+ ld8 temp3=[temp1],16 // cr.iim
+ ld8 temp4=[temp2],16 // cr.iha
+ ;;
+ mov cr.iim=temp3
+ mov cr.iha=temp4
+ dep r22=0,r22,62,2 // pal_min_state, physical, uncached
+ mov IA64_KR(CURRENT)=r21
+ ld8 r8=[temp1] // os_status
+ ld8 r10=[temp2] // context
+
+ br.sptk b0
//EndStub//////////////////////////////////////////////////////////////////////
-// ok, the issue here is that we need to save state information so
-// it can be useable by the kernel debugger and show regs routines.
-// In order to do this, our best bet is save the current state (plus
-// the state information obtain from the MIN_STATE_AREA) into a pt_regs
-// format. This way we can pass it on in a useable format.
+//++
+// Name:
+// ia64_new_stack()
//
-
+// Stub Description:
//
-// SAL to OS entry point for INIT on the monarch processor
-// This has been defined for registration purposes with SAL
-// as a part of ia64_mca_init.
+// Switch to the MCA/INIT stack.
//
-// When we get here, the following registers have been
-// set by the SAL for our use
+// r2 contains the return address, r3 contains either
+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
//
-// 1. GR1 = OS INIT GP
-// 2. GR8 = PAL_PROC physical address
-// 3. GR9 = SAL_PROC physical address
-// 4. GR10 = SAL GP (physical)
-// 5. GR11 = Init Reason
-// 0 = Received INIT for event other than crash dump switch
-// 1 = Received wakeup at the end of an OS_MCA corrected machine check
-// 2 = Received INIT dude to CrashDump switch assertion
+// On entry RBS is still on the original stack, this routine switches RBS
+// to use the MCA/INIT stack.
//
-// 6. GR12 = Return address to location within SAL_INIT procedure
-
+// On entry, sos->pal_min_state is physical, on exit it is virtual.
+//
+//--
-GLOBAL_ENTRY(ia64_monarch_init_handler)
- .prologue
- // stash the information the SAL passed to os
- SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
+ia64_new_stack:
+ add regs=MCA_PT_REGS_OFFSET, r3
+ add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3
+ mov b0=r2 // save return address
+ GET_IA64_MCA_DATA(temp1)
+ invala
;;
- SAVE_MIN_WITH_COVER
+ add temp2=temp2, temp1 // struct ia64_sal_os_state.pal_min_state on MCA or INIT stack
+ add regs=regs, temp1 // struct pt_regs on MCA or INIT stack
;;
- mov r8=cr.ifa
- mov r9=cr.isr
- adds r3=8,r2 // set up second base pointer
+ // Address of minstate area provided by PAL is physical, uncacheable.
+ // Convert to Linux virtual address in region 6 for C code.
+ ld8 ms=[temp2] // pal_min_state, physical
;;
- SAVE_REST
-
-// ok, enough should be saved at this point to be dangerous, and supply
-// information for a dump
-// We need to switch to Virtual mode before hitting the C functions.
+ dep temp1=-1,ms,62,2 // set region 6
+ mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET
+ ;;
+ st8 [temp2]=temp1 // pal_min_state, virtual
- movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
- mov r3=psr // get the current psr, minimum enabled at this point
+ add temp4=temp3, regs // start of bspstore on new stack
;;
- or r2=r2,r3
+ mov ar.bspstore=temp4 // switch RBS to MCA/INIT stack
;;
- movl r3=IVirtual_Switch
+ flushrs // must be first in group
+ br.sptk b0
+
+//EndStub//////////////////////////////////////////////////////////////////////
+
+
+//++
+// Name:
+// ia64_old_stack()
+//
+// Stub Description:
+//
+// Switch to the old stack.
+//
+// r2 contains the return address, r3 contains either
+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+// On entry, pal_min_state is virtual, on exit it is physical.
+//
+// On entry RBS is on the MCA/INIT stack, this routine switches RBS
+// back to the previous stack.
+//
+// The psr is set to all zeroes. SAL return requires either all zeroes or
+// just psr.mc set. Leaving psr.mc off allows INIT to be issued if this
+// code does not perform correctly.
+//
+// The dirty registers at the time of the event were flushed to the
+// MCA/INIT stack in ia64_pt_regs_save(). Restore the dirty registers
+// before reverting to the previous bspstore.
+//--
+
+ia64_old_stack:
+ add regs=MCA_PT_REGS_OFFSET, r3
+ mov b0=r2 // save return address
+ GET_IA64_MCA_DATA(temp2)
+ LOAD_PHYSICAL(p0,temp1,1f)
;;
- mov cr.iip=r3 // short return to set the appropriate bits
- mov cr.ipsr=r2 // need to do an rfi to set appropriate bits
+ mov cr.ipsr=r0
+ mov cr.ifs=r0
+ mov cr.iip=temp1
;;
+ invala
rfi
+1:
+
+ add regs=regs, temp2 // struct pt_regs on MCA or INIT stack
;;
-IVirtual_Switch:
- //
- // We should now be running virtual
- //
- // Let's call the C handler to get the rest of the state info
- //
- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
+ add temp1=PT(LOADRS), regs
;;
- adds out0=16,sp // out0 = pointer to pt_regs
+ ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS) // restore loadrs
;;
- DO_SAVE_SWITCH_STACK
- .body
- adds out1=16,sp // out0 = pointer to switch_stack
+ ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE) // restore ar.bspstore
+ mov ar.rsc=temp2
+ ;;
+ loadrs
+ ld8 temp4=[temp1] // restore ar.rnat
+ ;;
+ mov ar.bspstore=temp3 // back to old stack
+ ;;
+ mov ar.rnat=temp4
+ ;;
+
+ br.sptk b0
- br.call.sptk.many rp=ia64_init_handler
-.ret1:
+//EndStub//////////////////////////////////////////////////////////////////////
-return_from_init:
- br.sptk return_from_init
-END(ia64_monarch_init_handler)
+//++
+// Name:
+// ia64_set_kernel_registers()
//
-// SAL to OS entry point for INIT on the slave processor
-// This has been defined for registration purposes with SAL
-// as a part of ia64_mca_init.
+// Stub Description:
+//
+// Set the registers that are required by the C code in order to run on an
+// MCA/INIT stack.
+//
+// r2 contains the return address, r3 contains either
+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
//
+//--
+
+ia64_set_kernel_registers:
+ add temp3=MCA_SP_OFFSET, r3
+ add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3
+ mov b0=r2 // save return address
+ GET_IA64_MCA_DATA(temp1)
+ ;;
+ add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp
+ add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack
+ add r13=temp1, r3 // set current to start of MCA/INIT stack
+ ;;
+ ld8 r1=[temp4] // OS GP from SAL OS state
+ ;;
+ DATA_PA_TO_VA(r1,temp1)
+ DATA_PA_TO_VA(r12,temp2)
+ DATA_PA_TO_VA(r13,temp3)
+ ;;
+ mov IA64_KR(CURRENT)=r13
+
+ // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK?
+
+ br.sptk b0
+
+//EndStub//////////////////////////////////////////////////////////////////////
+
+#undef ms
+#undef regs
+#undef temp1
+#undef temp2
+#undef temp3
+#undef temp4
+
-GLOBAL_ENTRY(ia64_slave_init_handler)
-1: br.sptk 1b
-END(ia64_slave_init_handler)
+// Support function for mca.c, it is here to avoid using inline asm. Given the
+// address of an rnat slot, if that address is below the current ar.bspstore
+// then return the contents of that slot, otherwise return the contents of
+// ar.rnat.
+GLOBAL_ENTRY(ia64_get_rnat)
+ alloc r14=ar.pfs,1,0,0,0
+ mov ar.rsc=0
+ ;;
+ mov r14=ar.bspstore
+ ;;
+ cmp.lt p6,p7=in0,r14
+ ;;
+(p6) ld8 r8=[in0]
+(p7) mov r8=ar.rnat
+ mov ar.rsc=3
+ br.ret.sptk.many rp
+END(ia64_get_rnat)
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index abc0113a821d..6e683745af49 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -4,6 +4,8 @@
*
* Copyright (C) 2004 FUJITSU LIMITED
* Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2005 Silicon Graphics, Inc
+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
*/
#include <linux/config.h>
#include <linux/types.h>
@@ -38,10 +40,6 @@
/* max size of SAL error record (default) */
static int sal_rec_max = 10000;
-/* from mca.c */
-static ia64_mca_sal_to_os_state_t *sal_to_os_handoff_state;
-static ia64_mca_os_to_sal_state_t *os_to_sal_handoff_state;
-
/* from mca_drv_asm.S */
extern void *mca_handler_bhhook(void);
@@ -316,7 +314,8 @@ init_record_index_pools(void)
*/
static mca_type_t
-is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+ struct ia64_sal_os_state *sos)
{
pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
@@ -327,7 +326,7 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
* Therefore it is local MCA when rendezvous has not been requested.
* Failed to rendezvous, the system must be down.
*/
- switch (sal_to_os_handoff_state->imsto_rendez_state) {
+ switch (sos->rv_rc) {
case -1: /* SAL rendezvous unsuccessful */
return MCA_IS_GLOBAL;
case 0: /* SAL rendezvous not required */
@@ -388,7 +387,8 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
*/
static int
-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+ struct ia64_sal_os_state *sos)
{
sal_log_mod_error_info_t *smei;
pal_min_state_area_t *pmsa;
@@ -426,7 +426,7 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
* setup for resume to bottom half of MCA,
* "mca_handler_bhhook"
*/
- pmsa = (pal_min_state_area_t *)(sal_to_os_handoff_state->pal_min_state | (6ul<<61));
+ pmsa = sos->pal_min_state;
/* pass to bhhook as 1st argument (gr8) */
pmsa->pmsa_gr[8-1] = smei->target_identifier;
/* set interrupted return address (but no use) */
@@ -459,7 +459,8 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
*/
static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+ struct ia64_sal_os_state *sos)
{
int status = 0;
pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
@@ -469,7 +470,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
case 1: /* partial read */
case 3: /* full line(cpu) read */
case 9: /* I/O space read */
- status = recover_from_read_error(slidx, peidx, pbci);
+ status = recover_from_read_error(slidx, peidx, pbci, sos);
break;
case 0: /* unknown */
case 2: /* partial write */
@@ -508,7 +509,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
*/
static int
-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+ struct ia64_sal_os_state *sos)
{
pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
@@ -545,7 +547,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
* This means "there are some platform errors".
*/
if (platform)
- return recover_from_platform_error(slidx, peidx, pbci);
+ return recover_from_platform_error(slidx, peidx, pbci, sos);
/*
* On account of strange SAL error record, we cannot recover.
*/
@@ -562,8 +564,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
static int
mca_try_to_recover(void *rec,
- ia64_mca_sal_to_os_state_t *sal_to_os_state,
- ia64_mca_os_to_sal_state_t *os_to_sal_state)
+ struct ia64_sal_os_state *sos)
{
int platform_err;
int n_proc_err;
@@ -571,10 +572,6 @@ mca_try_to_recover(void *rec,
peidx_table_t peidx;
pal_bus_check_info_t pbci;
- /* handoff state from/to mca.c */
- sal_to_os_handoff_state = sal_to_os_state;
- os_to_sal_handoff_state = os_to_sal_state;
-
/* Make index of SAL error record */
platform_err = mca_make_slidx(rec, &slidx);
@@ -597,11 +594,11 @@ mca_try_to_recover(void *rec,
*((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
/* Check whether MCA is global or not */
- if (is_mca_global(&peidx, &pbci))
+ if (is_mca_global(&peidx, &pbci, sos))
return 0;
/* Try to recover a processor error */
- return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci);
+ return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);
}
/*
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index f6d8a010d99b..85ed54179afa 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -5,73 +5,6 @@
#include "entry.h"
/*
- * For ivt.s we want to access the stack virtually so we don't have to disable translation
- * on interrupts.
- *
- * On entry:
- * r1: pointer to current task (ar.k6)
- */
-#define MINSTATE_START_SAVE_MIN_VIRT \
-(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
- ;; \
-(pUStk) mov.m r24=ar.rnat; \
-(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
-(pKStk) mov r1=sp; /* get sp */ \
- ;; \
-(pUStk) lfetch.fault.excl.nt1 [r22]; \
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
-(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
- ;; \
-(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
- ;; \
-(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */
-
-#define MINSTATE_END_SAVE_MIN_VIRT \
- bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
- ;;
-
-/*
- * For mca_asm.S we want to access the stack physically since the state is saved before we
- * go virtual and don't want to destroy the iip or ipsr.
- */
-#define MINSTATE_START_SAVE_MIN_PHYS \
-(pKStk) mov r3=IA64_KR(PER_CPU_DATA);; \
-(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
-(pKStk) ld8 r3 = [r3];; \
-(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
-(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
-(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
-(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
- ;; \
-(pUStk) mov r24=ar.rnat; \
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
-(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
-(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \
- ;; \
-(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
- ;; \
-(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
-
-#define MINSTATE_END_SAVE_MIN_PHYS \
- dep r12=-1,r12,61,3; /* make sp a kernel virtual address */ \
- ;;
-
-#ifdef MINSTATE_VIRT
-# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT)
-# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT
-# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT
-#endif
-
-#ifdef MINSTATE_PHYS
-# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; tpa reg=reg
-# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS
-# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS
-#endif
-
-/*
* DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
* the minimum state necessary that allows us to turn psr.ic back
* on.
@@ -97,7 +30,7 @@
* we can pass interruption state as arguments to a handler.
*/
#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
- MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \
+ mov r16=IA64_KR(CURRENT); /* M */ \
mov r27=ar.rsc; /* M */ \
mov r20=r1; /* A */ \
mov r25=ar.unat; /* M */ \
@@ -118,7 +51,21 @@
SAVE_IFS; \
cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
;; \
- MINSTATE_START_SAVE_MIN \
+(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
+ ;; \
+(pUStk) mov.m r24=ar.rnat; \
+(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
+(pKStk) mov r1=sp; /* get sp */ \
+ ;; \
+(pUStk) lfetch.fault.excl.nt1 [r22]; \
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
+(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
+ ;; \
+(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
+ ;; \
+(pUStk) mov r18=ar.bsp; \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \
adds r16=PT(CR_IPSR),r1; \
;; \
@@ -181,7 +128,8 @@
EXTRA; \
movl r1=__gp; /* establish kernel global pointer */ \
;; \
- MINSTATE_END_SAVE_MIN
+ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
+ ;;
/*
* SAVE_REST saves the remainder of pt_regs (with psr.ic on).
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 25e7c8344564..89faa603c6be 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -307,11 +307,9 @@ vm_info(char *page)
if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
- return 0;
- }
+ } else {
-
- p += sprintf(p,
+ p += sprintf(p,
"Physical Address Space : %d bits\n"
"Virtual Address Space : %d bits\n"
"Protection Key Registers(PKR) : %d\n"
@@ -319,92 +317,99 @@ vm_info(char *page)
"Hash Tag ID : 0x%x\n"
"Size of RR.rid : %d\n",
vm_info_1.pal_vm_info_1_s.phys_add_size,
- vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
- vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
+ vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
+ vm_info_1.pal_vm_info_1_s.max_pkr+1,
+ vm_info_1.pal_vm_info_1_s.key_size,
+ vm_info_1.pal_vm_info_1_s.hash_tag_id,
vm_info_2.pal_vm_info_2_s.rid_size);
+ }
- if (ia64_pal_mem_attrib(&attrib) != 0)
- return 0;
-
- p += sprintf(p, "Supported memory attributes : ");
- sep = "";
- for (i = 0; i < 8; i++) {
- if (attrib & (1 << i)) {
- p += sprintf(p, "%s%s", sep, mem_attrib[i]);
- sep = ", ";
+ if (ia64_pal_mem_attrib(&attrib) == 0) {
+ p += sprintf(p, "Supported memory attributes : ");
+ sep = "";
+ for (i = 0; i < 8; i++) {
+ if (attrib & (1 << i)) {
+ p += sprintf(p, "%s%s", sep, mem_attrib[i]);
+ sep = ", ";
+ }
}
+ p += sprintf(p, "\n");
}
- p += sprintf(p, "\n");
if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
- return 0;
- }
-
- p += sprintf(p,
- "\nTLB walker : %simplemented\n"
- "Number of DTR : %d\n"
- "Number of ITR : %d\n"
- "TLB insertable page sizes : ",
- vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
- vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
- vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
+ } else {
+ p += sprintf(p,
+ "\nTLB walker : %simplemented\n"
+ "Number of DTR : %d\n"
+ "Number of ITR : %d\n"
+ "TLB insertable page sizes : ",
+ vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
+ vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
+ vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
- p = bitvector_process(p, tr_pages);
- p += sprintf(p, "\nTLB purgeable page sizes : ");
+ p = bitvector_process(p, tr_pages);
- p = bitvector_process(p, vw_pages);
+ p += sprintf(p, "\nTLB purgeable page sizes : ");
+ p = bitvector_process(p, vw_pages);
+ }
if ((status=ia64_get_ptce(&ptce)) != 0) {
printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
- return 0;
- }
-
- p += sprintf(p,
+ } else {
+ p += sprintf(p,
"\nPurge base address : 0x%016lx\n"
"Purge outer loop count : %d\n"
"Purge inner loop count : %d\n"
"Purge outer loop stride : %d\n"
"Purge inner loop stride : %d\n",
- ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
+ ptce.base, ptce.count[0], ptce.count[1],
+ ptce.stride[0], ptce.stride[1]);
- p += sprintf(p,
+ p += sprintf(p,
"TC Levels : %d\n"
"Unique TC(s) : %d\n",
vm_info_1.pal_vm_info_1_s.num_tc_levels,
vm_info_1.pal_vm_info_1_s.max_unique_tcs);
- for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
- for (j=2; j>0 ; j--) {
- tc_pages = 0; /* just in case */
+ for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
+ for (j=2; j>0 ; j--) {
+ tc_pages = 0; /* just in case */
- /* even without unification, some levels may not be present */
- if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
- continue;
- }
+ /* even without unification, some levels may not be present */
+ if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
+ continue;
+ }
- p += sprintf(p,
+ p += sprintf(p,
"\n%s Translation Cache Level %d:\n"
"\tHash sets : %d\n"
"\tAssociativity : %d\n"
"\tNumber of entries : %d\n"
"\tFlags : ",
- cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
- tc_info.tc_associativity, tc_info.tc_num_entries);
+ cache_types[j+tc_info.tc_unified], i+1,
+ tc_info.tc_num_sets,
+ tc_info.tc_associativity,
+ tc_info.tc_num_entries);
- if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
- if (tc_info.tc_unified) p += sprintf(p, "Unified ");
- if (tc_info.tc_reduce_tr) p += sprintf(p, "TCReduction");
+ if (tc_info.tc_pf)
+ p += sprintf(p, "PreferredPageSizeOptimized ");
+ if (tc_info.tc_unified)
+ p += sprintf(p, "Unified ");
+ if (tc_info.tc_reduce_tr)
+ p += sprintf(p, "TCReduction");
- p += sprintf(p, "\n\tSupported page sizes: ");
+ p += sprintf(p, "\n\tSupported page sizes: ");
- p = bitvector_process(p, tc_pages);
+ p = bitvector_process(p, tc_pages);
- /* when unified date (j=2) is enough */
- if (tc_info.tc_unified) break;
+ /* when unified date (j=2) is enough */
+ if (tc_info.tc_unified)
+ break;
+ }
}
}
p += sprintf(p, "\n");
@@ -440,14 +445,14 @@ register_info(char *page)
p += sprintf(p, "\n");
}
- if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
+ if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {
p += sprintf(p,
"RSE stacked physical registers : %ld\n"
"RSE load/store hints : %ld (%s)\n",
phys_stacked, hints.ph_data,
hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
-
+ }
if (ia64_pal_debug_info(&iregs, &dregs))
return 0;
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index f1201ac8a116..1650353e3f77 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -38,6 +38,7 @@
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/bitops.h>
+#include <linux/rcupdate.h>
#include <asm/errno.h>
#include <asm/intrinsics.h>
@@ -496,7 +497,7 @@ typedef struct {
static pfm_stats_t pfm_stats[NR_CPUS];
static pfm_session_t pfm_sessions; /* global sessions information */
-static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pfm_alt_install_check);
static pfm_intr_handler_desc_t *pfm_alt_intr_handler;
static struct proc_dir_entry *perfmon_dir;
@@ -2217,15 +2218,17 @@ static void
pfm_free_fd(int fd, struct file *file)
{
struct files_struct *files = current->files;
+ struct fdtable *fdt = files_fdtable(files);
/*
* there ie no fd_uninstall(), so we do it here
*/
spin_lock(&files->file_lock);
- files->fd[fd] = NULL;
+ rcu_assign_pointer(fdt->fd[fd], NULL);
spin_unlock(&files->file_lock);
- if (file) put_filp(file);
+ if (file)
+ put_filp(file);
put_unused_fd(fd);
}
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 6f0cc7a6634e..ca68e6e44a72 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -22,6 +22,11 @@
*
* Dec 5 2004 kaos@sgi.com
* Standardize which records are cleared automatically.
+ *
+ * Aug 18 2005 kaos@sgi.com
+ * mca.c may not pass a buffer, a NULL buffer just indicates that a new
+ * record is available in SAL.
+ * Replace some NR_CPUS by cpus_online, for hotplug cpu.
*/
#include <linux/types.h>
@@ -193,7 +198,7 @@ shift1_data_saved (struct salinfo_data *data, int shift)
* The buffer passed from mca.c points to the output from ia64_log_get. This is
* a persistent buffer but its contents can change between the interrupt and
* when user space processes the record. Save the record id to identify
- * changes.
+ * changes. If the buffer is NULL then just update the bitmap.
*/
void
salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
@@ -206,27 +211,29 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
- if (irqsafe)
- spin_lock_irqsave(&data_saved_lock, flags);
- for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
- if (!data_saved->buffer)
- break;
- }
- if (i == saved_size) {
- if (!data->saved_num) {
- shift1_data_saved(data, 0);
- data_saved = data->data_saved + saved_size - 1;
- } else
- data_saved = NULL;
- }
- if (data_saved) {
- data_saved->cpu = smp_processor_id();
- data_saved->id = ((sal_log_record_header_t *)buffer)->id;
- data_saved->size = size;
- data_saved->buffer = buffer;
+ if (buffer) {
+ if (irqsafe)
+ spin_lock_irqsave(&data_saved_lock, flags);
+ for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+ if (!data_saved->buffer)
+ break;
+ }
+ if (i == saved_size) {
+ if (!data->saved_num) {
+ shift1_data_saved(data, 0);
+ data_saved = data->data_saved + saved_size - 1;
+ } else
+ data_saved = NULL;
+ }
+ if (data_saved) {
+ data_saved->cpu = smp_processor_id();
+ data_saved->id = ((sal_log_record_header_t *)buffer)->id;
+ data_saved->size = size;
+ data_saved->buffer = buffer;
+ }
+ if (irqsafe)
+ spin_unlock_irqrestore(&data_saved_lock, flags);
}
- if (irqsafe)
- spin_unlock_irqrestore(&data_saved_lock, flags);
if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
if (irqsafe)
@@ -244,7 +251,7 @@ salinfo_timeout_check(struct salinfo_data *data)
int i;
if (!data->open)
return;
- for (i = 0; i < NR_CPUS; ++i) {
+ for_each_online_cpu(i) {
if (test_bit(i, &data->cpu_event)) {
/* double up() is not a problem, user space will see no
* records for the additional "events".
@@ -291,7 +298,7 @@ retry:
n = data->cpu_check;
for (i = 0; i < NR_CPUS; i++) {
- if (test_bit(n, &data->cpu_event)) {
+ if (test_bit(n, &data->cpu_event) && cpu_online(n)) {
cpu = n;
break;
}
@@ -585,11 +592,10 @@ salinfo_init(void)
/* we missed any events before now */
online = 0;
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j)) {
- set_bit(j, &data->cpu_event);
- ++online;
- }
+ for_each_online_cpu(j) {
+ set_bit(j, &data->cpu_event);
+ ++online;
+ }
sema_init(&data->sem, online);
*sdir++ = dir;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 84f89da7c640..1f5c26dbe705 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -384,7 +384,7 @@ setup_arch (char **cmdline_p)
if (early_console_setup(*cmdline_p) == 0)
mark_bsp_online();
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/* Initialize the ACPI boot-time table parser */
acpi_table_init();
# ifdef CONFIG_ACPI_NUMA
@@ -420,7 +420,7 @@ setup_arch (char **cmdline_p)
cpu_init(); /* initialize the bootstrap CPU */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
acpi_boot_init();
#endif
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index b8a0a7d257a9..774f34b675cf 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -467,15 +467,12 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
if (!setup_frame(sig, ka, info, oldset, scr))
return 0;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- {
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- }
- spin_unlock_irq(&current->sighand->siglock);
- }
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
return 1;
}
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 770fab37928e..f2dbcd1db0d4 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -35,7 +35,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
return -ENOMEM;
#ifdef CONFIG_HUGETLB_PAGE
- if (REGION_NUMBER(addr) == REGION_HPAGE)
+ if (REGION_NUMBER(addr) == RGN_HPAGE)
addr = 0;
#endif
if (!addr)
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 92ff46ad21e2..706b7734e191 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -36,7 +36,7 @@ int arch_register_cpu(int num)
parent = &sysfs_nodes[cpu_to_node(num)];
#endif /* CONFIG_NUMA */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/*
* If CPEI cannot be re-targetted, and this is
* CPEI target, then dont create the control file
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 4440c8343fa4..f970359e7edf 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -15,6 +15,7 @@
#include <linux/vt_kern.h> /* For unblank_screen() */
#include <linux/module.h> /* for EXPORT_SYMBOL */
#include <linux/hardirq.h>
+#include <linux/kprobes.h>
#include <asm/fpswa.h>
#include <asm/ia32.h>
@@ -122,7 +123,7 @@ die_if_kernel (char *str, struct pt_regs *regs, long err)
}
void
-ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
+__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
{
siginfo_t siginfo;
int sig, code;
@@ -444,7 +445,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
return rv;
}
-void
+void __kprobes
ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
unsigned long iim, unsigned long itir, long arg5, long arg6,
long arg7, struct pt_regs regs)
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 490dfc9ab47f..4e9d06c48a8b 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -184,7 +184,7 @@ uncached_free_page(unsigned long maddr)
{
int node;
- node = nasid_to_cnodeid(NASID_GET(maddr));
+ node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET);
dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
@@ -217,7 +217,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
memset((char *)vstart, 0, length);
- node = nasid_to_cnodeid(NASID_GET(start));
+ node = paddr_to_nid(start);
for (; vstart < vend ; vstart += PAGE_SIZE) {
dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 3288be47bc75..93d5a3b41f69 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -2020,28 +2020,6 @@ init_frame_info (struct unw_frame_info *info, struct task_struct *t,
}
void
-unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
- struct pt_regs *pt, struct switch_stack *sw)
-{
- unsigned long sof;
-
- init_frame_info(info, t, sw, pt->r12);
- info->cfm_loc = &pt->cr_ifs;
- info->unat_loc = &pt->ar_unat;
- info->pfs_loc = &pt->ar_pfs;
- sof = *info->cfm_loc & 0x7f;
- info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof);
- info->ip = pt->cr_iip + ia64_psr(pt)->ri;
- info->pt = (unsigned long) pt;
- UNW_DPRINT(3, "unwind.%s:\n"
- " bsp 0x%lx\n"
- " sof 0x%lx\n"
- " ip 0x%lx\n",
- __FUNCTION__, info->bsp, sof, info->ip);
- find_save_locs(info);
-}
-
-void
unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
{
unsigned long sol;
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index a676e79e0681..30d8564e9603 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,6 +48,7 @@ SECTIONS
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.gnu.linkonce.t*)
}
.text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index 1902c3c2ef92..799407e7726f 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -6,7 +6,7 @@ obj-y := io.o
lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \
- bitop.o checksum.o clear_page.o csum_partial_copy.o copy_page.o \
+ bitop.o checksum.o clear_page.o csum_partial_copy.o \
clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \
flush.o ip_fast_csum.o do_csum.o \
memset.o strlen.o swiotlb.o
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 3e2cfa2c6d39..2a0d27f2f21b 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -20,6 +20,7 @@
*
* Note: "in0" and "in1" are preserved for debugging purposes.
*/
+ .section .kprobes.text,"ax"
GLOBAL_ENTRY(flush_icache_range)
.prologue
diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
index 6f308e62c137..46c9331e7ab5 100644
--- a/arch/ia64/lib/memcpy_mck.S
+++ b/arch/ia64/lib/memcpy_mck.S
@@ -625,8 +625,11 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
clrrrb
;;
alloc saved_pfs_stack=ar.pfs,3,3,3,0
+ cmp.lt p8,p0=A,r0
sub B = dst0, saved_in0 // how many byte copied so far
;;
+(p8) mov A = 0; // A shouldn't be negative, cap it
+ ;;
sub C = A, B
sub D = saved_in2, A
;;
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index ab7b3ad99a7f..dbc0b3e449c5 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -93,8 +93,7 @@ static int __init
setup_io_tlb_npages(char *str)
{
if (isdigit(*str)) {
- io_tlb_nslabs = simple_strtoul(str, &str, 0) <<
- (PAGE_SHIFT - IO_TLB_SHIFT);
+ io_tlb_nslabs = simple_strtoul(str, &str, 0);
/* avoid tail segment of size < IO_TLB_SEGSIZE */
io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
}
@@ -117,7 +116,7 @@ swiotlb_init_with_default_size (size_t default_size)
unsigned long i;
if (!io_tlb_nslabs) {
- io_tlb_nslabs = (default_size >> PAGE_SHIFT);
+ io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index ff62551eb3a1..3c32af910d60 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned long address)
return pte_present(pte);
}
-void
+void __kprobes
ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
{
int signal = SIGSEGV, code = SEGV_MAPERR;
@@ -229,9 +230,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
return;
}
- if (ia64_done_with_exception(regs))
- return;
-
/*
* Since we have no vma's for region 5, we might get here even if the address is
* valid, due to the VHPT walker inserting a non present translation that becomes
@@ -242,6 +240,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address))
return;
+ if (ia64_done_with_exception(regs))
+ return;
+
/*
* Oops. The kernel tried to access some bad page. We'll have to terminate things
* with extreme prejudice.
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index e0a776a3044c..2d13889d0a99 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -76,7 +76,7 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return -EINVAL;
if (addr & ~HPAGE_MASK)
return -EINVAL;
- if (REGION_NUMBER(addr) != REGION_HPAGE)
+ if (REGION_NUMBER(addr) != RGN_HPAGE)
return -EINVAL;
return 0;
@@ -87,7 +87,7 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int writ
struct page *page;
pte_t *ptep;
- if (REGION_NUMBER(addr) != REGION_HPAGE)
+ if (REGION_NUMBER(addr) != RGN_HPAGE)
return ERR_PTR(-EINVAL);
ptep = huge_pte_offset(mm, addr);
@@ -142,8 +142,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
return -ENOMEM;
if (len & ~HPAGE_MASK)
return -EINVAL;
- /* This code assumes that REGION_HPAGE != 0. */
- if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
+ /* This code assumes that RGN_HPAGE != 0. */
+ if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1)))
addr = HPAGE_REGION_BASE;
else
addr = ALIGN(addr, HPAGE_SIZE);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 65f9958db9f0..1281c609ee98 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -382,13 +382,22 @@ ia64_mmu_init (void *my_cpu_data)
if (impl_va_bits < 51 || impl_va_bits > 61)
panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);
+ /*
+ * mapped_space_bits - PAGE_SHIFT is the total number of ptes we need,
+ * which must fit into "vmlpt_bits - pte_bits" slots. Second half of
+ * the test makes sure that our mapped space doesn't overlap the
+ * unimplemented hole in the middle of the region.
+ */
+ if ((mapped_space_bits - PAGE_SHIFT > vmlpt_bits - pte_bits) ||
+ (mapped_space_bits > impl_va_bits - 1))
+ panic("Cannot build a big enough virtual-linear page table"
+ " to cover mapped address space.\n"
+ " Try using a smaller page size.\n");
+
/* place the VMLPT at the end of each page-table mapped region: */
pta = POW2(61) - POW2(vmlpt_bits);
- if (POW2(mapped_space_bits) >= pta)
- panic("mm/init: overlap between virtually mapped linear page table and "
- "mapped kernel space!");
/*
* Set the (virtually mapped linear) page table address. Bit
* 8 selects between the short and long format, bits 2-7 the
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index f9472c50ab42..9b5de589b82f 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -24,7 +24,6 @@
#include <asm/machvec.h>
#include <asm/page.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/sal.h>
@@ -499,13 +498,11 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
return acpi_pci_irq_enable(dev);
}
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
void
pcibios_disable_device (struct pci_dev *dev)
{
acpi_pci_irq_disable(dev);
}
-#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
void
pcibios_align_resource (void *data, struct resource *res,
diff --git a/arch/ia64/sn/include/tio.h b/arch/ia64/sn/include/tio.h
index 0139124dd54a..6b2e7b75eb19 100644
--- a/arch/ia64/sn/include/tio.h
+++ b/arch/ia64/sn/include/tio.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_TIO_H
@@ -26,6 +26,10 @@
#define TIO_ITTE_VALID_MASK 0x1
#define TIO_ITTE_VALID_SHIFT 16
+#define TIO_ITTE_WIDGET(itte) \
+ (((itte) >> TIO_ITTE_WIDGET_SHIFT) & TIO_ITTE_WIDGET_MASK)
+#define TIO_ITTE_VALID(itte) \
+ (((itte) >> TIO_ITTE_VALID_SHIFT) & TIO_ITTE_VALID_MASK)
#define TIO_ITTE_PUT(nasid, bigwin, widget, addr, valid) \
REMOTE_HUB_S((nasid), TIO_ITTE(bigwin), \
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
index 580a1c0403a7..71c2b271b4c6 100644
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ b/arch/ia64/sn/include/xtalk/hubdev.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_XTALK_HUBDEV_H
#define _ASM_IA64_SN_XTALK_HUBDEV_H
@@ -16,6 +16,9 @@
#define IIO_ITTE_WIDGET_MASK ((1<<IIO_ITTE_WIDGET_BITS)-1)
#define IIO_ITTE_WIDGET_SHIFT 8
+#define IIO_ITTE_WIDGET(itte) \
+ (((itte) >> IIO_ITTE_WIDGET_SHIFT) & IIO_ITTE_WIDGET_MASK)
+
/*
* Use the top big window as a surrogate for the first small window
*/
@@ -34,7 +37,8 @@ struct sn_flush_device_list {
unsigned long sfdl_force_int_addr;
unsigned long sfdl_flush_value;
volatile unsigned long *sfdl_flush_addr;
- uint64_t sfdl_persistent_busnum;
+ uint32_t sfdl_persistent_busnum;
+ uint32_t sfdl_persistent_segment;
struct pcibus_info *sfdl_pcibus_info;
spinlock_t sfdl_flush_lock;
};
@@ -58,7 +62,8 @@ struct hubdev_info {
void *hdi_nodepda;
void *hdi_node_vertex;
- void *hdi_xtalk_vertex;
+ uint32_t max_segment_number;
+ uint32_t max_pcibus_number;
};
extern void hubdev_init_node(nodepda_t *, cnodeid_t);
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 647deae9bfcd..45854c637e9c 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -29,16 +29,30 @@
/* two interfaces on two btes */
#define MAX_INTERFACES_TO_TRY 4
+#define MAX_NODES_TO_TRY 2
static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface)
{
nodepda_t *tmp_nodepda;
+ if (nasid_to_cnodeid(nasid) == -1)
+ return (struct bteinfo_s *)NULL;;
+
tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid));
return &tmp_nodepda->bte_if[interface];
}
+static inline void bte_start_transfer(struct bteinfo_s *bte, u64 len, u64 mode)
+{
+ if (is_shub2()) {
+ BTE_CTRL_STORE(bte, (IBLS_BUSY | ((len) | (mode) << 24)));
+ } else {
+ BTE_LNSTAT_STORE(bte, len);
+ BTE_CTRL_STORE(bte, mode);
+ }
+}
+
/************************************************************************
* Block Transfer Engine copy related functions.
*
@@ -67,13 +81,15 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
{
u64 transfer_size;
u64 transfer_stat;
+ u64 notif_phys_addr;
struct bteinfo_s *bte;
bte_result_t bte_status;
unsigned long irq_flags;
unsigned long itc_end = 0;
- struct bteinfo_s *btes_to_try[MAX_INTERFACES_TO_TRY];
- int bte_if_index;
- int bte_pri, bte_sec;
+ int nasid_to_try[MAX_NODES_TO_TRY];
+ int my_nasid = get_nasid();
+ int bte_if_index, nasid_index;
+ int bte_first, btes_per_node = BTES_PER_NODE;
BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n",
src, dest, len, mode, notification));
@@ -86,36 +102,26 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
(src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK));
BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)));
- /* CPU 0 (per node) tries bte0 first, CPU 1 try bte1 first */
- if (cpuid_to_subnode(smp_processor_id()) == 0) {
- bte_pri = 0;
- bte_sec = 1;
- } else {
- bte_pri = 1;
- bte_sec = 0;
- }
+ /*
+ * Start with interface corresponding to cpu number
+ */
+ bte_first = raw_smp_processor_id() % btes_per_node;
if (mode & BTE_USE_DEST) {
/* try remote then local */
- btes_to_try[0] = bte_if_on_node(NASID_GET(dest), bte_pri);
- btes_to_try[1] = bte_if_on_node(NASID_GET(dest), bte_sec);
+ nasid_to_try[0] = NASID_GET(dest);
if (mode & BTE_USE_ANY) {
- btes_to_try[2] = bte_if_on_node(get_nasid(), bte_pri);
- btes_to_try[3] = bte_if_on_node(get_nasid(), bte_sec);
+ nasid_to_try[1] = my_nasid;
} else {
- btes_to_try[2] = NULL;
- btes_to_try[3] = NULL;
+ nasid_to_try[1] = (int)NULL;
}
} else {
/* try local then remote */
- btes_to_try[0] = bte_if_on_node(get_nasid(), bte_pri);
- btes_to_try[1] = bte_if_on_node(get_nasid(), bte_sec);
+ nasid_to_try[0] = my_nasid;
if (mode & BTE_USE_ANY) {
- btes_to_try[2] = bte_if_on_node(NASID_GET(dest), bte_pri);
- btes_to_try[3] = bte_if_on_node(NASID_GET(dest), bte_sec);
+ nasid_to_try[1] = NASID_GET(dest);
} else {
- btes_to_try[2] = NULL;
- btes_to_try[3] = NULL;
+ nasid_to_try[1] = (int)NULL;
}
}
@@ -123,11 +129,12 @@ retry_bteop:
do {
local_irq_save(irq_flags);
- bte_if_index = 0;
+ bte_if_index = bte_first;
+ nasid_index = 0;
/* Attempt to lock one of the BTE interfaces. */
- while (bte_if_index < MAX_INTERFACES_TO_TRY) {
- bte = btes_to_try[bte_if_index++];
+ while (nasid_index < MAX_NODES_TO_TRY) {
+ bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index);
if (bte == NULL) {
continue;
@@ -143,6 +150,15 @@ retry_bteop:
break;
}
}
+
+ bte_if_index = (bte_if_index + 1) % btes_per_node; /* Next interface */
+ if (bte_if_index == bte_first) {
+ /*
+ * We've tried all interfaces on this node
+ */
+ nasid_index++;
+ }
+
bte = NULL;
}
@@ -169,7 +185,13 @@ retry_bteop:
/* Initialize the notification to a known value. */
*bte->most_rcnt_na = BTE_WORD_BUSY;
+ notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na));
+ if (is_shub2()) {
+ src = SH2_TIO_PHYS_TO_DMA(src);
+ dest = SH2_TIO_PHYS_TO_DMA(dest);
+ notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr);
+ }
/* Set the source and destination registers */
BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src))));
BTE_SRC_STORE(bte, TO_PHYS(src));
@@ -177,14 +199,12 @@ retry_bteop:
BTE_DEST_STORE(bte, TO_PHYS(dest));
/* Set the notification register */
- BTE_PRINTKV(("IBNA = 0x%lx)\n",
- TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))));
- BTE_NOTIF_STORE(bte,
- TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)));
+ BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr));
+ BTE_NOTIF_STORE(bte, notif_phys_addr);
/* Initiate the transfer */
BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode)));
- BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode));
+ bte_start_transfer(bte, transfer_size, BTE_VALID_MODE(mode));
itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec);
@@ -195,6 +215,7 @@ retry_bteop:
}
while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) {
+ cpu_relax();
if (ia64_get_itc() > itc_end) {
BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n",
NASID_GET(bte->bte_base_addr), bte->bte_num,
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 5c39b43ba3c0..5c5eb01c50f0 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -76,7 +76,7 @@ void hubiio_crb_free(struct hubdev_info *hubdev_info, int crbnum)
*/
REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum));
while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND)
- udelay(1);
+ cpu_relax();
}
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 414cdf2e3c96..906622d9f933 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -18,6 +18,7 @@
#include <asm/sn/simulator.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/tioca_provider.h>
+#include <asm/sn/tioce_provider.h>
#include "xtalk/hubdev.h"
#include "xtalk/xwidgetdev.h"
@@ -44,6 +45,9 @@ int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */
struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
+static int max_segment_number = 0; /* Default highest segment number */
+static int max_pcibus_number = 255; /* Default highest pci bus number */
+
/*
* Hooks and struct for unsupported pci providers
*/
@@ -157,13 +161,28 @@ static void sn_fixup_ionodes(void)
uint64_t nasid;
int i, widget;
+ /*
+ * Get SGI Specific HUB chipset information.
+ * Inform Prom that this kernel can support domain bus numbering.
+ */
for (i = 0; i < numionodes; i++) {
hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
nasid = cnodeid_to_nasid(i);
+ hubdev->max_segment_number = 0xffffffff;
+ hubdev->max_pcibus_number = 0xff;
status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev));
if (status)
continue;
+ /* Save the largest Domain and pcibus numbers found. */
+ if (hubdev->max_segment_number) {
+ /*
+ * Dealing with a Prom that supports segments.
+ */
+ max_segment_number = hubdev->max_segment_number;
+ max_pcibus_number = hubdev->max_pcibus_number;
+ }
+
/* Attach the error interrupt handlers */
if (nasid & 1)
ice_error_init(hubdev);
@@ -230,7 +249,7 @@ void sn_pci_unfixup_slot(struct pci_dev *dev)
void sn_pci_fixup_slot(struct pci_dev *dev)
{
int idx;
- int segment = 0;
+ int segment = pci_domain_nr(dev->bus);
int status = 0;
struct pcibus_bussoft *bs;
struct pci_bus *host_pci_bus;
@@ -283,9 +302,9 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
* PCI host_pci_dev struct and set up host bus linkages
*/
- bus_no = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32;
+ bus_no = (SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32) & 0xff;
devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff;
- host_pci_bus = pci_find_bus(pci_domain_nr(dev->bus), bus_no);
+ host_pci_bus = pci_find_bus(segment, bus_no);
host_pci_dev = pci_get_slot(host_pci_bus, devfn);
SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev;
@@ -333,6 +352,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
prom_bussoft_ptr = __va(prom_bussoft_ptr);
controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL);
+ controller->segment = segment;
if (!controller)
BUG();
@@ -390,7 +410,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
if (controller->node >= num_online_nodes()) {
struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
- printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu"
+ printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
"L_IO=%lx L_MEM=%lx BASE=%lx\n",
b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
@@ -411,7 +431,7 @@ void sn_bus_store_sysdata(struct pci_dev *dev)
{
struct sysdata_el *element;
- element = kcalloc(1, sizeof(struct sysdata_el), GFP_KERNEL);
+ element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
if (!element) {
dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
return;
@@ -445,6 +465,7 @@ sn_sysdata_free_start:
static int __init sn_pci_init(void)
{
int i = 0;
+ int j = 0;
struct pci_dev *pci_dev = NULL;
extern void sn_init_cpei_timer(void);
#ifdef CONFIG_PROC_FS
@@ -464,6 +485,7 @@ static int __init sn_pci_init(void)
pcibr_init_provider();
tioca_init_provider();
+ tioce_init_provider();
/*
* This is needed to avoid bounce limit checks in the blk layer
@@ -479,8 +501,9 @@ static int __init sn_pci_init(void)
#endif
/* busses are not known yet ... */
- for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
- sn_pci_controller_fixup(0, i, NULL);
+ for (i = 0; i <= max_segment_number; i++)
+ for (j = 0; j <= max_pcibus_number; j++)
+ sn_pci_controller_fixup(i, j, NULL);
/*
* Generic Linux PCI Layer has created the pci_bus and pci_dev
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 84d276a14ecb..01d18b7b5bb3 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*/
#include <linux/irq.h>
@@ -23,7 +23,7 @@ static void force_interrupt(int irq);
static void register_intr_pda(struct sn_irq_info *sn_irq_info);
static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
-extern int sn_force_interrupt_flag;
+int sn_force_interrupt_flag = 1;
extern int sn_ioif_inited;
static struct list_head **sn_irq_lh;
static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
@@ -76,16 +76,14 @@ static void sn_enable_irq(unsigned int irq)
static void sn_ack_irq(unsigned int irq)
{
- uint64_t event_occurred, mask = 0;
- int nasid;
+ u64 event_occurred, mask = 0;
irq = irq & 0xff;
- nasid = get_nasid();
event_occurred =
- HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
+ HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
mask = event_occurred & SH_ALL_INT_MASK;
- HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS),
- mask);
+ HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
+ mask);
__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
move_irq(irq);
@@ -93,15 +91,12 @@ static void sn_ack_irq(unsigned int irq)
static void sn_end_irq(unsigned int irq)
{
- int nasid;
int ivec;
- uint64_t event_occurred;
+ u64 event_occurred;
ivec = irq & 0xff;
if (ivec == SGI_UART_VECTOR) {
- nasid = get_nasid();
- event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
- (nasid, SH_EVENT_OCCURRED));
+ event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
/* If the UART bit is set here, we may have received an
* interrupt from the UART that the driver missed. To
* make sure, we IPI ourselves to force us to look again.
@@ -132,6 +127,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
int local_widget, status;
nasid_t local_nasid;
struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *pci_provider;
new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
if (new_irq_info == NULL)
@@ -171,8 +167,9 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
new_irq_info->irq_cpuid = cpuid;
register_intr_pda(new_irq_info);
- if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type))
- pcibr_change_devices_irq(new_irq_info);
+ pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
+ if (pci_provider && pci_provider->target_interrupt)
+ (pci_provider->target_interrupt)(new_irq_info);
spin_lock(&sn_irq_info_lock);
list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
@@ -317,6 +314,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
pci_dev_put(pci_dev);
}
+static inline void
+sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
+{
+ struct sn_pcibus_provider *pci_provider;
+
+ pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
+ if (pci_provider && pci_provider->force_interrupt)
+ (*pci_provider->force_interrupt)(sn_irq_info);
+}
+
static void force_interrupt(int irq)
{
struct sn_irq_info *sn_irq_info;
@@ -325,11 +332,9 @@ static void force_interrupt(int irq)
return;
rcu_read_lock();
- list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) {
- if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
- (sn_irq_info->irq_bridge != NULL))
- pcibr_force_interrupt(sn_irq_info);
- }
+ list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
+ sn_call_force_intr_provider(sn_irq_info);
+
rcu_read_unlock();
}
@@ -351,6 +356,14 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
struct pcidev_info *pcidev_info;
struct pcibus_info *pcibus_info;
+ /*
+ * Bridge types attached to TIO (anything but PIC) do not need this WAR
+ * since they do not target Shub II interrupt registers. If that
+ * ever changes, this check needs to accomodate.
+ */
+ if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
+ return;
+
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
if (!pcidev_info)
return;
@@ -377,16 +390,12 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
break;
}
if (!test_bit(irr_bit, &irr_reg)) {
- if (!test_bit(irq, pda->sn_soft_irr)) {
- if (!test_bit(irq, pda->sn_in_service_ivecs)) {
- regval &= 0xff;
- if (sn_irq_info->irq_int_bit & regval &
- sn_irq_info->irq_last_intr) {
- regval &=
- ~(sn_irq_info->
- irq_int_bit & regval);
- pcibr_force_interrupt(sn_irq_info);
- }
+ if (!test_bit(irq, pda->sn_in_service_ivecs)) {
+ regval &= 0xff;
+ if (sn_irq_info->irq_int_bit & regval &
+ sn_irq_info->irq_last_intr) {
+ regval &= ~(sn_irq_info->irq_int_bit & regval);
+ sn_call_force_intr_provider(sn_irq_info);
}
}
}
@@ -404,13 +413,7 @@ void sn_lb_int_war_check(void)
rcu_read_lock();
for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
- /*
- * Only call for PCI bridges that are fully
- * initialized.
- */
- if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
- (sn_irq_info->irq_bridge != NULL))
- sn_check_intr(i, sn_irq_info);
+ sn_check_intr(i, sn_irq_info);
}
}
rcu_read_unlock();
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 7c7fe441d623..6f8c5883716b 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -49,6 +49,7 @@
#include <asm/sn/clksupport.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/geo.h>
+#include <asm/sn/sn_feature_sets.h>
#include "xtalk/xwidgetdev.h"
#include "xtalk/hubdev.h"
#include <asm/sn/klconfig.h>
@@ -56,7 +57,7 @@
DEFINE_PER_CPU(struct pda_s, pda_percpu);
-#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */
+#define MAX_PHYS_MEMORY (1UL << IA64_MAX_PHYS_BITS) /* Max physical address supported */
lboard_t *root_lboard[MAX_COMPACT_NODES];
@@ -80,8 +81,6 @@ EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
-partid_t sn_partid = -1;
-EXPORT_SYMBOL(sn_partid);
char sn_system_serial_number_string[128];
EXPORT_SYMBOL(sn_system_serial_number_string);
u64 sn_partition_serial_number;
@@ -99,6 +98,7 @@ EXPORT_SYMBOL(sn_region_size);
int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
short physical_node_map[MAX_PHYSNODE_ID];
+static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
EXPORT_SYMBOL(physical_node_map);
@@ -273,7 +273,10 @@ void __init sn_setup(char **cmdline_p)
u32 version = sn_sal_rev();
extern void sn_cpu_init(void);
- ia64_sn_plat_set_error_handling_features();
+ ia64_sn_plat_set_error_handling_features(); // obsolete
+ ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
+ ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
+
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
/*
@@ -316,16 +319,6 @@ void __init sn_setup(char **cmdline_p)
printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
- /*
- * Confirm the SAL we're running on is recent enough...
- */
- if (version < SN_SAL_MIN_VERSION) {
- printk(KERN_ERR "This kernel needs SGI SAL version >= "
- "%x.%02x\n", SN_SAL_MIN_VERSION >> 8,
- SN_SAL_MIN_VERSION & 0x00FF);
- panic("PROM version too old\n");
- }
-
master_nasid = boot_get_nasid();
status =
@@ -403,6 +396,7 @@ static void __init sn_init_pdas(char **cmdline_p)
memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
memset(nodepdaindr[cnode]->phys_cpuid, -1,
sizeof(nodepdaindr[cnode]->phys_cpuid));
+ spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
}
/*
@@ -481,6 +475,10 @@ void __init sn_cpu_init(void)
if (nodepdaindr[0] == NULL)
return;
+ for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)
+ if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
+ break;
+
cpuid = smp_processor_id();
cpuphyid = get_sapicid();
@@ -532,8 +530,8 @@ void __init sn_cpu_init(void)
*/
{
u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
- u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_1,
- SH2_PIO_WRITE_STATUS_2, SH2_PIO_WRITE_STATUS_3};
+ u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2,
+ SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
u64 *pio;
pio = is_shub1() ? pio1 : pio2;
pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
@@ -652,3 +650,12 @@ nasid_slice_to_cpuid(int nasid, int slice)
return -1;
}
+
+int sn_prom_feature_available(int id)
+{
+ if (id >= BITS_PER_LONG * MAX_PROM_FEATURE_SETS)
+ return 0;
+ return test_bit(id, sn_prom_features);
+}
+EXPORT_SYMBOL(sn_prom_feature_available);
+
diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
index 96cb71d15682..3fa95065a446 100644
--- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
+++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#include <asm/types.h>
@@ -11,7 +11,7 @@
#define DEADLOCKBIT SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT
#define WRITECOUNTMASK SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
-#define ALIAS_OFFSET (SH1_PIO_WRITE_STATUS_0_ALIAS-SH1_PIO_WRITE_STATUS_0)
+#define ALIAS_OFFSET 8
.global sn2_ptc_deadlock_recovery_core
@@ -36,13 +36,15 @@ sn2_ptc_deadlock_recovery_core:
extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address
dep piowcphy=-1,piowcphy,63,1
movl mask=WRITECOUNTMASK
+ mov r8=r0
1:
add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register
- mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR
- st8.rel [scr2]=scr1;;
+ ;;
+ ld8.acq scr1=[scr2];;
5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete.
+ hint @pause
and scr2=scr1,mask;; // mask of writecount bits
cmp.ne p6,p0=zeroval,scr2
(p6) br.cond.sptk 5b
@@ -57,6 +59,7 @@ sn2_ptc_deadlock_recovery_core:
st8.rel [ptc0]=data0 // Write PTC0 & wait for completion.
5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
+ hint @pause
and scr2=scr1,mask;; // mask of writecount bits
cmp.ne p6,p0=zeroval,scr2
(p6) br.cond.sptk 5b;;
@@ -67,6 +70,7 @@ sn2_ptc_deadlock_recovery_core:
(p7) st8.rel [ptc1]=data1;; // Now write PTC1.
5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
+ hint @pause
and scr2=scr1,mask;; // mask of writecount bits
cmp.ne p6,p0=zeroval,scr2
(p6) br.cond.sptk 5b
@@ -77,6 +81,7 @@ sn2_ptc_deadlock_recovery_core:
srlz.i;;
////////////// END PHYSICAL MODE ////////////////////
+(p8) add r8=1,r8
(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred.
br.ret.sptk rp
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 7af05a7ac743..0a4ee50c302f 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/init.h>
@@ -20,6 +20,8 @@
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/nodemask.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/processor.h>
#include <asm/irq.h>
@@ -39,12 +41,120 @@
#include <asm/sn/nodepda.h>
#include <asm/sn/rw_mmr.h>
-void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0,
- volatile unsigned long *, unsigned long data1);
+DEFINE_PER_CPU(struct ptc_stats, ptcstats);
+DECLARE_PER_CPU(struct ptc_stats, ptcstats);
static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
-static unsigned long sn2_ptc_deadlock_count;
+void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0,
+ volatile unsigned long *, unsigned long data1);
+
+#ifdef DEBUG_PTC
+/*
+ * ptctest:
+ *
+ * xyz - 3 digit hex number:
+ * x - Force PTC purges to use shub:
+ * 0 - no force
+ * 1 - force
+ * y - interupt enable
+ * 0 - disable interrupts
+ * 1 - leave interuupts enabled
+ * z - type of lock:
+ * 0 - global lock
+ * 1 - node local lock
+ * 2 - no lock
+ *
+ * Note: on shub1, only ptctest == 0 is supported. Don't try other values!
+ */
+
+static unsigned int sn2_ptctest = 0;
+
+static int __init ptc_test(char *str)
+{
+ get_option(&str, &sn2_ptctest);
+ return 1;
+}
+__setup("ptctest=", ptc_test);
+
+static inline int ptc_lock(unsigned long *flagp)
+{
+ unsigned long opt = sn2_ptctest & 255;
+
+ switch (opt) {
+ case 0x00:
+ spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
+ break;
+ case 0x01:
+ spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp);
+ break;
+ case 0x02:
+ local_irq_save(*flagp);
+ break;
+ case 0x10:
+ spin_lock(&sn2_global_ptc_lock);
+ break;
+ case 0x11:
+ spin_lock(&sn_nodepda->ptc_lock);
+ break;
+ case 0x12:
+ break;
+ default:
+ BUG();
+ }
+ return opt;
+}
+
+static inline void ptc_unlock(unsigned long flags, int opt)
+{
+ switch (opt) {
+ case 0x00:
+ spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+ break;
+ case 0x01:
+ spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags);
+ break;
+ case 0x02:
+ local_irq_restore(flags);
+ break;
+ case 0x10:
+ spin_unlock(&sn2_global_ptc_lock);
+ break;
+ case 0x11:
+ spin_unlock(&sn_nodepda->ptc_lock);
+ break;
+ case 0x12:
+ break;
+ default:
+ BUG();
+ }
+}
+#else
+
+#define sn2_ptctest 0
+
+static inline int ptc_lock(unsigned long *flagp)
+{
+ spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
+ return 0;
+}
+
+static inline void ptc_unlock(unsigned long flags, int opt)
+{
+ spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+}
+#endif
+
+struct ptc_stats {
+ unsigned long ptc_l;
+ unsigned long change_rid;
+ unsigned long shub_ptc_flushes;
+ unsigned long nodes_flushed;
+ unsigned long deadlocks;
+ unsigned long lock_itc_clocks;
+ unsigned long shub_itc_clocks;
+ unsigned long shub_itc_clocks_max;
+};
static inline unsigned long wait_piowc(void)
{
@@ -89,9 +199,9 @@ void
sn2_global_tlb_purge(unsigned long start, unsigned long end,
unsigned long nbits)
{
- int i, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
+ int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
volatile unsigned long *ptc0, *ptc1;
- unsigned long flags = 0, data0 = 0, data1 = 0;
+ unsigned long itc, itc2, flags, data0 = 0, data1 = 0;
struct mm_struct *mm = current->active_mm;
short nasids[MAX_NUMNODES], nix;
nodemask_t nodes_flushed;
@@ -114,16 +224,19 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
start += (1UL << nbits);
} while (start < end);
ia64_srlz_i();
+ __get_cpu_var(ptcstats).ptc_l++;
preempt_enable();
return;
}
if (atomic_read(&mm->mm_users) == 1) {
flush_tlb_mm(mm);
+ __get_cpu_var(ptcstats).change_rid++;
preempt_enable();
return;
}
+ itc = ia64_get_itc();
nix = 0;
for_each_node_mask(cnode, nodes_flushed)
nasids[nix++] = cnodeid_to_nasid(cnode);
@@ -148,7 +261,12 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
mynasid = get_nasid();
- spin_lock_irqsave(&sn2_global_ptc_lock, flags);
+ itc = ia64_get_itc();
+ opt = ptc_lock(&flags);
+ itc2 = ia64_get_itc();
+ __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc;
+ __get_cpu_var(ptcstats).shub_ptc_flushes++;
+ __get_cpu_var(ptcstats).nodes_flushed += nix;
do {
if (shub1)
@@ -157,7 +275,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
for (i = 0; i < nix; i++) {
nasid = nasids[i];
- if (unlikely(nasid == mynasid)) {
+ if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid)) {
ia64_ptcga(start, nbits << 2);
ia64_srlz_i();
} else {
@@ -169,18 +287,22 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
flushed = 1;
}
}
-
if (flushed
&& (wait_piowc() &
- SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK)) {
- sn2_ptc_deadlock_recovery(ptc0, data0, ptc1, data1);
+ (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) {
+ sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1);
}
start += (1UL << nbits);
} while (start < end);
- spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+ itc2 = ia64_get_itc() - itc2;
+ __get_cpu_var(ptcstats).shub_itc_clocks += itc2;
+ if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
+ __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;
+
+ ptc_unlock(flags, opt);
preempt_enable();
}
@@ -192,31 +314,29 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
* TLB flush transaction. The recovery sequence is somewhat tricky & is
* coded in assembly language.
*/
-void sn2_ptc_deadlock_recovery(volatile unsigned long *ptc0, unsigned long data0,
+void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0,
volatile unsigned long *ptc1, unsigned long data1)
{
extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long);
- int cnode, mycnode, nasid;
- volatile unsigned long *piows;
- volatile unsigned long zeroval;
+ short nasid, i;
+ unsigned long *piows, zeroval;
- sn2_ptc_deadlock_count++;
+ __get_cpu_var(ptcstats).deadlocks++;
- piows = pda->pio_write_status_addr;
+ piows = (unsigned long *) pda->pio_write_status_addr;
zeroval = pda->pio_write_status_val;
- mycnode = numa_node_id();
-
- for_each_online_node(cnode) {
- if (is_headless_node(cnode) || cnode == mycnode)
+ for (i=0; i < nix; i++) {
+ nasid = nasids[i];
+ if (!(sn2_ptctest & 3) && nasid == mynasid)
continue;
- nasid = cnodeid_to_nasid(cnode);
ptc0 = CHANGE_NASID(nasid, ptc0);
if (ptc1)
ptc1 = CHANGE_NASID(nasid, ptc1);
sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
}
+
}
/**
@@ -293,3 +413,93 @@ void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
}
+
+#ifdef CONFIG_PROC_FS
+
+#define PTC_BASENAME "sgi_sn/ptc_statistics"
+
+static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset)
+{
+ if (*offset < NR_CPUS)
+ return offset;
+ return NULL;
+}
+
+static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset)
+{
+ (*offset)++;
+ if (*offset < NR_CPUS)
+ return offset;
+ return NULL;
+}
+
+static void sn2_ptc_seq_stop(struct seq_file *file, void *data)
+{
+}
+
+static int sn2_ptc_seq_show(struct seq_file *file, void *data)
+{
+ struct ptc_stats *stat;
+ int cpu;
+
+ cpu = *(loff_t *) data;
+
+ if (!cpu) {
+ seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n");
+ seq_printf(file, "# ptctest %d\n", sn2_ptctest);
+ }
+
+ if (cpu < NR_CPUS && cpu_online(cpu)) {
+ stat = &per_cpu(ptcstats, cpu);
+ seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
+ stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
+ stat->deadlocks,
+ 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
+ 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
+ 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec);
+ }
+
+ return 0;
+}
+
+static struct seq_operations sn2_ptc_seq_ops = {
+ .start = sn2_ptc_seq_start,
+ .next = sn2_ptc_seq_next,
+ .stop = sn2_ptc_seq_stop,
+ .show = sn2_ptc_seq_show
+};
+
+int sn2_ptc_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &sn2_ptc_seq_ops);
+}
+
+static struct file_operations proc_sn2_ptc_operations = {
+ .open = sn2_ptc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct proc_dir_entry *proc_sn2_ptc;
+
+static int __init sn2_ptc_init(void)
+{
+ if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {
+ printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
+ return -EINVAL;
+ }
+ proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;
+ spin_lock_init(&sn2_global_ptc_lock);
+ return 0;
+}
+
+static void __exit sn2_ptc_exit(void)
+{
+ remove_proc_entry(PTC_BASENAME, NULL);
+}
+
+module_init(sn2_ptc_init);
+module_exit(sn2_ptc_exit);
+#endif /* CONFIG_PROC_FS */
+
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 833e700fdac9..0513aacac8c1 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -36,7 +36,6 @@
#include <asm/topology.h>
#include <asm/smp.h>
#include <asm/semaphore.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/sal.h>
#include <asm/sn/io.h>
@@ -59,7 +58,7 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
struct sn_hwperf_object_info *objbuf = NULL;
if ((e = sn_hwperf_init()) < 0) {
- printk("sn_hwperf_init failed: err %d\n", e);
+ printk(KERN_ERR "sn_hwperf_init failed: err %d\n", e);
goto out;
}
@@ -111,7 +110,7 @@ static int sn_hwperf_geoid_to_cnode(char *location)
if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
return -1;
- for (cnode = 0; cnode < numionodes; cnode++) {
+ for_each_node(cnode) {
geoid = cnodeid_get_geoid(cnode);
module_id = geo_module(geoid);
this_rack = MODULE_GET_RACK(module_id);
@@ -124,11 +123,13 @@ static int sn_hwperf_geoid_to_cnode(char *location)
}
}
- return cnode < numionodes ? cnode : -1;
+ return node_possible(cnode) ? cnode : -1;
}
static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
{
+ if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
+ BUG();
if (!obj->sn_hwp_this_part)
return -1;
return sn_hwperf_geoid_to_cnode(obj->location);
@@ -174,31 +175,199 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
return slabname;
}
-static void print_pci_topology(struct seq_file *s,
- struct sn_hwperf_object_info *obj, int *ordinal,
- u64 rack, u64 bay, u64 slot, u64 slab)
+static void print_pci_topology(struct seq_file *s)
+{
+ char *p;
+ size_t sz;
+ int e;
+
+ for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
+ if (!(p = (char *)kmalloc(sz, GFP_KERNEL)))
+ break;
+ e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
+ if (e == SALRET_OK)
+ seq_puts(s, p);
+ kfree(p);
+ if (e == SALRET_OK || e == SALRET_NOT_IMPLEMENTED)
+ break;
+ }
+}
+
+static inline int sn_hwperf_has_cpus(cnodeid_t node)
+{
+ return node_online(node) && nr_cpus_node(node);
+}
+
+static inline int sn_hwperf_has_mem(cnodeid_t node)
+{
+ return node_online(node) && NODE_DATA(node)->node_present_pages;
+}
+
+static struct sn_hwperf_object_info *
+sn_hwperf_findobj_id(struct sn_hwperf_object_info *objbuf,
+ int nobj, int id)
{
- char *p1;
- char *p2;
- char *pg;
-
- if (!(pg = (char *)get_zeroed_page(GFP_KERNEL)))
- return; /* ignore */
- if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab,
- __pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) {
- for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) {
- if (!(p2 = strchr(p1, '\n')))
+ int i;
+ struct sn_hwperf_object_info *p = objbuf;
+
+ for (i=0; i < nobj; i++, p++) {
+ if (p->id == id)
+ return p;
+ }
+
+ return NULL;
+
+}
+
+static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objbuf,
+ int nobj, cnodeid_t node, cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
+{
+ int e;
+ struct sn_hwperf_object_info *nodeobj = NULL;
+ struct sn_hwperf_object_info *op;
+ struct sn_hwperf_object_info *dest;
+ struct sn_hwperf_object_info *router;
+ struct sn_hwperf_port_info ptdata[16];
+ int sz, i, j;
+ cnodeid_t c;
+ int found_mem = 0;
+ int found_cpu = 0;
+
+ if (!node_possible(node))
+ return -EINVAL;
+
+ if (sn_hwperf_has_cpus(node)) {
+ if (near_cpu_node)
+ *near_cpu_node = node;
+ found_cpu++;
+ }
+
+ if (sn_hwperf_has_mem(node)) {
+ if (near_mem_node)
+ *near_mem_node = node;
+ found_mem++;
+ }
+
+ if (found_cpu && found_mem)
+ return 0; /* trivially successful */
+
+ /* find the argument node object */
+ for (i=0, op=objbuf; i < nobj; i++, op++) {
+ if (!SN_HWPERF_IS_NODE(op) && !SN_HWPERF_IS_IONODE(op))
+ continue;
+ if (node == sn_hwperf_obj_to_cnode(op)) {
+ nodeobj = op;
+ break;
+ }
+ }
+ if (!nodeobj) {
+ e = -ENOENT;
+ goto err;
+ }
+
+ /* get it's interconnect topology */
+ sz = op->ports * sizeof(struct sn_hwperf_port_info);
+ if (sz > sizeof(ptdata))
+ BUG();
+ e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+ SN_HWPERF_ENUM_PORTS, nodeobj->id, sz,
+ (u64)&ptdata, 0, 0, NULL);
+ if (e != SN_HWPERF_OP_OK) {
+ e = -EINVAL;
+ goto err;
+ }
+
+ /* 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_FOREIGN(dest) ||
+ !SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
+ continue;
+ }
+ c = sn_hwperf_obj_to_cnode(dest);
+ if (!found_cpu && sn_hwperf_has_cpus(c)) {
+ if (near_cpu_node)
+ *near_cpu_node = c;
+ found_cpu++;
+ }
+ if (!found_mem && sn_hwperf_has_mem(c)) {
+ if (near_mem_node)
+ *near_mem_node = c;
+ found_mem++;
+ }
+ if (SN_HWPERF_IS_ROUTER(dest))
+ router = dest;
+ }
+
+ if (router && (!found_cpu || !found_mem)) {
+ /* search for a node connected to the same router */
+ sz = router->ports * sizeof(struct sn_hwperf_port_info);
+ if (sz > sizeof(ptdata))
+ BUG();
+ e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+ SN_HWPERF_ENUM_PORTS, router->id, sz,
+ (u64)&ptdata, 0, 0, NULL);
+ if (e != SN_HWPERF_OP_OK) {
+ e = -EINVAL;
+ goto err;
+ }
+ for (j=0; j < router->ports; j++) {
+ dest = sn_hwperf_findobj_id(objbuf, nobj,
+ ptdata[j].conn_id);
+ if (!dest || dest->id == node ||
+ SN_HWPERF_FOREIGN(dest) ||
+ !SN_HWPERF_IS_NODE(dest) ||
+ SN_HWPERF_IS_IONODE(dest)) {
+ continue;
+ }
+ c = sn_hwperf_obj_to_cnode(dest);
+ if (!found_cpu && sn_hwperf_has_cpus(c)) {
+ if (near_cpu_node)
+ *near_cpu_node = c;
+ found_cpu++;
+ }
+ if (!found_mem && sn_hwperf_has_mem(c)) {
+ if (near_mem_node)
+ *near_mem_node = c;
+ found_mem++;
+ }
+ if (found_cpu && found_mem)
+ break;
+ }
+ }
+
+ if (!found_cpu || !found_mem) {
+ /* resort to _any_ node with CPUs and memory */
+ for (i=0, op=objbuf; i < nobj; i++, op++) {
+ if (SN_HWPERF_FOREIGN(op) ||
+ SN_HWPERF_IS_IONODE(op) ||
+ !SN_HWPERF_IS_NODE(op)) {
+ continue;
+ }
+ c = sn_hwperf_obj_to_cnode(op);
+ if (!found_cpu && sn_hwperf_has_cpus(c)) {
+ if (near_cpu_node)
+ *near_cpu_node = c;
+ found_cpu++;
+ }
+ if (!found_mem && sn_hwperf_has_mem(c)) {
+ if (near_mem_node)
+ *near_mem_node = c;
+ found_mem++;
+ }
+ if (found_cpu && found_mem)
break;
- *p2 = '\0';
- seq_printf(s, "pcibus %d %s-%s\n",
- *ordinal, obj->location, p1);
- (*ordinal)++;
- p1 = p2 + 1;
}
}
- free_page((unsigned long)pg);
+
+ if (!found_cpu || !found_mem)
+ e = -ENODATA;
+
+err:
+ return e;
}
+
static int sn_topology_show(struct seq_file *s, void *d)
{
int sz;
@@ -215,7 +384,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
struct sn_hwperf_object_info *p;
struct sn_hwperf_object_info *obj = d; /* this object */
struct sn_hwperf_object_info *objs = s->private; /* all objects */
- int rack, bay, slot, slab;
u8 shubtype;
u8 system_size;
u8 sharing_size;
@@ -225,7 +393,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
u8 region_size;
u16 nasid_mask;
int nasid_msb;
- int pci_bus_ordinal = 0;
if (obj == objs) {
seq_printf(s, "# sn_topology version 2\n");
@@ -253,6 +420,8 @@ static int sn_topology_show(struct seq_file *s, void *d)
shubtype ? "shub2" : "shub1",
(u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
system_size, sharing_size, coher, region_size);
+
+ print_pci_topology(s);
}
if (SN_HWPERF_FOREIGN(obj)) {
@@ -272,11 +441,24 @@ static int sn_topology_show(struct seq_file *s, void *d)
if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
seq_putc(s, '\n');
else {
+ cnodeid_t near_mem = -1;
+ cnodeid_t near_cpu = -1;
+
seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
- for (i=0; i < numionodes; i++) {
- seq_printf(s, i ? ":%d" : ", dist %d",
- node_distance(ordinal, i));
+
+ if (sn_hwperf_get_nearest_node_objdata(objs, sn_hwperf_obj_cnt,
+ ordinal, &near_mem, &near_cpu) == 0) {
+ seq_printf(s, ", near_mem_nodeid %d, near_cpu_nodeid %d",
+ near_mem, near_cpu);
+ }
+
+ if (!SN_HWPERF_IS_IONODE(obj)) {
+ for_each_online_node(i) {
+ seq_printf(s, i ? ":%d" : ", dist %d",
+ node_distance(ordinal, i));
+ }
}
+
seq_putc(s, '\n');
/*
@@ -300,17 +482,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
seq_putc(s, '\n');
}
}
-
- /*
- * PCI busses attached to this node, if any
- */
- if (sn_hwperf_location_to_bpos(obj->location,
- &rack, &bay, &slot, &slab)) {
- /* export pci bus info */
- print_pci_topology(s, obj, &pci_bus_ordinal,
- rack, bay, slot, slab);
-
- }
}
if (obj->ports) {
@@ -572,6 +743,8 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
memset(p, 0, a.sz);
for (i = 0; i < nobj; i++) {
+ if (!SN_HWPERF_IS_NODE(objs + i))
+ continue;
node = sn_hwperf_obj_to_cnode(objs + i);
for_each_online_cpu(j) {
if (node != cpu_to_node(j))
@@ -598,7 +771,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
case SN_HWPERF_GET_NODE_NASID:
if (a.sz != sizeof(u64) ||
- (node = a.arg) < 0 || node >= numionodes) {
+ (node = a.arg) < 0 || !node_possible(node)) {
r = -EINVAL;
goto error;
}
@@ -627,6 +800,14 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
vfree(objs);
goto error;
}
+
+ if (!SN_HWPERF_IS_NODE(objs + i) &&
+ !SN_HWPERF_IS_IONODE(objs + i)) {
+ r = -ENOENT;
+ vfree(objs);
+ goto error;
+ }
+
*(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i);
vfree(objs);
}
@@ -692,6 +873,7 @@ static int sn_hwperf_init(void)
/* single threaded, once-only initialization */
down(&sn_hwperf_init_mutex);
+
if (sn_hwperf_salheap) {
up(&sn_hwperf_init_mutex);
return e;
@@ -742,19 +924,6 @@ out:
sn_hwperf_salheap = NULL;
sn_hwperf_obj_cnt = 0;
}
-
- if (!e) {
- /*
- * Register a dynamic misc device for ioctl. Platforms
- * supporting hotplug will create /dev/sn_hwperf, else
- * user can to look up the minor number in /proc/misc.
- */
- if ((e = misc_register(&sn_hwperf_dev)) != 0) {
- printk(KERN_ERR "sn_hwperf_init: misc register "
- "for \"sn_hwperf\" failed, err %d\n", e);
- }
- }
-
up(&sn_hwperf_init_mutex);
return e;
}
@@ -782,3 +951,41 @@ int sn_topology_release(struct inode *inode, struct file *file)
vfree(seq->private);
return seq_release(inode, file);
}
+
+int sn_hwperf_get_nearest_node(cnodeid_t node,
+ cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
+{
+ int e;
+ int nobj;
+ struct sn_hwperf_object_info *objbuf;
+
+ if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
+ e = sn_hwperf_get_nearest_node_objdata(objbuf, nobj,
+ node, near_mem_node, near_cpu_node);
+ vfree(objbuf);
+ }
+
+ return e;
+}
+
+static int __devinit sn_hwperf_misc_register_init(void)
+{
+ int e;
+
+ sn_hwperf_init();
+
+ /*
+ * Register a dynamic misc device for hwperf ioctls. Platforms
+ * supporting hotplug will create /dev/sn_hwperf, else user
+ * can to look up the minor number in /proc/misc.
+ */
+ if ((e = misc_register(&sn_hwperf_dev)) != 0) {
+ printk(KERN_ERR "sn_hwperf_misc_register_init: failed to "
+ "register misc device for \"%s\"\n", sn_hwperf_dev.name);
+ }
+
+ return e;
+}
+
+device_initcall(sn_hwperf_misc_register_init); /* after misc_init() */
+EXPORT_SYMBOL(sn_hwperf_get_nearest_node);
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index 6a80fca807b9..a06719d752a0 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <asm/uaccess.h>
@@ -15,7 +15,7 @@
static int partition_id_show(struct seq_file *s, void *p)
{
- seq_printf(s, "%d\n", sn_local_partid());
+ seq_printf(s, "%d\n", sn_partition_id);
return 0;
}
@@ -52,7 +52,7 @@ static int licenseID_open(struct inode *inode, struct file *file)
* the bridge chip. The hardware will then send an interrupt message if the
* interrupt line is active. This mimics a level sensitive interrupt.
*/
-int sn_force_interrupt_flag = 1;
+extern int sn_force_interrupt_flag;
static int sn_force_interrupt_show(struct seq_file *s, void *p)
{
diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
index cde7375390b0..adf5db2e2afe 100644
--- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c
+++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
@@ -1,7 +1,7 @@
/*
*
*
- * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -50,14 +50,16 @@ void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT);
}
- if (enable_shub_wars_1_1()) {
- /* Bugfix code for SHUB 1.1 */
- if (pda->pio_shub_war_cam_addr)
- *pda->pio_shub_war_cam_addr = 0x8000000000000010UL;
+ if (is_shub1()) {
+ if (enable_shub_wars_1_1()) {
+ /* Bugfix code for SHUB 1.1 */
+ if (pda->pio_shub_war_cam_addr)
+ *pda->pio_shub_war_cam_addr = 0x8000000000000010UL;
+ }
+ if (pda->sn_lb_int_war_ticks == 0)
+ sn_lb_int_war_check();
+ pda->sn_lb_int_war_ticks++;
+ if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
+ pda->sn_lb_int_war_ticks = 0;
}
- if (pda->sn_lb_int_war_ticks == 0)
- sn_lb_int_war_check();
- pda->sn_lb_int_war_ticks++;
- if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
- pda->sn_lb_int_war_ticks = 0;
}
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 254fe15c064b..b45db5133f55 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -191,7 +191,7 @@ cx_device_register(nasid_t nasid, int part_num, int mfg_num,
{
struct cx_dev *cx_dev;
- cx_dev = kcalloc(1, sizeof(struct cx_dev), GFP_KERNEL);
+ cx_dev = kzalloc(sizeof(struct cx_dev), GFP_KERNEL);
DBG("cx_dev= 0x%p\n", cx_dev);
if (cx_dev == NULL)
return -ENOMEM;
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index bb1d5cf30440..ed7c21586e98 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -885,6 +885,10 @@ xpc_init(void)
pid_t pid;
+ if (!ia64_platform_is("sn2")) {
+ return -ENODEV;
+ }
+
/*
* xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
* both a partition's reserved page and its XPC variables. Its size was
diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
index 78c13d676fa6..e5c6d3c0a8e9 100644
--- a/arch/ia64/sn/kernel/xpnet.c
+++ b/arch/ia64/sn/kernel/xpnet.c
@@ -130,7 +130,7 @@ struct net_device *xpnet_device;
*/
static u64 xpnet_broadcast_partitions;
/* protect above */
-static spinlock_t xpnet_broadcast_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(xpnet_broadcast_lock);
/*
* Since the Block Transfer Engine (BTE) is being used for the transfer
@@ -636,6 +636,10 @@ xpnet_init(void)
int result = -ENOMEM;
+ if (!ia64_platform_is("sn2")) {
+ return -ENODEV;
+ }
+
dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
/*
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index 2f915bce25f9..321576b1b425 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,4 +7,4 @@
#
# Makefile for the sn pci general routines.
-obj-y := pci_dma.o tioca_provider.o pcibr/
+obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index b058dc2a0b9d..34093476e965 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
@@ -215,8 +215,8 @@ void sn_dma_flush(uint64_t addr)
int is_tio;
int wid_num;
int i, j;
- int bwin;
uint64_t flags;
+ uint64_t itte;
struct hubdev_info *hubinfo;
volatile struct sn_flush_device_list *p;
struct sn_flush_nasid_entry *flush_nasid_list;
@@ -233,31 +233,36 @@ void sn_dma_flush(uint64_t addr)
if (!hubinfo) {
BUG();
}
- is_tio = (nasid & 1);
- if (is_tio) {
- wid_num = TIO_SWIN_WIDGETNUM(addr);
- bwin = TIO_BWIN_WINDOWNUM(addr);
- } else {
- wid_num = SWIN_WIDGETNUM(addr);
- bwin = BWIN_WINDOWNUM(addr);
- }
flush_nasid_list = &hubinfo->hdi_flush_nasid_list;
if (flush_nasid_list->widget_p == NULL)
return;
- if (bwin > 0) {
- uint64_t itte = flush_nasid_list->iio_itte[bwin];
- if (is_tio) {
- wid_num = (itte >> TIO_ITTE_WIDGET_SHIFT) &
- TIO_ITTE_WIDGET_MASK;
- } else {
- wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) &
- IIO_ITTE_WIDGET_MASK;
- }
+ is_tio = (nasid & 1);
+ if (is_tio) {
+ int itte_index;
+
+ if (TIO_HWIN(addr))
+ itte_index = 0;
+ else if (TIO_BWIN_WINDOWNUM(addr))
+ itte_index = TIO_BWIN_WINDOWNUM(addr);
+ else
+ itte_index = -1;
+
+ if (itte_index >= 0) {
+ itte = flush_nasid_list->iio_itte[itte_index];
+ if (! TIO_ITTE_VALID(itte))
+ return;
+ wid_num = TIO_ITTE_WIDGET(itte);
+ } else
+ wid_num = TIO_SWIN_WIDGETNUM(addr);
+ } else {
+ if (BWIN_WINDOWNUM(addr)) {
+ itte = flush_nasid_list->iio_itte[BWIN_WINDOWNUM(addr)];
+ wid_num = IIO_ITTE_WIDGET(itte);
+ } else
+ wid_num = SWIN_WIDGETNUM(addr);
}
- if (flush_nasid_list->widget_p == NULL)
- return;
if (flush_nasid_list->widget_p[wid_num] == NULL)
return;
p = &flush_nasid_list->widget_p[wid_num][0];
@@ -283,10 +288,16 @@ void sn_dma_flush(uint64_t addr)
/*
* For TIOCP use the Device(x) Write Request Buffer Flush Bridge
* register since it ensures the data has entered the coherence
- * domain, unlike PIC
+ * domain, unlike PIC.
*/
if (is_tio) {
- uint32_t tio_id = REMOTE_HUB_L(nasid, TIO_NODE_ID);
+ /*
+ * Note: devices behind TIOCE should never be matched in the
+ * above code, and so the following code is PIC/CP centric.
+ * If CE ever needs the sn_dma_flush mechanism, we will have
+ * to account for that here and in tioce_bus_fixup().
+ */
+ uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id);
/* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */
@@ -306,7 +317,8 @@ void sn_dma_flush(uint64_t addr)
*(volatile uint32_t *)(p->sfdl_force_int_addr) = 1;
/* wait for the interrupt to come back. */
- while (*(p->sfdl_flush_addr) != 0x10f) ;
+ while (*(p->sfdl_flush_addr) != 0x10f)
+ cpu_relax();
/* okay, everything is synched up. */
spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index b95e928636a1..7b03b8084ffc 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -15,6 +15,7 @@
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/sn_sal.h>
+#include <asm/sn/sn2/sn_hwperf.h>
#include "xtalk/xwidgetdev.h"
#include "xtalk/hubdev.h"
@@ -60,7 +61,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
ret_stuff.status = 0;
ret_stuff.v0 = 0;
- segment = 0;
+ segment = soft->pbi_buscommon.bs_persist_segment;
busnum = soft->pbi_buscommon.bs_persist_busnum;
SAL_CALL_NOLOCK(ret_stuff,
(u64) SN_SAL_IOIF_ERROR_INTERRUPT,
@@ -88,6 +89,7 @@ void *
pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
{
int nasid, cnode, j;
+ cnodeid_t near_cnode;
struct hubdev_info *hubdev_info;
struct pcibus_info *soft;
struct sn_flush_device_list *sn_flush_device_list;
@@ -115,7 +117,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
/*
* register the bridge's error interrupt handler
*/
- if (request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler,
+ if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler,
SA_SHIRQ, "PCIBR error", (void *)(soft))) {
printk(KERN_WARNING
"pcibr cannot allocate interrupt for error handler\n");
@@ -142,9 +144,12 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
j++, sn_flush_device_list++) {
if (sn_flush_device_list->sfdl_slot == -1)
continue;
- if (sn_flush_device_list->
- sfdl_persistent_busnum ==
- soft->pbi_buscommon.bs_persist_busnum)
+ if ((sn_flush_device_list->
+ sfdl_persistent_segment ==
+ soft->pbi_buscommon.bs_persist_segment) &&
+ (sn_flush_device_list->
+ sfdl_persistent_busnum ==
+ soft->pbi_buscommon.bs_persist_busnum))
sn_flush_device_list->sfdl_pcibus_info =
soft;
}
@@ -158,12 +163,18 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
memset(soft->pbi_int_ate_resource.ate, 0,
(soft->pbi_int_ate_size * sizeof(uint64_t)));
- if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP)
- /*
- * TIO PCI Bridge with no closest node information.
- * FIXME: Find another way to determine the closest node
- */
- controller->node = -1;
+ if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
+ /* TIO PCI Bridge: find nearest node with CPUs */
+ int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode);
+
+ if (e < 0) {
+ near_cnode = (cnodeid_t)-1; /* use any node */
+ printk(KERN_WARNING "pcibr_bus_fixup: failed to find "
+ "near node with CPUs to TIO node %d, err=%d\n",
+ cnode, e);
+ }
+ controller->node = near_cnode;
+ }
else
controller->node = cnode;
return soft;
@@ -175,6 +186,9 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
struct pcibus_info *pcibus_info;
int bit = sn_irq_info->irq_int_bit;
+ if (! sn_irq_info->irq_bridge)
+ return;
+
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
if (pcidev_info) {
pcibus_info =
@@ -184,7 +198,7 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
}
}
-void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info)
+void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
{
struct pcidev_info *pcidev_info;
struct pcibus_info *pcibus_info;
@@ -219,6 +233,8 @@ struct sn_pcibus_provider pcibr_provider = {
.dma_map_consistent = pcibr_dma_map_consistent,
.dma_unmap = pcibr_dma_unmap,
.bus_fixup = pcibr_bus_fixup,
+ .force_interrupt = pcibr_force_interrupt,
+ .target_interrupt = pcibr_target_interrupt
};
int
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 5d76a7581465..19bced34d5f1 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -148,7 +148,7 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
tioca_kern->ca_pcigart_entries =
tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
tioca_kern->ca_pcigart_pagemap =
- kcalloc(1, tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
+ kzalloc(tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
if (!tioca_kern->ca_pcigart_pagemap) {
free_pages((unsigned long)tioca_kern->ca_gart,
get_order(tioca_kern->ca_gart_size));
@@ -392,7 +392,7 @@ tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
* allocate a map struct
*/
- ca_dmamap = kcalloc(1, sizeof(struct tioca_dmamap), GFP_ATOMIC);
+ ca_dmamap = kzalloc(sizeof(struct tioca_dmamap), GFP_ATOMIC);
if (!ca_dmamap)
goto map_return;
@@ -559,7 +559,7 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
ret_stuff.status = 0;
ret_stuff.v0 = 0;
- segment = 0;
+ segment = soft->ca_common.bs_persist_segment;
busnum = soft->ca_common.bs_persist_busnum;
SAL_CALL_NOLOCK(ret_stuff,
@@ -600,7 +600,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
* Allocate kernel bus soft and copy from prom.
*/
- tioca_common = kcalloc(1, sizeof(struct tioca_common), GFP_KERNEL);
+ tioca_common = kzalloc(sizeof(struct tioca_common), GFP_KERNEL);
if (!tioca_common)
return NULL;
@@ -609,7 +609,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
/* init kernel-private area */
- tioca_kern = kcalloc(1, sizeof(struct tioca_kernel), GFP_KERNEL);
+ tioca_kern = kzalloc(sizeof(struct tioca_kernel), GFP_KERNEL);
if (!tioca_kern) {
kfree(tioca_common);
return NULL;
@@ -622,7 +622,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
nasid_to_cnodeid(tioca_common->ca_closest_nasid);
tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
- bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum);
+ bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
+ tioca_common->ca_common.bs_persist_busnum);
BUG_ON(!bus);
tioca_kern->ca_devices = &bus->devices;
@@ -656,6 +657,8 @@ static struct sn_pcibus_provider tioca_pci_interfaces = {
.dma_map_consistent = tioca_dma_map,
.dma_unmap = tioca_dma_unmap,
.bus_fixup = tioca_bus_fixup,
+ .force_interrupt = NULL,
+ .target_interrupt = NULL
};
/**
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
new file mode 100644
index 000000000000..8e75db2b825d
--- /dev/null
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -0,0 +1,771 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/tioce_provider.h>
+
+/**
+ * Bus address ranges for the 5 flavors of TIOCE DMA
+ */
+
+#define TIOCE_D64_MIN 0x8000000000000000UL
+#define TIOCE_D64_MAX 0xffffffffffffffffUL
+#define TIOCE_D64_ADDR(a) ((a) >= TIOCE_D64_MIN)
+
+#define TIOCE_D32_MIN 0x0000000080000000UL
+#define TIOCE_D32_MAX 0x00000000ffffffffUL
+#define TIOCE_D32_ADDR(a) ((a) >= TIOCE_D32_MIN && (a) <= TIOCE_D32_MAX)
+
+#define TIOCE_M32_MIN 0x0000000000000000UL
+#define TIOCE_M32_MAX 0x000000007fffffffUL
+#define TIOCE_M32_ADDR(a) ((a) >= TIOCE_M32_MIN && (a) <= TIOCE_M32_MAX)
+
+#define TIOCE_M40_MIN 0x0000004000000000UL
+#define TIOCE_M40_MAX 0x0000007fffffffffUL
+#define TIOCE_M40_ADDR(a) ((a) >= TIOCE_M40_MIN && (a) <= TIOCE_M40_MAX)
+
+#define TIOCE_M40S_MIN 0x0000008000000000UL
+#define TIOCE_M40S_MAX 0x000000ffffffffffUL
+#define TIOCE_M40S_ADDR(a) ((a) >= TIOCE_M40S_MIN && (a) <= TIOCE_M40S_MAX)
+
+/*
+ * ATE manipulation macros.
+ */
+
+#define ATE_PAGESHIFT(ps) (__ffs(ps))
+#define ATE_PAGEMASK(ps) ((ps)-1)
+
+#define ATE_PAGE(x, ps) ((x) >> ATE_PAGESHIFT(ps))
+#define ATE_NPAGES(start, len, pagesize) \
+ (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
+
+#define ATE_VALID(ate) ((ate) & (1UL << 63))
+#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
+
+/*
+ * Flavors of ate-based mapping supported by tioce_alloc_map()
+ */
+
+#define TIOCE_ATE_M32 1
+#define TIOCE_ATE_M40 2
+#define TIOCE_ATE_M40S 3
+
+#define KB(x) ((x) << 10)
+#define MB(x) ((x) << 20)
+#define GB(x) ((x) << 30)
+
+/**
+ * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode
+ * @ct_addr: system coretalk address
+ *
+ * Map @ct_addr into 64-bit CE bus space. No device context is necessary
+ * and no CE mapping are consumed.
+ *
+ * Bits 53:0 come from the coretalk address. The remaining bits are set as
+ * follows:
+ *
+ * 63 - must be 1 to indicate d64 mode to CE hardware
+ * 62 - barrier bit ... controlled with tioce_dma_barrier()
+ * 61 - 0 since this is not an MSI transaction
+ * 60:54 - reserved, MBZ
+ */
+static uint64_t
+tioce_dma_d64(unsigned long ct_addr)
+{
+ uint64_t bus_addr;
+
+ bus_addr = ct_addr | (1UL << 63);
+
+ return bus_addr;
+}
+
+/**
+ * pcidev_to_tioce - return misc ce related pointers given a pci_dev
+ * @pci_dev: pci device context
+ * @base: ptr to store struct tioce_mmr * for the CE holding this device
+ * @kernel: ptr to store struct tioce_kernel * for the CE holding this device
+ * @port: ptr to store the CE port number that this device is on
+ *
+ * Return pointers to various CE-related structures for the CE upstream of
+ * @pci_dev.
+ */
+static inline void
+pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
+ struct tioce_kernel **kernel, int *port)
+{
+ struct pcidev_info *pcidev_info;
+ struct tioce_common *ce_common;
+ struct tioce_kernel *ce_kernel;
+
+ pcidev_info = SN_PCIDEV_INFO(pdev);
+ ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
+ ce_kernel = (struct tioce_kernel *)ce_common->ce_kernel_private;
+
+ if (base)
+ *base = (struct tioce *)ce_common->ce_pcibus.bs_base;
+ if (kernel)
+ *kernel = ce_kernel;
+
+ /*
+ * we use port as a zero-based value internally, even though the
+ * documentation is 1-based.
+ */
+ if (port)
+ *port =
+ (pdev->bus->number < ce_kernel->ce_port1_secondary) ? 0 : 1;
+}
+
+/**
+ * tioce_alloc_map - Given a coretalk address, map it to pcie bus address
+ * space using one of the various ATE-based address modes.
+ * @ce_kern: tioce context
+ * @type: map mode to use
+ * @port: 0-based port that the requesting device is downstream of
+ * @ct_addr: the coretalk address to map
+ * @len: number of bytes to map
+ *
+ * Given the addressing type, set up various paramaters that define the
+ * ATE pool to use. Search for a contiguous block of entries to cover the
+ * length, and if enough resources exist, fill in the ATE's and construct a
+ * tioce_dmamap struct to track the mapping.
+ */
+static uint64_t
+tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
+ uint64_t ct_addr, int len)
+{
+ int i;
+ int j;
+ int first;
+ int last;
+ int entries;
+ int nates;
+ int pagesize;
+ uint64_t *ate_shadow;
+ uint64_t *ate_reg;
+ uint64_t addr;
+ struct tioce *ce_mmr;
+ uint64_t bus_base;
+ struct tioce_dmamap *map;
+
+ ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
+
+ switch (type) {
+ case TIOCE_ATE_M32:
+ /*
+ * The first 64 entries of the ate3240 pool are dedicated to
+ * super-page (TIOCE_ATE_M40S) mode.
+ */
+ first = 64;
+ entries = TIOCE_NUM_M3240_ATES - 64;
+ ate_shadow = ce_kern->ce_ate3240_shadow;
+ ate_reg = ce_mmr->ce_ure_ate3240;
+ pagesize = ce_kern->ce_ate3240_pagesize;
+ bus_base = TIOCE_M32_MIN;
+ break;
+ case TIOCE_ATE_M40:
+ first = 0;
+ entries = TIOCE_NUM_M40_ATES;
+ ate_shadow = ce_kern->ce_ate40_shadow;
+ ate_reg = ce_mmr->ce_ure_ate40;
+ pagesize = MB(64);
+ bus_base = TIOCE_M40_MIN;
+ break;
+ case TIOCE_ATE_M40S:
+ /*
+ * ate3240 entries 0-31 are dedicated to port1 super-page
+ * mappings. ate3240 entries 32-63 are dedicated to port2.
+ */
+ first = port * 32;
+ entries = 32;
+ ate_shadow = ce_kern->ce_ate3240_shadow;
+ ate_reg = ce_mmr->ce_ure_ate3240;
+ pagesize = GB(16);
+ bus_base = TIOCE_M40S_MIN;
+ break;
+ default:
+ return 0;
+ }
+
+ nates = ATE_NPAGES(ct_addr, len, pagesize);
+ if (nates > entries)
+ return 0;
+
+ last = first + entries - nates;
+ for (i = first; i <= last; i++) {
+ if (ATE_VALID(ate_shadow[i]))
+ continue;
+
+ for (j = i; j < i + nates; j++)
+ if (ATE_VALID(ate_shadow[j]))
+ break;
+
+ if (j >= i + nates)
+ break;
+ }
+
+ if (i > last)
+ return 0;
+
+ map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC);
+ if (!map)
+ return 0;
+
+ addr = ct_addr;
+ for (j = 0; j < nates; j++) {
+ uint64_t ate;
+
+ ate = ATE_MAKE(addr, pagesize);
+ ate_shadow[i + j] = ate;
+ ate_reg[i + j] = ate;
+ addr += pagesize;
+ }
+
+ map->refcnt = 1;
+ map->nbytes = nates * pagesize;
+ map->ct_start = ct_addr & ~ATE_PAGEMASK(pagesize);
+ map->pci_start = bus_base + (i * pagesize);
+ map->ate_hw = &ate_reg[i];
+ map->ate_shadow = &ate_shadow[i];
+ map->ate_count = nates;
+
+ list_add(&map->ce_dmamap_list, &ce_kern->ce_dmamap_list);
+
+ return (map->pci_start + (ct_addr - map->ct_start));
+}
+
+/**
+ * tioce_dma_d32 - create a DMA mapping using 32-bit direct mode
+ * @pdev: linux pci_dev representing the function
+ * @paddr: system physical address
+ *
+ * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
+ */
+static uint64_t
+tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
+{
+ int dma_ok;
+ int port;
+ struct tioce *ce_mmr;
+ struct tioce_kernel *ce_kern;
+ uint64_t ct_upper;
+ uint64_t ct_lower;
+ dma_addr_t bus_addr;
+
+ ct_upper = ct_addr & ~0x3fffffffUL;
+ ct_lower = ct_addr & 0x3fffffffUL;
+
+ pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
+
+ if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
+ volatile uint64_t tmp;
+
+ ce_kern->ce_port[port].dirmap_shadow = ct_upper;
+ ce_mmr->ce_ure_dir_map[port] = ct_upper;
+ tmp = ce_mmr->ce_ure_dir_map[port];
+ dma_ok = 1;
+ } else
+ dma_ok = (ce_kern->ce_port[port].dirmap_shadow == ct_upper);
+
+ if (dma_ok) {
+ ce_kern->ce_port[port].dirmap_refcnt++;
+ bus_addr = TIOCE_D32_MIN + ct_lower;
+ } else
+ bus_addr = 0;
+
+ return bus_addr;
+}
+
+/**
+ * tioce_dma_barrier - swizzle a TIOCE bus address to include or exclude
+ * the barrier bit.
+ * @bus_addr: bus address to swizzle
+ *
+ * Given a TIOCE bus address, set the appropriate bit to indicate barrier
+ * attributes.
+ */
+static uint64_t
+tioce_dma_barrier(uint64_t bus_addr, int on)
+{
+ uint64_t barrier_bit;
+
+ /* barrier not supported in M40/M40S mode */
+ if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr))
+ return bus_addr;
+
+ if (TIOCE_D64_ADDR(bus_addr))
+ barrier_bit = (1UL << 62);
+ else /* must be m32 or d32 */
+ barrier_bit = (1UL << 30);
+
+ return (on) ? (bus_addr | barrier_bit) : (bus_addr & ~barrier_bit);
+}
+
+/**
+ * tioce_dma_unmap - release CE mapping resources
+ * @pdev: linux pci_dev representing the function
+ * @bus_addr: bus address returned by an earlier tioce_dma_map
+ * @dir: mapping direction (unused)
+ *
+ * Locate mapping resources associated with @bus_addr and release them.
+ * For mappings created using the direct modes there are no resources
+ * to release.
+ */
+void
+tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
+{
+ int i;
+ int port;
+ struct tioce_kernel *ce_kern;
+ struct tioce *ce_mmr;
+ unsigned long flags;
+
+ bus_addr = tioce_dma_barrier(bus_addr, 0);
+ pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
+
+ /* nothing to do for D64 */
+
+ if (TIOCE_D64_ADDR(bus_addr))
+ return;
+
+ spin_lock_irqsave(&ce_kern->ce_lock, flags);
+
+ if (TIOCE_D32_ADDR(bus_addr)) {
+ if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
+ ce_kern->ce_port[port].dirmap_shadow = 0;
+ ce_mmr->ce_ure_dir_map[port] = 0;
+ }
+ } else {
+ struct tioce_dmamap *map;
+
+ list_for_each_entry(map, &ce_kern->ce_dmamap_list,
+ ce_dmamap_list) {
+ uint64_t last;
+
+ last = map->pci_start + map->nbytes - 1;
+ if (bus_addr >= map->pci_start && bus_addr <= last)
+ break;
+ }
+
+ if (&map->ce_dmamap_list == &ce_kern->ce_dmamap_list) {
+ printk(KERN_WARNING
+ "%s: %s - no map found for bus_addr 0x%lx\n",
+ __FUNCTION__, pci_name(pdev), bus_addr);
+ } else if (--map->refcnt == 0) {
+ for (i = 0; i < map->ate_count; i++) {
+ map->ate_shadow[i] = 0;
+ map->ate_hw[i] = 0;
+ }
+
+ list_del(&map->ce_dmamap_list);
+ kfree(map);
+ }
+ }
+
+ spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
+}
+
+/**
+ * tioce_do_dma_map - map pages for PCI DMA
+ * @pdev: linux pci_dev representing the function
+ * @paddr: host physical address to map
+ * @byte_count: bytes to map
+ *
+ * This is the main wrapper for mapping host physical pages to CE PCI space.
+ * The mapping mode used is based on the device's dma_mask.
+ */
+static uint64_t
+tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
+ int barrier)
+{
+ unsigned long flags;
+ uint64_t ct_addr;
+ uint64_t mapaddr = 0;
+ struct tioce_kernel *ce_kern;
+ struct tioce_dmamap *map;
+ int port;
+ uint64_t dma_mask;
+
+ dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask;
+
+ /* cards must be able to address at least 31 bits */
+ if (dma_mask < 0x7fffffffUL)
+ return 0;
+
+ ct_addr = PHYS_TO_TIODMA(paddr);
+
+ /*
+ * If the device can generate 64 bit addresses, create a D64 map.
+ * Since this should never fail, bypass the rest of the checks.
+ */
+ if (dma_mask == ~0UL) {
+ mapaddr = tioce_dma_d64(ct_addr);
+ goto dma_map_done;
+ }
+
+ pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
+
+ spin_lock_irqsave(&ce_kern->ce_lock, flags);
+
+ /*
+ * D64 didn't work ... See if we have an existing map that covers
+ * this address range. Must account for devices dma_mask here since
+ * an existing map might have been done in a mode using more pci
+ * address bits than this device can support.
+ */
+ list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) {
+ uint64_t last;
+
+ last = map->ct_start + map->nbytes - 1;
+ if (ct_addr >= map->ct_start &&
+ ct_addr + byte_count - 1 <= last &&
+ map->pci_start <= dma_mask) {
+ map->refcnt++;
+ mapaddr = map->pci_start + (ct_addr - map->ct_start);
+ break;
+ }
+ }
+
+ /*
+ * If we don't have a map yet, and the card can generate 40
+ * bit addresses, try the M40/M40S modes. Note these modes do not
+ * support a barrier bit, so if we need a consistent map these
+ * won't work.
+ */
+ if (!mapaddr && !barrier && dma_mask >= 0xffffffffffUL) {
+ /*
+ * We have two options for 40-bit mappings: 16GB "super" ATE's
+ * and 64MB "regular" ATE's. We'll try both if needed for a
+ * given mapping but which one we try first depends on the
+ * size. For requests >64MB, prefer to use a super page with
+ * regular as the fallback. Otherwise, try in the reverse order.
+ */
+
+ if (byte_count > MB(64)) {
+ mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
+ port, ct_addr, byte_count);
+ if (!mapaddr)
+ mapaddr =
+ tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
+ ct_addr, byte_count);
+ } else {
+ mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
+ ct_addr, byte_count);
+ if (!mapaddr)
+ mapaddr =
+ tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
+ port, ct_addr, byte_count);
+ }
+ }
+
+ /*
+ * 32-bit direct is the next mode to try
+ */
+ if (!mapaddr && dma_mask >= 0xffffffffUL)
+ mapaddr = tioce_dma_d32(pdev, ct_addr);
+
+ /*
+ * Last resort, try 32-bit ATE-based map.
+ */
+ if (!mapaddr)
+ mapaddr =
+ tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
+ byte_count);
+
+ spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
+
+dma_map_done:
+ if (mapaddr & barrier)
+ mapaddr = tioce_dma_barrier(mapaddr, 1);
+
+ return mapaddr;
+}
+
+/**
+ * tioce_dma - standard pci dma map interface
+ * @pdev: pci device requesting the map
+ * @paddr: system physical address to map into pci space
+ * @byte_count: # bytes to map
+ *
+ * Simply call tioce_do_dma_map() to create a map with the barrier bit clear
+ * in the address.
+ */
+static uint64_t
+tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+{
+ return tioce_do_dma_map(pdev, paddr, byte_count, 0);
+}
+
+/**
+ * tioce_dma_consistent - consistent pci dma map interface
+ * @pdev: pci device requesting the map
+ * @paddr: system physical address to map into pci space
+ * @byte_count: # bytes to map
+ *
+ * Simply call tioce_do_dma_map() to create a map with the barrier bit set
+ * in the address.
+ */ static uint64_t
+tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+{
+ return tioce_do_dma_map(pdev, paddr, byte_count, 1);
+}
+
+/**
+ * tioce_error_intr_handler - SGI TIO CE error interrupt handler
+ * @irq: unused
+ * @arg: pointer to tioce_common struct for the given CE
+ * @pt: unused
+ *
+ * Handle a CE error interrupt. Simply a wrapper around a SAL call which
+ * defers processing to the SGI prom.
+ */ static irqreturn_t
+tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+{
+ struct tioce_common *soft = arg;
+ struct ia64_sal_retval ret_stuff;
+ ret_stuff.status = 0;
+ ret_stuff.v0 = 0;
+
+ SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
+ soft->ce_pcibus.bs_persist_segment,
+ soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * tioce_kern_init - init kernel structures related to a given TIOCE
+ * @tioce_common: ptr to a cached tioce_common struct that originated in prom
+ */ static struct tioce_kernel *
+tioce_kern_init(struct tioce_common *tioce_common)
+{
+ int i;
+ uint32_t tmp;
+ struct tioce *tioce_mmr;
+ struct tioce_kernel *tioce_kern;
+
+ tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL);
+ if (!tioce_kern) {
+ return NULL;
+ }
+
+ tioce_kern->ce_common = tioce_common;
+ spin_lock_init(&tioce_kern->ce_lock);
+ INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list);
+ tioce_common->ce_kernel_private = (uint64_t) tioce_kern;
+
+ /*
+ * Determine the secondary bus number of the port2 logical PPB.
+ * This is used to decide whether a given pci device resides on
+ * port1 or port2. Note: We don't have enough plumbing set up
+ * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
+ */
+
+ raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment,
+ tioce_common->ce_pcibus.bs_persist_busnum,
+ PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp);
+ tioce_kern->ce_port1_secondary = (uint8_t) tmp;
+
+ /*
+ * Set PMU pagesize to the largest size available, and zero out
+ * the ate's.
+ */
+
+ tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
+ tioce_mmr->ce_ure_page_map &= ~CE_URE_PAGESIZE_MASK;
+ tioce_mmr->ce_ure_page_map |= CE_URE_256K_PAGESIZE;
+ tioce_kern->ce_ate3240_pagesize = KB(256);
+
+ for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
+ tioce_kern->ce_ate40_shadow[i] = 0;
+ tioce_mmr->ce_ure_ate40[i] = 0;
+ }
+
+ for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
+ tioce_kern->ce_ate3240_shadow[i] = 0;
+ tioce_mmr->ce_ure_ate3240[i] = 0;
+ }
+
+ return tioce_kern;
+}
+
+/**
+ * tioce_force_interrupt - implement altix force_interrupt() backend for CE
+ * @sn_irq_info: sn asic irq that we need an interrupt generated for
+ *
+ * Given an sn_irq_info struct, set the proper bit in ce_adm_force_int to
+ * force a secondary interrupt to be generated. This is to work around an
+ * asic issue where there is a small window of opportunity for a legacy device
+ * interrupt to be lost.
+ */
+static void
+tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
+{
+ struct pcidev_info *pcidev_info;
+ struct tioce_common *ce_common;
+ struct tioce *ce_mmr;
+ uint64_t force_int_val;
+
+ if (!sn_irq_info->irq_bridge)
+ return;
+
+ if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_TIOCE)
+ return;
+
+ pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ if (!pcidev_info)
+ return;
+
+ ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
+ ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+
+ /*
+ * irq_int_bit is originally set up by prom, and holds the interrupt
+ * bit shift (not mask) as defined by the bit definitions in the
+ * ce_adm_int mmr. These shifts are not the same for the
+ * ce_adm_force_int register, so do an explicit mapping here to make
+ * things clearer.
+ */
+
+ switch (sn_irq_info->irq_int_bit) {
+ case CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT;
+ break;
+ case CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT:
+ force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT;
+ break;
+ default:
+ return;
+ }
+ ce_mmr->ce_adm_force_int = force_int_val;
+}
+
+/**
+ * tioce_target_interrupt - implement set_irq_affinity for tioce resident
+ * functions. Note: only applies to line interrupts, not MSI's.
+ *
+ * @sn_irq_info: SN IRQ context
+ *
+ * Given an sn_irq_info, set the associated CE device's interrupt destination
+ * register. Since the interrupt destination registers are on a per-ce-slot
+ * basis, this will retarget line interrupts for all functions downstream of
+ * the slot.
+ */
+static void
+tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
+{
+ struct pcidev_info *pcidev_info;
+ struct tioce_common *ce_common;
+ struct tioce *ce_mmr;
+ int bit;
+
+ pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ if (!pcidev_info)
+ return;
+
+ ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
+ ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+
+ bit = sn_irq_info->irq_int_bit;
+
+ ce_mmr->ce_adm_int_mask |= (1UL << bit);
+ ce_mmr->ce_adm_int_dest[bit] =
+ ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
+ sn_irq_info->irq_xtalkaddr;
+ ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
+
+ tioce_force_interrupt(sn_irq_info);
+}
+
+/**
+ * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
+ * @prom_bussoft: Common prom/kernel struct representing the bus
+ *
+ * Replicates the tioce_common pointed to by @prom_bussoft in kernel
+ * space. Allocates and initializes a kernel-only area for a given CE,
+ * and sets up an irq for handling CE error interrupts.
+ *
+ * On successful setup, returns the kernel version of tioce_common back to
+ * the caller.
+ */
+static void *
+tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
+{
+ struct tioce_common *tioce_common;
+
+ /*
+ * Allocate kernel bus soft and copy from prom.
+ */
+
+ tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL);
+ if (!tioce_common)
+ return NULL;
+
+ memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
+ tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
+
+ if (tioce_kern_init(tioce_common) == NULL) {
+ kfree(tioce_common);
+ return NULL;
+ }
+
+ if (request_irq(SGI_PCIASIC_ERROR,
+ tioce_error_intr_handler,
+ SA_SHIRQ, "TIOCE error", (void *)tioce_common))
+ printk(KERN_WARNING
+ "%s: Unable to get irq %d. "
+ "Error interrupts won't be routed for "
+ "TIOCE bus %04x:%02x\n",
+ __FUNCTION__, SGI_PCIASIC_ERROR,
+ tioce_common->ce_pcibus.bs_persist_segment,
+ tioce_common->ce_pcibus.bs_persist_busnum);
+
+ return tioce_common;
+}
+
+static struct sn_pcibus_provider tioce_pci_interfaces = {
+ .dma_map = tioce_dma,
+ .dma_map_consistent = tioce_dma_consistent,
+ .dma_unmap = tioce_dma_unmap,
+ .bus_fixup = tioce_bus_fixup,
+ .force_interrupt = tioce_force_interrupt,
+ .target_interrupt = tioce_target_interrupt
+};
+
+/**
+ * tioce_init_provider - init SN PCI provider ops for TIO CE
+ */
+int
+tioce_init_provider(void)
+{
+ sn_pci_provider[PCIIO_ASIC_TYPE_TIOCE] = &tioce_pci_interfaces;
+ return 0;
+}
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 7622d4ec5f08..1ef3987ebc6a 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -242,8 +242,8 @@ config SMP
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.tex>,
- <file:Documentation/smp.txt> and the SMP-HOWTO available at
+ See also the <file:Documentation/smp.txt>,
+ and the SMP-HOWTO available at
<http://www.linuxdoc.org/docs.html#howto>.
If you don't know what to do here, say N.
diff --git a/arch/m32r/kernel/asm-offsets.c b/arch/m32r/kernel/asm-offsets.c
new file mode 100644
index 000000000000..9e263112a6e2
--- /dev/null
+++ b/arch/m32r/kernel/asm-offsets.c
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 5aef7e406ef5..71763f7a1d19 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -341,13 +341,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up the stack frame */
setup_rt_frame(sig, ka, info, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
index 48b187f2d2b3..a4576ac7e870 100644
--- a/arch/m32r/kernel/smp.c
+++ b/arch/m32r/kernel/smp.c
@@ -892,7 +892,6 @@ unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
int try)
{
spinlock_t *ipilock;
- unsigned long flags = 0;
volatile unsigned long *ipicr_addr;
unsigned long ipicr_val;
unsigned long my_physid_mask;
@@ -916,50 +915,27 @@ unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
* write IPICRi (send IPIi)
* unlock ipi_lock[i]
*/
+ spin_lock(ipilock);
__asm__ __volatile__ (
- ";; LOCK ipi_lock[i] \n\t"
+ ";; CHECK IPICRi == 0 \n\t"
".fillinsn \n"
"1: \n\t"
- "mvfc %1, psw \n\t"
- "clrpsw #0x40 -> nop \n\t"
- DCACHE_CLEAR("r4", "r5", "%2")
- "lock r4, @%2 \n\t"
- "addi r4, #-1 \n\t"
- "unlock r4, @%2 \n\t"
- "mvtc %1, psw \n\t"
- "bnez r4, 2f \n\t"
- LOCK_SECTION_START(".balign 4 \n\t")
- ".fillinsn \n"
- "2: \n\t"
- "ld r4, @%2 \n\t"
- "blez r4, 2b \n\t"
+ "ld %0, @%1 \n\t"
+ "and %0, %4 \n\t"
+ "beqz %0, 2f \n\t"
+ "bnez %3, 3f \n\t"
"bra 1b \n\t"
- LOCK_SECTION_END
- ";; CHECK IPICRi == 0 \n\t"
- ".fillinsn \n"
- "3: \n\t"
- "ld %0, @%3 \n\t"
- "and %0, %6 \n\t"
- "beqz %0, 4f \n\t"
- "bnez %5, 5f \n\t"
- "bra 3b \n\t"
";; WRITE IPICRi (send IPIi) \n\t"
".fillinsn \n"
- "4: \n\t"
- "st %4, @%3 \n\t"
- ";; UNLOCK ipi_lock[i] \n\t"
+ "2: \n\t"
+ "st %2, @%1 \n\t"
".fillinsn \n"
- "5: \n\t"
- "ldi r4, #1 \n\t"
- "st r4, @%2 \n\t"
+ "3: \n\t"
: "=&r"(ipicr_val)
- : "r"(flags), "r"(&ipilock->slock), "r"(ipicr_addr),
- "r"(mask), "r"(try), "r"(my_physid_mask)
- : "memory", "r4"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r5"
-#endif /* CONFIG_CHIP_M32700_TS1 */
+ : "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask)
+ : "memory"
);
+ spin_unlock(ipilock);
return ipicr_val;
}
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 8a2b77bc5749..539c562cd54d 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -171,10 +171,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -221,7 +218,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* called as close as possible to 500 ms before the new second starts.
*/
write_seqlock(&xtime_lock);
- if ((time_status & STA_UNSYNC) == 0
+ 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)
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 178c4a3fbb72..ba960bbc8e6d 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -25,6 +25,11 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ depends on Q40 || (BROKEN && SUN3X)
+ default y
+
mainmenu "Linux/68k Kernel Configuration"
source "init/Kconfig"
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 466e7407afc7..34d826d10f1b 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -113,14 +113,5 @@ else
bzip2 -1c vmlinux >vmlinux.bz2
endif
-prepare: include/asm-$(ARCH)/offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
archclean:
rm -f vmlinux.gz vmlinux.bz2
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index cb5d93630467..bd5d134e9f12 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -63,7 +63,7 @@ void __init amiga_init_sound(void)
}
static void nosound( unsigned long ignored );
-static struct timer_list sound_timer = TIMER_INITIALIZER(nosound, 0, 0);
+static DEFINE_TIMER(sound_timer, nosound, 0, 0);
void amiga_mksound( unsigned int hz, unsigned int ticks )
{
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index c6b2a410bf9a..eb63ca6ed94c 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -14,6 +14,7 @@
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
+#include <linux/module.h>
#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
#include <linux/smp_lock.h>
#include <asm/bvme6000hw.h>
@@ -171,7 +172,7 @@ static struct miscdevice rtc_dev = {
.fops = &rtc_fops
};
-int __init rtc_DP8570A_init(void)
+static int __init rtc_DP8570A_init(void)
{
if (!MACH_IS_BVME6000)
return -ENODEV;
@@ -179,4 +180,4 @@ int __init rtc_DP8570A_init(void)
printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION);
return misc_register(&rtc_dev);
}
-
+module_init(rtc_DP8570A_init);
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index dbc1255a5e99..9571a21d6ad4 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -40,7 +40,7 @@
#include <linux/linkage.h>
#include <asm/entry.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
index 803a6ecdda81..4ba2c74da93d 100644
--- a/arch/m68k/ifpsp060/iskeleton.S
+++ b/arch/m68k/ifpsp060/iskeleton.S
@@ -36,7 +36,7 @@
#include <linux/linkage.h>
#include <asm/entry.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
|################################
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index e964015a31dc..23ca60a45552 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -42,7 +42,7 @@
#include <asm/traps.h>
#include <asm/unistd.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.globl system_call, buserr, trap
.globl resume, ret_from_exception
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 7cd6de17c20d..d4336d846df1 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -263,7 +263,7 @@
#include <asm/entry.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_MAC
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index fe837e31afbf..73e2f5e168dd 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -74,10 +74,6 @@ EXPORT_SYMBOL(vme_brdtype);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__down_failed);
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index f4e1e5eb8e12..8ed1b01a6a87 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -95,7 +95,7 @@ static inline int put_reg(struct task_struct *task, int regno,
if (regno == PT_USP)
addr = &task->thread.usp;
else if (regno < sizeof(regoff)/sizeof(regoff[0]))
- addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
+ addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
else
return -1;
*addr = data;
@@ -103,48 +103,56 @@ static inline int put_reg(struct task_struct *task, int regno,
}
/*
- * Called by kernel/ptrace.c when detaching..
- *
* Make sure the single step bit is not set.
*/
-void ptrace_disable(struct task_struct *child)
+static inline void singlestep_disable(struct task_struct *child)
{
- unsigned long tmp;
- /* make sure the single step bit is not set. */
- tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+ unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
child->thread.work.delayed_trace = 0;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ singlestep_disable(child);
child->thread.work.syscall_trace = 0;
}
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- int ret;
+ unsigned long tmp;
+ int i, ret = 0;
lock_kernel();
- ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
+ if (current->ptrace & PT_PTRACED) {
+ ret = -EPERM;
goto out;
+ }
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
- ret = 0;
goto out;
}
- ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
- if (!child)
+ if (unlikely(!child)) {
+ ret = -ESRCH;
goto out;
+ }
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
+ /* you may not mess with init */
+ if (unlikely(pid == 1)) {
+ ret = -EPERM;
goto out_tsk;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
@@ -152,227 +160,171 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
+ if (ret)
goto out_tsk;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
- break;
- }
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA:
+ i = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ if (i != sizeof(tmp))
+ goto out_eio;
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
- unsigned long tmp;
-
- ret = -EIO;
- if ((addr & 3) || addr < 0 ||
- addr > sizeof(struct user) - 3)
- break;
-
- tmp = 0; /* Default return condition */
- addr = addr >> 2; /* temporary hack. */
- ret = -EIO;
- if (addr < 19) {
- tmp = get_reg(child, addr);
- if (addr == PT_SR)
- tmp >>= 16;
- } else if (addr >= 21 && addr < 49) {
- tmp = child->thread.fp[addr - 21];
-#ifdef CONFIG_M68KFPU_EMU
- /* Convert internal fpu reg representation
- * into long double format
- */
- if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
- tmp = ((tmp & 0xffff0000) << 15) |
- ((tmp & 0x0000ffff) << 16);
-#endif
- } else
- break;
- ret = put_user(tmp,(unsigned long *) data);
- break;
- }
-
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
- break;
-
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = -EIO;
- if ((addr & 3) || addr < 0 ||
- addr > sizeof(struct user) - 3)
- break;
-
- addr = addr >> 2; /* temporary hack. */
-
- if (addr == PT_SR) {
- data &= SR_MASK;
- data <<= 16;
- data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
- }
- if (addr < 19) {
- if (put_reg(child, addr, data))
- break;
- ret = 0;
- break;
- }
- if (addr >= 21 && addr < 48)
- {
-#ifdef CONFIG_M68KFPU_EMU
- /* Convert long double format
- * into internal fpu reg representation
- */
- if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
- data = (unsigned long)data << 15;
- data = (data & 0xffff0000) |
- ((data & 0x0000ffff) >> 1);
- }
-#endif
- child->thread.fp[addr - 21] = data;
- ret = 0;
- }
+ case PTRACE_PEEKUSR:
+ if (addr & 3)
+ goto out_eio;
+ addr >>= 2; /* temporary hack. */
+
+ if (addr >= 0 && addr < 19) {
+ tmp = get_reg(child, addr);
+ if (addr == PT_SR)
+ tmp >>= 16;
+ } else if (addr >= 21 && addr < 49) {
+ tmp = child->thread.fp[addr - 21];
+ /* Convert internal fpu reg representation
+ * into long double format
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
+ tmp = ((tmp & 0xffff0000) << 15) |
+ ((tmp & 0x0000ffff) << 16);
+ } else
break;
-
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- long tmp;
-
- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL) {
- child->thread.work.syscall_trace = ~0;
- } else {
- child->thread.work.syscall_trace = 0;
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
+ goto out_eio;
+ break;
+
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ if (addr & 3)
+ goto out_eio;
+ addr >>= 2; /* temporary hack. */
+
+ if (addr == PT_SR) {
+ data &= SR_MASK;
+ data <<= 16;
+ data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
+ } else if (addr >= 0 && addr < 19) {
+ if (put_reg(child, addr, data))
+ goto out_eio;
+ } else if (addr >= 21 && addr < 48) {
+ /* Convert long double format
+ * into internal fpu reg representation
+ */
+ if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
+ data = (unsigned long)data << 15;
+ data = (data & 0xffff0000) |
+ ((data & 0x0000ffff) >> 1);
}
- child->exit_code = data;
- /* make sure the single step bit is not set. */
- tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);
- child->thread.work.delayed_trace = 0;
- wake_up_process(child);
- ret = 0;
- break;
- }
-
-/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
- long tmp;
-
- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- /* make sure the single step bit is not set. */
- tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);
- child->thread.work.delayed_trace = 0;
- wake_up_process(child);
- break;
- }
-
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
- long tmp;
-
- ret = -EIO;
- if (!valid_signal(data))
- break;
+ child->thread.fp[addr - 21] = data;
+ } else
+ goto out_eio;
+ break;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: /* restart after signal. */
+ if (!valid_signal(data))
+ goto out_eio;
+
+ if (request == PTRACE_SYSCALL)
+ child->thread.work.syscall_trace = ~0;
+ else
child->thread.work.syscall_trace = 0;
- tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);
- child->thread.work.delayed_trace = 1;
-
- child->exit_code = data;
- /* give it a chance to run. */
- wake_up_process(child);
- ret = 0;
- break;
- }
+ child->exit_code = data;
+ singlestep_disable(child);
+ wake_up_process(child);
+ break;
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
-
- case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i < 19; i++) {
- tmp = get_reg(child, i);
- if (i == PT_SR)
+ child->exit_code = SIGKILL;
+ singlestep_disable(child);
+ wake_up_process(child);
+ break;
+
+ case PTRACE_SINGLESTEP: /* set the trap flag. */
+ if (!valid_signal(data))
+ goto out_eio;
+
+ child->thread.work.syscall_trace = 0;
+ tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+ child->thread.work.delayed_trace = 1;
+
+ child->exit_code = data;
+ /* give it a chance to run. */
+ wake_up_process(child);
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+ case PTRACE_GETREGS: /* Get all gp regs from the child. */
+ for (i = 0; i < 19; i++) {
+ tmp = get_reg(child, i);
+ if (i == PT_SR)
tmp >>= 16;
- if (put_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
+ ret = put_user(tmp, (unsigned long *)data);
+ if (ret)
break;
- }
- data += sizeof(long);
- }
- ret = 0;
- break;
+ data += sizeof(long);
}
+ break;
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i < 19; i++) {
- if (get_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
+ case PTRACE_SETREGS: /* Set all gp regs in the child. */
+ for (i = 0; i < 19; i++) {
+ ret = get_user(tmp, (unsigned long *)data);
+ if (ret)
break;
- }
- if (i == PT_SR) {
+ if (i == PT_SR) {
tmp &= SR_MASK;
tmp <<= 16;
tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
- }
- put_reg(child, i, tmp);
- data += sizeof(long);
}
- ret = 0;
- break;
+ put_reg(child, i, tmp);
+ data += sizeof(long);
}
-
- case PTRACE_GETFPREGS: { /* Get the child FPU state. */
- ret = 0;
- if (copy_to_user((void *)data, &child->thread.fp,
- sizeof(struct user_m68kfp_struct)))
- ret = -EFAULT;
- break;
- }
-
- case PTRACE_SETFPREGS: { /* Set the child FPU state. */
- ret = 0;
- if (copy_from_user(&child->thread.fp, (void *)data,
- sizeof(struct user_m68kfp_struct)))
- ret = -EFAULT;
- break;
- }
-
- default:
- ret = ptrace_request(child, request, addr, data);
- break;
+ break;
+
+ case PTRACE_GETFPREGS: /* Get the child FPU state. */
+ if (copy_to_user((void *)data, &child->thread.fp,
+ sizeof(struct user_m68kfp_struct)))
+ ret = -EFAULT;
+ break;
+
+ case PTRACE_SETFPREGS: /* Set the child FPU state. */
+ if (copy_from_user(&child->thread.fp, (void *)data,
+ sizeof(struct user_m68kfp_struct)))
+ ret = -EFAULT;
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
}
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret;
+out_eio:
+ ret = -EIO;
+ goto out_tsk;
}
asmlinkage void syscall_trace(void)
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index e47e19588525..4ec95e3cb874 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -166,10 +166,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index 34b6dbc29c85..ebe51a513817 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -5,4 +5,4 @@
EXTRA_AFLAGS := -traditional
lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
- checksum.o memcmp.o memcpy.o memset.o semaphore.o
+ checksum.o string.o semaphore.o
diff --git a/arch/m68k/lib/memcmp.c b/arch/m68k/lib/memcmp.c
deleted file mode 100644
index f4796febb773..000000000000
--- a/arch/m68k/lib/memcmp.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <linux/types.h>
-
-int memcmp(const void * cs,const void * ct,size_t count)
-{
- const unsigned char *su1, *su2;
-
- for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
- if (*su1 != *su2)
- return((*su1 < *su2) ? -1 : +1);
- return(0);
-}
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c
deleted file mode 100644
index 73e181823d9b..000000000000
--- a/arch/m68k/lib/memcpy.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/types.h>
-
-void * memcpy(void * to, const void * from, size_t n)
-{
- void *xto = to;
- size_t temp, temp1;
-
- if (!n)
- return xto;
- if ((long) to & 1)
- {
- char *cto = to;
- const char *cfrom = from;
- *cto++ = *cfrom++;
- to = cto;
- from = cfrom;
- n--;
- }
- if (n > 2 && (long) to & 2)
- {
- short *sto = to;
- const short *sfrom = from;
- *sto++ = *sfrom++;
- to = sto;
- from = sfrom;
- n -= 2;
- }
- temp = n >> 2;
- if (temp)
- {
- long *lto = to;
- const long *lfrom = from;
-
- __asm__ __volatile__("movel %2,%3\n\t"
- "andw #7,%3\n\t"
- "lsrl #3,%2\n\t"
- "negw %3\n\t"
- "jmp %%pc@(1f,%3:w:2)\n\t"
- "4:\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "movel %0@+,%1@+\n\t"
- "1:\t"
- "dbra %2,4b\n\t"
- "clrw %2\n\t"
- "subql #1,%2\n\t"
- "jpl 4b\n\t"
- : "=a" (lfrom), "=a" (lto), "=d" (temp),
- "=&d" (temp1)
- : "0" (lfrom), "1" (lto), "2" (temp)
- );
- to = lto;
- from = lfrom;
- }
- if (n & 2)
- {
- short *sto = to;
- const short *sfrom = from;
- *sto++ = *sfrom++;
- to = sto;
- from = sfrom;
- }
- if (n & 1)
- {
- char *cto = to;
- const char *cfrom = from;
- *cto = *cfrom;
- }
- return xto;
-}
diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c
deleted file mode 100644
index d55fdb2ee9d3..000000000000
--- a/arch/m68k/lib/memset.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <linux/types.h>
-
-void * memset(void * s, int c, size_t count)
-{
- void *xs = s;
- size_t temp, temp1;
-
- if (!count)
- return xs;
- c &= 0xff;
- c |= c << 8;
- c |= c << 16;
- if ((long) s & 1)
- {
- char *cs = s;
- *cs++ = c;
- s = cs;
- count--;
- }
- if (count > 2 && (long) s & 2)
- {
- short *ss = s;
- *ss++ = c;
- s = ss;
- count -= 2;
- }
- temp = count >> 2;
- if (temp)
- {
- long *ls = s;
-
- __asm__ __volatile__("movel %1,%2\n\t"
- "andw #7,%2\n\t"
- "lsrl #3,%1\n\t"
- "negw %2\n\t"
- "jmp %%pc@(2f,%2:w:2)\n\t"
- "1:\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "movel %3,%0@+\n\t"
- "2:\t"
- "dbra %1,1b\n\t"
- "clrw %1\n\t"
- "subql #1,%1\n\t"
- "jpl 1b\n\t"
- : "=a" (ls), "=d" (temp), "=&d" (temp1)
- : "d" (c), "0" (ls), "1" (temp)
- );
- s = ls;
- }
- if (count & 2)
- {
- short *ss = s;
- *ss++ = c;
- s = ss;
- }
- if (count & 1)
- {
- char *cs = s;
- *cs = c;
- }
- return xs;
-}
diff --git a/arch/m68k/lib/string.c b/arch/m68k/lib/string.c
new file mode 100644
index 000000000000..b92b89e1ea0c
--- /dev/null
+++ b/arch/m68k/lib/string.c
@@ -0,0 +1,237 @@
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+void *memset(void *s, int c, size_t count)
+{
+ void *xs = s;
+ size_t temp, temp1;
+
+ if (!count)
+ return xs;
+ c &= 0xff;
+ c |= c << 8;
+ c |= c << 16;
+ if ((long)s & 1) {
+ char *cs = s;
+ *cs++ = c;
+ s = cs;
+ count--;
+ }
+ if (count > 2 && (long)s & 2) {
+ short *ss = s;
+ *ss++ = c;
+ s = ss;
+ count -= 2;
+ }
+ temp = count >> 2;
+ if (temp) {
+ long *ls = s;
+
+ asm volatile (
+ " movel %1,%2\n"
+ " andw #7,%2\n"
+ " lsrl #3,%1\n"
+ " negw %2\n"
+ " jmp %%pc@(2f,%2:w:2)\n"
+ "1: movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ " movel %3,%0@+\n"
+ "2: dbra %1,1b\n"
+ " clrw %1\n"
+ " subql #1,%1\n"
+ " jpl 1b"
+ : "=a" (ls), "=d" (temp), "=&d" (temp1)
+ : "d" (c), "0" (ls), "1" (temp));
+ s = ls;
+ }
+ if (count & 2) {
+ short *ss = s;
+ *ss++ = c;
+ s = ss;
+ }
+ if (count & 1) {
+ char *cs = s;
+ *cs = c;
+ }
+ return xs;
+}
+EXPORT_SYMBOL(memset);
+
+void *memcpy(void *to, const void *from, size_t n)
+{
+ void *xto = to;
+ size_t temp, temp1;
+
+ if (!n)
+ return xto;
+ if ((long)to & 1) {
+ char *cto = to;
+ const char *cfrom = from;
+ *cto++ = *cfrom++;
+ to = cto;
+ from = cfrom;
+ n--;
+ }
+ if (n > 2 && (long)to & 2) {
+ short *sto = to;
+ const short *sfrom = from;
+ *sto++ = *sfrom++;
+ to = sto;
+ from = sfrom;
+ n -= 2;
+ }
+ temp = n >> 2;
+ if (temp) {
+ long *lto = to;
+ const long *lfrom = from;
+
+ asm volatile (
+ " movel %2,%3\n"
+ " andw #7,%3\n"
+ " lsrl #3,%2\n"
+ " negw %3\n"
+ " jmp %%pc@(1f,%3:w:2)\n"
+ "4: movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ " movel %0@+,%1@+\n"
+ "1: dbra %2,4b\n"
+ " clrw %2\n"
+ " subql #1,%2\n"
+ " jpl 4b"
+ : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1)
+ : "0" (lfrom), "1" (lto), "2" (temp));
+ to = lto;
+ from = lfrom;
+ }
+ if (n & 2) {
+ short *sto = to;
+ const short *sfrom = from;
+ *sto++ = *sfrom++;
+ to = sto;
+ from = sfrom;
+ }
+ if (n & 1) {
+ char *cto = to;
+ const char *cfrom = from;
+ *cto = *cfrom;
+ }
+ return xto;
+}
+EXPORT_SYMBOL(memcpy);
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+ void *xdest = dest;
+ size_t temp;
+
+ if (!n)
+ return xdest;
+
+ if (dest < src) {
+ if ((long)dest & 1) {
+ char *cdest = dest;
+ const char *csrc = src;
+ *cdest++ = *csrc++;
+ dest = cdest;
+ src = csrc;
+ n--;
+ }
+ if (n > 2 && (long)dest & 2) {
+ short *sdest = dest;
+ const short *ssrc = src;
+ *sdest++ = *ssrc++;
+ dest = sdest;
+ src = ssrc;
+ n -= 2;
+ }
+ temp = n >> 2;
+ if (temp) {
+ long *ldest = dest;
+ const long *lsrc = src;
+ temp--;
+ do
+ *ldest++ = *lsrc++;
+ while (temp--);
+ dest = ldest;
+ src = lsrc;
+ }
+ if (n & 2) {
+ short *sdest = dest;
+ const short *ssrc = src;
+ *sdest++ = *ssrc++;
+ dest = sdest;
+ src = ssrc;
+ }
+ if (n & 1) {
+ char *cdest = dest;
+ const char *csrc = src;
+ *cdest = *csrc;
+ }
+ } else {
+ dest = (char *)dest + n;
+ src = (const char *)src + n;
+ if ((long)dest & 1) {
+ char *cdest = dest;
+ const char *csrc = src;
+ *--cdest = *--csrc;
+ dest = cdest;
+ src = csrc;
+ n--;
+ }
+ if (n > 2 && (long)dest & 2) {
+ short *sdest = dest;
+ const short *ssrc = src;
+ *--sdest = *--ssrc;
+ dest = sdest;
+ src = ssrc;
+ n -= 2;
+ }
+ temp = n >> 2;
+ if (temp) {
+ long *ldest = dest;
+ const long *lsrc = src;
+ temp--;
+ do
+ *--ldest = *--lsrc;
+ while (temp--);
+ dest = ldest;
+ src = lsrc;
+ }
+ if (n & 2) {
+ short *sdest = dest;
+ const short *ssrc = src;
+ *--sdest = *--ssrc;
+ dest = sdest;
+ src = ssrc;
+ }
+ if (n & 1) {
+ char *cdest = dest;
+ const char *csrc = src;
+ *--cdest = *--csrc;
+ }
+ }
+ return xdest;
+}
+EXPORT_SYMBOL(memmove);
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+
+ for (su1 = cs, su2 = ct; count > 0; ++su1, ++su2, count--)
+ if (*su1 != *su2)
+ return *su1 < *su2 ? -1 : +1;
+ return 0;
+}
+EXPORT_SYMBOL(memcmp);
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 44c5cd2ad6a8..8f0640847ad2 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -56,8 +56,7 @@ static void ( *mac_special_bell )( unsigned int, unsigned int, unsigned int );
/*
* our timer to start/continue/stop the bell
*/
-static struct timer_list mac_sound_timer =
- TIMER_INITIALIZER(mac_nosound, 0, 0);
+static DEFINE_TIMER(mac_sound_timer, mac_nosound, 0, 0);
/*
* Sort of initialize the sound chip (called from mac_mksound on the first
diff --git a/arch/m68k/math-emu/fp_emu.h b/arch/m68k/math-emu/fp_emu.h
index 1d6edc975d89..c1ecfef7886a 100644
--- a/arch/m68k/math-emu/fp_emu.h
+++ b/arch/m68k/math-emu/fp_emu.h
@@ -39,7 +39,7 @@
#define _FP_EMU_H
#ifdef __ASSEMBLY__
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#endif
#include <asm/math-emu.h>
diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile
index 90f1c735c110..5eaa43c4cb3c 100644
--- a/arch/m68k/mm/Makefile
+++ b/arch/m68k/mm/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux m68k-specific parts of the memory manager.
#
-obj-y := init.o fault.o hwtest.o
+obj-y := cache.o init.o fault.o hwtest.o
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
diff --git a/arch/m68k/mm/cache.c b/arch/m68k/mm/cache.c
new file mode 100644
index 000000000000..5437fff5fe07
--- /dev/null
+++ b/arch/m68k/mm/cache.c
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/m68k/mm/cache.c
+ *
+ * Instruction cache handling
+ *
+ * Copyright (C) 1995 Hamish Macdonald
+ */
+
+#include <linux/module.h>
+#include <asm/pgalloc.h>
+#include <asm/traps.h>
+
+
+static unsigned long virt_to_phys_slow(unsigned long vaddr)
+{
+ if (CPU_IS_060) {
+ unsigned long paddr;
+
+ /* The PLPAR instruction causes an access error if the translation
+ * is not possible. To catch this we use the same exception mechanism
+ * as for user space accesses in <asm/uaccess.h>. */
+ asm volatile (".chip 68060\n"
+ "1: plpar (%0)\n"
+ ".chip 68k\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ " .even\n"
+ "3: sub.l %0,%0\n"
+ " jra 2b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 1b,3b\n"
+ ".previous"
+ : "=a" (paddr)
+ : "0" (vaddr));
+ return paddr;
+ } else if (CPU_IS_040) {
+ unsigned long mmusr;
+
+ asm volatile (".chip 68040\n\t"
+ "ptestr (%1)\n\t"
+ "movec %%mmusr, %0\n\t"
+ ".chip 68k"
+ : "=r" (mmusr)
+ : "a" (vaddr));
+
+ if (mmusr & MMU_R_040)
+ return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
+ } else {
+ unsigned short mmusr;
+ unsigned long *descaddr;
+
+ asm volatile ("ptestr %3,%2@,#7,%0\n\t"
+ "pmove %%psr,%1@"
+ : "=a&" (descaddr)
+ : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg));
+ if (mmusr & (MMU_I|MMU_B|MMU_L))
+ return 0;
+ descaddr = phys_to_virt((unsigned long)descaddr);
+ switch (mmusr & MMU_NUM) {
+ case 1:
+ return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
+ case 2:
+ return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
+ case 3:
+ return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
+ }
+ }
+ return 0;
+}
+
+/* Push n pages at kernel virtual address and clear the icache */
+/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
+void flush_icache_range(unsigned long address, unsigned long endaddr)
+{
+
+ if (CPU_IS_040_OR_060) {
+ address &= PAGE_MASK;
+
+ do {
+ asm volatile ("nop\n\t"
+ ".chip 68040\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (virt_to_phys_slow(address)));
+ address += PAGE_SIZE;
+ } while (address < endaddr);
+ } else {
+ unsigned long tmp;
+ asm volatile ("movec %%cacr,%0\n\t"
+ "orw %1,%0\n\t"
+ "movec %0,%%cacr"
+ : "=&d" (tmp)
+ : "di" (FLUSH_I));
+ }
+}
+EXPORT_SYMBOL(flush_icache_range);
+
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+ unsigned long addr, int len)
+{
+ if (CPU_IS_040_OR_060) {
+ asm volatile ("nop\n\t"
+ ".chip 68040\n\t"
+ "cpushp %%bc,(%0)\n\t"
+ ".chip 68k"
+ : : "a" (page_to_phys(page)));
+ } else {
+ unsigned long tmp;
+ asm volatile ("movec %%cacr,%0\n\t"
+ "orw %1,%0\n\t"
+ "movec %0,%%cacr"
+ : "=&d" (tmp)
+ : "di" (FLUSH_I));
+ }
+}
+
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 1453a6013721..559942ce0e1e 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -354,110 +354,6 @@ void cache_push (unsigned long paddr, int len)
#endif
}
-static unsigned long virt_to_phys_slow(unsigned long vaddr)
-{
- if (CPU_IS_060) {
- mm_segment_t fs = get_fs();
- unsigned long paddr;
-
- set_fs(get_ds());
-
- /* The PLPAR instruction causes an access error if the translation
- * is not possible. To catch this we use the same exception mechanism
- * as for user space accesses in <asm/uaccess.h>. */
- asm volatile (".chip 68060\n"
- "1: plpar (%0)\n"
- ".chip 68k\n"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- " .even\n"
- "3: sub.l %0,%0\n"
- " jra 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 1b,3b\n"
- ".previous"
- : "=a" (paddr)
- : "0" (vaddr));
- set_fs(fs);
- return paddr;
- } else if (CPU_IS_040) {
- mm_segment_t fs = get_fs();
- unsigned long mmusr;
-
- set_fs(get_ds());
-
- asm volatile (".chip 68040\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr, %0\n\t"
- ".chip 68k"
- : "=r" (mmusr)
- : "a" (vaddr));
- set_fs(fs);
-
- if (mmusr & MMU_R_040)
- return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
- } else {
- unsigned short mmusr;
- unsigned long *descaddr;
-
- asm volatile ("ptestr #5,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (descaddr)
- : "a" (&mmusr), "a" (vaddr));
- if (mmusr & (MMU_I|MMU_B|MMU_L))
- return 0;
- descaddr = phys_to_virt((unsigned long)descaddr);
- switch (mmusr & MMU_NUM) {
- case 1:
- return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
- case 2:
- return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
- case 3:
- return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
- }
- }
- return 0;
-}
-
-/* Push n pages at kernel virtual address and clear the icache */
-/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
-void flush_icache_range(unsigned long address, unsigned long endaddr)
-{
- if (CPU_IS_040_OR_060) {
- address &= PAGE_MASK;
-
- if (address >= PAGE_OFFSET && address < (unsigned long)high_memory) {
- do {
- asm volatile ("nop\n\t"
- ".chip 68040\n\t"
- "cpushp %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (virt_to_phys((void *)address)));
- address += PAGE_SIZE;
- } while (address < endaddr);
- } else {
- do {
- asm volatile ("nop\n\t"
- ".chip 68040\n\t"
- "cpushp %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (virt_to_phys_slow(address)));
- address += PAGE_SIZE;
- } while (address < endaddr);
- }
- } else {
- unsigned long tmp;
- asm volatile ("movec %%cacr,%0\n\t"
- "orw %1,%0\n\t"
- "movec %0,%%cacr"
- : "=&d" (tmp)
- : "di" (FLUSH_I));
- }
-}
-
-
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
int mm_end_of_chunk (unsigned long addr, int len)
{
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 8a2425069088..7977eae50af2 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -161,7 +161,7 @@ static struct miscdevice rtc_dev=
.fops = &rtc_fops
};
-int __init rtc_MK48T08_init(void)
+static int __init rtc_MK48T08_init(void)
{
if (!MACH_IS_MVME16x)
return -ENODEV;
@@ -169,4 +169,4 @@ int __init rtc_MK48T08_init(void)
printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
return misc_register(&rtc_dev);
}
-
+module_init(rtc_MK48T08_init);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 117f183f0b43..8520df9cee6d 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -71,21 +71,31 @@ config M5206e
help
Motorola ColdFire 5206e processor support.
+config M523x
+ bool "MCF523x"
+ help
+ Freescale Coldfire 5230/1/2/4/5 processor support
+
config M5249
bool "MCF5249"
help
Motorola ColdFire 5249 processor support.
-config M527x
- bool "MCF527x"
+config M5271
+ bool "MCF5271"
help
- Freescale (Motorola) ColdFire 5270/5271/5274/5275 processor support.
+ Freescale (Motorola) ColdFire 5270/5271 processor support.
config M5272
bool "MCF5272"
help
Motorola ColdFire 5272 processor support.
+config M5275
+ bool "MCF5275"
+ help
+ Freescale (Motorola) ColdFire 5274/5275 processor support.
+
config M528x
bool "MCF528x"
help
@@ -103,9 +113,14 @@ config M5407
endchoice
+config M527x
+ bool
+ depends on (M5271 || M5275)
+ default y
+
config COLDFIRE
bool
- depends on (M5206 || M5206e || M5249 || M527x || M5272 || M528x || M5307 || M5407)
+ depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
default y
choice
@@ -183,6 +198,11 @@ config CLOCK_60MHz
help
Select a 60MHz CPU clock frequency.
+config CLOCK_62_5MHz
+ bool "62.5MHz"
+ help
+ Select a 62.5MHz CPU clock frequency.
+
config CLOCK_64MHz
bool "64MHz"
help
@@ -302,6 +322,12 @@ config ELITE
help
Support for the Motorola M5206eLITE board.
+config M5235EVB
+ bool "Freescale M5235EVB support"
+ depends on M523x
+ help
+ Support for the Freescale M5235EVB board.
+
config M5249C3
bool "Motorola M5249C3 board support"
depends on M5249
@@ -310,13 +336,13 @@ config M5249C3
config M5271EVB
bool "Freescale (Motorola) M5271EVB board support"
- depends on M527x
+ depends on M5271
help
Support for the Freescale (Motorola) M5271EVB board.
config M5275EVB
bool "Freescale (Motorola) M5275EVB board support"
- depends on M527x
+ depends on M5275
help
Support for the Freescale (Motorola) M5275EVB board.
@@ -343,6 +369,12 @@ config COBRA5282
depends on M528x
help
Support for the senTec COBRA5282 board.
+
+config SOM5282EM
+ bool "EMAC.Inc SOM5282EM board support"
+ depends on M528x
+ help
+ Support for the EMAC.Inc SOM5282EM module.
config ARN5307
bool "Arnewsh 5307 board support"
@@ -410,6 +442,12 @@ config CPU16B
help
Support for the SNEHA CPU16B board.
+config MOD5272
+ bool "Netburner MOD-5272 board support"
+ depends on M5272
+ help
+ Support for the Netburner MOD-5272 board.
+
config ROMFS_FROM_ROM
bool " ROMFS image not RAM resident"
depends on (NETtel || SNAPGEAR)
@@ -430,7 +468,7 @@ config ARNEWSH
config MOTOROLA
bool
default y
- depends on (M5206eC3 || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
+ depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
config HW_FEITH
bool
@@ -441,6 +479,11 @@ config senTec
bool
default y
depends on (COBRA5272 || COBRA5282)
+
+config EMAC_INC
+ bool
+ default y
+ depends on (SOM5282EM)
config SNEHA
bool
@@ -455,6 +498,15 @@ config LARGE_ALLOCS
a lot of RAM, and you need to able to allocate very large
contiguous chunks. If unsure, say N.
+config 4KSTACKS
+ bool "Use 4Kb for kernel stacks instead of 8Kb"
+ default y
+ help
+ If you say Y here the kernel will use a 4Kb stacksize for the
+ kernel stack attached to each process/thread. This facilitates
+ running more threads on a system and also reduces the pressure
+ on the VM subsystem for higher order allocations.
+
choice
prompt "RAM size"
default AUTO
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index a254aa9d4998..b8fdf191b8f6 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328) := 68VZ328
platform-$(CONFIG_M68360) := 68360
platform-$(CONFIG_M5206) := 5206
platform-$(CONFIG_M5206e) := 5206e
+platform-$(CONFIG_M523x) := 523x
platform-$(CONFIG_M5249) := 5249
platform-$(CONFIG_M527x) := 527x
platform-$(CONFIG_M5272) := 5272
@@ -29,6 +30,7 @@ board-$(CONFIG_UCQUICC) := uCquicc
board-$(CONFIG_DRAGEN2) := de2
board-$(CONFIG_ARNEWSH) := ARNEWSH
board-$(CONFIG_MOTOROLA) := MOTOROLA
+board-$(CONFIG_M5235EVB) := M5235EVB
board-$(CONFIG_M5271EVB) := M5271EVB
board-$(CONFIG_M5275EVB) := M5275EVB
board-$(CONFIG_M5282EVB) := M5282EVB
@@ -39,6 +41,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3
board-$(CONFIG_CLEOPATRA) := CLEOPATRA
board-$(CONFIG_senTec) := senTec
board-$(CONFIG_SNEHA) := SNEHA
+board-$(CONFIG_MOD5272) := MOD5272
BOARD := $(board-y)
model-$(CONFIG_RAMKERNEL) := ram
@@ -53,6 +56,7 @@ MODEL := $(model-y)
#
cpuclass-$(CONFIG_M5206) := 5307
cpuclass-$(CONFIG_M5206e) := 5307
+cpuclass-$(CONFIG_M523x) := 5307
cpuclass-$(CONFIG_M5249) := 5307
cpuclass-$(CONFIG_M527x) := 5307
cpuclass-$(CONFIG_M5272) := 5307
@@ -76,6 +80,7 @@ export PLATFORM BOARD MODEL CPUCLASS
#
cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200
cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200
+cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307
cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200
cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307
cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307
@@ -97,21 +102,11 @@ CFLAGS += -DUTS_SYSNAME=\"uClinux\"
head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
-CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \
- arch/$(ARCH)/kernel/asm-offsets.s
-
core-y += arch/m68knommu/kernel/ \
arch/m68knommu/mm/ \
$(CLASSDIR) \
arch/m68knommu/platform/$(PLATFORM)/
libs-y += arch/m68knommu/lib/
-prepare: include/asm-$(ARCH)/asm-offsets.h
-
archclean:
- $(call descend arch/$(ARCH)/boot, subdirclean)
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
- include/asm include/linux/version.h \
- include/config/MARKER
- $(call filechk,gen-asm-offsets)
+ $(Q)$(MAKE) $(clean)=arch/m68knommu/boot
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index e4bd31be966a..87f2d6587c56 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -1,24 +1,48 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-uc0
+# Wed Aug 31 15:03:26 2005
#
+CONFIG_M68KNOMMU=y
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=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_SYSVIPC is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -34,9 +58,11 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_M68360 is not set
# CONFIG_M5206 is not set
# CONFIG_M5206e is not set
+# CONFIG_M523x is not set
# CONFIG_M5249 is not set
-# CONFIG_M527x is not set
+# CONFIG_M5271 is not set
CONFIG_M5272=y
+# CONFIG_M5275 is not set
# CONFIG_M528x is not set
# CONFIG_M5307 is not set
# CONFIG_M5407 is not set
@@ -54,6 +80,8 @@ CONFIG_COLDFIRE=y
# CONFIG_CLOCK_50MHz is not set
# CONFIG_CLOCK_54MHz is not set
# CONFIG_CLOCK_60MHz is not set
+# CONFIG_CLOCK_62_5MHz is not set
+# CONFIG_CLOCK_64MHz is not set
CONFIG_CLOCK_66MHz=y
# CONFIG_CLOCK_70MHz is not set
# CONFIG_CLOCK_100MHz is not set
@@ -65,13 +93,19 @@ CONFIG_CLOCK_66MHz=y
# Platform
#
CONFIG_M5272C3=y
+# CONFIG_COBRA5272 is not set
+# CONFIG_CANCam is not set
+# CONFIG_SCALES is not set
# CONFIG_NETtel is not set
+# CONFIG_CPU16B is not set
+# CONFIG_MOD5272 is not set
CONFIG_MOTOROLA=y
# CONFIG_LARGE_ALLOCS is not set
-# CONFIG_RAMAUTO is not set
+CONFIG_4KSTACKS=y
+CONFIG_RAMAUTO=y
# CONFIG_RAM4MB is not set
# CONFIG_RAM8MB is not set
-CONFIG_RAM16MB=y
+# CONFIG_RAM16MB is not set
# CONFIG_RAM32MB is not set
CONFIG_RAMAUTOBIT=y
# CONFIG_RAM8BIT is not set
@@ -79,20 +113,34 @@ CONFIG_RAMAUTOBIT=y
# CONFIG_RAM32BIT is not set
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
-# CONFIG_HIMEMKERNEL 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
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
#
# Executable file formats
#
-CONFIG_KCORE_AOUT=y
CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
#
# Power management options
@@ -100,12 +148,82 @@ CONFIG_BINFMT_FLAT=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# 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_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -116,35 +234,50 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
#
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_SNAPGEARuC is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
-# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -159,21 +292,32 @@ CONFIG_MTD_UCLINUX=y
#
# Plug and Play support
#
-# CONFIG_PNP is not set
#
# 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
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_DEV_BLKMEM is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
#
-# ATA/IDE/MFM/RLL support
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -190,249 +334,230 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
-# CONFIG_IPV6 is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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
+# I2O device support
#
-# CONFIG_NET_SCHED is not set
#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN 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
-# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NE2000 is not set
+# CONFIG_NET_PCI is not set
CONFIG_FEC=y
+# CONFIG_FEC2 is not set
#
# Ethernet (1000 Mbit)
#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_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
#
-# Wireless LAN (non-hamradio)
+# ISDN subsystem
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_ISDN is not set
#
-# Token Ring devices (depends on LLC=y)
+# Telephony Support
#
-# CONFIG_SHAPER is not set
+# CONFIG_PHONE is not set
#
-# Wan interfaces
+# Input device support
#
-# CONFIG_WAN is not set
+# CONFIG_INPUT is not set
#
-# Amateur Radio support
+# Hardware I/O ports
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
#
-# IrDA (infrared) support
+# Character devices
#
-# CONFIG_IRDA is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_LEDMAN is not set
+# CONFIG_RESETSWITCH is not set
#
-# ISDN subsystem
+# Serial drivers
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_SERIAL_8250 is not set
#
-# Telephony Support
+# Non-8250 serial port support
#
-# CONFIG_PHONE is not set
+CONFIG_SERIAL_COLDFIRE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# Input device support
+# IPMI
#
-CONFIG_INPUT=y
+# CONFIG_IPMI_HANDLER is not set
#
-# Userland interfaces
+# Watchdog Cards
#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_MCFWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
#
-# Input I/O drivers
+# Ftape, the floppy tape device driver
#
-# 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_RAW_DRIVER is not set
#
-# Input Device Drivers
+# TPM devices
#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD 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_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_MCF_QSPI is not set
+# CONFIG_M41T11M6 is not set
#
-# Character devices
+# I2C support
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_RESETSWITCH is not set
+# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
#
-# Serial drivers
+# Dallas's 1-wire bus
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_W1 is not set
#
-# Non-8250 serial port support
+# Hardware Monitoring support
#
-CONFIG_SERIAL_COLDFIRE=y
-# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HWMON is not set
#
-# I2C support
+# Misc devices
#
-# CONFIG_I2C is not set
#
-# I2C Hardware Sensors Mainboard support
+# Multimedia devices
#
+# CONFIG_VIDEO_DEV is not set
#
-# I2C Hardware Sensors Chip support
+# Digital Video Broadcasting Devices
#
+# CONFIG_DVB is not set
#
-# Mice
+# Graphics support
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_FB is not set
#
-# IPMI
+# SPI support
#
-# CONFIG_IPMI_HANDLER is not set
+# CONFIG_SPI is not set
#
-# Watchdog Cards
+# Sound
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM 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_SOUND is not set
#
-# Ftape, the floppy tape device driver
+# USB support
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# Multimedia devices
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+
+#
+# SN Devices
#
-# CONFIG_VIDEO_DEV 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
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+CONFIG_MAGIC_ROM_PTR=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -445,15 +570,17 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# 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_DEVFS_FS is not set
+CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
#
@@ -462,6 +589,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -479,12 +607,10 @@ CONFIG_RAMFS=y
#
# 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_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -494,30 +620,19 @@ CONFIG_RAMFS=y
CONFIG_MSDOS_PARTITION=y
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-
-#
-# Bluetooth support
+# Native Language Support
#
-# CONFIG_BT is not set
+# CONFIG_NLS is not set
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_FULLDEBUG is not set
-# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
# CONFIG_DUMPTOFLASH is not set
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
@@ -525,6 +640,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -533,6 +649,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 557238596dcb..a220345e9746 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -6,7 +6,7 @@
* Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* Copyright (C) 1995 Hamish Macdonald
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
* Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
*
* 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/fb.h>
+#include <linux/module.h>
#include <linux/console.h>
#include <linux/genhd.h>
#include <linux/errno.h>
@@ -45,6 +46,9 @@ unsigned long rom_length;
unsigned long memory_start;
unsigned long memory_end;
+EXPORT_SYMBOL(memory_start);
+EXPORT_SYMBOL(memory_end);
+
char command_line[COMMAND_LINE_SIZE];
/* setup some dummy routines */
@@ -103,15 +107,21 @@ void (*mach_power_off)( void ) = NULL;
#if defined(CONFIG_M5206e)
#define CPU "COLDFIRE(m5206e)"
#endif
+#if defined(CONFIG_M523x)
+ #define CPU "COLDFIRE(m523x)"
+#endif
#if defined(CONFIG_M5249)
#define CPU "COLDFIRE(m5249)"
#endif
-#if defined(CONFIG_M527x)
- #define CPU "COLDFIRE(m5270/5271/5274/5275)"
+#if defined(CONFIG_M5271)
+ #define CPU "COLDFIRE(m5270/5271)"
#endif
#if defined(CONFIG_M5272)
#define CPU "COLDFIRE(m5272)"
#endif
+#if defined(CONFIG_M5275)
+ #define CPU "COLDFIRE(m5274/5275)"
+#endif
#if defined(CONFIG_M528x)
#define CPU "COLDFIRE(m5280/5282)"
#endif
@@ -152,7 +162,7 @@ void setup_arch(char **cmdline_p)
init_mm.start_code = (unsigned long) &_stext;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) 0;
+ init_mm.brk = (unsigned long) 0;
config_BSP(&command_line[0], sizeof(command_line));
@@ -171,7 +181,7 @@ void setup_arch(char **cmdline_p)
#endif
#ifdef CONFIG_ELITE
printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
-#endif
+#endif
#ifdef CONFIG_TELOS
printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n");
#endif
@@ -200,6 +210,9 @@ void setup_arch(char **cmdline_p)
#ifdef CONFIG_DRAGEN2
printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
#endif
+#ifdef CONFIG_M5235EVB
+ printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)");
+#endif
#ifdef DEBUG
printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
@@ -223,7 +236,7 @@ void setup_arch(char **cmdline_p)
saved_command_line[COMMAND_LINE_SIZE-1] = 0;
#ifdef DEBUG
- if (strlen(*cmdline_p))
+ if (strlen(*cmdline_p))
printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
#endif
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 30dceb59a462..43a2726c0d0a 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -732,13 +732,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 5c3ca671627c..b17c1ecba966 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -68,7 +68,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
@@ -178,10 +178,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index ad7dc6347f19..5bc068462864 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -21,6 +21,7 @@
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/a.out.h>
#include <linux/user.h>
@@ -38,7 +39,7 @@
#include <asm/machdep.h>
#include <asm/siginfo.h>
-static char *vec_names[] = {
+static char const * const vec_names[] = {
"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
@@ -106,17 +107,20 @@ asmlinkage void buserr_c(struct frame *fp)
int kstack_depth_to_print = 48;
-void show_stack(struct task_struct *task, unsigned long *esp)
+void show_stack(struct task_struct *task, unsigned long *stack)
{
- unsigned long *stack, *endstack, addr;
+ unsigned long *endstack, addr;
extern char _start, _etext;
int i;
- if (esp == NULL)
- esp = (unsigned long *) &esp;
+ if (!stack) {
+ if (task)
+ stack = (unsigned long *)task->thread.ksp;
+ else
+ stack = (unsigned long *)&stack;
+ }
- stack = esp;
- addr = (unsigned long) esp;
+ addr = (unsigned long) stack;
endstack = (unsigned long *) PAGE_ALIGN(addr);
printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
@@ -306,6 +310,8 @@ void dump_stack(void)
show_stack(current, &stack);
}
+EXPORT_SYMBOL(dump_stack);
+
#ifdef CONFIG_M68KFPU_EMU
asmlinkage void fpemu_signal(int signal, int code, void *addr)
{
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 31cb12892da5..47f06787190d 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -107,7 +107,7 @@
*/
#if defined(CONFIG_ELITE)
#define RAM_START 0x30020000
-#define RAM_END 0xe0000
+#define RAM_LENGTH 0xe0000
#endif
/*
@@ -118,7 +118,8 @@
#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \
- defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB)
+ defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) || \
+ defined(CONFIG_M5235EVB)
#define RAM_START 0x20000
#define RAM_LENGTH 0x3e0000
#endif
@@ -145,6 +146,16 @@
#define RAM_LENGTH 0x3f0000
#endif
+
+/*
+ * The EMAC SoM-5282EM module.
+ */
+#if defined(CONFIG_SOM5282EM)
+#define RAM_START 0x10000
+#define RAM_LENGTH 0xff0000
+#endif
+
+
/*
* These flash boot boards use all of ram for operation. Again the
* actual memory size is not important here, assume at least 4MiB.
@@ -158,7 +169,7 @@
#endif
/*
- * Sneha Boards mimimun memmory
+ * Sneha Boards mimimun memory
* The end of RAM will vary depending on how much ram is fitted,
* but this isn't important here, we assume at least 4MiB.
*/
@@ -167,6 +178,12 @@
#define RAM_LENGTH 0x3e0000
#endif
+#if defined(CONFIG_MOD5272)
+#define RAM_START 0x02000000
+#define RAM_LENGTH 0x00800000
+#define RAMVEC_START 0x20000000
+#define RAMVEC_LENGTH 0x00000400
+#endif
#if defined(CONFIG_RAMKERNEL)
#define TEXT ram
diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68knommu/platform/523x/Makefile
new file mode 100644
index 000000000000..c1578b016160
--- /dev/null
+++ b/arch/m68knommu/platform/523x/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this, which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+obj-y := config.o
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
new file mode 100644
index 000000000000..22767ce506e0
--- /dev/null
+++ b/arch/m68knommu/platform/523x/config.c
@@ -0,0 +1,82 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/523x/config.c
+ *
+ * Sub-architcture dependant initialization code for the Freescale
+ * 523x CPUs.
+ *
+ * Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void);
+void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_pit_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+/***************************************************************************/
+
+/*
+ * DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
+ MCF_MBAR + MCFDMA_BASE0,
+};
+
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void mcf_disableall(void)
+{
+ *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
+ *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
+}
+
+/***************************************************************************/
+
+void mcf_autovector(unsigned int vec)
+{
+ /* Everything is auto-vectored on the 5272 */
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+ mcf_disableall();
+
+#ifdef CONFIG_BOOTPARAM
+ strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+ commandp[size-1] = 0;
+#else
+ memset(commandp, 0, size);
+#endif
+
+ mach_sched_init = coldfire_pit_init;
+ mach_tick = coldfire_pit_tick;
+ mach_gettimeoffset = coldfire_pit_offset;
+ mach_trap_init = coldfire_trap_init;
+ mach_reset = coldfire_reset;
+}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index 5cb28690f89a..cf36e7d007b9 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -104,11 +104,11 @@ int mcf_timerirqpending(int timer)
void config_BSP(char *commandp, int size)
{
-#if 0
- volatile unsigned long *pivrp;
+#if defined (CONFIG_MOD5272)
+ volatile unsigned char *pivrp;
/* Set base of device vectors to be 64 */
- pivrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PIVR);
+ pivrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_PIVR);
*pivrp = 0x40;
#endif
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 84b6b70641e1..6fe5a2b8fb08 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o
obj-$(CONFIG_M5206) += timers.o
obj-$(CONFIG_M5206e) += timers.o
+obj-$(CONFIG_M523x) += pit.o
obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
obj-$(CONFIG_M5272) += timers.o
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index c7d7a395c4cc..7f4ba837901f 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -39,14 +39,18 @@
* Memory size exceptions for special cases. Some boards may be set
* for auto memory sizing, but we can't do it that way for some reason.
* For example the 5206eLITE board has static RAM, and auto-detecting
- * the SDRAM will do you no good at all.
+ * the SDRAM will do you no good at all. Same goes for the MOD5272.
*/
#ifdef CONFIG_RAMAUTO
#if defined(CONFIG_M5206eLITE)
-#define MEM_SIZE 0x00100000 /* 1MiB default memory */
+#define MEM_SIZE 0x00100000 /* 1MiB default memory */
+#endif
+#if defined(CONFIG_MOD5272)
+#define MEM_SIZE 0x00800000 /* 8MiB default memory */
#endif
#endif /* CONFIG_RAMAUTO */
+
/*
* If we don't have a fixed memory size now, then lets build in code
* to auto detect the DRAM size. Obviously this is the prefered
@@ -100,11 +104,15 @@
/*
* Most ColdFire boards have their DRAM starting at address 0.
- * Notable exception is the 5206eLITE board.
+ * Notable exception is the 5206eLITE board, another is the MOD5272.
*/
#if defined(CONFIG_M5206eLITE)
#define MEM_BASE 0x30000000
#endif
+#if defined(CONFIG_MOD5272)
+#define MEM_BASE 0x02000000
+#define VBR_BASE 0x20000000 /* vectors in SRAM */
+#endif
#ifndef MEM_BASE
#define MEM_BASE 0x00000000 /* memory base at address 0 */
@@ -188,6 +196,7 @@ _start:
movel %a7,_rambase
GET_MEM_SIZE /* macro code determines size */
+ addl %a7,%d0
movel %d0,_ramend /* set end ram addr */
/*
diff --git a/arch/m68knommu/platform/68328/config.c b/arch/m68knommu/platform/68328/config.c
index fd7c93f86481..bcfa5d7fe1e2 100644
--- a/arch/m68knommu/platform/68328/config.c
+++ b/arch/m68knommu/platform/68328/config.c
@@ -1,5 +1,7 @@
+/***************************************************************************/
+
/*
- * linux/arch/$(ARCH)/platform/$(PLATFORM)/config.c
+ * linux/arch/m68knommu/platform/68328/config.c
*
* Copyright (C) 1993 Hamish Macdonald
* Copyright (C) 1999 D. Jeff Dionne
@@ -11,6 +13,8 @@
* VZ Support/Fixes Evan Stawnyczy <e@lineo.ca>
*/
+/***************************************************************************/
+
#include <asm/dbg.h>
#include <stdarg.h>
#include <linux/config.h>
@@ -29,76 +33,16 @@
#include <asm/machdep.h>
#include <asm/MC68328.h>
+/***************************************************************************/
-void BSP_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
-{
-
-#ifdef CONFIG_XCOPILOT_BUGS
- /*
- * The only thing I know is that CLK32 is not available on Xcopilot
- * I have little idea about what frequency SYSCLK has on Xcopilot.
- * The values for prescaler and compare registers were simply
- * taken from the original source
- */
-
- /* Restart mode, Enable int, SYSCLK, Enable timer */
- TCTL2 = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_SYSCLK | TCTL_TEN;
- /* Set prescaler */
- TPRER2 = 2;
- /* Set compare register */
- TCMP2 = 0xd7e4;
-#else
- /* Restart mode, Enable int, 32KHz, Enable timer */
- TCTL2 = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
- /* Set prescaler (Divide 32KHz by 32)*/
- TPRER2 = 31;
- /* Set compare register 32Khz / 32 / 10 = 100 */
- TCMP2 = 10;
-#endif
-
- request_irq(TMR2_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL);
-}
-
-void BSP_tick(void)
-{
- /* Reset Timer2 */
- TSTAT2 &= 0;
-}
+void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_tick(void);
+unsigned long m68328_timer_gettimeoffset(void);
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-unsigned long BSP_gettimeoffset (void)
-{
- return 0;
-}
+/***************************************************************************/
-void BSP_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
-}
-
-int BSP_hwclk(int op, struct hwclk_time *t)
-{
- if (!op) {
- /* read */
- } else {
- /* write */
- }
- return 0;
-}
-
-int BSP_set_clock_mmss (unsigned long nowtime)
-{
-#if 0
- short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
-
- tod->second1 = real_seconds / 10;
- tod->second2 = real_seconds % 10;
- tod->minute1 = real_minutes / 10;
- tod->minute2 = real_minutes % 10;
-#endif
- return 0;
-}
-
-void BSP_reset (void)
+void m68328_reset (void)
{
local_irq_disable();
asm volatile ("moveal #0x10c00000, %a0;\n\t"
@@ -108,18 +52,22 @@ void BSP_reset (void)
"jmp (%a0);");
}
+/***************************************************************************/
+
void config_BSP(char *command, int len)
{
printk(KERN_INFO "\n68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
printk(KERN_INFO "68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
printk(KERN_INFO "68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
- mach_sched_init = BSP_sched_init;
- mach_tick = BSP_tick;
- mach_gettimeoffset = BSP_gettimeoffset;
- mach_gettod = BSP_gettod;
+ mach_sched_init = m68328_timer_init;
+ mach_tick = m68328_timer_tick;
+ mach_gettimeoffset = m68328_timer_gettimeoffset;
+ mach_gettod = m68328_timer_gettod;
mach_hwclk = NULL;
mach_set_clock_mmss = NULL;
- mach_reset = BSP_reset;
+ mach_reset = m68328_reset;
*command = '\0';
}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S
index 0f5d1fe8eb5f..7d8990d784a2 100644
--- a/arch/m68knommu/platform/68328/entry.S
+++ b/arch/m68knommu/platform/68328/entry.S
@@ -79,7 +79,7 @@ ENTRY(system_call)
movel %sp@(PT_ORIG_D0),%d0
movel %sp,%d1 /* get thread_info pointer */
- andl #0xffffe000,%d1
+ andl #-THREAD_SIZE,%d1
movel %d1,%a2
btst #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS)
jne do_trace
@@ -105,7 +105,7 @@ Luser_return:
andw #ALLOWINT,%sr
movel %sp,%d1 /* get thread_info pointer */
- andl #0xffffe000,%d1
+ andl #-THREAD_SIZE,%d1
movel %d1,%a2
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1
diff --git a/arch/m68knommu/platform/68328/head-de2.S b/arch/m68knommu/platform/68328/head-de2.S
new file mode 100644
index 000000000000..94c5a1609a75
--- /dev/null
+++ b/arch/m68knommu/platform/68328/head-de2.S
@@ -0,0 +1,135 @@
+#include <linux/config.h>
+
+#if defined(CONFIG_RAM32MB)
+#define MEM_END 0x02000000 /* Memory size 32Mb */
+#elif defined(CONFIG_RAM16MB)
+#define MEM_END 0x01000000 /* Memory size 16Mb */
+#else
+#define MEM_END 0x00800000 /* Memory size 8Mb */
+#endif
+
+#undef CRT_DEBUG
+
+.macro PUTC CHAR
+#ifdef CRT_DEBUG
+ moveq #\CHAR, %d7
+ jsr putc
+#endif
+.endm
+
+ .global _start
+ .global _rambase
+ .global _ramvec
+ .global _ramstart
+ .global _ramend
+
+ .data
+
+/*
+ * Set up the usable of RAM stuff
+ */
+_rambase:
+ .long 0
+_ramvec:
+ .long 0
+_ramstart:
+ .long 0
+_ramend:
+ .long 0
+
+ .text
+
+_start:
+
+/*
+ * Setup initial stack
+ */
+ /* disable all interrupts */
+ movew #0x2700, %sr
+ movel #-1, 0xfffff304
+ movel #MEM_END-4, %sp
+
+ PUTC '\r'
+ PUTC '\n'
+ PUTC 'A'
+ PUTC 'B'
+
+/*
+ * Determine end of RAM
+ */
+
+ movel #MEM_END, %a0
+ movel %a0, _ramend
+
+ PUTC 'C'
+
+/*
+ * Move ROM filesystem above bss :-)
+ */
+
+ moveal #_sbss, %a0 /* romfs at the start of bss */
+ moveal #_ebss, %a1 /* Set up destination */
+ movel %a0, %a2 /* Copy of bss start */
+
+ movel 8(%a0), %d1 /* Get size of ROMFS */
+ addql #8, %d1 /* Allow for rounding */
+ andl #0xfffffffc, %d1 /* Whole words */
+
+ addl %d1, %a0 /* Copy from end */
+ addl %d1, %a1 /* Copy from end */
+ movel %a1, _ramstart /* Set start of ram */
+
+1:
+ movel -(%a0), %d0 /* Copy dword */
+ movel %d0, -(%a1)
+ cmpl %a0, %a2 /* Check if at end */
+ bne 1b
+
+ PUTC 'D'
+
+/*
+ * Initialize BSS segment to 0
+ */
+
+ lea _sbss, %a0
+ lea _ebss, %a1
+
+ /* Copy 0 to %a0 until %a0 == %a1 */
+2: cmpal %a0, %a1
+ beq 1f
+ clrl (%a0)+
+ bra 2b
+1:
+
+ PUTC 'E'
+
+/*
+ * Load the current task pointer and stack
+ */
+
+ lea init_thread_union, %a0
+ lea 0x2000(%a0), %sp
+
+ PUTC 'F'
+ PUTC '\r'
+ PUTC '\n'
+
+/*
+ * Go
+ */
+
+ jmp start_kernel
+
+/*
+ * Local functions
+ */
+
+#ifdef CRT_DEBUG
+putc:
+ moveb %d7, 0xfffff907
+1:
+ movew 0xfffff906, %d7
+ andw #0x2000, %d7
+ beq 1b
+ rts
+#endif
diff --git a/arch/m68knommu/platform/68328/timers.c b/arch/m68knommu/platform/68328/timers.c
new file mode 100644
index 000000000000..68c2cd6b0030
--- /dev/null
+++ b/arch/m68knommu/platform/68328/timers.c
@@ -0,0 +1,106 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/68328/timers.c
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ * Copyright (C) 1999 D. Jeff Dionne
+ * Copyright (C) 2001 Georges Menie, Ken Desmet
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/MC68VZ328.h>
+
+/***************************************************************************/
+
+#if defined(CONFIG_DRAGEN2)
+/* with a 33.16 MHz clock, this will give usec resolution to the time functions */
+#define CLOCK_SOURCE TCTL_CLKSOURCE_SYSCLK
+#define CLOCK_PRE 7
+#define TICKS_PER_JIFFY 41450
+
+#elif defined(CONFIG_XCOPILOT_BUGS)
+/*
+ * The only thing I know is that CLK32 is not available on Xcopilot
+ * I have little idea about what frequency SYSCLK has on Xcopilot.
+ * The values for prescaler and compare registers were simply
+ * taken from the original source
+ */
+#define CLOCK_SOURCE TCTL_CLKSOURCE_SYSCLK
+#define CLOCK_PRE 2
+#define TICKS_PER_JIFFY 0xd7e4
+
+#else
+/* default to using the 32Khz clock */
+#define CLOCK_SOURCE TCTL_CLKSOURCE_32KHZ
+#define CLOCK_PRE 31
+#define TICKS_PER_JIFFY 10
+#endif
+
+/***************************************************************************/
+
+void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *))
+{
+ /* disable timer 1 */
+ TCTL = 0;
+
+ /* set ISR */
+ if (request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL))
+ panic("Unable to attach timer interrupt\n");
+
+ /* Restart mode, Enable int, Set clock source */
+ TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
+ TPRER = CLOCK_PRE;
+ TCMP = TICKS_PER_JIFFY;
+
+ /* Enable timer 1 */
+ TCTL |= TCTL_TEN;
+}
+
+/***************************************************************************/
+
+void m68328_timer_tick(void)
+{
+ /* Reset Timer1 */
+ TSTAT &= 0;
+}
+/***************************************************************************/
+
+unsigned long m68328_timer_gettimeoffset(void)
+{
+ unsigned long ticks = TCN, offset = 0;
+
+ /* check for pending interrupt */
+ if (ticks < (TICKS_PER_JIFFY >> 1) && (ISR & (1 << TMR_IRQ_NUM)))
+ offset = 1000000 / HZ;
+ ticks = (ticks * 1000000 / HZ) / TICKS_PER_JIFFY;
+ return ticks + offset;
+}
+
+/***************************************************************************/
+
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec)
+{
+ long now = RTCTIME;
+
+ *year = *mon = *day = 1;
+ *hour = (now >> 24) % 24;
+ *min = (now >> 16) % 60;
+ *sec = now % 60;
+}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S
index f7bc80a60e0f..8ff48adf24ab 100644
--- a/arch/m68knommu/platform/68360/entry.S
+++ b/arch/m68knommu/platform/68360/entry.S
@@ -96,7 +96,7 @@ Luser_return:
andw #ALLOWINT,%sr
movel %sp,%d1 /* get thread_info pointer */
- andl #0xffffe000,%d1
+ andl #-THREAD_SIZE,%d1
movel %d1,%a2
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
new file mode 100644
index 000000000000..a5c639a51eef
--- /dev/null
+++ b/arch/m68knommu/platform/68360/head-ram.S
@@ -0,0 +1,408 @@
+/* arch/m68knommu/platform/68360/head-ram.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ * uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#define ASSEMBLY
+#include <linux/config.h>
+
+.global _stext
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB 0x1000
+#define PEPAR (_dprbase + REGB + 0x0016)
+#define GMR (_dprbase + REGB + 0x0040)
+#define OR0 (_dprbase + REGB + 0x0054)
+#define BR0 (_dprbase + REGB + 0x0050)
+#define OR1 (_dprbase + REGB + 0x0064)
+#define BR1 (_dprbase + REGB + 0x0060)
+#define OR4 (_dprbase + REGB + 0x0094)
+#define BR4 (_dprbase + REGB + 0x0090)
+#define OR6 (_dprbase + REGB + 0x00b4)
+#define BR6 (_dprbase + REGB + 0x00b0)
+#define OR7 (_dprbase + REGB + 0x00c4)
+#define BR7 (_dprbase + REGB + 0x00c0)
+
+#define MCR (_dprbase + REGB + 0x0000)
+#define AVR (_dprbase + REGB + 0x0008)
+
+#define SYPCR (_dprbase + REGB + 0x0022)
+
+#define PLLCR (_dprbase + REGB + 0x0010)
+#define CLKOCR (_dprbase + REGB + 0x000C)
+#define CDVCR (_dprbase + REGB + 0x0014)
+
+#define BKAR (_dprbase + REGB + 0x0030)
+#define BKCR (_dprbase + REGB + 0x0034)
+#define SWIV (_dprbase + REGB + 0x0023)
+#define PICR (_dprbase + REGB + 0x0026)
+#define PITR (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR 0x00000000
+#define SIM_OR_MASK 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK 0x20000002
+#define SIM_BR0_MASK 0x00000001
+
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK 0x10000000
+#define SIM_BR1_MASK 0x00000001
+
+#define MCU_SIM_MBAR_ADRS 0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK 0xfffff000
+#define MCU_SIM_MBAR_AS_MASK 0x00000001
+
+#define MCU_SIM_PEPAR 0x00B4
+
+#define MCU_DISABLE_INTRPTS 0x2700
+#define MCU_SIM_AVR 0x00
+
+#define MCU_SIM_MCR 0x00005cff
+
+#define MCU_SIM_CLKOCR 0x00
+#define MCU_SIM_PLLCR 0x8000
+#define MCU_SIM_CDVCR 0x0000
+
+#define MCU_SIM_SYPCR 0x0000
+#define MCU_SIM_SWIV 0x00
+#define MCU_SIM_PICR 0x0000
+#define MCU_SIM_PITR 0x0000
+
+
+#include <asm/m68360_regs.h>
+
+
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+ .text
+_start:
+_stext:
+ nop
+ ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */
+ /* We should not need to setup the boot stack the reset should do it. */
+ movea.l #__ramend, %sp /*set up stack at the end of DRAM:*/
+
+set_mbar_register:
+ moveq.l #0x07, %d1 /* Setup MBAR */
+ movec %d1, %dfc
+
+ lea.l MCU_SIM_MBAR_ADRS, %a0
+ move.l #_dprbase, %d0
+ andi.l #MCU_SIM_MBAR_BA_MASK, %d0
+ ori.l #MCU_SIM_MBAR_AS_MASK, %d0
+ moves.l %d0, %a0@
+
+ moveq.l #0x05, %d1
+ movec.l %d1, %dfc
+
+ /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+ /* Set Module Configuration Register */
+ move.l #MCU_SIM_MCR, MCR
+
+ /* to do: Determine cause of reset */
+
+ /*
+ * configure system clock MC68360 p. 6-40
+ * (value +1)*osc/128 = system clock
+ */
+set_sim_clock:
+ move.w #MCU_SIM_PLLCR, PLLCR
+ move.b #MCU_SIM_CLKOCR, CLKOCR
+ move.w #MCU_SIM_CDVCR, CDVCR
+
+ /* Wait for the PLL to settle */
+ move.w #16384, %d0
+pll_settle_wait:
+ subi.w #1, %d0
+ bne pll_settle_wait
+
+ /* Setup the system protection register, and watchdog timer register */
+ move.b #MCU_SIM_SWIV, SWIV
+ move.w #MCU_SIM_PICR, PICR
+ move.w #MCU_SIM_PITR, PITR
+ move.w #MCU_SIM_SYPCR, SYPCR
+
+ /* Clear DPRAM - system + parameter */
+ movea.l #_dprbase, %a0
+ movea.l #_dprbase+0x2000, %a1
+
+ /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+ movel #0, %a0@+
+ cmpal %a0, %a1
+ bhi clear_dpram
+
+configure_memory_controller:
+ /* Set up Global Memory Register (GMR) */
+ move.l #MCU_SIM_GMR, %d0
+ move.l %d0, GMR
+
+configure_chip_select_0:
+ move.l #__ramend, %d0
+ subi.l #__ramstart, %d0
+ subq.l #0x01, %d0
+ eori.l #SIM_OR_MASK, %d0
+ ori.l #SIM_OR0_MASK, %d0
+ move.l %d0, OR0
+
+ move.l #__ramstart, %d0
+ ori.l #SIM_BR0_MASK, %d0
+ move.l %d0, BR0
+
+configure_chip_select_1:
+ move.l #__rom_end, %d0
+ subi.l #__rom_start, %d0
+ subq.l #0x01, %d0
+ eori.l #SIM_OR_MASK, %d0
+ ori.l #SIM_OR1_MASK, %d0
+ move.l %d0, OR1
+
+ move.l #__rom_start, %d0
+ ori.l #SIM_BR1_MASK, %d0
+ move.l %d0, BR1
+
+ move.w #MCU_SIM_PEPAR, PEPAR
+
+ /* point to vector table: */
+ move.l #_romvec, %a0
+ move.l #_ramvec, %a1
+copy_vectors:
+ move.l %a0@, %d0
+ move.l %d0, %a1@
+ move.l %a0@, %a1@
+ addq.l #0x04, %a0
+ addq.l #0x04, %a1
+ cmp.l #_start, %a0
+ blt copy_vectors
+
+ move.l #_ramvec, %a1
+ movec %a1, %vbr
+
+
+ /* Copy data segment from ROM to RAM */
+ moveal #_stext, %a0
+ moveal #_sdata, %a1
+ moveal #_edata, %a2
+
+ /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+ move.l %a0@, %d0
+ addq.l #0x04, %a0
+ move.l %d0, %a1@
+ addq.l #0x04, %a1
+ cmp.l #_edata, %a1
+ blt LD1
+
+ moveal #_sbss, %a0
+ moveal #_ebss, %a1
+
+ /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+ movel #0, %a0@+
+ cmpal %a0, %a1
+ bhi L1
+
+load_quicc:
+ move.l #_dprbase, _quicc_base
+
+store_ram_size:
+ /* Set ram size information */
+ move.l #_sdata, _rambase
+ move.l #_ebss, _ramstart
+ move.l #__ramend, %d0
+ sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/
+ move.l %d0, _ramend /* Different from __ramend.*/
+
+store_flash_size:
+ /* Set rom size information */
+ move.l #__rom_end, %d0
+ sub.l #__rom_start, %d0
+ move.l %d0, rom_length
+
+ pea 0
+ pea env
+ pea %sp@(4)
+ pea 0
+
+ lea init_thread_union, %a2
+ lea 0x2000(%a2), %sp
+
+lp:
+ jsr start_kernel
+
+_exit:
+ jmp _exit
+
+
+ .data
+ .align 4
+env:
+ .long 0
+_quicc_base:
+ .long 0
+_periph_base:
+ .long 0
+_ramvec:
+ .long 0
+_rambase:
+ .long 0
+_ramstart:
+ .long 0
+_ramend:
+ .long 0
+_dprbase:
+ .long 0xffffe000
+
+ .text
+
+ /*
+ * These are the exception vectors at boot up, they are copied into RAM
+ * and then overwritten as needed.
+ */
+
+.section ".data.initvect","awx"
+ .long __ramend /* Reset: Initial Stack Pointer - 0. */
+ .long _start /* Reset: Initial Program Counter - 1. */
+ .long buserr /* Bus Error - 2. */
+ .long trap /* Address Error - 3. */
+ .long trap /* Illegal Instruction - 4. */
+ .long trap /* Divide by zero - 5. */
+ .long trap /* CHK, CHK2 Instructions - 6. */
+ .long trap /* TRAPcc, TRAPV Instructions - 7. */
+ .long trap /* Privilege Violation - 8. */
+ .long trap /* Trace - 9. */
+ .long trap /* Line 1010 Emulator - 10. */
+ .long trap /* Line 1111 Emualtor - 11. */
+ .long trap /* Harware Breakpoint - 12. */
+ .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */
+ .long trap /* Format Error - 14. */
+ .long trap /* Uninitialized Interrupt - 15. */
+ .long trap /* (Unassigned, Reserver) - 16. */
+ .long trap /* (Unassigned, Reserver) - 17. */
+ .long trap /* (Unassigned, Reserver) - 18. */
+ .long trap /* (Unassigned, Reserver) - 19. */
+ .long trap /* (Unassigned, Reserver) - 20. */
+ .long trap /* (Unassigned, Reserver) - 21. */
+ .long trap /* (Unassigned, Reserver) - 22. */
+ .long trap /* (Unassigned, Reserver) - 23. */
+ .long trap /* Spurious Interrupt - 24. */
+ .long trap /* Level 1 Interrupt Autovector - 25. */
+ .long trap /* Level 2 Interrupt Autovector - 26. */
+ .long trap /* Level 3 Interrupt Autovector - 27. */
+ .long trap /* Level 4 Interrupt Autovector - 28. */
+ .long trap /* Level 5 Interrupt Autovector - 29. */
+ .long trap /* Level 6 Interrupt Autovector - 30. */
+ .long trap /* Level 7 Interrupt Autovector - 31. */
+ .long system_call /* Trap Instruction Vectors 0 - 32. */
+ .long trap /* Trap Instruction Vectors 1 - 33. */
+ .long trap /* Trap Instruction Vectors 2 - 34. */
+ .long trap /* Trap Instruction Vectors 3 - 35. */
+ .long trap /* Trap Instruction Vectors 4 - 36. */
+ .long trap /* Trap Instruction Vectors 5 - 37. */
+ .long trap /* Trap Instruction Vectors 6 - 38. */
+ .long trap /* Trap Instruction Vectors 7 - 39. */
+ .long trap /* Trap Instruction Vectors 8 - 40. */
+ .long trap /* Trap Instruction Vectors 9 - 41. */
+ .long trap /* Trap Instruction Vectors 10 - 42. */
+ .long trap /* Trap Instruction Vectors 11 - 43. */
+ .long trap /* Trap Instruction Vectors 12 - 44. */
+ .long trap /* Trap Instruction Vectors 13 - 45. */
+ .long trap /* Trap Instruction Vectors 14 - 46. */
+ .long trap /* Trap Instruction Vectors 15 - 47. */
+ .long 0 /* (Reserved for Coprocessor) - 48. */
+ .long 0 /* (Reserved for Coprocessor) - 49. */
+ .long 0 /* (Reserved for Coprocessor) - 50. */
+ .long 0 /* (Reserved for Coprocessor) - 51. */
+ .long 0 /* (Reserved for Coprocessor) - 52. */
+ .long 0 /* (Reserved for Coprocessor) - 53. */
+ .long 0 /* (Reserved for Coprocessor) - 54. */
+ .long 0 /* (Reserved for Coprocessor) - 55. */
+ .long 0 /* (Reserved for Coprocessor) - 56. */
+ .long 0 /* (Reserved for Coprocessor) - 57. */
+ .long 0 /* (Reserved for Coprocessor) - 58. */
+ .long 0 /* (Unassigned, Reserved) - 59. */
+ .long 0 /* (Unassigned, Reserved) - 60. */
+ .long 0 /* (Unassigned, Reserved) - 61. */
+ .long 0 /* (Unassigned, Reserved) - 62. */
+ .long 0 /* (Unassigned, Reserved) - 63. */
+ /* The assignment of these vectors to the CPM is */
+ /* dependent on the configuration of the CPM vba */
+ /* fields. */
+ .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */
+ .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+ .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+ .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */
+ .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */
+ .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */
+ .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+ .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */
+ .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */
+ .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+ .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+ .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+ .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */
+ .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */
+ .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+ .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+ .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */
+ .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+ .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */
+ .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */
+ .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */
+ .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */
+ .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */
+ .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+ .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+ .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */
+ .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+ .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */
+ .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */
+ .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */
+ .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */
+ .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+ /* I don't think anything uses the vectors after here. */
+ .long 0 /* (User-Defined Vectors 34) - 96. */
+ .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */
+ .long 0,0,0 /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
new file mode 100644
index 000000000000..0da357a4cfee
--- /dev/null
+++ b/arch/m68knommu/platform/68360/head-rom.S
@@ -0,0 +1,420 @@
+/* arch/m68knommu/platform/68360/head-rom.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ * uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#include <linux/config.h>
+
+.global _stext
+.global _sbss
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB 0x1000
+#define PEPAR (_dprbase + REGB + 0x0016)
+#define GMR (_dprbase + REGB + 0x0040)
+#define OR0 (_dprbase + REGB + 0x0054)
+#define BR0 (_dprbase + REGB + 0x0050)
+
+#define OR1 (_dprbase + REGB + 0x0064)
+#define BR1 (_dprbase + REGB + 0x0060)
+
+#define OR2 (_dprbase + REGB + 0x0074)
+#define BR2 (_dprbase + REGB + 0x0070)
+
+#define OR3 (_dprbase + REGB + 0x0084)
+#define BR3 (_dprbase + REGB + 0x0080)
+
+#define OR4 (_dprbase + REGB + 0x0094)
+#define BR4 (_dprbase + REGB + 0x0090)
+
+#define OR5 (_dprbase + REGB + 0x00A4)
+#define BR5 (_dprbase + REGB + 0x00A0)
+
+#define OR6 (_dprbase + REGB + 0x00b4)
+#define BR6 (_dprbase + REGB + 0x00b0)
+
+#define OR7 (_dprbase + REGB + 0x00c4)
+#define BR7 (_dprbase + REGB + 0x00c0)
+
+#define MCR (_dprbase + REGB + 0x0000)
+#define AVR (_dprbase + REGB + 0x0008)
+
+#define SYPCR (_dprbase + REGB + 0x0022)
+
+#define PLLCR (_dprbase + REGB + 0x0010)
+#define CLKOCR (_dprbase + REGB + 0x000C)
+#define CDVCR (_dprbase + REGB + 0x0014)
+
+#define BKAR (_dprbase + REGB + 0x0030)
+#define BKCR (_dprbase + REGB + 0x0034)
+#define SWIV (_dprbase + REGB + 0x0023)
+#define PICR (_dprbase + REGB + 0x0026)
+#define PITR (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR 0x00000000
+#define SIM_OR_MASK 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK 0x20000000
+#define SIM_BR0_MASK 0x00000001
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK 0x10000000
+#define SIM_BR1_MASK 0x00000001
+
+#define MCU_SIM_MBAR_ADRS 0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK 0xfffff000
+#define MCU_SIM_MBAR_AS_MASK 0x00000001
+
+#define MCU_SIM_PEPAR 0x00B4
+
+#define MCU_DISABLE_INTRPTS 0x2700
+#define MCU_SIM_AVR 0x00
+
+#define MCU_SIM_MCR 0x00005cff
+
+#define MCU_SIM_CLKOCR 0x00
+#define MCU_SIM_PLLCR 0x8000
+#define MCU_SIM_CDVCR 0x0000
+
+#define MCU_SIM_SYPCR 0x0000
+#define MCU_SIM_SWIV 0x00
+#define MCU_SIM_PICR 0x0000
+#define MCU_SIM_PITR 0x0000
+
+
+#include <asm/m68360_regs.h>
+
+
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+ .text
+_start:
+_stext:
+ nop
+ ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */
+ /* We should not need to setup the boot stack the reset should do it. */
+ movea.l #__ramend, %sp /* set up stack at the end of DRAM:*/
+
+
+set_mbar_register:
+ moveq.l #0x07, %d1 /* Setup MBAR */
+ movec %d1, %dfc
+
+ lea.l MCU_SIM_MBAR_ADRS, %a0
+ move.l #_dprbase, %d0
+ andi.l #MCU_SIM_MBAR_BA_MASK, %d0
+ ori.l #MCU_SIM_MBAR_AS_MASK, %d0
+ moves.l %d0, %a0@
+
+ moveq.l #0x05, %d1
+ movec.l %d1, %dfc
+
+ /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+ /* Set Module Configuration Register */
+ move.l #MCU_SIM_MCR, MCR
+
+ /* to do: Determine cause of reset */
+
+ /*
+ * configure system clock MC68360 p. 6-40
+ * (value +1)*osc/128 = system clock
+ * or
+ * (value + 1)*osc = system clock
+ * You do not need to divide the oscillator by 128 unless you want to.
+ */
+set_sim_clock:
+ move.w #MCU_SIM_PLLCR, PLLCR
+ move.b #MCU_SIM_CLKOCR, CLKOCR
+ move.w #MCU_SIM_CDVCR, CDVCR
+
+ /* Wait for the PLL to settle */
+ move.w #16384, %d0
+pll_settle_wait:
+ subi.w #1, %d0
+ bne pll_settle_wait
+
+ /* Setup the system protection register, and watchdog timer register */
+ move.b #MCU_SIM_SWIV, SWIV
+ move.w #MCU_SIM_PICR, PICR
+ move.w #MCU_SIM_PITR, PITR
+ move.w #MCU_SIM_SYPCR, SYPCR
+
+ /* Clear DPRAM - system + parameter */
+ movea.l #_dprbase, %a0
+ movea.l #_dprbase+0x2000, %a1
+
+ /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+ movel #0, %a0@+
+ cmpal %a0, %a1
+ bhi clear_dpram
+
+configure_memory_controller:
+ /* Set up Global Memory Register (GMR) */
+ move.l #MCU_SIM_GMR, %d0
+ move.l %d0, GMR
+
+configure_chip_select_0:
+ move.l #0x00400000, %d0
+ subq.l #0x01, %d0
+ eori.l #SIM_OR_MASK, %d0
+ ori.l #SIM_OR0_MASK, %d0
+ move.l %d0, OR0
+
+ move.l #__rom_start, %d0
+ ori.l #SIM_BR0_MASK, %d0
+ move.l %d0, BR0
+
+ move.l #0x0, BR1
+ move.l #0x0, BR2
+ move.l #0x0, BR3
+ move.l #0x0, BR4
+ move.l #0x0, BR5
+ move.l #0x0, BR6
+ move.l #0x0, BR7
+
+ move.w #MCU_SIM_PEPAR, PEPAR
+
+ /* point to vector table: */
+ move.l #_romvec, %a0
+ move.l #_ramvec, %a1
+copy_vectors:
+ move.l %a0@, %d0
+ move.l %d0, %a1@
+ move.l %a0@, %a1@
+ addq.l #0x04, %a0
+ addq.l #0x04, %a1
+ cmp.l #_start, %a0
+ blt copy_vectors
+
+ move.l #_ramvec, %a1
+ movec %a1, %vbr
+
+
+ /* Copy data segment from ROM to RAM */
+ moveal #_etext, %a0
+ moveal #_sdata, %a1
+ moveal #_edata, %a2
+
+ /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+ move.l %a0@, %d0
+ addq.l #0x04, %a0
+ move.l %d0, %a1@
+ addq.l #0x04, %a1
+ cmp.l #_edata, %a1
+ blt LD1
+
+ moveal #_sbss, %a0
+ moveal #_ebss, %a1
+
+ /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+ movel #0, %a0@+
+ cmpal %a0, %a1
+ bhi L1
+
+load_quicc:
+ move.l #_dprbase, _quicc_base
+
+store_ram_size:
+ /* Set ram size information */
+ move.l #_sdata, _rambase
+ move.l #_ebss, _ramstart
+ move.l #__ramend, %d0
+ sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/
+ move.l %d0, _ramend /* Different from __ramend.*/
+
+store_flash_size:
+ /* Set rom size information */
+ move.l #__rom_end, %d0
+ sub.l #__rom_start, %d0
+ move.l %d0, rom_length
+
+ pea 0
+ pea env
+ pea %sp@(4)
+ pea 0
+
+ lea init_thread_union, %a2
+ lea 0x2000(%a2), %sp
+
+lp:
+ jsr start_kernel
+
+_exit:
+ jmp _exit
+
+
+ .data
+ .align 4
+env:
+ .long 0
+_quicc_base:
+ .long 0
+_periph_base:
+ .long 0
+_ramvec:
+ .long 0
+_rambase:
+ .long 0
+_ramstart:
+ .long 0
+_ramend:
+ .long 0
+_dprbase:
+ .long 0xffffe000
+
+
+ .text
+
+ /*
+ * These are the exception vectors at boot up, they are copied into RAM
+ * and then overwritten as needed.
+ */
+
+.section ".data.initvect","awx"
+ .long __ramend /* Reset: Initial Stack Pointer - 0. */
+ .long _start /* Reset: Initial Program Counter - 1. */
+ .long buserr /* Bus Error - 2. */
+ .long trap /* Address Error - 3. */
+ .long trap /* Illegal Instruction - 4. */
+ .long trap /* Divide by zero - 5. */
+ .long trap /* CHK, CHK2 Instructions - 6. */
+ .long trap /* TRAPcc, TRAPV Instructions - 7. */
+ .long trap /* Privilege Violation - 8. */
+ .long trap /* Trace - 9. */
+ .long trap /* Line 1010 Emulator - 10. */
+ .long trap /* Line 1111 Emualtor - 11. */
+ .long trap /* Harware Breakpoint - 12. */
+ .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */
+ .long trap /* Format Error - 14. */
+ .long trap /* Uninitialized Interrupt - 15. */
+ .long trap /* (Unassigned, Reserver) - 16. */
+ .long trap /* (Unassigned, Reserver) - 17. */
+ .long trap /* (Unassigned, Reserver) - 18. */
+ .long trap /* (Unassigned, Reserver) - 19. */
+ .long trap /* (Unassigned, Reserver) - 20. */
+ .long trap /* (Unassigned, Reserver) - 21. */
+ .long trap /* (Unassigned, Reserver) - 22. */
+ .long trap /* (Unassigned, Reserver) - 23. */
+ .long trap /* Spurious Interrupt - 24. */
+ .long trap /* Level 1 Interrupt Autovector - 25. */
+ .long trap /* Level 2 Interrupt Autovector - 26. */
+ .long trap /* Level 3 Interrupt Autovector - 27. */
+ .long trap /* Level 4 Interrupt Autovector - 28. */
+ .long trap /* Level 5 Interrupt Autovector - 29. */
+ .long trap /* Level 6 Interrupt Autovector - 30. */
+ .long trap /* Level 7 Interrupt Autovector - 31. */
+ .long system_call /* Trap Instruction Vectors 0 - 32. */
+ .long trap /* Trap Instruction Vectors 1 - 33. */
+ .long trap /* Trap Instruction Vectors 2 - 34. */
+ .long trap /* Trap Instruction Vectors 3 - 35. */
+ .long trap /* Trap Instruction Vectors 4 - 36. */
+ .long trap /* Trap Instruction Vectors 5 - 37. */
+ .long trap /* Trap Instruction Vectors 6 - 38. */
+ .long trap /* Trap Instruction Vectors 7 - 39. */
+ .long trap /* Trap Instruction Vectors 8 - 40. */
+ .long trap /* Trap Instruction Vectors 9 - 41. */
+ .long trap /* Trap Instruction Vectors 10 - 42. */
+ .long trap /* Trap Instruction Vectors 11 - 43. */
+ .long trap /* Trap Instruction Vectors 12 - 44. */
+ .long trap /* Trap Instruction Vectors 13 - 45. */
+ .long trap /* Trap Instruction Vectors 14 - 46. */
+ .long trap /* Trap Instruction Vectors 15 - 47. */
+ .long 0 /* (Reserved for Coprocessor) - 48. */
+ .long 0 /* (Reserved for Coprocessor) - 49. */
+ .long 0 /* (Reserved for Coprocessor) - 50. */
+ .long 0 /* (Reserved for Coprocessor) - 51. */
+ .long 0 /* (Reserved for Coprocessor) - 52. */
+ .long 0 /* (Reserved for Coprocessor) - 53. */
+ .long 0 /* (Reserved for Coprocessor) - 54. */
+ .long 0 /* (Reserved for Coprocessor) - 55. */
+ .long 0 /* (Reserved for Coprocessor) - 56. */
+ .long 0 /* (Reserved for Coprocessor) - 57. */
+ .long 0 /* (Reserved for Coprocessor) - 58. */
+ .long 0 /* (Unassigned, Reserved) - 59. */
+ .long 0 /* (Unassigned, Reserved) - 60. */
+ .long 0 /* (Unassigned, Reserved) - 61. */
+ .long 0 /* (Unassigned, Reserved) - 62. */
+ .long 0 /* (Unassigned, Reserved) - 63. */
+ /* The assignment of these vectors to the CPM is */
+ /* dependent on the configuration of the CPM vba */
+ /* fields. */
+ .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */
+ .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+ .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+ .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */
+ .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */
+ .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */
+ .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+ .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */
+ .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */
+ .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+ .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+ .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+ .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */
+ .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */
+ .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+ .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+ .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */
+ .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+ .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */
+ .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */
+ .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */
+ .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */
+ .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */
+ .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+ .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+ .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */
+ .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+ .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */
+ .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */
+ .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */
+ .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */
+ .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+ /* I don't think anything uses the vectors after here. */
+ .long 0 /* (User-Defined Vectors 34) - 96. */
+ .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */
+ .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */
+ .long 0,0,0 /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/m68knommu/platform/68EZ328/config.c b/arch/m68knommu/platform/68EZ328/config.c
index c21971971ff5..d8d56e5de310 100644
--- a/arch/m68knommu/platform/68EZ328/config.c
+++ b/arch/m68knommu/platform/68EZ328/config.c
@@ -1,5 +1,7 @@
+/***************************************************************************/
+
/*
- * linux/arch/$(ARCH)/platform/$(PLATFORM)/config.c
+ * linux/arch/m68knommu/platform/68EZ328/config.c
*
* Copyright (C) 1993 Hamish Macdonald
* Copyright (C) 1999 D. Jeff Dionne
@@ -9,6 +11,8 @@
* for more details.
*/
+/***************************************************************************/
+
#include <stdarg.h>
#include <linux/config.h>
#include <linux/types.h>
@@ -20,68 +24,22 @@
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/MC68EZ328.h>
#ifdef CONFIG_UCSIMM
#include <asm/bootstd.h>
#endif
-#ifdef CONFIG_PILOT
-#include "PalmV/romfs.h"
-#endif
-
-void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
-{
- /* Restart mode, Enable int, 32KHz, Enable timer */
- TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
- /* Set prescaler (Divide 32KHz by 32)*/
- TPRER = 31;
- /* Set compare register 32Khz / 32 / 10 = 100 */
- TCMP = 10;
-
- request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL);
-}
-
-void BSP_tick(void)
-{
- /* Reset Timer1 */
- TSTAT &= 0;
-}
-
-unsigned long BSP_gettimeoffset (void)
-{
- return 0;
-}
-void BSP_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
-}
+/***************************************************************************/
-int BSP_hwclk(int op, struct hwclk_time *t)
-{
- if (!op) {
- /* read */
- } else {
- /* write */
- }
- return 0;
-}
+void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_tick(void);
+unsigned long m68328_timer_gettimeoffset(void);
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-int BSP_set_clock_mmss (unsigned long nowtime)
-{
-#if 0
- short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+/***************************************************************************/
- tod->second1 = real_seconds / 10;
- tod->second2 = real_seconds % 10;
- tod->minute1 = real_minutes / 10;
- tod->minute2 = real_minutes % 10;
-#endif
- return 0;
-}
-
-void BSP_reset (void)
+void m68ez328_reset(void)
{
local_irq_disable();
asm volatile ("
@@ -93,6 +51,8 @@ void BSP_reset (void)
");
}
+/***************************************************************************/
+
unsigned char *cs8900a_hwaddr;
static int errno;
@@ -119,11 +79,13 @@ void config_BSP(char *command, int len)
else command[0] = 0;
#endif
- mach_sched_init = BSP_sched_init;
- mach_tick = BSP_tick;
- mach_gettimeoffset = BSP_gettimeoffset;
- mach_gettod = BSP_gettod;
+ mach_sched_init = m68328_timer_init;
+ mach_tick = m68328_timer_tick;
+ mach_gettimeoffset = m68328_timer_gettimeoffset;
+ mach_gettod = m68328_timer_gettod;
mach_hwclk = NULL;
mach_set_clock_mmss = NULL;
- mach_reset = BSP_reset;
+ mach_reset = m68ez328_reset;
}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/68VZ328/de2/config.c b/arch/m68knommu/platform/68VZ328/config.c
index d0586197f113..d926524cdf82 100644
--- a/arch/m68knommu/platform/68VZ328/de2/config.c
+++ b/arch/m68knommu/platform/68VZ328/config.c
@@ -1,5 +1,7 @@
+/***************************************************************************/
+
/*
- * linux/arch/m68knommu/platform/MC68VZ328/de2/config.c
+ * linux/arch/m68knommu/platform/68VZ328/config.c
*
* Copyright (C) 1993 Hamish Macdonald
* Copyright (C) 1999 D. Jeff Dionne
@@ -10,6 +12,8 @@
* for more details.
*/
+/***************************************************************************/
+
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -25,66 +29,25 @@
#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/MC68VZ328.h>
+#include <asm/bootstd.h>
#ifdef CONFIG_INIT_LCD
-#include "screen.h"
+#include "bootlogo.h"
#endif
-/* with a 33.16 MHz clock, this will give usec resolution to the time functions */
-#define CLOCK_SOURCE TCTL_CLKSOURCE_SYSCLK
-#define CLOCK_PRE 7
-#define TICKS_PER_JIFFY 41450
-
-static void
-dragen2_sched_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *))
-{
- /* disable timer 1 */
- TCTL = 0;
-
- /* set ISR */
- if (request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL))
- panic("Unable to attach timer interrupt\n");
-
- /* Restart mode, Enable int, Set clock source */
- TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
- TPRER = CLOCK_PRE;
- TCMP = TICKS_PER_JIFFY;
-
- /* Enable timer 1 */
- TCTL |= TCTL_TEN;
-}
-
-static void dragen2_tick(void)
-{
- /* Reset Timer1 */
- TSTAT &= 0;
-}
-
-static unsigned long dragen2_gettimeoffset(void)
-{
- unsigned long ticks = TCN, offset = 0;
-
- /* check for pending interrupt */
- if (ticks < (TICKS_PER_JIFFY >> 1) && (ISR & (1 << TMR_IRQ_NUM)))
- offset = 1000000 / HZ;
-
- ticks = (ticks * 1000000 / HZ) / TICKS_PER_JIFFY;
+/***************************************************************************/
- return ticks + offset;
-}
+void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_tick(void);
+unsigned long m68328_timer_gettimeoffset(void);
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-static void dragen2_gettod(int *year, int *mon, int *day, int *hour,
- int *min, int *sec)
-{
- long now = RTCTIME;
+/***************************************************************************/
+/* Init Drangon Engine hardware */
+/***************************************************************************/
+#if defined(CONFIG_DRAGEN2)
- *year = *mon = *day = 1;
- *hour = (now >> 24) % 24;
- *min = (now >> 16) % 60;
- *sec = now % 60;
-}
-
-static void dragen2_reset(void)
+static void m68vz328_reset(void)
{
local_irq_disable();
@@ -103,7 +66,7 @@ static void dragen2_reset(void)
);
}
-static void init_hardware(void)
+static void init_hardware(char *command, int size)
{
#ifdef CONFIG_DIRECT_IO_ACCESS
SCR = 0x10; /* allow user access to internal registers */
@@ -170,6 +133,60 @@ static void init_hardware(void)
#endif
}
+/***************************************************************************/
+/* Init RT-Control uCdimm hardware */
+/***************************************************************************/
+#elif defined(CONFIG_UCDIMM)
+
+static void m68vz328_reset(void)
+{
+ local_irq_disable();
+ asm volatile ("
+ moveal #0x10c00000, %a0;
+ moveb #0, 0xFFFFF300;
+ moveal 0(%a0), %sp;
+ moveal 4(%a0), %a0;
+ jmp (%a0);
+ ");
+}
+
+unsigned char *cs8900a_hwaddr;
+static int errno;
+
+_bsc0(char *, getserialnum)
+_bsc1(unsigned char *, gethwaddr, int, a)
+_bsc1(char *, getbenv, char *, a)
+
+static void init_hardware(char *command, int size)
+{
+ char *p;
+
+ printk(KERN_INFO "uCdimm serial string [%s]\n", getserialnum());
+ p = cs8900a_hwaddr = gethwaddr(0);
+ printk(KERN_INFO "uCdimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5]);
+ p = getbenv("APPEND");
+ if (p)
+ strcpy(p, command);
+ else
+ command[0] = 0;
+}
+
+/***************************************************************************/
+#else
+
+static void m68vz328_reset(void)
+{
+}
+
+static void init_hardware(char *command, int size)
+{
+}
+
+/***************************************************************************/
+#endif
+/***************************************************************************/
+
void config_BSP(char *command, int size)
{
printk(KERN_INFO "68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
@@ -181,11 +198,13 @@ void config_BSP(char *command, int size)
memset(command, 0, size);
#endif
- init_hardware();
+ init_hardware(command, size);
- mach_sched_init = (void *)dragen2_sched_init;
- mach_tick = dragen2_tick;
- mach_gettimeoffset = dragen2_gettimeoffset;
- mach_reset = dragen2_reset;
- mach_gettod = dragen2_gettod;
+ mach_sched_init = (void *) m68328_timer_init;
+ mach_tick = m68328_timer_tick;
+ mach_gettimeoffset = m68328_timer_gettimeoffset;
+ mach_gettod = m68328_timer_gettod;
+ mach_reset = m68vz328_reset;
}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/config.c b/arch/m68knommu/platform/68VZ328/ucdimm/config.c
deleted file mode 100644
index 2deadaffd81e..000000000000
--- a/arch/m68knommu/platform/68VZ328/ucdimm/config.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * linux/arch/m68knommu/platform/68VZ328/ucdimm/config.c
- *
- * Copyright (C) 1993 Hamish Macdonald
- * Copyright (C) 1999 D. Jeff Dionne
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <stdarg.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-#include <asm/MC68VZ328.h>
-#include <asm/bootstd.h>
-
-void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
-{
- /* Restart mode, Enable int, 32KHz, Enable timer */
- TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
- /* Set prescaler (Divide 32KHz by 32)*/
- TPRER = 31;
- /* Set compare register 32Khz / 32 / 10 = 100 */
- TCMP = 10;
-
- request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL);
-}
-
-void BSP_tick(void)
-{
- /* Reset Timer1 */
- TSTAT &= 0;
-}
-
-unsigned long BSP_gettimeoffset (void)
-{
- return 0;
-}
-
-void BSP_gettod (int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
-}
-
-int BSP_hwclk(int op, struct hwclk_time *t)
-{
- if (!op) {
- /* read */
- } else {
- /* write */
- }
- return 0;
-}
-
-int BSP_set_clock_mmss (unsigned long nowtime)
-{
-#if 0
- short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
-
- tod->second1 = real_seconds / 10;
- tod->second2 = real_seconds % 10;
- tod->minute1 = real_minutes / 10;
- tod->minute2 = real_minutes % 10;
-#endif
- return 0;
-}
-
-void BSP_reset (void)
-{
- local_irq_disable();
- asm volatile ("
- moveal #0x10c00000, %a0;
- moveb #0, 0xFFFFF300;
- moveal 0(%a0), %sp;
- moveal 4(%a0), %a0;
- jmp (%a0);
- ");
-}
-
-unsigned char *cs8900a_hwaddr;
-static int errno;
-
-_bsc0(char *, getserialnum)
-_bsc1(unsigned char *, gethwaddr, int, a)
-_bsc1(char *, getbenv, char *, a)
-
-void config_BSP(char *command, int len)
-{
- unsigned char *p;
-
- printk(KERN_INFO "\n68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
-
- printk(KERN_INFO "uCdimm serial string [%s]\n",getserialnum());
- p = cs8900a_hwaddr = gethwaddr(0);
- printk(KERN_INFO "uCdimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- p[0], p[1], p[2], p[3], p[4], p[5]);
- p = getbenv("APPEND");
- if (p) strcpy(p,command);
- else command[0] = 0;
-
- mach_sched_init = BSP_sched_init;
- mach_tick = BSP_tick;
- mach_gettimeoffset = BSP_gettimeoffset;
- mach_gettod = BSP_gettod;
- mach_reset = BSP_reset;
-}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 898de2df1fc7..0eb71ac303af 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,27 +4,52 @@ config MIPS
# Horrible source of confusion. Die, die, die ...
select EMBEDDED
-config MIPS64
- bool "64-bit kernel"
- help
- Select this option if you want to build a 64-bit kernel. You should
- only select this option if you have hardware that actually has a
- 64-bit processor and if your application will actually benefit from
- 64-bit processing, otherwise say N. You must say Y for kernels for
- SGI IP27 (Origin 200 and 2000) and SGI IP32 (O2). If in doubt say N.
-
-config 64BIT
- def_bool MIPS64
-
-config MIPS32
+# shouldn't it be per-subarchitecture?
+config ARCH_MAY_HAVE_PC_FDC
bool
- depends on MIPS64 = 'n'
default y
mainmenu "Linux/MIPS Kernel Configuration"
source "init/Kconfig"
+config SYS_SUPPORTS_32BIT_KERNEL
+ bool
+config SYS_SUPPORTS_64BIT_KERNEL
+ bool
+config CPU_SUPPORTS_32BIT_KERNEL
+ bool
+config CPU_SUPPORTS_64BIT_KERNEL
+ bool
+
+menu "Kernel type"
+
+choice
+
+ prompt "Kernel code model"
+ help
+ You should only select this option if you have a workload that
+ actually benefits from 64-bit processing or if your machine has
+ large memory. You will only be presented a single option in this
+ menu if your system does not support both 32-bit and 64-bit kernels.
+
+config 32BIT
+ bool "32-bit kernel"
+ depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL
+ select TRAD_SIGNALS
+ help
+ Select this option if you want to build a 32-bit kernel.
+
+config 64BIT
+ bool "64-bit kernel"
+ depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
+ help
+ Select this option if you want to build a 64-bit kernel.
+
+endchoice
+
+endmenu
+
menu "Machine selection"
config MACH_JAZZ
@@ -34,6 +59,8 @@ config MACH_JAZZ
select GENERIC_ISA_DMA
select I8259
select ISA
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
This a family of machines based on the MIPS R4030 chipset which was
used by several vendors to build RISC/os and Windows NT workstations.
@@ -71,7 +98,9 @@ config OLIVETTI_M700
<http://www.linux-mips.org/>.
config MACH_VR41XX
- bool "Support for NEC VR41XX-based machines"
+ bool "Support for NEC VR4100 series based machines"
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
config NEC_CMBVR4133
bool "Support for NEC CMB-VR4133"
@@ -80,7 +109,6 @@ config NEC_CMBVR4133
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
- select PCI_VR41XX
config ROCKHOPPER
bool "Support for Rockhopper baseboard"
@@ -91,6 +119,7 @@ config ROCKHOPPER
config CASIO_E55
bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
depends on MACH_VR41XX
+ select CPU_LITTLE_ENDIAN
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
@@ -98,53 +127,61 @@ config CASIO_E55
config IBM_WORKPAD
bool "Support for IBM WorkPad z50"
depends on MACH_VR41XX
+ select CPU_LITTLE_ENDIAN
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
-config TANBAC_TB0226
- bool "Support for TANBAC TB0226 (Mbase)"
+config TANBAC_TB022X
+ bool "Support for TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
depends on MACH_VR41XX
+ select CPU_LITTLE_ENDIAN
select DMA_NONCOHERENT
- select HW_HAS_PCI
select IRQ_CPU
+ select HW_HAS_PCI
help
- The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC.
+ The TANBAC VR4131 multichip module(TB0225) and
+ the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms
+ manufactured by TANBAC.
+ Please refer to <http://www.tanbac.co.jp/>
+ about VR4131 multichip module and VR4131DIMM.
+
+config TANBAC_TB0226
+ bool "Support for TANBAC Mbase(TB0226)"
+ depends on TANBAC_TB022X
+ select GPIO_VR41XX
+ help
+ The TANBAC Mbase(TB0226) is a MIPS-based platform manufactured by TANBAC.
Please refer to <http://www.tanbac.co.jp/> about Mbase.
-config TANBAC_TB0229
- bool "Support for TANBAC TB0229 (VR4131DIMM)"
- depends on MACH_VR41XX
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
+config TANBAC_TB0287
+ bool "Support for TANBAC Mini-ITX DIMM base(TB0287)"
+ depends on TANBAC_TB022X
help
- The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
- Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
+ The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform manufactured by TANBAC.
+ Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base.
config VICTOR_MPC30X
bool "Support for Victor MP-C303/304"
+ depends on MACH_VR41XX
+ select CPU_LITTLE_ENDIAN
select DMA_NONCOHERENT
- select HW_HAS_PCI
select IRQ_CPU
- depends on MACH_VR41XX
+ select HW_HAS_PCI
config ZAO_CAPCELLA
bool "Support for ZAO Networks Capcella"
depends on MACH_VR41XX
+ select CPU_LITTLE_ENDIAN
select DMA_NONCOHERENT
- select HW_HAS_PCI
select IRQ_CPU
+ select HW_HAS_PCI
config PCI_VR41XX
bool "Add PCI control unit support of NEC VR4100 series"
- depends on MACH_VR41XX && PCI
-
-config VRC4171
- tristate "Add NEC VRC4171 companion chip support"
- depends on MACH_VR41XX && ISA
- ---help---
- The NEC VRC4171/4171A is a companion chip for NEC VR4111/VR4121.
+ depends on MACH_VR41XX && HW_HAS_PCI
+ default y
+ select PCI
config VRC4173
tristate "Add NEC VRC4173 companion chip support"
@@ -154,25 +191,28 @@ config VRC4173
config TOSHIBA_JMR3927
bool "Support for Toshiba JMR-TX3927 board"
- depends on MIPS32
select DMA_NONCOHERENT
select HW_HAS_PCI
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
config MIPS_COBALT
- bool "Support for Cobalt Server (EXPERIMENTAL)"
+ bool "Support for Cobalt Server"
depends on EXPERIMENTAL
select DMA_NONCOHERENT
select HW_HAS_PCI
select I8259
select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
config MACH_DECSTATION
bool "Support for DECstations"
select BOOT_ELF32
select DMA_NONCOHERENT
select IRQ_CPU
- depends on MIPS32 || EXPERIMENTAL
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
---help---
This enables support for DEC's MIPS based workstations. For details
see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
@@ -194,6 +234,8 @@ config MIPS_EV64120
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_GT64120
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This is an evaluation board based on the Galileo GT-64120
single-chip system controller that contains a MIPS R5000 compatible
@@ -214,6 +256,8 @@ config MIPS_EV96100
select MIPS_GT96100
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This is an evaluation board based on the Galileo GT-96100 LAN/WAN
communications controllers containing a MIPS R5000 compatible core
@@ -224,6 +268,8 @@ config MIPS_IVR
bool "Support for Globespan IVR board"
select DMA_NONCOHERENT
select HW_HAS_PCI
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
This is an evaluation board built by Globespan to showcase thir
iVR (Internet Video Recorder) design. It utilizes a QED RM5231
@@ -237,6 +283,8 @@ config LASAT
select HW_HAS_PCI
select MIPS_GT64120
select R5000_CPU_SCACHE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
config PICVUE
tristate "PICVUE LCD display driver"
@@ -258,6 +306,8 @@ config MIPS_ITE8172
bool "Support for ITE 8172G board"
select DMA_NONCOHERENT
select HW_HAS_PCI
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
with ATX form factor that utilizes a MIPS R5000 to work with its
@@ -281,6 +331,8 @@ config MIPS_ATLAS
select HW_HAS_PCI
select MIPS_GT64120
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This enables support for the QED R5231-based MIPS Atlas evaluation
board.
@@ -295,6 +347,8 @@ config MIPS_MALTA
select I8259
select MIPS_GT64120
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This enables support for the VR5000-based MIPS Malta evaluation
board.
@@ -304,6 +358,8 @@ config MIPS_SEAD
depends on EXPERIMENTAL
select IRQ_CPU
select DMA_NONCOHERENT
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
config MOMENCO_OCELOT
bool "Support for Momentum Ocelot board"
@@ -314,6 +370,8 @@ config MOMENCO_OCELOT
select MIPS_GT64120
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
@@ -327,6 +385,8 @@ config MOMENCO_OCELOT_G
select PCI_MARVELL
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
@@ -340,6 +400,8 @@ config MOMENCO_OCELOT_C
select PCI_MARVELL
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
@@ -355,6 +417,8 @@ config MOMENCO_OCELOT_3
select PCI_MARVELL
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
The Ocelot-3 is based off Discovery III System Controller and
PMC-Sierra Rm79000 core.
@@ -371,6 +435,8 @@ config MOMENCO_JAGUAR_ATX
select PCI_MARVELL
select RM7000_CPU_SCACHE
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
@@ -390,6 +456,8 @@ config PMC_YOSEMITE
select IRQ_CPU_RM7K
select IRQ_CPU_RM9K
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
Yosemite is an evaluation board for the RM9000x2 processor
manufactured by PMC-Sierra
@@ -407,6 +475,8 @@ config DDB5074
select IRQ_CPU
select I8259
select ISA
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This enables support for the VR5000-based NEC DDB Vrc-5074
evaluation board.
@@ -419,6 +489,8 @@ config DDB5476
select IRQ_CPU
select I8259
select ISA
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
This enables support for the R5432-based NEC DDB Vrc-5476
evaluation board.
@@ -433,6 +505,8 @@ config DDB5477
select HW_HAS_PCI
select I8259
select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
This enables support for the R5432-based NEC DDB Vrc-5477,
or Rockhopper/SolutionGear boards with R5432/R5500 CPUs.
@@ -445,10 +519,23 @@ config DDB5477_BUS_FREQUENCY
depends on DDB5477
default 0
-config NEC_OSPREY
- bool "Support for NEC Osprey board"
- select DMA_NONCOHERENT
- select IRQ_CPU
+config QEMU
+ bool "Support for Qemu"
+ select DMA_COHERENT
+ select GENERIC_ISA_DMA
+ select HAVE_STD_PC_SERIAL_PORT
+ select I8259
+ select ISA
+ select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ help
+ Qemu is a software emulator which among other architectures also
+ can simulate a MIPS32 4Kc system. This patch adds support for the
+ system architecture that currently is being simulated by Qemu. It
+ will eventually be removed again when Qemu has the capability to
+ simulate actual MIPS hardware platforms. More information on Qemu
+ can be found at http://www.linux-mips.org/wiki/Qemu.
config SGI_IP22
bool "Support for SGI IP22 (Indy/Indigo2)"
@@ -459,6 +546,8 @@ config SGI_IP22
select IP22_CPU_SCACHE
select IRQ_CPU
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This are the SGI Indy, Challenge S and Indigo2, as well as certain
OEM variants like the Tandem CMN B006S. To compile a Linux kernel
@@ -466,12 +555,12 @@ config SGI_IP22
config SGI_IP27
bool "Support for SGI IP27 (Origin200/2000)"
- depends on MIPS64
select ARC
select ARC64
select DMA_IP27
select HW_HAS_PCI
select PCI_DOMAINS
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
workstations. To compile a Linux kernel that runs on these, say Y
@@ -534,7 +623,7 @@ config REPLICATE_EXHANDLERS
config SGI_IP32
bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
- depends on MIPS64 && EXPERIMENTAL
+ depends on EXPERIMENTAL
select ARC
select ARC32
select BOOT_ELF32
@@ -544,12 +633,13 @@ config SGI_IP32
select HW_HAS_PCI
select R5000_CPU_SCACHE
select RM7000_CPU_SCACHE
+ select SYS_SUPPORTS_64BIT_KERNEL
help
If you want this kernel to run on SGI O2 workstation, say Y here.
config SOC_AU1X00
- depends on MIPS32
bool "Support for AMD/Alchemy Au1X00 SOCs"
+ select SYS_SUPPORTS_32BIT_KERNEL
choice
prompt "Au1X00 SOC Type"
@@ -661,6 +751,8 @@ config SIBYTE_SB1xxx_SOC
select BOOT_ELF32
select DMA_COHERENT
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
choice
prompt "BCM1xxx SOC-based board"
@@ -880,6 +972,8 @@ config SNI_RM200_PCI
select HW_HAS_PCI
select I8259
select ISA
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
help
The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
Nixdorf Informationssysteme (SNI), parent company of Pyramid
@@ -888,13 +982,14 @@ config SNI_RM200_PCI
config TOSHIBA_RBTX4927
bool "Support for Toshiba TBTX49[23]7 board"
- depends on MIPS32
select DMA_NONCOHERENT
select HAS_TXX9_SERIAL
select HW_HAS_PCI
select I8259
select ISA
select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
help
This Toshiba board is based on the TX4927 processor. Say Y here to
support this machine type
@@ -926,13 +1021,21 @@ config ARC
depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
default y
-config DMA_COHERENT
+config DMA_COHERENT
+ bool
+
+config DMA_IP27
bool
-config DMA_IP27
+config DMA_IP32
bool
+ select DMA_NEED_PCI_MAP_STATE
-config DMA_NONCOHERENT
+config DMA_NONCOHERENT
+ bool
+ select DMA_NEED_PCI_MAP_STATE
+
+config DMA_NEED_PCI_MAP_STATE
bool
config EARLY_PRINTK
@@ -974,7 +1077,7 @@ config MIPS_DISABLE_OBSOLETE_IDE
config CPU_LITTLE_ENDIAN
bool "Generate little endian code"
- default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || NEC_OSPREY || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
+ default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
default n if MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927
help
Some MIPS machines can be configured for either little or big endian
@@ -1091,11 +1194,6 @@ config ARC32
config HAVE_STD_PC_SERIAL_PORT
bool
-config VR4181
- bool
- depends on NEC_OSPREY
- default y
-
config ARC_CONSOLE
bool "ARC console support"
depends on SGI_IP22 || SNI_RM200_PCI
@@ -1145,13 +1243,16 @@ choice
config CPU_MIPS32
bool "MIPS32"
+ select CPU_SUPPORTS_32BIT_KERNEL
config CPU_MIPS64
bool "MIPS64"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
config CPU_R3000
bool "R3000"
- depends on MIPS32
+ select CPU_SUPPORTS_32BIT_KERNEL
help
Please make sure to pick the right CPU type. Linux/MIPS is not
designed to be generic, i.e. Kernels compiled for R3000 CPUs will
@@ -1162,10 +1263,12 @@ config CPU_R3000
config CPU_TX39XX
bool "R39XX"
- depends on MIPS32
+ select CPU_SUPPORTS_32BIT_KERNEL
config CPU_VR41XX
bool "R41xx"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
The options selects support for the NEC VR41xx series of processors.
Only choose this option if you have one of these processors as a
@@ -1174,20 +1277,28 @@ config CPU_VR41XX
config CPU_R4300
bool "R4300"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
MIPS Technologies R4300-series processors.
config CPU_R4X00
bool "R4x00"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
MIPS Technologies R4000-series processors other than 4300, including
the R4000, R4400, R4600, and 4700.
config CPU_TX49XX
bool "R49XX"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
config CPU_R5000
bool "R5000"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
MIPS Technologies R5000-series processors other than the Nevada.
@@ -1196,36 +1307,48 @@ config CPU_R5432
config CPU_R6000
bool "R6000"
- depends on MIPS32 && EXPERIMENTAL
+ depends on EXPERIMENTAL
+ select CPU_SUPPORTS_32BIT_KERNEL
help
MIPS Technologies R6000 and R6000A series processors. Note these
processors are extremly rare and the support for them is incomplete.
config CPU_NEVADA
bool "RM52xx"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
QED / PMC-Sierra RM52xx-series ("Nevada") processors.
config CPU_R8000
bool "R8000"
- depends on MIPS64 && EXPERIMENTAL
+ depends on EXPERIMENTAL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
MIPS Technologies R8000 processors. Note these processors are
uncommon and the support for them is incomplete.
config CPU_R10000
bool "R10000"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
help
MIPS Technologies R10000-series processors.
config CPU_RM7000
bool "RM7000"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
config CPU_RM9000
bool "RM9000"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
config CPU_SB1
bool "SB1"
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
endchoice
@@ -1321,11 +1444,11 @@ config SB1_PASS_2_1_WORKAROUNDS
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) && MIPS32
+ 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 MIPS32
+ 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.
@@ -1379,7 +1502,7 @@ config CPU_HAS_SYNC
#
config HIGHMEM
bool "High Memory Support"
- depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
+ depends on 32BIT && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
config ARCH_FLATMEM_ENABLE
def_bool y
@@ -1439,7 +1562,7 @@ config RTC_DS1742
config MIPS_INSANE_LARGE
bool "Support for large 64-bit configurations"
- depends on CPU_R10000 && MIPS64
+ depends on CPU_R10000 && 64BIT
help
MIPS R10000 does support a 44 bit / 16TB address space as opposed to
previous 64-bit processors which only supported 40 bit / 1TB. If you
@@ -1540,11 +1663,11 @@ source "fs/Kconfig.binfmt"
config TRAD_SIGNALS
bool
- default y if MIPS32
+ default y if 32BIT
config BUILD_ELF64
bool "Use 64-bit ELF format for building"
- depends on MIPS64
+ depends on 64BIT
help
A 64-bit kernel is usually built using the 64-bit ELF binary object
format as it's one that allows arbitrary 64-bit constructs. For
@@ -1559,11 +1682,11 @@ config BUILD_ELF64
config BINFMT_IRIX
bool "Include IRIX binary compatibility"
- depends on !CPU_LITTLE_ENDIAN && MIPS32 && BROKEN
+ depends on !CPU_LITTLE_ENDIAN && 32BIT && BROKEN
config MIPS32_COMPAT
bool "Kernel support for Linux/MIPS 32-bit binary compatibility"
- depends on MIPS64
+ depends on 64BIT
help
Select this option if you want Linux/MIPS 32-bit binary
compatibility. Since all software available for Linux/MIPS is
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index bc1c44274a58..346e803f153b 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -37,12 +37,12 @@ else
64bit-emul = elf64btsmip
endif
-ifdef CONFIG_MIPS32
+ifdef CONFIG_32BIT
gcc-abi = 32
tool-prefix = $(32bit-tool-prefix)
UTS_MACHINE := mips
endif
-ifdef CONFIG_MIPS64
+ifdef CONFIG_64BIT
gcc-abi = 64
tool-prefix = $(64bit-tool-prefix)
UTS_MACHINE := mips64
@@ -63,7 +63,7 @@ ld-emul = $(32bit-emul)
vmlinux-32 = vmlinux
vmlinux-64 = vmlinux.64
-cflags-$(CONFIG_MIPS64) += $(call cc-option,-mno-explicit-relocs)
+cflags-$(CONFIG_64BIT) += $(call cc-option,-mno-explicit-relocs)
endif
#
@@ -177,7 +177,7 @@ cflags-$(CONFIG_CPU_MIPS64) += \
cflags-$(CONFIG_CPU_R5000) += \
$(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
- -Wa,--trap
+ -Wa,--trap
cflags-$(CONFIG_CPU_R5432) += \
$(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
@@ -423,6 +423,12 @@ core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/
cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite
load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000
+# Qemu simulating MIPS32 4Kc
+#
+core-$(CONFIG_QEMU) += arch/mips/qemu/
+cflags-$(CONFIG_QEMU) += -Iinclude/asm-mips/mach-qemu
+load-$(CONFIG_QEMU) += 0xffffffff80010000
+
#
# Momentum Ocelot-3
#
@@ -469,13 +475,6 @@ cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
load-$(CONFIG_LASAT) += 0xffffffff80000000
#
-# NEC Osprey (vr4181) board
-#
-core-$(CONFIG_NEC_OSPREY) += arch/mips/vr4181/common/ \
- arch/mips/vr4181/osprey/
-load-$(CONFIG_NEC_OSPREY) += 0xffffffff80002000
-
-#
# Common VR41xx
#
core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/
@@ -490,13 +489,11 @@ load-$(CONFIG_NEC_CMBVR4133) += 0xffffffff80100000
#
# ZAO Networks Capcella (VR4131)
#
-core-$(CONFIG_ZAO_CAPCELLA) += arch/mips/vr41xx/zao-capcella/
load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000
#
# Victor MP-C303/304 (VR4122)
#
-core-$(CONFIG_VICTOR_MPC30X) += arch/mips/vr41xx/victor-mpc30x/
load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000
#
@@ -512,16 +509,9 @@ core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/
load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
#
-# TANBAC TB0226 Mbase (VR4131)
+# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131)
#
-core-$(CONFIG_TANBAC_TB0226) += arch/mips/vr41xx/tanbac-tb0226/
-load-$(CONFIG_TANBAC_TB0226) += 0xffffffff80000000
-
-#
-# TANBAC TB0229 VR4131DIMM (VR4131)
-#
-core-$(CONFIG_TANBAC_TB0229) += arch/mips/vr41xx/tanbac-tb0229/
-load-$(CONFIG_TANBAC_TB0229) += 0xffffffff80000000
+load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
#
# SGI IP22 (Indy/Indigo2)
@@ -534,10 +524,10 @@ load-$(CONFIG_TANBAC_TB0229) += 0xffffffff80000000
#
core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/
cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22
-ifdef CONFIG_MIPS32
+ifdef CONFIG_32BIT
load-$(CONFIG_SGI_IP22) += 0xffffffff88002000
endif
-ifdef CONFIG_MIPS64
+ifdef CONFIG_64BIT
load-$(CONFIG_SGI_IP22) += 0xffffffff88004000
endif
@@ -642,7 +632,7 @@ load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
cflags-y += -Iinclude/asm-mips/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/
-ifdef CONFIG_MIPS32
+ifdef CONFIG_32BIT
ifdef CONFIG_CPU_LITTLE_ENDIAN
JIFFIES = jiffies_64
else
@@ -674,8 +664,8 @@ CPPFLAGS_vmlinux.lds := \
head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
libs-y += arch/mips/lib/
-libs-$(CONFIG_MIPS32) += arch/mips/lib-32/
-libs-$(CONFIG_MIPS64) += arch/mips/lib-64/
+libs-$(CONFIG_32BIT) += arch/mips/lib-32/
+libs-$(CONFIG_64BIT) += arch/mips/lib-64/
core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
@@ -683,7 +673,7 @@ drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/
ifdef CONFIG_LASAT
rom.bin rom.sw: vmlinux
- $(call descend,arch/mips/lasat/image,$@)
+ $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
endif
#
@@ -730,38 +720,7 @@ archclean:
@$(MAKE) $(clean)=arch/mips/boot
@$(MAKE) $(clean)=arch/mips/lasat
-# Generate <asm/offset.h
-#
-# The default rule is suffering from funny problems on MIPS so we using our
-# own ...
-#
-# ---------------------------------------------------------------------------
-
-define filechk_gen-asm-offset.h
- (set -e; \
- echo "#ifndef _ASM_OFFSET_H"; \
- echo "#define _ASM_OFFSET_H"; \
- echo "/*"; \
- echo " * DO NOT MODIFY."; \
- echo " *"; \
- echo " * This file was generated by arch/$(ARCH)/Makefile"; \
- echo " *"; \
- echo " */"; \
- echo ""; \
- sed -ne "/^@@@/s///p"; \
- echo "#endif /* _ASM_OFFSET_H */" )
-endef
-
-prepare: include/asm-$(ARCH)/offset.h
-
-arch/$(ARCH)/kernel/offset.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/offset.s
- $(call filechk,gen-asm-offset.h)
-CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
- include/asm-$(ARCH)/offset.h \
- vmlinux.32 \
+CLEAN_FILES += vmlinux.32 \
vmlinux.64 \
vmlinux.ecoff
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
index 533721eef6ae..4e5a6e1a9a6e 100644
--- a/arch/mips/au1000/common/pci.c
+++ b/arch/mips/au1000/common/pci.c
@@ -40,14 +40,14 @@
/* TBD */
static struct resource pci_io_resource = {
- "pci IO space",
+ "pci IO space",
(u32)PCI_IO_START,
(u32)PCI_IO_END,
IORESOURCE_IO
};
static struct resource pci_mem_resource = {
- "pci memory space",
+ "pci memory space",
(u32)PCI_MEM_START,
(u32)PCI_MEM_END,
IORESOURCE_MEM
@@ -68,7 +68,7 @@ static unsigned long virt_io_addr;
static int __init au1x_pci_setup(void)
{
#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
- virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
+ virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
if (!virt_io_addr) {
@@ -77,7 +77,7 @@ static int __init au1x_pci_setup(void)
}
#ifdef CONFIG_DMA_NONCOHERENT
- /*
+ /*
* Set the NC bit in controller for Au1500 pre-AC silicon
*/
u32 prid = read_c0_prid();
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index dbc8b1bda963..eff89e109ce6 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -97,7 +97,7 @@ static int __init au1x00_setup(void)
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
-#endif
+#endif
#ifdef CONFIG_FB_AU1100
if ((argptr = strstr(argptr, "video=")) == NULL) {
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index fe418f1620c3..57675b41480e 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -281,7 +281,7 @@ unsigned long cal_r4koff(void)
cpu_speed = count * 2;
}
#else
- cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
+ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
AU1000_SRC_CLK;
count = cpu_speed / 2;
#endif
@@ -356,7 +356,7 @@ static unsigned long do_fast_cp0_gettimeoffset(void)
: "hi", "lo", GCC_REG_ACCUM);
/*
- * Due to possible jiffies inconsistencies, we need to check
+ * Due to possible jiffies inconsistencies, we need to check
* the result so that we'll get a timer that is monotonic.
*/
if (res >= USECS_PER_JIFFY)
@@ -375,8 +375,8 @@ static unsigned long do_fast_pm_gettimeoffset(void)
au_sync();
offset = pc0 - last_pc0;
if (offset > 2*MATCH20_INC) {
- printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
- (unsigned)offset, (unsigned)last_pc0,
+ printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
+ (unsigned)offset, (unsigned)last_pc0,
(unsigned)last_match20, (unsigned)pc0);
}
offset = (unsigned long)((offset * 305) / 10);
@@ -394,11 +394,11 @@ void au1xxx_timer_setup(struct irqaction *irq)
r4k_offset = cal_r4koff();
printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
- //est_freq = 2*r4k_offset*HZ;
- est_freq = r4k_offset*HZ;
+ //est_freq = 2*r4k_offset*HZ;
+ est_freq = r4k_offset*HZ;
est_freq += 5000; /* round */
est_freq -= est_freq%10000;
- printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
(est_freq%1000000)*100/1000000);
set_au1x00_speed(est_freq);
set_au1x00_lcd_clock(); // program the LCD clock
diff --git a/arch/mips/au1000/csb250/board_setup.c b/arch/mips/au1000/csb250/board_setup.c
index 90426eaffb23..1c55c5f59d75 100644
--- a/arch/mips/au1000/csb250/board_setup.c
+++ b/arch/mips/au1000/csb250/board_setup.c
@@ -182,7 +182,7 @@ void __init board_setup(void)
au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
au_writel(0x02a00356, Au1500_PCI_STATCMD);
- au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
+ au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
au_writel(0x00000008, Au1500_PCI_MBAR);
au_sync();
@@ -216,7 +216,7 @@ csb250_pci_idsel(unsigned int devsel, int assert)
unsigned int gpio2_pins;
retval = 1;
-
+
/* First, disable both selects, then assert the one requested.
*/
au_writel(0xc000c000, GPIO2_OUTPUT);
diff --git a/arch/mips/au1000/csb250/init.c b/arch/mips/au1000/csb250/init.c
index 4320057fc439..bd99733abc0b 100644
--- a/arch/mips/au1000/csb250/init.c
+++ b/arch/mips/au1000/csb250/init.c
@@ -81,7 +81,7 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
csb_env[0] = env1;
mips_machgroup = MACH_GROUP_ALCHEMY;
- mips_machtype = MACH_CSB250;
+ mips_machtype = MACH_CSB250;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
index 51eee94a5e82..4b9d5e46edbb 100644
--- a/arch/mips/au1000/db1x00/init.c
+++ b/arch/mips/au1000/db1x00/init.c
@@ -61,7 +61,7 @@ void __init prom_init(void)
prom_envp = (char **) fw_arg2;
mips_machgroup = MACH_GROUP_ALCHEMY;
- mips_machtype = MACH_DB1000; /* set the platform # */
+ mips_machtype = MACH_DB1000; /* set the platform # */
prom_init_cmdline();
diff --git a/arch/mips/au1000/hydrogen3/init.c b/arch/mips/au1000/hydrogen3/init.c
index eee4adf98711..8cc9879dd582 100644
--- a/arch/mips/au1000/hydrogen3/init.c
+++ b/arch/mips/au1000/hydrogen3/init.c
@@ -63,7 +63,7 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
prom_envp = envp;
mips_machgroup = MACH_GROUP_ALCHEMY;
- mips_machtype = MACH_DB1000; /* set the platform # */
+ mips_machtype = MACH_DB1000; /* set the platform # */
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c
index 2fa211b69329..0b4807dc9f44 100644
--- a/arch/mips/au1000/pb1000/board_setup.c
+++ b/arch/mips/au1000/pb1000/board_setup.c
@@ -174,7 +174,7 @@ void __init board_setup(void)
case 0x02: /* HB */
break;
default: /* HC and newer */
- /* Enable sys bus clock divider when IDLE state or no bus
+ /* Enable sys bus clock divider when IDLE state or no bus
activity. */
au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
break;
diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c
index 9dadc82536f4..1e59433dfd66 100644
--- a/arch/mips/au1000/xxs1500/board_setup.c
+++ b/arch/mips/au1000/xxs1500/board_setup.c
@@ -49,7 +49,7 @@ void board_reset (void)
void __init board_setup(void)
{
u32 pin_func;
-
+
// set multiple use pins (UART3/GPIO) to UART (it's used as UART too)
pin_func = au_readl(SYS_PINFUNC) & (u32)(~SYS_PF_UR3);
pin_func |= SYS_PF_UR3;
@@ -75,11 +75,11 @@ void __init board_setup(void)
au_writel(1, GPIO2_ENABLE);
/* gpio2 208/9/10/11 are inputs */
au_writel((1<<8) | (1<<9) | (1<<10) | (1<<11), GPIO2_DIR);
-
+
/* turn off power */
au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), GPIO2_OUTPUT);
#endif
-
+
#ifdef CONFIG_PCI
#if defined(__MIPSEB__)
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c
index 03f755291b51..f1c76533b6fc 100644
--- a/arch/mips/au1000/xxs1500/init.c
+++ b/arch/mips/au1000/xxs1500/init.c
@@ -55,7 +55,7 @@ void __init prom_init(void)
prom_envp = (char **) fw_arg2;
mips_machgroup = MACH_GROUP_ALCHEMY;
- mips_machtype = MACH_XXS1500; /* set the platform # */
+ mips_machtype = MACH_XXS1500; /* set the platform # */
prom_init_cmdline();
diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
index 954800a0ab52..52f2f7daeb05 100644
--- a/arch/mips/au1000/xxs1500/irqmap.c
+++ b/arch/mips/au1000/xxs1500/irqmap.c
@@ -56,7 +56,7 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index caad7ca27abd..3120a02b8670 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:00 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -88,6 +88,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_MIPS_BONITO64=y
CONFIG_MIPS_MSC=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 1b7f8a702d06..158e7165f4e3 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:00 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -97,6 +97,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 8861854561e5..4302c6f914f5 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:00 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -82,6 +82,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_I8259=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 19cac1bf4f01..962fc14b58c2 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:01 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -104,6 +104,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 035ac95d197e..6a528d479d70 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:01 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -104,6 +104,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index c38c4ed18fe7..fed6f2fab48b 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:01 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index ee81309ae3a5..178c0ad1af75 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:02 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index d43ed57c4b4e..70addc73f699 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:02 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -82,6 +82,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_I8259=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 5a032cdefd63..60292808b384 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:02 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -83,6 +83,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_I8259=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 32ada79da9d8..66ec1f41d122 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:03 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -88,6 +88,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_EARLY_PRINTK=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 52074a2085fb..ba2ec01defb1 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:03 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -96,6 +96,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index 360e842fd4be..17e87f70f602 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:03 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -89,6 +89,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_MIPS_GT64120=y
# CONFIG_SYSCLK_75 is not set
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index 657a9508d31a..9da4140eae00 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:03 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -88,6 +88,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_MIPS_GT64120=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 3fb102e6a7f7..17fa5c4e3ad1 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:04 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -90,6 +90,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_SWAP_IO_SPACE=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index b5bab3a42fc4..b2a67da1e031 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -4,7 +4,7 @@
# Wed Jan 26 02:49:04 2005
#
CONFIG_MIPS=y
-CONFIG_MIPS64=y
+CONFIG_64BIT=y
CONFIG_64BIT=y
#
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index bdf1415475ff..b26e1173365d 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -4,7 +4,7 @@
# Wed Jan 26 02:49:04 2005
#
CONFIG_MIPS=y
-CONFIG_MIPS64=y
+CONFIG_64BIT=y
CONFIG_64BIT=y
#
@@ -84,6 +84,7 @@ CONFIG_ARC=y
CONFIG_DMA_IP32=y
CONFIG_OWN_DMA=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_ARC32=y
CONFIG_BOOT_ELF32=y
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index 1ca7746388f0..08bd3ad64761 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:05 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -90,6 +90,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_ITE_BOARD_GEN=y
CONFIG_IT8172_CIR=y
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index c6eef708be1e..583ef5c5b1cd 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:05 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -89,6 +89,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_ITE_BOARD_GEN=y
CONFIG_IT8172_CIR=y
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 757c4e88cc00..8abb5a0c6c12 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:05 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -81,6 +81,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_LIMITED_DMA=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index e5a613906554..da5d9ee2ecce 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:06 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -82,6 +82,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_MIPS_TX3927=y
CONFIG_SWAP_IO_SPACE=y
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 1e7697834e90..8d600ae890f4 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:06 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -92,6 +92,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_MIPS_NILE4=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MIPS_GT64120=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 61fb9fb97e6e..79519ac5af4a 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:53:14 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -88,6 +88,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_I8259=y
CONFIG_MIPS_BONITO64=y
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 31b8f2ad7338..0fea57ef18f2 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:07 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -97,6 +97,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 2cce682fffcf..b4cf97a732bc 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:07 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -89,6 +89,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_IRQ_CPU_RM7K=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index 0cbf48a62e02..a38903db85a0 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -4,7 +4,7 @@
# Wed Jan 26 02:49:07 2005
#
CONFIG_MIPS=y
-CONFIG_MIPS64=y
+CONFIG_64BIT=y
CONFIG_64BIT=y
#
@@ -80,6 +80,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_IRQ_MV64340=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 4043950d360a..920d59b56a4e 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:08 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -82,6 +82,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_IRQ_CPU_RM7K=y
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index 3870af4537ad..ef5ea50893d1 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -4,7 +4,7 @@
# Wed Jan 26 02:49:08 2005
#
CONFIG_MIPS=y
-CONFIG_MIPS64=y
+CONFIG_64BIT=y
CONFIG_64BIT=y
#
@@ -80,6 +80,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_IRQ_CPU_RM7K=y
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 6cdabd550300..813e3a8b480b 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:08 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -104,6 +104,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SWAP_IO_SPACE=y
# CONFIG_AU1X00_USB_DEVICE is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 2aebbd2e82b3..49e528340a39 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:09 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 9e21edc28280..8e426776c098 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:09 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/configs/osprey_defconfig b/arch/mips/configs/qemu_defconfig
index 989cb9e7ae83..b6568e421b99 100644
--- a/arch/mips/configs/osprey_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,108 +1,133 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:08 2005
+# Linux kernel version: 2.6.13-rc6
+# Mon Aug 8 11:49:54 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
-# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
#
# Code maturity level options
#
-CONFIG_EXPERIMENTAL=y
+# CONFIG_EXPERIMENTAL is not set
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SHMEM=y
+# 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_TINY_SHMEM is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
#
# 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
+# CONFIG_MODULES is not set
#
# Machine selection
#
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# 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_LASAT 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_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE 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_NEC_OSPREY=y
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+CONFIG_QEMU=y
# CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 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_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
+CONFIG_DMA_COHERENT=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_VR4181=y
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
#
# CPU selection
#
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# 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_VR41XX is not set
# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
+CONFIG_CPU_R4X00=y
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
@@ -113,17 +138,36 @@ CONFIG_CPU_VR41XX=y
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+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_64BIT_PHYS_ADDR is not set
# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
+CONFIG_ISA=y
CONFIG_MMU=y
#
@@ -132,10 +176,6 @@ CONFIG_MMU=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
@@ -147,6 +187,56 @@ CONFIG_BINFMT_ELF=y
CONFIG_TRAD_SIGNALS=y
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_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=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER 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_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -154,7 +244,7 @@ CONFIG_TRAD_SIGNALS=y
# Generic Driver Options
#
CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
#
@@ -170,6 +260,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNP is not set
#
# Block devices
@@ -181,19 +272,16 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_BLK_DEV_RAM is not set
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# 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
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -206,6 +294,11 @@ CONFIG_ATA_OVER_ETH=m
# CONFIG_SCSI 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
@@ -213,6 +306,7 @@ CONFIG_ATA_OVER_ETH=m
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -223,84 +317,41 @@ CONFIG_ATA_OVER_ETH=m
#
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
+# Network device support
#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# 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_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_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=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
-
-#
-# 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_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
-# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=y
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
@@ -313,6 +364,7 @@ CONFIG_NET_ETHERNET=y
#
# Token Ring devices
#
+# CONFIG_TR is not set
#
# Wireless LAN (non-hamradio)
@@ -325,8 +377,8 @@ CONFIG_NET_ETHERNET=y
# 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
@@ -346,28 +398,13 @@ 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
# 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 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -377,6 +414,12 @@ CONFIG_SERIO_RAW=m
# 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
@@ -397,9 +440,8 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
#
# IPMI
@@ -418,13 +460,17 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
#
# Dallas's 1-wire bus
@@ -432,6 +478,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_W1 is not set
#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
+#
# Misc devices
#
@@ -453,9 +504,9 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Console display driver support
#
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -469,10 +520,6 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -488,19 +535,28 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_INFINIBAND is not set
#
+# SN Devices
+#
+
+#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS 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_FS_POSIX_ACL is not set
+
+#
+# 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_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -520,12 +576,8 @@ CONFIG_DNOTIFY=y
#
# Pseudo filesystems
#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_PROC_FS is not set
+# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -533,13 +585,7 @@ 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
@@ -551,23 +597,18 @@ CONFIG_RAMFS=y
# 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_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-CONFIG_EXPORTFS=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
#
# Partition Types
@@ -581,22 +622,18 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0"
+CONFIG_CMDLINE="console=ttyS0 debug ip=172.20.0.2:172.20.0.1::255.255.0.0"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -612,7 +649,7 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-CONFIG_LIBCRC32C=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index d0c85a4009d6..17d4fce6c4c6 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:09 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -91,6 +91,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_I8259=y
CONFIG_CPU_LITTLE_ENDIAN=y
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 84978b70714b..1dc935f37582 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:10 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 7c718a429b04..dd07e866b128 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:10 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -80,6 +80,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_BOARDS_GEN=y
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index e01727cd0fe9..c9d3f83caf0f 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:12 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -95,6 +95,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index c6ba3de27614..2cb669188aa9 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:12 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -98,6 +98,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644
index 000000000000..17b9f2f65ba0
--- /dev/null
+++ b/arch/mips/configs/tb0287_defconfig
@@ -0,0 +1,1041 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-mm1
+# Thu Sep 1 22:58:34 2005
+#
+CONFIG_MIPS=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_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_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=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_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
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD 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_TOSHIBA_JMR3927 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_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 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_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 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_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_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=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_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+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_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
+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_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_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_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
+# 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 is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_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_LBD is not set
+# 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=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
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ARCMSR 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_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 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_QLA24XX 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
+
+#
+# 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
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=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_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 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_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
+
+#
+# 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_RTC_VR41XX 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
+
+#
+# I2C support
+#
+# CONFIG_I2C 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 Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP 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=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_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
+#
+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
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# 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_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_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_GOTEMP 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
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM 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_REISER4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# 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
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ASFS_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
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+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_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
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 915c43b6e2d9..16e07fca446f 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:12 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -96,6 +96,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 562f2b8043ac..6d2290777ad7 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:49:13 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 5f027bfa4af8..9ffe1a9142ca 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -76,7 +76,7 @@ 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);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
void __init arch_init_irq(void)
@@ -94,7 +94,7 @@ void __init arch_init_irq(void)
/* setup PCI interrupt attributes */
set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
- if (mips_machtype == MACH_NEC_ROCKHOPPERII)
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII)
set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE);
else
set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
@@ -134,7 +134,7 @@ 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);
+ setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
/* hook up the first-level interrupt handler */
set_except_vector(0, ddb5477_handle_int);
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
index 15c6e543b56f..d62f5a789b05 100644
--- a/arch/mips/ddb5xxx/ddb5477/setup.c
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -141,7 +141,7 @@ static void __init ddb_time_init(void)
/* mips_hpt_frequency is 1/2 of the cpu core freq */
i = (read_c0_config() >> 28 ) & 7;
- if ((current_cpu_data.cputype == CPU_R5432) && (i == 3))
+ if ((current_cpu_data.cputype == CPU_R5432) && (i == 3))
i = 4;
mips_hpt_frequency = bus_frequency*(i+4)/4;
}
@@ -298,11 +298,11 @@ static void __init ddb5477_board_init(void)
if (mips_machtype == MACH_NEC_ROCKHOPPER
|| mips_machtype == MACH_NEC_ROCKHOPPERII) {
- /* Disable bus diagnostics. */
+ /* Disable bus diagnostics. */
ddb_out32(DDB_PCICTL0_L, 0);
ddb_out32(DDB_PCICTL0_H, 0);
ddb_out32(DDB_PCICTL1_L, 0);
- ddb_out32(DDB_PCICTL1_H, 0);
+ ddb_out32(DDB_PCICTL1_H, 0);
}
if (mips_machtype == MACH_NEC_ROCKHOPPER) {
@@ -354,7 +354,7 @@ static void __init ddb5477_board_init(void)
*/
pci_write_config_byte(&dev_m1533, 0x58, 0x74);
- /*
+ /*
* positive decode (bit6 -0)
* enable IDE controler interrupt (bit 4 -1)
* setup SIRQ to point to IRQ 14 (bit 3:0 - 1101)
@@ -364,31 +364,31 @@ static void __init ddb5477_board_init(void)
/* Setup M5229 registers */
dev_m5229.bus = &bus;
dev_m5229.sysdata = NULL;
- dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE
+ dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE
/*
* enable IDE in the M5229 config register 0x50 (bit 0 - 1)
- * M5229 IDSEL is addr:15; see above setting
+ * M5229 IDSEL is addr:15; see above setting
*/
pci_read_config_byte(&dev_m5229, 0x50, &temp8);
pci_write_config_byte(&dev_m5229, 0x50, temp8 | 0x1);
- /*
- * enable bus master (bit 2) and IO decoding (bit 0)
+ /*
+ * enable bus master (bit 2) and IO decoding (bit 0)
*/
pci_read_config_byte(&dev_m5229, 0x04, &temp8);
pci_write_config_byte(&dev_m5229, 0x04, temp8 | 0x5);
/*
* enable native, copied from arch/ppc/k2boot/head.S
- * TODO - need volatile, need to be portable
+ * TODO - need volatile, need to be portable
*/
pci_write_config_byte(&dev_m5229, 0x09, 0xef);
- /* Set Primary Channel Command Block Timing */
+ /* Set Primary Channel Command Block Timing */
pci_write_config_byte(&dev_m5229, 0x59, 0x31);
- /*
+ /*
* Enable primary channel 40-pin cable
* M5229 register 0x4a (bit 0)
*/
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 133fb7c48e6c..6dbce92eb068 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -253,7 +253,7 @@ static inline void dec_kn03_be_init(void)
kn0x_erraddr = (void *)(KN03_SLOT_BASE + IOASIC_ERRADDR);
kn0x_chksyn = (void *)(KN03_SLOT_BASE + IOASIC_CHKSYN);
-
+
/*
* Set normal ECC detection and generation, enable ECC correction.
* For KN05 we also need to make sure EE (?) is enabled in the MB.
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 3b3790993219..c89768d5c4e5 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -133,7 +133,7 @@
*/
mfc0 t0,CP0_CAUSE # get pending interrupts
mfc0 t1,CP0_STATUS
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
lw t2,cpu_fpu_mask
#endif
andi t0,ST0_IM # CAUSE.CE may be non-zero!
@@ -141,7 +141,7 @@
beqz t0,spurious
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
and t2,t0
bnez t2,fpu # handle FPU immediately
#endif
@@ -271,7 +271,7 @@ handle_it:
j ret_from_irq
nop
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
fpu:
j handle_fpe_int
nop
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
index 373822ec2d8c..bcd0247b3a66 100644
--- a/arch/mips/dec/prom/Makefile
+++ b/arch/mips/dec/prom/Makefile
@@ -5,7 +5,7 @@
lib-y += init.o memory.o cmdline.o identify.o console.o
-lib-$(CONFIG_MIPS32) += locore.o
-lib-$(CONFIG_MIPS64) += call_o32.o
+lib-$(CONFIG_32BIT) += locore.o
+lib-$(CONFIG_64BIT) += call_o32.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index d55fe665926f..20f84b119b4c 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -4,9 +4,9 @@
# Wed Jan 26 02:48:59 2005
#
CONFIG_MIPS=y
-# CONFIG_MIPS64 is not set
# CONFIG_64BIT is not set
-CONFIG_MIPS32=y
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
#
# Code maturity level options
@@ -90,6 +90,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_IRQ_CPU=y
CONFIG_SWAP_IO_SPACE=y
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
index d808a67294b8..a5f6d84bc181 100644
--- a/arch/mips/ite-boards/generic/it8172_setup.c
+++ b/arch/mips/ite-boards/generic/it8172_setup.c
@@ -129,7 +129,7 @@ static void __init it8172_setup(void)
/*
* IO/MEM resources.
- *
+ *
* revisit this area.
*/
set_io_port_base(KSEG1);
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
index 30a6c0d5fc50..f5d67ee21ac6 100644
--- a/arch/mips/ite-boards/generic/time.c
+++ b/arch/mips/ite-boards/generic/time.c
@@ -72,7 +72,7 @@ static inline int rtc_dm_binary(void) { return saved_control & RTC_DM_BINARY; }
static inline unsigned char
bin_to_hw(unsigned char c)
{
- if (rtc_dm_binary())
+ if (rtc_dm_binary())
return c;
else
return ((c/10) << 4) + (c%10);
@@ -91,9 +91,9 @@ hw_to_bin(unsigned char c)
static inline unsigned char
hour_bin_to_hw(unsigned char c)
{
- if (rtc_24h())
+ if (rtc_24h())
return bin_to_hw(c);
- if (c >= 12)
+ if (c >= 12)
return 0x80 | bin_to_hw((c==12)?12:c-12); /* 12 is 12pm */
else
return bin_to_hw((c==0)?12:c); /* 0 is 12 AM, not 0 am */
@@ -105,9 +105,9 @@ hour_hw_to_bin(unsigned char c)
unsigned char tmp = hw_to_bin(c&0x3f);
if (rtc_24h())
return tmp;
- if (c & 0x80)
+ if (c & 0x80)
return (tmp==12)?12:tmp+12; /* 12pm is 12, not 24 */
- else
+ else
return (tmp==12)?0:tmp; /* 12am is 0 */
}
@@ -145,7 +145,7 @@ static unsigned long __init cal_r4koff(void)
return (mips_hpt_frequency / HZ);
}
-static unsigned long
+static unsigned long
it8172_rtc_get_time(void)
{
unsigned int year, mon, day, hour, min, sec;
@@ -166,12 +166,12 @@ it8172_rtc_get_time(void)
hour = hour_hw_to_bin(CMOS_READ(RTC_HOURS));
day = hw_to_bin(CMOS_READ(RTC_DAY_OF_MONTH));
mon = hw_to_bin(CMOS_READ(RTC_MONTH));
- year = hw_to_bin(CMOS_READ(RTC_YEAR)) +
+ year = hw_to_bin(CMOS_READ(RTC_YEAR)) +
hw_to_bin(*rtc_century_reg) * 100;
/* restore interrupts */
local_irq_restore(flags);
-
+
return mktime(year, mon, day, hour, min, sec);
}
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index a0230ee0f7f4..d3303584fbd1 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -13,8 +13,8 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
ifdef CONFIG_MODULES
obj-y += mips_ksyms.o module.o
-obj-$(CONFIG_MIPS32) += module-elf32.o
-obj-$(CONFIG_MIPS64) += module-elf64.o
+obj-$(CONFIG_32BIT) += module-elf32.o
+obj-$(CONFIG_64BIT) += module-elf64.o
endif
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
@@ -45,8 +45,8 @@ obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
obj-$(CONFIG_IRQ_MV64340) += irq-mv6434x.o
-obj-$(CONFIG_MIPS32) += scall32-o32.o
-obj-$(CONFIG_MIPS64) += scall64-64.o
+obj-$(CONFIG_32BIT) += scall32-o32.o
+obj-$(CONFIG_64BIT) += scall64-64.o
obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o
obj-$(CONFIG_MIPS32_COMPAT) += ioctl32.o linux32.o signal32.o
obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
@@ -55,7 +55,7 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o
obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o
obj-$(CONFIG_PROC_FS) += proc.o
-obj-$(CONFIG_MIPS64) += cpu-bugs64.o
+obj-$(CONFIG_64BIT) += cpu-bugs64.o
obj-$(CONFIG_GEN_RTC) += genrtc.o
diff --git a/arch/mips/kernel/offset.c b/arch/mips/kernel/asm-offsets.c
index 2c11abb5a406..2c11abb5a406 100644
--- a/arch/mips/kernel/offset.c
+++ b/arch/mips/kernel/asm-offsets.c
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index ed47041f3030..6b645fbb1ddc 100644
--- a/arch/mips/kernel/binfmt_elfn32.c
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -103,7 +103,7 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
* Convert jiffies to nanoseconds and seperate with
* one divide.
*/
- u64 nsec = (u64)jiffies * TICK_NSEC;
+ u64 nsec = (u64)jiffies * TICK_NSEC;
value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
value->tv_usec /= NSEC_PER_USEC;
}
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index ee21b18c37a8..b4075e99c452 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -105,7 +105,7 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
* Convert jiffies to nanoseconds and seperate with
* one divide.
*/
- u64 nsec = (u64)jiffies * TICK_NSEC;
+ u64 nsec = (u64)jiffies * TICK_NSEC;
value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
value->tv_usec /= NSEC_PER_USEC;
}
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 11ebe5d4c446..47a087b6c11b 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -137,7 +137,7 @@ static inline void check_mult_sh(void)
for (i = 0; i < 8; i++)
if (v1[i] != w[i])
bug = 1;
-
+
if (bug == 0) {
printk("no.\n");
return;
@@ -149,7 +149,7 @@ static inline void check_mult_sh(void)
for (i = 0; i < 8; i++)
if (v2[i] != w[i])
fix = 0;
-
+
if (fix == 1) {
printk("yes.\n");
return;
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 4bb849582314..7685f8baf3f0 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -229,15 +229,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
break;
case PRID_IMP_VR41XX:
switch (c->processor_id & 0xf0) {
-#ifndef CONFIG_VR4181
case PRID_REV_VR4111:
c->cputype = CPU_VR4111;
break;
-#else
- case PRID_REV_VR4181:
- c->cputype = CPU_VR4181;
- break;
-#endif
case PRID_REV_VR4121:
c->cputype = CPU_VR4121;
break;
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index ece6ddaf7011..512bedbfa7b9 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -13,13 +13,13 @@
#include <asm/stackframe.h>
#include <asm/gdb-stub.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define DMFC0 mfc0
#define DMTC0 mtc0
#define LDC1 lwc1
#define SDC1 lwc1
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define DMFC0 dmfc0
#define DMTC0 dmtc0
#define LDC1 ldc1
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index 269889302a27..d3fd1ab14274 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -687,8 +687,8 @@ void handle_exception (struct gdb_regs *regs)
* acquire the big kgdb spinlock
*/
if (!spin_trylock(&kgdb_lock)) {
- /*
- * some other CPU has the lock, we should go back to
+ /*
+ * some other CPU has the lock, we should go back to
* receive the gdb_wait IPC
*/
return;
@@ -703,7 +703,7 @@ void handle_exception (struct gdb_regs *regs)
async_bp.addr = 0;
}
- /*
+ /*
* acquire the CPU spinlocks
*/
for (i = num_online_cpus()-1; i >= 0; i--)
@@ -894,7 +894,7 @@ void handle_exception (struct gdb_regs *regs)
ptr = &input_buffer[1];
if (hexToLong(&ptr, &addr))
regs->cp0_epc = addr;
-
+
goto exit_kgdb_exception;
break;
@@ -1001,7 +1001,7 @@ void breakpoint(void)
return;
__asm__ __volatile__(
- ".globl breakinst\n\t"
+ ".globl breakinst\n\t"
".set\tnoreorder\n\t"
"nop\n"
"breakinst:\tbreak\n\t"
@@ -1014,7 +1014,7 @@ void breakpoint(void)
void async_breakpoint(void)
{
__asm__ __volatile__(
- ".globl async_breakinst\n\t"
+ ".globl async_breakinst\n\t"
".set\tnoreorder\n\t"
"nop\n"
"async_breakinst:\tbreak\n\t"
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index a5b0a389b063..e7f6c1b90806 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -54,7 +54,7 @@ NESTED(except_vec3_generic, 0, sp)
#endif
mfc0 k1, CP0_CAUSE
andi k1, k1, 0x7c
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
dsll k1, k1, 1
#endif
PTR_L k0, exception_handlers(k1)
@@ -81,7 +81,7 @@ NESTED(except_vec3_r4000, 0, sp)
beq k1, k0, handle_vced
li k0, 14<<2
beq k1, k0, handle_vcei
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
dsll k1, k1, 1
#endif
.set pop
@@ -244,12 +244,12 @@ NESTED(nmi_handler, PT_SIZE, sp)
start with an n and gas will believe \n is ok ... */
.macro __BUILD_verbose nexception
LONG_L a1, PT_EPC(sp)
-#if CONFIG_MIPS32
+#ifdef CONFIG_32BIT
PRINT("Got \nexception at %08lx\012")
-#endif
-#if CONFIG_MIPS64
+#endif
+#ifdef CONFIG_64BIT
PRINT("Got \nexception at %016lx\012")
-#endif
+#endif
.endm
.macro __BUILD_count exception
@@ -293,7 +293,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
BUILD_HANDLER reserved reserved sti verbose /* others */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/* A temporary overflow handler used by check_daddi(). */
__INIT
diff --git a/arch/mips/kernel/genrtc.c b/arch/mips/kernel/genrtc.c
index 288bf51ad4ec..71416e7bbbaa 100644
--- a/arch/mips/kernel/genrtc.c
+++ b/arch/mips/kernel/genrtc.c
@@ -14,7 +14,7 @@
#include <asm/rtc.h>
#include <asm/time.h>
-static spinlock_t mips_rtc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mips_rtc_lock);
unsigned int get_rtc_time(struct rtc_time *time)
{
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index a64e87d22014..2a1b45d66f04 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -107,7 +107,7 @@
.endm
.macro setup_c0_status_pri
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
setup_c0_status ST0_KX 0
#else
setup_c0_status 0 0
@@ -115,7 +115,7 @@
.endm
.macro setup_c0_status_sec
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
setup_c0_status ST0_KX ST0_BEV
#else
setup_c0_status 0 ST0_BEV
@@ -215,7 +215,7 @@ NESTED(smp_bootstrap, 16, sp)
* slightly different layout ...
*/
page swapper_pg_dir, _PGD_ORDER
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
page invalid_pmd_table, _PMD_ORDER
#endif
page invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 7eec7568bfea..447759201d1d 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -31,7 +31,7 @@ void disable_8259A_irq(unsigned int irq);
* moves to arch independent land
*/
-spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t DEFINE_SPINLOCK(i8259A_lock);
static void end_8259A_irq (unsigned int irq)
{
diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c
index 519cd5d0aebb..c069719ff0d8 100644
--- a/arch/mips/kernel/ioctl32.c
+++ b/arch/mips/kernel/ioctl32.c
@@ -27,7 +27,7 @@ long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
#include "compat_ioctl.c"
typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
-
+
#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL },
#define IOCTL_TABLE_START \
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
index 4cd3d38a22c2..3cdc22346f4c 100644
--- a/arch/mips/kernel/irixioctl.c
+++ b/arch/mips/kernel/irixioctl.c
@@ -14,6 +14,7 @@
#include <linux/syscalls.h>
#include <linux/tty.h>
#include <linux/file.h>
+#include <linux/rcupdate.h>
#include <asm/uaccess.h>
#include <asm/ioctl.h>
@@ -33,7 +34,7 @@ static struct tty_struct *get_tty(int fd)
struct file *filp;
struct tty_struct *ttyp = NULL;
- spin_lock(&current->files->file_lock);
+ rcu_read_lock();
filp = fcheck(fd);
if(filp && filp->private_data) {
ttyp = (struct tty_struct *) filp->private_data;
@@ -41,7 +42,7 @@ static struct tty_struct *get_tty(int fd)
if(ttyp->magic != TTY_MAGIC)
ttyp =NULL;
}
- spin_unlock(&current->files->file_lock);
+ rcu_read_unlock();
return ttyp;
}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 40244782a8e5..eff89322ba50 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -155,13 +155,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
else
setup_irix_frame(ka, regs, sig, oldset);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
@@ -441,18 +440,6 @@ struct irix5_siginfo {
} stuff;
};
-static inline unsigned long timespectojiffies(struct timespec *value)
-{
- unsigned long sec = (unsigned) value->tv_sec;
- long nsec = value->tv_nsec;
-
- if (sec > (LONG_MAX / HZ))
- return LONG_MAX;
- nsec += 1000000000L / HZ - 1;
- nsec /= 1000000000L / HZ;
- return HZ * sec + nsec;
-}
-
asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
struct timespec *tp)
{
@@ -490,14 +477,13 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
error = -EINVAL;
goto out;
}
- expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec);
+ expire = timespec_to_jiffies(tp) + (tp->tv_sec||tp->tv_nsec);
}
while(1) {
long tmp = 0;
- current->state = TASK_INTERRUPTIBLE;
- expire = schedule_timeout(expire);
+ expire = schedule_timeout_interruptible(expire);
for (i=0; i<=4; i++)
tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 441157a1f994..7d93992e462c 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -77,7 +77,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
- if (!action)
+ if (!action)
goto skip;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 993abc868e54..ece4564919d8 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -313,7 +313,7 @@ asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
struct sysinfo s;
int ret, err;
mm_segment_t old_fs = get_fs ();
-
+
set_fs (KERNEL_DS);
ret = sys_sysinfo(&s);
set_fs (old_fs);
@@ -546,21 +546,21 @@ struct msgbuf32 { s32 mtype; char mtext[1]; };
struct ipc_perm32
{
key_t key;
- compat_uid_t uid;
- compat_gid_t gid;
- compat_uid_t cuid;
- compat_gid_t cgid;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
+ __compat_uid_t cuid;
+ __compat_gid_t cgid;
compat_mode_t mode;
unsigned short seq;
};
struct ipc64_perm32 {
key_t key;
- compat_uid_t uid;
- compat_gid_t gid;
- compat_uid_t cuid;
- compat_gid_t cgid;
- compat_mode_t mode;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
+ __compat_uid_t cuid;
+ __compat_gid_t cgid;
+ compat_mode_t mode;
unsigned short seq;
unsigned short __pad1;
unsigned int __unused1;
@@ -1334,17 +1334,17 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset,
mm_segment_t old_fs = get_fs();
int ret;
off_t of;
-
+
if (offset && get_user(of, offset))
return -EFAULT;
-
+
set_fs(KERNEL_DS);
ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
set_fs(old_fs);
-
+
if (offset && put_user(of, offset))
return -EFAULT;
-
+
return ret;
}
@@ -1362,11 +1362,11 @@ static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
#undef AL
/*
- * System call vectors.
+ * System call vectors.
*
* Argument checking cleaned up. Saved 20% in size.
* This function doesn't need to set the kernel lock because
- * it is set by the callees.
+ * it is set by the callees.
*/
asmlinkage long sys32_socketcall(int call, unsigned int *args32)
@@ -1402,11 +1402,11 @@ asmlinkage long sys32_socketcall(int call, unsigned int *args32)
/* copy_from_user should be SMP safe. */
if (copy_from_user(a, args32, socketcall_nargs[call]))
return -EFAULT;
-
+
a0=a[0];
a1=a[1];
-
- switch(call)
+
+ switch(call)
{
case SYS_SOCKET:
err = sys_socket(a0,a1,a[2]);
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index eed29fc9dc82..86e42c633f73 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strchr);
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
EXPORT_SYMBOL(strncmp);
#endif
EXPORT_SYMBOL(strlen);
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6e70c42c2058..e4f2f8011387 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -70,7 +70,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
/* New thread loses kernel privileges. */
status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|KU_MASK);
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
status &= ~ST0_FR;
status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR;
#endif
@@ -236,10 +236,10 @@ static int __init get_frame_info(struct mips_frame_info *info, void *func)
break;
if (
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
ip->i_format.opcode == sw_op &&
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
ip->i_format.opcode == sd_op &&
#endif
ip->i_format.rs == 29)
@@ -353,7 +353,7 @@ schedule_timeout_caller:
out:
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
if (current->thread.mflags & MF_32BIT_REGS) /* Kludge for 32-bit ps */
pc &= 0xffffffffUL;
#endif
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 92e70ca3bff9..0b571a5b4b83 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -124,7 +124,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (tsk_used_math(child)) {
fpureg_t *fregs = get_fpu_regs(child);
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
/*
* The odd registers are actually the high
* order bits of the values stored in the even
@@ -135,7 +135,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else
tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
tmp = fregs[addr - FPR_BASE];
#endif
} else {
@@ -213,7 +213,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
sizeof(child->thread.fpu.hard));
child->thread.fpu.hard.fcr31 = 0;
}
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
/*
* The odd registers are actually the high order bits
* of the values stored in the even registers - unless
@@ -227,7 +227,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
fregs[addr - FPR_BASE] |= data;
}
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
fregs[addr - FPR_BASE] = data;
#endif
break;
@@ -304,14 +304,14 @@ out:
static inline int audit_arch(void)
{
#ifdef CONFIG_CPU_LITTLE_ENDIAN
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
if (!(current->thread.mflags & MF_32BIT_REGS))
return AUDIT_ARCH_MIPSEL64;
#endif /* MIPS64 */
return AUDIT_ARCH_MIPSEL;
#else /* big endian... */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
if (!(current->thread.mflags & MF_32BIT_REGS))
return AUDIT_ARCH_MIPS64;
#endif /* MIPS64 */
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index f83c31f720c4..ac68e68339db 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -15,7 +15,7 @@
#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(a,b) \
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 243e7b629af6..0d9c4a32a9c2 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -15,7 +15,7 @@
#include <asm/cachectl.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
@@ -35,7 +35,7 @@
/*
* FPU context is saved iff the process has used it's FPU in the current
* time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
+ * space STATUS register should be 0, so that a process *always* starts its
* userland with FPU disabled after each context switch.
*
* FPU will be enabled as soon as the process accesses FPU again, through
@@ -55,7 +55,7 @@ LEAF(resume)
cpu_save_nonscratch a0
sw ra, THREAD_REG31(a0)
- /*
+ /*
* check if we need to save FPU registers
*/
lw t3, TASK_THREAD_INFO(a0)
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index ebb643d8d14c..1a14c6b18829 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -17,7 +17,7 @@
#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
.macro EX insn, reg, src
@@ -36,7 +36,7 @@
LEAF(_save_fp_context)
cfc1 t1, fcr31
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/* Store the 16 odd double precision registers */
EX sdc1 $f1, SC_FPREGS+8(a0)
EX sdc1 $f3, SC_FPREGS+24(a0)
@@ -118,7 +118,7 @@ LEAF(_save_fp_context32)
*/
LEAF(_restore_fp_context)
EX lw t0, SC_FPC_CSR(a0)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
EX ldc1 $f1, SC_FPREGS+8(a0)
EX ldc1 $f3, SC_FPREGS+24(a0)
EX ldc1 $f5, SC_FPREGS+40(a0)
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 1fc3b2eb12bd..d2afbd19a9c8 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -15,7 +15,7 @@
#include <asm/cachectl.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/pgtable-bits.h>
#include <asm/regdef.h>
@@ -33,7 +33,7 @@
/*
* FPU context is saved iff the process has used it's FPU in the current
* time slice as indicated by _TIF_USEDFPU. In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
+ * space STATUS register should be 0, so that a process *always* starts its
* userland with FPU disabled after each context switch.
*
* FPU will be enabled as soon as the process accesses FPU again, through
@@ -105,7 +105,7 @@
* Save a thread's fp context.
*/
LEAF(_save_fp)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
mfc0 t1, CP0_STATUS
#endif
fpu_save_double a0 t1 t0 t2 # clobbers t1
@@ -142,7 +142,7 @@ LEAF(_init_fpu)
li t1, -1 # SNaN
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
sll t0, t0, 5
bgez t0, 1f # 16 / 32 register mode?
@@ -164,7 +164,7 @@ LEAF(_init_fpu)
dmtc1 t1, $f31
1:
#endif
-
+
#ifdef CONFIG_CPU_MIPS32
mtc1 t1, $f0
mtc1 t1, $f1
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
index d8d3b13fe57f..43cda53f5af6 100644
--- a/arch/mips/kernel/r6000_fpu.S
+++ b/arch/mips/kernel/r6000_fpu.S
@@ -13,7 +13,7 @@
#include <asm/asm.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
.set noreorder
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 344f2e29eb61..17b5030fb6ea 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -19,7 +19,7 @@
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <asm/war.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
/* Highest syscall used of any syscall flavour */
#define MAX_SYSCALL_NO __NR_O32_Linux + __NR_O32_Linux_syscalls
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 32efb888160a..ffb22a2068bf 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -14,7 +14,7 @@
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/sysmips.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 3a240e3e004c..12b531c295c4 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -241,7 +241,7 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
if (*tmp)
strcat(command_line, tmp);
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/* HACK: Guess if the sign extension was forgotten */
if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
start |= 0xffffffff00000000;
@@ -446,7 +446,7 @@ static inline void resource_init(void)
{
int i;
-#if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
/*
* The 64bit code in 32bit object format trick can't represent
* 64bit wide relocations for linker script symbols.
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 65ee15396ffd..0209c1dd1429 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -425,13 +425,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
setup_frame(ka, regs, sig, oldset);
#endif
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index c1a69cf232f9..8ddfbd8d425a 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -558,7 +558,7 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
if (!used_math())
goto out;
- /*
+ /*
* Save FPU state to signal context. Signal handler will "inherit"
* current FPU state.
*/
@@ -751,13 +751,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
else
setup_frame(ka, regs, sig, oldset);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
int do_signal32(sigset_t *oldset, struct pt_regs *regs)
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index ae2a1312d4ef..21e3e13a4b44 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -31,7 +31,7 @@
#include <asm/cachectl.h>
#include <asm/cacheflush.h>
#include <asm/ipc.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/signal.h>
#include <asm/sim.h>
#include <asm/shmparam.h>
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index f3bf0e43b8bb..4de155699c4f 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -632,10 +632,7 @@ asmlinkage int irix_stime(int value)
write_seqlock_irq(&xtime_lock);
xtime.tv_sec = value;
xtime.tv_nsec = 0;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
return 0;
@@ -1035,8 +1032,7 @@ bad:
asmlinkage int irix_sginap(int ticks)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(ticks);
+ schedule_timeout_interruptible(ticks);
return 0;
}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 648c82292ed6..0dd0df7a3b04 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -223,10 +223,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -442,7 +439,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* called as close as possible to 500 ms before the new second starts.
*/
write_seqlock(&xtime_lock);
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 56c36e42e0a6..a53b1ed7b386 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -924,7 +924,7 @@ void __init per_cpu_trap_init(void)
* flag that some firmware may have left set and the TS bit (for
* IP27). Set XX for ISA IV code to work.
*/
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
#endif
if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 3f24a1d45865..36c5212e0928 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -240,7 +240,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
break;
case lwu_op:
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* A 32-bit kernel might be running on a 64-bit processor. But
* if we're on a 32-bit processor and an i-cache incoherency
@@ -278,13 +278,13 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
*newvalue = value;
*regptr = &regs->regs[insn.i_format.rt];
break;
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/* Cannot handle 64-bit instructions in 32-bit kernel */
goto sigill;
case ld_op:
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* A 32-bit kernel might be running on a 64-bit processor. But
* if we're on a 32-bit processor and an i-cache incoherency
@@ -320,7 +320,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
*newvalue = value;
*regptr = &regs->regs[insn.i_format.rt];
break;
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/* Cannot handle 64-bit instructions in 32-bit kernel */
goto sigill;
@@ -392,7 +392,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
break;
case sd_op:
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* A 32-bit kernel might be running on a 64-bit processor. But
* if we're on a 32-bit processor and an i-cache incoherency
@@ -428,7 +428,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
if (res)
goto fault;
break;
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/* Cannot handle 64-bit instructions in 32-bit kernel */
goto sigill;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index e830d788c106..482ac310c937 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -15,7 +15,7 @@ SECTIONS
/* This is the value for an Origin kernel, taken from an IRIX kernel. */
/* . = 0xc00000000001c000; */
- /* Set the vaddr for the text segment to a value
+ /* Set the vaddr for the text segment to a value
>= 0xa800 0000 0001 9000 if no symmon is going to configured
>= 0xa800 0000 0030 0000 otherwise */
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
index f6add041ebec..ca26e554615e 100644
--- a/arch/mips/lasat/at93c.c
+++ b/arch/mips/lasat/at93c.c
@@ -1,7 +1,7 @@
-/*
+/*
* Atmel AT93C46 serial eeprom driver
*
- * Brian Murphy <brian.murphy@eicon.com>
+ * Brian Murphy <brian.murphy@eicon.com>
*
*/
#include <linux/kernel.h>
@@ -21,12 +21,12 @@
struct at93c_defs *at93c;
-static void at93c_reg_write(u32 val)
+static void at93c_reg_write(u32 val)
{
*at93c->reg = val;
}
-static u32 at93c_reg_read(void)
+static u32 at93c_reg_read(void)
{
u32 tmp = *at93c->reg;
return tmp;
@@ -81,7 +81,7 @@ static u8 at93c_read_byte(void)
}
static void at93c_write_bits(u32 data, int size)
-{
+{
int i;
int shift = size - 1;
u32 mask = (1 << shift);
@@ -90,7 +90,7 @@ static void at93c_write_bits(u32 data, int size)
at93c_write_databit((data & mask) >> shift);
data <<= 1;
}
-}
+}
static void at93c_init_op(void)
{
@@ -104,8 +104,8 @@ static void at93c_end_op(void)
lasat_ndelay(250);
}
-static void at93c_wait(void)
-{
+static void at93c_wait(void)
+{
at93c_init_op();
while (!at93c_read_databit())
;
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
index a912ac2171b0..cfe2f99b1d44 100644
--- a/arch/mips/lasat/at93c.h
+++ b/arch/mips/lasat/at93c.h
@@ -1,7 +1,7 @@
-/*
+/*
* Atmel AT93C46 serial eeprom driver
*
- * Brian Murphy <brian.murphy@eicon.com>
+ * Brian Murphy <brian.murphy@eicon.com>
*
*/
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
index 7bbf6cf923c9..9d7812e03dcd 100644
--- a/arch/mips/lasat/ds1603.c
+++ b/arch/mips/lasat/ds1603.c
@@ -1,7 +1,7 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
+/*
+ * Dallas Semiconductors 1603 RTC driver
*
- * Brian Murphy <brian@murphy.dk>
+ * Brian Murphy <brian@murphy.dk>
*
*/
#include <linux/kernel.h>
@@ -20,12 +20,12 @@
struct ds_defs *ds1603 = NULL;
/* HW specific register functions */
-static void rtc_reg_write(unsigned long val)
+static void rtc_reg_write(unsigned long val)
{
*ds1603->reg = val;
}
-static unsigned long rtc_reg_read(void)
+static unsigned long rtc_reg_read(void)
{
unsigned long tmp = *ds1603->reg;
return tmp;
@@ -80,7 +80,7 @@ static unsigned int rtc_read_databit(void)
{
unsigned int data;
- data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
+ data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
>> ds1603->data_read_shift;
rtc_cycle_clock(rtc_reg_read());
return data;
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
index 55f3b0423c20..c2e5c76a379d 100644
--- a/arch/mips/lasat/ds1603.h
+++ b/arch/mips/lasat/ds1603.h
@@ -1,7 +1,7 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
+/*
+ * Dallas Semiconductors 1603 RTC driver
*
- * Brian Murphy <brian@murphy.dk>
+ * Brian Murphy <brian@murphy.dk>
*
*/
#ifndef __DS1603_H
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
index 18b6430f11be..35ecd6483ef6 100644
--- a/arch/mips/lasat/image/Makefile
+++ b/arch/mips/lasat/image/Makefile
@@ -21,7 +21,7 @@ LDSCRIPT= -L$(obj) -Tromscript.normal
HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
-D_kernel_entry=0x$(KERNEL_ENTRY) \
-D VERSION="\"$(Version)\"" \
- -D TIMESTAMP=$(shell date +%s)
+ -D TIMESTAMP=$(shell date +%s)
$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
$(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
index 426bd7de17bb..efb95f2609c2 100644
--- a/arch/mips/lasat/image/head.S
+++ b/arch/mips/lasat/image/head.S
@@ -27,5 +27,5 @@ reldate:
.word TIMESTAMP
.org 0x50
-release:
+release:
.string VERSION
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 1148a2d20aa7..c90da1639440 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
- * Routines for generic manipulation of the interrupts found on the
+ * Routines for generic manipulation of the interrupts found on the
* Lasat boards.
*/
#include <linux/init.h>
@@ -101,7 +101,7 @@ static unsigned long get_int_status_100(void)
return *lasat_int_status & *lasat_int_mask;
}
-static unsigned long get_int_status_200(void)
+static unsigned long get_int_status_200(void)
{
unsigned long int_status;
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
index 8c784bcf1111..fc9b0e2a6be1 100644
--- a/arch/mips/lasat/lasat_board.c
+++ b/arch/mips/lasat/lasat_board.c
@@ -67,7 +67,7 @@ static void init_flash_sizes(void)
if (mips_machtype == MACH_LASAT_100) {
lasat_board_info.li_flash_base = 0x1e000000;
-
+
lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
if (lasat_board_info.li_flash_size > 0x200000) {
@@ -103,7 +103,7 @@ int lasat_init_board_info(void)
memset(&lasat_board_info, 0, sizeof(lasat_board_info));
/* First read the EEPROM info */
- EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
+ EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
sizeof(struct lasat_eeprom_struct));
/* Check the CRC */
@@ -188,7 +188,7 @@ int lasat_init_board_info(void)
case 0x1:
lasat_board_info.li_cpu_hz =
lasat_board_info.li_bus_hz +
- (lasat_board_info.li_bus_hz >> 1);
+ (lasat_board_info.li_bus_hz >> 1);
break;
case 0x2:
lasat_board_info.li_cpu_hz =
@@ -271,7 +271,7 @@ void lasat_write_eeprom_info(void)
lasat_board_info.li_eeprom_info.crc32 = crc;
/* Write the EEPROM info */
- EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
+ EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
sizeof(struct lasat_eeprom_struct));
}
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
index 5637cd153926..9ae82c3ffb07 100644
--- a/arch/mips/lasat/picvue.c
+++ b/arch/mips/lasat/picvue.c
@@ -1,7 +1,7 @@
-/*
+/*
* Picvue PVC160206 display driver
*
- * Brian Murphy <brian@murphy.dk>
+ * Brian Murphy <brian@murphy.dk>
*
*/
#include <linux/kernel.h>
@@ -24,12 +24,12 @@ struct pvc_defs *picvue = NULL;
DECLARE_MUTEX(pvc_sem);
-static void pvc_reg_write(u32 val)
+static void pvc_reg_write(u32 val)
{
*picvue->reg = val;
}
-static u32 pvc_reg_read(void)
+static u32 pvc_reg_read(void)
{
u32 tmp = *picvue->reg;
return tmp;
@@ -65,12 +65,12 @@ static u8 pvc_read_data(void)
{
u32 data = pvc_reg_read();
u8 byte;
- data |= picvue->rw;
+ data |= picvue->rw;
data &= ~picvue->rs;
pvc_reg_write(data);
ndelay(40);
byte = pvc_read_byte(data);
- data |= picvue->rs;
+ data |= picvue->rs;
pvc_reg_write(data);
return byte;
}
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
index 74a39039135d..2a96bf971897 100644
--- a/arch/mips/lasat/picvue.h
+++ b/arch/mips/lasat/picvue.h
@@ -1,7 +1,7 @@
-/*
+/*
* Picvue PVC160206 display driver
*
- * Brian Murphy <brian.murphy@eicon.com>
+ * Brian Murphy <brian.murphy@eicon.com>
*
*/
#include <asm/semaphore.h>
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index eaa2b4625124..cce7cddcdb08 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -1,7 +1,7 @@
-/*
+/*
* Picvue PVC160206 display driver
*
- * Brian Murphy <brian.murphy@eicon.com>
+ * Brian Murphy <brian.murphy@eicon.com>
*
*/
#include <linux/kernel.h>
@@ -51,10 +51,10 @@ static int pvc_proc_read_line(char *page, char **start,
page += sprintf(page, "%s\n", pvc_lines[lineno]);
up(&pvc_sem);
- return page - origpage;
+ return page - origpage;
}
-static int pvc_proc_write_line(struct file *file, const char *buffer,
+static int pvc_proc_write_line(struct file *file, const char *buffer,
unsigned long count, void *data)
{
int origcount = count;
@@ -119,7 +119,7 @@ static int pvc_proc_read_scroll(char *page, char **start,
page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
up(&pvc_sem);
- return page - origpage;
+ return page - origpage;
}
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
index ca62881c9e52..88c7ab871ec4 100644
--- a/arch/mips/lasat/prom.c
+++ b/arch/mips/lasat/prom.c
@@ -42,7 +42,7 @@ static void null_prom_putc(char c)
/* these are functions provided by the bootloader */
static void (* prom_putc)(char c) = null_prom_putc;
void (* prom_printf)(const char * fmt, ...) = null_prom_printf;
-void (* prom_display)(const char *string, int pos, int clear) =
+void (* prom_display)(const char *string, int pos, int clear) =
null_prom_display;
void (* prom_monitor)(void) = null_prom_monitor;
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
index 37e4912ee1c8..8d7d7a454f9a 100644
--- a/arch/mips/lasat/reset.c
+++ b/arch/mips/lasat/reset.c
@@ -1,4 +1,4 @@
-/*
+/*
* Thomas Horsten <thh@lasat.com>
* Copyright (C) 2000 LASAT Networks A/S.
*
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index e371ed5cbe34..f2604fab9a99 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -105,7 +105,7 @@ static int lasat_panic_prom_monitor(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block lasat_panic_block[] =
+static struct notifier_block lasat_panic_block[] =
{
{ lasat_panic_display, NULL, INT_MAX },
{ lasat_panic_prom_monitor, NULL, INT_MIN }
@@ -120,7 +120,7 @@ static void lasat_timer_setup(struct irqaction *irq)
{
write_c0_compare(
- read_c0_count() +
+ read_c0_count() +
mips_hpt_frequency / HZ);
change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 1c0cc620a43f..8ff43a1c1e99 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -37,14 +37,14 @@
static DECLARE_MUTEX(lasat_info_sem);
-/* Strategy function to write EEPROM after changing string entry */
+/* Strategy function to write EEPROM after changing string entry */
int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
void *newval, size_t newlen, void **context)
{
int r;
down(&lasat_info_sem);
- r = sysctl_string(table, name,
+ r = sysctl_string(table, name,
nlen, oldval, oldlenp, newval, newlen, context);
if (r < 0) {
up(&lasat_info_sem);
@@ -74,7 +74,7 @@ int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
return 0;
}
-/* proc function to write EEPROM after changing int entry */
+/* proc function to write EEPROM after changing int entry */
int proc_dolasatint(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -93,7 +93,7 @@ int proc_dolasatint(ctl_table *table, int write, struct file *filp,
static int rtctmp;
#ifdef CONFIG_DS1603
-/* proc function to read/write RealTime Clock */
+/* proc function to read/write RealTime Clock */
int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -165,9 +165,9 @@ static char lasat_bcastaddr[16];
void update_bcastaddr(void)
{
unsigned int ip;
-
- ip = (lasat_board_info.li_eeprom_info.ipaddr &
- lasat_board_info.li_eeprom_info.netmask) |
+
+ ip = (lasat_board_info.li_eeprom_info.ipaddr &
+ lasat_board_info.li_eeprom_info.netmask) |
~lasat_board_info.li_eeprom_info.netmask;
sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
@@ -205,7 +205,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
break;
len++;
}
- if (len >= sizeof(proc_lasat_ipbuf)-1)
+ if (len >= sizeof(proc_lasat_ipbuf)-1)
len = sizeof(proc_lasat_ipbuf) - 1;
if (copy_from_user(proc_lasat_ipbuf, buffer, len))
{
@@ -249,8 +249,8 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
}
#endif /* defined(CONFIG_INET) */
-static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
+static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
void *newval, size_t newlen,
void **context)
{
@@ -293,7 +293,7 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
if (!strcmp(filp->f_dentry->d_name.name, "debugaccess"))
lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
}
- lasat_write_eeprom_info();
+ lasat_write_eeprom_info();
up(&lasat_info_sem);
return 0;
}
@@ -316,8 +316,8 @@ static ctl_table lasat_table[] = {
0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
{LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int),
0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
- {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
- sizeof(lasat_bcastaddr), 0600, NULL,
+ {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
+ sizeof(lasat_bcastaddr), 0600, NULL,
&proc_dostring, &sysctl_string},
#endif
{LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
index fd6a2bafdfcf..ad285786e74b 100644
--- a/arch/mips/lib-32/Makefile
+++ b/arch/mips/lib-32/Makefile
@@ -2,7 +2,7 @@
# Makefile for MIPS-specific library files..
#
-lib-y += csum_partial.o memset.o watch.o
+lib-y += csum_partial.o memset.o watch.o
obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
diff --git a/arch/mips/lib-32/memset.S b/arch/mips/lib-32/memset.S
index ad9ff4071ce9..1981485bd48b 100644
--- a/arch/mips/lib-32/memset.S
+++ b/arch/mips/lib-32/memset.S
@@ -7,7 +7,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(insn,reg,addr,handler) \
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
index fd6a2bafdfcf..ad285786e74b 100644
--- a/arch/mips/lib-64/Makefile
+++ b/arch/mips/lib-64/Makefile
@@ -2,7 +2,7 @@
# Makefile for MIPS-specific library files..
#
-lib-y += csum_partial.o memset.o watch.o
+lib-y += csum_partial.o memset.o watch.o
obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
diff --git a/arch/mips/lib-64/memset.S b/arch/mips/lib-64/memset.S
index 242f1976cfaf..e2c42c85113b 100644
--- a/arch/mips/lib-64/memset.S
+++ b/arch/mips/lib-64/memset.S
@@ -7,7 +7,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(insn,reg,addr,handler) \
diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c
index e44e9579bd36..fd82c84a93b7 100644
--- a/arch/mips/lib/dec_and_lock.c
+++ b/arch/mips/lib/dec_and_lock.c
@@ -20,14 +20,7 @@
* has a cmpxchg, and where atomic->value is an int holding
* the value of the atomic (i.e. the high bits aren't used
* for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
*/
-
-#ifndef ATOMIC_DEC_AND_LOCK
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
int counter;
@@ -52,4 +45,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index afa8eae18ff6..a78865f76547 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -14,7 +14,7 @@
*/
#include <linux/config.h>
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define dst a0
@@ -79,7 +79,7 @@
/*
* Only on the 64-bit kernel we can made use of 64-bit registers.
*/
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define USE_DOUBLE
#endif
@@ -101,7 +101,7 @@
#define NBYTES 8
#define LOG_NBYTES 3
-/*
+/*
* As we are sharing code base with the mips32 tree (which use the o32 ABI
* register definitions). We need to redefine the register definitions from
* the n64 ABI register naming to the o32 ABI register naming.
@@ -118,7 +118,7 @@
#define t5 $13
#define t6 $14
#define t7 $15
-
+
#else
#define LOAD lw
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S
index 07660e86c99d..eca558d83a37 100644
--- a/arch/mips/lib/strlen_user.S
+++ b/arch/mips/lib/strlen_user.S
@@ -7,7 +7,7 @@
* Copyright (c) 1999 Silicon Graphics, Inc.
*/
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(insn,reg,addr,handler) \
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index 14bed17c1648..d16c76fbfac7 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -7,7 +7,7 @@
*/
#include <linux/errno.h>
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(insn,reg,addr,handler) \
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S
index 6e7a8eed4de8..c0ea15194a0e 100644
--- a/arch/mips/lib/strnlen_user.S
+++ b/arch/mips/lib/strnlen_user.S
@@ -7,7 +7,7 @@
* Copyright (c) 1999 Silicon Graphics, Inc.
*/
#include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define EX(insn,reg,addr,handler) \
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 20a552be02ee..99c550632d44 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -320,7 +320,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
case cop1_op:
switch (MIPSInst_RS(ir)) {
-#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
case dmfc_op:
/* copregister fs -> gpr[rt] */
if (MIPSInst_RT(ir) != 0) {
@@ -805,7 +805,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
ieee754dp d;
ieee754sp s;
int w;
-#if __mips64
+#ifdef __mips64
s64 l;
#endif
} rv; /* resulting value */
@@ -950,7 +950,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
}
#endif /* __mips >= 2 */
-#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
case fcvtl_op:{
ieee754sp fs;
@@ -1125,7 +1125,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
}
#endif
-#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
case fcvtl_op:{
ieee754dp fs;
@@ -1203,7 +1203,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
break;
}
-#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
case l_fmt:{
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
@@ -1267,7 +1267,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
case w_fmt:
SITOREG(rv.w, MIPSInst_FD(ir));
break;
-#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
case l_fmt:
DITOREG(rv.l, MIPSInst_FD(ir));
break;
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index 04397fec30fc..4002f0cf79f3 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -86,7 +86,7 @@ int fpu_emulator_restore_context(struct sigcontext *sc)
return err;
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* This is the o32 version
*/
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index 8f1d875217a2..19d4b0792460 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -122,7 +122,7 @@ void __init arch_init_irq(void)
int i;
atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
-
+
/*
* Mask out all interrupt by writing "1" to all bit position in
* the interrupt reset reg.
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index 31caf0603a3f..311155d1d3ed 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -200,7 +200,7 @@ void __init kgdb_config (void)
generic_putDebugChar = saa9730_putDebugChar;
generic_getDebugChar = saa9730_getDebugChar;
}
- else
+ else
#endif
{
speed = rs_kgdb_hook(line, speed);
@@ -243,7 +243,7 @@ void __init prom_init(void)
mips_revision_corid = MIPS_REVISION_CORID;
if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
- if (BONITO_PCIDID == 0x0001df53 ||
+ if (BONITO_PCIDID == 0x0001df53 ||
BONITO_PCIDID == 0x0003df53)
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
else
@@ -310,7 +310,7 @@ void __init prom_init(void)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
- _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
+ _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
#ifdef CONFIG_CPU_LITTLE_ENDIAN
MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index fe7fc17305a6..16315444dd5a 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -89,7 +89,7 @@ static unsigned int __init estimate_cpu_frequency(void)
* really calculate the timer frequency
* For now we hardwire the SEAD board frequency to 12MHz.
*/
-
+
if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
(prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
count = 12000000;
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 3377e66de9eb..df6db6419ae9 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -149,15 +149,15 @@ static int __init malta_setup(void)
argptr = prom_getcmdline();
if (strstr(argptr, "iobcuncached")) {
BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
- BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
printk("Disabled Bonito IOBC coherency\n");
}
else {
BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
- BONITO_PCIMEMBASECFG |=
- (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG |=
+ (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
printk("Disabled Bonito IOBC coherency\n");
}
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index f61e038b4440..b56a0abdc3d4 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -5,8 +5,8 @@
obj-y += cache.o extable.o fault.o init.o pgtable.o \
tlbex.o tlbex-fault.o
-obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o
-obj-$(CONFIG_MIPS64) += pgtable-64.o
+obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
+obj-$(CONFIG_64BIT) += pgtable-64.o
obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index a03ebb2cba67..5ea84bc98c6a 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -126,13 +126,13 @@ static inline void tx49_blast_icache32(void)
CACHE32_UNROLL32_ALIGN2;
/* I'm in even chunk. blast odd chunks */
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
cache32_unroll32(addr|ws,Index_Invalidate_I);
CACHE32_UNROLL32_ALIGN;
/* I'm in odd chunk. blast even chunks */
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400 * 2)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400 * 2)
cache32_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -156,13 +156,13 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page)
CACHE32_UNROLL32_ALIGN2;
/* I'm in even chunk. blast odd chunks */
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
cache32_unroll32(addr|ws,Index_Invalidate_I);
CACHE32_UNROLL32_ALIGN;
/* I'm in odd chunk. blast even chunks */
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400 * 2)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400 * 2)
cache32_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -723,10 +723,10 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
".set push\n\t"
".set noat\n\t"
".set mips3\n\t"
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
"la $at,1f\n\t"
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
"dla $at,1f\n\t"
#endif
"cache %0,($at)\n\t"
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index ab30afd63b32..502f68c664b2 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -270,7 +270,7 @@ static void local_sb1_flush_icache_range(unsigned long start,
__sb1_writeback_inv_dcache_all();
else
__sb1_writeback_inv_dcache_range(start, end);
-
+
/* Just flush the whole icache if the range is big enough */
if ((end - start) > icache_range_cutoff)
__sb1_flush_icache_all();
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index 13d96d62764e..7166ffe63502 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -25,7 +25,7 @@
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_scd.h>
#endif
-
+
/* SB1 definitions */
/* XXX should come from config1 XXX */
@@ -136,14 +136,14 @@ static inline void breakout_cerrd(unsigned int val)
#ifndef CONFIG_SIBYTE_BUS_WATCHER
-static void check_bus_watcher(void)
-{
+static void check_bus_watcher(void)
+{
uint32_t status, l2_err, memio_err;
/* Destructive read, clears register and interrupt */
status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
/* Bit 31 is always on, but there's no #define for that */
- if (status & ~(1UL << 31)) {
+ if (status & ~(1UL << 31)) {
l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
@@ -153,14 +153,14 @@ static void check_bus_watcher(void)
(int)(G_SCD_BERR_TID(status) >> 6),
(int)G_SCD_BERR_RID(status),
(int)G_SCD_BERR_DCODE(status));
- } else {
- prom_printf("Bus watcher indicates no error\n");
- }
-}
-#else
-extern void check_bus_watcher(void);
-#endif
-
+ } else {
+ prom_printf("Bus watcher indicates no error\n");
+ }
+}
+#else
+extern void check_bus_watcher(void);
+#endif
+
asmlinkage void sb1_cache_error(void)
{
uint64_t cerr_dpa;
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
index 9895e32b0fce..59e54f12212e 100644
--- a/arch/mips/mm/dma-noncoherent.c
+++ b/arch/mips/mm/dma-noncoherent.c
@@ -162,7 +162,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
unsigned long addr;
-
+
addr = (unsigned long) page_address(sg->page);
if (addr)
__dma_sync(addr + sg->offset, sg->length, direction);
@@ -230,9 +230,9 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
unsigned long addr;
-
+
BUG_ON(direction == DMA_NONE);
-
+
addr = dma_handle + PAGE_OFFSET;
__dma_sync(addr, size, direction);
}
@@ -282,9 +282,9 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
int i;
-
+
BUG_ON(direction == DMA_NONE);
-
+
/* Make sure that gcc doesn't leave the empty loop body. */
for (i = 0; i < nelems; i++, sg++)
__dma_sync((unsigned long)page_address(sg->page),
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 9c9a271c8a3a..dc6830b10fab 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -96,7 +96,7 @@ static void __init kmap_init(void)
kmap_prot = PAGE_KERNEL;
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
@@ -125,7 +125,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
j = 0;
}
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
#endif /* CONFIG_HIGHMEM */
#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -258,7 +258,7 @@ void __init mem_init(void)
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/* Switch from KSEG0 to XKPHYS addresses */
start = (unsigned long)phys_to_virt(CPHYSADDR(start));
end = (unsigned long)phys_to_virt(CPHYSADDR(end));
@@ -286,7 +286,7 @@ void free_initmem(void)
addr = (unsigned long) &__init_begin;
while (addr < (unsigned long) &__init_end) {
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
page = PAGE_OFFSET | CPHYSADDR(addr);
#else
page = addr;
diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c
index 59d131b5e536..1b6df7133c1e 100644
--- a/arch/mips/mm/pg-sb1.c
+++ b/arch/mips/mm/pg-sb1.c
@@ -114,7 +114,7 @@ static inline void copy_page_cpu(void *to, void *from)
" pref " SB1_PREF_STORE_STREAMED_HINT ", -64(%1)\n"
" pref " SB1_PREF_LOAD_STREAMED_HINT ", -32(%0)\n"
"1: pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%1)\n"
-# ifdef CONFIG_MIPS64
+# ifdef CONFIG_64BIT
" ld $8, -128(%0) \n" /* Block copy a cacheline */
" ld $9, -120(%0) \n"
" ld $10, -112(%0) \n"
@@ -148,7 +148,7 @@ static inline void copy_page_cpu(void *to, void *from)
" daddiu %0, %0, -128 \n"
" daddiu %1, %1, -128 \n"
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
" ld $8, 0(%0) \n" /* Block copy a cacheline */
"1: ld $9, 8(%0) \n"
" ld $10, 16(%0) \n"
@@ -178,7 +178,7 @@ static inline void copy_page_cpu(void *to, void *from)
" daddiu %0, %0, 32 \n"
" daddiu %1, %1, 32 \n"
" bnel %0, %2, 1b \n"
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
" ld $8, 0(%0) \n"
#else
" lw $2, 0(%0) \n"
@@ -186,7 +186,7 @@ static inline void copy_page_cpu(void *to, void *from)
" .set pop \n"
: "+r" (src), "+r" (dst)
: "r" (end)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
: "$8","$9","$10","$11","memory");
#else
: "$2","$3","$6","$7","$8","$9","$10","$11","memory");
@@ -198,7 +198,7 @@ static inline void copy_page_cpu(void *to, void *from)
/*
* Pad descriptors to cacheline, since each is exclusively owned by a
- * particular CPU.
+ * particular CPU.
*/
typedef struct dmadscr_s {
u64 dscr_a;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 87e229f4d3d5..6569be3983c7 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -448,7 +448,7 @@ L_LA(_r3000_write_probe_fail)
L_LA(_r3000_write_probe_ok)
/* convenience macros for instructions */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
# define i_LW(buf, rs, rt, off) i_ld(buf, rs, rt, off)
# define i_SW(buf, rs, rt, off) i_sd(buf, rs, rt, off)
# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
@@ -486,7 +486,7 @@ L_LA(_r3000_write_probe_ok)
#define i_ssnop(buf) i_sll(buf, 0, 0, 1)
#define i_ehb(buf) i_sll(buf, 0, 0, 3)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
static __init int __attribute__((unused)) in_compat_space_p(long addr)
{
/* Is this address in 32bit compat space? */
@@ -516,7 +516,7 @@ static __init int rel_lo(long val)
static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr)
{
-#if CONFIG_MIPS64
+#ifdef CONFIG_64BIT
if (!in_compat_space_p(addr)) {
i_lui(buf, rs, rel_highest(addr));
if (rel_higher(addr))
@@ -682,7 +682,7 @@ static void il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
#define C0_EPC 14
#define C0_XCONTEXT 20
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
#else
# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_CONTEXT)
@@ -923,7 +923,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
}
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* TMP and PTR are scratch.
* TMP will be clobbered, PTR will hold the pmd entry.
@@ -1010,7 +1010,7 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r,
}
}
-#else /* !CONFIG_MIPS64 */
+#else /* !CONFIG_64BIT */
/*
* TMP and PTR are scratch.
@@ -1038,7 +1038,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
}
-#endif /* !CONFIG_MIPS64 */
+#endif /* !CONFIG_64BIT */
static __init void build_adjust_context(u32 **p, unsigned int ctx)
{
@@ -1159,7 +1159,7 @@ static void __init build_r4000_tlb_refill_handler(void)
/* No need for i_nop */
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
#else
build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
@@ -1171,7 +1171,7 @@ static void __init build_r4000_tlb_refill_handler(void)
l_leave(&l, p);
i_eret(&p); /* return from trap */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
#endif
@@ -1182,7 +1182,7 @@ static void __init build_r4000_tlb_refill_handler(void)
* need three, with the the second nop'ed and the third being
* unused.
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
if ((p - tlb_handler) > 64)
panic("TLB refill handler space exceeded");
#else
@@ -1195,12 +1195,12 @@ static void __init build_r4000_tlb_refill_handler(void)
/*
* Now fold the handler in the TLB refill handler space.
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
f = final_handler;
/* Simplest case, just copy the handler. */
copy_handler(relocs, labels, tlb_handler, p, f);
final_len = p - tlb_handler;
-#else /* CONFIG_MIPS64 */
+#else /* CONFIG_64BIT */
f = final_handler + 32;
if ((p - tlb_handler) <= 32) {
/* Just copy the handler. */
@@ -1235,7 +1235,7 @@ static void __init build_r4000_tlb_refill_handler(void)
copy_handler(relocs, labels, split, p, final_handler);
final_len = (f - (final_handler + 32)) + (p - split);
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
resolve_relocs(relocs, labels);
printk("Synthesized TLB refill handler (%u instructions).\n",
@@ -1605,7 +1605,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
struct reloc **r, unsigned int pte,
unsigned int ptr)
{
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
#else
build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
@@ -1636,7 +1636,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct label **l,
l_leave(l, *p);
i_eret(p); /* return from trap */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
build_get_pgd_vmalloc64(p, l, r, tmp, ptr);
#endif
}
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
index 43fd5a58077c..55bc789733f2 100644
--- a/arch/mips/momentum/jaguar_atx/int-handler.S
+++ b/arch/mips/momentum/jaguar_atx/int-handler.S
@@ -27,11 +27,11 @@
SAVE_ALL
CLI
.set at
- mfc0 t0, CP0_CAUSE
+ 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 */
@@ -103,25 +103,25 @@ ll_pcia_irq:
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
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
index fa5982ac0ac6..14ae2e713585 100644
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ b/arch/mips/momentum/jaguar_atx/prom.c
@@ -64,7 +64,7 @@ static u8 exchange_bit(u8 val, u8 cs)
/* turn the clock off and read-strobe */
JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
+
/* return the data */
return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
}
@@ -90,7 +90,7 @@ void get_mac(char dest[6])
}
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
unsigned long signext(unsigned long addr)
{
@@ -143,7 +143,7 @@ char *arg64(unsigned long addrin, int arg_index)
return p;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/* PMON passes arguments in C main() style */
void __init prom_init(void)
@@ -158,7 +158,7 @@ void __init prom_init(void)
// ja_setup_console(); /* The very first thing. */
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
char *ptr;
printk("Mips64 Jaguar-ATX\n");
@@ -201,7 +201,7 @@ void __init prom_init(void)
}
printk("arcs_cmdline: %s\n", arcs_cmdline);
-#else /* CONFIG_MIPS64 */
+#else /* CONFIG_64BIT */
/* save the PROM vectors for debugging use */
debug_vectors = cv;
@@ -226,7 +226,7 @@ void __init prom_init(void)
}
env++;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
mips_machgroup = MACH_GROUP_MOMENCO;
mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c
index 48039484cdf9..c4236b1e59fa 100644
--- a/arch/mips/momentum/jaguar_atx/reset.c
+++ b/arch/mips/momentum/jaguar_atx/reset.c
@@ -27,7 +27,7 @@
void momenco_jaguar_restart(char *command)
{
/* base address of timekeeper portion of part */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
void *nvram = (void*) 0xfffffffffc807000;
#else
void *nvram = (void*) 0xfc807000;
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 30462e715066..90288cf2b1e0 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -105,7 +105,7 @@ void __init bus_error_init(void) { /* nothing */ }
static __init void wire_stupidity_into_tlb(void)
{
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
write_c0_wired(0);
local_flush_tlb_all();
@@ -451,7 +451,7 @@ static int __init momenco_jaguar_atx_setup(void)
#ifdef GEMDEBUG_TRACEBUFFER
{
unsigned int tbControl;
- tbControl =
+ tbControl =
0 << 26 | /* post trigger delay 0 */
0x2 << 16 | /* sequential trace mode */
// 0x0 << 16 | /* non-sequential trace mode */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
index 89c17a0c0bed..c4fa9c525faa 100644
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ b/arch/mips/momentum/ocelot_3/prom.c
@@ -93,7 +93,7 @@ void get_mac(char dest[6])
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
unsigned long signext(unsigned long addr)
{
@@ -145,7 +145,7 @@ char *arg64(unsigned long addrin, int arg_index)
return p;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
void __init prom_init(void)
{
@@ -155,7 +155,7 @@ void __init prom_init(void)
struct callvectors *cv = (struct callvectors *) fw_arg3;
int i;
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
char *ptr;
printk("prom_init - MIPS64\n");
@@ -198,7 +198,7 @@ void __init prom_init(void)
}
printk("arcs_cmdline: %s\n", arcs_cmdline);
-#else /* CONFIG_MIPS64 */
+#else /* CONFIG_64BIT */
/* save the PROM vectors for debugging use */
debug_vectors = cv;
@@ -224,7 +224,7 @@ void __init prom_init(void)
}
env++;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
mips_machgroup = MACH_GROUP_MOMENCO;
mips_machtype = MACH_MOMENCO_OCELOT_3;
@@ -234,7 +234,7 @@ void __init prom_init(void)
get_mac(prom_mac_addr_base);
#endif
-#ifndef CONFIG_MIPS64
+#ifndef CONFIG_64BIT
debug_vectors->printf("Booting Linux kernel...\n");
#endif
}
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
index 2f2430648abc..52349d9bf1be 100644
--- a/arch/mips/momentum/ocelot_c/int-handler.S
+++ b/arch/mips/momentum/ocelot_c/int-handler.S
@@ -27,11 +27,11 @@
SAVE_ALL
CLI
.set at
- mfc0 t0, CP0_CAUSE
+ 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 */
@@ -83,7 +83,7 @@ ll_pmc_irq:
move a1, sp
jal do_IRQ
j ret_from_irq
-
+
ll_cpci_decode_irq:
move a0, sp
jal ll_cpci_irq
@@ -99,4 +99,4 @@ ll_cputimer_irq:
move a1, sp
jal do_IRQ
j ret_from_irq
-
+
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
index a6cf7a7959b3..97fb77dad723 100644
--- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
+++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
@@ -32,7 +32,7 @@
#include <linux/config.h>
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define OCELOT_C_CS0_ADDR (0xfffffffffc000000)
#else
#define OCELOT_C_CS0_ADDR (0xfc000000)
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
index 49ac302d8901..5b6809724b15 100644
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ b/arch/mips/momentum/ocelot_c/prom.c
@@ -67,7 +67,7 @@ static u8 exchange_bit(u8 val, u8 cs)
/* turn the clock off and read-strobe */
OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
+
/* return the data */
return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
}
@@ -94,7 +94,7 @@ void get_mac(char dest[6])
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
unsigned long signext(unsigned long addr)
{
@@ -144,7 +144,7 @@ char *arg64(unsigned long addrin, int arg_index)
p = (char *)get_arg(args, arg_index);
return p;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
void __init prom_init(void)
@@ -155,7 +155,7 @@ void __init prom_init(void)
struct callvectors *cv = (struct callvectors *) fw_arg3;
int i;
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
char *ptr;
printk("prom_init - MIPS64\n");
@@ -197,7 +197,7 @@ void __init prom_init(void)
}
printk("arcs_cmdline: %s\n", arcs_cmdline);
-#else /* CONFIG_MIPS64 */
+#else /* CONFIG_64BIT */
/* save the PROM vectors for debugging use */
debug_vectors = cv;
@@ -222,7 +222,7 @@ void __init prom_init(void)
}
env++;
}
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
mips_machgroup = MACH_GROUP_MOMENCO;
mips_machtype = MACH_MOMENCO_OCELOT_C;
@@ -232,7 +232,7 @@ void __init prom_init(void)
get_mac(prom_mac_addr_base);
#endif
-#ifndef CONFIG_MIPS64
+#ifndef CONFIG_64BIT
debug_vectors->printf("Booting Linux kernel...\n");
#endif
}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
index 1f2b4263cc8c..6a2489f3b9a0 100644
--- a/arch/mips/momentum/ocelot_c/reset.c
+++ b/arch/mips/momentum/ocelot_c/reset.c
@@ -28,7 +28,7 @@ void momenco_ocelot_restart(char *command)
{
/* base address of timekeeper portion of part */
void *nvram = (void *)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
0xfffffffffc807000;
#else
0xfc807000;
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index 021c00e3c07c..844ddd06349b 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -109,7 +109,7 @@ void PMON_v2_setup(void)
*/
printk("PMON_v2_setup\n");
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/* marvell and extra space */
add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
/* fpga, rtc, and uart */
@@ -134,7 +134,7 @@ void PMON_v2_setup(void)
unsigned long m48t37y_get_time(void)
{
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
#else
unsigned char* rtc_base = (unsigned char*)0xfc800000;
@@ -163,7 +163,7 @@ unsigned long m48t37y_get_time(void)
int m48t37y_set_time(unsigned long sec)
{
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
#else
unsigned char* rtc_base = (unsigned char*)0xfc800000;
@@ -342,7 +342,7 @@ static void __init momenco_ocelot_c_setup(void)
early_initcall(momenco_ocelot_c_setup);
-#ifndef CONFIG_MIPS64
+#ifndef CONFIG_64BIT
/* This needs to be one of the first initcalls, because no I/O port access
can work before this */
static int io_base_ioremap(void)
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index c53e4cb359ba..83d81c9cdc2b 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o pci-jmr3927.o
obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o
obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
index b345e528a53c..5a4a7c239c42 100644
--- a/arch/mips/pci/fixup-ddb5074.c
+++ b/arch/mips/pci/fixup-ddb5074.c
@@ -5,7 +5,7 @@ static void ddb5074_fixup(struct pci_dev *dev)
{
extern struct pci_dev *pci_pmu;
u8 t8;
-
+
pci_pmu = dev; /* for LEDs D2 and D3 */
/* Program the lines for LEDs D2 and D3 to output */
pci_read_config_byte(dev, 0x7d, &t8);
diff --git a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c
index 6abdc88bab1e..2f1444e60654 100644
--- a/arch/mips/pci/fixup-ddb5477.c
+++ b/arch/mips/pci/fixup-ddb5477.c
@@ -65,7 +65,7 @@ static void ddb5477_amd_lance_fixup(struct pci_dev *dev)
ioaddr = pci_resource_start(dev, 0);
inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */
-
+
/* bcr_18 |= 0x0800 */
outw(18, ioaddr + PCNET32_WIO_RAP);
temp = inw(ioaddr + PCNET32_WIO_BDP);
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index b9296d9942b3..bf2c41d1e9c5 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -56,7 +56,7 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
0, 0, 0, 3,
4, 5, 6, 7,
0, 9, 10, 11,
- 12, 0, 14, 15
+ 12, 0, 14, 15
};
int i;
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index de4e443da208..ceeb1860895a 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -7,7 +7,7 @@
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
- * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2000-2001 Toshiba Corporation
*
* Copyright (C) 2004 MontaVista Software Inc.
* Author: Manish Lachwani (mlachwani@mvista.com)
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index c8ef01a017cc..a176f2ca8656 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -32,7 +32,7 @@
* Device 4: Unused
* Device 5: Slot 2
* Device 6: Slot 3
- * Device 7: Slot 4
+ * Device 7: Slot 4
*
* Documentation says the VGA is device 5 and device 3 is unused but that
* seem to be a documentation error. At least on my RM200C the Cirrus
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 850a900f0eb4..bc55b06e1904 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -29,27 +29,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
switch (slot) {
case 12:
- vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN,
- TRIGGER_LEVEL,
- SIGNAL_THROUGH);
- vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN,
- LEVEL_LOW);
irq = TB0219_PCI_SLOT1_IRQ;
break;
case 13:
- vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN,
- TRIGGER_LEVEL,
- SIGNAL_THROUGH);
- vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN,
- LEVEL_LOW);
irq = TB0219_PCI_SLOT2_IRQ;
break;
case 14:
- vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN,
- TRIGGER_LEVEL,
- SIGNAL_THROUGH);
- vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN,
- LEVEL_LOW);
irq = TB0219_PCI_SLOT3_IRQ;
break;
default:
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
new file mode 100644
index 000000000000..8436d7f1fdb2
--- /dev/null
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -0,0 +1,65 @@
+/*
+ * fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
+ *
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/tb0287.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ unsigned char bus;
+ int irq = -1;
+
+ bus = dev->bus->number;
+ if (bus == 0) {
+ switch (slot) {
+ case 16:
+ irq = TB0287_SM501_IRQ;
+ break;
+ case 17:
+ irq = TB0287_SIL680A_IRQ;
+ break;
+ default:
+ break;
+ }
+ } else if (bus == 1) {
+ switch (PCI_SLOT(dev->devfn)) {
+ case 0:
+ irq = TB0287_PCI_SLOT_IRQ;
+ break;
+ case 2:
+ case 3:
+ irq = TB0287_RTL8110_IRQ;
+ break;
+ default:
+ break;
+ }
+ } else if (bus > 1) {
+ irq = TB0287_PCI_SLOT_IRQ;
+ }
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c
index e955443fedf9..0406b50a37d8 100644
--- a/arch/mips/pci/ops-ddb5477.c
+++ b/arch/mips/pci/ops-ddb5477.c
@@ -127,7 +127,7 @@ static inline void ddb_close_config_base(struct pci_config_swap *swap)
}
static int read_config_dword(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where,
+ struct pci_bus *bus, u32 devfn, u32 where,
u32 * val)
{
u32 bus_num, slot_num, func_num;
@@ -153,7 +153,7 @@ static int read_config_dword(struct pci_config_swap *swap,
}
static int read_config_word(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where,
+ struct pci_bus *bus, u32 devfn, u32 where,
u16 * val)
{
int status;
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 2a9d7227fe87..7688b7711329 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -1,16 +1,16 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
- * ahennessy@mvista.com
+ * ahennessy@mvista.com
*
- * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2000-2001 Toshiba Corporation
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
*
* Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
*
* Define the pci_ops for the Toshiba rbtx4927
*
- * Much of the code is derived from the original DDB5074 port by
+ * Much of the code is derived from the original DDB5074 port by
* Geert Uytterhoeven <geert@sonycom.com>
*
* Copyright 2004 MontaVista Software Inc.
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index 4ddd53eaf656..826d653184e5 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -76,7 +76,7 @@ struct pci_controller ddb5477_io_controller = {
*/
/*
- * irq mapping : device -> pci int # -> vrc4377 irq# ,
+ * irq mapping : device -> pci int # -> vrc4377 irq# ,
* ddb5477 board manual page 4 and vrc5477 manual page 46
*/
@@ -137,9 +137,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
unsigned char *slot_irq_map;
unsigned char irq;
- /*
+ /*
* We ignore the swizzled slot and pin values. The original
- * pci_fixup_irq() codes largely base irq number on the dev slot
+ * pci_fixup_irq() codes largely base irq number on the dev slot
* numbers because except for one case they are unique even
* though there are multiple pci buses.
*/
@@ -160,7 +160,7 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
/* hack to distinquish overlapping slot 20s, one
- * on bus 0 (ALI USB on the M1535 on the backplane),
+ * on bus 0 (ALI USB on the M1535 on the backplane),
* and one on bus 2 (NEC USB controller on the CPU board)
* Make the M1535 USB - ISA IRQ number 9.
*/
diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c
index 1faeb034f06e..000dc6af6cd3 100644
--- a/arch/mips/pci/pci-ip32.c
+++ b/arch/mips/pci/pci-ip32.c
@@ -84,7 +84,7 @@ static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs)
extern struct pci_ops mace_pci_ops;
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
static struct resource mace_pci_mem_resource = {
.name = "SGI O2 PCI MEM",
.start = MACEPCI_HI_MEMORY,
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 8141dffac241..a8d499b0a36f 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -132,7 +132,7 @@ static int __init pcibios_init(void)
hose->need_domain_info = need_domain_info;
next_busno = bus->subordinate + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
- reserve some space for bridges. */
+ reserve some space for bridges. */
if (next_busno > 224) {
next_busno = 0;
need_domain_info = 1;
@@ -260,7 +260,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus);
- }
+ }
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
struct pci_dev *dev = pci_dev_b(ln);
@@ -292,8 +292,25 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
region->end = res->end - offset;
}
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
#endif
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
index b067988614c3..97862f45496d 100644
--- a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -30,7 +30,7 @@
*
* This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
* 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
- * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
+ * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
* expected to have a connectivity from the EEPROM to the serial port. This program does
* __not__ communicate using the I2C protocol
*/
@@ -64,14 +64,14 @@ static void send_ack(void)
static void send_byte(unsigned char byte)
{
int i = 0;
-
- for (i = 7; i >= 0; i--)
+
+ for (i = 7; i >= 0; i--)
send_bit((byte >> i) & 0x01);
}
-
+
static void send_start(void)
{
- sda_hi;
+ sda_hi;
delay(TXX);
scl_hi;
delay(TXX);
@@ -114,9 +114,9 @@ static unsigned char recv_byte(void) {
int i;
unsigned char byte=0;
- for (i=7;i>=0;i--)
+ for (i=7;i>=0;i--)
byte |= (recv_bit() << i);
-
+
return byte;
}
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
index d27566d99ffc..c19f01a32045 100644
--- a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -27,7 +27,7 @@
*/
/*
- * Header file for atmel_read_eeprom.c
+ * Header file for atmel_read_eeprom.c
*/
#include <linux/types.h>
@@ -46,7 +46,7 @@
#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */
#define TXX 0 /* Dummy loop for spinning */
-#define BLOCK_SEL 0x00
+#define BLOCK_SEL 0x00
#define SLAVE_ADDR 0xa0
#define READ_BIT 0x01
#define WRITE_BIT 0x00
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
new file mode 100644
index 000000000000..934944ab9e85
--- /dev/null
+++ b/arch/mips/qemu/Makefile
@@ -0,0 +1,5 @@
+#
+# 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
diff --git a/arch/mips/qemu/q-firmware.c b/arch/mips/qemu/q-firmware.c
new file mode 100644
index 000000000000..5980f02b2df9
--- /dev/null
+++ b/arch/mips/qemu/q-firmware.c
@@ -0,0 +1,7 @@
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+void __init prom_init(void)
+{
+ add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
new file mode 100644
index 000000000000..6e3dfe5eb14b
--- /dev/null
+++ b/arch/mips/qemu/q-int.S
@@ -0,0 +1,17 @@
+/*
+ * 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
new file mode 100644
index 000000000000..2c4e0704ff10
--- /dev/null
+++ b/arch/mips/qemu/q-irq.c
@@ -0,0 +1,37 @@
+#include <linux/init.h>
+#include <linux/linkage.h>
+
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/qemu.h>
+#include <asm/system.h>
+#include <asm/time.h>
+
+extern asmlinkage void qemu_handle_int(void);
+
+asmlinkage void do_qemu_int(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & 0x8000) {
+ ll_timer_interrupt(Q_COUNT_COMPARE_IRQ, regs);
+ return;
+ }
+ if (pending & 0x0400) {
+ int irq = i8259_irq();
+
+ if (likely(irq >= 0))
+ do_IRQ(irq, regs);
+
+ return;
+ }
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, qemu_handle_int);
+ mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */
+
+ init_i8259_irqs();
+ set_c0_status(0x8400);
+}
diff --git a/arch/mips/qemu/q-mem.c b/arch/mips/qemu/q-mem.c
new file mode 100644
index 000000000000..d174fac43031
--- /dev/null
+++ b/arch/mips/qemu/q-mem.c
@@ -0,0 +1,6 @@
+#include <linux/init.h>
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0UL;
+}
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c
new file mode 100644
index 000000000000..1a80eee8cd35
--- /dev/null
+++ b/arch/mips/qemu/q-setup.c
@@ -0,0 +1,20 @@
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#define QEMU_PORT_BASE 0xb4000000
+
+static void __init qemu_timer_setup(struct irqaction *irq)
+{
+ /* set the clock to 100 Hz */
+ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(LATCH & 0xff , 0x40); /* LSB */
+ outb(LATCH >> 8 , 0x40); /* MSB */
+ setup_irq(0, irq);
+}
+
+void __init plat_setup(void)
+{
+ set_io_port_base(QEMU_PORT_BASE);
+ board_timer_setup = qemu_timer_setup;
+}
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index 0ab4abf65d58..fa0e719c5bd1 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -242,7 +242,7 @@ int __init ip22_eisa_init(void)
int i, c;
char *str;
u8 *slot_addr;
-
+
if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
printk(KERN_INFO "EISA: bus not present.\n");
return 1;
diff --git a/arch/mips/sgi-ip22/ip22-hpc.c b/arch/mips/sgi-ip22/ip22-hpc.c
index c0afeccb08c4..5c00cdd20d8e 100644
--- a/arch/mips/sgi-ip22/ip22-hpc.c
+++ b/arch/mips/sgi-ip22/ip22-hpc.c
@@ -49,7 +49,7 @@ void __init sgihpc_init(void)
sgint = &sgioc->int3;
system_type = "SGI Indy";
}
-
+
sgi_ioc_reset = (SGIOC_RESET_PPORT | SGIOC_RESET_KBDMOUSE |
SGIOC_RESET_EISA | SGIOC_RESET_ISDN |
SGIOC_RESET_LC0OFF);
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index ea2844d29e6e..d16fb43b1a93 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -28,7 +28,7 @@
/* #define DEBUG_SGINT */
/* So far nothing hangs here */
-#undef USE_LIO3_IRQ
+#undef USE_LIO3_IRQ
struct sgint_regs *sgint;
@@ -272,32 +272,32 @@ void indy_buserror_irq(struct pt_regs *regs)
irq_exit();
}
-static struct irqaction local0_cascade = {
+static struct irqaction local0_cascade = {
.handler = no_action,
.flags = SA_INTERRUPT,
.name = "local0 cascade",
};
-static struct irqaction local1_cascade = {
+static struct irqaction local1_cascade = {
.handler = no_action,
.flags = SA_INTERRUPT,
.name = "local1 cascade",
};
-static struct irqaction buserr = {
+static struct irqaction buserr = {
.handler = no_action,
.flags = SA_INTERRUPT,
.name = "Bus Error",
};
-static struct irqaction map0_cascade = {
+static struct irqaction map0_cascade = {
.handler = no_action,
.flags = SA_INTERRUPT,
.name = "mapable0 cascade",
};
#ifdef USE_LIO3_IRQ
-static struct irqaction map1_cascade = {
+static struct irqaction map1_cascade = {
.handler = no_action,
.flags = SA_INTERRUPT,
.name = "mapable1 cascade",
diff --git a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c
index de43e86fa17c..fd29fd407ae8 100644
--- a/arch/mips/sgi-ip22/ip22-nvram.c
+++ b/arch/mips/sgi-ip22/ip22-nvram.c
@@ -39,7 +39,7 @@
*ptr |= EEPROM_CSEL; \
*ptr |= EEPROM_ECLK; })
-
+
#define eeprom_cs_off(ptr) ({ \
*ptr &= ~EEPROM_ECLK; \
*ptr &= ~EEPROM_CSEL; \
@@ -50,7 +50,7 @@
/*
* clock in the nvram command and the register number. For the
* national semiconductor nv ram chip the op code is 3 bits and
- * the address is 6/8 bits.
+ * the address is 6/8 bits.
*/
static inline void eeprom_cmd(volatile unsigned int *ctrl, unsigned cmd,
unsigned reg)
@@ -90,7 +90,7 @@ unsigned short ip22_eeprom_read(volatile unsigned int *ctrl, int reg)
if (*ctrl & EEPROM_DATI)
res |= 1;
}
-
+
eeprom_cs_off(ctrl);
return res;
@@ -113,7 +113,7 @@ unsigned short ip22_nvram_read(int reg)
reg <<= 1;
tmp = hpc3c0->bbram[reg++] & 0xff;
return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff);
- }
+ }
}
EXPORT_SYMBOL(ip22_nvram_read);
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index ed5c60adce63..214ffd2e98a3 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -185,7 +185,7 @@ static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs)
add_timer(&debounce_timer);
}
- /* Power button was pressed
+ /* Power button was pressed
* ioc.ps page 22: "The Panel Register is called Power Control by Full
* House. Only lowest 2 bits are used. Guiness uses upper four bits
* for volume control". This is not true, all bits are pulled high
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 173f76805ea3..df9b5694328a 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -126,7 +126,7 @@ static __init void indy_time_init(void)
unsigned long r4k_ticks[3];
unsigned long r4k_tick;
- /*
+ /*
* Figure out the r4k offset, the algorithm is very simple and works in
* _all_ cases as long as the 8254 counter register itself works ok (as
* an interrupt driving timer it does not because of bug, this is why
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index a160d04f7dbe..ef20d9ac0ba3 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -538,7 +538,7 @@ void __init mem_init(void)
for_each_online_node(node) {
unsigned slot, numslots;
struct page *end, *p;
-
+
/*
* This will free up the bootmem, ie, slot 0 memory.
*/
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 8c1b96fffa76..cddf1cedf007 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -118,7 +118,7 @@ again:
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to when a second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index 281f090e48a4..88e1f52059ff 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -140,7 +140,7 @@ static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs)
reg_c = CMOS_READ(RTC_INTR_FLAGS);
if (!(reg_c & RTC_IRQF)) {
- printk(KERN_WARNING
+ printk(KERN_WARNING
"%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
}
/* Wait until interrupt goes away */
diff --git a/arch/mips/sibyte/cfe/cfe_error.h b/arch/mips/sibyte/cfe/cfe_error.h
index 77eb4935bfb4..975f00002cbe 100644
--- a/arch/mips/sibyte/cfe/cfe_error.h
+++ b/arch/mips/sibyte/cfe/cfe_error.h
@@ -17,15 +17,15 @@
*/
/* *********************************************************************
- *
+ *
* Broadcom Common Firmware Environment (CFE)
- *
+ *
* Error codes File: cfe_error.h
- *
+ *
* CFE's global error code list is here.
- *
+ *
* Author: Mitch Lichtenberg
- *
+ *
********************************************************************* */
diff --git a/arch/mips/sibyte/cfe/console.c b/arch/mips/sibyte/cfe/console.c
index 53a5c1eb5611..7721100d0275 100644
--- a/arch/mips/sibyte/cfe/console.c
+++ b/arch/mips/sibyte/cfe/console.c
@@ -38,7 +38,7 @@ static void cfe_console_write(struct console *cons, const char *str,
last += written;
} while (last < count);
}
-
+
}
static int cfe_console_setup(struct console *cons, char *str)
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index d6d0364fa760..7a2c7a8510d4 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -33,7 +33,7 @@
#include "cfe_error.h"
/* Max ram addressable in 32-bit segments */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define MAX_RAM_SIZE (~0ULL)
#else
#ifdef CONFIG_HIGHMEM
@@ -285,7 +285,7 @@ void __init prom_init(void)
while (1) ;
}
cfe_init(cfe_handle, cfe_ept);
- /*
+ /*
* Get the handle for (at least) prom_putchar, possibly for
* boot console
*/
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
index 73392190d2b1..e44ce1a9eea9 100644
--- a/arch/mips/sibyte/cfe/smp.c
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -57,7 +57,7 @@ void __init prom_prepare_cpus(unsigned int max_cpus)
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
int retval;
-
+
retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
__KSTK_TOS(idle),
(unsigned long)idle->thread_info, 0);
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
index 182a16f42e2d..1a97e3127aeb 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -10,13 +10,13 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*
+/*
* The Bus Watcher monitors internal bus transactions and maintains
* counts of transactions with error status, logging details and
* causing one of several interrupts. This driver provides a handler
@@ -155,7 +155,7 @@ static int bw_read_proc(char *page, char **start, off_t off,
static void create_proc_decoder(struct bw_stats_struct *stats)
{
struct proc_dir_entry *ent;
-
+
ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL,
bw_read_proc, stats);
if (!ent) {
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 2728abbc94d2..2725b263cced 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -377,7 +377,7 @@ void __init arch_init_irq(void)
/*
* Note that the timer interrupts are also mapped, but this is
- * done in sb1250_time_init(). Also, the profiling driver
+ * done in sb1250_time_init(). Also, the profiling driver
* does its own management of IP7.
*/
@@ -392,7 +392,7 @@ void __init arch_init_irq(void)
if (kgdb_flag) {
kgdb_irq = K_INT_UART_0 + kgdb_port;
-#ifdef CONFIG_SIBYTE_SB1250_DUART
+#ifdef CONFIG_SIBYTE_SB1250_DUART
sb1250_duart_present[kgdb_port] = 0;
#endif
/* Setup uart 1 settings, mapper */
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index 0e633ee8d83c..a686bb716ec6 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -128,7 +128,7 @@ static int m41t81_write(uint8_t addr, int b)
/* Clear error bit by writing a 1 */
bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
- }
+ }
/* read the same byte again to make sure it is written */
bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
@@ -136,7 +136,7 @@ static int m41t81_write(uint8_t addr, int b)
while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
-
+
return 0;
}
@@ -148,13 +148,13 @@ int m41t81_set_time(unsigned long t)
/*
* Note the write order matters as it ensures the correctness.
- * When we write sec, 10th sec is clear. It is reasonable to
+ * When we write sec, 10th sec is clear. It is reasonable to
* believe we should finish writing min within a second.
*/
tm.tm_sec = BIN2BCD(tm.tm_sec);
m41t81_write(M41T81REG_SC, tm.tm_sec);
-
+
tm.tm_min = BIN2BCD(tm.tm_min);
m41t81_write(M41T81REG_MN, tm.tm_min);
@@ -187,7 +187,7 @@ unsigned long m41t81_get_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- /*
+ /*
* min is valid if two reads of sec are the same.
*/
for (;;) {
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 457aeb7be858..4daeaa413def 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -73,7 +73,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
{
if (!is_fixup && (regs->cp0_cause & 4)) {
/* Data bus error - print PA */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
printk("DBE physical address: %010lx\n",
__read_64bit_c0_register($26, 1));
#else
@@ -98,7 +98,7 @@ static int __init swarm_setup(void)
rtc_get_time = xicor_get_time;
rtc_set_time = xicor_set_time;
}
-
+
if (m41t81_probe()) {
printk("swarm setup: M41T81 RTC detected.\n");
rtc_get_time = m41t81_get_time;
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 62c760f14674..141a310d74d8 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -103,7 +103,7 @@ static unsigned int ls1bit8(unsigned int x)
/*
* hwint 1 deals with EISA and SCSI interrupts,
- *
+ *
* The EISA_INT bit in CSITPEND is high active, all others are low active.
*/
void pciasic_hwint1(struct pt_regs *regs)
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 8f67cee4317b..1b3f8a0903e1 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -111,7 +111,7 @@ static struct resource sni_mem_resource = {
* The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
* for other purposes. Be paranoid and allocate all of the before the PCI
* code gets a chance to to map anything else there ...
- *
+ *
* This leaves the following areas available:
*
* 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
index ca123e28d1ef..dd3ceda9d712 100644
--- a/arch/mips/tx4927/common/tx4927_irq_handler.S
+++ b/arch/mips/tx4927/common/tx4927_irq_handler.S
@@ -42,13 +42,13 @@
CLI
.set at
- mfc0 t0, CP0_CAUSE
+ 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 */
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index 16bcbdc6d1cc..26d7c53612a8 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -152,7 +152,7 @@ dump_cp0(char *key)
print_cp0(key, 16, "CONFIG ", read_c0_config());
return;
}
-
+
void print_pic(char *key, u32 reg, char *name)
{
printk("%s pic:0x%08x:%s=0x%08x\n", key, reg, name,
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/Makefile b/arch/mips/tx4927/toshiba_rbtx4927/Makefile
index 86ca4cf2d587..c1a377a80a5d 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/Makefile
+++ b/arch/mips/tx4927/toshiba_rbtx4927/Makefile
@@ -1,5 +1,5 @@
-obj-y += toshiba_rbtx4927_prom.o
-obj-y += toshiba_rbtx4927_setup.o
-obj-y += toshiba_rbtx4927_irq.o
+obj-y += toshiba_rbtx4927_prom.o
+obj-y += toshiba_rbtx4927_setup.o
+obj-y += toshiba_rbtx4927_irq.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
index fd5b433f83b7..aee07ff2212a 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -31,7 +31,7 @@
/*
-IRQ Device
+IRQ Device
00 RBTX4927-ISA/00
01 RBTX4927-ISA/01 PS2/Keyboard
02 RBTX4927-ISA/02 Cascade RBTX4927-ISA (irqs 8-15)
@@ -52,15 +52,15 @@ IRQ Device
16 TX4927-CP0/00 Software 0
17 TX4927-CP0/01 Software 1
18 TX4927-CP0/02 Cascade TX4927-CP0
-19 TX4927-CP0/03 Multiplexed -- do not use
-20 TX4927-CP0/04 Multiplexed -- do not use
-21 TX4927-CP0/05 Multiplexed -- do not use
-22 TX4927-CP0/06 Multiplexed -- do not use
+19 TX4927-CP0/03 Multiplexed -- do not use
+20 TX4927-CP0/04 Multiplexed -- do not use
+21 TX4927-CP0/05 Multiplexed -- do not use
+22 TX4927-CP0/06 Multiplexed -- do not use
23 TX4927-CP0/07 CPU TIMER
24 TX4927-PIC/00
25 TX4927-PIC/01
-26 TX4927-PIC/02
+26 TX4927-PIC/02
27 TX4927-PIC/03 Cascade RBTX4927-IOC
28 TX4927-PIC/04
29 TX4927-PIC/05 RBTX4927 RTL-8019AS ethernet
@@ -80,7 +80,7 @@ IRQ Device
43 TX4927-PIC/19
44 TX4927-PIC/20
45 TX4927-PIC/21
-46 TX4927-PIC/22 TX4927 PCI PCI-ERR
+46 TX4927-PIC/22 TX4927 PCI PCI-ERR
47 TX4927-PIC/23 TX4927 PCI PCI-PMA (not used)
48 TX4927-PIC/24
49 TX4927-PIC/25
@@ -100,7 +100,7 @@ IRQ Device
62 RBTX4927-IOC/06
63 RBTX4927-IOC/07
-NOTES:
+NOTES:
SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58
SouthBridge/ISA/pin=0 no pci irq used by this device
SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR via ISA IRQ14
@@ -175,19 +175,19 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB
static const u32 toshiba_rbtx4927_irq_debug_flag =
(TOSHIBA_RBTX4927_IRQ_NONE | TOSHIBA_RBTX4927_IRQ_INFO |
TOSHIBA_RBTX4927_IRQ_WARN | TOSHIBA_RBTX4927_IRQ_EROR
-// | TOSHIBA_RBTX4927_IRQ_IOC_INIT
-// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP
-// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN
-// | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE
-// | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE
-// | TOSHIBA_RBTX4927_IRQ_IOC_MASK
-// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ
-// | TOSHIBA_RBTX4927_IRQ_ISA_INIT
-// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP
-// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN
-// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
-// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
-// | TOSHIBA_RBTX4927_IRQ_ISA_MASK
+// | TOSHIBA_RBTX4927_IRQ_IOC_INIT
+// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP
+// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN
+// | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE
+// | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE
+// | TOSHIBA_RBTX4927_IRQ_IOC_MASK
+// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ
+// | TOSHIBA_RBTX4927_IRQ_ISA_INIT
+// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP
+// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN
+// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
+// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
+// | TOSHIBA_RBTX4927_IRQ_ISA_MASK
// | TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ
);
#endif
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 8724ea3ae04e..fc0720599fd9 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -395,7 +395,7 @@ static int __init tx4927_pcibios_init(void)
/* enable secondary ide */
v08_43 |= 0x80;
- /*
+ /*
* !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
*
* This line of code is intended to provide the user with a work
diff --git a/arch/mips/vr4181/common/Makefile b/arch/mips/vr4181/common/Makefile
deleted file mode 100644
index f7587ca64ead..000000000000
--- a/arch/mips/vr4181/common/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for common code of NEC vr4181 based boards
-#
-
-obj-y := irq.o int_handler.o serial.o time.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr4181/common/int_handler.S b/arch/mips/vr4181/common/int_handler.S
deleted file mode 100644
index 2c041b8ee52b..000000000000
--- a/arch/mips/vr4181/common/int_handler.S
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * arch/mips/vr4181/common/int_handler.S
- *
- * Adapted to the VR4181 and almost entirely rewritten:
- * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar
- *
- * Clean up to conform to the new IRQ
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-#include <asm/vr4181/vr4181.h>
-
-/*
- * [jsun]
- * See include/asm/vr4181/irq.h for IRQ assignment and strategy.
- */
-
- .text
- .set noreorder
-
- .align 5
- NESTED(vr4181_handle_irq, PT_SIZE, ra)
-
- .set noat
- SAVE_ALL
- CLI
-
- .set at
- .set noreorder
-
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- /* we check IP3 first; it happens most frequently */
- andi t1, t0, STATUSF_IP3
- bnez t1, ll_cpu_ip3
- andi t1, t0, STATUSF_IP2
- bnez t1, ll_cpu_ip2
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
- 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
-do_spurious:
- j spurious_interrupt
-
-/*
- * regular CPU irqs
- */
-ll_cputimer_irq:
- li a0, VR4181_IRQ_TIMER
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_cpu_ip0:
- li a0, VR4181_IRQ_SW1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, VR4181_IRQ_SW2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip3:
- li a0, VR4181_IRQ_INT1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip4:
- li a0, VR4181_IRQ_INT2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip5:
- li a0, VR4181_IRQ_INT3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip6:
- li a0, VR4181_IRQ_INT4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-/*
- * One of the sys irq has happend.
- *
- * In the interest of speed, we first determine in the following order
- * which 16-irq block have pending interrupts:
- * sysint1 (16 sources, including cascading intrs from GPIO)
- * sysint2
- * gpio (16 intr sources)
- *
- * Then we do binary search to find the exact interrupt source.
- */
-ll_cpu_ip2:
-
- lui t3,%hi(VR4181_SYSINT1REG)
- lhu t0,%lo(VR4181_SYSINT1REG)(t3)
- lhu t2,%lo(VR4181_MSYSINT1REG)(t3)
- and t0, 0xfffb /* hack - remove RTC Long 1 intr */
- and t0, t2
- beqz t0, check_sysint2
-
- /* check for GPIO interrupts */
- andi t1, t0, 0x0100
- bnez t1, check_gpio_int
-
- /* so we have an interrupt in sysint1 which is not gpio int */
- li a0, VR4181_SYS_IRQ_BASE - 1
- j check_16
-
-check_sysint2:
-
- lhu t0,%lo(VR4181_SYSINT2REG)(t3)
- lhu t2,%lo(VR4181_MSYSINT2REG)(t3)
- and t0, 0xfffe /* hack - remove RTC Long 2 intr */
- and t0, t2
- li a0, VR4181_SYS_IRQ_BASE + 16 - 1
- j check_16
-
-check_gpio_int:
- lui t3,%hi(VR4181_GPINTMSK)
- lhu t0,%lo(VR4181_GPINTMSK)(t3)
- lhu t2,%lo(VR4181_GPINTSTAT)(t3)
- xori t0, 0xffff /* why? reverse logic? */
- and t0, t2
- li a0, VR4181_GPIO_IRQ_BASE - 1
- j check_16
-
-/*
- * When we reach check_16, we have 16-bit status in t0 and base irq number
- * in a0.
- */
-check_16:
- andi t1, t0, 0xff
- bnez t1, check_8
-
- srl t0, 8
- addi a0, 8
- j check_8
-
-/*
- * When we reach check_8, we have 8-bit status in t0 and base irq number
- * in a0.
- */
-check_8:
- andi t1, t0, 0xf
- bnez t1, check_4
-
- srl t0, 4
- addi a0, 4
- j check_4
-
-/*
- * When we reach check_4, we have 4-bit status in t0 and base irq number
- * in a0.
- */
-check_4:
- andi t0, t0, 0xf
- beqz t0, do_spurious
-
-loop:
- andi t2, t0, 0x1
- srl t0, 1
- addi a0, 1
- beqz t2, loop
-
-found_it:
- move a1, sp
- jal do_IRQ
-
- j ret_from_irq
-
- END(vr4181_handle_irq)
diff --git a/arch/mips/vr4181/common/irq.c b/arch/mips/vr4181/common/irq.c
deleted file mode 100644
index 2cdf77c5cb3e..000000000000
--- a/arch/mips/vr4181/common/irq.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
- *
- * linux/arch/mips/vr4181/common/irq.c
- * Completely re-written to use the new irq.c
- *
- * Credits to Bradley D. LaRonde and Michael Klar for writing the original
- * irq.c file which was derived from the common irq.c file.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/gdb-stub.h>
-
-#include <asm/vr4181/vr4181.h>
-
-/*
- * Strategy:
- *
- * We essentially have three irq controllers, CPU, system, and gpio.
- *
- * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
- * CONFIG_IRQ_CPU config option.
- *
- * We here provide sys_irq and gpio_irq controller code.
- */
-
-static int sys_irq_base;
-static int gpio_irq_base;
-
-/* ---------------------- sys irq ------------------------ */
-static void
-sys_irq_enable(unsigned int irq)
-{
- irq -= sys_irq_base;
- if (irq < 16) {
- *VR4181_MSYSINT1REG |= (u16)(1 << irq);
- } else {
- irq -= 16;
- *VR4181_MSYSINT2REG |= (u16)(1 << irq);
- }
-}
-
-static void
-sys_irq_disable(unsigned int irq)
-{
- irq -= sys_irq_base;
- if (irq < 16) {
- *VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
- } else {
- irq -= 16;
- *VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
- }
-
-}
-
-static unsigned int
-sys_irq_startup(unsigned int irq)
-{
- sys_irq_enable(irq);
- return 0;
-}
-
-#define sys_irq_shutdown sys_irq_disable
-#define sys_irq_ack sys_irq_disable
-
-static void
-sys_irq_end(unsigned int irq)
-{
- if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- sys_irq_enable(irq);
-}
-
-static hw_irq_controller sys_irq_controller = {
- "vr4181_sys_irq",
- sys_irq_startup,
- sys_irq_shutdown,
- sys_irq_enable,
- sys_irq_disable,
- sys_irq_ack,
- sys_irq_end,
- NULL /* no affinity stuff for UP */
-};
-
-/* ---------------------- gpio irq ------------------------ */
-/* gpio irq lines use reverse logic */
-static void
-gpio_irq_enable(unsigned int irq)
-{
- irq -= gpio_irq_base;
- *VR4181_GPINTMSK &= ~((u16)(1 << irq));
-}
-
-static void
-gpio_irq_disable(unsigned int irq)
-{
- irq -= gpio_irq_base;
- *VR4181_GPINTMSK |= (u16)(1 << irq);
-}
-
-static unsigned int
-gpio_irq_startup(unsigned int irq)
-{
- gpio_irq_enable(irq);
-
- irq -= gpio_irq_base;
- *VR4181_GPINTEN |= (u16)(1 << irq );
-
- return 0;
-}
-
-static void
-gpio_irq_shutdown(unsigned int irq)
-{
- gpio_irq_disable(irq);
-
- irq -= gpio_irq_base;
- *VR4181_GPINTEN &= ~((u16)(1 << irq ));
-}
-
-static void
-gpio_irq_ack(unsigned int irq)
-{
- u16 irqtype;
- u16 irqshift;
-
- gpio_irq_disable(irq);
-
- /* we clear interrupt if it is edge triggered */
- irq -= gpio_irq_base;
- if (irq < 8) {
- irqtype = *VR4181_GPINTTYPL;
- irqshift = 2 << (irq*2);
- } else {
- irqtype = *VR4181_GPINTTYPH;
- irqshift = 2 << ((irq-8)*2);
- }
- if ( ! (irqtype & irqshift) ) {
- *VR4181_GPINTSTAT = (u16) (1 << irq);
- }
-}
-
-static void
-gpio_irq_end(unsigned int irq)
-{
- if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- gpio_irq_enable(irq);
-}
-
-static hw_irq_controller gpio_irq_controller = {
- "vr4181_gpio_irq",
- gpio_irq_startup,
- gpio_irq_shutdown,
- gpio_irq_enable,
- gpio_irq_disable,
- gpio_irq_ack,
- gpio_irq_end,
- NULL /* no affinity stuff for UP */
-};
-
-/* --------------------- IRQ init stuff ---------------------- */
-
-extern asmlinkage void vr4181_handle_irq(void);
-extern void breakpoint(void);
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-extern void mips_cpu_irq_init(u32 irq_base);
-
-static struct irqaction cascade =
- { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
-static struct irqaction reserved =
- { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
-
-void __init arch_init_irq(void)
-{
- int i;
-
- set_except_vector(0, vr4181_handle_irq);
-
- /* init CPU irqs */
- mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
-
- /* init sys irqs */
- sys_irq_base = VR4181_SYS_IRQ_BASE;
- for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].handler = &sys_irq_controller;
- }
-
- /* init gpio irqs */
- gpio_irq_base = VR4181_GPIO_IRQ_BASE;
- for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].handler = &gpio_irq_controller;
- }
-
- /* Default all ICU IRQs to off ... */
- *VR4181_MSYSINT1REG = 0;
- *VR4181_MSYSINT2REG = 0;
-
- /* We initialize the level 2 ICU registers to all bits disabled. */
- *VR4181_MPIUINTREG = 0;
- *VR4181_MAIUINTREG = 0;
- *VR4181_MKIUINTREG = 0;
-
- /* disable all GPIO intrs */
- *VR4181_GPINTMSK = 0xffff;
-
- /* vector handler. What these do is register the IRQ as non-sharable */
- setup_irq(VR4181_IRQ_INT0, &cascade);
- setup_irq(VR4181_IRQ_GIU, &cascade);
-
- /*
- * RTC interrupts are interesting. They have two destinations.
- * One is at sys irq controller, and the other is at CPU IP3 and IP4.
- * RTC timer is used as system timer.
- * We enable them here, but timer routine will register later
- * with CPU IP3/IP4.
- */
- setup_irq(VR4181_IRQ_RTCL1, &reserved);
- setup_irq(VR4181_IRQ_RTCL2, &reserved);
-}
diff --git a/arch/mips/vr4181/common/serial.c b/arch/mips/vr4181/common/serial.c
deleted file mode 100644
index 3f62c62b107f..000000000000
--- a/arch/mips/vr4181/common/serial.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/vr4181/common/serial.c
- * initialize serial port on vr4181.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-/*
- * [jsun, 010925]
- * You need to make sure rs_table has at least one element in
- * drivers/char/serial.c file. There is no good way to do it right
- * now. A workaround is to include CONFIG_SERIAL_MANY_PORTS in your
- * configure file, which would gives you 64 ports and wastes 11K ram.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-
-#include <asm/vr4181/vr4181.h>
-
-void __init vr4181_init_serial(void)
-{
- struct serial_struct s;
-
- /* turn on UART clock */
- *VR4181_CMUCLKMSK |= VR4181_CMUCLKMSK_MSKSIU;
-
- /* clear memory */
- memset(&s, 0, sizeof(s));
-
- s.line = 0; /* we set the first one */
- s.baud_base = 1152000;
- s.irq = VR4181_IRQ_SIU;
- s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; /* STD_COM_FLAGS */
- s.iomem_base = (u8*)VR4181_SIURB;
- s.iomem_reg_shift = 0;
- s.io_type = SERIAL_IO_MEM;
- if (early_serial_setup(&s) != 0) {
- panic("vr4181_init_serial() failed!");
- }
-}
-
diff --git a/arch/mips/vr4181/common/time.c b/arch/mips/vr4181/common/time.c
deleted file mode 100644
index 17814076b6f4..000000000000
--- a/arch/mips/vr4181/common/time.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * rtc and time ops for vr4181. Part of code is drived from
- * linux-vr, originally written by Bradley D. LaRonde & Michael Klar.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/spinlock.h>
-#include <linux/param.h> /* for HZ */
-#include <linux/time.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/time.h>
-
-#include <asm/vr4181/vr4181.h>
-
-#define COUNTS_PER_JIFFY ((32768 + HZ/2) / HZ)
-
-/*
- * RTC ops
- */
-
-DEFINE_SPINLOCK(rtc_lock);
-
-/* per VR41xx docs, bad data can be read if between 2 counts */
-static inline unsigned short
-read_time_reg(volatile unsigned short *reg)
-{
- unsigned short value;
- do {
- value = *reg;
- barrier();
- } while (value != *reg);
- return value;
-}
-
-static unsigned long
-vr4181_rtc_get_time(void)
-{
- unsigned short regh, regm, regl;
-
- // why this crazy order, you ask? to guarantee that neither m
- // nor l wrap before all 3 read
- do {
- regm = read_time_reg(VR4181_ETIMEMREG);
- barrier();
- regh = read_time_reg(VR4181_ETIMEHREG);
- barrier();
- regl = read_time_reg(VR4181_ETIMELREG);
- } while (regm != read_time_reg(VR4181_ETIMEMREG));
- return ((regh << 17) | (regm << 1) | (regl >> 15));
-}
-
-static int
-vr4181_rtc_set_time(unsigned long timeval)
-{
- unsigned short intreg;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- intreg = *VR4181_RTCINTREG & 0x05;
- barrier();
- *VR4181_ETIMELREG = timeval << 15;
- *VR4181_ETIMEMREG = timeval >> 1;
- *VR4181_ETIMEHREG = timeval >> 17;
- barrier();
- // assume that any ints that just triggered are invalid, since the
- // time value is written non-atomically in 3 separate regs
- *VR4181_RTCINTREG = 0x05 ^ intreg;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-
-/*
- * timer interrupt routine (wrapper)
- *
- * we need our own interrupt routine because we need to clear
- * RTC1 interrupt.
- */
-static void
-vr4181_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- /* Clear the interrupt. */
- *VR4181_RTCINTREG = 0x2;
-
- /* call the generic one */
- timer_interrupt(irq, dev_id, regs);
-}
-
-
-/*
- * vr4181_time_init:
- *
- * We pick the following choices:
- * . we use elapsed timer as the RTC. We set some reasonable init data since
- * it does not persist across reset
- * . we use RTC1 as the system timer interrupt source.
- * . we use CPU counter for fast_gettimeoffset and we calivrate the cpu
- * frequency. In other words, we use calibrate_div64_gettimeoffset().
- * . we use our own timer interrupt routine which clears the interrupt
- * and then calls the generic high-level timer interrupt routine.
- *
- */
-
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-
-static void
-vr4181_timer_setup(struct irqaction *irq)
-{
- /* over-write the handler to be our own one */
- irq->handler = vr4181_timer_interrupt;
-
- /* sets up the frequency */
- *VR4181_RTCL1LREG = COUNTS_PER_JIFFY;
- *VR4181_RTCL1HREG = 0;
-
- /* and ack any pending ints */
- *VR4181_RTCINTREG = 0x2;
-
- /* setup irqaction */
- setup_irq(VR4181_IRQ_INT1, irq);
-
-}
-
-void
-vr4181_init_time(void)
-{
- /* setup hookup functions */
- rtc_get_time = vr4181_rtc_get_time;
- rtc_set_time = vr4181_rtc_set_time;
-
- board_timer_setup = vr4181_timer_setup;
-}
-
diff --git a/arch/mips/vr4181/osprey/Makefile b/arch/mips/vr4181/osprey/Makefile
deleted file mode 100644
index 34be05790883..000000000000
--- a/arch/mips/vr4181/osprey/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for common code of NEC Osprey board
-#
-
-obj-y := setup.o prom.o reset.o
-
-obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/vr4181/osprey/dbg_io.c b/arch/mips/vr4181/osprey/dbg_io.c
deleted file mode 100644
index 5e8a84072d5b..000000000000
--- a/arch/mips/vr4181/osprey/dbg_io.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * kgdb io functions for osprey. We use the serial port on debug board.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.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.
- *
- */
-
-/* ======================= CONFIG ======================== */
-
-/* [jsun] we use the second serial port for kdb */
-#define BASE 0xb7fffff0
-#define MAX_BAUD 115200
-
-/* distance in bytes between two serial registers */
-#define REG_OFFSET 1
-
-/*
- * 0 - kgdb does serial init
- * 1 - kgdb skip serial init
- */
-static int remoteDebugInitialized = 1;
-
-/*
- * the default baud rate *if* kgdb does serial init
- */
-#define BAUD_DEFAULT UART16550_BAUD_38400
-
-/* ======================= END OF CONFIG ======================== */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-#define UART16550_BAUD_2400 2400
-#define UART16550_BAUD_4800 4800
-#define UART16550_BAUD_9600 9600
-#define UART16550_BAUD_19200 19200
-#define UART16550_BAUD_38400 38400
-#define UART16550_BAUD_57600 57600
-#define UART16550_BAUD_115200 115200
-
-#define UART16550_PARITY_NONE 0
-#define UART16550_PARITY_ODD 0x08
-#define UART16550_PARITY_EVEN 0x18
-#define UART16550_PARITY_MARK 0x28
-#define UART16550_PARITY_SPACE 0x38
-
-#define UART16550_DATA_5BIT 0x0
-#define UART16550_DATA_6BIT 0x1
-#define UART16550_DATA_7BIT 0x2
-#define UART16550_DATA_8BIT 0x3
-
-#define UART16550_STOP_1BIT 0x0
-#define UART16550_STOP_2BIT 0x4
-
-/* register offset */
-#define OFS_RCV_BUFFER 0
-#define OFS_TRANS_HOLD 0
-#define OFS_SEND_BUFFER 0
-#define OFS_INTR_ENABLE (1*REG_OFFSET)
-#define OFS_INTR_ID (2*REG_OFFSET)
-#define OFS_DATA_FORMAT (3*REG_OFFSET)
-#define OFS_LINE_CONTROL (3*REG_OFFSET)
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-#define OFS_LINE_STATUS (5*REG_OFFSET)
-#define OFS_MODEM_STATUS (6*REG_OFFSET)
-#define OFS_RS232_INPUT (6*REG_OFFSET)
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
-#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
- /* disable interrupts */
- UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
- /* set up buad rate */
- {
- uint32 divisor;
-
- /* set DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
- /* set divisor */
- divisor = MAX_BAUD / baud;
- UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
- UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
- /* clear DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
- }
-
- /* set data format */
- UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-
-uint8 getDebugChar(void)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(BAUD_DEFAULT,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
- return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(BAUD_DEFAULT,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
- UART16550_WRITE(OFS_SEND_BUFFER, byte);
- return 1;
-}
diff --git a/arch/mips/vr4181/osprey/prom.c b/arch/mips/vr4181/osprey/prom.c
deleted file mode 100644
index af0d14561619..000000000000
--- a/arch/mips/vr4181/osprey/prom.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/vr4181/osprey/prom.c
- * prom code for osprey.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-
-const char *get_system_type(void)
-{
- return "NEC_Vr41xx Osprey";
-}
-
-/*
- * [jsun] right now we assume it is the nec debug monitor, which does
- * not pass any arguments.
- */
-void __init prom_init(void)
-{
- // cmdline is now set in default config
- // strcpy(arcs_cmdline, "ip=bootp ");
- // strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 ");
- // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 "
- // strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 ");
-
- mips_machgroup = MACH_GROUP_NEC_VR41XX;
- mips_machtype = MACH_NEC_OSPREY;
-
- /* 16MB fixed */
- add_memory_region(0, 16 << 20, BOOT_MEM_RAM);
-}
-
-unsigned long __init prom_free_prom_memory(void)
-{
- return 0;
-}
diff --git a/arch/mips/vr4181/osprey/reset.c b/arch/mips/vr4181/osprey/reset.c
deleted file mode 100644
index 036ae83d89d6..000000000000
--- a/arch/mips/vr4181/osprey/reset.c
+++ /dev/null
@@ -1,40 +0,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; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/cacheflush.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void nec_osprey_restart(char *command)
-{
- set_c0_status(ST0_ERL);
- change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
- flush_cache_all();
- write_c0_wired(0);
- __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void nec_osprey_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void nec_osprey_power_off(void)
-{
- nec_osprey_halt();
-}
diff --git a/arch/mips/vr4181/osprey/setup.c b/arch/mips/vr4181/osprey/setup.c
deleted file mode 100644
index 2ff7140e7ed7..000000000000
--- a/arch/mips/vr4181/osprey/setup.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * linux/arch/mips/vr4181/setup.c
- *
- * VR41xx setup routines
- *
- * Copyright (C) 1999 Bradley D. LaRonde
- * Copyright (C) 1999, 2000 Michael Klar
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/reboot.h>
-#include <asm/vr4181/vr4181.h>
-#include <asm/io.h>
-
-
-extern void nec_osprey_restart(char* c);
-extern void nec_osprey_halt(void);
-extern void nec_osprey_power_off(void);
-
-extern void vr4181_init_serial(void);
-extern void vr4181_init_time(void);
-
-static void __init nec_osprey_setup(void)
-{
- set_io_port_base(VR4181_PORT_BASE);
- isa_slot_offset = VR4181_ISAMEM_BASE;
-
- vr4181_init_serial();
- vr4181_init_time();
-
- _machine_restart = nec_osprey_restart;
- _machine_halt = nec_osprey_halt;
- _machine_power_off = nec_osprey_power_off;
-
- /* setup resource limit */
- ioport_resource.end = 0xffffffff;
- iomem_resource.end = 0xffffffff;
-
- /* [jsun] hack */
- /*
- printk("[jsun] hack to change external ISA control register, %x -> %x\n",
- (*VR4181_XISACTL),
- (*VR4181_XISACTL) | 0x2);
- *VR4181_XISACTL |= 0x2;
- */
-
- // *VR4181_GPHIBSTH = 0x2000;
- // *VR4181_GPMD0REG = 0x00c0;
- // *VR4181_GPINTEN = 1<<6;
-
- /* [jsun] I believe this will get the interrupt type right
- * for the ether port.
- */
- *VR4181_GPINTTYPL = 0x3000;
-}
-
-early_initcall(nec_osprey_setup);
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
index aa8605ab76ff..d29201acc4f3 100644
--- a/arch/mips/vr41xx/casio-e55/setup.c
+++ b/arch/mips/vr41xx/casio-e55/setup.c
@@ -23,11 +23,6 @@
#include <asm/io.h>
#include <asm/vr41xx/e55.h>
-const char *get_system_type(void)
-{
- return "CASIO CASSIOPEIA E-11/15/55/65";
-}
-
static int __init casio_e55_setup(void)
{
set_io_port_base(IO_PORT_BASE);
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index fa98ef3855bc..9096302a7ecc 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 pmu.o
+obj-y += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
obj-$(CONFIG_VRC4173) += vrc4173.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index c842661144cb..0b73c5ab3c0c 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -3,8 +3,7 @@
*
* Copyright (C) 2001-2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.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
@@ -31,7 +30,7 @@
*/
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/smp.h>
@@ -39,34 +38,24 @@
#include <asm/cpu.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
#include <asm/vr41xx/vr41xx.h>
-extern asmlinkage void vr41xx_handle_interrupt(void);
-
-extern void init_vr41xx_giuint_irq(void);
-extern void giuint_irq_dispatch(struct pt_regs *regs);
-
-static uint32_t icu1_base;
-static uint32_t icu2_base;
-
-static struct irqaction icu_cascade = {
- .handler = no_action,
- .mask = CPU_MASK_NONE,
- .name = "cascade",
-};
+static void __iomem *icu1_base;
+static void __iomem *icu2_base;
static unsigned char sysint1_assign[16] = {
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char sysint2_assign[16] = {
- 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
-#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
+#define ICU1_TYPE1_BASE 0x0b000080UL
+#define ICU2_TYPE1_BASE 0x0b000200UL
-#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
-#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
+#define ICU1_TYPE2_BASE 0x0f000080UL
+#define ICU2_TYPE2_BASE 0x0f0000a0UL
+
+#define ICU1_SIZE 0x20
+#define ICU2_SIZE 0x1c
#define SYSINT1REG 0x00
#define PIUINTREG 0x02
@@ -106,61 +95,61 @@ static unsigned char sysint2_assign[16] = {
#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
-#define read_icu1(offset) readw(icu1_base + (offset))
-#define write_icu1(val, offset) writew((val), icu1_base + (offset))
+#define INT_TO_IRQ(x) ((x) + 2) /* Int0-4 -> IRQ2-6 */
+
+#define icu1_read(offset) readw(icu1_base + (offset))
+#define icu1_write(offset, value) writew((value), icu1_base + (offset))
-#define read_icu2(offset) readw(icu2_base + (offset))
-#define write_icu2(val, offset) writew((val), icu2_base + (offset))
+#define icu2_read(offset) readw(icu2_base + (offset))
+#define icu2_write(offset, value) writew((value), icu2_base + (offset))
#define INTASSIGN_MAX 4
#define INTASSIGN_MASK 0x0007
-static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
+static inline uint16_t icu1_set(uint8_t offset, uint16_t set)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu1(offset);
- res |= set;
- write_icu1(res, offset);
+ data = icu1_read(offset);
+ data |= set;
+ icu1_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
+static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu1(offset);
- res &= ~clear;
- write_icu1(res, offset);
+ data = icu1_read(offset);
+ data &= ~clear;
+ icu1_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
+static inline uint16_t icu2_set(uint8_t offset, uint16_t set)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu2(offset);
- res |= set;
- write_icu2(res, offset);
+ data = icu2_read(offset);
+ data |= set;
+ icu2_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
+static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu2(offset);
- res &= ~clear;
- write_icu2(res, offset);
+ data = icu2_read(offset);
+ data &= ~clear;
+ icu2_write(offset, data);
- return res;
+ return data;
}
-/*=======================================================================*/
-
void vr41xx_enable_piuint(uint16_t mask)
{
irq_desc_t *desc = irq_desc + PIU_IRQ;
@@ -169,7 +158,7 @@ void vr41xx_enable_piuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- set_icu1(MPIUINTREG, mask);
+ icu1_set(MPIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -184,7 +173,7 @@ void vr41xx_disable_piuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- clear_icu1(MPIUINTREG, mask);
+ icu1_clear(MPIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -199,7 +188,7 @@ void vr41xx_enable_aiuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- set_icu1(MAIUINTREG, mask);
+ icu1_set(MAIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -214,7 +203,7 @@ void vr41xx_disable_aiuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- clear_icu1(MAIUINTREG, mask);
+ icu1_clear(MAIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -229,7 +218,7 @@ void vr41xx_enable_kiuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- set_icu1(MKIUINTREG, mask);
+ icu1_set(MKIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -244,7 +233,7 @@ void vr41xx_disable_kiuint(uint16_t mask)
if (current_cpu_data.cputype == CPU_VR4111 ||
current_cpu_data.cputype == CPU_VR4121) {
spin_lock_irqsave(&desc->lock, flags);
- clear_icu1(MKIUINTREG, mask);
+ icu1_clear(MKIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -257,7 +246,7 @@ void vr41xx_enable_dsiuint(uint16_t mask)
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
- set_icu1(MDSIUINTREG, mask);
+ icu1_set(MDSIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -269,7 +258,7 @@ void vr41xx_disable_dsiuint(uint16_t mask)
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
- clear_icu1(MDSIUINTREG, mask);
+ icu1_clear(MDSIUINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -281,7 +270,7 @@ void vr41xx_enable_firint(uint16_t mask)
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
- set_icu2(MFIRINTREG, mask);
+ icu2_set(MFIRINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -293,7 +282,7 @@ void vr41xx_disable_firint(uint16_t mask)
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
- clear_icu2(MFIRINTREG, mask);
+ icu2_clear(MFIRINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -308,7 +297,7 @@ void vr41xx_enable_pciint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(PCIINT0, MPCIINTREG);
+ icu2_write(MPCIINTREG, PCIINT0);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -324,7 +313,7 @@ void vr41xx_disable_pciint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(0, MPCIINTREG);
+ icu2_write(MPCIINTREG, 0);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -340,7 +329,7 @@ void vr41xx_enable_scuint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(SCUINT0, MSCUINTREG);
+ icu2_write(MSCUINTREG, SCUINT0);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -356,7 +345,7 @@ void vr41xx_disable_scuint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(0, MSCUINTREG);
+ icu2_write(MSCUINTREG, 0);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -372,7 +361,7 @@ void vr41xx_enable_csiint(uint16_t mask)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- set_icu2(MCSIINTREG, mask);
+ icu2_set(MCSIINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -388,7 +377,7 @@ void vr41xx_disable_csiint(uint16_t mask)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- clear_icu2(MCSIINTREG, mask);
+ icu2_clear(MCSIINTREG, mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -404,7 +393,7 @@ void vr41xx_enable_bcuint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(BCUINTR, MBCUINTREG);
+ icu2_write(MBCUINTREG, BCUINTR);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -420,30 +409,28 @@ void vr41xx_disable_bcuint(void)
current_cpu_data.cputype == CPU_VR4131 ||
current_cpu_data.cputype == CPU_VR4133) {
spin_lock_irqsave(&desc->lock, flags);
- write_icu2(0, MBCUINTREG);
+ icu2_write(MBCUINTREG, 0);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
EXPORT_SYMBOL(vr41xx_disable_bcuint);
-/*=======================================================================*/
-
static unsigned int startup_sysint1_irq(unsigned int irq)
{
- set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
return 0; /* never anything pending */
}
static void shutdown_sysint1_irq(unsigned int irq)
{
- clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
}
static void enable_sysint1_irq(unsigned int irq)
{
- set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
}
#define disable_sysint1_irq shutdown_sysint1_irq
@@ -452,7 +439,7 @@ static void enable_sysint1_irq(unsigned int irq)
static void end_sysint1_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
}
static struct hw_interrupt_type sysint1_irq_type = {
@@ -465,23 +452,21 @@ static struct hw_interrupt_type sysint1_irq_type = {
.end = end_sysint1_irq,
};
-/*=======================================================================*/
-
static unsigned int startup_sysint2_irq(unsigned int irq)
{
- set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+ icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
return 0; /* never anything pending */
}
static void shutdown_sysint2_irq(unsigned int irq)
{
- clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+ icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
}
static void enable_sysint2_irq(unsigned int irq)
{
- set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+ icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
}
#define disable_sysint2_irq shutdown_sysint2_irq
@@ -490,7 +475,7 @@ static void enable_sysint2_irq(unsigned int irq)
static void end_sysint2_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+ icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
}
static struct hw_interrupt_type sysint2_irq_type = {
@@ -503,8 +488,6 @@ static struct hw_interrupt_type sysint2_irq_type = {
.end = end_sysint2_irq,
};
-/*=======================================================================*/
-
static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
{
irq_desc_t *desc = irq_desc + irq;
@@ -515,8 +498,8 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
spin_lock_irq(&desc->lock);
- intassign0 = read_icu1(INTASSIGN0);
- intassign1 = read_icu1(INTASSIGN1);
+ intassign0 = icu1_read(INTASSIGN0);
+ intassign1 = icu1_read(INTASSIGN1);
switch (pin) {
case 0:
@@ -556,8 +539,8 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
}
sysint1_assign[pin] = assign;
- write_icu1(intassign0, INTASSIGN0);
- write_icu1(intassign1, INTASSIGN1);
+ icu1_write(INTASSIGN0, intassign0);
+ icu1_write(INTASSIGN1, intassign1);
spin_unlock_irq(&desc->lock);
@@ -574,8 +557,8 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
spin_lock_irq(&desc->lock);
- intassign2 = read_icu1(INTASSIGN2);
- intassign3 = read_icu1(INTASSIGN3);
+ intassign2 = icu1_read(INTASSIGN2);
+ intassign3 = icu1_read(INTASSIGN3);
switch (pin) {
case 0:
@@ -623,8 +606,8 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
}
sysint2_assign[pin] = assign;
- write_icu1(intassign2, INTASSIGN2);
- write_icu1(intassign3, INTASSIGN3);
+ icu1_write(INTASSIGN2, intassign2);
+ icu1_write(INTASSIGN3, intassign3);
spin_unlock_irq(&desc->lock);
@@ -651,88 +634,92 @@ int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
EXPORT_SYMBOL(vr41xx_set_intassign);
-/*=======================================================================*/
-
-asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
+static int icu_get_irq(unsigned int irq, struct pt_regs *regs)
{
uint16_t pend1, pend2;
uint16_t mask1, mask2;
int i;
- pend1 = read_icu1(SYSINT1REG);
- mask1 = read_icu1(MSYSINT1REG);
+ pend1 = icu1_read(SYSINT1REG);
+ mask1 = icu1_read(MSYSINT1REG);
- pend2 = read_icu2(SYSINT2REG);
- mask2 = read_icu2(MSYSINT2REG);
+ pend2 = icu2_read(SYSINT2REG);
+ mask2 = icu2_read(MSYSINT2REG);
mask1 &= pend1;
mask2 &= pend2;
if (mask1) {
for (i = 0; i < 16; i++) {
- if (intnum == sysint1_assign[i] &&
- (mask1 & ((uint16_t)1 << i))) {
- if (i == 8)
- giuint_irq_dispatch(regs);
- else
- do_IRQ(SYSINT1_IRQ(i), regs);
- return;
- }
+ if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i)))
+ return SYSINT1_IRQ(i);
}
}
if (mask2) {
for (i = 0; i < 16; i++) {
- if (intnum == sysint2_assign[i] &&
- (mask2 & ((uint16_t)1 << i))) {
- do_IRQ(SYSINT2_IRQ(i), regs);
- return;
- }
+ if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i)))
+ return SYSINT2_IRQ(i);
}
}
printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
atomic_inc(&irq_err_count);
-}
-/*=======================================================================*/
+ return -1;
+}
static int __init vr41xx_icu_init(void)
{
+ unsigned long icu1_start, icu2_start;
+ int i;
+
switch (current_cpu_data.cputype) {
case CPU_VR4111:
case CPU_VR4121:
- icu1_base = SYSINT1REG_TYPE1;
- icu2_base = SYSINT2REG_TYPE1;
+ icu1_start = ICU1_TYPE1_BASE;
+ icu2_start = ICU2_TYPE1_BASE;
break;
case CPU_VR4122:
case CPU_VR4131:
case CPU_VR4133:
- icu1_base = SYSINT1REG_TYPE2;
- icu2_base = SYSINT2REG_TYPE2;
+ icu1_start = ICU1_TYPE2_BASE;
+ icu2_start = ICU2_TYPE2_BASE;
break;
default:
printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
- return -EINVAL;
+ return -ENODEV;
}
- write_icu1(0, MSYSINT1REG);
- write_icu1(0xffff, MGIUINTLREG);
+ if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL)
+ return -EBUSY;
- write_icu2(0, MSYSINT2REG);
- write_icu2(0xffff, MGIUINTHREG);
+ if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) {
+ release_mem_region(icu1_start, ICU1_SIZE);
+ return -EBUSY;
+ }
- return 0;
-}
+ icu1_base = ioremap(icu1_start, ICU1_SIZE);
+ if (icu1_base == NULL) {
+ release_mem_region(icu1_start, ICU1_SIZE);
+ release_mem_region(icu2_start, ICU2_SIZE);
+ return -ENOMEM;
+ }
-early_initcall(vr41xx_icu_init);
+ icu2_base = ioremap(icu2_start, ICU2_SIZE);
+ if (icu2_base == NULL) {
+ iounmap(icu1_base);
+ release_mem_region(icu1_start, ICU1_SIZE);
+ release_mem_region(icu2_start, ICU2_SIZE);
+ return -ENOMEM;
+ }
-/*=======================================================================*/
+ icu1_write(MSYSINT1REG, 0);
+ icu1_write(MGIUINTLREG, 0xffff);
-static inline void init_vr41xx_icu_irq(void)
-{
- int i;
+ icu2_write(MSYSINT2REG, 0);
+ icu2_write(MGIUINTHREG, 0xffff);
for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
irq_desc[i].handler = &sysint1_irq_type;
@@ -740,18 +727,13 @@ static inline void init_vr41xx_icu_irq(void)
for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
irq_desc[i].handler = &sysint2_irq_type;
- setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
-}
+ cascade_irq(INT0_IRQ, icu_get_irq);
+ cascade_irq(INT1_IRQ, icu_get_irq);
+ cascade_irq(INT2_IRQ, icu_get_irq);
+ cascade_irq(INT3_IRQ, icu_get_irq);
+ cascade_irq(INT4_IRQ, icu_get_irq);
-void __init arch_init_irq(void)
-{
- mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
- init_vr41xx_icu_irq();
- init_vr41xx_giuint_irq();
-
- set_except_vector(0, vr41xx_handle_interrupt);
+ return 0;
}
+
+core_initcall(vr41xx_icu_init);
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
index 38ff89b505f2..272c13aee4fd 100644
--- a/arch/mips/vr41xx/common/int-handler.S
+++ b/arch/mips/vr41xx/common/int-handler.S
@@ -71,24 +71,24 @@
andi t1, t0, CAUSEF_IP3 # check for Int1
bnez t1, handle_int
- li a0, 1
+ li a0, 3
andi t1, t0, CAUSEF_IP4 # check for Int2
bnez t1, handle_int
- li a0, 2
+ li a0, 4
andi t1, t0, CAUSEF_IP5 # check for Int3
bnez t1, handle_int
- li a0, 3
+ li a0, 5
andi t1, t0, CAUSEF_IP6 # check for Int4
bnez t1, handle_int
- li a0, 4
+ li a0, 6
1:
andi t1, t0, CAUSEF_IP2 # check for Int0
bnez t1, handle_int
- li a0, 0
+ li a0, 2
andi t1, t0, CAUSEF_IP0 # check for IP0
bnez t1, handle_irq
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
new file mode 100644
index 000000000000..43b214d39438
--- /dev/null
+++ b/arch/mips/vr41xx/common/irq.c
@@ -0,0 +1,94 @@
+/*
+ * Interrupt handing routines for NEC VR4100 series.
+ *
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
+#include <asm/vr41xx/vr41xx.h>
+
+typedef struct irq_cascade {
+ int (*get_irq)(unsigned int, struct pt_regs *);
+} irq_cascade_t;
+
+static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned;
+
+static struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *))
+{
+ int retval = 0;
+
+ if (irq >= NR_IRQS)
+ return -EINVAL;
+
+ if (irq_cascade[irq].get_irq != NULL)
+ free_irq(irq, NULL);
+
+ irq_cascade[irq].get_irq = get_irq;
+
+ if (get_irq != NULL) {
+ retval = setup_irq(irq, &cascade_irqaction);
+ if (retval < 0)
+ irq_cascade[irq].get_irq = NULL;
+ }
+
+ return retval;
+}
+
+EXPORT_SYMBOL_GPL(cascade_irq);
+
+asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+{
+ irq_cascade_t *cascade;
+ irq_desc_t *desc;
+
+ if (irq >= NR_IRQS) {
+ atomic_inc(&irq_err_count);
+ return;
+ }
+
+ cascade = irq_cascade + irq;
+ if (cascade->get_irq != NULL) {
+ unsigned int source_irq = irq;
+ desc = irq_desc + source_irq;
+ desc->handler->ack(source_irq);
+ irq = cascade->get_irq(irq, regs);
+ if (irq < 0)
+ atomic_inc(&irq_err_count);
+ else
+ irq_dispatch(irq, regs);
+ desc->handler->end(source_irq);
+ } else
+ do_IRQ(irq, regs);
+}
+
+extern asmlinkage void vr41xx_handle_interrupt(void);
+
+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/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/common/type.c
index 60027e5dea25..bcb5f71b5026 100644
--- a/arch/mips/vr41xx/tanbac-tb0226/setup.c
+++ b/arch/mips/vr41xx/common/type.c
@@ -1,7 +1,7 @@
/*
- * setup.c, Setup for the TANBAC TB0226.
+ * type.c, System type for NEC VR4100 series.
*
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.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
@@ -20,5 +20,5 @@
const char *get_system_type(void)
{
- return "TANBAC TB0226";
+ return "NEC VR4100 series";
}
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
index 5475dd72e264..ba58764ef8ea 100644
--- a/arch/mips/vr41xx/common/vrc4173.c
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -476,7 +476,7 @@ static inline int vrc4173_icu_init(int cascade_irq)
if (cascade_irq < GIU_IRQ(0) || cascade_irq > GIU_IRQ(15))
return -EINVAL;
-
+
vrc4173_outw(0, VRC4173_MSYSINT1REG);
vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH);
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
index cff44602d3d4..e4b34ad6ea61 100644
--- a/arch/mips/vr41xx/ibm-workpad/setup.c
+++ b/arch/mips/vr41xx/ibm-workpad/setup.c
@@ -23,11 +23,6 @@
#include <asm/io.h>
#include <asm/vr41xx/workpad.h>
-const char *get_system_type(void)
-{
- return "IBM WorkPad z50";
-}
-
static int __init ibm_workpad_setup(void)
{
set_io_port_base(IO_PORT_BASE);
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/init.c b/arch/mips/vr41xx/nec-cmbvr4133/init.c
index 87f06b3f5a9c..be590edb0b83 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/init.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/init.c
@@ -16,11 +16,6 @@
* Manish Lachwani (mlachwani@mvista.com)
*/
#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
#ifdef CONFIG_ROCKHOPPER
#include <asm/io.h>
@@ -28,14 +23,7 @@
#define PCICONFDREG 0xaf000c14
#define PCICONFAREG 0xaf000c18
-#endif
-
-const char *get_system_type(void)
-{
- return "NEC CMB-VR4133";
-}
-#ifdef CONFIG_ROCKHOPPER
void disable_pcnet(void)
{
u32 data;
diff --git a/arch/mips/vr41xx/tanbac-tb0226/Makefile b/arch/mips/vr41xx/tanbac-tb0226/Makefile
deleted file mode 100644
index 372f953d240b..000000000000
--- a/arch/mips/vr41xx/tanbac-tb0226/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the TANBAC TB0226 specific parts of the kernel
-#
-
-obj-y += setup.o
diff --git a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile
deleted file mode 100644
index 9c6b864ef2ef..000000000000
--- a/arch/mips/vr41xx/tanbac-tb0229/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel
-#
-
-obj-y := setup.o
diff --git a/arch/mips/vr41xx/victor-mpc30x/Makefile b/arch/mips/vr41xx/victor-mpc30x/Makefile
deleted file mode 100644
index a2e8086a31a6..000000000000
--- a/arch/mips/vr41xx/victor-mpc30x/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the Victor MP-C303/304 specific parts of the kernel
-#
-
-obj-y += setup.o
diff --git a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c
deleted file mode 100644
index f591e36726e6..000000000000
--- a/arch/mips/vr41xx/victor-mpc30x/setup.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * setup.c, Setup for the Victor MP-C303/304.
- *
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-const char *get_system_type(void)
-{
- return "Victor MP-C303/304";
-}
diff --git a/arch/mips/vr41xx/zao-capcella/Makefile b/arch/mips/vr41xx/zao-capcella/Makefile
deleted file mode 100644
index cf420197cd23..000000000000
--- a/arch/mips/vr41xx/zao-capcella/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the ZAO Networks Capcella specific parts of the kernel
-#
-
-obj-y += setup.o
diff --git a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c
deleted file mode 100644
index 17bade241fe2..000000000000
--- a/arch/mips/vr41xx/zao-capcella/setup.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * setup.c, Setup for the ZAO Networks Capcella.
- *
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-const char *get_system_type(void)
-{
- return "ZAO Networks Capcella";
-}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 1c2d87435233..0b07922a2ac6 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -49,6 +49,10 @@ config ISA_DMA_API
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 0403d2fcb85e..3b339b1cce13 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -100,15 +100,7 @@ kernel_install: vmlinux
install: kernel_install modules_install
-prepare: include/asm-parisc/offsets.h
-
-arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += lifimage include/asm-parisc/offsets.h
+CLEAN_FILES += lifimage
MRPROPER_FILES += palo.conf
define archhelp
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
index 2680a1c0fa77..aaaf3306c05a 100644
--- a/arch/parisc/hpux/gate.S
+++ b/arch/parisc/hpux/gate.S
@@ -9,7 +9,7 @@
*/
#include <asm/assembly.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/errno.h>
diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S
index 1aa936dfe147..0b0c3a66b1be 100644
--- a/arch/parisc/hpux/wrappers.S
+++ b/arch/parisc/hpux/wrappers.S
@@ -24,7 +24,7 @@
#warning PA64 support needs more work...did first cut
#endif
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/assembly.h>
#include <asm/signal.h>
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index ee58d37dbb27..be0f07f2fa58 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -23,7 +23,7 @@
*/
#include <linux/config.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* we have the following possibilities to act on an interruption:
* - handle in assembly and use shadowed registers only
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index ddf7e914f15e..28405edf8448 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -14,7 +14,7 @@
#include <linux/autoconf.h> /* for CONFIG_SMP */
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/psw.h>
#include <asm/pdc.h>
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 4fc04501d5e5..46b759385115 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -47,7 +47,7 @@
#include <linux/kallsyms.h>
#include <asm/io.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pdc.h>
#include <asm/pdc_chassis.h>
#include <asm/pgalloc.h>
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index c07db9dff7cd..f3428e5e86fb 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -23,7 +23,7 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* PSW bits we allow the debugger to modify */
#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 9421bb98ea63..0224651fd8f1 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -32,7 +32,7 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
@@ -517,13 +517,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
return 0;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
return 1;
}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 32ea701f4d20..8c7a7185cd3b 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -7,7 +7,7 @@
* sorry about the wall, puffin..
*/
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/psw.h>
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 6cf7407344ba..7ff67f8e9f8c 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -188,10 +188,7 @@ do_settimeofday (struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
}
write_sequnlock_irq(&xtime_lock);
clock_was_set();
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 7bf705676297..5f2e6904d14a 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -5,5 +5,3 @@
lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
obj-y := iomap.o
-
-lib-$(CONFIG_SMP) += debuglocks.o
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
index 2de182f6fe8a..90f400b10282 100644
--- a/arch/parisc/lib/bitops.c
+++ b/arch/parisc/lib/bitops.c
@@ -13,8 +13,8 @@
#include <asm/atomic.h>
#ifdef CONFIG_SMP
-spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
- [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
+ [0 ... (ATOMIC_HASH_SIZE-1)] = __RAW_SPIN_LOCK_UNLOCKED
};
#endif
diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
deleted file mode 100644
index 1b33fe6e5b7a..000000000000
--- a/arch/parisc/lib/debuglocks.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Debugging versions of SMP locking primitives.
- *
- * Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
- *
- * Some code stollen from alpha & sparc64 ;)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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
- *
- * We use pdc_printf() throughout the file for all output messages, to avoid
- * losing messages because of disabled interrupts. Since we're using these
- * messages for debugging purposes, it makes sense not to send them to the
- * linux console.
- */
-
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/hardirq.h> /* in_interrupt() */
-#include <asm/system.h>
-#include <asm/hardirq.h> /* in_interrupt() */
-#include <asm/pdc.h>
-
-#undef INIT_STUCK
-#define INIT_STUCK 1L << 30
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-
-
-void _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
-{
- volatile unsigned int *a;
- long stuck = INIT_STUCK;
- void *inline_pc = __builtin_return_address(0);
- unsigned long started = jiffies;
- int printed = 0;
- int cpu = smp_processor_id();
-
-try_again:
-
- /* Do the actual locking */
- /* <T-Bone> ggg: we can't get stuck on the outter loop?
- * <ggg> T-Bone: We can hit the outer loop
- * alot if multiple CPUs are constantly racing for a lock
- * and the backplane is NOT fair about which CPU sees
- * the update first. But it won't hang since every failed
- * attempt will drop us back into the inner loop and
- * decrement `stuck'.
- * <ggg> K-class and some of the others are NOT fair in the HW
- * implementation so we could see false positives.
- * But fixing the lock contention is easier than
- * fixing the HW to be fair.
- * <tausq> __ldcw() returns 1 if we get the lock; otherwise we
- * spin until the value of the lock changes, or we time out.
- */
- mb();
- a = __ldcw_align(lock);
- while (stuck && (__ldcw(a) == 0))
- while ((*a == 0) && --stuck);
- mb();
-
- if (unlikely(stuck <= 0)) {
- pdc_printf(
- "%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)"
- " owned by %s:%d in %s at %p(%d)\n",
- base_file, line_no, lock->module, lock,
- current->comm, inline_pc, cpu,
- lock->bfile, lock->bline, lock->task->comm,
- lock->previous, lock->oncpu);
- stuck = INIT_STUCK;
- printed = 1;
- goto try_again;
- }
-
- /* Exiting. Got the lock. */
- lock->oncpu = cpu;
- lock->previous = inline_pc;
- lock->task = current;
- lock->bfile = (char *)base_file;
- lock->bline = line_no;
-
- if (unlikely(printed)) {
- pdc_printf(
- "%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n",
- base_file, line_no, current->comm, inline_pc,
- cpu, jiffies - started);
- }
-}
-
-void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no)
-{
- CHECK_LOCK(lock);
- volatile unsigned int *a;
- mb();
- a = __ldcw_align(lock);
- if (unlikely((*a != 0) && lock->babble)) {
- lock->babble--;
- pdc_printf(
- "%s:%d: spin_unlock(%s:%p) not locked\n",
- base_file, line_no, lock->module, lock);
- }
- *a = 1;
- mb();
-}
-
-int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
-{
- int ret;
- volatile unsigned int *a;
- mb();
- a = __ldcw_align(lock);
- ret = (__ldcw(a) != 0);
- mb();
- if (ret) {
- lock->oncpu = smp_processor_id();
- lock->previous = __builtin_return_address(0);
- lock->task = current;
- } else {
- lock->bfile = (char *)base_file;
- lock->bline = line_no;
- }
- return ret;
-}
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#ifdef CONFIG_DEBUG_RWLOCK
-
-/* Interrupts trouble detailed explanation, thx Grant:
- *
- * o writer (wants to modify data) attempts to acquire the rwlock
- * o He gets the write lock.
- * o Interupts are still enabled, we take an interrupt with the
- * write still holding the lock.
- * o interrupt handler tries to acquire the rwlock for read.
- * o deadlock since the writer can't release it at this point.
- *
- * In general, any use of spinlocks that competes between "base"
- * level and interrupt level code will risk deadlock. Interrupts
- * need to be disabled in the base level routines to avoid it.
- * Or more precisely, only the IRQ the base level routine
- * is competing with for the lock. But it's more efficient/faster
- * to just disable all interrupts on that CPU to guarantee
- * once it gets the lock it can release it quickly too.
- */
-
-void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline)
-{
- void *inline_pc = __builtin_return_address(0);
- unsigned long started = jiffies;
- long stuck = INIT_STUCK;
- int printed = 0;
- int cpu = smp_processor_id();
-
- if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
- pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
- BUG();
- }
-
- /* Note: if interrupts are disabled (which is most likely), the printk
- will never show on the console. We might need a polling method to flush
- the dmesg buffer anyhow. */
-
-retry:
- _raw_spin_lock(&rw->lock);
-
- if(rw->counter != 0) {
- /* this basically never happens */
- _raw_spin_unlock(&rw->lock);
-
- stuck--;
- if ((unlikely(stuck <= 0)) && (rw->counter < 0)) {
- pdc_printf(
- "%s:%d: write_lock stuck on writer"
- " in %s at %p(%d) %ld ticks\n",
- bfile, bline, current->comm, inline_pc,
- cpu, jiffies - started);
- stuck = INIT_STUCK;
- printed = 1;
- }
- else if (unlikely(stuck <= 0)) {
- pdc_printf(
- "%s:%d: write_lock stuck on reader"
- " in %s at %p(%d) %ld ticks\n",
- bfile, bline, current->comm, inline_pc,
- cpu, jiffies - started);
- stuck = INIT_STUCK;
- printed = 1;
- }
-
- while(rw->counter != 0);
-
- goto retry;
- }
-
- /* got it. now leave without unlocking */
- rw->counter = -1; /* remember we are locked */
-
- if (unlikely(printed)) {
- pdc_printf(
- "%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n",
- bfile, bline, current->comm, inline_pc,
- cpu, jiffies - started);
- }
-}
-
-int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
-{
-#if 0
- void *inline_pc = __builtin_return_address(0);
- int cpu = smp_processor_id();
-#endif
-
- if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
- pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
- BUG();
- }
-
- /* Note: if interrupts are disabled (which is most likely), the printk
- will never show on the console. We might need a polling method to flush
- the dmesg buffer anyhow. */
-
- _raw_spin_lock(&rw->lock);
-
- if(rw->counter != 0) {
- /* this basically never happens */
- _raw_spin_unlock(&rw->lock);
- return 0;
- }
-
- /* got it. now leave without unlocking */
- rw->counter = -1; /* remember we are locked */
-#if 0
- pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
- bfile, bline, current->comm, inline_pc, cpu);
-#endif
- return 1;
-}
-
-void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
-{
-#if 0
- void *inline_pc = __builtin_return_address(0);
- unsigned long started = jiffies;
- int cpu = smp_processor_id();
-#endif
- unsigned long flags;
-
- local_irq_save(flags);
- _raw_spin_lock(&rw->lock);
-
- rw->counter++;
-#if 0
- pdc_printf(
- "%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n",
- bfile, bline, current->comm, inline_pc,
- cpu, jiffies - started);
-#endif
- _raw_spin_unlock(&rw->lock);
- local_irq_restore(flags);
-}
-
-#endif /* CONFIG_DEBUG_RWLOCK */
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
index 134f0cd240f5..1b91612ed964 100644
--- a/arch/parisc/lib/fixup.S
+++ b/arch/parisc/lib/fixup.S
@@ -20,7 +20,7 @@
* Fixup routines for kernel exception handling.
*/
#include <linux/config.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/assembly.h>
#include <asm/errno.h>
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 89fe0ceeaa40..2ca9ec7ec3a7 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -1380,7 +1380,7 @@ static void cs_nosound(unsigned long xx)
spin_unlock_irqrestore(&cs4218_lock, flags);
}
-static struct timer_list beep_timer = TIMER_INITIALIZER(cs_nosound, 0, 0);
+static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0);
};
static void cs_mksound(unsigned int hz, unsigned int ticks)
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index e6fa1d1cc03a..347ea284140b 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -47,6 +47,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
menu "Processor"
@@ -261,6 +265,15 @@ config PPC601_SYNC_FIX
If in doubt, say Y here.
+config HOTPLUG_CPU
+ bool "Support for enabling/disabling CPUs"
+ depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC
+ ---help---
+ Say Y here to be able to disable and re-enable individual
+ CPUs at runtime on SMP machines.
+
+ Say N if you are unsure.
+
source arch/ppc/platforms/4xx/Kconfig
source arch/ppc/platforms/85xx/Kconfig
@@ -330,14 +343,6 @@ config RPXLITE
End of life: end 2000 ?
URL: see TQM850L
- SPD823TS:
- MPC823 based board used in the "Tele Server" product
- Manufacturer: Speech Design, <http://www.speech-design.de/>
- Date of Release: Mid 2000 (?)
- End of life: -
- URL: <http://www.speech-design.de/>
- select "English", then "Teleteam Solutions", then "TeleServer"
-
IVMS8:
MPC860 based board used in the "Integrated Voice Mail System",
Small Version (8 voice channels)
@@ -354,13 +359,6 @@ config RPXLITE
End of life: -
URL: <http://www.speech-design.de/>
- SM850:
- Service Module (based on TQM850L)
- Manufacturer: Dependable Computer Systems, <http://www.decomsys.com/>
- Date of Release: end 2000 (?)
- End of life: mid 2001 (?)
- URL: <http://www.tz-mikroelektronik.de/ServiceModule/index.html>
-
HERMES:
Hermes-Pro ISDN/LAN router with integrated 8 x hub
Manufacturer: Multidata Gesellschaft fur Datentechnik und Informatik
@@ -464,13 +462,6 @@ config TQM860L
config FPS850L
bool "FPS850L"
-config SPD823TS
- bool "SPD823TS"
- help
- Say Y here to support the Speech Design 823 Tele-Server from Speech
- Design, released in 2000. The manufacturer's website is at
- <http://www.speech-design.de/>.
-
config IVMS8
bool "IVMS8"
help
@@ -485,14 +476,6 @@ config IVML24
from Speech Design, released March 2001. The manufacturer's website
is at <http://www.speech-design.de/>.
-config SM850
- bool "SM850"
- help
- Say Y here to support the Service Module 850 from Dependable
- Computer Systems, an SBC based on the TQM850L module by TQ
- Components. This board is no longer in production. The
- manufacturer's website is at <http://www.decomsys.com/>.
-
config HERMES_PRO
bool "HERMES"
@@ -578,9 +561,6 @@ config CPCI690
help
Select CPCI690 if configuring a Force CPCI690 cPCI board.
-config PCORE
- bool "Force-PowerCore"
-
config POWERPMC250
bool "Force-PowerPMC250"
@@ -613,9 +593,6 @@ config EV64260
config LOPEC
bool "Motorola-LoPEC"
-config MCPN765
- bool "Motorola-MCPN765"
-
config MVME5100
bool "Motorola-MVME5100"
@@ -637,12 +614,6 @@ config SANDPOINT
config RADSTONE_PPC7D
bool "Radstone Technology PPC7D board"
-config ADIR
- bool "SBS-Adirondack"
-
-config K2
- bool "SBS-K2"
-
config PAL4
bool "SBS-Palomar4"
@@ -713,6 +684,16 @@ config MPC834x_SYS
help
This option enables support for the MPC 834x SYS evaluation board.
+ Be aware that PCI buses can only function when SYS board is plugged
+ into the PIB (Platform IO Board) board from Freescale which provide
+ 3 PCI slots. The PIBs PCI initialization is the bootloader's
+ responsiblilty.
+
+config EV64360
+ bool "Marvell-EV64360BP"
+ help
+ Select EV64360 if configuring a Marvell EV64360BP Evaluation
+ platform.
endchoice
config PQ2ADS
@@ -722,7 +703,7 @@ config PQ2ADS
config TQM8xxL
bool
- depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L || SM850)
+ depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
default y
config EMBEDDEDBOOT
@@ -796,15 +777,15 @@ config PPC_OF
config PPC_GEN550
bool
- depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
- PRPMC750 || K2 || PRPMC800 || LOPEC || \
+ depends on SANDPOINT || SPRUCE || PPLUS || \
+ PRPMC750 || PRPMC800 || LOPEC || \
(EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
83xx
default y
config FORCE
bool
- depends on 6xx && (PCORE || POWERPMC250)
+ depends on 6xx && POWERPMC250
default y
config GT64260
@@ -814,7 +795,7 @@ config GT64260
config MV64360 # Really MV64360 & MV64460
bool
- depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU
+ depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360
default y
config MV64X60
@@ -867,7 +848,7 @@ config EPIC_SERIAL_MODE
config MPC10X_BRIDGE
bool
- depends on PCORE || POWERPMC250 || LOPEC || SANDPOINT
+ depends on POWERPMC250 || LOPEC || SANDPOINT
default y
config MPC10X_OPENPIC
@@ -886,10 +867,6 @@ config SANDPOINT_ENABLE_UART1
If this option is enabled then the MPC824x processor will run
in DUART mode instead of UART mode.
-config CPC710_DATA_GATHERING
- bool "Enable CPC710 data gathering"
- depends on K2
-
config HARRIER_STORE_GATHERING
bool "Enable Harrier store gathering"
depends on HARRIER
@@ -1194,6 +1171,11 @@ config PCI_DOMAINS
bool
default PCI
+config MPC83xx_PCI2
+ bool " Supprt for 2nd PCI host controller"
+ depends on PCI && MPC834x
+ default y if MPC834x_SYS
+
config PCI_QSPAN
bool "QSpan PCI"
depends on !4xx && !CPM2 && 8xx
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index e16c7710d4be..61653cb60c4e 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -62,7 +62,8 @@ config BOOTX_TEXT
config SERIAL_TEXT_DEBUG
bool "Support for early boot texts over serial port"
- depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
+ depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
+ PPC_GEN550 || PPC_MPC52xx
config PPC_OCP
bool
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index f9b0d778dd82..16e2675f3270 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -21,11 +21,14 @@ CC := $(CC) -m32
endif
LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic
-CPPFLAGS += -Iarch/$(ARCH)
+# The -Iarch/$(ARCH)/include is temporary while we are merging
+CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
AFLAGS += -Iarch/$(ARCH)
CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
-ffixed-r2 -mmultiple
CPP = $(CC) -E $(CFLAGS)
+# Temporary hack until we have migrated to asm-powerpc
+LINUXINCLUDE += -Iarch/$(ARCH)/include
CHECKFLAGS += -D__powerpc__
@@ -101,14 +104,16 @@ endef
archclean:
$(Q)$(MAKE) $(clean)=arch/ppc/boot
+ # Temporary hack until we have migrated to asm-powerpc
+ $(Q)rm -rf arch/$(ARCH)/include
-prepare: include/asm-$(ARCH)/offsets.h checkbin
+archprepare: checkbin
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
+# Temporary hack until we have migrated to asm-powerpc
+include/asm: arch/$(ARCH)/include/asm
+arch/$(ARCH)/include/asm:
+ $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi
+ $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm
# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
# to stdout and these checks are run even on install targets.
@@ -134,7 +139,5 @@ checkbin:
false ; \
fi
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h \
- arch/$(ARCH)/kernel/asm-offsets.s \
- $(TOUT)
+CLEAN_FILES += $(TOUT)
diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
index 9017c547a6f6..26818bbb6cff 100644
--- a/arch/ppc/boot/common/ns16550.c
+++ b/arch/ppc/boot/common/ns16550.c
@@ -23,7 +23,7 @@ static int shift;
unsigned long serial_init(int chan, void *ignored)
{
- unsigned long com_port;
+ unsigned long com_port, base_baud;
unsigned char lcr, dlm;
/* We need to find out which type io we're expecting. If it's
@@ -43,6 +43,8 @@ unsigned long serial_init(int chan, void *ignored)
/* How far apart the registers are. */
shift = rs_table[chan].iomem_reg_shift;
+ /* Base baud.. */
+ base_baud = rs_table[chan].baud_base;
/* save the LCR */
lcr = inb(com_port + (UART_LCR << shift));
@@ -62,9 +64,9 @@ unsigned long serial_init(int chan, void *ignored)
else {
/* Input clock. */
outb(com_port + (UART_DLL << shift),
- (BASE_BAUD / SERIAL_BAUD) & 0xFF);
+ (base_baud / SERIAL_BAUD) & 0xFF);
outb(com_port + (UART_DLM << shift),
- (BASE_BAUD / SERIAL_BAUD) >> 8);
+ (base_baud / SERIAL_BAUD) >> 8);
/* 8 data, 1 stop, no parity */
outb(com_port + (UART_LCR << shift), 0x03);
/* RTS/DTR */
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
index 47e641455bc5..c96c9f80521e 100644
--- a/arch/ppc/boot/common/util.S
+++ b/arch/ppc/boot/common/util.S
@@ -252,7 +252,7 @@ _GLOBAL(flush_instruction_cache)
1: dcbf r0,r3 # Flush the data cache
icbi r0,r3 # Invalidate the instruction cache
addi r3,r3,0x10 # Increment by one cache line
- cmplwi cr0,r3,r4 # Are we at the end yet?
+ cmplw cr0,r3,r4 # Are we at the end yet?
blt 1b # No, keep flushing and invalidating
#else
/* Enable, invalidate and then disable the L1 icache/dcache. */
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index d4dc4fa79647..b7bd8f61a4ad 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -96,10 +96,6 @@ zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE
zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF
end-$(CONFIG_GEMINI) := gemini
- extra.o-$(CONFIG_K2) := prepmap.o
- end-$(CONFIG_K2) := k2
- cacheflag-$(CONFIG_K2) := -include $(clear_L2_L3)
-
extra.o-$(CONFIG_KATANA) := misc-katana.o
end-$(CONFIG_KATANA) := katana
cacheflag-$(CONFIG_KATANA) := -include $(clear_L2_L3)
@@ -108,12 +104,15 @@ zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF
end-$(CONFIG_RADSTONE_PPC7D) := radstone_ppc7d
cacheflag-$(CONFIG_RADSTONE_PPC7D) := -include $(clear_L2_L3)
+ extra.o-$(CONFIG_EV64360) := misc-ev64360.o
+ end-$(CONFIG_EV64360) := ev64360
+ cacheflag-$(CONFIG_EV64360) := -include $(clear_L2_L3)
+
# kconfig 'feature', only one of these will ever be 'y' at a time.
# The rest will be unset.
-motorola := $(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750) \
+motorola := $(CONFIG_MVME5100)$(CONFIG_PRPMC750) \
$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS)
motorola := $(strip $(motorola))
-pcore := $(CONFIG_PCORE)$(CONFIG_POWERPMC250)
zimage-$(motorola) := zImage-PPLUS
zimageinitrd-$(motorola) := zImage.initrd-PPLUS
@@ -123,12 +122,6 @@ zimageinitrd-$(motorola) := zImage.initrd-PPLUS
extra.o-$(CONFIG_PPLUS) := prepmap.o
extra.o-$(CONFIG_LOPEC) := mpc10x_memory.o
- zimage-$(pcore) := zImage-STRIPELF
-zimageinitrd-$(pcore) := zImage.initrd-STRIPELF
- extra.o-$(pcore) := chrpmap.o
- end-$(pcore) := pcore
- cacheflag-$(pcore) := -include $(clear_L2_L3)
-
# Really only valid if CONFIG_6xx=y
zimage-$(CONFIG_PPC_PREP) := zImage-PPLUS
zimageinitrd-$(CONFIG_PPC_PREP) := zImage.initrd-PPLUS
@@ -158,8 +151,6 @@ zimageinitrd-$(CONFIG_LITE5200) := zImage.initrd-STRIPELF
# This is a treeboot that needs init functions until the
# boot rom is sorted out (i.e. this is short lived)
-extra-aflags-$(CONFIG_REDWOOD_4) := -Wa,-m405
-extra.o-$(CONFIG_REDWOOD_4) := rw4/rw4_init.o rw4/rw4_init_brd.o
EXTRA_AFLAGS := $(extra-aflags-y)
# head.o needs to get the cacheflags defined.
AFLAGS_head.o += $(cacheflag-y)
diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c
index c342b47e763e..491a691d10cc 100644
--- a/arch/ppc/boot/simple/embed_config.c
+++ b/arch/ppc/boot/simple/embed_config.c
@@ -784,28 +784,12 @@ embed_config(bd_t ** bdp)
#ifdef CONFIG_IBM_OPENBIOS
/* This could possibly work for all treeboot roms.
*/
-#if defined(CONFIG_ASH) || defined(CONFIG_BEECH) || defined(CONFIG_BUBINGA)
+#if defined(CONFIG_BUBINGA)
#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */
#else
#define BOARD_INFO_VECTOR 0xFFFE0B50
#endif
-#ifdef CONFIG_BEECH
-static void
-get_board_info(bd_t **bdp)
-{
- typedef void (*PFV)(bd_t *bd);
- ((PFV)(*(unsigned long *)BOARD_INFO_VECTOR))(*bdp);
- return;
-}
-
-void
-embed_config(bd_t **bdp)
-{
- *bdp = &bdinfo;
- get_board_info(bdp);
-}
-#else /* !CONFIG_BEECH */
void
embed_config(bd_t **bdp)
{
@@ -860,7 +844,6 @@ embed_config(bd_t **bdp)
#endif
timebase_period_ns = 1000000000 / bd->bi_tbfreq;
}
-#endif /* CONFIG_BEECH */
#endif /* CONFIG_IBM_OPENBIOS */
#ifdef CONFIG_EP405
@@ -943,39 +926,3 @@ embed_config(bd_t **bdp)
#endif
}
#endif
-
-#ifdef CONFIG_RAINIER
-/* Rainier uses vxworks bootrom */
-void
-embed_config(bd_t **bdp)
-{
- u_char *cp;
- int i;
- bd_t *bd;
-
- bd = &bdinfo;
- *bdp = bd;
-
- for(i=0;i<8192;i+=32) {
- __asm__("dccci 0,%0" :: "r" (i));
- }
- __asm__("iccci 0,0");
- __asm__("sync;isync");
-
- /* init ram for parity */
- memset(0, 0,0x400000); /* Lo memory */
-
-
- bd->bi_memsize = (32 * 1024 * 1024) ;
- bd->bi_intfreq = 133000000; //the internal clock is 133 MHz
- bd->bi_busfreq = 100000000;
- bd->bi_pci_busfreq= 33000000;
-
- cp = (u_char *)def_enet_addr;
- for (i=0; i<6; i++) {
- bd->bi_enetaddr[i] = *cp++;
- }
-
-}
-#endif
-
diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S
index 524053202bb4..5e4adc298bf9 100644
--- a/arch/ppc/boot/simple/head.S
+++ b/arch/ppc/boot/simple/head.S
@@ -120,15 +120,6 @@ haveOF:
mtspr SPRN_DER,r4
#endif
-#ifdef CONFIG_REDWOOD_4
- /* All of this Redwood 4 stuff will soon disappear when the
- * boot rom is straightened out.
- */
- mr r29, r3 /* Easier than changing the other code */
- bl HdwInit
- mr r3, r29
-#endif
-
#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP)
mr r4,r29 /* put the board info pointer where the relocate
* routine will find it
diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c
index ef08e86c9b25..26860300fa09 100644
--- a/arch/ppc/boot/simple/misc-cpci690.c
+++ b/arch/ppc/boot/simple/misc-cpci690.c
@@ -12,16 +12,56 @@
*/
#include <linux/types.h>
+#include <asm/io.h>
#include <platforms/cpci690.h>
+#define KB (1024UL)
+#define MB (1024UL*KB)
+#define GB (1024UL*MB)
+
extern u32 mv64x60_console_baud;
extern u32 mv64x60_mpsc_clk_src;
extern u32 mv64x60_mpsc_clk_freq;
+u32 mag = 0xffff;
+
+unsigned long
+get_mem_size(void)
+{
+ u32 size;
+
+ switch (in_8(((void __iomem *)CPCI690_BR_BASE + CPCI690_BR_MEM_CTLR))
+ & 0x07) {
+ case 0x01:
+ size = 256*MB;
+ break;
+ case 0x02:
+ size = 512*MB;
+ break;
+ case 0x03:
+ size = 768*MB;
+ break;
+ case 0x04:
+ size = 1*GB;
+ break;
+ case 0x05:
+ size = 1*GB + 512*MB;
+ break;
+ case 0x06:
+ size = 2*GB;
+ break;
+ default:
+ size = 0;
+ }
+
+ return size;
+}
+
void
mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
{
mv64x60_console_baud = CPCI690_MPSC_BAUD;
mv64x60_mpsc_clk_src = CPCI690_MPSC_CLK_SRC;
- mv64x60_mpsc_clk_freq = CPCI690_BUS_FREQ;
+ mv64x60_mpsc_clk_freq =
+ (get_mem_size() >= (1*GB)) ? 100000000 : 133333333;
}
diff --git a/arch/ppc/boot/simple/misc-ev64360.c b/arch/ppc/boot/simple/misc-ev64360.c
new file mode 100644
index 000000000000..cd1ccf2a1582
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-ev64360.c
@@ -0,0 +1,44 @@
+/*
+ * arch/ppc/boot/simple/misc-ev64360.c
+ * Copyright (C) 2005 Lee Nicks <allinux@gmail.com>
+ *
+ * Based on arch/ppc/boot/simple/misc-katana.c from:
+ * Mark A. Greer <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/ev64360.h>
+
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+
+/* Not in the kernel so won't include kernel.h to get its 'min' definition */
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ mv64x60_console_baud = EV64360_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = EV64360_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = EV64360_MPSC_CLK_FREQ;
+}
diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c
index b6e1bb833157..ec94a11bacac 100644
--- a/arch/ppc/boot/simple/misc-katana.c
+++ b/arch/ppc/boot/simple/misc-katana.c
@@ -26,6 +26,8 @@ extern u32 mv64x60_mpsc_clk_freq;
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
+unsigned long mv64360_get_mem_size(void);
+
void
mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
{
@@ -35,3 +37,9 @@ mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
min(katana_bus_freq((void __iomem *)KATANA_CPLD_BASE),
MV64x60_TCLK_FREQ_MAX);
}
+
+unsigned long
+get_mem_size(void)
+{
+ return mv64360_get_mem_size();
+}
diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c
index 7e88fc6d207d..258d4599fadc 100644
--- a/arch/ppc/boot/simple/misc-mv64x60.c
+++ b/arch/ppc/boot/simple/misc-mv64x60.c
@@ -19,6 +19,33 @@
extern struct bi_record *decompress_kernel(unsigned long load_addr,
int num_words, unsigned long cksum);
+
+u32 size_reg[MV64x60_CPU2MEM_WINDOWS] = {
+ MV64x60_CPU2MEM_0_SIZE, MV64x60_CPU2MEM_1_SIZE,
+ MV64x60_CPU2MEM_2_SIZE, MV64x60_CPU2MEM_3_SIZE
+};
+
+/* Read mem ctlr to get the amount of mem in system */
+unsigned long
+mv64360_get_mem_size(void)
+{
+ u32 enables, i, v;
+ u32 mem = 0;
+
+ enables = in_le32((void __iomem *)CONFIG_MV64X60_NEW_BASE +
+ MV64360_CPU_BAR_ENABLE) & 0xf;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++)
+ if (!(enables & (1<<i))) {
+ v = in_le32((void __iomem *)CONFIG_MV64X60_NEW_BASE
+ + size_reg[i]) & 0xffff;
+ v = (v + 1) << 16;
+ mem += v;
+ }
+
+ return mem;
+}
+
void
mv64x60_move_base(void __iomem *old_base, void __iomem *new_base)
{
diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c
index 5b45eb46b669..b9c24d4c738b 100644
--- a/arch/ppc/boot/simple/mv64x60_tty.c
+++ b/arch/ppc/boot/simple/mv64x60_tty.c
@@ -22,9 +22,16 @@
#include <asm/mv64x60_defs.h>
#include <mpsc_defs.h>
+#ifdef CONFIG_EV64360
+#include <platforms/ev64360.h>
+u32 mv64x60_console_baud = EV64360_DEFAULT_BAUD;
+u32 mv64x60_mpsc_clk_src = EV64360_MPSC_CLK_SRC; /* TCLK */
+u32 mv64x60_mpsc_clk_freq = EV64360_MPSC_CLK_FREQ;
+#else
u32 mv64x60_console_baud = 9600;
u32 mv64x60_mpsc_clk_src = 8; /* TCLK */
u32 mv64x60_mpsc_clk_freq = 100000000;
+#endif
extern void udelay(long);
static void stop_dma(int chan);
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c
deleted file mode 100644
index 93400dfcce7f..000000000000
--- a/arch/ppc/boot/utils/addRamDisk.c
+++ /dev/null
@@ -1,203 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-
-#define ElfHeaderSize (64 * 1024)
-#define ElfPages (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc0000000)
-
-void get4k(FILE *file, char *buf )
-{
- unsigned j;
- unsigned num = fread(buf, 1, 4096, file);
- for ( j=num; j<4096; ++j )
- buf[j] = 0;
-}
-
-void put4k(FILE *file, char *buf )
-{
- fwrite(buf, 1, 4096, file);
-}
-
-void death(const char *msg, FILE *fdesc, const char *fname)
-{
- printf(msg);
- fclose(fdesc);
- unlink(fname);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- char inbuf[4096];
- FILE *ramDisk = NULL;
- FILE *inputVmlinux = NULL;
- FILE *outputVmlinux = NULL;
- unsigned i = 0;
- u_int32_t ramFileLen = 0;
- u_int32_t ramLen = 0;
- u_int32_t roundR = 0;
- u_int32_t kernelLen = 0;
- u_int32_t actualKernelLen = 0;
- u_int32_t round = 0;
- u_int32_t roundedKernelLen = 0;
- u_int32_t ramStartOffs = 0;
- u_int32_t ramPages = 0;
- u_int32_t roundedKernelPages = 0;
- u_int32_t hvReleaseData = 0;
- u_int32_t eyeCatcher = 0xc8a5d9c4;
- u_int32_t naca = 0;
- u_int32_t xRamDisk = 0;
- u_int32_t xRamDiskSize = 0;
- if ( argc < 2 ) {
- printf("Name of RAM disk file missing.\n");
- exit(1);
- }
-
- if ( argc < 3 ) {
- printf("Name of vmlinux file missing.\n");
- exit(1);
- }
-
- if ( argc < 4 ) {
- printf("Name of vmlinux output file missing.\n");
- exit(1);
- }
-
- ramDisk = fopen(argv[1], "r");
- if ( ! ramDisk ) {
- printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
- exit(1);
- }
- inputVmlinux = fopen(argv[2], "r");
- if ( ! inputVmlinux ) {
- printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
- exit(1);
- }
- outputVmlinux = fopen(argv[3], "w+");
- if ( ! outputVmlinux ) {
- printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
- exit(1);
- }
- fseek(ramDisk, 0, SEEK_END);
- ramFileLen = ftell(ramDisk);
- fseek(ramDisk, 0, SEEK_SET);
- printf("%s file size = %d\n", argv[1], ramFileLen);
-
- ramLen = ramFileLen;
-
- roundR = 4096 - (ramLen % 4096);
- if ( roundR ) {
- printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);
- ramLen += roundR;
- }
-
- printf("Rounded RAM disk size is %d\n", ramLen);
- fseek(inputVmlinux, 0, SEEK_END);
- kernelLen = ftell(inputVmlinux);
- fseek(inputVmlinux, 0, SEEK_SET);
- printf("kernel file size = %d\n", kernelLen);
- if ( kernelLen == 0 ) {
- printf("You must have a linux kernel specified as argv[2]\n");
- exit(1);
- }
-
- actualKernelLen = kernelLen - ElfHeaderSize;
-
- printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
-
- round = actualKernelLen % 4096;
- roundedKernelLen = actualKernelLen;
- if ( round )
- roundedKernelLen += (4096 - round);
-
- printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);
-
- ramStartOffs = roundedKernelLen;
- ramPages = ramLen / 4096;
-
- printf("RAM disk pages to copy = %d\n", ramPages);
-
- // Copy 64K ELF header
- for (i=0; i<(ElfPages); ++i) {
- get4k( inputVmlinux, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- roundedKernelPages = roundedKernelLen / 4096;
-
- fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-
- for ( i=0; i<roundedKernelPages; ++i ) {
- get4k( inputVmlinux, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- for ( i=0; i<ramPages; ++i ) {
- get4k( ramDisk, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- /* Close the input files */
- fclose(ramDisk);
- fclose(inputVmlinux);
- /* And flush the written output file */
- fflush(outputVmlinux);
-
- /* fseek to the hvReleaseData pointer */
- fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
- if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
- death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);
- }
- hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
- printf("hvReleaseData is at %08x\n", hvReleaseData);
-
- /* fseek to the hvReleaseData */
- fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
- if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
- death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);
- }
- /* Check hvReleaseData sanity */
- if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
- death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);
- }
- /* Get the naca pointer */
- naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;
- printf("naca is at %08x\n", naca);
-
- /* fseek to the naca */
- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
- if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
- death("Could not read naca\n", outputVmlinux, argv[3]);
- }
- xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
- xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
- /* Make sure a RAM disk isn't already present */
- if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
- death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);
- }
- /* Fill in the values */
- *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
- *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
-
- /* Write out the new naca */
- fflush(outputVmlinux);
- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
- if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
- death("Could not write naca\n", outputVmlinux, argv[3]);
- }
- printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
- ramPages, ramStartOffs);
-
- /* Done */
- fclose(outputVmlinux);
- /* Set permission to executable */
- chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
- return 0;
-}
-
diff --git a/arch/ppc/configs/SM850_defconfig b/arch/ppc/configs/SM850_defconfig
deleted file mode 100644
index 021884b43029..000000000000
--- a/arch/ppc/configs/SM850_defconfig
+++ /dev/null
@@ -1,522 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-CONFIG_8xx=y
-
-#
-# IBM 4xx options
-#
-CONFIG_EMBEDDEDBOOT=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_NOT_COHERENT_CACHE=y
-# CONFIG_RPXLITE is not set
-# CONFIG_RPXCLASSIC is not set
-# CONFIG_BSEIP is not set
-# CONFIG_FADS is not set
-# CONFIG_TQM823L is not set
-# CONFIG_TQM850L is not set
-# CONFIG_TQM855L is not set
-# CONFIG_TQM860L is not set
-# CONFIG_FPS850L is not set
-# CONFIG_SPD823TS is not set
-# CONFIG_IVMS8 is not set
-# CONFIG_IVML24 is not set
-CONFIG_SM850=y
-# CONFIG_HERMES_PRO is not set
-# CONFIG_IP860 is not set
-# CONFIG_LWMON is not set
-# CONFIG_PCU_E is not set
-# CONFIG_CCM is not set
-# CONFIG_LANTEC is not set
-# CONFIG_MBX is not set
-# CONFIG_WINCEPT is not set
-CONFIG_TQM8xxL=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-CONFIG_MATH_EMULATION=y
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PCI_QSPAN is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttyCPM1"
-
-#
-# 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=0x00400000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD 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_INITRD is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_SERIAL_CPM_SCC1 is not set
-# CONFIG_SERIAL_CPM_SCC2 is not set
-# CONFIG_SERIAL_CPM_SCC3 is not set
-# CONFIG_SERIAL_CPM_SCC4 is not set
-CONFIG_SERIAL_CPM_SMC1=y
-CONFIG_SERIAL_CPM_SMC2=y
-CONFIG_SERIAL_CPM_ALT_SMC2=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_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_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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_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
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# MPC8xx CPM Options
-#
-CONFIG_SCC_ENET=y
-# CONFIG_SCC1_ENET is not set
-# CONFIG_SCC2_ENET is not set
-CONFIG_SCC3_ENET=y
-# CONFIG_FEC_ENET is not set
-CONFIG_ENET_BIG_BUFFERS=y
-
-#
-# Generic MPC8xx Options
-#
-CONFIG_8xx_COPYBACK=y
-CONFIG_8xx_CPU6=y
-# CONFIG_UCODE_PATCH is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/SPD823TS_defconfig b/arch/ppc/configs/SPD823TS_defconfig
deleted file mode 100644
index ba60fea2b834..000000000000
--- a/arch/ppc/configs/SPD823TS_defconfig
+++ /dev/null
@@ -1,520 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-CONFIG_8xx=y
-
-#
-# IBM 4xx options
-#
-CONFIG_EMBEDDEDBOOT=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_NOT_COHERENT_CACHE=y
-# CONFIG_RPXLITE is not set
-# CONFIG_RPXCLASSIC is not set
-# CONFIG_BSEIP is not set
-# CONFIG_FADS is not set
-# CONFIG_TQM823L is not set
-# CONFIG_TQM850L is not set
-# CONFIG_TQM855L is not set
-# CONFIG_TQM860L is not set
-# CONFIG_FPS850L is not set
-CONFIG_SPD823TS=y
-# CONFIG_IVMS8 is not set
-# CONFIG_IVML24 is not set
-# CONFIG_SM850 is not set
-# CONFIG_HERMES_PRO is not set
-# CONFIG_IP860 is not set
-# CONFIG_LWMON is not set
-# CONFIG_PCU_E is not set
-# CONFIG_CCM is not set
-# CONFIG_LANTEC is not set
-# CONFIG_MBX is not set
-# CONFIG_WINCEPT is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-CONFIG_MATH_EMULATION=y
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PCI_QSPAN is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# 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=0x00400000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD 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_INITRD is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_SERIAL_CPM_SCC1 is not set
-# CONFIG_SERIAL_CPM_SCC2 is not set
-# CONFIG_SERIAL_CPM_SCC3 is not set
-# CONFIG_SERIAL_CPM_SCC4 is not set
-CONFIG_SERIAL_CPM_SMC1=y
-# CONFIG_SERIAL_CPM_SMC2 is not set
-CONFIG_SERIAL_CPM_ALT_SMC2=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_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_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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_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
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# MPC8xx CPM Options
-#
-CONFIG_SCC_ENET=y
-# CONFIG_SCC1_ENET is not set
-CONFIG_SCC2_ENET=y
-# CONFIG_SCC3_ENET is not set
-# CONFIG_FEC_ENET is not set
-CONFIG_ENET_BIG_BUFFERS=y
-
-#
-# Generic MPC8xx Options
-#
-CONFIG_8xx_COPYBACK=y
-# CONFIG_8xx_CPU6 is not set
-# CONFIG_UCODE_PATCH is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig
deleted file mode 100644
index f20e6533dc79..000000000000
--- a/arch/ppc/configs/adir_defconfig
+++ /dev/null
@@ -1,805 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-
-#
-# IBM 4xx options
-#
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_APUS is not set
-# CONFIG_WILLOW_2 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=y
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
-# CONFIG_PARPORT_SERIAL is not set
-CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_PC_SUPERIO=y
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
-
-#
-# 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
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# 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_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=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 low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID 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_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D 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_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I 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_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O 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_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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
-
-#
-# 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_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_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_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=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_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 is not set
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# 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 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO 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_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB 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
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-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
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_UHCI_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_BLUETOOTH_TTY is not set
-CONFIG_USB_ACM=m
-# CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-CONFIG_USB_STORAGE_FREECOM=y
-# CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=m
-
-#
-# Input core support is needed for USB HID input layer or HIDBP support
-#
-CONFIG_USB_HIDDEV=y
-
-#
-# USB HID Boot Protocol drivers
-#
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# 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
-
-#
-# USB port drivers
-#
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_GENERIC 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_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_KEYSPAN_PDA is not set
-CONFIG_USB_SERIAL_KEYSPAN=m
-# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-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 is not set
-# 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_SAFE is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-CONFIG_USB_EZUSB=y
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_TIGL is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ash_defconfig b/arch/ppc/configs/ash_defconfig
deleted file mode 100644
index c4a73cc16cf6..000000000000
--- a/arch/ppc/configs/ash_defconfig
+++ /dev/null
@@ -1,666 +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=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-CONFIG_ASH=y
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-# CONFIG_EVB405EP is not set
-# CONFIG_OAK is not set
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_WALNUT is not set
-CONFIG_NP405H=y
-CONFIG_IBM405_ERR77=y
-CONFIG_IBM405_ERR51=y
-CONFIG_IBM_OCP=y
-CONFIG_PPC_OCP=y
-CONFIG_IBM_OPENBIOS=y
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-CONFIG_NOT_COHERENT_CACHE=y
-
-#
-# Platform options
-#
-# CONFIG_PC_KEYBOARD is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
-
-#
-# Bus options
-#
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
-
-#
-# 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=0x00400000
-
-#
-# 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
-#
-
-#
-# 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
-# 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 is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI 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
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET 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=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=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_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q 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_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-CONFIG_IBM_EMAC=y
-# CONFIG_IBM_EMAC_ERRMSG is not set
-CONFIG_IBM_EMAC_RXB=64
-CONFIG_IBM_EMAC_TXB=8
-CONFIG_IBM_EMAC_FGAP=8
-CONFIG_IBM_EMAC_SKBRES=0
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT 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=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 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_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC 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_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_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=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 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_IBM_IIC is not set
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 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_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 is not set
-
-#
-# 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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=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 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_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 is not set
-
-#
-# IBM 40x options
-#
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-CONFIG_OCP=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/beech_defconfig b/arch/ppc/configs/beech_defconfig
deleted file mode 100644
index 0bd671bdceb4..000000000000
--- a/arch/ppc/configs/beech_defconfig
+++ /dev/null
@@ -1,615 +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
-
-#
-# 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 is not set
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# 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_KMOD=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-# CONFIG_ASH is not set
-CONFIG_BEECH=y
-# CONFIG_CEDAR is not set
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-# CONFIG_OAK is not set
-# CONFIG_REDWOOD_4 is not set
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_TIVO is not set
-# CONFIG_WALNUT is not set
-CONFIG_IBM405_ERR77=y
-CONFIG_IBM405_ERR51=y
-CONFIG_IBM_OCP=y
-CONFIG_IBM_OPENBIOS=y
-CONFIG_405_DMA=y
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-CONFIG_NOT_COHERENT_CACHE=y
-
-#
-# Platform options
-#
-# CONFIG_PC_KEYBOARD is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# 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=0x00400000
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_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
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-# 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 is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_BEECH=y
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD 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
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET 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=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO 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 I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# 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
-
-#
-# Macintosh device drivers
-#
-
-#
-# 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_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_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-CONFIG_I2C_IBM_IIC=y
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB 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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# 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_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# 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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# IBM 40x options
-#
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-CONFIG_OCP=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/cedar_defconfig b/arch/ppc/configs/cedar_defconfig
deleted file mode 100644
index 5de8288a0673..000000000000
--- a/arch/ppc/configs/cedar_defconfig
+++ /dev/null
@@ -1,534 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-# CONFIG_ASH is not set
-# CONFIG_BEECH is not set
-CONFIG_CEDAR=y
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-# CONFIG_OAK is not set
-# CONFIG_REDWOOD_4 is not set
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_TIVO is not set
-# CONFIG_WALNUT is not set
-CONFIG_IBM405_ERR77=y
-CONFIG_IBM405_ERR51=y
-CONFIG_IBM_OCP=y
-CONFIG_NP405L=y
-CONFIG_BIOS_FIXUP=y
-CONFIG_IBM_OPENBIOS=y
-# CONFIG_405_DMA is not set
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-CONFIG_NOT_COHERENT_CACHE=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PC_KEYBOARD is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# 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=0x00400000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER 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=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_IBM_OCP_ALGO=y
-CONFIG_I2C_IBM_OCP_ADAP=y
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB 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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_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
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# IBM 40x options
-#
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-CONFIG_OCP=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/cpci690_defconfig b/arch/ppc/configs/cpci690_defconfig
index 53948793d9af..ff3f7e02ab0f 100644
--- a/arch/ppc/configs/cpci690_defconfig
+++ b/arch/ppc/configs/cpci690_defconfig
@@ -1,15 +1,17 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Fri Dec 3 15:56:10 2004
+# Linux kernel version: 2.6.13-mm1
+# Thu Sep 1 17:10:37 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
@@ -17,33 +19,38 @@ CONFIG_GENERIC_NVRAM=y
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=y
# CONFIG_SWAP is not set
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_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,38 +72,42 @@ CONFIG_6xx=y
# 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 is not set
+# CONFIG_KEXEC is not set
# CONFIG_CPU_FREQ is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_PPC_STD_MMU=y
# CONFIG_NOT_COHERENT_CACHE is not set
#
+# Performance-monitoring counters support
+#
+# CONFIG_PERFCTR is not set
+
+#
# Platform options
#
# CONFIG_PPC_MULTIPLATFORM is not set
# CONFIG_APUS is not set
# CONFIG_KATANA is not set
-# CONFIG_DMV182 is not set
# CONFIG_WILLOW is not set
CONFIG_CPCI690=y
-# CONFIG_PCORE is not set
# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_DB64360 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_PRPMC880 is not set
# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
+# CONFIG_RADSTONE_PPC7D is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
# CONFIG_EST8260 is not set
@@ -105,22 +116,41 @@ CONFIG_CPCI690=y
# 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_EV64360 is not set
+CONFIG_GT64260=y
+CONFIG_MV64X60=y
#
# Set bridge options
#
CONFIG_MV64X60_BASE=0xf1000000
CONFIG_MV64X60_NEW_BASE=0xf1000000
-CONFIG_GT64260=y
-CONFIG_MV64X60=y
# CONFIG_SMP is not set
+CONFIG_HIGHMEM=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttyMM0,9600 ip=on"
+CONFIG_CMDLINE="console=ttyMM0 ip=on"
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -129,7 +159,11 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
#
# Advanced setup
@@ -146,6 +180,76 @@ CONFIG_TASK_SIZE=0x80000000
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=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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_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
+# 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 is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
#
@@ -154,6 +258,7 @@ CONFIG_BOOT_LOAD=0x00800000
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -177,6 +282,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# 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
@@ -185,7 +291,6 @@ 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 is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -196,6 +301,7 @@ 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
@@ -205,6 +311,7 @@ CONFIG_IOSCHED_CFQ=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -215,6 +322,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -231,71 +339,8 @@ CONFIG_IOSCHED_CFQ=y
#
#
-# Networking support
+# Network device 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=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_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_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
-#
-# 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
@@ -308,6 +353,11 @@ CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -328,6 +378,7 @@ CONFIG_TULIP=y
# CONFIG_DE4X5 is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
@@ -337,7 +388,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -360,13 +410,18 @@ CONFIG_EEPRO100=y
# 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
@@ -390,6 +445,11 @@ CONFIG_EEPRO100=y
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE 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
#
# ISDN subsystem
@@ -419,14 +479,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -436,6 +488,12 @@ CONFIG_SOUND_GAMEPORT=y
# 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
@@ -455,6 +513,7 @@ CONFIG_SERIAL_MPSC=y
CONFIG_SERIAL_MPSC_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -483,6 +542,11 @@ CONFIG_GEN_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -493,10 +557,21 @@ CONFIG_GEN_RTC=y
# CONFIG_W1 is not set
#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
# Misc devices
#
#
+# Multimedia Capabilities Port drivers
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -518,6 +593,11 @@ CONFIG_GEN_RTC=y
CONFIG_DUMMY_CONSOLE=y
#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+
+#
# Sound
#
# CONFIG_SOUND is not set
@@ -525,35 +605,59 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# USB Gadget Support
#
+# CONFIG_USB_GADGET is not set
#
-# USB Gadget Support
+# MMC/SD Card support
#
-# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM 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_REISER4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
# 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
@@ -574,20 +678,18 @@ CONFIG_DNOTIFY=y
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_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
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ASFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -605,13 +707,14 @@ CONFIG_RAMFS=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_RPCSEC_GSS_KRB5=y
@@ -621,6 +724,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
#
# Partition Types
@@ -637,6 +741,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
@@ -648,7 +753,9 @@ CONFIG_CRC32=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SERIAL_TEXT_DEBUG is not set
#
@@ -669,6 +776,7 @@ CONFIG_CRYPTO_MD5=y
# 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=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
@@ -684,3 +792,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/ev64360_defconfig
index f10f5a6d2dae..de9bbb791db9 100644
--- a/arch/ppc/configs/k2_defconfig
+++ b/arch/ppc/configs/ev64360_defconfig
@@ -1,52 +1,60 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc5
+# Fri Aug 5 15:18:23 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_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
+CONFIG_LOCALVERSION=""
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_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
+# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=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
+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 is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
#
# Processor
@@ -57,21 +65,33 @@ CONFIG_6xx=y
# 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_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 is not set
+# CONFIG_PM is not set
CONFIG_PPC_STD_MMU=y
+CONFIG_NOT_COHERENT_CACHE=y
#
# Platform options
#
# CONFIG_PPC_MULTIPLATFORM is not set
# 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_EV64260 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
@@ -79,24 +99,51 @@ CONFIG_PPC_STD_MMU=y
# 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=y
+# 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_RPX6 is not set
+# CONFIG_RPX8260 is not set
# CONFIG_TQM8260 is not set
-CONFIG_PPC_GEN550=y
-# CONFIG_CPC710_DATA_GATHERING 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_EV64360=y
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=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_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=y
CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
+CONFIG_CMDLINE="console=ttyMM0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -108,31 +155,182 @@ CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_NAMES is not set
#
-# Advanced setup
+# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_ADVANCED_OPTIONS is not set
+# CONFIG_PCCARD is not set
#
-# Default settings for advanced configuration options are used
+# 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 is not set
CONFIG_TASK_SIZE=0x80000000
+# CONFIG_CONSISTENT_START_BOOL is not set
+CONFIG_CONSISTENT_START=0xff100000
+# CONFIG_CONSISTENT_SIZE_BOOL is not set
+CONFIG_CONSISTENT_SIZE=0x00200000
+# CONFIG_BOOT_LOAD_BOOL is not set
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=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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
+# 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_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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
+
+#
# Device Drivers
#
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 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 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xff000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# 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=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD 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
#
# Parallel port support
@@ -151,72 +349,32 @@ CONFIG_BOOT_LOAD=0x00800000
# 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_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# 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=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE 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_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-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_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_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_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX 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
+# CONFIG_IDE is not set
#
# SCSI device support
@@ -248,122 +406,8 @@ CONFIG_BLK_DEV_IDEDMA=y
#
#
-# Networking support
-#
-CONFIG_NET=y
-
+# Network device support
#
-# 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 is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# 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 is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-# CONFIG_IP_NF_MATCH_IPRANGE is not set
-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 is not set
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-# CONFIG_IP_NF_MATCH_LENGTH is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-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 is not set
-# CONFIG_IP_NF_TARGET_SAME is not set
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_FTP=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 is not set
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IP_NF_RAW 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
@@ -378,38 +422,7 @@ CONFIG_NETDEVICES=y
#
# Ethernet (10 or 100Mbit)
#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# 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 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_EEPRO100_PIO 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_ETHERNET is not set
#
# Ethernet (1000 Mbit)
@@ -421,8 +434,14 @@ CONFIG_EEPRO100=y
# 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_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+# CONFIG_MV643XX_ETH_1 is not set
+# CONFIG_MV643XX_ETH_2 is not set
#
# Ethernet (10000 Mbit)
@@ -448,9 +467,10 @@ CONFIG_EEPRO100=y
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_RCPCI 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
@@ -465,47 +485,59 @@ CONFIG_EEPRO100=y
#
# Input device support
#
-# CONFIG_INPUT is not set
+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 is not set
+# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
+# Input Device Drivers
#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
+# 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
#
-# Input Device Drivers
+# Hardware I/O ports
#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
#
# Character devices
#
-# CONFIG_VT is not set
+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=2
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -526,15 +558,31 @@ CONFIG_GEN_RTC=y
#
# 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
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -556,6 +604,12 @@ CONFIG_GEN_RTC=y
# CONFIG_FB is not set
#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
# Sound
#
# CONFIG_SOUND is not set
@@ -563,6 +617,8 @@ CONFIG_GEN_RTC=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB is not set
#
@@ -571,18 +627,40 @@ CONFIG_GEN_RTC=y
# 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 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
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# 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
@@ -595,7 +673,8 @@ CONFIG_EXT2_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -604,9 +683,9 @@ CONFIG_EXT2_FS=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
@@ -620,6 +699,14 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# 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
@@ -631,20 +718,22 @@ CONFIG_RAMFS=y
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+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_EXPORTFS is not set
+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_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -661,20 +750,35 @@ CONFIG_MSDOS_PARTITION=y
#
# Library routines
#
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+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 is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_LOG_BUF_SHIFT=14
#
# 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/katana_defconfig b/arch/ppc/configs/katana_defconfig
index f0b0d5720154..0f3bb9af9c22 100644
--- a/arch/ppc/configs/katana_defconfig
+++ b/arch/ppc/configs/katana_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Tue Mar 8 17:31:00 2005
+# Linux kernel version: 2.6.13-mm1
+# Thu Sep 1 17:16:03 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ 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
@@ -18,28 +19,31 @@ CONFIG_GENERIC_NVRAM=y
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=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_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=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
@@ -68,15 +72,23 @@ CONFIG_6xx=y
# 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 is not set
+# CONFIG_KEXEC is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_83xx is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_PPC_STD_MMU=y
CONFIG_NOT_COHERENT_CACHE=y
#
+# Performance-monitoring counters support
+#
+# CONFIG_PERFCTR is not set
+
+#
# Platform options
#
# CONFIG_PPC_MULTIPLATFORM is not set
@@ -84,21 +96,18 @@ CONFIG_NOT_COHERENT_CACHE=y
CONFIG_KATANA=y
# 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
@@ -109,6 +118,8 @@ CONFIG_KATANA=y
# CONFIG_ADS8272 is not set
# CONFIG_PQ2FADS is not set
# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+# CONFIG_EV64360 is not set
CONFIG_MV64360=y
CONFIG_MV64X60=y
@@ -118,12 +129,28 @@ CONFIG_MV64X60=y
CONFIG_MV64X60_BASE=0xf8100000
CONFIG_MV64X60_NEW_BASE=0xf8100000
# CONFIG_SMP is not set
+CONFIG_HIGHMEM=y
+# 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_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttyMM0,9600 ip=on"
+CONFIG_CMDLINE="console=ttyMM0 ip=on"
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -132,7 +159,6 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -140,13 +166,10 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# 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
@@ -162,6 +185,76 @@ CONFIG_CONSISTENT_SIZE=0x00400000
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=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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_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
+# 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 is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
#
@@ -177,8 +270,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -212,6 +305,7 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=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
@@ -219,7 +313,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -229,6 +322,7 @@ CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0xe0000000
CONFIG_MTD_PHYSMAP_LEN=0x0
CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -278,7 +372,6 @@ 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 is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -299,6 +392,7 @@ CONFIG_IOSCHED_CFQ=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -309,6 +403,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -325,71 +420,8 @@ CONFIG_IOSCHED_CFQ=y
#
#
-# 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=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_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_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
@@ -402,6 +434,11 @@ CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -422,6 +459,7 @@ CONFIG_TULIP=y
# CONFIG_DE4X5 is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
@@ -448,14 +486,19 @@ CONFIG_E100=y
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
CONFIG_MV643XX_ETH=y
CONFIG_MV643XX_ETH_0=y
CONFIG_MV643XX_ETH_1=y
@@ -464,6 +507,7 @@ CONFIG_MV643XX_ETH_2=y
#
# Ethernet (10000 Mbit)
#
+# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
@@ -487,6 +531,11 @@ CONFIG_MV643XX_ETH_2=y
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE 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
#
# ISDN subsystem
@@ -516,14 +565,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -533,6 +574,12 @@ CONFIG_SOUND_GAMEPORT=y
# 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
@@ -552,6 +599,7 @@ CONFIG_SERIAL_MPSC=y
CONFIG_SERIAL_MPSC_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -580,6 +628,11 @@ CONFIG_GEN_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -602,11 +655,10 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 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
@@ -621,14 +673,39 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MV64XXX=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-# CONFIG_I2C_SENSOR is not set
+# 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=y
+# 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=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_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -644,36 +721,26 @@ CONFIG_I2C_MV64XXX=y
# 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_SMSC47B397 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_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
#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-CONFIG_SENSORS_M41T00=y
-# 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
+# Misc devices
#
-# CONFIG_W1 is not set
#
-# Misc devices
+# Multimedia Capabilities Port drivers
#
#
@@ -698,6 +765,11 @@ CONFIG_SENSORS_M41T00=y
CONFIG_DUMMY_CONSOLE=y
#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+
+#
# Sound
#
# CONFIG_SOUND is not set
@@ -705,13 +777,9 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -729,25 +797,39 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_INFINIBAND is not set
#
+# SN Devices
+#
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM 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_REISER4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
#
# 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
@@ -768,20 +850,18 @@ CONFIG_DNOTIFY=y
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_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
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ASFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -801,12 +881,14 @@ CONFIG_RAMFS=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -815,6 +897,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
@@ -831,6 +914,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
@@ -842,8 +926,10 @@ CONFIG_CRC32=y
#
# Kernel hacking
#
-# CONFIG_DEBUG_KERNEL is not set
# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SERIAL_TEXT_DEBUG is not set
#
# Security options
diff --git a/arch/ppc/configs/mcpn765_defconfig b/arch/ppc/configs/mcpn765_defconfig
deleted file mode 100644
index 899e89a9ea6a..000000000000
--- a/arch/ppc/configs/mcpn765_defconfig
+++ /dev/null
@@ -1,579 +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 is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_KMOD is not set
-
-#
-# 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=y
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-# CONFIG_PPC_MULTIPLATFORM is not set
-# 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=y
-# 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_GEN550=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 is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
-
-#
-# Bus options
-#
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
-
-#
-# 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
-#
-
-#
-# 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
-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 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_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# 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 is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC 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_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 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_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-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_SCSI 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
-#
-
-#
-# 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 is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=y
-# CONFIG_TULIP_MMIO is not set
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 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_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT 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 is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# 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_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_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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_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 is not set
-
-#
-# 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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig
deleted file mode 100644
index 321659b5505f..000000000000
--- a/arch/ppc/configs/menf1_defconfig
+++ /dev/null
@@ -1,621 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-
-#
-# IBM 4xx options
-#
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-CONFIG_MENF1=y
-# 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_MPC10X_STORE_GATHERING=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
-
-#
-# 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
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# 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
-# CONFIG_BLK_DEV_UMEM 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_INITRD is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O 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_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG 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=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=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_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_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=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_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=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_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# 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 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 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_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_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 is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/mpc8560_ads_defconfig b/arch/ppc/configs/mpc8560_ads_defconfig
index 38a343c9056a..f834fb541ad5 100644
--- a/arch/ppc/configs/mpc8560_ads_defconfig
+++ b/arch/ppc/configs/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1
-# Thu Jan 20 01:24:56 2005
+# Linux kernel version: 2.6.13-rc6
+# Thu Aug 11 18:14:45 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ 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
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -29,12 +31,14 @@ CONFIG_SYSVIPC=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_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ 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
@@ -59,12 +64,16 @@ CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_POWER3 is not set
# CONFIG_POWER4 is not set
# CONFIG_8xx is not set
+# CONFIG_E200 is not set
CONFIG_E500=y
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
CONFIG_MATH_EMULATION=y
+# CONFIG_KEXEC is not set
# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
CONFIG_85xx=y
CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -72,9 +81,11 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
# Freescale 85xx options
#
# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8548_CDS is not set
# CONFIG_MPC8555_CDS is not set
CONFIG_MPC8560_ADS=y
# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
CONFIG_MPC8560=y
#
@@ -83,11 +94,25 @@ CONFIG_MPC8560=y
CONFIG_CPM2=y
# CONFIG_PC_KEYBOARD is not set
# CONFIG_SMP is not set
-# CONFIG_PREEMPT 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 is not set
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -103,10 +128,6 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -121,6 +142,69 @@ CONFIG_TASK_SIZE=0x80000000
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=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_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
+# 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_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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
+
+#
# Device Drivers
#
@@ -193,6 +277,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -209,71 +294,8 @@ CONFIG_IOSCHED_CFQ=y
#
#
-# 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=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
+# Network device support
#
-# 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
-#
-# 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
@@ -311,8 +333,10 @@ CONFIG_MII=y
# 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_TIGON3 is not set
+# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
@@ -342,6 +366,8 @@ CONFIG_GFAR_NAPI=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
@@ -368,14 +394,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -385,6 +403,12 @@ CONFIG_SOUND_GAMEPORT=y
# 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
@@ -403,11 +427,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_SERIAL_CPM_SCC1=y
-# CONFIG_SERIAL_CPM_SCC2 is not set
+CONFIG_SERIAL_CPM_SCC2=y
# CONFIG_SERIAL_CPM_SCC3 is not set
-CONFIG_SERIAL_CPM_SCC4=y
+# CONFIG_SERIAL_CPM_SCC4 is not set
# CONFIG_SERIAL_CPM_SMC1 is not set
# CONFIG_SERIAL_CPM_SMC2 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -436,6 +461,11 @@ CONFIG_GEN_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -458,11 +488,11 @@ CONFIG_I2C_CHARDEV=y
# 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_ISA is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 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
@@ -473,19 +503,46 @@ CONFIG_I2C_MPC=y
# 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
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-# CONFIG_I2C_SENSOR is not set
+# 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=y
# 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
@@ -496,31 +553,18 @@ CONFIG_I2C_MPC=y
# 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_SMSC47B397 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_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_SENSORS_RTC8564 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
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -540,7 +584,6 @@ CONFIG_I2C_MPC=y
# Graphics support
#
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -550,13 +593,9 @@ CONFIG_I2C_MPC=y
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -574,10 +613,15 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_INFINIBAND is not set
#
+# SN Devices
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -587,9 +631,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# 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
@@ -614,7 +664,6 @@ CONFIG_DNOTIFY=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
@@ -648,7 +697,7 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -700,7 +749,9 @@ CONFIG_CRC32=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_KGDB_CONSOLE is not set
#
diff --git a/arch/ppc/configs/oak_defconfig b/arch/ppc/configs/oak_defconfig
deleted file mode 100644
index 366cc480cea3..000000000000
--- a/arch/ppc/configs/oak_defconfig
+++ /dev/null
@@ -1,485 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-# CONFIG_ASH is not set
-# CONFIG_BEECH is not set
-# CONFIG_CEDAR is not set
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-CONFIG_OAK=y
-# CONFIG_REDWOOD_4 is not set
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_TIVO is not set
-# CONFIG_WALNUT is not set
-CONFIG_IBM405_ERR51=y
-CONFIG_403GCX=y
-# CONFIG_405_DMA is not set
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-CONFIG_NOT_COHERENT_CACHE=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_PC_KEYBOARD is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# 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=0x00400000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER 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=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_OAKNET=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB 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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# IBM 40x options
-#
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pcore_defconfig b/arch/ppc/configs/pcore_defconfig
deleted file mode 100644
index ed34405a7574..000000000000
--- a/arch/ppc/configs/pcore_defconfig
+++ /dev/null
@@ -1,716 +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=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-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=y
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-CONFIG_PCORE=y
-# 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_GEN550=y
-CONFIG_FORCE=y
-# CONFIG_MPC10X_STORE_GATHERING is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
-
-#
-# Bus options
-#
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
-
-#
-# 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
-#
-
-#
-# 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
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP 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 is not set
-
-#
-# 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 is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# 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 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
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID 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_ADVANSYS 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_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_IPS is not set
-# CONFIG_SCSI_INIA100 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_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_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
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-
-#
-# 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=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_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
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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 is not set
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-# CONFIG_IP_NF_MATCH_IPRANGE is not set
-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 is not set
-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 is not set
-# CONFIG_IP_NF_TARGET_SAME is not set
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=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 is not set
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q 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_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-CONFIG_NET_TULIP=y
-# CONFIG_DE2104X is not set
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 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_EEPRO100_PIO 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_SIS190 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT 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 is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# 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_NR_UARTS=2
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_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 is not set
-
-#
-# 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=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_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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=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 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-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_INTERMEZZO_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 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/rainier_defconfig b/arch/ppc/configs/rainier_defconfig
deleted file mode 100644
index 4d4fcdc61bb7..000000000000
--- a/arch/ppc/configs/rainier_defconfig
+++ /dev/null
@@ -1,599 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-# CONFIG_ASH is not set
-# CONFIG_BEECH is not set
-# CONFIG_CEDAR is not set
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-# CONFIG_OAK is not set
-# CONFIG_REDWOOD_4 is not set
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_TIVO is not set
-CONFIG_WALNUT=y
-CONFIG_IBM405_ERR77=y
-CONFIG_IBM405_ERR51=y
-CONFIG_IBM_OCP=y
-CONFIG_BIOS_FIXUP=y
-CONFIG_405GP=y
-CONFIG_IBM_OPENBIOS=y
-CONFIG_405_DMA=y
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-CONFIG_NOT_COHERENT_CACHE=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-# CONFIG_PC_KEYBOARD is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# 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=0x00400000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# 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
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O 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_NETFILTER 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=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# 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_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO 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_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# 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
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_IBM_OCP_ALGO is not set
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-# 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_PIIX4 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=y
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB 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=y
-# 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 is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_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_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# IBM 40x options
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-CONFIG_OCP=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/redwood_defconfig b/arch/ppc/configs/redwood_defconfig
deleted file mode 100644
index 4aa348dcf22c..000000000000
--- a/arch/ppc/configs/redwood_defconfig
+++ /dev/null
@@ -1,540 +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
-
-#
-# 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_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-CONFIG_40x=y
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_4xx=y
-
-#
-# IBM 4xx options
-#
-# CONFIG_ASH is not set
-# CONFIG_BEECH is not set
-# CONFIG_CEDAR is not set
-# CONFIG_CPCI405 is not set
-# CONFIG_EP405 is not set
-# CONFIG_OAK is not set
-CONFIG_REDWOOD_4=y
-# CONFIG_REDWOOD_5 is not set
-# CONFIG_REDWOOD_6 is not set
-# CONFIG_SYCAMORE is not set
-# CONFIG_TIVO is not set
-# CONFIG_WALNUT is not set
-CONFIG_IBM405_ERR77=y
-CONFIG_IBM405_ERR51=y
-CONFIG_IBM_OCP=y
-CONFIG_STB03xxx=y
-CONFIG_IBM_OPENBIOS=y
-# CONFIG_405_DMA is not set
-# CONFIG_PM is not set
-CONFIG_UART0_TTYS0=y
-# CONFIG_UART0_TTYS1 is not set
-# CONFIG_SERIAL_SICC is not set
-CONFIG_NOT_COHERENT_CACHE=y
-
-#
-# Platform options
-#
-# CONFIG_PC_KEYBOARD is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-# CONFIG_PCI is not set
-# CONFIG_PCI_DOMAINS is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# 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=0x00400000
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET 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=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q 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_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_OAKNET=y
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB 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 I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# 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
-
-#
-# Macintosh device drivers
-#
-
-#
-# 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_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_UNIX98_PTYS is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-CONFIG_I2C_IBM_IIC=y
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE 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 is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_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 is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-# CONFIG_DEVFS_FS 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_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_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# IBM 40x options
-#
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_SERIAL_TEXT_DEBUG=y
-CONFIG_OCP=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index b1457a8a9c0f..1fb92f16acd6 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -15,8 +15,9 @@ extra-y += vmlinux.lds
obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
process.o signal.o ptrace.o align.o \
semaphore.o syscalls.o setup.o \
- cputable.o ppc_htab.o perfmon.o
+ cputable.o ppc_htab.o
obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_E500) += perfmon.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
obj-$(CONFIG_POWER4) += cpu_setup_power4.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index 468721d9ebd2..ba396438ede3 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -12,10 +12,9 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
-#include <asm/ppc_asm.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cache.h>
_GLOBAL(__setup_cpu_601)
@@ -249,8 +248,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
sync
isync
- /* Enable L2 HW prefetch
+ /* Enable L2 HW prefetch, if L2 is enabled
*/
+ mfspr r3,SPRN_L2CR
+ andis. r3,r3,L2CR_L2E@h
+ beqlr
mfspr r3,SPRN_MSSCR0
ori r3,r3,3
sync
@@ -324,6 +326,7 @@ _GLOBAL(__save_cpu_setup)
cmplwi cr4,r3,0x8002 /* 7457 */
cmplwi cr5,r3,0x8003 /* 7447A */
cmplwi cr6,r3,0x7000 /* 750FX */
+ cmplwi cr7,r3,0x8004 /* 7448 */
/* cr1 is 7400 || 7410 */
cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
/* cr0 is 74xx */
@@ -331,6 +334,7 @@ _GLOBAL(__save_cpu_setup)
cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
cror 4*cr0+eq,4*cr0+eq,4*cr5+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr7+eq
bne 1f
/* Backup 74xx specific regs */
mfspr r4,SPRN_MSSCR0
@@ -393,6 +397,7 @@ _GLOBAL(__restore_cpu_setup)
cmplwi cr4,r3,0x8002 /* 7457 */
cmplwi cr5,r3,0x8003 /* 7447A */
cmplwi cr6,r3,0x7000 /* 750FX */
+ cmplwi cr7,r3,0x8004 /* 7448 */
/* cr1 is 7400 || 7410 */
cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
/* cr0 is 74xx */
@@ -400,6 +405,7 @@ _GLOBAL(__restore_cpu_setup)
cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
cror 4*cr0+eq,4*cr0+eq,4*cr5+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr7+eq
bne 2f
/* Restore 74xx specific regs */
lwz r4,CS_MSSCR0(r5)
diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
index f2ea1a990f17..7e4fbb653724 100644
--- a/arch/ppc/kernel/cpu_setup_power4.S
+++ b/arch/ppc/kernel/cpu_setup_power4.S
@@ -14,8 +14,7 @@
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/cputable.h>
-#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cache.h>
_GLOBAL(__970_cpu_preinit)
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index 8a3d74f2531e..546e1ea4cafa 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -198,10 +198,10 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750
},
- { /* 745/755 */
- .pvr_mask = 0xfffff000,
- .pvr_value = 0x00083000,
- .cpu_name = "745/755",
+ { /* 750CX (80100 and 8010x?) */
+ .pvr_mask = 0xfffffff0,
+ .pvr_value = 0x00080100,
+ .cpu_name = "750CX",
.cpu_features = CPU_FTR_COMMON |
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
@@ -210,11 +210,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750cx
},
- { /* 750CX (80100 and 8010x?) */
+ { /* 750CX (82201 and 82202) */
.pvr_mask = 0xfffffff0,
- .pvr_value = 0x00080100,
+ .pvr_value = 0x00082200,
.cpu_name = "750CX",
.cpu_features = CPU_FTR_COMMON |
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
@@ -226,10 +226,10 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx
},
- { /* 750CX (82201 and 82202) */
+ { /* 750CXe (82214) */
.pvr_mask = 0xfffffff0,
- .pvr_value = 0x00082200,
- .cpu_name = "750CX",
+ .pvr_value = 0x00082210,
+ .cpu_name = "750CXe",
.cpu_features = CPU_FTR_COMMON |
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
@@ -240,9 +240,9 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx
},
- { /* 750CXe (82214) */
- .pvr_mask = 0xfffffff0,
- .pvr_value = 0x00082210,
+ { /* 750CXe "Gekko" (83214) */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x00083214,
.cpu_name = "750CXe",
.cpu_features = CPU_FTR_COMMON |
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
@@ -254,6 +254,20 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx
},
+ { /* 745/755 */
+ .pvr_mask = 0xfffff000,
+ .pvr_value = 0x00083000,
+ .cpu_name = "745/755",
+ .cpu_features = 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_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
{ /* 750FX rev 1.x */
.pvr_mask = 0xffffff00,
.pvr_value = 0x70000100,
@@ -536,6 +550,22 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
},
+ { /* 7448 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80040000,
+ .cpu_name = "7448",
+ .cpu_features = 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_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
.pvr_mask = 0x7fff0000,
.pvr_value = 0x00810000,
@@ -922,6 +952,26 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
},
+ { /* 440GX Rev. F */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x50000894,
+ .cpu_name = "440GX Rev. F",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 440SP Rev. A */
+ .pvr_mask = 0xff000fff,
+ .pvr_value = 0x53000891,
+ .cpu_name = "440SP Rev. A",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
#endif /* CONFIG_44x */
#ifdef CONFIG_FSL_BOOKE
{ /* e200z5 */
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
index e0c631cf96b0..b566d982806c 100644
--- a/arch/ppc/kernel/dma-mapping.c
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -393,7 +393,7 @@ EXPORT_SYMBOL(__dma_sync);
* __dma_sync_page() implementation for systems using highmem.
* In this case, each page of a buffer must be kmapped/kunmapped
* in order to have a virtual address for __dma_sync(). This must
- * not sleep so kmap_atmomic()/kunmap_atomic() are used.
+ * not sleep so kmap_atomic()/kunmap_atomic() are used.
*
* Note: yes, it is possible and correct to have a buffer extend
* beyond the first page.
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index cb83045e2edf..03d4886869f3 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -29,7 +29,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#undef SHOW_SYSCALLS
diff --git a/arch/ppc/kernel/find_name.c b/arch/ppc/kernel/find_name.c
deleted file mode 100644
index 3c0fa8e0c077..000000000000
--- a/arch/ppc/kernel/find_name.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <stdio.h>
-#include <asm/page.h>
-#include <sys/mman.h>
-#include <strings.h>
-/*
- * Finds a given address in the System.map and prints it out
- * with its neighbors. -- Cort
- */
-
-int main(int argc, char **argv)
-{
- unsigned long addr, cmp, i;
- FILE *f;
- char s[256], last[256];
-
- if ( argc < 2 )
- {
- fprintf(stderr, "Usage: %s <address>\n", argv[0]);
- return -1;
- }
-
- for ( i = 1 ; argv[i] ; i++ )
- {
- sscanf( argv[i], "%0lx", &addr );
- /* adjust if addr is relative to kernelbase */
- if ( addr < PAGE_OFFSET )
- addr += PAGE_OFFSET;
-
- if ( (f = fopen( "System.map", "r" )) == NULL )
- {
- perror("fopen()\n");
- exit(-1);
- }
-
- while ( !feof(f) )
- {
- fgets(s, 255 , f);
- sscanf( s, "%0lx", &cmp );
- if ( addr < cmp )
- break;
- strcpy( last, s);
- }
-
- printf( "%s%s", last, s );
- }
- fclose(f);
- return 0;
-}
diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S
index 6189b26f640f..665d7d34304c 100644
--- a/arch/ppc/kernel/fpu.S
+++ b/arch/ppc/kernel/fpu.S
@@ -18,7 +18,7 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/*
* This task wants to use the FPU now.
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index a931d773715f..1960fb8c259c 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -31,7 +31,7 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_APUS
#include <asm/amigappc.h>
@@ -1023,23 +1023,21 @@ __secondary_start_gemini:
andc r4,r4,r3
mtspr SPRN_HID0,r4
sync
- bl gemini_prom_init
b __secondary_start
#endif /* CONFIG_GEMINI */
- .globl __secondary_start_psurge
-__secondary_start_psurge:
- li r24,1 /* cpu # */
- b __secondary_start_psurge99
- .globl __secondary_start_psurge2
-__secondary_start_psurge2:
- li r24,2 /* cpu # */
- b __secondary_start_psurge99
- .globl __secondary_start_psurge3
-__secondary_start_psurge3:
- li r24,3 /* cpu # */
- b __secondary_start_psurge99
-__secondary_start_psurge99:
- /* we come in here with IR=0 and DR=1, and DBAT 0
+
+ .globl __secondary_start_pmac_0
+__secondary_start_pmac_0:
+ /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
+ li r24,0
+ b 1f
+ li r24,1
+ b 1f
+ li r24,2
+ b 1f
+ li r24,3
+1:
+ /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
set to map the 0xf0000000 - 0xffffffff region */
mfmsr r0
rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 69ff3a9961e8..599245b0407e 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -40,7 +40,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include "head_booke.h"
@@ -462,7 +462,11 @@ interrupt_base:
/* Watchdog Timer Interrupt */
/* TODO: Add watchdog support */
+#ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)
+#else
CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+#endif
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError)
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index 23fb51819ba5..8562b807b37c 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -40,7 +40,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* As with the other PowerPC ports, it is expected that when code
* execution begins here, the following registers contain valid, yet
@@ -448,9 +448,12 @@ label:
/* 0x1020 - Watchdog Timer (WDT) Exception
*/
-
+#ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x1020, WDTException, WatchdogException)
+#else
CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
#endif
+#endif
/* 0x1100 - Data TLB Miss Exception
* As the name implies, translation is not in the MMU, so search the
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index eb18cadb3755..cb1a3a54a026 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -30,7 +30,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* Macro to make the code more readable. */
#ifdef CONFIG_8xx_CPU6
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index eb804b7a3cb2..8e52e8408316 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -41,7 +41,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include "head_booke.h"
/* As with the other PowerPC ports, it is expected that when code
@@ -564,8 +564,11 @@ interrupt_base:
EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
/* Watchdog Timer Interrupt */
- /* TODO: Add watchdog support */
+#ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
+#else
CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+#endif
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError)
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 53547b6de45b..fba29c876b62 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -22,6 +22,7 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
+#include <linux/cpu.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -35,6 +36,7 @@
void default_idle(void)
{
void (*powersave)(void);
+ int cpu = smp_processor_id();
powersave = ppc_md.power_save;
@@ -44,7 +46,7 @@ void default_idle(void)
#ifdef CONFIG_SMP
else {
set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched())
+ while (!need_resched() && !cpu_is_offline(cpu))
barrier();
clear_thread_flag(TIF_POLLING_NRFLAG);
}
@@ -52,6 +54,8 @@ void default_idle(void)
}
if (need_resched())
schedule();
+ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+ cpu_die();
}
/*
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
index 25d009c75f7b..1a2194cf6828 100644
--- a/arch/ppc/kernel/idle_6xx.S
+++ b/arch/ppc/kernel/idle_6xx.S
@@ -20,7 +20,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#undef DEBUG
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
index 73a58ff03900..cc0d535365cd 100644
--- a/arch/ppc/kernel/idle_power4.S
+++ b/arch/ppc/kernel/idle_power4.S
@@ -20,7 +20,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#undef DEBUG
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
index c39441048266..861115249b35 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/ppc/kernel/l2cr.S
@@ -156,6 +156,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
The bit moved on the 7450.....
****/
+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_SPEC7450)
+
/* TODO: use HW flush assist when available */
lis r4,0x0002
@@ -230,7 +250,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
oris r3,r3,0x8000
mtspr SPRN_L2CR,r3
sync
-
+
+ /* Enable L2 HW prefetch on 744x/745x */
+BEGIN_FTR_SECTION
+ mfspr r3,SPRN_MSSCR0
+ ori r3,r3,3
+ sync
+ mtspr SPRN_MSSCR0,r3
+ sync
+ isync
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
4:
/* Restore HID0[DPM] to whatever it was before */
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index ce71b4a01585..90d917d2e856 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -23,7 +23,7 @@
#include <asm/mmu.h>
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 7b3586a3bf30..854e45beb387 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -80,7 +80,6 @@ fixup_broken_pcnet32(struct pci_dev* dev)
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
dev->vendor = PCI_VENDOR_ID_AMD;
pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
- pci_name_device(dev);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index e7d40cc6c1b6..88f6bb7b6964 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -51,9 +51,6 @@
#include <asm/commproc.h>
#endif
-/* Tell string.h we don't want memcpy etc. as cpp defines */
-#define EXPORT_SYMTAB_STROPS
-
extern void transfer_to_handler(void);
extern void do_IRQ(struct pt_regs *regs);
extern void MachineCheckException(struct pt_regs *regs);
@@ -263,6 +260,7 @@ EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(cacheable_memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memscan);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 929e5d1cc7fe..545cfd0fab59 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -41,7 +41,11 @@
#include <asm/xmon.h>
#include <asm/ocp.h>
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
+#define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \
+ defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
+ defined(CONFIG_PPC_MPC52xx))
+
+#if USES_PPC_SYS
#include <asm/ppc_sys.h>
#endif
@@ -241,7 +245,7 @@ int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "bogomips\t: %lu.%02lu\n",
lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
+#if USES_PPC_SYS
if (cur_ppc_sys_spec->ppc_sys_name)
seq_printf(m, "chipset\t\t: %s\n",
cur_ppc_sys_spec->ppc_sys_name);
@@ -615,6 +619,26 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
if (ppc_md.progress)
ppc_md.progress("id mach(): done", 0x200);
}
+#ifdef CONFIG_BOOKE_WDT
+/* Checks wdt=x and wdt_period=xx command-line option */
+int __init early_parse_wdt(char *p)
+{
+ if (p && strncmp(p, "0", 1) != 0)
+ booke_wdt_enabled = 1;
+
+ return 0;
+}
+early_param("wdt", early_parse_wdt);
+
+int __init early_parse_wdt_period (char *p)
+{
+ if (p)
+ booke_wdt_period = simple_strtoul(p, NULL, 0);
+
+ return 0;
+}
+early_param("wdt_period", early_parse_wdt_period);
+#endif /* CONFIG_BOOKE_WDT */
/* Checks "l2cr=xxxx" command-line option */
int __init ppc_setup_l2cr(char *str)
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 8aaeb6f4e750..2244bf91e593 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -759,13 +759,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
else
handle_signal(signr, &ka, &info, oldset, regs, newsp);
- if (!(ka.sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
return 1;
}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e70b587b9e51..726fe7ce1747 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -45,6 +45,7 @@ cpumask_t cpu_online_map;
cpumask_t cpu_possible_map;
int smp_hw_index[NR_CPUS];
struct thread_info *secondary_ti;
+static struct task_struct *idle_tasks[NR_CPUS];
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
@@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- int num_cpus, i;
+ int num_cpus, i, cpu;
+ struct task_struct *p;
/* Fixup boot cpu */
smp_store_cpu_info(smp_processor_id());
@@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (smp_ops->space_timers)
smp_ops->space_timers(num_cpus);
+
+ for_each_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ /* create a process for the processor */
+ p = fork_idle(cpu);
+ if (IS_ERR(p))
+ panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+ p->thread_info->cpu = cpu;
+ idle_tasks[cpu] = p;
+ }
}
void __devinit smp_prepare_boot_cpu(void)
@@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused)
set_dec(tb_ticks_per_jiffy);
cpu_callin_map[cpu] = 1;
- printk("CPU %i done callin...\n", cpu);
+ printk("CPU %d done callin...\n", cpu);
smp_ops->setup_cpu(cpu);
- printk("CPU %i done setup...\n", cpu);
- local_irq_enable();
+ printk("CPU %d done setup...\n", cpu);
smp_ops->take_timebase();
- printk("CPU %i done timebase take...\n", cpu);
+ printk("CPU %d done timebase take...\n", cpu);
+
+ spin_lock(&call_lock);
+ cpu_set(cpu, cpu_online_map);
+ spin_unlock(&call_lock);
+
+ local_irq_enable();
cpu_idle();
return 0;
@@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused)
int __cpu_up(unsigned int cpu)
{
- struct task_struct *p;
char buf[32];
int c;
- /* create a process for the processor */
- /* only regs.msr is actually used, and 0 is OK for it */
- p = fork_idle(cpu);
- if (IS_ERR(p))
- panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
- secondary_ti = p->thread_info;
- p->thread_info->cpu = cpu;
+ secondary_ti = idle_tasks[cpu]->thread_info;
+ mb();
/*
* There was a cache flush loop here to flush the cache
@@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu)
printk("Processor %d found.\n", cpu);
smp_ops->give_timebase();
- cpu_set(cpu, cpu_online_map);
+
+ /* Wait until cpu puts itself in the online map */
+ while (!cpu_online(cpu))
+ cpu_relax();
+
return 0;
}
diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S
index 55148bb88d39..69773cc1a85f 100644
--- a/arch/ppc/kernel/swsusp.S
+++ b/arch/ppc/kernel/swsusp.S
@@ -5,7 +5,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/*
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 124313ce3c09..127f040de9de 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -41,10 +41,6 @@
#include <asm/ipc.h>
#include <asm/semaphore.h>
-void
-check_bugs(void)
-{
-}
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
diff --git a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
index fe8bb634ead0..26bd8ea35a4e 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/ppc/kernel/temp.c
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/reg.h>
#include <asm/nvram.h>
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index bf4ddca5e853..22d7fd1e0aea 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -58,7 +58,6 @@
#include <linux/init.h>
#include <linux/profile.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/nvram.h>
#include <asm/cache.h>
@@ -169,7 +168,7 @@ void timer_interrupt(struct pt_regs * regs)
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
- if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
+ if ( ppc_md.set_rtc_time && ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ &&
jiffies - wall_jiffies == 1) {
@@ -271,10 +270,7 @@ int do_settimeofday(struct timespec *tv)
*/
last_rtc_update = new_sec - 658;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irqrestore(&xtime_lock, flags);
clock_was_set();
return 0;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 9e6ae5696650..961ede87be72 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
info.si_code = code;
info.si_addr = (void __user *) addr;
force_sig_info(signr, &info, current);
+
+ /*
+ * Init gets no signals that it doesn't have a handler for.
+ * That's all very well, but if it has caused a synchronous
+ * exception and we ignore the resulting signal, it will just
+ * generate the same exception over and over again and we get
+ * nowhere. Better to kill it and let the kernel panic.
+ */
+ if (current->pid == 1) {
+ __sighandler_t handler;
+
+ spin_lock_irq(&current->sighand->siglock);
+ handler = current->sighand->action[signr-1].sa.sa_handler;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (handler == SIG_DFL) {
+ /* init has generated a synchronous exception
+ and it doesn't have a handler for the signal */
+ printk(KERN_CRIT "init has generated signal %d "
+ "but has no handler for it\n", signr);
+ do_exit(signr);
+ }
+ }
}
/*
@@ -849,10 +871,12 @@ void AltivecAssistException(struct pt_regs *regs)
}
#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_E500
void PerformanceMonitorException(struct pt_regs *regs)
{
perf_irq(regs);
}
+#endif
#ifdef CONFIG_FSL_BOOKE
void CacheLockingException(struct pt_regs *regs, unsigned long address,
@@ -904,6 +928,25 @@ void SPEFloatingPointException(struct pt_regs *regs)
}
#endif
+#ifdef CONFIG_BOOKE_WDT
+/*
+ * Default handler for a Watchdog exception,
+ * spins until a reboot occurs
+ */
+void __attribute__ ((weak)) WatchdogHandler(struct pt_regs *regs)
+{
+ /* Generic WatchdogHandler, implement your own */
+ mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE));
+ return;
+}
+
+void WatchdogException(struct pt_regs *regs)
+{
+ printk (KERN_EMERG "PowerPC Book-E Watchdog Exception\n");
+ WatchdogHandler(regs);
+}
+#endif
+
void __init trap_init(void)
{
}
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 9353584fb710..17d2db7e537d 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -96,6 +96,9 @@ SECTIONS
*(.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 = .;
@@ -190,5 +193,6 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
+ *(.exit.data)
}
}
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index 1c380e67d435..f1e1fb4144f0 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -4,6 +4,5 @@
obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o
-obj-$(CONFIG_SMP) += locks.o
obj-$(CONFIG_8xx) += rheap.o
obj-$(CONFIG_CPM2) += rheap.o
diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c
index 4ee888070d91..b18f0d9a00fc 100644
--- a/arch/ppc/lib/dec_and_lock.c
+++ b/arch/ppc/lib/dec_and_lock.c
@@ -11,14 +11,7 @@
* has a cmpxchg, and where atomic->value is an int holding
* the value of the atomic (i.e. the high bits aren't used
* for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
*/
-
-#ifndef ATOMIC_DEC_AND_LOCK
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
int counter;
@@ -43,4 +36,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 57d9930843ac..ee5e9f25baf9 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -278,11 +278,7 @@ bad_area:
/* User mode accesses cause a SIGSEGV */
if (user_mode(regs)) {
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = code;
- info.si_addr = (void __user *) address;
- force_sig_info(SIGSEGV, &info, current);
+ _exception(SIGSEGV, regs, code, address);
return 0;
}
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index ab83132a7ed0..3ec87c91343e 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -30,7 +30,7 @@
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_SMP
.comm mmu_hash_lock,4
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 33ada72c7330..f421a4b337f6 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -560,9 +560,10 @@ void flush_dcache_page(struct page *page)
void flush_dcache_icache_page(struct page *page)
{
#ifdef CONFIG_BOOKE
- __flush_dcache_icache(kmap(page));
- kunmap(page);
-#elif CONFIG_8xx
+ void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
+ __flush_dcache_icache(start);
+ kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+#elif defined(CONFIG_8xx)
/* On 8xx there is no need to kmap since highmem is not supported */
__flush_dcache_icache(page_address(page));
#else
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 805dd98908a3..76f4476cab44 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -16,11 +16,6 @@ choice
depends on 40x
default WALNUT
-config ASH
- bool "Ash"
- help
- This option enables support for the IBM NP405H evaluation board.
-
config BUBINGA
bool "Bubinga"
select WANT_EARLY_SERIAL
@@ -37,11 +32,6 @@ config EP405
help
This option enables support for the EP405/EP405PC boards.
-config OAK
- bool "Oak"
- help
- This option enables support for the IBM 403GCX evaluation board.
-
config REDWOOD_5
bool "Redwood-5"
help
@@ -152,13 +142,13 @@ config IBM440EP_ERR42
# All 405-based cores up until the 405GPR and 405EP have this errata.
config IBM405_ERR77
bool
- depends on 40x && !403GCX && !405GPR
+ depends on 40x && !403GCX && !405GPR && !405EP
default y
# All 40x-based cores, up until the 405GPR and 405EP have this errata.
config IBM405_ERR51
bool
- depends on 40x && !405GPR
+ depends on 40x && !405GPR && !405EP
default y
config BOOKE
@@ -186,6 +176,7 @@ config BIOS_FIXUP
depends on BUBINGA || EP405 || SYCAMORE || WALNUT
default y
+# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
config 403GCX
bool
depends OAK
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index 844c3b5066e8..1dd6d7fd6a9a 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -1,14 +1,12 @@
#
# Makefile for the PowerPC 4xx linux kernel.
-obj-$(CONFIG_ASH) += ash.o
obj-$(CONFIG_BAMBOO) += bamboo.o
obj-$(CONFIG_CPCI405) += cpci405.o
obj-$(CONFIG_EBONY) += ebony.o
obj-$(CONFIG_EP405) += ep405.o
obj-$(CONFIG_BUBINGA) += bubinga.o
obj-$(CONFIG_LUAN) += luan.o
-obj-$(CONFIG_OAK) += oak.o
obj-$(CONFIG_OCOTEA) += ocotea.o
obj-$(CONFIG_REDWOOD_5) += redwood5.o
obj-$(CONFIG_REDWOOD_6) += redwood6.o
diff --git a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c
deleted file mode 100644
index ce2911793716..000000000000
--- a/arch/ppc/platforms/4xx/ash.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * arch/ppc/platforms/4xx/ash.c
- *
- * Support for the IBM NP405H ash eval board
- *
- * Author: Armin Kuster <akuster@mvista.com>
- *
- * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/pagemap.h>
-#include <linux/pci.h>
-
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/io.h>
-#include <asm/ocp.h>
-#include <asm/ibm_ocp_pci.h>
-#include <asm/todc.h>
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-void *ash_rtc_base;
-
-/* Some IRQs unique to Walnut.
- * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
- */
-int __init
-ppc405_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
- */
- {
- {24, 24, 24, 24}, /* IDSEL 1 - PCI slot 1 */
- {25, 25, 25, 25}, /* IDSEL 2 - PCI slot 2 */
- {26, 26, 26, 26}, /* IDSEL 3 - PCI slot 3 */
- {27, 27, 27, 27}, /* IDSEL 4 - PCI slot 4 */
- };
-
- const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-
-void __init
-ash_setup_arch(void)
-{
- ppc4xx_setup_arch();
-
- ibm_ocp_set_emac(0, 3);
-
-#ifdef CONFIG_DEBUG_BRINGUP
- int i;
- printk("\n");
- printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
- printk("\n");
- printk("bi_s_version\t %s\n", bip->bi_s_version);
- printk("bi_r_version\t %s\n", bip->bi_r_version);
- printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
- bip->bi_memsize / (1024 * 1000));
- for (i = 0; i < EMAC_NUMS; i++) {
- printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", i,
- bip->bi_enetaddr[i][0], bip->bi_enetaddr[i][1],
- bip->bi_enetaddr[i][2], bip->bi_enetaddr[i][3],
- bip->bi_enetaddr[i][4], bip->bi_enetaddr[i][5]);
- }
- printk("bi_pci_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
- bip->bi_pci_enetaddr[0], bip->bi_pci_enetaddr[1],
- bip->bi_pci_enetaddr[2], bip->bi_pci_enetaddr[3],
- bip->bi_pci_enetaddr[4], bip->bi_pci_enetaddr[5]);
-
- printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
- bip->bi_intfreq, bip->bi_intfreq / 1000000);
-
- printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
- bip->bi_busfreq, bip->bi_busfreq / 1000000);
- printk("bi_pci_busfreq\t 0x%8.8x\t pci bus clock:\t %dMHz\n",
- bip->bi_pci_busfreq, bip->bi_pci_busfreq / 1000000);
-
- printk("\n");
-#endif
- /* RTC step for ash */
- ash_rtc_base = (void *) ASH_RTC_VADDR;
- TODC_INIT(TODC_TYPE_DS1743, ash_rtc_base, ash_rtc_base, ash_rtc_base,
- 8);
-}
-
-void __init
-bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
-{
- /*
- * Expected PCI mapping:
- *
- * PLB addr PCI memory addr
- * --------------------- ---------------------
- * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
- * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
- *
- * PLB addr PCI io addr
- * --------------------- ---------------------
- * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
- *
- * The following code is simplified by assuming that the bootrom
- * has been well behaved in following this mapping.
- */
-
-#ifdef DEBUG
- int i;
-
- printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
- printk("PCI bridge regs before fixup \n");
- for (i = 0; i <= 2; i++) {
- printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
- printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
- printk(" pmm%dpcila\t0x%x\n", i,
- in_le32(&(pcip->pmm[i].pcila)));
- printk(" pmm%dpciha\t0x%x\n", i,
- in_le32(&(pcip->pmm[i].pciha)));
- }
- printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
- printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
- printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
- printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
- for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
- early_read_config_dword(hose, hose->first_busno,
- PCI_FUNC(hose->first_busno), bar,
- &bar_response);
- DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
- hose->first_busno, PCI_SLOT(hose->first_busno),
- PCI_FUNC(hose->first_busno), bar, bar_response);
- }
-
-#endif
- if (ppc_md.progress)
- ppc_md.progress("bios_fixup(): enter", 0x800);
-
- /* added for IBM boot rom version 1.15 bios bar changes -AK */
-
- /* Disable region first */
- out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
- /* PLB starting addr, PCI: 0x80000000 */
- out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
- /* PCI start addr, 0x80000000 */
- out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
- /* 512MB range of PLB to PCI */
- out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
- /* Enable no pre-fetch, enable region */
- out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
- (PPC405_PCI_UPPER_MEM -
- PPC405_PCI_MEM_BASE)) | 0x01));
-
- /* Disable region one */
- out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
- out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
- out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
- out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
- out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
-
- /* Disable region two */
- out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
- out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
- out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
- out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
- out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
-
- /* Enable PTM1 and PTM2, mapped to PLB address 0. */
-
- out_le32((void *) &(pcip->ptm1la), 0x00000000);
- out_le32((void *) &(pcip->ptm1ms), 0x00000001);
- out_le32((void *) &(pcip->ptm2la), 0x00000000);
- out_le32((void *) &(pcip->ptm2ms), 0x00000001);
-
- /* Write zero to PTM1 BAR. */
-
- early_write_config_dword(hose, hose->first_busno,
- PCI_FUNC(hose->first_busno),
- PCI_BASE_ADDRESS_1,
- 0x00000000);
-
- /* Disable PTM2 (unused) */
-
- out_le32((void *) &(pcip->ptm2la), 0x00000000);
- out_le32((void *) &(pcip->ptm2ms), 0x00000000);
-
- /* end work arround */
- if (ppc_md.progress)
- ppc_md.progress("bios_fixup(): done", 0x800);
-
-#ifdef DEBUG
- printk("PCI bridge regs after fixup \n");
- for (i = 0; i <= 2; i++) {
- printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
- printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
- printk(" pmm%dpcila\t0x%x\n", i,
- in_le32(&(pcip->pmm[i].pcila)));
- printk(" pmm%dpciha\t0x%x\n", i,
- in_le32(&(pcip->pmm[i].pciha)));
- }
- printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
- printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
- printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
- printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
-
- for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
- early_read_config_dword(hose, hose->first_busno,
- PCI_FUNC(hose->first_busno), bar,
- &bar_response);
- DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
- hose->first_busno, PCI_SLOT(hose->first_busno),
- PCI_FUNC(hose->first_busno), bar, bar_response);
- }
-
-
-#endif
-}
-
-void __init
-ash_map_io(void)
-{
- ppc4xx_map_io();
- io_block_mapping(ASH_RTC_VADDR, ASH_RTC_PADDR, ASH_RTC_SIZE, _PAGE_IO);
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- ppc4xx_init(r3, r4, r5, r6, r7);
-
- ppc_md.setup_arch = ash_setup_arch;
- ppc_md.setup_io_mappings = ash_map_io;
-
-#ifdef CONFIG_PPC_RTC
- ppc_md.time_init = todc_time_init;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.nvram_read_val = todc_direct_read_val;
- ppc_md.nvram_write_val = todc_direct_write_val;
-#endif
-}
diff --git a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h
deleted file mode 100644
index 5f7448ea418d..000000000000
--- a/arch/ppc/platforms/4xx/ash.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * arch/ppc/platforms/4xx/ash.h
- *
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * Ash eval board.
- *
- * Author: Armin Kuster <akuster@mvista.com>
- *
- * 2000-2002 (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.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_ASH_H__
-#define __ASM_ASH_H__
-#include <platforms/4xx/ibmnp405h.h>
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Ash" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
- unsigned char bi_s_version[4]; /* Version of this structure */
- unsigned char bi_r_version[30]; /* Version of the IBM ROM */
- unsigned int bi_memsize; /* DRAM installed, in bytes */
- unsigned char bi_enetaddr[4][6]; /* Local Ethernet MAC address */
- unsigned char bi_pci_enetaddr[6];
- unsigned int bi_intfreq; /* Processor speed, in Hz */
- unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
- unsigned int bi_pci_busfreq; /* PCI speed in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
-/* Memory map for the IBM "Ash" NP405H evaluation board.
- */
-
-extern void *ash_rtc_base;
-#define ASH_RTC_PADDR ((uint)0xf0000000)
-#define ASH_RTC_VADDR ASH_RTC_PADDR
-#define ASH_RTC_SIZE ((uint)8*1024)
-
-
-/* Early initialization address mapping for block_io.
- * Standard 405GP map.
- */
-#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE)
-#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR
-#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
-#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR)
-#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR
-#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
-#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000)
-#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR
-#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
-#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000)
-#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR
-#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
-
-#define NR_BOARD_IRQS 32
-
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD 201600
-#else
-#define BASE_BAUD 691200
-#endif
-
-#define PPC4xx_MACHINE_NAME "IBM NP405H Ash"
-
-extern char pci_irq_table[][4];
-
-
-#endif /* !__ASSEMBLY__ */
-#endif /* __ASM_ASH_H__ */
-#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
index f116787b0b76..ac391d463d78 100644
--- a/arch/ppc/platforms/4xx/bamboo.c
+++ b/arch/ppc/platforms/4xx/bamboo.c
@@ -52,13 +52,6 @@
#include <syslib/gen550.h>
#include <syslib/ibm440gx_common.h>
-/*
- * This is a horrible kludge, we eventually need to abstract this
- * generic PHY stuff, so the standard phy mode defines can be
- * easily used from arch code.
- */
-#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
-
bd_t __res;
static struct ibm44x_clocks clocks __initdata;
@@ -123,33 +116,69 @@ bamboo_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
static void __init bamboo_set_emacdata(void)
{
- unsigned char * selection1_base;
+ u8 * base_addr;
struct ocp_def *def;
struct ocp_func_emac_data *emacdata;
- u8 selection1_val;
+ u8 val;
int mode;
+ u32 excluded = 0;
- selection1_base = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16);
- selection1_val = readb(selection1_base);
- iounmap((void *) selection1_base);
- if (BAMBOO_SEL_MII(selection1_val))
+ base_addr = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16);
+ val = readb(base_addr);
+ iounmap((void *) base_addr);
+ if (BAMBOO_SEL_MII(val))
mode = PHY_MODE_MII;
- else if (BAMBOO_SEL_RMII(selection1_val))
+ else if (BAMBOO_SEL_RMII(val))
mode = PHY_MODE_RMII;
else
mode = PHY_MODE_SMII;
- /* Set mac_addr and phy mode for each EMAC */
+ /*
+ * SW2 on the Bamboo is used for ethernet configuration and is accessed
+ * via the CONFIG2 register in the FPGA. If the ANEG pin is set,
+ * overwrite the supported features with the settings in SW2.
+ *
+ * This is used as a workaround for the improperly biased RJ-45 sockets
+ * on the Rev. 0 Bamboo. By default only 10baseT is functional.
+ * Removing inductors L17 and L18 from the board allows 100baseT, but
+ * disables 10baseT. The Rev. 1 has no such limitations.
+ */
+
+ base_addr = ioremap64(BAMBOO_FPGA_CONFIG2_REG_ADDR, 8);
+ val = readb(base_addr);
+ iounmap((void *) base_addr);
+ if (!BAMBOO_AUTONEGOTIATE(val)) {
+ excluded |= SUPPORTED_Autoneg;
+ if (BAMBOO_FORCE_100Mbps(val)) {
+ excluded |= SUPPORTED_10baseT_Full;
+ excluded |= SUPPORTED_10baseT_Half;
+ if (BAMBOO_FULL_DUPLEX_EN(val))
+ excluded |= SUPPORTED_100baseT_Half;
+ else
+ excluded |= SUPPORTED_100baseT_Full;
+ } else {
+ excluded |= SUPPORTED_100baseT_Full;
+ excluded |= SUPPORTED_100baseT_Half;
+ if (BAMBOO_FULL_DUPLEX_EN(val))
+ excluded |= SUPPORTED_10baseT_Half;
+ else
+ excluded |= SUPPORTED_10baseT_Full;
+ }
+ }
+
+ /* Set mac_addr, phy mode and unsupported phy features for each EMAC */
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
emacdata = def->additions;
memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
emacdata->phy_mode = mode;
+ emacdata->phy_feat_exc = excluded;
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
emacdata = def->additions;
memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
emacdata->phy_mode = mode;
+ emacdata->phy_feat_exc = excluded;
}
static int
diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h
index 63d714504148..5c0192826494 100644
--- a/arch/ppc/platforms/4xx/bamboo.h
+++ b/arch/ppc/platforms/4xx/bamboo.h
@@ -88,7 +88,7 @@
#define STD_UART_OP(num) \
{ 0, BASE_BAUD, 0, UART##num##_INT, \
(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
- iomem_base: UART##num##_IO_BASE, \
+ iomem_base: (void*)UART##num##_IO_BASE, \
io_type: SERIAL_IO_MEM},
#define SERIAL_PORT_DFNS \
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index 509e69a095f0..d6b2b1965dcb 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -55,13 +55,6 @@
#include <syslib/gen550.h>
#include <syslib/ibm440gp_common.h>
-/*
- * This is a horrible kludge, we eventually need to abstract this
- * generic PHY stuff, so the standard phy mode defines can be
- * easily used from arch code.
- */
-#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
-
bd_t __res;
static struct ibm44x_clocks clocks __initdata;
@@ -98,15 +91,10 @@ ebony_calibrate_decr(void)
* on Rev. C silicon then errata forces us to
* use the internal clock.
*/
- switch (PVR_REV(mfspr(SPRN_PVR))) {
- case PVR_REV(PVR_440GP_RB):
- freq = EBONY_440GP_RB_SYSCLK;
- break;
- case PVR_REV(PVR_440GP_RC1):
- default:
- freq = EBONY_440GP_RC_SYSCLK;
- break;
- }
+ if (strcmp(cur_cpu_spec[0]->cpu_name, "440GP Rev. B") == 0)
+ freq = EBONY_440GP_RB_SYSCLK;
+ else
+ freq = EBONY_440GP_RC_SYSCLK;
ibm44x_calibrate_decr(freq);
}
diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c
index 6d44567f4dd2..093b28d27a41 100644
--- a/arch/ppc/platforms/4xx/ibm405ep.c
+++ b/arch/ppc/platforms/4xx/ibm405ep.c
@@ -33,6 +33,7 @@ static struct ocp_func_mal_data ibm405ep_mal0_def = {
.txde_irq = 13, /* TX Descriptor Error IRQ */
.rxde_irq = 14, /* RX Descriptor Error IRQ */
.serr_irq = 10, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c
index dfd7ef3ba5f8..e5700469a682 100644
--- a/arch/ppc/platforms/4xx/ibm405gp.c
+++ b/arch/ppc/platforms/4xx/ibm405gp.c
@@ -46,6 +46,7 @@ static struct ocp_func_mal_data ibm405gp_mal0_def = {
.txde_irq = 13, /* TX Descriptor Error IRQ */
.rxde_irq = 14, /* RX Descriptor Error IRQ */
.serr_irq = 10, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c
index 01c8ccbc7214..cd0d00d8e8ee 100644
--- a/arch/ppc/platforms/4xx/ibm405gpr.c
+++ b/arch/ppc/platforms/4xx/ibm405gpr.c
@@ -42,6 +42,7 @@ static struct ocp_func_mal_data ibm405gpr_mal0_def = {
.txde_irq = 13, /* TX Descriptor Error IRQ */
.rxde_irq = 14, /* RX Descriptor Error IRQ */
.serr_irq = 10, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c
index 284da01f1ffd..4712de8ff80f 100644
--- a/arch/ppc/platforms/4xx/ibm440ep.c
+++ b/arch/ppc/platforms/4xx/ibm440ep.c
@@ -53,6 +53,7 @@ static struct ocp_func_mal_data ibm440ep_mal0_def = {
.txde_irq = 33, /* TX Descriptor Error IRQ */
.rxde_irq = 34, /* RX Descriptor Error IRQ */
.serr_irq = 32, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c
index 27615ef8309c..d926245e8b3e 100644
--- a/arch/ppc/platforms/4xx/ibm440gp.c
+++ b/arch/ppc/platforms/4xx/ibm440gp.c
@@ -56,6 +56,7 @@ static struct ocp_func_mal_data ibm440gp_mal0_def = {
.txde_irq = 33, /* TX Descriptor Error IRQ */
.rxde_irq = 34, /* RX Descriptor Error IRQ */
.serr_irq = 32, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c
index 1f38f42835b4..956f45e4ef97 100644
--- a/arch/ppc/platforms/4xx/ibm440gx.c
+++ b/arch/ppc/platforms/4xx/ibm440gx.c
@@ -84,6 +84,7 @@ static struct ocp_func_mal_data ibm440gx_mal0_def = {
.txde_irq = 33, /* TX Descriptor Error IRQ */
.rxde_irq = 34, /* RX Descriptor Error IRQ */
.serr_irq = 32, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c
index fa3e003a0db9..feb17e41ef69 100644
--- a/arch/ppc/platforms/4xx/ibm440sp.c
+++ b/arch/ppc/platforms/4xx/ibm440sp.c
@@ -43,6 +43,7 @@ static struct ocp_func_mal_data ibm440sp_mal0_def = {
.txde_irq = 34, /* TX Descriptor Error IRQ */
.rxde_irq = 35, /* RX Descriptor Error IRQ */
.serr_irq = 33, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c
index ecdc5be6ae28..a477a78f4902 100644
--- a/arch/ppc/platforms/4xx/ibmnp405h.c
+++ b/arch/ppc/platforms/4xx/ibmnp405h.c
@@ -34,7 +34,7 @@ static struct ocp_func_emac_data ibmnp405h_emac1_def = {
.zmii_mux = 1, /* ZMII input of this EMAC */
.mal_idx = 0, /* MAL device index */
.mal_rx_chan = 1, /* MAL rx channel number */
- .mal_tx_chan = 1, /* MAL tx channel number */
+ .mal_tx_chan = 2, /* MAL tx channel number */
.wol_irq = 41, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = -1, /* No TAH */
@@ -46,7 +46,7 @@ static struct ocp_func_emac_data ibmnp405h_emac2_def = {
.zmii_mux = 2, /* ZMII input of this EMAC */
.mal_idx = 0, /* MAL device index */
.mal_rx_chan = 2, /* MAL rx channel number */
- .mal_tx_chan = 2, /* MAL tx channel number */
+ .mal_tx_chan = 4, /* MAL tx channel number */
.wol_irq = 41, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = -1, /* No TAH */
@@ -58,7 +58,7 @@ static struct ocp_func_emac_data ibmnp405h_emac3_def = {
.zmii_mux = 3, /* ZMII input of this EMAC */
.mal_idx = 0, /* MAL device index */
.mal_rx_chan = 3, /* MAL rx channel number */
- .mal_tx_chan = 3, /* MAL tx channel number */
+ .mal_tx_chan = 6, /* MAL tx channel number */
.wol_irq = 41, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = -1, /* No TAH */
@@ -73,6 +73,7 @@ static struct ocp_func_mal_data ibmnp405h_mal0_def = {
.txde_irq = 46, /* TX Descriptor Error IRQ */
.rxde_irq = 47, /* RX Descriptor Error IRQ */
.serr_irq = 45, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
};
OCP_SYSFS_MAL_DATA()
diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c
index 874d16bab73c..d90627b68faa 100644
--- a/arch/ppc/platforms/4xx/ibmstb4.c
+++ b/arch/ppc/platforms/4xx/ibmstb4.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
#include <platforms/4xx/ibmstb4.h>
static struct ocp_func_iic_data ibmstb4_iic0_def = {
@@ -72,12 +73,51 @@ struct ocp_def core_ocp[] __initdata = {
.irq = IDE0_IRQ,
.pm = OCP_CPM_NA,
},
- { .vendor = OCP_VENDOR_IBM,
- .function = OCP_FUNC_USB,
- .paddr = USB0_BASE,
- .irq = USB0_IRQ,
- .pm = OCP_CPM_NA,
- },
{ .vendor = OCP_VENDOR_INVALID,
}
};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0x7fffff01,
+ .triggering = 0x00000000,
+ .ext_irq_mask = 0x0000007e, /* IRQ0 - IRQ5 */
+ }
+};
+
+static struct resource ohci_usb_resources[] = {
+ [0] = {
+ .start = USB0_BASE,
+ .end = USB0_BASE + USB0_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = USB0_IRQ,
+ .end = USB0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 dma_mask = 0xffffffffULL;
+
+static struct platform_device ohci_usb_device = {
+ .name = "ppc-soc-ohci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ohci_usb_resources),
+ .resource = ohci_usb_resources,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffffULL,
+ }
+};
+
+static struct platform_device *ibmstb4_devs[] __initdata = {
+ &ohci_usb_device,
+};
+
+static int __init
+ibmstb4_platform_add_devices(void)
+{
+ return platform_add_devices(ibmstb4_devs, ARRAY_SIZE(ibmstb4_devs));
+}
+arch_initcall(ibmstb4_platform_add_devices);
diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h
index bcb4b1ee71f2..9f21d4c88a3d 100644
--- a/arch/ppc/platforms/4xx/ibmstb4.h
+++ b/arch/ppc/platforms/4xx/ibmstb4.h
@@ -73,9 +73,9 @@
#define OPB0_BASE 0x40000000
#define GPIO0_BASE 0x40060000
+#define USB0_BASE 0x40010000
+#define USB0_SIZE 0xA0
#define USB0_IRQ 18
-#define USB0_BASE STB04xxx_MAP_IO_ADDR(0x40010000)
-#define USB0_EXTENT 4096
#define IIC_NUMS 2
#define UART_NUMS 3
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
index 95359f748e7b..a38e6f9ef858 100644
--- a/arch/ppc/platforms/4xx/luan.c
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -53,13 +53,6 @@
#include <syslib/ibm440gx_common.h>
#include <syslib/ibm440sp_common.h>
-/*
- * This is a horrible kludge, we eventually need to abstract this
- * generic PHY stuff, so the standard phy mode defines can be
- * easily used from arch code.
- */
-#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
-
bd_t __res;
static struct ibm44x_clocks clocks __initdata;
diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h
index 09b444c87816..bbe7d0766db8 100644
--- a/arch/ppc/platforms/4xx/luan.h
+++ b/arch/ppc/platforms/4xx/luan.h
@@ -55,7 +55,7 @@
#define STD_UART_OP(num) \
{ 0, BASE_BAUD, 0, UART##num##_INT, \
(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
- iomem_base: UART##num##_IO_BASE, \
+ iomem_base: (void*)UART##num##_IO_BASE, \
io_type: SERIAL_IO_MEM},
#define SERIAL_PORT_DFNS \
diff --git a/arch/ppc/platforms/4xx/oak.c b/arch/ppc/platforms/4xx/oak.c
deleted file mode 100644
index fa25ee1fa733..000000000000
--- a/arch/ppc/platforms/4xx/oak.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: oak.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/initrd.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/ppc4xx_pic.h>
-#include <asm/time.h>
-
-#include "oak.h"
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init oak_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = oak_setup_arch;
- ppc_md.show_percpuinfo = oak_show_percpuinfo;
- ppc_md.irq_canonicalize = NULL;
- ppc_md.init_IRQ = ppc4xx_pic_init;
- ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
- ppc_md.init = NULL;
-
- ppc_md.restart = oak_restart;
- ppc_md.power_off = oak_power_off;
- ppc_md.halt = oak_halt;
-
- ppc_md.time_init = oak_time_init;
- ppc_md.set_rtc_time = oak_set_rtc_time;
- ppc_md.get_rtc_time = oak_get_rtc_time;
- ppc_md.calibrate_decr = oak_calibrate_decr;
-}
-
-/*
- * Document me.
- */
-void __init
-oak_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int oak_show_percpuinfo()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-oak_show_percpuinfo(struct seq_file *m, int i)
-{
- bd_t *bp = (bd_t *)__res;
-
- seq_printf(m, "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return 0;
-}
-
-/*
- * Document me.
- */
-void
-oak_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-oak_power_off(void)
-{
- oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-oak_halt(void)
-{
- oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-long __init
-oak_time_init(void)
-{
- /* XXX - Implement me */
- return 0;
-}
-
-/*
- * Document me.
- */
-int __init
-oak_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-oak_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init oak_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-oak_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
diff --git a/arch/ppc/platforms/4xx/oak.h b/arch/ppc/platforms/4xx/oak.h
deleted file mode 100644
index 1b86a4c66b04..000000000000
--- a/arch/ppc/platforms/4xx/oak.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *
- * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: oak.h
- *
- * Description:
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * 403G{A,B,C,CX} "Oak" evaluation board. Anything specific to the pro-
- * cessor itself is defined elsewhere.
- *
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_OAK_H__
-#define __ASM_OAK_H__
-
-/* We have an IBM 403G{A,B,C,CX} core */
-#include <asm/ibm403.h>
-
-#define _IO_BASE 0
-#define _ISA_MEM_BASE 0
-#define PCI_DRAM_OFFSET 0
-
-/* Memory map for the "Oak" evaluation board */
-
-#define PPC403SPU_IO_BASE 0x40000000 /* 403 On-chip serial port */
-#define PPC403SPU_IO_SIZE 0x00000008
-#define OAKSERIAL_IO_BASE 0x7E000000 /* NS16550DV serial port */
-#define OAKSERIAL_IO_SIZE 0x00000008
-#define OAKNET_IO_BASE 0xF4000000 /* NS83902AV Ethernet */
-#define OAKNET_IO_SIZE 0x00000040
-#define OAKPROM_IO_BASE 0xFFFE0000 /* AMD 29F010 Flash ROM */
-#define OAKPROM_IO_SIZE 0x00020000
-
-
-/* Interrupt assignments fixed by the hardware implementation */
-
-/* This is annoying kbuild-2.4 problem. -- Tom */
-
-#define PPC403SPU_RX_INT 4 /* AIC_INT4 */
-#define PPC403SPU_TX_INT 5 /* AIC_INT5 */
-#define OAKNET_INT 27 /* AIC_INT27 */
-#define OAKSERIAL_INT 28 /* AIC_INT28 */
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Oak" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
- unsigned char bi_s_version[4]; /* Version of this structure */
- unsigned char bi_r_version[30]; /* Version of the IBM ROM */
- unsigned int bi_memsize; /* DRAM installed, in bytes */
- unsigned char bi_enetaddr[6]; /* Ethernet MAC address */
- unsigned int bi_intfreq; /* Processor speed, in Hz */
- unsigned int bi_busfreq; /* Bus speed, in Hz */
-} bd_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void oak_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void oak_setup_arch(void);
-extern int oak_setup_residual(char *buffer);
-extern void oak_init_IRQ(void);
-extern int oak_get_irq(struct pt_regs *regs);
-extern void oak_restart(char *cmd);
-extern void oak_power_off(void);
-extern void oak_halt(void);
-extern void oak_time_init(void);
-extern int oak_set_rtc_time(unsigned long now);
-extern unsigned long oak_get_rtc_time(void);
-extern void oak_calibrate_decr(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
-#define PPC4xx_MACHINE_NAME "IBM Oak"
-
-#endif /* !__ASSEMBLY__ */
-#endif /* __ASM_OAK_H__ */
-#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/oak_setup.h b/arch/ppc/platforms/4xx/oak_setup.h
deleted file mode 100644
index 8648bd084df8..000000000000
--- a/arch/ppc/platforms/4xx/oak_setup.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: oak_setup.h
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __OAK_SETUP_H__
-#define __OAK_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void oak_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void oak_setup_arch(void);
-extern int oak_setup_residual(char *buffer);
-extern void oak_init_IRQ(void);
-extern int oak_get_irq(struct pt_regs *regs);
-extern void oak_restart(char *cmd);
-extern void oak_power_off(void);
-extern void oak_halt(void);
-extern void oak_time_init(void);
-extern int oak_set_rtc_time(unsigned long now);
-extern unsigned long oak_get_rtc_time(void);
-extern void oak_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __OAK_SETUP_H__ */
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index 8fc34a344769..80028df1b445 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -53,13 +53,6 @@
#include <syslib/gen550.h>
#include <syslib/ibm440gx_common.h>
-/*
- * This is a horrible kludge, we eventually need to abstract this
- * generic PHY stuff, so the standard phy mode defines can be
- * easily used from arch code.
- */
-#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
-
bd_t __res;
static struct ibm44x_clocks clocks __initdata;
diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c
index 2f5e410afbc5..bee8b4ac8afd 100644
--- a/arch/ppc/platforms/4xx/redwood5.c
+++ b/arch/ppc/platforms/4xx/redwood5.c
@@ -18,6 +18,19 @@
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/machdep.h>
+#include <asm/ppc4xx_pic.h>
+
+/*
+ * Define external IRQ senses and polarities.
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */
+};
static struct resource smc91x_resources[] = {
[0] = {
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index ddd04d4c1ea9..b38a851a64ec 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -62,9 +62,29 @@ extern unsigned long total_memory; /* in mm/init */
unsigned char __res[sizeof (bd_t)];
#ifdef CONFIG_PCI
-#error "PCI is not supported"
-/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
- see platforms/85xx/mpc85xx_ads_common.c */
+int
+mpc83xx_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
+ */
+ {
+ {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
+ {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
+ {PIRQD, PIRQA, PIRQB, PIRQC} /* idsel 0x13 */
+ };
+
+ const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int
+mpc83xx_exclude_device(u_char bus, u_char devfn)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
#endif /* CONFIG_PCI */
/* ************************************************************************
@@ -88,7 +108,7 @@ mpc834x_sys_setup_arch(void)
#ifdef CONFIG_PCI
/* setup PCI host bridges */
- mpc83xx_sys_setup_hose();
+ mpc83xx_setup_hose();
#endif
mpc83xx_early_serial_map();
@@ -175,10 +195,17 @@ mpc834x_sys_init_IRQ(void)
IRQ_SENSE_LEVEL, /* EXT 1 */
IRQ_SENSE_LEVEL, /* EXT 2 */
0, /* EXT 3 */
+#ifdef CONFIG_PCI
+ IRQ_SENSE_LEVEL, /* EXT 4 */
+ IRQ_SENSE_LEVEL, /* EXT 5 */
+ IRQ_SENSE_LEVEL, /* EXT 6 */
+ IRQ_SENSE_LEVEL, /* EXT 7 */
+#else
0, /* EXT 4 */
0, /* EXT 5 */
0, /* EXT 6 */
0, /* EXT 7 */
+#endif
};
ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
index a2f6e49d7151..1584cd77a9ef 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.h
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -26,7 +26,7 @@
#define VIRT_IMMRBAR ((uint)0xfe000000)
#define BCSR_PHYS_ADDR ((uint)0xf8000000)
-#define BCSR_SIZE ((uint)(32 * 1024))
+#define BCSR_SIZE ((uint)(128 * 1024))
#define BCSR_MISC_REG2_OFF 0x07
#define BCSR_MISC_REG2_PORESET 0x01
@@ -34,23 +34,25 @@
#define BCSR_MISC_REG3_OFF 0x08
#define BCSR_MISC_REG3_CNFLOCK 0x80
-#ifdef CONFIG_PCI
-/* PCI interrupt controller */
-#define PIRQA MPC83xx_IRQ_IRQ4
-#define PIRQB MPC83xx_IRQ_IRQ5
-#define PIRQC MPC83xx_IRQ_IRQ6
-#define PIRQD MPC83xx_IRQ_IRQ7
-
-#define MPC834x_SYS_PCI1_LOWER_IO 0x00000000
-#define MPC834x_SYS_PCI1_UPPER_IO 0x00ffffff
-
-#define MPC834x_SYS_PCI1_LOWER_MEM 0x80000000
-#define MPC834x_SYS_PCI1_UPPER_MEM 0x9fffffff
-
-#define MPC834x_SYS_PCI1_IO_BASE 0xe2000000
-#define MPC834x_SYS_PCI1_MEM_OFFSET 0x00000000
-
-#define MPC834x_SYS_PCI1_IO_SIZE 0x01000000
-#endif /* CONFIG_PCI */
+#define PIRQA MPC83xx_IRQ_EXT4
+#define PIRQB MPC83xx_IRQ_EXT5
+#define PIRQC MPC83xx_IRQ_EXT6
+#define PIRQD MPC83xx_IRQ_EXT7
+
+#define MPC83xx_PCI1_LOWER_IO 0x00000000
+#define MPC83xx_PCI1_UPPER_IO 0x00ffffff
+#define MPC83xx_PCI1_LOWER_MEM 0x80000000
+#define MPC83xx_PCI1_UPPER_MEM 0x9fffffff
+#define MPC83xx_PCI1_IO_BASE 0xe2000000
+#define MPC83xx_PCI1_MEM_OFFSET 0x00000000
+#define MPC83xx_PCI1_IO_SIZE 0x01000000
+
+#define MPC83xx_PCI2_LOWER_IO 0x00000000
+#define MPC83xx_PCI2_UPPER_IO 0x00ffffff
+#define MPC83xx_PCI2_LOWER_MEM 0xa0000000
+#define MPC83xx_PCI2_UPPER_MEM 0xbfffffff
+#define MPC83xx_PCI2_IO_BASE 0xe3000000
+#define MPC83xx_PCI2_MEM_OFFSET 0x00000000
+#define MPC83xx_PCI2_IO_SIZE 0x01000000
#endif /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 5488a053f415..ff7452e5d8e5 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -21,22 +21,17 @@ obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
endif
obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
-obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
obj-$(CONFIG_TQM8260) += tqm8260_setup.o
obj-$(CONFIG_CPCI690) += cpci690.o
obj-$(CONFIG_EV64260) += ev64260.o
obj-$(CONFIG_CHESTNUT) += chestnut.o
obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o
-obj-$(CONFIG_K2) += k2.o
obj-$(CONFIG_LOPEC) += lopec.o
obj-$(CONFIG_KATANA) += katana.o
obj-$(CONFIG_HDPU) += hdpu.o
-obj-$(CONFIG_MCPN765) += mcpn765.o
-obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o
obj-$(CONFIG_MVME5100) += mvme5100.o
obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o
-obj-$(CONFIG_PCORE) += pcore.o
obj-$(CONFIG_POWERPMC250) += powerpmc250.o
obj-$(CONFIG_PPLUS) += pplus.o
obj-$(CONFIG_PRPMC750) += prpmc750.o
@@ -46,6 +41,7 @@ obj-$(CONFIG_SANDPOINT) += sandpoint.o
obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE) += spruce.o
obj-$(CONFIG_LITE5200) += lite5200.o
+obj-$(CONFIG_EV64360) += ev64360.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/adir.h b/arch/ppc/platforms/adir.h
deleted file mode 100644
index 13a748b46956..000000000000
--- a/arch/ppc/platforms/adir.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * arch/ppc/platforms/adir.h
- *
- * Definitions for SBS Adirondack board support
- *
- * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
- */
-
-#ifndef __PPC_PLATFORMS_ADIR_H
-#define __PPC_PLATFORMS_ADIR_H
-
-/*
- * SBS Adirondack definitions
- */
-
-/* PPC physical address space layout. We use the one set up by the firmware. */
-#define ADIR_PCI32_MEM_BASE 0x80000000
-#define ADIR_PCI32_MEM_SIZE 0x20000000
-#define ADIR_PCI64_MEM_BASE 0xA0000000
-#define ADIR_PCI64_MEM_SIZE 0x20000000
-#define ADIR_PCI32_IO_BASE 0xC0000000
-#define ADIR_PCI32_IO_SIZE 0x10000000
-#define ADIR_PCI64_IO_BASE 0xD0000000
-#define ADIR_PCI64_IO_SIZE 0x10000000
-#define ADIR_PCI64_PHB 0xFF400000
-#define ADIR_PCI32_PHB 0xFF500000
-
-#define ADIR_PCI64_CONFIG_ADDR (ADIR_PCI64_PHB + 0x000f8000)
-#define ADIR_PCI64_CONFIG_DATA (ADIR_PCI64_PHB + 0x000f8010)
-
-#define ADIR_PCI32_CONFIG_ADDR (ADIR_PCI32_PHB + 0x000f8000)
-#define ADIR_PCI32_CONFIG_DATA (ADIR_PCI32_PHB + 0x000f8010)
-
-/* System memory as seen from PCI */
-#define ADIR_PCI_SYS_MEM_BASE 0x80000000
-
-/* Static virtual mapping of PCI I/O */
-#define ADIR_PCI32_VIRT_IO_BASE 0xFE000000
-#define ADIR_PCI32_VIRT_IO_SIZE 0x01000000
-#define ADIR_PCI64_VIRT_IO_BASE 0xFF000000
-#define ADIR_PCI64_VIRT_IO_SIZE 0x01000000
-
-/* Registers */
-#define ADIR_NVRAM_RTC_ADDR 0x74
-#define ADIR_NVRAM_RTC_DATA 0x75
-
-#define ADIR_BOARD_ID_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF0)
-#define ADIR_CPLD1REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF1)
-#define ADIR_CPLD2REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF2)
-#define ADIR_FLASHCTL_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF3)
-#define ADIR_CPC710_STAT_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF4)
-#define ADIR_CLOCK_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF5)
-#define ADIR_GPIO_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF8)
-#define ADIR_MISC_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF9)
-#define ADIR_LED_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFFA)
-
-#define ADIR_CLOCK_REG_PD 0x10
-#define ADIR_CLOCK_REG_SPREAD 0x08
-#define ADIR_CLOCK_REG_SEL133 0x04
-#define ADIR_CLOCK_REG_SEL1 0x02
-#define ADIR_CLOCK_REG_SEL0 0x01
-
-#define ADIR_PROCA_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF0)
-#define ADIR_PROCB_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF2)
-#define ADIR_PROCA_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF4)
-#define ADIR_PROCB_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF6)
-
-/* Linux IRQ numbers */
-#define ADIR_IRQ_NONE -1
-#define ADIR_IRQ_SERIAL2 3
-#define ADIR_IRQ_SERIAL1 4
-#define ADIR_IRQ_FDC 6
-#define ADIR_IRQ_PARALLEL 7
-#define ADIR_IRQ_VIA_AUDIO 10
-#define ADIR_IRQ_VIA_USB 11
-#define ADIR_IRQ_IDE0 14
-#define ADIR_IRQ_IDE1 15
-#define ADIR_IRQ_PCI0_INTA 16
-#define ADIR_IRQ_PCI0_INTB 17
-#define ADIR_IRQ_PCI0_INTC 18
-#define ADIR_IRQ_PCI0_INTD 19
-#define ADIR_IRQ_PCI1_INTA 20
-#define ADIR_IRQ_PCI1_INTB 21
-#define ADIR_IRQ_PCI1_INTC 22
-#define ADIR_IRQ_PCI1_INTD 23
-#define ADIR_IRQ_MBSCSI 24 /* motherboard SCSI */
-#define ADIR_IRQ_MBETH1 25 /* motherboard Ethernet 1 */
-#define ADIR_IRQ_MBETH0 26 /* motherboard Ethernet 0 */
-#define ADIR_IRQ_CPC710_INT1 27
-#define ADIR_IRQ_CPC710_INT2 28
-#define ADIR_IRQ_VT82C686_NMI 29
-#define ADIR_IRQ_VT82C686_INTR 30
-#define ADIR_IRQ_INTERPROC 31
-
-#endif /* __PPC_PLATFORMS_ADIR_H */
diff --git a/arch/ppc/platforms/adir_pci.c b/arch/ppc/platforms/adir_pci.c
deleted file mode 100644
index f94ac53e0711..000000000000
--- a/arch/ppc/platforms/adir_pci.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * arch/ppc/platforms/adir_pci.c
- *
- * PCI support for SBS Adirondack
- *
- * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
- * based on the K2 version by Matt Porter <mporter@mvista.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-
-#include <syslib/cpc710.h>
-#include "adir.h"
-
-#undef DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif /* DEBUG */
-
-static inline int __init
-adir_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-#define PCIIRQ(a,b,c,d) {ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d},
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- /*
- * The three PCI devices on the motherboard have dedicated lines to the
- * CPLD interrupt controller, bypassing the standard PCI INTA-D and the
- * PC interrupt controller. All other PCI devices (slots) have usual
- * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and
- * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D
- * also go to the south bridge, so we have the option of taking them
- * via the CPLD interrupt controller or via the south bridge 8259
- * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt
- * controller. We take all PCI interrupts via the CPLD interrupt
- * controller as recommended by SBS.
- *
- * We also have some monkey business with the PCI devices within the
- * VT82C686B south bridge itself. This chip actually has 7 functions on
- * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE,
- * and function 4 is some special stuff. The other 4 functions are just
- * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5
- * and 6 are audio (not supported on the Adirondack).
- *
- * This is where the monkey business begins. PCI devices are supposed
- * to signal normal PCI interrupts. But the 4 functions in question are
- * located in the south bridge chip, which is designed with the
- * assumption that it will be fielding PCI INTA-D interrupts rather
- * than generating them. Here's what it does. Each of the functions in
- * question routes its interrupt to one of the IRQs on the 8259 thingy.
- * Which one? It looks at the Interrupt Line register in the PCI config
- * space, even though the PCI spec says it's for BIOS/OS interaction
- * only.
- *
- * How do we deal with this? We take these interrupts via 8259 IRQs as
- * we have to. We return the desired IRQ numbers from this routine when
- * called for the functions in question. The PCI scan code will then
- * stick our return value into the Interrupt Line register in the PCI
- * config space, and the interrupt will actually go there. We identify
- * these functions within the south bridge IDSEL by their interrupt pin
- * numbers, as the VT82C686B has 04 in the Interrupt Pin register for
- * USB and 03 for audio.
- */
- if (!hose->index) {
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- /* south bridge */ PCIIRQ(IDE0, NONE, VIA_AUDIO, VIA_USB)
- /* Ethernet 0 */ PCIIRQ(MBETH0, MBETH0, MBETH0, MBETH0)
- /* PCI0 slot 1 */ PCIIRQ(PCI0_INTB, PCI0_INTC, PCI0_INTD, PCI0_INTA)
- /* PCI0 slot 2 */ PCIIRQ(PCI0_INTC, PCI0_INTD, PCI0_INTA, PCI0_INTB)
- /* PCI0 slot 3 */ PCIIRQ(PCI0_INTD, PCI0_INTA, PCI0_INTB, PCI0_INTC)
- };
- const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
- } else {
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- /* Ethernet 1 */ PCIIRQ(MBETH1, MBETH1, MBETH1, MBETH1)
- /* SCSI */ PCIIRQ(MBSCSI, MBSCSI, MBSCSI, MBSCSI)
- /* PCI1 slot 1 */ PCIIRQ(PCI1_INTB, PCI1_INTC, PCI1_INTD, PCI1_INTA)
- /* PCI1 slot 2 */ PCIIRQ(PCI1_INTC, PCI1_INTD, PCI1_INTA, PCI1_INTB)
- /* PCI1 slot 3 */ PCIIRQ(PCI1_INTD, PCI1_INTA, PCI1_INTB, PCI1_INTC)
- };
- const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
- }
-#undef PCIIRQ
-}
-
-static void
-adir_pcibios_fixup_resources(struct pci_dev *dev)
-{
- int i;
-
- if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
- (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64))
- {
- DBG("Fixup CPC710 resources\n");
- for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
- {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- }
- }
-}
-
-/*
- * CPC710 DD3 has an errata causing it to hang the system if a type 0 config
- * cycle is attempted on its PCI32 interface with a device number > 21.
- * CPC710's PCI bridges map device numbers 1 through 21 to AD11 through AD31.
- * Per the PCI spec it MUST accept all other device numbers and do nothing, and
- * software MUST scan all device numbers without assuming how IDSELs are
- * mapped. However, as the CPC710 DD3's errata causes such correct scanning
- * procedure to hang the system, we have no choice but to introduce this hack
- * of knowingly avoiding device numbers > 21 on PCI0,
- */
-static int
-adir_exclude_device(u_char bus, u_char devfn)
-{
- if ((bus == 0) && (PCI_SLOT(devfn) > 21))
- return PCIBIOS_DEVICE_NOT_FOUND;
- else
- return PCIBIOS_SUCCESSFUL;
-}
-
-void adir_find_bridges(void)
-{
- struct pci_controller *hose_a, *hose_b;
-
- /* Setup PCI32 hose */
- hose_a = pcibios_alloc_controller();
- if (!hose_a)
- return;
-
- hose_a->first_busno = 0;
- hose_a->last_busno = 0xff;
- hose_a->pci_mem_offset = ADIR_PCI32_MEM_BASE;
- hose_a->io_space.start = 0;
- hose_a->io_space.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
- hose_a->mem_space.start = 0;
- hose_a->mem_space.end = ADIR_PCI32_MEM_SIZE - 1;
- hose_a->io_resource.start = 0;
- hose_a->io_resource.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
- hose_a->io_resource.flags = IORESOURCE_IO;
- hose_a->mem_resources[0].start = ADIR_PCI32_MEM_BASE;
- hose_a->mem_resources[0].end = ADIR_PCI32_MEM_BASE +
- ADIR_PCI32_MEM_SIZE - 1;
- hose_a->mem_resources[0].flags = IORESOURCE_MEM;
- hose_a->io_base_phys = ADIR_PCI32_IO_BASE;
- hose_a->io_base_virt = (void *) ADIR_PCI32_VIRT_IO_BASE;
-
- ppc_md.pci_exclude_device = adir_exclude_device;
- setup_indirect_pci(hose_a, ADIR_PCI32_CONFIG_ADDR,
- ADIR_PCI32_CONFIG_DATA);
-
- /* Initialize PCI32 bus registers */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_BUS_NUMBER,
- hose_a->first_busno);
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER,
- hose_a->last_busno);
-
- hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
-
- /* Write out correct max subordinate bus number for hose A */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER,
- hose_a->last_busno);
-
- /* Setup PCI64 hose */
- hose_b = pcibios_alloc_controller();
- if (!hose_b)
- return;
-
- hose_b->first_busno = hose_a->last_busno + 1;
- hose_b->last_busno = 0xff;
- hose_b->pci_mem_offset = ADIR_PCI64_MEM_BASE;
- hose_b->io_space.start = 0;
- hose_b->io_space.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
- hose_b->mem_space.start = 0;
- hose_b->mem_space.end = ADIR_PCI64_MEM_SIZE - 1;
- hose_b->io_resource.start = 0;
- hose_b->io_resource.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
- hose_b->io_resource.flags = IORESOURCE_IO;
- hose_b->mem_resources[0].start = ADIR_PCI64_MEM_BASE;
- hose_b->mem_resources[0].end = ADIR_PCI64_MEM_BASE +
- ADIR_PCI64_MEM_SIZE - 1;
- hose_b->mem_resources[0].flags = IORESOURCE_MEM;
- hose_b->io_base_phys = ADIR_PCI64_IO_BASE;
- hose_b->io_base_virt = (void *) ADIR_PCI64_VIRT_IO_BASE;
-
- setup_indirect_pci(hose_b, ADIR_PCI64_CONFIG_ADDR,
- ADIR_PCI64_CONFIG_DATA);
-
- /* Initialize PCI64 bus registers */
- early_write_config_byte(hose_b,
- 0,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER,
- 0xff);
-
- early_write_config_byte(hose_b,
- 0,
- PCI_DEVFN(0, 0),
- CPC710_BUS_NUMBER,
- hose_b->first_busno);
-
- hose_b->last_busno = pciauto_bus_scan(hose_b,
- hose_b->first_busno);
-
- /* Write out correct max subordinate bus number for hose B */
- early_write_config_byte(hose_b,
- hose_b->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER,
- hose_b->last_busno);
-
- ppc_md.pcibios_fixup = NULL;
- ppc_md.pcibios_fixup_resources = adir_pcibios_fixup_resources;
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = adir_map_irq;
-}
diff --git a/arch/ppc/platforms/adir_pic.c b/arch/ppc/platforms/adir_pic.c
deleted file mode 100644
index 9947cba52af5..000000000000
--- a/arch/ppc/platforms/adir_pic.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * arch/ppc/platforms/adir_pic.c
- *
- * Interrupt controller support for SBS Adirondack
- *
- * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
- * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
- */
-
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/i8259.h>
-#include "adir.h"
-
-static void adir_onboard_pic_enable(unsigned int irq);
-static void adir_onboard_pic_disable(unsigned int irq);
-
-__init static void
-adir_onboard_pic_init(void)
-{
- volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
-
- /* Disable all Adirondack onboard interrupts */
- out_be16(maskreg, 0xFFFF);
-}
-
-static int
-adir_onboard_pic_get_irq(void)
-{
- volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
- int irq;
- u_short int_status, int_test;
-
- int_status = in_be16(statreg);
- for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
- if (int_status & int_test)
- break;
- }
-
- if (irq == 16)
- return -1;
-
- return (irq+16);
-}
-
-static void
-adir_onboard_pic_enable(unsigned int irq)
-{
- volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
-
- /* Change irq to Adirondack onboard native value */
- irq -= 16;
-
- /* Enable requested irq number */
- out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
-}
-
-static void
-adir_onboard_pic_disable(unsigned int irq)
-{
- volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
-
- /* Change irq to Adirondack onboard native value */
- irq -= 16;
-
- /* Disable requested irq number */
- out_be16(maskreg, in_be16(maskreg) | (1 << irq));
-}
-
-static struct hw_interrupt_type adir_onboard_pic = {
- " ADIR PIC ",
- NULL,
- NULL,
- adir_onboard_pic_enable, /* unmask */
- adir_onboard_pic_disable, /* mask */
- adir_onboard_pic_disable, /* mask and ack */
- NULL,
- NULL
-};
-
-static struct irqaction noop_action = {
- .handler = no_action,
- .flags = SA_INTERRUPT,
- .mask = CPU_MASK_NONE,
- .name = "82c59 primary cascade",
-};
-
-/*
- * Linux interrupt values are assigned as follows:
- *
- * 0-15 VT82C686 8259 interrupts
- * 16-31 Adirondack CPLD interrupts
- */
-__init void
-adir_init_IRQ(void)
-{
- int i;
-
- /* Initialize the cascaded 8259's on the VT82C686 */
- for (i=0; i<16; i++)
- irq_desc[i].handler = &i8259_pic;
- i8259_init(NULL);
-
- /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
- for (i=16; i<32; i++)
- irq_desc[i].handler = &adir_onboard_pic;
- adir_onboard_pic_init();
-
- /* Enable 8259 interrupt cascade */
- setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
-}
-
-int
-adir_get_irq(struct pt_regs *regs)
-{
- int irq;
-
- if ((irq = adir_onboard_pic_get_irq()) < 0)
- return irq;
-
- if (irq == ADIR_IRQ_VT82C686_INTR)
- irq = i8259_irq(regs);
-
- return irq;
-}
diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c
deleted file mode 100644
index 6a6754ee0617..000000000000
--- a/arch/ppc/platforms/adir_setup.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * arch/ppc/platforms/adir_setup.c
- *
- * Board setup routines for SBS Adirondack
- *
- * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
- * based on the K2 version by Matt Porter <mporter@mvista.com>
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-
-#include "adir.h"
-
-extern void adir_init_IRQ(void);
-extern int adir_get_irq(struct pt_regs *);
-extern void adir_find_bridges(void);
-extern unsigned long loops_per_jiffy;
-
-static unsigned int cpu_750cx[16] = {
- 5, 15, 14, 0, 4, 13, 0, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
-
-static int
-adir_get_bus_speed(void)
-{
- if (!(*((u_char *) ADIR_CLOCK_REG) & ADIR_CLOCK_REG_SEL133))
- return 100000000;
- else
- return 133333333;
-}
-
-static int
-adir_get_cpu_speed(void)
-{
- unsigned long hid1;
- int cpu_speed;
-
- hid1 = mfspr(SPRN_HID1) >> 28;
-
- hid1 = cpu_750cx[hid1];
-
- cpu_speed = adir_get_bus_speed()*hid1/2;
- return cpu_speed;
-}
-
-static void __init
-adir_calibrate_decr(void)
-{
- int freq, divisor = 4;
-
- /* determine processor bus speed */
- freq = adir_get_bus_speed();
- tb_ticks_per_jiffy = freq / HZ / divisor;
- tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-}
-
-static int
-adir_show_cpuinfo(struct seq_file *m)
-{
- seq_printf(m, "vendor\t\t: SBS\n");
- seq_printf(m, "machine\t\t: Adirondack\n");
- seq_printf(m, "cpu speed\t: %dMhz\n", adir_get_cpu_speed()/1000000);
- seq_printf(m, "bus speed\t: %dMhz\n", adir_get_bus_speed()/1000000);
- seq_printf(m, "memory type\t: SDRAM\n");
-
- return 0;
-}
-
-extern char cmd_line[];
-
-TODC_ALLOC();
-
-static void __init
-adir_setup_arch(void)
-{
- unsigned int cpu;
-
- /* Setup TODC access */
- TODC_INIT(TODC_TYPE_MC146818, ADIR_NVRAM_RTC_ADDR, 0,
- ADIR_NVRAM_RTC_DATA, 8);
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
- /* Setup PCI host bridges */
- adir_find_bridges();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_SDA1;
-#endif
-
- /* Identify the system */
- printk("System Identification: SBS Adirondack - PowerPC 750CXe @ %d Mhz\n", adir_get_cpu_speed()/1000000);
- printk("SBS Adirondack port (C) 2001 SBS Technologies, Inc.\n");
-
- /* Identify the CPU manufacturer */
- cpu = mfspr(SPRN_PVR);
- printk("CPU manufacturer: IBM [rev=%04x]\n", (cpu & 0xffff));
-}
-
-static void
-adir_restart(char *cmd)
-{
- local_irq_disable();
- /* SRR0 has system reset vector, SRR1 has default MSR value */
- /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
- __asm__ __volatile__
- ("lis 3,0xfff0\n\t"
- "ori 3,3,0x0100\n\t"
- "mtspr 26,3\n\t"
- "li 3,0\n\t"
- "mtspr 27,3\n\t"
- "rfi\n\t");
- for(;;);
-}
-
-static void
-adir_power_off(void)
-{
- for(;;);
-}
-
-static void
-adir_halt(void)
-{
- adir_restart(NULL);
-}
-
-static unsigned long __init
-adir_find_end_of_memory(void)
-{
- return boot_mem_size;
-}
-
-static void __init
-adir_map_io(void)
-{
- io_block_mapping(ADIR_PCI32_VIRT_IO_BASE, ADIR_PCI32_IO_BASE,
- ADIR_PCI32_VIRT_IO_SIZE, _PAGE_IO);
- io_block_mapping(ADIR_PCI64_VIRT_IO_BASE, ADIR_PCI64_IO_BASE,
- ADIR_PCI64_VIRT_IO_SIZE, _PAGE_IO);
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * On the Adirondack we use bi_recs and pass the pointer to them in R3.
- */
- parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
-
- /* Remember, isa_io_base is virtual but isa_mem_base is physical! */
- isa_io_base = ADIR_PCI32_VIRT_IO_BASE;
- isa_mem_base = ADIR_PCI32_MEM_BASE;
- pci_dram_offset = ADIR_PCI_SYS_MEM_BASE;
-
- ppc_md.setup_arch = adir_setup_arch;
- ppc_md.show_cpuinfo = adir_show_cpuinfo;
- ppc_md.irq_canonicalize = NULL;
- ppc_md.init_IRQ = adir_init_IRQ;
- ppc_md.get_irq = adir_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.find_end_of_memory = adir_find_end_of_memory;
- ppc_md.setup_io_mappings = adir_map_io;
-
- ppc_md.restart = adir_restart;
- ppc_md.power_off = adir_power_off;
- ppc_md.halt = adir_halt;
-
- ppc_md.time_init = todc_time_init;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.nvram_read_val = todc_mc146818_read_val;
- ppc_md.nvram_write_val = todc_mc146818_write_val;
- ppc_md.calibrate_decr = adir_calibrate_decr;
-}
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
index 4864a7de3daa..6037ce7796f5 100644
--- a/arch/ppc/platforms/chrp_time.c
+++ b/arch/ppc/platforms/chrp_time.c
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/bcd.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/nvram.h>
#include <asm/prom.h>
diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
index 507870c9a97a..f64ac2acb603 100644
--- a/arch/ppc/platforms/cpci690.c
+++ b/arch/ppc/platforms/cpci690.c
@@ -35,11 +35,7 @@
#define SET_PCI_IDE_NATIVE
static struct mv64x60_handle bh;
-static u32 cpci690_br_base;
-
-static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */
- 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
+static void __iomem *cpci690_br_base;
TODC_ALLOC();
@@ -55,7 +51,7 @@ cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
* A B C D
*/
{
- { 90, 91, 88, 89}, /* IDSEL 30/20 - Sentinel */
+ { 90, 91, 88, 89 }, /* IDSEL 30/20 - Sentinel */
};
const long min_idsel = 20, max_idsel = 20, irqs_per_slot = 4;
@@ -67,9 +63,9 @@ cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
* A B C D
*/
{
- { 93, 94, 95, 92}, /* IDSEL 28/18 - PMC slot 2 */
- { 0, 0, 0, 0}, /* IDSEL 29/19 - Not used */
- { 94, 95, 92, 93}, /* IDSEL 30/20 - PMC slot 1 */
+ { 93, 94, 95, 92 }, /* IDSEL 28/18 - PMC slot 2 */
+ { 0, 0, 0, 0 }, /* IDSEL 29/19 - Not used */
+ { 94, 95, 92, 93 }, /* IDSEL 30/20 - PMC slot 1 */
};
const long min_idsel = 18, max_idsel = 20, irqs_per_slot = 4;
@@ -77,68 +73,29 @@ cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
}
}
-static int
-cpci690_get_cpu_speed(void)
-{
- unsigned long hid1;
+#define GB (1024UL * 1024UL * 1024UL)
- hid1 = mfspr(SPRN_HID1) >> 28;
- return CPCI690_BUS_FREQ * cpu_7xx[hid1]/2;
+static u32
+cpci690_get_bus_freq(void)
+{
+ if (boot_mem_size >= (1*GB)) /* bus speed based on mem size */
+ return 100000000;
+ else
+ return 133333333;
}
-#define KB (1024UL)
-#define MB (1024UL * KB)
-#define GB (1024UL * MB)
+static const unsigned int cpu_750xx[32] = { /* 750FX & 750GX */
+ 0, 0, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,/* 0-15*/
+ 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0 /*16-31*/
+};
-unsigned long __init
-cpci690_find_end_of_memory(void)
+static int
+cpci690_get_cpu_freq(void)
{
- u32 mem_ctlr_size;
- static u32 board_size;
- static u8 first_time = 1;
-
- if (first_time) {
- /* Using cpci690_set_bat() mapping ==> virt addr == phys addr */
- switch (in_8((u8 *) (cpci690_br_base +
- CPCI690_BR_MEM_CTLR)) & 0x07) {
- case 0x01:
- board_size = 256*MB;
- break;
- case 0x02:
- board_size = 512*MB;
- break;
- case 0x03:
- board_size = 768*MB;
- break;
- case 0x04:
- board_size = 1*GB;
- break;
- case 0x05:
- board_size = 1*GB + 512*MB;
- break;
- case 0x06:
- board_size = 2*GB;
- break;
- default:
- board_size = 0xffffffff; /* use mem ctlr size */
- } /* switch */
-
- mem_ctlr_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
- MV64x60_TYPE_GT64260A);
-
- /* Check that mem ctlr & board reg agree. If not, pick MIN. */
- if (board_size != mem_ctlr_size) {
- printk(KERN_WARNING "Board register & memory controller"
- "mem size disagree (board reg: 0x%lx, "
- "mem ctlr: 0x%lx)\n",
- (ulong)board_size, (ulong)mem_ctlr_size);
- board_size = min(board_size, mem_ctlr_size);
- }
-
- first_time = 0;
- } /* if */
-
- return board_size;
+ unsigned long pll_cfg;
+
+ pll_cfg = (mfspr(SPRN_HID1) & 0xf8000000) >> 27;
+ return cpci690_get_bus_freq() * cpu_750xx[pll_cfg]/2;
}
static void __init
@@ -228,7 +185,7 @@ cpci690_setup_peripherals(void)
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, CPCI690_BR_BASE,
CPCI690_BR_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
- cpci690_br_base = (u32)ioremap(CPCI690_BR_BASE, CPCI690_BR_SIZE);
+ cpci690_br_base = ioremap(CPCI690_BR_BASE, CPCI690_BR_SIZE);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, CPCI690_TODC_BASE,
CPCI690_TODC_SIZE, 0);
@@ -329,7 +286,7 @@ cpci690_fixup_mpsc_pdata(struct platform_device *pdev)
pdata->max_idle = 40;
pdata->default_baud = CPCI690_MPSC_BAUD;
pdata->brg_clk_src = CPCI690_MPSC_CLK_SRC;
- pdata->brg_clk_freq = CPCI690_BUS_FREQ;
+ pdata->brg_clk_freq = cpci690_get_bus_freq();
}
static int __init
@@ -365,7 +322,7 @@ cpci690_reset_board(void)
u32 i = 10000;
local_irq_disable();
- out_8((u8 *)(cpci690_br_base + CPCI690_BR_SW_RESET), 0x11);
+ out_8((cpci690_br_base + CPCI690_BR_SW_RESET), 0x11);
while (i != 0) i++;
panic("restart failed\n");
@@ -394,10 +351,40 @@ cpci690_power_off(void)
static int
cpci690_show_cpuinfo(struct seq_file *m)
{
+ char *s;
+
+ seq_printf(m, "cpu MHz\t\t: %d\n",
+ (cpci690_get_cpu_freq() + 500000) / 1000000);
+ seq_printf(m, "bus MHz\t\t: %d\n",
+ (cpci690_get_bus_freq() + 500000) / 1000000);
seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
- seq_printf(m, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000);
- seq_printf(m, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ/1000/1000);
+ seq_printf(m, "FPGA Revision\t: %d\n",
+ in_8(cpci690_br_base + CPCI690_BR_MEM_CTLR) >> 5);
+
+ switch(bh.type) {
+ case MV64x60_TYPE_GT64260A:
+ s = "gt64260a";
+ break;
+ case MV64x60_TYPE_GT64260B:
+ s = "gt64260b";
+ break;
+ case MV64x60_TYPE_MV64360:
+ s = "mv64360";
+ break;
+ case MV64x60_TYPE_MV64460:
+ s = "mv64460";
+ break;
+ default:
+ s = "Unknown";
+ }
+ seq_printf(m, "bridge type\t: %s\n", s);
+ seq_printf(m, "bridge rev\t: 0x%x\n", bh.rev);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ seq_printf(m, "coherency\t: %s\n", "off");
+#else
+ seq_printf(m, "coherency\t: %s\n", "on");
+#endif
return 0;
}
@@ -407,7 +394,7 @@ cpci690_calibrate_decr(void)
{
ulong freq;
- freq = CPCI690_BUS_FREQ / 4;
+ freq = cpci690_get_bus_freq() / 4;
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq/1000000, freq%1000000);
@@ -416,25 +403,12 @@ cpci690_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
-static __inline__ void
-cpci690_set_bat(u32 addr, u32 size)
-{
- addr &= 0xfffe0000;
- size &= 0x1ffe0000;
- size = ((size >> 17) - 1) << 2;
-
- mb();
- mtspr(SPRN_DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */
- mtspr(SPRN_DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */
- mb();
-}
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC)
static void __init
cpci690_map_io(void)
{
io_block_mapping(CONFIG_MV64X60_NEW_BASE, CONFIG_MV64X60_NEW_BASE,
- 128 * KB, _PAGE_IO);
+ 128 * 1024, _PAGE_IO);
}
#endif
@@ -442,14 +416,15 @@ void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_start=initrd_end=0;
- initrd_below_start_ok=0;
-#endif /* CONFIG_BLK_DEV_INITRD */
-
parse_bootinfo(find_bootinfo());
- loops_per_jiffy = cpci690_get_cpu_speed() / HZ;
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
isa_mem_base = 0;
@@ -460,7 +435,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.restart = cpci690_restart;
ppc_md.power_off = cpci690_power_off;
ppc_md.halt = cpci690_halt;
- ppc_md.find_end_of_memory = cpci690_find_end_of_memory;
ppc_md.time_init = todc_time_init;
ppc_md.set_rtc_time = todc_set_rtc_time;
ppc_md.get_rtc_time = todc_get_rtc_time;
@@ -468,22 +442,13 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.nvram_write_val = todc_direct_write_val;
ppc_md.calibrate_decr = cpci690_calibrate_decr;
- /*
- * Need to map in board regs (used by cpci690_find_end_of_memory())
- * and the bridge's regs (used by progress);
- */
- cpci690_set_bat(CPCI690_BR_BASE, 32 * MB);
- cpci690_br_base = CPCI690_BR_BASE;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC)
ppc_md.setup_io_mappings = cpci690_map_io;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.progress = mv64x60_mpsc_progress;
mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-#ifdef CONFIG_KGDB
- ppc_md.setup_io_mappings = cpci690_map_io;
- ppc_md.early_serial_map = cpci690_early_serial_map;
-#endif /* CONFIG_KGDB */
+#endif /* defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_MPSC) */
#if defined(CONFIG_SERIAL_MPSC)
platform_notify = cpci690_platform_notify;
diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h
index 36cd2673c742..49584c9cedf3 100644
--- a/arch/ppc/platforms/cpci690.h
+++ b/arch/ppc/platforms/cpci690.h
@@ -73,6 +73,4 @@ typedef struct board_info {
#define CPCI690_MPSC_BAUD 9600
#define CPCI690_MPSC_CLK_SRC 8 /* TCLK */
-#define CPCI690_BUS_FREQ 133333333
-
#endif /* __PPC_PLATFORMS_CPCI690_H */
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
new file mode 100644
index 000000000000..9811a8a52c25
--- /dev/null
+++ b/arch/ppc/platforms/ev64360.c
@@ -0,0 +1,510 @@
+/*
+ * arch/ppc/platforms/ev64360.c
+ *
+ * Board setup routines for the Marvell EV-64360-BP Evaluation Board.
+ *
+ * Author: Lee Nicks <allinux@gmail.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@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 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/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx.h>
+#ifdef CONFIG_BOOTIMG
+#include <linux/bootimg.h>
+#endif
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/smp.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
+#include <asm/mv64x60.h>
+#include <platforms/ev64360.h>
+
+#define BOARD_VENDOR "Marvell"
+#define BOARD_MACHINE "EV-64360-BP"
+
+static struct mv64x60_handle bh;
+static void __iomem *sram_base;
+
+static u32 ev64360_flash_size_0;
+static u32 ev64360_flash_size_1;
+
+static u32 ev64360_bus_frequency;
+
+unsigned char __res[sizeof(bd_t)];
+
+static int __init
+ev64360_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ return 0;
+}
+
+static void __init
+ev64360_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ #ifdef CONFIG_PCI
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = EV64360_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = EV64360_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = EV64360_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = EV64360_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = EV64360_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = EV64360_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = EV64360_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+ #else
+ si.pci_0.enable_bus = 0;
+ si.pci_1.enable_bus = 0;
+ #endif
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+ }
+
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_WARNING "Bridge initialization failed.\n");
+
+ #ifdef CONFIG_PCI
+ pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ev64360_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 1, 0);
+ bh.hose_b->first_busno = 0;
+ bh.hose_b->last_busno = 0xff;
+ #endif
+}
+
+/* Bridge & platform setup routines */
+void __init
+ev64360_intr_setup(void)
+{
+ /* MPP 8, 9, and 10 */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff);
+
+ /*
+ * Define GPP 8,9,and 10 interrupt polarity as active low
+ * input signal and level triggered
+ */
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700);
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700);
+
+ /* Config GPP intr ctlr to respond to level trigger */
+ mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10));
+
+ /* Erranum FEr PCI-#8 */
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9));
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700);
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700);
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT25 summarizes GPP interrupts 8-15
+ */
+ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));
+}
+
+void __init
+ev64360_setup_peripherals(void)
+{
+ u32 base;
+
+ /* Set up window for boot CS */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ EV64360_BOOT_WINDOW_BASE, EV64360_BOOT_WINDOW_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ /* We only use the 32-bit flash */
+ mv64x60_get_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, &base,
+ &ev64360_flash_size_0);
+ ev64360_flash_size_1 = 0;
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ sram_base = ioremap(EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+
+ /* Set up Enet->SRAM window */
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+ EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2);
+ bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+ /* Give enet r/w access to memory region */
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1)));
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1)));
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1)));
+
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#endif
+
+ /*
+ * Setting the SRAM to 0. Note that this generates parity errors on
+ * internal data path in SRAM since it's first time accessing it
+ * while after reset it's not configured.
+ */
+ memset(sram_base, 0, MV64360_SRAM_SIZE);
+
+ /* set up PCI interrupt controller */
+ ev64360_intr_setup();
+}
+
+static void __init
+ev64360_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("ev64360_setup_arch: enter", 0);
+
+ set_tb(0, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ /*
+ * Set up the L2CR register.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2PE);
+
+ if (ppc_md.progress)
+ ppc_md.progress("ev64360_setup_arch: calling setup_bridge", 0);
+
+ ev64360_setup_bridge();
+ ev64360_setup_peripherals();
+ ev64360_bus_frequency = ev64360_bus_freq();
+
+ printk(KERN_INFO "%s %s port (C) 2005 Lee Nicks "
+ "(allinux@gmail.com)\n", BOARD_VENDOR, BOARD_MACHINE);
+ if (ppc_md.progress)
+ ppc_md.progress("ev64360_setup_arch: exit", 0);
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+ev64360_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = EV64360_DEFAULT_BAUD;
+ pdata->brg_clk_src = EV64360_MPSC_CLK_SRC;
+ /*
+ * TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts,
+ * TCLK == SysCLK but on 64460, they are separate pins.
+ * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz.
+ */
+ pdata->brg_clk_freq = min(ev64360_bus_frequency, MV64x60_TCLK_FREQ_MAX);
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init
+ev64360_fixup_eth_pdata(struct platform_device *pdev)
+{
+ struct mv643xx_eth_platform_data *eth_pd;
+ static u16 phy_addr[] = {
+ EV64360_ETH0_PHY_ADDR,
+ EV64360_ETH1_PHY_ADDR,
+ EV64360_ETH2_PHY_ADDR,
+ };
+
+ eth_pd = pdev->dev.platform_data;
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = phy_addr[pdev->id];
+ eth_pd->tx_queue_size = EV64360_ETH_TX_QUEUE_SIZE;
+ eth_pd->rx_queue_size = EV64360_ETH_RX_QUEUE_SIZE;
+}
+#endif
+
+static int __init
+ev64360_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn)(struct platform_device *pdev));
+ } dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+ { MPSC_CTLR_NAME ".0", ev64360_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", ev64360_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+ { MV643XX_ETH_NAME ".0", ev64360_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".1", ev64360_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".2", ev64360_fixup_eth_pdata },
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i=0; i<ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device, dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+
+#ifndef MB
+#define MB (1 << 20)
+#endif
+
+/*
+ * MTD Layout.
+ *
+ * FLASH Amount: 0xff000000 - 0xffffffff
+ * ------------- -----------------------
+ * Reserved: 0xff000000 - 0xff03ffff
+ * JFFS2 file system: 0xff040000 - 0xffefffff
+ * U-boot: 0xfff00000 - 0xffffffff
+ */
+static int __init
+ev64360_setup_mtd(void)
+{
+ u32 size;
+ int ptbl_entries;
+ static struct mtd_partition *ptbl;
+
+ size = ev64360_flash_size_0 + ev64360_flash_size_1;
+ if (!size)
+ return -ENOMEM;
+
+ ptbl_entries = 3;
+
+ if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+ GFP_KERNEL)) == NULL) {
+
+ printk(KERN_WARNING "Can't alloc MTD partition table\n");
+ return -ENOMEM;
+ }
+ memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
+
+ ptbl[0].name = "reserved";
+ ptbl[0].offset = 0;
+ ptbl[0].size = EV64360_MTD_RESERVED_SIZE;
+ ptbl[1].name = "jffs2";
+ ptbl[1].offset = EV64360_MTD_RESERVED_SIZE;
+ ptbl[1].size = EV64360_MTD_JFFS2_SIZE;
+ ptbl[2].name = "U-BOOT";
+ ptbl[2].offset = EV64360_MTD_RESERVED_SIZE + EV64360_MTD_JFFS2_SIZE;
+ ptbl[2].size = EV64360_MTD_UBOOT_SIZE;
+
+ physmap_map.size = size;
+ physmap_set_partitions(ptbl, ptbl_entries);
+ return 0;
+}
+
+arch_initcall(ev64360_setup_mtd);
+#endif
+
+static void
+ev64360_restart(char *cmd)
+{
+ ulong i = 0xffffffff;
+ volatile unsigned char * rtc_base = ioremap(EV64360_RTC_WINDOW_BASE,0x4000);
+
+ /* issue hard reset */
+ rtc_base[0xf] = 0x80;
+ rtc_base[0xc] = 0x00;
+ rtc_base[0xd] = 0x01;
+ rtc_base[0xf] = 0x83;
+
+ while (i-- > 0) ;
+ panic("restart failed\n");
+}
+
+static void
+ev64360_halt(void)
+{
+ while (1) ;
+ /* NOTREACHED */
+}
+
+static void
+ev64360_power_off(void)
+{
+ ev64360_halt();
+ /* NOTREACHED */
+}
+
+static int
+ev64360_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
+ seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
+ seq_printf(m, "bus speed\t: %dMHz\n", ev64360_bus_frequency/1000/1000);
+
+ return 0;
+}
+
+static void __init
+ev64360_calibrate_decr(void)
+{
+ u32 freq;
+
+ freq = ev64360_bus_frequency / 4;
+
+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ (long)freq / 1000000, (long)freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+unsigned long __init
+ev64360_find_end_of_memory(void)
+{
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_MV64360);
+}
+
+static inline void
+ev64360_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT2U, 0xf0001ffe);
+ mtspr(SPRN_DBAT2L, 0xf000002a);
+ mb();
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+ev64360_map_io(void)
+{
+ io_block_mapping(CONFIG_MV64X60_NEW_BASE, \
+ CONFIG_MV64X60_NEW_BASE, \
+ 0x00020000, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ /* copy board info structure */
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ /* copy command line */
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+ #ifdef CONFIG_ISA
+ isa_mem_base = 0;
+ #endif
+
+ ppc_md.setup_arch = ev64360_setup_arch;
+ ppc_md.show_cpuinfo = ev64360_show_cpuinfo;
+ ppc_md.init_IRQ = mv64360_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.restart = ev64360_restart;
+ ppc_md.power_off = ev64360_power_off;
+ ppc_md.halt = ev64360_halt;
+ ppc_md.find_end_of_memory = ev64360_find_end_of_memory;
+ ppc_md.calibrate_decr = ev64360_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ ppc_md.setup_io_mappings = ev64360_map_io;
+ ppc_md.progress = mv64x60_mpsc_progress;
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+ platform_notify = ev64360_platform_notify;
+#endif
+
+ ev64360_set_bat(); /* Need for ev64360_find_end_of_memory and progress */
+}
diff --git a/arch/ppc/platforms/ev64360.h b/arch/ppc/platforms/ev64360.h
new file mode 100644
index 000000000000..68eabe490397
--- /dev/null
+++ b/arch/ppc/platforms/ev64360.h
@@ -0,0 +1,116 @@
+/*
+ * arch/ppc/platforms/ev64360.h
+ *
+ * Definitions for Marvell EV-64360-BP Evaluation Board.
+ *
+ * Author: Lee Nicks <allinux@gmail.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64KB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 0x42000000-0x4203ffff - Internal SRAM
+ * 0xf1000000-0xf100ffff - MV64360 Registers (CONFIG_MV64X60_NEW_BASE)
+ * 0xfc800000-0xfcffffff - RTC
+ * 0xff000000-0xffffffff - Boot window, 16 MB flash
+ * 0xc0000000-0xc3ffffff - PCI I/O (second hose)
+ * 0x80000000-0xbfffffff - PCI MEM (second hose)
+ */
+
+#ifndef __PPC_PLATFORMS_EV64360_H
+#define __PPC_PLATFORMS_EV64360_H
+
+/* CPU Physical Memory Map setup. */
+#define EV64360_BOOT_WINDOW_BASE 0xff000000
+#define EV64360_BOOT_WINDOW_SIZE 0x01000000 /* 16 MB */
+#define EV64360_INTERNAL_SRAM_BASE 0x42000000
+#define EV64360_RTC_WINDOW_BASE 0xfc800000
+#define EV64360_RTC_WINDOW_SIZE 0x00800000 /* 8 MB */
+
+#define EV64360_PCI1_MEM_START_PROC_ADDR 0x80000000
+#define EV64360_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
+#define EV64360_PCI1_MEM_START_PCI_LO_ADDR 0x80000000
+#define EV64360_PCI1_MEM_SIZE 0x40000000 /* 1 GB */
+#define EV64360_PCI1_IO_START_PROC_ADDR 0xc0000000
+#define EV64360_PCI1_IO_START_PCI_ADDR 0x00000000
+#define EV64360_PCI1_IO_SIZE 0x04000000 /* 64 MB */
+
+#define EV64360_DEFAULT_BAUD 115200
+#define EV64360_MPSC_CLK_SRC 8 /* TCLK */
+#define EV64360_MPSC_CLK_FREQ 133333333
+
+#define EV64360_MTD_RESERVED_SIZE 0x40000
+#define EV64360_MTD_JFFS2_SIZE 0xec0000
+#define EV64360_MTD_UBOOT_SIZE 0x100000
+
+#define EV64360_ETH0_PHY_ADDR 8
+#define EV64360_ETH1_PHY_ADDR 9
+#define EV64360_ETH2_PHY_ADDR 10
+
+#define EV64360_ETH_TX_QUEUE_SIZE 800
+#define EV64360_ETH_RX_QUEUE_SIZE 400
+
+#define EV64360_ETH_PORT_CONFIG_VALUE \
+ ETH_UNICAST_NORMAL_MODE | \
+ ETH_DEFAULT_RX_QUEUE_0 | \
+ ETH_DEFAULT_RX_ARP_QUEUE_0 | \
+ ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ ETH_RECEIVE_BC_IF_IP | \
+ ETH_RECEIVE_BC_IF_ARP | \
+ ETH_CAPTURE_TCP_FRAMES_DIS | \
+ ETH_CAPTURE_UDP_FRAMES_DIS | \
+ ETH_DEFAULT_RX_TCP_QUEUE_0 | \
+ ETH_DEFAULT_RX_UDP_QUEUE_0 | \
+ ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define EV64360_ETH_PORT_CONFIG_EXTEND_VALUE \
+ ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
+ ETH_PARTITION_DISABLE
+
+#define GT_ETH_IPG_INT_RX(value) \
+ ((value & 0x3fff) << 8)
+
+#define EV64360_ETH_PORT_SDMA_CONFIG_VALUE \
+ ETH_RX_BURST_SIZE_4_64BIT | \
+ GT_ETH_IPG_INT_RX(0) | \
+ ETH_TX_BURST_SIZE_4_64BIT
+
+#define EV64360_ETH_PORT_SERIAL_CONTROL_VALUE \
+ ETH_FORCE_LINK_PASS | \
+ ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
+ ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ ETH_ADV_SYMMETRIC_FLOW_CTRL | \
+ ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ ETH_FORCE_BP_MODE_NO_JAM | \
+ BIT9 | \
+ ETH_DO_NOT_FORCE_LINK_FAIL | \
+ ETH_RETRANSMIT_16_ATTEMPTS | \
+ ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
+ ETH_DTE_ADV_0 | \
+ ETH_DISABLE_AUTO_NEG_BYPASS | \
+ ETH_AUTO_NEG_NO_CHANGE | \
+ ETH_MAX_RX_PACKET_9700BYTE | \
+ ETH_CLR_EXT_LOOPBACK | \
+ ETH_SET_FULL_DUPLEX_MODE | \
+ ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+static inline u32
+ev64360_bus_freq(void)
+{
+ return 133333333;
+}
+
+#endif /* __PPC_PLATFORMS_EV64360_H */
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
index b659d7b3d747..ff3796860123 100644
--- a/arch/ppc/platforms/hdpu.c
+++ b/arch/ppc/platforms/hdpu.c
@@ -58,7 +58,7 @@ static void parse_bootinfo(unsigned long r3,
static void hdpu_set_l1pe(void);
static void hdpu_cpustate_set(unsigned char new_state);
#ifdef CONFIG_SMP
-static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(timebase_lock);
static unsigned int timebase_upper = 0, timebase_lower = 0;
extern int smp_tb_synchronized;
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
deleted file mode 100644
index aacb438708ff..000000000000
--- a/arch/ppc/platforms/k2.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * arch/ppc/platforms/k2.c
- *
- * Board setup routines for SBS K2
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * Updated by: Randy Vinson <rvinson@mvista.com.
- *
- * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/i8259.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-
-#include <syslib/cpc710.h>
-#include "k2.h"
-
-extern unsigned long loops_per_jiffy;
-extern void gen550_progress(char *, unsigned short);
-
-static unsigned int cpu_7xx[16] = {
- 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
-static unsigned int cpu_6xx[16] = {
- 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
-};
-
-static inline int __init
-k2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- /*
- * Check our hose index. If we are zero then we are on the
- * local PCI hose, otherwise we are on the cPCI hose.
- */
- if (!hose->index) {
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- {1, 0, 0, 0}, /* Ethernet */
- {5, 5, 5, 5}, /* PMC Site 1 */
- {6, 6, 6, 6}, /* PMC Site 2 */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* PCI-ISA Bridge */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {0, 0, 0, 0}, /* unused */
- {15, 0, 0, 0}, /* M5229 IDE */
- };
- const long min_idsel = 3, max_idsel = 17, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
- } else {
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- {10, 11, 12, 9}, /* cPCI slot 8 */
- {11, 12, 9, 10}, /* cPCI slot 7 */
- {12, 9, 10, 11}, /* cPCI slot 6 */
- {9, 10, 11, 12}, /* cPCI slot 5 */
- {10, 11, 12, 9}, /* cPCI slot 4 */
- {11, 12, 9, 10}, /* cPCI slot 3 */
- {12, 9, 10, 11}, /* cPCI slot 2 */
- };
- const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
- }
-}
-
-void k2_pcibios_fixup(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- struct pci_dev *ide_dev;
-
- /*
- * Enable DMA support on hdc
- */
- ide_dev = pci_get_device(PCI_VENDOR_ID_AL,
- PCI_DEVICE_ID_AL_M5229, NULL);
-
- if (ide_dev) {
-
- unsigned long ide_dma_base;
-
- ide_dma_base = pci_resource_start(ide_dev, 4);
- outb(0x00, ide_dma_base + 0x2);
- outb(0x20, ide_dma_base + 0xa);
- pci_dev_put(ide_dev);
- }
-#endif
-}
-
-void k2_pcibios_fixup_resources(struct pci_dev *dev)
-{
- int i;
-
- if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
- (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64)) {
- pr_debug("Fixup CPC710 resources\n");
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- }
- }
-}
-
-void k2_setup_hoses(void)
-{
- struct pci_controller *hose_a, *hose_b;
-
- /*
- * Reconfigure CPC710 memory map so
- * we have some more PCI memory space.
- */
-
- /* Set FPHB mode */
- __raw_writel(0x808000e0, PGCHP); /* Set FPHB mode */
-
- /* PCI32 mappings */
- __raw_writel(0x00000000, K2_PCI32_BAR + PIBAR); /* PCI I/O base */
- __raw_writel(0x00000000, K2_PCI32_BAR + PMBAR); /* PCI Mem base */
- __raw_writel(0xf0000000, K2_PCI32_BAR + MSIZE); /* 256MB */
- __raw_writel(0xfff00000, K2_PCI32_BAR + IOSIZE); /* 1MB */
- __raw_writel(0xc0000000, K2_PCI32_BAR + SMBAR); /* Base@0xc0000000 */
- __raw_writel(0x80000000, K2_PCI32_BAR + SIBAR); /* Base@0x80000000 */
- __raw_writel(0x000000c0, K2_PCI32_BAR + PSSIZE); /* 1GB space */
- __raw_writel(0x000000c0, K2_PCI32_BAR + PPSIZE); /* 1GB space */
- __raw_writel(0x00000000, K2_PCI32_BAR + BARPS); /* Base@0x00000000 */
- __raw_writel(0x00000000, K2_PCI32_BAR + BARPP); /* Base@0x00000000 */
- __raw_writel(0x00000080, K2_PCI32_BAR + PSBAR); /* Base@0x80 */
- __raw_writel(0x00000000, K2_PCI32_BAR + PPBAR);
-
- __raw_writel(0xc0000000, K2_PCI32_BAR + BPMDLK);
- __raw_writel(0xd0000000, K2_PCI32_BAR + TPMDLK);
- __raw_writel(0x80000000, K2_PCI32_BAR + BIODLK);
- __raw_writel(0x80100000, K2_PCI32_BAR + TIODLK);
- __raw_writel(0xe0008000, K2_PCI32_BAR + DLKCTRL);
- __raw_writel(0xffffffff, K2_PCI32_BAR + DLKDEV);
-
- /* PCI64 mappings */
- __raw_writel(0x00100000, K2_PCI64_BAR + PIBAR); /* PCI I/O base */
- __raw_writel(0x10000000, K2_PCI64_BAR + PMBAR); /* PCI Mem base */
- __raw_writel(0xf0000000, K2_PCI64_BAR + MSIZE); /* 256MB */
- __raw_writel(0xfff00000, K2_PCI64_BAR + IOSIZE); /* 1MB */
- __raw_writel(0xd0000000, K2_PCI64_BAR + SMBAR); /* Base@0xd0000000 */
- __raw_writel(0x80100000, K2_PCI64_BAR + SIBAR); /* Base@0x80100000 */
- __raw_writel(0x000000c0, K2_PCI64_BAR + PSSIZE); /* 1GB space */
- __raw_writel(0x000000c0, K2_PCI64_BAR + PPSIZE); /* 1GB space */
- __raw_writel(0x00000000, K2_PCI64_BAR + BARPS); /* Base@0x00000000 */
- __raw_writel(0x00000000, K2_PCI64_BAR + BARPP); /* Base@0x00000000 */
-
- /* Setup PCI32 hose */
- hose_a = pcibios_alloc_controller();
- if (!hose_a)
- return;
-
- hose_a->first_busno = 0;
- hose_a->last_busno = 0xff;
- hose_a->pci_mem_offset = K2_PCI32_MEM_BASE;
-
- pci_init_resource(&hose_a->io_resource,
- K2_PCI32_LOWER_IO,
- K2_PCI32_UPPER_IO,
- IORESOURCE_IO, "PCI32 host bridge");
-
- pci_init_resource(&hose_a->mem_resources[0],
- K2_PCI32_LOWER_MEM + K2_PCI32_MEM_BASE,
- K2_PCI32_UPPER_MEM + K2_PCI32_MEM_BASE,
- IORESOURCE_MEM, "PCI32 host bridge");
-
- hose_a->io_space.start = K2_PCI32_LOWER_IO;
- hose_a->io_space.end = K2_PCI32_UPPER_IO;
- hose_a->mem_space.start = K2_PCI32_LOWER_MEM;
- hose_a->mem_space.end = K2_PCI32_UPPER_MEM;
- hose_a->io_base_virt = (void *)K2_ISA_IO_BASE;
-
- setup_indirect_pci(hose_a, K2_PCI32_CONFIG_ADDR, K2_PCI32_CONFIG_DATA);
-
- /* Initialize PCI32 bus registers */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_BUS_NUMBER, hose_a->first_busno);
-
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
-
- /* Enable PCI interrupt polling */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x45, 0x80);
-
- /* Route polled PCI interrupts */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x48, 0x58);
-
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x49, 0x07);
-
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x4a, 0x31);
-
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x4b, 0xb9);
-
- /* route secondary IDE channel interrupt to IRQ 15 */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x75, 0x0f);
-
- /* enable IDE controller IDSEL */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(8, 0), 0x58, 0x48);
-
- /* Enable IDE function */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(17, 0), 0x50, 0x03);
-
- /* Set M5229 IDE controller to native mode */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(17, 0), PCI_CLASS_PROG, 0xdf);
-
- hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
-
- /* Write out correct max subordinate bus number for hose A */
- early_write_config_byte(hose_a,
- hose_a->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
-
- /* Only setup PCI64 hose if we are in the system slot */
- if (!(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK)) {
- /* Setup PCI64 hose */
- hose_b = pcibios_alloc_controller();
- if (!hose_b)
- return;
-
- hose_b->first_busno = hose_a->last_busno + 1;
- hose_b->last_busno = 0xff;
-
- /* Reminder: quit changing the following, it is correct. */
- hose_b->pci_mem_offset = K2_PCI32_MEM_BASE;
-
- pci_init_resource(&hose_b->io_resource,
- K2_PCI64_LOWER_IO,
- K2_PCI64_UPPER_IO,
- IORESOURCE_IO, "PCI64 host bridge");
-
- pci_init_resource(&hose_b->mem_resources[0],
- K2_PCI64_LOWER_MEM + K2_PCI32_MEM_BASE,
- K2_PCI64_UPPER_MEM + K2_PCI32_MEM_BASE,
- IORESOURCE_MEM, "PCI64 host bridge");
-
- hose_b->io_space.start = K2_PCI64_LOWER_IO;
- hose_b->io_space.end = K2_PCI64_UPPER_IO;
- hose_b->mem_space.start = K2_PCI64_LOWER_MEM;
- hose_b->mem_space.end = K2_PCI64_UPPER_MEM;
- hose_b->io_base_virt = (void *)K2_ISA_IO_BASE;
-
- setup_indirect_pci(hose_b,
- K2_PCI64_CONFIG_ADDR, K2_PCI64_CONFIG_DATA);
-
- /* Initialize PCI64 bus registers */
- early_write_config_byte(hose_b,
- 0,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER, 0xff);
-
- early_write_config_byte(hose_b,
- 0,
- PCI_DEVFN(0, 0),
- CPC710_BUS_NUMBER, hose_b->first_busno);
-
- hose_b->last_busno = pciauto_bus_scan(hose_b,
- hose_b->first_busno);
-
- /* Write out correct max subordinate bus number for hose B */
- early_write_config_byte(hose_b,
- hose_b->first_busno,
- PCI_DEVFN(0, 0),
- CPC710_SUB_BUS_NUMBER,
- hose_b->last_busno);
-
- /* Configure PCI64 PSBAR */
- early_write_config_dword(hose_b,
- hose_b->first_busno,
- PCI_DEVFN(0, 0),
- PCI_BASE_ADDRESS_0,
- K2_PCI64_SYS_MEM_BASE);
- }
-
- /* Configure i8259 level/edge settings */
- outb(0x62, 0x4d0);
- outb(0xde, 0x4d1);
-
-#ifdef CONFIG_CPC710_DATA_GATHERING
- {
- unsigned int tmp;
- tmp = __raw_readl(ABCNTL);
- /* Enable data gathering on both PCI interfaces */
- __raw_writel(tmp | 0x05000000, ABCNTL);
- }
-#endif
-
- ppc_md.pcibios_fixup = k2_pcibios_fixup;
- ppc_md.pcibios_fixup_resources = k2_pcibios_fixup_resources;
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = k2_map_irq;
-}
-
-static int k2_get_bus_speed(void)
-{
- int bus_speed;
- unsigned char board_id;
-
- board_id = *(unsigned char *)K2_BOARD_ID_REG;
-
- switch (K2_BUS_SPD(board_id)) {
-
- case 0:
- default:
- bus_speed = 100000000;
- break;
-
- case 1:
- bus_speed = 83333333;
- break;
-
- case 2:
- bus_speed = 75000000;
- break;
-
- case 3:
- bus_speed = 66666666;
- break;
- }
- return bus_speed;
-}
-
-static int k2_get_cpu_speed(void)
-{
- unsigned long hid1;
- int cpu_speed;
-
- hid1 = mfspr(SPRN_HID1) >> 28;
-
- if ((mfspr(SPRN_PVR) >> 16) == 8)
- hid1 = cpu_7xx[hid1];
- else
- hid1 = cpu_6xx[hid1];
-
- cpu_speed = k2_get_bus_speed() * hid1 / 2;
- return cpu_speed;
-}
-
-static void __init k2_calibrate_decr(void)
-{
- int freq, divisor = 4;
-
- /* determine processor bus speed */
- freq = k2_get_bus_speed();
- tb_ticks_per_jiffy = freq / HZ / divisor;
- tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
-}
-
-static int k2_show_cpuinfo(struct seq_file *m)
-{
- unsigned char k2_geo_bits, k2_system_slot;
-
- seq_printf(m, "vendor\t\t: SBS\n");
- seq_printf(m, "machine\t\t: K2\n");
- seq_printf(m, "cpu speed\t: %dMhz\n", k2_get_cpu_speed() / 1000000);
- seq_printf(m, "bus speed\t: %dMhz\n", k2_get_bus_speed() / 1000000);
- seq_printf(m, "memory type\t: SDRAM\n");
-
- k2_geo_bits = readb(K2_MSIZ_GEO_REG) & K2_GEO_ADR_MASK;
- k2_system_slot = !(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK);
- seq_printf(m, "backplane\t: %s slot board",
- k2_system_slot ? "System" : "Non system");
- seq_printf(m, "with geographical address %x\n", k2_geo_bits);
-
- return 0;
-}
-
-TODC_ALLOC();
-
-static void __init k2_setup_arch(void)
-{
- unsigned int cpu;
-
- /* Setup TODC access */
- TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
- ioremap(K2_RTC_BASE_ADDRESS, K2_RTC_SIZE), 8);
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000 / HZ;
-
- /* make FLASH transactions higher priority than PCI to avoid deadlock */
- __raw_writel(__raw_readl(SIOC1) | 0x80000000, SIOC1);
-
- /* Set hardware to access FLASH page 2 */
- __raw_writel(1 << 29, GPOUT);
-
- /* Setup PCI host bridges */
- k2_setup_hoses();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDC1;
-#endif
-
- /* Identify the system */
- printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
- "%d Mhz\n", k2_get_cpu_speed() / 1000000);
- printk(KERN_INFO "Port by MontaVista Software, Inc. "
- "(source@mvista.com)\n");
-
- /* Identify the CPU manufacturer */
- cpu = PVR_REV(mfspr(SPRN_PVR));
- printk(KERN_INFO "CPU manufacturer: %s [rev=%04x]\n",
- (cpu & (1 << 15)) ? "IBM" : "Motorola", cpu);
-}
-
-static void k2_restart(char *cmd)
-{
- local_irq_disable();
-
- /* Flip FLASH back to page 1 to access firmware image */
- __raw_writel(0, GPOUT);
-
- /* SRR0 has system reset vector, SRR1 has default MSR value */
- /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
- mtspr(SPRN_SRR0, 0xfff00100);
- mtspr(SPRN_SRR1, 0);
- __asm__ __volatile__("rfi\n\t");
-
- /* not reached */
- for (;;) ;
-}
-
-static void k2_power_off(void)
-{
- for (;;) ;
-}
-
-static void k2_halt(void)
-{
- k2_restart(NULL);
-}
-
-/*
- * Set BAT 3 to map PCI32 I/O space.
- */
-static __inline__ void k2_set_bat(void)
-{
- /* wait for all outstanding memory accesses to complete */
- mb();
-
- /* setup DBATs */
- mtspr(SPRN_DBAT2U, 0x80001ffe);
- mtspr(SPRN_DBAT2L, 0x8000002a);
- mtspr(SPRN_DBAT3U, 0xf0001ffe);
- mtspr(SPRN_DBAT3L, 0xf000002a);
-
- /* wait for updates */
- mb();
-}
-
-static unsigned long __init k2_find_end_of_memory(void)
-{
- unsigned long total;
- unsigned char msize = 7; /* Default to 128MB */
-
- msize = K2_MEM_SIZE(readb(K2_MSIZ_GEO_REG));
-
- switch (msize) {
- case 2:
- /*
- * This will break without a lowered
- * KERNELBASE or CONFIG_HIGHMEM on.
- * It seems non 1GB builds exist yet,
- * though.
- */
- total = K2_MEM_SIZE_1GB;
- break;
- case 3:
- case 4:
- total = K2_MEM_SIZE_512MB;
- break;
- case 5:
- case 6:
- total = K2_MEM_SIZE_256MB;
- break;
- case 7:
- total = K2_MEM_SIZE_128MB;
- break;
- default:
- printk
- ("K2: Invalid memory size detected, defaulting to 128MB\n");
- total = K2_MEM_SIZE_128MB;
- break;
- }
- return total;
-}
-
-static void __init k2_map_io(void)
-{
- io_block_mapping(K2_PCI32_IO_BASE,
- K2_PCI32_IO_BASE, 0x00200000, _PAGE_IO);
- io_block_mapping(0xff000000, 0xff000000, 0x01000000, _PAGE_IO);
-}
-
-static void __init k2_init_irq(void)
-{
- int i;
-
- for (i = 0; i < 16; i++)
- irq_desc[i].handler = &i8259_pic;
-
- i8259_init(0);
-}
-
-void __init platform_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7)
-{
- parse_bootinfo((struct bi_record *)(r3 + KERNELBASE));
-
- k2_set_bat();
-
- isa_io_base = K2_ISA_IO_BASE;
- isa_mem_base = K2_ISA_MEM_BASE;
- pci_dram_offset = K2_PCI32_SYS_MEM_BASE;
-
- ppc_md.setup_arch = k2_setup_arch;
- ppc_md.show_cpuinfo = k2_show_cpuinfo;
- ppc_md.init_IRQ = k2_init_irq;
- ppc_md.get_irq = i8259_irq;
-
- ppc_md.find_end_of_memory = k2_find_end_of_memory;
- ppc_md.setup_io_mappings = k2_map_io;
-
- ppc_md.restart = k2_restart;
- ppc_md.power_off = k2_power_off;
- ppc_md.halt = k2_halt;
-
- ppc_md.time_init = todc_time_init;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.calibrate_decr = k2_calibrate_decr;
-
- ppc_md.nvram_read_val = todc_direct_read_val;
- ppc_md.nvram_write_val = todc_direct_write_val;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = gen550_progress;
-#endif
-}
diff --git a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h
deleted file mode 100644
index 78326aba1988..000000000000
--- a/arch/ppc/platforms/k2.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * arch/ppc/platforms/k2.h
- *
- * Definitions for SBS K2 board support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (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 __PPC_PLATFORMS_K2_H
-#define __PPC_PLATFORMS_K2_H
-
-/*
- * SBS K2 definitions
- */
-
-#define K2_PCI64_BAR 0xff400000
-#define K2_PCI32_BAR 0xff500000
-
-#define K2_PCI64_CONFIG_ADDR (K2_PCI64_BAR + 0x000f8000)
-#define K2_PCI64_CONFIG_DATA (K2_PCI64_BAR + 0x000f8010)
-
-#define K2_PCI32_CONFIG_ADDR (K2_PCI32_BAR + 0x000f8000)
-#define K2_PCI32_CONFIG_DATA (K2_PCI32_BAR + 0x000f8010)
-
-#define K2_PCI64_MEM_BASE 0xd0000000
-#define K2_PCI64_IO_BASE 0x80100000
-
-#define K2_PCI32_MEM_BASE 0xc0000000
-#define K2_PCI32_IO_BASE 0x80000000
-
-#define K2_PCI32_SYS_MEM_BASE 0x80000000
-#define K2_PCI64_SYS_MEM_BASE K2_PCI32_SYS_MEM_BASE
-
-#define K2_PCI32_LOWER_MEM 0x00000000
-#define K2_PCI32_UPPER_MEM 0x0fffffff
-#define K2_PCI32_LOWER_IO 0x00000000
-#define K2_PCI32_UPPER_IO 0x000fffff
-
-#define K2_PCI64_LOWER_MEM 0x10000000
-#define K2_PCI64_UPPER_MEM 0x1fffffff
-#define K2_PCI64_LOWER_IO 0x00100000
-#define K2_PCI64_UPPER_IO 0x001fffff
-
-#define K2_ISA_IO_BASE K2_PCI32_IO_BASE
-#define K2_ISA_MEM_BASE K2_PCI32_MEM_BASE
-
-#define K2_BOARD_ID_REG (K2_ISA_IO_BASE + 0x800)
-#define K2_MISC_REG (K2_ISA_IO_BASE + 0x804)
-#define K2_MSIZ_GEO_REG (K2_ISA_IO_BASE + 0x808)
-#define K2_HOT_SWAP_REG (K2_ISA_IO_BASE + 0x80c)
-#define K2_PLD2_REG (K2_ISA_IO_BASE + 0x80e)
-#define K2_PLD3_REG (K2_ISA_IO_BASE + 0x80f)
-
-#define K2_BUS_SPD(board_id) (board_id >> 2) & 3
-
-#define K2_RTC_BASE_OFFSET 0x90000
-#define K2_RTC_BASE_ADDRESS (K2_PCI32_MEM_BASE + K2_RTC_BASE_OFFSET)
-#define K2_RTC_SIZE 0x8000
-
-#define K2_MEM_SIZE_MASK 0xe0
-#define K2_MEM_SIZE(size_reg) (size_reg & K2_MEM_SIZE_MASK) >> 5
-#define K2_MEM_SIZE_1GB 0x40000000
-#define K2_MEM_SIZE_512MB 0x20000000
-#define K2_MEM_SIZE_256MB 0x10000000
-#define K2_MEM_SIZE_128MB 0x08000000
-
-#define K2_L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */
-#define K2_L2CACHE_512KB 0x00 /* 512KB */
-#define K2_L2CACHE_256KB 0x01 /* 256KB */
-#define K2_L2CACHE_1MB 0x02 /* 1MB */
-#define K2_L2CACHE_NONE 0x03 /* None */
-
-#define K2_GEO_ADR_MASK 0x1f
-
-#define K2_SYS_SLOT_MASK 0x08
-
-#endif /* __PPC_PLATFORMS_K2_H */
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
index 169dbf6534b9..2b53afae0e9c 100644
--- a/arch/ppc/platforms/katana.c
+++ b/arch/ppc/platforms/katana.c
@@ -33,6 +33,7 @@
#include <linux/bootimg.h>
#endif
#include <asm/io.h>
+#include <asm/unistd.h>
#include <asm/page.h>
#include <asm/time.h>
#include <asm/smp.h>
@@ -42,15 +43,14 @@
#include <asm/mv64x60.h>
#include <platforms/katana.h>
-static struct mv64x60_handle bh;
-static katana_id_t katana_id;
-static void __iomem *cpld_base;
-static void __iomem *sram_base;
-
-static u32 katana_flash_size_0;
-static u32 katana_flash_size_1;
-
-static u32 katana_bus_frequency;
+static struct mv64x60_handle bh;
+static katana_id_t katana_id;
+static void __iomem *cpld_base;
+static void __iomem *sram_base;
+static u32 katana_flash_size_0;
+static u32 katana_flash_size_1;
+static u32 katana_bus_frequency;
+static struct pci_controller katana_hose_a;
unsigned char __res[sizeof(bd_t)];
@@ -71,8 +71,12 @@ katana_irq_lookup_750i(unsigned char idsel, unsigned char pin)
KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i },
/* IDSEL 6 (T8110) */
{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
+ /* IDSEL 7 (unused) */
+ {0, 0, 0, 0 },
+ /* IDSEL 8 (Intel 82544) (752i only but doesn't harm 750i) */
+ {KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
};
- const long min_idsel = 4, max_idsel = 6, irqs_per_slot = 4;
+ const long min_idsel = 4, max_idsel = 8, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
@@ -148,7 +152,7 @@ katana_get_proc_num(void)
save_exclude = mv64x60_pci_exclude_bridge;
mv64x60_pci_exclude_bridge = 0;
- early_read_config_word(bh.hose_a, 0,
+ early_read_config_word(bh.hose_b, 0,
PCI_DEVFN(0,0), PCI_DEVICE_ID, &val);
mv64x60_pci_exclude_bridge = save_exclude;
@@ -191,7 +195,8 @@ katana_setup_bridge(void)
struct mv64x60_setup_info si;
void __iomem *vaddr;
int i;
- u16 val;
+ u32 v;
+ u16 val, type;
u8 save_exclude;
/*
@@ -222,6 +227,20 @@ katana_setup_bridge(void)
PCI_DEVICE_ID, val);
}
+ /*
+ * While we're in here, set the hotswap register correctly.
+ * Turn off blue LED; mask ENUM#, clear insertion & extraction bits.
+ */
+ early_read_config_dword(&hose, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, &v);
+ v &= ~(1<<19);
+ v |= ((1<<17) | (1<<22) | (1<<23));
+ early_write_config_dword(&hose, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, v);
+
+ /* While we're at it, grab the bridge type for later */
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_DEVICE_ID, &type);
+
mv64x60_pci_exclude_bridge = save_exclude;
iounmap(vaddr);
@@ -251,21 +270,23 @@ katana_setup_bridge(void)
si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
si.pci_1.acc_cntl_options[i] =
- MV64360_PCI_ACC_CNTL_SNOOP_NONE |
- MV64360_PCI_ACC_CNTL_SWAP_NONE |
- MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
- MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
#else
si.cpu_prot_options[i] = 0;
- si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
- si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
- si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
si.pci_1.acc_cntl_options[i] =
- MV64360_PCI_ACC_CNTL_SNOOP_WB |
- MV64360_PCI_ACC_CNTL_SWAP_NONE |
- MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
- MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ ((type == PCI_DEVICE_ID_MARVELL_MV64360) ?
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES :
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES);
#endif
}
@@ -281,12 +302,26 @@ katana_setup_bridge(void)
mv64x60_set_bus(&bh, 1, 0);
bh.hose_b->first_busno = 0;
bh.hose_b->last_busno = 0xff;
+
+ /*
+ * Need to access hotswap reg which is in the pci config area of the
+ * bridge's hose 0. Note that pcibios_alloc_controller() can't be used
+ * to alloc hose_a b/c that would make hose 0 known to the generic
+ * pci code which we don't want.
+ */
+ bh.hose_a = &katana_hose_a;
+ setup_indirect_pci_nomap(bh.hose_a,
+ bh.v_base + MV64x60_PCI0_CONFIG_ADDR,
+ bh.v_base + MV64x60_PCI0_CONFIG_DATA);
}
/* Bridge & platform setup routines */
void __init
katana_intr_setup(void)
{
+ if (bh.type == MV64x60_TYPE_MV64460) /* As per instns from Marvell */
+ mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, 1 << 15);
+
/* MPP 8, 9, and 10 */
mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff);
@@ -309,9 +344,16 @@ katana_intr_setup(void)
/* Config GPP intr ctlr to respond to level trigger */
mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10));
- /* Erranum FEr PCI-#8 */
- mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9));
- mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9));
+ if (bh.type == MV64x60_TYPE_MV64360) {
+ /* Erratum FEr PCI-#9 */
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD,
+ (1<<4) | (1<<5) | (1<<6) | (1<<7));
+ mv64x60_set_bits(&bh, MV64x60_PCI1_CMD, (1<<8) | (1<<9));
+ } else {
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<6) | (1<<7));
+ mv64x60_set_bits(&bh, MV64x60_PCI1_CMD,
+ (1<<4) | (1<<5) | (1<<8) | (1<<9));
+ }
/*
* Dismiss and then enable interrupt on GPP interrupt cause
@@ -473,17 +515,46 @@ katana_setup_arch(void)
ppc_md.progress("katana_setup_arch: exit", 0);
}
+void
+katana_fixup_resources(struct pci_dev *dev)
+{
+ u16 v16;
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_LINE_SIZE>>2);
+
+ pci_read_config_word(dev, PCI_COMMAND, &v16);
+ v16 |= PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK;
+ pci_write_config_word(dev, PCI_COMMAND, v16);
+}
+
+static const unsigned int cpu_750xx[32] = { /* 750FX & 750GX */
+ 0, 0, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,/* 0-15*/
+ 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0 /*16-31*/
+};
+
+static int
+katana_get_cpu_freq(void)
+{
+ unsigned long pll_cfg;
+
+ pll_cfg = (mfspr(SPRN_HID1) & 0xf8000000) >> 27;
+ return katana_bus_frequency * cpu_750xx[pll_cfg]/2;
+}
+
/* Platform device data fixup routines. */
#if defined(CONFIG_SERIAL_MPSC)
static void __init
katana_fixup_mpsc_pdata(struct platform_device *pdev)
{
- struct mpsc_pdata *pdata;
+ struct mpsc_pdata *pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+ bd_t *bdp = (bd_t *)__res;
- pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+ if (bdp->bi_baudrate)
+ pdata->default_baud = bdp->bi_baudrate;
+ else
+ pdata->default_baud = KATANA_DEFAULT_BAUD;
pdata->max_idle = 40;
- pdata->default_baud = KATANA_DEFAULT_BAUD;
pdata->brg_clk_src = KATANA_MPSC_CLK_SRC;
/*
* TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts,
@@ -513,6 +584,18 @@ katana_fixup_eth_pdata(struct platform_device *pdev)
}
#endif
+#if defined(CONFIG_SYSFS)
+static void __init
+katana_fixup_mv64xxx_pdata(struct platform_device *pdev)
+{
+ struct mv64xxx_pdata *pdata = (struct mv64xxx_pdata *)
+ pdev->dev.platform_data;
+
+ /* Katana supports the mv64xxx hotswap register */
+ pdata->hs_reg_valid = 1;
+}
+#endif
+
static int __init
katana_platform_notify(struct device *dev)
{
@@ -529,6 +612,9 @@ katana_platform_notify(struct device *dev)
{ MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata },
{ MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata },
#endif
+#if defined(CONFIG_SYSFS)
+ { MV64XXX_DEV_NAME ".0", katana_fixup_mv64xxx_pdata },
+#endif
};
struct platform_device *pdev;
int i;
@@ -536,8 +622,7 @@ katana_platform_notify(struct device *dev)
if (dev && dev->bus_id)
for (i=0; i<ARRAY_SIZE(dev_map); i++)
if (!strncmp(dev->bus_id, dev_map[i].bus_id,
- BUS_ID_SIZE)) {
-
+ BUS_ID_SIZE)) {
pdev = container_of(dev,
struct platform_device, dev);
dev_map[i].rtn(pdev);
@@ -578,8 +663,7 @@ katana_setup_mtd(void)
ptbl_entries = (size >= (64*MB)) ? 6 : 4;
if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
- GFP_KERNEL)) == NULL) {
-
+ GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "Can't alloc MTD partition table\n");
return -ENOMEM;
}
@@ -611,7 +695,6 @@ katana_setup_mtd(void)
physmap_set_partitions(ptbl, ptbl_entries);
return 0;
}
-
arch_initcall(katana_setup_mtd);
#endif
@@ -632,7 +715,22 @@ katana_halt(void)
{
u8 v;
- if (katana_id == KATANA_ID_752I) {
+ /* Turn on blue LED to indicate its okay to remove */
+ if (katana_id == KATANA_ID_750I) {
+ u32 v;
+ u8 save_exclude;
+
+ /* Set LOO bit in cPCI HotSwap reg of hose 0 to turn on LED. */
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_read_config_dword(bh.hose_a, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, &v);
+ v &= 0xff;
+ v |= (1 << 19);
+ early_write_config_dword(bh.hose_a, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, v);
+ mv64x60_pci_exclude_bridge = save_exclude;
+ } else if (katana_id == KATANA_ID_752I) {
v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF);
v |= HSL_PLD_HOT_SWAP_LED_BIT;
out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v);
@@ -652,37 +750,65 @@ katana_power_off(void)
static int
katana_show_cpuinfo(struct seq_file *m)
{
+ char *s;
+
+ seq_printf(m, "cpu freq\t: %dMHz\n",
+ (katana_get_cpu_freq() + 500000) / 1000000);
+ seq_printf(m, "bus freq\t: %ldMHz\n",
+ ((long)katana_bus_frequency + 500000) / 1000000);
seq_printf(m, "vendor\t\t: Artesyn Communication Products, LLC\n");
seq_printf(m, "board\t\t: ");
-
switch (katana_id) {
case KATANA_ID_3750:
- seq_printf(m, "Katana 3750\n");
+ seq_printf(m, "Katana 3750");
break;
case KATANA_ID_750I:
- seq_printf(m, "Katana 750i\n");
+ seq_printf(m, "Katana 750i");
break;
case KATANA_ID_752I:
- seq_printf(m, "Katana 752i\n");
+ seq_printf(m, "Katana 752i");
break;
default:
- seq_printf(m, "Unknown\n");
+ seq_printf(m, "Unknown");
break;
}
-
- seq_printf(m, "product ID\t: 0x%x\n",
+ seq_printf(m, " (product id: 0x%x)\n",
in_8(cpld_base + KATANA_CPLD_PRODUCT_ID));
+
+ seq_printf(m, "pci mode\t: %sMonarch\n",
+ katana_is_monarch()? "" : "Non-");
seq_printf(m, "hardware rev\t: 0x%x\n",
in_8(cpld_base+KATANA_CPLD_HARDWARE_VER));
- seq_printf(m, "PLD rev\t\t: 0x%x\n",
+ seq_printf(m, "pld rev\t\t: 0x%x\n",
in_8(cpld_base + KATANA_CPLD_PLD_VER));
- seq_printf(m, "PLB freq\t: %ldMhz\n",
- (long)katana_bus_frequency / 1000000);
- seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-");
+
+ switch(bh.type) {
+ case MV64x60_TYPE_GT64260A:
+ s = "gt64260a";
+ break;
+ case MV64x60_TYPE_GT64260B:
+ s = "gt64260b";
+ break;
+ case MV64x60_TYPE_MV64360:
+ s = "mv64360";
+ break;
+ case MV64x60_TYPE_MV64460:
+ s = "mv64460";
+ break;
+ default:
+ s = "Unknown";
+ }
+ seq_printf(m, "bridge type\t: %s\n", s);
+ seq_printf(m, "bridge rev\t: 0x%x\n", bh.rev);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ seq_printf(m, "coherency\t: %s\n", "off");
+#else
+ seq_printf(m, "coherency\t: %s\n", "on");
+#endif
return 0;
}
@@ -701,11 +827,20 @@ katana_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
+/*
+ * The katana supports both uImage and zImage. If uImage, get the mem size
+ * from the bd info. If zImage, the bootwrapper adds a BI_MEMSIZE entry in
+ * the bi_rec data which is sucked out and put into boot_mem_size by
+ * parse_bootinfo(). MMU_init() will then use the boot_mem_size for the mem
+ * size and not call this routine. The only way this will fail is when a uImage
+ * is used but the fw doesn't pass in a valid bi_memsize. This should never
+ * happen, though.
+ */
unsigned long __init
katana_find_end_of_memory(void)
{
- return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
- MV64x60_TYPE_MV64360);
+ bd_t *bdp = (bd_t *)__res;
+ return bdp->bi_memsize;
}
#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00)
@@ -729,15 +864,6 @@ katana_rtc_hookup(void)
late_initcall(katana_rtc_hookup);
#endif
-static inline void
-katana_set_bat(void)
-{
- mb();
- mtspr(SPRN_DBAT2U, 0xf0001ffe);
- mtspr(SPRN_DBAT2L, 0xf000002a);
- mb();
-}
-
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
static void __init
katana_map_io(void)
@@ -763,15 +889,24 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
*/
if (r3 && r6) {
/* copy board info structure */
- memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ memcpy((void *)__res, (void *)(r3+KERNELBASE), sizeof(bd_t));
/* copy command line */
*(char *)(r7+KERNELBASE) = 0;
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
isa_mem_base = 0;
ppc_md.setup_arch = katana_setup_arch;
+ ppc_md.pcibios_fixup_resources = katana_fixup_resources;
ppc_md.show_cpuinfo = katana_show_cpuinfo;
ppc_md.init_IRQ = mv64360_init_irq;
ppc_md.get_irq = mv64360_get_irq;
@@ -790,6 +925,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
platform_notify = katana_platform_notify;
#endif
-
- katana_set_bat(); /* Need for katana_find_end_of_memory and progress */
}
diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h
index b82ed81950f5..597257eff2ec 100644
--- a/arch/ppc/platforms/katana.h
+++ b/arch/ppc/platforms/katana.h
@@ -56,14 +56,14 @@
#define KATANA_PCI1_IO_SIZE 0x04000000 /* 64 MB */
/* Board-specific IRQ info */
-#define KATANA_PCI_INTA_IRQ_3750 64+8
-#define KATANA_PCI_INTB_IRQ_3750 64+9
-#define KATANA_PCI_INTC_IRQ_3750 64+10
-
-#define KATANA_PCI_INTA_IRQ_750i 64+8
-#define KATANA_PCI_INTB_IRQ_750i 64+9
-#define KATANA_PCI_INTC_IRQ_750i 64+10
-#define KATANA_PCI_INTD_IRQ_750i 64+14
+#define KATANA_PCI_INTA_IRQ_3750 (64+8)
+#define KATANA_PCI_INTB_IRQ_3750 (64+9)
+#define KATANA_PCI_INTC_IRQ_3750 (64+10)
+
+#define KATANA_PCI_INTA_IRQ_750i (64+8)
+#define KATANA_PCI_INTB_IRQ_750i (64+9)
+#define KATANA_PCI_INTC_IRQ_750i (64+10)
+#define KATANA_PCI_INTD_IRQ_750i (64+14)
#define KATANA_CPLD_RST_EVENT 0x00000000
#define KATANA_CPLD_RST_CMD 0x00001000
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
deleted file mode 100644
index e88d294ea593..000000000000
--- a/arch/ppc/platforms/mcpn765.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * arch/ppc/platforms/mcpn765.c
- *
- * Board setup routines for the Motorola MCG MCPN765 cPCI Board.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * Modified by Randy Vinson (rvinson@mvista.com)
- *
- * 2001-2002 (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.
- */
-
-/*
- * This file adds support for the Motorola MCG MCPN765.
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/serial.h>
-#include <linux/tty.h> /* for linux/serial_core.h */
-#include <linux/serial_core.h>
-#include <linux/slab.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/time.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/open_pic.h>
-#include <asm/i8259.h>
-#include <asm/todc.h>
-#include <asm/pci-bridge.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bootinfo.h>
-#include <asm/hawk.h>
-#include <asm/kgdb.h>
-
-#include "mcpn765.h"
-
-static u_char mcpn765_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 17: COM1,2,3,4 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 18: Enet 1 (front) */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 19: HAWK WDT XXXX */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 20: 21554 bridge */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 21: cPCI INTA# */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 22: cPCI INTB# */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 23: cPCI INTC# */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 24: cPCI INTD# */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 25: PMC1 INTA#,PMC2 INTB#*/
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 26: PMC1 INTB#,PMC2 INTC#*/
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 27: PMC1 INTC#,PMC2 INTD#*/
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 28: PMC1 INTD#,PMC2 INTA#*/
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 29: Enet 2 (J3) */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 30: Abort Switch */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 31: RTC Alarm */
-};
-
-extern void mcpn765_set_VIA_IDE_native(void);
-
-extern u_int openpic_irq(void);
-extern char cmd_line[];
-
-extern void gen550_progress(char *, unsigned short);
-extern void gen550_init(int, struct uart_port *);
-
-int use_of_interrupt_tree = 0;
-
-static void mcpn765_halt(void);
-
-TODC_ALLOC();
-
-/*
- * Motorola MCG MCPN765 interrupt routing.
- */
-static inline int
-mcpn765_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
- */
- {
- { 14, 0, 0, 0 }, /* IDSEL 11 - have to manually set */
- { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
- { 0, 0, 0, 0 }, /* IDSEL 13 - unused */
- { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 0 */
- { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
- { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */
- { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */
- { 0, 0, 0, 0 }, /* IDSEL 18 - PMC 2B Connector XXXX */
- { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 1 */
- { 20, 0, 0, 0 }, /* IDSEL 20 - 21554 cPCI bridge */
- };
-
- const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-
-void __init
-mcpn765_set_VIA_IDE_legacy(void)
-{
- unsigned short vend, dev;
-
- early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
- early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
-
- if ((vend == PCI_VENDOR_ID_VIA) &&
- (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
-
- unsigned char temp;
-
- /* put back original "standard" port base addresses */
- early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
- PCI_BASE_ADDRESS_0, 0x1f1);
- early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
- PCI_BASE_ADDRESS_1, 0x3f5);
- early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
- PCI_BASE_ADDRESS_2, 0x171);
- early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
- PCI_BASE_ADDRESS_3, 0x375);
- early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
- PCI_BASE_ADDRESS_4, 0xcc01);
-
- /* put into legacy mode */
- early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
- &temp);
- temp &= ~0x05;
- early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
- temp);
- }
-}
-
-void
-mcpn765_set_VIA_IDE_native(void)
-{
- unsigned short vend, dev;
-
- early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
- early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
-
- if ((vend == PCI_VENDOR_ID_VIA) &&
- (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
-
- unsigned char temp;
-
- /* put into native mode */
- early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
- &temp);
- temp |= 0x05;
- early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
- temp);
- }
-}
-
-/*
- * Initialize the VIA 82c586b.
- */
-static void __init
-mcpn765_setup_via_82c586b(void)
-{
- struct pci_dev *dev;
- u_char c;
-
- if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_0,
- NULL)) == NULL) {
- printk("No VIA ISA bridge found\n");
- mcpn765_halt();
- /* NOTREACHED */
- }
-
- /*
- * If the firmware left the EISA 4d0/4d1 ports enabled, make sure
- * IRQ 14 is set for edge.
- */
- pci_read_config_byte(dev, 0x47, &c);
-
- if (c & (1<<5)) {
- c = inb(0x4d1);
- c &= ~(1<<6);
- outb(c, 0x4d1);
- }
-
- /* Disable PNP IRQ routing since we use the Hawk's MPIC */
- pci_write_config_dword(dev, 0x54, 0);
- pci_write_config_byte(dev, 0x58, 0);
-
- pci_dev_put(dev);
- if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_1,
- NULL)) == NULL) {
- printk("No VIA ISA bridge found\n");
- mcpn765_halt();
- /* NOTREACHED */
- }
-
- /*
- * PPCBug doesn't set the enable bits for the IDE device.
- * Turn them on now.
- */
- pci_read_config_byte(dev, 0x40, &c);
- c |= 0x03;
- pci_write_config_byte(dev, 0x40, c);
- pci_dev_put(dev);
-
- return;
-}
-
-void __init
-mcpn765_pcibios_fixup(void)
-{
- /* Do MCPN765 board specific initialization. */
- mcpn765_setup_via_82c586b();
-}
-
-void __init
-mcpn765_find_bridges(void)
-{
- struct pci_controller *hose;
-
- hose = pcibios_alloc_controller();
-
- if (!hose)
- return;
-
- hose->first_busno = 0;
- hose->last_busno = 0xff;
- hose->pci_mem_offset = MCPN765_PCI_PHY_MEM_OFFSET;
-
- pci_init_resource(&hose->io_resource,
- MCPN765_PCI_IO_START,
- MCPN765_PCI_IO_END,
- IORESOURCE_IO,
- "PCI host bridge");
-
- pci_init_resource(&hose->mem_resources[0],
- MCPN765_PCI_MEM_START,
- MCPN765_PCI_MEM_END,
- IORESOURCE_MEM,
- "PCI host bridge");
-
- hose->io_space.start = MCPN765_PCI_IO_START;
- hose->io_space.end = MCPN765_PCI_IO_END;
- hose->mem_space.start = MCPN765_PCI_MEM_START;
- hose->mem_space.end = MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE;
-
- if (hawk_init(hose,
- MCPN765_HAWK_PPC_REG_BASE,
- MCPN765_PROC_PCI_MEM_START,
- MCPN765_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
- MCPN765_PROC_PCI_IO_START,
- MCPN765_PROC_PCI_IO_END,
- MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE + 1) != 0) {
- printk("Could not initialize HAWK bridge\n");
- }
-
- /* VIA IDE BAR decoders are only 16-bits wide. PCI Auto Config
- * will reassign the bars outside of 16-bit I/O space, which will
- * "break" things. To prevent this, we'll set the IDE chip into
- * legacy mode and seed the bars with their legacy addresses (in 16-bit
- * I/O space). The Auto Config code will skip the IDE contoller in
- * legacy mode, so our bar values will stick.
- */
- mcpn765_set_VIA_IDE_legacy();
-
- hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
- /* Now that we've got 16-bit addresses in the bars, we can switch the
- * IDE controller back into native mode so we can do "modern" resource
- * and interrupt management.
- */
- mcpn765_set_VIA_IDE_native();
-
- ppc_md.pcibios_fixup = mcpn765_pcibios_fixup;
- ppc_md.pcibios_fixup_bus = NULL;
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = mcpn765_map_irq;
-
- return;
-}
-static void __init
-mcpn765_setup_arch(void)
-{
- struct pci_controller *hose;
-
- if ( ppc_md.progress )
- ppc_md.progress("mcpn765_setup_arch: enter", 0);
-
- loops_per_jiffy = 50000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_SDA2;
-#endif
-
- if ( ppc_md.progress )
- ppc_md.progress("mcpn765_setup_arch: find_bridges", 0);
-
- /* Lookup PCI host bridges */
- mcpn765_find_bridges();
-
- hose = pci_bus_to_hose(0);
- isa_io_base = (ulong)hose->io_base_virt;
-
- TODC_INIT(TODC_TYPE_MK48T37,
- (MCPN765_PHYS_NVRAM_AS0 - isa_io_base),
- (MCPN765_PHYS_NVRAM_AS1 - isa_io_base),
- (MCPN765_PHYS_NVRAM_DATA - isa_io_base),
- 8);
-
- OpenPIC_InitSenses = mcpn765_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof(mcpn765_openpic_initsenses);
-
- printk("Motorola MCG MCPN765 cPCI Non-System Board\n");
- printk("MCPN765 port (MontaVista Software, Inc. (source@mvista.com))\n");
-
- if ( ppc_md.progress )
- ppc_md.progress("mcpn765_setup_arch: exit", 0);
-
- return;
-}
-
-static void __init
-mcpn765_init2(void)
-{
-
- request_region(0x00,0x20,"dma1");
- request_region(0x20,0x20,"pic1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xa0,0x20,"pic2");
- request_region(0xc0,0x20,"dma2");
-
- return;
-}
-
-/*
- * Interrupt setup and service.
- * Have MPIC on HAWK and cascaded 8259s on VIA 82586 cascaded to MPIC.
- */
-static void __init
-mcpn765_init_IRQ(void)
-{
- int i;
-
- if ( ppc_md.progress )
- ppc_md.progress("init_irq: enter", 0);
-
- openpic_init(NUM_8259_INTERRUPTS);
- openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
- i8259_irq);
-
- for(i=0; i < NUM_8259_INTERRUPTS; i++)
- irq_desc[i].handler = &i8259_pic;
-
- i8259_init(0);
-
- if ( ppc_md.progress )
- ppc_md.progress("init_irq: exit", 0);
-
- return;
-}
-
-static u32
-mcpn765_irq_canonicalize(u32 irq)
-{
- if (irq == 2)
- return 9;
- else
- return irq;
-}
-
-static unsigned long __init
-mcpn765_find_end_of_memory(void)
-{
- return hawk_get_mem_size(MCPN765_HAWK_SMC_BASE);
-}
-
-static void __init
-mcpn765_map_io(void)
-{
- io_block_mapping(0xfe800000, 0xfe800000, 0x00800000, _PAGE_IO);
-}
-
-static void
-mcpn765_reset_board(void)
-{
- local_irq_disable();
-
- /* set VIA IDE controller into native mode */
- mcpn765_set_VIA_IDE_native();
-
- /* Set exception prefix high - to the firmware */
- _nmask_and_or_msr(0, MSR_IP);
-
- out_8((u_char *)MCPN765_BOARD_MODRST_REG, 0x01);
-
- return;
-}
-
-static void
-mcpn765_restart(char *cmd)
-{
- volatile ulong i = 10000000;
-
- mcpn765_reset_board();
-
- while (i-- > 0);
- panic("restart failed\n");
-}
-
-static void
-mcpn765_power_off(void)
-{
- mcpn765_halt();
- /* NOTREACHED */
-}
-
-static void
-mcpn765_halt(void)
-{
- local_irq_disable();
- while (1);
- /* NOTREACHED */
-}
-
-static int
-mcpn765_show_cpuinfo(struct seq_file *m)
-{
- seq_printf(m, "vendor\t\t: Motorola MCG\n");
- seq_printf(m, "machine\t\t: MCPN765\n");
-
- return 0;
-}
-
-/*
- * Set BAT 3 to map 0xf0000000 to end of physical memory space.
- */
-static __inline__ void
-mcpn765_set_bat(void)
-{
- mb();
- mtspr(SPRN_DBAT1U, 0xfe8000fe);
- mtspr(SPRN_DBAT1L, 0xfe80002a);
- mb();
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- /* Map in board regs, etc. */
- mcpn765_set_bat();
-
- isa_mem_base = MCPN765_ISA_MEM_BASE;
- pci_dram_offset = MCPN765_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = 0x00ffffff;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-
- ppc_md.setup_arch = mcpn765_setup_arch;
- ppc_md.show_cpuinfo = mcpn765_show_cpuinfo;
- ppc_md.irq_canonicalize = mcpn765_irq_canonicalize;
- ppc_md.init_IRQ = mcpn765_init_IRQ;
- ppc_md.get_irq = openpic_get_irq;
- ppc_md.init = mcpn765_init2;
-
- ppc_md.restart = mcpn765_restart;
- ppc_md.power_off = mcpn765_power_off;
- ppc_md.halt = mcpn765_halt;
-
- ppc_md.find_end_of_memory = mcpn765_find_end_of_memory;
- ppc_md.setup_io_mappings = mcpn765_map_io;
-
- ppc_md.time_init = todc_time_init;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.calibrate_decr = todc_calibrate_decr;
-
- ppc_md.nvram_read_val = todc_m48txx_read_val;
- ppc_md.nvram_write_val = todc_m48txx_write_val;
-
- ppc_md.heartbeat = NULL;
- ppc_md.heartbeat_reset = 0;
- ppc_md.heartbeat_count = 0;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = gen550_progress;
-#endif
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
-
- return;
-}
diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
deleted file mode 100644
index 4d35ecad097b..000000000000
--- a/arch/ppc/platforms/mcpn765.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * arch/ppc/platforms/mcpn765.h
- *
- * Definitions for Motorola MCG MCPN765 cPCI Board.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * From Processor to PCI:
- * PCI Mem Space: 0x80000000 - 0xc0000000 -> 0x80000000 - 0xc0000000 (1 GB)
- * PCI I/O Space: 0xfd800000 - 0xfe000000 -> 0x00000000 - 0x00800000 (8 MB)
- * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
- * MPIC in PCI Mem Space: 0xfe800000 - 0xfe830000 (not all used by MPIC)
- *
- * From PCI to Processor:
- * System Memory: 0x00000000 -> 0x00000000
- */
-
-#ifndef __PPC_PLATFORMS_MCPN765_H
-#define __PPC_PLATFORMS_MCPN765_H
-#include <linux/config.h>
-
-/* PCI Memory space mapping info */
-#define MCPN765_PCI_MEM_SIZE 0x40000000U
-#define MCPN765_PROC_PCI_MEM_START 0x80000000U
-#define MCPN765_PROC_PCI_MEM_END (MCPN765_PROC_PCI_MEM_START + \
- MCPN765_PCI_MEM_SIZE - 1)
-#define MCPN765_PCI_MEM_START 0x80000000U
-#define MCPN765_PCI_MEM_END (MCPN765_PCI_MEM_START + \
- MCPN765_PCI_MEM_SIZE - 1)
-
-/* PCI I/O space mapping info */
-#define MCPN765_PCI_IO_SIZE 0x00800000U
-#define MCPN765_PROC_PCI_IO_START 0xfd800000U
-#define MCPN765_PROC_PCI_IO_END (MCPN765_PROC_PCI_IO_START + \
- MCPN765_PCI_IO_SIZE - 1)
-#define MCPN765_PCI_IO_START 0x00000000U
-#define MCPN765_PCI_IO_END (MCPN765_PCI_IO_START + \
- MCPN765_PCI_IO_SIZE - 1)
-
-/* System memory mapping info */
-#define MCPN765_PCI_DRAM_OFFSET 0x00000000U
-#define MCPN765_PCI_PHY_MEM_OFFSET 0x00000000U
-
-#define MCPN765_ISA_MEM_BASE 0x00000000U
-#define MCPN765_ISA_IO_BASE MCPN765_PROC_PCI_IO_START
-
-/* Define base addresses for important sets of registers */
-#define MCPN765_HAWK_MPIC_BASE 0xfe800000U
-#define MCPN765_HAWK_SMC_BASE 0xfef80000U
-#define MCPN765_HAWK_PPC_REG_BASE 0xfeff0000U
-
-/* Define MCPN765 board register addresses. */
-#define MCPN765_BOARD_STATUS_REG 0xfef88080U
-#define MCPN765_BOARD_MODFAIL_REG 0xfef88090U
-#define MCPN765_BOARD_MODRST_REG 0xfef880a0U
-#define MCPN765_BOARD_TBEN_REG 0xfef880c0U
-#define MCPN765_BOARD_GEOGRAPHICAL_REG 0xfef880e8U
-#define MCPN765_BOARD_EXT_FEATURE_REG 0xfef880f0U
-#define MCPN765_BOARD_LAST_RESET_REG 0xfef880f8U
-
-/* Defines for UART */
-
-/* Define the UART base addresses */
-#define MCPN765_SERIAL_1 0xfef88000
-#define MCPN765_SERIAL_2 0xfef88200
-#define MCPN765_SERIAL_3 0xfef88400
-#define MCPN765_SERIAL_4 0xfef88600
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE 64
-#else
-#define RS_TABLE_SIZE 4
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 1843200 / 16 )
-#define UART_CLK 1843200
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-/* All UART IRQ's are wire-OR'd to IRQ 17 */
-#define STD_SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
- iomem_base: (u8 *)MCPN765_SERIAL_1, \
- iomem_reg_shift: 4, \
- io_type: SERIAL_IO_MEM }, \
- { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
- iomem_base: (u8 *)MCPN765_SERIAL_2, \
- iomem_reg_shift: 4, \
- io_type: SERIAL_IO_MEM }, \
- { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
- iomem_base: (u8 *)MCPN765_SERIAL_3, \
- iomem_reg_shift: 4, \
- io_type: SERIAL_IO_MEM }, \
- { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
- iomem_base: (u8 *)MCPN765_SERIAL_4, \
- iomem_reg_shift: 4, \
- io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
- STD_SERIAL_PORT_DFNS
-
-/* Define the NVRAM/RTC address strobe & data registers */
-#define MCPN765_PHYS_NVRAM_AS0 0xfef880c8U
-#define MCPN765_PHYS_NVRAM_AS1 0xfef880d0U
-#define MCPN765_PHYS_NVRAM_DATA 0xfef880d8U
-
-extern void mcpn765_find_bridges(void);
-
-#endif /* __PPC_PLATFORMS_MCPN765_H */
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
deleted file mode 100644
index d7191630a650..000000000000
--- a/arch/ppc/platforms/pcore.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * arch/ppc/platforms/pcore_setup.c
- *
- * Setup routines for Force PCORE boards
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/i8259.h>
-#include <asm/mpc10x.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-#include <asm/kgdb.h>
-
-#include "pcore.h"
-
-extern unsigned long loops_per_jiffy;
-
-static int board_type;
-
-static inline int __init
-pcore_6750_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
- */
- {
- {9, 10, 11, 12}, /* IDSEL 24 - DEC 21554 */
- {10, 0, 0, 0}, /* IDSEL 25 - DEC 21143 */
- {11, 12, 9, 10}, /* IDSEL 26 - PMC I */
- {12, 9, 10, 11}, /* IDSEL 27 - PMC II */
- {0, 0, 0, 0}, /* IDSEL 28 - unused */
- {0, 0, 9, 0}, /* IDSEL 29 - unused */
- {0, 0, 0, 0}, /* IDSEL 30 - Winbond */
- };
- const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-};
-
-static inline int __init
-pcore_680_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
- */
- {
- {9, 10, 11, 12}, /* IDSEL 24 - Sentinel */
- {10, 0, 0, 0}, /* IDSEL 25 - i82559 #1 */
- {11, 12, 9, 10}, /* IDSEL 26 - PMC I */
- {12, 9, 10, 11}, /* IDSEL 27 - PMC II */
- {9, 0, 0, 0}, /* IDSEL 28 - i82559 #2 */
- {0, 0, 0, 0}, /* IDSEL 29 - unused */
- {0, 0, 0, 0}, /* IDSEL 30 - Winbond */
- };
- const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-};
-
-void __init
-pcore_pcibios_fixup(void)
-{
- struct pci_dev *dev;
-
- if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
- PCI_DEVICE_ID_WINBOND_83C553,
- 0)))
- {
- /* Reroute interrupts both IDE channels to 15 */
- pci_write_config_byte(dev,
- PCORE_WINBOND_IDE_INT,
- 0xff);
-
- /* Route INTA-D to IRQ9-12, respectively */
- pci_write_config_word(dev,
- PCORE_WINBOND_PCI_INT,
- 0x9abc);
-
- /*
- * Set up 8259 edge/level triggering
- */
- outb(0x00, PCORE_WINBOND_PRI_EDG_LVL);
- outb(0x1e, PCORE_WINBOND_SEC_EDG_LVL);
- pci_dev_put(dev);
- }
-}
-
-int __init
-pcore_find_bridges(void)
-{
- struct pci_controller* hose;
- int host_bridge, board_type;
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return 0;
-
- mpc10x_bridge_init(hose,
- MPC10X_MEM_MAP_B,
- MPC10X_MEM_MAP_B,
- MPC10X_MAPB_EUMB_BASE);
-
- /* Determine board type */
- early_read_config_dword(hose,
- 0,
- PCI_DEVFN(0,0),
- PCI_VENDOR_ID,
- &host_bridge);
- if (host_bridge == MPC10X_BRIDGE_106)
- board_type = PCORE_TYPE_6750;
- else /* MPC10X_BRIDGE_107 */
- board_type = PCORE_TYPE_680;
-
- hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
- ppc_md.pcibios_fixup = pcore_pcibios_fixup;
- ppc_md.pci_swizzle = common_swizzle;
-
- if (board_type == PCORE_TYPE_6750)
- ppc_md.pci_map_irq = pcore_6750_map_irq;
- else /* PCORE_TYPE_680 */
- ppc_md.pci_map_irq = pcore_680_map_irq;
-
- return board_type;
-}
-
-/* Dummy variable to satisfy mpc10x_common.o */
-void *OpenPIC_Addr;
-
-static int
-pcore_show_cpuinfo(struct seq_file *m)
-{
- seq_printf(m, "vendor\t\t: Force Computers\n");
-
- if (board_type == PCORE_TYPE_6750)
- seq_printf(m, "machine\t\t: PowerCore 6750\n");
- else /* PCORE_TYPE_680 */
- seq_printf(m, "machine\t\t: PowerCore 680\n");
-
- seq_printf(m, "L2\t\t: " );
- if (board_type == PCORE_TYPE_6750)
- switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
- {
- case PCORE_DCCR_L2_0KB:
- seq_printf(m, "nocache");
- break;
- case PCORE_DCCR_L2_256KB:
- seq_printf(m, "256KB");
- break;
- case PCORE_DCCR_L2_1MB:
- seq_printf(m, "1MB");
- break;
- case PCORE_DCCR_L2_512KB:
- seq_printf(m, "512KB");
- break;
- default:
- seq_printf(m, "error");
- break;
- }
- else /* PCORE_TYPE_680 */
- switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
- {
- case PCORE_DCCR_L2_2MB:
- seq_printf(m, "2MB");
- break;
- case PCORE_DCCR_L2_256KB:
- seq_printf(m, "reserved");
- break;
- case PCORE_DCCR_L2_1MB:
- seq_printf(m, "1MB");
- break;
- case PCORE_DCCR_L2_512KB:
- seq_printf(m, "512KB");
- break;
- default:
- seq_printf(m, "error");
- break;
- }
-
- seq_printf(m, "\n");
-
- return 0;
-}
-
-static void __init
-pcore_setup_arch(void)
-{
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
- /* Lookup PCI host bridges */
- board_type = pcore_find_bridges();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_SDA2;
-#endif
-
- printk(KERN_INFO "Force PowerCore ");
- if (board_type == PCORE_TYPE_6750)
- printk("6750\n");
- else
- printk("680\n");
- printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
- _set_L2CR(L2CR_L2E | _get_L2CR());
-
-}
-
-static void
-pcore_restart(char *cmd)
-{
- local_irq_disable();
- /* Hard reset */
- writeb(0x11, 0xfe000332);
- while(1);
-}
-
-static void
-pcore_halt(void)
-{
- local_irq_disable();
- /* Turn off user LEDs */
- writeb(0x00, 0xfe000300);
- while (1);
-}
-
-static void
-pcore_power_off(void)
-{
- pcore_halt();
-}
-
-
-static void __init
-pcore_init_IRQ(void)
-{
- int i;
-
- for ( i = 0 ; i < 16 ; i++ )
- irq_desc[i].handler = &i8259_pic;
-
- i8259_init(0);
-}
-
-/*
- * Set BAT 3 to map 0xf0000000 to end of physical memory space.
- */
-static __inline__ void
-pcore_set_bat(void)
-{
- mb();
- mtspr(SPRN_DBAT3U, 0xf0001ffe);
- mtspr(SPRN_DBAT3L, 0xfe80002a);
- mb();
-
-}
-
-static unsigned long __init
-pcore_find_end_of_memory(void)
-{
-
- return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-}
-
-static void __init
-pcore_map_io(void)
-{
- io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- /* Cover I/O space with a BAT */
- /* yuck, better hope your ram size is a power of 2 -- paulus */
- pcore_set_bat();
-
- isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
- isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
- pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-
- ppc_md.setup_arch = pcore_setup_arch;
- ppc_md.show_cpuinfo = pcore_show_cpuinfo;
- ppc_md.init_IRQ = pcore_init_IRQ;
- ppc_md.get_irq = i8259_irq;
-
- ppc_md.find_end_of_memory = pcore_find_end_of_memory;
- ppc_md.setup_io_mappings = pcore_map_io;
-
- ppc_md.restart = pcore_restart;
- ppc_md.power_off = pcore_power_off;
- ppc_md.halt = pcore_halt;
-
- TODC_INIT(TODC_TYPE_MK48T59,
- PCORE_NVRAM_AS0,
- PCORE_NVRAM_AS1,
- PCORE_NVRAM_DATA,
- 8);
-
- ppc_md.time_init = todc_time_init;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.calibrate_decr = todc_calibrate_decr;
-
- ppc_md.nvram_read_val = todc_m48txx_read_val;
- ppc_md.nvram_write_val = todc_m48txx_write_val;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = gen550_progress;
-#endif
-#ifdef CONFIG_KGDB
- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
-#endif
-}
diff --git a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h
deleted file mode 100644
index c6a26e764926..000000000000
--- a/arch/ppc/platforms/pcore.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * arch/ppc/platforms/pcore.h
- *
- * Definitions for Force PowerCore board support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (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 __PPC_PLATFORMS_PCORE_H
-#define __PPC_PLATFORMS_PCORE_H
-
-#include <asm/mpc10x.h>
-
-#define PCORE_TYPE_6750 1
-#define PCORE_TYPE_680 2
-
-#define PCORE_NVRAM_AS0 0x73
-#define PCORE_NVRAM_AS1 0x75
-#define PCORE_NVRAM_DATA 0x77
-
-#define PCORE_DCCR_REG (MPC10X_MAPB_ISA_IO_BASE + 0x308)
-#define PCORE_DCCR_L2_MASK 0xc0
-#define PCORE_DCCR_L2_0KB 0x00
-#define PCORE_DCCR_L2_256KB 0x40
-#define PCORE_DCCR_L2_512KB 0xc0
-#define PCORE_DCCR_L2_1MB 0x80
-#define PCORE_DCCR_L2_2MB 0x00
-
-#define PCORE_WINBOND_IDE_INT 0x43
-#define PCORE_WINBOND_PCI_INT 0x44
-#define PCORE_WINBOND_PRI_EDG_LVL 0x4d0
-#define PCORE_WINBOND_SEC_EDG_LVL 0x4d1
-
-#endif /* __PPC_PLATFORMS_PCORE_H */
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
index 9f92e1bb7f34..2ce058895e03 100644
--- a/arch/ppc/platforms/pmac_pic.c
+++ b/arch/ppc/platforms/pmac_pic.c
@@ -619,7 +619,7 @@ not_found:
return viaint;
}
-static int pmacpic_suspend(struct sys_device *sysdev, u32 state)
+static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
{
int viaint = pmacpic_find_viaint();
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
index 016a74649155..88419c77ac43 100644
--- a/arch/ppc/platforms/pmac_sleep.S
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -17,7 +17,7 @@
#include <asm/cputable.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#define MAGIC 0x4c617273 /* 'Lars' */
@@ -161,6 +161,8 @@ _GLOBAL(low_sleep_handler)
addi r3,r3,sleep_storage@l
stw r5,0(r3)
+ .globl low_cpu_die
+low_cpu_die:
/* Flush & disable all caches */
bl flush_disable_caches
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 8e049dab4e63..794a23994b82 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -33,6 +33,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/hardirq.h>
+#include <linux/cpu.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -55,9 +56,7 @@
* Powersurge (old powermac SMP) support.
*/
-extern void __secondary_start_psurge(void);
-extern void __secondary_start_psurge2(void); /* Temporary horrible hack */
-extern void __secondary_start_psurge3(void); /* Temporary horrible hack */
+extern void __secondary_start_pmac_0(void);
/* Addresses for powersurge registers */
#define HAMMERHEAD_BASE 0xf8000000
@@ -119,7 +118,7 @@ static volatile int sec_tb_reset = 0;
static unsigned int pri_tb_hi, pri_tb_lo;
static unsigned int pri_tb_stamp;
-static void __init core99_init_caches(int cpu)
+static void __devinit core99_init_caches(int cpu)
{
if (!cpu_has_feature(CPU_FTR_L2CR))
return;
@@ -346,7 +345,7 @@ static int __init smp_psurge_probe(void)
static void __init smp_psurge_kick_cpu(int nr)
{
- void (*start)(void) = __secondary_start_psurge;
+ unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
unsigned long a;
/* may need to flush here if secondary bats aren't setup */
@@ -356,17 +355,7 @@ static void __init smp_psurge_kick_cpu(int nr)
if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
- /* setup entry point of secondary processor */
- switch (nr) {
- case 2:
- start = __secondary_start_psurge2;
- break;
- case 3:
- start = __secondary_start_psurge3;
- break;
- }
-
- out_be32(psurge_start, __pa(start));
+ out_be32(psurge_start, start);
mb();
psurge_set_ipi(nr);
@@ -500,14 +489,14 @@ static int __init smp_core99_probe(void)
return ncpus;
}
-static void __init smp_core99_kick_cpu(int nr)
+static void __devinit smp_core99_kick_cpu(int nr)
{
unsigned long save_vector, new_vector;
unsigned long flags;
volatile unsigned long *vector
= ((volatile unsigned long *)(KERNELBASE+0x100));
- if (nr < 1 || nr > 3)
+ if (nr < 0 || nr > 3)
return;
if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
@@ -518,19 +507,9 @@ static void __init smp_core99_kick_cpu(int nr)
save_vector = *vector;
/* Setup fake reset vector that does
- * b __secondary_start_psurge - KERNELBASE
+ * b __secondary_start_pmac_0 + nr*8 - KERNELBASE
*/
- switch(nr) {
- case 1:
- new_vector = (unsigned long)__secondary_start_psurge;
- break;
- case 2:
- new_vector = (unsigned long)__secondary_start_psurge2;
- break;
- case 3:
- new_vector = (unsigned long)__secondary_start_psurge3;
- break;
- }
+ new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;
*vector = 0x48000002 + new_vector - KERNELBASE;
/* flush data cache and inval instruction cache */
@@ -554,7 +533,7 @@ static void __init smp_core99_kick_cpu(int nr)
if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
}
-static void __init smp_core99_setup_cpu(int cpu_nr)
+static void __devinit smp_core99_setup_cpu(int cpu_nr)
{
/* Setup L2/L3 */
if (cpu_nr != 0)
@@ -668,3 +647,47 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
.give_timebase = smp_core99_give_timebase,
.take_timebase = smp_core99_take_timebase,
};
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+int __cpu_disable(void)
+{
+ cpu_clear(smp_processor_id(), cpu_online_map);
+
+ /* XXX reset cpu affinity here */
+ openpic_set_priority(0xf);
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ mb();
+ udelay(20);
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ return 0;
+}
+
+extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */
+static int cpu_dead[NR_CPUS];
+
+void cpu_die(void)
+{
+ local_irq_disable();
+ cpu_dead[smp_processor_id()] = 1;
+ mb();
+ low_cpu_die();
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ int timeout;
+
+ timeout = 1000;
+ while (!cpu_dead[cpu]) {
+ if (--timeout == 0) {
+ printk("CPU %u refused to die!\n", cpu);
+ break;
+ }
+ msleep(1);
+ }
+ cpu_callin_map[cpu] = 0;
+ cpu_dead[cpu] = 0;
+}
+
+#endif
diff --git a/arch/ppc/platforms/spd8xx.h b/arch/ppc/platforms/spd8xx.h
deleted file mode 100644
index ed48d144f415..000000000000
--- a/arch/ppc/platforms/spd8xx.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Speech Design SPD8xxTS board specific definitions
- *
- * Copyright (c) 2000,2001 Wolfgang Denk (wd@denx.de)
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_SPD8XX_H__
-#define __ASM_SPD8XX_H__
-
-#include <linux/config.h>
-
-#include <asm/ppcboot.h>
-
-#ifndef __ASSEMBLY__
-#define SPD_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
-#define SPD_IMAP_SIZE (64 * 1024) /* size of mapped area */
-
-#define IMAP_ADDR SPD_IMMR_BASE /* physical base address of IMMR area */
-#define IMAP_SIZE SPD_IMAP_SIZE /* mapped size of IMMR area */
-
-#define PCMCIA_MEM_ADDR ((uint)0xFE100000)
-#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
-
-#define IDE0_INTERRUPT 10 /* = IRQ5 */
-#define IDE1_INTERRUPT 12 /* = IRQ6 */
-#define CPM_INTERRUPT 13 /* = SIU_LEVEL6 (was: SIU_LEVEL2) */
-
-/* override the default number of IDE hardware interfaces */
-#define MAX_HWIFS 2
-
-/*
- * Definitions for IDE0 Interface
- */
-#define IDE0_BASE_OFFSET 0x0000 /* Offset in PCMCIA memory */
-#define IDE0_DATA_REG_OFFSET 0x0000
-#define IDE0_ERROR_REG_OFFSET 0x0081
-#define IDE0_NSECTOR_REG_OFFSET 0x0082
-#define IDE0_SECTOR_REG_OFFSET 0x0083
-#define IDE0_LCYL_REG_OFFSET 0x0084
-#define IDE0_HCYL_REG_OFFSET 0x0085
-#define IDE0_SELECT_REG_OFFSET 0x0086
-#define IDE0_STATUS_REG_OFFSET 0x0087
-#define IDE0_CONTROL_REG_OFFSET 0x0106
-#define IDE0_IRQ_REG_OFFSET 0x000A /* not used */
-
-/*
- * Definitions for IDE1 Interface
- */
-#define IDE1_BASE_OFFSET 0x0C00 /* Offset in PCMCIA memory */
-#define IDE1_DATA_REG_OFFSET 0x0000
-#define IDE1_ERROR_REG_OFFSET 0x0081
-#define IDE1_NSECTOR_REG_OFFSET 0x0082
-#define IDE1_SECTOR_REG_OFFSET 0x0083
-#define IDE1_LCYL_REG_OFFSET 0x0084
-#define IDE1_HCYL_REG_OFFSET 0x0085
-#define IDE1_SELECT_REG_OFFSET 0x0086
-#define IDE1_STATUS_REG_OFFSET 0x0087
-#define IDE1_CONTROL_REG_OFFSET 0x0106
-#define IDE1_IRQ_REG_OFFSET 0x000A /* not used */
-
-/* CPM Ethernet through SCCx.
- *
- * Bits in parallel I/O port registers that have to be set/cleared
- * to configure the pins for SCC2 use.
- */
-#define PA_ENET_MDC ((ushort)0x0001) /* PA 15 !!! */
-#define PA_ENET_MDIO ((ushort)0x0002) /* PA 14 !!! */
-#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
-#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
-#define PA_ENET_RCLK ((ushort)0x0200) /* PA 6 */
-#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
-
-#define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */
-
-#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */
-#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */
-#define PC_ENET_RESET ((ushort)0x0100) /* PC 7 !!! */
-
-/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK2) to
- * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
- */
-#define SICR_ENET_MASK ((uint)0x0000ff00)
-#define SICR_ENET_CLKRT ((uint)0x00002E00)
-
-/* We don't use the 8259.
-*/
-#define NR_8259_INTS 0
-
-#endif /* !__ASSEMBLY__ */
-#endif /* __ASM_SPD8XX_H__ */
-#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/tqm8xx.h b/arch/ppc/platforms/tqm8xx.h
index 2150dc87b18f..43ac064ebe5a 100644
--- a/arch/ppc/platforms/tqm8xx.h
+++ b/arch/ppc/platforms/tqm8xx.h
@@ -147,29 +147,6 @@ static __inline__ void ide_led(int on)
#define SICR_ENET_CLKRT ((uint)0x00002600)
#endif /* CONFIG_FPS850L */
-/*** SM850 *********************************************************/
-
-/* The SM850 Service Module uses SCC2 for IrDA and SCC3 for Ethernet */
-
-#ifdef CONFIG_SM850
-#define PB_ENET_RXD ((uint)0x00000004) /* PB 29 */
-#define PB_ENET_TXD ((uint)0x00000002) /* PB 30 */
-#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */
-#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
-
-#define PC_ENET_LBK ((ushort)0x0008) /* PC 12 */
-#define PC_ENET_TENA ((ushort)0x0004) /* PC 13 */
-
-#define PC_ENET_RENA ((ushort)0x0800) /* PC 4 */
-#define PC_ENET_CLSN ((ushort)0x0400) /* PC 5 */
-
-/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
- * SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero.
- */
-#define SICR_ENET_MASK ((uint)0x00FF0000)
-#define SICR_ENET_CLKRT ((uint)0x00260000)
-#endif /* CONFIG_SM850 */
-
/* We don't use the 8259.
*/
#define NR_8259_INTS 0
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 220a65ab0a51..8b9b226005d1 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -43,8 +43,6 @@ obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o
obj-$(CONFIG_POWER4) += open_pic2.o
obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o
obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o
-obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
- todc_time.o
obj-$(CONFIG_BAMBOO) += indirect_pci.o pci_auto.o todc_time.o
obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o
@@ -52,16 +50,10 @@ obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o
obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o indirect_pci.o
obj-$(CONFIG_GT64260) += gt64260_pic.o
-obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
- pci_auto.o
obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o
obj-$(CONFIG_HDPU) += pci_auto.o
obj-$(CONFIG_LUAN) += indirect_pci.o pci_auto.o todc_time.o
obj-$(CONFIG_KATANA) += pci_auto.o
-obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \
- open_pic.o i8259.o hawk_common.o
-obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \
- pci_auto.o indirect_pci.o
obj-$(CONFIG_MV64360) += mv64360_pic.o
obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o indirect_pci.o
obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \
@@ -69,7 +61,6 @@ obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \
obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o
obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o
obj-$(CONFIG_PAL4) += cpc700_pic.o
-obj-$(CONFIG_PCORE) += todc_time.o i8259.o pci_auto.o
obj-$(CONFIG_POWERPMC250) += pci_auto.o
obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o i8259.o \
indirect_pci.o todc_time.o pci_auto.o
@@ -82,7 +73,8 @@ obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o
obj-$(CONFIG_SBC82xx) += todc_time.o
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
todc_time.o
-obj-$(CONFIG_8260) += m8260_setup.o
+obj-$(CONFIG_8260) += m8260_setup.o pq2_devices.o pq2_sys.o \
+ ppc_sys.o
obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o
obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c
index 774709807538..75fe8eb10693 100644
--- a/arch/ppc/syslib/cpc700_pic.c
+++ b/arch/ppc/syslib/cpc700_pic.c
@@ -90,14 +90,10 @@ cpc700_mask_and_ack_irq(unsigned int irq)
}
static struct hw_interrupt_type cpc700_pic = {
- "CPC700 PIC",
- NULL,
- NULL,
- cpc700_unmask_irq,
- cpc700_mask_irq,
- cpc700_mask_and_ack_irq,
- NULL,
- NULL
+ .typename = "CPC700 PIC",
+ .enable = cpc700_unmask_irq,
+ .disable = cpc700_mask_irq,
+ .ack = cpc700_mask_and_ack_irq,
};
__init static void
diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
index b9391e650141..5c7908c20e43 100644
--- a/arch/ppc/syslib/i8259.c
+++ b/arch/ppc/syslib/i8259.c
@@ -129,14 +129,11 @@ static void i8259_end_irq(unsigned int irq)
}
struct hw_interrupt_type i8259_pic = {
- " i8259 ",
- NULL,
- NULL,
- i8259_unmask_irq,
- i8259_mask_irq,
- i8259_mask_and_ack_irq,
- i8259_end_irq,
- NULL
+ .typename = " i8259 ",
+ .enable = i8259_unmask_irq,
+ .disable = i8259_mask_irq,
+ .ack = i8259_mask_and_ack_irq,
+ .end = i8259_end_irq,
};
static struct resource pic1_iores = {
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index d4776af6a3ca..0bb919859b8b 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -236,9 +236,10 @@ void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
/* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
enable it on all other revisions
*/
- u32 pvr = mfspr(SPRN_PVR);
- if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB ||
- (pvr == PVR_440GX_RC && p->cpu > 667000000))
+ if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 ||
+ strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0
+ || (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C")
+ == 0 && p->cpu > 667000000))
ibm440gx_l2c_disable();
else
ibm440gx_l2c_enable();
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index a3702cfe8f7c..4c888da89b3c 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -57,7 +57,7 @@ unsigned char __res[sizeof(bd_t)];
extern void m8xx_ide_init(void);
extern unsigned long find_available_memory(void);
-extern void m8xx_cpm_reset();
+extern void m8xx_cpm_reset(void);
extern void m8xx_wdt_handler_install(bd_t *bp);
extern void rpxfb_alloc_pages(void);
extern void cpm_interrupt_init(void);
@@ -266,8 +266,8 @@ m8xx_show_percpuinfo(struct seq_file *m, int i)
bp = (bd_t *)__res;
- seq_printf(m, "clock\t\t: %ldMHz\n"
- "bus clock\t: %ldMHz\n",
+ seq_printf(m, "clock\t\t: %uMHz\n"
+ "bus clock\t: %uMHz\n",
bp->bi_intfreq / 1000000,
bp->bi_busfreq / 1000000);
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
index 87065e2e4c5f..3e039706bdbc 100644
--- a/arch/ppc/syslib/mpc10x_common.c
+++ b/arch/ppc/syslib/mpc10x_common.c
@@ -140,12 +140,12 @@ struct platform_device ppc_sys_platform_devices[] = {
},
[MPC10X_UART0] = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev.platform_data = serial_plat_uart0,
},
[MPC10X_UART1] = {
.name = "serial8250",
- .id = 1,
+ .id = PLAT8250_DEV_PLATFORM1,
.dev.platform_data = serial_plat_uart1,
},
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 5aaf0e58e1f9..95b3b8a7f0ba 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -165,7 +165,7 @@ struct platform_device ppc_sys_platform_devices[] = {
},
[MPC83xx_DUART] = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev.platform_data = serial_platform_data,
},
[MPC83xx_SEC2] = {
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 8af322dd476a..bbc5ac0de878 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -282,7 +282,7 @@ struct platform_device ppc_sys_platform_devices[] = {
},
[MPC85xx_DUART] = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev.platform_data = serial_platform_data,
},
[MPC85xx_PERFMON] = {
diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
index 74d8996418e9..8356da4678a2 100644
--- a/arch/ppc/syslib/mv64360_pic.c
+++ b/arch/ppc/syslib/mv64360_pic.c
@@ -366,10 +366,16 @@ mv64360_pci_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+/*
+ * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
+ * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
+ * well. IOW, don't set bit 0.
+ */
+#define MV64360_PCI0_ERR_MASK_VAL 0x00a50c24
+
static int __init
mv64360_register_hdlrs(void)
{
- u32 mask;
int rc;
/* Clear old errors and register CPU interface error intr handler */
@@ -387,17 +393,6 @@ mv64360_register_hdlrs(void)
mv64360_sram_error_int_handler,SA_INTERRUPT,SRAM_INTR_STR, 0)))
printk(KERN_WARNING "Can't register SRAM error handler: %d",rc);
- /*
- * Bit 0 reserved on 64360 and erratum FEr PCI-#11 (PCI internal
- * data parity error set incorrectly) on rev 0 & 1 of 64460 requires
- * bit 0 to be cleared.
- */
- mask = 0x00a50c24;
-
- if ((mv64x60_get_bridge_type() == MV64x60_TYPE_MV64460) &&
- (mv64x60_get_bridge_rev() > 1))
- mask |= 0x1; /* enable DPErr on 64460 */
-
/* Clear old errors and register PCI 0 error intr handler */
mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, 0);
if ((rc = request_irq(MV64360_IRQ_PCI0 + mv64360_irq_base,
@@ -407,7 +402,11 @@ mv64360_register_hdlrs(void)
rc);
mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, 0);
- mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, mask);
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, MV64360_PCI0_ERR_MASK_VAL);
+
+ /* Erratum FEr PCI-#16 says to clear bit 0 of PCI SERRn Mask reg. */
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_SERR_MASK,
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_SERR_MASK) & ~0x1UL);
/* Clear old errors and register PCI 1 error intr handler */
mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, 0);
@@ -418,7 +417,11 @@ mv64360_register_hdlrs(void)
rc);
mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, 0);
- mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, mask);
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, MV64360_PCI0_ERR_MASK_VAL);
+
+ /* Erratum FEr PCI-#16 says to clear bit 0 of PCI Intr Mask reg. */
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_SERR_MASK,
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_SERR_MASK) & ~0x1UL);
return 0;
}
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index cc77177fa1c6..839f8872826f 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -30,13 +30,16 @@
#include <asm/mv64x60.h>
-u8 mv64x60_pci_exclude_bridge = 1;
-spinlock_t mv64x60_lock = SPIN_LOCK_UNLOCKED;
+u8 mv64x60_pci_exclude_bridge = 1;
+DEFINE_SPINLOCK(mv64x60_lock);
-static phys_addr_t mv64x60_bridge_pbase = 0;
-static void *mv64x60_bridge_vbase = 0;
+static phys_addr_t mv64x60_bridge_pbase;
+static void *mv64x60_bridge_vbase;
static u32 mv64x60_bridge_type = MV64x60_TYPE_INVALID;
-static u32 mv64x60_bridge_rev = 0;
+static u32 mv64x60_bridge_rev;
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+static struct pci_controller sysfs_hose_a;
+#endif
static u32 gt64260_translate_size(u32 base, u32 size, u32 num_bits);
static u32 gt64260_untranslate_size(u32 base, u32 size, u32 num_bits);
@@ -432,6 +435,20 @@ static struct platform_device i2c_device = {
};
#endif
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+static struct mv64xxx_pdata mv64xxx_pdata = {
+ .hs_reg_valid = 0,
+};
+
+static struct platform_device mv64xxx_device = { /* general mv64x60 stuff */
+ .name = MV64XXX_DEV_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &mv64xxx_pdata,
+ },
+};
+#endif
+
static struct platform_device *mv64x60_pd_devs[] __initdata = {
#ifdef CONFIG_SERIAL_MPSC
&mpsc_shared_device,
@@ -453,6 +470,9 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = {
#ifdef CONFIG_I2C_MV64XXX
&i2c_device,
#endif
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+ &mv64xxx_device,
+#endif
};
/*
@@ -574,6 +594,11 @@ mv64x60_early_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si)
bh->hose_a = &hose_a;
bh->hose_b = &hose_b;
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+ /* Save a copy of hose_a for sysfs functions -- hack */
+ memcpy(&sysfs_hose_a, &hose_a, sizeof(hose_a));
+#endif
+
mv64x60_set_bus(bh, 0, 0);
mv64x60_set_bus(bh, 1, 0);
@@ -590,8 +615,6 @@ mv64x60_early_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si)
mv64x60_set_bits(bh, MV64x60_PCI0_TO_RETRY, 0xffff);
mv64x60_set_bits(bh, MV64x60_PCI1_TO_RETRY, 0xffff);
-
- return;
}
/*
@@ -628,19 +651,15 @@ mv64x60_get_32bit_window(struct mv64x60_handle *bh, u32 window,
val = mv64x60_read(bh, size_reg);
val = get_from_field(val, size_bits);
*size = bh->ci->untranslate_size(*base, val, size_bits);
- }
- else
+ } else
*size = 0;
- }
- else {
+ } else {
*base = 0;
*size = 0;
}
pr_debug("get 32bit window: %d, base: 0x%x, size: 0x%x\n",
window, *base, *size);
-
- return;
}
/*
@@ -677,8 +696,6 @@ mv64x60_set_32bit_window(struct mv64x60_handle *bh, u32 window,
(void)mv64x60_read(bh, base_reg); /* Flush FIFO */
}
-
- return;
}
/*
@@ -712,11 +729,9 @@ mv64x60_get_64bit_window(struct mv64x60_handle *bh, u32 window,
val = get_from_field(val, size_bits);
*size = bh->ci->untranslate_size(*base_lo, val,
size_bits);
- }
- else
+ } else
*size = 0;
- }
- else {
+ } else {
*base_hi = 0;
*base_lo = 0;
*size = 0;
@@ -724,8 +739,6 @@ mv64x60_get_64bit_window(struct mv64x60_handle *bh, u32 window,
pr_debug("get 64bit window: %d, base hi: 0x%x, base lo: 0x%x, "
"size: 0x%x\n", window, *base_hi, *base_lo, *size);
-
- return;
}
/*
@@ -766,8 +779,6 @@ mv64x60_set_64bit_window(struct mv64x60_handle *bh, u32 window,
(void)mv64x60_read(bh, base_lo_reg); /* Flush FIFO */
}
-
- return;
}
/*
@@ -1008,8 +1019,6 @@ mv64x60_get_mem_windows(struct mv64x60_handle *bh,
mem_windows[i][0] = 0;
mem_windows[i][1] = 0;
}
-
- return;
}
/*
@@ -1077,8 +1086,6 @@ mv64x60_config_cpu2mem_windows(struct mv64x60_handle *bh,
}
}
-
- return;
}
/*
@@ -1112,8 +1119,7 @@ mv64x60_config_cpu2pci_windows(struct mv64x60_handle *bh,
mv64x60_set_32bit_window(bh, remap_tab[bus][0],
pi->pci_io.pci_base_lo, 0, 0);
bh->ci->enable_window_32bit(bh, win_tab[bus][0]);
- }
- else /* Actually, the window should already be disabled */
+ } else /* Actually, the window should already be disabled */
bh->ci->disable_window_32bit(bh, win_tab[bus][0]);
for (i=0; i<3; i++)
@@ -1125,11 +1131,8 @@ mv64x60_config_cpu2pci_windows(struct mv64x60_handle *bh,
pi->pci_mem[i].pci_base_hi,
pi->pci_mem[i].pci_base_lo, 0, 0);
bh->ci->enable_window_32bit(bh, win_tab[bus][i+1]);
- }
- else /* Actually, the window should already be disabled */
+ } else /* Actually, the window should already be disabled */
bh->ci->disable_window_32bit(bh, win_tab[bus][i+1]);
-
- return;
}
/*
@@ -1206,8 +1209,6 @@ mv64x60_config_pci2mem_windows(struct mv64x60_handle *bh,
MV64x60_PCI0_BAR_ENABLE :
MV64x60_PCI1_BAR_ENABLE), (1 << i));
}
-
- return;
}
/*
@@ -1229,7 +1230,6 @@ mv64x60_alloc_hose(struct mv64x60_handle *bh, u32 cfg_addr, u32 cfg_data,
*hose = pcibios_alloc_controller();
setup_indirect_pci_nomap(*hose, bh->v_base + cfg_addr,
bh->v_base + cfg_data);
- return;
}
/*
@@ -1272,7 +1272,6 @@ mv64x60_config_resources(struct pci_controller *hose,
pi->pci_mem[0].size - 1;
hose->pci_mem_offset = pi->pci_mem[0].cpu_base -
pi->pci_mem[0].pci_base_lo;
- return;
}
/*
@@ -1309,7 +1308,6 @@ mv64x60_config_pci_params(struct pci_controller *hose,
early_write_config_word(hose, 0, devfn, PCI_CACHE_LINE_SIZE, u16_val);
mv64x60_pci_exclude_bridge = save_exclude;
- return;
}
/*
@@ -1336,8 +1334,7 @@ mv64x60_set_bus(struct mv64x60_handle *bh, u32 bus, u32 child_bus)
p2p_cfg = MV64x60_PCI0_P2P_CONFIG;
pci_cfg_offset = 0x64;
hose = bh->hose_a;
- }
- else {
+ } else {
pci_mode = bh->pci_mode_b;
p2p_cfg = MV64x60_PCI1_P2P_CONFIG;
pci_cfg_offset = 0xe4;
@@ -1352,8 +1349,7 @@ mv64x60_set_bus(struct mv64x60_handle *bh, u32 bus, u32 child_bus)
val |= (child_bus << 16) | 0xff;
mv64x60_write(bh, p2p_cfg, val);
(void)mv64x60_read(bh, p2p_cfg); /* Flush FIFO */
- }
- else { /* PCI-X */
+ } else { /* PCI-X */
/*
* Need to use the current bus/dev number (that's in the
* P2P CONFIG reg) to access the bridge's pci config space.
@@ -1365,8 +1361,6 @@ mv64x60_set_bus(struct mv64x60_handle *bh, u32 bus, u32 child_bus)
pci_cfg_offset, child_bus << 8);
mv64x60_pci_exclude_bridge = save_exclude;
}
-
- return;
}
/*
@@ -1423,8 +1417,6 @@ mv64x60_pd_fixup(struct mv64x60_handle *bh, struct platform_device *pd_devs[],
j++;
}
}
-
- return;
}
/*
@@ -1498,8 +1490,6 @@ gt64260_set_pci2mem_window(struct pci_controller *hose, u32 bus, u32 window,
early_write_config_dword(hose, 0, PCI_DEVFN(0, 0),
gt64260_reg_addrs[bus][window], mv64x60_mask(base, 20) | 0x8);
mv64x60_pci_exclude_bridge = save_exclude;
-
- return;
}
/*
@@ -1523,8 +1513,6 @@ gt64260_set_pci2regs_window(struct mv64x60_handle *bh,
early_write_config_dword(hose, 0, PCI_DEVFN(0,0), gt64260_offset[bus],
(base << 16));
mv64x60_pci_exclude_bridge = save_exclude;
-
- return;
}
/*
@@ -1561,7 +1549,6 @@ static void __init
gt64260_enable_window_32bit(struct mv64x60_handle *bh, u32 window)
{
pr_debug("enable 32bit window: %d\n", window);
- return;
}
/*
@@ -1584,8 +1571,6 @@ gt64260_disable_window_32bit(struct mv64x60_handle *bh, u32 window)
mv64x60_write(bh, gt64260_32bit_windows[window].base_reg,0xfff);
mv64x60_write(bh, gt64260_32bit_windows[window].size_reg, 0);
}
-
- return;
}
/*
@@ -1599,7 +1584,6 @@ static void __init
gt64260_enable_window_64bit(struct mv64x60_handle *bh, u32 window)
{
pr_debug("enable 64bit window: %d\n", window);
- return; /* Enabled when window configured (i.e., when top >= base) */
}
/*
@@ -1624,8 +1608,6 @@ gt64260_disable_window_64bit(struct mv64x60_handle *bh, u32 window)
mv64x60_write(bh, gt64260_64bit_windows[window].base_hi_reg, 0);
mv64x60_write(bh, gt64260_64bit_windows[window].size_reg, 0);
}
-
- return;
}
/*
@@ -1712,8 +1694,6 @@ gt64260_disable_all_windows(struct mv64x60_handle *bh,
mv64x60_write(bh, GT64260_IC_CPU_INT_1_MASK, 0);
mv64x60_write(bh, GT64260_IC_CPU_INT_2_MASK, 0);
mv64x60_write(bh, GT64260_IC_CPU_INT_3_MASK, 0);
-
- return;
}
/*
@@ -1781,14 +1761,11 @@ gt64260a_chip_specific_init(struct mv64x60_handle *bh,
mv64x60_mpsc1_pdata.cache_mgmt = 1;
if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 0))
- != NULL) {
-
+ != NULL) {
r->start = MV64x60_IRQ_SDMA_0;
r->end = MV64x60_IRQ_SDMA_0;
}
#endif
-
- return;
}
/*
@@ -1861,14 +1838,11 @@ gt64260b_chip_specific_init(struct mv64x60_handle *bh,
mv64x60_mpsc1_pdata.cache_mgmt = 1;
if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 0))
- != NULL) {
-
+ != NULL) {
r->start = MV64x60_IRQ_SDMA_0;
r->end = MV64x60_IRQ_SDMA_0;
}
#endif
-
- return;
}
/*
@@ -1945,8 +1919,6 @@ mv64360_set_pci2mem_window(struct pci_controller *hose, u32 bus, u32 window,
mv64360_reg_addrs[bus][window].base_lo_bar,
mv64x60_mask(base,20) | 0xc);
mv64x60_pci_exclude_bridge = save_exclude;
-
- return;
}
/*
@@ -1972,8 +1944,6 @@ mv64360_set_pci2regs_window(struct mv64x60_handle *bh,
early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
mv64360_offset[bus][1], 0);
mv64x60_pci_exclude_bridge = save_exclude;
-
- return;
}
/*
@@ -2082,8 +2052,6 @@ mv64360_enable_window_32bit(struct mv64x60_handle *bh, u32 window)
"32bit table corrupted");
}
}
-
- return;
}
/*
@@ -2139,8 +2107,6 @@ mv64360_disable_window_32bit(struct mv64x60_handle *bh, u32 window)
"32bit table corrupted");
}
}
-
- return;
}
/*
@@ -2158,8 +2124,7 @@ mv64360_enable_window_64bit(struct mv64x60_handle *bh, u32 window)
(mv64360_64bit_windows[window].size_reg != 0)) {
if ((mv64360_64bit_windows[window].extra & MV64x60_EXTRA_MASK)
- == MV64x60_EXTRA_PCIACC_ENAB)
-
+ == MV64x60_EXTRA_PCIACC_ENAB)
mv64x60_set_bits(bh,
mv64360_64bit_windows[window].base_lo_reg,
(1 << (mv64360_64bit_windows[window].extra &
@@ -2168,8 +2133,6 @@ mv64360_enable_window_64bit(struct mv64x60_handle *bh, u32 window)
printk(KERN_ERR "mv64360_enable: %s\n",
"64bit table corrupted");
}
-
- return;
}
/*
@@ -2186,11 +2149,9 @@ mv64360_disable_window_64bit(struct mv64x60_handle *bh, u32 window)
mv64360_64bit_windows[window].size_reg);
if ((mv64360_64bit_windows[window].base_lo_reg != 0) &&
- (mv64360_64bit_windows[window].size_reg != 0)) {
-
+ (mv64360_64bit_windows[window].size_reg != 0)) {
if ((mv64360_64bit_windows[window].extra & MV64x60_EXTRA_MASK)
- == MV64x60_EXTRA_PCIACC_ENAB)
-
+ == MV64x60_EXTRA_PCIACC_ENAB)
mv64x60_clr_bits(bh,
mv64360_64bit_windows[window].base_lo_reg,
(1 << (mv64360_64bit_windows[window].extra &
@@ -2199,8 +2160,6 @@ mv64360_disable_window_64bit(struct mv64x60_handle *bh, u32 window)
printk(KERN_ERR "mv64360_disable: %s\n",
"64bit table corrupted");
}
-
- return;
}
/*
@@ -2241,8 +2200,6 @@ mv64360_disable_all_windows(struct mv64x60_handle *bh,
/* Disable all PCI-><whatever> windows */
mv64x60_set_bits(bh, MV64x60_PCI0_BAR_ENABLE, 0x0000f9ff);
mv64x60_set_bits(bh, MV64x60_PCI1_BAR_ENABLE, 0x0000f9ff);
-
- return;
}
/*
@@ -2335,8 +2292,6 @@ mv64360_config_io2mem_windows(struct mv64x60_handle *bh,
mv64x60_set_bits(bh, MV64360_IDMA2MEM_ACC_PROT_3,
(0x3 << (i << 1)));
}
-
- return;
}
/*
@@ -2350,42 +2305,145 @@ static void __init
mv64360_set_mpsc2regs_window(struct mv64x60_handle *bh, u32 base)
{
pr_debug("set mpsc->internal regs, base: 0x%x\n", base);
-
mv64x60_write(bh, MV64360_MPSC2REGS_BASE, base & 0xffff0000);
- return;
}
/*
* mv64360_chip_specific_init()
*
- * No errata work arounds for the MV64360 implemented at this point.
+ * Implement errata work arounds for the MV64360.
*/
static void __init
mv64360_chip_specific_init(struct mv64x60_handle *bh,
struct mv64x60_setup_info *si)
{
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_set_bits(bh, MV64360_D_UNIT_CONTROL_HIGH, (1<<24));
+#endif
#ifdef CONFIG_SERIAL_MPSC
mv64x60_mpsc0_pdata.brg_can_tune = 1;
mv64x60_mpsc0_pdata.cache_mgmt = 1;
mv64x60_mpsc1_pdata.brg_can_tune = 1;
mv64x60_mpsc1_pdata.cache_mgmt = 1;
#endif
-
- return;
}
/*
* mv64460_chip_specific_init()
*
- * No errata work arounds for the MV64460 implemented at this point.
+ * Implement errata work arounds for the MV64460.
*/
static void __init
mv64460_chip_specific_init(struct mv64x60_handle *bh,
struct mv64x60_setup_info *si)
{
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_set_bits(bh, MV64360_D_UNIT_CONTROL_HIGH, (1<<24) | (1<<25));
+ mv64x60_set_bits(bh, MV64460_D_UNIT_MMASK, (1<<1) | (1<<4));
+#endif
#ifdef CONFIG_SERIAL_MPSC
mv64x60_mpsc0_pdata.brg_can_tune = 1;
+ mv64x60_mpsc0_pdata.cache_mgmt = 1;
mv64x60_mpsc1_pdata.brg_can_tune = 1;
+ mv64x60_mpsc1_pdata.cache_mgmt = 1;
#endif
- return;
}
+
+
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+/* Export the hotswap register via sysfs for enum event monitoring */
+#define VAL_LEN_MAX 11 /* 32-bit hex or dec stringified number + '\n' */
+
+DECLARE_MUTEX(mv64xxx_hs_lock);
+
+static ssize_t
+mv64xxx_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ u32 v;
+ u8 save_exclude;
+
+ if (off > 0)
+ return 0;
+ if (count < VAL_LEN_MAX)
+ return -EINVAL;
+
+ if (down_interruptible(&mv64xxx_hs_lock))
+ return -ERESTARTSYS;
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_read_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, &v);
+ mv64x60_pci_exclude_bridge = save_exclude;
+ up(&mv64xxx_hs_lock);
+
+ return sprintf(buf, "0x%08x\n", v);
+}
+
+static ssize_t
+mv64xxx_hs_reg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ u32 v;
+ u8 save_exclude;
+
+ if (off > 0)
+ return 0;
+ if (count <= 0)
+ return -EINVAL;
+
+ if (sscanf(buf, "%i", &v) == 1) {
+ if (down_interruptible(&mv64xxx_hs_lock))
+ return -ERESTARTSYS;
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0),
+ MV64360_PCICFG_CPCI_HOTSWAP, v);
+ mv64x60_pci_exclude_bridge = save_exclude;
+ up(&mv64xxx_hs_lock);
+ }
+ else
+ count = -EINVAL;
+
+ return count;
+}
+
+static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */
+ .attr = {
+ .name = "hs_reg",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = VAL_LEN_MAX,
+ .read = mv64xxx_hs_reg_read,
+ .write = mv64xxx_hs_reg_write,
+};
+
+/* Provide sysfs file indicating if this platform supports the hs_reg */
+static ssize_t
+mv64xxx_hs_reg_valid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct platform_device *pdev;
+ struct mv64xxx_pdata *pdp;
+ u32 v;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ pdp = (struct mv64xxx_pdata *)pdev->dev.platform_data;
+
+ if (down_interruptible(&mv64xxx_hs_lock))
+ return -ERESTARTSYS;
+ v = pdp->hs_reg_valid;
+ up(&mv64xxx_hs_lock);
+
+ return sprintf(buf, "%i\n", v);
+}
+static DEVICE_ATTR(hs_reg_valid, S_IRUGO, mv64xxx_hs_reg_valid_show, NULL);
+
+static int __init
+mv64xxx_sysfs_init(void)
+{
+ sysfs_create_bin_file(&mv64xxx_device.dev.kobj, &mv64xxx_hs_reg_attr);
+ sysfs_create_file(&mv64xxx_device.dev.kobj,&dev_attr_hs_reg_valid.attr);
+ return 0;
+}
+subsys_initcall(mv64xxx_sysfs_init);
+#endif
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index e5fd2ae503ea..9ccce438bd7a 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -165,7 +165,7 @@ ocp_device_remove(struct device *dev)
}
static int
-ocp_device_suspend(struct device *dev, u32 state)
+ocp_device_suspend(struct device *dev, pm_message_t state)
{
struct ocp_device *ocp_dev = to_ocp_dev(dev);
struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
index 1eb4f726ca9f..da8a0f2128dc 100644
--- a/arch/ppc/syslib/of_device.c
+++ b/arch/ppc/syslib/of_device.c
@@ -105,7 +105,7 @@ static int of_device_remove(struct device *dev)
return 0;
}
-static int of_device_suspend(struct device *dev, u32 state)
+static int of_device_suspend(struct device *dev, pm_message_t state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index ad39b86ca92c..53da58523e39 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -948,7 +948,7 @@ static void openpic_cached_disable_irq(u_int irq)
* we need something better to deal with that... Maybe switch to S1 for
* cpufreq changes
*/
-int openpic_suspend(struct sys_device *sysdev, u32 state)
+int openpic_suspend(struct sys_device *sysdev, pm_message_t state)
{
int i;
unsigned long flags;
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index 7e272c51a497..2e0ea92144f6 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -82,13 +82,11 @@ static void openpic2_end_irq(unsigned int irq_nr);
static void openpic2_ack_irq(unsigned int irq_nr);
struct hw_interrupt_type open_pic2 = {
- " OpenPIC2 ",
- NULL,
- NULL,
- openpic2_enable_irq,
- openpic2_disable_irq,
- openpic2_ack_irq,
- openpic2_end_irq,
+ .typename = " OpenPIC2 ",
+ .enable = openpic2_enable_irq,
+ .disable = openpic2_disable_irq,
+ .ack = openpic2_ack_irq,
+ .end = openpic2_end_irq,
};
/*
diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c
index 06cb0af2a58d..ce4d1deb86e9 100644
--- a/arch/ppc/syslib/ppc403_pic.c
+++ b/arch/ppc/syslib/ppc403_pic.c
@@ -34,13 +34,10 @@ static void ppc403_aic_disable(unsigned int irq);
static void ppc403_aic_disable_and_ack(unsigned int irq);
static struct hw_interrupt_type ppc403_aic = {
- "403GC AIC",
- NULL,
- NULL,
- ppc403_aic_enable,
- ppc403_aic_disable,
- ppc403_aic_disable_and_ack,
- 0
+ .typename = "403GC AIC",
+ .enable = ppc403_aic_enable,
+ .disable = ppc403_aic_disable,
+ .ack = ppc403_aic_disable_and_ack,
};
int
diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
index e170aebeb69b..b843c4fef25e 100644
--- a/arch/ppc/syslib/ppc4xx_setup.c
+++ b/arch/ppc/syslib/ppc4xx_setup.c
@@ -48,10 +48,6 @@
extern void abort(void);
extern void ppc4xx_find_bridges(void);
-extern void ppc4xx_wdt_heartbeat(void);
-extern int wdt_enable;
-extern unsigned long wdt_period;
-
/* Global Variables */
bd_t __res;
@@ -171,7 +167,7 @@ ppc4xx_calibrate_decr(void)
unsigned int freq;
bd_t *bip = &__res;
-#if defined(CONFIG_WALNUT) || defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE)
+#if defined(CONFIG_WALNUT) || defined(CONFIG_SYCAMORE)
/* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
#endif
@@ -257,22 +253,6 @@ ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
*(char *) (r7 + KERNELBASE) = 0;
strcpy(cmd_line, (char *) (r6 + KERNELBASE));
}
-#if defined(CONFIG_PPC405_WDT)
-/* Look for wdt= option on command line */
- if (strstr(cmd_line, "wdt=")) {
- int valid_wdt = 0;
- char *p, *q;
- for (q = cmd_line; (p = strstr(q, "wdt=")) != 0;) {
- q = p + 4;
- if (p > cmd_line && p[-1] != ' ')
- continue;
- wdt_period = simple_strtoul(q, &q, 0);
- valid_wdt = 1;
- ++q;
- }
- wdt_enable = valid_wdt;
- }
-#endif
/* Initialize machine-dependent vectors */
@@ -287,11 +267,6 @@ ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.calibrate_decr = ppc4xx_calibrate_decr;
-#ifdef CONFIG_PPC405_WDT
- ppc_md.heartbeat = ppc4xx_wdt_heartbeat;
-#endif
- ppc_md.heartbeat_count = 0;
-
ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory;
ppc_md.setup_io_mappings = ppc4xx_map_io;
diff --git a/arch/ppc/syslib/ppc83xx_pci.h b/arch/ppc/syslib/ppc83xx_pci.h
new file mode 100644
index 000000000000..ec691640f6be
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_pci.h
@@ -0,0 +1,151 @@
+/* Created by Tony Li <tony.li@freescale.com>
+ * Copyright (c) 2005 freescale semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PPC_SYSLIB_PPC83XX_PCI_H
+#define __PPC_SYSLIB_PPC83XX_PCI_H
+
+typedef struct immr_clk {
+ u32 spmr; /* system PLL mode Register */
+ u32 occr; /* output clock control Register */
+ u32 sccr; /* system clock control Register */
+ u8 res0[0xF4];
+} immr_clk_t;
+
+/*
+ * Sequencer
+ */
+typedef struct immr_ios {
+ u32 potar0;
+ u8 res0[4];
+ u32 pobar0;
+ u8 res1[4];
+ u32 pocmr0;
+ u8 res2[4];
+ u32 potar1;
+ u8 res3[4];
+ u32 pobar1;
+ u8 res4[4];
+ u32 pocmr1;
+ u8 res5[4];
+ u32 potar2;
+ u8 res6[4];
+ u32 pobar2;
+ u8 res7[4];
+ u32 pocmr2;
+ u8 res8[4];
+ u32 potar3;
+ u8 res9[4];
+ u32 pobar3;
+ u8 res10[4];
+ u32 pocmr3;
+ u8 res11[4];
+ u32 potar4;
+ u8 res12[4];
+ u32 pobar4;
+ u8 res13[4];
+ u32 pocmr4;
+ u8 res14[4];
+ u32 potar5;
+ u8 res15[4];
+ u32 pobar5;
+ u8 res16[4];
+ u32 pocmr5;
+ u8 res17[4];
+ u8 res18[0x60];
+ u32 pmcr;
+ u8 res19[4];
+ u32 dtcr;
+ u8 res20[4];
+} immr_ios_t;
+#define POTAR_TA_MASK 0x000fffff
+#define POBAR_BA_MASK 0x000fffff
+#define POCMR_EN 0x80000000
+#define POCMR_IO 0x40000000 /* 0--memory space 1--I/O space */
+#define POCMR_SE 0x20000000 /* streaming enable */
+#define POCMR_DST 0x10000000 /* 0--PCI1 1--PCI2 */
+#define POCMR_CM_MASK 0x000fffff
+
+/*
+ * PCI Controller Control and Status Registers
+ */
+typedef struct immr_pcictrl {
+ u32 esr;
+ u32 ecdr;
+ u32 eer;
+ u32 eatcr;
+ u32 eacr;
+ u32 eeacr;
+ u32 edlcr;
+ u32 edhcr;
+ u32 gcr;
+ u32 ecr;
+ u32 gsr;
+ u8 res0[12];
+ u32 pitar2;
+ u8 res1[4];
+ u32 pibar2;
+ u32 piebar2;
+ u32 piwar2;
+ u8 res2[4];
+ u32 pitar1;
+ u8 res3[4];
+ u32 pibar1;
+ u32 piebar1;
+ u32 piwar1;
+ u8 res4[4];
+ u32 pitar0;
+ u8 res5[4];
+ u32 pibar0;
+ u8 res6[4];
+ u32 piwar0;
+ u8 res7[132];
+} immr_pcictrl_t;
+#define PITAR_TA_MASK 0x000fffff
+#define PIBAR_MASK 0xffffffff
+#define PIEBAR_EBA_MASK 0x000fffff
+#define PIWAR_EN 0x80000000
+#define PIWAR_PF 0x20000000
+#define PIWAR_RTT_MASK 0x000f0000
+#define PIWAR_RTT_NO_SNOOP 0x00040000
+#define PIWAR_RTT_SNOOP 0x00050000
+#define PIWAR_WTT_MASK 0x0000f000
+#define PIWAR_WTT_NO_SNOOP 0x00004000
+#define PIWAR_WTT_SNOOP 0x00005000
+#define PIWAR_IWS_MASK 0x0000003F
+#define PIWAR_IWS_4K 0x0000000B
+#define PIWAR_IWS_8K 0x0000000C
+#define PIWAR_IWS_16K 0x0000000D
+#define PIWAR_IWS_32K 0x0000000E
+#define PIWAR_IWS_64K 0x0000000F
+#define PIWAR_IWS_128K 0x00000010
+#define PIWAR_IWS_256K 0x00000011
+#define PIWAR_IWS_512K 0x00000012
+#define PIWAR_IWS_1M 0x00000013
+#define PIWAR_IWS_2M 0x00000014
+#define PIWAR_IWS_4M 0x00000015
+#define PIWAR_IWS_8M 0x00000016
+#define PIWAR_IWS_16M 0x00000017
+#define PIWAR_IWS_32M 0x00000018
+#define PIWAR_IWS_64M 0x00000019
+#define PIWAR_IWS_128M 0x0000001A
+#define PIWAR_IWS_256M 0x0000001B
+#define PIWAR_IWS_512M 0x0000001C
+#define PIWAR_IWS_1G 0x0000001D
+#define PIWAR_IWS_2G 0x0000001E
+
+#endif /* __PPC_SYSLIB_PPC83XX_PCI_H */
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index 602a86891f7f..890484e576e7 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -11,6 +11,17 @@
* under the terms of the 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.
+ *
+ * Added PCI support -- Tony Li <tony.li@freescale.com>
*/
#include <linux/config.h>
@@ -31,6 +42,10 @@
#include <asm/delay.h>
#include <syslib/ppc83xx_setup.h>
+#if defined(CONFIG_PCI)
+#include <asm/delay.h>
+#include <syslib/ppc83xx_pci.h>
+#endif
phys_addr_t immrbar;
@@ -162,4 +177,237 @@ mpc83xx_halt(void)
for(;;);
}
-/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
+#if defined(CONFIG_PCI)
+void __init
+mpc83xx_setup_pci1(struct pci_controller *hose)
+{
+ u16 reg16;
+ volatile immr_pcictrl_t * pci_ctrl;
+ volatile immr_ios_t * ios;
+ bd_t *binfo = (bd_t *) __res;
+
+ pci_ctrl = ioremap(binfo->bi_immr_base + 0x8500, sizeof(immr_pcictrl_t));
+ ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
+
+ /*
+ * Configure PCI Outbound Translation Windows
+ */
+ ios->potar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POTAR_TA_MASK;
+ ios->pobar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POBAR_BA_MASK;
+ ios->pocmr0 = POCMR_EN |
+ (((0xffffffff - (MPC83xx_PCI1_UPPER_MEM -
+ MPC83xx_PCI1_LOWER_MEM)) >> 12) & POCMR_CM_MASK);
+
+ /* mapped to PCI1 IO space */
+ ios->potar1 = (MPC83xx_PCI1_LOWER_IO >> 12) & POTAR_TA_MASK;
+ ios->pobar1 = (MPC83xx_PCI1_IO_BASE >> 12) & POBAR_BA_MASK;
+ ios->pocmr1 = POCMR_EN | POCMR_IO |
+ (((0xffffffff - (MPC83xx_PCI1_UPPER_IO -
+ MPC83xx_PCI1_LOWER_IO)) >> 12) & POCMR_CM_MASK);
+
+ /*
+ * Configure PCI Inbound Translation Windows
+ */
+ pci_ctrl->pitar1 = 0x0;
+ pci_ctrl->pibar1 = 0x0;
+ pci_ctrl->piebar1 = 0x0;
+ pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+
+ /*
+ * Release PCI RST signal
+ */
+ pci_ctrl->gcr = 0;
+ udelay(2000);
+ pci_ctrl->gcr = 1;
+ udelay(2000);
+
+ reg16 = 0xff;
+ early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS, 0xffff);
+ early_write_config_byte(hose, hose->first_busno, 0, PCI_LATENCY_TIMER, 0x80);
+
+ iounmap(pci_ctrl);
+ iounmap(ios);
+}
+
+void __init
+mpc83xx_setup_pci2(struct pci_controller *hose)
+{
+ u16 reg16;
+ volatile immr_pcictrl_t * pci_ctrl;
+ volatile immr_ios_t * ios;
+ bd_t *binfo = (bd_t *) __res;
+
+ pci_ctrl = ioremap(binfo->bi_immr_base + 0x8600, sizeof(immr_pcictrl_t));
+ ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
+
+ /*
+ * Configure PCI Outbound Translation Windows
+ */
+ ios->potar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POTAR_TA_MASK;
+ ios->pobar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POBAR_BA_MASK;
+ ios->pocmr3 = POCMR_EN | POCMR_DST |
+ (((0xffffffff - (MPC83xx_PCI2_UPPER_MEM -
+ MPC83xx_PCI2_LOWER_MEM)) >> 12) & POCMR_CM_MASK);
+
+ /* mapped to PCI2 IO space */
+ ios->potar4 = (MPC83xx_PCI2_LOWER_IO >> 12) & POTAR_TA_MASK;
+ ios->pobar4 = (MPC83xx_PCI2_IO_BASE >> 12) & POBAR_BA_MASK;
+ ios->pocmr4 = POCMR_EN | POCMR_DST | POCMR_IO |
+ (((0xffffffff - (MPC83xx_PCI2_UPPER_IO -
+ MPC83xx_PCI2_LOWER_IO)) >> 12) & POCMR_CM_MASK);
+
+ /*
+ * Configure PCI Inbound Translation Windows
+ */
+ pci_ctrl->pitar1 = 0x0;
+ pci_ctrl->pibar1 = 0x0;
+ pci_ctrl->piebar1 = 0x0;
+ pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+
+ /*
+ * Release PCI RST signal
+ */
+ pci_ctrl->gcr = 0;
+ udelay(2000);
+ pci_ctrl->gcr = 1;
+ udelay(2000);
+
+ reg16 = 0xff;
+ early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS, 0xffff);
+ early_write_config_byte(hose, hose->first_busno, 0, PCI_LATENCY_TIMER, 0x80);
+
+ iounmap(pci_ctrl);
+ iounmap(ios);
+}
+
+/*
+ * PCI buses can be enabled only if SYS board combinates with PIB
+ * (Platform IO Board) board which provide 3 PCI slots. There is 2 PCI buses
+ * and 3 PCI slots, so people must configure the routes between them before
+ * enable PCI bus. This routes are under the control of PCA9555PW device which
+ * can be accessed via I2C bus 2 and are configured by firmware. Refer to
+ * Freescale to get more information about firmware configuration.
+ */
+
+extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin);
+void __init
+mpc83xx_setup_hose(void)
+{
+ u32 val32;
+ volatile immr_clk_t * clk;
+ struct pci_controller * hose1;
+#ifdef CONFIG_MPC83xx_PCI2
+ struct pci_controller * hose2;
+#endif
+ bd_t * binfo = (bd_t *)__res;
+
+ clk = ioremap(binfo->bi_immr_base + 0xA00,
+ sizeof(immr_clk_t));
+
+ /*
+ * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
+ */
+ val32 = clk->occr;
+ udelay(2000);
+ clk->occr = 0xff000000;
+ udelay(2000);
+
+ iounmap(clk);
+
+ hose1 = pcibios_alloc_controller();
+ if(!hose1)
+ return;
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = mpc83xx_map_irq;
+
+ hose1->bus_offset = 0;
+ hose1->first_busno = 0;
+ hose1->last_busno = 0xff;
+
+ setup_indirect_pci(hose1, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET,
+ binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
+ hose1->set_cfg_type = 1;
+
+ mpc83xx_setup_pci1(hose1);
+
+ hose1->pci_mem_offset = MPC83xx_PCI1_MEM_OFFSET;
+ hose1->mem_space.start = MPC83xx_PCI1_LOWER_MEM;
+ hose1->mem_space.end = MPC83xx_PCI1_UPPER_MEM;
+
+ hose1->io_base_phys = MPC83xx_PCI1_IO_BASE;
+ hose1->io_space.start = MPC83xx_PCI1_LOWER_IO;
+ hose1->io_space.end = MPC83xx_PCI1_UPPER_IO;
+#ifdef CONFIG_MPC83xx_PCI2
+ isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
+ MPC83xx_PCI1_IO_SIZE + MPC83xx_PCI2_IO_SIZE);
+#else
+ isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
+ MPC83xx_PCI1_IO_SIZE);
+#endif /* CONFIG_MPC83xx_PCI2 */
+ hose1->io_base_virt = (void *)isa_io_base;
+ /* setup resources */
+ pci_init_resource(&hose1->io_resource,
+ MPC83xx_PCI1_LOWER_IO,
+ MPC83xx_PCI1_UPPER_IO,
+ IORESOURCE_IO, "PCI host bridge 1");
+ pci_init_resource(&hose1->mem_resources[0],
+ MPC83xx_PCI1_LOWER_MEM,
+ MPC83xx_PCI1_UPPER_MEM,
+ IORESOURCE_MEM, "PCI host bridge 1");
+
+ ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+ hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno);
+
+#ifdef CONFIG_MPC83xx_PCI2
+ hose2 = pcibios_alloc_controller();
+ if(!hose2)
+ return;
+
+ hose2->bus_offset = hose1->last_busno + 1;
+ hose2->first_busno = hose1->last_busno + 1;
+ hose2->last_busno = 0xff;
+ setup_indirect_pci(hose2, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET,
+ binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
+ hose2->set_cfg_type = 1;
+
+ mpc83xx_setup_pci2(hose2);
+
+ hose2->pci_mem_offset = MPC83xx_PCI2_MEM_OFFSET;
+ hose2->mem_space.start = MPC83xx_PCI2_LOWER_MEM;
+ hose2->mem_space.end = MPC83xx_PCI2_UPPER_MEM;
+
+ hose2->io_base_phys = MPC83xx_PCI2_IO_BASE;
+ hose2->io_space.start = MPC83xx_PCI2_LOWER_IO;
+ hose2->io_space.end = MPC83xx_PCI2_UPPER_IO;
+ hose2->io_base_virt = (void *)(isa_io_base + MPC83xx_PCI1_IO_SIZE);
+ /* setup resources */
+ pci_init_resource(&hose2->io_resource,
+ MPC83xx_PCI2_LOWER_IO,
+ MPC83xx_PCI2_UPPER_IO,
+ IORESOURCE_IO, "PCI host bridge 2");
+ pci_init_resource(&hose2->mem_resources[0],
+ MPC83xx_PCI2_LOWER_MEM,
+ MPC83xx_PCI2_UPPER_MEM,
+ IORESOURCE_MEM, "PCI host bridge 2");
+
+ hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
+#endif /* CONFIG_MPC83xx_PCI2 */
+}
+#endif /*CONFIG_PCI*/
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h
index 683f179b746c..c766c1a5f786 100644
--- a/arch/ppc/syslib/ppc83xx_setup.h
+++ b/arch/ppc/syslib/ppc83xx_setup.h
@@ -12,6 +12,14 @@
* 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 __PPC_SYSLIB_PPC83XX_SETUP_H
@@ -19,7 +27,6 @@
#include <linux/config.h>
#include <linux/init.h>
-#include <asm/ppcboot.h>
extern unsigned long mpc83xx_find_end_of_memory(void) __init;
extern long mpc83xx_time_init(void) __init;
@@ -31,13 +38,11 @@ extern void mpc83xx_halt(void);
extern void mpc83xx_setup_hose(void) __init;
/* PCI config */
-#if 0
-#define PCI1_CFG_ADDR_OFFSET (FIXME)
-#define PCI1_CFG_DATA_OFFSET (FIXME)
+#define PCI1_CFG_ADDR_OFFSET (0x8300)
+#define PCI1_CFG_DATA_OFFSET (0x8304)
-#define PCI2_CFG_ADDR_OFFSET (FIXME)
-#define PCI2_CFG_DATA_OFFSET (FIXME)
-#endif
+#define PCI2_CFG_ADDR_OFFSET (0x8380)
+#define PCI2_CFG_DATA_OFFSET (0x8384)
/* Serial Config */
#ifdef CONFIG_SERIAL_MANY_PORTS
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 879202352560..52ba0c68078d 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -6,6 +6,7 @@
* Maintainer: Kumar Gala <kumar.gala@freescale.com>
*
* Copyright 2005 Freescale Semiconductor Inc.
+ * Copyright 2005 MontaVista, Inc. by 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 the
@@ -35,10 +36,59 @@ void __init identify_ppc_sys_by_id(u32 id)
void __init identify_ppc_sys_by_name(char *name)
{
- /* TODO */
+ unsigned int i = 0;
+ while (ppc_sys_specs[i].ppc_sys_name[0])
+ {
+ if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
+ break;
+ i++;
+ }
+ cur_ppc_sys_spec = &ppc_sys_specs[i];
return;
}
+static int __init count_sys_specs(void)
+{
+ int i = 0;
+ while (ppc_sys_specs[i].ppc_sys_name[0])
+ i++;
+ return i;
+}
+
+static int __init find_chip_by_name_and_id(char *name, u32 id)
+{
+ int ret = -1;
+ unsigned int i = 0;
+ unsigned int j = 0;
+ unsigned int dups = 0;
+
+ unsigned char matched[count_sys_specs()];
+
+ while (ppc_sys_specs[i].ppc_sys_name[0]) {
+ if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
+ matched[j++] = i;
+ i++;
+ }
+ if (j != 0) {
+ for (i = 0; i < j; i++) {
+ if ((ppc_sys_specs[matched[i]].mask & id) ==
+ ppc_sys_specs[matched[i]].value) {
+ ret = matched[i];
+ dups++;
+ }
+ }
+ ret = (dups == 1) ? ret : (-1 * dups);
+ }
+ return ret;
+}
+
+void __init identify_ppc_sys_by_name_and_id(char *name, u32 id)
+{
+ int i = find_chip_by_name_and_id(name, id);
+ BUG_ON(i < 0);
+ cur_ppc_sys_spec = &ppc_sys_specs[i];
+}
+
/* Update all memory resources by paddr, call before platform_device_register */
void __init
ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c
new file mode 100644
index 000000000000..1d3869768f96
--- /dev/null
+++ b/arch/ppc/syslib/pq2_devices.c
@@ -0,0 +1,389 @@
+/*
+ * arch/ppc/syslib/pq2_devices.c
+ *
+ * PQ2 Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC82xx_CPM_FCC1] = {
+ .name = "fsl-cpm-fcc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "fcc_regs",
+ .start = 0x11300,
+ .end = 0x1131f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fcc_pram",
+ .start = 0x8400,
+ .end = 0x84ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC1,
+ .end = SIU_INT_FCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_FCC2] = {
+ .name = "fsl-cpm-fcc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "fcc_regs",
+ .start = 0x11320,
+ .end = 0x1133f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fcc_pram",
+ .start = 0x8500,
+ .end = 0x85ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC2,
+ .end = SIU_INT_FCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_FCC3] = {
+ .name = "fsl-cpm-fcc",
+ .id = 3,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "fcc_regs",
+ .start = 0x11340,
+ .end = 0x1135f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fcc_pram",
+ .start = 0x8600,
+ .end = 0x86ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC3,
+ .end = SIU_INT_FCC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_I2C] = {
+ .name = "fsl-cpm-i2c",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "i2c_mem",
+ .start = 0x11860,
+ .end = 0x118BF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "i2c_pram",
+ .start = 0x8afc,
+ .end = 0x8afd,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_I2C,
+ .end = SIU_INT_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SCC1] = {
+ .name = "fsl-cpm-scc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "scc_mem",
+ .start = 0x11A00,
+ .end = 0x11A1F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "scc_pram",
+ .start = 0x8000,
+ .end = 0x80ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC1,
+ .end = SIU_INT_SCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SCC2] = {
+ .name = "fsl-cpm-scc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "scc_mem",
+ .start = 0x11A20,
+ .end = 0x11A3F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "scc_pram",
+ .start = 0x8100,
+ .end = 0x81ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC2,
+ .end = SIU_INT_SCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SCC3] = {
+ .name = "fsl-cpm-scc",
+ .id = 3,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "scc_mem",
+ .start = 0x11A40,
+ .end = 0x11A5F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "scc_pram",
+ .start = 0x8200,
+ .end = 0x82ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC3,
+ .end = SIU_INT_SCC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SCC4] = {
+ .name = "fsl-cpm-scc",
+ .id = 4,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "scc_mem",
+ .start = 0x11A60,
+ .end = 0x11A7F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "scc_pram",
+ .start = 0x8300,
+ .end = 0x83ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC4,
+ .end = SIU_INT_SCC4,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SPI] = {
+ .name = "fsl-cpm-spi",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "spi_mem",
+ .start = 0x11AA0,
+ .end = 0x11AFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "spi_pram",
+ .start = 0x89fc,
+ .end = 0x89fd,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SPI,
+ .end = SIU_INT_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_MCC1] = {
+ .name = "fsl-cpm-mcc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "mcc_mem",
+ .start = 0x11B30,
+ .end = 0x11B3F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mcc_pram",
+ .start = 0x8700,
+ .end = 0x877f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_MCC1,
+ .end = SIU_INT_MCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_MCC2] = {
+ .name = "fsl-cpm-mcc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "mcc_mem",
+ .start = 0x11B50,
+ .end = 0x11B5F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mcc_pram",
+ .start = 0x8800,
+ .end = 0x887f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_MCC2,
+ .end = SIU_INT_MCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SMC1] = {
+ .name = "fsl-cpm-smc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "smc_mem",
+ .start = 0x11A80,
+ .end = 0x11A8F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "smc_pram",
+ .start = 0x87fc,
+ .end = 0x87fd,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SMC1,
+ .end = SIU_INT_SMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_SMC2] = {
+ .name = "fsl-cpm-smc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "smc_mem",
+ .start = 0x11A90,
+ .end = 0x11A9F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "smc_pram",
+ .start = 0x88fc,
+ .end = 0x88fd,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SMC2,
+ .end = SIU_INT_SMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC82xx_CPM_USB] = {
+ .name = "fsl-cpm-usb",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "usb_mem",
+ .start = 0x11b60,
+ .end = 0x11b78,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "usb_pram",
+ .start = 0x8b00,
+ .end = 0x8bff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_USB,
+ .end = SIU_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+
+ },
+ },
+ [MPC82xx_SEC1] = {
+ .name = "fsl-sec",
+ .id = 1,
+ .num_resources = 1,
+ .resource = (struct resource[]) {
+ {
+ .name = "sec_mem",
+ .start = 0x40000,
+ .end = 0x52fff,
+ .flags = IORESOURCE_MEM,
+ },
+ },
+ },
+};
+
+static int __init mach_mpc82xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
+ return 0;
+}
+
+static int __init mach_mpc82xx_init(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("mach_mpc82xx_init:enter", 0);
+ ppc_sys_device_fixup = mach_mpc82xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc82xx_init);
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
new file mode 100644
index 000000000000..7b6c9ebdb9e3
--- /dev/null
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -0,0 +1,200 @@
+/*
+ * arch/ppc/syslib/pq2_devices.c
+ *
+ * PQ2 System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ /* below is a list of the 8260 family of processors */
+ {
+ .ppc_sys_name = "8250",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ {
+ .ppc_sys_name = "8255",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
+ MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2,
+ MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ {
+ .ppc_sys_name = "8260",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ {
+ .ppc_sys_name = "8264",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ {
+ .ppc_sys_name = "8265",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ {
+ .ppc_sys_name = "8266",
+ .mask = 0x0000ff00,
+ .value = 0x00000000,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ }
+ },
+ /* below is a list of the 8272 family of processors */
+ {
+ .ppc_sys_name = "8247",
+ .mask = 0x0000ff00,
+ .value = 0x00000d00,
+ .num_devices = 10,
+ .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,
+ },
+ },
+ {
+ .ppc_sys_name = "8248",
+ .mask = 0x0000ff00,
+ .value = 0x00000c00,
+ .num_devices = 11,
+ .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,
+ },
+ },
+ {
+ .ppc_sys_name = "8271",
+ .mask = 0x0000ff00,
+ .value = 0x00000d00,
+ .num_devices = 10,
+ .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,
+ },
+ },
+ {
+ .ppc_sys_name = "8272",
+ .mask = 0x0000ff00,
+ .value = 0x00000c00,
+ .num_devices = 11,
+ .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,
+ },
+ },
+ /* below is a list of the 8280 family of processors */
+ {
+ .ppc_sys_name = "8270",
+ .mask = 0x0000ff00,
+ .value = 0x00000a00,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ },
+ },
+ {
+ .ppc_sys_name = "8275",
+ .mask = 0x0000ff00,
+ .value = 0x00000a00,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
+ },
+ },
+ {
+ .ppc_sys_name = "8280",
+ .mask = 0x0000ff00,
+ .value = 0x00000a00,
+ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4, MPC82xx_CPM_MCC1, MPC82xx_CPM_MCC2,
+ MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+ MPC82xx_CPM_I2C,
+ },
+ },
+ {
+ /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c
index 2bcf8a16d1c9..8599850ca772 100644
--- a/arch/ppc/syslib/prep_nvram.c
+++ b/arch/ppc/syslib/prep_nvram.c
@@ -15,7 +15,6 @@
#include <linux/ioport.h>
#include <asm/sections.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/prep_nvram.h>
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
index 57f4ed5e5ae1..0970b5d30391 100644
--- a/arch/ppc/syslib/qspan_pci.c
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -94,7 +94,7 @@
#define mk_config_type1(bus, dev, offset) \
mk_config_addr(bus, dev, offset) | 1;
-static spinlock_t pcibios_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pcibios_lock);
int qspan_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
index e0bd66f0847a..2cbcad278cef 100644
--- a/arch/ppc/syslib/xilinx_pic.c
+++ b/arch/ppc/syslib/xilinx_pic.c
@@ -79,14 +79,11 @@ xilinx_intc_end(unsigned int irq)
}
static struct hw_interrupt_type xilinx_intc = {
- "Xilinx Interrupt Controller",
- NULL,
- NULL,
- xilinx_intc_enable,
- xilinx_intc_disable,
- xilinx_intc_disable_and_ack,
- xilinx_intc_end,
- 0
+ .typename = "Xilinx Interrupt Controller",
+ .enable = xilinx_intc_enable,
+ .disable = xilinx_intc_disable,
+ .ack = xilinx_intc_disable_and_ack,
+ .end = xilinx_intc_end,
};
int
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 2ce87836c671..deca68ad644a 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -44,6 +44,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
# We optimistically allocate largepages from the VM, so make the limit
# large enough (16MB). This badly named config option is actually
# max order + 1
@@ -302,12 +306,6 @@ config GENERIC_HARDIRQS
bool
default y
-config MSCHUNKS
- bool
- depends on PPC_ISERIES
- default y
-
-
config PPC_RTAS
bool
depends on PPC_PSERIES || PPC_BPA
@@ -350,13 +348,46 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
+source "fs/Kconfig.binfmt"
+
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs"
+ depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+ select HOTPLUG
+ ---help---
+ Say Y here to be able to turn CPUs off and on.
+
+ Say N if you are unsure.
+
+config PROC_DEVICETREE
+ bool "Support for Open Firmware device tree in /proc"
+ depends on !PPC_ISERIES
+ 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 CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+ depends on !PPC_ISERIES
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
+ help
+ On some platforms, there is currently no way for the boot loader to
+ pass arguments to the kernel. For these platforms, you can supply
+ some command-line options at build time by entering them here. In
+ most cases you will need to specify the root device here.
+
endmenu
config ISA_DMA_API
bool
default y
-menu "General setup"
+menu "Bus Options"
config ISA
bool
@@ -389,45 +420,12 @@ config PCI_DOMAINS
bool
default PCI
-source "fs/Kconfig.binfmt"
-
source "drivers/pci/Kconfig"
-config HOTPLUG_CPU
- bool "Support for hot-pluggable CPUs"
- depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
- select HOTPLUG
- ---help---
- Say Y here to be able to turn CPUs off and on.
-
- Say N if you are unsure.
-
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
-config PROC_DEVICETREE
- bool "Support for Open Firmware device tree in /proc"
- depends on !PPC_ISERIES
- 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 CMDLINE_BOOL
- bool "Default bootloader kernel arguments"
- depends on !PPC_ISERIES
-
-config CMDLINE
- string "Initial kernel command string"
- depends on CMDLINE_BOOL
- default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
- help
- On some platforms, there is currently no way for the boot loader to
- pass arguments to the kernel. For these platforms, you can supply
- some command-line options at build time by entering them here. In
- most cases you will need to specify the root device here.
-
endmenu
source "net/Kconfig"
diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
index 46b1ce58da3b..f16a5030527b 100644
--- a/arch/ppc64/Kconfig.debug
+++ b/arch/ppc64/Kconfig.debug
@@ -41,10 +41,19 @@ config XMON
help
Include in-kernel hooks for the xmon kernel monitor/debugger.
Unless you are intending to debug the kernel, say N here.
+ Make sure to enable also CONFIG_BOOTX_TEXT on Macs. Otherwise
+ nothing will appear on the screen (xmon writes directly to the
+ framebuffer memory).
+ The cmdline option 'xmon' or 'xmon=early' will drop into xmon very
+ early during boot. 'xmon=on' will just enable the xmon debugger hooks.
+ 'xmon=off' will disable the debugger hooks if CONFIG_XMON_DEFAULT is set.
config XMON_DEFAULT
bool "Enable xmon by default"
depends on XMON
+ help
+ xmon is normally disabled unless booted with 'xmon=on'.
+ Use 'xmon=off' to disable xmon init during runtime.
config PPCDBG
bool "Include PPCDBG realtime debugging"
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 731b84758331..17d2c1eac3b8 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -49,12 +49,14 @@ NM := $(NM) --synthetic
endif
-CHECKFLAGS += -m64 -D__powerpc__
+CHECKFLAGS += -m64 -D__powerpc__ -D__powerpc64__
LDFLAGS := -m elf64ppc
LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \
-mcall-aixdesc
+# Temporary hack until we have migrated to asm-powerpc
+CPPFLAGS += -Iarch/$(ARCH)/include
GCC_VERSION := $(call cc-version)
GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;)
@@ -87,11 +89,12 @@ drivers-$(CONFIG_OPROFILE) += arch/ppc64/oprofile/
boot := arch/ppc64/boot
-boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd
-boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd
-boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
-boottarget-$(CONFIG_PPC_BPA) := zImage zImage.initrd
-$(boottarget-y): vmlinux
+boottargets-$(CONFIG_PPC_PSERIES) += zImage zImage.initrd
+boottargets-$(CONFIG_PPC_PMAC) += zImage.vmode zImage.initrd.vmode
+boottargets-$(CONFIG_PPC_MAPLE) += zImage zImage.initrd
+boottargets-$(CONFIG_PPC_ISERIES) += vmlinux.sminitrd vmlinux.initrd vmlinux.sm
+boottargets-$(CONFIG_PPC_BPA) += zImage zImage.initrd
+$(boottargets-y): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
@@ -112,20 +115,21 @@ all: $(KBUILD_IMAGE)
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
+ # Temporary hack until we have migrated to asm-powerpc
+ $(Q)rm -rf arch/$(ARCH)/include
-prepare: include/asm-ppc64/offsets.h
-arch/ppc64/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
+# Temporary hack until we have migrated to asm-powerpc
+include/asm: arch/$(ARCH)/include/asm
+arch/$(ARCH)/include/asm:
+ $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi
+ $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm
define archhelp
- echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
- echo ' zImage.initrd- Compressed kernel image with initrd attached,'
- echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz'
- echo ' (arch/$(ARCH)/boot/zImage.initrd)'
+ echo ' zImage.vmode - Compressed kernel image (arch/$(ARCH)/boot/zImage.vmode)'
+ echo ' zImage.initrd.vmode - Compressed kernel image with initrd attached,'
+ echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz'
+ echo ' (arch/$(ARCH)/boot/zImage.initrd.vmode)'
+ echo ' zImage - zImage for pSeries machines'
+ echo ' zImage.initrd - zImage with initrd for pSeries machines'
endef
-
-CLEAN_FILES += include/asm-ppc64/offsets.h
diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
index 683b2d43c15f..33fdc8710891 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/ppc64/boot/Makefile
@@ -22,8 +22,8 @@
HOSTCC := gcc
-BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin
-BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
+BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include)
+BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
OBJCOPYFLAGS := contents,alloc,load,readonly,data
@@ -37,6 +37,9 @@ quiet_cmd_bootcc = BOOTCC $@
quiet_cmd_bootas = BOOTAS $@
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
+quiet_cmd_bootld = BOOTLD $@
+ cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2)
+
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
$(call if_changed_dep,bootcc)
$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
@@ -53,7 +56,7 @@ src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
hostprogs-y := addnote addRamDisk
-targets += zImage zImage.initrd imagesize.c \
+targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd imagesize.c \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
@@ -63,7 +66,7 @@ extra-y := initrd.o
quiet_cmd_ramdisk = RAMDISK $@
cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
-quiet_cmd_stripvm = STRIP $@
+quiet_cmd_stripvm = STRIP $@
cmd_stripvm = $(STRIP) -s $< -o $@
vmlinux.strip: vmlinux FORCE
@@ -71,12 +74,20 @@ vmlinux.strip: vmlinux FORCE
$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
$(call if_changed,ramdisk)
-addsection = $(CROSS32OBJCOPY) $(1) \
- --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
- --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(OBJCOPYFLAGS)
+quiet_cmd_addsection = ADDSEC $@
+ cmd_addsection = $(CROSS32OBJCOPY) $@ \
+ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(patsubst %.o,%.gz, $@) \
+ --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(OBJCOPYFLAGS)
+
+quiet_cmd_imagesize = GENSIZE $@
+ cmd_imagesize = ls -l vmlinux.strip | \
+ awk '{printf "/* generated -- do not edit! */\n" "unsigned long vmlinux_filesize = %d;\n", $$5}' \
+ > $(obj)/imagesize.c && \
+ $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
+ awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' >> $(obj)/imagesize.c
-quiet_cmd_addnote = ADDNOTE $@
- cmd_addnote = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@
+quiet_cmd_addnote = ADDNOTE $@
+ cmd_addnote = $(obj)/addnote $@
$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE
$(call if_changed,gzip)
@@ -85,28 +96,30 @@ $(obj)/kernel-initrd.gz: $(obj)/ramdisk.image.gz
cp -f $(obj)/ramdisk.image.gz $@
$(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz FORCE
- touch $@
+ @touch $@
$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c FORCE
$(call if_changed_dep,bootcc)
- $(call addsection, $@)
+ $(call cmd,addsection)
+
+$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
+$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) FORCE
+ $(call cmd,bootld,$(obj-boot))
+
+$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
+$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) FORCE
+ $(call cmd,bootld,$(obj-boot))
-$(obj)/zImage: obj-boot += $(call obj-sec, $(required))
-$(obj)/zImage: $(call obj-sec, $(required)) $(obj-boot) $(obj)/addnote FORCE
+$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote FORCE
+ @cp -f $< $@
$(call if_changed,addnote)
-$(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd))
-$(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
+$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote FORCE
+ @cp -f $< $@
$(call if_changed,addnote)
$(obj)/imagesize.c: vmlinux.strip
- @echo Generating $@
- ls -l vmlinux.strip | \
- awk '{printf "/* generated -- do not edit! */\n" \
- "unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
- $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
- awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \
- >> $(obj)/imagesize.c
+ $(call cmd,imagesize)
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c
index 719663a694bb..8041a9845ab7 100644
--- a/arch/ppc64/boot/addnote.c
+++ b/arch/ppc64/boot/addnote.c
@@ -157,7 +157,7 @@ main(int ac, char **av)
PUT_32BE(ns, strlen(arch) + 1);
PUT_32BE(ns + 4, N_DESCR * 4);
PUT_32BE(ns + 8, 0x1275);
- strcpy(&buf[ns + 12], arch);
+ strcpy((char *) &buf[ns + 12], arch);
ns += 12 + strlen(arch) + 1;
for (i = 0; i < N_DESCR; ++i, ns += 4)
PUT_32BE(ns, descr[i]);
@@ -172,7 +172,7 @@ main(int ac, char **av)
PUT_32BE(ns, strlen(rpaname) + 1);
PUT_32BE(ns + 4, sizeof(rpanote));
PUT_32BE(ns + 8, 0x12759999);
- strcpy(&buf[ns + 12], rpaname);
+ strcpy((char *) &buf[ns + 12], rpaname);
ns += 12 + ROUNDUP(strlen(rpaname) + 1);
for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
PUT_32BE(ns, rpanote[i]);
diff --git a/arch/ppc64/boot/crt0.S b/arch/ppc64/boot/crt0.S
index 04d3e74cd72f..3861e7f9cf19 100644
--- a/arch/ppc64/boot/crt0.S
+++ b/arch/ppc64/boot/crt0.S
@@ -9,7 +9,7 @@
* NOTE: this code runs in 32 bit mode and is packaged as ELF32.
*/
-#include <asm/ppc_asm.h>
+#include "ppc_asm.h"
.text
.globl _start
diff --git a/arch/ppc64/boot/div64.S b/arch/ppc64/boot/div64.S
index 38f7e466d7d6..722f360a32a9 100644
--- a/arch/ppc64/boot/div64.S
+++ b/arch/ppc64/boot/div64.S
@@ -13,7 +13,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <asm/ppc_asm.h>
+#include "ppc_asm.h"
.globl __div64_32
__div64_32:
diff --git a/arch/ppc64/boot/elf.h b/arch/ppc64/boot/elf.h
new file mode 100644
index 000000000000..d4828fcf1cb9
--- /dev/null
+++ b/arch/ppc64/boot/elf.h
@@ -0,0 +1,149 @@
+#ifndef _PPC_BOOT_ELF_H_
+#define _PPC_BOOT_ELF_H_
+
+/* 32-bit ELF base types. */
+typedef unsigned int Elf32_Addr;
+typedef unsigned short Elf32_Half;
+typedef unsigned int Elf32_Off;
+typedef signed int Elf32_Sword;
+typedef unsigned int Elf32_Word;
+
+/* 64-bit ELF base types. */
+typedef unsigned long long Elf64_Addr;
+typedef unsigned short Elf64_Half;
+typedef signed short Elf64_SHalf;
+typedef unsigned long long Elf64_Off;
+typedef signed int Elf64_Sword;
+typedef unsigned int Elf64_Word;
+typedef unsigned long long Elf64_Xword;
+typedef signed long long Elf64_Sxword;
+
+/* These constants are for the segment types stored in the image headers */
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_TLS 7 /* Thread local storage segment */
+#define PT_LOOS 0x60000000 /* OS-specific */
+#define PT_HIOS 0x6fffffff /* OS-specific */
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+#define PT_GNU_EH_FRAME 0x6474e550
+
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+
+/* These constants define the different elf file types */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+
+/* These constants define the various ELF target machines */
+#define EM_NONE 0
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC64 */
+
+#define EI_NIDENT 16
+
+typedef struct elf32_hdr {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry; /* Entry point */
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct elf64_hdr {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ Elf64_Half e_type;
+ Elf64_Half e_machine;
+ Elf64_Word e_version;
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags;
+ Elf64_Half e_ehsize;
+ Elf64_Half e_phentsize;
+ Elf64_Half e_phnum;
+ Elf64_Half e_shentsize;
+ Elf64_Half e_shnum;
+ Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+
+/* These constants define the permissions on sections in the program
+ header, p_flags. */
+#define PF_R 0x4
+#define PF_W 0x2
+#define PF_X 0x1
+
+typedef struct elf32_phdr {
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf64_phdr {
+ Elf64_Word p_type;
+ Elf64_Word p_flags;
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment, file & memory */
+} Elf64_Phdr;
+
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_OSABI 7
+#define EI_PAD 8
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define ELFCLASSNONE 0 /* EI_CLASS */
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define ELFDATANONE 0 /* e_ident[EI_DATA] */
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_NONE 0 /* e_version, EI_VERSION */
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+#define ELFOSABI_NONE 0
+#define ELFOSABI_LINUX 3
+
+#endif /* _PPC_BOOT_ELF_H_ */
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index 199d9804f61c..f7ec19a2d0b0 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -8,38 +8,32 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include "ppc32-types.h"
+#include <stdarg.h>
+#include <stddef.h>
+#include "elf.h"
+#include "page.h"
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
#include "zlib.h"
-#include <linux/elf.h>
-#include <linux/string.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-
-extern void *finddevice(const char *);
-extern int getprop(void *, const char *, void *, int);
-extern void printf(const char *fmt, ...);
-extern int sprintf(char *buf, const char *fmt, ...);
-void gunzip(void *, int, unsigned char *, int *);
-void *claim(unsigned int, unsigned int, unsigned int);
-void flush_cache(void *, unsigned long);
-void pause(void);
-extern void exit(void);
-
-unsigned long strlen(const char *s);
-void *memmove(void *dest, const void *src, unsigned long n);
-void *memcpy(void *dest, const void *src, unsigned long n);
+
+static void gunzip(void *, int, unsigned char *, int *);
+extern void flush_cache(void *, unsigned long);
+
/* Value picked to match that used by yaboot */
#define PROG_START 0x01400000
-#define RAM_END (256<<20) // Fixme: use OF */
+#define RAM_END (512<<20) // Fixme: use OF */
+#define ONE_MB 0x100000
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-unsigned int heap_use;
-unsigned int heap_max;
+static char *avail_ram;
+static char *begin_avail, *end_avail;
+static char *avail_high;
+static unsigned int heap_use;
+static unsigned int heap_max;
extern char _start[];
+extern char _end[];
extern char _vmlinux_start[];
extern char _vmlinux_end[];
extern char _initrd_start[];
@@ -52,9 +46,9 @@ struct addr_range {
unsigned long size;
unsigned long memsize;
};
-struct addr_range vmlinux = {0, 0, 0};
-struct addr_range vmlinuz = {0, 0, 0};
-struct addr_range initrd = {0, 0, 0};
+static struct addr_range vmlinux = {0, 0, 0};
+static struct addr_range vmlinuz = {0, 0, 0};
+static struct addr_range initrd = {0, 0, 0};
static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
@@ -64,22 +58,15 @@ typedef void (*kernel_entry_t)( unsigned long,
void *);
-int (*prom)(void *);
-
-void *chosen_handle;
-void *stdin;
-void *stdout;
-void *stderr;
-
#undef DEBUG
-static unsigned long claim_base = PROG_START;
+static unsigned long claim_base;
static unsigned long try_claim(unsigned long size)
{
unsigned long addr = 0;
- for(; claim_base < RAM_END; claim_base += 0x100000) {
+ for(; claim_base < RAM_END; claim_base += ONE_MB) {
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_base);
#endif
@@ -110,7 +97,26 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
exit();
- printf("\n\rzImage starting: loaded at 0x%x\n\r", (unsigned)_start);
+ printf("\n\rzImage starting: loaded at 0x%lx\n\r", (unsigned long) _start);
+
+ /*
+ * The first available claim_base must be above the end of the
+ * the loaded kernel wrapper file (_start to _end includes the
+ * initrd image if it is present) and rounded up to a nice
+ * 1 MB boundary for good measure.
+ */
+
+ claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+
+#if defined(PROG_START)
+ /*
+ * Maintain a "magic" minimum address. This keeps some older
+ * firmware platforms running.
+ */
+
+ if (claim_base < PROG_START)
+ claim_base = PROG_START;
+#endif
/*
* Now we try to claim some memory for the kernel itself
@@ -120,7 +126,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
* size... In practice we add 1Mb, that is enough, but we should really
* consider fixing the Makefile to put a _raw_ kernel in there !
*/
- vmlinux_memsize += 0x100000;
+ vmlinux_memsize += ONE_MB;
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
vmlinux.addr = try_claim(vmlinux_memsize);
if (vmlinux.addr == 0) {
@@ -277,7 +283,7 @@ void zfree(void *x, void *addr, unsigned nb)
#define DEFLATED 8
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
{
z_stream s;
int r, i, flags;
diff --git a/arch/ppc64/boot/page.h b/arch/ppc64/boot/page.h
new file mode 100644
index 000000000000..14eca30fef64
--- /dev/null
+++ b/arch/ppc64/boot/page.h
@@ -0,0 +1,34 @@
+#ifndef _PPC_BOOT_PAGE_H
+#define _PPC_BOOT_PAGE_H
+/*
+ * Copyright (C) 2001 PPC64 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.
+ */
+
+#ifdef __ASSEMBLY__
+#define ASM_CONST(x) x
+#else
+#define __ASM_CONST(x) x##UL
+#define ASM_CONST(x) __ASM_CONST(x)
+#endif
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+/* align addr on a size boundary - adjust address up/down if needed */
+#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
+#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
+
+/* align addr on a size boundary - adjust address up if needed */
+#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
+
+#endif /* _PPC_BOOT_PAGE_H */
diff --git a/arch/ppc64/boot/ppc32-types.h b/arch/ppc64/boot/ppc32-types.h
deleted file mode 100644
index f7b8884f8f70..000000000000
--- a/arch/ppc64/boot/ppc32-types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _PPC64_TYPES_H
-#define _PPC64_TYPES_H
-
-typedef __signed__ char __s8;
-typedef unsigned char __u8;
-
-typedef __signed__ short __s16;
-typedef unsigned short __u16;
-
-typedef __signed__ int __s32;
-typedef unsigned int __u32;
-
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-
-typedef signed char s8;
-typedef unsigned char u8;
-
-typedef signed short s16;
-typedef unsigned short u16;
-
-typedef signed int s32;
-typedef unsigned int u32;
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-
-typedef struct {
- __u32 u[4];
-} __attribute((aligned(16))) __vector128;
-
-#define BITS_PER_LONG 32
-
-typedef __vector128 vector128;
-
-#endif /* _PPC64_TYPES_H */
diff --git a/arch/ppc64/boot/ppc_asm.h b/arch/ppc64/boot/ppc_asm.h
new file mode 100644
index 000000000000..1c2c2817f9b7
--- /dev/null
+++ b/arch/ppc64/boot/ppc_asm.h
@@ -0,0 +1,62 @@
+#ifndef _PPC64_PPC_ASM_H
+#define _PPC64_PPC_ASM_H
+/*
+ *
+ * Definitions used by various bits of low-level assembly code on PowerPC.
+ *
+ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+#endif /* _PPC64_PPC_ASM_H */
diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c
index 5e48b80ff5a0..4bea2f4dcb06 100644
--- a/arch/ppc64/boot/prom.c
+++ b/arch/ppc64/boot/prom.c
@@ -7,43 +7,19 @@
* 2 of the License, or (at your option) any later version.
*/
#include <stdarg.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-
-extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);
-
-/* The unnecessary pointer compare is there
- * to check for type safety (n must be 64bit)
- */
-# define do_div(n,base) ({ \
- __u32 __base = (base); \
- __u32 __rem; \
- (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
- if (((n) >> 32) == 0) { \
- __rem = (__u32)(n) % __base; \
- (n) = (__u32)(n) / __base; \
- } else \
- __rem = __div64_32(&(n), __base); \
- __rem; \
- })
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
int (*prom)(void *);
void *chosen_handle;
+
void *stdin;
void *stdout;
void *stderr;
-void exit(void);
-void *finddevice(const char *name);
-int getprop(void *phandle, const char *name, void *buf, int buflen);
-void chrpboot(int a1, int a2, void *prom); /* in main.c */
-
-int printf(char *fmt, ...);
-
-/* there is no convenient header to get this from... -- paulus */
-extern unsigned long strlen(const char *);
int
write(void *handle, void *ptr, int nb)
@@ -210,107 +186,6 @@ fputs(char *str, void *f)
return write(f, str, n) == n? 0: -1;
}
-int
-readchar(void)
-{
- char ch;
-
- for (;;) {
- switch (read(stdin, &ch, 1)) {
- case 1:
- return ch;
- case -1:
- printf("read(stdin) returned -1\r\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++;
-}
-
-
-
-/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
-unsigned char _ctype[] = {
-_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
-_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
-_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
-_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
-_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
-_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
-
size_t strnlen(const char * s, size_t count)
{
const char *sc;
@@ -320,44 +195,30 @@ size_t strnlen(const char * s, size_t count)
return sc - s;
}
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
- unsigned long result = 0,value;
+extern unsigned int __div64_32(unsigned long long *dividend,
+ unsigned int divisor);
- if (!base) {
- base = 10;
- if (*cp == '0') {
- base = 8;
- cp++;
- if ((*cp == 'x') && isxdigit(cp[1])) {
- cp++;
- base = 16;
- }
- }
- }
- while (isxdigit(*cp) &&
- (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
- result = result*base + value;
- cp++;
- }
- if (endp)
- *endp = (char *)cp;
- return result;
-}
-
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
- if(*cp=='-')
- return -simple_strtoul(cp+1,endp,base);
- return simple_strtoul(cp,endp,base);
-}
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({ \
+ unsigned int __base = (base); \
+ unsigned int __rem; \
+ (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
+ if (((n) >> 32) == 0) { \
+ __rem = (unsigned int)(n) % __base; \
+ (n) = (unsigned int)(n) / __base; \
+ } else \
+ __rem = __div64_32(&(n), __base); \
+ __rem; \
+ })
static int skip_atoi(const char **s)
{
- int i=0;
+ int i, c;
- while (isdigit(**s))
- i = i*10 + *((*s)++) - '0';
+ for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
+ i = i*10 + c - '0';
return i;
}
@@ -436,9 +297,6 @@ static char * number(char * str, unsigned long long num, int base, int size, int
return str;
}
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char * buf, const char *fmt, ...);
-
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
@@ -477,7 +335,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
/* get field width */
field_width = -1;
- if (isdigit(*fmt))
+ if ('0' <= *fmt && *fmt <= '9')
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
@@ -493,7 +351,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
precision = -1;
if (*fmt == '.') {
++fmt;
- if (isdigit(*fmt))
+ if ('0' <= *fmt && *fmt <= '9')
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
@@ -628,7 +486,7 @@ int sprintf(char * buf, const char *fmt, ...)
static char sprint_buf[1024];
int
-printf(char *fmt, ...)
+printf(const char *fmt, ...)
{
va_list args;
int n;
diff --git a/arch/ppc64/boot/prom.h b/arch/ppc64/boot/prom.h
new file mode 100644
index 000000000000..96ab5aec740c
--- /dev/null
+++ b/arch/ppc64/boot/prom.h
@@ -0,0 +1,18 @@
+#ifndef _PPC_BOOT_PROM_H_
+#define _PPC_BOOT_PROM_H_
+
+extern int (*prom) (void *);
+extern void *chosen_handle;
+
+extern void *stdin;
+extern void *stdout;
+extern void *stderr;
+
+extern int write(void *handle, void *ptr, int nb);
+extern int read(void *handle, void *ptr, int nb);
+extern void exit(void);
+extern void pause(void);
+extern void *finddevice(const char *);
+extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
+extern int getprop(void *phandle, const char *name, void *buf, int buflen);
+#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/ppc64/boot/stdio.h b/arch/ppc64/boot/stdio.h
new file mode 100644
index 000000000000..24bd3a8dee94
--- /dev/null
+++ b/arch/ppc64/boot/stdio.h
@@ -0,0 +1,16 @@
+#ifndef _PPC_BOOT_STDIO_H_
+#define _PPC_BOOT_STDIO_H_
+
+extern int printf(const char *fmt, ...);
+
+extern int sprintf(char *buf, const char *fmt, ...);
+
+extern int vsprintf(char *buf, const char *fmt, va_list args);
+
+extern int putc(int c, void *f);
+extern int putchar(int c);
+extern int getchar(void);
+
+extern int fputs(char *str, void *f);
+
+#endif /* _PPC_BOOT_STDIO_H_ */
diff --git a/arch/ppc64/boot/string.S b/arch/ppc64/boot/string.S
index ba5f2d21c9ea..7ade87ae7718 100644
--- a/arch/ppc64/boot/string.S
+++ b/arch/ppc64/boot/string.S
@@ -9,7 +9,7 @@
* NOTE: this code runs in 32 bit mode and is packaged as ELF32.
*/
-#include <asm/ppc_asm.h>
+#include "ppc_asm.h"
.text
.globl strcpy
diff --git a/arch/ppc64/boot/string.h b/arch/ppc64/boot/string.h
new file mode 100644
index 000000000000..9289258bcbd6
--- /dev/null
+++ b/arch/ppc64/boot/string.h
@@ -0,0 +1,16 @@
+#ifndef _PPC_BOOT_STRING_H_
+#define _PPC_BOOT_STRING_H_
+
+extern char *strcpy(char *dest, const char *src);
+extern char *strncpy(char *dest, const char *src, size_t n);
+extern char *strcat(char *dest, const char *src);
+extern int strcmp(const char *s1, const char *s2);
+extern size_t strlen(const char *s);
+extern size_t strnlen(const char *s, size_t count);
+
+extern void *memset(void *s, int c, size_t n);
+extern void *memmove(void *dest, const void *src, unsigned long n);
+extern void *memcpy(void *dest, const void *src, unsigned long n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+
+#endif /* _PPC_BOOT_STRING_H_ */
diff --git a/arch/ppc64/boot/zlib.c b/arch/ppc64/boot/zlib.c
index 78837e884b8b..0d910cd2079d 100644
--- a/arch/ppc64/boot/zlib.c
+++ b/arch/ppc64/boot/zlib.c
@@ -107,7 +107,7 @@ extern void *memcpy(void *, const void *, unsigned long);
/* Diagnostic functions */
#ifdef DEBUG_ZLIB
-# include <stdio.h>
+# include "stdio.h"
# ifndef verbose
# define verbose 0
# endif
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index ab567741e80e..fc83d9330282 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -103,10 +103,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
CONFIG_GENERIC_HARDIRQS=y
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index 394ba18b58c7..013d4e0e4003 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -94,12 +94,11 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
CONFIG_GENERIC_HARDIRQS=y
-CONFIG_MSCHUNKS=y
CONFIG_LPARCFG=y
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
index 2033fe663dbe..dd42892cd873 100644
--- a/arch/ppc64/configs/maple_defconfig
+++ b/arch/ppc64/configs/maple_defconfig
@@ -103,10 +103,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
CONFIG_GENERIC_HARDIRQS=y
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index 297fd5229487..29f7b80b0efc 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -112,10 +112,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
CONFIG_EEH=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
index c361e7727b7a..7cb4750bb7a9 100644
--- a/arch/ppc64/defconfig
+++ b/arch/ppc64/defconfig
@@ -114,10 +114,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
CONFIG_EEH=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 1c11031c838e..0a9c23ca2f0c 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -51,6 +51,17 @@ struct HvReleaseData hvReleaseData = {
0xf4, 0x4b, 0xf6, 0xf4 },
};
+/*
+ * The NACA. The first dword of the naca is required by the iSeries
+ * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
+ * through the pointer in hvReleaseData.
+ */
+struct naca_struct naca = {
+ .xItVpdAreas = &itVpdAreas,
+ .xRamDisk = 0,
+ .xRamDiskSize = 0,
+};
+
extern void system_reset_iSeries(void);
extern void machine_check_iSeries(void);
extern void data_access_iSeries(void);
@@ -214,29 +225,3 @@ struct ItVpdAreas itVpdAreas = {
0,0
}
};
-
-struct msChunks msChunks;
-EXPORT_SYMBOL(msChunks);
-
-/* Depending on whether this is called from iSeries or pSeries setup
- * code, the location of the msChunks struct may or may not have
- * to be reloc'd, so we force the caller to do that for us by passing
- * in a pointer to the structure.
- */
-unsigned long
-msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)
-{
- unsigned long offset = reloc_offset();
- struct msChunks *_msChunks = PTRRELOC(&msChunks);
-
- _msChunks->num_chunks = num_chunks;
- _msChunks->chunk_size = chunk_size;
- _msChunks->chunk_shift = __ilog2(chunk_size);
- _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;
-
- mem = _ALIGN(mem, sizeof(msChunks_entry));
- _msChunks->abs = (msChunks_entry *)(mem + offset);
- mem += num_chunks * sizeof(msChunks_entry);
-
- return mem;
-}
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 2ecccb6b4f8c..ae60eb1193c6 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
ptrace32.o signal32.o rtc.o init_task.o \
lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
- iommu.o sysfs.o vdso.o pmc.o
+ iommu.o sysfs.o vdso.o pmc.o firmware.o
obj-y += vdso32/ vdso64/
obj-$(CONFIG_PPC_OF) += of_device.o
@@ -31,7 +31,7 @@ obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
- pSeries_setup.o pSeries_iommu.o
+ pSeries_setup.o pSeries_iommu.o udbg_16550.o
obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
bpa_iic.o spider-pic.o
@@ -50,14 +50,19 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o
-obj-$(CONFIG_IBMVIO) += vio.o
+
+vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o
+vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o
+obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y)
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_MPIC) += mpic.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
- pmac_time.o pmac_nvram.o pmac_low_i2c.o
+ pmac_time.o pmac_nvram.o pmac_low_i2c.o \
+ udbg_scc.o
-obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o
+obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \
+ udbg_16550.o
obj-$(CONFIG_U3_DART) += u3_iommu.o
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 6f910fa2746f..1ff4fa05a973 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -95,7 +95,8 @@ int main(void)
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
#ifdef CONFIG_HUGETLB_PAGE
- DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs));
+ DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
+ DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
#endif /* CONFIG_HUGETLB_PAGE */
DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c
index c8f3dc3fad70..0aaa878e19d3 100644
--- a/arch/ppc64/kernel/bpa_iic.c
+++ b/arch/ppc64/kernel/bpa_iic.c
@@ -205,6 +205,18 @@ static struct iic_regs __iomem *find_iic(int cpu)
}
#ifdef CONFIG_SMP
+
+/* Use the highest interrupt priorities for IPI */
+static inline int iic_ipi_to_irq(int ipi)
+{
+ return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi;
+}
+
+static inline int iic_irq_to_ipi(int irq)
+{
+ return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET);
+}
+
void iic_setup_cpu(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
@@ -212,18 +224,20 @@ void iic_setup_cpu(void)
void iic_cause_IPI(int cpu, int mesg)
{
- out_be64(&per_cpu(iic, cpu).regs->generate, mesg);
+ out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
}
static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
-
- smp_message_recv(irq - IIC_IPI_OFFSET, regs);
+ smp_message_recv(iic_irq_to_ipi(irq), regs);
return IRQ_HANDLED;
}
-static void iic_request_ipi(int irq, const char *name)
+static void iic_request_ipi(int ipi, const char *name)
{
+ int irq;
+
+ irq = iic_ipi_to_irq(ipi);
/* IPIs are marked SA_INTERRUPT as they must run with irqs
* disabled */
get_irq_desc(irq)->handler = &iic_pic;
@@ -233,10 +247,10 @@ static void iic_request_ipi(int irq, const char *name)
void iic_request_IPIs(void)
{
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");
+ iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
+ iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
#ifdef CONFIG_DEBUGGER
- iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
+ iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
#endif /* CONFIG_DEBUGGER */
}
#endif /* CONFIG_SMP */
diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c
index c53f079e9b77..b6fbfbe9032d 100644
--- a/arch/ppc64/kernel/btext.c
+++ b/arch/ppc64/kernel/btext.c
@@ -7,7 +7,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <asm/sections.h>
#include <asm/prom.h>
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S
index 0482c063c26e..1fb673c511ff 100644
--- a/arch/ppc64/kernel/cpu_setup_power4.S
+++ b/arch/ppc64/kernel/cpu_setup_power4.S
@@ -12,10 +12,9 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
-#include <asm/ppc_asm.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cache.h>
_GLOBAL(__970_cpu_preinit)
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 77cec42f9525..8831a28c3c4e 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -5,7 +5,7 @@
*
* Modifications for ppc64:
* Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
- *
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/module.h>
+#include <asm/oprofile_impl.h>
#include <asm/cputable.h>
struct cpu_spec* cur_cpu_spec = NULL;
@@ -54,26 +55,32 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00400000,
.cpu_name = "POWER3 (630)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8,
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power3",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* Power3+ */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00410000,
.cpu_name = "POWER3 (630+)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8,
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power3",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* Northstar */
.pvr_mask = 0xffff0000,
@@ -81,12 +88,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "RS64-II (northstar)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ CPU_FTR_MMCRA | CPU_FTR_CTRL,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/rs64",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* Pulsar */
.pvr_mask = 0xffff0000,
@@ -94,12 +105,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "RS64-III (pulsar)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ CPU_FTR_MMCRA | CPU_FTR_CTRL,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/rs64",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* I-star */
.pvr_mask = 0xffff0000,
@@ -107,12 +122,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "RS64-III (icestar)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ CPU_FTR_MMCRA | CPU_FTR_CTRL,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/rs64",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* S-star */
.pvr_mask = 0xffff0000,
@@ -120,12 +139,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "RS64-IV (sstar)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+ CPU_FTR_MMCRA | CPU_FTR_CTRL,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/rs64",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* Power4 */
.pvr_mask = 0xffff0000,
@@ -133,12 +156,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "POWER4 (gp)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power4,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power4",
+ .oprofile_model = &op_model_rs64,
+#endif
},
{ /* Power4+ */
.pvr_mask = 0xffff0000,
@@ -146,12 +173,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "POWER4+ (gq)",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_power4,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power4",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* PPC970 */
.pvr_mask = 0xffff0000,
@@ -160,13 +191,17 @@ struct cpu_spec cpu_specs[] = {
.cpu_features = 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_PMC8 | CPU_FTR_MMCRA,
+ CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
.cpu_user_features = COMMON_USER_PPC64 |
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/970",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* PPC970FX */
.pvr_mask = 0xffff0000,
@@ -175,13 +210,17 @@ struct cpu_spec cpu_specs[] = {
.cpu_features = 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_PMC8 | CPU_FTR_MMCRA,
+ CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
.cpu_user_features = COMMON_USER_PPC64 |
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/970",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* PPC970MP */
.pvr_mask = 0xffff0000,
@@ -190,13 +229,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_features = 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_PMC8 | CPU_FTR_MMCRA,
+ CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
.cpu_user_features = COMMON_USER_PPC64 |
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
.dcache_bsize = 128,
.cpu_setup = __setup_cpu_ppc970,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/970",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* Power5 */
.pvr_mask = 0xffff0000,
@@ -210,8 +252,12 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power5",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* Power5 */
.pvr_mask = 0xffff0000,
@@ -225,8 +271,12 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
- .firmware_features = COMMON_PPC64_FW,
+#ifdef CONFIG_OPROFILE
+ .oprofile_cpu_type = "ppc64/power5",
+ .oprofile_model = &op_model_power4,
+#endif
},
{ /* BE DD1.x */
.pvr_mask = 0xffff0000,
@@ -241,7 +291,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.cpu_setup = __setup_cpu_be,
- .firmware_features = COMMON_PPC64_FW,
},
{ /* default match */
.pvr_mask = 0x00000000,
@@ -253,30 +302,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_PPC64,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
- .firmware_features = COMMON_PPC64_FW,
}
};
-
-firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
- {FW_FEATURE_PFT, "hcall-pft"},
- {FW_FEATURE_TCE, "hcall-tce"},
- {FW_FEATURE_SPRG0, "hcall-sprg0"},
- {FW_FEATURE_DABR, "hcall-dabr"},
- {FW_FEATURE_COPY, "hcall-copy"},
- {FW_FEATURE_ASR, "hcall-asr"},
- {FW_FEATURE_DEBUG, "hcall-debug"},
- {FW_FEATURE_PERF, "hcall-perf"},
- {FW_FEATURE_DUMP, "hcall-dump"},
- {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
- {FW_FEATURE_MIGRATE, "hcall-migrate"},
- {FW_FEATURE_PERFMON, "hcall-perfmon"},
- {FW_FEATURE_CRQ, "hcall-crq"},
- {FW_FEATURE_VIO, "hcall-vio"},
- {FW_FEATURE_RDMA, "hcall-rdma"},
- {FW_FEATURE_LLAN, "hcall-lLAN"},
- {FW_FEATURE_BULK, "hcall-bulk"},
- {FW_FEATURE_XDABR, "hcall-xdabr"},
- {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
- {FW_FEATURE_SPLPAR, "hcall-splpar"},
-};
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index af5272fedadf..ba93fd731222 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -202,10 +202,9 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
while (n) {
struct pci_io_addr_range *piar;
piar = rb_entry(n, struct pci_io_addr_range, rb_node);
- printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s %s\n",
+ printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n",
(piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
- piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev),
- pci_pretty_name(piar->pcidev));
+ piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
cnt++;
n = rb_next(n);
}
@@ -255,22 +254,24 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
static void __pci_addr_cache_insert_device(struct pci_dev *dev)
{
struct device_node *dn;
+ struct pci_dn *pdn;
int i;
int inserted = 0;
dn = pci_device_to_OF_node(dev);
if (!dn) {
- printk(KERN_WARNING "PCI: no pci dn found for dev=%s %s\n",
- pci_name(dev), pci_pretty_name(dev));
+ printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n",
+ pci_name(dev));
return;
}
/* Skip any devices for which EEH is not enabled. */
- if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
- dn->eeh_mode & EEH_MODE_NOCHECK) {
+ pdn = dn->data;
+ if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ pdn->eeh_mode & EEH_MODE_NOCHECK) {
#ifdef DEBUG
- printk(KERN_INFO "PCI: skip building address cache for=%s %s\n",
- pci_name(dev), pci_pretty_name(dev));
+ printk(KERN_INFO "PCI: skip building address cache for=%s\n",
+ pci_name(dev));
#endif
return;
}
@@ -416,6 +417,7 @@ int eeh_unregister_notifier(struct notifier_block *nb)
static int read_slot_reset_state(struct device_node *dn, int rets[])
{
int token, outputs;
+ struct pci_dn *pdn = dn->data;
if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
token = ibm_read_slot_reset_state2;
@@ -425,8 +427,8 @@ static int read_slot_reset_state(struct device_node *dn, int rets[])
outputs = 3;
}
- return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr,
- BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
+ return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
}
/**
@@ -447,12 +449,12 @@ static void eeh_panic(struct pci_dev *dev, int reset_state)
* in light of potential corruption, we can use it here.
*/
if (panic_on_oops)
- panic("EEH: MMIO failure (%d) on device:%s %s\n", reset_state,
- pci_name(dev), pci_pretty_name(dev));
+ panic("EEH: MMIO failure (%d) on device:%s\n", reset_state,
+ pci_name(dev));
else {
__get_cpu_var(ignored_failures)++;
- printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s %s\n",
- reset_state, pci_name(dev), pci_pretty_name(dev));
+ printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n",
+ reset_state, pci_name(dev));
}
}
@@ -482,8 +484,8 @@ static void eeh_event_handler(void *dummy)
break;
printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device "
- "%s %s\n", event->reset_state,
- pci_name(event->dev), pci_pretty_name(event->dev));
+ "%s\n", event->reset_state,
+ pci_name(event->dev));
atomic_set(&eeh_fail_count, 0);
notifier_call_chain (&eeh_notifier_chain,
@@ -535,6 +537,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
unsigned long flags;
int rc, reset_state;
struct eeh_event *event;
+ struct pci_dn *pdn;
__get_cpu_var(total_mmio_ffs)++;
@@ -543,14 +546,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
if (!dn)
return 0;
+ pdn = dn->data;
/* Access to IO BARs might get this far and still not want checking. */
- if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
- dn->eeh_mode & EEH_MODE_NOCHECK) {
+ if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ pdn->eeh_mode & EEH_MODE_NOCHECK) {
return 0;
}
- if (!dn->eeh_config_addr) {
+ if (!pdn->eeh_config_addr) {
return 0;
}
@@ -558,7 +562,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
* If we already have a pending isolation event for this
* slot, we know it's bad already, we don't need to check...
*/
- if (dn->eeh_mode & EEH_MODE_ISOLATED) {
+ if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
atomic_inc(&eeh_fail_count);
if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) {
/* re-read the slot reset state */
@@ -583,7 +587,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
}
/* prevent repeated reports of this failure */
- dn->eeh_mode |= EEH_MODE_ISOLATED;
+ pdn->eeh_mode |= EEH_MODE_ISOLATED;
reset_state = rets[0];
@@ -591,9 +595,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
memset(slot_errbuf, 0, eeh_error_buf_size);
rc = rtas_call(ibm_slot_error_detail,
- 8, 1, NULL, dn->eeh_config_addr,
- BUID_HI(dn->phb->buid),
- BUID_LO(dn->phb->buid), NULL, 0,
+ 8, 1, NULL, pdn->eeh_config_addr,
+ BUID_HI(pdn->phb->buid),
+ BUID_LO(pdn->phb->buid), NULL, 0,
virt_to_phys(slot_errbuf),
eeh_error_buf_size,
1 /* Temporary Error */);
@@ -680,8 +684,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
u32 *device_id = (u32 *)get_property(dn, "device-id", NULL);
u32 *regs;
int enable;
+ struct pci_dn *pdn = dn->data;
- dn->eeh_mode = 0;
+ pdn->eeh_mode = 0;
if (status && strcmp(status, "ok") != 0)
return NULL; /* ignore devices with bad status */
@@ -692,7 +697,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* There is nothing to check on PCI to ISA bridges */
if (dn->type && !strcmp(dn->type, "isa")) {
- dn->eeh_mode |= EEH_MODE_NOCHECK;
+ pdn->eeh_mode |= EEH_MODE_NOCHECK;
return NULL;
}
@@ -709,7 +714,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
enable = 0;
if (!enable)
- dn->eeh_mode |= EEH_MODE_NOCHECK;
+ pdn->eeh_mode |= EEH_MODE_NOCHECK;
/* Ok... see if this device supports EEH. Some do, some don't,
* and the only way to find out is to check each and every one. */
@@ -722,8 +727,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
EEH_ENABLE);
if (ret == 0) {
eeh_subsystem_enabled = 1;
- dn->eeh_mode |= EEH_MODE_SUPPORTED;
- dn->eeh_config_addr = regs[0];
+ pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+ pdn->eeh_config_addr = regs[0];
#ifdef DEBUG
printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name);
#endif
@@ -731,10 +736,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* This device doesn't support EEH, but it may have an
* EEH parent, in which case we mark it as supported. */
- if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
+ if (dn->parent && dn->parent->data
+ && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
/* Parent supports EEH. */
- dn->eeh_mode |= EEH_MODE_SUPPORTED;
- dn->eeh_config_addr = dn->parent->eeh_config_addr;
+ pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+ pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr;
return NULL;
}
}
@@ -791,11 +797,13 @@ void __init eeh_init(void)
for (phb = of_find_node_by_name(NULL, "pci"); phb;
phb = of_find_node_by_name(phb, "pci")) {
unsigned long buid;
+ struct pci_dn *pci;
buid = get_phb_buid(phb);
- if (buid == 0)
+ if (buid == 0 || phb->data == NULL)
continue;
+ pci = phb->data;
info.buid_lo = BUID_LO(buid);
info.buid_hi = BUID_HI(buid);
traverse_pci_devices(phb, early_enable_eeh, &info);
@@ -824,9 +832,9 @@ void eeh_add_device_early(struct device_node *dn)
struct pci_controller *phb;
struct eeh_early_enable_info info;
- if (!dn)
+ if (!dn || !dn->data)
return;
- phb = dn->phb;
+ phb = PCI_DN(dn)->phb;
if (NULL == phb || 0 == phb->buid) {
printk(KERN_WARNING "EEH: Expected buid but found none\n");
return;
@@ -851,8 +859,7 @@ void eeh_add_device_late(struct pci_dev *dev)
return;
#ifdef DEBUG
- printk(KERN_DEBUG "EEH: adding device %s %s\n", pci_name(dev),
- pci_pretty_name(dev));
+ printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
#endif
pci_addr_cache_insert_device (dev);
@@ -873,8 +880,7 @@ void eeh_remove_device(struct pci_dev *dev)
/* Unregister the device with the EEH/PCI address search system */
#ifdef DEBUG
- printk(KERN_DEBUG "EEH: remove device %s %s\n", pci_name(dev),
- pci_pretty_name(dev));
+ printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
#endif
pci_addr_cache_remove_device(dev);
}
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index 14cd56ac40dd..e8c0bbf4d000 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -28,7 +28,7 @@
#include <asm/mmu.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cputable.h>
#ifdef CONFIG_PPC_ISERIES
@@ -410,15 +410,14 @@ BEGIN_FTR_SECTION
cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */
cror eq,4*cr1+eq,eq
beq 2f /* if yes, don't slbie it */
- oris r0,r6,0x0800 /* set C (class) bit */
/* Bolt in the new stack SLB entry */
ld r7,KSP_VSID(r4) /* Get new stack's VSID */
- oris r6,r6,(SLB_ESID_V)@h
- ori r6,r6,(SLB_NUM_BOLTED-1)@l
- slbie r0
- slbie r0 /* Workaround POWER5 < DD2.1 issue */
- slbmte r7,r6
+ oris r0,r6,(SLB_ESID_V)@h
+ ori r0,r0,(SLB_NUM_BOLTED-1)@l
+ slbie r6
+ slbie r6 /* Workaround POWER5 < DD2.1 issue */
+ slbmte r7,r0
isync
2:
diff --git a/arch/ppc64/kernel/firmware.c b/arch/ppc64/kernel/firmware.c
new file mode 100644
index 000000000000..d8432c0fb27d
--- /dev/null
+++ b/arch/ppc64/kernel/firmware.c
@@ -0,0 +1,47 @@
+/*
+ * arch/ppc64/kernel/firmware.c
+ *
+ * Extracted from cputable.c
+ *
+ * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * Modifications for ppc64:
+ * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
+ * Copyright (C) 2005 Stephen Rothwell, 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.
+ */
+
+#include <linux/config.h>
+
+#include <asm/firmware.h>
+
+unsigned long ppc64_firmware_features;
+
+#ifdef CONFIG_PPC_PSERIES
+firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
+ {FW_FEATURE_PFT, "hcall-pft"},
+ {FW_FEATURE_TCE, "hcall-tce"},
+ {FW_FEATURE_SPRG0, "hcall-sprg0"},
+ {FW_FEATURE_DABR, "hcall-dabr"},
+ {FW_FEATURE_COPY, "hcall-copy"},
+ {FW_FEATURE_ASR, "hcall-asr"},
+ {FW_FEATURE_DEBUG, "hcall-debug"},
+ {FW_FEATURE_PERF, "hcall-perf"},
+ {FW_FEATURE_DUMP, "hcall-dump"},
+ {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
+ {FW_FEATURE_MIGRATE, "hcall-migrate"},
+ {FW_FEATURE_PERFMON, "hcall-perfmon"},
+ {FW_FEATURE_CRQ, "hcall-crq"},
+ {FW_FEATURE_VIO, "hcall-vio"},
+ {FW_FEATURE_RDMA, "hcall-rdma"},
+ {FW_FEATURE_LLAN, "hcall-lLAN"},
+ {FW_FEATURE_BULK, "hcall-bulk"},
+ {FW_FEATURE_XDABR, "hcall-xdabr"},
+ {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
+ {FW_FEATURE_SPLPAR, "hcall-splpar"},
+};
+#endif
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index accaa052d31f..58c314738c99 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -23,17 +23,14 @@
* 2 of the License, or (at your option) any later version.
*/
-#define SECONDARY_PROCESSORS
-
#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
-#include <asm/naca.h>
#include <asm/systemcfg.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/bug.h>
#include <asm/cputable.h>
#include <asm/setup.h>
@@ -45,18 +42,13 @@
#endif
/*
- * hcall interface to pSeries LPAR
- */
-#define H_SET_ASR 0x30
-
-/*
* We layout physical memory as follows:
* 0x0000 - 0x00ff : Secondary processor spin code
* 0x0100 - 0x2fff : pSeries Interrupt prologs
- * 0x3000 - 0x3fff : Interrupt support
- * 0x4000 - 0x4fff : NACA
- * 0x6000 : iSeries and common interrupt prologs
- * 0x9000 - 0x9fff : Initial segment table
+ * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
+ * 0x6000 - 0x6fff : Initial (CPU0) segment table
+ * 0x7000 - 0x7fff : FWNMI data area
+ * 0x8000 - : Early init and support code
*/
/*
@@ -94,6 +86,7 @@ END_FTR_SECTION(0, 1)
/* Catch branch to 0 in real mode */
trap
+
#ifdef CONFIG_PPC_ISERIES
/*
* At offset 0x20, there is a pointer to iSeries LPAR data.
@@ -103,12 +96,12 @@ END_FTR_SECTION(0, 1)
.llong hvReleaseData-KERNELBASE
/*
- * At offset 0x28 and 0x30 are offsets to the msChunks
+ * At offset 0x28 and 0x30 are offsets to the mschunks_map
* array (used by the iSeries LPAR debugger to do translation
* between physical addresses and absolute addresses) and
* to the pidhash table (also used by the debugger)
*/
- .llong msChunks-KERNELBASE
+ .llong mschunks_map-KERNELBASE
.llong 0 /* pidhash-KERNELBASE SFRXXX */
/* Offset 0x38 - Pointer to start of embedded System.map */
@@ -120,7 +113,7 @@ embedded_sysmap_start:
embedded_sysmap_end:
.llong 0
-#else /* CONFIG_PPC_ISERIES */
+#endif /* CONFIG_PPC_ISERIES */
/* Secondary processors spin on this value until it goes to 1. */
.globl __secondary_hold_spinloop
@@ -155,7 +148,7 @@ _GLOBAL(__secondary_hold)
std r24,__secondary_hold_acknowledge@l(0)
sync
- /* All secondary cpu's wait here until told to start. */
+ /* All secondary cpus wait here until told to start. */
100: ld r4,__secondary_hold_spinloop@l(0)
cmpdi 0,r4,1
bne 100b
@@ -170,7 +163,6 @@ _GLOBAL(__secondary_hold)
BUG_OPCODE
#endif
#endif
-#endif
/* This value is used to mark exception frames on the stack. */
.section ".toc","aw"
@@ -502,33 +494,37 @@ system_call_pSeries:
STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
+ . = 0x3000
+
+/*** pSeries interrupt support ***/
+
/* moved from 0xf00 */
- STD_EXCEPTION_PSERIES(0x3000, performance_monitor)
+ STD_EXCEPTION_PSERIES(., performance_monitor)
- . = 0x3100
+ .align 7
_GLOBAL(do_stab_bolted_pSeries)
mtcrf 0x80,r12
mfspr r12,SPRG2
EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
-
- /* Space for the naca. Architected to be located at real address
- * NACA_PHYS_ADDR. Various tools rely on this location being fixed.
- * The first dword of the naca is required by iSeries LPAR to
- * point to itVpdAreas. On pSeries native, this value is not used.
- */
- . = NACA_PHYS_ADDR
- .globl __end_interrupts
-__end_interrupts:
-#ifdef CONFIG_PPC_ISERIES
- .globl naca
-naca:
- .llong itVpdAreas
- .llong 0 /* xRamDisk */
- .llong 0 /* xRamDiskSize */
+/*
+ * Vectors for the FWNMI option. Share common code.
+ */
+ .globl system_reset_fwnmi
+system_reset_fwnmi:
+ HMT_MEDIUM
+ mtspr SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
- . = 0x6100
+ .globl machine_check_fwnmi
+machine_check_fwnmi:
+ HMT_MEDIUM
+ mtspr SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+#ifdef CONFIG_PPC_ISERIES
/*** ISeries-LPAR interrupt handlers ***/
STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)
@@ -626,9 +622,7 @@ system_reset_iSeries:
cmpwi 0,r23,0
beq iSeries_secondary_smp_loop /* Loop until told to go */
-#ifdef SECONDARY_PROCESSORS
bne .__secondary_start /* Loop until told to go */
-#endif
iSeries_secondary_smp_loop:
/* Let the Hypervisor know we are alive */
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
@@ -671,51 +665,8 @@ hardware_interrupt_iSeries_masked:
ld r13,PACA_EXGEN+EX_R13(r13)
rfid
b . /* prevent speculative execution */
-#endif
-
-/*
- * Data area reserved for FWNMI option.
- */
- .= 0x7000
- .globl fwnmi_data_area
-fwnmi_data_area:
-
-#ifdef CONFIG_PPC_ISERIES
- . = LPARMAP_PHYS
-#include "lparmap.s"
#endif /* CONFIG_PPC_ISERIES */
-/*
- * Vectors for the FWNMI option. Share common code.
- */
- . = 0x8000
- .globl system_reset_fwnmi
-system_reset_fwnmi:
- HMT_MEDIUM
- mtspr SPRG1,r13 /* save r13 */
- RUNLATCH_ON(r13)
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
- .globl machine_check_fwnmi
-machine_check_fwnmi:
- HMT_MEDIUM
- mtspr SPRG1,r13 /* save r13 */
- RUNLATCH_ON(r13)
- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
-
- /*
- * Space for the initial segment table
- * For LPAR, the hypervisor must fill in at least one entry
- * before we get control (with relocate on)
- */
- . = STAB0_PHYS_ADDR
- .globl __start_stab
-__start_stab:
-
- . = (STAB0_PHYS_ADDR + PAGE_SIZE)
- .globl __end_stab
-__end_stab:
-
-
/*** Common interrupt handlers ***/
STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
@@ -752,8 +703,8 @@ machine_check_common:
* R9 contains the saved CR, r13 points to the paca,
* r10 contains the (bad) kernel stack pointer,
* r11 and r12 contain the saved SRR0 and SRR1.
- * We switch to using the paca guard page as an emergency stack,
- * save the registers there, and call kernel_bad_stack(), which panics.
+ * We switch to using an emergency stack, save the registers there,
+ * and call kernel_bad_stack(), which panics.
*/
bad_stack:
ld r1,PACAEMERGSP(r13)
@@ -906,6 +857,62 @@ fp_unavailable_common:
bl .kernel_fp_unavailable_exception
BUG_OPCODE
+/*
+ * load_up_fpu(unused, unused, tsk)
+ * Disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ * On SMP we know the fpu is free, since we give it up every
+ * switch (ie, no lazy save of the FP registers).
+ * On entry: r13 == 'current' && last_task_used_math != 'current'
+ */
+_STATIC(load_up_fpu)
+ mfmsr r5 /* grab the current MSR */
+ ori r5,r5,MSR_FP
+ mtmsrd r5 /* enable use of fpu now */
+ isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ *
+ */
+#ifndef CONFIG_SMP
+ ld r3,last_task_used_math@got(r2)
+ ld r4,0(r3)
+ cmpdi 0,r4,0
+ beq 1f
+ /* Save FP state to last_task_used_math's THREAD struct */
+ addi r4,r4,THREAD
+ SAVE_32FPRS(0, r4)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR(r4)
+ /* Disable FP for last_task_used_math */
+ ld r5,PT_REGS(r4)
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r6,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r6
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of FP after return */
+ ld r4,PACACURRENT(r13)
+ addi r5,r4,THREAD /* Get THREAD */
+ ld r4,THREAD_FPEXC_MODE(r5)
+ ori r12,r12,MSR_FP
+ or r12,r12,r4
+ std r12,_MSR(r1)
+ lfd fr0,THREAD_FPSCR(r5)
+ mtfsf 0xff,fr0
+ REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+ /* Update last_task_used_math to 'current' */
+ subi r4,r5,THREAD /* Back to 'current' */
+ std r4,0(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ b fast_exception_return
+
.align 7
.globl altivec_unavailable_common
altivec_unavailable_common:
@@ -921,6 +928,80 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
bl .altivec_unavailable_exception
b .ret_from_except
+#ifdef CONFIG_ALTIVEC
+/*
+ * load_up_altivec(unused, unused, tsk)
+ * Disable VMX for the task which had it previously,
+ * and save its vector registers in its thread_struct.
+ * Enables the VMX for use in the kernel on return.
+ * On SMP we know the VMX is free, since we give it up every
+ * switch (ie, no lazy save of the vector registers).
+ * On entry: r13 == 'current' && last_task_used_altivec != 'current'
+ */
+_STATIC(load_up_altivec)
+ mfmsr r5 /* grab the current MSR */
+ oris r5,r5,MSR_VEC@h
+ mtmsrd r5 /* enable use of VMX now */
+ isync
+
+/*
+ * For SMP, we don't do lazy VMX switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_altvec in switch_to.
+ * VRSAVE isn't dealt with here, that is done in the normal context
+ * switch code. Note that we could rely on vrsave value to eventually
+ * avoid saving all of the VREGs here...
+ */
+#ifndef CONFIG_SMP
+ ld r3,last_task_used_altivec@got(r2)
+ ld r4,0(r3)
+ cmpdi 0,r4,0
+ beq 1f
+ /* Save VMX state to last_task_used_altivec's THREAD struct */
+ addi r4,r4,THREAD
+ SAVE_32VRS(0,r5,r4)
+ mfvscr vr0
+ li r10,THREAD_VSCR
+ stvx vr0,r10,r4
+ /* Disable VMX for last_task_used_altivec */
+ ld r5,PT_REGS(r4)
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r6,MSR_VEC@h
+ andc r4,r4,r6
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* Hack: if we get an altivec unavailable trap with VRSAVE
+ * set to all zeros, we assume this is a broken application
+ * that fails to set it properly, and thus we switch it to
+ * all 1's
+ */
+ mfspr r4,SPRN_VRSAVE
+ cmpdi 0,r4,0
+ bne+ 1f
+ li r4,-1
+ mtspr SPRN_VRSAVE,r4
+1:
+ /* enable use of VMX after return */
+ ld r4,PACACURRENT(r13)
+ addi r5,r4,THREAD /* Get THREAD */
+ oris r12,r12,MSR_VEC@h
+ std r12,_MSR(r1)
+ li r4,1
+ li r10,THREAD_VSCR
+ stw r4,THREAD_USED_VR(r5)
+ lvx vr0,r10,r5
+ mtvscr vr0
+ REST_32VRS(0,r4,r5)
+#ifndef CONFIG_SMP
+ /* Update last_task_used_math to 'current' */
+ subi r4,r5,THREAD /* Back to 'current' */
+ std r4,0(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ b fast_exception_return
+#endif /* CONFIG_ALTIVEC */
+
/*
* Hash table stuff
*/
@@ -1167,6 +1248,42 @@ unrecov_slb:
bl .unrecoverable_exception
b 1b
+/*
+ * Space for CPU0's segment table.
+ *
+ * On iSeries, the hypervisor must fill in at least one entry before
+ * we get control (with relocate on). The address is give to the hv
+ * as a page number (see xLparMap in LparData.c), so this must be at a
+ * fixed address (the linker can't compute (u64)&initial_stab >>
+ * PAGE_SHIFT).
+ */
+ . = STAB0_PHYS_ADDR /* 0x6000 */
+ .globl initial_stab
+initial_stab:
+ .space 4096
+
+/*
+ * Data area reserved for FWNMI option.
+ * This address (0x7000) is fixed by the RPA.
+ */
+ .= 0x7000
+ .globl fwnmi_data_area
+fwnmi_data_area:
+
+ /* iSeries does not use the FWNMI stuff, so it is safe to put
+ * this here, even if we later allow kernels that will boot on
+ * both pSeries and iSeries */
+#ifdef CONFIG_PPC_ISERIES
+ . = LPARMAP_PHYS
+#include "lparmap.s"
+/*
+ * This ".text" is here for old compilers that generate a trailing
+ * .note section when compiling .c files to .s
+ */
+ .text
+#endif /* CONFIG_PPC_ISERIES */
+
+ . = 0x8000
/*
* On pSeries, secondary processors spin in the following code.
@@ -1200,7 +1317,7 @@ _GLOBAL(pSeries_secondary_smp_init)
b .kexec_wait /* next kernel might do better */
2: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
- /* From now on, r24 is expected to be logica cpuid */
+ /* From now on, r24 is expected to be logical cpuid */
mr r24,r5
3: HMT_LOW
lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
@@ -1213,10 +1330,8 @@ _GLOBAL(pSeries_secondary_smp_init)
cmpwi 0,r23,0
#ifdef CONFIG_SMP
-#ifdef SECONDARY_PROCESSORS
bne .__secondary_start
#endif
-#endif
b 3b /* Loop until told to go */
#ifdef CONFIG_PPC_ISERIES
@@ -1430,228 +1545,6 @@ _GLOBAL(copy_and_flush)
.align 8
copy_to_here:
-/*
- * load_up_fpu(unused, unused, tsk)
- * Disable FP for the task which had the FPU previously,
- * and save its floating-point registers in its thread_struct.
- * Enables the FPU for use in the kernel on return.
- * On SMP we know the fpu is free, since we give it up every
- * switch (ie, no lazy save of the FP registers).
- * On entry: r13 == 'current' && last_task_used_math != 'current'
- */
-_STATIC(load_up_fpu)
- mfmsr r5 /* grab the current MSR */
- ori r5,r5,MSR_FP
- mtmsrd r5 /* enable use of fpu now */
- isync
-/*
- * For SMP, we don't do lazy FPU switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another. Instead we call giveup_fpu in switch_to.
- *
- */
-#ifndef CONFIG_SMP
- ld r3,last_task_used_math@got(r2)
- ld r4,0(r3)
- cmpdi 0,r4,0
- beq 1f
- /* Save FP state to last_task_used_math's THREAD struct */
- addi r4,r4,THREAD
- SAVE_32FPRS(0, r4)
- mffs fr0
- stfd fr0,THREAD_FPSCR(r4)
- /* Disable FP for last_task_used_math */
- ld r5,PT_REGS(r4)
- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r6,MSR_FP|MSR_FE0|MSR_FE1
- andc r4,r4,r6
- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
- /* enable use of FP after return */
- ld r4,PACACURRENT(r13)
- addi r5,r4,THREAD /* Get THREAD */
- ld r4,THREAD_FPEXC_MODE(r5)
- ori r12,r12,MSR_FP
- or r12,r12,r4
- std r12,_MSR(r1)
- lfd fr0,THREAD_FPSCR(r5)
- mtfsf 0xff,fr0
- REST_32FPRS(0, r5)
-#ifndef CONFIG_SMP
- /* Update last_task_used_math to 'current' */
- subi r4,r5,THREAD /* Back to 'current' */
- std r4,0(r3)
-#endif /* CONFIG_SMP */
- /* restore registers and return */
- b fast_exception_return
-
-/*
- * disable_kernel_fp()
- * Disable the FPU.
- */
-_GLOBAL(disable_kernel_fp)
- mfmsr r3
- rldicl r0,r3,(63-MSR_FP_LG),1
- rldicl r3,r0,(MSR_FP_LG+1),0
- mtmsrd r3 /* disable use of fpu now */
- isync
- blr
-
-/*
- * giveup_fpu(tsk)
- * Disable FP for the task given as the argument,
- * and save the floating-point registers in its thread_struct.
- * Enables the FPU for use in the kernel on return.
- */
-_GLOBAL(giveup_fpu)
- mfmsr r5
- ori r5,r5,MSR_FP
- mtmsrd r5 /* enable use of fpu now */
- isync
- cmpdi 0,r3,0
- beqlr- /* if no previous owner, done */
- addi r3,r3,THREAD /* want THREAD of task */
- ld r5,PT_REGS(r3)
- cmpdi 0,r5,0
- SAVE_32FPRS(0, r3)
- mffs fr0
- stfd fr0,THREAD_FPSCR(r3)
- beq 1f
- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r3,MSR_FP|MSR_FE0|MSR_FE1
- andc r4,r4,r3 /* disable FP for previous task */
- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
- li r5,0
- ld r4,last_task_used_math@got(r2)
- std r5,0(r4)
-#endif /* CONFIG_SMP */
- blr
-
-
-#ifdef CONFIG_ALTIVEC
-
-/*
- * load_up_altivec(unused, unused, tsk)
- * Disable VMX for the task which had it previously,
- * and save its vector registers in its thread_struct.
- * Enables the VMX for use in the kernel on return.
- * On SMP we know the VMX is free, since we give it up every
- * switch (ie, no lazy save of the vector registers).
- * On entry: r13 == 'current' && last_task_used_altivec != 'current'
- */
-_STATIC(load_up_altivec)
- mfmsr r5 /* grab the current MSR */
- oris r5,r5,MSR_VEC@h
- mtmsrd r5 /* enable use of VMX now */
- isync
-
-/*
- * For SMP, we don't do lazy VMX switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another. Instead we call giveup_altvec in switch_to.
- * VRSAVE isn't dealt with here, that is done in the normal context
- * switch code. Note that we could rely on vrsave value to eventually
- * avoid saving all of the VREGs here...
- */
-#ifndef CONFIG_SMP
- ld r3,last_task_used_altivec@got(r2)
- ld r4,0(r3)
- cmpdi 0,r4,0
- beq 1f
- /* Save VMX state to last_task_used_altivec's THREAD struct */
- addi r4,r4,THREAD
- SAVE_32VRS(0,r5,r4)
- mfvscr vr0
- li r10,THREAD_VSCR
- stvx vr0,r10,r4
- /* Disable VMX for last_task_used_altivec */
- ld r5,PT_REGS(r4)
- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- lis r6,MSR_VEC@h
- andc r4,r4,r6
- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
- /* Hack: if we get an altivec unavailable trap with VRSAVE
- * set to all zeros, we assume this is a broken application
- * that fails to set it properly, and thus we switch it to
- * all 1's
- */
- mfspr r4,SPRN_VRSAVE
- cmpdi 0,r4,0
- bne+ 1f
- li r4,-1
- mtspr SPRN_VRSAVE,r4
-1:
- /* enable use of VMX after return */
- ld r4,PACACURRENT(r13)
- addi r5,r4,THREAD /* Get THREAD */
- oris r12,r12,MSR_VEC@h
- std r12,_MSR(r1)
- li r4,1
- li r10,THREAD_VSCR
- stw r4,THREAD_USED_VR(r5)
- lvx vr0,r10,r5
- mtvscr vr0
- REST_32VRS(0,r4,r5)
-#ifndef CONFIG_SMP
- /* Update last_task_used_math to 'current' */
- subi r4,r5,THREAD /* Back to 'current' */
- std r4,0(r3)
-#endif /* CONFIG_SMP */
- /* restore registers and return */
- b fast_exception_return
-
-/*
- * disable_kernel_altivec()
- * Disable the VMX.
- */
-_GLOBAL(disable_kernel_altivec)
- mfmsr r3
- rldicl r0,r3,(63-MSR_VEC_LG),1
- rldicl r3,r0,(MSR_VEC_LG+1),0
- mtmsrd r3 /* disable use of VMX now */
- isync
- blr
-
-/*
- * giveup_altivec(tsk)
- * Disable VMX for the task given as the argument,
- * and save the vector registers in its thread_struct.
- * Enables the VMX for use in the kernel on return.
- */
-_GLOBAL(giveup_altivec)
- mfmsr r5
- oris r5,r5,MSR_VEC@h
- mtmsrd r5 /* enable use of VMX now */
- isync
- cmpdi 0,r3,0
- beqlr- /* if no previous owner, done */
- addi r3,r3,THREAD /* want THREAD of task */
- ld r5,PT_REGS(r3)
- cmpdi 0,r5,0
- SAVE_32VRS(0,r4,r3)
- mfvscr vr0
- li r4,THREAD_VSCR
- stvx vr0,r4,r3
- beq 1f
- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- lis r3,MSR_VEC@h
- andc r4,r4,r3 /* disable FP for previous task */
- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
- li r5,0
- ld r4,last_task_used_altivec@got(r2)
- std r5,0(r4)
-#endif /* CONFIG_SMP */
- blr
-
-#endif /* CONFIG_ALTIVEC */
-
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_PMAC
/*
@@ -1753,8 +1646,9 @@ _GLOBAL(__secondary_start)
#else
/* set the ASR */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
+ ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
- cmpldi r3,PLATFORM_PSERIES_LPAR
+ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
bne 98f
mfspr r3,PVR
srwi r3,r3,16
@@ -1916,8 +1810,9 @@ _STATIC(start_here_multiplatform)
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
+ ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
- cmpldi r3,PLATFORM_PSERIES_LPAR
+ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
bne 98f
mfspr r3,PVR
srwi r3,r3,16
@@ -1935,9 +1830,10 @@ _STATIC(start_here_multiplatform)
99:
/* Set SDR1 (hash table pointer) */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
+ ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */
- andi. r3,r3,0x1
+ andi. r3,r3,PLATFORM_LPAR
bne 98f
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
sub r6,r6,r26
@@ -2002,9 +1898,6 @@ _STATIC(start_here_common)
bl .start_kernel
-_GLOBAL(__setup_cpu_power3)
- blr
-
_GLOBAL(hmt_init)
#ifdef CONFIG_HMT
LOADADDR(r5, hmt_thread_data)
@@ -2095,20 +1988,19 @@ _GLOBAL(smp_release_cpus)
/*
* We put a few things here that have to be page-aligned.
- * This stuff goes at the beginning of the data segment,
- * which is page-aligned.
+ * This stuff goes at the beginning of the bss, which is page-aligned.
*/
- .data
+ .section ".bss"
+
.align 12
- .globl sdata
-sdata:
+
.globl empty_zero_page
empty_zero_page:
- .space 4096
+ .space PAGE_SIZE
.globl swapper_pg_dir
swapper_pg_dir:
- .space 4096
+ .space PAGE_SIZE
/*
* This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
index d11c732daf81..5d921792571f 100644
--- a/arch/ppc64/kernel/iSeries_VpdInfo.c
+++ b/arch/ppc64/kernel/iSeries_VpdInfo.c
@@ -264,8 +264,5 @@ void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ",
count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
frame, card);
- if (pci_class_name(PciDev->class >> 8) == 0)
- printk("0x%04X\n", (int)(PciDev->class >> 8));
- else
- printk("%s\n", pci_class_name(PciDev->class >> 8));
+ printk("0x%04X\n", (int)(PciDev->class >> 8));
}
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index b0250ae4a72a..2192055a90a0 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -41,6 +41,7 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long prpn, unsigned long vflags,
unsigned long rflags)
{
+ unsigned long arpn;
long slot;
hpte_t lhpte;
int secondary = 0;
@@ -70,8 +71,10 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
slot &= 0x7fffffffffffffff;
}
+ arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
+
lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
- lhpte.r = (physRpn_to_absRpn(prpn) << HPTE_R_RPN_SHIFT) | rflags;
+ lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
/* Now fill in the actual HPTE */
HvCallHpt_addValidate(slot, secondary, &lhpte);
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index 356e4fd9a94f..fbc273c32bcc 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void)
phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
if (phb == NULL)
return -ENOMEM;
- pci_setup_pci_controller(phb);
+ pci_setup_pci_controller(phb);
phb->pci_mem_offset = phb->local_number = bus;
phb->first_busno = bus;
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index a649edbb23b6..3ffefbbc6623 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -39,6 +39,7 @@
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/iommu.h>
+#include <asm/firmware.h>
#include <asm/time.h>
#include "iSeries_setup.h"
@@ -314,6 +315,8 @@ static void __init iSeries_init_early(void)
DBG(" -> iSeries_init_early()\n");
+ ppc64_firmware_features = FW_FEATURE_ISERIES;
+
ppcdbg_initialize();
#if defined(CONFIG_BLK_DEV_INITRD)
@@ -412,6 +415,22 @@ static void __init iSeries_init_early(void)
DBG(" <- iSeries_init_early()\n");
}
+struct mschunks_map mschunks_map = {
+ /* XXX We don't use these, but Piranha might need them. */
+ .chunk_size = MSCHUNKS_CHUNK_SIZE,
+ .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
+ .chunk_mask = MSCHUNKS_OFFSET_MASK,
+};
+EXPORT_SYMBOL(mschunks_map);
+
+void mschunks_alloc(unsigned long num_chunks)
+{
+ klimit = _ALIGN(klimit, sizeof(u32));
+ mschunks_map.mapping = (u32 *)klimit;
+ klimit += num_chunks * sizeof(u32);
+ mschunks_map.num_chunks = num_chunks;
+}
+
/*
* The iSeries may have very large memories ( > 128 GB ) and a partition
* may get memory in "chunks" that may be anywhere in the 2**52 real
@@ -449,7 +468,7 @@ static void __init build_iSeries_Memory_Map(void)
/* Chunk size on iSeries is 256K bytes */
totalChunks = (u32)HvLpConfig_getMsChunks();
- klimit = msChunks_alloc(klimit, totalChunks, 1UL << 18);
+ mschunks_alloc(totalChunks);
/*
* Get absolute address of our load area
@@ -486,7 +505,7 @@ static void __init build_iSeries_Memory_Map(void)
printk("Load area size %dK\n", loadAreaSize * 256);
for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
- msChunks.abs[nextPhysChunk] =
+ mschunks_map.mapping[nextPhysChunk] =
loadAreaFirstChunk + nextPhysChunk;
/*
@@ -495,7 +514,7 @@ static void __init build_iSeries_Memory_Map(void)
*/
hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
hptSizePages = (u32)HvCallHpt_getHptPages();
- hptSizeChunks = hptSizePages >> (msChunks.chunk_shift - PAGE_SHIFT);
+ hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
printk("HPT absolute addr = %016lx, size = %dK\n",
@@ -552,7 +571,8 @@ static void __init build_iSeries_Memory_Map(void)
(absChunk > hptLastChunk)) &&
((absChunk < loadAreaFirstChunk) ||
(absChunk > loadAreaLastChunk))) {
- msChunks.abs[nextPhysChunk] = absChunk;
+ mschunks_map.mapping[nextPhysChunk] =
+ absChunk;
++nextPhysChunk;
}
}
@@ -944,6 +964,8 @@ void __init iSeries_early_setup(void)
ppc_md.calibrate_decr = iSeries_calibrate_decr;
ppc_md.progress = iSeries_progress;
+ /* XXX Implement enable_pmcs for iSeries */
+
if (get_paca()->lppaca.shared_proc) {
ppc_md.idle_loop = iseries_shared_idle;
printk(KERN_INFO "Using shared processor idle loop\n");
diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c
new file mode 100644
index 000000000000..6b754b0c8344
--- /dev/null
+++ b/arch/ppc64/kernel/iSeries_vio.c
@@ -0,0 +1,155 @@
+/*
+ * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
+ *
+ * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/init.h>
+
+#include <asm/vio.h>
+#include <asm/iommu.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpConfig.h>
+#include <asm/iSeries/HvCallXm.h>
+
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
+EXPORT_SYMBOL(iSeries_vio_dev);
+
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+static void __init iommu_vio_init(void)
+{
+ struct iommu_table *t;
+ struct iommu_table_cb cb;
+ unsigned long cbp;
+ unsigned long itc_entries;
+
+ cb.itc_busno = 255; /* Bus 255 is the virtual bus */
+ cb.itc_virtbus = 0xff; /* Ask for virtual bus */
+
+ cbp = virt_to_abs(&cb);
+ HvCallXm_getTceTableParms(cbp);
+
+ itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
+ veth_iommu_table.it_size = itc_entries / 2;
+ veth_iommu_table.it_busno = cb.itc_busno;
+ veth_iommu_table.it_offset = cb.itc_offset;
+ veth_iommu_table.it_index = cb.itc_index;
+ veth_iommu_table.it_type = TCE_VB;
+ veth_iommu_table.it_blocksize = 1;
+
+ t = iommu_init_table(&veth_iommu_table);
+
+ if (!t)
+ printk("Virtual Bus VETH TCE table failed.\n");
+
+ vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
+ vio_iommu_table.it_busno = cb.itc_busno;
+ vio_iommu_table.it_offset = cb.itc_offset +
+ veth_iommu_table.it_size;
+ vio_iommu_table.it_index = cb.itc_index;
+ vio_iommu_table.it_type = TCE_VB;
+ vio_iommu_table.it_blocksize = 1;
+
+ t = iommu_init_table(&vio_iommu_table);
+
+ if (!t)
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+
+/**
+ * vio_register_device_iseries: - Register a new iSeries vio device.
+ * @voidev: The device to register.
+ */
+static struct vio_dev *__init vio_register_device_iseries(char *type,
+ uint32_t unit_num)
+{
+ struct vio_dev *viodev;
+
+ /* allocate a vio_dev for this device */
+ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+ if (!viodev)
+ return NULL;
+ memset(viodev, 0, sizeof(struct vio_dev));
+
+ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
+
+ viodev->name = viodev->dev.bus_id;
+ viodev->type = type;
+ viodev->unit_address = unit_num;
+ viodev->iommu_table = &vio_iommu_table;
+ if (vio_register_device(viodev) == NULL) {
+ kfree(viodev);
+ return NULL;
+ }
+ return viodev;
+}
+
+void __init probe_bus_iseries(void)
+{
+ HvLpIndexMap vlan_map;
+ struct vio_dev *viodev;
+ int i;
+
+ /* there is only one of each of these */
+ vio_register_device_iseries("viocons", 0);
+ vio_register_device_iseries("vscsi", 0);
+
+ vlan_map = HvLpConfig_getVirtualLanIndexMap();
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+ if ((vlan_map & (0x8000 >> i)) == 0)
+ continue;
+ viodev = vio_register_device_iseries("vlan", i);
+ /* veth is special and has it own iommu_table */
+ viodev->iommu_table = &veth_iommu_table;
+ }
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+ vio_register_device_iseries("viodasd", i);
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+ vio_register_device_iseries("viocd", i);
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+ vio_register_device_iseries("viotape", i);
+}
+
+/**
+ * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
+ * vio_device_id
+ */
+static int vio_match_device_iseries(const struct vio_device_id *id,
+ const struct vio_dev *dev)
+{
+ return strncmp(dev->type, id->type, strlen(id->type)) == 0;
+}
+
+static struct vio_bus_ops vio_bus_ops_iseries = {
+ .match = vio_match_device_iseries,
+};
+
+/**
+ * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
+ */
+static int __init vio_bus_init_iseries(void)
+{
+ int err;
+
+ err = vio_bus_init(&vio_bus_ops_iseries);
+ if (err == 0) {
+ iommu_vio_init();
+ vio_bus_device.iommu_table = &vio_iommu_table;
+ iSeries_vio_dev = &vio_bus_device.dev;
+ probe_bus_iseries();
+ }
+ return err;
+}
+
+__initcall(vio_bus_init_iseries);
diff --git a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S
index 97e4a2655040..ca02afe2a795 100644
--- a/arch/ppc64/kernel/idle_power4.S
+++ b/arch/ppc64/kernel/idle_power4.S
@@ -20,7 +20,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#undef DEBUG
diff --git a/arch/ppc64/kernel/iomap.c b/arch/ppc64/kernel/iomap.c
index 153cc8b0f136..6160c8dbb7c5 100644
--- a/arch/ppc64/kernel/iomap.c
+++ b/arch/ppc64/kernel/iomap.c
@@ -22,13 +22,23 @@ unsigned int fastcall ioread16(void __iomem *addr)
{
return readw(addr);
}
+unsigned int fastcall ioread16be(void __iomem *addr)
+{
+ return in_be16(addr);
+}
unsigned int fastcall ioread32(void __iomem *addr)
{
return readl(addr);
}
+unsigned int fastcall ioread32be(void __iomem *addr)
+{
+ return in_be32(addr);
+}
EXPORT_SYMBOL(ioread8);
EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread16be);
EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(ioread32be);
void fastcall iowrite8(u8 val, void __iomem *addr)
{
@@ -38,13 +48,23 @@ void fastcall iowrite16(u16 val, void __iomem *addr)
{
writew(val, addr);
}
+void fastcall iowrite16be(u16 val, void __iomem *addr)
+{
+ out_be16(addr, val);
+}
void fastcall iowrite32(u32 val, void __iomem *addr)
{
writel(val, addr);
}
+void fastcall iowrite32be(u32 val, void __iomem *addr)
+{
+ out_be32(addr, val);
+}
EXPORT_SYMBOL(iowrite8);
EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite16be);
EXPORT_SYMBOL(iowrite32);
+EXPORT_SYMBOL(iowrite32be);
/*
* These are the "repeat read/write" functions. Note the
@@ -56,15 +76,15 @@ EXPORT_SYMBOL(iowrite32);
*/
void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
{
- _insb((u8 __force *) addr, dst, count);
+ _insb((u8 __iomem *) addr, dst, count);
}
void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
{
- _insw_ns((u16 __force *) addr, dst, count);
+ _insw_ns((u16 __iomem *) addr, dst, count);
}
void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
{
- _insl_ns((u32 __force *) addr, dst, count);
+ _insl_ns((u32 __iomem *) addr, dst, count);
}
EXPORT_SYMBOL(ioread8_rep);
EXPORT_SYMBOL(ioread16_rep);
@@ -72,15 +92,15 @@ EXPORT_SYMBOL(ioread32_rep);
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
{
- _outsb((u8 __force *) addr, src, count);
+ _outsb((u8 __iomem *) addr, src, count);
}
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
{
- _outsw_ns((u16 __force *) addr, src, count);
+ _outsw_ns((u16 __iomem *) addr, src, count);
}
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
{
- _outsl_ns((u32 __force *) addr, src, count);
+ _outsl_ns((u32 __iomem *) addr, src, count);
}
EXPORT_SYMBOL(iowrite8_rep);
EXPORT_SYMBOL(iowrite16_rep);
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 845eebd1e28d..9032b6bfe036 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -438,7 +438,8 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
void iommu_free_table(struct device_node *dn)
{
- struct iommu_table *tbl = dn->iommu_table;
+ struct pci_dn *pdn = dn->data;
+ struct iommu_table *tbl = pdn->iommu_table;
unsigned long bitmap_sz, i;
unsigned int order;
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index a3d519518fb8..7e80d49c589a 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev;
static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
static struct pt_regs jprobe_saved_regs;
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
kprobe_opcode_t insn = *p->addr;
@@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p)
return ret;
}
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
{
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
}
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
{
up(&kprobe_mutex);
free_insn_slot(p->ainsn.insn);
@@ -102,7 +102,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->msr |= MSR_SE;
/* single step inline if it is a trap variant */
- if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn))
+ if (is_trap(insn))
regs->nip = (unsigned long)p->addr;
else
regs->nip = (unsigned long)p->ainsn.insn;
@@ -122,7 +122,8 @@ static inline void restore_previous_kprobe(void)
kprobe_saved_msr = kprobe_saved_msr_prev;
}
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
{
struct kretprobe_instance *ri;
@@ -151,7 +152,9 @@ static inline int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS) {
+ kprobe_opcode_t insn = *p->ainsn.insn;
+ if (kprobe_status == KPROBE_HIT_SS &&
+ is_trap(insn)) {
regs->msr &= ~MSR_SE;
regs->msr |= kprobe_saved_msr;
unlock_kprobes();
@@ -191,8 +194,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
* trap variant, it could belong to someone else
*/
kprobe_opcode_t cur_insn = *addr;
- if (IS_TW(cur_insn) || IS_TD(cur_insn) ||
- IS_TWI(cur_insn) || IS_TDI(cur_insn))
+ if (is_trap(cur_insn))
goto no_kprobe;
/*
* The breakpoint instruction was removed right
@@ -244,7 +246,7 @@ void kretprobe_trampoline_holder(void)
/*
* Called when the probe at kretprobe trampoline is hit
*/
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
@@ -308,7 +310,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* single-stepped a copy of the instruction. The address of this
* copy is p->ainsn.insn.
*/
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
int ret;
unsigned int insn = *p->ainsn.insn;
@@ -373,8 +375,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
/*
* Wrapper routine to for handling exceptions.
*/
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
- void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
@@ -402,11 +404,11 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
default:
break;
}
- preempt_enable();
+ preempt_enable_no_resched();
return ret;
}
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
@@ -419,16 +421,16 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
{
asm volatile("trap" ::: "memory");
}
-void jprobe_return_end(void)
+void __kprobes jprobe_return_end(void)
{
};
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
/*
* FIXME - we should ideally be validating that we got here 'cos
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index d6c6bd03d2a4..5adaca2ddc9d 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -28,33 +28,28 @@ void lmb_dump_all(void)
{
#ifdef DEBUG
unsigned long i;
- struct lmb *_lmb = &lmb;
udbg_printf("lmb_dump_all:\n");
udbg_printf(" memory.cnt = 0x%lx\n",
- _lmb->memory.cnt);
+ lmb.memory.cnt);
udbg_printf(" memory.size = 0x%lx\n",
- _lmb->memory.size);
- for (i=0; i < _lmb->memory.cnt ;i++) {
+ lmb.memory.size);
+ for (i=0; i < lmb.memory.cnt ;i++) {
udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
- i, _lmb->memory.region[i].base);
- udbg_printf(" .physbase = 0x%lx\n",
- _lmb->memory.region[i].physbase);
+ i, lmb.memory.region[i].base);
udbg_printf(" .size = 0x%lx\n",
- _lmb->memory.region[i].size);
+ lmb.memory.region[i].size);
}
udbg_printf("\n reserved.cnt = 0x%lx\n",
- _lmb->reserved.cnt);
+ lmb.reserved.cnt);
udbg_printf(" reserved.size = 0x%lx\n",
- _lmb->reserved.size);
- for (i=0; i < _lmb->reserved.cnt ;i++) {
+ lmb.reserved.size);
+ for (i=0; i < lmb.reserved.cnt ;i++) {
udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
- i, _lmb->reserved.region[i].base);
- udbg_printf(" .physbase = 0x%lx\n",
- _lmb->reserved.region[i].physbase);
+ i, lmb.reserved.region[i].base);
udbg_printf(" .size = 0x%lx\n",
- _lmb->reserved.region[i].size);
+ lmb.reserved.region[i].size);
}
#endif /* DEBUG */
}
@@ -98,7 +93,6 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
rgn->region[r1].size += rgn->region[r2].size;
for (i=r2; i < rgn->cnt-1; i++) {
rgn->region[i].base = rgn->region[i+1].base;
- rgn->region[i].physbase = rgn->region[i+1].physbase;
rgn->region[i].size = rgn->region[i+1].size;
}
rgn->cnt--;
@@ -108,49 +102,29 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
void __init
lmb_init(void)
{
- struct lmb *_lmb = &lmb;
-
/* Create a dummy zero size LMB which will get coalesced away later.
* This simplifies the lmb_add() code below...
*/
- _lmb->memory.region[0].base = 0;
- _lmb->memory.region[0].size = 0;
- _lmb->memory.cnt = 1;
+ lmb.memory.region[0].base = 0;
+ lmb.memory.region[0].size = 0;
+ lmb.memory.cnt = 1;
/* Ditto. */
- _lmb->reserved.region[0].base = 0;
- _lmb->reserved.region[0].size = 0;
- _lmb->reserved.cnt = 1;
+ lmb.reserved.region[0].base = 0;
+ lmb.reserved.region[0].size = 0;
+ lmb.reserved.cnt = 1;
}
/* This routine called with relocation disabled. */
void __init
lmb_analyze(void)
{
- unsigned long i;
- unsigned long mem_size = 0;
- unsigned long size_mask = 0;
- struct lmb *_lmb = &lmb;
-#ifdef CONFIG_MSCHUNKS
- unsigned long physbase = 0;
-#endif
-
- for (i=0; i < _lmb->memory.cnt; i++) {
- unsigned long lmb_size;
-
- lmb_size = _lmb->memory.region[i].size;
-
-#ifdef CONFIG_MSCHUNKS
- _lmb->memory.region[i].physbase = physbase;
- physbase += lmb_size;
-#else
- _lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
-#endif
- mem_size += lmb_size;
- size_mask |= lmb_size;
- }
+ int i;
+
+ lmb.memory.size = 0;
- _lmb->memory.size = mem_size;
+ for (i = 0; i < lmb.memory.cnt; i++)
+ lmb.memory.size += lmb.memory.region[i].size;
}
/* This routine called with relocation disabled. */
@@ -168,7 +142,6 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
if ( adjacent > 0 ) {
rgn->region[i].base -= size;
- rgn->region[i].physbase -= size;
rgn->region[i].size += size;
coalesced++;
break;
@@ -195,11 +168,9 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
for (i=rgn->cnt-1; i >= 0; i--) {
if (base < rgn->region[i].base) {
rgn->region[i+1].base = rgn->region[i].base;
- rgn->region[i+1].physbase = rgn->region[i].physbase;
rgn->region[i+1].size = rgn->region[i].size;
} else {
rgn->region[i+1].base = base;
- rgn->region[i+1].physbase = lmb_abs_to_phys(base);
rgn->region[i+1].size = size;
break;
}
@@ -213,12 +184,11 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
long __init
lmb_add(unsigned long base, unsigned long size)
{
- struct lmb *_lmb = &lmb;
- struct lmb_region *_rgn = &(_lmb->memory);
+ struct lmb_region *_rgn = &(lmb.memory);
/* On pSeries LPAR systems, the first LMB is our RMO region. */
if ( base == 0 )
- _lmb->rmo_size = size;
+ lmb.rmo_size = size;
return lmb_add_region(_rgn, base, size);
@@ -227,8 +197,7 @@ lmb_add(unsigned long base, unsigned long size)
long __init
lmb_reserve(unsigned long base, unsigned long size)
{
- struct lmb *_lmb = &lmb;
- struct lmb_region *_rgn = &(_lmb->reserved);
+ struct lmb_region *_rgn = &(lmb.reserved);
return lmb_add_region(_rgn, base, size);
}
@@ -260,13 +229,10 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
{
long i, j;
unsigned long base = 0;
- struct lmb *_lmb = &lmb;
- struct lmb_region *_mem = &(_lmb->memory);
- struct lmb_region *_rsv = &(_lmb->reserved);
- for (i=_mem->cnt-1; i >= 0; i--) {
- unsigned long lmbbase = _mem->region[i].base;
- unsigned long lmbsize = _mem->region[i].size;
+ for (i=lmb.memory.cnt-1; i >= 0; i--) {
+ unsigned long lmbbase = lmb.memory.region[i].base;
+ unsigned long lmbsize = lmb.memory.region[i].size;
if ( max_addr == LMB_ALLOC_ANYWHERE )
base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);
@@ -276,8 +242,8 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
continue;
while ( (lmbbase <= base) &&
- ((j = lmb_overlaps_region(_rsv,base,size)) >= 0) ) {
- base = _ALIGN_DOWN(_rsv->region[j].base-size, align);
+ ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) {
+ base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align);
}
if ( (base != 0) && (lmbbase <= base) )
@@ -287,62 +253,24 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
if ( i < 0 )
return 0;
- lmb_add_region(_rsv, base, size);
+ lmb_add_region(&lmb.reserved, base, size);
return base;
}
+/* You must call lmb_analyze() before this. */
unsigned long __init
lmb_phys_mem_size(void)
{
- struct lmb *_lmb = &lmb;
-#ifdef CONFIG_MSCHUNKS
- return _lmb->memory.size;
-#else
- struct lmb_region *_mem = &(_lmb->memory);
- unsigned long total = 0;
- int i;
-
- /* add all physical memory to the bootmem map */
- for (i=0; i < _mem->cnt; i++)
- total += _mem->region[i].size;
- return total;
-#endif /* CONFIG_MSCHUNKS */
+ return lmb.memory.size;
}
unsigned long __init
lmb_end_of_DRAM(void)
{
- struct lmb *_lmb = &lmb;
- struct lmb_region *_mem = &(_lmb->memory);
- int idx = _mem->cnt - 1;
-
-#ifdef CONFIG_MSCHUNKS
- return (_mem->region[idx].physbase + _mem->region[idx].size);
-#else
- return (_mem->region[idx].base + _mem->region[idx].size);
-#endif /* CONFIG_MSCHUNKS */
-
- return 0;
-}
-
-unsigned long __init
-lmb_abs_to_phys(unsigned long aa)
-{
- unsigned long i, pa = aa;
- struct lmb *_lmb = &lmb;
- struct lmb_region *_mem = &(_lmb->memory);
-
- for (i=0; i < _mem->cnt; i++) {
- unsigned long lmbbase = _mem->region[i].base;
- unsigned long lmbsize = _mem->region[i].size;
- if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) {
- pa = _mem->region[i].physbase + (aa - lmbbase);
- break;
- }
- }
+ int idx = lmb.memory.cnt - 1;
- return pa;
+ return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
}
/*
@@ -353,20 +281,19 @@ void __init lmb_enforce_memory_limit(void)
{
extern unsigned long memory_limit;
unsigned long i, limit;
- struct lmb_region *mem = &(lmb.memory);
if (! memory_limit)
return;
limit = memory_limit;
- for (i = 0; i < mem->cnt; i++) {
- if (limit > mem->region[i].size) {
- limit -= mem->region[i].size;
+ for (i = 0; i < lmb.memory.cnt; i++) {
+ if (limit > lmb.memory.region[i].size) {
+ limit -= lmb.memory.region[i].size;
continue;
}
- mem->region[i].size = limit;
- mem->cnt = i + 1;
+ lmb.memory.region[i].size = limit;
+ lmb.memory.cnt = i + 1;
break;
}
}
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index 02e96627fa66..cae19bbd5acd 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -29,7 +29,7 @@
#include <asm/iSeries/HvLpConfig.h>
#include <asm/lppaca.h>
#include <asm/hvcall.h>
-#include <asm/cputable.h>
+#include <asm/firmware.h>
#include <asm/rtas.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -273,6 +273,7 @@ static void parse_system_parameter_string(struct seq_file *m)
if (!workbuffer) {
printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
__FILE__, __FUNCTION__, __LINE__);
+ kfree(local_buffer);
return;
}
#ifdef LPARCFG_DEBUG
@@ -377,7 +378,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
partition_active_processors = lparcfg_count_active_processors();
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
unsigned long h_entitled, h_unallocated;
unsigned long h_aggregation, h_resource;
unsigned long pool_idle_time, pool_procs;
@@ -568,10 +569,10 @@ struct file_operations lparcfg_fops = {
int __init lparcfg_init(void)
{
struct proc_dir_entry *ent;
- mode_t mode = S_IRUSR;
+ mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
/* Allow writing if we have FW_FEATURE_SPLPAR */
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
lparcfg_fops.write = lparcfg_write;
mode |= S_IWUSR;
}
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
index 53993999b265..1d297e0edfc0 100644
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
*/
- hose->first_busno = 0xf0;
+ hose->first_busno = 0xf0;
hose->last_busno = 0xff;
hose->ops = &u3_agp_pci_ops;
hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev)
char* disp_name;
int *bus_range;
int primary = 1;
- struct property *of_prop;
+ struct property *of_prop;
DBG("Adding PCI host bridge %s\n", dev->full_name);
- 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, assume bus 0\n",
- dev->full_name);
- }
+ 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, assume bus 0\n",
+ dev->full_name);
+ }
hose = alloc_bootmem(sizeof(struct pci_controller));
if (hose == NULL)
return -ENOMEM;
- pci_setup_pci_controller(hose);
+ pci_setup_pci_controller(hose);
- hose->arch_data = dev;
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ hose->arch_data = dev;
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
of_prop = alloc_bootmem(sizeof(struct property) +
sizeof(hose->global_number));
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev)
}
disp_name = NULL;
- if (device_is_compatible(dev, "u3-agp")) {
- setup_u3_agp(hose);
- disp_name = "U3-AGP";
- primary = 0;
- } else if (device_is_compatible(dev, "u3-ht")) {
- setup_u3_ht(hose);
- disp_name = "U3-HT";
- primary = 1;
- }
- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
- disp_name, hose->first_busno, hose->last_busno);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev);
+ if (device_is_compatible(dev, "u3-agp")) {
+ setup_u3_agp(hose);
+ disp_name = "U3-AGP";
+ primary = 0;
+ } else if (device_is_compatible(dev, "u3-ht")) {
+ setup_u3_ht(hose);
+ disp_name = "U3-HT";
+ primary = 1;
+ }
+ printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+ disp_name, hose->first_busno, hose->last_busno);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pci_process_bridge_OF_ranges(hose, dev);
pci_setup_phb_io(hose, primary);
- /* Fixup "bus-range" OF property */
- fixup_bus_range(dev);
+ /* Fixup "bus-range" OF property */
+ fixup_bus_range(dev);
return 0;
}
@@ -447,9 +447,9 @@ void __init maple_pci_init(void)
*/
if (u3_agp) {
struct device_node *np = u3_agp->arch_data;
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
for (np = np->child; np; np = np->sibling)
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
}
/* Tell pci.c to use the common resource allocation mecanism */
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
index bb55b5a56910..fc0567498a3a 100644
--- a/arch/ppc64/kernel/maple_setup.c
+++ b/arch/ppc64/kernel/maple_setup.c
@@ -207,9 +207,6 @@ static void __init maple_init_early(void)
comport = (void *)ioremap(physport, 16);
udbg_init_uart(comport, default_speed);
- ppc_md.udbg_putc = udbg_putc;
- ppc_md.udbg_getc = udbg_getc;
- ppc_md.udbg_getc_poll = udbg_getc_poll;
DBG("Hello World !\n");
}
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index a05b50b738e9..e7241ad80a08 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -26,7 +26,7 @@
#include <asm/page.h>
#include <asm/cache.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cputable.h>
.text
@@ -183,7 +183,7 @@ PPC64_CACHES:
* flush all bytes from start through stop-1 inclusive
*/
-_GLOBAL(__flush_icache_range)
+_KPROBE(__flush_icache_range)
/*
* Flush the data cache to memory
@@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range)
bdnz 2b
isync
blr
-
+ .previous .text
/*
* Like above, but only do the D-cache.
*
@@ -680,6 +680,104 @@ _GLOBAL(kernel_thread)
ld r30,-16(r1)
blr
+/*
+ * disable_kernel_fp()
+ * Disable the FPU.
+ */
+_GLOBAL(disable_kernel_fp)
+ mfmsr r3
+ rldicl r0,r3,(63-MSR_FP_LG),1
+ rldicl r3,r0,(MSR_FP_LG+1),0
+ mtmsrd r3 /* disable use of fpu now */
+ isync
+ blr
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+_GLOBAL(giveup_fpu)
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ mtmsrd r5 /* enable use of fpu now */
+ isync
+ cmpdi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ ld r5,PT_REGS(r3)
+ cmpdi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR(r3)
+ beq 1f
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ ld r4,last_task_used_math@got(r2)
+ std r5,0(r4)
+#endif /* CONFIG_SMP */
+ blr
+
+#ifdef CONFIG_ALTIVEC
+
+#if 0 /* this has no callers for now */
+/*
+ * disable_kernel_altivec()
+ * Disable the VMX.
+ */
+_GLOBAL(disable_kernel_altivec)
+ mfmsr r3
+ rldicl r0,r3,(63-MSR_VEC_LG),1
+ rldicl r3,r0,(MSR_VEC_LG+1),0
+ mtmsrd r3 /* disable use of VMX now */
+ isync
+ blr
+#endif /* 0 */
+
+/*
+ * giveup_altivec(tsk)
+ * Disable VMX for the task given as the argument,
+ * and save the vector registers in its thread_struct.
+ * Enables the VMX for use in the kernel on return.
+ */
+_GLOBAL(giveup_altivec)
+ mfmsr r5
+ oris r5,r5,MSR_VEC@h
+ mtmsrd r5 /* enable use of VMX now */
+ isync
+ cmpdi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ ld r5,PT_REGS(r3)
+ cmpdi 0,r5,0
+ SAVE_32VRS(0,r4,r3)
+ mfvscr vr0
+ li r4,THREAD_VSCR
+ stvx vr0,r4,r3
+ beq 1f
+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r3,MSR_VEC@h
+ andc r4,r4,r3 /* disable FP for previous task */
+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ ld r4,last_task_used_altivec@got(r2)
+ std r5,0(r4)
+#endif /* CONFIG_SMP */
+ blr
+
+#endif /* CONFIG_ALTIVEC */
+
+_GLOBAL(__setup_cpu_power3)
+ blr
+
/* kexec_wait(phys_cpu)
*
* wait for the flag to change, indicating this kernel is going away but
@@ -859,7 +957,7 @@ _GLOBAL(sys_call_table32)
.llong .ppc_fork
.llong .sys_read
.llong .sys_write
- .llong .sys32_open /* 5 */
+ .llong .compat_sys_open /* 5 */
.llong .sys_close
.llong .sys32_waitpid
.llong .sys32_creat
@@ -1333,9 +1431,9 @@ _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* 195 - 32bit only stat64 */
.llong .sys_ni_syscall /* 32bit only lstat64 */
.llong .sys_ni_syscall /* 32bit only fstat64 */
- .llong .sys_ni_syscall /* 32bit only pciconfig_read */
- .llong .sys_ni_syscall /* 32bit only pciconfig_write */
- .llong .sys_ni_syscall /* 32bit only pciconfig_iobase */
+ .llong .sys_pciconfig_read
+ .llong .sys_pciconfig_write
+ .llong .sys_pciconfig_iobase /* 200 - pciconfig_iobase */
.llong .sys_ni_syscall /* reserved for MacOnLinux */
.llong .sys_getdents64
.llong .sys_pivot_root
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index b80e81984ba8..da580812ddfe 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -236,7 +236,6 @@ void of_device_unregister(struct of_device *ofdev)
struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
{
struct of_device *dev;
- u32 *reg;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -250,7 +249,6 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
dev->dev.bus = &of_platform_bus_type;
dev->dev.release = of_release_dev;
- reg = (u32 *)get_property(np, "reg", NULL);
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
if (of_device_register(dev) != 0) {
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 69130522a87e..f0fd7fbd6531 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -45,6 +45,7 @@
#include <asm/plpar_wrappers.h>
#include <asm/pSeries_reconfig.h>
#include <asm/systemcfg.h>
+#include <asm/firmware.h>
#include "pci.h"
#define DBG(fmt...)
@@ -294,7 +295,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct iommu_table *tbl,
unsigned int *dma_window)
{
- tbl->it_busno = dn->bussubno;
+ tbl->it_busno = PCI_DN(dn)->bussubno;
/* TODO: Parse field size properties properly. */
tbl->it_size = (((unsigned long)dma_window[4] << 32) |
@@ -310,6 +311,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
static void iommu_bus_setup_pSeries(struct pci_bus *bus)
{
struct device_node *dn, *pdn;
+ struct pci_dn *pci;
struct iommu_table *tbl;
DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
@@ -324,6 +326,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
*/
dn = pci_bus_to_OF_node(bus);
+ pci = dn->data;
if (!bus->self) {
/* Root bus */
@@ -340,18 +343,18 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
* alltogether. This leaves 768MB for the window.
*/
DBG("PHB has io-hole, reserving 256MB\n");
- dn->phb->dma_window_size = 3 << 28;
- dn->phb->dma_window_base_cur = 1 << 28;
+ pci->phb->dma_window_size = 3 << 28;
+ pci->phb->dma_window_base_cur = 1 << 28;
} else {
/* 1GB window by default */
- dn->phb->dma_window_size = 1 << 30;
- dn->phb->dma_window_base_cur = 0;
+ pci->phb->dma_window_size = 1 << 30;
+ pci->phb->dma_window_base_cur = 0;
}
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
+ pci->iommu_table = iommu_init_table(tbl);
} else {
/* Do a 128MB table at root. This is used for the IDE
* controller on some SMP-mode POWER4 machines. It
@@ -362,16 +365,16 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
* Allocate at offset 128MB to avoid having to deal
* with ISA holes; 128MB table for IDE is plenty.
*/
- dn->phb->dma_window_size = 1 << 27;
- dn->phb->dma_window_base_cur = 1 << 27;
+ pci->phb->dma_window_size = 1 << 27;
+ pci->phb->dma_window_base_cur = 1 << 27;
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
+ pci->iommu_table = iommu_init_table(tbl);
/* All child buses have 256MB tables */
- dn->phb->dma_window_size = 1 << 28;
+ pci->phb->dma_window_size = 1 << 28;
}
} else {
pdn = pci_bus_to_OF_node(bus->parent);
@@ -385,12 +388,12 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_setparms(dn->phb, dn, tbl);
+ iommu_table_setparms(pci->phb, dn, tbl);
- dn->iommu_table = iommu_init_table(tbl);
+ pci->iommu_table = iommu_init_table(tbl);
} else {
/* Lower than first child or under python, use parent table */
- dn->iommu_table = pdn->iommu_table;
+ pci->iommu_table = PCI_DN(pdn)->iommu_table;
}
}
}
@@ -400,6 +403,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
{
struct iommu_table *tbl;
struct device_node *dn, *pdn;
+ struct pci_dn *ppci;
unsigned int *dma_window = NULL;
DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
@@ -418,22 +422,24 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
return;
}
- if (!pdn->iommu_table) {
+ ppci = pdn->data;
+ if (!ppci->iommu_table) {
/* Bussubno hasn't been copied yet.
* Do it now because iommu_table_setparms_lpar needs it.
*/
- pdn->bussubno = bus->number;
+
+ ppci->bussubno = bus->number;
tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
GFP_KERNEL);
- iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
- pdn->iommu_table = iommu_init_table(tbl);
+ ppci->iommu_table = iommu_init_table(tbl);
}
if (pdn != dn)
- dn->iommu_table = pdn->iommu_table;
+ PCI_DN(dn)->iommu_table = ppci->iommu_table;
}
@@ -448,11 +454,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
*/
mydn = dn = pci_device_to_OF_node(dev);
- while (dn && dn->iommu_table == NULL)
+ while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
dn = dn->parent;
- if (dn) {
- mydn->iommu_table = dn->iommu_table;
+ if (dn && dn->data) {
+ PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
} else {
DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name);
}
@@ -462,10 +468,11 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
{
int err = NOTIFY_OK;
struct device_node *np = node;
+ struct pci_dn *pci = np->data;
switch (action) {
case PSERIES_RECONFIG_REMOVE:
- if (np->iommu_table &&
+ if (pci->iommu_table &&
get_property(np, "ibm,dma-window", NULL))
iommu_free_table(np);
break;
@@ -485,6 +492,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
struct device_node *pdn, *dn;
struct iommu_table *tbl;
int *dma_window = NULL;
+ struct pci_dn *pci;
DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
@@ -496,8 +504,10 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
*/
dn = pci_device_to_OF_node(dev);
- for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) {
- dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+ for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+ pdn = pdn->parent) {
+ dma_window = (unsigned int *)
+ get_property(pdn, "ibm,dma-window", NULL);
if (dma_window)
break;
}
@@ -514,20 +524,21 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
DBG("Found DMA window, allocating table\n");
}
- if (!pdn->iommu_table) {
+ pci = pdn->data;
+ if (!pci->iommu_table) {
/* iommu_table_setparms_lpar needs bussubno. */
- pdn->bussubno = pdn->phb->bus->number;
+ pci->bussubno = pci->phb->bus->number;
tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
GFP_KERNEL);
- iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+ iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
- pdn->iommu_table = iommu_init_table(tbl);
+ pci->iommu_table = iommu_init_table(tbl);
}
if (pdn != dn)
- dn->iommu_table = pdn->iommu_table;
+ PCI_DN(dn)->iommu_table = pci->iommu_table;
}
static void iommu_bus_setup_null(struct pci_bus *b) { }
@@ -546,7 +557,7 @@ void iommu_init_early_pSeries(void)
}
if (systemcfg->platform & PLATFORM_LPAR) {
- if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {
+ if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
ppc_md.tce_build = tce_buildmulti_pSeriesLP;
ppc_md.tce_free = tce_freemulti_pSeriesLP;
} else {
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index 74dd144dcce8..a6de83f2078f 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -52,7 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_4out);
EXPORT_SYMBOL(plpar_hcall_norets);
EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-extern void fw_feature_init(void);
extern void pSeries_find_serial_port(void);
@@ -193,9 +192,9 @@ static unsigned char udbg_getcLP(void)
void udbg_init_debug_lpar(void)
{
vtermno = 0;
- ppc_md.udbg_putc = udbg_putcLP;
- ppc_md.udbg_getc = udbg_getcLP;
- ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+ udbg_putc = udbg_putcLP;
+ udbg_getc = udbg_getcLP;
+ udbg_getc_poll = udbg_getc_pollLP;
}
/* returns 0 if couldn't find or use /chosen/stdout as console */
@@ -228,18 +227,18 @@ int find_udbg_vterm(void)
termno = (u32 *)get_property(stdout_node, "reg", NULL);
if (termno) {
vtermno = termno[0];
- ppc_md.udbg_putc = udbg_putcLP;
- ppc_md.udbg_getc = udbg_getcLP;
- ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+ udbg_putc = udbg_putcLP;
+ udbg_getc = udbg_getcLP;
+ udbg_getc_poll = udbg_getc_pollLP;
found = 1;
}
} else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
termno = (u32 *)get_property(stdout_node, "reg", NULL);
if (termno) {
vtermno = termno[0];
- ppc_md.udbg_putc = udbg_hvsi_putc;
- ppc_md.udbg_getc = udbg_hvsi_getc;
- ppc_md.udbg_getc_poll = udbg_hvsi_getc_poll;
+ udbg_putc = udbg_hvsi_putc;
+ udbg_getc = udbg_hvsi_getc;
+ udbg_getc_poll = udbg_hvsi_getc_poll;
found = 1;
}
}
@@ -267,6 +266,10 @@ void vpa_init(int cpu)
/* Register the Virtual Processor Area (VPA) */
flags = 1UL << (63 - 18);
+
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ paca[cpu].lppaca.vmxregs_in_use = 1;
+
ret = register_vpa(flags, hwcpu, __pa(vpa));
if (ret)
@@ -279,7 +282,6 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
unsigned long vflags, unsigned long rflags)
{
- unsigned long arpn = physRpn_to_absRpn(prpn);
unsigned long lpar_rc;
unsigned long flags;
unsigned long slot;
@@ -290,7 +292,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
if (vflags & HPTE_V_LARGE)
hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
- hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
+ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
/* Now fill in the actual HPTE */
/* Set CEC cookie to 0 */
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c
index dc2a69d412a2..58c61219d08e 100644
--- a/arch/ppc64/kernel/pSeries_reconfig.c
+++ b/arch/ppc64/kernel/pSeries_reconfig.c
@@ -111,7 +111,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
struct device_node *np;
int err = -ENOMEM;
- np = kcalloc(1, sizeof(*np), GFP_KERNEL);
+ np = kzalloc(sizeof(*np), GFP_KERNEL);
if (!np)
goto out_err;
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 5bec956e44a0..3009701eb90d 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -37,7 +37,7 @@
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/pci.h>
-#include <linux/version.h>
+#include <linux/utsname.h>
#include <linux/adb.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -60,7 +60,8 @@
#include <asm/nvram.h>
#include <asm/plpar_wrappers.h>
#include <asm/xics.h>
-#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/pmc.h>
#include "i8259.h"
#include "mpic.h"
@@ -187,6 +188,21 @@ static void __init pSeries_setup_mpic(void)
" MPIC ");
}
+static void pseries_lpar_enable_pmcs(void)
+{
+ unsigned long set, reset;
+
+ power4_enable_pmcs();
+
+ set = 1UL << 63;
+ reset = 0;
+ plpar_hcall_norets(H_PERFMON, set, reset);
+
+ /* instruct hypervisor to maintain PMCs */
+ if (firmware_has_feature(FW_FEATURE_SPLPAR))
+ get_paca()->lppaca.pmcregs_in_use = 1;
+}
+
static void __init pSeries_setup_arch(void)
{
/* Fixup ppc_md depending on the type of interrupt controller */
@@ -222,8 +238,8 @@ static void __init pSeries_setup_arch(void)
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
- eeh_init();
find_and_init_phbs();
+ eeh_init();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
@@ -231,11 +247,9 @@ static void __init pSeries_setup_arch(void)
pSeries_nvram_init();
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
- vpa_init(boot_cpuid);
-
/* Choose an idle loop */
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+ vpa_init(boot_cpuid);
if (get_paca()->lppaca.shared_proc) {
printk(KERN_INFO "Using shared processor idle loop\n");
ppc_md.idle_loop = pseries_shared_idle;
@@ -247,24 +261,29 @@ static void __init pSeries_setup_arch(void)
printk(KERN_INFO "Using default idle loop\n");
ppc_md.idle_loop = default_idle;
}
+
+ if (systemcfg->platform & PLATFORM_LPAR)
+ ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
+ else
+ ppc_md.enable_pmcs = power4_enable_pmcs;
}
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(UTS_RELEASE, 0);
+ ppc_md.progress(system_utsname.version, 0);
return 0;
}
arch_initcall(pSeries_init_panel);
-/* Build up the firmware_features bitmask field
+/* Build up the ppc64_firmware_features bitmask field
* using contents of device-tree/ibm,hypertas-functions.
* Ultimately this functionality may be moved into prom.c prom_init().
*/
-void __init fw_feature_init(void)
+static void __init fw_feature_init(void)
{
struct device_node * dn;
char * hypertas;
@@ -272,7 +291,7 @@ void __init fw_feature_init(void)
DBG(" -> fw_feature_init()\n");
- cur_cpu_spec->firmware_features = 0;
+ ppc64_firmware_features = 0;
dn = of_find_node_by_path("/rtas");
if (dn == NULL) {
printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
@@ -288,7 +307,7 @@ void __init fw_feature_init(void)
if ((firmware_features_table[i].name) &&
(strcmp(firmware_features_table[i].name,hypertas))==0) {
/* we have a match */
- cur_cpu_spec->firmware_features |=
+ ppc64_firmware_features |=
(firmware_features_table[i].val);
break;
}
@@ -302,7 +321,7 @@ void __init fw_feature_init(void)
of_node_put(dn);
no_rtas:
printk(KERN_INFO "firmware_features = 0x%lx\n",
- cur_cpu_spec->firmware_features);
+ ppc64_firmware_features);
DBG(" <- fw_feature_init()\n");
}
@@ -378,9 +397,6 @@ static void __init pSeries_init_early(void)
comport = (void *)ioremap(physport, 16);
udbg_init_uart(comport, default_speed);
- ppc_md.udbg_putc = udbg_putc;
- ppc_md.udbg_getc = udbg_getc;
- ppc_md.udbg_getc_poll = udbg_getc_poll;
DBG("Hello World !\n");
}
@@ -574,6 +590,13 @@ static int pseries_shared_idle(void)
return 0;
}
+static int pSeries_pci_probe_mode(struct pci_bus *bus)
+{
+ if (systemcfg->platform & PLATFORM_LPAR)
+ return PCI_PROBE_DEVTREE;
+ return PCI_PROBE_NORMAL;
+}
+
struct machdep_calls __initdata pSeries_md = {
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
@@ -581,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = {
.get_cpuinfo = pSeries_get_cpuinfo,
.log_error = pSeries_log_error,
.pcibios_fixup = pSeries_final_fixup,
+ .pci_probe_mode = pSeries_pci_probe_mode,
.irq_bus_setup = pSeries_irq_bus_setup,
.restart = rtas_restart,
.power_off = rtas_power_off,
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 62c55a123560..d2c7e2c4733b 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -41,6 +41,7 @@
#include <asm/machdep.h>
#include <asm/xics.h>
#include <asm/cputable.h>
+#include <asm/firmware.h>
#include <asm/system.h>
#include <asm/rtas.h>
#include <asm/plpar_wrappers.h>
@@ -271,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
unsigned long start_here = __pa((u32)*((unsigned long *)
pSeries_secondary_smp_init));
unsigned int pcpu;
+ int start_cpu;
if (cpu_isset(lcpu, of_spin_map))
/* Already started by OF and sitting in spin loop */
@@ -281,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
/* Fixup atomic count: it exited inside IRQ handler. */
paca[lcpu].__current->thread_info->preempt_count = 0;
- status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
- pcpu, start_here, lcpu);
+ /*
+ * If the RTAS start-cpu token does not exist then presume the
+ * cpu is already spinning.
+ */
+ start_cpu = rtas_token("start-cpu");
+ if (start_cpu == RTAS_UNKNOWN_SERVICE)
+ return 1;
+
+ status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
if (status != 0) {
printk(KERN_ERR "start-cpu failed: %i\n", status);
return 0;
}
+
return 1;
}
@@ -326,7 +336,7 @@ static void __devinit smp_xics_setup_cpu(int cpu)
if (cpu != boot_cpuid)
xics_setup_cpu();
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+ if (firmware_has_feature(FW_FEATURE_SPLPAR))
vpa_init(cpu);
cpu_clear(cpu, of_spin_map);
diff --git a/arch/ppc64/kernel/pSeries_vio.c b/arch/ppc64/kernel/pSeries_vio.c
new file mode 100644
index 000000000000..e0ae06f58f86
--- /dev/null
+++ b/arch/ppc64/kernel/pSeries_vio.c
@@ -0,0 +1,273 @@
+/*
+ * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
+ *
+ * Copyright (c) 2003-2005 IBM Corp.
+ * Dave Engebretsen engebret@us.ibm.com
+ * Santiago Leon santil@us.ibm.com
+ * Hollis Blanchard <hollisb@us.ibm.com>
+ * Stephen Rothwell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/kobject.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/prom.h>
+#include <asm/vio.h>
+#include <asm/hvcall.h>
+
+extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+
+static void probe_bus_pseries(void)
+{
+ struct device_node *node_vroot, *of_node;
+
+ node_vroot = find_devices("vdevice");
+ if ((node_vroot == NULL) || (node_vroot->child == NULL))
+ /* this machine doesn't do virtual IO, and that's ok */
+ return;
+
+ /*
+ * Create struct vio_devices for each virtual device in the device tree.
+ * Drivers will associate with them later.
+ */
+ for (of_node = node_vroot->child; of_node != NULL;
+ of_node = of_node->sibling) {
+ printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
+ vio_register_device_node(of_node);
+ }
+}
+
+/**
+ * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
+ * vio_device_id
+ */
+static int vio_match_device_pseries(const struct vio_device_id *id,
+ const struct vio_dev *dev)
+{
+ return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
+ device_is_compatible(dev->dev.platform_data, id->compat);
+}
+
+static void vio_release_device_pseries(struct device *dev)
+{
+ /* XXX free TCE table */
+ of_node_put(dev->platform_data);
+}
+
+static ssize_t viodev_show_devspec(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct device_node *of_node = dev->platform_data;
+
+ return sprintf(buf, "%s\n", of_node->full_name);
+}
+DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
+
+static void vio_unregister_device_pseries(struct vio_dev *viodev)
+{
+ device_remove_file(&viodev->dev, &dev_attr_devspec);
+}
+
+static struct vio_bus_ops vio_bus_ops_pseries = {
+ .match = vio_match_device_pseries,
+ .unregister_device = vio_unregister_device_pseries,
+ .release_device = vio_release_device_pseries,
+};
+
+/**
+ * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
+ */
+static int __init vio_bus_init_pseries(void)
+{
+ int err;
+
+ err = vio_bus_init(&vio_bus_ops_pseries);
+ if (err == 0)
+ probe_bus_pseries();
+ return err;
+}
+
+__initcall(vio_bus_init_pseries);
+
+/**
+ * vio_build_iommu_table: - gets the dma information from OF and
+ * builds the TCE tree.
+ * @dev: the virtual device.
+ *
+ * Returns a pointer to the built tce tree, or NULL if it can't
+ * find property.
+*/
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+ unsigned int *dma_window;
+ struct iommu_table *newTceTable;
+ unsigned long offset;
+ int dma_window_property_size;
+
+ dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
+ if(!dma_window) {
+ return NULL;
+ }
+
+ newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+
+ /* There should be some code to extract the phys-encoded offset
+ using prom_n_addr_cells(). However, according to a comment
+ on earlier versions, it's always zero, so we don't bother */
+ offset = dma_window[1] >> PAGE_SHIFT;
+
+ /* TCE table size - measured in tce entries */
+ newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
+ /* offset for VIO should always be 0 */
+ newTceTable->it_offset = offset;
+ newTceTable->it_busno = 0;
+ newTceTable->it_index = (unsigned long)dma_window[0];
+ newTceTable->it_type = TCE_VB;
+
+ return iommu_init_table(newTceTable);
+}
+
+/**
+ * vio_register_device_node: - Register a new vio device.
+ * @of_node: The OF node for this device.
+ *
+ * Creates and initializes a vio_dev structure from the data in
+ * of_node (dev.platform_data) and adds it to the list of virtual devices.
+ * Returns a pointer to the created vio_dev or NULL if node has
+ * NULL device_type or compatible fields.
+ */
+struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
+{
+ struct vio_dev *viodev;
+ unsigned int *unit_address;
+ unsigned int *irq_p;
+
+ /* we need the 'device_type' property, in order to match with drivers */
+ if ((NULL == of_node->type)) {
+ printk(KERN_WARNING
+ "%s: node %s missing 'device_type'\n", __FUNCTION__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
+ }
+
+ unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
+ if (!unit_address) {
+ printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
+ }
+
+ /* allocate a vio_dev for this node */
+ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+ if (!viodev) {
+ return NULL;
+ }
+ memset(viodev, 0, sizeof(struct vio_dev));
+
+ viodev->dev.platform_data = of_node_get(of_node);
+
+ viodev->irq = NO_IRQ;
+ irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
+ if (irq_p) {
+ int virq = virt_irq_create_mapping(*irq_p);
+ if (virq == NO_IRQ) {
+ printk(KERN_ERR "Unable to allocate interrupt "
+ "number for %s\n", of_node->full_name);
+ } else
+ viodev->irq = irq_offset_up(virq);
+ }
+
+ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+ viodev->name = of_node->name;
+ viodev->type = of_node->type;
+ viodev->unit_address = *unit_address;
+ viodev->iommu_table = vio_build_iommu_table(viodev);
+
+ /* register with generic device framework */
+ if (vio_register_device(viodev) == NULL) {
+ /* XXX free TCE table */
+ kfree(viodev);
+ return NULL;
+ }
+ device_create_file(&viodev->dev, &dev_attr_devspec);
+
+ return viodev;
+}
+EXPORT_SYMBOL(vio_register_device_node);
+
+/**
+ * vio_get_attribute: - get attribute for virtual device
+ * @vdev: The vio device to get property.
+ * @which: The property/attribute to be extracted.
+ * @length: Pointer to length of returned data size (unused if NULL).
+ *
+ * Calls prom.c's get_property() to return the value of the
+ * attribute specified by the preprocessor constant @which
+*/
+const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
+{
+ return get_property(vdev->dev.platform_data, (char*)which, length);
+}
+EXPORT_SYMBOL(vio_get_attribute);
+
+/* vio_find_name() - internal because only vio.c knows how we formatted the
+ * kobject name
+ * XXX once vio_bus_type.devices is actually used as a kset in
+ * drivers/base/bus.c, this function should be removed in favor of
+ * "device_find(kobj_name, &vio_bus_type)"
+ */
+static struct vio_dev *vio_find_name(const char *kobj_name)
+{
+ struct kobject *found;
+
+ found = kset_find_obj(&devices_subsys.kset, kobj_name);
+ if (!found)
+ return NULL;
+
+ return to_vio_dev(container_of(found, struct device, kobj));
+}
+
+/**
+ * vio_find_node - find an already-registered vio_dev
+ * @vnode: device_node of the virtual device we're looking for
+ */
+struct vio_dev *vio_find_node(struct device_node *vnode)
+{
+ uint32_t *unit_address;
+ char kobj_name[BUS_ID_SIZE];
+
+ /* construct the kobject name from the device node */
+ unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
+ if (!unit_address)
+ return NULL;
+ snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+
+ return vio_find_name(kobj_name);
+}
+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)
+ printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+ return rc;
+}
+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)
+ printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+ return rc;
+}
+EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 6316188737b6..33a2d8db3f21 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -59,6 +59,7 @@ extern unsigned long __toc_start;
.fpregs_in_use = 1, \
.end_of_quantum = 0xfffffffffffffffful, \
.slb_count = 64, \
+ .vmxregs_in_use = 0, \
}, \
#ifdef CONFIG_PPC_ISERIES
@@ -78,7 +79,7 @@ extern unsigned long __toc_start;
#define BOOTCPU_PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 1, 0, STAB0_VIRT_ADDR) \
+ PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
PACA_INIT_ISERIES(number) \
}
@@ -90,7 +91,7 @@ extern unsigned long __toc_start;
#define BOOTCPU_PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR) \
+ PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
}
#endif
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index d0d55c7908ef..861138ad092c 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -21,6 +21,7 @@
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/list.h>
+#include <linux/syscalls.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -50,6 +51,10 @@ unsigned long io_page_mask;
EXPORT_SYMBOL(io_page_mask);
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static void fixup_resource(struct resource *res, struct pci_dev *dev);
+static void do_bus_setup(struct pci_bus *bus);
+#endif
unsigned int pcibios_assign_all_busses(void)
{
@@ -84,7 +89,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev)
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
dev->vendor = PCI_VENDOR_ID_AMD;
pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
- pci_name_device(dev);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void)
}
#endif
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
+{
+ u32 *prop;
+ int len;
+
+ prop = (u32 *) get_property(np, name, &len);
+ if (prop && len >= 4)
+ return *prop;
+ return def;
+}
+
+static unsigned int pci_parse_of_flags(u32 addr0)
+{
+ unsigned int flags = 0;
+
+ if (addr0 & 0x02000000) {
+ flags |= IORESOURCE_MEM;
+ if (addr0 & 0x40000000)
+ flags |= IORESOURCE_PREFETCH;
+ } else if (addr0 & 0x01000000)
+ flags |= IORESOURCE_IO;
+ return flags;
+}
+
+#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
+
+static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
+{
+ u64 base, size;
+ unsigned int flags;
+ struct resource *res;
+ u32 *addrs, i;
+ int proplen;
+
+ addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
+ if (!addrs)
+ return;
+ for (; proplen >= 20; proplen -= 20, addrs += 5) {
+ flags = pci_parse_of_flags(addrs[0]);
+ if (!flags)
+ continue;
+ base = GET_64BIT(addrs, 1);
+ size = GET_64BIT(addrs, 3);
+ if (!size)
+ continue;
+ i = addrs[0] & 0xff;
+ if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
+ res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
+ } else if (i == dev->rom_base_reg) {
+ res = &dev->resource[PCI_ROM_RESOURCE];
+ flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+ } else {
+ printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
+ continue;
+ }
+ res->start = base;
+ res->end = base + size - 1;
+ res->flags = flags;
+ res->name = pci_name(dev);
+ fixup_resource(res, dev);
+ }
+}
+
+static struct pci_dev *of_create_pci_dev(struct device_node *node,
+ struct pci_bus *bus, int devfn)
+{
+ struct pci_dev *dev;
+ const char *type;
+
+ dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+ type = get_property(node, "device_type", NULL);
+ if (type == NULL)
+ type = "";
+
+ memset(dev, 0, sizeof(struct pci_dev));
+ dev->bus = bus;
+ dev->sysdata = node;
+ dev->dev.parent = bus->bridge;
+ dev->dev.bus = &pci_bus_type;
+ dev->devfn = devfn;
+ dev->multifunction = 0; /* maybe a lie? */
+
+ dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
+ dev->device = get_int_prop(node, "device-id", 0xffff);
+ dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
+ dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
+
+ dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+
+ sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ dev->class = get_int_prop(node, "class-code", 0);
+
+ dev->current_state = 4; /* unknown power state */
+
+ if (!strcmp(type, "pci")) {
+ /* a PCI-PCI bridge */
+ dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+ dev->rom_base_reg = PCI_ROM_ADDRESS1;
+ } else if (!strcmp(type, "cardbus")) {
+ dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+ } else {
+ dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+ dev->rom_base_reg = PCI_ROM_ADDRESS;
+ dev->irq = NO_IRQ;
+ if (node->n_intrs > 0) {
+ dev->irq = node->intrs[0].line;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ dev->irq);
+ }
+ }
+
+ pci_parse_of_addrs(node, dev);
+
+ pci_device_add(dev, bus);
+
+ /* XXX pci_scan_msi_device(dev); */
+
+ return dev;
+}
+
+static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev);
+
+static void __devinit of_scan_bus(struct device_node *node,
+ struct pci_bus *bus)
+{
+ struct device_node *child = NULL;
+ u32 *reg;
+ int reglen, devfn;
+ struct pci_dev *dev;
+
+ while ((child = of_get_next_child(node, child)) != NULL) {
+ reg = (u32 *) get_property(child, "reg", &reglen);
+ if (reg == NULL || reglen < 20)
+ continue;
+ devfn = (reg[0] >> 8) & 0xff;
+ /* create a new pci_dev for this device */
+ dev = of_create_pci_dev(child, bus, devfn);
+ if (!dev)
+ continue;
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ of_scan_pci_bridge(child, dev);
+ }
+
+ do_bus_setup(bus);
+}
+
+static void __devinit of_scan_pci_bridge(struct device_node *node,
+ struct pci_dev *dev)
+{
+ struct pci_bus *bus;
+ u32 *busrange, *ranges;
+ int len, i, mode;
+ struct resource *res;
+ unsigned int flags;
+ u64 size;
+
+ /* parse bus-range property */
+ busrange = (u32 *) get_property(node, "bus-range", &len);
+ if (busrange == NULL || len != 8) {
+ printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+ node->full_name);
+ return;
+ }
+ ranges = (u32 *) get_property(node, "ranges", &len);
+ if (ranges == NULL) {
+ printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+ node->full_name);
+ return;
+ }
+
+ bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+ if (!bus) {
+ printk(KERN_ERR "Failed to create pci bus for %s\n",
+ node->full_name);
+ return;
+ }
+
+ bus->primary = dev->bus->number;
+ bus->subordinate = busrange[1];
+ bus->bridge_ctl = 0;
+ bus->sysdata = node;
+
+ /* parse ranges property */
+ /* PCI #address-cells == 3 and #size-cells == 2 always */
+ res = &dev->resource[PCI_BRIDGE_RESOURCES];
+ for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) {
+ res->flags = 0;
+ bus->resource[i] = res;
+ ++res;
+ }
+ i = 1;
+ for (; len >= 32; len -= 32, ranges += 8) {
+ flags = pci_parse_of_flags(ranges[0]);
+ size = GET_64BIT(ranges, 6);
+ if (flags == 0 || size == 0)
+ continue;
+ if (flags & IORESOURCE_IO) {
+ res = bus->resource[0];
+ if (res->flags) {
+ printk(KERN_ERR "PCI: ignoring extra I/O range"
+ " for bridge %s\n", node->full_name);
+ continue;
+ }
+ } else {
+ if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
+ printk(KERN_ERR "PCI: too many memory ranges"
+ " for bridge %s\n", node->full_name);
+ continue;
+ }
+ res = bus->resource[i];
+ ++i;
+ }
+ res->start = GET_64BIT(ranges, 1);
+ res->end = res->start + size - 1;
+ res->flags = flags;
+ fixup_resource(res, dev);
+ }
+ sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
+ bus->number);
+
+ mode = PCI_PROBE_NORMAL;
+ if (ppc_md.pci_probe_mode)
+ mode = ppc_md.pci_probe_mode(bus);
+ if (mode == PCI_PROBE_DEVTREE)
+ of_scan_bus(node, bus);
+ else if (mode == PCI_PROBE_NORMAL)
+ pci_scan_child_bus(bus);
+}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+static void __devinit scan_phb(struct pci_controller *hose)
+{
+ struct pci_bus *bus;
+ struct device_node *node = hose->arch_data;
+ int i, mode;
+ struct resource *res;
+
+ bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
+ if (bus == NULL) {
+ printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+ hose->global_number);
+ return;
+ }
+ bus->secondary = hose->first_busno;
+ hose->bus = bus;
+
+ bus->resource[0] = res = &hose->io_resource;
+ if (res->flags && request_resource(&ioport_resource, res))
+ printk(KERN_ERR "Failed to request PCI IO region "
+ "on PCI domain %04x\n", hose->global_number);
+
+ for (i = 0; i < 3; ++i) {
+ res = &hose->mem_resources[i];
+ bus->resource[i+1] = res;
+ if (res->flags && request_resource(&iomem_resource, res))
+ printk(KERN_ERR "Failed to request PCI memory region "
+ "on PCI domain %04x\n", hose->global_number);
+ }
+
+ mode = PCI_PROBE_NORMAL;
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ if (ppc_md.pci_probe_mode)
+ mode = ppc_md.pci_probe_mode(bus);
+ if (mode == PCI_PROBE_DEVTREE) {
+ bus->subordinate = hose->last_busno;
+ of_scan_bus(node, bus);
+ }
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+ if (mode == PCI_PROBE_NORMAL)
+ hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+ pci_bus_add_devices(bus);
+}
+
static int __init pcibios_init(void)
{
struct pci_controller *hose, *tmp;
- struct pci_bus *bus;
/* For now, override phys_mem_access_prot. If we need it,
* later, we may move that initialization to each ppc_md
@@ -242,13 +523,8 @@ static int __init pcibios_init(void)
printk("PCI: Probing PCI hardware\n");
/* Scan all of the recorded PCI controllers. */
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- hose->last_busno = 0xff;
- bus = pci_scan_bus(hose->first_busno, hose->ops,
- hose->arch_data);
- hose->bus = bus;
- hose->last_busno = bus->subordinate;
- }
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ scan_phb(hose);
#ifndef CONFIG_PPC_ISERIES
if (pci_probe_only)
@@ -820,118 +1096,89 @@ void phbs_remap_io(void)
/*
* ppc64 can have multifunction devices that do not respond to function 0.
* In this case we must scan all functions.
+ * XXX this can go now, we use the OF device tree in all the
+ * cases that caused problems. -- paulus
*/
int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
{
- struct device_node *busdn, *dn;
+ return 0;
+}
+
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ unsigned long start, end, mask, offset;
- if (bus->self)
- busdn = pci_device_to_OF_node(bus->self);
- else
- busdn = bus->sysdata; /* must be a phb */
+ if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long)hose->io_base_virt - pci_io_base;
- if (busdn == NULL)
- return 0;
+ start = res->start += offset;
+ end = res->end += offset;
- /*
- * Check to see if there is any of the 8 functions are in the
- * device tree. If they are then we need to scan all the
- * functions of this slot.
- */
- for (dn = busdn->child; dn; dn = dn->sibling)
- if ((dn->devfn >> 3) == (devfn >> 3))
- return 1;
+ /* Need to allow IO access to pages that are in the
+ ISA range */
+ if (start < MAX_ISA_PORT) {
+ if (end > MAX_ISA_PORT)
+ end = MAX_ISA_PORT;
- return 0;
-}
+ start >>= PAGE_SHIFT;
+ end >>= PAGE_SHIFT;
+ /* get the range of pages for the map */
+ mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
+ io_page_mask |= mask;
+ }
+ } else if (res->flags & IORESOURCE_MEM) {
+ res->start += hose->pci_mem_offset;
+ res->end += hose->pci_mem_offset;
+ }
+}
void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
- struct pci_bus *bus)
+ struct pci_bus *bus)
{
/* Update device resources. */
- struct pci_controller *hose = pci_bus_to_host(bus);
int i;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- if (dev->resource[i].flags & IORESOURCE_IO) {
- unsigned long offset = (unsigned long)hose->io_base_virt
- - pci_io_base;
- unsigned long start, end, mask;
-
- start = dev->resource[i].start += offset;
- end = dev->resource[i].end += offset;
-
- /* Need to allow IO access to pages that are in the
- ISA range */
- if (start < MAX_ISA_PORT) {
- if (end > MAX_ISA_PORT)
- end = MAX_ISA_PORT;
-
- start >>= PAGE_SHIFT;
- end >>= PAGE_SHIFT;
-
- /* get the range of pages for the map */
- mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
- io_page_mask |= mask;
- }
- }
- else if (dev->resource[i].flags & IORESOURCE_MEM) {
- dev->resource[i].start += hose->pci_mem_offset;
- dev->resource[i].end += hose->pci_mem_offset;
- }
- }
+ for (i = 0; i < PCI_NUM_RESOURCES; i++)
+ if (dev->resource[i].flags)
+ fixup_resource(&dev->resource[i], dev);
}
EXPORT_SYMBOL(pcibios_fixup_device_resources);
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+static void __devinit do_bus_setup(struct pci_bus *bus)
{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct pci_dev *dev = bus->self;
- struct resource *res;
- int i;
+ struct pci_dev *dev;
- if (!dev) {
- /* Root bus. */
+ ppc_md.iommu_bus_setup(bus);
- hose->bus = bus;
- bus->resource[0] = res = &hose->io_resource;
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ ppc_md.iommu_dev_setup(dev);
- if (res->flags && request_resource(&ioport_resource, res))
- printk(KERN_ERR "Failed to request IO on "
- "PCI domain %d\n", pci_domain_nr(bus));
+ if (ppc_md.irq_bus_setup)
+ ppc_md.irq_bus_setup(bus);
+}
- for (i = 0; i < 3; ++i) {
- res = &hose->mem_resources[i];
- bus->resource[i+1] = res;
- if (res->flags && request_resource(&iomem_resource, res))
- printk(KERN_ERR "Failed to request MEM on "
- "PCI domain %d\n",
- pci_domain_nr(bus));
- }
- } else if (pci_probe_only &&
- (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev = bus->self;
+
+ if (dev && pci_probe_only &&
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
/* This is a subordinate bridge */
pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus);
}
- ppc_md.iommu_bus_setup(bus);
-
- list_for_each_entry(dev, &bus->devices, bus_list)
- ppc_md.iommu_dev_setup(dev);
-
- if (ppc_md.irq_bus_setup)
- ppc_md.irq_bus_setup(bus);
+ do_bus_setup(bus);
if (!pci_probe_only)
return;
- list_for_each_entry(dev, &bus->devices, bus_list) {
+ list_for_each_entry(dev, &bus->devices, bus_list)
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
pcibios_fixup_device_resources(dev, bus);
- }
}
EXPORT_SYMBOL(pcibios_fixup_bus);
@@ -983,3 +1230,62 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
}
#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+
+#define IOBASE_BRIDGE_NUMBER 0
+#define IOBASE_MEMORY 1
+#define IOBASE_IO 2
+#define IOBASE_ISA_IO 3
+#define IOBASE_ISA_MEM 4
+
+long sys_pciconfig_iobase(long which, unsigned long in_bus,
+ unsigned long in_devfn)
+{
+ struct pci_controller* hose;
+ struct list_head *ln;
+ struct pci_bus *bus = NULL;
+ struct device_node *hose_node;
+
+ /* Argh ! Please forgive me for that hack, but that's the
+ * simplest way to get existing XFree to not lockup on some
+ * G5 machines... So when something asks for bus 0 io base
+ * (bus 0 is HT root), we return the AGP one instead.
+ */
+#ifdef CONFIG_PPC_PMAC
+ if (systemcfg->platform == PLATFORM_POWERMAC &&
+ machine_is_compatible("MacRISC4"))
+ if (in_bus == 0)
+ in_bus = 0xf0;
+#endif /* CONFIG_PPC_PMAC */
+
+ /* That syscall isn't quite compatible with PCI domains, but it's
+ * used on pre-domains setup. We return the first match
+ */
+
+ for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
+ bus = pci_bus_b(ln);
+ if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
+ break;
+ bus = NULL;
+ }
+ if (bus == NULL || bus->sysdata == NULL)
+ return -ENODEV;
+
+ hose_node = (struct device_node *)bus->sysdata;
+ hose = PCI_DN(hose_node)->phb;
+
+ switch (which) {
+ case IOBASE_BRIDGE_NUMBER:
+ return (long)hose->first_busno;
+ case IOBASE_MEMORY:
+ return (long)hose->pci_mem_offset;
+ case IOBASE_IO:
+ return (long)hose->io_base_phys;
+ case IOBASE_ISA_IO:
+ return (long)isa_io_base;
+ case IOBASE_ISA_MEM:
+ return -EINVAL;
+ }
+
+ return -EOPNOTSUPP;
+}
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 26be78b13af1..5eb2cc320566 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -34,7 +34,6 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void pci_devs_phb_init(void);
void pci_devs_phb_init_dynamic(struct pci_controller *phb);
-struct device_node *fetch_dev_dn(struct pci_dev *dev);
/* PCI address cache management routines */
void pci_addr_cache_insert_device(struct pci_dev *dev);
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
index ec345462afc3..a86389d07d57 100644
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -23,6 +23,8 @@
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -40,16 +42,26 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
struct pci_controller *phb = data;
int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
u32 *regs;
-
- dn->phb = phb;
+ struct pci_dn *pdn;
+
+ if (phb->is_dynamic)
+ pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
+ else
+ pdn = alloc_bootmem(sizeof(*pdn));
+ if (pdn == NULL)
+ return NULL;
+ memset(pdn, 0, sizeof(*pdn));
+ dn->data = pdn;
+ pdn->node = dn;
+ pdn->phb = phb;
regs = (u32 *)get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
- dn->busno = (regs[0] >> 16) & 0xff;
- dn->devfn = (regs[0] >> 8) & 0xff;
+ pdn->busno = (regs[0] >> 16) & 0xff;
+ pdn->devfn = (regs[0] >> 8) & 0xff;
}
- dn->pci_ext_config_space = (type && *type == 1);
+ pdn->pci_ext_config_space = (type && *type == 1);
return NULL;
}
@@ -112,10 +124,15 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
{
struct device_node * dn = (struct device_node *) phb->arch_data;
+ struct pci_dn *pdn;
/* PHB nodes themselves must not match */
- dn->devfn = dn->busno = -1;
- dn->phb = phb;
+ update_dn_pci_info(dn, phb);
+ pdn = dn->data;
+ if (pdn) {
+ pdn->devfn = pdn->busno = -1;
+ pdn->phb = phb;
+ }
/* Update dn->phb ptrs for new phb and children devices */
traverse_pci_devices(dn, update_dn_pci_info, phb);
@@ -123,14 +140,17 @@ void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
/*
* Traversal func that looks for a <busno,devfcn> value.
- * If found, the device_node is returned (thus terminating the traversal).
+ * If found, the pci_dn is returned (thus terminating the traversal).
*/
static void *is_devfn_node(struct device_node *dn, void *data)
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xff;
+ struct pci_dn *pci = dn->data;
- return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
+ if (pci && (devfn == pci->devfn) && (busno == pci->busno))
+ return dn;
+ return NULL;
}
/*
@@ -149,13 +169,10 @@ static void *is_devfn_node(struct device_node *dn, void *data)
struct device_node *fetch_dev_dn(struct pci_dev *dev)
{
struct device_node *orig_dn = dev->sysdata;
- struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */
- struct device_node *phb_dn;
struct device_node *dn;
unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
- phb_dn = phb->arch_data;
- dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
+ dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
if (dn)
dev->sysdata = dn;
return dn;
@@ -165,11 +182,13 @@ EXPORT_SYMBOL(fetch_dev_dn);
static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
{
struct device_node *np = node;
+ struct pci_dn *pci;
int err = NOTIFY_OK;
switch (action) {
case PSERIES_RECONFIG_ADD:
- update_dn_pci_info(np, np->parent->phb);
+ pci = np->parent->data;
+ update_dn_pci_info(np, pci->phb);
break;
default:
err = NOTIFY_DONE;
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
index ef0a62b916be..14647e09c9cd 100644
--- a/arch/ppc64/kernel/pci_iommu.c
+++ b/arch/ppc64/kernel/pci_iommu.c
@@ -66,7 +66,7 @@ static inline struct iommu_table *devnode_table(struct device *dev)
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
- return PCI_GET_DN(pdev)->iommu_table;
+ return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
#endif /* CONFIG_PPC_MULTIPLATFORM */
}
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
index 98ed2bccab1a..eb4e6c3f694d 100644
--- a/arch/ppc64/kernel/pmac_feature.c
+++ b/arch/ppc64/kernel/pmac_feature.c
@@ -674,6 +674,7 @@ void __init pmac_check_ht_link(void)
#if 0 /* Disabled for now */
u32 ufreq, freq, ucfg, cfg;
struct device_node *pcix_node;
+ struct pci_dn *pdn;
u8 px_bus, px_devfn;
struct pci_controller *px_hose;
@@ -687,9 +688,10 @@ void __init pmac_check_ht_link(void)
printk("No PCI-X bridge found\n");
return;
}
- px_hose = pcix_node->phb;
- px_bus = pcix_node->busno;
- px_devfn = pcix_node->devfn;
+ pdn = pcix_node->data;
+ px_hose = pdn->phb;
+ px_bus = pdn->busno;
+ px_devfn = pdn->devfn;
early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index 71fe911ad183..dc40a0cad0b4 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -242,7 +242,7 @@ static int u3_ht_skip_device(struct pci_controller *hose,
else
busdn = hose->arch_data;
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
+ if (dn->data && PCI_DN(dn)->devfn == devfn)
break;
if (dn == NULL)
return -1;
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
*/
- hose->first_busno = 0xf0;
+ hose->first_busno = 0xf0;
hose->last_busno = 0xff;
has_uninorth = 1;
hose->ops = &macrisc_pci_ops;
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
continue;
}
cur++;
- DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+ DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
cur-1, res->start - 1, cur, res->end + 1);
hose->mem_resources[cur].name = np->full_name;
hose->mem_resources[cur].flags = IORESOURCE_MEM;
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev)
char* disp_name;
int *bus_range;
int primary = 1;
- struct property *of_prop;
+ struct property *of_prop;
DBG("Adding PCI host bridge %s\n", dev->full_name);
- 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, assume bus 0\n",
- dev->full_name);
- }
+ 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, assume bus 0\n",
+ dev->full_name);
+ }
hose = alloc_bootmem(sizeof(struct pci_controller));
if (hose == NULL)
return -ENOMEM;
- pci_setup_pci_controller(hose);
+ pci_setup_pci_controller(hose);
- hose->arch_data = dev;
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ hose->arch_data = dev;
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
of_prop = alloc_bootmem(sizeof(struct property) +
sizeof(hose->global_number));
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev)
}
disp_name = NULL;
- if (device_is_compatible(dev, "u3-agp")) {
- setup_u3_agp(hose);
- disp_name = "U3-AGP";
- primary = 0;
- } else if (device_is_compatible(dev, "u3-ht")) {
- setup_u3_ht(hose);
- disp_name = "U3-HT";
- primary = 1;
- }
- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
- disp_name, hose->first_busno, hose->last_busno);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pmac_process_bridge_OF_ranges(hose, dev, primary);
-
- /* Fixup "bus-range" OF property */
- fixup_bus_range(dev);
+ if (device_is_compatible(dev, "u3-agp")) {
+ setup_u3_agp(hose);
+ disp_name = "U3-AGP";
+ primary = 0;
+ } else if (device_is_compatible(dev, "u3-ht")) {
+ setup_u3_ht(hose);
+ disp_name = "U3-HT";
+ primary = 1;
+ }
+ printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+ disp_name, hose->first_busno, hose->last_busno);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pmac_process_bridge_OF_ranges(hose, dev, primary);
+
+ /* Fixup "bus-range" OF property */
+ fixup_bus_range(dev);
return 0;
}
@@ -746,9 +746,9 @@ void __init pmac_pci_init(void)
*/
if (u3_agp) {
struct device_node *np = u3_agp->arch_data;
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
for (np = np->child; np; np = np->sibling)
- np->busno = 0xf0;
+ PCI_DN(np)->busno = 0xf0;
}
pmac_check_ht_link();
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e40877fa67cd..325426c7bed0 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -71,6 +71,7 @@
#include <asm/of_device.h>
#include <asm/lmb.h>
#include <asm/smu.h>
+#include <asm/pmc.h>
#include "pmac.h"
#include "mpic.h"
@@ -273,16 +274,6 @@ static void __pmac pmac_halt(void)
}
#ifdef CONFIG_BOOTX_TEXT
-static int dummy_getc_poll(void)
-{
- return -1;
-}
-
-static unsigned char dummy_getc(void)
-{
- return 0;
-}
-
static void btext_putc(unsigned char c)
{
btext_drawchar(c);
@@ -341,16 +332,13 @@ static void __init pmac_init_early(void)
sccdbg = 1;
udbg_init_scc(NULL);
}
-
- else {
#ifdef CONFIG_BOOTX_TEXT
+ else {
init_boot_display();
- ppc_md.udbg_putc = btext_putc;
- ppc_md.udbg_getc = dummy_getc;
- ppc_md.udbg_getc_poll = dummy_getc_poll;
-#endif /* CONFIG_BOOTX_TEXT */
+ udbg_putc = btext_putc;
}
+#endif /* CONFIG_BOOTX_TEXT */
/* Setup interrupt mapping options */
ppc64_interrupt_controller = IC_OPEN_PIC;
@@ -489,6 +477,18 @@ static int __init pmac_probe(int platform)
return 1;
}
+static int pmac_probe_mode(struct pci_bus *bus)
+{
+ struct device_node *node = bus->sysdata;
+
+ /* We need to use normal PCI probing for the AGP bus,
+ since the device for the AGP bridge isn't in the tree. */
+ if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+ return PCI_PROBE_NORMAL;
+
+ return PCI_PROBE_DEVTREE;
+}
+
struct machdep_calls __initdata pmac_md = {
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = generic_mach_cpu_die,
@@ -500,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
.init_IRQ = pmac_init_IRQ,
.get_irq = mpic_get_irq,
.pcibios_fixup = pmac_pcibios_fixup,
+ .pci_probe_mode = pmac_probe_mode,
.restart = pmac_restart,
.power_off = pmac_power_off,
.halt = pmac_halt,
@@ -511,4 +512,5 @@ struct machdep_calls __initdata pmac_md = {
.progress = pmac_progress,
.check_legacy_ioport = pmac_check_legacy_ioport,
.idle_loop = native_idle,
+ .enable_pmcs = power4_enable_pmcs,
};
diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
index 67be773f9c00..63d9481c3ec2 100644
--- a/arch/ppc64/kernel/pmc.c
+++ b/arch/ppc64/kernel/pmc.c
@@ -26,7 +26,7 @@ static void dummy_perf(struct pt_regs *regs)
mtspr(SPRN_MMCR0, mmcr0);
}
-static spinlock_t pmc_owner_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pmc_owner_lock);
static void *pmc_owner_caller; /* mostly for debugging */
perf_irq_t perf_irq = dummy_perf;
@@ -65,3 +65,24 @@ void release_pmc_hardware(void)
spin_unlock(&pmc_owner_lock);
}
EXPORT_SYMBOL_GPL(release_pmc_hardware);
+
+void power4_enable_pmcs(void)
+{
+ unsigned long hid0;
+
+ hid0 = mfspr(HID0);
+ hid0 |= 1UL << (63 - 20);
+
+ /* POWER4 requires the following sequence */
+ asm volatile(
+ "sync\n"
+ "mtspr %1, %0\n"
+ "mfspr %0, %1\n"
+ "mfspr %0, %1\n"
+ "mfspr %0, %1\n"
+ "mfspr %0, %1\n"
+ "mfspr %0, %1\n"
+ "mfspr %0, %1\n"
+ "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
+ "memory");
+}
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index f7cae05e40fb..887005358eb1 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -50,9 +50,11 @@
#include <asm/machdep.h>
#include <asm/iSeries/HvCallHpt.h>
#include <asm/cputable.h>
+#include <asm/firmware.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/time.h>
+#include <asm/plpar_wrappers.h>
#ifndef CONFIG_SMP
struct task_struct *last_task_used_math = NULL;
@@ -162,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
#endif /* CONFIG_ALTIVEC */
+static void set_dabr_spr(unsigned long val)
+{
+ mtspr(SPRN_DABR, val);
+}
+
+int set_dabr(unsigned long dabr)
+{
+ int ret = 0;
+
+ if (firmware_has_feature(FW_FEATURE_XDABR)) {
+ /* We want to catch accesses from kernel and userspace */
+ unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
+ ret = plpar_set_xdabr(dabr, flags);
+ } else if (firmware_has_feature(FW_FEATURE_DABR)) {
+ ret = plpar_set_dabr(dabr);
+ } else {
+ set_dabr_spr(dabr);
+ }
+
+ return ret;
+}
+
DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+static DEFINE_PER_CPU(unsigned long, current_dabr);
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
@@ -197,16 +222,20 @@ struct task_struct *__switch_to(struct task_struct *prev,
new->thread.regs->msr |= MSR_VEC;
#endif /* CONFIG_ALTIVEC */
+ if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+ set_dabr(new->thread.dabr);
+ __get_cpu_var(current_dabr) = new->thread.dabr;
+ }
+
flush_tlb_pending();
new_thread = &new->thread;
old_thread = &current->thread;
-/* Collect purr utilization data per process and per processor wise */
-/* purr is nothing but processor time base */
-
-#if defined(CONFIG_PPC_PSERIES)
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ /* Collect purr utilization data per process and per processor
+ * wise purr is nothing but processor time base
+ */
+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
long unsigned start_tb, current_tb;
start_tb = old_thread->start_tb;
@@ -214,8 +243,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
old_thread->accum_tb += (current_tb - start_tb);
new_thread->start_tb = current_tb;
}
-#endif
-
local_irq_save(flags);
last = _switch(old_thread, new_thread);
@@ -336,6 +363,11 @@ void flush_thread(void)
last_task_used_altivec = NULL;
#endif /* CONFIG_ALTIVEC */
#endif /* CONFIG_SMP */
+
+ if (current->thread.dabr) {
+ current->thread.dabr = 0;
+ set_dabr(0);
+ }
}
void
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 5aca01ddd81f..7035deb6de92 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -22,7 +22,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -625,8 +624,8 @@ void __init finish_device_tree(void)
static inline char *find_flat_dt_string(u32 offset)
{
- return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
- + offset;
+ return ((char *)initial_boot_params) +
+ initial_boot_params->off_dt_strings + offset;
}
/**
@@ -635,26 +634,33 @@ static inline char *find_flat_dt_string(u32 offset)
* unflatten the tree
*/
static int __init scan_flat_dt(int (*it)(unsigned long node,
- const char *full_path, void *data),
+ const char *uname, int depth,
+ void *data),
void *data)
{
unsigned long p = ((unsigned long)initial_boot_params) +
initial_boot_params->off_dt_struct;
int rc = 0;
+ int depth = -1;
do {
u32 tag = *((u32 *)p);
char *pathp;
p += 4;
- if (tag == OF_DT_END_NODE)
+ if (tag == OF_DT_END_NODE) {
+ depth --;
+ continue;
+ }
+ if (tag == OF_DT_NOP)
continue;
if (tag == OF_DT_END)
break;
if (tag == OF_DT_PROP) {
u32 sz = *((u32 *)p);
p += 8;
- p = _ALIGN(p, sz >= 8 ? 8 : 4);
+ if (initial_boot_params->version < 0x10)
+ p = _ALIGN(p, sz >= 8 ? 8 : 4);
p += sz;
p = _ALIGN(p, 4);
continue;
@@ -664,9 +670,18 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
" device tree !\n", tag);
return -EINVAL;
}
+ depth++;
pathp = (char *)p;
p = _ALIGN(p + strlen(pathp) + 1, 4);
- rc = it(p, pathp, data);
+ if ((*pathp) == '/') {
+ char *lp, *np;
+ for (lp = NULL, np = pathp; *np; np++)
+ if ((*np) == '/')
+ lp = np+1;
+ if (lp != NULL)
+ pathp = lp;
+ }
+ rc = it(p, pathp, depth, data);
if (rc != 0)
break;
} while(1);
@@ -689,17 +704,21 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
const char *nstr;
p += 4;
+ if (tag == OF_DT_NOP)
+ continue;
if (tag != OF_DT_PROP)
return NULL;
sz = *((u32 *)p);
noff = *((u32 *)(p + 4));
p += 8;
- p = _ALIGN(p, sz >= 8 ? 8 : 4);
+ if (initial_boot_params->version < 0x10)
+ p = _ALIGN(p, sz >= 8 ? 8 : 4);
nstr = find_flat_dt_string(noff);
if (nstr == NULL) {
- printk(KERN_WARNING "Can't find property index name !\n");
+ printk(KERN_WARNING "Can't find property index"
+ " name !\n");
return NULL;
}
if (strcmp(name, nstr) == 0) {
@@ -713,7 +732,7 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
}
static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
- unsigned long align)
+ unsigned long align)
{
void *res;
@@ -727,13 +746,16 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
static unsigned long __init unflatten_dt_node(unsigned long mem,
unsigned long *p,
struct device_node *dad,
- struct device_node ***allnextpp)
+ struct device_node ***allnextpp,
+ unsigned long fpsize)
{
struct device_node *np;
struct property *pp, **prev_pp = NULL;
char *pathp;
u32 tag;
- unsigned int l;
+ unsigned int l, allocl;
+ int has_name = 0;
+ int new_format = 0;
tag = *((u32 *)(*p));
if (tag != OF_DT_BEGIN_NODE) {
@@ -742,21 +764,62 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
}
*p += 4;
pathp = (char *)*p;
- l = strlen(pathp) + 1;
+ l = allocl = strlen(pathp) + 1;
*p = _ALIGN(*p + l, 4);
- np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
+ /* version 0x10 has a more compact unit name here instead of the full
+ * path. we accumulate the full path size using "fpsize", we'll rebuild
+ * it later. We detect this because the first character of the name is
+ * not '/'.
+ */
+ if ((*pathp) != '/') {
+ new_format = 1;
+ if (fpsize == 0) {
+ /* root node: special case. fpsize accounts for path
+ * plus terminating zero. root node only has '/', so
+ * fpsize should be 2, but we want to avoid the first
+ * level nodes to have two '/' so we use fpsize 1 here
+ */
+ fpsize = 1;
+ allocl = 2;
+ } else {
+ /* account for '/' and path size minus terminal 0
+ * already in 'l'
+ */
+ fpsize += l;
+ allocl = fpsize;
+ }
+ }
+
+
+ np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
__alignof__(struct device_node));
if (allnextpp) {
memset(np, 0, sizeof(*np));
np->full_name = ((char*)np) + sizeof(struct device_node);
- memcpy(np->full_name, pathp, l);
+ if (new_format) {
+ char *p = np->full_name;
+ /* rebuild full path for new format */
+ if (dad && dad->parent) {
+ strcpy(p, dad->full_name);
+#ifdef DEBUG
+ if ((strlen(p) + l + 1) != allocl) {
+ DBG("%s: p: %d, l: %d, a: %d\n",
+ pathp, strlen(p), l, allocl);
+ }
+#endif
+ p += strlen(p);
+ }
+ *(p++) = '/';
+ memcpy(p, pathp, l);
+ } else
+ memcpy(np->full_name, pathp, l);
prev_pp = &np->properties;
**allnextpp = np;
*allnextpp = &np->allnext;
if (dad != NULL) {
np->parent = dad;
- /* we temporarily use the `next' field as `last_child'. */
+ /* we temporarily use the next field as `last_child'*/
if (dad->next == 0)
dad->child = np;
else
@@ -770,18 +833,26 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
char *pname;
tag = *((u32 *)(*p));
+ if (tag == OF_DT_NOP) {
+ *p += 4;
+ continue;
+ }
if (tag != OF_DT_PROP)
break;
*p += 4;
sz = *((u32 *)(*p));
noff = *((u32 *)((*p) + 4));
- *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
+ *p += 8;
+ if (initial_boot_params->version < 0x10)
+ *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
pname = find_flat_dt_string(noff);
if (pname == NULL) {
printk("Can't find property name in list !\n");
break;
}
+ if (strcmp(pname, "name") == 0)
+ has_name = 1;
l = strlen(pname) + 1;
pp = unflatten_dt_alloc(&mem, sizeof(struct property),
__alignof__(struct property));
@@ -801,6 +872,36 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
}
*p = _ALIGN((*p) + sz, 4);
}
+ /* with version 0x10 we may not have the name property, recreate
+ * it here from the unit name if absent
+ */
+ if (!has_name) {
+ char *p = pathp, *ps = pathp, *pa = NULL;
+ int sz;
+
+ while (*p) {
+ if ((*p) == '@')
+ pa = p;
+ if ((*p) == '/')
+ ps = p + 1;
+ p++;
+ }
+ if (pa < ps)
+ pa = p;
+ sz = (pa - ps) + 1;
+ pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
+ __alignof__(struct property));
+ if (allnextpp) {
+ pp->name = "name";
+ pp->length = sz;
+ pp->value = (unsigned char *)(pp + 1);
+ *prev_pp = pp;
+ prev_pp = &pp->next;
+ memcpy(pp->value, ps, sz - 1);
+ ((char *)pp->value)[sz - 1] = 0;
+ DBG("fixed up name for %s -> %s\n", pathp, pp->value);
+ }
+ }
if (allnextpp) {
*prev_pp = NULL;
np->name = get_property(np, "name", NULL);
@@ -812,11 +913,11 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
np->type = "<NULL>";
}
while (tag == OF_DT_BEGIN_NODE) {
- mem = unflatten_dt_node(mem, p, np, allnextpp);
+ mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
tag = *((u32 *)(*p));
}
if (tag != OF_DT_END_NODE) {
- printk("Weird tag at start of node: %x\n", tag);
+ printk("Weird tag at end of node: %x\n", tag);
return mem;
}
*p += 4;
@@ -842,21 +943,32 @@ void __init unflatten_device_tree(void)
/* First pass, scan for size */
start = ((unsigned long)initial_boot_params) +
initial_boot_params->off_dt_struct;
- size = unflatten_dt_node(0, &start, NULL, NULL);
+ size = unflatten_dt_node(0, &start, NULL, NULL, 0);
+ size = (size | 3) + 1;
DBG(" size is %lx, allocating...\n", size);
/* Allocate memory for the expanded device tree */
- mem = (unsigned long)abs_to_virt(lmb_alloc(size,
- __alignof__(struct device_node)));
+ mem = lmb_alloc(size + 4, __alignof__(struct device_node));
+ if (!mem) {
+ DBG("Couldn't allocate memory with lmb_alloc()!\n");
+ panic("Couldn't allocate memory with lmb_alloc()!\n");
+ }
+ mem = (unsigned long)abs_to_virt(mem);
+
+ ((u32 *)mem)[size / 4] = 0xdeadbeef;
+
DBG(" unflattening...\n", mem);
/* Second pass, do actual unflattening */
start = ((unsigned long)initial_boot_params) +
initial_boot_params->off_dt_struct;
- unflatten_dt_node(mem, &start, NULL, &allnextp);
+ unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
if (*((u32 *)start) != OF_DT_END)
- printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
+ printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
+ if (((u32 *)mem)[size / 4] != 0xdeadbeef)
+ printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
+ ((u32 *)mem)[size / 4] );
*allnextp = NULL;
/* Get pointer to OF "/chosen" node for use everywhere */
@@ -880,7 +992,7 @@ void __init unflatten_device_tree(void)
static int __init early_init_dt_scan_cpus(unsigned long node,
- const char *full_path, void *data)
+ const char *uname, int depth, void *data)
{
char *type = get_flat_dt_prop(node, "device_type", NULL);
u32 *prop;
@@ -947,13 +1059,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
}
static int __init early_init_dt_scan_chosen(unsigned long node,
- const char *full_path, void *data)
+ const char *uname, int depth, void *data)
{
u32 *prop;
u64 *prop64;
extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
- if (strcmp(full_path, "/chosen") != 0)
+ DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+ if (depth != 1 || strcmp(uname, "chosen") != 0)
return 0;
/* get platform type */
@@ -1003,18 +1117,20 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
}
static int __init early_init_dt_scan_root(unsigned long node,
- const char *full_path, void *data)
+ const char *uname, int depth, void *data)
{
u32 *prop;
- if (strcmp(full_path, "/") != 0)
+ if (depth != 0)
return 0;
prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
dt_root_size_cells = (prop == NULL) ? 1 : *prop;
-
+ DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
+
prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+ DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
/* break now */
return 1;
@@ -1042,7 +1158,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
static int __init early_init_dt_scan_memory(unsigned long node,
- const char *full_path, void *data)
+ const char *uname, int depth, void *data)
{
char *type = get_flat_dt_prop(node, "device_type", NULL);
cell_t *reg, *endp;
@@ -1058,7 +1174,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
endp = reg + (l / sizeof(cell_t));
- DBG("memory scan node %s ...\n", full_path);
+ DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
+ uname, l, reg[0], reg[1], reg[2], reg[3]);
+
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
unsigned long base, size;
@@ -1469,10 +1587,11 @@ struct device_node *of_find_node_by_path(const char *path)
struct device_node *np = allnodes;
read_lock(&devtree_lock);
- for (; np != 0; np = np->allnext)
+ for (; np != 0; np = np->allnext) {
if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
&& of_node_get(np))
break;
+ }
read_unlock(&devtree_lock);
return np;
}
@@ -1614,6 +1733,7 @@ static void of_node_release(struct kref *kref)
kfree(node->intrs);
kfree(node->addrs);
kfree(node->full_name);
+ kfree(node->data);
kfree(node);
}
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index dbbe6c79d8da..9979919cdf92 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -22,7 +22,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -892,7 +891,10 @@ static void __init prom_init_mem(void)
if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
RELOC(alloc_top) = RELOC(rmo_top);
else
- RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
+ /* Some RS64 machines have buggy firmware where claims up at 1GB
+ * fails. Cap at 768MB as a workaround. Still plenty of room.
+ */
+ RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top));
prom_printf("memory layout at init:\n");
prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
@@ -1534,7 +1536,8 @@ static unsigned long __init dt_find_string(char *str)
*/
#define MAX_PROPERTY_NAME 64
-static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
+static void __init scan_dt_build_strings(phandle node,
+ unsigned long *mem_start,
unsigned long *mem_end)
{
unsigned long offset = reloc_offset();
@@ -1547,16 +1550,21 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
/* get and store all property names */
prev_name = RELOC("");
for (;;) {
- int rc;
-
/* 64 is max len of name including nul. */
namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
- rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
- if (rc != 1) {
+ if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
}
+
+ /* skip "name" */
+ if (strcmp(namep, RELOC("name")) == 0) {
+ *mem_start = (unsigned long)namep;
+ prev_name = RELOC("name");
+ continue;
+ }
+ /* get/create string entry */
soff = dt_find_string(namep);
if (soff != 0) {
*mem_start = (unsigned long)namep;
@@ -1571,7 +1579,7 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
/* do all our children */
child = call_prom("child", 1, 1, node);
- while (child != (phandle)0) {
+ while (child != 0) {
scan_dt_build_strings(child, mem_start, mem_end);
child = call_prom("peer", 1, 1, child);
}
@@ -1580,16 +1588,13 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
{
- int l, align;
phandle child;
- char *namep, *prev_name, *sstart, *p, *ep;
+ char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
- char pname[MAX_PROPERTY_NAME];
- char *path;
-
- path = RELOC(prom_scratch);
+ static char pname[MAX_PROPERTY_NAME];
+ int l;
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
@@ -1599,23 +1604,33 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
namep, *mem_end - *mem_start);
if (l >= 0) {
/* Didn't fit? Get more room. */
- if (l+1 > *mem_end - *mem_start) {
+ if ((l+1) > (*mem_end - *mem_start)) {
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom("package-to-path", 3, 1, node, namep, l);
}
namep[l] = '\0';
+
/* Fixup an Apple bug where they have bogus \0 chars in the
* middle of the path in some properties
*/
for (p = namep, ep = namep + l; p < ep; p++)
if (*p == '\0') {
memmove(p, p+1, ep - p);
- ep--; l--;
+ ep--; l--; p--;
}
- *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
+
+ /* now try to extract the unit name in that mess */
+ for (p = namep, lp = NULL; *p; p++)
+ if (*p == '/')
+ lp = p + 1;
+ if (lp != NULL)
+ memmove(namep, lp, strlen(lp) + 1);
+ *mem_start = _ALIGN(((unsigned long) namep) +
+ strlen(namep) + 1, 4);
}
/* get it again for debugging */
+ path = RELOC(prom_scratch);
memset(path, 0, PROM_SCRATCH_SIZE);
call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
@@ -1623,23 +1638,27 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
prev_name = RELOC("");
sstart = (char *)RELOC(dt_string_start);
for (;;) {
- int rc;
-
- rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
- if (rc != 1)
+ if (call_prom("nextprop", 3, 1, node, prev_name,
+ RELOC(pname)) != 1)
break;
+ /* skip "name" */
+ if (strcmp(RELOC(pname), RELOC("name")) == 0) {
+ prev_name = RELOC("name");
+ continue;
+ }
+
/* find string offset */
- soff = dt_find_string(pname);
+ soff = dt_find_string(RELOC(pname));
if (soff == 0) {
- prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
- pname, path);
+ prom_printf("WARNING: Can't find string index for"
+ " <%s>, node %s\n", RELOC(pname), path);
break;
}
prev_name = sstart + soff;
/* get length */
- l = call_prom("getproplen", 2, 1, node, pname);
+ l = call_prom("getproplen", 2, 1, node, RELOC(pname));
/* sanity checks */
if (l == PROM_ERROR)
@@ -1648,7 +1667,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
prom_printf("WARNING: ignoring large property ");
/* It seems OF doesn't null-terminate the path :-( */
prom_printf("[%s] ", path);
- prom_printf("%s length 0x%x\n", pname, l);
+ prom_printf("%s length 0x%x\n", RELOC(pname), l);
continue;
}
@@ -1658,17 +1677,16 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
dt_push_token(soff, mem_start, mem_end);
/* push property content */
- align = (l >= 8) ? 8 : 4;
- valp = make_room(mem_start, mem_end, l, align);
- call_prom("getprop", 4, 1, node, pname, valp, l);
+ valp = make_room(mem_start, mem_end, l, 4);
+ call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
*mem_start = _ALIGN(*mem_start, 4);
}
/* Add a "linux,phandle" property. */
soff = dt_find_string(RELOC("linux,phandle"));
if (soff == 0)
- prom_printf("WARNING: Can't find string index for <linux-phandle>"
- " node %s\n", path);
+ prom_printf("WARNING: Can't find string index for"
+ " <linux-phandle> node %s\n", path);
else {
dt_push_token(OF_DT_PROP, mem_start, mem_end);
dt_push_token(4, mem_start, mem_end);
@@ -1679,7 +1697,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
/* do all our children */
child = call_prom("child", 1, 1, node);
- while (child != (phandle)0) {
+ while (child != 0) {
scan_dt_build_struct(child, mem_start, mem_end);
child = call_prom("peer", 1, 1, child);
}
@@ -1718,7 +1736,8 @@ static void __init flatten_device_tree(void)
/* Build header and make room for mem rsv map */
mem_start = _ALIGN(mem_start, 4);
- hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
+ hdr = make_room(&mem_start, &mem_end,
+ sizeof(struct boot_param_header), 4);
RELOC(dt_header_start) = (unsigned long)hdr;
rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
@@ -1731,11 +1750,11 @@ static void __init flatten_device_tree(void)
namep = make_room(&mem_start, &mem_end, 16, 1);
strcpy(namep, RELOC("linux,phandle"));
mem_start = (unsigned long)namep + strlen(namep) + 1;
- RELOC(dt_string_end) = mem_start;
/* Build string array */
prom_printf("Building dt strings...\n");
scan_dt_build_strings(root, &mem_start, &mem_end);
+ RELOC(dt_string_end) = mem_start;
/* Build structure */
mem_start = PAGE_ALIGN(mem_start);
@@ -1750,9 +1769,11 @@ static void __init flatten_device_tree(void)
hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
+ hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
hdr->version = OF_DT_VERSION;
- hdr->last_comp_version = 1;
+ /* Version 16 is not backward compatible */
+ hdr->last_comp_version = 0x10;
/* Reserve the whole thing and copy the reserve map in, we
* also bump mem_reserve_cnt to cause further reservations to
@@ -1808,6 +1829,9 @@ static void __init fixup_device_tree(void)
/* does it need fixup ? */
if (prom_getproplen(i2c, "interrupts") > 0)
return;
+
+ prom_printf("fixing up bogus interrupts for u3 i2c...\n");
+
/* interrupt on this revision of u3 is number 0 and level */
interrupts[0] = 0;
interrupts[1] = 1;
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 2993f108d96d..85ed3188a91d 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -17,6 +17,7 @@
* this archive for more details.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data)
break;
}
+ case PTRACE_GET_DEBUGREG: {
+ ret = -EINVAL;
+ /* We only support one DABR and no IABRS at the moment */
+ if (addr > 0)
+ break;
+ ret = put_user(child->thread.dabr,
+ (unsigned long __user *)data);
+ break;
+ }
+
+ case PTRACE_SET_DEBUGREG:
+ ret = ptrace_set_debugreg(child, addr, data);
+
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
break;
}
+#ifdef CONFIG_ALTIVEC
+ case PTRACE_GETVRREGS:
+ /* Get the child altivec register state. */
+ flush_altivec_to_thread(child);
+ ret = get_vrregs((unsigned long __user *)data, child);
+ break;
+
+ case PTRACE_SETVRREGS:
+ /* Set the child altivec register state. */
+ flush_altivec_to_thread(child);
+ ret = set_vrregs(child, (unsigned long __user *)data);
+ break;
+#endif
+
default:
ret = ptrace_request(child, request, addr, data);
break;
diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
index 16436426c7e2..fb8c22d6084a 100644
--- a/arch/ppc64/kernel/ptrace32.c
+++ b/arch/ppc64/kernel/ptrace32.c
@@ -17,6 +17,7 @@
* this archive for more details.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break;
}
+ case PTRACE_GET_DEBUGREG: {
+ ret = -EINVAL;
+ /* We only support one DABR and no IABRS at the moment */
+ if (addr > 0)
+ break;
+ ret = put_user(child->thread.dabr, (u32 __user *)data);
+ break;
+ }
+
+ case PTRACE_SET_DEBUGREG:
+ ret = ptrace_set_debugreg(child, addr, data);
+ break;
+
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break;
}
- case PTRACE_GETEVENTMSG:
- ret = put_user(child->ptrace_message, (unsigned int __user *) data);
- break;
+ case PTRACE_GETEVENTMSG:
+ ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+ break;
+
+#ifdef CONFIG_ALTIVEC
+ case PTRACE_GETVRREGS:
+ /* Get the child altivec register state. */
+ flush_altivec_to_thread(child);
+ ret = get_vrregs((unsigned long __user *)data, child);
+ break;
+
+ case PTRACE_SETVRREGS:
+ /* Set the child altivec register state. */
+ flush_altivec_to_thread(child);
+ ret = set_vrregs(child, (unsigned long __user *)data);
+ break;
+#endif
default:
ret = ptrace_request(child, request, addr, data);
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 3c00f7bfc1b5..41b97dc9cc0a 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX]
/* This is true if we are using the firmware NMI handler (typically LPAR) */
extern int fwnmi_active;
-extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
-
static int ras_get_sensor_state_token;
static int ras_check_exception_token;
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 1048817befb8..4a9719b48abe 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -48,7 +48,7 @@ static int write_pci_config;
static int ibm_read_pci_config;
static int ibm_write_pci_config;
-static int config_access_valid(struct device_node *dn, int where)
+static int config_access_valid(struct pci_dn *dn, int where)
{
if (where < 256)
return 1;
@@ -58,20 +58,37 @@ static int config_access_valid(struct device_node *dn, int where)
return 0;
}
+static int of_device_available(struct device_node * dn)
+{
+ char * status;
+
+ status = get_property(dn, "status", NULL);
+
+ if (!status)
+ return 1;
+
+ if (!strcmp(status, "okay"))
+ return 1;
+
+ return 0;
+}
+
static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
{
int returnval = -1;
unsigned long buid, addr;
int ret;
+ struct pci_dn *pdn;
- if (!dn)
+ if (!dn || !dn->data)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
+ pdn = dn->data;
+ if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
+ addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+ (pdn->devfn << 8) | (where & 0xff);
+ buid = pdn->phb->buid;
if (buid) {
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
addr, buid >> 32, buid & 0xffffffff, size);
@@ -83,8 +100,8 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
if (ret)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (returnval == EEH_IO_ERROR_VALUE(size)
- && eeh_dn_check_failure (dn, NULL))
+ if (returnval == EEH_IO_ERROR_VALUE(size) &&
+ eeh_dn_check_failure (dn, NULL))
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
@@ -103,24 +120,28 @@ static int rtas_pci_read_config(struct pci_bus *bus,
/* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
+ if (dn->data && PCI_DN(dn)->devfn == devfn
+ && of_device_available(dn))
return rtas_read_config(dn, where, size, val);
+
return PCIBIOS_DEVICE_NOT_FOUND;
}
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
{
unsigned long buid, addr;
int ret;
+ struct pci_dn *pdn;
- if (!dn)
+ if (!dn || !dn->data)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
+ pdn = dn->data;
+ if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
+ addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+ (pdn->devfn << 8) | (where & 0xff);
+ buid = pdn->phb->buid;
if (buid) {
ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
} else {
@@ -146,7 +167,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
/* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
+ if (dn->data && PCI_DN(dn)->devfn == devfn
+ && of_device_available(dn))
return rtas_write_config(dn, where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index b0c3b829fe47..e26b0420b6dd 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -19,6 +19,7 @@
#include <linux/vmalloc.h>
#include <linux/spinlock.h>
#include <linux/cpu.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -412,8 +413,7 @@ static void do_event_scan_all_cpus(long delay)
/* Drop hotplug lock, and sleep for the specified delay */
unlock_cpu_hotplug();
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(delay);
+ msleep_interruptible(delay);
lock_cpu_hotplug();
cpu = next_cpu(cpu, cpu_online_map);
@@ -442,7 +442,7 @@ static int rtasd(void *unused)
printk(KERN_INFO "RTAS daemon started\n");
- DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
+ DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
/* See if we have any error stored in NVRAM */
memset(logdata, 0, rtas_error_log_max);
@@ -459,7 +459,7 @@ static int rtasd(void *unused)
}
/* First pass. */
- do_event_scan_all_cpus(HZ);
+ do_event_scan_all_cpus(1000);
if (surveillance_timeout != -1) {
DEBUG("enabling surveillance\n");
@@ -471,7 +471,7 @@ static int rtasd(void *unused)
* machines have problems if we call event-scan too
* quickly. */
for (;;)
- do_event_scan_all_cpus((HZ*60/rtas_event_scan_rate) / 2);
+ do_event_scan_all_cpus(30000/rtas_event_scan_rate);
error:
/* Should delete proc entries */
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index d729fefa0df5..6ff52bc61325 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/bcd.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -351,8 +352,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
return; /* delay not allowed */
}
wait_time = rtas_extended_busy_delay_time(error);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(wait_time);
+ msleep_interruptible(wait_time);
error = RTAS_CLOCK_BUSY;
}
} while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb));
@@ -386,8 +386,7 @@ int rtas_set_rtc_time(struct rtc_time *tm)
if (in_interrupt())
return 1; /* probably decrementer */
wait_time = rtas_extended_busy_delay_time(error);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(wait_time);
+ msleep_interruptible(wait_time);
error = RTAS_CLOCK_BUSY;
}
} while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb));
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
index 4d70736619c7..215bf8900304 100644
--- a/arch/ppc64/kernel/scanlog.c
+++ b/arch/ppc64/kernel/scanlog.c
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#include <asm/prom.h>
@@ -77,7 +78,7 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
return -EFAULT;
for (;;) {
- wait_time = HZ/2; /* default wait if no data */
+ wait_time = 500; /* default wait if no data */
spin_lock(&rtas_data_buf_lock);
memcpy(rtas_data_buf, data, RTAS_DATA_BUF_SIZE);
status = rtas_call(ibm_scan_log_dump, 2, 1, NULL,
@@ -107,24 +108,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
break;
default:
if (status > 9900 && status <= 9905) {
- /* No data. RTAS is hinting at a delay required
- * between 1-100000 milliseconds
- */
- int ms = 1;
- for (; status > 9900; status--)
- ms = ms * 10;
- /* Use microseconds for reasonable accuracy */
- ms *= 1000;
- wait_time = ms / (1000000/HZ); /* round down is fine */
- /* Fall through to sleep */
+ wait_time = rtas_extended_busy_delay_time(status);
} else {
printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
return -EIO;
}
}
/* Apparently no data yet. Wait and try again. */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(wait_time);
+ msleep_interruptible(wait_time);
}
/*NOTREACHED*/
}
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index e9c24d2dbd91..5ac48bd64891 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -25,7 +25,7 @@
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/console.h>
-#include <linux/version.h>
+#include <linux/utsname.h>
#include <linux/tty.h>
#include <linux/root_dev.h>
#include <linux/notifier.h>
@@ -89,7 +89,7 @@ extern void udbg_init_maple_realmode(void);
#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
#define EARLY_DEBUG_INIT() \
- do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0)
+ do { udbg_putc = call_rtas_display_status_delay; } while(0)
#endif
/* extern void *stab; */
@@ -108,7 +108,6 @@ int boot_cpuid = 0;
int boot_cpuid_phys = 0;
dev_t boot_dev;
u64 ppc64_pft_size;
-u64 ppc64_debug_switch;
struct ppc64_caches ppc64_caches;
EXPORT_SYMBOL_GPL(ppc64_caches);
@@ -154,34 +153,6 @@ struct screen_info screen_info = {
.orig_video_points = 16
};
-/*
- * Initialize the PPCDBG state. Called before relocation has been enabled.
- */
-void __init ppcdbg_initialize(void)
-{
- ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
- /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
-}
-
-/*
- * Early boot console based on udbg
- */
-static struct console udbg_console = {
- .name = "udbg",
- .write = udbg_console_write,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-static int early_console_initialized;
-
-void __init disable_early_printk(void)
-{
- if (!early_console_initialized)
- return;
- unregister_console(&udbg_console);
- early_console_initialized = 0;
-}
-
#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
static int smt_enabled_cmdline;
@@ -425,12 +396,6 @@ void __init early_setup(unsigned long dt_ptr)
}
ppc_md = **mach;
- /* our udbg callbacks got overriden by the above, let's put them
- * back in. Ultimately, I want those things to be split from the
- * main ppc_md
- */
- EARLY_DEBUG_INIT();
-
DBG("Found, Initializing memory management...\n");
/*
@@ -536,15 +501,19 @@ static void __init check_for_initrd(void)
DBG(" -> check_for_initrd()\n");
- prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL);
- if (prop != NULL) {
- initrd_start = (unsigned long)__va(*prop);
- prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);
+ if (of_chosen) {
+ prop = (u64 *)get_property(of_chosen,
+ "linux,initrd-start", NULL);
if (prop != NULL) {
- initrd_end = (unsigned long)__va(*prop);
- initrd_below_start_ok = 1;
- } else
- initrd_start = 0;
+ initrd_start = (unsigned long)__va(*prop);
+ prop = (u64 *)get_property(of_chosen,
+ "linux,initrd-end", NULL);
+ if (prop != NULL) {
+ initrd_end = (unsigned long)__va(*prop);
+ initrd_below_start_ok = 1;
+ } else
+ initrd_start = 0;
+ }
}
/* If we were passed an initrd, set the ROOT_DEV properly if the values
@@ -627,13 +596,12 @@ void __init setup_system(void)
* Initialize xmon
*/
#ifdef CONFIG_XMON_DEFAULT
- xmon_init();
+ xmon_init(1);
#endif
/*
* Register early console
*/
- early_console_initialized = 1;
- register_console(&udbg_console);
+ register_early_udbg_console();
/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
@@ -653,7 +621,7 @@ void __init setup_system(void)
smp_release_cpus();
#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
- printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
+ printk("Starting Linux PPC64 %s\n", system_utsname.version);
printk("-----------------------------------------------------\n");
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
@@ -1096,8 +1064,6 @@ void __init setup_arch(char **cmdline_p)
#define PPC64_LINUX_FUNCTION 0x0f000000
#define PPC64_IPL_MESSAGE 0xc0000000
#define PPC64_TERM_MESSAGE 0xb0000000
-#define PPC64_ATTN_MESSAGE 0xa0000000
-#define PPC64_DUMP_MESSAGE 0xd0000000
static void ppc64_do_msg(unsigned int src, const char *msg)
{
@@ -1125,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk("[terminate]%04x %s\n", src, msg);
}
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg)
-{
- ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
- printk("[attention]%04x %s\n", src, msg);
-}
-
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg)
-{
- ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
- printk("[dump]%04x %s\n", src, msg);
-}
-
/* This should only be called on processor 0 during calibrate decr */
void __init setup_default_decr(void)
{
@@ -1315,7 +1267,7 @@ void __init generic_find_legacy_serial_ports(u64 *physport,
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_ports,
},
@@ -1343,11 +1295,13 @@ static int __init early_xmon(char *p)
/* ensure xmon is enabled */
if (p) {
if (strncmp(p, "on", 2) == 0)
- xmon_init();
+ xmon_init(1);
+ if (strncmp(p, "off", 3) == 0)
+ xmon_init(0);
if (strncmp(p, "early", 5) != 0)
return 0;
}
- xmon_init();
+ xmon_init(1);
debugger(NULL);
return 0;
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index bf782276984c..347112cca3c0 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -481,10 +481,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
/* Set up Signal Frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- sigaddset(&current->blocked,sig);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
@@ -549,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
if (TRAP(regs) == 0x0C00)
syscall_restart(regs, &ka);
+
+ /*
+ * Reenable the DABR before delivering the signal to
+ * user space. The DABR will have been cleared if it
+ * triggered inside the kernel.
+ */
+ if (current->thread.dabr)
+ set_dabr(current->thread.dabr);
+
return handle_signal(signr, &ka, &info, oldset, regs);
}
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index 3c2fa5c284c0..a8b7a5a56bb4 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -970,17 +970,26 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
newsp = regs->gpr[1];
newsp &= ~0xfUL;
+ /*
+ * Reenable the DABR before delivering the signal to
+ * user space. The DABR will have been cleared if it
+ * triggered inside the kernel.
+ */
+ if (current->thread.dabr)
+ set_dabr(current->thread.dabr);
+
/* Whee! Actually deliver the signal. */
if (ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
else
ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp);
- if (ret && !(ka.sa.sa_flags & SA_NODEFER)) {
+ if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka.sa.sa_mask);
- sigaddset(&current->blocked, signr);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 206619080e66..e93c13458910 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -708,62 +708,9 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
compat_ptr(ubuf));
}
-#define IOBASE_BRIDGE_NUMBER 0
-#define IOBASE_MEMORY 1
-#define IOBASE_IO 2
-#define IOBASE_ISA_IO 3
-#define IOBASE_ISA_MEM 4
-
asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
{
-#ifdef CONFIG_PCI
- struct pci_controller* hose;
- struct list_head *ln;
- struct pci_bus *bus = NULL;
- struct device_node *hose_node;
-
- /* Argh ! Please forgive me for that hack, but that's the
- * simplest way to get existing XFree to not lockup on some
- * G5 machines... So when something asks for bus 0 io base
- * (bus 0 is HT root), we return the AGP one instead.
- */
-#ifdef CONFIG_PPC_PMAC
- if (systemcfg->platform == PLATFORM_POWERMAC &&
- machine_is_compatible("MacRISC4"))
- if (in_bus == 0)
- in_bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
- /* That syscall isn't quite compatible with PCI domains, but it's
- * used on pre-domains setup. We return the first match
- */
-
- for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
- bus = pci_bus_b(ln);
- if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
- break;
- bus = NULL;
- }
- if (bus == NULL || bus->sysdata == NULL)
- return -ENODEV;
-
- hose_node = (struct device_node *)bus->sysdata;
- hose = hose_node->phb;
-
- switch (which) {
- case IOBASE_BRIDGE_NUMBER:
- return (long)hose->first_busno;
- case IOBASE_MEMORY:
- return (long)hose->pci_mem_offset;
- case IOBASE_IO:
- return (long)hose->io_base_phys;
- case IOBASE_ISA_IO:
- return (long)isa_io_base;
- case IOBASE_ISA_MEM:
- return -EINVAL;
- }
-#endif /* CONFIG_PCI */
- return -EOPNOTSUPP;
+ return sys_pciconfig_iobase(which, in_bus, in_devfn);
}
@@ -867,37 +814,6 @@ off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
return sys_lseek(fd, (int)offset, origin);
}
-/*
- * This is just a version for 32-bit applications which does
- * not force O_LARGEFILE on.
- */
-asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
-{
- char * tmp;
- int fd, error;
-
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file * f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (IS_ERR(f))
- goto out_error;
- fd_install(fd, f);
- }
-out:
- putname(tmp);
- }
- return fd;
-
-out_error:
- put_unused_fd(fd);
- fd = error;
- goto out;
-}
-
/* Note: it is necessary to treat bufsiz as an unsigned int,
* with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
index a8cbb202b8cd..05f16633bd2c 100644
--- a/arch/ppc64/kernel/syscalls.c
+++ b/arch/ppc64/kernel/syscalls.c
@@ -46,10 +46,6 @@
extern unsigned long wall_jiffies;
-void
-check_bugs(void)
-{
-}
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 02b8ac4e0168..6654b350979c 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -13,6 +13,7 @@
#include <asm/current.h>
#include <asm/processor.h>
#include <asm/cputable.h>
+#include <asm/firmware.h>
#include <asm/hvcall.h>
#include <asm/prom.h>
#include <asm/systemcfg.h>
@@ -100,6 +101,8 @@ static int __init setup_smt_snooze_delay(char *str)
}
__setup("smt-snooze-delay=", setup_smt_snooze_delay);
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
/*
* Enabling PMCs will slow partition context switch times so we only do
* it the first time we write to the PMCs.
@@ -109,65 +112,15 @@ static DEFINE_PER_CPU(char, pmcs_enabled);
void ppc64_enable_pmcs(void)
{
- unsigned long hid0;
-#ifdef CONFIG_PPC_PSERIES
- unsigned long set, reset;
-#endif /* CONFIG_PPC_PSERIES */
-
/* Only need to enable them once */
if (__get_cpu_var(pmcs_enabled))
return;
__get_cpu_var(pmcs_enabled) = 1;
- switch (systemcfg->platform) {
- case PLATFORM_PSERIES:
- case PLATFORM_POWERMAC:
- hid0 = mfspr(HID0);
- hid0 |= 1UL << (63 - 20);
-
- /* POWER4 requires the following sequence */
- asm volatile(
- "sync\n"
- "mtspr %1, %0\n"
- "mfspr %0, %1\n"
- "mfspr %0, %1\n"
- "mfspr %0, %1\n"
- "mfspr %0, %1\n"
- "mfspr %0, %1\n"
- "mfspr %0, %1\n"
- "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
- "memory");
- break;
-
-#ifdef CONFIG_PPC_PSERIES
- case PLATFORM_PSERIES_LPAR:
- set = 1UL << 63;
- reset = 0;
- plpar_hcall_norets(H_PERFMON, set, reset);
- break;
-#endif /* CONFIG_PPC_PSERIES */
-
- default:
- break;
- }
-
-#ifdef CONFIG_PPC_PSERIES
- /* instruct hypervisor to maintain PMCs */
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
- get_paca()->lppaca.pmcregs_in_use = 1;
-#endif /* CONFIG_PPC_PSERIES */
+ if (ppc_md.enable_pmcs)
+ ppc_md.enable_pmcs();
}
-
-#else
-
-/* PMC stuff */
-void ppc64_enable_pmcs(void)
-{
- /* XXX Implement for iseries */
-}
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
EXPORT_SYMBOL(ppc64_enable_pmcs);
/* XXX convert to rusty's on_one_cpu */
@@ -262,18 +215,23 @@ static void register_cpu_online(unsigned int cpu)
if (cpu_has_feature(CPU_FTR_MMCRA))
sysdev_create_file(s, &attr_mmcra);
- sysdev_create_file(s, &attr_pmc1);
- sysdev_create_file(s, &attr_pmc2);
- sysdev_create_file(s, &attr_pmc3);
- sysdev_create_file(s, &attr_pmc4);
- sysdev_create_file(s, &attr_pmc5);
- sysdev_create_file(s, &attr_pmc6);
-
- if (cpu_has_feature(CPU_FTR_PMC8)) {
+ if (cur_cpu_spec->num_pmcs >= 1)
+ sysdev_create_file(s, &attr_pmc1);
+ if (cur_cpu_spec->num_pmcs >= 2)
+ sysdev_create_file(s, &attr_pmc2);
+ if (cur_cpu_spec->num_pmcs >= 3)
+ sysdev_create_file(s, &attr_pmc3);
+ if (cur_cpu_spec->num_pmcs >= 4)
+ sysdev_create_file(s, &attr_pmc4);
+ if (cur_cpu_spec->num_pmcs >= 5)
+ sysdev_create_file(s, &attr_pmc5);
+ if (cur_cpu_spec->num_pmcs >= 6)
+ sysdev_create_file(s, &attr_pmc6);
+ if (cur_cpu_spec->num_pmcs >= 7)
sysdev_create_file(s, &attr_pmc7);
+ if (cur_cpu_spec->num_pmcs >= 8)
sysdev_create_file(s, &attr_pmc8);
- }
-
+
if (cpu_has_feature(CPU_FTR_SMT))
sysdev_create_file(s, &attr_purr);
}
@@ -299,17 +257,22 @@ static void unregister_cpu_online(unsigned int cpu)
if (cpu_has_feature(CPU_FTR_MMCRA))
sysdev_remove_file(s, &attr_mmcra);
- sysdev_remove_file(s, &attr_pmc1);
- sysdev_remove_file(s, &attr_pmc2);
- sysdev_remove_file(s, &attr_pmc3);
- sysdev_remove_file(s, &attr_pmc4);
- sysdev_remove_file(s, &attr_pmc5);
- sysdev_remove_file(s, &attr_pmc6);
-
- if (cpu_has_feature(CPU_FTR_PMC8)) {
+ if (cur_cpu_spec->num_pmcs >= 1)
+ sysdev_remove_file(s, &attr_pmc1);
+ if (cur_cpu_spec->num_pmcs >= 2)
+ sysdev_remove_file(s, &attr_pmc2);
+ if (cur_cpu_spec->num_pmcs >= 3)
+ sysdev_remove_file(s, &attr_pmc3);
+ if (cur_cpu_spec->num_pmcs >= 4)
+ sysdev_remove_file(s, &attr_pmc4);
+ if (cur_cpu_spec->num_pmcs >= 5)
+ sysdev_remove_file(s, &attr_pmc5);
+ if (cur_cpu_spec->num_pmcs >= 6)
+ sysdev_remove_file(s, &attr_pmc6);
+ if (cur_cpu_spec->num_pmcs >= 7)
sysdev_remove_file(s, &attr_pmc7);
+ if (cur_cpu_spec->num_pmcs >= 8)
sysdev_remove_file(s, &attr_pmc8);
- }
if (cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_purr);
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 909462e1adea..9939c206afa4 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -51,7 +51,6 @@
#include <linux/cpu.h>
#include <linux/security.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/nvram.h>
@@ -67,6 +66,7 @@
#include <asm/prom.h>
#include <asm/sections.h>
#include <asm/systemcfg.h>
+#include <asm/firmware.h>
u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
@@ -128,7 +128,7 @@ static __inline__ void timer_check_rtc(void)
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
- if ( (time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
jiffies - wall_jiffies == 1) {
@@ -370,13 +370,11 @@ int timer_interrupt(struct pt_regs * regs)
process_hvlpevents(regs);
#endif
-/* collect purr register values often, for accurate calculations */
-#if defined(CONFIG_PPC_PSERIES)
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ /* collect purr register values often, for accurate calculations */
+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
cu->current_tb = mfspr(SPRN_PURR);
}
-#endif
irq_exit();
@@ -437,10 +435,7 @@ int do_settimeofday(struct timespec *tv)
*/
last_rtc_update = new_sec - 658;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
do_gtod.varp->tb_to_xs );
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index a8d5e83ee89f..7467ae508e6e 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/kprobes.h>
#include <asm/kdebug.h>
#include <asm/pgtable.h>
@@ -220,7 +221,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
}
-void single_step_exception(struct pt_regs *regs)
+void __kprobes single_step_exception(struct pt_regs *regs)
{
regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
@@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs)
return 0;
}
-void program_check_exception(struct pt_regs *regs)
+void __kprobes program_check_exception(struct pt_regs *regs)
{
if (debugger_fault_handler(regs))
return;
diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
index b6e3bca4102d..41ea09cb9ac7 100644
--- a/arch/ppc64/kernel/u3_iommu.c
+++ b/arch/ppc64/kernel/u3_iommu.c
@@ -276,7 +276,7 @@ static void iommu_dev_setup_u3(struct pci_dev *dev)
dn = pci_device_to_OF_node(dev);
if (dn)
- dn->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_u3;
}
static void iommu_bus_setup_u3(struct pci_bus *bus)
@@ -291,7 +291,7 @@ static void iommu_bus_setup_u3(struct pci_bus *bus)
dn = pci_bus_to_OF_node(bus);
if (dn)
- dn->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_u3;
}
static void iommu_dev_setup_null(struct pci_dev *dev) { }
diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
index c0da45540f0f..d49c3613c8ec 100644
--- a/arch/ppc64/kernel/udbg.c
+++ b/arch/ppc64/kernel/udbg.c
@@ -1,5 +1,5 @@
/*
- * NS16550 Serial Port (uart) debugging stuff.
+ * polling mode stateless debugging stuff, originally for NS16550 Serial Ports
*
* c 2001 PPC 64 Team, IBM Corp
*
@@ -13,249 +13,24 @@
#define WANT_PPCDBG_TAB /* Only defined here */
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/console.h>
#include <asm/ppcdebug.h>
#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pmac_feature.h>
-extern u8 real_readb(volatile u8 __iomem *addr);
-extern void real_writeb(u8 data, volatile u8 __iomem *addr);
-
-struct NS16550 {
- /* this struct must be packed */
- unsigned char rbr; /* 0 */
- unsigned char ier; /* 1 */
- unsigned char fcr; /* 2 */
- unsigned char lcr; /* 3 */
- unsigned char mcr; /* 4 */
- unsigned char lsr; /* 5 */
- unsigned char msr; /* 6 */
- unsigned char scr; /* 7 */
-};
-
-#define thr rbr
-#define iir fcr
-#define dll rbr
-#define dlm ier
-#define dlab lcr
-
-#define LSR_DR 0x01 /* Data ready */
-#define LSR_OE 0x02 /* Overrun */
-#define LSR_PE 0x04 /* Parity error */
-#define LSR_FE 0x08 /* Framing error */
-#define LSR_BI 0x10 /* Break */
-#define LSR_THRE 0x20 /* Xmit holding register empty */
-#define LSR_TEMT 0x40 /* Xmitter empty */
-#define LSR_ERR 0x80 /* Error */
-
-static volatile struct NS16550 __iomem *udbg_comport;
-
-void udbg_init_uart(void __iomem *comport, unsigned int speed)
-{
- u16 dll = speed ? (115200 / speed) : 12;
-
- if (comport) {
- udbg_comport = (struct NS16550 __iomem *)comport;
- out_8(&udbg_comport->lcr, 0x00);
- out_8(&udbg_comport->ier, 0xff);
- out_8(&udbg_comport->ier, 0x00);
- out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */
- out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600,
- 3 = 38400, 12 = 9600 baud */
- out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero
- for fast rates; */
- out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */
- out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */
- out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */
- }
-}
-
-#ifdef CONFIG_PPC_PMAC
-
-#define SCC_TXRDY 4
-#define SCC_RXRDY 1
-
-static volatile u8 __iomem *sccc;
-static volatile u8 __iomem *sccd;
-
-static unsigned char scc_inittab[] = {
- 13, 0, /* set baud rate divisor */
- 12, 0,
- 14, 1, /* baud rate gen enable, src=rtxc */
- 11, 0x50, /* clocks = br gen */
- 5, 0xea, /* tx 8 bits, assert DTR & RTS */
- 4, 0x46, /* x16 clock, 1 stop */
- 3, 0xc1, /* rx enable, 8 bits */
-};
-
-void udbg_init_scc(struct device_node *np)
-{
- u32 *reg;
- unsigned long addr;
- int i, x;
-
- if (np == NULL)
- np = of_find_node_by_name(NULL, "escc");
- if (np == NULL || np->parent == NULL)
- return;
-
- udbg_printf("found SCC...\n");
- /* Get address within mac-io ASIC */
- reg = (u32 *)get_property(np, "reg", NULL);
- if (reg == NULL)
- return;
- addr = reg[0];
- udbg_printf("local addr: %lx\n", addr);
- /* Get address of mac-io PCI itself */
- reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
- if (reg == NULL)
- return;
- addr += reg[2];
- udbg_printf("final addr: %lx\n", addr);
-
- /* Setup for 57600 8N1 */
- addr += 0x20;
- sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
- sccc += addr & ~PAGE_MASK;
- sccd = sccc + 0x10;
-
- udbg_printf("ioremap result sccc: %p\n", sccc);
- mb();
-
- for (i = 20000; i != 0; --i)
- x = in_8(sccc);
- out_8(sccc, 0x09); /* reset A or B side */
- out_8(sccc, 0xc0);
- for (i = 0; i < sizeof(scc_inittab); ++i)
- out_8(sccc, scc_inittab[i]);
-
- ppc_md.udbg_putc = udbg_putc;
- ppc_md.udbg_getc = udbg_getc;
- ppc_md.udbg_getc_poll = udbg_getc_poll;
-
- udbg_puts("Hello World !\n");
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
-#ifdef CONFIG_PPC_PMAC
-static void udbg_real_putc(unsigned char c)
-{
- while ((real_readb(sccc) & SCC_TXRDY) == 0)
- ;
- real_writeb(c, sccd);
- if (c == '\n')
- udbg_real_putc('\r');
-}
-
-void udbg_init_pmac_realmode(void)
-{
- sccc = (volatile u8 __iomem *)0x80013020ul;
- sccd = (volatile u8 __iomem *)0x80013030ul;
-
- ppc_md.udbg_putc = udbg_real_putc;
- ppc_md.udbg_getc = NULL;
- ppc_md.udbg_getc_poll = NULL;
-}
-#endif /* CONFIG_PPC_PMAC */
-
-#ifdef CONFIG_PPC_MAPLE
-void udbg_maple_real_putc(unsigned char c)
-{
- if (udbg_comport) {
- while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
- /* wait for idle */;
- real_writeb(c, &udbg_comport->thr); eieio();
- if (c == '\n') {
- /* Also put a CR. This is for convenience. */
- while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
- /* wait for idle */;
- real_writeb('\r', &udbg_comport->thr); eieio();
- }
- }
-}
-
-void udbg_init_maple_realmode(void)
-{
- udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
-
- ppc_md.udbg_putc = udbg_maple_real_putc;
- ppc_md.udbg_getc = NULL;
- ppc_md.udbg_getc_poll = NULL;
-}
-#endif /* CONFIG_PPC_MAPLE */
-
-void udbg_putc(unsigned char c)
-{
- if (udbg_comport) {
- while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
- /* wait for idle */;
- out_8(&udbg_comport->thr, c);
- if (c == '\n') {
- /* Also put a CR. This is for convenience. */
- while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
- /* wait for idle */;
- out_8(&udbg_comport->thr, '\r');
- }
- }
-#ifdef CONFIG_PPC_PMAC
- else if (sccc) {
- while ((in_8(sccc) & SCC_TXRDY) == 0)
- ;
- out_8(sccd, c);
- if (c == '\n')
- udbg_putc('\r');
- }
-#endif /* CONFIG_PPC_PMAC */
-}
-
-int udbg_getc_poll(void)
-{
- if (udbg_comport) {
- if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
- return in_8(&udbg_comport->rbr);
- else
- return -1;
- }
-#ifdef CONFIG_PPC_PMAC
- else if (sccc) {
- if ((in_8(sccc) & SCC_RXRDY) != 0)
- return in_8(sccd);
- else
- return -1;
- }
-#endif /* CONFIG_PPC_PMAC */
- return -1;
-}
-
-unsigned char udbg_getc(void)
-{
- if (udbg_comport) {
- while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
- /* wait for char */;
- return in_8(&udbg_comport->rbr);
- }
-#ifdef CONFIG_PPC_PMAC
- else if (sccc) {
- while ((in_8(sccc) & SCC_RXRDY) == 0)
- ;
- return in_8(sccd);
- }
-#endif /* CONFIG_PPC_PMAC */
- return 0;
-}
+void (*udbg_putc)(unsigned char c);
+unsigned char (*udbg_getc)(void);
+int (*udbg_getc_poll)(void);
+/* udbg library, used by xmon et al */
void udbg_puts(const char *s)
{
- if (ppc_md.udbg_putc) {
+ if (udbg_putc) {
char c;
if (s && *s != '\0') {
while ((c = *s++) != '\0')
- ppc_md.udbg_putc(c);
+ udbg_putc(c);
}
}
#if 0
@@ -270,12 +45,12 @@ int udbg_write(const char *s, int n)
int remain = n;
char c;
- if (!ppc_md.udbg_putc)
+ if (!udbg_putc)
return 0;
if (s && *s != '\0') {
while (((c = *s++) != '\0') && (remain-- > 0)) {
- ppc_md.udbg_putc(c);
+ udbg_putc(c);
}
}
@@ -287,12 +62,12 @@ int udbg_read(char *buf, int buflen)
char c, *p = buf;
int i;
- if (!ppc_md.udbg_getc)
+ if (!udbg_getc)
return 0;
for (i = 0; i < buflen; ++i) {
do {
- c = ppc_md.udbg_getc();
+ c = udbg_getc();
} while (c == 0x11 || c == 0x13);
if (c == 0)
break;
@@ -302,11 +77,6 @@ int udbg_read(char *buf, int buflen)
return i;
}
-void udbg_console_write(struct console *con, const char *s, unsigned int n)
-{
- udbg_write(s, n);
-}
-
#define UDBG_BUFSIZE 256
void udbg_printf(const char *fmt, ...)
{
@@ -319,6 +89,10 @@ void udbg_printf(const char *fmt, ...)
va_end(args);
}
+/* PPCDBG stuff */
+
+u64 ppc64_debug_switch;
+
/* Special print used by PPCDBG() macro */
void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...)
{
@@ -358,3 +132,49 @@ unsigned long udbg_ifdebug(unsigned long flags)
{
return (flags & ppc64_debug_switch);
}
+
+/*
+ * Initialize the PPCDBG state. Called before relocation has been enabled.
+ */
+void __init ppcdbg_initialize(void)
+{
+ ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
+ /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
+}
+
+/*
+ * Early boot console based on udbg
+ */
+static void udbg_console_write(struct console *con, const char *s,
+ unsigned int n)
+{
+ udbg_write(s, n);
+}
+
+static struct console udbg_console = {
+ .name = "udbg",
+ .write = udbg_console_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static int early_console_initialized;
+
+void __init disable_early_printk(void)
+{
+ if (!early_console_initialized)
+ return;
+ unregister_console(&udbg_console);
+ early_console_initialized = 0;
+}
+
+/* called by setup_system */
+void register_early_udbg_console(void)
+{
+ early_console_initialized = 1;
+ register_console(&udbg_console);
+}
+
+#if 0 /* if you want to use this as a regular output console */
+console_initcall(register_udbg_console);
+#endif
diff --git a/arch/ppc64/kernel/udbg_16550.c b/arch/ppc64/kernel/udbg_16550.c
new file mode 100644
index 000000000000..9313574ab935
--- /dev/null
+++ b/arch/ppc64/kernel/udbg_16550.c
@@ -0,0 +1,123 @@
+/*
+ * udbg for for NS16550 compatable serial ports
+ *
+ * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/udbg.h>
+#include <asm/io.h>
+
+extern u8 real_readb(volatile u8 __iomem *addr);
+extern void real_writeb(u8 data, volatile u8 __iomem *addr);
+
+struct NS16550 {
+ /* this struct must be packed */
+ unsigned char rbr; /* 0 */
+ unsigned char ier; /* 1 */
+ unsigned char fcr; /* 2 */
+ unsigned char lcr; /* 3 */
+ unsigned char mcr; /* 4 */
+ unsigned char lsr; /* 5 */
+ unsigned char msr; /* 6 */
+ unsigned char scr; /* 7 */
+};
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+#define dlab lcr
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+static volatile struct NS16550 __iomem *udbg_comport;
+
+static void udbg_550_putc(unsigned char c)
+{
+ if (udbg_comport) {
+ while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
+ /* wait for idle */;
+ out_8(&udbg_comport->thr, c);
+ if (c == '\n')
+ udbg_550_putc('\r');
+ }
+}
+
+static int udbg_550_getc_poll(void)
+{
+ if (udbg_comport) {
+ if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
+ return in_8(&udbg_comport->rbr);
+ else
+ return -1;
+ }
+ return -1;
+}
+
+static unsigned char udbg_550_getc(void)
+{
+ if (udbg_comport) {
+ while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
+ /* wait for char */;
+ return in_8(&udbg_comport->rbr);
+ }
+ return 0;
+}
+
+void udbg_init_uart(void __iomem *comport, unsigned int speed)
+{
+ u16 dll = speed ? (115200 / speed) : 12;
+
+ if (comport) {
+ udbg_comport = (struct NS16550 __iomem *)comport;
+ out_8(&udbg_comport->lcr, 0x00);
+ out_8(&udbg_comport->ier, 0xff);
+ out_8(&udbg_comport->ier, 0x00);
+ out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */
+ out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600,
+ 3 = 38400, 12 = 9600 baud */
+ out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero
+ for fast rates; */
+ out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */
+ out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */
+ out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */
+ udbg_putc = udbg_550_putc;
+ udbg_getc = udbg_550_getc;
+ udbg_getc_poll = udbg_550_getc_poll;
+ }
+}
+
+#ifdef CONFIG_PPC_MAPLE
+void udbg_maple_real_putc(unsigned char c)
+{
+ if (udbg_comport) {
+ while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
+ /* wait for idle */;
+ real_writeb(c, &udbg_comport->thr); eieio();
+ if (c == '\n')
+ udbg_maple_real_putc('\r');
+ }
+}
+
+void udbg_init_maple_realmode(void)
+{
+ udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
+
+ udbg_putc = udbg_maple_real_putc;
+ udbg_getc = NULL;
+ udbg_getc_poll = NULL;
+}
+#endif /* CONFIG_PPC_MAPLE */
diff --git a/arch/ppc64/kernel/udbg_scc.c b/arch/ppc64/kernel/udbg_scc.c
new file mode 100644
index 000000000000..c47fd6c63531
--- /dev/null
+++ b/arch/ppc64/kernel/udbg_scc.c
@@ -0,0 +1,136 @@
+/*
+ * udbg for for zilog scc ports as found on Apple PowerMacs
+ *
+ * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/udbg.h>
+#include <asm/processor.h>
+#include <asm/naca.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
+
+extern u8 real_readb(volatile u8 __iomem *addr);
+extern void real_writeb(u8 data, volatile u8 __iomem *addr);
+
+#define SCC_TXRDY 4
+#define SCC_RXRDY 1
+
+static volatile u8 __iomem *sccc;
+static volatile u8 __iomem *sccd;
+
+static void udbg_scc_putc(unsigned char c)
+{
+ if (sccc) {
+ while ((in_8(sccc) & SCC_TXRDY) == 0)
+ ;
+ out_8(sccd, c);
+ if (c == '\n')
+ udbg_scc_putc('\r');
+ }
+}
+
+static int udbg_scc_getc_poll(void)
+{
+ if (sccc) {
+ if ((in_8(sccc) & SCC_RXRDY) != 0)
+ return in_8(sccd);
+ else
+ return -1;
+ }
+ return -1;
+}
+
+static unsigned char udbg_scc_getc(void)
+{
+ if (sccc) {
+ while ((in_8(sccc) & SCC_RXRDY) == 0)
+ ;
+ return in_8(sccd);
+ }
+ return 0;
+}
+
+static unsigned char scc_inittab[] = {
+ 13, 0, /* set baud rate divisor */
+ 12, 0,
+ 14, 1, /* baud rate gen enable, src=rtxc */
+ 11, 0x50, /* clocks = br gen */
+ 5, 0xea, /* tx 8 bits, assert DTR & RTS */
+ 4, 0x46, /* x16 clock, 1 stop */
+ 3, 0xc1, /* rx enable, 8 bits */
+};
+
+void udbg_init_scc(struct device_node *np)
+{
+ u32 *reg;
+ unsigned long addr;
+ int i, x;
+
+ if (np == NULL)
+ np = of_find_node_by_name(NULL, "escc");
+ if (np == NULL || np->parent == NULL)
+ return;
+
+ udbg_printf("found SCC...\n");
+ /* Get address within mac-io ASIC */
+ reg = (u32 *)get_property(np, "reg", NULL);
+ if (reg == NULL)
+ return;
+ addr = reg[0];
+ udbg_printf("local addr: %lx\n", addr);
+ /* Get address of mac-io PCI itself */
+ reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
+ if (reg == NULL)
+ return;
+ addr += reg[2];
+ udbg_printf("final addr: %lx\n", addr);
+
+ /* Setup for 57600 8N1 */
+ addr += 0x20;
+ sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
+ sccc += addr & ~PAGE_MASK;
+ sccd = sccc + 0x10;
+
+ udbg_printf("ioremap result sccc: %p\n", sccc);
+ mb();
+
+ for (i = 20000; i != 0; --i)
+ x = in_8(sccc);
+ out_8(sccc, 0x09); /* reset A or B side */
+ out_8(sccc, 0xc0);
+ for (i = 0; i < sizeof(scc_inittab); ++i)
+ out_8(sccc, scc_inittab[i]);
+
+ udbg_putc = udbg_scc_putc;
+ udbg_getc = udbg_scc_getc;
+ udbg_getc_poll = udbg_scc_getc_poll;
+
+ udbg_puts("Hello World !\n");
+}
+
+static void udbg_real_scc_putc(unsigned char c)
+{
+ while ((real_readb(sccc) & SCC_TXRDY) == 0)
+ ;
+ real_writeb(c, sccd);
+ if (c == '\n')
+ udbg_real_scc_putc('\r');
+}
+
+void udbg_init_pmac_realmode(void)
+{
+ sccc = (volatile u8 __iomem *)0x80013020ul;
+ sccd = (volatile u8 __iomem *)0x80013030ul;
+
+ udbg_putc = udbg_real_scc_putc;
+ udbg_getc = NULL;
+ udbg_getc_poll = NULL;
+}
diff --git a/arch/ppc64/kernel/vdso32/cacheflush.S b/arch/ppc64/kernel/vdso32/cacheflush.S
index 0ed7ea721715..c8db993574ee 100644
--- a/arch/ppc64/kernel/vdso32/cacheflush.S
+++ b/arch/ppc64/kernel/vdso32/cacheflush.S
@@ -13,7 +13,7 @@
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/ppc64/kernel/vdso32/datapage.S b/arch/ppc64/kernel/vdso32/datapage.S
index 29b6bd32e1f1..4f4eb0be3992 100644
--- a/arch/ppc64/kernel/vdso32/datapage.S
+++ b/arch/ppc64/kernel/vdso32/datapage.S
@@ -12,7 +12,7 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/vdso.h>
diff --git a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S
index 2b48bf1fb109..07f1c1c650c8 100644
--- a/arch/ppc64/kernel/vdso32/gettimeofday.S
+++ b/arch/ppc64/kernel/vdso32/gettimeofday.S
@@ -13,7 +13,7 @@
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
.text
diff --git a/arch/ppc64/kernel/vdso64/cacheflush.S b/arch/ppc64/kernel/vdso64/cacheflush.S
index e0725b7b7003..d4a0ad28d534 100644
--- a/arch/ppc64/kernel/vdso64/cacheflush.S
+++ b/arch/ppc64/kernel/vdso64/cacheflush.S
@@ -13,7 +13,7 @@
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/ppc64/kernel/vdso64/datapage.S b/arch/ppc64/kernel/vdso64/datapage.S
index 18afd971c9d9..ed6e599ae824 100644
--- a/arch/ppc64/kernel/vdso64/datapage.S
+++ b/arch/ppc64/kernel/vdso64/datapage.S
@@ -12,7 +12,7 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/vdso.h>
diff --git a/arch/ppc64/kernel/vdso64/gettimeofday.S b/arch/ppc64/kernel/vdso64/gettimeofday.S
index ed3f970ff05e..f6df8028570a 100644
--- a/arch/ppc64/kernel/vdso64/gettimeofday.S
+++ b/arch/ppc64/kernel/vdso64/gettimeofday.S
@@ -14,7 +14,7 @@
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
/*
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index 0c0ba71ac0e8..c90e1dd875ce 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -1,10 +1,11 @@
/*
* IBM PowerPC Virtual I/O Infrastructure Support.
*
- * Copyright (c) 2003 IBM Corp.
+ * Copyright (c) 2003-2005 IBM Corp.
* Dave Engebretsen engebret@us.ibm.com
* Santiago Leon santil@us.ibm.com
* Hollis Blanchard <hollisb@us.ibm.com>
+ * Stephen Rothwell
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,61 +15,30 @@
#include <linux/init.h>
#include <linux/console.h>
-#include <linux/version.h>
#include <linux/module.h>
-#include <linux/kobject.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
-#include <asm/rtas.h>
#include <asm/iommu.h>
#include <asm/dma.h>
-#include <asm/ppcdebug.h>
#include <asm/vio.h>
-#include <asm/hvcall.h>
-#include <asm/iSeries/vio.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/HvLpConfig.h>
-
-#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
-
-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
static const struct vio_device_id *vio_match_device(
const struct vio_device_id *, const struct vio_dev *);
-#ifdef CONFIG_PPC_PSERIES
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
-static int vio_num_address_cells;
-#endif
-#ifdef CONFIG_PPC_ISERIES
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
-#endif
-static struct vio_dev vio_bus_device = { /* fake "parent" device */
+struct vio_dev vio_bus_device = { /* fake "parent" device */
.name = vio_bus_device.dev.bus_id,
.type = "",
-#ifdef CONFIG_PPC_ISERIES
- .iommu_table = &vio_iommu_table,
-#endif
.dev.bus_id = "vio",
.dev.bus = &vio_bus_type,
};
-#ifdef CONFIG_PPC_ISERIES
-static struct vio_dev *__init vio_register_device_iseries(char *type,
- uint32_t unit_num);
-
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
-
-#define device_is_compatible(a, b) 1
+static struct vio_bus_ops vio_bus_ops;
-#endif
-
-/* convert from struct device to struct vio_dev and pass to driver.
+/*
+ * Convert from struct device to struct vio_dev and pass to driver.
* dev->driver has already been set by generic code because vio_bus_match
- * succeeded. */
+ * succeeded.
+ */
static int vio_bus_probe(struct device *dev)
{
struct vio_dev *viodev = to_vio_dev(dev);
@@ -76,15 +46,12 @@ static int vio_bus_probe(struct device *dev)
const struct vio_device_id *id;
int error = -ENODEV;
- DBGENTER();
-
if (!viodrv->probe)
return error;
id = vio_match_device(viodrv->id_table, viodev);
- if (id) {
+ if (id)
error = viodrv->probe(viodev, id);
- }
return error;
}
@@ -95,11 +62,8 @@ static int vio_bus_remove(struct device *dev)
struct vio_dev *viodev = to_vio_dev(dev);
struct vio_driver *viodrv = to_vio_driver(dev->driver);
- DBGENTER();
-
- if (viodrv->remove) {
+ if (viodrv->remove)
return viodrv->remove(viodev);
- }
/* driver can't remove */
return 1;
@@ -135,193 +99,72 @@ void vio_unregister_driver(struct vio_driver *viodrv)
EXPORT_SYMBOL(vio_unregister_driver);
/**
- * vio_match_device: - Tell if a VIO device has a matching VIO device id structure.
- * @ids: array of VIO device id structures to search in
- * @dev: the VIO device structure to match against
+ * vio_match_device: - Tell if a VIO device has a matching
+ * VIO device id structure.
+ * @ids: array of VIO device id structures to search in
+ * @dev: the VIO device structure to match against
*
* Used by a driver to check whether a VIO device present in the
* system is in its list of supported devices. Returns the matching
* vio_device_id structure or NULL if there is no match.
*/
-static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
- const struct vio_dev *dev)
+static const struct vio_device_id *vio_match_device(
+ const struct vio_device_id *ids, const struct vio_dev *dev)
{
- DBGENTER();
-
- while (ids->type) {
- if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
- device_is_compatible(dev->dev.platform_data, ids->compat))
+ while (ids->type[0] != '\0') {
+ if (vio_bus_ops.match(ids, dev))
return ids;
ids++;
}
return NULL;
}
-#ifdef CONFIG_PPC_ISERIES
-void __init iommu_vio_init(void)
-{
- struct iommu_table *t;
- struct iommu_table_cb cb;
- unsigned long cbp;
- unsigned long itc_entries;
-
- cb.itc_busno = 255; /* Bus 255 is the virtual bus */
- cb.itc_virtbus = 0xff; /* Ask for virtual bus */
-
- cbp = virt_to_abs(&cb);
- HvCallXm_getTceTableParms(cbp);
-
- itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
- veth_iommu_table.it_size = itc_entries / 2;
- veth_iommu_table.it_busno = cb.itc_busno;
- veth_iommu_table.it_offset = cb.itc_offset;
- veth_iommu_table.it_index = cb.itc_index;
- veth_iommu_table.it_type = TCE_VB;
- veth_iommu_table.it_blocksize = 1;
-
- t = iommu_init_table(&veth_iommu_table);
-
- if (!t)
- printk("Virtual Bus VETH TCE table failed.\n");
-
- vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
- vio_iommu_table.it_busno = cb.itc_busno;
- vio_iommu_table.it_offset = cb.itc_offset +
- veth_iommu_table.it_size;
- vio_iommu_table.it_index = cb.itc_index;
- vio_iommu_table.it_type = TCE_VB;
- vio_iommu_table.it_blocksize = 1;
-
- t = iommu_init_table(&vio_iommu_table);
-
- if (!t)
- printk("Virtual Bus VIO TCE table failed.\n");
-}
-#endif
-
-#ifdef CONFIG_PPC_PSERIES
-static void probe_bus_pseries(void)
-{
- struct device_node *node_vroot, *of_node;
-
- node_vroot = find_devices("vdevice");
- if ((node_vroot == NULL) || (node_vroot->child == NULL))
- /* this machine doesn't do virtual IO, and that's ok */
- return;
-
- vio_num_address_cells = prom_n_addr_cells(node_vroot->child);
-
- /*
- * Create struct vio_devices for each virtual device in the device tree.
- * Drivers will associate with them later.
- */
- for (of_node = node_vroot->child; of_node != NULL;
- of_node = of_node->sibling) {
- printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
- vio_register_device_node(of_node);
- }
-}
-#endif
-
-#ifdef CONFIG_PPC_ISERIES
-static void probe_bus_iseries(void)
-{
- HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();
- struct vio_dev *viodev;
- int i;
-
- /* there is only one of each of these */
- vio_register_device_iseries("viocons", 0);
- vio_register_device_iseries("vscsi", 0);
-
- vlan_map = HvLpConfig_getVirtualLanIndexMap();
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
- if ((vlan_map & (0x8000 >> i)) == 0)
- continue;
- viodev = vio_register_device_iseries("vlan", i);
- /* veth is special and has it own iommu_table */
- viodev->iommu_table = &veth_iommu_table;
- }
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
- vio_register_device_iseries("viodasd", i);
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
- vio_register_device_iseries("viocd", i);
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
- vio_register_device_iseries("viotape", i);
-}
-#endif
-
/**
* vio_bus_init: - Initialize the virtual IO bus
*/
-static int __init vio_bus_init(void)
+int __init vio_bus_init(struct vio_bus_ops *ops)
{
int err;
+ vio_bus_ops = *ops;
+
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
return err;
}
- /* the fake parent of all vio devices, just to give us a nice directory */
+ /*
+ * The fake parent of all vio devices, just to give us
+ * a nice directory
+ */
err = device_register(&vio_bus_device.dev);
if (err) {
- printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
- err);
+ printk(KERN_WARNING "%s: device_register returned %i\n",
+ __FUNCTION__, err);
return err;
}
-#ifdef CONFIG_PPC_PSERIES
- probe_bus_pseries();
-#endif
-#ifdef CONFIG_PPC_ISERIES
- probe_bus_iseries();
-#endif
-
return 0;
}
-__initcall(vio_bus_init);
-
/* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev)
{
- DBGENTER();
-
-#ifdef CONFIG_PPC_PSERIES
- /* XXX free TCE table */
- of_node_put(dev->platform_data);
-#endif
+ if (vio_bus_ops.release_device)
+ vio_bus_ops.release_device(dev);
kfree(to_vio_dev(dev));
}
-#ifdef CONFIG_PPC_PSERIES
-static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct device_node *of_node = dev->platform_data;
-
- return sprintf(buf, "%s\n", of_node->full_name);
-}
-DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
-#endif
-
-static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t viodev_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
}
DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
-static struct vio_dev * __devinit vio_register_device_common(
- struct vio_dev *viodev, char *name, char *type,
- uint32_t unit_address, struct iommu_table *iommu_table)
+struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
{
- DBGENTER();
-
- viodev->name = name;
- viodev->type = type;
- viodev->unit_address = unit_address;
- viodev->iommu_table = iommu_table;
/* init generic 'struct device' fields: */
viodev->dev.parent = &vio_bus_device.dev;
viodev->dev.bus = &vio_bus_type;
@@ -338,222 +181,15 @@ static struct vio_dev * __devinit vio_register_device_common(
return viodev;
}
-#ifdef CONFIG_PPC_PSERIES
-/**
- * vio_register_device_node: - Register a new vio device.
- * @of_node: The OF node for this device.
- *
- * Creates and initializes a vio_dev structure from the data in
- * of_node (dev.platform_data) and adds it to the list of virtual devices.
- * Returns a pointer to the created vio_dev or NULL if node has
- * NULL device_type or compatible fields.
- */
-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
-{
- struct vio_dev *viodev;
- unsigned int *unit_address;
- unsigned int *irq_p;
-
- DBGENTER();
-
- /* we need the 'device_type' property, in order to match with drivers */
- if ((NULL == of_node->type)) {
- printk(KERN_WARNING
- "%s: node %s missing 'device_type'\n", __FUNCTION__,
- of_node->name ? of_node->name : "<unknown>");
- return NULL;
- }
-
- unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
- if (!unit_address) {
- printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
- of_node->name ? of_node->name : "<unknown>");
- return NULL;
- }
-
- /* allocate a vio_dev for this node */
- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
- if (!viodev) {
- return NULL;
- }
- memset(viodev, 0, sizeof(struct vio_dev));
-
- viodev->dev.platform_data = of_node_get(of_node);
-
- viodev->irq = NO_IRQ;
- irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
- if (irq_p) {
- int virq = virt_irq_create_mapping(*irq_p);
- if (virq == NO_IRQ) {
- printk(KERN_ERR "Unable to allocate interrupt "
- "number for %s\n", of_node->full_name);
- } else
- viodev->irq = irq_offset_up(virq);
- }
-
- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
-
- /* register with generic device framework */
- if (vio_register_device_common(viodev, of_node->name, of_node->type,
- *unit_address, vio_build_iommu_table(viodev))
- == NULL) {
- /* XXX free TCE table */
- kfree(viodev);
- return NULL;
- }
- device_create_file(&viodev->dev, &dev_attr_devspec);
-
- return viodev;
-}
-EXPORT_SYMBOL(vio_register_device_node);
-#endif
-
-#ifdef CONFIG_PPC_ISERIES
-/**
- * vio_register_device: - Register a new vio device.
- * @voidev: The device to register.
- */
-static struct vio_dev *__init vio_register_device_iseries(char *type,
- uint32_t unit_num)
-{
- struct vio_dev *viodev;
-
- DBGENTER();
-
- /* allocate a vio_dev for this node */
- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
- if (!viodev)
- return NULL;
- memset(viodev, 0, sizeof(struct vio_dev));
-
- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
-
- return vio_register_device_common(viodev, viodev->dev.bus_id, type,
- unit_num, &vio_iommu_table);
-}
-#endif
-
void __devinit vio_unregister_device(struct vio_dev *viodev)
{
- DBGENTER();
-#ifdef CONFIG_PPC_PSERIES
- device_remove_file(&viodev->dev, &dev_attr_devspec);
-#endif
+ if (vio_bus_ops.unregister_device)
+ vio_bus_ops.unregister_device(viodev);
device_remove_file(&viodev->dev, &dev_attr_name);
device_unregister(&viodev->dev);
}
EXPORT_SYMBOL(vio_unregister_device);
-#ifdef CONFIG_PPC_PSERIES
-/**
- * vio_get_attribute: - get attribute for virtual device
- * @vdev: The vio device to get property.
- * @which: The property/attribute to be extracted.
- * @length: Pointer to length of returned data size (unused if NULL).
- *
- * Calls prom.c's get_property() to return the value of the
- * attribute specified by the preprocessor constant @which
-*/
-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
-{
- return get_property(vdev->dev.platform_data, (char*)which, length);
-}
-EXPORT_SYMBOL(vio_get_attribute);
-
-/* vio_find_name() - internal because only vio.c knows how we formatted the
- * kobject name
- * XXX once vio_bus_type.devices is actually used as a kset in
- * drivers/base/bus.c, this function should be removed in favor of
- * "device_find(kobj_name, &vio_bus_type)"
- */
-static struct vio_dev *vio_find_name(const char *kobj_name)
-{
- struct kobject *found;
-
- found = kset_find_obj(&devices_subsys.kset, kobj_name);
- if (!found)
- return NULL;
-
- return to_vio_dev(container_of(found, struct device, kobj));
-}
-
-/**
- * vio_find_node - find an already-registered vio_dev
- * @vnode: device_node of the virtual device we're looking for
- */
-struct vio_dev *vio_find_node(struct device_node *vnode)
-{
- uint32_t *unit_address;
- char kobj_name[BUS_ID_SIZE];
-
- /* construct the kobject name from the device node */
- unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
- if (!unit_address)
- return NULL;
- snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
-
- return vio_find_name(kobj_name);
-}
-EXPORT_SYMBOL(vio_find_node);
-
-/**
- * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree.
- * @dev: the virtual device.
- *
- * Returns a pointer to the built tce tree, or NULL if it can't
- * find property.
-*/
-static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)
-{
- unsigned int *dma_window;
- struct iommu_table *newTceTable;
- unsigned long offset;
- int dma_window_property_size;
-
- dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
- if(!dma_window) {
- return NULL;
- }
-
- newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
- /* There should be some code to extract the phys-encoded offset
- using prom_n_addr_cells(). However, according to a comment
- on earlier versions, it's always zero, so we don't bother */
- offset = dma_window[1] >> PAGE_SHIFT;
-
- /* TCE table size - measured in tce entries */
- newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
- /* offset for VIO should always be 0 */
- newTceTable->it_offset = offset;
- newTceTable->it_busno = 0;
- newTceTable->it_index = (unsigned long)dma_window[0];
- newTceTable->it_type = TCE_VB;
-
- return iommu_init_table(newTceTable);
-}
-
-int vio_enable_interrupts(struct vio_dev *dev)
-{
- int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
- if (rc != H_Success) {
- printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
- }
- return rc;
-}
-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) {
- printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
- }
- return rc;
-}
-EXPORT_SYMBOL(vio_disable_interrupts);
-#endif
-
static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
@@ -615,18 +251,8 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
const struct vio_dev *vio_dev = to_vio_dev(dev);
struct vio_driver *vio_drv = to_vio_driver(drv);
const struct vio_device_id *ids = vio_drv->id_table;
- const struct vio_device_id *found_id;
-
- DBGENTER();
- if (!ids)
- return 0;
-
- found_id = vio_match_device(ids, vio_dev);
- if (found_id)
- return 1;
-
- return 0;
+ return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
}
struct bus_type vio_bus_type = {
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
index 4103cc13f8d6..0306510bc4ff 100644
--- a/arch/ppc64/kernel/vmlinux.lds.S
+++ b/arch/ppc64/kernel/vmlinux.lds.S
@@ -15,6 +15,7 @@ SECTIONS
*(.text .text.*)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
. = ALIGN(4096);
_etext = .;
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index d9dc6f28d050..daf93885dcfa 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq);
static void xics_end_irq(unsigned int irq);
static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
-struct hw_interrupt_type xics_pic = {
+static struct hw_interrupt_type xics_pic = {
.typename = " XICS ",
.startup = xics_startup,
.enable = xics_enable_irq,
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = {
.set_affinity = xics_set_affinity
};
-struct hw_interrupt_type xics_8259_pic = {
+static struct hw_interrupt_type xics_8259_pic = {
.typename = " XICS/8259",
.ack = xics_mask_and_ack_irq,
};
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
static int xics_irq_8259_cascade = 0;
static int xics_irq_8259_cascade_real = 0;
static unsigned int default_server = 0xFF;
-/* also referenced in smp.c... */
-unsigned int default_distrib_server = 0;
-unsigned int interrupt_server_size = 8;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
/*
* XICS only has a single IPI, so encode the messages per CPU
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8;
struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
/* RTAS service tokens */
-int ibm_get_xive;
-int ibm_set_xive;
-int ibm_int_on;
-int ibm_int_off;
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
typedef struct {
int (*xirr_info_get)(int cpu);
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq)
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
DEFAULT_PRIORITY);
if (call_status != 0) {
- printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive "
- "returned %x\n", irq, call_status);
+ printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
+ "returned %d\n", irq, call_status);
+ printk("set_xive %x, server %x\n", ibm_set_xive, server);
return;
}
/* Now unmask the interrupt (often a no-op) */
call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
if (call_status != 0) {
- printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on "
- "returned %x\n", irq, call_status);
+ printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
+ "returned %d\n", irq, call_status);
return;
}
}
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq)
call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
if (call_status != 0) {
- printk(KERN_ERR "xics_disable_real_irq: irq=%d: "
- "ibm_int_off returned %x\n", irq, call_status);
+ printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
+ "ibm_int_off returned %d\n", irq, call_status);
return;
}
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq)
/* Have to set XIVE to 0xff to be able to remove a slot */
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
if (call_status != 0) {
- printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)"
- " returned %x\n", irq, call_status);
+ printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
+ " returned %d\n", irq, call_status);
return;
}
}
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs)
if (irq == NO_IRQ)
irq = real_irq_to_virt_slowpath(vec);
if (irq == NO_IRQ) {
- printk(KERN_ERR "Interrupt %d (real) is invalid,"
+ printk(KERN_ERR "Interrupt %u (real) is invalid,"
" disabling it.\n", vec);
xics_disable_real_irq(vec);
} else
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
if (status) {
- printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive "
+ printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
"returns %d\n", irq, status);
return;
}
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
irq, newmask, xics_status[1]);
if (status) {
- printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive "
+ printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
"returns %d\n", irq, status);
return;
}
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void)
status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
if (status) {
- printk(KERN_ERR "migrate_irqs_away: irq=%d "
+ printk(KERN_ERR "migrate_irqs_away: irq=%u "
"ibm,get-xive returns %d\n",
virq, status);
goto unlock;
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void)
if (xics_status[0] != get_hard_smp_processor_id(cpu))
goto unlock;
- printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n",
+ printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
virq, cpu);
/* Reset affinity to all cpus */
diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c
index 6e8d8591708c..7b9d4da5cf92 100644
--- a/arch/ppc64/lib/dec_and_lock.c
+++ b/arch/ppc64/lib/dec_and_lock.c
@@ -20,14 +20,7 @@
* has a cmpxchg, and where atomic->value is an int holding
* the value of the atomic (i.e. the high bits aren't used
* for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
*/
-
-#ifndef ATOMIC_DEC_AND_LOCK
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
int counter;
@@ -52,4 +45,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c
index ef70ef91abe2..033643ab69e0 100644
--- a/arch/ppc64/lib/locks.c
+++ b/arch/ppc64/lib/locks.c
@@ -23,12 +23,12 @@
/* waiting for a spinlock... */
#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
-void __spin_yield(spinlock_t *lock)
+void __spin_yield(raw_spinlock_t *lock)
{
unsigned int lock_value, holder_cpu, yield_count;
struct paca_struct *holder_paca;
- lock_value = lock->lock;
+ lock_value = lock->slock;
if (lock_value == 0)
return;
holder_cpu = lock_value & 0xffff;
@@ -38,7 +38,7 @@ void __spin_yield(spinlock_t *lock)
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
- if (lock->lock != lock_value)
+ if (lock->slock != lock_value)
return; /* something has changed */
#ifdef CONFIG_PPC_ISERIES
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
@@ -54,7 +54,7 @@ void __spin_yield(spinlock_t *lock)
* This turns out to be the same for read and write locks, since
* we only know the holder if it is write-locked.
*/
-void __rw_yield(rwlock_t *rw)
+void __rw_yield(raw_rwlock_t *rw)
{
int lock_value;
unsigned int holder_cpu, yield_count;
@@ -82,9 +82,9 @@ void __rw_yield(rwlock_t *rw)
}
#endif
-void spin_unlock_wait(spinlock_t *lock)
+void __raw_spin_unlock_wait(raw_spinlock_t *lock)
{
- while (lock->lock) {
+ while (lock->slock) {
HMT_low();
if (SHARED_PROCESSOR)
__spin_yield(lock);
@@ -92,4 +92,4 @@ void spin_unlock_wait(spinlock_t *lock)
HMT_medium();
}
-EXPORT_SYMBOL(spin_unlock_wait);
+EXPORT_SYMBOL(__raw_spin_unlock_wait);
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 20b0f37e8bf8..7fbc68bbb739 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
+#include <linux/kprobes.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -76,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs)
return 0;
}
+static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+{
+ siginfo_t info;
+
+ if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+ 11, SIGSEGV) == NOTIFY_STOP)
+ return;
+
+ if (debugger_dabr_match(regs))
+ return;
+
+ /* Clear the DABR */
+ set_dabr(0);
+
+ /* Deliver the signal to userspace */
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void __user *)regs->nip;
+ force_sig_info(SIGTRAP, &info, current);
+}
+
/*
* The error_code parameter is
* - DSISR for a non-SLB data access fault,
@@ -84,8 +107,8 @@ static int store_updates_sp(struct pt_regs *regs)
* The return value is 0 if the fault was handled, or the signal
* number if this is a kernel fault that can't be handled here.
*/
-int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned long error_code)
+int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
@@ -110,12 +133,9 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
if (!user_mode(regs) && (address >= TASK_SIZE))
return SIGSEGV;
- if (error_code & DSISR_DABRMATCH) {
- if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
- 11, SIGSEGV) == NOTIFY_STOP)
- return 0;
- if (debugger_dabr_match(regs))
- return 0;
+ if (error_code & DSISR_DABRMATCH) {
+ do_dabr(regs, error_code);
+ return 0;
}
if (in_atomic() || mm == NULL) {
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index fbff24827ae7..ee5a5d36bfa8 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -16,7 +16,7 @@
#include <asm/page.h>
#include <asm/types.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cputable.h>
.text
@@ -129,12 +129,10 @@ _GLOBAL(__hash_page)
* code rather than call a C function...)
*/
BEGIN_FTR_SECTION
-BEGIN_FTR_SECTION
mr r4,r30
mr r5,r7
bl .hash_page_do_lazy_icache
-END_FTR_SECTION_IFSET(CPU_FTR_NOEXECUTE)
-END_FTR_SECTION_IFCLR(CPU_FTR_COHERENT_ICACHE)
+END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
/* At this point, r3 contains new PP bits, save them in
* place of "access" in the param area (sic)
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index a6abd3a979bf..7626bb59954d 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -51,7 +51,6 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long prpn, unsigned long vflags,
unsigned long rflags)
{
- unsigned long arpn = physRpn_to_absRpn(prpn);
hpte_t *hptep = htab_address + hpte_group;
unsigned long hpte_v, hpte_r;
int i;
@@ -74,7 +73,7 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
if (vflags & HPTE_V_LARGE)
va &= ~(1UL << HPTE_V_AVPN_SHIFT);
- hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
+ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
hptep->r = hpte_r;
/* Guarantee the second dword is visible before the valid bit */
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 623b5d130c31..09475c8edf7c 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -210,7 +210,7 @@ void __init htab_initialize(void)
/* create bolted the linear mapping in the hash table */
for (i=0; i < lmb.memory.cnt; i++) {
- base = lmb.memory.region[i].physbase + KERNELBASE;
+ base = lmb.memory.region[i].base + KERNELBASE;
size = lmb.memory.region[i].size;
DBG("creating mapping for region: %lx : %lx\n", base, size);
@@ -302,7 +302,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
int local = 0;
cpumask_t tmp;
- if ((ea & ~REGION_MASK) > EADDR_MASK)
+ if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
return 1;
switch (REGION_ID(ea)) {
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index f9524602818d..338771ec70d7 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -27,124 +27,94 @@
#include <linux/sysctl.h>
-#define HUGEPGDIR_SHIFT (HPAGE_SHIFT + PAGE_SHIFT - 3)
-#define HUGEPGDIR_SIZE (1UL << HUGEPGDIR_SHIFT)
-#define HUGEPGDIR_MASK (~(HUGEPGDIR_SIZE-1))
+#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
+#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
-#define HUGEPTE_INDEX_SIZE 9
-#define HUGEPGD_INDEX_SIZE 10
-
-#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
-#define PTRS_PER_HUGEPGD (1 << HUGEPGD_INDEX_SIZE)
-
-static inline int hugepgd_index(unsigned long addr)
-{
- return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
-}
-
-static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
+/* Modelled after find_linux_pte() */
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
- int index;
+ pgd_t *pg;
+ pud_t *pu;
+ pmd_t *pm;
+ pte_t *pt;
- if (! mm->context.huge_pgdir)
- return NULL;
+ BUG_ON(! in_hugepage_area(mm->context, addr));
+ addr &= HPAGE_MASK;
+
+ pg = pgd_offset(mm, addr);
+ if (!pgd_none(*pg)) {
+ pu = pud_offset(pg, addr);
+ if (!pud_none(*pu)) {
+ pm = pmd_offset(pu, addr);
+ pt = (pte_t *)pm;
+ BUG_ON(!pmd_none(*pm)
+ && !(pte_present(*pt) && pte_huge(*pt)));
+ return pt;
+ }
+ }
- index = hugepgd_index(addr);
- BUG_ON(index >= PTRS_PER_HUGEPGD);
- return (pud_t *)(mm->context.huge_pgdir + index);
+ return NULL;
}
-static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
- int index;
-
- if (pud_none(*dir))
- return NULL;
+ pgd_t *pg;
+ pud_t *pu;
+ pmd_t *pm;
+ pte_t *pt;
- index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
- return (pte_t *)pud_page(*dir) + index;
-}
-
-static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
-{
BUG_ON(! in_hugepage_area(mm->context, addr));
- if (! mm->context.huge_pgdir) {
- pgd_t *new;
- spin_unlock(&mm->page_table_lock);
- /* Don't use pgd_alloc(), because we want __GFP_REPEAT */
- new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
- BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
- spin_lock(&mm->page_table_lock);
+ addr &= HPAGE_MASK;
- /*
- * Because we dropped the lock, we should re-check the
- * entry, as somebody else could have populated it..
- */
- if (mm->context.huge_pgdir)
- pgd_free(new);
- else
- mm->context.huge_pgdir = new;
- }
- return hugepgd_offset(mm, addr);
-}
+ pg = pgd_offset(mm, addr);
+ pu = pud_alloc(mm, pg, addr);
-static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr)
-{
- if (! pud_present(*dir)) {
- pte_t *new;
-
- spin_unlock(&mm->page_table_lock);
- new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
- BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
- spin_lock(&mm->page_table_lock);
- /*
- * Because we dropped the lock, we should re-check the
- * entry, as somebody else could have populated it..
- */
- if (pud_present(*dir)) {
- if (new)
- kmem_cache_free(zero_cache, new);
- } else {
- struct page *ptepage;
-
- if (! new)
- return NULL;
- ptepage = virt_to_page(new);
- ptepage->mapping = (void *) mm;
- ptepage->index = addr & HUGEPGDIR_MASK;
- pud_populate(mm, dir, new);
+ if (pu) {
+ pm = pmd_alloc(mm, pu, addr);
+ if (pm) {
+ pt = (pte_t *)pm;
+ BUG_ON(!pmd_none(*pm)
+ && !(pte_present(*pt) && pte_huge(*pt)));
+ return pt;
}
}
- return hugepte_offset(dir, addr);
+ return NULL;
}
-pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
-{
- pud_t *pud;
+#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
- BUG_ON(! in_hugepage_area(mm->context, addr));
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ int i;
- pud = hugepgd_offset(mm, addr);
- if (! pud)
- return NULL;
+ if (pte_present(*ptep)) {
+ pte_clear(mm, addr, ptep);
+ flush_tlb_pending();
+ }
- return hugepte_offset(pud, addr);
+ for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
+ *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
+ ptep++;
+ }
}
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
{
- pud_t *pud;
+ unsigned long old = pte_update(ptep, ~0UL);
+ int i;
- BUG_ON(! in_hugepage_area(mm->context, addr));
+ if (old & _PAGE_HASHPTE)
+ hpte_update(mm, addr, old, 0);
- pud = hugepgd_alloc(mm, addr);
- if (! pud)
- return NULL;
+ for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
+ ptep[i] = __pte(0);
- return hugepte_alloc(mm, pud, addr);
+ return __pte(old);
}
/*
@@ -162,29 +132,53 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-static void flush_segments(void *parm)
+static void flush_low_segments(void *parm)
{
- u16 segs = (unsigned long) parm;
+ u16 areas = (unsigned long) parm;
unsigned long i;
asm volatile("isync" : : : "memory");
- for (i = 0; i < 16; i++) {
- if (! (segs & (1U << i)))
+ BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
+
+ for (i = 0; i < NUM_LOW_AREAS; i++) {
+ if (! (areas & (1U << i)))
continue;
- asm volatile("slbie %0" : : "r" (i << SID_SHIFT));
+ asm volatile("slbie %0"
+ : : "r" ((i << SID_SHIFT) | SLBIE_C));
}
asm volatile("isync" : : : "memory");
}
-static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg)
+static void flush_high_segments(void *parm)
{
- unsigned long start = seg << SID_SHIFT;
- unsigned long end = (seg+1) << SID_SHIFT;
+ u16 areas = (unsigned long) parm;
+ unsigned long i, j;
+
+ asm volatile("isync" : : : "memory");
+
+ BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
+
+ for (i = 0; i < NUM_HIGH_AREAS; i++) {
+ if (! (areas & (1U << i)))
+ continue;
+ for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
+ asm volatile("slbie %0"
+ :: "r" (((i << HTLB_AREA_SHIFT)
+ + (j << SID_SHIFT)) | SLBIE_C));
+ }
+
+ asm volatile("isync" : : : "memory");
+}
+
+static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
+{
+ unsigned long start = area << SID_SHIFT;
+ unsigned long end = (area+1) << SID_SHIFT;
struct vm_area_struct *vma;
- BUG_ON(seg >= 16);
+ BUG_ON(area >= NUM_LOW_AREAS);
/* Check no VMAs are in the region */
vma = find_vma(mm, start);
@@ -194,20 +188,39 @@ static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg)
return 0;
}
-static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs)
+static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
+{
+ unsigned long start = area << HTLB_AREA_SHIFT;
+ unsigned long end = (area+1) << HTLB_AREA_SHIFT;
+ struct vm_area_struct *vma;
+
+ BUG_ON(area >= NUM_HIGH_AREAS);
+
+ /* Check no VMAs are in the region */
+ vma = find_vma(mm, start);
+ if (vma && (vma->vm_start < end))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
{
unsigned long i;
- newsegs &= ~(mm->context.htlb_segs);
- if (! newsegs)
+ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
+ BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
+
+ newareas &= ~(mm->context.low_htlb_areas);
+ if (! newareas)
return 0; /* The segments we want are already open */
- for (i = 0; i < 16; i++)
- if ((1 << i) & newsegs)
- if (prepare_low_seg_for_htlb(mm, i) != 0)
+ for (i = 0; i < NUM_LOW_AREAS; i++)
+ if ((1 << i) & newareas)
+ if (prepare_low_area_for_htlb(mm, i) != 0)
return -EBUSY;
- mm->context.htlb_segs |= newsegs;
+ mm->context.low_htlb_areas |= newareas;
/* update the paca copy of the context struct */
get_paca()->context = mm->context;
@@ -215,29 +228,63 @@ static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs)
/* the context change must make it to memory before the flush,
* so that further SLB misses do the right thing. */
mb();
- on_each_cpu(flush_segments, (void *)(unsigned long)newsegs, 0, 1);
+ on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
+
+ return 0;
+}
+
+static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
+{
+ unsigned long i;
+
+ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
+ BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
+ != NUM_HIGH_AREAS);
+
+ newareas &= ~(mm->context.high_htlb_areas);
+ if (! newareas)
+ return 0; /* The areas we want are already open */
+
+ for (i = 0; i < NUM_HIGH_AREAS; i++)
+ if ((1 << i) & newareas)
+ if (prepare_high_area_for_htlb(mm, i) != 0)
+ return -EBUSY;
+
+ mm->context.high_htlb_areas |= newareas;
+
+ /* update the paca copy of the context struct */
+ get_paca()->context = mm->context;
+
+ /* the context change must make it to memory before the flush,
+ * so that further SLB misses do the right thing. */
+ mb();
+ on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
return 0;
}
int prepare_hugepage_range(unsigned long addr, unsigned long len)
{
- if (within_hugepage_high_range(addr, len))
- return 0;
- else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) {
- int err;
- /* Yes, we need both tests, in case addr+len overflows
- * 64-bit arithmetic */
- err = open_low_hpage_segs(current->mm,
+ int err;
+
+ if ( (addr+len) < addr )
+ return -EINVAL;
+
+ if ((addr + len) < 0x100000000UL)
+ err = open_low_hpage_areas(current->mm,
LOW_ESID_MASK(addr, len));
- if (err)
- printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
- " failed (segs: 0x%04hx)\n", addr, len,
- LOW_ESID_MASK(addr, len));
+ else
+ err = open_high_hpage_areas(current->mm,
+ HTLB_AREA_MASK(addr, len));
+ if (err) {
+ printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
+ " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
+ addr, len,
+ LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
return err;
}
- return -EINVAL;
+ return 0;
}
struct page *
@@ -309,8 +356,8 @@ full_search:
vma = find_vma(mm, addr);
continue;
}
- if (touches_hugepage_high_range(addr, len)) {
- addr = TASK_HPAGE_END;
+ if (touches_hugepage_high_range(mm, addr, len)) {
+ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
vma = find_vma(mm, addr);
continue;
}
@@ -389,8 +436,9 @@ hugepage_recheck:
if (touches_hugepage_low_range(mm, addr, len)) {
addr = (addr & ((~0) << SID_SHIFT)) - len;
goto hugepage_recheck;
- } else if (touches_hugepage_high_range(addr, len)) {
- addr = TASK_HPAGE_BASE - len;
+ } else if (touches_hugepage_high_range(mm, addr, len)) {
+ addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
+ goto hugepage_recheck;
}
/*
@@ -481,23 +529,28 @@ static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
return -ENOMEM;
}
-static unsigned long htlb_get_high_area(unsigned long len)
+static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
{
- unsigned long addr = TASK_HPAGE_BASE;
+ unsigned long addr = 0x100000000UL;
struct vm_area_struct *vma;
vma = find_vma(current->mm, addr);
- for (vma = find_vma(current->mm, addr);
- addr + len <= TASK_HPAGE_END;
- vma = vma->vm_next) {
+ while (addr + len <= TASK_SIZE_USER64) {
BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
- BUG_ON(! within_hugepage_high_range(addr, len));
+
+ if (! __within_hugepage_high_range(addr, len, areamask)) {
+ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
+ vma = find_vma(current->mm, addr);
+ continue;
+ }
if (!vma || (addr + len) <= vma->vm_start)
return addr;
addr = ALIGN(vma->vm_end, HPAGE_SIZE);
- /* Because we're in a hugepage region, this alignment
- * should not skip us over any VMAs */
+ /* Depending on segmask this might not be a confirmed
+ * hugepage region, so the ALIGN could have skipped
+ * some VMAs */
+ vma = find_vma(current->mm, addr);
}
return -ENOMEM;
@@ -507,6 +560,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
+ int lastshift;
+ u16 areamask, curareas;
+
if (len & ~HPAGE_MASK)
return -EINVAL;
@@ -514,67 +570,49 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return -EINVAL;
if (test_thread_flag(TIF_32BIT)) {
- int lastshift = 0;
- u16 segmask, cursegs = current->mm->context.htlb_segs;
+ curareas = current->mm->context.low_htlb_areas;
/* First see if we can do the mapping in the existing
- * low hpage segments */
- addr = htlb_get_low_area(len, cursegs);
+ * low areas */
+ addr = htlb_get_low_area(len, curareas);
if (addr != -ENOMEM)
return addr;
- for (segmask = LOW_ESID_MASK(0x100000000UL-len, len);
- ! lastshift; segmask >>=1) {
- if (segmask & 1)
+ lastshift = 0;
+ for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
+ ! lastshift; areamask >>=1) {
+ if (areamask & 1)
lastshift = 1;
- addr = htlb_get_low_area(len, cursegs | segmask);
+ addr = htlb_get_low_area(len, curareas | areamask);
if ((addr != -ENOMEM)
- && open_low_hpage_segs(current->mm, segmask) == 0)
+ && open_low_hpage_areas(current->mm, areamask) == 0)
return addr;
}
- printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
- " enough segments\n");
- return -ENOMEM;
} else {
- return htlb_get_high_area(len);
- }
-}
-
-void hugetlb_mm_free_pgd(struct mm_struct *mm)
-{
- int i;
- pgd_t *pgdir;
-
- spin_lock(&mm->page_table_lock);
-
- pgdir = mm->context.huge_pgdir;
- if (! pgdir)
- goto out;
-
- mm->context.huge_pgdir = NULL;
+ curareas = current->mm->context.high_htlb_areas;
- /* cleanup any hugepte pages leftover */
- for (i = 0; i < PTRS_PER_HUGEPGD; i++) {
- pud_t *pud = (pud_t *)(pgdir + i);
-
- if (! pud_none(*pud)) {
- pte_t *pte = (pte_t *)pud_page(*pud);
- struct page *ptepage = virt_to_page(pte);
+ /* First see if we can do the mapping in the existing
+ * high areas */
+ addr = htlb_get_high_area(len, curareas);
+ if (addr != -ENOMEM)
+ return addr;
- ptepage->mapping = NULL;
+ lastshift = 0;
+ for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
+ ! lastshift; areamask >>=1) {
+ if (areamask & 1)
+ lastshift = 1;
- BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));
- kmem_cache_free(zero_cache, pte);
+ addr = htlb_get_high_area(len, curareas | areamask);
+ if ((addr != -ENOMEM)
+ && open_high_hpage_areas(current->mm, areamask) == 0)
+ return addr;
}
- pud_clear(pud);
}
-
- BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));
- kmem_cache_free(zero_cache, pgdir);
-
- out:
- spin_unlock(&mm->page_table_lock);
+ printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
+ " enough areas\n");
+ return -ENOMEM;
}
int hash_huge_page(struct mm_struct *mm, unsigned long access,
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index b6e75b891ac0..c65b87b92756 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -31,7 +31,7 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
break;
if ((unsigned long)tmp->addr >= ioremap_bot)
addr = tmp->size + (unsigned long) tmp->addr;
- if (addr > IMALLOC_END-size)
+ if (addr >= IMALLOC_END-size)
return 1;
}
*im_addr = addr;
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index e58a24d42879..c2157c9c3acb 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -42,7 +42,6 @@
#include <asm/pgalloc.h>
#include <asm/page.h>
-#include <asm/abs_addr.h>
#include <asm/prom.h>
#include <asm/lmb.h>
#include <asm/rtas.h>
@@ -66,6 +65,14 @@
#include <asm/vdso.h>
#include <asm/imalloc.h>
+#if PGTABLE_RANGE > USER_VSID_RANGE
+#warning Limited user VSID range means pagetable space is wasted
+#endif
+
+#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
+#warning TASK_SIZE is smaller than it needs to be.
+#endif
+
int mem_init_done;
unsigned long ioremap_bot = IMALLOC_BASE;
static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -159,7 +166,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
if (!ptep)
return -ENOMEM;
- pa = abs_to_phys(pa);
set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
__pgprot(flags)));
spin_unlock(&init_mm.page_table_lock);
@@ -226,7 +232,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
* Before that, we map using addresses going
* up from ioremap_bot. imalloc will use
* the addresses from ioremap_bot through
- * IMALLOC_END (0xE000001fffffffff)
+ * IMALLOC_END
*
*/
pa = addr & PAGE_MASK;
@@ -386,6 +392,7 @@ void free_initmem(void)
addr = (unsigned long)__init_begin;
for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
+ memset((void *)addr, 0xcc, PAGE_SIZE);
ClearPageReserved(virt_to_page(addr));
set_page_count(virt_to_page(addr), 1);
free_page(addr);
@@ -417,12 +424,6 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
int index;
int err;
-#ifdef CONFIG_HUGETLB_PAGE
- /* We leave htlb_segs as it was, but for a fork, we need to
- * clear the huge_pgdir. */
- mm->context.huge_pgdir = NULL;
-#endif
-
again:
if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
return -ENOMEM;
@@ -453,8 +454,6 @@ void destroy_context(struct mm_struct *mm)
spin_unlock(&mmu_context_lock);
mm->context.id = NO_CONTEXT;
-
- hugetlb_mm_free_pgd(mm);
}
/*
@@ -484,9 +483,9 @@ void __init mm_init_ppc64(void)
for (i = 1; i < lmb.memory.cnt; i++) {
unsigned long base, prevbase, prevsize;
- prevbase = lmb.memory.region[i-1].physbase;
+ prevbase = lmb.memory.region[i-1].base;
prevsize = lmb.memory.region[i-1].size;
- base = lmb.memory.region[i].physbase;
+ base = lmb.memory.region[i].base;
if (base > (prevbase + prevsize)) {
io_hole_start = prevbase + prevsize;
io_hole_size = base - (prevbase + prevsize);
@@ -513,11 +512,8 @@ int page_is_ram(unsigned long pfn)
for (i=0; i < lmb.memory.cnt; i++) {
unsigned long base;
-#ifdef CONFIG_MSCHUNKS
- base = lmb.memory.region[i].physbase;
-#else
base = lmb.memory.region[i].base;
-#endif
+
if ((paddr >= base) &&
(paddr < (base + lmb.memory.region[i].size))) {
return 1;
@@ -547,7 +543,7 @@ void __init do_init_bootmem(void)
*/
bootmap_pages = bootmem_bootmap_pages(total_pages);
- start = abs_to_phys(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE));
+ start = lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
BUG_ON(!start);
boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
@@ -557,27 +553,18 @@ void __init do_init_bootmem(void)
/* Add all physical memory to the bootmem map, mark each area
* present.
*/
- for (i=0; i < lmb.memory.cnt; i++) {
- unsigned long physbase, size;
- unsigned long start_pfn, end_pfn;
-
- physbase = lmb.memory.region[i].physbase;
- size = lmb.memory.region[i].size;
-
- start_pfn = physbase >> PAGE_SHIFT;
- end_pfn = start_pfn + (size >> PAGE_SHIFT);
- memory_present(0, start_pfn, end_pfn);
-
- free_bootmem(physbase, size);
- }
+ for (i=0; i < lmb.memory.cnt; i++)
+ free_bootmem(lmb.memory.region[i].base,
+ lmb_size_bytes(&lmb.memory, i));
/* reserve the sections we're already using */
- for (i=0; i < lmb.reserved.cnt; i++) {
- unsigned long physbase = lmb.reserved.region[i].physbase;
- unsigned long size = lmb.reserved.region[i].size;
+ for (i=0; i < lmb.reserved.cnt; i++)
+ reserve_bootmem(lmb.reserved.region[i].base,
+ lmb_size_bytes(&lmb.reserved, i));
- reserve_bootmem(physbase, size);
- }
+ for (i=0; i < lmb.memory.cnt; i++)
+ memory_present(0, lmb_start_pfn(&lmb.memory, i),
+ lmb_end_pfn(&lmb.memory, i));
}
/*
@@ -615,10 +602,10 @@ static int __init setup_kcore(void)
int i;
for (i=0; i < lmb.memory.cnt; i++) {
- unsigned long physbase, size;
+ unsigned long base, size;
struct kcore_list *kcore_mem;
- physbase = lmb.memory.region[i].physbase;
+ base = lmb.memory.region[i].base;
size = lmb.memory.region[i].size;
/* GFP_ATOMIC to avoid might_sleep warnings during boot */
@@ -626,7 +613,7 @@ static int __init setup_kcore(void)
if (!kcore_mem)
panic("mem_init: kmalloc failed\n");
- kclist_add(kcore_mem, __va(physbase), size);
+ kclist_add(kcore_mem, __va(base), size);
}
kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
@@ -686,9 +673,6 @@ void __init mem_init(void)
mem_init_done = 1;
-#ifdef CONFIG_PPC_ISERIES
- iommu_vio_init();
-#endif
/* Initialize the vDSO */
vdso_init();
}
@@ -833,23 +817,43 @@ void __iomem * reserve_phb_iospace(unsigned long size)
return virt_addr;
}
-kmem_cache_t *zero_cache;
-
-static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
+static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
{
- memset(pte, 0, PAGE_SIZE);
+ memset(addr, 0, kmem_cache_size(cache));
}
+static const int pgtable_cache_size[2] = {
+ PTE_TABLE_SIZE, PMD_TABLE_SIZE
+};
+static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
+ "pgd_pte_cache", "pud_pmd_cache",
+};
+
+kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+
void pgtable_cache_init(void)
{
- zero_cache = kmem_cache_create("zero",
- PAGE_SIZE,
- 0,
- SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,
- zero_ctor,
- NULL);
- if (!zero_cache)
- panic("pgtable_cache_init(): could not create zero_cache!\n");
+ int i;
+
+ BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
+ BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
+ BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
+ BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
+
+ for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
+ int size = pgtable_cache_size[i];
+ const char *name = pgtable_cache_name[i];
+
+ pgtable_cache[i] = kmem_cache_create(name,
+ size, size,
+ SLAB_HWCACHE_ALIGN
+ | SLAB_MUST_HWCACHE_ALIGN,
+ zero_ctor,
+ NULL);
+ if (! pgtable_cache[i])
+ panic("pgtable_cache_init(): could not create %s!\n",
+ name);
+ }
}
pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 0b191f2de016..cb864b8f2750 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -440,8 +440,6 @@ new_range:
for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
numa_domain;
- memory_present(numa_domain, start >> PAGE_SHIFT,
- (start + size) >> PAGE_SHIFT);
if (--ranges)
goto new_range;
@@ -483,7 +481,6 @@ static void __init setup_nonnuma(void)
for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
- memory_present(0, 0, init_node_data[0].node_end_pfn);
}
static void __init dump_numa_topology(void)
@@ -671,7 +668,7 @@ new_range:
* Mark reserved regions on this node
*/
for (i = 0; i < lmb.reserved.cnt; i++) {
- unsigned long physbase = lmb.reserved.region[i].physbase;
+ unsigned long physbase = lmb.reserved.region[i].base;
unsigned long size = lmb.reserved.region[i].size;
if (pa_to_nid(physbase) != nid &&
@@ -695,6 +692,46 @@ new_range:
size);
}
}
+ /*
+ * This loop may look famaliar, but we have to do it again
+ * after marking our reserved memory to mark memory present
+ * for sparsemem.
+ */
+ addr_cells = get_mem_addr_cells();
+ size_cells = get_mem_size_cells();
+ memory = NULL;
+ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+ unsigned long mem_start, mem_size;
+ int numa_domain, ranges;
+ unsigned int *memcell_buf;
+ unsigned int len;
+
+ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+ if (!memcell_buf || len <= 0)
+ continue;
+
+ ranges = memory->n_addrs; /* ranges in cell */
+new_range2:
+ mem_start = read_n_cells(addr_cells, &memcell_buf);
+ mem_size = read_n_cells(size_cells, &memcell_buf);
+ if (numa_enabled) {
+ numa_domain = of_node_numa_domain(memory);
+ if (numa_domain >= MAX_NUMNODES)
+ numa_domain = 0;
+ } else
+ numa_domain = 0;
+
+ if (numa_domain != nid)
+ continue;
+
+ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+ memory_present(numa_domain, mem_start >> PAGE_SHIFT,
+ (mem_start + mem_size) >> PAGE_SHIFT);
+
+ if (--ranges) /* process all ranges in cell */
+ goto new_range2;
+ }
+
}
}
diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
index 244150a0bc18..0473953f6a37 100644
--- a/arch/ppc64/mm/slb.c
+++ b/arch/ppc64/mm/slb.c
@@ -87,8 +87,8 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
int i;
asm volatile("isync" : : : "memory");
for (i = 0; i < offset; i++) {
- esid_data = (unsigned long)get_paca()->slb_cache[i]
- << SID_SHIFT;
+ esid_data = ((unsigned long)get_paca()->slb_cache[i]
+ << SID_SHIFT) | SLBIE_C;
asm volatile("slbie %0" : : "r" (esid_data));
}
asm volatile("isync" : : : "memory");
diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
index 8379d678f70f..a3a03da503bc 100644
--- a/arch/ppc64/mm/slb_low.S
+++ b/arch/ppc64/mm/slb_low.S
@@ -21,7 +21,7 @@
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cputable.h>
/* void slb_allocate(unsigned long ea);
@@ -89,32 +89,29 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
b 9f
0: /* user address: proto-VSID = context<<15 | ESID */
- li r11,SLB_VSID_USER
-
- srdi. r9,r3,13
+ srdi. r9,r3,USER_ESID_BITS
bne- 8f /* invalid ea bits set */
#ifdef CONFIG_HUGETLB_PAGE
BEGIN_FTR_SECTION
- /* check against the hugepage ranges */
- cmpldi r3,(TASK_HPAGE_END>>SID_SHIFT)
- bge 6f /* >= TASK_HPAGE_END */
- cmpldi r3,(TASK_HPAGE_BASE>>SID_SHIFT)
- bge 5f /* TASK_HPAGE_BASE..TASK_HPAGE_END */
- cmpldi r3,16
- bge 6f /* 4GB..TASK_HPAGE_BASE */
-
- lhz r9,PACAHTLBSEGS(r13)
- srd r9,r9,r3
- andi. r9,r9,1
- beq 6f
-
-5: /* this is a hugepage user address */
- li r11,(SLB_VSID_USER|SLB_VSID_L)
+ lhz r9,PACAHIGHHTLBAREAS(r13)
+ srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
+ srd r9,r9,r11
+ lhz r11,PACALOWHTLBAREAS(r13)
+ srd r11,r11,r3
+ or r9,r9,r11
+END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
+#endif /* CONFIG_HUGETLB_PAGE */
+
+ li r11,SLB_VSID_USER
+
+#ifdef CONFIG_HUGETLB_PAGE
+BEGIN_FTR_SECTION
+ rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */
END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
#endif /* CONFIG_HUGETLB_PAGE */
-6: ld r9,PACACONTEXTID(r13)
+ ld r9,PACACONTEXTID(r13)
rldimi r3,r9,USER_ESID_BITS,0
9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
index 26f0172c4527..d8a6593a13f0 100644
--- a/arch/ppc64/mm/tlb.c
+++ b/arch/ppc64/mm/tlb.c
@@ -41,7 +41,58 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
unsigned long pte_freelist_forced_free;
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
+struct pte_freelist_batch
+{
+ struct rcu_head rcu;
+ unsigned int index;
+ pgtable_free_t tables[0];
+};
+
+DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
+unsigned long pte_freelist_forced_free;
+
+#define PTE_FREELIST_SIZE \
+ ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
+ / sizeof(pgtable_free_t))
+
+#ifdef CONFIG_SMP
+static void pte_free_smp_sync(void *arg)
+{
+ /* Do nothing, just ensure we sync with all CPUs */
+}
+#endif
+
+/* This is only called when we are critically out of memory
+ * (and fail to get a page in pte_free_tlb).
+ */
+static void pgtable_free_now(pgtable_free_t pgf)
+{
+ pte_freelist_forced_free++;
+
+ smp_call_function(pte_free_smp_sync, NULL, 0, 1);
+
+ pgtable_free(pgf);
+}
+
+static void pte_free_rcu_callback(struct rcu_head *head)
+{
+ struct pte_freelist_batch *batch =
+ container_of(head, struct pte_freelist_batch, rcu);
+ unsigned int i;
+
+ for (i = 0; i < batch->index; i++)
+ pgtable_free(batch->tables[i]);
+
+ free_page((unsigned long)batch);
+}
+
+static void pte_free_submit(struct pte_freelist_batch *batch)
+{
+ INIT_RCU_HEAD(&batch->rcu);
+ call_rcu(&batch->rcu, pte_free_rcu_callback);
+}
+
+void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
{
/* This is safe as we are holding page_table_lock */
cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
@@ -49,19 +100,19 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
if (atomic_read(&tlb->mm->mm_users) < 2 ||
cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
- pte_free(ptepage);
+ pgtable_free(pgf);
return;
}
if (*batchp == NULL) {
*batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
if (*batchp == NULL) {
- pte_free_now(ptepage);
+ pgtable_free_now(pgf);
return;
}
(*batchp)->index = 0;
}
- (*batchp)->pages[(*batchp)->index++] = ptepage;
+ (*batchp)->tables[(*batchp)->index++] = pgf;
if ((*batchp)->index == PTE_FREELIST_SIZE) {
pte_free_submit(*batchp);
*batchp = NULL;
@@ -132,42 +183,6 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
put_cpu();
}
-#ifdef CONFIG_SMP
-static void pte_free_smp_sync(void *arg)
-{
- /* Do nothing, just ensure we sync with all CPUs */
-}
-#endif
-
-/* This is only called when we are critically out of memory
- * (and fail to get a page in pte_free_tlb).
- */
-void pte_free_now(struct page *ptepage)
-{
- pte_freelist_forced_free++;
-
- smp_call_function(pte_free_smp_sync, NULL, 0, 1);
-
- pte_free(ptepage);
-}
-
-static void pte_free_rcu_callback(struct rcu_head *head)
-{
- struct pte_freelist_batch *batch =
- container_of(head, struct pte_freelist_batch, rcu);
- unsigned int i;
-
- for (i = 0; i < batch->index; i++)
- pte_free(batch->pages[i]);
- free_page((unsigned long)batch);
-}
-
-void pte_free_submit(struct pte_freelist_batch *batch)
-{
- INIT_RCU_HEAD(&batch->rcu);
- call_rcu(&batch->rcu, pte_free_rcu_callback);
-}
-
void pte_free_finish(void)
{
/* This is safe as we are holding page_table_lock */
diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
index b28bfda23d94..e5f572710aa0 100644
--- a/arch/ppc64/oprofile/common.c
+++ b/arch/ppc64/oprofile/common.c
@@ -16,11 +16,9 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/pmc.h>
+#include <asm/cputable.h>
+#include <asm/oprofile_impl.h>
-#include "op_impl.h"
-
-extern struct op_ppc64_model op_model_rs64;
-extern struct op_ppc64_model op_model_power4;
static struct op_ppc64_model *model;
static struct op_counter_config ctr[OP_MAX_COUNTER];
@@ -123,52 +121,13 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
- unsigned int pvr;
-
- pvr = mfspr(SPRN_PVR);
-
- switch (PVR_VER(pvr)) {
- case PV_630:
- case PV_630p:
- model = &op_model_rs64;
- model->num_counters = 8;
- ops->cpu_type = "ppc64/power3";
- break;
-
- case PV_NORTHSTAR:
- case PV_PULSAR:
- case PV_ICESTAR:
- case PV_SSTAR:
- model = &op_model_rs64;
- model->num_counters = 8;
- ops->cpu_type = "ppc64/rs64";
- break;
-
- case PV_POWER4:
- case PV_POWER4p:
- model = &op_model_power4;
- model->num_counters = 8;
- ops->cpu_type = "ppc64/power4";
- break;
-
- case PV_970:
- case PV_970FX:
- model = &op_model_power4;
- model->num_counters = 8;
- ops->cpu_type = "ppc64/970";
- break;
-
- case PV_POWER5:
- case PV_POWER5p:
- model = &op_model_power4;
- model->num_counters = 6;
- ops->cpu_type = "ppc64/power5";
- break;
-
- default:
- return -ENODEV;
- }
+ if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type)
+ return -ENODEV;
+
+ model = cur_cpu_spec->oprofile_model;
+ model->num_counters = cur_cpu_spec->num_pmcs;
+ ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
ops->create_files = op_ppc64_create_files;
ops->setup = op_ppc64_setup;
ops->shutdown = op_ppc64_shutdown;
diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
index 3d103d66870d..32b2bb5625fe 100644
--- a/arch/ppc64/oprofile/op_model_power4.c
+++ b/arch/ppc64/oprofile/op_model_power4.c
@@ -16,14 +16,12 @@
#include <asm/cputable.h>
#include <asm/systemcfg.h>
#include <asm/rtas.h>
+#include <asm/oprofile_impl.h>
#define dbg(args...)
-#include "op_impl.h"
-
static unsigned long reset_value[OP_MAX_COUNTER];
-static int num_counters;
static int oprofile_running;
static int mmcra_has_sihv;
@@ -45,8 +43,6 @@ static void power4_reg_setup(struct op_counter_config *ctr,
{
int i;
- num_counters = num_ctrs;
-
/*
* SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
* However we disable it on all POWER4 until we verify it works
@@ -68,7 +64,7 @@ static void power4_reg_setup(struct op_counter_config *ctr,
backtrace_spinlocks = sys->backtrace_spinlocks;
- for (i = 0; i < num_counters; ++i)
+ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;
/* setup user and kernel profiling */
@@ -121,7 +117,7 @@ static void power4_start(struct op_counter_config *ctr)
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
- for (i = 0; i < num_counters; ++i) {
+ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
if (ctr[i].enabled) {
ctr_write(i, reset_value[i]);
} else {
@@ -272,7 +268,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
- for (i = 0; i < num_counters; ++i) {
+ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
index bcec506c266a..08c5b333f5c4 100644
--- a/arch/ppc64/oprofile/op_model_rs64.c
+++ b/arch/ppc64/oprofile/op_model_rs64.c
@@ -14,11 +14,10 @@
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/cputable.h>
+#include <asm/oprofile_impl.h>
#define dbg(args...)
-#include "op_impl.h"
-
static void ctrl_write(unsigned int i, unsigned int val)
{
unsigned int tmp = 0;
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h
index 183c3e400258..02eb40dac0b3 100644
--- a/arch/ppc64/xmon/privinst.h
+++ b/arch/ppc64/xmon/privinst.h
@@ -46,7 +46,6 @@ GSETSPR(287, pvr)
GSETSPR(1008, hid0)
GSETSPR(1009, hid1)
GSETSPR(1010, iabr)
-GSETSPR(1013, dabr)
GSETSPR(1023, pir)
static inline void store_inst(void *p)
diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
index a9265bcc79b2..e50c158191e1 100644
--- a/arch/ppc64/xmon/start.c
+++ b/arch/ppc64/xmon/start.c
@@ -27,7 +27,7 @@ static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
/* ensure xmon is enabled */
- xmon_init();
+ xmon_init(1);
debugger(pt_regs);
}
@@ -61,7 +61,9 @@ xmon_read(void *handle, void *ptr, int nb)
int
xmon_read_poll(void)
{
- return udbg_getc_poll();
+ if (udbg_getc_poll)
+ return udbg_getc_poll();
+ return -1;
}
FILE *xmon_stdin;
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 05539439e6bc..74e63a886a69 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs)
{
if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
return 0;
+ if (dabr.enabled == 0)
+ return 0;
xmon_core(regs, 0);
return 1;
}
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs)
return 0;
}
-/* On systems with a hypervisor, we can't set the DABR
- (data address breakpoint register) directly. */
-static void set_controlled_dabr(unsigned long val)
-{
-#ifdef CONFIG_PPC_PSERIES
- if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
- int rc = plpar_hcall_norets(H_SET_DABR, val);
- if (rc != H_Success)
- xmon_printf("Warning: setting DABR failed (%d)\n", rc);
- } else
-#endif
- set_dabr(val);
-}
-
static struct bpt *at_breakpoint(unsigned long pc)
{
int i;
@@ -728,7 +716,7 @@ static void insert_bpts(void)
static void insert_cpu_bpts(void)
{
if (dabr.enabled)
- set_controlled_dabr(dabr.address | (dabr.enabled & 7));
+ set_dabr(dabr.address | (dabr.enabled & 7));
if (iabr && cpu_has_feature(CPU_FTR_IABR))
set_iabr(iabr->address
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -756,7 +744,7 @@ static void remove_bpts(void)
static void remove_cpu_bpts(void)
{
- set_controlled_dabr(0);
+ set_dabr(0);
if (cpu_has_feature(CPU_FTR_IABR))
set_iabr(0);
}
@@ -2496,15 +2484,25 @@ static void dump_stab(void)
}
}
-void xmon_init(void)
+void xmon_init(int enable)
{
- __debugger = xmon;
- __debugger_ipi = xmon_ipi;
- __debugger_bpt = xmon_bpt;
- __debugger_sstep = xmon_sstep;
- __debugger_iabr_match = xmon_iabr_match;
- __debugger_dabr_match = xmon_dabr_match;
- __debugger_fault_handler = xmon_fault_handler;
+ if (enable) {
+ __debugger = xmon;
+ __debugger_ipi = xmon_ipi;
+ __debugger_bpt = xmon_bpt;
+ __debugger_sstep = xmon_sstep;
+ __debugger_iabr_match = xmon_iabr_match;
+ __debugger_dabr_match = xmon_dabr_match;
+ __debugger_fault_handler = xmon_fault_handler;
+ } else {
+ __debugger = NULL;
+ __debugger_ipi = NULL;
+ __debugger_bpt = NULL;
+ __debugger_sstep = NULL;
+ __debugger_iabr_match = NULL;
+ __debugger_dabr_match = NULL;
+ __debugger_fault_handler = NULL;
+ }
}
void dump_segments(void)
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 3cd8dd25c9d7..98db30481d97 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -19,6 +19,7 @@ CFLAGS += -m31
AFLAGS += -m31
UTS_MACHINE := s390
STACK_SIZE := 8192
+CHECKFLAGS += -D__s390__
endif
ifdef CONFIG_ARCH_S390X
@@ -28,6 +29,7 @@ CFLAGS += -m64
AFLAGS += -m64
UTS_MACHINE := s390x
STACK_SIZE := 16384
+CHECKFLAGS += -D__s390__ -D__s390x__
endif
cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5)
@@ -100,16 +102,6 @@ image: vmlinux
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-prepare: include/asm-$(ARCH)/offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h
-
# Don't use tabs in echo arguments
define archhelp
echo '* image - Kernel image for IPL ($(boot)/image)'
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 18610cea03a2..ed877d0f27e6 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -678,7 +678,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size
ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
set_fs(old_fs);
- if (!ret && offset && put_user(of, offset))
+ if (offset && put_user(of, offset))
return -EFAULT;
return ret;
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index d05d65ac9694..7358cdb8441f 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -637,12 +637,11 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
else
setup_frame32(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 960ba6029c3a..bc59282da762 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -62,7 +62,7 @@ typedef struct
} debug_sprintf_entry_t;
-extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
+extern void tod_to_timeval(uint64_t todval, struct timespec *xtime);
/* internal function prototyes */
@@ -374,9 +374,24 @@ debug_info_copy(debug_info_t* in, int mode)
{
int i,j;
debug_info_t* rc;
+ unsigned long flags;
+
+ /* get a consistent copy of the debug areas */
+ do {
+ rc = debug_info_alloc(in->name, in->pages_per_area,
+ in->nr_areas, in->buf_size, in->level, mode);
+ spin_lock_irqsave(&in->lock, flags);
+ if(!rc)
+ goto out;
+ /* has something changed in the meantime ? */
+ if((rc->pages_per_area == in->pages_per_area) &&
+ (rc->nr_areas == in->nr_areas)) {
+ break;
+ }
+ spin_unlock_irqrestore(&in->lock, flags);
+ debug_info_free(rc);
+ } while (1);
- rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas,
- in->buf_size, in->level, mode);
if(!rc || (mode == NO_AREAS))
goto out;
@@ -386,6 +401,7 @@ debug_info_copy(debug_info_t* in, int mode)
}
}
out:
+ spin_unlock_irqrestore(&in->lock, flags);
return rc;
}
@@ -593,19 +609,15 @@ debug_open(struct inode *inode, struct file *file)
debug_info_t *debug_info, *debug_info_snapshot;
down(&debug_lock);
-
- /* find debug log and view */
- debug_info = debug_area_first;
- while(debug_info != NULL){
- for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
- if (!debug_info->views[i])
- continue;
- else if (debug_info->debugfs_entries[i] ==
- file->f_dentry) {
- goto found; /* found view ! */
- }
+ debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
+ /* find debug view */
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ if (!debug_info->views[i])
+ continue;
+ else if (debug_info->debugfs_entries[i] ==
+ file->f_dentry) {
+ goto found; /* found view ! */
}
- debug_info = debug_info->next;
}
/* no entry found */
rc = -EINVAL;
@@ -833,7 +845,7 @@ extern inline void
debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
int exception)
{
- STCK(active->id.stck);
+ active->id.stck = get_clock();
active->id.fields.cpuid = smp_processor_id();
active->caller = __builtin_return_address(0);
active->id.fields.exception = exception;
@@ -1078,7 +1090,7 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
if (view->input_proc)
mode |= S_IWUSR;
pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
- NULL, &debug_file_ops);
+ id , &debug_file_ops);
if (!pde){
printk(KERN_WARNING "debug: debugfs_create_file() failed!"\
" Cannot register view %s/%s\n", id->name,view->name);
@@ -1432,7 +1444,7 @@ int
debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
int area, debug_entry_t * entry, char *out_buf)
{
- struct timeval time_val;
+ struct timespec time_spec;
unsigned long long time;
char *except_str;
unsigned long caller;
@@ -1443,7 +1455,7 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
time = entry->id.stck;
/* adjust todclock to 1970 */
time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
- tod_to_timeval(time, &time_val);
+ tod_to_timeval(time, &time_spec);
if (entry->id.fields.exception)
except_str = "*";
@@ -1451,7 +1463,7 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
except_str = "-";
caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN;
rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p ",
- area, time_val.tv_sec, time_val.tv_usec, level,
+ area, time_spec.tv_sec, time_spec.tv_nsec / 1000, level,
except_str, entry->id.fields.cpuid, (void *) caller);
return rc;
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1a271b16cb5c..58fc7fbcb40e 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -18,7 +18,7 @@
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/page.h>
@@ -138,14 +138,14 @@ STACK_SIZE = 1 << STACK_SHIFT
st %r12,__SF_BACKCHAIN(%r15) # clear back chain
.endm
- .macro RESTORE_ALL sync
- mvc __LC_RETURN_PSW(8),SP_PSW(%r15) # move user PSW to lowcore
+ .macro RESTORE_ALL psworg,sync
+ mvc \psworg(8),SP_PSW(%r15) # move user PSW to lowcore
.if !\sync
- ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
+ ni \psworg+1,0xfd # clear wait state bit
.endif
lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
STORE_TIMER __LC_EXIT_TIMER
- lpsw __LC_RETURN_PSW # back to caller
+ lpsw \psworg # back to caller
.endm
/*
@@ -235,7 +235,7 @@ sysc_return:
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_leave:
- RESTORE_ALL 1
+ RESTORE_ALL __LC_RETURN_PSW,1
#
# recheck if there is more work to do
@@ -312,8 +312,6 @@ sysc_singlestep:
la %r14,BASED(sysc_return) # load adr. of system return
br %r1 # branch to do_single_step
-__critical_end:
-
#
# call trace before and after sys_call
#
@@ -571,7 +569,8 @@ io_return:
tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.)
io_leave:
- RESTORE_ALL 0
+ RESTORE_ALL __LC_RETURN_PSW,0
+io_done:
#ifdef CONFIG_PREEMPT
io_preempt:
@@ -621,7 +620,7 @@ io_work_loop:
#
io_mcck_pending:
l %r1,BASED(.Ls390_handle_mcck)
- l %r14,BASED(io_work_loop)
+ la %r14,BASED(io_work_loop)
br %r1 # TIF bit will be cleared by handler
#
@@ -674,6 +673,8 @@ ext_no_vtime:
basr %r14,%r1
b BASED(io_return)
+__critical_end:
+
/*
* Machine check handler routines
*/
@@ -681,6 +682,7 @@ ext_no_vtime:
.globl mcck_int_handler
mcck_int_handler:
spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
+ mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+32
la %r12,__LC_MCK_OLD_PSW
@@ -693,17 +695,8 @@ mcck_int_handler:
mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER
-0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
- bno BASED(mcck_no_vtime) # no -> skip cleanup critical
- tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
- bz BASED(mcck_no_vtime)
- UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
- UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
- mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
-mcck_no_vtime:
#endif
-0:
- tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
+0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
bno BASED(mcck_int_main) # no -> skip cleanup critical
tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
bnz BASED(mcck_int_main) # from user -> load async stack
@@ -720,6 +713,16 @@ mcck_int_main:
be BASED(0f)
l %r15,__LC_PANIC_STACK # load panic stack
0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
+ bno BASED(mcck_no_vtime) # no -> skip cleanup critical
+ tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
+ bz BASED(mcck_no_vtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+mcck_no_vtime:
+#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ls390_mcck)
@@ -737,7 +740,7 @@ mcck_int_main:
l %r1,BASED(.Ls390_handle_mcck)
basr %r14,%r1 # call machine check handler
mcck_return:
- RESTORE_ALL 0
+ RESTORE_ALL __LC_RETURN_MCCK_PSW,0
#ifdef CONFIG_SMP
/*
@@ -803,6 +806,10 @@ cleanup_table_sysc_leave:
.long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000
cleanup_table_sysc_work_loop:
.long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000
+cleanup_table_io_leave:
+ .long io_leave + 0x80000000, io_done + 0x80000000
+cleanup_table_io_work_loop:
+ .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000
cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_system_call)
@@ -825,10 +832,26 @@ cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
bl BASED(cleanup_sysc_return)
0:
+ clc 4(4,%r12),BASED(cleanup_table_io_leave)
+ bl BASED(0f)
+ clc 4(4,%r12),BASED(cleanup_table_io_leave+4)
+ bl BASED(cleanup_io_leave)
+0:
+ clc 4(4,%r12),BASED(cleanup_table_io_work_loop)
+ bl BASED(0f)
+ clc 4(4,%r12),BASED(cleanup_table_io_work_loop+4)
+ bl BASED(cleanup_io_return)
+0:
br %r14
cleanup_system_call:
mvc __LC_RETURN_PSW(8),0(%r12)
+ c %r12,BASED(.Lmck_old_psw)
+ be BASED(0f)
+ la %r12,__LC_SAVE_AREA+16
+ b BASED(1f)
+0: la %r12,__LC_SAVE_AREA+32
+1:
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)
bh BASED(0f)
@@ -838,11 +861,13 @@ cleanup_system_call:
#endif
clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn)
bh BASED(0f)
- mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16
-0: st %r13,__LC_SAVE_AREA+20
+ mvc __LC_SAVE_AREA(16),0(%r12)
+0: st %r13,4(%r12)
+ st %r12,__LC_SAVE_AREA+48 # argh
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
- st %r15,__LC_SAVE_AREA+28
+ l %r12,__LC_SAVE_AREA+48 # argh
+ st %r15,12(%r12)
lh %r7,0x8a
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
cleanup_vtime:
@@ -879,17 +904,21 @@ cleanup_sysc_return:
cleanup_sysc_leave:
clc 4(4,%r12),BASED(cleanup_sysc_leave_insn)
- be BASED(0f)
+ be BASED(2f)
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4)
- be BASED(0f)
+ be BASED(2f)
#endif
mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
- mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
- lm %r0,%r11,SP_R0(%r15)
+ c %r12,BASED(.Lmck_old_psw)
+ bne BASED(0f)
+ mvc __LC_SAVE_AREA+32(16),SP_R12(%r15)
+ b BASED(1f)
+0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
+1: lm %r0,%r11,SP_R0(%r15)
l %r15,SP_R15(%r15)
-0: la %r12,__LC_RETURN_PSW
+2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_sysc_leave_insn:
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -897,6 +926,36 @@ cleanup_sysc_leave_insn:
#endif
.long sysc_leave + 10 + 0x80000000
+cleanup_io_return:
+ mvc __LC_RETURN_PSW(4),0(%r12)
+ mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop)
+ la %r12,__LC_RETURN_PSW
+ br %r14
+
+cleanup_io_leave:
+ clc 4(4,%r12),BASED(cleanup_io_leave_insn)
+ be BASED(2f)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ clc 4(4,%r12),BASED(cleanup_io_leave_insn+4)
+ be BASED(2f)
+#endif
+ mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
+ c %r12,BASED(.Lmck_old_psw)
+ bne BASED(0f)
+ mvc __LC_SAVE_AREA+32(16),SP_R12(%r15)
+ b BASED(1f)
+0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
+1: lm %r0,%r11,SP_R0(%r15)
+ l %r15,SP_R15(%r15)
+2: la %r12,__LC_RETURN_PSW
+ br %r14
+cleanup_io_leave_insn:
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .long io_leave + 18 + 0x80000000
+#endif
+ .long io_leave + 14 + 0x80000000
+
/*
* Integer constants
*/
@@ -918,6 +977,7 @@ cleanup_sysc_leave_insn:
.Ls390_mcck: .long s390_do_machine_check
.Ls390_handle_mcck:
.long s390_handle_mcck
+.Lmck_old_psw: .long __LC_MCK_OLD_PSW
.Ldo_IRQ: .long do_IRQ
.Ldo_extint: .long do_extint
.Ldo_signal: .long do_signal
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d9f22915008c..d0c9ffaa25db 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -18,7 +18,7 @@
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/page.h>
@@ -131,14 +131,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
stg %r12,__SF_BACKCHAIN(%r15)
.endm
- .macro RESTORE_ALL sync
- mvc __LC_RETURN_PSW(16),SP_PSW(%r15) # move user PSW to lowcore
+ .macro RESTORE_ALL psworg,sync
+ mvc \psworg(16),SP_PSW(%r15) # move user PSW to lowcore
.if !\sync
- ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
+ ni \psworg+1,0xfd # clear wait state bit
.endif
lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
STORE_TIMER __LC_EXIT_TIMER
- lpswe __LC_RETURN_PSW # back to caller
+ lpswe \psworg # back to caller
.endm
/*
@@ -214,8 +214,8 @@ sysc_nr_ok:
sysc_do_restart:
larl %r10,sys_call_table
#ifdef CONFIG_S390_SUPPORT
- tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ?
- jo sysc_noemu
+ tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ?
+ jno sysc_noemu
larl %r10,sys_call_table_emu # use 31 bit emulation system calls
sysc_noemu:
#endif
@@ -233,7 +233,7 @@ sysc_return:
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
sysc_leave:
- RESTORE_ALL 1
+ RESTORE_ALL __LC_RETURN_PSW,1
#
# recheck if there is more work to do
@@ -308,8 +308,6 @@ sysc_singlestep:
jg do_single_step # branch to do_sigtrap
-__critical_end:
-
#
# call syscall_trace before and after system call
# special linkage: %r12 contains the return address for trace_svc
@@ -612,7 +610,8 @@ io_return:
tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.)
io_leave:
- RESTORE_ALL 0
+ RESTORE_ALL __LC_RETURN_PSW,0
+io_done:
#ifdef CONFIG_PREEMPT
io_preempt:
@@ -711,6 +710,8 @@ ext_no_vtime:
brasl %r14,do_extint
j io_return
+__critical_end:
+
/*
* Machine check handler routines
*/
@@ -718,6 +719,7 @@ ext_no_vtime:
mcck_int_handler:
la %r1,4095 # revalidate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
+ mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1)
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+64
la %r12,__LC_MCK_OLD_PSW
@@ -730,17 +732,8 @@ mcck_int_handler:
mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER
mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER
-0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
- jno mcck_no_vtime # no -> no timer update
- tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
- jz mcck_no_vtime
- UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
- UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
- mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
-mcck_no_vtime:
#endif
-0:
- tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
+0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
jno mcck_int_main # no -> skip cleanup critical
tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
jnz mcck_int_main # from user -> load kernel stack
@@ -756,6 +749,16 @@ mcck_int_main:
jz 0f
lg %r15,__LC_PANIC_STACK # load panic stack
0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
+ jno mcck_no_vtime # no -> no timer update
+ tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
+ jz mcck_no_vtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+mcck_no_vtime:
+#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,s390_do_machine_check
@@ -771,7 +774,7 @@ mcck_int_main:
jno mcck_return
brasl %r14,s390_handle_mcck
mcck_return:
- RESTORE_ALL 0
+ RESTORE_ALL __LC_RETURN_MCCK_PSW,0
#ifdef CONFIG_SMP
/*
@@ -833,6 +836,10 @@ cleanup_table_sysc_leave:
.quad sysc_leave, sysc_work_loop
cleanup_table_sysc_work_loop:
.quad sysc_work_loop, sysc_reschedule
+cleanup_table_io_leave:
+ .quad io_leave, io_done
+cleanup_table_io_work_loop:
+ .quad io_work_loop, io_mcck_pending
cleanup_critical:
clc 8(8,%r12),BASED(cleanup_table_system_call)
@@ -855,10 +862,26 @@ cleanup_critical:
clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
jl cleanup_sysc_return
0:
+ clc 8(8,%r12),BASED(cleanup_table_io_leave)
+ jl 0f
+ clc 8(8,%r12),BASED(cleanup_table_io_leave+8)
+ jl cleanup_io_leave
+0:
+ clc 8(8,%r12),BASED(cleanup_table_io_work_loop)
+ jl 0f
+ clc 8(8,%r12),BASED(cleanup_table_io_work_loop+8)
+ jl cleanup_io_return
+0:
br %r14
cleanup_system_call:
mvc __LC_RETURN_PSW(16),0(%r12)
+ cghi %r12,__LC_MCK_OLD_PSW
+ je 0f
+ la %r12,__LC_SAVE_AREA+32
+ j 1f
+0: la %r12,__LC_SAVE_AREA+64
+1:
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8)
jh 0f
@@ -868,11 +891,13 @@ cleanup_system_call:
#endif
clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn)
jh 0f
- mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32
-0: stg %r13,__LC_SAVE_AREA+40
+ mvc __LC_SAVE_AREA(32),0(%r12)
+0: stg %r13,8(%r12)
+ stg %r12,__LC_SAVE_AREA+96 # argh
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
- stg %r15,__LC_SAVE_AREA+56
+ lg %r12,__LC_SAVE_AREA+96 # argh
+ stg %r15,24(%r12)
llgh %r7,__LC_SVC_INT_CODE
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
cleanup_vtime:
@@ -909,17 +934,21 @@ cleanup_sysc_return:
cleanup_sysc_leave:
clc 8(8,%r12),BASED(cleanup_sysc_leave_insn)
- je 0f
+ je 2f
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
- je 0f
+ je 2f
#endif
mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
- mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
- lmg %r0,%r11,SP_R0(%r15)
+ cghi %r12,__LC_MCK_OLD_PSW
+ jne 0f
+ mvc __LC_SAVE_AREA+64(32),SP_R12(%r15)
+ j 1f
+0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
+1: lmg %r0,%r11,SP_R0(%r15)
lg %r15,SP_R15(%r15)
-0: la %r12,__LC_RETURN_PSW
+2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_sysc_leave_insn:
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -927,6 +956,36 @@ cleanup_sysc_leave_insn:
#endif
.quad sysc_leave + 12
+cleanup_io_return:
+ mvc __LC_RETURN_PSW(8),0(%r12)
+ mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop)
+ la %r12,__LC_RETURN_PSW
+ br %r14
+
+cleanup_io_leave:
+ clc 8(8,%r12),BASED(cleanup_io_leave_insn)
+ je 2f
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ clc 8(8,%r12),BASED(cleanup_io_leave_insn+8)
+ je 2f
+#endif
+ mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
+ cghi %r12,__LC_MCK_OLD_PSW
+ jne 0f
+ mvc __LC_SAVE_AREA+64(32),SP_R12(%r15)
+ j 1f
+0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
+1: lmg %r0,%r11,SP_R0(%r15)
+ lg %r15,SP_R15(%r15)
+2: la %r12,__LC_RETURN_PSW
+ br %r14
+cleanup_io_leave_insn:
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .quad io_leave + 20
+#endif
+ .quad io_leave + 16
+
/*
* Integer constants
*/
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 2710e66fefba..55654b6e16dc 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -30,7 +30,7 @@
#include <linux/config.h>
#include <asm/setup.h>
#include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 9a8263a153cb..c9ff0404c875 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -30,7 +30,7 @@
#include <linux/config.h>
#include <asm/setup.h>
#include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 610c1d03e975..6a3f5b7473a9 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -429,13 +429,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
else
setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 8ca485676780..2fd75da15495 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -139,10 +139,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 888b5596c195..2dc14e9c8327 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -36,7 +36,7 @@ _diag44(void)
}
void
-_raw_spin_lock_wait(spinlock_t *lp, unsigned int pc)
+_raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
{
int count = spin_retry;
@@ -53,7 +53,7 @@ _raw_spin_lock_wait(spinlock_t *lp, unsigned int pc)
EXPORT_SYMBOL(_raw_spin_lock_wait);
int
-_raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc)
+_raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
{
int count = spin_retry;
@@ -67,7 +67,7 @@ _raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc)
EXPORT_SYMBOL(_raw_spin_trylock_retry);
void
-_raw_read_lock_wait(rwlock_t *rw)
+_raw_read_lock_wait(raw_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
@@ -86,7 +86,7 @@ _raw_read_lock_wait(rwlock_t *rw)
EXPORT_SYMBOL(_raw_read_lock_wait);
int
-_raw_read_trylock_retry(rwlock_t *rw)
+_raw_read_trylock_retry(raw_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
@@ -102,7 +102,7 @@ _raw_read_trylock_retry(rwlock_t *rw)
EXPORT_SYMBOL(_raw_read_trylock_retry);
void
-_raw_write_lock_wait(rwlock_t *rw)
+_raw_write_lock_wait(raw_rwlock_t *rw)
{
int count = spin_retry;
@@ -119,7 +119,7 @@ _raw_write_lock_wait(rwlock_t *rw)
EXPORT_SYMBOL(_raw_write_lock_wait);
int
-_raw_write_trylock_retry(rwlock_t *rw)
+_raw_write_trylock_retry(raw_rwlock_t *rw)
{
int count = spin_retry;
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index e8029ef42ef2..88fc94fe6488 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -11,7 +11,7 @@
#include <linux/errno.h>
#include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
.align 4
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
index 0ca56972f4f0..50219786fc7a 100644
--- a/arch/s390/lib/uaccess64.S
+++ b/arch/s390/lib/uaccess64.S
@@ -11,7 +11,7 @@
#include <linux/errno.h>
#include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
.align 4
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 75fde949d125..856a971759b1 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -563,12 +563,14 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code)
* interrupt. pfault_wait is valid. Set pfault_wait
* back to zero and wake up the process. This can
* safely be done because the task is still sleeping
- * and can't procude new pfaults. */
+ * and can't produce new pfaults. */
tsk->thread.pfault_wait = 0;
wake_up_process(tsk);
+ put_task_struct(tsk);
}
} else {
/* signal bit not set -> a real page is missing. */
+ get_task_struct(tsk);
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (xchg(&tsk->thread.pfault_wait, 1) != 0) {
/* Completion interrupt was faster than the initial
@@ -578,6 +580,7 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code)
* mode and can't produce new pfaults. */
tsk->thread.pfault_wait = 0;
set_task_state(tsk, TASK_RUNNING);
+ put_task_struct(tsk);
} else
set_tsk_need_resched(tsk);
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index adc8109f8b77..3e804c736e64 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -37,6 +37,10 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
menu "System type"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index b5635635b5ee..4a3049080b41 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -152,10 +152,10 @@ endif
@touch $@
-prepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
.PHONY: maketools FORCE
-maketools: include/asm-sh/asm-offsets.h include/linux/version.h FORCE
+maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
all: zImage
@@ -168,14 +168,7 @@ compressed: zImage
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-CLEAN_FILES += include/asm-sh/machtypes.h include/asm-sh/asm-offsets.h
-
-arch/sh/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/asm-sh/.cpu include/asm-sh/.mach
-
-include/asm-sh/asm-offsets.h: arch/sh/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
+CLEAN_FILES += include/asm-sh/machtypes.h
define archhelp
@echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)'
diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/boards/adx/irq_maskreg.c
index ca91bb0f1f5c..c0973f8d57ba 100644
--- a/arch/sh/boards/adx/irq_maskreg.c
+++ b/arch/sh/boards/adx/irq_maskreg.c
@@ -37,13 +37,13 @@ static void end_maskreg_irq(unsigned int irq);
/* hw_interrupt_type */
static struct hw_interrupt_type maskreg_irq_type = {
- " Mask Register",
- startup_maskreg_irq,
- shutdown_maskreg_irq,
- enable_maskreg_irq,
- disable_maskreg_irq,
- mask_and_ack_maskreg,
- end_maskreg_irq
+ .typename = " Mask Register",
+ .startup = startup_maskreg_irq,
+ .shutdown = shutdown_maskreg_irq,
+ .enable = enable_maskreg_irq,
+ .disable = disable_maskreg_irq,
+ .ack = mask_and_ack_maskreg,
+ .end = end_maskreg_irq
};
/* actual implementatin */
diff --git a/arch/sh/boards/bigsur/io.c b/arch/sh/boards/bigsur/io.c
index 697144de7419..a9fde781b21a 100644
--- a/arch/sh/boards/bigsur/io.c
+++ b/arch/sh/boards/bigsur/io.c
@@ -37,10 +37,6 @@ static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
-#ifndef MAX
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#endif
-
void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
{
u32 port, endport = baseport + nports;
@@ -57,7 +53,7 @@ void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
}
- for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+ for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
pr_debug(" maphi[0x%x] = 0x%08x\n", port, addr);
@@ -80,7 +76,7 @@ void bigsur_port_unmap(u32 baseport, u32 nports)
bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
}
- for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+ for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
index c188fc32dc9a..6ddbcc77244d 100644
--- a/arch/sh/boards/bigsur/irq.c
+++ b/arch/sh/boards/bigsur/irq.c
@@ -228,23 +228,23 @@ static void shutdown_bigsur_irq(unsigned int irq)
/* Define the IRQ structures for the L1 and L2 IRQ types */
static struct hw_interrupt_type bigsur_l1irq_type = {
- "BigSur-CPLD-Level1-IRQ",
- startup_bigsur_irq,
- shutdown_bigsur_irq,
- enable_bigsur_l1irq,
- disable_bigsur_l1irq,
- mask_and_ack_bigsur,
- end_bigsur_irq
+ .typename = "BigSur-CPLD-Level1-IRQ",
+ .startup = startup_bigsur_irq,
+ .shutdown = shutdown_bigsur_irq,
+ .enable = enable_bigsur_l1irq,
+ .disable = disable_bigsur_l1irq,
+ .ack = mask_and_ack_bigsur,
+ .end = end_bigsur_irq
};
static struct hw_interrupt_type bigsur_l2irq_type = {
- "BigSur-CPLD-Level2-IRQ",
- startup_bigsur_irq,
- shutdown_bigsur_irq,
- enable_bigsur_l2irq,
- disable_bigsur_l2irq,
- mask_and_ack_bigsur,
- end_bigsur_irq
+ .typename = "BigSur-CPLD-Level2-IRQ",
+ .startup = startup_bigsur_irq,
+ .shutdown =shutdown_bigsur_irq,
+ .enable = enable_bigsur_l2irq,
+ .disable = disable_bigsur_l2irq,
+ .ack = mask_and_ack_bigsur,
+ .end = end_bigsur_irq
};
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
index fa6cfe5a20a7..d1da0d844567 100644
--- a/arch/sh/boards/cqreek/irq.c
+++ b/arch/sh/boards/cqreek/irq.c
@@ -83,13 +83,13 @@ static void shutdown_cqreek_irq(unsigned int irq)
}
static struct hw_interrupt_type cqreek_irq_type = {
- "CqREEK-IRQ",
- startup_cqreek_irq,
- shutdown_cqreek_irq,
- enable_cqreek_irq,
- disable_cqreek_irq,
- mask_and_ack_cqreek,
- end_cqreek_irq
+ .typename = "CqREEK-IRQ",
+ .startup = startup_cqreek_irq,
+ .shutdown = shutdown_cqreek_irq,
+ .enable = enable_cqreek_irq,
+ .disable = disable_cqreek_irq,
+ .ack = mask_and_ack_cqreek,
+ .end = end_cqreek_irq
};
int cqreek_has_ide, cqreek_has_isa;
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
index acd58489970f..52d0ba39031b 100644
--- a/arch/sh/boards/harp/irq.c
+++ b/arch/sh/boards/harp/irq.c
@@ -39,13 +39,13 @@ static unsigned int startup_harp_irq(unsigned int irq)
}
static struct hw_interrupt_type harp_irq_type = {
- "Harp-IRQ",
- startup_harp_irq,
- shutdown_harp_irq,
- enable_harp_irq,
- disable_harp_irq,
- mask_and_ack_harp,
- end_harp_irq
+ .typename = "Harp-IRQ",
+ .startup = startup_harp_irq,
+ .shutdown = shutdown_harp_irq,
+ .enable = enable_harp_irq,
+ .disable = disable_harp_irq,
+ .ack = mask_and_ack_harp,
+ .end = end_harp_irq
};
static void disable_harp_irq(unsigned int irq)
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
index 23adc6be71e7..715e8feb3a68 100644
--- a/arch/sh/boards/overdrive/irq.c
+++ b/arch/sh/boards/overdrive/irq.c
@@ -86,13 +86,13 @@ static unsigned int startup_od_irq(unsigned int irq)
}
static struct hw_interrupt_type od_irq_type = {
- "Overdrive-IRQ",
- startup_od_irq,
- shutdown_od_irq,
- enable_od_irq,
- disable_od_irq,
- mask_and_ack_od,
- end_od_irq
+ .typename = "Overdrive-IRQ",
+ .startup = startup_od_irq,
+ .shutdown = shutdown_od_irq,
+ .enable = enable_od_irq,
+ .disable = disable_od_irq,
+ .ack = mask_and_ack_od,
+ .end = end_od_irq
};
static void disable_od_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
index a7921f67a35f..ed4c5b50ea45 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/irq.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -74,13 +74,13 @@ static void end_hs7751rvoip_irq(unsigned int irq)
}
static struct hw_interrupt_type hs7751rvoip_irq_type = {
- "HS7751RVoIP IRQ",
- startup_hs7751rvoip_irq,
- shutdown_hs7751rvoip_irq,
- enable_hs7751rvoip_irq,
- disable_hs7751rvoip_irq,
- ack_hs7751rvoip_irq,
- end_hs7751rvoip_irq,
+ .typename = "HS7751RVoIP IRQ",
+ .startup = startup_hs7751rvoip_irq,
+ .shutdown = shutdown_hs7751rvoip_irq,
+ .enable = enable_hs7751rvoip_irq,
+ .disable = disable_hs7751rvoip_irq,
+ .ack = ack_hs7751rvoip_irq,
+ .end = end_hs7751rvoip_irq,
};
static void make_hs7751rvoip_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
index 95717f4f1e2d..d36c9374aed1 100644
--- a/arch/sh/boards/renesas/rts7751r2d/irq.c
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -88,13 +88,13 @@ static void end_rts7751r2d_irq(unsigned int irq)
}
static struct hw_interrupt_type rts7751r2d_irq_type = {
- "RTS7751R2D IRQ",
- startup_rts7751r2d_irq,
- shutdown_rts7751r2d_irq,
- enable_rts7751r2d_irq,
- disable_rts7751r2d_irq,
- ack_rts7751r2d_irq,
- end_rts7751r2d_irq,
+ .typename = "RTS7751R2D IRQ",
+ .startup = startup_rts7751r2d_irq,
+ .shutdown = shutdown_rts7751r2d_irq,
+ .enable = enable_rts7751r2d_irq,
+ .disable = disable_rts7751r2d_irq,
+ .ack = ack_rts7751r2d_irq,
+ .end = end_rts7751r2d_irq,
};
static void make_rts7751r2d_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/systemh/irq.c b/arch/sh/boards/renesas/systemh/irq.c
index 5675a4134eee..7a2eb10edb56 100644
--- a/arch/sh/boards/renesas/systemh/irq.c
+++ b/arch/sh/boards/renesas/systemh/irq.c
@@ -35,13 +35,13 @@ static void end_systemh_irq(unsigned int irq);
/* hw_interrupt_type */
static struct hw_interrupt_type systemh_irq_type = {
- " SystemH Register",
- startup_systemh_irq,
- shutdown_systemh_irq,
- enable_systemh_irq,
- disable_systemh_irq,
- mask_and_ack_systemh,
- end_systemh_irq
+ .typename = " SystemH Register",
+ .startup = startup_systemh_irq,
+ .shutdown = shutdown_systemh_irq,
+ .enable = enable_systemh_irq,
+ .disable = disable_systemh_irq,
+ .ack = mask_and_ack_systemh,
+ .end = end_systemh_irq
};
static unsigned int startup_systemh_irq(unsigned int irq)
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index 1298883eca4b..1395c1e65da4 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -83,13 +83,13 @@ static unsigned int startup_microdev_irq(unsigned int irq)
}
static struct hw_interrupt_type microdev_irq_type = {
- "MicroDev-IRQ",
- startup_microdev_irq,
- shutdown_microdev_irq,
- enable_microdev_irq,
- disable_microdev_irq,
- mask_and_ack_microdev,
- end_microdev_irq
+ .typename = "MicroDev-IRQ",
+ .startup = startup_microdev_irq,
+ .shutdown = shutdown_microdev_irq,
+ .enable = enable_microdev_irq,
+ .disable = disable_microdev_irq,
+ .ack = mask_and_ack_microdev,
+ .end = end_microdev_irq
};
static void disable_microdev_irq(unsigned int irq)
diff --git a/arch/sh/cchips/hd6446x/hd64465/io.c b/arch/sh/cchips/hd6446x/hd64465/io.c
index 99ac709c550e..84cb142def0b 100644
--- a/arch/sh/cchips/hd6446x/hd64465/io.c
+++ b/arch/sh/cchips/hd6446x/hd64465/io.c
@@ -48,10 +48,6 @@ static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
-#ifndef MAX
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#endif
-
#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
void hd64465_port_map(unsigned short baseport, unsigned int nports,
@@ -71,7 +67,7 @@ void hd64465_port_map(unsigned short baseport, unsigned int nports,
addr += (1<<(HD64465_IOMAP_LO_SHIFT));
}
- for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+ for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
port < endport && port < HD64465_IOMAP_HI_THRESH ;
port += (1<<HD64465_IOMAP_HI_SHIFT)) {
DPRINTK(" maphi[0x%x] = 0x%08lx\n", port, addr);
@@ -95,7 +91,7 @@ void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
}
- for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+ for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
port < endport && port < HD64465_IOMAP_HI_THRESH ;
port += (1<<HD64465_IOMAP_HI_SHIFT)) {
hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 3079234cb65b..1b6ac523b458 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -87,13 +87,13 @@ static void shutdown_voyagergx_irq(unsigned int irq)
}
static struct hw_interrupt_type voyagergx_irq_type = {
- "VOYAGERGX-IRQ",
- startup_voyagergx_irq,
- shutdown_voyagergx_irq,
- enable_voyagergx_irq,
- disable_voyagergx_irq,
- mask_and_ack_voyagergx,
- end_voyagergx_irq,
+ .typename = "VOYAGERGX-IRQ",
+ .startup = startup_voyagergx_irq,
+ .shutdown = shutdown_voyagergx_irq,
+ .enable = enable_voyagergx_irq,
+ .disable = disable_voyagergx_irq,
+ .ack = mask_and_ack_voyagergx,
+ .end = end_voyagergx_irq,
};
static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq_imask.c
index f76901e732fb..a963d00a971e 100644
--- a/arch/sh/kernel/cpu/irq_imask.c
+++ b/arch/sh/kernel/cpu/irq_imask.c
@@ -46,13 +46,13 @@ static unsigned int startup_imask_irq(unsigned int irq)
}
static struct hw_interrupt_type imask_irq_type = {
- "SR.IMASK",
- startup_imask_irq,
- shutdown_imask_irq,
- enable_imask_irq,
- disable_imask_irq,
- mask_and_ack_imask,
- end_imask_irq
+ .typename = "SR.IMASK",
+ .startup = startup_imask_irq,
+ .shutdown = shutdown_imask_irq,
+ .enable = enable_imask_irq,
+ .disable = disable_imask_irq,
+ .ack = mask_and_ack_imask,
+ .end = end_imask_irq
};
void static inline set_interrupt_registers(int ip)
diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq_ipr.c
index 7ea3d2d030e5..71f92096132b 100644
--- a/arch/sh/kernel/cpu/irq_ipr.c
+++ b/arch/sh/kernel/cpu/irq_ipr.c
@@ -48,13 +48,13 @@ static unsigned int startup_ipr_irq(unsigned int irq)
}
static struct hw_interrupt_type ipr_irq_type = {
- "IPR-IRQ",
- startup_ipr_irq,
- shutdown_ipr_irq,
- enable_ipr_irq,
- disable_ipr_irq,
- mask_and_ack_ipr,
- end_ipr_irq
+ .typename = "IPR-IRQ",
+ .startup = startup_ipr_irq,
+ .shutdown = shutdown_ipr_irq,
+ .enable = enable_ipr_irq,
+ .disable = disable_ipr_irq,
+ .ack = mask_and_ack_ipr,
+ .end = end_ipr_irq
};
static void disable_ipr_irq(unsigned int irq)
@@ -142,13 +142,13 @@ static unsigned int startup_pint_irq(unsigned int irq)
}
static struct hw_interrupt_type pint_irq_type = {
- "PINT-IRQ",
- startup_pint_irq,
- shutdown_pint_irq,
- enable_pint_irq,
- disable_pint_irq,
- mask_and_ack_pint,
- end_pint_irq
+ .typename = "PINT-IRQ",
+ .startup = startup_pint_irq,
+ .shutdown = shutdown_pint_irq,
+ .enable = enable_pint_irq,
+ .disable = disable_pint_irq,
+ .ack = mask_and_ack_pint,
+ .end = end_pint_irq
};
static void disable_pint_irq(unsigned int irq)
diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c
index 099ebbf89745..f6b16ba01932 100644
--- a/arch/sh/kernel/cpu/sh4/irq_intc2.c
+++ b/arch/sh/kernel/cpu/sh4/irq_intc2.c
@@ -48,13 +48,13 @@ static unsigned int startup_intc2_irq(unsigned int irq)
}
static struct hw_interrupt_type intc2_irq_type = {
- "INTC2-IRQ",
- startup_intc2_irq,
- shutdown_intc2_irq,
- enable_intc2_irq,
- disable_intc2_irq,
- mask_and_ack_intc2,
- end_intc2_irq
+ .typename = "INTC2-IRQ",
+ .startup = startup_intc2_irq,
+ .shutdown = shutdown_intc2_irq,
+ .enable = enable_intc2_irq,
+ .disable = disable_intc2_irq,
+ .ack = mask_and_ack_intc2,
+ .end = end_intc2_irq
};
static void disable_intc2_irq(unsigned int irq)
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 8022243f0178..b475c4d2405f 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -546,13 +546,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index df7a9b9d4cbf..02ca69918d7c 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -215,10 +215,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -234,7 +231,7 @@ static long last_rtc_update;
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
{
do_timer(regs);
#ifndef CONFIG_SMP
@@ -252,7 +249,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
@@ -285,7 +282,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* locally disabled. -arca
*/
write_seqlock(&xtime_lock);
- do_timer_interrupt(irq, NULL, regs);
+ do_timer_interrupt(irq, regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 4c3e5334adb3..fb35b45dc130 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -29,10 +29,6 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
-config LOG_BUF_SHIFT
- int
- default 14
-
config RWSEM_XCHGADD_ALGORITHM
bool
diff --git a/arch/sh64/Makefile b/arch/sh64/Makefile
index b4fd8e13fea9..8ca57ffa2b70 100644
--- a/arch/sh64/Makefile
+++ b/arch/sh64/Makefile
@@ -73,11 +73,7 @@ compressed: zImage
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-prepare: include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
- include/asm include/linux/version.h
- $(call filechk,gen-asm-offsets)
+archprepare: arch/$(ARCH)/lib/syscalltab.h
define filechk_gen-syscalltab
(set -e; \
@@ -108,7 +104,7 @@ endef
arch/$(ARCH)/lib/syscalltab.h: arch/sh64/kernel/syscalls.S
$(call filechk,gen-syscalltab)
-CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
+CLEAN_FILES += arch/$(ARCH)/lib/syscalltab.h
define archhelp
@echo ' zImage - Compressed kernel image (arch/sh64/boot/zImage)'
diff --git a/arch/sh64/kernel/irq_intc.c b/arch/sh64/kernel/irq_intc.c
index 43f88f3a78b0..fc99bf4e362c 100644
--- a/arch/sh64/kernel/irq_intc.c
+++ b/arch/sh64/kernel/irq_intc.c
@@ -107,13 +107,13 @@ static void mask_and_ack_intc(unsigned int);
static void end_intc_irq(unsigned int irq);
static struct hw_interrupt_type intc_irq_type = {
- "INTC",
- startup_intc_irq,
- shutdown_intc_irq,
- enable_intc_irq,
- disable_intc_irq,
- mask_and_ack_intc,
- end_intc_irq
+ .typename = "INTC",
+ .startup = startup_intc_irq,
+ .shutdown = shutdown_intc_irq,
+ .enable = enable_intc_irq,
+ .disable = disable_intc_irq,
+ .ack = mask_and_ack_intc,
+ .end = end_intc_irq
};
static int irlm; /* IRL mode */
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index c6a14a87c59b..3ea8929e483b 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -664,13 +664,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 6c84da3efc73..f4a62a10053c 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -247,10 +247,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -303,7 +300,7 @@ static long last_rtc_update = 0;
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
{
unsigned long long current_ctc;
asm ("getcon cr62, %0" : "=r" (current_ctc));
@@ -328,7 +325,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
@@ -361,7 +358,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* locally disabled. -arca
*/
write_lock(&xtime_lock);
- do_timer_interrupt(irq, NULL, regs);
+ do_timer_interrupt(irq, regs);
write_unlock(&xtime_lock);
return IRQ_HANDLED;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index aca028aa29bf..aba05394d30a 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -211,6 +211,10 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
config SUN_PM
bool
default y
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 7b3bbaf083a6..dea48f6cff38 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -59,17 +59,7 @@ image tftpboot.img: vmlinux
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-prepare: include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h \
- arch/$(ARCH)/kernel/asm-offsets.s \
- arch/$(ARCH)/boot/System.map
+CLEAN_FILES += arch/$(ARCH)/boot/System.map
# Don't use tabs in echo arguments.
define archhelp
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index b448166f5da9..03ecb4e4614e 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -17,7 +17,7 @@
#include <asm/kgdb.h>
#include <asm/contregs.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/psr.h>
#include <asm/vaddrs.h>
#include <asm/memreg.h>
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 7931d6f92819..787d5f1347ec 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -10,6 +10,7 @@
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
+#include <linux/ctype.h>
void *module_alloc(unsigned long size)
{
@@ -37,7 +38,7 @@ void module_free(struct module *mod, void *module_region)
}
/* Make generic code ignore STT_REGISTER dummy undefined symbols,
- * and replace references to .func with func as in ppc64's dedotify.
+ * and replace references to .func with _Func
*/
int module_frob_arch_sections(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
@@ -64,8 +65,10 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
sym[i].st_shndx = SHN_ABS;
else {
char *name = strtab + sym[i].st_name;
- if (name[0] == '.')
- memmove(name, name+1, strlen(name));
+ if (name[0] == '.') {
+ name[0] = '_';
+ name[1] = toupper(name[1]);
+ }
}
}
}
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 597d3ff6ad68..36a40697b8d6 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -840,10 +840,7 @@ static int pci_do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
return 0;
}
diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
index 3a867fc19927..136e37c53d49 100644
--- a/arch/sparc/kernel/sclow.S
+++ b/arch/sparc/kernel/sclow.S
@@ -7,7 +7,7 @@
*/
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/errno.h>
#include <asm/winmacro.h>
#include <asm/thread_info.h>
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 55352ed85e8a..53c192a4982f 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -32,7 +32,6 @@
#include <linux/spinlock.h>
#include <linux/root_dev.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 011ff35057a5..5f34d7dc2b89 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -1034,13 +1034,12 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
else
setup_frame(&ka->sa, regs, signr, oldset, info);
}
- if (!(ka->sa.sa_flags & SA_NOMASK)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 8faa8dc4de43..1c8fd0fd9305 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -97,34 +97,17 @@ extern void ___rw_write_enter(void);
/* Alias functions whose names begin with "." and export the aliases.
* The module references will be fixed up by module_frob_arch_sections.
*/
-#define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \
- extern __ret __x(__arg1, __arg2); \
- asm(".weak " #__x);\
- asm(#__x "=." #__x);
-
-DOT_ALIAS2(int, div, int, int)
-DOT_ALIAS2(int, mul, int, int)
-DOT_ALIAS2(int, rem, int, int)
-DOT_ALIAS2(unsigned, udiv, unsigned, unsigned)
-DOT_ALIAS2(unsigned, umul, unsigned, unsigned)
-DOT_ALIAS2(unsigned, urem, unsigned, unsigned)
-
-#undef DOT_ALIAS2
+extern int _Div(int, int);
+extern int _Mul(int, int);
+extern int _Rem(int, int);
+extern unsigned _Udiv(unsigned, unsigned);
+extern unsigned _Umul(unsigned, unsigned);
+extern unsigned _Urem(unsigned, unsigned);
/* used by various drivers */
EXPORT_SYMBOL(sparc_cpu_model);
EXPORT_SYMBOL(kernel_thread);
-#ifdef CONFIG_DEBUG_SPINLOCK
#ifdef CONFIG_SMP
-EXPORT_SYMBOL(_do_spin_lock);
-EXPORT_SYMBOL(_do_spin_unlock);
-EXPORT_SYMBOL(_spin_trylock);
-EXPORT_SYMBOL(_do_read_lock);
-EXPORT_SYMBOL(_do_read_unlock);
-EXPORT_SYMBOL(_do_write_lock);
-EXPORT_SYMBOL(_do_write_unlock);
-#endif
-#else
// XXX find what uses (or used) these.
EXPORT_SYMBOL(___rw_read_enter);
EXPORT_SYMBOL(___rw_read_exit);
@@ -175,7 +158,6 @@ EXPORT_SYMBOL(set_auxio);
EXPORT_SYMBOL(get_auxio);
#endif
EXPORT_SYMBOL(request_fast_irq);
-EXPORT_SYMBOL(io_remap_page_range);
EXPORT_SYMBOL(io_remap_pfn_range);
/* P3: iounit_xxx may be needed, sun4d users */
/* EXPORT_SYMBOL(iounit_map_dma_init); */
@@ -331,12 +313,12 @@ EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__divdi3);
-EXPORT_SYMBOL(rem);
-EXPORT_SYMBOL(urem);
-EXPORT_SYMBOL(mul);
-EXPORT_SYMBOL(umul);
-EXPORT_SYMBOL(div);
-EXPORT_SYMBOL(udiv);
+EXPORT_SYMBOL(_Rem);
+EXPORT_SYMBOL(_Urem);
+EXPORT_SYMBOL(_Mul);
+EXPORT_SYMBOL(_Umul);
+EXPORT_SYMBOL(_Div);
+EXPORT_SYMBOL(_Udiv);
#ifdef CONFIG_DEBUG_BUGVERBOSE
EXPORT_SYMBOL(do_BUG);
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c
index fd8005a3e6bd..591547af4c65 100644
--- a/arch/sparc/kernel/tick14.c
+++ b/arch/sparc/kernel/tick14.c
@@ -19,7 +19,6 @@
#include <linux/interrupt.h>
#include <asm/oplib.h>
-#include <asm/segment.h>
#include <asm/timer.h>
#include <asm/mostek.h>
#include <asm/system.h>
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 6486cbf2efe9..bc015e980341 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -32,7 +32,6 @@
#include <linux/profile.h>
#include <asm/oplib.h>
-#include <asm/segment.h>
#include <asm/timer.h>
#include <asm/mostek.h>
#include <asm/system.h>
@@ -140,7 +139,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* Determine when to update the Mostek clock. */
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
@@ -555,10 +554,7 @@ static int sbus_do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
return 0;
}
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 2296ff9dc47a..fa5006946062 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -9,5 +9,3 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
copy_user.o locks.o atomic.o atomic32.o bitops.o \
lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
-
-lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index 19724c5800a7..2e64e8c3e8e5 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -20,7 +20,7 @@ spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
#else /* SMP */
-static spinlock_t dummy = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dummy);
#define ATOMIC_HASH_SIZE 1
#define ATOMIC_HASH(a) (&dummy)
diff --git a/arch/sparc/lib/debuglocks.c b/arch/sparc/lib/debuglocks.c
deleted file mode 100644
index fb182352782c..000000000000
--- a/arch/sparc/lib/debuglocks.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $
- * debuglocks.c: Debugging versions of SMP locking primitives.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h> /* For NR_CPUS */
-#include <linux/spinlock.h>
-#include <asm/psr.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-
-/* Some notes on how these debugging routines work. When a lock is acquired
- * an extra debugging member lock->owner_pc is set to the caller of the lock
- * acquisition routine. Right before releasing a lock, the debugging program
- * counter is cleared to zero.
- *
- * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
- * number of the owner in the lowest two bits.
- */
-
-#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
-
-static inline void show(char *str, spinlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
-
- printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
- lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-}
-
-static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
-
- printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str,
- lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-}
-
-static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
- int i;
-
- printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,
- lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-
- for(i = 0; i < NR_CPUS; i++)
- printk(" reader[%d]=%08lx", i, lock->reader_pc[i]);
-
- printk("\n");
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-void _do_spin_lock(spinlock_t *lock, char *str)
-{
- unsigned long caller;
- unsigned long val;
- int cpu = smp_processor_id();
- int stuck = INIT_STUCK;
-
- STORE_CALLER(caller);
-
-again:
- __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
- if(val) {
- while(lock->lock) {
- if (!--stuck) {
- show(str, lock, caller);
- stuck = INIT_STUCK;
- }
- barrier();
- }
- goto again;
- }
- lock->owner_pc = (cpu & 3) | (caller & ~3);
-}
-
-int _spin_trylock(spinlock_t *lock)
-{
- unsigned long val;
- unsigned long caller;
- int cpu = smp_processor_id();
-
- STORE_CALLER(caller);
-
- __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
- if(!val) {
- /* We got it, record our identity for debugging. */
- lock->owner_pc = (cpu & 3) | (caller & ~3);
- }
- return val == 0;
-}
-
-void _do_spin_unlock(spinlock_t *lock)
-{
- lock->owner_pc = 0;
- barrier();
- lock->lock = 0;
-}
-
-void _do_read_lock(rwlock_t *rw, char *str)
-{
- unsigned long caller;
- unsigned long val;
- int cpu = smp_processor_id();
- int stuck = INIT_STUCK;
-
- STORE_CALLER(caller);
-
-wlock_again:
- __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
- if(val) {
- while(rw->lock & 0xff) {
- if (!--stuck) {
- show_read(str, rw, caller);
- stuck = INIT_STUCK;
- }
- barrier();
- }
- goto wlock_again;
- }
-
- rw->reader_pc[cpu] = caller;
- barrier();
- rw->lock++;
-}
-
-void _do_read_unlock(rwlock_t *rw, char *str)
-{
- unsigned long caller;
- unsigned long val;
- int cpu = smp_processor_id();
- int stuck = INIT_STUCK;
-
- STORE_CALLER(caller);
-
-wlock_again:
- __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
- if(val) {
- while(rw->lock & 0xff) {
- if (!--stuck) {
- show_read(str, rw, caller);
- stuck = INIT_STUCK;
- }
- barrier();
- }
- goto wlock_again;
- }
-
- rw->reader_pc[cpu] = 0;
- barrier();
- rw->lock -= 0x1ff;
-}
-
-void _do_write_lock(rwlock_t *rw, char *str)
-{
- unsigned long caller;
- unsigned long val;
- int cpu = smp_processor_id();
- int stuck = INIT_STUCK;
-
- STORE_CALLER(caller);
-
-wlock_again:
- __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
- if(val) {
-wlock_wait:
- while(rw->lock) {
- if (!--stuck) {
- show_write(str, rw, caller);
- stuck = INIT_STUCK;
- }
- barrier();
- }
- goto wlock_again;
- }
-
- if (rw->lock & ~0xff) {
- *(((unsigned char *)&rw->lock)+3) = 0;
- barrier();
- goto wlock_wait;
- }
-
- barrier();
- rw->owner_pc = (cpu & 3) | (caller & ~3);
-}
-
-void _do_write_unlock(rwlock_t *rw)
-{
- rw->owner_pc = 0;
- barrier();
- rw->lock = 0;
-}
-
-#endif /* SMP */
diff --git a/arch/sparc/lib/mul.S b/arch/sparc/lib/mul.S
index 83dffbc2f62f..da693560d878 100644
--- a/arch/sparc/lib/mul.S
+++ b/arch/sparc/lib/mul.S
@@ -16,7 +16,9 @@
*/
.globl .mul
+ .globl _Mul
.mul:
+_Mul: /* needed for export */
mov %o0, %y ! multiplier -> Y
andncc %o0, 0xfff, %g0 ! test bits 12..31
be Lmul_shortway ! if zero, can do it the short way
diff --git a/arch/sparc/lib/rem.S b/arch/sparc/lib/rem.S
index 44508148d055..bf015a90d07e 100644
--- a/arch/sparc/lib/rem.S
+++ b/arch/sparc/lib/rem.S
@@ -43,7 +43,9 @@
.globl .rem
+ .globl _Rem
.rem:
+_Rem: /* needed for export */
! compute sign of result; if neither is negative, no problem
orcc %o1, %o0, %g0 ! either negative?
bge 2f ! no, go do the divide
diff --git a/arch/sparc/lib/sdiv.S b/arch/sparc/lib/sdiv.S
index e0ad80b6f63d..af9451629d0b 100644
--- a/arch/sparc/lib/sdiv.S
+++ b/arch/sparc/lib/sdiv.S
@@ -43,7 +43,9 @@
.globl .div
+ .globl _Div
.div:
+_Div: /* needed for export */
! compute sign of result; if neither is negative, no problem
orcc %o1, %o0, %g0 ! either negative?
bge 2f ! no, go do the divide
diff --git a/arch/sparc/lib/udiv.S b/arch/sparc/lib/udiv.S
index 2abfc6b0f3e9..169e01da6715 100644
--- a/arch/sparc/lib/udiv.S
+++ b/arch/sparc/lib/udiv.S
@@ -43,7 +43,9 @@
.globl .udiv
+ .globl _Udiv
.udiv:
+_Udiv: /* needed for export */
! Ready to divide. Compute size of quotient; scale comparand.
orcc %o1, %g0, %o5
diff --git a/arch/sparc/lib/umul.S b/arch/sparc/lib/umul.S
index a784720a8a22..f0e5b20a2536 100644
--- a/arch/sparc/lib/umul.S
+++ b/arch/sparc/lib/umul.S
@@ -21,7 +21,9 @@
*/
.globl .umul
+ .globl _Umul
.umul:
+_Umul: /* needed for export */
or %o0, %o1, %o4
mov %o0, %y ! multiplier -> Y
diff --git a/arch/sparc/lib/urem.S b/arch/sparc/lib/urem.S
index ec7f0c502c56..6b92bdc8b04c 100644
--- a/arch/sparc/lib/urem.S
+++ b/arch/sparc/lib/urem.S
@@ -41,7 +41,9 @@
*/
.globl .urem
+ .globl _Urem
.urem:
+_Urem: /* needed for export */
! Ready to divide. Compute size of quotient; scale comparand.
orcc %o1, %g0, %o5
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index 37f4107bae66..2bbd53f3cafb 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/memreg.h>
diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c
index db27eee3bda1..20ccb957fb77 100644
--- a/arch/sparc/mm/generic.c
+++ b/arch/sparc/mm/generic.c
@@ -16,31 +16,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-static inline void forget_pte(pte_t page)
-{
-#if 0 /* old 2.4 code */
- if (pte_none(page))
- return;
- if (pte_present(page)) {
- unsigned long pfn = pte_pfn(page);
- struct page *ptpage;
- if (!pfn_valid(pfn))
- return;
- ptpage = pfn_to_page(pfn);
- if (PageReserved(ptpage))
- return;
- page_cache_release(ptpage);
- return;
- }
- swap_free(pte_to_swp_entry(page));
-#else
- if (!pte_none(page)) {
- printk("forget_pte: old mapping existed!\n");
- BUG();
- }
-#endif
-}
-
/* Remap IO memory, the same way as remap_pfn_range(), but use
* the obio memory space.
*
@@ -60,7 +35,6 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigne
pte_t oldpage = *pte;
pte_clear(mm, address, pte);
set_pte(pte, mk_pte_io(offset, prot, space));
- forget_pte(oldpage);
address += PAGE_SIZE;
offset += PAGE_SIZE;
pte++;
@@ -88,37 +62,6 @@ static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned
return 0;
}
-int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space)
-{
- int error = 0;
- pgd_t * dir;
- unsigned long beg = from;
- unsigned long end = from + size;
- struct mm_struct *mm = vma->vm_mm;
-
- prot = __pgprot(pg_iobits);
- offset -= from;
- dir = pgd_offset(mm, from);
- flush_cache_range(vma, beg, end);
-
- spin_lock(&mm->page_table_lock);
- while (from < end) {
- pmd_t *pmd = pmd_alloc(current->mm, dir, from);
- error = -ENOMEM;
- if (!pmd)
- break;
- error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
- if (error)
- break;
- from = (from + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- }
- spin_unlock(&mm->page_table_lock);
-
- flush_tlb_range(vma, beg, end);
- return error;
-}
-
int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long pfn, unsigned long size, pgprot_t prot)
{
diff --git a/arch/sparc/mm/hypersparc.S b/arch/sparc/mm/hypersparc.S
index 54b8e764b042..a231cca37216 100644
--- a/arch/sparc/mm/hypersparc.S
+++ b/arch/sparc/mm/hypersparc.S
@@ -6,7 +6,7 @@
#include <asm/ptrace.h>
#include <asm/psr.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/asi.h>
#include <asm/page.h>
#include <asm/pgtsrmmu.h>
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index ec2e05028a10..c03babaa0498 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -25,7 +25,6 @@
#include <linux/bootmem.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/vac-ops.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S
index 2dcaa5ac1a38..cd90f3fdc4e7 100644
--- a/arch/sparc/mm/swift.S
+++ b/arch/sparc/mm/swift.S
@@ -9,7 +9,7 @@
#include <asm/asi.h>
#include <asm/page.h>
#include <asm/pgtsrmmu.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
.text
.align 4
diff --git a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S
index 8acd1787fde2..697af617594a 100644
--- a/arch/sparc/mm/tsunami.S
+++ b/arch/sparc/mm/tsunami.S
@@ -6,7 +6,7 @@
#include <linux/config.h>
#include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/psr.h>
#include <asm/asi.h>
#include <asm/page.h>
diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S
index f58712d26bf5..3cbd6de18dde 100644
--- a/arch/sparc/mm/viking.S
+++ b/arch/sparc/mm/viking.S
@@ -9,7 +9,7 @@
#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/asi.h>
#include <asm/mxcc.h>
#include <asm/page.h>
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 9afd28e2c4d5..1e9d8638a28a 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -5,6 +5,16 @@
mainmenu "Linux/UltraSPARC Kernel Configuration"
+config SPARC64
+ bool
+ default y
+ help
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. This port covers the newer 64-bit
+ UltraSPARC. The UltraLinux project maintains both the SPARC32 and
+ SPARC64 ports; its web page is available at
+ <http://www.ultralinux.org/>.
+
config 64BIT
def_bool y
@@ -16,6 +26,10 @@ config TIME_INTERPOLATION
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
choice
prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB
@@ -71,75 +85,6 @@ config SYSVIPC_COMPAT
menu "General machine setup"
-config BBC_I2C
- tristate "UltraSPARC-III bootbus i2c controller driver"
- depends on PCI
- help
- The BBC devices on the UltraSPARC III have two I2C controllers. The
- first I2C controller connects mainly to configuration PROMs (NVRAM,
- CPU configuration, DIMM types, etc.). The second I2C controller
- connects to environmental control devices such as fans and
- temperature sensors. The second controller also connects to the
- smartcard reader, if present. Say Y to enable support for these.
-
-config VT
- bool "Virtual terminal" if EMBEDDED
- select INPUT
- default y
- ---help---
- If you say Y here, you will get support for terminal devices with
- display and keyboard devices. These are called "virtual" because you
- can run several virtual terminals (also called virtual consoles) on
- one physical terminal. This is rather useful, for example one
- virtual terminal can collect system messages and warnings, another
- one can be used for a text-mode user session, and a third could run
- an X session, all in parallel. Switching between virtual terminals
- is done with certain key combinations, usually Alt-<function key>.
-
- The setterm command ("man setterm") can be used to change the
- properties (such as colors or beeping) of a virtual terminal. The
- man page console_codes(4) ("man console_codes") contains the special
- character sequences that can be used to change those properties
- directly. The fonts used on virtual terminals can be changed with
- the setfont ("man setfont") command and the key bindings are defined
- with the loadkeys ("man loadkeys") command.
-
- You need at least one virtual terminal device in order to make use
- of your keyboard and monitor. Therefore, only people configuring an
- embedded system would want to say N here in order to save some
- memory; the only way to log into such a system is then via a serial
- or network connection.
-
- If unsure, say Y, or else you won't be able to do much with your new
- shiny Linux system :-)
-
-config VT_CONSOLE
- bool "Support for console on virtual terminal" if EMBEDDED
- depends on VT
- default y
- ---help---
- The system console is the device which receives all kernel messages
- and warnings and which allows logins in single user mode. If you
- answer Y here, a virtual terminal (the device used to interact with
- a physical terminal) can be used as system console. This is the most
- common mode of operations, so you should say Y here unless you want
- the kernel messages be output only to a serial port (in which case
- you should say Y to "Console on serial port", below).
-
- If you do say Y here, by default the currently visible virtual
- terminal (/dev/tty0) will be used as system console. You can change
- that with a kernel command line option such as "console=tty3" which
- would use the third virtual terminal as system console. (Try "man
- bootparam" or see the documentation of your boot loader (lilo or
- loadlin) about how to pass options to the kernel at boot time.)
-
- If unsure, say Y.
-
-config HW_CONSOLE
- bool
- depends on VT
- default y
-
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -205,17 +150,6 @@ config US2E_FREQ
If in doubt, say N.
-# Identify this as a Sparc64 build
-config SPARC64
- bool
- default y
- help
- SPARC is a family of RISC microprocessors designed and marketed by
- Sun Microsystems, incorporated. This port covers the newer 64-bit
- UltraSPARC. The UltraLinux project maintains both the SPARC32 and
- SPARC64 ports; its web page is available at
- <http://www.ultralinux.org/>.
-
# Global things across all Sun machines.
config RWSEM_GENERIC_SPINLOCK
bool
@@ -246,6 +180,10 @@ config HUGETLB_PAGE_SIZE_64K
endchoice
+endmenu
+
+source "mm/Kconfig"
+
config GENERIC_ISA_DMA
bool
default y
@@ -344,33 +282,6 @@ config PCI_DOMAINS
bool
default PCI
-config RTC
- tristate
- depends on PCI
- default y
- ---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
- will get access to the real time clock (or hardware clock) built
- into your computer.
-
- Every PC has such a clock built in. It can be used to generate
- signals from as low as 1Hz up to 8192Hz, and can also be used
- as a 24 hour alarm. It reports status information via the file
- /proc/driver/rtc and its behaviour is set by various ioctls on
- /dev/rtc.
-
- If you run Linux on a multiprocessor machine and said Y to
- "Symmetric Multi Processing" above, you should say Y here to read
- and set the RTC in an SMP compatible fashion.
-
- If you think you have a use for such a device (such as periodic data
- sampling), then say Y here, and read <file:Documentation/rtc.txt>
- for details.
-
- To compile this driver as a module, choose M here: the
- module will be called rtc.
-
source "drivers/pci/Kconfig"
config SUN_OPENPROMFS
@@ -414,6 +325,8 @@ config BINFMT_AOUT32
If you want to run SunOS binaries (see SunOS binary emulation below)
or other a.out binaries, say Y. If unsure, say N.
+menu "Executable file formats"
+
source "fs/Kconfig.binfmt"
config SUNOS_EMUL
@@ -436,74 +349,7 @@ config SOLARIS_EMUL
To compile this code as a module, choose M here: the
module will be called solaris.
-source "drivers/parport/Kconfig"
-
-config PRINTER
- tristate "Parallel printer support"
- depends on PARPORT
- ---help---
- If you intend to attach a printer to the parallel port of your Linux
- box (as opposed to using a serial printer; if the connector at the
- printer has 9 or 25 holes ["female"], then it's serial), say Y.
- Also read the Printing-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- It is possible to share one parallel port among several devices
- (e.g. printer and ZIP drive) and it is safe to compile the
- corresponding drivers into the kernel.
- To compile this driver as a module, choose M here and read
- <file:Documentation/parport.txt>. The module will be called lp.
-
- If you have several parallel ports, you can specify which ports to
- use with the "lp" kernel command line option. (Try "man bootparam"
- or see the documentation of your boot loader (lilo or loadlin) about
- how to pass options to the kernel at boot time.) The syntax of the
- "lp" command line option can be found in <file:drivers/char/lp.c>.
-
- If you have more than 8 printers, you need to increase the LP_NO
- macro in lp.c and the PARPORT_MAX macro in parport.h.
-
-config PPDEV
- tristate "Support for user-space parallel port device drivers"
- depends on PARPORT
- ---help---
- Saying Y to this adds support for /dev/parport device nodes. This
- is needed for programs that want portable access to the parallel
- port, for instance deviceid (which displays Plug-and-Play device
- IDs).
-
- This is the parallel port equivalent of SCSI generic support (sg).
- It is safe to say N to this -- it is not needed for normal printing
- or parallel port CD-ROM/disk support.
-
- To compile this driver as a module, choose M here: the
- module will be called ppdev.
-
- If unsure, say N.
-
-config ENVCTRL
- tristate "SUNW, envctrl support"
- depends on PCI
- help
- Kernel support for temperature and fan monitoring on Sun SME
- machines.
-
- To compile this driver as a module, choose M here: the
- module will be called envctrl.
-
-config DISPLAY7SEG
- tristate "7-Segment Display support"
- depends on PCI
- ---help---
- This is the driver for the 7-segment display and LED present on
- Sun Microsystems CompactPCI models CP1400 and CP1500.
-
- To compile this driver as a module, choose M here: the
- module will be called display7seg.
-
- If you do not have a CompactPCI model CP1400 or CP1500, or
- another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
- you should say N to this option.
+endmenu
config CMDLINE_BOOL
bool "Default bootloader kernel arguments"
@@ -521,148 +367,16 @@ config CMDLINE
NOTE: This option WILL override the PROM bootargs setting!
-source "mm/Kconfig"
-
-endmenu
-
source "net/Kconfig"
-source "drivers/base/Kconfig"
-
-source "drivers/video/Kconfig"
-
-source "drivers/serial/Kconfig"
+source "drivers/Kconfig"
source "drivers/sbus/char/Kconfig"
-source "drivers/mtd/Kconfig"
-
-source "drivers/block/Kconfig"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
source "drivers/fc4/Kconfig"
-source "drivers/md/Kconfig"
-
-if PCI
-source "drivers/message/fusion/Kconfig"
-endif
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/net/Kconfig"
-
-source "drivers/isdn/Kconfig"
-
-source "drivers/telephony/Kconfig"
-
-# This one must be before the filesystem configs. -DaveM
-
-menu "Unix98 PTY support"
-
-config UNIX98_PTYS
- bool "Unix98 PTY support"
- ---help---
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
- a physical terminal; the master device is used by a process to
- read data from and write data to the slave, thereby emulating a
- terminal. Typical programs for the master side are telnet servers
- and xterms.
-
- Linux has traditionally used the BSD-like names /dev/ptyxx for
- masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
- has a number of problems. The GNU C library glibc 2.1 and later,
- however, supports the Unix98 naming standard: in order to acquire a
- pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
- terminal is then made available to the process and the pseudo
- terminal slave can be accessed as /dev/pts/<number>. What was
- traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
- The entries in /dev/pts/ are created on the fly by a virtual
- file system; therefore, if you say Y here you should say Y to
- "/dev/pts file system for Unix98 PTYs" as well.
-
- If you want to say Y here, you need to have the C library glibc 2.1
- or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
- Read the instructions in <file:Documentation/Changes> pertaining to
- pseudo terminals. It's safe to say N.
-
-config UNIX98_PTY_COUNT
- int "Maximum number of Unix98 PTYs in use (0-2048)"
- depends on UNIX98_PTYS
- default "256"
- help
- The maximum number of Unix98 PTYs that can be used at any one time.
- The default is 256, and should be enough for desktop systems. Server
- machines which support incoming telnet/rlogin/ssh connections and/or
- serve several X terminals may want to increase this: every incoming
- connection and every xterm uses up one PTY.
-
- When not in use, each additional set of 256 PTYs occupy
- approximately 8 KB of kernel memory on 32-bit architectures.
-
-endmenu
-
-menu "XFree86 DRI support"
-
-config DRM
- bool "Direct Rendering Manager (XFree86 DRI support)"
- help
- Kernel-level support for the Direct Rendering Infrastructure (DRI)
- introduced in XFree86 4.0. If you say Y here, you need to select
- the module that's right for your graphics card from the list below.
- These modules provide support for synchronization, security, and
- DMA transfers. Please see <http://dri.sourceforge.net/> for more
- details. You should also select and configure AGP
- (/dev/agpgart) support.
-
-config DRM_FFB
- tristate "Creator/Creator3D"
- depends on DRM && BROKEN
- help
- Choose this option if you have one of Sun's Creator3D-based graphics
- and frame buffer cards. Product page at
- <http://www.sun.com/desktop/products/Graphics/creator3d.html>.
-
-config DRM_TDFX
- tristate "3dfx Banshee/Voodoo3+"
- depends on DRM
- help
- Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
- graphics card. If M is selected, the module will be called tdfx.
-
-config DRM_R128
- tristate "ATI Rage 128"
- depends on DRM
- help
- Choose this option if you have an ATI Rage 128 graphics card. If M
- is selected, the module will be called r128. AGP support for
- this card is strongly suggested (unless you have a PCI version).
-
-endmenu
-
-source "drivers/input/Kconfig"
-
-source "drivers/i2c/Kconfig"
-
-source "drivers/hwmon/Kconfig"
-
source "fs/Kconfig"
-source "drivers/media/Kconfig"
-
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-source "drivers/infiniband/Kconfig"
-
-source "drivers/char/watchdog/Kconfig"
-
source "arch/sparc64/oprofile/Kconfig"
source "arch/sparc64/Kconfig.debug"
diff --git a/arch/sparc64/kernel/asm-offsets.c b/arch/sparc64/kernel/asm-offsets.c
new file mode 100644
index 000000000000..9e263112a6e2
--- /dev/null
+++ b/arch/sparc64/kernel/asm-offsets.c
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 88332f00094a..3e0badb820c5 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -21,6 +21,7 @@
#include <asm/visasm.h>
#include <asm/estate.h>
#include <asm/auxio.h>
+#include <asm/sfafsr.h>
#define curptr g6
@@ -690,14 +691,159 @@ netbsd_syscall:
retl
nop
- /* These next few routines must be sure to clear the
- * SFSR FaultValid bit so that the fast tlb data protection
- * handler does not flush the wrong context and lock up the
- * box.
+ /* We need to carefully read the error status, ACK
+ * the errors, prevent recursive traps, and pass the
+ * information on to C code for logging.
+ *
+ * We pass the AFAR in as-is, and we encode the status
+ * information as described in asm-sparc64/sfafsr.h
+ */
+ .globl __spitfire_access_error
+__spitfire_access_error:
+ /* Disable ESTATE error reporting so that we do not
+ * take recursive traps and RED state the processor.
+ */
+ stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
+ membar #Sync
+
+ mov UDBE_UE, %g1
+ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+
+ /* __spitfire_cee_trap branches here with AFSR in %g4 and
+ * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the
+ * ESTATE Error Enable register.
+ */
+__spitfire_cee_trap_continue:
+ ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
+
+ rdpr %tt, %g3
+ and %g3, 0x1ff, %g3 ! Paranoia
+ sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
+ or %g4, %g3, %g4
+ rdpr %tl, %g3
+ cmp %g3, 1
+ mov 1, %g3
+ bleu %xcc, 1f
+ sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
+
+ or %g4, %g3, %g4
+
+ /* Read in the UDB error register state, clearing the
+ * sticky error bits as-needed. We only clear them if
+ * the UE bit is set. Likewise, __spitfire_cee_trap
+ * below will only do so if the CE bit is set.
+ *
+ * NOTE: UltraSparc-I/II have high and low UDB error
+ * registers, corresponding to the two UDB units
+ * present on those chips. UltraSparc-IIi only
+ * has a single UDB, called "SDB" in the manual.
+ * For IIi the upper UDB register always reads
+ * as zero so for our purposes things will just
+ * work with the checks below.
*/
- .globl __do_data_access_exception
- .globl __do_data_access_exception_tl1
-__do_data_access_exception_tl1:
+1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
+ and %g3, 0x3ff, %g7 ! Paranoia
+ sllx %g7, SFSTAT_UDBH_SHIFT, %g7
+ or %g4, %g7, %g4
+ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+ be,pn %xcc, 1f
+ nop
+ stxa %g3, [%g0] ASI_UDB_ERROR_W
+ membar #Sync
+
+1: mov 0x18, %g3
+ ldxa [%g3] ASI_UDBL_ERROR_R, %g3
+ and %g3, 0x3ff, %g7 ! Paranoia
+ sllx %g7, SFSTAT_UDBL_SHIFT, %g7
+ or %g4, %g7, %g4
+ andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
+ be,pn %xcc, 1f
+ nop
+ mov 0x18, %g7
+ stxa %g3, [%g7] ASI_UDB_ERROR_W
+ membar #Sync
+
+1: /* Ok, now that we've latched the error state,
+ * clear the sticky bits in the AFSR.
+ */
+ stxa %g4, [%g0] ASI_AFSR
+ membar #Sync
+
+ rdpr %tl, %g2
+ cmp %g2, 1
+ rdpr %pil, %g2
+ bleu,pt %xcc, 1f
+ wrpr %g0, 15, %pil
+
+ ba,pt %xcc, etraptl1
+ rd %pc, %g7
+
+ ba,pt %xcc, 2f
+ nop
+
+1: ba,pt %xcc, etrap_irq
+ rd %pc, %g7
+
+2: mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_access_error
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
+
+ /* This is the trap handler entry point for ECC correctable
+ * errors. They are corrected, but we listen for the trap
+ * so that the event can be logged.
+ *
+ * Disrupting errors are either:
+ * 1) single-bit ECC errors during UDB reads to system
+ * memory
+ * 2) data parity errors during write-back events
+ *
+ * As far as I can make out from the manual, the CEE trap
+ * is only for correctable errors during memory read
+ * accesses by the front-end of the processor.
+ *
+ * The code below is only for trap level 1 CEE events,
+ * as it is the only situation where we can safely record
+ * and log. For trap level >1 we just clear the CE bit
+ * in the AFSR and return.
+ *
+ * This is just like __spiftire_access_error above, but it
+ * specifically handles correctable errors. If an
+ * uncorrectable error is indicated in the AFSR we
+ * will branch directly above to __spitfire_access_error
+ * to handle it instead. Uncorrectable therefore takes
+ * priority over correctable, and the error logging
+ * C code will notice this case by inspecting the
+ * trap type.
+ */
+ .globl __spitfire_cee_trap
+__spitfire_cee_trap:
+ ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
+ mov 1, %g3
+ sllx %g3, SFAFSR_UE_SHIFT, %g3
+ andcc %g4, %g3, %g0 ! Check for UE
+ bne,pn %xcc, __spitfire_access_error
+ nop
+
+ /* Ok, in this case we only have a correctable error.
+ * Indicate we only wish to capture that state in register
+ * %g1, and we only disable CE error reporting unlike UE
+ * handling which disables all errors.
+ */
+ ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
+ andn %g3, ESTATE_ERR_CE, %g3
+ stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
+ membar #Sync
+
+ /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
+ ba,pt %xcc, __spitfire_cee_trap_continue
+ mov UDBE_CE, %g1
+
+ .globl __spitfire_data_access_exception
+ .globl __spitfire_data_access_exception_tl1
+__spitfire_data_access_exception_tl1:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
mov TLB_SFSR, %g3
@@ -706,9 +852,25 @@ __do_data_access_exception_tl1:
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
membar #Sync
+ rdpr %tt, %g3
+ cmp %g3, 0x80 ! first win spill/fill trap
+ blu,pn %xcc, 1f
+ cmp %g3, 0xff ! last win spill/fill trap
+ bgu,pn %xcc, 1f
+ nop
ba,pt %xcc, winfix_dax
rdpr %tpc, %g3
-__do_data_access_exception:
+1: sethi %hi(109f), %g7
+ ba,pt %xcc, etraptl1
+109: or %g7, %lo(109b), %g7
+ mov %l4, %o1
+ mov %l5, %o2
+ call spitfire_data_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
+
+__spitfire_data_access_exception:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
mov TLB_SFSR, %g3
@@ -722,20 +884,19 @@ __do_data_access_exception:
109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
- call data_access_exception
+ call spitfire_data_access_exception
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
clr %l6
- .globl __do_instruction_access_exception
- .globl __do_instruction_access_exception_tl1
-__do_instruction_access_exception_tl1:
+ .globl __spitfire_insn_access_exception
+ .globl __spitfire_insn_access_exception_tl1
+__spitfire_insn_access_exception_tl1:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
mov TLB_SFSR, %g3
- mov DMMU_SFAR, %g5
- ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
- ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
membar #Sync
sethi %hi(109f), %g7
@@ -743,18 +904,17 @@ __do_instruction_access_exception_tl1:
109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
- call instruction_access_exception_tl1
+ call spitfire_insn_access_exception_tl1
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
clr %l6
-__do_instruction_access_exception:
+__spitfire_insn_access_exception:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
mov TLB_SFSR, %g3
- mov DMMU_SFAR, %g5
- ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
- ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
+ ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
+ rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
membar #Sync
sethi %hi(109f), %g7
@@ -762,235 +922,11 @@ __do_instruction_access_exception:
109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
- call instruction_access_exception
+ call spitfire_insn_access_exception
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
clr %l6
- /* This is the trap handler entry point for ECC correctable
- * errors. They are corrected, but we listen for the trap
- * so that the event can be logged.
- *
- * Disrupting errors are either:
- * 1) single-bit ECC errors during UDB reads to system
- * memory
- * 2) data parity errors during write-back events
- *
- * As far as I can make out from the manual, the CEE trap
- * is only for correctable errors during memory read
- * accesses by the front-end of the processor.
- *
- * The code below is only for trap level 1 CEE events,
- * as it is the only situation where we can safely record
- * and log. For trap level >1 we just clear the CE bit
- * in the AFSR and return.
- */
-
- /* Our trap handling infrastructure allows us to preserve
- * two 64-bit values during etrap for arguments to
- * subsequent C code. Therefore we encode the information
- * as follows:
- *
- * value 1) Full 64-bits of AFAR
- * value 2) Low 33-bits of AFSR, then bits 33-->42
- * are UDBL error status and bits 43-->52
- * are UDBH error status
- */
- .align 64
- .globl cee_trap
-cee_trap:
- ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
- ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
- sllx %g1, 31, %g1 ! Clear reserved bits
- srlx %g1, 31, %g1 ! in AFSR
-
- /* NOTE: UltraSparc-I/II have high and low UDB error
- * registers, corresponding to the two UDB units
- * present on those chips. UltraSparc-IIi only
- * has a single UDB, called "SDB" in the manual.
- * For IIi the upper UDB register always reads
- * as zero so for our purposes things will just
- * work with the checks below.
- */
- ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
- andcc %g3, (1 << 8), %g4 ! Check CE bit
- sllx %g3, (64 - 10), %g3 ! Clear reserved bits
- srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
-
- sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
- or %g1, %g3, %g1 ! Or it in
- be,pn %xcc, 1f ! Branch if CE bit was clear
- nop
- stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
- membar #Sync ! Synchronize ASI stores
-1: mov 0x18, %g5 ! Addr of UDB-High error status
- ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
-
- andcc %g3, (1 << 8), %g4 ! Check CE bit
- sllx %g3, (64 - 10), %g3 ! Clear reserved bits
- srlx %g3, (64 - 10), %g3 ! in UDB-High error status
- sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
- or %g1, %g3, %g1 ! Or it in
- be,pn %xcc, 1f ! Branch if CE bit was clear
- nop
- nop
-
- stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
- membar #Sync ! Synchronize ASI stores
-1: mov 1, %g5 ! AFSR CE bit is
- sllx %g5, 20, %g5 ! bit 20
- stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
- membar #Sync ! Synchronize ASI stores
- sllx %g2, (64 - 41), %g2 ! Clear reserved bits
- srlx %g2, (64 - 41), %g2 ! in latched AFAR
-
- andn %g2, 0x0f, %g2 ! Finish resv bit clearing
- mov %g1, %g4 ! Move AFSR+UDB* into save reg
- mov %g2, %g5 ! Move AFAR into save reg
- rdpr %pil, %g2
- wrpr %g0, 15, %pil
- ba,pt %xcc, etrap_irq
- rd %pc, %g7
- mov %l4, %o0
-
- mov %l5, %o1
- call cee_log
- add %sp, PTREGS_OFF, %o2
- ba,a,pt %xcc, rtrap_irq
-
- /* Capture I/D/E-cache state into per-cpu error scoreboard.
- *
- * %g1: (TL>=0) ? 1 : 0
- * %g2: scratch
- * %g3: scratch
- * %g4: AFSR
- * %g5: AFAR
- * %g6: current thread ptr
- * %g7: scratch
- */
-#define CHEETAH_LOG_ERROR \
- /* Put "TL1" software bit into AFSR. */ \
- and %g1, 0x1, %g1; \
- sllx %g1, 63, %g2; \
- or %g4, %g2, %g4; \
- /* Get log entry pointer for this cpu at this trap level. */ \
- BRANCH_IF_JALAPENO(g2,g3,50f) \
- ldxa [%g0] ASI_SAFARI_CONFIG, %g2; \
- srlx %g2, 17, %g2; \
- ba,pt %xcc, 60f; \
- and %g2, 0x3ff, %g2; \
-50: ldxa [%g0] ASI_JBUS_CONFIG, %g2; \
- srlx %g2, 17, %g2; \
- and %g2, 0x1f, %g2; \
-60: sllx %g2, 9, %g2; \
- sethi %hi(cheetah_error_log), %g3; \
- ldx [%g3 + %lo(cheetah_error_log)], %g3; \
- brz,pn %g3, 80f; \
- nop; \
- add %g3, %g2, %g3; \
- sllx %g1, 8, %g1; \
- add %g3, %g1, %g1; \
- /* %g1 holds pointer to the top of the logging scoreboard */ \
- ldx [%g1 + 0x0], %g7; \
- cmp %g7, -1; \
- bne,pn %xcc, 80f; \
- nop; \
- stx %g4, [%g1 + 0x0]; \
- stx %g5, [%g1 + 0x8]; \
- add %g1, 0x10, %g1; \
- /* %g1 now points to D-cache logging area */ \
- set 0x3ff8, %g2; /* DC_addr mask */ \
- and %g5, %g2, %g2; /* DC_addr bits of AFAR */ \
- srlx %g5, 12, %g3; \
- or %g3, 1, %g3; /* PHYS tag + valid */ \
-10: ldxa [%g2] ASI_DCACHE_TAG, %g7; \
- cmp %g3, %g7; /* TAG match? */ \
- bne,pt %xcc, 13f; \
- nop; \
- /* Yep, what we want, capture state. */ \
- stx %g2, [%g1 + 0x20]; \
- stx %g7, [%g1 + 0x28]; \
- /* A membar Sync is required before and after utag access. */ \
- membar #Sync; \
- ldxa [%g2] ASI_DCACHE_UTAG, %g7; \
- membar #Sync; \
- stx %g7, [%g1 + 0x30]; \
- ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7; \
- stx %g7, [%g1 + 0x38]; \
- clr %g3; \
-12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7; \
- stx %g7, [%g1]; \
- add %g3, (1 << 5), %g3; \
- cmp %g3, (4 << 5); \
- bl,pt %xcc, 12b; \
- add %g1, 0x8, %g1; \
- ba,pt %xcc, 20f; \
- add %g1, 0x20, %g1; \
-13: sethi %hi(1 << 14), %g7; \
- add %g2, %g7, %g2; \
- srlx %g2, 14, %g7; \
- cmp %g7, 4; \
- bl,pt %xcc, 10b; \
- nop; \
- add %g1, 0x40, %g1; \
-20: /* %g1 now points to I-cache logging area */ \
- set 0x1fe0, %g2; /* IC_addr mask */ \
- and %g5, %g2, %g2; /* IC_addr bits of AFAR */ \
- sllx %g2, 1, %g2; /* IC_addr[13:6]==VA[12:5] */ \
- srlx %g5, (13 - 8), %g3; /* Make PTAG */ \
- andn %g3, 0xff, %g3; /* Mask off undefined bits */ \
-21: ldxa [%g2] ASI_IC_TAG, %g7; \
- andn %g7, 0xff, %g7; \
- cmp %g3, %g7; \
- bne,pt %xcc, 23f; \
- nop; \
- /* Yep, what we want, capture state. */ \
- stx %g2, [%g1 + 0x40]; \
- stx %g7, [%g1 + 0x48]; \
- add %g2, (1 << 3), %g2; \
- ldxa [%g2] ASI_IC_TAG, %g7; \
- add %g2, (1 << 3), %g2; \
- stx %g7, [%g1 + 0x50]; \
- ldxa [%g2] ASI_IC_TAG, %g7; \
- add %g2, (1 << 3), %g2; \
- stx %g7, [%g1 + 0x60]; \
- ldxa [%g2] ASI_IC_TAG, %g7; \
- stx %g7, [%g1 + 0x68]; \
- sub %g2, (3 << 3), %g2; \
- ldxa [%g2] ASI_IC_STAG, %g7; \
- stx %g7, [%g1 + 0x58]; \
- clr %g3; \
- srlx %g2, 2, %g2; \
-22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7; \
- stx %g7, [%g1]; \
- add %g3, (1 << 3), %g3; \
- cmp %g3, (8 << 3); \
- bl,pt %xcc, 22b; \
- add %g1, 0x8, %g1; \
- ba,pt %xcc, 30f; \
- add %g1, 0x30, %g1; \
-23: sethi %hi(1 << 14), %g7; \
- add %g2, %g7, %g2; \
- srlx %g2, 14, %g7; \
- cmp %g7, 4; \
- bl,pt %xcc, 21b; \
- nop; \
- add %g1, 0x70, %g1; \
-30: /* %g1 now points to E-cache logging area */ \
- andn %g5, (32 - 1), %g2; /* E-cache subblock */ \
- stx %g2, [%g1 + 0x20]; \
- ldxa [%g2] ASI_EC_TAG_DATA, %g7; \
- stx %g7, [%g1 + 0x28]; \
- ldxa [%g2] ASI_EC_R, %g0; \
- clr %g3; \
-31: ldxa [%g3] ASI_EC_DATA, %g7; \
- stx %g7, [%g1 + %g3]; \
- add %g3, 0x8, %g3; \
- cmp %g3, 0x20; \
- bl,pt %xcc, 31b; \
- nop; \
-80: /* DONE */
-
/* These get patched into the trap table at boot time
* once we know we have a cheetah processor.
*/
@@ -1227,6 +1163,170 @@ dcpe_icpe_tl1_common:
membar #Sync
retry
+ /* Capture I/D/E-cache state into per-cpu error scoreboard.
+ *
+ * %g1: (TL>=0) ? 1 : 0
+ * %g2: scratch
+ * %g3: scratch
+ * %g4: AFSR
+ * %g5: AFAR
+ * %g6: current thread ptr
+ * %g7: scratch
+ */
+__cheetah_log_error:
+ /* Put "TL1" software bit into AFSR. */
+ and %g1, 0x1, %g1
+ sllx %g1, 63, %g2
+ or %g4, %g2, %g4
+
+ /* Get log entry pointer for this cpu at this trap level. */
+ BRANCH_IF_JALAPENO(g2,g3,50f)
+ ldxa [%g0] ASI_SAFARI_CONFIG, %g2
+ srlx %g2, 17, %g2
+ ba,pt %xcc, 60f
+ and %g2, 0x3ff, %g2
+
+50: ldxa [%g0] ASI_JBUS_CONFIG, %g2
+ srlx %g2, 17, %g2
+ and %g2, 0x1f, %g2
+
+60: sllx %g2, 9, %g2
+ sethi %hi(cheetah_error_log), %g3
+ ldx [%g3 + %lo(cheetah_error_log)], %g3
+ brz,pn %g3, 80f
+ nop
+
+ add %g3, %g2, %g3
+ sllx %g1, 8, %g1
+ add %g3, %g1, %g1
+
+ /* %g1 holds pointer to the top of the logging scoreboard */
+ ldx [%g1 + 0x0], %g7
+ cmp %g7, -1
+ bne,pn %xcc, 80f
+ nop
+
+ stx %g4, [%g1 + 0x0]
+ stx %g5, [%g1 + 0x8]
+ add %g1, 0x10, %g1
+
+ /* %g1 now points to D-cache logging area */
+ set 0x3ff8, %g2 /* DC_addr mask */
+ and %g5, %g2, %g2 /* DC_addr bits of AFAR */
+ srlx %g5, 12, %g3
+ or %g3, 1, %g3 /* PHYS tag + valid */
+
+10: ldxa [%g2] ASI_DCACHE_TAG, %g7
+ cmp %g3, %g7 /* TAG match? */
+ bne,pt %xcc, 13f
+ nop
+
+ /* Yep, what we want, capture state. */
+ stx %g2, [%g1 + 0x20]
+ stx %g7, [%g1 + 0x28]
+
+ /* A membar Sync is required before and after utag access. */
+ membar #Sync
+ ldxa [%g2] ASI_DCACHE_UTAG, %g7
+ membar #Sync
+ stx %g7, [%g1 + 0x30]
+ ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7
+ stx %g7, [%g1 + 0x38]
+ clr %g3
+
+12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7
+ stx %g7, [%g1]
+ add %g3, (1 << 5), %g3
+ cmp %g3, (4 << 5)
+ bl,pt %xcc, 12b
+ add %g1, 0x8, %g1
+
+ ba,pt %xcc, 20f
+ add %g1, 0x20, %g1
+
+13: sethi %hi(1 << 14), %g7
+ add %g2, %g7, %g2
+ srlx %g2, 14, %g7
+ cmp %g7, 4
+ bl,pt %xcc, 10b
+ nop
+
+ add %g1, 0x40, %g1
+
+ /* %g1 now points to I-cache logging area */
+20: set 0x1fe0, %g2 /* IC_addr mask */
+ and %g5, %g2, %g2 /* IC_addr bits of AFAR */
+ sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */
+ srlx %g5, (13 - 8), %g3 /* Make PTAG */
+ andn %g3, 0xff, %g3 /* Mask off undefined bits */
+
+21: ldxa [%g2] ASI_IC_TAG, %g7
+ andn %g7, 0xff, %g7
+ cmp %g3, %g7
+ bne,pt %xcc, 23f
+ nop
+
+ /* Yep, what we want, capture state. */
+ stx %g2, [%g1 + 0x40]
+ stx %g7, [%g1 + 0x48]
+ add %g2, (1 << 3), %g2
+ ldxa [%g2] ASI_IC_TAG, %g7
+ add %g2, (1 << 3), %g2
+ stx %g7, [%g1 + 0x50]
+ ldxa [%g2] ASI_IC_TAG, %g7
+ add %g2, (1 << 3), %g2
+ stx %g7, [%g1 + 0x60]
+ ldxa [%g2] ASI_IC_TAG, %g7
+ stx %g7, [%g1 + 0x68]
+ sub %g2, (3 << 3), %g2
+ ldxa [%g2] ASI_IC_STAG, %g7
+ stx %g7, [%g1 + 0x58]
+ clr %g3
+ srlx %g2, 2, %g2
+
+22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7
+ stx %g7, [%g1]
+ add %g3, (1 << 3), %g3
+ cmp %g3, (8 << 3)
+ bl,pt %xcc, 22b
+ add %g1, 0x8, %g1
+
+ ba,pt %xcc, 30f
+ add %g1, 0x30, %g1
+
+23: sethi %hi(1 << 14), %g7
+ add %g2, %g7, %g2
+ srlx %g2, 14, %g7
+ cmp %g7, 4
+ bl,pt %xcc, 21b
+ nop
+
+ add %g1, 0x70, %g1
+
+ /* %g1 now points to E-cache logging area */
+30: andn %g5, (32 - 1), %g2
+ stx %g2, [%g1 + 0x20]
+ ldxa [%g2] ASI_EC_TAG_DATA, %g7
+ stx %g7, [%g1 + 0x28]
+ ldxa [%g2] ASI_EC_R, %g0
+ clr %g3
+
+31: ldxa [%g3] ASI_EC_DATA, %g7
+ stx %g7, [%g1 + %g3]
+ add %g3, 0x8, %g3
+ cmp %g3, 0x20
+
+ bl,pt %xcc, 31b
+ nop
+80:
+ rdpr %tt, %g2
+ cmp %g2, 0x70
+ be c_fast_ecc
+ cmp %g2, 0x63
+ be c_cee
+ nop
+ ba,pt %xcc, c_deferred
+
/* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
* in the trap table. That code has done a memory barrier
* and has disabled both the I-cache and D-cache in the DCU
@@ -1252,8 +1352,10 @@ cheetah_fast_ecc:
stxa %g4, [%g0] ASI_AFSR
membar #Sync
- CHEETAH_LOG_ERROR
+ ba,pt %xcc, __cheetah_log_error
+ nop
+c_fast_ecc:
rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
@@ -1278,8 +1380,10 @@ cheetah_cee:
stxa %g4, [%g0] ASI_AFSR
membar #Sync
- CHEETAH_LOG_ERROR
+ ba,pt %xcc, __cheetah_log_error
+ nop
+c_cee:
rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
@@ -1304,8 +1408,10 @@ cheetah_deferred_trap:
stxa %g4, [%g0] ASI_AFSR
membar #Sync
- CHEETAH_LOG_ERROR
+ ba,pt %xcc, __cheetah_log_error
+ nop
+c_deferred:
rdpr %pil, %g2
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 8104a56ca2d8..1fa06c4e3bdb 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -538,11 +538,12 @@ cheetah_tlb_fixup:
nop
call cheetah_plus_patch_winfixup
nop
-
2: /* Patch copy/page operations to cheetah optimized versions. */
call cheetah_patch_copyops
nop
+ call cheetah_patch_copy_page
+ nop
call cheetah_patch_cachetlbops
nop
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index bbf11f85dab1..0d66d07c8c6e 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -8,6 +8,7 @@
#include <linux/kprobes.h>
#include <asm/kdebug.h>
#include <asm/signal.h>
+#include <asm/cacheflush.h>
/* We do not have hardware single-stepping on sparc64.
* So we implement software single-stepping with breakpoint
@@ -37,31 +38,31 @@
* - Mark that we are no longer actively in a kprobe.
*/
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
return 0;
}
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
{
p->ainsn.insn[0] = *p->addr;
p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
p->opcode = *p->addr;
}
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
flushi(p->addr);
}
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flushi(p->addr);
}
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}
@@ -111,7 +112,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
}
}
-static int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
void *addr = (void *) regs->tpc;
@@ -191,8 +192,9 @@ no_kprobe:
* The original INSN location was REAL_PC, it actually
* executed at PC and produced destination address NPC.
*/
-static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
- unsigned long pc, unsigned long npc)
+static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
+ unsigned long pc,
+ unsigned long npc)
{
/* Branch not taken, no mods necessary. */
if (npc == pc + 0x4UL)
@@ -217,7 +219,8 @@ static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
/* If INSN is an instruction which writes it's PC location
* into a destination register, fix that up.
*/
-static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
+static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
+ unsigned long real_pc)
{
unsigned long *slot = NULL;
@@ -257,7 +260,7 @@ static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
* This function prepares to return from the post-single-step
* breakpoint trap.
*/
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
u32 insn = p->ainsn.insn[0];
@@ -315,8 +318,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
/*
* Wrapper routine to for handling exceptions.
*/
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
- void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
switch (val) {
@@ -344,7 +347,8 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
return NOTIFY_DONE;
}
-asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
+asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
+ struct pt_regs *regs)
{
BUG_ON(trap_level != 0x170 && trap_level != 0x171);
@@ -368,7 +372,7 @@ static struct pt_regs jprobe_saved_regs;
static struct pt_regs *jprobe_saved_regs_location;
static struct sparc_stackf jprobe_saved_stack;
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
@@ -390,7 +394,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
{
preempt_enable_no_resched();
__asm__ __volatile__(
@@ -403,7 +407,7 @@ extern void jprobe_return_trap_instruction(void);
extern void __show_regs(struct pt_regs * regs);
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
u32 *addr = (u32 *) regs->tpc;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index f21c993f8856..2ff7c32ab0ce 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -359,134 +359,17 @@ void pcibios_fixup_bus(struct pci_bus *pbus)
pbus->resource[1] = &pbm->mem_space;
}
-int pci_claim_resource(struct pci_dev *pdev, int resource)
+struct resource *pcibios_select_root(struct pci_dev *pdev, struct resource *r)
{
struct pci_pbm_info *pbm = pdev->bus->sysdata;
- struct resource *res = &pdev->resource[resource];
- struct resource *root;
-
- if (!pbm)
- return -EINVAL;
+ struct resource *root = NULL;
- if (res->flags & IORESOURCE_IO)
+ if (r->flags & IORESOURCE_IO)
root = &pbm->io_space;
- else
+ if (r->flags & IORESOURCE_MEM)
root = &pbm->mem_space;
- pbm->parent->resource_adjust(pdev, res, root);
-
- return request_resource(root, res);
-}
-
-/*
- * Given the PCI bus a device resides on, try to
- * find an acceptable resource allocation for a
- * specific device resource..
- */
-static int pci_assign_bus_resource(const struct pci_bus *bus,
- struct pci_dev *dev,
- struct resource *res,
- unsigned long size,
- unsigned long min,
- int resno)
-{
- unsigned int type_mask;
- int i;
-
- type_mask = IORESOURCE_IO | IORESOURCE_MEM;
- for (i = 0 ; i < 4; i++) {
- struct resource *r = bus->resource[i];
- if (!r)
- continue;
-
- /* type_mask must match */
- if ((res->flags ^ r->flags) & type_mask)
- continue;
-
- /* Ok, try it out.. */
- if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
- continue;
-
- /* PCI config space updated by caller. */
- return 0;
- }
- return -EBUSY;
-}
-
-int pci_assign_resource(struct pci_dev *pdev, int resource)
-{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_pbm_info *pbm = pcp->pbm;
- struct resource *res = &pdev->resource[resource];
- unsigned long min, size;
- int err;
-
- if (res->flags & IORESOURCE_IO)
- min = pbm->io_space.start + 0x400UL;
- else
- min = pbm->mem_space.start;
-
- size = res->end - res->start + 1;
-
- err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
-
- if (err < 0) {
- printk("PCI: Failed to allocate resource %d for %s\n",
- resource, pci_name(pdev));
- } else {
- /* Update PCI config space. */
- pbm->parent->base_address_update(pdev, resource);
- }
-
- return err;
-}
-
-/* Sort resources by alignment */
-void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
-{
- int i;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *r;
- struct resource_list *list, *tmp;
- unsigned long r_align;
-
- r = &dev->resource[i];
- r_align = r->end - r->start;
-
- if (!(r->flags) || r->parent)
- continue;
- if (!r_align) {
- printk(KERN_WARNING "PCI: Ignore bogus resource %d "
- "[%lx:%lx] of %s\n",
- i, r->start, r->end, pci_name(dev));
- continue;
- }
- r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
- for (list = head; ; list = list->next) {
- unsigned long align = 0;
- struct resource_list *ln = list->next;
- int idx;
-
- if (ln) {
- idx = ln->res - &ln->dev->resource[0];
- align = (idx < PCI_BRIDGE_RESOURCES) ?
- ln->res->end - ln->res->start + 1 :
- ln->res->start;
- }
- if (r_align > align) {
- tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
- if (!tmp)
- panic("pdev_sort_resources(): "
- "kmalloc() failed!\n");
- tmp->next = ln;
- tmp->res = r;
- tmp->dev = dev;
- list->next = tmp;
- break;
- }
- }
- }
+ return root;
}
void pcibios_update_irq(struct pci_dev *pdev, int irq)
@@ -736,8 +619,7 @@ static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma
static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
- /* Our io_remap_page_range/io_remap_pfn_range takes care of this,
- do nothing. */
+ /* Our io_remap_pfn_range takes care of this, do nothing. */
}
/* Perform the actual remap of the pages for a PCI device mapping, as appropriate
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 2803bc7c2c79..425c60cfea19 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -466,7 +466,7 @@ do_flush_sync:
if (!limit)
break;
udelay(1);
- membar("#LoadLoad");
+ rmb();
}
if (!limit)
printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 91ab466d6c66..6ed1ef25e0ac 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -307,7 +307,7 @@ static unsigned char psycho_pil_table[] = {
/*0x32*/15, /* Power Management */
};
-static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
int ret;
@@ -344,9 +344,9 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
return ret;
}
-static unsigned int __init psycho_irq_build(struct pci_pbm_info *pbm,
- struct pci_dev *pdev,
- unsigned int ino)
+static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev,
+ unsigned int ino)
{
struct ino_bucket *bucket;
unsigned long imap, iclr;
@@ -1024,7 +1024,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
#define PSYCHO_CE_INO 0x2f
#define PSYCHO_PCIERR_A_INO 0x30
#define PSYCHO_PCIERR_B_INO 0x31
-static void __init psycho_register_error_handlers(struct pci_controller_info *p)
+static void psycho_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
unsigned long base = p->pbm_A.controller_regs;
@@ -1091,15 +1091,15 @@ static void __init psycho_register_error_handlers(struct pci_controller_info *p)
}
/* PSYCHO boot time probing and initialization. */
-static void __init psycho_resource_adjust(struct pci_dev *pdev,
- struct resource *res,
- struct resource *root)
+static void psycho_resource_adjust(struct pci_dev *pdev,
+ struct resource *res,
+ struct resource *root)
{
res->start += root->start;
res->end += root->start;
}
-static void __init psycho_base_address_update(struct pci_dev *pdev, int resource)
+static void psycho_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
@@ -1144,7 +1144,7 @@ static void __init psycho_base_address_update(struct pci_dev *pdev, int resource
pci_write_config_dword(pdev, where + 4, 0);
}
-static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
+static void pbm_config_busmastering(struct pci_pbm_info *pbm)
{
u8 *addr;
@@ -1161,8 +1161,8 @@ static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
pci_config_write8(addr, 64);
}
-static void __init pbm_scan_bus(struct pci_controller_info *p,
- struct pci_pbm_info *pbm)
+static void pbm_scan_bus(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
@@ -1189,7 +1189,7 @@ static void __init pbm_scan_bus(struct pci_controller_info *p,
pci_setup_busmastering(pbm, pbm->pci_bus);
}
-static void __init psycho_scan_bus(struct pci_controller_info *p)
+static void psycho_scan_bus(struct pci_controller_info *p)
{
pbm_config_busmastering(&p->pbm_B);
p->pbm_B.is_66mhz_capable = 0;
@@ -1204,7 +1204,7 @@ static void __init psycho_scan_bus(struct pci_controller_info *p)
psycho_register_error_handlers(p);
}
-static void __init psycho_iommu_init(struct pci_controller_info *p)
+static void psycho_iommu_init(struct pci_controller_info *p)
{
struct pci_iommu *iommu = p->pbm_A.iommu;
unsigned long tsbbase, i;
@@ -1327,8 +1327,8 @@ static void psycho_controller_hwinit(struct pci_controller_info *p)
psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp);
}
-static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
- struct pci_pbm_info *pbm)
+static void pbm_register_toplevel_resources(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
{
char *name = pbm->name;
@@ -1481,7 +1481,7 @@ static void psycho_pbm_init(struct pci_controller_info *p,
#define PSYCHO_CONFIGSPACE 0x001000000UL
-void __init psycho_init(int node, char *model_name)
+void psycho_init(int node, char *model_name)
{
struct linux_prom64_registers pr_regs[3];
struct pci_controller_info *p;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 52bf3431a422..0ee6bd5b9ac6 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -554,7 +554,7 @@ static unsigned char sabre_pil_table[] = {
/*0x32*/15, /* Power Management */
};
-static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
int ret;
@@ -612,9 +612,9 @@ static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_a
sabre_read(sync_reg);
}
-static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
- struct pci_dev *pdev,
- unsigned int ino)
+static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev,
+ unsigned int ino)
{
struct ino_bucket *bucket;
unsigned long imap, iclr;
@@ -1009,7 +1009,7 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs
#define SABRE_UE_INO 0x2e
#define SABRE_CE_INO 0x2f
#define SABRE_PCIERR_INO 0x30
-static void __init sabre_register_error_handlers(struct pci_controller_info *p)
+static void sabre_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
unsigned long base = pbm->controller_regs;
@@ -1056,9 +1056,9 @@ static void __init sabre_register_error_handlers(struct pci_controller_info *p)
sabre_write(base + SABRE_PCICTRL, tmp);
}
-static void __init sabre_resource_adjust(struct pci_dev *pdev,
- struct resource *res,
- struct resource *root)
+static void sabre_resource_adjust(struct pci_dev *pdev,
+ struct resource *res,
+ struct resource *root)
{
struct pci_pbm_info *pbm = pdev->bus->sysdata;
unsigned long base;
@@ -1072,7 +1072,7 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev,
res->end += base;
}
-static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
+static void sabre_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
@@ -1118,7 +1118,7 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
pci_write_config_dword(pdev, where + 4, 0);
}
-static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
+static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
{
struct pci_dev *pdev;
@@ -1181,7 +1181,7 @@ static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
return cookie;
}
-static void __init sabre_scan_bus(struct pci_controller_info *p)
+static void sabre_scan_bus(struct pci_controller_info *p)
{
static int once;
struct pci_bus *sabre_bus, *pbus;
@@ -1262,9 +1262,9 @@ static void __init sabre_scan_bus(struct pci_controller_info *p)
sabre_register_error_handlers(p);
}
-static void __init sabre_iommu_init(struct pci_controller_info *p,
- int tsbsize, unsigned long dvma_offset,
- u32 dma_mask)
+static void sabre_iommu_init(struct pci_controller_info *p,
+ int tsbsize, unsigned long dvma_offset,
+ u32 dma_mask)
{
struct pci_iommu *iommu = p->pbm_A.iommu;
unsigned long tsbbase, i, order;
@@ -1345,8 +1345,8 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
}
}
-static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
- struct pci_pbm_info *pbm)
+static void pbm_register_toplevel_resources(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
{
char *name = pbm->name;
unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
@@ -1415,7 +1415,7 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
&pbm->mem_space);
}
-static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
+static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
{
struct pci_pbm_info *pbm;
char namebuf[128];
@@ -1552,7 +1552,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
}
}
-void __init sabre_init(int pnode, char *model_name)
+void sabre_init(int pnode, char *model_name)
{
struct linux_prom64_registers pr_regs[2];
struct pci_controller_info *p;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 6a182bb66281..331382e1a75d 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -285,7 +285,7 @@ static unsigned char schizo_pil_table[] = {
/*0x3f*/0, /* Reserved for NewLink */
};
-static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
int ret;
@@ -1221,7 +1221,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
* PCI bus units of the same Tomatillo. I still have not really
* figured this out...
*/
-static void __init tomatillo_register_error_handlers(struct pci_controller_info *p)
+static void tomatillo_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm;
unsigned int irq;
@@ -1359,7 +1359,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
(SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
}
-static void __init schizo_register_error_handlers(struct pci_controller_info *p)
+static void schizo_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm;
unsigned int irq;
@@ -1505,7 +1505,7 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
(SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
}
-static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
+static void pbm_config_busmastering(struct pci_pbm_info *pbm)
{
u8 *addr;
@@ -1522,8 +1522,8 @@ static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
pci_config_write8(addr, 64);
}
-static void __init pbm_scan_bus(struct pci_controller_info *p,
- struct pci_pbm_info *pbm)
+static void pbm_scan_bus(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
@@ -1550,8 +1550,8 @@ static void __init pbm_scan_bus(struct pci_controller_info *p,
pci_setup_busmastering(pbm, pbm->pci_bus);
}
-static void __init __schizo_scan_bus(struct pci_controller_info *p,
- int chip_type)
+static void __schizo_scan_bus(struct pci_controller_info *p,
+ int chip_type)
{
if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
printk("PCI: Only one PCI bus module of controller found.\n");
@@ -1577,17 +1577,17 @@ static void __init __schizo_scan_bus(struct pci_controller_info *p,
schizo_register_error_handlers(p);
}
-static void __init schizo_scan_bus(struct pci_controller_info *p)
+static void schizo_scan_bus(struct pci_controller_info *p)
{
__schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
}
-static void __init tomatillo_scan_bus(struct pci_controller_info *p)
+static void tomatillo_scan_bus(struct pci_controller_info *p)
{
__schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
}
-static void __init schizo_base_address_update(struct pci_dev *pdev, int resource)
+static void schizo_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
@@ -1632,9 +1632,9 @@ static void __init schizo_base_address_update(struct pci_dev *pdev, int resource
pci_write_config_dword(pdev, where + 4, 0);
}
-static void __init schizo_resource_adjust(struct pci_dev *pdev,
- struct resource *res,
- struct resource *root)
+static void schizo_resource_adjust(struct pci_dev *pdev,
+ struct resource *res,
+ struct resource *root)
{
res->start += root->start;
res->end += root->start;
@@ -1702,8 +1702,8 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
pbm->mem_space.start);
}
-static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
- struct pci_pbm_info *pbm)
+static void pbm_register_toplevel_resources(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
{
pbm->io_space.name = pbm->mem_space.name = pbm->name;
@@ -1932,7 +1932,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
#define TOMATILLO_PCI_IOC_TDIAG (0x2250UL)
#define TOMATILLO_PCI_IOC_DDIAG (0x2290UL)
-static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
+static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
{
u64 tmp;
@@ -1986,9 +1986,9 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
}
}
-static void __init schizo_pbm_init(struct pci_controller_info *p,
- int prom_node, u32 portid,
- int chip_type)
+static void schizo_pbm_init(struct pci_controller_info *p,
+ int prom_node, u32 portid,
+ int chip_type)
{
struct linux_prom64_registers pr_regs[4];
unsigned int busrange[2];
@@ -2145,7 +2145,7 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
return (x == y);
}
-static void __init __schizo_init(int node, char *model_name, int chip_type)
+static void __schizo_init(int node, char *model_name, int chip_type)
{
struct pci_controller_info *p;
struct pci_iommu *iommu;
@@ -2213,17 +2213,17 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
schizo_pbm_init(p, node, portid, chip_type);
}
-void __init schizo_init(int node, char *model_name)
+void schizo_init(int node, char *model_name)
{
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO);
}
-void __init schizo_plus_init(int node, char *model_name)
+void schizo_plus_init(int node, char *model_name)
{
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
}
-void __init tomatillo_init(int node, char *model_name)
+void tomatillo_init(int node, char *model_name)
{
__schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
}
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 07424b075938..7d10b0397091 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -103,7 +103,7 @@ void cpu_idle(void)
* other cpus see our increasing idleness for the buddy
* redistribution algorithm. -DaveM
*/
- membar("#StoreStore | #StoreLoad");
+ membar_storeload_storestore();
}
}
@@ -607,11 +607,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct thread_info *t = p->thread_info;
char *child_trap_frame;
-#ifdef CONFIG_DEBUG_SPINLOCK
- p->thread.smp_lock_count = 0;
- p->thread.smp_lock_pc = 0;
-#endif
-
/* Calculate offset to stack_frame & pt_regs */
child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ));
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 0696ed4b9d64..fafd227735fa 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -153,11 +153,14 @@ __handle_signal:
rtrap_irq:
rtrap_clr_l6: clr %l6
rtrap:
- ldub [%g6 + TI_CPU], %l0
- sethi %hi(irq_stat), %l2 ! &softirq_active
- or %l2, %lo(irq_stat), %l2 ! &softirq_active
-irqsz_patchme: sllx %l0, 0, %l0
- lduw [%l2 + %l0], %l1 ! softirq_pending
+#ifndef CONFIG_SMP
+ sethi %hi(per_cpu____cpu_data), %l0
+ lduw [%l0 + %lo(per_cpu____cpu_data)], %l1
+#else
+ sethi %hi(per_cpu____cpu_data), %l0
+ or %l0, %lo(per_cpu____cpu_data), %l0
+ lduw [%l0 + %g5], %l1
+#endif
cmp %l1, 0
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 89f5e019f24c..e09ddf927655 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -147,7 +147,7 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long
if (!limit)
break;
udelay(1);
- membar("#LoadLoad");
+ rmb();
}
if (!limit)
printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index b7e6a91952b2..ddbed3341a23 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -33,7 +33,6 @@
#include <linux/cpu.h>
#include <linux/initrd.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
@@ -512,18 +511,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &prom_con;
#endif
-#ifdef CONFIG_SMP
- i = (unsigned long)&irq_stat[1] - (unsigned long)&irq_stat[0];
- if ((i == SMP_CACHE_BYTES) || (i == (2 * SMP_CACHE_BYTES))) {
- extern unsigned int irqsz_patchme[1];
- irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \
- SMP_CACHE_BYTES_SHIFT + 1);
- flushi((long)&irqsz_patchme[0]);
- } else {
- prom_printf("Unexpected size of irq_stat[] elements\n");
- prom_halt();
- }
-#endif
/* Work out if we are starfire early on */
check_if_starfire();
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index b27934671c35..60f5dfabb1e1 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -574,13 +574,12 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
{
setup_rt_frame(ka, regs, signr, oldset,
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
- if (!(ka->sa.sa_flags & SA_NOMASK)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked,signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index f28428f4170e..aecccd0df1d1 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -877,11 +877,12 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
unsigned long page = (unsigned long)
page_address(pte_page(*ptep));
- __asm__ __volatile__(
- " membar #StoreStore\n"
- " flush %0 + %1"
- : : "r" (page), "r" (address & (PAGE_SIZE - 1))
- : "memory");
+ wmb();
+ __asm__ __volatile__("flush %0 + %1"
+ : /* no outputs */
+ : "r" (page),
+ "r" (address & (PAGE_SIZE - 1))
+ : "memory");
}
pte_unmap(ptep);
preempt_enable();
@@ -1292,11 +1293,12 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
unsigned long page = (unsigned long)
page_address(pte_page(*ptep));
- __asm__ __volatile__(
- " membar #StoreStore\n"
- " flush %0 + %1"
- : : "r" (page), "r" (address & (PAGE_SIZE - 1))
- : "memory");
+ wmb();
+ __asm__ __volatile__("flush %0 + %1"
+ : /* no outputs */
+ : "r" (page),
+ "r" (address & (PAGE_SIZE - 1))
+ : "memory");
}
pte_unmap(ptep);
preempt_enable();
@@ -1325,13 +1327,12 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
else
setup_frame32(&ka->sa, regs, signr, oldset, info);
}
- if (!(ka->sa.sa_flags & SA_NOMASK)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked,signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b9b42491e118..b4fc6a5462b2 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -144,7 +144,7 @@ void __init smp_callin(void)
current->active_mm = &init_mm;
while (!cpu_isset(cpuid, smp_commenced_mask))
- membar("#LoadLoad");
+ rmb();
cpu_set(cpuid, cpu_online_map);
}
@@ -184,11 +184,11 @@ static inline long get_delta (long *rt, long *master)
for (i = 0; i < NUM_ITERS; i++) {
t0 = tick_ops->get_tick();
go[MASTER] = 1;
- membar("#StoreLoad");
+ membar_storeload();
while (!(tm = go[SLAVE]))
- membar("#LoadLoad");
+ rmb();
go[SLAVE] = 0;
- membar("#StoreStore");
+ wmb();
t1 = tick_ops->get_tick();
if (t1 - t0 < best_t1 - best_t0)
@@ -221,7 +221,7 @@ void smp_synchronize_tick_client(void)
go[MASTER] = 1;
while (go[MASTER])
- membar("#LoadLoad");
+ rmb();
local_irq_save(flags);
{
@@ -273,21 +273,21 @@ static void smp_synchronize_one_tick(int cpu)
/* wait for client to be ready */
while (!go[MASTER])
- membar("#LoadLoad");
+ rmb();
/* now let the client proceed into his loop */
go[MASTER] = 0;
- membar("#StoreLoad");
+ membar_storeload();
spin_lock_irqsave(&itc_sync_lock, flags);
{
for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) {
while (!go[MASTER])
- membar("#LoadLoad");
+ rmb();
go[MASTER] = 0;
- membar("#StoreStore");
+ wmb();
go[SLAVE] = tick_ops->get_tick();
- membar("#StoreLoad");
+ membar_storeload();
}
}
spin_unlock_irqrestore(&itc_sync_lock, flags);
@@ -927,11 +927,11 @@ void smp_capture(void)
smp_processor_id());
#endif
penguins_are_doing_time = 1;
- membar("#StoreStore | #LoadStore");
+ membar_storestore_loadstore();
atomic_inc(&smp_capture_registry);
smp_cross_call(&xcall_capture, 0, 0, 0);
while (atomic_read(&smp_capture_registry) != ncpus)
- membar("#LoadLoad");
+ rmb();
#ifdef CAPTURE_DEBUG
printk("done\n");
#endif
@@ -947,7 +947,7 @@ void smp_release(void)
smp_processor_id());
#endif
penguins_are_doing_time = 0;
- membar("#StoreStore | #StoreLoad");
+ membar_storeload_storestore();
atomic_dec(&smp_capture_registry);
}
}
@@ -970,9 +970,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
save_alternate_globals(global_save);
prom_world(1);
atomic_inc(&smp_capture_registry);
- membar("#StoreLoad | #StoreStore");
+ membar_storeload_storestore();
while (penguins_are_doing_time)
- membar("#LoadLoad");
+ rmb();
restore_alternate_globals(global_save);
atomic_dec(&smp_capture_registry);
prom_world(0);
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 9202d925a9ce..cbb5e59824e5 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -88,8 +88,6 @@ extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
extern long sparc32_open(const char __user * filename, int flags, int mode);
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long offset, unsigned long size, pgprot_t prot, int space);
extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long pfn, unsigned long size, pgprot_t prot);
extern void (*prom_palette)(int);
@@ -99,17 +97,6 @@ extern int __ashrdi3(int, int);
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
-#if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK)
-extern void _do_spin_lock (spinlock_t *lock, char *str);
-extern void _do_spin_unlock (spinlock_t *lock);
-extern int _spin_trylock (spinlock_t *lock);
-extern void _do_read_lock(rwlock_t *rw, char *str);
-extern void _do_read_unlock(rwlock_t *rw, char *str);
-extern void _do_write_lock(rwlock_t *rw, char *str);
-extern void _do_write_unlock(rwlock_t *rw);
-extern int _do_write_trylock(rwlock_t *rw, char *str);
-#endif
-
extern unsigned long phys_base;
extern unsigned long pfn_base;
@@ -128,17 +115,12 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
/* used by various drivers */
#ifdef CONFIG_SMP
-#ifndef CONFIG_DEBUG_SPINLOCK
/* Out of line rw-locking implementation. */
EXPORT_SYMBOL(__read_lock);
EXPORT_SYMBOL(__read_unlock);
EXPORT_SYMBOL(__write_lock);
EXPORT_SYMBOL(__write_unlock);
EXPORT_SYMBOL(__write_trylock);
-/* Out of line spin-locking implementation. */
-EXPORT_SYMBOL(_raw_spin_lock);
-EXPORT_SYMBOL(_raw_spin_lock_flags);
-#endif
/* Hard IRQ locking */
EXPORT_SYMBOL(synchronize_irq);
@@ -152,18 +134,6 @@ EXPORT_SYMBOL(_mcount);
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map);
-/* Spinlock debugging library, optional. */
-#ifdef CONFIG_DEBUG_SPINLOCK
-EXPORT_SYMBOL(_do_spin_lock);
-EXPORT_SYMBOL(_do_spin_unlock);
-EXPORT_SYMBOL(_spin_trylock);
-EXPORT_SYMBOL(_do_read_lock);
-EXPORT_SYMBOL(_do_read_unlock);
-EXPORT_SYMBOL(_do_write_lock);
-EXPORT_SYMBOL(_do_write_unlock);
-EXPORT_SYMBOL(_do_write_trylock);
-#endif
-
EXPORT_SYMBOL(smp_call_function);
#endif /* CONFIG_SMP */
@@ -268,7 +238,6 @@ EXPORT_SYMBOL(pci_dma_supported);
#endif
/* I/O device mmaping on Sparc64. */
-EXPORT_SYMBOL(io_remap_page_range);
EXPORT_SYMBOL(io_remap_pfn_range);
/* Solaris/SunOS binary compatibility */
diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c
index 87c1aeb02220..7654b8a7f03a 100644
--- a/arch/sparc64/kernel/sunos_ioctl32.c
+++ b/arch/sparc64/kernel/sunos_ioctl32.c
@@ -152,11 +152,12 @@ asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg)
ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg);
goto out;
- case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
- ret = sys_ioctl(fd, SIOCSIFMTU, arg);
+ case _IOW('i', 21, struct ifreq32):
+ ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg);
goto out;
- case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
- ret = sys_ioctl(fd, SIOCGIFMTU, arg);
+
+ case _IOWR('i', 22, struct ifreq32):
+ ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg);
goto out;
case _IOWR('i', 23, struct ifreq32):
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 1d3aa588df8a..7f6239ed2521 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1002,29 +1002,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
asmlinkage long sparc32_open(const char __user *filename,
int flags, int mode)
{
- char * tmp;
- int fd, error;
-
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file * f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (IS_ERR(f))
- goto out_error;
- fd_install(fd, f);
- }
-out:
- putname(tmp);
- }
- return fd;
-
-out_error:
- put_unused_fd(fd);
- fd = error;
- goto out;
+ return do_sys_open(filename, flags, mode);
}
extern unsigned long do_mremap(unsigned long addr,
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 362b9c26871b..3f08a32f51a1 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -449,7 +449,7 @@ static inline void timer_check_rtc(void)
static long last_rtc_update;
/* Determine when to update the Mostek clock. */
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 0c9e54b2f0c8..b280b2ef674f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -33,6 +33,7 @@
#include <asm/dcu.h>
#include <asm/estate.h>
#include <asm/chafsr.h>
+#include <asm/sfafsr.h>
#include <asm/psrcompat.h>
#include <asm/processor.h>
#include <asm/timer.h>
@@ -143,8 +144,7 @@ void do_BUG(const char *file, int line)
}
#endif
-void instruction_access_exception(struct pt_regs *regs,
- unsigned long sfsr, unsigned long sfar)
+void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
{
siginfo_t info;
@@ -153,8 +153,8 @@ void instruction_access_exception(struct pt_regs *regs,
return;
if (regs->tstate & TSTATE_PRIV) {
- printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
- sfsr, sfar);
+ printk("spitfire_insn_access_exception: SFSR[%016lx] "
+ "SFAR[%016lx], going.\n", sfsr, sfar);
die_if_kernel("Iax", regs);
}
if (test_thread_flag(TIF_32BIT)) {
@@ -169,19 +169,17 @@ void instruction_access_exception(struct pt_regs *regs,
force_sig_info(SIGSEGV, &info, current);
}
-void instruction_access_exception_tl1(struct pt_regs *regs,
- unsigned long sfsr, unsigned long sfar)
+void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
{
if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
0, 0x8, SIGTRAP) == NOTIFY_STOP)
return;
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
- instruction_access_exception(regs, sfsr, sfar);
+ spitfire_insn_access_exception(regs, sfsr, sfar);
}
-void data_access_exception(struct pt_regs *regs,
- unsigned long sfsr, unsigned long sfar)
+void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
{
siginfo_t info;
@@ -207,8 +205,8 @@ void data_access_exception(struct pt_regs *regs,
return;
}
/* Shit... */
- printk("data_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
- sfsr, sfar);
+ printk("spitfire_data_access_exception: SFSR[%016lx] "
+ "SFAR[%016lx], going.\n", sfsr, sfar);
die_if_kernel("Dax", regs);
}
@@ -220,6 +218,16 @@ void data_access_exception(struct pt_regs *regs,
force_sig_info(SIGSEGV, &info, current);
}
+void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
+{
+ if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
+ 0, 0x30, SIGTRAP) == NOTIFY_STOP)
+ return;
+
+ dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
+ spitfire_data_access_exception(regs, sfsr, sfar);
+}
+
#ifdef CONFIG_PCI
/* This is really pathetic... */
extern volatile int pci_poke_in_progress;
@@ -253,54 +261,13 @@ static void spitfire_clean_and_reenable_l1_caches(void)
: "memory");
}
-void do_iae(struct pt_regs *regs)
+static void spitfire_enable_estate_errors(void)
{
- siginfo_t info;
-
- spitfire_clean_and_reenable_l1_caches();
-
- if (notify_die(DIE_TRAP, "instruction access exception", regs,
- 0, 0x8, SIGTRAP) == NOTIFY_STOP)
- return;
-
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_OBJERR;
- info.si_addr = (void *)0;
- info.si_trapno = 0;
- force_sig_info(SIGBUS, &info, current);
-}
-
-void do_dae(struct pt_regs *regs)
-{
- siginfo_t info;
-
-#ifdef CONFIG_PCI
- if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
- spitfire_clean_and_reenable_l1_caches();
-
- pci_poke_faulted = 1;
-
- /* Why the fuck did they have to change this? */
- if (tlb_type == cheetah || tlb_type == cheetah_plus)
- regs->tpc += 4;
-
- regs->tnpc = regs->tpc + 4;
- return;
- }
-#endif
- spitfire_clean_and_reenable_l1_caches();
-
- if (notify_die(DIE_TRAP, "data access exception", regs,
- 0, 0x30, SIGTRAP) == NOTIFY_STOP)
- return;
-
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_OBJERR;
- info.si_addr = (void *)0;
- info.si_trapno = 0;
- force_sig_info(SIGBUS, &info, current);
+ __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (ESTATE_ERR_ALL),
+ "i" (ASI_ESTATE_ERROR_EN));
}
static char ecc_syndrome_table[] = {
@@ -338,65 +305,15 @@ static char ecc_syndrome_table[] = {
0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
};
-/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
- * in the following format. The AFAR is left as is, with
- * reserved bits cleared, and is a raw 40-bit physical
- * address.
- */
-#define CE_STATUS_UDBH_UE (1UL << (43 + 9))
-#define CE_STATUS_UDBH_CE (1UL << (43 + 8))
-#define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
-#define CE_STATUS_UDBH_SHIFT 43
-#define CE_STATUS_UDBL_UE (1UL << (33 + 9))
-#define CE_STATUS_UDBL_CE (1UL << (33 + 8))
-#define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
-#define CE_STATUS_UDBL_SHIFT 33
-#define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
-#define CE_STATUS_AFSR_ME (1UL << 32)
-#define CE_STATUS_AFSR_PRIV (1UL << 31)
-#define CE_STATUS_AFSR_ISAP (1UL << 30)
-#define CE_STATUS_AFSR_ETP (1UL << 29)
-#define CE_STATUS_AFSR_IVUE (1UL << 28)
-#define CE_STATUS_AFSR_TO (1UL << 27)
-#define CE_STATUS_AFSR_BERR (1UL << 26)
-#define CE_STATUS_AFSR_LDP (1UL << 25)
-#define CE_STATUS_AFSR_CP (1UL << 24)
-#define CE_STATUS_AFSR_WP (1UL << 23)
-#define CE_STATUS_AFSR_EDP (1UL << 22)
-#define CE_STATUS_AFSR_UE (1UL << 21)
-#define CE_STATUS_AFSR_CE (1UL << 20)
-#define CE_STATUS_AFSR_ETS (0xfUL << 16)
-#define CE_STATUS_AFSR_ETS_SHIFT 16
-#define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
-#define CE_STATUS_AFSR_PSYND_SHIFT 0
-
-/* Layout of Ecache TAG Parity Syndrome of AFSR */
-#define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
-#define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
-#define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
-#define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
-
static char *syndrome_unknown = "<Unknown>";
-asmlinkage void cee_log(unsigned long ce_status,
- unsigned long afar,
- struct pt_regs *regs)
+static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
{
- char memmod_str[64];
- char *p;
- unsigned short scode, udb_reg;
+ unsigned short scode;
+ char memmod_str[64], *p;
- printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
- "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",
- smp_processor_id(),
- (ce_status & CE_STATUS_AFSR_MASK),
- afar,
- ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
- ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
-
- udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
- if (udb_reg & (1 << 8)) {
- scode = ecc_syndrome_table[udb_reg & 0xff];
+ if (udbl & bit) {
+ scode = ecc_syndrome_table[udbl & 0xff];
if (prom_getunumber(scode, afar,
memmod_str, sizeof(memmod_str)) == -1)
p = syndrome_unknown;
@@ -407,9 +324,8 @@ asmlinkage void cee_log(unsigned long ce_status,
smp_processor_id(), scode, p);
}
- udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);
- if (udb_reg & (1 << 8)) {
- scode = ecc_syndrome_table[udb_reg & 0xff];
+ if (udbh & bit) {
+ scode = ecc_syndrome_table[udbh & 0xff];
if (prom_getunumber(scode, afar,
memmod_str, sizeof(memmod_str)) == -1)
p = syndrome_unknown;
@@ -419,6 +335,127 @@ asmlinkage void cee_log(unsigned long ce_status,
"Memory Module \"%s\"\n",
smp_processor_id(), scode, p);
}
+
+}
+
+static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
+{
+
+ printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
+ "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
+ smp_processor_id(), afsr, afar, udbl, udbh, tl1);
+
+ spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
+
+ /* We always log it, even if someone is listening for this
+ * trap.
+ */
+ notify_die(DIE_TRAP, "Correctable ECC Error", regs,
+ 0, TRAP_TYPE_CEE, SIGTRAP);
+
+ /* The Correctable ECC Error trap does not disable I/D caches. So
+ * we only have to restore the ESTATE Error Enable register.
+ */
+ spitfire_enable_estate_errors();
+}
+
+static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
+ "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
+ smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
+
+ /* XXX add more human friendly logging of the error status
+ * XXX as is implemented for cheetah
+ */
+
+ spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
+
+ /* We always log it, even if someone is listening for this
+ * trap.
+ */
+ notify_die(DIE_TRAP, "Uncorrectable Error", regs,
+ 0, tt, SIGTRAP);
+
+ if (regs->tstate & TSTATE_PRIV) {
+ if (tl1)
+ dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
+ die_if_kernel("UE", regs);
+ }
+
+ /* XXX need more intelligent processing here, such as is implemented
+ * XXX for cheetah errors, in fact if the E-cache still holds the
+ * XXX line with bad parity this will loop
+ */
+
+ spitfire_clean_and_reenable_l1_caches();
+ spitfire_enable_estate_errors();
+
+ if (test_thread_flag(TIF_32BIT)) {
+ regs->tpc &= 0xffffffff;
+ regs->tnpc &= 0xffffffff;
+ }
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_OBJERR;
+ info.si_addr = (void *)0;
+ info.si_trapno = 0;
+ force_sig_info(SIGBUS, &info, current);
+}
+
+void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
+{
+ unsigned long afsr, tt, udbh, udbl;
+ int tl1;
+
+ afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
+ tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
+ tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
+ udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
+ udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
+
+#ifdef CONFIG_PCI
+ if (tt == TRAP_TYPE_DAE &&
+ pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
+ spitfire_clean_and_reenable_l1_caches();
+ spitfire_enable_estate_errors();
+
+ pci_poke_faulted = 1;
+ regs->tnpc = regs->tpc + 4;
+ return;
+ }
+#endif
+
+ if (afsr & SFAFSR_UE)
+ spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
+
+ if (tt == TRAP_TYPE_CEE) {
+ /* Handle the case where we took a CEE trap, but ACK'd
+ * only the UE state in the UDB error registers.
+ */
+ if (afsr & SFAFSR_UE) {
+ if (udbh & UDBE_CE) {
+ __asm__ __volatile__(
+ "stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (udbh & UDBE_CE),
+ "r" (0x0), "i" (ASI_UDB_ERROR_W));
+ }
+ if (udbl & UDBE_CE) {
+ __asm__ __volatile__(
+ "stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (udbl & UDBE_CE),
+ "r" (0x18), "i" (ASI_UDB_ERROR_W));
+ }
+ }
+
+ spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
+ }
}
int cheetah_pcache_forced_on;
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 491bb3681f9d..8365bc1f81f3 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -18,9 +18,10 @@ sparc64_ttable_tl0:
tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
tl0_iax: membar #Sync
- TRAP_NOSAVE_7INSNS(__do_instruction_access_exception)
+ TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception)
tl0_resv009: BTRAP(0x9)
-tl0_iae: TRAP(do_iae)
+tl0_iae: membar #Sync
+ TRAP_NOSAVE_7INSNS(__spitfire_access_error)
tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
tl0_ill: membar #Sync
TRAP_7INSNS(do_illegal_instruction)
@@ -36,9 +37,10 @@ tl0_cwin: CLEAN_WINDOW
tl0_div0: TRAP(do_div0)
tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
tl0_resv02f: BTRAP(0x2f)
-tl0_dax: TRAP_NOSAVE(__do_data_access_exception)
+tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
tl0_resv031: BTRAP(0x31)
-tl0_dae: TRAP(do_dae)
+tl0_dae: membar #Sync
+ TRAP_NOSAVE_7INSNS(__spitfire_access_error)
tl0_resv033: BTRAP(0x33)
tl0_mna: TRAP_NOSAVE(do_mna)
tl0_lddfmna: TRAP_NOSAVE(do_lddfmna)
@@ -73,7 +75,8 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)
tl0_ivec: TRAP_IVEC
tl0_paw: TRAP(do_paw)
tl0_vaw: TRAP(do_vaw)
-tl0_cee: TRAP_NOSAVE(cee_trap)
+tl0_cee: membar #Sync
+ TRAP_NOSAVE_7INSNS(__spitfire_cee_trap)
tl0_iamiss:
#include "itlb_base.S"
tl0_damiss:
@@ -175,9 +178,10 @@ tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
sparc64_ttable_tl1:
tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3)
tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7)
-tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1)
+tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
tl1_resv009: BTRAPTL1(0x9)
-tl1_iae: TRAPTL1(do_iae_tl1)
+tl1_iae: membar #Sync
+ TRAP_NOSAVE_7INSNS(__spitfire_access_error)
tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
tl1_ill: TRAPTL1(do_ill_tl1)
tl1_privop: BTRAPTL1(0x11)
@@ -193,9 +197,10 @@ tl1_cwin: CLEAN_WINDOW
tl1_div0: TRAPTL1(do_div0_tl1)
tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
-tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1)
+tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
tl1_resv031: BTRAPTL1(0x31)
-tl1_dae: TRAPTL1(do_dae_tl1)
+tl1_dae: membar #Sync
+ TRAP_NOSAVE_7INSNS(__spitfire_access_error)
tl1_resv033: BTRAPTL1(0x33)
tl1_mna: TRAP_NOSAVE(do_mna)
tl1_lddfmna: TRAPTL1(do_lddfmna_tl1)
@@ -219,8 +224,8 @@ tl1_paw: TRAPTL1(do_paw_tl1)
tl1_vaw: TRAPTL1(do_vaw_tl1)
/* The grotty trick to save %g1 into current->thread.cee_stuff
- * is because when we take this trap we could be interrupting trap
- * code already using the trap alternate global registers.
+ * is because when we take this trap we could be interrupting
+ * trap code already using the trap alternate global registers.
*
* We cross our fingers and pray that this store/load does
* not cause yet another CEE trap.
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 11c3e88732e4..da9739f0d437 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -349,9 +349,9 @@ int handle_popc(u32 insn, struct pt_regs *regs)
extern void do_fpother(struct pt_regs *regs);
extern void do_privact(struct pt_regs *regs);
-extern void data_access_exception(struct pt_regs *regs,
- unsigned long sfsr,
- unsigned long sfar);
+extern void spitfire_data_access_exception(struct pt_regs *regs,
+ unsigned long sfsr,
+ unsigned long sfar);
int handle_ldf_stq(u32 insn, struct pt_regs *regs)
{
@@ -394,14 +394,14 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
break;
}
default:
- data_access_exception(regs, 0, addr);
+ spitfire_data_access_exception(regs, 0, addr);
return 1;
}
if (put_user (first >> 32, (u32 __user *)addr) ||
__put_user ((u32)first, (u32 __user *)(addr + 4)) ||
__put_user (second >> 32, (u32 __user *)(addr + 8)) ||
__put_user ((u32)second, (u32 __user *)(addr + 12))) {
- data_access_exception(regs, 0, addr);
+ spitfire_data_access_exception(regs, 0, addr);
return 1;
}
} else {
@@ -414,7 +414,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
do_privact(regs);
return 1;
} else if (asi > ASI_SNFL) {
- data_access_exception(regs, 0, addr);
+ spitfire_data_access_exception(regs, 0, addr);
return 1;
}
switch (insn & 0x180000) {
@@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
}
if (err && !(asi & 0x2 /* NF */)) {
- data_access_exception(regs, 0, addr);
+ spitfire_data_access_exception(regs, 0, addr);
return 1;
}
if (asi & 0x8) /* Little */ {
@@ -534,7 +534,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
*(u64 *)(f->regs + freg) = value;
current_thread_info()->fpsaved[0] |= flag;
} else {
-daex: data_access_exception(regs, sfsr, sfar);
+daex: spitfire_data_access_exception(regs, sfsr, sfar);
return;
}
advance(regs);
@@ -578,7 +578,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
__put_user ((u32)value, (u32 __user *)(sfar + 4)))
goto daex;
} else {
-daex: data_access_exception(regs, sfsr, sfar);
+daex: spitfire_data_access_exception(regs, sfsr, sfar);
return;
}
advance(regs);
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 950423da8a6a..f47d0be39378 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -17,6 +17,7 @@ SECTIONS
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.gnu.warning)
} =0
_etext = .;
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index dfbc7e0dcf70..99c809a1e5ac 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -318,7 +318,7 @@ fill_fixup_dax:
nop
rdpr %pstate, %l1 ! Prepare to change globals.
mov %g4, %o1 ! Setup args for
- mov %g5, %o2 ! final call to data_access_exception.
+ mov %g5, %o2 ! final call to spitfire_data_access_exception.
andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
mov %g6, %o7 ! Stash away current.
@@ -330,7 +330,7 @@ fill_fixup_dax:
mov TSB_REG, %g1
ldxa [%g1] ASI_IMMU, %g5
#endif
- call data_access_exception
+ call spitfire_data_access_exception
add %sp, PTREGS_OFF, %o0
b,pt %xcc, rtrap
@@ -391,7 +391,7 @@ window_dax_from_user_common:
109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
- call data_access_exception
+ call spitfire_data_access_exception
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
clr %l6
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 40dbeec7e5d6..d968aebe83b2 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,7 +14,6 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
copy_in_user.o user_fixup.o memmove.o \
mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
-lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
obj-y += iomap.o
diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c
index 3008d536e8c2..3c6cfbb20360 100644
--- a/arch/sparc64/lib/PeeCeeI.c
+++ b/arch/sparc64/lib/PeeCeeI.c
@@ -7,28 +7,31 @@
#include <asm/io.h>
#include <asm/byteorder.h>
-void outsb(void __iomem *addr, const void *src, unsigned long count)
+void outsb(unsigned long __addr, const void *src, unsigned long count)
{
+ void __iomem *addr = (void __iomem *) __addr;
const u8 *p = src;
- while(count--)
+ while (count--)
outb(*p++, addr);
}
-void outsw(void __iomem *addr, const void *src, unsigned long count)
+void outsw(unsigned long __addr, const void *src, unsigned long count)
{
- if(count) {
+ void __iomem *addr = (void __iomem *) __addr;
+
+ if (count) {
u16 *ps = (u16 *)src;
u32 *pi;
- if(((u64)src) & 0x2) {
+ if (((u64)src) & 0x2) {
u16 val = le16_to_cpup(ps);
outw(val, addr);
ps++;
count--;
}
pi = (u32 *)ps;
- while(count >= 2) {
+ while (count >= 2) {
u32 w = le32_to_cpup(pi);
pi++;
@@ -37,19 +40,21 @@ void outsw(void __iomem *addr, const void *src, unsigned long count)
count -= 2;
}
ps = (u16 *)pi;
- if(count) {
+ if (count) {
u16 val = le16_to_cpup(ps);
outw(val, addr);
}
}
}
-void outsl(void __iomem *addr, const void *src, unsigned long count)
+void outsl(unsigned long __addr, const void *src, unsigned long count)
{
- if(count) {
- if((((u64)src) & 0x3) == 0) {
+ void __iomem *addr = (void __iomem *) __addr;
+
+ if (count) {
+ if ((((u64)src) & 0x3) == 0) {
u32 *p = (u32 *)src;
- while(count--) {
+ while (count--) {
u32 val = cpu_to_le32p(p);
outl(val, addr);
p++;
@@ -60,13 +65,13 @@ void outsl(void __iomem *addr, const void *src, unsigned long count)
u32 l = 0, l2;
u32 *pi;
- switch(((u64)src) & 0x3) {
+ switch (((u64)src) & 0x3) {
case 0x2:
count -= 1;
l = cpu_to_le16p(ps) << 16;
ps++;
pi = (u32 *)ps;
- while(count--) {
+ while (count--) {
l2 = cpu_to_le32p(pi);
pi++;
outl(((l >> 16) | (l2 << 16)), addr);
@@ -86,7 +91,7 @@ void outsl(void __iomem *addr, const void *src, unsigned long count)
ps++;
l |= (l2 << 16);
pi = (u32 *)ps;
- while(count--) {
+ while (count--) {
l2 = cpu_to_le32p(pi);
pi++;
outl(((l >> 8) | (l2 << 24)), addr);
@@ -101,7 +106,7 @@ void outsl(void __iomem *addr, const void *src, unsigned long count)
pb = (u8 *)src;
l = (*pb++ << 24);
pi = (u32 *)pb;
- while(count--) {
+ while (count--) {
l2 = cpu_to_le32p(pi);
pi++;
outl(((l >> 24) | (l2 << 8)), addr);
@@ -119,16 +124,18 @@ void outsl(void __iomem *addr, const void *src, unsigned long count)
}
}
-void insb(void __iomem *addr, void *dst, unsigned long count)
+void insb(unsigned long __addr, void *dst, unsigned long count)
{
- if(count) {
+ void __iomem *addr = (void __iomem *) __addr;
+
+ if (count) {
u32 *pi;
u8 *pb = dst;
- while((((unsigned long)pb) & 0x3) && count--)
+ while ((((unsigned long)pb) & 0x3) && count--)
*pb++ = inb(addr);
pi = (u32 *)pb;
- while(count >= 4) {
+ while (count >= 4) {
u32 w;
w = (inb(addr) << 24);
@@ -139,23 +146,25 @@ void insb(void __iomem *addr, void *dst, unsigned long count)
count -= 4;
}
pb = (u8 *)pi;
- while(count--)
+ while (count--)
*pb++ = inb(addr);
}
}
-void insw(void __iomem *addr, void *dst, unsigned long count)
+void insw(unsigned long __addr, void *dst, unsigned long count)
{
- if(count) {
+ void __iomem *addr = (void __iomem *) __addr;
+
+ if (count) {
u16 *ps = dst;
u32 *pi;
- if(((unsigned long)ps) & 0x2) {
+ if (((unsigned long)ps) & 0x2) {
*ps++ = le16_to_cpu(inw(addr));
count--;
}
pi = (u32 *)ps;
- while(count >= 2) {
+ while (count >= 2) {
u32 w;
w = (le16_to_cpu(inw(addr)) << 16);
@@ -164,31 +173,33 @@ void insw(void __iomem *addr, void *dst, unsigned long count)
count -= 2;
}
ps = (u16 *)pi;
- if(count)
+ if (count)
*ps = le16_to_cpu(inw(addr));
}
}
-void insl(void __iomem *addr, void *dst, unsigned long count)
+void insl(unsigned long __addr, void *dst, unsigned long count)
{
- if(count) {
- if((((unsigned long)dst) & 0x3) == 0) {
+ void __iomem *addr = (void __iomem *) __addr;
+
+ if (count) {
+ if ((((unsigned long)dst) & 0x3) == 0) {
u32 *pi = dst;
- while(count--)
+ while (count--)
*pi++ = le32_to_cpu(inl(addr));
} else {
u32 l = 0, l2, *pi;
u16 *ps;
u8 *pb;
- switch(((unsigned long)dst) & 3) {
+ switch (((unsigned long)dst) & 3) {
case 0x2:
ps = dst;
count -= 1;
l = le32_to_cpu(inl(addr));
*ps++ = l;
pi = (u32 *)ps;
- while(count--) {
+ while (count--) {
l2 = le32_to_cpu(inl(addr));
*pi++ = (l << 16) | (l2 >> 16);
l = l2;
@@ -205,7 +216,7 @@ void insl(void __iomem *addr, void *dst, unsigned long count)
ps = (u16 *)pb;
*ps++ = ((l >> 8) & 0xffff);
pi = (u32 *)ps;
- while(count--) {
+ while (count--) {
l2 = le32_to_cpu(inl(addr));
*pi++ = (l << 24) | (l2 >> 8);
l = l2;
@@ -220,7 +231,7 @@ void insl(void __iomem *addr, void *dst, unsigned long count)
l = le32_to_cpu(inl(addr));
*pb++ = l >> 24;
pi = (u32 *)pb;
- while(count--) {
+ while (count--) {
l2 = le32_to_cpu(inl(addr));
*pi++ = (l << 8) | (l2 >> 24);
l = l2;
diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S
index 23ebf2c970b7..feebb14fd27a 100644
--- a/arch/sparc64/lib/copy_page.S
+++ b/arch/sparc64/lib/copy_page.S
@@ -87,7 +87,7 @@ copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
membar #Sync
wrpr %o2, 0x0, %pstate
- BRANCH_IF_ANY_CHEETAH(g3,o2,1f)
+cheetah_copy_page_insn:
ba,pt %xcc, 9f
nop
@@ -240,3 +240,14 @@ copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
stw %o4, [%g6 + TI_PRE_COUNT]
.size copy_user_page, .-copy_user_page
+
+ .globl cheetah_patch_copy_page
+cheetah_patch_copy_page:
+ sethi %hi(0x01000000), %o1 ! NOP
+ sethi %hi(cheetah_copy_page_insn), %o0
+ or %o0, %lo(cheetah_copy_page_insn), %o0
+ stw %o1, [%o0]
+ membar #StoreStore
+ flush %o0
+ retl
+ nop
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
deleted file mode 100644
index f03344cf784e..000000000000
--- a/arch/sparc64/lib/debuglocks.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
- * debuglocks.c: Debugging versions of SMP locking primitives.
- *
- * Copyright (C) 1998 David S. Miller (davem@redhat.com)
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-
-#define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC))
-
-static inline void show (char *str, spinlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
-
- printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
- str, lock, cpu, (unsigned int) caller,
- lock->owner_pc, lock->owner_cpu);
-}
-
-static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
-
- printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
- str, lock, cpu, (unsigned int) caller,
- lock->writer_pc, lock->writer_cpu);
-}
-
-static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
-{
- int cpu = smp_processor_id();
- int i;
-
- printk("%s(%p) CPU#%d stuck at %08x\n",
- str, lock, cpu, (unsigned int) caller);
- printk("Writer: PC(%08x):CPU(%x)\n",
- lock->writer_pc, lock->writer_cpu);
- printk("Readers:");
- for (i = 0; i < NR_CPUS; i++)
- if (lock->reader_pc[i])
- printk(" %d[%08x]", i, lock->reader_pc[i]);
- printk("\n");
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-void _do_spin_lock(spinlock_t *lock, char *str)
-{
- unsigned long caller, val;
- int stuck = INIT_STUCK;
- int cpu = get_cpu();
- int shown = 0;
-
- GET_CALLER(caller);
-again:
- __asm__ __volatile__("ldstub [%1], %0"
- : "=r" (val)
- : "r" (&(lock->lock))
- : "memory");
- membar("#StoreLoad | #StoreStore");
- if (val) {
- while (lock->lock) {
- if (!--stuck) {
- if (shown++ <= 2)
- show(str, lock, caller);
- stuck = INIT_STUCK;
- }
- membar("#LoadLoad");
- }
- goto again;
- }
- lock->owner_pc = ((unsigned int)caller);
- lock->owner_cpu = cpu;
- current->thread.smp_lock_count++;
- current->thread.smp_lock_pc = ((unsigned int)caller);
-
- put_cpu();
-}
-
-int _do_spin_trylock(spinlock_t *lock)
-{
- unsigned long val, caller;
- int cpu = get_cpu();
-
- GET_CALLER(caller);
- __asm__ __volatile__("ldstub [%1], %0"
- : "=r" (val)
- : "r" (&(lock->lock))
- : "memory");
- membar("#StoreLoad | #StoreStore");
- if (!val) {
- lock->owner_pc = ((unsigned int)caller);
- lock->owner_cpu = cpu;
- current->thread.smp_lock_count++;
- current->thread.smp_lock_pc = ((unsigned int)caller);
- }
-
- put_cpu();
-
- return val == 0;
-}
-
-void _do_spin_unlock(spinlock_t *lock)
-{
- lock->owner_pc = 0;
- lock->owner_cpu = NO_PROC_ID;
- membar("#StoreStore | #LoadStore");
- lock->lock = 0;
- current->thread.smp_lock_count--;
-}
-
-/* Keep INIT_STUCK the same... */
-
-void _do_read_lock (rwlock_t *rw, char *str)
-{
- unsigned long caller, val;
- int stuck = INIT_STUCK;
- int cpu = get_cpu();
- int shown = 0;
-
- GET_CALLER(caller);
-wlock_again:
- /* Wait for any writer to go away. */
- while (((long)(rw->lock)) < 0) {
- if (!--stuck) {
- if (shown++ <= 2)
- show_read(str, rw, caller);
- stuck = INIT_STUCK;
- }
- membar("#LoadLoad");
- }
- /* Try once to increment the counter. */
- __asm__ __volatile__(
-" ldx [%0], %%g1\n"
-" brlz,a,pn %%g1, 2f\n"
-" mov 1, %0\n"
-" add %%g1, 1, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" sub %%g1, %%g7, %0\n"
-"2:" : "=r" (val)
- : "0" (&(rw->lock))
- : "g1", "g7", "memory");
- membar("#StoreLoad | #StoreStore");
- if (val)
- goto wlock_again;
- rw->reader_pc[cpu] = ((unsigned int)caller);
- current->thread.smp_lock_count++;
- current->thread.smp_lock_pc = ((unsigned int)caller);
-
- put_cpu();
-}
-
-void _do_read_unlock (rwlock_t *rw, char *str)
-{
- unsigned long caller, val;
- int stuck = INIT_STUCK;
- int cpu = get_cpu();
- int shown = 0;
-
- GET_CALLER(caller);
-
- /* Drop our identity _first_. */
- rw->reader_pc[cpu] = 0;
- current->thread.smp_lock_count--;
-runlock_again:
- /* Spin trying to decrement the counter using casx. */
- __asm__ __volatile__(
-" membar #StoreLoad | #LoadLoad\n"
-" ldx [%0], %%g1\n"
-" sub %%g1, 1, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" sub %%g1, %%g7, %0\n"
- : "=r" (val)
- : "0" (&(rw->lock))
- : "g1", "g7", "memory");
- if (val) {
- if (!--stuck) {
- if (shown++ <= 2)
- show_read(str, rw, caller);
- stuck = INIT_STUCK;
- }
- goto runlock_again;
- }
-
- put_cpu();
-}
-
-void _do_write_lock (rwlock_t *rw, char *str)
-{
- unsigned long caller, val;
- int stuck = INIT_STUCK;
- int cpu = get_cpu();
- int shown = 0;
-
- GET_CALLER(caller);
-wlock_again:
- /* Spin while there is another writer. */
- while (((long)rw->lock) < 0) {
- if (!--stuck) {
- if (shown++ <= 2)
- show_write(str, rw, caller);
- stuck = INIT_STUCK;
- }
- membar("#LoadLoad");
- }
-
- /* Try to acuire the write bit. */
- __asm__ __volatile__(
-" mov 1, %%g3\n"
-" sllx %%g3, 63, %%g3\n"
-" ldx [%0], %%g1\n"
-" brlz,pn %%g1, 1f\n"
-" or %%g1, %%g3, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" ba,pt %%xcc, 2f\n"
-" sub %%g1, %%g7, %0\n"
-"1: mov 1, %0\n"
-"2:" : "=r" (val)
- : "0" (&(rw->lock))
- : "g3", "g1", "g7", "memory");
- if (val) {
- /* We couldn't get the write bit. */
- if (!--stuck) {
- if (shown++ <= 2)
- show_write(str, rw, caller);
- stuck = INIT_STUCK;
- }
- goto wlock_again;
- }
- if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
- /* Readers still around, drop the write
- * lock, spin, and try again.
- */
- if (!--stuck) {
- if (shown++ <= 2)
- show_write(str, rw, caller);
- stuck = INIT_STUCK;
- }
- __asm__ __volatile__(
-" mov 1, %%g3\n"
-" sllx %%g3, 63, %%g3\n"
-"1: ldx [%0], %%g1\n"
-" andn %%g1, %%g3, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" cmp %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" bne,pn %%xcc, 1b\n"
-" nop"
- : /* no outputs */
- : "r" (&(rw->lock))
- : "g3", "g1", "g7", "cc", "memory");
- while(rw->lock != 0) {
- if (!--stuck) {
- if (shown++ <= 2)
- show_write(str, rw, caller);
- stuck = INIT_STUCK;
- }
- membar("#LoadLoad");
- }
- goto wlock_again;
- }
-
- /* We have it, say who we are. */
- rw->writer_pc = ((unsigned int)caller);
- rw->writer_cpu = cpu;
- current->thread.smp_lock_count++;
- current->thread.smp_lock_pc = ((unsigned int)caller);
-
- put_cpu();
-}
-
-void _do_write_unlock(rwlock_t *rw)
-{
- unsigned long caller, val;
- int stuck = INIT_STUCK;
- int shown = 0;
-
- GET_CALLER(caller);
-
- /* Drop our identity _first_ */
- rw->writer_pc = 0;
- rw->writer_cpu = NO_PROC_ID;
- current->thread.smp_lock_count--;
-wlock_again:
- __asm__ __volatile__(
-" membar #StoreLoad | #LoadLoad\n"
-" mov 1, %%g3\n"
-" sllx %%g3, 63, %%g3\n"
-" ldx [%0], %%g1\n"
-" andn %%g1, %%g3, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" sub %%g1, %%g7, %0\n"
- : "=r" (val)
- : "0" (&(rw->lock))
- : "g3", "g1", "g7", "memory");
- if (val) {
- if (!--stuck) {
- if (shown++ <= 2)
- show_write("write_unlock", rw, caller);
- stuck = INIT_STUCK;
- }
- goto wlock_again;
- }
-}
-
-int _do_write_trylock (rwlock_t *rw, char *str)
-{
- unsigned long caller, val;
- int cpu = get_cpu();
-
- GET_CALLER(caller);
-
- /* Try to acuire the write bit. */
- __asm__ __volatile__(
-" mov 1, %%g3\n"
-" sllx %%g3, 63, %%g3\n"
-" ldx [%0], %%g1\n"
-" brlz,pn %%g1, 1f\n"
-" or %%g1, %%g3, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" ba,pt %%xcc, 2f\n"
-" sub %%g1, %%g7, %0\n"
-"1: mov 1, %0\n"
-"2:" : "=r" (val)
- : "0" (&(rw->lock))
- : "g3", "g1", "g7", "memory");
-
- if (val) {
- put_cpu();
- return 0;
- }
-
- if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
- /* Readers still around, drop the write
- * lock, return failure.
- */
- __asm__ __volatile__(
-" mov 1, %%g3\n"
-" sllx %%g3, 63, %%g3\n"
-"1: ldx [%0], %%g1\n"
-" andn %%g1, %%g3, %%g7\n"
-" casx [%0], %%g1, %%g7\n"
-" cmp %%g1, %%g7\n"
-" membar #StoreLoad | #StoreStore\n"
-" bne,pn %%xcc, 1b\n"
-" nop"
- : /* no outputs */
- : "r" (&(rw->lock))
- : "g3", "g1", "g7", "cc", "memory");
-
- put_cpu();
-
- return 0;
- }
-
- /* We have it, say who we are. */
- rw->writer_pc = ((unsigned int)caller);
- rw->writer_cpu = cpu;
- current->thread.smp_lock_count++;
- current->thread.smp_lock_pc = ((unsigned int)caller);
-
- put_cpu();
-
- return 1;
-}
-
-#endif /* CONFIG_SMP */
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 52e9375288a9..db1e3310e907 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -18,6 +18,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/kprobes.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -117,8 +118,9 @@ unsigned long __init prom_probe_memory (void)
return tally;
}
-static void unhandled_fault(unsigned long address, struct task_struct *tsk,
- struct pt_regs *regs)
+static void __kprobes unhandled_fault(unsigned long address,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
{
if ((unsigned long) address < PAGE_SIZE) {
printk(KERN_ALERT "Unable to handle kernel NULL "
@@ -304,7 +306,7 @@ cannot_handle:
unhandled_fault (address, current, regs);
}
-asmlinkage void do_sparc64_fault(struct pt_regs *regs)
+asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index 6b31f6117a95..c954d91f01d0 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -116,37 +116,6 @@ static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned
return 0;
}
-int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space)
-{
- int error = 0;
- pgd_t * dir;
- unsigned long beg = from;
- unsigned long end = from + size;
- struct mm_struct *mm = vma->vm_mm;
-
- prot = __pgprot(pg_iobits);
- offset -= from;
- dir = pgd_offset(mm, from);
- flush_cache_range(vma, beg, end);
-
- spin_lock(&mm->page_table_lock);
- while (from < end) {
- pud_t *pud = pud_alloc(mm, dir, from);
- error = -ENOMEM;
- if (!pud)
- break;
- error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
- if (error)
- break;
- from = (from + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- }
- flush_tlb_range(vma, beg, end);
- spin_unlock(&mm->page_table_lock);
-
- return error;
-}
-
int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long pfn, unsigned long size, pgprot_t prot)
{
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 3fbaf342a452..fdb1ebb308c9 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -19,6 +19,7 @@
#include <linux/pagemap.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
+#include <linux/kprobes.h>
#include <asm/head.h>
#include <asm/system.h>
@@ -250,7 +251,7 @@ out:
put_cpu();
}
-void flush_icache_range(unsigned long start, unsigned long end)
+void __kprobes flush_icache_range(unsigned long start, unsigned long end)
{
/* Cheetah has coherent I-cache. */
if (tlb_type == spitfire) {
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 363770893797..b2ee9b53227f 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -10,6 +10,7 @@
#include <asm/page.h>
#include <asm/spitfire.h>
#include <asm/mmu_context.h>
+#include <asm/mmu.h>
#include <asm/pil.h>
#include <asm/head.h>
#include <asm/thread_info.h>
@@ -45,6 +46,8 @@ __flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
nop
nop
nop
+ nop
+ nop
.align 32
.globl __flush_tlb_pending
@@ -73,6 +76,9 @@ __flush_tlb_pending:
retl
wrpr %g7, 0x0, %pstate
nop
+ nop
+ nop
+ nop
.align 32
.globl __flush_tlb_kernel_range
@@ -113,6 +119,7 @@ __spitfire_flush_tlb_mm_slow:
#else
#error unsupported PAGE_SIZE
#endif
+ .section .kprobes.text, "ax"
.align 32
.globl __flush_icache_page
__flush_icache_page: /* %o0 = phys_page */
@@ -195,6 +202,7 @@ dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG
nop
#endif /* DCACHE_ALIASING_POSSIBLE */
+ .previous .text
.align 32
__prefill_dtlb:
rdpr %pstate, %g7
@@ -224,16 +232,8 @@ __update_mmu_cache: /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
or %o5, %o0, %o5
ba,a,pt %xcc, __prefill_itlb
- /* Cheetah specific versions, patched at boot time.
- *
- * This writes of the PRIMARY_CONTEXT register in this file are
- * safe even on Cheetah+ and later wrt. the page size fields.
- * The nucleus page size fields do not matter because we make
- * no data references, and these instructions execute out of a
- * locked I-TLB entry sitting in the fully assosciative I-TLB.
- * This sequence should also never trap.
- */
-__cheetah_flush_tlb_mm: /* 15 insns */
+ /* Cheetah specific versions, patched at boot time. */
+__cheetah_flush_tlb_mm: /* 18 insns */
rdpr %pstate, %g7
andn %g7, PSTATE_IE, %g2
wrpr %g2, 0x0, %pstate
@@ -241,6 +241,9 @@ __cheetah_flush_tlb_mm: /* 15 insns */
mov PRIMARY_CONTEXT, %o2
mov 0x40, %g3
ldxa [%o2] ASI_DMMU, %g2
+ srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o1
+ sllx %o1, CTX_PGSZ1_NUC_SHIFT, %o1
+ or %o0, %o1, %o0 /* Preserve nucleus page size fields */
stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%g3] ASI_DMMU_DEMAP
stxa %g0, [%g3] ASI_IMMU_DEMAP
@@ -250,7 +253,7 @@ __cheetah_flush_tlb_mm: /* 15 insns */
retl
wrpr %g7, 0x0, %pstate
-__cheetah_flush_tlb_pending: /* 23 insns */
+__cheetah_flush_tlb_pending: /* 26 insns */
/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
rdpr %pstate, %g7
sllx %o1, 3, %o1
@@ -259,6 +262,9 @@ __cheetah_flush_tlb_pending: /* 23 insns */
wrpr %g0, 1, %tl
mov PRIMARY_CONTEXT, %o4
ldxa [%o4] ASI_DMMU, %g2
+ srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o3
+ sllx %o3, CTX_PGSZ1_NUC_SHIFT, %o3
+ or %o0, %o3, %o0 /* Preserve nucleus page size fields */
stxa %o0, [%o4] ASI_DMMU
1: sub %o1, (1 << 3), %o1
ldx [%o2 + %o1], %o3
@@ -311,14 +317,14 @@ cheetah_patch_cachetlbops:
sethi %hi(__cheetah_flush_tlb_mm), %o1
or %o1, %lo(__cheetah_flush_tlb_mm), %o1
call cheetah_patch_one
- mov 15, %o2
+ mov 18, %o2
sethi %hi(__flush_tlb_pending), %o0
or %o0, %lo(__flush_tlb_pending), %o0
sethi %hi(__cheetah_flush_tlb_pending), %o1
or %o1, %lo(__cheetah_flush_tlb_pending), %o1
call cheetah_patch_one
- mov 23, %o2
+ mov 26, %o2
#ifdef DCACHE_ALIASING_POSSIBLE
sethi %hi(__flush_dcache_page), %o0
@@ -352,9 +358,12 @@ cheetah_patch_cachetlbops:
.globl xcall_flush_tlb_mm
xcall_flush_tlb_mm:
mov PRIMARY_CONTEXT, %g2
- mov 0x40, %g4
ldxa [%g2] ASI_DMMU, %g3
+ srlx %g3, CTX_PGSZ1_NUC_SHIFT, %g4
+ sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4
+ or %g5, %g4, %g5 /* Preserve nucleus page size fields */
stxa %g5, [%g2] ASI_DMMU
+ mov 0x40, %g4
stxa %g0, [%g4] ASI_DMMU_DEMAP
stxa %g0, [%g4] ASI_IMMU_DEMAP
stxa %g3, [%g2] ASI_DMMU
@@ -366,6 +375,10 @@ xcall_flush_tlb_pending:
sllx %g1, 3, %g1
mov PRIMARY_CONTEXT, %g4
ldxa [%g4] ASI_DMMU, %g2
+ srlx %g2, CTX_PGSZ1_NUC_SHIFT, %g4
+ sllx %g4, CTX_PGSZ1_NUC_SHIFT, %g4
+ or %g5, %g4, %g5
+ mov PRIMARY_CONTEXT, %g4
stxa %g5, [%g4] ASI_DMMU
1: sub %g1, (1 << 3), %g1
ldx [%g7 + %g1], %g5
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index cac0a1cf0050..be0a054e3ed6 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -24,6 +24,7 @@
#include <linux/netdevice.h>
#include <linux/mtio.h>
#include <linux/time.h>
+#include <linux/rcupdate.h>
#include <linux/compat.h>
#include <net/sock.h>
@@ -293,16 +294,18 @@ static struct module_info {
static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
{
struct inode *ino;
+ struct fdtable *fdt;
/* I wonder which of these tests are superfluous... --patrik */
- spin_lock(&current->files->file_lock);
- if (! current->files->fd[fd] ||
- ! current->files->fd[fd]->f_dentry ||
- ! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
+ rcu_read_lock();
+ fdt = files_fdtable(current->files);
+ if (! fdt->fd[fd] ||
+ ! fdt->fd[fd]->f_dentry ||
+ ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
! S_ISSOCK(ino->i_mode)) {
- spin_unlock(&current->files->file_lock);
+ rcu_read_unlock();
return TBADF;
}
- spin_unlock(&current->files->file_lock);
+ rcu_read_unlock();
switch (cmd & 0xff) {
case 109: /* SI_SOCKPARAMS */
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 15b4cfe07557..302efbcba70e 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -737,7 +737,8 @@ MODULE_LICENSE("GPL");
extern u32 tl0_solaris[8];
#define update_ttable(x) \
tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
- __asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3]))
+ wmb(); \
+ __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
#else
#endif
@@ -761,7 +762,8 @@ int init_module(void)
entry64_personality_patch |=
(offsetof(struct task_struct, personality) +
(sizeof(unsigned long) - 1));
- __asm__ __volatile__("membar #StoreStore; flush %0"
+ wmb();
+ __asm__ __volatile__("flush %0"
: : "r" (&entry64_personality_patch));
return 0;
}
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index 022c80f43392..aaad29c35c83 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -143,9 +143,11 @@ static struct T_primsg *timod_mkctl(int size)
static void timod_wake_socket(unsigned int fd)
{
struct socket *sock;
+ struct fdtable *fdt;
SOLD("wakeing socket");
- sock = SOCKET_I(current->files->fd[fd]->f_dentry->d_inode);
+ fdt = files_fdtable(current->files);
+ sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode);
wake_up_interruptible(&sock->wait);
read_lock(&sock->sk->sk_callback_lock);
if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -157,9 +159,11 @@ static void timod_wake_socket(unsigned int fd)
static void timod_queue(unsigned int fd, struct T_primsg *it)
{
struct sol_socket_struct *sock;
+ struct fdtable *fdt;
SOLD("queuing primsg");
- sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
+ fdt = files_fdtable(current->files);
+ sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
it->next = sock->pfirst;
sock->pfirst = it;
if (!sock->plast)
@@ -171,9 +175,11 @@ static void timod_queue(unsigned int fd, struct T_primsg *it)
static void timod_queue_end(unsigned int fd, struct T_primsg *it)
{
struct sol_socket_struct *sock;
+ struct fdtable *fdt;
SOLD("queuing primsg at end");
- sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
+ fdt = files_fdtable(current->files);
+ sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
it->next = NULL;
if (sock->plast)
sock->plast->next = it;
@@ -344,6 +350,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
char *buf;
struct file *filp;
struct inode *ino;
+ struct fdtable *fdt;
struct sol_socket_struct *sock;
mm_segment_t old_fs = get_fs();
long args[6];
@@ -351,7 +358,9 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
(int (*)(int, unsigned long __user *))SYS(socketcall);
int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) =
(int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto);
- filp = current->files->fd[fd];
+
+ fdt = files_fdtable(current->files);
+ filp = fdt->fd[fd];
ino = filp->f_dentry->d_inode;
sock = (struct sol_socket_struct *)filp->private_data;
SOLD("entry");
@@ -620,6 +629,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
int oldflags;
struct file *filp;
struct inode *ino;
+ struct fdtable *fdt;
struct sol_socket_struct *sock;
struct T_unitdata_ind udi;
mm_segment_t old_fs = get_fs();
@@ -632,7 +642,8 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
SOLD("entry");
SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
- filp = current->files->fd[fd];
+ fdt = files_fdtable(current->files);
+ filp = fdt->fd[fd];
ino = filp->f_dentry->d_inode;
sock = (struct sol_socket_struct *)filp->private_data;
SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
@@ -844,12 +855,14 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
int __user *flgptr;
int flags;
int error = -EBADF;
+ struct fdtable *fdt;
SOLD("entry");
lock_kernel();
if(fd >= NR_OPEN) goto out;
- filp = current->files->fd[fd];
+ fdt = files_fdtable(current->files);
+ filp = fdt->fd[fd];
if(!filp) goto out;
ino = filp->f_dentry->d_inode;
@@ -910,12 +923,14 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
struct strbuf ctl, dat;
int flags = (int) arg3;
int error = -EBADF;
+ struct fdtable *fdt;
SOLD("entry");
lock_kernel();
if(fd >= NR_OPEN) goto out;
- filp = current->files->fd[fd];
+ fdt = files_fdtable(current->files);
+ filp = fdt->fd[fd];
if(!filp) goto out;
ino = filp->f_dentry->d_inode;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index f945444df49c..684e1f8b2755 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -73,7 +73,7 @@ config MODE_SKAS
to CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this
option will shrink the UML binary slightly.
-source "arch/um/Kconfig_arch"
+source "arch/um/Kconfig.arch"
source "mm/Kconfig"
config LD_SCRIPT_STATIC
@@ -196,7 +196,7 @@ config HOST_2G_2G
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
- depends on MODE_TT && EXPERIMENTAL
+ depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN)
help
This option enables UML SMP support.
It is NOT related to having a real SMP box. Not directly, at least.
@@ -279,7 +279,7 @@ source "net/Kconfig"
source "drivers/base/Kconfig"
-source "arch/um/Kconfig_char"
+source "arch/um/Kconfig.char"
source "drivers/block/Kconfig"
@@ -287,7 +287,7 @@ config NETDEVICES
bool
default NET
-source "arch/um/Kconfig_net"
+source "arch/um/Kconfig.net"
source "drivers/net/Kconfig"
@@ -311,7 +311,7 @@ config GENERIC_ISA_DMA
depends on SCSI
default y
-source "arch/um/Kconfig_scsi"
+source "arch/um/Kconfig.scsi"
endmenu
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig.char
index 62d87b71179b..62d87b71179b 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig.char
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index bd41e4286d0d..5681a8bd370b 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -2,6 +2,17 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
+config CMDLINE_ON_HOST
+ bool "Show command line arguments on the host in TT mode"
+ depends on MODE_TT
+ default !DEBUG_INFO
+ help
+ This controls whether arguments in guest processes should be shown on
+ the host's ps output.
+ Enabling this option hinders debugging on some recent GDB versions
+ (because GDB gets "confused" when we do an execvp()). So probably you
+ should disable it.
+
config PT_PROXY
bool "Enable ptrace proxy"
depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig.i386
index 27c18a8d9d17..8ad156a00499 100644
--- a/arch/um/Kconfig_i386
+++ b/arch/um/Kconfig.i386
@@ -6,6 +6,10 @@ config 64BIT
bool
default n
+config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
config TOP_ADDR
hex
default 0xc0000000 if !HOST_2G_2G
diff --git a/arch/um/Kconfig_net b/arch/um/Kconfig.net
index fa2ab2dd78b7..14a04ebdeae9 100644
--- a/arch/um/Kconfig_net
+++ b/arch/um/Kconfig.net
@@ -34,7 +34,7 @@ config UML_NET_ETHERTAP
link with the host.
To use this, your host kernel must have support for Ethertap
- devices. Also, if your host kernel is 2.4.x, it must have
+ devices. Also, if your host kernel is 2.4.x, it must have
CONFIG_NETLINK_DEV configured as Y or M.
For more information, see
@@ -43,7 +43,7 @@ config UML_NET_ETHERTAP
networking.
If you'd like to set up an IP network with the host and/or the
- outside world, say Y to this, the Daemon Transport and/or the
+ outside world, say Y to this, the Daemon Transport and/or the
Slip Transport. You'll need at least one of them, but may choose
more than one without conflict. If you don't need UML networking,
say N.
@@ -78,7 +78,7 @@ config UML_NET_SLIP
The Ethertap Transport is preferred over slip because of its
limitations. If you prefer slip, however, say Y here. Otherwise
- choose the Multicast transport (to network multiple UMLs on
+ choose the Multicast transport (to network multiple UMLs on
multiple hosts), Ethertap (to network with the host and the
outside world), and/or the Daemon transport (to network multiple
UMLs on a single host). You may choose more than one without
@@ -138,7 +138,7 @@ config UML_NET_PCAP
depends on UML_NET && EXPERIMENTAL
help
The pcap transport makes a pcap packet stream on the host look
- like an ethernet device inside UML. This is useful for making
+ like an ethernet device inside UML. This is useful for making
UML act as a network monitor for the host. You must have libcap
installed in order to build the pcap transport into UML.
@@ -169,11 +169,11 @@ config UML_NET_SLIRP
setup string. The effect of this transport on the UML is similar
that of a host behind a firewall that masquerades all network
connections passing through it (but is less secure).
-
+
To use this you should first have slirp compiled somewhere
accessible on the host, and have read its documentation. If you
don't need UML networking, say N.
-
+
Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
endmenu
diff --git a/arch/um/Kconfig_scsi b/arch/um/Kconfig.scsi
index c291c942b1a8..c291c942b1a8 100644
--- a/arch/um/Kconfig_scsi
+++ b/arch/um/Kconfig.scsi
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig.x86_64
index 735a047c890c..bd35e59419c8 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig.x86_64
@@ -6,6 +6,10 @@ config 64BIT
bool
default y
+config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
config TOP_ADDR
hex
default 0x80000000
@@ -33,3 +37,7 @@ config ARCH_HAS_SC_SIGNALS
config ARCH_REUSE_HOST_VSYSCALL_AREA
bool
default n
+
+config SMP_BROKEN
+ bool
+ default y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f5a83a72aa75..ce987266dac6 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -56,6 +56,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap
+AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
@@ -101,13 +102,12 @@ define archhelp
endef
ifneq ($(KBUILD_SRC),)
-$(shell mkdir -p $(ARCH_DIR) && ln -fsn $(srctree)/$(ARCH_DIR)/Kconfig_$(SUBARCH) $(ARCH_DIR)/Kconfig_arch)
-CLEAN_FILES += $(ARCH_DIR)/Kconfig_arch
+$(shell mkdir -p $(ARCH_DIR) && ln -fsn $(srctree)/$(ARCH_DIR)/Kconfig.$(SUBARCH) $(ARCH_DIR)/Kconfig.arch)
else
-$(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch)
+$(shell cd $(ARCH_DIR) && ln -sf Kconfig.$(SUBARCH) Kconfig.arch)
endif
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
+archprepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -143,14 +143,14 @@ endef
#TT or skas makefiles and don't clean skas_ptregs.h.
CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
$(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \
- $(ARCH_DIR)/include/user_constants.h
+ $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/Kconfig.arch
MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
- $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os \
- $(ARCH_DIR)/Kconfig_arch
+ $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
archclean:
$(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util
+ $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/os-$(OS)/util
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
@@ -196,6 +196,22 @@ define filechk_umlconfig
sed 's/ CONFIG/ UML_CONFIG/'
endef
+define filechk_gen-asm-offsets
+ (set -e; \
+ echo "#ifndef __ASM_OFFSETS_H__"; \
+ echo "#define __ASM_OFFSETS_H__"; \
+ echo "/*"; \
+ echo " * DO NOT MODIFY."; \
+ echo " *"; \
+ echo " * This file was generated by arch/$(ARCH)/Makefile"; \
+ echo " *"; \
+ echo " */"; \
+ echo ""; \
+ sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
+ echo ""; \
+ echo "#endif" )
+endef
+
$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
$(call filechk,umlconfig)
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index a777e57dbf89..1ab431a53ac3 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -27,7 +27,7 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
endif
endif
-CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS)
+CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
ifneq ($(CONFIG_GPROF),y)
ARCH_CFLAGS += -DUM_FASTCALL
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index aa2f7174ebca..436abbba409b 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -6,8 +6,9 @@ START := 0x60000000
#We #undef __x86_64__ for kernelspace, not for userspace where
#it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin $(STUB_CFLAGS)
+CFLAGS += -U__$(SUBARCH)__ -fno-builtin
USER_CFLAGS += -fno-builtin
+CHECKFLAGS += -m64
ELF_ARCH := i386:x86-64
ELF_FORMAT := elf64-x86-64
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index de17d4c6e02d..783e18cae090 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o
net-objs := net_kern.o net_user.o
mconsole-objs := mconsole_kern.o mconsole_user.o
hostaudio-objs := hostaudio_kern.o
-ubd-objs := ubd_kern.o ubd_user.o
+ubd-objs := ubd_kern.o
port-objs := port_kern.o port_user.o
harddog-objs := harddog_kern.o harddog_user.o
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 5d3768156c92..de3bce71aeb3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -63,7 +63,7 @@ error:
*
* SIGWINCH can't be received synchronously, so you have to set up to receive it
* as a signal. That being the case, if you are going to wait for it, it is
- * convenient to sit in a pause() and wait for the signal to bounce you out of
+ * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
* it (see below for how we make sure to exit only on SIGWINCH).
*/
@@ -94,18 +94,19 @@ static int winch_thread(void *arg)
"byte, err = %d\n", -count);
/* We are not using SIG_IGN on purpose, so don't fix it as I thought to
- * do! If using SIG_IGN, the pause() call below would not stop on
+ * do! If using SIG_IGN, the sigsuspend() call below would not stop on
* SIGWINCH. */
signal(SIGWINCH, winch_handler);
sigfillset(&sigs);
- sigdelset(&sigs, SIGWINCH);
- /* Block anything else than SIGWINCH. */
+ /* Block all signals possible. */
if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){
printk("winch_thread : sigprocmask failed, errno = %d\n",
errno);
exit(1);
}
+ /* In sigsuspend(), block anything else than SIGWINCH. */
+ sigdelset(&sigs, SIGWINCH);
if(setsid() < 0){
printk("winch_thread : setsid failed, errno = %d\n", errno);
@@ -130,7 +131,7 @@ static int winch_thread(void *arg)
while(1){
/* This will be interrupted by SIGWINCH only, since other signals
* are blocked.*/
- pause();
+ sigsuspend(&sigs);
count = os_write_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index a37a5ac13c22..022f67bb6873 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -9,19 +9,11 @@
*
*/
-#include <linux/types.h>
-#include <linux/kdev_t.h>
-#include <linux/time.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
#include "mem_user.h"
#include "user_util.h"
@@ -31,35 +23,22 @@ static unsigned long p_buf = 0;
static char *v_buf = NULL;
static ssize_t
-mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- if(*ppos > mmapper_size)
- return -EINVAL;
-
- if(count + *ppos > mmapper_size)
- count = count + *ppos - mmapper_size;
-
- if(count < 0)
- return -EINVAL;
-
- copy_to_user(buf,&v_buf[*ppos],count);
-
- return count;
+ return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size);
}
static ssize_t
-mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- if(*ppos > mmapper_size)
+ if (*ppos > mmapper_size)
return -EINVAL;
- if(count + *ppos > mmapper_size)
- count = count + *ppos - mmapper_size;
-
- if(count < 0)
- return -EINVAL;
+ if (count > mmapper_size - *ppos)
+ count = mmapper_size - *ppos;
- copy_from_user(&v_buf[*ppos],buf,count);
+ if (copy_from_user(&v_buf[*ppos], buf, count))
+ return -EFAULT;
return count;
}
@@ -77,7 +56,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma)
int ret = -EINVAL;
int size;
- lock_kernel();
if (vma->vm_pgoff != 0)
goto out;
@@ -92,7 +70,6 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma)
goto out;
ret = 0;
out:
- unlock_kernel();
return ret;
}
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 344b24d09a7c..e77a38da4350 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -35,6 +35,7 @@
#include "linux/blkpg.h"
#include "linux/genhd.h"
#include "linux/spinlock.h"
+#include "asm/atomic.h"
#include "asm/segment.h"
#include "asm/uaccess.h"
#include "asm/irq.h"
@@ -53,20 +54,21 @@
#include "mem.h"
#include "mem_kern.h"
#include "cow.h"
+#include "aio.h"
enum ubd_req { UBD_READ, UBD_WRITE };
struct io_thread_req {
- enum ubd_req op;
+ enum aio_type op;
int fds[2];
unsigned long offsets[2];
unsigned long long offset;
unsigned long length;
char *buffer;
int sectorsize;
- unsigned long sector_mask;
- unsigned long long cow_offset;
- unsigned long bitmap_words[2];
+ int bitmap_offset;
+ long bitmap_start;
+ long bitmap_end;
int error;
};
@@ -80,28 +82,31 @@ extern int create_cow_file(char *cow_file, char *backing_file,
unsigned long *bitmap_len_out,
int *data_offset_out);
extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
-extern void do_io(struct io_thread_req *req);
+extern void do_io(struct io_thread_req *req, struct request *r,
+ unsigned long *bitmap);
-static inline int ubd_test_bit(__u64 bit, unsigned char *data)
+static inline int ubd_test_bit(__u64 bit, void *data)
{
+ unsigned char *buffer = data;
__u64 n;
int bits, off;
- bits = sizeof(data[0]) * 8;
+ bits = sizeof(buffer[0]) * 8;
n = bit / bits;
off = bit % bits;
- return((data[n] & (1 << off)) != 0);
+ return((buffer[n] & (1 << off)) != 0);
}
-static inline void ubd_set_bit(__u64 bit, unsigned char *data)
+static inline void ubd_set_bit(__u64 bit, void *data)
{
+ unsigned char *buffer = data;
__u64 n;
int bits, off;
- bits = sizeof(data[0]) * 8;
+ bits = sizeof(buffer[0]) * 8;
n = bit / bits;
off = bit % bits;
- data[n] |= (1 << off);
+ buffer[n] |= (1 << off);
}
/*End stuff from ubd_user.h*/
@@ -110,8 +115,6 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
static DEFINE_SPINLOCK(ubd_io_lock);
static DEFINE_SPINLOCK(ubd_lock);
-static void (*do_ubd)(void);
-
static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_release(struct inode * inode, struct file * file);
static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -158,6 +161,8 @@ struct cow {
int data_offset;
};
+#define MAX_SG 64
+
struct ubd {
char *file;
int count;
@@ -168,6 +173,7 @@ struct ubd {
int no_cow;
struct cow cow;
struct platform_device pdev;
+ struct scatterlist sg[MAX_SG];
};
#define DEFAULT_COW { \
@@ -460,80 +466,113 @@ __uml_help(fakehd,
);
static void do_ubd_request(request_queue_t * q);
-
-/* Only changed by ubd_init, which is an initcall. */
-int thread_fd = -1;
+static int in_ubd;
/* Changed by ubd_handler, which is serialized because interrupts only
* happen on CPU 0.
*/
int intr_count = 0;
-/* call ubd_finish if you need to serialize */
-static void __ubd_finish(struct request *req, int error)
+static void ubd_end_request(struct request *req, int bytes, int uptodate)
{
- int nsect;
-
- if(error){
- end_request(req, 0);
- return;
+ if (!end_that_request_first(req, uptodate, bytes >> 9)) {
+ add_disk_randomness(req->rq_disk);
+ end_that_request_last(req);
}
- nsect = req->current_nr_sectors;
- req->sector += nsect;
- req->buffer += nsect << 9;
- req->errors = 0;
- req->nr_sectors -= nsect;
- req->current_nr_sectors = 0;
- end_request(req, 1);
}
-static inline void ubd_finish(struct request *req, int error)
+/* call ubd_finish if you need to serialize */
+static void __ubd_finish(struct request *req, int bytes)
{
- spin_lock(&ubd_io_lock);
- __ubd_finish(req, error);
- spin_unlock(&ubd_io_lock);
+ if(bytes < 0){
+ ubd_end_request(req, 0, 0);
+ return;
+ }
+
+ ubd_end_request(req, bytes, 1);
}
-/* Called without ubd_io_lock held */
-static void ubd_handler(void)
+static inline void ubd_finish(struct request *req, int bytes)
{
- struct io_thread_req req;
- struct request *rq = elv_next_request(ubd_queue);
- int n;
-
- do_ubd = NULL;
- intr_count++;
- n = os_read_file(thread_fd, &req, sizeof(req));
- if(n != sizeof(req)){
- printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
- "err = %d\n", os_getpid(), -n);
- spin_lock(&ubd_io_lock);
- end_request(rq, 0);
- spin_unlock(&ubd_io_lock);
- return;
- }
-
- ubd_finish(rq, req.error);
- reactivate_fd(thread_fd, UBD_IRQ);
- do_ubd_request(ubd_queue);
+ spin_lock(&ubd_io_lock);
+ __ubd_finish(req, bytes);
+ spin_unlock(&ubd_io_lock);
}
+struct bitmap_io {
+ atomic_t count;
+ struct aio_context aio;
+};
+
+struct ubd_aio {
+ struct aio_context aio;
+ struct request *req;
+ int len;
+ struct bitmap_io *bitmap;
+ void *bitmap_buf;
+};
+
+static int ubd_reply_fd = -1;
+
static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
{
- ubd_handler();
- return(IRQ_HANDLED);
-}
+ struct aio_thread_reply reply;
+ struct ubd_aio *aio;
+ struct request *req;
+ int err, n, fd = (int) (long) dev;
+
+ while(1){
+ err = os_read_file(fd, &reply, sizeof(reply));
+ if(err == -EAGAIN)
+ break;
+ if(err < 0){
+ printk("ubd_aio_handler - read returned err %d\n",
+ -err);
+ break;
+ }
-/* Only changed by ubd_init, which is an initcall. */
-static int io_pid = -1;
+ aio = container_of(reply.data, struct ubd_aio, aio);
+ n = reply.err;
-void kill_io_thread(void)
-{
- if(io_pid != -1)
- os_kill_process(io_pid, 1);
-}
+ if(n == 0){
+ req = aio->req;
+ req->nr_sectors -= aio->len >> 9;
+
+ if((aio->bitmap != NULL) &&
+ (atomic_dec_and_test(&aio->bitmap->count))){
+ aio->aio = aio->bitmap->aio;
+ aio->len = 0;
+ kfree(aio->bitmap);
+ aio->bitmap = NULL;
+ submit_aio(&aio->aio);
+ }
+ else {
+ if((req->nr_sectors == 0) &&
+ (aio->bitmap == NULL)){
+ int len = req->hard_nr_sectors << 9;
+ ubd_finish(req, len);
+ }
+
+ if(aio->bitmap_buf != NULL)
+ kfree(aio->bitmap_buf);
+ kfree(aio);
+ }
+ }
+ else if(n < 0){
+ ubd_finish(aio->req, n);
+ if(aio->bitmap != NULL)
+ kfree(aio->bitmap);
+ if(aio->bitmap_buf != NULL)
+ kfree(aio->bitmap_buf);
+ kfree(aio);
+ }
+ }
+ reactivate_fd(fd, UBD_IRQ);
-__uml_exitcall(kill_io_thread);
+ do_ubd_request(ubd_queue);
+
+ return(IRQ_HANDLED);
+}
static int ubd_file_size(struct ubd *dev, __u64 *size_out)
{
@@ -569,7 +608,7 @@ static int ubd_open_dev(struct ubd *dev)
&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_len,
@@ -668,21 +707,22 @@ static int ubd_add(int n)
struct ubd *dev = &ubd_dev[n];
int err;
+ err = -ENODEV;
if(dev->file == NULL)
- return(-ENODEV);
+ goto out;
if (ubd_open_dev(dev))
- return(-ENODEV);
+ goto out;
err = ubd_file_size(dev, &dev->size);
if(err < 0)
- return(err);
+ goto out_close;
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
if(err)
- return(err);
+ goto out_close;
if(fake_major != MAJOR_NR)
ubd_new_disk(fake_major, dev->size, n,
@@ -693,8 +733,11 @@ static int ubd_add(int n)
if (fake_ide)
make_ide_entries(ubd_gendisk[n]->disk_name);
+ err = 0;
+out_close:
ubd_close(dev);
- return 0;
+out:
+ return err;
}
static int ubd_config(char *str)
@@ -827,6 +870,10 @@ int ubd_init(void)
{
int i;
+ ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr);
+ if(ubd_reply_fd < 0)
+ printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd);
+
devfs_mk_dir("ubd");
if (register_blkdev(MAJOR_NR, "ubd"))
return -1;
@@ -837,6 +884,7 @@ int ubd_init(void)
return -1;
}
+ blk_queue_max_hw_segments(ubd_queue, MAX_SG);
if (fake_major != MAJOR_NR) {
char name[sizeof("ubd_nnn\0")];
@@ -848,40 +896,12 @@ int ubd_init(void)
driver_register(&ubd_driver);
for (i = 0; i < MAX_DEV; i++)
ubd_add(i);
+
return 0;
}
late_initcall(ubd_init);
-int ubd_driver_init(void){
- unsigned long stack;
- int err;
-
- /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
- if(global_openflags.s){
- printk(KERN_INFO "ubd: Synchronous mode\n");
- /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
- * enough. So use anyway the io thread. */
- }
- stack = alloc_stack(0, 0);
- io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
- &thread_fd);
- if(io_pid < 0){
- 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,
- SA_INTERRUPT, "ubd", ubd_dev);
- if(err != 0)
- printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
- return(err);
-}
-
-device_initcall(ubd_driver_init);
-
static int ubd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
@@ -919,105 +939,55 @@ static int ubd_release(struct inode * inode, struct file * file)
return(0);
}
-static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
- __u64 *cow_offset, unsigned long *bitmap,
- __u64 bitmap_offset, unsigned long *bitmap_words,
- __u64 bitmap_len)
+static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap)
{
- __u64 sector = io_offset >> 9;
- int i, update_bitmap = 0;
-
- for(i = 0; i < length >> 9; i++){
- if(cow_mask != NULL)
- ubd_set_bit(i, (unsigned char *) cow_mask);
- if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
- continue;
-
- update_bitmap = 1;
- ubd_set_bit(sector + i, (unsigned char *) bitmap);
- }
-
- if(!update_bitmap)
- return;
-
- *cow_offset = sector / (sizeof(unsigned long) * 8);
-
- /* This takes care of the case where we're exactly at the end of the
- * device, and *cow_offset + 1 is off the end. So, just back it up
- * by one word. Thanks to Lynn Kerby for the fix and James McMechan
- * for the original diagnosis.
- */
- if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
- sizeof(unsigned long) - 1))
- (*cow_offset)--;
-
- bitmap_words[0] = bitmap[*cow_offset];
- bitmap_words[1] = bitmap[*cow_offset + 1];
-
- *cow_offset *= sizeof(unsigned long);
- *cow_offset += bitmap_offset;
-}
+ __u64 sector = req->offset / req->sectorsize;
+ int i;
-static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
- __u64 bitmap_offset, __u64 bitmap_len)
-{
- __u64 sector = req->offset >> 9;
- int i;
+ for(i = 0; i < req->length / req->sectorsize; i++){
+ if(ubd_test_bit(sector + i, bitmap))
+ continue;
- if(req->length > (sizeof(req->sector_mask) * 8) << 9)
- panic("Operation too long");
+ if(req->bitmap_start == -1)
+ req->bitmap_start = sector + i;
+ req->bitmap_end = sector + i + 1;
- 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 *)
- &req->sector_mask);
- }
- }
- else cowify_bitmap(req->offset, req->length, &req->sector_mask,
- &req->cow_offset, bitmap, bitmap_offset,
- req->bitmap_words, bitmap_len);
+ ubd_set_bit(sector + i, bitmap);
+ }
}
/* Called with ubd_io_lock held */
-static int prepare_request(struct request *req, struct io_thread_req *io_req)
+static int prepare_request(struct request *req, struct io_thread_req *io_req,
+ unsigned long long offset, int page_offset,
+ int len, struct page *page)
{
struct gendisk *disk = req->rq_disk;
struct ubd *dev = disk->private_data;
- __u64 offset;
- int len;
-
- if(req->rq_status == RQ_INACTIVE) return(1);
/* This should be impossible now */
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
- end_request(req, 0);
+ ubd_end_request(req, 0, 0);
return(1);
}
- offset = ((__u64) req->sector) << 9;
- len = req->current_nr_sectors << 9;
-
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
io_req->fds[1] = dev->fd;
- io_req->cow_offset = -1;
io_req->offset = offset;
io_req->length = len;
io_req->error = 0;
- io_req->sector_mask = 0;
-
- io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
+ io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
- io_req->buffer = req->buffer;
+ io_req->buffer = page_address(page) + page_offset;
io_req->sectorsize = 1 << 9;
+ io_req->bitmap_offset = dev->cow.bitmap_offset;
+ io_req->bitmap_start = -1;
+ io_req->bitmap_end = -1;
- if(dev->cow.file != NULL)
- cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
- dev->cow.bitmap_len);
-
+ if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE))
+ cowify_bitmap(io_req, dev->cow.bitmap);
return(0);
}
@@ -1026,30 +996,36 @@ static void do_ubd_request(request_queue_t *q)
{
struct io_thread_req io_req;
struct request *req;
- int err, n;
-
- if(thread_fd == -1){
- while((req = elv_next_request(q)) != NULL){
- err = prepare_request(req, &io_req);
- if(!err){
- do_io(&io_req);
- __ubd_finish(req, io_req.error);
- }
- }
- }
- else {
- if(do_ubd || (req = elv_next_request(q)) == NULL)
- return;
- err = prepare_request(req, &io_req);
- if(!err){
- do_ubd = ubd_handler;
- n = os_write_file(thread_fd, (char *) &io_req,
- sizeof(io_req));
- if(n != sizeof(io_req))
- printk("write to io thread failed, "
- "errno = %d\n", -n);
+ __u64 sector;
+ int err;
+
+ if(in_ubd)
+ return;
+ in_ubd = 1;
+ while((req = elv_next_request(q)) != NULL){
+ struct gendisk *disk = req->rq_disk;
+ struct ubd *dev = disk->private_data;
+ int n, i;
+
+ blkdev_dequeue_request(req);
+
+ sector = req->sector;
+ n = blk_rq_map_sg(q, req, dev->sg);
+
+ for(i = 0; i < n; i++){
+ struct scatterlist *sg = &dev->sg[i];
+
+ err = prepare_request(req, &io_req, sector << 9,
+ sg->offset, sg->length,
+ sg->page);
+ if(err)
+ continue;
+
+ sector += sg->length >> 9;
+ do_io(&io_req, req, dev->cow.bitmap);
}
}
+ in_ubd = 0;
}
static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -1265,131 +1241,95 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
return(err);
}
-static int update_bitmap(struct io_thread_req *req)
-{
- int n;
-
- if(req->cow_offset == -1)
- return(0);
-
- n = os_seek_file(req->fds[1], req->cow_offset);
- if(n < 0){
- printk("do_io - bitmap lseek failed : err = %d\n", -n);
- return(1);
- }
-
- n = os_write_file(req->fds[1], &req->bitmap_words,
- sizeof(req->bitmap_words));
- if(n != sizeof(req->bitmap_words)){
- printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
- req->fds[1]);
- return(1);
- }
-
- return(0);
-}
-
-void do_io(struct io_thread_req *req)
+void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap)
{
- char *buf;
- unsigned long len;
- int n, nsectors, start, end, bit;
- int err;
- __u64 off;
-
- nsectors = req->length / req->sectorsize;
- start = 0;
- do {
- bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
- end = start;
- while((end < nsectors) &&
- (ubd_test_bit(end, (unsigned char *)
- &req->sector_mask) == bit))
- end++;
-
- off = req->offset + req->offsets[bit] +
- start * req->sectorsize;
- len = (end - start) * req->sectorsize;
- buf = &req->buffer[start * req->sectorsize];
-
- err = os_seek_file(req->fds[bit], off);
- if(err < 0){
- printk("do_io - lseek failed : err = %d\n", -err);
- req->error = 1;
- return;
- }
- if(req->op == UBD_READ){
- n = 0;
- do {
- buf = &buf[n];
- len -= n;
- n = os_read_file(req->fds[bit], buf, len);
- if (n < 0) {
- printk("do_io - read failed, err = %d "
- "fd = %d\n", -n, req->fds[bit]);
- req->error = 1;
- return;
- }
- } while((n < len) && (n != 0));
- if (n < len) memset(&buf[n], 0, len - n);
- } else {
- n = os_write_file(req->fds[bit], buf, len);
- if(n != len){
- printk("do_io - write failed err = %d "
- "fd = %d\n", -n, req->fds[bit]);
- req->error = 1;
- return;
- }
- }
+ struct ubd_aio *aio;
+ struct bitmap_io *bitmap_io = NULL;
+ char *buf;
+ void *bitmap_buf = NULL;
+ unsigned long len, sector;
+ int nsectors, start, end, bit, err;
+ __u64 off;
+
+ if(req->bitmap_start != -1){
+ /* Round up to the nearest word */
+ int round = sizeof(unsigned long);
+ len = (req->bitmap_end - req->bitmap_start +
+ round * 8 - 1) / (round * 8);
+ len *= round;
+
+ off = req->bitmap_start / (8 * round);
+ off *= round;
+
+ bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL);
+ if(bitmap_io == NULL){
+ printk("Failed to kmalloc bitmap IO\n");
+ req->error = 1;
+ return;
+ }
- start = end;
- } while(start < nsectors);
+ bitmap_buf = kmalloc(len, GFP_KERNEL);
+ if(bitmap_buf == NULL){
+ printk("do_io : kmalloc of bitmap chunk "
+ "failed\n");
+ kfree(bitmap_io);
+ req->error = 1;
+ return;
+ }
+ memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len);
+
+ *bitmap_io = ((struct bitmap_io)
+ { .count = ATOMIC_INIT(0),
+ .aio = INIT_AIO(AIO_WRITE, req->fds[1],
+ bitmap_buf, len,
+ req->bitmap_offset + off,
+ ubd_reply_fd) } );
+ }
- req->error = update_bitmap(req);
-}
+ nsectors = req->length / req->sectorsize;
+ start = 0;
+ end = nsectors;
+ bit = 0;
+ do {
+ if(bitmap != NULL){
+ sector = req->offset / req->sectorsize;
+ bit = ubd_test_bit(sector + start, bitmap);
+ end = start;
+ while((end < nsectors) &&
+ (ubd_test_bit(sector + end, bitmap) == bit))
+ end++;
+ }
-/* Changed in start_io_thread, which is serialized by being called only
- * from ubd_init, which is an initcall.
- */
-int kernel_fd = -1;
+ off = req->offsets[bit] + req->offset +
+ start * req->sectorsize;
+ len = (end - start) * req->sectorsize;
+ buf = &req->buffer[start * req->sectorsize];
-/* Only changed by the io thread */
-int io_count = 0;
+ aio = kmalloc(sizeof(*aio), GFP_KERNEL);
+ if(aio == NULL){
+ req->error = 1;
+ return;
+ }
-int io_thread(void *arg)
-{
- struct io_thread_req req;
- int n;
+ *aio = ((struct ubd_aio)
+ { .aio = INIT_AIO(req->op, req->fds[bit], buf,
+ len, off, ubd_reply_fd),
+ .len = len,
+ .req = r,
+ .bitmap = bitmap_io,
+ .bitmap_buf = bitmap_buf });
+
+ if(aio->bitmap != NULL)
+ atomic_inc(&aio->bitmap->count);
+
+ err = submit_aio(&aio->aio);
+ if(err){
+ printk("do_io - submit_aio failed, "
+ "err = %d\n", err);
+ req->error = 1;
+ return;
+ }
- ignore_sigwinch_sig();
- while(1){
- n = os_read_file(kernel_fd, &req, sizeof(req));
- if(n != sizeof(req)){
- if(n < 0)
- printk("io_thread - read failed, fd = %d, "
- "err = %d\n", kernel_fd, -n);
- else {
- printk("io_thread - short read, fd = %d, "
- "length = %d\n", kernel_fd, n);
- }
- continue;
- }
- io_count++;
- do_io(&req);
- n = os_write_file(kernel_fd, &req, sizeof(req));
- if(n != sizeof(req))
- printk("io_thread - write failed, fd = %d, err = %d\n",
- kernel_fd, -n);
- }
+ start = end;
+ } while(start < nsectors);
}
-
-/*
- * 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/aio.h b/arch/um/include/aio.h
new file mode 100644
index 000000000000..83f16877ab08
--- /dev/null
+++ b/arch/um/include/aio.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef AIO_H__
+#define AIO_H__
+
+enum aio_type { AIO_READ, AIO_WRITE, AIO_MMAP };
+
+struct aio_thread_reply {
+ void *data;
+ int err;
+};
+
+struct aio_context {
+ enum aio_type type;
+ int fd;
+ void *data;
+ int len;
+ unsigned long long offset;
+ int reply_fd;
+ struct aio_context *next;
+};
+
+#define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \
+ aio_reply_fd) \
+ { .type = aio_type, \
+ .fd = aio_fd, \
+ .data = aio_data, \
+ .len = aio_len, \
+ .offset = aio_offset, \
+ .reply_fd = aio_reply_fd }
+
+#define INIT_AIO_CONTEXT { .reply_fd = -1, \
+ .next = NULL }
+
+extern int submit_aio(struct aio_context *aio);
+
+#endif
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index d705daa2d854..0aa620970adb 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -12,3 +12,4 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
DEFINE_STR(UM_KERN_INFO, KERN_INFO);
DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+DEFINE(HOST_ELF_CLASS, ELF_CLASS);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index 55c2693f8778..cbd79a8d213d 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -111,7 +111,15 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
#ifndef __KERNEL__
-#define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn
+#define __define_initcall(level,fn) \
+ static initcall_t __initcall_##fn __attribute_used__ \
+ __attribute__((__section__(".initcall" level ".init"))) = fn
+
+/* Userspace initcalls shouldn't depend on anything in the kernel, so we'll
+ * make them run first.
+ */
+#define __initcall(fn) __define_initcall("1", fn)
+
#define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn
#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
index 3af52a634c4c..c222d56b1494 100644
--- a/arch/um/include/irq_kern.h
+++ b/arch/um/include/irq_kern.h
@@ -7,12 +7,15 @@
#define __IRQ_KERN_H__
#include "linux/interrupt.h"
+#include "asm/ptrace.h"
extern int um_request_irq(unsigned int irq, int fd, int type,
irqreturn_t (*handler)(int, void *,
struct pt_regs *),
unsigned long irqflags, const char * devname,
void *dev_id);
+extern int init_aio_irq(int irq, char *name,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *));
#endif
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h
index 99d3ad4a03e5..e8ff0d8fa610 100644
--- a/arch/um/include/mem.h
+++ b/arch/um/include/mem.h
@@ -13,7 +13,17 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
extern int is_remapped(void *virt);
extern int physmem_remove_mapping(void *virt);
extern void physmem_forget_descriptor(int fd);
-extern unsigned long to_phys(void *virt);
+
+extern unsigned long uml_physmem;
+static inline unsigned long to_phys(void *virt)
+{
+ return(((unsigned long) virt) - uml_physmem);
+}
+
+static inline void *to_virt(unsigned long phys)
+{
+ return((void *) uml_physmem + phys);
+}
#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 881d2988d2d8..4c362458052c 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -153,6 +153,11 @@ 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);
+/* start_up.c */
+extern void os_early_checks(void);
+extern int can_do_skas(void);
+
+/* process.c */
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_stop_process(int pid);
@@ -161,6 +166,9 @@ extern void os_kill_ptraced_process(int pid, int reap_child);
extern void os_usr1_process(int pid);
extern int os_getpid(void);
extern int os_getpgrp(void);
+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+extern void init_new_thread_signals(int altstack);
+extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
extern int os_map_memory(void *virt, int fd, unsigned long long off,
unsigned long len, int r, int w, int x);
@@ -170,6 +178,13 @@ extern int os_unmap_memory(void *addr, int len);
extern void os_flush_stdout(void);
extern unsigned long long os_usecs(void);
+/* tt.c
+ * for tt mode only (will be deleted in future...)
+ */
+extern void forward_pending_sigio(int target);
+extern int start_fork_tramp(void *arg, unsigned long temp_stack,
+ int clone_flags, int (*tramp)(void *));
+
#endif
/*
diff --git a/arch/um/include/syscall.h b/arch/um/include/syscall.h
new file mode 100644
index 000000000000..dda1df901a08
--- /dev/null
+++ b/arch/um/include/syscall.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSCALL_USER_H
+#define __SYSCALL_USER_H
+
+extern int record_syscall_start(int syscall);
+extern void record_syscall_end(int index, long result);
+
+#endif
diff --git a/arch/um/include/syscall_user.h b/arch/um/include/syscall_user.h
deleted file mode 100644
index 811d0ec2445e..000000000000
--- a/arch/um/include/syscall_user.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSCALL_USER_H
-#define __SYSCALL_USER_H
-
-extern int record_syscall_start(int syscall);
-extern void record_syscall_end(int index, long result);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index be0a3e3469eb..a0d5b74d3731 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -16,6 +16,8 @@ extern syscall_handler_t sys_rt_sigaction;
extern syscall_handler_t old_mmap_i386;
+extern syscall_handler_t *sys_call_table[];
+
#define EXECUTE_SYSCALL(syscall, regs) \
((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index be8acd5efd97..331aa2d1f3f5 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -227,7 +227,7 @@ struct syscall_args {
panic("Bad register in UPT_SET : %d\n", reg); \
break; \
} \
- val; \
+ __upt_val; \
})
#define UPT_SET_SYSCALL_RETURN(r, res) \
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index 67923cca5691..e06f83e80f4a 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -14,6 +14,8 @@ typedef long syscall_handler_t(void);
extern syscall_handler_t *ia32_sys_call_table[];
+extern syscall_handler_t *sys_call_table[];
+
#define EXECUTE_SYSCALL(syscall, regs) \
(((long (*)(long, long, long, long, long, long)) \
(*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index c6f9628f39bf..45d7da6c3b2c 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -9,7 +9,7 @@
#include "um_mmu.h"
struct host_vm_op {
- enum { MMAP, MUNMAP, MPROTECT } type;
+ enum { NONE, MMAP, MUNMAP, MPROTECT } type;
union {
struct {
unsigned long addr;
@@ -38,24 +38,10 @@ extern void mprotect_kernel_vm(int w);
extern void force_flush_all(void);
extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force,
- void (*do_ops)(union mm_context *,
- struct host_vm_op *, int));
+ int (*do_ops)(union mm_context *,
+ struct host_vm_op *, int, int,
+ void **));
extern int flush_tlb_kernel_range_common(unsigned long start,
unsigned long end);
-extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x, struct host_vm_op *ops, int index,
- int last_filled, union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *,
- int));
-extern int add_munmap(unsigned long addr, unsigned long len,
- struct host_vm_op *ops, int index, int last_filled,
- union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *,
- int));
-extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
- int x, struct host_vm_op *ops, int index,
- int last_filled, union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *,
- int));
#endif
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 6e348cb6de24..84c0868cd561 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -20,13 +20,6 @@
#define access_ok(type, addr, size) \
CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
- return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
- size));
-}
-
static inline int copy_from_user(void *to, const void __user *from, int n)
{
return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to,
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 7b6a24dfd302..bb505e01d994 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -54,8 +54,6 @@ extern void stack_protections(unsigned long address);
extern void task_protections(unsigned long address);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern void *add_signal_handler(int sig, void (*handler)(int));
-extern int start_fork_tramp(void *arg, unsigned long temp_stack,
- int clone_flags, int (*tramp)(void *));
extern int linux_main(int argc, char **argv);
extern void set_cmdline(char *cmd);
extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
@@ -64,8 +62,6 @@ extern void *um_kmalloc(int size);
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(void);
-extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
-extern void init_new_thread_signals(int altstack);
extern void do_exec(int old_pid, int new_pid);
extern void tracer_panic(char *msg, ...);
extern char *get_umid(int only_if_set);
@@ -74,16 +70,12 @@ 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_ptrace(void);
extern void check_sigio(void);
-extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
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);
extern int arch_fixup(unsigned long address, void *sc_ptr);
-extern void forward_pending_sigio(int target);
-extern int can_do_skas(void);
extern void arch_init_thread(void);
extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern int raw(int fd);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index a8918e80df96..614b8ebeb0ed 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -8,25 +8,24 @@ clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
- physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
- sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
- syscall_kern.o sysrq.o tempfile.o time.o time_kern.o \
- tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
- user_util.o
+ physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
+ sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \
+ tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \
+ uaccess_user.o um_arch.o umid.o user_util.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_user.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 helper.o main.o process.o tempfile.o \
- time.o tty_log.o umid.o user_util.o
+USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \
+ tty_log.o umid.o user_util.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
new file mode 100644
index 000000000000..c13a64a288f6
--- /dev/null
+++ b/arch/um/kernel/asm-offsets.c
@@ -0,0 +1 @@
+/* Dummy file to make kbuild happy - unused! */
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 3942a5f245de..2517ecb8bf27 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -146,37 +146,8 @@ SECTIONS
}
_end = .;
PROVIDE (end = .);
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
+
+ STABS_DEBUG
+
+ DWARF_DEBUG
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 9f18061ef4c9..dcd814971995 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -31,7 +31,7 @@
#include "kern_util.h"
#include "irq_user.h"
#include "irq_kern.h"
-
+#include "os.h"
/*
* Generic, controller-independent functions:
@@ -168,13 +168,32 @@ void __init init_IRQ(void)
}
}
-/*
- * 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:
- */
+int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
+ struct pt_regs *))
+{
+ int fds[2], err;
+
+ err = os_pipe(fds, 1, 1);
+ if(err){
+ printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
+ goto out;
+ }
+
+ err = um_request_irq(irq, fds[0], IRQ_READ, handler,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, name,
+ (void *) (long) fds[0]);
+ if(err){
+ printk("init_aio_irq - : um_request_irq failed, err = %d\n",
+ err);
+ goto out_close;
+ }
+
+ err = fds[1];
+ goto out;
+
+ out_close:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+ out:
+ return(err);
+}
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 99439fa15ef4..a97a72e516aa 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -34,14 +34,9 @@ EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
EXPORT_SYMBOL(get_kmem_end);
-EXPORT_SYMBOL(page_to_phys);
-EXPORT_SYMBOL(phys_to_page);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(um_virt_to_phys);
-EXPORT_SYMBOL(__virt_to_page);
-EXPORT_SYMBOL(to_phys);
-EXPORT_SYMBOL(to_virt);
EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
@@ -114,22 +109,3 @@ extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL(__read_lock_failed);
#endif
-
-#ifdef CONFIG_HIGHMEM
-EXPORT_SYMBOL(kmap);
-EXPORT_SYMBOL(kunmap);
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic);
-EXPORT_SYMBOL(kmap_atomic_to_page);
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index 1e1a87f1c510..d31027f0fe39 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -97,7 +97,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
-#ifdef UML_CONFIG_MODE_TT
+#ifdef UML_CONFIG_CMDLINE_ON_HOST
/* Allocate memory for thread command lines */
if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 5597bd39e6b5..64fa062cc119 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -196,7 +196,7 @@ static void init_highmem(void)
static void __init fixaddr_user_init( void)
{
-#if CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
long size = FIXADDR_USER_END - FIXADDR_USER_START;
pgd_t *pgd;
pud_t *pud;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index a24e3b7f4bf0..ea670fcc8af5 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -248,16 +248,6 @@ unsigned long high_physmem;
extern unsigned long physmem_size;
-void *to_virt(unsigned long phys)
-{
- return((void *) uml_physmem + phys);
-}
-
-unsigned long to_phys(void *virt)
-{
- return(((unsigned long) virt) - uml_physmem);
-}
-
int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
{
struct page *p, *map;
@@ -298,31 +288,6 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
return(0);
}
-struct page *phys_to_page(const unsigned long phys)
-{
- return(&mem_map[phys >> PAGE_SHIFT]);
-}
-
-struct page *__virt_to_page(const unsigned long virt)
-{
- return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
-}
-
-phys_t page_to_phys(struct page *page)
-{
- return((page - mem_map) << PAGE_SHIFT);
-}
-
-pte_t mk_pte(struct page *page, pgprot_t pgprot)
-{
- pte_t pte;
-
- pte_set_val(pte, page_to_phys(page), pgprot);
- if(pte_present(pte))
- pte_mknewprot(pte_mknewpage(pte));
- return(pte);
-}
-
/* Changed during early boot */
static unsigned long kmem_top = 0;
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 7807a3e8c426..03618bd13d55 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -87,12 +87,12 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
force_sigsegv(signr, current);
- }
- else if(!(ka->sa.sa_flags & SA_NODEFER)){
+ } else {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
- sigaddset(&current->blocked, signr);
+ if(!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index d296d55ade4b..db36c7c95940 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -4,7 +4,7 @@
#
obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
- syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
+ syscall.o tlb.o trap_user.o uaccess.o
subdir- := util
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 278b72f1d9ad..09536f81ee42 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -6,11 +6,15 @@
#ifndef __SKAS_MMU_H
#define __SKAS_MMU_H
+#include "linux/config.h"
#include "mm_id.h"
struct mmu_context_skas {
struct mm_id id;
unsigned long last_page_table;
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ unsigned long last_pmd;
+#endif
};
extern void switch_mm_skas(struct mm_id * mm_idp);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index d983ea842547..060934740f9f 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -24,28 +24,26 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig));
extern void remove_sigstack(void);
extern void new_thread_handler(int sig);
extern void handle_syscall(union uml_pt_regs *regs);
-extern int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
- int r, int w, int x, int phys_fd, unsigned long long offset);
-extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len);
+extern int map(struct mm_id * mm_idp, unsigned long virt,
+ unsigned long len, int r, int w, int x, int phys_fd,
+ unsigned long long offset, int done, void **data);
+extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
+ int done, void **data);
extern int protect(struct mm_id * mm_idp, unsigned long addr,
- unsigned long len, int r, int w, int x);
+ unsigned long len, int r, int w, int x, int done,
+ void **data);
extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
-extern int new_mm(int from);
+extern int new_mm(int from, unsigned long stack);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
extern unsigned long current_stub_stack(void);
+extern long run_syscall_stub(struct mm_id * mm_idp,
+ int syscall, unsigned long *args, long expected,
+ void **addr, int done);
+extern long syscall_stub_data(struct mm_id * mm_idp,
+ unsigned long *data, int data_count,
+ void **addr, void **stub_addr);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index cd6c280482cb..6ee3f3902e68 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/kernel/skas/include/uaccess-skas.h
@@ -18,18 +18,18 @@
((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
-static inline int verify_area_skas(int type, const void * addr,
+static inline int verify_area_skas(int type, const void __user * addr,
unsigned long size)
{
return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
}
-extern int copy_from_user_skas(void *to, const void *from, int n);
-extern int copy_to_user_skas(void *to, const void *from, int n);
-extern int strncpy_from_user_skas(char *dst, const char *src, int count);
-extern int __clear_user_skas(void *mem, int len);
-extern int clear_user_skas(void *mem, int len);
-extern int strnlen_user_skas(const void *str, int len);
+extern int copy_from_user_skas(void *to, const void __user *from, int n);
+extern int copy_to_user_skas(void __user *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
+extern int __clear_user_skas(void __user *mem, int len);
+extern int clear_user_skas(void __user *mem, int len);
+extern int strnlen_user_skas(const void __user *str, int len);
#endif
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
index b0980ff3bd95..1d89640bd502 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/kernel/skas/mem_user.c
@@ -5,13 +5,14 @@
#include <signal.h>
#include <errno.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <asm/page.h>
#include <asm/unistd.h>
#include "mem_user.h"
#include "mem.h"
-#include "mm_id.h"
+#include "skas.h"
#include "user.h"
#include "os.h"
#include "proc_mm.h"
@@ -23,46 +24,155 @@
#include "uml-config.h"
#include "sysdep/ptrace.h"
#include "sysdep/stub.h"
-#include "skas.h"
-extern unsigned long syscall_stub, __syscall_stub_start;
+extern unsigned long batch_syscall_stub, __syscall_stub_start;
extern void wait_stub_done(int pid, int sig, char * fname);
-static long run_syscall_stub(struct mm_id * mm_idp, int syscall,
- unsigned long *args)
+static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
+ unsigned long *stack)
+{
+ if(stack == NULL){
+ stack = (unsigned long *) mm_idp->stack + 2;
+ *stack = 0;
+ }
+ return stack;
+}
+
+extern int proc_mm;
+
+int single_count = 0;
+int multi_count = 0;
+int multi_op_count = 0;
+
+static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
{
+ unsigned long regs[MAX_REG_NR];
+ unsigned long *data;
+ unsigned long *syscall;
+ long ret, offset;
int n, pid = mm_idp->u.pid;
- unsigned long regs[MAX_REG_NR];
+
+ if(proc_mm)
+#warning Need to look up userspace_pid by cpu
+ pid = userspace_pid[0];
+
+ multi_count++;
get_safe_registers(regs);
regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
- ((unsigned long) &syscall_stub -
+ ((unsigned long) &batch_syscall_stub -
(unsigned long) &__syscall_stub_start);
- /* XXX Don't have a define for starting a syscall */
- regs[REGS_SYSCALL_NR] = syscall;
- regs[REGS_SYSCALL_ARG1] = args[0];
- regs[REGS_SYSCALL_ARG2] = args[1];
- regs[REGS_SYSCALL_ARG3] = args[2];
- regs[REGS_SYSCALL_ARG4] = args[3];
- regs[REGS_SYSCALL_ARG5] = args[4];
- regs[REGS_SYSCALL_ARG6] = args[5];
- n = ptrace_setregs(pid, regs);
- if(n < 0){
- printk("run_syscall_stub : PTRACE_SETREGS failed, "
- "errno = %d\n", n);
- return(n);
+ n = ptrace_setregs(pid, regs);
+ if(n < 0)
+ panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
+ n);
+
+ wait_stub_done(pid, 0, "do_syscall_stub");
+
+ /* When the stub stops, we find the following values on the
+ * beginning of the stack:
+ * (long )return_value
+ * (long )offset to failed sycall-data (0, if no error)
+ */
+ ret = *((unsigned long *) mm_idp->stack);
+ offset = *((unsigned long *) mm_idp->stack + 1);
+ if (offset) {
+ data = (unsigned long *)(mm_idp->stack +
+ offset - UML_CONFIG_STUB_DATA);
+ 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",
+ syscall[0], ret, syscall[7]);
+ printk(" syscall parameters: "
+ "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ syscall[1], syscall[2], syscall[3],
+ syscall[4], syscall[5], syscall[6]);
+ for(n = 1; n < data[0]/sizeof(long); n++) {
+ if(n == 1)
+ printk(" additional syscall data:");
+ if(n % 4 == 1)
+ printk("\n ");
+ printk(" 0x%lx", data[n]);
+ }
+ if(n > 1)
+ printk("\n");
+ }
+ else ret = 0;
+
+ *addr = check_init_stack(mm_idp, NULL);
+
+ return ret;
+}
+
+long run_syscall_stub(struct mm_id * mm_idp, int syscall,
+ unsigned long *args, long expected, void **addr,
+ int done)
+{
+ unsigned long *stack = check_init_stack(mm_idp, *addr);
+
+ if(done && *addr == NULL)
+ single_count++;
+
+ *stack += sizeof(long);
+ stack += *stack / sizeof(long);
+
+ *stack++ = syscall;
+ *stack++ = args[0];
+ *stack++ = args[1];
+ *stack++ = args[2];
+ *stack++ = args[3];
+ *stack++ = args[4];
+ *stack++ = args[5];
+ *stack++ = expected;
+ *stack = 0;
+ multi_op_count++;
+
+ if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
+ PAGE_SIZE - 10 * sizeof(long))){
+ *addr = stack;
+ return 0;
}
- wait_stub_done(pid, 0, "run_syscall_stub");
+ return do_syscall_stub(mm_idp, addr);
+}
+
+long syscall_stub_data(struct mm_id * mm_idp,
+ unsigned long *data, int data_count,
+ void **addr, void **stub_addr)
+{
+ unsigned long *stack;
+ int ret = 0;
- return(*((unsigned long *) mm_idp->stack));
+ /* If *addr still is uninitialized, it *must* contain NULL.
+ * Thus in this case do_syscall_stub correctly won't be called.
+ */
+ if((((unsigned long) *addr) & ~PAGE_MASK) >=
+ PAGE_SIZE - (10 + data_count) * sizeof(long)) {
+ ret = do_syscall_stub(mm_idp, addr);
+ /* in case of error, don't overwrite data on stack */
+ if(ret)
+ return ret;
+ }
+
+ stack = check_init_stack(mm_idp, *addr);
+ *addr = stack;
+
+ *stack = data_count * sizeof(long);
+
+ memcpy(stack + 1, data, data_count * sizeof(long));
+
+ *stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
+ UML_CONFIG_STUB_DATA);
+
+ return 0;
}
-int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
- int r, int w, int x, int phys_fd, unsigned long long offset)
+int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
+ int r, int w, int x, int phys_fd, unsigned long long offset,
+ int done, void **data)
{
- int prot, n;
+ int prot, ret;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
@@ -70,6 +180,7 @@ int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
if(proc_mm){
struct proc_mm_op map;
int fd = mm_idp->u.mm_fd;
+
map = ((struct proc_mm_op) { .op = MM_MMAP,
.u =
{ .mmap =
@@ -81,63 +192,61 @@ int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
.fd = phys_fd,
.offset= offset
} } } );
- n = os_write_file(fd, &map, sizeof(map));
- if(n != sizeof(map))
- printk("map : /proc/mm map failed, err = %d\n", -n);
+ ret = os_write_file(fd, &map, sizeof(map));
+ if(ret != sizeof(map))
+ printk("map : /proc/mm map failed, err = %d\n", -ret);
+ else ret = 0;
}
else {
- long res;
unsigned long args[] = { virt, len, prot,
MAP_SHARED | MAP_FIXED, phys_fd,
MMAP_OFFSET(offset) };
- res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args);
- if((void *) res == MAP_FAILED)
- printk("mmap stub failed, errno = %d\n", res);
+ ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
+ data, done);
}
- return 0;
+ return ret;
}
-int unmap(struct mm_id *mm_idp, void *addr, unsigned long len)
+int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
+ void **data)
{
- int n;
+ int ret;
if(proc_mm){
struct proc_mm_op unmap;
int fd = mm_idp->u.mm_fd;
+
unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
.u =
{ .munmap =
{ .addr =
(unsigned long) addr,
.len = len } } } );
- n = os_write_file(fd, &unmap, sizeof(unmap));
- if(n != sizeof(unmap)) {
- if(n < 0)
- return(n);
- else if(n > 0)
- return(-EIO);
- }
+ ret = os_write_file(fd, &unmap, sizeof(unmap));
+ if(ret != sizeof(unmap))
+ printk("unmap - proc_mm write returned %d\n", ret);
+ else ret = 0;
}
else {
- int res;
unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
0 };
- res = run_syscall_stub(mm_idp, __NR_munmap, args);
- if(res < 0)
- printk("munmap stub failed, errno = %d\n", res);
+ ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
+ data, done);
+ if(ret < 0)
+ printk("munmap stub failed, errno = %d\n", ret);
}
- return(0);
+ return ret;
}
-int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
- int r, int w, int x)
+int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
+ int r, int w, int x, int done, void **data)
{
struct proc_mm_op protect;
- int prot, n;
+ int prot, ret;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
@@ -152,20 +261,19 @@ int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
.len = len,
.prot = prot } } } );
- n = os_write_file(fd, &protect, sizeof(protect));
- if(n != sizeof(protect))
- panic("protect failed, err = %d", -n);
+ ret = os_write_file(fd, &protect, sizeof(protect));
+ if(ret != sizeof(protect))
+ printk("protect failed, err = %d", -ret);
+ else ret = 0;
}
else {
- int res;
unsigned long args[] = { addr, len, prot, 0, 0, 0 };
- res = run_syscall_stub(mm_idp, __NR_mprotect, args);
- if(res < 0)
- panic("mprotect stub failed, errno = %d\n", res);
+ ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
+ data, done);
}
- return(0);
+ return ret;
}
void before_mem_skas(unsigned long unused)
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index d232daa42c31..240143b616a2 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -56,6 +56,9 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
*/
mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
+#endif
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkexec(*pte);
@@ -77,23 +80,14 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
struct mm_struct *cur_mm = current->mm;
struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
struct mm_id *mm_id = &mm->context.skas.id;
- unsigned long stack;
- int from, ret;
+ unsigned long stack = 0;
+ int from, ret = -ENOMEM;
- if(proc_mm){
- if((cur_mm != NULL) && (cur_mm != &init_mm))
- from = cur_mm->context.skas.id.u.mm_fd;
- else from = -1;
+ if(!proc_mm || !ptrace_faultinfo){
+ stack = get_zeroed_page(GFP_KERNEL);
+ if(stack == 0)
+ goto out;
- ret = new_mm(from);
- if(ret < 0){
- printk("init_new_context_skas - new_mm failed, "
- "errno = %d\n", ret);
- return ret;
- }
- mm_id->u.mm_fd = ret;
- }
- else {
/* This zeros the entry that pgd_alloc didn't, needed since
* we are about to reinitialize it, and want mm.nr_ptes to
* be accurate.
@@ -103,20 +97,30 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
ret = init_stub_pte(mm, CONFIG_STUB_CODE,
(unsigned long) &__syscall_stub_start);
if(ret)
- goto out;
-
- ret = -ENOMEM;
- stack = get_zeroed_page(GFP_KERNEL);
- if(stack == 0)
- goto out;
- mm_id->stack = stack;
+ goto out_free;
ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
if(ret)
goto out_free;
mm->nr_ptes--;
+ }
+ mm_id->stack = stack;
+ if(proc_mm){
+ if((cur_mm != NULL) && (cur_mm != &init_mm))
+ from = cur_mm_id->u.mm_fd;
+ else from = -1;
+
+ ret = new_mm(from, stack);
+ if(ret < 0){
+ printk("init_new_context_skas - new_mm failed, "
+ "errno = %d\n", ret);
+ goto out_free;
+ }
+ mm_id->u.mm_fd = ret;
+ }
+ else {
if((cur_mm != NULL) && (cur_mm != &init_mm))
mm_id->u.pid = copy_context_skas0(stack,
cur_mm_id->u.pid);
@@ -126,7 +130,8 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
return 0;
out_free:
- free_page(mm_id->stack);
+ if(mm_id->stack != 0)
+ free_page(mm_id->stack);
out:
return ret;
}
@@ -137,9 +142,15 @@ void destroy_context_skas(struct mm_struct *mm)
if(proc_mm)
os_close_file(mmu->id.u.mm_fd);
- else {
+ else
os_kill_ptraced_process(mmu->id.u.pid, 1);
+
+ if(!proc_mm || !ptrace_faultinfo){
free_page(mmu->id.stack);
- free_page(mmu->last_page_table);
+ pte_free_kernel((pte_t *) mmu->last_page_table);
+ dec_page_state(nr_page_table_pages);
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ pmd_free((pmd_t *) mmu->last_pmd);
+#endif
}
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index f228f8b54194..5cd0e9929789 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -138,6 +138,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
}
extern int __syscall_stub_start;
+int stub_code_fd = -1;
+__u64 stub_code_offset;
static int userspace_tramp(void *stack)
{
@@ -152,31 +154,31 @@ static int userspace_tramp(void *stack)
/* This has a pte, but it can't be mapped in with the usual
* tlb_flush mechanism because this is part of that mechanism
*/
- int fd;
- __u64 offset;
-
- fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
- PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+ PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
+ stub_code_fd, stub_code_offset);
if(addr == MAP_FAILED){
- printk("mapping mmap stub failed, errno = %d\n",
+ printk("mapping stub code failed, errno = %d\n",
errno);
exit(1);
}
if(stack != NULL){
+ int fd;
+ __u64 offset;
+
fd = phys_mapping(to_phys(stack), &offset);
addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, offset);
if(addr == MAP_FAILED){
- printk("mapping segfault stack failed, "
+ printk("mapping stub stack failed, "
"errno = %d\n", errno);
exit(1);
}
}
}
- if(!ptrace_faultinfo && (stack != NULL)){
+ if(!ptrace_faultinfo){
unsigned long v = UML_CONFIG_STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
@@ -202,6 +204,10 @@ int start_userspace(unsigned long stub_stack)
unsigned long sp;
int pid, status, n, flags;
+ if ( stub_code_fd == -1 )
+ stub_code_fd = phys_mapping(to_phys(&__syscall_stub_start),
+ &stub_code_offset);
+
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
@@ -363,6 +369,53 @@ int copy_context_skas0(unsigned long new_stack, int pid)
return pid;
}
+/*
+ * This is used only, if proc_mm is available, while PTRACE_FAULTINFO
+ * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages
+ * Thus, we map them using /proc/mm-fd
+ */
+void map_stub_pages(int fd, unsigned long code,
+ unsigned long data, unsigned long stack)
+{
+ struct proc_mm_op mmop;
+ int n;
+
+ mmop = ((struct proc_mm_op) { .op = MM_MMAP,
+ .u =
+ { .mmap =
+ { .addr = code,
+ .len = PAGE_SIZE,
+ .prot = PROT_EXEC,
+ .flags = MAP_FIXED | MAP_PRIVATE,
+ .fd = stub_code_fd,
+ .offset = stub_code_offset
+ } } });
+ n = os_write_file(fd, &mmop, sizeof(mmop));
+ if(n != sizeof(mmop))
+ panic("map_stub_pages : /proc/mm map for code failed, "
+ "err = %d\n", -n);
+
+ if ( stack ) {
+ __u64 map_offset;
+ int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
+ mmop = ((struct proc_mm_op)
+ { .op = MM_MMAP,
+ .u =
+ { .mmap =
+ { .addr = data,
+ .len = PAGE_SIZE,
+ .prot = PROT_READ | PROT_WRITE,
+ .flags = MAP_FIXED | MAP_SHARED,
+ .fd = map_fd,
+ .offset = map_offset
+ } } });
+ n = os_write_file(fd, &mmop, sizeof(mmop));
+ if(n != sizeof(mmop))
+ panic("map_stub_pages : /proc/mm map for data failed, "
+ "err = %d\n", -n);
+ }
+}
+
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index cbabab104ac3..3d1b227226e6 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -129,7 +129,9 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
return(0);
}
-int new_mm(int from)
+extern void map_stub_pages(int fd, unsigned long code,
+ unsigned long data, unsigned long stack);
+int new_mm(int from, unsigned long stack)
{
struct proc_mm_op copy;
int n, fd;
@@ -148,6 +150,9 @@ int new_mm(int from)
"err = %d\n", -n);
}
+ if(!ptrace_faultinfo)
+ map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+
return(fd);
}
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
new file mode 100644
index 000000000000..51fb94076fcf
--- /dev/null
+++ b/arch/um/kernel/skas/syscall.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sys.h"
+#include "linux/ptrace.h"
+#include "asm/errno.h"
+#include "asm/unistd.h"
+#include "asm/ptrace.h"
+#include "asm/current.h"
+#include "sysdep/syscalls.h"
+#include "kern_util.h"
+#include "syscall.h"
+
+void handle_syscall(union uml_pt_regs *r)
+{
+ struct pt_regs *regs = container_of(r, struct pt_regs, regs);
+ long result;
+ int syscall;
+#ifdef UML_CONFIG_SYSCALL_DEBUG
+ int index;
+
+ index = record_syscall_start(UPT_SYSCALL_NR(r));
+#endif
+ syscall_trace(r, 0);
+
+ current->thread.nsyscalls++;
+ nsyscalls++;
+
+ /* This should go in the declaration of syscall, but when I do that,
+ * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
+ * children at all, sometimes hanging when bash doesn't see the first
+ * ls exit.
+ * The assembly looks functionally the same to me. This is
+ * gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
+ * in case it's a compiler bug.
+ */
+ syscall = UPT_SYSCALL_NR(r);
+ if((syscall >= NR_syscalls) || (syscall < 0))
+ result = -ENOSYS;
+ else result = EXECUTE_SYSCALL(syscall, regs);
+
+ REGS_SET_SYSCALL_RETURN(r->skas.regs, result);
+
+ syscall_trace(r, 1);
+#ifdef UML_CONFIG_SYSCALL_DEBUG
+ record_syscall_end(index, result);
+#endif
+}
diff --git a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c
deleted file mode 100644
index bdf040ce5b8e..000000000000
--- a/arch/um/kernel/skas/syscall_kern.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sys.h"
-#include "linux/ptrace.h"
-#include "asm/errno.h"
-#include "asm/unistd.h"
-#include "asm/ptrace.h"
-#include "asm/current.h"
-#include "sysdep/syscalls.h"
-#include "kern_util.h"
-
-extern syscall_handler_t *sys_call_table[];
-
-long execute_syscall_skas(void *r)
-{
- struct pt_regs *regs = r;
- long res;
- int syscall;
-
- current->thread.nsyscalls++;
- nsyscalls++;
- syscall = UPT_SYSCALL_NR(&regs->regs);
-
- if((syscall >= NR_syscalls) || (syscall < 0))
- res = -ENOSYS;
- else res = EXECUTE_SYSCALL(syscall, regs);
-
- return(res);
-}
-
-/*
- * 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/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
deleted file mode 100644
index 6b0664970147..000000000000
--- a/arch/um/kernel/skas/syscall_user.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <signal.h>
-#include "kern_util.h"
-#include "uml-config.h"
-#include "syscall_user.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "skas.h"
-
-void handle_syscall(union uml_pt_regs *regs)
-{
- long result;
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- int index;
-
- index = record_syscall_start(UPT_SYSCALL_NR(regs));
-#endif
-
- syscall_trace(regs, 0);
- result = execute_syscall_skas(regs);
-
- REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
-
- syscall_trace(regs, 1);
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- record_syscall_end(index, result);
-#endif
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 6230999c672c..6e84963dfc29 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -18,33 +18,39 @@
#include "os.h"
#include "tlb.h"
-static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
+static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
+ int finished, void **flush)
{
struct host_vm_op *op;
- int i;
+ int i, ret = 0;
- for(i = 0; i <= last; i++){
+ for(i = 0; i <= last && !ret; i++){
op = &ops[i];
switch(op->type){
case MMAP:
- map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len,
- op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
- op->u.mmap.fd, op->u.mmap.offset);
+ ret = map(&mmu->skas.id, op->u.mmap.addr,
+ op->u.mmap.len, op->u.mmap.r, op->u.mmap.w,
+ op->u.mmap.x, op->u.mmap.fd,
+ op->u.mmap.offset, finished, flush);
break;
case MUNMAP:
- unmap(&mmu->skas.id, (void *) op->u.munmap.addr,
- op->u.munmap.len);
+ ret = unmap(&mmu->skas.id,
+ (void *) op->u.munmap.addr,
+ op->u.munmap.len, finished, flush);
break;
case MPROTECT:
- protect(&mmu->skas.id, op->u.mprotect.addr,
- op->u.mprotect.len, op->u.mprotect.r,
- op->u.mprotect.w, op->u.mprotect.x);
+ ret = protect(&mmu->skas.id, op->u.mprotect.addr,
+ op->u.mprotect.len, op->u.mprotect.r,
+ op->u.mprotect.w, op->u.mprotect.x,
+ finished, flush);
break;
default:
printk("Unknown op type %d in do_ops\n", op->type);
break;
}
}
+
+ return ret;
}
extern int proc_mm;
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
new file mode 100644
index 000000000000..1429c131879d
--- /dev/null
+++ b/arch/um/kernel/syscall.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "kern_util.h"
+#include "syscall.h"
+#include "os.h"
+
+struct {
+ int syscall;
+ int pid;
+ long result;
+ unsigned long long start;
+ unsigned long long end;
+} syscall_record[1024];
+
+int record_syscall_start(int syscall)
+{
+ int max, index;
+
+ max = sizeof(syscall_record)/sizeof(syscall_record[0]);
+ index = next_syscall_index(max);
+
+ syscall_record[index].syscall = syscall;
+ syscall_record[index].pid = current_pid();
+ syscall_record[index].result = 0xdeadbeef;
+ syscall_record[index].start = os_usecs();
+ return(index);
+}
+
+void record_syscall_end(int index, long result)
+{
+ syscall_record[index].result = result;
+ syscall_record[index].end = os_usecs();
+}
diff --git a/arch/um/kernel/syscall_user.c b/arch/um/kernel/syscall_user.c
deleted file mode 100644
index 01b711e00a85..000000000000
--- a/arch/um/kernel/syscall_user.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <sys/time.h>
-#include "kern_util.h"
-#include "syscall_user.h"
-
-struct {
- int syscall;
- int pid;
- long result;
- struct timeval start;
- struct timeval end;
-} syscall_record[1024];
-
-int record_syscall_start(int syscall)
-{
- int max, index;
-
- max = sizeof(syscall_record)/sizeof(syscall_record[0]);
- index = next_syscall_index(max);
-
- syscall_record[index].syscall = syscall;
- syscall_record[index].pid = current_pid();
- syscall_record[index].result = 0xdeadbeef;
- gettimeofday(&syscall_record[index].start, NULL);
- return(index);
-}
-
-void record_syscall_end(int index, long result)
-{
- syscall_record[index].result = result;
- gettimeofday(&syscall_record[index].end, NULL);
-}
-
-/*
- * 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/tlb.c b/arch/um/kernel/tlb.c
index 83ec8d4747fd..80ed6188e8a2 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -15,12 +15,118 @@
#include "mem_user.h"
#include "os.h"
+static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
+ int r, int w, int x, struct host_vm_op *ops, int *index,
+ int last_filled, union mm_context *mmu, void **flush,
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int, int, void **))
+{
+ __u64 offset;
+ struct host_vm_op *last;
+ int fd, ret = 0;
+
+ fd = phys_mapping(phys, &offset);
+ if(*index != -1){
+ last = &ops[*index];
+ if((last->type == MMAP) &&
+ (last->u.mmap.addr + last->u.mmap.len == virt) &&
+ (last->u.mmap.r == r) && (last->u.mmap.w == w) &&
+ (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
+ (last->u.mmap.offset + last->u.mmap.len == offset)){
+ last->u.mmap.len += len;
+ return 0;
+ }
+ }
+
+ if(*index == last_filled){
+ ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
+ *index = -1;
+ }
+
+ ops[++*index] = ((struct host_vm_op) { .type = MMAP,
+ .u = { .mmap = {
+ .addr = virt,
+ .len = len,
+ .r = r,
+ .w = w,
+ .x = x,
+ .fd = fd,
+ .offset = offset }
+ } });
+ return ret;
+}
+
+static int add_munmap(unsigned long addr, unsigned long len,
+ struct host_vm_op *ops, int *index, int last_filled,
+ union mm_context *mmu, void **flush,
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int, int, void **))
+{
+ struct host_vm_op *last;
+ int ret = 0;
+
+ if(*index != -1){
+ last = &ops[*index];
+ if((last->type == MUNMAP) &&
+ (last->u.munmap.addr + last->u.mmap.len == addr)){
+ last->u.munmap.len += len;
+ return 0;
+ }
+ }
+
+ if(*index == last_filled){
+ ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
+ *index = -1;
+ }
+
+ ops[++*index] = ((struct host_vm_op) { .type = MUNMAP,
+ .u = { .munmap = {
+ .addr = addr,
+ .len = len } } });
+ return ret;
+}
+
+static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
+ int x, struct host_vm_op *ops, int *index,
+ int last_filled, union mm_context *mmu, void **flush,
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int, int, void **))
+{
+ struct host_vm_op *last;
+ int ret = 0;
+
+ if(*index != -1){
+ last = &ops[*index];
+ if((last->type == MPROTECT) &&
+ (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
+ (last->u.mprotect.r == r) && (last->u.mprotect.w == w) &&
+ (last->u.mprotect.x == x)){
+ last->u.mprotect.len += len;
+ return 0;
+ }
+ }
+
+ if(*index == last_filled){
+ ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
+ *index = -1;
+ }
+
+ ops[++*index] = ((struct host_vm_op) { .type = MPROTECT,
+ .u = { .mprotect = {
+ .addr = addr,
+ .len = len,
+ .r = r,
+ .w = w,
+ .x = x } } });
+ return ret;
+}
+
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force,
- void (*do_ops)(union mm_context *, struct host_vm_op *,
- int))
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int, int, void **))
{
pgd_t *npgd;
pud_t *npud;
@@ -29,21 +135,24 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
union mm_context *mmu = &mm->context;
unsigned long addr, end;
int r, w, x;
- struct host_vm_op ops[16];
+ struct host_vm_op ops[1];
+ void *flush = NULL;
int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1;
+ int ret = 0;
if(mm == NULL) return;
- for(addr = start_addr; addr < end_addr;){
+ ops[0].type = NONE;
+ for(addr = start_addr; addr < end_addr && !ret;){
npgd = pgd_offset(mm, addr);
if(!pgd_present(*npgd)){
end = ADD_ROUND(addr, PGDIR_SIZE);
if(end > end_addr)
end = end_addr;
if(force || pgd_newpage(*npgd)){
- op_index = add_munmap(addr, end - addr, ops,
- op_index, last_op, mmu,
- do_ops);
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
pgd_mkuptodate(*npgd);
}
addr = end;
@@ -56,9 +165,9 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
if(end > end_addr)
end = end_addr;
if(force || pud_newpage(*npud)){
- op_index = add_munmap(addr, end - addr, ops,
- op_index, last_op, mmu,
- do_ops);
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
pud_mkuptodate(*npud);
}
addr = end;
@@ -71,9 +180,9 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
if(end > end_addr)
end = end_addr;
if(force || pmd_newpage(*npmd)){
- op_index = add_munmap(addr, end - addr, ops,
- op_index, last_op, mmu,
- do_ops);
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
pmd_mkuptodate(*npmd);
}
addr = end;
@@ -92,24 +201,32 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
}
if(force || pte_newpage(*npte)){
if(pte_present(*npte))
- op_index = add_mmap(addr,
- pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x, ops,
- op_index, last_op, mmu,
- do_ops);
- else op_index = add_munmap(addr, PAGE_SIZE, ops,
- op_index, last_op, mmu,
- do_ops);
+ ret = add_mmap(addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ else ret = add_munmap(addr, PAGE_SIZE, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
}
else if(pte_newprot(*npte))
- op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
- op_index, last_op, mmu,
- do_ops);
+ ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
*npte = pte_mkuptodate(*npte);
addr += PAGE_SIZE;
}
- (*do_ops)(mmu, ops, op_index);
+
+ if(!ret)
+ ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
+
+ /* This is not an else because ret is modified above */
+ if(ret) {
+ printk("fix_range_common: failed, killing current process\n");
+ force_sig(SIGKILL, current);
+ }
}
int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
@@ -226,106 +343,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
return(pte_offset_map(pmd, addr));
}
-int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x, struct host_vm_op *ops, int index,
- int last_filled, union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *, int))
-{
- __u64 offset;
- struct host_vm_op *last;
- int fd;
-
- fd = phys_mapping(phys, &offset);
- if(index != -1){
- last = &ops[index];
- if((last->type == MMAP) &&
- (last->u.mmap.addr + last->u.mmap.len == virt) &&
- (last->u.mmap.r == r) && (last->u.mmap.w == w) &&
- (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
- (last->u.mmap.offset + last->u.mmap.len == offset)){
- last->u.mmap.len += len;
- return(index);
- }
- }
-
- if(index == last_filled){
- (*do_ops)(mmu, ops, last_filled);
- index = -1;
- }
-
- ops[++index] = ((struct host_vm_op) { .type = MMAP,
- .u = { .mmap = {
- .addr = virt,
- .len = len,
- .r = r,
- .w = w,
- .x = x,
- .fd = fd,
- .offset = offset }
- } });
- return(index);
-}
-
-int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
- int index, int last_filled, union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *, int))
-{
- struct host_vm_op *last;
-
- if(index != -1){
- last = &ops[index];
- if((last->type == MUNMAP) &&
- (last->u.munmap.addr + last->u.mmap.len == addr)){
- last->u.munmap.len += len;
- return(index);
- }
- }
-
- if(index == last_filled){
- (*do_ops)(mmu, ops, last_filled);
- index = -1;
- }
-
- ops[++index] = ((struct host_vm_op) { .type = MUNMAP,
- .u = { .munmap = {
- .addr = addr,
- .len = len } } });
- return(index);
-}
-
-int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
- struct host_vm_op *ops, int index, int last_filled,
- union mm_context *mmu,
- void (*do_ops)(union mm_context *, struct host_vm_op *, int))
-{
- struct host_vm_op *last;
-
- if(index != -1){
- last = &ops[index];
- if((last->type == MPROTECT) &&
- (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
- (last->u.mprotect.r == r) && (last->u.mprotect.w == w) &&
- (last->u.mprotect.x == x)){
- last->u.mprotect.len += len;
- return(index);
- }
- }
-
- if(index == last_filled){
- (*do_ops)(mmu, ops, last_filled);
- index = -1;
- }
-
- ops[++index] = ((struct host_vm_op) { .type = MPROTECT,
- .u = { .mprotect = {
- .addr = addr,
- .len = len,
- .r = r,
- .w = w,
- .x = x } } });
- return(index);
-}
-
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
{
address &= PAGE_MASK;
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index c20aef120598..87cc6fd76ced 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -26,6 +26,7 @@
#include "mem.h"
#include "mem_kern.h"
+/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
{
@@ -35,7 +36,6 @@ int handle_page_fault(unsigned long address, unsigned long ip,
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long page;
int err = -EFAULT;
*code_out = SEGV_MAPERR;
@@ -52,17 +52,17 @@ int handle_page_fault(unsigned long address, unsigned long ip,
else if(expand_stack(vma, address))
goto out;
- good_area:
+good_area:
*code_out = SEGV_ACCERR;
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
- if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ /* Don't require VM_READ|VM_EXEC for write faults! */
+ if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
goto out;
- page = address & PAGE_MASK;
do {
- survive:
+survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
case VM_FAULT_MINOR:
current->min_flt++;
@@ -79,16 +79,15 @@ int handle_page_fault(unsigned long address, unsigned long ip,
default:
BUG();
}
- pgd = pgd_offset(mm, page);
- pud = pud_offset(pgd, page);
- pmd = pmd_offset(pud, page);
- pte = pte_offset_kernel(pmd, page);
+ pgd = pgd_offset(mm, address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ pte = pte_offset_kernel(pmd, address);
} while(!pte_present(*pte));
err = 0;
- *pte = pte_mkyoung(*pte);
- if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
- flush_tlb_page(vma, page);
- out:
+ WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
+ flush_tlb_page(vma, address);
+out:
up_read(&mm->mmap_sem);
return(err);
@@ -144,19 +143,18 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
address, ip);
- if(err == -EACCES){
+ if (err == -EACCES) {
si.si_signo = SIGBUS;
si.si_errno = 0;
si.si_code = BUS_ADRERR;
si.si_addr = (void *)address;
current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
- }
- else if(err == -ENOMEM){
+ } else if (err == -ENOMEM) {
printk("VM: killing process %s\n", current->comm);
do_exit(SIGKILL);
- }
- else {
+ } else {
+ BUG_ON(err != -EFAULT);
si.si_signo = SIGSEGV;
si.si_addr = (void *) address;
current->thread.arch.faultinfo = fi;
@@ -200,30 +198,3 @@ void winch(int sig, union uml_pt_regs *regs)
void trap_init(void)
{
}
-
-DEFINE_SPINLOCK(trap_lock);
-
-static int trap_index = 0;
-
-int next_trap_index(int limit)
-{
- int ret;
-
- spin_lock(&trap_lock);
- ret = trap_index;
- if(++trap_index == limit)
- trap_index = 0;
- spin_unlock(&trap_lock);
- return(ret);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index f825a6eda3f5..e9ccd6b8d3c7 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -40,35 +40,14 @@ void kill_child_dead(int pid)
} while(1);
}
-/* Unlocked - don't care if this is a bit off */
-int nsegfaults = 0;
-
-struct {
- unsigned long address;
- int is_write;
- int pid;
- unsigned long sp;
- int is_user;
-} segfault_record[1024];
-
void segv_handler(int sig, union uml_pt_regs *regs)
{
- int index, max;
struct faultinfo * fi = UPT_FAULTINFO(regs);
if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
bad_segv(*fi, UPT_IP(regs));
return;
}
- max = sizeof(segfault_record)/sizeof(segfault_record[0]);
- index = next_trap_index(max);
-
- nsegfaults++;
- segfault_record[index].address = FAULT_ADDRESS(*fi);
- segfault_record[index].pid = os_getpid();
- segfault_record[index].is_write = FAULT_WRITE(*fi);
- segfault_record[index].sp = UPT_SP(regs);
- segfault_record[index].is_user = UPT_IS_USER(regs);
segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
}
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h
index 3fbb5fe26f49..aa6db384af80 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/kernel/tt/include/uaccess-tt.h
@@ -33,7 +33,7 @@ extern unsigned long uml_physmem;
(((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
(under_task_size(addr, size) || is_stack(addr, size))))
-static inline int verify_area_tt(int type, const void * addr,
+static inline int verify_area_tt(int type, const void __user * addr,
unsigned long size)
{
return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
@@ -50,12 +50,12 @@ extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
extern int __do_strnlen_user(const char *str, unsigned long n,
void **fault_addr, void **fault_catcher);
-extern int copy_from_user_tt(void *to, const void *from, int n);
-extern int copy_to_user_tt(void *to, const void *from, int n);
-extern int strncpy_from_user_tt(char *dst, const char *src, int count);
-extern int __clear_user_tt(void *mem, int len);
-extern int clear_user_tt(void *mem, int len);
-extern int strnlen_user_tt(const void *str, int len);
+extern int copy_from_user_tt(void *to, const void __user *from, int n);
+extern int copy_to_user_tt(void __user *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char __user *src, int count);
+extern int __clear_user_tt(void __user *mem, int len);
+extern int clear_user_tt(void __user *mem, int len);
+extern int strnlen_user_tt(const void __user *str, int len);
#endif
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index 2650a628719e..3d29c90514cc 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -12,36 +12,41 @@
#include "asm/uaccess.h"
#include "asm/stat.h"
#include "sysdep/syscalls.h"
+#include "sysdep/sigcontext.h"
#include "kern_util.h"
+#include "syscall.h"
-extern syscall_handler_t *sys_call_table[];
-
-long execute_syscall_tt(void *r)
+void syscall_handler_tt(int sig, struct pt_regs *regs)
{
- struct pt_regs *regs = r;
- long res;
+ void *sc;
+ long result;
int syscall;
-
#ifdef CONFIG_SYSCALL_DEBUG
+ int index;
+ index = record_syscall_start(syscall);
+#endif
+ sc = UPT_SC(&regs->regs);
+ SC_START_SYSCALL(sc);
+
+ syscall_trace(&regs->regs, 0);
+
current->thread.nsyscalls++;
nsyscalls++;
-#endif
syscall = UPT_SYSCALL_NR(&regs->regs);
if((syscall >= NR_syscalls) || (syscall < 0))
- res = -ENOSYS;
- else res = EXECUTE_SYSCALL(syscall, regs);
+ result = -ENOSYS;
+ else result = EXECUTE_SYSCALL(syscall, regs);
- return(res);
-}
+ /* regs->sc may have changed while the system call ran (there may
+ * have been an interrupt or segfault), so it needs to be refreshed.
+ */
+ UPT_SC(&regs->regs) = sc;
-/*
- * 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:
- */
+ SC_SET_SYSCALL_RETURN(sc, result);
+
+ syscall_trace(&regs->regs, 1);
+#ifdef CONFIG_SYSCALL_DEBUG
+ record_syscall_end(index, result);
+#endif
+}
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index b218316cfdb2..902987bf379b 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -13,42 +13,9 @@
#include "task.h"
#include "user_util.h"
#include "kern_util.h"
-#include "syscall_user.h"
+#include "syscall.h"
#include "tt.h"
-
-void syscall_handler_tt(int sig, union uml_pt_regs *regs)
-{
- void *sc;
- long result;
- int syscall;
-#ifdef UML_CONFIG_DEBUG_SYSCALL
- int index;
-#endif
-
- syscall = UPT_SYSCALL_NR(regs);
- sc = UPT_SC(regs);
- SC_START_SYSCALL(sc);
-
-#ifdef UML_CONFIG_DEBUG_SYSCALL
- index = record_syscall_start(syscall);
-#endif
- syscall_trace(regs, 0);
- result = execute_syscall_tt(regs);
-
- /* regs->sc may have changed while the system call ran (there may
- * have been an interrupt or segfault), so it needs to be refreshed.
- */
- UPT_SC(regs) = sc;
-
- SC_SET_SYSCALL_RETURN(sc, result);
-
- syscall_trace(regs, 1);
-#ifdef UML_CONFIG_DEBUG_SYSCALL
- record_syscall_end(index, result);
-#endif
-}
-
void do_sigtrap(void *task)
{
UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index 2eefb43bc9c2..f1d85dbb45b9 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -17,25 +17,31 @@
#include "os.h"
#include "tlb.h"
-static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
+static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
+ int finished, void **flush)
{
struct host_vm_op *op;
- int i;
+ int i, ret=0;
- for(i = 0; i <= last; i++){
+ for(i = 0; i <= last && !ret; i++){
op = &ops[i];
switch(op->type){
case MMAP:
- os_map_memory((void *) op->u.mmap.addr, op->u.mmap.fd,
- op->u.mmap.offset, op->u.mmap.len,
- op->u.mmap.r, op->u.mmap.w,
- op->u.mmap.x);
+ ret = os_map_memory((void *) op->u.mmap.addr,
+ op->u.mmap.fd, op->u.mmap.offset,
+ op->u.mmap.len, op->u.mmap.r,
+ op->u.mmap.w, op->u.mmap.x);
break;
case MUNMAP:
- os_unmap_memory((void *) op->u.munmap.addr,
- op->u.munmap.len);
+ ret = os_unmap_memory((void *) op->u.munmap.addr,
+ op->u.munmap.len);
break;
case MPROTECT:
+ ret = protect_memory(op->u.mprotect.addr,
+ op->u.munmap.len,
+ op->u.mprotect.r,
+ op->u.mprotect.w,
+ op->u.mprotect.x, 1);
protect_memory(op->u.mprotect.addr, op->u.munmap.len,
op->u.mprotect.r, op->u.mprotect.w,
op->u.mprotect.x, 1);
@@ -45,6 +51,8 @@ static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
break;
}
}
+
+ return ret;
}
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index ca2bb6f09a7d..09f6f7ce4695 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -126,7 +126,7 @@ unsigned long start_vm;
unsigned long end_vm;
int ncpus = 1;
-#ifdef CONFIG_MODE_TT
+#ifdef CONFIG_CMDLINE_ON_HOST
/* Pointer set in linux_main, the array itself is private to each thread,
* and changed at address space creation time so this poses no concurrency
* problems.
@@ -141,7 +141,7 @@ long physmem_size = 32 * 1024 * 1024;
void set_cmdline(char *cmd)
{
-#ifdef CONFIG_MODE_TT
+#ifdef CONFIG_CMDLINE_ON_HOST
char *umid, *ptr;
if(CHOOSE_MODE(honeypot, 0)) return;
@@ -333,6 +333,7 @@ int linux_main(int argc, char **argv)
if(have_root == 0)
add_arg(DEFAULT_COMMAND_LINE);
+ os_early_checks();
mode_tt = force_tt ? 1 : !can_do_skas();
#ifndef CONFIG_MODE_TT
if (mode_tt) {
@@ -385,7 +386,7 @@ int linux_main(int argc, char **argv)
setup_machinename(system_utsname.machine);
-#ifdef CONFIG_MODE_TT
+#ifdef CONFIG_CMDLINE_ON_HOST
argv1_begin = argv[1];
argv1_end = &argv[1][strlen(argv[1])];
#endif
@@ -470,7 +471,6 @@ void __init setup_arch(char **cmdline_p)
void __init check_bugs(void)
{
arch_check_bugs();
- check_ptrace();
check_sigio();
check_devanon();
}
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index b03326d391c9..af11915ce0a8 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -93,14 +93,10 @@ SECTIONS
*(.bss)
*(COMMON)
}
- _end = . ;
+ _end = .;
PROVIDE (end = .);
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
+
+ STABS_DEBUG
+
+ DWARF_DEBUG
}
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 4ddf540284ce..7a1662419c0c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,11 +3,19 @@
# Licensed under the GPL
#
-obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \
- sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
+ tty.o user_syms.o drivers/ sys-$(SUBARCH)/
-USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o
+USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
+ tty.o
+
+elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
+CFLAGS_elf_aux.o += -I$(objtree)/arch/um
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
+HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \
+ echo -DHAVE_AIO_ABI )
+CFLAGS_aio.o += $(HAVE_AIO_ABI)
+
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
new file mode 100644
index 000000000000..b04897cd995d
--- /dev/null
+++ b/arch/um/os-Linux/aio.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include "os.h"
+#include "helper.h"
+#include "aio.h"
+#include "init.h"
+#include "user.h"
+#include "mode.h"
+
+static int aio_req_fd_r = -1;
+static int aio_req_fd_w = -1;
+
+static int update_aio(struct aio_context *aio, int res)
+{
+ if(res < 0)
+ aio->len = res;
+ else if((res == 0) && (aio->type == AIO_READ)){
+ /* This is the EOF case - we have hit the end of the file
+ * and it ends in a partial block, so we fill the end of
+ * the block with zeros and claim success.
+ */
+ memset(aio->data, 0, aio->len);
+ aio->len = 0;
+ }
+ else if(res > 0){
+ aio->len -= res;
+ aio->data += res;
+ aio->offset += res;
+ return aio->len;
+ }
+
+ return 0;
+}
+
+#if defined(HAVE_AIO_ABI)
+#include <linux/aio_abi.h>
+
+/* If we have the headers, we are going to build with AIO enabled.
+ * If we don't have aio in libc, we define the necessary stubs here.
+ */
+
+#if !defined(HAVE_AIO_LIBC)
+
+static long io_setup(int n, aio_context_t *ctxp)
+{
+ return syscall(__NR_io_setup, n, ctxp);
+}
+
+static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
+{
+ return syscall(__NR_io_submit, ctx, nr, iocbpp);
+}
+
+static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
+ struct io_event *events, struct timespec *timeout)
+{
+ return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
+}
+
+#endif
+
+/* The AIO_MMAP cases force the mmapped page into memory here
+ * rather than in whatever place first touches the data. I used
+ * to do this by touching the page, but that's delicate because
+ * gcc is prone to optimizing that away. So, what's done here
+ * is we read from the descriptor from which the page was
+ * mapped. The caller is required to pass an offset which is
+ * inside the page that was mapped. Thus, when the read
+ * returns, we know that the page is in the page cache, and
+ * that it now backs the mmapped area.
+ */
+
+static int do_aio(aio_context_t ctx, struct aio_context *aio)
+{
+ struct iocb iocb, *iocbp = &iocb;
+ char c;
+ int err;
+
+ iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
+ .aio_reqprio = 0,
+ .aio_fildes = aio->fd,
+ .aio_buf = (unsigned long) aio->data,
+ .aio_nbytes = aio->len,
+ .aio_offset = aio->offset,
+ .aio_reserved1 = 0,
+ .aio_reserved2 = 0,
+ .aio_reserved3 = 0 });
+
+ switch(aio->type){
+ case AIO_READ:
+ iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+ break;
+ case AIO_WRITE:
+ iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
+ break;
+ case AIO_MMAP:
+ iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+ iocb.aio_buf = (unsigned long) &c;
+ iocb.aio_nbytes = sizeof(c);
+ break;
+ default:
+ printk("Bogus op in do_aio - %d\n", aio->type);
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = io_submit(ctx, 1, &iocbp);
+ if(err > 0)
+ err = 0;
+
+ out:
+ return err;
+}
+
+static aio_context_t ctx = 0;
+
+static int aio_thread(void *arg)
+{
+ struct aio_thread_reply reply;
+ struct aio_context *aio;
+ struct io_event event;
+ int err, n;
+
+ signal(SIGWINCH, SIG_IGN);
+
+ while(1){
+ n = io_getevents(ctx, 1, 1, &event, NULL);
+ if(n < 0){
+ if(errno == EINTR)
+ continue;
+ printk("aio_thread - io_getevents failed, "
+ "errno = %d\n", errno);
+ }
+ else {
+ aio = (struct aio_context *) event.data;
+ if(update_aio(aio, event.res)){
+ do_aio(ctx, aio);
+ continue;
+ }
+
+ reply = ((struct aio_thread_reply)
+ { .data = aio,
+ .err = aio->len });
+ err = os_write_file(aio->reply_fd, &reply,
+ sizeof(reply));
+ if(err != sizeof(reply))
+ printk("aio_thread - write failed, "
+ "fd = %d, err = %d\n", aio->reply_fd,
+ -err);
+ }
+ }
+ return 0;
+}
+
+#endif
+
+static int do_not_aio(struct aio_context *aio)
+{
+ char c;
+ int err;
+
+ switch(aio->type){
+ case AIO_READ:
+ err = os_seek_file(aio->fd, aio->offset);
+ if(err)
+ goto out;
+
+ err = os_read_file(aio->fd, aio->data, aio->len);
+ break;
+ case AIO_WRITE:
+ err = os_seek_file(aio->fd, aio->offset);
+ if(err)
+ goto out;
+
+ err = os_write_file(aio->fd, aio->data, aio->len);
+ break;
+ case AIO_MMAP:
+ err = os_seek_file(aio->fd, aio->offset);
+ if(err)
+ goto out;
+
+ err = os_read_file(aio->fd, &c, sizeof(c));
+ break;
+ default:
+ printk("do_not_aio - bad request type : %d\n", aio->type);
+ err = -EINVAL;
+ break;
+ }
+
+ out:
+ return err;
+}
+
+static int not_aio_thread(void *arg)
+{
+ struct aio_context *aio;
+ struct aio_thread_reply reply;
+ int err;
+
+ signal(SIGWINCH, SIG_IGN);
+ while(1){
+ err = os_read_file(aio_req_fd_r, &aio, sizeof(aio));
+ if(err != sizeof(aio)){
+ if(err < 0)
+ printk("not_aio_thread - read failed, "
+ "fd = %d, err = %d\n", aio_req_fd_r,
+ -err);
+ else {
+ printk("not_aio_thread - short read, fd = %d, "
+ "length = %d\n", aio_req_fd_r, err);
+ }
+ continue;
+ }
+ again:
+ err = do_not_aio(aio);
+
+ if(update_aio(aio, err))
+ goto again;
+
+ reply = ((struct aio_thread_reply) { .data = aio,
+ .err = aio->len });
+ err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+ if(err != sizeof(reply))
+ printk("not_aio_thread - write failed, fd = %d, "
+ "err = %d\n", aio_req_fd_r, -err);
+ }
+}
+
+static int submit_aio_24(struct aio_context *aio)
+{
+ int err;
+
+ err = os_write_file(aio_req_fd_w, &aio, sizeof(aio));
+ if(err == sizeof(aio))
+ err = 0;
+
+ return err;
+}
+
+static int aio_pid = -1;
+static int (*submit_proc)(struct aio_context *aio);
+
+static int init_aio_24(void)
+{
+ unsigned long stack;
+ int fds[2], err;
+
+ err = os_pipe(fds, 1, 1);
+ if(err)
+ goto out;
+
+ aio_req_fd_w = fds[0];
+ aio_req_fd_r = fds[1];
+ err = run_helper_thread(not_aio_thread, NULL,
+ CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+ if(err < 0)
+ goto out_close_pipe;
+
+ aio_pid = err;
+ goto out;
+
+ out_close_pipe:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+ aio_req_fd_w = -1;
+ aio_req_fd_r = -1;
+ out:
+#ifndef HAVE_AIO_ABI
+ printk("/usr/include/linux/aio_abi.h not present during build\n");
+#endif
+ printk("2.6 host AIO support not used - falling back to I/O "
+ "thread\n");
+
+ submit_proc = submit_aio_24;
+
+ return 0;
+}
+
+#ifdef HAVE_AIO_ABI
+#define DEFAULT_24_AIO 0
+static int submit_aio_26(struct aio_context *aio)
+{
+ struct aio_thread_reply reply;
+ int err;
+
+ err = do_aio(ctx, aio);
+ if(err){
+ reply = ((struct aio_thread_reply) { .data = aio,
+ .err = err });
+ err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+ if(err != sizeof(reply))
+ printk("submit_aio_26 - write failed, "
+ "fd = %d, err = %d\n", aio->reply_fd, -err);
+ else err = 0;
+ }
+
+ return err;
+}
+
+static int init_aio_26(void)
+{
+ unsigned long stack;
+ int err;
+
+ if(io_setup(256, &ctx)){
+ printk("aio_thread failed to initialize context, err = %d\n",
+ errno);
+ return -errno;
+ }
+
+ err = run_helper_thread(aio_thread, NULL,
+ CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+ if(err < 0)
+ return -errno;
+
+ aio_pid = err;
+
+ printk("Using 2.6 host AIO\n");
+
+ submit_proc = submit_aio_26;
+
+ return 0;
+}
+
+#else
+#define DEFAULT_24_AIO 1
+static int submit_aio_26(struct aio_context *aio)
+{
+ return -ENOSYS;
+}
+
+static int init_aio_26(void)
+{
+ submit_proc = submit_aio_26;
+ return -ENOSYS;
+}
+#endif
+
+static int aio_24 = DEFAULT_24_AIO;
+
+static int __init set_aio_24(char *name, int *add)
+{
+ aio_24 = 1;
+ return 0;
+}
+
+__uml_setup("aio=2.4", set_aio_24,
+"aio=2.4\n"
+" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
+" available. 2.4 AIO is a single thread that handles one request at a\n"
+" time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO \n"
+" interface to handle an arbitrary number of pending requests. 2.6 AIO \n"
+" is not available in tt mode, on 2.4 hosts, or when UML is built with\n"
+" /usr/include/linux/aio_abi.h not available. Many distributions don't\n"
+" include aio_abi.h, so you will need to copy it from a kernel tree to\n"
+" your /usr/include/linux in order to build an AIO-capable UML\n\n"
+);
+
+static int init_aio(void)
+{
+ int err;
+
+ CHOOSE_MODE(({
+ if(!aio_24){
+ printk("Disabling 2.6 AIO in tt mode\n");
+ aio_24 = 1;
+ } }), (void) 0);
+
+ if(!aio_24){
+ err = init_aio_26();
+ if(err && (errno == ENOSYS)){
+ printk("2.6 AIO not supported on the host - "
+ "reverting to 2.4 AIO\n");
+ aio_24 = 1;
+ }
+ else return err;
+ }
+
+ if(aio_24)
+ return init_aio_24();
+
+ return 0;
+}
+
+/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
+ * needs to be called when the kernel is running because it calls run_helper,
+ * which needs get_free_page. exit_aio is a __uml_exitcall because the generic
+ * kernel does not run __exitcalls on shutdown, and can't because many of them
+ * break when called outside of module unloading.
+ */
+__initcall(init_aio);
+
+static void exit_aio(void)
+{
+ if(aio_pid != -1)
+ os_kill_process(aio_pid, 1);
+}
+
+__uml_exitcall(exit_aio);
+
+int submit_aio(struct aio_context *aio)
+{
+ return (*submit_proc)(aio);
+}
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 4cca3e9c23fe..1399520a8588 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -12,8 +12,9 @@
#include "init.h"
#include "elf_user.h"
#include "mem_user.h"
+#include <kernel-offsets.h>
-#if ELF_CLASS == ELFCLASS32
+#if HOST_ELF_CLASS == ELFCLASS32
typedef Elf32_auxv_t elf_auxv_t;
#else
typedef Elf64_auxv_t elf_auxv_t;
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 1e126bfd31a7..d32413e4b4ce 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -3,10 +3,10 @@
* Licensed under the GPL
*/
-#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
+#include <setjmp.h>
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
@@ -14,6 +14,10 @@
#include "os.h"
#include "user.h"
#include "user_util.h"
+#include "signal_user.h"
+#include "process.h"
+#include "irq_user.h"
+#include "kern_util.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -114,8 +118,10 @@ void os_usr1_process(int pid)
kill(pid, SIGUSR1);
}
-/*Don't use the glibc version, which caches the result in TLS. It misses some
- * syscalls, and also breaks with clone(), which does not unshare the TLS.*/
+/* Don't use the glibc version, which caches the result in TLS. It misses some
+ * syscalls, and also breaks with clone(), which does not unshare the TLS.
+ */
+
inline _syscall0(pid_t, getpid)
int os_getpid(void)
@@ -164,6 +170,52 @@ int os_unmap_memory(void *addr, int len)
return(0);
}
+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
+{
+ int flags = 0, pages;
+
+ if(sig_stack != NULL){
+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
+ set_sigstack(sig_stack, pages * page_size());
+ flags = SA_ONSTACK;
+ }
+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
+}
+
+void init_new_thread_signals(int altstack)
+{
+ int flags = altstack ? SA_ONSTACK : 0;
+
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGFPE, (__sighandler_t) sig_handler, flags,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGILL, (__sighandler_t) sig_handler, flags,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGUSR2, (__sighandler_t) sig_handler,
+ flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ signal(SIGHUP, SIG_IGN);
+
+ init_irq_signals(altstack);
+}
+
+int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
+{
+ sigjmp_buf buf;
+ int n;
+
+ *jmp_ptr = &buf;
+ n = sigsetjmp(buf, 1);
+ if(n != 0)
+ return(n);
+ (*fn)(arg);
+ return(0);
+}
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/process.c b/arch/um/os-Linux/start_up.c
index 67acd92c5322..040cc1472bc7 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/os-Linux/start_up.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -19,7 +19,6 @@
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
-#include "process.h"
#include "signal_kern.h"
#include "signal_user.h"
#include "sysdep/ptrace.h"
@@ -39,98 +38,6 @@
#include "registers.h"
#endif
-void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
-{
- int flags = 0, pages;
-
- if(sig_stack != NULL){
- pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
- set_sigstack(sig_stack, pages * page_size());
- flags = SA_ONSTACK;
- }
- if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
-}
-
-void init_new_thread_signals(int altstack)
-{
- int flags = altstack ? SA_ONSTACK : 0;
-
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGFPE, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGILL, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGUSR2, (__sighandler_t) sig_handler,
- flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- signal(SIGHUP, SIG_IGN);
-
- init_irq_signals(altstack);
-}
-
-struct tramp {
- int (*tramp)(void *);
- void *tramp_data;
- unsigned long temp_stack;
- int flags;
- int pid;
-};
-
-/* See above for why sigkill is here */
-
-int sigkill = SIGKILL;
-
-int outer_tramp(void *arg)
-{
- struct tramp *t;
- int sig = sigkill;
-
- t = arg;
- t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2,
- t->flags, t->tramp_data);
- if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
- kill(os_getpid(), sig);
- _exit(0);
-}
-
-int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
- int clone_flags, int (*tramp)(void *))
-{
- struct tramp arg;
- unsigned long sp;
- int new_pid, status, err;
-
- /* The trampoline will run on the temporary stack */
- sp = stack_sp(temp_stack);
-
- clone_flags |= CLONE_FILES | SIGCHLD;
-
- arg.tramp = tramp;
- arg.tramp_data = thread_arg;
- arg.temp_stack = temp_stack;
- arg.flags = clone_flags;
-
- /* Start the process and wait for it to kill itself */
- new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
- if(new_pid < 0)
- return(new_pid);
-
- CATCH_EINTR(err = waitpid(new_pid, &status, 0));
- if(err < 0)
- panic("Waiting for outer trampoline failed - errno = %d",
- errno);
-
- if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
- panic("outer trampoline didn't exit with SIGKILL, "
- "status = %d", status);
-
- return(arg.pid);
-}
-
static int ptrace_child(void *arg)
{
int ret;
@@ -165,7 +72,7 @@ static int start_ptraced_child(void **stack_out)
void *stack;
unsigned long sp;
int pid, n, status;
-
+
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
@@ -173,10 +80,10 @@ static int start_ptraced_child(void **stack_out)
sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
if(pid < 0)
- panic("check_ptrace : clone failed, errno = %d", errno);
+ panic("start_ptraced_child : clone failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
- panic("check_ptrace : wait failed, errno = %d", errno);
+ panic("check_ptrace : clone failed, errno = %d", errno);
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("check_ptrace : expected SIGSTOP, got status = %d",
status);
@@ -185,11 +92,14 @@ static int start_ptraced_child(void **stack_out)
return(pid);
}
-/* When testing for SYSEMU support, if it is one of the broken versions, we must
- * just avoid using sysemu, not panic, but only if SYSEMU features are broken.
+/* When testing for SYSEMU support, if it is one of the broken versions, we
+ * must just avoid using sysemu, not panic, but only if SYSEMU features are
+ * broken.
* So only for SYSEMU features we test mustpanic, while normal host features
- * must work anyway!*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
+ * must work anyway!
+ */
+static int stop_ptraced_child(int pid, void *stack, int exitcode,
+ int mustpanic)
{
int status, n, ret = 0;
@@ -217,8 +127,6 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
return ret;
}
-static int force_sysemu_disabled = 0;
-
int ptrace_faultinfo = 1;
int proc_mm = 1;
@@ -228,29 +136,32 @@ static int __init skas0_cmd_param(char *str, int* add)
return 0;
}
+__uml_setup("skas0", skas0_cmd_param,
+ "skas0\n"
+ " Disables SKAS3 usage, so that SKAS0 is used, unless \n"
+ " you specify mode=tt.\n\n");
+
+static int force_sysemu_disabled = 0;
+
static int __init nosysemu_cmd_param(char *str, int* add)
{
force_sysemu_disabled = 1;
return 0;
}
-__uml_setup("skas0", skas0_cmd_param,
- "skas0\n"
- " Disables SKAS3 usage, so that SKAS0 is used, unless you \n"
- " specify mode=tt.\n\n");
-
__uml_setup("nosysemu", nosysemu_cmd_param,
- "nosysemu\n"
- " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
- " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
- " behaviour of ptrace() and helps reducing host context switch rate.\n"
- " To make it working, you need a kernel patch for your host, too.\n"
- " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n\n");
+"nosysemu\n"
+" Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
+" SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
+" behaviour of ptrace() and helps reducing host context switch rate.\n"
+" To make it working, you need a kernel patch for your host, too.\n"
+" See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n"
+" information.\n\n");
static void __init check_sysemu(void)
{
void *stack;
- int pid, syscall, n, status, count=0;
+ int pid, n, status, count=0;
printk("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
@@ -281,6 +192,12 @@ static void __init check_sysemu(void)
printk("Checking advanced syscall emulation patch for ptrace...");
pid = start_ptraced_child(&stack);
+
+ if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+ (void *) PTRACE_O_TRACESYSGOOD) < 0)
+ panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d",
+ errno);
+
while(1){
count++;
if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
@@ -288,15 +205,10 @@ static void __init check_sysemu(void)
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
- panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
- "got status = %d", status);
-
- syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
- 0);
- if(syscall == __NR_getpid){
+ if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
if (!count)
- panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep");
+ panic("check_ptrace : SYSEMU_SINGLESTEP "
+ "doesn't singlestep");
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
@@ -304,6 +216,11 @@ static void __init check_sysemu(void)
"call return, errno = %d", errno);
break;
}
+ else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
+ count++;
+ else
+ panic("check_ptrace : expected SIGTRAP or "
+ "(SIGTRAP|0x80), got status = %d", status);
}
if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;
@@ -321,7 +238,7 @@ fail_stopped:
printk("missing\n");
}
-void __init check_ptrace(void)
+static void __init check_ptrace(void)
{
void *stack;
int pid, syscall, n, status;
@@ -329,20 +246,20 @@ void __init check_ptrace(void)
printk("Checking that ptrace can change system call numbers...");
pid = start_ptraced_child(&stack);
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
+ if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
+ panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno);
while(1){
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
- panic("check_ptrace : ptrace failed, errno = %d",
+ panic("check_ptrace : ptrace failed, errno = %d",
errno);
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP + 0x80))
- panic("check_ptrace : expected SIGTRAP + 0x80, "
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80)))
+ panic("check_ptrace : expected (SIGTRAP|0x80), "
"got status = %d", status);
-
+
syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
0);
if(syscall == __NR_getpid){
@@ -359,33 +276,36 @@ void __init check_ptrace(void)
check_sysemu();
}
-int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
+void os_early_checks(void)
{
- sigjmp_buf buf;
- int n;
-
- *jmp_ptr = &buf;
- n = sigsetjmp(buf, 1);
- if(n != 0)
- return(n);
- (*fn)(arg);
- return(0);
+ check_ptrace();
}
-void forward_pending_sigio(int target)
+static int __init noprocmm_cmd_param(char *str, int* add)
{
- sigset_t sigs;
+ proc_mm = 0;
+ return 0;
+}
+
+__uml_setup("noprocmm", noprocmm_cmd_param,
+"noprocmm\n"
+" Turns off usage of /proc/mm, even if host supports it.\n"
+" To support /proc/mm, the host needs to be patched using\n"
+" the current skas3 patch.\n\n");
- if(sigpending(&sigs))
- panic("forward_pending_sigio : sigpending failed");
- if(sigismember(&sigs, SIGIO))
- kill(target, SIGIO);
+static int __init noptracefaultinfo_cmd_param(char *str, int* add)
+{
+ ptrace_faultinfo = 0;
+ return 0;
}
-extern void *__syscall_stub_start, __syscall_stub_end;
+__uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
+"noptracefaultinfo\n"
+" Turns off usage of PTRACE_FAULTINFO, even if host supports\n"
+" it. To support PTRACE_FAULTINFO, the host needs to be patched\n"
+" using the current skas3 patch.\n\n");
#ifdef UML_CONFIG_MODE_SKAS
-
static inline void check_skas3_ptrace_support(void)
{
struct ptrace_faultinfo fi;
@@ -400,9 +320,8 @@ static inline void check_skas3_ptrace_support(void)
ptrace_faultinfo = 0;
if(errno == EIO)
printf("not found\n");
- else {
+ else
perror("not found");
- }
}
else {
if (!ptrace_faultinfo)
@@ -419,9 +338,10 @@ int can_do_skas(void)
{
printf("Checking for /proc/mm...");
if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
- proc_mm = 0;
+ proc_mm = 0;
printf("not found\n");
- } else {
+ }
+ else {
if (!proc_mm)
printf("found but disabled on command line\n");
else
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
new file mode 100644
index 000000000000..5b047ab8416a
--- /dev/null
+++ b/arch/um/os-Linux/tt.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sched.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <sys/time.h>
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+#include <asm/page.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "signal_kern.h"
+#include "signal_user.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/sigcontext.h"
+#include "irq_user.h"
+#include "ptrace_user.h"
+#include "time_user.h"
+#include "init.h"
+#include "os.h"
+#include "uml-config.h"
+#include "choose-mode.h"
+#include "mode.h"
+#include "tempfile.h"
+
+/*
+ *-------------------------
+ * only for tt mode (will be deleted in future...)
+ *-------------------------
+ */
+
+struct tramp {
+ int (*tramp)(void *);
+ void *tramp_data;
+ unsigned long temp_stack;
+ int flags;
+ int pid;
+};
+
+/* See above for why sigkill is here */
+
+int sigkill = SIGKILL;
+
+int outer_tramp(void *arg)
+{
+ struct tramp *t;
+ int sig = sigkill;
+
+ t = arg;
+ t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2,
+ t->flags, t->tramp_data);
+ if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
+ kill(os_getpid(), sig);
+ _exit(0);
+}
+
+int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
+ int clone_flags, int (*tramp)(void *))
+{
+ struct tramp arg;
+ unsigned long sp;
+ int new_pid, status, err;
+
+ /* The trampoline will run on the temporary stack */
+ sp = stack_sp(temp_stack);
+
+ clone_flags |= CLONE_FILES | SIGCHLD;
+
+ arg.tramp = tramp;
+ arg.tramp_data = thread_arg;
+ arg.temp_stack = temp_stack;
+ arg.flags = clone_flags;
+
+ /* Start the process and wait for it to kill itself */
+ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
+ if(new_pid < 0)
+ return(new_pid);
+
+ CATCH_EINTR(err = waitpid(new_pid, &status, 0));
+ if(err < 0)
+ panic("Waiting for outer trampoline failed - errno = %d",
+ errno);
+
+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
+ panic("outer trampoline didn't exit with SIGKILL, "
+ "status = %d", status);
+
+ return(arg.pid);
+}
+
+void forward_pending_sigio(int target)
+{
+ sigset_t sigs;
+
+ if(sigpending(&sigs))
+ panic("forward_pending_sigio : sigpending failed");
+ if(sigismember(&sigs, SIGIO))
+ kill(target, SIGIO);
+}
+
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 17f305b6bade..59a1291f477e 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -9,6 +9,11 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : 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 =
+
# The stubs and unmap.o can't try to call mcount or update basic block data
define unprofile
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
index 802d027a1e13..b2165188d942 100644
--- a/arch/um/scripts/Makefile.unmap
+++ b/arch/um/scripts/Makefile.unmap
@@ -12,7 +12,7 @@ $(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
quiet_cmd_wrapld = LD $@
define cmd_wrapld
- $(LD) $(LDFLAGS) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) $(CFLAGS) -print-file-name=libc.a); \
+ $(LD) $(LDFLAGS) -r -o $(obj)/unmap_tmp.o $< ; \
$(OBJCOPY) $(UML_OBJCOPYFLAGS) $(obj)/unmap_tmp.o $@ -G switcheroo
endef
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 77c3c4d29f55..4ca2a229da49 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -16,13 +16,7 @@ semaphore.c-dir = kernel
highmem.c-dir = mm
module.c-dir = kernel
-STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
-
-# _cflags works with kernel files, not with userspace ones, but c_flags does,
-# why ask why?
-$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
-
-$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
+$(obj)/stub_segv.o : _c_flags = $(call unprofile,$(CFLAGS))
subdir- := util
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/sys-i386/kernel-offsets.c
index 9f8ecd1fdd96..a1070af2bcd8 100644
--- a/arch/um/sys-i386/kernel-offsets.c
+++ b/arch/um/sys-i386/kernel-offsets.c
@@ -2,6 +2,7 @@
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/elf.h>
#include <asm/page.h>
#define DEFINE(sym, val) \
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 4efc69a039d7..16bc19928b3c 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -122,9 +122,9 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
int err;
to_fp = to->fpstate;
- from_fp = from->fpstate;
sigs = to->oldmask;
err = copy_from_user(to, from, sizeof(*to));
+ from_fp = to->fpstate;
to->oldmask = sigs;
to->fpstate = to_fp;
if(to_fp != NULL)
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index 2f2c70a8f043..6a70d9ab5c29 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -2,7 +2,50 @@
.globl syscall_stub
.section .__syscall_stub, "x"
-syscall_stub:
- int $0x80
+
+ .globl batch_syscall_stub
+batch_syscall_stub:
+ /* load pointer to first operation */
+ mov $(UML_CONFIG_STUB_DATA+8), %esp
+
+again:
+ /* load length of additional data */
+ mov 0x0(%esp), %eax
+
+ /* if(length == 0) : end of list */
+ /* write possible 0 to header */
+ mov %eax, UML_CONFIG_STUB_DATA+4
+ cmpl $0, %eax
+ jz done
+
+ /* save current pointer */
+ mov %esp, UML_CONFIG_STUB_DATA+4
+
+ /* skip additional data */
+ add %eax, %esp
+
+ /* load syscall-# */
+ pop %eax
+
+ /* load syscall params */
+ pop %ebx
+ pop %ecx
+ pop %edx
+ pop %esi
+ pop %edi
+ pop %ebp
+
+ /* execute syscall */
+ int $0x80
+
+ /* check return value */
+ pop %ebx
+ cmp %ebx, %eax
+ je again
+
+done:
+ /* save return value */
mov %eax, UML_CONFIG_STUB_DATA
+
+ /* stop */
int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index 68aeabe3a654..1e88b275edac 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -3,8 +3,7 @@
* Licensed under the GPL
*/
-#include <signal.h>
-#include <asm/sigcontext.h>
+#include <asm/signal.h>
#include <asm/unistd.h>
#include "uml-config.h"
#include "sysdep/sigcontext.h"
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 7488206ce6f4..f0ab574d1e95 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -6,7 +6,7 @@
#XXX: why into lib-y?
lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
- ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \
+ ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \
stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
obj-y := ksyms.o
@@ -15,7 +15,7 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
USER_OBJS := ptrace_user.o sigcontext.o
SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
- semaphore.c thunk.S module.c
+ thunk.S module.c
include arch/um/scripts/Makefile.rules
@@ -24,17 +24,10 @@ csum-copy.S-dir = lib
csum-partial.c-dir = lib
csum-wrappers.c-dir = lib
memcpy.S-dir = lib
-semaphore.c-dir = kernel
thunk.S-dir = lib
module.c-dir = kernel
-STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
-
-# _cflags works with kernel files, not with userspace ones, but c_flags does,
-# why ask why?
-$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
-
-$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
+$(obj)/stub_segv.o: _c_flags = $(call unprofile,$(CFLAGS))
subdir- := util
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/sys-x86_64/kernel-offsets.c
index 220e875cbe29..998541eade41 100644
--- a/arch/um/sys-x86_64/kernel-offsets.c
+++ b/arch/um/sys-x86_64/kernel-offsets.c
@@ -2,6 +2,7 @@
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/elf.h>
#include <asm/page.h>
#define DEFINE(sym, val) \
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 8fdaed06c10d..fe1d065332b1 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -104,28 +104,35 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
int fpsize)
{
- struct _fpstate *to_fp, *from_fp;
- unsigned long sigs;
- int err;
-
- to_fp = to->fpstate;
- from_fp = from->fpstate;
- sigs = to->oldmask;
- err = copy_from_user(to, from, sizeof(*to));
- to->oldmask = sigs;
- return(err);
+ struct _fpstate *to_fp, *from_fp;
+ unsigned long sigs;
+ int err;
+
+ to_fp = to->fpstate;
+ sigs = to->oldmask;
+ err = copy_from_user(to, from, sizeof(*to));
+ from_fp = to->fpstate;
+ to->fpstate = to_fp;
+ to->oldmask = sigs;
+ if(to_fp != NULL)
+ err |= copy_from_user(to_fp, from_fp, fpsize);
+ return(err);
}
int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
struct sigcontext *from, int fpsize)
{
- struct _fpstate *to_fp, *from_fp;
- int err;
-
- to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
- from_fp = from->fpstate;
- err = copy_to_user(to, from, sizeof(*to));
- return(err);
+ struct _fpstate *to_fp, *from_fp;
+ int err;
+
+ to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+ from_fp = from->fpstate;
+ err = copy_to_user(to, from, sizeof(*to));
+ 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);
}
#endif
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
index 31c14925716b..03c279735784 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -13,3 +13,54 @@ syscall_stub:
or %rcx, %rbx
movq %rax, (%rbx)
int3
+
+ .globl batch_syscall_stub
+batch_syscall_stub:
+ mov $(UML_CONFIG_STUB_DATA >> 32), %rbx
+ sal $32, %rbx
+ mov $(UML_CONFIG_STUB_DATA & 0xffffffff), %rax
+ or %rax, %rbx
+ /* load pointer to first operation */
+ mov %rbx, %rsp
+ add $0x10, %rsp
+again:
+ /* load length of additional data */
+ mov 0x0(%rsp), %rax
+
+ /* if(length == 0) : end of list */
+ /* write possible 0 to header */
+ mov %rax, 8(%rbx)
+ cmp $0, %rax
+ jz done
+
+ /* save current pointer */
+ mov %rsp, 8(%rbx)
+
+ /* skip additional data */
+ add %rax, %rsp
+
+ /* load syscall-# */
+ pop %rax
+
+ /* load syscall params */
+ pop %rdi
+ pop %rsi
+ pop %rdx
+ pop %r10
+ pop %r8
+ pop %r9
+
+ /* execute syscall */
+ syscall
+
+ /* check return value */
+ pop %rcx
+ cmp %rcx, %rax
+ je again
+
+done:
+ /* save return value */
+ mov %rax, (%rbx)
+
+ /* stop */
+ int3
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 161d1fe9c034..65a131b362b6 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -3,9 +3,10 @@
* Licensed under the GPL
*/
-#include <signal.h>
+#include <asm/signal.h>
#include <linux/compiler.h>
#include <asm/unistd.h>
+#include <asm/ucontext.h>
#include "uml-config.h"
#include "sysdep/sigcontext.h"
#include "sysdep/faultinfo.h"
diff --git a/arch/v850/Makefile b/arch/v850/Makefile
index bf38ca0ad781..8be9aacb20a7 100644
--- a/arch/v850/Makefile
+++ b/arch/v850/Makefile
@@ -51,16 +51,4 @@ root_fs_image_force: $(ROOT_FS_IMAGE)
$(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
endif
-
-prepare: include/asm-$(ARCH)/asm-consts.h
-
-# Generate constants from C code for use by asm files
-arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/asm-consts.h: arch/$(ARCH)/kernel/asm-consts.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h \
- arch/$(ARCH)/kernel/asm-consts.s \
- root_fs_image.o
+CLEAN_FILES += root_fs_image.o
diff --git a/arch/v850/configs/rte-ma1-cb_defconfig b/arch/v850/configs/rte-ma1-cb_defconfig
index 1b5ca3c3a658..1a5beda36e29 100644
--- a/arch/v850/configs/rte-ma1-cb_defconfig
+++ b/arch/v850/configs/rte-ma1-cb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-uc0
-# Thu Jul 21 11:08:27 2005
+# Linux kernel version: 2.6.13-uc0
+# Fri Sep 2 13:54:27 2005
#
# CONFIG_MMU is not set
# CONFIG_UID16 is not set
@@ -44,6 +44,8 @@ CONFIG_ZERO_BSS=y
# CONFIG_V850E_HIGHRES_TIMER is not set
# CONFIG_RESET_GUARD is not set
CONFIG_LARGE_ALLOCS=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
#
# Code maturity level options
@@ -111,6 +113,52 @@ CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_MISC is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE 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_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER 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_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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
+
+#
# Generic Driver Options
#
CONFIG_STANDALONE=y
@@ -158,6 +206,7 @@ CONFIG_MTD_CFI_I2=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -232,6 +281,7 @@ CONFIG_IOSCHED_NOOP=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -244,53 +294,8 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_UNIX is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE 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
-# 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
-
-#
-# 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
@@ -372,6 +377,8 @@ CONFIG_EEPRO100=y
# CONFIG_FDDI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -472,6 +479,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -479,6 +487,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_MAGIC_ROM_PTR is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -524,9 +534,11 @@ CONFIG_RAMFS=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
diff --git a/arch/v850/configs/rte-me2-cb_defconfig b/arch/v850/configs/rte-me2-cb_defconfig
index 44becc065404..15e666478061 100644
--- a/arch/v850/configs/rte-me2-cb_defconfig
+++ b/arch/v850/configs/rte-me2-cb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-uc0
-# Thu Jul 21 11:30:08 2005
+# Linux kernel version: 2.6.13-uc0
+# Fri Sep 2 13:47:50 2005
#
# CONFIG_MMU is not set
# CONFIG_UID16 is not set
@@ -41,6 +41,8 @@ CONFIG_ZERO_BSS=y
# CONFIG_V850E_HIGHRES_TIMER is not set
# CONFIG_RESET_GUARD is not set
CONFIG_LARGE_ALLOCS=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
#
# Code maturity level options
@@ -56,7 +58,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
@@ -104,6 +105,11 @@ CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_MISC is not set
#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
# Generic Driver Options
#
CONFIG_STANDALONE=y
@@ -151,6 +157,7 @@ CONFIG_MTD_CFI_I2=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -218,6 +225,7 @@ CONFIG_IOSCHED_NOOP=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -228,9 +236,8 @@ CONFIG_IOSCHED_NOOP=y
#
#
-# Networking support
+# Network device support
#
-# CONFIG_NET is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -311,7 +318,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -335,6 +341,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -342,6 +349,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_MAGIC_ROM_PTR is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
diff --git a/arch/v850/configs/sim_defconfig b/arch/v850/configs/sim_defconfig
index d73f5f9d8383..f31ba7398ad0 100644
--- a/arch/v850/configs/sim_defconfig
+++ b/arch/v850/configs/sim_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-uc0
-# Thu Jul 21 11:29:27 2005
+# Linux kernel version: 2.6.13-uc0
+# Fri Sep 2 13:36:43 2005
#
# CONFIG_MMU is not set
# CONFIG_UID16 is not set
@@ -36,6 +36,8 @@ CONFIG_NO_CACHE=y
CONFIG_ZERO_BSS=y
# CONFIG_RESET_GUARD is not set
CONFIG_LARGE_ALLOCS=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
#
# Code maturity level options
@@ -51,7 +53,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
@@ -99,6 +100,11 @@ CONFIG_BINFMT_FLAT=y
# CONFIG_BINFMT_MISC is not set
#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
# Generic Driver Options
#
CONFIG_STANDALONE=y
@@ -146,6 +152,7 @@ CONFIG_MTD_CFI_I2=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -213,6 +220,7 @@ CONFIG_IOSCHED_NOOP=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -223,9 +231,8 @@ CONFIG_IOSCHED_NOOP=y
#
#
-# Networking support
+# Network device support
#
-# CONFIG_NET is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -300,7 +307,6 @@ CONFIG_SERIO=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -324,6 +330,7 @@ CONFIG_SERIO=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -331,6 +338,8 @@ CONFIG_SERIO=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
+# CONFIG_MAGIC_ROM_PTR is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
diff --git a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-offsets.c
index 24f291369070..24f291369070 100644
--- a/arch/v850/kernel/asm-consts.c
+++ b/arch/v850/kernel/asm-offsets.c
diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
index 895e27b1d839..d991e4547dbb 100644
--- a/arch/v850/kernel/entry.S
+++ b/arch/v850/kernel/entry.S
@@ -22,7 +22,7 @@
#include <asm/irq.h>
#include <asm/errno.h>
-#include <asm/asm-consts.h>
+#include <asm/asm-offsets.h>
/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
index 336cbf21dc8f..9e85969ba976 100644
--- a/arch/v850/kernel/irq.c
+++ b/arch/v850/kernel/irq.c
@@ -67,13 +67,13 @@ static void ack_none(unsigned int irq)
#define end_none enable_none
struct hw_interrupt_type no_irq_type = {
- "none",
- startup_none,
- shutdown_none,
- enable_none,
- disable_none,
- ack_none,
- end_none
+ .typename = "none",
+ .startup = startup_none,
+ .shutdown = shutdown_none,
+ .enable = enable_none,
+ .disable = disable_none,
+ .ack = ack_none,
+ .end = end_none
};
volatile unsigned long irq_err_count, spurious_count;
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index c41d72b01b88..62bdb8d29fc0 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -1,8 +1,8 @@
/*
* arch/v850/kernel/setup.c -- Arch-dependent initialization functions
*
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
+ * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
@@ -98,10 +98,20 @@ void __init trap_init (void)
}
#ifdef CONFIG_MTD
+
+/* From drivers/mtd/devices/slram.c */
+#define SLRAM_BLK_SZ 0x4000
+
/* Set the root filesystem to be the given memory region.
Some parameter may be appended to CMD_LINE. */
void set_mem_root (void *addr, size_t len, char *cmd_line)
{
+ /* Some sort of idiocy in MTD means we must supply a length that's
+ a multiple of SLRAM_BLK_SZ. We just round up the real length,
+ as the file system shouldn't attempt to access anything beyond
+ the end of the image anyway. */
+ len = (((len - 1) + SLRAM_BLK_SZ) / SLRAM_BLK_SZ) * SLRAM_BLK_SZ;
+
/* The only way to pass info to the MTD slram driver is via
the command line. */
if (*cmd_line) {
@@ -128,13 +138,13 @@ static void nmi_end (unsigned irq)
}
static struct hw_interrupt_type nmi_irq_type = {
- "NMI",
- irq_zero, /* startup */
- irq_nop, /* shutdown */
- irq_nop, /* enable */
- irq_nop, /* disable */
- irq_nop, /* ack */
- nmi_end, /* end */
+ .typename = "NMI",
+ .startup = irq_zero, /* startup */
+ .shutdown = irq_nop, /* shutdown */
+ .enable = irq_nop, /* enable */
+ .disable = irq_nop, /* disable */
+ .ack = irq_nop, /* ack */
+ .end = nmi_end, /* end */
};
void __init init_IRQ (void)
@@ -284,3 +294,33 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
free_area_init_node (0, NODE_DATA(0), zones_size,
ADDR_TO_PAGE (PAGE_OFFSET), 0);
}
+
+
+
+/* Taken from m68knommu */
+void show_mem(void)
+{
+ unsigned long i;
+ int free = 0, total = 0, reserved = 0, shared = 0;
+ int cached = 0;
+
+ printk(KERN_INFO "\nMem-info:\n");
+ show_free_areas();
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (!page_count(mem_map+i))
+ free++;
+ else
+ shared += page_count(mem_map+i) - 1;
+ }
+ printk(KERN_INFO "%d pages of RAM\n",total);
+ printk(KERN_INFO "%d free pages\n",free);
+ printk(KERN_INFO "%d reserved pages\n",reserved);
+ printk(KERN_INFO "%d pages shared\n",shared);
+ printk(KERN_INFO "%d pages swap cached\n",cached);
+}
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
index 37061e32e1a4..633e4e1b825f 100644
--- a/arch/v850/kernel/signal.c
+++ b/arch/v850/kernel/signal.c
@@ -462,13 +462,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}
/*
diff --git a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c
index e2cc5580fa2a..17049aaa8f11 100644
--- a/arch/v850/kernel/sim.c
+++ b/arch/v850/kernel/sim.c
@@ -73,13 +73,13 @@ static void irq_nop (unsigned irq) { }
static unsigned irq_zero (unsigned irq) { return 0; }
static struct hw_interrupt_type sim_irq_type = {
- "IRQ",
- irq_zero, /* startup */
- irq_nop, /* shutdown */
- irq_nop, /* enable */
- irq_nop, /* disable */
- irq_nop, /* ack */
- irq_nop, /* end */
+ .typename = "IRQ",
+ .startup = irq_zero, /* startup */
+ .shutdown = irq_nop, /* shutdown */
+ .enable = irq_nop, /* enable */
+ .disable = irq_nop, /* disable */
+ .ack = irq_nop, /* ack */
+ .end = irq_nop, /* end */
};
void __init mach_init_irqs (void)
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index f722a268238a..ea3fd8844ff0 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -66,7 +66,7 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ 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) {
@@ -169,10 +169,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime () */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq (&xtime_lock);
clock_was_set();
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 660a03a89e66..e63323e03ea9 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -24,6 +24,10 @@ config X86
bool
default y
+config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
config MMU
bool
default y
@@ -61,6 +65,10 @@ config GENERIC_IOMAP
bool
default y
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ default y
+
source "init/Kconfig"
@@ -144,7 +152,6 @@ config X86_CPUID
with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
/dev/cpu/31/cpuid.
-# disable it for opteron optimized builds because it pulls in ACPI_BOOT
config X86_HT
bool
depends on SMP && !MK8
@@ -437,6 +444,11 @@ config ISA_DMA_API
bool
default y
+config GENERIC_PENDING_IRQ
+ bool
+ depends on GENERIC_HARDIRQS && SMP
+ default y
+
menu "Power management options"
source kernel/power/Kconfig
@@ -461,7 +473,6 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
depends on PCI && ACPI
- select ACPI_BOOT
config UNORDERED_IO
bool "Unordered IO mapping access"
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 4c6ed96d5f7c..a9cd42e61828 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -86,16 +86,6 @@ install fdimage fdimage144 fdimage288: vmlinux
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-prepare: include/asm-$(ARCH)/offset.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
- include/config/MARKER
-
-include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/offset.h
-
define archhelp
echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
echo ' install - Install kernel using'
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index f4399c701b77..18c6e915d69b 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -46,7 +46,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
- @echo 'Kernel: $@ is ready'
+ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index b38d5b8b5fb8..0e10fd84c7cc 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -83,7 +83,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
#endif
#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
-extern char input_data[];
+extern unsigned char input_data[];
extern int input_len;
static long bytes_out = 0;
@@ -288,7 +288,7 @@ void setup_normal_output_buffer(void)
#else
if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
#endif
- output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
+ output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
free_mem_end_ptr = (long)real_mode;
}
@@ -305,7 +305,7 @@ void setup_output_buffer_if_we_run_high(struct moveparams *mv)
#else
if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
#endif
- mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+ mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
index ff58b2832b75..12ea0b6c52e2 100644
--- a/arch/x86_64/boot/setup.S
+++ b/arch/x86_64/boot/setup.S
@@ -81,7 +81,7 @@ start:
# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
.ascii "HdrS" # header signature
- .word 0x0203 # header version number (>= 0x0105)
+ .word 0x0204 # header version number (>= 0x0105)
# or else old loadlin-1.5 will fail)
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
start_sys_seg: .word SYSSEG
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
index 18b5bac1c428..c44f5e2ec100 100644
--- a/arch/x86_64/boot/tools/build.c
+++ b/arch/x86_64/boot/tools/build.c
@@ -178,7 +178,9 @@ int main(int argc, char ** argv)
die("Output: seek failed");
buf[0] = (sys_size & 0xff);
buf[1] = ((sys_size >> 8) & 0xff);
- if (write(1, buf, 2) != 2)
+ buf[2] = ((sys_size >> 16) & 0xff);
+ buf[3] = ((sys_size >> 24) & 0xff);
+ if (write(1, buf, 4) != 4)
die("Write of image length failed");
return 0; /* Everything is OK */
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index b97a61e1c71c..f8db7e500fbf 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,11 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-git3
-# Fri Aug 12 16:40:34 2005
+# Linux kernel version: 2.6.13-git11
+# Mon Sep 12 16:16:16 2005
#
CONFIG_X86_64=y
CONFIG_64BIT=y
CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -13,6 +14,7 @@ CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
#
# Code maturity level options
@@ -26,6 +28,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
@@ -37,6 +40,7 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
@@ -102,6 +106,7 @@ CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_NR_CPUS=32
@@ -122,6 +127,7 @@ CONFIG_HZ=250
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
#
# Power management options
@@ -135,8 +141,6 @@ CONFIG_PM_STD_PARTITION=""
# ACPI (Advanced Configuration and Power Interface) Support
#
CONFIG_ACPI=y
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
@@ -151,10 +155,8 @@ CONFIG_ACPI_NUMA=y
CONFIG_ACPI_TOSHIBA=y
CONFIG_ACPI_BLACKLIST_YEAR=2001
# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_BUS=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_CONTAINER is not set
@@ -198,7 +200,6 @@ CONFIG_UNORDERED_IO=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -238,7 +239,10 @@ CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
@@ -248,8 +252,8 @@ CONFIG_IP_FIB_HASH=y
# 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=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
@@ -262,6 +266,11 @@ CONFIG_IPV6=y
# CONFIG_NETFILTER is not set
#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
@@ -284,9 +293,11 @@ CONFIG_IPV6=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK 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
@@ -333,7 +344,6 @@ 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 is not set
@@ -413,6 +423,7 @@ CONFIG_IDEDMA_AUTO=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
@@ -436,7 +447,7 @@ CONFIG_BLK_DEV_SD=y
#
# SCSI Transport Attributes
#
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
@@ -462,6 +473,7 @@ CONFIG_SCSI_SATA=y
# CONFIG_SCSI_SATA_AHCI is not set
# CONFIG_SCSI_SATA_SVW is not set
CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_MV is not set
# CONFIG_SCSI_SATA_NV is not set
# CONFIG_SCSI_SATA_PROMISE is not set
# CONFIG_SCSI_SATA_QSTOR is not set
@@ -541,6 +553,11 @@ CONFIG_TUN=y
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -590,6 +607,7 @@ CONFIG_E1000=y
# 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_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
@@ -599,6 +617,7 @@ CONFIG_TIGON3=y
#
# Ethernet (10000 Mbit)
#
+# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
@@ -753,7 +772,6 @@ CONFIG_MAX_RAW_DEVS=256
# I2C support
#
# CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
#
# Dallas's 1-wire bus
@@ -764,6 +782,7 @@ CONFIG_MAX_RAW_DEVS=256
# Hardware Monitoring support
#
CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -772,6 +791,10 @@ CONFIG_HWMON=y
# CONFIG_IBM_ASM is not set
#
+# Multimedia Capabilities Port drivers
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -862,9 +885,8 @@ CONFIG_USB_UHCI_HCD=y
#
# USB Device Class drivers
#
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
@@ -881,6 +903,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
#
# USB Input Devices
@@ -897,6 +920,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_MTOUCH is not set
# CONFIG_USB_ITMTOUCH is not set
# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
@@ -980,6 +1004,8 @@ CONFIG_USB_MON=y
# Firmware Drivers
#
# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+CONFIG_DCDBAS=m
#
# File systems
@@ -1004,10 +1030,6 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
# CONFIG_REISERFS_FS_SECURITY 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
@@ -1016,6 +1038,7 @@ CONFIG_INOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -1041,12 +1064,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -1078,6 +1100,7 @@ CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
@@ -1090,6 +1113,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
@@ -1154,6 +1178,7 @@ CONFIG_OPROFILE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1161,6 +1186,7 @@ CONFIG_LOG_BUF_SHIFT=18
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
+# CONFIG_FRAME_POINTER is not set
CONFIG_INIT_DEBUG=y
# CONFIG_IOMMU_DEBUG is not set
CONFIG_KPROBES=y
@@ -1184,5 +1210,6 @@ CONFIG_KPROBES=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
index d259f8a6f811..419758f19ca4 100644
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ b/arch/x86_64/ia32/ia32_ioctl.c
@@ -24,17 +24,26 @@
static int tiocgdev(unsigned fd, unsigned cmd, unsigned int __user *ptr)
{
- struct file *file = fget(fd);
+ struct file *file;
struct tty_struct *real_tty;
+ int fput_needed, ret;
+ file = fget_light(fd, &fput_needed);
if (!file)
return -EBADF;
+
+ ret = -EINVAL;
if (file->f_op->ioctl != tty_ioctl)
- return -EINVAL;
+ goto out;
real_tty = (struct tty_struct *)file->private_data;
if (!real_tty)
- return -EINVAL;
- return put_user(new_encode_dev(tty_devnum(real_tty)), ptr);
+ goto out;
+
+ ret = put_user(new_encode_dev(tty_devnum(real_tty)), ptr);
+
+out:
+ fput_light(file, fput_needed);
+ return ret;
}
#define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index c45d6a05b984..e0eb0c712fe9 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -6,7 +6,7 @@
#include <asm/dwarf2.h>
#include <asm/calling.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/current.h>
#include <asm/errno.h>
#include <asm/ia32_unistd.h>
@@ -55,20 +55,34 @@
* with the int 0x80 path.
*/
ENTRY(ia32_sysenter_target)
- CFI_STARTPROC
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,0
+ CFI_REGISTER rsp,rbp
swapgs
movq %gs:pda_kernelstack, %rsp
addq $(PDA_STACKOFFSET),%rsp
sti
movl %ebp,%ebp /* zero extension */
pushq $__USER32_DS
+ CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET ss,0*/
pushq %rbp
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rsp,0
pushfq
+ CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET rflags,0*/
movl $VSYSCALL32_SYSEXIT, %r10d
+ CFI_REGISTER rip,r10
pushq $__USER32_CS
+ CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET cs,0*/
movl %eax, %eax
pushq %r10
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rip,0
pushq %rax
+ CFI_ADJUST_CFA_OFFSET 8
cld
SAVE_ARGS 0,0,1
/* no need to do an access_ok check here because rbp has been
@@ -79,6 +93,7 @@ ENTRY(ia32_sysenter_target)
.previous
GET_THREAD_INFO(%r10)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+ CFI_REMEMBER_STATE
jnz sysenter_tracesys
sysenter_do_call:
cmpl $(IA32_NR_syscalls),%eax
@@ -94,14 +109,20 @@ sysenter_do_call:
andl $~0x200,EFLAGS-R11(%rsp)
RESTORE_ARGS 1,24,1,1,1,1
popfq
+ CFI_ADJUST_CFA_OFFSET -8
+ /*CFI_RESTORE rflags*/
popq %rcx /* User %esp */
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_REGISTER rsp,rcx
movl $VSYSCALL32_SYSEXIT,%edx /* User %eip */
+ CFI_REGISTER rip,rdx
swapgs
sti /* sti only takes effect after the next instruction */
/* sysexit */
.byte 0xf, 0x35
sysenter_tracesys:
+ CFI_RESTORE_STATE
SAVE_REST
CLEAR_RREGS
movq $-ENOSYS,RAX(%rsp) /* really needed? */
@@ -140,21 +161,28 @@ sysenter_tracesys:
* with the int 0x80 path.
*/
ENTRY(ia32_cstar_target)
- CFI_STARTPROC
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,0
+ CFI_REGISTER rip,rcx
+ /*CFI_REGISTER rflags,r11*/
swapgs
movl %esp,%r8d
+ CFI_REGISTER rsp,r8
movq %gs:pda_kernelstack,%rsp
sti
SAVE_ARGS 8,1,1
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
movq %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
movl %ebp,%ecx
movq $__USER32_CS,CS-ARGOFFSET(%rsp)
movq $__USER32_DS,SS-ARGOFFSET(%rsp)
movq %r11,EFLAGS-ARGOFFSET(%rsp)
+ /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
movq %r8,RSP-ARGOFFSET(%rsp)
+ CFI_REL_OFFSET rsp,RSP-ARGOFFSET
/* no need to do an access_ok check here because r8 has been
32bit zero extended */
/* hardware stack frame is complete now */
@@ -164,6 +192,7 @@ ENTRY(ia32_cstar_target)
.previous
GET_THREAD_INFO(%r10)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+ CFI_REMEMBER_STATE
jnz cstar_tracesys
cstar_do_call:
cmpl $IA32_NR_syscalls,%eax
@@ -177,12 +206,16 @@ cstar_do_call:
jnz int_ret_from_sys_call
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
movl RIP-ARGOFFSET(%rsp),%ecx
+ CFI_REGISTER rip,rcx
movl EFLAGS-ARGOFFSET(%rsp),%r11d
+ /*CFI_REGISTER rflags,r11*/
movl RSP-ARGOFFSET(%rsp),%esp
+ CFI_RESTORE rsp
swapgs
sysretl
cstar_tracesys:
+ CFI_RESTORE_STATE
SAVE_REST
CLEAR_RREGS
movq $-ENOSYS,RAX(%rsp) /* really needed? */
@@ -226,11 +259,18 @@ ia32_badarg:
*/
ENTRY(ia32_syscall)
- CFI_STARTPROC
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,SS+8-RIP
+ /*CFI_REL_OFFSET ss,SS-RIP*/
+ CFI_REL_OFFSET rsp,RSP-RIP
+ /*CFI_REL_OFFSET rflags,EFLAGS-RIP*/
+ /*CFI_REL_OFFSET cs,CS-RIP*/
+ CFI_REL_OFFSET rip,RIP-RIP
swapgs
sti
movl %eax,%eax
pushq %rax
+ CFI_ADJUST_CFA_OFFSET 8
cld
/* note the registers are not zero extended to the sf.
this could be a problem. */
@@ -278,6 +318,8 @@ quiet_ni_syscall:
jmp ia32_ptregs_common
.endm
+ CFI_STARTPROC
+
PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
@@ -290,8 +332,9 @@ quiet_ni_syscall:
PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
ENTRY(ia32_ptregs_common)
- CFI_STARTPROC
popq %r11
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_REGISTER rip, r11
SAVE_REST
call *%rax
RESTORE_REST
@@ -307,7 +350,7 @@ ia32_sys_call_table:
.quad stub32_fork
.quad sys_read
.quad sys_write
- .quad sys32_open /* 5 */
+ .quad compat_sys_open /* 5 */
.quad sys_close
.quad sys32_waitpid
.quad sys_creat
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index be996d1b691e..5389df610e78 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -751,7 +751,7 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
set_fs(old_fs);
- if (!ret && offset && put_user(of, offset))
+ if (offset && put_user(of, offset))
return -EFAULT;
return ret;
@@ -969,32 +969,6 @@ long sys32_kill(int pid, int sig)
return sys_kill(pid, sig);
}
-asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
-{
- char * tmp;
- int fd, error;
-
- /* don't force O_LARGEFILE */
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file *f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (IS_ERR(f)) {
- put_unused_fd(fd);
- fd = error;
- } else {
- fsnotify_open(f->f_dentry);
- fd_install(fd, f);
- }
- }
- putname(tmp);
- }
- return fd;
-}
-
extern asmlinkage long
sys_timer_create(clockid_t which_clock,
struct sigevent __user *timer_event_spec,
diff --git a/arch/x86_64/ia32/vsyscall-syscall.S b/arch/x86_64/ia32/vsyscall-syscall.S
index e2aaf3de8a42..b024965bb689 100644
--- a/arch/x86_64/ia32/vsyscall-syscall.S
+++ b/arch/x86_64/ia32/vsyscall-syscall.S
@@ -3,7 +3,7 @@
*/
#include <asm/ia32_unistd.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/segment.h>
.text
diff --git a/arch/x86_64/ia32/vsyscall-sysenter.S b/arch/x86_64/ia32/vsyscall-sysenter.S
index 8fb8e0ff3afa..71f3de586b56 100644
--- a/arch/x86_64/ia32/vsyscall-sysenter.S
+++ b/arch/x86_64/ia32/vsyscall-sysenter.S
@@ -3,7 +3,7 @@
*/
#include <asm/ia32_unistd.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
.text
.section .text.vsyscall,"ax"
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 48f9e2c19cd6..bcdd0a805fe7 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -4,15 +4,15 @@
extra-y := head.o head64.o init_task.o vmlinux.lds
EXTRA_AFLAGS := -traditional
-obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
+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
+ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o
obj-$(CONFIG_X86_MCE) += mce.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/
-obj-$(CONFIG_ACPI_BOOT) += acpi/
+obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
@@ -45,3 +45,5 @@ swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o
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
diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile
index d2c2ee5f9a88..7da9ace890bd 100644
--- a/arch/x86_64/kernel/acpi/Makefile
+++ b/arch/x86_64/kernel/acpi/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ACPI_BOOT) := boot.o
-boot-$(CONFIG_ACPI_BOOT) := ../../../i386/kernel/acpi/boot.o
+obj-y := boot.o
+boot-y := ../../../i386/kernel/acpi/boot.o
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index 7a275de6df22..867a0ebee177 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -34,7 +34,6 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/bootmem.h>
-#include <linux/irq.h>
#include <linux/acpi.h>
#include <asm/mpspec.h>
#include <asm/io.h>
@@ -47,7 +46,6 @@
#include <asm/proto.h>
#include <asm/tlbflush.h>
-
/* --------------------------------------------------------------------------
Low-Level Sleep Support
-------------------------------------------------------------------------- */
@@ -77,11 +75,12 @@ static void init_low_mapping(void)
* Create an identity mapped page table and copy the wakeup routine to
* low memory.
*/
-int acpi_save_state_mem (void)
+int acpi_save_state_mem(void)
{
init_low_mapping();
- memcpy((void *) acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);
+ memcpy((void *)acpi_wakeup_address, &wakeup_start,
+ &wakeup_end - &wakeup_start);
acpi_copy_wakeup_routine(acpi_wakeup_address);
return 0;
@@ -90,7 +89,7 @@ int acpi_save_state_mem (void)
/*
* acpi_restore_state
*/
-void acpi_restore_state_mem (void)
+void acpi_restore_state_mem(void)
{
set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
flush_tlb_all();
@@ -108,7 +107,8 @@ void __init acpi_reserve_bootmem(void)
{
acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
if ((&wakeup_end - &wakeup_start) > PAGE_SIZE)
- printk(KERN_CRIT "ACPI: Wakeup code way too big, will crash on attempt to suspend\n");
+ printk(KERN_CRIT
+ "ACPI: Wakeup code way too big, will crash on attempt to suspend\n");
}
static int __init acpi_sleep_setup(char *str)
@@ -127,6 +127,8 @@ static int __init acpi_sleep_setup(char *str)
__setup("acpi_sleep=", acpi_sleep_setup);
-#endif /*CONFIG_ACPI_SLEEP*/
+#endif /*CONFIG_ACPI_SLEEP */
-void acpi_pci_link_exit(void) {}
+void acpi_pci_link_exit(void)
+{
+}
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index c9a6b812e926..962ad4823b6a 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -245,6 +245,8 @@ void __init iommu_hole_init(void)
if (aper_alloc) {
/* Got the aperture from the AGP bridge */
+ } else if (swiotlb && !valid_agp) {
+ /* Do nothing */
} else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
force_iommu ||
valid_agp ||
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 375d369570ca..b6e7715d877f 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -18,7 +18,6 @@
#include <linux/init.h>
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
@@ -109,11 +108,8 @@ void clear_local_APIC(void)
if (maxlvt >= 4)
apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
v = GET_APIC_VERSION(apic_read(APIC_LVR));
- if (APIC_INTEGRATED(v)) { /* !82489DX */
- if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
- apic_write(APIC_ESR, 0);
- apic_read(APIC_ESR);
- }
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
}
void __init connect_bsp_APIC(void)
@@ -316,8 +312,6 @@ void __init init_bsp_APIC(void)
*/
apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
value = APIC_DM_NMI;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
apic_write_around(APIC_LVT1, value);
}
@@ -325,14 +319,6 @@ void __cpuinit setup_local_APIC (void)
{
unsigned int value, ver, maxlvt;
- /* Pound the ESR really hard over the head with a big hammer - mbligh */
- if (esr_disable) {
- apic_write(APIC_ESR, 0);
- apic_write(APIC_ESR, 0);
- apic_write(APIC_ESR, 0);
- apic_write(APIC_ESR, 0);
- }
-
value = apic_read(APIC_LVR);
ver = GET_APIC_VERSION(value);
@@ -430,15 +416,11 @@ void __cpuinit setup_local_APIC (void)
value = APIC_DM_NMI;
else
value = APIC_DM_NMI | APIC_LVT_MASKED;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
apic_write_around(APIC_LVT1, value);
- if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */
+ {
unsigned oldvalue;
maxlvt = get_maxlvt();
- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
- apic_write(APIC_ESR, 0);
oldvalue = apic_read(APIC_ESR);
value = ERROR_APIC_VECTOR; // enables sending errors
apic_write_around(APIC_LVTERR, value);
@@ -452,17 +434,6 @@ void __cpuinit setup_local_APIC (void)
apic_printk(APIC_VERBOSE,
"ESR value after enabling vector: %08x, after %08x\n",
oldvalue, value);
- } else {
- if (esr_disable)
- /*
- * Something untraceble is creating bad interrupts on
- * secondary quads ... for the moment, just leave the
- * ESR disabled - we can't do anything useful with the
- * errors anyway - mbligh
- */
- apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
- else
- apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
}
nmi_watchdog_default();
@@ -650,8 +621,7 @@ void __init init_apic_mappings(void)
* Fetch the APIC ID of the BSP in case we have a
* default configuration (or the MP table is broken).
*/
- if (boot_cpu_id == -1U)
- boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+ boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
#ifdef CONFIG_X86_IO_APIC
{
@@ -693,8 +663,6 @@ static void __setup_APIC_LVTT(unsigned int clocks)
ver = GET_APIC_VERSION(apic_read(APIC_LVR));
lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
- if (!APIC_INTEGRATED(ver))
- lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
apic_write_around(APIC_LVTT, lvtt_value);
/*
@@ -1081,7 +1049,7 @@ int __init APIC_init_uniprocessor (void)
connect_bsp_APIC();
- phys_cpu_present_map = physid_mask_of_physid(0);
+ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
apic_write_around(APIC_ID, boot_cpu_id);
setup_local_APIC();
diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
index 35b4c3fcbb37..aaa6d3833517 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -39,7 +39,6 @@ int main(void)
ENTRY(kernelstack);
ENTRY(oldrsp);
ENTRY(pcurrent);
- ENTRY(irqrsp);
ENTRY(irqcount);
ENTRY(cpunumber);
ENTRY(irqstackptr);
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index d7fa4248501c..535e04466079 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -11,7 +11,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
-#include <linux/irq.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index b548dea4e5b9..eb7929eea7b3 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -85,7 +85,7 @@ int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
struct e820entry *ei = &e820.map[i];
if (type && ei->type != type)
continue;
- if (ei->addr >= end || ei->addr + ei->size < start)
+ if (ei->addr >= end || ei->addr + ei->size <= start)
continue;
return 1;
}
@@ -131,7 +131,7 @@ void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned lon
if (ei->type != E820_RAM ||
ei->addr+ei->size <= start ||
- ei->addr > end)
+ ei->addr >= end)
continue;
addr = round_up(ei->addr, PAGE_SIZE);
@@ -567,7 +567,7 @@ unsigned long pci_mem_start = 0xaeedbabe;
*/
__init void e820_setup_gap(void)
{
- unsigned long gapstart, gapsize;
+ unsigned long gapstart, gapsize, round;
unsigned long last;
int i;
int found = 0;
@@ -604,14 +604,14 @@ __init void e820_setup_gap(void)
}
/*
- * Start allocating dynamic PCI memory a bit into the gap,
- * aligned up to the nearest megabyte.
- *
- * Question: should we try to pad it up a bit (do something
- * like " + (gapsize >> 3)" in there too?). We now have the
- * technology.
+ * See how much we want to round up: start off with
+ * rounding to the next 1MB area.
*/
- pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+ round = 0x100000;
+ while ((gapsize >> 4) > round)
+ round += round;
+ /* Fun with two's complement */
+ pci_mem_start = (gapstart + round) & -round;
printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
pci_mem_start, gapstart, gapsize);
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 9631c747c5e3..9cd968dd0f5a 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -5,6 +5,7 @@
#include <linux/tty.h>
#include <asm/io.h>
#include <asm/processor.h>
+#include <asm/fcntl.h>
/* Simple VGA output */
@@ -158,6 +159,47 @@ static struct console early_serial_console = {
.index = -1,
};
+/* Console interface to a host file on AMD's SimNow! */
+
+static int simnow_fd;
+
+enum {
+ MAGIC1 = 0xBACCD00A,
+ MAGIC2 = 0xCA110000,
+ XOPEN = 5,
+ XWRITE = 4,
+};
+
+static noinline long simnow(long cmd, long a, long b, long c)
+{
+ long ret;
+ asm volatile("cpuid" :
+ "=a" (ret) :
+ "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+ return ret;
+}
+
+void __init simnow_init(char *str)
+{
+ char *fn = "klog";
+ if (*str == '=')
+ fn = ++str;
+ /* error ignored */
+ simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
+}
+
+static void simnow_write(struct console *con, const char *s, unsigned n)
+{
+ simnow(XWRITE, simnow_fd, (unsigned long)s, n);
+}
+
+static struct console simnow_console = {
+ .name = "simnow",
+ .write = simnow_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
/* Direct interface for emergencies */
struct console *early_console = &early_vga_console;
static int early_console_initialized = 0;
@@ -205,6 +247,10 @@ int __init setup_early_printk(char *opt)
max_xpos = SCREEN_INFO.orig_video_cols;
max_ypos = SCREEN_INFO.orig_video_lines;
early_console = &early_vga_console;
+ } else if (!strncmp(buf, "simnow", 6)) {
+ simnow_init(buf + 6);
+ early_console = &simnow_console;
+ keep_early = 1;
}
early_console_initialized = 1;
register_console(early_console);
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 096d470e280f..7937971d1853 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -36,7 +36,7 @@
#include <asm/errno.h>
#include <asm/dwarf2.h>
#include <asm/calling.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/msr.h>
#include <asm/unistd.h>
#include <asm/thread_info.h>
@@ -79,16 +79,19 @@
xorl %eax, %eax
pushq %rax /* ss */
CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET ss,0*/
pushq %rax /* rsp */
CFI_ADJUST_CFA_OFFSET 8
- CFI_OFFSET rip,0
+ CFI_REL_OFFSET rsp,0
pushq $(1<<9) /* eflags - interrupts on */
CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET rflags,0*/
pushq $__KERNEL_CS /* cs */
CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET cs,0*/
pushq \child_rip /* rip */
CFI_ADJUST_CFA_OFFSET 8
- CFI_OFFSET rip,0
+ CFI_REL_OFFSET rip,0
pushq %rax /* orig rax */
CFI_ADJUST_CFA_OFFSET 8
.endm
@@ -98,32 +101,39 @@
CFI_ADJUST_CFA_OFFSET -(6*8)
.endm
- .macro CFI_DEFAULT_STACK
- CFI_ADJUST_CFA_OFFSET (SS)
- CFI_OFFSET r15,R15-SS
- CFI_OFFSET r14,R14-SS
- CFI_OFFSET r13,R13-SS
- CFI_OFFSET r12,R12-SS
- CFI_OFFSET rbp,RBP-SS
- CFI_OFFSET rbx,RBX-SS
- CFI_OFFSET r11,R11-SS
- CFI_OFFSET r10,R10-SS
- CFI_OFFSET r9,R9-SS
- CFI_OFFSET r8,R8-SS
- CFI_OFFSET rax,RAX-SS
- CFI_OFFSET rcx,RCX-SS
- CFI_OFFSET rdx,RDX-SS
- CFI_OFFSET rsi,RSI-SS
- CFI_OFFSET rdi,RDI-SS
- CFI_OFFSET rsp,RSP-SS
- CFI_OFFSET rip,RIP-SS
+ .macro CFI_DEFAULT_STACK start=1
+ .if \start
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,SS+8
+ .else
+ CFI_DEF_CFA_OFFSET SS+8
+ .endif
+ CFI_REL_OFFSET r15,R15
+ CFI_REL_OFFSET r14,R14
+ CFI_REL_OFFSET r13,R13
+ CFI_REL_OFFSET r12,R12
+ CFI_REL_OFFSET rbp,RBP
+ CFI_REL_OFFSET rbx,RBX
+ CFI_REL_OFFSET r11,R11
+ CFI_REL_OFFSET r10,R10
+ CFI_REL_OFFSET r9,R9
+ CFI_REL_OFFSET r8,R8
+ CFI_REL_OFFSET rax,RAX
+ CFI_REL_OFFSET rcx,RCX
+ CFI_REL_OFFSET rdx,RDX
+ CFI_REL_OFFSET rsi,RSI
+ CFI_REL_OFFSET rdi,RDI
+ CFI_REL_OFFSET rip,RIP
+ /*CFI_REL_OFFSET cs,CS*/
+ /*CFI_REL_OFFSET rflags,EFLAGS*/
+ CFI_REL_OFFSET rsp,RSP
+ /*CFI_REL_OFFSET ss,SS*/
.endm
/*
* A newly forked process directly context switches into this.
*/
/* rdi: prev */
ENTRY(ret_from_fork)
- CFI_STARTPROC
CFI_DEFAULT_STACK
call schedule_tail
GET_THREAD_INFO(%rcx)
@@ -172,16 +182,21 @@ rff_trace:
*/
ENTRY(system_call)
- CFI_STARTPROC
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,0
+ CFI_REGISTER rip,rcx
+ /*CFI_REGISTER rflags,r11*/
swapgs
movq %rsp,%gs:pda_oldrsp
movq %gs:pda_kernelstack,%rsp
sti
SAVE_ARGS 8,1
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
- movq %rcx,RIP-ARGOFFSET(%rsp)
+ movq %rcx,RIP-ARGOFFSET(%rsp)
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
GET_THREAD_INFO(%rcx)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+ CFI_REMEMBER_STATE
jnz tracesys
cmpq $__NR_syscall_max,%rax
ja badsys
@@ -201,9 +216,12 @@ sysret_check:
cli
movl threadinfo_flags(%rcx),%edx
andl %edi,%edx
+ CFI_REMEMBER_STATE
jnz sysret_careful
movq RIP-ARGOFFSET(%rsp),%rcx
+ CFI_REGISTER rip,rcx
RESTORE_ARGS 0,-ARG_SKIP,1
+ /*CFI_REGISTER rflags,r11*/
movq %gs:pda_oldrsp,%rsp
swapgs
sysretq
@@ -211,12 +229,15 @@ sysret_check:
/* Handle reschedules */
/* edx: work, edi: workmask */
sysret_careful:
+ CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc sysret_signal
sti
pushq %rdi
+ CFI_ADJUST_CFA_OFFSET 8
call schedule
popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
jmp sysret_check
/* Handle a signal */
@@ -234,8 +255,13 @@ sysret_signal:
1: movl $_TIF_NEED_RESCHED,%edi
jmp sysret_check
+badsys:
+ movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+ jmp ret_from_sys_call
+
/* Do syscall tracing */
tracesys:
+ CFI_RESTORE_STATE
SAVE_REST
movq $-ENOSYS,RAX(%rsp)
FIXUP_TOP_OF_STACK %rdi
@@ -254,16 +280,29 @@ tracesys:
RESTORE_TOP_OF_STACK %rbx
RESTORE_REST
jmp ret_from_sys_call
+ CFI_ENDPROC
-badsys:
- movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
- jmp ret_from_sys_call
-
/*
* Syscall return path ending with IRET.
* Has correct top of stack, but partial stack frame.
*/
-ENTRY(int_ret_from_sys_call)
+ENTRY(int_ret_from_sys_call)
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,SS+8-ARGOFFSET
+ /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
+ CFI_REL_OFFSET rsp,RSP-ARGOFFSET
+ /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
+ /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
+ CFI_REL_OFFSET rdx,RDX-ARGOFFSET
+ CFI_REL_OFFSET rcx,RCX-ARGOFFSET
+ CFI_REL_OFFSET rax,RAX-ARGOFFSET
+ CFI_REL_OFFSET rdi,RDI-ARGOFFSET
+ CFI_REL_OFFSET rsi,RSI-ARGOFFSET
+ CFI_REL_OFFSET r8,R8-ARGOFFSET
+ CFI_REL_OFFSET r9,R9-ARGOFFSET
+ CFI_REL_OFFSET r10,R10-ARGOFFSET
+ CFI_REL_OFFSET r11,R11-ARGOFFSET
cli
testl $3,CS-ARGOFFSET(%rsp)
je retint_restore_args
@@ -284,8 +323,10 @@ int_careful:
jnc int_very_careful
sti
pushq %rdi
+ CFI_ADJUST_CFA_OFFSET 8
call schedule
popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
cli
jmp int_with_check
@@ -297,9 +338,11 @@ int_very_careful:
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
jz int_signal
pushq %rdi
+ CFI_ADJUST_CFA_OFFSET 8
leaq 8(%rsp),%rdi # &ptregs -> arg1
call syscall_trace_leave
popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
cli
jmp int_restore_rest
@@ -329,6 +372,8 @@ int_restore_rest:
jmp ptregscall_common
.endm
+ CFI_STARTPROC
+
PTREGSCALL stub_clone, sys_clone, %r8
PTREGSCALL stub_fork, sys_fork, %rdi
PTREGSCALL stub_vfork, sys_vfork, %rdi
@@ -337,40 +382,49 @@ int_restore_rest:
PTREGSCALL stub_iopl, sys_iopl, %rsi
ENTRY(ptregscall_common)
- CFI_STARTPROC
popq %r11
- CFI_ADJUST_CFA_OFFSET -8
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_REGISTER rip, r11
SAVE_REST
movq %r11, %r15
+ CFI_REGISTER rip, r15
FIXUP_TOP_OF_STACK %r11
call *%rax
RESTORE_TOP_OF_STACK %r11
movq %r15, %r11
+ CFI_REGISTER rip, r11
RESTORE_REST
pushq %r11
- CFI_ADJUST_CFA_OFFSET 8
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rip, 0
ret
CFI_ENDPROC
ENTRY(stub_execve)
CFI_STARTPROC
popq %r11
- CFI_ADJUST_CFA_OFFSET -8
+ 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
- push %r11
+ pushq %r11
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rip, 0
ret
exec_32bit:
- CFI_ADJUST_CFA_OFFSET REST_SKIP
+ CFI_RESTORE_STATE
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
@@ -382,7 +436,8 @@ exec_32bit:
*/
ENTRY(stub_rt_sigreturn)
CFI_STARTPROC
- addq $8, %rsp
+ addq $8, %rsp
+ CFI_ADJUST_CFA_OFFSET -8
SAVE_REST
movq %rsp,%rdi
FIXUP_TOP_OF_STACK %r11
@@ -392,6 +447,25 @@ ENTRY(stub_rt_sigreturn)
jmp int_ret_from_sys_call
CFI_ENDPROC
+/*
+ * initial frame state for interrupts and exceptions
+ */
+ .macro _frame ref
+ CFI_STARTPROC simple
+ CFI_DEF_CFA rsp,SS+8-\ref
+ /*CFI_REL_OFFSET ss,SS-\ref*/
+ CFI_REL_OFFSET rsp,RSP-\ref
+ /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+ /*CFI_REL_OFFSET cs,CS-\ref*/
+ CFI_REL_OFFSET rip,RIP-\ref
+ .endm
+
+/* initial frame state for interrupts (and exceptions without error code) */
+#define INTR_FRAME _frame RIP
+/* initial frame state for exceptions with error code (and interrupts with
+ vector already pushed) */
+#define XCPT_FRAME _frame ORIG_RAX
+
/*
* Interrupt entry/exit.
*
@@ -402,10 +476,6 @@ ENTRY(stub_rt_sigreturn)
/* 0(%rsp): interrupt number */
.macro interrupt func
- CFI_STARTPROC simple
- CFI_DEF_CFA rsp,(SS-RDI)
- CFI_REL_OFFSET rsp,(RSP-ORIG_RAX)
- CFI_REL_OFFSET rip,(RIP-ORIG_RAX)
cld
#ifdef CONFIG_DEBUG_INFO
SAVE_ALL
@@ -425,23 +495,27 @@ ENTRY(stub_rt_sigreturn)
swapgs
1: incl %gs:pda_irqcount # RED-PEN should check preempt count
movq %gs:pda_irqstackptr,%rax
- cmoveq %rax,%rsp
+ cmoveq %rax,%rsp /*todo This needs CFI annotation! */
pushq %rdi # save old stack
+ CFI_ADJUST_CFA_OFFSET 8
call \func
.endm
ENTRY(common_interrupt)
+ XCPT_FRAME
interrupt do_IRQ
/* 0(%rsp): oldrsp-ARGOFFSET */
-ret_from_intr:
+ret_from_intr:
popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
cli
decl %gs:pda_irqcount
#ifdef CONFIG_DEBUG_INFO
movq RBP(%rdi),%rbp
+ CFI_DEF_CFA_REGISTER rsp
#endif
- leaq ARGOFFSET(%rdi),%rsp
-exit_intr:
+ leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
+exit_intr:
GET_THREAD_INFO(%rcx)
testl $3,CS-ARGOFFSET(%rsp)
je retint_kernel
@@ -453,9 +527,10 @@ exit_intr:
*/
retint_with_reschedule:
movl $_TIF_WORK_MASK,%edi
-retint_check:
+retint_check:
movl threadinfo_flags(%rcx),%edx
andl %edi,%edx
+ CFI_REMEMBER_STATE
jnz retint_careful
retint_swapgs:
swapgs
@@ -476,14 +551,17 @@ bad_iret:
jmp do_exit
.previous
- /* edi: workmask, edx: work */
+ /* edi: workmask, edx: work */
retint_careful:
+ CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc retint_signal
sti
pushq %rdi
+ CFI_ADJUST_CFA_OFFSET 8
call schedule
popq %rdi
+ CFI_ADJUST_CFA_OFFSET -8
GET_THREAD_INFO(%rcx)
cli
jmp retint_check
@@ -523,7 +601,9 @@ retint_kernel:
* APIC interrupts.
*/
.macro apicinterrupt num,func
+ INTR_FRAME
pushq $\num-256
+ CFI_ADJUST_CFA_OFFSET 8
interrupt \func
jmp ret_from_intr
CFI_ENDPROC
@@ -536,8 +616,19 @@ ENTRY(thermal_interrupt)
ENTRY(reschedule_interrupt)
apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
-ENTRY(invalidate_interrupt)
- apicinterrupt INVALIDATE_TLB_VECTOR,smp_invalidate_interrupt
+ .macro INVALIDATE_ENTRY num
+ENTRY(invalidate_interrupt\num)
+ apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
+ .endm
+
+ INVALIDATE_ENTRY 0
+ INVALIDATE_ENTRY 1
+ INVALIDATE_ENTRY 2
+ INVALIDATE_ENTRY 3
+ INVALIDATE_ENTRY 4
+ INVALIDATE_ENTRY 5
+ INVALIDATE_ENTRY 6
+ INVALIDATE_ENTRY 7
ENTRY(call_function_interrupt)
apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
@@ -558,16 +649,23 @@ ENTRY(spurious_interrupt)
* Exception entry points.
*/
.macro zeroentry sym
+ INTR_FRAME
pushq $0 /* push error code/oldrax */
+ CFI_ADJUST_CFA_OFFSET 8
pushq %rax /* push real oldrax to the rdi slot */
+ CFI_ADJUST_CFA_OFFSET 8
leaq \sym(%rip),%rax
jmp error_entry
+ CFI_ENDPROC
.endm
.macro errorentry sym
+ XCPT_FRAME
pushq %rax
+ CFI_ADJUST_CFA_OFFSET 8
leaq \sym(%rip),%rax
jmp error_entry
+ CFI_ENDPROC
.endm
/* error code is on the stack already */
@@ -594,10 +692,7 @@ ENTRY(spurious_interrupt)
* and the exception handler in %rax.
*/
ENTRY(error_entry)
- CFI_STARTPROC simple
- CFI_DEF_CFA rsp,(SS-RDI)
- CFI_REL_OFFSET rsp,(RSP-RDI)
- CFI_REL_OFFSET rip,(RIP-RDI)
+ _frame RDI
/* rdi slot contains rax, oldrax contains error code */
cld
subq $14*8,%rsp
@@ -679,7 +774,9 @@ error_kernelspace:
/* Reload gs selector with exception handling */
/* edi: new selector */
ENTRY(load_gs_index)
+ CFI_STARTPROC
pushf
+ CFI_ADJUST_CFA_OFFSET 8
cli
swapgs
gs_change:
@@ -687,7 +784,9 @@ gs_change:
2: mfence /* workaround */
swapgs
popf
+ CFI_ADJUST_CFA_OFFSET -8
ret
+ CFI_ENDPROC
.section __ex_table,"a"
.align 8
@@ -784,8 +883,9 @@ ENTRY(execve)
ret
CFI_ENDPROC
-ENTRY(page_fault)
+KPROBE_ENTRY(page_fault)
errorentry do_page_fault
+ .previous .text
ENTRY(coprocessor_error)
zeroentry do_coprocessor_error
@@ -797,19 +897,20 @@ ENTRY(device_not_available)
zeroentry math_state_restore
/* runs on exception stack */
-ENTRY(debug)
- CFI_STARTPROC
+KPROBE_ENTRY(debug)
+ INTR_FRAME
pushq $0
CFI_ADJUST_CFA_OFFSET 8
paranoidentry do_debug
jmp paranoid_exit
CFI_ENDPROC
+ .previous .text
/* runs on exception stack */
ENTRY(nmi)
- CFI_STARTPROC
+ INTR_FRAME
pushq $-1
- CFI_ADJUST_CFA_OFFSET 8
+ CFI_ADJUST_CFA_OFFSET 8
paranoidentry do_nmi
/*
* "Paranoid" exit path from exception stack.
@@ -854,8 +955,9 @@ paranoid_schedule:
jmp paranoid_userspace
CFI_ENDPROC
-ENTRY(int3)
+KPROBE_ENTRY(int3)
zeroentry do_int3
+ .previous .text
ENTRY(overflow)
zeroentry do_overflow
@@ -874,7 +976,7 @@ ENTRY(reserved)
/* runs on exception stack */
ENTRY(double_fault)
- CFI_STARTPROC
+ XCPT_FRAME
paranoidentry do_double_fault
jmp paranoid_exit
CFI_ENDPROC
@@ -887,13 +989,14 @@ ENTRY(segment_not_present)
/* runs on exception stack */
ENTRY(stack_segment)
- CFI_STARTPROC
+ XCPT_FRAME
paranoidentry do_stack_segment
jmp paranoid_exit
CFI_ENDPROC
-ENTRY(general_protection)
+KPROBE_ENTRY(general_protection)
errorentry do_general_protection
+ .previous .text
ENTRY(alignment_check)
errorentry do_alignment_check
@@ -907,7 +1010,7 @@ ENTRY(spurious_interrupt_bug)
#ifdef CONFIG_X86_MCE
/* runs on exception stack */
ENTRY(machine_check)
- CFI_STARTPROC
+ INTR_FRAME
pushq $0
CFI_ADJUST_CFA_OFFSET 8
paranoidentry do_machine_check
@@ -919,14 +1022,19 @@ ENTRY(call_debug)
zeroentry do_call_debug
ENTRY(call_softirq)
+ CFI_STARTPROC
movq %gs:pda_irqstackptr,%rax
pushq %r15
+ CFI_ADJUST_CFA_OFFSET 8
movq %rsp,%r15
+ CFI_DEF_CFA_REGISTER r15
incl %gs:pda_irqcount
cmove %rax,%rsp
call __do_softirq
movq %r15,%rsp
+ CFI_DEF_CFA_REGISTER rsp
decl %gs:pda_irqcount
popq %r15
+ CFI_ADJUST_CFA_OFFSET -8
ret
-
+ CFI_ENDPROC
diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c
index 30c843a5efdd..7a64ea181788 100644
--- a/arch/x86_64/kernel/genapic.c
+++ b/arch/x86_64/kernel/genapic.c
@@ -20,12 +20,12 @@
#include <asm/smp.h>
#include <asm/ipi.h>
-#if defined(CONFIG_ACPI_BUS)
+#if defined(CONFIG_ACPI)
#include <acpi/acpi_bus.h>
#endif
/* which logical CPU number maps to which CPU (physical APIC ID) */
-u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
EXPORT_SYMBOL(x86_cpu_to_apicid);
u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
@@ -45,9 +45,9 @@ void __init clustered_apic_check(void)
u8 clusters, max_cluster;
u8 id;
u8 cluster_cnt[NUM_APIC_CLUSTERS];
- int num_cpus = 0;
+ int max_apic = 0;
-#if defined(CONFIG_ACPI_BUS)
+#if defined(CONFIG_ACPI)
/*
* Some x86_64 machines use physical APIC mode regardless of how many
* procs/clusters are present (x86_64 ES7000 is an example).
@@ -64,14 +64,15 @@ void __init clustered_apic_check(void)
id = bios_cpu_apicid[i];
if (id == BAD_APICID)
continue;
- num_cpus++;
+ if (id > max_apic)
+ max_apic = id;
cluster_cnt[APIC_CLUSTERID(id)]++;
}
/* Don't use clustered mode on AMD platforms. */
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
genapic = &apic_physflat;
-#ifndef CONFIG_CPU_HOTPLUG
+#ifndef CONFIG_HOTPLUG_CPU
/* In the CPU hotplug case we cannot use broadcast mode
because that opens a race when a CPU is removed.
Stay at physflat mode in this case.
@@ -79,7 +80,7 @@ void __init clustered_apic_check(void)
we have ACPI platform support for CPU hotplug
we should detect hotplug capablity from ACPI tables and
only do this when really needed. -AK */
- if (num_cpus <= 8)
+ if (max_apic <= 8)
genapic = &apic_flat;
#endif
goto print;
@@ -103,9 +104,14 @@ void __init clustered_apic_check(void)
* (We don't use lowest priority delivery + HW APIC IRQ steering, so
* can ignore the clustered logical case and go straight to physical.)
*/
- if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
+ if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Don't use APIC shortcuts in CPU hotplug to avoid races */
+ genapic = &apic_physflat;
+#else
genapic = &apic_flat;
- else
+#endif
+ } else
genapic = &apic_cluster;
print:
diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
index 9703da7202e3..a472d62f899a 100644
--- a/arch/x86_64/kernel/genapic_cluster.c
+++ b/arch/x86_64/kernel/genapic_cluster.c
@@ -51,10 +51,10 @@ static void cluster_init_apic_ldr(void)
count = 3;
id = my_cluster | (1UL << count);
x86_cpu_to_log_apicid[smp_processor_id()] = id;
- apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+ apic_write(APIC_DFR, APIC_DFR_CLUSTER);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(id);
- apic_write_around(APIC_LDR, val);
+ apic_write(APIC_LDR, val);
}
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
@@ -72,10 +72,14 @@ static void cluster_send_IPI_mask(cpumask_t mask, int vector)
static void cluster_send_IPI_allbutself(int vector)
{
cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
+ int me = get_cpu(); /* Ensure we are not preempted when we clear */
+
+ cpu_clear(me, mask);
if (!cpus_empty(mask))
cluster_send_IPI_mask(mask, vector);
+
+ put_cpu();
}
static void cluster_send_IPI_all(int vector)
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index adc96282a9e2..9da3edb799ea 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -38,10 +38,10 @@ static void flat_init_apic_ldr(void)
num = smp_processor_id();
id = 1UL << num;
x86_cpu_to_log_apicid[num] = id;
- apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+ apic_write(APIC_DFR, APIC_DFR_FLAT);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(id);
- apic_write_around(APIC_LDR, val);
+ apic_write(APIC_LDR, val);
}
static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
@@ -62,7 +62,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
* prepare target chip field
*/
cfg = __prepare_ICR2(mask);
- apic_write_around(APIC_ICR2, cfg);
+ apic_write(APIC_ICR2, cfg);
/*
* program the ICR
@@ -72,14 +72,24 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
- apic_write_around(APIC_ICR, cfg);
+ apic_write(APIC_ICR, cfg);
local_irq_restore(flags);
}
static void flat_send_IPI_allbutself(int vector)
{
+#ifndef CONFIG_HOTPLUG_CPU
if (((num_online_cpus()) - 1) >= 1)
__send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL);
+#else
+ cpumask_t allbutme = cpu_online_map;
+ int me = get_cpu(); /* Ensure we are not preempted when we clear */
+ cpu_clear(me, allbutme);
+
+ if (!cpus_empty(allbutme))
+ flat_send_IPI_mask(allbutme, vector);
+ put_cpu();
+#endif
}
static void flat_send_IPI_all(int vector)
@@ -167,9 +177,9 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
struct genapic apic_physflat = {
.name = "physical flat",
- .int_delivery_mode = dest_LowestPrio,
+ .int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
- .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST,
+ .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
.target_cpus = physflat_target_cpus,
.apic_id_registered = flat_apic_id_registered,
.init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 98ff5eb32b9a..4592bf21fcaf 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -270,7 +270,7 @@ ENTRY(level3_kernel_pgt)
.org 0x4000
ENTRY(level2_ident_pgt)
/* 40MB for bootup. */
- .quad 0x0000000000000283
+ .quad 0x0000000000000183
.quad 0x0000000000200183
.quad 0x0000000000400183
.quad 0x0000000000600183
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index a89169095129..b2a238b5a17e 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -18,15 +18,12 @@
#include <asm/atomic.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/pgtable.h>
#include <asm/delay.h>
#include <asm/desc.h>
#include <asm/apic.h>
-#include <linux/irq.h>
-
/*
* Common place to define all x86 IRQ vectors
*
@@ -486,7 +483,14 @@ void spurious_interrupt(void);
void error_interrupt(void);
void reschedule_interrupt(void);
void call_function_interrupt(void);
-void invalidate_interrupt(void);
+void invalidate_interrupt0(void);
+void invalidate_interrupt1(void);
+void invalidate_interrupt2(void);
+void invalidate_interrupt3(void);
+void invalidate_interrupt4(void);
+void invalidate_interrupt5(void);
+void invalidate_interrupt6(void);
+void invalidate_interrupt7(void);
void thermal_interrupt(void);
void i8254_timer_resume(void);
@@ -562,8 +566,15 @@ void __init init_IRQ(void)
*/
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
- /* IPI for invalidation */
- set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+ /* IPIs for invalidation */
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
+ set_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index c4dc91491157..e0ba5c1043fd 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -44,6 +44,6 @@ EXPORT_SYMBOL(init_task);
* section. Since TSS's are completely CPU-local, we want them
* on exact cacheline boundaries, to eliminate cacheline ping-pong.
*/
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d206d7e49cf5..522944a000ad 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -21,7 +21,6 @@
*/
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -45,6 +44,8 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
static int no_timer_check;
+int disable_timer_pin_1 __initdata;
+
static DEFINE_SPINLOCK(ioapic_lock);
/*
@@ -70,7 +71,7 @@ static struct irq_pin_list {
short apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
-int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
#ifdef CONFIG_PCI_MSI
#define vector_to_irq(vector) \
(platform_legacy_irq(vector) ? vector : vector_irq[vector])
@@ -78,6 +79,54 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
#define vector_to_irq(vector) (vector)
#endif
+#define __DO_ACTION(R, ACTION, FINAL) \
+ \
+{ \
+ int pin; \
+ struct irq_pin_list *entry = irq_2_pin + irq; \
+ \
+ for (;;) { \
+ unsigned int reg; \
+ pin = entry->pin; \
+ if (pin == -1) \
+ break; \
+ reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
+ reg ACTION; \
+ io_apic_modify(entry->apic, reg); \
+ if (!entry->next) \
+ break; \
+ entry = irq_2_pin + entry->next; \
+ } \
+ FINAL; \
+}
+
+#ifdef CONFIG_SMP
+static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+ unsigned long flags;
+ unsigned int dest;
+ cpumask_t tmp;
+
+ cpus_and(tmp, mask, cpu_online_map);
+ if (cpus_empty(tmp))
+ tmp = TARGET_CPUS;
+
+ cpus_and(mask, tmp, CPU_MASK_ALL);
+
+ dest = cpu_mask_to_apicid(mask);
+
+ /*
+ * Only the high 8 bits are valid.
+ */
+ dest = SET_APIC_LOGICAL_ID(dest);
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ __DO_ACTION(1, = dest, )
+ set_irq_info(irq, mask);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+#endif
+
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
@@ -101,26 +150,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
entry->pin = pin;
}
-#define __DO_ACTION(R, ACTION, FINAL) \
- \
-{ \
- int pin; \
- struct irq_pin_list *entry = irq_2_pin + irq; \
- \
- for (;;) { \
- unsigned int reg; \
- pin = entry->pin; \
- if (pin == -1) \
- break; \
- reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
- reg ACTION; \
- io_apic_modify(entry->apic, reg); \
- if (!entry->next) \
- break; \
- entry = irq_2_pin + entry->next; \
- } \
- FINAL; \
-}
#define DO_ACTION(name,R,ACTION, FINAL) \
\
@@ -270,6 +299,15 @@ void __init check_ioapic(void)
#endif
/* RED-PEN skip them on mptables too? */
return;
+ case PCI_VENDOR_ID_ATI:
+ /* All timer interrupts on atiixp
+ are doubled. Disable one. */
+ if (disable_timer_pin_1 == 0) {
+ disable_timer_pin_1 = 1;
+ printk(KERN_INFO
+ "ATI board detected. Disabling timer pin 1.\n");
+ }
+ return;
}
/* No multi-function device? */
@@ -655,7 +693,7 @@ static inline int IO_APIC_irq_trigger(int irq)
}
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
int assign_irq_vector(int irq)
{
@@ -767,6 +805,7 @@ static void __init setup_IO_APIC_irqs(void)
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
}
@@ -993,13 +1032,11 @@ void __apicdebuginit print_local_APIC(void * dummy)
v = apic_read(APIC_TASKPRI);
printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- v = apic_read(APIC_ARBPRI);
- printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
- v & APIC_ARBPRI_MASK);
- v = apic_read(APIC_PROCPRI);
- printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
- }
+ v = apic_read(APIC_ARBPRI);
+ printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+ v & APIC_ARBPRI_MASK);
+ v = apic_read(APIC_PROCPRI);
+ printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
v = apic_read(APIC_EOI);
printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
@@ -1019,12 +1056,8 @@ void __apicdebuginit print_local_APIC(void * dummy)
printk(KERN_DEBUG "... APIC IRR field:\n");
print_APIC_bitfield(APIC_IRR);
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
- apic_write(APIC_ESR, 0);
- v = apic_read(APIC_ESR);
- printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
- }
+ v = apic_read(APIC_ESR);
+ printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
v = apic_read(APIC_ICR);
printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
@@ -1138,9 +1171,9 @@ void disable_IO_APIC(void)
clear_IO_APIC();
/*
- * If the i82559 is routed through an IOAPIC
+ * If the i8259 is routed through an IOAPIC
* Put that IOAPIC in virtual wire mode
- * so legacy interrups can be delivered.
+ * so legacy interrupts can be delivered.
*/
pin = find_isa_irq_pin(0, mp_ExtINT);
if (pin != -1) {
@@ -1314,6 +1347,7 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
+ move_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
@@ -1343,26 +1377,10 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq)
static void end_level_ioapic_irq (unsigned int irq)
{
+ move_irq(irq);
ack_APIC_irq();
}
-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
-{
- unsigned long flags;
- unsigned int dest;
-
- dest = cpu_mask_to_apicid(mask);
-
- /*
- * Only the high 8 bits are valid.
- */
- dest = SET_APIC_LOGICAL_ID(dest);
-
- spin_lock_irqsave(&ioapic_lock, flags);
- __DO_ACTION(1, = dest, )
- spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
#ifdef CONFIG_PCI_MSI
static unsigned int startup_edge_ioapic_vector(unsigned int vector)
{
@@ -1375,6 +1393,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
{
int irq = vector_to_irq(vector);
+ move_native_irq(vector);
ack_edge_ioapic_irq(irq);
}
@@ -1389,6 +1408,7 @@ static void end_level_ioapic_vector (unsigned int vector)
{
int irq = vector_to_irq(vector);
+ move_native_irq(vector);
end_level_ioapic_irq(irq);
}
@@ -1406,14 +1426,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
unmask_IO_APIC_irq(irq);
}
+#ifdef CONFIG_SMP
static void set_ioapic_affinity_vector (unsigned int vector,
cpumask_t cpu_mask)
{
int irq = vector_to_irq(vector);
+ set_native_irq_info(vector, cpu_mask);
set_ioapic_affinity_irq(irq, cpu_mask);
}
-#endif
+#endif // CONFIG_SMP
+#endif // CONFIG_PCI_MSI
/*
* Level and edge triggered IO-APIC interrupts need different handling,
@@ -1424,7 +1447,7 @@ static void set_ioapic_affinity_vector (unsigned int vector,
* races.
*/
-static struct hw_interrupt_type ioapic_edge_type = {
+static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
.typename = "IO-APIC-edge",
.startup = startup_edge_ioapic,
.shutdown = shutdown_edge_ioapic,
@@ -1432,10 +1455,12 @@ static struct hw_interrupt_type ioapic_edge_type = {
.disable = disable_edge_ioapic,
.ack = ack_edge_ioapic,
.end = end_edge_ioapic,
+#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
+#endif
};
-static struct hw_interrupt_type ioapic_level_type = {
+static struct hw_interrupt_type ioapic_level_type __read_mostly = {
.typename = "IO-APIC-level",
.startup = startup_level_ioapic,
.shutdown = shutdown_level_ioapic,
@@ -1443,7 +1468,9 @@ static struct hw_interrupt_type ioapic_level_type = {
.disable = disable_level_ioapic,
.ack = mask_and_ack_level_ioapic,
.end = end_level_ioapic,
+#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
+#endif
};
static inline void init_IO_APIC_traps(void)
@@ -1506,7 +1533,7 @@ static void ack_lapic_irq (unsigned int irq)
static void end_lapic_irq (unsigned int i) { /* nothing */ }
-static struct hw_interrupt_type lapic_irq_type = {
+static struct hw_interrupt_type lapic_irq_type __read_mostly = {
.typename = "local-APIC-edge",
.startup = NULL, /* startup_irq() not used for IRQ0 */
.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
@@ -1642,6 +1669,8 @@ static inline void check_timer(void)
setup_nmi();
enable_8259A_irq(0);
}
+ if (disable_timer_pin_1 > 0)
+ clear_IO_APIC_pin(0, pin1);
return;
}
clear_IO_APIC_pin(0, pin1);
@@ -1841,7 +1870,7 @@ device_initcall(ioapic_init_sysfs);
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
#define IO_APIC_MAX_ID 0xFE
@@ -1918,12 +1947,13 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
return 0;
}
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /* CONFIG_ACPI */
/*
@@ -1931,6 +1961,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
* we need to reprogram the ioredtbls to cater for the cpus which have come online
* so mask in all cases should simply be TARGET_CPUS
*/
+#ifdef CONFIG_SMP
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
@@ -1949,3 +1980,4 @@ void __init setup_ioapic_dest(void)
}
}
+#endif
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 849a20aec7ca..d6a04a8320a3 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -99,7 +99,6 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
unsigned irq = regs->orig_rax & 0xff;
irq_enter();
- BUG_ON(irq > 256);
__do_IRQ(irq, regs);
irq_exit();
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 5c6dc7051482..df08c43276a0 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -74,7 +74,7 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn)
return 0;
}
-int arch_prepare_kprobe(struct kprobe *p)
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
/* insn: must be on special executable page on x86_64. */
up(&kprobe_mutex);
@@ -189,7 +189,7 @@ static inline s32 *is_riprel(u8 *insn)
return NULL;
}
-void arch_copy_kprobe(struct kprobe *p)
+void __kprobes arch_copy_kprobe(struct kprobe *p)
{
s32 *ripdisp;
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
@@ -215,21 +215,21 @@ void arch_copy_kprobe(struct kprobe *p)
p->opcode = *p->addr;
}
-void arch_arm_kprobe(struct kprobe *p)
+void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_disarm_kprobe(struct kprobe *p)
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void arch_remove_kprobe(struct kprobe *p)
+void __kprobes arch_remove_kprobe(struct kprobe *p)
{
up(&kprobe_mutex);
free_insn_slot(p->ainsn.insn);
@@ -261,7 +261,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
kprobe_saved_rflags &= ~IF_MASK;
}
-static 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;
@@ -272,7 +272,8 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->rip = (unsigned long)p->ainsn.insn;
}
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
{
unsigned long *sara = (unsigned long *)regs->rsp;
struct kretprobe_instance *ri;
@@ -295,7 +296,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
*/
-int kprobe_handler(struct pt_regs *regs)
+int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
@@ -310,7 +311,8 @@ int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS) {
+ if (kprobe_status == KPROBE_HIT_SS &&
+ *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
regs->eflags &= ~TF_MASK;
regs->eflags |= kprobe_saved_rflags;
unlock_kprobes();
@@ -360,7 +362,10 @@ int kprobe_handler(struct pt_regs *regs)
* either a probepoint or a debugger breakpoint
* at this address. In either case, no further
* handling of this interrupt is appropriate.
+ * Back up over the (now missing) int3 and run
+ * the original instruction.
*/
+ regs->rip = (unsigned long)addr;
ret = 1;
}
/* Not one of ours: let kernel handle it */
@@ -399,7 +404,7 @@ no_kprobe:
/*
* Called when we hit the probe point at kretprobe_trampoline
*/
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
@@ -478,7 +483,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* that is atop the stack is the address following the copied instruction.
* We need to make it the address following the original instruction.
*/
-static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
unsigned long *tos = (unsigned long *)regs->rsp;
unsigned long next_rip = 0;
@@ -536,7 +541,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
* Interrupts are disabled on entry as trap1 is an interrupt gate and they
* remain disabled thoroughout this function. And we hold kprobe lock.
*/
-int post_kprobe_handler(struct pt_regs *regs)
+int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
if (!kprobe_running())
return 0;
@@ -571,7 +576,7 @@ out:
}
/* Interrupts disabled, kprobe_lock held. */
-int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
if (current_kprobe->fault_handler
&& current_kprobe->fault_handler(current_kprobe, regs, trapnr))
@@ -590,8 +595,8 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
/*
* Wrapper routine for handling exceptions.
*/
-int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
- void *data)
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
switch (val) {
@@ -619,7 +624,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
return NOTIFY_DONE;
}
-int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr;
@@ -640,7 +645,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-void jprobe_return(void)
+void __kprobes jprobe_return(void)
{
preempt_enable_no_resched();
asm volatile (" xchg %%rbx,%%rsp \n"
@@ -651,7 +656,7 @@ void jprobe_return(void)
(jprobe_saved_rsp):"memory");
}
-int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
u8 *addr = (u8 *) (regs->rip - 1);
unsigned long stack_addr = (unsigned long)jprobe_saved_rsp;
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 8aa56736cde3..08203b07f4bd 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -17,6 +17,7 @@
#include <linux/fs.h>
#include <linux/cpu.h>
#include <linux/percpu.h>
+#include <linux/ctype.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/mce.h>
@@ -56,15 +57,19 @@ void mce_log(struct mce *mce)
smp_wmb();
for (;;) {
entry = rcu_dereference(mcelog.next);
- /* When the buffer fills up discard new entries. Assume
- that the earlier errors are the more interesting. */
- if (entry >= MCE_LOG_LEN) {
- set_bit(MCE_OVERFLOW, &mcelog.flags);
- return;
+ for (;;) {
+ /* When the buffer fills up discard new entries. Assume
+ that the earlier errors are the more interesting. */
+ if (entry >= MCE_LOG_LEN) {
+ set_bit(MCE_OVERFLOW, &mcelog.flags);
+ return;
+ }
+ /* Old left over entry. Skip. */
+ if (mcelog.entry[entry].finished) {
+ entry++;
+ continue;
+ }
}
- /* Old left over entry. Skip. */
- if (mcelog.entry[entry].finished)
- continue;
smp_rmb();
next = entry + 1;
if (cmpxchg(&mcelog.next, entry, next) == entry)
@@ -212,7 +217,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
panicm_found = 1;
}
- tainted |= TAINT_MACHINE_CHECK;
+ add_taint(TAINT_MACHINE_CHECK);
}
/* Never do anything final in the polling timer */
@@ -404,9 +409,15 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
}
err = 0;
- for (i = 0; i < next; i++) {
- if (!mcelog.entry[i].finished)
- continue;
+ for (i = 0; i < next; i++) {
+ unsigned long start = jiffies;
+ while (!mcelog.entry[i].finished) {
+ if (!time_before(jiffies, start + 2)) {
+ memset(mcelog.entry + i,0, sizeof(struct mce));
+ continue;
+ }
+ cpu_relax();
+ }
smp_rmb();
err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
buf += sizeof(struct mce);
@@ -479,6 +490,7 @@ static int __init mcheck_disable(char *str)
/* mce=off disables machine check. Note you can reenable it later
using sysfs.
+ mce=TOLERANCELEVEL (number, see above)
mce=bootlog Log MCEs from before booting. Disabled by default to work
around buggy BIOS that leave bogus MCEs. */
static int __init mcheck_enable(char *str)
@@ -489,6 +501,8 @@ static int __init mcheck_enable(char *str)
mce_dont_init = 1;
else if (!strcmp(str, "bootlog"))
mce_bootlog = 1;
+ else if (isdigit(str[0]))
+ get_option(&str, &tolerant);
else
printk("mce= argument %s ignored. Please use /sys", str);
return 0;
@@ -501,10 +515,12 @@ __setup("mce", mcheck_enable);
* Sysfs support
*/
-/* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
+/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
+ Only one CPU is active at this time, the others get readded later using
+ CPU hotplug. */
static int mce_resume(struct sys_device *dev)
{
- on_each_cpu(mce_init, NULL, 1, 1);
+ mce_init(NULL);
return 0;
}
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 79c362d03e2e..f16d38d09daf 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -14,7 +14,6 @@
*/
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/config.h>
@@ -46,8 +45,6 @@ int acpi_found_madt;
int apic_version [MAX_APICS];
unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-unsigned char pci_bus_to_node [256];
-EXPORT_SYMBOL(pci_bus_to_node);
static int mp_current_pci_id = 0;
/* I/O APIC entries */
@@ -74,7 +71,7 @@ static unsigned int num_processors = 0;
physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
/* ACPI MADT entry parsing functions */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern struct acpi_boot_flags acpi_boot;
#ifdef CONFIG_X86_LOCAL_APIC
extern int acpi_parse_lapic (acpi_table_entry_header *header);
@@ -84,7 +81,7 @@ extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
#ifdef CONFIG_X86_IO_APIC
extern int acpi_parse_ioapic (acpi_table_entry_header *header);
#endif /*CONFIG_X86_IO_APIC*/
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /*CONFIG_ACPI*/
u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
@@ -519,8 +516,6 @@ void __init get_smp_config (void)
struct intel_mp_floating *mpf = mpf_found;
/*
- * ACPI may be used to obtain the entire SMP configuration or just to
- * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that
* ACPI supports both logical (e.g. Hyper-Threading) and physical
* processors, where MPS only supports physical.
*/
@@ -673,7 +668,7 @@ void __init find_smp_config (void)
ACPI-based MP Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
void __init mp_register_lapic_address (
u64 address)
@@ -707,7 +702,7 @@ void __init mp_register_lapic (
processor.mpc_type = MP_PROCESSOR;
processor.mpc_apicid = id;
- processor.mpc_apicver = 0x10; /* TBD: lapic version */
+ processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
@@ -929,11 +924,9 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
-#ifdef CONFIG_ACPI_BUS
/* Don't set up the ACPI SCI because it's already set up */
if (acpi_fadt.sci_int == gsi)
return gsi;
-#endif
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
@@ -973,13 +966,11 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
if (gsi < MAX_GSI_NUM) {
if (gsi > 15)
gsi = pci_irq++;
-#ifdef CONFIG_ACPI_BUS
/*
* Don't assign IRQ used by ACPI SCI
*/
if (gsi == acpi_fadt.sci_int)
gsi = pci_irq++;
-#endif
gsi_to_irq[irq] = gsi;
} else {
printk(KERN_ERR "GSI %u is too high\n", gsi);
@@ -994,4 +985,4 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
}
#endif /*CONFIG_X86_IO_APIC*/
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /*CONFIG_ACPI*/
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
deleted file mode 100644
index 598953ab0154..000000000000
--- a/arch/x86_64/kernel/msr.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2000 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- * USA; either version 2 of the License, or (at your option) any later
- * version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * msr.c
- *
- * x86 MSR access device
- *
- * This device is accessed by lseek() to the appropriate register number
- * and then read/write in chunks of 8 bytes. A larger size means multiple
- * reads or writes of the same register.
- *
- * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
- * an SMP box will direct the access to CPU %d.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* Note: "err" is handled in a funny way below. Otherwise one version
- of gcc or another breaks. */
-
-static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
-{
- int err;
-
- asm volatile ("1: wrmsr\n"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- "3: movl %4,%0\n"
- " jmp 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n" " .quad 1b,3b\n" ".previous":"=&bDS" (err)
- :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
-
- return err;
-}
-
-static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
-{
- int err;
-
- asm volatile ("1: rdmsr\n"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- "3: movl %4,%0\n"
- " jmp 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 1b,3b\n"
- ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
- :"c"(reg), "i"(-EIO), "0"(0));
-
- return err;
-}
-
-#ifdef CONFIG_SMP
-
-struct msr_command {
- int cpu;
- int err;
- u32 reg;
- u32 data[2];
-};
-
-static void msr_smp_wrmsr(void *cmd_block)
-{
- struct msr_command *cmd = (struct msr_command *)cmd_block;
-
- if (cmd->cpu == smp_processor_id())
- cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
-}
-
-static void msr_smp_rdmsr(void *cmd_block)
-{
- struct msr_command *cmd = (struct msr_command *)cmd_block;
-
- if (cmd->cpu == smp_processor_id())
- cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
-}
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
- struct msr_command cmd;
- int ret;
-
- preempt_disable();
- if (cpu == smp_processor_id()) {
- ret = wrmsr_eio(reg, eax, edx);
- } else {
- cmd.cpu = cpu;
- cmd.reg = reg;
- cmd.data[0] = eax;
- cmd.data[1] = edx;
-
- smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
- ret = cmd.err;
- }
- preempt_enable();
- return ret;
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
-{
- struct msr_command cmd;
- int ret;
-
- preempt_disable();
- if (cpu == smp_processor_id()) {
- ret = rdmsr_eio(reg, eax, edx);
- } else {
- cmd.cpu = cpu;
- cmd.reg = reg;
-
- smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-
- *eax = cmd.data[0];
- *edx = cmd.data[1];
-
- ret = cmd.err;
- }
- preempt_enable();
- return ret;
-}
-
-#else /* ! CONFIG_SMP */
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
- return wrmsr_eio(reg, eax, edx);
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
-{
- return rdmsr_eio(reg, eax, edx);
-}
-
-#endif /* ! CONFIG_SMP */
-
-static loff_t msr_seek(struct file *file, loff_t offset, int orig)
-{
- loff_t ret = -EINVAL;
-
- lock_kernel();
- switch (orig) {
- case 0:
- file->f_pos = offset;
- ret = file->f_pos;
- break;
- case 1:
- file->f_pos += offset;
- ret = file->f_pos;
- }
- unlock_kernel();
- return ret;
-}
-
-static ssize_t msr_read(struct file *file, char __user * buf,
- size_t count, loff_t * ppos)
-{
- u32 __user *tmp = (u32 __user *) buf;
- u32 data[2];
- size_t rv;
- u32 reg = *ppos;
- int cpu = iminor(file->f_dentry->d_inode);
- int err;
-
- if (count % 8)
- return -EINVAL; /* Invalid chunk size */
-
- for (rv = 0; count; count -= 8) {
- err = do_rdmsr(cpu, reg, &data[0], &data[1]);
- if (err)
- return err;
- if (copy_to_user(tmp, &data, 8))
- return -EFAULT;
- tmp += 2;
- }
-
- return ((char __user *)tmp) - buf;
-}
-
-static ssize_t msr_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- const u32 __user *tmp = (const u32 __user *)buf;
- u32 data[2];
- size_t rv;
- u32 reg = *ppos;
- int cpu = iminor(file->f_dentry->d_inode);
- int err;
-
- if (count % 8)
- return -EINVAL; /* Invalid chunk size */
-
- for (rv = 0; count; count -= 8) {
- if (copy_from_user(&data, tmp, 8))
- return -EFAULT;
- err = do_wrmsr(cpu, reg, data[0], data[1]);
- if (err)
- return err;
- tmp += 2;
- }
-
- return ((char __user *)tmp) - buf;
-}
-
-static int msr_open(struct inode *inode, struct file *file)
-{
- unsigned int cpu = iminor(file->f_dentry->d_inode);
- struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-
- if (cpu >= NR_CPUS || !cpu_online(cpu))
- return -ENXIO; /* No such CPU */
- if (!cpu_has(c, X86_FEATURE_MSR))
- return -EIO; /* MSR not supported */
-
- return 0;
-}
-
-/*
- * File operations we support
- */
-static struct file_operations msr_fops = {
- .owner = THIS_MODULE,
- .llseek = msr_seek,
- .read = msr_read,
- .write = msr_write,
- .open = msr_open,
-};
-
-static int __init msr_init(void)
-{
- if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
- printk(KERN_ERR "msr: unable to get major %d for msr\n",
- MSR_MAJOR);
- return -EBUSY;
- }
-
- return 0;
-}
-
-static void __exit msr_exit(void)
-{
- unregister_chrdev(MSR_MAJOR, "cpu/msr");
-}
-
-module_init(msr_init);
-module_exit(msr_exit)
-
-MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
-MODULE_DESCRIPTION("x86 generic MSR driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 4e44d6e6b7e5..39d445e16f22 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -14,7 +14,6 @@
#include <linux/config.h>
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
@@ -290,7 +289,7 @@ void enable_timer_nmi_watchdog(void)
static int nmi_pm_active; /* nmi_active before suspend */
-static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
+static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
{
nmi_pm_active = nmi_active;
disable_lapic_nmi_watchdog();
@@ -367,7 +366,7 @@ static void setup_k7_watchdog(void)
| K7_NMI_EVENT;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+ wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
@@ -408,8 +407,8 @@ static int setup_p4_watchdog(void)
wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+ Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz));
+ wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz));
apic_write(APIC_LVTPC, APIC_DM_NMI);
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
return 1;
@@ -463,6 +462,8 @@ void touch_nmi_watchdog (void)
*/
for (i = 0; i < NR_CPUS; i++)
per_cpu(nmi_touch, i) = 1;
+
+ touch_softlockup_watchdog();
}
void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
@@ -486,8 +487,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
== NOTIFY_STOP) {
local_set(&__get_cpu_var(alert_counter), 0);
return;
- }
- die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
+ }
+ die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
}
} else {
__get_cpu_var(last_irq_sum) = sum;
@@ -505,7 +506,7 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
- wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+ wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
}
}
@@ -522,14 +523,14 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
nmi_enter();
add_pda(__nmi_count,1);
- if (!nmi_callback(regs, cpu))
+ if (!rcu_dereference(nmi_callback)(regs, cpu))
default_do_nmi(regs);
nmi_exit();
}
void set_nmi_callback(nmi_callback_t callback)
{
- nmi_callback = callback;
+ rcu_assign_pointer(nmi_callback, callback);
}
void unset_nmi_callback(void)
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 57f35c68aa34..cf0a0315d586 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -191,11 +191,9 @@ static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
{
struct page *page;
int node;
- if (dev->bus == &pci_bus_type) {
- cpumask_t mask;
- mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
- node = cpu_to_node(first_cpu(mask));
- } else
+ if (dev->bus == &pci_bus_type)
+ node = pcibus_to_node(to_pci_dev(dev)->bus);
+ else
node = numa_node_id();
page = alloc_pages_node(node, gfp, order);
return page ? page_address(page) : NULL;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 7577f9d7a75d..b5a89c0bdf59 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -32,7 +32,6 @@
#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/irq.h>
#include <linux/ptrace.h>
#include <linux/utsname.h>
#include <linux/random.h>
@@ -123,6 +122,7 @@ static void poll_idle (void)
: :
"i" (_TIF_NEED_RESCHED),
"m" (current_thread_info()->flags));
+ clear_thread_flag(TIF_POLLING_NRFLAG);
} else {
set_need_resched();
}
@@ -271,8 +271,11 @@ void __show_regs(struct pt_regs * regs)
printk("\n");
print_modules();
- printk("Pid: %d, comm: %.20s %s %s\n",
- current->pid, current->comm, print_tainted(), system_utsname.release);
+ printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+ current->pid, current->comm, print_tainted(),
+ system_utsname.release,
+ (int)strcspn(system_utsname.version, " "),
+ system_utsname.version);
printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
printk_address(regs->rip);
printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags);
@@ -310,6 +313,7 @@ void __show_regs(struct pt_regs * regs)
void show_regs(struct pt_regs *regs)
{
+ printk("CPU %d:", smp_processor_id());
__show_regs(regs);
show_trace(&regs->rsp);
}
@@ -482,33 +486,6 @@ out:
}
/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
- struct task_struct *next_p)
-{
- struct thread_info *prev, *next;
-
- /*
- * gcc should eliminate the ->thread_info dereference if
- * has_secure_computing returns 0 at compile time (SECCOMP=n).
- */
- prev = prev_p->thread_info;
- next = next_p->thread_info;
-
- if (has_secure_computing(prev) || has_secure_computing(next)) {
- /* slow path here */
- if (has_secure_computing(prev) &&
- !has_secure_computing(next)) {
- write_cr4(read_cr4() & ~X86_CR4_TSD);
- } else if (!has_secure_computing(prev) &&
- has_secure_computing(next))
- write_cr4(read_cr4() | X86_CR4_TSD);
- }
-}
-
-/*
* This special macro can be used to load a debugging register
*/
#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r)
@@ -626,8 +603,6 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
}
}
- disable_tsc(prev_p, next_p);
-
return prev_p;
}
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 116a491e2961..351d8d64c2fb 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -65,13 +65,13 @@
* Machine setup..
*/
-struct cpuinfo_x86 boot_cpu_data;
+struct cpuinfo_x86 boot_cpu_data __read_mostly;
unsigned long mmu_cr4_features;
int acpi_disabled;
EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern int __initdata acpi_ht;
extern acpi_interrupt_flags acpi_sci_flags;
int __initdata acpi_force = 0;
@@ -294,7 +294,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
maxcpus = simple_strtoul(from + 8, NULL, 0);
}
#endif
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/* "acpi=off" disables both ACPI table parsing and interpreter init */
if (!memcmp(from, "acpi=off", 8))
disable_acpi();
@@ -336,6 +336,11 @@ static __init void parse_cmdline_early (char ** cmdline_p)
#endif
#endif
+ if (!memcmp(from, "disable_timer_pin_1", 19))
+ disable_timer_pin_1 = 1;
+ if (!memcmp(from, "enable_timer_pin_1", 18))
+ disable_timer_pin_1 = -1;
+
if (!memcmp(from, "nolapic", 7) ||
!memcmp(from, "disableapic", 11))
disable_apic = 1;
@@ -566,7 +571,7 @@ void __init setup_arch(char **cmdline_p)
init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/*
* Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
* Call this early for SRAT node setup.
@@ -658,7 +663,7 @@ void __init setup_arch(char **cmdline_p)
check_ioapic();
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
/*
* Read APIC and some other early information from ACPI tables.
*/
@@ -755,6 +760,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
}
}
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+ int i;
+ for (i = apicid - 1; i >= 0; i--) {
+ int node = apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+ int node = apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
/*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
@@ -763,8 +786,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
int cpu = smp_processor_id();
- int node = 0;
unsigned bits;
+#ifdef CONFIG_NUMA
+ int node = 0;
+ unsigned apicid = phys_proc_id[cpu];
+#endif
bits = 0;
while ((1 << bits) < c->x86_num_cores)
@@ -776,20 +802,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
phys_proc_id[cpu] >>= bits;
#ifdef CONFIG_NUMA
- /* When an ACPI SRAT table is available use the mappings from SRAT
- instead. */
- if (acpi_numa <= 0) {
- node = phys_proc_id[cpu];
- if (!node_online(node))
- node = first_node(node_online_map);
- cpu_to_node[cpu] = node;
- } else {
- node = cpu_to_node[cpu];
- }
+ node = phys_proc_id[cpu];
+ if (apicid_to_node[apicid] != NUMA_NO_NODE)
+ node = apicid_to_node[apicid];
+ if (!node_online(node)) {
+ /* Two possibilities here:
+ - The CPU is missing memory and no node was created.
+ In that case try picking one from a nearby CPU
+ - The APIC IDs differ from the HyperTransport node IDs
+ which the K8 northbridge parsing fills in.
+ Assume they are all increased by a constant offset,
+ but in the same order as the HT nodeids.
+ If that doesn't result in a usable node fall back to the
+ path for the previous case. */
+ int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+ if (ht_nodeid >= 0 &&
+ apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+ node = apicid_to_node[ht_nodeid];
+ /* Pick a nearby node */
+ if (!node_online(node))
+ node = nearby_node(apicid);
+ }
+ cpu_to_node[cpu] = node;
+
+ printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+ cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
#endif
-
- printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
- cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
#endif
}
@@ -909,6 +947,25 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
return 1;
}
+static void srat_detect_node(void)
+{
+#ifdef CONFIG_NUMA
+ unsigned apicid, node;
+ int cpu = smp_processor_id();
+
+ /* Don't do the funky fallback heuristics the AMD version employs
+ for now. */
+ apicid = phys_proc_id[cpu];
+ node = apicid_to_node[apicid];
+ if (node == NUMA_NO_NODE)
+ node = 0;
+ cpu_to_node[cpu] = node;
+
+ if (acpi_numa > 0)
+ printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
+#endif
+}
+
static void __cpuinit init_intel(struct cpuinfo_x86 *c)
{
/* Cache sizes */
@@ -927,9 +984,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if (c->x86 >= 15)
set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
c->x86_num_cores = intel_num_cpu_cores(c);
+
+ srat_detect_node();
}
-void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 34082c1cc41e..bd33be24a386 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -36,7 +36,7 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
-unsigned long __supported_pte_mask = ~0UL;
+unsigned long __supported_pte_mask __read_mostly = ~0UL;
static int do_not_nx __initdata = 0;
/* noexec=on|off
@@ -94,7 +94,7 @@ void __init setup_per_cpu_areas(void)
size = PERCPU_ENOUGH_ROOM;
#endif
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_cpu_mask (i, cpu_possible_map) {
char *ptr;
if (!NODE_DATA(cpu_to_node(i))) {
@@ -119,7 +119,6 @@ void pda_init(int cpu)
asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
wrmsrl(MSR_GS_BASE, cpu_pda + cpu);
- pda->me = pda;
pda->cpunumber = cpu;
pda->irqcount = -1;
pda->kernelstack =
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 98590a989f3d..d642fbf3da29 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -394,10 +394,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
#endif
ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- sigaddset(&current->blocked,sig);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index e5958220d6b8..9db9dda161b4 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -12,7 +12,6 @@
#include <linux/init.h>
#include <linux/mm.h>
-#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
@@ -29,6 +28,8 @@
#include <asm/proto.h>
#include <asm/apicdef.h>
+#define __cpuinit __init
+
/*
* Smarter SMP flushing macros.
* c/o Linus Torvalds.
@@ -37,19 +38,41 @@
* writing to user space from interrupts. (Its not allowed anyway).
*
* Optimizations Manfred Spraul <manfred@colorfullife.com>
+ *
+ * More scalable flush, from Andi Kleen
+ *
+ * To avoid global state use 8 different call vectors.
+ * Each CPU uses a specific vector to trigger flushes on other
+ * CPUs. Depending on the received vector the target CPUs look into
+ * the right per cpu variable for the flush data.
+ *
+ * With more than 8 CPUs they are hashed to the 8 available
+ * vectors. The limited global vector space forces us to this right now.
+ * In future when interrupts are split into per CPU domains this could be
+ * fixed, at the cost of triggering multiple IPIs in some cases.
*/
-static cpumask_t flush_cpumask;
-static struct mm_struct * flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
+union smp_flush_state {
+ struct {
+ cpumask_t flush_cpumask;
+ struct mm_struct *flush_mm;
+ unsigned long flush_va;
#define FLUSH_ALL -1ULL
+ spinlock_t tlbstate_lock;
+ };
+ char pad[SMP_CACHE_BYTES];
+} ____cacheline_aligned;
+
+/* State is put into the per CPU data section, but padded
+ to a full cache line because other CPUs can access it and we don't
+ want false sharing in the per cpu data segment. */
+static DEFINE_PER_CPU(union smp_flush_state, flush_state);
/*
* We cannot call mmdrop() because we are in interrupt context,
* instead update mm->cpu_vm_mask.
*/
-static inline void leave_mm (unsigned long cpu)
+static inline void leave_mm(int cpu)
{
if (read_pda(mmu_state) == TLBSTATE_OK)
BUG();
@@ -101,15 +124,25 @@ static inline void leave_mm (unsigned long cpu)
*
* 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
* 2) Leave the mm if we are in the lazy tlb mode.
+ *
+ * Interrupts are disabled.
*/
-asmlinkage void smp_invalidate_interrupt (void)
+asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
{
- unsigned long cpu;
+ int cpu;
+ int sender;
+ union smp_flush_state *f;
- cpu = get_cpu();
+ cpu = smp_processor_id();
+ /*
+ * orig_rax contains the interrupt vector - 256.
+ * Use that to determine where the sender put the data.
+ */
+ sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
+ f = &per_cpu(flush_state, sender);
- if (!cpu_isset(cpu, flush_cpumask))
+ if (!cpu_isset(cpu, f->flush_cpumask))
goto out;
/*
* This was a BUG() but until someone can quote me the
@@ -120,64 +153,63 @@ asmlinkage void smp_invalidate_interrupt (void)
* BUG();
*/
- if (flush_mm == read_pda(active_mm)) {
+ if (f->flush_mm == read_pda(active_mm)) {
if (read_pda(mmu_state) == TLBSTATE_OK) {
- if (flush_va == FLUSH_ALL)
+ if (f->flush_va == FLUSH_ALL)
local_flush_tlb();
else
- __flush_tlb_one(flush_va);
+ __flush_tlb_one(f->flush_va);
} else
leave_mm(cpu);
}
out:
ack_APIC_irq();
- cpu_clear(cpu, flush_cpumask);
- put_cpu_no_resched();
+ cpu_clear(cpu, f->flush_cpumask);
}
static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
unsigned long va)
{
- cpumask_t tmp;
- /*
- * A couple of (to be removed) sanity checks:
- *
- * - we do not send IPIs to not-yet booted CPUs.
- * - current CPU must not be in mask
- * - mask must exist :)
- */
- BUG_ON(cpus_empty(cpumask));
- cpus_and(tmp, cpumask, cpu_online_map);
- BUG_ON(!cpus_equal(tmp, cpumask));
- BUG_ON(cpu_isset(smp_processor_id(), cpumask));
- if (!mm)
- BUG();
+ int sender;
+ union smp_flush_state *f;
- /*
- * I'm not happy about this global shared spinlock in the
- * MM hot path, but we'll see how contended it is.
- * Temporarily this turns IRQs off, so that lockups are
- * detected by the NMI watchdog.
- */
- spin_lock(&tlbstate_lock);
-
- flush_mm = mm;
- flush_va = va;
- cpus_or(flush_cpumask, cpumask, flush_cpumask);
+ /* Caller has disabled preemption */
+ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+ f = &per_cpu(flush_state, sender);
+
+ /* Could avoid this lock when
+ num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+ probably not worth checking this for a cache-hot lock. */
+ spin_lock(&f->tlbstate_lock);
+
+ f->flush_mm = mm;
+ f->flush_va = va;
+ cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
/*
* We have to send the IPI only to
* CPUs affected.
*/
- send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+
+ while (!cpus_empty(f->flush_cpumask))
+ cpu_relax();
- while (!cpus_empty(flush_cpumask))
- mb(); /* nothing. lockup detection does not belong here */;
+ f->flush_mm = NULL;
+ f->flush_va = 0;
+ spin_unlock(&f->tlbstate_lock);
+}
- flush_mm = NULL;
- flush_va = 0;
- spin_unlock(&tlbstate_lock);
+int __cpuinit init_smp_flush(void)
+{
+ int i;
+ for_each_cpu_mask(i, cpu_possible_map) {
+ spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+ }
+ return 0;
}
+
+core_initcall(init_smp_flush);
void flush_tlb_current_task(void)
{
@@ -295,8 +327,11 @@ void unlock_ipi_call_lock(void)
/*
* this function sends a 'generic call function' IPI to one other CPU
* in the system.
+ *
+ * cpu is a standard Linux logical CPU number.
*/
-static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+static void
+__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
int nonatomic, int wait)
{
struct call_data_struct data;
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index fa25e39fe54d..e12d7baeb33e 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -44,7 +44,6 @@
#include <linux/mm.h>
#include <linux/kernel_stat.h>
#include <linux/smp_lock.h>
-#include <linux/irq.h>
#include <linux/bootmem.h>
#include <linux/thread_info.h>
#include <linux/module.h>
@@ -58,17 +57,19 @@
#include <asm/tlbflush.h>
#include <asm/proto.h>
#include <asm/nmi.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
/* Package ID of each logical CPU */
-u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
-u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
EXPORT_SYMBOL(phys_proc_id);
EXPORT_SYMBOL(cpu_core_id);
/* Bitmask of currently online CPUs */
-cpumask_t cpu_online_map;
+cpumask_t cpu_online_map __read_mostly;
EXPORT_SYMBOL(cpu_online_map);
@@ -88,8 +89,8 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
/* Set when the idlers are all forked */
int smp_threads_ready;
-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_core_map);
/*
@@ -413,8 +414,13 @@ void __cpuinit smp_callin(void)
/*
* Get our bogomips.
+ *
+ * Need to enable IRQs because it can take longer and then
+ * the NMI watchdog might kill us.
*/
+ local_irq_enable();
calibrate_delay();
+ local_irq_disable();
Dprintk("Stack at about %p\n",&cpuid);
disable_APIC_timer();
@@ -540,8 +546,8 @@ static void inquire_remote_apic(int apicid)
*/
apic_wait_icr_idle();
- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+ apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
timeout = 0;
do {
@@ -574,12 +580,12 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
/*
* Turn INIT on target chip
*/
- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
/*
* Send IPI
*/
- apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
| APIC_DM_INIT);
Dprintk("Waiting for send to finish...\n");
@@ -595,10 +601,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
Dprintk("Deasserting INIT.\n");
/* Target chip */
- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
/* Send IPI */
- apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
Dprintk("Waiting for send to finish...\n");
timeout = 0;
@@ -610,16 +616,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
atomic_set(&init_deasserted, 1);
- /*
- * Should we send STARTUP IPIs ?
- *
- * Determine this based on the APIC version.
- * If we don't have an integrated APIC, don't send the STARTUP IPIs.
- */
- if (APIC_INTEGRATED(apic_version[phys_apicid]))
- num_starts = 2;
- else
- num_starts = 0;
+ num_starts = 2;
/*
* Run STARTUP IPI loop.
@@ -640,12 +637,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
*/
/* Target chip */
- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
/* Boot on the stack */
/* Kick the second */
- apic_write_around(APIC_ICR, APIC_DM_STARTUP
- | (start_rip >> 12));
+ apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
/*
* Give the other CPU some time to accept the IPI.
@@ -864,17 +860,6 @@ static __cpuinit void smp_cleanup_boot(void)
* Reset trampoline flag
*/
*((volatile int *) phys_to_virt(0x467)) = 0;
-
-#ifndef CONFIG_HOTPLUG_CPU
- /*
- * Free pages reserved for SMP bootup.
- * When you add hotplug CPU support later remove this
- * Note there is more work to be done for later CPU bootup.
- */
-
- free_page((unsigned long) __va(PAGE_SIZE));
- free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
-#endif
}
/*
@@ -894,23 +879,6 @@ static __init void disable_smp(void)
cpu_set(0, cpu_core_map[0]);
}
-/*
- * Handle user cpus=... parameter.
- */
-static __init void enforce_max_cpus(unsigned max_cpus)
-{
- int i, k;
- k = 0;
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
- if (++k > max_cpus) {
- cpu_clear(i, cpu_possible_map);
- cpu_clear(i, cpu_present_map);
- }
- }
-}
-
#ifdef CONFIG_HOTPLUG_CPU
/*
* cpu_possible_map should be static, it cannot change as cpu's
@@ -999,8 +967,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
current_cpu_data = boot_cpu_data;
current_thread_info()->cpu = 0; /* needed? */
- enforce_max_cpus(max_cpus);
-
#ifdef CONFIG_HOTPLUG_CPU
prefill_possible_map();
#endif
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index 0612640d91b1..ebb9abf3ce6d 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -8,23 +8,8 @@
*/
#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/sysrq.h>
-#include <linux/proc_fs.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/device.h>
+#include <linux/smp.h>
#include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/acpi.h>
-#include <asm/tlbflush.h>
-#include <asm/io.h>
#include <asm/proto.h>
struct saved_context saved_context;
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
index 53f8e1659511..4d659e97df10 100644
--- a/arch/x86_64/kernel/suspend_asm.S
+++ b/arch/x86_64/kernel/suspend_asm.S
@@ -14,7 +14,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
ENTRY(swsusp_arch_suspend)
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 66bf6ddeb0c3..2373cb8b8625 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -18,7 +18,6 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
-#include <linux/irq.h>
#include <linux/time.h>
#include <linux/ioport.h>
#include <linux/module.h>
@@ -176,10 +175,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -471,7 +467,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* off) isn't likely to go away much sooner anyway.
*/
- if ((~time_status & STA_UNSYNC) && xtime.tv_sec > rtc_update &&
+ if (ntp_synced() && xtime.tv_sec > rtc_update &&
abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
set_rtc_mmss(xtime.tv_sec);
rtc_update = xtime.tv_sec + 660;
@@ -940,7 +936,6 @@ void __init time_init(void)
vxtime.mode = VXTIME_TSC;
vxtime.quot = (1000000L << 32) / vxtime_hz;
vxtime.tsc_quot = (1000L << 32) / cpu_khz;
- vxtime.hz = vxtime_hz;
rdtscll_sync(&vxtime.last_tsc);
setup_irq(0, &irq0);
@@ -1041,6 +1036,7 @@ static int timer_resume(struct sys_device *dev)
write_sequnlock_irqrestore(&xtime_lock,flags);
jiffies += sleep_length;
wall_jiffies += sleep_length;
+ touch_softlockup_watchdog();
return 0;
}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 6ead433a3885..b5e09e6b5536 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/nmi.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -46,9 +47,6 @@
#include <asm/proto.h>
#include <asm/nmi.h>
-#include <linux/irq.h>
-
-
extern struct gate_struct idt_table[256];
asmlinkage void divide_error(void);
@@ -323,13 +321,13 @@ void handle_BUG(struct pt_regs *regs)
if (__copy_from_user(&f, (struct bug_frame *) regs->rip,
sizeof(struct bug_frame)))
return;
- if ((unsigned long)f.filename < __PAGE_OFFSET ||
+ if (f.filename >= 0 ||
f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
return;
- if (__get_user(tmp, f.filename))
- f.filename = "unmapped filename";
+ if (__get_user(tmp, (char *)(long)f.filename))
+ f.filename = (int)(long)"unmapped filename";
printk("----------- [cut here ] --------- [please bite here ] ---------\n");
- printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
+ printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
}
#ifdef CONFIG_BUG
@@ -342,30 +340,33 @@ void out_of_line_bug(void)
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
-void oops_begin(void)
+unsigned long oops_begin(void)
{
- int cpu = safe_smp_processor_id();
- /* racy, but better than risking deadlock. */
- local_irq_disable();
+ int cpu = safe_smp_processor_id();
+ unsigned long flags;
+
+ /* racy, but better than risking deadlock. */
+ local_irq_save(flags);
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
else
- spin_lock(&die_lock);
+ spin_lock(&die_lock);
}
- die_owner = cpu;
+ die_owner = cpu;
console_verbose();
- bust_spinlocks(1);
+ bust_spinlocks(1);
+ return flags;
}
-void oops_end(void)
+void oops_end(unsigned long flags)
{
die_owner = -1;
- bust_spinlocks(0);
- spin_unlock(&die_lock);
+ bust_spinlocks(0);
+ spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
- panic("Oops");
-}
+ panic("Oops");
+}
void __die(const char * str, struct pt_regs * regs, long err)
{
@@ -391,10 +392,11 @@ void __die(const char * str, struct pt_regs * regs, long err)
void die(const char * str, struct pt_regs * regs, long err)
{
- oops_begin();
+ unsigned long flags = oops_begin();
+
handle_BUG(regs);
__die(str, regs, err);
- oops_end();
+ oops_end(flags);
do_exit(SIGSEGV);
}
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -405,7 +407,8 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
void die_nmi(char *str, struct pt_regs *regs)
{
- oops_begin();
+ unsigned long flags = oops_begin();
+
/*
* We are in trouble anyway, lets at least try
* to get a message out.
@@ -415,12 +418,13 @@ void die_nmi(char *str, struct pt_regs *regs)
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
- oops_end();
+ oops_end(flags);
do_exit(SIGSEGV);
}
-static void do_trap(int trapnr, int signr, char *str,
- struct pt_regs * regs, long error_code, siginfo_t *info)
+static void __kprobes do_trap(int trapnr, int signr, char *str,
+ struct pt_regs * regs, long error_code,
+ siginfo_t *info)
{
conditional_sti(regs);
@@ -504,7 +508,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+ long error_code)
{
conditional_sti(regs);
@@ -622,7 +627,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
io_check_error(reason, regs);
}
-asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+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;
@@ -653,7 +658,8 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
}
/* runs on IST stack. */
-asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
+asmlinkage void __kprobes do_debug(struct pt_regs * regs,
+ unsigned long error_code)
{
unsigned long condition;
struct task_struct *tsk = current;
@@ -786,13 +792,16 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
*/
cwd = get_fpu_cwd(task);
swd = get_fpu_swd(task);
- switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+ switch (swd & ~cwd & 0x3f) {
case 0x000:
default:
break;
case 0x001: /* Invalid Op */
- case 0x041: /* Stack Fault */
- case 0x241: /* Stack Fault | Direction */
+ /*
+ * swd & 0x240 == 0x040: Stack Underflow
+ * swd & 0x240 == 0x240: Stack Overflow
+ * User must clear the SF bit (0x40) if set
+ */
info.si_code = FPE_FLTINV;
break;
case 0x002: /* Denormalize */
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 2a94f9b60b2d..6dd642cad2ef 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -21,6 +21,7 @@ SECTIONS
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
} = 0x9090
@@ -193,20 +194,7 @@ SECTIONS
#endif
}
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-
-
- .comment 0 : { *(.comment) }
+ STABS_DEBUG
+
+ DWARF_DEBUG
}
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 2e5734425949..70a0bd16085f 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -107,7 +107,7 @@ static force_inline long time_syscall(long *t)
return secs;
}
-static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
{
if (unlikely(!__sysctl_vsyscall))
return gettimeofday(tv,tz);
@@ -120,7 +120,7 @@ static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz
/* This will break when the xtime seconds get inaccurate, but that is
* unlikely */
-static time_t __vsyscall(1) vtime(time_t *t)
+time_t __vsyscall(1) vtime(time_t *t)
{
if (unlikely(!__sysctl_vsyscall))
return time_syscall(t);
@@ -129,12 +129,12 @@ static time_t __vsyscall(1) vtime(time_t *t)
return __xtime.tv_sec;
}
-static long __vsyscall(2) venosys_0(void)
+long __vsyscall(2) venosys_0(void)
{
return -ENOSYS;
}
-static long __vsyscall(3) venosys_1(void)
+long __vsyscall(3) venosys_1(void)
{
return -ENOSYS;
}
diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
index bd556c804248..dfa358b05c89 100644
--- a/arch/x86_64/lib/copy_user.S
+++ b/arch/x86_64/lib/copy_user.S
@@ -7,7 +7,7 @@
#define FIX_ALIGNMENT 1
#include <asm/current.h>
- #include <asm/offset.h>
+ #include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/cpufeature.h>
diff --git a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
index f80bafee8669..3844d5e885a4 100644
--- a/arch/x86_64/lib/getuser.S
+++ b/arch/x86_64/lib/getuser.S
@@ -29,7 +29,7 @@
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/errno.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
.text
diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S
index 5828b8191667..7f5593974e2d 100644
--- a/arch/x86_64/lib/putuser.S
+++ b/arch/x86_64/lib/putuser.S
@@ -27,7 +27,7 @@
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/errno.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
.text
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index ca914c3bd49c..b75b872ec154 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -23,6 +23,7 @@
#include <linux/vt_kern.h> /* For unblank_screen() */
#include <linux/compiler.h>
#include <linux/module.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -220,12 +221,13 @@ int unhandled_signal(struct task_struct *tsk, int sig)
static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
unsigned long error_code)
{
- oops_begin();
+ unsigned long flags = oops_begin();
+
printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
current->comm, address);
dump_pagetable(address);
__die("Bad pagetable", regs, error_code);
- oops_end();
+ oops_end(flags);
do_exit(SIGKILL);
}
@@ -294,7 +296,8 @@ int exception_trace = 1;
* bit 2 == 0 means kernel, 1 means user-mode
* bit 3 == 1 means fault was an instruction fetch
*/
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+ unsigned long error_code)
{
struct task_struct *tsk;
struct mm_struct *mm;
@@ -302,6 +305,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
unsigned long address;
const struct exception_table_entry *fixup;
int write;
+ unsigned long flags;
siginfo_t info;
#ifdef CONFIG_CHECKING
@@ -519,7 +523,7 @@ no_context:
* terminate things with extreme prejudice.
*/
- oops_begin();
+ flags = oops_begin();
if (address < PAGE_SIZE)
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
@@ -532,7 +536,7 @@ no_context:
__die("Oops", regs, error_code);
/* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address);
- oops_end();
+ oops_end(flags);
do_exit(SIGKILL);
/*
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index aa4a5189ecee..e60a1a848de8 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -57,31 +57,31 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
void show_mem(void)
{
- int i, total = 0, reserved = 0;
- int shared = 0, cached = 0;
+ long i, total = 0, reserved = 0;
+ long shared = 0, cached = 0;
pg_data_t *pgdat;
struct page *page;
- printk("Mem-info:\n");
+ printk(KERN_INFO "Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
- if (PageReserved(page))
- reserved++;
- else if (PageSwapCache(page))
- cached++;
- else if (page_count(page))
- shared += page_count(page) - 1;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (page_count(page))
+ shared += page_count(page) - 1;
}
}
- printk("%d pages of RAM\n", total);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
+ printk(KERN_INFO "%lu pages of RAM\n", total);
+ printk(KERN_INFO "%lu reserved pages\n",reserved);
+ printk(KERN_INFO "%lu pages shared\n",shared);
+ printk(KERN_INFO "%lu pages swap cached\n",cached);
}
/* References to section boundaries */
@@ -381,41 +381,14 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
__flush_tlb_all();
}
-static inline int page_is_ram (unsigned long pagenr)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- unsigned long addr, end;
-
- if (e820.map[i].type != E820_RAM) /* not usable memory */
- continue;
- /*
- * !!!FIXME!!! Some BIOSen report areas as RAM that
- * are not. Notably the 640->1Mb area. We need a sanity
- * check here.
- */
- addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
- end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
- if ((pagenr >= addr) && (pagenr < end))
- return 1;
- }
- return 0;
-}
-
-extern int swiotlb_force;
-
static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
kcore_vsyscall;
void __init mem_init(void)
{
- int codesize, reservedpages, datasize, initsize;
- int tmp;
+ long codesize, reservedpages, datasize, initsize;
#ifdef CONFIG_SWIOTLB
- if (swiotlb_force)
- swiotlb = 1;
if (!iommu_aperture &&
(end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
swiotlb = 1;
@@ -436,25 +409,11 @@ void __init mem_init(void)
/* this will put all low memory onto the freelists */
#ifdef CONFIG_NUMA
- totalram_pages += numa_free_all_bootmem();
- tmp = 0;
- /* should count reserved pages here for all nodes */
+ totalram_pages = numa_free_all_bootmem();
#else
-
-#ifdef CONFIG_FLATMEM
- max_mapnr = end_pfn;
- if (!mem_map) BUG();
-#endif
-
- totalram_pages += free_all_bootmem();
-
- for (tmp = 0; tmp < end_pfn; tmp++)
- /*
- * Only count reserved RAM pages
- */
- if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
- reservedpages++;
+ totalram_pages = free_all_bootmem();
#endif
+ reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
after_bootmem = 1;
@@ -471,7 +430,7 @@ void __init mem_init(void)
kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START,
VSYSCALL_END - VSYSCALL_START);
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+ printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
end_pfn << (PAGE_SHIFT-10),
codesize >> 10,
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index ec35747aacd7..65417b040c1b 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -45,10 +45,12 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
unsigned long prevbase;
struct node nodes[8];
int nodeid, i, nb;
+ unsigned char nodeids[8];
int found = 0;
u32 reg;
unsigned numnodes;
nodemask_t nodes_parsed;
+ unsigned dualcore = 0;
nodes_clear(nodes_parsed);
@@ -67,11 +69,15 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
prevbase = 0;
for (i = 0; i < 8; i++) {
unsigned long base,limit;
-
+ u32 nodeid;
+
+ /* Undefined before E stepping, but hopefully 0 */
+ dualcore |= ((read_pci_config(0, nb, 3, 0xe8) >> 12) & 3) == 1;
base = read_pci_config(0, nb, 1, 0x40 + i*8);
limit = read_pci_config(0, nb, 1, 0x44 + i*8);
nodeid = limit & 7;
+ nodeids[i] = nodeid;
if ((base & 3) == 0) {
if (i < numnodes)
printk("Skipping disabled node %d\n", i);
@@ -157,8 +163,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
for (i = 0; i < 8; i++) {
if (nodes[i].start != nodes[i].end) {
- /* assume 1:1 NODE:CPU */
- cpu_to_node[i] = i;
+ nodeid = nodeids[i];
+ apicid_to_node[nodeid << dualcore] = i;
+ apicid_to_node[(nodeid << dualcore) + dualcore] = i;
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
}
}
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 6a156f5692ae..80a49d9bd8a7 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -22,14 +22,19 @@
#define Dprintk(x...)
#endif
-struct pglist_data *node_data[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
bootmem_data_t plat_node_bdata[MAX_NUMNODES];
int memnode_shift;
u8 memnodemap[NODEMAPSIZE];
-unsigned char cpu_to_node[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
-cpumask_t node_to_cpumask[MAX_NUMNODES];
+unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
+ [0 ... NR_CPUS-1] = NUMA_NO_NODE
+};
+unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+ [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
int numa_off __initdata;
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 8e3d097a9ddd..4b2e844c15a7 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -20,14 +20,20 @@
static struct acpi_table_slit *acpi_slit;
-/* Internal processor count */
-static unsigned int __initdata num_processors = 0;
-
static nodemask_t nodes_parsed __initdata;
static nodemask_t nodes_found __initdata;
static struct node nodes[MAX_NUMNODES] __initdata;
static __u8 pxm2node[256] = { [0 ... 255] = 0xff };
+static int node_to_pxm(int n);
+
+int pxm_to_node(int pxm)
+{
+ if ((unsigned)pxm >= 256)
+ return 0;
+ return pxm2node[pxm];
+}
+
static __init int setup_node(int pxm)
{
unsigned node = pxm2node[pxm];
@@ -44,14 +50,14 @@ static __init int setup_node(int pxm)
static __init int conflicting_nodes(unsigned long start, unsigned long end)
{
int i;
- for_each_online_node(i) {
+ for_each_node_mask(i, nodes_parsed) {
struct node *nd = &nodes[i];
if (nd->start == nd->end)
continue;
if (nd->end > start && nd->start < end)
- return 1;
+ return i;
if (nd->end == end && nd->start == start)
- return 1;
+ return i;
}
return -1;
}
@@ -75,8 +81,11 @@ static __init void cutoff_node(int i, unsigned long start, unsigned long end)
static __init void bad_srat(void)
{
+ int i;
printk(KERN_ERR "SRAT: SRAT not used.\n");
acpi_numa = -1;
+ for (i = 0; i < MAX_LOCAL_APIC; i++)
+ apicid_to_node[i] = NUMA_NO_NODE;
}
static __init inline int srat_disabled(void)
@@ -104,18 +113,10 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
bad_srat();
return;
}
- if (num_processors >= NR_CPUS) {
- printk(KERN_ERR "SRAT: Processor #%d (lapic %u) INVALID. (Max ID: %d).\n",
- num_processors, pa->apic_id, NR_CPUS);
- bad_srat();
- return;
- }
- cpu_to_node[num_processors] = node;
+ apicid_to_node[pa->apic_id] = node;
acpi_numa = 1;
- printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> CPU %u -> Node %u\n",
- pxm, pa->apic_id, num_processors, node);
-
- num_processors++;
+ printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+ pxm, pa->apic_id, node);
}
/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
@@ -143,10 +144,15 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
start, end);
i = conflicting_nodes(start, end);
- if (i >= 0) {
+ if (i == node) {
+ printk(KERN_WARNING
+ "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+ pxm, start, end, nodes[i].start, nodes[i].end);
+ } else if (i >= 0) {
printk(KERN_ERR
- "SRAT: pxm %d overlap %lx-%lx with node %d(%Lx-%Lx)\n",
- pxm, start, end, i, nodes[i].start, nodes[i].end);
+ "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
+ pxm, start, end, node_to_pxm(i),
+ nodes[i].start, nodes[i].end);
bad_srat();
return;
}
@@ -174,6 +180,14 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
int i;
if (acpi_numa <= 0)
return -1;
+
+ /* First clean up the node list */
+ for_each_node_mask(i, nodes_parsed) {
+ cutoff_node(i, start, end);
+ if (nodes[i].start == nodes[i].end)
+ node_clear(i, nodes_parsed);
+ }
+
memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
if (memnode_shift < 0) {
printk(KERN_ERR
@@ -181,16 +195,10 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
bad_srat();
return -1;
}
- for (i = 0; i < MAX_NUMNODES; i++) {
- if (!node_isset(i, nodes_parsed))
- continue;
- cutoff_node(i, start, end);
- if (nodes[i].start == nodes[i].end) {
- node_clear(i, nodes_parsed);
- continue;
- }
+
+ /* Finally register nodes */
+ for_each_node_mask(i, nodes_parsed)
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;
@@ -201,7 +209,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
return 0;
}
-int node_to_pxm(int n)
+static int node_to_pxm(int n)
{
int i;
if (pxm2node[n] == n)
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index 37c92e841dec..bb34e5ef916c 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -8,7 +8,7 @@ CFLAGS += -Iarch/i386/pci
obj-y := i386.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o
obj-y += fixup.o
-obj-$(CONFIG_ACPI_PCI) += acpi.o
+obj-$(CONFIG_ACPI) += acpi.o
obj-y += legacy.o irq.o common.o
# mmconfig has a 64bit special
obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
diff --git a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS
index 291985f0d2e4..4f0c05abd408 100644
--- a/arch/x86_64/pci/Makefile-BUS
+++ b/arch/x86_64/pci/Makefile-BUS
@@ -8,7 +8,7 @@ CFLAGS += -I arch/i386/pci
obj-y := i386.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o
obj-y += fixup.o
-obj-$(CONFIG_ACPI_PCI) += acpi.o
+obj-$(CONFIG_ACPI) += acpi.o
obj-y += legacy.o irq.o common.o
# mmconfig has a 64bit special
obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index d80c323669e0..3acf60ded2a0 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -58,10 +58,16 @@ fill_mp_bus_to_cpumask(void)
for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
j++) {
- int node = NODE_ID(nid);
+ struct pci_bus *bus;
+ long node = NODE_ID(nid);
+ /* Algorithm a bit dumb, but
+ it shouldn't matter here */
+ bus = pci_find_bus(0, j);
+ if (!bus)
+ continue;
if (!node_online(node))
node = 0;
- pci_bus_to_node[j] = node;
+ bus->sysdata = (void *)node;
}
}
}
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 657e88aa0902..a0838c4a94e4 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -111,13 +111,6 @@ static int __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return 0;
- /* Kludge for now. Don't use mmconfig on AMD systems because
- those have some busses where mmconfig doesn't work,
- and we don't parse ACPI MCFG well enough to handle that.
- Remove when proper handling is added. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
- return 0;
-
/* 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/Makefile b/arch/xtensa/Makefile
index 27847e4ffcbf..98fac8489aed 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -66,13 +66,7 @@ boot := arch/xtensa/boot
archinc := include/asm-xtensa
-arch/xtensa/kernel/asm-offsets.s: \
- arch/xtensa/kernel/asm-offsets.c $(archinc)/.platform
-
-include/asm-xtensa/offsets.h: arch/xtensa/kernel/asm-offsets.s
- $(call filechk,gen-asm-offsets)
-
-prepare: $(archinc)/.platform $(archinc)/offsets.h
+archprepare: $(archinc)/.platform
# Update machine cpu and platform symlinks if something which affects
# them changed.
@@ -94,7 +88,7 @@ bzImage : zImage
zImage zImage.initrd: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
-CLEAN_FILES += arch/xtensa/vmlinux.lds $(archinc)/offset.h \
+CLEAN_FILES += arch/xtensa/vmlinux.lds \
$(archinc)/platform $(archinc)/xtensa/config \
$(archinc)/.platform
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index 74b1e90ef08c..a4956578a24d 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -19,7 +19,7 @@
#include <asm/ptrace.h>
#include <asm/ptrace.h>
#include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index c64a01f71de6..5c018c503dfa 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -14,7 +14,7 @@
*/
#include <linux/linkage.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/uaccess.h>
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 4099703b14be..c83bb0d41787 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -43,7 +43,7 @@
#include <asm/mmu.h>
#include <asm/irq.h>
#include <asm/atomic.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/coprocessor.h>
extern void ret_from_fork(void);
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index df6e1e17b096..dc42cede9394 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -702,12 +702,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (ka.sa.sa_flags & SA_ONESHOT)
ka.sa.sa_handler = SIG_DFL;
- if (!(ka.sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
return 1;
}
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index e07287db5a40..1ac7d5ce7456 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -122,10 +122,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
return 0;
}
@@ -184,7 +181,7 @@ again:
next += CCOUNT_PER_JIFFY;
do_timer (regs); /* Linux handler in kernel/timer.c */
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
jiffies - wall_jiffies == 1) {
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 81808f0c6742..0e74397bfa2b 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -46,7 +46,7 @@
#include <asm/ptrace.h>
#include <asm/ptrace.h>
#include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 256c0b1fed10..89299f4ffe12 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -219,7 +219,7 @@ config CRYPTO_CAST6
described in RFC2612.
config CRYPTO_TEA
- tristate "TEA and XTEA cipher algorithms"
+ tristate "TEA, XTEA and XETA cipher algorithms"
depends on CRYPTO
help
TEA cipher algorithm.
@@ -232,6 +232,9 @@ config CRYPTO_TEA
the TEA algorithm to address a potential key weakness
in the TEA algorithm.
+ Xtendend Encryption Tiny Algorithm is a mis-implementation
+ of the XTEA algorithm for compatibility purposes.
+
config CRYPTO_ARC4
tristate "ARC4 cipher algorithm"
depends on CRYPTO
diff --git a/crypto/api.c b/crypto/api.c
index b4728811ce3b..959c4e5f264f 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -66,7 +66,8 @@ static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
{
- tfm->crt_flags = 0;
+ tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
+ flags &= ~CRYPTO_TFM_REQ_MASK;
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 8da644364cb4..dfd4bcfc5975 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -191,6 +191,8 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
u8 *iv = desc->info;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
xor(iv, src);
fn(crypto_tfm_ctx(tfm), dst, iv);
@@ -198,7 +200,7 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
@@ -219,6 +221,8 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
u8 *iv = desc->info;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
u8 *tmp_dst = *dst_p;
@@ -230,7 +234,7 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
@@ -243,12 +247,14 @@ static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
unsigned int done = 0;
+ nbytes -= bsize;
+
do {
fn(crypto_tfm_ctx(tfm), dst, src);
src += bsize;
dst += bsize;
- } while ((done += bsize) < nbytes);
+ } while ((done += bsize) <= nbytes);
return done;
}
@@ -377,11 +383,7 @@ static int nocrypt_iv(struct crypto_tfm *tfm,
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
{
u32 mode = flags & CRYPTO_TFM_MODE_MASK;
-
tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
- if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
- tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
-
return 0;
}
diff --git a/crypto/internal.h b/crypto/internal.h
index 37515beafc8c..37aa652ce5ce 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <asm/kmap_types.h>
extern enum km_type crypto_km_types[];
@@ -38,7 +39,7 @@ static inline void crypto_kunmap(void *vaddr, int out)
static inline void crypto_yield(struct crypto_tfm *tfm)
{
- if (!in_atomic())
+ if (tfm->crt_flags & CRYPTO_TFM_REQ_MAY_SLEEP)
cond_resched();
}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index bd7524cfff33..68639419c5bd 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -72,7 +72,7 @@ static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
- "khazad", "wp512", "wp384", "wp256", "tnepres", NULL
+ "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL
};
static void hexdump(unsigned char *buf, unsigned int len)
@@ -859,6 +859,10 @@ static void do_test(void)
test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
+ //XETA
+ test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS);
+ test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS);
+
test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -1016,6 +1020,11 @@ static void do_test(void)
case 29:
test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
break;
+
+ case 30:
+ test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS);
+ test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS);
+ break;
#ifdef CONFIG_CRYPTO_HMAC
case 100:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index c01a0ce9b40a..522ffd4b6f43 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -2211,7 +2211,7 @@ static struct cipher_testvec xtea_enc_tv_template[] = {
.klen = 16,
.input = { [0 ... 8] = 0x00 },
.ilen = 8,
- .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .result = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
.rlen = 8,
}, {
.key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
@@ -2219,31 +2219,31 @@ static struct cipher_testvec xtea_enc_tv_template[] = {
.klen = 16,
.input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
.ilen = 8,
- .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .result = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
.rlen = 8,
}, {
.key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
- .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.ilen = 16,
- .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
.rlen = 16,
}, {
.key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.ilen = 32,
- .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
- 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .result = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+ 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+ 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+ 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
.rlen = 32,
}
};
@@ -2252,7 +2252,7 @@ static struct cipher_testvec xtea_dec_tv_template[] = {
{
.key = { [0 ... 15] = 0x00 },
.klen = 16,
- .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .input = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
.ilen = 8,
.result = { [0 ... 8] = 0x00 },
.rlen = 8,
@@ -2260,7 +2260,7 @@ static struct cipher_testvec xtea_dec_tv_template[] = {
.key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
.klen = 16,
- .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .input = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
.ilen = 8,
.result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
.rlen = 8,
@@ -2268,24 +2268,24 @@ static struct cipher_testvec xtea_dec_tv_template[] = {
.key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
- .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
- 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+ .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+ 0x77, 0x4d, 0xd4, 0xb4, 0x87, 0x24, 0xe3, 0x9a },
.ilen = 16,
- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.rlen = 16,
}, {
.key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
- .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
- 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .input = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+ 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+ 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+ 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
.ilen = 32,
- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.rlen = 32,
}
@@ -2594,6 +2594,98 @@ static struct cipher_testvec anubis_cbc_dec_tv_template[] = {
},
};
+/*
+ * XETA test vectors
+ */
+#define XETA_ENC_TEST_VECTORS 4
+#define XETA_DEC_TEST_VECTORS 4
+
+static struct cipher_testvec xeta_enc_tv_template[] = {
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { [0 ... 8] = 0x00 },
+ .ilen = 8,
+ .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .ilen = 8,
+ .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .ilen = 16,
+ .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .ilen = 32,
+ .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .rlen = 32,
+ }
+};
+
+static struct cipher_testvec xeta_dec_tv_template[] = {
+ {
+ .key = { [0 ... 15] = 0x00 },
+ .klen = 16,
+ .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+ .ilen = 8,
+ .result = { [0 ... 8] = 0x00 },
+ .rlen = 8,
+ }, {
+ .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+ 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+ .klen = 16,
+ .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+ .ilen = 8,
+ .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+ .rlen = 8,
+ }, {
+ .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+ 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+ .klen = 16,
+ .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+ .ilen = 16,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+ .rlen = 16,
+ }, {
+ .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+ 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+ .klen = 16,
+ .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+ .ilen = 32,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+ .rlen = 32,
+ }
+};
+
/*
* Compression stuff.
*/
diff --git a/crypto/tea.c b/crypto/tea.c
index 03c23cbd3afa..5924efdd3a16 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -1,11 +1,15 @@
/*
* Cryptographic API.
*
- * TEA and Xtended TEA Algorithms
+ * TEA, XTEA, and XETA crypto alogrithms
*
* The TEA and Xtended TEA algorithms were developed by David Wheeler
* and Roger Needham at the Computer Laboratory of Cambridge University.
*
+ * Due to the order of evaluation in XTEA many people have incorrectly
+ * implemented it. XETA (XTEA in the wrong order), exists for
+ * compatibility with these implementations.
+ *
* Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
*
* This program is free software; you can redistribute it and/or modify
@@ -153,9 +157,9 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
z = u32_in (src + 4);
while (sum != limit) {
- y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
+ y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]);
sum += XTEA_DELTA;
- z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
+ z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]);
}
u32_out (dst, y);
@@ -175,6 +179,51 @@ static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
sum = XTEA_DELTA * XTEA_ROUNDS;
while (sum) {
+ z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]);
+ sum -= XTEA_DELTA;
+ y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]);
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+
+}
+
+
+static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+
+ u32 y, z, sum = 0;
+ u32 limit = XTEA_DELTA * XTEA_ROUNDS;
+
+ struct xtea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ while (sum != limit) {
+ y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
+ sum += XTEA_DELTA;
+ z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
+ }
+
+ u32_out (dst, y);
+ u32_out (dst + 4, z);
+
+}
+
+static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+
+ u32 y, z, sum;
+ struct tea_ctx *ctx = ctx_arg;
+
+ y = u32_in (src);
+ z = u32_in (src + 4);
+
+ sum = XTEA_DELTA * XTEA_ROUNDS;
+
+ while (sum) {
z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
sum -= XTEA_DELTA;
y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
@@ -215,6 +264,21 @@ static struct crypto_alg xtea_alg = {
.cia_decrypt = xtea_decrypt } }
};
+static struct crypto_alg xeta_alg = {
+ .cra_name = "xeta",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = XTEA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof (struct xtea_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = XTEA_KEY_SIZE,
+ .cia_max_keysize = XTEA_KEY_SIZE,
+ .cia_setkey = xtea_setkey,
+ .cia_encrypt = xeta_encrypt,
+ .cia_decrypt = xeta_decrypt } }
+};
+
static int __init init(void)
{
int ret = 0;
@@ -229,6 +293,13 @@ static int __init init(void)
goto out;
}
+ ret = crypto_register_alg(&xeta_alg);
+ if (ret < 0) {
+ crypto_unregister_alg(&tea_alg);
+ crypto_unregister_alg(&xtea_alg);
+ goto out;
+ }
+
out:
return ret;
}
@@ -237,12 +308,14 @@ static void __exit fini(void)
{
crypto_unregister_alg(&tea_alg);
crypto_unregister_alg(&xtea_alg);
+ crypto_unregister_alg(&xeta_alg);
}
MODULE_ALIAS("xtea");
+MODULE_ALIAS("xeta");
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");
+MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");
diff --git a/drivers/Kconfig b/drivers/Kconfig
index cecab0acc3fe..48f446d3c671 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -4,6 +4,8 @@ menu "Device Drivers"
source "drivers/base/Kconfig"
+source "drivers/connector/Kconfig"
+
source "drivers/mtd/Kconfig"
source "drivers/parport/Kconfig"
@@ -48,6 +50,8 @@ source "drivers/hwmon/Kconfig"
source "drivers/misc/Kconfig"
+source "drivers/mfd/Kconfig"
+
source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 126a851d5653..1a109a6dd953 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -8,7 +8,7 @@
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-y += video/
-obj-$(CONFIG_ACPI_BOOT) += acpi/
+obj-$(CONFIG_ACPI) += acpi/
# PnP must come after ACPI since it will eventually need to check if acpi
# was used and do nothing if so
obj-$(CONFIG_PNP) += pnp/
@@ -17,6 +17,8 @@ obj-$(CONFIG_PNP) += pnp/
# default.
obj-y += char/
+obj-$(CONFIG_CONNECTOR) += connector/
+
# i810fb and intelfb depend on char/agp/
obj-$(CONFIG_FB_I810) += video/i810/
obj-$(CONFIG_FB_INTEL) += video/intelfb/
@@ -26,7 +28,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/
obj-$(CONFIG_SERIO) += input/serio/
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
-obj-y += base/ block/ misc/ net/ media/
+obj-y += base/ block/ misc/ mfd/ net/ media/
obj-$(CONFIG_NUBUS) += nubus/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_PPC_PMAC) += macintosh/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index c0a37d98b4f3..048542341204 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -376,19 +376,15 @@ static void do_fd_request(request_queue_t *);
/************************* End of Prototypes **************************/
-static struct timer_list motor_off_timer =
- TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
#ifdef TRACKBUFFER
-static struct timer_list readtrack_timer =
- TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
#endif
-static struct timer_list timeout_timer =
- TIMER_INITIALIZER(fd_times_out, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
-static struct timer_list fd_timer =
- TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
/* DAG: Haven't got a clue what this is? */
int stdma_islocked(void)
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ba13896cae40..fe1e8126fbae 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -3,7 +3,6 @@
#
menu "ACPI (Advanced Configuration and Power Interface) Support"
- depends on PM
depends on !X86_VISWS
depends on !IA64_HP_SIM
depends on IA64 || X86
@@ -11,6 +10,8 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
config ACPI
bool "ACPI Support"
depends on IA64 || X86
+ select PM
+ select PCI
default y
---help---
@@ -43,20 +44,10 @@ config ACPI
if ACPI
-config ACPI_BOOT
- bool
- default y
-
-config ACPI_INTERPRETER
- bool
- default y
-
-if ACPI_INTERPRETER
-
config ACPI_SLEEP
- bool "Sleep States (EXPERIMENTAL)"
+ bool "Sleep States"
depends on X86 && (!SMP || SUSPEND_SMP)
- depends on EXPERIMENTAL && PM
+ depends on PM
default y
---help---
This option adds support for ACPI suspend states.
@@ -90,16 +81,16 @@ config ACPI_SLEEP_PROC_SLEEP
config ACPI_AC
tristate "AC Adapter"
depends on X86
- default m
+ default y
help
This driver adds support for the AC Adapter object, which indicates
- whether a system is on AC, or not. Typically, only mobile systems
- have this object, since desktops are always on AC.
+ whether a system is on AC, or not. If you have a system that can
+ switch between A/C and battery, say Y.
config ACPI_BATTERY
tristate "Battery"
depends on X86
- default m
+ default y
help
This driver adds support for battery information through
/proc/acpi/battery. If you have a mobile system with a battery,
@@ -107,18 +98,17 @@ config ACPI_BATTERY
config ACPI_BUTTON
tristate "Button"
- default m
+ default y
help
- This driver registers for events based on buttons, such as the
- power, sleep, and lid switch. In the future, a daemon will read
- /proc/acpi/event and perform user-defined actions such as shutting
- down the system. Until then, you can cat it, and see output when
- a button is pressed.
+ This driver handles events on the power, sleep and lid buttons.
+ A daemon reads /proc/acpi/event and perform user-defined actions
+ such as shutting down the system. This is necessary for
+ software controlled poweroff.
config ACPI_VIDEO
tristate "Video"
- depends on EXPERIMENTAL
- default m
+ depends on X86
+ default y
help
This driver implement the ACPI Extensions For Display Adapters
for integrated graphics devices on motherboard, as specified in
@@ -129,10 +119,9 @@ config ACPI_VIDEO
for your integrated video device.
config ACPI_HOTKEY
- tristate "Generic Hotkey"
- depends on ACPI_INTERPRETER
+ tristate "Generic Hotkey (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on !IA64_SGI_SN
+ depends on X86
default n
help
Experimental consolidated hotkey driver.
@@ -140,31 +129,30 @@ config ACPI_HOTKEY
config ACPI_FAN
tristate "Fan"
- default m
+ default y
help
This driver adds support for ACPI fan devices, allowing user-mode
applications to perform basic fan control (on, off, status).
config ACPI_PROCESSOR
tristate "Processor"
- default m
+ default y
help
This driver installs ACPI as the idle handler for Linux, and uses
ACPI C2 and C3 processor states to save power, on systems that
- support it.
+ support it. It is required by several flavors of cpufreq
+ Performance-state drivers.
config ACPI_HOTPLUG_CPU
- bool "Processor Hotplug (EXPERIMENTAL)"
- depends on ACPI_PROCESSOR && HOTPLUG_CPU && EXPERIMENTAL
+ bool
+ depends on ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_CONTAINER
- default n
- ---help---
- Select this option if your platform support physical CPU hotplug.
+ default y
config ACPI_THERMAL
tristate "Thermal Zone"
depends on ACPI_PROCESSOR
- default m
+ default y
help
This driver adds support for ACPI thermal zones. Most mobile and
some desktop systems support ACPI thermal zones. It is HIGHLY
@@ -180,7 +168,7 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
- default m
+ default y
---help---
This driver provides support for extra features of ACPI-compatible
ASUS laptops. As some of Medion laptops are made by ASUS, it may also
@@ -209,7 +197,7 @@ config ACPI_ASUS
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
- default m
+ default y
---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
@@ -222,7 +210,7 @@ config ACPI_IBM
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
- default m
+ default y
---help---
This driver adds support for access to certain system settings
on "legacy free" Toshiba laptops. These laptops can be recognized by
@@ -262,8 +250,7 @@ config ACPI_CUSTOM_DSDT_FILE
Enter the full path name to the file wich includes the AmlCode declaration.
config ACPI_BLACKLIST_YEAR
- int "Disable ACPI for systems before Jan 1st this year"
- depends on ACPI_INTERPRETER
+ int "Disable ACPI for systems before Jan 1st this year" if X86
default 0
help
enter a 4-digit year, eg. 2001 to disable ACPI by default
@@ -281,10 +268,6 @@ config ACPI_DEBUG
of verbosity. Saying Y enables these statements. This will increase
your kernel size by around 50K.
-config ACPI_BUS
- bool
- default y
-
config ACPI_EC
bool
depends on X86
@@ -298,10 +281,6 @@ config ACPI_POWER
bool
default y
-config ACPI_PCI
- bool
- default PCI
-
config ACPI_SYSTEM
bool
default y
@@ -309,14 +288,11 @@ config ACPI_SYSTEM
This driver will enable your system to shut down using ACPI, and
dump your ACPI DSDT table using /proc/acpi/dsdt.
-endif # ACPI_INTERPRETER
-
config X86_PM_TIMER
bool "Power Management Timer Support"
depends on X86
- depends on ACPI_BOOT && EXPERIMENTAL
depends on !X86_64
- default n
+ default y
help
The Power Management Timer is available on all ACPI-capable,
in most cases even if ACPI is unusable or blacklisted.
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index ad67e8f61e6c..a18243488c66 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -15,13 +15,13 @@ EXTRA_CFLAGS += $(ACPI_CFLAGS)
#
# ACPI Boot-Time Table Parsing
#
-obj-$(CONFIG_ACPI_BOOT) += tables.o
-obj-$(CONFIG_ACPI_INTERPRETER) += blacklist.o
+obj-y += tables.o
+obj-y += blacklist.o
#
# ACPI Core Subsystem (Interpreter)
#
-obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \
+obj-y += osl.o utils.o \
dispatcher/ events/ executer/ hardware/ \
namespace/ parser/ resources/ tables/ \
utilities/
@@ -35,8 +35,8 @@ ifdef CONFIG_CPU_FREQ
processor-objs += processor_perflib.o
endif
-obj-$(CONFIG_ACPI_BUS) += sleep/
-obj-$(CONFIG_ACPI_BUS) += bus.o glue.o
+obj-y += sleep/
+obj-y += bus.o glue.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
@@ -44,7 +44,7 @@ obj-$(CONFIG_ACPI_EC) += ec.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o
-obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o
+obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
@@ -55,5 +55,5 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
-obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o
+obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 23ab761dd721..7839b831df94 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -32,7 +32,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_AC_COMPONENT 0x00020000
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_HID "ACPI0003"
@@ -45,47 +44,45 @@
#define ACPI_AC_STATUS_UNKNOWN 0xFF
#define _COMPONENT ACPI_AC_COMPONENT
-ACPI_MODULE_NAME ("acpi_ac")
+ACPI_MODULE_NAME("acpi_ac")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_ac_add (struct acpi_device *device);
-static int acpi_ac_remove (struct acpi_device *device, int type);
+static int acpi_ac_add(struct acpi_device *device);
+static int acpi_ac_remove(struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_ac_driver = {
- .name = ACPI_AC_DRIVER_NAME,
- .class = ACPI_AC_CLASS,
- .ids = ACPI_AC_HID,
- .ops = {
- .add = acpi_ac_add,
- .remove = acpi_ac_remove,
- },
+ .name = ACPI_AC_DRIVER_NAME,
+ .class = ACPI_AC_CLASS,
+ .ids = ACPI_AC_HID,
+ .ops = {
+ .add = acpi_ac_add,
+ .remove = acpi_ac_remove,
+ },
};
struct acpi_ac {
- acpi_handle handle;
- unsigned long state;
+ acpi_handle handle;
+ unsigned long state;
};
static struct file_operations acpi_ac_fops = {
- .open = acpi_ac_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_ac_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
AC Adapter Management
-------------------------------------------------------------------------- */
-static int
-acpi_ac_get_state (
- struct acpi_ac *ac)
+static int acpi_ac_get_state(struct acpi_ac *ac)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_ac_get_state");
@@ -95,24 +92,23 @@ acpi_ac_get_state (
status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading AC Adapter state\n"));
+ "Error reading AC Adapter state\n"));
ac->state = ACPI_AC_STATUS_UNKNOWN;
return_VALUE(-ENODEV);
}
-
+
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_ac_dir;
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_ac *ac = (struct acpi_ac *) seq->private;
+ struct acpi_ac *ac = (struct acpi_ac *)seq->private;
ACPI_FUNCTION_TRACE("acpi_ac_seq_show");
@@ -139,23 +135,21 @@ static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
return_VALUE(0);
}
-
+
static int acpi_ac_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
}
-static int
-acpi_ac_add_fs (
- struct acpi_device *device)
+static int acpi_ac_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_ac_dir);
+ acpi_ac_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -163,11 +157,11 @@ acpi_ac_add_fs (
/* 'state' [R] */
entry = create_proc_entry(ACPI_AC_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_AC_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_AC_FILE_STATE));
else {
entry->proc_fops = &acpi_ac_fops;
entry->data = acpi_driver_data(device);
@@ -177,16 +171,12 @@ acpi_ac_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_ac_remove_fs (
- struct acpi_device *device)
+static int acpi_ac_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_AC_FILE_STATE,
- acpi_device_dir(device));
+ remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
acpi_device_dir(device) = NULL;
@@ -195,19 +185,14 @@ acpi_ac_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Model
-------------------------------------------------------------------------- */
-static void
-acpi_ac_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_ac *ac = (struct acpi_ac *) data;
- struct acpi_device *device = NULL;
+ struct acpi_ac *ac = (struct acpi_ac *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_notify");
@@ -224,21 +209,18 @@ acpi_ac_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_ac_add (
- struct acpi_device *device)
+static int acpi_ac_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_ac *ac = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add");
@@ -264,19 +246,20 @@ acpi_ac_add (
goto end;
status = acpi_install_notify_handler(ac->handle,
- ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac);
+ ACPI_DEVICE_NOTIFY, acpi_ac_notify,
+ ac);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
- printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
- acpi_device_name(device), acpi_device_bid(device),
- ac->state?"on-line":"off-line");
+ printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ ac->state ? "on-line" : "off-line");
-end:
+ end:
if (result) {
acpi_ac_remove_fs(device);
kfree(ac);
@@ -285,27 +268,23 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_ac_remove (
- struct acpi_device *device,
- int type)
+static int acpi_ac_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_ac *ac = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- ac = (struct acpi_ac *) acpi_driver_data(device);
+ ac = (struct acpi_ac *)acpi_driver_data(device);
status = acpi_remove_notify_handler(ac->handle,
- ACPI_DEVICE_NOTIFY, acpi_ac_notify);
+ ACPI_DEVICE_NOTIFY, acpi_ac_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_ac_remove_fs(device);
@@ -314,11 +293,9 @@ acpi_ac_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_ac_init (void)
+static int __init acpi_ac_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ac_init");
@@ -336,9 +313,7 @@ acpi_ac_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_ac_exit (void)
+static void __exit acpi_ac_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_ac_exit");
@@ -349,6 +324,5 @@ acpi_ac_exit (void)
return_VOID;
}
-
module_init(acpi_ac_init);
module_exit(acpi_ac_exit);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 77285ffe41c5..01a1bd239263 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -32,7 +32,6 @@
#include <linux/memory_hotplug.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
#define ACPI_MEMORY_DEVICE_CLASS "memory"
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
@@ -41,8 +40,8 @@
#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
-ACPI_MODULE_NAME ("acpi_memory")
-MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+ACPI_MODULE_NAME("acpi_memory")
+ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -56,34 +55,33 @@ MODULE_LICENSE("GPL");
#define MEMORY_POWER_ON_STATE 1
#define MEMORY_POWER_OFF_STATE 2
-static int acpi_memory_device_add (struct acpi_device *device);
-static int acpi_memory_device_remove (struct acpi_device *device, int type);
+static int acpi_memory_device_add(struct acpi_device *device);
+static int acpi_memory_device_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_memory_device_driver = {
- .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
- .class = ACPI_MEMORY_DEVICE_CLASS,
- .ids = ACPI_MEMORY_DEVICE_HID,
- .ops = {
- .add = acpi_memory_device_add,
- .remove = acpi_memory_device_remove,
- },
+ .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+ .class = ACPI_MEMORY_DEVICE_CLASS,
+ .ids = ACPI_MEMORY_DEVICE_HID,
+ .ops = {
+ .add = acpi_memory_device_add,
+ .remove = acpi_memory_device_remove,
+ },
};
struct acpi_memory_device {
acpi_handle handle;
- unsigned int state; /* State of the memory device */
+ unsigned int state; /* State of the memory device */
unsigned short cache_attribute; /* memory cache attribute */
- unsigned short read_write_attribute;/* memory read/write attribute */
- u64 start_addr; /* Memory Range start physical addr */
- u64 end_addr; /* Memory Range end physical addr */
+ unsigned short read_write_attribute; /* memory read/write attribute */
+ u64 start_addr; /* Memory Range start physical addr */
+ u64 end_addr; /* Memory Range end physical addr */
};
-
static int
acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
{
acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_resource *resource = NULL;
struct acpi_resource_address64 address64;
@@ -94,15 +92,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
if (ACPI_FAILURE(status))
return_VALUE(-EINVAL);
- resource = (struct acpi_resource *) buffer.pointer;
+ resource = (struct acpi_resource *)buffer.pointer;
status = acpi_resource_to_address64(resource, &address64);
if (ACPI_SUCCESS(status)) {
if (address64.resource_type == ACPI_MEMORY_RANGE) {
/* Populate the structure */
mem_device->cache_attribute =
- address64.attribute.memory.cache_attribute;
+ address64.attribute.memory.cache_attribute;
mem_device->read_write_attribute =
- address64.attribute.memory.read_write_attribute;
+ address64.attribute.memory.read_write_attribute;
mem_device->start_addr = address64.min_address_range;
mem_device->end_addr = address64.max_address_range;
}
@@ -114,7 +112,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
static int
acpi_memory_get_device(acpi_handle handle,
- struct acpi_memory_device **mem_device)
+ struct acpi_memory_device **mem_device)
{
acpi_status status;
acpi_handle phandle;
@@ -128,8 +126,7 @@ acpi_memory_get_device(acpi_handle handle,
status = acpi_get_parent(handle, &phandle);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_get_parent\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_get_parent\n"));
return_VALUE(-EINVAL);
}
@@ -137,7 +134,7 @@ acpi_memory_get_device(acpi_handle handle,
status = acpi_bus_get_device(phandle, &pdevice);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_bus_get_device\n"));
+ "Error in acpi_bus_get_device\n"));
return_VALUE(-EINVAL);
}
@@ -147,23 +144,21 @@ acpi_memory_get_device(acpi_handle handle,
*/
status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_bus_add\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_bus_add\n"));
return_VALUE(-EINVAL);
}
-end:
+ end:
*mem_device = acpi_driver_data(device);
if (!(*mem_device)) {
- printk(KERN_ERR "\n driver data not found" );
+ printk(KERN_ERR "\n driver data not found");
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
-static int
-acpi_memory_check_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
unsigned long current_status;
@@ -171,22 +166,21 @@ acpi_memory_check_device(struct acpi_memory_device *mem_device)
/* Get device present/absent information from the _STA */
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
- NULL, &current_status)))
+ NULL, &current_status)))
return_VALUE(-ENODEV);
/*
* Check for device status. Device should be
* present/enabled/functioning.
*/
if (!((current_status & ACPI_MEMORY_STA_PRESENT)
- && (current_status & ACPI_MEMORY_STA_ENABLED)
- && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
+ && (current_status & ACPI_MEMORY_STA_ENABLED)
+ && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
return_VALUE(-ENODEV);
return_VALUE(0);
}
-static int
-acpi_memory_enable_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
{
int result;
@@ -196,7 +190,7 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
result = acpi_memory_get_device_resources(mem_device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "\nget_device_resources failed\n"));
+ "\nget_device_resources failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
return result;
}
@@ -206,11 +200,10 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
* 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,
- mem_device->read_write_attribute);
+ (mem_device->end_addr - mem_device->start_addr) + 1,
+ mem_device->read_write_attribute);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "\nadd_memory failed\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
return result;
}
@@ -218,11 +211,10 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
return result;
}
-static int
-acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
{
acpi_status status;
- struct acpi_object_list arg_list;
+ struct acpi_object_list arg_list;
union acpi_object arg;
unsigned long current_status;
@@ -234,16 +226,16 @@ acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = 1;
status = acpi_evaluate_object(mem_device->handle,
- "_EJ0", &arg_list, NULL);
+ "_EJ0", &arg_list, NULL);
/* Return on _EJ0 failure */
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "_EJ0 failed.\n"));
return_VALUE(-ENODEV);
}
/* Evalute _STA to check if the device is disabled */
status = acpi_evaluate_integer(mem_device->handle, "_STA",
- NULL, &current_status);
+ NULL, &current_status);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -254,8 +246,7 @@ acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
return_VALUE(0);
}
-static int
-acpi_memory_disable_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
{
int result;
u64 start = mem_device->start_addr;
@@ -278,7 +269,7 @@ acpi_memory_disable_device(struct acpi_memory_device *mem_device)
result = acpi_memory_powerdown_device(mem_device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device Power Down failed.\n"));
+ "Device Power Down failed.\n"));
/* Set the status of the device to invalid */
mem_device->state = MEMORY_INVALID_STATE;
return result;
@@ -288,8 +279,7 @@ acpi_memory_disable_device(struct acpi_memory_device *mem_device)
return result;
}
-static void
-acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_memory_device *mem_device;
struct acpi_device *device;
@@ -299,37 +289,37 @@ acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived BUS CHECK notification for device\n"));
+ "\nReceived BUS CHECK notification for device\n"));
/* Fall Through */
case ACPI_NOTIFY_DEVICE_CHECK:
if (event == ACPI_NOTIFY_DEVICE_CHECK)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived DEVICE CHECK notification for device\n"));
+ "\nReceived DEVICE CHECK notification for device\n"));
if (acpi_memory_get_device(handle, &mem_device)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in finding driver data\n"));
+ "Error in finding driver data\n"));
return_VOID;
}
if (!acpi_memory_check_device(mem_device)) {
if (acpi_memory_enable_device(mem_device))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_enable_device\n"));
+ "Error in acpi_memory_enable_device\n"));
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived EJECT REQUEST notification for device\n"));
+ "\nReceived EJECT REQUEST notification for device\n"));
if (acpi_bus_get_device(handle, &device)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device doesn't exist\n"));
+ "Device doesn't exist\n"));
break;
}
mem_device = acpi_driver_data(device);
if (!mem_device) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Driver Data is NULL\n"));
+ "Driver Data is NULL\n"));
break;
}
@@ -337,26 +327,25 @@ acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
* Currently disabling memory device from kernel mode
* TBD: Can also be disabled from user mode scripts
* TBD: Can also be disabled by Callback registration
- * with generic sysfs driver
+ * with generic sysfs driver
*/
if (acpi_memory_disable_device(mem_device))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_disable_device\n"));
+ "Error in acpi_memory_disable_device\n"));
/*
* TBD: Invoke acpi_bus_remove to cleanup data structures
*/
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static int
-acpi_memory_device_add(struct acpi_device *device)
+static int acpi_memory_device_add(struct acpi_device *device)
{
int result;
struct acpi_memory_device *mem_device = NULL;
@@ -391,8 +380,7 @@ acpi_memory_device_add(struct acpi_device *device)
return_VALUE(result);
}
-static int
-acpi_memory_device_remove (struct acpi_device *device, int type)
+static int acpi_memory_device_remove(struct acpi_device *device, int type)
{
struct acpi_memory_device *mem_device = NULL;
@@ -401,7 +389,7 @@ acpi_memory_device_remove (struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- mem_device = (struct acpi_memory_device *) acpi_driver_data(device);
+ mem_device = (struct acpi_memory_device *)acpi_driver_data(device);
kfree(mem_device);
return_VALUE(0);
@@ -410,12 +398,11 @@ acpi_memory_device_remove (struct acpi_device *device, int type)
/*
* Helper function to check for memory device
*/
-static acpi_status
-is_memory_device(acpi_handle handle)
+static acpi_status is_memory_device(acpi_handle handle)
{
char *hardware_id;
acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info;
ACPI_FUNCTION_TRACE("is_memory_device");
@@ -432,7 +419,7 @@ is_memory_device(acpi_handle handle)
hardware_id = info->hardware_id.value;
if ((hardware_id == NULL) ||
- (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
+ (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
status = AE_ERROR;
acpi_os_free(buffer.pointer);
@@ -440,8 +427,8 @@ is_memory_device(acpi_handle handle)
}
static acpi_status
-acpi_memory_register_notify_handler (acpi_handle handle,
- u32 level, void *ctxt, void **retv)
+acpi_memory_register_notify_handler(acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
{
acpi_status status;
@@ -452,10 +439,10 @@ acpi_memory_register_notify_handler (acpi_handle handle,
return_ACPI_STATUS(AE_OK); /* continue */
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- acpi_memory_device_notify, NULL);
+ acpi_memory_device_notify, NULL);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
return_ACPI_STATUS(AE_OK); /* continue */
}
@@ -463,8 +450,8 @@ acpi_memory_register_notify_handler (acpi_handle handle,
}
static acpi_status
-acpi_memory_deregister_notify_handler (acpi_handle handle,
- u32 level, void *ctxt, void **retv)
+acpi_memory_deregister_notify_handler(acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
{
acpi_status status;
@@ -475,18 +462,18 @@ acpi_memory_deregister_notify_handler (acpi_handle handle,
return_ACPI_STATUS(AE_OK); /* continue */
status = acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_memory_device_notify);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
return_ACPI_STATUS(AE_OK); /* continue */
}
return_ACPI_STATUS(status);
}
-static int __init
-acpi_memory_device_init (void)
+static int __init acpi_memory_device_init(void)
{
int result;
acpi_status status;
@@ -499,21 +486,20 @@ acpi_memory_device_init (void)
return_VALUE(-ENODEV);
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_register_notify_handler,
- NULL, NULL);
+ ACPI_UINT32_MAX,
+ acpi_memory_register_notify_handler,
+ NULL, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed\n"));
acpi_bus_unregister_driver(&acpi_memory_device_driver);
return_VALUE(-ENODEV);
- }
+ }
return_VALUE(0);
}
-static void __exit
-acpi_memory_device_exit (void)
+static void __exit acpi_memory_device_exit(void)
{
acpi_status status;
@@ -524,12 +510,12 @@ acpi_memory_device_exit (void)
* handles.
*/
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_deregister_notify_handler,
- NULL, NULL);
+ ACPI_UINT32_MAX,
+ acpi_memory_deregister_notify_handler,
+ NULL, NULL);
- if (ACPI_FAILURE (status))
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed\n"));
acpi_bus_unregister_driver(&acpi_memory_device_driver);
@@ -538,5 +524,3 @@ acpi_memory_device_exit (void)
module_init(acpi_memory_device_init);
module_exit(acpi_memory_device_exit);
-
-
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index a560b1e2da77..fec895af6ae6 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -61,7 +61,7 @@
/*
* Some events we use, same for all Asus
*/
-#define BR_UP 0x10
+#define BR_UP 0x10
#define BR_DOWN 0x20
/*
@@ -75,7 +75,6 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
MODULE_LICENSE("GPL");
-
static uid_t asus_uid;
static gid_t asus_gid;
module_param(asus_uid, uint, 0);
@@ -83,26 +82,25 @@ MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
module_param(asus_gid, uint, 0);
MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n");
-
/* For each model, all features implemented,
* those marked with R are relative to HOTK, A for absolute */
struct model_data {
- char *name; //name of the laptop________________A
- char *mt_mled; //method to handle mled_____________R
- char *mled_status; //node to handle mled reading_______A
- char *mt_wled; //method to handle wled_____________R
- char *wled_status; //node to handle wled reading_______A
- char *mt_tled; //method to handle tled_____________R
- char *tled_status; //node to handle tled reading_______A
- char *mt_lcd_switch; //method to turn LCD ON/OFF_________A
- char *lcd_status; //node to read LCD panel state______A
- char *brightness_up; //method to set brightness up_______A
- char *brightness_down; //guess what ?______________________A
- char *brightness_set; //method to set absolute brightness_R
- char *brightness_get; //method to get absolute brightness_R
- char *brightness_status; //node to get brightness____________A
- char *display_set; //method to set video output________R
- char *display_get; //method to get video output________R
+ char *name; //name of the laptop________________A
+ char *mt_mled; //method to handle mled_____________R
+ char *mled_status; //node to handle mled reading_______A
+ char *mt_wled; //method to handle wled_____________R
+ char *wled_status; //node to handle wled reading_______A
+ char *mt_tled; //method to handle tled_____________R
+ char *tled_status; //node to handle tled reading_______A
+ char *mt_lcd_switch; //method to turn LCD ON/OFF_________A
+ char *lcd_status; //node to read LCD panel state______A
+ char *brightness_up; //method to set brightness up_______A
+ char *brightness_down; //guess what ?______________________A
+ char *brightness_set; //method to set absolute brightness_R
+ char *brightness_get; //method to get absolute brightness_R
+ char *brightness_status; //node to get brightness____________A
+ char *display_set; //method to set video output________R
+ char *display_get; //method to get video output________R
};
/*
@@ -110,34 +108,34 @@ struct model_data {
* about the hotk device
*/
struct asus_hotk {
- struct acpi_device *device; //the device we are in
- acpi_handle handle; //the handle of the hotk device
- char status; //status of the hotk, for LEDs, ...
- struct model_data *methods; //methods available on the laptop
- u8 brightness; //brightness level
+ struct acpi_device *device; //the device we are in
+ acpi_handle handle; //the handle of the hotk device
+ char status; //status of the hotk, for LEDs, ...
+ struct model_data *methods; //methods available on the laptop
+ u8 brightness; //brightness level
enum {
- A1x = 0, //A1340D, A1300F
- A2x, //A2500H
- D1x, //D1
- L2D, //L2000D
- L3C, //L3800C
- L3D, //L3400D
- L3H, //L3H, but also L2000E
- L4R, //L4500R
- L5x, //L5800C
- L8L, //L8400L
- M1A, //M1300A
- M2E, //M2400E, L4400L
- M6N, //M6800N
- M6R, //M6700R
- P30, //Samsung P30
- S1x, //S1300A, but also L1400B and M2400A (L84F)
- S2x, //S200 (J1 reported), Victor MP-XP7210
- xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
- //(Centrino)
+ A1x = 0, //A1340D, A1300F
+ A2x, //A2500H
+ D1x, //D1
+ L2D, //L2000D
+ L3C, //L3800C
+ L3D, //L3400D
+ L3H, //L3H, but also L2000E
+ L4R, //L4500R
+ L5x, //L5800C
+ L8L, //L8400L
+ M1A, //M1300A
+ M2E, //M2400E, L4400L
+ M6N, //M6800N
+ M6R, //M6700R
+ P30, //Samsung P30
+ S1x, //S1300A, but also L1400B and M2400A (L84F)
+ S2x, //S200 (J1 reported), Victor MP-XP7210
+ xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
+ //(Centrino)
END_MODEL
- } model; //Models currently supported
- u16 event_count[128]; //count for each event TODO make this better
+ } model; //Models currently supported
+ u16 event_count[128]; //count for each event TODO make this better
};
/* Here we go */
@@ -150,7 +148,7 @@ struct asus_hotk {
#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
static struct model_data model_conf[END_MODEL] = {
- /*
+ /*
* Those pathnames are relative to the HOTK / ATKD device :
* - mt_mled
* - mt_wled
@@ -165,215 +163,197 @@ static struct model_data model_conf[END_MODEL] = {
*/
{
- .name = "A1x",
- .mt_mled = "MLED",
- .mled_status = "\\MAIL",
- .mt_lcd_switch = A1x_PREFIX "_Q10",
- .lcd_status = "\\BKLI",
- .brightness_up = A1x_PREFIX "_Q0E",
- .brightness_down = A1x_PREFIX "_Q0F"
- },
+ .name = "A1x",
+ .mt_mled = "MLED",
+ .mled_status = "\\MAIL",
+ .mt_lcd_switch = A1x_PREFIX "_Q10",
+ .lcd_status = "\\BKLI",
+ .brightness_up = A1x_PREFIX "_Q0E",
+ .brightness_down = A1x_PREFIX "_Q0F"},
{
- .name = "A2x",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\SG66",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\BAOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "A2x",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\SG66",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\BAOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "D1x",
- .mt_mled = "MLED",
- .mt_lcd_switch = "\\Q0D",
- .lcd_status = "\\GP11",
- .brightness_up = "\\Q0C",
- .brightness_down = "\\Q0B",
- .brightness_status = "\\BLVL",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "D1x",
+ .mt_mled = "MLED",
+ .mt_lcd_switch = "\\Q0D",
+ .lcd_status = "\\GP11",
+ .brightness_up = "\\Q0C",
+ .brightness_down = "\\Q0B",
+ .brightness_status = "\\BLVL",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L2D",
- .mt_mled = "MLED",
- .mled_status = "\\SGP6",
- .mt_wled = "WLED",
- .wled_status = "\\RCP3",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\SGP0",
- .brightness_up = "\\Q0E",
- .brightness_down = "\\Q0F",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L2D",
+ .mt_mled = "MLED",
+ .mled_status = "\\SGP6",
+ .mt_wled = "WLED",
+ .wled_status = "\\RCP3",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\SGP0",
+ .brightness_up = "\\Q0E",
+ .brightness_down = "\\Q0F",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L3C",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = L3C_PREFIX "_Q10",
- .lcd_status = "\\GL32",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"
- },
+ .name = "L3C",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = L3C_PREFIX "_Q10",
+ .lcd_status = "\\GL32",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"},
{
- .name = "L3D",
- .mt_mled = "MLED",
- .mled_status = "\\MALD",
- .mt_wled = "WLED",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\BKLG",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L3D",
+ .mt_mled = "MLED",
+ .mled_status = "\\MALD",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\BKLG",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L3H",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = "EHK",
- .lcd_status = "\\_SB.PCI0.PM.PBC",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L3H",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "EHK",
+ .lcd_status = "\\_SB.PCI0.PM.PBC",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L4R",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\_SB.PCI0.SBRG.SG13",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"
- },
+ .name = "L4R",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\_SB.PCI0.SBRG.SG13",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
{
- .name = "L5x",
- .mt_mled = "MLED",
+ .name = "L5x",
+ .mt_mled = "MLED",
/* WLED present, but not controlled by ACPI */
- .mt_tled = "TLED",
- .mt_lcd_switch = "\\Q0D",
- .lcd_status = "\\BAOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .mt_tled = "TLED",
+ .mt_lcd_switch = "\\Q0D",
+ .lcd_status = "\\BAOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L8L"
+ .name = "L8L"
/* No features, but at least support the hotkeys */
- },
+ },
{
- .name = "M1A",
- .mt_mled = "MLED",
- .mt_lcd_switch = M1A_PREFIX "Q10",
- .lcd_status = "\\PNOF",
- .brightness_up = M1A_PREFIX "Q0E",
- .brightness_down = M1A_PREFIX "Q0F",
- .brightness_status = "\\BRIT",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "M1A",
+ .mt_mled = "MLED",
+ .mt_lcd_switch = M1A_PREFIX "Q10",
+ .lcd_status = "\\PNOF",
+ .brightness_up = M1A_PREFIX "Q0E",
+ .brightness_down = M1A_PREFIX "Q0F",
+ .brightness_status = "\\BRIT",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "M2E",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\GP06",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "M2E",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\GP06",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "M6N",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\_SB.PCI0.SBRG.SG13",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.BKLT",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\SSTE"
- },
+ .name = "M6N",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\_SB.PCI0.SBRG.SG13",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.BKLT",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\SSTE"},
{
- .name = "M6R",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\SSTE"
- },
-
+ .name = "M6R",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\SSTE"},
{
- .name = "P30",
- .mt_wled = "WLED",
- .mt_lcd_switch = P30_PREFIX "_Q0E",
- .lcd_status = "\\BKLT",
- .brightness_up = P30_PREFIX "_Q68",
- .brightness_down = P30_PREFIX "_Q69",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\DNXT"
- },
+ .name = "P30",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = P30_PREFIX "_Q0E",
+ .lcd_status = "\\BKLT",
+ .brightness_up = P30_PREFIX "_Q68",
+ .brightness_down = P30_PREFIX "_Q69",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\DNXT"},
{
- .name = "S1x",
- .mt_mled = "MLED",
- .mled_status = "\\EMLE",
- .mt_wled = "WLED",
- .mt_lcd_switch = S1x_PREFIX "Q10" ,
- .lcd_status = "\\PNOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV"
- },
+ .name = "S1x",
+ .mt_mled = "MLED",
+ .mled_status = "\\EMLE",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = S1x_PREFIX "Q10",
+ .lcd_status = "\\PNOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV"},
{
- .name = "S2x",
- .mt_mled = "MLED",
- .mled_status = "\\MAIL",
- .mt_lcd_switch = S2x_PREFIX "_Q10",
- .lcd_status = "\\BKLI",
- .brightness_up = S2x_PREFIX "_Q0B",
- .brightness_down = S2x_PREFIX "_Q0A"
- },
+ .name = "S2x",
+ .mt_mled = "MLED",
+ .mled_status = "\\MAIL",
+ .mt_lcd_switch = S2x_PREFIX "_Q10",
+ .lcd_status = "\\BKLI",
+ .brightness_up = S2x_PREFIX "_Q0B",
+ .brightness_down = S2x_PREFIX "_Q0A"},
{
- .name = "xxN",
- .mt_mled = "MLED",
+ .name = "xxN",
+ .mt_mled = "MLED",
/* WLED present, but not controlled by ACPI */
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\BKLT",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\ADVG"
- }
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\BKLT",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\ADVG"}
};
/* procdir we use */
@@ -395,13 +375,13 @@ static struct asus_hotk *hotk;
static int asus_hotk_add(struct acpi_device *device);
static int asus_hotk_remove(struct acpi_device *device, int type);
static struct acpi_driver asus_hotk_driver = {
- .name = ACPI_HOTK_NAME,
- .class = ACPI_HOTK_CLASS,
- .ids = ACPI_HOTK_HID,
- .ops = {
- .add = asus_hotk_add,
- .remove = asus_hotk_remove,
- },
+ .name = ACPI_HOTK_NAME,
+ .class = ACPI_HOTK_CLASS,
+ .ids = ACPI_HOTK_HID,
+ .ops = {
+ .add = asus_hotk_add,
+ .remove = asus_hotk_remove,
+ },
};
/*
@@ -423,11 +403,10 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = val;
- status = acpi_evaluate_object(handle, (char *) method, &params, output);
+ status = acpi_evaluate_object(handle, (char *)method, &params, output);
return (status == AE_OK);
}
-
static int read_acpi_int(acpi_handle handle, const char *method, int *val)
{
struct acpi_buffer output;
@@ -437,7 +416,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
output.length = sizeof(out_obj);
output.pointer = &out_obj;
- status = acpi_evaluate_object(handle, (char *) method, NULL, &output);
+ status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
*val = out_obj.integer.value;
return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
}
@@ -449,7 +428,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
*/
static int
proc_read_info(char *page, char **start, off_t off, int count, int *eof,
- void *data)
+ void *data)
{
int len = 0;
int temp;
@@ -460,7 +439,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
*/
len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
- len += sprintf(page + len, "Model reference : %s\n",
+ len += sprintf(page + len, "Model reference : %s\n",
hotk->methods->name);
/*
* The SFUN method probably allows the original driver to get the list
@@ -469,7 +448,8 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
* The significance of others is yet to be found.
*/
if (read_acpi_int(hotk->handle, "SFUN", &temp))
- len += sprintf(page + len, "SFUN value : 0x%04x\n", temp);
+ len +=
+ sprintf(page + len, "SFUN value : 0x%04x\n", temp);
/*
* Another value for userspace: the ASYM method returns 0x02 for
* battery low and 0x04 for battery critical, its readings tend to be
@@ -478,7 +458,8 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
* silently ignored.
*/
if (read_acpi_int(hotk->handle, "ASYM", &temp))
- len += sprintf(page + len, "ASYM value : 0x%04x\n", temp);
+ len +=
+ sprintf(page + len, "ASYM value : 0x%04x\n", temp);
if (asus_info) {
snprintf(buf, 16, "%d", asus_info->length);
len += sprintf(page + len, "DSDT length : %s\n", buf);
@@ -501,7 +482,6 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
return len;
}
-
/*
* /proc handlers
* We write our info in page, we begin at offset off and cannot write more
@@ -510,8 +490,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
*/
/* Generic LED functions */
-static int
-read_led(const char *ledname, int ledmask)
+static int read_led(const char *ledname, int ledmask)
{
if (ledname) {
int led_status;
@@ -525,7 +504,7 @@ read_led(const char *ledname, int ledmask)
return (hotk->status & ledmask) ? 1 : 0;
}
-static int parse_arg(const char __user *buf, unsigned long count, int *val)
+static int parse_arg(const char __user * buf, unsigned long count, int *val)
{
char s[32];
if (!count)
@@ -542,8 +521,8 @@ static int parse_arg(const char __user *buf, unsigned long count, int *val)
/* FIXME: kill extraneous args so it can be called independently */
static int
-write_led(const char __user *buffer, unsigned long count,
- char *ledname, int ledmask, int invert)
+write_led(const char __user * buffer, unsigned long count,
+ char *ledname, int ledmask, int invert)
{
int value;
int led_out = 0;
@@ -555,16 +534,16 @@ write_led(const char __user *buffer, unsigned long count,
hotk->status =
(led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
- if (invert) /* invert target value */
+ if (invert) /* invert target value */
led_out = !led_out & 0x1;
if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
- printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname);
+ printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+ ledname);
return count;
}
-
/*
* Proc handlers for MLED
*/
@@ -572,12 +551,12 @@ static int
proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->mled_status, MLED_ON));
}
-
static int
-proc_write_mled(struct file *file, const char __user *buffer,
+proc_write_mled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
@@ -590,11 +569,12 @@ static int
proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->wled_status, WLED_ON));
}
static int
-proc_write_wled(struct file *file, const char __user *buffer,
+proc_write_wled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
@@ -607,35 +587,36 @@ static int
proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->tled_status, TLED_ON));
}
static int
-proc_write_tled(struct file *file, const char __user *buffer,
+proc_write_tled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
}
-
static int get_lcd_state(void)
{
int lcd = 0;
if (hotk->model != L3H) {
- /* We don't have to check anything if we are here */
+ /* We don't have to check anything if we are here */
if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
- printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n");
-
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading LCD status\n");
+
if (hotk->model == L2D)
lcd = ~lcd;
- } else { /* L3H and the like have to be handled differently */
+ } else { /* L3H and the like have to be handled differently */
acpi_status status = 0;
struct acpi_object_list input;
union acpi_object mt_params[2];
struct acpi_buffer output;
union acpi_object out_obj;
-
+
input.count = 2;
input.pointer = mt_params;
/* Note: the following values are partly guessed up, but
@@ -647,15 +628,17 @@ static int get_lcd_state(void)
output.length = sizeof(out_obj);
output.pointer = &out_obj;
-
- status = acpi_evaluate_object(NULL, hotk->methods->lcd_status, &input, &output);
+
+ status =
+ acpi_evaluate_object(NULL, hotk->methods->lcd_status,
+ &input, &output);
if (status != AE_OK)
return -1;
if (out_obj.type == ACPI_TYPE_INTEGER)
/* That's what the AML code does */
lcd = out_obj.integer.value >> 8;
}
-
+
return (lcd & 1);
}
@@ -669,10 +652,13 @@ static int set_lcd_state(int value)
/* switch */
if (hotk->model != L3H) {
status =
- acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch,
+ acpi_evaluate_object(NULL,
+ hotk->methods->mt_lcd_switch,
NULL, NULL);
- } else { /* L3H and the like have to be handled differently */
- if (!write_acpi_int(hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL))
+ } else { /* L3H and the like have to be handled differently */
+ if (!write_acpi_int
+ (hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
+ NULL))
status = AE_ERROR;
/* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
the exact behaviour is simulated here */
@@ -691,33 +677,33 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
return sprintf(page, "%d\n", get_lcd_state());
}
-
static int
-proc_write_lcd(struct file *file, const char __user *buffer,
+proc_write_lcd(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int value;
-
+
count = parse_arg(buffer, count, &value);
if (count > 0)
set_lcd_state(value);
return count;
}
-
static int read_brightness(void)
{
int value;
-
- if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
- if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
+
+ if (hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
+ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
&value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else if (hotk->methods->brightness_status) { /* For D1 for example */
- if (!read_acpi_int(NULL, hotk->methods->brightness_status,
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading brightness\n");
+ } else if (hotk->methods->brightness_status) { /* For D1 for example */
+ if (!read_acpi_int(NULL, hotk->methods->brightness_status,
&value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else /* No GPLV method */
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading brightness\n");
+ } else /* No GPLV method */
value = hotk->brightness;
return value;
}
@@ -730,23 +716,25 @@ static void set_brightness(int value)
acpi_status status = 0;
/* SPLV laptop */
- if(hotk->methods->brightness_set) {
- if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
+ if (hotk->methods->brightness_set) {
+ if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
value, NULL))
- printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ printk(KERN_WARNING
+ "Asus ACPI: Error changing brightness\n");
return;
}
/* No SPLV method if we are here, act as appropriate */
value -= read_brightness();
while (value != 0) {
- status = acpi_evaluate_object(NULL, (value > 0) ?
- hotk->methods->brightness_up :
+ status = acpi_evaluate_object(NULL, (value > 0) ?
+ hotk->methods->brightness_up :
hotk->methods->brightness_down,
NULL, NULL);
(value > 0) ? value-- : value++;
if (ACPI_FAILURE(status))
- printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ printk(KERN_WARNING
+ "Asus ACPI: Error changing brightness\n");
}
return;
}
@@ -759,7 +747,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_brn(struct file *file, const char __user *buffer,
+proc_write_brn(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int value;
@@ -767,7 +755,7 @@ proc_write_brn(struct file *file, const char __user *buffer,
count = parse_arg(buffer, count, &value);
if (count > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
- /* 0 <= value <= 15 */
+ /* 0 <= value <= 15 */
set_brightness(value);
} else if (count < 0) {
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
@@ -779,7 +767,7 @@ proc_write_brn(struct file *file, const char __user *buffer,
static void set_display(int value)
{
/* no sanity check needed for now */
- if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
+ if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
value, NULL))
printk(KERN_WARNING "Asus ACPI: Error setting display\n");
return;
@@ -791,13 +779,14 @@ static void set_display(int value)
*/
static int
proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
- void *data)
+ void *data)
{
int value = 0;
-
+
if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
- printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
- value &= 0x07; /* needed for some models, shouldn't hurt others */
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading display status\n");
+ value &= 0x07; /* needed for some models, shouldn't hurt others */
return sprintf(page, "%d\n", value);
}
@@ -808,8 +797,8 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
* simultaneously, so be warned. See the acpi4asus README for more info.
*/
static int
-proc_write_disp(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+proc_write_disp(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
{
int value;
@@ -822,19 +811,19 @@ proc_write_disp(struct file *file, const char __user *buffer,
return count;
}
-
-typedef int (proc_readfunc)(char *page, char **start, off_t off, int count,
- int *eof, void *data);
-typedef int (proc_writefunc)(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
+typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
+ int *eof, void *data);
+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,
- proc_readfunc *readfunc, mode_t mode,
- struct acpi_device *device)
+__init asus_proc_add(char *name, proc_writefunc * writefunc,
+ proc_readfunc * readfunc, mode_t mode,
+ struct acpi_device *device)
{
- struct proc_dir_entry *proc = create_proc_entry(name, mode, acpi_device_dir(device));
- if(!proc) {
+ struct proc_dir_entry *proc =
+ create_proc_entry(name, mode, acpi_device_dir(device));
+ if (!proc) {
printk(KERN_WARNING " Unable to create %s fs entry\n", name);
return -1;
}
@@ -851,14 +840,14 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *proc;
mode_t mode;
-
+
/*
* If parameter uid or gid is not changed, keep the default setting for
* our proc entries (-rw-rw-rw-) else, it means we care about security,
* and then set to -rw-rw----
*/
- if ((asus_uid == 0) && (asus_gid == 0)){
+ if ((asus_uid == 0) && (asus_gid == 0)) {
mode = S_IFREG | S_IRUGO | S_IWUGO;
} else {
mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
@@ -881,15 +870,18 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
}
if (hotk->methods->mt_wled) {
- asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, mode, device);
+ asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled,
+ mode, device);
}
if (hotk->methods->mt_mled) {
- asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, mode, device);
+ asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled,
+ mode, device);
}
if (hotk->methods->mt_tled) {
- asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, mode, device);
+ asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled,
+ mode, device);
}
/*
@@ -897,35 +889,40 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
* from keyboard
*/
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
- asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, device);
+ asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode,
+ device);
}
-
+
if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
(hotk->methods->brightness_get && hotk->methods->brightness_set)) {
- asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device);
+ asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode,
+ device);
}
if (hotk->methods->display_set) {
- asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device);
+ asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp,
+ mode, device);
}
return 0;
}
-static int asus_hotk_remove_fs(struct acpi_device* device)
+static int asus_hotk_remove_fs(struct acpi_device *device)
{
- if(acpi_device_dir(device)) {
- remove_proc_entry(PROC_INFO,acpi_device_dir(device));
+ if (acpi_device_dir(device)) {
+ remove_proc_entry(PROC_INFO, acpi_device_dir(device));
if (hotk->methods->mt_wled)
- remove_proc_entry(PROC_WLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_WLED, acpi_device_dir(device));
if (hotk->methods->mt_mled)
- remove_proc_entry(PROC_MLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_MLED, acpi_device_dir(device));
if (hotk->methods->mt_tled)
- remove_proc_entry(PROC_TLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_TLED, acpi_device_dir(device));
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
remove_proc_entry(PROC_LCD, acpi_device_dir(device));
- if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
- (hotk->methods->brightness_get && hotk->methods->brightness_set))
+ if ((hotk->methods->brightness_up
+ && hotk->methods->brightness_down)
+ || (hotk->methods->brightness_get
+ && hotk->methods->brightness_set))
remove_proc_entry(PROC_BRN, acpi_device_dir(device));
if (hotk->methods->display_set)
remove_proc_entry(PROC_DISP, acpi_device_dir(device));
@@ -933,16 +930,15 @@ static int asus_hotk_remove_fs(struct acpi_device* device)
return 0;
}
-
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
{
- /* TODO Find a better way to handle events count.*/
+ /* TODO Find a better way to handle events count. */
if (!hotk)
return;
if ((event & ~((u32) BR_UP)) < 16) {
hotk->brightness = (event & ~((u32) BR_UP));
- } else if ((event & ~((u32) BR_DOWN)) < 16 ) {
+ } else if ((event & ~((u32) BR_DOWN)) < 16) {
hotk->brightness = (event & ~((u32) BR_DOWN));
}
@@ -976,7 +972,7 @@ static int __init asus_hotk_get_info(void)
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Couldn't get the DSDT table header\n");
else
- asus_info = (struct acpi_table_header *) dsdt.pointer;
+ asus_info = (struct acpi_table_header *)dsdt.pointer;
/* We have to write 0 on init this far for all ASUS models */
if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
@@ -988,15 +984,17 @@ static int __init asus_hotk_get_info(void)
if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
printk(KERN_WARNING " Error calling BSTS\n");
else if (bsts_result)
- printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result);
+ printk(KERN_NOTICE " BSTS called, 0x%02x returned\n",
+ bsts_result);
/* Samsung P30 has a device with a valid _HID whose INIT does not
* return anything. Catch this one and any similar here */
if (buffer.pointer == NULL) {
- if (asus_info && /* Samsung P30 */
+ if (asus_info && /* Samsung P30 */
strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
hotk->model = P30;
- printk(KERN_NOTICE " Samsung P30 detected, supported\n");
+ printk(KERN_NOTICE
+ " Samsung P30 detected, supported\n");
} else {
hotk->model = M2E;
printk(KERN_WARNING " no string returned by INIT\n");
@@ -1006,10 +1004,11 @@ static int __init asus_hotk_get_info(void)
hotk->methods = &model_conf[hotk->model];
return AE_OK;
}
-
- model = (union acpi_object *) buffer.pointer;
+
+ model = (union acpi_object *)buffer.pointer;
if (model->type == ACPI_TYPE_STRING) {
- printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
+ printk(KERN_NOTICE " %s model detected, ",
+ model->string.pointer);
}
hotk->model = END_MODEL;
@@ -1035,7 +1034,7 @@ static int __init asus_hotk_get_info(void)
strncmp(model->string.pointer, "M6N", 3) == 0 ||
strncmp(model->string.pointer, "S1N", 3) == 0 ||
strncmp(model->string.pointer, "S5N", 3) == 0 ||
- strncmp(model->string.pointer, "W1N", 3) == 0)
+ strncmp(model->string.pointer, "W1N", 3) == 0)
hotk->model = xxN;
else if (strncmp(model->string.pointer, "M1", 2) == 0)
hotk->model = M1A;
@@ -1069,21 +1068,21 @@ static int __init asus_hotk_get_info(void)
/* Sort of per-model blacklist */
if (strncmp(model->string.pointer, "L2B", 3) == 0)
- hotk->methods->lcd_status = NULL;
+ hotk->methods->lcd_status = NULL;
/* L2B is similar enough to L3C to use its settings, with this only
exception */
else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
strncmp(model->string.pointer, "M5N", 3) == 0)
- hotk->methods->mt_mled = NULL;
+ hotk->methods->mt_mled = NULL;
/* S5N and M5N have no MLED */
else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
strncmp(model->string.pointer, "W1N", 3) == 0)
- hotk->methods->mt_wled = "WLED";
+ hotk->methods->mt_wled = "WLED";
/* M2N and W1N have a usable WLED */
else if (asus_info) {
if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
hotk->methods->mled_status = NULL;
- /* S1300A reports L84F, but L1400B too, account for that */
+ /* S1300A reports L84F, but L1400B too, account for that */
}
acpi_os_free(model);
@@ -1091,7 +1090,6 @@ static int __init asus_hotk_get_info(void)
return AE_OK;
}
-
static int __init asus_hotk_check(void)
{
int result = 0;
@@ -1110,7 +1108,6 @@ static int __init asus_hotk_check(void)
return result;
}
-
static int __init asus_hotk_add(struct acpi_device *device)
{
acpi_status status = AE_OK;
@@ -1123,7 +1120,7 @@ static int __init asus_hotk_add(struct acpi_device *device)
ASUS_ACPI_VERSION);
hotk =
- (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+ (struct asus_hotk *)kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
if (!hotk)
return -ENOMEM;
memset(hotk, 0, sizeof(struct asus_hotk));
@@ -1134,7 +1131,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
acpi_driver_data(device) = hotk;
hotk->device = device;
-
result = asus_hotk_check();
if (result)
goto end;
@@ -1153,17 +1149,22 @@ static int __init asus_hotk_add(struct acpi_device *device)
printk(KERN_ERR " Error installing notify handler\n");
/* For laptops without GPLV: init the hotk->brightness value */
- if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) &&
- (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
- status = acpi_evaluate_object(NULL, hotk->methods->brightness_down,
- NULL, NULL);
+ if ((!hotk->methods->brightness_get)
+ && (!hotk->methods->brightness_status)
+ && (hotk->methods->brightness_up
+ && hotk->methods->brightness_down)) {
+ status =
+ acpi_evaluate_object(NULL, hotk->methods->brightness_down,
+ NULL, NULL);
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Error changing brightness\n");
else {
- status = acpi_evaluate_object(NULL, hotk->methods->brightness_up,
- NULL, NULL);
+ status =
+ acpi_evaluate_object(NULL,
+ hotk->methods->brightness_up,
+ NULL, NULL);
if (ACPI_FAILURE(status))
- printk(KERN_WARNING " Strange, error changing"
+ printk(KERN_WARNING " Strange, error changing"
" brightness\n");
}
}
@@ -1176,7 +1177,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
return result;
}
-
static int asus_hotk_remove(struct acpi_device *device, int type)
{
acpi_status status = 0;
@@ -1196,7 +1196,6 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
return 0;
}
-
static int __init asus_acpi_init(void)
{
int result;
@@ -1204,9 +1203,9 @@ static int __init asus_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
+ if (!acpi_specific_hotkey_enabled) {
printk(KERN_ERR "Using generic hotkey driver\n");
- return -ENODEV;
+ return -ENODEV;
}
asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
if (!asus_proc_dir) {
@@ -1225,7 +1224,6 @@ static int __init asus_acpi_init(void)
return 0;
}
-
static void __exit asus_acpi_exit(void)
{
acpi_bus_unregister_driver(&asus_hotk_driver);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index c55feca9b7d5..702e857e98c5 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -34,7 +34,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
@@ -53,87 +52,85 @@
#define ACPI_BATTERY_UNITS_WATTS "mW"
#define ACPI_BATTERY_UNITS_AMPS "mA"
-
#define _COMPONENT ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME ("acpi_battery")
+ACPI_MODULE_NAME("acpi_battery")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_battery_add (struct acpi_device *device);
-static int acpi_battery_remove (struct acpi_device *device, int type);
+static int acpi_battery_add(struct acpi_device *device);
+static int acpi_battery_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_battery_driver = {
- .name = ACPI_BATTERY_DRIVER_NAME,
- .class = ACPI_BATTERY_CLASS,
- .ids = ACPI_BATTERY_HID,
- .ops = {
- .add = acpi_battery_add,
- .remove = acpi_battery_remove,
- },
+ .name = ACPI_BATTERY_DRIVER_NAME,
+ .class = ACPI_BATTERY_CLASS,
+ .ids = ACPI_BATTERY_HID,
+ .ops = {
+ .add = acpi_battery_add,
+ .remove = acpi_battery_remove,
+ },
};
struct acpi_battery_status {
- acpi_integer state;
- acpi_integer present_rate;
- acpi_integer remaining_capacity;
- acpi_integer present_voltage;
+ acpi_integer state;
+ acpi_integer present_rate;
+ acpi_integer remaining_capacity;
+ acpi_integer present_voltage;
};
struct acpi_battery_info {
- acpi_integer power_unit;
- acpi_integer design_capacity;
- acpi_integer last_full_capacity;
- acpi_integer battery_technology;
- acpi_integer design_voltage;
- acpi_integer design_capacity_warning;
- acpi_integer design_capacity_low;
- acpi_integer battery_capacity_granularity_1;
- acpi_integer battery_capacity_granularity_2;
- acpi_string model_number;
- acpi_string serial_number;
- acpi_string battery_type;
- acpi_string oem_info;
+ acpi_integer power_unit;
+ acpi_integer design_capacity;
+ acpi_integer last_full_capacity;
+ acpi_integer battery_technology;
+ acpi_integer design_voltage;
+ acpi_integer design_capacity_warning;
+ acpi_integer design_capacity_low;
+ acpi_integer battery_capacity_granularity_1;
+ acpi_integer battery_capacity_granularity_2;
+ acpi_string model_number;
+ acpi_string serial_number;
+ acpi_string battery_type;
+ acpi_string oem_info;
};
struct acpi_battery_flags {
- u8 present:1; /* Bay occupied? */
- u8 power_unit:1; /* 0=watts, 1=apms */
- u8 alarm:1; /* _BTP present? */
- u8 reserved:5;
+ u8 present:1; /* Bay occupied? */
+ u8 power_unit:1; /* 0=watts, 1=apms */
+ u8 alarm:1; /* _BTP present? */
+ u8 reserved:5;
};
struct acpi_battery_trips {
- unsigned long warning;
- unsigned long low;
+ unsigned long warning;
+ unsigned long low;
};
struct acpi_battery {
- acpi_handle handle;
+ acpi_handle handle;
struct acpi_battery_flags flags;
struct acpi_battery_trips trips;
- unsigned long alarm;
+ unsigned long alarm;
struct acpi_battery_info *info;
};
-
/* --------------------------------------------------------------------------
Battery Management
-------------------------------------------------------------------------- */
static int
-acpi_battery_get_info (
- struct acpi_battery *battery,
- struct acpi_battery_info **bif)
+acpi_battery_get_info(struct acpi_battery *battery,
+ struct acpi_battery_info **bif)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
- ACPI_BATTERY_FORMAT_BIF};
- struct acpi_buffer data = {0, NULL};
- union acpi_object *package = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
+ ACPI_BATTERY_FORMAT_BIF
+ };
+ struct acpi_buffer data = { 0, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_get_info");
@@ -148,7 +145,7 @@ acpi_battery_get_info (
return_VALUE(-ENODEV);
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
/* Extract Package Data */
@@ -174,27 +171,27 @@ acpi_battery_get_info (
goto end;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
if (!result)
- (*bif) = (struct acpi_battery_info *) data.pointer;
+ (*bif) = (struct acpi_battery_info *)data.pointer;
return_VALUE(result);
}
static int
-acpi_battery_get_status (
- struct acpi_battery *battery,
- struct acpi_battery_status **bst)
+acpi_battery_get_status(struct acpi_battery *battery,
+ struct acpi_battery_status **bst)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST),
- ACPI_BATTERY_FORMAT_BST};
- struct acpi_buffer data = {0, NULL};
- union acpi_object *package = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
+ ACPI_BATTERY_FORMAT_BST
+ };
+ struct acpi_buffer data = { 0, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_get_status");
@@ -209,7 +206,7 @@ acpi_battery_get_status (
return_VALUE(-ENODEV);
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
/* Extract Package Data */
@@ -235,24 +232,21 @@ acpi_battery_get_status (
goto end;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
if (!result)
- (*bst) = (struct acpi_battery_status *) data.pointer;
+ (*bst) = (struct acpi_battery_status *)data.pointer;
return_VALUE(result);
}
-
static int
-acpi_battery_set_alarm (
- struct acpi_battery *battery,
- unsigned long alarm)
+acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
{
- acpi_status status = 0;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg0};
+ acpi_status status = 0;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
@@ -275,19 +269,16 @@ acpi_battery_set_alarm (
return_VALUE(0);
}
-
-static int
-acpi_battery_check (
- struct acpi_battery *battery)
+static int acpi_battery_check(struct acpi_battery *battery)
{
- int result = 0;
- acpi_status status = AE_OK;
- acpi_handle handle = NULL;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ acpi_handle handle = NULL;
+ struct acpi_device *device = NULL;
struct acpi_battery_info *bif = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_check");
-
+
if (!battery)
return_VALUE(-EINVAL);
@@ -336,18 +327,17 @@ acpi_battery_check (
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_battery_dir;
+static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
+ int result = 0;
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
struct acpi_battery_info *bif = NULL;
- char *units = "?";
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_info");
@@ -369,19 +359,21 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
goto end;
}
- units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
-
+ units =
+ bif->
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+
if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "design capacity: unknown\n");
else
seq_printf(seq, "design capacity: %d %sh\n",
- (u32) bif->design_capacity, units);
+ (u32) bif->design_capacity, units);
if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "last full capacity: unknown\n");
else
seq_printf(seq, "last full capacity: %d %sh\n",
- (u32) bif->last_full_capacity, units);
+ (u32) bif->last_full_capacity, units);
switch ((u32) bif->battery_technology) {
case 0:
@@ -399,26 +391,22 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
seq_printf(seq, "design voltage: unknown\n");
else
seq_printf(seq, "design voltage: %d mV\n",
- (u32) bif->design_voltage);
-
+ (u32) bif->design_voltage);
+
seq_printf(seq, "design capacity warning: %d %sh\n",
- (u32) bif->design_capacity_warning, units);
+ (u32) bif->design_capacity_warning, units);
seq_printf(seq, "design capacity low: %d %sh\n",
- (u32) bif->design_capacity_low, units);
+ (u32) bif->design_capacity_low, units);
seq_printf(seq, "capacity granularity 1: %d %sh\n",
- (u32) bif->battery_capacity_granularity_1, units);
+ (u32) bif->battery_capacity_granularity_1, units);
seq_printf(seq, "capacity granularity 2: %d %sh\n",
- (u32) bif->battery_capacity_granularity_2, units);
- seq_printf(seq, "model number: %s\n",
- bif->model_number);
- seq_printf(seq, "serial number: %s\n",
- bif->serial_number);
- seq_printf(seq, "battery type: %s\n",
- bif->battery_type);
- seq_printf(seq, "OEM info: %s\n",
- bif->oem_info);
-
-end:
+ (u32) bif->battery_capacity_granularity_2, units);
+ seq_printf(seq, "model number: %s\n", bif->model_number);
+ seq_printf(seq, "serial number: %s\n", bif->serial_number);
+ seq_printf(seq, "battery type: %s\n", bif->battery_type);
+ seq_printf(seq, "OEM info: %s\n", bif->oem_info);
+
+ end:
kfree(bif);
return_VALUE(0);
@@ -429,14 +417,12 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_battery_read_info, PDE(inode)->data);
}
-
-static int
-acpi_battery_read_state (struct seq_file *seq, void *offset)
+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
+ int result = 0;
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
struct acpi_battery_status *bst = NULL;
- char *units = "?";
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_state");
@@ -452,7 +438,9 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
/* Battery Units */
- units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+ units =
+ battery->flags.
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
/* Battery Status (_BST) */
@@ -467,12 +455,12 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
else
seq_printf(seq, "capacity state: critical\n");
- if ((bst->state & 0x01) && (bst->state & 0x02)){
- seq_printf(seq, "charging state: charging/discharging\n");
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Battery Charging and Discharging?\n"));
- }
- else if (bst->state & 0x01)
+ if ((bst->state & 0x01) && (bst->state & 0x02)) {
+ seq_printf(seq,
+ "charging state: charging/discharging\n");
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Battery Charging and Discharging?\n"));
+ } else if (bst->state & 0x01)
seq_printf(seq, "charging state: discharging\n");
else if (bst->state & 0x02)
seq_printf(seq, "charging state: charging\n");
@@ -484,21 +472,21 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
seq_printf(seq, "present rate: unknown\n");
else
seq_printf(seq, "present rate: %d %s\n",
- (u32) bst->present_rate, units);
+ (u32) bst->present_rate, units);
if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "remaining capacity: unknown\n");
else
seq_printf(seq, "remaining capacity: %d %sh\n",
- (u32) bst->remaining_capacity, units);
+ (u32) bst->remaining_capacity, units);
if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "present voltage: unknown\n");
else
seq_printf(seq, "present voltage: %d mV\n",
- (u32) bst->present_voltage);
+ (u32) bst->present_voltage);
-end:
+ end:
kfree(bst);
return_VALUE(0);
@@ -509,12 +497,10 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_battery_read_state, PDE(inode)->data);
}
-
-static int
-acpi_battery_read_alarm (struct seq_file *seq, void *offset)
+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
{
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
- char *units = "?";
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
@@ -527,8 +513,10 @@ acpi_battery_read_alarm (struct seq_file *seq, void *offset)
}
/* Battery Units */
-
- units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+
+ units =
+ battery->flags.
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
/* Battery Alarm */
@@ -538,22 +526,19 @@ acpi_battery_read_alarm (struct seq_file *seq, void *offset)
else
seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
-end:
+ end:
return_VALUE(0);
}
-
static ssize_t
-acpi_battery_write_alarm (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_battery_write_alarm(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- int result = 0;
- char alarm_string[12] = {'\0'};
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_battery *battery = (struct acpi_battery *)m->private;
+ int result = 0;
+ char alarm_string[12] = { '\0' };
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_battery *battery = (struct acpi_battery *)m->private;
ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
@@ -565,11 +550,11 @@ acpi_battery_write_alarm (
if (copy_from_user(alarm_string, buffer, count))
return_VALUE(-EFAULT);
-
+
alarm_string[count] = '\0';
- result = acpi_battery_set_alarm(battery,
- simple_strtoul(alarm_string, NULL, 0));
+ result = acpi_battery_set_alarm(battery,
+ simple_strtoul(alarm_string, NULL, 0));
if (result)
return_VALUE(result);
@@ -582,41 +567,39 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_battery_info_ops = {
- .open = acpi_battery_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
static struct file_operations acpi_battery_state_ops = {
- .open = acpi_battery_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
static struct file_operations acpi_battery_alarm_ops = {
- .open = acpi_battery_alarm_open_fs,
- .read = seq_read,
- .write = acpi_battery_write_alarm,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_alarm_open_fs,
+ .read = seq_read,
+ .write = acpi_battery_write_alarm,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_battery_add_fs (
- struct acpi_device *device)
+static int acpi_battery_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_battery_dir);
+ acpi_battery_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -624,24 +607,24 @@ acpi_battery_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_INFO));
else {
- entry->proc_fops = &acpi_battery_info_ops;
+ entry->proc_fops = &acpi_battery_info_ops;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
/* 'status' [R] */
entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_STATUS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_STATUS));
else {
entry->proc_fops = &acpi_battery_state_ops;
entry->data = acpi_driver_data(device);
@@ -650,11 +633,12 @@ acpi_battery_add_fs (
/* 'alarm' [R/W] */
entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_ALARM));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_ALARM));
else {
entry->proc_fops = &acpi_battery_alarm_ops;
entry->data = acpi_driver_data(device);
@@ -664,10 +648,7 @@ acpi_battery_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_battery_remove_fs (
- struct acpi_device *device)
+static int acpi_battery_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
@@ -686,19 +667,14 @@ acpi_battery_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_battery_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_battery *battery = (struct acpi_battery *) data;
- struct acpi_device *device = NULL;
+ struct acpi_battery *battery = (struct acpi_battery *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_notify");
@@ -716,24 +692,21 @@ acpi_battery_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_battery_add (
- struct acpi_device *device)
+static int acpi_battery_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_battery *battery = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_battery *battery = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_add");
-
+
if (!device)
return_VALUE(-EINVAL);
@@ -756,19 +729,20 @@ acpi_battery_add (
goto end;
status = acpi_install_notify_handler(battery->handle,
- ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery);
+ ACPI_DEVICE_NOTIFY,
+ acpi_battery_notify, battery);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
- ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
- device->status.battery_present?"present":"absent");
-
-end:
+ ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+ device->status.battery_present ? "present" : "absent");
+
+ end:
if (result) {
acpi_battery_remove_fs(device);
kfree(battery);
@@ -777,27 +751,24 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_battery_remove (
- struct acpi_device *device,
- int type)
+static int acpi_battery_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_battery *battery = NULL;
+ acpi_status status = 0;
+ struct acpi_battery *battery = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- battery = (struct acpi_battery *) acpi_driver_data(device);
+ battery = (struct acpi_battery *)acpi_driver_data(device);
status = acpi_remove_notify_handler(battery->handle,
- ACPI_DEVICE_NOTIFY, acpi_battery_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_battery_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_battery_remove_fs(device);
@@ -806,11 +777,9 @@ acpi_battery_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_battery_init (void)
+static int __init acpi_battery_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_battery_init");
@@ -828,9 +797,7 @@ acpi_battery_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_battery_exit (void)
+static void __exit acpi_battery_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_battery_exit");
@@ -841,6 +808,5 @@ acpi_battery_exit (void)
return_VOID;
}
-
module_init(acpi_battery_init);
module_exit(acpi_battery_exit);
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 4c010e7f11b8..9824f679a910 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -26,7 +26,6 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -34,49 +33,49 @@
#include <acpi/acpi_bus.h>
#include <linux/dmi.h>
-enum acpi_blacklist_predicates
-{
- all_versions,
- less_than_or_equal,
- equal,
- greater_than_or_equal,
+enum acpi_blacklist_predicates {
+ all_versions,
+ less_than_or_equal,
+ equal,
+ greater_than_or_equal,
};
-struct acpi_blacklist_item
-{
- char oem_id[7];
- char oem_table_id[9];
- u32 oem_revision;
- acpi_table_type table;
- enum acpi_blacklist_predicates oem_revision_predicate;
- char *reason;
- u32 is_critical_error;
+struct acpi_blacklist_item {
+ char oem_id[7];
+ char oem_table_id[9];
+ u32 oem_revision;
+ acpi_table_type table;
+ enum acpi_blacklist_predicates oem_revision_predicate;
+ char *reason;
+ u32 is_critical_error;
};
/*
* POLICY: If *anything* doesn't work, put it on the blacklist.
* If they are critical errors, mark it critical, and abort driver load.
*/
-static struct acpi_blacklist_item acpi_blacklist[] __initdata =
-{
+static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
/* Compaq Presario 1700 */
- {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
+ {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal,
+ "Multiple problems", 1},
/* Sony FX120, FX140, FX150? */
- {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1},
+ {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal,
+ "ACPI driver problem", 1},
/* Compaq Presario 800, Insyde BIOS */
- {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
+ {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal,
+ "Does not use _REG to protect EC OpRegions", 1},
/* IBM 600E - _ADR should return 7, but it returns 1 */
- {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
- {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1},
+ {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal,
+ "Incorrect _ADR", 1},
+ {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions,
+ "Bogus PCI routing", 1},
{""}
};
-
#if CONFIG_ACPI_BLACKLIST_YEAR
-static int __init
-blacklist_by_year(void)
+static int __init blacklist_by_year(void)
{
int year;
char *s = dmi_get_system_info(DMI_BIOS_DATE);
@@ -92,36 +91,38 @@ blacklist_by_year(void)
s += 1;
- year = simple_strtoul(s,NULL,0);
+ year = simple_strtoul(s, NULL, 0);
- if (year < 100) { /* 2-digit year */
+ if (year < 100) { /* 2-digit year */
year += 1900;
if (year < 1996) /* no dates < spec 1.0 */
year += 100;
}
if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
- printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
- "acpi=force is required to enable ACPI\n",
- year, CONFIG_ACPI_BLACKLIST_YEAR);
+ printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
+ "acpi=force is required to enable ACPI\n",
+ year, CONFIG_ACPI_BLACKLIST_YEAR);
return 1;
}
return 0;
}
#else
-static inline int blacklist_by_year(void) { return 0; }
+static inline int blacklist_by_year(void)
+{
+ return 0;
+}
#endif
-int __init
-acpi_blacklisted(void)
+int __init acpi_blacklisted(void)
{
int i = 0;
int blacklisted = 0;
struct acpi_table_header *table_header;
- while (acpi_blacklist[i].oem_id[0] != '\0')
- {
- if (acpi_get_table_header_early(acpi_blacklist[i].table, &table_header)) {
+ while (acpi_blacklist[i].oem_id[0] != '\0') {
+ if (acpi_get_table_header_early
+ (acpi_blacklist[i].table, &table_header)) {
i++;
continue;
}
@@ -131,33 +132,43 @@ acpi_blacklisted(void)
continue;
}
- if (strncmp(acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) {
+ if (strncmp
+ (acpi_blacklist[i].oem_table_id, table_header->oem_table_id,
+ 8)) {
i++;
continue;
}
if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
- || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal
- && table_header->oem_revision <= acpi_blacklist[i].oem_revision)
- || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal
- && table_header->oem_revision >= acpi_blacklist[i].oem_revision)
+ || (acpi_blacklist[i].oem_revision_predicate ==
+ less_than_or_equal
+ && table_header->oem_revision <=
+ acpi_blacklist[i].oem_revision)
+ || (acpi_blacklist[i].oem_revision_predicate ==
+ greater_than_or_equal
+ && table_header->oem_revision >=
+ acpi_blacklist[i].oem_revision)
|| (acpi_blacklist[i].oem_revision_predicate == equal
- && table_header->oem_revision == acpi_blacklist[i].oem_revision)) {
-
- printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" "
- "Revision 0x%x has a known ACPI BIOS problem.\n",
- acpi_blacklist[i].oem_id,
- acpi_blacklist[i].oem_table_id,
- acpi_blacklist[i].oem_revision);
-
- printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n",
- acpi_blacklist[i].reason,
- (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable"));
+ && table_header->oem_revision ==
+ acpi_blacklist[i].oem_revision)) {
+
+ printk(KERN_ERR PREFIX
+ "Vendor \"%6.6s\" System \"%8.8s\" "
+ "Revision 0x%x has a known ACPI BIOS problem.\n",
+ acpi_blacklist[i].oem_id,
+ acpi_blacklist[i].oem_table_id,
+ acpi_blacklist[i].oem_revision);
+
+ printk(KERN_ERR PREFIX
+ "Reason: %s. This is a %s error\n",
+ acpi_blacklist[i].reason,
+ (acpi_blacklist[i].
+ is_critical_error ? "non-recoverable" :
+ "recoverable"));
blacklisted = acpi_blacklist[i].is_critical_error;
break;
- }
- else {
+ } else {
i++;
}
}
@@ -166,4 +177,3 @@ acpi_blacklisted(void)
return blacklisted;
}
-
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d77c2307883c..6a4da417c16b 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -36,19 +36,17 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("acpi_bus")
-
+ACPI_MODULE_NAME("acpi_bus")
#ifdef CONFIG_X86
extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
#endif
-FADT_DESCRIPTOR acpi_fadt;
+FADT_DESCRIPTOR acpi_fadt;
EXPORT_SYMBOL(acpi_fadt);
-struct acpi_device *acpi_root;
-struct proc_dir_entry *acpi_root_dir;
+struct acpi_device *acpi_root;
+struct proc_dir_entry *acpi_root_dir;
EXPORT_SYMBOL(acpi_root_dir);
#define STRUCT_TO_INT(s) (*((int*)&s))
@@ -57,12 +55,9 @@ EXPORT_SYMBOL(acpi_root_dir);
Device Management
-------------------------------------------------------------------------- */
-int
-acpi_bus_get_device (
- acpi_handle handle,
- struct acpi_device **device)
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_bus_get_device");
@@ -71,24 +66,23 @@ acpi_bus_get_device (
/* TBD: Support fixed-feature devices */
- status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device);
+ status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No context for object [%p]\n",
- handle));
+ handle));
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
+
EXPORT_SYMBOL(acpi_bus_get_device);
-int
-acpi_bus_get_status (
- struct acpi_device *device)
+int acpi_bus_get_status(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- unsigned long sta = 0;
-
+ acpi_status status = AE_OK;
+ unsigned long sta = 0;
+
ACPI_FUNCTION_TRACE("acpi_bus_get_status");
if (!device)
@@ -98,10 +92,11 @@ acpi_bus_get_status (
* Evaluate _STA if present.
*/
if (device->flags.dynamic_status) {
- status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
+ status =
+ acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- STRUCT_TO_INT(device->status) = (int) sta;
+ STRUCT_TO_INT(device->status) = (int)sta;
}
/*
@@ -115,33 +110,30 @@ acpi_bus_get_status (
if (device->status.functional && !device->status.present) {
printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
- "functional but not present; setting present\n",
- device->pnp.bus_id,
- (u32) STRUCT_TO_INT(device->status));
+ "functional but not present; setting present\n",
+ device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
device->status.present = 1;
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
- device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
+ device->pnp.bus_id,
+ (u32) STRUCT_TO_INT(device->status)));
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_get_status);
+EXPORT_SYMBOL(acpi_bus_get_status);
/* --------------------------------------------------------------------------
Power Management
-------------------------------------------------------------------------- */
-int
-acpi_bus_get_power (
- acpi_handle handle,
- int *state)
+int acpi_bus_get_power(acpi_handle handle, int *state)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_device *device = NULL;
- unsigned long psc = 0;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_device *device = NULL;
+ unsigned long psc = 0;
ACPI_FUNCTION_TRACE("acpi_bus_get_power");
@@ -157,20 +149,18 @@ acpi_bus_get_power (
*state = device->parent->power.state;
else
*state = ACPI_STATE_D0;
- }
- else {
+ } else {
/*
* Get the device's power state either directly (via _PSC) or
* indirectly (via power resources).
*/
if (device->power.flags.explicit_get) {
- status = acpi_evaluate_integer(device->handle, "_PSC",
- NULL, &psc);
+ status = acpi_evaluate_integer(device->handle, "_PSC",
+ NULL, &psc);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- device->power.state = (int) psc;
- }
- else if (device->power.flags.power_resources) {
+ device->power.state = (int)psc;
+ } else if (device->power.flags.power_resources) {
result = acpi_power_get_inferred_state(device);
if (result)
return_VALUE(result);
@@ -180,22 +170,19 @@ acpi_bus_get_power (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
- device->pnp.bus_id, device->power.state));
+ device->pnp.bus_id, device->power.state));
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_get_power);
+EXPORT_SYMBOL(acpi_bus_get_power);
-int
-acpi_bus_set_power (
- acpi_handle handle,
- int state)
+int acpi_bus_set_power(acpi_handle handle, int state)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
- char object_name[5] = {'_','P','S','0'+state,'\0'};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
+ char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
ACPI_FUNCTION_TRACE("acpi_bus_set_power");
@@ -209,7 +196,8 @@ acpi_bus_set_power (
/* Make sure this is a valid target state */
if (!device->flags.power_manageable) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Device is not power manageable\n"));
return_VALUE(-ENODEV);
}
/*
@@ -219,15 +207,18 @@ acpi_bus_set_power (
if (device->power.state == ACPI_STATE_UNKNOWN)
acpi_bus_get_power(device->handle, &device->power.state);
if (state == device->power.state) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+ state));
return_VALUE(0);
}
if (!device->power.states[state].flags.valid) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n",
+ state));
return_VALUE(-ENODEV);
}
if (device->parent && (state < device->parent->power.state)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Cannot set device to a higher-powered state than parent\n"));
return_VALUE(-ENODEV);
}
@@ -245,18 +236,17 @@ acpi_bus_set_power (
goto end;
}
if (device->power.states[state].flags.explicit_set) {
- status = acpi_evaluate_object(device->handle,
- object_name, NULL, NULL);
+ status = acpi_evaluate_object(device->handle,
+ object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto end;
}
}
- }
- else {
+ } else {
if (device->power.states[state].flags.explicit_set) {
- status = acpi_evaluate_object(device->handle,
- object_name, NULL, NULL);
+ status = acpi_evaluate_object(device->handle,
+ object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto end;
@@ -269,19 +259,20 @@ acpi_bus_set_power (
}
}
-end:
+ end:
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Error transitioning device [%s] to D%d\n",
+ device->pnp.bus_id, state));
else
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device [%s] transitioned to D%d\n",
+ device->pnp.bus_id, state));
return_VALUE(result);
}
-EXPORT_SYMBOL(acpi_bus_set_power);
-
+EXPORT_SYMBOL(acpi_bus_set_power);
/* --------------------------------------------------------------------------
Event Management
@@ -292,16 +283,12 @@ static DEFINE_SPINLOCK(acpi_bus_event_lock);
LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
-extern int event_is_open;
+extern int event_is_open;
-int
-acpi_bus_generate_event (
- struct acpi_device *device,
- u8 type,
- int data)
+int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data)
{
- struct acpi_bus_event *event = NULL;
- unsigned long flags = 0;
+ struct acpi_bus_event *event = NULL;
+ unsigned long flags = 0;
ACPI_FUNCTION_TRACE("acpi_bus_generate_event");
@@ -329,14 +316,13 @@ acpi_bus_generate_event (
return_VALUE(0);
}
+
EXPORT_SYMBOL(acpi_bus_generate_event);
-int
-acpi_bus_receive_event (
- struct acpi_bus_event *event)
+int acpi_bus_receive_event(struct acpi_bus_event *event)
{
- unsigned long flags = 0;
- struct acpi_bus_event *entry = NULL;
+ unsigned long flags = 0;
+ struct acpi_bus_event *entry = NULL;
DECLARE_WAITQUEUE(wait, current);
@@ -361,7 +347,8 @@ acpi_bus_receive_event (
}
spin_lock_irqsave(&acpi_bus_event_lock, flags);
- entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
+ entry =
+ list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
if (entry)
list_del(&entry->node);
spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
@@ -375,19 +362,17 @@ acpi_bus_receive_event (
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_receive_event);
+EXPORT_SYMBOL(acpi_bus_receive_event);
/* --------------------------------------------------------------------------
Notification Handling
-------------------------------------------------------------------------- */
static int
-acpi_bus_check_device (
- struct acpi_device *device,
- int *status_changed)
+acpi_bus_check_device(struct acpi_device *device, int *status_changed)
{
- acpi_status status = 0;
+ acpi_status status = 0;
struct acpi_device_status old_status;
ACPI_FUNCTION_TRACE("acpi_bus_check_device");
@@ -422,15 +407,14 @@ acpi_bus_check_device (
if (status_changed)
*status_changed = 1;
-
+
/*
* Device Insertion/Removal
*/
if ((device->status.present) && !(old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
/* TBD: Handle device insertion */
- }
- else if (!(device->status.present) && (old_status.present)) {
+ } else if (!(device->status.present) && (old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
/* TBD: Handle device removal */
}
@@ -438,13 +422,10 @@ acpi_bus_check_device (
return_VALUE(0);
}
-
-static int
-acpi_bus_check_scope (
- struct acpi_device *device)
+static int acpi_bus_check_scope(struct acpi_device *device)
{
- int result = 0;
- int status_changed = 0;
+ int result = 0;
+ int status_changed = 0;
ACPI_FUNCTION_TRACE("acpi_bus_check_scope");
@@ -467,20 +448,15 @@ acpi_bus_check_scope (
return_VALUE(0);
}
-
/**
* acpi_bus_notify
* ---------------
* Callback for all 'system-level' device notifications (values 0x00-0x7F).
*/
-static void
-acpi_bus_notify (
- acpi_handle handle,
- u32 type,
- void *data)
+static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_notify");
@@ -490,64 +466,73 @@ acpi_bus_notify (
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received BUS CHECK notification for device [%s]\n",
+ device->pnp.bus_id));
result = acpi_bus_check_scope(device);
/*
* TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
+ * drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_CHECK:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE CHECK notification for device [%s]\n",
+ device->pnp.bus_id));
result = acpi_bus_check_device(device, NULL);
/*
* TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
+ * drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_WAKE:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE WAKE notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_EJECT_REQUEST:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received EJECT REQUEST notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE CHECK LIGHT notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD: Exactly what does 'light' mean? */
break;
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received FREQUENCY MISMATCH notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received BUS MODE MISMATCH notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_POWER_FAULT:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received POWER FAULT notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n",
- type));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received unknown/unsupported notification [%08x]\n",
+ type));
break;
}
@@ -558,13 +543,12 @@ acpi_bus_notify (
Initialization/Cleanup
-------------------------------------------------------------------------- */
-static int __init
-acpi_bus_init_irq (void)
+static int __init acpi_bus_init_irq(void)
{
- acpi_status status = AE_OK;
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- char *message = NULL;
+ acpi_status status = AE_OK;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ char *message = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_init_irq");
@@ -601,12 +585,10 @@ acpi_bus_init_irq (void)
return_VALUE(0);
}
-
-void __init
-acpi_early_init (void)
+void __init acpi_early_init(void)
{
- acpi_status status = AE_OK;
- struct acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt};
+ acpi_status status = AE_OK;
+ struct acpi_buffer buffer = { sizeof(acpi_fadt), &acpi_fadt };
ACPI_FUNCTION_TRACE("acpi_early_init");
@@ -619,13 +601,15 @@ acpi_early_init (void)
status = acpi_initialize_subsystem();
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n");
+ printk(KERN_ERR PREFIX
+ "Unable to initialize the ACPI Interpreter\n");
goto error0;
}
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n");
+ printk(KERN_ERR PREFIX
+ "Unable to load the System Description Tables\n");
goto error0;
}
@@ -637,7 +621,6 @@ acpi_early_init (void)
printk(KERN_ERR PREFIX "Unable to get the FADT\n");
goto error0;
}
-
#ifdef CONFIG_X86
if (!acpi_ioapic) {
extern acpi_interrupt_flags acpi_sci_flags;
@@ -647,7 +630,8 @@ acpi_early_init (void)
acpi_sci_flags.trigger = 3;
/* Set PIC-mode SCI trigger type */
- acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
+ acpi_pic_sci_set_trigger(acpi_fadt.sci_int,
+ acpi_sci_flags.trigger);
} else {
extern int acpi_sci_override_gsi;
/*
@@ -658,7 +642,10 @@ acpi_early_init (void)
}
#endif
- status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE));
+ status =
+ acpi_enable_subsystem(~
+ (ACPI_NO_HARDWARE_INIT |
+ ACPI_NO_ACPI_ENABLE));
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
goto error0;
@@ -666,30 +653,32 @@ acpi_early_init (void)
return_VOID;
-error0:
+ error0:
disable_acpi();
return_VOID;
}
-static int __init
-acpi_bus_init (void)
+static int __init acpi_bus_init(void)
{
- int result = 0;
- acpi_status status = AE_OK;
- extern acpi_status acpi_os_initialize1(void);
+ int result = 0;
+ acpi_status status = AE_OK;
+ extern acpi_status acpi_os_initialize1(void);
ACPI_FUNCTION_TRACE("acpi_bus_init");
status = acpi_os_initialize1();
- status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
+ status =
+ acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n");
+ printk(KERN_ERR PREFIX
+ "Unable to start the ACPI Interpreter\n");
goto error1;
}
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n");
+ printk(KERN_ERR PREFIX
+ "Unable to initialize ACPI OS objects\n");
goto error1;
}
#ifdef CONFIG_ACPI_EC
@@ -723,9 +712,12 @@ acpi_bus_init (void)
/*
* Register the for all standard device notifications.
*/
- status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
+ status =
+ acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
+ &acpi_bus_notify, NULL);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to register for device notifications\n");
+ printk(KERN_ERR PREFIX
+ "Unable to register for device notifications\n");
goto error1;
}
@@ -737,21 +729,20 @@ acpi_bus_init (void)
return_VALUE(0);
/* Mimic structured exception handling */
-error1:
+ error1:
acpi_terminate();
return_VALUE(-ENODEV);
}
-decl_subsys(acpi,NULL,NULL);
+decl_subsys(acpi, NULL, NULL);
-static int __init acpi_init (void)
+static int __init acpi_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_init");
- printk(KERN_INFO PREFIX "Subsystem revision %08x\n",
- ACPI_CA_VERSION);
+ printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION);
if (acpi_disabled) {
printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -767,7 +758,8 @@ static int __init acpi_init (void)
if (!PM_IS_ACTIVE())
pm_active = 1;
else {
- printk(KERN_INFO PREFIX "APM is already active, exiting\n");
+ printk(KERN_INFO PREFIX
+ "APM is already active, exiting\n");
disable_acpi();
result = -ENODEV;
}
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 8162fd0c21a7..4b6d9f0096a1 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -32,7 +32,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_BUTTON_COMPONENT 0x00080000
#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
#define ACPI_BUTTON_CLASS "button"
@@ -42,7 +41,7 @@
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
#define ACPI_BUTTON_SUBCLASS_POWER "power"
-#define ACPI_BUTTON_HID_POWER "PNP0C0C"
+#define ACPI_BUTTON_HID_POWER "PNP0C0C"
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
#define ACPI_BUTTON_TYPE_POWER 0x01
@@ -61,65 +60,65 @@
#define ACPI_BUTTON_TYPE_LID 0x05
#define _COMPONENT ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME ("acpi_button")
+ACPI_MODULE_NAME("acpi_button")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
MODULE_LICENSE("GPL");
-
-static int acpi_button_add (struct acpi_device *device);
-static int acpi_button_remove (struct acpi_device *device, int type);
+static int acpi_button_add(struct acpi_device *device);
+static int acpi_button_remove(struct acpi_device *device, int type);
static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
- .name = ACPI_BUTTON_DRIVER_NAME,
- .class = ACPI_BUTTON_CLASS,
- .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
- .ops = {
- .add = acpi_button_add,
- .remove = acpi_button_remove,
- },
+ .name = ACPI_BUTTON_DRIVER_NAME,
+ .class = ACPI_BUTTON_CLASS,
+ .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
+ .ops = {
+ .add = acpi_button_add,
+ .remove = acpi_button_remove,
+ },
};
struct acpi_button {
- acpi_handle handle;
- struct acpi_device *device; /* Fixed button kludge */
- u8 type;
- unsigned long pushed;
+ acpi_handle handle;
+ struct acpi_device *device; /* Fixed button kludge */
+ u8 type;
+ unsigned long pushed;
};
static struct file_operations acpi_button_info_fops = {
- .open = acpi_button_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_button_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_button_state_fops = {
- .open = acpi_button_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_button_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
+
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_button_dir;
+static struct proc_dir_entry *acpi_button_dir;
static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *) seq->private;
+ struct acpi_button *button = (struct acpi_button *)seq->private;
ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
if (!button || !button->device)
return_VALUE(0);
- seq_printf(seq, "type: %s\n",
- acpi_device_name(button->device));
+ seq_printf(seq, "type: %s\n",
+ acpi_device_name(button->device));
return_VALUE(0);
}
@@ -128,24 +127,24 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
}
-
+
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *) seq->private;
- acpi_status status;
- unsigned long state;
+ struct acpi_button *button = (struct acpi_button *)seq->private;
+ acpi_status status;
+ unsigned long state;
ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
if (!button || !button->device)
return_VALUE(0);
- status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state);
+ status = acpi_evaluate_integer(button->handle, "_LID", NULL, &state);
if (ACPI_FAILURE(status)) {
seq_printf(seq, "state: unsupported\n");
- }
- else{
- seq_printf(seq, "state: %s\n", (state ? "open" : "closed"));
+ } else {
+ seq_printf(seq, "state: %s\n",
+ (state ? "open" : "closed"));
}
return_VALUE(0);
@@ -160,12 +159,10 @@ static struct proc_dir_entry *acpi_power_dir;
static struct proc_dir_entry *acpi_sleep_dir;
static struct proc_dir_entry *acpi_lid_dir;
-static int
-acpi_button_add_fs (
- struct acpi_device *device)
+static int acpi_button_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_button *button = NULL;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add_fs");
@@ -178,21 +175,21 @@ acpi_button_add_fs (
case ACPI_BUTTON_TYPE_POWER:
case ACPI_BUTTON_TYPE_POWERF:
if (!acpi_power_dir)
- acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
- acpi_button_dir);
+ acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
+ acpi_button_dir);
entry = acpi_power_dir;
break;
case ACPI_BUTTON_TYPE_SLEEP:
case ACPI_BUTTON_TYPE_SLEEPF:
if (!acpi_sleep_dir)
- acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
- acpi_button_dir);
+ acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
+ acpi_button_dir);
entry = acpi_sleep_dir;
break;
case ACPI_BUTTON_TYPE_LID:
if (!acpi_lid_dir)
- acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
- acpi_button_dir);
+ acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
+ acpi_button_dir);
entry = acpi_lid_dir;
break;
}
@@ -208,11 +205,11 @@ acpi_button_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BUTTON_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
else {
entry->proc_fops = &acpi_button_info_fops;
entry->data = acpi_driver_data(device);
@@ -222,11 +219,11 @@ acpi_button_add_fs (
/* show lid state [R] */
if (button->type == ACPI_BUTTON_TYPE_LID) {
entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BUTTON_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
else {
entry->proc_fops = &acpi_button_state_fops;
entry->data = acpi_driver_data(device);
@@ -237,12 +234,9 @@ acpi_button_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_button_remove_fs (
- struct acpi_device *device)
+static int acpi_button_remove_fs(struct acpi_device *device)
{
- struct acpi_button *button = NULL;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
@@ -250,30 +244,25 @@ acpi_button_remove_fs (
if (acpi_device_dir(device)) {
if (button->type == ACPI_BUTTON_TYPE_LID)
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
- acpi_device_dir(device));
+ acpi_device_dir(device));
remove_proc_entry(ACPI_BUTTON_FILE_INFO,
- acpi_device_dir(device));
+ acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device),
- acpi_device_dir(device)->parent);
+ acpi_device_dir(device)->parent);
acpi_device_dir(device) = NULL;
}
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_button_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_button *button = (struct acpi_button *) data;
+ struct acpi_button *button = (struct acpi_button *)data;
ACPI_FUNCTION_TRACE("acpi_button_notify");
@@ -282,24 +271,22 @@ acpi_button_notify (
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
- acpi_bus_generate_event(button->device, event, ++button->pushed);
+ acpi_bus_generate_event(button->device, event,
+ ++button->pushed);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static acpi_status
-acpi_button_notify_fixed (
- void *data)
+static acpi_status acpi_button_notify_fixed(void *data)
{
- struct acpi_button *button = (struct acpi_button *) data;
-
+ struct acpi_button *button = (struct acpi_button *)data;
+
ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
if (!button)
@@ -310,14 +297,11 @@ acpi_button_notify_fixed (
return_ACPI_STATUS(AE_OK);
}
-
-static int
-acpi_button_add (
- struct acpi_device *device)
+static int acpi_button_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_button *button = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add");
@@ -339,42 +323,34 @@ acpi_button_add (
*/
if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
button->type = ACPI_BUTTON_TYPE_POWER;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_POWER);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_POWER);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWERF;
strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_POWERF);
- sprintf(acpi_device_class(device), "%s/%s",
+ ACPI_BUTTON_DEVICE_NAME_POWERF);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_SLEEP);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_SLEEP);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEPF;
strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_SLEEPF);
- sprintf(acpi_device_class(device), "%s/%s",
+ ACPI_BUTTON_DEVICE_NAME_SLEEPF);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_LID);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_LID);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
- }
- else {
+ } else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
- acpi_device_hid(device)));
+ acpi_device_hid(device)));
result = -ENODEV;
goto end;
}
@@ -385,46 +361,46 @@ acpi_button_add (
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
- status = acpi_install_fixed_event_handler (
- ACPI_EVENT_POWER_BUTTON,
- acpi_button_notify_fixed,
- button);
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed,
+ button);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
- status = acpi_install_fixed_event_handler (
- ACPI_EVENT_SLEEP_BUTTON,
- acpi_button_notify_fixed,
- button);
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed,
+ button);
break;
default:
- status = acpi_install_notify_handler (
- button->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_button_notify,
- button);
+ status = acpi_install_notify_handler(button->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify,
+ button);
break;
}
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
- acpi_set_gpe_type(device->wakeup.gpe_device,
- device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
- acpi_enable_gpe(device->wakeup.gpe_device,
- device->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_set_gpe_type(device->wakeup.gpe_device,
+ device->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_enable_gpe(device->wakeup.gpe_device,
+ device->wakeup.gpe_number, ACPI_NOT_ISR);
device->wakeup.state.enabled = 1;
}
- printk(KERN_INFO PREFIX "%s [%s]\n",
- acpi_device_name(device), acpi_device_bid(device));
+ printk(KERN_INFO PREFIX "%s [%s]\n",
+ acpi_device_name(device), acpi_device_bid(device));
-end:
+ end:
if (result) {
acpi_button_remove_fs(device);
kfree(button);
@@ -433,12 +409,10 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_button_remove (struct acpi_device *device, int type)
+static int acpi_button_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_button *button = NULL;
+ acpi_status status = 0;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_remove");
@@ -450,35 +424,36 @@ acpi_button_remove (struct acpi_device *device, int type)
/* Unregister for device notifications. */
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
- status = acpi_remove_fixed_event_handler(
- ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed);
+ status =
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
- status = acpi_remove_fixed_event_handler(
- ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed);
+ status =
+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed);
break;
default:
status = acpi_remove_notify_handler(button->handle,
- ACPI_DEVICE_NOTIFY, acpi_button_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify);
break;
}
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
- acpi_button_remove_fs(device);
+ acpi_button_remove_fs(device);
kfree(button);
return_VALUE(0);
}
-
-static int __init
-acpi_button_init (void)
+static int __init acpi_button_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_button_init");
@@ -495,15 +470,13 @@ acpi_button_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_button_exit (void)
+static void __exit acpi_button_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_button_exit");
acpi_bus_unregister_driver(&acpi_button_driver);
- if (acpi_power_dir)
+ if (acpi_power_dir)
remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
if (acpi_sleep_dir)
remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
@@ -514,6 +487,5 @@ acpi_button_exit (void)
return_VOID;
}
-
module_init(acpi_button_init);
module_exit(acpi_button_exit);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 97013ddfa202..10dd695a1dd9 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -44,9 +44,9 @@
#define ACPI_CONTAINER_COMPONENT 0x01000000
#define _COMPONENT ACPI_CONTAINER_COMPONENT
-ACPI_MODULE_NAME ("acpi_container")
+ACPI_MODULE_NAME("acpi_container")
-MODULE_AUTHOR("Anil S Keshavamurthy");
+ MODULE_AUTHOR("Anil S Keshavamurthy");
MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -56,41 +56,38 @@ static int acpi_container_add(struct acpi_device *device);
static int acpi_container_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_container_driver = {
- .name = ACPI_CONTAINER_DRIVER_NAME,
- .class = ACPI_CONTAINER_CLASS,
- .ids = "ACPI0004,PNP0A05,PNP0A06",
- .ops = {
- .add = acpi_container_add,
- .remove = acpi_container_remove,
- },
+ .name = ACPI_CONTAINER_DRIVER_NAME,
+ .class = ACPI_CONTAINER_CLASS,
+ .ids = "ACPI0004,PNP0A05,PNP0A06",
+ .ops = {
+ .add = acpi_container_add,
+ .remove = acpi_container_remove,
+ },
};
-
/*******************************************************************/
-static int
-is_device_present(acpi_handle handle)
+static int is_device_present(acpi_handle handle)
{
- acpi_handle temp;
- acpi_status status;
- unsigned long sta;
+ acpi_handle temp;
+ acpi_status status;
+ unsigned long sta;
ACPI_FUNCTION_TRACE("is_device_present");
status = acpi_get_handle(handle, "_STA", &temp);
if (ACPI_FAILURE(status))
- return_VALUE(1); /* _STA not found, assmue device present */
+ return_VALUE(1); /* _STA not found, assmue device present */
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
- return_VALUE(0); /* Firmware error */
+ return_VALUE(0); /* Firmware error */
return_VALUE((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT);
}
/*******************************************************************/
-static int
-acpi_container_add(struct acpi_device *device)
+static int acpi_container_add(struct acpi_device *device)
{
struct acpi_container *container;
@@ -102,28 +99,26 @@ acpi_container_add(struct acpi_device *device)
}
container = kmalloc(sizeof(struct acpi_container), GFP_KERNEL);
- if(!container)
+ if (!container)
return_VALUE(-ENOMEM);
-
+
memset(container, 0, sizeof(struct acpi_container));
container->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
acpi_driver_data(device) = container;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", \
- acpi_device_name(device), acpi_device_bid(device)));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
+ acpi_device_name(device), acpi_device_bid(device)));
return_VALUE(0);
}
-static int
-acpi_container_remove(struct acpi_device *device, int type)
+static int acpi_container_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_container *pc = NULL;
- pc = (struct acpi_container*) acpi_driver_data(device);
+ acpi_status status = AE_OK;
+ struct acpi_container *pc = NULL;
+ pc = (struct acpi_container *)acpi_driver_data(device);
if (pc)
kfree(pc);
@@ -131,9 +126,7 @@ acpi_container_remove(struct acpi_device *device, int type)
return status;
}
-
-static int
-container_device_add(struct acpi_device **device, acpi_handle handle)
+static int container_device_add(struct acpi_device **device, acpi_handle handle)
{
acpi_handle phandle;
struct acpi_device *pdev;
@@ -158,10 +151,9 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
return_VALUE(result);
}
-static void
-container_notify_cb(acpi_handle handle, u32 type, void *context)
+static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = NULL;
int result;
int present;
acpi_status status;
@@ -169,14 +161,14 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
ACPI_FUNCTION_TRACE("container_notify_cb");
present = is_device_present(handle);
-
+
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* Fall through */
case ACPI_NOTIFY_DEVICE_CHECK:
printk("Container driver received %s event\n",
- (type == ACPI_NOTIFY_BUS_CHECK)?
- "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ (type == ACPI_NOTIFY_BUS_CHECK) ?
+ "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
status = acpi_bus_get_device(handle, &device);
if (present) {
if (ACPI_FAILURE(status) || !device) {
@@ -207,15 +199,13 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
static acpi_status
container_walk_namespace_cb(acpi_handle handle,
- u32 lvl,
- void *context,
- void **rv)
+ u32 lvl, void *context, void **rv)
{
- char *hid = NULL;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_device_info *info;
- acpi_status status;
- int *action = context;
+ char *hid = NULL;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_device_info *info;
+ acpi_status status;
+ int *action = context;
ACPI_FUNCTION_TRACE("container_walk_namespace_cb");
@@ -233,66 +223,60 @@ container_walk_namespace_cb(acpi_handle handle,
}
if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
- strcmp(hid, "PNP0A06")) {
+ strcmp(hid, "PNP0A06")) {
goto end;
}
- switch(*action) {
+ switch (*action) {
case INSTALL_NOTIFY_HANDLER:
acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb,
- NULL);
+ ACPI_SYSTEM_NOTIFY,
+ container_notify_cb, NULL);
break;
case UNINSTALL_NOTIFY_HANDLER:
acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb);
+ ACPI_SYSTEM_NOTIFY,
+ container_notify_cb);
break;
default:
break;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
return_ACPI_STATUS(AE_OK);
}
-
-static int __init
-acpi_container_init(void)
+static int __init acpi_container_init(void)
{
- int result = 0;
- int action = INSTALL_NOTIFY_HANDLER;
+ int result = 0;
+ int action = INSTALL_NOTIFY_HANDLER;
result = acpi_bus_register_driver(&acpi_container_driver);
if (result < 0) {
- return(result);
+ return (result);
}
/* register notify handler to every container device */
acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ container_walk_namespace_cb, &action, NULL);
- return(0);
+ return (0);
}
-static void __exit
-acpi_container_exit(void)
+static void __exit acpi_container_exit(void)
{
- int action = UNINSTALL_NOTIFY_HANDLER;
+ int action = UNINSTALL_NOTIFY_HANDLER;
ACPI_FUNCTION_TRACE("acpi_container_exit");
acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ container_walk_namespace_cb, &action, NULL);
acpi_bus_unregister_driver(&acpi_container_driver);
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 2c0dac559f16..263322b7d113 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -12,17 +12,14 @@
#include <acpi/acglobal.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("debug")
-
+ACPI_MODULE_NAME("debug")
#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
-
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
-
#define MODULE_PARAM_PREFIX
-module_param(acpi_dbg_layer, uint, 0400);
+ module_param(acpi_dbg_layer, uint, 0400);
module_param(acpi_dbg_level, uint, 0400);
struct acpi_dlayer {
@@ -35,8 +32,7 @@ struct acpi_dlevel {
};
#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
-static const struct acpi_dlayer acpi_debug_layers[] =
-{
+static const struct acpi_dlayer acpi_debug_layers[] = {
ACPI_DEBUG_INIT(ACPI_UTILITIES),
ACPI_DEBUG_INIT(ACPI_HARDWARE),
ACPI_DEBUG_INIT(ACPI_EVENTS),
@@ -53,8 +49,7 @@ static const struct acpi_dlayer acpi_debug_layers[] =
ACPI_DEBUG_INIT(ACPI_TOOLS),
};
-static const struct acpi_dlevel acpi_debug_levels[] =
-{
+static const struct acpi_dlevel acpi_debug_levels[] = {
ACPI_DEBUG_INIT(ACPI_LV_ERROR),
ACPI_DEBUG_INIT(ACPI_LV_WARN),
ACPI_DEBUG_INIT(ACPI_LV_INIT),
@@ -88,81 +83,77 @@ static const struct acpi_dlevel acpi_debug_levels[] =
ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
- ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
+ ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
};
static int
-acpi_system_read_debug (
- char *page,
- char **start,
- off_t off,
- int count,
- int *eof,
- void *data)
+acpi_system_read_debug(char *page,
+ char **start, off_t off, int count, int *eof, void *data)
{
- char *p = page;
- int size = 0;
- unsigned int i;
+ char *p = page;
+ int size = 0;
+ unsigned int i;
if (off != 0)
goto end;
p += sprintf(p, "%-25s\tHex SET\n", "Description");
- switch ((unsigned long) data) {
+ switch ((unsigned long)data) {
case 0:
for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
- acpi_debug_layers[i].name,
- acpi_debug_layers[i].value,
- (acpi_dbg_layer & acpi_debug_layers[i].value) ?
- '*' : ' ');
+ acpi_debug_layers[i].name,
+ acpi_debug_layers[i].value,
+ (acpi_dbg_layer & acpi_debug_layers[i].
+ value) ? '*' : ' ');
}
p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
- ACPI_ALL_DRIVERS,
- (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
- '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
- ' ' : '-');
+ ACPI_ALL_DRIVERS,
+ (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
+ ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
+ ACPI_ALL_DRIVERS) ==
+ 0 ? ' ' : '-');
p += sprintf(p,
- "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
- acpi_dbg_layer);
+ "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
+ acpi_dbg_layer);
break;
case 1:
for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
- acpi_debug_levels[i].name,
- acpi_debug_levels[i].value,
- (acpi_dbg_level & acpi_debug_levels[i].value) ?
- '*' : ' ');
+ acpi_debug_levels[i].name,
+ acpi_debug_levels[i].value,
+ (acpi_dbg_level & acpi_debug_levels[i].
+ value) ? '*' : ' ');
}
p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
- acpi_dbg_level);
+ acpi_dbg_level);
break;
default:
p += sprintf(p, "Invalid debug option\n");
break;
}
-
-end:
+
+ end:
size = (p - page);
- if (size <= off+count) *eof = 1;
+ if (size <= off + count)
+ *eof = 1;
*start = page + off;
size -= off;
- if (size>count) size = count;
- if (size<0) size = 0;
+ if (size > count)
+ size = count;
+ if (size < 0)
+ size = 0;
return size;
}
-
static int
-acpi_system_write_debug (
- struct file *file,
- const char __user *buffer,
- unsigned long count,
- void *data)
+acpi_system_write_debug(struct file *file,
+ const char __user * buffer,
+ unsigned long count, void *data)
{
- char debug_string[12] = {'\0'};
+ char debug_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_system_write_debug");
@@ -174,7 +165,7 @@ acpi_system_write_debug (
debug_string[count] = '\0';
- switch ((unsigned long) data) {
+ switch ((unsigned long)data) {
case 0:
acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
break;
@@ -190,9 +181,9 @@ acpi_system_write_debug (
static int __init acpi_debug_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
- char * name;
+ char *name;
ACPI_FUNCTION_TRACE("acpi_debug_init");
@@ -201,8 +192,10 @@ static int __init acpi_debug_init(void)
/* 'debug_layer' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
- entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
- acpi_system_read_debug,(void *)0);
+ entry =
+ create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir, acpi_system_read_debug,
+ (void *)0);
if (entry)
entry->write_proc = acpi_system_write_debug;
else
@@ -210,19 +203,21 @@ static int __init acpi_debug_init(void)
/* 'debug_level' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
- entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
- acpi_system_read_debug, (void *)1);
- if (entry)
+ entry =
+ create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir, acpi_system_read_debug,
+ (void *)1);
+ if (entry)
entry->write_proc = acpi_system_write_debug;
else
goto Error;
- Done:
+ Done:
return_VALUE(error);
- Error:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n", name));
+ Error:
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n", name));
remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 84193983d6ba..2022aeaecfbb 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
@@ -49,18 +48,14 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsfield")
+ACPI_MODULE_NAME("dsfield")
/* Local prototypes */
-
static acpi_status
-acpi_ds_get_field_names (
- struct acpi_create_field_info *info,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg);
-
+acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg);
/*******************************************************************************
*
@@ -82,41 +77,36 @@ acpi_ds_get_field_names (
******************************************************************************/
acpi_status
-acpi_ds_create_buffer_field (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *arg;
- struct acpi_namespace_node *node;
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *second_desc = NULL;
- u32 flags;
-
-
- ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *second_desc = NULL;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ds_create_buffer_field");
/* Get the name_string argument */
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
- arg = acpi_ps_get_arg (op, 3);
- }
- else {
+ arg = acpi_ps_get_arg(op, 3);
+ } else {
/* Create Bit/Byte/Word/Dword field */
- arg = acpi_ps_get_arg (op, 2);
+ arg = acpi_ps_get_arg(op, 2);
}
if (!arg) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
if (walk_state->deferred_node) {
node = walk_state->deferred_node;
status = AE_OK;
- }
- else {
+ } else {
/*
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the size
@@ -124,21 +114,22 @@ acpi_ds_create_buffer_field (
*/
if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
- }
- else {
+ } else {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
- ACPI_NS_ERROR_IF_FOUND;
+ ACPI_NS_ERROR_IF_FOUND;
}
/*
* Enter the name_string into the namespace
*/
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
- flags, walk_state, &(node));
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state,
+ &(node));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
}
@@ -153,9 +144,9 @@ acpi_ds_create_buffer_field (
* and we need to create the field object. Otherwise, this was a lookup
* of an existing node and we don't want to create the field object again.
*/
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -165,7 +156,7 @@ acpi_ds_create_buffer_field (
/* Create the buffer field object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -176,28 +167,26 @@ acpi_ds_create_buffer_field (
* opcode and operands -- since the buffer and index
* operands must be evaluated.
*/
- second_desc = obj_desc->common.next_object;
+ second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data;
second_desc->extra.aml_length = op->named.length;
obj_desc->buffer_field.node = node;
/* Attach constructed field descriptors to parent node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_field_names
@@ -214,17 +203,14 @@ cleanup:
******************************************************************************/
static acpi_status
-acpi_ds_get_field_names (
- struct acpi_create_field_info *info,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg)
+acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg)
{
- acpi_status status;
- acpi_integer position;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
+ acpi_status status;
+ acpi_integer position;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info);
/* First field starts at bit zero */
@@ -243,18 +229,16 @@ acpi_ds_get_field_names (
case AML_INT_RESERVEDFIELD_OP:
position = (acpi_integer) info->field_bit_position
- + (acpi_integer) arg->common.value.size;
+ + (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR ((
- "Bit offset within field too large (> 0xFFFFFFFF)\n"));
- return_ACPI_STATUS (AE_SUPPORT);
+ ACPI_REPORT_ERROR(("Bit offset within field too large (> 0xFFFFFFFF)\n"));
+ return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position = (u32) position;
break;
-
case AML_INT_ACCESSFIELD_OP:
/*
@@ -266,73 +250,70 @@ acpi_ds_get_field_names (
* ACCESS_TYPE bits
*/
info->field_flags = (u8)
- ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
- ((u8) ((u32) arg->common.value.integer >> 8)));
+ ((info->
+ field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
+ ((u8) ((u32) arg->common.value.integer >> 8)));
info->attribute = (u8) (arg->common.value.integer);
break;
-
case AML_INT_NAMEDFIELD_OP:
/* Lookup the name */
- status = acpi_ns_lookup (walk_state->scope_info,
- (char *) &arg->named.name,
- info->field_type, ACPI_IMODE_EXECUTE,
- ACPI_NS_DONT_OPEN_SCOPE,
- walk_state, &info->field_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ (char *)&arg->named.name,
+ info->field_type,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state, &info->field_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Already exists, ignore error */
- }
- else {
+ } else {
arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size;
/* Create and initialize an object for the new Field Node */
- status = acpi_ex_prep_field_value (info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_prep_field_value(info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Keep track of bit position for the next field */
position = (acpi_integer) info->field_bit_position
- + (acpi_integer) arg->common.value.size;
+ + (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR ((
- "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
- (char *) &info->field_node->name));
- return_ACPI_STATUS (AE_SUPPORT);
+ ACPI_REPORT_ERROR(("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", (char *)&info->field_node->name));
+ return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position += info->field_bit_length;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid opcode in field list: %X\n",
- arg->common.aml_opcode));
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid opcode in field list: %X\n",
+ arg->common.aml_opcode));
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg = arg->common.next;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_field
@@ -348,29 +329,28 @@ acpi_ds_get_field_names (
******************************************************************************/
acpi_status
-acpi_ds_create_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_field", op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
- ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.name, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.name, ACPI_TYPE_REGION,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &region_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ return_ACPI_STATUS(status);
}
}
@@ -385,12 +365,11 @@ acpi_ds_create_field (
info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_field_objects
@@ -407,37 +386,34 @@ acpi_ds_create_field (
******************************************************************************/
acpi_status
-acpi_ds_init_field_objects (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_init_field_objects(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg = NULL;
- struct acpi_namespace_node *node;
- u8 type = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
+ acpi_status status;
+ union acpi_parse_object *arg = NULL;
+ struct acpi_namespace_node *node;
+ u8 type = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op);
switch (walk_state->opcode) {
case AML_FIELD_OP:
- arg = acpi_ps_get_arg (op, 2);
+ arg = acpi_ps_get_arg(op, 2);
type = ACPI_TYPE_LOCAL_REGION_FIELD;
break;
case AML_BANK_FIELD_OP:
- arg = acpi_ps_get_arg (op, 4);
+ arg = acpi_ps_get_arg(op, 4);
type = ACPI_TYPE_LOCAL_BANK_FIELD;
break;
case AML_INDEX_FIELD_OP:
- arg = acpi_ps_get_arg (op, 3);
+ arg = acpi_ps_get_arg(op, 3);
type = ACPI_TYPE_LOCAL_INDEX_FIELD;
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -447,16 +423,18 @@ acpi_ds_init_field_objects (
/* Ignore OFFSET and ACCESSAS terms here */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
- status = acpi_ns_lookup (walk_state->scope_info,
- (char *) &arg->named.name,
- type, ACPI_IMODE_LOAD_PASS1,
- ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
- ACPI_NS_ERROR_IF_FOUND,
- walk_state, &node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ (char *)&arg->named.name,
+ type, ACPI_IMODE_LOAD_PASS1,
+ ACPI_NS_NO_UPSEARCH |
+ ACPI_NS_DONT_OPEN_SCOPE |
+ ACPI_NS_ERROR_IF_FOUND,
+ walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Name already exists, just ignore this error */
@@ -472,10 +450,9 @@ acpi_ds_init_field_objects (
arg = arg->common.next;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_bank_field
@@ -491,41 +468,42 @@ acpi_ds_init_field_objects (
******************************************************************************/
acpi_status
-acpi_ds_create_bank_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_bank_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
- ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.name, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.name, ACPI_TYPE_REGION,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &region_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ return_ACPI_STATUS(status);
}
}
/* Second arg is the Bank Register (Field) (must already exist) */
arg = arg->common.next;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Third arg is the bank_value */
@@ -543,12 +521,11 @@ acpi_ds_create_bank_field (
info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_index_field
@@ -564,39 +541,40 @@ acpi_ds_create_bank_field (
******************************************************************************/
acpi_status
-acpi_ds_create_index_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_index_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op);
/* First arg is the name of the Index register (must already exist) */
arg = op->common.value.arg;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Second arg is the data register (must already exist) */
arg = arg->common.next;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.data_register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Next arg is the field flags */
@@ -609,9 +587,7 @@ acpi_ds_create_index_field (
info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index d7790db50178..8693c704aea6 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -41,23 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsinit")
+ACPI_MODULE_NAME("dsinit")
/* Local prototypes */
-
static acpi_status
-acpi_ds_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
-
+acpi_ds_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
/*******************************************************************************
*
@@ -80,26 +74,23 @@ acpi_ds_init_one_object (
******************************************************************************/
static acpi_status
-acpi_ds_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ds_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- acpi_object_type type;
- acpi_status status;
- struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
-
-
- ACPI_FUNCTION_NAME ("ds_init_one_object");
+ struct acpi_init_walk_info *info =
+ (struct acpi_init_walk_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ acpi_object_type type;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ds_init_one_object");
/*
- * We are only interested in objects owned by the table that
+ * We are only interested in NS nodes owned by the table that
* was just loaded
*/
- if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
- info->table_desc->table_id) {
+ if (node->owner_id != info->table_desc->owner_id) {
return (AE_OK);
}
@@ -107,33 +98,31 @@ acpi_ds_init_one_object (
/* And even then, we are only interested in a few object types */
- type = acpi_ns_get_type (obj_handle);
+ type = acpi_ns_get_type(obj_handle);
switch (type) {
case ACPI_TYPE_REGION:
- status = acpi_ds_initialize_region (obj_handle);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Region %p [%4.4s] - Init failure, %s\n",
- obj_handle, acpi_ut_get_node_name (obj_handle),
- acpi_format_exception (status)));
+ status = acpi_ds_initialize_region(obj_handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region %p [%4.4s] - Init failure, %s\n",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle),
+ acpi_format_exception(status)));
}
info->op_region_count++;
break;
-
case ACPI_TYPE_METHOD:
- info->method_count++;
-
/*
* Print a dot for each method unless we are going to print
* the entire pathname
*/
if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
/*
@@ -143,41 +132,32 @@ acpi_ds_init_one_object (
* on a per-table basis. Currently, we just use a global for the width.
*/
if (info->table_desc->pointer->revision == 1) {
- ((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
+ node->flags |= ANOBJ_DATA_WIDTH_32;
}
/*
* Always parse methods to detect errors, we will delete
* the parse tree below
*/
- status = acpi_ds_parse_method (obj_handle);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Method %p [%4.4s] - parse failure, %s\n",
- obj_handle, acpi_ut_get_node_name (obj_handle),
- acpi_format_exception (status)));
+ status = acpi_ds_parse_method(obj_handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\n+Method %p [%4.4s] - parse failure, %s\n",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle),
+ acpi_format_exception(status)));
/* This parse failed, but we will continue parsing more methods */
-
- break;
}
- /*
- * Delete the parse tree. We simply re-parse the method
- * for every execution since there isn't much overhead
- */
- acpi_ns_delete_namespace_subtree (obj_handle);
- acpi_ns_delete_namespace_by_owner (
- ((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
+ info->method_count++;
break;
-
case ACPI_TYPE_DEVICE:
info->device_count++;
break;
-
default:
break;
}
@@ -189,7 +169,6 @@ acpi_ds_init_one_object (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_objects
@@ -205,45 +184,43 @@ acpi_ds_init_one_object (
******************************************************************************/
acpi_status
-acpi_ds_initialize_objects (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *start_node)
+acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
+ struct acpi_namespace_node * start_node)
{
- acpi_status status;
- struct acpi_init_walk_info info;
+ 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"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:"));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "**** Starting initialization of namespace objects ****\n"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));
-
- info.method_count = 0;
+ info.method_count = 0;
info.op_region_count = 0;
- info.object_count = 0;
- info.device_count = 0;
- info.table_desc = table_desc;
+ info.object_count = 0;
+ info.device_count = 0;
+ info.table_desc = table_desc;
/* Walk entire namespace from the supplied root */
- status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
- acpi_ds_init_one_object, &info, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
+ acpi_ds_init_one_object, &info, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
- table_desc->pointer->signature, table_desc->table_id, info.object_count,
- info.device_count, info.method_count, info.op_region_count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
+ table_desc->pointer->signature,
+ table_desc->owner_id, info.object_count,
+ info.device_count, info.method_count,
+ info.op_region_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Methods, %hd Regions\n", info.method_count,
+ info.op_region_count));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 9fc3f4c033eb..36c1ca0b9adb 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -49,67 +48,57 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsmethod")
-
+ACPI_MODULE_NAME("dsmethod")
/*******************************************************************************
*
* FUNCTION: acpi_ds_parse_method
*
- * PARAMETERS: obj_handle - Method node
+ * PARAMETERS: Node - Method node
*
* RETURN: Status
*
- * DESCRIPTION: Call the parser and parse the AML that is associated with the
- * method.
+ * DESCRIPTION: Parse the AML that is associated with the method.
*
* MUTEX: Assumes parser is locked
*
******************************************************************************/
-
-acpi_status
-acpi_ds_parse_method (
- acpi_handle obj_handle)
+acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_owner_id owner_id;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
/* Parameter Validation */
- if (!obj_handle) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ if (!node) {
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
- acpi_ut_get_node_name (obj_handle), obj_handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Parsing [%4.4s] **** named_obj=%p\n",
+ acpi_ut_get_node_name(node), node));
/* Extract the method object from the method Node */
- node = (struct acpi_namespace_node *) obj_handle;
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Create a mutex for the method if there is a concurrency limit */
if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
- (!obj_desc->method.semaphore)) {
- status = acpi_os_create_semaphore (obj_desc->method.concurrency,
- obj_desc->method.concurrency,
- &obj_desc->method.semaphore);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ (!obj_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore(obj_desc->method.concurrency,
+ obj_desc->method.concurrency,
+ &obj_desc->method.semaphore);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -117,14 +106,14 @@ acpi_ds_parse_method (
* Allocate a new parser op to be the root of the parsed
* method tree
*/
- op = acpi_ps_alloc_op (AML_METHOD_OP);
+ op = acpi_ps_alloc_op(AML_METHOD_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init new op with the method name and pointer back to the Node */
- acpi_ps_set_name (op, node->name.integer);
+ acpi_ps_set_name(op, node->name.integer);
op->common.node = node;
/*
@@ -132,22 +121,27 @@ acpi_ds_parse_method (
* objects (such as Operation Regions) can be created during the
* first pass parse.
*/
- owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
- obj_desc->method.owning_id = owner_id;
+ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
/* Create and initialize a new walk state */
- walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
+ walk_state =
+ acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
+ NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup2;
}
- status = acpi_ds_init_aml_walk (walk_state, op, node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup2;
}
/*
@@ -159,19 +153,30 @@ acpi_ds_parse_method (
* method so that operands to the named objects can take on dynamic
* run-time values.
*/
- status = acpi_ps_parse_aml (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ps_parse_aml(walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup2;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
- acpi_ut_get_node_name (obj_handle), obj_handle, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+ acpi_ut_get_node_name(node), node, op));
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
-}
+ /*
+ * Delete the parse tree. We simply re-parse the method for every
+ * execution since there isn't much overhead (compared to keeping lots
+ * of parse trees around)
+ */
+ acpi_ns_delete_namespace_subtree(node);
+ acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
+
+ cleanup2:
+ acpi_ut_release_owner_id(&obj_desc->method.owner_id);
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -190,19 +195,23 @@ acpi_ds_parse_method (
******************************************************************************/
acpi_status
-acpi_ds_begin_method_execution (
- struct acpi_namespace_node *method_node,
- union acpi_operand_object *obj_desc,
- struct acpi_namespace_node *calling_method_node)
+acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
+ union acpi_operand_object *obj_desc,
+ struct acpi_namespace_node *calling_method_node)
{
- acpi_status status = AE_OK;
+ 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);
+ }
+ /* Prevent wraparound of thread count */
- if (!method_node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
+ ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n"));
+ return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
/*
@@ -219,8 +228,9 @@ acpi_ds_begin_method_execution (
* thread that is making recursive method calls.
*/
if (method_node == calling_method_node) {
- if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
- return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
+ if (obj_desc->method.thread_count >=
+ obj_desc->method.concurrency) {
+ return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
}
@@ -228,8 +238,21 @@ acpi_ds_begin_method_execution (
* Get a unit from the method semaphore. This releases the
* interpreter if we block
*/
- status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
- ACPI_WAIT_FOREVER);
+ status =
+ acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
+ ACPI_WAIT_FOREVER);
+ }
+
+ /*
+ * Allocate an Owner ID for this method, only if this is the first thread
+ * to begin concurrent execution. We only need one owner_id, even if the
+ * method is invoked recursively.
+ */
+ 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);
+ }
}
/*
@@ -237,10 +260,9 @@ acpi_ds_begin_method_execution (
* reentered one more time (even if it is the same thread)
*/
obj_desc->method.thread_count++;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_call_control_method
@@ -256,101 +278,99 @@ acpi_ds_begin_method_execution (
******************************************************************************/
acpi_status
-acpi_ds_call_control_method (
- struct acpi_thread_state *thread,
- struct acpi_walk_state *this_walk_state,
- union acpi_parse_object *op)
+acpi_ds_call_control_method(struct acpi_thread_state *thread,
+ struct acpi_walk_state *this_walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- struct acpi_namespace_node *method_node;
- struct acpi_walk_state *next_walk_state;
- union acpi_operand_object *obj_desc;
- struct acpi_parameter_info info;
- u32 i;
-
+ acpi_status status;
+ 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;
+ 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",
- this_walk_state->prev_op, this_walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Execute method %p, currentstate=%p\n",
+ this_walk_state->prev_op, this_walk_state));
/*
* Get the namespace entry for the control method we are about to call
*/
method_node = this_walk_state->method_call_node;
if (!method_node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
- obj_desc = acpi_ns_get_attached_object (method_node);
+ obj_desc = acpi_ns_get_attached_object(method_node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
- obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
-
/* Init for new method, wait on concurrency semaphore */
- status = acpi_ds_begin_method_execution (method_node, obj_desc,
- this_walk_state->method_node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_begin_method_execution(method_node, obj_desc,
+ this_walk_state->method_node);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
/* 1) Parse: Create a new walk state for the preempting walk */
- next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- op, obj_desc, NULL);
+ 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);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Create and init a Root Node */
- op = acpi_ps_create_scope_op ();
+ op = acpi_ps_create_scope_op();
if (!op) {
status = AE_NO_MEMORY;
goto cleanup;
}
- status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
- obj_desc->method.aml_start, obj_desc->method.aml_length,
- NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (next_walk_state);
+ status = acpi_ds_init_aml_walk(next_walk_state, op, method_node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length,
+ NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(next_walk_state);
goto cleanup;
}
/* Begin AML parse */
- status = acpi_ps_parse_aml (next_walk_state);
- acpi_ps_delete_parse_tree (op);
+ status = acpi_ps_parse_aml(next_walk_state);
+ acpi_ps_delete_parse_tree(op);
}
/* 2) Execute: Create a new state for the preempting walk */
- next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- NULL, obj_desc, thread);
+ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
+ NULL, obj_desc, thread);
if (!next_walk_state) {
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
- * start at index 0.
- * Null terminate the list of arguments
+ * stack. Operands on the previous walk state stack always
+ * start at index 0. Also, null terminate the list of arguments
*/
- this_walk_state->operands [this_walk_state->num_operands] = NULL;
+ this_walk_state->operands[this_walk_state->num_operands] = NULL;
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);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, &info, 3);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -359,38 +379,37 @@ acpi_ds_call_control_method (
* (they were copied to new objects)
*/
for (i = 0; i < obj_desc->method.param_count; i++) {
- acpi_ut_remove_reference (this_walk_state->operands [i]);
- this_walk_state->operands [i] = NULL;
+ acpi_ut_remove_reference(this_walk_state->operands[i]);
+ this_walk_state->operands[i] = NULL;
}
/* Clear the operand stack */
this_walk_state->num_operands = 0;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Starting nested execution, newstate=%p\n", next_walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Starting nested execution, newstate=%p\n",
+ next_walk_state));
if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
- status = obj_desc->method.implementation (next_walk_state);
- return_ACPI_STATUS (status);
+ status = obj_desc->method.implementation(next_walk_state);
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(status);
- /* On error, we must delete the new walk state */
+ cleanup:
+ /* Decrement the thread count on the method parse tree */
-cleanup:
if (next_walk_state && (next_walk_state->method_desc)) {
- /* Decrement the thread count on the method parse tree */
-
- next_walk_state->method_desc->method.thread_count--;
+ next_walk_state->method_desc->method.thread_count--;
}
- (void) acpi_ds_terminate_control_method (next_walk_state);
- acpi_ds_delete_walk_state (next_walk_state);
- return_ACPI_STATUS (status);
-}
+ /* On error, we must delete the new walk state */
+
+ acpi_ds_terminate_control_method(next_walk_state);
+ acpi_ds_delete_walk_state(next_walk_state);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -407,25 +426,22 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ds_restart_control_method (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *return_desc)
+acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *return_desc)
{
- acpi_status status;
+ acpi_status status;
+ 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",
+ (char *)&walk_state->method_node->name,
+ walk_state->method_call_op, return_desc));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "****Restart [%4.4s] Op %p return_value_from_callee %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",
- walk_state->return_used,
- walk_state->results, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ " return_from_this_method_used?=%X res_stack %p Walk %p\n",
+ walk_state->return_used,
+ walk_state->results, walk_state));
/* Did the called method return a value? */
@@ -435,10 +451,10 @@ acpi_ds_restart_control_method (
if (walk_state->return_used) {
/* Save the return value from the previous method */
- status = acpi_ds_result_push (return_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
- return_ACPI_STATUS (status);
+ status = acpi_ds_result_push(return_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
+ return_ACPI_STATUS(status);
}
/*
@@ -456,26 +472,26 @@ acpi_ds_restart_control_method (
* 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)) {
+ else if (!acpi_ds_do_implicit_return
+ (return_desc, walk_state, FALSE)) {
/*
* Delete the return value if it will not be used by the
* calling method
*/
- acpi_ut_remove_reference (return_desc);
+ acpi_ut_remove_reference(return_desc);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_terminate_control_method
*
* PARAMETERS: walk_state - State of the method
*
- * RETURN: Status
+ * RETURN: None
*
* DESCRIPTION: Terminate a control method. Delete everything that the method
* created, delete all locals and arguments, and delete the parse
@@ -483,63 +499,59 @@ acpi_ds_restart_control_method (
*
******************************************************************************/
-acpi_status
-acpi_ds_terminate_control_method (
- struct acpi_walk_state *walk_state)
+void acpi_ds_terminate_control_method(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);
+ 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);
if (!walk_state) {
- return (AE_BAD_PARAMETER);
+ return_VOID;
}
/* The current method object was saved in the walk state */
obj_desc = walk_state->method_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_OK);
+ return_VOID;
}
/* Delete all arguments and locals */
- acpi_ds_method_data_delete_all (walk_state);
+ 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER);
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
}
/* Signal completion of the execution of this method if necessary */
if (walk_state->method_desc->method.semaphore) {
- status = acpi_os_signal_semaphore (
- walk_state->method_desc->method.semaphore, 1);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
- status = AE_OK;
+ status =
+ acpi_os_signal_semaphore(walk_state->method_desc->method.
+ semaphore, 1);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not signal method semaphore\n"));
/* Ignore error and continue cleanup */
}
}
if (walk_state->method_desc->method.thread_count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "*** Not deleting method namespace, there are still %d threads\n",
- walk_state->method_desc->method.thread_count));
- }
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "*** Not deleting method namespace, there are still %d threads\n",
+ walk_state->method_desc->method.
+ thread_count));
+ } else { /* This is the last executing thread */
- if (!walk_state->method_desc->method.thread_count) {
/*
* Support to dynamically change a method from not_serialized to
* Serialized if it appears that the method is written foolishly and
@@ -551,10 +563,11 @@ acpi_ds_terminate_control_method (
* before creating the synchronization semaphore.
*/
if ((walk_state->method_desc->method.concurrency == 1) &&
- (!walk_state->method_desc->method.semaphore)) {
- status = acpi_os_create_semaphore (1,
- 1,
- &walk_state->method_desc->method.semaphore);
+ (!walk_state->method_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore(1, 1,
+ &walk_state->
+ method_desc->method.
+ semaphore);
}
/*
@@ -569,28 +582,27 @@ acpi_ds_terminate_control_method (
* Delete any namespace entries created immediately underneath
* the method
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
}
if (method_node->child) {
- acpi_ns_delete_namespace_subtree (method_node);
+ acpi_ns_delete_namespace_subtree(method_node);
}
/*
* Delete any namespace entries created anywhere else within
* the namespace
*/
- acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
+ method.owner_id);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ acpi_ut_release_owner_id(&walk_state->method_desc->method.
+ owner_id);
}
- status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
- return_ACPI_STATUS (status);
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
+ return_VOID;
}
-
-
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index f7998306f756..4095ce70982b 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -41,41 +41,32 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsmthdat")
+ACPI_MODULE_NAME("dsmthdat")
/* Local prototypes */
-
static void
-acpi_ds_method_data_delete_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_delete_value(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state);
static acpi_status
-acpi_ds_method_data_set_value (
- u16 opcode,
- u32 index,
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_set_value(u16 opcode,
+ u32 index,
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state);
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_object_type
-acpi_ds_method_data_get_type (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_get_type(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init
@@ -97,45 +88,41 @@ acpi_ds_method_data_get_type (
*
******************************************************************************/
-void
-acpi_ds_method_data_init (
- struct acpi_walk_state *walk_state)
+void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_init");
+ u32 i;
+ ACPI_FUNCTION_TRACE("ds_method_data_init");
/* Init the method arguments */
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
- ACPI_MOVE_32_TO_32 (&walk_state->arguments[i].name,
+ 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].type = ACPI_TYPE_ANY;
- walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST |
- ANOBJ_METHOD_ARG;
+ walk_state->arguments[i].descriptor = 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;
}
/* Init the method locals */
for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
- ACPI_MOVE_32_TO_32 (&walk_state->local_variables[i].name,
+ ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
NAMEOF_LOCAL_NTE);
walk_state->local_variables[i].name.integer |= (i << 24);
- walk_state->local_variables[i].descriptor = 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].descriptor =
+ 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;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_all
@@ -149,26 +136,25 @@ acpi_ds_method_data_init (
*
******************************************************************************/
-void
-acpi_ds_method_data_delete_all (
- struct acpi_walk_state *walk_state)
+void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
{
- u32 index;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_delete_all");
+ u32 index;
+ ACPI_FUNCTION_TRACE("ds_method_data_delete_all");
/* Detach the locals */
for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
if (walk_state->local_variables[index].object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
- index, walk_state->local_variables[index].object));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
+ index,
+ walk_state->local_variables[index].
+ object));
/* Detach object (if present) and remove a reference */
- acpi_ns_detach_object (&walk_state->local_variables[index]);
+ acpi_ns_detach_object(&walk_state->
+ local_variables[index]);
}
}
@@ -176,19 +162,19 @@ acpi_ds_method_data_delete_all (
for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
if (walk_state->arguments[index].object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
- index, walk_state->arguments[index].object));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
+ index,
+ walk_state->arguments[index].object));
/* Detach object (if present) and remove a reference */
- acpi_ns_detach_object (&walk_state->arguments[index]);
+ acpi_ns_detach_object(&walk_state->arguments[index]);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init_args
@@ -206,47 +192,44 @@ acpi_ds_method_data_delete_all (
******************************************************************************/
acpi_status
-acpi_ds_method_data_init_args (
- union acpi_operand_object **params,
- u32 max_param_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_init_args(union acpi_operand_object **params,
+ u32 max_param_count,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- u32 index = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_method_data_init_args", params);
+ acpi_status status;
+ u32 index = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params);
if (!params) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n"));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "No param list passed to method\n"));
+ return_ACPI_STATUS(AE_OK);
}
/* Copy passed parameters into the new method stack frame */
while ((index < ACPI_METHOD_NUM_ARGS) &&
- (index < max_param_count) &&
- params[index]) {
+ (index < max_param_count) && params[index]) {
/*
* A valid parameter.
* Store the argument in the method/walk descriptor.
* Do not copy the arg in order to implement call by reference
*/
- status = acpi_ds_method_data_set_value (AML_ARG_OP, index,
- params[index], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_set_value(AML_ARG_OP, index,
+ params[index],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
index++;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", index));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%d args passed to method\n", index));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_node
@@ -263,14 +246,12 @@ acpi_ds_method_data_init_args (
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_node (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **node)
+acpi_ds_method_data_get_node(u16 opcode,
+ u32 index,
+ 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
@@ -279,10 +260,10 @@ acpi_ds_method_data_get_node (
case AML_LOCAL_OP:
if (index > ACPI_METHOD_MAX_LOCAL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Local index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_LOCAL));
- return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Local index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_LOCAL));
+ return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
@@ -293,10 +274,10 @@ acpi_ds_method_data_get_node (
case AML_ARG_OP:
if (index > ACPI_METHOD_MAX_ARG) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Arg index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_ARG));
- return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Arg index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_ARG));
+ return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
@@ -305,14 +286,14 @@ acpi_ds_method_data_get_node (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode));
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Opcode %d is invalid\n",
+ opcode));
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_set_value
@@ -330,29 +311,26 @@ acpi_ds_method_data_get_node (
******************************************************************************/
static acpi_status
-acpi_ds_method_data_set_value (
- u16 opcode,
- u32 index,
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_set_value(u16 opcode,
+ u32 index,
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
-
+ 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,
- opcode, object->common.reference_count,
- acpi_ut_get_type_name (object->common.type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
+ opcode, object->common.reference_count,
+ acpi_ut_get_type_name(object->common.type)));
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -361,15 +339,14 @@ acpi_ds_method_data_set_value (
* reference semantics of ACPI Control Method invocation.
* (See ACPI specification 2.0_c)
*/
- acpi_ut_add_reference (object);
+ acpi_ut_add_reference(object);
/* Install the object */
node->object = object;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_value
@@ -387,32 +364,30 @@ acpi_ds_method_data_set_value (
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **dest_desc)
+acpi_ds_method_data_get_value(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object **dest_desc)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_get_value");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_get_value");
/* Validate the object descriptor */
if (!dest_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null object descriptor pointer\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the object from the node */
@@ -433,9 +408,10 @@ acpi_ds_method_data_get_value (
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
if (acpi_gbl_enable_interpreter_slack) {
- object = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ object =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!object) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
object->integer.value = 0;
@@ -444,27 +420,29 @@ acpi_ds_method_data_get_value (
/* Otherwise, return the error */
- else switch (opcode) {
- case AML_ARG_OP:
+ else
+ switch (opcode) {
+ case AML_ARG_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Uninitialized Arg[%d] at node %p\n",
- index, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Uninitialized Arg[%d] at node %p\n",
+ index, node));
- return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
+ return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
- case AML_LOCAL_OP:
+ case AML_LOCAL_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Uninitialized Local[%d] at node %p\n",
- index, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Uninitialized Local[%d] at node %p\n",
+ index, node));
- return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
+ return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
- default:
- ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
- }
+ default:
+ ACPI_REPORT_ERROR(("Not Arg/Local opcode: %X\n",
+ opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
+ }
}
/*
@@ -472,12 +450,11 @@ acpi_ds_method_data_get_value (
* Return an additional reference to the object
*/
*dest_desc = object;
- acpi_ut_add_reference (object);
+ acpi_ut_add_reference(object);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_value
@@ -494,29 +471,25 @@ acpi_ds_method_data_get_value (
******************************************************************************/
static void
-acpi_ds_method_data_delete_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_delete_value(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_delete_value");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_delete_value");
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Get the associated object */
- object = acpi_ns_get_attached_object (node);
+ object = acpi_ns_get_attached_object(node);
/*
* Undefine the Arg or Local by setting its descriptor
@@ -526,19 +499,18 @@ acpi_ds_method_data_delete_value (
node->object = NULL;
if ((object) &&
- (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) {
+ (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
/*
* There is a valid object.
* Decrement the reference count by one to balance the
* increment when the object was stored.
*/
- acpi_ut_remove_reference (object);
+ acpi_ut_remove_reference(object);
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_store_object_to_local
@@ -557,40 +529,38 @@ acpi_ds_method_data_delete_value (
******************************************************************************/
acpi_status
-acpi_ds_store_object_to_local (
- u16 opcode,
- u32 index,
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ds_store_object_to_local(u16 opcode,
+ u32 index,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *current_obj_desc;
- union acpi_operand_object *new_obj_desc;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *current_obj_desc;
+ union acpi_operand_object *new_obj_desc;
- 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));
+ 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));
/* Parameter validation */
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- current_obj_desc = acpi_ns_get_attached_object (node);
+ current_obj_desc = acpi_ns_get_attached_object(node);
if (current_obj_desc == obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
- obj_desc));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
+ obj_desc));
+ return_ACPI_STATUS(status);
}
/*
@@ -602,9 +572,11 @@ acpi_ds_store_object_to_local (
*/
new_obj_desc = obj_desc;
if (obj_desc->common.reference_count > 1) {
- status = acpi_ut_copy_iobject_to_iobject (obj_desc, &new_obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -633,42 +605,39 @@ acpi_ds_store_object_to_local (
*/
if (opcode == AML_ARG_OP) {
/*
- * Make sure that the object is the correct type. This may be
- * overkill, butit is here because references were NS nodes in
- * the past. Now they are operand objects of type Reference.
- */
- if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_REPORT_ERROR ((
- "Invalid descriptor type while storing to method arg: [%s]\n",
- acpi_ut_get_descriptor_name (current_obj_desc)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
- }
-
- /*
* If we have a valid reference object that came from ref_of(),
* do the indirect store
*/
- if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (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",
- new_obj_desc, current_obj_desc));
+ if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (current_obj_desc->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (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",
+ new_obj_desc,
+ current_obj_desc));
/*
* Store this object to the Node (perform the indirect store)
* NOTE: No implicit conversion is performed, as per the ACPI
* specification rules on storing to Locals/Args.
*/
- status = acpi_ex_store_object_to_node (new_obj_desc,
- current_obj_desc->reference.object, walk_state,
- ACPI_NO_IMPLICIT_CONVERSION);
+ status =
+ acpi_ex_store_object_to_node(new_obj_desc,
+ current_obj_desc->
+ reference.
+ object,
+ walk_state,
+ ACPI_NO_IMPLICIT_CONVERSION);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
- acpi_ut_remove_reference (new_obj_desc);
+ acpi_ut_remove_reference(new_obj_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
}
@@ -676,7 +645,7 @@ acpi_ds_store_object_to_local (
* Delete the existing object
* before storing the new one
*/
- acpi_ds_method_data_delete_value (opcode, index, walk_state);
+ acpi_ds_method_data_delete_value(opcode, index, walk_state);
}
/*
@@ -684,18 +653,19 @@ acpi_ds_store_object_to_local (
* the descriptor for the Arg or Local.
* (increments the object reference count by one)
*/
- status = acpi_ds_method_data_set_value (opcode, index, new_obj_desc, walk_state);
+ status =
+ acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
+ walk_state);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
- acpi_ut_remove_reference (new_obj_desc);
+ acpi_ut_remove_reference(new_obj_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -712,39 +682,33 @@ acpi_ds_store_object_to_local (
******************************************************************************/
acpi_object_type
-acpi_ds_method_data_get_type (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_get_type(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_get_type");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_get_type");
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_VALUE ((ACPI_TYPE_NOT_FOUND));
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_VALUE((ACPI_TYPE_NOT_FOUND));
}
/* Get the object */
- object = acpi_ns_get_attached_object (node);
+ object = acpi_ns_get_attached_object(node);
if (!object) {
/* Uninitialized local/arg, return TYPE_ANY */
- return_VALUE (ACPI_TYPE_ANY);
+ return_VALUE(ACPI_TYPE_ANY);
}
/* Get the object type */
- return_VALUE (ACPI_GET_OBJECT_TYPE (object));
+ return_VALUE(ACPI_GET_OBJECT_TYPE(object));
}
#endif
-
-
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index bfbae4e4c667..8ac0cd93adb5 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -50,14 +49,12 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsobject")
+ACPI_MODULE_NAME("dsobject")
static acpi_status
-acpi_ds_build_internal_object (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object **obj_desc_ptr);
-
+acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object **obj_desc_ptr);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -76,17 +73,14 @@ acpi_ds_build_internal_object (
******************************************************************************/
static acpi_status
-acpi_ds_build_internal_object (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_object");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ds_build_internal_object");
*obj_desc_ptr = NULL;
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -96,40 +90,44 @@ acpi_ds_build_internal_object (
* Otherwise, go ahead and look it up now
*/
if (!op->common.node) {
- status = acpi_ns_lookup (walk_state->scope_info,
- op->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- NULL,
- (struct acpi_namespace_node **) &(op->common.node));
-
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (op->common.value.string, status);
- return_ACPI_STATUS (status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ op->common.value.string,
+ ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, NULL,
+ (struct acpi_namespace_node **)
+ &(op->common.node));
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(op->common.value.string,
+ status);
+ return_ACPI_STATUS(status);
}
}
}
/* Create and init the internal ACPI object */
- obj_desc = acpi_ut_create_internal_object (
- (acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
+ obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
+ (op->common.aml_opcode))->
+ object_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
*obj_desc_ptr = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_buffer_obj
@@ -147,20 +145,17 @@ acpi_ds_build_internal_object (
******************************************************************************/
acpi_status
-acpi_ds_build_internal_buffer_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 buffer_length,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 buffer_length,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_parse_object *arg;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *byte_list;
- u32 byte_list_length = 0;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
+ union acpi_parse_object *arg;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *byte_list;
+ u32 byte_list_length = 0;
+ ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
obj_desc = *obj_desc_ptr;
if (obj_desc) {
@@ -168,14 +163,13 @@ acpi_ds_build_internal_buffer_obj (
* We are evaluating a Named buffer object "Name (xxxx, Buffer)".
* The buffer object already exists (from the NS node)
*/
- }
- else {
+ } else {
/* Create a new buffer object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
}
@@ -184,16 +178,17 @@ acpi_ds_build_internal_buffer_obj (
* individual bytes or a string initializer. In either case, a
* byte_list appears in the AML.
*/
- arg = op->common.value.arg; /* skip first arg */
+ arg = op->common.value.arg; /* skip first arg */
byte_list = arg->named.next;
if (byte_list) {
if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Expecting bytelist, got AML opcode %X in op %p\n",
- byte_list->common.aml_opcode, byte_list));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting bytelist, got AML opcode %X in op %p\n",
+ byte_list->common.aml_opcode,
+ byte_list));
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return (AE_TYPE);
}
@@ -214,31 +209,29 @@ acpi_ds_build_internal_buffer_obj (
if (obj_desc->buffer.length == 0) {
obj_desc->buffer.pointer = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Buffer defined with zero length in AML, creating\n"));
- }
- else {
- obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
- obj_desc->buffer.length);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Buffer defined with zero length in AML, creating\n"));
+ } else {
+ obj_desc->buffer.pointer =
+ ACPI_MEM_CALLOCATE(obj_desc->buffer.length);
if (!obj_desc->buffer.pointer) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize buffer from the byte_list (if present) */
if (byte_list) {
- ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
- byte_list_length);
+ ACPI_MEMCPY(obj_desc->buffer.pointer,
+ byte_list->named.data, byte_list_length);
}
}
obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
- op->common.node = (struct acpi_namespace_node *) obj_desc;
- return_ACPI_STATUS (AE_OK);
+ op->common.node = (struct acpi_namespace_node *)obj_desc;
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_package_obj
@@ -256,28 +249,25 @@ acpi_ds_build_internal_buffer_obj (
******************************************************************************/
acpi_status
-acpi_ds_build_internal_package_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 package_length,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 package_length,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_parse_object *arg;
- union acpi_parse_object *parent;
- union acpi_operand_object *obj_desc = NULL;
- u32 package_list_length;
- acpi_status status = AE_OK;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
+ union acpi_parse_object *arg;
+ union acpi_parse_object *parent;
+ union acpi_operand_object *obj_desc = NULL;
+ u32 package_list_length;
+ acpi_status status = AE_OK;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
/* Find the parent of a possibly nested package */
parent = op->common.parent;
- while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
+ while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
+ (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
parent = parent->common.parent;
}
@@ -287,12 +277,11 @@ acpi_ds_build_internal_package_obj (
* We are evaluating a Named package object "Name (xxxx, Package)".
* Get the existing package object from the NS node
*/
- }
- else {
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+ } else {
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
obj_desc->package.node = parent->common.node;
@@ -323,12 +312,13 @@ acpi_ds_build_internal_package_obj (
* 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_MEM_CALLOCATE(((acpi_size) obj_desc->
+ package.count +
+ 1) * sizeof(void *));
if (!obj_desc->package.elements) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -342,11 +332,13 @@ acpi_ds_build_internal_package_obj (
/* Object (package or buffer) is already built */
obj_desc->package.elements[i] =
- ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
- }
- else {
- status = acpi_ds_build_internal_object (walk_state, arg,
- &obj_desc->package.elements[i]);
+ ACPI_CAST_PTR(union acpi_operand_object,
+ arg->common.node);
+ } else {
+ status = acpi_ds_build_internal_object(walk_state, arg,
+ &obj_desc->
+ package.
+ elements[i]);
}
i++;
@@ -354,11 +346,10 @@ acpi_ds_build_internal_package_obj (
}
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
- op->common.node = (struct acpi_namespace_node *) obj_desc;
- return_ACPI_STATUS (status);
+ op->common.node = (struct acpi_namespace_node *)obj_desc;
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_node
@@ -374,57 +365,53 @@ acpi_ds_build_internal_package_obj (
******************************************************************************/
acpi_status
-acpi_ds_create_node (
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- union acpi_parse_object *op)
+acpi_ds_create_node(struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_node", op);
/*
* Because of the execution pass through the non-control-method
* parts of the table, we can arrive here twice. Only init
* the named object node the first time through
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
if (!op->common.value.arg) {
/* No arguments, there is nothing to do */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Build an internal object for the argument(s) */
- status = acpi_ds_build_internal_object (walk_state, op->common.value.arg,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Re-type the object according to its argument */
- node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ node->type = ACPI_GET_OBJECT_TYPE(obj_desc);
/* Attach obj to node */
- status = acpi_ns_attach_object (node, obj_desc, node->type);
+ status = acpi_ns_attach_object(node, obj_desc, node->type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_NO_METHOD_EXECUTION */
-
+#endif /* ACPI_NO_METHOD_EXECUTION */
/*******************************************************************************
*
@@ -444,55 +431,50 @@ acpi_ds_create_node (
******************************************************************************/
acpi_status
-acpi_ds_init_object_from_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u16 opcode,
- union acpi_operand_object **ret_obj_desc)
+acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u16 opcode,
+ union acpi_operand_object **ret_obj_desc)
{
- const struct acpi_opcode_info *op_info;
- union acpi_operand_object *obj_desc;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
+ const struct acpi_opcode_info *op_info;
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ds_init_object_from_op");
obj_desc = *ret_obj_desc;
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Unknown opcode */
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Perform per-object initialization */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER:
/*
* Defer evaluation of Buffer term_arg operand
*/
- obj_desc->buffer.node = (struct acpi_namespace_node *)
- walk_state->operands[0];
+ obj_desc->buffer.node = (struct acpi_namespace_node *)
+ walk_state->operands[0];
obj_desc->buffer.aml_start = op->named.data;
obj_desc->buffer.aml_length = op->named.length;
break;
-
case ACPI_TYPE_PACKAGE:
/*
* Defer evaluation of Package term_arg operand
*/
- obj_desc->package.node = (struct acpi_namespace_node *)
- walk_state->operands[0];
+ obj_desc->package.node = (struct acpi_namespace_node *)
+ walk_state->operands[0];
obj_desc->package.aml_start = op->named.data;
obj_desc->package.aml_length = op->named.length;
break;
-
case ACPI_TYPE_INTEGER:
switch (op_info->type) {
@@ -525,7 +507,7 @@ acpi_ds_init_object_from_op (
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
- acpi_ex_truncate_for32bit_table (obj_desc);
+ acpi_ex_truncate_for32bit_table(obj_desc);
#endif
break;
@@ -536,33 +518,36 @@ acpi_ds_init_object_from_op (
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown constant opcode %X\n", opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown constant opcode %X\n",
+ opcode));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
-
case AML_TYPE_LITERAL:
obj_desc->integer.value = op->common.value.integer;
+#ifndef ACPI_NO_METHOD_EXECUTION
+ acpi_ex_truncate_for32bit_table(obj_desc);
+#endif
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n",
- op_info->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Integer type %X\n",
+ op_info->type));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
-
case ACPI_TYPE_STRING:
obj_desc->string.pointer = op->common.value.string;
- obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
+ obj_desc->string.length =
+ (u32) ACPI_STRLEN(op->common.value.string);
/*
* The string is contained in the ACPI table, don't ever try
@@ -571,11 +556,9 @@ acpi_ds_init_object_from_op (
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
-
case ACPI_TYPE_METHOD:
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
switch (op_info->type) {
@@ -587,14 +570,17 @@ acpi_ds_init_object_from_op (
obj_desc->reference.offset = opcode - AML_LOCAL_OP;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node (AML_LOCAL_OP,
- obj_desc->reference.offset,
- walk_state,
- (struct acpi_namespace_node **) &obj_desc->reference.object);
+ status = acpi_ds_method_data_get_node(AML_LOCAL_OP,
+ obj_desc->
+ reference.offset,
+ walk_state,
+ (struct
+ acpi_namespace_node
+ **)&obj_desc->
+ reference.object);
#endif
break;
-
case AML_TYPE_METHOD_ARGUMENT:
/* Split the opcode into a base opcode + offset */
@@ -603,14 +589,18 @@ acpi_ds_init_object_from_op (
obj_desc->reference.offset = opcode - AML_ARG_OP;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node (AML_ARG_OP,
- obj_desc->reference.offset,
- walk_state,
- (struct acpi_namespace_node **) &obj_desc->reference.object);
+ status = acpi_ds_method_data_get_node(AML_ARG_OP,
+ obj_desc->
+ reference.offset,
+ walk_state,
+ (struct
+ acpi_namespace_node
+ **)&obj_desc->
+ reference.object);
#endif
break;
- default: /* Other literals, etc.. */
+ default: /* Other literals, etc.. */
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
/* Node was saved in Op */
@@ -623,17 +613,15 @@ acpi_ds_init_object_from_op (
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
- ACPI_GET_OBJECT_TYPE (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unimplemented data type: %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index ba13bca28bee..939d167bf87b 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -52,26 +51,21 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsopcode")
+ACPI_MODULE_NAME("dsopcode")
/* Local prototypes */
-
static acpi_status
-acpi_ds_execute_arguments (
- struct acpi_namespace_node *node,
- struct acpi_namespace_node *scope_node,
- u32 aml_length,
- u8 *aml_start);
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+ struct acpi_namespace_node *scope_node,
+ u32 aml_length, u8 * aml_start);
static acpi_status
-acpi_ds_init_buffer_field (
- u16 aml_opcode,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *buffer_desc,
- union acpi_operand_object *offset_desc,
- union acpi_operand_object *length_desc,
- union acpi_operand_object *result_desc);
-
+acpi_ds_init_buffer_field(u16 aml_opcode,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object *buffer_desc,
+ union acpi_operand_object *offset_desc,
+ union acpi_operand_object *length_desc,
+ union acpi_operand_object *result_desc);
/*******************************************************************************
*
@@ -89,26 +83,22 @@ acpi_ds_init_buffer_field (
******************************************************************************/
static acpi_status
-acpi_ds_execute_arguments (
- struct acpi_namespace_node *node,
- struct acpi_namespace_node *scope_node,
- u32 aml_length,
- u8 *aml_start)
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+ struct acpi_namespace_node *scope_node,
+ u32 aml_length, u8 * aml_start)
{
- acpi_status status;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("ds_execute_arguments");
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ds_execute_arguments");
/*
* Allocate a new parser op to be the root of the parsed tree
*/
- op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the Node for use in acpi_ps_parse_aml */
@@ -117,16 +107,17 @@ acpi_ds_execute_arguments (
/* Create and initialize a new parser state */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
- aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+ aml_length, NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
/* Mark this parse as a deferred opcode */
@@ -136,50 +127,51 @@ acpi_ds_execute_arguments (
/* Pass1: Parse the entire declaration */
- status = acpi_ps_parse_aml (walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
+ status = acpi_ps_parse_aml(walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
/* Get and init the Op created above */
op->common.node = node;
- acpi_ps_delete_parse_tree (op);
+ acpi_ps_delete_parse_tree(op);
/* Evaluate the deferred arguments */
- op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
op->common.node = scope_node;
/* Create and initialize a new parser state */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
/* Execute the opcode and arguments */
- status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
- aml_length, NULL, 3);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+ aml_length, NULL, 3);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
/* Mark this execution as a deferred opcode */
walk_state->deferred_node = node;
- status = acpi_ps_parse_aml (walk_state);
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
-}
+ status = acpi_ps_parse_aml(walk_state);
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -195,38 +187,36 @@ acpi_ds_execute_arguments (
******************************************************************************/
acpi_status
-acpi_ds_get_buffer_field_arguments (
- union acpi_operand_object *obj_desc)
+acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
{
- union acpi_operand_object *extra_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_field_arguments", obj_desc);
+ union acpi_operand_object *extra_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the AML pointer (method object) and buffer_field node */
- extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->buffer_field.node;
- 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_ut_get_node_name (node)));
+ 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_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
- extra_desc->extra.aml_length, extra_desc->extra.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
+ extra_desc->extra.aml_length,
+ extra_desc->extra.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_arguments
@@ -240,40 +230,35 @@ acpi_ds_get_buffer_field_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_get_buffer_arguments (
- union acpi_operand_object *obj_desc)
+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);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the Buffer node */
node = obj_desc->buffer.node;
if (!node) {
- ACPI_REPORT_ERROR ((
- "No pointer back to NS node in buffer obj %p\n", obj_desc));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("No pointer back to NS node in buffer obj %p\n", obj_desc));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, node,
- obj_desc->buffer.aml_length, obj_desc->buffer.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, node,
+ obj_desc->buffer.aml_length,
+ obj_desc->buffer.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_package_arguments
@@ -287,40 +272,36 @@ acpi_ds_get_buffer_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_get_package_arguments (
- union acpi_operand_object *obj_desc)
+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);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the Package node */
node = obj_desc->package.node;
if (!node) {
- ACPI_REPORT_ERROR ((
- "No pointer back to NS node in package %p\n", obj_desc));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("No pointer back to NS node in package %p\n",
+ obj_desc));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, node,
- obj_desc->package.aml_length, obj_desc->package.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, node,
+ obj_desc->package.aml_length,
+ obj_desc->package.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_get_region_arguments
@@ -334,44 +315,43 @@ acpi_ds_get_package_arguments (
*
****************************************************************************/
-acpi_status
-acpi_ds_get_region_arguments (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
{
- struct acpi_namespace_node *node;
- acpi_status status;
- union acpi_operand_object *extra_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_region_arguments", obj_desc);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *extra_desc;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc);
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ extra_desc = acpi_ns_get_secondary_object(obj_desc);
if (!extra_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the Region node */
node = obj_desc->region.node;
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
+ 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_ut_get_node_name (node), extra_desc->extra.aml_start));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%4.4s] op_region Arg Init at AML %p\n",
+ acpi_ut_get_node_name(node),
+ extra_desc->extra.aml_start));
/* Execute the argument AML */
- status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
- extra_desc->extra.aml_length, extra_desc->extra.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
+ extra_desc->extra.aml_length,
+ extra_desc->extra.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_region
@@ -384,23 +364,19 @@ acpi_ds_get_region_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_initialize_region (
- acpi_handle obj_handle)
+acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
-
- obj_desc = acpi_ns_get_attached_object (obj_handle);
+ obj_desc = acpi_ns_get_attached_object(obj_handle);
/* Namespace is NOT locked */
- status = acpi_ev_initialize_region (obj_desc, FALSE);
+ status = acpi_ev_initialize_region(obj_desc, FALSE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_buffer_field
@@ -419,30 +395,27 @@ acpi_ds_initialize_region (
******************************************************************************/
static acpi_status
-acpi_ds_init_buffer_field (
- u16 aml_opcode,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *buffer_desc,
- union acpi_operand_object *offset_desc,
- union acpi_operand_object *length_desc,
- union acpi_operand_object *result_desc)
+acpi_ds_init_buffer_field(u16 aml_opcode,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object *buffer_desc,
+ union acpi_operand_object *offset_desc,
+ union acpi_operand_object *length_desc,
+ union acpi_operand_object *result_desc)
{
- u32 offset;
- u32 bit_offset;
- u32 bit_count;
- u8 field_flags;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_init_buffer_field", obj_desc);
+ u32 offset;
+ u32 bit_offset;
+ u32 bit_count;
+ u8 field_flags;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc);
/* Host object must be a Buffer */
- if (ACPI_GET_OBJECT_TYPE (buffer_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target of Create Field is not a Buffer object - %s\n",
- acpi_ut_get_object_type_name (buffer_desc)));
+ if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target of Create Field is not a Buffer object - %s\n",
+ acpi_ut_get_object_type_name(buffer_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -453,11 +426,11 @@ acpi_ds_init_buffer_field (
* out as a name_string, and should therefore now be a NS node
* after resolution in acpi_ex_resolve_operands().
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(%s) destination not a NS Node [%s]\n",
- acpi_ps_get_opcode_name (aml_opcode),
- acpi_ut_get_descriptor_name (result_desc)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(%s) destination not a NS Node [%s]\n",
+ acpi_ps_get_opcode_name(aml_opcode),
+ acpi_ut_get_descriptor_name(result_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -475,13 +448,13 @@ acpi_ds_init_buffer_field (
field_flags = AML_FIELD_ACCESS_BYTE;
bit_offset = offset;
- bit_count = (u32) length_desc->integer.value;
+ bit_count = (u32) length_desc->integer.value;
/* Must have a valid (>0) bit count */
if (bit_count == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Attempt to create_field of length 0\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Attempt to create_field of length 0\n"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -492,7 +465,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bits, Field is one bit */
bit_offset = offset;
- bit_count = 1;
+ bit_count = 1;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
@@ -501,7 +474,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one byte */
bit_offset = 8 * offset;
- bit_count = 8;
+ bit_count = 8;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
@@ -510,7 +483,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one word */
bit_offset = 8 * offset;
- bit_count = 16;
+ bit_count = 16;
field_flags = AML_FIELD_ACCESS_WORD;
break;
@@ -519,7 +492,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one dword */
bit_offset = 8 * offset;
- bit_count = 32;
+ bit_count = 32;
field_flags = AML_FIELD_ACCESS_DWORD;
break;
@@ -528,29 +501,29 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one qword */
bit_offset = 8 * offset;
- bit_count = 64;
+ bit_count = 64;
field_flags = AML_FIELD_ACCESS_QWORD;
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown field creation opcode %02x\n",
- aml_opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown field creation opcode %02x\n",
+ aml_opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Entire field must fit within the current length of the buffer */
- if ((bit_offset + bit_count) >
- (8 * (u32) buffer_desc->buffer.length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
- acpi_ut_get_node_name (result_desc),
- bit_offset + bit_count,
- acpi_ut_get_node_name (buffer_desc->buffer.node),
- 8 * (u32) buffer_desc->buffer.length));
+ if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
+ acpi_ut_get_node_name(result_desc),
+ bit_offset + bit_count,
+ acpi_ut_get_node_name(buffer_desc->buffer.
+ node),
+ 8 * (u32) buffer_desc->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
@@ -560,9 +533,9 @@ acpi_ds_init_buffer_field (
* For field_flags, use LOCK_RULE = 0 (NO_LOCK),
* UPDATE_RULE = 0 (UPDATE_PRESERVE)
*/
- status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0,
- bit_offset, bit_count);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
+ bit_offset, bit_count);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -571,35 +544,33 @@ acpi_ds_init_buffer_field (
/* Reference count for buffer_desc inherits obj_desc count */
buffer_desc->common.reference_count = (u16)
- (buffer_desc->common.reference_count + obj_desc->common.reference_count);
+ (buffer_desc->common.reference_count +
+ obj_desc->common.reference_count);
-
-cleanup:
+ cleanup:
/* Always delete the operands */
- acpi_ut_remove_reference (offset_desc);
- acpi_ut_remove_reference (buffer_desc);
+ acpi_ut_remove_reference(offset_desc);
+ acpi_ut_remove_reference(buffer_desc);
if (aml_opcode == AML_CREATE_FIELD_OP) {
- acpi_ut_remove_reference (length_desc);
+ acpi_ut_remove_reference(length_desc);
}
/* On failure, delete the result descriptor */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (result_desc); /* Result descriptor */
- }
- else {
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(result_desc); /* Result descriptor */
+ } else {
/* Now the address and length are valid for this buffer_field */
obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_buffer_field_operands
@@ -615,24 +586,21 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ds_eval_buffer_field_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- union acpi_parse_object *next_op;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_eval_buffer_field_operands", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+ ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op);
/*
* This is where we evaluate the address and length fields of the
* create_xxx_field declaration
*/
- node = op->common.node;
+ node = op->common.node;
/* next_op points to the op that holds the Buffer */
@@ -640,30 +608,32 @@ acpi_ds_eval_buffer_field_operands (
/* Evaluate/create the address and length operands */
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Resolve the operands */
- status = acpi_ex_resolve_operands (op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
+ status = acpi_ex_resolve_operands(op->common.aml_opcode,
+ ACPI_WALK_OPERANDS, 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");
+ 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");
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode), status));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
+ acpi_ps_get_opcode_name(op->common.
+ aml_opcode), status));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Initialize the Buffer Field */
@@ -671,22 +641,25 @@ acpi_ds_eval_buffer_field_operands (
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* NOTE: Slightly different operands for this opcode */
- status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
- walk_state->operands[0], walk_state->operands[1],
- walk_state->operands[2], walk_state->operands[3]);
- }
- else {
+ status =
+ acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
+ walk_state->operands[0],
+ walk_state->operands[1],
+ walk_state->operands[2],
+ walk_state->operands[3]);
+ } else {
/* All other, create_xxx_field opcodes */
- status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
- walk_state->operands[0], walk_state->operands[1],
- NULL, walk_state->operands[2]);
+ status =
+ acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
+ walk_state->operands[0],
+ walk_state->operands[1], NULL,
+ walk_state->operands[2]);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_region_operands
@@ -702,25 +675,22 @@ acpi_ds_eval_buffer_field_operands (
******************************************************************************/
acpi_status
-acpi_ds_eval_region_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *operand_desc;
- struct acpi_namespace_node *node;
- union acpi_parse_object *next_op;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_eval_region_operands", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *operand_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+ ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op);
/*
* This is where we evaluate the address and length fields of the
* op_region declaration
*/
- node = op->common.node;
+ node = op->common.node;
/* next_op points to the op that holds the space_iD */
@@ -732,26 +702,26 @@ acpi_ds_eval_region_operands (
/* Evaluate/create the address and length operands */
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Resolve the length and address operands to numbers */
- status = acpi_ex_resolve_operands (op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_operands(op->common.aml_opcode,
+ ACPI_WALK_OPERANDS, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- 1, "after acpi_ex_resolve_operands");
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ 1, "after acpi_ex_resolve_operands");
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -761,7 +731,7 @@ acpi_ds_eval_region_operands (
operand_desc = walk_state->operands[walk_state->num_operands - 1];
obj_desc->region.length = (u32) operand_desc->integer.value;
- acpi_ut_remove_reference (operand_desc);
+ acpi_ut_remove_reference(operand_desc);
/*
* Get the address and save it
@@ -770,22 +740,21 @@ acpi_ds_eval_region_operands (
operand_desc = walk_state->operands[walk_state->num_operands - 2];
obj_desc->region.address = (acpi_physical_address)
- operand_desc->integer.value;
- acpi_ut_remove_reference (operand_desc);
+ 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",
- obj_desc,
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
+ obj_desc,
+ ACPI_FORMAT_UINT64(obj_desc->region.address),
+ obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_data_object_operands
@@ -802,46 +771,44 @@ acpi_ds_eval_region_operands (
******************************************************************************/
acpi_status
-acpi_ds_eval_data_object_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object *obj_desc)
+acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object *obj_desc)
{
- acpi_status status;
- union acpi_operand_object *arg_desc;
- u32 length;
-
-
- ACPI_FUNCTION_TRACE ("ds_eval_data_object_operands");
+ acpi_status status;
+ union acpi_operand_object *arg_desc;
+ u32 length;
+ ACPI_FUNCTION_TRACE("ds_eval_data_object_operands");
/* The first operand (for all of these data objects) is the length */
- status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_resolve_operands (walk_state->opcode,
- &(walk_state->operands [walk_state->num_operands -1]),
- walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_operands(walk_state->opcode,
+ &(walk_state->
+ operands[walk_state->num_operands -
+ 1]), walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Extract length operand */
- arg_desc = walk_state->operands [walk_state->num_operands - 1];
+ arg_desc = walk_state->operands[walk_state->num_operands - 1];
length = (u32) arg_desc->integer.value;
/* Cleanup for length operand */
- status = acpi_ds_obj_stack_pop (1, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_pop(1, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- acpi_ut_remove_reference (arg_desc);
+ acpi_ut_remove_reference(arg_desc);
/*
* Create the actual data object
@@ -849,37 +816,42 @@ acpi_ds_eval_data_object_operands (
switch (op->common.aml_opcode) {
case AML_BUFFER_OP:
- status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc);
+ status =
+ acpi_ds_build_internal_buffer_obj(walk_state, op, length,
+ &obj_desc);
break;
case AML_PACKAGE_OP:
case AML_VAR_PACKAGE_OP:
- status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc);
+ status =
+ acpi_ds_build_internal_package_obj(walk_state, op, length,
+ &obj_desc);
break;
default:
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Return the object in the walk_state, unless the parent is a package -
* in this case, the return object will be stored in the parse tree
* for the package.
*/
if ((!op->common.parent) ||
- ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
- (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) &&
- (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+ ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
+ (op->common.parent->common.aml_opcode !=
+ AML_VAR_PACKAGE_OP)
+ && (op->common.parent->common.aml_opcode !=
+ AML_NAME_OP))) {
walk_state->result_obj = obj_desc;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_control_op
@@ -895,19 +867,16 @@ acpi_ds_eval_data_object_operands (
******************************************************************************/
acpi_status
-acpi_ds_exec_begin_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *control_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));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
+ op->common.aml_opcode, walk_state));
switch (op->common.aml_opcode) {
case AML_IF_OP:
@@ -918,7 +887,7 @@ acpi_ds_exec_begin_control_op (
* constructs. We need to manage these as a stack, in order
* to handle nesting.
*/
- control_state = acpi_ut_create_control_state ();
+ control_state = acpi_ut_create_control_state();
if (!control_state) {
status = AE_NO_MEMORY;
break;
@@ -927,14 +896,16 @@ acpi_ds_exec_begin_control_op (
* Save a pointer to the predicate for multiple executions
* of a loop
*/
- control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1;
- control_state->control.package_end = walk_state->parser_state.pkg_end;
+ control_state->control.aml_predicate_start =
+ walk_state->parser_state.aml - 1;
+ control_state->control.package_end =
+ walk_state->parser_state.pkg_end;
control_state->control.opcode = op->common.aml_opcode;
-
/* Push the control state on this walk's control stack */
- acpi_ut_push_generic_state (&walk_state->control_state, control_state);
+ acpi_ut_push_generic_state(&walk_state->control_state,
+ control_state);
break;
case AML_ELSE_OP:
@@ -959,7 +930,6 @@ acpi_ds_exec_begin_control_op (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_end_control_op
@@ -975,46 +945,42 @@ acpi_ds_exec_begin_control_op (
******************************************************************************/
acpi_status
-acpi_ds_exec_end_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *control_state;
-
-
- ACPI_FUNCTION_NAME ("ds_exec_end_control_op");
+ acpi_status status = AE_OK;
+ union acpi_generic_state *control_state;
+ ACPI_FUNCTION_NAME("ds_exec_end_control_op");
switch (op->common.aml_opcode) {
case AML_IF_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
/*
* Save the result of the predicate in case there is an
* ELSE to come
*/
walk_state->last_predicate =
- (u8) walk_state->control_state->common.value;
+ (u8) walk_state->control_state->common.value;
/*
* Pop the control state that was created at the start
* of the IF and free it
*/
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
- acpi_ut_delete_generic_state (control_state);
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->control_state);
+ acpi_ut_delete_generic_state(control_state);
break;
-
case AML_ELSE_OP:
break;
-
case AML_WHILE_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
+ 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! */
@@ -1022,22 +988,24 @@ acpi_ds_exec_end_control_op (
status = AE_CTRL_PENDING;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[WHILE_OP] termination! Op=%p\n",op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[WHILE_OP] termination! Op=%p\n", op));
/* Pop this control state and free it */
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->control_state);
- walk_state->aml_last_while = control_state->control.aml_predicate_start;
- acpi_ut_delete_generic_state (control_state);
+ walk_state->aml_last_while =
+ control_state->control.aml_predicate_start;
+ acpi_ut_delete_generic_state(control_state);
break;
-
case AML_RETURN_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[RETURN_OP] Op=%p Arg=%p\n", op,
+ op->common.value.arg));
/*
* One optional operand -- the return value
@@ -1047,12 +1015,14 @@ acpi_ds_exec_end_control_op (
if (op->common.value.arg) {
/* Since we have a real Return(), delete any implicit return */
- acpi_ds_clear_implicit_return (walk_state);
+ acpi_ds_clear_implicit_return(walk_state);
/* Return statement has an immediate operand */
- status = acpi_ds_create_operands (walk_state, op->common.value.arg);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.arg);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -1061,8 +1031,10 @@ acpi_ds_exec_end_control_op (
* an arg or local), resolve it now because it may
* cease to exist at the end of the method.
*/
- status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -1072,12 +1044,11 @@ acpi_ds_exec_end_control_op (
* is set to anything other than zero!
*/
walk_state->return_desc = walk_state->operands[0];
- }
- else if ((walk_state->results) &&
- (walk_state->results->results.num_results > 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);
+ acpi_ds_clear_implicit_return(walk_state);
/*
* The return value has come from a previous calculation.
@@ -1088,67 +1059,78 @@ acpi_ds_exec_end_control_op (
*
* Allow references created by the Index operator to return unchanged.
*/
- if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc [0]) == ACPI_TYPE_LOCAL_REFERENCE) &&
- ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
- status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
- if (ACPI_FAILURE (status)) {
+ if ((ACPI_GET_DESCRIPTOR_TYPE
+ (walk_state->results->results.obj_desc[0]) ==
+ ACPI_DESC_TYPE_OPERAND)
+ &&
+ (ACPI_GET_OBJECT_TYPE
+ (walk_state->results->results.obj_desc[0]) ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && ((walk_state->results->results.obj_desc[0])->
+ reference.opcode != AML_INDEX_OP)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->
+ results->results.
+ obj_desc[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
- walk_state->return_desc = walk_state->results->results.obj_desc [0];
- }
- else {
+ walk_state->return_desc =
+ walk_state->results->results.obj_desc[0];
+ } else {
/* No return operand */
if (walk_state->num_operands) {
- acpi_ut_remove_reference (walk_state->operands [0]);
+ acpi_ut_remove_reference(walk_state->
+ operands[0]);
}
- walk_state->operands [0] = NULL;
- walk_state->num_operands = 0;
- walk_state->return_desc = NULL;
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
+ walk_state->return_desc = NULL;
}
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Completed RETURN_OP State=%p, ret_val=%p\n",
- walk_state, walk_state->return_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Completed RETURN_OP State=%p, ret_val=%p\n",
+ walk_state, walk_state->return_desc));
/* End the control method execution right now */
status = AE_CTRL_TERMINATE;
break;
-
case AML_NOOP_OP:
/* Just do nothing! */
break;
-
case AML_BREAK_POINT_OP:
/* Call up to the OS service layer to handle this */
- status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
+ status =
+ acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
+ "Executed AML Breakpoint opcode");
/* If and when it returns, all done. */
break;
-
case AML_BREAK_OP:
- case AML_CONTINUE_OP: /* ACPI 2.0 */
-
+ case AML_CONTINUE_OP: /* ACPI 2.0 */
/* Pop and delete control states until we find a while */
while (walk_state->control_state &&
- (walk_state->control_state->control.opcode != AML_WHILE_OP)) {
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
- acpi_ut_delete_generic_state (control_state);
+ (walk_state->control_state->control.opcode !=
+ AML_WHILE_OP)) {
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->
+ control_state);
+ acpi_ut_delete_generic_state(control_state);
}
/* No while found? */
@@ -1159,23 +1141,23 @@ acpi_ds_exec_end_control_op (
/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
- walk_state->aml_last_while = walk_state->control_state->control.package_end;
+ walk_state->aml_last_while =
+ walk_state->control_state->control.package_end;
/* Return status depending on opcode */
if (op->common.aml_opcode == AML_BREAK_OP) {
status = AE_CTRL_BREAK;
- }
- else {
+ } else {
status = AE_CTRL_CONTINUE;
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n",
- op->common.aml_opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown control opcode=%X Op=%p\n",
+ op->common.aml_opcode, op));
status = AE_AML_BAD_OPCODE;
break;
@@ -1183,4 +1165,3 @@ acpi_ds_exec_end_control_op (
return (status);
}
-
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 9613349ac31d..83ae1c1aa286 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -51,8 +50,7 @@
#include <acpi/acdebug.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsutils")
-
+ACPI_MODULE_NAME("dsutils")
/*******************************************************************************
*
@@ -68,13 +66,9 @@
* parent method exits.)
*
******************************************************************************/
-
-void
-acpi_ds_clear_implicit_return (
- struct acpi_walk_state *walk_state)
+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
@@ -89,16 +83,15 @@ acpi_ds_clear_implicit_return (
* complex statements, the implicit return value can be
* bubbled up several levels.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Removing reference on stale implicit return obj %p\n",
- walk_state->implicit_return_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
- acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ acpi_ut_remove_reference(walk_state->implicit_return_obj);
walk_state->implicit_return_obj = NULL;
}
}
-
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -119,27 +112,22 @@ acpi_ds_clear_implicit_return (
******************************************************************************/
u8
-acpi_ds_do_implicit_return (
- union acpi_operand_object *return_desc,
- struct acpi_walk_state *walk_state,
- u8 add_reference)
+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
* have a valid return object
*/
- if ((!acpi_gbl_enable_interpreter_slack) ||
- (!return_desc)) {
+ if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
return (FALSE);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result %p will be implicitly returned; Prev=%p\n",
- return_desc,
- walk_state->implicit_return_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc, walk_state->implicit_return_obj));
/*
* Delete any "stale" implicit return value first. However, in
@@ -151,20 +139,19 @@ acpi_ds_do_implicit_return (
if (walk_state->implicit_return_obj == return_desc) {
return (TRUE);
}
- acpi_ds_clear_implicit_return (walk_state);
+ acpi_ds_clear_implicit_return(walk_state);
}
/* Save the implicit return value, add a reference if requested */
walk_state->implicit_return_obj = return_desc;
if (add_reference) {
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
return (TRUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_is_result_used
@@ -179,20 +166,18 @@ acpi_ds_do_implicit_return (
******************************************************************************/
u8
-acpi_ds_is_result_used (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_is_result_used(union acpi_parse_object * op,
+ struct acpi_walk_state * walk_state)
{
- const struct acpi_opcode_info *parent_info;
-
- ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
+ const struct acpi_opcode_info *parent_info;
+ ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op);
/* Must have both an Op and a Result Object */
if (!op) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
- return_VALUE (TRUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
+ return_VALUE(TRUE);
}
/*
@@ -204,7 +189,8 @@ acpi_ds_is_result_used (
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
- (void) acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+ (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
+ TRUE);
/*
* Now determine if the parent will use the result
@@ -215,22 +201,24 @@ acpi_ds_is_result_used (
* via execute_control_method has a scope_op as the parent.
*/
if ((!op->common.parent) ||
- (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
+ (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
/* No parent, the return value cannot possibly be used */
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "At Method level, result of [%s] not used\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode)));
- return_VALUE (FALSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "At Method level, result of [%s] not used\n",
+ acpi_ps_get_opcode_name(op->common.
+ aml_opcode)));
+ return_VALUE(FALSE);
}
/* Get info on the parent. The root_op is AML_SCOPE */
- parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
+ parent_info =
+ acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
if (parent_info->class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown parent opcode. Op=%p\n", op));
- return_VALUE (FALSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown parent opcode. Op=%p\n", op));
+ return_VALUE(FALSE);
}
/*
@@ -256,8 +244,10 @@ acpi_ds_is_result_used (
* If we are executing the predicate AND this is the predicate op,
* we will use the return value
*/
- if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
- (walk_state->control_state->control.predicate_op == op)) {
+ if ((walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING)
+ && (walk_state->control_state->control.
+ predicate_op == op)) {
goto result_used;
}
break;
@@ -271,7 +261,6 @@ acpi_ds_is_result_used (
goto result_not_used;
-
case AML_CLASS_CREATE:
/*
@@ -280,15 +269,16 @@ acpi_ds_is_result_used (
*/
goto result_used;
-
case AML_CLASS_NAMED_OBJECT:
- if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
+ if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
+ (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
+ || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_INT_EVAL_SUBTREE_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
@@ -298,7 +288,6 @@ acpi_ds_is_result_used (
goto result_not_used;
-
default:
/*
@@ -308,26 +297,25 @@ acpi_ds_is_result_used (
goto result_used;
}
+ result_used:
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result of [%s] used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ acpi_ps_get_opcode_name(op->common.parent->common.
+ aml_opcode), op));
-result_used:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] used by Parent [%s] Op=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
-
- return_VALUE (TRUE);
-
+ return_VALUE(TRUE);
-result_not_used:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] not used by Parent [%s] Op=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
+ result_not_used:
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result of [%s] not used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ acpi_ps_get_opcode_name(op->common.parent->common.
+ aml_opcode), op));
- return_VALUE (FALSE);
+ return_VALUE(FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_result_if_not_used
@@ -346,20 +334,17 @@ result_not_used:
******************************************************************************/
void
-acpi_ds_delete_result_if_not_used (
- union acpi_parse_object *op,
- union acpi_operand_object *result_obj,
- struct acpi_walk_state *walk_state)
+acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
+ union acpi_operand_object *result_obj,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
if (!op) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
return_VOID;
}
@@ -367,19 +352,18 @@ acpi_ds_delete_result_if_not_used (
return_VOID;
}
- if (!acpi_ds_is_result_used (op, walk_state)) {
+ 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);
- if (ACPI_SUCCESS (status)) {
- acpi_ut_remove_reference (result_obj);
+ status = acpi_ds_result_pop(&obj_desc, walk_state);
+ if (ACPI_SUCCESS(status)) {
+ acpi_ut_remove_reference(result_obj);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_resolve_operands
@@ -394,16 +378,12 @@ acpi_ds_delete_result_if_not_used (
*
******************************************************************************/
-acpi_status
-acpi_ds_resolve_operands (
- struct acpi_walk_state *walk_state)
+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);
+ u32 i;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state);
/*
* Attempt to resolve each of the valid operands
@@ -411,16 +391,17 @@ acpi_ds_resolve_operands (
* that the actual objects are passed, not copies of the objects.
*/
for (i = 0; i < walk_state->num_operands; i++) {
- status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[i],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_clear_operands
@@ -433,15 +414,11 @@ acpi_ds_resolve_operands (
*
******************************************************************************/
-void
-acpi_ds_clear_operands (
- struct acpi_walk_state *walk_state)
+void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
+ u32 i;
+ ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state);
/* Remove a reference on each operand on the stack */
@@ -450,7 +427,7 @@ acpi_ds_clear_operands (
* Remove a reference to all operands, including both
* "Arguments" and "Targets".
*/
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
@@ -459,7 +436,6 @@ acpi_ds_clear_operands (
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operand
@@ -478,37 +454,36 @@ acpi_ds_clear_operands (
******************************************************************************/
acpi_status
-acpi_ds_create_operand (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg,
- u32 arg_index)
+acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg, u32 arg_index)
{
- acpi_status status = AE_OK;
- char *name_string;
- u32 name_length;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *parent_op;
- u16 opcode;
- acpi_interpreter_mode interpreter_mode;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
+ acpi_status status = AE_OK;
+ char *name_string;
+ u32 name_length;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *parent_op;
+ u16 opcode;
+ acpi_interpreter_mode interpreter_mode;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg);
/* A valid name must be looked up in the namespace */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
- (arg->common.value.string)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
+ (arg->common.value.string)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
+ arg));
/* Get the entire name string from the AML stream */
- status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
- &name_string, &name_length);
+ status =
+ acpi_ex_get_name_string(ACPI_TYPE_ANY,
+ arg->common.value.buffer,
+ &name_string, &name_length);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* All prefixes have been handled, and the name is in name_string */
@@ -523,13 +498,14 @@ acpi_ds_create_operand (
* actual opcode exists.
*/
if ((walk_state->deferred_node) &&
- (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
- (arg_index != 0)) {
- obj_desc = ACPI_CAST_PTR (
- union acpi_operand_object, walk_state->deferred_node);
+ (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
+ && (arg_index != 0)) {
+ obj_desc =
+ ACPI_CAST_PTR(union acpi_operand_object,
+ walk_state->deferred_node);
status = AE_OK;
- }
- else /* All other opcodes */ {
+ } else { /* All other opcodes */
+
/*
* Differentiate between a namespace "create" operation
* versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
@@ -537,43 +513,51 @@ acpi_ds_create_operand (
* namespace objects during the execution of control methods.
*/
parent_op = arg->common.parent;
- op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
- if ((op_info->flags & AML_NSNODE) &&
- (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
- (parent_op->common.aml_opcode != AML_REGION_OP) &&
- (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
+ op_info =
+ acpi_ps_get_opcode_info(parent_op->common.
+ aml_opcode);
+ if ((op_info->flags & AML_NSNODE)
+ && (parent_op->common.aml_opcode !=
+ AML_INT_METHODCALL_OP)
+ && (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;
- }
- else {
+ } else {
/* Return a failure if name not found */
interpreter_mode = ACPI_IMODE_EXECUTE;
}
- status = acpi_ns_lookup (walk_state->scope_info, name_string,
- ACPI_TYPE_ANY, interpreter_mode,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- walk_state,
- ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
+ status =
+ acpi_ns_lookup(walk_state->scope_info, name_string,
+ ACPI_TYPE_ANY, interpreter_mode,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, walk_state,
+ ACPI_CAST_INDIRECT_PTR(struct
+ acpi_namespace_node,
+ &obj_desc));
/*
* The only case where we pass through (ignore) a NOT_FOUND
* error is for the cond_ref_of opcode.
*/
if (status == AE_NOT_FOUND) {
- if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
+ if (parent_op->common.aml_opcode ==
+ AML_COND_REF_OF_OP) {
/*
* For the Conditional Reference op, it's OK if
* the name is not found; We just need a way to
* indicate this to the interpreter, set the
* object to the root
*/
- obj_desc = ACPI_CAST_PTR (
- union acpi_operand_object, acpi_gbl_root_node);
+ obj_desc =
+ ACPI_CAST_PTR(union
+ acpi_operand_object,
+ acpi_gbl_root_node);
status = AE_OK;
- }
- else {
+ } else {
/*
* We just plain didn't find it -- which is a
* very serious error at this point
@@ -582,30 +566,30 @@ acpi_ds_create_operand (
}
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (name_string, status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(name_string, status);
}
}
/* Free the namestring created above */
- ACPI_MEM_FREE (name_string);
+ ACPI_MEM_FREE(name_string);
/* Check status from the lookup */
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Put the resulting object onto the current object stack */
- status = acpi_ds_obj_stack_push (obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_push(obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
- }
- else {
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (obj_desc, walk_state));
+ } else {
/* Check for null name case */
if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -615,77 +599,83 @@ acpi_ds_create_operand (
* in the original ASL. Create a Zero Constant for a
* placeholder. (Store to a constant is a Noop.)
*/
- opcode = AML_ZERO_OP; /* Has no arguments! */
+ opcode = AML_ZERO_OP; /* Has no arguments! */
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Null namepath: Arg=%p\n", arg));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Null namepath: Arg=%p\n", arg));
+ } else {
opcode = arg->common.aml_opcode;
}
/* Get the object type of the argument */
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->object_type == ACPI_TYPE_INVALID) {
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
if (op_info->flags & AML_HAS_RETVAL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Argument previously created, already stacked \n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Argument previously created, already stacked \n"));
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
- walk_state->operands [walk_state->num_operands - 1], walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (walk_state->
+ operands[walk_state->num_operands -
+ 1], walk_state));
/*
* Use value that was already previously returned
* by the evaluation of this argument
*/
- status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_result_pop_from_bottom(&obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
/*
* Only error is underflow, and this indicates
* a missing or null operand!
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Missing or null operand, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Missing or null operand, %s\n",
+ acpi_format_exception
+ (status)));
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/* Create an ACPI_INTERNAL_OBJECT for the argument */
- obj_desc = acpi_ut_create_internal_object (op_info->object_type);
+ obj_desc =
+ acpi_ut_create_internal_object(op_info->
+ object_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new object */
- status = acpi_ds_init_object_from_op (
- walk_state, arg, opcode, &obj_desc);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_init_object_from_op(walk_state, arg, opcode,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
}
}
/* Put the operand object on the object stack */
- status = acpi_ds_obj_stack_push (obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_push(obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (obj_desc, walk_state));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operands
@@ -702,29 +692,27 @@ acpi_ds_create_operand (
******************************************************************************/
acpi_status
-acpi_ds_create_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *first_arg)
+acpi_ds_create_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *first_arg)
{
- acpi_status status = AE_OK;
- union acpi_parse_object *arg;
- u32 arg_count = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
+ acpi_status status = AE_OK;
+ union acpi_parse_object *arg;
+ u32 arg_count = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg);
/* For all arguments in the list... */
arg = first_arg;
while (arg) {
- status = acpi_ds_create_operand (walk_state, arg, arg_count);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operand(walk_state, arg, arg_count);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
- arg_count, arg, first_arg));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Arg #%d (%p) done, Arg1=%p\n", arg_count,
+ arg, first_arg));
/* Move on to next argument, if any */
@@ -732,20 +720,17 @@ acpi_ds_create_operands (
arg_count++;
}
- return_ACPI_STATUS (status);
-
+ return_ACPI_STATUS(status);
-cleanup:
+ cleanup:
/*
* We must undo everything done above; meaning that we must
* pop everything off of the operand stack and delete those
* objects
*/
- (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
+ (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
- (arg_count + 1), acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
+ (arg_count + 1), acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index 10f71318e23b..e522763bb692 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -52,27 +51,26 @@
#include <acpi/acdebug.h>
#include <acpi/acdisasm.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswexec")
+ACPI_MODULE_NAME("dswexec")
/*
* Dispatch table for opcode classes
*/
-static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
- acpi_ex_opcode_0A_0T_1R,
- acpi_ex_opcode_1A_0T_0R,
- acpi_ex_opcode_1A_0T_1R,
- acpi_ex_opcode_1A_1T_0R,
- acpi_ex_opcode_1A_1T_1R,
- acpi_ex_opcode_2A_0T_0R,
- acpi_ex_opcode_2A_0T_1R,
- acpi_ex_opcode_2A_1T_1R,
- acpi_ex_opcode_2A_2T_1R,
- acpi_ex_opcode_3A_0T_0R,
- acpi_ex_opcode_3A_1T_1R,
- acpi_ex_opcode_6A_0T_1R};
-
+static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = {
+ acpi_ex_opcode_0A_0T_1R,
+ acpi_ex_opcode_1A_0T_0R,
+ acpi_ex_opcode_1A_0T_1R,
+ acpi_ex_opcode_1A_1T_0R,
+ acpi_ex_opcode_1A_1T_1R,
+ acpi_ex_opcode_2A_0T_0R,
+ acpi_ex_opcode_2A_0T_1R,
+ acpi_ex_opcode_2A_1T_1R,
+ acpi_ex_opcode_2A_2T_1R,
+ acpi_ex_opcode_3A_0T_0R,
+ acpi_ex_opcode_3A_1T_1R,
+ acpi_ex_opcode_6A_0T_1R
+};
/*****************************************************************************
*
@@ -88,64 +86,64 @@ static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
****************************************************************************/
acpi_status
-acpi_ds_get_predicate_value (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *result_obj) {
- acpi_status status = AE_OK;
- 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_ds_get_predicate_value(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *result_obj)
+{
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state);
walk_state->control_state->common.state = 0;
if (result_obj) {
- status = acpi_ds_result_pop (&obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not get result from predicate evaluation, %s\n",
- acpi_format_exception (status)));
+ status = acpi_ds_result_pop(&obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not get result from predicate evaluation, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- }
- else {
- status = acpi_ds_create_operand (walk_state, walk_state->op, 0);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ } else {
+ status = acpi_ds_create_operand(walk_state, walk_state->op, 0);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = walk_state->operands [0];
+ obj_desc = walk_state->operands[0];
}
if (!obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No predicate obj_desc=%p State=%p\n",
- obj_desc, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No predicate obj_desc=%p State=%p\n",
+ obj_desc, walk_state));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
* Result of predicate evaluation must be an Integer
* object. Implicitly convert the argument if necessary.
*/
- status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
- obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
+ if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
+ obj_desc, walk_state,
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -153,7 +151,7 @@ acpi_ds_get_predicate_value (
/* Truncate the predicate to 32-bits if necessary */
- acpi_ex_truncate_for32bit_table (local_obj_desc);
+ acpi_ex_truncate_for32bit_table(local_obj_desc);
/*
* Save the result of the predicate evaluation on
@@ -161,8 +159,7 @@ acpi_ds_get_predicate_value (
*/
if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
- }
- else {
+ } else {
/*
* Predicate is FALSE, we will just toss the
* rest of the package
@@ -171,30 +168,30 @@ acpi_ds_get_predicate_value (
status = AE_CTRL_FALSE;
}
+ cleanup:
-cleanup:
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
+ walk_state->control_state->common.value,
+ walk_state->op));
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
- walk_state->control_state->common.value, walk_state->op));
+ /* Break to debugger to display result */
- /* Break to debugger to display result */
-
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
+ (local_obj_desc, walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
if (local_obj_desc != obj_desc) {
- acpi_ut_remove_reference (local_obj_desc);
+ acpi_ut_remove_reference(local_obj_desc);
}
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_op
@@ -211,38 +208,39 @@ cleanup:
****************************************************************************/
acpi_status
-acpi_ds_exec_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- u32 opcode_class;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_exec_begin_op", walk_state);
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 opcode_class;
+ ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state);
op = walk_state->op;
if (!op) {
- status = acpi_ds_load2_begin_op (walk_state, out_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_load2_begin_op(walk_state, out_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
op = *out_op;
walk_state->op = op;
walk_state->opcode = op->common.aml_opcode;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
-
- if (acpi_ns_opens_scope (walk_state->op_info->object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "(%s) Popping scope for Op %p\n",
- acpi_ut_get_type_name (walk_state->op_info->object_type), op));
-
- status = acpi_ds_scope_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+
+ if (acpi_ns_opens_scope(walk_state->op_info->object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name(walk_state->
+ op_info->
+ object_type),
+ op));
+
+ status = acpi_ds_scope_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
@@ -252,7 +250,7 @@ acpi_ds_exec_begin_op (
*out_op = op;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -261,19 +259,20 @@ acpi_ds_exec_begin_op (
* Save this knowledge in the current scope descriptor
*/
if ((walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n",
- op, walk_state));
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Exec predicate Op=%p State=%p\n", op,
+ walk_state));
- walk_state->control_state->common.state = ACPI_CONTROL_PREDICATE_EXECUTING;
+ walk_state->control_state->common.state =
+ ACPI_CONTROL_PREDICATE_EXECUTING;
/* Save start of predicate */
walk_state->control_state->control.predicate_op = op;
}
-
opcode_class = walk_state->op_info->class;
/* We want to send namepaths to the load code */
@@ -288,15 +287,14 @@ acpi_ds_exec_begin_op (
switch (opcode_class) {
case AML_CLASS_CONTROL:
- status = acpi_ds_result_stack_push (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_result_stack_push(walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ds_exec_begin_control_op (walk_state, op);
+ status = acpi_ds_exec_begin_control_op(walk_state, op);
break;
-
case AML_CLASS_NAMED_OBJECT:
if (walk_state->walk_type == ACPI_WALK_METHOD) {
@@ -306,15 +304,14 @@ acpi_ds_exec_begin_op (
* object is temporary and will be deleted upon completion of
* the execution of this method.
*/
- status = acpi_ds_load2_begin_op (walk_state, NULL);
+ status = acpi_ds_load2_begin_op(walk_state, NULL);
}
if (op->common.aml_opcode == AML_REGION_OP) {
- status = acpi_ds_result_stack_push (walk_state);
+ status = acpi_ds_result_stack_push(walk_state);
}
break;
-
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
@@ -322,20 +319,18 @@ acpi_ds_exec_begin_op (
* Most operators with arguments.
* Start a new result/operand state
*/
- status = acpi_ds_result_stack_push (walk_state);
+ status = acpi_ds_result_stack_push(walk_state);
break;
-
default:
break;
}
/* Nothing to do here during method execution */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_end_op
@@ -350,28 +345,25 @@ acpi_ds_exec_begin_op (
*
****************************************************************************/
-acpi_status
-acpi_ds_exec_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- u32 op_type;
- u32 op_class;
- union acpi_parse_object *next_op;
- union acpi_parse_object *first_arg;
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 op_type;
+ u32 op_class;
+ 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 = walk_state->op;
op_type = walk_state->op_info->type;
op_class = walk_state->op_info->class;
if (op_class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown opcode %X\n",
+ op->common.aml_opcode));
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
first_arg = op->common.value.arg;
@@ -384,29 +376,31 @@ acpi_ds_exec_end_op (
/* Call debugger for single step support (DEBUG build only) */
- ACPI_DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class));
- ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);});
+ ACPI_DEBUGGER_EXEC(status =
+ acpi_db_single_step(walk_state, op, op_class));
+ ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);}
+ ) ;
/* Decode the Opcode Class */
switch (op_class) {
- case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
+ case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
break;
-
- case AML_CLASS_EXECUTE: /* most operators with arguments */
+ case AML_CLASS_EXECUTE: /* most operators with arguments */
/* Build resolved operand stack */
- status = acpi_ds_create_operands (walk_state, first_arg);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, first_arg);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Done with this result state (Now that operand stack is built) */
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -417,86 +411,93 @@ acpi_ds_exec_end_op (
if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
/* Resolve all operands */
- status = acpi_ex_resolve_operands (walk_state->opcode,
- &(walk_state->operands [walk_state->num_operands -1]),
- walk_state);
- if (ACPI_SUCCESS (status)) {
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (walk_state->opcode),
- walk_state->num_operands, "after ex_resolve_operands");
+ status = acpi_ex_resolve_operands(walk_state->opcode,
+ &(walk_state->
+ operands
+ [walk_state->
+ num_operands - 1]),
+ walk_state);
+ if (ACPI_SUCCESS(status)) {
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
+ ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name
+ (walk_state->opcode),
+ walk_state->num_operands,
+ "after ex_resolve_operands");
}
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Dispatch the request to the appropriate interpreter handler
* routine. There is one routine per opcode "type" based upon the
* number of opcode arguments and return type.
*/
- status = acpi_gbl_op_type_dispatch[op_type] (walk_state);
- }
- else {
+ status =
+ acpi_gbl_op_type_dispatch[op_type] (walk_state);
+ } else {
/*
* Treat constructs of the form "Store(local_x,local_x)" as noops when the
* Local is uninitialized.
*/
- if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
- (walk_state->opcode == AML_STORE_OP) &&
- (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (walk_state->operands[0]->reference.opcode ==
- walk_state->operands[1]->reference.opcode) &&
- (walk_state->operands[0]->reference.offset ==
- walk_state->operands[1]->reference.offset)) {
+ if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
+ (walk_state->opcode == AML_STORE_OP) &&
+ (walk_state->operands[0]->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (walk_state->operands[1]->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (walk_state->operands[0]->reference.opcode ==
+ walk_state->operands[1]->reference.opcode)
+ && (walk_state->operands[0]->reference.offset ==
+ walk_state->operands[1]->reference.offset)) {
status = AE_OK;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "[%s]: Could not resolve operands, %s\n",
- acpi_ps_get_opcode_name (walk_state->opcode),
- acpi_format_exception (status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "[%s]: Could not resolve operands, %s\n",
+ acpi_ps_get_opcode_name
+ (walk_state->opcode),
+ acpi_format_exception
+ (status)));
}
}
/* Always delete the argument objects and clear the operand stack */
- acpi_ds_clear_operands (walk_state);
+ acpi_ds_clear_operands(walk_state);
/*
* If a result object was returned from above, push it on the
* current result stack
*/
- if (ACPI_SUCCESS (status) &&
- walk_state->result_obj) {
- status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ if (ACPI_SUCCESS(status) && walk_state->result_obj) {
+ status =
+ acpi_ds_result_push(walk_state->result_obj,
+ walk_state);
}
break;
-
default:
switch (op_type) {
- case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
+ case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
/* 1 Operand, 0 external_result, 0 internal_result */
- status = acpi_ds_exec_end_control_op (walk_state, op);
+ status = acpi_ds_exec_end_control_op(walk_state, op);
/* Make sure to properly pop the result stack */
- if (ACPI_SUCCESS (status)) {
- status = acpi_ds_result_stack_pop (walk_state);
- }
- else if (status == AE_CTRL_PENDING) {
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ } else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_SUCCESS(status)) {
status = AE_CTRL_PENDING;
}
}
break;
-
case AML_TYPE_METHOD_CALL:
/*
@@ -505,16 +506,22 @@ acpi_ds_exec_end_op (
* a reference to it.
*/
if ((op->asl.parent) &&
- ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
- (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Method Reference in a Package, Op=%p\n", op));
- op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
- acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
- return_ACPI_STATUS (AE_OK);
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
+ || (op->asl.parent->asl.aml_opcode ==
+ AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Method Reference in a Package, Op=%p\n",
+ op));
+ op->common.node =
+ (struct acpi_namespace_node *)op->asl.value.
+ arg->asl.node->object;
+ acpi_ut_add_reference(op->asl.value.arg->asl.
+ node->object);
+ return_ACPI_STATUS(AE_OK);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Method invocation, Op=%p\n", op));
/*
* (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
@@ -531,8 +538,8 @@ acpi_ds_exec_end_op (
/*
* Get the method's arguments and put them on the operand stack
*/
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -541,11 +548,11 @@ acpi_ds_exec_end_op (
* we must resolve all local references here (Local variables,
* arguments to *this* method, etc.)
*/
- status = acpi_ds_resolve_operands (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_resolve_operands(walk_state);
+ if (ACPI_FAILURE(status)) {
/* On error, clear all resolved operands */
- acpi_ds_clear_operands (walk_state);
+ acpi_ds_clear_operands(walk_state);
break;
}
@@ -559,27 +566,28 @@ acpi_ds_exec_end_op (
* Return now; we don't want to disturb anything,
* especially the operand count!
*/
- return_ACPI_STATUS (status);
-
+ return_ACPI_STATUS(status);
case AML_TYPE_CREATE_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing create_field Buffer/Index Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing create_field Buffer/Index Op=%p\n",
+ op));
- status = acpi_ds_load2_end_op (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_load2_end_op(walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
- status = acpi_ds_eval_buffer_field_operands (walk_state, op);
+ status =
+ acpi_ds_eval_buffer_field_operands(walk_state, op);
break;
-
case AML_TYPE_CREATE_OBJECT:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing create_object (Buffer/Package) Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing create_object (Buffer/Package) Op=%p\n",
+ op));
switch (op->common.parent->common.aml_opcode) {
case AML_NAME_OP:
@@ -588,13 +596,15 @@ acpi_ds_exec_end_op (
* Put the Node on the object stack (Contains the ACPI Name
* of this object)
*/
- walk_state->operands[0] = (void *) op->common.parent->common.node;
+ walk_state->operands[0] =
+ (void *)op->common.parent->common.node;
walk_state->num_operands = 1;
- status = acpi_ds_create_node (walk_state,
- op->common.parent->common.node,
- op->common.parent);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_node(walk_state,
+ op->common.parent->
+ common.node,
+ op->common.parent);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -603,20 +613,26 @@ acpi_ds_exec_end_op (
case AML_INT_EVAL_SUBTREE_OP:
- status = acpi_ds_eval_data_object_operands (walk_state, op,
- acpi_ns_get_attached_object (op->common.parent->common.node));
+ status =
+ acpi_ds_eval_data_object_operands
+ (walk_state, op,
+ acpi_ns_get_attached_object(op->common.
+ parent->common.
+ node));
break;
default:
- status = acpi_ds_eval_data_object_operands (walk_state, op, NULL);
+ status =
+ acpi_ds_eval_data_object_operands
+ (walk_state, op, NULL);
break;
}
/* Done with result state (Now that operand stack is built) */
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -625,56 +641,58 @@ acpi_ds_exec_end_op (
* current result stack
*/
if (walk_state->result_obj) {
- status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ status =
+ acpi_ds_result_push(walk_state->result_obj,
+ walk_state);
}
break;
-
case AML_TYPE_NAMED_FIELD:
case AML_TYPE_NAMED_COMPLEX:
case AML_TYPE_NAMED_SIMPLE:
case AML_TYPE_NAMED_NO_OBJ:
- status = acpi_ds_load2_end_op (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_load2_end_op(walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
if (op->common.aml_opcode == AML_REGION_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing op_region Address/Length Op=%p\n", op));
-
- status = acpi_ds_eval_region_operands (walk_state, op);
- if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing op_region Address/Length Op=%p\n",
+ op));
+
+ status =
+ acpi_ds_eval_region_operands(walk_state,
+ op);
+ if (ACPI_FAILURE(status)) {
break;
}
- status = acpi_ds_result_stack_pop (walk_state);
+ status = acpi_ds_result_stack_pop(walk_state);
}
break;
-
case AML_TYPE_UNDEFINED:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Undefined opcode type Op=%p\n", op));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
-
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Undefined opcode type Op=%p\n", op));
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
case AML_TYPE_BOGUS:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Internal opcode=%X type Op=%p\n",
- walk_state->opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Internal opcode=%X type Op=%p\n",
+ walk_state->opcode, op));
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
- op_class, op_type, op->common.aml_opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
+ op_class, op_type,
+ op->common.aml_opcode, op));
status = AE_NOT_IMPLEMENTED;
break;
@@ -685,55 +703,58 @@ acpi_ds_exec_end_op (
* ACPI 2.0 support for 64-bit integers: Truncate numeric
* result value if we are executing from a 32-bit ACPI table
*/
- acpi_ex_truncate_for32bit_table (walk_state->result_obj);
+ acpi_ex_truncate_for32bit_table(walk_state->result_obj);
/*
* Check if we just completed the evaluation of a
* conditional predicate
*/
- if ((ACPI_SUCCESS (status)) &&
- (walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_PREDICATE_EXECUTING) &&
- (walk_state->control_state->control.predicate_op == op)) {
- status = acpi_ds_get_predicate_value (walk_state, walk_state->result_obj);
+ if ((ACPI_SUCCESS(status)) &&
+ (walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING) &&
+ (walk_state->control_state->control.predicate_op == op)) {
+ status =
+ acpi_ds_get_predicate_value(walk_state,
+ walk_state->result_obj);
walk_state->result_obj = NULL;
}
-
-cleanup:
+ cleanup:
/* Invoke exception handler on error */
- if (ACPI_FAILURE (status) &&
- acpi_gbl_exception_handler &&
- !(status & AE_CODE_CONTROL)) {
- acpi_ex_exit_interpreter ();
- status = acpi_gbl_exception_handler (status,
- walk_state->method_node->name.integer, walk_state->opcode,
- walk_state->aml_offset, NULL);
- (void) acpi_ex_enter_interpreter ();
+ if (ACPI_FAILURE(status) &&
+ acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
+ acpi_ex_exit_interpreter();
+ status = acpi_gbl_exception_handler(status,
+ walk_state->method_node->
+ name.integer,
+ walk_state->opcode,
+ walk_state->aml_offset,
+ NULL);
+ (void)acpi_ex_enter_interpreter();
}
if (walk_state->result_obj) {
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj,
- walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
+ (walk_state->result_obj, walk_state));
/*
* Delete the result op if and only if:
* Parent will not use the result -- such as any
* non-nested type2 op in a method (parent will be method)
*/
- acpi_ds_delete_result_if_not_used (op, walk_state->result_obj, walk_state);
+ acpi_ds_delete_result_if_not_used(op, walk_state->result_obj,
+ walk_state);
}
-
#ifdef _UNDER_DEVELOPMENT
if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
- acpi_db_method_end (walk_state);
+ acpi_db_method_end(walk_state);
}
#endif
@@ -745,12 +766,10 @@ cleanup:
/* On error, display method locals/args */
- if (ACPI_FAILURE (status)) {
- acpi_dm_dump_method_info (status, walk_state, op);
+ if (ACPI_FAILURE(status)) {
+ acpi_dm_dump_method_info(status, walk_state, op);
}
#endif
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index d11620018421..411731261c29 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -50,13 +49,12 @@
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
-#ifdef _ACPI_ASL_COMPILER
+#ifdef ACPI_ASL_COMPILER
#include <acpi/acdisasm.h>
#endif
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswload")
-
+ACPI_MODULE_NAME("dswload")
/*******************************************************************************
*
@@ -70,32 +68,29 @@
* DESCRIPTION: Init walk state callbacks
*
******************************************************************************/
-
acpi_status
-acpi_ds_init_callbacks (
- struct acpi_walk_state *walk_state,
- u32 pass_number)
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
{
switch (pass_number) {
case 1:
- walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load1_begin_op;
walk_state->ascending_callback = acpi_ds_load1_end_op;
break;
case 2:
- walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load2_begin_op;
walk_state->ascending_callback = acpi_ds_load2_end_op;
break;
case 3:
#ifndef ACPI_NO_METHOD_EXECUTION
- walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_exec_begin_op;
walk_state->ascending_callback = acpi_ds_exec_end_op;
#endif
@@ -108,7 +103,6 @@ acpi_ds_init_callbacks (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_begin_op
@@ -123,37 +117,26 @@ acpi_ds_init_callbacks (
******************************************************************************/
acpi_status
-acpi_ds_load1_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object ** out_op)
{
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_status status;
- acpi_object_type object_type;
- char *path;
- u32 flags;
-
-
- ACPI_FUNCTION_NAME ("ds_load1_begin_op");
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *path;
+ u32 flags;
+ ACPI_FUNCTION_NAME("ds_load1_begin_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
/* We are only interested in opcodes that have an associated name */
if (op) {
if (!(walk_state->op_info->flags & AML_NAMED)) {
-#if 0
- if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
- (walk_state->op_info->class == AML_CLASS_CONTROL)) {
- acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n",
- walk_state->op_info->name);
- *out_op = op;
- return (AE_CTRL_SKIP);
- }
-#endif
*out_op = op;
return (AE_OK);
}
@@ -166,14 +149,15 @@ acpi_ds_load1_begin_op (
}
}
- path = acpi_ps_get_next_namestring (&walk_state->parser_state);
+ path = acpi_ps_get_next_namestring(&walk_state->parser_state);
/* Map the raw opcode into an internal object type */
object_type = walk_state->op_info->object_type;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name (object_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "State=%p Op=%p [%s]\n", walk_state, op,
+ acpi_ut_get_type_name(object_type)));
switch (walk_state->opcode) {
case AML_SCOPE_OP:
@@ -183,23 +167,27 @@ acpi_ds_load1_begin_op (
* that we can actually open the scope to enter new names underneath it.
* Allow search-to-root for single namesegs.
*/
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
-#ifdef _ACPI_ASL_COMPILER
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &(node));
+#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
/*
* Table disassembly:
* Target of Scope() not found. Generate an External for it, and
* insert the name into the namespace.
*/
- acpi_dm_add_to_external_list (path);
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
+ acpi_dm_add_to_external_list(path);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path,
+ object_type, ACPI_IMODE_LOAD_PASS1,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &(node));
}
#endif
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (path, status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(path, status);
return (status);
}
@@ -208,7 +196,7 @@ acpi_ds_load1_begin_op (
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
- case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
@@ -232,9 +220,10 @@ acpi_ds_load1_begin_op (
* a warning
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
- path, acpi_ut_get_type_name (node->type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
+ path,
+ acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -244,15 +233,12 @@ acpi_ds_load1_begin_op (
/* All other types are an error */
- ACPI_REPORT_ERROR ((
- "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n",
- acpi_ut_get_type_name (node->type), path));
+ ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path));
return (AE_AML_OPERAND_TYPE);
}
break;
-
default:
/*
@@ -281,15 +267,15 @@ acpi_ds_load1_begin_op (
flags = ACPI_NS_NO_UPSEARCH;
if ((walk_state->opcode != AML_SCOPE_OP) &&
- (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
+ (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
flags |= ACPI_NS_ERROR_IF_FOUND;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
- acpi_ut_get_type_name (object_type)));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[%s] Both Find or Create allowed\n",
- acpi_ut_get_type_name (object_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[%s] Cannot already exist\n",
+ acpi_ut_get_type_name(object_type)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[%s] Both Find or Create allowed\n",
+ acpi_ut_get_type_name(object_type)));
}
/*
@@ -298,22 +284,23 @@ acpi_ds_load1_begin_op (
* involve arguments to the opcode must be created as we go back up the
* parse tree later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node));
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (path, status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path, object_type,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state,
+ &(node));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(path, status);
return (status);
}
break;
}
-
/* Common exit */
if (!op) {
/* Create a new op */
- op = acpi_ps_alloc_op (walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
if (!op) {
return (AE_NO_MEMORY);
}
@@ -327,19 +314,18 @@ acpi_ds_load1_begin_op (
op->named.path = (u8 *) path;
#endif
-
/*
* Put the Node in the "op" object that the parser uses, so we
* can get it again quickly when this scope is closed
*/
op->common.node = node;
- acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
+ acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
+ op);
*out_op = op;
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_end_op
@@ -353,20 +339,17 @@ acpi_ds_load1_begin_op (
*
******************************************************************************/
-acpi_status
-acpi_ds_load1_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
{
- union acpi_parse_object *op;
- acpi_object_type object_type;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_NAME ("ds_load1_end_op");
+ union acpi_parse_object *op;
+ acpi_object_type object_type;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_NAME("ds_load1_end_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
/* We are only interested in opcodes that have an associated name */
@@ -380,21 +363,20 @@ acpi_ds_load1_end_op (
#ifndef ACPI_NO_METHOD_EXECUTION
if (walk_state->op_info->flags & AML_FIELD) {
- if (walk_state->opcode == AML_FIELD_OP ||
- walk_state->opcode == AML_BANK_FIELD_OP ||
- walk_state->opcode == AML_INDEX_FIELD_OP) {
- status = acpi_ds_init_field_objects (op, walk_state);
+ if (walk_state->opcode == AML_FIELD_OP ||
+ walk_state->opcode == AML_BANK_FIELD_OP ||
+ walk_state->opcode == AML_INDEX_FIELD_OP) {
+ status = acpi_ds_init_field_objects(op, walk_state);
}
return (status);
}
-
if (op->common.aml_opcode == AML_REGION_OP) {
- status = acpi_ex_create_region (op->named.data, op->named.length,
- (acpi_adr_space_type)
- ((op->common.value.arg)->common.value.integer),
- walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_create_region(op->named.data, op->named.length,
+ (acpi_adr_space_type)
+ ((op->common.value.arg)->common.
+ value.integer), walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -404,8 +386,11 @@ acpi_ds_load1_end_op (
/* For Name opcode, get the object type from the argument */
if (op->common.value.arg) {
- object_type = (acpi_ps_get_opcode_info (
- (op->common.value.arg)->common.aml_opcode))->object_type;
+ object_type = (acpi_ps_get_opcode_info((op->common.
+ value.arg)->
+ common.
+ aml_opcode))->
+ object_type;
op->common.node->type = (u8) object_type;
}
}
@@ -419,23 +404,26 @@ acpi_ds_load1_end_op (
* of invocations of the method (need to know the number of
* arguments.)
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "LOADING-Method: State=%p Op=%p named_obj=%p\n",
- walk_state, op, op->named.node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, op->named.node));
- if (!acpi_ns_get_attached_object (op->named.node)) {
- walk_state->operands[0] = (void *) op->named.node;
+ if (!acpi_ns_get_attached_object(op->named.node)) {
+ walk_state->operands[0] = (void *)op->named.node;
walk_state->num_operands = 1;
- status = acpi_ds_create_operands (walk_state, op->common.value.arg);
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_create_method (op->named.data,
- op->named.length, walk_state);
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.arg);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ex_create_method(op->named.data,
+ op->named.length,
+ walk_state);
}
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -443,17 +431,17 @@ acpi_ds_load1_end_op (
/* Pop the scope stack */
- if (acpi_ns_opens_scope (object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
- acpi_ut_get_type_name (object_type), op));
+ if (acpi_ns_opens_scope(object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s): Popping scope for Op %p\n",
+ acpi_ut_get_type_name(object_type), op));
- status = acpi_ds_scope_stack_pop (walk_state);
+ status = acpi_ds_scope_stack_pop(walk_state);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_begin_op
@@ -468,30 +456,53 @@ acpi_ds_load1_end_op (
******************************************************************************/
acpi_status
-acpi_ds_load2_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object ** out_op)
{
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_status status;
- acpi_object_type object_type;
- char *buffer_ptr;
-
-
- ACPI_FUNCTION_TRACE ("ds_load2_begin_op");
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *buffer_ptr;
+ ACPI_FUNCTION_TRACE("ds_load2_begin_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
if (op) {
+ 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);
+ return_ACPI_STATUS(status);
+ }
+
/* We only care about Namespace opcodes here */
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
- (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
- (!(walk_state->op_info->flags & AML_NAMED))) {
- return_ACPI_STATUS (AE_OK);
+ (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
+ (!(walk_state->op_info->flags & AML_NAMED))) {
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
+ if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
+ (walk_state->op_info->class == AML_CLASS_CONTROL)) {
+
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Begin/EXEC: %s (fl %8.8X)\n",
+ walk_state->op_info->name,
+ walk_state->op_info->flags));
+
+ /* Executing a type1 or type2 opcode outside of a method */
+
+ status =
+ acpi_ds_exec_begin_op(walk_state, out_op);
+ return_ACPI_STATUS(status);
+ }
+#endif
+ return_ACPI_STATUS(AE_OK);
}
/* Get the name we are going to enter or lookup in the namespace */
@@ -503,28 +514,27 @@ acpi_ds_load2_begin_op (
if (!buffer_ptr) {
/* No name, just exit */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- }
- else {
+ } else {
/* Get name from the op */
- buffer_ptr = (char *) &op->named.name;
+ buffer_ptr = (char *)&op->named.name;
}
- }
- else {
+ } else {
/* Get the namestring from the raw AML */
- buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
+ buffer_ptr =
+ acpi_ps_get_next_namestring(&walk_state->parser_state);
}
/* Map the opcode into an internal object type */
object_type = walk_state->op_info->object_type;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "State=%p Op=%p Type=%X\n", walk_state, op, object_type));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "State=%p Op=%p Type=%X\n", walk_state, op,
+ object_type));
switch (walk_state->opcode) {
case AML_FIELD_OP:
@@ -542,9 +552,10 @@ acpi_ds_load2_begin_op (
* Don't enter the name into the namespace, but look it up
* for use later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &(node));
break;
case AML_SCOPE_OP:
@@ -554,28 +565,28 @@ acpi_ds_load2_begin_op (
* Don't enter the name into the namespace, but look it up
* for use later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
- if (ACPI_FAILURE (status)) {
-#ifdef _ACPI_ASL_COMPILER
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+ if (ACPI_FAILURE(status)) {
+#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
status = AE_OK;
- }
- else {
- ACPI_REPORT_NSERROR (buffer_ptr, status);
+ } else {
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
}
#else
- ACPI_REPORT_NSERROR (buffer_ptr, status);
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
#endif
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
* We must check to make sure that the target is
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
- case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
@@ -596,9 +607,7 @@ acpi_ds_load2_begin_op (
* Scope (DEB) { ... }
*/
- ACPI_REPORT_WARNING ((
- "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
- buffer_ptr, acpi_ut_get_type_name (node->type)));
+ ACPI_REPORT_WARNING(("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", buffer_ptr, acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -608,9 +617,7 @@ acpi_ds_load2_begin_op (
/* All other types are an error */
- ACPI_REPORT_ERROR ((
- "Invalid type (%s) for target of Scope operator [%4.4s]\n",
- acpi_ut_get_type_name (node->type), buffer_ptr));
+ ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s]\n", acpi_ut_get_type_name(node->type), buffer_ptr));
return (AE_AML_OPERAND_TYPE);
}
@@ -625,14 +632,16 @@ acpi_ds_load2_begin_op (
node = op->common.node;
- 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);
+ 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);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -651,24 +660,26 @@ acpi_ds_load2_begin_op (
break;
}
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH,
- walk_state, &(node));
+ /* Add new entry into namespace */
+
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_NO_UPSEARCH, walk_state, &(node));
break;
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (buffer_ptr, status);
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
+ return_ACPI_STATUS(status);
}
-
if (!op) {
/* Create a new op */
- op = acpi_ps_alloc_op (walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new op */
@@ -676,9 +687,7 @@ acpi_ds_load2_begin_op (
if (node) {
op->named.name = node->name.integer;
}
- if (out_op) {
- *out_op = op;
- }
+ *out_op = op;
}
/*
@@ -687,10 +696,9 @@ acpi_ds_load2_begin_op (
*/
op->common.node = node;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_end_op
@@ -704,39 +712,54 @@ acpi_ds_load2_begin_op (
*
******************************************************************************/
-acpi_status
-acpi_ds_load2_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- acpi_object_type object_type;
- struct acpi_namespace_node *node;
- union acpi_parse_object *arg;
- struct acpi_namespace_node *new_node;
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ acpi_object_type object_type;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *new_node;
#ifndef ACPI_NO_METHOD_EXECUTION
- u32 i;
+ 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",
- walk_state->op_info->name, op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
+ walk_state->op_info->name, op, walk_state));
- /* Only interested in opcodes that have namespace objects */
+ /* Check if opcode had an associated namespace object */
if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
- return_ACPI_STATUS (AE_OK);
+#ifndef ACPI_NO_METHOD_EXECUTION
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
+ /* No namespace object. Executable opcode? */
+
+ if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
+ (walk_state->op_info->class == AML_CLASS_CONTROL)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "End/EXEC: %s (fl %8.8X)\n",
+ walk_state->op_info->name,
+ walk_state->op_info->flags));
+
+ /* Executing a type1 or type2 opcode outside of a method */
+
+ status = acpi_ds_exec_end_op(walk_state);
+ return_ACPI_STATUS(status);
+ }
+#endif
+#endif
+ return_ACPI_STATUS(AE_OK);
}
if (op->common.aml_opcode == AML_SCOPE_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Ending scope Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Ending scope Op=%p State=%p\n", op,
+ walk_state));
}
-
object_type = walk_state->op_info->object_type;
/*
@@ -749,18 +772,19 @@ acpi_ds_load2_end_op (
* Put the Node on the object stack (Contains the ACPI Name of
* this object)
*/
- walk_state->operands[0] = (void *) node;
+ walk_state->operands[0] = (void *)node;
walk_state->num_operands = 1;
/* Pop the scope stack */
- if (acpi_ns_opens_scope (object_type) &&
- (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
- acpi_ut_get_type_name (object_type), op));
+ if (acpi_ns_opens_scope(object_type) &&
+ (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name(object_type), op));
- status = acpi_ds_scope_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_scope_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
@@ -793,9 +817,10 @@ acpi_ds_load2_end_op (
* AML_THERMALZONE
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ walk_state, op, node));
/* Decode the opcode */
@@ -810,27 +835,32 @@ acpi_ds_load2_end_op (
* Create the field object, but the field buffer and index must
* be evaluated later during the execution phase
*/
- status = acpi_ds_create_buffer_field (op, walk_state);
+ status = acpi_ds_create_buffer_field(op, walk_state);
break;
-
- case AML_TYPE_NAMED_FIELD:
+ case AML_TYPE_NAMED_FIELD:
switch (op->common.aml_opcode) {
case AML_INDEX_FIELD_OP:
- status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node,
- walk_state);
+ status =
+ acpi_ds_create_index_field(op,
+ (acpi_handle) arg->
+ common.node, walk_state);
break;
case AML_BANK_FIELD_OP:
- status = acpi_ds_create_bank_field (op, arg->common.node, walk_state);
+ status =
+ acpi_ds_create_bank_field(op, arg->common.node,
+ walk_state);
break;
case AML_FIELD_OP:
- status = acpi_ds_create_field (op, arg->common.node, walk_state);
+ status =
+ acpi_ds_create_field(op, arg->common.node,
+ walk_state);
break;
default:
@@ -839,43 +869,42 @@ acpi_ds_load2_end_op (
}
break;
+ case AML_TYPE_NAMED_SIMPLE:
- case AML_TYPE_NAMED_SIMPLE:
-
- status = acpi_ds_create_operands (walk_state, arg);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, arg);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
switch (op->common.aml_opcode) {
case AML_PROCESSOR_OP:
- status = acpi_ex_create_processor (walk_state);
+ status = acpi_ex_create_processor(walk_state);
break;
case AML_POWER_RES_OP:
- status = acpi_ex_create_power_resource (walk_state);
+ status = acpi_ex_create_power_resource(walk_state);
break;
case AML_MUTEX_OP:
- status = acpi_ex_create_mutex (walk_state);
+ status = acpi_ex_create_mutex(walk_state);
break;
case AML_EVENT_OP:
- status = acpi_ex_create_event (walk_state);
+ status = acpi_ex_create_event(walk_state);
break;
case AML_DATA_REGION_OP:
- status = acpi_ex_create_table_region (walk_state);
+ status = acpi_ex_create_table_region(walk_state);
break;
case AML_ALIAS_OP:
- status = acpi_ex_create_alias (walk_state);
+ status = acpi_ex_create_alias(walk_state);
break;
default:
@@ -888,12 +917,12 @@ acpi_ds_load2_end_op (
/* Delete operands */
for (i = 1; i < walk_state->num_operands; i++) {
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
break;
-#endif /* ACPI_NO_METHOD_EXECUTION */
+#endif /* ACPI_NO_METHOD_EXECUTION */
case AML_TYPE_NAMED_COMPLEX:
@@ -909,9 +938,10 @@ acpi_ds_load2_end_op (
* If we have a valid region, initialize it
* Namespace is NOT locked at this point.
*/
- status = acpi_ev_initialize_region (acpi_ns_get_attached_object (node),
- FALSE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_initialize_region
+ (acpi_ns_get_attached_object(node), FALSE);
+ if (ACPI_FAILURE(status)) {
/*
* If AE_NOT_EXIST is returned, it is not fatal
* because many regions get created before a handler
@@ -923,13 +953,11 @@ acpi_ds_load2_end_op (
}
break;
-
case AML_NAME_OP:
- status = acpi_ds_create_node (walk_state, node, op);
+ status = acpi_ds_create_node(walk_state, node, op);
break;
-#endif /* ACPI_NO_METHOD_EXECUTION */
-
+#endif /* ACPI_NO_METHOD_EXECUTION */
default:
/* All NAMED_COMPLEX opcodes must be handled above */
@@ -938,27 +966,29 @@ acpi_ds_load2_end_op (
}
break;
-
case AML_CLASS_INTERNAL:
/* case AML_INT_NAMEPATH_OP: */
break;
-
case AML_CLASS_METHOD_CALL:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
- walk_state, op, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, node));
/*
* Lookup the method name and save the Node
*/
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- walk_state, &(new_node));
- if (ACPI_SUCCESS (status)) {
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_SEARCH_PARENT |
+ 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
@@ -973,24 +1003,20 @@ acpi_ds_load2_end_op (
* parser uses, so we can get it again at the end of this scope
*/
op->common.node = new_node;
- }
- else {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ } else {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
}
break;
-
default:
break;
}
-cleanup:
+ cleanup:
/* Remove the Node pushed at the very beginning */
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index 21f4548ff323..defe956ef751 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswscope")
-
+ACPI_MODULE_NAME("dswscope")
/****************************************************************************
*
@@ -62,15 +59,11 @@
* root scope object (which remains at the stack top.)
*
***************************************************************************/
-
-void
-acpi_ds_scope_stack_clear (
- struct acpi_walk_state *walk_state)
+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");
+ union acpi_generic_state *scope_info;
+ ACPI_FUNCTION_NAME("ds_scope_stack_clear");
while (walk_state->scope_info) {
/* Pop a scope off the stack */
@@ -78,14 +71,14 @@ acpi_ds_scope_stack_clear (
scope_info = walk_state->scope_info;
walk_state->scope_info = scope_info->scope.next;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Popped object type (%s)\n",
- acpi_ut_get_type_name (scope_info->common.value)));
- acpi_ut_delete_generic_state (scope_info);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Popped object type (%s)\n",
+ acpi_ut_get_type_name(scope_info->common.
+ value)));
+ acpi_ut_delete_generic_state(scope_info);
}
}
-
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_push
@@ -102,74 +95,70 @@ acpi_ds_scope_stack_clear (
***************************************************************************/
acpi_status
-acpi_ds_scope_stack_push (
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_walk_state *walk_state)
+acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *scope_info;
- union acpi_generic_state *old_scope_info;
-
-
- ACPI_FUNCTION_TRACE ("ds_scope_stack_push");
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *old_scope_info;
+ ACPI_FUNCTION_TRACE("ds_scope_stack_push");
if (!node) {
/* Invalid scope */
- ACPI_REPORT_ERROR (("ds_scope_stack_push: null scope passed\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ds_scope_stack_push: null scope passed\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Make sure object type is valid */
- if (!acpi_ut_valid_object_type (type)) {
- ACPI_REPORT_WARNING ((
- "ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+ if (!acpi_ut_valid_object_type(type)) {
+ ACPI_REPORT_WARNING(("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
}
/* Allocate a new scope object */
- scope_info = acpi_ut_create_generic_state ();
+ scope_info = acpi_ut_create_generic_state();
if (!scope_info) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init new scope object */
scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
- scope_info->scope.node = node;
- scope_info->common.value = (u16) type;
+ scope_info->scope.node = node;
+ scope_info->common.value = (u16) type;
walk_state->scope_depth++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[%.2d] Pushed scope ", (u32) walk_state->scope_depth));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%.2d] Pushed scope ",
+ (u32) walk_state->scope_depth));
old_scope_info = walk_state->scope_info;
if (old_scope_info) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[%4.4s] (%s)",
- acpi_ut_get_node_name (old_scope_info->scope.node),
- acpi_ut_get_type_name (old_scope_info->common.value)));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[\\___] (%s)", "ROOT"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ "[%4.4s] (%s)",
+ acpi_ut_get_node_name(old_scope_info->
+ scope.node),
+ acpi_ut_get_type_name(old_scope_info->
+ common.value)));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT"));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- ", New scope -> [%4.4s] (%s)\n",
- acpi_ut_get_node_name (scope_info->scope.node),
- acpi_ut_get_type_name (scope_info->common.value)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ ", New scope -> [%4.4s] (%s)\n",
+ acpi_ut_get_node_name(scope_info->scope.node),
+ acpi_ut_get_type_name(scope_info->common.value)));
/* Push new scope object onto stack */
- acpi_ut_push_generic_state (&walk_state->scope_info, scope_info);
- return_ACPI_STATUS (AE_OK);
+ acpi_ut_push_generic_state(&walk_state->scope_info, scope_info);
+ return_ACPI_STATUS(AE_OK);
}
-
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_pop
@@ -182,47 +171,41 @@ acpi_ds_scope_stack_push (
*
***************************************************************************/
-acpi_status
-acpi_ds_scope_stack_pop (
- struct acpi_walk_state *walk_state)
+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");
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *new_scope_info;
+ ACPI_FUNCTION_TRACE("ds_scope_stack_pop");
/*
* Pop scope info object off the stack.
*/
- scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info);
+ scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info);
if (!scope_info) {
- return_ACPI_STATUS (AE_STACK_UNDERFLOW);
+ return_ACPI_STATUS(AE_STACK_UNDERFLOW);
}
walk_state->scope_depth--;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
- (u32) walk_state->scope_depth,
- acpi_ut_get_node_name (scope_info->scope.node),
- acpi_ut_get_type_name (scope_info->common.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
+ (u32) walk_state->scope_depth,
+ acpi_ut_get_node_name(scope_info->scope.node),
+ acpi_ut_get_type_name(scope_info->common.value)));
new_scope_info = walk_state->scope_info;
if (new_scope_info) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[%4.4s] (%s)\n",
- acpi_ut_get_node_name (new_scope_info->scope.node),
- acpi_ut_get_type_name (new_scope_info->common.value)));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[\\___] (ROOT)\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ "[%4.4s] (%s)\n",
+ acpi_ut_get_node_name(new_scope_info->
+ scope.node),
+ acpi_ut_get_type_name(new_scope_info->
+ common.value)));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n"));
}
- acpi_ut_delete_generic_state (scope_info);
- return_ACPI_STATUS (AE_OK);
+ acpi_ut_delete_generic_state(scope_info);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 9cd3db652b31..7d68a5aaf3c4 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -41,37 +41,28 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswstate")
+ACPI_MODULE_NAME("dswstate")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_status
-acpi_ds_result_insert (
- void *object,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_result_insert(void *object,
+ u32 index, struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ds_obj_stack_delete_all (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_obj_stack_pop_object (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state);
-
-void *
-acpi_ds_obj_stack_get_value (
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state);
+
+void *acpi_ds_obj_stack_get_value(u32 index,
+ struct acpi_walk_state *walk_state);
#endif
#ifdef ACPI_FUTURE_USAGE
@@ -92,36 +83,35 @@ acpi_ds_obj_stack_get_value (
******************************************************************************/
acpi_status
-acpi_ds_result_remove (
- union acpi_operand_object **object,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_remove(union acpi_operand_object **object,
+ u32 index, struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_remove");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_remove");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_MAX_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index out of range: %X State=%p Num=%X\n",
- index, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index out of range: %X State=%p Num=%X\n",
+ index, walk_state,
+ state->results.num_results));
}
/* Check for a valid result object */
- if (!state->results.obj_desc [index]) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X, Index=%X\n",
- walk_state, state->results.num_results, index));
+ if (!state->results.obj_desc[index]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X, Index=%X\n",
+ walk_state, state->results.num_results,
+ index));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -129,18 +119,20 @@ acpi_ds_result_remove (
state->results.num_results--;
- *object = state->results.obj_desc [index];
- state->results.obj_desc [index] = NULL;
+ *object = state->results.obj_desc[index];
+ state->results.obj_desc[index] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
- *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- index, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object,
+ (*object) ? acpi_ut_get_object_type_name(*object) :
+ "NULL", index, walk_state,
+ state->results.num_results));
return (AE_OK);
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -157,16 +149,13 @@ acpi_ds_result_remove (
******************************************************************************/
acpi_status
-acpi_ds_result_pop (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_pop(union acpi_operand_object ** object,
+ struct acpi_walk_state * walk_state)
{
- acpi_native_uint index;
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_pop");
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_pop");
state = walk_state->results;
if (!state) {
@@ -174,8 +163,9 @@ acpi_ds_result_pop (
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Result stack is empty! State=%p\n",
+ walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -186,26 +176,27 @@ acpi_ds_result_pop (
for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
/* Check for a valid result object */
- if (state->results.obj_desc [index -1]) {
- *object = state->results.obj_desc [index -1];
- state->results.obj_desc [index -1] = NULL;
+ if (state->results.obj_desc[index - 1]) {
+ *object = state->results.obj_desc[index - 1];
+ state->results.obj_desc[index - 1] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
- *object,
- (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- (u32) index -1, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object,
+ (*object) ?
+ acpi_ut_get_object_type_name(*object)
+ : "NULL", (u32) index - 1, walk_state,
+ state->results.num_results));
return (AE_OK);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No result objects! State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result objects! State=%p\n", walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_pop_from_bottom
@@ -221,38 +212,37 @@ acpi_ds_result_pop (
******************************************************************************/
acpi_status
-acpi_ds_result_pop_from_bottom (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
+ struct acpi_walk_state * walk_state)
{
- acpi_native_uint index;
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_pop_from_bottom");
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_pop_from_bottom");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Warning: No result object pushed! State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Warning: No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result objects! State=%p\n", walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
/* Remove Bottom element */
- *object = state->results.obj_desc [0];
+ *object = state->results.obj_desc[0];
/* Push entire stack down one element */
for (index = 0; index < state->results.num_results; index++) {
- state->results.obj_desc [index] = state->results.obj_desc [index + 1];
+ state->results.obj_desc[index] =
+ state->results.obj_desc[index + 1];
}
state->results.num_results--;
@@ -260,20 +250,21 @@ acpi_ds_result_pop_from_bottom (
/* Check for a valid result object */
if (!*object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X, Index=%X\n",
- walk_state, state->results.num_results, (u32) index));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X Index=%X\n",
+ walk_state, state->results.num_results,
+ (u32) index));
return (AE_AML_NO_RETURN_VALUE);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n",
- *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- state, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n",
+ *object,
+ (*object) ? acpi_ut_get_object_type_name(*object) :
+ "NULL", state, walk_state));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_push
@@ -288,47 +279,50 @@ acpi_ds_result_pop_from_bottom (
******************************************************************************/
acpi_status
-acpi_ds_result_push (
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_push(union acpi_operand_object * object,
+ struct acpi_walk_state * walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_push");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_push");
state = walk_state->results;
if (!state) {
- ACPI_REPORT_ERROR (("No result stack frame during push\n"));
+ ACPI_REPORT_ERROR(("No result stack frame during push\n"));
return (AE_AML_INTERNAL);
}
if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Result stack overflow: Obj=%p State=%p Num=%X\n",
- object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Result stack overflow: Obj=%p State=%p Num=%X\n",
+ object, walk_state,
+ state->results.num_results));
return (AE_STACK_OVERFLOW);
}
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null Object! Obj=%p State=%p Num=%X\n",
- object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null Object! Obj=%p State=%p Num=%X\n",
+ object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
- state->results.obj_desc [state->results.num_results] = object;
+ state->results.obj_desc[state->results.num_results] = object;
state->results.num_results++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
- object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
- walk_state, state->results.num_results, walk_state->current_result));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object,
+ object ?
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object) : "NULL",
+ walk_state, state->results.num_results,
+ walk_state->current_result));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_push
@@ -341,30 +335,26 @@ acpi_ds_result_push (
*
******************************************************************************/
-acpi_status
-acpi_ds_result_stack_push (
- struct acpi_walk_state *walk_state)
+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");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_stack_push");
- state = acpi_ut_create_generic_state ();
+ state = acpi_ut_create_generic_state();
if (!state) {
return (AE_NO_MEMORY);
}
state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
- acpi_ut_push_generic_state (&walk_state->results, state);
+ acpi_ut_push_generic_state(&walk_state->results, state);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
- state, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
+ state, walk_state));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_pop
@@ -377,35 +367,31 @@ acpi_ds_result_stack_push (
*
******************************************************************************/
-acpi_status
-acpi_ds_result_stack_pop (
- struct acpi_walk_state *walk_state)
+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");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_stack_pop");
/* Check for stack underflow */
if (walk_state->results == NULL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n",
+ walk_state));
return (AE_AML_NO_OPERAND);
}
- state = acpi_ut_pop_generic_state (&walk_state->results);
+ state = acpi_ut_pop_generic_state(&walk_state->results);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Result=%p remaining_results=%X State=%p\n",
- state, state->results.num_results, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Result=%p remaining_results=%X State=%p\n",
+ state, state->results.num_results, walk_state));
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_push
@@ -420,35 +406,35 @@ acpi_ds_result_stack_pop (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_push (
- void *object,
- struct acpi_walk_state *walk_state)
+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 */
if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "overflow! Obj=%p State=%p #Ops=%X\n",
- object, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "overflow! Obj=%p State=%p #Ops=%X\n",
+ object, walk_state,
+ walk_state->num_operands));
return (AE_STACK_OVERFLOW);
}
/* Put the object onto the stack */
- walk_state->operands [walk_state->num_operands] = object;
+ walk_state->operands[walk_state->num_operands] = object;
walk_state->num_operands++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
- object, acpi_ut_get_object_type_name ((union acpi_operand_object *) object),
- walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ object,
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object), walk_state,
+ walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop
@@ -464,38 +450,35 @@ acpi_ds_obj_stack_push (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop (
- u32 pop_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
{
- u32 i;
-
- ACPI_FUNCTION_NAME ("ds_obj_stack_pop");
+ u32 i;
+ ACPI_FUNCTION_NAME("ds_obj_stack_pop");
for (i = 0; i < pop_count; i++) {
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
/* Just set the stack entry to null */
walk_state->num_operands--;
- walk_state->operands [walk_state->num_operands] = NULL;
+ walk_state->operands[walk_state->num_operands] = NULL;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
pop_count, walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop_and_delete
@@ -511,44 +494,43 @@ acpi_ds_obj_stack_pop (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop_and_delete (
- u32 pop_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
+ struct acpi_walk_state * walk_state)
{
- u32 i;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete");
+ u32 i;
+ union acpi_operand_object *obj_desc;
+ 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) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
/* Pop the stack and delete an object if present in this stack entry */
walk_state->num_operands--;
- obj_desc = walk_state->operands [walk_state->num_operands];
+ obj_desc = walk_state->operands[walk_state->num_operands];
if (obj_desc) {
- acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]);
- walk_state->operands [walk_state->num_operands] = NULL;
+ acpi_ut_remove_reference(walk_state->
+ operands[walk_state->
+ num_operands]);
+ walk_state->operands[walk_state->num_operands] = NULL;
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
pop_count, walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_current_walk_state
@@ -562,25 +544,21 @@ acpi_ds_obj_stack_pop_and_delete (
*
******************************************************************************/
-struct acpi_walk_state *
-acpi_ds_get_current_walk_state (
- struct acpi_thread_state *thread)
-
+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",
- thread->walk_state_list));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n",
+ thread->walk_state_list));
return (thread->walk_state_list);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_push_walk_state
@@ -595,20 +573,17 @@ acpi_ds_get_current_walk_state (
******************************************************************************/
void
-acpi_ds_push_walk_state (
- struct acpi_walk_state *walk_state,
- struct acpi_thread_state *thread)
+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;
+ walk_state->next = thread->walk_state_list;
thread->walk_state_list = walk_state;
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_pop_walk_state
@@ -623,15 +598,11 @@ acpi_ds_push_walk_state (
*
******************************************************************************/
-struct acpi_walk_state *
-acpi_ds_pop_walk_state (
- struct acpi_thread_state *thread)
+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");
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ds_pop_walk_state");
walk_state = thread->walk_state_list;
@@ -647,10 +618,9 @@ acpi_ds_pop_walk_state (
*/
}
- return_PTR (walk_state);
+ return_PTR(walk_state);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_walk_state
@@ -667,57 +637,55 @@ acpi_ds_pop_walk_state (
*
******************************************************************************/
-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,
- struct acpi_thread_state *thread)
+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,
+ struct acpi_thread_state
+ *thread)
{
- struct acpi_walk_state *walk_state;
- acpi_status status;
-
+ 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_ut_acquire_from_cache (ACPI_MEM_LIST_WALK);
+ walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state));
if (!walk_state) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- walk_state->data_type = ACPI_DESC_TYPE_WALK;
- walk_state->owner_id = owner_id;
- walk_state->origin = origin;
- walk_state->method_desc = mth_desc;
- walk_state->thread = thread;
+ walk_state->data_type = ACPI_DESC_TYPE_WALK;
+ 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;
/* Init the method args/local */
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
- acpi_ds_method_data_init (walk_state);
+ acpi_ds_method_data_init(walk_state);
#endif
/* Create an initial result stack entry */
- status = acpi_ds_result_stack_push (walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
- return_PTR (NULL);
+ status = acpi_ds_result_stack_push(walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(walk_state);
+ return_PTR(NULL);
}
/* Put the new state at the head of the walk list */
if (thread) {
- acpi_ds_push_walk_state (walk_state, thread);
+ acpi_ds_push_walk_state(walk_state, thread);
}
- return_PTR (walk_state);
+ return_PTR(walk_state);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_aml_walk
@@ -737,70 +705,70 @@ acpi_ds_create_walk_state (
******************************************************************************/
acpi_status
-acpi_ds_init_aml_walk (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- struct acpi_namespace_node *method_node,
- u8 *aml_start,
- u32 aml_length,
- struct acpi_parameter_info *info,
- u32 pass_number)
+acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *method_node,
+ u8 * aml_start,
+ u32 aml_length,
+ struct acpi_parameter_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_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;
+ walk_state->parser_state.aml =
+ walk_state->parser_state.aml_start = aml_start;
walk_state->parser_state.aml_end =
- walk_state->parser_state.pkg_end = aml_start + aml_length;
+ walk_state->parser_state.pkg_end = aml_start + aml_length;
/* The next_op of the next_walk will be the beginning of the method */
walk_state->next_op = NULL;
+ walk_state->pass_number = pass_number;
if (info) {
if (info->parameter_type == ACPI_PARAM_GPE) {
- walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
- info->parameters);
- }
- else {
- walk_state->params = info->parameters;
+ walk_state->gpe_event_info =
+ ACPI_CAST_PTR(struct acpi_gpe_event_info,
+ info->parameters);
+ } else {
+ walk_state->params = info->parameters;
walk_state->caller_return_desc = &info->return_object;
}
}
- status = acpi_ps_init_scope (&walk_state->parser_state, op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ps_init_scope(&walk_state->parser_state, op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (method_node) {
walk_state->parser_state.start_node = method_node;
- walk_state->walk_type = ACPI_WALK_METHOD;
- walk_state->method_node = method_node;
- walk_state->method_desc = acpi_ns_get_attached_object (method_node);
+ walk_state->walk_type = ACPI_WALK_METHOD;
+ walk_state->method_node = method_node;
+ walk_state->method_desc =
+ acpi_ns_get_attached_object(method_node);
/* Push start scope on scope stack and make it current */
- status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Init the method arguments */
- status = acpi_ds_method_data_init_args (walk_state->params,
- ACPI_METHOD_NUM_ARGS, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_init_args(walk_state->params,
+ ACPI_METHOD_NUM_ARGS,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/*
* Setup the current scope.
* Find a Named Op that has a namespace node associated with it.
@@ -814,27 +782,27 @@ acpi_ds_init_aml_walk (
if (!extra_op) {
parser_state->start_node = NULL;
- }
- else {
+ } else {
parser_state->start_node = extra_op->common.node;
}
if (parser_state->start_node) {
/* Push start scope on scope stack and make it current */
- status = acpi_ds_scope_stack_push (parser_state->start_node,
- parser_state->start_node->type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_scope_stack_push(parser_state->start_node,
+ parser_state->start_node->
+ type, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
- status = acpi_ds_init_callbacks (walk_state, pass_number);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_callbacks(walk_state, pass_number);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_walk_state
@@ -847,29 +815,27 @@ acpi_ds_init_aml_walk (
*
******************************************************************************/
-void
-acpi_ds_delete_walk_state (
- struct acpi_walk_state *walk_state)
+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);
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state);
if (!walk_state) {
return;
}
if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p is not a valid walk state\n",
+ walk_state));
return;
}
if (walk_state->parser_state.scope) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p walk still has a scope list\n",
+ walk_state));
}
/* Always must free any linked control states */
@@ -878,7 +844,7 @@ acpi_ds_delete_walk_state (
state = walk_state->control_state;
walk_state->control_state = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
/* Always must free any linked parse states */
@@ -887,7 +853,7 @@ acpi_ds_delete_walk_state (
state = walk_state->scope_info;
walk_state->scope_info = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
/* Always must free any stacked result states */
@@ -896,40 +862,12 @@ acpi_ds_delete_walk_state (
state = walk_state->results;
walk_state->results = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
- acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/******************************************************************************
- *
- * FUNCTION: acpi_ds_delete_walk_state_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ds_delete_walk_state_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK);
+ ACPI_MEM_FREE(walk_state);
return_VOID;
}
-#endif
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
@@ -947,50 +885,53 @@ acpi_ds_delete_walk_state_cache (
******************************************************************************/
acpi_status
-acpi_ds_result_insert (
- void *object,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_insert(void *object,
+ u32 index, struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_insert");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_insert");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index out of range: %X Obj=%p State=%p Num=%X\n",
- index, object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index out of range: %X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
- index, object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
- state->results.obj_desc [index] = object;
+ state->results.obj_desc[index] = object;
state->results.num_results++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
- object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
- walk_state, state->results.num_results, walk_state->current_result));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object,
+ object ?
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object) : "NULL",
+ walk_state, state->results.num_results,
+ walk_state->current_result));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_delete_all
@@ -1004,29 +945,24 @@ acpi_ds_result_insert (
*
******************************************************************************/
-acpi_status
-acpi_ds_obj_stack_delete_all (
- struct acpi_walk_state *walk_state)
+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);
+ u32 i;
+ ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state);
/* The stack size is configurable, but fixed */
for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) {
if (walk_state->operands[i]) {
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop_object
@@ -1042,19 +978,17 @@ acpi_ds_obj_stack_delete_all (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop_object (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+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 */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Missing operand/stack empty! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Missing operand/stack empty! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
@@ -1065,27 +999,26 @@ acpi_ds_obj_stack_pop_object (
/* Check for a valid operand */
- if (!walk_state->operands [walk_state->num_operands]) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ if (!walk_state->operands[walk_state->num_operands]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
/* Get operand and set stack entry to null */
- *object = walk_state->operands [walk_state->num_operands];
- walk_state->operands [walk_state->num_operands] = NULL;
+ *object = walk_state->operands[walk_state->num_operands];
+ walk_state->operands[walk_state->num_operands] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
- *object, acpi_ut_get_object_type_name (*object),
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ *object, acpi_ut_get_object_type_name(*object),
walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_get_value
@@ -1101,30 +1034,25 @@ acpi_ds_obj_stack_pop_object (
*
******************************************************************************/
-void *
-acpi_ds_obj_stack_get_value (
- u32 index,
- struct acpi_walk_state *walk_state)
+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 */
if (walk_state->num_operands == 0) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* or if the index is past the top of the stack */
if (index > (walk_state->num_operands - (u32) 1)) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) -
- index]);
+ return_PTR(walk_state->
+ operands[(acpi_native_uint) (walk_state->num_operands - 1) -
+ index]);
}
#endif
-
-
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 1ac5731d45e5..7e1a445955bc 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -38,130 +38,112 @@
#include <acpi/actypes.h>
#define _COMPONENT ACPI_EC_COMPONENT
-ACPI_MODULE_NAME ("acpi_ec")
-
+ACPI_MODULE_NAME("acpi_ec")
#define ACPI_EC_COMPONENT 0x00100000
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_HID "PNP0C09"
#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
-
-
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
-
#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */
#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */
-
#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
-
-#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
-
+#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
+#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
#define ACPI_EC_COMMAND_READ 0x80
#define ACPI_EC_COMMAND_WRITE 0x81
#define ACPI_EC_BURST_ENABLE 0x82
#define ACPI_EC_BURST_DISABLE 0x83
#define ACPI_EC_COMMAND_QUERY 0x84
-
#define EC_POLLING 0xFF
#define EC_BURST 0x00
-
-
-static int acpi_ec_remove (struct acpi_device *device, int type);
-static int acpi_ec_start (struct acpi_device *device);
-static int acpi_ec_stop (struct acpi_device *device, int type);
-static int acpi_ec_burst_add ( struct acpi_device *device);
-static int acpi_ec_polling_add ( struct acpi_device *device);
+static int acpi_ec_remove(struct acpi_device *device, int type);
+static int acpi_ec_start(struct acpi_device *device);
+static int acpi_ec_stop(struct acpi_device *device, int type);
+static int acpi_ec_burst_add(struct acpi_device *device);
+static int acpi_ec_polling_add(struct acpi_device *device);
static struct acpi_driver acpi_ec_driver = {
- .name = ACPI_EC_DRIVER_NAME,
- .class = ACPI_EC_CLASS,
- .ids = ACPI_EC_HID,
- .ops = {
- .add = acpi_ec_polling_add,
- .remove = acpi_ec_remove,
- .start = acpi_ec_start,
- .stop = acpi_ec_stop,
- },
+ .name = ACPI_EC_DRIVER_NAME,
+ .class = ACPI_EC_CLASS,
+ .ids = ACPI_EC_HID,
+ .ops = {
+ .add = acpi_ec_polling_add,
+ .remove = acpi_ec_remove,
+ .start = acpi_ec_start,
+ .stop = acpi_ec_stop,
+ },
};
union acpi_ec {
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
} common;
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
- unsigned int expect_event;
- atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
- atomic_t pending_gpe;
- struct semaphore sem;
- wait_queue_head_t wait;
- }burst;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ unsigned int expect_event;
+ atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
+ atomic_t pending_gpe;
+ struct semaphore sem;
+ wait_queue_head_t wait;
+ } burst;
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
- spinlock_t lock;
- }polling;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ spinlock_t lock;
+ } polling;
};
-static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event);
+static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event);
static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data);
-static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data);
-static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data);
-static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data);
-static void acpi_ec_gpe_polling_query ( void *ec_cxt);
-static void acpi_ec_gpe_burst_query ( void *ec_cxt);
-static u32 acpi_ec_gpe_polling_handler ( void *data);
-static u32 acpi_ec_gpe_burst_handler ( void *data);
+static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data);
+static void acpi_ec_gpe_polling_query(void *ec_cxt);
+static void acpi_ec_gpe_burst_query(void *ec_cxt);
+static u32 acpi_ec_gpe_polling_handler(void *data);
+static u32 acpi_ec_gpe_burst_handler(void *data);
static acpi_status __init
-acpi_fake_ecdt_polling_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval);
+acpi_fake_ecdt_polling_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval);
static acpi_status __init
-acpi_fake_ecdt_burst_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval);
-
-static int __init
-acpi_ec_polling_get_real_ecdt(void);
-static int __init
-acpi_ec_burst_get_real_ecdt(void);
+acpi_fake_ecdt_burst_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval);
+
+static int __init acpi_ec_polling_get_real_ecdt(void);
+static int __init acpi_ec_burst_get_real_ecdt(void);
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
-static union acpi_ec *ec_ecdt;
+static union acpi_ec *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
@@ -173,30 +155,24 @@ static int acpi_ec_polling_mode = EC_POLLING;
static inline u32 acpi_ec_read_status(union acpi_ec *ec)
{
- u32 status = 0;
+ u32 status = 0;
acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
return status;
}
-static int
-acpi_ec_wait (
- union acpi_ec *ec,
- u8 event)
+static int acpi_ec_wait(union acpi_ec *ec, u8 event)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_wait (ec, event);
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_wait(ec, event);
else
- return acpi_ec_burst_wait (ec, event);
+ return acpi_ec_burst_wait(ec, event);
}
-static int
-acpi_ec_polling_wait (
- union acpi_ec *ec,
- u8 event)
+static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
{
- u32 acpi_ec_status = 0;
- u32 i = ACPI_EC_UDELAY_COUNT;
+ u32 acpi_ec_status = 0;
+ u32 i = ACPI_EC_UDELAY_COUNT;
if (!ec)
return -EINVAL;
@@ -205,19 +181,21 @@ acpi_ec_polling_wait (
switch (event) {
case ACPI_EC_EVENT_OBF:
do {
- acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ acpi_hw_low_level_read(8, &acpi_ec_status,
+ &ec->common.status_addr);
if (acpi_ec_status & ACPI_EC_FLAG_OBF)
return 0;
udelay(ACPI_EC_UDELAY);
- } while (--i>0);
+ } while (--i > 0);
break;
case ACPI_EC_EVENT_IBE:
do {
- acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ acpi_hw_low_level_read(8, &acpi_ec_status,
+ &ec->common.status_addr);
if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
return 0;
udelay(ACPI_EC_UDELAY);
- } while (--i>0);
+ } while (--i > 0);
break;
default:
return -EINVAL;
@@ -227,25 +205,36 @@ acpi_ec_polling_wait (
}
static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_wait");
ec->burst.expect_event = event;
smp_mb();
- result = wait_event_interruptible_timeout(ec->burst.wait,
- !ec->burst.expect_event,
- msecs_to_jiffies(ACPI_EC_DELAY));
-
- ec->burst.expect_event = 0;
- smp_mb();
+ switch (event) {
+ case ACPI_EC_EVENT_OBF:
+ if (acpi_ec_read_status(ec) & event) {
+ ec->burst.expect_event = 0;
+ return_VALUE(0);
+ }
+ break;
- if (result < 0){
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result));
- return_VALUE(result);
+ case ACPI_EC_EVENT_IBE:
+ if (~acpi_ec_read_status(ec) & event) {
+ ec->burst.expect_event = 0;
+ return_VALUE(0);
+ }
+ break;
}
+ result = wait_event_timeout(ec->burst.wait,
+ !ec->burst.expect_event,
+ msecs_to_jiffies(ACPI_EC_DELAY));
+
+ ec->burst.expect_event = 0;
+ smp_mb();
+
/*
* Verify that the event in question has actually happened by
* querying EC status. Do the check even if operation timed-out
@@ -266,95 +255,65 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
return_VALUE(-ETIME);
}
-
-
-static int
-acpi_ec_enter_burst_mode (
- union acpi_ec *ec)
+static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
{
- u32 tmp = 0;
- int status = 0;
+ u32 tmp = 0;
+ int status = 0;
ACPI_FUNCTION_TRACE("acpi_ec_enter_burst_mode");
status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- !(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
+ if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status)
+ goto end;
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ if (status)
return_VALUE(-EINVAL);
- }
acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if(tmp != 0x90 ) {/* Burst ACK byte*/
+ if (tmp != 0x90) { /* Burst ACK byte */
return_VALUE(-EINVAL);
}
}
- atomic_set(&ec->burst.leaving_burst , 0);
+ atomic_set(&ec->burst.leaving_burst, 0);
return_VALUE(0);
+ end:
+ printk("Error in acpi_ec_wait\n");
+ return_VALUE(-1);
}
-static int
-acpi_ec_leave_burst_mode (
- union acpi_ec *ec)
+static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
{
- int status =0;
ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
- atomic_set(&ec->burst.leaving_burst , 1);
- status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- (status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n"));
- return_VALUE(-EINVAL);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = acpi_ec_read_status(ec);
- }
-
+ atomic_set(&ec->burst.leaving_burst, 1);
return_VALUE(0);
}
-static int
-acpi_ec_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_read(ec, address, data);
else
return acpi_ec_burst_read(ec, address, data);
}
-static int
-acpi_ec_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_write(ec, address, data);
else
return acpi_ec_burst_write(ec, address, data);
}
-static int
-acpi_ec_polling_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
{
- acpi_status status = AE_OK;
- int result = 0;
- unsigned long flags = 0;
- u32 glk = 0;
+ acpi_status status = AE_OK;
+ int result = 0;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_read");
@@ -371,7 +330,8 @@ acpi_ec_polling_read (
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (result)
goto end;
@@ -384,9 +344,9 @@ acpi_ec_polling_read (
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
-
-end:
+ *data, address));
+
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -395,17 +355,12 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_ec_polling_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
{
- int result = 0;
- acpi_status status = AE_OK;
- unsigned long flags = 0;
- u32 glk = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_write");
@@ -420,7 +375,8 @@ acpi_ec_polling_write (
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (result)
goto end;
@@ -436,9 +392,9 @@ acpi_ec_polling_write (
goto end;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
+ data, address));
-end:
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -447,21 +403,16 @@ end:
return_VALUE(result);
}
-static int
-acpi_ec_burst_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
{
- int status = 0;
- u32 glk;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_read");
if (!ec || !data)
return_VALUE(-EINVAL);
-retry:
*data = 0;
if (ec->common.global_lock) {
@@ -473,64 +424,49 @@ retry:
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
- goto end;
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+ acpi_ec_enter_burst_mode(ec);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (status) {
+ printk("read EC, IB not empty\n");
goto end;
}
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
+ &ec->common.command_addr);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("read EC, IB not empty\n");
+ }
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+ if (status) {
+ printk("read EC, OB not full\n");
goto end;
}
-
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
-
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
-
-end:
+ *data, address));
+
+ end:
acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->burst.pending_gpe)){
- msleep(1);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto retry;
- }
-
return_VALUE(status);
}
-
-static int
-acpi_ec_burst_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
{
- int status = 0;
- u32 glk;
- u32 tmp;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_write");
if (!ec)
return_VALUE(-EINVAL);
-retry:
+
if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
@@ -540,69 +476,43 @@ retry:
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
- goto end;
+ acpi_ec_enter_burst_mode(ec);
- status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- !(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status)
- goto end;
- acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
- if(tmp != 0x90 ) /* Burst ACK byte*/
- goto end;
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("write EC, IB not empty\n");
}
- /*Now we are in burst mode*/
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if (status){
- goto end;
+ if (status) {
+ printk("write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto end;
+ if (status) {
+ printk("write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, data, &ec->common.data_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if (status)
- goto end;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
+ data, address));
-end:
acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->burst.pending_gpe)){
- msleep(1);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto retry;
- }
-
return_VALUE(status);
}
/*
* Externally callable EC access functions. For now, assume 1 EC only
*/
-int
-ec_read(u8 addr, u8 *val)
+int ec_read(u8 addr, u8 * val)
{
union acpi_ec *ec;
int err;
@@ -618,14 +528,13 @@ ec_read(u8 addr, u8 *val)
if (!err) {
*val = temp_data;
return 0;
- }
- else
+ } else
return err;
}
+
EXPORT_SYMBOL(ec_read);
-int
-ec_write(u8 addr, u8 val)
+int ec_write(u8 addr, u8 val)
{
union acpi_ec *ec;
int err;
@@ -639,27 +548,22 @@ ec_write(u8 addr, u8 val)
return err;
}
+
EXPORT_SYMBOL(ec_write);
-static int
-acpi_ec_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_query(union acpi_ec *ec, u32 * data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_query(ec, data);
else
return acpi_ec_burst_query(ec, data);
}
-static int
-acpi_ec_polling_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
{
- int result = 0;
- acpi_status status = AE_OK;
- unsigned long flags = 0;
- u32 glk = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_query");
@@ -681,7 +585,8 @@ acpi_ec_polling_query (
*/
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (result)
goto end;
@@ -690,7 +595,7 @@ acpi_ec_polling_query (
if (!*data)
result = -ENODATA;
-end:
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -698,13 +603,10 @@ end:
return_VALUE(result);
}
-static int
-acpi_ec_burst_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
{
- int status = 0;
- u32 glk;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_query");
@@ -719,70 +621,64 @@ acpi_ec_burst_query (
}
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
+
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("query EC, IB not empty\n");
goto end;
+ }
/*
* Query the EC to find out which _Qxx method we need to evaluate.
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ if (status) {
+ printk("query EC, OB not full\n");
goto end;
}
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (!*data)
status = -ENODATA;
-end:
- acpi_ec_leave_burst_mode(ec);
+ end:
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = -ENODATA;
- }
return_VALUE(status);
}
-
/* --------------------------------------------------------------------------
Event Management
-------------------------------------------------------------------------- */
union acpi_ec_query_data {
- acpi_handle handle;
- u8 data;
+ acpi_handle handle;
+ u8 data;
};
-static void
-acpi_ec_gpe_query (
- void *ec_cxt)
+static void acpi_ec_gpe_query(void *ec_cxt)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
acpi_ec_gpe_polling_query(ec_cxt);
else
acpi_ec_gpe_burst_query(ec_cxt);
}
-static void
-acpi_ec_gpe_polling_query (
- void *ec_cxt)
+static void acpi_ec_gpe_polling_query(void *ec_cxt)
{
- union acpi_ec *ec = (union acpi_ec *) ec_cxt;
- u32 value = 0;
- unsigned long flags = 0;
- static char object_name[5] = {'_','Q','0','0','\0'};
- const char hex[] = {'0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'};
+ union acpi_ec *ec = (union acpi_ec *)ec_cxt;
+ u32 value = 0;
+ unsigned long flags = 0;
+ static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
+ const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
@@ -812,19 +708,18 @@ acpi_ec_gpe_polling_query (
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
-end:
+ end:
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
}
-static void
-acpi_ec_gpe_burst_query (
- void *ec_cxt)
+static void acpi_ec_gpe_burst_query(void *ec_cxt)
{
- union acpi_ec *ec = (union acpi_ec *) ec_cxt;
- u32 value;
- int result = -ENODATA;
- static char object_name[5] = {'_','Q','0','0','\0'};
- const char hex[] = {'0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'};
+ union acpi_ec *ec = (union acpi_ec *)ec_cxt;
+ u32 value;
+ int result = -ENODATA;
+ static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
+ const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
@@ -840,26 +735,22 @@ acpi_ec_gpe_burst_query (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
-end:
+ end:
atomic_dec(&ec->burst.pending_gpe);
return;
}
-static u32
-acpi_ec_gpe_handler (
- void *data)
+static u32 acpi_ec_gpe_handler(void *data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_gpe_polling_handler(data);
else
- return acpi_ec_gpe_burst_handler(data);
+ return acpi_ec_gpe_burst_handler(data);
}
-static u32
-acpi_ec_gpe_polling_handler (
- void *data)
+static u32 acpi_ec_gpe_polling_handler(void *data)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = (union acpi_ec *) data;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = (union acpi_ec *)data;
if (!ec)
return ACPI_INTERRUPT_NOT_HANDLED;
@@ -867,61 +758,49 @@ acpi_ec_gpe_polling_handler (
acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, ec);
+ acpi_ec_gpe_query, ec);
if (status == AE_OK)
return ACPI_INTERRUPT_HANDLED;
else
return ACPI_INTERRUPT_NOT_HANDLED;
}
-static u32
-acpi_ec_gpe_burst_handler (
- void *data)
+static u32 acpi_ec_gpe_burst_handler(void *data)
{
- acpi_status status = AE_OK;
- u32 value;
- union acpi_ec *ec = (union acpi_ec *) data;
+ acpi_status status = AE_OK;
+ u32 value;
+ union acpi_ec *ec = (union acpi_ec *)data;
if (!ec)
return ACPI_INTERRUPT_NOT_HANDLED;
- acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
-
+ acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
value = acpi_ec_read_status(ec);
- if((value & ACPI_EC_FLAG_IBF) &&
- !(value & ACPI_EC_FLAG_BURST) &&
- (atomic_read(&ec->burst.leaving_burst) == 0)) {
- /*
- * the embedded controller disables
- * burst mode for any reason other
- * than the burst disable command
- * to process critical event.
- */
- atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction
- and retry */
+ switch (ec->burst.expect_event) {
+ case ACPI_EC_EVENT_OBF:
+ if (!(value & ACPI_EC_FLAG_OBF))
+ break;
+ case ACPI_EC_EVENT_IBE:
+ if ((value & ACPI_EC_FLAG_IBF))
+ break;
+ ec->burst.expect_event = 0;
wake_up(&ec->burst.wait);
- }else {
- if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF &&
- (value & ACPI_EC_FLAG_OBF)) ||
- (ec->burst.expect_event == ACPI_EC_EVENT_IBE &&
- !(value & ACPI_EC_FLAG_IBF))) {
- ec->burst.expect_event = 0;
- wake_up(&ec->burst.wait);
- return ACPI_INTERRUPT_HANDLED;
- }
+ return ACPI_INTERRUPT_HANDLED;
+ default:
+ break;
}
- if (value & ACPI_EC_FLAG_SCI){
- atomic_add(1, &ec->burst.pending_gpe) ;
+ if (value & ACPI_EC_FLAG_SCI) {
+ atomic_add(1, &ec->burst.pending_gpe);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, ec);
+ acpi_ec_gpe_query, ec);
return status == AE_OK ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
- }
+ ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ }
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
return status == AE_OK ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
/* --------------------------------------------------------------------------
@@ -929,37 +808,31 @@ acpi_ec_gpe_burst_handler (
-------------------------------------------------------------------------- */
static acpi_status
-acpi_ec_space_setup (
- acpi_handle region_handle,
- u32 function,
- void *handler_context,
- void **return_context)
+acpi_ec_space_setup(acpi_handle region_handle,
+ u32 function, void *handler_context, void **return_context)
{
/*
* The EC object is in the handler context and is needed
* when calling the acpi_ec_space_handler.
*/
- *return_context = (function != ACPI_REGION_DEACTIVATE) ?
- handler_context : NULL;
+ *return_context = (function != ACPI_REGION_DEACTIVATE) ?
+ handler_context : NULL;
return AE_OK;
}
-
static acpi_status
-acpi_ec_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ec_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- int result = 0;
- union acpi_ec *ec = NULL;
- u64 temp = *value;
- acpi_integer f_v = 0;
- int i = 0;
+ int result = 0;
+ union acpi_ec *ec = NULL;
+ u64 temp = *value;
+ acpi_integer f_v = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_ec_space_handler");
@@ -967,17 +840,18 @@ acpi_ec_space_handler (
return_VALUE(AE_BAD_PARAMETER);
if (bit_width != 8 && acpi_strict) {
- printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n");
+ printk(KERN_WARNING PREFIX
+ "acpi_ec_space_handler: bit_width should be 8\n");
return_VALUE(AE_BAD_PARAMETER);
}
- ec = (union acpi_ec *) handler_context;
+ ec = (union acpi_ec *)handler_context;
-next_byte:
+ next_byte:
switch (function) {
case ACPI_READ:
temp = 0;
- result = acpi_ec_read(ec, (u8) address, (u32 *)&temp);
+ result = acpi_ec_read(ec, (u8) address, (u32 *) & temp);
break;
case ACPI_WRITE:
result = acpi_ec_write(ec, (u8) address, (u8) temp);
@@ -1004,8 +878,7 @@ next_byte:
*value = f_v;
}
-
-out:
+ out:
switch (result) {
case -EINVAL:
return_VALUE(AE_BAD_PARAMETER);
@@ -1021,18 +894,15 @@ out:
}
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_ec_dir;
-
+static struct proc_dir_entry *acpi_ec_dir;
-static int
-acpi_ec_read_info (struct seq_file *seq, void *offset)
+static int acpi_ec_read_info(struct seq_file *seq, void *offset)
{
- union acpi_ec *ec = (union acpi_ec *) seq->private;
+ union acpi_ec *ec = (union acpi_ec *)seq->private;
ACPI_FUNCTION_TRACE("acpi_ec_read_info");
@@ -1040,14 +910,15 @@ acpi_ec_read_info (struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "gpe bit: 0x%02x\n",
- (u32) ec->common.gpe_bit);
+ (u32) ec->common.gpe_bit);
seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
- (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address);
+ (u32) ec->common.status_addr.address,
+ (u32) ec->common.data_addr.address);
seq_printf(seq, "use global lock: %s\n",
- ec->common.global_lock?"yes":"no");
+ ec->common.global_lock ? "yes" : "no");
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
-end:
+ end:
return_VALUE(0);
}
@@ -1057,34 +928,32 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_ec_info_ops = {
- .open = acpi_ec_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_ec_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_ec_add_fs (
- struct acpi_device *device)
+static int acpi_ec_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_ec_dir);
+ acpi_ec_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
- acpi_device_dir(device));
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Unable to create '%s' fs entry\n",
- ACPI_EC_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_EC_FILE_INFO));
else {
entry->proc_fops = &acpi_ec_info_ops;
entry->data = acpi_driver_data(device);
@@ -1094,10 +963,7 @@ acpi_ec_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_ec_remove_fs (
- struct acpi_device *device)
+static int acpi_ec_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
@@ -1110,20 +976,16 @@ acpi_ec_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-
-static int
-acpi_ec_polling_add (
- struct acpi_device *device)
+static int acpi_ec_polling_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
- unsigned long uid;
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
+ unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1143,26 +1005,31 @@ acpi_ec_polling_add (
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+ 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.*/
+ 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) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
-
- acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
+
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+ &acpi_ec_gpe_handler);
kfree(ec_ecdt);
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
+ &ec->common.gpe_bit);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error obtaining GPE bit assignment\n"));
+ "Error obtaining GPE bit assignment\n"));
result = -ENODEV;
goto end;
}
@@ -1172,26 +1039,24 @@ acpi_ec_polling_add (
goto end;
printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
- acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->common.gpe_bit);
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->common.gpe_bit);
if (!first_ec)
first_ec = device;
-end:
+ end:
if (result)
kfree(ec);
return_VALUE(result);
}
-static int
-acpi_ec_burst_add (
- struct acpi_device *device)
+static int acpi_ec_burst_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
- unsigned long uid;
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
+ unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1205,35 +1070,40 @@ acpi_ec_burst_add (
ec->common.handle = device->handle;
ec->common.uid = -1;
- atomic_set(&ec->burst.pending_gpe, 0);
- atomic_set(&ec->burst.leaving_burst , 1);
- init_MUTEX(&ec->burst.sem);
- init_waitqueue_head(&ec->burst.wait);
+ atomic_set(&ec->burst.pending_gpe, 0);
+ atomic_set(&ec->burst.leaving_burst, 1);
+ init_MUTEX(&ec->burst.sem);
+ init_waitqueue_head(&ec->burst.wait);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+ 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.*/
+ 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) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
- acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+ &acpi_ec_gpe_handler);
kfree(ec_ecdt);
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
+ &ec->common.gpe_bit);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error obtaining GPE bit assignment\n"));
+ "Error obtaining GPE bit assignment\n"));
result = -ENODEV;
goto end;
}
@@ -1242,27 +1112,24 @@ acpi_ec_burst_add (
if (result)
goto end;
+ printk("burst-mode-ec-10-Aug\n");
printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
- acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->common.gpe_bit);
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->common.gpe_bit);
if (!first_ec)
first_ec = device;
-end:
+ end:
if (result)
kfree(ec);
return_VALUE(result);
}
-
-static int
-acpi_ec_remove (
- struct acpi_device *device,
- int type)
+static int acpi_ec_remove(struct acpi_device *device, int type)
{
- union acpi_ec *ec = NULL;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_remove");
@@ -1278,13 +1145,10 @@ acpi_ec_remove (
return_VALUE(0);
}
-
static acpi_status
-acpi_ec_io_ports (
- struct acpi_resource *resource,
- void *context)
+acpi_ec_io_ports(struct acpi_resource *resource, void *context)
{
- union acpi_ec *ec = (union acpi_ec *) context;
+ union acpi_ec *ec = (union acpi_ec *)context;
struct acpi_generic_address *addr;
if (resource->id != ACPI_RSTYPE_IO) {
@@ -1312,13 +1176,10 @@ acpi_ec_io_ports (
return AE_OK;
}
-
-static int
-acpi_ec_start (
- struct acpi_device *device)
+static int acpi_ec_start(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_start");
@@ -1334,49 +1195,50 @@ acpi_ec_start (
* Get I/O port addresses. Convert to GAS format.
*/
status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec);
- if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses"));
+ acpi_ec_io_ports, ec);
+ if (ACPI_FAILURE(status)
+ || ec->common.command_addr.register_bit_width == 0) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error getting I/O port addresses"));
return_VALUE(-ENODEV);
}
ec->common.status_addr = ec->common.command_addr;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
- (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address,
- (u32) ec->common.data_addr.address));
-
+ (u32) ec->common.gpe_bit,
+ (u32) ec->common.command_addr.address,
+ (u32) ec->common.data_addr.address));
/*
* Install GPE handler
*/
status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
- ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
return_VALUE(-ENODEV);
}
- acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = acpi_install_address_space_handler (ec->common.handle,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
- &acpi_ec_space_setup, ec);
+ status = acpi_install_address_space_handler(ec->common.handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ &acpi_ec_space_setup, ec);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+ &acpi_ec_gpe_handler);
return_VALUE(-ENODEV);
}
return_VALUE(AE_OK);
}
-
-static int
-acpi_ec_stop (
- struct acpi_device *device,
- int type)
+static int acpi_ec_stop(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_stop");
@@ -1386,11 +1248,14 @@ acpi_ec_stop (
ec = acpi_driver_data(device);
status = acpi_remove_address_space_handler(ec->common.handle,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
+ status =
+ acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+ &acpi_ec_gpe_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -1398,32 +1263,26 @@ acpi_ec_stop (
}
static acpi_status __init
-acpi_fake_ecdt_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
if (acpi_ec_polling_mode)
return acpi_fake_ecdt_polling_callback(handle,
- Level, context, retval);
+ Level, context, retval);
else
return acpi_fake_ecdt_burst_callback(handle,
- Level, context, retval);
+ Level, context, retval);
}
static acpi_status __init
-acpi_fake_ecdt_polling_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_polling_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
- acpi_status status;
+ acpi_status status;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec_ecdt);
+ acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
@@ -1431,33 +1290,33 @@ acpi_fake_ecdt_polling_callback (
ec_ecdt->common.uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(handle, "_GPE", NULL,
+ &ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
spin_lock_init(&ec_ecdt->polling.lock);
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
- printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
- (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
- (u32) ec_ecdt->common.data_addr.address);
+ printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+ (u32) ec_ecdt->common.gpe_bit,
+ (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
return AE_CTRL_TERMINATE;
}
static acpi_status __init
-acpi_fake_ecdt_burst_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_burst_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
- acpi_status status;
+ acpi_status status;
init_MUTEX(&ec_ecdt->burst.sem);
init_waitqueue_head(&ec_ecdt->burst.wait);
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec_ecdt);
+ acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
@@ -1465,15 +1324,18 @@ acpi_fake_ecdt_burst_callback (
ec_ecdt->common.uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(handle, "_GPE", NULL,
+ &ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
- printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
- (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
- (u32) ec_ecdt->common.data_addr.address);
+ printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+ (u32) ec_ecdt->common.gpe_bit,
+ (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
return AE_CTRL_TERMINATE;
}
@@ -1488,11 +1350,10 @@ acpi_fake_ecdt_burst_callback (
* op region (since _REG isn't invoked yet). The assumption is true for
* all systems found.
*/
-static int __init
-acpi_ec_fake_ecdt(void)
+static int __init acpi_ec_fake_ecdt(void)
{
- acpi_status status;
- int ret = 0;
+ acpi_status status;
+ int ret = 0;
printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
@@ -1503,10 +1364,8 @@ acpi_ec_fake_ecdt(void)
}
memset(ec_ecdt, 0, sizeof(union acpi_ec));
- status = acpi_get_devices (ACPI_EC_HID,
- acpi_fake_ecdt_callback,
- NULL,
- NULL);
+ status = acpi_get_devices(ACPI_EC_HID,
+ acpi_fake_ecdt_callback, NULL, NULL);
if (ACPI_FAILURE(status)) {
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1514,13 +1373,12 @@ acpi_ec_fake_ecdt(void)
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Can't make an fake ECDT\n");
return ret;
}
-static int __init
-acpi_ec_get_real_ecdt(void)
+static int __init acpi_ec_get_real_ecdt(void)
{
if (acpi_ec_polling_mode)
return acpi_ec_polling_get_real_ecdt();
@@ -1528,14 +1386,14 @@ acpi_ec_get_real_ecdt(void)
return acpi_ec_burst_get_real_ecdt();
}
-static int __init
-acpi_ec_polling_get_real_ecdt(void)
+static int __init acpi_ec_polling_get_real_ecdt(void)
{
- acpi_status status;
- struct acpi_table_ecdt *ecdt_ptr;
+ acpi_status status;
+ struct acpi_table_ecdt *ecdt_ptr;
- status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
- (struct acpi_table_header **) &ecdt_ptr);
+ status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **)
+ &ecdt_ptr);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -1558,13 +1416,14 @@ acpi_ec_polling_get_real_ecdt(void)
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+ status =
+ acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
if (ACPI_FAILURE(status)) {
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1572,15 +1431,14 @@ error:
return -ENODEV;
}
-
-static int __init
-acpi_ec_burst_get_real_ecdt(void)
+static int __init acpi_ec_burst_get_real_ecdt(void)
{
- acpi_status status;
- struct acpi_table_ecdt *ecdt_ptr;
+ acpi_status status;
+ struct acpi_table_ecdt *ecdt_ptr;
status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
- (struct acpi_table_header **) &ecdt_ptr);
+ (struct acpi_table_header **)
+ &ecdt_ptr);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -1594,8 +1452,8 @@ acpi_ec_burst_get_real_ecdt(void)
return -ENOMEM;
memset(ec_ecdt, 0, sizeof(union acpi_ec));
- init_MUTEX(&ec_ecdt->burst.sem);
- init_waitqueue_head(&ec_ecdt->burst.wait);
+ init_MUTEX(&ec_ecdt->burst.sem);
+ init_waitqueue_head(&ec_ecdt->burst.wait);
ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
@@ -1604,13 +1462,14 @@ acpi_ec_burst_get_real_ecdt(void)
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+ status =
+ acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
if (ACPI_FAILURE(status)) {
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1619,11 +1478,10 @@ error:
}
static int __initdata acpi_fake_ecdt_enabled;
-int __init
-acpi_ec_ecdt_probe (void)
+int __init acpi_ec_ecdt_probe(void)
{
- acpi_status status;
- int ret;
+ acpi_status status;
+ int ret;
ret = acpi_ec_get_real_ecdt();
/* Try to make a fake ECDT */
@@ -1638,26 +1496,28 @@ acpi_ec_ecdt_probe (void)
* Install GPE handler
*/
status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
- ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
- ec_ecdt);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec_ecdt);
if (ACPI_FAILURE(status)) {
goto error;
}
- acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
-
- status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
- &acpi_ec_space_setup, ec_ecdt);
+ acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
+
+ status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ &acpi_ec_space_setup,
+ ec_ecdt);
if (ACPI_FAILURE(status)) {
acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
- &acpi_ec_gpe_handler);
+ &acpi_ec_gpe_handler);
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1665,10 +1525,9 @@ error:
return -ENODEV;
}
-
-static int __init acpi_ec_init (void)
+static int __init acpi_ec_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_init");
@@ -1693,8 +1552,7 @@ subsys_initcall(acpi_ec_init);
/* EC driver currently not unloadable */
#if 0
-static void __exit
-acpi_ec_exit (void)
+static void __exit acpi_ec_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_ec_exit");
@@ -1704,7 +1562,7 @@ acpi_ec_exit (void)
return_VOID;
}
-#endif /* 0 */
+#endif /* 0 */
static int __init acpi_fake_ecdt_setup(char *str)
{
@@ -1727,8 +1585,8 @@ static int __init acpi_ec_set_polling_mode(char *str)
acpi_ec_polling_mode = EC_POLLING;
acpi_ec_driver.ops.add = acpi_ec_polling_add;
}
- printk(KERN_INFO PREFIX "EC %s mode.\n",
- burst ? "burst": "polling");
+ printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling");
return 0;
}
+
__setup("ec_burst=", acpi_ec_set_polling_mode);
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 43c49f66a328..bfa8b76de403 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -13,45 +13,40 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("event")
+ACPI_MODULE_NAME("event")
/* Global vars for handling event proc entry */
static DEFINE_SPINLOCK(acpi_system_event_lock);
-int event_is_open = 0;
-extern struct list_head acpi_bus_event_list;
-extern wait_queue_head_t acpi_bus_event_queue;
+int event_is_open = 0;
+extern struct list_head acpi_bus_event_list;
+extern wait_queue_head_t acpi_bus_event_queue;
-static int
-acpi_system_open_event(struct inode *inode, struct file *file)
+static int acpi_system_open_event(struct inode *inode, struct file *file)
{
- spin_lock_irq (&acpi_system_event_lock);
+ spin_lock_irq(&acpi_system_event_lock);
- if(event_is_open)
+ if (event_is_open)
goto out_busy;
event_is_open = 1;
- spin_unlock_irq (&acpi_system_event_lock);
+ spin_unlock_irq(&acpi_system_event_lock);
return 0;
-out_busy:
- spin_unlock_irq (&acpi_system_event_lock);
+ out_busy:
+ spin_unlock_irq(&acpi_system_event_lock);
return -EBUSY;
}
static ssize_t
-acpi_system_read_event (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
+ loff_t * ppos)
{
- int result = 0;
- struct acpi_bus_event event;
- static char str[ACPI_MAX_STRING];
- static int chars_remaining = 0;
- static char *ptr;
-
+ int result = 0;
+ struct acpi_bus_event event;
+ static char str[ACPI_MAX_STRING];
+ static int chars_remaining = 0;
+ static char *ptr;
ACPI_FUNCTION_TRACE("acpi_system_read_event");
@@ -67,10 +62,12 @@ acpi_system_read_event (
return_VALUE(-EIO);
}
- chars_remaining = sprintf(str, "%s %s %08x %08x\n",
- event.device_class?event.device_class:"<unknown>",
- event.bus_id?event.bus_id:"<unknown>",
- event.type, event.data);
+ chars_remaining = sprintf(str, "%s %s %08x %08x\n",
+ event.device_class ? event.
+ device_class : "<unknown>",
+ event.bus_id ? event.
+ bus_id : "<unknown>", event.type,
+ event.data);
ptr = str;
}
@@ -88,19 +85,15 @@ acpi_system_read_event (
return_VALUE(count);
}
-static int
-acpi_system_close_event(struct inode *inode, struct file *file)
+static int acpi_system_close_event(struct inode *inode, struct file *file)
{
- spin_lock_irq (&acpi_system_event_lock);
+ spin_lock_irq(&acpi_system_event_lock);
event_is_open = 0;
- spin_unlock_irq (&acpi_system_event_lock);
+ spin_unlock_irq(&acpi_system_event_lock);
return 0;
}
-static unsigned int
-acpi_system_poll_event(
- struct file *file,
- poll_table *wait)
+static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
{
poll_wait(file, &acpi_bus_event_queue, wait);
if (!list_empty(&acpi_bus_event_list))
@@ -109,15 +102,15 @@ acpi_system_poll_event(
}
static struct file_operations acpi_system_event_ops = {
- .open = acpi_system_open_event,
- .read = acpi_system_read_event,
- .release = acpi_system_close_event,
- .poll = acpi_system_poll_event,
+ .open = acpi_system_open_event,
+ .read = acpi_system_read_event,
+ .release = acpi_system_close_event,
+ .poll = acpi_system_poll_event,
};
static int __init acpi_event_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
ACPI_FUNCTION_TRACE("acpi_event_init");
@@ -130,8 +123,9 @@ static int __init acpi_event_init(void)
if (entry)
entry->proc_fops = &acpi_system_event_ops;
else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n","event" ));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n",
+ "event"));
error = -EFAULT;
}
return_VALUE(error);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index dd3a72a869f4..842d1e3fb37b 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -45,18 +45,12 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evevent")
+ACPI_MODULE_NAME("evevent")
/* Local prototypes */
+static acpi_status acpi_ev_fixed_event_initialize(void);
-static acpi_status
-acpi_ev_fixed_event_initialize (
- void);
-
-static u32
-acpi_ev_fixed_event_dispatch (
- u32 event);
-
+static u32 acpi_ev_fixed_event_dispatch(u32 event);
/*******************************************************************************
*
@@ -70,21 +64,17 @@ acpi_ev_fixed_event_dispatch (
*
******************************************************************************/
-acpi_status
-acpi_ev_initialize_events (
- void)
+acpi_status acpi_ev_initialize_events(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_initialize_events");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_initialize_events");
/* Make sure we have ACPI tables */
if (!acpi_gbl_DSDT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No ACPI tables present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
@@ -92,26 +82,22 @@ acpi_ev_initialize_events (
* enabling SCIs to prevent interrupts from occurring before the handlers are
* installed.
*/
- status = acpi_ev_fixed_event_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize fixed events, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_fixed_event_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize fixed events, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- status = acpi_ev_gpe_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize general purpose events, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_gpe_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize general purpose events, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_xrupt_handlers
@@ -124,41 +110,32 @@ acpi_ev_initialize_events (
*
******************************************************************************/
-acpi_status
-acpi_ev_install_xrupt_handlers (
- void)
+acpi_status acpi_ev_install_xrupt_handlers(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers");
/* Install the SCI handler */
- status = acpi_ev_install_sci_handler ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to install System Control Interrupt Handler, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_sci_handler();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* Install the handler for the Global Lock */
- status = acpi_ev_init_global_lock_handler ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize Global Lock handler, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_init_global_lock_handler();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize Global Lock handler, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
acpi_gbl_events_initialized = TRUE;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_initialize
@@ -171,13 +148,10 @@ acpi_ev_install_xrupt_handlers (
*
******************************************************************************/
-static acpi_status
-acpi_ev_fixed_event_initialize (
- void)
+static acpi_status acpi_ev_fixed_event_initialize(void)
{
- acpi_native_uint i;
- acpi_status status;
-
+ acpi_native_uint i;
+ acpi_status status;
/*
* Initialize the structure that keeps track of fixed event handlers
@@ -190,10 +164,11 @@ acpi_ev_fixed_event_initialize (
/* Enable the fixed event */
if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
- status = acpi_set_register (
- acpi_gbl_fixed_event_info[i].enable_register_id,
- 0, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[i].
+ enable_register_id, 0,
+ ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -202,7 +177,6 @@ acpi_ev_fixed_event_initialize (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_detect
@@ -215,31 +189,27 @@ acpi_ev_fixed_event_initialize (
*
******************************************************************************/
-u32
-acpi_ev_fixed_event_detect (
- void)
+u32 acpi_ev_fixed_event_detect(void)
{
- u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
- u32 fixed_status;
- u32 fixed_enable;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_NAME ("ev_fixed_event_detect");
+ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+ u32 fixed_status;
+ u32 fixed_enable;
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ev_fixed_event_detect");
/*
* Read the fixed feature status and enable registers, as all the cases
* depend on their values. Ignore errors here.
*/
- (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
- &fixed_status);
- (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE,
- &fixed_enable);
+ (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS, &fixed_status);
+ (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
- ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
- "Fixed Event Block: Enable %08X Status %08X\n",
- fixed_enable, fixed_status));
+ ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+ "Fixed Event Block: Enable %08X Status %08X\n",
+ fixed_enable, fixed_status));
/*
* Check for all possible Fixed Events and dispatch those that are active
@@ -247,18 +217,19 @@ acpi_ev_fixed_event_detect (
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)) {
+ 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);
+ int_status |= acpi_ev_fixed_event_dispatch((u32) i);
}
}
return (int_status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_dispatch
@@ -272,39 +243,32 @@ acpi_ev_fixed_event_detect (
*
******************************************************************************/
-static u32
-acpi_ev_fixed_event_dispatch (
- u32 event)
+static u32 acpi_ev_fixed_event_dispatch(u32 event)
{
-
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/* Clear the status bit */
- (void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)acpi_set_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, 1, ACPI_MTX_DO_NOT_LOCK);
/*
* Make sure we've got a handler. If not, report an error.
* The event is disabled to prevent further interrupts.
*/
if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
- (void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 0, ACPI_MTX_DO_NOT_LOCK);
+ (void)acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 0,
+ ACPI_MTX_DO_NOT_LOCK);
- ACPI_REPORT_ERROR (
- ("No installed handler for fixed event [%08X]\n",
- event));
+ ACPI_REPORT_ERROR(("No installed handler for fixed event [%08X]\n", event));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
/* Invoke the Fixed Event handler */
- return ((acpi_gbl_fixed_event_handlers[event].handler)(
- acpi_gbl_fixed_event_handlers[event].context));
+ return ((acpi_gbl_fixed_event_handlers[event].
+ handler) (acpi_gbl_fixed_event_handlers[event].context));
}
-
-
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 081120b109ba..b2f232df13d8 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -46,14 +46,10 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evgpe")
+ACPI_MODULE_NAME("evgpe")
/* Local prototypes */
-
-static void ACPI_SYSTEM_XFACE
-acpi_ev_asynch_execute_gpe_method (
- void *context);
-
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
/*******************************************************************************
*
@@ -69,15 +65,11 @@ acpi_ev_asynch_execute_gpe_method (
******************************************************************************/
acpi_status
-acpi_ev_set_gpe_type (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type)
+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_status status;
+ ACPI_FUNCTION_TRACE("ev_set_gpe_type");
/* Validate type and update register enable masks */
@@ -88,21 +80,20 @@ acpi_ev_set_gpe_type (
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Disable the GPE if currently enabled */
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
/* Type was validated above */
- gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
- gpe_event_info->flags |= type; /* Insert type */
- return_ACPI_STATUS (status);
+ gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
+ gpe_event_info->flags |= type; /* Insert type */
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_update_gpe_enable_masks
@@ -118,57 +109,55 @@ acpi_ev_set_gpe_type (
******************************************************************************/
acpi_status
-acpi_ev_update_gpe_enable_masks (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type)
+acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
+ u8 type)
{
- struct acpi_gpe_register_info *gpe_register_info;
- u8 register_bit;
-
-
- ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
+ struct acpi_gpe_register_info *gpe_register_info;
+ u8 register_bit;
+ ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks");
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
register_bit = gpe_event_info->register_bit;
/* 1) Disable case. Simply clear all enable bits */
if (type == ACPI_GPE_DISABLE) {
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
- return_ACPI_STATUS (AE_OK);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+ register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
+ return_ACPI_STATUS(AE_OK);
}
/* 2) Enable case. Set/Clear the appropriate enable bits */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
break;
case ACPI_GPE_TYPE_RUNTIME:
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+ register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_enable_gpe
@@ -184,21 +173,19 @@ acpi_ev_update_gpe_enable_masks (
******************************************************************************/
acpi_status
-acpi_ev_enable_gpe (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 write_to_hardware)
+acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
+ u8 write_to_hardware)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_enable_gpe");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_enable_gpe");
/* Make sure HW enable masks are updated */
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Mark wake-enabled or HW enable, or both */
@@ -206,41 +193,40 @@ acpi_ev_enable_gpe (
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
/*lint -fallthrough */
case ACPI_GPE_TYPE_RUNTIME:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+ 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Enable the requested runtime GPE */
- status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+ status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
}
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_disable_gpe
@@ -253,36 +239,33 @@ acpi_ev_enable_gpe (
*
******************************************************************************/
-acpi_status
-acpi_ev_disable_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_disable_gpe");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_disable_gpe");
if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Make sure HW enable masks are updated */
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Mark wake-disabled or HW disable, or both */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
/*lint -fallthrough */
@@ -290,18 +273,17 @@ acpi_ev_disable_gpe (
/* Disable the requested runtime GPE */
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
- status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+ status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_event_info
@@ -319,18 +301,14 @@ acpi_ev_disable_gpe (
*
******************************************************************************/
-struct acpi_gpe_event_info *
-acpi_ev_get_gpe_event_info (
- acpi_handle gpe_device,
- u32 gpe_number)
+struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
+ u32 gpe_number)
{
- union acpi_operand_object *obj_desc;
- struct acpi_gpe_block_info *gpe_block;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_operand_object *obj_desc;
+ struct acpi_gpe_block_info *gpe_block;
+ acpi_native_uint i;
+ ACPI_FUNCTION_ENTRY();
/* A NULL gpe_block means use the FADT-defined GPE block(s) */
@@ -340,11 +318,14 @@ acpi_ev_get_gpe_event_info (
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
gpe_block = acpi_gbl_gpe_fadt_blocks[i];
if (gpe_block) {
- if ((gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number +
- (gpe_block->register_count * 8))) {
- return (&gpe_block->event_info[gpe_number -
- gpe_block->block_base_number]);
+ if ((gpe_number >= gpe_block->block_base_number)
+ && (gpe_number <
+ gpe_block->block_base_number +
+ (gpe_block->register_count * 8))) {
+ return (&gpe_block->
+ event_info[gpe_number -
+ gpe_block->
+ block_base_number]);
}
}
}
@@ -356,23 +337,25 @@ acpi_ev_get_gpe_event_info (
/* A Non-NULL gpe_device means this is a GPE Block Device */
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
- if (!obj_desc ||
- !obj_desc->device.gpe_block) {
+ obj_desc =
+ acpi_ns_get_attached_object((struct acpi_namespace_node *)
+ gpe_device);
+ if (!obj_desc || !obj_desc->device.gpe_block) {
return (NULL);
}
gpe_block = obj_desc->device.gpe_block;
if ((gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
- return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
+ (gpe_number <
+ gpe_block->block_base_number + (gpe_block->register_count * 8))) {
+ return (&gpe_block->
+ event_info[gpe_number - gpe_block->block_base_number]);
}
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_detect
@@ -387,22 +370,20 @@ acpi_ev_get_gpe_event_info (
*
******************************************************************************/
-u32
-acpi_ev_gpe_detect (
- struct acpi_gpe_xrupt_info *gpe_xrupt_list)
+u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
{
- u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
- u8 enabled_status_byte;
- struct acpi_gpe_register_info *gpe_register_info;
- u32 status_reg;
- u32 enable_reg;
- acpi_status status;
- struct acpi_gpe_block_info *gpe_block;
- acpi_native_uint i;
- acpi_native_uint j;
-
-
- ACPI_FUNCTION_NAME ("ev_gpe_detect");
+ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+ u8 enabled_status_byte;
+ struct acpi_gpe_register_info *gpe_register_info;
+ u32 status_reg;
+ u32 enable_reg;
+ u32 flags;
+ acpi_status status;
+ struct acpi_gpe_block_info *gpe_block;
+ acpi_native_uint i;
+ acpi_native_uint j;
+
+ ACPI_FUNCTION_NAME("ev_gpe_detect");
/* Check for the case where there are no GPEs */
@@ -412,7 +393,7 @@ acpi_ev_gpe_detect (
/* Examine all GPE blocks attached to this interrupt level */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) {
/*
@@ -427,23 +408,30 @@ acpi_ev_gpe_detect (
/* Read the Status Register */
- status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
- &gpe_register_info->status_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
+ &status_reg,
+ &gpe_register_info->
+ status_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Read the Enable Register */
- status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
- &gpe_register_info->enable_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
+ &enable_reg,
+ &gpe_register_info->
+ enable_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
- "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
- gpe_register_info->base_gpe_number, status_reg, enable_reg));
+ ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+ "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
+ gpe_register_info->base_gpe_number,
+ status_reg, enable_reg));
/* Check if there is anything active at all in this register */
@@ -459,14 +447,21 @@ acpi_ev_gpe_detect (
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
/* Examine one GPE bit */
- if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) {
+ if (enabled_status_byte &
+ acpi_gbl_decode_to8bit[j]) {
/*
* Found an active GPE. Dispatch the event to a handler
* or method.
*/
- int_status |= acpi_ev_gpe_dispatch (
- &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
- (u32) j + gpe_register_info->base_gpe_number);
+ int_status |=
+ acpi_ev_gpe_dispatch(&gpe_block->
+ event_info[(i *
+ ACPI_GPE_REGISTER_WIDTH)
+ +
+ j],
+ (u32) j +
+ gpe_register_info->
+ base_gpe_number);
}
}
}
@@ -474,13 +469,12 @@ acpi_ev_gpe_detect (
gpe_block = gpe_block->next;
}
-unlock_and_exit:
+ unlock_and_exit:
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return (int_status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_asynch_execute_gpe_method
@@ -497,45 +491,41 @@ unlock_and_exit:
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_asynch_execute_gpe_method (
- void *context)
+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_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;
- 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)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Must revalidate the gpe_number/gpe_block */
- if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (!acpi_ev_valid_gpe_event(gpe_event_info)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_VOID;
}
/* Set the GPE flags for return to enabled state */
- (void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
+ (void)acpi_ev_enable_gpe(gpe_event_info, FALSE);
/*
* Take a snapshot of the GPE info for this level - we copy the
* info to prevent a race condition with remove_handler/remove_block.
*/
- ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info,
- sizeof (struct acpi_gpe_event_info));
+ ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
+ sizeof(struct acpi_gpe_event_info));
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
@@ -544,44 +534,40 @@ acpi_ev_asynch_execute_gpe_method (
* time to avoid race with ev_gpe_install_handler
*/
if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_METHOD) {
+ 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.parameters =
+ ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info);
info.parameter_type = ACPI_PARAM_GPE;
- status = acpi_ns_evaluate_by_handle (&info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "%s while evaluating method [%4.4s] for GPE[%2X]\n",
- acpi_format_exception (status),
- acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
- gpe_number));
+ status = acpi_ns_evaluate_by_handle(&info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number));
}
}
if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_LEVEL_TRIGGERED) {
+ ACPI_GPE_LEVEL_TRIGGERED) {
/*
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
- status = acpi_hw_clear_gpe (&local_gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_clear_gpe(&local_gpe_event_info);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Enable this GPE */
- (void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
+ (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_dispatch
@@ -599,38 +585,31 @@ acpi_ev_asynch_execute_gpe_method (
******************************************************************************/
u32
-acpi_ev_gpe_dispatch (
- struct acpi_gpe_event_info *gpe_event_info,
- u32 gpe_number)
+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_status status;
+ ACPI_FUNCTION_TRACE("ev_gpe_dispatch");
/*
* If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_EDGE_TRIGGERED) {
- status = acpi_hw_clear_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_GPE_EDGE_TRIGGERED) {
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
}
/* Save current system state */
if (acpi_gbl_system_awake_and_running) {
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
- }
- else {
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+ } else {
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
}
/*
@@ -647,19 +626,19 @@ acpi_ev_gpe_dispatch (
* Invoke the installed handler (at interrupt level)
* Ignore return status for now. TBD: leave GPE disabled on error?
*/
- (void) gpe_event_info->dispatch.handler->address (
- gpe_event_info->dispatch.handler->context);
+ (void)gpe_event_info->dispatch.handler->address(gpe_event_info->
+ dispatch.
+ handler->
+ context);
/* It is now safe to clear level-triggered events. */
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_LEVEL_TRIGGERED) {
- status = acpi_hw_clear_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_GPE_LEVEL_TRIGGERED) {
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
}
break;
@@ -670,24 +649,21 @@ acpi_ev_gpe_dispatch (
* Disable GPE, so it doesn't keep firing before the method has a
* chance to run.
*/
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
/*
* 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);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n",
- acpi_format_exception (status), gpe_number));
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+ acpi_ev_asynch_execute_gpe_method,
+ gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number));
}
break;
@@ -695,28 +671,23 @@ acpi_ev_gpe_dispatch (
/* No handler or method to run! */
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n",
- gpe_number));
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number));
/*
* Disable the GPE. The GPE will remain disabled until the ACPI
* Core Subsystem is restarted, or a handler is installed.
*/
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
break;
}
- return_VALUE (ACPI_INTERRUPT_HANDLED);
+ return_VALUE(ACPI_INTERRUPT_HANDLED);
}
-
#ifdef ACPI_GPE_NOTIFY_CHECK
/*******************************************************************************
* TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
@@ -735,35 +706,29 @@ acpi_ev_gpe_dispatch (
******************************************************************************/
acpi_status
-acpi_ev_check_for_wake_only_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
- acpi_status status;
+ 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 */ {
+ 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 */
/* This must be a wake-only GPE, disable it */
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
/* Set GPE to wake-only. Do not change wake disabled/enabled status */
- acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+ acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
- ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
- gpe_event_info));
+ ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info));
/* This was a wake-only GPE */
- return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+ return_ACPI_STATUS(AE_WAKE_ONLY_GPE);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
-
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index 84186a7d17b2..b312eb33c43e 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -46,41 +46,29 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evgpeblk")
+ACPI_MODULE_NAME("evgpeblk")
/* Local prototypes */
-
static acpi_status
-acpi_ev_save_method_info (
- acpi_handle obj_handle,
- u32 level,
- void *obj_desc,
- void **return_value);
+acpi_ev_save_method_info(acpi_handle obj_handle,
+ u32 level, void *obj_desc, void **return_value);
static acpi_status
-acpi_ev_match_prw_and_gpe (
- acpi_handle obj_handle,
- u32 level,
- void *info,
- void **return_value);
+acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
+ u32 level, void *info, void **return_value);
-static struct acpi_gpe_xrupt_info *
-acpi_ev_get_gpe_xrupt_block (
- u32 interrupt_level);
+static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
+ interrupt_number);
static acpi_status
-acpi_ev_delete_gpe_xrupt (
- struct acpi_gpe_xrupt_info *gpe_xrupt);
+acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
static acpi_status
-acpi_ev_install_gpe_block (
- struct acpi_gpe_block_info *gpe_block,
- u32 interrupt_level);
+acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
+ u32 interrupt_number);
static acpi_status
-acpi_ev_create_gpe_info_blocks (
- struct acpi_gpe_block_info *gpe_block);
-
+acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
/*******************************************************************************
*
@@ -96,16 +84,12 @@ acpi_ev_create_gpe_info_blocks (
*
******************************************************************************/
-u8
-acpi_ev_valid_gpe_event (
- struct acpi_gpe_event_info *gpe_event_info)
+u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
{
- struct acpi_gpe_xrupt_info *gpe_xrupt_block;
- struct acpi_gpe_block_info *gpe_block;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_gpe_xrupt_info *gpe_xrupt_block;
+ struct acpi_gpe_block_info *gpe_block;
+ ACPI_FUNCTION_ENTRY();
/* No need for spin lock since we are not changing any list elements */
@@ -119,7 +103,10 @@ acpi_ev_valid_gpe_event (
while (gpe_block) {
if ((&gpe_block->event_info[0] <= gpe_event_info) &&
- (&gpe_block->event_info[((acpi_size) gpe_block->register_count) * 8] > gpe_event_info)) {
+ (&gpe_block->
+ event_info[((acpi_size) gpe_block->
+ register_count) * 8] >
+ gpe_event_info)) {
return (TRUE);
}
@@ -132,13 +119,11 @@ acpi_ev_valid_gpe_event (
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_walk_gpe_list
*
* PARAMETERS: gpe_walk_callback - Routine called for each GPE block
- * Flags - ACPI_NOT_ISR or ACPI_ISR
*
* RETURN: Status
*
@@ -146,20 +131,16 @@ acpi_ev_valid_gpe_event (
*
******************************************************************************/
-acpi_status
-acpi_ev_walk_gpe_list (
- ACPI_GPE_CALLBACK gpe_walk_callback,
- u32 flags)
+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;
-
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ acpi_status status = AE_OK;
+ u32 flags;
- ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
+ ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
-
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Walk the interrupt level descriptor list */
@@ -171,8 +152,8 @@ acpi_ev_walk_gpe_list (
while (gpe_block) {
/* One callback per GPE block */
- status = gpe_walk_callback (gpe_xrupt_info, gpe_block);
- if (ACPI_FAILURE (status)) {
+ status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -182,12 +163,11 @@ acpi_ev_walk_gpe_list (
gpe_xrupt_info = gpe_xrupt_info->next;
}
-unlock_and_exit:
- acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_handlers
@@ -203,17 +183,14 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ev_delete_gpe_handlers (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block)
{
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
-
-
- ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers");
/* Examine each GPE Register within the block */
@@ -221,21 +198,23 @@ acpi_ev_delete_gpe_handlers (
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
- gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ gpe_event_info =
+ &gpe_block->
+ event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_HANDLER) {
- ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
+ ACPI_GPE_DISPATCH_HANDLER) {
+ ACPI_MEM_FREE(gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
- gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
+ gpe_event_info->flags &=
+ ~ACPI_GPE_DISPATCH_MASK;
}
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_save_method_info
@@ -259,30 +238,26 @@ acpi_ev_delete_gpe_handlers (
******************************************************************************/
static acpi_status
-acpi_ev_save_method_info (
- acpi_handle obj_handle,
- u32 level,
- void *obj_desc,
- void **return_value)
+acpi_ev_save_method_info(acpi_handle obj_handle,
+ u32 level, void *obj_desc, void **return_value)
{
- struct acpi_gpe_block_info *gpe_block = (void *) obj_desc;
- struct acpi_gpe_event_info *gpe_event_info;
- u32 gpe_number;
- char name[ACPI_NAME_SIZE + 1];
- u8 type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_save_method_info");
+ struct acpi_gpe_block_info *gpe_block = (void *)obj_desc;
+ struct acpi_gpe_event_info *gpe_event_info;
+ u32 gpe_number;
+ char name[ACPI_NAME_SIZE + 1];
+ u8 type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_save_method_info");
/*
* _Lxx and _Exx GPE method support
*
* 1) Extract the name from the object and convert to a string
*/
- ACPI_MOVE_32_TO_32 (name,
- &((struct acpi_namespace_node *) obj_handle)->name.integer);
+ ACPI_MOVE_32_TO_32(name,
+ &((struct acpi_namespace_node *)obj_handle)->name.
+ integer);
name[ACPI_NAME_SIZE] = 0;
/*
@@ -304,34 +279,36 @@ acpi_ev_save_method_info (
default:
/* Unknown method type, just ignore it! */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
- name));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
+ name));
+ return_ACPI_STATUS(AE_OK);
}
/* Convert the last two characters of the name to the GPE Number */
- gpe_number = ACPI_STRTOUL (&name[2], NULL, 16);
+ gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
if (gpe_number == ACPI_UINT32_MAX) {
/* Conversion failed; invalid method, just ignore it */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
- name));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
+ name));
+ return_ACPI_STATUS(AE_OK);
}
/* Ensure that we have a valid GPE number for this GPE block */
if ((gpe_number < gpe_block->block_base_number) ||
- (gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) {
+ (gpe_number >=
+ (gpe_block->block_base_number +
+ (gpe_block->register_count * 8)))) {
/*
* Not valid for this GPE block, just ignore it
* However, it may be valid for a different GPE block, since GPE0 and GPE1
* methods both appear under \_GPE.
*/
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -339,24 +316,25 @@ acpi_ev_save_method_info (
* for use during dispatch of this GPE. Default type is RUNTIME, although
* this may change when the _PRW methods are executed later.
*/
- gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
+ gpe_event_info =
+ &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
- ACPI_GPE_TYPE_RUNTIME);
+ ACPI_GPE_TYPE_RUNTIME);
- gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
+ gpe_event_info->dispatch.method_node =
+ (struct acpi_namespace_node *)obj_handle;
/* Update enable mask, but don't enable the HW GPE as of yet */
- status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
+ status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
- "Registered GPE method %s as GPE number 0x%.2X\n",
- name, gpe_number));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "Registered GPE method %s as GPE number 0x%.2X\n",
+ name, gpe_number));
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_match_prw_and_gpe
@@ -373,34 +351,29 @@ acpi_ev_save_method_info (
******************************************************************************/
static acpi_status
-acpi_ev_match_prw_and_gpe (
- acpi_handle obj_handle,
- u32 level,
- void *info,
- void **return_value)
+acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
+ u32 level, void *info, void **return_value)
{
- struct acpi_gpe_walk_info *gpe_info = (void *) info;
- struct acpi_namespace_node *gpe_device;
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_namespace_node *target_gpe_device;
- struct acpi_gpe_event_info *gpe_event_info;
- union acpi_operand_object *pkg_desc;
- union acpi_operand_object *obj_desc;
- u32 gpe_number;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
-
+ struct acpi_gpe_walk_info *gpe_info = (void *)info;
+ struct acpi_namespace_node *gpe_device;
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_namespace_node *target_gpe_device;
+ struct acpi_gpe_event_info *gpe_event_info;
+ union acpi_operand_object *pkg_desc;
+ union acpi_operand_object *obj_desc;
+ u32 gpe_number;
+ acpi_status status;
+
+ 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)) {
+ 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);
+ return_ACPI_STATUS(AE_OK);
}
/* The returned _PRW package must have at least two elements */
@@ -420,7 +393,7 @@ acpi_ev_match_prw_and_gpe (
*/
obj_desc = pkg_desc->package.elements[0];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ 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;
@@ -428,22 +401,23 @@ acpi_ev_match_prw_and_gpe (
/* Integer is the GPE number in the FADT described GPE blocks */
gpe_number = (u32) obj_desc->integer.value;
- }
- else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+ } 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) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) !=
+ ACPI_TYPE_LOCAL_REFERENCE)
+ || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) !=
+ ACPI_TYPE_INTEGER)) {
goto cleanup;
}
/* Get GPE block reference and decode */
- target_gpe_device = obj_desc->package.elements[0]->reference.node;
+ target_gpe_device =
+ obj_desc->package.elements[0]->reference.node;
gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
- }
- else {
+ } else {
/* Unknown type, just ignore it */
goto cleanup;
@@ -458,31 +432,37 @@ acpi_ev_match_prw_and_gpe (
* associated with the GPE device.
*/
if ((gpe_device == target_gpe_device) &&
- (gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
- gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
+ (gpe_number >= gpe_block->block_base_number) &&
+ (gpe_number <
+ gpe_block->block_base_number + (gpe_block->register_count * 8))) {
+ gpe_event_info =
+ &gpe_block->event_info[gpe_number -
+ gpe_block->block_base_number];
/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
- gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
- status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
- if (ACPI_FAILURE (status)) {
+ gpe_event_info->flags &=
+ ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+ status =
+ acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info,
+ ACPI_GPE_DISABLE);
}
-cleanup:
- acpi_ut_remove_reference (pkg_desc);
- return_ACPI_STATUS (AE_OK);
+ cleanup:
+ acpi_ut_remove_reference(pkg_desc);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
- * PARAMETERS: interrupt_level - Interrupt for a GPE block
+ * PARAMETERS: interrupt_number - Interrupt for a GPE block
*
* RETURN: A GPE interrupt block
*
@@ -493,24 +473,22 @@ cleanup:
*
******************************************************************************/
-static struct acpi_gpe_xrupt_info *
-acpi_ev_get_gpe_xrupt_block (
- u32 interrupt_level)
+static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
+ interrupt_number)
{
- struct acpi_gpe_xrupt_info *next_gpe_xrupt;
- struct acpi_gpe_xrupt_info *gpe_xrupt;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_get_gpe_xrupt_block");
+ struct acpi_gpe_xrupt_info *next_gpe_xrupt;
+ struct acpi_gpe_xrupt_info *gpe_xrupt;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
/* No need for lock since we are not changing any list elements here */
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt) {
- if (next_gpe_xrupt->interrupt_level == interrupt_level) {
- return_PTR (next_gpe_xrupt);
+ if (next_gpe_xrupt->interrupt_number == interrupt_number) {
+ return_PTR(next_gpe_xrupt);
}
next_gpe_xrupt = next_gpe_xrupt->next;
@@ -518,16 +496,16 @@ acpi_ev_get_gpe_xrupt_block (
/* Not found, must allocate a new xrupt descriptor */
- gpe_xrupt = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_xrupt_info));
+ gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- gpe_xrupt->interrupt_level = interrupt_level;
+ gpe_xrupt->interrupt_number = interrupt_number;
/* Install new interrupt descriptor with spin lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (acpi_gbl_gpe_xrupt_list_head) {
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt->next) {
@@ -536,29 +514,28 @@ acpi_ev_get_gpe_xrupt_block (
next_gpe_xrupt->next = gpe_xrupt;
gpe_xrupt->previous = next_gpe_xrupt;
- }
- else {
+ } else {
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Install new interrupt handler if not SCI_INT */
- if (interrupt_level != acpi_gbl_FADT->sci_int) {
- status = acpi_os_install_interrupt_handler (interrupt_level,
- acpi_ev_gpe_xrupt_handler, gpe_xrupt);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not install GPE interrupt handler at level 0x%X\n",
- interrupt_level));
- return_PTR (NULL);
+ if (interrupt_number != acpi_gbl_FADT->sci_int) {
+ status = acpi_os_install_interrupt_handler(interrupt_number,
+ acpi_ev_gpe_xrupt_handler,
+ gpe_xrupt);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not install GPE interrupt handler at level 0x%X\n",
+ interrupt_number));
+ return_PTR(NULL);
}
}
- return_PTR (gpe_xrupt);
+ return_PTR(gpe_xrupt);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_xrupt
@@ -573,33 +550,31 @@ acpi_ev_get_gpe_xrupt_block (
******************************************************************************/
static acpi_status
-acpi_ev_delete_gpe_xrupt (
- struct acpi_gpe_xrupt_info *gpe_xrupt)
+acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt");
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
/* We never want to remove the SCI interrupt handler */
- if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) {
+ if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) {
gpe_xrupt->gpe_block_list_head = NULL;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Disable this interrupt */
- status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level,
- acpi_ev_gpe_xrupt_handler);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
+ acpi_ev_gpe_xrupt_handler);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Unlink the interrupt block with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt->previous) {
gpe_xrupt->previous->next = gpe_xrupt->next;
}
@@ -607,21 +582,20 @@ acpi_ev_delete_gpe_xrupt (
if (gpe_xrupt->next) {
gpe_xrupt->next->previous = gpe_xrupt->previous;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Free the block */
- ACPI_MEM_FREE (gpe_xrupt);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MEM_FREE(gpe_xrupt);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_gpe_block
*
* PARAMETERS: gpe_block - New GPE block
- * interrupt_level - Level to be associated with this GPE block
+ * interrupt_number - Xrupt to be associated with this GPE block
*
* RETURN: Status
*
@@ -630,24 +604,22 @@ acpi_ev_delete_gpe_xrupt (
******************************************************************************/
static acpi_status
-acpi_ev_install_gpe_block (
- struct acpi_gpe_block_info *gpe_block,
- u32 interrupt_level)
+acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
+ u32 interrupt_number)
{
- struct acpi_gpe_block_info *next_gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_block;
- acpi_status status;
+ struct acpi_gpe_block_info *next_gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_block;
+ acpi_status status;
+ u32 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
+ gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number);
if (!gpe_xrupt_block) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -655,7 +627,7 @@ acpi_ev_install_gpe_block (
/* Install the new block at the end of the list with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt_block->gpe_block_list_head) {
next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (next_gpe_block->next) {
@@ -664,20 +636,18 @@ acpi_ev_install_gpe_block (
next_gpe_block->next = gpe_block;
gpe_block->previous = next_gpe_block;
- }
- else {
+ } else {
gpe_xrupt_block->gpe_block_list_head = gpe_block;
}
gpe_block->xrupt_block = gpe_xrupt_block;
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_block
@@ -690,62 +660,57 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ev_delete_gpe_block (
- struct acpi_gpe_block_info *gpe_block)
+acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_install_gpe_block");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Disable all GPEs in this block */
- status = acpi_hw_disable_gpe_block (gpe_block->xrupt_block, 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);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Remove the block on this interrupt with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_block->previous) {
gpe_block->previous->next = gpe_block->next;
- }
- else {
- gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next;
+ } else {
+ gpe_block->xrupt_block->gpe_block_list_head =
+ gpe_block->next;
}
if (gpe_block->next) {
gpe_block->next->previous = gpe_block->previous;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
/* Free the gpe_block */
- ACPI_MEM_FREE (gpe_block->register_info);
- ACPI_MEM_FREE (gpe_block->event_info);
- ACPI_MEM_FREE (gpe_block);
+ ACPI_MEM_FREE(gpe_block->register_info);
+ ACPI_MEM_FREE(gpe_block->event_info);
+ ACPI_MEM_FREE(gpe_block);
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_info_blocks
@@ -759,43 +724,41 @@ unlock_and_exit:
******************************************************************************/
static acpi_status
-acpi_ev_create_gpe_info_blocks (
- struct acpi_gpe_block_info *gpe_block)
+acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
{
- struct acpi_gpe_register_info *gpe_register_info = NULL;
- struct acpi_gpe_event_info *gpe_event_info = NULL;
- struct acpi_gpe_event_info *this_event;
- struct acpi_gpe_register_info *this_register;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_create_gpe_info_blocks");
+ struct acpi_gpe_register_info *gpe_register_info = NULL;
+ struct acpi_gpe_event_info *gpe_event_info = NULL;
+ struct acpi_gpe_event_info *this_event;
+ struct acpi_gpe_register_info *this_register;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ acpi_status status;
+ 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_MEM_CALLOCATE((acpi_size) gpe_block->
+ register_count *
+ sizeof(struct
+ acpi_gpe_register_info));
if (!gpe_register_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not allocate the gpe_register_info table\n"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not allocate the gpe_register_info table\n"));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* 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_MEM_CALLOCATE(((acpi_size) gpe_block->
+ register_count *
+ ACPI_GPE_REGISTER_WIDTH) *
+ sizeof(struct acpi_gpe_event_info));
if (!gpe_event_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not allocate the gpe_event_info table\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not allocate the gpe_event_info table\n"));
status = AE_NO_MEMORY;
goto error_exit;
}
@@ -803,7 +766,7 @@ acpi_ev_create_gpe_info_blocks (
/* Save the new Info arrays in the GPE block */
gpe_block->register_info = gpe_register_info;
- gpe_block->event_info = gpe_event_info;
+ gpe_block->event_info = gpe_event_info;
/*
* Initialize the GPE Register and Event structures. A goal of these
@@ -812,29 +775,34 @@ acpi_ev_create_gpe_info_blocks (
* and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
- this_event = gpe_event_info;
+ 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 = (u8) (gpe_block->block_base_number +
- (i * ACPI_GPE_REGISTER_WIDTH));
-
- ACPI_STORE_ADDRESS (this_register->status_address.address,
- (gpe_block->block_address.address
- + i));
-
- ACPI_STORE_ADDRESS (this_register->enable_address.address,
- (gpe_block->block_address.address
- + i
- + gpe_block->register_count));
-
- this_register->status_address.address_space_id = gpe_block->block_address.address_space_id;
- this_register->enable_address.address_space_id = gpe_block->block_address.address_space_id;
- this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
- this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
- this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
- this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
+ this_register->base_gpe_number =
+ (u8) (gpe_block->block_base_number +
+ (i * ACPI_GPE_REGISTER_WIDTH));
+
+ ACPI_STORE_ADDRESS(this_register->status_address.address,
+ (gpe_block->block_address.address + i));
+
+ ACPI_STORE_ADDRESS(this_register->enable_address.address,
+ (gpe_block->block_address.address
+ + i + gpe_block->register_count));
+
+ this_register->status_address.address_space_id =
+ gpe_block->block_address.address_space_id;
+ this_register->enable_address.address_space_id =
+ gpe_block->block_address.address_space_id;
+ this_register->status_address.register_bit_width =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->enable_address.register_bit_width =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->status_address.register_bit_offset =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->enable_address.register_bit_offset =
+ ACPI_GPE_REGISTER_WIDTH;
/* Init the event_info for each GPE within this register */
@@ -849,36 +817,36 @@ acpi_ev_create_gpe_info_blocks (
* are cleared by writing a '1', while enable registers are cleared
* by writing a '0'.
*/
- status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00,
- &this_register->enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
+ &this_register->
+ enable_address);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
- status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF,
- &this_register->status_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
+ &this_register->
+ status_address);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
this_register++;
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
if (gpe_register_info) {
- ACPI_MEM_FREE (gpe_register_info);
+ ACPI_MEM_FREE(gpe_register_info);
}
if (gpe_event_info) {
- ACPI_MEM_FREE (gpe_event_info);
+ ACPI_MEM_FREE(gpe_event_info);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_block
@@ -887,7 +855,7 @@ error_exit:
* gpe_block_address - Address and space_iD
* register_count - Number of GPE register pairs in the block
* gpe_block_base_number - Starting GPE number for the block
- * interrupt_level - H/W interrupt for the block
+ * interrupt_number - H/W interrupt for the block
* return_gpe_block - Where the new block descriptor is returned
*
* RETURN: Status
@@ -897,68 +865,66 @@ error_exit:
******************************************************************************/
acpi_status
-acpi_ev_create_gpe_block (
- struct acpi_namespace_node *gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u8 gpe_block_base_number,
- u32 interrupt_level,
- struct acpi_gpe_block_info **return_gpe_block)
+acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u8 gpe_block_base_number,
+ u32 interrupt_number,
+ struct acpi_gpe_block_info **return_gpe_block)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
- u32 wake_gpe_count;
- u32 gpe_enabled_count;
- acpi_status status;
- struct acpi_gpe_walk_info gpe_info;
-
-
- ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ u32 wake_gpe_count;
+ u32 gpe_enabled_count;
+ acpi_status status;
+ struct acpi_gpe_walk_info gpe_info;
+ ACPI_FUNCTION_TRACE("ev_create_gpe_block");
if (!register_count) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Allocate a new GPE block */
- gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
+ gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info));
if (!gpe_block) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new GPE block */
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
- gpe_block->node = gpe_device;
+ gpe_block->node = gpe_device;
- ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address,
- sizeof (struct acpi_generic_address));
+ ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
+ sizeof(struct acpi_generic_address));
/* Create the register_info and event_info sub-structures */
- status = acpi_ev_create_gpe_info_blocks (gpe_block);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (gpe_block);
- return_ACPI_STATUS (status);
+ status = acpi_ev_create_gpe_info_blocks(gpe_block);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(gpe_block);
+ return_ACPI_STATUS(status);
}
/* Install the new block in the global list(s) */
- status = acpi_ev_install_gpe_block (gpe_block, interrupt_level);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (gpe_block);
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(gpe_block);
+ return_ACPI_STATUS(status);
}
/* Find all GPE methods (_Lxx, _Exx) for this block */
- status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
- gpe_block, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ev_save_method_info, gpe_block,
+ NULL);
/*
* Runtime option: Should Wake GPEs be enabled at runtime? The default
@@ -974,9 +940,11 @@ acpi_ev_create_gpe_block (
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
- &gpe_info, NULL);
+ status =
+ acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
+ acpi_ev_match_prw_and_gpe, &gpe_info,
+ NULL);
}
/*
@@ -991,10 +959,14 @@ acpi_ev_create_gpe_block (
for (j = 0; j < 8; j++) {
/* Get the info block for this particular GPE */
- gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ gpe_event_info =
+ &gpe_block->
+ event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
- if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
- (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
+ if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_METHOD)
+ && (gpe_event_info->
+ flags & ACPI_GPE_TYPE_RUNTIME)) {
gpe_enabled_count++;
}
@@ -1006,22 +978,22 @@ acpi_ev_create_gpe_block (
/* Dump info about this GPE block */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
- (u32) gpe_block->block_base_number,
- (u32) (gpe_block->block_base_number +
- ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
- gpe_device->name.ascii,
- gpe_block->register_count,
- interrupt_level));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ (u32) gpe_block->block_base_number,
+ (u32) (gpe_block->block_base_number +
+ ((gpe_block->register_count *
+ ACPI_GPE_REGISTER_WIDTH) - 1)),
+ gpe_device->name.ascii, gpe_block->register_count,
+ interrupt_number));
/* Enable all valid GPEs found above */
- status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
+ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
- wake_gpe_count, gpe_enabled_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
+ wake_gpe_count, gpe_enabled_count));
/* Return the new block */
@@ -1029,10 +1001,9 @@ acpi_ev_create_gpe_block (
(*return_gpe_block) = gpe_block;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_initialize
@@ -1045,22 +1016,18 @@ acpi_ev_create_gpe_block (
*
******************************************************************************/
-acpi_status
-acpi_ev_gpe_initialize (
- void)
+acpi_status acpi_ev_gpe_initialize(void)
{
- u32 register_count0 = 0;
- u32 register_count1 = 0;
- u32 gpe_number_max = 0;
- acpi_status status;
+ u32 register_count0 = 0;
+ u32 register_count1 = 0;
+ 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -1088,29 +1055,29 @@ acpi_ev_gpe_initialize (
* If EITHER the register length OR the block address are zero, then that
* particular block is not supported.
*/
- if (acpi_gbl_FADT->gpe0_blk_len &&
- acpi_gbl_FADT->xgpe0_blk.address) {
+ 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);
- gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
+ gpe_number_max =
+ (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
/* Install GPE Block 0 */
- status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device,
- &acpi_gbl_FADT->xgpe0_blk, register_count0, 0,
- acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
+ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
+ &acpi_gbl_FADT->xgpe0_blk,
+ register_count0, 0,
+ acpi_gbl_FADT->sci_int,
+ &acpi_gbl_gpe_fadt_blocks[0]);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not create GPE Block 0, %s\n",
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n",
+ acpi_format_exception(status)));
}
}
- if (acpi_gbl_FADT->gpe1_blk_len &&
- acpi_gbl_FADT->xgpe1_blk.address) {
+ 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);
@@ -1118,29 +1085,26 @@ acpi_ev_gpe_initialize (
/* Check for GPE0/GPE1 overlap (if both banks exist) */
if ((register_count0) &&
- (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
- ACPI_REPORT_ERROR ((
- "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n",
- gpe_number_max, acpi_gbl_FADT->gpe1_base,
- acpi_gbl_FADT->gpe1_base +
- ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
+ (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
+ ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
/* Ignore GPE1 block by setting the register count to zero */
register_count1 = 0;
- }
- else {
+ } else {
/* Install GPE Block 1 */
- status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device,
- &acpi_gbl_FADT->xgpe1_blk, register_count1,
- acpi_gbl_FADT->gpe1_base,
- acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
-
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not create GPE Block 1, %s\n",
- acpi_format_exception (status)));
+ status =
+ acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
+ &acpi_gbl_FADT->xgpe1_blk,
+ register_count1,
+ acpi_gbl_FADT->gpe1_base,
+ acpi_gbl_FADT->sci_int,
+ &acpi_gbl_gpe_fadt_blocks
+ [1]);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status)));
}
/*
@@ -1148,7 +1112,7 @@ acpi_ev_gpe_initialize (
* space. However, GPE0 always starts at GPE number zero.
*/
gpe_number_max = acpi_gbl_FADT->gpe1_base +
- ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
+ ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
}
}
@@ -1157,8 +1121,8 @@ acpi_ev_gpe_initialize (
if ((register_count0 + register_count1) == 0) {
/* GPEs are not required by ACPI, this is OK */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "There are no GPE blocks defined in the FADT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "There are no GPE blocks defined in the FADT\n"));
status = AE_OK;
goto cleanup;
}
@@ -1166,15 +1130,12 @@ acpi_ev_gpe_initialize (
/* Check for Max GPE number out-of-range */
if (gpe_number_max > ACPI_GPE_MAX) {
- ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
- gpe_number_max));
+ ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max));
status = AE_BAD_VALUE;
goto cleanup;
}
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (AE_OK);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 659e90956112..7e57b8470f55 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -47,12 +47,10 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evmisc")
-
+ACPI_MODULE_NAME("evmisc")
#ifdef ACPI_DEBUG_OUTPUT
-static const char *acpi_notify_value_names[] =
-{
+static const char *acpi_notify_value_names[] = {
"Bus Check",
"Device Check",
"Device Wake",
@@ -66,18 +64,11 @@ static const char *acpi_notify_value_names[] =
/* Local prototypes */
-static void ACPI_SYSTEM_XFACE
-acpi_ev_notify_dispatch (
- void *context);
-
-static void ACPI_SYSTEM_XFACE
-acpi_ev_global_lock_thread (
- void *context);
+static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
-static u32
-acpi_ev_global_lock_handler (
- void *context);
+static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context);
+static u32 acpi_ev_global_lock_handler(void *context);
/*******************************************************************************
*
@@ -93,9 +84,7 @@ acpi_ev_global_lock_handler (
*
******************************************************************************/
-u8
-acpi_ev_is_notify_object (
- struct acpi_namespace_node *node)
+u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
{
switch (node->type) {
case ACPI_TYPE_DEVICE:
@@ -112,7 +101,6 @@ acpi_ev_is_notify_object (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_queue_notify_request
@@ -128,18 +116,15 @@ acpi_ev_is_notify_object (
******************************************************************************/
acpi_status
-acpi_ev_queue_notify_request (
- struct acpi_namespace_node *node,
- u32 notify_value)
+acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ u32 notify_value)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj = NULL;
- union acpi_generic_state *notify_info;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_NAME ("ev_queue_notify_request");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj = NULL;
+ union acpi_generic_state *notify_info;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_NAME("ev_queue_notify_request");
/*
* For value 3 (Ejection Request), some device method may need to be run.
@@ -148,22 +133,22 @@ acpi_ev_queue_notify_request (
* For value 0x80 (Status Change) on the power button or sleep button,
* initiate soft-off or sleep operation?
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Dispatching Notify(%X) on node %p\n", notify_value, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Dispatching Notify(%X) on node %p\n", notify_value,
+ node));
if (notify_value <= 7) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
- acpi_notify_value_names[notify_value]));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Notify value: 0x%2.2X **Device Specific**\n",
- notify_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
+ acpi_notify_value_names[notify_value]));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Notify value: 0x%2.2X **Device Specific**\n",
+ notify_value));
}
/* Get the notify object attached to the NS Node */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* We have the notify object, Get the right handler */
@@ -174,10 +159,11 @@ acpi_ev_queue_notify_request (
case ACPI_TYPE_POWER:
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
- handler_obj = obj_desc->common_notify.system_notify;
- }
- else {
- handler_obj = obj_desc->common_notify.device_notify;
+ handler_obj =
+ obj_desc->common_notify.system_notify;
+ } else {
+ handler_obj =
+ obj_desc->common_notify.device_notify;
}
break;
@@ -189,23 +175,25 @@ acpi_ev_queue_notify_request (
/* If there is any handler to run, schedule the dispatcher */
- if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
- (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) ||
- handler_obj) {
- notify_info = acpi_ut_create_generic_state ();
+ if ((acpi_gbl_system_notify.handler
+ && (notify_value <= ACPI_MAX_SYS_NOTIFY))
+ || (acpi_gbl_device_notify.handler
+ && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) {
+ notify_info = acpi_ut_create_generic_state();
if (!notify_info) {
return (AE_NO_MEMORY);
}
notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
- notify_info->notify.node = node;
- notify_info->notify.value = (u16) notify_value;
+ 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);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_generic_state (notify_info);
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
+ acpi_ev_notify_dispatch,
+ notify_info);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_generic_state(notify_info);
}
}
@@ -214,15 +202,15 @@ acpi_ev_queue_notify_request (
* There is no per-device notify handler for this device.
* This may or may not be a problem.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "No notify handler for Notify(%4.4s, %X) node %p\n",
- acpi_ut_get_node_name (node), notify_value, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No notify handler for Notify(%4.4s, %X) node %p\n",
+ acpi_ut_get_node_name(node), notify_value,
+ node));
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_notify_dispatch
@@ -236,18 +224,15 @@ acpi_ev_queue_notify_request (
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_notify_dispatch (
- void *context)
+static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
{
- union acpi_generic_state *notify_info = (union acpi_generic_state *) context;
- acpi_notify_handler global_handler = NULL;
- void *global_context = NULL;
- union acpi_operand_object *handler_obj;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_generic_state *notify_info =
+ (union acpi_generic_state *)context;
+ acpi_notify_handler global_handler = NULL;
+ void *global_context = NULL;
+ union acpi_operand_object *handler_obj;
+ ACPI_FUNCTION_ENTRY();
/*
* We will invoke a global notify handler if installed.
@@ -261,8 +246,7 @@ acpi_ev_notify_dispatch (
global_handler = acpi_gbl_system_notify.handler;
global_context = acpi_gbl_system_notify.context;
}
- }
- else {
+ } else {
/* Global driver notification handler */
if (acpi_gbl_device_notify.handler) {
@@ -274,25 +258,24 @@ acpi_ev_notify_dispatch (
/* Invoke the system handler first, if present */
if (global_handler) {
- global_handler (notify_info->notify.node, notify_info->notify.value,
- global_context);
+ global_handler(notify_info->notify.node,
+ notify_info->notify.value, global_context);
}
/* Now invoke the per-device handler, if present */
handler_obj = notify_info->notify.handler_obj;
if (handler_obj) {
- handler_obj->notify.handler (notify_info->notify.node,
- notify_info->notify.value,
- handler_obj->notify.context);
+ handler_obj->notify.handler(notify_info->notify.node,
+ notify_info->notify.value,
+ handler_obj->notify.context);
}
/* All done with the info object */
- acpi_ut_delete_generic_state (notify_info);
+ acpi_ut_delete_generic_state(notify_info);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_global_lock_thread
@@ -307,27 +290,24 @@ acpi_ev_notify_dispatch (
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_global_lock_thread (
- void *context)
+static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
{
- acpi_status status;
-
+ acpi_status status;
/* Signal threads that are waiting for the lock */
if (acpi_gbl_global_lock_thread_count) {
/* Send sufficient units to the semaphore */
- status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore,
- acpi_gbl_global_lock_thread_count);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n"));
+ status =
+ acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
+ acpi_gbl_global_lock_thread_count);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not signal Global Lock semaphore\n"));
}
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_global_lock_handler
@@ -342,20 +322,17 @@ acpi_ev_global_lock_thread (
*
******************************************************************************/
-static u32
-acpi_ev_global_lock_handler (
- void *context)
+static u32 acpi_ev_global_lock_handler(void *context)
{
- u8 acquired = FALSE;
- acpi_status status;
-
+ u8 acquired = FALSE;
+ acpi_status status;
/*
* Attempt to get the lock
* If we don't get it now, it will be marked pending and we will
* take another interrupt when it becomes free.
*/
- ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
/* Got the lock, now wake all threads waiting for it */
@@ -363,11 +340,11 @@ acpi_ev_global_lock_handler (
/* 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);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n",
- acpi_format_exception (status)));
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
+ acpi_ev_global_lock_thread,
+ context);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not queue Global Lock thread, %s\n", acpi_format_exception(status)));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
@@ -376,7 +353,6 @@ acpi_ev_global_lock_handler (
return (ACPI_INTERRUPT_HANDLED);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_init_global_lock_handler
@@ -389,19 +365,16 @@ acpi_ev_global_lock_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_init_global_lock_handler (
- void)
+acpi_status acpi_ev_init_global_lock_handler(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_init_global_lock_handler");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_init_global_lock_handler");
acpi_gbl_global_lock_present = TRUE;
- status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL,
- acpi_ev_global_lock_handler, NULL);
+ status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
+ acpi_ev_global_lock_handler,
+ NULL);
/*
* If the global lock does not exist on this platform, the attempt
@@ -411,14 +384,15 @@ acpi_ev_init_global_lock_handler (
* with an error.
*/
if (status == AE_NO_HARDWARE_RESPONSE) {
+ ACPI_REPORT_ERROR(("No response from Global Lock hardware, disabling lock\n"));
+
acpi_gbl_global_lock_present = FALSE;
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_acquire_global_lock
@@ -431,22 +405,18 @@ acpi_ev_init_global_lock_handler (
*
*****************************************************************************/
-acpi_status
-acpi_ev_acquire_global_lock (
- u16 timeout)
+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_status status = AE_OK;
+ u8 acquired = FALSE;
+ ACPI_FUNCTION_TRACE("ev_acquire_global_lock");
#ifndef ACPI_APPLICATION
/* Make sure that we actually have a global lock */
if (!acpi_gbl_global_lock_present) {
- return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
+ return_ACPI_STATUS(AE_NO_GLOBAL_LOCK);
}
#endif
@@ -459,37 +429,37 @@ acpi_ev_acquire_global_lock (
* we are done
*/
if (acpi_gbl_global_lock_acquired) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* We must acquire the actual hardware lock */
- ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
- /* We got the lock */
+ /* We got the lock */
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Acquired the HW Global Lock\n"));
acpi_gbl_global_lock_acquired = TRUE;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
* Did not get the lock. The pending bit was set above, and we must now
* wait until we get the global lock released interrupt.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
/*
* 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);
- return_ACPI_STATUS (status);
+ status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
+ timeout);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_release_global_lock
@@ -502,21 +472,16 @@ acpi_ev_acquire_global_lock (
*
******************************************************************************/
-acpi_status
-acpi_ev_release_global_lock (
- void)
+acpi_status acpi_ev_release_global_lock(void)
{
- u8 pending = FALSE;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ev_release_global_lock");
+ u8 pending = FALSE;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ev_release_global_lock");
if (!acpi_gbl_global_lock_thread_count) {
- ACPI_REPORT_WARNING((
- "Cannot release HW Global Lock, it has not been acquired\n"));
- return_ACPI_STATUS (AE_NOT_ACQUIRED);
+ ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
+ return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
/* One fewer thread has the global lock */
@@ -525,14 +490,14 @@ acpi_ev_release_global_lock (
if (acpi_gbl_global_lock_thread_count) {
/* There are still some threads holding the lock, cannot release */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
* No more threads holding lock, we can do the actual hardware
* release
*/
- ACPI_RELEASE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, pending);
+ ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
acpi_gbl_global_lock_acquired = FALSE;
/*
@@ -540,14 +505,13 @@ acpi_ev_release_global_lock (
* register
*/
if (pending) {
- status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE,
- 1, ACPI_MTX_LOCK);
+ status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
+ 1, ACPI_MTX_LOCK);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_terminate
@@ -560,16 +524,12 @@ acpi_ev_release_global_lock (
*
******************************************************************************/
-void
-acpi_ev_terminate (
- void)
+void acpi_ev_terminate(void)
{
- acpi_native_uint i;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_terminate");
+ acpi_native_uint i;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_terminate");
if (acpi_gbl_events_initialized) {
/*
@@ -580,38 +540,39 @@ acpi_ev_terminate (
/* Disable all fixed events */
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
- status = acpi_disable_event ((u32) i, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not disable fixed event %d\n", (u32) i));
+ status = acpi_disable_event((u32) i, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not disable fixed event %d\n",
+ (u32) i));
}
}
/* Disable all GPEs in all GPE blocks */
- status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
/* Remove SCI handler */
- status = acpi_ev_remove_sci_handler ();
+ status = acpi_ev_remove_sci_handler();
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not remove SCI handler\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not remove SCI handler\n"));
}
}
/* Deallocate all handler objects installed within GPE info structs */
- status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers);
/* Return to original mode if necessary */
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
- status = acpi_disable ();
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_disable failed\n"));
+ status = acpi_disable();
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "acpi_disable failed\n"));
}
}
return_VOID;
}
-
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index a1d7276c5742..84fad082d80d 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -41,39 +41,30 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evregion")
-
+ACPI_MODULE_NAME("evregion")
#define ACPI_NUM_DEFAULT_SPACES 4
-
-static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE};
+static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
/* Local prototypes */
static acpi_status
-acpi_ev_reg_run (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
static acpi_status
-acpi_ev_install_handler (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
-
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
/*******************************************************************************
*
@@ -87,19 +78,16 @@ acpi_ev_install_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_install_region_handlers (
- void) {
- acpi_status status;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
+acpi_status acpi_ev_install_region_handlers(void)
+{
+ acpi_status status;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ev_install_region_handlers");
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -121,9 +109,11 @@ acpi_ev_install_region_handlers (
* Similar for AE_SAME_HANDLER.
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
- status = acpi_ev_install_space_handler (acpi_gbl_root_node,
- acpi_gbl_default_address_spaces[i],
- ACPI_DEFAULT_HANDLER, NULL, NULL);
+ status = acpi_ev_install_space_handler(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i],
+ ACPI_DEFAULT_HANDLER,
+ NULL, NULL);
switch (status) {
case AE_OK:
case AE_SAME_HANDLER:
@@ -140,12 +130,11 @@ acpi_ev_install_region_handlers (
}
}
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_op_regions
@@ -159,20 +148,16 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ev_initialize_op_regions (
- void)
+acpi_status acpi_ev_initialize_op_regions(void)
{
- acpi_status status;
- acpi_native_uint i;
-
+ 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -182,15 +167,15 @@ acpi_ev_initialize_op_regions (
/* TBD: Make sure handler is the DEFAULT handler, otherwise
* _REG will have already been run.
*/
- status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
- acpi_gbl_default_address_spaces[i]);
+ status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i]);
}
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_method
@@ -205,26 +190,22 @@ acpi_ev_initialize_op_regions (
******************************************************************************/
acpi_status
-acpi_ev_execute_reg_method (
- union acpi_operand_object *region_obj,
- u32 function)
+acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[3];
- union acpi_operand_object *region_obj2;
- acpi_status status;
-
+ struct acpi_parameter_info info;
+ union acpi_operand_object *params[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);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
if (region_obj2->extra.method_REG == NULL) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -237,12 +218,12 @@ acpi_ev_execute_reg_method (
* 0 for disconnecting the handler
* Passed as a parameter
*/
- params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[0]) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[1]) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -260,19 +241,18 @@ acpi_ev_execute_reg_method (
/* 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_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_METHOD, info.node, NULL));
+ status = acpi_ns_evaluate_by_handle(&info);
- acpi_ut_remove_reference (params[1]);
+ acpi_ut_remove_reference(params[1]);
-cleanup:
- acpi_ut_remove_reference (params[0]);
+ cleanup:
+ acpi_ut_remove_reference(params[0]);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_address_space_dispatch
@@ -291,40 +271,38 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ev_address_space_dispatch (
- union acpi_operand_object *region_obj,
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- void *value)
+acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ u32 function,
+ acpi_physical_address address,
+ u32 bit_width, void *value)
{
- acpi_status status;
- acpi_status status2;
- acpi_adr_space_handler handler;
- acpi_adr_space_setup region_setup;
- union acpi_operand_object *handler_desc;
- union acpi_operand_object *region_obj2;
- void *region_context = NULL;
+ acpi_status status;
+ acpi_status status2;
+ acpi_adr_space_handler handler;
+ acpi_adr_space_setup region_setup;
+ union acpi_operand_object *handler_desc;
+ 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);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Ensure that there is a handler associated with this region */
handler_desc = region_obj->region.handler;
if (!handler_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No handler for Region [%4.4s] (%p) [%s]\n",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
-
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No handler for Region [%4.4s] (%p) [%s]\n",
+ acpi_ut_get_node_name(region_obj->region.
+ node), region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
+
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -339,10 +317,13 @@ acpi_ev_address_space_dispatch (
if (!region_setup) {
/* No initialization routine, exit with error */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No init routine for region(%p) [%s]\n",
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No init routine for region(%p) [%s]\n",
+ region_obj,
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -350,25 +331,29 @@ acpi_ev_address_space_dispatch (
* setup will potentially execute control methods
* (e.g., _REG method for this region)
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
- handler_desc->address_space.context, &region_context);
+ status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
+ handler_desc->address_space.context,
+ &region_context);
/* Re-enter the interpreter */
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
/* Check for failure of the Region Setup */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region Init: %s [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
+ return_ACPI_STATUS(status);
}
/*
@@ -380,14 +365,14 @@ acpi_ev_address_space_dispatch (
if (region_obj2->extra.region_context) {
/* The handler for this region was already installed */
- ACPI_MEM_FREE (region_context);
- }
- else {
+ ACPI_MEM_FREE(region_context);
+ } else {
/*
* Save the returned context for use in all accesses to
* this particular region
*/
- region_obj2->extra.region_context = region_context;
+ region_obj2->extra.region_context =
+ region_context;
}
}
}
@@ -396,13 +381,16 @@ acpi_ev_address_space_dispatch (
handler = handler_desc->address_space.handler;
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
- &region_obj->region.handler->address_space, handler,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ &region_obj->region.handler->address_space, handler,
+ ACPI_FORMAT_UINT64(address),
+ 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.
+ hflags & 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
@@ -413,31 +401,33 @@ acpi_ev_address_space_dispatch (
/* Call the handler */
- status = handler (function, address, bit_width, value,
+ status = handler(function, address, bit_width, value,
handler_desc->address_space.context,
region_obj2->extra.region_context);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
- acpi_ut_get_region_name (region_obj->region.space_id),
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Handler for [%s] returned %s\n",
+ acpi_ut_get_region_name(region_obj->region.
+ space_id),
+ acpi_format_exception(status)));
}
- if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+ if (!
+ (handler_desc->address_space.
+ hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_detach_region
@@ -453,23 +443,20 @@ acpi_ev_address_space_dispatch (
******************************************************************************/
void
-acpi_ev_detach_region(
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_detach_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object **last_obj_ptr;
- acpi_adr_space_setup region_setup;
- void **region_context;
- union acpi_operand_object *region_obj2;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_detach_region");
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object **last_obj_ptr;
+ acpi_adr_space_setup region_setup;
+ void **region_context;
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_detach_region");
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_VOID;
}
@@ -493,34 +480,39 @@ acpi_ev_detach_region(
/* Is this the correct Region? */
if (obj_desc == region_obj) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Removing Region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Removing Region %p from address handler %p\n",
+ region_obj, handler_obj));
/* This is it, remove it from the handler's list */
*last_obj_ptr = obj_desc->region.next;
- obj_desc->region.next = NULL; /* Must clear field */
+ obj_desc->region.next = NULL; /* Must clear field */
if (acpi_ns_is_locked) {
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Now stop region accesses by executing the _REG method */
- status = acpi_ev_execute_reg_method (region_obj, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ status = acpi_ev_execute_reg_method(region_obj, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s from region _REG, [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name
+ (region_obj->region.
+ space_id)));
}
if (acpi_ns_is_locked) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
@@ -528,15 +520,20 @@ acpi_ev_detach_region(
/* Call the setup handler with the deactivate notification */
region_setup = handler_obj->address_space.setup;
- status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
- handler_obj->address_space.context, region_context);
+ status =
+ region_setup(region_obj, ACPI_REGION_DEACTIVATE,
+ handler_obj->address_space.context,
+ region_context);
/* Init routine may fail, Just ignore errors */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s from region init, [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name
+ (region_obj->region.
+ space_id)));
}
region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
@@ -552,7 +549,7 @@ acpi_ev_detach_region(
* this better be the region's handler
*/
region_obj->region.handler = NULL;
- acpi_ut_remove_reference (handler_obj);
+ acpi_ut_remove_reference(handler_obj);
return_VOID;
}
@@ -565,14 +562,13 @@ acpi_ev_detach_region(
/* If we get here, the region was not in the handler's region list */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Cannot remove region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Cannot remove region %p from address handler %p\n",
+ region_obj, handler_obj));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_attach_region
@@ -589,20 +585,19 @@ acpi_ev_detach_region(
******************************************************************************/
acpi_status
-acpi_ev_attach_region (
- union acpi_operand_object *handler_obj,
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_attach_region(union acpi_operand_object *handler_obj,
+ union acpi_operand_object *region_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",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, handler_obj,
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Adding Region [%4.4s] %p to address handler %p [%s]\n",
+ acpi_ut_get_node_name(region_obj->region.node),
+ region_obj, handler_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
/* Link this region to the front of the handler's list */
@@ -612,16 +607,15 @@ acpi_ev_attach_region (
/* Install the region's handler */
if (region_obj->region.handler) {
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
region_obj->region.handler = handler_obj;
- acpi_ut_add_reference (handler_obj);
+ acpi_ut_add_reference(handler_obj);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_handler
@@ -640,23 +634,18 @@ acpi_ev_attach_region (
******************************************************************************/
static acpi_status
-acpi_ev_install_handler (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *next_handler_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *next_handler_obj;
+ union acpi_operand_object *obj_desc;
+ 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;
+ handler_obj = (union acpi_operand_object *)context;
/* Parameter validation */
@@ -666,7 +655,7 @@ acpi_ev_install_handler (
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
@@ -676,14 +665,13 @@ acpi_ev_install_handler (
* that are allowed to have address space handlers
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
- (node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
@@ -692,18 +680,22 @@ acpi_ev_install_handler (
/* Devices are handled different than regions */
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
+ 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 == handler_obj->address_space.space_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) handler %p\n",
- acpi_ut_get_region_name (handler_obj->address_space.space_id),
- obj_desc, next_handler_obj, handler_obj));
+ if (next_handler_obj->address_space.space_id ==
+ handler_obj->address_space.space_id) {
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) handler %p\n",
+ acpi_ut_get_region_name
+ (handler_obj->address_space.
+ space_id), obj_desc,
+ next_handler_obj,
+ handler_obj));
/*
* Since the object we found it on was a device, then it
@@ -744,15 +736,14 @@ acpi_ev_install_handler (
*
* First disconnect region for any previous handler (if any)
*/
- acpi_ev_detach_region (obj_desc, FALSE);
+ acpi_ev_detach_region(obj_desc, FALSE);
/* Connect the region to the new handler */
- status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
+ status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_space_handler
@@ -771,32 +762,27 @@ acpi_ev_install_handler (
******************************************************************************/
acpi_status
-acpi_ev_install_space_handler (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context)
+acpi_ev_install_space_handler(struct acpi_namespace_node * node,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj;
- acpi_status status;
- acpi_object_type type;
- u16 flags = 0;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_space_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ acpi_status status;
+ acpi_object_type type;
+ u16 flags = 0;
+ ACPI_FUNCTION_TRACE("ev_install_space_handler");
/*
* This registration is valid for only the types below
* and the root. This is where the default handlers
* get placed.
*/
- if ((node->type != ACPI_TYPE_DEVICE) &&
- (node->type != ACPI_TYPE_PROCESSOR) &&
- (node->type != ACPI_TYPE_THERMAL) &&
- (node != acpi_gbl_root_node)) {
+ if ((node->type != ACPI_TYPE_DEVICE) &&
+ (node->type != ACPI_TYPE_PROCESSOR) &&
+ (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
@@ -807,32 +793,32 @@ acpi_ev_install_space_handler (
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
handler = acpi_ex_system_memory_space_handler;
- setup = acpi_ev_system_memory_region_setup;
+ setup = acpi_ev_system_memory_region_setup;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
handler = acpi_ex_system_io_space_handler;
- setup = acpi_ev_io_space_region_setup;
+ setup = acpi_ev_io_space_region_setup;
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
handler = acpi_ex_pci_config_space_handler;
- setup = acpi_ev_pci_config_region_setup;
+ setup = acpi_ev_pci_config_region_setup;
break;
case ACPI_ADR_SPACE_CMOS:
handler = acpi_ex_cmos_space_handler;
- setup = acpi_ev_cmos_region_setup;
+ setup = acpi_ev_cmos_region_setup;
break;
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
handler = acpi_ex_pci_bar_space_handler;
- setup = acpi_ev_pci_bar_region_setup;
+ setup = acpi_ev_pci_bar_region_setup;
break;
case ACPI_ADR_SPACE_DATA_TABLE:
handler = acpi_ex_data_table_space_handler;
- setup = NULL;
+ setup = NULL;
break;
default:
@@ -849,7 +835,7 @@ acpi_ev_install_space_handler (
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/*
* The attached device object already exists.
@@ -863,7 +849,8 @@ acpi_ev_install_space_handler (
/* Same space_id indicates a handler already installed */
if (handler_obj->address_space.space_id == space_id) {
- if (handler_obj->address_space.handler == handler) {
+ if (handler_obj->address_space.handler ==
+ handler) {
/*
* It is (relatively) OK to attempt to install the SAME
* handler twice. This can easily happen
@@ -871,8 +858,7 @@ acpi_ev_install_space_handler (
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
- }
- else {
+ } else {
/* A handler is already installed */
status = AE_ALREADY_EXISTS;
@@ -884,21 +870,20 @@ acpi_ev_install_space_handler (
handler_obj = handler_obj->address_space.next;
}
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Creating object on Device %p while installing handler\n", node));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Creating object on Device %p while installing handler\n",
+ node));
/* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
- }
- else {
+ } else {
type = node->type;
}
- obj_desc = acpi_ut_create_internal_object (type);
+ obj_desc = acpi_ut_create_internal_object(type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -910,21 +895,21 @@ acpi_ev_install_space_handler (
/* Attach the new object to the Node */
- status = acpi_ns_attach_object (node, obj_desc, type);
+ status = acpi_ns_attach_object(node, obj_desc, type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
- acpi_ut_get_region_name (space_id), space_id,
- acpi_ut_get_node_name (node), node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ acpi_ut_get_region_name(space_id), space_id,
+ acpi_ut_get_node_name(node), node, obj_desc));
/*
* Install the handler
@@ -933,7 +918,8 @@ acpi_ev_install_space_handler (
* Just allocate the object for the handler and link it
* into the list.
*/
- handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+ handler_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -941,17 +927,17 @@ acpi_ev_install_space_handler (
/* Init handler obj */
- handler_obj->address_space.space_id = (u8) space_id;
- handler_obj->address_space.hflags = flags;
+ handler_obj->address_space.space_id = (u8) space_id;
+ handler_obj->address_space.hflags = flags;
handler_obj->address_space.region_list = NULL;
- handler_obj->address_space.node = node;
- handler_obj->address_space.handler = handler;
- handler_obj->address_space.context = context;
- handler_obj->address_space.setup = setup;
+ handler_obj->address_space.node = node;
+ handler_obj->address_space.handler = handler;
+ handler_obj->address_space.context = context;
+ handler_obj->address_space.setup = setup;
/* Install at head of Device.address_space list */
- handler_obj->address_space.next = obj_desc->device.handler;
+ handler_obj->address_space.next = obj_desc->device.handler;
/*
* The Device object is the first reference on the handler_obj.
@@ -971,15 +957,15 @@ acpi_ev_install_space_handler (
* In either case, back up and search down the remainder
* of the branch
*/
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
- handler_obj, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK,
+ acpi_ev_install_handler, handler_obj,
+ NULL);
-unlock_and_exit:
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_methods
@@ -995,15 +981,12 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ev_execute_reg_methods (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id)
+acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_execute_reg_methods");
/*
* Run all _REG methods for all Operation Regions for this
@@ -1012,14 +995,13 @@ acpi_ev_execute_reg_methods (
* must be installed for all regions of this Space ID before we
* can run any _REG methods)
*/
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
- &space_id, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
+ &space_id, NULL);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_reg_run
@@ -1031,23 +1013,19 @@ acpi_ev_execute_reg_methods (
******************************************************************************/
static acpi_status
-acpi_ev_reg_run (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_adr_space_type space_id;
- acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_adr_space_type space_id;
+ acpi_status status;
-
- space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
+ space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context);
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
@@ -1056,14 +1034,13 @@ acpi_ev_reg_run (
* We only care about regions.and objects
* that are allowed to have address space handlers
*/
- if ((node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
@@ -1080,7 +1057,6 @@ acpi_ev_reg_run (
return (AE_OK);
}
- status = acpi_ev_execute_reg_method (obj_desc, 1);
+ status = acpi_ev_execute_reg_method(obj_desc, 1);
return (status);
}
-
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 95bc09c73a6a..a1bd2da27c45 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -41,14 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evrgnini")
-
+ACPI_MODULE_NAME("evrgnini")
/*******************************************************************************
*
@@ -64,34 +62,31 @@
* DESCRIPTION: Setup a system_memory operation region
*
******************************************************************************/
-
acpi_status
-acpi_ev_system_memory_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_system_memory_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- union acpi_operand_object *region_desc = (union acpi_operand_object *) handle;
- struct acpi_mem_space_context *local_region_context;
-
-
- ACPI_FUNCTION_TRACE ("ev_system_memory_region_setup");
+ union acpi_operand_object *region_desc =
+ (union acpi_operand_object *)handle;
+ struct acpi_mem_space_context *local_region_context;
+ ACPI_FUNCTION_TRACE("ev_system_memory_region_setup");
if (function == ACPI_REGION_DEACTIVATE) {
if (*region_context) {
- ACPI_MEM_FREE (*region_context);
+ ACPI_MEM_FREE(*region_context);
*region_context = NULL;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Create a new context */
- local_region_context = ACPI_MEM_CALLOCATE (sizeof (struct acpi_mem_space_context));
+ local_region_context =
+ ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context));
if (!(local_region_context)) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the region length and address for use in the handler */
@@ -100,10 +95,9 @@ acpi_ev_system_memory_region_setup (
local_region_context->address = region_desc->region.address;
*region_context = local_region_context;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_io_space_region_setup
@@ -120,26 +114,21 @@ acpi_ev_system_memory_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_io_space_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+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;
- }
- else {
+ } else {
*region_context = handler_context;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_config_region_setup
@@ -158,24 +147,21 @@ acpi_ev_io_space_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_pci_config_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_pci_config_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- acpi_status status = AE_OK;
- acpi_integer pci_value;
- struct acpi_pci_id *pci_id = *region_context;
- union acpi_operand_object *handler_obj;
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *pci_root_node;
- union acpi_operand_object *region_obj = (union acpi_operand_object *) handle;
- struct acpi_device_id object_hID;
-
-
- ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup");
-
+ acpi_status status = AE_OK;
+ acpi_integer pci_value;
+ struct acpi_pci_id *pci_id = *region_context;
+ union acpi_operand_object *handler_obj;
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *pci_root_node;
+ union acpi_operand_object *region_obj =
+ (union acpi_operand_object *)handle;
+ struct acpi_device_id object_hID;
+
+ ACPI_FUNCTION_TRACE("ev_pci_config_region_setup");
handler_obj = region_obj->region.handler;
if (!handler_obj) {
@@ -183,20 +169,21 @@ acpi_ev_pci_config_region_setup (
* No installed handler. This shouldn't happen because the dispatch
* routine checks before we get here, but we check again just in case.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Attempting to init a region %p, with no handler\n", region_obj));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Attempting to init a region %p, with no handler\n",
+ region_obj));
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
*region_context = NULL;
if (function == ACPI_REGION_DEACTIVATE) {
if (pci_id) {
- ACPI_MEM_FREE (pci_id);
+ ACPI_MEM_FREE(pci_id);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- parent_node = acpi_ns_get_parent_node (region_obj->region.node);
+ parent_node = acpi_ns_get_parent_node(region_obj->region.node);
/*
* Get the _SEG and _BBN values from the device upon which the handler
@@ -216,18 +203,28 @@ acpi_ev_pci_config_region_setup (
pci_root_node = parent_node;
while (pci_root_node != acpi_gbl_root_node) {
- status = acpi_ut_execute_HID (pci_root_node, &object_hID);
- if (ACPI_SUCCESS (status)) {
- /* Got a valid _HID, check if this is a PCI root */
-
- if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING,
- sizeof (PCI_ROOT_HID_STRING)))) {
+ status =
+ acpi_ut_execute_HID(pci_root_node, &object_hID);
+ if (ACPI_SUCCESS(status)) {
+ /*
+ * Got a valid _HID string, check if this is a PCI root.
+ * New for ACPI 3.0: check for a PCI Express root also.
+ */
+ if (!
+ (ACPI_STRNCMP
+ (object_hID.value, PCI_ROOT_HID_STRING,
+ sizeof(PCI_ROOT_HID_STRING))
+ ||
+ !(ACPI_STRNCMP
+ (object_hID.value,
+ PCI_EXPRESS_ROOT_HID_STRING,
+ sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
+ {
/* Install a handler for this PCI root bridge */
- status = acpi_install_address_space_handler ((acpi_handle) pci_root_node,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
if (status == AE_SAME_HANDLER) {
/*
* It is OK if the handler is already installed on the root
@@ -235,23 +232,19 @@ acpi_ev_pci_config_region_setup (
* new PCI_Config operation region, however.
*/
status = AE_OK;
- }
- else {
- ACPI_REPORT_ERROR ((
- "Could not install pci_config handler for Root Bridge %4.4s, %s\n",
- acpi_ut_get_node_name (pci_root_node), acpi_format_exception (status)));
+ } else {
+ ACPI_REPORT_ERROR(("Could not install pci_config handler for Root Bridge %4.4s, %s\n", acpi_ut_get_node_name(pci_root_node), acpi_format_exception(status)));
}
}
break;
}
}
- pci_root_node = acpi_ns_get_parent_node (pci_root_node);
+ pci_root_node = acpi_ns_get_parent_node(pci_root_node);
}
/* PCI root bridge not found, use namespace root node */
- }
- else {
+ } else {
pci_root_node = handler_obj->address_space.node;
}
@@ -260,14 +253,14 @@ acpi_ev_pci_config_region_setup (
* (install_address_space_handler could have initialized it)
*/
if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Region is still not initialized. Create a new context */
- pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id));
+ pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id));
if (!pci_id) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -279,40 +272,45 @@ acpi_ev_pci_config_region_setup (
* Get the PCI device and function numbers from the _ADR object
* contained in the parent's scope.
*/
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node,
+ &pci_value);
/*
* The default is zero, and since the allocation above zeroed
* the data, just do nothing on failure.
*/
- if (ACPI_SUCCESS (status)) {
- pci_id->device = ACPI_HIWORD (ACPI_LODWORD (pci_value));
- pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value));
+ if (ACPI_SUCCESS(status)) {
+ pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
+ pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
}
/* The PCI segment number comes from the _SEG method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value);
- if (ACPI_SUCCESS (status)) {
- pci_id->segment = ACPI_LOWORD (pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node,
+ &pci_value);
+ if (ACPI_SUCCESS(status)) {
+ pci_id->segment = ACPI_LOWORD(pci_value);
}
/* The PCI bus number comes from the _BBN method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value);
- if (ACPI_SUCCESS (status)) {
- pci_id->bus = ACPI_LOWORD (pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node,
+ &pci_value);
+ if (ACPI_SUCCESS(status)) {
+ pci_id->bus = ACPI_LOWORD(pci_value);
}
/* Complete this device's pci_id */
- acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id);
+ acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);
*region_context = pci_id;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_bar_region_setup
@@ -331,19 +329,15 @@ acpi_ev_pci_config_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_pci_bar_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+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);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_cmos_region_setup
@@ -362,19 +356,15 @@ acpi_ev_pci_bar_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_cmos_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+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);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_default_region_setup
@@ -391,26 +381,21 @@ acpi_ev_cmos_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_default_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+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;
- }
- else {
+ } else {
*region_context = handler_context;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_region
@@ -434,37 +419,34 @@ acpi_ev_default_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_initialize_region (
- union acpi_operand_object *region_obj,
- u8 acpi_ns_locked)
+acpi_ev_initialize_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_locked)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *obj_desc;
- acpi_adr_space_type space_id;
- struct acpi_namespace_node *node;
- acpi_status status;
- struct acpi_namespace_node *method_node;
- 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);
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *obj_desc;
+ acpi_adr_space_type space_id;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ struct acpi_namespace_node *method_node;
+ 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);
if (!region_obj) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- node = acpi_ns_get_parent_node (region_obj->region.node);
+ node = acpi_ns_get_parent_node(region_obj->region.node);
space_id = region_obj->region.space_id;
/* Setup defaults */
@@ -476,9 +458,9 @@ acpi_ev_initialize_region (
/* Find any "_REG" method associated with this region definition */
- status = acpi_ns_search_node (*reg_name_ptr, node,
- ACPI_TYPE_METHOD, &method_node);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_search_node(*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
* definition. This will be executed when the handler is attached
@@ -495,7 +477,7 @@ acpi_ev_initialize_region (
/* Check to see if a handler exists */
handler_obj = NULL;
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* Can only be a handler if the object exists */
@@ -523,37 +505,50 @@ acpi_ev_initialize_region (
while (handler_obj) {
/* Is this handler of the correct type? */
- if (handler_obj->address_space.space_id == space_id) {
+ if (handler_obj->address_space.space_id ==
+ space_id) {
/* Found correct handler */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler %p for region %p in obj %p\n",
- handler_obj, region_obj, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler %p for region %p in obj %p\n",
+ handler_obj,
+ region_obj,
+ obj_desc));
- status = acpi_ev_attach_region (handler_obj, region_obj,
- acpi_ns_locked);
+ status =
+ acpi_ev_attach_region(handler_obj,
+ region_obj,
+ acpi_ns_locked);
/*
* Tell all users that this region is usable by running the _REG
* method
*/
if (acpi_ns_locked) {
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_release_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS
+ (status);
}
}
- status = acpi_ev_execute_reg_method (region_obj, 1);
+ status =
+ acpi_ev_execute_reg_method
+ (region_obj, 1);
if (acpi_ns_locked) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_acquire_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS
+ (status);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Try next handler in the list */
@@ -566,15 +561,15 @@ acpi_ev_initialize_region (
* This node does not have the handler we need;
* Pop up one level
*/
- node = acpi_ns_get_parent_node (node);
+ node = acpi_ns_get_parent_node(node);
}
/* 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",
- acpi_ut_get_region_name (space_id), space_id, region_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "No handler for region_type %s(%X) (region_obj %p)\n",
+ acpi_ut_get_region_name(space_id), space_id,
+ region_obj));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
-
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index f3123c26ae98..141835977002 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -45,16 +45,11 @@
#include <acpi/acpi.h>
#include <acpi/acevents.h>
-
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evsci")
+ACPI_MODULE_NAME("evsci")
/* Local prototypes */
-
-static u32 ACPI_SYSTEM_XFACE
-acpi_ev_sci_xrupt_handler (
- void *context);
-
+static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
/*******************************************************************************
*
@@ -69,17 +64,13 @@ acpi_ev_sci_xrupt_handler (
*
******************************************************************************/
-static u32 ACPI_SYSTEM_XFACE
-acpi_ev_sci_xrupt_handler (
- void *context)
+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;
-
+ struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
+ u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
-
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
@@ -89,18 +80,17 @@ acpi_ev_sci_xrupt_handler (
* Fixed Events:
* Check for and dispatch any Fixed Events that have occurred
*/
- interrupt_handled |= acpi_ev_fixed_event_detect ();
+ interrupt_handled |= acpi_ev_fixed_event_detect();
/*
* General Purpose Events:
* Check for and dispatch any GPEs that have occurred
*/
- interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
+ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE (interrupt_handled);
+ return_VALUE(interrupt_handled);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_xrupt_handler
@@ -113,17 +103,13 @@ acpi_ev_sci_xrupt_handler (
*
******************************************************************************/
-u32 ACPI_SYSTEM_XFACE
-acpi_ev_gpe_xrupt_handler (
- void *context)
+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;
-
+ struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
+ u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
-
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
@@ -133,12 +119,11 @@ acpi_ev_gpe_xrupt_handler (
* GPEs:
* Check for and dispatch any GPEs that have occurred
*/
- interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
+ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE (interrupt_handled);
+ return_VALUE(interrupt_handled);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_install_sci_handler
@@ -151,22 +136,18 @@ acpi_ev_gpe_xrupt_handler (
*
******************************************************************************/
-u32
-acpi_ev_install_sci_handler (
- void)
+u32 acpi_ev_install_sci_handler(void)
{
- u32 status = AE_OK;
-
+ 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, acpi_gbl_gpe_xrupt_list_head);
- return_ACPI_STATUS (status);
+ status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
+ acpi_ev_sci_xrupt_handler,
+ acpi_gbl_gpe_xrupt_list_head);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_remove_sci_handler
@@ -186,22 +167,16 @@ acpi_ev_install_sci_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_remove_sci_handler (
- void)
+acpi_status acpi_ev_remove_sci_handler(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_remove_sci_handler");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_remove_sci_handler");
/* Just let the OS remove the handler and disable the level */
- status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
- acpi_ev_sci_xrupt_handler);
+ status = acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
+ acpi_ev_sci_xrupt_handler);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 4092d47f6758..43b33d19cdf9 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -49,8 +49,7 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxface")
-
+ACPI_MODULE_NAME("evxface")
/*******************************************************************************
*
@@ -64,21 +63,16 @@
* DESCRIPTION: Saves the pointer to the handler function
*
******************************************************************************/
-
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_install_exception_handler (
- acpi_exception_handler handler)
+acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
{
- acpi_status status;
-
+ 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
@@ -92,12 +86,11 @@ acpi_install_exception_handler (
acpi_gbl_exception_handler = handler;
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -116,26 +109,22 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_install_fixed_event_handler (
- u32 event,
- acpi_event_handler handler,
- void *context)
+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_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler");
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
@@ -150,29 +139,29 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
- status = acpi_clear_event (event);
+ status = acpi_clear_event(event);
if (ACPI_SUCCESS(status))
- status = acpi_enable_event (event, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
+ status = acpi_enable_event(event, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Could not enable fixed event.\n"));
/* Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Enabled fixed event %X, Handler=%p\n", event, handler));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Enabled fixed event %X, Handler=%p\n", event,
+ handler));
}
-
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_fixed_event_handler);
+EXPORT_SYMBOL(acpi_install_fixed_event_handler);
/*******************************************************************************
*
@@ -188,49 +177,45 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler);
******************************************************************************/
acpi_status
-acpi_remove_fixed_event_handler (
- u32 event,
- acpi_event_handler handler)
+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_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler");
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Disable the event before removing the handler */
- status = acpi_disable_event (event, 0);
+ status = acpi_disable_event(event, 0);
/* Always Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
- "Could not write to fixed event enable register.\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Could not write to fixed event enable register.\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X.\n",
+ event));
}
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
+EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
/*******************************************************************************
*
@@ -251,37 +236,32 @@ EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
******************************************************************************/
acpi_status
-acpi_install_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler,
- void *context)
+acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler handler, void *context)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *notify_obj;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_notify_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *notify_obj;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_notify_handler");
/* Parameter validation */
- if ((!device) ||
- (!handler) ||
- (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device) ||
+ (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -297,21 +277,21 @@ acpi_install_notify_handler (
/* Make sure the handler is not already installed */
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
- acpi_gbl_system_notify.handler) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- acpi_gbl_device_notify.handler)) {
+ acpi_gbl_system_notify.handler) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ acpi_gbl_device_notify.handler)) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
if (handler_type & ACPI_SYSTEM_NOTIFY) {
- acpi_gbl_system_notify.node = node;
+ acpi_gbl_system_notify.node = node;
acpi_gbl_system_notify.handler = handler;
acpi_gbl_system_notify.context = context;
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
- acpi_gbl_device_notify.node = node;
+ acpi_gbl_device_notify.node = node;
acpi_gbl_device_notify.handler = handler;
acpi_gbl_device_notify.context = context;
}
@@ -327,29 +307,28 @@ acpi_install_notify_handler (
else {
/* Notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
+ if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE;
goto unlock_and_exit;
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ 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) &&
- obj_desc->common_notify.system_notify) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- obj_desc->common_notify.device_notify)) {
+ obj_desc->common_notify.system_notify) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ obj_desc->common_notify.device_notify)) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Create a new object */
- obj_desc = acpi_ut_create_internal_object (node->type);
+ obj_desc = acpi_ut_create_internal_object(node->type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -357,25 +336,27 @@ acpi_install_notify_handler (
/* Attach new object to the Node */
- status = acpi_ns_attach_object (device, obj_desc, node->type);
+ status =
+ acpi_ns_attach_object(device, obj_desc, node->type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- if (ACPI_FAILURE (status)) {
+ acpi_ut_remove_reference(obj_desc);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
/* Install the handler */
- notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY);
+ notify_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
if (!notify_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- notify_obj->notify.node = node;
+ notify_obj->notify.node = node;
notify_obj->notify.handler = handler;
notify_obj->notify.context = context;
@@ -390,17 +371,16 @@ acpi_install_notify_handler (
if (handler_type == ACPI_ALL_NOTIFY) {
/* Extra ref if installed in both */
- acpi_ut_add_reference (notify_obj);
+ acpi_ut_add_reference(notify_obj);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_notify_handler);
+EXPORT_SYMBOL(acpi_install_notify_handler);
/*******************************************************************************
*
@@ -420,36 +400,31 @@ EXPORT_SYMBOL(acpi_install_notify_handler);
******************************************************************************/
acpi_status
-acpi_remove_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler)
+acpi_remove_notify_handler(acpi_handle device,
+ u32 handler_type, acpi_notify_handler handler)
{
- union acpi_operand_object *notify_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler");
+ union acpi_operand_object *notify_obj;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
/* Parameter validation */
- if ((!device) ||
- (!handler) ||
- (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device) ||
+ (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -458,34 +433,34 @@ acpi_remove_notify_handler (
/* Root Object */
if (device == ACPI_ROOT_OBJECT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Removing notify handler for ROOT object.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Removing notify handler for ROOT object.\n"));
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
- !acpi_gbl_system_notify.handler) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- !acpi_gbl_device_notify.handler)) {
+ !acpi_gbl_system_notify.handler) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ !acpi_gbl_device_notify.handler)) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
if (handler_type & ACPI_SYSTEM_NOTIFY) {
- acpi_gbl_system_notify.node = NULL;
+ acpi_gbl_system_notify.node = NULL;
acpi_gbl_system_notify.handler = NULL;
acpi_gbl_system_notify.context = NULL;
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
- acpi_gbl_device_notify.node = NULL;
+ acpi_gbl_device_notify.node = NULL;
acpi_gbl_device_notify.handler = NULL;
acpi_gbl_device_notify.context = NULL;
}
@@ -496,14 +471,14 @@ acpi_remove_notify_handler (
else {
/* Notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
+ if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE;
goto unlock_and_exit;
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
@@ -514,53 +489,52 @@ acpi_remove_notify_handler (
if (handler_type & ACPI_SYSTEM_NOTIFY) {
notify_obj = obj_desc->common_notify.system_notify;
if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ (notify_obj->notify.handler != handler)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
obj_desc->common_notify.system_notify = NULL;
- acpi_ut_remove_reference (notify_obj);
+ acpi_ut_remove_reference(notify_obj);
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
notify_obj = obj_desc->common_notify.device_notify;
if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ (notify_obj->notify.handler != handler)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
obj_desc->common_notify.device_notify = NULL;
- acpi_ut_remove_reference (notify_obj);
+ acpi_ut_remove_reference(notify_obj);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_notify_handler);
+EXPORT_SYMBOL(acpi_remove_notify_handler);
/*******************************************************************************
*
@@ -581,35 +555,31 @@ EXPORT_SYMBOL(acpi_remove_notify_handler);
******************************************************************************/
acpi_status
-acpi_install_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 type,
- acpi_event_handler address,
- void *context)
+acpi_install_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number,
+ u32 type, acpi_event_handler address, void *context)
{
- struct acpi_gpe_event_info *gpe_event_info;
- struct acpi_handler_info *handler;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
/* Parameter validation */
if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -617,49 +587,49 @@ acpi_install_gpe_handler (
/* Make sure that there isn't a handler there already */
- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
+ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_HANDLER) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
/* Allocate and init handler object */
- handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
+ handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
if (!handler) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- handler->address = address;
- handler->context = context;
+ handler->address = address;
+ handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
/* Disable the GPE before installing the handler */
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Install the handler */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
gpe_event_info->dispatch.handler = handler;
/* Setup up dispatch flags to indicate handler (vs. method) */
- gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
+ gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_handler);
+EXPORT_SYMBOL(acpi_install_gpe_handler);
/*******************************************************************************
*
@@ -677,33 +647,30 @@ EXPORT_SYMBOL(acpi_install_gpe_handler);
******************************************************************************/
acpi_status
-acpi_remove_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- acpi_event_handler address)
+acpi_remove_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number, acpi_event_handler address)
{
- struct acpi_gpe_event_info *gpe_event_info;
- struct acpi_handler_info *handler;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
/* Parameter validation */
if (!address) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -711,7 +678,8 @@ acpi_remove_gpe_handler (
/* Make sure that a handler is indeed installed */
- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
+ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
+ ACPI_GPE_DISPATCH_HANDLER) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
@@ -725,45 +693,44 @@ acpi_remove_gpe_handler (
/* Disable the GPE before removing the handler */
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
handler = gpe_event_info->dispatch.handler;
/* Restore Method node (if any), set dispatch flags */
gpe_event_info->dispatch.method_node = handler->method_node;
- gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
+ gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
if (handler->method_node) {
gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Now we can free the handler object */
- ACPI_MEM_FREE (handler);
+ ACPI_MEM_FREE(handler);
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_gpe_handler);
+EXPORT_SYMBOL(acpi_remove_gpe_handler);
/*******************************************************************************
*
@@ -779,35 +746,31 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler);
*
******************************************************************************/
-acpi_status
-acpi_acquire_global_lock (
- u16 timeout,
- u32 *handle)
+acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
{
- acpi_status status;
-
+ acpi_status status;
if (!handle) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
return (status);
}
- status = acpi_ev_acquire_global_lock (timeout);
- acpi_ex_exit_interpreter ();
+ status = acpi_ev_acquire_global_lock(timeout);
+ acpi_ex_exit_interpreter();
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
acpi_gbl_global_lock_handle++;
*handle = acpi_gbl_global_lock_handle;
}
return (status);
}
-EXPORT_SYMBOL(acpi_acquire_global_lock);
+EXPORT_SYMBOL(acpi_acquire_global_lock);
/*******************************************************************************
*
@@ -821,19 +784,16 @@ EXPORT_SYMBOL(acpi_acquire_global_lock);
*
******************************************************************************/
-acpi_status
-acpi_release_global_lock (
- u32 handle)
+acpi_status acpi_release_global_lock(u32 handle)
{
- acpi_status status;
-
+ acpi_status status;
if (handle != acpi_gbl_global_lock_handle) {
return (AE_NOT_ACQUIRED);
}
- status = acpi_ev_release_global_lock ();
+ status = acpi_ev_release_global_lock();
return (status);
}
-EXPORT_SYMBOL(acpi_release_global_lock);
+EXPORT_SYMBOL(acpi_release_global_lock);
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index f337dc2cc569..887ff9f28a0d 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -48,8 +48,7 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxfevnt")
-
+ACPI_MODULE_NAME("evxfevnt")
/*******************************************************************************
*
@@ -62,44 +61,39 @@
* DESCRIPTION: Transfers the system into ACPI mode.
*
******************************************************************************/
-
-acpi_status
-acpi_enable (
- void)
+acpi_status acpi_enable(void)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("acpi_enable");
+ ACPI_FUNCTION_TRACE("acpi_enable");
-
- /* Make sure we have the FADT*/
+ /* Make sure we have the FADT */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "No FADT information present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n"));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "System is already in ACPI mode\n"));
+ } else {
/* Transition to ACPI mode */
- status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not transition to ACPI mode.\n"));
- return_ACPI_STATUS (status);
+ status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not transition to ACPI mode.\n"));
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Transition to ACPI mode successful\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Transition to ACPI mode successful\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_disable
@@ -112,43 +106,38 @@ acpi_enable (
*
******************************************************************************/
-acpi_status
-acpi_disable (
- void)
+acpi_status acpi_disable(void)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_disable");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_disable");
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "No FADT information present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "System is already in legacy (non-ACPI) mode\n"));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "System is already in legacy (non-ACPI) mode\n"));
+ } else {
/* Transition to LEGACY mode */
- status = acpi_hw_set_mode (ACPI_SYS_MODE_LEGACY);
+ status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not exit ACPI mode to legacy mode"));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not exit ACPI mode to legacy mode"));
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enable_event
@@ -162,52 +151,50 @@ acpi_disable (
*
******************************************************************************/
-acpi_status
-acpi_enable_event (
- u32 event,
- u32 flags)
+acpi_status acpi_enable_event(u32 event, u32 flags)
{
- acpi_status status = AE_OK;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enable_event");
+ acpi_status status = AE_OK;
+ u32 value;
+ ACPI_FUNCTION_TRACE("acpi_enable_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Enable the requested fixed event (by writing a one to the
* enable register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 1, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 1, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Make sure that the hardware responded */
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (value != 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not enable %s event\n", acpi_ut_get_event_name (event)));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not enable %s event\n",
+ acpi_ut_get_event_name(event)));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_event);
+EXPORT_SYMBOL(acpi_enable_event);
/*******************************************************************************
*
@@ -223,40 +210,34 @@ EXPORT_SYMBOL(acpi_enable_event);
*
******************************************************************************/
-acpi_status
-acpi_set_gpe_type (
- acpi_handle gpe_device,
- u32 gpe_number,
- u8 type)
+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_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_set_gpe_type");
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Set the new type (will disable GPE if currently enabled) */
- status = acpi_ev_set_gpe_type (gpe_event_info, type);
+ status = acpi_ev_set_gpe_type(gpe_event_info, type);
-unlock_and_exit:
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_gpe_type);
+EXPORT_SYMBOL(acpi_set_gpe_type);
/*******************************************************************************
*
@@ -273,31 +254,25 @@ EXPORT_SYMBOL(acpi_set_gpe_type);
*
******************************************************************************/
-acpi_status
-acpi_enable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+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_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_enable_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -305,16 +280,16 @@ acpi_enable_gpe (
/* Perform the enable */
- status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
+ status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_gpe);
+EXPORT_SYMBOL(acpi_enable_gpe);
/*******************************************************************************
*
@@ -331,46 +306,39 @@ EXPORT_SYMBOL(acpi_enable_gpe);
*
******************************************************************************/
-acpi_status
-acpi_disable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+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_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_disable_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
@@ -384,50 +352,48 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_disable_event (
- u32 event,
- u32 flags)
+acpi_status acpi_disable_event(u32 event, u32 flags)
{
- acpi_status status = AE_OK;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("acpi_disable_event");
+ acpi_status status = AE_OK;
+ u32 value;
+ ACPI_FUNCTION_TRACE("acpi_disable_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Disable the requested fixed event (by writing a zero to the
* enable register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 0, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 0, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (value != 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not disable %s events\n", acpi_ut_get_event_name (event)));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not disable %s events\n",
+ acpi_ut_get_event_name(event)));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_disable_event);
+EXPORT_SYMBOL(acpi_disable_event);
/*******************************************************************************
*
@@ -441,33 +407,30 @@ EXPORT_SYMBOL(acpi_disable_event);
*
******************************************************************************/
-acpi_status
-acpi_clear_event (
- u32 event)
+acpi_status acpi_clear_event(u32 event)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_clear_event");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_clear_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Clear the requested fixed event (By writing a one to the
* status register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
- 1, ACPI_MTX_LOCK);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, 1, ACPI_MTX_LOCK);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_clear_event);
+EXPORT_SYMBOL(acpi_clear_event);
/*******************************************************************************
*
@@ -483,46 +446,39 @@ EXPORT_SYMBOL(acpi_clear_event);
*
******************************************************************************/
-acpi_status
-acpi_clear_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+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_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_clear_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_hw_clear_gpe (gpe_event_info);
+ status = acpi_hw_clear_gpe(gpe_event_info);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -538,36 +494,31 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_get_event_status (
- u32 event,
- acpi_event_status *event_status)
+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_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_get_event_status");
if (!event_status) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the status of the requested fixed event */
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
- event_status, ACPI_MTX_LOCK);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, event_status, ACPI_MTX_LOCK);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_status
@@ -585,31 +536,26 @@ acpi_get_event_status (
******************************************************************************/
acpi_status
-acpi_get_gpe_status (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags,
- acpi_event_status *event_status)
+acpi_get_gpe_status(acpi_handle gpe_device,
+ u32 gpe_number, u32 flags, acpi_event_status * event_status)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_get_gpe_status");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -617,16 +563,15 @@ acpi_get_gpe_status (
/* Obtain status on the requested GPE number */
- status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
+ status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -635,7 +580,7 @@ unlock_and_exit:
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
* gpe_block_address - Address and space_iD
* register_count - Number of GPE register pairs in the block
- * interrupt_level - H/W interrupt for the block
+ * interrupt_number - H/W interrupt for the block
*
* RETURN: Status
*
@@ -644,33 +589,27 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_install_gpe_block (
- acpi_handle gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u32 interrupt_level)
+acpi_install_gpe_block(acpi_handle gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count, u32 interrupt_number)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- struct acpi_gpe_block_info *gpe_block;
-
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ 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);
+ if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (gpe_device);
+ node = acpi_ns_map_handle_to_node(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -680,31 +619,33 @@ acpi_install_gpe_block (
* For user-installed GPE Block Devices, the gpe_block_base_number
* is always zero
*/
- status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count,
- 0, interrupt_level, &gpe_block);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
+ interrupt_number, &gpe_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Get the device_object attached to the node */
- obj_desc = acpi_ns_get_attached_object (node);
+ 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);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE);
+ status =
+ acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
@@ -713,13 +654,12 @@ acpi_install_gpe_block (
obj_desc->device.gpe_block = gpe_block;
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_block);
+EXPORT_SYMBOL(acpi_install_gpe_block);
/*******************************************************************************
*
@@ -733,28 +673,24 @@ EXPORT_SYMBOL(acpi_install_gpe_block);
*
******************************************************************************/
-acpi_status
-acpi_remove_gpe_block (
- acpi_handle gpe_device)
+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");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ ACPI_FUNCTION_TRACE("acpi_remove_gpe_block");
if (!gpe_device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (gpe_device);
+ node = acpi_ns_map_handle_to_node(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -762,22 +698,21 @@ acpi_remove_gpe_block (
/* Get the device_object attached to the node */
- obj_desc = acpi_ns_get_attached_object (node);
- if (!obj_desc ||
- !obj_desc->device.gpe_block) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (!obj_desc || !obj_desc->device.gpe_block) {
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Delete the GPE block (but not the device_object) */
- status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
+ if (ACPI_SUCCESS(status)) {
obj_desc->device.gpe_block = NULL;
}
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_remove_gpe_block);
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index d058587b3427..6f28ea2db5ba 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -49,8 +49,7 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxfregn")
-
+ACPI_MODULE_NAME("evxfregn")
/*******************************************************************************
*
@@ -67,36 +66,31 @@
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
*
******************************************************************************/
-
acpi_status
-acpi_install_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context)
+acpi_install_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_address_space_handler");
/* Parameter validation */
if (!device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -104,21 +98,23 @@ acpi_install_address_space_handler (
/* Install the handler for all Regions for this Space ID */
- status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_install_space_handler(node, space_id, handler, setup,
+ context);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Run all _REG methods for this address space */
- status = acpi_ev_execute_reg_methods (node, space_id);
+ status = acpi_ev_execute_reg_methods(node, space_id);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_address_space_handler);
+EXPORT_SYMBOL(acpi_install_address_space_handler);
/*******************************************************************************
*
@@ -135,36 +131,33 @@ EXPORT_SYMBOL(acpi_install_address_space_handler);
******************************************************************************/
acpi_status
-acpi_remove_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler)
+acpi_remove_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *region_obj;
- union acpi_operand_object **last_obj_ptr;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_address_space_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *region_obj;
+ union acpi_operand_object **last_obj_ptr;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler");
/* Parameter validation */
if (!device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -172,7 +165,7 @@ acpi_remove_address_space_handler (
/* Make sure the internal object exists */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
@@ -188,10 +181,11 @@ acpi_remove_address_space_handler (
if (handler_obj->address_space.space_id == space_id) {
/* Matched space_id, first dereference this in the Regions */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
- handler_obj, handler, acpi_ut_get_region_name (space_id),
- node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
+ handler_obj, handler,
+ acpi_ut_get_region_name(space_id),
+ node, obj_desc));
region_obj = handler_obj->address_space.region_list;
@@ -205,13 +199,14 @@ acpi_remove_address_space_handler (
* The region is just inaccessible as indicated to
* the _REG method
*/
- acpi_ev_detach_region (region_obj, TRUE);
+ acpi_ev_detach_region(region_obj, TRUE);
/*
* Walk the list: Just grab the head because the
* detach_region removed the previous head.
*/
- region_obj = handler_obj->address_space.region_list;
+ region_obj =
+ handler_obj->address_space.region_list;
}
@@ -221,7 +216,7 @@ acpi_remove_address_space_handler (
/* Now we can delete the handler object */
- acpi_ut_remove_reference (handler_obj);
+ acpi_ut_remove_reference(handler_obj);
goto unlock_and_exit;
}
@@ -233,15 +228,16 @@ acpi_remove_address_space_handler (
/* 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",
- handler, acpi_ut_get_region_name (space_id), space_id, node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
+ handler, acpi_ut_get_region_name(space_id), space_id,
+ node, obj_desc));
status = AE_NOT_EXIST;
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_address_space_handler);
+EXPORT_SYMBOL(acpi_remove_address_space_handler);
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 734b2f24af48..1ce365d651d8 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -50,18 +49,14 @@
#include <acpi/actables.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exconfig")
+ACPI_MODULE_NAME("exconfig")
/* Local prototypes */
-
static acpi_status
-acpi_ex_add_table (
- struct acpi_table_header *table,
- struct acpi_namespace_node *parent_node,
- union acpi_operand_object **ddb_handle);
-
+acpi_ex_add_table(struct acpi_table_header *table,
+ struct acpi_namespace_node *parent_node,
+ union acpi_operand_object **ddb_handle);
/*******************************************************************************
*
@@ -79,64 +74,67 @@ acpi_ex_add_table (
******************************************************************************/
static acpi_status
-acpi_ex_add_table (
- struct acpi_table_header *table,
- struct acpi_namespace_node *parent_node,
- union acpi_operand_object **ddb_handle)
+acpi_ex_add_table(struct acpi_table_header *table,
+ struct acpi_namespace_node *parent_node,
+ union acpi_operand_object **ddb_handle)
{
- acpi_status status;
- struct acpi_table_desc table_info;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ex_add_table");
+ acpi_status status;
+ struct acpi_table_desc table_info;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ex_add_table");
/* Create an object to be the table handle */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
+ /* Init the table handle */
+
+ obj_desc->reference.opcode = AML_LOAD_OP;
+ *ddb_handle = obj_desc;
+
/* Install the new table into the local data structures */
- ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc));
+ ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc));
- table_info.type = ACPI_TABLE_SSDT;
- table_info.pointer = table;
- table_info.length = (acpi_size) table->length;
+ table_info.type = ACPI_TABLE_SSDT;
+ table_info.pointer = table;
+ table_info.length = (acpi_size) table->length;
table_info.allocation = ACPI_MEM_ALLOCATED;
- status = acpi_tb_install_table (&table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_install_table(&table_info);
+ obj_desc->reference.object = table_info.installed_desc;
+
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ /* Table already exists, just return the handle */
+
+ return_ACPI_STATUS(AE_OK);
+ }
goto cleanup;
}
/* Add the table to the namespace */
- status = acpi_ns_load_table (table_info.installed_desc, parent_node);
- if (ACPI_FAILURE (status)) {
+ 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);
+ (void)acpi_tb_uninstall_table(table_info.installed_desc);
goto cleanup;
}
- /* Init the table handle */
+ return_ACPI_STATUS(AE_OK);
- obj_desc->reference.opcode = AML_LOAD_OP;
- obj_desc->reference.object = table_info.installed_desc;
- *ddb_handle = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
-
-cleanup:
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ cleanup:
+ acpi_ut_remove_reference(obj_desc);
+ *ddb_handle = NULL;
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_table_op
@@ -151,56 +149,53 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ex_load_table_op (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **return_desc)
+acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
+ union acpi_operand_object **return_desc)
{
- acpi_status status;
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_table_header *table;
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *start_node;
- struct acpi_namespace_node *parameter_node = NULL;
- union acpi_operand_object *ddb_handle;
-
-
- ACPI_FUNCTION_TRACE ("ex_load_table_op");
+ acpi_status status;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_table_header *table;
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *start_node;
+ struct acpi_namespace_node *parameter_node = NULL;
+ union acpi_operand_object *ddb_handle;
+ ACPI_FUNCTION_TRACE("ex_load_table_op");
#if 0
/*
* Make sure that the signature does not match one of the tables that
* is already loaded.
*/
- status = acpi_tb_match_signature (operand[0]->string.pointer, NULL);
+ 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);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
#endif
/* Find the ACPI table */
- status = acpi_tb_find_table (operand[0]->string.pointer,
- operand[1]->string.pointer,
- operand[2]->string.pointer, &table);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_find_table(operand[0]->string.pointer,
+ operand[1]->string.pointer,
+ operand[2]->string.pointer, &table);
+ if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Table not found, return an Integer=0 and AE_OK */
- ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!ddb_handle) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
ddb_handle->integer.value = 0;
*return_desc = ddb_handle;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Default nodes */
@@ -215,10 +210,12 @@ acpi_ex_load_table_op (
* Find the node referenced by the root_path_string. This is the
* 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_get_node_by_path(operand[3]->string.pointer,
+ start_node, ACPI_NS_SEARCH_PARENT,
+ &parent_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -226,7 +223,7 @@ acpi_ex_load_table_op (
if (operand[4]->string.length > 0) {
if ((operand[4]->string.pointer[0] != '\\') &&
- (operand[4]->string.pointer[0] != '^')) {
+ (operand[4]->string.pointer[0] != '^')) {
/*
* Path is not absolute, so it will be relative to the node
* referenced by the root_path_string (or the NS root if omitted)
@@ -236,18 +233,20 @@ acpi_ex_load_table_op (
/* 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_get_node_by_path(operand[4]->string.pointer,
+ start_node, ACPI_NS_SEARCH_PARENT,
+ &parameter_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Load the table into the namespace */
- status = acpi_ex_add_table (table, parent_node, &ddb_handle);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_add_table(table, parent_node, &ddb_handle);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Parameter Data (optional) */
@@ -255,20 +254,20 @@ acpi_ex_load_table_op (
if (parameter_node) {
/* Store the parameter data into the optional parameter object */
- status = acpi_ex_store (operand[5],
- ACPI_CAST_PTR (union acpi_operand_object, parameter_node),
- walk_state);
- if (ACPI_FAILURE (status)) {
- (void) acpi_ex_unload_table (ddb_handle);
- return_ACPI_STATUS (status);
+ status = acpi_ex_store(operand[5],
+ ACPI_CAST_PTR(union acpi_operand_object,
+ parameter_node),
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ (void)acpi_ex_unload_table(ddb_handle);
+ return_ACPI_STATUS(status);
}
}
*return_desc = ddb_handle;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_op
@@ -285,38 +284,37 @@ acpi_ex_load_table_op (
******************************************************************************/
acpi_status
-acpi_ex_load_op (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *target,
- struct acpi_walk_state *walk_state)
+acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ union acpi_operand_object *target,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *ddb_handle;
- union acpi_operand_object *buffer_desc = NULL;
- struct acpi_table_header *table_ptr = NULL;
- acpi_physical_address address;
- struct acpi_table_header table_header;
- u32 i;
-
- ACPI_FUNCTION_TRACE ("ex_load_op");
+ acpi_status status;
+ union acpi_operand_object *ddb_handle;
+ union acpi_operand_object *buffer_desc = NULL;
+ struct acpi_table_header *table_ptr = NULL;
+ acpi_physical_address address;
+ struct acpi_table_header table_header;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ex_load_op");
/* Object can be either an op_region or a Field */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
+ obj_desc,
+ acpi_ut_get_object_type_name(obj_desc)));
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_region_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_region_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -328,116 +326,127 @@ acpi_ex_load_op (
table_header.length = 0;
for (i = 0; i < 8; i++) {
- status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
- (acpi_physical_address) (i + address), 8,
- ((u8 *) &table_header) + i);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
+ (acpi_physical_address)
+ (i + address), 8,
+ ((u8 *) &
+ table_header) + i);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Sanity check the table length */
- if (table_header.length < sizeof (struct acpi_table_header)) {
- return_ACPI_STATUS (AE_BAD_HEADER);
+ if (table_header.length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_BAD_HEADER);
}
/* Allocate a buffer for the entire table */
- table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
+ table_ptr = ACPI_MEM_ALLOCATE(table_header.length);
if (!table_ptr) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Get the entire table from the op region */
for (i = 0; i < table_header.length; i++) {
- status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
- (acpi_physical_address) (i + address), 8,
- ((u8 *) table_ptr + i));
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
+ (acpi_physical_address)
+ (i + address), 8,
+ ((u8 *) table_ptr +
+ i));
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n",
+ obj_desc,
+ acpi_ut_get_object_type_name(obj_desc)));
/*
* The length of the field must be at least as large as the table.
* Read the entire field and thus the entire table. Buffer is
* allocated during the read.
*/
- status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
+ status =
+ acpi_ex_read_data_from_field(walk_state, obj_desc,
+ &buffer_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- table_ptr = ACPI_CAST_PTR (struct acpi_table_header,
- buffer_desc->buffer.pointer);
+ table_ptr = ACPI_CAST_PTR(struct acpi_table_header,
+ buffer_desc->buffer.pointer);
- /* Sanity check the table length */
+ /* All done with the buffer_desc, delete it */
- if (table_ptr->length < sizeof (struct acpi_table_header)) {
- return_ACPI_STATUS (AE_BAD_HEADER);
+ buffer_desc->buffer.pointer = NULL;
+ acpi_ut_remove_reference(buffer_desc);
+
+ /* Sanity check the table length */
+
+ if (table_ptr->length < sizeof(struct acpi_table_header)) {
+ status = AE_BAD_HEADER;
+ goto cleanup;
}
break;
-
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* 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))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
- table_ptr->signature));
+ 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))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
+ table_ptr->signature));
status = AE_BAD_SIGNATURE;
goto cleanup;
}
/* Install the new table into the local data structures */
- status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
- }
-
- /* Store the ddb_handle into the Target operand */
+ status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle);
+ if (ACPI_FAILURE(status)) {
+ /* On error, table_ptr was deallocated above */
- status = acpi_ex_store (ddb_handle, target, walk_state);
- if (ACPI_FAILURE (status)) {
- (void) acpi_ex_unload_table (ddb_handle);
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ /* Store the ddb_handle into the Target operand */
+ status = acpi_ex_store(ddb_handle, target, walk_state);
+ if (ACPI_FAILURE(status)) {
+ (void)acpi_ex_unload_table(ddb_handle);
-cleanup:
+ /* table_ptr was deallocated above */
- if (buffer_desc) {
- acpi_ut_remove_reference (buffer_desc);
+ return_ACPI_STATUS(status);
}
- else {
- ACPI_MEM_FREE (table_ptr);
+
+ cleanup:
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(table_ptr);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_unload_table
@@ -450,17 +459,13 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_unload_table (
- union acpi_operand_object *ddb_handle)
+acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *table_desc = ddb_handle;
- struct acpi_table_desc *table_info;
-
-
- ACPI_FUNCTION_TRACE ("ex_unload_table");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *table_desc = ddb_handle;
+ struct acpi_table_desc *table_info;
+ ACPI_FUNCTION_TRACE("ex_unload_table");
/*
* Validate the handle
@@ -469,28 +474,28 @@ acpi_ex_unload_table (
* validated here.
*/
if ((!ddb_handle) ||
- (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
- (ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
+ (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the actual table descriptor from the ddb_handle */
- table_info = (struct acpi_table_desc *) table_desc->reference.object;
+ table_info = (struct acpi_table_desc *)table_desc->reference.object;
/*
* Delete the entire namespace under this table Node
* (Offset contains the table_id)
*/
- acpi_ns_delete_namespace_by_owner (table_info->table_id);
+ acpi_ns_delete_namespace_by_owner(table_info->owner_id);
+ acpi_ut_release_owner_id(&table_info->owner_id);
/* Delete the table itself */
- (void) acpi_tb_uninstall_table (table_info->installed_desc);
+ (void)acpi_tb_uninstall_table(table_info->installed_desc);
/* Delete the table descriptor (ddb_handle) */
- acpi_ut_remove_reference (table_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(table_desc);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index 97856c48bd74..04e5194989a6 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -41,24 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exconvrt")
+ACPI_MODULE_NAME("exconvrt")
/* Local prototypes */
-
static u32
-acpi_ex_convert_to_ascii (
- acpi_integer integer,
- u16 base,
- u8 *string,
- u8 max_length);
-
+acpi_ex_convert_to_ascii(acpi_integer integer,
+ u16 base, u8 * string, u8 max_length);
/*******************************************************************************
*
@@ -76,29 +69,25 @@ acpi_ex_convert_to_ascii (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_integer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 flags)
+acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc, u32 flags)
{
- union acpi_operand_object *return_desc;
- u8 *pointer;
- acpi_integer result;
- u32 i;
- u32 count;
- acpi_status status;
-
+ union acpi_operand_object *return_desc;
+ u8 *pointer;
+ acpi_integer result;
+ u32 i;
+ 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)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
@@ -106,11 +95,11 @@ acpi_ex_convert_to_integer (
/* Note: Takes advantage of common buffer/string fields */
pointer = obj_desc->buffer.pointer;
- count = obj_desc->buffer.length;
+ count = obj_desc->buffer.length;
break;
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/*
@@ -126,7 +115,7 @@ acpi_ex_convert_to_integer (
/* String conversion is different than Buffer conversion */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
/*
@@ -135,19 +124,18 @@ acpi_ex_convert_to_integer (
* of ACPI 3.0) is that the to_integer() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
- status = acpi_ut_strtoul64 ((char *) pointer, flags, &result);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_strtoul64((char *)pointer, flags, &result);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
break;
-
case ACPI_TYPE_BUFFER:
/* Check for zero-length buffer */
if (!count) {
- return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
/* Transfer no more than an integer's worth of data */
@@ -170,7 +158,6 @@ acpi_ex_convert_to_integer (
}
break;
-
default:
/* No other types can get here */
break;
@@ -178,20 +165,19 @@ acpi_ex_convert_to_integer (
/* Create a new integer */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the Result */
return_desc->integer.value = result;
- acpi_ex_truncate_for32bit_table (return_desc);
+ acpi_ex_truncate_for32bit_table(return_desc);
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_buffer
@@ -207,25 +193,21 @@ acpi_ex_convert_to_integer (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_buffer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc)
+acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
+ 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)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
@@ -233,20 +215,20 @@ acpi_ex_convert_to_buffer (
* Create a new Buffer object.
* Need enough space for one integer
*/
- return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
+ return_desc =
+ acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the integer to the buffer, LSB first */
new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY (new_buf,
- &obj_desc->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf,
+ &obj_desc->integer.value,
+ acpi_gbl_integer_byte_width);
break;
-
case ACPI_TYPE_STRING:
/*
@@ -258,32 +240,31 @@ acpi_ex_convert_to_buffer (
* ASL/AML code that depends on the null being transferred to the new
* buffer.
*/
- return_desc = acpi_ut_create_buffer_object (
- (acpi_size) obj_desc->string.length + 1);
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ obj_desc->string.
+ length + 1);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the string to the buffer */
new_buf = return_desc->buffer.pointer;
- ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer,
- obj_desc->string.length);
+ ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer,
+ obj_desc->string.length);
break;
-
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Mark buffer initialized */
return_desc->common.flags |= AOPOBJ_DATA_VALID;
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_ascii
@@ -300,24 +281,19 @@ acpi_ex_convert_to_buffer (
******************************************************************************/
static u32
-acpi_ex_convert_to_ascii (
- acpi_integer integer,
- u16 base,
- u8 *string,
- u8 data_width)
+acpi_ex_convert_to_ascii(acpi_integer integer,
+ u16 base, u8 * string, u8 data_width)
{
- acpi_integer digit;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_native_uint k = 0;
- acpi_native_uint hex_length;
- acpi_native_uint decimal_length;
- u32 remainder;
- u8 supress_zeros;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_integer digit;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ acpi_native_uint k = 0;
+ acpi_native_uint hex_length;
+ acpi_native_uint decimal_length;
+ u32 remainder;
+ u8 supress_zeros;
+ ACPI_FUNCTION_ENTRY();
switch (base) {
case 10:
@@ -339,7 +315,7 @@ acpi_ex_convert_to_ascii (
break;
}
- supress_zeros = TRUE; /* No leading zeros */
+ supress_zeros = TRUE; /* No leading zeros */
remainder = 0;
for (i = decimal_length; i > 0; i--) {
@@ -347,7 +323,8 @@ acpi_ex_convert_to_ascii (
digit = integer;
for (j = 0; j < i; j++) {
- (void) acpi_ut_short_divide (digit, 10, &digit, &remainder);
+ (void)acpi_ut_short_divide(digit, 10, &digit,
+ &remainder);
}
/* Handle leading zeros */
@@ -367,11 +344,13 @@ acpi_ex_convert_to_ascii (
/* hex_length: 2 ascii hex chars per data byte */
- hex_length = ACPI_MUL_2 (data_width);
- for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) {
+ 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] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j));
+ string[k] =
+ (u8) acpi_ut_hex_to_ascii_char(integer,
+ ACPI_MUL_4(j));
k++;
}
break;
@@ -387,15 +366,14 @@ acpi_ex_convert_to_ascii (
* Finally, null terminate the string and return the length
*/
if (!k) {
- string [0] = ACPI_ASCII_ZERO;
+ string[0] = ACPI_ASCII_ZERO;
k = 1;
}
- string [k] = 0;
+ string[k] = 0;
return ((u32) k);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_string
@@ -412,30 +390,25 @@ acpi_ex_convert_to_ascii (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_string (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 type)
+acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
+ union acpi_operand_object ** result_desc, u32 type)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
- u32 i;
- u32 string_length = 0;
- u16 base = 16;
- u8 separator = ',';
+ union acpi_operand_object *return_desc;
+ u8 *new_buf;
+ u32 i;
+ u32 string_length = 0;
+ 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)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
@@ -452,7 +425,7 @@ acpi_ex_convert_to_string (
/* Two hex string characters for each integer byte */
- string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width);
+ string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
break;
}
@@ -460,31 +433,33 @@ acpi_ex_convert_to_string (
* Create a new String
* Need enough space for one ASCII integer (plus null terminator)
*/
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
+ return_desc =
+ acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
/* Convert integer to string */
- string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base,
- new_buf, acpi_gbl_integer_byte_width);
+ string_length =
+ acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
+ new_buf,
+ acpi_gbl_integer_byte_width);
/* Null terminate at the correct place */
return_desc->string.length = string_length;
- new_buf [string_length] = 0;
+ new_buf[string_length] = 0;
break;
-
case ACPI_TYPE_BUFFER:
/* Setup string length, base, and separator */
switch (type) {
- case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
+ case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* decimal values separated by commas."
@@ -498,11 +473,9 @@ acpi_ex_convert_to_string (
for (i = 0; i < obj_desc->buffer.length; i++) {
if (obj_desc->buffer.pointer[i] >= 100) {
string_length += 4;
- }
- else if (obj_desc->buffer.pointer[i] >= 10) {
+ } else if (obj_desc->buffer.pointer[i] >= 10) {
string_length += 3;
- }
- else {
+ } else {
string_length += 2;
}
}
@@ -518,7 +491,7 @@ acpi_ex_convert_to_string (
string_length = (obj_desc->buffer.length * 3);
break;
- case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */
+ case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* hexadecimal values separated by commas."
@@ -527,7 +500,7 @@ acpi_ex_convert_to_string (
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -535,15 +508,16 @@ acpi_ex_convert_to_string (
* (-1 because of extra separator included in string_length from above)
*/
string_length--;
- if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ {
- return_ACPI_STATUS (AE_AML_STRING_LIMIT);
+ if (string_length > ACPI_MAX_STRING_CONVERSION) { /* ACPI limit */
+ return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
/* Create a new string object and string buffer */
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
+ return_desc =
+ acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
@@ -553,10 +527,11 @@ acpi_ex_convert_to_string (
* (separated by commas or spaces)
*/
for (i = 0; i < obj_desc->buffer.length; i++) {
- new_buf += acpi_ex_convert_to_ascii (
- (acpi_integer) obj_desc->buffer.pointer[i], base,
- new_buf, 1);
- *new_buf++ = separator; /* each separated by a comma or space */
+ new_buf += acpi_ex_convert_to_ascii((acpi_integer)
+ obj_desc->buffer.
+ pointer[i], base,
+ new_buf, 1);
+ *new_buf++ = separator; /* each separated by a comma or space */
}
/*
@@ -568,14 +543,13 @@ acpi_ex_convert_to_string (
break;
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_target_type
@@ -592,17 +566,14 @@ acpi_ex_convert_to_string (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_target_type (
- acpi_object_type destination_type,
- union acpi_operand_object *source_desc,
- union acpi_operand_object **result_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_convert_to_target_type(acpi_object_type destination_type,
+ union acpi_operand_object *source_desc,
+ union acpi_operand_object **result_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_convert_to_target_type");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_convert_to_target_type");
/* Default behavior */
@@ -612,10 +583,10 @@ acpi_ex_convert_to_target_type (
* If required by the target,
* perform implicit conversion on the source before we store it.
*/
- switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
+ switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
case ARGI_SIMPLE_TARGET:
case ARGI_FIXED_TARGET:
- case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
+ case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
switch (destination_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
@@ -627,17 +598,19 @@ acpi_ex_convert_to_target_type (
default:
/* No conversion allowed for these types */
- if (destination_type != ACPI_GET_OBJECT_TYPE (source_desc)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Explicit operator, will store (%s) over existing type (%s)\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_type_name (destination_type)));
+ if (destination_type !=
+ ACPI_GET_OBJECT_TYPE(source_desc)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Explicit operator, will store (%s) over existing type (%s)\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_type_name
+ (destination_type)));
status = AE_TYPE;
}
}
break;
-
case ARGI_TARGETREF:
switch (destination_type) {
@@ -649,55 +622,55 @@ acpi_ex_convert_to_target_type (
* These types require an Integer operand. We can convert
* a Buffer or a String to an Integer if necessary.
*/
- status = acpi_ex_convert_to_integer (source_desc, result_desc,
- 16);
+ status =
+ acpi_ex_convert_to_integer(source_desc, result_desc,
+ 16);
break;
-
case ACPI_TYPE_STRING:
/*
* The operand must be a String. We can convert an
* Integer or Buffer if necessary
*/
- status = acpi_ex_convert_to_string (source_desc, result_desc,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status =
+ acpi_ex_convert_to_string(source_desc, result_desc,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
-
case ACPI_TYPE_BUFFER:
/*
* The operand must be a Buffer. We can convert an
* Integer or String if necessary
*/
- status = acpi_ex_convert_to_buffer (source_desc, result_desc);
+ status =
+ acpi_ex_convert_to_buffer(source_desc, result_desc);
break;
-
default:
- ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
- destination_type));
+ ACPI_REPORT_ERROR(("Bad destination type during conversion: %X\n", destination_type));
status = AE_AML_INTERNAL;
break;
}
break;
-
case ARGI_REFERENCE:
/*
* create_xxxx_field cases - we are storing the field object into the name
*/
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown Target type ID 0x%X Op %s dest_type %s\n",
- GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
- walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
-
- ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
- GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
- status = AE_AML_INTERNAL;
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Target type ID 0x%X Op %s dest_type %s\n",
+ GET_CURRENT_ARG_TYPE(walk_state->op_info->
+ runtime_args),
+ walk_state->op_info->name,
+ acpi_ut_get_type_name(destination_type)));
+
+ ACPI_REPORT_ERROR(("Bad Target Type (ARGI): %X\n",
+ GET_CURRENT_ARG_TYPE(walk_state->op_info->
+ runtime_args)))
+ status = AE_AML_INTERNAL;
}
/*
@@ -710,7 +683,5 @@ acpi_ex_convert_to_target_type (
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 812cdcb2e370..91c49188fb07 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -49,10 +48,8 @@
#include <acpi/acevents.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("excreate")
-
+ACPI_MODULE_NAME("excreate")
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -66,33 +63,30 @@
* DESCRIPTION: Create a new named alias
*
******************************************************************************/
-
-acpi_status
-acpi_ex_create_alias (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
{
- struct acpi_namespace_node *target_node;
- struct acpi_namespace_node *alias_node;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_alias");
+ struct acpi_namespace_node *target_node;
+ struct acpi_namespace_node *alias_node;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_create_alias");
/* Get the source/alias operands (both namespace nodes) */
- alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
- target_node = (struct acpi_namespace_node *) walk_state->operands[1];
+ alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
+ target_node = (struct acpi_namespace_node *)walk_state->operands[1];
if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
- (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+ (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/*
* Dereference an existing alias so that we don't create a chain
* of aliases. With this code, we guarantee that an alias is
* always exactly one level of indirection away from the
* actual aliased name.
*/
- target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
+ target_node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ target_node->object);
}
/*
@@ -115,7 +109,8 @@ acpi_ex_create_alias (
* types, the object can change dynamically via a Store.
*/
alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
- alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
+ alias_node->object =
+ ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
case ACPI_TYPE_METHOD:
@@ -126,7 +121,8 @@ acpi_ex_create_alias (
* types, the object can change dynamically via a Store.
*/
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
- alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
+ alias_node->object =
+ ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
default:
@@ -139,17 +135,18 @@ acpi_ex_create_alias (
* additional reference to prevent deletion out from under either the
* target node or the alias Node
*/
- status = acpi_ns_attach_object (alias_node,
- acpi_ns_get_attached_object (target_node), target_node->type);
+ status = acpi_ns_attach_object(alias_node,
+ acpi_ns_get_attached_object
+ (target_node),
+ target_node->type);
break;
}
/* Since both operands are Nodes, we don't need to delete them */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_event
@@ -162,18 +159,14 @@ acpi_ex_create_alias (
*
******************************************************************************/
-acpi_status
-acpi_ex_create_event (
- struct acpi_walk_state *walk_state)
+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_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ex_create_event");
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -183,27 +176,27 @@ acpi_ex_create_event (
* Create the actual OS semaphore, with zero initial units -- meaning
* that the event is created in an unsignalled state
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0,
- &obj_desc->event.semaphore);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
+ &obj_desc->event.semaphore);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Attach object to the Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0],
- obj_desc, ACPI_TYPE_EVENT);
+ status =
+ acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
+ operands[0], obj_desc, ACPI_TYPE_EVENT);
-cleanup:
+ cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_mutex
@@ -218,20 +211,16 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_mutex (
- struct acpi_walk_state *walk_state)
+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_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS);
/* Create the new mutex object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -242,30 +231,30 @@ acpi_ex_create_mutex (
* One unit max to make it a mutex, with one initial unit to allow
* the mutex to be acquired.
*/
- status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_create_semaphore(1, 1, &obj_desc->mutex.semaphore);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Init object and attach to NS node */
- obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value;
- 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);
+ obj_desc->mutex.sync_level =
+ (u8) walk_state->operands[1]->integer.value;
+ 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);
-cleanup:
+ cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_region
@@ -282,20 +271,16 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ex_create_region (
- u8 *aml_start,
- u32 aml_length,
- u8 region_space,
- struct acpi_walk_state *walk_state)
+acpi_ex_create_region(u8 * aml_start,
+ u32 aml_length,
+ u8 region_space, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- union acpi_operand_object *region_obj2;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_region");
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *region_obj2;
+ ACPI_FUNCTION_TRACE("ex_create_region");
/* Get the Namespace Node */
@@ -305,8 +290,8 @@ acpi_ex_create_region (
* If the region object is already attached to this node,
* just return
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -314,17 +299,18 @@ acpi_ex_create_region (
* range
*/
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
- (region_space < ACPI_USER_REGION_BEGIN)) {
- ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space));
- return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
+ (region_space < ACPI_USER_REGION_BEGIN)) {
+ ACPI_REPORT_ERROR(("Invalid address_space type %X\n",
+ region_space));
+ return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
- acpi_ut_get_region_name (region_space), region_space));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
+ acpi_ut_get_region_name(region_space), region_space));
/* Create the region descriptor */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -334,7 +320,7 @@ acpi_ex_create_region (
* Remember location in AML stream of address & length
* operands since they need to be evaluated at run time.
*/
- region_obj2 = obj_desc->common.next_object;
+ region_obj2 = obj_desc->common.next_object;
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
@@ -343,22 +329,20 @@ acpi_ex_create_region (
obj_desc->region.space_id = region_space;
obj_desc->region.address = 0;
obj_desc->region.length = 0;
- obj_desc->region.node = node;
+ obj_desc->region.node = node;
/* Install the new region object in the parent Node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_table_region
@@ -371,20 +355,16 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_table_region (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- struct acpi_table_header *table;
- union acpi_operand_object *region_obj2;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_table_region");
+ acpi_status status;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ struct acpi_table_header *table;
+ union acpi_operand_object *region_obj2;
+ ACPI_FUNCTION_TRACE("ex_create_table_region");
/* Get the Node from the object stack */
@@ -394,66 +374,64 @@ acpi_ex_create_table_region (
* If the region object is already attached to this node,
* just return
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
/* Find the ACPI table */
- status = acpi_tb_find_table (operand[1]->string.pointer,
- operand[2]->string.pointer,
- operand[3]->string.pointer, &table);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_find_table(operand[1]->string.pointer,
+ operand[2]->string.pointer,
+ operand[3]->string.pointer, &table);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Create the region descriptor */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- region_obj2 = obj_desc->common.next_object;
+ region_obj2 = obj_desc->common.next_object;
region_obj2->extra.region_context = NULL;
/* Init the region from the operands */
obj_desc->region.space_id = REGION_DATA_TABLE;
- obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table);
+ obj_desc->region.address =
+ (acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;
- obj_desc->region.node = node;
- obj_desc->region.flags = AOPOBJ_DATA_VALID;
+ obj_desc->region.node = node;
+ obj_desc->region.flags = AOPOBJ_DATA_VALID;
/* Install the new region object in the parent Node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ev_initialize_region (obj_desc, FALSE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_initialize_region(obj_desc, FALSE);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_EXIST) {
status = AE_OK;
- }
- else {
+ } else {
goto cleanup;
}
}
obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_processor
@@ -468,43 +446,39 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_processor (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state);
/* Create the processor object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the processor object from the operands */
- obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
- obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value;
- obj_desc->processor.length = (u8) operand[3]->integer.value;
+ obj_desc->processor.proc_id = (u8) operand[1]->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 */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_PROCESSOR);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_PROCESSOR);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_power_resource
@@ -519,43 +493,39 @@ acpi_ex_create_processor (
*
******************************************************************************/
-acpi_status
-acpi_ex_create_power_resource (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state);
/* Create the power resource object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the power object from the operands */
obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
- obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value;
+ obj_desc->power_resource.resource_order =
+ (u16) operand[2]->integer.value;
/* Install the power resource object in the parent Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_POWER);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_POWER);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_method
@@ -571,25 +541,21 @@ acpi_ex_create_power_resource (
******************************************************************************/
acpi_status
-acpi_ex_create_method (
- u8 *aml_start,
- u32 aml_length,
- struct acpi_walk_state *walk_state)
+acpi_ex_create_method(u8 * aml_start,
+ u32 aml_length, struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u8 method_flags;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u8 method_flags;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state);
/* Create a new method object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the method's AML pointer and length */
@@ -603,8 +569,10 @@ acpi_ex_create_method (
*/
method_flags = (u8) operand[1]->integer.value;
- obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
- obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
+ obj_desc->method.method_flags =
+ (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
+ obj_desc->method.param_count =
+ (u8) (method_flags & AML_METHOD_ARG_COUNT);
/*
* Get the concurrency count. If required, a semaphore will be
@@ -613,32 +581,28 @@ acpi_ex_create_method (
if (acpi_gbl_all_methods_serialized) {
obj_desc->method.concurrency = 1;
obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
- }
- else if (method_flags & AML_METHOD_SERIALIZED) {
+ } else if (method_flags & AML_METHOD_SERIALIZED) {
/*
* ACPI 1.0: Concurrency = 1
* ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
*/
obj_desc->method.concurrency = (u8)
- (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
- }
- else {
+ (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
+ } else {
obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
}
/* Attach the new object to the method Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_METHOD);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_METHOD);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
/* Remove a reference to the operand */
- acpi_ut_remove_reference (operand[1]);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(operand[1]);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 408500648114..bc2fa996047e 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -49,37 +48,27 @@
#include <acpi/acparser.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exdump")
+ACPI_MODULE_NAME("exdump")
+/*
+ * The following routines are used for debug output only
+ */
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
-
#ifdef ACPI_FUTURE_USAGE
-static void
-acpi_ex_out_string (
- char *title,
- char *value);
+static void acpi_ex_out_string(char *title, char *value);
-static void
-acpi_ex_out_pointer (
- char *title,
- void *value);
+static void acpi_ex_out_pointer(char *title, void *value);
-static void
-acpi_ex_out_integer (
- char *title,
- u32 value);
+static void acpi_ex_out_integer(char *title, u32 value);
-static void
-acpi_ex_out_address (
- char *title,
- acpi_physical_address value);
-#endif /* ACPI_FUTURE_USAGE */
+static void acpi_ex_out_address(char *title, acpi_physical_address value);
+static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc);
-/*
- * The following routines are used for debug output only
- */
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+static void
+acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index);
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -94,143 +83,140 @@ acpi_ex_out_address (
*
******************************************************************************/
-void
-acpi_ex_dump_operand (
- union acpi_operand_object *obj_desc,
- u32 depth)
+void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
{
- u32 length;
- u32 index;
-
+ u32 length;
+ u32 index;
- ACPI_FUNCTION_NAME ("ex_dump_operand")
+ ACPI_FUNCTION_NAME("ex_dump_operand")
-
- if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_EXEC & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return;
}
if (!obj_desc) {
/* This could be a null element of a package */
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
return;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc));
- ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC);
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ",
+ obj_desc));
+ ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC);
return;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%p is not a node or operand object: [%s]\n",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
- ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object));
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%p is not a node or operand object: [%s]\n",
+ obj_desc,
+ acpi_ut_get_descriptor_name(obj_desc)));
+ ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object));
return;
}
/* obj_desc is a valid object */
if (depth > 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ",
- depth, " ", depth, obj_desc));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ",
+ depth, " ", depth, obj_desc));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc));
}
/* Decode object type */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
switch (obj_desc->reference.opcode) {
case AML_DEBUG_OP:
- acpi_os_printf ("Reference: Debug\n");
+ acpi_os_printf("Reference: Debug\n");
break;
-
case AML_NAME_OP:
- ACPI_DUMP_PATHNAME (obj_desc->reference.object,
- "Reference: Name: ", ACPI_LV_INFO, _COMPONENT);
- ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO);
+ ACPI_DUMP_PATHNAME(obj_desc->reference.object,
+ "Reference: Name: ", ACPI_LV_INFO,
+ _COMPONENT);
+ ACPI_DUMP_ENTRY(obj_desc->reference.object,
+ ACPI_LV_INFO);
break;
-
case AML_INDEX_OP:
- acpi_os_printf ("Reference: Index %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("Reference: Index %p\n",
+ obj_desc->reference.object);
break;
-
case AML_REF_OF_OP:
- acpi_os_printf ("Reference: (ref_of) %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("Reference: (ref_of) %p\n",
+ obj_desc->reference.object);
break;
-
case AML_ARG_OP:
- acpi_os_printf ("Reference: Arg%d",
- obj_desc->reference.offset);
+ acpi_os_printf("Reference: Arg%d",
+ obj_desc->reference.offset);
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Value is an Integer */
- acpi_os_printf (" value is [%8.8X%8.8x]",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" value is [%8.8X%8.8x]",
+ ACPI_FORMAT_UINT64(obj_desc->
+ integer.
+ value));
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
-
case AML_LOCAL_OP:
- acpi_os_printf ("Reference: Local%d",
- obj_desc->reference.offset);
+ acpi_os_printf("Reference: Local%d",
+ obj_desc->reference.offset);
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Value is an Integer */
- acpi_os_printf (" value is [%8.8X%8.8x]",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" value is [%8.8X%8.8x]",
+ ACPI_FORMAT_UINT64(obj_desc->
+ integer.
+ value));
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
-
case AML_INT_NAMEPATH_OP:
- acpi_os_printf ("Reference.Node->Name %X\n",
- obj_desc->reference.node->name.integer);
+ acpi_os_printf("Reference.Node->Name %X\n",
+ obj_desc->reference.node->name.integer);
break;
-
default:
/* Unknown opcode */
- acpi_os_printf ("Unknown Reference opcode=%X\n",
- obj_desc->reference.opcode);
+ acpi_os_printf("Unknown Reference opcode=%X\n",
+ obj_desc->reference.opcode);
break;
}
break;
-
case ACPI_TYPE_BUFFER:
- acpi_os_printf ("Buffer len %X @ %p \n",
- obj_desc->buffer.length, obj_desc->buffer.pointer);
+ acpi_os_printf("Buffer len %X @ %p \n",
+ obj_desc->buffer.length,
+ obj_desc->buffer.pointer);
length = obj_desc->buffer.length;
if (length > 64) {
@@ -240,178 +226,166 @@ acpi_ex_dump_operand (
/* Debug only -- dump the buffer contents */
if (obj_desc->buffer.pointer) {
- acpi_os_printf ("Buffer Contents: ");
+ acpi_os_printf("Buffer Contents: ");
for (index = 0; index < length; index++) {
- acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]);
+ acpi_os_printf(" %02x",
+ obj_desc->buffer.pointer[index]);
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
}
break;
-
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("Integer %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("Integer %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
-
case ACPI_TYPE_PACKAGE:
- acpi_os_printf ("Package [Len %X] element_array %p\n",
- obj_desc->package.count, obj_desc->package.elements);
+ acpi_os_printf("Package [Len %X] element_array %p\n",
+ obj_desc->package.count,
+ obj_desc->package.elements);
/*
* If elements exist, package element pointer is valid,
* and debug_level exceeds 1, dump package's elements.
*/
if (obj_desc->package.count &&
- obj_desc->package.elements &&
- acpi_dbg_level > 1) {
- for (index = 0; index < obj_desc->package.count; index++) {
- acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1);
+ obj_desc->package.elements && acpi_dbg_level > 1) {
+ for (index = 0; index < obj_desc->package.count;
+ index++) {
+ acpi_ex_dump_operand(obj_desc->package.
+ elements[index],
+ depth + 1);
}
}
break;
-
case ACPI_TYPE_REGION:
- acpi_os_printf ("Region %s (%X)",
- acpi_ut_get_region_name (obj_desc->region.space_id),
- obj_desc->region.space_id);
+ acpi_os_printf("Region %s (%X)",
+ acpi_ut_get_region_name(obj_desc->region.
+ space_id),
+ obj_desc->region.space_id);
/*
* If the address and length have not been evaluated,
* don't print them.
*/
if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) {
- acpi_os_printf ("\n");
- }
- else {
- acpi_os_printf (" base %8.8X%8.8X Length %X\n",
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length);
+ acpi_os_printf("\n");
+ } else {
+ acpi_os_printf(" base %8.8X%8.8X Length %X\n",
+ ACPI_FORMAT_UINT64(obj_desc->region.
+ address),
+ obj_desc->region.length);
}
break;
-
case ACPI_TYPE_STRING:
- acpi_os_printf ("String length %X @ %p ",
- obj_desc->string.length,
- obj_desc->string.pointer);
+ acpi_os_printf("String length %X @ %p ",
+ obj_desc->string.length,
+ obj_desc->string.pointer);
- acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
- acpi_os_printf ("\n");
+ acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_os_printf ("bank_field\n");
+ acpi_os_printf("bank_field\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",
- obj_desc->field.bit_length,
- obj_desc->field.access_byte_width,
- obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
- obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
- obj_desc->field.base_byte_offset,
- obj_desc->field.start_field_bit_offset);
+ acpi_os_printf
+ ("region_field: Bits=%X acc_width=%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,
+ obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
+ obj_desc->field.base_byte_offset,
+ obj_desc->field.start_field_bit_offset);
- acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1);
+ acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1);
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf ("index_field\n");
+ acpi_os_printf("index_field\n");
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- acpi_os_printf (
- "buffer_field: %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);
+ acpi_os_printf("buffer_field: %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);
if (!obj_desc->buffer_field.buffer_obj) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n"));
- }
- else if (ACPI_GET_OBJECT_TYPE (obj_desc->buffer_field.buffer_obj) !=
- ACPI_TYPE_BUFFER) {
- acpi_os_printf ("*not a Buffer* \n");
- }
- else {
- acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL* \n"));
+ } else
+ if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj)
+ != ACPI_TYPE_BUFFER) {
+ acpi_os_printf("*not a Buffer* \n");
+ } else {
+ acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj,
+ depth + 1);
}
break;
-
case ACPI_TYPE_EVENT:
- acpi_os_printf ("Event\n");
+ acpi_os_printf("Event\n");
break;
-
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Method(%X) @ %p:%X\n",
- obj_desc->method.param_count,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length);
+ acpi_os_printf("Method(%X) @ %p:%X\n",
+ obj_desc->method.param_count,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length);
break;
-
case ACPI_TYPE_MUTEX:
- acpi_os_printf ("Mutex\n");
+ acpi_os_printf("Mutex\n");
break;
-
case ACPI_TYPE_DEVICE:
- acpi_os_printf ("Device\n");
+ acpi_os_printf("Device\n");
break;
-
case ACPI_TYPE_POWER:
- acpi_os_printf ("Power\n");
+ acpi_os_printf("Power\n");
break;
-
case ACPI_TYPE_PROCESSOR:
- acpi_os_printf ("Processor\n");
+ acpi_os_printf("Processor\n");
break;
-
case ACPI_TYPE_THERMAL:
- acpi_os_printf ("Thermal\n");
+ acpi_os_printf("Thermal\n");
break;
-
default:
/* Unknown Type */
- acpi_os_printf ("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE (obj_desc));
+ acpi_os_printf("Unknown Type %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc));
break;
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_operands
@@ -429,20 +403,15 @@ acpi_ex_dump_operand (
******************************************************************************/
void
-acpi_ex_dump_operands (
- union acpi_operand_object **operands,
- acpi_interpreter_mode interpreter_mode,
- char *ident,
- u32 num_levels,
- char *note,
- char *module_name,
- u32 line_number)
+acpi_ex_dump_operands(union acpi_operand_object **operands,
+ acpi_interpreter_mode interpreter_mode,
+ char *ident,
+ u32 num_levels,
+ char *note, char *module_name, u32 line_number)
{
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_NAME ("ex_dump_operands");
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ex_dump_operands");
if (!ident) {
ident = "?";
@@ -452,9 +421,9 @@ acpi_ex_dump_operands (
note = "?";
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
- ident, num_levels));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
+ ident, num_levels));
if (num_levels == 0) {
num_levels = 1;
@@ -463,16 +432,15 @@ acpi_ex_dump_operands (
/* Dump the operand stack starting at the top */
for (i = 0; num_levels > 0; i--, num_levels--) {
- acpi_ex_dump_operand (operands[i], 0);
+ acpi_ex_dump_operand(operands[i], 0);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "************* Stack dump from %s(%d), %s\n",
- module_name, line_number, note));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "************* Operand Stack dump from %s(%d), %s\n",
+ module_name, line_number, note));
return;
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -487,44 +455,31 @@ acpi_ex_dump_operands (
*
******************************************************************************/
-static void
-acpi_ex_out_string (
- char *title,
- char *value)
+static void acpi_ex_out_string(char *title, char *value)
{
- acpi_os_printf ("%20s : %s\n", title, value);
+ acpi_os_printf("%20s : %s\n", title, value);
}
-static void
-acpi_ex_out_pointer (
- char *title,
- void *value)
+static void acpi_ex_out_pointer(char *title, void *value)
{
- acpi_os_printf ("%20s : %p\n", title, value);
+ acpi_os_printf("%20s : %p\n", title, value);
}
-static void
-acpi_ex_out_integer (
- char *title,
- u32 value)
+static void acpi_ex_out_integer(char *title, u32 value)
{
- acpi_os_printf ("%20s : %X\n", title, value);
+ acpi_os_printf("%20s : %.2X\n", title, value);
}
-static void
-acpi_ex_out_address (
- char *title,
- acpi_physical_address value)
+static void acpi_ex_out_address(char *title, acpi_physical_address value)
{
#if ACPI_MACHINE_WIDTH == 16
- acpi_os_printf ("%20s : %p\n", title, value);
+ acpi_os_printf("%20s : %p\n", title, value);
#else
- acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value));
+ acpi_os_printf("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
#endif
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_node
@@ -536,38 +491,161 @@ acpi_ex_out_address (
*
******************************************************************************/
-void
-acpi_ex_dump_node (
- struct acpi_namespace_node *node,
- u32 flags)
+void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return;
}
}
- acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node));
- acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type));
- acpi_ex_out_integer ("Flags", node->flags);
- acpi_ex_out_integer ("Owner Id", node->owner_id);
- acpi_ex_out_integer ("Reference Count", node->reference_count);
- acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node));
- acpi_ex_out_pointer ("child_list", node->child);
- acpi_ex_out_pointer ("next_peer", node->peer);
- acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node));
+ acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node));
+ acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
+ acpi_ex_out_integer("Flags", node->flags);
+ acpi_ex_out_integer("Owner Id", node->owner_id);
+ acpi_ex_out_integer("Reference Count", node->reference_count);
+ acpi_ex_out_pointer("Attached Object",
+ acpi_ns_get_attached_object(node));
+ acpi_ex_out_pointer("child_list", node->child);
+ acpi_ex_out_pointer("next_peer", node->peer);
+ acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_dump_reference
+ *
+ * PARAMETERS: Object - Descriptor to dump
+ *
+ * DESCRIPTION: Dumps a reference object
+ *
+ ******************************************************************************/
+
+static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
+{
+ struct acpi_buffer ret_buf;
+ acpi_status status;
+
+ if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
+ acpi_os_printf("Named Object %p ", obj_desc->reference.node);
+ ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status =
+ acpi_ns_handle_to_pathname(obj_desc->reference.node,
+ &ret_buf);
+ if (ACPI_FAILURE(status)) {
+ 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);
+ }
+ } else if (obj_desc->reference.object) {
+ acpi_os_printf("\nReferenced Object: %p\n",
+ obj_desc->reference.object);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_dump_package
+ *
+ * PARAMETERS: Object - Descriptor to dump
+ * Level - Indentation Level
+ * Index - Package index for this object
+ *
+ * DESCRIPTION: Dumps the elements of the package
+ *
+ ******************************************************************************/
+
+static void
+acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
+{
+ u32 i;
+
+ /* Indentation and index output */
+
+ if (level > 0) {
+ for (i = 0; i < level; i++) {
+ acpi_os_printf(" ");
+ }
+
+ acpi_os_printf("[%.2d] ", index);
+ }
+
+ acpi_os_printf("%p ", obj_desc);
+
+ /* Null package elements are allowed */
+
+ if (!obj_desc) {
+ acpi_os_printf("[Null Object]\n");
+ return;
+ }
+
+ /* Packages may only contain a few object types */
+
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
+ case ACPI_TYPE_INTEGER:
+
+ acpi_os_printf("[Integer] = %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ acpi_os_printf("[String] Value: ");
+ for (i = 0; i < obj_desc->string.length; i++) {
+ acpi_os_printf("%c", obj_desc->string.pointer[i]);
+ }
+ acpi_os_printf("\n");
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ acpi_os_printf("[Buffer] Length %.2X = ",
+ obj_desc->buffer.length);
+ if (obj_desc->buffer.length) {
+ acpi_ut_dump_buffer((u8 *) obj_desc->buffer.pointer,
+ obj_desc->buffer.length,
+ DB_DWORD_DISPLAY, _COMPONENT);
+ } else {
+ acpi_os_printf("\n");
+ }
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ acpi_os_printf("[Package] Contains %d Elements: \n",
+ obj_desc->package.count);
+
+ for (i = 0; i < obj_desc->package.count; i++) {
+ acpi_ex_dump_package(obj_desc->package.elements[i],
+ level + 1, i);
+ }
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ acpi_os_printf("[Object Reference] ");
+ acpi_ex_dump_reference(obj_desc);
+ break;
+
+ default:
+
+ acpi_os_printf("[Unknown Type] %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc));
+ break;
+ }
+}
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_object_descriptor
*
- * PARAMETERS: *Object - Descriptor to dump
+ * PARAMETERS: Object - Descriptor to dump
* Flags - Force display if TRUE
*
* DESCRIPTION: Dumps the members of the object descriptor given.
@@ -575,202 +653,213 @@ acpi_ex_dump_node (
******************************************************************************/
void
-acpi_ex_dump_object_descriptor (
- union acpi_operand_object *obj_desc,
- u32 flags)
+acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor");
-
+ ACPI_FUNCTION_TRACE("ex_dump_object_descriptor");
if (!obj_desc) {
return_VOID;
}
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return_VOID;
}
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
- acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags);
- acpi_os_printf ("\nAttached Object (%p):\n",
- ((struct acpi_namespace_node *) obj_desc)->object);
- acpi_ex_dump_object_descriptor (
- ((struct acpi_namespace_node *) obj_desc)->object, flags);
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ acpi_ex_dump_node((struct acpi_namespace_node *)obj_desc,
+ flags);
+ acpi_os_printf("\nAttached Object (%p):\n",
+ ((struct acpi_namespace_node *)obj_desc)->
+ object);
+ acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *)
+ obj_desc)->object, flags);
return_VOID;
}
- 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",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc));
+ 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",
+ obj_desc, acpi_ut_get_descriptor_name(obj_desc));
return_VOID;
}
/* Common Fields */
- acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc));
- acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count);
- acpi_ex_out_integer ("Flags", obj_desc->common.flags);
+ acpi_ex_out_string("Type", acpi_ut_get_object_type_name(obj_desc));
+ acpi_ex_out_integer("Reference Count",
+ obj_desc->common.reference_count);
+ acpi_ex_out_integer("Flags", obj_desc->common.flags);
/* Object-specific Fields */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
-
case ACPI_TYPE_STRING:
- acpi_ex_out_integer ("Length", obj_desc->string.length);
+ acpi_ex_out_integer("Length", obj_desc->string.length);
- acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer);
- acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
- acpi_os_printf ("\n");
+ acpi_os_printf("%20s : %p ", "Pointer",
+ obj_desc->string.pointer);
+ acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_BUFFER:
- acpi_ex_out_integer ("Length", obj_desc->buffer.length);
- acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer);
- ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length);
+ acpi_ex_out_integer("Length", obj_desc->buffer.length);
+ acpi_ex_out_pointer("Pointer", obj_desc->buffer.pointer);
+ ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
break;
-
case ACPI_TYPE_PACKAGE:
- acpi_ex_out_integer ("Flags", obj_desc->package.flags);
- acpi_ex_out_integer ("Count", obj_desc->package.count);
- acpi_ex_out_pointer ("Elements", obj_desc->package.elements);
+ acpi_ex_out_integer("Flags", obj_desc->package.flags);
+ acpi_ex_out_integer("Elements", obj_desc->package.count);
+ acpi_ex_out_pointer("Element List", obj_desc->package.elements);
/* Dump the package contents */
- if (obj_desc->package.count > 0) {
- acpi_os_printf ("\nPackage Contents:\n");
- for (i = 0; i < obj_desc->package.count; i++) {
- acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]);
- if (obj_desc->package.elements[i]) {
- acpi_os_printf (" %s",
- acpi_ut_get_object_type_name (obj_desc->package.elements[i]));
- }
- acpi_os_printf ("\n");
- }
- }
+ acpi_os_printf("\nPackage Contents:\n");
+ acpi_ex_dump_package(obj_desc, 0, 0);
break;
-
case ACPI_TYPE_DEVICE:
- acpi_ex_out_pointer ("Handler", obj_desc->device.handler);
- acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->device.handler);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->device.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->device.device_notify);
break;
-
case ACPI_TYPE_EVENT:
- acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore);
+ acpi_ex_out_pointer("Semaphore", obj_desc->event.semaphore);
break;
-
case ACPI_TYPE_METHOD:
- acpi_ex_out_integer ("param_count", obj_desc->method.param_count);
- acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency);
- acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore);
- acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id);
- acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length);
- acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start);
+ acpi_ex_out_integer("param_count",
+ obj_desc->method.param_count);
+ acpi_ex_out_integer("Concurrency",
+ obj_desc->method.concurrency);
+ acpi_ex_out_pointer("Semaphore", obj_desc->method.semaphore);
+ acpi_ex_out_integer("owner_id", obj_desc->method.owner_id);
+ acpi_ex_out_integer("aml_length", obj_desc->method.aml_length);
+ acpi_ex_out_pointer("aml_start", obj_desc->method.aml_start);
break;
-
case ACPI_TYPE_MUTEX:
- acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level);
- acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread);
- acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth);
- acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore);
+ acpi_ex_out_integer("sync_level", obj_desc->mutex.sync_level);
+ acpi_ex_out_pointer("owner_thread",
+ obj_desc->mutex.owner_thread);
+ acpi_ex_out_integer("acquire_depth",
+ obj_desc->mutex.acquisition_depth);
+ acpi_ex_out_pointer("Semaphore", obj_desc->mutex.semaphore);
break;
-
case ACPI_TYPE_REGION:
- acpi_ex_out_integer ("space_id", obj_desc->region.space_id);
- acpi_ex_out_integer ("Flags", obj_desc->region.flags);
- acpi_ex_out_address ("Address", obj_desc->region.address);
- acpi_ex_out_integer ("Length", obj_desc->region.length);
- acpi_ex_out_pointer ("Handler", obj_desc->region.handler);
- acpi_ex_out_pointer ("Next", obj_desc->region.next);
+ acpi_ex_out_integer("space_id", obj_desc->region.space_id);
+ acpi_ex_out_integer("Flags", obj_desc->region.flags);
+ acpi_ex_out_address("Address", obj_desc->region.address);
+ acpi_ex_out_integer("Length", obj_desc->region.length);
+ acpi_ex_out_pointer("Handler", obj_desc->region.handler);
+ acpi_ex_out_pointer("Next", obj_desc->region.next);
break;
-
case ACPI_TYPE_POWER:
- acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level);
- acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order);
- acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify);
+ acpi_ex_out_integer("system_level",
+ obj_desc->power_resource.system_level);
+ acpi_ex_out_integer("resource_order",
+ obj_desc->power_resource.resource_order);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->power_resource.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->power_resource.device_notify);
break;
-
case ACPI_TYPE_PROCESSOR:
- acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id);
- acpi_ex_out_integer ("Length", obj_desc->processor.length);
- acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address);
- acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify);
- acpi_ex_out_pointer ("Handler", obj_desc->processor.handler);
+ acpi_ex_out_integer("Processor ID",
+ obj_desc->processor.proc_id);
+ acpi_ex_out_integer("Length", obj_desc->processor.length);
+ acpi_ex_out_address("Address",
+ (acpi_physical_address) obj_desc->processor.
+ address);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->processor.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->processor.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->processor.handler);
break;
-
case ACPI_TYPE_THERMAL:
- acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify);
- acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->thermal_zone.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->thermal_zone.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->thermal_zone.handler);
break;
-
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags);
- acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width);
- acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
- acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
- acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
- acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ acpi_ex_out_integer("field_flags",
+ obj_desc->common_field.field_flags);
+ acpi_ex_out_integer("access_byte_width",
+ obj_desc->common_field.access_byte_width);
+ acpi_ex_out_integer("bit_length",
+ obj_desc->common_field.bit_length);
+ acpi_ex_out_integer("fld_bit_offset",
+ obj_desc->common_field.
+ start_field_bit_offset);
+ acpi_ex_out_integer("base_byte_offset",
+ obj_desc->common_field.base_byte_offset);
+ acpi_ex_out_pointer("parent_node", obj_desc->common_field.node);
+
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER_FIELD:
- acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj);
+ acpi_ex_out_pointer("buffer_obj",
+ obj_desc->buffer_field.buffer_obj);
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj);
+ acpi_ex_out_pointer("region_obj",
+ obj_desc->field.region_obj);
break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_ex_out_integer ("Value", obj_desc->bank_field.value);
- acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj);
- acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj);
+ acpi_ex_out_integer("Value",
+ obj_desc->bank_field.value);
+ acpi_ex_out_pointer("region_obj",
+ obj_desc->bank_field.region_obj);
+ acpi_ex_out_pointer("bank_obj",
+ obj_desc->bank_field.bank_obj);
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_ex_out_integer ("Value", obj_desc->index_field.value);
- acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj);
- acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj);
+ acpi_ex_out_integer("Value",
+ obj_desc->index_field.value);
+ acpi_ex_out_pointer("Index",
+ obj_desc->index_field.index_obj);
+ acpi_ex_out_pointer("Data",
+ obj_desc->index_field.data_obj);
break;
default:
@@ -779,56 +868,52 @@ acpi_ex_dump_object_descriptor (
}
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
- acpi_ex_out_integer ("target_type", obj_desc->reference.target_type);
- acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (
- obj_desc->reference.opcode))->name);
- acpi_ex_out_integer ("Offset", obj_desc->reference.offset);
- acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object);
- acpi_ex_out_pointer ("Node", obj_desc->reference.node);
- acpi_ex_out_pointer ("Where", obj_desc->reference.where);
-
- if (obj_desc->reference.object) {
- acpi_os_printf ("\nReferenced Object:\n");
- acpi_ex_dump_object_descriptor (obj_desc->reference.object, flags);
- }
- break;
+ acpi_ex_out_integer("target_type",
+ obj_desc->reference.target_type);
+ acpi_ex_out_string("Opcode",
+ (acpi_ps_get_opcode_info
+ (obj_desc->reference.opcode))->name);
+ acpi_ex_out_integer("Offset", obj_desc->reference.offset);
+ acpi_ex_out_pointer("obj_desc", obj_desc->reference.object);
+ acpi_ex_out_pointer("Node", obj_desc->reference.node);
+ acpi_ex_out_pointer("Where", obj_desc->reference.where);
+ acpi_ex_dump_reference(obj_desc);
+ break;
case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
- acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id);
- acpi_ex_out_pointer ("Next", obj_desc->address_space.next);
- acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list);
- acpi_ex_out_pointer ("Node", obj_desc->address_space.node);
- acpi_ex_out_pointer ("Context", obj_desc->address_space.context);
+ acpi_ex_out_integer("space_id",
+ obj_desc->address_space.space_id);
+ acpi_ex_out_pointer("Next", obj_desc->address_space.next);
+ acpi_ex_out_pointer("region_list",
+ obj_desc->address_space.region_list);
+ acpi_ex_out_pointer("Node", obj_desc->address_space.node);
+ acpi_ex_out_pointer("Context", obj_desc->address_space.context);
break;
-
case ACPI_TYPE_LOCAL_NOTIFY:
- acpi_ex_out_pointer ("Node", obj_desc->notify.node);
- acpi_ex_out_pointer ("Context", obj_desc->notify.context);
+ acpi_ex_out_pointer("Node", obj_desc->notify.node);
+ acpi_ex_out_pointer("Context", obj_desc->notify.context);
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
case ACPI_TYPE_LOCAL_EXTRA:
case ACPI_TYPE_LOCAL_DATA:
default:
- acpi_os_printf (
- "ex_dump_object_descriptor: Display not implemented for object type %s\n",
- acpi_ut_get_object_type_name (obj_desc));
+ acpi_os_printf
+ ("ex_dump_object_descriptor: Display not implemented for object type %s\n",
+ acpi_ut_get_object_type_name(obj_desc));
break;
}
return_VOID;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
#endif
-
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index 22c8fa480f60..ab1ba399aa28 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -41,15 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exfield")
-
+ACPI_MODULE_NAME("exfield")
/*******************************************************************************
*
@@ -65,64 +62,70 @@
* Buffer, depending on the size of the field.
*
******************************************************************************/
-
acpi_status
-acpi_ex_read_data_from_field (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **ret_buffer_desc)
+acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **ret_buffer_desc)
{
- acpi_status status;
- union acpi_operand_object *buffer_desc;
- acpi_size length;
- void *buffer;
- u8 locked;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_read_data_from_field", obj_desc);
+ acpi_status status;
+ union acpi_operand_object *buffer_desc;
+ acpi_size length;
+ void *buffer;
+ u8 locked;
+ ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc);
/* Parameter validation */
if (!obj_desc) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
+ }
+ if (!ret_buffer_desc) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- }
- else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
- (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+ } else
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
+ && (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_SMBUS)) {
/*
* This is an SMBus read. We must create a buffer to hold the data
* and directly access the region handler.
*/
- buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
+ buffer_desc =
+ acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.
+ field_flags);
/*
* Perform the read.
* Note: Smbus protocol value is passed in upper 16-bits of Function
*/
- status = acpi_ex_access_region (obj_desc, 0,
- ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer),
- ACPI_READ | (obj_desc->field.attribute << 16));
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_access_region(obj_desc, 0,
+ ACPI_CAST_PTR(acpi_integer,
+ buffer_desc->
+ buffer.pointer),
+ ACPI_READ | (obj_desc->field.
+ attribute << 16));
+ acpi_ex_release_global_lock(locked);
goto exit;
}
@@ -136,22 +139,22 @@ acpi_ex_read_data_from_field (
*
* Note: Field.length is in bits.
*/
- length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length);
+ 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);
+ buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
- }
- else {
+ } else {
/* Field will fit within an Integer (normal case) */
- buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
length = acpi_gbl_integer_byte_width;
@@ -159,37 +162,36 @@ acpi_ex_read_data_from_field (
buffer = &buffer_desc->integer.value;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %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",
- obj_desc->common_field.bit_length,
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.base_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %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",
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Read from the field */
- status = acpi_ex_extract_from_field (obj_desc, buffer, (u32) length);
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
+ acpi_ex_release_global_lock(locked);
-
-exit:
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (buffer_desc);
- }
- else if (ret_buffer_desc) {
+ exit:
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(buffer_desc);
+ } else {
*ret_buffer_desc = buffer_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_write_data_to_field
@@ -205,97 +207,96 @@ exit:
******************************************************************************/
acpi_status
-acpi_ex_write_data_to_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc)
+acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc)
{
- acpi_status status;
- u32 length;
- u32 required_length;
- void *buffer;
- void *new_buffer;
- u8 locked;
- union acpi_operand_object *buffer_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_write_data_to_field", obj_desc);
+ acpi_status status;
+ u32 length;
+ u32 required_length;
+ void *buffer;
+ void *new_buffer;
+ u8 locked;
+ union acpi_operand_object *buffer_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc);
/* Parameter validation */
if (!source_desc || !obj_desc) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- }
- else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
- (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+ } else
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
+ && (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_SMBUS)) {
/*
* This is an SMBus write. We will bypass the entire field mechanism
* and handoff the buffer directly to the handler.
*
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
*/
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_REPORT_ERROR(("SMBus write requires Buffer, found type %s\n", acpi_ut_get_object_type_name(source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
- ACPI_REPORT_ERROR ((
- "SMBus write requires Buffer of length %X, found length %X\n",
- ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
+ ACPI_REPORT_ERROR(("SMBus write requires Buffer of length %X, found length %X\n", ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
- return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
- buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
+ buffer_desc =
+ acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
- ACPI_MEMCPY (buffer, source_desc->buffer.pointer,
- ACPI_SMBUS_BUFFER_SIZE);
+ ACPI_MEMCPY(buffer, source_desc->buffer.pointer,
+ ACPI_SMBUS_BUFFER_SIZE);
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.
+ field_flags);
/*
* Perform the write (returns status and perhaps data in the
* same buffer)
* Note: SMBus protocol type is passed in upper 16-bits of Function.
*/
- status = acpi_ex_access_region (obj_desc, 0,
- (acpi_integer *) buffer,
- ACPI_WRITE | (obj_desc->field.attribute << 16));
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_access_region(obj_desc, 0,
+ (acpi_integer *) buffer,
+ ACPI_WRITE | (obj_desc->field.
+ attribute << 16));
+ acpi_ex_release_global_lock(locked);
*result_desc = buffer_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Get a pointer to the data to be written */
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
buffer = &source_desc->integer.value;
- length = sizeof (source_desc->integer.value);
+ length = sizeof(source_desc->integer.value);
break;
case ACPI_TYPE_BUFFER:
@@ -309,7 +310,7 @@ acpi_ex_write_data_to_field (
break;
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -319,15 +320,15 @@ acpi_ex_write_data_to_field (
* the ACPI specification.
*/
new_buffer = NULL;
- required_length = ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length);
+ required_length =
+ 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_MEM_CALLOCATE(required_length);
if (!new_buffer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -335,40 +336,42 @@ acpi_ex_write_data_to_field (
* at Byte zero. All unused (upper) bytes of the
* buffer will be 0.
*/
- ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length);
+ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length);
buffer = new_buffer;
length = required_length;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %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",
- obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)),
- ACPI_GET_OBJECT_TYPE (obj_desc),
- obj_desc->common_field.bit_length,
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.base_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %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",
+ obj_desc,
+ acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)),
+ ACPI_GET_OBJECT_TYPE(obj_desc),
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Write to the field */
- status = acpi_ex_insert_into_field (obj_desc, buffer, length);
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_insert_into_field(obj_desc, buffer, length);
+ acpi_ex_release_global_lock(locked);
/* Free temporary buffer if we used one */
if (new_buffer) {
- ACPI_MEM_FREE (new_buffer);
+ ACPI_MEM_FREE(new_buffer);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index 3c2f89e00f78..ba6e08843c29 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -41,36 +41,28 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acevents.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exfldio")
+ACPI_MODULE_NAME("exfldio")
/* Local prototypes */
-
static acpi_status
-acpi_ex_field_datum_io (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 read_write);
+acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 read_write);
static u8
-acpi_ex_register_overflow (
- union acpi_operand_object *obj_desc,
- acpi_integer value);
+acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
+ acpi_integer value);
static acpi_status
-acpi_ex_setup_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset);
-
+acpi_ex_setup_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset);
/*******************************************************************************
*
@@ -89,27 +81,25 @@ acpi_ex_setup_region (
******************************************************************************/
static acpi_status
-acpi_ex_setup_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset)
+acpi_ex_setup_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *rgn_desc;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *rgn_desc;
+ ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset);
rgn_desc = obj_desc->common_field.region_obj;
/* We must have a valid region */
- if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
- ACPI_GET_OBJECT_TYPE (rgn_desc),
- acpi_ut_get_object_type_name (rgn_desc)));
+ if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Region, found type %X (%s)\n",
+ ACPI_GET_OBJECT_TYPE(rgn_desc),
+ acpi_ut_get_object_type_name(rgn_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -117,26 +107,25 @@ acpi_ex_setup_region (
* evaluate them now and save the results.
*/
if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_region_arguments (rgn_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_region_arguments(rgn_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
/* SMBus has a non-linear address space */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
#ifdef ACPI_UNDER_DEVELOPMENT
/*
* If the Field access is any_acc, we can now compute the optimal
* access (because we know know the length of the parent region)
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
#endif
@@ -147,56 +136,64 @@ acpi_ex_setup_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)) {
+ 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
* field if it is within the region length rounded up to the next
* access width boundary.
*/
- if (ACPI_ROUND_UP (rgn_desc->region.length,
- obj_desc->common_field.access_byte_width) >=
- (obj_desc->common_field.base_byte_offset +
- (acpi_native_uint) obj_desc->common_field.access_byte_width +
- field_datum_byte_offset)) {
- return_ACPI_STATUS (AE_OK);
+ if (ACPI_ROUND_UP(rgn_desc->region.length,
+ obj_desc->common_field.
+ access_byte_width) >=
+ (obj_desc->common_field.base_byte_offset +
+ (acpi_native_uint) obj_desc->common_field.
+ access_byte_width + field_datum_byte_offset)) {
+ return_ACPI_STATUS(AE_OK);
}
}
- if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
+ if (rgn_desc->region.length <
+ obj_desc->common_field.access_byte_width) {
/*
* This is the case where the access_type (acc_word, etc.) is wider
* than the region itself. For example, a region of length one
* byte, and a field with Dword access specified.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name (obj_desc->common_field.node),
- obj_desc->common_field.access_byte_width,
- acpi_ut_get_node_name (rgn_desc->region.node),
- rgn_desc->region.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ node),
+ obj_desc->common_field.
+ access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->
+ region.node),
+ rgn_desc->region.length));
}
/*
* Offset rounded up to next multiple of field width
* exceeds region length, indicate an error
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name (obj_desc->common_field.node),
- obj_desc->common_field.base_byte_offset,
- field_datum_byte_offset, obj_desc->common_field.access_byte_width,
- acpi_ut_get_node_name (rgn_desc->region.node),
- rgn_desc->region.length));
-
- return_ACPI_STATUS (AE_AML_REGION_LIMIT);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
+ acpi_ut_get_node_name(obj_desc->common_field.
+ node),
+ obj_desc->common_field.base_byte_offset,
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->region.node),
+ rgn_desc->region.length));
+
+ return_ACPI_STATUS(AE_AML_REGION_LIMIT);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_access_region
@@ -216,27 +213,23 @@ acpi_ex_setup_region (
******************************************************************************/
acpi_status
-acpi_ex_access_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 function)
+acpi_ex_access_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 function)
{
- acpi_status status;
- union acpi_operand_object *rgn_desc;
- acpi_physical_address address;
-
-
- ACPI_FUNCTION_TRACE ("ex_access_region");
+ acpi_status status;
+ union acpi_operand_object *rgn_desc;
+ acpi_physical_address address;
+ ACPI_FUNCTION_TRACE("ex_access_region");
/*
* Ensure that the region operands are fully evaluated and verify
* the validity of the request
*/
- status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -248,50 +241,53 @@ acpi_ex_access_region (
*/
rgn_desc = obj_desc->common_field.region_obj;
address = rgn_desc->region.address +
- obj_desc->common_field.base_byte_offset +
- field_datum_byte_offset;
+ obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
if ((function & ACPI_IO_MASK) == ACPI_READ) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
- " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id,
- obj_desc->common_field.access_byte_width,
- obj_desc->common_field.base_byte_offset,
- field_datum_byte_offset,
- ACPI_FORMAT_UINT64 (address)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
+ " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
+ acpi_ut_get_region_name(rgn_desc->region.
+ space_id),
+ rgn_desc->region.space_id,
+ obj_desc->common_field.access_byte_width,
+ obj_desc->common_field.base_byte_offset,
+ field_datum_byte_offset,
+ ACPI_FORMAT_UINT64(address)));
/* Invoke the appropriate address_space/op_region handler */
- status = acpi_ev_address_space_dispatch (rgn_desc, function,
- address,
- ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
+ status = acpi_ev_address_space_dispatch(rgn_desc, function,
+ address,
+ ACPI_MUL_8(obj_desc->
+ common_field.
+ access_byte_width),
+ value);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_IMPLEMENTED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Region %s(%X) not implemented\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id));
- }
- else if (status == AE_NOT_EXIST) {
- ACPI_REPORT_ERROR ((
- "Region %s(%X) has no handler\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region %s(%X) not implemented\n",
+ acpi_ut_get_region_name(rgn_desc->
+ region.
+ space_id),
+ rgn_desc->region.space_id));
+ } else if (status == AE_NOT_EXIST) {
+ ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n",
+ acpi_ut_get_region_name(rgn_desc->
+ region.
+ space_id),
+ rgn_desc->region.space_id));
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_register_overflow
@@ -310,9 +306,8 @@ acpi_ex_access_region (
******************************************************************************/
static u8
-acpi_ex_register_overflow (
- union acpi_operand_object *obj_desc,
- acpi_integer value)
+acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
+ acpi_integer value)
{
if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
@@ -336,7 +331,6 @@ acpi_ex_register_overflow (
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_field_datum_io
@@ -356,18 +350,14 @@ acpi_ex_register_overflow (
******************************************************************************/
static acpi_status
-acpi_ex_field_datum_io (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 read_write)
+acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 read_write)
{
- acpi_status status;
- acpi_integer local_value;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);
+ acpi_status status;
+ acpi_integer local_value;
+ ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset);
if (read_write == ACPI_READ) {
if (!value) {
@@ -392,16 +382,16 @@ acpi_ex_field_datum_io (
* index_field - Write to an Index Register, then read/write from/to a
* Data Register
*/
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER_FIELD:
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -410,47 +400,50 @@ acpi_ex_field_datum_io (
* Copy the data from the source buffer.
* Length is the field width in bytes.
*/
- ACPI_MEMCPY (value,
- (obj_desc->buffer_field.buffer_obj)->buffer.pointer +
- obj_desc->buffer_field.base_byte_offset +
- field_datum_byte_offset,
- obj_desc->common_field.access_byte_width);
- }
- else {
+ ACPI_MEMCPY(value,
+ (obj_desc->buffer_field.buffer_obj)->buffer.
+ pointer +
+ obj_desc->buffer_field.base_byte_offset +
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width);
+ } else {
/*
* Copy the data to the target buffer.
* Length is the field width in bytes.
*/
- ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer +
- obj_desc->buffer_field.base_byte_offset +
- field_datum_byte_offset,
- value, obj_desc->common_field.access_byte_width);
+ ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
+ pointer +
+ obj_desc->buffer_field.base_byte_offset +
+ field_datum_byte_offset, value,
+ obj_desc->common_field.access_byte_width);
}
status = AE_OK;
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
/*
* Ensure that the bank_value is not beyond the capacity of
* the register
*/
- if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
- (acpi_integer) obj_desc->bank_field.value)) {
- return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
+ if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
+ (acpi_integer) obj_desc->
+ bank_field.value)) {
+ return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
}
/*
* For bank_fields, we must write the bank_value to the bank_register
* (itself a region_field) before we can access the data.
*/
- status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
- &obj_desc->bank_field.value,
- sizeof (obj_desc->bank_field.value));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
+ &obj_desc->bank_field.value,
+ sizeof(obj_desc->bank_field.
+ value));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -460,90 +453,92 @@ acpi_ex_field_datum_io (
/*lint -fallthrough */
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
/*
* For simple region_fields, we just directly access the owning
* Operation Region.
*/
- status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
- read_write);
+ status =
+ acpi_ex_access_region(obj_desc, field_datum_byte_offset,
+ value, read_write);
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
-
/*
* Ensure that the index_value is not beyond the capacity of
* the register
*/
- if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
- (acpi_integer) obj_desc->index_field.value)) {
- return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
+ if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
+ (acpi_integer) obj_desc->
+ index_field.value)) {
+ return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
}
/* Write the index value to the index_register (itself a region_field) */
field_datum_byte_offset += obj_desc->index_field.value;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Write to Index Register: Value %8.8X\n",
- field_datum_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Write to Index Register: Value %8.8X\n",
+ field_datum_byte_offset));
- status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
- &field_datum_byte_offset,
- sizeof (field_datum_byte_offset));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
+ &field_datum_byte_offset,
+ sizeof(field_datum_byte_offset));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "I/O to Data Register: value_ptr %p\n",
- value));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "I/O to Data Register: value_ptr %p\n",
+ value));
if (read_write == ACPI_READ) {
/* Read the datum from the data_register */
- status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
- value, sizeof (acpi_integer));
- }
- else {
+ status =
+ acpi_ex_extract_from_field(obj_desc->index_field.
+ data_obj, value,
+ sizeof(acpi_integer));
+ } else {
/* Write the datum to the data_register */
- status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
- value, sizeof (acpi_integer));
+ status =
+ acpi_ex_insert_into_field(obj_desc->index_field.
+ data_obj, value,
+ sizeof(acpi_integer));
}
break;
-
default:
- ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
- ACPI_GET_OBJECT_TYPE (obj_desc)));
+ ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_INTERNAL;
break;
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
if (read_write == ACPI_READ) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Value Read %8.8X%8.8X, Width %d\n",
- ACPI_FORMAT_UINT64 (*value),
- obj_desc->common_field.access_byte_width));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Value Written %8.8X%8.8X, Width %d\n",
- ACPI_FORMAT_UINT64 (*value),
- obj_desc->common_field.access_byte_width));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Value Read %8.8X%8.8X, Width %d\n",
+ ACPI_FORMAT_UINT64(*value),
+ obj_desc->common_field.
+ access_byte_width));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Value Written %8.8X%8.8X, Width %d\n",
+ ACPI_FORMAT_UINT64(*value),
+ obj_desc->common_field.
+ access_byte_width));
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_write_with_update_rule
@@ -560,19 +555,16 @@ acpi_ex_field_datum_io (
******************************************************************************/
acpi_status
-acpi_ex_write_with_update_rule (
- union acpi_operand_object *obj_desc,
- acpi_integer mask,
- acpi_integer field_value,
- u32 field_datum_byte_offset)
+acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
+ acpi_integer mask,
+ acpi_integer field_value,
+ u32 field_datum_byte_offset)
{
- acpi_status status = AE_OK;
- acpi_integer merged_value;
- acpi_integer current_value;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);
+ acpi_status status = AE_OK;
+ acpi_integer merged_value;
+ acpi_integer current_value;
+ ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask);
/* Start with the new bits */
@@ -583,22 +575,27 @@ acpi_ex_write_with_update_rule (
if (mask != ACPI_INTEGER_MAX) {
/* Decode the update rule */
- switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
+ switch (obj_desc->common_field.
+ field_flags & AML_FIELD_UPDATE_RULE_MASK) {
case AML_FIELD_UPDATE_PRESERVE:
/*
* Check if update rule needs to be applied (not if mask is all
* ones) The left shift drops the bits we want to ignore.
*/
- if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
- ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
+ if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
+ ACPI_MUL_8(obj_desc->common_field.
+ access_byte_width))) != 0) {
/*
* Read the current contents of the byte/word/dword containing
* the field, and merge with the new field value.
*/
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &current_value, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_field_datum_io(obj_desc,
+ field_datum_byte_offset,
+ &current_value,
+ ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
merged_value |= (current_value & ~mask);
@@ -621,30 +618,31 @@ acpi_ex_write_with_update_rule (
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "write_with_update_rule: Unknown update_rule setting: %X\n",
- (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "write_with_update_rule: Unknown update_rule setting: %X\n",
+ (obj_desc->common_field.
+ field_flags &
+ AML_FIELD_UPDATE_RULE_MASK)));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
}
- 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",
- ACPI_FORMAT_UINT64 (mask),
- field_datum_byte_offset,
- obj_desc->common_field.access_byte_width,
- ACPI_FORMAT_UINT64 (field_value),
- ACPI_FORMAT_UINT64 (merged_value)));
+ 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",
+ ACPI_FORMAT_UINT64(mask),
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width,
+ ACPI_FORMAT_UINT64(field_value),
+ ACPI_FORMAT_UINT64(merged_value)));
/* Write the merged value */
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &merged_value, ACPI_WRITE);
+ status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
+ &merged_value, ACPI_WRITE);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_extract_from_field
@@ -660,54 +658,54 @@ acpi_ex_write_with_update_rule (
******************************************************************************/
acpi_status
-acpi_ex_extract_from_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length)
+acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length)
{
- acpi_status status;
- acpi_integer raw_datum;
- acpi_integer merged_datum;
- u32 field_offset = 0;
- u32 buffer_offset = 0;
- u32 buffer_tail_bits;
- u32 datum_count;
- u32 field_datum_count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_extract_from_field");
-
+ acpi_status status;
+ acpi_integer raw_datum;
+ acpi_integer merged_datum;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
+ u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ex_extract_from_field");
/* Validate target buffer and clear it */
- if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length, buffer_length));
+ if (buffer_length <
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length,
+ buffer_length));
- return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+ return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
- ACPI_MEMSET (buffer, 0, buffer_length);
+ ACPI_MEMSET(buffer, 0, buffer_length);
/* Compute the number of datums (access width data items) */
- 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);
+ 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);
/* Priming read from the field */
- status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
+ ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum >> obj_desc->common_field.start_field_bit_offset;
/* Read the rest of the field */
@@ -715,17 +713,17 @@ acpi_ex_extract_from_field (
/* Get next input datum from the field */
field_offset += obj_desc->common_field.access_byte_width;
- status = acpi_ex_field_datum_io (obj_desc, field_offset,
- &raw_datum, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_field_datum_io(obj_desc, field_offset,
+ &raw_datum, ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Merge with previous datum if necessary */
merged_datum |= raw_datum <<
- (obj_desc->common_field.access_bit_width -
- obj_desc->common_field.start_field_bit_offset);
+ (obj_desc->common_field.access_bit_width -
+ obj_desc->common_field.start_field_bit_offset);
if (i == datum_count) {
break;
@@ -733,32 +731,32 @@ acpi_ex_extract_from_field (
/* Write merged datum to target buffer */
- ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
buffer_offset += obj_desc->common_field.access_byte_width;
- merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum >> obj_desc->common_field.start_field_bit_offset;
}
/* Mask off any extra bits in the last datum */
buffer_tail_bits = obj_desc->common_field.bit_length %
- obj_desc->common_field.access_bit_width;
+ obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
- merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
+ merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
/* Write the last datum to the buffer */
- ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_insert_into_field
@@ -774,53 +772,54 @@ acpi_ex_extract_from_field (
******************************************************************************/
acpi_status
-acpi_ex_insert_into_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length)
+acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length)
{
- acpi_status status;
- acpi_integer mask;
- acpi_integer merged_datum;
- acpi_integer raw_datum = 0;
- u32 field_offset = 0;
- u32 buffer_offset = 0;
- u32 buffer_tail_bits;
- u32 datum_count;
- u32 field_datum_count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_insert_into_field");
-
+ acpi_status status;
+ acpi_integer mask;
+ acpi_integer merged_datum;
+ acpi_integer raw_datum = 0;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
+ u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ex_insert_into_field");
/* Validate input buffer */
- if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length, buffer_length));
+ if (buffer_length <
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length,
+ buffer_length));
- return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+ return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
/* Compute the number of datums (access width data items) */
- 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);
+ 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 */
- ACPI_MEMCPY (&raw_datum, buffer,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(&raw_datum, buffer,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum << obj_desc->common_field.start_field_bit_offset;
/* Write the entire field */
@@ -828,18 +827,19 @@ acpi_ex_insert_into_field (
/* Write merged datum to the target field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule (obj_desc, mask,
- merged_datum, field_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_write_with_update_rule(obj_desc, mask,
+ merged_datum,
+ field_offset);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Start new output datum by merging with previous input datum */
field_offset += obj_desc->common_field.access_byte_width;
merged_datum = raw_datum >>
- (obj_desc->common_field.access_bit_width -
- obj_desc->common_field.start_field_bit_offset);
+ (obj_desc->common_field.access_bit_width -
+ obj_desc->common_field.start_field_bit_offset);
mask = ACPI_INTEGER_MAX;
if (i == datum_count) {
@@ -849,28 +849,28 @@ acpi_ex_insert_into_field (
/* Get the next input datum from the buffer */
buffer_offset += obj_desc->common_field.access_byte_width;
- ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
- merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
+ ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
+ merged_datum |=
+ raw_datum << obj_desc->common_field.start_field_bit_offset;
}
/* Mask off any extra bits in the last datum */
buffer_tail_bits = (obj_desc->common_field.bit_length +
- obj_desc->common_field.start_field_bit_offset) %
- obj_desc->common_field.access_bit_width;
+ obj_desc->common_field.start_field_bit_offset) %
+ obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
- mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
+ mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
/* Write the last datum to the field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule (obj_desc,
- mask, merged_datum, field_offset);
+ status = acpi_ex_write_with_update_rule(obj_desc,
+ mask, merged_datum,
+ field_offset);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 022f281345b8..a3f4d72bedc9 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -42,15 +42,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exmisc")
-
+ACPI_MODULE_NAME("exmisc")
/*******************************************************************************
*
@@ -66,27 +63,23 @@
* Common code for the ref_of_op and the cond_ref_of_op.
*
******************************************************************************/
-
acpi_status
-acpi_ex_get_object_reference (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *reference_obj;
- union acpi_operand_object *referenced_obj;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc);
+ union acpi_operand_object *reference_obj;
+ union acpi_operand_object *referenced_obj;
+ ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc);
*return_desc = NULL;
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
- if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -104,13 +97,11 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
- obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
break;
-
case ACPI_DESC_TYPE_NAMED:
/*
@@ -119,34 +110,32 @@ acpi_ex_get_object_reference (
referenced_obj = obj_desc;
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
- ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
- return_ACPI_STATUS (AE_TYPE);
+ ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
+ return_ACPI_STATUS(AE_TYPE);
}
-
/* Create a new reference object */
- reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ reference_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!reference_obj) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
reference_obj->reference.opcode = AML_REF_OF_OP;
reference_obj->reference.object = referenced_obj;
*return_desc = reference_obj;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Object %p Type [%s], returning Reference %p\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Object %p Type [%s], returning Reference %p\n",
+ obj_desc, acpi_ut_get_object_type_name(obj_desc),
+ *return_desc));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_concat_template
@@ -163,63 +152,58 @@ acpi_ex_get_object_reference (
******************************************************************************/
acpi_status
-acpi_ex_concat_template (
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_concat_template(union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
- u8 *end_tag1;
- u8 *end_tag2;
- acpi_size length1;
- acpi_size length2;
-
-
- ACPI_FUNCTION_TRACE ("ex_concat_template");
+ union acpi_operand_object *return_desc;
+ u8 *new_buf;
+ u8 *end_tag1;
+ u8 *end_tag2;
+ acpi_size length1;
+ acpi_size length2;
+ ACPI_FUNCTION_TRACE("ex_concat_template");
/* Find the end_tags in each resource template */
- end_tag1 = acpi_ut_get_resource_end_tag (operand0);
- end_tag2 = acpi_ut_get_resource_end_tag (operand1);
+ end_tag1 = acpi_ut_get_resource_end_tag(operand0);
+ end_tag2 = acpi_ut_get_resource_end_tag(operand1);
if (!end_tag1 || !end_tag2) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Compute the length of each part */
- length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer);
- length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) +
- 2; /* Size of END_TAG */
+ length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer);
+ length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2; /* Size of END_TAG */
/* Create a new buffer object for the result */
- return_desc = acpi_ut_create_buffer_object (length1 + length2);
+ return_desc = acpi_ut_create_buffer_object(length1 + length2);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the templates to the new descriptor */
new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1);
- ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2);
+ ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1);
+ ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2);
/* Compute the new checksum */
new_buf[return_desc->buffer.length - 1] =
- acpi_ut_generate_checksum (return_desc->buffer.pointer,
- (return_desc->buffer.length - 1));
+ acpi_ut_generate_checksum(return_desc->buffer.pointer,
+ (return_desc->buffer.length - 1));
/* Return the completed template descriptor */
*actual_return_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_concatenate
@@ -236,21 +220,18 @@ acpi_ex_concat_template (
******************************************************************************/
acpi_status
-acpi_ex_do_concatenate (
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_do_concatenate(union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *local_operand1 = operand1;
- union acpi_operand_object *return_desc;
- char *new_buf;
- acpi_status status;
- acpi_size new_length;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_concatenate");
+ union acpi_operand_object *local_operand1 = operand1;
+ union acpi_operand_object *return_desc;
+ char *new_buf;
+ acpi_status status;
+ acpi_size new_length;
+ ACPI_FUNCTION_TRACE("ex_do_concatenate");
/*
* Convert the second operand if necessary. The first operand
@@ -259,27 +240,28 @@ acpi_ex_do_concatenate (
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
- status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
+ status =
+ acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_convert_to_string (operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
- status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
+ status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
- ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
- ACPI_GET_OBJECT_TYPE (operand0)));
+ ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n",
+ ACPI_GET_OBJECT_TYPE(operand0)));
status = AE_AML_INTERNAL;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -296,32 +278,33 @@ acpi_ex_do_concatenate (
* 2) Two Strings concatenated to produce a new String
* 3) Two Buffers concatenated to produce a new Buffer
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
/* Result of two Integers is a Buffer */
/* Need enough buffer space for two integers */
- return_desc = acpi_ut_create_buffer_object (
- ACPI_MUL_2 (acpi_gbl_integer_byte_width));
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ ACPI_MUL_2
+ (acpi_gbl_integer_byte_width));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- new_buf = (char *) return_desc->buffer.pointer;
+ new_buf = (char *)return_desc->buffer.pointer;
/* Copy the first integer, LSB first */
- ACPI_MEMCPY (new_buf,
- &operand0->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf,
+ &operand0->integer.value,
+ acpi_gbl_integer_byte_width);
/* Copy the second integer (LSB first) after the first */
- ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width,
- &local_operand1->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width,
+ &local_operand1->integer.value,
+ acpi_gbl_integer_byte_width);
break;
case ACPI_TYPE_STRING:
@@ -329,13 +312,13 @@ acpi_ex_do_concatenate (
/* Result of two Strings is a String */
new_length = (acpi_size) operand0->string.length +
- (acpi_size) local_operand1->string.length;
+ (acpi_size) local_operand1->string.length;
if (new_length > ACPI_MAX_STRING_CONVERSION) {
status = AE_AML_STRING_LIMIT;
goto cleanup;
}
- return_desc = acpi_ut_create_string_object (new_length);
+ return_desc = acpi_ut_create_string_object(new_length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -345,56 +328,56 @@ acpi_ex_do_concatenate (
/* Concatenate the strings */
- ACPI_STRCPY (new_buf,
- operand0->string.pointer);
- ACPI_STRCPY (new_buf + operand0->string.length,
- local_operand1->string.pointer);
+ ACPI_STRCPY(new_buf, operand0->string.pointer);
+ ACPI_STRCPY(new_buf + operand0->string.length,
+ local_operand1->string.pointer);
break;
case ACPI_TYPE_BUFFER:
/* Result of two Buffers is a Buffer */
- return_desc = acpi_ut_create_buffer_object (
- (acpi_size) operand0->buffer.length +
- (acpi_size) local_operand1->buffer.length);
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ operand0->buffer.
+ length +
+ (acpi_size)
+ local_operand1->
+ buffer.length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- new_buf = (char *) return_desc->buffer.pointer;
+ new_buf = (char *)return_desc->buffer.pointer;
/* Concatenate the buffers */
- ACPI_MEMCPY (new_buf,
- operand0->buffer.pointer,
- operand0->buffer.length);
- ACPI_MEMCPY (new_buf + operand0->buffer.length,
- local_operand1->buffer.pointer,
- local_operand1->buffer.length);
+ ACPI_MEMCPY(new_buf,
+ operand0->buffer.pointer, operand0->buffer.length);
+ ACPI_MEMCPY(new_buf + operand0->buffer.length,
+ local_operand1->buffer.pointer,
+ local_operand1->buffer.length);
break;
default:
/* Invalid object type, should not happen here */
- ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
- ACPI_GET_OBJECT_TYPE (operand0)));
- status =AE_AML_INTERNAL;
+ ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n",
+ ACPI_GET_OBJECT_TYPE(operand0)));
+ status = AE_AML_INTERNAL;
goto cleanup;
}
*actual_return_desc = return_desc;
-cleanup:
+ cleanup:
if (local_operand1 != operand1) {
- acpi_ut_remove_reference (local_operand1);
+ acpi_ut_remove_reference(local_operand1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_math_op
@@ -412,62 +395,49 @@ cleanup:
******************************************************************************/
acpi_integer
-acpi_ex_do_math_op (
- u16 opcode,
- acpi_integer integer0,
- acpi_integer integer1)
+acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
switch (opcode) {
- case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
+ case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
return (integer0 + integer1);
-
- case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
+ case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
return (integer0 & integer1);
-
- case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
+ case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
return (~(integer0 & integer1));
-
- case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
+ case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
return (integer0 | integer1);
-
- case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
+ case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
return (~(integer0 | integer1));
-
- case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
+ case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
return (integer0 ^ integer1);
-
- case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
+ case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
return (integer0 * integer1);
-
- case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result)*/
+ case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
return (integer0 << integer1);
-
- case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
+ case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
return (integer0 >> integer1);
-
- case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
+ case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
return (integer0 - integer1);
@@ -477,7 +447,6 @@ acpi_ex_do_math_op (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_numeric_op
@@ -499,28 +468,24 @@ acpi_ex_do_math_op (
******************************************************************************/
acpi_status
-acpi_ex_do_logical_numeric_op (
- u16 opcode,
- acpi_integer integer0,
- acpi_integer integer1,
- u8 *logical_result)
+acpi_ex_do_logical_numeric_op(u16 opcode,
+ acpi_integer integer0,
+ acpi_integer integer1, u8 * logical_result)
{
- acpi_status status = AE_OK;
- u8 local_result = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op");
+ acpi_status status = AE_OK;
+ u8 local_result = FALSE;
+ ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op");
switch (opcode) {
- case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
+ case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
if (integer0 && integer1) {
local_result = TRUE;
}
break;
- case AML_LOR_OP: /* LOr (Integer0, Integer1) */
+ case AML_LOR_OP: /* LOr (Integer0, Integer1) */
if (integer0 || integer1) {
local_result = TRUE;
@@ -535,10 +500,9 @@ acpi_ex_do_logical_numeric_op (
/* Return the logical result and status */
*logical_result = local_result;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_op
@@ -566,24 +530,20 @@ acpi_ex_do_logical_numeric_op (
******************************************************************************/
acpi_status
-acpi_ex_do_logical_op (
- u16 opcode,
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- u8 *logical_result)
+acpi_ex_do_logical_op(u16 opcode,
+ union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1, u8 * logical_result)
{
- union acpi_operand_object *local_operand1 = operand1;
- acpi_integer integer0;
- acpi_integer integer1;
- u32 length0;
- u32 length1;
- acpi_status status = AE_OK;
- u8 local_result = FALSE;
- int compare;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_logical_op");
+ union acpi_operand_object *local_operand1 = operand1;
+ acpi_integer integer0;
+ acpi_integer integer1;
+ u32 length0;
+ u32 length1;
+ acpi_status status = AE_OK;
+ u8 local_result = FALSE;
+ int compare;
+ ACPI_FUNCTION_TRACE("ex_do_logical_op");
/*
* Convert the second operand if necessary. The first operand
@@ -592,18 +552,19 @@ acpi_ex_do_logical_op (
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
- status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
+ status =
+ acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_convert_to_string (operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
- status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
+ status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
@@ -611,14 +572,14 @@ acpi_ex_do_logical_op (
break;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Two cases: 1) Both Integers, 2) Both Strings or Buffers
*/
- if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) {
/*
* 1) Both operands are of type integer
* Note: local_operand1 may have changed above
@@ -627,21 +588,21 @@ acpi_ex_do_logical_op (
integer1 = local_operand1->integer.value;
switch (opcode) {
- case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
+ case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
if (integer0 == integer1) {
local_result = TRUE;
}
break;
- case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
+ case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (integer0 > integer1) {
local_result = TRUE;
}
break;
- case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
+ case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (integer0 < integer1) {
local_result = TRUE;
@@ -652,8 +613,7 @@ acpi_ex_do_logical_op (
status = AE_AML_INTERNAL;
break;
}
- }
- else {
+ } else {
/*
* 2) Both operands are Strings or both are Buffers
* Note: Code below takes advantage of common Buffer/String
@@ -665,31 +625,31 @@ acpi_ex_do_logical_op (
/* Lexicographic compare: compare the data bytes */
- compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer,
- (const char * ) local_operand1->buffer.pointer,
- (length0 > length1) ? length1 : length0);
+ compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer,
+ (const char *)local_operand1->buffer.
+ pointer,
+ (length0 > length1) ? length1 : length0);
switch (opcode) {
- case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
+ case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
/* Length and all bytes must be equal */
- if ((length0 == length1) &&
- (compare == 0)) {
+ if ((length0 == length1) && (compare == 0)) {
/* Length and all bytes match ==> TRUE */
local_result = TRUE;
}
break;
- case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
+ case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (compare > 0) {
local_result = TRUE;
- goto cleanup; /* TRUE */
+ goto cleanup; /* TRUE */
}
if (compare < 0) {
- goto cleanup; /* FALSE */
+ goto cleanup; /* FALSE */
}
/* Bytes match (to shortest length), compare lengths */
@@ -699,14 +659,14 @@ acpi_ex_do_logical_op (
}
break;
- case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
+ case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (compare > 0) {
- goto cleanup; /* FALSE */
+ goto cleanup; /* FALSE */
}
if (compare < 0) {
local_result = TRUE;
- goto cleanup; /* TRUE */
+ goto cleanup; /* TRUE */
}
/* Bytes match (to shortest length), compare lengths */
@@ -722,18 +682,16 @@ acpi_ex_do_logical_op (
}
}
-cleanup:
+ cleanup:
/* New object was created if implicit conversion performed - delete */
if (local_operand1 != operand1) {
- acpi_ut_remove_reference (local_operand1);
+ acpi_ut_remove_reference(local_operand1);
}
/* Return the logical result and status */
*logical_result = local_result;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index c3cb714d2cba..ab47f6d8b5c0 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -42,20 +42,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exmutex")
+ACPI_MODULE_NAME("exmutex")
/* Local prototypes */
-
static void
-acpi_ex_link_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_thread_state *thread);
-
+acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread);
/*******************************************************************************
*
@@ -69,12 +65,9 @@ acpi_ex_link_mutex (
*
******************************************************************************/
-void
-acpi_ex_unlink_mutex (
- union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
{
- struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
+ struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
if (!thread) {
return;
@@ -88,13 +81,11 @@ acpi_ex_unlink_mutex (
if (obj_desc->mutex.prev) {
(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
- }
- else {
+ } else {
thread->acquired_mutex_list = obj_desc->mutex.next;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_link_mutex
@@ -109,12 +100,10 @@ acpi_ex_unlink_mutex (
******************************************************************************/
static void
-acpi_ex_link_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_thread_state *thread)
+acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread)
{
- union acpi_operand_object *list_head;
-
+ union acpi_operand_object *list_head;
list_head = thread->acquired_mutex_list;
@@ -134,7 +123,6 @@ acpi_ex_link_mutex (
thread->acquired_mutex_list = obj_desc;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_mutex
@@ -150,27 +138,23 @@ acpi_ex_link_mutex (
******************************************************************************/
acpi_status
-acpi_ex_acquire_mutex (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc);
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc);
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
@@ -178,10 +162,8 @@ acpi_ex_acquire_mutex (
* mutex. This mechanism provides some deadlock prevention
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
- ACPI_REPORT_ERROR ((
- "Cannot acquire Mutex [%4.4s], incorrect sync_level\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
+ ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/* Support for multiple acquires by the owning thread */
@@ -190,43 +172,43 @@ acpi_ex_acquire_mutex (
/* Special case for Global Lock, allow all threads */
if ((obj_desc->mutex.owner_thread->thread_id ==
- walk_state->thread->thread_id) ||
- (obj_desc->mutex.semaphore ==
- acpi_gbl_global_lock_semaphore)) {
+ walk_state->thread->thread_id) ||
+ (obj_desc->mutex.semaphore ==
+ acpi_gbl_global_lock_semaphore)) {
/*
* The mutex is already owned by this thread,
* just increment the acquisition depth
*/
obj_desc->mutex.acquisition_depth++;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
/* Acquire the mutex, wait if necessary */
- status = acpi_ex_system_acquire_mutex (time_desc, obj_desc);
- if (ACPI_FAILURE (status)) {
+ 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);
+ return_ACPI_STATUS(status);
}
/* Have the mutex: update mutex and walk info and save the sync_level */
- obj_desc->mutex.owner_thread = walk_state->thread;
+ obj_desc->mutex.owner_thread = walk_state->thread;
obj_desc->mutex.acquisition_depth = 1;
- obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
+ obj_desc->mutex.original_sync_level =
+ walk_state->thread->current_sync_level;
walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
/* Link the mutex to the current thread for force-unlock at method exit */
- acpi_ex_link_mutex (obj_desc, walk_state->thread);
+ acpi_ex_link_mutex(obj_desc, walk_state->thread);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_mutex
@@ -241,48 +223,40 @@ acpi_ex_acquire_mutex (
******************************************************************************/
acpi_status
-acpi_ex_release_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_release_mutex");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_release_mutex");
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* The mutex must have been previously acquired in order to release it */
if (!obj_desc->mutex.owner_thread) {
- ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], not acquired\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
}
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* The Mutex is owned, but this thread must be the owner.
* Special case for Global Lock, any thread can release
*/
- if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
- (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
- ACPI_REPORT_ERROR ((
- "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
- walk_state->thread->thread_id,
- acpi_ut_get_node_name (obj_desc->mutex.node),
- obj_desc->mutex.owner_thread->thread_id));
- return_ACPI_STATUS (AE_AML_NOT_OWNER);
+ if ((obj_desc->mutex.owner_thread->thread_id !=
+ walk_state->thread->thread_id)
+ && (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
+ ACPI_REPORT_ERROR(("Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id));
+ return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
/*
@@ -290,10 +264,8 @@ acpi_ex_release_mutex (
* equal to the current sync level
*/
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
- ACPI_REPORT_ERROR ((
- "Cannot release Mutex [%4.4s], incorrect sync_level\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/* Match multiple Acquires with multiple Releases */
@@ -302,26 +274,26 @@ acpi_ex_release_mutex (
if (obj_desc->mutex.acquisition_depth != 0) {
/* Just decrement the depth and return */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Unlink the mutex from the owner's list */
- acpi_ex_unlink_mutex (obj_desc);
+ acpi_ex_unlink_mutex(obj_desc);
/* Release the mutex */
- status = acpi_ex_system_release_mutex (obj_desc);
+ status = acpi_ex_system_release_mutex(obj_desc);
/* Update the mutex and walk state, restore sync_level before acquire */
obj_desc->mutex.owner_thread = NULL;
- walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
+ walk_state->thread->current_sync_level =
+ obj_desc->mutex.original_sync_level;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_all_mutexes
@@ -334,17 +306,13 @@ acpi_ex_release_mutex (
*
******************************************************************************/
-void
-acpi_ex_release_all_mutexes (
- struct acpi_thread_state *thread)
+void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
{
- union acpi_operand_object *next = thread->acquired_mutex_list;
- union acpi_operand_object *this;
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_operand_object *next = thread->acquired_mutex_list;
+ union acpi_operand_object *this;
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Traverse the list of owned mutexes, releasing each one */
@@ -353,13 +321,13 @@ acpi_ex_release_all_mutexes (
next = this->mutex.next;
this->mutex.acquisition_depth = 1;
- this->mutex.prev = NULL;
- this->mutex.next = NULL;
+ this->mutex.prev = NULL;
+ this->mutex.next = NULL;
- /* Release the mutex */
+ /* Release the mutex */
- status = acpi_ex_system_release_mutex (this);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_system_release_mutex(this);
+ if (ACPI_FAILURE(status)) {
continue;
}
@@ -372,5 +340,3 @@ acpi_ex_release_all_mutexes (
thread->current_sync_level = this->mutex.original_sync_level;
}
}
-
-
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 639f0bd3f6d8..239d8473e9a5 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -42,26 +42,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exnames")
+ACPI_MODULE_NAME("exnames")
/* Local prototypes */
-
-static char *
-acpi_ex_allocate_name_string (
- u32 prefix_count,
- u32 num_name_segs);
+static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
static acpi_status
-acpi_ex_name_segment (
- u8 **in_aml_address,
- char *name_string);
-
+acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
/*******************************************************************************
*
@@ -79,17 +71,13 @@ acpi_ex_name_segment (
*
******************************************************************************/
-static char *
-acpi_ex_allocate_name_string (
- u32 prefix_count,
- u32 num_name_segs)
+static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
{
- char *temp_ptr;
- char *name_string;
- u32 size_needed;
-
- ACPI_FUNCTION_TRACE ("ex_allocate_name_string");
+ char *temp_ptr;
+ char *name_string;
+ u32 size_needed;
+ ACPI_FUNCTION_TRACE("ex_allocate_name_string");
/*
* Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
@@ -100,20 +88,19 @@ acpi_ex_allocate_name_string (
/* Special case for root */
size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
- }
- else {
- size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
+ } else {
+ size_needed =
+ prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
}
/*
* Allocate a buffer for the name.
* This buffer must be deleted by the caller!
*/
- name_string = ACPI_MEM_ALLOCATE (size_needed);
+ name_string = ACPI_MEM_ALLOCATE(size_needed);
if (!name_string) {
- ACPI_REPORT_ERROR ((
- "ex_allocate_name_string: Could not allocate size %d\n", size_needed));
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
+ return_PTR(NULL);
}
temp_ptr = name_string;
@@ -122,23 +109,20 @@ acpi_ex_allocate_name_string (
if (prefix_count == ACPI_UINT32_MAX) {
*temp_ptr++ = AML_ROOT_PREFIX;
- }
- else {
+ } else {
while (prefix_count--) {
*temp_ptr++ = AML_PARENT_PREFIX;
}
}
-
/* 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) {
+ *temp_ptr++ = (char)num_name_segs;
+ } else if (2 == num_name_segs) {
/* Set up dual prefixes */
*temp_ptr++ = AML_DUAL_NAME_PREFIX;
@@ -150,7 +134,7 @@ acpi_ex_allocate_name_string (
*/
*temp_ptr = 0;
- return_PTR (name_string);
+ return_PTR(name_string);
}
/*******************************************************************************
@@ -167,19 +151,14 @@ acpi_ex_allocate_name_string (
*
******************************************************************************/
-static acpi_status
-acpi_ex_name_segment (
- u8 **in_aml_address,
- char *name_string)
+static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
{
- char *aml_address = (void *) *in_aml_address;
- acpi_status status = AE_OK;
- u32 index;
- char char_buf[5];
-
-
- ACPI_FUNCTION_TRACE ("ex_name_segment");
+ char *aml_address = (void *)*in_aml_address;
+ acpi_status status = AE_OK;
+ u32 index;
+ char char_buf[5];
+ ACPI_FUNCTION_TRACE("ex_name_segment");
/*
* If first character is a digit, then we know that we aren't looking at a
@@ -188,20 +167,20 @@ acpi_ex_name_segment (
char_buf[0] = *aml_address;
if ('0' <= char_buf[0] && char_buf[0] <= '9') {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
- return_ACPI_STATUS (AE_CTRL_PENDING);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "leading digit: %c\n",
+ char_buf[0]));
+ return_ACPI_STATUS(AE_CTRL_PENDING);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
for (index = 0;
- (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address));
- index++) {
+ (index < ACPI_NAME_SIZE)
+ && (acpi_ut_valid_acpi_character(*aml_address)); index++) {
char_buf[index] = *aml_address++;
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index]));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
}
-
/* Valid name segment */
if (index == 4) {
@@ -210,41 +189,37 @@ acpi_ex_name_segment (
char_buf[4] = '\0';
if (name_string) {
- ACPI_STRCAT (name_string, char_buf);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Appended to - %s \n", name_string));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "No Name string - %s \n", char_buf));
+ ACPI_STRCAT(name_string, char_buf);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Appended to - %s \n", name_string));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "No Name string - %s \n", char_buf));
}
- }
- else if (index == 0) {
+ } else if (index == 0) {
/*
* First character was not a valid name character,
* so we are looking at something other than a name.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Leading character is not alpha: %02Xh (not a name)\n",
- char_buf[0]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Leading character is not alpha: %02Xh (not a name)\n",
+ char_buf[0]));
status = AE_CTRL_PENDING;
- }
- else {
+ } else {
/*
* Segment started with one or more valid characters, but fewer than
* the required 4
*/
status = AE_AML_BAD_NAME;
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad character %02x in name, at %p\n",
- *aml_address, aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad character %02x in name, at %p\n",
+ *aml_address, aml_address));
}
*in_aml_address = (u8 *) aml_address;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_name_string
@@ -263,37 +238,32 @@ acpi_ex_name_segment (
******************************************************************************/
acpi_status
-acpi_ex_get_name_string (
- acpi_object_type data_type,
- u8 *in_aml_address,
- char **out_name_string,
- u32 *out_name_length)
+acpi_ex_get_name_string(acpi_object_type data_type,
+ u8 * in_aml_address,
+ char **out_name_string, u32 * out_name_length)
{
- acpi_status status = AE_OK;
- u8 *aml_address = in_aml_address;
- char *name_string = NULL;
- u32 num_segments;
- u32 prefix_count = 0;
- u8 has_prefix = FALSE;
-
-
- 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) {
+ acpi_status status = AE_OK;
+ u8 *aml_address = in_aml_address;
+ char *name_string = NULL;
+ u32 num_segments;
+ u32 prefix_count = 0;
+ u8 has_prefix = FALSE;
+
+ 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);
+ name_string = acpi_ex_allocate_name_string(0, 1);
if (!name_string) {
status = AE_NO_MEMORY;
+ } else {
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
}
- else {
- status = acpi_ex_name_segment (&aml_address, name_string);
- }
- }
- else {
+ } else {
/*
* data_type is not a field name.
* Examine first character of name for root or parent prefix operators
@@ -301,8 +271,9 @@ acpi_ex_get_name_string (
switch (*aml_address) {
case AML_ROOT_PREFIX:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "root_prefix(\\) at %p\n",
+ aml_address));
/*
* Remember that we have a root_prefix --
@@ -313,14 +284,14 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
break;
-
case AML_PARENT_PREFIX:
/* Increment past possibly multiple parent prefixes */
do {
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "parent_prefix (^) at %p\n",
+ aml_address));
aml_address++;
prefix_count++;
@@ -330,7 +301,6 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
break;
-
default:
/* Not a prefix character */
@@ -343,11 +313,13 @@ acpi_ex_get_name_string (
switch (*aml_address) {
case AML_DUAL_NAME_PREFIX:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "dual_name_prefix at %p\n",
+ aml_address));
aml_address++;
- name_string = acpi_ex_allocate_name_string (prefix_count, 2);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 2);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -357,24 +329,29 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
- status = acpi_ex_name_segment (&aml_address, name_string);
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_name_segment (&aml_address, name_string);
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ex_name_segment(&aml_address,
+ name_string);
}
break;
-
case AML_MULTI_NAME_PREFIX_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "multi_name_prefix at %p\n",
+ aml_address));
/* Fetch count of segments remaining in name path */
aml_address++;
num_segments = *aml_address;
- name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count,
+ num_segments);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -386,27 +363,28 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
while (num_segments &&
- (status = acpi_ex_name_segment (&aml_address, name_string)) ==
- AE_OK) {
+ (status =
+ acpi_ex_name_segment(&aml_address,
+ name_string)) == AE_OK) {
num_segments--;
}
break;
-
case 0:
/* null_name valid as of 8-12-98 ASL/AML Grammar Update */
if (prefix_count == ACPI_UINT32_MAX) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "name_seg is \"\\\" followed by NULL\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "name_seg is \"\\\" followed by NULL\n"));
}
/* Consume the NULL byte */
aml_address++;
- name_string = acpi_ex_allocate_name_string (prefix_count, 0);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 0);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -414,18 +392,19 @@ acpi_ex_get_name_string (
break;
-
default:
/* Name segment string */
- name_string = acpi_ex_allocate_name_string (prefix_count, 1);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 1);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
- status = acpi_ex_name_segment (&aml_address, name_string);
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
break;
}
}
@@ -433,15 +412,20 @@ acpi_ex_get_name_string (
if (AE_CTRL_PENDING == status && has_prefix) {
/* Ran out of segments after processing a prefix */
- ACPI_REPORT_ERROR (
- ("ex_do_name: Malformed Name at %p\n", name_string));
+ ACPI_REPORT_ERROR(("ex_do_name: Malformed Name at %p\n",
+ name_string));
status = AE_AML_BAD_NAME;
}
+ if (ACPI_FAILURE(status)) {
+ if (name_string) {
+ ACPI_MEM_FREE(name_string);
+ }
+ return_ACPI_STATUS(status);
+ }
+
*out_name_string = name_string;
*out_name_length = (u32) (aml_address - in_aml_address);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index dbdf8262ba00..97e34542f5e4 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
@@ -50,10 +49,8 @@
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg1")
-
+ACPI_MODULE_NAME("exoparg1")
/*!
* Naming convention for AML interpreter execution routines.
@@ -76,7 +73,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_0A_0T_1R
@@ -88,59 +84,53 @@
* DESCRIPTION: Execute operator with no operands, one return value
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_0A_0T_1R (
- struct acpi_walk_state *walk_state)
+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_ps_get_opcode_name (walk_state->opcode));
+ acpi_status status = AE_OK;
+ union acpi_operand_object *return_desc = NULL;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_TIMER_OP: /* Timer () */
+ case AML_TIMER_OP: /* Timer () */
/* Create a return object of type Integer */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
-
- return_desc->integer.value = acpi_os_get_timer ();
+#if ACPI_MACHINE_WIDTH != 16
+ return_desc->integer.value = acpi_os_get_timer();
+#endif
break;
- default: /* Unknown opcode */
+ default: /* Unknown opcode */
- ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
-cleanup:
-
- if (!walk_state->result_obj) {
- walk_state->result_obj = return_desc;
- }
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
+ } else {
+ /* Save the return value */
+
+ walk_state->result_obj = return_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_0T_0R
@@ -154,69 +144,58 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_0T_0R (
- struct acpi_walk_state *walk_state)
+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_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_RELEASE_OP: /* Release (mutex_object) */
+ case AML_RELEASE_OP: /* Release (mutex_object) */
- status = acpi_ex_release_mutex (operand[0], walk_state);
+ status = acpi_ex_release_mutex(operand[0], walk_state);
break;
+ case AML_RESET_OP: /* Reset (event_object) */
- case AML_RESET_OP: /* Reset (event_object) */
-
- status = acpi_ex_system_reset_event (operand[0]);
+ status = acpi_ex_system_reset_event(operand[0]);
break;
+ case AML_SIGNAL_OP: /* Signal (event_object) */
- case AML_SIGNAL_OP: /* Signal (event_object) */
-
- status = acpi_ex_system_signal_event (operand[0]);
+ status = acpi_ex_system_signal_event(operand[0]);
break;
+ case AML_SLEEP_OP: /* Sleep (msec_time) */
- case AML_SLEEP_OP: /* Sleep (msec_time) */
-
- status = acpi_ex_system_do_suspend (operand[0]->integer.value);
+ status = acpi_ex_system_do_suspend(operand[0]->integer.value);
break;
+ case AML_STALL_OP: /* Stall (usec_time) */
- case AML_STALL_OP: /* Stall (usec_time) */
-
- status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value);
+ status =
+ acpi_ex_system_do_stall((u32) operand[0]->integer.value);
break;
+ case AML_UNLOAD_OP: /* Unload (Handle) */
- case AML_UNLOAD_OP: /* Unload (Handle) */
-
- status = acpi_ex_unload_table (operand[0]);
+ status = acpi_ex_unload_table(operand[0]);
break;
+ default: /* Unknown opcode */
- default: /* Unknown opcode */
-
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_1T_0R
@@ -230,41 +209,34 @@ acpi_ex_opcode_1A_0T_0R (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_1T_0R (
- struct acpi_walk_state *walk_state)
+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_ps_get_opcode_name (walk_state->opcode));
+ acpi_status status = AE_OK;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
case AML_LOAD_OP:
- status = acpi_ex_load_op (operand[0], operand[1], walk_state);
+ status = acpi_ex_load_op(operand[0], operand[1], walk_state);
break;
- default: /* Unknown opcode */
+ default: /* Unknown opcode */
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
+ cleanup:
-cleanup:
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_1T_1R
@@ -278,23 +250,19 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- union acpi_operand_object *return_desc2 = NULL;
- u32 temp32;
- u32 i;
- acpi_integer power_of_ten;
- acpi_integer digit;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
-
+ acpi_status status = AE_OK;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ union acpi_operand_object *return_desc2 = NULL;
+ u32 temp32;
+ u32 i;
+ acpi_integer power_of_ten;
+ acpi_integer digit;
+
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -308,20 +276,19 @@ acpi_ex_opcode_1A_1T_1R (
/* Create a return object of type Integer for these opcodes */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
switch (walk_state->opcode) {
- case AML_BIT_NOT_OP: /* Not (Operand, Result) */
+ case AML_BIT_NOT_OP: /* Not (Operand, Result) */
return_desc->integer.value = ~operand[0]->integer.value;
break;
-
- case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
+ case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
return_desc->integer.value = operand[0]->integer.value;
@@ -330,15 +297,14 @@ acpi_ex_opcode_1A_1T_1R (
* endian unsigned value, so this boundary condition is valid.
*/
for (temp32 = 0; return_desc->integer.value &&
- temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
+ temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
return_desc->integer.value >>= 1;
}
return_desc->integer.value = temp32;
break;
-
- case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
+ case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
return_desc->integer.value = operand[0]->integer.value;
@@ -347,18 +313,17 @@ acpi_ex_opcode_1A_1T_1R (
* endian unsigned value, so this boundary condition is valid.
*/
for (temp32 = 0; return_desc->integer.value &&
- temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
+ temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
return_desc->integer.value <<= 1;
}
/* Since the bit position is one-based, subtract from 33 (65) */
return_desc->integer.value = temp32 == 0 ? 0 :
- (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
+ (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
break;
-
- case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
+ case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
/*
* The 64-bit ACPI integer can hold 16 4-bit BCD characters
@@ -371,7 +336,9 @@ acpi_ex_opcode_1A_1T_1R (
/* Convert each BCD digit (each is one nybble wide) */
- for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
+ for (i = 0;
+ (i < acpi_gbl_integer_nybble_width) && (digit > 0);
+ i++) {
/* Get the least significant 4-bit BCD digit */
temp32 = ((u32) digit) & 0xF;
@@ -379,9 +346,9 @@ acpi_ex_opcode_1A_1T_1R (
/* Check the range of the digit */
if (temp32 > 9) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "BCD digit too large (not decimal): 0x%X\n",
- temp32));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "BCD digit too large (not decimal): 0x%X\n",
+ temp32));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
@@ -389,8 +356,8 @@ acpi_ex_opcode_1A_1T_1R (
/* Sum the digit into the result with the current power of 10 */
- return_desc->integer.value += (((acpi_integer) temp32) *
- power_of_ten);
+ return_desc->integer.value +=
+ (((acpi_integer) temp32) * power_of_ten);
/* Shift to next BCD digit */
@@ -402,45 +369,50 @@ acpi_ex_opcode_1A_1T_1R (
}
break;
-
- case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
+ case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
return_desc->integer.value = 0;
digit = operand[0]->integer.value;
/* Each BCD digit is one nybble wide */
- for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
- (void) acpi_ut_short_divide (digit, 10, &digit, &temp32);
+ for (i = 0;
+ (i < acpi_gbl_integer_nybble_width) && (digit > 0);
+ i++) {
+ (void)acpi_ut_short_divide(digit, 10, &digit,
+ &temp32);
/*
* Insert the BCD digit that resides in the
* remainder from above
*/
- return_desc->integer.value |= (((acpi_integer) temp32) <<
- ACPI_MUL_4 (i));
+ return_desc->integer.value |=
+ (((acpi_integer) temp32) << ACPI_MUL_4(i));
}
/* Overflow if there is any data left in Digit */
if (digit > 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Integer too large to convert to BCD: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (operand[0]->integer.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Integer too large to convert to BCD: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(operand
+ [0]->
+ integer.
+ value)));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
}
break;
-
- case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */
+ case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */
/*
* This op is a little strange because the internal return value is
* different than the return value stored in the result descriptor
* (There are really two return values)
*/
- if ((struct acpi_namespace_node *) operand[0] == acpi_gbl_root_node) {
+ if ((struct acpi_namespace_node *)operand[0] ==
+ acpi_gbl_root_node) {
/*
* This means that the object does not exist in the namespace,
* return FALSE
@@ -451,38 +423,38 @@ acpi_ex_opcode_1A_1T_1R (
/* Get the object reference, store it, and remove our reference */
- status = acpi_ex_get_object_reference (operand[0],
- &return_desc2, walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_get_object_reference(operand[0],
+ &return_desc2,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_store (return_desc2, operand[1], walk_state);
- acpi_ut_remove_reference (return_desc2);
+ status =
+ acpi_ex_store(return_desc2, operand[1], walk_state);
+ acpi_ut_remove_reference(return_desc2);
/* The object exists in the namespace, return TRUE */
return_desc->integer.value = ACPI_INTEGER_MAX;
goto cleanup;
-
default:
/* No other opcodes get here */
break;
}
break;
-
- case AML_STORE_OP: /* Store (Source, Target) */
+ case AML_STORE_OP: /* Store (Source, Target) */
/*
* A store operand is typically a number, string, buffer or lvalue
* Be careful about deleting the source object,
* since the object itself may have been stored.
*/
- status = acpi_ex_store (operand[0], operand[1], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_store(operand[0], operand[1], walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* It is possible that the Store already produced a return object */
@@ -495,92 +467,84 @@ acpi_ex_opcode_1A_1T_1R (
* cancel out, and we simply don't do anything.
*/
walk_state->result_obj = operand[0];
- walk_state->operands[0] = NULL; /* Prevent deletion */
+ walk_state->operands[0] = NULL; /* Prevent deletion */
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
+ /*
+ * ACPI 2.0 Opcodes
+ */
+ case AML_COPY_OP: /* Copy (Source, Target) */
- /*
- * ACPI 2.0 Opcodes
- */
- case AML_COPY_OP: /* Copy (Source, Target) */
-
- status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc,
- walk_state);
+ status =
+ acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
+ walk_state);
break;
+ case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
- case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
-
- status = acpi_ex_convert_to_string (operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_DECIMAL);
+ 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);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
- case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
-
- status = acpi_ex_convert_to_string (operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_HEX);
+ 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);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
- case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
-
- status = acpi_ex_convert_to_buffer (operand[0], &return_desc);
+ 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);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
- case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
-
- status = acpi_ex_convert_to_integer (operand[0], &return_desc,
- ACPI_ANY_BASE);
+ 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);
+ acpi_ut_add_reference(return_desc);
}
break;
-
- case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
- case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
+ case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
+ case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
/* These are two obsolete opcodes */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%s is obsolete and not implemented\n",
- acpi_ps_get_opcode_name (walk_state->opcode)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s is obsolete and not implemented\n",
+ acpi_ps_get_opcode_name(walk_state->opcode)));
status = AE_SUPPORT;
goto cleanup;
+ default: /* Unknown opcode */
- default: /* Unknown opcode */
-
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Store the return value computed above into the target object */
- status = acpi_ex_store (return_desc, operand[1], walk_state);
+ status = acpi_ex_store(return_desc, operand[1], walk_state);
}
-
-cleanup:
+ cleanup:
if (!walk_state->result_obj) {
walk_state->result_obj = return_desc;
@@ -588,14 +552,13 @@ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_0T_1R
@@ -608,28 +571,24 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *temp_desc;
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- u32 type;
- acpi_integer value;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *temp_desc;
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ u32 type;
+ acpi_integer value;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_LNOT_OP: /* LNot (Operand) */
+ case AML_LNOT_OP: /* LNot (Operand) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -644,15 +603,14 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
- case AML_DECREMENT_OP: /* Decrement (Operand) */
- case AML_INCREMENT_OP: /* Increment (Operand) */
+ case AML_DECREMENT_OP: /* Decrement (Operand) */
+ case AML_INCREMENT_OP: /* Increment (Operand) */
/*
* Create a new integer. Can't just get the base integer and
* increment it because it may be an Arg or Field.
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -663,10 +621,11 @@ acpi_ex_opcode_1A_0T_1R (
* NS Node or an internal object.
*/
temp_desc = operand[0];
- if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
+ ACPI_DESC_TYPE_OPERAND) {
/* Internal reference object - prevent deletion */
- acpi_ut_add_reference (temp_desc);
+ acpi_ut_add_reference(temp_desc);
}
/*
@@ -676,11 +635,15 @@ acpi_ex_opcode_1A_0T_1R (
* NOTE: We use LNOT_OP here in order to force resolution of the
* reference operand to an actual integer.
*/
- status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n",
- acpi_ps_get_opcode_name (walk_state->opcode),
- acpi_format_exception(status)));
+ status =
+ acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s: bad operand(s) %s\n",
+ acpi_ps_get_opcode_name(walk_state->
+ opcode),
+ acpi_format_exception(status)));
goto cleanup;
}
@@ -690,25 +653,25 @@ acpi_ex_opcode_1A_0T_1R (
* Perform the actual increment or decrement
*/
if (walk_state->opcode == AML_INCREMENT_OP) {
- return_desc->integer.value = temp_desc->integer.value +1;
- }
- else {
- return_desc->integer.value = temp_desc->integer.value -1;
+ return_desc->integer.value =
+ temp_desc->integer.value + 1;
+ } else {
+ return_desc->integer.value =
+ temp_desc->integer.value - 1;
}
/* Finished with this Integer object */
- acpi_ut_remove_reference (temp_desc);
+ acpi_ut_remove_reference(temp_desc);
/*
* Store the result back (indirectly) through the original
* Reference object
*/
- status = acpi_ex_store (return_desc, operand[0], walk_state);
+ status = acpi_ex_store(return_desc, operand[0], walk_state);
break;
-
- case AML_TYPE_OP: /* object_type (source_object) */
+ case AML_TYPE_OP: /* object_type (source_object) */
/*
* Note: The operand is not resolved at this point because we want to
@@ -719,13 +682,15 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the type of the base object */
- status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_multiple(walk_state, operand[0], &type,
+ NULL);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Allocate a descriptor to hold the type. */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -734,8 +699,7 @@ acpi_ex_opcode_1A_0T_1R (
return_desc->integer.value = type;
break;
-
- case AML_SIZE_OF_OP: /* size_of (source_object) */
+ case AML_SIZE_OF_OP: /* size_of (source_object) */
/*
* Note: The operand is not resolved at this point because we want to
@@ -744,9 +708,10 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the base object */
- status = acpi_ex_resolve_multiple (walk_state,
- operand[0], &type, &temp_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_resolve_multiple(walk_state,
+ operand[0], &type,
+ &temp_desc);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -777,9 +742,9 @@ acpi_ex_opcode_1A_0T_1R (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
- acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
+ acpi_ut_get_type_name(type)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
@@ -788,7 +753,7 @@ acpi_ex_opcode_1A_0T_1R (
* Now that we have the size of the object, create a result
* object to hold the value
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -797,22 +762,23 @@ acpi_ex_opcode_1A_0T_1R (
return_desc->integer.value = value;
break;
+ case AML_REF_OF_OP: /* ref_of (source_object) */
- case AML_REF_OF_OP: /* ref_of (source_object) */
-
- status = acpi_ex_get_object_reference (operand[0], &return_desc, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_get_object_reference(operand[0], &return_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
break;
-
- case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
+ case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
/* Check for a method local or argument, or standalone String */
- if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) {
- switch (ACPI_GET_OBJECT_TYPE (operand[0])) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+ ACPI_DESC_TYPE_NAMED) {
+ switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
case ACPI_TYPE_LOCAL_REFERENCE:
/*
* This is a deref_of (local_x | arg_x)
@@ -825,11 +791,12 @@ acpi_ex_opcode_1A_0T_1R (
/* Set Operand[0] to the value of the local/arg */
- status = acpi_ds_method_data_get_value (
- operand[0]->reference.opcode,
- operand[0]->reference.offset,
- walk_state, &temp_desc);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_method_data_get_value
+ (operand[0]->reference.opcode,
+ operand[0]->reference.offset,
+ walk_state, &temp_desc);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -837,7 +804,7 @@ acpi_ex_opcode_1A_0T_1R (
* Delete our reference to the input object and
* point to the object just retrieved
*/
- acpi_ut_remove_reference (operand[0]);
+ acpi_ut_remove_reference(operand[0]);
operand[0] = temp_desc;
break;
@@ -845,8 +812,9 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the object to which the reference refers */
- temp_desc = operand[0]->reference.object;
- acpi_ut_remove_reference (operand[0]);
+ temp_desc =
+ operand[0]->reference.object;
+ acpi_ut_remove_reference(operand[0]);
operand[0] = temp_desc;
break;
@@ -857,7 +825,6 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
case ACPI_TYPE_STRING:
/*
@@ -868,22 +835,28 @@ acpi_ex_opcode_1A_0T_1R (
* 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));
- if (ACPI_FAILURE (status)) {
+ 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));
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_resolve_node_to_value (
- ACPI_CAST_INDIRECT_PTR (
- struct acpi_namespace_node, &return_desc),
- walk_state);
+ status =
+ acpi_ex_resolve_node_to_value
+ (ACPI_CAST_INDIRECT_PTR
+ (struct acpi_namespace_node, &return_desc),
+ walk_state);
goto cleanup;
-
default:
status = AE_AML_OPERAND_TYPE;
@@ -893,17 +866,20 @@ acpi_ex_opcode_1A_0T_1R (
/* Operand[0] may have changed from the code above */
- if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
+ ACPI_DESC_TYPE_NAMED) {
/*
* This is a deref_of (object_reference)
* Get the actual object from the Node (This is the dereference).
* This case may only happen when a local_x or arg_x is
* dereferenced above.
*/
- return_desc = acpi_ns_get_attached_object (
- (struct acpi_namespace_node *) operand[0]);
- }
- else {
+ return_desc = acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)
+ operand[0]);
+ acpi_ut_add_reference(return_desc);
+ } else {
/*
* This must be a reference object produced by either the
* Index() or ref_of() operator
@@ -918,7 +894,8 @@ acpi_ex_opcode_1A_0T_1R (
switch (operand[0]->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
- temp_desc = operand[0]->reference.object;
+ temp_desc =
+ operand[0]->reference.object;
/*
* Create a new object that contains one element of the
@@ -928,7 +905,9 @@ acpi_ex_opcode_1A_0T_1R (
* sub-buffer of the main buffer, it is only a pointer to a
* single element (byte) of the buffer!
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc =
+ acpi_ut_create_internal_object
+ (ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -940,66 +919,63 @@ acpi_ex_opcode_1A_0T_1R (
* reference to the buffer itself.
*/
return_desc->integer.value =
- temp_desc->buffer.pointer[operand[0]->reference.offset];
+ temp_desc->buffer.
+ pointer[operand[0]->reference.
+ offset];
break;
-
case ACPI_TYPE_PACKAGE:
/*
* Return the referenced element of the package. We must
* add another reference to the referenced object, however.
*/
- return_desc = *(operand[0]->reference.where);
- if (!return_desc) {
- /*
- * We can't return a NULL dereferenced value. This is
- * an uninitialized package element and is thus a
- * severe error.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "NULL package element obj %p\n",
- operand[0]));
- status = AE_AML_UNINITIALIZED_ELEMENT;
- goto cleanup;
+ return_desc =
+ *(operand[0]->reference.where);
+ if (return_desc) {
+ acpi_ut_add_reference
+ (return_desc);
}
- acpi_ut_add_reference (return_desc);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown Index target_type %X in obj %p\n",
- operand[0]->reference.target_type, operand[0]));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Index target_type %X in obj %p\n",
+ operand[0]->reference.
+ target_type,
+ operand[0]));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
break;
-
case AML_REF_OF_OP:
return_desc = operand[0]->reference.object;
- if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) ==
- ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
- return_desc = acpi_ns_get_attached_object (
- (struct acpi_namespace_node *) return_desc);
+ return_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)
+ return_desc);
}
/* Add another reference to the object! */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown opcode in ref(%p) - %X\n",
- operand[0], operand[0]->reference.opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown opcode in ref(%p) - %X\n",
+ operand[0],
+ operand[0]->reference.
+ opcode));
status = AE_TYPE;
goto cleanup;
@@ -1007,25 +983,21 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
walk_state->result_obj = return_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 7429032c2b6c..8d70c6beef00 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -41,17 +41,14 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg2")
-
+ACPI_MODULE_NAME("exoparg2")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,8 +71,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_0R
@@ -90,29 +85,24 @@
* ALLOCATION: Deletes both operands
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_2A_0T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_namespace_node *node;
- u32 value;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_namespace_node *node;
+ u32 value;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the opcode */
switch (walk_state->opcode) {
- case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
+ case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
/* The first operand is a namespace node */
- node = (struct acpi_namespace_node *) operand[0];
+ node = (struct acpi_namespace_node *)operand[0];
/* Second value is the notify value */
@@ -120,15 +110,14 @@ acpi_ex_opcode_2A_0T_0R (
/* Are notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unexpected notify object type [%s]\n",
- acpi_ut_get_type_name (node->type)));
+ if (!acpi_ev_is_notify_object(node)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unexpected notify object type [%s]\n",
+ acpi_ut_get_type_name(node->type)));
status = AE_AML_OPERAND_TYPE;
break;
}
-
#ifdef ACPI_GPE_NOTIFY_CHECK
/*
* GPE method wake/notify check. Here, we want to ensure that we
@@ -144,12 +133,14 @@ acpi_ex_opcode_2A_0T_0R (
* If all three cases are true, this is a wake-only GPE that should
* be disabled at runtime.
*/
- if (value == 2) /* device_wake */ {
- status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ if (value == 2) { /* device_wake */
+ status =
+ 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)
+ return_ACPI_STATUS(AE_OK)
}
}
#endif
@@ -161,21 +152,18 @@ acpi_ex_opcode_2A_0T_0R (
* from this thread -- because handlers may in turn run other
* control methods.
*/
- status = acpi_ev_queue_notify_request (node, value);
+ status = acpi_ev_queue_notify_request(node, value);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_2T_1R
@@ -189,19 +177,15 @@ acpi_ex_opcode_2A_0T_0R (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_2T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc1 = NULL;
- union acpi_operand_object *return_desc2 = NULL;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc1 = NULL;
+ union acpi_operand_object *return_desc2 = NULL;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
@@ -210,13 +194,15 @@ acpi_ex_opcode_2A_2T_1R (
/* Divide (Dividend, Divisor, remainder_result quotient_result) */
- return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc1 =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc1) {
status = AE_NO_MEMORY;
goto cleanup;
}
- return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc2 =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc2) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -224,33 +210,31 @@ acpi_ex_opcode_2A_2T_1R (
/* Quotient to return_desc1, remainder to return_desc2 */
- status = acpi_ut_divide (operand[0]->integer.value,
- operand[1]->integer.value,
- &return_desc1->integer.value,
- &return_desc2->integer.value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_divide(operand[0]->integer.value,
+ operand[1]->integer.value,
+ &return_desc1->integer.value,
+ &return_desc2->integer.value);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the results to the target reference operands */
- status = acpi_ex_store (return_desc2, operand[2], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc2, operand[2], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_store (return_desc1, operand[3], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc1, operand[3], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -258,24 +242,22 @@ acpi_ex_opcode_2A_2T_1R (
walk_state->result_obj = return_desc1;
-
-cleanup:
+ cleanup:
/*
* Since the remainder is not returned indirectly, remove a reference to
* it. Only the quotient is returned indirectly.
*/
- acpi_ut_remove_reference (return_desc2);
+ acpi_ut_remove_reference(return_desc2);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Delete the return object */
- acpi_ut_remove_reference (return_desc1);
+ acpi_ut_remove_reference(return_desc1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_1T_1R
@@ -289,42 +271,39 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_integer index;
- acpi_status status = AE_OK;
- acpi_size length;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_integer index;
+ acpi_status status = AE_OK;
+ acpi_size length;
+ 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);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
- operand[0]->integer.value,
- operand[1]->integer.value);
+ return_desc->integer.value =
+ acpi_ex_do_math_op(walk_state->opcode,
+ operand[0]->integer.value,
+ operand[1]->integer.value);
goto store_result_to_target;
}
switch (walk_state->opcode) {
- case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
+ case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -332,21 +311,18 @@ acpi_ex_opcode_2A_1T_1R (
/* return_desc will contain the remainder */
- status = acpi_ut_divide (operand[0]->integer.value,
- operand[1]->integer.value,
- NULL,
- &return_desc->integer.value);
+ status = acpi_ut_divide(operand[0]->integer.value,
+ operand[1]->integer.value,
+ NULL, &return_desc->integer.value);
break;
+ case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
- case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
-
- status = acpi_ex_do_concatenate (operand[0], operand[1],
- &return_desc, walk_state);
+ status = acpi_ex_do_concatenate(operand[0], operand[1],
+ &return_desc, walk_state);
break;
-
- case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
+ case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
/*
* Input object is guaranteed to be a buffer at this point (it may have
@@ -365,8 +341,8 @@ acpi_ex_opcode_2A_1T_1R (
*/
length = 0;
while ((length < operand[0]->buffer.length) &&
- (length < operand[1]->integer.value) &&
- (operand[0]->buffer.pointer[length])) {
+ (length < operand[1]->integer.value) &&
+ (operand[0]->buffer.pointer[length])) {
length++;
if (length > ACPI_MAX_STRING_CONVERSION) {
status = AE_AML_STRING_LIMIT;
@@ -376,33 +352,32 @@ acpi_ex_opcode_2A_1T_1R (
/* Allocate a new string object */
- return_desc = acpi_ut_create_string_object (length);
+ return_desc = acpi_ut_create_string_object(length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Copy the raw buffer data with no transform. NULL terminated already*/
+ /* Copy the raw buffer data with no transform. NULL terminated already */
- ACPI_MEMCPY (return_desc->string.pointer,
- operand[0]->buffer.pointer, length);
+ ACPI_MEMCPY(return_desc->string.pointer,
+ operand[0]->buffer.pointer, length);
break;
-
case AML_CONCAT_RES_OP:
/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
- status = acpi_ex_concat_template (operand[0], operand[1],
- &return_desc, walk_state);
+ status = acpi_ex_concat_template(operand[0], operand[1],
+ &return_desc, walk_state);
break;
-
- case AML_INDEX_OP: /* Index (Source Index Result) */
+ case AML_INDEX_OP: /* Index (Source Index Result) */
/* Create the internal return object */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ return_desc =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -412,76 +387,75 @@ acpi_ex_opcode_2A_1T_1R (
/* At this point, the Source operand is a Package, Buffer, or String */
- if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) {
/* Object to be indexed is a Package */
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index value (%X%8.8X) beyond package end (%X)\n",
+ 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 {
+ return_desc->reference.object = operand[0];
+ return_desc->reference.where =
+ &operand[0]->package.elements[index];
+ } else {
/* Object to be indexed is a Buffer/String */
if (index >= operand[0]->buffer.length) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond end of buffer (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->buffer.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index value (%X%8.8X) beyond end of buffer (%X)\n",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
- return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
- return_desc->reference.object = operand[0];
+ return_desc->reference.target_type =
+ ACPI_TYPE_BUFFER_FIELD;
+ return_desc->reference.object = operand[0];
}
/*
* Add a reference to the target package/buffer/string for the life
* of the index.
*/
- acpi_ut_add_reference (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;
+ 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);
+ status = acpi_ex_store(return_desc, operand[2], walk_state);
/* Return the reference */
walk_state->result_obj = return_desc;
goto cleanup;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
+ store_result_to_target:
-store_result_to_target:
-
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Store the result of the operation (which is now in return_desc) into
* the Target descriptor.
*/
- status = acpi_ex_store (return_desc, operand[2], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc, operand[2], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -490,19 +464,17 @@ store_result_to_target:
}
}
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_1R
@@ -515,23 +487,19 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- u8 logical_result = FALSE;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ u8 logical_result = FALSE;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Create the internal return object */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -542,50 +510,48 @@ acpi_ex_opcode_2A_0T_1R (
if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
/* logical_op (Operand0, Operand1) */
- status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
- operand[0]->integer.value, operand[1]->integer.value,
- &logical_result);
+ status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
+ operand[0]->integer.
+ value,
+ operand[1]->integer.
+ value, &logical_result);
goto store_logical_result;
- }
- else if (walk_state->op_info->flags & AML_LOGICAL) {
+ } else if (walk_state->op_info->flags & AML_LOGICAL) {
/* logical_op (Operand0, Operand1) */
- status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
- operand[1], &logical_result);
+ status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
+ operand[1], &logical_result);
goto store_logical_result;
}
switch (walk_state->opcode) {
- case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
+ case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
- status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
+ status =
+ acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
if (status == AE_TIME) {
- logical_result = TRUE; /* TRUE = Acquire timed out */
+ logical_result = TRUE; /* TRUE = Acquire timed out */
status = AE_OK;
}
break;
+ case AML_WAIT_OP: /* Wait (event_object, Timeout) */
- case AML_WAIT_OP: /* Wait (event_object, Timeout) */
-
- status = acpi_ex_system_wait_event (operand[1], operand[0]);
+ status = acpi_ex_system_wait_event(operand[1], operand[0]);
if (status == AE_TIME) {
- logical_result = TRUE; /* TRUE, Wait timed out */
+ logical_result = TRUE; /* TRUE, Wait timed out */
status = AE_OK;
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
-
-store_logical_result:
+ store_logical_result:
/*
* Set return value to according to logical_result. logical TRUE (all ones)
* Default is FALSE (zero)
@@ -596,16 +562,13 @@ store_logical_result:
walk_state->result_obj = return_desc;
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 23b068adbf58..483365777670 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -42,16 +42,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg3")
-
+ACPI_MODULE_NAME("exoparg3")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,8 +71,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_0T_0R
@@ -87,61 +82,53 @@
* DESCRIPTION: Execute Triadic operator (3 operands)
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_3A_0T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_signal_fatal_info *fatal;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_0T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_signal_fatal_info *fatal;
+ acpi_status status = AE_OK;
+ 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) */
+ 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",
- (u32) operand[0]->integer.value,
- (u32) operand[1]->integer.value,
- (u32) operand[2]->integer.value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "fatal_op: 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_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
if (fatal) {
- fatal->type = (u32) operand[0]->integer.value;
- fatal->code = (u32) operand[1]->integer.value;
+ fatal->type = (u32) operand[0]->integer.value;
+ fatal->code = (u32) operand[1]->integer.value;
fatal->argument = (u32) operand[2]->integer.value;
}
/* Always signal the OS! */
- status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
+ status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
/* Might return while OS is shutting down, just continue */
- ACPI_MEM_FREE (fatal);
+ ACPI_MEM_FREE(fatal);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
+ cleanup:
-cleanup:
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_1T_1R
@@ -154,31 +141,28 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_3A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- char *buffer;
- acpi_status status = AE_OK;
- acpi_integer index;
- acpi_size length;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ char *buffer = NULL;
+ acpi_status status = AE_OK;
+ acpi_integer index;
+ acpi_size length;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
- case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
+ case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
/*
* Create the return object. The Source operand is guaranteed to be
* either a String or a Buffer, so just use its type.
*/
- return_desc = acpi_ut_create_internal_object (
- ACPI_GET_OBJECT_TYPE (operand[0]));
+ return_desc =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE
+ (operand[0]));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -193,67 +177,92 @@ acpi_ex_opcode_3A_1T_1R (
* If the index is beyond the length of the String/Buffer, or if the
* requested length is zero, return a zero-length String/Buffer
*/
- if ((index < operand[0]->string.length) &&
- (length > 0)) {
- /* Truncate request if larger than the actual String/Buffer */
-
- if ((index + length) >
- operand[0]->string.length) {
- length = (acpi_size) operand[0]->string.length -
- (acpi_size) index;
- }
+ if (index >= operand[0]->string.length) {
+ length = 0;
+ }
+
+ /* Truncate request if larger than the actual String/Buffer */
+
+ else if ((index + length) > operand[0]->string.length) {
+ length = (acpi_size) operand[0]->string.length -
+ (acpi_size) index;
+ }
+
+ /* Strings always have a sub-pointer, not so for buffers */
+
+ switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
+ case ACPI_TYPE_STRING:
- /* Allocate a new buffer for the String/Buffer */
+ /* Always allocate a new buffer for the String */
- buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
+ buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
}
+ break;
- /* Copy the portion requested */
+ case ACPI_TYPE_BUFFER:
- ACPI_MEMCPY (buffer, operand[0]->string.pointer + index,
- length);
+ /* If the requested length is zero, don't allocate a buffer */
- /* Set the length of the new String/Buffer */
+ if (length > 0) {
+ /* Allocate a new buffer for the Buffer */
- return_desc->string.pointer = buffer;
- return_desc->string.length = (u32) length;
+ buffer = ACPI_MEM_CALLOCATE(length);
+ if (!buffer) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+ }
+ break;
+
+ default: /* Should not happen */
+
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
}
+ if (length > 0) {
+ /* Copy the portion requested */
+
+ ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
+ length);
+ }
+
+ /* Set the length of the new String/Buffer */
+
+ return_desc->string.pointer = buffer;
+ return_desc->string.length = (u32) length;
+
/* Mark buffer initialized */
return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the result in the target */
- status = acpi_ex_store (return_desc, operand[3], walk_state);
+ status = acpi_ex_store(return_desc, operand[3], walk_state);
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
}
/* Set the return object and exit */
- if (!walk_state->result_obj) {
+ else {
walk_state->result_obj = return_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index 17f81d42ee41..5dee77139576 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -42,16 +42,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg6")
-
+ACPI_MODULE_NAME("exoparg6")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,15 +71,11 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
/* Local prototypes */
-
static u8
-acpi_ex_do_match (
- u32 match_op,
- union acpi_operand_object *package_obj,
- union acpi_operand_object *match_obj);
-
+acpi_ex_do_match(u32 match_op,
+ union acpi_operand_object *package_obj,
+ union acpi_operand_object *match_obj);
/*******************************************************************************
*
@@ -101,14 +94,12 @@ acpi_ex_do_match (
******************************************************************************/
static u8
-acpi_ex_do_match (
- u32 match_op,
- union acpi_operand_object *package_obj,
- union acpi_operand_object *match_obj)
+acpi_ex_do_match(u32 match_op,
+ union acpi_operand_object *package_obj,
+ union acpi_operand_object *match_obj)
{
- u8 logical_result = TRUE;
- acpi_status status;
-
+ u8 logical_result = TRUE;
+ acpi_status status;
/*
* Note: Since the package_obj/match_obj ordering is opposite to that of
@@ -133,9 +124,10 @@ acpi_ex_do_match (
* True if equal: (P[i] == M)
* Change to: (M == P[i])
*/
- status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -146,12 +138,13 @@ acpi_ex_do_match (
* True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
* Change to: (M >= P[i]) (M not_less than P[i])
*/
- status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
- logical_result = (u8) !logical_result;
+ logical_result = (u8) ! logical_result;
break;
case MATCH_MLT:
@@ -160,9 +153,10 @@ acpi_ex_do_match (
* True if less than: (P[i] < M)
* Change to: (M > P[i])
*/
- status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+ package_obj, &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -173,12 +167,13 @@ acpi_ex_do_match (
* True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
* Change to: (M <= P[i]) (M not_greater than P[i])
*/
- status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+ package_obj, &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
- logical_result = (u8)!logical_result;
+ logical_result = (u8) ! logical_result;
break;
case MATCH_MGT:
@@ -187,9 +182,10 @@ acpi_ex_do_match (
* True if greater than: (P[i] > M)
* Change to: (M < P[i])
*/
- status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -204,7 +200,6 @@ acpi_ex_do_match (
return logical_result;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_6A_0T_1R
@@ -217,20 +212,16 @@ acpi_ex_do_match (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_6A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- acpi_integer index;
- union acpi_operand_object *this_element;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_6A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ acpi_integer index;
+ union acpi_operand_object *this_element;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_MATCH_OP:
@@ -242,8 +233,9 @@ acpi_ex_opcode_6A_0T_1R (
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
- (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n"));
+ (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Match operator out of range\n"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -252,16 +244,17 @@ acpi_ex_opcode_6A_0T_1R (
index = operand[5]->integer.value;
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index (%X%8.8X) beyond package end (%X)\n",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
/* Create an integer for the return value */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -283,7 +276,7 @@ acpi_ex_opcode_6A_0T_1R (
* ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
- for ( ; index < operand[0]->package.count; index++) {
+ for (; index < operand[0]->package.count; index++) {
/* Get the current package element */
this_element = operand[0]->package.elements[index];
@@ -299,13 +292,13 @@ acpi_ex_opcode_6A_0T_1R (
* (proceed to next iteration of enclosing for loop) signifies a
* non-match.
*/
- if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
- this_element, operand[2])) {
+ if (!acpi_ex_do_match((u32) operand[1]->integer.value,
+ this_element, operand[2])) {
continue;
}
- if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
- this_element, operand[4])) {
+ if (!acpi_ex_do_match((u32) operand[3]->integer.value,
+ this_element, operand[4])) {
continue;
}
@@ -316,31 +309,27 @@ acpi_ex_opcode_6A_0T_1R (
}
break;
-
case AML_LOAD_TABLE_OP:
- status = acpi_ex_load_table_op (walk_state, &return_desc);
+ status = acpi_ex_load_table_op(walk_state, &return_desc);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
walk_state->result_obj = return_desc;
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index c9e3c68b5549..7476c363e407 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -42,32 +42,24 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exprep")
+ACPI_MODULE_NAME("exprep")
/* Local prototypes */
-
static u32
-acpi_ex_decode_field_access (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u32 *return_byte_alignment);
-
+acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
+ u8 field_flags, u32 * return_byte_alignment);
#ifdef ACPI_UNDER_DEVELOPMENT
static u32
-acpi_ex_generate_access (
- u32 field_bit_offset,
- u32 field_bit_length,
- u32 region_length);
+acpi_ex_generate_access(u32 field_bit_offset,
+ u32 field_bit_length, u32 region_length);
/*******************************************************************************
*
@@ -92,39 +84,36 @@ acpi_ex_generate_access (
******************************************************************************/
static u32
-acpi_ex_generate_access (
- u32 field_bit_offset,
- u32 field_bit_length,
- u32 region_length)
+acpi_ex_generate_access(u32 field_bit_offset,
+ u32 field_bit_length, u32 region_length)
{
- u32 field_byte_length;
- u32 field_byte_offset;
- u32 field_byte_end_offset;
- u32 access_byte_width;
- u32 field_start_offset;
- u32 field_end_offset;
- u32 minimum_access_width = 0xFFFFFFFF;
- u32 minimum_accesses = 0xFFFFFFFF;
- u32 accesses;
-
-
- ACPI_FUNCTION_TRACE ("ex_generate_access");
-
+ u32 field_byte_length;
+ u32 field_byte_offset;
+ u32 field_byte_end_offset;
+ u32 access_byte_width;
+ u32 field_start_offset;
+ u32 field_end_offset;
+ u32 minimum_access_width = 0xFFFFFFFF;
+ u32 minimum_accesses = 0xFFFFFFFF;
+ u32 accesses;
+
+ ACPI_FUNCTION_TRACE("ex_generate_access");
/* Round Field start offset and length to "minimal" byte boundaries */
- field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
- field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length +
- field_bit_offset, 8));
- field_byte_length = field_byte_end_offset - field_byte_offset;
+ field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
+ field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
+ field_bit_offset, 8));
+ field_byte_length = field_byte_end_offset - field_byte_offset;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Bit length %d, Bit offset %d\n",
- field_bit_length, field_bit_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Bit length %d, Bit offset %d\n",
+ field_bit_length, field_bit_offset));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Byte Length %d, Byte Offset %d, End Offset %d\n",
- field_byte_length, field_byte_offset, field_byte_end_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Byte Length %d, Byte Offset %d, End Offset %d\n",
+ field_byte_length, field_byte_offset,
+ field_byte_end_offset));
/*
* Iterative search for the maximum access width that is both aligned
@@ -132,7 +121,8 @@ acpi_ex_generate_access (
*
* Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
*/
- for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
+ for (access_byte_width = 1; access_byte_width <= 8;
+ access_byte_width <<= 1) {
/*
* 1) Round end offset up to next access boundary and make sure that
* this does not go beyond the end of the parent region.
@@ -140,31 +130,37 @@ acpi_ex_generate_access (
* are done. (This does not optimize for the perfectly aligned
* case yet).
*/
- if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
+ if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <=
+ region_length) {
field_start_offset =
- ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
- access_byte_width;
+ ACPI_ROUND_DOWN(field_byte_offset,
+ access_byte_width) /
+ access_byte_width;
field_end_offset =
- ACPI_ROUND_UP ((field_byte_length + field_byte_offset),
- access_byte_width) / access_byte_width;
+ ACPI_ROUND_UP((field_byte_length +
+ field_byte_offset),
+ access_byte_width) /
+ access_byte_width;
accesses = field_end_offset - field_start_offset;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "access_width %d end is within region\n", access_byte_width));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "access_width %d end is within region\n",
+ access_byte_width));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Field Start %d, Field End %d -- requires %d accesses\n",
- field_start_offset, field_end_offset, accesses));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Field Start %d, Field End %d -- requires %d accesses\n",
+ field_start_offset, field_end_offset,
+ accesses));
/* Single access is optimal */
if (accesses <= 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Entire field can be accessed with one operation of size %d\n",
- access_byte_width));
- return_VALUE (access_byte_width);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Entire field can be accessed with one operation of size %d\n",
+ access_byte_width));
+ return_VALUE(access_byte_width);
}
/*
@@ -172,30 +168,30 @@ acpi_ex_generate_access (
* try the next wider access on next iteration
*/
if (accesses < minimum_accesses) {
- minimum_accesses = accesses;
+ minimum_accesses = accesses;
minimum_access_width = access_byte_width;
}
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "access_width %d end is NOT within region\n", access_byte_width));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "access_width %d end is NOT within region\n",
+ access_byte_width));
if (access_byte_width == 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Field goes beyond end-of-region!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Field goes beyond end-of-region!\n"));
/* Field does not fit in the region at all */
- return_VALUE (0);
+ return_VALUE(0);
}
/*
* This width goes beyond the end-of-region, back off to
* previous access
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Backing off to previous optimal access width of %d\n",
- minimum_access_width));
- return_VALUE (minimum_access_width);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Backing off to previous optimal access width of %d\n",
+ minimum_access_width));
+ return_VALUE(minimum_access_width);
}
}
@@ -203,12 +199,11 @@ acpi_ex_generate_access (
* Could not read/write field with one operation,
* just use max access width
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Cannot access field in one operation, using width 8\n"));
- return_VALUE (8);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Cannot access field in one operation, using width 8\n"));
+ return_VALUE(8);
}
-#endif /* ACPI_UNDER_DEVELOPMENT */
-
+#endif /* ACPI_UNDER_DEVELOPMENT */
/*******************************************************************************
*
@@ -226,18 +221,14 @@ acpi_ex_generate_access (
******************************************************************************/
static u32
-acpi_ex_decode_field_access (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u32 *return_byte_alignment)
+acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
+ u8 field_flags, u32 * return_byte_alignment)
{
- u32 access;
- u32 byte_alignment;
- u32 bit_length;
-
-
- ACPI_FUNCTION_TRACE ("ex_decode_field_access");
+ u32 access;
+ u32 byte_alignment;
+ u32 bit_length;
+ ACPI_FUNCTION_TRACE("ex_decode_field_access");
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -246,9 +237,12 @@ acpi_ex_decode_field_access (
#ifdef ACPI_UNDER_DEVELOPMENT
byte_alignment =
- acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.bit_length,
- 0xFFFFFFFF /* Temp until we pass region_length as parameter */);
+ acpi_ex_generate_access(obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+ 0xFFFFFFFF
+ /* Temp until we pass region_length as parameter */
+ );
bit_length = byte_alignment * 8;
#endif
@@ -257,36 +251,35 @@ acpi_ex_decode_field_access (
break;
case AML_FIELD_ACCESS_BYTE:
- case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
+ case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
byte_alignment = 1;
- bit_length = 8;
+ bit_length = 8;
break;
case AML_FIELD_ACCESS_WORD:
byte_alignment = 2;
- bit_length = 16;
+ bit_length = 16;
break;
case AML_FIELD_ACCESS_DWORD:
byte_alignment = 4;
- bit_length = 32;
+ bit_length = 32;
break;
- case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
+ case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
byte_alignment = 8;
- bit_length = 64;
+ bit_length = 64;
break;
default:
/* Invalid field access type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown field access type %X\n",
- access));
- return_VALUE (0);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown field access type %X\n", access));
+ return_VALUE(0);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* buffer_field access can be on any byte boundary, so the
* byte_alignment is always 1 byte -- regardless of any byte_alignment
@@ -296,10 +289,9 @@ acpi_ex_decode_field_access (
}
*return_byte_alignment = byte_alignment;
- return_VALUE (bit_length);
+ return_VALUE(bit_length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_common_field_object
@@ -322,20 +314,16 @@ acpi_ex_decode_field_access (
******************************************************************************/
acpi_status
-acpi_ex_prep_common_field_object (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u8 field_attribute,
- u32 field_bit_position,
- u32 field_bit_length)
+acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
+ u8 field_flags,
+ u8 field_attribute,
+ u32 field_bit_position, u32 field_bit_length)
{
- u32 access_bit_width;
- u32 byte_alignment;
- u32 nearest_byte_address;
-
-
- ACPI_FUNCTION_TRACE ("ex_prep_common_field_object");
+ u32 access_bit_width;
+ u32 byte_alignment;
+ u32 nearest_byte_address;
+ ACPI_FUNCTION_TRACE("ex_prep_common_field_object");
/*
* Note: the structure being initialized is the
@@ -361,16 +349,16 @@ acpi_ex_prep_common_field_object (
* For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
* the same (equivalent) as the byte_alignment.
*/
- access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
- &byte_alignment);
+ access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags,
+ &byte_alignment);
if (!access_bit_width) {
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
/* Setup width (access granularity) fields */
obj_desc->common_field.access_byte_width = (u8)
- ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
+ ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
@@ -385,30 +373,30 @@ acpi_ex_prep_common_field_object (
* region or buffer.
*/
nearest_byte_address =
- ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
+ ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position);
obj_desc->common_field.base_byte_offset = (u32)
- ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
+ ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment);
/*
* start_field_bit_offset is the offset of the first bit of the field within
* a field datum.
*/
obj_desc->common_field.start_field_bit_offset = (u8)
- (field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
+ (field_bit_position -
+ ACPI_MUL_8(obj_desc->common_field.base_byte_offset));
/*
* Does the entire field fit within a single field access element? (datum)
* (i.e., without crossing a datum boundary)
*/
- if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
- (u16) access_bit_width) {
+ if ((obj_desc->common_field.start_field_bit_offset +
+ field_bit_length) <= (u16) access_bit_width) {
obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_field_value
@@ -422,51 +410,49 @@ acpi_ex_prep_common_field_object (
*
******************************************************************************/
-acpi_status
-acpi_ex_prep_field_value (
- struct acpi_create_field_info *info)
+acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
- union acpi_operand_object *obj_desc;
- u32 type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_prep_field_value");
+ union acpi_operand_object *obj_desc;
+ u32 type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_prep_field_value");
/* Parameter validation */
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
if (!info->region_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null region_node\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
- type = acpi_ns_get_type (info->region_node);
+ type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed Region, found type %X (%s)\n",
- type, acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Region, found type %X (%s)\n",
+ type, acpi_ut_get_type_name(type)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
/* Allocate a new field object */
- obj_desc = acpi_ut_create_internal_object (info->field_type);
+ obj_desc = acpi_ut_create_internal_object(info->field_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node;
- status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
- info->attribute, info->field_bit_position, info->field_bit_length);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (status);
+ status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
+ info->attribute,
+ info->field_bit_position,
+ info->field_bit_length);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
}
/* Initialize areas of the object that are specific to the field type */
@@ -474,71 +460,73 @@ acpi_ex_prep_field_value (
switch (info->field_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
- obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node);
+ obj_desc->field.region_obj =
+ acpi_ns_get_attached_object(info->region_node);
/* An additional reference for the container */
- acpi_ut_add_reference (obj_desc->field.region_obj);
+ 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",
- obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
- obj_desc->field.access_byte_width, obj_desc->field.region_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "region_field: bit_off %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,
+ obj_desc->field.region_obj));
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- obj_desc->bank_field.value = info->bank_value;
- obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (
- info->region_node);
- obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (
- info->register_node);
+ obj_desc->bank_field.value = info->bank_value;
+ obj_desc->bank_field.region_obj =
+ acpi_ns_get_attached_object(info->region_node);
+ obj_desc->bank_field.bank_obj =
+ acpi_ns_get_attached_object(info->register_node);
/* An additional reference for the attached objects */
- acpi_ut_add_reference (obj_desc->bank_field.region_obj);
- acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
+ acpi_ut_add_reference(obj_desc->bank_field.region_obj);
+ 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",
- obj_desc->bank_field.start_field_bit_offset,
- obj_desc->bank_field.base_byte_offset,
- obj_desc->field.access_byte_width,
- obj_desc->bank_field.region_obj,
- 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",
+ obj_desc->bank_field.start_field_bit_offset,
+ obj_desc->bank_field.base_byte_offset,
+ obj_desc->field.access_byte_width,
+ obj_desc->bank_field.region_obj,
+ obj_desc->bank_field.bank_obj));
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- obj_desc->index_field.index_obj = acpi_ns_get_attached_object (
- info->register_node);
- obj_desc->index_field.data_obj = acpi_ns_get_attached_object (
- info->data_register_node);
- obj_desc->index_field.value = (u32)
- (info->field_bit_position / ACPI_MUL_8 (
- obj_desc->field.access_byte_width));
-
- if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
- ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ obj_desc->index_field.index_obj =
+ acpi_ns_get_attached_object(info->register_node);
+ obj_desc->index_field.data_obj =
+ acpi_ns_get_attached_object(info->data_register_node);
+ obj_desc->index_field.value = (u32)
+ (info->field_bit_position /
+ ACPI_MUL_8(obj_desc->field.access_byte_width));
+
+ if (!obj_desc->index_field.data_obj
+ || !obj_desc->index_field.index_obj) {
+ ACPI_REPORT_ERROR(("Null Index Object during field prep\n"));
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* An additional reference for the attached objects */
- acpi_ut_add_reference (obj_desc->index_field.data_obj);
- acpi_ut_add_reference (obj_desc->index_field.index_obj);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "index_field: bit_off %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,
- obj_desc->field.access_byte_width,
- obj_desc->index_field.index_obj,
- obj_desc->index_field.data_obj));
+ acpi_ut_add_reference(obj_desc->index_field.data_obj);
+ acpi_ut_add_reference(obj_desc->index_field.index_obj);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "index_field: bit_off %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,
+ obj_desc->field.access_byte_width,
+ obj_desc->index_field.index_obj,
+ obj_desc->index_field.data_obj));
break;
default:
@@ -550,15 +538,16 @@ acpi_ex_prep_field_value (
* Store the constructed descriptor (obj_desc) into the parent Node,
* preserving the current type of that named_obj.
*/
- status = acpi_ns_attach_object (info->field_node, obj_desc,
- acpi_ns_get_type (info->field_node));
+ status = acpi_ns_attach_object(info->field_node, obj_desc,
+ acpi_ns_get_type(info->field_node));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
- info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Set named_obj %p [%4.4s], obj_desc %p\n",
+ info->field_node,
+ acpi_ut_get_node_name(info->field_node), obj_desc));
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 723aaef4bb4a..9a2f5bea3afe 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exregion")
-
+ACPI_MODULE_NAME("exregion")
/*******************************************************************************
*
@@ -68,27 +65,23 @@
* DESCRIPTION: Handler for the System Memory address space (Op Region)
*
******************************************************************************/
-
acpi_status
-acpi_ex_system_memory_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_system_memory_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- void *logical_addr_ptr = NULL;
- struct acpi_mem_space_context *mem_info = region_context;
- u32 length;
- acpi_size window_size;
+ acpi_status status = AE_OK;
+ void *logical_addr_ptr = NULL;
+ struct acpi_mem_space_context *mem_info = region_context;
+ u32 length;
+ acpi_size window_size;
#ifndef ACPI_MISALIGNED_TRANSFERS
- u32 remainder;
+ 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 */
@@ -110,9 +103,10 @@ acpi_ex_system_memory_space_handler (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n",
- bit_width));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid system_memory width %d\n",
+ bit_width));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
#ifndef ACPI_MISALIGNED_TRANSFERS
@@ -120,9 +114,10 @@ acpi_ex_system_memory_space_handler (
* Hardware does not support non-aligned data transfers, we must verify
* the request.
*/
- (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder);
+ (void)acpi_ut_short_divide((acpi_integer) address, length, NULL,
+ &remainder);
if (remainder != 0) {
- return_ACPI_STATUS (AE_AML_ALIGNMENT);
+ return_ACPI_STATUS(AE_AML_ALIGNMENT);
}
#endif
@@ -132,9 +127,10 @@ acpi_ex_system_memory_space_handler (
* 2) Address beyond the current mapping?
*/
if ((address < mem_info->mapped_physical_address) ||
- (((acpi_integer) address + length) >
- ((acpi_integer)
- mem_info->mapped_physical_address + mem_info->mapped_length))) {
+ (((acpi_integer) address + length) > ((acpi_integer)
+ mem_info->
+ mapped_physical_address +
+ mem_info->mapped_length))) {
/*
* The request cannot be resolved by the current memory mapping;
* Delete the existing mapping and create a new one.
@@ -142,8 +138,8 @@ acpi_ex_system_memory_space_handler (
if (mem_info->mapped_length) {
/* Valid mapping, delete it */
- acpi_os_unmap_memory (mem_info->mapped_logical_address,
- mem_info->mapped_length);
+ acpi_os_unmap_memory(mem_info->mapped_logical_address,
+ mem_info->mapped_length);
}
/*
@@ -151,7 +147,7 @@ acpi_ex_system_memory_space_handler (
* constrain the maximum mapping size to something reasonable.
*/
window_size = (acpi_size)
- ((mem_info->address + mem_info->length) - address);
+ ((mem_info->address + mem_info->length) - address);
if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
@@ -159,14 +155,16 @@ acpi_ex_system_memory_space_handler (
/* Create a new mapping starting at the address given */
- status = acpi_os_map_memory (address, window_size,
- (void **) &mem_info->mapped_logical_address);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X%8.8X, size %X\n",
- ACPI_FORMAT_UINT64 (address), (u32) window_size));
+ status = acpi_os_map_memory(address, window_size,
+ (void **)&mem_info->
+ mapped_logical_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X%8.8X, size %X\n",
+ ACPI_FORMAT_UINT64(address),
+ (u32) window_size));
mem_info->mapped_length = 0;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Save the physical address and mapping size */
@@ -180,42 +178,41 @@ acpi_ex_system_memory_space_handler (
* access
*/
logical_addr_ptr = mem_info->mapped_logical_address +
- ((acpi_integer) address -
- (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)));
-
- /*
- * Perform the memory read or write
- *
- * Note: For machines that do not support non-aligned transfers, the target
- * address was checked for alignment above. We do not attempt to break the
- * transfer up into smaller (byte-size) chunks because the AML specifically
- * asked for a transfer width that the hardware may require.
- */
+ ((acpi_integer) address -
+ (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)));
+
+ /*
+ * Perform the memory read or write
+ *
+ * Note: For machines that do not support non-aligned transfers, the target
+ * address was checked for alignment above. We do not attempt to break the
+ * transfer up into smaller (byte-size) chunks because the AML specifically
+ * asked for a transfer width that the hardware may require.
+ */
switch (function) {
case ACPI_READ:
*value = 0;
switch (bit_width) {
case 8:
- *value = (acpi_integer) *((u8 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u8 *) logical_addr_ptr);
break;
case 16:
- *value = (acpi_integer) *((u16 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u16 *) logical_addr_ptr);
break;
case 32:
- *value = (acpi_integer) *((u32 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u32 *) logical_addr_ptr);
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *value = (acpi_integer) *((u64 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u64 *) logical_addr_ptr);
break;
#endif
default:
@@ -228,20 +225,20 @@ acpi_ex_system_memory_space_handler (
switch (bit_width) {
case 8:
- *(u8 *) logical_addr_ptr = (u8) *value;
+ *(u8 *) logical_addr_ptr = (u8) * value;
break;
case 16:
- *(u16 *) logical_addr_ptr = (u16) *value;
+ *(u16 *) logical_addr_ptr = (u16) * value;
break;
case 32:
- *(u32 *) logical_addr_ptr = (u32) *value;
+ *(u32 *) logical_addr_ptr = (u32) * value;
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *(u64 *) logical_addr_ptr = (u64) *value;
+ *(u64 *) logical_addr_ptr = (u64) * value;
break;
#endif
@@ -256,10 +253,9 @@ acpi_ex_system_memory_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_io_space_handler
@@ -279,39 +275,35 @@ acpi_ex_system_memory_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_system_io_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_system_io_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- u32 value32;
+ 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)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "system_iO %d (%d width) Address=%8.8X%8.8X\n",
+ function, bit_width, ACPI_FORMAT_UINT64(address)));
/* Decode the function parameter */
switch (function) {
case ACPI_READ:
- status = acpi_os_read_port ((acpi_io_address) address,
- &value32, bit_width);
+ status = acpi_os_read_port((acpi_io_address) address,
+ &value32, bit_width);
*value = value32;
break;
case ACPI_WRITE:
- status = acpi_os_write_port ((acpi_io_address) address,
- (u32) *value, bit_width);
+ status = acpi_os_write_port((acpi_io_address) address,
+ (u32) * value, bit_width);
break;
default:
@@ -319,10 +311,9 @@ acpi_ex_system_io_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_config_space_handler
@@ -342,21 +333,17 @@ acpi_ex_system_io_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_pci_config_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_pci_config_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- struct acpi_pci_id *pci_id;
- u16 pci_register;
-
-
- ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler");
+ acpi_status status = AE_OK;
+ struct acpi_pci_id *pci_id;
+ u16 pci_register;
+ ACPI_FUNCTION_TRACE("ex_pci_config_space_handler");
/*
* The arguments to acpi_os(Read|Write)pci_configuration are:
@@ -370,26 +357,26 @@ acpi_ex_pci_config_space_handler (
* Value - input value for write, output address for read
*
*/
- pci_id = (struct acpi_pci_id *) region_context;
+ pci_id = (struct acpi_pci_id *)region_context;
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",
- function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
- pci_id->function, pci_register));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "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));
switch (function) {
case ACPI_READ:
*value = 0;
- status = acpi_os_read_pci_configuration (pci_id, pci_register,
- value, bit_width);
+ status = acpi_os_read_pci_configuration(pci_id, pci_register,
+ value, bit_width);
break;
case ACPI_WRITE:
- status = acpi_os_write_pci_configuration (pci_id, pci_register,
- *value, bit_width);
+ status = acpi_os_write_pci_configuration(pci_id, pci_register,
+ *value, bit_width);
break;
default:
@@ -398,10 +385,9 @@ acpi_ex_pci_config_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_cmos_space_handler
@@ -421,24 +407,19 @@ acpi_ex_pci_config_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_cmos_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_cmos_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("ex_cmos_space_handler");
+ ACPI_FUNCTION_TRACE("ex_cmos_space_handler");
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_bar_space_handler
@@ -458,24 +439,19 @@ acpi_ex_cmos_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_pci_bar_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_pci_bar_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
-
+ 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);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_data_table_space_handler
@@ -495,24 +471,20 @@ acpi_ex_pci_bar_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_data_table_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_data_table_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ 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_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");
+ ACPI_FUNCTION_TRACE("ex_data_table_space_handler");
-
- logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address);
+ logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address);
/* Perform the memory read or write */
@@ -520,17 +492,15 @@ acpi_ex_data_table_space_handler (
case ACPI_READ:
for (i = 0; i < byte_width; i++) {
- ((char *) value) [i] = logical_addr_ptr[i];
+ ((char *)value)[i] = logical_addr_ptr[i];
}
break;
case ACPI_WRITE:
default:
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 21d5c74fa309..ff5d8f97e8eb 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
@@ -50,10 +49,8 @@
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresnte")
-
+ACPI_MODULE_NAME("exresnte")
/*******************************************************************************
*
@@ -80,41 +77,37 @@
* ACPI_TYPE_PACKAGE
*
******************************************************************************/
-
acpi_status
-acpi_ex_resolve_node_to_value (
- struct acpi_namespace_node **object_ptr,
- struct acpi_walk_state *walk_state)
-
+acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *source_desc;
- union acpi_operand_object *obj_desc = NULL;
- struct acpi_namespace_node *node;
- acpi_object_type entry_type;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *source_desc;
+ union acpi_operand_object *obj_desc = NULL;
+ struct acpi_namespace_node *node;
+ acpi_object_type entry_type;
+ ACPI_FUNCTION_TRACE("ex_resolve_node_to_value");
/*
* The stack pointer points to a struct acpi_namespace_node (Node). Get the
* object that is attached to the Node.
*/
- node = *object_ptr;
- source_desc = acpi_ns_get_attached_object (node);
- entry_type = acpi_ns_get_type ((acpi_handle) node);
+ 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",
- node, source_desc, acpi_ut_get_type_name (entry_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%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)) {
+ (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);
- source_desc = acpi_ns_get_attached_object (node);
- entry_type = acpi_ns_get_type ((acpi_handle) node);
+ node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
+ source_desc = acpi_ns_get_attached_object(node);
+ entry_type = acpi_ns_get_type((acpi_handle) node);
*object_ptr = node;
}
@@ -124,14 +117,14 @@ acpi_ex_resolve_node_to_value (
* 2) Method locals and arguments have a pseudo-Node
*/
if (entry_type == ACPI_TYPE_DEVICE ||
- (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
- return_ACPI_STATUS (AE_OK);
+ (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
+ return_ACPI_STATUS(AE_OK);
}
if (!source_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n",
- node));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No object attached to node %p\n", node));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
@@ -141,83 +134,89 @@ acpi_ex_resolve_node_to_value (
switch (entry_type) {
case ACPI_TYPE_PACKAGE:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Package, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- status = acpi_ds_get_package_arguments (source_desc);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_get_package_arguments(source_desc);
+ if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
}
break;
-
case ACPI_TYPE_BUFFER:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Buffer, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- status = acpi_ds_get_buffer_arguments (source_desc);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_get_buffer_arguments(source_desc);
+ if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
}
break;
-
case ACPI_TYPE_STRING:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a String, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
-
case ACPI_TYPE_INTEGER:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Integer, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
-
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "field_read Node=%p source_desc=%p Type=%X\n",
- node, source_desc, entry_type));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "field_read Node=%p source_desc=%p Type=%X\n",
+ node, source_desc, entry_type));
- status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
+ status =
+ acpi_ex_read_data_from_field(walk_state, source_desc,
+ &obj_desc);
break;
- /* For these objects, just return the object attached to the Node */
+ /* For these objects, just return the object attached to the Node */
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_METHOD:
@@ -230,19 +229,18 @@ acpi_ex_resolve_node_to_value (
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
- /* TYPE_ANY is untyped, and thus there is no object associated with it */
+ /* TYPE_ANY is untyped, and thus there is no object associated with it */
case ACPI_TYPE_ANY:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Untyped entry %p, no attached object!\n",
- node));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Untyped entry %p, no attached object!\n",
+ node));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -253,39 +251,37 @@ acpi_ex_resolve_node_to_value (
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
default:
/* No named references are allowed here */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported Reference opcode %X (%s)\n",
- source_desc->reference.opcode,
- acpi_ps_get_opcode_name (source_desc->reference.opcode)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported Reference opcode %X (%s)\n",
+ source_desc->reference.opcode,
+ acpi_ps_get_opcode_name(source_desc->
+ reference.
+ opcode)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
-
default:
/* Default case is for unknown types */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Node %p - Unknown object type %X\n",
- node, entry_type));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Node %p - Unknown object type %X\n",
+ node, entry_type));
- } /* switch (entry_type) */
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ } /* switch (entry_type) */
/* Return the object descriptor */
- *object_ptr = (void *) obj_desc;
- return_ACPI_STATUS (status);
+ *object_ptr = (void *)obj_desc;
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 3de45672379a..97eecbd3242d 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
@@ -50,17 +49,13 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresolv")
+ACPI_MODULE_NAME("exresolv")
/* Local prototypes */
-
static acpi_status
-acpi_ex_resolve_object_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -78,19 +73,16 @@ acpi_ex_resolve_object_to_value (
******************************************************************************/
acpi_status
-acpi_ex_resolve_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_resolve_to_value", stack_ptr);
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
if (!stack_ptr || !*stack_ptr) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Internal - null pointer\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
@@ -98,15 +90,16 @@ acpi_ex_resolve_to_value (
* 1) A valid union acpi_operand_object, or
* 2) A struct acpi_namespace_node (named_obj)
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
- status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
+ status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (!*stack_ptr) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Internal - null pointer\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
}
@@ -114,20 +107,20 @@ acpi_ex_resolve_to_value (
* Object on the stack may have changed if acpi_ex_resolve_object_to_value()
* was called (i.e., we can't use an _else_ here.)
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
- status = acpi_ex_resolve_node_to_value (
- ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, stack_ptr),
- walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
+ status =
+ acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
+ (struct acpi_namespace_node,
+ stack_ptr), walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_object_to_value
@@ -143,25 +136,22 @@ acpi_ex_resolve_to_value (
******************************************************************************/
static acpi_status
-acpi_ex_resolve_object_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *stack_desc;
- void *temp_node;
- union acpi_operand_object *obj_desc;
- u16 opcode;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_object_to_value");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *stack_desc;
+ void *temp_node;
+ union acpi_operand_object *obj_desc;
+ u16 opcode;
+ ACPI_FUNCTION_TRACE("ex_resolve_object_to_value");
stack_desc = *stack_ptr;
/* This is an union acpi_operand_object */
- switch (ACPI_GET_OBJECT_TYPE (stack_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
opcode = stack_desc->reference.opcode;
@@ -177,14 +167,13 @@ acpi_ex_resolve_object_to_value (
/* Delete the Reference Object */
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_remove_reference(stack_desc);
/* Return the namespace node */
(*stack_ptr) = temp_node;
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
@@ -192,24 +181,28 @@ acpi_ex_resolve_object_to_value (
* Get the local from the method's state info
* Note: this increments the local's object reference count
*/
- status = acpi_ds_method_data_get_value (opcode,
- stack_desc->reference.offset, walk_state, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_value(opcode,
+ stack_desc->
+ reference.offset,
+ walk_state,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
- stack_desc->reference.offset, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Arg/Local %X] value_obj is %p\n",
+ stack_desc->reference.offset,
+ obj_desc));
/*
* Now we can delete the original Reference Object and
* replace it with the resolved value
*/
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_remove_reference(stack_desc);
*stack_ptr = obj_desc;
break;
-
case AML_INDEX_OP:
switch (stack_desc->reference.target_type) {
@@ -218,7 +211,6 @@ acpi_ex_resolve_object_to_value (
/* Just return - leave the Reference on the stack */
break;
-
case ACPI_TYPE_PACKAGE:
obj_desc = *stack_desc->reference.where;
@@ -228,36 +220,31 @@ acpi_ex_resolve_object_to_value (
* (i.e., dereference the package index)
* Delete the ref object, increment the returned object
*/
- acpi_ut_remove_reference (stack_desc);
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_remove_reference(stack_desc);
+ acpi_ut_add_reference(obj_desc);
*stack_ptr = obj_desc;
- }
- else {
+ } else {
/*
* A NULL object descriptor means an unitialized element of
* the package, can't dereference it
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Attempt to deref an Index to NULL pkg element Idx=%p\n",
- stack_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Attempt to deref an Index to NULL pkg element Idx=%p\n",
+ stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
break;
-
default:
/* Invalid reference object */
- ACPI_REPORT_ERROR ((
- "During resolve, Unknown target_type %X in Index/Reference obj %p\n",
- stack_desc->reference.target_type, stack_desc));
+ ACPI_REPORT_ERROR(("During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
-
case AML_REF_OF_OP:
case AML_DEBUG_OP:
case AML_LOAD_OP:
@@ -266,60 +253,58 @@ acpi_ex_resolve_object_to_value (
break;
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
+ case AML_INT_NAMEPATH_OP: /* Reference to a named object */
/* Get the object pointed to by the namespace node */
*stack_ptr = (stack_desc->reference.node)->object;
- acpi_ut_add_reference (*stack_ptr);
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_add_reference(*stack_ptr);
+ acpi_ut_remove_reference(stack_desc);
break;
default:
- ACPI_REPORT_ERROR ((
- "During resolve, Unknown Reference opcode %X (%s) in %p\n",
- opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
+ ACPI_REPORT_ERROR(("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name(opcode), stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
-
case ACPI_TYPE_BUFFER:
- status = acpi_ds_get_buffer_arguments (stack_desc);
+ status = acpi_ds_get_buffer_arguments(stack_desc);
break;
-
case ACPI_TYPE_PACKAGE:
- status = acpi_ds_get_package_arguments (stack_desc);
+ status = acpi_ds_get_package_arguments(stack_desc);
break;
-
- /* These cases may never happen here, but just in case.. */
+ /* These cases may never happen here, but just in case.. */
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read source_desc=%p Type=%X\n",
- stack_desc, ACPI_GET_OBJECT_TYPE (stack_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "field_read source_desc=%p Type=%X\n",
+ stack_desc,
+ ACPI_GET_OBJECT_TYPE(stack_desc)));
- status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc);
- *stack_ptr = (void *) obj_desc;
+ status =
+ acpi_ex_read_data_from_field(walk_state, stack_desc,
+ &obj_desc);
+ *stack_ptr = (void *)obj_desc;
break;
default:
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_multiple
@@ -337,42 +322,44 @@ acpi_ex_resolve_object_to_value (
******************************************************************************/
acpi_status
-acpi_ex_resolve_multiple (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *operand,
- acpi_object_type *return_type,
- union acpi_operand_object **return_desc)
+acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *operand,
+ acpi_object_type * return_type,
+ union acpi_operand_object **return_desc)
{
- union acpi_operand_object *obj_desc = (void *) operand;
- struct acpi_namespace_node *node;
- acpi_object_type type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple");
+ union acpi_operand_object *obj_desc = (void *)operand;
+ struct acpi_namespace_node *node;
+ acpi_object_type type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple");
/* Operand can be either a namespace node or an operand descriptor */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
type = obj_desc->common.type;
break;
case ACPI_DESC_TYPE_NAMED:
- type = ((struct acpi_namespace_node *) obj_desc)->type;
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
+ type = ((struct acpi_namespace_node *)obj_desc)->type;
+ obj_desc =
+ acpi_ns_get_attached_object((struct acpi_namespace_node *)
+ obj_desc);
/* If we had an Alias node, use the attached object for type info */
if (type == ACPI_TYPE_LOCAL_ALIAS) {
- type = ((struct acpi_namespace_node *) obj_desc)->type;
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
+ type = ((struct acpi_namespace_node *)obj_desc)->type;
+ obj_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node *)
+ obj_desc);
}
break;
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* If type is anything other than a reference, we are done */
@@ -387,7 +374,7 @@ acpi_ex_resolve_multiple (
* of the object_type and size_of operators). This means traversing
* the list of possibly many nested references.
*/
- while (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
+ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.opcode) {
case AML_REF_OF_OP:
@@ -397,31 +384,29 @@ acpi_ex_resolve_multiple (
/* All "References" point to a NS node */
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", 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);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, use the NS node type */
- type = acpi_ns_get_type (node);
+ type = acpi_ns_get_type(node);
goto exit;
}
/* Check for circular references */
if (obj_desc == operand) {
- return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
+ return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
}
break;
-
case AML_INDEX_OP:
/* Get the type of this reference (index into another object) */
@@ -442,12 +427,11 @@ acpi_ex_resolve_multiple (
if (!obj_desc) {
/* NULL package elements are allowed */
- type = 0; /* Uninitialized */
+ type = 0; /* Uninitialized */
goto exit;
}
break;
-
case AML_INT_NAMEPATH_OP:
/* Dereference the reference pointer */
@@ -456,50 +440,61 @@ acpi_ex_resolve_multiple (
/* All "References" point to a NS node */
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", 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);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, use the NS node type */
- type = acpi_ns_get_type (node);
+ type = acpi_ns_get_type(node);
goto exit;
}
/* Check for circular references */
if (obj_desc == operand) {
- return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
+ return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
}
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
if (return_desc) {
- status = acpi_ds_method_data_get_value (obj_desc->reference.opcode,
- obj_desc->reference.offset, walk_state, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_method_data_get_value(obj_desc->
+ reference.
+ opcode,
+ obj_desc->
+ reference.
+ offset,
+ walk_state,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- acpi_ut_remove_reference (obj_desc);
- }
- else {
- status = acpi_ds_method_data_get_node (obj_desc->reference.opcode,
- obj_desc->reference.offset, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ } else {
+ status =
+ acpi_ds_method_data_get_node(obj_desc->
+ reference.
+ opcode,
+ obj_desc->
+ reference.
+ offset,
+ walk_state,
+ &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
type = ACPI_TYPE_ANY;
goto exit;
@@ -507,7 +502,6 @@ acpi_ex_resolve_multiple (
}
break;
-
case AML_DEBUG_OP:
/* The Debug Object is of type "debug_object" */
@@ -515,13 +509,10 @@ acpi_ex_resolve_multiple (
type = ACPI_TYPE_DEBUG_OBJECT;
goto exit;
-
default:
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Unknown Reference subtype %X\n",
- obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
@@ -529,10 +520,9 @@ acpi_ex_resolve_multiple (
* Now we are guaranteed to have an object that has not been created
* via the ref_of or Index operators.
*/
- type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ type = ACPI_GET_OBJECT_TYPE(obj_desc);
-
-exit:
+ exit:
/* Convert internal types to external types */
switch (type) {
@@ -559,7 +549,5 @@ exit:
if (return_desc) {
*return_desc = obj_desc;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index d8b470eefe7a..ff064e79ab90 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -42,24 +42,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresop")
+ACPI_MODULE_NAME("exresop")
/* Local prototypes */
-
static acpi_status
-acpi_ex_check_object_type (
- acpi_object_type type_needed,
- acpi_object_type this_type,
- void *object);
-
+acpi_ex_check_object_type(acpi_object_type type_needed,
+ acpi_object_type this_type, void *object);
/*******************************************************************************
*
@@ -76,13 +70,10 @@ acpi_ex_check_object_type (
******************************************************************************/
static acpi_status
-acpi_ex_check_object_type (
- acpi_object_type type_needed,
- acpi_object_type this_type,
- void *object)
+acpi_ex_check_object_type(acpi_object_type type_needed,
+ acpi_object_type this_type, void *object)
{
- ACPI_FUNCTION_NAME ("ex_check_object_type");
-
+ ACPI_FUNCTION_NAME("ex_check_object_type");
if (type_needed == ACPI_TYPE_ANY) {
/* All types OK, so we don't perform any typechecks */
@@ -97,16 +88,17 @@ acpi_ex_check_object_type (
* specification, a store to a constant is a noop.)
*/
if ((this_type == ACPI_TYPE_INTEGER) &&
- (((union acpi_operand_object *) object)->common.flags & AOPOBJ_AML_CONSTANT)) {
+ (((union acpi_operand_object *)object)->common.
+ flags & AOPOBJ_AML_CONSTANT)) {
return (AE_OK);
}
}
if (type_needed != this_type) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [%s], found [%s] %p\n",
- acpi_ut_get_type_name (type_needed),
- acpi_ut_get_type_name (this_type), object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [%s], found [%s] %p\n",
+ acpi_ut_get_type_name(type_needed),
+ acpi_ut_get_type_name(this_type), object));
return (AE_AML_OPERAND_TYPE);
}
@@ -114,7 +106,6 @@ acpi_ex_check_object_type (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_operands
@@ -137,41 +128,37 @@ acpi_ex_check_object_type (
******************************************************************************/
acpi_status
-acpi_ex_resolve_operands (
- u16 opcode,
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_operands(u16 opcode,
+ union acpi_operand_object ** stack_ptr,
+ struct acpi_walk_state * walk_state)
{
- union acpi_operand_object *obj_desc;
- acpi_status status = AE_OK;
- u8 object_type;
- void *temp_node;
- u32 arg_types;
- const struct acpi_opcode_info *op_info;
- u32 this_arg_type;
- acpi_object_type type_needed;
- u16 target_op = 0;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_resolve_operands", opcode);
-
-
- op_info = acpi_ps_get_opcode_info (opcode);
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ u8 object_type;
+ void *temp_node;
+ u32 arg_types;
+ const struct acpi_opcode_info *op_info;
+ u32 this_arg_type;
+ acpi_object_type type_needed;
+ u16 target_op = 0;
+
+ ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode);
+
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg_types = op_info->runtime_args;
if (arg_types == ARGI_INVALID_OPCODE) {
- ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
- opcode));
+ ACPI_REPORT_ERROR(("resolve_operands: %X is not a valid AML opcode\n", opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Opcode %X [%s] required_operand_types=%8.8X \n",
- opcode, op_info->name, arg_types));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Opcode %X [%s] required_operand_types=%8.8X \n",
+ opcode, op_info->name, arg_types));
/*
* Normal exit is with (arg_types == 0) at end of argument list.
@@ -180,12 +167,11 @@ acpi_ex_resolve_operands (
* to) the required type; if stack underflows; or upon
* finding a NULL stack entry (which should not happen).
*/
- while (GET_CURRENT_ARG_TYPE (arg_types)) {
+ while (GET_CURRENT_ARG_TYPE(arg_types)) {
if (!stack_ptr || !*stack_ptr) {
- ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
- stack_ptr));
+ ACPI_REPORT_ERROR(("resolve_operands: Null stack entry at %p\n", stack_ptr));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Extract useful items */
@@ -194,37 +180,37 @@ acpi_ex_resolve_operands (
/* Decode the descriptor type */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_NAMED:
/* Namespace Node */
- object_type = ((struct acpi_namespace_node *) obj_desc)->type;
+ object_type =
+ ((struct acpi_namespace_node *)obj_desc)->type;
break;
-
case ACPI_DESC_TYPE_OPERAND:
/* ACPI internal object */
- object_type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ object_type = ACPI_GET_OBJECT_TYPE(obj_desc);
/* Check for bad acpi_object_type */
- if (!acpi_ut_valid_object_type (object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad operand object type [%X]\n",
- object_type));
+ if (!acpi_ut_valid_object_type(object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad operand object type [%X]\n",
+ object_type));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
/* Decode the Reference */
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
switch (obj_desc->reference.opcode) {
@@ -238,51 +224,62 @@ acpi_ex_resolve_operands (
case AML_REF_OF_OP:
case AML_ARG_OP:
case AML_LOCAL_OP:
- case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
-
- ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Operand is a Reference, ref_opcode [%s]\n",
- (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)));
+ case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
+ case AML_INT_NAMEPATH_OP: /* Reference to a named object */
+
+ ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
+ ((ACPI_DB_EXEC,
+ "Operand is a Reference, ref_opcode [%s]\n",
+ (acpi_ps_get_opcode_info
+ (obj_desc->
+ reference.
+ opcode))->
+ name)));
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
- obj_desc->reference.opcode,
- (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
+ obj_desc->reference.
+ opcode,
+ (acpi_ps_get_opcode_info
+ (obj_desc->reference.
+ opcode))->name));
+
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
break;
-
default:
/* Invalid descriptor */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid descriptor %p [%s]\n",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid descriptor %p [%s]\n",
+ obj_desc,
+ acpi_ut_get_descriptor_name
+ (obj_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Get one argument type, point to the next */
- this_arg_type = GET_CURRENT_ARG_TYPE (arg_types);
- INCREMENT_ARG_LIST (arg_types);
+ this_arg_type = GET_CURRENT_ARG_TYPE(arg_types);
+ INCREMENT_ARG_LIST(arg_types);
/*
* Handle cases where the object does not need to be
* resolved to a value
*/
switch (this_arg_type) {
- case ARGI_REF_OR_STRING: /* Can be a String or Reference */
+ case ARGI_REF_OR_STRING: /* Can be a String or Reference */
- if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) {
+ if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_OBJECT_TYPE(obj_desc) ==
+ ACPI_TYPE_STRING)) {
/*
* String found - the string references a named object and
* must be resolved to a node
@@ -296,39 +293,40 @@ acpi_ex_resolve_operands (
*/
/*lint -fallthrough */
- case ARGI_REFERENCE: /* References: */
+ case ARGI_REFERENCE: /* References: */
case ARGI_INTEGER_REF:
case ARGI_OBJECT_REF:
case ARGI_DEVICE_REF:
- case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
- case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
- case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
+ case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
+ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
+ case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
/*
* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE
* A Namespace Node is OK as-is
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
goto next_operand;
}
- status = acpi_ex_check_object_type (ACPI_TYPE_LOCAL_REFERENCE,
- object_type, obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_check_object_type(ACPI_TYPE_LOCAL_REFERENCE,
+ object_type, obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (obj_desc->reference.opcode == AML_NAME_OP) {
/* Convert a named reference to the actual named object */
temp_node = obj_desc->reference.object;
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
(*stack_ptr) = temp_node;
}
goto next_operand;
-
- case ARGI_DATAREFOBJ: /* Store operator only */
+ case ARGI_DATAREFOBJ: /* Store operator only */
/*
* We don't want to resolve index_op reference objects during
@@ -337,8 +335,10 @@ acpi_ex_resolve_operands (
* -- All others must be resolved below.
*/
if ((opcode == AML_STORE_OP) &&
- (ACPI_GET_OBJECT_TYPE (*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) &&
- ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
+ (ACPI_GET_OBJECT_TYPE(*stack_ptr) ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && ((*stack_ptr)->reference.opcode ==
+ AML_INDEX_OP)) {
goto next_operand;
}
break;
@@ -351,9 +351,9 @@ acpi_ex_resolve_operands (
/*
* Resolve this object to a value
*/
- status = acpi_ex_resolve_to_value (stack_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_to_value(stack_ptr, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the resolved object */
@@ -364,10 +364,10 @@ acpi_ex_resolve_operands (
* Check the resulting object (value) type
*/
switch (this_arg_type) {
- /*
- * For the simple cases, only one type of resolved object
- * is allowed
- */
+ /*
+ * For the simple cases, only one type of resolved object
+ * is allowed
+ */
case ARGI_MUTEX:
/* Need an operand of type ACPI_TYPE_MUTEX */
@@ -382,7 +382,7 @@ acpi_ex_resolve_operands (
type_needed = ACPI_TYPE_EVENT;
break;
- case ARGI_PACKAGE: /* Package */
+ case ARGI_PACKAGE: /* Package */
/* Need an operand of type ACPI_TYPE_PACKAGE */
@@ -403,10 +403,9 @@ acpi_ex_resolve_operands (
type_needed = ACPI_TYPE_LOCAL_REFERENCE;
break;
-
- /*
- * The more complex cases allow multiple resolved object types
- */
+ /*
+ * The more complex cases allow multiple resolved object types
+ */
case ARGI_INTEGER:
/*
@@ -414,20 +413,26 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a STRING or BUFFER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_BUFFER:
@@ -436,20 +441,25 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a STRING or INTEGER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_STRING:
@@ -458,75 +468,86 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a BUFFER or INTEGER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_string (obj_desc, stack_ptr,
- ACPI_IMPLICIT_CONVERT_HEX);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_string(obj_desc, stack_ptr,
+ ACPI_IMPLICIT_CONVERT_HEX);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_COMPUTEDATA:
/* Need an operand of type INTEGER, STRING or BUFFER */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
- break;
+ break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_BUFFER_OR_STRING:
/* Need an operand of type STRING or BUFFER */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
- break;
+ break;
case ACPI_TYPE_INTEGER:
/* Highest priority conversion is to type Buffer */
- status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_convert_to_buffer(obj_desc,
+ stack_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
}
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_DATAOBJECT:
/*
* ARGI_DATAOBJECT is only used by the size_of operator.
@@ -535,7 +556,7 @@ acpi_ex_resolve_operands (
* The only reference allowed here is a direct reference to
* a namespace node.
*/
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -545,20 +566,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_COMPLEXOBJ:
/* Need a buffer or package or (ACPI 2.0) String */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -567,20 +588,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Buffer/String/Package], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_REGION_OR_FIELD:
/* Need an operand of type REGION or a FIELD in a region */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
@@ -590,20 +611,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Region/region_field], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Region/region_field], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_DATAREFOBJ:
/* Used by the Store() operator only */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
@@ -635,47 +656,46 @@ acpi_ex_resolve_operands (
break;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
default:
/* Unknown type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Internal - Unknown ARGI (required operand) type %X\n",
- this_arg_type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Internal - Unknown ARGI (required operand) type %X\n",
+ this_arg_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Make sure that the original object was resolved to the
* required object type (Simple cases only).
*/
- status = acpi_ex_check_object_type (type_needed,
- ACPI_GET_OBJECT_TYPE (*stack_ptr), *stack_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_check_object_type(type_needed,
+ ACPI_GET_OBJECT_TYPE
+ (*stack_ptr), *stack_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
-next_operand:
+ next_operand:
/*
* If more operands needed, decrement stack_ptr to point
* to next operand on stack
*/
- if (GET_CURRENT_ARG_TYPE (arg_types)) {
+ if (GET_CURRENT_ARG_TYPE(arg_types)) {
stack_ptr--;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 2725db0901b8..a7d8eea305c2 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
@@ -50,24 +49,18 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstore")
+ACPI_MODULE_NAME("exstore")
/* Local prototypes */
-
static void
-acpi_ex_do_debug_object (
- union acpi_operand_object *source_desc,
- u32 level,
- u32 index);
+acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ u32 level, u32 index);
static acpi_status
-acpi_ex_store_object_to_index (
- union acpi_operand_object *val_desc,
- union acpi_operand_object *dest_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
+ union acpi_operand_object *dest_desc,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -84,136 +77,146 @@ acpi_ex_store_object_to_index (
******************************************************************************/
static void
-acpi_ex_do_debug_object (
- union acpi_operand_object *source_desc,
- u32 level,
- u32 index)
+acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ u32 level, u32 index)
{
- u32 i;
-
+ 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, " "));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
+ level, " "));
/* Display index for package output only */
if (index > 0) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
- "(%.2u) ", index -1));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "(%.2u) ", index - 1));
}
if (!source_desc) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
return_VOID;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (source_desc) == ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s: ",
- acpi_ut_get_object_type_name (source_desc)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ",
+ acpi_ut_get_object_type_name
+ (source_desc)));
- if (!acpi_ut_valid_internal_object (source_desc)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
- "%p, Invalid Internal Object!\n", source_desc));
- return_VOID;
+ if (!acpi_ut_valid_internal_object(source_desc)) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "%p, Invalid Internal Object!\n",
+ source_desc));
+ return_VOID;
}
- }
- else if (ACPI_GET_DESCRIPTOR_TYPE (source_desc) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
- acpi_ut_get_type_name (((struct acpi_namespace_node *) source_desc)->type),
- source_desc));
+ } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
+ acpi_ut_get_type_name(((struct
+ acpi_namespace_node
+ *)source_desc)->
+ type),
+ source_desc));
return_VOID;
- }
- else {
+ } else {
return_VOID;
}
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
/* Output correct integer width */
if (acpi_gbl_integer_byte_width == 4) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
- (u32) source_desc->integer.value));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (source_desc->integer.value)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
+ (u32) source_desc->integer.
+ value));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "0x%8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(source_desc->
+ integer.
+ value)));
}
break;
case ACPI_TYPE_BUFFER:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]",
- (u32) source_desc->buffer.length));
- ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
- (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n",
+ (u32) source_desc->buffer.length));
+ ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
+ (source_desc->buffer.length <
+ 32) ? source_desc->buffer.length : 32);
break;
case ACPI_TYPE_STRING:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
- source_desc->string.length, source_desc->string.pointer));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
+ source_desc->string.length,
+ source_desc->string.pointer));
break;
case ACPI_TYPE_PACKAGE:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X Elements]\n",
- source_desc->package.count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "[0x%.2X Elements]\n",
+ source_desc->package.count));
/* Output the entire contents of the package */
for (i = 0; i < source_desc->package.count; i++) {
- acpi_ex_do_debug_object (source_desc->package.elements[i],
- level+4, i+1);
+ acpi_ex_do_debug_object(source_desc->package.
+ elements[i], level + 4, i + 1);
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
if (source_desc->reference.opcode == AML_INDEX_OP) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[%s, 0x%X]\n",
- acpi_ps_get_opcode_name (source_desc->reference.opcode),
- source_desc->reference.offset));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "[%s, 0x%X]\n",
+ acpi_ps_get_opcode_name
+ (source_desc->reference.opcode),
+ source_desc->reference.offset));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
+ acpi_ps_get_opcode_name
+ (source_desc->reference.opcode)));
}
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
- acpi_ps_get_opcode_name (source_desc->reference.opcode)));
- }
-
if (source_desc->reference.object) {
- if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) ==
- ACPI_DESC_TYPE_NAMED) {
- acpi_ex_do_debug_object (((struct acpi_namespace_node *)
- source_desc->reference.object)->object,
- level+4, 0);
+ if (ACPI_GET_DESCRIPTOR_TYPE
+ (source_desc->reference.object) ==
+ ACPI_DESC_TYPE_NAMED) {
+ acpi_ex_do_debug_object(((struct
+ acpi_namespace_node *)
+ source_desc->reference.
+ object)->object,
+ level + 4, 0);
+ } else {
+ acpi_ex_do_debug_object(source_desc->reference.
+ object, level + 4, 0);
}
- else {
- acpi_ex_do_debug_object (source_desc->reference.object, level+4, 0);
- }
- }
- else if (source_desc->reference.node) {
- acpi_ex_do_debug_object ((source_desc->reference.node)->object,
- level+4, 0);
+ } else if (source_desc->reference.node) {
+ acpi_ex_do_debug_object((source_desc->reference.node)->
+ object, level + 4, 0);
}
break;
default:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
- source_desc, acpi_ut_get_object_type_name (source_desc)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
+ source_desc,
+ acpi_ut_get_object_type_name
+ (source_desc)));
break;
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n"));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store
@@ -235,42 +238,41 @@ acpi_ex_do_debug_object (
******************************************************************************/
acpi_status
-acpi_ex_store (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *ref_desc = dest_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *ref_desc = dest_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc);
/* Validate parameters */
if (!source_desc || !dest_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null parameter\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/* dest_desc can be either a namespace node or an ACPI object */
- if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
/*
* Dest is a namespace node,
* Storing an object into a Named node.
*/
- status = acpi_ex_store_object_to_node (source_desc,
- (struct acpi_namespace_node *) dest_desc, walk_state,
- ACPI_IMPLICIT_CONVERSION);
+ status = acpi_ex_store_object_to_node(source_desc,
+ (struct
+ acpi_namespace_node *)
+ dest_desc, walk_state,
+ ACPI_IMPLICIT_CONVERSION);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Destination object must be a Reference or a Constant object */
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
break;
@@ -279,7 +281,7 @@ acpi_ex_store (
/* Allow stores to Constants -- a Noop as per ACPI spec */
if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*lint -fallthrough */
@@ -288,16 +290,18 @@ acpi_ex_store (
/* Destination is not a Reference object */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target is not a Reference or Constant object - %s [%p]\n",
- acpi_ut_get_object_type_name (dest_desc), dest_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target is not a Reference or Constant object - %s [%p]\n",
+ acpi_ut_get_object_type_name(dest_desc),
+ dest_desc));
- ACPI_DUMP_STACK_ENTRY (source_desc);
- ACPI_DUMP_STACK_ENTRY (dest_desc);
- ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
- 2, "Target is not a Reference or Constant object");
+ ACPI_DUMP_STACK_ENTRY(source_desc);
+ ACPI_DUMP_STACK_ENTRY(dest_desc);
+ ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
+ 2,
+ "Target is not a Reference or Constant object");
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -314,58 +318,59 @@ acpi_ex_store (
/* Storing an object into a Name "container" */
- status = acpi_ex_store_object_to_node (source_desc,
- ref_desc->reference.object,
- walk_state, ACPI_IMPLICIT_CONVERSION);
+ status = acpi_ex_store_object_to_node(source_desc,
+ ref_desc->reference.
+ object, walk_state,
+ ACPI_IMPLICIT_CONVERSION);
break;
-
case AML_INDEX_OP:
/* Storing to an Index (pointer into a packager or buffer) */
- status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state);
+ status =
+ acpi_ex_store_object_to_index(source_desc, ref_desc,
+ walk_state);
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
/* Store to a method local/arg */
- status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
- ref_desc->reference.offset, source_desc, walk_state);
+ status =
+ acpi_ds_store_object_to_local(ref_desc->reference.opcode,
+ ref_desc->reference.offset,
+ source_desc, walk_state);
break;
-
case AML_DEBUG_OP:
/*
* Storing to the Debug object causes the value stored to be
* displayed and otherwise has no effect -- see ACPI Specification
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "**** Write to Debug Object: Object %p %s ****:\n\n",
- source_desc, acpi_ut_get_object_type_name (source_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "**** Write to Debug Object: Object %p %s ****:\n\n",
+ source_desc,
+ acpi_ut_get_object_type_name(source_desc)));
- acpi_ex_do_debug_object (source_desc, 0, 0);
+ acpi_ex_do_debug_object(source_desc, 0, 0);
break;
-
default:
- ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
- ref_desc->reference.opcode));
- ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
+ ACPI_REPORT_ERROR(("ex_store: Unknown Reference opcode %X\n",
+ ref_desc->reference.opcode));
+ ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
status = AE_AML_INTERNAL;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_index
@@ -381,20 +386,17 @@ acpi_ex_store (
******************************************************************************/
static acpi_status
-acpi_ex_store_object_to_index (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *index_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
+ union acpi_operand_object *index_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *new_desc;
- u8 value = 0;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *new_desc;
+ u8 value = 0;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ex_store_object_to_index");
/*
* Destination must be a reference pointer, and
@@ -413,19 +415,20 @@ acpi_ex_store_object_to_index (
*/
obj_desc = *(index_desc->reference.where);
- status = acpi_ut_copy_iobject_to_iobject (source_desc, &new_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (obj_desc) {
/* Decrement reference count by the ref count of the parent package */
- for (i = 0;
- i < ((union acpi_operand_object *)
- index_desc->reference.object)->common.reference_count;
- i++) {
- acpi_ut_remove_reference (obj_desc);
+ for (i = 0; i < ((union acpi_operand_object *)
+ index_desc->reference.object)->common.
+ reference_count; i++) {
+ acpi_ut_remove_reference(obj_desc);
}
}
@@ -433,16 +436,14 @@ acpi_ex_store_object_to_index (
/* Increment ref count by the ref count of the parent package-1 */
- for (i = 1;
- i < ((union acpi_operand_object *)
- index_desc->reference.object)->common.reference_count;
- i++) {
- acpi_ut_add_reference (new_desc);
+ for (i = 1; i < ((union acpi_operand_object *)
+ index_desc->reference.object)->common.
+ reference_count; i++) {
+ acpi_ut_add_reference(new_desc);
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
/*
@@ -460,16 +461,16 @@ acpi_ex_store_object_to_index (
* by the INDEX_OP code.
*/
obj_desc = index_desc->reference.object;
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) &&
- (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_STRING)) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) &&
+ (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* The assignment of the individual elements will be slightly
* different for each source type.
*/
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
/* Use the least-significant byte of the integer */
@@ -489,10 +490,11 @@ acpi_ex_store_object_to_index (
/* All other types are invalid */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Source must be Integer/Buffer/String type, not %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Source must be Integer/Buffer/String type, not %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Store the source value into the target buffer byte */
@@ -500,18 +502,16 @@ acpi_ex_store_object_to_index (
obj_desc->buffer.pointer[index_desc->reference.offset] = value;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target is not a Package or buffer_field\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target is not a Package or buffer_field\n"));
status = AE_AML_OPERAND_TYPE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_node
@@ -539,42 +539,40 @@ acpi_ex_store_object_to_index (
******************************************************************************/
acpi_status
-acpi_ex_store_object_to_node (
- union acpi_operand_object *source_desc,
- struct acpi_namespace_node *node,
- struct acpi_walk_state *walk_state,
- u8 implicit_conversion)
+acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
+ struct acpi_namespace_node *node,
+ struct acpi_walk_state *walk_state,
+ u8 implicit_conversion)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *target_desc;
- union acpi_operand_object *new_desc;
- acpi_object_type target_type;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *target_desc;
+ union acpi_operand_object *new_desc;
+ acpi_object_type target_type;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc);
/* Get current type of the node, and object attached to Node */
- target_type = acpi_ns_get_type (node);
- target_desc = acpi_ns_get_attached_object (node);
+ target_type = acpi_ns_get_type(node);
+ target_desc = acpi_ns_get_attached_object(node);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
- source_desc, acpi_ut_get_object_type_name (source_desc),
- node, acpi_ut_get_type_name (target_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
+ source_desc,
+ acpi_ut_get_object_type_name(source_desc), node,
+ acpi_ut_get_type_name(target_type)));
/*
* Resolve the source object to an actual value
* (If it is a reference object)
*/
- status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* If no implicit conversion, drop into the default case below */
- if (!implicit_conversion) {
+ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
/* Force execution of default (no implicit conversion) */
target_type = ACPI_TYPE_ANY;
@@ -590,11 +588,10 @@ acpi_ex_store_object_to_node (
/* For fields, copy the source data to the target field. */
- status = acpi_ex_write_data_to_field (source_desc, target_desc,
- &walk_state->result_obj);
+ status = acpi_ex_write_data_to_field(source_desc, target_desc,
+ &walk_state->result_obj);
break;
-
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -605,10 +602,11 @@ acpi_ex_store_object_to_node (
*
* Copy and/or convert the source object to a new target object
*/
- status = acpi_ex_store_object_to_object (source_desc, target_desc,
- &new_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_store_object_to_object(source_desc, target_desc,
+ &new_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (new_desc != target_desc) {
@@ -621,30 +619,33 @@ acpi_ex_store_object_to_node (
* has been performed such that the node/object type has been
* changed.
*/
- status = acpi_ns_attach_object (node, new_desc, new_desc->common.type);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Store %s into %s via Convert/Attach\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_object_type_name (new_desc)));
+ status =
+ acpi_ns_attach_object(node, new_desc,
+ new_desc->common.type);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Store %s into %s via Convert/Attach\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_object_type_name
+ (new_desc)));
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Storing %s (%p) directly into node (%p), no implicit conversion\n",
- acpi_ut_get_object_type_name (source_desc), source_desc, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
+ acpi_ut_get_object_type_name(source_desc),
+ source_desc, node));
/* No conversions for all other types. Just attach the source object */
- status = acpi_ns_attach_object (node, source_desc,
- ACPI_GET_OBJECT_TYPE (source_desc));
+ status = acpi_ns_attach_object(node, source_desc,
+ ACPI_GET_OBJECT_TYPE
+ (source_desc));
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 120f30ed0bd4..382f63c14ea1 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -43,15 +43,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstoren")
-
+ACPI_MODULE_NAME("exstoren")
/*******************************************************************************
*
@@ -67,19 +64,15 @@
* it and return the actual object in the source_desc_ptr.
*
******************************************************************************/
-
acpi_status
-acpi_ex_resolve_object (
- union acpi_operand_object **source_desc_ptr,
- acpi_object_type target_type,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
+ acpi_object_type target_type,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *source_desc = *source_desc_ptr;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_object");
+ union acpi_operand_object *source_desc = *source_desc_ptr;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_resolve_object");
/* Ensure we have a Target that can be stored to */
@@ -102,11 +95,14 @@ acpi_ex_resolve_object (
* are all essentially the same. This case handles the
* "interchangeable" types Integer, String, and Buffer.
*/
- if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
+ if (ACPI_GET_OBJECT_TYPE(source_desc) ==
+ ACPI_TYPE_LOCAL_REFERENCE) {
/* Resolve a reference object first */
- status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(source_desc_ptr,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
}
@@ -119,31 +115,32 @@ acpi_ex_resolve_object (
/* Must have a Integer, Buffer, or String */
- if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) &&
- (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) &&
- (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) &&
- !((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) {
+ if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) &&
+ (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) &&
+ (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) &&
+ !((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_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_type_name (target_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_type_name(target_type)));
status = AE_AML_OPERAND_TYPE;
}
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
/* Aliases are resolved by acpi_ex_prep_operands */
- ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
+ ACPI_REPORT_ERROR(("Store into Alias - should never happen\n"));
status = AE_AML_INTERNAL;
break;
-
case ACPI_TYPE_PACKAGE:
default:
@@ -154,10 +151,9 @@ acpi_ex_resolve_object (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_object
@@ -194,18 +190,15 @@ acpi_ex_resolve_object (
******************************************************************************/
acpi_status
-acpi_ex_store_object_to_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc,
- union acpi_operand_object **new_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc,
+ union acpi_operand_object **new_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *actual_src_desc;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_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);
actual_src_desc = source_desc;
if (!dest_desc) {
@@ -214,11 +207,14 @@ acpi_ex_store_object_to_object (
* package element), so we can simply copy the source object
* creating a new destination object
*/
- status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc,
+ walk_state);
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ if (ACPI_GET_OBJECT_TYPE(source_desc) !=
+ ACPI_GET_OBJECT_TYPE(dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
@@ -228,10 +224,13 @@ acpi_ex_store_object_to_object (
* Otherwise, actual_src_desc is a temporary object to hold the
* converted object.
*/
- status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc),
- source_desc, &actual_src_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE
+ (dest_desc), source_desc,
+ &actual_src_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (source_desc == actual_src_desc) {
@@ -240,7 +239,7 @@ acpi_ex_store_object_to_object (
* new object.
*/
*new_desc = source_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -248,42 +247,42 @@ acpi_ex_store_object_to_object (
* We now have two objects of identical types, and we can perform a
* copy of the *value* of the source object.
*/
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
case ACPI_TYPE_INTEGER:
dest_desc->integer.value = actual_src_desc->integer.value;
/* Truncate value if we are executing from a 32-bit ACPI table */
- acpi_ex_truncate_for32bit_table (dest_desc);
+ acpi_ex_truncate_for32bit_table(dest_desc);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc);
+ status =
+ acpi_ex_store_string_to_string(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_BUFFER:
- /*
- * Note: There is different store behavior depending on the original
- * source type
- */
- status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
+ status =
+ acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_PACKAGE:
- status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc,
- walk_state);
+ status =
+ acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc,
+ walk_state);
break;
default:
/*
* All other types come here.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n",
- acpi_ut_get_object_type_name (dest_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Store into type %s not implemented\n",
+ acpi_ut_get_object_type_name(dest_desc)));
status = AE_NOT_IMPLEMENTED;
break;
@@ -292,11 +291,9 @@ acpi_ex_store_object_to_object (
if (actual_src_desc != source_desc) {
/* Delete the intermediate (temporary) source object */
- acpi_ut_remove_reference (actual_src_desc);
+ acpi_ut_remove_reference(actual_src_desc);
}
*new_desc = dest_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 12d1527669c8..c4ff654a6697 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstorob")
-
+ACPI_MODULE_NAME("exstorob")
/*******************************************************************************
*
@@ -63,18 +60,14 @@
* DESCRIPTION: Copy a buffer object to another buffer object.
*
******************************************************************************/
-
acpi_status
-acpi_ex_store_buffer_to_buffer (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc)
+acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc)
{
- u32 length;
- u8 *buffer;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
+ u32 length;
+ u8 *buffer;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc);
/* We know that source_desc is a buffer by now */
@@ -86,10 +79,10 @@ acpi_ex_store_buffer_to_buffer (
* allocate a new buffer of the proper length
*/
if ((target_desc->buffer.length == 0) ||
- (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
- target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length);
+ (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
+ target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length);
if (!target_desc->buffer.pointer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->buffer.length = length;
@@ -100,8 +93,9 @@ acpi_ex_store_buffer_to_buffer (
if (length <= target_desc->buffer.length) {
/* Clear existing buffer and copy in the new one */
- ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
- ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
+ ACPI_MEMSET(target_desc->buffer.pointer, 0,
+ target_desc->buffer.length);
+ ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length);
#ifdef ACPI_OBSOLETE_BEHAVIOR
/*
@@ -124,26 +118,24 @@ acpi_ex_store_buffer_to_buffer (
target_desc->buffer.length = length;
}
#endif
- }
- else {
+ } else {
/* Truncate the source, copy only what will fit */
- ACPI_MEMCPY (target_desc->buffer.pointer, buffer,
- target_desc->buffer.length);
+ ACPI_MEMCPY(target_desc->buffer.pointer, buffer,
+ target_desc->buffer.length);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Truncating source buffer from %X to %X\n",
- length, target_desc->buffer.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Truncating source buffer from %X to %X\n",
+ length, target_desc->buffer.length));
}
/* Copy flags */
target_desc->buffer.flags = source_desc->buffer.flags;
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_string_to_string
@@ -158,16 +150,13 @@ acpi_ex_store_buffer_to_buffer (
******************************************************************************/
acpi_status
-acpi_ex_store_string_to_string (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc)
+acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc)
{
- u32 length;
- u8 *buffer;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
+ u32 length;
+ u8 *buffer;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc);
/* We know that source_desc is a string by now */
@@ -179,41 +168,38 @@ acpi_ex_store_string_to_string (
* pointer is not a static pointer (part of an ACPI table)
*/
if ((length < target_desc->string.length) &&
- (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+ (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
/*
* String will fit in existing non-static buffer.
* Clear old string and copy in the new one
*/
- ACPI_MEMSET (target_desc->string.pointer, 0,
- (acpi_size) target_desc->string.length + 1);
- ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
- }
- else {
+ ACPI_MEMSET(target_desc->string.pointer, 0,
+ (acpi_size) target_desc->string.length + 1);
+ ACPI_MEMCPY(target_desc->string.pointer, buffer, length);
+ } else {
/*
* Free the current buffer, then allocate a new buffer
* large enough to hold the value
*/
if (target_desc->string.pointer &&
- (!(target_desc->common.flags & AOPOBJ_STATIC_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_MEM_FREE(target_desc->string.pointer);
}
- target_desc->string.pointer = ACPI_MEM_CALLOCATE (
- (acpi_size) length + 1);
+ target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size)
+ length + 1);
if (!target_desc->string.pointer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
+ ACPI_MEMCPY(target_desc->string.pointer, buffer, length);
}
/* Set the new target length */
target_desc->string.length = length;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index cafa702108dc..8a88b841237d 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -42,14 +42,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exsystem")
-
+ACPI_MODULE_NAME("exsystem")
/*******************************************************************************
*
@@ -65,49 +63,42 @@
* interpreter is released.
*
******************************************************************************/
-
-acpi_status
-acpi_ex_system_wait_semaphore (
- acpi_handle semaphore,
- u16 timeout)
+acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
{
- acpi_status status;
- acpi_status status2;
-
+ 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_wait_semaphore(semaphore, 1, 0);
+ if (ACPI_SUCCESS(status)) {
+ return_ACPI_STATUS(status);
}
if (status == AE_TIME) {
/* We must wait, so unlock the interpreter */
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- status = acpi_os_wait_semaphore (semaphore, 1, timeout);
+ status = acpi_os_wait_semaphore(semaphore, 1, timeout);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "*** Thread awake after blocking, %s\n",
- acpi_format_exception (status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "*** Thread awake after blocking, %s\n",
+ acpi_format_exception(status)));
/* Reacquire the interpreter */
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
/* Report fatal error, could not acquire interpreter */
- return_ACPI_STATUS (status2);
+ return_ACPI_STATUS(status2);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_stall
@@ -125,35 +116,29 @@ acpi_ex_system_wait_semaphore (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_do_stall (
- u32 how_long)
+acpi_status acpi_ex_system_do_stall(u32 how_long)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- if (how_long > 255) /* 255 microseconds */ {
+ if (how_long > 255) { /* 255 microseconds */
/*
* Longer than 255 usec, this is an error
*
* (ACPI specifies 100 usec as max, but this gives some slack in
* order to support existing BIOSs)
*/
- ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n",
- how_long));
+ ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n",
+ how_long));
status = AE_AML_OPERAND_VALUE;
- }
- else {
- acpi_os_stall (how_long);
+ } else {
+ acpi_os_stall(how_long);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_suspend
@@ -167,29 +152,24 @@ acpi_ex_system_do_stall (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_do_suspend (
- acpi_integer how_long)
+acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Since this thread will sleep, we must release the interpreter */
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- acpi_os_sleep (how_long);
+ acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
- status = acpi_ex_enter_interpreter ();
+ status = acpi_ex_enter_interpreter();
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_acquire_mutex
@@ -206,33 +186,30 @@ acpi_ex_system_do_suspend (
******************************************************************************/
acpi_status
-acpi_ex_system_acquire_mutex (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc)
+acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc,
+ union acpi_operand_object * obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_system_acquire_mutex", obj_desc);
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc);
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Support for the _GL_ Mutex object -- go get the global lock */
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
- status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_acquire_global_lock((u16) time_desc->integer.value);
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore,
- (u16) time_desc->integer.value);
- return_ACPI_STATUS (status);
+ status = acpi_ex_system_wait_semaphore(obj_desc->mutex.semaphore,
+ (u16) time_desc->integer.value);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_release_mutex
@@ -248,32 +225,27 @@ acpi_ex_system_acquire_mutex (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_release_mutex (
- union acpi_operand_object *obj_desc)
+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_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_release_mutex");
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Support for the _GL_ Mutex object -- release the global lock */
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
- status = acpi_ev_release_global_lock ();
- return_ACPI_STATUS (status);
+ status = acpi_ev_release_global_lock();
+ return_ACPI_STATUS(status);
}
- status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1);
- return_ACPI_STATUS (status);
+ status = acpi_os_signal_semaphore(obj_desc->mutex.semaphore, 1);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_signal_event
@@ -287,24 +259,19 @@ acpi_ex_system_release_mutex (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_signal_event (
- union acpi_operand_object *obj_desc)
+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_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_signal_event");
if (obj_desc) {
- status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1);
+ status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_wait_event
@@ -321,25 +288,23 @@ acpi_ex_system_signal_event (
******************************************************************************/
acpi_status
-acpi_ex_system_wait_event (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc)
+acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
+ union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_system_wait_event");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_wait_event");
if (obj_desc) {
- status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore,
- (u16) time_desc->integer.value);
+ status =
+ acpi_ex_system_wait_semaphore(obj_desc->event.semaphore,
+ (u16) time_desc->integer.
+ value);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_reset_event
@@ -352,27 +317,23 @@ acpi_ex_system_wait_event (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_reset_event (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
- void *temp_semaphore;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status = AE_OK;
+ void *temp_semaphore;
+ ACPI_FUNCTION_ENTRY();
/*
* We are going to simply delete the existing semaphore and
* create a new one!
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
- if (ACPI_SUCCESS (status)) {
- (void) acpi_os_delete_semaphore (obj_desc->event.semaphore);
+ status =
+ acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
+ if (ACPI_SUCCESS(status)) {
+ (void)acpi_os_delete_semaphore(obj_desc->event.semaphore);
obj_desc->event.semaphore = temp_semaphore;
}
return (status);
}
-
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 5c7ec0c04177..1ee79d8c8f88 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
/*
* DEFINE_AML_GLOBALS is tested in amlcode.h
* to determine whether certain global names should be "defined" or only
@@ -65,15 +64,10 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exutils")
+ACPI_MODULE_NAME("exutils")
/* Local prototypes */
-
-static u32
-acpi_ex_digits_needed (
- acpi_integer value,
- u32 base);
-
+static u32 acpi_ex_digits_needed(acpi_integer value, u32 base);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -89,24 +83,20 @@ acpi_ex_digits_needed (
*
******************************************************************************/
-acpi_status
-acpi_ex_enter_interpreter (
- void)
+acpi_status acpi_ex_enter_interpreter(void)
{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE ("ex_enter_interpreter");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_enter_interpreter");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n"));
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_exit_interpreter
@@ -129,25 +119,20 @@ acpi_ex_enter_interpreter (
*
******************************************************************************/
-void
-acpi_ex_exit_interpreter (
- void)
+void acpi_ex_exit_interpreter(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_exit_interpreter");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_exit_interpreter");
- status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not release interpreter mutex\n"));
+ status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not release interpreter mutex\n"));
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_truncate_for32bit_table
@@ -161,20 +146,17 @@ acpi_ex_exit_interpreter (
*
******************************************************************************/
-void
-acpi_ex_truncate_for32bit_table (
- union acpi_operand_object *obj_desc)
+void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/*
* Object must be a valid number and we must be executing
* a control method
*/
if ((!obj_desc) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
return;
}
@@ -187,7 +169,6 @@ acpi_ex_truncate_for32bit_table (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_global_lock
@@ -203,37 +184,31 @@ acpi_ex_truncate_for32bit_table (
*
******************************************************************************/
-u8
-acpi_ex_acquire_global_lock (
- u32 field_flags)
+u8 acpi_ex_acquire_global_lock(u32 field_flags)
{
- u8 locked = FALSE;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_acquire_global_lock");
+ u8 locked = FALSE;
+ acpi_status status;
+ 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);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
+ if (ACPI_SUCCESS(status)) {
locked = TRUE;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not acquire Global Lock, %s\n",
- acpi_format_exception (status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not acquire Global Lock, %s\n",
+ acpi_format_exception(status)));
}
}
- return_VALUE (locked);
+ return_VALUE(locked);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_global_lock
@@ -247,34 +222,28 @@ acpi_ex_acquire_global_lock (
*
******************************************************************************/
-void
-acpi_ex_release_global_lock (
- u8 locked_by_me)
+void acpi_ex_release_global_lock(u8 locked_by_me)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_release_global_lock");
+ acpi_status status;
+ 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)) {
+ status = acpi_ev_release_global_lock();
+ if (ACPI_FAILURE(status)) {
/* Report the error, but there isn't much else we can do */
- ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n",
- acpi_format_exception (status)));
+ ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status)));
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_digits_needed
@@ -289,22 +258,17 @@ acpi_ex_release_global_lock (
*
******************************************************************************/
-static u32
-acpi_ex_digits_needed (
- acpi_integer value,
- u32 base)
+static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
{
- u32 num_digits;
- acpi_integer current_value;
-
-
- ACPI_FUNCTION_TRACE ("ex_digits_needed");
+ u32 num_digits;
+ acpi_integer current_value;
+ ACPI_FUNCTION_TRACE("ex_digits_needed");
/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
if (value == 0) {
- return_VALUE (1);
+ return_VALUE(1);
}
current_value = value;
@@ -313,14 +277,14 @@ acpi_ex_digits_needed (
/* Count the digits in the requested base */
while (current_value) {
- (void) acpi_ut_short_divide (current_value, base, &current_value, NULL);
+ (void)acpi_ut_short_divide(current_value, base, &current_value,
+ NULL);
num_digits++;
}
- return_VALUE (num_digits);
+ return_VALUE(num_digits);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_eisa_id_to_string
@@ -334,32 +298,26 @@ acpi_ex_digits_needed (
*
******************************************************************************/
-void
-acpi_ex_eisa_id_to_string (
- u32 numeric_id,
- char *out_string)
+void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string)
{
- u32 eisa_id;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 eisa_id;
+ ACPI_FUNCTION_ENTRY();
/* Swap ID to big-endian to get contiguous bits */
- eisa_id = acpi_ut_dword_byte_swap (numeric_id);
+ eisa_id = acpi_ut_dword_byte_swap(numeric_id);
- out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f));
- out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f));
- out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f));
- out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12);
- out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8);
- out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4);
- out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0);
+ out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f));
+ out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f));
+ out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f));
+ out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12);
+ out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8);
+ out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4);
+ out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0);
out_string[7] = 0;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_unsigned_integer_to_string
@@ -369,30 +327,25 @@ acpi_ex_eisa_id_to_string (
*
* RETURN: None, string
*
- * DESCRIPTOIN: Convert a number to string representation. Assumes string
+ * DESCRIPTION: Convert a number to string representation. Assumes string
* buffer is large enough to hold the string.
*
******************************************************************************/
-void
-acpi_ex_unsigned_integer_to_string (
- acpi_integer value,
- char *out_string)
+void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string)
{
- u32 count;
- u32 digits_needed;
- u32 remainder;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 count;
+ u32 digits_needed;
+ u32 remainder;
+ ACPI_FUNCTION_ENTRY();
- digits_needed = acpi_ex_digits_needed (value, 10);
+ digits_needed = acpi_ex_digits_needed(value, 10);
out_string[digits_needed] = 0;
for (count = digits_needed; count > 0; count--) {
- (void) acpi_ut_short_divide (value, 10, &value, &remainder);
- out_string[count-1] = (char) ('0' + remainder);\
+ (void)acpi_ut_short_divide(value, 10, &value, &remainder);
+ out_string[count - 1] = (char)('0' + remainder);
}
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 14192ee55f8f..e8165c4f162a 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -34,52 +34,45 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_FAN_COMPONENT 0x00200000
#define ACPI_FAN_CLASS "fan"
-#define ACPI_FAN_HID "PNP0C0B"
#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver"
-#define ACPI_FAN_DEVICE_NAME "Fan"
#define ACPI_FAN_FILE_STATE "state"
-#define ACPI_FAN_NOTIFY_STATUS 0x80
#define _COMPONENT ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME ("acpi_fan")
+ACPI_MODULE_NAME("acpi_fan")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_fan_add (struct acpi_device *device);
-static int acpi_fan_remove (struct acpi_device *device, int type);
+static int acpi_fan_add(struct acpi_device *device);
+static int acpi_fan_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
- .name = ACPI_FAN_DRIVER_NAME,
- .class = ACPI_FAN_CLASS,
- .ids = ACPI_FAN_HID,
- .ops = {
- .add = acpi_fan_add,
- .remove = acpi_fan_remove,
- },
+ .name = ACPI_FAN_DRIVER_NAME,
+ .class = ACPI_FAN_CLASS,
+ .ids = "PNP0C0B",
+ .ops = {
+ .add = acpi_fan_add,
+ .remove = acpi_fan_remove,
+ },
};
struct acpi_fan {
- acpi_handle handle;
+ acpi_handle handle;
};
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_fan_dir;
+static struct proc_dir_entry *acpi_fan_dir;
-
-static int
-acpi_fan_read_state (struct seq_file *seq, void *offset)
+static int acpi_fan_read_state(struct seq_file *seq, void *offset)
{
- struct acpi_fan *fan = seq->private;
- int state = 0;
+ struct acpi_fan *fan = seq->private;
+ int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_read_state");
@@ -88,7 +81,7 @@ acpi_fan_read_state (struct seq_file *seq, void *offset)
seq_printf(seq, "status: ERROR\n");
else
seq_printf(seq, "status: %s\n",
- !state?"on":"off");
+ !state ? "on" : "off");
}
return_VALUE(0);
}
@@ -99,29 +92,26 @@ static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_fan_write_state (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_fan_write_state(struct file *file, const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_fan *fan = (struct acpi_fan *) m->private;
- char state_string[12] = {'\0'};
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_fan *fan = (struct acpi_fan *)m->private;
+ char state_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_fan_write_state");
if (!fan || (count > sizeof(state_string) - 1))
return_VALUE(-EINVAL);
-
+
if (copy_from_user(state_string, buffer, count))
return_VALUE(-EFAULT);
-
+
state_string[count] = '\0';
-
- result = acpi_bus_set_power(fan->handle,
- simple_strtoul(state_string, NULL, 0));
+
+ result = acpi_bus_set_power(fan->handle,
+ simple_strtoul(state_string, NULL, 0));
if (result)
return_VALUE(result);
@@ -129,19 +119,17 @@ acpi_fan_write_state (
}
static struct file_operations acpi_fan_state_ops = {
- .open = acpi_fan_state_open_fs,
- .read = seq_read,
- .write = acpi_fan_write_state,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_fan_state_open_fs,
+ .read = seq_read,
+ .write = acpi_fan_write_state,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_fan_add_fs (
- struct acpi_device *device)
+static int acpi_fan_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_add_fs");
@@ -150,7 +138,7 @@ acpi_fan_add_fs (
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_fan_dir);
+ acpi_fan_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -158,11 +146,12 @@ acpi_fan_add_fs (
/* 'status' [R/W] */
entry = create_proc_entry(ACPI_FAN_FILE_STATE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_FAN_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_FAN_FILE_STATE));
else {
entry->proc_fops = &acpi_fan_state_ops;
entry->data = acpi_driver_data(device);
@@ -172,16 +161,12 @@ acpi_fan_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_fan_remove_fs (
- struct acpi_device *device)
+static int acpi_fan_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_FAN_FILE_STATE,
- acpi_device_dir(device));
+ remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
acpi_device_dir(device) = NULL;
}
@@ -189,18 +174,15 @@ acpi_fan_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_fan_add (
- struct acpi_device *device)
+static int acpi_fan_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_fan *fan = NULL;
- int state = 0;
+ int result = 0;
+ struct acpi_fan *fan = NULL;
+ int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_add");
@@ -213,14 +195,14 @@ acpi_fan_add (
memset(fan, 0, sizeof(struct acpi_fan));
fan->handle = device->handle;
- strcpy(acpi_device_name(device), ACPI_FAN_DEVICE_NAME);
+ strcpy(acpi_device_name(device), "Fan");
strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
acpi_driver_data(device) = fan;
result = acpi_bus_get_power(fan->handle, &state);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading power state\n"));
+ "Error reading power state\n"));
goto end;
}
@@ -229,30 +211,26 @@ acpi_fan_add (
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
- acpi_device_name(device), acpi_device_bid(device),
- !device->power.state?"on":"off");
+ acpi_device_name(device), acpi_device_bid(device),
+ !device->power.state ? "on" : "off");
-end:
+ end:
if (result)
kfree(fan);
return_VALUE(result);
}
-
-static int
-acpi_fan_remove (
- struct acpi_device *device,
- int type)
+static int acpi_fan_remove(struct acpi_device *device, int type)
{
- struct acpi_fan *fan = NULL;
+ struct acpi_fan *fan = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- fan = (struct acpi_fan *) acpi_driver_data(device);
+ fan = (struct acpi_fan *)acpi_driver_data(device);
acpi_fan_remove_fs(device);
@@ -261,11 +239,9 @@ acpi_fan_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_fan_init (void)
+static int __init acpi_fan_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_fan_init");
@@ -283,9 +259,7 @@ acpi_fan_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_fan_exit (void)
+static void __exit acpi_fan_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_fan_exit");
@@ -296,7 +270,5 @@ acpi_fan_exit (void)
return_VOID;
}
-
module_init(acpi_fan_init);
module_exit(acpi_fan_exit);
-
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 770cfc8b17e0..e36c5da2b31a 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -29,7 +29,8 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "bus type %s registered\n", type->bus->name);
+ printk(KERN_INFO PREFIX "bus type %s registered\n",
+ type->bus->name);
return 0;
}
return -ENODEV;
@@ -45,7 +46,8 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_del_init(&type->list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", type->bus->name);
+ printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
+ type->bus->name);
return 0;
}
return -ENODEV;
@@ -168,9 +170,6 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &seg);
if (status == AE_NOT_FOUND) {
/* Assume seg = 0 */
- printk(KERN_INFO PREFIX
- "Assume root bridge [%s] segment is 0\n",
- (char *)buffer.pointer);
status = AE_OK;
seg = 0;
}
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index b51001e74eea..1bb3463d7040 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -42,13 +42,10 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwacpi")
-
+ACPI_MODULE_NAME("hwacpi")
/******************************************************************************
*
@@ -62,36 +59,30 @@
* the FADT.
*
******************************************************************************/
-
-acpi_status
-acpi_hw_initialize (
- void)
+acpi_status acpi_hw_initialize(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_initialize");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("hw_initialize");
/* We must have the ACPI tables by the time we get here */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT is present\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No FADT is present\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Sanity check the FADT for valid values */
- status = acpi_ut_validate_fadt ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_fadt();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_set_mode
@@ -104,24 +95,21 @@ acpi_hw_initialize (
*
******************************************************************************/
-acpi_status
-acpi_hw_set_mode (
- u32 mode)
+acpi_status acpi_hw_set_mode(u32 mode)
{
- acpi_status status;
- u32 retry;
-
+ 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,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- ACPI_REPORT_ERROR (("No SMI_CMD in FADT, mode transition failed.\n"));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_REPORT_ERROR(("No SMI_CMD in FADT, mode transition failed.\n"));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
/*
@@ -132,9 +120,8 @@ acpi_hw_set_mode (
* transitions are not supported.
*/
if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
- ACPI_REPORT_ERROR ((
- "No ACPI mode transition supported in this system (enable/disable both zero)\n"));
- return_ACPI_STATUS (AE_OK);
+ ACPI_REPORT_ERROR(("No ACPI mode transition supported in this system (enable/disable both zero)\n"));
+ return_ACPI_STATUS(AE_OK);
}
switch (mode) {
@@ -142,9 +129,11 @@ acpi_hw_set_mode (
/* BIOS should have disabled ALL fixed and GP events */
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->acpi_enable, 8);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->acpi_enable,
+ 8);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Attempting to enable ACPI mode\n"));
break;
case ACPI_SYS_MODE_LEGACY:
@@ -153,20 +142,21 @@ acpi_hw_set_mode (
* BIOS should clear all fixed status bits and restore fixed event
* enable bits to default
*/
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->acpi_disable, 8);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Attempting to enable Legacy (non-ACPI) mode\n"));
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->acpi_disable,
+ 8);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Attempting to enable Legacy (non-ACPI) mode\n"));
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not write mode change, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not write mode change, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
@@ -176,19 +166,19 @@ acpi_hw_set_mode (
retry = 3000;
while (retry) {
if (acpi_hw_get_mode() == mode) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
- mode));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Mode %X successfully enabled\n",
+ mode));
+ return_ACPI_STATUS(AE_OK);
}
acpi_os_stall(1000);
retry--;
}
- ACPI_REPORT_ERROR (("Hardware never changed modes\n"));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_REPORT_ERROR(("Hardware never changed modes\n"));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_mode
@@ -202,34 +192,30 @@ acpi_hw_set_mode (
*
******************************************************************************/
-u32
-acpi_hw_get_mode (
- void)
+u32 acpi_hw_get_mode(void)
{
- acpi_status status;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("hw_get_mode");
+ acpi_status status;
+ u32 value;
+ ACPI_FUNCTION_TRACE("hw_get_mode");
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- return_VALUE (ACPI_SYS_MODE_ACPI);
+ return_VALUE(ACPI_SYS_MODE_ACPI);
}
- status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_VALUE (ACPI_SYS_MODE_LEGACY);
+ status =
+ acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_VALUE(ACPI_SYS_MODE_LEGACY);
}
if (value) {
- return_VALUE (ACPI_SYS_MODE_ACPI);
- }
- else {
- return_VALUE (ACPI_SYS_MODE_LEGACY);
+ return_VALUE(ACPI_SYS_MODE_ACPI);
+ } else {
+ return_VALUE(ACPI_SYS_MODE_LEGACY);
}
}
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 8daeabb2fc7a..5c8e5dfd024e 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -46,15 +46,12 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwgpe")
+ACPI_MODULE_NAME("hwgpe")
/* Local prototypes */
-
static acpi_status
-acpi_hw_enable_wakeup_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
-
+acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
/******************************************************************************
*
@@ -71,15 +68,12 @@ acpi_hw_enable_wakeup_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_write_gpe_enable_reg (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info)
{
- struct acpi_gpe_register_info *gpe_register_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_gpe_register_info *gpe_register_info;
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
@@ -90,13 +84,12 @@ acpi_hw_write_gpe_enable_reg (
/* Write the entire GPE (runtime) enable register */
- status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
+ status = acpi_hw_low_level_write(8, gpe_register_info->enable_for_run,
+ &gpe_register_info->enable_address);
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe
@@ -109,27 +102,23 @@ acpi_hw_write_gpe_enable_reg (
*
******************************************************************************/
-acpi_status
-acpi_hw_clear_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
- status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
- &gpe_event_info->register_info->status_address);
+ status = acpi_hw_low_level_write(8, gpe_event_info->register_bit,
+ &gpe_event_info->register_info->
+ status_address);
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_get_gpe_status
@@ -145,19 +134,16 @@ acpi_hw_clear_gpe (
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_hw_get_gpe_status (
- struct acpi_gpe_event_info *gpe_event_info,
- acpi_event_status *event_status)
+acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
+ acpi_event_status * event_status)
{
- u32 in_byte;
- u8 register_bit;
- struct acpi_gpe_register_info *gpe_register_info;
- acpi_status status;
- acpi_event_status local_event_status = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 in_byte;
+ u8 register_bit;
+ struct acpi_gpe_register_info *gpe_register_info;
+ acpi_status status;
+ acpi_event_status local_event_status = 0;
+ ACPI_FUNCTION_ENTRY();
if (!event_status) {
return (AE_BAD_PARAMETER);
@@ -185,8 +171,10 @@ acpi_hw_get_gpe_status (
/* GPE currently active (status bit == 1)? */
- status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(8, &in_byte,
+ &gpe_register_info->status_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -198,12 +186,10 @@ acpi_hw_get_gpe_status (
(*event_status) = local_event_status;
-
-unlock_and_exit:
+ unlock_and_exit:
return (status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/******************************************************************************
*
@@ -219,22 +205,21 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_hw_disable_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* 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,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8, 0x00,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -242,7 +227,6 @@ acpi_hw_disable_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe_block
@@ -257,22 +241,21 @@ acpi_hw_disable_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_clear_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* 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,
- &gpe_block->register_info[i].status_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8, 0xFF,
+ &gpe_block->register_info[i].
+ status_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -280,7 +263,6 @@ acpi_hw_clear_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_runtime_gpe_block
@@ -296,13 +278,11 @@ acpi_hw_clear_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_enable_runtime_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* NOTE: assumes that all GPEs are currently disabled */
@@ -315,9 +295,13 @@ acpi_hw_enable_runtime_gpe_block (
/* Enable all "runtime" GPEs in this register */
- status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(8,
+ gpe_block->register_info[i].
+ enable_for_run,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -325,7 +309,6 @@ acpi_hw_enable_runtime_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_wakeup_gpe_block
@@ -341,13 +324,11 @@ acpi_hw_enable_runtime_gpe_block (
******************************************************************************/
static acpi_status
-acpi_hw_enable_wakeup_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* Examine each GPE Register within the block */
@@ -358,10 +339,12 @@ acpi_hw_enable_wakeup_gpe_block (
/* Enable all "wake" GPEs in this register */
- status = acpi_hw_low_level_write (8,
- gpe_block->register_info[i].enable_for_wake,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8,
+ gpe_block->register_info[i].
+ enable_for_wake,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -369,12 +352,11 @@ acpi_hw_enable_wakeup_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_all_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -382,27 +364,22 @@ acpi_hw_enable_wakeup_gpe_block (
*
******************************************************************************/
-acpi_status
-acpi_hw_disable_all_gpes (
- u32 flags)
+acpi_status acpi_hw_disable_all_gpes(void)
{
- acpi_status status;
-
+ 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, flags);
- status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
- return_ACPI_STATUS (status);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_runtime_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -410,26 +387,21 @@ acpi_hw_disable_all_gpes (
*
******************************************************************************/
-acpi_status
-acpi_hw_enable_all_runtime_gpes (
- u32 flags)
+acpi_status acpi_hw_enable_all_runtime_gpes(void)
{
- acpi_status status;
-
+ 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, flags);
- return_ACPI_STATUS (status);
+ status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_wakeup_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -437,17 +409,12 @@ acpi_hw_enable_all_runtime_gpes (
*
******************************************************************************/
-acpi_status
-acpi_hw_enable_all_wakeup_gpes (
- u32 flags)
+acpi_status acpi_hw_enable_all_wakeup_gpes(void)
{
- acpi_status status;
-
+ 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, flags);
- return_ACPI_STATUS (status);
+ 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 6d9e4eb84836..536a7aea80c9 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -50,8 +50,7 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwregs")
-
+ACPI_MODULE_NAME("hwregs")
/*******************************************************************************
*
@@ -65,57 +64,52 @@
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
-
-acpi_status
-acpi_hw_clear_acpi_status (
- u32 flags)
+acpi_status acpi_hw_clear_acpi_status(u32 flags)
{
- acpi_status status;
-
+ acpi_status status;
- 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));
+ 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);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS,
- ACPI_BITMASK_ALL_FIXED_STATUS);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITMASK_ALL_FIXED_STATUS);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Clear the fixed events */
if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
- status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS,
- &acpi_gbl_FADT->xpm1b_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
/* Clear the GPE Bits in all GPE registers in all GPE blocks */
- status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_sleep_type_data
@@ -132,53 +126,48 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_get_sleep_type_data (
- u8 sleep_state,
- u8 *sleep_type_a,
- u8 *sleep_type_b)
+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;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
+ acpi_status status = AE_OK;
+ struct acpi_parameter_info info;
+ char *sleep_state_name;
+ ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data");
/* Validate parameters */
- if ((sleep_state > ACPI_S_STATES_MAX) ||
- !sleep_type_a || !sleep_type_b) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Evaluate the namespace object containing the values for this state */
info.parameters = NULL;
info.return_object = NULL;
- sleep_state_name = (char *) acpi_gbl_sleep_state_names[sleep_state];
+ sleep_state_name = (char *)acpi_gbl_sleep_state_names[sleep_state];
- status = acpi_ns_evaluate_by_name (sleep_state_name, &info);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s while evaluating sleep_state [%s]\n",
- acpi_format_exception (status), sleep_state_name));
+ status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%s while evaluating sleep_state [%s]\n",
+ acpi_format_exception(status),
+ sleep_state_name));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Must have a return object */
if (!info.return_object) {
- ACPI_REPORT_ERROR (("No Sleep State object returned from [%s]\n",
- sleep_state_name));
+ ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n",
+ sleep_state_name));
status = AE_NOT_EXIST;
}
/* It must be of type Package */
- else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
- ACPI_REPORT_ERROR (("Sleep State return object is not a Package\n"));
+ else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
+ ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n"));
status = AE_AML_OPERAND_TYPE;
}
@@ -190,45 +179,41 @@ acpi_get_sleep_type_data (
* one per sleep type (A/B).
*/
else if (info.return_object->package.count < 2) {
- ACPI_REPORT_ERROR ((
- "Sleep State return package does not have at least two elements\n"));
+ ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n"));
status = AE_AML_NO_OPERAND;
}
/* The first two elements must both be of type Integer */
- 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_TYPE_INTEGER)) {
- ACPI_REPORT_ERROR ((
- "Sleep State return package elements are not both Integers (%s, %s)\n",
- acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
- acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
+ 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_TYPE_INTEGER)) {
+ ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1])));
status = AE_AML_OPERAND_TYPE;
- }
- else {
+ } 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_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
- acpi_format_exception (status),
- sleep_state_name, info.return_object,
- acpi_ut_get_object_type_name (info.return_object)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+ acpi_format_exception(status),
+ sleep_state_name, info.return_object,
+ acpi_ut_get_object_type_name(info.
+ return_object)));
}
- acpi_ut_remove_reference (info.return_object);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(info.return_object);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_sleep_type_data);
+EXPORT_SYMBOL(acpi_get_sleep_type_data);
/*******************************************************************************
*
@@ -242,22 +227,20 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data);
*
******************************************************************************/
-struct acpi_bit_register_info *
-acpi_hw_get_bit_register_info (
- u32 register_id)
+struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
{
- ACPI_FUNCTION_NAME ("hw_get_bit_register_info");
-
+ ACPI_FUNCTION_NAME("hw_get_bit_register_info");
if (register_id > ACPI_BITREG_MAX) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid bit_register ID: %X\n", register_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid bit_register ID: %X\n",
+ register_id));
return (NULL);
}
return (&acpi_gbl_bit_register_info[register_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_register
@@ -273,59 +256,56 @@ acpi_hw_get_bit_register_info (
*
******************************************************************************/
-acpi_status
-acpi_get_register (
- u32 register_id,
- u32 *return_value,
- u32 flags)
+acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
{
- u32 register_value = 0;
- struct acpi_bit_register_info *bit_reg_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_register");
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_register");
/* Get the info structure corresponding to the requested ACPI Register */
- bit_reg_info = acpi_hw_get_bit_register_info (register_id);
+ bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ 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);
+ 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,
- bit_reg_info->parent_register, &register_value);
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register,
+ &register_value);
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Normalize the value that was read */
- register_value = ((register_value & bit_reg_info->access_bit_mask)
- >> bit_reg_info->bit_position);
+ register_value =
+ ((register_value & bit_reg_info->access_bit_mask)
+ >> bit_reg_info->bit_position);
*return_value = register_value;
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
- register_value, bit_reg_info->parent_register));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n",
+ register_value,
+ bit_reg_info->parent_register));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_register);
+EXPORT_SYMBOL(acpi_get_register);
/*******************************************************************************
*
@@ -342,40 +322,36 @@ EXPORT_SYMBOL(acpi_get_register);
*
******************************************************************************/
-acpi_status
-acpi_set_register (
- u32 register_id,
- u32 value,
- u32 flags)
+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_FUNCTION_TRACE_U32 ("acpi_set_register", register_id);
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
+ 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);
+ bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- ACPI_REPORT_ERROR (("Bad ACPI HW register_id: %X\n", register_id));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n",
+ 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);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Always do a register read first so we can insert the new bits */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- bit_reg_info->parent_register, &register_value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register,
+ &register_value);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -395,26 +371,30 @@ acpi_set_register (
* information is the single bit we're interested in, all others should
* be written as 0 so they will be left unchanged.
*/
- value = ACPI_REGISTER_PREPARE_BITS (value,
- bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
+ value = ACPI_REGISTER_PREPARE_BITS(value,
+ bit_reg_info->bit_position,
+ bit_reg_info->
+ access_bit_mask);
if (value) {
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS, (u16) value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS,
+ (u16) value);
register_value = 0;
}
break;
-
case ACPI_REGISTER_PM1_ENABLE:
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_ENABLE, (u16) register_value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_ENABLE,
+ (u16) register_value);
break;
-
case ACPI_REGISTER_PM1_CONTROL:
/*
@@ -422,65 +402,73 @@ acpi_set_register (
* Note that at this level, the fact that there are actually TWO
* registers (A and B - and B may not exist) is abstracted.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n",
+ register_value));
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, (u16) register_value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ (u16) register_value);
break;
-
case ACPI_REGISTER_PM2_CONTROL:
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL, &register_value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL,
+ &register_value);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
- register_value,
- ACPI_FORMAT_UINT64 (
- acpi_gbl_FADT->xpm2_cnt_blk.address)));
-
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
- register_value,
- ACPI_FORMAT_UINT64 (
- acpi_gbl_FADT->xpm2_cnt_blk.address)));
-
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL, (u8) (register_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "PM2 control: Read %X from %8.8X%8.8X\n",
+ register_value,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT->
+ xpm2_cnt_blk.address)));
+
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "About to write %4.4X to %8.8X%8.8X\n",
+ register_value,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT->
+ xpm2_cnt_blk.address)));
+
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL,
+ (u8) (register_value));
break;
-
default:
break;
}
-
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
/* Normalize the value that was read */
- ACPI_DEBUG_EXEC (register_value =
- ((register_value & bit_reg_info->access_bit_mask) >>
- bit_reg_info->bit_position));
+ ACPI_DEBUG_EXEC(register_value =
+ ((register_value & bit_reg_info->access_bit_mask) >>
+ bit_reg_info->bit_position));
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
- value, register_value, bit_reg_info->parent_register));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Set bits: %8.8X actual %8.8X register %X\n", value,
+ register_value, bit_reg_info->parent_register));
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_register);
+EXPORT_SYMBOL(acpi_set_register);
/******************************************************************************
*
@@ -498,103 +486,107 @@ EXPORT_SYMBOL(acpi_set_register);
******************************************************************************/
acpi_status
-acpi_hw_register_read (
- u8 use_lock,
- u32 register_id,
- u32 *return_value)
+acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
{
- u32 value1 = 0;
- u32 value2 = 0;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_register_read");
+ u32 value1 = 0;
+ u32 value2 = 0;
+ acpi_status status;
+ 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);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1,
+ &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk);
+ status =
+ acpi_hw_low_level_read(16, &value2,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
-
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable);
+ status =
+ acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_read(16, &value2,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk);
+ status =
+ acpi_hw_low_level_read(8, &value1,
+ &acpi_gbl_FADT->xpm2_cnt_blk);
break;
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk);
+ status =
+ acpi_hw_low_level_read(32, &value1,
+ &acpi_gbl_FADT->xpm_tmr_blk);
break;
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
- status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8);
+ status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8);
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
- register_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
+ register_id));
status = AE_BAD_PARAMETER;
break;
}
-unlock_and_exit:
+ unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
*return_value = value1;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_register_write
@@ -610,109 +602,112 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_hw_register_write (
- u8 use_lock,
- u32 register_id,
- u32 value)
+acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_register_write");
+ acpi_status status;
+ 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);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable);
+ status =
+ acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
break;
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
+ case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
break;
+ case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk);
+ status =
+ acpi_hw_low_level_write(8, value,
+ &acpi_gbl_FADT->xpm2_cnt_blk);
break;
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk);
+ status =
+ acpi_hw_low_level_write(32, value,
+ &acpi_gbl_FADT->xpm_tmr_blk);
break;
-
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
/* SMI_CMD is currently always in IO space */
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8);
break;
-
default:
status = AE_BAD_PARAMETER;
break;
}
-unlock_and_exit:
+ unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_low_level_read
@@ -728,17 +723,12 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_hw_low_level_read (
- u32 width,
- u32 *value,
- struct acpi_generic_address *reg)
+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");
+ u64 address;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("hw_low_level_read");
/*
* Must have a valid pointer to a GAS structure, and
@@ -751,7 +741,7 @@ acpi_hw_low_level_read (
/* Get a local copy of the address. Handles possible alignment issues */
- ACPI_MOVE_64_TO_64 (&address, &reg->address);
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_OK);
}
@@ -764,35 +754,32 @@ acpi_hw_low_level_read (
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_read_memory (
- (acpi_physical_address) address,
- value, width);
+ status = acpi_os_read_memory((acpi_physical_address) address,
+ value, width);
break;
-
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_read_port ((acpi_io_address) address,
- value, width);
+ status = acpi_os_read_port((acpi_io_address) address,
+ value, width);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported address space: %X\n", reg->address_space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO,
- "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
- *value, width,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (reg->address_space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
+ *value, width,
+ ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->address_space_id)));
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_low_level_write
@@ -808,17 +795,12 @@ acpi_hw_low_level_read (
******************************************************************************/
acpi_status
-acpi_hw_low_level_write (
- u32 width,
- u32 value,
- struct acpi_generic_address *reg)
+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");
+ u64 address;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("hw_low_level_write");
/*
* Must have a valid pointer to a GAS structure, and
@@ -831,7 +813,7 @@ acpi_hw_low_level_write (
/* Get a local copy of the address. Handles possible alignment issues */
- ACPI_MOVE_64_TO_64 (&address, &reg->address);
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_OK);
}
@@ -843,30 +825,28 @@ acpi_hw_low_level_write (
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_write_memory (
- (acpi_physical_address) address,
- value, width);
+ status = acpi_os_write_memory((acpi_physical_address) address,
+ value, width);
break;
-
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_write_port ((acpi_io_address) address,
- value, width);
+ status = acpi_os_write_port((acpi_io_address) address,
+ value, width);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported address space: %X\n", reg->address_space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO,
- "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
- value, width,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (reg->address_space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
+ value, width,
+ ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->address_space_id)));
return (status);
}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 415d342aeab5..34519069050c 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -46,8 +46,7 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwsleep")
-
+ACPI_MODULE_NAME("hwsleep")
/*******************************************************************************
*
@@ -61,30 +60,25 @@
* DESCRIPTION: Access function for the firmware_waking_vector field in FACS
*
******************************************************************************/
-
acpi_status
-acpi_set_firmware_waking_vector (
- acpi_physical_address physical_address)
+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 */
if (acpi_gbl_common_fACS.vector_width == 32) {
- *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector))
- = (u32) physical_address;
- }
- else {
- *acpi_gbl_common_fACS.firmware_waking_vector
- = physical_address;
+ *(ACPI_CAST_PTR
+ (u32, acpi_gbl_common_fACS.firmware_waking_vector))
+ = (u32) physical_address;
+ } else {
+ *acpi_gbl_common_fACS.firmware_waking_vector = physical_address;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_waking_vector
@@ -101,33 +95,31 @@ acpi_set_firmware_waking_vector (
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_firmware_waking_vector (
- acpi_physical_address *physical_address)
+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);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the vector */
if (acpi_gbl_common_fACS.vector_width == 32) {
*physical_address = (acpi_physical_address)
- *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector));
- }
- else {
+ *
+ (ACPI_CAST_PTR
+ (u32, acpi_gbl_common_fACS.firmware_waking_vector));
+ } else {
*physical_address =
- *acpi_gbl_common_fACS.firmware_waking_vector;
+ *acpi_gbl_common_fACS.firmware_waking_vector;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_prep
@@ -143,25 +135,22 @@ acpi_get_firmware_waking_vector (
*
******************************************************************************/
-acpi_status
-acpi_enter_sleep_state_prep (
- u8 sleep_state)
+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_status status;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep");
/*
* _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
*/
- status = acpi_get_sleep_type_data (sleep_state,
- &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_sleep_type_data(sleep_state,
+ &acpi_gbl_sleep_type_a,
+ &acpi_gbl_sleep_type_b);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Setup parameter object */
@@ -174,14 +163,14 @@ acpi_enter_sleep_state_prep (
/* Run the _PTS and _GTS methods */
- status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
}
- status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
}
/* Setup the argument to _SST */
@@ -202,22 +191,21 @@ acpi_enter_sleep_state_prep (
break;
default:
- arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */
+ arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */
break;
}
/* Set the system indicators to show the desired sleep state. */
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state
@@ -231,80 +219,82 @@ acpi_enter_sleep_state_prep (
*
******************************************************************************/
-acpi_status asmlinkage
-acpi_enter_sleep_state (
- u8 sleep_state)
+acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
- u32 PM1Acontrol;
- u32 PM1Bcontrol;
- struct acpi_bit_register_info *sleep_type_reg_info;
- struct acpi_bit_register_info *sleep_enable_reg_info;
- u32 in_value;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state");
+ u32 PM1Acontrol;
+ u32 PM1Bcontrol;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
+ u32 in_value;
+ acpi_status status;
+ 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)) {
- ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
- acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
+ ACPI_REPORT_ERROR(("Sleep values out of range: A=%X B=%X\n",
+ acpi_gbl_sleep_type_a,
+ acpi_gbl_sleep_type_b));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
- sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
- sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
+ sleep_type_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
+ sleep_enable_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Clear wake status */
- status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Clear all fixed and general purpose status bits */
- status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
- status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_wakeup_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get current value of PM1A control */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Entering sleep state [S%d]\n", sleep_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Entering sleep state [S%d]\n", sleep_state));
/* Clear SLP_EN and SLP_TYP fields */
PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
- sleep_enable_reg_info->access_bit_mask);
+ sleep_enable_reg_info->access_bit_mask);
PM1Bcontrol = PM1Acontrol;
/* Insert SLP_TYP bits */
- PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
- PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+ PM1Acontrol |=
+ (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
+ PM1Bcontrol |=
+ (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
/*
* We split the writes of SLP_TYP and SLP_EN to workaround
@@ -313,16 +303,18 @@ acpi_enter_sleep_state (
/* Write #1: fill in SLP_TYP data */
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Insert SLP_ENABLE bit */
@@ -332,18 +324,20 @@ acpi_enter_sleep_state (
/* Write #2: SLP_TYP + SLP_EN */
- ACPI_FLUSH_CPU_CACHE ();
+ ACPI_FLUSH_CPU_CACHE();
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (sleep_state > ACPI_STATE_S3) {
@@ -358,33 +352,34 @@ acpi_enter_sleep_state (
* still read the right value. Ideally, this block would go
* away entirely.
*/
- acpi_os_stall (10000000);
-
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
- sleep_enable_reg_info->access_bit_mask);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ acpi_os_stall(10000000);
+
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ sleep_enable_reg_info->
+ access_bit_mask);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Wait until we enter sleep state */
do {
- status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value,
- ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
+ ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Spin until we wake */
} while (!in_value);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state);
+EXPORT_SYMBOL(acpi_enter_sleep_state);
/*******************************************************************************
*
@@ -399,60 +394,57 @@ EXPORT_SYMBOL(acpi_enter_sleep_state);
*
******************************************************************************/
-acpi_status asmlinkage
-acpi_enter_sleep_state_s4bios (
- void)
+acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
{
- u32 in_value;
- acpi_status status;
-
+ 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
- status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_wakeup_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_FLUSH_CPU_CACHE ();
+ ACPI_FLUSH_CPU_CACHE();
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->S4bios_req, 8);
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->S4bios_req, 8);
do {
acpi_os_stall(1000);
- status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value,
- ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
+ ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
} while (!in_value);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
+EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
/*******************************************************************************
*
@@ -467,55 +459,62 @@ EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
*
******************************************************************************/
-acpi_status
-acpi_leave_sleep_state (
- u8 sleep_state)
+acpi_status acpi_leave_sleep_state(u8 sleep_state)
{
- struct acpi_object_list arg_list;
- union acpi_object arg;
- acpi_status status;
- struct acpi_bit_register_info *sleep_type_reg_info;
- struct acpi_bit_register_info *sleep_enable_reg_info;
- u32 PM1Acontrol;
- u32 PM1Bcontrol;
-
-
- ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state");
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
+ u32 PM1Acontrol;
+ u32 PM1Bcontrol;
+ ACPI_FUNCTION_TRACE("acpi_leave_sleep_state");
/*
* Set SLP_TYPE and SLP_EN to state S0.
* This is unclear from the ACPI Spec, but it is required
* by some machines.
*/
- status = acpi_get_sleep_type_data (ACPI_STATE_S0,
- &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
- if (ACPI_SUCCESS (status)) {
- sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
- sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
+ status = acpi_get_sleep_type_data(ACPI_STATE_S0,
+ &acpi_gbl_sleep_type_a,
+ &acpi_gbl_sleep_type_b);
+ if (ACPI_SUCCESS(status)) {
+ sleep_type_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
+ sleep_enable_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Get current value of PM1A control */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ &PM1Acontrol);
+ if (ACPI_SUCCESS(status)) {
/* Clear SLP_EN and SLP_TYP fields */
PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
- sleep_enable_reg_info->access_bit_mask);
+ sleep_enable_reg_info->
+ access_bit_mask);
PM1Bcontrol = PM1Acontrol;
/* Insert SLP_TYP bits */
- PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
- PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+ PM1Acontrol |=
+ (acpi_gbl_sleep_type_a << sleep_type_reg_info->
+ bit_position);
+ PM1Bcontrol |=
+ (acpi_gbl_sleep_type_b << sleep_type_reg_info->
+ bit_position);
/* Just ignore any errors */
- (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
+ (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
}
}
@@ -532,23 +531,23 @@ acpi_leave_sleep_state (
/* Ignore any errors from these methods */
arg.integer.value = ACPI_SST_WAKING;
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
arg.integer.value = sleep_state;
- status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _BFS failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _BFS failed, %s\n",
+ acpi_format_exception(status)));
}
- status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _WAK failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _WAK failed, %s\n",
+ acpi_format_exception(status)));
}
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
@@ -557,33 +556,35 @@ acpi_leave_sleep_state (
* 1) Disable/Clear all GPEs
* 2) Enable all runtime GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = TRUE;
- status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_runtime_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Enable power button */
- (void) acpi_set_register(
- acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)
+ acpi_set_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1,
+ ACPI_MTX_DO_NOT_LOCK);
- (void) acpi_set_register(
- acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)
+ acpi_set_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_POWER_BUTTON].status_register_id, 1,
+ ACPI_MTX_DO_NOT_LOCK);
arg.integer.value = ACPI_SST_WORKING;
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index 49d7b395322e..aff6dc141784 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -46,8 +46,7 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwtimer")
-
+ACPI_MODULE_NAME("hwtimer")
/******************************************************************************
*
@@ -60,29 +59,23 @@
* DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
*
******************************************************************************/
-
-acpi_status
-acpi_get_timer_resolution (
- u32 *resolution)
+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);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (0 == acpi_gbl_FADT->tmr_val_ext) {
*resolution = 24;
- }
- else {
+ } else {
*resolution = 32;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_get_timer
@@ -95,26 +88,22 @@ acpi_get_timer_resolution (
*
******************************************************************************/
-acpi_status
-acpi_get_timer (
- u32 *ticks)
+acpi_status acpi_get_timer(u32 * ticks)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_timer");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_timer");
if (!ticks) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk);
+ status = acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT->xpm_tmr_blk);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_timer);
+EXPORT_SYMBOL(acpi_get_timer);
/******************************************************************************
*
@@ -146,21 +135,16 @@ EXPORT_SYMBOL(acpi_get_timer);
******************************************************************************/
acpi_status
-acpi_get_timer_duration (
- u32 start_ticks,
- u32 end_ticks,
- u32 *time_elapsed)
+acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
{
- acpi_status status;
- u32 delta_ticks;
- acpi_integer quotient;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_timer_duration");
+ acpi_status status;
+ u32 delta_ticks;
+ acpi_integer quotient;
+ ACPI_FUNCTION_TRACE("acpi_get_timer_duration");
if (!time_elapsed) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -169,22 +153,22 @@ acpi_get_timer_duration (
*/
if (start_ticks < end_ticks) {
delta_ticks = end_ticks - start_ticks;
- }
- else if (start_ticks > end_ticks) {
+ } else if (start_ticks > end_ticks) {
if (0 == acpi_gbl_FADT->tmr_val_ext) {
/* 24-bit Timer */
- delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF);
- }
- else {
+ delta_ticks =
+ (((0x00FFFFFF - start_ticks) +
+ end_ticks) & 0x00FFFFFF);
+ } else {
/* 32-bit Timer */
delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
}
- }
- else /* start_ticks == end_ticks */ {
+ } else { /* start_ticks == end_ticks */
+
*time_elapsed = 0;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -192,12 +176,11 @@ acpi_get_timer_duration (
*
* time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
*/
- status = acpi_ut_short_divide (((u64) delta_ticks) * 1000000,
- PM_TIMER_FREQUENCY, &quotient, NULL);
+ status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000,
+ PM_TIMER_FREQUENCY, &quotient, NULL);
*time_elapsed = (u32) quotient;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_get_timer_duration);
-
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 1f76a40badec..2e2e4051dfa7 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -62,7 +62,7 @@
#define _COMPONENT ACPI_HOTKEY_COMPONENT
ACPI_MODULE_NAME("acpi_hotkey")
-MODULE_AUTHOR("luming.yu@intel.com");
+ MODULE_AUTHOR("luming.yu@intel.com");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
MODULE_LICENSE("GPL");
@@ -180,8 +180,8 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event);
+ acpi_hotkey_list
+ *hotkey_list, int event);
/* event based config */
static struct file_operations hotkey_config_fops = {
@@ -246,7 +246,7 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
static char *format_result(union acpi_object *object)
{
char *buf = NULL;
-
+
buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
if (buf)
memset(buf, 0, RESULT_STR_LEN);
@@ -256,7 +256,7 @@ static char *format_result(union acpi_object *object)
/* Now, just support integer type */
if (object->type == ACPI_TYPE_INTEGER)
sprintf(buf, "%d\n", (u32) object->integer.value);
-do_fail:
+ do_fail:
return (buf);
}
@@ -268,9 +268,9 @@ static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
ACPI_FUNCTION_TRACE("hotkey_polling_seq_show");
- if (poll_hotkey->poll_result){
+ if (poll_hotkey->poll_result) {
buf = format_result(poll_hotkey->poll_result);
- if(buf)
+ if (buf)
seq_printf(seq, "%s", buf);
kfree(buf);
}
@@ -299,7 +299,7 @@ static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
- && key->event_hotkey.external_hotkey_num == event){
+ && key->event_hotkey.external_hotkey_num == event) {
val = key->link.hotkey_standard_num;
break;
}
@@ -343,7 +343,7 @@ static int auto_hotkey_remove(struct acpi_device *device, int type)
static int create_polling_proc(union acpi_hotkey *device)
{
struct proc_dir_entry *proc;
- char proc_name[80];
+ char proc_name[80];
mode_t mode;
ACPI_FUNCTION_TRACE("create_polling_proc");
@@ -351,8 +351,8 @@ static int create_polling_proc(union acpi_hotkey *device)
sprintf(proc_name, "%d", device->link.hotkey_standard_num);
/*
- strcat(proc_name, device->poll_hotkey.poll_method);
- */
+ strcat(proc_name, device->poll_hotkey.poll_method);
+ */
proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
if (!proc) {
@@ -415,50 +415,50 @@ static int hotkey_remove(union acpi_hotkey *device)
return_VALUE(0);
}
-static int hotkey_update(union acpi_hotkey *key)
+static int hotkey_update(union acpi_hotkey *key)
{
struct list_head *entries;
ACPI_FUNCTION_TRACE("hotkey_update");
list_for_each(entries, global_hotkey_list.entries) {
- union acpi_hotkey *tmp=
+ union acpi_hotkey *tmp =
container_of(entries, union acpi_hotkey, entries);
if (tmp->link.hotkey_standard_num ==
key->link.hotkey_standard_num) {
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
free_hotkey_buffer(tmp);
tmp->event_hotkey.bus_handle =
- key->event_hotkey.bus_handle;
+ key->event_hotkey.bus_handle;
tmp->event_hotkey.external_hotkey_num =
- key->event_hotkey.external_hotkey_num;
+ key->event_hotkey.external_hotkey_num;
tmp->event_hotkey.action_handle =
- key->event_hotkey.action_handle;
+ key->event_hotkey.action_handle;
tmp->event_hotkey.action_method =
- key->event_hotkey.action_method;
+ key->event_hotkey.action_method;
kfree(key);
} else {
/*
- char proc_name[80];
+ char proc_name[80];
- sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
- strcat(proc_name, tmp->poll_hotkey.poll_method);
- remove_proc_entry(proc_name,hotkey_proc_dir);
- */
+ sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
+ strcat(proc_name, tmp->poll_hotkey.poll_method);
+ remove_proc_entry(proc_name,hotkey_proc_dir);
+ */
free_poll_hotkey_buffer(tmp);
tmp->poll_hotkey.poll_handle =
- key->poll_hotkey.poll_handle;
+ key->poll_hotkey.poll_handle;
tmp->poll_hotkey.poll_method =
- key->poll_hotkey.poll_method;
+ key->poll_hotkey.poll_method;
tmp->poll_hotkey.action_handle =
- key->poll_hotkey.action_handle;
+ key->poll_hotkey.action_handle;
tmp->poll_hotkey.action_method =
- key->poll_hotkey.action_method;
+ key->poll_hotkey.action_method;
tmp->poll_hotkey.poll_result =
- key->poll_hotkey.poll_result;
+ key->poll_hotkey.poll_result;
/*
- create_polling_proc(tmp);
- */
+ create_polling_proc(tmp);
+ */
kfree(key);
}
return_VALUE(0);
@@ -483,27 +483,25 @@ static void free_hotkey_device(union acpi_hotkey *key)
acpi_hotkey_notify_handler);
free_hotkey_buffer(key);
} else {
- char proc_name[80];
+ char proc_name[80];
sprintf(proc_name, "%d", key->link.hotkey_standard_num);
/*
- strcat(proc_name, key->poll_hotkey.poll_method);
- */
- remove_proc_entry(proc_name,hotkey_proc_dir);
+ strcat(proc_name, key->poll_hotkey.poll_method);
+ */
+ remove_proc_entry(proc_name, hotkey_proc_dir);
free_poll_hotkey_buffer(key);
}
kfree(key);
return_VOID;
}
-static void
-free_hotkey_buffer(union acpi_hotkey *key)
+static void free_hotkey_buffer(union acpi_hotkey *key)
{
kfree(key->event_hotkey.action_method);
}
-static void
-free_poll_hotkey_buffer(union acpi_hotkey *key)
+static void free_poll_hotkey_buffer(union acpi_hotkey *key)
{
kfree(key->poll_hotkey.action_method);
kfree(key->poll_hotkey.poll_method);
@@ -513,15 +511,15 @@ static int
init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
char *method, int std_num, int external_num)
{
- acpi_handle tmp_handle;
+ acpi_handle tmp_handle;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("init_hotkey_device");
- if(std_num < 0 || IS_POLL(std_num) || !key )
+ if (std_num < 0 || IS_POLL(std_num) || !key)
goto do_fail;
- if(!bus_str || !action_str || !method)
+ if (!bus_str || !action_str || !method)
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_EVENT;
@@ -529,19 +527,22 @@ init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
key->event_hotkey.flag = 0;
key->event_hotkey.action_method = method;
- status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
key->event_hotkey.external_hotkey_num = external_num;
- status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, action_str,
+ &(key->event_hotkey.action_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->event_hotkey.action_handle,
- method, &tmp_handle);
+ method, &tmp_handle);
if (ACPI_FAILURE(status))
goto do_fail;
return_VALUE(AE_OK);
-do_fail:
+ do_fail:
return_VALUE(-ENODEV);
}
@@ -552,14 +553,14 @@ init_poll_hotkey_device(union acpi_hotkey *key,
char *action_str, char *action_method, int std_num)
{
acpi_status status = AE_OK;
- acpi_handle tmp_handle;
+ acpi_handle tmp_handle;
ACPI_FUNCTION_TRACE("init_poll_hotkey_device");
- if(std_num < 0 || IS_EVENT(std_num) || !key)
+ if (std_num < 0 || IS_EVENT(std_num) || !key)
goto do_fail;
- if(!poll_str || !poll_method || !action_str || !action_method)
+ if (!poll_str || !poll_method || !action_str || !action_method)
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_POLLING;
@@ -568,30 +569,32 @@ init_poll_hotkey_device(union acpi_hotkey *key,
key->poll_hotkey.poll_method = poll_method;
key->poll_hotkey.action_method = action_method;
- status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->poll_hotkey.poll_handle,
- poll_method, &tmp_handle);
- if (ACPI_FAILURE(status))
- goto do_fail;
- status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle));
+ poll_method, &tmp_handle);
+ if (ACPI_FAILURE(status))
+ goto do_fail;
+ status =
+ acpi_get_handle(NULL, action_str,
+ &(key->poll_hotkey.action_handle));
if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->poll_hotkey.action_handle,
- action_method, &tmp_handle);
+ action_method, &tmp_handle);
if (ACPI_FAILURE(status))
goto do_fail;
key->poll_hotkey.poll_result =
(union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if(!key->poll_hotkey.poll_result)
+ if (!key->poll_hotkey.poll_result)
goto do_fail;
return_VALUE(AE_OK);
-do_fail:
+ do_fail:
return_VALUE(-ENODEV);
}
-
static int hotkey_open_config(struct inode *inode, struct file *file)
{
ACPI_FUNCTION_TRACE("hotkey_open_config");
@@ -679,8 +682,9 @@ get_parms(char *config_record,
sscanf(config_record, "%d", cmd);
- if(*cmd == 1){
- if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2)
+ if (*cmd == 1) {
+ if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
+ 2)
goto do_fail;
else
return (6);
@@ -694,8 +698,8 @@ get_parms(char *config_record,
goto do_fail;
count = tmp1 - tmp;
- *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*bus_handle)
+ *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*bus_handle)
goto do_fail;
strncpy(*bus_handle, tmp, count);
*(*bus_handle + count) = 0;
@@ -706,8 +710,8 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *bus_method = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*bus_method)
+ *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*bus_method)
goto do_fail;
strncpy(*bus_method, tmp, count);
*(*bus_method + count) = 0;
@@ -718,7 +722,7 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *action_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+ *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
strncpy(*action_handle, tmp, count);
*(*action_handle + count) = 0;
@@ -728,17 +732,18 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *method = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*method)
+ *method = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*method)
goto do_fail;
strncpy(*method, tmp, count);
*(*method + count) = 0;
- if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0)
+ if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <=
+ 0)
goto do_fail;
return_VALUE(6);
-do_fail:
+ do_fail:
return_VALUE(-1);
}
@@ -758,8 +763,8 @@ static ssize_t hotkey_write_config(struct file *file,
ACPI_FUNCTION_TRACE(("hotkey_write_config"));
- config_record = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!config_record)
+ config_record = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!config_record)
return_VALUE(-ENOMEM);
if (copy_from_user(config_record, buffer, count)) {
@@ -777,10 +782,10 @@ static ssize_t hotkey_write_config(struct file *file,
&method, &internal_event_num, &external_event_num);
kfree(config_record);
- if(IS_OTHERS(internal_event_num))
+ if (IS_OTHERS(internal_event_num))
goto do_fail;
if (ret != 6) {
-do_fail:
+ do_fail:
kfree(bus_handle);
kfree(bus_method);
kfree(action_handle);
@@ -791,14 +796,14 @@ do_fail:
}
key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
- if(!key)
+ if (!key)
goto do_fail;
memset(key, 0, sizeof(union acpi_hotkey));
- if(cmd == 1) {
+ if (cmd == 1) {
union acpi_hotkey *tmp = NULL;
tmp = get_hotkey_by_event(&global_hotkey_list,
- internal_event_num);
- if(!tmp)
+ internal_event_num);
+ if (!tmp)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key"));
else
memcpy(key, tmp, sizeof(union acpi_hotkey));
@@ -807,15 +812,16 @@ do_fail:
if (IS_EVENT(internal_event_num)) {
kfree(bus_method);
ret = init_hotkey_device(key, bus_handle, action_handle, method,
- internal_event_num, external_event_num);
+ internal_event_num,
+ external_event_num);
} else
ret = init_poll_hotkey_device(key, bus_handle, bus_method,
- action_handle, method,
- internal_event_num);
+ action_handle, method,
+ internal_event_num);
if (ret) {
kfree(bus_handle);
kfree(action_handle);
- if(IS_EVENT(internal_event_num))
+ if (IS_EVENT(internal_event_num))
free_hotkey_buffer(key);
else
free_poll_hotkey_buffer(key);
@@ -824,13 +830,14 @@ do_fail:
return_VALUE(-EINVAL);
}
-cont_cmd:
+ cont_cmd:
kfree(bus_handle);
kfree(action_handle);
switch (cmd) {
case 0:
- if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num))
+ if (get_hotkey_by_event
+ (&global_hotkey_list, key->link.hotkey_standard_num))
goto fail_out;
else
hotkey_add(key);
@@ -839,7 +846,7 @@ cont_cmd:
hotkey_remove(key);
break;
case 2:
- if(hotkey_update(key))
+ if (hotkey_update(key))
goto fail_out;
break;
default:
@@ -847,8 +854,8 @@ cont_cmd:
break;
}
return_VALUE(count);
-fail_out:
- if(IS_EVENT(internal_event_num))
+ fail_out:
+ if (IS_EVENT(internal_event_num))
free_hotkey_buffer(key);
else
free_poll_hotkey_buffer(key);
@@ -882,7 +889,8 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
return_VALUE(status == AE_OK);
}
-static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val)
+static int read_acpi_int(acpi_handle handle, const char *method,
+ union acpi_object *val)
{
struct acpi_buffer output;
union acpi_object out_obj;
@@ -893,7 +901,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, union acpi_obje
output.pointer = &out_obj;
status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
- if(val){
+ if (val) {
val->integer.value = out_obj.integer.value;
val->type = out_obj.type;
} else
@@ -903,8 +911,8 @@ static int read_acpi_int(acpi_handle handle, const char *method, union acpi_obje
}
static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event)
+ acpi_hotkey_list
+ *hotkey_list, int event)
{
struct list_head *entries;
@@ -912,10 +920,10 @@ static union acpi_hotkey *get_hotkey_by_event(struct
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_standard_num == event) {
- return(key);
+ return (key);
}
}
- return(NULL);
+ return (NULL);
}
/*
@@ -932,15 +940,15 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
{
struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
char *arg;
- int event,method_type,type, value;
+ int event, method_type, type, value;
union acpi_hotkey *key;
ACPI_FUNCTION_TRACE("hotkey_execte_aml_method");
- arg = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!arg)
+ arg = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!arg)
return_VALUE(-ENOMEM);
- arg[count]=0;
+ arg[count] = 0;
if (copy_from_user(arg, buffer, count)) {
kfree(arg);
@@ -948,7 +956,8 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
return_VALUE(-EINVAL);
}
- if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) {
+ if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) !=
+ 4) {
kfree(arg);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3"));
return_VALUE(-EINVAL);
@@ -956,19 +965,21 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
kfree(arg);
if (type == ACPI_TYPE_INTEGER) {
key = get_hotkey_by_event(hotkey_list, event);
- if(!key)
+ if (!key)
goto do_fail;
if (IS_EVENT(event))
write_acpi_int(key->event_hotkey.action_handle,
- key->event_hotkey.action_method, value, NULL);
+ key->event_hotkey.action_method, value,
+ NULL);
else if (IS_POLL(event)) {
- if ( method_type == POLL_METHOD )
+ if (method_type == POLL_METHOD)
read_acpi_int(key->poll_hotkey.poll_handle,
- key->poll_hotkey.poll_method,
- key->poll_hotkey.poll_result);
- else if ( method_type == ACTION_METHOD )
+ key->poll_hotkey.poll_method,
+ key->poll_hotkey.poll_result);
+ else if (method_type == ACTION_METHOD)
write_acpi_int(key->poll_hotkey.action_handle,
- key->poll_hotkey.action_method, value, NULL);
+ key->poll_hotkey.action_method,
+ value, NULL);
else
goto do_fail;
@@ -978,7 +989,7 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
return_VALUE(-EINVAL);
}
return_VALUE(count);
-do_fail:
+ do_fail:
return_VALUE(-EINVAL);
}
@@ -1074,15 +1085,15 @@ static int __init hotkey_init(void)
return (0);
-do_fail5:
+ do_fail5:
remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-do_fail4:
+ do_fail4:
remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-do_fail3:
+ do_fail3:
remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-do_fail2:
+ do_fail2:
remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-do_fail1:
+ do_fail1:
remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
return (-ENODEV);
}
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index ad85e10001f4..5cc090326ddc 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -2,7 +2,7 @@
* ibm_acpi.c - IBM ThinkPad ACPI Extras
*
*
- * Copyright (C) 2004 Borislav Deianov
+ * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.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
@@ -17,38 +17,62 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ */
+
+#define IBM_VERSION "0.12a"
+
+/*
* Changelog:
- *
- * 2004-08-09 0.1 initial release, support for X series
- * 2004-08-14 0.2 support for T series, X20
- * bluetooth enable/disable
- * hotkey events disabled by default
- * removed fan control, currently useless
- * 2004-08-17 0.3 support for R40
- * lcd off, brightness control
- * thinklight on/off
- * 2004-09-16 0.4 support for module parameters
- * hotkey mask can be prefixed by 0x
- * video output switching
- * video expansion control
- * ultrabay eject support
- * removed lcd brightness/on/off control, didn't work
+ *
+ * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
+ * 2005-03-17 0.11 support for 600e, 770x
+ * thanks to Jamie Lentin <lentinj@dial.pipex.com>
+ * support for 770e, G41
+ * G40 and G41 don't have a thinklight
+ * temperatures no longer experimental
+ * experimental brightness control
+ * experimental volume control
+ * experimental fan enable/disable
+ * 2005-01-16 0.10 fix module loading on R30, R31
+ * 2005-01-16 0.9 support for 570, R30, R31
+ * ultrabay support on A22p, A3x
+ * limit arg for cmos, led, beep, drop experimental status
+ * more capable led control on A21e, A22p, T20-22, X20
+ * experimental temperatures and fan speed
+ * experimental embedded controller register dump
+ * mark more functions as __init, drop incorrect __exit
+ * use MODULE_VERSION
+ * thanks to Henrik Brix Andersen <brix@gentoo.org>
+ * fix parameter passing on module loading
+ * thanks to Rusty Russell <rusty@rustcorp.com.au>
+ * thanks to Jim Radford <radford@blackbean.org>
+ * 2004-11-08 0.8 fix init error case, don't return from a macro
+ * thanks to Chris Wright <chrisw@osdl.org>
+ * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
+ * fix led control on A21e
+ * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
* 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
* proc file format changed
* video_switch command
* experimental cmos control
* experimental led control
* experimental acpi sounds
- * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
- * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
- * fix LED control on A21e
- * 2004-11-08 0.8 fix init error case, don't return from a macro
- * thanks to Chris Wright <chrisw@osdl.org>
+ * 2004-09-16 0.4 support for module parameters
+ * hotkey mask can be prefixed by 0x
+ * video output switching
+ * video expansion control
+ * ultrabay eject support
+ * removed lcd brightness/on/off control, didn't work
+ * 2004-08-17 0.3 support for R40
+ * lcd off, brightness control
+ * thinklight on/off
+ * 2004-08-14 0.2 support for T series, X20
+ * bluetooth enable/disable
+ * hotkey events disabled by default
+ * removed fan control, currently useless
+ * 2004-08-09 0.1 initial release, support for X series
*/
-#define IBM_VERSION "0.8"
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -64,6 +88,11 @@
#define IBM_FILE "ibm_acpi"
#define IBM_URL "http://ibm-acpi.sf.net/"
+MODULE_AUTHOR("Borislav Deianov");
+MODULE_DESCRIPTION(IBM_DESC);
+MODULE_VERSION(IBM_VERSION);
+MODULE_LICENSE("GPL");
+
#define IBM_DIR IBM_NAME
#define IBM_LOG IBM_FILE ": "
@@ -84,54 +113,122 @@ static acpi_handle root_handle = NULL;
#define IBM_HANDLE(object, parent, paths...) \
static acpi_handle object##_handle; \
static acpi_handle *object##_parent = &parent##_handle; \
+ static char *object##_path; \
static char *object##_paths[] = { paths }
-IBM_HANDLE(ec, root,
- "\\_SB.PCI0.ISA.EC", /* A21e, A22p, T20, T21, X20 */
- "\\_SB.PCI0.LPC.EC", /* all others */
-);
-
-IBM_HANDLE(vid, root,
- "\\_SB.PCI0.VID", /* A21e, G40, X30, X40 */
- "\\_SB.PCI0.AGP.VID", /* all others */
-);
-
-IBM_HANDLE(cmos, root,
- "\\UCMS", /* R50, R50p, R51, T4x, X31, X40 */
- "\\CMOS", /* A3x, G40, R32, T23, T30, X22, X24, X30 */
- "\\CMS", /* R40, R40e */
-); /* A21e, A22p, T20, T21, X20 */
-
-IBM_HANDLE(dock, root,
- "\\_SB.GDCK", /* X30, X31, X40 */
- "\\_SB.PCI0.DOCK", /* A22p, T20, T21, X20 */
- "\\_SB.PCI0.PCI1.DOCK", /* all others */
-); /* A21e, G40, R32, R40, R40e */
-
-IBM_HANDLE(bay, root,
- "\\_SB.PCI0.IDE0.SCND.MSTR"); /* all except A21e */
-IBM_HANDLE(bayej, root,
- "\\_SB.PCI0.IDE0.SCND.MSTR._EJ0"); /* all except A2x, A3x */
-
-IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(hkey, ec, "HKEY"); /* all */
-IBM_HANDLE(led, ec, "LED"); /* all except A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(sysl, ec, "SYSL"); /* A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(bled, ec, "BLED"); /* A22p, T20, T21, X20 */
-IBM_HANDLE(beep, ec, "BEEP"); /* all models */
+/*
+ * The following models are supported to various degrees:
+ *
+ * 570, 600e, 600x, 770e, 770x
+ * A20m, A21e, A21m, A21p, A22p, A30, A30p, A31, A31p
+ * G40, G41
+ * R30, R31, R32, R40, R40e, R50, R50e, R50p, R51
+ * T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p, T43
+ * X20, X21, X22, X23, X24, X30, X31, X40
+ *
+ * The following models have no supported features:
+ *
+ * 240, 240x, i1400
+ *
+ * Still missing DSDTs for the following models:
+ *
+ * A20p, A22e, A22m
+ * R52
+ * S31
+ * T43p
+ */
+
+IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
+ "\\_SB.PCI.ISA.EC", /* 570 */
+ "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
+ "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
+ "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
+ "\\_SB.PCI0.ICH3.EC0", /* R31 */
+ "\\_SB.PCI0.LPC.EC", /* all others */
+ );
+
+IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
+ "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
+ "\\_SB.PCI0.VID0", /* 770e */
+ "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
+ "\\_SB.PCI0.AGP.VID", /* all others */
+ ); /* R30, R31 */
+
+IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
+
+IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
+ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
+ "\\CMS", /* R40, R40e */
+ ); /* all others */
+
+IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
+ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
+ "\\_SB.PCI0.PCI1.DOCK", /* all others */
+ "\\_SB.PCI.ISA.SLCE", /* 570 */
+ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
+
+IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
+ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
+ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
+ ); /* A21e, R30, R31 */
+
+IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
+ "_EJ0", /* all others */
+ ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
+
+IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
+ "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
+ ); /* all others */
+
+IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
+ "_EJ0", /* 770x */
+ ); /* all others */
+
+/* don't list other alternatives as we install a notify handler on the 570 */
+IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
+
+IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
+ "^HKEY", /* R30, R31 */
+ "HKEY", /* all others */
+ ); /* 570 */
+
+IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
+IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
+
+IBM_HANDLE(led, ec, "SLED", /* 570 */
+ "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+ "LED", /* all others */
+ ); /* R30, R31 */
+
+IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
+IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
+IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
+IBM_HANDLE(fans, ec, "FANS"); /* X31, X40 */
+
+IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
+ "\\FSPD", /* 600e/x, 770e, 770x */
+ ); /* all others */
+
+IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
+ "JFNS", /* 770x-JL */
+ ); /* all others */
+
+#define IBM_HKEY_HID "IBM0068"
+#define IBM_PCI_HID "PNP0A03"
struct ibm_struct {
char *name;
+ char param[32];
char *hid;
struct acpi_driver *driver;
-
- int (*init) (struct ibm_struct *);
- int (*read) (struct ibm_struct *, char *);
- int (*write) (struct ibm_struct *, char *);
- void (*exit) (struct ibm_struct *);
- void (*notify) (struct ibm_struct *, u32);
+ int (*init) (void);
+ int (*read) (char *);
+ int (*write) (char *);
+ void (*exit) (void);
+
+ void (*notify) (struct ibm_struct *, u32);
acpi_handle *handle;
int type;
struct acpi_device *device;
@@ -141,17 +238,6 @@ struct ibm_struct {
int init_called;
int notify_installed;
- int supported;
- union {
- struct {
- int status;
- int mask;
- } hotkey;
- struct {
- int autoswitch;
- } video;
- } state;
-
int experimental;
};
@@ -165,15 +251,15 @@ static int acpi_evalf(acpi_handle handle,
void *res, char *method, char *fmt, ...)
{
char *fmt0 = fmt;
- struct acpi_object_list params;
- union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
- struct acpi_buffer result;
- union acpi_object out_obj;
- acpi_status status;
- va_list ap;
- char res_type;
- int success;
- int quiet;
+ struct acpi_object_list params;
+ union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
+ struct acpi_buffer result, *resultp;
+ union acpi_object out_obj;
+ acpi_status status;
+ va_list ap;
+ char res_type;
+ int success;
+ int quiet;
if (!*fmt) {
printk(IBM_ERR "acpi_evalf() called with empty format\n");
@@ -199,7 +285,7 @@ static int acpi_evalf(acpi_handle handle,
in_objs[params.count].integer.value = va_arg(ap, int);
in_objs[params.count++].type = ACPI_TYPE_INTEGER;
break;
- /* add more types as needed */
+ /* add more types as needed */
default:
printk(IBM_ERR "acpi_evalf() called "
"with invalid format character '%c'\n", c);
@@ -208,21 +294,25 @@ static int acpi_evalf(acpi_handle handle,
}
va_end(ap);
- result.length = sizeof(out_obj);
- result.pointer = &out_obj;
+ if (res_type != 'v') {
+ result.length = sizeof(out_obj);
+ result.pointer = &out_obj;
+ resultp = &result;
+ } else
+ resultp = NULL;
- status = acpi_evaluate_object(handle, method, &params, &result);
+ status = acpi_evaluate_object(handle, method, &params, resultp);
switch (res_type) {
- case 'd': /* int */
+ case 'd': /* int */
if (res)
*(int *)res = out_obj.integer.value;
success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
break;
- case 'v': /* void */
+ case 'v': /* void */
success = status == AE_OK;
break;
- /* add more types as needed */
+ /* add more types as needed */
default:
printk(IBM_ERR "acpi_evalf() called "
"with invalid format character '%c'\n", res_type);
@@ -262,7 +352,7 @@ static char *next_cmd(char **cmds)
return start;
}
-static int driver_init(struct ibm_struct *ibm)
+static int driver_init(void)
{
printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
printk(IBM_INFO "%s\n", IBM_URL);
@@ -270,7 +360,7 @@ static int driver_init(struct ibm_struct *ibm)
return 0;
}
-static int driver_read(struct ibm_struct *ibm, char *p)
+static int driver_read(char *p)
{
int len = 0;
@@ -280,67 +370,74 @@ static int driver_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int hotkey_get(struct ibm_struct *ibm, int *status, int *mask)
+static int hotkey_supported;
+static int hotkey_mask_supported;
+static int hotkey_orig_status;
+static int hotkey_orig_mask;
+
+static int hotkey_get(int *status, int *mask)
{
if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
- return -EIO;
- if (ibm->supported) {
- if (!acpi_evalf(hkey_handle, mask, "DHKN", "qd"))
- return -EIO;
- } else {
- *mask = ibm->state.hotkey.mask;
- }
- return 0;
+ return 0;
+
+ if (hotkey_mask_supported)
+ if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
+ return 0;
+
+ return 1;
}
-static int hotkey_set(struct ibm_struct *ibm, int status, int mask)
+static int hotkey_set(int status, int mask)
{
int i;
if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
- return -EIO;
-
- if (!ibm->supported)
return 0;
- for (i=0; i<32; i++) {
- int bit = ((1 << i) & mask) != 0;
- if (!acpi_evalf(hkey_handle, NULL, "MHKM", "vdd", i+1, bit))
- return -EIO;
- }
+ if (hotkey_mask_supported)
+ for (i = 0; i < 32; i++) {
+ int bit = ((1 << i) & mask) != 0;
+ if (!acpi_evalf(hkey_handle,
+ NULL, "MHKM", "vdd", i + 1, bit))
+ return 0;
+ }
- return 0;
+ return 1;
}
-static int hotkey_init(struct ibm_struct *ibm)
+static int hotkey_init(void)
{
- int ret;
+ /* hotkey not supported on 570 */
+ hotkey_supported = hkey_handle != NULL;
- ibm->supported = 1;
- ret = hotkey_get(ibm,
- &ibm->state.hotkey.status,
- &ibm->state.hotkey.mask);
- if (ret < 0) {
- /* mask not supported on A21e, A22p, T20, T21, X20, X22, X24 */
- ibm->supported = 0;
- ret = hotkey_get(ibm,
- &ibm->state.hotkey.status,
- &ibm->state.hotkey.mask);
+ if (hotkey_supported) {
+ /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ A30, R30, R31, T20-22, X20-21, X22-24 */
+ hotkey_mask_supported =
+ acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
+
+ if (!hotkey_get(&hotkey_orig_status, &hotkey_orig_mask))
+ return -ENODEV;
}
- return ret;
-}
+ return 0;
+}
-static int hotkey_read(struct ibm_struct *ibm, char *p)
+static int hotkey_read(char *p)
{
int status, mask;
int len = 0;
- if (hotkey_get(ibm, &status, &mask) < 0)
+ if (!hotkey_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+
+ if (!hotkey_get(&status, &mask))
return -EIO;
len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
- if (ibm->supported) {
+ if (hotkey_mask_supported) {
len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
len += sprintf(p + len,
"commands:\tenable, disable, reset, <mask>\n");
@@ -352,23 +449,26 @@ static int hotkey_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int hotkey_write(struct ibm_struct *ibm, char *buf)
+static int hotkey_write(char *buf)
{
int status, mask;
char *cmd;
int do_cmd = 0;
- if (hotkey_get(ibm, &status, &mask) < 0)
+ if (!hotkey_supported)
return -ENODEV;
+ if (!hotkey_get(&status, &mask))
+ return -EIO;
+
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
status = 1;
} else if (strlencmp(cmd, "disable") == 0) {
status = 0;
} else if (strlencmp(cmd, "reset") == 0) {
- status = ibm->state.hotkey.status;
- mask = ibm->state.hotkey.mask;
+ status = hotkey_orig_status;
+ mask = hotkey_orig_mask;
} else if (sscanf(cmd, "0x%x", &mask) == 1) {
/* mask set */
} else if (sscanf(cmd, "%x", &mask) == 1) {
@@ -378,15 +478,16 @@ static int hotkey_write(struct ibm_struct *ibm, char *buf)
do_cmd = 1;
}
- if (do_cmd && hotkey_set(ibm, status, mask) < 0)
+ if (do_cmd && !hotkey_set(status, mask))
return -EIO;
return 0;
-}
+}
-static void hotkey_exit(struct ibm_struct *ibm)
+static void hotkey_exit(void)
{
- hotkey_set(ibm, ibm->state.hotkey.status, ibm->state.hotkey.mask);
+ if (hotkey_supported)
+ hotkey_set(hotkey_orig_status, hotkey_orig_mask);
}
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -398,33 +499,38 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
else {
printk(IBM_ERR "unknown hotkey event %d\n", event);
acpi_bus_generate_event(ibm->device, event, 0);
- }
+ }
}
-static int bluetooth_init(struct ibm_struct *ibm)
+static int bluetooth_supported;
+
+static int bluetooth_init(void)
{
- /* bluetooth not supported on A21e, G40, T20, T21, X20 */
- ibm->supported = acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
+ /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
+ bluetooth_supported = hkey_handle &&
+ acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
return 0;
}
-static int bluetooth_status(struct ibm_struct *ibm)
+static int bluetooth_status(void)
{
int status;
- if (!ibm->supported || !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+ if (!bluetooth_supported ||
+ !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
status = 0;
return status;
}
-static int bluetooth_read(struct ibm_struct *ibm, char *p)
+static int bluetooth_read(char *p)
{
int len = 0;
- int status = bluetooth_status(ibm);
+ int status = bluetooth_status();
- if (!ibm->supported)
+ if (!bluetooth_supported)
len += sprintf(p + len, "status:\t\tnot supported\n");
else if (!(status & 1))
len += sprintf(p + len, "status:\t\tnot installed\n");
@@ -436,14 +542,14 @@ static int bluetooth_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int bluetooth_write(struct ibm_struct *ibm, char *buf)
+static int bluetooth_write(char *buf)
{
- int status = bluetooth_status(ibm);
+ int status = bluetooth_status();
char *cmd;
int do_cmd = 0;
- if (!ibm->supported)
- return -EINVAL;
+ if (!bluetooth_supported)
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
@@ -456,64 +562,166 @@ static int bluetooth_write(struct ibm_struct *ibm, char *buf)
}
if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
- return -EIO;
+ return -EIO;
return 0;
}
-static int video_init(struct ibm_struct *ibm)
+static int video_supported;
+static int video_orig_autosw;
+
+#define VIDEO_570 1
+#define VIDEO_770 2
+#define VIDEO_NEW 3
+
+static int video_init(void)
{
- if (!acpi_evalf(vid_handle,
- &ibm->state.video.autoswitch, "^VDEE", "d"))
- return -ENODEV;
+ int ivga;
+
+ if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
+ /* G41, assume IVGA doesn't change */
+ vid_handle = vid2_handle;
+
+ if (!vid_handle)
+ /* video switching not supported on R30, R31 */
+ video_supported = 0;
+ else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
+ /* 570 */
+ video_supported = VIDEO_570;
+ else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
+ /* 600e/x, 770e, 770x */
+ video_supported = VIDEO_770;
+ else
+ /* all others */
+ video_supported = VIDEO_NEW;
return 0;
}
-static int video_status(struct ibm_struct *ibm)
+static int video_status(void)
{
int status = 0;
int i;
- acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
- if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
- status |= 0x02 * i;
+ if (video_supported == VIDEO_570) {
+ if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
+ status = i & 3;
+ } else if (video_supported == VIDEO_770) {
+ if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
+ status |= 0x01 * i;
+ if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
+ status |= 0x02 * i;
+ } else if (video_supported == VIDEO_NEW) {
+ acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
+ if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
+ status |= 0x02 * i;
+
+ acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
+ if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
+ status |= 0x01 * i;
+ if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
+ status |= 0x08 * i;
+ }
+
+ return status;
+}
- acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
- if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
- status |= 0x01 * i;
- if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
- status |= 0x08 * i;
+static int video_autosw(void)
+{
+ int autosw = 0;
- if (acpi_evalf(vid_handle, &i, "^VDEE", "d"))
- status |= 0x10 * (i & 1);
+ if (video_supported == VIDEO_570)
+ acpi_evalf(vid_handle, &autosw, "SWIT", "d");
+ else if (video_supported == VIDEO_770 || video_supported == VIDEO_NEW)
+ acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
- return status;
+ return autosw & 1;
}
-static int video_read(struct ibm_struct *ibm, char *p)
+static int video_read(char *p)
{
- int status = video_status(ibm);
+ int status = video_status();
+ int autosw = video_autosw();
int len = 0;
+ if (!video_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+
+ len += sprintf(p + len, "status:\t\tsupported\n");
len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
- len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
- len += sprintf(p + len, "auto:\t\t%s\n", enabled(status, 4));
- len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable, "
- "crt_enable, crt_disable\n");
- len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable, "
- "auto_enable, auto_disable\n");
+ if (video_supported == VIDEO_NEW)
+ len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
+ len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
+ len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
+ len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
+ if (video_supported == VIDEO_NEW)
+ len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
+ len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
return len;
}
-static int video_write(struct ibm_struct *ibm, char *buf)
+static int video_switch(void)
+{
+ int autosw = video_autosw();
+ int ret;
+
+ if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
+ return -EIO;
+ ret = video_supported == VIDEO_570 ?
+ acpi_evalf(ec_handle, NULL, "_Q16", "v") :
+ acpi_evalf(vid_handle, NULL, "VSWT", "v");
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
+
+ return ret;
+}
+
+static int video_expand(void)
+{
+ if (video_supported == VIDEO_570)
+ return acpi_evalf(ec_handle, NULL, "_Q17", "v");
+ else if (video_supported == VIDEO_770)
+ return acpi_evalf(vid_handle, NULL, "VEXP", "v");
+ else
+ return acpi_evalf(NULL, NULL, "\\VEXP", "v");
+}
+
+static int video_switch2(int status)
+{
+ int ret;
+
+ if (video_supported == VIDEO_570) {
+ ret = acpi_evalf(NULL, NULL,
+ "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
+ } else if (video_supported == VIDEO_770) {
+ int autosw = video_autosw();
+ if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
+ return -EIO;
+
+ ret = acpi_evalf(vid_handle, NULL,
+ "ASWT", "vdd", status * 0x100, 0);
+
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
+ } else {
+ ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
+ acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
+ }
+
+ return ret;
+}
+
+static int video_write(char *buf)
{
char *cmd;
int enable, disable, status;
+ if (!video_supported)
+ return -ENODEV;
+
enable = disable = 0;
while ((cmd = next_cmd(&buf))) {
@@ -525,9 +733,11 @@ static int video_write(struct ibm_struct *ibm, char *buf)
enable |= 0x02;
} else if (strlencmp(cmd, "crt_disable") == 0) {
disable |= 0x02;
- } else if (strlencmp(cmd, "dvi_enable") == 0) {
+ } else if (video_supported == VIDEO_NEW &&
+ strlencmp(cmd, "dvi_enable") == 0) {
enable |= 0x08;
- } else if (strlencmp(cmd, "dvi_disable") == 0) {
+ } else if (video_supported == VIDEO_NEW &&
+ strlencmp(cmd, "dvi_disable") == 0) {
disable |= 0x08;
} else if (strlencmp(cmd, "auto_enable") == 0) {
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
@@ -536,71 +746,75 @@ static int video_write(struct ibm_struct *ibm, char *buf)
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
return -EIO;
} else if (strlencmp(cmd, "video_switch") == 0) {
- int autoswitch;
- if (!acpi_evalf(vid_handle, &autoswitch, "^VDEE", "d"))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "VSWT", "v"))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd",
- autoswitch))
+ if (!video_switch())
return -EIO;
} else if (strlencmp(cmd, "expand_toggle") == 0) {
- if (!acpi_evalf(NULL, NULL, "\\VEXP", "v"))
+ if (!video_expand())
return -EIO;
} else
return -EINVAL;
}
if (enable || disable) {
- status = (video_status(ibm) & 0x0f & ~disable) | enable;
- if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80))
- return -EIO;
- if (!acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1))
+ status = (video_status() & 0x0f & ~disable) | enable;
+ if (!video_switch2(status))
return -EIO;
}
return 0;
}
-static void video_exit(struct ibm_struct *ibm)
+static void video_exit(void)
{
- acpi_evalf(vid_handle, NULL, "_DOS", "vd",
- ibm->state.video.autoswitch);
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw);
}
-static int light_init(struct ibm_struct *ibm)
+static int light_supported;
+static int light_status_supported;
+
+static int light_init(void)
{
- /* kblt not supported on G40, R32, X20 */
- ibm->supported = acpi_evalf(ec_handle, NULL, "KBLT", "qv");
+ /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
+ light_supported = (cmos_handle || lght_handle) && !ledb_handle;
+
+ if (light_supported)
+ /* light status not supported on
+ 570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
+ light_status_supported = acpi_evalf(ec_handle, NULL,
+ "KBLT", "qv");
return 0;
}
-static int light_read(struct ibm_struct *ibm, char *p)
+static int light_read(char *p)
{
int len = 0;
int status = 0;
- if (ibm->supported) {
+ if (!light_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ } else if (!light_status_supported) {
+ len += sprintf(p + len, "status:\t\tunknown\n");
+ len += sprintf(p + len, "commands:\ton, off\n");
+ } else {
if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
return -EIO;
len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
- } else
- len += sprintf(p + len, "status:\t\tunknown\n");
-
- len += sprintf(p + len, "commands:\ton, off\n");
+ len += sprintf(p + len, "commands:\ton, off\n");
+ }
return len;
}
-static int light_write(struct ibm_struct *ibm, char *buf)
+static int light_write(char *buf)
{
int cmos_cmd, lght_cmd;
char *cmd;
int success;
-
+
+ if (!light_supported)
+ return -ENODEV;
+
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "on") == 0) {
cmos_cmd = 0x0c;
@@ -610,10 +824,10 @@ static int light_write(struct ibm_struct *ibm, char *buf)
lght_cmd = 0;
} else
return -EINVAL;
-
+
success = cmos_handle ?
- acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
- acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
+ acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
+ acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
if (!success)
return -EIO;
}
@@ -633,7 +847,7 @@ static int _sta(acpi_handle handle)
#define dock_docked() (_sta(dock_handle) & 1)
-static int dock_read(struct ibm_struct *ibm, char *p)
+static int dock_read(char *p)
{
int len = 0;
int docked = dock_docked();
@@ -650,18 +864,17 @@ static int dock_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int dock_write(struct ibm_struct *ibm, char *buf)
+static int dock_write(char *buf)
{
char *cmd;
if (!dock_docked())
- return -EINVAL;
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "undock") == 0) {
- if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0))
- return -EIO;
- if (!acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
+ if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
+ !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
return -EIO;
} else if (strlencmp(cmd, "dock") == 0) {
if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
@@ -671,90 +884,131 @@ static int dock_write(struct ibm_struct *ibm, char *buf)
}
return 0;
-}
+}
static void dock_notify(struct ibm_struct *ibm, u32 event)
{
int docked = dock_docked();
-
- if (event == 3 && docked)
- acpi_bus_generate_event(ibm->device, event, 1); /* button */
+ int pci = ibm->hid && strstr(ibm->hid, IBM_PCI_HID);
+
+ if (event == 1 && !pci) /* 570 */
+ acpi_bus_generate_event(ibm->device, event, 1); /* button */
+ else if (event == 1 && pci) /* 570 */
+ acpi_bus_generate_event(ibm->device, event, 3); /* dock */
+ else if (event == 3 && docked)
+ acpi_bus_generate_event(ibm->device, event, 1); /* button */
else if (event == 3 && !docked)
- acpi_bus_generate_event(ibm->device, event, 2); /* undock */
+ acpi_bus_generate_event(ibm->device, event, 2); /* undock */
else if (event == 0 && docked)
- acpi_bus_generate_event(ibm->device, event, 3); /* dock */
+ acpi_bus_generate_event(ibm->device, event, 3); /* dock */
else {
printk(IBM_ERR "unknown dock event %d, status %d\n",
event, _sta(dock_handle));
- acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
+ acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
}
}
-#define bay_occupied() (_sta(bay_handle) & 1)
+static int bay_status_supported;
+static int bay_status2_supported;
+static int bay_eject_supported;
+static int bay_eject2_supported;
-static int bay_init(struct ibm_struct *ibm)
+static int bay_init(void)
{
- /* bay not supported on A21e, A22p, A31, A31p, G40, R32, R40e */
- ibm->supported = bay_handle && bayej_handle &&
- acpi_evalf(bay_handle, NULL, "_STA", "qv");
+ bay_status_supported = bay_handle &&
+ acpi_evalf(bay_handle, NULL, "_STA", "qv");
+ bay_status2_supported = bay2_handle &&
+ acpi_evalf(bay2_handle, NULL, "_STA", "qv");
+
+ bay_eject_supported = bay_handle && bay_ej_handle &&
+ (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
+ bay_eject2_supported = bay2_handle && bay2_ej_handle &&
+ (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
return 0;
}
-static int bay_read(struct ibm_struct *ibm, char *p)
+#define bay_occupied(b) (_sta(b##_handle) & 1)
+
+static int bay_read(char *p)
{
int len = 0;
- int occupied = bay_occupied();
-
- if (!ibm->supported)
- len += sprintf(p + len, "status:\t\tnot supported\n");
- else if (!occupied)
- len += sprintf(p + len, "status:\t\tunoccupied\n");
- else {
- len += sprintf(p + len, "status:\t\toccupied\n");
+ int occupied = bay_occupied(bay);
+ int occupied2 = bay_occupied(bay2);
+ int eject, eject2;
+
+ len += sprintf(p + len, "status:\t\t%s\n", bay_status_supported ?
+ (occupied ? "occupied" : "unoccupied") :
+ "not supported");
+ if (bay_status2_supported)
+ len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
+ "occupied" : "unoccupied");
+
+ eject = bay_eject_supported && occupied;
+ eject2 = bay_eject2_supported && occupied2;
+
+ if (eject && eject2)
+ len += sprintf(p + len, "commands:\teject, eject2\n");
+ else if (eject)
len += sprintf(p + len, "commands:\teject\n");
- }
+ else if (eject2)
+ len += sprintf(p + len, "commands:\teject2\n");
return len;
}
-static int bay_write(struct ibm_struct *ibm, char *buf)
+static int bay_write(char *buf)
{
char *cmd;
+ if (!bay_eject_supported && !bay_eject2_supported)
+ return -ENODEV;
+
while ((cmd = next_cmd(&buf))) {
- if (strlencmp(cmd, "eject") == 0) {
- if (!ibm->supported ||
- !acpi_evalf(bay_handle, NULL, "_EJ0", "vd", 1))
+ if (bay_eject_supported && strlencmp(cmd, "eject") == 0) {
+ if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
+ return -EIO;
+ } else if (bay_eject2_supported &&
+ strlencmp(cmd, "eject2") == 0) {
+ if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
return -EIO;
} else
return -EINVAL;
}
return 0;
-}
+}
static void bay_notify(struct ibm_struct *ibm, u32 event)
{
acpi_bus_generate_event(ibm->device, event, 0);
}
-static int cmos_read(struct ibm_struct *ibm, char *p)
+static int cmos_read(char *p)
{
int len = 0;
- /* cmos not supported on A21e, A22p, T20, T21, X20 */
+ /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ R30, R31, T20-22, X20-21 */
if (!cmos_handle)
len += sprintf(p + len, "status:\t\tnot supported\n");
else {
len += sprintf(p + len, "status:\t\tsupported\n");
- len += sprintf(p + len, "commands:\t<int>\n");
+ len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
}
return len;
}
-static int cmos_write(struct ibm_struct *ibm, char *buf)
+static int cmos_eval(int cmos_cmd)
+{
+ if (cmos_handle)
+ return acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd);
+ else
+ return 1;
+}
+
+static int cmos_write(char *buf)
{
char *cmd;
int cmos_cmd;
@@ -763,183 +1017,644 @@ static int cmos_write(struct ibm_struct *ibm, char *buf)
return -EINVAL;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &cmos_cmd) == 1) {
+ if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
+ cmos_cmd >= 0 && cmos_cmd <= 21) {
/* cmos_cmd set */
} else
return -EINVAL;
- if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
+ if (!cmos_eval(cmos_cmd))
return -EIO;
}
return 0;
-}
-
-static int led_read(struct ibm_struct *ibm, char *p)
+}
+
+static int led_supported;
+
+#define LED_570 1
+#define LED_OLD 2
+#define LED_NEW 3
+
+static int led_init(void)
+{
+ if (!led_handle)
+ /* led not supported on R30, R31 */
+ led_supported = 0;
+ else if (strlencmp(led_path, "SLED") == 0)
+ /* 570 */
+ led_supported = LED_570;
+ else if (strlencmp(led_path, "SYSL") == 0)
+ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+ led_supported = LED_OLD;
+ else
+ /* all others */
+ led_supported = LED_NEW;
+
+ return 0;
+}
+
+#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
+
+static int led_read(char *p)
{
int len = 0;
+ if (!led_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+ len += sprintf(p + len, "status:\t\tsupported\n");
+
+ if (led_supported == LED_570) {
+ /* 570 */
+ int i, status;
+ for (i = 0; i < 8; i++) {
+ if (!acpi_evalf(ec_handle,
+ &status, "GLED", "dd", 1 << i))
+ return -EIO;
+ len += sprintf(p + len, "%d:\t\t%s\n",
+ i, led_status(status));
+ }
+ }
+
len += sprintf(p + len, "commands:\t"
- "<int> on, <int> off, <int> blink\n");
+ "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
return len;
}
-static int led_write(struct ibm_struct *ibm, char *buf)
+/* off, on, blink */
+static const int led_sled_arg1[] = { 0, 1, 3 };
+static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
+static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
+static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
+
+#define EC_HLCL 0x0c
+#define EC_HLBL 0x0d
+#define EC_HLMS 0x0e
+
+static int led_write(char *buf)
{
char *cmd;
- unsigned int led;
- int led_cmd, sysl_cmd, bled_a, bled_b;
+ int led, ind, ret;
+
+ if (!led_supported)
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &led) != 1)
+ if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
return -EINVAL;
- if (strstr(cmd, "blink")) {
- led_cmd = 0xc0;
- sysl_cmd = 2;
- bled_a = 2;
- bled_b = 1;
+ if (strstr(cmd, "off")) {
+ ind = 0;
} else if (strstr(cmd, "on")) {
- led_cmd = 0x80;
- sysl_cmd = 1;
- bled_a = 2;
- bled_b = 0;
- } else if (strstr(cmd, "off")) {
- led_cmd = sysl_cmd = bled_a = bled_b = 0;
+ ind = 1;
+ } else if (strstr(cmd, "blink")) {
+ ind = 2;
} else
return -EINVAL;
-
- if (led_handle) {
+
+ if (led_supported == LED_570) {
+ /* 570 */
+ led = 1 << led;
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
- led, led_cmd))
+ led, led_sled_arg1[ind]))
return -EIO;
- } else if (led < 2) {
- if (acpi_evalf(sysl_handle, NULL, NULL, "vdd",
- led, sysl_cmd))
+ } else if (led_supported == LED_OLD) {
+ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+ led = 1 << led;
+ ret = ec_write(EC_HLMS, led);
+ if (ret >= 0)
+ ret =
+ ec_write(EC_HLBL, led * led_exp_hlbl[ind]);
+ if (ret >= 0)
+ ret =
+ ec_write(EC_HLCL, led * led_exp_hlcl[ind]);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* all others */
+ if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+ led, led_led_arg1[ind]))
return -EIO;
- } else if (led == 2 && bled_handle) {
- if (acpi_evalf(bled_handle, NULL, NULL, "vdd",
- bled_a, bled_b))
+ }
+ }
+
+ return 0;
+}
+
+static int beep_read(char *p)
+{
+ int len = 0;
+
+ if (!beep_handle)
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ else {
+ len += sprintf(p + len, "status:\t\tsupported\n");
+ len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
+ }
+
+ return len;
+}
+
+static int beep_write(char *buf)
+{
+ char *cmd;
+ int beep_cmd;
+
+ if (!beep_handle)
+ return -ENODEV;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
+ beep_cmd >= 0 && beep_cmd <= 17) {
+ /* beep_cmd set */
+ } else
+ return -EINVAL;
+ if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int acpi_ec_read(int i, u8 * p)
+{
+ int v;
+
+ if (ecrd_handle) {
+ if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
+ return 0;
+ *p = v;
+ } else {
+ if (ec_read(i, p) < 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int acpi_ec_write(int i, u8 v)
+{
+ if (ecwr_handle) {
+ if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
+ return 0;
+ } else {
+ if (ec_write(i, v) < 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int thermal_tmp_supported;
+static int thermal_updt_supported;
+
+static int thermal_init(void)
+{
+ /* temperatures not supported on 570, G4x, R30, R31, R32 */
+ thermal_tmp_supported = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+
+ /* 600e/x, 770e, 770x */
+ thermal_updt_supported = acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+
+ return 0;
+}
+
+static int thermal_read(char *p)
+{
+ int len = 0;
+
+ if (!thermal_tmp_supported)
+ len += sprintf(p + len, "temperatures:\tnot supported\n");
+ else {
+ int i, t;
+ char tmpi[] = "TMPi";
+ s8 tmp[8];
+
+ if (thermal_updt_supported)
+ if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+ return -EIO;
+
+ for (i = 0; i < 8; i++) {
+ tmpi[3] = '0' + i;
+ if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+ return -EIO;
+ if (thermal_updt_supported)
+ tmp[i] = (t - 2732 + 5) / 10;
+ else
+ tmp[i] = t;
+ }
+
+ len += sprintf(p + len,
+ "temperatures:\t%d %d %d %d %d %d %d %d\n",
+ tmp[0], tmp[1], tmp[2], tmp[3],
+ tmp[4], tmp[5], tmp[6], tmp[7]);
+ }
+
+ return len;
+}
+
+static u8 ecdump_regs[256];
+
+static int ecdump_read(char *p)
+{
+ int len = 0;
+ int i, j;
+ u8 v;
+
+ len += sprintf(p + len, "EC "
+ " +00 +01 +02 +03 +04 +05 +06 +07"
+ " +08 +09 +0a +0b +0c +0d +0e +0f\n");
+ for (i = 0; i < 256; i += 16) {
+ len += sprintf(p + len, "EC 0x%02x:", i);
+ for (j = 0; j < 16; j++) {
+ if (!acpi_ec_read(i + j, &v))
+ break;
+ if (v != ecdump_regs[i + j])
+ len += sprintf(p + len, " *%02x", v);
+ else
+ len += sprintf(p + len, " %02x", v);
+ ecdump_regs[i + j] = v;
+ }
+ len += sprintf(p + len, "\n");
+ if (j != 16)
+ break;
+ }
+
+ /* These are way too dangerous to advertise openly... */
+#if 0
+ len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
+ " (<offset> is 00-ff, <value> is 00-ff)\n");
+ len += sprintf(p + len, "commands:\t0x<offset> <value> "
+ " (<offset> is 00-ff, <value> is 0-255)\n");
+#endif
+ return len;
+}
+
+static int ecdump_write(char *buf)
+{
+ char *cmd;
+ int i, v;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
+ /* i and v set */
+ } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
+ /* i and v set */
+ } else
+ return -EINVAL;
+ if (i >= 0 && i < 256 && v >= 0 && v < 256) {
+ if (!acpi_ec_write(i, v))
return -EIO;
} else
return -EINVAL;
}
return 0;
-}
-
-static int beep_read(struct ibm_struct *ibm, char *p)
+}
+
+static int brightness_offset = 0x31;
+
+static int brightness_read(char *p)
{
int len = 0;
+ u8 level;
- len += sprintf(p + len, "commands:\t<int>\n");
+ if (!acpi_ec_read(brightness_offset, &level)) {
+ len += sprintf(p + len, "level:\t\tunreadable\n");
+ } else {
+ len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
+ len += sprintf(p + len, "commands:\tup, down\n");
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-7)\n");
+ }
return len;
}
-static int beep_write(struct ibm_struct *ibm, char *buf)
+#define BRIGHTNESS_UP 4
+#define BRIGHTNESS_DOWN 5
+
+static int brightness_write(char *buf)
{
+ int cmos_cmd, inc, i;
+ u8 level;
+ int new_level;
char *cmd;
- int beep_cmd;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &beep_cmd) == 1) {
- /* beep_cmd set */
+ if (!acpi_ec_read(brightness_offset, &level))
+ return -EIO;
+ level &= 7;
+
+ if (strlencmp(cmd, "up") == 0) {
+ new_level = level == 7 ? 7 : level + 1;
+ } else if (strlencmp(cmd, "down") == 0) {
+ new_level = level == 0 ? 0 : level - 1;
+ } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
+ new_level >= 0 && new_level <= 7) {
+ /* new_level set */
+ } else
+ return -EINVAL;
+
+ cmos_cmd = new_level > level ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
+ inc = new_level > level ? 1 : -1;
+ for (i = level; i != new_level; i += inc) {
+ if (!cmos_eval(cmos_cmd))
+ return -EIO;
+ if (!acpi_ec_write(brightness_offset, i + inc))
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int volume_offset = 0x30;
+
+static int volume_read(char *p)
+{
+ int len = 0;
+ u8 level;
+
+ if (!acpi_ec_read(volume_offset, &level)) {
+ len += sprintf(p + len, "level:\t\tunreadable\n");
+ } else {
+ len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
+ len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
+ len += sprintf(p + len, "commands:\tup, down, mute\n");
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-15)\n");
+ }
+
+ return len;
+}
+
+#define VOLUME_DOWN 0
+#define VOLUME_UP 1
+#define VOLUME_MUTE 2
+
+static int volume_write(char *buf)
+{
+ int cmos_cmd, inc, i;
+ u8 level, mute;
+ int new_level, new_mute;
+ char *cmd;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (!acpi_ec_read(volume_offset, &level))
+ return -EIO;
+ new_mute = mute = level & 0x40;
+ new_level = level = level & 0xf;
+
+ if (strlencmp(cmd, "up") == 0) {
+ if (mute)
+ new_mute = 0;
+ else
+ new_level = level == 15 ? 15 : level + 1;
+ } else if (strlencmp(cmd, "down") == 0) {
+ if (mute)
+ new_mute = 0;
+ else
+ new_level = level == 0 ? 0 : level - 1;
+ } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
+ new_level >= 0 && new_level <= 15) {
+ /* new_level set */
+ } else if (strlencmp(cmd, "mute") == 0) {
+ new_mute = 0x40;
} else
return -EINVAL;
- if (!acpi_evalf(beep_handle, NULL, NULL, "vd", beep_cmd))
+ if (new_level != level) { /* mute doesn't change */
+ cmos_cmd = new_level > level ? VOLUME_UP : VOLUME_DOWN;
+ inc = new_level > level ? 1 : -1;
+
+ if (mute && (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, level)))
+ return -EIO;
+
+ for (i = level; i != new_level; i += inc)
+ if (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, i + inc))
+ return -EIO;
+
+ if (mute && (!cmos_eval(VOLUME_MUTE) ||
+ !acpi_ec_write(volume_offset,
+ new_level + mute)))
+ return -EIO;
+ }
+
+ if (new_mute != mute) { /* level doesn't change */
+ cmos_cmd = new_mute ? VOLUME_MUTE : VOLUME_UP;
+
+ if (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, level + new_mute))
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int fan_status_offset = 0x2f;
+static int fan_rpm_offset = 0x84;
+
+static int fan_read(char *p)
+{
+ int len = 0;
+ int s;
+ u8 lo, hi, status;
+
+ if (gfan_handle) {
+ /* 570, 600e/x, 770e, 770x */
+ if (!acpi_evalf(gfan_handle, &s, NULL, "d"))
return -EIO;
+
+ len += sprintf(p + len, "level:\t\t%d\n", s);
+ } else {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_read(fan_status_offset, &status))
+ len += sprintf(p + len, "status:\t\tunreadable\n");
+ else
+ len += sprintf(p + len, "status:\t\t%s\n",
+ enabled(status, 7));
+
+ if (!acpi_ec_read(fan_rpm_offset, &lo) ||
+ !acpi_ec_read(fan_rpm_offset + 1, &hi))
+ len += sprintf(p + len, "speed:\t\tunreadable\n");
+ else
+ len += sprintf(p + len, "speed:\t\t%d\n",
+ (hi << 8) + lo);
+ }
+
+ if (sfan_handle)
+ /* 570, 770x-JL */
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-7)\n");
+ if (!gfan_handle)
+ /* all except 570, 600e/x, 770e, 770x */
+ len += sprintf(p + len, "commands:\tenable, disable\n");
+ if (fans_handle)
+ /* X31, X40 */
+ len += sprintf(p + len, "commands:\tspeed <speed>"
+ " (<speed> is 0-65535)\n");
+
+ return len;
+}
+
+static int fan_write(char *buf)
+{
+ char *cmd;
+ int level, speed;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sfan_handle &&
+ sscanf(cmd, "level %d", &level) == 1 &&
+ level >= 0 && level <= 7) {
+ /* 570, 770x-JL */
+ if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+ return -EIO;
+ } else if (!gfan_handle && strlencmp(cmd, "enable") == 0) {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_write(fan_status_offset, 0x80))
+ return -EIO;
+ } else if (!gfan_handle && strlencmp(cmd, "disable") == 0) {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_write(fan_status_offset, 0x00))
+ return -EIO;
+ } else if (fans_handle &&
+ sscanf(cmd, "speed %d", &speed) == 1 &&
+ speed >= 0 && speed <= 65535) {
+ /* X31, X40 */
+ if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
+ speed, speed, speed))
+ return -EIO;
+ } else
+ return -EINVAL;
}
return 0;
-}
-
+}
+
static struct ibm_struct ibms[] = {
{
- .name = "driver",
- .init = driver_init,
- .read = driver_read,
- },
+ .name = "driver",
+ .init = driver_init,
+ .read = driver_read,
+ },
+ {
+ .name = "hotkey",
+ .hid = IBM_HKEY_HID,
+ .init = hotkey_init,
+ .read = hotkey_read,
+ .write = hotkey_write,
+ .exit = hotkey_exit,
+ .notify = hotkey_notify,
+ .handle = &hkey_handle,
+ .type = ACPI_DEVICE_NOTIFY,
+ },
+ {
+ .name = "bluetooth",
+ .init = bluetooth_init,
+ .read = bluetooth_read,
+ .write = bluetooth_write,
+ },
+ {
+ .name = "video",
+ .init = video_init,
+ .read = video_read,
+ .write = video_write,
+ .exit = video_exit,
+ },
{
- .name = "hotkey",
- .hid = "IBM0068",
- .init = hotkey_init,
- .read = hotkey_read,
- .write = hotkey_write,
- .exit = hotkey_exit,
- .notify = hotkey_notify,
- .handle = &hkey_handle,
- .type = ACPI_DEVICE_NOTIFY,
- },
+ .name = "light",
+ .init = light_init,
+ .read = light_read,
+ .write = light_write,
+ },
{
- .name = "bluetooth",
- .init = bluetooth_init,
- .read = bluetooth_read,
- .write = bluetooth_write,
- },
+ .name = "dock",
+ .read = dock_read,
+ .write = dock_write,
+ .notify = dock_notify,
+ .handle = &dock_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "video",
- .init = video_init,
- .read = video_read,
- .write = video_write,
- .exit = video_exit,
- },
+ .name = "dock",
+ .hid = IBM_PCI_HID,
+ .notify = dock_notify,
+ .handle = &pci_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "light",
- .init = light_init,
- .read = light_read,
- .write = light_write,
- },
+ .name = "bay",
+ .init = bay_init,
+ .read = bay_read,
+ .write = bay_write,
+ .notify = bay_notify,
+ .handle = &bay_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "dock",
- .read = dock_read,
- .write = dock_write,
- .notify = dock_notify,
- .handle = &dock_handle,
- .type = ACPI_SYSTEM_NOTIFY,
- },
+ .name = "cmos",
+ .read = cmos_read,
+ .write = cmos_write,
+ },
{
- .name = "bay",
- .init = bay_init,
- .read = bay_read,
- .write = bay_write,
- .notify = bay_notify,
- .handle = &bay_handle,
- .type = ACPI_SYSTEM_NOTIFY,
- },
+ .name = "led",
+ .init = led_init,
+ .read = led_read,
+ .write = led_write,
+ },
{
- .name = "cmos",
- .read = cmos_read,
- .write = cmos_write,
- .experimental = 1,
- },
+ .name = "beep",
+ .read = beep_read,
+ .write = beep_write,
+ },
{
- .name = "led",
- .read = led_read,
- .write = led_write,
- .experimental = 1,
- },
+ .name = "thermal",
+ .init = thermal_init,
+ .read = thermal_read,
+ },
{
- .name = "beep",
- .read = beep_read,
- .write = beep_write,
- .experimental = 1,
- },
+ .name = "ecdump",
+ .read = ecdump_read,
+ .write = ecdump_write,
+ .experimental = 1,
+ },
+ {
+ .name = "brightness",
+ .read = brightness_read,
+ .write = brightness_write,
+ .experimental = 1,
+ },
+ {
+ .name = "volume",
+ .read = volume_read,
+ .write = volume_write,
+ .experimental = 1,
+ },
+ {
+ .name = "fan",
+ .read = fan_read,
+ .write = fan_write,
+ .experimental = 1,
+ },
};
-#define NUM_IBMS (sizeof(ibms)/sizeof(ibms[0]))
static int dispatch_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct ibm_struct *ibm = (struct ibm_struct *)data;
int len;
-
+
if (!ibm || !ibm->read)
return -EINVAL;
- len = ibm->read(ibm, page);
+ len = ibm->read(page);
if (len < 0)
return len;
@@ -955,7 +1670,7 @@ static int dispatch_read(char *page, char **start, off_t off, int count,
return len;
}
-static int dispatch_write(struct file *file, const char __user *userbuf,
+static int dispatch_write(struct file *file, const char __user * userbuf,
unsigned long count, void *data)
{
struct ibm_struct *ibm = (struct ibm_struct *)data;
@@ -969,20 +1684,20 @@ static int dispatch_write(struct file *file, const char __user *userbuf,
if (!kernbuf)
return -ENOMEM;
- if (copy_from_user(kernbuf, userbuf, count)) {
+ if (copy_from_user(kernbuf, userbuf, count)) {
kfree(kernbuf);
- return -EFAULT;
+ return -EFAULT;
}
kernbuf[count] = 0;
strcat(kernbuf, ",");
- ret = ibm->write(ibm, kernbuf);
+ ret = ibm->write(kernbuf);
if (ret == 0)
ret = count;
kfree(kernbuf);
- return ret;
+ return ret;
}
static void dispatch_notify(acpi_handle handle, u32 event, void *data)
@@ -995,7 +1710,7 @@ static void dispatch_notify(acpi_handle handle, u32 event, void *data)
ibm->notify(ibm, event);
}
-static int setup_notify(struct ibm_struct *ibm)
+static int __init setup_notify(struct ibm_struct *ibm)
{
acpi_status status;
int ret;
@@ -1020,17 +1735,15 @@ static int setup_notify(struct ibm_struct *ibm)
return -ENODEV;
}
- ibm->notify_installed = 1;
-
return 0;
}
-static int ibmacpi_device_add(struct acpi_device *device)
+static int __init ibm_device_add(struct acpi_device *device)
{
return 0;
}
-static int register_driver(struct ibm_struct *ibm)
+static int __init register_driver(struct ibm_struct *ibm)
{
int ret;
@@ -1043,7 +1756,7 @@ static int register_driver(struct ibm_struct *ibm)
memset(ibm->driver, 0, sizeof(struct acpi_driver));
sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name);
ibm->driver->ids = ibm->hid;
- ibm->driver->ops.add = &ibmacpi_device_add;
+ ibm->driver->ops.add = &ibm_device_add;
ret = acpi_bus_register_driver(ibm->driver);
if (ret < 0) {
@@ -1055,7 +1768,7 @@ static int register_driver(struct ibm_struct *ibm)
return ret;
}
-static int ibm_init(struct ibm_struct *ibm)
+static int __init ibm_init(struct ibm_struct *ibm)
{
int ret;
struct proc_dir_entry *entry;
@@ -1071,31 +1784,34 @@ static int ibm_init(struct ibm_struct *ibm)
}
if (ibm->init) {
- ret = ibm->init(ibm);
+ ret = ibm->init();
if (ret != 0)
return ret;
ibm->init_called = 1;
}
- entry = create_proc_entry(ibm->name, S_IFREG | S_IRUGO | S_IWUSR,
- proc_dir);
- if (!entry) {
- printk(IBM_ERR "unable to create proc entry %s\n", ibm->name);
- return -ENODEV;
- }
- entry->owner = THIS_MODULE;
- ibm->proc_created = 1;
-
- entry->data = ibm;
- if (ibm->read)
+ if (ibm->read) {
+ entry = create_proc_entry(ibm->name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ proc_dir);
+ if (!entry) {
+ printk(IBM_ERR "unable to create proc entry %s\n",
+ ibm->name);
+ return -ENODEV;
+ }
+ entry->owner = THIS_MODULE;
+ entry->data = ibm;
entry->read_proc = &dispatch_read;
- if (ibm->write)
- entry->write_proc = &dispatch_write;
+ if (ibm->write)
+ entry->write_proc = &dispatch_write;
+ ibm->proc_created = 1;
+ }
if (ibm->notify) {
ret = setup_notify(ibm);
if (ret < 0)
return ret;
+ ibm->notify_installed = 1;
}
return 0;
@@ -1111,7 +1827,7 @@ static void ibm_exit(struct ibm_struct *ibm)
remove_proc_entry(ibm->name, proc_dir);
if (ibm->init_called && ibm->exit)
- ibm->exit(ibm);
+ ibm->exit();
if (ibm->driver_registered) {
acpi_bus_unregister_driver(ibm->driver);
@@ -1119,60 +1835,66 @@ static void ibm_exit(struct ibm_struct *ibm)
}
}
-static int ibm_handle_init(char *name,
- acpi_handle *handle, acpi_handle parent,
- char **paths, int num_paths, int required)
+static void __init ibm_handle_init(char *name,
+ acpi_handle * handle, acpi_handle parent,
+ char **paths, int num_paths, char **path)
{
int i;
acpi_status status;
- for (i=0; i<num_paths; i++) {
+ for (i = 0; i < num_paths; i++) {
status = acpi_get_handle(parent, paths[i], handle);
- if (ACPI_SUCCESS(status))
- return 0;
- }
-
- *handle = NULL;
-
- if (required) {
- printk(IBM_ERR "%s object not found\n", name);
- return -1;
+ if (ACPI_SUCCESS(status)) {
+ *path = paths[i];
+ return;
+ }
}
- return 0;
+ *handle = NULL;
}
-#define IBM_HANDLE_INIT(object, required) \
+#define IBM_HANDLE_INIT(object) \
ibm_handle_init(#object, &object##_handle, *object##_parent, \
- object##_paths, sizeof(object##_paths)/sizeof(char*), required)
-
+ object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
static int set_ibm_param(const char *val, struct kernel_param *kp)
{
unsigned int i;
- char arg_with_comma[32];
-
- if (strlen(val) > 30)
- return -ENOSPC;
- strcpy(arg_with_comma, val);
- strcat(arg_with_comma, ",");
+ for (i = 0; i < ARRAY_SIZE(ibms); i++)
+ if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) {
+ if (strlen(val) > sizeof(ibms[i].param) - 2)
+ return -ENOSPC;
+ strcpy(ibms[i].param, val);
+ strcat(ibms[i].param, ",");
+ return 0;
+ }
- for (i=0; i<NUM_IBMS; i++)
- if (strcmp(ibms[i].name, kp->name) == 0)
- return ibms[i].write(&ibms[i], arg_with_comma);
- BUG();
return -EINVAL;
}
#define IBM_PARAM(feature) \
module_param_call(feature, set_ibm_param, NULL, NULL, 0)
+IBM_PARAM(hotkey);
+IBM_PARAM(bluetooth);
+IBM_PARAM(video);
+IBM_PARAM(light);
+IBM_PARAM(dock);
+IBM_PARAM(bay);
+IBM_PARAM(cmos);
+IBM_PARAM(led);
+IBM_PARAM(beep);
+IBM_PARAM(ecdump);
+IBM_PARAM(brightness);
+IBM_PARAM(volume);
+IBM_PARAM(fan);
+
static void acpi_ibm_exit(void)
{
int i;
- for (i=NUM_IBMS-1; i>=0; i--)
+ for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
ibm_exit(&ibms[i]);
remove_proc_entry(IBM_DIR, acpi_root_dir);
@@ -1185,30 +1907,40 @@ static int __init acpi_ibm_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
- printk(IBM_ERR "Using generic hotkey driver\n");
- return -ENODEV;
- }
- /* these handles are required */
- if (IBM_HANDLE_INIT(ec, 1) < 0 ||
- IBM_HANDLE_INIT(hkey, 1) < 0 ||
- IBM_HANDLE_INIT(vid, 1) < 0 ||
- IBM_HANDLE_INIT(beep, 1) < 0)
+ if (!acpi_specific_hotkey_enabled) {
+ printk(IBM_ERR "using generic hotkey driver\n");
return -ENODEV;
+ }
- /* these handles have alternatives */
- IBM_HANDLE_INIT(lght, 0);
- if (IBM_HANDLE_INIT(cmos, !lght_handle) < 0)
- return -ENODEV;
- IBM_HANDLE_INIT(sysl, 0);
- if (IBM_HANDLE_INIT(led, !sysl_handle) < 0)
+ /* ec is required because many other handles are relative to it */
+ IBM_HANDLE_INIT(ec);
+ if (!ec_handle) {
+ printk(IBM_ERR "ec object not found\n");
return -ENODEV;
+ }
/* these handles are not required */
- IBM_HANDLE_INIT(dock, 0);
- IBM_HANDLE_INIT(bay, 0);
- IBM_HANDLE_INIT(bayej, 0);
- IBM_HANDLE_INIT(bled, 0);
+ IBM_HANDLE_INIT(vid);
+ IBM_HANDLE_INIT(vid2);
+ IBM_HANDLE_INIT(ledb);
+ IBM_HANDLE_INIT(led);
+ IBM_HANDLE_INIT(hkey);
+ IBM_HANDLE_INIT(lght);
+ IBM_HANDLE_INIT(cmos);
+ IBM_HANDLE_INIT(dock);
+ IBM_HANDLE_INIT(pci);
+ IBM_HANDLE_INIT(bay);
+ if (bay_handle)
+ IBM_HANDLE_INIT(bay_ej);
+ IBM_HANDLE_INIT(bay2);
+ if (bay2_handle)
+ IBM_HANDLE_INIT(bay2_ej);
+ IBM_HANDLE_INIT(beep);
+ IBM_HANDLE_INIT(ecrd);
+ IBM_HANDLE_INIT(ecwr);
+ IBM_HANDLE_INIT(fans);
+ IBM_HANDLE_INIT(gfan);
+ IBM_HANDLE_INIT(sfan);
proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
if (!proc_dir) {
@@ -1216,9 +1948,11 @@ static int __init acpi_ibm_init(void)
return -ENODEV;
}
proc_dir->owner = THIS_MODULE;
-
- for (i=0; i<NUM_IBMS; i++) {
+
+ for (i = 0; i < ARRAY_SIZE(ibms); i++) {
ret = ibm_init(&ibms[i]);
+ if (ret >= 0 && *ibms[i].param)
+ ret = ibms[i].write(ibms[i].param);
if (ret < 0) {
acpi_ibm_exit();
return ret;
@@ -1230,17 +1964,3 @@ static int __init acpi_ibm_init(void)
module_init(acpi_ibm_init);
module_exit(acpi_ibm_exit);
-
-MODULE_AUTHOR("Borislav Deianov");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_LICENSE("GPL");
-
-IBM_PARAM(hotkey);
-IBM_PARAM(bluetooth);
-IBM_PARAM(video);
-IBM_PARAM(light);
-IBM_PARAM(dock);
-IBM_PARAM(bay);
-IBM_PARAM(cmos);
-IBM_PARAM(led);
-IBM_PARAM(beep);
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index 61ea70742d49..e928e8c2c6ec 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -30,12 +30,11 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("acpi_motherboard")
+ACPI_MODULE_NAME("acpi_motherboard")
/* Dell use PNP0C01 instead of PNP0C02 */
#define ACPI_MB_HID1 "PNP0C01"
#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
@@ -44,15 +43,12 @@ ACPI_MODULE_NAME ("acpi_motherboard")
#define IS_RESERVED_ADDR(base, len) \
(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
&& ((base) + (len) > PCIBIOS_MIN_IO))
-
/*
* 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.
*/
-
-static acpi_status
-acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
+static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
{
struct resource *requested_res = NULL;
@@ -63,22 +59,32 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
if (io_res->min_base_address != io_res->max_base_address)
return_VALUE(AE_OK);
- if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
- io_res->min_base_address,
- io_res->min_base_address + io_res->range_length));
- requested_res = request_region(io_res->min_base_address,
- io_res->range_length, "motherboard");
+ if (IS_RESERVED_ADDR
+ (io_res->min_base_address, io_res->range_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Motherboard resources 0x%08x - 0x%08x\n",
+ io_res->min_base_address,
+ io_res->min_base_address +
+ io_res->range_length));
+ requested_res =
+ request_region(io_res->min_base_address,
+ io_res->range_length, "motherboard");
}
} else if (res->id == ACPI_RSTYPE_FIXED_IO) {
- struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
-
- if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
- fixed_io_res->base_address,
- fixed_io_res->base_address + fixed_io_res->range_length));
- requested_res = request_region(fixed_io_res->base_address,
- fixed_io_res->range_length, "motherboard");
+ struct acpi_resource_fixed_io *fixed_io_res =
+ &res->data.fixed_io;
+
+ if (IS_RESERVED_ADDR
+ (fixed_io_res->base_address, fixed_io_res->range_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Motherboard resources 0x%08x - 0x%08x\n",
+ fixed_io_res->base_address,
+ fixed_io_res->base_address +
+ fixed_io_res->range_length));
+ requested_res =
+ request_region(fixed_io_res->base_address,
+ fixed_io_res->range_length,
+ "motherboard");
}
} else {
/* Memory mapped IO? */
@@ -89,72 +95,70 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
return_VALUE(AE_OK);
}
-static int acpi_motherboard_add (struct acpi_device *device)
+static int acpi_motherboard_add(struct acpi_device *device)
{
if (!device)
return -EINVAL;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- acpi_reserve_io_ranges, NULL);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ acpi_reserve_io_ranges, NULL);
return 0;
}
static struct acpi_driver acpi_motherboard_driver1 = {
- .name = "motherboard",
- .class = "",
- .ids = ACPI_MB_HID1,
- .ops = {
- .add = acpi_motherboard_add,
- },
+ .name = "motherboard",
+ .class = "",
+ .ids = ACPI_MB_HID1,
+ .ops = {
+ .add = acpi_motherboard_add,
+ },
};
static struct acpi_driver acpi_motherboard_driver2 = {
- .name = "motherboard",
- .class = "",
- .ids = ACPI_MB_HID2,
- .ops = {
- .add = acpi_motherboard_add,
- },
+ .name = "motherboard",
+ .class = "",
+ .ids = ACPI_MB_HID2,
+ .ops = {
+ .add = acpi_motherboard_add,
+ },
};
-static void __init
-acpi_reserve_resources (void)
+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");
+ request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
+ acpi_gbl_FADT->pm1_evt_len, "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_gbl_FADT->pm1_evt_len, "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");
+ request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
+ acpi_gbl_FADT->pm1_cnt_len, "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");
+ request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
+ acpi_gbl_FADT->pm1_cnt_len, "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");
+ request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "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_gbl_FADT->pm2_cnt_len, "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))
+ !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
request_region(acpi_gbl_FADT->xgpe0_blk.address,
- acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+ acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
- !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+ !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
request_region(acpi_gbl_FADT->xgpe1_blk.address,
- acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+ acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
}
static int __init acpi_motherboard_init(void)
@@ -166,7 +170,7 @@ static int __init acpi_motherboard_init(void)
* This module must run after scan.c
*/
if (!acpi_disabled)
- acpi_reserve_resources ();
+ acpi_reserve_resources();
return 0;
}
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index ece7a9dedd5c..edfbe34600f5 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsaccess")
-
+ACPI_MODULE_NAME("nsaccess")
/*******************************************************************************
*
@@ -65,24 +62,19 @@
* MUTEX: Locks namespace for entire execution
*
******************************************************************************/
-
-acpi_status
-acpi_ns_root_initialize (
- void)
+acpi_status acpi_ns_root_initialize(void)
{
- acpi_status status;
+ acpi_status status;
const struct acpi_predefined_names *init_val = NULL;
- struct acpi_namespace_node *new_node;
- union acpi_operand_object *obj_desc;
- acpi_string val = NULL;
-
-
- ACPI_FUNCTION_TRACE ("ns_root_initialize");
+ struct acpi_namespace_node *new_node;
+ union acpi_operand_object *obj_desc;
+ acpi_string val = NULL;
+ ACPI_FUNCTION_TRACE("ns_root_initialize");
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -102,24 +94,26 @@ acpi_ns_root_initialize (
/* Enter the pre-defined names in the name table */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Entering predefined entries into namespace\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "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") && !acpi_gbl_create_osi_method) {
+ if (!ACPI_STRCMP(init_val->name, "_OSI")
+ && !acpi_gbl_create_osi_method) {
continue;
}
- status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
- ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
- NULL, &new_node);
+ status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
+ ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_NO_UPSEARCH, NULL, &new_node);
- if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not create predefined name %s, %s\n",
- init_val->name, acpi_format_exception (status)));
+ if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not create predefined name %s, %s\n",
+ init_val->name,
+ acpi_format_exception(status)));
}
/*
@@ -128,11 +122,11 @@ acpi_ns_root_initialize (
* initial value, create the initial value.
*/
if (init_val->val) {
- status = acpi_os_predefined_override (init_val, &val);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not override predefined %s\n",
- init_val->name));
+ status = acpi_os_predefined_override(init_val, &val);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not override predefined %s\n",
+ init_val->name));
}
if (!val) {
@@ -143,7 +137,8 @@ acpi_ns_root_initialize (
* Entry requests an initial value, allocate a
* descriptor for it.
*/
- obj_desc = acpi_ut_create_internal_object (init_val->type);
+ obj_desc =
+ acpi_ut_create_internal_object(init_val->type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -156,55 +151,62 @@ acpi_ns_root_initialize (
*/
switch (init_val->type) {
case ACPI_TYPE_METHOD:
- obj_desc->method.param_count = (u8) ACPI_TO_INTEGER (val);
+ obj_desc->method.param_count =
+ (u8) ACPI_TO_INTEGER(val);
obj_desc->common.flags |= AOPOBJ_DATA_VALID;
-#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
+#if defined (ACPI_ASL_COMPILER)
- /*
- * i_aSL Compiler cheats by putting parameter count
- * in the owner_iD
- */
- new_node->owner_id = obj_desc->method.param_count;
+ /* save the parameter count for the i_aSL compiler */
+
+ new_node->value = obj_desc->method.param_count;
#else
/* Mark this as a very SPECIAL method */
- obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
- obj_desc->method.implementation = acpi_ut_osi_implementation;
+ obj_desc->method.method_flags =
+ AML_METHOD_INTERNAL_ONLY;
+
+#ifndef ACPI_DUMP_APP
+ obj_desc->method.implementation =
+ acpi_ut_osi_implementation;
+#endif
#endif
break;
case ACPI_TYPE_INTEGER:
- obj_desc->integer.value = ACPI_TO_INTEGER (val);
+ obj_desc->integer.value = ACPI_TO_INTEGER(val);
break;
-
case ACPI_TYPE_STRING:
/*
* Build an object around the static string
*/
- obj_desc->string.length = (u32) ACPI_STRLEN (val);
+ obj_desc->string.length =
+ (u32) ACPI_STRLEN(val);
obj_desc->string.pointer = val;
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
-
case ACPI_TYPE_MUTEX:
obj_desc->mutex.node = new_node;
- obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER (val) - 1);
+ obj_desc->mutex.sync_level =
+ (u8) (ACPI_TO_INTEGER(val) - 1);
- if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
+ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) {
/*
* Create a counting semaphore for the
* global lock
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
- 1, &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
+ status =
+ acpi_os_create_semaphore
+ (ACPI_NO_UNIT_LIMIT, 1,
+ &obj_desc->mutex.semaphore);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference
+ (obj_desc);
goto unlock_and_exit;
}
@@ -212,56 +214,58 @@ acpi_ns_root_initialize (
* We just created the mutex for the
* global lock, save it
*/
- acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
- }
- else {
+ acpi_gbl_global_lock_semaphore =
+ obj_desc->mutex.semaphore;
+ } else {
/* Create a mutex */
- status = acpi_os_create_semaphore (1, 1,
- &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
+ status = acpi_os_create_semaphore(1, 1,
+ &obj_desc->
+ mutex.
+ semaphore);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference
+ (obj_desc);
goto unlock_and_exit;
}
}
break;
-
default:
- ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
- init_val->type));
- acpi_ut_remove_reference (obj_desc);
+ ACPI_REPORT_ERROR(("Unsupported initial type value %X\n", init_val->type));
+ acpi_ut_remove_reference(obj_desc);
obj_desc = NULL;
continue;
}
/* Store pointer to value descriptor in the Node */
- status = acpi_ns_attach_object (new_node, obj_desc,
- ACPI_GET_OBJECT_TYPE (obj_desc));
+ status = acpi_ns_attach_object(new_node, obj_desc,
+ ACPI_GET_OBJECT_TYPE
+ (obj_desc));
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* 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);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ns_get_node_by_path("\\_GPE", NULL,
+ ACPI_NS_NO_UPSEARCH,
+ &acpi_gbl_fadt_gpe_device);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_lookup
@@ -286,62 +290,57 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ns_lookup (
- union acpi_generic_state *scope_info,
- char *pathname,
- acpi_object_type type,
- acpi_interpreter_mode interpreter_mode,
- u32 flags,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **return_node)
+acpi_ns_lookup(union acpi_generic_state *scope_info,
+ char *pathname,
+ acpi_object_type type,
+ acpi_interpreter_mode interpreter_mode,
+ u32 flags,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **return_node)
{
- acpi_status status;
- char *path = pathname;
- struct acpi_namespace_node *prefix_node;
- struct acpi_namespace_node *current_node = NULL;
- struct acpi_namespace_node *this_node = NULL;
- u32 num_segments;
- u32 num_carats;
- acpi_name simple_name;
- 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);
-
-
- ACPI_FUNCTION_TRACE ("ns_lookup");
-
+ acpi_status status;
+ char *path = pathname;
+ struct acpi_namespace_node *prefix_node;
+ struct acpi_namespace_node *current_node = NULL;
+ struct acpi_namespace_node *this_node = NULL;
+ u32 num_segments;
+ u32 num_carats;
+ acpi_name simple_name;
+ 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);
+
+ ACPI_FUNCTION_TRACE("ns_lookup");
if (!return_node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
acpi_gbl_ns_lookup_count++;
*return_node = ACPI_ENTRY_NOT_FOUND;
if (!acpi_gbl_root_node) {
- return_ACPI_STATUS (AE_NO_NAMESPACE);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
/*
* Get the prefix scope.
* A null scope means use the root scope
*/
- if ((!scope_info) ||
- (!scope_info->scope.node)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Null scope prefix, using root node (%p)\n",
- acpi_gbl_root_node));
+ if ((!scope_info) || (!scope_info->scope.node)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Null scope prefix, using root node (%p)\n",
+ acpi_gbl_root_node));
prefix_node = acpi_gbl_root_node;
- }
- else {
+ } else {
prefix_node = scope_info->scope.node;
- if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
- prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name(prefix_node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
@@ -349,9 +348,9 @@ acpi_ns_lookup (
* 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);
+ while (!acpi_ns_opens_scope(prefix_node->type) &&
+ prefix_node->type != ACPI_TYPE_ANY) {
+ prefix_node = acpi_ns_get_parent_node(prefix_node);
}
}
@@ -366,13 +365,13 @@ acpi_ns_lookup (
/* A Null name_path is allowed and refers to the root */
num_segments = 0;
- this_node = acpi_gbl_root_node;
- path = "";
+ this_node = acpi_gbl_root_node;
+ path = "";
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Null Pathname (Zero segments), Flags=%X\n", flags));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Null Pathname (Zero segments), Flags=%X\n",
+ flags));
+ } else {
/*
* Name pointer is valid (and must be in internal name format)
*
@@ -396,15 +395,16 @@ acpi_ns_lookup (
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Path is absolute from root [%p]\n", this_node));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Path is absolute from root [%p]\n",
+ this_node));
+ } else {
/* Pathname is relative to current scope, start there */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching relative to prefix scope [%4.4s] (%p)\n",
- acpi_ut_get_node_name (prefix_node), prefix_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching relative to prefix scope [%4.4s] (%p)\n",
+ acpi_ut_get_node_name(prefix_node),
+ prefix_node));
/*
* Handle multiple Parent Prefixes (carat) by just getting
@@ -425,20 +425,20 @@ acpi_ns_lookup (
/* Backup to the parent node */
num_carats++;
- this_node = acpi_ns_get_parent_node (this_node);
+ this_node = acpi_ns_get_parent_node(this_node);
if (!this_node) {
/* Current scope has no parent scope */
- ACPI_REPORT_ERROR (
- ("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_REPORT_ERROR(("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
}
if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Search scope is [%4.4s], path has %d carat(s)\n",
- acpi_ut_get_node_name (this_node), num_carats));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Search scope is [%4.4s], path has %d carat(s)\n",
+ acpi_ut_get_node_name
+ (this_node), num_carats));
}
}
@@ -464,9 +464,9 @@ acpi_ns_lookup (
num_segments = 0;
type = this_node->type;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Prefix-only Pathname (Zero name segments), Flags=%X\n",
- flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Prefix-only Pathname (Zero name segments), Flags=%X\n",
+ flags));
break;
case AML_DUAL_NAME_PREFIX:
@@ -480,8 +480,9 @@ acpi_ns_lookup (
num_segments = 2;
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Dual Pathname (2 segments, Flags=%X)\n", flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Dual Pathname (2 segments, Flags=%X)\n",
+ flags));
break;
case AML_MULTI_NAME_PREFIX_OP:
@@ -493,12 +494,12 @@ acpi_ns_lookup (
/* Extract segment count, point to first name segment */
path++;
- num_segments = (u32) (u8) *path;
+ num_segments = (u32) (u8) * path;
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Multi Pathname (%d Segments, Flags=%X) \n",
- num_segments, flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Multi Pathname (%d Segments, Flags=%X) \n",
+ num_segments, flags));
break;
default:
@@ -508,15 +509,15 @@ acpi_ns_lookup (
*/
num_segments = 1;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Simple Pathname (1 segment, Flags=%X)\n", flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Simple Pathname (1 segment, Flags=%X)\n",
+ flags));
break;
}
- ACPI_DEBUG_EXEC (acpi_ns_print_pathname (num_segments, path));
+ ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path));
}
-
/*
* Search namespace for each segment of the name. Loop through and
* verify (or add to the namespace) each name segment.
@@ -540,7 +541,7 @@ acpi_ns_lookup (
* requested it AND we have a single, non-fully-qualified name_seg
*/
if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
- (flags & ACPI_NS_SEARCH_PARENT)) {
+ (flags & ACPI_NS_SEARCH_PARENT)) {
local_flags |= ACPI_NS_SEARCH_PARENT;
}
@@ -553,24 +554,28 @@ acpi_ns_lookup (
/* Extract one ACPI name from the front of the pathname */
- ACPI_MOVE_32_TO_32 (&simple_name, path);
+ ACPI_MOVE_32_TO_32(&simple_name, path);
/* Try to find the single (4 character) ACPI name */
- status = acpi_ns_search_and_enter (simple_name, walk_state, current_node,
- interpreter_mode, this_search_type, local_flags, &this_node);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ns_search_and_enter(simple_name, walk_state,
+ current_node, interpreter_mode,
+ this_search_type, local_flags,
+ &this_node);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
/* Name not found in ACPI namespace */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] not found in scope [%4.4s] %p\n",
- (char *) &simple_name, (char *) &current_node->name,
- current_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] not found in scope [%4.4s] %p\n",
+ (char *)&simple_name,
+ (char *)&current_node->name,
+ current_node));
}
*return_node = this_node;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
@@ -586,19 +591,16 @@ acpi_ns_lookup (
*
* Then we have a type mismatch. Just warn and ignore it.
*/
- if ((num_segments == 0) &&
- (type_to_check_for != ACPI_TYPE_ANY) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
- (this_node->type != ACPI_TYPE_ANY) &&
- (this_node->type != type_to_check_for)) {
+ if ((num_segments == 0) &&
+ (type_to_check_for != ACPI_TYPE_ANY) &&
+ (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
+ (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
+ (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_REPORT_WARNING (
- ("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n",
- (char *) &simple_name, acpi_ut_get_type_name (this_node->type),
- acpi_ut_get_type_name (type_to_check_for)));
+ ACPI_REPORT_WARNING(("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n", (char *)&simple_name, acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(type_to_check_for)));
}
/*
@@ -624,15 +626,16 @@ acpi_ns_lookup (
* If entry is a type which opens a scope, push the new scope on the
* scope stack.
*/
- if (acpi_ns_opens_scope (type)) {
- status = acpi_ds_scope_stack_push (this_node, type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (acpi_ns_opens_scope(type)) {
+ status =
+ acpi_ds_scope_stack_push(this_node, type,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
*return_node = this_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 5653a19d7172..cc7a85f8cfe6 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -41,20 +41,14 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsalloc")
+ACPI_MODULE_NAME("nsalloc")
/* Local prototypes */
-
-static void
-acpi_ns_remove_reference (
- struct acpi_namespace_node *node);
-
+static void acpi_ns_remove_reference(struct acpi_namespace_node *node);
/*******************************************************************************
*
@@ -68,31 +62,26 @@ acpi_ns_remove_reference (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_create_node (
- u32 name)
+struct acpi_namespace_node *acpi_ns_create_node(u32 name)
{
- struct acpi_namespace_node *node;
-
+ 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_MEM_CALLOCATE(sizeof(struct acpi_namespace_node));
if (!node) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
- node->name.integer = name;
+ node->name.integer = name;
node->reference_count = 1;
- ACPI_SET_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED);
+ ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
- return_PTR (node);
+ return_PTR(node);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_node
@@ -105,19 +94,15 @@ acpi_ns_create_node (
*
******************************************************************************/
-void
-acpi_ns_delete_node (
- struct acpi_namespace_node *node)
+void acpi_ns_delete_node(struct acpi_namespace_node *node)
{
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *prev_node;
- struct acpi_namespace_node *next_node;
-
+ struct acpi_namespace_node *parent_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);
+ parent_node = acpi_ns_get_parent_node(node);
prev_node = NULL;
next_node = parent_node->child;
@@ -136,32 +121,29 @@ acpi_ns_delete_node (
if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
}
- }
- else {
+ } else {
/* 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;
- }
- else { /* Link peer list to parent */
+ } else { /* Link peer list to parent */
parent_node->child = next_node->peer;
}
}
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
/*
* Detach an object if there is one then delete the node
*/
- acpi_ns_detach_object (node);
- ACPI_MEM_FREE (node);
+ acpi_ns_detach_object(node);
+ ACPI_MEM_FREE(node);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_install_node
@@ -176,30 +158,20 @@ acpi_ns_delete_node (
* DESCRIPTION: Initialize a new namespace node and install it amongst
* its peers.
*
- * Note: Current namespace lookup is linear search. However, the
- * nodes are linked in alphabetical order to 1) put all reserved
- * names (start with underscore) first, and to 2) make a readable
- * namespace dump.
+ * Note: Current namespace lookup is linear search. This appears
+ * to be sufficient as namespace searches consume only a small
+ * fraction of the execution time of the ACPI subsystem.
*
******************************************************************************/
-void
-acpi_ns_install_node (
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *parent_node, /* Parent */
- struct acpi_namespace_node *node, /* New Child*/
- acpi_object_type type)
+void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */
+ struct acpi_namespace_node *node, /* New Child */
+ acpi_object_type type)
{
- u16 owner_id = 0;
- struct acpi_namespace_node *child_node;
-#ifdef ACPI_ALPHABETIC_NAMESPACE
-
- struct acpi_namespace_node *previous_child_node;
-#endif
-
-
- ACPI_FUNCTION_TRACE ("ns_install_node");
+ acpi_owner_id owner_id = 0;
+ struct acpi_namespace_node *child_node;
+ ACPI_FUNCTION_TRACE("ns_install_node");
/*
* Get the owner ID from the Walk state
@@ -217,59 +189,7 @@ acpi_ns_install_node (
parent_node->child = node;
node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
- }
- else {
-#ifdef ACPI_ALPHABETIC_NAMESPACE
- /*
- * Walk the list whilst searching for the correct
- * alphabetic placement.
- */
- previous_child_node = NULL;
- while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node),
- acpi_ut_get_node_name (node)) < 0) {
- if (child_node->flags & ANOBJ_END_OF_PEER_LIST) {
- /* Last peer; Clear end-of-list flag */
-
- child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
-
- /* This node is the new peer to the child node */
-
- child_node->peer = node;
-
- /* This node is the new end-of-list */
-
- node->flags |= ANOBJ_END_OF_PEER_LIST;
- node->peer = parent_node;
- break;
- }
-
- /* Get next peer */
-
- previous_child_node = child_node;
- child_node = child_node->peer;
- }
-
- /* Did the node get inserted at the end-of-list? */
-
- if (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
- /*
- * Loop above terminated without reaching the end-of-list.
- * Insert the new node at the current location
- */
- if (previous_child_node) {
- /* Insert node alphabetically */
-
- node->peer = child_node;
- previous_child_node->peer = node;
- }
- else {
- /* Insert node alphabetically at start of list */
-
- node->peer = child_node;
- parent_node->child = node;
- }
- }
-#else
+ } else {
while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
child_node = child_node->peer;
}
@@ -279,9 +199,8 @@ acpi_ns_install_node (
/* Clear end-of-list flag */
child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
- node->flags |= ANOBJ_END_OF_PEER_LIST;
+ node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
-#endif
}
/* Init the new entry */
@@ -289,24 +208,25 @@ acpi_ns_install_node (
node->owner_id = owner_id;
node->type = (u8) type;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
- acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
- acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
- parent_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(node->type), node, owner_id,
+ acpi_ut_get_node_name(parent_node),
+ 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) {
+ while ((node = acpi_ns_get_parent_node(node)) != NULL) {
node->reference_count++;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_children
@@ -320,18 +240,14 @@ acpi_ns_install_node (
*
******************************************************************************/
-void
-acpi_ns_delete_children (
- struct acpi_namespace_node *parent_node)
+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);
+ 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);
if (!parent_node) {
return_VOID;
@@ -350,48 +266,48 @@ acpi_ns_delete_children (
do {
/* Get the things we need */
- next_node = child_node->peer;
- flags = child_node->flags;
+ next_node = child_node->peer;
+ flags = child_node->flags;
/* Grandchildren should have all been deleted already */
if (child_node->child) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
- parent_node, child_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Found a grandchild! P=%p C=%p\n",
+ parent_node, child_node));
}
/* Now we can free this child object */
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
- child_node, acpi_gbl_current_node_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Object %p, Remaining %X\n", child_node,
+ acpi_gbl_current_node_count));
/*
* Detach an object if there is one, then free the child node
*/
- acpi_ns_detach_object (child_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) {
+ 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_REPORT_WARNING ((
- "Existing references (%d) on node being deleted (%p)\n",
- child_node->reference_count, child_node));
+ ACPI_REPORT_WARNING(("Existing references (%d) on node being deleted (%p)\n", child_node->reference_count, child_node));
}
/* Now we can delete the node */
- ACPI_MEM_FREE (child_node);
+ ACPI_MEM_FREE(child_node);
/* And move on to the next child in the list */
@@ -399,7 +315,6 @@ acpi_ns_delete_children (
} while (!(flags & ANOBJ_END_OF_PEER_LIST));
-
/* Clear the parent's child pointer */
parent_node->child = NULL;
@@ -407,7 +322,6 @@ acpi_ns_delete_children (
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_namespace_subtree
@@ -421,16 +335,12 @@ acpi_ns_delete_children (
*
******************************************************************************/
-void
-acpi_ns_delete_namespace_subtree (
- struct acpi_namespace_node *parent_node)
+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");
+ struct acpi_namespace_node *child_node = NULL;
+ u32 level = 1;
+ ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree");
if (!parent_node) {
return_VOID;
@@ -443,16 +353,17 @@ acpi_ns_delete_namespace_subtree (
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);
+ acpi_ns_detach_object(child_node);
/* Check if this node has any children */
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this node,
* visit the node
@@ -461,8 +372,7 @@ acpi_ns_delete_namespace_subtree (
parent_node = child_node;
child_node = NULL;
}
- }
- else {
+ } else {
/*
* No more children of this parent node.
* Move up to the grandparent.
@@ -473,7 +383,7 @@ acpi_ns_delete_namespace_subtree (
* Now delete all of the children of this parent
* all at the same time.
*/
- acpi_ns_delete_children (parent_node);
+ acpi_ns_delete_children(parent_node);
/* New "last child" is this parent node */
@@ -481,14 +391,13 @@ acpi_ns_delete_namespace_subtree (
/* Move up the tree to the grandparent */
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_remove_reference
@@ -504,16 +413,12 @@ acpi_ns_delete_namespace_subtree (
*
******************************************************************************/
-static void
-acpi_ns_remove_reference (
- struct acpi_namespace_node *node)
+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 ();
+ 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
@@ -523,7 +428,7 @@ acpi_ns_remove_reference (
while (this_node) {
/* Prepare to move up to parent */
- parent_node = acpi_ns_get_parent_node (this_node);
+ parent_node = acpi_ns_get_parent_node(this_node);
/* Decrement the reference count on this node */
@@ -534,15 +439,14 @@ acpi_ns_remove_reference (
if (!this_node->reference_count) {
/* Delete all children and delete the node */
- acpi_ns_delete_children (this_node);
- acpi_ns_delete_node (this_node);
+ acpi_ns_delete_children(this_node);
+ acpi_ns_delete_node(this_node);
}
this_node = parent_node;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_namespace_by_owner
@@ -557,23 +461,23 @@ acpi_ns_remove_reference (
*
******************************************************************************/
-void
-acpi_ns_delete_namespace_by_owner (
- u16 owner_id)
+void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
{
- struct acpi_namespace_node *child_node;
- struct acpi_namespace_node *deletion_node;
- u32 level;
- struct acpi_namespace_node *parent_node;
-
+ struct acpi_namespace_node *child_node;
+ struct acpi_namespace_node *deletion_node;
+ 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;
+ }
- parent_node = acpi_gbl_root_node;
- child_node = NULL;
+ parent_node = acpi_gbl_root_node;
+ child_node = NULL;
deletion_node = NULL;
- level = 1;
+ level = 1;
/*
* Traverse the tree of nodes until we bubble back up
@@ -584,10 +488,12 @@ acpi_ns_delete_namespace_by_owner (
* Get the next child of this parent node. When child_node is NULL,
* the first child of the parent is returned
*/
- 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 (deletion_node) {
- acpi_ns_remove_reference (deletion_node);
+ acpi_ns_remove_reference(deletion_node);
deletion_node = NULL;
}
@@ -595,12 +501,13 @@ acpi_ns_delete_namespace_by_owner (
if (child_node->owner_id == owner_id) {
/* Found a matching child node - detach any attached object */
- acpi_ns_detach_object (child_node);
+ acpi_ns_detach_object(child_node);
}
/* Check if this node has any children */
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this node,
* visit the node
@@ -608,12 +515,10 @@ acpi_ns_delete_namespace_by_owner (
level++;
parent_node = child_node;
child_node = NULL;
- }
- else if (child_node->owner_id == owner_id) {
+ } else if (child_node->owner_id == owner_id) {
deletion_node = child_node;
}
- }
- else {
+ } else {
/*
* No more children of this parent node.
* Move up to the grandparent.
@@ -631,62 +536,9 @@ acpi_ns_delete_namespace_by_owner (
/* Move up the tree to the grandparent */
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
return_VOID;
}
-
-
-#ifdef ACPI_ALPHABETIC_NAMESPACE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_compare_names
- *
- * PARAMETERS: Name1 - First name to compare
- * Name2 - Second name to compare
- *
- * RETURN: value from strncmp
- *
- * DESCRIPTION: Compare two ACPI names. Names that are prefixed with an
- * underscore are forced to be alphabetically first.
- *
- ******************************************************************************/
-
-int
-acpi_ns_compare_names (
- char *name1,
- char *name2)
-{
- char reversed_name1[ACPI_NAME_SIZE];
- char reversed_name2[ACPI_NAME_SIZE];
- u32 i;
- u32 j;
-
-
- /*
- * Replace all instances of "underscore" with a value that is smaller so
- * that all names that are prefixed with underscore(s) are alphabetically
- * first.
- *
- * Reverse the name bytewise so we can just do a 32-bit compare instead
- * of a strncmp.
- */
- for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--) {
- reversed_name1[j] = name1[i];
- if (name1[i] == '_') {
- reversed_name1[j] = '*';
- }
-
- reversed_name2[j] = name2[i];
- if (name2[i] == '_') {
- reversed_name2[j] = '*';
- }
- }
-
- return (*(int *) reversed_name1 - *(int *) reversed_name2);
-}
-#endif
-
-
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 6c2aef0e0dd4..9faf1d5c86ed 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -41,31 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsdump")
+ACPI_MODULE_NAME("nsdump")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
-void
-acpi_ns_dump_root_devices (
- void);
+void acpi_ns_dump_root_devices(void);
static acpi_status
-acpi_ns_dump_one_device (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ns_dump_one_device(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
#endif
-
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*******************************************************************************
*
@@ -80,36 +71,38 @@ acpi_ns_dump_one_device (
*
******************************************************************************/
-void
-acpi_ns_print_pathname (
- u32 num_segments,
- char *pathname)
+void acpi_ns_print_pathname(u32 num_segments, char *pathname)
{
- ACPI_FUNCTION_NAME ("ns_print_pathname");
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ns_print_pathname");
- if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
+ if (!(acpi_dbg_level & ACPI_LV_NAMES)
+ || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
return;
}
/* Print the entire name */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "["));
while (num_segments) {
- acpi_os_printf ("%4.4s", pathname);
- pathname += ACPI_NAME_SIZE;
+ for (i = 0; i < 4; i++) {
+ ACPI_IS_PRINT(pathname[i]) ?
+ acpi_os_printf("%c", pathname[i]) :
+ acpi_os_printf("?");
+ }
+ pathname += ACPI_NAME_SIZE;
num_segments--;
if (num_segments) {
- acpi_os_printf (".");
+ acpi_os_printf(".");
}
}
- acpi_os_printf ("]\n");
+ acpi_os_printf("]\n");
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_pathname
@@ -127,15 +120,10 @@ acpi_ns_print_pathname (
******************************************************************************/
void
-acpi_ns_dump_pathname (
- acpi_handle handle,
- char *msg,
- u32 level,
- u32 component)
+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 */
@@ -145,12 +133,11 @@ acpi_ns_dump_pathname (
/* Convert handle to a full pathname and print it (with supplied message) */
- acpi_ns_print_node_pathname (handle, msg);
- acpi_os_printf ("\n");
+ acpi_ns_print_node_pathname(handle, msg);
+ acpi_os_printf("\n");
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_object
@@ -168,24 +155,19 @@ acpi_ns_dump_pathname (
******************************************************************************/
acpi_status
-acpi_ns_dump_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_dump_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- struct acpi_walk_info *info = (struct acpi_walk_info *) context;
- struct acpi_namespace_node *this_node;
- union acpi_operand_object *obj_desc = NULL;
- acpi_object_type obj_type;
- acpi_object_type type;
- u32 bytes_to_dump;
- u32 dbg_level;
- u32 i;
-
-
- ACPI_FUNCTION_NAME ("ns_dump_one_object");
+ struct acpi_walk_info *info = (struct acpi_walk_info *)context;
+ struct acpi_namespace_node *this_node;
+ union acpi_operand_object *obj_desc = NULL;
+ acpi_object_type obj_type;
+ acpi_object_type type;
+ u32 bytes_to_dump;
+ u32 dbg_level;
+ u32 i;
+ ACPI_FUNCTION_NAME("ns_dump_one_object");
/* Is output enabled? */
@@ -194,193 +176,215 @@ acpi_ns_dump_one_object (
}
if (!obj_handle) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
return (AE_OK);
}
- this_node = acpi_ns_map_handle_to_node (obj_handle);
+ this_node = acpi_ns_map_handle_to_node(obj_handle);
type = this_node->type;
/* Check if the owner matches */
- if ((info->owner_id != ACPI_UINT32_MAX) &&
- (info->owner_id != this_node->owner_id)) {
+ if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
+ (info->owner_id != this_node->owner_id)) {
return (AE_OK);
}
- /* Indent the object according to the level */
+ 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, " ");
+ acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");
- /* Check the node type and name */
+ /* Check the node type and name */
- if (type > ACPI_TYPE_LOCAL_MAX) {
- ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type));
- }
+ if (type > ACPI_TYPE_LOCAL_MAX) {
+ ACPI_REPORT_WARNING(("Invalid ACPI Type %08X\n", type));
+ }
+
+ if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
+ ACPI_REPORT_WARNING(("Invalid ACPI Name %08X\n",
+ this_node->name.integer));
+ }
- if (!acpi_ut_valid_acpi_name (this_node->name.integer)) {
- ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n",
- this_node->name.integer));
+ acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
}
/*
* Now we can print out the pertinent information
*/
- acpi_os_printf ("%4.4s %-12s %p ",
- acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node);
+ acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node);
dbg_level = acpi_dbg_level;
acpi_dbg_level = 0;
- obj_desc = acpi_ns_get_attached_object (this_node);
+ obj_desc = acpi_ns_get_attached_object(this_node);
acpi_dbg_level = dbg_level;
- switch (info->display_type) {
+ switch (info->display_type & ACPI_DISPLAY_MASK) {
case ACPI_DISPLAY_SUMMARY:
if (!obj_desc) {
/* No attached object, we are done */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return (AE_OK);
}
switch (type) {
case ACPI_TYPE_PROCESSOR:
- acpi_os_printf ("ID %X Len %.4X Addr %p\n",
- obj_desc->processor.proc_id, obj_desc->processor.length,
- (char *) obj_desc->processor.address);
+ acpi_os_printf("ID %X Len %.4X Addr %p\n",
+ obj_desc->processor.proc_id,
+ obj_desc->processor.length,
+ (char *)obj_desc->processor.address);
break;
-
case ACPI_TYPE_DEVICE:
- acpi_os_printf ("Notify Object: %p\n", obj_desc);
+ acpi_os_printf("Notify Object: %p\n", obj_desc);
break;
-
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Args %X Len %.4X Aml %p\n",
- (u32) obj_desc->method.param_count,
- obj_desc->method.aml_length, obj_desc->method.aml_start);
+ acpi_os_printf("Args %X Len %.4X Aml %p\n",
+ (u32) obj_desc->method.param_count,
+ obj_desc->method.aml_length,
+ obj_desc->method.aml_start);
break;
-
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("= %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("= %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.
+ value));
break;
-
case ACPI_TYPE_PACKAGE:
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf ("Elements %.2X\n",
- obj_desc->package.count);
- }
- else {
- acpi_os_printf ("[Length not yet evaluated]\n");
+ acpi_os_printf("Elements %.2X\n",
+ obj_desc->package.count);
+ } else {
+ acpi_os_printf("[Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_BUFFER:
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf ("Len %.2X",
- obj_desc->buffer.length);
+ acpi_os_printf("Len %.2X",
+ obj_desc->buffer.length);
/* Dump some of the buffer */
if (obj_desc->buffer.length > 0) {
- acpi_os_printf (" =");
- for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
- acpi_os_printf (" %.2hX", obj_desc->buffer.pointer[i]);
+ acpi_os_printf(" =");
+ for (i = 0;
+ (i < obj_desc->buffer.length
+ && i < 12); i++) {
+ acpi_os_printf(" %.2hX",
+ obj_desc->buffer.
+ pointer[i]);
}
}
- acpi_os_printf ("\n");
- }
- else {
- acpi_os_printf ("[Length not yet evaluated]\n");
+ acpi_os_printf("\n");
+ } else {
+ acpi_os_printf("[Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_STRING:
- acpi_os_printf ("Len %.2X ", obj_desc->string.length);
- acpi_ut_print_string (obj_desc->string.pointer, 32);
- acpi_os_printf ("\n");
+ acpi_os_printf("Len %.2X ", obj_desc->string.length);
+ acpi_ut_print_string(obj_desc->string.pointer, 32);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_REGION:
- acpi_os_printf ("[%s]",
- acpi_ut_get_region_name (obj_desc->region.space_id));
+ acpi_os_printf("[%s]",
+ acpi_ut_get_region_name(obj_desc->region.
+ space_id));
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n",
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length);
- }
- else {
- acpi_os_printf (" [Address/Length not yet evaluated]\n");
+ acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
+ ACPI_FORMAT_UINT64(obj_desc->
+ region.
+ address),
+ obj_desc->region.length);
+ } else {
+ acpi_os_printf
+ (" [Address/Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
- acpi_os_printf ("[%s]\n",
- acpi_ps_get_opcode_name (obj_desc->reference.opcode));
+ acpi_os_printf("[%s]\n",
+ acpi_ps_get_opcode_name(obj_desc->
+ reference.
+ opcode));
break;
-
case ACPI_TYPE_BUFFER_FIELD:
if (obj_desc->buffer_field.buffer_obj &&
- obj_desc->buffer_field.buffer_obj->buffer.node) {
- acpi_os_printf ("Buf [%4.4s]",
- acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node));
+ obj_desc->buffer_field.buffer_obj->buffer.node) {
+ acpi_os_printf("Buf [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ buffer_field.
+ buffer_obj->
+ buffer.
+ node));
}
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_os_printf ("Rgn [%4.4s]",
- acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node));
+ acpi_os_printf("Rgn [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ region_obj->region.
+ node));
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]",
- acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node),
- acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node));
+ acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ region_obj->region.
+ node),
+ acpi_ut_get_node_name(obj_desc->
+ bank_field.
+ bank_obj->
+ common_field.
+ node));
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]",
- acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node),
- acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node));
+ acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ index_field.
+ index_obj->
+ common_field.node),
+ acpi_ut_get_node_name(obj_desc->
+ index_field.
+ data_obj->
+ common_field.
+ node));
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
- acpi_os_printf ("Target %4.4s (%p)\n",
- acpi_ut_get_node_name (obj_desc), obj_desc);
+ acpi_os_printf("Target %4.4s (%p)\n",
+ acpi_ut_get_node_name(obj_desc),
+ obj_desc);
break;
default:
- acpi_os_printf ("Object %p\n", obj_desc);
+ acpi_os_printf("Object %p\n", obj_desc);
break;
}
@@ -392,11 +396,15 @@ acpi_ns_dump_one_object (
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n",
- (obj_desc->common_field.base_byte_offset * 8)
- + obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.bit_length,
- obj_desc->common_field.access_byte_width);
+ acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
+ (obj_desc->common_field.
+ base_byte_offset * 8)
+ +
+ obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.
+ access_byte_width);
break;
default:
@@ -404,56 +412,55 @@ acpi_ns_dump_one_object (
}
break;
-
case ACPI_DISPLAY_OBJECTS:
- acpi_os_printf ("O:%p", obj_desc);
+ acpi_os_printf("O:%p", obj_desc);
if (!obj_desc) {
/* No attached object, we are done */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return (AE_OK);
}
- acpi_os_printf ("(R%d)", obj_desc->common.reference_count);
+ acpi_os_printf("(R%d)", obj_desc->common.reference_count);
switch (type) {
case ACPI_TYPE_METHOD:
/* Name is a Method and its AML offset/length are set */
- acpi_os_printf (" M:%p-%X\n", obj_desc->method.aml_start,
- obj_desc->method.aml_length);
+ acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
+ obj_desc->method.aml_length);
break;
case ACPI_TYPE_INTEGER:
- acpi_os_printf (" I:%8.8X8.8%X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" I:%8.8X8.8%X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.
+ value));
break;
case ACPI_TYPE_STRING:
- acpi_os_printf (" S:%p-%X\n", obj_desc->string.pointer,
- obj_desc->string.length);
+ acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
+ obj_desc->string.length);
break;
case ACPI_TYPE_BUFFER:
- acpi_os_printf (" B:%p-%X\n", obj_desc->buffer.pointer,
- obj_desc->buffer.length);
+ acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
break;
default:
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
}
break;
-
default:
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
}
@@ -463,61 +470,58 @@ acpi_ns_dump_one_object (
return (AE_OK);
}
-
/* If there is an attached object, display it */
- dbg_level = acpi_dbg_level;
+ dbg_level = acpi_dbg_level;
acpi_dbg_level = 0;
- obj_desc = acpi_ns_get_attached_object (this_node);
+ obj_desc = acpi_ns_get_attached_object(this_node);
acpi_dbg_level = dbg_level;
/* Dump attached objects */
while (obj_desc) {
obj_type = ACPI_TYPE_INVALID;
- acpi_os_printf (" Attached Object %p: ", obj_desc);
+ acpi_os_printf("Attached Object %p: ", obj_desc);
/* Decode the type of attached object and dump the contents */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_NAMED:
- acpi_os_printf ("(Ptr to Node)\n");
- bytes_to_dump = sizeof (struct acpi_namespace_node);
+ acpi_os_printf("(Ptr to Node)\n");
+ bytes_to_dump = sizeof(struct acpi_namespace_node);
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
break;
-
case ACPI_DESC_TYPE_OPERAND:
- obj_type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ obj_type = ACPI_GET_OBJECT_TYPE(obj_desc);
if (obj_type > ACPI_TYPE_LOCAL_MAX) {
- acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
- obj_type);
+ acpi_os_printf
+ ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
+ obj_type);
bytes_to_dump = 32;
+ } else {
+ acpi_os_printf
+ ("(Ptr to ACPI Object type %X [%s])\n",
+ obj_type, acpi_ut_get_type_name(obj_type));
+ bytes_to_dump =
+ sizeof(union acpi_operand_object);
}
- else {
- acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n",
- acpi_ut_get_type_name (obj_type), obj_type);
- bytes_to_dump = sizeof (union acpi_operand_object);
- }
- break;
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
+ break;
default:
- acpi_os_printf (
- "(String or Buffer ptr - not an object descriptor) [%s]\n",
- acpi_ut_get_descriptor_name (obj_desc));
- bytes_to_dump = 16;
break;
}
- ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump);
-
/* If value is NOT an internal object, we are done */
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
+ ACPI_DESC_TYPE_OPERAND) {
goto cleanup;
}
@@ -525,51 +529,56 @@ acpi_ns_dump_one_object (
* Valid object, get the pointer to next level, if any
*/
switch (obj_type) {
- case ACPI_TYPE_STRING:
- obj_desc = (void *) obj_desc->string.pointer;
- break;
-
case ACPI_TYPE_BUFFER:
- obj_desc = (void *) obj_desc->buffer.pointer;
- break;
+ case ACPI_TYPE_STRING:
+ /*
+ * NOTE: takes advantage of common fields between string/buffer
+ */
+ bytes_to_dump = obj_desc->string.length;
+ obj_desc = (void *)obj_desc->string.pointer;
+ acpi_os_printf("(Buffer/String pointer %p length %X)\n",
+ obj_desc, bytes_to_dump);
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
+ goto cleanup;
case ACPI_TYPE_BUFFER_FIELD:
- obj_desc = (union acpi_operand_object *) obj_desc->buffer_field.buffer_obj;
+ obj_desc =
+ (union acpi_operand_object *)obj_desc->buffer_field.
+ buffer_obj;
break;
case ACPI_TYPE_PACKAGE:
- obj_desc = (void *) obj_desc->package.elements;
+ obj_desc = (void *)obj_desc->package.elements;
break;
case ACPI_TYPE_METHOD:
- obj_desc = (void *) obj_desc->method.aml_start;
+ obj_desc = (void *)obj_desc->method.aml_start;
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
- obj_desc = (void *) obj_desc->field.region_obj;
+ obj_desc = (void *)obj_desc->field.region_obj;
break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- obj_desc = (void *) obj_desc->bank_field.region_obj;
+ obj_desc = (void *)obj_desc->bank_field.region_obj;
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- obj_desc = (void *) obj_desc->index_field.index_obj;
+ obj_desc = (void *)obj_desc->index_field.index_obj;
break;
default:
goto cleanup;
}
- obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
+ obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
}
-cleanup:
- acpi_os_printf ("\n");
+ cleanup:
+ acpi_os_printf("\n");
return (AE_OK);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -591,29 +600,25 @@ cleanup:
******************************************************************************/
void
-acpi_ns_dump_objects (
- acpi_object_type type,
- u8 display_type,
- u32 max_depth,
- u32 owner_id,
- acpi_handle start_handle)
+acpi_ns_dump_objects(acpi_object_type type,
+ u8 display_type,
+ u32 max_depth,
+ acpi_owner_id owner_id, acpi_handle start_handle)
{
- struct acpi_walk_info info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_walk_info info;
+ ACPI_FUNCTION_ENTRY();
info.debug_level = ACPI_LV_TABLES;
info.owner_id = owner_id;
info.display_type = display_type;
- (void) acpi_ns_walk_namespace (type, start_handle, max_depth,
- ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object,
- (void *) &info, NULL);
+ (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+ ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ns_dump_one_object, (void *)&info,
+ NULL);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -628,26 +633,20 @@ acpi_ns_dump_objects (
*
******************************************************************************/
-void
-acpi_ns_dump_entry (
- acpi_handle handle,
- u32 debug_level)
+void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
{
- struct acpi_walk_info info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_walk_info info;
+ ACPI_FUNCTION_ENTRY();
info.debug_level = debug_level;
- info.owner_id = ACPI_UINT32_MAX;
+ info.owner_id = ACPI_OWNER_ID_MAX;
info.display_type = ACPI_DISPLAY_SUMMARY;
- (void) acpi_ns_dump_one_object (handle, 1, &info, NULL);
+ (void)acpi_ns_dump_one_object(handle, 1, &info, NULL);
}
-
-#ifdef _ACPI_ASL_COMPILER
+#ifdef ACPI_ASL_COMPILER
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_tables
@@ -663,23 +662,19 @@ acpi_ns_dump_entry (
*
******************************************************************************/
-void
-acpi_ns_dump_tables (
- acpi_handle search_base,
- u32 max_depth)
+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_handle search_handle = search_base;
+ ACPI_FUNCTION_TRACE("ns_dump_tables");
if (!acpi_gbl_root_node) {
/*
* If the name space has not been initialized,
* there is nothing to dump.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "namespace not initialized!\n"));
return_VOID;
}
@@ -687,12 +682,12 @@ acpi_ns_dump_tables (
/* Entire namespace */
search_handle = acpi_gbl_root_node;
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "\\\n"));
}
- acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
- ACPI_UINT32_MAX, search_handle);
+ acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
+ ACPI_OWNER_ID_MAX, search_handle);
return_VOID;
}
-#endif /* _ACPI_ASL_COMPILER */
-#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */
+#endif /* _ACPI_ASL_COMPILER */
+#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index 27c4f7cd2a43..55de883943d6 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -41,20 +41,15 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
/* TBD: This entire module is apparently obsolete and should be removed */
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsdumpdv")
-
+ACPI_MODULE_NAME("nsdumpdv")
#ifdef ACPI_OBSOLETE_FUNCTIONS
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-
#include <acpi/acnamesp.h>
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_device
@@ -70,44 +65,39 @@
* This procedure is a user_function called by acpi_ns_walk_namespace.
*
******************************************************************************/
-
static acpi_status
-acpi_ns_dump_one_device (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_dump_one_device(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- struct acpi_buffer buffer;
- struct acpi_device_info *info;
- acpi_status status;
- u32 i;
-
+ struct acpi_buffer buffer;
+ struct acpi_device_info *info;
+ 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);
+ status =
+ acpi_ns_dump_one_object(obj_handle, level, context, return_value);
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_get_object_info (obj_handle, &buffer);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_get_object_info(obj_handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
info = buffer.pointer;
for (i = 0; i < level; i++) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " "));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES,
- " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
- info->hardware_id.value, ACPI_FORMAT_UINT64 (info->address),
- info->current_status));
- ACPI_MEM_FREE (info);
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
+ " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
+ info->hardware_id.value,
+ ACPI_FORMAT_UINT64(info->address),
+ info->current_status));
+ ACPI_MEM_FREE(info);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_root_devices
@@ -120,16 +110,12 @@ acpi_ns_dump_one_device (
*
******************************************************************************/
-void
-acpi_ns_dump_root_devices (
- void)
+void acpi_ns_dump_root_devices(void)
{
- acpi_handle sys_bus_handle;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("ns_dump_root_devices");
+ acpi_handle sys_bus_handle;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ns_dump_root_devices");
/* Only dump the table if tracing is enabled */
@@ -138,19 +124,17 @@ acpi_ns_dump_root_devices (
}
status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
return;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Display of all devices in the namespace:\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Display of all devices in the namespace:\n"));
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ns_dump_one_device, NULL, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ns_dump_one_device, NULL, NULL);
}
#endif
#endif
-
-
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 1ae89a1c8826..0191c7d92824 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -42,26 +42,19 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nseval")
+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);
+acpi_ns_execute_control_method(struct acpi_parameter_info *info);
+static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info);
/*******************************************************************************
*
@@ -85,48 +78,44 @@ acpi_ns_get_object_value (
******************************************************************************/
acpi_status
-acpi_ns_evaluate_relative (
- char *pathname,
- struct acpi_parameter_info *info)
+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");
+ 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);
+ 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);
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- scope_info = acpi_ut_create_generic_state ();
+ 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)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- info->node = acpi_ns_map_handle_to_node (info->node);
+ info->node = acpi_ns_map_handle_to_node(info->node);
if (!info->node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
status = AE_BAD_PARAMETER;
goto cleanup;
}
@@ -134,39 +123,38 @@ acpi_ns_evaluate_relative (
/* 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);
+ 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);
+ (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)));
+ 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)));
+ 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);
+ status = acpi_ns_evaluate_by_handle(info);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
- pathname));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "*** Completed eval of object %s ***\n", pathname));
-cleanup:
- acpi_ut_delete_generic_state (scope_info);
+ cleanup:
+ acpi_ut_delete_generic_state(scope_info);
-cleanup1:
- ACPI_MEM_FREE (internal_path);
- return_ACPI_STATUS (status);
+ cleanup1:
+ ACPI_MEM_FREE(internal_path);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate_by_name
@@ -189,68 +177,63 @@ cleanup1:
******************************************************************************/
acpi_status
-acpi_ns_evaluate_by_name (
- char *pathname,
- struct acpi_parameter_info *info)
+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");
+ 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_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)) {
+ 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);
+ 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);
+ (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));
+ 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, "%s [%p] Value %p\n",
+ pathname, info->node,
+ acpi_ns_get_attached_object(info->node)));
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
- pathname));
+ status = acpi_ns_evaluate_by_handle(info);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "*** Completed eval of object %s ***\n", pathname));
-cleanup:
+ cleanup:
/* Cleanup */
if (internal_path) {
- ACPI_MEM_FREE (internal_path);
+ ACPI_MEM_FREE(internal_path);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate_by_handle
@@ -275,26 +258,22 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ns_evaluate_by_handle (
- struct acpi_parameter_info *info)
+acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
+ 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);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
/* Parameter Validation */
if (!info) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Initialize the return value to an invalid object */
@@ -303,23 +282,25 @@ acpi_ns_evaluate_by_handle (
/* Get the prefix handle and Node */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- info->node = acpi_ns_map_handle_to_node (info->node);
+ 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);
+ (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 = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
+ if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ info->node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ info->node->object);
}
/*
@@ -329,17 +310,16 @@ acpi_ns_evaluate_by_handle (
*
* In both cases, the namespace is unlocked by the acpi_ns* procedure
*/
- if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
+ 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 {
+ status = acpi_ns_execute_control_method(info);
+ } else {
/*
* Case 2) Object is NOT a method, just return its current value
*/
- status = acpi_ns_get_object_value (info);
+ status = acpi_ns_get_object_value(info);
}
/*
@@ -355,16 +335,16 @@ acpi_ns_evaluate_by_handle (
* Namespace was unlocked by the handling acpi_ns* function, so we
* just return
*/
- return_ACPI_STATUS (status);
+ 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.
@@ -383,31 +363,29 @@ acpi_ns_evaluate_by_handle (
******************************************************************************/
static acpi_status
-acpi_ns_execute_control_method (
- struct acpi_parameter_info *info)
+acpi_ns_execute_control_method(struct acpi_parameter_info *info)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_execute_control_method");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_execute_control_method");
/* Verify that there is a method associated with this object */
- obj_desc = acpi_ns_get_attached_object (info->node);
- if (!obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
+ info->obj_desc = acpi_ns_get_attached_object(info->node);
+ if (!info->obj_desc) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No attached method object\n"));
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (AE_NULL_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_DUMP_PATHNAME(info->node, "Execute Method:",
+ ACPI_LV_INFO, _COMPONENT);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
- obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
+ 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
@@ -416,27 +394,26 @@ acpi_ns_execute_control_method (
* 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);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* 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);
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_psx_execute (info);
- acpi_ex_exit_interpreter ();
+ status = acpi_ps_execute_method(info);
+ acpi_ex_exit_interpreter();
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_object_value
@@ -454,16 +431,12 @@ acpi_ns_execute_control_method (
*
******************************************************************************/
-static acpi_status
-acpi_ns_get_object_value (
- struct acpi_parameter_info *info)
+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;
-
-
- ACPI_FUNCTION_TRACE ("ns_get_object_value");
+ acpi_status status = AE_OK;
+ struct acpi_namespace_node *resolved_node = info->node;
+ ACPI_FUNCTION_TRACE("ns_get_object_value");
/*
* Objects require additional resolution steps (e.g., the Node may be a
@@ -486,32 +459,33 @@ acpi_ns_get_object_value (
*
* 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_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_enter_interpreter ();
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_resolve_node_to_value (&resolved_node, NULL);
+ 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 ();
+ acpi_ex_exit_interpreter();
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
status = AE_CTRL_RETURN_VALUE;
info->return_object = ACPI_CAST_PTR
- (union acpi_operand_object, resolved_node);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
- info->return_object,
- acpi_ut_get_object_type_name (info->return_object)));
+ (union acpi_operand_object, resolved_node);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Returning object %p [%s]\n",
+ info->return_object,
+ acpi_ut_get_object_type_name(info->
+ return_object)));
}
}
/* Namespace is unlocked */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 362802ae29a2..0a08d2f04a06 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -41,31 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsinit")
+ACPI_MODULE_NAME("nsinit")
/* Local prototypes */
-
static acpi_status
-acpi_ns_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ns_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
static acpi_status
-acpi_ns_init_one_device (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value);
-
+acpi_ns_init_one_device(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
/*******************************************************************************
*
@@ -80,52 +71,48 @@ acpi_ns_init_one_device (
*
******************************************************************************/
-acpi_status
-acpi_ns_initialize_objects (
- void)
+acpi_status acpi_ns_initialize_objects(void)
{
- acpi_status status;
- struct acpi_init_walk_info info;
-
+ 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"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Completing Region/Field/Buffer/Package initialization:"));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "**** Starting initialization of namespace objects ****\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "Completing Region/Field/Buffer/Package initialization:"));
/* Set all init info to zero */
- ACPI_MEMSET (&info, 0, sizeof (struct acpi_init_walk_info));
+ ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info));
/* Walk entire namespace from the supplied root */
- status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, acpi_ns_init_one_object,
- &info, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception (status)));
+ status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_ns_init_one_object,
+ &info, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
- info.op_region_init, info.op_region_count,
- info.field_init, info.field_count,
- info.buffer_init, info.buffer_count,
- info.package_init, info.package_count, info.object_count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
+ info.op_region_init, info.op_region_count,
+ info.field_init, info.field_count,
+ info.buffer_init, info.buffer_count,
+ info.package_init, info.package_count,
+ info.object_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Control Methods found\n", info.method_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Op Regions found\n", info.op_region_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Control Methods found\n", info.method_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Op Regions found\n", info.op_region_count));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_initialize_devices
@@ -142,16 +129,12 @@ acpi_ns_initialize_objects (
*
******************************************************************************/
-acpi_status
-acpi_ns_initialize_devices (
- void)
+acpi_status acpi_ns_initialize_devices(void)
{
- acpi_status status;
- struct acpi_device_walk_info info;
-
-
- ACPI_FUNCTION_TRACE ("ns_initialize_devices");
+ acpi_status status;
+ struct acpi_device_walk_info info;
+ ACPI_FUNCTION_TRACE("ns_initialize_devices");
/* Init counters */
@@ -159,34 +142,34 @@ acpi_ns_initialize_devices (
info.num_STA = 0;
info.num_INI = 0;
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Executing all Device _STA and_INI methods:"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "Executing all Device _STA and_INI methods:"));
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Walk namespace for all objects */
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, TRUE,
+ acpi_ns_init_one_device, &info, NULL);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
- info.device_count, info.num_STA, info.num_INI));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
+ info.device_count, info.num_STA, info.num_INI));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_init_one_object
@@ -208,28 +191,25 @@ acpi_ns_initialize_devices (
******************************************************************************/
static acpi_status
-acpi_ns_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- acpi_object_type type;
- acpi_status status;
- struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
- struct acpi_namespace_node *node = (struct acpi_namespace_node *) obj_handle;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_NAME ("ns_init_one_object");
+ acpi_object_type type;
+ acpi_status status;
+ struct acpi_init_walk_info *info =
+ (struct acpi_init_walk_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_NAME("ns_init_one_object");
info->object_count++;
/* And even then, we are only interested in a few object types */
- type = acpi_ns_get_type (obj_handle);
- obj_desc = acpi_ns_get_attached_object (node);
+ type = acpi_ns_get_type(obj_handle);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return (AE_OK);
}
@@ -269,8 +249,8 @@ acpi_ns_init_one_object (
/*
* Must lock the interpreter before executing AML code
*/
- status = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -282,25 +262,25 @@ acpi_ns_init_one_object (
case ACPI_TYPE_REGION:
info->op_region_init++;
- status = acpi_ds_get_region_arguments (obj_desc);
+ status = acpi_ds_get_region_arguments(obj_desc);
break;
case ACPI_TYPE_BUFFER_FIELD:
info->field_init++;
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
break;
case ACPI_TYPE_BUFFER:
info->buffer_init++;
- status = acpi_ds_get_buffer_arguments (obj_desc);
+ status = acpi_ds_get_buffer_arguments(obj_desc);
break;
case ACPI_TYPE_PACKAGE:
info->package_init++;
- status = acpi_ds_get_package_arguments (obj_desc);
+ status = acpi_ds_get_package_arguments(obj_desc);
break;
default:
@@ -308,12 +288,13 @@ acpi_ns_init_one_object (
break;
}
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not execute arguments for [%4.4s] (%s), %s\n",
- acpi_ut_get_node_name (node), acpi_ut_get_type_name (type),
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not execute arguments for [%4.4s] (%s), %s\n",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(type),
+ acpi_format_exception(status)));
}
/*
@@ -321,18 +302,17 @@ acpi_ns_init_one_object (
* pathname
*/
if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
/*
* We ignore errors from above, and always return OK, since we don't want
* to abort the walk on any single error.
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_init_one_device
@@ -348,41 +328,37 @@ acpi_ns_init_one_object (
******************************************************************************/
static acpi_status
-acpi_ns_init_one_device (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value)
+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;
- u32 flags;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_init_one_device");
+ struct acpi_device_walk_info *info =
+ (struct acpi_device_walk_info *)context;
+ struct acpi_parameter_info pinfo;
+ u32 flags;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_init_one_device");
pinfo.parameters = NULL;
pinfo.parameter_type = ACPI_PARAM_ARGS;
- pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
+ pinfo.node = acpi_ns_map_handle_to_node(obj_handle);
if (!pinfo.node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We will run _STA/_INI on Devices, Processors and thermal_zones only
*/
- if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
- (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
- (pinfo.node->type != ACPI_TYPE_THERMAL)) {
- return_ACPI_STATUS (AE_OK);
+ if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
+ (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
+ (pinfo.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, "."));
+ (!(acpi_dbg_level & ACPI_LV_INFO))) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
info->device_count++;
@@ -390,20 +366,20 @@ acpi_ns_init_one_device (
/*
* Run _STA to determine if we can run _INI on the device.
*/
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD,
- pinfo.node, METHOD_NAME__STA));
- status = acpi_ut_execute_STA (pinfo.node, &flags);
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
+ pinfo.node,
+ METHOD_NAME__STA));
+ status = acpi_ut_execute_STA(pinfo.node, &flags);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
if (pinfo.node->type == ACPI_TYPE_DEVICE) {
/* Ignore error and move on to next device */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* _STA is not required for Processor or thermal_zone objects */
- }
- else {
+ } else {
info->num_STA++;
if (!(flags & 0x01)) {
@@ -416,32 +392,34 @@ acpi_ns_init_one_device (
/*
* The device is present. Run _INI.
*/
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD,
- pinfo.node, METHOD_NAME__INI));
- status = acpi_ns_evaluate_relative (METHOD_NAME__INI, &pinfo);
- if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
+ pinfo.node,
+ METHOD_NAME__INI));
+ status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
+ if (ACPI_FAILURE(status)) {
/* No _INI (AE_NOT_FOUND) means device requires no initialization */
if (status != AE_NOT_FOUND) {
/* Ignore error and move on to next device */
#ifdef ACPI_DEBUG_OUTPUT
- char *scope_name = acpi_ns_get_external_pathname (pinfo.node);
+ char *scope_name =
+ acpi_ns_get_external_pathname(pinfo.node);
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
- scope_name, acpi_format_exception (status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n",
+ scope_name,
+ acpi_format_exception(status)));
- ACPI_MEM_FREE (scope_name);
+ ACPI_MEM_FREE(scope_name);
#endif
}
status = AE_OK;
- }
- else {
+ } else {
/* Delete any return object (especially if implicit_return is enabled) */
if (pinfo.return_object) {
- acpi_ut_remove_reference (pinfo.return_object);
+ acpi_ut_remove_reference(pinfo.return_object);
}
/* Count of successful INIs */
@@ -452,8 +430,9 @@ acpi_ns_init_one_device (
if (acpi_gbl_init_handler) {
/* External initialization handler is present, call it */
- status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
+ status =
+ acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 34e497016601..c28849de465a 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -41,32 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsload")
+ACPI_MODULE_NAME("nsload")
/* Local prototypes */
-
-static acpi_status
-acpi_ns_load_table_by_type (
- acpi_table_type table_type);
+static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type);
#ifdef ACPI_FUTURE_IMPLEMENTATION
-acpi_status
-acpi_ns_unload_namespace (
- acpi_handle handle);
+acpi_status acpi_ns_unload_namespace(acpi_handle handle);
-static acpi_status
-acpi_ns_delete_subtree (
- acpi_handle start_handle);
+static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
#endif
-
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -82,40 +72,39 @@ acpi_ns_delete_subtree (
******************************************************************************/
acpi_status
-acpi_ns_load_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *node)
+acpi_ns_load_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *node)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_load_table");
+ acpi_status status;
+ 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)) {
+ if (!
+ (acpi_gbl_table_data[table_desc->type].
+ flags & ACPI_TABLE_EXECUTABLE)) {
/* Just ignore this table */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Check validity of the AML start and length */
if (!table_desc->aml_start) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null AML pointer\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
- table_desc->aml_start));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AML block at %p\n",
+ table_desc->aml_start));
/* Ignore table if there is no AML contained within */
if (!table_desc->aml_length) {
- ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
- table_desc->pointer->signature));
- return_ACPI_STATUS (AE_OK);
+ ACPI_REPORT_WARNING(("Zero-length AML block in table [%4.4s]\n",
+ table_desc->pointer->signature));
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -127,19 +116,19 @@ acpi_ns_load_table (
* to another control method, we can't continue parsing
* because we don't know how many arguments to parse next!
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Loading table into namespace ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Loading table into namespace ****\n"));
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ns_parse_table (table_desc, node->child);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ns_parse_table(table_desc, node->child);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -148,18 +137,17 @@ acpi_ns_load_table (
* just-in-time parsing, we delete the control method
* parse trees.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Begin Table Method Parsing and Object Initialization ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Begin Table Method Parsing and Object Initialization ****\n"));
- status = acpi_ds_initialize_objects (table_desc, node);
+ status = acpi_ds_initialize_objects(table_desc, node);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Completed Table Method Parsing and Object Initialization ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Completed Table Method Parsing and Object Initialization ****\n"));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_load_table_by_type
@@ -174,21 +162,17 @@ acpi_ns_load_table (
*
******************************************************************************/
-static acpi_status
-acpi_ns_load_table_by_type (
- acpi_table_type table_type)
+static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
{
- u32 i;
- acpi_status status;
- struct acpi_table_desc *table_desc;
-
+ u32 i;
+ 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)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -198,7 +182,7 @@ acpi_ns_load_table_by_type (
switch (table_type) {
case ACPI_TABLE_DSDT:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n"));
table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
@@ -210,57 +194,33 @@ acpi_ns_load_table_by_type (
/* Now load the single DSDT */
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_load_table(table_desc, acpi_gbl_root_node);
+ if (ACPI_SUCCESS(status)) {
table_desc->loaded_into_namespace = TRUE;
}
break;
-
case ACPI_TABLE_SSDT:
+ case ACPI_TABLE_PSDT:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
- acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Namespace load: %d SSDT or PSDTs\n",
+ acpi_gbl_table_lists[table_type].count));
/*
- * Traverse list of SSDT tables
+ * Traverse list of SSDT or PSDT tables
*/
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
- for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
+ table_desc = acpi_gbl_table_lists[table_type].next;
+ for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) {
/*
- * Only attempt to load table if it is not
+ * Only attempt to load table into namespace if it is not
* already loaded!
*/
if (!table_desc->loaded_into_namespace) {
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_FAILURE (status)) {
- break;
- }
-
- table_desc->loaded_into_namespace = TRUE;
- }
-
- table_desc = table_desc->next;
- }
- break;
-
-
- case ACPI_TABLE_PSDT:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
- acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
-
- /*
- * Traverse list of PSDT tables
- */
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
-
- for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
- /* Only attempt to load table if it is not already loaded! */
-
- if (!table_desc->loaded_into_namespace) {
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ns_load_table(table_desc,
+ acpi_gbl_root_node);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -271,19 +231,16 @@ acpi_ns_load_table_by_type (
}
break;
-
default:
status = AE_SUPPORT;
break;
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_load_namespace
@@ -297,45 +254,40 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ns_load_namespace (
- void)
+acpi_status acpi_ns_load_namespace(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_load_name_space");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_load_name_space");
/* There must be at least a DSDT installed */
if (acpi_gbl_DSDT == NULL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "DSDT is not in memory\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_load_table_by_type(ACPI_TABLE_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_SSDT);
+ (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT);
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "ACPI Namespace successfully loaded at root %p\n",
- acpi_gbl_root_node));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "ACPI Namespace successfully loaded at root %p\n",
+ acpi_gbl_root_node));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_IMPLEMENTATION
/*******************************************************************************
*
@@ -353,24 +305,20 @@ acpi_ns_load_namespace (
*
******************************************************************************/
-static acpi_status
-acpi_ns_delete_subtree (
- acpi_handle start_handle)
+static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
{
- acpi_status status;
- acpi_handle child_handle;
- acpi_handle parent_handle;
- acpi_handle next_child_handle;
- acpi_handle dummy;
- u32 level;
-
-
- ACPI_FUNCTION_TRACE ("ns_delete_subtree");
+ acpi_status status;
+ acpi_handle child_handle;
+ acpi_handle parent_handle;
+ acpi_handle next_child_handle;
+ acpi_handle dummy;
+ u32 level;
+ ACPI_FUNCTION_TRACE("ns_delete_subtree");
parent_handle = start_handle;
child_handle = NULL;
- level = 1;
+ level = 1;
/*
* Traverse the tree of objects until we bubble back up
@@ -379,18 +327,19 @@ acpi_ns_delete_subtree (
while (level > 0) {
/* Attempt to get the next object in this scope */
- status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
- child_handle, &next_child_handle);
+ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
+ child_handle, &next_child_handle);
child_handle = next_child_handle;
/* Did we get a new object? */
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Check if this object has any children */
- if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
- NULL, &dummy))) {
+ if (ACPI_SUCCESS
+ (acpi_get_next_object
+ (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
/*
* There is at least one child of this object,
* visit the object
@@ -399,8 +348,7 @@ acpi_ns_delete_subtree (
parent_handle = child_handle;
child_handle = NULL;
}
- }
- else {
+ } else {
/*
* No more children in this object, go back up to
* the object's parent
@@ -409,24 +357,23 @@ acpi_ns_delete_subtree (
/* Delete all children now */
- acpi_ns_delete_children (child_handle);
+ acpi_ns_delete_children(child_handle);
child_handle = parent_handle;
- status = acpi_get_parent (parent_handle, &parent_handle);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_parent(parent_handle, &parent_handle);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
/* Now delete the starting object, and we are done */
- acpi_ns_delete_node (child_handle);
+ acpi_ns_delete_node(child_handle);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_unload_name_space
@@ -441,32 +388,27 @@ acpi_ns_delete_subtree (
*
******************************************************************************/
-acpi_status
-acpi_ns_unload_namespace (
- acpi_handle handle)
+acpi_status acpi_ns_unload_namespace(acpi_handle handle)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_unload_name_space");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_unload_name_space");
/* Parameter validation */
if (!acpi_gbl_root_node) {
- return_ACPI_STATUS (AE_NO_NAMESPACE);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
if (!handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* This function does the real work */
- status = acpi_ns_delete_subtree (handle);
+ status = acpi_ns_delete_subtree(handle);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
#endif
#endif
-
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index d8ce7e39795f..d5e8dea61c27 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -41,23 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsnames")
+ACPI_MODULE_NAME("nsnames")
/* Local prototypes */
-
static void
-acpi_ns_build_external_path (
- struct acpi_namespace_node *node,
- acpi_size size,
- char *name_buffer);
-
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+ acpi_size size, char *name_buffer);
/*******************************************************************************
*
@@ -75,17 +69,13 @@ acpi_ns_build_external_path (
******************************************************************************/
static void
-acpi_ns_build_external_path (
- struct acpi_namespace_node *node,
- acpi_size size,
- char *name_buffer)
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+ acpi_size size, char *name_buffer)
{
- acpi_size index;
- struct acpi_namespace_node *parent_node;
-
-
- ACPI_FUNCTION_NAME ("ns_build_external_path");
+ acpi_size index;
+ struct acpi_namespace_node *parent_node;
+ ACPI_FUNCTION_NAME("ns_build_external_path");
/* Special case for root */
@@ -106,8 +96,8 @@ acpi_ns_build_external_path (
/* Put the name into the buffer */
- ACPI_MOVE_32_TO_32 ((name_buffer + index), &parent_node->name);
- parent_node = acpi_ns_get_parent_node (parent_node);
+ ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name);
+ parent_node = acpi_ns_get_parent_node(parent_node);
/* Prefix name with the path separator */
@@ -120,15 +110,14 @@ acpi_ns_build_external_path (
name_buffer[index] = AML_ROOT_PREFIX;
if (index != 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not construct pathname; index=%X, size=%X, Path=%s\n",
- (u32) index, (u32) size, &name_buffer[size]));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not construct pathname; index=%X, size=%X, Path=%s\n",
+ (u32) index, (u32) size, &name_buffer[size]));
}
return;
}
-
#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
*
@@ -144,37 +133,32 @@ acpi_ns_build_external_path (
*
******************************************************************************/
-char *
-acpi_ns_get_external_pathname (
- struct acpi_namespace_node *node)
+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);
+ char *name_buffer;
+ acpi_size size;
+ ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node);
/* Calculate required buffer size based on depth below root */
- size = acpi_ns_get_pathname_length (node);
+ size = acpi_ns_get_pathname_length(node);
/* Allocate a buffer to be returned to caller */
- name_buffer = ACPI_MEM_CALLOCATE (size);
+ name_buffer = ACPI_MEM_CALLOCATE(size);
if (!name_buffer) {
- ACPI_REPORT_ERROR (("ns_get_table_pathname: allocation failure\n"));
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("ns_get_table_pathname: allocation failure\n"));
+ return_PTR(NULL);
}
/* Build the path in the allocated buffer */
- acpi_ns_build_external_path (node, size, name_buffer);
- return_PTR (name_buffer);
+ acpi_ns_build_external_path(node, size, name_buffer);
+ return_PTR(name_buffer);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_pathname_length
@@ -187,16 +171,12 @@ acpi_ns_get_external_pathname (
*
******************************************************************************/
-acpi_size
-acpi_ns_get_pathname_length (
- struct acpi_namespace_node *node)
+acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
{
- acpi_size size;
- struct acpi_namespace_node *next_node;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_size size;
+ struct acpi_namespace_node *next_node;
+ ACPI_FUNCTION_ENTRY();
/*
* Compute length of pathname as 5 * number of name segments.
@@ -207,17 +187,16 @@ acpi_ns_get_pathname_length (
while (next_node && (next_node != acpi_gbl_root_node)) {
size += ACPI_PATH_SEGMENT_LENGTH;
- next_node = acpi_ns_get_parent_node (next_node);
+ next_node = acpi_ns_get_parent_node(next_node);
}
if (!size) {
- size = 1; /* Root node case */
+ size = 1; /* Root node case */
}
- return (size + 1); /* +1 for null string terminator */
+ return (size + 1); /* +1 for null string terminator */
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_handle_to_pathname
@@ -233,41 +212,36 @@ acpi_ns_get_pathname_length (
******************************************************************************/
acpi_status
-acpi_ns_handle_to_pathname (
- acpi_handle target_handle,
- struct acpi_buffer *buffer)
+acpi_ns_handle_to_pathname(acpi_handle target_handle,
+ struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- acpi_size required_size;
+ acpi_status status;
+ 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);
+ node = acpi_ns_map_handle_to_node(target_handle);
if (!node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Determine size required for the caller buffer */
- required_size = acpi_ns_get_pathname_length (node);
+ required_size = acpi_ns_get_pathname_length(node);
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, required_size);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(buffer, required_size);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Build the path in the caller buffer */
- acpi_ns_build_external_path (node, required_size, buffer->pointer);
+ acpi_ns_build_external_path(node, required_size, buffer->pointer);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n",
- (char *) buffer->pointer, (u32) required_size));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X] \n",
+ (char *)buffer->pointer, (u32) required_size));
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index 27258c1ca4f1..fc9be946ebed 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsobject")
-
+ACPI_MODULE_NAME("nsobject")
/*******************************************************************************
*
@@ -71,20 +68,15 @@
* MUTEX: Assumes namespace is locked
*
******************************************************************************/
-
acpi_status
-acpi_ns_attach_object (
- struct acpi_namespace_node *node,
- union acpi_operand_object *object,
- acpi_object_type type)
+acpi_ns_attach_object(struct acpi_namespace_node *node,
+ union acpi_operand_object *object, acpi_object_type type)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *last_obj_desc;
- acpi_object_type object_type = ACPI_TYPE_ANY;
-
-
- ACPI_FUNCTION_TRACE ("ns_attach_object");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *last_obj_desc;
+ acpi_object_type object_type = ACPI_TYPE_ANY;
+ ACPI_FUNCTION_TRACE("ns_attach_object");
/*
* Parameter validation
@@ -92,40 +84,39 @@ acpi_ns_attach_object (
if (!node) {
/* Invalid handle */
- ACPI_REPORT_ERROR (("ns_attach_object: Null named_obj handle\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Null named_obj handle\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (!object && (ACPI_TYPE_ANY != type)) {
/* Null object */
- ACPI_REPORT_ERROR ((
- "ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
/* Not a name handle */
- ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Invalid handle %p [%s]\n",
+ node, acpi_ut_get_descriptor_name(node)));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check if this object is already attached */
if (node->object == object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj %p already installed in name_obj %p\n",
- object, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj %p already installed in name_obj %p\n",
+ object, node));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* If null object, we will just install it */
if (!object) {
- obj_desc = NULL;
+ obj_desc = NULL;
object_type = ACPI_TYPE_ANY;
}
@@ -133,14 +124,14 @@ acpi_ns_attach_object (
* If the source object is a namespace Node with an attached object,
* we will use that (attached) object
*/
- else if ((ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) &&
- ((struct acpi_namespace_node *) object)->object) {
+ else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
+ ((struct acpi_namespace_node *)object)->object) {
/*
* Value passed is a name handle and that name has a
* non-null value. Use that name's value and type.
*/
- obj_desc = ((struct acpi_namespace_node *) object)->object;
- object_type = ((struct acpi_namespace_node *) object)->type;
+ obj_desc = ((struct acpi_namespace_node *)object)->object;
+ object_type = ((struct acpi_namespace_node *)object)->type;
}
/*
@@ -148,20 +139,20 @@ acpi_ns_attach_object (
* it first
*/
else {
- obj_desc = (union acpi_operand_object *) object;
+ obj_desc = (union acpi_operand_object *)object;
/* Use the given type */
object_type = type;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
- obj_desc, node, acpi_ut_get_node_name (node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
+ obj_desc, node, acpi_ut_get_node_name(node)));
/* Detach an existing attached object if present */
if (node->object) {
- acpi_ns_detach_object (node);
+ acpi_ns_detach_object(node);
}
if (obj_desc) {
@@ -169,7 +160,7 @@ acpi_ns_attach_object (
* Must increment the new value's reference count
* (if it is an internal object)
*/
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
/*
* Handle objects with multiple descriptors - walk
@@ -185,13 +176,12 @@ acpi_ns_attach_object (
last_obj_desc->common.next_object = node->object;
}
- node->type = (u8) object_type;
- node->object = obj_desc;
+ node->type = (u8) object_type;
+ node->object = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_detach_object
@@ -206,30 +196,27 @@ acpi_ns_attach_object (
*
******************************************************************************/
-void
-acpi_ns_detach_object (
- struct acpi_namespace_node *node)
+void acpi_ns_detach_object(struct acpi_namespace_node *node)
{
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_detach_object");
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ns_detach_object");
obj_desc = node->object;
if (!obj_desc ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
return_VOID;
}
/* Clear the entry in all cases */
node->object = NULL;
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
node->object = obj_desc->common.next_object;
if (node->object &&
- (ACPI_GET_OBJECT_TYPE (node->object) != ACPI_TYPE_LOCAL_DATA)) {
+ (ACPI_GET_OBJECT_TYPE(node->object) !=
+ ACPI_TYPE_LOCAL_DATA)) {
node->object = node->object->common.next_object;
}
}
@@ -238,16 +225,15 @@ acpi_ns_detach_object (
node->type = ACPI_TYPE_ANY;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
- node, acpi_ut_get_node_name (node), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
+ node, acpi_ut_get_node_name(node), obj_desc));
/* Remove one reference on the object (and all subobjects) */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_attached_object
@@ -261,29 +247,28 @@ acpi_ns_detach_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ns_get_attached_object (
- struct acpi_namespace_node *node)
+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_DEBUG_PRINT ((ACPI_DB_WARN, "Null Node ptr\n"));
- return_PTR (NULL);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Null Node ptr\n"));
+ return_PTR(NULL);
}
if (!node->object ||
- ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) ||
- (ACPI_GET_OBJECT_TYPE (node->object) == ACPI_TYPE_LOCAL_DATA)) {
- return_PTR (NULL);
+ ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
+ ACPI_DESC_TYPE_NAMED))
+ || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) {
+ return_PTR(NULL);
}
- return_PTR (node->object);
+ return_PTR(node->object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_secondary_object
@@ -297,24 +282,23 @@ acpi_ns_get_attached_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ns_get_secondary_object (
- union acpi_operand_object *obj_desc)
+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);
-
-
- if ((!obj_desc) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
- (!obj_desc->common.next_object) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->common.next_object) == ACPI_TYPE_LOCAL_DATA)) {
- return_PTR (NULL);
+ ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc);
+
+ if ((!obj_desc) ||
+ (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
+ (!obj_desc->common.next_object) ||
+ (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) ==
+ ACPI_TYPE_LOCAL_DATA)) {
+ return_PTR(NULL);
}
- return_PTR (obj_desc->common.next_object);
+ return_PTR(obj_desc->common.next_object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_attach_data
@@ -330,23 +314,20 @@ acpi_ns_get_secondary_object (
******************************************************************************/
acpi_status
-acpi_ns_attach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void *data)
+acpi_ns_attach_data(struct acpi_namespace_node *node,
+ acpi_object_handler handler, void *data)
{
- union acpi_operand_object *prev_obj_desc;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *data_desc;
-
+ union acpi_operand_object *prev_obj_desc;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *data_desc;
/* We only allow one attachment per handler */
prev_obj_desc = NULL;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
return (AE_ALREADY_EXISTS);
}
@@ -356,7 +337,7 @@ acpi_ns_attach_data (
/* Create an internal object for the data */
- data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA);
+ data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
if (!data_desc) {
return (AE_NO_MEMORY);
}
@@ -368,15 +349,13 @@ acpi_ns_attach_data (
if (prev_obj_desc) {
prev_obj_desc->common.next_object = data_desc;
- }
- else {
+ } else {
node->object = data_desc;
}
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_detach_data
@@ -392,27 +371,25 @@ acpi_ns_attach_data (
******************************************************************************/
acpi_status
-acpi_ns_detach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler)
+acpi_ns_detach_data(struct acpi_namespace_node * node,
+ acpi_object_handler handler)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *prev_obj_desc;
-
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *prev_obj_desc;
prev_obj_desc = NULL;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
if (prev_obj_desc) {
- prev_obj_desc->common.next_object = obj_desc->common.next_object;
- }
- else {
+ prev_obj_desc->common.next_object =
+ obj_desc->common.next_object;
+ } else {
node->object = obj_desc->common.next_object;
}
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return (AE_OK);
}
@@ -423,7 +400,6 @@ acpi_ns_detach_data (
return (AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_attached_data
@@ -440,18 +416,15 @@ acpi_ns_detach_data (
******************************************************************************/
acpi_status
-acpi_ns_get_attached_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void **data)
+acpi_ns_get_attached_data(struct acpi_namespace_node * node,
+ acpi_object_handler handler, void **data)
{
- union acpi_operand_object *obj_desc;
-
+ union acpi_operand_object *obj_desc;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
*data = obj_desc->data.pointer;
return (AE_OK);
}
@@ -461,5 +434,3 @@ acpi_ns_get_attached_data (
return (AE_NOT_FOUND);
}
-
-
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index a0e13e8d3764..433442a9ec74 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsparse")
-
+ACPI_MODULE_NAME("nsparse")
/*******************************************************************************
*
@@ -64,54 +61,50 @@
* DESCRIPTION: Perform one complete parse of an ACPI/AML table.
*
******************************************************************************/
-
acpi_status
-acpi_ns_one_complete_parse (
- u32 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");
+ union acpi_parse_object *parse_root;
+ acpi_status status;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ns_one_complete_parse");
/* Create and init a Root Node */
- parse_root = acpi_ps_create_scope_op ();
+ parse_root = acpi_ps_create_scope_op();
if (!parse_root) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Create and initialize a new walk state */
- walk_state = acpi_ds_create_walk_state (table_desc->table_id,
- NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(table_desc->owner_id,
+ NULL, NULL, NULL);
if (!walk_state) {
- acpi_ps_free_op (parse_root);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ps_free_op(parse_root);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
- table_desc->aml_start, table_desc->aml_length,
- NULL, pass_number);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
+ table_desc->aml_start,
+ table_desc->aml_length, NULL,
+ pass_number);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ return_ACPI_STATUS(status);
}
/* Parse the AML */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", pass_number));
- status = acpi_ps_parse_aml (walk_state);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n",
+ pass_number));
+ status = acpi_ps_parse_aml(walk_state);
- acpi_ps_delete_parse_tree (parse_root);
- return_ACPI_STATUS (status);
+ acpi_ps_delete_parse_tree(parse_root);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_parse_table
@@ -126,15 +119,12 @@ acpi_ns_one_complete_parse (
******************************************************************************/
acpi_status
-acpi_ns_parse_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *start_node)
+acpi_ns_parse_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *start_node)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_parse_table");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_parse_table");
/*
* AML Parse, pass 1
@@ -146,9 +136,10 @@ acpi_ns_parse_table (
* to service the entire parse. The second pass of the parse then
* performs another complete parse of the AML..
*/
- status = acpi_ns_one_complete_parse (1, table_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+ status = acpi_ns_one_complete_parse(1, table_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -160,12 +151,11 @@ acpi_ns_parse_table (
* overhead of this is compensated for by the fact that the
* parse objects are all cached.
*/
- status = acpi_ns_one_complete_parse (2, table_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
+ status = acpi_ns_one_complete_parse(2, table_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index af8aaa9cc4f3..50a3ca5470ed 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -41,23 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nssearch")
+ACPI_MODULE_NAME("nssearch")
/* Local prototypes */
-
static acpi_status
-acpi_ns_search_parent_tree (
- u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node);
-
+acpi_ns_search_parent_tree(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node);
/*******************************************************************************
*
@@ -87,30 +82,28 @@ acpi_ns_search_parent_tree (
******************************************************************************/
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_node(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node)
{
- struct acpi_namespace_node *next_node;
-
-
- ACPI_FUNCTION_TRACE ("ns_search_node");
+ struct acpi_namespace_node *next_node;
+ ACPI_FUNCTION_TRACE("ns_search_node");
#ifdef ACPI_DEBUG_OUTPUT
if (ACPI_LV_NAMES & acpi_dbg_level) {
- char *scope_name;
+ char *scope_name;
- scope_name = acpi_ns_get_external_pathname (node);
+ scope_name = acpi_ns_get_external_pathname(node);
if (scope_name) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching %s (%p) For [%4.4s] (%s)\n",
- scope_name, node, (char *) &target_name,
- acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching %s (%p) For [%4.4s] (%s)\n",
+ scope_name, node,
+ (char *)&target_name,
+ acpi_ut_get_type_name(type)));
- ACPI_MEM_FREE (scope_name);
+ ACPI_MEM_FREE(scope_name);
}
}
#endif
@@ -126,20 +119,26 @@ acpi_ns_search_node (
if (next_node->name.integer == target_name) {
/* Resolve a control method alias if any */
- if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
+ if (acpi_ns_get_type(next_node) ==
+ ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ next_node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ next_node->object);
}
/*
* Found matching entry.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
- (char *) &target_name, acpi_ut_get_type_name (next_node->type),
- next_node, acpi_ut_get_node_name (node), node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
+ (char *)&target_name,
+ acpi_ut_get_type_name(next_node->
+ type),
+ next_node,
+ acpi_ut_get_node_name(node), node));
*return_node = next_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -159,15 +158,14 @@ acpi_ns_search_node (
/* Searched entire namespace level, not found */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
- (char *) &target_name, acpi_ut_get_type_name (type),
- acpi_ut_get_node_name (node), node, node->child));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
+ (char *)&target_name, acpi_ut_get_type_name(type),
+ acpi_ut_get_node_name(node), node, node->child));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_search_parent_tree
@@ -194,43 +192,42 @@ acpi_ns_search_node (
******************************************************************************/
static acpi_status
-acpi_ns_search_parent_tree (
- u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_parent_tree(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node)
{
- acpi_status status;
- struct acpi_namespace_node *parent_node;
+ 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);
+ parent_node = acpi_ns_get_parent_node(node);
/*
* If there is no parent (i.e., we are at the root) or type is "local",
* we won't be searching the parent tree.
*/
if (!parent_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
- (char *) &target_name));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
+ (char *)&target_name));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
- if (acpi_ns_local (type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
- (char *) &target_name, acpi_ut_get_type_name (type)));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ if (acpi_ns_local(type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
+ (char *)&target_name,
+ acpi_ut_get_type_name(type)));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
/* Search the parent tree */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching parent [%4.4s] for [%4.4s]\n",
- acpi_ut_get_node_name (parent_node), (char *) &target_name));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching parent [%4.4s] for [%4.4s]\n",
+ acpi_ut_get_node_name(parent_node),
+ (char *)&target_name));
/*
* Search parents until target is found or we have backed up to the root
@@ -241,25 +238,24 @@ acpi_ns_search_parent_tree (
* object type at this point, we only care about the existence of
* the actual name we are searching for. Typechecking comes later.
*/
- status = acpi_ns_search_node (target_name, parent_node,
- ACPI_TYPE_ANY, return_node);
- if (ACPI_SUCCESS (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_search_node(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)
*/
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
/* Not found in parent tree */
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_search_and_enter
@@ -286,52 +282,46 @@ acpi_ns_search_parent_tree (
******************************************************************************/
acpi_status
-acpi_ns_search_and_enter (
- u32 target_name,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- acpi_interpreter_mode interpreter_mode,
- acpi_object_type type,
- u32 flags,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_and_enter(u32 target_name,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ acpi_interpreter_mode interpreter_mode,
+ acpi_object_type type,
+ u32 flags, struct acpi_namespace_node **return_node)
{
- acpi_status status;
- struct acpi_namespace_node *new_node;
-
-
- ACPI_FUNCTION_TRACE ("ns_search_and_enter");
+ acpi_status status;
+ struct acpi_namespace_node *new_node;
+ ACPI_FUNCTION_TRACE("ns_search_and_enter");
/* Parameter validation */
if (!node || !target_name || !return_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null param: Node %p Name %X return_node %p\n",
- node, target_name, return_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null param: Node %p Name %X return_node %p\n",
+ node, target_name, return_node));
- ACPI_REPORT_ERROR (("ns_search_and_enter: Null parameter\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_search_and_enter: Null parameter\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Name must consist of printable characters */
- if (!acpi_ut_valid_acpi_name (target_name)) {
- ACPI_REPORT_ERROR (("ns_search_and_enter: Bad character in ACPI Name: %X\n",
- target_name));
- return_ACPI_STATUS (AE_BAD_CHARACTER);
+ if (!acpi_ut_valid_acpi_name(target_name)) {
+ ACPI_REPORT_ERROR(("ns_search_and_enter: Bad character in ACPI Name: %X\n", target_name));
+ return_ACPI_STATUS(AE_BAD_CHARACTER);
}
/* 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_node(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,
* return the error
*/
- if ((status == AE_OK) &&
- (flags & ACPI_NS_ERROR_IF_FOUND)) {
+ if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) {
status = AE_ALREADY_EXISTS;
}
@@ -339,7 +329,7 @@ acpi_ns_search_and_enter (
* Either found it or there was an error
* -- finished either way
*/
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
@@ -351,14 +341,16 @@ acpi_ns_search_and_enter (
* and during the execution phase.
*/
if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) &&
- (flags & ACPI_NS_SEARCH_PARENT)) {
+ (flags & ACPI_NS_SEARCH_PARENT)) {
/*
* Not found at this level - search parent tree according to the
* ACPI specification
*/
- status = acpi_ns_search_parent_tree (target_name, node, type, return_node);
- if (ACPI_SUCCESS (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_search_parent_tree(target_name, node, type,
+ return_node);
+ if (ACPI_SUCCESS(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -366,25 +358,24 @@ acpi_ns_search_and_enter (
* 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",
- (char *) &target_name, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "%4.4s Not found in %p [Not adding]\n",
+ (char *)&target_name, node));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
/* Create the new named object */
- new_node = acpi_ns_create_node (target_name);
+ new_node = acpi_ns_create_node(target_name);
if (!new_node) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Install the new object into the parent's list of children */
- acpi_ns_install_node (walk_state, node, new_node, type);
+ acpi_ns_install_node(walk_state, node, new_node, type);
*return_node = new_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index c53b82e94ce3..ebec036423c9 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -42,28 +42,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/amlcode.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsutils")
+ACPI_MODULE_NAME("nsutils")
/* Local prototypes */
-
-static u8
-acpi_ns_valid_path_separator (
- char sep);
+static u8 acpi_ns_valid_path_separator(char sep);
#ifdef ACPI_OBSOLETE_FUNCTIONS
-acpi_name
-acpi_ns_find_parent_name (
- struct acpi_namespace_node *node_to_search);
+acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_error
@@ -81,51 +74,45 @@ acpi_ns_find_parent_name (
******************************************************************************/
void
-acpi_ns_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *internal_name,
- acpi_status lookup_status)
+acpi_ns_report_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *internal_name, acpi_status lookup_status)
{
- acpi_status status;
- char *name = NULL;
-
+ acpi_status status;
+ char *name = NULL;
- acpi_os_printf ("%8s-%04d: *** Error: Looking up ",
- module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Error: Looking up ",
+ 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)\n",
- *(ACPI_CAST_PTR (u32, internal_name)));
- }
- else {
+ acpi_os_printf("[0x%4.4X] (NON-ASCII)\n",
+ *(ACPI_CAST_PTR(u32, internal_name)));
+ } else {
/* Convert path to external format */
- status = acpi_ns_externalize_name (ACPI_UINT32_MAX,
- internal_name, NULL, &name);
+ status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
+ internal_name, NULL, &name);
/* Print target name */
- if (ACPI_SUCCESS (status)) {
- acpi_os_printf ("[%s]", name);
- }
- else {
- acpi_os_printf ("[COULD NOT EXTERNALIZE NAME]");
+ if (ACPI_SUCCESS(status)) {
+ acpi_os_printf("[%s]", name);
+ } else {
+ acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
}
if (name) {
- ACPI_MEM_FREE (name);
+ ACPI_MEM_FREE(name);
}
}
- acpi_os_printf (" in namespace, %s\n",
- acpi_format_exception (lookup_status));
+ acpi_os_printf(" in namespace, %s\n",
+ acpi_format_exception(lookup_status));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_method_error
@@ -145,34 +132,31 @@ acpi_ns_report_error (
******************************************************************************/
void
-acpi_ns_report_method_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *message,
- struct acpi_namespace_node *prefix_node,
- char *path,
- acpi_status method_status)
+acpi_ns_report_method_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *message,
+ struct acpi_namespace_node *prefix_node,
+ char *path, acpi_status method_status)
{
- acpi_status status;
- struct acpi_namespace_node *node = prefix_node;
-
+ acpi_status status;
+ struct acpi_namespace_node *node = prefix_node;
if (path) {
- status = acpi_ns_get_node_by_path (path, prefix_node,
- ACPI_NS_NO_UPSEARCH, &node);
- if (ACPI_FAILURE (status)) {
- acpi_os_printf ("report_method_error: Could not get node\n");
+ status = acpi_ns_get_node_by_path(path, prefix_node,
+ ACPI_NS_NO_UPSEARCH, &node);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("report_method_error: Could not get node\n");
return;
}
}
- acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
- acpi_ns_print_node_pathname (node, message);
- acpi_os_printf (", %s\n", acpi_format_exception (method_status));
+ acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
+ acpi_ns_print_node_pathname(node, message);
+ acpi_os_printf(", %s\n", acpi_format_exception(method_status));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_print_node_pathname
@@ -186,16 +170,13 @@ acpi_ns_report_method_error (
******************************************************************************/
void
-acpi_ns_print_node_pathname (
- struct acpi_namespace_node *node,
- char *message)
+acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
{
- struct acpi_buffer buffer;
- acpi_status status;
-
+ struct acpi_buffer buffer;
+ acpi_status status;
if (!node) {
- acpi_os_printf ("[NULL NAME]");
+ acpi_os_printf("[NULL NAME]");
return;
}
@@ -203,18 +184,17 @@ acpi_ns_print_node_pathname (
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_ns_handle_to_pathname (node, &buffer);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_handle_to_pathname(node, &buffer);
+ if (ACPI_SUCCESS(status)) {
if (message) {
- acpi_os_printf ("%s ", message);
+ acpi_os_printf("%s ", message);
}
- acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node);
- ACPI_MEM_FREE (buffer.pointer);
+ acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
+ ACPI_MEM_FREE(buffer.pointer);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_valid_root_prefix
@@ -227,15 +207,12 @@ acpi_ns_print_node_pathname (
*
******************************************************************************/
-u8
-acpi_ns_valid_root_prefix (
- char prefix)
+u8 acpi_ns_valid_root_prefix(char prefix)
{
return ((u8) (prefix == '\\'));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_valid_path_separator
@@ -248,15 +225,12 @@ acpi_ns_valid_root_prefix (
*
******************************************************************************/
-static u8
-acpi_ns_valid_path_separator (
- char sep)
+static u8 acpi_ns_valid_path_separator(char sep)
{
return ((u8) (sep == '.'));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_type
@@ -269,22 +243,18 @@ acpi_ns_valid_path_separator (
*
******************************************************************************/
-acpi_object_type
-acpi_ns_get_type (
- struct acpi_namespace_node *node)
+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_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
- return_VALUE (ACPI_TYPE_ANY);
+ ACPI_REPORT_WARNING(("ns_get_type: Null Node input pointer\n"));
+ return_VALUE(ACPI_TYPE_ANY);
}
- return_VALUE ((acpi_object_type) node->type);
+ return_VALUE((acpi_object_type) node->type);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_local
@@ -298,24 +268,20 @@ acpi_ns_get_type (
*
******************************************************************************/
-u32
-acpi_ns_local (
- acpi_object_type type)
+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)) {
+ if (!acpi_ut_valid_object_type(type)) {
/* Type code out of range */
- ACPI_REPORT_WARNING (("ns_local: Invalid Object Type\n"));
- return_VALUE (ACPI_NS_NORMAL);
+ ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n"));
+ return_VALUE(ACPI_NS_NORMAL);
}
- return_VALUE ((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
+ return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_internal_name_length
@@ -330,16 +296,12 @@ acpi_ns_local (
*
******************************************************************************/
-void
-acpi_ns_get_internal_name_length (
- struct acpi_namestring_info *info)
+void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
{
- char *next_external_char;
- u32 i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ char *next_external_char;
+ u32 i;
+ ACPI_FUNCTION_ENTRY();
next_external_char = info->external_name;
info->num_carats = 0;
@@ -353,11 +315,10 @@ acpi_ns_get_internal_name_length (
*
* strlen() + 1 covers the first name_seg, which has no path separator
*/
- if (acpi_ns_valid_root_prefix (next_external_char[0])) {
+ if (acpi_ns_valid_root_prefix(next_external_char[0])) {
info->fully_qualified = TRUE;
next_external_char++;
- }
- else {
+ } else {
/*
* Handle Carat prefixes
*/
@@ -375,19 +336,18 @@ acpi_ns_get_internal_name_length (
if (*next_external_char) {
info->num_segments = 1;
for (i = 0; next_external_char[i]; i++) {
- if (acpi_ns_valid_path_separator (next_external_char[i])) {
+ if (acpi_ns_valid_path_separator(next_external_char[i])) {
info->num_segments++;
}
}
}
info->length = (ACPI_NAME_SIZE * info->num_segments) +
- 4 + info->num_carats;
+ 4 + info->num_carats;
info->next_external_char = next_external_char;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_build_internal_name
@@ -401,19 +361,15 @@ acpi_ns_get_internal_name_length (
*
******************************************************************************/
-acpi_status
-acpi_ns_build_internal_name (
- struct acpi_namestring_info *info)
+acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
{
- u32 num_segments = info->num_segments;
- char *internal_name = info->internal_name;
- char *external_name = info->next_external_char;
- char *result = NULL;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ns_build_internal_name");
+ u32 num_segments = info->num_segments;
+ char *internal_name = info->internal_name;
+ char *external_name = info->next_external_char;
+ char *result = NULL;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ns_build_internal_name");
/* Setup the correct prefixes, counts, and pointers */
@@ -422,18 +378,15 @@ acpi_ns_build_internal_name (
if (num_segments <= 1) {
result = &internal_name[1];
- }
- else if (num_segments == 2) {
+ } else if (num_segments == 2) {
internal_name[1] = AML_DUAL_NAME_PREFIX;
result = &internal_name[2];
- }
- else {
+ } else {
internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[2] = (char) num_segments;
+ internal_name[2] = (char)num_segments;
result = &internal_name[3];
}
- }
- else {
+ } else {
/*
* Not fully qualified.
* Handle Carats first, then append the name segments
@@ -447,15 +400,14 @@ acpi_ns_build_internal_name (
if (num_segments <= 1) {
result = &internal_name[i];
- }
- else if (num_segments == 2) {
+ } else if (num_segments == 2) {
internal_name[i] = AML_DUAL_NAME_PREFIX;
- result = &internal_name[(acpi_native_uint) (i+1)];
- }
- else {
+ result = &internal_name[(acpi_native_uint) (i + 1)];
+ } else {
internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[(acpi_native_uint) (i+1)] = (char) num_segments;
- result = &internal_name[(acpi_native_uint) (i+2)];
+ internal_name[(acpi_native_uint) (i + 1)] =
+ (char)num_segments;
+ result = &internal_name[(acpi_native_uint) (i + 2)];
}
}
@@ -463,25 +415,25 @@ acpi_ns_build_internal_name (
for (; num_segments; num_segments--) {
for (i = 0; i < ACPI_NAME_SIZE; i++) {
- if (acpi_ns_valid_path_separator (*external_name) ||
- (*external_name == 0)) {
+ if (acpi_ns_valid_path_separator(*external_name) ||
+ (*external_name == 0)) {
/* Pad the segment with underscore(s) if segment is short */
result[i] = '_';
- }
- else {
+ } else {
/* Convert the character to uppercase and save it */
- result[i] = (char) ACPI_TOUPPER ((int) *external_name);
+ result[i] =
+ (char)ACPI_TOUPPER((int)*external_name);
external_name++;
}
}
/* Now we must have a path separator, or the pathname is bad */
- if (!acpi_ns_valid_path_separator (*external_name) &&
- (*external_name != 0)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if (!acpi_ns_valid_path_separator(*external_name) &&
+ (*external_name != 0)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Move on the next segment */
@@ -495,18 +447,17 @@ acpi_ns_build_internal_name (
*result = 0;
if (info->fully_qualified) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
- internal_name, internal_name));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
- internal_name, internal_name));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Returning [%p] (abs) \"\\%s\"\n",
+ internal_name, internal_name));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
+ internal_name, internal_name));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_internalize_name
@@ -522,51 +473,43 @@ acpi_ns_build_internal_name (
*
*******************************************************************************/
-acpi_status
-acpi_ns_internalize_name (
- char *external_name,
- char **converted_name)
+acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
{
- char *internal_name;
- struct acpi_namestring_info info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_internalize_name");
+ char *internal_name;
+ struct acpi_namestring_info info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_internalize_name");
- if ((!external_name) ||
- (*external_name == 0) ||
- (!converted_name)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!external_name) || (*external_name == 0) || (!converted_name)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the length of the new internal name */
info.external_name = external_name;
- acpi_ns_get_internal_name_length (&info);
+ acpi_ns_get_internal_name_length(&info);
/* We need a segment to store the internal name */
- internal_name = ACPI_MEM_CALLOCATE (info.length);
+ internal_name = ACPI_MEM_CALLOCATE(info.length);
if (!internal_name) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Build the name */
info.internal_name = internal_name;
- status = acpi_ns_build_internal_name (&info);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (internal_name);
- return_ACPI_STATUS (status);
+ status = acpi_ns_build_internal_name(&info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(internal_name);
+ return_ACPI_STATUS(status);
}
*converted_name = internal_name;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_externalize_name
@@ -585,27 +528,21 @@ acpi_ns_internalize_name (
******************************************************************************/
acpi_status
-acpi_ns_externalize_name (
- u32 internal_name_length,
- char *internal_name,
- u32 *converted_name_length,
- char **converted_name)
+acpi_ns_externalize_name(u32 internal_name_length,
+ char *internal_name,
+ u32 * converted_name_length, char **converted_name)
{
- acpi_native_uint names_index = 0;
- acpi_native_uint num_segments = 0;
- acpi_native_uint required_length;
- acpi_native_uint prefix_length = 0;
- acpi_native_uint i = 0;
- acpi_native_uint j = 0;
-
+ acpi_native_uint names_index = 0;
+ acpi_native_uint num_segments = 0;
+ acpi_native_uint required_length;
+ acpi_native_uint prefix_length = 0;
+ 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);
+ if (!internal_name_length || !internal_name || !converted_name) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -620,8 +557,7 @@ acpi_ns_externalize_name (
for (i = 0; i < internal_name_length; i++) {
if (internal_name[i] == '^') {
prefix_length = i + 1;
- }
- else {
+ } else {
break;
}
}
@@ -648,7 +584,8 @@ acpi_ns_externalize_name (
names_index = prefix_length + 2;
num_segments = (acpi_native_uint) (u8)
- internal_name[(acpi_native_uint) (prefix_length + 1)];
+ internal_name[(acpi_native_uint)
+ (prefix_length + 1)];
break;
case AML_DUAL_NAME_PREFIX:
@@ -683,23 +620,23 @@ acpi_ns_externalize_name (
* punctuation ('.') between object names, plus the NULL terminator.
*/
required_length = prefix_length + (4 * num_segments) +
- ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
+ ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
/*
* Check to see if we're still in bounds. If not, there's a problem
* with internal_name (invalid format).
*/
if (required_length > internal_name_length) {
- ACPI_REPORT_ERROR (("ns_externalize_name: Invalid internal name\n"));
- return_ACPI_STATUS (AE_BAD_PATHNAME);
+ ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n"));
+ return_ACPI_STATUS(AE_BAD_PATHNAME);
}
/*
* Build converted_name
*/
- *converted_name = ACPI_MEM_CALLOCATE (required_length);
+ *converted_name = ACPI_MEM_CALLOCATE(required_length);
if (!(*converted_name)) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
j = 0;
@@ -725,10 +662,9 @@ acpi_ns_externalize_name (
*converted_name_length = (u32) required_length;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_map_handle_to_node
@@ -745,13 +681,10 @@ acpi_ns_externalize_name (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_map_handle_to_node (
- acpi_handle handle)
+struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/*
* Simple implementation.
@@ -766,14 +699,13 @@ acpi_ns_map_handle_to_node (
/* We can at least attempt to verify the handle */
- if (ACPI_GET_DESCRIPTOR_TYPE (handle) != ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
return (NULL);
}
- return ((struct acpi_namespace_node *) handle);
+ return ((struct acpi_namespace_node *)handle);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_convert_entry_to_handle
@@ -786,18 +718,14 @@ acpi_ns_map_handle_to_node (
*
******************************************************************************/
-acpi_handle
-acpi_ns_convert_entry_to_handle (
- struct acpi_namespace_node *node)
+acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node)
{
-
/*
* Simple implementation for now;
*/
return ((acpi_handle) node);
-
/* Example future implementation ---------------------
if (!Node)
@@ -810,12 +738,10 @@ acpi_ns_convert_entry_to_handle (
return (ACPI_ROOT_OBJECT);
}
-
return ((acpi_handle) Node);
------------------------------------------------------*/
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_terminate
@@ -828,42 +754,37 @@ acpi_ns_convert_entry_to_handle (
*
******************************************************************************/
-void
-acpi_ns_terminate (
- void)
+void acpi_ns_terminate(void)
{
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_terminate");
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ns_terminate");
/*
* 1) Free the entire namespace -- all nodes and objects
*
* Delete all object descriptors attached to namepsace nodes
*/
- acpi_ns_delete_namespace_subtree (acpi_gbl_root_node);
+ acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
/* Detach any objects attached to the root */
- obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node);
+ obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
if (obj_desc) {
- acpi_ns_detach_object (acpi_gbl_root_node);
+ acpi_ns_detach_object(acpi_gbl_root_node);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
/*
* 2) Now we can delete the ACPI tables
*/
- acpi_tb_delete_all_tables ();
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
+ acpi_tb_delete_all_tables();
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_opens_scope
@@ -875,24 +796,21 @@ acpi_ns_terminate (
*
******************************************************************************/
-u32
-acpi_ns_opens_scope (
- acpi_object_type type)
+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)) {
+ if (!acpi_ut_valid_object_type(type)) {
/* type code out of range */
- ACPI_REPORT_WARNING (("ns_opens_scope: Invalid Object Type %X\n", type));
- return_VALUE (ACPI_NS_NORMAL);
+ ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n",
+ type));
+ return_VALUE(ACPI_NS_NORMAL);
}
- return_VALUE (((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
+ return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_node_by_path
@@ -916,33 +834,29 @@ acpi_ns_opens_scope (
******************************************************************************/
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_by_path(char *pathname,
+ struct acpi_namespace_node *start_node,
+ 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);
+ union acpi_generic_state scope_info;
+ acpi_status status;
+ char *internal_path = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname);
if (pathname) {
/* Convert path to internal representation */
- status = acpi_ns_internalize_name (pathname, &internal_path);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Must lock namespace during lookup */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -952,25 +866,25 @@ acpi_ns_get_node_by_path (
/* 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);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s, %s\n",
- internal_path, acpi_format_exception (status)));
+ 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)));
}
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-cleanup:
+ cleanup:
if (internal_path) {
- ACPI_MEM_FREE (internal_path);
+ ACPI_MEM_FREE(internal_path);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_parent_node
@@ -983,12 +897,10 @@ cleanup:
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_get_parent_node (
- struct acpi_namespace_node *node)
+struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node
+ *node)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
if (!node) {
return (NULL);
@@ -1006,7 +918,6 @@ acpi_ns_get_parent_node (
return (node->peer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_next_valid_node
@@ -1021,9 +932,9 @@ acpi_ns_get_parent_node (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_get_next_valid_node (
- struct acpi_namespace_node *node)
+struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct
+ acpi_namespace_node
+ *node)
{
/* If we are at the end of this peer list, return NULL */
@@ -1037,7 +948,6 @@ acpi_ns_get_next_valid_node (
return (node->peer);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -1053,38 +963,36 @@ acpi_ns_get_next_valid_node (
*
******************************************************************************/
-acpi_name
-acpi_ns_find_parent_name (
- struct acpi_namespace_node *child_node)
+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");
+ struct acpi_namespace_node *parent_node;
+ 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);
+ parent_node = acpi_ns_get_parent_node(child_node);
if (parent_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Parent of %p [%4.4s] is %p [%4.4s]\n",
- child_node, acpi_ut_get_node_name (child_node),
- parent_node, acpi_ut_get_node_name (parent_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Parent of %p [%4.4s] is %p [%4.4s]\n",
+ child_node,
+ acpi_ut_get_node_name(child_node),
+ parent_node,
+ acpi_ut_get_node_name(parent_node)));
if (parent_node->name.integer) {
- return_VALUE ((acpi_name) parent_node->name.integer);
+ return_VALUE((acpi_name) parent_node->name.
+ integer);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Unable to find parent of %p (%4.4s)\n",
- child_node, acpi_ut_get_node_name (child_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Unable to find parent of %p (%4.4s)\n",
+ child_node,
+ acpi_ut_get_node_name(child_node)));
}
- return_VALUE (ACPI_UNKNOWN_NAME);
+ return_VALUE(ACPI_UNKNOWN_NAME);
}
#endif
-
-
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index f9a7277dca6e..5f164c0df33b 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nswalk")
-
+ACPI_MODULE_NAME("nswalk")
/*******************************************************************************
*
@@ -68,18 +65,15 @@
* within Scope is returned.
*
******************************************************************************/
-
-struct acpi_namespace_node *
-acpi_ns_get_next_node (
- acpi_object_type type,
- struct acpi_namespace_node *parent_node,
- struct acpi_namespace_node *child_node)
+struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
+ struct acpi_namespace_node
+ *parent_node,
+ struct acpi_namespace_node
+ *child_node)
{
- struct acpi_namespace_node *next_node = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_namespace_node *next_node = NULL;
+ ACPI_FUNCTION_ENTRY();
if (!child_node) {
/* It's really the parent's _scope_ that we want */
@@ -92,7 +86,7 @@ acpi_ns_get_next_node (
else {
/* Start search at the NEXT node */
- next_node = acpi_ns_get_next_valid_node (child_node);
+ next_node = acpi_ns_get_next_valid_node(child_node);
}
/* If any type is OK, we are done */
@@ -114,7 +108,7 @@ acpi_ns_get_next_node (
/* Otherwise, move on to the next node */
- next_node = acpi_ns_get_next_valid_node (next_node);
+ next_node = acpi_ns_get_next_valid_node(next_node);
}
/* Not found */
@@ -122,7 +116,6 @@ acpi_ns_get_next_node (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_walk_namespace
@@ -154,25 +147,21 @@ acpi_ns_get_next_node (
******************************************************************************/
acpi_status
-acpi_ns_walk_namespace (
- acpi_object_type type,
- acpi_handle start_node,
- u32 max_depth,
- u8 unlock_before_callback,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_ns_walk_namespace(acpi_object_type type,
+ acpi_handle start_node,
+ u32 max_depth,
+ u8 unlock_before_callback,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
- acpi_status mutex_status;
- struct acpi_namespace_node *child_node;
- struct acpi_namespace_node *parent_node;
- acpi_object_type child_type;
- u32 level;
-
-
- ACPI_FUNCTION_TRACE ("ns_walk_namespace");
+ acpi_status status;
+ acpi_status mutex_status;
+ struct acpi_namespace_node *child_node;
+ struct acpi_namespace_node *parent_node;
+ acpi_object_type child_type;
+ u32 level;
+ ACPI_FUNCTION_TRACE("ns_walk_namespace");
/* Special case for the namespace Root Node */
@@ -183,9 +172,9 @@ acpi_ns_walk_namespace (
/* Null child means "get first node" */
parent_node = start_node;
- child_node = NULL;
- child_type = ACPI_TYPE_ANY;
- level = 1;
+ child_node = NULL;
+ child_type = ACPI_TYPE_ANY;
+ level = 1;
/*
* Traverse the tree of nodes until we bubble back up to where we
@@ -196,7 +185,9 @@ acpi_ns_walk_namespace (
/* Get the next node in this scope. Null if not found */
status = AE_OK;
- 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 node, Get the type if we are not
@@ -212,19 +203,25 @@ acpi_ns_walk_namespace (
* callback function
*/
if (unlock_before_callback) {
- mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (mutex_status)) {
- return_ACPI_STATUS (mutex_status);
+ mutex_status =
+ acpi_ut_release_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS
+ (mutex_status);
}
}
- status = user_function (child_node, level,
- context, return_value);
+ status = user_function(child_node, level,
+ context, return_value);
if (unlock_before_callback) {
- mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (mutex_status)) {
- return_ACPI_STATUS (mutex_status);
+ mutex_status =
+ acpi_ut_acquire_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS
+ (mutex_status);
}
}
@@ -239,13 +236,13 @@ acpi_ns_walk_namespace (
/* Exit now, with OK status */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
default:
/* All others are valid exceptions */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
}
@@ -258,7 +255,8 @@ acpi_ns_walk_namespace (
* maximum depth has been reached.
*/
if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this
* node, visit the onde
@@ -268,8 +266,7 @@ acpi_ns_walk_namespace (
child_node = NULL;
}
}
- }
- else {
+ } else {
/*
* No more children of this node (acpi_ns_get_next_node
* failed), go back upwards in the namespace tree to
@@ -277,13 +274,11 @@ acpi_ns_walk_namespace (
*/
level--;
child_node = parent_node;
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
/* Complete walk, not terminated by user function */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 12ea202257fa..c07b046659ff 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -48,10 +48,8 @@
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfeval")
-
+ACPI_MODULE_NAME("nsxfeval")
/*******************************************************************************
*
@@ -73,27 +71,23 @@
* 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,
- acpi_object_type return_type)
+acpi_evaluate_object_typed(acpi_handle handle,
+ acpi_string pathname,
+ 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_status status;
+ u8 must_free = FALSE;
+ ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed");
/* Return buffer must be valid */
if (!return_buffer) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
@@ -102,51 +96,52 @@ acpi_evaluate_object_typed (
/* Evaluate the object */
- status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_evaluate_object(handle, pathname, external_params,
+ return_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Type ANY means "don't care" */
if (return_type == ACPI_TYPE_ANY) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
if (return_buffer->length == 0) {
/* Error because caller specifically asked for a return value */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No return value\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return value\n"));
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Examine the object type returned from evaluate_object */
- if (((union acpi_object *) return_buffer->pointer)->type == return_type) {
- return_ACPI_STATUS (AE_OK);
+ if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
+ return_ACPI_STATUS(AE_OK);
}
/* Return object type does not match requested type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Incorrect return type [%s] requested [%s]\n",
- acpi_ut_get_type_name (((union acpi_object *) return_buffer->pointer)->type),
- acpi_ut_get_type_name (return_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Incorrect return type [%s] requested [%s]\n",
+ acpi_ut_get_type_name(((union acpi_object *)
+ return_buffer->pointer)->type),
+ 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);
+ acpi_os_free(return_buffer->pointer);
return_buffer->pointer = NULL;
}
return_buffer->length = 0;
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -169,21 +164,18 @@ acpi_evaluate_object_typed (
******************************************************************************/
acpi_status
-acpi_evaluate_object (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *external_params,
- struct acpi_buffer *return_buffer)
+acpi_evaluate_object(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *external_params,
+ struct acpi_buffer *return_buffer)
{
- acpi_status status;
- acpi_status status2;
- struct acpi_parameter_info info;
- acpi_size buffer_space_needed;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
+ acpi_status status;
+ acpi_status status2;
+ struct acpi_parameter_info info;
+ acpi_size buffer_space_needed;
+ u32 i;
+ ACPI_FUNCTION_TRACE("acpi_evaluate_object");
info.node = handle;
info.parameters = NULL;
@@ -200,11 +192,11 @@ acpi_evaluate_object (
* 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 *));
+ info.parameters = ACPI_MEM_CALLOCATE(((acpi_size)
+ external_params->count +
+ 1) * sizeof(void *));
if (!info.parameters) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -212,48 +204,47 @@ acpi_evaluate_object (
* internal object
*/
for (i = 0; i < external_params->count; i++) {
- status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
- &info.parameters[i]);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_internal_object_list (info.parameters);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_eobject_to_iobject(&external_params->
+ pointer[i],
+ &info.
+ parameters[i]);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_internal_object_list(info.
+ parameters);
+ return_ACPI_STATUS(status);
}
}
info.parameters[external_params->count] = NULL;
}
-
/*
* Three major cases:
* 1) Fully qualified pathname
* 2) No handle, not fully qualified pathname (error)
* 3) Valid handle
*/
- if ((pathname) &&
- (acpi_ns_valid_root_prefix (pathname[0]))) {
+ 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);
- }
- else if (!handle) {
+ status = acpi_ns_evaluate_by_name(pathname, &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
*/
if (!pathname) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Both Handle and Pathname are NULL\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Handle is NULL and Pathname is relative\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Both Handle and Pathname are NULL\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Handle is NULL and Pathname is relative\n"));
}
status = AE_BAD_PARAMETER;
- }
- else {
+ } else {
/*
* We get here if we have a handle -- and if we have a
* pathname it is relative. The handle will be validated
@@ -264,17 +255,15 @@ acpi_evaluate_object (
* 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);
+ status = acpi_ns_evaluate_by_handle(&info);
+ } else {
+ /*
+ * Both a Handle and a relative Pathname
+ */
+ status = acpi_ns_evaluate_relative(pathname, &info);
}
}
-
/*
* If we are expecting a return value, and all went well above,
* copy the return value to an external object.
@@ -282,9 +271,9 @@ acpi_evaluate_object (
if (return_buffer) {
if (!info.return_object) {
return_buffer->length = 0;
- }
- else {
- if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
+ } else {
+ 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
* the object we are evaluating has nothing interesting to
@@ -294,37 +283,43 @@ acpi_evaluate_object (
* 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)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Find out how large a buffer is needed
* to contain the returned object
*/
- status = acpi_ut_get_object_size (info.return_object,
- &buffer_space_needed);
- if (ACPI_SUCCESS (status)) {
+ status =
+ acpi_ut_get_object_size(info.return_object,
+ &buffer_space_needed);
+ if (ACPI_SUCCESS(status)) {
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (return_buffer,
- buffer_space_needed);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_initialize_buffer
+ (return_buffer,
+ buffer_space_needed);
+ if (ACPI_FAILURE(status)) {
/*
* 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",
- (u32) buffer_space_needed,
- acpi_format_exception (status)));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Needed buffer size %X, %s\n",
+ (u32)
+ buffer_space_needed,
+ acpi_format_exception
+ (status)));
+ } else {
/*
* We have enough space for the object, build it
*/
- status = acpi_ut_copy_iobject_to_eobject (info.return_object,
- return_buffer);
+ status =
+ acpi_ut_copy_iobject_to_eobject
+ (info.return_object,
+ return_buffer);
}
}
}
@@ -336,14 +331,14 @@ acpi_evaluate_object (
* Delete the internal return object. NOTE: Interpreter
* must be locked to avoid race condition.
*/
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_SUCCESS (status2)) {
+ 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);
- acpi_ex_exit_interpreter ();
+ acpi_ut_remove_reference(info.return_object);
+ acpi_ex_exit_interpreter();
}
}
@@ -353,13 +348,13 @@ acpi_evaluate_object (
if (info.parameters) {
/* Free the allocated parameter block */
- acpi_ut_delete_internal_object_list (info.parameters);
+ acpi_ut_delete_internal_object_list(info.parameters);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_evaluate_object);
+EXPORT_SYMBOL(acpi_evaluate_object);
/*******************************************************************************
*
@@ -392,26 +387,20 @@ EXPORT_SYMBOL(acpi_evaluate_object);
******************************************************************************/
acpi_status
-acpi_walk_namespace (
- acpi_object_type type,
- acpi_handle start_object,
- u32 max_depth,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_walk_namespace(acpi_object_type type,
+ acpi_handle start_object,
+ u32 max_depth,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_walk_namespace");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_walk_namespace");
/* Parameter validation */
- if ((type > ACPI_TYPE_EXTERNAL_MAX) ||
- (!max_depth) ||
- (!user_function)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((type > ACPI_TYPE_EXTERNAL_MAX) || (!max_depth) || (!user_function)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -420,20 +409,20 @@ acpi_walk_namespace (
* to the user function - since this function
* must be allowed to make Acpi calls itself.
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ns_walk_namespace (type, start_object, max_depth,
- ACPI_NS_WALK_UNLOCK,
- user_function, context, return_value);
+ status = acpi_ns_walk_namespace(type, start_object, max_depth,
+ ACPI_NS_WALK_UNLOCK,
+ user_function, context, return_value);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_namespace);
+EXPORT_SYMBOL(acpi_walk_namespace);
/*******************************************************************************
*
@@ -450,29 +439,26 @@ EXPORT_SYMBOL(acpi_walk_namespace);
******************************************************************************/
static acpi_status
-acpi_ns_get_device_callback (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value)
+acpi_ns_get_device_callback(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
{
- struct acpi_get_devices_info *info = context;
- acpi_status status;
- struct acpi_namespace_node *node;
- u32 flags;
- struct acpi_device_id hid;
+ struct acpi_get_devices_info *info = context;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ u32 flags;
+ struct acpi_device_id hid;
struct acpi_compatible_id_list *cid;
- acpi_native_uint i;
-
+ acpi_native_uint i;
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (obj_handle);
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ node = acpi_ns_map_handle_to_node(obj_handle);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -482,8 +468,8 @@ acpi_ns_get_device_callback (
/* Run _STA to determine if device is present */
- status = acpi_ut_execute_STA (node, &flags);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_execute_STA(node, &flags);
+ if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
@@ -496,44 +482,43 @@ acpi_ns_get_device_callback (
/* Filter based on device HID & CID */
if (info->hid != NULL) {
- status = acpi_ut_execute_HID (node, &hid);
+ status = acpi_ut_execute_HID(node, &hid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
+ } else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
- if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) {
+ if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
/* Get the list of Compatible IDs */
- status = acpi_ut_execute_CID (node, &cid);
+ status = acpi_ut_execute_CID(node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
+ } else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
/* Walk the CID list */
for (i = 0; i < cid->count; i++) {
- if (ACPI_STRNCMP (cid->id[i].value, info->hid,
- sizeof (struct acpi_compatible_id)) != 0) {
- ACPI_MEM_FREE (cid);
+ if (ACPI_STRNCMP(cid->id[i].value, info->hid,
+ sizeof(struct
+ acpi_compatible_id)) !=
+ 0) {
+ ACPI_MEM_FREE(cid);
return (AE_OK);
}
}
- ACPI_MEM_FREE (cid);
+ ACPI_MEM_FREE(cid);
}
}
- status = info->user_function (obj_handle, nesting_level, info->context,
- return_value);
+ status = info->user_function(obj_handle, nesting_level, info->context,
+ return_value);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_devices
@@ -560,32 +545,28 @@ acpi_ns_get_device_callback (
******************************************************************************/
acpi_status
-acpi_get_devices (
- char *HID,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_get_devices(char *HID,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
- struct acpi_get_devices_info info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_devices");
+ acpi_status status;
+ struct acpi_get_devices_info info;
+ ACPI_FUNCTION_TRACE("acpi_get_devices");
/* Parameter validation */
if (!user_function) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
- info.context = context;
+ info.context = context;
info.user_function = user_function;
- info.hid = HID;
+ info.hid = HID;
/*
* Lock the namespace around the walk.
@@ -593,22 +574,22 @@ acpi_get_devices (
* to the user function - since this function
* must be allowed to make Acpi calls itself.
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- 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);
+ 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);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_devices);
+EXPORT_SYMBOL(acpi_get_devices);
/*******************************************************************************
*
@@ -625,44 +606,38 @@ EXPORT_SYMBOL(acpi_get_devices);
******************************************************************************/
acpi_status
-acpi_attach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void *data)
+acpi_attach_data(acpi_handle obj_handle,
+ acpi_object_handler handler, void *data)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler ||
- !data) {
+ if (!obj_handle || !handler || !data) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_attach_data (node, handler, data);
+ status = acpi_ns_attach_data(node, handler, data);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_detach_data
@@ -677,42 +652,37 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_detach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler)
+acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler) {
+ if (!obj_handle || !handler) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_detach_data (node, handler);
+ status = acpi_ns_detach_data(node, handler);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_data
@@ -728,41 +698,33 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_get_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void **data)
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler ||
- !data) {
+ if (!obj_handle || !handler || !data) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_get_attached_data (node, handler, data);
+ status = acpi_ns_get_attached_data(node, handler, data);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
-
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 8d097914c49a..6b5f8d4481d1 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -47,10 +47,8 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfname")
-
+ACPI_MODULE_NAME("nsxfname")
/******************************************************************************
*
@@ -69,20 +67,15 @@
* namespace handle.
*
******************************************************************************/
-
acpi_status
-acpi_get_handle (
- acpi_handle parent,
- acpi_string pathname,
- acpi_handle *ret_handle)
+acpi_get_handle(acpi_handle parent,
+ acpi_string pathname, acpi_handle * ret_handle)
{
- acpi_status status;
- struct acpi_namespace_node *node = NULL;
- struct acpi_namespace_node *prefix_node = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ struct acpi_namespace_node *node = NULL;
+ struct acpi_namespace_node *prefix_node = NULL;
+ ACPI_FUNCTION_ENTRY();
/* Parameter Validation */
@@ -93,45 +86,47 @@ acpi_get_handle (
/* Convert a parent handle to a prefix node */
if (parent) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- prefix_node = acpi_ns_map_handle_to_node (parent);
+ prefix_node = acpi_ns_map_handle_to_node(parent);
if (!prefix_node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
/* Special case for root, since we can't search for it */
- if (ACPI_STRCMP (pathname, ACPI_NS_ROOT_PATH) == 0) {
- *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node);
+ if (ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH) == 0) {
+ *ret_handle =
+ acpi_ns_convert_entry_to_handle(acpi_gbl_root_node);
return (AE_OK);
}
/*
* 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_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
+ &node);
*ret_handle = NULL;
- if (ACPI_SUCCESS (status)) {
- *ret_handle = acpi_ns_convert_entry_to_handle (node);
+ if (ACPI_SUCCESS(status)) {
+ *ret_handle = acpi_ns_convert_entry_to_handle(node);
}
return (status);
}
-EXPORT_SYMBOL(acpi_get_handle);
+EXPORT_SYMBOL(acpi_get_handle);
/******************************************************************************
*
@@ -150,14 +145,10 @@ EXPORT_SYMBOL(acpi_get_handle);
******************************************************************************/
acpi_status
-acpi_get_name (
- acpi_handle handle,
- u32 name_type,
- struct acpi_buffer *buffer)
+acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
/* Parameter validation */
@@ -165,15 +156,15 @@ acpi_get_name (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_validate_buffer(buffer);
+ if (ACPI_FAILURE(status)) {
return (status);
}
if (name_type == ACPI_FULL_PATHNAME) {
/* Get the full pathname (From the namespace root) */
- status = acpi_ns_handle_to_pathname (handle, buffer);
+ status = acpi_ns_handle_to_pathname(handle, buffer);
return (status);
}
@@ -181,12 +172,12 @@ acpi_get_name (
* Wants the single segment ACPI name.
* Validate handle and convert to a namespace Node
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -194,26 +185,25 @@ acpi_get_name (
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, ACPI_PATH_SEGMENT_LENGTH);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Just copy the ACPI name from the Node and zero terminate it */
- ACPI_STRNCPY (buffer->pointer, acpi_ut_get_node_name (node),
- ACPI_NAME_SIZE);
- ((char *) buffer->pointer) [ACPI_NAME_SIZE] = 0;
+ ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
+ ACPI_NAME_SIZE);
+ ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
status = AE_OK;
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_name);
+EXPORT_SYMBOL(acpi_get_name);
/******************************************************************************
*
@@ -231,17 +221,14 @@ EXPORT_SYMBOL(acpi_get_name);
******************************************************************************/
acpi_status
-acpi_get_object_info (
- acpi_handle handle,
- struct acpi_buffer *buffer)
+acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- struct acpi_device_info *info;
- struct acpi_device_info *return_info;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ struct acpi_device_info *info;
+ struct acpi_device_info *return_info;
struct acpi_compatible_id_list *cid_list = NULL;
- acpi_size size;
-
+ acpi_size size;
/* Parameter validation */
@@ -249,37 +236,37 @@ acpi_get_object_info (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_validate_buffer(buffer);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_device_info));
+ info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
goto cleanup;
}
/* Init return structure */
- size = sizeof (struct acpi_device_info);
+ size = sizeof(struct acpi_device_info);
- info->type = node->type;
- info->name = node->name.integer;
+ info->type = node->type;
+ info->name = node->name.integer;
info->valid = 0;
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -297,73 +284,73 @@ acpi_get_object_info (
/* Execute the Device._HID method */
- status = acpi_ut_execute_HID (node, &info->hardware_id);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_HID(node, &info->hardware_id);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
- status = acpi_ut_execute_UID (node, &info->unique_id);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_UID(node, &info->unique_id);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_UID;
}
/* Execute the Device._CID method */
- status = acpi_ut_execute_CID (node, &cid_list);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_CID(node, &cid_list);
+ if (ACPI_SUCCESS(status)) {
size += ((acpi_size) cid_list->count - 1) *
- sizeof (struct acpi_compatible_id);
+ sizeof(struct acpi_compatible_id);
info->valid |= ACPI_VALID_CID;
}
/* Execute the Device._STA method */
- status = acpi_ut_execute_STA (node, &info->current_status);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_STA(node, &info->current_status);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_STA;
}
/* Execute the Device._ADR method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
- &info->address);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
+ &info->address);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_ADR;
}
/* Execute the Device._sx_d methods */
- status = acpi_ut_execute_sxds (node, info->highest_dstates);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_sxds(node, info->highest_dstates);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_SXDS;
}
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, size);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_initialize_buffer(buffer, size);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Populate the return buffer */
return_info = buffer->pointer;
- ACPI_MEMCPY (return_info, info, sizeof (struct acpi_device_info));
+ ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info));
if (cid_list) {
- ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
+ ACPI_MEMCPY(&return_info->compatibility_id, cid_list,
+ cid_list->size);
}
-
-cleanup:
- ACPI_MEM_FREE (info);
+ cleanup:
+ ACPI_MEM_FREE(info);
if (cid_list) {
- ACPI_MEM_FREE (cid_list);
+ ACPI_MEM_FREE(cid_list);
}
return (status);
}
-EXPORT_SYMBOL(acpi_get_object_info);
+EXPORT_SYMBOL(acpi_get_object_info);
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index 363e1f6cfb18..0856d42e6909 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -47,9 +47,8 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfobj")
+ACPI_MODULE_NAME("nsxfobj")
/*******************************************************************************
*
@@ -63,15 +62,10 @@
* DESCRIPTION: This routine returns the type associatd with a particular handle
*
******************************************************************************/
-
-acpi_status
-acpi_get_type (
- acpi_handle handle,
- acpi_object_type *ret_type)
+acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter Validation */
@@ -88,27 +82,26 @@ acpi_get_type (
return (AE_OK);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
*ret_type = node->type;
-
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_type);
+EXPORT_SYMBOL(acpi_get_type);
/*******************************************************************************
*
@@ -124,14 +117,10 @@ EXPORT_SYMBOL(acpi_get_type);
*
******************************************************************************/
-acpi_status
-acpi_get_parent (
- acpi_handle handle,
- acpi_handle *ret_handle)
+acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
if (!ret_handle) {
return (AE_BAD_PARAMETER);
@@ -143,14 +132,14 @@ acpi_get_parent (
return (AE_NULL_ENTRY);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -159,22 +148,21 @@ acpi_get_parent (
/* Get the parent entry */
*ret_handle =
- acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node));
+ acpi_ns_convert_entry_to_handle(acpi_ns_get_parent_node(node));
/* Return exception if parent is null */
- if (!acpi_ns_get_parent_node (node)) {
+ if (!acpi_ns_get_parent_node(node)) {
status = AE_NULL_ENTRY;
}
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_parent);
+EXPORT_SYMBOL(acpi_get_parent);
/*******************************************************************************
*
@@ -195,17 +183,14 @@ EXPORT_SYMBOL(acpi_get_parent);
******************************************************************************/
acpi_status
-acpi_get_next_object (
- acpi_object_type type,
- acpi_handle parent,
- acpi_handle child,
- acpi_handle *ret_handle)
+acpi_get_next_object(acpi_object_type type,
+ acpi_handle parent,
+ acpi_handle child, acpi_handle * ret_handle)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- struct acpi_namespace_node *parent_node = NULL;
- struct acpi_namespace_node *child_node = NULL;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ struct acpi_namespace_node *parent_node = NULL;
+ struct acpi_namespace_node *child_node = NULL;
/* Parameter validation */
@@ -213,8 +198,8 @@ acpi_get_next_object (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -223,17 +208,16 @@ acpi_get_next_object (
if (!child) {
/* Start search at the beginning of the specified scope */
- parent_node = acpi_ns_map_handle_to_node (parent);
+ parent_node = acpi_ns_map_handle_to_node(parent);
if (!parent_node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Non-null handle, ignore the parent */
/* Convert and validate the handle */
- child_node = acpi_ns_map_handle_to_node (child);
+ child_node = acpi_ns_map_handle_to_node(child);
if (!child_node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -242,20 +226,19 @@ acpi_get_next_object (
/* Internal function does the real work */
- node = acpi_ns_get_next_node (type, parent_node, child_node);
+ node = acpi_ns_get_next_node(type, parent_node, child_node);
if (!node) {
status = AE_NOT_FOUND;
goto unlock_and_exit;
}
if (ret_handle) {
- *ret_handle = acpi_ns_convert_entry_to_handle (node);
+ *ret_handle = acpi_ns_convert_entry_to_handle(node);
}
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a82834b32752..64b98e82feb7 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -34,16 +34,18 @@
#define ACPI_NUMA 0x80000000
#define _COMPONENT ACPI_NUMA
- ACPI_MODULE_NAME ("numa")
+ACPI_MODULE_NAME("numa")
-extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries);
+extern int __init acpi_table_parse_madt_family(enum acpi_table_id id,
+ unsigned long madt_size,
+ int entry_id,
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries);
-void __init
-acpi_table_print_srat_entry (
- acpi_table_entry_header *header)
+void __init acpi_table_print_srat_entry(acpi_table_entry_header * header)
{
- ACPI_FUNCTION_NAME ("acpi_table_print_srat_entry");
+ ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
if (!header)
return;
@@ -52,48 +54,55 @@ acpi_table_print_srat_entry (
case ACPI_SRAT_PROCESSOR_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
- {
- struct acpi_table_processor_affinity *p =
- (struct acpi_table_processor_affinity*) header;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
- p->apic_id, p->lsapic_eid, p->proximity_domain,
- p->flags.enabled?"enabled":"disabled"));
- }
-#endif /* ACPI_DEBUG_OUTPUT */
+ {
+ struct acpi_table_processor_affinity *p =
+ (struct acpi_table_processor_affinity *)header;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
+ p->apic_id, p->lsapic_eid,
+ p->proximity_domain,
+ p->flags.
+ enabled ? "enabled" : "disabled"));
+ }
+#endif /* ACPI_DEBUG_OUTPUT */
break;
case ACPI_SRAT_MEMORY_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
- {
- struct acpi_table_memory_affinity *p =
- (struct acpi_table_memory_affinity*) header;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
- p->base_addr_hi, p->base_addr_lo, p->length_hi, p->length_lo,
- p->memory_type, p->proximity_domain,
- p->flags.enabled ? "enabled" : "disabled",
- p->flags.hot_pluggable ? " hot-pluggable" : ""));
- }
-#endif /* ACPI_DEBUG_OUTPUT */
+ {
+ struct acpi_table_memory_affinity *p =
+ (struct acpi_table_memory_affinity *)header;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
+ p->base_addr_hi, p->base_addr_lo,
+ p->length_hi, p->length_lo,
+ p->memory_type, p->proximity_domain,
+ p->flags.
+ enabled ? "enabled" : "disabled",
+ p->flags.
+ hot_pluggable ? " hot-pluggable" :
+ ""));
+ }
+#endif /* ACPI_DEBUG_OUTPUT */
break;
default:
- printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n",
- header->type);
+ printk(KERN_WARNING PREFIX
+ "Found unsupported SRAT entry (type = 0x%x)\n",
+ header->type);
break;
}
}
-
-static int __init
-acpi_parse_slit (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_slit(unsigned long phys_addr, unsigned long size)
{
- struct acpi_table_slit *slit;
- u32 localities;
+ struct acpi_table_slit *slit;
+ u32 localities;
if (!phys_addr || !size)
return -EINVAL;
- slit = (struct acpi_table_slit *) __va(phys_addr);
+ slit = (struct acpi_table_slit *)__va(phys_addr);
/* downcast just for %llu vs %lu for i386/ia64 */
localities = (u32) slit->localities;
@@ -103,15 +112,13 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
return 0;
}
-
static int __init
-acpi_parse_processor_affinity (
- acpi_table_entry_header *header,
- const unsigned long end)
+acpi_parse_processor_affinity(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_processor_affinity *processor_affinity;
- processor_affinity = (struct acpi_table_processor_affinity*) header;
+ processor_affinity = (struct acpi_table_processor_affinity *)header;
if (!processor_affinity)
return -EINVAL;
@@ -123,15 +130,13 @@ acpi_parse_processor_affinity (
return 0;
}
-
static int __init
-acpi_parse_memory_affinity (
- acpi_table_entry_header *header,
- const unsigned long end)
+acpi_parse_memory_affinity(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_memory_affinity *memory_affinity;
- memory_affinity = (struct acpi_table_memory_affinity*) header;
+ memory_affinity = (struct acpi_table_memory_affinity *)header;
if (!memory_affinity)
return -EINVAL;
@@ -143,36 +148,30 @@ acpi_parse_memory_affinity (
return 0;
}
-
-static int __init
-acpi_parse_srat (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_srat(unsigned long phys_addr, unsigned long size)
{
- struct acpi_table_srat *srat;
+ struct acpi_table_srat *srat;
if (!phys_addr || !size)
return -EINVAL;
- srat = (struct acpi_table_srat *) __va(phys_addr);
+ srat = (struct acpi_table_srat *)__va(phys_addr);
return 0;
}
-
int __init
-acpi_table_parse_srat (
- enum acpi_srat_entry_id id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_srat(enum acpi_srat_entry_id id,
+ acpi_madt_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
- id, handler, max_entries);
+ return acpi_table_parse_madt_family(ACPI_SRAT,
+ sizeof(struct acpi_table_srat), id,
+ handler, max_entries);
}
-
-int __init
-acpi_numa_init(void)
+int __init acpi_numa_init(void)
{
- int result;
+ int result;
/* SRAT: Static Resource Affinity Table */
result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat);
@@ -181,9 +180,7 @@ acpi_numa_init(void)
result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
acpi_parse_processor_affinity,
NR_CPUS);
- result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
- acpi_parse_memory_affinity,
- NR_NODE_MEMBLKS); // IA64 specific
+ result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific
}
/* SLIT: System Locality Information Table */
@@ -193,8 +190,7 @@ acpi_numa_init(void)
return 0;
}
-int
-acpi_get_pxm(acpi_handle h)
+int acpi_get_pxm(acpi_handle h)
{
unsigned long pxm;
acpi_status status;
@@ -207,7 +203,8 @@ acpi_get_pxm(acpi_handle h)
if (ACPI_SUCCESS(status))
return (int)pxm;
status = acpi_get_parent(handle, &phandle);
- } while(ACPI_SUCCESS(status));
+ } while (ACPI_SUCCESS(status));
return -1;
}
+
EXPORT_SYMBOL(acpi_get_pxm);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 0d11d6e6abd6..d528c750a380 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -45,16 +45,12 @@
#include <linux/efi.h>
-
#define _COMPONENT ACPI_OS_SERVICES
-ACPI_MODULE_NAME ("osl")
-
+ACPI_MODULE_NAME("osl")
#define PREFIX "ACPI: "
-
-struct acpi_os_dpc
-{
- acpi_osd_exec_callback function;
- void *context;
+struct acpi_os_dpc {
+ acpi_osd_exec_callback function;
+ void *context;
};
#ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -69,7 +65,7 @@ int acpi_in_debugger;
EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
-#endif /*ENABLE_DEBUGGER*/
+#endif /*ENABLE_DEBUGGER */
int acpi_specific_hotkey_enabled = TRUE;
EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
@@ -79,33 +75,29 @@ static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
-acpi_status
-acpi_os_initialize(void)
+acpi_status acpi_os_initialize(void)
{
return AE_OK;
}
-acpi_status
-acpi_os_initialize1(void)
+acpi_status acpi_os_initialize1(void)
{
/*
* Initialize PCI configuration space access, as we'll need to access
* it while walking the namespace (bus 0 and root bridges w/ _BBNs).
*/
-#ifdef CONFIG_ACPI_PCI
if (!raw_pci_ops) {
- printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n");
+ printk(KERN_ERR PREFIX
+ "Access to PCI configuration space unavailable\n");
return AE_NULL_ENTRY;
}
-#endif
kacpid_wq = create_singlethread_workqueue("kacpid");
BUG_ON(!kacpid_wq);
return AE_OK;
}
-acpi_status
-acpi_os_terminate(void)
+acpi_status acpi_os_terminate(void)
{
if (acpi_irq_handler) {
acpi_os_remove_interrupt_handler(acpi_irq_irq,
@@ -117,21 +109,20 @@ acpi_os_terminate(void)
return AE_OK;
}
-void
-acpi_os_printf(const char *fmt,...)
+void acpi_os_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
acpi_os_vprintf(fmt, args);
va_end(args);
}
+
EXPORT_SYMBOL(acpi_os_printf);
-void
-acpi_os_vprintf(const char *fmt, va_list args)
+void acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
-
+
vsprintf(buffer, fmt, args);
#ifdef ENABLE_DEBUGGER
@@ -146,8 +137,7 @@ acpi_os_vprintf(const char *fmt, va_list args)
}
extern int acpi_in_resume;
-void *
-acpi_os_allocate(acpi_size size)
+void *acpi_os_allocate(acpi_size size)
{
if (acpi_in_resume)
return kmalloc(size, GFP_ATOMIC);
@@ -155,31 +145,32 @@ acpi_os_allocate(acpi_size size)
return kmalloc(size, GFP_KERNEL);
}
-void
-acpi_os_free(void *ptr)
+void acpi_os_free(void *ptr)
{
kfree(ptr);
}
+
EXPORT_SYMBOL(acpi_os_free);
-acpi_status
-acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
+acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
{
if (efi_enabled) {
addr->pointer_type = ACPI_PHYSICAL_POINTER;
if (efi.acpi20)
addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi20);
+ (acpi_physical_address) virt_to_phys(efi.acpi20);
else if (efi.acpi)
addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi);
+ (acpi_physical_address) virt_to_phys(efi.acpi);
else {
- printk(KERN_ERR PREFIX "System description tables not found\n");
+ printk(KERN_ERR PREFIX
+ "System description tables not found\n");
return AE_NOT_FOUND;
}
} else {
if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
- printk(KERN_ERR PREFIX "System description tables not found\n");
+ printk(KERN_ERR PREFIX
+ "System description tables not found\n");
return AE_NOT_FOUND;
}
}
@@ -188,11 +179,12 @@ acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
}
acpi_status
-acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
+ void __iomem ** virt)
{
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
- *virt = (void __iomem *) phys_to_virt(phys);
+ *virt = (void __iomem *)phys_to_virt(phys);
} else {
*virt = ioremap(phys, size);
}
@@ -202,9 +194,9 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **vi
return AE_BAD_PARAMETER;
}
/*
- * ioremap checks to ensure this is in reserved space
- */
- *virt = ioremap((unsigned long) phys, size);
+ * ioremap checks to ensure this is in reserved space
+ */
+ *virt = ioremap((unsigned long)phys, size);
}
if (!*virt)
@@ -213,17 +205,16 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **vi
return AE_OK;
}
-void
-acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
+void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
iounmap(virt);
}
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
+acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
{
- if(!phys || !virt)
+ if (!phys || !virt)
return AE_BAD_PARAMETER;
*phys = virt_to_phys(virt);
@@ -237,16 +228,16 @@ acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
acpi_status
-acpi_os_predefined_override (const struct acpi_predefined_names *init_val,
- acpi_string *new_val)
+acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
+ acpi_string * new_val)
{
if (!init_val || !new_val)
return AE_BAD_PARAMETER;
*new_val = NULL;
- if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
+ if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
- acpi_os_name);
+ acpi_os_name);
*new_val = acpi_os_name;
}
@@ -254,15 +245,15 @@ acpi_os_predefined_override (const struct acpi_predefined_names *init_val,
}
acpi_status
-acpi_os_table_override (struct acpi_table_header *existing_table,
- struct acpi_table_header **new_table)
+acpi_os_table_override(struct acpi_table_header * existing_table,
+ struct acpi_table_header ** new_table)
{
if (!existing_table || !new_table)
return AE_BAD_PARAMETER;
#ifdef CONFIG_ACPI_CUSTOM_DSDT
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
- *new_table = (struct acpi_table_header*)AmlCode;
+ *new_table = (struct acpi_table_header *)AmlCode;
else
*new_table = NULL;
#else
@@ -271,14 +262,14 @@ acpi_os_table_override (struct acpi_table_header *existing_table,
return AE_OK;
}
-static irqreturn_t
-acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
+ return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
}
acpi_status
-acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context)
+acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
+ void *context)
{
unsigned int irq;
@@ -305,8 +296,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *conte
return AE_OK;
}
-acpi_status
-acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
+acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
{
if (irq) {
free_irq(irq, acpi_irq);
@@ -321,16 +311,15 @@ acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
* Running in interpreter thread context, safe to sleep
*/
-void
-acpi_os_sleep(acpi_integer ms)
+void acpi_os_sleep(acpi_integer ms)
{
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(((signed long) ms * HZ) / 1000);
+ schedule_timeout(((signed long)ms * HZ) / 1000);
}
+
EXPORT_SYMBOL(acpi_os_sleep);
-void
-acpi_os_stall(u32 us)
+void acpi_os_stall(u32 us)
{
while (us) {
u32 delay = 1000;
@@ -342,6 +331,7 @@ acpi_os_stall(u32 us)
us -= delay;
}
}
+
EXPORT_SYMBOL(acpi_os_stall);
/*
@@ -349,8 +339,7 @@ EXPORT_SYMBOL(acpi_os_stall);
* Returns 64-bit free-running, monotonically increasing timer
* with 100ns granularity
*/
-u64
-acpi_os_get_timer (void)
+u64 acpi_os_get_timer(void)
{
static u64 t;
@@ -367,27 +356,22 @@ acpi_os_get_timer (void)
return ++t;
}
-acpi_status
-acpi_os_read_port(
- acpi_io_address port,
- u32 *value,
- u32 width)
+acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
{
u32 dummy;
if (!value)
value = &dummy;
- switch (width)
- {
+ switch (width) {
case 8:
- *(u8*) value = inb(port);
+ *(u8 *) value = inb(port);
break;
case 16:
- *(u16*) value = inw(port);
+ *(u16 *) value = inw(port);
break;
case 32:
- *(u32*) value = inl(port);
+ *(u32 *) value = inl(port);
break;
default:
BUG();
@@ -395,16 +379,12 @@ acpi_os_read_port(
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_read_port);
-acpi_status
-acpi_os_write_port(
- acpi_io_address port,
- u32 value,
- u32 width)
+acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{
- switch (width)
- {
+ switch (width) {
case 8:
outb(value, port);
break;
@@ -420,40 +400,38 @@ acpi_os_write_port(
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_write_port);
acpi_status
-acpi_os_read_memory(
- acpi_physical_address phys_addr,
- u32 *value,
- u32 width)
+acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
{
- u32 dummy;
- void __iomem *virt_addr;
- int iomem = 0;
+ u32 dummy;
+ void __iomem *virt_addr;
+ int iomem = 0;
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
/* HACK ALERT! We can use readb/w/l on real memory too.. */
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
} else {
iomem = 1;
virt_addr = ioremap(phys_addr, width);
}
} else
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
if (!value)
value = &dummy;
switch (width) {
case 8:
- *(u8*) value = readb(virt_addr);
+ *(u8 *) value = readb(virt_addr);
break;
case 16:
- *(u16*) value = readw(virt_addr);
+ *(u16 *) value = readw(virt_addr);
break;
case 32:
- *(u32*) value = readl(virt_addr);
+ *(u32 *) value = readl(virt_addr);
break;
default:
BUG();
@@ -468,24 +446,21 @@ acpi_os_read_memory(
}
acpi_status
-acpi_os_write_memory(
- acpi_physical_address phys_addr,
- u32 value,
- u32 width)
+acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
- void __iomem *virt_addr;
- int iomem = 0;
+ void __iomem *virt_addr;
+ int iomem = 0;
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
/* HACK ALERT! We can use writeb/w/l on real memory too */
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
} else {
iomem = 1;
virt_addr = ioremap(phys_addr, width);
}
} else
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
switch (width) {
case 8:
@@ -507,10 +482,9 @@ acpi_os_write_memory(
return AE_OK;
}
-#ifdef CONFIG_ACPI_PCI
-
acpi_status
-acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width)
+acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+ void *value, u32 width)
{
int result, size;
@@ -534,15 +508,17 @@ acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value
BUG_ON(!raw_pci_ops);
result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
- PCI_DEVFN(pci_id->device, pci_id->function),
- reg, size, value);
+ PCI_DEVFN(pci_id->device, pci_id->function),
+ reg, size, value);
return (result ? AE_ERROR : AE_OK);
}
+
EXPORT_SYMBOL(acpi_os_read_pci_configuration);
acpi_status
-acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width)
+acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+ acpi_integer value, u32 width)
{
int result, size;
@@ -563,56 +539,62 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ
BUG_ON(!raw_pci_ops);
result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
- PCI_DEVFN(pci_id->device, pci_id->function),
- reg, size, value);
+ PCI_DEVFN(pci_id->device, pci_id->function),
+ reg, size, value);
return (result ? AE_ERROR : AE_OK);
}
/* TODO: Change code to take advantage of driver model more */
-static void
-acpi_os_derive_pci_id_2 (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id,
- int *is_bridge,
- u8 *bus_number)
+static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
+ acpi_handle chandle, /* current node */
+ struct acpi_pci_id **id,
+ int *is_bridge, u8 * bus_number)
{
- acpi_handle handle;
- struct acpi_pci_id *pci_id = *id;
- acpi_status status;
- unsigned long temp;
- acpi_object_type type;
- u8 tu8;
+ acpi_handle handle;
+ struct acpi_pci_id *pci_id = *id;
+ acpi_status status;
+ unsigned long temp;
+ acpi_object_type type;
+ u8 tu8;
acpi_get_parent(chandle, &handle);
if (handle != rhandle) {
- acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number);
+ acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
+ bus_number);
status = acpi_get_type(handle, &type);
- if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) )
+ if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
return;
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp);
+ status =
+ acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
+ &temp);
if (ACPI_SUCCESS(status)) {
- pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp));
- pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp));
+ pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
+ pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
if (*is_bridge)
pci_id->bus = *bus_number;
/* any nicer way to get bus number of bridge ? */
- status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8);
- if (ACPI_SUCCESS(status) &&
- ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
- status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8);
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
+ 8);
+ if (ACPI_SUCCESS(status)
+ && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x18,
+ &tu8, 8);
if (!ACPI_SUCCESS(status)) {
/* Certainly broken... FIX ME */
return;
}
*is_bridge = 1;
pci_id->bus = tu8;
- status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8);
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x19,
+ &tu8, 8);
if (ACPI_SUCCESS(status)) {
*bus_number = tu8;
}
@@ -622,11 +604,9 @@ acpi_os_derive_pci_id_2 (
}
}
-void
-acpi_os_derive_pci_id (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id)
+void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
+ acpi_handle chandle, /* current node */
+ struct acpi_pci_id **id)
{
int is_bridge = 1;
u8 bus_number = (*id)->bus;
@@ -634,49 +614,15 @@ acpi_os_derive_pci_id (
acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
}
-#else /*!CONFIG_ACPI_PCI*/
-
-acpi_status
-acpi_os_write_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- acpi_integer value,
- u32 width)
-{
- return AE_SUPPORT;
-}
-
-acpi_status
-acpi_os_read_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- void *value,
- u32 width)
-{
- return AE_SUPPORT;
-}
-
-void
-acpi_os_derive_pci_id (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id)
-{
-}
-
-#endif /*CONFIG_ACPI_PCI*/
-
-static void
-acpi_os_execute_deferred (
- void *context)
+static void acpi_os_execute_deferred(void *context)
{
- struct acpi_os_dpc *dpc = NULL;
+ struct acpi_os_dpc *dpc = NULL;
- ACPI_FUNCTION_TRACE ("os_execute_deferred");
+ ACPI_FUNCTION_TRACE("os_execute_deferred");
- dpc = (struct acpi_os_dpc *) context;
+ dpc = (struct acpi_os_dpc *)context;
if (!dpc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
return_VOID;
}
@@ -688,21 +634,21 @@ acpi_os_execute_deferred (
}
acpi_status
-acpi_os_queue_for_execution(
- u32 priority,
- acpi_osd_exec_callback function,
- void *context)
+acpi_os_queue_for_execution(u32 priority,
+ acpi_osd_exec_callback function, void *context)
{
- acpi_status status = AE_OK;
- struct acpi_os_dpc *dpc;
- struct work_struct *task;
+ acpi_status status = AE_OK;
+ struct acpi_os_dpc *dpc;
+ struct work_struct *task;
- ACPI_FUNCTION_TRACE ("os_queue_for_execution");
+ ACPI_FUNCTION_TRACE("os_queue_for_execution");
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Scheduling function [%p(%p)] for deferred execution.\n",
+ function, context));
if (!function)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
/*
* Allocate/initialize DPC structure. Note that this memory will be
@@ -715,146 +661,94 @@ acpi_os_queue_for_execution(
* from the same memory.
*/
- dpc = kmalloc(sizeof(struct acpi_os_dpc)+sizeof(struct work_struct), GFP_ATOMIC);
+ dpc =
+ kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
+ GFP_ATOMIC);
if (!dpc)
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
dpc->function = function;
dpc->context = context;
- task = (void *)(dpc+1);
- INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
+ 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"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Call to queue_work() failed.\n"));
kfree(dpc);
status = AE_ERROR;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
+
EXPORT_SYMBOL(acpi_os_queue_for_execution);
-void
-acpi_os_wait_events_complete(
- void *context)
+void acpi_os_wait_events_complete(void *context)
{
flush_workqueue(kacpid_wq);
}
+
EXPORT_SYMBOL(acpi_os_wait_events_complete);
/*
* Allocate the memory for a spinlock and initialize it.
*/
-acpi_status
-acpi_os_create_lock (
- acpi_handle *out_handle)
+acpi_status acpi_os_create_lock(acpi_handle * out_handle)
{
spinlock_t *lock_ptr;
- ACPI_FUNCTION_TRACE ("os_create_lock");
+ ACPI_FUNCTION_TRACE("os_create_lock");
lock_ptr = acpi_os_allocate(sizeof(spinlock_t));
spin_lock_init(lock_ptr);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
*out_handle = lock_ptr;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*
* Deallocate the memory for a spinlock.
*/
-void
-acpi_os_delete_lock (
- acpi_handle handle)
+void acpi_os_delete_lock(acpi_handle handle)
{
- ACPI_FUNCTION_TRACE ("os_create_lock");
+ ACPI_FUNCTION_TRACE("os_create_lock");
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
acpi_os_free(handle);
return_VOID;
}
-/*
- * Acquire a spinlock.
- *
- * handle is a pointer to the spinlock_t.
- * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
- * that indicates whether we are at interrupt level.
- */
-void
-acpi_os_acquire_lock (
- acpi_handle handle,
- u32 flags)
-{
- ACPI_FUNCTION_TRACE ("os_acquire_lock");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle,
- ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
-
- if (flags & ACPI_NOT_ISR)
- ACPI_DISABLE_IRQS();
-
- spin_lock((spinlock_t *)handle);
-
- return_VOID;
-}
-
-
-/*
- * Release a spinlock. See above.
- */
-void
-acpi_os_release_lock (
- acpi_handle handle,
- u32 flags)
-{
- ACPI_FUNCTION_TRACE ("os_release_lock");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle,
- ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
-
- spin_unlock((spinlock_t *)handle);
-
- if (flags & ACPI_NOT_ISR)
- ACPI_ENABLE_IRQS();
-
- return_VOID;
-}
-
-
acpi_status
-acpi_os_create_semaphore(
- u32 max_units,
- u32 initial_units,
- acpi_handle *handle)
+acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
{
- struct semaphore *sem = NULL;
+ struct semaphore *sem = NULL;
- ACPI_FUNCTION_TRACE ("os_create_semaphore");
+ ACPI_FUNCTION_TRACE("os_create_semaphore");
sem = acpi_os_allocate(sizeof(struct semaphore));
if (!sem)
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
memset(sem, 0, sizeof(struct semaphore));
sema_init(sem, initial_units);
- *handle = (acpi_handle*)sem;
+ *handle = (acpi_handle *) sem;
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
+ *handle, initial_units));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_os_create_semaphore);
+EXPORT_SYMBOL(acpi_os_create_semaphore);
/*
* TODO: A better way to delete semaphores? Linux doesn't have a
@@ -863,25 +757,24 @@ EXPORT_SYMBOL(acpi_os_create_semaphore);
* we at least check for blocked threads and signal/cancel them?
*/
-acpi_status
-acpi_os_delete_semaphore(
- acpi_handle handle)
+acpi_status acpi_os_delete_semaphore(acpi_handle handle)
{
- struct semaphore *sem = (struct semaphore*) handle;
+ struct semaphore *sem = (struct semaphore *)handle;
- ACPI_FUNCTION_TRACE ("os_delete_semaphore");
+ ACPI_FUNCTION_TRACE("os_delete_semaphore");
if (!sem)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
- acpi_os_free(sem); sem = NULL;
+ acpi_os_free(sem);
+ sem = NULL;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_os_delete_semaphore);
+EXPORT_SYMBOL(acpi_os_delete_semaphore);
/*
* TODO: The kernel doesn't have a 'down_timeout' function -- had to
@@ -892,31 +785,27 @@ EXPORT_SYMBOL(acpi_os_delete_semaphore);
*
* TODO: Support for units > 1?
*/
-acpi_status
-acpi_os_wait_semaphore(
- acpi_handle handle,
- u32 units,
- u16 timeout)
+acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
{
- acpi_status status = AE_OK;
- struct semaphore *sem = (struct semaphore*)handle;
- int ret = 0;
+ acpi_status status = AE_OK;
+ struct semaphore *sem = (struct semaphore *)handle;
+ int ret = 0;
- ACPI_FUNCTION_TRACE ("os_wait_semaphore");
+ ACPI_FUNCTION_TRACE("os_wait_semaphore");
if (!sem || (units < 1))
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
if (units > 1)
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
+ handle, units, timeout));
if (in_atomic())
timeout = 0;
- switch (timeout)
- {
+ switch (timeout) {
/*
* No Wait:
* --------
@@ -924,8 +813,8 @@ acpi_os_wait_semaphore(
* acquire the semaphore if available otherwise return AE_TIME
* (a.k.a. 'would block').
*/
- case 0:
- if(down_trylock(sem))
+ case 0:
+ if (down_trylock(sem))
status = AE_TIME;
break;
@@ -933,7 +822,7 @@ acpi_os_wait_semaphore(
* Wait Indefinitely:
* ------------------
*/
- case ACPI_WAIT_FOREVER:
+ case ACPI_WAIT_FOREVER:
down(sem);
break;
@@ -941,11 +830,11 @@ acpi_os_wait_semaphore(
* Wait w/ Timeout:
* ----------------
*/
- default:
+ default:
// TODO: A better timeout algorithm?
{
int i = 0;
- static const int quantum_ms = 1000/HZ;
+ static const int quantum_ms = 1000 / HZ;
ret = down_trylock(sem);
for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
@@ -953,7 +842,7 @@ acpi_os_wait_semaphore(
schedule_timeout(1);
ret = down_trylock(sem);
}
-
+
if (ret != 0)
status = AE_TIME;
}
@@ -961,47 +850,48 @@ acpi_os_wait_semaphore(
}
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n",
- handle, units, timeout, acpi_format_exception(status)));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Failed to acquire semaphore[%p|%d|%d], %s\n",
+ handle, units, timeout,
+ acpi_format_exception(status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Acquired semaphore[%p|%d|%d]\n", handle,
+ units, timeout));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_os_wait_semaphore);
+EXPORT_SYMBOL(acpi_os_wait_semaphore);
/*
* TODO: Support for units > 1?
*/
-acpi_status
-acpi_os_signal_semaphore(
- acpi_handle handle,
- u32 units)
+acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
{
- struct semaphore *sem = (struct semaphore *) handle;
+ struct semaphore *sem = (struct semaphore *)handle;
- ACPI_FUNCTION_TRACE ("os_signal_semaphore");
+ ACPI_FUNCTION_TRACE("os_signal_semaphore");
if (!sem || (units < 1))
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
if (units > 1)
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
+ units));
up(sem);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
+
EXPORT_SYMBOL(acpi_os_signal_semaphore);
#ifdef ACPI_FUTURE_USAGE
-u32
-acpi_os_get_line(char *buffer)
+u32 acpi_os_get_line(char *buffer)
{
#ifdef ENABLE_DEBUGGER
@@ -1018,22 +908,21 @@ acpi_os_get_line(char *buffer)
return 0;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/* Assumes no unreadable holes inbetween */
-u8
-acpi_os_readable(void *ptr, acpi_size len)
+u8 acpi_os_readable(void *ptr, acpi_size len)
{
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
char tmp;
- return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);
+ return !__get_user(tmp, (char __user *)ptr)
+ && !__get_user(tmp, (char __user *)ptr + len - 1);
#endif
return 1;
}
#ifdef ACPI_FUTURE_USAGE
-u8
-acpi_os_writable(void *ptr, acpi_size len)
+u8 acpi_os_writable(void *ptr, acpi_size len)
{
/* could do dummy write (racy) or a kernel page table lookup.
The later may be difficult at early boot when kmap doesn't work yet. */
@@ -1041,8 +930,7 @@ acpi_os_writable(void *ptr, acpi_size len)
}
#endif
-u32
-acpi_os_get_thread_id (void)
+u32 acpi_os_get_thread_id(void)
{
if (!in_atomic())
return current->pid;
@@ -1050,13 +938,9 @@ acpi_os_get_thread_id (void)
return 0;
}
-acpi_status
-acpi_os_signal (
- u32 function,
- void *info)
+acpi_status acpi_os_signal(u32 function, void *info)
{
- switch (function)
- {
+ switch (function) {
case ACPI_SIGNAL_FATAL:
printk(KERN_ERR PREFIX "Fatal opcode executed\n");
break;
@@ -1076,13 +960,13 @@ acpi_os_signal (
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_signal);
-static int __init
-acpi_os_name_setup(char *str)
+static int __init acpi_os_name_setup(char *str)
{
char *p = acpi_os_name;
- int count = ACPI_MAX_OVERRIDE_LEN-1;
+ int count = ACPI_MAX_OVERRIDE_LEN - 1;
if (!str || !*str)
return 0;
@@ -1098,7 +982,7 @@ acpi_os_name_setup(char *str)
*p = 0;
return 1;
-
+
}
__setup("acpi_os_name=", acpi_os_name_setup);
@@ -1108,16 +992,15 @@ __setup("acpi_os_name=", acpi_os_name_setup);
* empty string disables _OSI
* TBD additional string adds to _OSI
*/
-static int __init
-acpi_osi_setup(char *str)
+static int __init acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
- } else
- {
+ } else {
/* TBD */
- printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str);
+ printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
+ str);
}
return 1;
@@ -1126,8 +1009,7 @@ acpi_osi_setup(char *str)
__setup("acpi_osi=", acpi_osi_setup);
/* enable serialization to combat AE_ALREADY_EXISTS errors */
-static int __init
-acpi_serialize_setup(char *str)
+static int __init acpi_serialize_setup(char *str)
{
printk(KERN_INFO PREFIX "serialize enabled\n");
@@ -1147,8 +1029,7 @@ __setup("acpi_serialize", acpi_serialize_setup);
* Run-time events on the same GPE this flag is available
* to tell Linux to keep the wake-time GPEs enabled at run-time.
*/
-static int __init
-acpi_wake_gpes_always_on_setup(char *str)
+static int __init acpi_wake_gpes_always_on_setup(char *str)
{
printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
@@ -1159,8 +1040,7 @@ acpi_wake_gpes_always_on_setup(char *str)
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
-int __init
-acpi_hotkey_setup(char *str)
+static int __init acpi_hotkey_setup(char *str)
{
acpi_specific_hotkey_enabled = FALSE;
return 1;
@@ -1174,5 +1054,132 @@ __setup("acpi_generic_hotkey", acpi_hotkey_setup);
*/
unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
-
EXPORT_SYMBOL(max_cstate);
+
+/*
+ * Acquire a spinlock.
+ *
+ * handle is a pointer to the spinlock_t.
+ * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
+ * that indicates whether we are at interrupt level.
+ */
+
+unsigned long acpi_os_acquire_lock(acpi_handle handle)
+{
+ unsigned long flags;
+ spin_lock_irqsave((spinlock_t *) handle, flags);
+ return flags;
+}
+
+/*
+ * Release a spinlock. See above.
+ */
+
+void acpi_os_release_lock(acpi_handle handle, unsigned long flags)
+{
+ spin_unlock_irqrestore((spinlock_t *) handle, flags);
+}
+
+#ifndef ACPI_USE_LOCAL_CACHE
+
+/*******************************************************************************
+ *
+ * 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
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+
+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;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_purge_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
+{
+ (void)kmem_cache_shrink(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_delete_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ * cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
+{
+ (void)kmem_cache_destroy(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_release_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * Object - The object to be released
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ * the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
+{
+ kmem_cache_free(cache, object);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_acquire_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * ReturnObject - Where the object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ * the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(acpi_cache_t * cache)
+{
+ void *object = kmem_cache_alloc(cache, GFP_KERNEL);
+ WARN_ON(!object);
+ return object;
+}
+
+#endif
diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile
index bbdd286c660d..db24ee09cf11 100644
--- a/drivers/acpi/parser/Makefile
+++ b/drivers/acpi/parser/Makefile
@@ -2,7 +2,7 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
-obj-y := psargs.o psparse.o pstree.o pswalk.o \
+obj-y := psargs.o psparse.o psloop.o pstree.o pswalk.o \
psopcode.o psscope.o psutils.o psxface.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index b7ac68cc9e1c..5858188f94a6 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -41,25 +41,20 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psargs")
+ACPI_MODULE_NAME("psargs")
/* Local prototypes */
-
static u32
-acpi_ps_get_next_package_length (
- struct acpi_parse_state *parser_state);
-
-static union acpi_parse_object *
-acpi_ps_get_next_field (
- struct acpi_parse_state *parser_state);
+acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
+static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+ *parser_state);
/*******************************************************************************
*
@@ -75,49 +70,43 @@ acpi_ps_get_next_field (
******************************************************************************/
static u32
-acpi_ps_get_next_package_length (
- struct acpi_parse_state *parser_state)
+acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
{
- u32 encoded_length;
- u32 length = 0;
+ u32 encoded_length;
+ u32 length = 0;
+ ACPI_FUNCTION_TRACE("ps_get_next_package_length");
- ACPI_FUNCTION_TRACE ("ps_get_next_package_length");
-
-
- encoded_length = (u32) ACPI_GET8 (parser_state->aml);
+ encoded_length = (u32) ACPI_GET8(parser_state->aml);
parser_state->aml++;
- switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
- case 0: /* 1-byte encoding (bits 0-5) */
+ switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */
+ case 0: /* 1-byte encoding (bits 0-5) */
length = (encoded_length & 0x3F);
break;
+ case 1: /* 2-byte encoding (next byte + bits 0-3) */
- case 1: /* 2-byte encoding (next byte + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml++;
break;
+ case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
- case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml + 1) << 12) |
- (ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml + 1) << 12) |
+ (ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml += 2;
break;
+ case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
- case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml + 2) << 20) |
- (ACPI_GET8 (parser_state->aml + 1) << 12) |
- (ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml + 2) << 20) |
+ (ACPI_GET8(parser_state->aml + 1) << 12) |
+ (ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml += 3;
break;
@@ -127,10 +116,9 @@ acpi_ps_get_next_package_length (
break;
}
- return_VALUE (length);
+ return_VALUE(length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_package_end
@@ -144,25 +132,21 @@ acpi_ps_get_next_package_length (
*
******************************************************************************/
-u8 *
-acpi_ps_get_next_package_end (
- struct acpi_parse_state *parser_state)
+u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
{
- u8 *start = parser_state->aml;
- acpi_native_uint length;
-
-
- ACPI_FUNCTION_TRACE ("ps_get_next_package_end");
+ u8 *start = parser_state->aml;
+ acpi_native_uint length;
+ ACPI_FUNCTION_TRACE("ps_get_next_package_end");
/* Function below changes parser_state->Aml */
- length = (acpi_native_uint) acpi_ps_get_next_package_length (parser_state);
+ length =
+ (acpi_native_uint) acpi_ps_get_next_package_length(parser_state);
- return_PTR (start + length); /* end of package */
+ return_PTR(start + length); /* end of package */
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_namestring
@@ -178,20 +162,16 @@ acpi_ps_get_next_package_end (
*
******************************************************************************/
-char *
-acpi_ps_get_next_namestring (
- struct acpi_parse_state *parser_state)
+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");
+ u8 *start = parser_state->aml;
+ u8 *end = parser_state->aml;
+ ACPI_FUNCTION_TRACE("ps_get_next_namestring");
/* Handle multiple prefix characters */
- while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) {
+ while (acpi_ps_is_prefix_char(ACPI_GET8(end))) {
/* Include prefix '\\' or '^' */
end++;
@@ -199,7 +179,7 @@ acpi_ps_get_next_namestring (
/* Decode the path */
- switch (ACPI_GET8 (end)) {
+ switch (ACPI_GET8(end)) {
case 0:
/* null_name */
@@ -221,7 +201,7 @@ acpi_ps_get_next_namestring (
/* Multiple name segments, 4 chars each */
- end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE);
+ end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE);
break;
default:
@@ -232,11 +212,10 @@ acpi_ps_get_next_namestring (
break;
}
- parser_state->aml = (u8*) end;
- return_PTR ((char *) start);
+ parser_state->aml = (u8 *) end;
+ return_PTR((char *)start);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_namepath
@@ -259,24 +238,20 @@ acpi_ps_get_next_namestring (
******************************************************************************/
acpi_status
-acpi_ps_get_next_namepath (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *arg,
- u8 method_call)
+acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ union acpi_parse_object *arg, u8 method_call)
{
- char *path;
- union acpi_parse_object *name_op;
- acpi_status status = AE_OK;
- union acpi_operand_object *method_desc;
- struct acpi_namespace_node *node;
- union acpi_generic_state scope_info;
+ char *path;
+ union acpi_parse_object *name_op;
+ acpi_status status = AE_OK;
+ union acpi_operand_object *method_desc;
+ 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);
+ path = acpi_ps_get_next_namestring(parser_state);
/* Null path case is allowed */
@@ -296,49 +271,50 @@ acpi_ps_get_next_namepath (
* parent tree, but don't open a new scope -- we just want to lookup the
* object (MUST BE mode EXECUTE to perform upsearch)
*/
- status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- NULL, &node);
- if (ACPI_SUCCESS (status) && method_call) {
+ status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
+ if (ACPI_SUCCESS(status) && method_call) {
if (node->type == ACPI_TYPE_METHOD) {
/* This name is actually a control method invocation */
- method_desc = acpi_ns_get_attached_object (node);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Control Method - %p Desc %p Path=%p\n",
- node, method_desc, path));
+ method_desc = acpi_ns_get_attached_object(node);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Desc %p Path=%p\n",
+ node, method_desc, path));
- name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
+ name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
if (!name_op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Change arg into a METHOD CALL and attach name to it */
- acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
+ acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
name_op->common.value.name = path;
/* Point METHODCALL/NAME to the METHOD Node */
name_op->common.node = node;
- acpi_ps_append_arg (arg, name_op);
+ acpi_ps_append_arg(arg, name_op);
if (!method_desc) {
- ACPI_REPORT_ERROR ((
- "ps_get_next_namepath: Control Method %p has no attached object\n",
- node));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Control Method - %p Args %X\n",
- node, method_desc->method.param_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Args %X\n",
+ node,
+ method_desc->method.
+ param_count));
/* Get the number of arguments to expect */
- walk_state->arg_count = method_desc->method.param_count;
- return_ACPI_STATUS (AE_OK);
+ walk_state->arg_count =
+ method_desc->method.param_count;
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -348,25 +324,26 @@ acpi_ps_get_next_namepath (
*/
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/*
* 1) Any error other than NOT_FOUND is always severe
* 2) NOT_FOUND is only important if we are executing a method.
* 3) If executing a cond_ref_of opcode, NOT_FOUND is ok.
*/
- if ((((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) &&
- (status == AE_NOT_FOUND) &&
- (walk_state->op->common.aml_opcode != AML_COND_REF_OF_OP)) ||
-
- (status != AE_NOT_FOUND)) {
- ACPI_REPORT_NSERROR (path, status);
-
- acpi_os_printf ("search_node %p start_node %p return_node %p\n",
- scope_info.scope.node, parser_state->start_node, node);
-
-
- }
- else {
+ if ((((walk_state->
+ parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND)
+ && (walk_state->op->common.aml_opcode !=
+ AML_COND_REF_OF_OP))
+ || (status != AE_NOT_FOUND)) {
+ ACPI_REPORT_NSERROR(path, status);
+
+ acpi_os_printf
+ ("search_node %p start_node %p return_node %p\n",
+ scope_info.scope.node,
+ parser_state->start_node, node);
+
+ } else {
/*
* We got a NOT_FOUND during table load or we encountered
* a cond_ref_of(x) where the target does not exist.
@@ -381,13 +358,12 @@ acpi_ps_get_next_namepath (
* Regardless of success/failure above,
* Just initialize the Op with the pathname.
*/
- acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
+ acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
arg->common.value.name = path;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_simple_arg
@@ -403,87 +379,81 @@ acpi_ps_get_next_namepath (
******************************************************************************/
void
-acpi_ps_get_next_simple_arg (
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object *arg)
+acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object *arg)
{
- 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:
- acpi_ps_init_op (arg, AML_BYTE_OP);
- arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml);
+ acpi_ps_init_op(arg, AML_BYTE_OP);
+ arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml);
parser_state->aml++;
break;
-
case ARGP_WORDDATA:
- acpi_ps_init_op (arg, AML_WORD_OP);
+ acpi_ps_init_op(arg, AML_WORD_OP);
/* Get 2 bytes from the AML stream */
- ACPI_MOVE_16_TO_32 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_16_TO_32(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 2;
break;
-
case ARGP_DWORDDATA:
- acpi_ps_init_op (arg, AML_DWORD_OP);
+ acpi_ps_init_op(arg, AML_DWORD_OP);
/* Get 4 bytes from the AML stream */
- ACPI_MOVE_32_TO_32 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_32_TO_32(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 4;
break;
-
case ARGP_QWORDDATA:
- acpi_ps_init_op (arg, AML_QWORD_OP);
+ acpi_ps_init_op(arg, AML_QWORD_OP);
/* Get 8 bytes from the AML stream */
- ACPI_MOVE_64_TO_64 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_64_TO_64(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 8;
break;
-
case ARGP_CHARLIST:
- acpi_ps_init_op (arg, AML_STRING_OP);
- arg->common.value.string = (char *) parser_state->aml;
+ acpi_ps_init_op(arg, AML_STRING_OP);
+ arg->common.value.string = (char *)parser_state->aml;
- while (ACPI_GET8 (parser_state->aml) != '\0') {
+ while (ACPI_GET8(parser_state->aml) != '\0') {
parser_state->aml++;
}
parser_state->aml++;
break;
-
case ARGP_NAME:
case ARGP_NAMESTRING:
- acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
- arg->common.value.name = acpi_ps_get_next_namestring (parser_state);
+ acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
+ arg->common.value.name =
+ acpi_ps_get_next_namestring(parser_state);
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid arg_type %X\n", arg_type));
+ ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
break;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_field
@@ -496,24 +466,21 @@ acpi_ps_get_next_simple_arg (
*
******************************************************************************/
-static union acpi_parse_object *
-acpi_ps_get_next_field (
- struct acpi_parse_state *parser_state)
+static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+ *parser_state)
{
- u32 aml_offset = (u32)
- ACPI_PTR_DIFF (parser_state->aml,
- parser_state->aml_start);
- union acpi_parse_object *field;
- u16 opcode;
- u32 name;
-
-
- ACPI_FUNCTION_TRACE ("ps_get_next_field");
+ u32 aml_offset = (u32)
+ ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->aml_start);
+ union acpi_parse_object *field;
+ u16 opcode;
+ u32 name;
+ ACPI_FUNCTION_TRACE("ps_get_next_field");
/* Determine field type */
- switch (ACPI_GET8 (parser_state->aml)) {
+ switch (ACPI_GET8(parser_state->aml)) {
default:
opcode = AML_INT_NAMEDFIELD_OP;
@@ -534,9 +501,9 @@ acpi_ps_get_next_field (
/* Allocate a new field op */
- field = acpi_ps_alloc_op (opcode);
+ field = acpi_ps_alloc_op(opcode);
if (!field) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
field->common.aml_offset = aml_offset;
@@ -548,33 +515,34 @@ acpi_ps_get_next_field (
/* Get the 4-character name */
- ACPI_MOVE_32_TO_32 (&name, parser_state->aml);
- acpi_ps_set_name (field, name);
+ ACPI_MOVE_32_TO_32(&name, parser_state->aml);
+ acpi_ps_set_name(field, name);
parser_state->aml += ACPI_NAME_SIZE;
/* Get the length which is encoded as a package length */
- field->common.value.size = acpi_ps_get_next_package_length (parser_state);
+ field->common.value.size =
+ acpi_ps_get_next_package_length(parser_state);
break;
-
case AML_INT_RESERVEDFIELD_OP:
/* Get the length which is encoded as a package length */
- field->common.value.size = acpi_ps_get_next_package_length (parser_state);
+ field->common.value.size =
+ acpi_ps_get_next_package_length(parser_state);
break;
-
case AML_INT_ACCESSFIELD_OP:
/*
* Get access_type and access_attrib and merge into the field Op
* access_type is first operand, access_attribute is second
*/
- field->common.value.integer = (ACPI_GET8 (parser_state->aml) << 8);
+ field->common.value.integer =
+ (ACPI_GET8(parser_state->aml) << 8);
parser_state->aml++;
- field->common.value.integer |= ACPI_GET8 (parser_state->aml);
+ field->common.value.integer |= ACPI_GET8(parser_state->aml);
parser_state->aml++;
break;
@@ -584,10 +552,9 @@ acpi_ps_get_next_field (
break;
}
- return_PTR (field);
+ return_PTR(field);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_arg
@@ -605,21 +572,17 @@ acpi_ps_get_next_field (
******************************************************************************/
acpi_status
-acpi_ps_get_next_arg (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object **return_arg)
+acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object **return_arg)
{
- union acpi_parse_object *arg = NULL;
- union acpi_parse_object *prev = NULL;
- union acpi_parse_object *field;
- u32 subop;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_get_next_arg", parser_state);
+ union acpi_parse_object *arg = NULL;
+ union acpi_parse_object *prev = NULL;
+ union acpi_parse_object *field;
+ u32 subop;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state);
switch (arg_type) {
case ARGP_BYTEDATA:
@@ -631,37 +594,35 @@ acpi_ps_get_next_arg (
/* Constants, strings, and namestrings are all the same size */
- arg = acpi_ps_alloc_op (AML_BYTE_OP);
+ arg = acpi_ps_alloc_op(AML_BYTE_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
+ acpi_ps_get_next_simple_arg(parser_state, arg_type, arg);
break;
-
case ARGP_PKGLENGTH:
/* Package length, nothing returned */
- parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
+ parser_state->pkg_end =
+ acpi_ps_get_next_package_end(parser_state);
break;
-
case ARGP_FIELDLIST:
if (parser_state->aml < parser_state->pkg_end) {
/* Non-empty list */
while (parser_state->aml < parser_state->pkg_end) {
- field = acpi_ps_get_next_field (parser_state);
+ field = acpi_ps_get_next_field(parser_state);
if (!field) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
if (prev) {
prev->common.next = field;
- }
- else {
+ } else {
arg = field;
}
prev = field;
@@ -673,21 +634,21 @@ acpi_ps_get_next_arg (
}
break;
-
case ARGP_BYTELIST:
if (parser_state->aml < parser_state->pkg_end) {
/* Non-empty list */
- arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP);
+ arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Fill in bytelist data */
arg->common.value.size = (u32)
- ACPI_PTR_DIFF (parser_state->pkg_end, parser_state->aml);
+ ACPI_PTR_DIFF(parser_state->pkg_end,
+ parser_state->aml);
arg->named.data = parser_state->aml;
/* Skip to End of byte data */
@@ -696,32 +657,31 @@ acpi_ps_get_next_arg (
}
break;
-
case ARGP_TARGET:
case ARGP_SUPERNAME:
case ARGP_SIMPLENAME:
- subop = acpi_ps_peek_opcode (parser_state);
- if (subop == 0 ||
- acpi_ps_is_leading_char (subop) ||
- acpi_ps_is_prefix_char (subop)) {
+ subop = acpi_ps_peek_opcode(parser_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);
+ arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ps_get_next_namepath (walk_state, parser_state, arg, 0);
- }
- else {
+ status =
+ acpi_ps_get_next_namepath(walk_state, parser_state,
+ arg, 0);
+ } else {
/* Single complex argument, nothing returned */
walk_state->arg_count = 1;
}
break;
-
case ARGP_DATAOBJ:
case ARGP_TERMARG:
@@ -730,7 +690,6 @@ acpi_ps_get_next_arg (
walk_state->arg_count = 1;
break;
-
case ARGP_DATAOBJLIST:
case ARGP_TERMLIST:
case ARGP_OBJLIST:
@@ -742,14 +701,13 @@ acpi_ps_get_next_arg (
}
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid arg_type: %X\n", arg_type));
+ ACPI_REPORT_ERROR(("Invalid arg_type: %X\n", arg_type));
status = AE_AML_OPERAND_TYPE;
break;
}
*return_arg = arg;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
new file mode 100644
index 000000000000..088d33999d90
--- /dev/null
+++ b/drivers/acpi/parser/psloop.c
@@ -0,0 +1,874 @@
+/******************************************************************************
+ *
+ * Module Name: psloop - Main AML parse loop
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+/*
+ * Parse the AML and build an operation tree as most interpreters,
+ * like Perl, do. Parsing is done by hand rather than with a YACC
+ * generated parser to tightly constrain stack and dynamic memory
+ * usage. At the same time, parsing is kept flexible and the code
+ * fairly compact by parsing based on a list of AML opcode
+ * templates in aml_op_info[]
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/acdispat.h>
+#include <acpi/amlcode.h>
+
+#define _COMPONENT ACPI_PARSER
+ACPI_MODULE_NAME("psloop")
+
+static u32 acpi_gbl_depth = 0;
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_parse_loop
+ *
+ * PARAMETERS: walk_state - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
+ * a tree of ops.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
+{
+ acpi_status status = AE_OK;
+ acpi_status status2;
+ union acpi_parse_object *op = NULL; /* current op */
+ union acpi_parse_object *arg = NULL;
+ union acpi_parse_object *pre_op = NULL;
+ struct acpi_parse_state *parser_state;
+ u8 *aml_op_start = NULL;
+
+ ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state);
+
+ if (walk_state->descending_callback == NULL) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ parser_state = &walk_state->parser_state;
+ walk_state->arg_types = 0;
+
+#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)) {
+ /*
+ * We must check if a predicate to an IF or WHILE statement
+ * was just completed
+ */
+ if ((parser_state->scope->parse_scope.op) &&
+ ((parser_state->scope->parse_scope.op->common.
+ aml_opcode == AML_IF_OP)
+ || (parser_state->scope->parse_scope.op->common.
+ aml_opcode == AML_WHILE_OP))
+ && (walk_state->control_state)
+ && (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING)) {
+ /*
+ * A predicate was just completed, get the value of the
+ * predicate and branch based on that value
+ */
+ walk_state->op = NULL;
+ status =
+ acpi_ds_get_predicate_value(walk_state,
+ ACPI_TO_POINTER
+ (TRUE));
+ if (ACPI_FAILURE(status)
+ && ((status & AE_CODE_MASK) !=
+ AE_CODE_CONTROL)) {
+ if (status == AE_AML_NO_RETURN_VALUE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invoked method did not return a value, %s\n",
+ acpi_format_exception
+ (status)));
+
+ }
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "get_predicate Failed, %s\n",
+ acpi_format_exception
+ (status)));
+ return_ACPI_STATUS(status);
+ }
+
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ }
+
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ 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;
+ walk_state->arg_types = walk_state->prev_arg_types;
+ }
+ }
+#endif
+
+ /* Iterative parsing loop, while there is more AML to process: */
+
+ 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 =
+ (u32) ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->aml_start);
+ walk_state->opcode = acpi_ps_peek_opcode(parser_state);
+
+ /*
+ * First cut to determine what we have found:
+ * 1) A valid AML opcode
+ * 2) A name string
+ * 3) An unknown/invalid opcode
+ */
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(walk_state->opcode);
+ switch (walk_state->op_info->class) {
+ case AML_CLASS_ASCII:
+ case AML_CLASS_PREFIX:
+ /*
+ * Starts with a valid prefix or ASCII char, this is a name
+ * string. Convert the bare name string to a namepath.
+ */
+ walk_state->opcode = AML_INT_NAMEPATH_OP;
+ walk_state->arg_types = ARGP_NAMESTRING;
+ break;
+
+ case AML_CLASS_UNKNOWN:
+
+ /* The opcode is unrecognized. Just skip unknown opcodes */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
+ walk_state->opcode,
+ parser_state->aml,
+ walk_state->aml_offset));
+
+ ACPI_DUMP_BUFFER(parser_state->aml, 128);
+
+ /* Assume one-byte bad opcode */
+
+ parser_state->aml++;
+ continue;
+
+ default:
+
+ /* Found opcode info, this is a normal opcode */
+
+ parser_state->aml +=
+ acpi_ps_get_opcode_size(walk_state->opcode);
+ walk_state->arg_types =
+ walk_state->op_info->parse_args;
+ break;
+ }
+
+ /* 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) {
+ pre_op =
+ acpi_ps_alloc_op(walk_state->
+ opcode);
+ if (!pre_op) {
+ status = AE_NO_MEMORY;
+ goto close_this_op;
+ }
+ }
+
+ pre_op->common.value.arg = NULL;
+ pre_op->common.aml_opcode = walk_state->opcode;
+
+ /*
+ * Get and append arguments until we find the node that contains
+ * the name (the type ARGP_NAME).
+ */
+ while (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)
+ &&
+ (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types) != ARGP_NAME)) {
+ status =
+ acpi_ps_get_next_arg(walk_state,
+ parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types),
+ &arg);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ acpi_ps_append_arg(pre_op, arg);
+ INCREMENT_ARG_LIST(walk_state->
+ arg_types);
+ }
+
+ /*
+ * Make sure that we found a NAME and didn't run out of
+ * arguments
+ */
+ if (!GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)) {
+ status = AE_AML_NO_OPERAND;
+ goto close_this_op;
+ }
+
+ /* We know that this arg is a name, move to next arg */
+
+ INCREMENT_ARG_LIST(walk_state->arg_types);
+
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ walk_state->op = NULL;
+
+ status =
+ walk_state->descending_callback(walk_state,
+ &op);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "During name lookup/catalog, %s\n",
+ acpi_format_exception
+ (status)));
+ goto close_this_op;
+ }
+
+ if (!op) {
+ continue;
+ }
+
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ acpi_ps_append_arg(op,
+ pre_op->common.value.arg);
+ acpi_gbl_depth++;
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ /*
+ * Defer final parsing of an operation_region body,
+ * because we don't have enough info in the first pass
+ * to parse it correctly (i.e., there may be method
+ * calls within the term_arg elements of the body.)
+ *
+ * However, we must continue parsing because
+ * the opregion is not a standalone package --
+ * we don't know where the end is at this point.
+ *
+ * (Length is unknown until parse of the body complete)
+ */
+ op->named.data = aml_op_start;
+ op->named.length = 0;
+ }
+ } else {
+ /* Not a named opcode, just allocate Op and append to parent */
+
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
+ if (!op) {
+ status = AE_NO_MEMORY;
+ goto close_this_op;
+ }
+
+ if (walk_state->op_info->flags & AML_CREATE) {
+ /*
+ * Backup to beginning of create_xXXfield declaration
+ * body_length is unknown until we parse the body
+ */
+ op->named.data = aml_op_start;
+ op->named.length = 0;
+ }
+
+ acpi_ps_append_arg(acpi_ps_get_parent_scope
+ (parser_state), op);
+
+ if ((walk_state->descending_callback != NULL)) {
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ walk_state->op = op;
+
+ status =
+ walk_state->
+ descending_callback(walk_state,
+ &op);
+ status =
+ acpi_ps_next_parse_state(walk_state,
+ op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+ }
+ }
+
+ op->common.aml_offset = walk_state->aml_offset;
+
+ if (walk_state->op_info) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
+ (u32) op->common.aml_opcode,
+ walk_state->op_info->name, op,
+ parser_state->aml,
+ op->common.aml_offset));
+ }
+ }
+
+ /*
+ * Start arg_count at zero because we don't know if there are
+ * any args yet
+ */
+ walk_state->arg_count = 0;
+
+ /* Are there any arguments that must be processed? */
+
+ if (walk_state->arg_types) {
+ /* Get arguments */
+
+ switch (op->common.aml_opcode) {
+ case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
+ case AML_WORD_OP: /* AML_WORDDATA_ARG */
+ case AML_DWORD_OP: /* AML_DWORDATA_ARG */
+ case AML_QWORD_OP: /* AML_QWORDATA_ARG */
+ case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
+
+ /* Fill in constant or string argument directly */
+
+ acpi_ps_get_next_simple_arg(parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types), op);
+ break;
+
+ case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
+
+ status =
+ acpi_ps_get_next_namepath(walk_state,
+ parser_state, op,
+ 1);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ walk_state->arg_types = 0;
+ break;
+
+ default:
+ /*
+ * Op is not a constant or string, append each argument
+ * to the Op
+ */
+ while (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)
+ && !walk_state->arg_count) {
+ walk_state->aml_offset = (u32)
+ ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->
+ aml_start);
+
+ status =
+ acpi_ps_get_next_arg(walk_state,
+ parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types),
+ &arg);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ if (arg) {
+ arg->common.aml_offset =
+ walk_state->aml_offset;
+ acpi_ps_append_arg(op, arg);
+ }
+ INCREMENT_ARG_LIST(walk_state->
+ arg_types);
+ }
+
+ /* Special processing for certain opcodes */
+
+ /* TBD (remove): Temporary mechanism to disable this code if needed */
+
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
+
+ if ((walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS1)
+ &&
+ ((walk_state->
+ parse_flags & ACPI_PARSE_DISASSEMBLE) ==
+ 0)) {
+ /*
+ * We want to skip If/Else/While constructs during Pass1
+ * because we want to actually conditionally execute the
+ * code during Pass2.
+ *
+ * Except for disassembly, where we always want to
+ * walk the If/Else/While packages
+ */
+ switch (op->common.aml_opcode) {
+ case AML_IF_OP:
+ case AML_ELSE_OP:
+ case AML_WHILE_OP:
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Pass1: Skipping an If/Else/While body\n"));
+
+ /* Skip body of if/else/while in pass 1 */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+ switch (op->common.aml_opcode) {
+ case AML_METHOD_OP:
+
+ /*
+ * Skip parsing of control method
+ * because we don't have enough info in the first pass
+ * to parse it correctly.
+ *
+ * Save the length and address of the body
+ */
+ op->named.data = parser_state->aml;
+ op->named.length =
+ (u32) (parser_state->pkg_end -
+ parser_state->aml);
+
+ /* Skip body of method */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+
+ case AML_BUFFER_OP:
+ case AML_PACKAGE_OP:
+ case AML_VAR_PACKAGE_OP:
+
+ if ((op->common.parent) &&
+ (op->common.parent->common.
+ aml_opcode == AML_NAME_OP)
+ && (walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS2)) {
+ /*
+ * Skip parsing of Buffers and Packages
+ * because we don't have enough info in the first pass
+ * to parse them correctly.
+ */
+ op->named.data = aml_op_start;
+ op->named.length =
+ (u32) (parser_state->
+ pkg_end -
+ aml_op_start);
+
+ /* Skip body */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ }
+ break;
+
+ case AML_WHILE_OP:
+
+ if (walk_state->control_state) {
+ walk_state->control_state->
+ control.package_end =
+ parser_state->pkg_end;
+ }
+ break;
+
+ default:
+
+ /* No action for all other opcodes */
+ break;
+ }
+ break;
+ }
+ }
+
+ /* Check for arguments that need to be processed */
+
+ if (walk_state->arg_count) {
+ /*
+ * There are arguments (complex ones), push Op and
+ * prepare for argument
+ */
+ status = acpi_ps_push_scope(parser_state, op,
+ walk_state->arg_types,
+ walk_state->arg_count);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+ op = NULL;
+ continue;
+ }
+
+ /*
+ * All arguments have been processed -- Op is complete,
+ * prepare for next
+ */
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+ if (walk_state->op_info->flags & AML_NAMED) {
+ if (acpi_gbl_depth) {
+ acpi_gbl_depth--;
+ }
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ /*
+ * Skip parsing of control method or opregion body,
+ * because we don't have enough info in the first pass
+ * to parse them correctly.
+ *
+ * Completed parsing an op_region declaration, we now
+ * know the length.
+ */
+ op->named.length =
+ (u32) (parser_state->aml - op->named.data);
+ }
+ }
+
+ if (walk_state->op_info->flags & AML_CREATE) {
+ /*
+ * Backup to beginning of create_xXXfield declaration (1 for
+ * Opcode)
+ *
+ * body_length is unknown until we parse the body
+ */
+ op->named.length =
+ (u32) (parser_state->aml - op->named.data);
+ }
+
+ /* This op complete, notify the dispatcher */
+
+ if (walk_state->ascending_callback != NULL) {
+ walk_state->op = op;
+ walk_state->opcode = op->common.aml_opcode;
+
+ status = walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op, status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+ }
+
+ close_this_op:
+ /*
+ * Finished one argument of the containing scope
+ */
+ parser_state->scope->parse_scope.arg_count--;
+
+ /* Finished with pre_op */
+
+ if (pre_op) {
+ acpi_ps_free_op(pre_op);
+ pre_op = NULL;
+ }
+
+ /* Close this Op (will result in parse subtree deletion) */
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+
+ switch (status) {
+ case AE_OK:
+ break;
+
+ case AE_CTRL_TRANSFER:
+
+ /* We are about to transfer to a called method. */
+
+ walk_state->prev_op = op;
+ walk_state->prev_arg_types = walk_state->arg_types;
+ return_ACPI_STATUS(status);
+
+ case AE_CTRL_END:
+
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ if (op) {
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.
+ aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status =
+ walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+
+ status2 =
+ acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+ }
+ status = AE_OK;
+ break;
+
+ case AE_CTRL_BREAK:
+ case AE_CTRL_CONTINUE:
+
+ /* Pop off scopes until we find the While */
+
+ while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ }
+
+ /* Close this iteration of the While loop */
+
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status = walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op, status);
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+
+ status = AE_OK;
+ break;
+
+ case AE_CTRL_TERMINATE:
+
+ status = AE_OK;
+
+ /* Clean up */
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+
+ default: /* All other non-AE_OK status */
+
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ /*
+ * TBD: Cleanup parse ops on error
+ */
+#if 0
+ if (op == NULL) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ }
+#endif
+ walk_state->prev_op = op;
+ walk_state->prev_arg_types = walk_state->arg_types;
+ return_ACPI_STATUS(status);
+ }
+
+ /* This scope complete? */
+
+ if (acpi_ps_has_completed_scope(parser_state)) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Popped scope, Op=%p\n", op));
+ } else {
+ op = NULL;
+ }
+
+ } /* while parser_state->Aml */
+
+ /*
+ * Complete the last Op (if not completed), and clear the scope stack.
+ * It is easily possible to end an AML "package" with an unbounded number
+ * of open scopes (such as when several ASL blocks are closed with
+ * sequential closing braces). We want to terminate each one cleanly.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
+ op));
+ do {
+ if (op) {
+ if (walk_state->ascending_callback != NULL) {
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.
+ aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status =
+ walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (status == AE_CTRL_TERMINATE) {
+ status = AE_OK;
+
+ /* Clean up */
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op
+ (walk_state, op);
+ if (ACPI_FAILURE
+ (status2)) {
+ return_ACPI_STATUS
+ (status2);
+ }
+ }
+
+ acpi_ps_pop_scope(parser_state,
+ &op,
+ &walk_state->
+ arg_types,
+ &walk_state->
+ arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+ }
+
+ else if (ACPI_FAILURE(status)) {
+ /* First error is most important */
+
+ (void)
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+
+ acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 5744673568c0..229ae86afe8b 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acopcode.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psopcode")
-
+ACPI_MODULE_NAME("psopcode")
/*******************************************************************************
*
@@ -62,7 +59,6 @@
* the operand type.
*
******************************************************************************/
-
/*
* Summary of opcode types/flags
*
@@ -180,156 +176,468 @@
AML_CREATE_QWORD_FIELD_OP
******************************************************************************/
-
-
/*
* Master Opcode information table. A summary of everything we know about each
* opcode, all in one place.
*/
-const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
-{
+const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/*! [Begin] no source code translation */
/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */
-/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
-/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
-/* 02 */ ACPI_OP ("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 03 */ ACPI_OP ("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 08 */ ACPI_OP ("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
-/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
-/* 0B */ ACPI_OP ("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
-/* 0C */ ACPI_OP ("Local0", ARGP_LOCAL0, ARGI_LOCAL0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0D */ ACPI_OP ("Local1", ARGP_LOCAL1, ARGI_LOCAL1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0E */ ACPI_OP ("Local2", ARGP_LOCAL2, ARGI_LOCAL2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0F */ ACPI_OP ("Local3", ARGP_LOCAL3, ARGI_LOCAL3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 10 */ ACPI_OP ("Local4", ARGP_LOCAL4, ARGI_LOCAL4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 11 */ ACPI_OP ("Local5", ARGP_LOCAL5, ARGI_LOCAL5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 12 */ ACPI_OP ("Local6", ARGP_LOCAL6, ARGI_LOCAL6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 13 */ ACPI_OP ("Local7", ARGP_LOCAL7, ARGI_LOCAL7, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 14 */ ACPI_OP ("Arg0", ARGP_ARG0, ARGI_ARG0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 15 */ ACPI_OP ("Arg1", ARGP_ARG1, ARGI_ARG1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 16 */ ACPI_OP ("Arg2", ARGP_ARG2, ARGI_ARG2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 17 */ ACPI_OP ("Arg3", ARGP_ARG3, ARGI_ARG3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 18 */ ACPI_OP ("Arg4", ARGP_ARG4, ARGI_ARG4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 19 */ ACPI_OP ("Arg5", ARGP_ARG5, ARGI_ARG5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 1A */ ACPI_OP ("Arg6", ARGP_ARG6, ARGI_ARG6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 1B */ ACPI_OP ("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 1C */ ACPI_OP ("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
-/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
-/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
-/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
-/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R),
-/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
-/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
-/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
-/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3E */ ACPI_OP ("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 3F */ ACPI_OP ("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 40 */ ACPI_OP ("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 41 */ ACPI_OP ("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 42 */ ACPI_OP ("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 43 */ ACPI_OP ("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 44 */ ACPI_OP ("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP,
+ ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP,
+ ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
+ ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP,
+ ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+/* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP,
+ ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+/* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP,
+ ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
+/* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R),
+/* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R),
+/* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_2T_1R,
+ AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
+/* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP,
+ ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,
+ ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+/* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
+/* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+/* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R),
+/* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
+ AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
+/* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,
+ ARGI_CREATE_DWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP,
+ ARGI_CREATE_WORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP,
+ ARGI_CREATE_BYTE_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP,
+ ARGI_CREATE_BIT_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+/* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
+/* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
+/* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL,
+ AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
/* Prefixed opcodes (Two-byte opcodes with a prefix op) */
-/* 46 */ ACPI_OP ("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 47 */ ACPI_OP ("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
-/* 48 */ ACPI_OP ("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 49 */ ACPI_OP ("CreateField", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_FIELD | AML_CREATE),
-/* 4A */ ACPI_OP ("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, AML_FLAGS_EXEC_1A_1T_0R),
-/* 4B */ ACPI_OP ("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4C */ ACPI_OP ("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4D */ ACPI_OP ("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
-/* 4E */ ACPI_OP ("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4F */ ACPI_OP ("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
-/* 50 */ ACPI_OP ("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 51 */ ACPI_OP ("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 54 */ ACPI_OP ("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 55 */ ACPI_OP ("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
-/* 56 */ ACPI_OP ("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
-/* 57 */ ACPI_OP ("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R),
-/* 58 */ ACPI_OP ("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
-/* 59 */ ACPI_OP ("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
-/* 5A */ ACPI_OP ("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5B */ ACPI_OP ("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5C */ ACPI_OP ("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5D */ ACPI_OP ("ThermalZone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5E */ ACPI_OP ("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
-/* 5F */ ACPI_OP ("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+/* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+/* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+/* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP,
+ ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
+ AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_FIELD | AML_CREATE),
+/* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
+ AML_FLAGS_EXEC_1A_1T_0R),
+/* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
+/* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R),
+/* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
+/* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
+/* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
+ AML_FLAGS_EXEC_3A_0T_0R),
+/* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP,
+ ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
+/* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
+/* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
+ ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP,
+ ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP,
+ ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP,
+ ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
+/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
/* Internal opcodes that map to invalid AML opcodes */
-/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 63 */ ACPI_OP ("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE ),
-/* 64 */ ACPI_OP ("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, AML_TYPE_METHOD_CALL, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
-/* 65 */ ACPI_OP ("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0),
-/* 66 */ ACPI_OP ("-ReservedField-", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 67 */ ACPI_OP ("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
-/* 68 */ ACPI_OP ("-AccessField-", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 69 */ ACPI_OP ("-StaticString", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 6A */ ACPI_OP ("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, AML_HAS_ARGS | AML_HAS_RETVAL),
-/* 6B */ ACPI_OP ("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
-/* 6C */ ACPI_OP ("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
-/* 6D */ ACPI_OP ("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+/* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+/* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP,
+ ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
+ AML_HAS_ARGS | AML_CONSTANT),
+/* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
+/* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP,
+ ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
+ AML_TYPE_METHOD_CALL,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
+/* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP,
+ ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, 0),
+/* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP,
+ ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+/* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP,
+ ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP,
+ ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
+ AML_HAS_ARGS | AML_HAS_RETVAL),
+/* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID,
+ AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* ACPI 2.0 opcodes */
-/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 6F */ ACPI_OP ("Package /*Var*/", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER),
-/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 78 */ ACPI_OP ("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
-/* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
-/* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
+/* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+ /* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP,
+ ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE,
+ AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER),
+/* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,
+ ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,
+ ARGI_CREATE_QWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP,
+ ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+/* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
+ AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
+/* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
+ ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE),
/* ACPI 3.0 opcodes */
-/* 7E */ ACPI_OP ("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_FLAGS_EXEC_0A_0T_1R)
+/* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+ AML_FLAGS_EXEC_0A_0T_1R)
/*! [End] no source code translation !*/
};
@@ -338,73 +646,70 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
* This table is directly indexed by the opcodes, and returns an
* index into the table above
*/
-static const u8 acpi_gbl_short_op_index[256] =
-{
+static const u8 acpi_gbl_short_op_index[256] = {
/* 0 1 2 3 4 5 6 7 */
/* 8 9 A B C D E F */
-/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
-/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
-/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
-/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
-/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
-/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
-/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
-/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
-/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
-/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
-/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
-/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
+/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
+/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
+/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
+/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
+/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
+/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
+/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
+/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
};
/*
* This table is indexed by the second opcode of the extended opcode
* pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
*/
-static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] =
-{
+static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
/* 0 1 2 3 4 5 6 7 */
/* 8 9 A B C D E F */
-/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
-/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
-/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-/* 0x88 */ 0x7C,
+/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
+/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
+/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */ 0x7C,
};
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_opcode_info
@@ -418,48 +723,36 @@ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] =
*
******************************************************************************/
-const struct acpi_opcode_info *
-acpi_ps_get_opcode_info (
- u16 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
*/
- switch ((u8) (opcode >> 8)) {
- case 0:
-
+ if (!(opcode & 0xFF00)) {
/* Simple (8-bit) opcode: 0-255, can't index beyond table */
- return (&acpi_gbl_aml_op_info [acpi_gbl_short_op_index [(u8) opcode]]);
-
- case AML_EXTOP:
-
- /* Extended (16-bit, prefix+opcode) opcode */
-
- if (((u8) opcode) <= MAX_EXTENDED_OPCODE) {
- return (&acpi_gbl_aml_op_info [acpi_gbl_long_op_index [(u8) opcode]]);
- }
-
- /* Else fall through to error case below */
- /*lint -fallthrough */
+ return (&acpi_gbl_aml_op_info
+ [acpi_gbl_short_op_index[(u8) opcode]]);
+ }
- default:
+ if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
+ (((u8) opcode) <= MAX_EXTENDED_OPCODE)) {
+ /* Valid extended (16-bit) opcode */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown AML opcode [%4.4X]\n", opcode));
- break;
+ return (&acpi_gbl_aml_op_info
+ [acpi_gbl_long_op_index[(u8) opcode]]);
}
+ /* Unknown AML opcode */
- /* Default is "unknown opcode" */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown AML opcode [%4.4X]\n", opcode));
- return (&acpi_gbl_aml_op_info [_UNK]);
+ return (&acpi_gbl_aml_op_info[_UNK]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_opcode_name
@@ -473,16 +766,13 @@ acpi_ps_get_opcode_info (
*
******************************************************************************/
-char *
-acpi_ps_get_opcode_name (
- u16 opcode)
+char *acpi_ps_get_opcode_name(u16 opcode)
{
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
- const struct acpi_opcode_info *op;
+ const struct acpi_opcode_info *op;
-
- op = acpi_ps_get_opcode_info (opcode);
+ op = acpi_ps_get_opcode_info(opcode);
/* Always guaranteed to return a valid pointer */
@@ -493,4 +783,3 @@ acpi_ps_get_opcode_name (
#endif
}
-
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index bbfdc1a58c27..76d4d640d83c 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
/*
* Parse the AML and build an operation tree as most interpreters,
* like Perl, do. Parsing is done by hand rather than with a YACC
@@ -59,28 +58,7 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psparse")
-
-
-static u32 acpi_gbl_depth = 0;
-
-/* Local prototypes */
-
-static void
-acpi_ps_complete_this_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
-static acpi_status
-acpi_ps_next_parse_state (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_status callback_status);
-
-static acpi_status
-acpi_ps_parse_loop (
- struct acpi_walk_state *walk_state);
-
+ACPI_MODULE_NAME("psparse")
/*******************************************************************************
*
@@ -93,10 +71,7 @@ acpi_ps_parse_loop (
* DESCRIPTION: Get the size of the current opcode.
*
******************************************************************************/
-
-u32
-acpi_ps_get_opcode_size (
- u32 opcode)
+u32 acpi_ps_get_opcode_size(u32 opcode)
{
/* Extended (2-byte) opcode if > 255 */
@@ -110,7 +85,6 @@ acpi_ps_get_opcode_size (
return (1);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_peek_opcode
@@ -123,28 +97,24 @@ acpi_ps_get_opcode_size (
*
******************************************************************************/
-u16
-acpi_ps_peek_opcode (
- struct acpi_parse_state *parser_state)
+u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state)
{
- u8 *aml;
- u16 opcode;
-
+ u8 *aml;
+ u16 opcode;
aml = parser_state->aml;
- opcode = (u16) ACPI_GET8 (aml);
+ opcode = (u16) ACPI_GET8(aml);
- if (opcode == AML_EXTOP) {
- /* Extended opcode */
+ if (opcode == AML_EXTENDED_OP_PREFIX) {
+ /* Extended opcode, get the second opcode byte */
aml++;
- opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml));
+ opcode = (u16) ((opcode << 8) | ACPI_GET8(aml));
}
return (opcode);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_complete_this_op
@@ -152,47 +122,54 @@ acpi_ps_peek_opcode (
* PARAMETERS: walk_state - Current State
* Op - Op to complete
*
- * RETURN: None.
+ * RETURN: Status
*
* DESCRIPTION: Perform any cleanup at the completion of an Op.
*
******************************************************************************/
-static void
-acpi_ps_complete_this_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_status
+acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op)
{
- union acpi_parse_object *prev;
- union acpi_parse_object *next;
- const struct acpi_opcode_info *parent_info;
- union acpi_parse_object *replacement_op = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op);
+ union acpi_parse_object *prev;
+ union acpi_parse_object *next;
+ const struct acpi_opcode_info *parent_info;
+ union acpi_parse_object *replacement_op = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op);
/* Check for null Op, can happen if AML code is corrupt */
if (!op) {
- return_VOID;
+ return_ACPI_STATUS(AE_OK); /* OK for now */
}
/* Delete this op and the subtree below it if asked to */
- if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
- (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
- return_VOID;
+ if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) !=
+ ACPI_PARSE_DELETE_TREE)
+ || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
+ return_ACPI_STATUS(AE_OK);
}
/* Make sure that we only delete this subtree */
if (op->common.parent) {
+ prev = op->common.parent->common.value.arg;
+ if (!prev) {
+ /* Nothing more to do */
+
+ goto cleanup;
+ }
+
/*
* Check if we need to replace the operator and its subtree
* with a return value op (placeholder op)
*/
- parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
+ parent_info =
+ acpi_ps_get_opcode_info(op->common.parent->common.
+ aml_opcode);
switch (parent_info->class) {
case AML_CLASS_CONTROL:
@@ -204,9 +181,10 @@ acpi_ps_complete_this_op (
* These opcodes contain term_arg operands. The current
* op must be replaced by a placeholder return op
*/
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
break;
@@ -216,91 +194,117 @@ acpi_ps_complete_this_op (
* These opcodes contain term_arg operands. The current
* op must be replaced by a placeholder return op
*/
- if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+ if ((op->common.parent->common.aml_opcode ==
+ AML_REGION_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_DATA_REGION_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_BUFFER_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)) {
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
- }
-
- if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
- if ((op->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
- replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
+ } else
+ if ((op->common.parent->common.aml_opcode ==
+ AML_NAME_OP)
+ && (walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS2)) {
+ if ((op->common.aml_opcode == AML_BUFFER_OP)
+ || (op->common.aml_opcode == AML_PACKAGE_OP)
+ || (op->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)) {
+ replacement_op =
+ acpi_ps_alloc_op(op->common.
+ aml_opcode);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
- replacement_op->named.data = op->named.data;
- replacement_op->named.length = op->named.length;
+ replacement_op->named.data =
+ op->named.data;
+ replacement_op->named.length =
+ op->named.length;
}
}
break;
default:
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
}
/* We must unlink this op from the parent tree */
- prev = op->common.parent->common.value.arg;
if (prev == op) {
/* This op is the first in the list */
if (replacement_op) {
- replacement_op->common.parent = op->common.parent;
- replacement_op->common.value.arg = NULL;
- replacement_op->common.node = op->common.node;
- op->common.parent->common.value.arg = replacement_op;
- replacement_op->common.next = op->common.next;
- }
- else {
- op->common.parent->common.value.arg = op->common.next;
+ replacement_op->common.parent =
+ op->common.parent;
+ replacement_op->common.value.arg = NULL;
+ replacement_op->common.node = op->common.node;
+ op->common.parent->common.value.arg =
+ replacement_op;
+ replacement_op->common.next = op->common.next;
+ } else {
+ op->common.parent->common.value.arg =
+ op->common.next;
}
}
/* Search the parent list */
- else while (prev) {
- /* Traverse all siblings in the parent's argument list */
-
- next = prev->common.next;
- if (next == op) {
- if (replacement_op) {
- replacement_op->common.parent = op->common.parent;
- replacement_op->common.value.arg = NULL;
- replacement_op->common.node = op->common.node;
- prev->common.next = replacement_op;
- replacement_op->common.next = op->common.next;
- next = NULL;
- }
- else {
- prev->common.next = op->common.next;
- next = NULL;
+ else
+ while (prev) {
+ /* Traverse all siblings in the parent's argument list */
+
+ next = prev->common.next;
+ if (next == op) {
+ if (replacement_op) {
+ replacement_op->common.parent =
+ op->common.parent;
+ replacement_op->common.value.
+ arg = NULL;
+ replacement_op->common.node =
+ op->common.node;
+ prev->common.next =
+ replacement_op;
+ replacement_op->common.next =
+ op->common.next;
+ next = NULL;
+ } else {
+ prev->common.next =
+ op->common.next;
+ next = NULL;
+ }
}
+ prev = next;
}
- prev = next;
- }
}
-
-cleanup:
+ cleanup:
/* Now we can actually delete the subtree rooted at Op */
- acpi_ps_delete_parse_tree (op);
- return_VOID;
-}
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(AE_OK);
+ allocate_error:
+
+ /* Always delete the subtree, even on error */
+
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+}
/*******************************************************************************
*
@@ -317,18 +321,15 @@ cleanup:
*
******************************************************************************/
-static acpi_status
-acpi_ps_next_parse_state (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_status callback_status)
+acpi_status
+acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ acpi_status callback_status)
{
- 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);
+ 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);
switch (callback_status) {
case AE_CTRL_TERMINATE:
@@ -341,7 +342,6 @@ acpi_ps_next_parse_state (
status = AE_CTRL_TERMINATE;
break;
-
case AE_CTRL_BREAK:
parser_state->aml = walk_state->aml_last_while;
@@ -351,7 +351,6 @@ acpi_ps_next_parse_state (
case AE_CTRL_CONTINUE:
-
parser_state->aml = walk_state->aml_last_while;
status = AE_CTRL_CONTINUE;
break;
@@ -375,10 +374,9 @@ acpi_ps_next_parse_state (
* Predicate of an IF was true, and we are at the matching ELSE.
* Just close out this package
*/
- parser_state->aml = acpi_ps_get_next_package_end (parser_state);
+ parser_state->aml = acpi_ps_get_next_package_end(parser_state);
break;
-
case AE_CTRL_FALSE:
/*
@@ -396,7 +394,6 @@ acpi_ps_next_parse_state (
status = AE_CTRL_END;
break;
-
case AE_CTRL_TRANSFER:
/* A method call (invocation) -- transfer control */
@@ -404,14 +401,15 @@ acpi_ps_next_parse_state (
status = AE_CTRL_TRANSFER;
walk_state->prev_op = op;
walk_state->method_call_op = op;
- walk_state->method_call_node = (op->common.value.arg)->common.node;
+ walk_state->method_call_node =
+ (op->common.value.arg)->common.node;
/* Will return value (if any) be used by the caller? */
- walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
+ walk_state->return_used =
+ acpi_ds_is_result_used(op, walk_state);
break;
-
default:
status = callback_status;
@@ -421,667 +419,9 @@ acpi_ps_next_parse_state (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_parse_loop
- *
- * PARAMETERS: walk_state - Current state
- *
- * RETURN: Status
- *
- * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
- * a tree of ops.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ps_parse_loop (
- struct acpi_walk_state *walk_state)
-{
- acpi_status status = AE_OK;
- union acpi_parse_object *op = NULL; /* current op */
- union acpi_parse_object *arg = NULL;
- union acpi_parse_object *pre_op = NULL;
- struct acpi_parse_state *parser_state;
- u8 *aml_op_start = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state);
-
- if (walk_state->descending_callback == NULL) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- parser_state = &walk_state->parser_state;
- walk_state->arg_types = 0;
-
-#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)) {
- /*
- * We must check if a predicate to an IF or WHILE statement
- * was just completed
- */
- if ((parser_state->scope->parse_scope.op) &&
- ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) ||
- (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) &&
- (walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_PREDICATE_EXECUTING)) {
- /*
- * A predicate was just completed, get the value of the
- * predicate and branch based on that value
- */
- walk_state->op = NULL;
- status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE));
- if (ACPI_FAILURE (status) &&
- ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
- if (status == AE_AML_NO_RETURN_VALUE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invoked method did not return a value, %s\n",
- acpi_format_exception (status)));
-
- }
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "get_predicate Failed, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
- }
-
- status = acpi_ps_next_parse_state (walk_state, op, status);
- }
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- 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;
- walk_state->arg_types = walk_state->prev_arg_types;
- }
- }
-#endif
-
- /* Iterative parsing loop, while there is more AML to process: */
-
- 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 = (u32) ACPI_PTR_DIFF (parser_state->aml,
- parser_state->aml_start);
- walk_state->opcode = acpi_ps_peek_opcode (parser_state);
-
- /*
- * First cut to determine what we have found:
- * 1) A valid AML opcode
- * 2) A name string
- * 3) An unknown/invalid opcode
- */
- walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
- switch (walk_state->op_info->class) {
- case AML_CLASS_ASCII:
- case AML_CLASS_PREFIX:
- /*
- * Starts with a valid prefix or ASCII char, this is a name
- * string. Convert the bare name string to a namepath.
- */
- walk_state->opcode = AML_INT_NAMEPATH_OP;
- walk_state->arg_types = ARGP_NAMESTRING;
- break;
-
- case AML_CLASS_UNKNOWN:
-
- /* The opcode is unrecognized. Just skip unknown opcodes */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
- walk_state->opcode, parser_state->aml, walk_state->aml_offset));
-
- ACPI_DUMP_BUFFER (parser_state->aml, 128);
-
- /* Assume one-byte bad opcode */
-
- parser_state->aml++;
- continue;
-
- default:
-
- /* Found opcode info, this is a normal opcode */
-
- parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
- walk_state->arg_types = walk_state->op_info->parse_args;
- break;
- }
-
- /* 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) {
- pre_op = acpi_ps_alloc_op (walk_state->opcode);
- if (!pre_op) {
- status = AE_NO_MEMORY;
- goto close_this_op;
- }
- }
-
- pre_op->common.value.arg = NULL;
- pre_op->common.aml_opcode = walk_state->opcode;
-
- /*
- * Get and append arguments until we find the node that contains
- * the name (the type ARGP_NAME).
- */
- while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
- (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) {
- status = acpi_ps_get_next_arg (walk_state, parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- acpi_ps_append_arg (pre_op, arg);
- INCREMENT_ARG_LIST (walk_state->arg_types);
- }
-
- /*
- * Make sure that we found a NAME and didn't run out of
- * arguments
- */
- if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) {
- status = AE_AML_NO_OPERAND;
- goto close_this_op;
- }
-
- /* We know that this arg is a name, move to next arg */
-
- INCREMENT_ARG_LIST (walk_state->arg_types);
-
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- walk_state->op = NULL;
-
- status = walk_state->descending_callback (walk_state, &op);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "During name lookup/catalog, %s\n",
- acpi_format_exception (status)));
- goto close_this_op;
- }
-
- if (!op) {
- continue;
- }
-
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- acpi_ps_append_arg (op, pre_op->common.value.arg);
- acpi_gbl_depth++;
-
- if (op->common.aml_opcode == AML_REGION_OP) {
- /*
- * Defer final parsing of an operation_region body,
- * because we don't have enough info in the first pass
- * to parse it correctly (i.e., there may be method
- * calls within the term_arg elements of the body.)
- *
- * However, we must continue parsing because
- * the opregion is not a standalone package --
- * we don't know where the end is at this point.
- *
- * (Length is unknown until parse of the body complete)
- */
- op->named.data = aml_op_start;
- op->named.length = 0;
- }
- }
- else {
- /* Not a named opcode, just allocate Op and append to parent */
-
- walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
- op = acpi_ps_alloc_op (walk_state->opcode);
- if (!op) {
- status = AE_NO_MEMORY;
- goto close_this_op;
- }
-
- if (walk_state->op_info->flags & AML_CREATE) {
- /*
- * Backup to beginning of create_xXXfield declaration
- * body_length is unknown until we parse the body
- */
- op->named.data = aml_op_start;
- op->named.length = 0;
- }
-
- acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
-
- if ((walk_state->descending_callback != NULL)) {
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- walk_state->op = op;
-
- status = walk_state->descending_callback (walk_state, &op);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
- }
- }
-
- op->common.aml_offset = walk_state->aml_offset;
-
- if (walk_state->op_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
- (u32) op->common.aml_opcode, walk_state->op_info->name,
- op, parser_state->aml, op->common.aml_offset));
- }
- }
-
-
- /*
- * Start arg_count at zero because we don't know if there are
- * any args yet
- */
- walk_state->arg_count = 0;
-
- /* Are there any arguments that must be processed? */
-
- if (walk_state->arg_types) {
- /* Get arguments */
-
- switch (op->common.aml_opcode) {
- case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
- case AML_WORD_OP: /* AML_WORDDATA_ARG */
- case AML_DWORD_OP: /* AML_DWORDATA_ARG */
- case AML_QWORD_OP: /* AML_QWORDATA_ARG */
- case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
-
- /* Fill in constant or string argument directly */
-
- acpi_ps_get_next_simple_arg (parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
- break;
-
- case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
-
- status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- walk_state->arg_types = 0;
- break;
-
- default:
-
- /*
- * Op is not a constant or string, append each argument
- * to the Op
- */
- while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
- !walk_state->arg_count) {
- walk_state->aml_offset = (u32)
- ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start);
-
- status = acpi_ps_get_next_arg (walk_state, parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types),
- &arg);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- if (arg) {
- arg->common.aml_offset = walk_state->aml_offset;
- acpi_ps_append_arg (op, arg);
- }
- INCREMENT_ARG_LIST (walk_state->arg_types);
- }
-
- /* Special processing for certain opcodes */
-
- switch (op->common.aml_opcode) {
- case AML_METHOD_OP:
-
- /*
- * Skip parsing of control method
- * because we don't have enough info in the first pass
- * to parse it correctly.
- *
- * Save the length and address of the body
- */
- op->named.data = parser_state->aml;
- op->named.length = (u32) (parser_state->pkg_end -
- parser_state->aml);
-
- /* Skip body of method */
-
- parser_state->aml = parser_state->pkg_end;
- walk_state->arg_count = 0;
- break;
-
- case AML_BUFFER_OP:
- case AML_PACKAGE_OP:
- case AML_VAR_PACKAGE_OP:
-
- if ((op->common.parent) &&
- (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
- /*
- * Skip parsing of Buffers and Packages
- * because we don't have enough info in the first pass
- * to parse them correctly.
- */
- op->named.data = aml_op_start;
- op->named.length = (u32) (parser_state->pkg_end -
- aml_op_start);
-
- /* Skip body */
-
- parser_state->aml = parser_state->pkg_end;
- walk_state->arg_count = 0;
- }
- break;
-
- case AML_WHILE_OP:
-
- if (walk_state->control_state) {
- walk_state->control_state->control.package_end =
- parser_state->pkg_end;
- }
- break;
-
- default:
-
- /* No action for all other opcodes */
- break;
- }
- break;
- }
- }
-
- /* Check for arguments that need to be processed */
-
- if (walk_state->arg_count) {
- /*
- * There are arguments (complex ones), push Op and
- * prepare for argument
- */
- status = acpi_ps_push_scope (parser_state, op,
- walk_state->arg_types, walk_state->arg_count);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
- op = NULL;
- continue;
- }
-
- /*
- * All arguments have been processed -- Op is complete,
- * prepare for next
- */
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- if (walk_state->op_info->flags & AML_NAMED) {
- if (acpi_gbl_depth) {
- acpi_gbl_depth--;
- }
-
- if (op->common.aml_opcode == AML_REGION_OP) {
- /*
- * Skip parsing of control method or opregion body,
- * because we don't have enough info in the first pass
- * to parse them correctly.
- *
- * Completed parsing an op_region declaration, we now
- * know the length.
- */
- op->named.length = (u32) (parser_state->aml - op->named.data);
- }
- }
-
- if (walk_state->op_info->flags & AML_CREATE) {
- /*
- * Backup to beginning of create_xXXfield declaration (1 for
- * Opcode)
- *
- * body_length is unknown until we parse the body
- */
- op->named.length = (u32) (parser_state->aml - op->named.data);
- }
-
- /* This op complete, notify the dispatcher */
-
- if (walk_state->ascending_callback != NULL) {
- walk_state->op = op;
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
- }
-
-
-close_this_op:
- /*
- * Finished one argument of the containing scope
- */
- parser_state->scope->parse_scope.arg_count--;
-
- /* Close this Op (will result in parse subtree deletion) */
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
- if (pre_op) {
- acpi_ps_free_op (pre_op);
- pre_op = NULL;
- }
-
- switch (status) {
- case AE_OK:
- break;
-
-
- case AE_CTRL_TRANSFER:
-
- /* We are about to transfer to a called method. */
-
- walk_state->prev_op = op;
- walk_state->prev_arg_types = walk_state->arg_types;
- return_ACPI_STATUS (status);
-
-
- case AE_CTRL_END:
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- if (op) {
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
- }
- status = AE_OK;
- break;
-
-
- case AE_CTRL_BREAK:
- case AE_CTRL_CONTINUE:
-
- /* Pop off scopes until we find the While */
-
- while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- }
-
- /* Close this iteration of the While loop */
-
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
-
- status = AE_OK;
- break;
-
-
- case AE_CTRL_TERMINATE:
-
- status = AE_OK;
-
- /* Clean up */
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
-
-
- default: /* All other non-AE_OK status */
-
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
-
- /*
- * TBD: Cleanup parse ops on error
- */
-#if 0
- if (op == NULL) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- }
-#endif
- walk_state->prev_op = op;
- walk_state->prev_arg_types = walk_state->arg_types;
- return_ACPI_STATUS (status);
- }
-
- /* This scope complete? */
-
- if (acpi_ps_has_completed_scope (parser_state)) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
- }
- else {
- op = NULL;
- }
-
- } /* while parser_state->Aml */
-
-
- /*
- * Complete the last Op (if not completed), and clear the scope stack.
- * It is easily possible to end an AML "package" with an unbounded number
- * of open scopes (such as when several ASL blocks are closed with
- * sequential closing braces). We want to terminate each one cleanly.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op));
- do {
- if (op) {
- if (walk_state->ascending_callback != NULL) {
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (status == AE_CTRL_TERMINATE) {
- status = AE_OK;
-
- /* Clean up */
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
- }
-
- else if (ACPI_FAILURE (status)) {
- acpi_ps_complete_this_op (walk_state, op);
- return_ACPI_STATUS (status);
- }
- }
-
- acpi_ps_complete_this_op (walk_state, op);
- }
-
- acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
- &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
-}
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_parse_aml
@@ -1095,34 +435,29 @@ close_this_op:
*
******************************************************************************/
-acpi_status
-acpi_ps_parse_aml (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
{
- acpi_status status;
- acpi_status terminate_status;
- struct acpi_thread_state *thread;
- struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
- struct acpi_walk_state *previous_walk_state;
+ acpi_status status;
+ struct acpi_thread_state *thread;
+ 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",
- walk_state, walk_state->parser_state.aml,
- walk_state->parser_state.aml_size));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Entered with walk_state=%p Aml=%p size=%X\n",
+ walk_state, walk_state->parser_state.aml,
+ walk_state->parser_state.aml_size));
/* Create and initialize a new thread state */
- thread = acpi_ut_create_thread_state ();
+ thread = acpi_ut_create_thread_state();
if (!thread) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
walk_state->thread = thread;
- acpi_ds_push_walk_state (walk_state, thread);
+ acpi_ds_push_walk_state(walk_state, thread);
/*
* This global allows the AML debugger to get a handle to the currently
@@ -1134,130 +469,136 @@ acpi_ps_parse_aml (
* Execute the walk loop as long as there is a valid Walk State. This
* handles nested control method invocations without recursion.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state));
status = AE_OK;
while (walk_state) {
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* The parse_loop executes AML until the method terminates
* or calls another method.
*/
- status = acpi_ps_parse_loop (walk_state);
+ status = acpi_ps_parse_loop(walk_state);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Completed one call to walk loop, %s State=%p\n",
- acpi_format_exception (status), walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Completed one call to walk loop, %s State=%p\n",
+ acpi_format_exception(status), walk_state));
if (status == AE_CTRL_TRANSFER) {
/*
* A method call was detected.
* Transfer control to the called control method
*/
- status = acpi_ds_call_control_method (thread, walk_state, NULL);
+ status =
+ acpi_ds_call_control_method(thread, walk_state,
+ NULL);
/*
* If the transfer to the new method method call worked, a new walk
* state was created -- get it
*/
- walk_state = acpi_ds_get_current_walk_state (thread);
+ walk_state = acpi_ds_get_current_walk_state(thread);
continue;
- }
- else if (status == AE_CTRL_TERMINATE) {
+ } else if (status == AE_CTRL_TERMINATE) {
status = AE_OK;
- }
- else if ((status != AE_OK) && (walk_state->method_desc)) {
- ACPI_REPORT_METHOD_ERROR ("Method execution failed",
- walk_state->method_node, NULL, status);
+ } else if ((status != AE_OK) && (walk_state->method_desc)) {
+ ACPI_REPORT_METHOD_ERROR("Method execution failed",
+ walk_state->method_node, NULL,
+ status);
+
+ /* Ensure proper cleanup */
+
+ walk_state->parse_flags |= ACPI_PARSE_EXECUTE;
/* Check for possible multi-thread reentrancy problem */
if ((status == AE_ALREADY_EXISTS) &&
- (!walk_state->method_desc->method.semaphore)) {
+ (!walk_state->method_desc->method.semaphore)) {
/*
* This method is marked not_serialized, but it tried to create
* a named object, causing the second thread entrance to fail.
* We will workaround this by marking the method permanently
* as Serialized.
*/
- walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
+ walk_state->method_desc->method.method_flags |=
+ AML_METHOD_SERIALIZED;
walk_state->method_desc->method.concurrency = 1;
}
}
- 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--;
- }
- }
-
/* We are done with this walk, move on to the parent if any */
- walk_state = acpi_ds_pop_walk_state (thread);
+ walk_state = acpi_ds_pop_walk_state(thread);
/* Reset the current scope to the beginning of scope stack */
- acpi_ds_scope_stack_clear (walk_state);
+ acpi_ds_scope_stack_clear(walk_state);
/*
* If we just returned from the execution of a control method,
* there's lots of cleanup to do
*/
- if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
- terminate_status = acpi_ds_terminate_control_method (walk_state);
- if (ACPI_FAILURE (terminate_status)) {
- ACPI_REPORT_ERROR ((
- "Could not terminate control method properly\n"));
+ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) {
+ if (walk_state->method_desc) {
+ /* Decrement the thread count on the method parse tree */
- /* Ignore error and continue */
+ walk_state->method_desc->method.thread_count--;
}
+
+ acpi_ds_terminate_control_method(walk_state);
}
/* Delete this walk state and all linked control states */
- acpi_ps_cleanup_scope (&walk_state->parser_state);
+ acpi_ps_cleanup_scope(&walk_state->parser_state);
previous_walk_state = walk_state;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "return_value=%p, implicit_value=%p State=%p\n",
- walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "return_value=%p, implicit_value=%p State=%p\n",
+ walk_state->return_desc,
+ walk_state->implicit_return_obj, walk_state));
/* Check if we have restarted a preempted walk */
- walk_state = acpi_ds_get_current_walk_state (thread);
+ walk_state = acpi_ds_get_current_walk_state(thread);
if (walk_state) {
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* There is another walk state, restart it.
* If the method return value is not used by the parent,
* The object is deleted
*/
if (!previous_walk_state->return_desc) {
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->implicit_return_obj);
- }
- else {
+ status =
+ acpi_ds_restart_control_method
+ (walk_state,
+ previous_walk_state->
+ implicit_return_obj);
+ } else {
/*
* We have a valid return value, delete any implicit
* return value.
*/
- acpi_ds_clear_implicit_return (previous_walk_state);
+ acpi_ds_clear_implicit_return
+ (previous_walk_state);
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->return_desc);
+ status =
+ acpi_ds_restart_control_method
+ (walk_state,
+ previous_walk_state->return_desc);
}
- if (ACPI_SUCCESS (status)) {
- walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
+ if (ACPI_SUCCESS(status)) {
+ walk_state->walk_type |=
+ ACPI_WALK_METHOD_RESTART;
}
- }
- else {
+ } else {
/* On error, delete any return object */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ acpi_ut_remove_reference(previous_walk_state->
+ return_desc);
}
}
@@ -1268,37 +609,36 @@ acpi_ps_parse_aml (
else if (previous_walk_state->caller_return_desc) {
if (previous_walk_state->implicit_return_obj) {
*(previous_walk_state->caller_return_desc) =
- previous_walk_state->implicit_return_obj;
- }
- else {
- /* NULL if no return value */
+ previous_walk_state->implicit_return_obj;
+ } else {
+ /* NULL if no return value */
*(previous_walk_state->caller_return_desc) =
- previous_walk_state->return_desc;
+ previous_walk_state->return_desc;
}
- }
- else {
+ } else {
if (previous_walk_state->return_desc) {
/* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ 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->implicit_return_obj);
+ acpi_ut_remove_reference(previous_walk_state->
+ implicit_return_obj);
}
}
- acpi_ds_delete_walk_state (previous_walk_state);
+ acpi_ds_delete_walk_state(previous_walk_state);
}
/* Normal exit */
- acpi_ex_release_all_mutexes (thread);
- acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
+ acpi_ex_release_all_mutexes(thread);
+ acpi_ut_delete_generic_state(ACPI_CAST_PTR
+ (union acpi_generic_state, thread));
acpi_gbl_current_walk_list = prev_walk_list;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index 8dcd1b1e7131..1c953b6f1af1 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psscope")
-
+ACPI_MODULE_NAME("psscope")
/*******************************************************************************
*
@@ -60,16 +58,13 @@
* DESCRIPTION: Get parent of current op being parsed
*
******************************************************************************/
-
-union acpi_parse_object *
-acpi_ps_get_parent_scope (
- struct acpi_parse_state *parser_state)
+union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
+ *parser_state)
{
return (parser_state->scope->parse_scope.op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_has_completed_scope
@@ -84,17 +79,14 @@ acpi_ps_get_parent_scope (
*
******************************************************************************/
-u8
-acpi_ps_has_completed_scope (
- struct acpi_parse_state *parser_state)
+u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)
{
return ((u8)
- ((parser_state->aml >= parser_state->scope->parse_scope.arg_end ||
- !parser_state->scope->parse_scope.arg_count)));
+ ((parser_state->aml >= parser_state->scope->parse_scope.arg_end
+ || !parser_state->scope->parse_scope.arg_count)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_init_scope
@@ -109,34 +101,30 @@ acpi_ps_has_completed_scope (
******************************************************************************/
acpi_status
-acpi_ps_init_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *root_op)
+acpi_ps_init_scope(struct acpi_parse_state * parser_state,
+ union acpi_parse_object * root_op)
{
- union acpi_generic_state *scope;
+ 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 ();
+ scope = acpi_ut_create_generic_state();
if (!scope) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
- scope->parse_scope.op = root_op;
+ scope->common.data_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;
- scope->parse_scope.pkg_end = parser_state->aml_end;
+ scope->parse_scope.arg_end = parser_state->aml_end;
+ scope->parse_scope.pkg_end = parser_state->aml_end;
- parser_state->scope = scope;
- parser_state->start_op = root_op;
+ parser_state->scope = scope;
+ parser_state->start_op = root_op;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_push_scope
@@ -153,48 +141,42 @@ acpi_ps_init_scope (
******************************************************************************/
acpi_status
-acpi_ps_push_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *op,
- u32 remaining_args,
- u32 arg_count)
+acpi_ps_push_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object *op,
+ u32 remaining_args, u32 arg_count)
{
- union acpi_generic_state *scope;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_push_scope", op);
+ union acpi_generic_state *scope;
+ ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op);
- scope = acpi_ut_create_generic_state ();
+ scope = acpi_ut_create_generic_state();
if (!scope) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
- scope->parse_scope.op = op;
+ scope->common.data_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;
scope->parse_scope.pkg_end = parser_state->pkg_end;
/* Push onto scope stack */
- acpi_ut_push_generic_state (&parser_state->scope, scope);
+ 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;
- }
- else {
+ } else {
/* Single argument */
- scope->parse_scope.arg_end = ACPI_TO_POINTER (ACPI_MAX_PTR);
+ scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_pop_scope
@@ -212,48 +194,41 @@ acpi_ps_push_scope (
******************************************************************************/
void
-acpi_ps_pop_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object **op,
- u32 *arg_list,
- u32 *arg_count)
+acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object **op, u32 * arg_list, u32 * arg_count)
{
- union acpi_generic_state *scope = parser_state->scope;
-
-
- ACPI_FUNCTION_TRACE ("ps_pop_scope");
+ union acpi_generic_state *scope = parser_state->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);
+ scope = acpi_ut_pop_generic_state(&parser_state->scope);
/* return to parsing previous op */
- *op = scope->parse_scope.op;
- *arg_list = scope->parse_scope.arg_list;
- *arg_count = scope->parse_scope.arg_count;
+ *op = scope->parse_scope.op;
+ *arg_list = scope->parse_scope.arg_list;
+ *arg_count = scope->parse_scope.arg_count;
parser_state->pkg_end = scope->parse_scope.pkg_end;
/* All done with this scope state structure */
- acpi_ut_delete_generic_state (scope);
- }
- else {
+ acpi_ut_delete_generic_state(scope);
+ } else {
/* empty parse stack, prepare to fetch next opcode */
- *op = NULL;
+ *op = NULL;
*arg_list = 0;
*arg_count = 0;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Popped Op %p Args %X\n", *op, *arg_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Popped Op %p Args %X\n", *op, *arg_count));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_cleanup_scope
@@ -267,15 +242,11 @@ acpi_ps_pop_scope (
*
******************************************************************************/
-void
-acpi_ps_cleanup_scope (
- struct acpi_parse_state *parser_state)
+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);
+ union acpi_generic_state *scope;
+ ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state);
if (!parser_state) {
return_VOID;
@@ -284,10 +255,9 @@ acpi_ps_cleanup_scope (
/* Delete anything on the scope stack */
while (parser_state->scope) {
- scope = acpi_ut_pop_generic_state (&parser_state->scope);
- acpi_ut_delete_generic_state (scope);
+ scope = acpi_ut_pop_generic_state(&parser_state->scope);
+ acpi_ut_delete_generic_state(scope);
}
return_VOID;
}
-
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index d5aafe73fca0..f0e755884eea 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -41,23 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("pstree")
+ACPI_MODULE_NAME("pstree")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
-union acpi_parse_object *
-acpi_ps_get_child (
- union acpi_parse_object *op);
+union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_arg
@@ -71,21 +66,16 @@ acpi_ps_get_child (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_arg (
- union acpi_parse_object *op,
- u32 argn)
+union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
{
- union acpi_parse_object *arg = NULL;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *arg = NULL;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_ENTRY();
/* Get the info structure for this opcode */
- op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
+ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Invalid opcode or ASCII character */
@@ -111,7 +101,6 @@ acpi_ps_get_arg (
return (arg);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_append_arg
@@ -126,16 +115,12 @@ acpi_ps_get_arg (
******************************************************************************/
void
-acpi_ps_append_arg (
- union acpi_parse_object *op,
- union acpi_parse_object *arg)
+acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
{
- union acpi_parse_object *prev_arg;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *prev_arg;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_ENTRY();
if (!op) {
return;
@@ -143,12 +128,11 @@ acpi_ps_append_arg (
/* Get the info structure for this opcode */
- op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
+ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Invalid opcode */
- ACPI_REPORT_ERROR (("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n",
- op->common.aml_opcode));
+ ACPI_REPORT_ERROR(("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->common.aml_opcode));
return;
}
@@ -170,8 +154,7 @@ acpi_ps_append_arg (
prev_arg = prev_arg->common.next;
}
prev_arg->common.next = arg;
- }
- else {
+ } else {
/* No argument list, this will be the first argument */
op->common.value.arg = arg;
@@ -185,7 +168,6 @@ acpi_ps_append_arg (
}
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -201,18 +183,14 @@ acpi_ps_append_arg (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_depth_next (
- union acpi_parse_object *origin,
- union acpi_parse_object *op)
+union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
+ union acpi_parse_object *op)
{
- union acpi_parse_object *next = NULL;
- union acpi_parse_object *parent;
- union acpi_parse_object *arg;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent;
+ union acpi_parse_object *arg;
+ ACPI_FUNCTION_ENTRY();
if (!op) {
return (NULL);
@@ -220,7 +198,7 @@ acpi_ps_get_depth_next (
/* Look for an argument or child */
- next = acpi_ps_get_arg (op, 0);
+ next = acpi_ps_get_arg(op, 0);
if (next) {
return (next);
}
@@ -237,7 +215,7 @@ acpi_ps_get_depth_next (
parent = op->common.parent;
while (parent) {
- arg = acpi_ps_get_arg (parent, 0);
+ arg = acpi_ps_get_arg(parent, 0);
while (arg && (arg != origin) && (arg != op)) {
arg = arg->common.next;
}
@@ -261,7 +239,6 @@ acpi_ps_get_depth_next (
return (next);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -275,15 +252,11 @@ acpi_ps_get_depth_next (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_child (
- union acpi_parse_object *op)
+union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
{
- union acpi_parse_object *child = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *child = NULL;
+ ACPI_FUNCTION_ENTRY();
switch (op->common.aml_opcode) {
case AML_SCOPE_OP:
@@ -292,10 +265,9 @@ acpi_ps_get_child (
case AML_THERMAL_ZONE_OP:
case AML_INT_METHODCALL_OP:
- child = acpi_ps_get_arg (op, 0);
+ child = acpi_ps_get_arg(op, 0);
break;
-
case AML_BUFFER_OP:
case AML_PACKAGE_OP:
case AML_METHOD_OP:
@@ -303,24 +275,21 @@ acpi_ps_get_child (
case AML_WHILE_OP:
case AML_FIELD_OP:
- child = acpi_ps_get_arg (op, 1);
+ child = acpi_ps_get_arg(op, 1);
break;
-
case AML_POWER_RES_OP:
case AML_INDEX_FIELD_OP:
- child = acpi_ps_get_arg (op, 2);
+ child = acpi_ps_get_arg(op, 2);
break;
-
case AML_PROCESSOR_OP:
case AML_BANK_FIELD_OP:
- child = acpi_ps_get_arg (op, 3);
+ child = acpi_ps_get_arg(op, 3);
break;
-
default:
/* All others have no children */
break;
@@ -330,5 +299,4 @@ acpi_ps_get_child (
}
#endif
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index a10f88715d43..2075efbb4324 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -41,14 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psutils")
-
+ACPI_MODULE_NAME("psutils")
/*******************************************************************************
*
@@ -61,15 +59,11 @@
* DESCRIPTION: Create a Scope and associated namepath op with the root name
*
******************************************************************************/
-
-union acpi_parse_object *
-acpi_ps_create_scope_op (
- void)
+union acpi_parse_object *acpi_ps_create_scope_op(void)
{
- union acpi_parse_object *scope_op;
+ union acpi_parse_object *scope_op;
-
- scope_op = acpi_ps_alloc_op (AML_SCOPE_OP);
+ scope_op = acpi_ps_alloc_op(AML_SCOPE_OP);
if (!scope_op) {
return (NULL);
}
@@ -78,7 +72,6 @@ acpi_ps_create_scope_op (
return (scope_op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_init_op
@@ -92,23 +85,19 @@ acpi_ps_create_scope_op (
*
******************************************************************************/
-void
-acpi_ps_init_op (
- union acpi_parse_object *op,
- u16 opcode)
+void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
op->common.data_type = ACPI_DESC_TYPE_PARSER;
op->common.aml_opcode = opcode;
- ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name,
- (acpi_ps_get_opcode_info (opcode))->name,
- sizeof (op->common.aml_op_name)));
+ ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name,
+ (acpi_ps_get_opcode_info
+ (opcode))->name,
+ sizeof(op->common.aml_op_name)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_alloc_op
@@ -123,29 +112,23 @@ acpi_ps_init_op (
*
******************************************************************************/
-union acpi_parse_object*
-acpi_ps_alloc_op (
- u16 opcode)
+union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
{
- union acpi_parse_object *op;
- const struct acpi_opcode_info *op_info;
- u8 flags = ACPI_PARSEOP_GENERIC;
-
+ union acpi_parse_object *op;
+ const struct acpi_opcode_info *op_info;
+ u8 flags = ACPI_PARSEOP_GENERIC;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
/* Determine type of parse_op required */
if (op_info->flags & AML_DEFER) {
flags = ACPI_PARSEOP_DEFERRED;
- }
- else if (op_info->flags & AML_NAMED) {
+ } else if (op_info->flags & AML_NAMED) {
flags = ACPI_PARSEOP_NAMED;
- }
- else if (opcode == AML_INT_BYTELIST_OP) {
+ } else if (opcode == AML_INT_BYTELIST_OP) {
flags = ACPI_PARSEOP_BYTELIST;
}
@@ -154,25 +137,25 @@ acpi_ps_alloc_op (
if (flags == ACPI_PARSEOP_GENERIC) {
/* The generic op (default) is by far the most common (16 to 1) */
- op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE);
- }
- else {
+ op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
+ memset(op, 0, sizeof(struct acpi_parse_obj_common));
+ } else {
/* Extended parseop */
- op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT);
+ op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache);
+ memset(op, 0, sizeof(struct acpi_parse_obj_named));
}
/* Initialize the Op */
if (op) {
- acpi_ps_init_op (op, opcode);
+ acpi_ps_init_op(op, opcode);
op->common.flags = flags;
}
return (op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_free_op
@@ -186,53 +169,22 @@ acpi_ps_alloc_op (
*
******************************************************************************/
-void
-acpi_ps_free_op (
- union acpi_parse_object *op)
+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", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
+ op));
}
if (op->common.flags & ACPI_PARSEOP_GENERIC) {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op);
- }
- else {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op);
+ (void)acpi_os_release_object(acpi_gbl_ps_node_cache, op);
+ } else {
+ (void)acpi_os_release_object(acpi_gbl_ps_node_ext_cache, op);
}
}
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_parse_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Free all objects that are on the parse cache list.
- *
- ******************************************************************************/
-
-void
-acpi_ps_delete_parse_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ps_delete_parse_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE);
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE_EXT);
- return_VOID;
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: Utility functions
@@ -241,36 +193,27 @@ acpi_ps_delete_parse_cache (
*
******************************************************************************/
-
/*
* Is "c" a namestring lead character?
*/
-u8
-acpi_ps_is_leading_char (
- u32 c)
+u8 acpi_ps_is_leading_char(u32 c)
{
return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
}
-
/*
* Is "c" a namestring prefix character?
*/
-u8
-acpi_ps_is_prefix_char (
- u32 c)
+u8 acpi_ps_is_prefix_char(u32 c)
{
return ((u8) (c == '\\' || c == '^'));
}
-
/*
* Get op's name (4-byte name segment) or 0 if unnamed
*/
#ifdef ACPI_FUTURE_USAGE
-u32
-acpi_ps_get_name (
- union acpi_parse_object *op)
+u32 acpi_ps_get_name(union acpi_parse_object * op)
{
/* The "generic" object has no name associated with it */
@@ -283,16 +226,12 @@ acpi_ps_get_name (
return (op->named.name);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*
* Set op's name
*/
-void
-acpi_ps_set_name (
- union acpi_parse_object *op,
- u32 name)
+void acpi_ps_set_name(union acpi_parse_object *op, u32 name)
{
/* The "generic" object has no name associated with it */
@@ -303,4 +242,3 @@ acpi_ps_set_name (
op->named.name = name;
}
-
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 9d20cb2ceb51..08f2321b6ded 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("pswalk")
-
+ACPI_MODULE_NAME("pswalk")
/*******************************************************************************
*
@@ -60,18 +58,13 @@
* DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *subtree_root)
+void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
{
- union acpi_parse_object *op = subtree_root;
- union acpi_parse_object *next = NULL;
- union acpi_parse_object *parent = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
+ union acpi_parse_object *op = subtree_root;
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root);
/* Visit all nodes in the subtree */
@@ -81,7 +74,7 @@ acpi_ps_delete_parse_tree (
if (op != parent) {
/* Look for an argument or child of the current op */
- next = acpi_ps_get_arg (op, 0);
+ next = acpi_ps_get_arg(op, 0);
if (next) {
/* Still going downward in tree (Op is not completed yet) */
@@ -95,7 +88,7 @@ acpi_ps_delete_parse_tree (
next = op->common.next;
parent = op->common.parent;
- acpi_ps_free_op (op);
+ acpi_ps_free_op(op);
/* If we are back to the starting point, the walk is complete. */
@@ -104,8 +97,7 @@ acpi_ps_delete_parse_tree (
}
if (next) {
op = next;
- }
- else {
+ } else {
op = parent;
}
}
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index dba893648e84..4dcbd443160e 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -41,24 +41,27 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psxface")
+ACPI_MODULE_NAME("psxface")
+
+/* Local Prototypes */
+static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
+static void
+acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action);
/*******************************************************************************
*
- * FUNCTION: acpi_psx_execute
+ * FUNCTION: acpi_ps_execute_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.
@@ -67,6 +70,7 @@
* parameter_type - Type of Parameter list
* return_object - Where to put method's return value (if
* any). If NULL, no value is returned.
+ * pass_number - Parse or execute pass
*
* RETURN: Status
*
@@ -74,173 +78,170 @@
*
******************************************************************************/
-acpi_status
-acpi_psx_execute (
- struct acpi_parameter_info *info)
+acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- u32 i;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("psx_execute");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ps_execute_method");
- /* Validate the Node and get the attached object */
+ /* Validate the Info and method Node */
if (!info || !info->node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
- }
-
- obj_desc = acpi_ns_get_attached_object (info->node);
- if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
/* Init for new method, wait on concurrency semaphore */
- status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if ((info->parameter_type == ACPI_PARAM_ARGS) &&
- (info->parameters)) {
- /*
- * The caller "owns" the parameters, so give each one an extra
- * reference
- */
- for (i = 0; info->parameters[i]; i++) {
- acpi_ut_add_reference (info->parameters[i]);
- }
- }
+ /*
+ * The caller "owns" the parameters, so give each one an extra
+ * reference
+ */
+ acpi_ps_update_parameter_list(info, REF_INCREMENT);
/*
* 1) Perform the first pass parse of the method to enter any
- * named objects that it creates into the namespace
+ * named objects that it creates into the namespace
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Parse **** Entry=%p obj=%p\n",
- info->node, obj_desc));
-
- /* Create and init a Root Node */
-
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Parse **** Entry=%p obj=%p\n",
+ info->node, info->obj_desc));
+
+ info->pass_number = 1;
+ status = acpi_ps_execute_pass(info);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
/*
- * Get a new owner_id for objects created by this method. Namespace
- * objects (such as Operation Regions) can be created during the
- * first pass parse.
+ * 2) Execute the method. Performs second pass parse simultaneously
*/
- obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Execution **** Entry=%p obj=%p\n",
+ info->node, info->obj_desc));
- /* Create and initialize a new walk state */
+ info->pass_number = 3;
+ status = acpi_ps_execute_pass(info);
- walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
- }
+ cleanup:
+ /* Take away the extra reference that we gave the parameters above */
- status = acpi_ds_init_aml_walk (walk_state, op, info->node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
- }
+ acpi_ps_update_parameter_list(info, REF_DECREMENT);
- /* Parse the AML */
+ /* Exit now if error above */
- status = acpi_ps_parse_aml (walk_state);
- acpi_ps_delete_parse_tree (op);
- if (ACPI_FAILURE (status)) {
- goto cleanup1; /* Walk state is already deleted */
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
- * 2) Execute the method. Performs second pass parse simultaneously
+ * If the method has returned an object, signal this to the caller with
+ * a control exception code
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Execution **** Entry=%p obj=%p\n",
- info->node, obj_desc));
-
- /* Create and init a Root Node */
+ if (info->return_object) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Method returned obj_desc=%p\n",
+ info->return_object));
+ ACPI_DUMP_STACK_ENTRY(info->return_object);
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
+ status = AE_CTRL_RETURN_VALUE;
}
- /* Init new op with the method name and pointer back to the NS node */
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_update_parameter_list
+ *
+ * PARAMETERS: Info - See struct acpi_parameter_info
+ * (Used: parameter_type and Parameters)
+ * Action - Add or Remove reference
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Update reference count on all method parameter objects
+ *
+ ******************************************************************************/
- acpi_ps_set_name (op, info->node->name.integer);
- op->common.node = info->node;
+static void
+acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
+{
+ acpi_native_uint i;
- /* Create and initialize a new walk state */
+ if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+ /* Update reference count for each parameter */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
- }
+ for (i = 0; info->parameters[i]; i++) {
+ /* Ignore errors, just do them all */
- status = acpi_ds_init_aml_walk (walk_state, op, info->node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, info, 3);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
+ (void)acpi_ut_update_object_reference(info->
+ parameters[i],
+ action);
+ }
}
+}
- /* The walk of the parse tree is where we actually execute the method */
-
- status = acpi_ps_parse_aml (walk_state);
- goto cleanup2; /* Walk state already deleted */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_execute_pass
+ *
+ * PARAMETERS: Info - See struct acpi_parameter_info
+ * (Used: pass_number, Node, and obj_desc)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Single AML pass: Parse or Execute a control method
+ *
+ ******************************************************************************/
+static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info)
+{
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
-cleanup3:
- acpi_ds_delete_walk_state (walk_state);
+ ACPI_FUNCTION_TRACE("ps_execute_pass");
-cleanup2:
- acpi_ps_delete_parse_tree (op);
+ /* Create and init a Root Node */
-cleanup1:
- if ((info->parameter_type == ACPI_PARAM_ARGS) &&
- (info->parameters)) {
- /* Take away the extra reference that we gave the parameters above */
+ op = acpi_ps_create_scope_op();
+ if (!op) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
- for (i = 0; info->parameters[i]; i++) {
- /* Ignore errors, just do them all */
+ /* Create and initialize a new walk state */
- (void) acpi_ut_update_object_reference (
- info->parameters[i], REF_DECREMENT);
- }
+ walk_state =
+ acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
+ NULL, NULL);
+ if (!walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, info->node,
+ info->obj_desc->method.aml_start,
+ info->obj_desc->method.aml_length,
+ info->pass_number == 1 ? NULL : info,
+ info->pass_number);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
- /*
- * If the method has returned an object, signal this to the caller with
- * a control exception code
- */
- if (info->return_object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
- info->return_object));
- ACPI_DUMP_STACK_ENTRY (info->return_object);
-
- status = AE_CTRL_RETURN_VALUE;
- }
+ /* Parse the AML */
- return_ACPI_STATUS (status);
-}
+ status = acpi_ps_parse_aml(walk_state);
+ /* Walk state was deleted by parse_aml */
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 5148f3c10b5c..2a718df769b5 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -35,22 +35,17 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_bind")
+ACPI_MODULE_NAME("pci_bind")
struct acpi_pci_data {
- struct acpi_pci_id id;
- struct pci_bus *bus;
- struct pci_dev *dev;
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
+ struct pci_dev *dev;
};
-
-void
-acpi_pci_data_handler (
- acpi_handle handle,
- u32 function,
- void *context)
+static void acpi_pci_data_handler(acpi_handle handle, u32 function,
+ void *context)
{
ACPI_FUNCTION_TRACE("acpi_pci_data_handler");
@@ -59,7 +54,6 @@ acpi_pci_data_handler (
return_VOID;
}
-
/**
* acpi_get_pci_id
* ------------------
@@ -67,15 +61,12 @@ acpi_pci_data_handler (
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
* This typically occurs when resolving PCI operation region information.
*/
-acpi_status
-acpi_get_pci_id (
- acpi_handle handle,
- struct acpi_pci_id *id)
+acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
- struct acpi_pci_data *data = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_data *data = NULL;
ACPI_FUNCTION_TRACE("acpi_get_pci_id");
@@ -84,52 +75,50 @@ acpi_get_pci_id (
result = acpi_bus_get_device(handle, &device);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI Bus context for device %s\n",
- acpi_device_bid(device)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI Bus context for device %s\n",
+ acpi_device_bid(device)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
- status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
+ status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data);
if (ACPI_FAILURE(status) || !data) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI-PCI context for device %s\n",
- acpi_device_bid(device)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI-PCI context for device %s\n",
+ acpi_device_bid(device)));
return_ACPI_STATUS(status);
}
*id = data->id;
-
+
/*
- id->segment = data->id.segment;
- id->bus = data->id.bus;
- id->device = data->id.device;
- id->function = data->id.function;
- */
+ id->segment = data->id.segment;
+ id->bus = data->id.bus;
+ id->device = data->id.device;
+ id->function = data->id.function;
+ */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %s has PCI address %02x:%02x:%02x.%02x\n",
- acpi_device_bid(device), id->segment, id->bus,
- id->device, id->function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %s has PCI address %02x:%02x:%02x.%02x\n",
+ acpi_device_bid(device), id->segment, id->bus,
+ id->device, id->function));
return_ACPI_STATUS(AE_OK);
}
+
EXPORT_SYMBOL(acpi_get_pci_id);
-
-int
-acpi_pci_bind (
- struct acpi_device *device)
+int acpi_pci_bind(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- struct acpi_pci_data *pdata = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
- acpi_handle handle = NULL;
- struct pci_dev *dev;
- struct pci_bus *bus;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ struct acpi_pci_data *pdata = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
+ acpi_handle handle = NULL;
+ struct pci_dev *dev;
+ struct pci_bus *bus;
ACPI_FUNCTION_TRACE("acpi_pci_bind");
@@ -137,34 +126,34 @@ acpi_pci_bind (
return_VALUE(-EINVAL);
pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data){
- kfree (pathname);
+ if (!data) {
+ kfree(pathname);
return_VALUE(-ENOMEM);
}
memset(data, 0, sizeof(struct acpi_pci_data));
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
- pathname));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
+ pathname));
/*
* Segment & Bus
* -------------
* These are obtained via the parent device's ACPI-PCI context.
*/
- status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
- (void**) &pdata);
+ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
+ (void **)&pdata);
if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI-PCI context for parent device %s\n",
- acpi_device_bid(device->parent)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI-PCI context for parent device %s\n",
+ acpi_device_bid(device->parent)));
result = -ENODEV;
goto end;
}
@@ -181,8 +170,8 @@ acpi_pci_bind (
data->id.function = device->pnp.bus_address & 0xFFFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n",
- data->id.segment, data->id.bus, data->id.device,
- data->id.function));
+ data->id.segment, data->id.bus, data->id.device,
+ data->id.function));
/*
* TBD: Support slot devices (e.g. function=0xFFFF).
@@ -202,25 +191,25 @@ acpi_pci_bind (
if (bus) {
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->devfn == PCI_DEVFN(data->id.device,
- data->id.function)) {
+ data->id.function)) {
data->dev = dev;
break;
}
}
}
if (!data->dev) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
if (!data->dev->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
@@ -232,10 +221,10 @@ acpi_pci_bind (
* facilitate callbacks for all of its children.
*/
if (data->dev->subordinate) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
data->bus = data->dev->subordinate;
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
@@ -249,8 +238,8 @@ acpi_pci_bind (
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to attach ACPI-PCI context to device %s\n",
- acpi_device_bid(device)));
+ "Unable to attach ACPI-PCI context to device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -267,15 +256,15 @@ acpi_pci_bind (
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status)) {
- if (data->bus) /* PCI-PCI bridge */
- acpi_pci_irq_add_prt(device->handle, data->id.segment,
- data->bus->number);
- else /* non-bridge PCI device */
+ if (data->bus) /* PCI-PCI bridge */
acpi_pci_irq_add_prt(device->handle, data->id.segment,
- data->id.bus);
+ data->bus->number);
+ else /* non-bridge PCI device */
+ acpi_pci_irq_add_prt(device->handle, data->id.segment,
+ data->id.bus);
}
-end:
+ end:
kfree(pathname);
if (result)
kfree(data);
@@ -283,22 +272,21 @@ end:
return_VALUE(result);
}
-int acpi_pci_unbind(
- struct acpi_device *device)
+int acpi_pci_unbind(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_unbind");
if (!device || !device->parent)
return_VALUE(-EINVAL);
- pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
@@ -306,14 +294,16 @@ int acpi_pci_unbind(
buffer.pointer = pathname;
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
- pathname));
+ pathname));
kfree(pathname);
- status = acpi_get_data(device->handle, acpi_pci_data_handler, (void**)&data);
+ status =
+ acpi_get_data(device->handle, acpi_pci_data_handler,
+ (void **)&data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to get data from device %s\n",
- acpi_device_bid(device)));
+ "Unable to get data from device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -321,8 +311,8 @@ int acpi_pci_unbind(
status = acpi_detach_data(device->handle, acpi_pci_data_handler);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to detach data from device %s\n",
- acpi_device_bid(device)));
+ "Unable to detach data from device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -331,39 +321,37 @@ int acpi_pci_unbind(
}
kfree(data);
-end:
+ end:
return_VALUE(result);
}
-int
-acpi_pci_bind_root (
- struct acpi_device *device,
- struct acpi_pci_id *id,
- struct pci_bus *bus)
+int
+acpi_pci_bind_root(struct acpi_device *device,
+ struct acpi_pci_id *id, struct pci_bus *bus)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_bind_root");
pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
- if (!device || !id || !bus){
+ if (!device || !id || !bus) {
kfree(pathname);
return_VALUE(-EINVAL);
}
data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data){
+ if (!data) {
kfree(pathname);
return_VALUE(-ENOMEM);
}
@@ -377,18 +365,18 @@ acpi_pci_bind_root (
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
- "%02x:%02x\n", pathname, id->segment, id->bus));
+ "%02x:%02x\n", pathname, id->segment, id->bus));
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to attach ACPI-PCI context to device %s\n",
- pathname));
+ "Unable to attach ACPI-PCI context to device %s\n",
+ pathname));
result = -ENODEV;
goto end;
}
-end:
+ end:
kfree(pathname);
if (result != 0)
kfree(data);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index bb973d2109a1..09567c2edcfb 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -38,26 +38,22 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_irq")
+ACPI_MODULE_NAME("pci_irq")
-static struct acpi_prt_list acpi_prt;
+static struct acpi_prt_list acpi_prt;
static DEFINE_SPINLOCK(acpi_prt_lock);
/* --------------------------------------------------------------------------
PCI IRQ Routing Table (PRT) Support
-------------------------------------------------------------------------- */
-static struct acpi_prt_entry *
-acpi_pci_irq_find_prt_entry (
- int segment,
- int bus,
- int device,
- int pin)
+static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
+ int bus,
+ int device, int pin)
{
- struct list_head *node = NULL;
- struct acpi_prt_entry *entry = NULL;
+ struct list_head *node = NULL;
+ struct acpi_prt_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
@@ -72,10 +68,10 @@ acpi_pci_irq_find_prt_entry (
spin_lock(&acpi_prt_lock);
list_for_each(node, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
- if ((segment == entry->id.segment)
- && (bus == entry->id.bus)
- && (device == entry->id.device)
- && (pin == entry->pin)) {
+ if ((segment == entry->id.segment)
+ && (bus == entry->id.bus)
+ && (device == entry->id.device)
+ && (pin == entry->pin)) {
spin_unlock(&acpi_prt_lock);
return_PTR(entry);
}
@@ -85,15 +81,11 @@ acpi_pci_irq_find_prt_entry (
return_PTR(NULL);
}
-
static int
-acpi_pci_irq_add_entry (
- acpi_handle handle,
- int segment,
- int bus,
- struct acpi_pci_routing_table *prt)
+acpi_pci_irq_add_entry(acpi_handle handle,
+ int segment, int bus, struct acpi_pci_routing_table *prt)
{
- struct acpi_prt_entry *entry = NULL;
+ struct acpi_prt_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_add_entry");
@@ -139,9 +131,10 @@ acpi_pci_irq_add_entry (
entry->link.index = prt->source_index;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
- " %02X:%02X:%02X[%c] -> %s[%d]\n",
- entry->id.segment, entry->id.bus, entry->id.device,
- ('A' + entry->pin), prt->source, entry->link.index));
+ " %02X:%02X:%02X[%c] -> %s[%d]\n",
+ entry->id.segment, entry->id.bus,
+ entry->id.device, ('A' + entry->pin), prt->source,
+ entry->link.index));
spin_lock(&acpi_prt_lock);
list_add_tail(&entry->node, &acpi_prt.entries);
@@ -151,38 +144,29 @@ acpi_pci_irq_add_entry (
return_VALUE(0);
}
-
static void
-acpi_pci_irq_del_entry (
- int segment,
- int bus,
- struct acpi_prt_entry *entry)
+acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry)
{
- if (segment == entry->id.segment && bus == entry->id.bus){
+ if (segment == entry->id.segment && bus == entry->id.bus) {
acpi_prt.count--;
list_del(&entry->node);
kfree(entry);
}
}
-
-int
-acpi_pci_irq_add_prt (
- acpi_handle handle,
- int segment,
- int bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
{
- acpi_status status = AE_OK;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
- struct acpi_pci_routing_table *prt = NULL;
- struct acpi_pci_routing_table *entry = NULL;
- static int first_time = 1;
+ acpi_status status = AE_OK;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
+ struct acpi_pci_routing_table *prt = NULL;
+ struct acpi_pci_routing_table *entry = NULL;
+ static int first_time = 1;
ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
- pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
@@ -202,7 +186,7 @@ acpi_pci_irq_add_prt (
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
- pathname);
+ pathname);
/*
* Evaluate this _PRT and add its entries to our global list (acpi_prt).
@@ -214,12 +198,12 @@ acpi_pci_irq_add_prt (
status = acpi_get_irq_routing_table(handle, &buffer);
if (status != AE_BUFFER_OVERFLOW) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
- acpi_format_exception(status)));
+ acpi_format_exception(status)));
return_VALUE(-ENODEV);
}
prt = kmalloc(buffer.length, GFP_KERNEL);
- if (!prt){
+ if (!prt) {
return_VALUE(-ENOMEM);
}
memset(prt, 0, buffer.length);
@@ -228,7 +212,7 @@ acpi_pci_irq_add_prt (
status = acpi_get_irq_routing_table(handle, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
- acpi_format_exception(status)));
+ acpi_format_exception(status)));
kfree(buffer.pointer);
return_VALUE(-ENODEV);
}
@@ -238,7 +222,7 @@ acpi_pci_irq_add_prt (
while (entry && (entry->length > 0)) {
acpi_pci_irq_add_entry(handle, segment, bus, entry);
entry = (struct acpi_pci_routing_table *)
- ((unsigned long) entry + entry->length);
+ ((unsigned long)entry + entry->length);
}
kfree(prt);
@@ -246,18 +230,18 @@ acpi_pci_irq_add_prt (
return_VALUE(0);
}
-void
-acpi_pci_irq_del_prt (int segment, int bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
{
- struct list_head *node = NULL, *n = NULL;
- struct acpi_prt_entry *entry = NULL;
+ struct list_head *node = NULL, *n = NULL;
+ struct acpi_prt_entry *entry = NULL;
- if (!acpi_prt.count) {
+ if (!acpi_prt.count) {
return;
}
- printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n",
- segment, bus);
+ printk(KERN_DEBUG
+ "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", segment,
+ bus);
spin_lock(&acpi_prt_lock);
list_for_each_safe(node, n, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
@@ -266,26 +250,27 @@ acpi_pci_irq_del_prt (int segment, int bus)
}
spin_unlock(&acpi_prt_lock);
}
+
/* --------------------------------------------------------------------------
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
-typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **);
+typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **);
static int
acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
- int *edge_level,
- int *active_high_low,
- char **link)
+ int *edge_level, int *active_high_low, char **link)
{
- int irq;
+ int irq;
ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq");
if (entry->link.handle) {
irq = acpi_pci_link_allocate_irq(entry->link.handle,
- entry->link.index, edge_level, active_high_low, link);
+ entry->link.index, edge_level,
+ active_high_low, link);
if (irq < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ link routing entry\n"));
return_VALUE(-1);
}
} else {
@@ -300,11 +285,9 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
static int
acpi_pci_free_irq(struct acpi_prt_entry *entry,
- int *edge_level,
- int *active_high_low,
- char **link)
+ int *edge_level, int *active_high_low, char **link)
{
- int irq;
+ int irq;
ACPI_FUNCTION_TRACE("acpi_pci_free_irq");
if (entry->link.handle) {
@@ -314,38 +297,36 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry,
}
return_VALUE(irq);
}
+
/*
* acpi_pci_irq_lookup
* success: return IRQ >= 0
* failure: return -1
*/
static int
-acpi_pci_irq_lookup (
- struct pci_bus *bus,
- int device,
- int pin,
- int *edge_level,
- int *active_high_low,
- char **link,
- irq_lookup_func func)
+acpi_pci_irq_lookup(struct pci_bus *bus,
+ int device,
+ int pin,
+ int *edge_level,
+ int *active_high_low, char **link, irq_lookup_func func)
{
- struct acpi_prt_entry *entry = NULL;
+ struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
int bus_nr = bus->number;
int ret;
ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
- segment, bus_nr, device, ('A' + pin)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
+ segment, bus_nr, device, ('A' + pin)));
- entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
+ entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
if (!entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
return_VALUE(-1);
}
-
+
ret = func(entry, edge_level, active_high_low, link);
return_VALUE(ret);
}
@@ -356,17 +337,14 @@ acpi_pci_irq_lookup (
* failure: return < 0
*/
static int
-acpi_pci_irq_derive (
- struct pci_dev *dev,
- int pin,
- int *edge_level,
- int *active_high_low,
- char **link,
- irq_lookup_func func)
+acpi_pci_irq_derive(struct pci_dev *dev,
+ int pin,
+ int *edge_level,
+ int *active_high_low, char **link, irq_lookup_func func)
{
- struct pci_dev *bridge = dev;
- int irq = -1;
- u8 bridge_pin = 0;
+ struct pci_dev *bridge = dev;
+ int irq = -1;
+ u8 bridge_pin = 0;
ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
@@ -383,28 +361,33 @@ acpi_pci_irq_derive (
if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
/* PC card has the same IRQ as its cardbridge */
- pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
+ pci_read_config_byte(bridge, PCI_INTERRUPT_PIN,
+ &bridge_pin);
if (!bridge_pin) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No interrupt pin configured for device %s\n", pci_name(bridge)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No interrupt pin configured for device %s\n",
+ pci_name(bridge)));
return_VALUE(-1);
}
/* Pin is from 0 to 3 */
- bridge_pin --;
+ bridge_pin--;
pin = bridge_pin;
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low, link, func);
+ pin, edge_level, active_high_low,
+ link, func);
}
if (irq < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to derive IRQ for device %s\n",
+ pci_name(dev)));
return_VALUE(-1);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
- irq, pci_name(dev), pci_name(bridge)));
+ irq, pci_name(dev), pci_name(bridge)));
return_VALUE(irq);
}
@@ -415,30 +398,32 @@ acpi_pci_irq_derive (
* failure: return < 0
*/
-int
-acpi_pci_irq_enable (
- struct pci_dev *dev)
+int acpi_pci_irq_enable(struct pci_dev *dev)
{
- int irq = 0;
- u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
- char *link = NULL;
+ int irq = 0;
+ u8 pin = 0;
+ int edge_level = ACPI_LEVEL_SENSITIVE;
+ int active_high_low = ACPI_ACTIVE_LOW;
+ char *link = NULL;
+ int rc;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
if (!dev)
return_VALUE(-EINVAL);
-
+
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(dev)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No interrupt pin configured for device %s\n",
+ pci_name(dev)));
return_VALUE(0);
}
pin--;
if (!dev->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) 'bus' field\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid (NULL) 'bus' field\n"));
return_VALUE(-ENODEV);
}
@@ -446,69 +431,76 @@ acpi_pci_irq_enable (
* First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
* values override any BIOS-assigned IRQs set during boot.
*/
- irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, &link, acpi_pci_allocate_irq);
+ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, &link,
+ acpi_pci_allocate_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &edge_level,
- &active_high_low, &link, acpi_pci_allocate_irq);
-
+ irq = acpi_pci_irq_derive(dev, pin, &edge_level,
+ &active_high_low, &link,
+ acpi_pci_allocate_irq);
+
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.
*/
if (irq < 0) {
printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
- pci_name(dev), ('A' + pin));
+ pci_name(dev), ('A' + pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
- acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
+ acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
+ ACPI_ACTIVE_LOW);
return_VALUE(0);
- }
- else {
+ } else {
printk("\n");
return_VALUE(0);
}
- }
+ }
- dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
+ rc = acpi_register_gsi(irq, edge_level, active_high_low);
+ if (rc < 0) {
+ printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
+ "to register GSI\n", pci_name(dev), ('A' + pin));
+ return_VALUE(rc);
+ }
+ dev->irq = rc;
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
- pci_name(dev), 'A' + pin);
+ pci_name(dev), 'A' + pin);
if (link)
printk("Link [%s] -> ", link);
printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
- (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
- dev->irq);
+ (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_pci_irq_enable);
+EXPORT_SYMBOL(acpi_pci_irq_enable);
/* FIXME: implement x86/x86_64 version */
-void __attribute__((weak)) acpi_unregister_gsi(u32 i) {}
+void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
+{
+}
-void
-acpi_pci_irq_disable (
- struct pci_dev *dev)
+void acpi_pci_irq_disable(struct pci_dev *dev)
{
- int gsi = 0;
- u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
+ int gsi = 0;
+ u8 pin = 0;
+ int edge_level = ACPI_LEVEL_SENSITIVE;
+ int active_high_low = ACPI_ACTIVE_LOW;
ACPI_FUNCTION_TRACE("acpi_pci_irq_disable");
- if (!dev)
+ if (!dev || !dev->bus)
return_VOID;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -516,21 +508,20 @@ acpi_pci_irq_disable (
return_VOID;
pin--;
- if (!dev->bus)
- return_VOID;
-
/*
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
- gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
+ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, NULL,
+ acpi_pci_free_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (gsi < 0)
- gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
+ gsi = acpi_pci_irq_derive(dev, pin,
+ &edge_level, &active_high_low, NULL,
+ acpi_pci_free_irq);
if (gsi < 0)
return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 834c2ceff1aa..82292b77e5c6 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -42,30 +42,26 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_link")
-
+ACPI_MODULE_NAME("pci_link")
#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
#define ACPI_PCI_LINK_HID "PNP0C0F"
#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
#define ACPI_PCI_LINK_FILE_INFO "info"
#define ACPI_PCI_LINK_FILE_STATUS "state"
-
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
-
-static int acpi_pci_link_add (struct acpi_device *device);
-static int acpi_pci_link_remove (struct acpi_device *device, int type);
+static int acpi_pci_link_add(struct acpi_device *device);
+static int acpi_pci_link_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_pci_link_driver = {
- .name = ACPI_PCI_LINK_DRIVER_NAME,
- .class = ACPI_PCI_LINK_CLASS,
- .ids = ACPI_PCI_LINK_HID,
- .ops = {
- .add = acpi_pci_link_add,
- .remove = acpi_pci_link_remove,
- },
+ .name = ACPI_PCI_LINK_DRIVER_NAME,
+ .class = ACPI_PCI_LINK_CLASS,
+ .ids = ACPI_PCI_LINK_HID,
+ .ops = {
+ .add = acpi_pci_link_add,
+ .remove = acpi_pci_link_remove,
+ },
};
/*
@@ -73,31 +69,30 @@ static struct acpi_driver acpi_pci_link_driver = {
* later even the link is disable. Instead, we just repick the active irq
*/
struct acpi_pci_link_irq {
- u8 active; /* Current IRQ */
- u8 edge_level; /* All IRQs */
- u8 active_high_low; /* All IRQs */
- u8 resource_type;
- u8 possible_count;
- u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
- u8 initialized:1;
- u8 reserved:7;
+ u8 active; /* Current IRQ */
+ u8 edge_level; /* All IRQs */
+ u8 active_high_low; /* All IRQs */
+ u8 resource_type;
+ u8 possible_count;
+ u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+ u8 initialized:1;
+ u8 reserved:7;
};
struct acpi_pci_link {
- struct list_head node;
- struct acpi_device *device;
- acpi_handle handle;
+ struct list_head node;
+ struct acpi_device *device;
+ acpi_handle handle;
struct acpi_pci_link_irq irq;
- int refcnt;
+ int refcnt;
};
static struct {
- int count;
- struct list_head entries;
-} acpi_link;
+ int count;
+ struct list_head entries;
+} acpi_link;
DECLARE_MUTEX(acpi_link_lock);
-
/* --------------------------------------------------------------------------
PCI Link Device Management
-------------------------------------------------------------------------- */
@@ -106,12 +101,10 @@ DECLARE_MUTEX(acpi_link_lock);
* set context (link) possible list from resource list
*/
static acpi_status
-acpi_pci_link_check_possible (
- struct acpi_resource *resource,
- void *context)
+acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
{
- struct acpi_pci_link *link = (struct acpi_pci_link *) context;
- u32 i = 0;
+ struct acpi_pci_link *link = (struct acpi_pci_link *)context;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
@@ -119,61 +112,68 @@ acpi_pci_link_check_possible (
case ACPI_RSTYPE_START_DPF:
return_ACPI_STATUS(AE_OK);
case ACPI_RSTYPE_IRQ:
- {
- struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
- }
- for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
- if (!p->interrupts[i]) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
- continue;
+ {
+ struct acpi_resource_irq *p = &resource->data.irq;
+ if (!p || !p->number_of_interrupts) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
}
- link->irq.possible[i] = p->interrupts[i];
- link->irq.possible_count++;
+ for (i = 0;
+ (i < p->number_of_interrupts
+ && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
+ if (!p->interrupts[i]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ %d\n",
+ p->interrupts[i]));
+ continue;
+ }
+ link->irq.possible[i] = p->interrupts[i];
+ link->irq.possible_count++;
+ }
+ link->irq.edge_level = p->edge_level;
+ link->irq.active_high_low = p->active_high_low;
+ link->irq.resource_type = ACPI_RSTYPE_IRQ;
+ break;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_IRQ;
- break;
- }
case ACPI_RSTYPE_EXT_IRQ:
- {
- struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Blank EXT IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
- }
- for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
- if (!p->interrupts[i]) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
- continue;
+ {
+ struct acpi_resource_ext_irq *p =
+ &resource->data.extended_irq;
+ if (!p || !p->number_of_interrupts) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank EXT IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ for (i = 0;
+ (i < p->number_of_interrupts
+ && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
+ if (!p->interrupts[i]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ %d\n",
+ p->interrupts[i]));
+ continue;
+ }
+ link->irq.possible[i] = p->interrupts[i];
+ link->irq.possible_count++;
}
- link->irq.possible[i] = p->interrupts[i];
- link->irq.possible_count++;
+ link->irq.edge_level = p->edge_level;
+ link->irq.active_high_low = p->active_high_low;
+ link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
+ break;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
- break;
- }
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Resource is not an IRQ entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Resource is not an IRQ entry\n"));
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
-
-static int
-acpi_pci_link_get_possible (
- struct acpi_pci_link *link)
+static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
{
- acpi_status status;
+ acpi_status status;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
@@ -181,62 +181,60 @@ acpi_pci_link_get_possible (
return_VALUE(-EINVAL);
status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
- acpi_pci_link_check_possible, link);
+ acpi_pci_link_check_possible, link);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
return_VALUE(-ENODEV);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Found %d possible IRQs\n", link->irq.possible_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found %d possible IRQs\n",
+ link->irq.possible_count));
return_VALUE(0);
}
-
static acpi_status
-acpi_pci_link_check_current (
- struct acpi_resource *resource,
- void *context)
+acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
{
- int *irq = (int *) context;
+ int *irq = (int *)context;
ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
switch (resource->id) {
case ACPI_RSTYPE_IRQ:
- {
- struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
- /*
- * IRQ descriptors may have no IRQ# bits set,
- * particularly those those w/ _STA disabled
- */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Blank IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
+ {
+ struct acpi_resource_irq *p = &resource->data.irq;
+ if (!p || !p->number_of_interrupts) {
+ /*
+ * IRQ descriptors may have no IRQ# bits set,
+ * particularly those those w/ _STA disabled
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Blank IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ *irq = p->interrupts[0];
+ break;
}
- *irq = p->interrupts[0];
- break;
- }
case ACPI_RSTYPE_EXT_IRQ:
- {
- struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
- /*
- * extended IRQ descriptors must
- * return at least 1 IRQ
- */
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Blank EXT IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
+ {
+ struct acpi_resource_ext_irq *p =
+ &resource->data.extended_irq;
+ if (!p || !p->number_of_interrupts) {
+ /*
+ * extended IRQ descriptors must
+ * return at least 1 IRQ
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank EXT IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ *irq = p->interrupts[0];
+ break;
}
- *irq = p->interrupts[0];
- break;
- }
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Resource isn't an IRQ\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n"));
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_CTRL_TERMINATE);
@@ -249,13 +247,11 @@ acpi_pci_link_check_current (
* 0 - success
* !0 - failure
*/
-static int
-acpi_pci_link_get_current (
- struct acpi_pci_link *link)
+static int acpi_pci_link_get_current(struct acpi_pci_link *link)
{
- int result = 0;
- acpi_status status = AE_OK;
- int irq = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ int irq = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
@@ -269,7 +265,8 @@ acpi_pci_link_get_current (
/* Query _STA, set link->device->status */
result = acpi_bus_get_status(link->device);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to read status\n"));
goto end;
}
@@ -284,7 +281,7 @@ acpi_pci_link_get_current (
*/
status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
- acpi_pci_link_check_current, &irq);
+ acpi_pci_link_check_current, &irq);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
result = -ENODEV;
@@ -300,58 +297,61 @@ acpi_pci_link_get_current (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
-end:
+ end:
return_VALUE(result);
}
-static int
-acpi_pci_link_set (
- struct acpi_pci_link *link,
- int irq)
+static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
{
- int result = 0;
- acpi_status status = AE_OK;
+ int result = 0;
+ acpi_status status = AE_OK;
struct {
- struct acpi_resource res;
- struct acpi_resource end;
- } *resource;
- struct acpi_buffer buffer = {0, NULL};
+ struct acpi_resource res;
+ struct acpi_resource end;
+ } *resource;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_link_set");
if (!link || !irq)
return_VALUE(-EINVAL);
- resource = kmalloc( sizeof(*resource)+1, GFP_KERNEL);
- if(!resource)
+ resource = kmalloc(sizeof(*resource) + 1, GFP_KERNEL);
+ if (!resource)
return_VALUE(-ENOMEM);
- memset(resource, 0, sizeof(*resource)+1);
- buffer.length = sizeof(*resource) +1;
+ memset(resource, 0, sizeof(*resource) + 1);
+ buffer.length = sizeof(*resource) + 1;
buffer.pointer = resource;
- switch(link->irq.resource_type) {
+ switch (link->irq.resource_type) {
case ACPI_RSTYPE_IRQ:
resource->res.id = ACPI_RSTYPE_IRQ;
resource->res.length = sizeof(struct acpi_resource);
resource->res.data.irq.edge_level = link->irq.edge_level;
- resource->res.data.irq.active_high_low = link->irq.active_high_low;
+ resource->res.data.irq.active_high_low =
+ link->irq.active_high_low;
if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->res.data.irq.shared_exclusive =
+ ACPI_EXCLUSIVE;
else
resource->res.data.irq.shared_exclusive = ACPI_SHARED;
resource->res.data.irq.number_of_interrupts = 1;
resource->res.data.irq.interrupts[0] = irq;
break;
-
+
case ACPI_RSTYPE_EXT_IRQ:
resource->res.id = ACPI_RSTYPE_EXT_IRQ;
resource->res.length = sizeof(struct acpi_resource);
- resource->res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
- resource->res.data.extended_irq.edge_level = link->irq.edge_level;
- resource->res.data.extended_irq.active_high_low = link->irq.active_high_low;
+ resource->res.data.extended_irq.producer_consumer =
+ ACPI_CONSUMER;
+ resource->res.data.extended_irq.edge_level =
+ link->irq.edge_level;
+ resource->res.data.extended_irq.active_high_low =
+ link->irq.active_high_low;
if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->res.data.irq.shared_exclusive =
+ ACPI_EXCLUSIVE;
else
resource->res.data.irq.shared_exclusive = ACPI_SHARED;
resource->res.data.extended_irq.number_of_interrupts = 1;
@@ -384,9 +384,9 @@ acpi_pci_link_set (
}
if (!link->device->status.enabled) {
printk(KERN_WARNING PREFIX
- "%s [%s] disabled and referenced, BIOS bug.\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device));
+ "%s [%s] disabled and referenced, BIOS bug.\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device));
}
/* Query _CRS, set link->irq.active */
@@ -404,22 +404,20 @@ acpi_pci_link_set (
* policy: when _CRS doesn't return what we just _SRS
* assume _SRS worked and override _CRS value.
*/
- printk(KERN_WARNING PREFIX
- "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device),
- link->irq.active, irq);
+ printk(KERN_WARNING PREFIX
+ "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device), link->irq.active, irq);
link->irq.active = irq;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
-
-end:
+
+ end:
kfree(resource);
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
PCI Link IRQ Management
-------------------------------------------------------------------------- */
@@ -469,8 +467,8 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
- PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
- PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
+ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
+ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
@@ -482,15 +480,14 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
- /* >IRQ15 */
+ /* >IRQ15 */
};
-int __init
-acpi_irq_penalty_init(void)
+int __init acpi_irq_penalty_init(void)
{
- struct list_head *node = NULL;
- struct acpi_pci_link *link = NULL;
- int i = 0;
+ struct list_head *node = NULL;
+ struct acpi_pci_link *link = NULL;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
@@ -501,7 +498,8 @@ acpi_irq_penalty_init(void)
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid link context\n"));
continue;
}
@@ -510,15 +508,20 @@ acpi_irq_penalty_init(void)
* useful for breaking ties.
*/
if (link->irq.possible_count) {
- int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
+ int penalty =
+ PIRQ_PENALTY_PCI_POSSIBLE /
+ link->irq.possible_count;
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
- acpi_irq_penalty[link->irq.possible[i]] += penalty;
+ acpi_irq_penalty[link->irq.
+ possible[i]] +=
+ penalty;
}
} else if (link->irq.active) {
- acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE;
+ acpi_irq_penalty[link->irq.active] +=
+ PIRQ_PENALTY_PCI_POSSIBLE;
}
}
/* Add a penalty for the SCI */
@@ -529,11 +532,10 @@ acpi_irq_penalty_init(void)
static int acpi_irq_balance; /* 0: static, 1: balance */
-static int acpi_pci_link_allocate(
- struct acpi_pci_link *link)
+static int acpi_pci_link_allocate(struct acpi_pci_link *link)
{
- int irq;
- int i;
+ int irq;
+ int i;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
@@ -557,7 +559,7 @@ static int acpi_pci_link_allocate(
if (i == link->irq.possible_count) {
if (acpi_strict)
printk(KERN_WARNING PREFIX "_CRS %d not found"
- " in _PRS\n", link->irq.active);
+ " in _PRS\n", link->irq.active);
link->irq.active = 0;
}
@@ -576,23 +578,25 @@ static int acpi_pci_link_allocate(
* the use of IRQs 9, 10, 11, and >15.
*/
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
- if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+ if (acpi_irq_penalty[irq] >
+ acpi_irq_penalty[link->irq.possible[i]])
irq = link->irq.possible[i];
}
}
/* Attempt to enable the link device at this IRQ. */
if (acpi_pci_link_set(link, irq)) {
- printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
- "Try pci=noacpi or acpi=off\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device));
+ printk(PREFIX
+ "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
+ "Try pci=noacpi or acpi=off\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device));
return_VALUE(-ENODEV);
} else {
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
- printk(PREFIX "%s [%s] enabled at IRQ %d\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device), link->irq.active);
+ printk(PREFIX "%s [%s] enabled at IRQ %d\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device), link->irq.active);
}
link->irq.initialized = 1;
@@ -607,16 +611,13 @@ static int acpi_pci_link_allocate(
*/
int
-acpi_pci_link_allocate_irq (
- acpi_handle handle,
- int index,
- int *edge_level,
- int *active_high_low,
- char **name)
+acpi_pci_link_allocate_irq(acpi_handle handle,
+ int index,
+ int *edge_level, int *active_high_low, char **name)
{
- int result = 0;
- struct acpi_device *device = NULL;
- struct acpi_pci_link *link = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_link *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq");
@@ -626,7 +627,7 @@ acpi_pci_link_allocate_irq (
return_VALUE(-1);
}
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
return_VALUE(-1);
@@ -643,20 +644,24 @@ acpi_pci_link_allocate_irq (
up(&acpi_link_lock);
return_VALUE(-1);
}
-
+
if (!link->irq.active) {
up(&acpi_link_lock);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
return_VALUE(-1);
}
- link->refcnt ++;
+ link->refcnt++;
up(&acpi_link_lock);
- if (edge_level) *edge_level = link->irq.edge_level;
- if (active_high_low) *active_high_low = link->irq.active_high_low;
- if (name) *name = acpi_device_bid(link->device);
+ if (edge_level)
+ *edge_level = link->irq.edge_level;
+ if (active_high_low)
+ *active_high_low = link->irq.active_high_low;
+ if (name)
+ *name = acpi_device_bid(link->device);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Link %s is referenced\n", acpi_device_bid(link->device)));
+ "Link %s is referenced\n",
+ acpi_device_bid(link->device)));
return_VALUE(link->irq.active);
}
@@ -664,12 +669,11 @@ acpi_pci_link_allocate_irq (
* We don't change link's irq information here. After it is reenabled, we
* continue use the info
*/
-int
-acpi_pci_link_free_irq(acpi_handle handle)
+int acpi_pci_link_free_irq(acpi_handle handle)
{
- struct acpi_device *device = NULL;
- struct acpi_pci_link *link = NULL;
- acpi_status result;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_link *link = NULL;
+ acpi_status result;
ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq");
@@ -679,7 +683,7 @@ acpi_pci_link_free_irq(acpi_handle handle)
return_VALUE(-1);
}
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
return_VALUE(-1);
@@ -691,7 +695,6 @@ acpi_pci_link_free_irq(acpi_handle handle)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
return_VALUE(-1);
}
-
#ifdef FUTURE_USE
/*
* The Link reference count allows us to _DISable an unused link
@@ -702,10 +705,11 @@ acpi_pci_link_free_irq(acpi_handle handle)
* to prevent duplicate acpi_pci_link_set()
* which would harm some systems
*/
- link->refcnt --;
+ link->refcnt--;
#endif
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Link %s is dereferenced\n", acpi_device_bid(link->device)));
+ "Link %s is dereferenced\n",
+ acpi_device_bid(link->device)));
if (link->refcnt == 0) {
acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
@@ -713,18 +717,17 @@ acpi_pci_link_free_irq(acpi_handle handle)
up(&acpi_link_lock);
return_VALUE(link->irq.active);
}
+
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_pci_link_add (
- struct acpi_device *device)
+static int acpi_pci_link_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_pci_link *link = NULL;
- int i = 0;
- int found = 0;
+ int result = 0;
+ struct acpi_pci_link *link = NULL;
+ int i = 0;
+ int found = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_add");
@@ -751,13 +754,12 @@ acpi_pci_link_add (
acpi_pci_link_get_current(link);
printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
- acpi_device_bid(device));
+ acpi_device_bid(device));
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.active == link->irq.possible[i]) {
printk(" *%d", link->irq.possible[i]);
found = 1;
- }
- else
+ } else
printk(" %d", link->irq.possible[i]);
}
@@ -766,7 +768,7 @@ acpi_pci_link_add (
if (!found)
printk(" *%d", link->irq.active);
- if(!link->device->status.enabled)
+ if (!link->device->status.enabled)
printk(", disabled.");
printk("\n");
@@ -775,7 +777,7 @@ acpi_pci_link_add (
list_add_tail(&link->node, &acpi_link.entries);
acpi_link.count++;
-end:
+ end:
/* disable all links -- to be activated on use */
acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
up(&acpi_link_lock);
@@ -786,9 +788,7 @@ end:
return_VALUE(result);
}
-static int
-acpi_pci_link_resume(
- struct acpi_pci_link *link)
+static int acpi_pci_link_resume(struct acpi_pci_link *link)
{
ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
@@ -803,12 +803,10 @@ acpi_pci_link_resume(
* after every device calls pci_disable_device in .resume.
*/
int acpi_in_resume;
-static int
-irqrouter_resume(
- struct sys_device *dev)
+static int irqrouter_resume(struct sys_device *dev)
{
- struct list_head *node = NULL;
- struct acpi_pci_link *link = NULL;
+ struct list_head *node = NULL;
+ struct acpi_pci_link *link = NULL;
ACPI_FUNCTION_TRACE("irqrouter_resume");
@@ -817,7 +815,7 @@ irqrouter_resume(
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid link context\n"));
+ "Invalid link context\n"));
continue;
}
acpi_pci_link_resume(link);
@@ -826,11 +824,7 @@ irqrouter_resume(
return_VALUE(0);
}
-
-static int
-acpi_pci_link_remove (
- struct acpi_device *device,
- int type)
+static int acpi_pci_link_remove(struct acpi_device *device, int type)
{
struct acpi_pci_link *link = NULL;
@@ -839,7 +833,7 @@ acpi_pci_link_remove (
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
down(&acpi_link_lock);
list_del(&link->node);
@@ -861,14 +855,14 @@ static int __init acpi_irq_penalty_update(char *str, int used)
int retval;
int irq;
- retval = get_option(&str,&irq);
+ retval = get_option(&str, &irq);
if (!retval)
break; /* no number found */
if (irq < 0)
continue;
-
+
if (irq >= ACPI_MAX_IRQS)
continue;
@@ -907,6 +901,7 @@ static int __init acpi_irq_isa(char *str)
{
return acpi_irq_penalty_update(str, 1);
}
+
__setup("acpi_irq_isa=", acpi_irq_isa);
/*
@@ -918,6 +913,7 @@ static int __init acpi_irq_pci(char *str)
{
return acpi_irq_penalty_update(str, 0);
}
+
__setup("acpi_irq_pci=", acpi_irq_pci);
static int __init acpi_irq_nobalance_set(char *str)
@@ -925,6 +921,7 @@ static int __init acpi_irq_nobalance_set(char *str)
acpi_irq_balance = 0;
return 1;
}
+
__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
int __init acpi_irq_balance_set(char *str)
@@ -932,22 +929,20 @@ int __init acpi_irq_balance_set(char *str)
acpi_irq_balance = 1;
return 1;
}
-__setup("acpi_irq_balance", acpi_irq_balance_set);
+__setup("acpi_irq_balance", acpi_irq_balance_set);
/* FIXME: we will remove this interface after all drivers call pci_disable_device */
static struct sysdev_class irqrouter_sysdev_class = {
- set_kset_name("irqrouter"),
- .resume = irqrouter_resume,
+ set_kset_name("irqrouter"),
+ .resume = irqrouter_resume,
};
-
static struct sys_device device_irqrouter = {
- .id = 0,
- .cls = &irqrouter_sysdev_class,
+ .id = 0,
+ .cls = &irqrouter_sysdev_class,
};
-
static int __init irqrouter_init_sysfs(void)
{
int error;
@@ -962,12 +957,11 @@ static int __init irqrouter_init_sysfs(void)
error = sysdev_register(&device_irqrouter);
return_VALUE(error);
-}
+}
device_initcall(irqrouter_init_sysfs);
-
-static int __init acpi_pci_link_init (void)
+static int __init acpi_pci_link_init(void)
{
ACPI_FUNCTION_TRACE("acpi_pci_link_init");
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 5d2f77fcd50c..0fd9988c283d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -35,35 +35,32 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_root")
-
+ACPI_MODULE_NAME("pci_root")
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_HID "PNP0A03"
#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
-
-static int acpi_pci_root_add (struct acpi_device *device);
-static int acpi_pci_root_remove (struct acpi_device *device, int type);
-static int acpi_pci_root_start (struct acpi_device *device);
+static int acpi_pci_root_add(struct acpi_device *device);
+static int acpi_pci_root_remove(struct acpi_device *device, int type);
+static int acpi_pci_root_start(struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = {
- .name = ACPI_PCI_ROOT_DRIVER_NAME,
- .class = ACPI_PCI_ROOT_CLASS,
- .ids = ACPI_PCI_ROOT_HID,
- .ops = {
- .add = acpi_pci_root_add,
- .remove = acpi_pci_root_remove,
- .start = acpi_pci_root_start,
- },
+ .name = ACPI_PCI_ROOT_DRIVER_NAME,
+ .class = ACPI_PCI_ROOT_CLASS,
+ .ids = ACPI_PCI_ROOT_HID,
+ .ops = {
+ .add = acpi_pci_root_add,
+ .remove = acpi_pci_root_remove,
+ .start = acpi_pci_root_start,
+ },
};
struct acpi_pci_root {
- struct list_head node;
- acpi_handle handle;
- struct acpi_pci_id id;
- struct pci_bus *bus;
+ struct list_head node;
+ acpi_handle handle;
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
};
static LIST_HEAD(acpi_pci_roots);
@@ -92,6 +89,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
return n;
}
+
EXPORT_SYMBOL(acpi_pci_register_driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
@@ -115,10 +113,11 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
driver->remove(root->handle);
}
}
+
EXPORT_SYMBOL(acpi_pci_unregister_driver);
static acpi_status
-get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
+get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
int *busnr = (int *)data;
struct acpi_resource_address64 address;
@@ -129,20 +128,21 @@ get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
return AE_OK;
acpi_resource_to_address64(resource, &address);
- if ((address.address_length > 0) &&
- (address.resource_type == ACPI_BUS_NUMBER_RANGE))
+ if ((address.address_length > 0) &&
+ (address.resource_type == ACPI_BUS_NUMBER_RANGE))
*busnr = address.min_address_range;
return AE_OK;
}
-static acpi_status
-try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
+static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
{
acpi_status status;
*busnum = -1;
- status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
+ status =
+ acpi_walk_resources(handle, METHOD_NAME__CRS,
+ get_root_bridge_busnr_callback, busnum);
if (ACPI_FAILURE(status))
return status;
/* Check if we really get a bus number from _CRS */
@@ -151,16 +151,14 @@ try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
return AE_OK;
}
-static int
-acpi_pci_root_add (
- struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_pci_root *root = NULL;
- struct acpi_pci_root *tmp;
- acpi_status status = AE_OK;
- unsigned long value = 0;
- acpi_handle handle = NULL;
+ int result = 0;
+ struct acpi_pci_root *root = NULL;
+ struct acpi_pci_root *tmp;
+ acpi_status status = AE_OK;
+ unsigned long value = 0;
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_add");
@@ -188,15 +186,15 @@ acpi_pci_root_add (
* -------
* Obtained via _SEG, if exists, otherwise assumed to be zero (0).
*/
- status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
- &value);
+ status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
+ &value);
switch (status) {
case AE_OK:
root->id.segment = (u16) value;
break;
case AE_NOT_FOUND:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Assuming segment 0 (no _SEG)\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Assuming segment 0 (no _SEG)\n"));
root->id.segment = 0;
break;
default:
@@ -210,8 +208,8 @@ acpi_pci_root_add (
* ---
* Obtained via _BBN, if exists, otherwise assumed to be zero (0).
*/
- status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
- &value);
+ status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
+ &value);
switch (status) {
case AE_OK:
root->id.bus = (u16) value;
@@ -229,18 +227,19 @@ acpi_pci_root_add (
/* Some systems have wrong _BBN */
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == root->id.segment)
- && (tmp->id.bus == root->id.bus)) {
+ && (tmp->id.bus == root->id.bus)) {
int bus = 0;
acpi_status status;
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
status = try_get_root_bridge_busnr(root->handle, &bus);
if (ACPI_FAILURE(status))
break;
if (bus != root->id.bus) {
- printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
+ printk(KERN_INFO PREFIX
+ "PCI _CRS %d overrides _BBN 0\n", bus);
root->id.bus = bus;
}
break;
@@ -258,12 +257,12 @@ acpi_pci_root_add (
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
- /* TBD: Locking */
- list_add_tail(&root->node, &acpi_pci_roots);
+ /* TBD: Locking */
+ list_add_tail(&root->node, &acpi_pci_roots);
- printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
- acpi_device_name(device), acpi_device_bid(device),
- root->id.segment, root->id.bus);
+ printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ root->id.segment, root->id.bus);
/*
* Scan the Root Bridge
@@ -274,9 +273,9 @@ acpi_pci_root_add (
*/
root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
if (!root->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bus %04x:%02x not present in PCI namespace\n",
- root->id.segment, root->id.bus));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->id.segment, root->id.bus));
result = -ENODEV;
goto end;
}
@@ -298,9 +297,9 @@ acpi_pci_root_add (
status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
result = acpi_pci_irq_add_prt(root->handle, root->id.segment,
- root->id.bus);
+ root->id.bus);
-end:
+ end:
if (result) {
if (!list_empty(&root->node))
list_del(&root->node);
@@ -310,11 +309,9 @@ end:
return_VALUE(result);
}
-static int
-acpi_pci_root_start (
- struct acpi_device *device)
+static int acpi_pci_root_start(struct acpi_device *device)
{
- struct acpi_pci_root *root;
+ struct acpi_pci_root *root;
ACPI_FUNCTION_TRACE("acpi_pci_root_start");
@@ -327,27 +324,23 @@ acpi_pci_root_start (
return_VALUE(-ENODEV);
}
-static int
-acpi_pci_root_remove (
- struct acpi_device *device,
- int type)
+static int acpi_pci_root_remove(struct acpi_device *device, int type)
{
- struct acpi_pci_root *root = NULL;
+ struct acpi_pci_root *root = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- root = (struct acpi_pci_root *) acpi_driver_data(device);
+ root = (struct acpi_pci_root *)acpi_driver_data(device);
kfree(root);
return_VALUE(0);
}
-
-static int __init acpi_pci_root_init (void)
+static int __init acpi_pci_root_init(void)
{
ACPI_FUNCTION_TRACE("acpi_pci_root_init");
@@ -355,8 +348,8 @@ static int __init acpi_pci_root_init (void)
return_VALUE(0);
/* DEBUG:
- acpi_dbg_layer = ACPI_PCI_COMPONENT;
- acpi_dbg_level = 0xFFFFFFFF;
+ acpi_dbg_layer = ACPI_PCI_COMPONENT;
+ acpi_dbg_level = 0xFFFFFFFF;
*/
if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
@@ -366,4 +359,3 @@ static int __init acpi_pci_root_init (void)
}
subsys_initcall(acpi_pci_root_init);
-
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 373a3a95bb4e..62a5595ed8bc 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -44,10 +44,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_POWER_COMPONENT
-ACPI_MODULE_NAME ("acpi_power")
-
+ACPI_MODULE_NAME("acpi_power")
#define ACPI_POWER_COMPONENT 0x00800000
#define ACPI_POWER_CLASS "power_resource"
#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver"
@@ -57,38 +55,36 @@ ACPI_MODULE_NAME ("acpi_power")
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
-
-static int acpi_power_add (struct acpi_device *device);
-static int acpi_power_remove (struct acpi_device *device, int type);
+static int acpi_power_add(struct acpi_device *device);
+static int acpi_power_remove(struct acpi_device *device, int type);
static int acpi_power_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_power_driver = {
- .name = ACPI_POWER_DRIVER_NAME,
- .class = ACPI_POWER_CLASS,
- .ids = ACPI_POWER_HID,
- .ops = {
- .add = acpi_power_add,
- .remove = acpi_power_remove,
- },
+ .name = ACPI_POWER_DRIVER_NAME,
+ .class = ACPI_POWER_CLASS,
+ .ids = ACPI_POWER_HID,
+ .ops = {
+ .add = acpi_power_add,
+ .remove = acpi_power_remove,
+ },
};
-struct acpi_power_resource
-{
- acpi_handle handle;
- acpi_bus_id name;
- u32 system_level;
- u32 order;
- int state;
- int references;
+struct acpi_power_resource {
+ acpi_handle handle;
+ acpi_bus_id name;
+ u32 system_level;
+ u32 order;
+ int state;
+ int references;
};
-static struct list_head acpi_power_resource_list;
+static struct list_head acpi_power_resource_list;
static struct file_operations acpi_power_fops = {
- .open = acpi_power_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
@@ -96,12 +92,11 @@ static struct file_operations acpi_power_fops = {
-------------------------------------------------------------------------- */
static int
-acpi_power_get_context (
- acpi_handle handle,
- struct acpi_power_resource **resource)
+acpi_power_get_context(acpi_handle handle,
+ struct acpi_power_resource **resource)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_power_get_context");
@@ -111,24 +106,21 @@ acpi_power_get_context (
result = acpi_bus_get_device(handle, &device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context [%p]\n",
- handle));
+ handle));
return_VALUE(result);
}
- *resource = (struct acpi_power_resource *) acpi_driver_data(device);
+ *resource = (struct acpi_power_resource *)acpi_driver_data(device);
if (!resource)
return_VALUE(-ENODEV);
return_VALUE(0);
}
-
-static int
-acpi_power_get_state (
- struct acpi_power_resource *resource)
+static int acpi_power_get_state(struct acpi_power_resource *resource)
{
- acpi_status status = AE_OK;
- unsigned long sta = 0;
+ acpi_status status = AE_OK;
+ unsigned long sta = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_state");
@@ -145,20 +137,16 @@ acpi_power_get_state (
resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- resource->name, resource->state?"on":"off"));
+ resource->name, resource->state ? "on" : "off"));
return_VALUE(0);
}
-
-static int
-acpi_power_get_list_state (
- struct acpi_handle_list *list,
- int *state)
+static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
- int result = 0;
+ int result = 0;
struct acpi_power_resource *resource = NULL;
- u32 i = 0;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_list_state");
@@ -167,7 +155,7 @@ acpi_power_get_list_state (
/* The state of the list is 'on' IFF all resources are 'on'. */
- for (i=0; i<list->count; i++) {
+ for (i = 0; i < list->count; i++) {
result = acpi_power_get_context(list->handles[i], &resource);
if (result)
return_VALUE(result);
@@ -182,19 +170,16 @@ acpi_power_get_list_state (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
- *state?"on":"off"));
+ *state ? "on" : "off"));
return_VALUE(result);
}
-
-static int
-acpi_power_on (
- acpi_handle handle)
+static int acpi_power_on(acpi_handle handle)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
struct acpi_power_resource *resource = NULL;
ACPI_FUNCTION_TRACE("acpi_power_on");
@@ -205,10 +190,10 @@ acpi_power_on (
resource->references++;
- if ((resource->references > 1)
- || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
+ if ((resource->references > 1)
+ || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
@@ -229,19 +214,16 @@ acpi_power_on (
device->power.state = ACPI_STATE_D0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
-
-static int
-acpi_power_off_device (
- acpi_handle handle)
+static int acpi_power_off_device(acpi_handle handle)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
struct acpi_power_resource *resource = NULL;
ACPI_FUNCTION_TRACE("acpi_power_off_device");
@@ -254,15 +236,15 @@ acpi_power_off_device (
resource->references--;
if (resource->references) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Resource [%s] is still in use, dereferencing\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Resource [%s] is still in use, dereferencing\n",
+ device->pnp.bus_id));
return_VALUE(0);
}
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
- device->pnp.bus_id));
+ device->pnp.bus_id));
return_VALUE(0);
}
@@ -283,7 +265,7 @@ acpi_power_off_device (
device->power.state = ACPI_STATE_D3;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
@@ -293,13 +275,13 @@ acpi_power_off_device (
* 1. Power on the power resources required for the wakeup device
* 2. Enable _PSW (power state wake) for the device if present
*/
-int acpi_enable_wakeup_device_power (struct acpi_device *dev)
+int acpi_enable_wakeup_device_power(struct acpi_device *dev)
{
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ acpi_status status = AE_OK;
+ int i;
+ int ret = 0;
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
if (!dev || !dev->wakeup.flags.valid)
@@ -310,8 +292,8 @@ int acpi_enable_wakeup_device_power (struct acpi_device *dev)
for (i = 0; i < dev->wakeup.resources.count; i++) {
ret = acpi_power_on(dev->wakeup.resources.handles[i]);
if (ret) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error transition power state\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error transition power state\n"));
dev->wakeup.flags.valid = 0;
return_VALUE(-1);
}
@@ -333,20 +315,20 @@ int acpi_enable_wakeup_device_power (struct acpi_device *dev)
* 1. Disable _PSW (power state wake)
* 2. Shutdown down the power resources
*/
-int acpi_disable_wakeup_device_power (struct acpi_device *dev)
+int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ acpi_status status = AE_OK;
+ int i;
+ int ret = 0;
ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
if (!dev || !dev->wakeup.flags.valid)
return_VALUE(-1);
- arg.integer.value = 0;
+ arg.integer.value = 0;
/* Execute PSW */
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
@@ -359,8 +341,8 @@ int acpi_disable_wakeup_device_power (struct acpi_device *dev)
for (i = 0; i < dev->wakeup.resources.count; i++) {
ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
if (ret) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error transition power state\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error transition power state\n"));
dev->wakeup.flags.valid = 0;
return_VALUE(-1);
}
@@ -373,14 +355,12 @@ int acpi_disable_wakeup_device_power (struct acpi_device *dev)
Device Power Management
-------------------------------------------------------------------------- */
-int
-acpi_power_get_inferred_state (
- struct acpi_device *device)
+int acpi_power_get_inferred_state(struct acpi_device *device)
{
- int result = 0;
- struct acpi_handle_list *list = NULL;
- int list_state = 0;
- int i = 0;
+ int result = 0;
+ struct acpi_handle_list *list = NULL;
+ int list_state = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state");
@@ -393,7 +373,7 @@ acpi_power_get_inferred_state (
* We know a device's inferred power state when all the resources
* required for a given D-state are 'on'.
*/
- for (i=ACPI_STATE_D0; i<ACPI_STATE_D3; i++) {
+ for (i = ACPI_STATE_D0; i < ACPI_STATE_D3; i++) {
list = &device->power.states[i].resources;
if (list->count < 1)
continue;
@@ -413,23 +393,20 @@ acpi_power_get_inferred_state (
return_VALUE(0);
}
-
-int
-acpi_power_transition (
- struct acpi_device *device,
- int state)
+int acpi_power_transition(struct acpi_device *device, int state)
{
- int result = 0;
- struct acpi_handle_list *cl = NULL; /* Current Resources */
- struct acpi_handle_list *tl = NULL; /* Target Resources */
- int i = 0;
+ int result = 0;
+ struct acpi_handle_list *cl = NULL; /* Current Resources */
+ struct acpi_handle_list *tl = NULL; /* Target Resources */
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_power_transition");
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
return_VALUE(-EINVAL);
- if ((device->power.state < ACPI_STATE_D0) || (device->power.state > ACPI_STATE_D3))
+ if ((device->power.state < ACPI_STATE_D0)
+ || (device->power.state > ACPI_STATE_D3))
return_VALUE(-ENODEV);
cl = &device->power.states[device->power.state].resources;
@@ -448,7 +425,7 @@ acpi_power_transition (
* First we reference all power resources required in the target list
* (e.g. so the device doesn't lose power while transitioning).
*/
- for (i=0; i<tl->count; i++) {
+ for (i = 0; i < tl->count; i++) {
result = acpi_power_on(tl->handles[i]);
if (result)
goto end;
@@ -457,7 +434,7 @@ acpi_power_transition (
/*
* Then we dereference all power resources used in the current list.
*/
- for (i=0; i<cl->count; i++) {
+ for (i = 0; i < cl->count; i++) {
result = acpi_power_off_device(cl->handles[i]);
if (result)
goto end;
@@ -465,21 +442,20 @@ acpi_power_transition (
/* We shouldn't change the state till all above operations succeed */
device->power.state = state;
-end:
+ end:
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Error transitioning device [%s] to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Error transitioning device [%s] to D%d\n",
+ device->pnp.bus_id, state));
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
@@ -506,13 +482,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "system level: S%d\n"
- "order: %d\n"
- "reference count: %d\n",
- resource->system_level,
- resource->order,
- resource->references);
+ "order: %d\n"
+ "reference count: %d\n",
+ resource->system_level,
+ resource->order, resource->references);
-end:
+ end:
return_VALUE(0);
}
@@ -521,11 +496,9 @@ static int acpi_power_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_power_seq_show, PDE(inode)->data);
}
-static int
-acpi_power_add_fs (
- struct acpi_device *device)
+static int acpi_power_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_power_add_fs");
@@ -534,18 +507,18 @@ acpi_power_add_fs (
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_power_dir);
+ acpi_power_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
/* 'status' [R] */
entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_POWER_FILE_STATUS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_POWER_FILE_STATUS));
else {
entry->proc_fops = &acpi_power_fops;
entry->data = acpi_driver_data(device);
@@ -554,10 +527,7 @@ acpi_power_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_power_remove_fs (
- struct acpi_device *device)
+static int acpi_power_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
@@ -571,20 +541,17 @@ acpi_power_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_power_add (
- struct acpi_device *device)
+static int acpi_power_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
+ int result = 0;
+ acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
- union acpi_object acpi_object;
- struct acpi_buffer buffer = {sizeof(acpi_object), &acpi_object};
+ union acpi_object acpi_object;
+ struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
ACPI_FUNCTION_TRACE("acpi_power_add");
@@ -630,22 +597,18 @@ acpi_power_add (
result = acpi_power_add_fs(device);
if (result)
goto end;
-
+
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
- acpi_device_bid(device), resource->state?"on":"off");
+ acpi_device_bid(device), resource->state ? "on" : "off");
-end:
+ end:
if (result)
kfree(resource);
-
+
return_VALUE(result);
}
-
-static int
-acpi_power_remove (
- struct acpi_device *device,
- int type)
+static int acpi_power_remove(struct acpi_device *device, int type)
{
struct acpi_power_resource *resource = NULL;
@@ -654,7 +617,7 @@ acpi_power_remove (
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- resource = (struct acpi_power_resource *) acpi_driver_data(device);
+ resource = (struct acpi_power_resource *)acpi_driver_data(device);
acpi_power_remove_fs(device);
@@ -663,10 +626,9 @@ acpi_power_remove (
return_VALUE(0);
}
-
-static int __init acpi_power_init (void)
+static int __init acpi_power_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_power_init");
@@ -689,4 +651,3 @@ static int __init acpi_power_init (void)
}
subsys_initcall(acpi_power_init);
-
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index d56a439ac614..421792562642 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -58,7 +58,6 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
@@ -75,59 +74,53 @@
#define ACPI_STA_PRESENT 0x00000001
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
+ACPI_MODULE_NAME("acpi_processor")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
MODULE_LICENSE("GPL");
-
-static int acpi_processor_add (struct acpi_device *device);
-static int acpi_processor_start (struct acpi_device *device);
-static int acpi_processor_remove (struct acpi_device *device, int type);
+static int acpi_processor_add(struct acpi_device *device);
+static int acpi_processor_start(struct acpi_device *device);
+static int acpi_processor_remove(struct acpi_device *device, int type);
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
-static void acpi_processor_notify ( acpi_handle handle, u32 event, void *data);
+static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
static struct acpi_driver acpi_processor_driver = {
- .name = ACPI_PROCESSOR_DRIVER_NAME,
- .class = ACPI_PROCESSOR_CLASS,
- .ids = ACPI_PROCESSOR_HID,
- .ops = {
- .add = acpi_processor_add,
- .remove = acpi_processor_remove,
- .start = acpi_processor_start,
- },
+ .name = ACPI_PROCESSOR_DRIVER_NAME,
+ .class = ACPI_PROCESSOR_CLASS,
+ .ids = ACPI_PROCESSOR_HID,
+ .ops = {
+ .add = acpi_processor_add,
+ .remove = acpi_processor_remove,
+ .start = acpi_processor_start,
+ },
};
#define INSTALL_NOTIFY_HANDLER 1
#define UNINSTALL_NOTIFY_HANDLER 2
-
static struct file_operations acpi_processor_info_fops = {
- .open = acpi_processor_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
-struct acpi_processor *processors[NR_CPUS];
+struct acpi_processor *processors[NR_CPUS];
struct acpi_processor_errata errata;
-
/* --------------------------------------------------------------------------
Errata Handling
-------------------------------------------------------------------------- */
-static int
-acpi_processor_errata_piix4 (
- struct pci_dev *dev)
+static int acpi_processor_errata_piix4(struct pci_dev *dev)
{
- u8 rev = 0;
- u8 value1 = 0;
- u8 value2 = 0;
+ u8 rev = 0;
+ u8 value1 = 0;
+ u8 value2 = 0;
ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
@@ -188,8 +181,8 @@ acpi_processor_errata_piix4 (
* DMA activity.
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB,
- PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
errata.piix4.bmisx = pci_resource_start(dev, 4);
pci_dev_put(dev);
@@ -205,8 +198,8 @@ acpi_processor_errata_piix4 (
* devices won't operate well if fast DMA is disabled.
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_0,
- PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB_0,
+ PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
pci_read_config_byte(dev, 0x76, &value1);
pci_read_config_byte(dev, 0x77, &value2);
@@ -220,21 +213,18 @@ acpi_processor_errata_piix4 (
if (errata.piix4.bmisx)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Bus master activity detection (BM-IDE) erratum enabled\n"));
+ "Bus master activity detection (BM-IDE) erratum enabled\n"));
if (errata.piix4.fdma)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Type-F DMA livelock erratum (C3 disabled)\n"));
+ "Type-F DMA livelock erratum (C3 disabled)\n"));
return_VALUE(0);
}
-
-int
-acpi_processor_errata (
- struct acpi_processor *pr)
+static int acpi_processor_errata(struct acpi_processor *pr)
{
- int result = 0;
- struct pci_dev *dev = NULL;
+ int result = 0;
+ struct pci_dev *dev = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_errata");
@@ -245,7 +235,8 @@ acpi_processor_errata (
* PIIX4
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
+ PCI_ANY_ID, NULL);
if (dev) {
result = acpi_processor_errata_piix4(dev);
pci_dev_put(dev);
@@ -254,7 +245,6 @@ acpi_processor_errata (
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
Common ACPI processor fucntions
-------------------------------------------------------------------------- */
@@ -265,13 +255,13 @@ acpi_processor_errata (
*/
int acpi_processor_set_pdc(struct acpi_processor *pr,
- struct acpi_object_list *pdc_in)
+ struct acpi_object_list *pdc_in)
{
- acpi_status status = AE_OK;
- u32 arg0_buf[3];
- union acpi_object arg0 = {ACPI_TYPE_BUFFER};
- struct acpi_object_list no_object = {1, &arg0};
- struct acpi_object_list *pdc;
+ acpi_status status = AE_OK;
+ u32 arg0_buf[3];
+ union acpi_object arg0 = { ACPI_TYPE_BUFFER };
+ struct acpi_object_list no_object = { 1, &arg0 };
+ struct acpi_object_list *pdc;
ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
@@ -286,21 +276,21 @@ int acpi_processor_set_pdc(struct acpi_processor *pr,
status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
if ((ACPI_FAILURE(status)) && (pdc_in))
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Error evaluating _PDC, using legacy perf. control...\n"));
return_VALUE(status);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_processor_dir = NULL;
+static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
@@ -308,40 +298,37 @@ static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "processor id: %d\n"
- "acpi id: %d\n"
- "bus mastering control: %s\n"
- "power management: %s\n"
- "throttling control: %s\n"
- "limit interface: %s\n",
- pr->id,
- pr->acpi_id,
- pr->flags.bm_control ? "yes" : "no",
- pr->flags.power ? "yes" : "no",
- pr->flags.throttling ? "yes" : "no",
- pr->flags.limit ? "yes" : "no");
-
-end:
+ "acpi id: %d\n"
+ "bus mastering control: %s\n"
+ "power management: %s\n"
+ "throttling control: %s\n"
+ "limit interface: %s\n",
+ pr->id,
+ pr->acpi_id,
+ pr->flags.bm_control ? "yes" : "no",
+ pr->flags.power ? "yes" : "no",
+ pr->flags.throttling ? "yes" : "no",
+ pr->flags.limit ? "yes" : "no");
+
+ end:
return_VALUE(0);
}
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_info_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-
-static int
-acpi_processor_add_fs (
- struct acpi_device *device)
+static int acpi_processor_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_processor_dir);
+ acpi_processor_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
@@ -349,11 +336,11 @@ acpi_processor_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_INFO));
else {
entry->proc_fops = &acpi_processor_info_fops;
entry->data = acpi_driver_data(device);
@@ -362,11 +349,12 @@ acpi_processor_add_fs (
/* 'throttling' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_THROTTLING));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_THROTTLING));
else {
entry->proc_fops = &acpi_processor_throttling_fops;
entry->proc_fops->write = acpi_processor_write_throttling;
@@ -376,11 +364,12 @@ acpi_processor_add_fs (
/* 'limit' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_LIMIT));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_LIMIT));
else {
entry->proc_fops = &acpi_processor_limit_fops;
entry->proc_fops->write = acpi_processor_write_limit;
@@ -391,18 +380,17 @@ acpi_processor_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_processor_remove_fs (
- struct acpi_device *device)
+static int acpi_processor_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
+ acpi_device_dir(device));
remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
- acpi_device_dir(device));
- remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device));
+ acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
+ acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
acpi_device_dir(device) = NULL;
}
@@ -446,15 +434,13 @@ static u8 convert_acpiid_to_cpu(u8 acpi_id)
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_processor_get_info (
- struct acpi_processor *pr)
+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;
- static int cpu0_initialized;
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ u8 cpu_index;
+ static int cpu0_initialized;
ACPI_FUNCTION_TRACE("acpi_processor_get_info");
@@ -473,11 +459,10 @@ acpi_processor_get_info (
if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
pr->flags.bm_control = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Bus mastering arbitration control present\n"));
- }
- else
+ "Bus mastering arbitration control present\n"));
+ } else
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No bus mastering arbitration control\n"));
+ "No bus mastering arbitration control\n"));
/*
* Evalute the processor object. Note that it is common on SMP to
@@ -487,50 +472,51 @@ acpi_processor_get_info (
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error evaluating processor object\n"));
+ "Error evaluating processor object\n"));
return_VALUE(-ENODEV);
}
/*
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
- * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
*/
pr->acpi_id = object.processor.proc_id;
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) &&
- (num_online_cpus() == 1)) {
- cpu_index = 0;
- }
-
- cpu0_initialized = 1;
-
- pr->id = cpu_index;
-
- /*
- * Extra Processor objects may be enumerated on MP systems with
- * less than the max # of CPUs. They should be ignored _iff
- * they are physically not present.
- */
- if (cpu_index >= NR_CPUS) {
- if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error getting cpuindex for acpiid 0x%x\n",
- pr->acpi_id));
- return_VALUE(-ENODEV);
- }
- }
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == 0xff) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (cpu_index >= NR_CPUS) {
+ if (ACPI_FAILURE
+ (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error getting cpuindex for acpiid 0x%x\n",
+ pr->acpi_id));
+ return_VALUE(-ENODEV);
+ }
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
- pr->acpi_id));
+ pr->acpi_id));
if (!object.processor.pblk_address)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
else if (object.processor.pblk_length != 6)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n",
- object.processor.pblk_length));
+ object.processor.pblk_length));
else {
pr->throttling.address = object.processor.pblk_address;
pr->throttling.duty_offset = acpi_fadt.duty_offset;
@@ -557,13 +543,11 @@ acpi_processor_get_info (
return_VALUE(0);
}
-static int
-acpi_processor_start(
- struct acpi_device *device)
+static int acpi_processor_start(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_processor *pr;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_start");
@@ -584,36 +568,30 @@ acpi_processor_start(
goto end;
status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
- acpi_processor_notify, pr);
+ acpi_processor_notify, pr);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing device notify handler\n"));
+ "Error installing device notify handler\n"));
}
acpi_processor_power_init(pr, device);
if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
- acpi_device_name(device), acpi_device_bid(device));
+ acpi_device_name(device), acpi_device_bid(device));
printk(" %d throttling states", pr->throttling.state_count);
printk(")\n");
}
-end:
+ end:
return_VALUE(result);
}
-
-
-static void
-acpi_processor_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_processor *pr = (struct acpi_processor *) data;
- struct acpi_device *device = NULL;
+ struct acpi_processor *pr = (struct acpi_processor *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_notify");
@@ -627,7 +605,7 @@ acpi_processor_notify (
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
acpi_processor_ppc_has_changed(pr);
acpi_bus_generate_event(device, event,
- pr->performance_platform_limit);
+ pr->performance_platform_limit);
break;
case ACPI_PROCESSOR_NOTIFY_POWER:
acpi_processor_cst_has_changed(pr);
@@ -635,19 +613,16 @@ acpi_processor_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_processor_add (
- struct acpi_device *device)
+static int acpi_processor_add(struct acpi_device *device)
{
- struct acpi_processor *pr = NULL;
+ struct acpi_processor *pr = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_add");
@@ -667,21 +642,17 @@ acpi_processor_add (
return_VALUE(0);
}
-
-static int
-acpi_processor_remove (
- struct acpi_device *device,
- int type)
+static int acpi_processor_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_processor *pr = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_processor *pr = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- pr = (struct acpi_processor *) acpi_driver_data(device);
+ pr = (struct acpi_processor *)acpi_driver_data(device);
if (pr->id >= NR_CPUS) {
kfree(pr);
@@ -696,10 +667,10 @@ acpi_processor_remove (
acpi_processor_power_exit(pr, device);
status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
- acpi_processor_notify);
+ acpi_processor_notify);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
}
acpi_processor_remove_fs(device);
@@ -718,33 +689,28 @@ acpi_processor_remove (
static int is_processor_present(acpi_handle handle);
-static int
-is_processor_present(
- acpi_handle handle)
+static int is_processor_present(acpi_handle handle)
{
- acpi_status status;
- unsigned long sta = 0;
+ acpi_status status;
+ unsigned long sta = 0;
ACPI_FUNCTION_TRACE("is_processor_present");
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Processor Device is not present\n"));
+ "Processor Device is not present\n"));
return_VALUE(0);
}
return_VALUE(1);
}
-
static
-int acpi_processor_device_add(
- acpi_handle handle,
- struct acpi_device **device)
+int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
{
- acpi_handle phandle;
- struct acpi_device *pdev;
- struct acpi_processor *pr;
+ acpi_handle phandle;
+ struct acpi_device *pdev;
+ struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_device_add");
@@ -766,21 +732,17 @@ int acpi_processor_device_add(
if (!pr)
return_VALUE(-ENODEV);
- if ((pr->id >=0) && (pr->id < NR_CPUS)) {
+ if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
}
return_VALUE(0);
}
-
static void
-acpi_processor_hotplug_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_processor *pr;
- struct acpi_device *device = NULL;
+ struct acpi_processor *pr;
+ struct acpi_device *device = NULL;
int result;
ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
@@ -789,8 +751,8 @@ acpi_processor_hotplug_notify (
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
printk("Processor driver received %s event\n",
- (event==ACPI_NOTIFY_BUS_CHECK)?
- "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ (event == ACPI_NOTIFY_BUS_CHECK) ?
+ "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
if (!is_processor_present(handle))
break;
@@ -799,14 +761,14 @@ acpi_processor_hotplug_notify (
result = acpi_processor_device_add(handle, &device);
if (result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to add the device\n"));
+ "Unable to add the device\n"));
break;
}
pr = acpi_driver_data(device);
if (!pr) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Driver data is NULL\n"));
+ "Driver data is NULL\n"));
break;
}
@@ -816,24 +778,27 @@ acpi_processor_hotplug_notify (
}
result = acpi_processor_start(device);
- if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) {
+ if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
kobject_hotplug(&device->kobj, KOBJ_ONLINE);
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device [%s] failed to start\n",
- acpi_device_bid(device)));
+ "Device [%s] failed to start\n",
+ acpi_device_bid(device)));
}
- break;
+ break;
case ACPI_NOTIFY_EJECT_REQUEST:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "received ACPI_NOTIFY_EJECT_REQUEST\n"));
if (acpi_bus_get_device(handle, &device)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device don't exist, dropping EJECT\n"));
break;
}
pr = acpi_driver_data(device);
if (!pr) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Driver data is NULL, dropping EJECT\n"));
return_VOID;
}
@@ -842,7 +807,7 @@ acpi_processor_hotplug_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
@@ -851,45 +816,39 @@ acpi_processor_hotplug_notify (
static acpi_status
processor_walk_namespace_cb(acpi_handle handle,
- u32 lvl,
- void *context,
- void **rv)
+ u32 lvl, void *context, void **rv)
{
- acpi_status status;
+ acpi_status status;
int *action = context;
- acpi_object_type type = 0;
+ acpi_object_type type = 0;
status = acpi_get_type(handle, &type);
if (ACPI_FAILURE(status))
- return(AE_OK);
+ return (AE_OK);
if (type != ACPI_TYPE_PROCESSOR)
- return(AE_OK);
+ return (AE_OK);
- switch(*action) {
+ switch (*action) {
case INSTALL_NOTIFY_HANDLER:
acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- acpi_processor_hotplug_notify,
- NULL);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_processor_hotplug_notify,
+ NULL);
break;
case UNINSTALL_NOTIFY_HANDLER:
acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- acpi_processor_hotplug_notify);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_processor_hotplug_notify);
break;
default:
break;
}
- return(AE_OK);
+ return (AE_OK);
}
-
-static acpi_status
-acpi_processor_hotadd_init(
- acpi_handle handle,
- int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
{
ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
@@ -908,57 +867,47 @@ acpi_processor_hotadd_init(
return_VALUE(AE_OK);
}
-
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
{
if (cpu_online(pr->id)) {
- return(-EINVAL);
+ return (-EINVAL);
}
arch_unregister_cpu(pr->id);
acpi_unmap_lsapic(pr->id);
- return(0);
+ return (0);
}
#else
-static acpi_status
-acpi_processor_hotadd_init(
- acpi_handle handle,
- int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
{
return AE_ERROR;
}
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
{
- return(-EINVAL);
+ return (-EINVAL);
}
#endif
-
static
void acpi_processor_install_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = INSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- processor_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ processor_walk_namespace_cb, &action, NULL);
#endif
}
-
static
void acpi_processor_uninstall_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = UNINSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- processor_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ processor_walk_namespace_cb, &action, NULL);
#endif
}
@@ -968,10 +917,9 @@ void acpi_processor_uninstall_hotplug_notify(void)
* ACPI, but needs symbols from this driver
*/
-static int __init
-acpi_processor_init (void)
+static int __init acpi_processor_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_init");
@@ -998,9 +946,7 @@ acpi_processor_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_processor_exit (void)
+static void __exit acpi_processor_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_processor_exit");
@@ -1017,7 +963,6 @@ acpi_processor_exit (void)
return_VOID;
}
-
module_init(acpi_processor_init);
module_exit(acpi_processor_exit);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2c04740c6543..26a3a4016115 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -48,15 +48,12 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
#define ACPI_PROCESSOR_FILE_POWER "power"
-
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
-
-static void (*pm_idle_save)(void);
+static void (*pm_idle_save) (void);
module_param(max_cstate, uint, 0644);
static unsigned int nocst = 0;
@@ -69,7 +66,8 @@ module_param(nocst, uint, 0000);
* 100 HZ: 0x0000000F: 4 jiffies = 40ms
* reduce history for more aggressive entry into C3
*/
-static unsigned int bm_history = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
+static unsigned int bm_history =
+ (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
module_param(bm_history, uint, 0644);
/* --------------------------------------------------------------------------
Power Management
@@ -87,34 +85,36 @@ static int set_max_cstate(struct dmi_system_id *id)
return 0;
printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate."
- " Override with \"processor.max_cstate=%d\"\n", id->ident,
- (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
+ " Override with \"processor.max_cstate=%d\"\n", id->ident,
+ (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
max_cstate = (long)id->driver_data;
return 0;
}
-
static struct dmi_system_id __initdata processor_power_dmi_table[] = {
- { set_max_cstate, "IBM ThinkPad R40e", {
- DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
- DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
- { set_max_cstate, "Medion 41700", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1},
- { set_max_cstate, "Clevo 5600D", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") },
- (void*)2},
+ {set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "1SET60WW")},
+ (void *)1},
+ {set_max_cstate, "Medion 41700", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "R01-A1J")}, (void *)1},
+ {set_max_cstate, "Clevo 5600D", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "SHE845M0.86C.0013.D.0302131307")},
+ (void *)2},
{},
};
-
-static inline u32
-ticks_elapsed (
- u32 t1,
- u32 t2)
+static inline u32 ticks_elapsed(u32 t1, u32 t2)
{
if (t2 >= t1)
return (t2 - t1);
@@ -124,13 +124,11 @@ ticks_elapsed (
return ((0xFFFFFFFF - t1) + t2);
}
-
static void
-acpi_processor_power_activate (
- struct acpi_processor *pr,
- struct acpi_processor_cx *new)
+acpi_processor_power_activate(struct acpi_processor *pr,
+ struct acpi_processor_cx *new)
{
- struct acpi_processor_cx *old;
+ struct acpi_processor_cx *old;
if (!pr || !new)
return;
@@ -139,7 +137,7 @@ acpi_processor_power_activate (
if (old)
old->promotion.count = 0;
- new->demotion.count = 0;
+ new->demotion.count = 0;
/* Cleanup from old state. */
if (old) {
@@ -147,7 +145,8 @@ acpi_processor_power_activate (
case ACPI_STATE_C3:
/* Disable bus master reload */
if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
- acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
+ ACPI_MTX_DO_NOT_LOCK);
break;
}
}
@@ -157,7 +156,8 @@ acpi_processor_power_activate (
case ACPI_STATE_C3:
/* Enable bus master reload */
if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
- acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1,
+ ACPI_MTX_DO_NOT_LOCK);
break;
}
@@ -166,17 +166,15 @@ acpi_processor_power_activate (
return;
}
+static atomic_t c3_cpu_count;
-static atomic_t c3_cpu_count;
-
-
-static void acpi_processor_idle (void)
+static void acpi_processor_idle(void)
{
- struct acpi_processor *pr = NULL;
+ struct acpi_processor *pr = NULL;
struct acpi_processor_cx *cx = NULL;
struct acpi_processor_cx *next_state = NULL;
- int sleep_ticks = 0;
- u32 t1, t2 = 0;
+ int sleep_ticks = 0;
+ u32 t1, t2 = 0;
pr = processors[raw_smp_processor_id()];
if (!pr)
@@ -208,8 +206,8 @@ static void acpi_processor_idle (void)
* for demotion.
*/
if (pr->flags.bm_check) {
- u32 bm_status = 0;
- unsigned long diff = jiffies - pr->power.bm_check_timestamp;
+ u32 bm_status = 0;
+ unsigned long diff = jiffies - pr->power.bm_check_timestamp;
if (diff > 32)
diff = 32;
@@ -223,11 +221,11 @@ static void acpi_processor_idle (void)
}
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
- &bm_status, ACPI_MTX_DO_NOT_LOCK);
+ &bm_status, ACPI_MTX_DO_NOT_LOCK);
if (bm_status) {
pr->power.bm_activity++;
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ 1, ACPI_MTX_DO_NOT_LOCK);
}
/*
* PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
@@ -236,7 +234,7 @@ static void acpi_processor_idle (void)
*/
else if (errata.piix4.bmisx) {
if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
- || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+ || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
pr->power.bm_activity++;
}
@@ -281,7 +279,7 @@ static void acpi_processor_idle (void)
else
safe_halt();
/*
- * TBD: Can't get time duration while in C1, as resumes
+ * TBD: Can't get time duration while in C1, as resumes
* go to an ISR rather than here. Need to instrument
* base interrupt handler.
*/
@@ -300,26 +298,27 @@ static void acpi_processor_idle (void)
/* Re-enable interrupts */
local_irq_enable();
/* Compute time (ticks) that we were actually asleep */
- sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+ sleep_ticks =
+ ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
break;
case ACPI_STATE_C3:
-
+
if (pr->flags.bm_check) {
if (atomic_inc_return(&c3_cpu_count) ==
- num_online_cpus()) {
+ num_online_cpus()) {
/*
* All CPUs are trying to go to C3
* Disable bus master arbitration
*/
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
- ACPI_MTX_DO_NOT_LOCK);
+ ACPI_MTX_DO_NOT_LOCK);
}
} else {
/* SMP with no shared cache... Invalidate cache */
ACPI_FLUSH_CPU_CACHE();
}
-
+
/* Get start time (ticks) */
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
/* Invoke C3 */
@@ -331,13 +330,15 @@ static void acpi_processor_idle (void)
if (pr->flags.bm_check) {
/* Enable bus master arbitration */
atomic_dec(&c3_cpu_count);
- acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
+ ACPI_MTX_DO_NOT_LOCK);
}
/* Re-enable interrupts */
local_irq_enable();
/* Compute time (ticks) that we were actually asleep */
- sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+ sleep_ticks =
+ ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
break;
default:
@@ -359,15 +360,18 @@ static void acpi_processor_idle (void)
((cx->promotion.state - pr->power.states) <= max_cstate)) {
if (sleep_ticks > cx->promotion.threshold.ticks) {
cx->promotion.count++;
- cx->demotion.count = 0;
- if (cx->promotion.count >= cx->promotion.threshold.count) {
+ cx->demotion.count = 0;
+ if (cx->promotion.count >=
+ cx->promotion.threshold.count) {
if (pr->flags.bm_check) {
- if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) {
- next_state = cx->promotion.state;
+ if (!
+ (pr->power.bm_activity & cx->
+ promotion.threshold.bm)) {
+ next_state =
+ cx->promotion.state;
goto end;
}
- }
- else {
+ } else {
next_state = cx->promotion.state;
goto end;
}
@@ -392,7 +396,7 @@ static void acpi_processor_idle (void)
}
}
-end:
+ end:
/*
* Demote if current state exceeds max_cstate
*/
@@ -412,7 +416,7 @@ end:
return;
- easy_out:
+ easy_out:
/* do C1 instead of busy loop */
if (pm_idle_save)
pm_idle_save();
@@ -421,10 +425,7 @@ end:
return;
}
-
-static int
-acpi_processor_set_power_policy (
- struct acpi_processor *pr)
+static int acpi_processor_set_power_policy(struct acpi_processor *pr)
{
unsigned int i;
unsigned int state_is_set = 0;
@@ -432,7 +433,7 @@ acpi_processor_set_power_policy (
struct acpi_processor_cx *higher = NULL;
struct acpi_processor_cx *cx;
- ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy");
+ ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy");
if (!pr)
return_VALUE(-EINVAL);
@@ -447,7 +448,7 @@ acpi_processor_set_power_policy (
*/
/* startup state */
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
cx = &pr->power.states[i];
if (!cx->valid)
continue;
@@ -456,13 +457,13 @@ acpi_processor_set_power_policy (
pr->power.state = cx;
state_is_set++;
break;
- }
+ }
if (!state_is_set)
return_VALUE(-ENODEV);
/* demotion */
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
cx = &pr->power.states[i];
if (!cx->valid)
continue;
@@ -485,7 +486,7 @@ acpi_processor_set_power_policy (
continue;
if (higher) {
- cx->promotion.state = higher;
+ cx->promotion.state = higher;
cx->promotion.threshold.ticks = cx->latency_ticks;
if (cx->type >= ACPI_STATE_C2)
cx->promotion.threshold.count = 4;
@@ -498,11 +499,10 @@ acpi_processor_set_power_policy (
higher = cx;
}
- return_VALUE(0);
+ return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
{
int i;
@@ -543,15 +543,14 @@ static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr)
return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
{
int i;
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
+ memset(&(pr->power.states[i]), 0,
sizeof(struct acpi_processor_cx));
/* if info is obtained from pblk/fadt, type equals state */
@@ -567,14 +566,13 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
{
- acpi_status status = 0;
- acpi_integer count;
- int i;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *cst;
+ acpi_status status = 0;
+ acpi_integer count;
+ int i;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *cst;
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst");
@@ -583,20 +581,21 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
pr->power.count = 0;
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
+ memset(&(pr->power.states[i]), 0,
sizeof(struct acpi_processor_cx));
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n"));
return_VALUE(-ENODEV);
- }
+ }
- cst = (union acpi_object *) buffer.pointer;
+ cst = (union acpi_object *)buffer.pointer;
/* There must be at least 2 elements */
if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "not enough elements in _CST\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "not enough elements in _CST\n"));
status = -EFAULT;
goto end;
}
@@ -605,15 +604,19 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
/* Validate number of power states. */
if (count < 1 || count != cst->package.count - 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "count given by _CST is not valid\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "count given by _CST is not valid\n"));
status = -EFAULT;
goto end;
}
/* We support up to ACPI_PROCESSOR_MAX_POWER. */
if (count > ACPI_PROCESSOR_MAX_POWER) {
- printk(KERN_WARNING "Limiting number of power states to max (%d)\n", ACPI_PROCESSOR_MAX_POWER);
- printk(KERN_WARNING "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
+ printk(KERN_WARNING
+ "Limiting number of power states to max (%d)\n",
+ ACPI_PROCESSOR_MAX_POWER);
+ printk(KERN_WARNING
+ "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
count = ACPI_PROCESSOR_MAX_POWER;
}
@@ -628,29 +631,29 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
memset(&cx, 0, sizeof(cx));
- element = (union acpi_object *) &(cst->package.elements[i]);
+ element = (union acpi_object *)&(cst->package.elements[i]);
if (element->type != ACPI_TYPE_PACKAGE)
continue;
if (element->package.count != 4)
continue;
- obj = (union acpi_object *) &(element->package.elements[0]);
+ obj = (union acpi_object *)&(element->package.elements[0]);
if (obj->type != ACPI_TYPE_BUFFER)
continue;
- reg = (struct acpi_power_register *) obj->buffer.pointer;
+ reg = (struct acpi_power_register *)obj->buffer.pointer;
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
- (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
+ (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
continue;
cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
- 0 : reg->address;
+ 0 : reg->address;
/* There should be an easy way to extract an integer... */
- obj = (union acpi_object *) &(element->package.elements[1]);
+ obj = (union acpi_object *)&(element->package.elements[1]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -660,17 +663,16 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
continue;
- if ((cx.type < ACPI_STATE_C1) ||
- (cx.type > ACPI_STATE_C3))
+ if ((cx.type < ACPI_STATE_C1) || (cx.type > ACPI_STATE_C3))
continue;
- obj = (union acpi_object *) &(element->package.elements[2]);
+ obj = (union acpi_object *)&(element->package.elements[2]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
cx.latency = obj->integer.value;
- obj = (union acpi_object *) &(element->package.elements[3]);
+ obj = (union acpi_object *)&(element->package.elements[3]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -680,19 +682,19 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", pr->power.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
+ pr->power.count));
/* Validate number of power states discovered */
if (pr->power.count < 2)
status = -ENODEV;
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(status);
}
-
static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c2");
@@ -706,8 +708,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
*/
else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "latency too large [%d]\n",
- cx->latency));
+ "latency too large [%d]\n", cx->latency));
return_VOID;
}
@@ -721,10 +722,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
return_VOID;
}
-
-static void acpi_processor_power_verify_c3(
- struct acpi_processor *pr,
- struct acpi_processor_cx *cx)
+static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
+ struct acpi_processor_cx *cx)
{
static int bm_check_flag;
@@ -739,8 +738,7 @@ static void acpi_processor_power_verify_c3(
*/
else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "latency too large [%d]\n",
- cx->latency));
+ "latency too large [%d]\n", cx->latency));
return_VOID;
}
@@ -753,7 +751,7 @@ static void acpi_processor_power_verify_c3(
*/
else if (errata.piix4.fdma) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "C3 not supported on PIIX4 with Type-F DMA\n"));
+ "C3 not supported on PIIX4 with Type-F DMA\n"));
return_VOID;
}
@@ -770,7 +768,7 @@ static void acpi_processor_power_verify_c3(
/* bus mastering control is necessary */
if (!pr->flags.bm_control) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "C3 support requires bus mastering control\n"));
+ "C3 support requires bus mastering control\n"));
return_VOID;
}
} else {
@@ -780,12 +778,12 @@ static void acpi_processor_power_verify_c3(
*/
if (acpi_fadt.wb_invd != 1) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Cache invalidation should work properly"
- " for C3 to be enabled on SMP systems\n"));
+ "Cache invalidation should work properly"
+ " for C3 to be enabled on SMP systems\n"));
return_VOID;
}
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD,
- 0, ACPI_MTX_DO_NOT_LOCK);
+ 0, ACPI_MTX_DO_NOT_LOCK);
}
/*
@@ -800,13 +798,12 @@ static void acpi_processor_power_verify_c3(
return_VOID;
}
-
static int acpi_processor_power_verify(struct acpi_processor *pr)
{
unsigned int i;
unsigned int working = 0;
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
struct acpi_processor_cx *cx = &pr->power.states[i];
switch (cx->type) {
@@ -830,8 +827,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
return (working);
}
-static int acpi_processor_get_power_info (
- struct acpi_processor *pr)
+static int acpi_processor_get_power_info(struct acpi_processor *pr)
{
unsigned int i;
int result;
@@ -874,16 +870,16 @@ static int acpi_processor_get_power_info (
return_VALUE(0);
}
-int acpi_processor_cst_has_changed (struct acpi_processor *pr)
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_cst_has_changed");
if (!pr)
- return_VALUE(-EINVAL);
+ return_VALUE(-EINVAL);
- if ( nocst) {
+ if (nocst) {
return_VALUE(-ENODEV);
}
@@ -892,7 +888,7 @@ int acpi_processor_cst_has_changed (struct acpi_processor *pr)
/* Fall back to the default idle loop */
pm_idle = pm_idle_save;
- synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
+ synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
pr->flags.power = 0;
result = acpi_processor_get_power_info(pr);
@@ -906,8 +902,8 @@ int acpi_processor_cst_has_changed (struct acpi_processor *pr)
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- unsigned int i;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ unsigned int i;
ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show");
@@ -915,17 +911,17 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "active state: C%zd\n"
- "max_cstate: C%d\n"
- "bus master activity: %08x\n",
- pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate,
- (unsigned)pr->power.bm_activity);
+ "max_cstate: C%d\n"
+ "bus master activity: %08x\n",
+ pr->power.state ? pr->power.state - pr->power.states : 0,
+ max_cstate, (unsigned)pr->power.bm_activity);
seq_puts(seq, "states:\n");
for (i = 1; i <= pr->power.count; i++) {
seq_printf(seq, " %cC%d: ",
- (&pr->power.states[i] == pr->power.state?'*':' '), i);
+ (&pr->power.states[i] ==
+ pr->power.state ? '*' : ' '), i);
if (!pr->power.states[i].valid) {
seq_puts(seq, "<not supported>\n");
@@ -949,45 +945,46 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
if (pr->power.states[i].promotion.state)
seq_printf(seq, "promotion[C%zd] ",
- (pr->power.states[i].promotion.state -
- pr->power.states));
+ (pr->power.states[i].promotion.state -
+ pr->power.states));
else
seq_puts(seq, "promotion[--] ");
if (pr->power.states[i].demotion.state)
seq_printf(seq, "demotion[C%zd] ",
- (pr->power.states[i].demotion.state -
- pr->power.states));
+ (pr->power.states[i].demotion.state -
+ pr->power.states));
else
seq_puts(seq, "demotion[--] ");
seq_printf(seq, "latency[%03d] usage[%08d]\n",
- pr->power.states[i].latency,
- pr->power.states[i].usage);
+ pr->power.states[i].latency,
+ pr->power.states[i].usage);
}
-end:
+ end:
return_VALUE(0);
}
static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_power_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static struct file_operations acpi_processor_power_fops = {
- .open = acpi_processor_power_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device)
+int acpi_processor_power_init(struct acpi_processor *pr,
+ struct acpi_device *device)
{
- acpi_status status = 0;
- static int first_run = 0;
- struct proc_dir_entry *entry = NULL;
+ acpi_status status = 0;
+ static int first_run = 0;
+ struct proc_dir_entry *entry = NULL;
unsigned int i;
ACPI_FUNCTION_TRACE("acpi_processor_power_init");
@@ -995,7 +992,9 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
if (!first_run) {
dmi_check_system(processor_power_dmi_table);
if (max_cstate < ACPI_C_STATES_MAX)
- printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate);
+ printk(KERN_NOTICE
+ "ACPI: processor limited to max C-state %d\n",
+ max_cstate);
first_run++;
}
@@ -1003,7 +1002,8 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
return_VALUE(-EINVAL);
if (acpi_fadt.cst_cnt && !nocst) {
- status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
+ status =
+ acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Notifying BIOS of _CST ability failed\n"));
@@ -1023,7 +1023,8 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
for (i = 1; i <= pr->power.count; i++)
if (pr->power.states[i].valid)
- printk(" C%d[C%d]", i, pr->power.states[i].type);
+ printk(" C%d[C%d]", i,
+ pr->power.states[i].type);
printk(")\n");
if (pr->id == 0) {
@@ -1034,11 +1035,11 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
/* 'power' [R] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_POWER));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_POWER));
else {
entry->proc_fops = &acpi_processor_power_fops;
entry->data = acpi_driver_data(device);
@@ -1050,14 +1051,16 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
return_VALUE(0);
}
-int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device)
+int acpi_processor_power_exit(struct acpi_processor *pr,
+ struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_processor_power_exit");
pr->flags.power_setup_done = 0;
if (acpi_device_dir(device))
- remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
+ acpi_device_dir(device));
/* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0) {
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 1f0d6256302f..22c7bb66c200 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -26,7 +26,6 @@
*
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -42,14 +41,12 @@
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
-
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
static DECLARE_MUTEX(performance_sem);
@@ -69,8 +66,7 @@ static DECLARE_MUTEX(performance_sem);
static int acpi_processor_ppc_status = 0;
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
- unsigned long event,
- void *data)
+ unsigned long event, void *data)
{
struct cpufreq_policy *policy = data;
struct acpi_processor *pr;
@@ -85,7 +81,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
if (!pr || !pr->performance)
goto out;
- ppc = (unsigned int) pr->performance_platform_limit;
+ ppc = (unsigned int)pr->performance_platform_limit;
if (!ppc)
goto out;
@@ -93,26 +89,23 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
goto out;
cpufreq_verify_within_limits(policy, 0,
- pr->performance->states[ppc].core_frequency * 1000);
+ pr->performance->states[ppc].
+ core_frequency * 1000);
- out:
+ out:
up(&performance_sem);
return 0;
}
-
static struct notifier_block acpi_ppc_notifier_block = {
.notifier_call = acpi_processor_ppc_notifier,
};
-
-static int
-acpi_processor_get_platform_limit (
- struct acpi_processor* pr)
+static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
- acpi_status status = 0;
- unsigned long ppc = 0;
+ acpi_status status = 0;
+ unsigned long ppc = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
@@ -128,19 +121,17 @@ acpi_processor_get_platform_limit (
if (status != AE_NOT_FOUND)
acpi_processor_ppc_status |= PPC_IN_USE;
- if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
return_VALUE(-ENODEV);
}
- pr->performance_platform_limit = (int) ppc;
+ pr->performance_platform_limit = (int)ppc;
return_VALUE(0);
}
-
-int acpi_processor_ppc_has_changed(
- struct acpi_processor *pr)
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
{
int ret = acpi_processor_get_platform_limit(pr);
if (ret < 0)
@@ -149,44 +140,44 @@ int acpi_processor_ppc_has_changed(
return cpufreq_update_policy(pr->id);
}
-
-void acpi_processor_ppc_init(void) {
- if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
+void acpi_processor_ppc_init(void)
+{
+ if (!cpufreq_register_notifier
+ (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
acpi_processor_ppc_status |= PPC_REGISTERED;
else
- printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
+ printk(KERN_DEBUG
+ "Warning: Processor Platform Limit not supported.\n");
}
-
-void acpi_processor_ppc_exit(void) {
+void acpi_processor_ppc_exit(void)
+{
if (acpi_processor_ppc_status & PPC_REGISTERED)
- cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
acpi_processor_ppc_status &= ~PPC_REGISTERED;
}
-
-static int
-acpi_processor_get_performance_control (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_control(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *pct = NULL;
- union acpi_object obj = {0};
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *pct = NULL;
+ union acpi_object obj = { 0 };
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
- if(ACPI_FAILURE(status)) {
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
return_VALUE(-ENODEV);
}
- pct = (union acpi_object *) buffer.pointer;
+ pct = (union acpi_object *)buffer.pointer;
if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
- || (pct->package.count != 2)) {
+ || (pct->package.count != 2)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
result = -EFAULT;
goto end;
@@ -199,15 +190,15 @@ acpi_processor_get_performance_control (
obj = pct->package.elements[0];
if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ || (obj.buffer.length < sizeof(struct acpi_pct_register))
+ || (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid _PCT data (control_register)\n"));
+ "Invalid _PCT data (control_register)\n"));
result = -EFAULT;
goto end;
}
- memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
-
+ memcpy(&pr->performance->control_register, obj.buffer.pointer,
+ sizeof(struct acpi_pct_register));
/*
* status_register
@@ -216,44 +207,42 @@ acpi_processor_get_performance_control (
obj = pct->package.elements[1];
if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ || (obj.buffer.length < sizeof(struct acpi_pct_register))
+ || (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid _PCT data (status_register)\n"));
+ "Invalid _PCT data (status_register)\n"));
result = -EFAULT;
goto end;
}
- memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
+ memcpy(&pr->performance->status_register, obj.buffer.pointer,
+ sizeof(struct acpi_pct_register));
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(result);
}
-
-static int
-acpi_processor_get_performance_states (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_states(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"};
- struct acpi_buffer state = {0, NULL};
- union acpi_object *pss = NULL;
- int i;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
+ struct acpi_buffer state = { 0, NULL };
+ union acpi_object *pss = NULL;
+ int i;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
- if(ACPI_FAILURE(status)) {
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
return_VALUE(-ENODEV);
}
- pss = (union acpi_object *) buffer.pointer;
+ pss = (union acpi_object *)buffer.pointer;
if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
result = -EFAULT;
@@ -261,10 +250,12 @@ acpi_processor_get_performance_states (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
- pss->package.count));
+ pss->package.count));
pr->performance->state_count = pss->package.count;
- pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
+ pr->performance->states =
+ kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
+ GFP_KERNEL);
if (!pr->performance->states) {
result = -ENOMEM;
goto end;
@@ -280,46 +271,44 @@ acpi_processor_get_performance_states (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
status = acpi_extract_package(&(pss->package.elements[i]),
- &format, &state);
+ &format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _PSS data\n"));
result = -EFAULT;
kfree(pr->performance->states);
goto end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
- i,
- (u32) px->core_frequency,
- (u32) px->power,
- (u32) px->transition_latency,
- (u32) px->bus_master_latency,
- (u32) px->control,
- (u32) px->status));
+ "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
+ i,
+ (u32) px->core_frequency,
+ (u32) px->power,
+ (u32) px->transition_latency,
+ (u32) px->bus_master_latency,
+ (u32) px->control, (u32) px->status));
if (!px->core_frequency) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _PSS data: freq is zero\n"));
result = -EFAULT;
kfree(pr->performance->states);
goto end;
}
}
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(result);
}
-
-static int
-acpi_processor_get_performance_info (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_info(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = AE_OK;
- acpi_handle handle = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
@@ -331,7 +320,7 @@ acpi_processor_get_performance_info (
status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "ACPI-based processor performance control unavailable\n"));
+ "ACPI-based processor performance control unavailable\n"));
return_VALUE(-ENODEV);
}
@@ -350,10 +339,10 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
-
-int acpi_processor_notify_smm(struct module *calling_module) {
- acpi_status status;
- static int is_done = 0;
+int acpi_processor_notify_smm(struct module *calling_module)
+{
+ acpi_status status;
+ static int is_done = 0;
ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
@@ -371,8 +360,7 @@ int acpi_processor_notify_smm(struct module *calling_module) {
if (is_done > 0) {
module_put(calling_module);
return_VALUE(0);
- }
- else if (is_done < 0) {
+ } else if (is_done < 0) {
module_put(calling_module);
return_VALUE(is_done);
}
@@ -380,28 +368,30 @@ int acpi_processor_notify_smm(struct module *calling_module) {
is_done = -EIO;
/* Can't write pstate_cnt to smi_cmd if either value is zero */
- if ((!acpi_fadt.smi_cmd) ||
- (!acpi_fadt.pstate_cnt)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No SMI port or pstate_cnt\n"));
+ if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_cnt\n"));
module_put(calling_module);
return_VALUE(0);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n",
+ acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
* it anyway, so we need to support it... */
if (acpi_fadt_is_v1) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Using v1.0 FADT reserved value for pstate_cnt\n"));
}
- status = acpi_os_write_port (acpi_fadt.smi_cmd,
- (u32) acpi_fadt.pstate_cnt, 8);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_write_port(acpi_fadt.smi_cmd,
+ (u32) acpi_fadt.pstate_cnt, 8);
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Failed to write pstate_cnt [0x%x] to "
- "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
+ "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt,
+ acpi_fadt.smi_cmd));
module_put(calling_module);
return_VALUE(status);
}
@@ -415,24 +405,24 @@ int acpi_processor_notify_smm(struct module *calling_module) {
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_processor_notify_smm);
+EXPORT_SYMBOL(acpi_processor_notify_smm);
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_processor_perf_fops = {
- .open = acpi_processor_perf_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_perf_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- int i;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ int i;
ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
@@ -445,42 +435,40 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "state count: %d\n"
- "active state: P%d\n",
- pr->performance->state_count,
- pr->performance->state);
+ "active state: P%d\n",
+ pr->performance->state_count, pr->performance->state);
seq_puts(seq, "states:\n");
for (i = 0; i < pr->performance->state_count; i++)
- seq_printf(seq, " %cP%d: %d MHz, %d mW, %d uS\n",
- (i == pr->performance->state?'*':' '), i,
- (u32) pr->performance->states[i].core_frequency,
- (u32) pr->performance->states[i].power,
- (u32) pr->performance->states[i].transition_latency);
-
-end:
+ seq_printf(seq,
+ " %cP%d: %d MHz, %d mW, %d uS\n",
+ (i == pr->performance->state ? '*' : ' '), i,
+ (u32) pr->performance->states[i].core_frequency,
+ (u32) pr->performance->states[i].power,
+ (u32) pr->performance->states[i].transition_latency);
+
+ end:
return_VALUE(0);
}
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_perf_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_processor_write_performance (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_processor_write_performance(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *) m->private;
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
struct acpi_processor_performance *perf;
- char state_string[12] = {'\0'};
- unsigned int new_state = 0;
- struct cpufreq_policy policy;
+ char state_string[12] = { '\0' };
+ unsigned int new_state = 0;
+ struct cpufreq_policy policy;
ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
@@ -513,12 +501,10 @@ acpi_processor_write_performance (
return_VALUE(count);
}
-static void
-acpi_cpufreq_add_file (
- struct acpi_processor *pr)
+static void acpi_cpufreq_add_file(struct acpi_processor *pr)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_device *device = NULL;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
@@ -527,11 +513,12 @@ acpi_cpufreq_add_file (
/* add file 'performance' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_PERFORMANCE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_PERFORMANCE));
else {
entry->proc_fops = &acpi_processor_perf_fops;
entry->proc_fops->write = acpi_processor_write_performance;
@@ -541,11 +528,9 @@ acpi_cpufreq_add_file (
return_VOID;
}
-static void
-acpi_cpufreq_remove_file (
- struct acpi_processor *pr)
+static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
@@ -554,21 +539,25 @@ acpi_cpufreq_remove_file (
/* remove file 'performance' */
remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- acpi_device_dir(device));
+ acpi_device_dir(device));
return_VOID;
}
#else
-static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
-static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
-#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
-
+static void acpi_cpufreq_add_file(struct acpi_processor *pr)
+{
+ return;
+}
+static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
+{
+ return;
+}
+#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
int
-acpi_processor_register_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu)
+acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
{
struct acpi_processor *pr;
@@ -603,13 +592,12 @@ acpi_processor_register_performance (
up(&performance_sem);
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_processor_register_performance);
+EXPORT_SYMBOL(acpi_processor_register_performance);
void
-acpi_processor_unregister_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu)
+acpi_processor_unregister_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
{
struct acpi_processor *pr;
@@ -632,4 +620,5 @@ acpi_processor_unregister_performance (
return_VOID;
}
+
EXPORT_SYMBOL(acpi_processor_unregister_performance);
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 12bd980a12e9..37528c3b64b0 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -43,20 +43,16 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
/* --------------------------------------------------------------------------
Limit Interface
-------------------------------------------------------------------------- */
-
-static int
-acpi_processor_apply_limit (
- struct acpi_processor* pr)
+static int acpi_processor_apply_limit(struct acpi_processor *pr)
{
- int result = 0;
- u16 px = 0;
- u16 tx = 0;
+ int result = 0;
+ u16 px = 0;
+ u16 tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
@@ -80,19 +76,17 @@ acpi_processor_apply_limit (
pr->limit.state.px = px;
pr->limit.state.tx = tx;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n",
- pr->id,
- pr->limit.state.px,
- pr->limit.state.tx));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Processor [%d] limit set to (P%d:T%d)\n", pr->id,
+ pr->limit.state.px, pr->limit.state.tx));
-end:
+ end:
if (result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
return_VALUE(result);
}
-
#ifdef CONFIG_CPU_FREQ
/* If a passive cooling situation is detected, primarily CPUfreq is used, as it
@@ -104,7 +98,6 @@ end:
static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
static unsigned int acpi_thermal_cpufreq_is_init = 0;
-
static int cpu_has_cpufreq(unsigned int cpu)
{
struct cpufreq_policy policy;
@@ -115,7 +108,6 @@ static int cpu_has_cpufreq(unsigned int cpu)
return 0;
}
-
static int acpi_thermal_cpufreq_increase(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
@@ -130,7 +122,6 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
return -ERANGE;
}
-
static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
@@ -145,11 +136,8 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
return -ERANGE;
}
-
-static int acpi_thermal_cpufreq_notifier(
- struct notifier_block *nb,
- unsigned long event,
- void *data)
+static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
{
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
@@ -157,68 +145,74 @@ static int acpi_thermal_cpufreq_notifier(
if (event != CPUFREQ_ADJUST)
goto out;
- max_freq = (policy->cpuinfo.max_freq * (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
+ max_freq =
+ (policy->cpuinfo.max_freq *
+ (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
cpufreq_verify_within_limits(policy, 0, max_freq);
- out:
+ out:
return 0;
}
-
static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
.notifier_call = acpi_thermal_cpufreq_notifier,
};
-
-void acpi_thermal_cpufreq_init(void) {
+void acpi_thermal_cpufreq_init(void)
+{
int i;
- for (i=0; i<NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++)
cpufreq_thermal_reduction_pctg[i] = 0;
- i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
if (!i)
acpi_thermal_cpufreq_is_init = 1;
}
-void acpi_thermal_cpufreq_exit(void) {
+void acpi_thermal_cpufreq_exit(void)
+{
if (acpi_thermal_cpufreq_is_init)
- cpufreq_unregister_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier
+ (&acpi_thermal_cpufreq_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
acpi_thermal_cpufreq_is_init = 0;
}
-#else /* ! CONFIG_CPU_FREQ */
-
-static int acpi_thermal_cpufreq_increase(unsigned int cpu) { return -ENODEV; }
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu) { return -ENODEV; }
+#else /* ! CONFIG_CPU_FREQ */
+static int acpi_thermal_cpufreq_increase(unsigned int cpu)
+{
+ return -ENODEV;
+}
+static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
+{
+ return -ENODEV;
+}
#endif
-
-int
-acpi_processor_set_thermal_limit (
- acpi_handle handle,
- int type)
+int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
{
- int result = 0;
- struct acpi_processor *pr = NULL;
- struct acpi_device *device = NULL;
- int tx = 0;
+ int result = 0;
+ struct acpi_processor *pr = NULL;
+ struct acpi_device *device = NULL;
+ int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
if ((type < ACPI_PROCESSOR_LIMIT_NONE)
- || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
+ || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
return_VALUE(-EINVAL);
result = acpi_bus_get_device(handle, &device);
if (result)
return_VALUE(result);
- pr = (struct acpi_processor *) acpi_driver_data(device);
+ pr = (struct acpi_processor *)acpi_driver_data(device);
if (!pr)
return_VALUE(-ENODEV);
@@ -250,12 +244,12 @@ acpi_processor_set_thermal_limit (
goto end;
else if (result == -ERANGE)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At maximum performance state\n"));
+ "At maximum performance state\n"));
if (pr->flags.throttling) {
if (tx == (pr->throttling.state_count - 1))
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At maximum throttling state\n"));
+ "At maximum throttling state\n"));
else
tx++;
}
@@ -267,7 +261,7 @@ acpi_processor_set_thermal_limit (
if (pr->flags.throttling) {
if (tx == 0)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At minimum throttling state\n"));
+ "At minimum throttling state\n"));
else {
tx--;
goto end;
@@ -277,12 +271,12 @@ acpi_processor_set_thermal_limit (
result = acpi_thermal_cpufreq_decrease(pr->id);
if (result == -ERANGE)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At minimum performance state\n"));
+ "At minimum performance state\n"));
break;
}
-end:
+ end:
if (pr->flags.throttling) {
pr->limit.thermal.px = 0;
pr->limit.thermal.tx = tx;
@@ -293,18 +287,14 @@ end:
"Unable to set thermal limit\n"));
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
- pr->limit.thermal.px,
- pr->limit.thermal.tx));
+ pr->limit.thermal.px, pr->limit.thermal.tx));
} else
result = 0;
return_VALUE(result);
}
-
-int
-acpi_processor_get_limit_info (
- struct acpi_processor *pr)
+int acpi_processor_get_limit_info(struct acpi_processor *pr)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
@@ -317,12 +307,11 @@ acpi_processor_get_limit_info (
return_VALUE(0);
}
-
/* /proc interface */
static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show");
@@ -335,34 +324,32 @@ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "active limit: P%d:T%d\n"
- "user limit: P%d:T%d\n"
- "thermal limit: P%d:T%d\n",
- pr->limit.state.px, pr->limit.state.tx,
- pr->limit.user.px, pr->limit.user.tx,
- pr->limit.thermal.px, pr->limit.thermal.tx);
+ "user limit: P%d:T%d\n"
+ "thermal limit: P%d:T%d\n",
+ pr->limit.state.px, pr->limit.state.tx,
+ pr->limit.user.px, pr->limit.user.tx,
+ pr->limit.thermal.px, pr->limit.thermal.tx);
-end:
+ end:
return_VALUE(0);
}
static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_limit_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-ssize_t acpi_processor_write_limit (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+ssize_t acpi_processor_write_limit(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
- char limit_string[25] = {'\0'};
- int px = 0;
- int tx = 0;
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ char limit_string[25] = { '\0' };
+ int px = 0;
+ int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
@@ -396,11 +383,9 @@ ssize_t acpi_processor_write_limit (
return_VALUE(count);
}
-
struct file_operations acpi_processor_limit_fops = {
- .open = acpi_processor_limit_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_limit_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index be9f569d39d3..74a52d4e79ae 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -43,21 +43,17 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
/* --------------------------------------------------------------------------
Throttling Control
-------------------------------------------------------------------------- */
-
-static int
-acpi_processor_get_throttling (
- struct acpi_processor *pr)
+static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
- int state = 0;
- u32 value = 0;
- u32 duty_mask = 0;
- u32 duty_value = 0;
+ int state = 0;
+ u32 value = 0;
+ u32 duty_mask = 0;
+ u32 duty_value = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_throttling");
@@ -86,7 +82,7 @@ acpi_processor_get_throttling (
duty_value >>= pr->throttling.duty_offset;
if (duty_value)
- state = pr->throttling.state_count-duty_value;
+ state = pr->throttling.state_count - duty_value;
}
pr->throttling.state = state;
@@ -94,20 +90,17 @@ acpi_processor_get_throttling (
local_irq_enable();
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling state is T%d (%d%% throttling applied)\n",
- state, pr->throttling.states[state].performance));
+ "Throttling state is T%d (%d%% throttling applied)\n",
+ state, pr->throttling.states[state].performance));
return_VALUE(0);
}
-
-int acpi_processor_set_throttling (
- struct acpi_processor *pr,
- int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
- u32 value = 0;
- u32 duty_mask = 0;
- u32 duty_value = 0;
+ u32 value = 0;
+ u32 duty_mask = 0;
+ u32 duty_value = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_throttling");
@@ -168,28 +161,26 @@ int acpi_processor_set_throttling (
local_irq_enable();
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling state set to T%d (%d%%)\n", state,
- (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
+ "Throttling state set to T%d (%d%%)\n", state,
+ (pr->throttling.states[state].performance ? pr->
+ throttling.states[state].performance / 10 : 0)));
return_VALUE(0);
}
-
-int
-acpi_processor_get_throttling_info (
- struct acpi_processor *pr)
+int acpi_processor_get_throttling_info(struct acpi_processor *pr)
{
- int result = 0;
- int step = 0;
- int i = 0;
+ int result = 0;
+ int step = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_throttling_info");
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
- pr->throttling.address,
- pr->throttling.duty_offset,
- pr->throttling.duty_width));
+ "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
+ pr->throttling.address,
+ pr->throttling.duty_offset,
+ pr->throttling.duty_width));
if (!pr)
return_VALUE(-EINVAL);
@@ -199,14 +190,12 @@ acpi_processor_get_throttling_info (
if (!pr->throttling.address) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
return_VALUE(0);
- }
- else if (!pr->throttling.duty_width) {
+ } else if (!pr->throttling.duty_width) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
return_VALUE(0);
}
/* TBD: Support duty_cycle values that span bit 4. */
- else if ((pr->throttling.duty_offset
- + pr->throttling.duty_width) > 4) {
+ else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n"));
return_VALUE(0);
}
@@ -218,7 +207,7 @@ acpi_processor_get_throttling_info (
*/
if (errata.piix4.throttle) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling not supported on PIIX4 A- or B-step\n"));
+ "Throttling not supported on PIIX4 A- or B-step\n"));
return_VALUE(0);
}
@@ -232,13 +221,13 @@ acpi_processor_get_throttling_info (
step = (1000 / pr->throttling.state_count);
- for (i=0; i<pr->throttling.state_count; i++) {
+ for (i = 0; i < pr->throttling.state_count; i++) {
pr->throttling.states[i].performance = step * i;
pr->throttling.states[i].power = step * i;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
- pr->throttling.state_count));
+ pr->throttling.state_count));
pr->flags.throttling = 1;
@@ -253,28 +242,29 @@ acpi_processor_get_throttling_info (
goto end;
if (pr->throttling.state) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n",
- pr->throttling.state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Disabling throttling (was T%d)\n",
+ pr->throttling.state));
result = acpi_processor_set_throttling(pr, 0);
if (result)
goto end;
}
-end:
+ end:
if (result)
pr->flags.throttling = 0;
return_VALUE(result);
}
-
/* proc interface */
-static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset)
+static int acpi_processor_throttling_seq_show(struct seq_file *seq,
+ void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- int i = 0;
- int result = 0;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ int i = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_throttling_seq_show");
@@ -289,41 +279,41 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset
result = acpi_processor_get_throttling(pr);
if (result) {
- seq_puts(seq, "Could not determine current throttling state.\n");
+ seq_puts(seq,
+ "Could not determine current throttling state.\n");
goto end;
}
seq_printf(seq, "state count: %d\n"
- "active state: T%d\n",
- pr->throttling.state_count,
- pr->throttling.state);
+ "active state: T%d\n",
+ pr->throttling.state_count, pr->throttling.state);
seq_puts(seq, "states:\n");
for (i = 0; i < pr->throttling.state_count; i++)
seq_printf(seq, " %cT%d: %02d%%\n",
- (i == pr->throttling.state?'*':' '), i,
- (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
+ (i == pr->throttling.state ? '*' : ' '), i,
+ (pr->throttling.states[i].performance ? pr->
+ throttling.states[i].performance / 10 : 0));
-end:
+ end:
return_VALUE(0);
}
-static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_throttling_open_fs(struct inode *inode,
+ struct file *file)
{
return single_open(file, acpi_processor_throttling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-ssize_t acpi_processor_write_throttling (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+ssize_t acpi_processor_write_throttling(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
- char state_string[12] = {'\0'};
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ char state_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_processor_write_throttling");
@@ -336,7 +326,8 @@ ssize_t acpi_processor_write_throttling (
state_string[count] = '\0';
result = acpi_processor_set_throttling(pr,
- simple_strtoul(state_string, NULL, 0));
+ simple_strtoul(state_string,
+ NULL, 0));
if (result)
return_VALUE(result);
@@ -344,8 +335,8 @@ ssize_t acpi_processor_write_throttling (
}
struct file_operations acpi_processor_throttling_fops = {
- .open = acpi_processor_throttling_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_throttling_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index 55d264771c48..23b54baa0cb2 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -41,13 +41,185 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsaddr")
+ACPI_MODULE_NAME("rsaddr")
+
+/* Local prototypes */
+static void
+acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags);
+
+static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource);
+
+static void
+acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags);
+
+static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_decode_general_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ * Flags - Actual flag byte
+ *
+ * RETURN: Decoded flag bits in resource struct
+ *
+ * DESCRIPTION: Decode a general flag byte to an address resource struct
+ *
+ ******************************************************************************/
+
+static void
+acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /* Producer / Consumer - flag bit[0] */
+
+ resource->address.producer_consumer = (u32) (flags & 0x01);
+
+ /* Decode (_DEC) - flag bit[1] */
+ resource->address.decode = (u32) ((flags >> 1) & 0x01);
+
+ /* Min Address Fixed (_MIF) - flag bit[2] */
+
+ resource->address.min_address_fixed = (u32) ((flags >> 2) & 0x01);
+
+ /* Max Address Fixed (_MAF) - flag bit[3] */
+
+ resource->address.max_address_fixed = (u32) ((flags >> 3) & 0x01);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_encode_general_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ *
+ * RETURN: Encoded general flag byte
+ *
+ * DESCRIPTION: Construct a general flag byte from an address resource struct
+ *
+ ******************************************************************************/
+
+static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource)
+{
+ u8 flags;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Producer / Consumer - flag bit[0] */
+
+ flags = (u8) (resource->address.producer_consumer & 0x01);
+
+ /* Decode (_DEC) - flag bit[1] */
+
+ flags |= (u8) ((resource->address.decode & 0x01) << 1);
+
+ /* Min Address Fixed (_MIF) - flag bit[2] */
+
+ flags |= (u8) ((resource->address.min_address_fixed & 0x01) << 2);
+
+ /* Max Address Fixed (_MAF) - flag bit[3] */
+
+ flags |= (u8) ((resource->address.max_address_fixed & 0x01) << 3);
+
+ return (flags);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_decode_specific_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ * Flags - Actual flag byte
+ *
+ * RETURN: Decoded flag bits in attribute struct
+ *
+ * DESCRIPTION: Decode a type-specific flag byte to an attribute struct.
+ * Type-specific flags are only defined for the Memory and IO
+ * resource types.
+ *
+ ******************************************************************************/
+
+static void
+acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
+ /* Write Status (_RW) - flag bit[0] */
+
+ resource->address.attribute.memory.read_write_attribute =
+ (u16) (flags & 0x01);
+
+ /* Memory Attributes (_MEM) - flag bits[2:1] */
+
+ resource->address.attribute.memory.cache_attribute =
+ (u16) ((flags >> 1) & 0x03);
+ } else if (resource->address.resource_type == ACPI_IO_RANGE) {
+ /* Ranges (_RNG) - flag bits[1:0] */
+
+ resource->address.attribute.io.range_attribute =
+ (u16) (flags & 0x03);
+
+ /* Translations (_TTP and _TRS) - flag bits[5:4] */
+
+ resource->address.attribute.io.translation_attribute =
+ (u16) ((flags >> 4) & 0x03);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_encode_specific_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ *
+ * RETURN: Encoded type-specific flag byte
+ *
+ * DESCRIPTION: Construct a type-specific flag byte from an attribute struct.
+ * Type-specific flags are only defined for the Memory and IO
+ * resource types.
+ *
+ ******************************************************************************/
+
+static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource)
+{
+ u8 flags = 0;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
+ /* Write Status (_RW) - flag bit[0] */
+
+ flags = (u8)
+ (resource->address.attribute.memory.
+ read_write_attribute & 0x01);
+
+ /* Memory Attributes (_MEM) - flag bits[2:1] */
+
+ flags |= (u8)
+ ((resource->address.attribute.memory.
+ cache_attribute & 0x03) << 1);
+ } else if (resource->address.resource_type == ACPI_IO_RANGE) {
+ /* Ranges (_RNG) - flag bits[1:0] */
+
+ flags = (u8)
+ (resource->address.attribute.io.range_attribute & 0x03);
+
+ /* Translations (_TTP and _TRS) - flag bits[5:4] */
+
+ flags |= (u8)
+ ((resource->address.attribute.io.
+ translation_attribute & 0x03) << 4);
+ }
+
+ return (flags);
+}
/*******************************************************************************
*
@@ -71,34 +243,30 @@
******************************************************************************/
acpi_status
-acpi_rs_address16_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address16_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u32 index;
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_address16);
-
+ u32 index;
+ u16 temp16;
+ u8 temp8;
+ u8 *temp_ptr;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16);
- ACPI_FUNCTION_TRACE ("rs_address16_resource");
+ ACPI_FUNCTION_TRACE("rs_address16_resource");
-
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 13) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -112,7 +280,7 @@ acpi_rs_address16_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address16.resource_type = temp8;
@@ -120,73 +288,41 @@ acpi_rs_address16_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address16.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address16.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
- output_struct->data.address16.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
- output_struct->data.address16.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
- output_struct->data.address16.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address16.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == Address16.Data->resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
/* Get Granularity (Bytes 6-7) */
buffer += 1;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
/* Get min_address_range (Bytes 8-9) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 10-11) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 12-13) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset,
- buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 14-15) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
+ buffer);
/* Resource Source Index (if present) */
@@ -205,8 +341,8 @@ acpi_rs_address16_resource (
if (*bytes_consumed > (16 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
- output_struct->data.address16.resource_source.index = (u32) temp8;
+ output_struct->data.address16.resource_source.index =
+ (u32) * buffer;
/* Point to the String */
@@ -215,28 +351,27 @@ acpi_rs_address16_resource (
/* Point the String pointer to the end of this structure */
output_struct->data.address16.resource_source.string_ptr =
- (char *)((u8 * )output_struct + struct_size);
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address16.resource_source.string_ptr;
+ output_struct->data.address16.resource_source.string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
-
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
- /* Add the terminating null */
-
- *temp_ptr = 0x00;
+ /* Add the terminating null and set the string length */
- output_struct->data.address16.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address16.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -244,10 +379,9 @@ acpi_rs_address16_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address16.resource_source.index = 0x00;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.address16.resource_source.index = 0;
output_struct->data.address16.resource_source.string_length = 0;
output_struct->data.address16.resource_source.string_ptr = NULL;
}
@@ -259,10 +393,9 @@ acpi_rs_address16_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address16_stream
@@ -280,24 +413,18 @@ acpi_rs_address16_resource (
******************************************************************************/
acpi_status
-acpi_rs_address16_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address16_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 *length_field;
- u8 temp8;
- char *temp_pointer = NULL;
- acpi_size actual_bytes;
-
-
- ACPI_FUNCTION_TRACE ("rs_address16_stream");
+ u8 *buffer = *output_buffer;
+ u8 *length_field;
+ acpi_size actual_bytes;
+ ACPI_FUNCTION_TRACE("rs_address16_stream");
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x88;
+ *buffer = ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE;
buffer += 1;
/* Save a pointer to the Length field - to be filled in later */
@@ -307,98 +434,74 @@ acpi_rs_address16_stream (
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address16.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01);
-
- temp8 |= (linked_list->data.address16.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
- temp8 = (u8)
- (linked_list->data.address16.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address16.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
- temp8 = (u8)
- (linked_list->data.address16.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address16.attribute.io.translation_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
buffer += 2;
/* Set the address range minimum */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.min_address_range);
buffer += 2;
/* Set the address range maximum */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.max_address_range);
buffer += 2;
/* Set the address translation offset */
- ACPI_MOVE_32_TO_16 (buffer,
- &linked_list->data.address16.address_translation_offset);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.
+ address_translation_offset);
buffer += 2;
/* Set the address length */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
buffer += 2;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address16.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address16.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address16.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address16.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
- /* Copy the string */
+ /* Copy the resource_source string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address16.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address16.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address16.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address16.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer);
+ actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
*bytes_consumed = actual_bytes;
/*
@@ -406,11 +509,10 @@ acpi_rs_address16_stream (
* minus the header size (3 bytes)
*/
actual_bytes -= 3;
- ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address32_resource
@@ -433,36 +535,30 @@ acpi_rs_address16_stream (
******************************************************************************/
acpi_status
-acpi_rs_address32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer;
- struct acpi_resource *output_struct= (void *) *output_buffer;
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- acpi_size struct_size;
- u32 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_address32_resource");
+ u16 temp16;
+ u8 temp8;
+ u8 *temp_ptr;
+ u32 index;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
+ ACPI_FUNCTION_TRACE("rs_address32_resource");
- buffer = byte_stream_buffer;
- struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32);
-
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 23) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -476,7 +572,7 @@ acpi_rs_address32_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address32.resource_type = temp8;
@@ -484,74 +580,41 @@ acpi_rs_address32_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address32.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
- output_struct->data.address32.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
-
- output_struct->data.address32.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
- output_struct->data.address32.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address32.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
/* Get Granularity (Bytes 6-9) */
buffer += 1;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
/* Get min_address_range (Bytes 10-13) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 14-17) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 18-21) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset,
- buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 22-25) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
+ buffer);
/* Resource Source Index (if present) */
@@ -568,9 +631,8 @@ acpi_rs_address32_resource (
if (*bytes_consumed > (26 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
output_struct->data.address32.resource_source.index =
- (u32) temp8;
+ (u32) * buffer;
/* Point to the String */
@@ -579,26 +641,27 @@ acpi_rs_address32_resource (
/* Point the String pointer to the end of this structure */
output_struct->data.address32.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address32.resource_source.string_ptr;
+ output_struct->data.address32.resource_source.string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
- /* Add the terminating null */
+ /* Add the terminating null and set the string length */
- *temp_ptr = 0x00;
- output_struct->data.address32.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address32.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -606,10 +669,9 @@ acpi_rs_address32_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address32.resource_source.index = 0x00;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.address32.resource_source.index = 0;
output_struct->data.address32.resource_source.string_length = 0;
output_struct->data.address32.resource_source.string_ptr = NULL;
}
@@ -621,10 +683,9 @@ acpi_rs_address32_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address32_stream
@@ -642,136 +703,105 @@ acpi_rs_address32_resource (
******************************************************************************/
acpi_status
-acpi_rs_address32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer;
- u16 *length_field;
- u8 temp8;
- char *temp_pointer;
-
-
- ACPI_FUNCTION_TRACE ("rs_address32_stream");
+ u8 *buffer;
+ u16 *length_field;
+ ACPI_FUNCTION_TRACE("rs_address32_stream");
buffer = *output_buffer;
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x87;
+ *buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
-
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address32.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
- temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
- temp8 = (u8)
- (linked_list->data.address32.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address32.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
- temp8 = (u8)
- (linked_list->data.address32.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address32.attribute.io.translation_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
buffer += 4;
/* Set the address range minimum */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.min_address_range);
buffer += 4;
/* Set the address range maximum */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.max_address_range);
buffer += 4;
/* Set the address translation offset */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.address32.address_translation_offset);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.
+ address_translation_offset);
buffer += 4;
/* Set the address length */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
buffer += 4;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address32.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address32.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address32.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address32.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
- /* Copy the string */
+ /* Copy the resource_source string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address32.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address32.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address32.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address32.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
+ * minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address64_resource
@@ -794,38 +824,35 @@ acpi_rs_address32_stream (
******************************************************************************/
acpi_status
-acpi_rs_address64_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address64_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16;
- u8 temp8;
- u8 resource_type;
- u8 *temp_ptr;
- acpi_size struct_size;
- u32 index;
-
+ u16 temp16;
+ u8 temp8;
+ u8 resource_type;
+ u8 *temp_ptr;
+ u32 index;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
- ACPI_FUNCTION_TRACE ("rs_address64_resource");
+ ACPI_FUNCTION_TRACE("rs_address64_resource");
+ /* Get the Descriptor Type */
- buffer = byte_stream_buffer;
- struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
resource_type = *buffer;
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 43) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -839,7 +866,7 @@ acpi_rs_address64_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address64.resource_type = temp8;
@@ -847,48 +874,12 @@ acpi_rs_address64_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address64.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
- output_struct->data.address64.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
-
- output_struct->data.address64.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
- output_struct->data.address64.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address64.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
/* Move past revision_id and Reserved byte */
@@ -899,30 +890,33 @@ acpi_rs_address64_resource (
/* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
buffer += 1;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
/* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset,
- buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 38-45) or (Bytes 40-47) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
+ buffer);
- output_struct->data.address64.resource_source.index = 0x00;
+ output_struct->data.address64.resource_source.index = 0;
output_struct->data.address64.resource_source.string_length = 0;
output_struct->data.address64.resource_source.string_ptr = NULL;
@@ -930,11 +924,9 @@ acpi_rs_address64_resource (
/* Get type_specific_attribute (Bytes 48-55) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (
- &output_struct->data.address64.type_specific_attributes,
- buffer);
- }
- else {
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.
+ type_specific_attributes, buffer);
+ } else {
output_struct->data.address64.type_specific_attributes = 0;
/* Resource Source Index (if present) */
@@ -954,9 +946,8 @@ acpi_rs_address64_resource (
if (*bytes_consumed > (46 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
output_struct->data.address64.resource_source.index =
- (u32) temp8;
+ (u32) * buffer;
/* Point to the String */
@@ -964,29 +955,31 @@ acpi_rs_address64_resource (
/* Point the String pointer to the end of this structure */
- output_struct->data.address64.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ output_struct->data.address64.resource_source.
+ string_ptr =
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address64.resource_source.string_ptr;
+ output_struct->data.address64.resource_source.
+ string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
/*
- * Add the terminating null
+ * Add the terminating null and set the string length
*/
- *temp_ptr = 0x00;
- output_struct->data.address64.resource_source.string_length =
- index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address64.resource_source.
+ string_length = index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -994,7 +987,7 @@ acpi_rs_address64_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
}
}
@@ -1005,10 +998,9 @@ acpi_rs_address64_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address64_stream
@@ -1026,132 +1018,101 @@ acpi_rs_address64_resource (
******************************************************************************/
acpi_status
-acpi_rs_address64_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address64_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer;
- u16 *length_field;
- u8 temp8;
- char *temp_pointer;
-
-
- ACPI_FUNCTION_TRACE ("rs_address64_stream");
+ u8 *buffer;
+ u16 *length_field;
+ ACPI_FUNCTION_TRACE("rs_address64_stream");
buffer = *output_buffer;
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x8A;
+ *buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
-
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address64.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01);
- temp8 |= (linked_list->data.address64.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
- temp8 = (u8)
- (linked_list->data.address64.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address64.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
- temp8 = (u8)
- (linked_list->data.address64.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address64.attribute.io.range_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity);
+ ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
buffer += 8;
/* Set the address range minimum */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.min_address_range);
buffer += 8;
/* Set the address range maximum */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.max_address_range);
buffer += 8;
/* Set the address translation offset */
- ACPI_MOVE_64_TO_64 (buffer,
- &linked_list->data.address64.address_translation_offset);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.
+ address_translation_offset);
buffer += 8;
/* Set the address length */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length);
+ ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
buffer += 8;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address64.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address64.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address64.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address64.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
+ /* Copy the resource_source string */
- /* Copy the string */
-
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address64.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address64.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address64.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address64.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
* minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 98176f2fcb5d..378f58390fc1 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -41,15 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rscalc")
-
+ACPI_MODULE_NAME("rscalc")
/*******************************************************************************
*
@@ -66,19 +64,15 @@
* the resource data.
*
******************************************************************************/
-
acpi_status
-acpi_rs_get_byte_stream_length (
- struct acpi_resource *linked_list,
- acpi_size *size_needed)
+acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list,
+ acpi_size * size_needed)
{
- acpi_size byte_stream_size_needed = 0;
- acpi_size segment_size;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length");
+ acpi_size byte_stream_size_needed = 0;
+ acpi_size segment_size;
+ u8 done = FALSE;
+ ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
while (!done) {
/* Init the variable that will hold the size to add to the total. */
@@ -145,11 +139,11 @@ acpi_rs_get_byte_stream_length (
*/
if (linked_list->data.vendor_specific.length > 7) {
segment_size = 3;
- }
- else {
+ } else {
segment_size = 1;
}
- segment_size += linked_list->data.vendor_specific.length;
+ segment_size +=
+ linked_list->data.vendor_specific.length;
break;
case ACPI_RSTYPE_END_TAG:
@@ -194,9 +188,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 16;
- if (linked_list->data.address16.resource_source.string_ptr) {
+ if (linked_list->data.address16.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address16.resource_source.string_length;
+ linked_list->data.address16.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -211,9 +207,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 26;
- if (linked_list->data.address32.resource_source.string_ptr) {
+ if (linked_list->data.address32.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address32.resource_source.string_length;
+ linked_list->data.address32.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -227,9 +225,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 46;
- if (linked_list->data.address64.resource_source.string_ptr) {
+ if (linked_list->data.address64.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address64.resource_source.string_length;
+ linked_list->data.address64.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -244,11 +244,14 @@ acpi_rs_get_byte_stream_length (
* Resource Source + 1 for the null.
*/
segment_size = 9 + (((acpi_size)
- linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
+ linked_list->data.extended_irq.
+ number_of_interrupts - 1) * 4);
- if (linked_list->data.extended_irq.resource_source.string_ptr) {
+ if (linked_list->data.extended_irq.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.extended_irq.resource_source.string_length;
+ linked_list->data.extended_irq.
+ resource_source.string_length;
segment_size++;
}
break;
@@ -257,9 +260,9 @@ acpi_rs_get_byte_stream_length (
/* If we get here, everything is out of sync, exit with error */
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
- } /* switch (linked_list->Id) */
+ } /* switch (linked_list->Id) */
/* Update the total */
@@ -267,17 +270,16 @@ acpi_rs_get_byte_stream_length (
/* Point to the next object */
- linked_list = ACPI_PTR_ADD (struct acpi_resource,
- linked_list, linked_list->length);
+ linked_list = ACPI_PTR_ADD(struct acpi_resource,
+ linked_list, linked_list->length);
}
/* This is the data the caller needs */
*size_needed = byte_stream_size_needed;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_list_length
@@ -297,32 +299,28 @@ acpi_rs_get_byte_stream_length (
******************************************************************************/
acpi_status
-acpi_rs_get_list_length (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- acpi_size *size_needed)
+acpi_rs_get_list_length(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, acpi_size * size_needed)
{
- u32 buffer_size = 0;
- u32 bytes_parsed = 0;
- u8 number_of_interrupts = 0;
- u8 number_of_channels = 0;
- u8 resource_type;
- u32 structure_size;
- u32 bytes_consumed;
- u8 *buffer;
- u8 temp8;
- u16 temp16;
- u8 index;
- u8 additional_bytes;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_list_length");
-
+ u32 buffer_size = 0;
+ u32 bytes_parsed = 0;
+ u8 number_of_interrupts = 0;
+ u8 number_of_channels = 0;
+ u8 resource_type;
+ u32 structure_size;
+ u32 bytes_consumed;
+ u8 *buffer;
+ u8 temp8;
+ u16 temp16;
+ u8 index;
+ u8 additional_bytes;
+
+ ACPI_FUNCTION_TRACE("rs_get_list_length");
while (bytes_parsed < byte_stream_buffer_length) {
/* The next byte in the stream is the resource type */
- resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
+ resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
switch (resource_type) {
case ACPI_RDESC_TYPE_MEMORY_24:
@@ -331,10 +329,10 @@ acpi_rs_get_list_length (
*/
bytes_consumed = 12;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
break;
-
case ACPI_RDESC_TYPE_LARGE_VENDOR:
/*
* Vendor Defined Resource
@@ -342,38 +340,39 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
/* Ensure a 32-bit boundary for the structure */
- temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
+ temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
- (temp16 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
+ (temp16 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_MEMORY_32:
/*
* 32-Bit Memory Range Resource
*/
bytes_consumed = 20;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
break;
-
case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
/*
* 32-Bit Fixed Memory Resource
*/
bytes_consumed = 12;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_fixed_mem32);
break;
-
case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
@@ -381,13 +380,14 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_address64);
break;
-
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
@@ -395,7 +395,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -409,20 +409,19 @@ acpi_rs_get_list_length (
*/
if (43 < temp16) {
temp8 = (u8) (temp16 - 44);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 64-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
/*
* 32-Bit Address Resource
@@ -430,7 +429,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -444,20 +443,19 @@ acpi_rs_get_list_length (
*/
if (23 < temp16) {
temp8 = (u8) (temp16 - 24);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
/*
* 16-Bit Address Resource
@@ -465,7 +463,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -479,20 +477,19 @@ acpi_rs_get_list_length (
*/
if (13 < temp16) {
temp8 = (u8) (temp16 - 14);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
/*
* Extended IRQ
@@ -500,7 +497,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -527,21 +524,20 @@ acpi_rs_get_list_length (
*/
if (9 + additional_bytes < temp16) {
temp8 = (u8) (temp16 - (9 + additional_bytes));
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
- (additional_bytes * sizeof (u8)) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) +
+ (additional_bytes * sizeof(u8)) +
+ (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_IRQ_FORMAT:
/*
* IRQ Resource.
@@ -550,10 +546,9 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
temp8 = *buffer;
- if(temp8 & 0x01) {
+ if (temp8 & 0x01) {
bytes_consumed = 4;
- }
- else {
+ } else {
bytes_consumed = 3;
}
@@ -563,7 +558,7 @@ acpi_rs_get_list_length (
/* Look at the number of bits set */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
for (index = 0; index < 16; index++) {
if (temp16 & 0x1) {
@@ -573,11 +568,11 @@ acpi_rs_get_list_length (
temp16 >>= 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
- (number_of_interrupts * sizeof (u32));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) +
+ (number_of_interrupts * sizeof(u32));
break;
-
case ACPI_RDESC_TYPE_DMA_FORMAT:
/*
* DMA Resource
@@ -593,19 +588,19 @@ acpi_rs_get_list_length (
temp8 = *buffer;
- for(index = 0; index < 8; index++) {
- if(temp8 & 0x1) {
+ for (index = 0; index < 8; index++) {
+ if (temp8 & 0x1) {
++number_of_channels;
}
temp8 >>= 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
- (number_of_channels * sizeof (u32));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) +
+ (number_of_channels * sizeof(u32));
break;
-
case ACPI_RDESC_TYPE_START_DEPENDENT:
/*
* Start Dependent Functions Resource
@@ -614,17 +609,17 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
temp8 = *buffer;
- if(temp8 & 0x01) {
+ if (temp8 & 0x01) {
bytes_consumed = 2;
- }
- else {
+ } else {
bytes_consumed = 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_start_dpf);
break;
-
case ACPI_RDESC_TYPE_END_DEPENDENT:
/*
* End Dependent Functions Resource
@@ -633,25 +628,24 @@ acpi_rs_get_list_length (
structure_size = ACPI_RESOURCE_LENGTH;
break;
-
case ACPI_RDESC_TYPE_IO_PORT:
/*
* IO Port Resource
*/
bytes_consumed = 8;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
break;
-
case ACPI_RDESC_TYPE_FIXED_IO_PORT:
/*
* Fixed IO Port Resource
*/
bytes_consumed = 4;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
break;
-
case ACPI_RDESC_TYPE_SMALL_VENDOR:
/*
* Vendor Specific Resource
@@ -664,12 +658,12 @@ acpi_rs_get_list_length (
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
- (temp8 * sizeof (u8));
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
+ (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_END_TAG:
/*
* End Tag
@@ -679,18 +673,17 @@ acpi_rs_get_list_length (
byte_stream_buffer_length = bytes_parsed;
break;
-
default:
/*
* If we get here, everything is out of sync,
* exit with an error
*/
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
/* Update the return value and counter */
- buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
+ buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size);
bytes_parsed += bytes_consumed;
/* Set the byte stream to point to the next resource */
@@ -701,10 +694,9 @@ acpi_rs_get_list_length (
/* This is the data the caller needs */
*size_needed = buffer_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_pci_routing_table_length
@@ -723,22 +715,19 @@ acpi_rs_get_list_length (
******************************************************************************/
acpi_status
-acpi_rs_get_pci_routing_table_length (
- union acpi_operand_object *package_object,
- acpi_size *buffer_size_needed)
+acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
+ acpi_size * buffer_size_needed)
{
- u32 number_of_elements;
- acpi_size temp_size_needed = 0;
- union acpi_operand_object **top_object_list;
- u32 index;
- union acpi_operand_object *package_element;
- union acpi_operand_object **sub_object_list;
- u8 name_found;
- u32 table_index;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
+ u32 number_of_elements;
+ acpi_size temp_size_needed = 0;
+ union acpi_operand_object **top_object_list;
+ u32 index;
+ union acpi_operand_object *package_element;
+ union acpi_operand_object **sub_object_list;
+ u8 name_found;
+ u32 table_index;
+ ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length");
number_of_elements = package_object->package.count;
@@ -769,53 +758,51 @@ acpi_rs_get_pci_routing_table_length (
name_found = FALSE;
- for (table_index = 0; table_index < 4 && !name_found; table_index++) {
+ for (table_index = 0; table_index < 4 && !name_found;
+ table_index++) {
if ((ACPI_TYPE_STRING ==
- ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
-
- ((ACPI_TYPE_LOCAL_REFERENCE ==
- ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
-
- ((*sub_object_list)->reference.opcode ==
- AML_INT_NAMEPATH_OP))) {
+ ACPI_GET_OBJECT_TYPE(*sub_object_list))
+ ||
+ ((ACPI_TYPE_LOCAL_REFERENCE ==
+ ACPI_GET_OBJECT_TYPE(*sub_object_list))
+ && ((*sub_object_list)->reference.opcode ==
+ AML_INT_NAMEPATH_OP))) {
name_found = TRUE;
- }
- else {
+ } else {
/* Look at the next element */
sub_object_list++;
}
}
- temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
+ temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
/* Was a String type found? */
if (name_found) {
- if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
+ if (ACPI_GET_OBJECT_TYPE(*sub_object_list) ==
+ ACPI_TYPE_STRING) {
/*
* The length String.Length field does not include the
* terminating NULL, add 1
*/
temp_size_needed += ((acpi_size)
- (*sub_object_list)->string.length + 1);
+ (*sub_object_list)->string.
+ length + 1);
+ } else {
+ temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
}
- else {
- temp_size_needed += acpi_ns_get_pathname_length (
- (*sub_object_list)->reference.node);
- }
- }
- else {
+ } else {
/*
* If no name was found, then this is a NULL, which is
* translated as a u32 zero.
*/
- temp_size_needed += sizeof (u32);
+ temp_size_needed += sizeof(u32);
}
/* 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_64_bITS(temp_size_needed);
/* Point to the next union acpi_operand_object */
@@ -826,6 +813,7 @@ acpi_rs_get_pci_routing_table_length (
* Adding an extra element to the end of the list, essentially a
* NULL terminator
*/
- *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
- return_ACPI_STATUS (AE_OK);
+ *buffer_size_needed =
+ temp_size_needed + sizeof(struct acpi_pci_routing_table);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 8e0eae0d50bb..0911526b7ad8 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -41,15 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rscreate")
-
+ACPI_MODULE_NAME("rscreate")
/*******************************************************************************
*
@@ -68,24 +66,20 @@
* of device resources.
*
******************************************************************************/
-
acpi_status
-acpi_rs_create_resource_list (
- union acpi_operand_object *byte_stream_buffer,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
+ struct acpi_buffer *output_buffer)
{
- acpi_status status;
- u8 *byte_stream_start;
- acpi_size list_size_needed = 0;
- u32 byte_stream_buffer_length;
+ acpi_status status;
+ u8 *byte_stream_start;
+ acpi_size list_size_needed = 0;
+ u32 byte_stream_buffer_length;
+ ACPI_FUNCTION_TRACE("rs_create_resource_list");
- ACPI_FUNCTION_TRACE ("rs_create_resource_list");
-
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
- byte_stream_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
+ byte_stream_buffer));
/* Params already validated, so we don't re-validate here */
@@ -96,36 +90,39 @@ acpi_rs_create_resource_list (
* Pass the byte_stream_buffer into a module that can calculate
* the buffer size needed for the linked list
*/
- status = acpi_rs_get_list_length (byte_stream_start, byte_stream_buffer_length,
- &list_size_needed);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
- status, (u32) list_size_needed));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_get_list_length(byte_stream_start,
+ byte_stream_buffer_length,
+ &list_size_needed);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
+ status, (u32) list_size_needed));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, list_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(output_buffer, list_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Do the conversion */
- status = acpi_rs_byte_stream_to_list (byte_stream_start, byte_stream_buffer_length,
- output_buffer->pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_byte_stream_to_list(byte_stream_start,
+ byte_stream_buffer_length,
+ output_buffer->pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ output_buffer->pointer, (u32) output_buffer->length));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_create_pci_routing_table
@@ -148,44 +145,41 @@ acpi_rs_create_resource_list (
******************************************************************************/
acpi_status
-acpi_rs_create_pci_routing_table (
- union acpi_operand_object *package_object,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
+ struct acpi_buffer *output_buffer)
{
- u8 *buffer;
- union acpi_operand_object **top_object_list;
- union acpi_operand_object **sub_object_list;
- union acpi_operand_object *obj_desc;
- acpi_size buffer_size_needed = 0;
- u32 number_of_elements;
- u32 index;
- struct acpi_pci_routing_table *user_prt;
- struct acpi_namespace_node *node;
- acpi_status status;
- struct acpi_buffer path_buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_create_pci_routing_table");
-
+ u8 *buffer;
+ union acpi_operand_object **top_object_list;
+ union acpi_operand_object **sub_object_list;
+ union acpi_operand_object *obj_desc;
+ acpi_size buffer_size_needed = 0;
+ u32 number_of_elements;
+ u32 index;
+ struct acpi_pci_routing_table *user_prt;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ struct acpi_buffer path_buffer;
+
+ ACPI_FUNCTION_TRACE("rs_create_pci_routing_table");
/* Params already validated, so we don't re-validate here */
/* Get the required buffer length */
- status = acpi_rs_get_pci_routing_table_length (package_object,
- &buffer_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_pci_routing_table_length(package_object,
+ &buffer_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "buffer_size_needed = %X\n",
- (u32) buffer_size_needed));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n",
+ (u32) buffer_size_needed));
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, buffer_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -193,10 +187,10 @@ acpi_rs_create_pci_routing_table (
* should be a package that in turn contains an
* acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
*/
- top_object_list = package_object->package.elements;
+ top_object_list = package_object->package.elements;
number_of_elements = package_object->package.count;
- buffer = output_buffer->pointer;
- user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ buffer = output_buffer->pointer;
+ user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
/*
@@ -206,31 +200,34 @@ acpi_rs_create_pci_routing_table (
* be zero because we cleared the return buffer earlier
*/
buffer += user_prt->length;
- user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
/*
* Fill in the Length field with the information we have at this point.
* The minus four is to subtract the size of the u8 Source[4] member
* because it is added below.
*/
- user_prt->length = (sizeof (struct acpi_pci_routing_table) - 4);
+ user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
/* Each element of the top-level package must also be a package */
- if (ACPI_GET_OBJECT_TYPE (*top_object_list) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X]) Need sub-package, found %s\n",
- index, acpi_ut_get_object_type_name (*top_object_list)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X]) Need sub-package, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (*top_object_list)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Each sub-package must be of length 4 */
if ((*top_object_list)->package.count != 4) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X]) Need package of length 4, found length %d\n",
- index, (*top_object_list)->package.count));
- return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X]) Need package of length 4, found length %d\n",
+ index,
+ (*top_object_list)->package.count));
+ return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
}
/*
@@ -243,40 +240,43 @@ acpi_rs_create_pci_routing_table (
/* 1) First subobject: Dereference the PRT.Address */
obj_desc = sub_object_list[0];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->address = obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Address) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Address) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* 2) Second subobject: Dereference the PRT.Pin */
obj_desc = sub_object_list[1];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->pin = (u32) obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Pin) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Pin) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* 3) Third subobject: Dereference the PRT.source_name */
obj_desc = sub_object_list[2];
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need name, found reference op %X\n",
- index, obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Source) Need name, found reference op %X\n",
+ index,
+ obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
node = obj_desc->reference.node;
@@ -284,21 +284,23 @@ acpi_rs_create_pci_routing_table (
/* Use *remaining* length of the buffer as max for pathname */
path_buffer.length = output_buffer->length -
- (u32) ((u8 *) user_prt->source -
- (u8 *) output_buffer->pointer);
+ (u32) ((u8 *) user_prt->source -
+ (u8 *) output_buffer->pointer);
path_buffer.pointer = user_prt->source;
- status = acpi_ns_handle_to_pathname ((acpi_handle) node, &path_buffer);
+ status =
+ acpi_ns_handle_to_pathname((acpi_handle) node,
+ &path_buffer);
/* +1 to include null terminator */
- user_prt->length += (u32) ACPI_STRLEN (user_prt->source) + 1;
+ user_prt->length +=
+ (u32) ACPI_STRLEN(user_prt->source) + 1;
break;
-
case ACPI_TYPE_STRING:
- ACPI_STRCPY (user_prt->source, obj_desc->string.pointer);
+ ACPI_STRCPY(user_prt->source, obj_desc->string.pointer);
/*
* Add to the Length field the length of the string
@@ -307,7 +309,6 @@ acpi_rs_create_pci_routing_table (
user_prt->length += obj_desc->string.length + 1;
break;
-
case ACPI_TYPE_INTEGER:
/*
* If this is a number, then the Source Name is NULL, since the
@@ -315,33 +316,36 @@ acpi_rs_create_pci_routing_table (
*
* Add to the Length field the length of the u32 NULL
*/
- user_prt->length += sizeof (u32);
+ user_prt->length += sizeof(u32);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Now align the current length */
- user_prt->length = (u32) ACPI_ROUND_UP_to_64_bITS (user_prt->length);
+ user_prt->length =
+ (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length);
/* 4) Fourth subobject: Dereference the PRT.source_index */
obj_desc = sub_object_list[3];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->source_index = (u32) obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].source_index) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].source_index) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Point to the next union acpi_operand_object in the top level package */
@@ -349,12 +353,11 @@ acpi_rs_create_pci_routing_table (
top_object_list++;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ output_buffer->pointer, (u32) output_buffer->length));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_create_byte_stream
@@ -374,19 +377,16 @@ acpi_rs_create_pci_routing_table (
******************************************************************************/
acpi_status
-acpi_rs_create_byte_stream (
- struct acpi_resource *linked_list_buffer,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
+ struct acpi_buffer *output_buffer)
{
- acpi_status status;
- acpi_size byte_stream_size_needed = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_create_byte_stream");
+ acpi_status status;
+ acpi_size byte_stream_size_needed = 0;
+ ACPI_FUNCTION_TRACE("rs_create_byte_stream");
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "linked_list_buffer = %p\n",
- linked_list_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
+ linked_list_buffer));
/*
* Params already validated, so we don't re-validate here
@@ -394,32 +394,35 @@ acpi_rs_create_byte_stream (
* Pass the linked_list_buffer into a module that calculates
* the buffer size needed for the byte stream.
*/
- status = acpi_rs_get_byte_stream_length (linked_list_buffer,
- &byte_stream_size_needed);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
- (u32) byte_stream_size_needed, acpi_format_exception (status)));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_byte_stream_length(linked_list_buffer,
+ &byte_stream_size_needed);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
+ (u32) byte_stream_size_needed,
+ acpi_format_exception(status)));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, byte_stream_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_initialize_buffer(output_buffer, byte_stream_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Do the conversion */
- status = acpi_rs_list_to_byte_stream (linked_list_buffer, byte_stream_size_needed,
- output_buffer->pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_list_to_byte_stream(linked_list_buffer,
+ byte_stream_size_needed,
+ output_buffer->pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %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 1935dab2ab51..75bd34d1783f 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -41,69 +41,40 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsdump")
+ACPI_MODULE_NAME("rsdump")
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
+static void acpi_rs_dump_irq(union acpi_resource_data *data);
-static void
-acpi_rs_dump_irq (
- union acpi_resource_data *data);
-
-static void
-acpi_rs_dump_address16 (
- union acpi_resource_data *data);
-
-static void
-acpi_rs_dump_address32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address16(union acpi_resource_data *data);
-static void
-acpi_rs_dump_address64 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_dma (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address64(union acpi_resource_data *data);
-static void
-acpi_rs_dump_io (
- union acpi_resource_data *data);
+static void acpi_rs_dump_dma(union acpi_resource_data *data);
-static void
-acpi_rs_dump_extended_irq (
- union acpi_resource_data *data);
+static void acpi_rs_dump_io(union acpi_resource_data *data);
-static void
-acpi_rs_dump_fixed_io (
- union acpi_resource_data *data);
+static void acpi_rs_dump_extended_irq(union acpi_resource_data *data);
-static void
-acpi_rs_dump_fixed_memory32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_fixed_io(union acpi_resource_data *data);
-static void
-acpi_rs_dump_memory24 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_memory32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_memory24(union acpi_resource_data *data);
-static void
-acpi_rs_dump_start_depend_fns (
- union acpi_resource_data *data);
+static void acpi_rs_dump_memory32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_vendor_specific (
- union acpi_resource_data *data);
+static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data);
+static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data);
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_irq
@@ -116,39 +87,37 @@ acpi_rs_dump_vendor_specific (
*
******************************************************************************/
-static void
-acpi_rs_dump_irq (
- union acpi_resource_data *data)
+static void acpi_rs_dump_irq(union acpi_resource_data *data)
{
- struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("IRQ Resource\n");
+ acpi_os_printf("IRQ Resource\n");
- acpi_os_printf (" %s Triggered\n",
- ACPI_LEVEL_SENSITIVE == irq_data->edge_level ? "Level" : "Edge");
+ acpi_os_printf(" %s Triggered\n",
+ ACPI_LEVEL_SENSITIVE ==
+ irq_data->edge_level ? "Level" : "Edge");
- acpi_os_printf (" Active %s\n",
- ACPI_ACTIVE_LOW == irq_data->active_high_low ? "Low" : "High");
+ acpi_os_printf(" Active %s\n",
+ ACPI_ACTIVE_LOW ==
+ irq_data->active_high_low ? "Low" : "High");
- acpi_os_printf (" %s\n",
- ACPI_SHARED == irq_data->shared_exclusive ? "Shared" : "Exclusive");
+ acpi_os_printf(" %s\n",
+ ACPI_SHARED ==
+ irq_data->shared_exclusive ? "Shared" : "Exclusive");
- acpi_os_printf (" %X Interrupts ( ", irq_data->number_of_interrupts);
+ acpi_os_printf(" %X Interrupts ( ", irq_data->number_of_interrupts);
for (index = 0; index < irq_data->number_of_interrupts; index++) {
- acpi_os_printf ("%X ", irq_data->interrupts[index]);
+ acpi_os_printf("%X ", irq_data->interrupts[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_dma
@@ -161,75 +130,69 @@ acpi_rs_dump_irq (
*
******************************************************************************/
-static void
-acpi_rs_dump_dma (
- union acpi_resource_data *data)
+static void acpi_rs_dump_dma(union acpi_resource_data *data)
{
- struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("DMA Resource\n");
+ acpi_os_printf("DMA Resource\n");
switch (dma_data->type) {
case ACPI_COMPATIBILITY:
- acpi_os_printf (" Compatibility mode\n");
+ acpi_os_printf(" Compatibility mode\n");
break;
case ACPI_TYPE_A:
- acpi_os_printf (" Type A\n");
+ acpi_os_printf(" Type A\n");
break;
case ACPI_TYPE_B:
- acpi_os_printf (" Type B\n");
+ acpi_os_printf(" Type B\n");
break;
case ACPI_TYPE_F:
- acpi_os_printf (" Type F\n");
+ acpi_os_printf(" Type F\n");
break;
default:
- acpi_os_printf (" Invalid DMA type\n");
+ acpi_os_printf(" Invalid DMA type\n");
break;
}
- acpi_os_printf (" %sBus Master\n",
- ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
-
+ acpi_os_printf(" %sBus Master\n",
+ ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
switch (dma_data->transfer) {
case ACPI_TRANSFER_8:
- acpi_os_printf (" 8-bit only transfer\n");
+ acpi_os_printf(" 8-bit only transfer\n");
break;
case ACPI_TRANSFER_8_16:
- acpi_os_printf (" 8 and 16-bit transfer\n");
+ acpi_os_printf(" 8 and 16-bit transfer\n");
break;
case ACPI_TRANSFER_16:
- acpi_os_printf (" 16 bit only transfer\n");
+ acpi_os_printf(" 16 bit only transfer\n");
break;
default:
- acpi_os_printf (" Invalid transfer preference\n");
+ acpi_os_printf(" Invalid transfer preference\n");
break;
}
- acpi_os_printf (" Number of Channels: %X ( ",
- dma_data->number_of_channels);
+ acpi_os_printf(" Number of Channels: %X ( ",
+ dma_data->number_of_channels);
for (index = 0; index < dma_data->number_of_channels; index++) {
- acpi_os_printf ("%X ", dma_data->channels[index]);
+ acpi_os_printf("%X ", dma_data->channels[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_start_depend_fns
@@ -242,58 +205,54 @@ acpi_rs_dump_dma (
*
******************************************************************************/
-static void
-acpi_rs_dump_start_depend_fns (
- union acpi_resource_data *data)
+static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data)
{
- struct acpi_resource_start_dpf *sdf_data = (struct acpi_resource_start_dpf *) data;
-
+ struct acpi_resource_start_dpf *sdf_data =
+ (struct acpi_resource_start_dpf *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf ("Start Dependent Functions Resource\n");
+ acpi_os_printf("Start Dependent Functions Resource\n");
switch (sdf_data->compatibility_priority) {
case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf (" Good configuration\n");
+ acpi_os_printf(" Good configuration\n");
break;
case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf (" Acceptable configuration\n");
+ acpi_os_printf(" Acceptable configuration\n");
break;
case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf (" Sub-optimal configuration\n");
+ acpi_os_printf(" Sub-optimal configuration\n");
break;
default:
- acpi_os_printf (" Invalid compatibility priority\n");
+ acpi_os_printf(" Invalid compatibility priority\n");
break;
}
- switch(sdf_data->performance_robustness) {
+ switch (sdf_data->performance_robustness) {
case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf (" Good configuration\n");
+ acpi_os_printf(" Good configuration\n");
break;
case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf (" Acceptable configuration\n");
+ acpi_os_printf(" Acceptable configuration\n");
break;
case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf (" Sub-optimal configuration\n");
+ acpi_os_printf(" Sub-optimal configuration\n");
break;
default:
- acpi_os_printf (" Invalid performance robustness preference\n");
+ acpi_os_printf(" Invalid performance robustness preference\n");
break;
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_io
@@ -306,33 +265,30 @@ acpi_rs_dump_start_depend_fns (
*
******************************************************************************/
-static void
-acpi_rs_dump_io (
- union acpi_resource_data *data)
+static void acpi_rs_dump_io(union acpi_resource_data *data)
{
- struct acpi_resource_io *io_data = (struct acpi_resource_io *) data;
-
+ struct acpi_resource_io *io_data = (struct acpi_resource_io *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Io Resource\n");
- acpi_os_printf ("Io Resource\n");
+ acpi_os_printf(" %d bit decode\n",
+ ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
- acpi_os_printf (" %d bit decode\n",
- ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
+ acpi_os_printf(" Range minimum base: %08X\n",
+ io_data->min_base_address);
- acpi_os_printf (" Range minimum base: %08X\n", io_data->min_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ io_data->max_base_address);
- acpi_os_printf (" Range maximum base: %08X\n", io_data->max_base_address);
+ acpi_os_printf(" Alignment: %08X\n", io_data->alignment);
- acpi_os_printf (" Alignment: %08X\n", io_data->alignment);
-
- acpi_os_printf (" Range Length: %08X\n", io_data->range_length);
+ acpi_os_printf(" Range Length: %08X\n", io_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_fixed_io
@@ -345,25 +301,22 @@ acpi_rs_dump_io (
*
******************************************************************************/
-static void
-acpi_rs_dump_fixed_io (
- union acpi_resource_data *data)
+static void acpi_rs_dump_fixed_io(union acpi_resource_data *data)
{
- struct acpi_resource_fixed_io *fixed_io_data = (struct acpi_resource_fixed_io *) data;
-
+ struct acpi_resource_fixed_io *fixed_io_data =
+ (struct acpi_resource_fixed_io *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Fixed Io Resource\n");
+ acpi_os_printf(" Range base address: %08X",
+ fixed_io_data->base_address);
- acpi_os_printf ("Fixed Io Resource\n");
- acpi_os_printf (" Range base address: %08X", fixed_io_data->base_address);
-
- acpi_os_printf (" Range length: %08X", fixed_io_data->range_length);
+ acpi_os_printf(" Range length: %08X", fixed_io_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_vendor_specific
@@ -376,30 +329,26 @@ acpi_rs_dump_fixed_io (
*
******************************************************************************/
-static void
-acpi_rs_dump_vendor_specific (
- union acpi_resource_data *data)
+static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data)
{
- struct acpi_resource_vendor *vendor_data = (struct acpi_resource_vendor *) data;
- u16 index = 0;
-
+ struct acpi_resource_vendor *vendor_data =
+ (struct acpi_resource_vendor *)data;
+ u16 index = 0;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Vendor Specific Resource\n");
- acpi_os_printf ("Vendor Specific Resource\n");
-
- acpi_os_printf (" Length: %08X\n", vendor_data->length);
+ acpi_os_printf(" Length: %08X\n", vendor_data->length);
for (index = 0; index < vendor_data->length; index++) {
- acpi_os_printf (" Byte %X: %08X\n",
- index, vendor_data->reserved[index]);
+ acpi_os_printf(" Byte %X: %08X\n",
+ index, vendor_data->reserved[index]);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_memory24
@@ -412,37 +361,33 @@ acpi_rs_dump_vendor_specific (
*
******************************************************************************/
-static void
-acpi_rs_dump_memory24 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_memory24(union acpi_resource_data *data)
{
- struct acpi_resource_mem24 *memory24_data = (struct acpi_resource_mem24 *) data;
-
+ struct acpi_resource_mem24 *memory24_data =
+ (struct acpi_resource_mem24 *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("24-Bit Memory Range Resource\n");
- acpi_os_printf ("24-Bit Memory Range Resource\n");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ memory24_data->read_write_attribute ?
+ "/Write" : " only");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory24_data->read_write_attribute ?
- "/Write" : " only");
+ acpi_os_printf(" Range minimum base: %08X\n",
+ memory24_data->min_base_address);
- acpi_os_printf (" Range minimum base: %08X\n",
- memory24_data->min_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ memory24_data->max_base_address);
- acpi_os_printf (" Range maximum base: %08X\n",
- memory24_data->max_base_address);
+ acpi_os_printf(" Alignment: %08X\n", memory24_data->alignment);
- acpi_os_printf (" Alignment: %08X\n", memory24_data->alignment);
-
- acpi_os_printf (" Range length: %08X\n", memory24_data->range_length);
+ acpi_os_printf(" Range length: %08X\n", memory24_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_memory32
@@ -455,37 +400,33 @@ acpi_rs_dump_memory24 (
*
******************************************************************************/
-static void
-acpi_rs_dump_memory32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_memory32(union acpi_resource_data *data)
{
- struct acpi_resource_mem32 *memory32_data = (struct acpi_resource_mem32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_mem32 *memory32_data =
+ (struct acpi_resource_mem32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Memory Range Resource\n");
+ acpi_os_printf("32-Bit Memory Range Resource\n");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory32_data->read_write_attribute ?
- "/Write" : " only");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ memory32_data->read_write_attribute ?
+ "/Write" : " only");
- acpi_os_printf (" Range minimum base: %08X\n",
- memory32_data->min_base_address);
+ acpi_os_printf(" Range minimum base: %08X\n",
+ memory32_data->min_base_address);
- acpi_os_printf (" Range maximum base: %08X\n",
- memory32_data->max_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ memory32_data->max_base_address);
- acpi_os_printf (" Alignment: %08X\n", memory32_data->alignment);
+ acpi_os_printf(" Alignment: %08X\n", memory32_data->alignment);
- acpi_os_printf (" Range length: %08X\n", memory32_data->range_length);
+ acpi_os_printf(" Range length: %08X\n", memory32_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_fixed_memory32
@@ -498,33 +439,29 @@ acpi_rs_dump_memory32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_fixed_memory32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data)
{
- struct acpi_resource_fixed_mem32 *fixed_memory32_data =
- (struct acpi_resource_fixed_mem32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_fixed_mem32 *fixed_memory32_data =
+ (struct acpi_resource_fixed_mem32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Fixed Location Memory Range Resource\n");
+ acpi_os_printf("32-Bit Fixed Location Memory Range Resource\n");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- fixed_memory32_data->read_write_attribute ? "/Write" : " Only");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ fixed_memory32_data->
+ read_write_attribute ? "/Write" : " Only");
- acpi_os_printf (" Range base address: %08X\n",
- fixed_memory32_data->range_base_address);
+ acpi_os_printf(" Range base address: %08X\n",
+ fixed_memory32_data->range_base_address);
- acpi_os_printf (" Range length: %08X\n",
- fixed_memory32_data->range_length);
+ acpi_os_printf(" Range length: %08X\n",
+ fixed_memory32_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address16
@@ -537,134 +474,136 @@ acpi_rs_dump_fixed_memory32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address16 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address16(union acpi_resource_data *data)
{
- struct acpi_resource_address16 *address16_data = (struct acpi_resource_address16 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address16 *address16_data =
+ (struct acpi_resource_address16 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("16-Bit Address Space Resource\n");
- acpi_os_printf (" Resource Type: ");
+ acpi_os_printf("16-Bit Address Space Resource\n");
+ acpi_os_printf(" Resource Type: ");
switch (address16_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf ("Memory Range\n");
+ acpi_os_printf("Memory Range\n");
switch (address16_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address16_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address16_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf ("I/O Range\n");
+ acpi_os_printf("I/O Range\n");
switch (address16_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid range attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid range attribute\n");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address16_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address16_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf ("Bus Number Range\n");
+ acpi_os_printf("Bus Number Range\n");
break;
default:
- acpi_os_printf ("0x%2.2X\n", address16_data->resource_type);
+ acpi_os_printf("0x%2.2X\n", address16_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address16_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address16_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address16_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address16_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
- "" : "not");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
+ "" : "not");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
- "" : "not");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
+ "" : "not");
- acpi_os_printf (" Granularity: %08X\n",
- address16_data->granularity);
+ acpi_os_printf(" Granularity: %08X\n", address16_data->granularity);
- acpi_os_printf (" Address range min: %08X\n",
- address16_data->min_address_range);
+ acpi_os_printf(" Address range min: %08X\n",
+ address16_data->min_address_range);
- acpi_os_printf (" Address range max: %08X\n",
- address16_data->max_address_range);
+ acpi_os_printf(" Address range max: %08X\n",
+ address16_data->max_address_range);
- acpi_os_printf (" Address translation offset: %08X\n",
- address16_data->address_translation_offset);
+ acpi_os_printf(" Address translation offset: %08X\n",
+ address16_data->address_translation_offset);
- acpi_os_printf (" Address Length: %08X\n",
- address16_data->address_length);
+ acpi_os_printf(" Address Length: %08X\n",
+ address16_data->address_length);
if (0xFF != address16_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address16_data->resource_source.index);
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address16_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address16_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address16_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address32
@@ -677,134 +616,136 @@ acpi_rs_dump_address16 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address32(union acpi_resource_data *data)
{
- struct acpi_resource_address32 *address32_data = (struct acpi_resource_address32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address32 *address32_data =
+ (struct acpi_resource_address32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Address Space Resource\n");
+ acpi_os_printf("32-Bit Address Space Resource\n");
switch (address32_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf (" Resource Type: Memory Range\n");
+ acpi_os_printf(" Resource Type: Memory Range\n");
switch (address32_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address32_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address32_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf (" Resource Type: Io Range\n");
+ acpi_os_printf(" Resource Type: Io Range\n");
switch (address32_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid Range attribute");
+ acpi_os_printf
+ (" Type Specific: Invalid Range attribute");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address32_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address32_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf (" Resource Type: Bus Number Range\n");
+ acpi_os_printf(" Resource Type: Bus Number Range\n");
break;
default:
- acpi_os_printf (" Resource Type: 0x%2.2X\n",
- address32_data->resource_type);
+ acpi_os_printf(" Resource Type: 0x%2.2X\n",
+ address32_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address32_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address32_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address32_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address32_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Granularity: %08X\n",
- address32_data->granularity);
+ acpi_os_printf(" Granularity: %08X\n", address32_data->granularity);
- acpi_os_printf (" Address range min: %08X\n",
- address32_data->min_address_range);
+ acpi_os_printf(" Address range min: %08X\n",
+ address32_data->min_address_range);
- acpi_os_printf (" Address range max: %08X\n",
- address32_data->max_address_range);
+ acpi_os_printf(" Address range max: %08X\n",
+ address32_data->max_address_range);
- acpi_os_printf (" Address translation offset: %08X\n",
- address32_data->address_translation_offset);
+ acpi_os_printf(" Address translation offset: %08X\n",
+ address32_data->address_translation_offset);
- acpi_os_printf (" Address Length: %08X\n",
- address32_data->address_length);
+ acpi_os_printf(" Address Length: %08X\n",
+ address32_data->address_length);
- if(0xFF != address32_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address32_data->resource_source.index);
+ if (0xFF != address32_data->resource_source.index) {
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address32_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address32_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address32_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address64
@@ -817,137 +758,142 @@ acpi_rs_dump_address32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address64 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address64(union acpi_resource_data *data)
{
- struct acpi_resource_address64 *address64_data = (struct acpi_resource_address64 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address64 *address64_data =
+ (struct acpi_resource_address64 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("64-Bit Address Space Resource\n");
+ acpi_os_printf("64-Bit Address Space Resource\n");
switch (address64_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf (" Resource Type: Memory Range\n");
+ acpi_os_printf(" Resource Type: Memory Range\n");
switch (address64_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address64_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address64_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf (" Resource Type: Io Range\n");
+ acpi_os_printf(" Resource Type: Io Range\n");
switch (address64_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid Range attribute");
+ acpi_os_printf
+ (" Type Specific: Invalid Range attribute");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address64_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address64_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf (" Resource Type: Bus Number Range\n");
+ acpi_os_printf(" Resource Type: Bus Number Range\n");
break;
default:
- acpi_os_printf (" Resource Type: 0x%2.2X\n",
- address64_data->resource_type);
+ acpi_os_printf(" Resource Type: 0x%2.2X\n",
+ address64_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address64_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address64_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address64_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address64_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Granularity: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->granularity));
+ acpi_os_printf(" Granularity: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->granularity));
- acpi_os_printf (" Address range min: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->min_address_range));
+ acpi_os_printf(" Address range min: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->min_address_range));
- acpi_os_printf (" Address range max: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->max_address_range));
+ acpi_os_printf(" Address range max: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->max_address_range));
- acpi_os_printf (" Address translation offset: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->address_translation_offset));
+ acpi_os_printf(" Address translation offset: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->
+ address_translation_offset));
- acpi_os_printf (" Address Length: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->address_length));
+ acpi_os_printf(" Address Length: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->address_length));
- acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes));
+ acpi_os_printf(" Type Specific Attributes: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->
+ type_specific_attributes));
if (0xFF != address64_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address64_data->resource_source.index);
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address64_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address64_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address64_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_extended_irq
@@ -960,55 +906,52 @@ acpi_rs_dump_address64 (
*
******************************************************************************/
-static void
-acpi_rs_dump_extended_irq (
- union acpi_resource_data *data)
+static void acpi_rs_dump_extended_irq(union acpi_resource_data *data)
{
- struct acpi_resource_ext_irq *ext_irq_data = (struct acpi_resource_ext_irq *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_ext_irq *ext_irq_data =
+ (struct acpi_resource_ext_irq *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("Extended IRQ Resource\n");
+ acpi_os_printf("Extended IRQ Resource\n");
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == ext_irq_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == ext_irq_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s\n",
- ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
- "Level" : "Edge");
+ acpi_os_printf(" %s\n",
+ ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
+ "Level" : "Edge");
- acpi_os_printf (" Active %s\n",
- ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
- "low" : "high");
+ acpi_os_printf(" Active %s\n",
+ ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
+ "low" : "high");
- acpi_os_printf (" %s\n",
- ACPI_SHARED == ext_irq_data->shared_exclusive ?
- "Shared" : "Exclusive");
+ acpi_os_printf(" %s\n",
+ ACPI_SHARED == ext_irq_data->shared_exclusive ?
+ "Shared" : "Exclusive");
- acpi_os_printf (" Interrupts : %X ( ", ext_irq_data->number_of_interrupts);
+ acpi_os_printf(" Interrupts : %X ( ",
+ ext_irq_data->number_of_interrupts);
for (index = 0; index < ext_irq_data->number_of_interrupts; index++) {
- acpi_os_printf ("%X ", ext_irq_data->interrupts[index]);
+ acpi_os_printf("%X ", ext_irq_data->interrupts[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
- if(0xFF != ext_irq_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X",
- ext_irq_data->resource_source.index);
+ if (0xFF != ext_irq_data->resource_source.index) {
+ acpi_os_printf(" Resource Source Index: %X",
+ ext_irq_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s",
- ext_irq_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s",
+ ext_irq_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_resource_list
@@ -1021,92 +964,91 @@ acpi_rs_dump_extended_irq (
*
******************************************************************************/
-void
-acpi_rs_dump_resource_list (
- struct acpi_resource *resource)
+void acpi_rs_dump_resource_list(struct acpi_resource *resource)
{
- u8 count = 0;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u8 count = 0;
+ u8 done = FALSE;
+ ACPI_FUNCTION_ENTRY();
if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
while (!done) {
- acpi_os_printf ("Resource structure %X.\n", count++);
+ acpi_os_printf("Resource structure %X.\n", count++);
switch (resource->id) {
case ACPI_RSTYPE_IRQ:
- acpi_rs_dump_irq (&resource->data);
+ acpi_rs_dump_irq(&resource->data);
break;
case ACPI_RSTYPE_DMA:
- acpi_rs_dump_dma (&resource->data);
+ acpi_rs_dump_dma(&resource->data);
break;
case ACPI_RSTYPE_START_DPF:
- acpi_rs_dump_start_depend_fns (&resource->data);
+ acpi_rs_dump_start_depend_fns(&resource->data);
break;
case ACPI_RSTYPE_END_DPF:
- acpi_os_printf ("end_dependent_functions Resource\n");
- /* acpi_rs_dump_end_dependent_functions (Resource->Data);*/
+ acpi_os_printf
+ ("end_dependent_functions Resource\n");
+ /* acpi_rs_dump_end_dependent_functions (Resource->Data); */
break;
case ACPI_RSTYPE_IO:
- acpi_rs_dump_io (&resource->data);
+ acpi_rs_dump_io(&resource->data);
break;
case ACPI_RSTYPE_FIXED_IO:
- acpi_rs_dump_fixed_io (&resource->data);
+ acpi_rs_dump_fixed_io(&resource->data);
break;
case ACPI_RSTYPE_VENDOR:
- acpi_rs_dump_vendor_specific (&resource->data);
+ acpi_rs_dump_vendor_specific(&resource->data);
break;
case ACPI_RSTYPE_END_TAG:
- /*rs_dump_end_tag (Resource->Data);*/
- acpi_os_printf ("end_tag Resource\n");
+ /*rs_dump_end_tag (Resource->Data); */
+ acpi_os_printf("end_tag Resource\n");
done = TRUE;
break;
case ACPI_RSTYPE_MEM24:
- acpi_rs_dump_memory24 (&resource->data);
+ acpi_rs_dump_memory24(&resource->data);
break;
case ACPI_RSTYPE_MEM32:
- acpi_rs_dump_memory32 (&resource->data);
+ acpi_rs_dump_memory32(&resource->data);
break;
case ACPI_RSTYPE_FIXED_MEM32:
- acpi_rs_dump_fixed_memory32 (&resource->data);
+ acpi_rs_dump_fixed_memory32(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS16:
- acpi_rs_dump_address16 (&resource->data);
+ acpi_rs_dump_address16(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS32:
- acpi_rs_dump_address32 (&resource->data);
+ acpi_rs_dump_address32(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS64:
- acpi_rs_dump_address64 (&resource->data);
+ acpi_rs_dump_address64(&resource->data);
break;
case ACPI_RSTYPE_EXT_IRQ:
- acpi_rs_dump_extended_irq (&resource->data);
+ acpi_rs_dump_extended_irq(&resource->data);
break;
default:
- acpi_os_printf ("Invalid resource type\n");
+ acpi_os_printf("Invalid resource type\n");
break;
}
- resource = ACPI_PTR_ADD (struct acpi_resource, resource, resource->length);
+ resource =
+ ACPI_PTR_ADD(struct acpi_resource, resource,
+ resource->length);
}
}
@@ -1125,36 +1067,38 @@ acpi_rs_dump_resource_list (
*
******************************************************************************/
-void
-acpi_rs_dump_irq_list (
- u8 *route_table)
+void acpi_rs_dump_irq_list(u8 * route_table)
{
- u8 *buffer = route_table;
- u8 count = 0;
- u8 done = FALSE;
- struct acpi_pci_routing_table *prt_element;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u8 *buffer = route_table;
+ u8 count = 0;
+ u8 done = FALSE;
+ struct acpi_pci_routing_table *prt_element;
+ ACPI_FUNCTION_ENTRY();
if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
- prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ prt_element =
+ ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
while (!done) {
- acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++);
+ acpi_os_printf("PCI IRQ Routing Table structure %X.\n",
+ count++);
- acpi_os_printf (" Address: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (prt_element->address));
+ acpi_os_printf(" Address: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(prt_element->
+ address));
- acpi_os_printf (" Pin: %X\n", prt_element->pin);
+ acpi_os_printf(" Pin: %X\n", prt_element->pin);
- acpi_os_printf (" Source: %s\n", prt_element->source);
+ acpi_os_printf(" Source: %s\n", prt_element->source);
- acpi_os_printf (" source_index: %X\n", prt_element->source_index);
+ acpi_os_printf(" source_index: %X\n",
+ prt_element->source_index);
buffer += prt_element->length;
- prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ prt_element =
+ ACPI_CAST_PTR(struct acpi_pci_routing_table,
+ buffer);
if (0 == prt_element->length) {
done = TRUE;
}
@@ -1165,4 +1109,3 @@ acpi_rs_dump_irq_list (
}
#endif
-
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index 23a4d149fac8..d53bbe89e851 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsio")
-
+ACPI_MODULE_NAME("rsio")
/*******************************************************************************
*
@@ -69,24 +67,18 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_io);
-
-
- ACPI_FUNCTION_TRACE ("rs_io_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
+ ACPI_FUNCTION_TRACE("rs_io_resource");
/* The number of bytes consumed are Constant */
@@ -104,14 +96,14 @@ acpi_rs_io_resource (
/* Check min_base Address */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.io.min_base_address = temp16;
/* Check max_base Address */
buffer += 2;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.io.max_base_address = temp16;
@@ -136,10 +128,9 @@ acpi_rs_io_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_io_resource
@@ -162,22 +153,18 @@ acpi_rs_io_resource (
******************************************************************************/
acpi_status
-acpi_rs_fixed_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_fixed_io);
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_io_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
+ ACPI_FUNCTION_TRACE("rs_fixed_io_resource");
/* The number of bytes consumed are Constant */
@@ -188,7 +175,7 @@ acpi_rs_fixed_io_resource (
/* Check Range Base Address */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.fixed_io.base_address = temp16;
@@ -206,10 +193,9 @@ acpi_rs_fixed_io_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_io_stream
@@ -227,18 +213,14 @@ acpi_rs_fixed_io_resource (
******************************************************************************/
acpi_status
-acpi_rs_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_io_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_io_stream");
/* The descriptor field is static */
@@ -256,14 +238,14 @@ acpi_rs_io_stream (
temp16 = (u16) linked_list->data.io.min_base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Range maximum base address */
temp16 = (u16) linked_list->data.io.max_base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the base alignment */
@@ -282,11 +264,10 @@ acpi_rs_io_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_io_stream
@@ -304,18 +285,14 @@ acpi_rs_io_stream (
******************************************************************************/
acpi_status
-acpi_rs_fixed_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_io_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_fixed_io_stream");
/* The descriptor field is static */
@@ -327,7 +304,7 @@ acpi_rs_fixed_io_stream (
temp16 = (u16) linked_list->data.fixed_io.base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the range length */
@@ -339,11 +316,10 @@ acpi_rs_fixed_io_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dma_resource
@@ -366,23 +342,18 @@ acpi_rs_fixed_io_stream (
******************************************************************************/
acpi_status
-acpi_rs_dma_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_dma_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_dma);
-
-
- ACPI_FUNCTION_TRACE ("rs_dma_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u8 temp8 = 0;
+ u8 index;
+ u8 i;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma);
+ ACPI_FUNCTION_TRACE("rs_dma_resource");
/* The number of bytes consumed are Constant */
@@ -422,9 +393,9 @@ acpi_rs_dma_resource (
output_struct->data.dma.transfer = temp8 & 0x03;
if (0x03 == output_struct->data.dma.transfer) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid DMA.Transfer preference (3)\n"));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid DMA.Transfer preference (3)\n"));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Get bus master preference (Bit[2]) */
@@ -442,10 +413,9 @@ acpi_rs_dma_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dma_stream
@@ -463,19 +433,15 @@ acpi_rs_dma_resource (
******************************************************************************/
acpi_status
-acpi_rs_dma_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_dma_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_dma_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_dma_stream");
/* The descriptor field is static */
@@ -486,8 +452,7 @@ acpi_rs_dma_stream (
/* Loop through all of the Channels and set the mask bits */
for (index = 0;
- index < linked_list->data.dma.number_of_channels;
- index++) {
+ index < linked_list->data.dma.number_of_channels; index++) {
temp16 = (u16) linked_list->data.dma.channels[index];
temp8 |= 0x1 << temp16;
}
@@ -506,7 +471,6 @@ acpi_rs_dma_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 8a2b630be45b..56043fee96cb 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsirq")
-
+ACPI_MODULE_NAME("rsirq")
/*******************************************************************************
*
@@ -69,26 +67,20 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_irq);
-
-
- ACPI_FUNCTION_TRACE ("rs_irq_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ u8 i;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq);
+ ACPI_FUNCTION_TRACE("rs_irq_resource");
/*
* The number of bytes consumed are contained in the descriptor
@@ -101,7 +93,7 @@ acpi_rs_irq_resource (
/* Point to the 16-bits of Bytes 1 and 2 */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.irq.number_of_interrupts = 0;
@@ -132,14 +124,18 @@ acpi_rs_irq_resource (
/* Check for HE, LL interrupts */
switch (temp8 & 0x09) {
- case 0x01: /* HE */
- output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
- output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
+ case 0x01: /* HE */
+ output_struct->data.irq.edge_level =
+ ACPI_EDGE_SENSITIVE;
+ output_struct->data.irq.active_high_low =
+ ACPI_ACTIVE_HIGH;
break;
- case 0x08: /* LL */
- output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE;
- output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW;
+ case 0x08: /* LL */
+ output_struct->data.irq.edge_level =
+ ACPI_LEVEL_SENSITIVE;
+ output_struct->data.irq.active_high_low =
+ ACPI_ACTIVE_LOW;
break;
default:
@@ -148,17 +144,16 @@ acpi_rs_irq_resource (
* are allowed (ACPI spec, section "IRQ Format")
* so 0x00 and 0x09 are illegal.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid interrupt polarity/trigger in resource list, %X\n",
- temp8));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid interrupt polarity/trigger in resource list, %X\n",
+ temp8));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Check for sharable */
output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
- }
- else {
+ } else {
/*
* Assume Edge Sensitive, Active High, Non-Sharable
* per ACPI Specification
@@ -175,10 +170,9 @@ acpi_rs_irq_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_irq_stream
@@ -196,32 +190,27 @@ acpi_rs_irq_resource (
******************************************************************************/
acpi_status
-acpi_rs_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 IRqinfo_byte_needed;
-
-
- ACPI_FUNCTION_TRACE ("rs_irq_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ u8 IRqinfo_byte_needed;
+ ACPI_FUNCTION_TRACE("rs_irq_stream");
/*
* The descriptor field is set based upon whether a third byte is
* needed to contain the IRQ Information.
*/
if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
- ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
+ ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
+ ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
*buffer = 0x22;
IRqinfo_byte_needed = FALSE;
- }
- else {
+ } else {
*buffer = 0x23;
IRqinfo_byte_needed = TRUE;
}
@@ -231,14 +220,13 @@ acpi_rs_irq_stream (
/* Loop through all of the interrupts and set the mask bits */
- for(index = 0;
- index < linked_list->data.irq.number_of_interrupts;
- index++) {
+ for (index = 0;
+ index < linked_list->data.irq.number_of_interrupts; index++) {
temp8 = (u8) linked_list->data.irq.interrupts[index];
temp16 |= 0x1 << temp8;
}
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the IRQ Info byte if needed. */
@@ -246,13 +234,12 @@ acpi_rs_irq_stream (
if (IRqinfo_byte_needed) {
temp8 = 0;
temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
- 0x01) << 4);
+ 0x01) << 4);
if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
+ ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
temp8 |= 0x08;
- }
- else {
+ } else {
temp8 |= 0x01;
}
@@ -262,11 +249,10 @@ acpi_rs_irq_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_extended_irq_resource
@@ -289,34 +275,30 @@ acpi_rs_irq_stream (
******************************************************************************/
acpi_status
-acpi_rs_extended_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 *temp_ptr;
- u8 index;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_ext_irq);
-
-
- ACPI_FUNCTION_TRACE ("rs_extended_irq_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 *temp_ptr;
+ u8 index;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq);
+ ACPI_FUNCTION_TRACE("rs_extended_irq_resource");
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 6) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -338,7 +320,7 @@ acpi_rs_extended_irq_resource (
* - Edge/Level are defined opposite in the table vs the headers
*/
output_struct->data.extended_irq.edge_level =
- (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+ (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
/* Check Interrupt Polarity */
@@ -356,7 +338,7 @@ acpi_rs_extended_irq_resource (
/* Must have at least one IRQ */
if (temp8 < 1) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
output_struct->data.extended_irq.number_of_interrupts = temp8;
@@ -374,8 +356,8 @@ acpi_rs_extended_irq_resource (
/* Cycle through every IRQ in the table */
for (index = 0; index < temp8; index++) {
- ACPI_MOVE_32_TO_32 (
- &output_struct->data.extended_irq.interrupts[index], buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq.
+ interrupts[index], buffer);
/* Point to the next IRQ */
@@ -393,12 +375,13 @@ acpi_rs_extended_irq_resource (
* we add 1 to the length.
*/
if (*bytes_consumed >
- ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) +
- (5 + 1)) {
+ ((acpi_size) output_struct->data.extended_irq.number_of_interrupts *
+ 4) + (5 + 1)) {
/* Dereference the Index */
temp8 = *buffer;
- output_struct->data.extended_irq.resource_source.index = (u32) temp8;
+ output_struct->data.extended_irq.resource_source.index =
+ (u32) temp8;
/* Point to the String */
@@ -407,15 +390,15 @@ acpi_rs_extended_irq_resource (
/* Point the String pointer to the end of this structure. */
output_struct->data.extended_irq.resource_source.string_ptr =
- (char *)((char *) output_struct + struct_size);
+ (char *)((char *)output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.extended_irq.resource_source.string_ptr;
+ output_struct->data.extended_irq.resource_source.string_ptr;
/* Copy the string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
temp_ptr += 1;
@@ -425,8 +408,9 @@ acpi_rs_extended_irq_resource (
/* Add the terminating null */
- *temp_ptr = 0x00;
- output_struct->data.extended_irq.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.extended_irq.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -434,12 +418,13 @@ acpi_rs_extended_irq_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.extended_irq.resource_source.index = 0x00;
- output_struct->data.extended_irq.resource_source.string_length = 0;
- output_struct->data.extended_irq.resource_source.string_ptr = NULL;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.extended_irq.resource_source.index = 0;
+ output_struct->data.extended_irq.resource_source.string_length =
+ 0;
+ output_struct->data.extended_irq.resource_source.string_ptr =
+ NULL;
}
/* Set the Length parameter */
@@ -449,10 +434,9 @@ acpi_rs_extended_irq_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_extended_irq_stream
@@ -470,35 +454,31 @@ acpi_rs_extended_irq_resource (
******************************************************************************/
acpi_status
-acpi_rs_extended_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 *length_field;
- u8 temp8 = 0;
- u8 index;
- char *temp_pointer = NULL;
-
-
- ACPI_FUNCTION_TRACE ("rs_extended_irq_stream");
+ u8 *buffer = *output_buffer;
+ u16 *length_field;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_extended_irq_stream");
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x89;
+ *buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Interrupt vector flags */
- temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01);
- temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
+ temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01);
+ temp8 |=
+ ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
/*
* Set the Interrupt Mode
@@ -527,43 +507,46 @@ acpi_rs_extended_irq_stream (
*buffer = temp8;
buffer += 1;
- for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts;
- index++) {
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.extended_irq.interrupts[index]);
+ for (index = 0;
+ index < linked_list->data.extended_irq.number_of_interrupts;
+ index++) {
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.extended_irq.
+ interrupts[index]);
buffer += 4;
}
/* Resource Source Index and Resource Source are optional */
if (0 != linked_list->data.extended_irq.resource_source.string_length) {
- *buffer = (u8) linked_list->data.extended_irq.resource_source.index;
+ *buffer =
+ (u8) linked_list->data.extended_irq.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
/* Copy the string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.extended_irq.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.extended_irq.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size) (ACPI_STRLEN (
- linked_list->data.extended_irq.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.extended_irq.
+ resource_source.string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
* minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index db7bcb4e60e3..103eb31c284e 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rslist")
-
+ACPI_MODULE_NAME("rslist")
/*******************************************************************************
*
@@ -61,14 +59,10 @@
* a resource descriptor.
*
******************************************************************************/
-
-u8
-acpi_rs_get_resource_type (
- u8 resource_start_byte)
+u8 acpi_rs_get_resource_type(u8 resource_start_byte)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/* Determine if this is a small or large resource */
@@ -79,14 +73,12 @@ acpi_rs_get_resource_type (
return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK));
-
case ACPI_RDESC_TYPE_LARGE:
/* Large Resource Type -- All bits are valid */
return (resource_start_byte);
-
default:
/* Invalid type */
break;
@@ -95,7 +87,6 @@ acpi_rs_get_resource_type (
return (0xFF);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_byte_stream_to_list
@@ -113,176 +104,189 @@ acpi_rs_get_resource_type (
******************************************************************************/
acpi_status
-acpi_rs_byte_stream_to_list (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- u8 *output_buffer)
+acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, u8 * output_buffer)
{
- acpi_status status;
- acpi_size bytes_parsed = 0;
- u8 resource_type = 0;
- acpi_size bytes_consumed = 0;
- u8 *buffer = output_buffer;
- acpi_size structure_size = 0;
- u8 end_tag_processed = FALSE;
- struct acpi_resource *resource;
-
- ACPI_FUNCTION_TRACE ("rs_byte_stream_to_list");
-
-
- while (bytes_parsed < byte_stream_buffer_length &&
- !end_tag_processed) {
+ acpi_status status;
+ acpi_size bytes_parsed = 0;
+ u8 resource_type = 0;
+ acpi_size bytes_consumed = 0;
+ u8 *buffer = output_buffer;
+ acpi_size structure_size = 0;
+ u8 end_tag_processed = FALSE;
+ struct acpi_resource *resource;
+
+ ACPI_FUNCTION_TRACE("rs_byte_stream_to_list");
+
+ while (bytes_parsed < byte_stream_buffer_length && !end_tag_processed) {
/* The next byte in the stream is the resource type */
- resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
+ resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
switch (resource_type) {
case ACPI_RDESC_TYPE_MEMORY_24:
/*
* 24-Bit Memory Resource
*/
- status = acpi_rs_memory24_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_memory24_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_LARGE_VENDOR:
/*
* Vendor Defined Resource
*/
- status = acpi_rs_vendor_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_vendor_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_MEMORY_32:
/*
* 32-Bit Memory Range Resource
*/
- status = acpi_rs_memory32_range_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_memory32_range_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
/*
* 32-Bit Fixed Memory Resource
*/
- status = acpi_rs_fixed_memory32_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_fixed_memory32_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
*/
- status = acpi_rs_address64_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address64_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
/*
* 32-Bit Address Resource
*/
- status = acpi_rs_address32_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address32_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
/*
* 16-Bit Address Resource
*/
- status = acpi_rs_address16_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address16_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
/*
* Extended IRQ
*/
- status = acpi_rs_extended_irq_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_extended_irq_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_IRQ_FORMAT:
/*
* IRQ Resource
*/
- status = acpi_rs_irq_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_irq_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_DMA_FORMAT:
/*
* DMA Resource
*/
- status = acpi_rs_dma_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_dma_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_START_DEPENDENT:
/*
* Start Dependent Functions Resource
*/
- status = acpi_rs_start_depend_fns_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_start_depend_fns_resource
+ (byte_stream_buffer, &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_END_DEPENDENT:
/*
* End Dependent Functions Resource
*/
- status = acpi_rs_end_depend_fns_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_end_depend_fns_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_IO_PORT:
/*
* IO Port Resource
*/
- status = acpi_rs_io_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_io_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_FIXED_IO_PORT:
/*
* Fixed IO Port Resource
*/
- status = acpi_rs_fixed_io_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_fixed_io_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_SMALL_VENDOR:
/*
* Vendor Specific Resource
*/
- status = acpi_rs_vendor_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_vendor_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_END_TAG:
/*
* End Tag
*/
end_tag_processed = TRUE;
- status = acpi_rs_end_tag_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_end_tag_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
default:
/*
* Invalid/Unknown resource type
@@ -291,8 +295,8 @@ acpi_rs_byte_stream_to_list (
break;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Update the return value and counter */
@@ -305,21 +309,21 @@ acpi_rs_byte_stream_to_list (
/* Set the Buffer to the next structure */
- resource = ACPI_CAST_PTR (struct acpi_resource, buffer);
- resource->length = (u32) ACPI_ALIGN_RESOURCE_SIZE (resource->length);
- buffer += ACPI_ALIGN_RESOURCE_SIZE (structure_size);
+ resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
+ resource->length =
+ (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
+ buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size);
}
/* Check the reason for exiting the while loop */
if (!end_tag_processed) {
- return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_list_to_byte_stream
@@ -342,19 +346,16 @@ acpi_rs_byte_stream_to_list (
******************************************************************************/
acpi_status
-acpi_rs_list_to_byte_stream (
- struct acpi_resource *linked_list,
- acpi_size byte_stream_size_needed,
- u8 *output_buffer)
+acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
+ acpi_size byte_stream_size_needed,
+ u8 * output_buffer)
{
- acpi_status status;
- u8 *buffer = output_buffer;
- acpi_size bytes_consumed = 0;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("rs_list_to_byte_stream");
+ acpi_status status;
+ u8 *buffer = output_buffer;
+ acpi_size bytes_consumed = 0;
+ u8 done = FALSE;
+ ACPI_FUNCTION_TRACE("rs_list_to_byte_stream");
while (!done) {
switch (linked_list->id) {
@@ -362,58 +363,72 @@ acpi_rs_list_to_byte_stream (
/*
* IRQ Resource
*/
- status = acpi_rs_irq_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_irq_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_DMA:
/*
* DMA Resource
*/
- status = acpi_rs_dma_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_dma_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_START_DPF:
/*
* Start Dependent Functions Resource
*/
- status = acpi_rs_start_depend_fns_stream (linked_list,
- &buffer, &bytes_consumed);
+ status = acpi_rs_start_depend_fns_stream(linked_list,
+ &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_END_DPF:
/*
* End Dependent Functions Resource
*/
- status = acpi_rs_end_depend_fns_stream (linked_list,
- &buffer, &bytes_consumed);
+ status = acpi_rs_end_depend_fns_stream(linked_list,
+ &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_IO:
/*
* IO Port Resource
*/
- status = acpi_rs_io_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_io_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_FIXED_IO:
/*
* Fixed IO Port Resource
*/
- status = acpi_rs_fixed_io_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_fixed_io_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_VENDOR:
/*
* Vendor Defined Resource
*/
- status = acpi_rs_vendor_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_vendor_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_END_TAG:
/*
* End Tag
*/
- status = acpi_rs_end_tag_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_end_tag_stream(linked_list, &buffer,
+ &bytes_consumed);
/* An End Tag indicates the end of the Resource Template */
@@ -424,55 +439,60 @@ acpi_rs_list_to_byte_stream (
/*
* 24-Bit Memory Resource
*/
- status = acpi_rs_memory24_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_memory24_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_MEM32:
/*
* 32-Bit Memory Range Resource
*/
- status = acpi_rs_memory32_range_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_memory32_range_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_FIXED_MEM32:
/*
* 32-Bit Fixed Memory Resource
*/
- status = acpi_rs_fixed_memory32_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_fixed_memory32_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS16:
/*
* 16-Bit Address Descriptor Resource
*/
- status = acpi_rs_address16_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address16_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS32:
/*
* 32-Bit Address Descriptor Resource
*/
- status = acpi_rs_address32_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address32_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS64:
/*
* 64-Bit Address Descriptor Resource
*/
- status = acpi_rs_address64_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address64_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_EXT_IRQ:
/*
* Extended IRQ Resource
*/
- status = acpi_rs_extended_irq_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_extended_irq_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
default:
@@ -480,15 +500,15 @@ acpi_rs_list_to_byte_stream (
* If we get here, everything is out of sync,
* so exit with an error
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid descriptor type (%X) in resource list\n",
- linked_list->id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid descriptor type (%X) in resource list\n",
+ linked_list->id));
status = AE_BAD_DATA;
break;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Set the Buffer to point to the open byte */
@@ -497,10 +517,9 @@ acpi_rs_list_to_byte_stream (
/* Point to the next object */
- linked_list = ACPI_PTR_ADD (struct acpi_resource,
- linked_list, linked_list->length);
+ linked_list = ACPI_PTR_ADD(struct acpi_resource,
+ linked_list, linked_list->length);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
index 91d0207f01ac..daba1a1ed46d 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/resources/rsmemory.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsmemory")
-
+ACPI_MODULE_NAME("rsmemory")
/*******************************************************************************
*
@@ -69,30 +67,25 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_memory24_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_memory24_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_mem24);
-
-
- ACPI_FUNCTION_TRACE ("rs_memory24_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
+ ACPI_FUNCTION_TRACE("rs_memory24_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
output_struct->id = ACPI_RSTYPE_MEM24;
@@ -105,25 +98,25 @@ acpi_rs_memory24_resource (
/* Get min_base_address (Bytes 4-5) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.min_base_address = temp16;
/* Get max_base_address (Bytes 6-7) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.max_base_address = temp16;
/* Get Alignment (Bytes 8-9) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.alignment = temp16;
/* Get range_length (Bytes 10-11) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.memory24.range_length = temp16;
/* Set the Length parameter */
@@ -133,10 +126,9 @@ acpi_rs_memory24_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory24_stream
@@ -154,18 +146,14 @@ acpi_rs_memory24_resource (
******************************************************************************/
acpi_status
-acpi_rs_memory24_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_memory24_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_memory24_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_memory24_stream");
/* The descriptor field is static */
@@ -175,7 +163,7 @@ acpi_rs_memory24_stream (
/* The length field is static */
temp16 = 0x09;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
@@ -186,31 +174,32 @@ acpi_rs_memory24_stream (
/* Set the Range minimum base address */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.min_base_address);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.memory24.min_base_address);
buffer += 2;
/* Set the Range maximum base address */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.max_base_address);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.memory24.max_base_address);
buffer += 2;
/* Set the base alignment */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.alignment);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.alignment);
buffer += 2;
/* Set the range length */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.range_length);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.range_length);
buffer += 2;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory32_range_resource
@@ -233,28 +222,24 @@ acpi_rs_memory24_stream (
******************************************************************************/
acpi_status
-acpi_rs_memory32_range_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_mem32);
-
-
- ACPI_FUNCTION_TRACE ("rs_memory32_range_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
+ ACPI_FUNCTION_TRACE("rs_memory32_range_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
@@ -279,22 +264,24 @@ acpi_rs_memory32_range_resource (
/* Get min_base_address (Bytes 4-7) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.min_base_address, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.min_base_address,
+ buffer);
buffer += 4;
/* Get max_base_address (Bytes 8-11) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.max_base_address, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.max_base_address,
+ buffer);
buffer += 4;
/* Get Alignment (Bytes 12-15) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.alignment, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.alignment, buffer);
buffer += 4;
/* Get range_length (Bytes 16-19) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.range_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.range_length, buffer);
/* Set the Length parameter */
@@ -303,10 +290,9 @@ acpi_rs_memory32_range_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_memory32_resource
@@ -329,27 +315,23 @@ acpi_rs_memory32_range_resource (
******************************************************************************/
acpi_status
-acpi_rs_fixed_memory32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_fixed_mem32);
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_memory32_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32);
+ ACPI_FUNCTION_TRACE("rs_fixed_memory32_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
@@ -364,13 +346,14 @@ acpi_rs_fixed_memory32_resource (
/* Get range_base_address (Bytes 4-7) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_base_address,
- buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.
+ range_base_address, buffer);
buffer += 4;
/* Get range_length (Bytes 8-11) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.range_length,
+ buffer);
/* Set the Length parameter */
@@ -379,10 +362,9 @@ acpi_rs_fixed_memory32_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory32_range_stream
@@ -400,18 +382,14 @@ acpi_rs_fixed_memory32_resource (
******************************************************************************/
acpi_status
-acpi_rs_memory32_range_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_memory32_range_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_memory32_range_stream");
/* The descriptor field is static */
@@ -422,7 +400,7 @@ acpi_rs_memory32_range_stream (
temp16 = 0x11;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
@@ -433,31 +411,32 @@ acpi_rs_memory32_range_stream (
/* Set the Range minimum base address */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.min_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.memory32.min_base_address);
buffer += 4;
/* Set the Range maximum base address */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.max_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.memory32.max_base_address);
buffer += 4;
/* Set the base alignment */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.alignment);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.alignment);
buffer += 4;
/* Set the range length */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.range_length);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.range_length);
buffer += 4;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_memory32_stream
@@ -475,18 +454,14 @@ acpi_rs_memory32_range_stream (
******************************************************************************/
acpi_status
-acpi_rs_fixed_memory32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_memory32_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_fixed_memory32_stream");
/* The descriptor field is static */
@@ -497,30 +472,31 @@ acpi_rs_fixed_memory32_stream (
temp16 = 0x09;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
- temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
+ temp8 =
+ (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
*buffer = temp8;
buffer += 1;
/* Set the Range base address */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.fixed_memory32.range_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.fixed_memory32.
+ range_base_address);
buffer += 4;
/* Set the range length */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.fixed_memory32.range_length);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.fixed_memory32.range_length);
buffer += 4;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index a1f1741f0d83..7a8a34e757f5 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsmisc")
-
+ACPI_MODULE_NAME("rsmisc")
/*******************************************************************************
*
@@ -69,20 +67,15 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_end_tag_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_tag_resource");
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+ ACPI_FUNCTION_TRACE("rs_end_tag_resource");
/* The number of bytes consumed is static */
@@ -99,10 +92,9 @@ acpi_rs_end_tag_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_tag_stream
@@ -120,17 +112,13 @@ acpi_rs_end_tag_resource (
******************************************************************************/
acpi_status
-acpi_rs_end_tag_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_tag_stream");
+ u8 *buffer = *output_buffer;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_end_tag_stream");
/* The descriptor field is static */
@@ -148,11 +136,10 @@ acpi_rs_end_tag_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_vendor_resource
@@ -175,23 +162,19 @@ acpi_rs_end_tag_stream (
******************************************************************************/
acpi_status
-acpi_rs_vendor_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_vendor_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_vendor);
-
-
- ACPI_FUNCTION_TRACE ("rs_vendor_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor);
+ ACPI_FUNCTION_TRACE("rs_vendor_resource");
/* Dereference the Descriptor to find if this is a large or small item. */
@@ -204,7 +187,7 @@ acpi_rs_vendor_resource (
/* Dereference */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Calculate bytes consumed */
@@ -213,11 +196,10 @@ acpi_rs_vendor_resource (
/* Point to the first vendor byte */
buffer += 2;
- }
- else {
+ } else {
/* Small Item, dereference the size */
- temp16 = (u8)(*buffer & 0x07);
+ temp16 = (u8) (*buffer & 0x07);
/* Calculate bytes consumed */
@@ -241,7 +223,7 @@ acpi_rs_vendor_resource (
* calculate the length of the vendor string and expand the
* struct_size to the next 32-bit boundary.
*/
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp16);
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp16);
/* Set the Length parameter */
@@ -250,10 +232,9 @@ acpi_rs_vendor_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_vendor_stream
@@ -271,23 +252,19 @@ acpi_rs_vendor_resource (
******************************************************************************/
acpi_status
-acpi_rs_vendor_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_vendor_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_vendor_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_vendor_stream");
/* Dereference the length to find if this is a large or small item. */
- if(linked_list->data.vendor_specific.length > 7) {
+ if (linked_list->data.vendor_specific.length > 7) {
/* Large Item, Set the descriptor field and length bytes */
*buffer = 0x84;
@@ -295,10 +272,9 @@ acpi_rs_vendor_stream (
temp16 = (u16) linked_list->data.vendor_specific.length;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
- }
- else {
+ } else {
/* Small Item, Set the descriptor field */
temp8 = 0x70;
@@ -310,7 +286,8 @@ acpi_rs_vendor_stream (
/* Loop through all of the Vendor Specific fields */
- for (index = 0; index < linked_list->data.vendor_specific.length; index++) {
+ for (index = 0; index < linked_list->data.vendor_specific.length;
+ index++) {
temp8 = linked_list->data.vendor_specific.reserved[index];
*buffer = temp8;
@@ -319,11 +296,10 @@ acpi_rs_vendor_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_start_depend_fns_resource
@@ -346,21 +322,18 @@ acpi_rs_vendor_stream (
******************************************************************************/
acpi_status
-acpi_rs_start_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_start_dpf);
-
-
- ACPI_FUNCTION_TRACE ("rs_start_depend_fns_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf);
+ ACPI_FUNCTION_TRACE("rs_start_depend_fns_resource");
/* The number of bytes consumed are found in the descriptor (Bits:0-1) */
@@ -378,26 +351,27 @@ acpi_rs_start_depend_fns_resource (
/* Check Compatibility priority */
- output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03;
+ output_struct->data.start_dpf.compatibility_priority =
+ temp8 & 0x03;
if (3 == output_struct->data.start_dpf.compatibility_priority) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
}
/* Check Performance/Robustness preference */
- output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03;
+ output_struct->data.start_dpf.performance_robustness =
+ (temp8 >> 2) & 0x03;
if (3 == output_struct->data.start_dpf.performance_robustness) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
}
- }
- else {
+ } else {
output_struct->data.start_dpf.compatibility_priority =
- ACPI_ACCEPTABLE_CONFIGURATION;
+ ACPI_ACCEPTABLE_CONFIGURATION;
output_struct->data.start_dpf.performance_robustness =
- ACPI_ACCEPTABLE_CONFIGURATION;
+ ACPI_ACCEPTABLE_CONFIGURATION;
}
/* Set the Length parameter */
@@ -407,10 +381,9 @@ acpi_rs_start_depend_fns_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_depend_fns_resource
@@ -433,18 +406,14 @@ acpi_rs_start_depend_fns_resource (
******************************************************************************/
acpi_status
-acpi_rs_end_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_depend_fns_resource");
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+ ACPI_FUNCTION_TRACE("rs_end_depend_fns_resource");
/* The number of bytes consumed is static */
@@ -461,10 +430,9 @@ acpi_rs_end_depend_fns_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_start_depend_fns_stream
@@ -483,39 +451,35 @@ acpi_rs_end_depend_fns_resource (
******************************************************************************/
acpi_status
-acpi_rs_start_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_start_depend_fns_stream");
+ u8 *buffer = *output_buffer;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_start_depend_fns_stream");
/*
* The descriptor field is set based upon whether a byte is needed
* to contain Priority data.
*/
if (ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.compatibility_priority &&
- ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.performance_robustness) {
+ linked_list->data.start_dpf.compatibility_priority &&
+ ACPI_ACCEPTABLE_CONFIGURATION ==
+ linked_list->data.start_dpf.performance_robustness) {
*buffer = 0x30;
- }
- else {
+ } else {
*buffer = 0x31;
buffer += 1;
/* Set the Priority Byte Definition */
temp8 = 0;
- temp8 = (u8) ((linked_list->data.start_dpf.performance_robustness &
- 0x03) << 2);
- temp8 |= (linked_list->data.start_dpf.compatibility_priority &
- 0x03);
+ temp8 =
+ (u8) ((linked_list->data.start_dpf.
+ performance_robustness & 0x03) << 2);
+ temp8 |=
+ (linked_list->data.start_dpf.compatibility_priority & 0x03);
*buffer = temp8;
}
@@ -523,11 +487,10 @@ acpi_rs_start_depend_fns_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_depend_fns_stream
@@ -545,16 +508,12 @@ acpi_rs_start_depend_fns_stream (
******************************************************************************/
acpi_status
-acpi_rs_end_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_depend_fns_stream");
+ u8 *buffer = *output_buffer;
+ ACPI_FUNCTION_TRACE("rs_end_depend_fns_stream");
/* The descriptor field is static */
@@ -563,7 +522,6 @@ acpi_rs_end_depend_fns_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 700cf7d65d76..4446778eaf79 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -41,15 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acresrc.h>
-
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsutils")
-
+ACPI_MODULE_NAME("rsutils")
/*******************************************************************************
*
@@ -68,42 +65,36 @@
* and the contents of the callers buffer is undefined.
*
******************************************************************************/
-
acpi_status
-acpi_rs_get_prt_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_prt_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ 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,
- ACPI_BTYPE_PACKAGE, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
+ ACPI_BTYPE_PACKAGE, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Create a resource linked list from the byte stream buffer that comes
* back from the _CRS method execution.
*/
- status = acpi_rs_create_pci_routing_table (obj_desc, ret_buffer);
+ status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
/* On exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_crs_method_data
@@ -123,25 +114,21 @@ acpi_rs_get_prt_method_data (
******************************************************************************/
acpi_status
-acpi_rs_get_crs_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_crs_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ 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,
- ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
+ ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -149,15 +136,14 @@ acpi_rs_get_crs_method_data (
* byte stream buffer that comes back from the _CRS method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* on exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_prs_method_data
@@ -178,25 +164,21 @@ acpi_rs_get_crs_method_data (
#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(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_prs_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ 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,
- ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
+ ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -204,15 +186,14 @@ acpi_rs_get_prs_method_data (
* byte stream buffer that comes back from the _CRS method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* on exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -234,25 +215,22 @@ acpi_rs_get_prs_method_data (
******************************************************************************/
acpi_status
-acpi_rs_get_method_data (
- acpi_handle handle,
- char *path,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_method_data(acpi_handle handle,
+ char *path, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("rs_get_method_data");
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object (handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -260,12 +238,12 @@ acpi_rs_get_method_data (
* byte stream buffer that comes back from the method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* On exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -287,18 +265,14 @@ acpi_rs_get_method_data (
******************************************************************************/
acpi_status
-acpi_rs_set_srs_method_data (
- acpi_handle handle,
- struct acpi_buffer *in_buffer)
+acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[2];
- acpi_status status;
- struct acpi_buffer buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_set_srs_method_data");
+ struct acpi_parameter_info info;
+ union acpi_operand_object *params[2];
+ acpi_status status;
+ struct acpi_buffer buffer;
+ ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
/* Parameters guaranteed valid by caller */
@@ -310,24 +284,24 @@ acpi_rs_set_srs_method_data (
* Convert the linked list into a byte stream
*/
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_rs_create_byte_stream (in_buffer->pointer, &buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Init the param object */
- params[0] = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
if (!params[0]) {
- acpi_os_free (buffer.pointer);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Set up the parameter object */
- params[0]->buffer.length = (u32) buffer.length;
+ params[0]->buffer.length = (u32) buffer.length;
params[0]->buffer.pointer = buffer.pointer;
- params[0]->common.flags = AOPOBJ_DATA_VALID;
+ params[0]->common.flags = AOPOBJ_DATA_VALID;
params[1] = NULL;
info.node = handle;
@@ -336,18 +310,17 @@ acpi_rs_set_srs_method_data (
/* Execute the method, no return value */
- status = acpi_ns_evaluate_relative (METHOD_NAME__SRS, &info);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
+ if (ACPI_SUCCESS(status)) {
/* Delete any return object (especially if implicit_return is enabled) */
if (info.return_object) {
- acpi_ut_remove_reference (info.return_object);
+ acpi_ut_remove_reference(info.return_object);
}
}
/* Clean up and return the status from acpi_ns_evaluate_relative */
- acpi_ut_remove_reference (params[0]);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(params[0]);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 83c944b8b097..ee5a5c509199 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -47,10 +47,9 @@
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsxface")
+ACPI_MODULE_NAME("rsxface")
/* Local macros for 16,32-bit to 64-bit conversion */
-
#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)
#define ACPI_COPY_ADDRESS(out, in) \
ACPI_COPY_FIELD(out, in, resource_type); \
@@ -65,8 +64,6 @@
ACPI_COPY_FIELD(out, in, address_translation_offset); \
ACPI_COPY_FIELD(out, in, address_length); \
ACPI_COPY_FIELD(out, in, resource_source);
-
-
/*******************************************************************************
*
* FUNCTION: acpi_get_irq_routing_table
@@ -89,17 +86,13 @@
* the object indicated by the passed device_handle.
*
******************************************************************************/
-
acpi_status
-acpi_get_irq_routing_table (
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_irq_routing_table(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_irq_routing_table ");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table ");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -108,19 +101,18 @@ acpi_get_irq_routing_table (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prt_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_prt_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_current_resources
@@ -146,15 +138,12 @@ acpi_get_irq_routing_table (
******************************************************************************/
acpi_status
-acpi_get_current_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;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_current_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_current_resources");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -163,19 +152,19 @@ acpi_get_current_resources (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_crs_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_crs_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_current_resources);
+EXPORT_SYMBOL(acpi_get_current_resources);
/*******************************************************************************
*
@@ -200,15 +189,12 @@ EXPORT_SYMBOL(acpi_get_current_resources);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_possible_resources (
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_possible_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_possible_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_possible_resources");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -217,20 +203,20 @@ acpi_get_possible_resources (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prs_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_prs_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_possible_resources);
-#endif /* ACPI_FUTURE_USAGE */
+EXPORT_SYMBOL(acpi_get_possible_resources);
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -252,37 +238,33 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
******************************************************************************/
acpi_status
-acpi_walk_resources (
- acpi_handle device_handle,
- char *path,
- ACPI_WALK_RESOURCE_CALLBACK user_function,
- void *context)
+acpi_walk_resources(acpi_handle device_handle,
+ char *path,
+ ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
{
- acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_resource *resource;
- struct acpi_resource *buffer_end;
-
-
- ACPI_FUNCTION_TRACE ("acpi_walk_resources");
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_resource *resource;
+ struct acpi_resource *buffer_end;
+ ACPI_FUNCTION_TRACE("acpi_walk_resources");
if (!device_handle ||
- (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) &&
- ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
+ ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_rs_get_method_data (device_handle, path, &buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_method_data(device_handle, path, &buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Setup pointers */
- resource = (struct acpi_resource *) buffer.pointer;
- buffer_end = ACPI_CAST_PTR (struct acpi_resource,
- ((u8 *) buffer.pointer + buffer.length));
+ resource = (struct acpi_resource *)buffer.pointer;
+ buffer_end = ACPI_CAST_PTR(struct acpi_resource,
+ ((u8 *) buffer.pointer + buffer.length));
/* Walk the resource list */
@@ -291,7 +273,7 @@ acpi_walk_resources (
break;
}
- status = user_function (resource, context);
+ status = user_function(resource, context);
switch (status) {
case AE_OK:
@@ -318,7 +300,7 @@ acpi_walk_resources (
/* Get the next resource descriptor */
- resource = ACPI_NEXT_RESOURCE (resource);
+ resource = ACPI_NEXT_RESOURCE(resource);
/* Check for end-of-buffer */
@@ -327,13 +309,13 @@ acpi_walk_resources (
}
}
-cleanup:
+ cleanup:
- acpi_os_free (buffer.pointer);
- return_ACPI_STATUS (status);
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_resources);
+EXPORT_SYMBOL(acpi_walk_resources);
/*******************************************************************************
*
@@ -354,30 +336,25 @@ EXPORT_SYMBOL(acpi_walk_resources);
******************************************************************************/
acpi_status
-acpi_set_current_resources (
- acpi_handle device_handle,
- struct acpi_buffer *in_buffer)
+acpi_set_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *in_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_set_current_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_set_current_resources");
/* Must have a valid handle and buffer */
- if ((!device_handle) ||
- (!in_buffer) ||
- (!in_buffer->pointer) ||
- (!in_buffer->length)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device_handle) ||
+ (!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);
- return_ACPI_STATUS (status);
+ status = acpi_rs_set_srs_method_data(device_handle, in_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_current_resources);
+EXPORT_SYMBOL(acpi_set_current_resources);
/******************************************************************************
*
@@ -398,41 +375,38 @@ EXPORT_SYMBOL(acpi_set_current_resources);
******************************************************************************/
acpi_status
-acpi_resource_to_address64 (
- struct acpi_resource *resource,
- struct acpi_resource_address64 *out)
+acpi_resource_to_address64(struct acpi_resource *resource,
+ struct acpi_resource_address64 *out)
{
- struct acpi_resource_address16 *address16;
- struct acpi_resource_address32 *address32;
-
+ struct acpi_resource_address16 *address16;
+ struct acpi_resource_address32 *address32;
switch (resource->id) {
case ACPI_RSTYPE_ADDRESS16:
- address16 = (struct acpi_resource_address16 *) &resource->data;
- ACPI_COPY_ADDRESS (out, address16);
+ address16 = (struct acpi_resource_address16 *)&resource->data;
+ ACPI_COPY_ADDRESS(out, address16);
break;
-
case ACPI_RSTYPE_ADDRESS32:
- address32 = (struct acpi_resource_address32 *) &resource->data;
- ACPI_COPY_ADDRESS (out, address32);
+ address32 = (struct acpi_resource_address32 *)&resource->data;
+ ACPI_COPY_ADDRESS(out, address32);
break;
-
case ACPI_RSTYPE_ADDRESS64:
/* Simple copy for 64 bit source */
- ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64));
+ ACPI_MEMCPY(out, &resource->data,
+ sizeof(struct acpi_resource_address64));
break;
-
default:
return (AE_BAD_PARAMETER);
}
return (AE_OK);
}
+
EXPORT_SYMBOL(acpi_resource_to_address64);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index cbcda30c172d..c6db591479de 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -9,14 +9,10 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("scan")
-
+ACPI_MODULE_NAME("scan")
#define STRUCT_TO_INT(s) (*((int*)&s))
-
-extern struct acpi_device *acpi_root;
-
+extern struct acpi_device *acpi_root;
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "ACPI_BUS"
@@ -27,13 +23,11 @@ static LIST_HEAD(acpi_device_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
-static int
-acpi_bus_trim(struct acpi_device *start,
- int rmdevice);
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice);
-static void acpi_device_release(struct kobject * kobj)
+static void acpi_device_release(struct kobject *kobj)
{
- struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
+ struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
if (dev->pnp.cid_list)
kfree(dev->pnp.cid_list);
kfree(dev);
@@ -41,34 +35,34 @@ static void acpi_device_release(struct kobject * kobj)
struct acpi_device_attribute {
struct attribute attr;
- ssize_t (*show)(struct acpi_device *, char *);
- ssize_t (*store)(struct acpi_device *, const char *, size_t);
+ ssize_t(*show) (struct acpi_device *, char *);
+ ssize_t(*store) (struct acpi_device *, const char *, size_t);
};
typedef void acpi_device_sysfs_files(struct kobject *,
- const struct attribute *);
+ const struct attribute *);
static void setup_sys_fs_device_files(struct acpi_device *dev,
- acpi_device_sysfs_files *func);
+ acpi_device_sysfs_files * func);
#define create_sysfs_device_files(dev) \
setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
#define remove_sysfs_device_files(dev) \
setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file)
-
#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr);
static ssize_t acpi_device_attr_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct attribute *attr, char *buf)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
return attribute->show ? attribute->show(device, buf) : -EIO;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t len)
+ struct attribute *attr, const char *buf,
+ size_t len)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
@@ -76,13 +70,13 @@ static ssize_t acpi_device_attr_store(struct kobject *kobj,
}
static struct sysfs_ops acpi_device_sysfs_ops = {
- .show = acpi_device_attr_show,
- .store = acpi_device_attr_store,
+ .show = acpi_device_attr_show,
+ .store = acpi_device_attr_store,
};
static struct kobj_type ktype_acpi_ns = {
- .sysfs_ops = &acpi_device_sysfs_ops,
- .release = acpi_device_release,
+ .sysfs_ops = &acpi_device_sysfs_ops,
+ .release = acpi_device_release,
};
static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
@@ -110,16 +104,16 @@ static struct kset_hotplug_ops namespace_hotplug_ops = {
};
static struct kset acpi_namespace_kset = {
- .kobj = {
- .name = "namespace",
- },
+ .kobj = {
+ .name = "namespace",
+ },
.subsys = &acpi_subsys,
- .ktype = &ktype_acpi_ns,
+ .ktype = &ktype_acpi_ns,
.hotplug_ops = &namespace_hotplug_ops,
};
-
-static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
+static void acpi_device_register(struct acpi_device *device,
+ struct acpi_device *parent)
{
/*
* Linkage
@@ -134,14 +128,14 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
spin_lock(&acpi_device_lock);
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
- list_add_tail(&device->g_list,&device->parent->g_list);
+ list_add_tail(&device->g_list, &device->parent->g_list);
} else
- list_add_tail(&device->g_list,&acpi_device_list);
+ list_add_tail(&device->g_list, &acpi_device_list);
if (device->wakeup.flags.valid)
- list_add_tail(&device->wakeup_list,&acpi_wakeup_device_list);
+ list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
spin_unlock(&acpi_device_lock);
- strlcpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
+ strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN);
if (parent)
device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns;
@@ -150,10 +144,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
create_sysfs_device_files(device);
}
-static int
-acpi_device_unregister (
- struct acpi_device *device,
- int type)
+static int acpi_device_unregister(struct acpi_device *device, int type)
{
spin_lock(&acpi_device_lock);
if (device->parent) {
@@ -172,11 +163,7 @@ acpi_device_unregister (
return 0;
}
-void
-acpi_bus_data_handler (
- acpi_handle handle,
- u32 function,
- void *context)
+void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
{
ACPI_FUNCTION_TRACE("acpi_bus_data_handler");
@@ -185,13 +172,11 @@ acpi_bus_data_handler (
return_VOID;
}
-static int
-acpi_bus_get_power_flags (
- struct acpi_device *device)
+static int acpi_bus_get_power_flags(struct acpi_device *device)
{
- acpi_status status = 0;
- acpi_handle handle = NULL;
- u32 i = 0;
+ acpi_status status = 0;
+ acpi_handle handle = NULL;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags");
@@ -210,11 +195,11 @@ acpi_bus_get_power_flags (
*/
for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
struct acpi_device_power_state *ps = &device->power.states[i];
- char object_name[5] = {'_','P','R','0'+i,'\0'};
+ char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
/* Evaluate "_PRx" to se if power resources are referenced */
acpi_evaluate_reference(device->handle, object_name, NULL,
- &ps->resources);
+ &ps->resources);
if (ps->resources.count) {
device->power.flags.power_resources = 1;
ps->flags.valid = 1;
@@ -232,7 +217,7 @@ acpi_bus_get_power_flags (
if (ps->resources.count || ps->flags.explicit_set)
ps->flags.valid = 1;
- ps->power = -1; /* Unknown - driver assigned */
+ ps->power = -1; /* Unknown - driver assigned */
ps->latency = -1; /* Unknown - driver assigned */
}
@@ -249,13 +234,10 @@ acpi_bus_get_power_flags (
return_VALUE(0);
}
-int
-acpi_match_ids (
- struct acpi_device *device,
- char *ids)
+int acpi_match_ids(struct acpi_device *device, char *ids)
{
int error = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (device->flags.hardware_id)
if (strstr(ids, device->pnp.hardware_id))
@@ -266,27 +248,25 @@ acpi_match_ids (
int i;
/* compare multiple _CID entries against driver ids */
- for (i = 0; i < cid_list->count; i++)
- {
+ for (i = 0; i < cid_list->count; i++) {
if (strstr(ids, cid_list->id[i].value))
goto Done;
}
}
error = -ENOENT;
- Done:
+ Done:
if (buffer.pointer)
acpi_os_free(buffer.pointer);
return error;
}
static acpi_status
-acpi_bus_extract_wakeup_device_power_package (
- struct acpi_device *device,
- union acpi_object *package)
+acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
+ union acpi_object *package)
{
- int i = 0;
- union acpi_object *element = NULL;
+ int i = 0;
+ union acpi_object *element = NULL;
if (!device || !package || (package->package.count < 2))
return AE_BAD_PARAMETER;
@@ -296,14 +276,17 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_BAD_PARAMETER;
if (element->type == ACPI_TYPE_PACKAGE) {
if ((element->package.count < 2) ||
- (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) ||
- (element->package.elements[1].type != ACPI_TYPE_INTEGER))
+ (element->package.elements[0].type !=
+ ACPI_TYPE_LOCAL_REFERENCE)
+ || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
return AE_BAD_DATA;
- device->wakeup.gpe_device = element->package.elements[0].reference.handle;
- device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value;
- }else if (element->type == ACPI_TYPE_INTEGER) {
+ device->wakeup.gpe_device =
+ element->package.elements[0].reference.handle;
+ device->wakeup.gpe_number =
+ (u32) element->package.elements[1].integer.value;
+ } else if (element->type == ACPI_TYPE_INTEGER) {
device->wakeup.gpe_number = element->integer.value;
- }else
+ } else
return AE_BAD_DATA;
element = &(package->package.elements[1]);
@@ -316,9 +299,9 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_NO_MEMORY;
}
device->wakeup.resources.count = package->package.count - 2;
- for (i=0; i < device->wakeup.resources.count; i++) {
+ for (i = 0; i < device->wakeup.resources.count; i++) {
element = &(package->package.elements[i + 2]);
- if (element->type != ACPI_TYPE_ANY ) {
+ if (element->type != ACPI_TYPE_ANY) {
return AE_BAD_DATA;
}
@@ -328,13 +311,11 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_OK;
}
-static int
-acpi_bus_get_wakeup_device_flags (
- struct acpi_device *device)
+static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
{
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *package = NULL;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
@@ -345,21 +326,22 @@ acpi_bus_get_wakeup_device_flags (
goto end;
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
status = acpi_bus_extract_wakeup_device_power_package(device, package);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error extracting _PRW package\n"));
goto end;
}
acpi_os_free(buffer.pointer);
device->wakeup.flags.valid = 1;
- /* Power button, Lid switch always enable wakeup*/
+ /* Power button, Lid switch always enable wakeup */
if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
device->wakeup.flags.run_wake = 1;
-end:
+ end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
return_VALUE(0);
@@ -368,8 +350,8 @@ end:
/* --------------------------------------------------------------------------
ACPI hotplug sysfs device file support
-------------------------------------------------------------------------- */
-static ssize_t acpi_eject_store(struct acpi_device *device,
- const char *buf, size_t count);
+static ssize_t acpi_eject_store(struct acpi_device *device,
+ const char *buf, size_t count);
#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
static struct acpi_device_attribute acpi_device_attr_##_name = \
@@ -383,12 +365,11 @@ ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
* @func: function pointer to create or destroy the device file
*/
static void
-setup_sys_fs_device_files (
- struct acpi_device *dev,
- acpi_device_sysfs_files *func)
+setup_sys_fs_device_files(struct acpi_device *dev,
+ acpi_device_sysfs_files * func)
{
- acpi_status status;
- acpi_handle temp = NULL;
+ acpi_status status;
+ acpi_handle temp = NULL;
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
@@ -396,11 +377,10 @@ setup_sys_fs_device_files (
*/
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
- (*(func))(&dev->kobj,&acpi_device_attr_eject.attr);
+ (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr);
}
-static int
-acpi_eject_operation(acpi_handle handle, int lockable)
+static int acpi_eject_operation(acpi_handle handle, int lockable)
{
struct acpi_object_list arg_list;
union acpi_object arg;
@@ -429,27 +409,25 @@ acpi_eject_operation(acpi_handle handle, int lockable)
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) {
- return(-ENODEV);
+ return (-ENODEV);
}
- return(0);
+ return (0);
}
-
static ssize_t
acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
{
- int result;
- int ret = count;
- int islockable;
- acpi_status status;
- acpi_handle handle;
- acpi_object_type type = 0;
+ int result;
+ int ret = count;
+ int islockable;
+ acpi_status status;
+ acpi_handle handle;
+ acpi_object_type type = 0;
if ((!count) || (buf[0] != '1')) {
return -EINVAL;
}
-
#ifndef FORCE_EJECT
if (device->driver == NULL) {
ret = -ENODEV;
@@ -457,7 +435,7 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
}
#endif
status = acpi_get_type(device->handle, &type);
- if (ACPI_FAILURE(status) || (!device->flags.ejectable) ) {
+ if (ACPI_FAILURE(status) || (!device->flags.ejectable)) {
ret = -ENODEV;
goto err;
}
@@ -476,18 +454,15 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
if (result) {
ret = -EBUSY;
}
-err:
+ err:
return ret;
}
-
/* --------------------------------------------------------------------------
Performance Management
-------------------------------------------------------------------------- */
-static int
-acpi_bus_get_perf_flags (
- struct acpi_device *device)
+static int acpi_bus_get_perf_flags(struct acpi_device *device)
{
device->performance.state = ACPI_STATE_UNKNOWN;
return 0;
@@ -500,7 +475,6 @@ acpi_bus_get_perf_flags (
static LIST_HEAD(acpi_bus_drivers);
static DECLARE_MUTEX(acpi_bus_drivers_lock);
-
/**
* acpi_bus_match
* --------------
@@ -508,16 +482,13 @@ static DECLARE_MUTEX(acpi_bus_drivers_lock);
* matches the specified driver's criteria.
*/
static int
-acpi_bus_match (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
if (driver && driver->ops.match)
return driver->ops.match(device, driver);
return acpi_match_ids(device, driver->ids);
}
-
/**
* acpi_bus_driver_init
* --------------------
@@ -525,11 +496,9 @@ acpi_bus_match (
* driver is bound to a device. Invokes the driver's add() and start() ops.
*/
static int
-acpi_bus_driver_init (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_bus_driver_init");
@@ -553,13 +522,12 @@ acpi_bus_driver_init (
* upon possible configuration and currently allocated resources.
*/
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Driver successfully bound to device\n"));
return_VALUE(0);
}
-int
-acpi_start_single_object (
- struct acpi_device *device)
+static int acpi_start_single_object(struct acpi_device *device)
{
int result = 0;
struct acpi_driver *driver;
@@ -578,16 +546,17 @@ acpi_start_single_object (
return_VALUE(result);
}
-static int acpi_driver_attach(struct acpi_driver * drv)
+static int acpi_driver_attach(struct acpi_driver *drv)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
int count = 0;
ACPI_FUNCTION_TRACE("acpi_driver_attach");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, g_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, g_list);
if (dev->driver || !dev->status.present)
continue;
@@ -598,7 +567,8 @@ static int acpi_driver_attach(struct acpi_driver * drv)
acpi_start_single_object(dev);
atomic_inc(&drv->references);
count++;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found driver [%s] for device [%s]\n",
drv->name, dev->pnp.bus_id));
}
}
@@ -608,20 +578,21 @@ static int acpi_driver_attach(struct acpi_driver * drv)
return_VALUE(count);
}
-static int acpi_driver_detach(struct acpi_driver * drv)
+static int acpi_driver_detach(struct acpi_driver *drv)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_driver_detach");
spin_lock(&acpi_device_lock);
- list_for_each_safe(node,next,&acpi_device_list) {
- struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
+ list_for_each_safe(node, next, &acpi_device_list) {
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, g_list);
if (dev->driver == drv) {
spin_unlock(&acpi_device_lock);
if (drv->ops.remove)
- drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
+ drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL);
spin_lock(&acpi_device_lock);
dev->driver = NULL;
dev->driver_data = NULL;
@@ -640,9 +611,7 @@ static int acpi_driver_detach(struct acpi_driver * drv)
* number of devices that were claimed by the driver, or a negative
* error status for failure.
*/
-int
-acpi_bus_register_driver (
- struct acpi_driver *driver)
+int acpi_bus_register_driver(struct acpi_driver *driver)
{
int count;
@@ -661,8 +630,8 @@ acpi_bus_register_driver (
return_VALUE(count);
}
-EXPORT_SYMBOL(acpi_bus_register_driver);
+EXPORT_SYMBOL(acpi_bus_register_driver);
/**
* acpi_bus_unregister_driver
@@ -670,9 +639,7 @@ EXPORT_SYMBOL(acpi_bus_register_driver);
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
*/
-int
-acpi_bus_unregister_driver (
- struct acpi_driver *driver)
+int acpi_bus_unregister_driver(struct acpi_driver *driver)
{
int error = 0;
@@ -685,11 +652,12 @@ acpi_bus_unregister_driver (
spin_lock(&acpi_device_lock);
list_del_init(&driver->node);
spin_unlock(&acpi_device_lock);
- }
- } else
+ }
+ } else
error = -EINVAL;
return_VALUE(error);
}
+
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/**
@@ -698,18 +666,17 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver);
* Parses the list of registered drivers looking for a driver applicable for
* the specified device.
*/
-static int
-acpi_bus_find_driver (
- struct acpi_device *device)
+static int acpi_bus_find_driver(struct acpi_device *device)
{
- int result = 0;
- struct list_head * node, *next;
+ int result = 0;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_bus_find_driver");
spin_lock(&acpi_device_lock);
- list_for_each_safe(node,next,&acpi_bus_drivers) {
- struct acpi_driver * driver = container_of(node,struct acpi_driver,node);
+ list_for_each_safe(node, next, &acpi_bus_drivers) {
+ struct acpi_driver *driver =
+ container_of(node, struct acpi_driver, node);
atomic_inc(&driver->references);
spin_unlock(&acpi_device_lock);
@@ -723,21 +690,18 @@ acpi_bus_find_driver (
}
spin_unlock(&acpi_device_lock);
- Done:
+ Done:
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
-static int
-acpi_bus_get_flags (
- struct acpi_device *device)
+static int acpi_bus_get_flags(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- acpi_handle temp = NULL;
+ acpi_status status = AE_OK;
+ acpi_handle temp = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_get_flags");
@@ -788,11 +752,12 @@ acpi_bus_get_flags (
return_VALUE(0);
}
-static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_busid(struct acpi_device *device,
+ acpi_handle handle, int type)
{
- char bus_id[5] = {'?',0};
- struct acpi_buffer buffer = {sizeof(bus_id), bus_id};
- int i = 0;
+ char bus_id[5] = { '?', 0 };
+ struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
+ int i = 0;
/*
* Bus ID
@@ -824,21 +789,22 @@ static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handl
}
}
-static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent,
- acpi_handle handle, int type)
+static void acpi_device_set_id(struct acpi_device *device,
+ struct acpi_device *parent, acpi_handle handle,
+ int type)
{
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- char *hid = NULL;
- char *uid = NULL;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ char *hid = NULL;
+ char *uid = NULL;
struct acpi_compatible_id_list *cid_list = NULL;
- acpi_status status;
+ acpi_status status;
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
status = acpi_get_object_info(handle, &buffer);
if (ACPI_FAILURE(status)) {
- printk("%s: Error reading device info\n",__FUNCTION__);
+ printk("%s: Error reading device info\n", __FUNCTION__);
return;
}
@@ -904,7 +870,7 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device *
acpi_os_free(buffer.pointer);
}
-static int acpi_device_set_context(struct acpi_device * device, int type)
+static int acpi_device_set_context(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
int result = 0;
@@ -916,10 +882,10 @@ static int acpi_device_set_context(struct acpi_device * device, int type)
* to be careful with fixed-feature devices as they all attach to the
* root object.
*/
- if (type != ACPI_BUS_TYPE_POWER_BUTTON &&
+ if (type != ACPI_BUS_TYPE_POWER_BUTTON &&
type != ACPI_BUS_TYPE_SLEEP_BUTTON) {
status = acpi_attach_data(device->handle,
- acpi_bus_data_handler, device);
+ acpi_bus_data_handler, device);
if (ACPI_FAILURE(status)) {
printk("Error attaching device data\n");
@@ -929,12 +895,13 @@ static int acpi_device_set_context(struct acpi_device * device, int type)
return result;
}
-static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_debug_info(struct acpi_device *device,
+ acpi_handle handle, int type)
{
#ifdef CONFIG_ACPI_DEBUG_OUTPUT
- char *type_string = NULL;
- char name[80] = {'?','\0'};
- struct acpi_buffer buffer = {sizeof(name), name};
+ char *type_string = NULL;
+ char name[80] = { '?', '\0' };
+ struct acpi_buffer buffer = { sizeof(name), name };
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
@@ -968,18 +935,14 @@ static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle
}
printk(KERN_DEBUG "Found %s %s [%p]\n", type_string, name, handle);
-#endif /*CONFIG_ACPI_DEBUG_OUTPUT*/
+#endif /*CONFIG_ACPI_DEBUG_OUTPUT */
}
-
-static int
-acpi_bus_remove (
- struct acpi_device *dev,
- int rmdevice)
+static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
{
- int result = 0;
- struct acpi_driver *driver;
-
+ int result = 0;
+ struct acpi_driver *driver;
+
ACPI_FUNCTION_TRACE("acpi_bus_remove");
if (!dev)
@@ -1012,22 +975,18 @@ acpi_bus_remove (
if ((dev->parent) && (dev->parent->ops.unbind))
dev->parent->ops.unbind(dev);
}
-
+
acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
return_VALUE(0);
}
-
static int
-acpi_add_single_object (
- struct acpi_device **child,
- struct acpi_device *parent,
- acpi_handle handle,
- int type)
+acpi_add_single_object(struct acpi_device **child,
+ struct acpi_device *parent, acpi_handle handle, int type)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_add_single_object");
@@ -1044,7 +1003,7 @@ acpi_add_single_object (
device->handle = handle;
device->parent = parent;
- acpi_device_get_busid(device,handle,type);
+ acpi_device_get_busid(device, handle, type);
/*
* Flags
@@ -1092,7 +1051,7 @@ acpi_add_single_object (
* Hardware ID, Unique ID, & Bus Address
* -------------------------------------
*/
- acpi_device_set_id(device,parent,handle,type);
+ acpi_device_set_id(device, parent, handle, type);
/*
* Power Management
@@ -1104,7 +1063,7 @@ acpi_add_single_object (
goto end;
}
- /*
+ /*
* Wakeup device management
*-----------------------
*/
@@ -1124,12 +1083,12 @@ acpi_add_single_object (
goto end;
}
- if ((result = acpi_device_set_context(device,type)))
+ if ((result = acpi_device_set_context(device, type)))
goto end;
- acpi_device_get_debug_info(device,handle,type);
+ acpi_device_get_debug_info(device, handle, type);
- acpi_device_register(device,parent);
+ acpi_device_register(device, parent);
/*
* Bind _ADR-Based Devices
@@ -1154,7 +1113,7 @@ acpi_add_single_object (
*/
result = acpi_bus_find_driver(device);
-end:
+ end:
if (!result)
*child = device;
else {
@@ -1166,17 +1125,15 @@ end:
return_VALUE(result);
}
-
-static int acpi_bus_scan (struct acpi_device *start,
- struct acpi_bus_ops *ops)
+static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
{
- acpi_status status = AE_OK;
- struct acpi_device *parent = NULL;
- struct acpi_device *child = NULL;
- acpi_handle phandle = NULL;
- acpi_handle chandle = NULL;
- acpi_object_type type = 0;
- u32 level = 1;
+ acpi_status status = AE_OK;
+ struct acpi_device *parent = NULL;
+ struct acpi_device *child = NULL;
+ acpi_handle phandle = NULL;
+ acpi_handle chandle = NULL;
+ acpi_object_type type = 0;
+ u32 level = 1;
ACPI_FUNCTION_TRACE("acpi_bus_scan");
@@ -1185,7 +1142,7 @@ static int acpi_bus_scan (struct acpi_device *start,
parent = start;
phandle = start->handle;
-
+
/*
* Parse through the ACPI namespace, identify all 'devices', and
* create a new 'struct acpi_device' for each.
@@ -1193,7 +1150,7 @@ static int acpi_bus_scan (struct acpi_device *start,
while ((level > 0) && parent) {
status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
- chandle, &chandle);
+ chandle, &chandle);
/*
* If this scope is exhausted then move our way back up.
@@ -1243,12 +1200,12 @@ static int acpi_bus_scan (struct acpi_device *start,
if (ops->acpi_op_add)
status = acpi_add_single_object(&child, parent,
- chandle, type);
- else
+ chandle, type);
+ else
status = acpi_bus_get_device(chandle, &child);
- if (ACPI_FAILURE(status))
- continue;
+ if (ACPI_FAILURE(status))
+ continue;
if (ops->acpi_op_start) {
status = acpi_start_single_object(child);
@@ -1264,7 +1221,7 @@ static int acpi_bus_scan (struct acpi_device *start,
* which will be enumerated when the parent is inserted).
*
* TBD: Need notifications and other detection mechanisms
- * in place before we can fully implement this.
+ * in place before we can fully implement this.
*/
if (child->status.present) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
@@ -1282,11 +1239,8 @@ static int acpi_bus_scan (struct acpi_device *start,
}
int
-acpi_bus_add (
- struct acpi_device **child,
- struct acpi_device *parent,
- acpi_handle handle,
- int type)
+acpi_bus_add(struct acpi_device **child,
+ struct acpi_device *parent, acpi_handle handle, int type)
{
int result;
struct acpi_bus_ops ops;
@@ -1301,11 +1255,10 @@ acpi_bus_add (
}
return_VALUE(result);
}
+
EXPORT_SYMBOL(acpi_bus_add);
-int
-acpi_bus_start (
- struct acpi_device *device)
+int acpi_bus_start(struct acpi_device *device)
{
int result;
struct acpi_bus_ops ops;
@@ -1323,26 +1276,25 @@ acpi_bus_start (
}
return_VALUE(result);
}
+
EXPORT_SYMBOL(acpi_bus_start);
-static int
-acpi_bus_trim(struct acpi_device *start,
- int rmdevice)
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
{
- acpi_status status;
- struct acpi_device *parent, *child;
- acpi_handle phandle, chandle;
- acpi_object_type type;
- u32 level = 1;
- int err = 0;
-
- parent = start;
+ acpi_status status;
+ struct acpi_device *parent, *child;
+ acpi_handle phandle, chandle;
+ acpi_object_type type;
+ u32 level = 1;
+ int err = 0;
+
+ parent = start;
phandle = start->handle;
child = chandle = NULL;
while ((level > 0) && parent && (!err)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
- chandle, &chandle);
+ chandle, &chandle);
/*
* If this scope is exhausted then move our way back up.
@@ -1381,12 +1333,10 @@ acpi_bus_trim(struct acpi_device *start,
return err;
}
-static int
-acpi_bus_scan_fixed (
- struct acpi_device *root)
+static int acpi_bus_scan_fixed(struct acpi_device *root)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");
@@ -1398,14 +1348,16 @@ acpi_bus_scan_fixed (
*/
if (acpi_fadt.pwr_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
- NULL, ACPI_BUS_TYPE_POWER_BUTTON);
+ NULL,
+ ACPI_BUS_TYPE_POWER_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}
if (acpi_fadt.sleep_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
- NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
+ NULL,
+ ACPI_BUS_TYPE_SLEEP_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}
@@ -1413,7 +1365,6 @@ acpi_bus_scan_fixed (
return_VALUE(result);
}
-
static int __init acpi_scan_init(void)
{
int result;
@@ -1430,7 +1381,7 @@ static int __init acpi_scan_init(void)
* Create the root device in the bus's device tree
*/
result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
- ACPI_BUS_TYPE_SYSTEM);
+ ACPI_BUS_TYPE_SYSTEM);
if (result)
goto Done;
@@ -1450,7 +1401,7 @@ static int __init acpi_scan_init(void)
if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
- Done:
+ Done:
return_VALUE(result);
}
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 7249ba2b7a27..aee50b453265 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -23,7 +23,6 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
static struct pm_ops acpi_pm_ops;
-extern void do_suspend_lowlevel_s4bios(void);
extern void do_suspend_lowlevel(void);
static u32 acpi_suspend_states[] = {
@@ -98,8 +97,6 @@ static int acpi_pm_enter(suspend_state_t pm_state)
case PM_SUSPEND_DISK:
if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM)
status = acpi_enter_sleep_state(acpi_state);
- else
- do_suspend_lowlevel_s4bios();
break;
case PM_SUSPEND_MAX:
acpi_power_off();
@@ -206,11 +203,6 @@ static int __init acpi_sleep_init(void)
printk(" S%d", i);
}
if (i == ACPI_STATE_S4) {
- if (acpi_gbl_FACS->S4bios_f) {
- sleep_states[i] = 1;
- printk(" S4bios");
- acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
- }
if (sleep_states[i])
acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
}
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index 186b182c5825..af7935a95bcc 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -21,9 +21,7 @@ int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
/* do we have a wakeup address for S2 and S3? */
- /* Here, we support only S4BIOS, those we set the wakeup address */
- /* S4OS is only supported for now via swsusp.. */
- if (acpi_state == ACPI_STATE_S3 || acpi_state == ACPI_STATE_S4) {
+ if (acpi_state == ACPI_STATE_S3) {
if (!acpi_wakeup_address) {
return -EFAULT;
}
@@ -55,7 +53,11 @@ void acpi_power_off(void)
static int acpi_shutdown(struct sys_device *x)
{
- return acpi_sleep_prepare(ACPI_STATE_S5);
+ if (system_state == SYSTEM_POWER_OFF) {
+ /* Prepare if we are going to power off the system */
+ return acpi_sleep_prepare(ACPI_STATE_S5);
+ }
+ return 0;
}
static struct sysdev_class acpi_sysclass = {
@@ -91,4 +93,4 @@ static int acpi_poweroff_init(void)
late_initcall(acpi_poweroff_init);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM */
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 1be99f0996d6..4696a85a98b9 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -13,29 +13,18 @@
#include "sleep.h"
-#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
-#define ACPI_SYSTEM_FILE_SLEEP "sleep"
-#endif
-
-#define ACPI_SYSTEM_FILE_ALARM "alarm"
-#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE "wakeup"
-
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("sleep")
-
+ACPI_MODULE_NAME("sleep")
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
-
static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{
- int i;
+ int i;
ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show");
for (i = 0; i <= ACPI_STATE_S5; i++) {
if (sleep_states[i]) {
- seq_printf(seq,"S%d ", i);
- if (i == ACPI_STATE_S4 && acpi_gbl_FACS->S4bios_f)
- seq_printf(seq, "S4bios ");
+ seq_printf(seq, "S%d ", i);
}
}
@@ -50,24 +39,21 @@ static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_system_write_sleep (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_sleep(struct file *file,
+ const char __user * buffer, size_t count, loff_t * ppos)
{
- char str[12];
- u32 state = 0;
- int error = 0;
+ char str[12];
+ u32 state = 0;
+ int error = 0;
if (count > sizeof(str) - 1)
goto Done;
- memset(str,0,sizeof(str));
+ memset(str, 0, sizeof(str));
if (copy_from_user(str, buffer, count))
return -EFAULT;
/* Check for S4 bios request */
- if (!strcmp(str,"4b")) {
+ if (!strcmp(str, "4b")) {
error = acpi_suspend(4);
goto Done;
}
@@ -79,17 +65,17 @@ acpi_system_write_sleep (
}
#endif
error = acpi_suspend(state);
- Done:
+ Done:
return error ? error : count;
}
-#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
+#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
{
- u32 sec, min, hr;
- u32 day, mo, yr;
- unsigned char rtc_control = 0;
- unsigned long flags;
+ u32 sec, min, hr;
+ u32 day, mo, yr;
+ unsigned char rtc_control = 0;
+ unsigned long flags;
ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
@@ -105,13 +91,14 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
/* ACPI spec: only low 6 its should be cared */
day = CMOS_READ(acpi_gbl_FADT->day_alrm) & 0x3F;
else
- day = CMOS_READ(RTC_DAY_OF_MONTH);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
if (acpi_gbl_FADT->mon_alrm)
mo = CMOS_READ(acpi_gbl_FADT->mon_alrm);
else
mo = CMOS_READ(RTC_MONTH);
if (acpi_gbl_FADT->century)
- yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR);
+ yr = CMOS_READ(acpi_gbl_FADT->century) * 100 +
+ CMOS_READ(RTC_YEAR);
else
yr = CMOS_READ(RTC_YEAR);
@@ -126,33 +113,33 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
BCD_TO_BIN(yr);
}
- /* we're trusting the FADT (see above)*/
+ /* we're trusting the FADT (see above) */
if (!acpi_gbl_FADT->century)
- /* If we're not trusting the FADT, we should at least make it
- * right for _this_ century... ehm, what is _this_ century?
- *
- * TBD:
- * ASAP: find piece of code in the kernel, e.g. star tracker driver,
- * which we can trust to determine the century correctly. Atom
- * watch driver would be nice, too...
- *
- * if that has not happened, change for first release in 2050:
- * if (yr<50)
- * yr += 2100;
- * else
- * yr += 2000; // current line of code
- *
- * if that has not happened either, please do on 2099/12/31:23:59:59
- * s/2000/2100
- *
- */
+ /* If we're not trusting the FADT, we should at least make it
+ * right for _this_ century... ehm, what is _this_ century?
+ *
+ * TBD:
+ * ASAP: find piece of code in the kernel, e.g. star tracker driver,
+ * which we can trust to determine the century correctly. Atom
+ * watch driver would be nice, too...
+ *
+ * if that has not happened, change for first release in 2050:
+ * if (yr<50)
+ * yr += 2100;
+ * else
+ * yr += 2000; // current line of code
+ *
+ * if that has not happened either, please do on 2099/12/31:23:59:59
+ * s/2000/2100
+ *
+ */
yr += 2000;
- seq_printf(seq,"%4.4u-", yr);
- (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
- (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
- (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
- (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
+ seq_printf(seq, "%4.4u-", yr);
+ (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
+ (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
+ (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
+ (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
(sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
return 0;
@@ -163,15 +150,11 @@ static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
}
-
-static int
-get_date_field (
- char **p,
- u32 *value)
+static int get_date_field(char **p, u32 * value)
{
- char *next = NULL;
- char *string_end = NULL;
- int result = -EINVAL;
+ char *next = NULL;
+ char *string_end = NULL;
+ int result = -EINVAL;
/*
* Try to find delimeter, only to insert null. The end of the
@@ -193,26 +176,22 @@ get_date_field (
return result;
}
-
static ssize_t
-acpi_system_write_alarm (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_alarm(struct file *file,
+ const char __user * buffer, size_t count, loff_t * ppos)
{
- int result = 0;
- char alarm_string[30] = {'\0'};
- char *p = alarm_string;
- u32 sec, min, hr, day, mo, yr;
- int adjust = 0;
- unsigned char rtc_control = 0;
+ int result = 0;
+ char alarm_string[30] = { '\0' };
+ char *p = alarm_string;
+ u32 sec, min, hr, day, mo, yr;
+ int adjust = 0;
+ unsigned char rtc_control = 0;
ACPI_FUNCTION_TRACE("acpi_system_write_alarm");
if (count > sizeof(alarm_string) - 1)
return_VALUE(-EINVAL);
-
+
if (copy_from_user(alarm_string, buffer, count))
return_VALUE(-EFAULT);
@@ -271,10 +250,10 @@ acpi_system_write_alarm (
}
if (adjust) {
- yr += CMOS_READ(RTC_YEAR);
- mo += CMOS_READ(RTC_MONTH);
+ yr += CMOS_READ(RTC_YEAR);
+ mo += CMOS_READ(RTC_MONTH);
day += CMOS_READ(RTC_DAY_OF_MONTH);
- hr += CMOS_READ(RTC_HOURS);
+ hr += CMOS_READ(RTC_HOURS);
min += CMOS_READ(RTC_MINUTES);
sec += CMOS_READ(RTC_SECONDS);
}
@@ -343,7 +322,7 @@ acpi_system_write_alarm (
if (acpi_gbl_FADT->mon_alrm)
CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm);
if (acpi_gbl_FADT->century)
- CMOS_WRITE(yr/100, acpi_gbl_FADT->century);
+ CMOS_WRITE(yr / 100, acpi_gbl_FADT->century);
/* enable the rtc alarm interrupt */
rtc_control |= RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
@@ -357,35 +336,33 @@ acpi_system_write_alarm (
*ppos += count;
result = 0;
-end:
+ end:
return_VALUE(result ? result : count);
}
-extern struct list_head acpi_wakeup_device_list;
+extern struct list_head acpi_wakeup_device_list;
extern spinlock_t acpi_device_lock;
static int
acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
seq_printf(seq, "Device Sleep state Status\n");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
spin_unlock(&acpi_device_lock);
- if (dev->wakeup.flags.run_wake)
- seq_printf(seq, "%4s %4d %8s\n",
- dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
- dev->wakeup.state.enabled ? "*enabled" : "*disabled");
- else
- seq_printf(seq, "%4s %4d %8s\n",
- dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
- dev->wakeup.state.enabled ? "enabled" : "disabled");
+ seq_printf(seq, "%4s %4d %s%8s\n",
+ dev->pnp.bus_id,
+ (u32) dev->wakeup.sleep_state,
+ dev->wakeup.flags.run_wake ? "*" : "",
+ dev->wakeup.state.enabled ? "enabled" : "disabled");
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -393,19 +370,18 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
}
static ssize_t
-acpi_system_write_wakeup_device (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_wakeup_device(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct list_head * node, * next;
- char strbuf[5];
- char str[5] = "";
- int len = count;
+ struct list_head *node, *next;
+ char strbuf[5];
+ char str[5] = "";
+ int len = count;
struct acpi_device *found_dev = NULL;
- if (len > 4) len = 4;
+ if (len > 4)
+ len = 4;
if (copy_from_user(strbuf, buffer, len))
return -EFAULT;
@@ -414,28 +390,36 @@ acpi_system_write_wakeup_device (
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
if (!strncmp(dev->pnp.bus_id, str, 4)) {
- dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
+ dev->wakeup.state.enabled =
+ dev->wakeup.state.enabled ? 0 : 1;
found_dev = dev;
break;
}
}
if (found_dev) {
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct
+ acpi_device,
+ wakeup_list);
if ((dev != found_dev) &&
- (dev->wakeup.gpe_number == found_dev->wakeup.gpe_number) &&
- (dev->wakeup.gpe_device == found_dev->wakeup.gpe_device)) {
- printk(KERN_WARNING "ACPI: '%s' and '%s' have the same GPE, "
- "can't disable/enable one seperately\n",
- dev->pnp.bus_id, found_dev->pnp.bus_id);
- dev->wakeup.state.enabled = found_dev->wakeup.state.enabled;
+ (dev->wakeup.gpe_number ==
+ found_dev->wakeup.gpe_number)
+ && (dev->wakeup.gpe_device ==
+ found_dev->wakeup.gpe_device)) {
+ printk(KERN_WARNING
+ "ACPI: '%s' and '%s' have the same GPE, "
+ "can't disable/enable one seperately\n",
+ dev->pnp.bus_id, found_dev->pnp.bus_id);
+ dev->wakeup.state.enabled =
+ found_dev->wakeup.state.enabled;
}
}
}
@@ -446,37 +430,37 @@ acpi_system_write_wakeup_device (
static int
acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_system_wakeup_device_seq_show,
+ PDE(inode)->data);
}
static struct file_operations acpi_system_wakeup_device_fops = {
- .open = acpi_system_wakeup_device_open_fs,
- .read = seq_read,
- .write = acpi_system_write_wakeup_device,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_wakeup_device_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_wakeup_device,
+ .llseek = seq_lseek,
+ .release = single_release,
};
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
static struct file_operations acpi_system_sleep_fops = {
- .open = acpi_system_sleep_open_fs,
- .read = seq_read,
- .write = acpi_system_write_sleep,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_sleep_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_sleep,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
+#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
static struct file_operations acpi_system_alarm_fops = {
- .open = acpi_system_alarm_open_fs,
- .read = seq_read,
- .write = acpi_system_write_alarm,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_alarm_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_alarm,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
-static u32 rtc_handler(void * context)
+static u32 rtc_handler(void *context)
{
acpi_clear_event(ACPI_EVENT_RTC);
acpi_disable_event(ACPI_EVENT_RTC, 0);
@@ -486,28 +470,31 @@ static u32 rtc_handler(void * context)
static int acpi_sleep_proc_init(void)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
if (acpi_disabled)
return 0;
-
+
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
- /* 'sleep' [R/W]*/
- entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ /* 'sleep' [R/W] */
+ entry =
+ create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_sleep_fops;
#endif
/* 'alarm' [R/W] */
- entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ entry =
+ create_proc_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_alarm_fops;
- /* 'wakeup device' [R/W]*/
- entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ /* 'wakeup device' [R/W] */
+ entry =
+ create_proc_entry("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_wakeup_device_fops;
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index d9b199969d5d..4134ed43d026 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -12,9 +12,9 @@
#include "sleep.h"
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("wakeup_devices")
+ACPI_MODULE_NAME("wakeup_devices")
-extern struct list_head acpi_wakeup_device_list;
+extern struct list_head acpi_wakeup_device_list;
extern spinlock_t acpi_device_lock;
#ifdef CONFIG_ACPI_SLEEP
@@ -25,22 +25,21 @@ extern spinlock_t acpi_device_lock;
* is higher than requested sleep level
*/
-void
-acpi_enable_wakeup_device_prep(
- u8 sleep_state)
+void acpi_enable_wakeup_device_prep(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
-
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.enabled ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
+
+ if (!dev->wakeup.flags.valid ||
+ !dev->wakeup.state.enabled ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
@@ -55,11 +54,9 @@ acpi_enable_wakeup_device_prep(
* @sleep_state: ACPI state
* Enable all wakup devices's GPE
*/
-void
-acpi_enable_wakeup_device(
- u8 sleep_state)
+void acpi_enable_wakeup_device(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
/*
* Caution: this routine must be invoked when interrupt is disabled
@@ -68,33 +65,35 @@ acpi_enable_wakeup_device(
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_RUNTIME);
/* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_ISR);
spin_lock(&acpi_device_lock);
continue;
}
if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.enabled ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ !dev->wakeup.state.enabled ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
/* run-wake GPE has been enabled */
if (!dev->wakeup.flags.run_wake)
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_ISR);
dev->wakeup.state.active = 1;
spin_lock(&acpi_device_lock);
}
@@ -106,43 +105,43 @@ acpi_enable_wakeup_device(
* @sleep_state: ACPI state
* Disable all wakup devices's GPE and wakeup capability
*/
-void
-acpi_disable_wakeup_device (
- u8 sleep_state)
+void acpi_disable_wakeup_device(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
/* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
spin_lock(&acpi_device_lock);
continue;
}
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.active ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ if (!dev->wakeup.flags.valid ||
+ !dev->wakeup.state.active ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
acpi_disable_wakeup_device_power(dev);
/* Never disable run-wake GPE */
if (!dev->wakeup.flags.run_wake) {
- acpi_disable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
- acpi_clear_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_disable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_clear_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
}
dev->wakeup.state.active = 0;
spin_lock(&acpi_device_lock);
@@ -152,7 +151,7 @@ acpi_disable_wakeup_device (
static int __init acpi_wakeup_device_init(void)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
if (acpi_disabled)
return 0;
@@ -160,16 +159,18 @@ static int __init acpi_wakeup_device_init(void)
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
-
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
+
/* In case user doesn't load button driver */
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
dev->wakeup.state.enabled = 1;
spin_lock(&acpi_device_lock);
}
@@ -193,17 +194,19 @@ late_initcall(acpi_wakeup_device_init);
*/
void acpi_wakeup_gpe_poweroff_prepare(void)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
/* The GPE can wakeup system from S5, don't touch it */
- if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5)
+ if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5)
continue;
/* acpi_set_gpe_type will automatically disable GPE */
acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_RUNTIME);
}
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 8925a6ca5f87..e4308c7a6743 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -30,10 +30,8 @@
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("acpi_system")
-
+ACPI_MODULE_NAME("acpi_system")
#define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
#define ACPI_SYSTEM_DEVICE_NAME "System"
@@ -41,15 +39,13 @@ 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 FADT_DESCRIPTOR acpi_fadt;
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static int
-acpi_system_read_info (struct seq_file *seq, void *offset)
+static int acpi_system_read_info(struct seq_file *seq, void *offset)
{
ACPI_FUNCTION_TRACE("acpi_system_read_info");
@@ -63,28 +59,26 @@ static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_system_info_ops = {
- .open = acpi_system_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static ssize_t acpi_system_read_dsdt (struct file*, char __user *, size_t, loff_t*);
+static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
+ loff_t *);
static struct file_operations acpi_system_dsdt_ops = {
- .read = acpi_system_read_dsdt,
+ .read = acpi_system_read_dsdt,
};
static ssize_t
-acpi_system_read_dsdt (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_dsdt(struct file *file,
+ char __user * buffer, size_t count, loff_t * ppos)
{
- acpi_status status = AE_OK;
- struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL};
- ssize_t res;
+ acpi_status status = AE_OK;
+ struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
+ ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
@@ -99,23 +93,20 @@ acpi_system_read_dsdt (
return_VALUE(res);
}
-
-static ssize_t acpi_system_read_fadt (struct file*, char __user *, size_t, loff_t*);
+static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
+ loff_t *);
static struct file_operations acpi_system_fadt_ops = {
- .read = acpi_system_read_fadt,
+ .read = acpi_system_read_fadt,
};
static ssize_t
-acpi_system_read_fadt (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_fadt(struct file *file,
+ char __user * buffer, size_t count, loff_t * ppos)
{
- acpi_status status = AE_OK;
- struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL};
- ssize_t res;
+ acpi_status status = AE_OK;
+ struct acpi_buffer fadt = { ACPI_ALLOCATE_BUFFER, NULL };
+ ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
@@ -130,12 +121,11 @@ acpi_system_read_fadt (
return_VALUE(res);
}
-
-static int __init acpi_system_init (void)
+static int __init acpi_system_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
- char * name;
+ char *name;
ACPI_FUNCTION_TRACE("acpi_system_init");
@@ -144,8 +134,7 @@ static int __init acpi_system_init (void)
/* 'info' [R] */
name = ACPI_SYSTEM_FILE_INFO;
- entry = create_proc_entry(name,
- S_IRUGO, acpi_root_dir);
+ entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
if (!entry)
goto Error;
else {
@@ -157,7 +146,7 @@ static int __init acpi_system_init (void)
entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_dsdt_ops;
- else
+ else
goto Error;
/* 'fadt' [R] */
@@ -168,12 +157,12 @@ static int __init acpi_system_init (void)
else
goto Error;
- Done:
+ Done:
return_VALUE(error);
- Error:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n", name));
+ Error:
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n", name));
remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
@@ -183,5 +172,4 @@ static int __init acpi_system_init (void)
goto Done;
}
-
subsys_initcall(acpi_system_init);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index fb64bd5d2e18..a2bf25b05e1c 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -40,25 +40,25 @@
#define ACPI_MAX_TABLES 256
static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
- [ACPI_TABLE_UNKNOWN] = "????",
- [ACPI_APIC] = "APIC",
- [ACPI_BOOT] = "BOOT",
- [ACPI_DBGP] = "DBGP",
- [ACPI_DSDT] = "DSDT",
- [ACPI_ECDT] = "ECDT",
- [ACPI_ETDT] = "ETDT",
- [ACPI_FADT] = "FACP",
- [ACPI_FACS] = "FACS",
- [ACPI_OEMX] = "OEM",
- [ACPI_PSDT] = "PSDT",
- [ACPI_SBST] = "SBST",
- [ACPI_SLIT] = "SLIT",
- [ACPI_SPCR] = "SPCR",
- [ACPI_SRAT] = "SRAT",
- [ACPI_SSDT] = "SSDT",
- [ACPI_SPMI] = "SPMI",
- [ACPI_HPET] = "HPET",
- [ACPI_MCFG] = "MCFG",
+ [ACPI_TABLE_UNKNOWN] = "????",
+ [ACPI_APIC] = "APIC",
+ [ACPI_BOOT] = "BOOT",
+ [ACPI_DBGP] = "DBGP",
+ [ACPI_DSDT] = "DSDT",
+ [ACPI_ECDT] = "ECDT",
+ [ACPI_ETDT] = "ETDT",
+ [ACPI_FADT] = "FACP",
+ [ACPI_FACS] = "FACS",
+ [ACPI_OEMX] = "OEM",
+ [ACPI_PSDT] = "PSDT",
+ [ACPI_SBST] = "SBST",
+ [ACPI_SLIT] = "SLIT",
+ [ACPI_SPCR] = "SPCR",
+ [ACPI_SRAT] = "SRAT",
+ [ACPI_SSDT] = "SSDT",
+ [ACPI_SPMI] = "SPMI",
+ [ACPI_HPET] = "HPET",
+ [ACPI_MCFG] = "MCFG",
};
static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
@@ -66,52 +66,44 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
/* System Description Table (RSDT/XSDT) */
struct acpi_table_sdt {
- unsigned long pa;
- enum acpi_table_id id;
- unsigned long size;
+ unsigned long pa;
+ enum acpi_table_id id;
+ unsigned long size;
} __attribute__ ((packed));
-static unsigned long sdt_pa; /* Physical Address */
-static unsigned long sdt_count; /* Table count */
+static unsigned long sdt_pa; /* Physical Address */
+static unsigned long sdt_count; /* Table count */
-static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
+static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
-void
-acpi_table_print (
- struct acpi_table_header *header,
- unsigned long phys_addr)
+void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr)
{
- char *name = NULL;
+ char *name = NULL;
if (!header)
return;
/* Some table signatures aren't good table names */
- if (!strncmp((char *) &header->signature,
- acpi_table_signatures[ACPI_APIC],
- sizeof(header->signature))) {
+ if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[ACPI_APIC],
+ sizeof(header->signature))) {
name = "MADT";
- }
- else if (!strncmp((char *) &header->signature,
- acpi_table_signatures[ACPI_FADT],
- sizeof(header->signature))) {
+ } else if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[ACPI_FADT],
+ sizeof(header->signature))) {
name = "FADT";
- }
- else
+ } else
name = header->signature;
- printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
- name, header->revision, header->oem_id,
- header->oem_table_id, header->oem_revision,
- header->asl_compiler_id, header->asl_compiler_revision,
- (void *) phys_addr);
+ printk(KERN_DEBUG PREFIX
+ "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name,
+ header->revision, header->oem_id, header->oem_table_id,
+ header->oem_revision, header->asl_compiler_id,
+ header->asl_compiler_revision, (void *)phys_addr);
}
-
-void
-acpi_table_print_madt_entry (
- acpi_table_entry_header *header)
+void acpi_table_print_madt_entry(acpi_table_entry_header * header)
{
if (!header)
return;
@@ -119,113 +111,127 @@ acpi_table_print_madt_entry (
switch (header->type) {
case ACPI_MADT_LAPIC:
- {
- struct acpi_table_lapic *p =
- (struct acpi_table_lapic*) header;
- printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
- p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled");
- }
+ {
+ struct acpi_table_lapic *p =
+ (struct acpi_table_lapic *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
+ p->acpi_id, p->id,
+ p->flags.enabled ? "enabled" : "disabled");
+ }
break;
case ACPI_MADT_IOAPIC:
- {
- struct acpi_table_ioapic *p =
- (struct acpi_table_ioapic*) header;
- printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
- p->id, p->address, p->global_irq_base);
- }
+ {
+ struct acpi_table_ioapic *p =
+ (struct acpi_table_ioapic *)header;
+ printk(KERN_INFO PREFIX
+ "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
+ p->id, p->address, p->global_irq_base);
+ }
break;
case ACPI_MADT_INT_SRC_OVR:
- {
- struct acpi_table_int_src_ovr *p =
- (struct acpi_table_int_src_ovr*) header;
- printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
- p->bus, p->bus_irq, p->global_irq,
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger]);
- if(p->flags.reserved)
- printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
- p->flags.reserved);
+ {
+ struct acpi_table_int_src_ovr *p =
+ (struct acpi_table_int_src_ovr *)header;
+ printk(KERN_INFO PREFIX
+ "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
+ p->bus, p->bus_irq, p->global_irq,
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger]);
+ if (p->flags.reserved)
+ printk(KERN_INFO PREFIX
+ "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
+ p->flags.reserved);
- }
+ }
break;
case ACPI_MADT_NMI_SRC:
- {
- struct acpi_table_nmi_src *p =
- (struct acpi_table_nmi_src*) header;
- printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n",
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger], p->global_irq);
- }
+ {
+ struct acpi_table_nmi_src *p =
+ (struct acpi_table_nmi_src *)header;
+ printk(KERN_INFO PREFIX
+ "NMI_SRC (%s %s global_irq %d)\n",
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->global_irq);
+ }
break;
case ACPI_MADT_LAPIC_NMI:
- {
- struct acpi_table_lapic_nmi *p =
- (struct acpi_table_lapic_nmi*) header;
- printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
- p->acpi_id,
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger], p->lint);
- }
+ {
+ struct acpi_table_lapic_nmi *p =
+ (struct acpi_table_lapic_nmi *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
+ p->acpi_id,
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->lint);
+ }
break;
case ACPI_MADT_LAPIC_ADDR_OVR:
- {
- struct acpi_table_lapic_addr_ovr *p =
- (struct acpi_table_lapic_addr_ovr*) header;
- printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n",
- (void *) (unsigned long) p->address);
- }
+ {
+ struct acpi_table_lapic_addr_ovr *p =
+ (struct acpi_table_lapic_addr_ovr *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC_ADDR_OVR (address[%p])\n",
+ (void *)(unsigned long)p->address);
+ }
break;
case ACPI_MADT_IOSAPIC:
- {
- struct acpi_table_iosapic *p =
- (struct acpi_table_iosapic*) header;
- printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
- p->id, (void *) (unsigned long) p->address, p->global_irq_base);
- }
+ {
+ struct acpi_table_iosapic *p =
+ (struct acpi_table_iosapic *)header;
+ printk(KERN_INFO PREFIX
+ "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
+ p->id, (void *)(unsigned long)p->address,
+ p->global_irq_base);
+ }
break;
case ACPI_MADT_LSAPIC:
- {
- struct acpi_table_lsapic *p =
- (struct acpi_table_lsapic*) header;
- printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
- p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled");
- }
+ {
+ struct acpi_table_lsapic *p =
+ (struct acpi_table_lsapic *)header;
+ printk(KERN_INFO PREFIX
+ "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
+ p->acpi_id, p->id, p->eid,
+ p->flags.enabled ? "enabled" : "disabled");
+ }
break;
case ACPI_MADT_PLAT_INT_SRC:
- {
- struct acpi_table_plat_int_src *p =
- (struct acpi_table_plat_int_src*) header;
- printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger],
- p->type, p->id, p->eid, p->iosapic_vector, p->global_irq);
- }
+ {
+ struct acpi_table_plat_int_src *p =
+ (struct acpi_table_plat_int_src *)header;
+ printk(KERN_INFO PREFIX
+ "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->type, p->id, p->eid, p->iosapic_vector,
+ p->global_irq);
+ }
break;
default:
- printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n",
- header->type);
+ printk(KERN_WARNING PREFIX
+ "Found unsupported MADT entry (type = 0x%x)\n",
+ header->type);
break;
}
}
-
static int
-acpi_table_compute_checksum (
- void *table_pointer,
- unsigned long length)
+acpi_table_compute_checksum(void *table_pointer, unsigned long length)
{
- u8 *p = (u8 *) table_pointer;
- unsigned long remains = length;
- unsigned long sum = 0;
+ u8 *p = (u8 *) table_pointer;
+ unsigned long remains = length;
+ unsigned long sum = 0;
if (!p || !length)
return -EINVAL;
@@ -241,9 +247,8 @@ acpi_table_compute_checksum (
* for acpi_blacklisted(), acpi_table_get_sdt()
*/
int __init
-acpi_get_table_header_early (
- enum acpi_table_id id,
- struct acpi_table_header **header)
+acpi_get_table_header_early(enum acpi_table_id id,
+ struct acpi_table_header **header)
{
unsigned int i;
enum acpi_table_id temp_id;
@@ -260,7 +265,7 @@ acpi_get_table_header_early (
if (sdt_entry[i].id != temp_id)
continue;
*header = (void *)
- __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
if (!*header) {
printk(KERN_WARNING PREFIX "Unable to map %s\n",
acpi_table_signatures[temp_id]);
@@ -277,14 +282,17 @@ acpi_get_table_header_early (
/* 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_rev2 *fadt =
+ (struct fadt_descriptor_rev2 *)*header;
if (fadt->revision == 3 && fadt->Xdsdt) {
- *header = (void *) __acpi_map_table(fadt->Xdsdt,
- sizeof(struct acpi_table_header));
+ *header = (void *)__acpi_map_table(fadt->Xdsdt,
+ sizeof(struct
+ acpi_table_header));
} else if (fadt->V1_dsdt) {
- *header = (void *) __acpi_map_table(fadt->V1_dsdt,
- sizeof(struct acpi_table_header));
+ *header = (void *)__acpi_map_table(fadt->V1_dsdt,
+ sizeof(struct
+ acpi_table_header));
} else
*header = NULL;
@@ -296,21 +304,19 @@ acpi_get_table_header_early (
return 0;
}
-
int __init
-acpi_table_parse_madt_family (
- enum acpi_table_id id,
- unsigned long madt_size,
- int entry_id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_madt_family(enum acpi_table_id id,
+ unsigned long madt_size,
+ int entry_id,
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries)
{
- void *madt = NULL;
- acpi_table_entry_header *entry;
- unsigned int count = 0;
- unsigned long madt_end;
- unsigned int i;
+ void *madt = NULL;
+ acpi_table_entry_header *entry;
+ unsigned int count = 0;
+ unsigned long madt_end;
+ unsigned int i;
if (!handler)
return -EINVAL;
@@ -321,7 +327,7 @@ acpi_table_parse_madt_family (
if (sdt_entry[i].id != id)
continue;
madt = (void *)
- __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
if (!madt) {
printk(KERN_WARNING PREFIX "Unable to map %s\n",
acpi_table_signatures[id]);
@@ -336,21 +342,22 @@ acpi_table_parse_madt_family (
return -ENODEV;
}
- madt_end = (unsigned long) madt + sdt_entry[i].size;
+ madt_end = (unsigned long)madt + sdt_entry[i].size;
/* Parse all entries looking for a match. */
entry = (acpi_table_entry_header *)
- ((unsigned long) madt + madt_size);
+ ((unsigned long)madt + madt_size);
- while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
- if (entry->type == entry_id &&
- (!max_entries || count++ < max_entries))
+ while (((unsigned long)entry) + sizeof(acpi_table_entry_header) <
+ madt_end) {
+ if (entry->type == entry_id
+ && (!max_entries || count++ < max_entries))
if (handler(entry, madt_end))
return -EINVAL;
entry = (acpi_table_entry_header *)
- ((unsigned long) entry + entry->length);
+ ((unsigned long)entry + entry->length);
}
if (max_entries && count > max_entries) {
printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
@@ -361,25 +368,19 @@ acpi_table_parse_madt_family (
return count;
}
-
int __init
-acpi_table_parse_madt (
- enum acpi_madt_entry_id id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_madt(enum acpi_madt_entry_id id,
+ acpi_madt_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
- id, handler, max_entries);
+ return acpi_table_parse_madt_family(ACPI_APIC,
+ sizeof(struct acpi_table_madt), id,
+ handler, max_entries);
}
-
-int __init
-acpi_table_parse (
- enum acpi_table_id id,
- acpi_table_handler handler)
+int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler)
{
- int count = 0;
- unsigned int i = 0;
+ int count = 0;
+ unsigned int i = 0;
if (!handler)
return -EINVAL;
@@ -392,20 +393,18 @@ acpi_table_parse (
handler(sdt_entry[i].pa, sdt_entry[i].size);
else
- printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n",
- count, acpi_table_signatures[id]);
+ printk(KERN_WARNING PREFIX
+ "%d duplicate %s table ignored.\n", count,
+ acpi_table_signatures[id]);
}
return count;
}
-
-static int __init
-acpi_table_get_sdt (
- struct acpi_table_rsdp *rsdp)
+static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp)
{
struct acpi_table_header *header = NULL;
- unsigned int i, id = 0;
+ unsigned int i, id = 0;
if (!rsdp)
return -EINVAL;
@@ -413,24 +412,25 @@ acpi_table_get_sdt (
/* First check XSDT (but only on ACPI 2.0-compatible systems) */
if ((rsdp->revision >= 2) &&
- (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) {
-
- struct acpi_table_xsdt *mapped_xsdt = NULL;
+ (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) {
+
+ struct acpi_table_xsdt *mapped_xsdt = NULL;
- sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
+ sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address;
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
if (!header) {
- printk(KERN_WARNING PREFIX "Unable to map XSDT header\n");
+ printk(KERN_WARNING PREFIX
+ "Unable to map XSDT header\n");
return -ENODEV;
}
/* remap in the entire table before processing */
mapped_xsdt = (struct acpi_table_xsdt *)
- __acpi_map_table(sdt_pa, header->length);
+ __acpi_map_table(sdt_pa, header->length);
if (!mapped_xsdt) {
printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
return -ENODEV;
@@ -438,7 +438,8 @@ acpi_table_get_sdt (
header = &mapped_xsdt->header;
if (strncmp(header->signature, "XSDT", 4)) {
- printk(KERN_WARNING PREFIX "XSDT signature incorrect\n");
+ printk(KERN_WARNING PREFIX
+ "XSDT signature incorrect\n");
return -ENODEV;
}
@@ -447,36 +448,39 @@ acpi_table_get_sdt (
return -ENODEV;
}
- sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3;
+ sdt_count =
+ (header->length - sizeof(struct acpi_table_header)) >> 3;
if (sdt_count > ACPI_MAX_TABLES) {
- printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
- (sdt_count - ACPI_MAX_TABLES));
+ printk(KERN_WARNING PREFIX
+ "Truncated %lu XSDT entries\n",
+ (sdt_count - ACPI_MAX_TABLES));
sdt_count = ACPI_MAX_TABLES;
}
for (i = 0; i < sdt_count; i++)
- sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
+ sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i];
}
/* Then check RSDT */
else if (rsdp->rsdt_address) {
- struct acpi_table_rsdt *mapped_rsdt = NULL;
+ struct acpi_table_rsdt *mapped_rsdt = NULL;
sdt_pa = rsdp->rsdt_address;
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
if (!header) {
- printk(KERN_WARNING PREFIX "Unable to map RSDT header\n");
+ printk(KERN_WARNING PREFIX
+ "Unable to map RSDT header\n");
return -ENODEV;
}
/* remap in the entire table before processing */
mapped_rsdt = (struct acpi_table_rsdt *)
- __acpi_map_table(sdt_pa, header->length);
+ __acpi_map_table(sdt_pa, header->length);
if (!mapped_rsdt) {
printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
return -ENODEV;
@@ -484,7 +488,8 @@ acpi_table_get_sdt (
header = &mapped_rsdt->header;
if (strncmp(header->signature, "RSDT", 4)) {
- printk(KERN_WARNING PREFIX "RSDT signature incorrect\n");
+ printk(KERN_WARNING PREFIX
+ "RSDT signature incorrect\n");
return -ENODEV;
}
@@ -493,19 +498,22 @@ acpi_table_get_sdt (
return -ENODEV;
}
- sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2;
+ sdt_count =
+ (header->length - sizeof(struct acpi_table_header)) >> 2;
if (sdt_count > ACPI_MAX_TABLES) {
- printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
- (sdt_count - ACPI_MAX_TABLES));
+ printk(KERN_WARNING PREFIX
+ "Truncated %lu RSDT entries\n",
+ (sdt_count - ACPI_MAX_TABLES));
sdt_count = ACPI_MAX_TABLES;
}
for (i = 0; i < sdt_count; i++)
- sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
+ sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i];
}
else {
- printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n");
+ printk(KERN_WARNING PREFIX
+ "No System Description Table (RSDT/XSDT) specified in RSDP\n");
return -ENODEV;
}
@@ -515,18 +523,17 @@ acpi_table_get_sdt (
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_entry[i].pa,
- sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_entry[i].pa,
+ sizeof(struct acpi_table_header));
if (!header)
continue;
/* remap in the entire table before processing */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_entry[i].pa,
- header->length);
+ __acpi_map_table(sdt_entry[i].pa, header->length);
if (!header)
continue;
-
+
acpi_table_print(header, sdt_entry[i].pa);
if (acpi_table_compute_checksum(header, header->length)) {
@@ -537,9 +544,9 @@ acpi_table_get_sdt (
sdt_entry[i].size = header->length;
for (id = 0; id < ACPI_TABLE_COUNT; id++) {
- if (!strncmp((char *) &header->signature,
- acpi_table_signatures[id],
- sizeof(header->signature))) {
+ if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[id],
+ sizeof(header->signature))) {
sdt_entry[i].id = id;
}
}
@@ -551,7 +558,7 @@ acpi_table_get_sdt (
* against. Unfortunately, we don't know the phys_addr, so just
* print 0. Maybe no one will notice.
*/
- if(!acpi_get_table_header_early(ACPI_DSDT, &header))
+ if (!acpi_get_table_header_early(ACPI_DSDT, &header))
acpi_table_print(header, 0);
return 0;
@@ -566,12 +573,11 @@ acpi_table_get_sdt (
* result: sdt_entry[] is initialized
*/
-int __init
-acpi_table_init (void)
+int __init acpi_table_init(void)
{
- struct acpi_table_rsdp *rsdp = NULL;
- unsigned long rsdp_phys = 0;
- int result = 0;
+ struct acpi_table_rsdp *rsdp = NULL;
+ unsigned long rsdp_phys = 0;
+ int result = 0;
/* Locate and map the Root System Description Table (RSDP) */
@@ -581,19 +587,25 @@ acpi_table_init (void)
return -ENODEV;
}
- rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys);
+ rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys);
if (!rsdp) {
printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
return -ENODEV;
}
- printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
- rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
+ printk(KERN_DEBUG PREFIX
+ "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
+ rsdp->revision, rsdp->oem_id, (void *)rsdp_phys);
if (rsdp->revision < 2)
- result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
+ result =
+ acpi_table_compute_checksum(rsdp,
+ sizeof(struct acpi_table_rsdp));
else
- result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
+ result =
+ acpi_table_compute_checksum(rsdp,
+ ((struct acpi20_table_rsdp *)
+ rsdp)->length);
if (result) {
printk(KERN_WARNING " >>> ERROR: Invalid checksum\n");
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index 92e0c31539be..a03939399fa9 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -46,28 +46,22 @@
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbconvrt")
+ACPI_MODULE_NAME("tbconvrt")
/* Local prototypes */
-
static void
-acpi_tb_init_generic_address (
- struct acpi_generic_address *new_gas_struct,
- u8 register_bit_width,
- acpi_physical_address address);
+acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
+ u8 register_bit_width,
+ acpi_physical_address address);
static void
-acpi_tb_convert_fadt1 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev1 *original_fadt);
+acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *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_rev2 *local_fadt,
+ struct fadt_descriptor_rev2 *original_fadt);
u8 acpi_fadt_is_v1;
EXPORT_SYMBOL(acpi_fadt_is_v1);
@@ -87,21 +81,19 @@ EXPORT_SYMBOL(acpi_fadt_is_v1);
******************************************************************************/
u32
-acpi_tb_get_table_count (
- struct rsdp_descriptor *RSDP,
- struct acpi_table_header *RSDT)
+acpi_tb_get_table_count(struct rsdp_descriptor *RSDP,
+ struct acpi_table_header *RSDT)
{
- u32 pointer_size;
+ u32 pointer_size;
+ ACPI_FUNCTION_ENTRY();
- ACPI_FUNCTION_ENTRY ();
+ /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
-
- if (RSDP->revision < 2) {
- pointer_size = sizeof (u32);
- }
- else {
- pointer_size = sizeof (u64);
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ pointer_size = sizeof(u32);
+ } else {
+ pointer_size = sizeof(u64);
}
/*
@@ -110,10 +102,10 @@ acpi_tb_get_table_count (
* pointers contained within the RSDT/XSDT. The size of the pointers
* is architecture-dependent.
*/
- return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size);
+ return ((RSDT->length -
+ sizeof(struct acpi_table_header)) / pointer_size);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_to_xsdt
@@ -126,64 +118,65 @@ acpi_tb_get_table_count (
*
******************************************************************************/
-acpi_status
-acpi_tb_convert_to_xsdt (
- struct acpi_table_desc *table_info)
+acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
{
- acpi_size table_size;
- u32 i;
- XSDT_DESCRIPTOR *new_table;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_size table_size;
+ u32 i;
+ XSDT_DESCRIPTOR *new_table;
+ ACPI_FUNCTION_ENTRY();
/* Compute size of the converted XSDT */
- table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) +
- sizeof (struct acpi_table_header);
+ table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) +
+ sizeof(struct acpi_table_header);
/* Allocate an XSDT */
- new_table = ACPI_MEM_CALLOCATE (table_size);
+ new_table = ACPI_MEM_CALLOCATE(table_size);
if (!new_table) {
return (AE_NO_MEMORY);
}
/* Copy the header and set the length */
- ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(new_table, table_info->pointer,
+ sizeof(struct acpi_table_header));
new_table->length = (u32) table_size;
/* Copy the table pointers */
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
- if (acpi_gbl_RSDP->revision < 2) {
- ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
- (ACPI_CAST_PTR (struct rsdt_descriptor_rev1,
- table_info->pointer))->table_offset_entry[i]);
- }
- else {
+ /* 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,
+ table_info->pointer))->
+ table_offset_entry[i]);
+ } else {
new_table->table_offset_entry[i] =
- (ACPI_CAST_PTR (XSDT_DESCRIPTOR,
- table_info->pointer))->table_offset_entry[i];
+ (ACPI_CAST_PTR(XSDT_DESCRIPTOR,
+ table_info->pointer))->
+ table_offset_entry[i];
}
}
/* Delete the original table (either mapped or in a buffer) */
- acpi_tb_delete_single_table (table_info);
+ acpi_tb_delete_single_table(table_info);
/* Point the table descriptor to the new table */
- table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table);
- table_info->length = table_size;
- table_info->allocation = ACPI_MEM_ALLOCATED;
+ table_info->pointer =
+ ACPI_CAST_PTR(struct acpi_table_header, new_table);
+ table_info->length = table_size;
+ table_info->allocation = ACPI_MEM_ALLOCATED;
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_generic_address
@@ -199,21 +192,19 @@ acpi_tb_convert_to_xsdt (
******************************************************************************/
static void
-acpi_tb_init_generic_address (
- struct acpi_generic_address *new_gas_struct,
- u8 register_bit_width,
- acpi_physical_address address)
+acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
+ u8 register_bit_width,
+ acpi_physical_address address)
{
- ACPI_STORE_ADDRESS (new_gas_struct->address, address);
+ ACPI_STORE_ADDRESS(new_gas_struct->address, address);
new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
new_gas_struct->register_bit_width = register_bit_width;
new_gas_struct->register_bit_offset = 0;
- new_gas_struct->access_width = 0;
+ new_gas_struct->access_width = 0;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt1
@@ -228,9 +219,8 @@ acpi_tb_init_generic_address (
******************************************************************************/
static void
-acpi_tb_convert_fadt1 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev1 *original_fadt)
+acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev1 *original_fadt)
{
/* ACPI 1.0 FACS */
@@ -243,12 +233,14 @@ acpi_tb_convert_fadt1 (
* The 2.0 table is an extension of the 1.0 table, so the entire 1.0
* table can be copied first, then expand some fields to 64 bits.
*/
- ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1));
+ ACPI_MEMCPY(local_fadt, original_fadt,
+ sizeof(struct fadt_descriptor_rev1));
/* Convert table pointers to 64-bit fields */
- ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
- ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
+ ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
+ local_fadt->V1_firmware_ctrl);
+ ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
/*
* System Interrupt Model isn't used in ACPI 2.0
@@ -283,17 +275,17 @@ acpi_tb_convert_fadt1 (
* It primarily adds the FADT reset mechanism.
*/
if ((original_fadt->revision == 2) &&
- (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) {
+ (original_fadt->length ==
+ sizeof(struct fadt_descriptor_rev2_minus))) {
/*
* Grab the entire generic address struct, plus the 1-byte reset value
* that immediately follows.
*/
- ACPI_MEMCPY (&local_fadt->reset_register,
- &(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus,
- original_fadt))->reset_register,
- sizeof (struct acpi_generic_address) + 1);
- }
- else {
+ ACPI_MEMCPY(&local_fadt->reset_register,
+ &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus,
+ original_fadt))->reset_register,
+ sizeof(struct acpi_generic_address) + 1);
+ } else {
/*
* Since there isn't any equivalence in 1.0 and since it is highly
* likely that a 1.0 system has legacy support.
@@ -304,43 +296,60 @@ acpi_tb_convert_fadt1 (
/*
* Convert the V1.0 block addresses to V2.0 GAS structures
*/
- acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len,
- (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
- acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0,
- (acpi_physical_address) local_fadt->V1_gpe0_blk);
- acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0,
- (acpi_physical_address) local_fadt->V1_gpe1_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1a_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1b_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1a_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1b_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
+ local_fadt->pm2_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm2_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
+ local_fadt->pm_tm_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm_tmr_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0,
+ (acpi_physical_address) local_fadt->
+ V1_gpe0_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0,
+ (acpi_physical_address) local_fadt->
+ V1_gpe1_blk);
/* Create separate GAS structs for the PM1 Enable registers */
- acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1a_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
- acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1b_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1b_evt_blk.
+ address +
+ ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len)));
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt2
@@ -356,14 +365,14 @@ acpi_tb_convert_fadt1 (
******************************************************************************/
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_rev2 *local_fadt,
+ struct fadt_descriptor_rev2 *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_rev2));
/*
* "X" fields are optional extensions to the original V1.0 fields, so
@@ -371,86 +380,99 @@ acpi_tb_convert_fadt2 (
* is zero.
*/
if (!(local_fadt->xfirmware_ctrl)) {
- ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl,
- local_fadt->V1_firmware_ctrl);
+ ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
+ local_fadt->V1_firmware_ctrl);
}
if (!(local_fadt->Xdsdt)) {
- ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
+ ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
}
if (!(local_fadt->xpm1a_evt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk,
- local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1a_evt_blk);
}
if (!(local_fadt->xpm1b_evt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk,
- local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1b_evt_blk);
}
if (!(local_fadt->xpm1a_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk,
- local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1a_cnt_blk);
}
if (!(local_fadt->xpm1b_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk,
- local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1b_cnt_blk);
}
if (!(local_fadt->xpm2_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk,
- local_fadt->pm2_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
+ local_fadt->pm2_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm2_cnt_blk);
}
if (!(local_fadt->xpm_tmr_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk,
- local_fadt->pm_tm_len,
- (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
+ local_fadt->pm_tm_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm_tmr_blk);
}
if (!(local_fadt->xgpe0_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xgpe0_blk,
- 0, (acpi_physical_address) local_fadt->V1_gpe0_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe0_blk,
+ 0,
+ (acpi_physical_address)
+ local_fadt->V1_gpe0_blk);
}
if (!(local_fadt->xgpe1_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xgpe1_blk,
- 0, (acpi_physical_address) local_fadt->V1_gpe1_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe1_blk,
+ 0,
+ (acpi_physical_address)
+ local_fadt->V1_gpe1_blk);
}
/* Create separate GAS structs for the PM1 Enable registers */
- acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1a_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
acpi_gbl_xpm1a_enable.address_space_id =
- local_fadt->xpm1a_evt_blk.address_space_id;
+ local_fadt->xpm1a_evt_blk.address_space_id;
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
- acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1b_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1b_evt_blk.
+ address +
+ ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len)));
acpi_gbl_xpm1b_enable.address_space_id =
- local_fadt->xpm1b_evt_blk.address_space_id;
+ local_fadt->xpm1b_evt_blk.address_space_id;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_table_fadt
@@ -467,83 +489,76 @@ acpi_tb_convert_fadt2 (
*
******************************************************************************/
-acpi_status
-acpi_tb_convert_table_fadt (
- void)
+acpi_status acpi_tb_convert_table_fadt(void)
{
- struct fadt_descriptor_rev2 *local_fadt;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
+ struct fadt_descriptor_rev2 *local_fadt;
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_TRACE("tb_convert_table_fadt");
/*
* acpi_gbl_FADT is valid. Validate the FADT length. The table must be
* at least as long as the version 1.0 FADT
*/
- if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) {
- ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n",
- acpi_gbl_FADT->length));
- return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
+ if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) {
+ ACPI_REPORT_ERROR(("FADT is invalid, too short: 0x%X\n",
+ acpi_gbl_FADT->length));
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/* Allocate buffer for the ACPI 2.0(+) FADT */
- local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2));
+ local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2));
if (!local_fadt) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ 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_rev2)) {
/* Length is too short to be a V2.0 table */
- ACPI_REPORT_WARNING ((
- "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
- acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
+ ACPI_REPORT_WARNING(("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
- acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
- }
- else {
+ acpi_tb_convert_fadt1(local_fadt,
+ (void *)acpi_gbl_FADT);
+ } else {
/* Valid V2.0 table */
- acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT);
+ acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT);
}
- }
- else {
+ } else {
/* Valid V1.0 table */
- acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
+ acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT);
}
/* 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(FADT_DESCRIPTOR);
/* Free the original table */
table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
- acpi_tb_delete_single_table (table_desc);
+ acpi_tb_delete_single_table(table_desc);
/* Install the new table */
- 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->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);
/* Dump the entire FADT */
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Hex dump of common internal FADT, size %d (%X)\n",
- acpi_gbl_FADT->length, acpi_gbl_FADT->length));
- ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Hex dump of common internal FADT, size %d (%X)\n",
+ acpi_gbl_FADT->length, acpi_gbl_FADT->length));
+ ACPI_DUMP_BUFFER((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_build_common_facs
@@ -557,26 +572,21 @@ acpi_tb_convert_table_fadt (
*
******************************************************************************/
-acpi_status
-acpi_tb_build_common_facs (
- struct acpi_table_desc *table_info)
+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 */
if (acpi_gbl_FACS->length < 24) {
- ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n",
- acpi_gbl_FACS->length));
- return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
+ ACPI_REPORT_ERROR(("Invalid FACS table length: 0x%X\n",
+ acpi_gbl_FACS->length));
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
if (acpi_gbl_FACS->length < 64) {
- ACPI_REPORT_WARNING ((
- "FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
- acpi_gbl_FACS->length));
+ ACPI_REPORT_WARNING(("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", acpi_gbl_FACS->length));
}
/* Copy fields to the new FACS */
@@ -584,22 +594,22 @@ acpi_tb_build_common_facs (
acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
if ((acpi_gbl_RSDP->revision < 2) ||
- (acpi_gbl_FACS->length < 32) ||
- (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
+ (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,
- &(acpi_gbl_FACS->firmware_waking_vector));
+ acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64,
+ &
+ (acpi_gbl_FACS->
+ firmware_waking_vector));
acpi_gbl_common_fACS.vector_width = 32;
- }
- else {
+ } else {
/* ACPI 2.0 FACS with valid X_ field */
- acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector;
+ acpi_gbl_common_fACS.firmware_waking_vector =
+ &acpi_gbl_FACS->xfirmware_waking_vector;
acpi_gbl_common_fACS.vector_width = 64;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 4ab2aadc6133..6acd5aeb093e 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -41,27 +41,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbget")
+ACPI_MODULE_NAME("tbget")
/* Local prototypes */
-
static acpi_status
-acpi_tb_get_this_table (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info);
+acpi_tb_get_this_table(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info);
static acpi_status
-acpi_tb_table_override (
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info);
-
+acpi_tb_table_override(struct acpi_table_header *header,
+ struct acpi_table_desc *table_info);
/*******************************************************************************
*
@@ -78,37 +72,34 @@ acpi_tb_table_override (
******************************************************************************/
acpi_status
-acpi_tb_get_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info)
+acpi_tb_get_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table");
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE("tb_get_table");
/* Get the header in order to get signature and table size */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n",
- header.length, acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get ACPI table (size %X), %s\n",
+ header.length,
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_header
@@ -127,16 +118,13 @@ acpi_tb_get_table (
******************************************************************************/
acpi_status
-acpi_tb_get_table_header (
- struct acpi_pointer *address,
- struct acpi_table_header *return_header)
+acpi_tb_get_table_header(struct acpi_pointer *address,
+ struct acpi_table_header *return_header)
{
- acpi_status status = AE_OK;
- struct acpi_table_header *header = NULL;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_header");
+ acpi_status status = AE_OK;
+ struct acpi_table_header *header = NULL;
+ ACPI_FUNCTION_TRACE("tb_get_table_header");
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -148,46 +136,42 @@ acpi_tb_get_table_header (
/* Pointer matches processor mode, copy the header */
- ACPI_MEMCPY (return_header, address->pointer.logical,
- sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(return_header, address->pointer.logical,
+ sizeof(struct acpi_table_header));
break;
-
case ACPI_LOGMODE_PHYSPTR:
- /* Create a logical address for the physical pointer*/
+ /* Create a logical address for the physical pointer */
- status = acpi_os_map_memory (address->pointer.physical,
- sizeof (struct acpi_table_header), (void *) &header);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not map memory at %8.8X%8.8X for length %X\n",
- ACPI_FORMAT_UINT64 (address->pointer.physical),
- sizeof (struct acpi_table_header)));
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address->pointer.physical,
+ sizeof(struct acpi_table_header),
+ (void *)&header);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_FORMAT_UINT64(address->pointer.physical), sizeof(struct acpi_table_header)));
+ return_ACPI_STATUS(status);
}
/* Copy header and delete mapping */
- ACPI_MEMCPY (return_header, header, sizeof (struct acpi_table_header));
- acpi_os_unmap_memory (header, sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(return_header, header,
+ sizeof(struct acpi_table_header));
+ acpi_os_unmap_memory(header, sizeof(struct acpi_table_header));
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid address flags %X\n",
- address->pointer_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("Invalid address flags %X\n",
+ address->pointer_type));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
- return_header->signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
+ return_header->signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_body
@@ -209,37 +193,33 @@ acpi_tb_get_table_header (
******************************************************************************/
acpi_status
-acpi_tb_get_table_body (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_get_table_body(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_body");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_get_table_body");
if (!table_info || !address) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Attempt table override. */
- status = acpi_tb_table_override (header, table_info);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_tb_table_override(header, table_info);
+ if (ACPI_SUCCESS(status)) {
/* Table was overridden by the host OS */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* No override, get the original table */
- status = acpi_tb_get_this_table (address, header, table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_this_table(address, header, table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_table_override
@@ -255,61 +235,57 @@ acpi_tb_get_table_body (
******************************************************************************/
static acpi_status
-acpi_tb_table_override (
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_table_override(struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_header *new_table;
- acpi_status status;
- struct acpi_pointer address;
-
-
- ACPI_FUNCTION_TRACE ("tb_table_override");
+ struct acpi_table_header *new_table;
+ acpi_status status;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("tb_table_override");
/*
* The OSL will examine the header and decide whether to override this
* table. If it decides to override, a table will be returned in new_table,
* which we will then copy.
*/
- status = acpi_os_table_override (header, &new_table);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_table_override(header, &new_table);
+ if (ACPI_FAILURE(status)) {
/* Some severe error from the OSL, but we basically ignore it */
- ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_REPORT_ERROR(("Could not override ACPI table, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
if (!new_table) {
/* No table override */
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* We have a new table to override the old one. Get a copy of
* the new one. We know that the new table has a logical pointer.
*/
- address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
address.pointer.logical = new_table;
- status = acpi_tb_get_this_table (&address, new_table, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not copy override ACPI table, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_this_table(&address, new_table, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not copy override ACPI table, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* Copy the table info */
- ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n",
- table_info->pointer->signature));
+ ACPI_REPORT_INFO(("Table [%4.4s] replaced by host OS\n",
+ table_info->pointer->signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_this_table
@@ -329,18 +305,15 @@ acpi_tb_table_override (
******************************************************************************/
static acpi_status
-acpi_tb_get_this_table (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_get_this_table(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_header *full_table = NULL;
- u8 allocation;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_this_table");
+ struct acpi_table_header *full_table = NULL;
+ u8 allocation;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("tb_get_this_table");
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -352,38 +325,33 @@ acpi_tb_get_this_table (
/* Pointer matches processor mode, copy the table to a new buffer */
- full_table = ACPI_MEM_ALLOCATE (header->length);
+ full_table = ACPI_MEM_ALLOCATE(header->length);
if (!full_table) {
- ACPI_REPORT_ERROR ((
- "Could not allocate table memory for [%4.4s] length %X\n",
- header->signature, header->length));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_REPORT_ERROR(("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the entire table (including header) to the local buffer */
- ACPI_MEMCPY (full_table, address->pointer.logical, header->length);
+ ACPI_MEMCPY(full_table, address->pointer.logical,
+ header->length);
/* Save allocation type */
allocation = ACPI_MEM_ALLOCATED;
break;
-
case ACPI_LOGMODE_PHYSPTR:
/*
* Just map the table's physical memory
* into our address space.
*/
- status = acpi_os_map_memory (address->pointer.physical,
- (acpi_size) header->length, (void *) &full_table);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
- header->signature,
- ACPI_FORMAT_UINT64 (address->pointer.physical),
- header->length));
+ status = acpi_os_map_memory(address->pointer.physical,
+ (acpi_size) header->length,
+ (void *)&full_table);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64(address->pointer.physical), header->length));
return (status);
}
@@ -392,12 +360,11 @@ acpi_tb_get_this_table (
allocation = ACPI_MEM_MAPPED;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n",
- address->pointer_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid address flags %X\n",
+ address->pointer_type));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -405,10 +372,10 @@ acpi_tb_get_this_table (
* even the ones whose signature we don't recognize
*/
if (table_info->type != ACPI_TABLE_FACS) {
- status = acpi_tb_verify_table_checksum (full_table);
+ status = acpi_tb_verify_table_checksum(full_table);
#if (!ACPI_CHECKSUM_ABORT)
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Ignore the error if configuration says so */
status = AE_OK;
@@ -418,19 +385,19 @@ acpi_tb_get_this_table (
/* Return values */
- table_info->pointer = full_table;
- table_info->length = (acpi_size) header->length;
- table_info->allocation = allocation;
+ table_info->pointer = full_table;
+ table_info->length = (acpi_size) header->length;
+ table_info->allocation = allocation;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
- full_table->signature,
- ACPI_FORMAT_UINT64 (address->pointer.physical), full_table));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
+ full_table->signature,
+ ACPI_FORMAT_UINT64(address->pointer.physical),
+ full_table));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_ptr
@@ -447,24 +414,20 @@ acpi_tb_get_this_table (
******************************************************************************/
acpi_status
-acpi_tb_get_table_ptr (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header **table_ptr_loc)
+acpi_tb_get_table_ptr(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header **table_ptr_loc)
{
- struct acpi_table_desc *table_desc;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_ptr");
+ 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);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (table_type > ACPI_TABLE_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -476,15 +439,16 @@ acpi_tb_get_table_ptr (
*table_ptr_loc = NULL;
if (acpi_gbl_table_lists[table_type].next) {
- *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer;
+ *table_ptr_loc =
+ acpi_gbl_table_lists[table_type].next->pointer;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Check for instance out of range */
if (instance > acpi_gbl_table_lists[table_type].count) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Walk the list to get the desired table
@@ -503,6 +467,5 @@ acpi_tb_get_table_ptr (
*table_ptr_loc = table_desc->pointer;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index eea5b8cb5ebb..8d72343537e7 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -41,27 +41,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbgetall")
+ACPI_MODULE_NAME("tbgetall")
/* Local prototypes */
-
static acpi_status
-acpi_tb_get_primary_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info);
+acpi_tb_get_primary_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info);
static acpi_status
-acpi_tb_get_secondary_table (
- struct acpi_pointer *address,
- acpi_string signature,
- struct acpi_table_desc *table_info);
-
+acpi_tb_get_secondary_table(struct acpi_pointer *address,
+ acpi_string signature,
+ struct acpi_table_desc *table_info);
/*******************************************************************************
*
@@ -77,58 +71,54 @@ acpi_tb_get_secondary_table (
******************************************************************************/
static acpi_status
-acpi_tb_get_primary_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info)
+acpi_tb_get_primary_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_primary_table");
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE("tb_get_primary_table");
/* Ignore a NULL address in the RSDT */
if (!address->pointer.value) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the header in order to get signature and table size */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Clear the table_info */
- ACPI_MEMSET (table_info, 0, sizeof (struct acpi_table_desc));
+ ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc));
/*
* Check the table signature and make sure it is recognized.
* Also checks the header checksum
*/
table_info->pointer = &header;
- status = acpi_tb_recognize_table (table_info, ACPI_TABLE_PRIMARY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table */
- status = acpi_tb_install_table (table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_install_table(table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_secondary_table
@@ -143,32 +133,27 @@ acpi_tb_get_primary_table (
******************************************************************************/
static acpi_status
-acpi_tb_get_secondary_table (
- struct acpi_pointer *address,
- acpi_string signature,
- struct acpi_table_desc *table_info)
+acpi_tb_get_secondary_table(struct acpi_pointer *address,
+ acpi_string signature,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature);
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature);
/* Get the header in order to match the signature */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Signature must match request */
- if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
- ACPI_REPORT_ERROR ((
- "Incorrect table signature - wanted [%s] found [%4.4s]\n",
- signature, header.signature));
- return_ACPI_STATUS (AE_BAD_SIGNATURE);
+ if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
+ ACPI_REPORT_ERROR(("Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature));
+ return_ACPI_STATUS(AE_BAD_SIGNATURE);
}
/*
@@ -176,25 +161,24 @@ acpi_tb_get_secondary_table (
* Also checks the header checksum
*/
table_info->pointer = &header;
- status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table */
- status = acpi_tb_install_table (table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_install_table(table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_required_tables
@@ -214,23 +198,19 @@ acpi_tb_get_secondary_table (
*
******************************************************************************/
-acpi_status
-acpi_tb_get_required_tables (
- void)
+acpi_status acpi_tb_get_required_tables(void)
{
- acpi_status status = AE_OK;
- u32 i;
- struct acpi_table_desc table_info;
- struct acpi_pointer address;
-
+ acpi_status status = AE_OK;
+ u32 i;
+ 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));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
+ acpi_gbl_rsdt_table_count));
-
- address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
/*
* Loop through all table pointers found in RSDT.
@@ -243,84 +223,79 @@ acpi_tb_get_required_tables (
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];
+ address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
/*
* Get the tables needed by this subsystem (FADT and any SSDTs).
* NOTE: All other tables are completely ignored at this time.
*/
- status = acpi_tb_get_primary_table (&address, &table_info);
+ status = acpi_tb_get_primary_table(&address, &table_info);
if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
- ACPI_REPORT_WARNING (("%s, while getting table at %8.8X%8.8X\n",
- acpi_format_exception (status),
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ ACPI_REPORT_WARNING(("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception(status), ACPI_FORMAT_UINT64(address.pointer.value)));
}
}
/* We must have a FADT to continue */
if (!acpi_gbl_FADT) {
- ACPI_REPORT_ERROR (("No FADT present in RSDT/XSDT\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_REPORT_ERROR(("No FADT present in RSDT/XSDT\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* Convert the FADT to a common format. This allows earlier revisions of
* the table to coexist with newer versions, using common access code.
*/
- status = acpi_tb_convert_table_fadt ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not convert FADT to internal common format\n"));
- return_ACPI_STATUS (status);
+ status = acpi_tb_convert_table_fadt();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not convert FADT to internal common format\n"));
+ return_ACPI_STATUS(status);
}
/* Get the FACS (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl;
- status = acpi_tb_get_secondary_table (&address, FACS_SIG, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get/install the FACS, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get/install the FACS, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
* Create the common FACS pointer table
* (Contains pointers to the original table)
*/
- status = acpi_tb_build_common_facs (&table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_build_common_facs(&table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get/install the DSDT (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->Xdsdt;
- status = acpi_tb_get_secondary_table (&address, DSDT_SIG, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get/install the DSDT\n"));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get/install the DSDT\n"));
+ return_ACPI_STATUS(status);
}
/* Set Integer Width (32/64) based upon DSDT revision */
- acpi_ut_set_integer_width (acpi_gbl_DSDT->revision);
+ acpi_ut_set_integer_width(acpi_gbl_DSDT->revision);
/* Dump the entire DSDT */
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
- acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width));
- ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
+ acpi_gbl_DSDT->length, acpi_gbl_DSDT->length,
+ acpi_gbl_integer_bit_width));
+ ACPI_DUMP_BUFFER((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
/* Always delete the RSDP mapping, we are done with it */
- acpi_tb_delete_tables_by_type (ACPI_TABLE_RSDP);
- return_ACPI_STATUS (status);
+ acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 629b64c8193d..10db8484e462 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -41,22 +41,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbinstal")
+ACPI_MODULE_NAME("tbinstal")
/* Local prototypes */
-
static acpi_status
-acpi_tb_match_signature (
- char *signature,
- struct acpi_table_desc *table_info,
- u8 search_type);
-
+acpi_tb_match_signature(char *signature,
+ struct acpi_table_desc *table_info, u8 search_type);
/*******************************************************************************
*
@@ -74,16 +68,12 @@ acpi_tb_match_signature (
******************************************************************************/
static acpi_status
-acpi_tb_match_signature (
- char *signature,
- struct acpi_table_desc *table_info,
- u8 search_type)
+acpi_tb_match_signature(char *signature,
+ struct acpi_table_desc *table_info, u8 search_type)
{
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("tb_match_signature");
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("tb_match_signature");
/* Search for a signature match among the known table types */
@@ -92,30 +82,30 @@ acpi_tb_match_signature (
continue;
}
- if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature,
- acpi_gbl_table_data[i].sig_length)) {
+ 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) {
table_info->type = (u8) i;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
- (char *) acpi_gbl_table_data[i].signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
+ (char *)acpi_gbl_table_data[i].
+ signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
- (char *) signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
+ (char *)signature));
- return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED);
+ return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_install_table
@@ -124,46 +114,52 @@ acpi_tb_match_signature (
*
* RETURN: Status
*
- * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must
- * already be loaded and validated.
- * Install the table into the global data structs.
+ * DESCRIPTION: Install the table into the global data structures.
*
******************************************************************************/
-acpi_status
-acpi_tb_install_table (
- struct acpi_table_desc *table_info)
+acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info)
{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE ("tb_install_table");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_install_table");
/* Lock tables while installing */
- status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n",
- table_info->pointer->signature, acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not acquire table mutex, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Ignore a table that is already installed. For example, some BIOS
+ * ASL code will repeatedly attempt to load the same SSDT.
+ */
+ status = acpi_tb_is_table_installed(table_info);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
}
/* Install the table into the global data structure */
- status = acpi_tb_init_table_descriptor (table_info->type, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n",
- table_info->pointer->signature, acpi_format_exception (status)));
+ status = acpi_tb_init_table_descriptor(table_info->type, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not install table [%4.4s], %s\n",
+ table_info->pointer->signature,
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n",
- acpi_gbl_table_data[table_info->type].name, table_info->pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n",
+ acpi_gbl_table_data[table_info->type].name,
+ table_info->pointer));
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_recognize_table
@@ -186,22 +182,18 @@ acpi_tb_install_table (
******************************************************************************/
acpi_status
-acpi_tb_recognize_table (
- struct acpi_table_desc *table_info,
- u8 search_type)
+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");
+ struct acpi_table_header *table_header;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_recognize_table");
/* Ensure that we have a valid table pointer */
- table_header = (struct acpi_table_header *) table_info->pointer;
+ table_header = (struct acpi_table_header *)table_info->pointer;
if (!table_header) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -212,25 +204,24 @@ acpi_tb_recognize_table (
* This can be any one of many valid ACPI tables, it just isn't one of
* the tables that is consumed by the core subsystem
*/
- status = acpi_tb_match_signature (table_header->signature,
- table_info, search_type);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_match_signature(table_header->signature,
+ table_info, search_type);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_tb_validate_table_header (table_header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_validate_table_header(table_header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Return the table type and length via the info struct */
table_info->length = (acpi_size) table_header->length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_table_descriptor
@@ -245,22 +236,27 @@ acpi_tb_recognize_table (
******************************************************************************/
acpi_status
-acpi_tb_init_table_descriptor (
- acpi_table_type table_type,
- struct acpi_table_desc *table_info)
+acpi_tb_init_table_descriptor(acpi_table_type table_type,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_list *list_head;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type);
+ struct acpi_table_list *list_head;
+ struct acpi_table_desc *table_desc;
+ acpi_status status;
+ 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_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
if (!table_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Get a new owner ID for the table */
+
+ status = acpi_ut_allocate_owner_id(&table_desc->owner_id);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table into the global data structure */
@@ -272,14 +268,14 @@ acpi_tb_init_table_descriptor (
* includes most ACPI tables such as the DSDT. 2) Multiple instances of
* the table are allowed. This includes SSDT and PSDTs.
*/
- if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) {
+ if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) {
/*
* Only one table allowed, and a table has alread been installed
* at this location, so return an error.
*/
if (list_head->next) {
- ACPI_MEM_FREE (table_desc);
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ ACPI_MEM_FREE(table_desc);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
table_desc->next = list_head->next;
@@ -290,8 +286,7 @@ acpi_tb_init_table_descriptor (
}
list_head->count++;
- }
- else {
+ } else {
/*
* Link the new table in to the list of tables of this type.
* Insert at the end of the list, order IS IMPORTANT.
@@ -302,8 +297,7 @@ acpi_tb_init_table_descriptor (
if (!list_head->next) {
list_head->next = table_desc;
- }
- else {
+ } else {
table_desc->next = list_head->next;
while (table_desc->next->next) {
@@ -318,15 +312,14 @@ acpi_tb_init_table_descriptor (
/* Finish initialization of the table descriptor */
- 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->table_id = acpi_ut_allocate_owner_id (
- ACPI_OWNER_TYPE_TABLE);
+ 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;
/*
@@ -334,18 +327,18 @@ acpi_tb_init_table_descriptor (
* newly installed table
*/
if (acpi_gbl_table_data[table_type].global_ptr) {
- *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer;
+ *(acpi_gbl_table_data[table_type].global_ptr) =
+ table_info->pointer;
}
/* Return Data */
- table_info->table_id = table_desc->table_id;
- table_info->installed_desc = table_desc;
+ table_info->owner_id = table_desc->owner_id;
+ table_info->installed_desc = table_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_all_tables
@@ -358,23 +351,19 @@ acpi_tb_init_table_descriptor (
*
******************************************************************************/
-void
-acpi_tb_delete_all_tables (
- void)
+void acpi_tb_delete_all_tables(void)
{
- acpi_table_type type;
-
+ acpi_table_type type;
/*
* Free memory allocated for ACPI tables
* Memory can either be mapped or allocated
*/
for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) {
- acpi_tb_delete_tables_by_type (type);
+ acpi_tb_delete_tables_by_type(type);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_tables_by_type
@@ -388,23 +377,19 @@ acpi_tb_delete_all_tables (
*
******************************************************************************/
-void
-acpi_tb_delete_tables_by_type (
- acpi_table_type type)
+void acpi_tb_delete_tables_by_type(acpi_table_type type)
{
- struct acpi_table_desc *table_desc;
- u32 count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type);
+ struct acpi_table_desc *table_desc;
+ u32 count;
+ u32 i;
+ ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type);
if (type > ACPI_TABLE_MAX) {
return_VOID;
}
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_TABLES))) {
+ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) {
return;
}
@@ -442,21 +427,20 @@ acpi_tb_delete_tables_by_type (
* 1) Get the head of the list
*/
table_desc = acpi_gbl_table_lists[type].next;
- count = acpi_gbl_table_lists[type].count;
+ count = acpi_gbl_table_lists[type].count;
/*
* 2) Walk the entire list, deleting both the allocated tables
* and the table descriptors
*/
for (i = 0; i < count; i++) {
- table_desc = acpi_tb_uninstall_table (table_desc);
+ table_desc = acpi_tb_uninstall_table(table_desc);
}
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_single_table
@@ -470,15 +454,12 @@ acpi_tb_delete_tables_by_type (
*
******************************************************************************/
-void
-acpi_tb_delete_single_table (
- struct acpi_table_desc *table_desc)
+void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc)
{
/* Must have a valid table descriptor and pointer */
- if ((!table_desc) ||
- (!table_desc->pointer)) {
+ if ((!table_desc) || (!table_desc->pointer)) {
return;
}
@@ -490,12 +471,12 @@ acpi_tb_delete_single_table (
case ACPI_MEM_ALLOCATED:
- ACPI_MEM_FREE (table_desc->pointer);
+ ACPI_MEM_FREE(table_desc->pointer);
break;
case ACPI_MEM_MAPPED:
- acpi_os_unmap_memory (table_desc->pointer, table_desc->length);
+ acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
break;
default:
@@ -503,7 +484,6 @@ acpi_tb_delete_single_table (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_uninstall_table
@@ -518,26 +498,22 @@ acpi_tb_delete_single_table (
*
******************************************************************************/
-struct acpi_table_desc *
-acpi_tb_uninstall_table (
- struct acpi_table_desc *table_desc)
+struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
+ *table_desc)
{
- struct acpi_table_desc *next_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc);
+ struct acpi_table_desc *next_desc;
+ ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc);
if (!table_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Unlink the descriptor from the doubly linked list */
if (table_desc->prev) {
table_desc->prev->next = table_desc->next;
- }
- else {
+ } else {
/* Is first on list, update list head */
acpi_gbl_table_lists[table_desc->type].next = table_desc->next;
@@ -549,16 +525,14 @@ acpi_tb_uninstall_table (
/* Free the memory allocated for the table itself */
- acpi_tb_delete_single_table (table_desc);
+ acpi_tb_delete_single_table(table_desc);
/* Free the table descriptor */
next_desc = table_desc->next;
- ACPI_MEM_FREE (table_desc);
+ ACPI_MEM_FREE(table_desc);
/* Return pointer to the next descriptor */
- return_PTR (next_desc);
+ return_PTR(next_desc);
}
-
-
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index b7ffe39c3626..ad0252c2f7db 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbrsdt")
-
+ACPI_MODULE_NAME("tbrsdt")
/*******************************************************************************
*
@@ -61,18 +58,13 @@
* DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
*
******************************************************************************/
-
-acpi_status
-acpi_tb_verify_rsdp (
- struct acpi_pointer *address)
+acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
{
- struct acpi_table_desc table_info;
- acpi_status status;
- struct rsdp_descriptor *rsdp;
-
-
- ACPI_FUNCTION_TRACE ("tb_verify_rsdp");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ struct rsdp_descriptor *rsdp;
+ ACPI_FUNCTION_TRACE("tb_verify_rsdp");
switch (address->pointer_type) {
case ACPI_LOGICAL_POINTER:
@@ -84,73 +76,53 @@ acpi_tb_verify_rsdp (
/*
* Obtain access to the RSDP structure
*/
- status = acpi_os_map_memory (address->pointer.physical,
- sizeof (struct rsdp_descriptor),
- (void *) &rsdp);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address->pointer.physical,
+ sizeof(struct rsdp_descriptor),
+ (void *)&rsdp);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /*
- * The signature and checksum must both be correct
- */
- if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
- /* Nope, BAD Signature */
+ /* Verify RSDP signature and checksum */
- status = AE_BAD_SIGNATURE;
+ status = acpi_tb_validate_rsdp(rsdp);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- /* Check the standard checksum */
-
- if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
- status = AE_BAD_CHECKSUM;
- goto cleanup;
- }
-
- /* Check extended checksum if table version >= 2 */
-
- if (rsdp->revision >= 2) {
- if (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
- status = AE_BAD_CHECKSUM;
- goto cleanup;
- }
- }
-
/* The RSDP supplied is OK */
- table_info.pointer = ACPI_CAST_PTR (struct acpi_table_header, rsdp);
- table_info.length = sizeof (struct rsdp_descriptor);
- table_info.allocation = ACPI_MEM_MAPPED;
+ table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
+ table_info.length = sizeof(struct rsdp_descriptor);
+ table_info.allocation = ACPI_MEM_MAPPED;
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Save the RSDP in a global for easy access */
- acpi_gbl_RSDP = ACPI_CAST_PTR (struct rsdp_descriptor, table_info.pointer);
- return_ACPI_STATUS (status);
-
+ acpi_gbl_RSDP =
+ ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer);
+ return_ACPI_STATUS(status);
/* Error exit */
-cleanup:
+ cleanup:
if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
- acpi_os_unmap_memory (rsdp, sizeof (struct rsdp_descriptor));
+ acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_rsdt_address
@@ -159,35 +131,35 @@ cleanup:
*
* RETURN: None, Address
*
- * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the
- * version of the RSDP
+ * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the
+ * version of the RSDP and whether the XSDT pointer is valid
*
******************************************************************************/
-void
-acpi_tb_get_rsdt_address (
- struct acpi_pointer *out_address)
+void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address)
{
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ out_address->pointer_type =
+ acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
- out_address->pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
+ /* Use XSDT if it is present */
- /*
- * For RSDP revision 0 or 1, we use the RSDT.
- * For RSDP revision 2 (and above), we use the XSDT
- */
- if (acpi_gbl_RSDP->revision < 2) {
- out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address;
- }
- else {
+ if ((acpi_gbl_RSDP->revision >= 2) &&
+ acpi_gbl_RSDP->xsdt_physical_address) {
out_address->pointer.value =
- acpi_gbl_RSDP->xsdt_physical_address;
+ acpi_gbl_RSDP->xsdt_physical_address;
+ acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT;
+ } else {
+ /* No XSDT, use the RSDT */
+
+ out_address->pointer.value =
+ acpi_gbl_RSDP->rsdt_physical_address;
+ acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_validate_rsdt
@@ -200,50 +172,43 @@ acpi_tb_get_rsdt_address (
*
******************************************************************************/
-acpi_status
-acpi_tb_validate_rsdt (
- struct acpi_table_header *table_ptr)
+acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
{
- int no_match;
-
-
- ACPI_FUNCTION_NAME ("tb_validate_rsdt");
+ int no_match;
+ ACPI_FUNCTION_NAME("tb_validate_rsdt");
/*
- * For RSDP revision 0 or 1, we use the RSDT.
- * For RSDP revision 2 and above, we use the XSDT
+ * Search for appropriate signature, RSDT or XSDT
*/
- if (acpi_gbl_RSDP->revision < 2) {
- no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG,
- sizeof (RSDT_SIG) -1);
- }
- else {
- no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG,
- sizeof (XSDT_SIG) -1);
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG,
+ sizeof(RSDT_SIG) - 1);
+ } else {
+ no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG,
+ sizeof(XSDT_SIG) - 1);
}
if (no_match) {
/* Invalid RSDT or XSDT signature */
- ACPI_REPORT_ERROR ((
- "Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
+ ACPI_REPORT_ERROR(("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
- ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20);
+ ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR,
- "RSDT/XSDT signature at %X (%p) is invalid\n",
- acpi_gbl_RSDP->rsdt_physical_address,
- (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR,
+ "RSDT/XSDT signature at %X (%p) is invalid\n",
+ acpi_gbl_RSDP->rsdt_physical_address,
+ (void *)(acpi_native_uint) acpi_gbl_RSDP->
+ rsdt_physical_address));
- if (acpi_gbl_RSDP->revision < 2) {
- ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n"))
- }
- else {
- ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n"))
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ ACPI_REPORT_ERROR(("Looking for RSDT\n"))
+ } else {
+ ACPI_REPORT_ERROR(("Looking for XSDT\n"))
}
- ACPI_DUMP_BUFFER ((char *) table_ptr, 48);
+ ACPI_DUMP_BUFFER((char *)table_ptr, 48);
return (AE_BAD_SIGNATURE);
}
@@ -251,7 +216,6 @@ acpi_tb_validate_rsdt (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_rsdt
@@ -264,66 +228,61 @@ acpi_tb_validate_rsdt (
*
******************************************************************************/
-acpi_status
-acpi_tb_get_table_rsdt (
- void)
+acpi_status acpi_tb_get_table_rsdt(void)
{
- struct acpi_table_desc table_info;
- acpi_status status;
- struct acpi_pointer address;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_rsdt");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("tb_get_table_rsdt");
/* Get the RSDT/XSDT via the RSDP */
- acpi_tb_get_rsdt_address (&address);
+ acpi_tb_get_rsdt_address(&address);
table_info.type = ACPI_TABLE_XSDT;
- status = acpi_tb_get_table (&address, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT/XSDT, %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_table(&address, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not get the RSDT/XSDT, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
- acpi_gbl_RSDP,
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
+ acpi_gbl_RSDP,
+ ACPI_FORMAT_UINT64(address.pointer.value)));
/* Check the RSDT or XSDT signature */
- status = acpi_tb_validate_rsdt (table_info.pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_validate_rsdt(table_info.pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the number of tables defined in the RSDT or XSDT */
- acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP,
- table_info.pointer);
+ acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP,
+ table_info.pointer);
/* Convert and/or copy to an XSDT structure */
- status = acpi_tb_convert_to_xsdt (&table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_convert_to_xsdt(&table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_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(XSDT_DESCRIPTOR, table_info.pointer);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
- return_ACPI_STATUS (status);
+ 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 e69d01d443d2..4b2fbb592f49 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -41,23 +41,84 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbutils")
+ACPI_MODULE_NAME("tbutils")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_status
-acpi_tb_handle_to_object (
- u16 table_id,
- struct acpi_table_desc **table_desc);
+acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc);
#endif
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_is_table_installed
+ *
+ * PARAMETERS: new_table_desc - Descriptor for new table being installed
+ *
+ * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed
+ *
+ * DESCRIPTION: Determine if an ACPI table is already installed
+ *
+ * MUTEX: Table data structures should be locked
+ *
+ ******************************************************************************/
+
+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");
+
+ /* Get the list descriptor and first table descriptor */
+
+ table_desc = acpi_gbl_table_lists[new_table_desc->type].next;
+
+ /* Examine all installed tables of this type */
+
+ while (table_desc) {
+ /*
+ * If the table lengths match, perform a full bytewise compare. This
+ * means that we will allow tables with duplicate oem_table_id(s), as
+ * long as the tables are different in some way.
+ *
+ * Checking if the table has been loaded into the namespace means that
+ * we don't check for duplicate tables during the initial installation
+ * of tables within the RSDT/XSDT.
+ */
+ if ((table_desc->loaded_into_namespace) &&
+ (table_desc->pointer->length ==
+ new_table_desc->pointer->length)
+ &&
+ (!ACPI_MEMCMP
+ ((const char *)table_desc->pointer,
+ (const char *)new_table_desc->pointer,
+ (acpi_size) 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",
+ new_table_desc->pointer->signature,
+ new_table_desc->pointer->revision,
+ new_table_desc->pointer->
+ oem_table_id));
+
+ new_table_desc->owner_id = table_desc->owner_id;
+ new_table_desc->installed_desc = table_desc;
+
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ }
+
+ /* Get next table on the list */
+
+ table_desc = table_desc->next;
+ }
+
+ return_ACPI_STATUS(AE_OK);
+}
/*******************************************************************************
*
@@ -80,57 +141,55 @@ acpi_tb_handle_to_object (
******************************************************************************/
acpi_status
-acpi_tb_validate_table_header (
- struct acpi_table_header *table_header)
+acpi_tb_validate_table_header(struct acpi_table_header *table_header)
{
- acpi_name signature;
-
-
- ACPI_FUNCTION_NAME ("tb_validate_table_header");
+ acpi_name signature;
+ ACPI_FUNCTION_NAME("tb_validate_table_header");
/* Verify that this is a valid address */
- if (!acpi_os_readable (table_header, sizeof (struct acpi_table_header))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Cannot read table header at %p\n", table_header));
+ if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cannot read table header at %p\n",
+ table_header));
return (AE_BAD_ADDRESS);
}
/* Ensure that the signature is 4 ASCII characters */
- ACPI_MOVE_32_TO_32 (&signature, table_header->signature);
- if (!acpi_ut_valid_acpi_name (signature)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Table signature at %p [%p] has invalid characters\n",
- table_header, &signature));
+ ACPI_MOVE_32_TO_32(&signature, table_header->signature);
+ if (!acpi_ut_valid_acpi_name(signature)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Table signature at %p [%p] has invalid characters\n",
+ table_header, &signature));
- ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n",
- (char *) &signature));
+ ACPI_REPORT_WARNING(("Invalid table signature found: [%4.4s]\n",
+ (char *)&signature));
- ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
+ ACPI_DUMP_BUFFER(table_header,
+ sizeof(struct acpi_table_header));
return (AE_BAD_SIGNATURE);
}
/* Validate the table length */
- if (table_header->length < sizeof (struct acpi_table_header)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid length in table header %p name %4.4s\n",
- table_header, (char *) &signature));
+ if (table_header->length < sizeof(struct acpi_table_header)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid length in table header %p name %4.4s\n",
+ table_header, (char *)&signature));
- ACPI_REPORT_WARNING (("Invalid table header length (0x%X) found\n",
- (u32) table_header->length));
+ ACPI_REPORT_WARNING(("Invalid table header length (0x%X) found\n", (u32) table_header->length));
- ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
+ ACPI_DUMP_BUFFER(table_header,
+ sizeof(struct acpi_table_header));
return (AE_BAD_HEADER);
}
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_verify_table_checksum
@@ -145,37 +204,31 @@ acpi_tb_validate_table_header (
******************************************************************************/
acpi_status
-acpi_tb_verify_table_checksum (
- struct acpi_table_header *table_header)
+acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
{
- u8 checksum;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("tb_verify_table_checksum");
+ u8 checksum;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("tb_verify_table_checksum");
/* Compute the checksum on the table */
- checksum = acpi_tb_checksum (table_header, table_header->length);
+ checksum =
+ acpi_tb_generate_checksum(table_header, table_header->length);
/* Return the appropriate exception */
if (checksum) {
- ACPI_REPORT_WARNING ((
- "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n",
- table_header->signature, (u32) table_header->checksum,
- (u32) checksum));
+ ACPI_REPORT_WARNING(("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", table_header->signature, (u32) table_header->checksum, (u32) checksum));
status = AE_BAD_CHECKSUM;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
- * FUNCTION: acpi_tb_checksum
+ * FUNCTION: acpi_tb_generate_checksum
*
* PARAMETERS: Buffer - Buffer to checksum
* Length - Size of the buffer
@@ -186,15 +239,11 @@ acpi_tb_verify_table_checksum (
*
******************************************************************************/
-u8
-acpi_tb_checksum (
- void *buffer,
- u32 length)
+u8 acpi_tb_generate_checksum(void *buffer, u32 length)
{
- const u8 *limit;
- const u8 *rover;
- u8 sum = 0;
-
+ const u8 *limit;
+ const u8 *rover;
+ u8 sum = 0;
if (buffer && length) {
/* Buffer and Length are valid */
@@ -208,7 +257,6 @@ acpi_tb_checksum (
return (sum);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -224,16 +272,13 @@ acpi_tb_checksum (
******************************************************************************/
acpi_status
-acpi_tb_handle_to_object (
- u16 table_id,
- struct acpi_table_desc **return_table_desc)
+acpi_tb_handle_to_object(u16 table_id,
+ struct acpi_table_desc ** return_table_desc)
{
- u32 i;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_NAME ("tb_handle_to_object");
+ u32 i;
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_NAME("tb_handle_to_object");
for (i = 0; i < ACPI_TABLE_MAX; i++) {
table_desc = acpi_gbl_table_lists[i].next;
@@ -247,9 +292,8 @@ acpi_tb_handle_to_object (
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "table_id=%X does not exist\n",
+ table_id));
return (AE_BAD_PARAMETER);
}
#endif
-
-
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 0c0b9085dbeb..3f96a4909aad 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -48,10 +48,8 @@
#include <acpi/acnamesp.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbxface")
-
+ACPI_MODULE_NAME("tbxface")
/*******************************************************************************
*
@@ -65,25 +63,20 @@
* provided RSDT
*
******************************************************************************/
-
-acpi_status
-acpi_load_tables (
- void)
+acpi_status acpi_load_tables(void)
{
- struct acpi_pointer rsdp_address;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_load_tables");
+ struct acpi_pointer rsdp_address;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_load_tables");
/* Get the RSDP */
- status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
- &rsdp_address);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
- acpi_format_exception (status)));
+ status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
+ &rsdp_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n",
+ acpi_format_exception(status)));
goto error_exit;
}
@@ -91,54 +84,47 @@ acpi_load_tables (
acpi_gbl_table_flags = rsdp_address.pointer_type;
- status = acpi_tb_verify_rsdp (&rsdp_address);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_verify_rsdp(&rsdp_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status)));
goto error_exit;
}
/* Get the RSDT via the RSDP */
- status = acpi_tb_get_table_rsdt ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_table_rsdt();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status)));
goto error_exit;
}
/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */
- status = acpi_tb_get_required_tables ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_required_tables();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status)));
goto error_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
/* Load the namespace from the tables */
- status = acpi_ns_load_namespace ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
- acpi_format_exception (status)));
+ status = acpi_ns_load_namespace();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status)));
goto error_exit;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
+ error_exit:
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n",
+ acpi_format_exception(status)));
-error_exit:
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
- acpi_format_exception (status)));
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -156,40 +142,49 @@ error_exit:
*
******************************************************************************/
-acpi_status
-acpi_load_table (
- struct acpi_table_header *table_ptr)
+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_status status;
+ struct acpi_table_desc table_info;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("acpi_load_table");
if (!table_ptr) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Copy the table to a local buffer */
- address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
address.pointer.logical = table_ptr;
- status = acpi_tb_get_table_body (&address, table_ptr, &table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(&address, table_ptr, &table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Check signature for a valid table type */
+
+ status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the new table into the local data structures */
- status = acpi_tb_install_table (&table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_install_table(&table_info);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ /* Table already exists, no error */
+
+ status = AE_OK;
+ }
+
/* Free table allocated by acpi_tb_get_table_body */
- acpi_tb_delete_single_table (&table_info);
- return_ACPI_STATUS (status);
+ acpi_tb_delete_single_table(&table_info);
+ return_ACPI_STATUS(status);
}
/* Convert the table to common format if necessary */
@@ -197,31 +192,32 @@ acpi_load_table (
switch (table_info.type) {
case ACPI_TABLE_FADT:
- status = acpi_tb_convert_table_fadt ();
+ status = acpi_tb_convert_table_fadt();
break;
case ACPI_TABLE_FACS:
- status = acpi_tb_build_common_facs (&table_info);
+ status = acpi_tb_build_common_facs(&table_info);
break;
default:
/* Load table into namespace if it contains executable AML */
- status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node);
+ status =
+ acpi_ns_load_table(table_info.installed_desc,
+ acpi_gbl_root_node);
break;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Uninstall table and free the buffer */
- (void) acpi_tb_uninstall_table (table_info.installed_desc);
+ (void)acpi_tb_uninstall_table(table_info.installed_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_unload_table
@@ -234,20 +230,16 @@ acpi_load_table (
*
******************************************************************************/
-acpi_status
-acpi_unload_table (
- acpi_table_type table_type)
+acpi_status acpi_unload_table(acpi_table_type table_type)
{
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE ("acpi_unload_table");
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_TRACE("acpi_unload_table");
/* Parameter validation */
if (table_type > ACPI_TABLE_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Find all tables of the requested type */
@@ -260,18 +252,17 @@ acpi_unload_table (
* "Scope" operator. Thus, we need to track ownership by an ID, not
* simply a position within the hierarchy
*/
- acpi_ns_delete_namespace_by_owner (table_desc->table_id);
-
+ acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
+ acpi_ut_release_owner_id(&table_desc->owner_id);
table_desc = table_desc->next;
}
/* Delete (or unmap) all tables of this type */
- acpi_tb_delete_tables_by_type (table_type);
- return_ACPI_STATUS (AE_OK);
+ acpi_tb_delete_tables_by_type(table_type);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_table_header
@@ -294,54 +285,49 @@ acpi_unload_table (
******************************************************************************/
acpi_status
-acpi_get_table_header (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header *out_table_header)
+acpi_get_table_header(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header *out_table_header)
{
- struct acpi_table_header *tbl_ptr;
- acpi_status status;
+ 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)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((instance == 0) ||
+ (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
- (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
- instance > 1)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((table_type > ACPI_TABLE_MAX) ||
+ (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
+ instance > 1)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get a pointer to the entire table */
- status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* The function will return a NULL pointer if the table is not loaded */
if (tbl_ptr == NULL) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Copy the header to the caller's buffer */
- ACPI_MEMCPY ((void *) out_table_header, (void *) tbl_ptr,
- sizeof (struct acpi_table_header));
+ ACPI_MEMCPY((void *)out_table_header, (void *)tbl_ptr,
+ sizeof(struct acpi_table_header));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -367,43 +353,39 @@ acpi_get_table_header (
******************************************************************************/
acpi_status
-acpi_get_table (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_buffer *ret_buffer)
+acpi_get_table(acpi_table_type table_type,
+ u32 instance, struct acpi_buffer *ret_buffer)
{
- struct acpi_table_header *tbl_ptr;
- acpi_status status;
- acpi_size table_length;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_table");
+ struct acpi_table_header *tbl_ptr;
+ acpi_status status;
+ acpi_size table_length;
+ ACPI_FUNCTION_TRACE("acpi_get_table");
/* Parameter validation */
if (instance == 0) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
- (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
- instance > 1)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((table_type > ACPI_TABLE_MAX) ||
+ (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
+ instance > 1)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get a pointer to the entire table */
- status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -411,7 +393,7 @@ acpi_get_table (
* table is not loaded.
*/
if (tbl_ptr == NULL) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the table length */
@@ -419,23 +401,22 @@ acpi_get_table (
if (table_type == ACPI_TABLE_RSDP) {
/* RSD PTR is the only "table" without a header */
- table_length = sizeof (struct rsdp_descriptor);
- }
- else {
+ table_length = sizeof(struct rsdp_descriptor);
+ } else {
table_length = (acpi_size) tbl_ptr->length;
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (ret_buffer, table_length);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(ret_buffer, table_length);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Copy the table to the buffer */
- ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MEMCPY((void *)ret_buffer->pointer, (void *)tbl_ptr, table_length);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_table);
+EXPORT_SYMBOL(acpi_get_table);
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index dc3c3f6a9f62..3b8a7e063e8a 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -46,22 +46,56 @@
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbxfroot")
+ACPI_MODULE_NAME("tbxfroot")
/* Local prototypes */
-
static acpi_status
-acpi_tb_find_rsdp (
- struct acpi_table_desc *table_info,
- u32 flags);
+acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags);
-static u8 *
-acpi_tb_scan_memory_for_rsdp (
- u8 *start_address,
- u32 length);
+static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_validate_rsdp
+ *
+ * PARAMETERS: Rsdp - Pointer to unvalidated RSDP
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Validate the RSDP (ptr)
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * 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);
+ }
+
+ /* Check the standard checksum */
+
+ if (acpi_tb_generate_checksum(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)) {
+ return (AE_BAD_CHECKSUM);
+ }
+
+ return (AE_OK);
+}
/*******************************************************************************
*
@@ -80,28 +114,24 @@ acpi_tb_scan_memory_for_rsdp (
******************************************************************************/
acpi_status
-acpi_tb_find_table (
- char *signature,
- char *oem_id,
- char *oem_table_id,
- struct acpi_table_header **table_ptr)
+acpi_tb_find_table(char *signature,
+ char *oem_id,
+ char *oem_table_id, struct acpi_table_header ** table_ptr)
{
- acpi_status status;
- struct acpi_table_header *table;
-
-
- ACPI_FUNCTION_TRACE ("tb_find_table");
+ acpi_status status;
+ struct acpi_table_header *table;
+ ACPI_FUNCTION_TRACE("tb_find_table");
/* Validate string lengths */
- if ((ACPI_STRLEN (signature) > ACPI_NAME_SIZE) ||
- (ACPI_STRLEN (oem_id) > sizeof (table->oem_id)) ||
- (ACPI_STRLEN (oem_table_id) > sizeof (table->oem_table_id))) {
- return_ACPI_STATUS (AE_AML_STRING_LIMIT);
+ if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
+ (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
+ (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
+ return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
- if (!ACPI_STRNCMP (signature, DSDT_SIG, ACPI_NAME_SIZE)) {
+ if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
/*
* The DSDT pointer is contained in the FADT, not the RSDT.
* This code should suffice, because the only code that would perform
@@ -110,40 +140,36 @@ acpi_tb_find_table (
* If this becomes insufficient, the FADT will have to be found first.
*/
if (!acpi_gbl_DSDT) {
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
table = acpi_gbl_DSDT;
- }
- else {
+ } else {
/* Find the table */
- status = acpi_get_firmware_table (signature, 1,
- ACPI_LOGICAL_ADDRESSING, &table);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_firmware_table(signature, 1,
+ ACPI_LOGICAL_ADDRESSING,
+ &table);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* 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)))) {
- return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND);
+ 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);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n",
- table->signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
+ table->signature));
*table_ptr = table;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_table
@@ -164,34 +190,28 @@ acpi_tb_find_table (
******************************************************************************/
acpi_status
-acpi_get_firmware_table (
- acpi_string signature,
- u32 instance,
- u32 flags,
- struct acpi_table_header **table_pointer)
+acpi_get_firmware_table(acpi_string signature,
+ u32 instance,
+ u32 flags, struct acpi_table_header **table_pointer)
{
- acpi_status status;
- struct acpi_pointer address;
- struct acpi_table_header *header = NULL;
- struct acpi_table_desc *table_info = NULL;
- struct acpi_table_desc *rsdt_info;
- u32 table_count;
- u32 i;
- u32 j;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_firmware_table");
+ acpi_status status;
+ struct acpi_pointer address;
+ struct acpi_table_header *header = NULL;
+ struct acpi_table_desc *table_info = NULL;
+ struct acpi_table_desc *rsdt_info;
+ u32 table_count;
+ u32 i;
+ u32 j;
+ ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
/*
* Ensure that at least the table manager is initialized. We don't
* require that the entire ACPI subsystem is up for this interface.
* If we have a buffer, we must have a length too
*/
- if ((instance == 0) ||
- (!signature) ||
- (!table_pointer)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((instance == 0) || (!signature) || (!table_pointer)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Ensure that we have a RSDP */
@@ -199,48 +219,41 @@ acpi_get_firmware_table (
if (!acpi_gbl_RSDP) {
/* Get the RSDP */
- status = acpi_os_get_root_pointer (flags, &address);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ status = acpi_os_get_root_pointer(flags, &address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Map and validate the RSDP */
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
- status = acpi_os_map_memory (address.pointer.physical,
- sizeof (struct rsdp_descriptor), (void *) &acpi_gbl_RSDP);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address.pointer.physical,
+ sizeof(struct
+ rsdp_descriptor),
+ (void *)&acpi_gbl_RSDP);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
acpi_gbl_RSDP = address.pointer.logical;
}
- /* The signature and checksum must both be correct */
-
- if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG,
- sizeof (RSDP_SIG)-1) != 0) {
- /* Nope, BAD Signature */
+ /* The RDSP signature and checksum must both be correct */
- return_ACPI_STATUS (AE_BAD_SIGNATURE);
- }
-
- if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
- /* Nope, BAD Checksum */
-
- return_ACPI_STATUS (AE_BAD_CHECKSUM);
+ status = acpi_tb_validate_rsdp(acpi_gbl_RSDP);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Get the RSDT address via the RSDP */
- acpi_tb_get_rsdt_address (&address);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
- acpi_gbl_RSDP,
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ acpi_tb_get_rsdt_address(&address);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
+ acpi_gbl_RSDP,
+ ACPI_FORMAT_UINT64(address.pointer.value)));
/* Insert processor_mode flags */
@@ -248,30 +261,30 @@ acpi_get_firmware_table (
/* Get and validate the RSDT */
- rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+ rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
if (!rsdt_info) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_tb_get_table (&address, rsdt_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_get_table(&address, rsdt_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_tb_validate_rsdt (rsdt_info->pointer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_validate_rsdt(rsdt_info->pointer);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Allocate a scratch table header and table descriptor */
- header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
+ header = ACPI_MEM_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_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
if (!table_info) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -279,7 +292,8 @@ acpi_get_firmware_table (
/* Get the number of table pointers within the RSDT */
- table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
+ table_count =
+ acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer);
address.pointer_type = acpi_gbl_table_flags | flags;
/*
@@ -287,35 +301,42 @@ acpi_get_firmware_table (
* requested table
*/
for (i = 0, j = 0; i < table_count; i++) {
- /* Get the next table pointer, handle RSDT vs. XSDT */
-
- if (acpi_gbl_RSDP->revision < 2) {
- address.pointer.value = (ACPI_CAST_PTR (
- RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
- }
- else {
- address.pointer.value = (ACPI_CAST_PTR (
- XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
+ /*
+ * Get the next table pointer, handle RSDT vs. XSDT
+ * RSDT pointers are 32 bits, XSDT pointers are 64 bits
+ */
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ address.pointer.value =
+ (ACPI_CAST_PTR
+ (RSDT_DESCRIPTOR,
+ rsdt_info->pointer))->table_offset_entry[i];
+ } else {
+ address.pointer.value =
+ (ACPI_CAST_PTR
+ (XSDT_DESCRIPTOR,
+ rsdt_info->pointer))->table_offset_entry[i];
}
/* Get the table header */
- status = acpi_tb_get_table_header (&address, header);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_get_table_header(&address, header);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Compare table signatures and table instance */
- if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
+ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
/* An instance of the table was found */
j++;
if (j >= instance) {
/* Found the correct instance, get the entire table */
- status = acpi_tb_get_table_body (&address, header, table_info);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_tb_get_table_body(&address, header,
+ table_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -329,22 +350,23 @@ acpi_get_firmware_table (
status = AE_NOT_EXIST;
-
-cleanup:
- acpi_os_unmap_memory (rsdt_info->pointer,
- (acpi_size) rsdt_info->pointer->length);
- ACPI_MEM_FREE (rsdt_info);
+ cleanup:
+ if (rsdt_info->pointer) {
+ acpi_os_unmap_memory(rsdt_info->pointer,
+ (acpi_size) rsdt_info->pointer->length);
+ }
+ ACPI_MEM_FREE(rsdt_info);
if (header) {
- ACPI_MEM_FREE (header);
+ ACPI_MEM_FREE(header);
}
if (table_info) {
- ACPI_MEM_FREE (table_info);
+ ACPI_MEM_FREE(table_info);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_firmware_table);
+EXPORT_SYMBOL(acpi_get_firmware_table);
/* TBD: Move to a new file */
@@ -363,35 +385,29 @@ EXPORT_SYMBOL(acpi_get_firmware_table);
*
******************************************************************************/
-acpi_status
-acpi_find_root_pointer (
- u32 flags,
- struct acpi_pointer *rsdp_address)
+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");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
/* Get the RSDP */
- status = acpi_tb_find_rsdp (&table_info, flags);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "RSDP structure not found, %s Flags=%X\n",
- acpi_format_exception (status), flags));
+ status = acpi_tb_find_rsdp(&table_info, flags);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "RSDP structure not found, %s Flags=%X\n",
+ acpi_format_exception(status), flags));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
rsdp_address->pointer.physical = table_info.physical_address;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
@@ -405,68 +421,45 @@ acpi_find_root_pointer (
*
******************************************************************************/
-static u8 *
-acpi_tb_scan_memory_for_rsdp (
- u8 *start_address,
- u32 length)
+static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
{
- u8 *mem_rover;
- u8 *end_address;
- u8 checksum;
-
-
- ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp");
+ acpi_status status;
+ u8 *mem_rover;
+ u8 *end_address;
+ ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp");
end_address = start_address + length;
/* Search from given start address for the requested length */
for (mem_rover = start_address; mem_rover < end_address;
- mem_rover += ACPI_RSDP_SCAN_STEP) {
- /* The signature and checksum must both be correct */
-
- if (ACPI_STRNCMP ((char *) mem_rover,
- RSDP_SIG, sizeof (RSDP_SIG) - 1) != 0) {
- /* No signature match, keep looking */
-
- continue;
- }
-
- /* Signature matches, check the appropriate checksum */
-
- if ((ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover))->revision < 2) {
- /* ACPI version 1.0 */
-
- checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH);
- }
- else {
- /* Post ACPI 1.0, use extended_checksum */
-
- checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_XCHECKSUM_LENGTH);
+ 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,
+ "RSDP located at physical address %p\n",
+ mem_rover));
+ return_PTR(mem_rover);
}
- if (checksum == 0) {
- /* Checksum valid, we have found a valid RSDP */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at physical address %p\n", mem_rover));
- return_PTR (mem_rover);
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Found an RSDP at physical address %p, but it has a bad checksum\n",
- mem_rover));
+ /* No sig match or bad checksum, keep searching */
}
/* Searched entire block, no RSDP was found */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Searched entire block, no valid RSDP was found.\n"));
- return_PTR (NULL);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Searched entire block from %p, valid RSDP was not found\n",
+ start_address));
+ return_PTR(NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_find_rsdp
@@ -490,18 +483,14 @@ acpi_tb_scan_memory_for_rsdp (
******************************************************************************/
static acpi_status
-acpi_tb_find_rsdp (
- struct acpi_table_desc *table_info,
- u32 flags)
+acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
{
- u8 *table_ptr;
- u8 *mem_rover;
- u32 physical_address;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("tb_find_rsdp");
+ u8 *table_ptr;
+ u8 *mem_rover;
+ u32 physical_address;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_find_rsdp");
/*
* Scan supports either logical addressing or physical addressing
@@ -509,23 +498,25 @@ acpi_tb_find_rsdp (
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) ACPI_EBDA_PTR_LOCATION,
- ACPI_EBDA_PTR_LENGTH, (void *) &table_ptr);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH,
+ (void *)&table_ptr);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH));
+
+ return_ACPI_STATUS(status);
}
- ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+ ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
/* Convert segment part to physical address */
physical_address <<= 4;
- acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
+ acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
/* EBDA present? */
@@ -534,59 +525,67 @@ acpi_tb_find_rsdp (
* 1b) Search EBDA paragraphs (EBDa is required to be a
* minimum of 1_k length)
*/
- status = acpi_os_map_memory (
- (acpi_physical_address) physical_address,
- ACPI_EBDA_WINDOW_SIZE, (void *) &table_ptr);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- physical_address, ACPI_EBDA_WINDOW_SIZE));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ physical_address,
+ ACPI_EBDA_WINDOW_SIZE,
+ (void *)&table_ptr);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ physical_address,
+ ACPI_EBDA_WINDOW_SIZE));
+
+ return_ACPI_STATUS(status);
}
- mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr,
- ACPI_EBDA_WINDOW_SIZE);
- acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+ mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr,
+ ACPI_EBDA_WINDOW_SIZE);
+ acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
- physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+ physical_address +=
+ ACPI_PTR_DIFF(mem_rover, table_ptr);
table_info->physical_address =
- (acpi_physical_address) physical_address;
- return_ACPI_STATUS (AE_OK);
+ (acpi_physical_address) physical_address;
+ return_ACPI_STATUS(AE_OK);
}
}
/*
* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
*/
- status = acpi_os_map_memory (
- (acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
- ACPI_HI_RSDP_WINDOW_SIZE, (void *) &table_ptr);
-
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE,
+ (void *)&table_ptr);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE));
+
+ return_ACPI_STATUS(status);
}
- mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
- acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(table_ptr,
+ ACPI_HI_RSDP_WINDOW_SIZE);
+ acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
physical_address =
- ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
+ ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
+ table_ptr);
table_info->physical_address =
- (acpi_physical_address) physical_address;
- return_ACPI_STATUS (AE_OK);
+ (acpi_physical_address) physical_address;
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -596,8 +595,8 @@ acpi_tb_find_rsdp (
else {
/* 1a) Get the location of the EBDA */
- ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
- physical_address <<= 4; /* Convert segment to physical address */
+ ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION);
+ physical_address <<= 4; /* Convert segment to physical address */
/* EBDA present? */
@@ -606,34 +605,38 @@ acpi_tb_find_rsdp (
* 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
* 1_k length)
*/
- mem_rover = acpi_tb_scan_memory_for_rsdp (
- ACPI_PHYSADDR_TO_PTR (physical_address),
- ACPI_EBDA_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
+ (physical_address),
+ ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
- table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
- return_ACPI_STATUS (AE_OK);
+ table_info->physical_address =
+ ACPI_TO_INTEGER(mem_rover);
+ return_ACPI_STATUS(AE_OK);
}
}
/* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
- mem_rover = acpi_tb_scan_memory_for_rsdp (
- ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
- ACPI_HI_RSDP_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
+ (ACPI_HI_RSDP_WINDOW_BASE),
+ ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
/* Found it, return the physical address */
- table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
- return_ACPI_STATUS (AE_OK);
+ table_info->physical_address =
+ ACPI_TO_INTEGER(mem_rover);
+ return_ACPI_STATUS(AE_OK);
}
}
- /* RSDP signature was not found */
+ /* A valid RSDP was not found */
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_REPORT_ERROR(("No valid RSDP was found\n"));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
#endif
-
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 79c3a686bc44..a24847c08f7f 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -70,9 +70,9 @@
#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
#define _COMPONENT ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME ("acpi_thermal")
+ACPI_MODULE_NAME("acpi_thermal")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -80,143 +80,145 @@ static int tzp;
module_param(tzp, int, 0);
MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
-
-static int acpi_thermal_add (struct acpi_device *device);
-static int acpi_thermal_remove (struct acpi_device *device, int type);
+static int acpi_thermal_add(struct acpi_device *device);
+static int acpi_thermal_remove(struct acpi_device *device, int type);
static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_trip_points (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_trip_points(struct file *,
+ const char __user *, size_t,
+ loff_t *);
static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_cooling_mode(struct file *,
+ const char __user *, size_t,
+ loff_t *);
static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_polling(struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
+ size_t, loff_t *);
static struct acpi_driver acpi_thermal_driver = {
- .name = ACPI_THERMAL_DRIVER_NAME,
- .class = ACPI_THERMAL_CLASS,
- .ids = ACPI_THERMAL_HID,
- .ops = {
- .add = acpi_thermal_add,
- .remove = acpi_thermal_remove,
- },
+ .name = ACPI_THERMAL_DRIVER_NAME,
+ .class = ACPI_THERMAL_CLASS,
+ .ids = ACPI_THERMAL_HID,
+ .ops = {
+ .add = acpi_thermal_add,
+ .remove = acpi_thermal_remove,
+ },
};
struct acpi_thermal_state {
- u8 critical:1;
- u8 hot:1;
- u8 passive:1;
- u8 active:1;
- u8 reserved:4;
- int active_index;
+ u8 critical:1;
+ u8 hot:1;
+ u8 passive:1;
+ u8 active:1;
+ u8 reserved:4;
+ int active_index;
};
struct acpi_thermal_state_flags {
- u8 valid:1;
- u8 enabled:1;
- u8 reserved:6;
+ u8 valid:1;
+ u8 enabled:1;
+ u8 reserved:6;
};
struct acpi_thermal_critical {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
+ unsigned long temperature;
};
struct acpi_thermal_hot {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
+ unsigned long temperature;
};
struct acpi_thermal_passive {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
- unsigned long tc1;
- unsigned long tc2;
- unsigned long tsp;
- struct acpi_handle_list devices;
+ unsigned long temperature;
+ unsigned long tc1;
+ unsigned long tc2;
+ unsigned long tsp;
+ struct acpi_handle_list devices;
};
struct acpi_thermal_active {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
- struct acpi_handle_list devices;
+ unsigned long temperature;
+ struct acpi_handle_list devices;
};
struct acpi_thermal_trips {
struct acpi_thermal_critical critical;
- struct acpi_thermal_hot hot;
+ struct acpi_thermal_hot hot;
struct acpi_thermal_passive passive;
struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
};
struct acpi_thermal_flags {
- u8 cooling_mode:1; /* _SCP */
- u8 devices:1; /* _TZD */
- u8 reserved:6;
+ u8 cooling_mode:1; /* _SCP */
+ u8 devices:1; /* _TZD */
+ u8 reserved:6;
};
struct acpi_thermal {
- acpi_handle handle;
- acpi_bus_id name;
- unsigned long temperature;
- unsigned long last_temperature;
- unsigned long polling_frequency;
- u8 cooling_mode;
- volatile u8 zombie;
+ acpi_handle handle;
+ acpi_bus_id name;
+ unsigned long temperature;
+ unsigned long last_temperature;
+ unsigned long polling_frequency;
+ u8 cooling_mode;
+ volatile u8 zombie;
struct acpi_thermal_flags flags;
struct acpi_thermal_state state;
struct acpi_thermal_trips trips;
- struct acpi_handle_list devices;
- struct timer_list timer;
+ struct acpi_handle_list devices;
+ struct timer_list timer;
};
static struct file_operations acpi_thermal_state_fops = {
- .open = acpi_thermal_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_temp_fops = {
- .open = acpi_thermal_temp_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_temp_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_trip_fops = {
- .open = acpi_thermal_trip_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_trip_points,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_trip_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_trip_points,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_cooling_fops = {
- .open = acpi_thermal_cooling_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_cooling_mode,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_cooling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_cooling_mode,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_polling_fops = {
- .open = acpi_thermal_polling_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_polling,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_polling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_polling,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
Thermal Zone Management
-------------------------------------------------------------------------- */
-static int
-acpi_thermal_get_temperature (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
@@ -225,41 +227,39 @@ acpi_thermal_get_temperature (
tz->last_temperature = tz->temperature;
- status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
+ tz->temperature));
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_polling_frequency (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
if (!tz)
return_VALUE(-EINVAL);
- status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TZP", NULL,
+ &tz->polling_frequency);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
+ tz->polling_frequency));
return_VALUE(0);
}
-
-static int
-acpi_thermal_set_polling (
- struct acpi_thermal *tz,
- int seconds)
+static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
{
ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
@@ -268,21 +268,19 @@ acpi_thermal_set_polling (
tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Polling frequency set to %lu seconds\n",
+ tz->polling_frequency));
return_VALUE(0);
}
-
-static int
-acpi_thermal_set_cooling_mode (
- struct acpi_thermal *tz,
- int mode)
+static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
{
- acpi_status status = AE_OK;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg0};
- acpi_handle handle = NULL;
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
@@ -303,19 +301,16 @@ acpi_thermal_set_cooling_mode (
tz->cooling_mode = mode;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
- mode?"passive":"active"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
+ mode ? "passive" : "active"));
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_trip_points (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
- int i = 0;
+ acpi_status status = AE_OK;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
@@ -324,111 +319,128 @@ acpi_thermal_get_trip_points (
/* Critical Shutdown (required) */
- status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
- &tz->trips.critical.temperature);
+ status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
+ &tz->trips.critical.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.critical.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
return_VALUE(-ENODEV);
- }
- else {
+ } else {
tz->trips.critical.flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found critical threshold [%lu]\n",
+ tz->trips.critical.temperature));
}
/* Critical Sleep (optional) */
- status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_HOT", NULL,
+ &tz->trips.hot.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.hot.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
- }
- else {
+ } else {
tz->trips.hot.flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
+ tz->trips.hot.temperature));
}
/* Passive: Processors (optional) */
- status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_PSV", NULL,
+ &tz->trips.passive.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.passive.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
- }
- else {
+ } else {
tz->trips.passive.flags.valid = 1;
- status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TC1", NULL,
+ &tz->trips.passive.tc1);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TC2", NULL,
+ &tz->trips.passive.tc2);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TSP", NULL,
+ &tz->trips.passive.tsp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices);
+ status =
+ acpi_evaluate_reference(tz->handle, "_PSL", NULL,
+ &tz->trips.passive.devices);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
if (!tz->trips.passive.flags.valid)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid passive threshold\n"));
else
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found passive threshold [%lu]\n",
+ tz->trips.passive.temperature));
}
/* Active: Fans, etc. (optional) */
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- char name[5] = {'_','A','C',('0'+i),'\0'};
+ char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
- status = acpi_evaluate_integer(tz->handle, name, NULL, &tz->trips.active[i].temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, name, NULL,
+ &tz->trips.active[i].temperature);
if (ACPI_FAILURE(status))
break;
name[2] = 'L';
- status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices);
+ status =
+ acpi_evaluate_reference(tz->handle, name, NULL,
+ &tz->trips.active[i].devices);
if (ACPI_SUCCESS(status)) {
tz->trips.active[i].flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature));
- }
- else
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found active threshold [%d]:[%lu]\n",
+ i, tz->trips.active[i].temperature));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid active threshold [%d]\n",
+ i));
}
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_devices (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_devices(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
if (!tz)
return_VALUE(-EINVAL);
- status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
+ status =
+ acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
return_VALUE(0);
}
-
-static int
-acpi_thermal_call_usermode (
- char *path)
+static int acpi_thermal_call_usermode(char *path)
{
- char *argv[2] = {NULL, NULL};
- char *envp[3] = {NULL, NULL, NULL};
+ char *argv[2] = { NULL, NULL };
+ char *envp[3] = { NULL, NULL, NULL };
ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
@@ -440,19 +452,16 @@ acpi_thermal_call_usermode (
/* minimal command environment */
envp[0] = "HOME=/";
envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
+
call_usermodehelper(argv[0], argv, envp, 0);
return_VALUE(0);
}
-
-static int
-acpi_thermal_critical (
- struct acpi_thermal *tz)
+static int acpi_thermal_critical(struct acpi_thermal *tz)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_critical");
@@ -462,29 +471,28 @@ acpi_thermal_critical (
if (tz->temperature >= tz->trips.critical.temperature) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
tz->trips.critical.flags.enabled = 1;
- }
- else if (tz->trips.critical.flags.enabled)
+ } else if (tz->trips.critical.flags.enabled)
tz->trips.critical.flags.enabled = 0;
result = acpi_bus_get_device(tz->handle, &device);
if (result)
return_VALUE(result);
- printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature));
- acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled);
+ printk(KERN_EMERG
+ "Critical temperature reached (%ld C), shutting down.\n",
+ KELVIN_TO_CELSIUS(tz->temperature));
+ acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL,
+ tz->trips.critical.flags.enabled);
acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
return_VALUE(0);
}
-
-static int
-acpi_thermal_hot (
- struct acpi_thermal *tz)
+static int acpi_thermal_hot(struct acpi_thermal *tz)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_hot");
@@ -494,30 +502,27 @@ acpi_thermal_hot (
if (tz->temperature >= tz->trips.hot.temperature) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
tz->trips.hot.flags.enabled = 1;
- }
- else if (tz->trips.hot.flags.enabled)
+ } else if (tz->trips.hot.flags.enabled)
tz->trips.hot.flags.enabled = 0;
result = acpi_bus_get_device(tz->handle, &device);
if (result)
return_VALUE(result);
- acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled);
+ acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT,
+ tz->trips.hot.flags.enabled);
/* TBD: Call user-mode "sleep(S4)" function */
return_VALUE(0);
}
-
-static int
-acpi_thermal_passive (
- struct acpi_thermal *tz)
+static int acpi_thermal_passive(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
struct acpi_thermal_passive *passive = NULL;
- int trend = 0;
- int i = 0;
+ int trend = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_passive");
@@ -534,25 +539,29 @@ acpi_thermal_passive (
* accordingly. Note that we assume symmetry.
*/
if (tz->temperature >= passive->temperature) {
- trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
- trend, passive->tc1, tz->temperature,
- tz->last_temperature, passive->tc2,
- tz->temperature, passive->temperature));
+ trend =
+ (passive->tc1 * (tz->temperature - tz->last_temperature)) +
+ (passive->tc2 * (tz->temperature - passive->temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
+ trend, passive->tc1, tz->temperature,
+ tz->last_temperature, passive->tc2,
+ tz->temperature, passive->temperature));
tz->trips.passive.flags.enabled = 1;
/* Heating up? */
if (trend > 0)
- for (i=0; i<passive->devices.count; i++)
- acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_INCREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ acpi_processor_set_thermal_limit(passive->
+ devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_INCREMENT);
/* Cooling off? */
else if (trend < 0)
- for (i=0; i<passive->devices.count; i++)
- acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ acpi_processor_set_thermal_limit(passive->
+ devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_DECREMENT);
}
/*
@@ -563,37 +572,35 @@ acpi_thermal_passive (
* assume symmetry.
*/
else if (tz->trips.passive.flags.enabled) {
- for (i=0; i<passive->devices.count; i++)
- result = acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ result =
+ acpi_processor_set_thermal_limit(passive->devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_DECREMENT);
if (result == 1) {
tz->trips.passive.flags.enabled = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Disabling passive cooling (zone is cool)\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Disabling passive cooling (zone is cool)\n"));
}
}
return_VALUE(0);
}
-
-static int
-acpi_thermal_active (
- struct acpi_thermal *tz)
+static int acpi_thermal_active(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
struct acpi_thermal_active *active = NULL;
- int i = 0;
- int j = 0;
- unsigned long maxtemp = 0;
+ int i = 0;
+ int j = 0;
+ unsigned long maxtemp = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_active");
if (!tz)
return_VALUE(-EINVAL);
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
active = &(tz->trips.active[i]);
if (!active || !active->flags.valid)
@@ -607,16 +614,27 @@ acpi_thermal_active (
*/
if (tz->temperature >= active->temperature) {
if (active->temperature > maxtemp)
- tz->state.active_index = i, maxtemp = active->temperature;
+ tz->state.active_index = i, maxtemp =
+ active->temperature;
if (!active->flags.enabled) {
for (j = 0; j < active->devices.count; j++) {
- result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0);
+ result =
+ acpi_bus_set_power(active->devices.
+ handles[j],
+ ACPI_STATE_D0);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to turn cooling device [%p] 'on'\n",
+ active->
+ devices.
+ handles[j]));
continue;
}
active->flags.enabled = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Cooling device [%p] now 'on'\n",
+ active->devices.
+ handles[j]));
}
}
}
@@ -628,13 +646,21 @@ acpi_thermal_active (
*/
else if (active->flags.enabled) {
for (j = 0; j < active->devices.count; j++) {
- result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3);
+ result =
+ acpi_bus_set_power(active->devices.
+ handles[j],
+ ACPI_STATE_D3);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to turn cooling device [%p] 'off'\n",
+ active->devices.
+ handles[j]));
continue;
}
active->flags.enabled = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Cooling device [%p] now 'off'\n",
+ active->devices.handles[j]));
}
}
}
@@ -642,28 +668,22 @@ acpi_thermal_active (
return_VALUE(0);
}
+static void acpi_thermal_check(void *context);
-static void acpi_thermal_check (void *context);
-
-static void
-acpi_thermal_run (
- unsigned long data)
+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_queue_for_execution(OSD_PRIORITY_GPE,
+ acpi_thermal_check, (void *)data);
}
-
-static void
-acpi_thermal_check (
- void *data)
+static void acpi_thermal_check(void *data)
{
- int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *) data;
- unsigned long sleep_time = 0;
- int i = 0;
+ int result = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ unsigned long sleep_time = 0;
+ int i = 0;
struct acpi_thermal_state state;
ACPI_FUNCTION_TRACE("acpi_thermal_check");
@@ -678,9 +698,9 @@ acpi_thermal_check (
result = acpi_thermal_get_temperature(tz);
if (result)
return_VOID;
-
+
memset(&tz->state, 0, sizeof(tz->state));
-
+
/*
* Check Trip Points
* -----------------
@@ -690,14 +710,18 @@ acpi_thermal_check (
* individual policy decides when it is exited (e.g. hysteresis).
*/
if (tz->trips.critical.flags.valid)
- state.critical |= (tz->temperature >= tz->trips.critical.temperature);
+ state.critical |=
+ (tz->temperature >= tz->trips.critical.temperature);
if (tz->trips.hot.flags.valid)
state.hot |= (tz->temperature >= tz->trips.hot.temperature);
if (tz->trips.passive.flags.valid)
- state.passive |= (tz->temperature >= tz->trips.passive.temperature);
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
+ state.passive |=
+ (tz->temperature >= tz->trips.passive.temperature);
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
if (tz->trips.active[i].flags.valid)
- state.active |= (tz->temperature >= tz->trips.active[i].temperature);
+ state.active |=
+ (tz->temperature >=
+ tz->trips.active[i].temperature);
/*
* Invoke Policy
@@ -726,7 +750,7 @@ acpi_thermal_check (
tz->state.hot = 1;
if (tz->trips.passive.flags.enabled)
tz->state.passive = 1;
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
if (tz->trips.active[i].flags.enabled)
tz->state.active = 1;
@@ -744,8 +768,8 @@ acpi_thermal_check (
else if (tz->polling_frequency > 0)
sleep_time = tz->polling_frequency * 100;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
- tz->name, tz->temperature, sleep_time));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
+ tz->name, tz->temperature, sleep_time));
/*
* Schedule Next Poll
@@ -754,12 +778,11 @@ acpi_thermal_check (
if (!sleep_time) {
if (timer_pending(&(tz->timer)))
del_timer(&(tz->timer));
- }
- else {
+ } else {
if (timer_pending(&(tz->timer)))
mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
else {
- tz->timer.data = (unsigned long) tz;
+ tz->timer.data = (unsigned long)tz;
tz->timer.function = acpi_thermal_run;
tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
add_timer(&(tz->timer));
@@ -769,16 +792,15 @@ acpi_thermal_check (
return_VOID;
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_thermal_dir;
+static struct proc_dir_entry *acpi_thermal_dir;
static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
@@ -787,7 +809,8 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "state: ");
- if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
+ if (!tz->state.critical && !tz->state.hot && !tz->state.passive
+ && !tz->state.active)
seq_puts(seq, "ok\n");
else {
if (tz->state.critical)
@@ -801,7 +824,7 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "\n");
}
-end:
+ end:
return_VALUE(0);
}
@@ -810,11 +833,10 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
}
-
static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ int result = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
@@ -825,10 +847,10 @@ static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
if (result)
goto end;
- seq_printf(seq, "temperature: %ld C\n",
- KELVIN_TO_CELSIUS(tz->temperature));
+ seq_printf(seq, "temperature: %ld C\n",
+ KELVIN_TO_CELSIUS(tz->temperature));
-end:
+ end:
return_VALUE(0);
}
@@ -837,12 +859,11 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
}
-
static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
- int i = 0;
- int j = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ int i = 0;
+ int j = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
@@ -851,21 +872,22 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
if (tz->trips.critical.flags.valid)
seq_printf(seq, "critical (S5): %ld C\n",
- KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
+ KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
if (tz->trips.hot.flags.valid)
seq_printf(seq, "hot (S4): %ld C\n",
- KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
+ KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
if (tz->trips.passive.flags.valid) {
- seq_printf(seq, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
- KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
- tz->trips.passive.tc1,
- tz->trips.passive.tc2,
- tz->trips.passive.tsp);
- for (j=0; j<tz->trips.passive.devices.count; j++) {
-
- seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]);
+ seq_printf(seq,
+ "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
+ tz->trips.passive.tc1, tz->trips.passive.tc2,
+ tz->trips.passive.tsp);
+ for (j = 0; j < tz->trips.passive.devices.count; j++) {
+
+ seq_printf(seq, "0x%p ",
+ tz->trips.passive.devices.handles[j]);
}
seq_puts(seq, "\n");
}
@@ -874,14 +896,15 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
if (!(tz->trips.active[i].flags.valid))
break;
seq_printf(seq, "active[%d]: %ld C: devices=",
- i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
- for (j = 0; j < tz->trips.active[i].devices.count; j++)
+ i,
+ KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
+ for (j = 0; j < tz->trips.active[i].devices.count; j++)
seq_printf(seq, "0x%p ",
- tz->trips.active[i].devices.handles[j]);
+ tz->trips.active[i].devices.handles[j]);
seq_puts(seq, "\n");
}
-end:
+ end:
return_VALUE(0);
}
@@ -891,30 +914,28 @@ static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_thermal_write_trip_points (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_trip_points(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- char *limit_string;
- int num, critical, hot, passive;
- int *active;
- int i = 0;
+ char *limit_string;
+ int num, critical, hot, passive;
+ int *active;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
- if(!limit_string)
+ if (!limit_string)
return_VALUE(-ENOMEM);
memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
- active = kmalloc(ACPI_THERMAL_MAX_ACTIVE *sizeof(int), GFP_KERNEL);
- if(!active)
+ active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
+ if (!active)
return_VALUE(-ENOMEM);
if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
@@ -922,20 +943,21 @@ acpi_thermal_write_trip_points (
count = -EINVAL;
goto end;
}
-
+
if (copy_from_user(limit_string, buffer, count)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
count = -EFAULT;
goto end;
}
-
+
limit_string[count] = '\0';
num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &critical, &hot, &passive,
- &active[0], &active[1], &active[2], &active[3], &active[4],
- &active[5], &active[6], &active[7], &active[8], &active[9]);
- if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
+ &critical, &hot, &passive,
+ &active[0], &active[1], &active[2], &active[3], &active[4],
+ &active[5], &active[6], &active[7], &active[8],
+ &active[9]);
+ if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
count = -EINVAL;
goto end;
@@ -949,17 +971,16 @@ acpi_thermal_write_trip_points (
break;
tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
}
-
-end:
+
+ end:
kfree(active);
kfree(limit_string);
return_VALUE(count);
}
-
static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
@@ -970,33 +991,31 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "<setting not supported>\n");
}
- if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL )
+ if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL)
seq_printf(seq, "cooling mode: critical\n");
else
seq_printf(seq, "cooling mode: %s\n",
- tz->cooling_mode?"passive":"active");
+ tz->cooling_mode ? "passive" : "active");
-end:
+ end:
return_VALUE(0);
}
static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_thermal_cooling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_thermal_write_cooling_mode (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_cooling_mode(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- int result = 0;
- char mode_string[12] = {'\0'};
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ int result = 0;
+ char mode_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
@@ -1008,11 +1027,12 @@ acpi_thermal_write_cooling_mode (
if (copy_from_user(mode_string, buffer, count))
return_VALUE(-EFAULT);
-
+
mode_string[count] = '\0';
-
- result = acpi_thermal_set_cooling_mode(tz,
- simple_strtoul(mode_string, NULL, 0));
+
+ result = acpi_thermal_set_cooling_mode(tz,
+ simple_strtoul(mode_string, NULL,
+ 0));
if (result)
return_VALUE(result);
@@ -1021,10 +1041,9 @@ acpi_thermal_write_cooling_mode (
return_VALUE(count);
}
-
static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
@@ -1037,43 +1056,41 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "polling frequency: %lu seconds\n",
- (tz->polling_frequency / 10));
+ (tz->polling_frequency / 10));
-end:
+ end:
return_VALUE(0);
}
static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_thermal_polling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_thermal_write_polling (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_polling(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- int result = 0;
- char polling_string[12] = {'\0'};
- int seconds = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ int result = 0;
+ char polling_string[12] = { '\0' };
+ int seconds = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
if (!tz || (count > sizeof(polling_string) - 1))
return_VALUE(-EINVAL);
-
+
if (copy_from_user(polling_string, buffer, count))
return_VALUE(-EFAULT);
-
+
polling_string[count] = '\0';
seconds = simple_strtoul(polling_string, NULL, 0);
-
+
result = acpi_thermal_set_polling(tz, seconds);
if (result)
return_VALUE(result);
@@ -1083,18 +1100,15 @@ acpi_thermal_write_polling (
return_VALUE(count);
}
-
-static int
-acpi_thermal_add_fs (
- struct acpi_device *device)
+static int acpi_thermal_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_thermal_dir);
+ acpi_thermal_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -1102,11 +1116,11 @@ acpi_thermal_add_fs (
/* 'state' [R] */
entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_STATE));
else {
entry->proc_fops = &acpi_thermal_state_fops;
entry->data = acpi_driver_data(device);
@@ -1115,11 +1129,11 @@ acpi_thermal_add_fs (
/* 'temperature' [R] */
entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_TEMPERATURE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_TEMPERATURE));
else {
entry->proc_fops = &acpi_thermal_temp_fops;
entry->data = acpi_driver_data(device);
@@ -1128,11 +1142,12 @@ acpi_thermal_add_fs (
/* 'trip_points' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_TRIP_POINTS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_TRIP_POINTS));
else {
entry->proc_fops = &acpi_thermal_trip_fops;
entry->data = acpi_driver_data(device);
@@ -1141,11 +1156,12 @@ acpi_thermal_add_fs (
/* 'cooling_mode' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_COOLING_MODE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_COOLING_MODE));
else {
entry->proc_fops = &acpi_thermal_cooling_fops;
entry->data = acpi_driver_data(device);
@@ -1154,11 +1170,12 @@ acpi_thermal_add_fs (
/* 'polling_frequency' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_POLLING_FREQ));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_POLLING_FREQ));
else {
entry->proc_fops = &acpi_thermal_polling_fops;
entry->data = acpi_driver_data(device);
@@ -1168,10 +1185,7 @@ acpi_thermal_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_thermal_remove_fs (
- struct acpi_device *device)
+static int acpi_thermal_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
@@ -1193,19 +1207,14 @@ acpi_thermal_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_thermal_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_thermal *tz = (struct acpi_thermal *) data;
- struct acpi_device *device = NULL;
+ struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_notify");
@@ -1231,19 +1240,16 @@ acpi_thermal_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_thermal_get_info (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_info(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
@@ -1262,20 +1268,24 @@ acpi_thermal_get_info (
/* Set the cooling mode [_SCP] to active cooling (default) */
result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
- if (!result)
+ if (!result)
tz->flags.cooling_mode = 1;
- else {
+ else {
/* Oh,we have not _SCP method.
- Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
+ Generally show cooling_mode by _ACx, _PSV,spec 12.2 */
tz->flags.cooling_mode = 0;
- if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
- if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
+ if (tz->trips.active[0].flags.valid
+ && tz->trips.passive.flags.valid) {
+ if (tz->trips.passive.temperature >
+ tz->trips.active[0].temperature)
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
- else
+ else
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
- } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+ } else if (!tz->trips.active[0].flags.valid
+ && tz->trips.passive.flags.valid) {
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
- } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
+ } else if (tz->trips.active[0].flags.valid
+ && !tz->trips.passive.flags.valid) {
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
} else {
/* _ACx and _PSV are optional, but _CRT is required */
@@ -1297,14 +1307,11 @@ acpi_thermal_get_info (
return_VALUE(0);
}
-
-static int
-acpi_thermal_add (
- struct acpi_device *device)
+static int acpi_thermal_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_thermal *tz = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_thermal *tz = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_add");
@@ -1335,19 +1342,20 @@ acpi_thermal_add (
acpi_thermal_check(tz);
status = acpi_install_notify_handler(tz->handle,
- ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz);
+ ACPI_DEVICE_NOTIFY,
+ acpi_thermal_notify, tz);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
- acpi_device_name(device), acpi_device_bid(device),
- KELVIN_TO_CELSIUS(tz->temperature));
+ acpi_device_name(device), acpi_device_bid(device),
+ KELVIN_TO_CELSIUS(tz->temperature));
-end:
+ end:
if (result) {
acpi_thermal_remove_fs(device);
kfree(tz);
@@ -1356,21 +1364,17 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_thermal_remove (
- struct acpi_device *device,
- int type)
+static int acpi_thermal_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_thermal *tz = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_thermal *tz = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- tz = (struct acpi_thermal *) acpi_driver_data(device);
+ tz = (struct acpi_thermal *)acpi_driver_data(device);
/* avoid timer adding new defer task */
tz->zombie = 1;
@@ -1382,19 +1386,19 @@ acpi_thermal_remove (
del_timer_sync(&(tz->timer));
status = acpi_remove_notify_handler(tz->handle,
- ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_thermal_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
/* Terminate policy */
- if (tz->trips.passive.flags.valid
- && tz->trips.passive.flags.enabled) {
+ if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) {
tz->trips.passive.flags.enabled = 0;
acpi_thermal_passive(tz);
}
if (tz->trips.active[0].flags.valid
- && tz->trips.active[0].flags.enabled) {
+ && tz->trips.active[0].flags.enabled) {
tz->trips.active[0].flags.enabled = 0;
acpi_thermal_active(tz);
}
@@ -1405,11 +1409,9 @@ acpi_thermal_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_thermal_init (void)
+static int __init acpi_thermal_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_init");
@@ -1427,9 +1429,7 @@ acpi_thermal_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_thermal_exit (void)
+static void __exit acpi_thermal_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_thermal_exit");
@@ -1440,6 +1440,5 @@ acpi_thermal_exit (void)
return_VOID;
}
-
module_init(acpi_thermal_init);
module_exit(acpi_thermal_exit);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 73b1d8aeae9d..7fe0b7ae9733 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -100,8 +100,7 @@ MODULE_LICENSE("GPL");
/* utility
*/
-static __inline__ void
-_set_bit(u32* word, u32 mask, int value)
+static __inline__ void _set_bit(u32 * word, u32 mask, int value)
{
*word = (*word & ~mask) | (mask * value);
}
@@ -109,35 +108,32 @@ _set_bit(u32* word, u32 mask, int value)
/* acpi interface wrappers
*/
-static int
-is_valid_acpi_path(const char* methodName)
+static int is_valid_acpi_path(const char *methodName)
{
acpi_handle handle;
acpi_status status;
- status = acpi_get_handle(NULL, (char*)methodName, &handle);
+ status = acpi_get_handle(NULL, (char *)methodName, &handle);
return !ACPI_FAILURE(status);
}
-static int
-write_acpi_int(const char* methodName, int val)
+static int write_acpi_int(const char *methodName, int val)
{
struct acpi_object_list params;
union acpi_object in_objs[1];
acpi_status status;
- params.count = sizeof(in_objs)/sizeof(in_objs[0]);
+ params.count = sizeof(in_objs) / sizeof(in_objs[0]);
params.pointer = in_objs;
in_objs[0].type = ACPI_TYPE_INTEGER;
in_objs[0].integer.value = val;
- status = acpi_evaluate_object(NULL, (char*)methodName, &params, NULL);
+ status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
return (status == AE_OK);
}
#if 0
-static int
-read_acpi_int(const char* methodName, int* pVal)
+static int read_acpi_int(const char *methodName, int *pVal)
{
struct acpi_buffer results;
union acpi_object out_objs[1];
@@ -146,25 +142,24 @@ read_acpi_int(const char* methodName, int* pVal)
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(0, (char*)methodName, 0, &results);
+ status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
*pVal = out_objs[0].integer.value;
return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
}
#endif
-static const char* method_hci /*= 0*/;
+static const char *method_hci /*= 0*/ ;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
-static acpi_status
-hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
{
struct acpi_object_list params;
union acpi_object in_objs[HCI_WORDS];
struct acpi_buffer results;
- union acpi_object out_objs[HCI_WORDS+1];
+ union acpi_object out_objs[HCI_WORDS + 1];
acpi_status status;
int i;
@@ -178,8 +173,8 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(NULL, (char*)method_hci, &params,
- &results);
+ status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
+ &results);
if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
for (i = 0; i < out_objs->package.count; ++i) {
out[i] = out_objs->package.elements[i].integer.value;
@@ -195,8 +190,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
* may be useful (such as "not supported").
*/
-static acpi_status
-hci_write1(u32 reg, u32 in1, u32* result)
+static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
@@ -205,8 +199,7 @@ hci_write1(u32 reg, u32 in1, u32* result)
return status;
}
-static acpi_status
-hci_read1(u32 reg, u32* out1, u32* result)
+static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
@@ -216,26 +209,25 @@ hci_read1(u32 reg, u32* out1, u32* result)
return status;
}
-static struct proc_dir_entry* toshiba_proc_dir /*= 0*/;
-static int force_fan;
-static int last_key_event;
-static int key_event_valid;
+static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+static int force_fan;
+static int last_key_event;
+static int key_event_valid;
-typedef struct _ProcItem
-{
- const char* name;
- char* (*read_func)(char*);
- unsigned long (*write_func)(const char*, unsigned long);
+typedef struct _ProcItem {
+ const char *name;
+ char *(*read_func) (char *);
+ unsigned long (*write_func) (const char *, unsigned long);
} ProcItem;
/* proc file handlers
*/
static int
-dispatch_read(char* page, char** start, off_t off, int count, int* eof,
- ProcItem* item)
+dispatch_read(char *page, char **start, off_t off, int count, int *eof,
+ ProcItem * item)
{
- char* p = page;
+ char *p = page;
int len;
if (off == 0)
@@ -243,33 +235,35 @@ dispatch_read(char* page, char** start, off_t off, int count, int* eof,
/* ISSUE: I don't understand this code */
len = (p - page);
- if (len <= off+count) *eof = 1;
+ if (len <= off + count)
+ *eof = 1;
*start = page + off;
len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
return len;
}
static int
-dispatch_write(struct file* file, const char __user * buffer,
- unsigned long count, ProcItem* item)
+dispatch_write(struct file *file, const char __user * buffer,
+ unsigned long count, ProcItem * item)
{
int result;
- char* tmp_buffer;
+ char *tmp_buffer;
/* Arg buffer points to userspace memory, which can't be accessed
* directly. Since we're making a copy, zero-terminate the
* destination so that sscanf can be used on it safely.
*/
tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
- if(!tmp_buffer)
+ if (!tmp_buffer)
return -ENOMEM;
if (copy_from_user(tmp_buffer, buffer, count)) {
result = -EFAULT;
- }
- else {
+ } else {
tmp_buffer[count] = 0;
result = item->write_func(tmp_buffer, count);
}
@@ -277,8 +271,7 @@ dispatch_write(struct file* file, const char __user * buffer,
return result;
}
-static char*
-read_lcd(char* p)
+static char *read_lcd(char *p)
{
u32 hci_result;
u32 value;
@@ -288,7 +281,7 @@ read_lcd(char* p)
value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
p += sprintf(p, "brightness: %d\n", value);
p += sprintf(p, "brightness_levels: %d\n",
- HCI_LCD_BRIGHTNESS_LEVELS);
+ HCI_LCD_BRIGHTNESS_LEVELS);
} else {
printk(MY_ERR "Error reading LCD brightness\n");
}
@@ -296,14 +289,13 @@ read_lcd(char* p)
return p;
}
-static unsigned long
-write_lcd(const char* buffer, unsigned long count)
+static unsigned long write_lcd(const char *buffer, unsigned long count)
{
int value;
u32 hci_result;
if (sscanf(buffer, " brightness : %i", &value) == 1 &&
- value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
+ value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
value = value << HCI_LCD_BRIGHTNESS_SHIFT;
hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
if (hci_result != HCI_SUCCESS)
@@ -315,8 +307,7 @@ write_lcd(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_video(char* p)
+static char *read_video(char *p)
{
u32 hci_result;
u32 value;
@@ -325,7 +316,7 @@ read_video(char* p)
if (hci_result == HCI_SUCCESS) {
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
- int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
+ int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
p += sprintf(p, "lcd_out: %d\n", is_lcd);
p += sprintf(p, "crt_out: %d\n", is_crt);
p += sprintf(p, "tv_out: %d\n", is_tv);
@@ -336,8 +327,7 @@ read_video(char* p)
return p;
}
-static unsigned long
-write_video(const char* buffer, unsigned long count)
+static unsigned long write_video(const char *buffer, unsigned long count)
{
int value;
int remain = count;
@@ -363,7 +353,7 @@ write_video(const char* buffer, unsigned long count)
++buffer;
--remain;
}
- while (remain && *(buffer-1) != ';');
+ while (remain && *(buffer - 1) != ';');
}
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
@@ -386,8 +376,7 @@ write_video(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_fan(char* p)
+static char *read_fan(char *p)
{
u32 hci_result;
u32 value;
@@ -403,14 +392,13 @@ read_fan(char* p)
return p;
}
-static unsigned long
-write_fan(const char* buffer, unsigned long count)
+static unsigned long write_fan(const char *buffer, unsigned long count)
{
int value;
u32 hci_result;
if (sscanf(buffer, " force_on : %i", &value) == 1 &&
- value >= 0 && value <= 1) {
+ value >= 0 && value <= 1) {
hci_write1(HCI_FAN, value, &hci_result);
if (hci_result != HCI_SUCCESS)
return -EFAULT;
@@ -423,8 +411,7 @@ write_fan(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_keys(char* p)
+static char *read_keys(char *p)
{
u32 hci_result;
u32 value;
@@ -451,17 +438,15 @@ read_keys(char* p)
p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
-end:
+ end:
return p;
}
-static unsigned long
-write_keys(const char* buffer, unsigned long count)
+static unsigned long write_keys(const char *buffer, unsigned long count)
{
int value;
- if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 &&
- value == 0) {
+ if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) {
key_event_valid = 0;
} else {
return -EINVAL;
@@ -470,12 +455,11 @@ write_keys(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_version(char* p)
+static char *read_version(char *p)
{
p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
p += sprintf(p, "proc_interface: %d\n",
- PROC_INTERFACE_VERSION);
+ PROC_INTERFACE_VERSION);
return p;
}
@@ -484,48 +468,45 @@ read_version(char* p)
#define PROC_TOSHIBA "toshiba"
-static ProcItem proc_items[] =
-{
- { "lcd" , read_lcd , write_lcd },
- { "video" , read_video , write_video },
- { "fan" , read_fan , write_fan },
- { "keys" , read_keys , write_keys },
- { "version" , read_version , NULL },
- { NULL }
+static ProcItem proc_items[] = {
+ {"lcd", read_lcd, write_lcd},
+ {"video", read_video, write_video},
+ {"fan", read_fan, write_fan},
+ {"keys", read_keys, write_keys},
+ {"version", read_version, NULL},
+ {NULL}
};
-static acpi_status __init
-add_device(void)
+static acpi_status __init add_device(void)
{
- struct proc_dir_entry* proc;
- ProcItem* item;
+ struct proc_dir_entry *proc;
+ ProcItem *item;
- for (item = proc_items; item->name; ++item)
- {
+ for (item = proc_items; item->name; ++item) {
proc = create_proc_read_entry(item->name,
- S_IFREG | S_IRUGO | S_IWUSR,
- toshiba_proc_dir, (read_proc_t*)dispatch_read, item);
+ S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir,
+ (read_proc_t *) dispatch_read,
+ item);
if (proc)
proc->owner = THIS_MODULE;
if (proc && item->write_func)
- proc->write_proc = (write_proc_t*)dispatch_write;
+ proc->write_proc = (write_proc_t *) dispatch_write;
}
return AE_OK;
}
-static acpi_status __exit
-remove_device(void)
+static acpi_status __exit remove_device(void)
{
- ProcItem* item;
+ ProcItem *item;
for (item = proc_items; item->name; ++item)
remove_proc_entry(item->name, toshiba_proc_dir);
return AE_OK;
}
-static int __init
-toshiba_acpi_init(void)
+static int __init toshiba_acpi_init(void)
{
acpi_status status = AE_OK;
u32 hci_result;
@@ -533,9 +514,9 @@ toshiba_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
+ if (!acpi_specific_hotkey_enabled) {
printk(MY_INFO "Using generic hotkey driver\n");
- return -ENODEV;
+ return -ENODEV;
}
/* simple device detection: look for HCI method */
if (is_valid_acpi_path(METHOD_HCI_1))
@@ -546,7 +527,7 @@ toshiba_acpi_init(void)
return -ENODEV;
printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
- TOSHIBA_ACPI_VERSION);
+ TOSHIBA_ACPI_VERSION);
printk(MY_INFO " HCI method: %s\n", method_hci);
force_fan = 0;
@@ -568,8 +549,7 @@ toshiba_acpi_init(void)
return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
}
-static void __exit
-toshiba_acpi_exit(void)
+static void __exit toshiba_acpi_exit(void)
{
remove_device();
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
index 939c447dd52a..e87108b7338a 100644
--- a/drivers/acpi/utilities/Makefile
+++ b/drivers/acpi/utilities/Makefile
@@ -3,6 +3,6 @@
#
obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
- utcopy.o utdelete.o utglobal.o utmath.o utobject.o
+ utcopy.o utdelete.o utglobal.o utmath.o utobject.o utstate.o utmutex.o utobject.o utcache.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index c4e7f989a2bd..068450b36475 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Module Name: utalloc - local cache and memory allocation routines
+ * Module Name: utalloc - local memory allocation routines
*
*****************************************************************************/
@@ -41,232 +41,134 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utalloc")
+ACPI_MODULE_NAME("utalloc")
/* Local prototypes */
-
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-static struct acpi_debug_mem_block *
-acpi_ut_find_allocation (
- u32 list_id,
- void *allocation);
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
static acpi_status
-acpi_ut_track_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *address,
- acpi_size size,
- u8 alloc_type,
- u32 component,
- char *module,
- u32 line);
+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 (
- u32 list_id,
- struct acpi_debug_mem_block *address,
- u32 component,
- char *module,
- u32 line);
-#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
+ u32 component, char *module, u32 line);
+#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+static acpi_status
+acpi_ut_create_list(char *list_name,
+ u16 object_size, struct acpi_memory_list **return_cache);
+#endif
/*******************************************************************************
*
- * FUNCTION: acpi_ut_release_to_cache
+ * FUNCTION: acpi_ut_create_caches
*
- * PARAMETERS: list_id - Memory list/cache ID
- * Object - The object to be released
+ * PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Release an object to the specified cache. If cache is full,
- * the object is deleted.
+ * DESCRIPTION: Create all local caches
*
******************************************************************************/
-void
-acpi_ut_release_to_cache (
- u32 list_id,
- void *object)
+acpi_status acpi_ut_create_caches(void)
{
- struct acpi_memory_list *cache_info;
-
+ acpi_status status;
- ACPI_FUNCTION_ENTRY ();
-
-
- cache_info = &acpi_gbl_memory_lists[list_id];
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- /* If walk cache is full, just free this wallkstate object */
+ /* Memory allocation lists */
- if (cache_info->cache_depth >= cache_info->max_cache_depth) {
- ACPI_MEM_FREE (object);
- ACPI_MEM_TRACKING (cache_info->total_freed++);
+ status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- /* Otherwise put this object back into the cache */
-
- else {
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
- return;
- }
-
- /* Mark the object as cached */
-
- ACPI_MEMSET (object, 0xCA, cache_info->object_size);
- ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED);
-
- /* Put the object at the head of the cache list */
-
- * (ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head;
- cache_info->list_head = object;
- cache_info->cache_depth++;
-
- (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
+ status =
+ acpi_ut_create_list("Acpi-Namespace",
+ sizeof(struct acpi_namespace_node),
+ &acpi_gbl_ns_node_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
-
-#else
-
- /* Object cache is disabled; just free the object */
-
- ACPI_MEM_FREE (object);
- ACPI_MEM_TRACKING (cache_info->total_freed++);
#endif
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_acquire_from_cache
- *
- * PARAMETERS: list_id - Memory list ID
- *
- * RETURN: A requested object. NULL if the object could not be
- * allocated.
- *
- * DESCRIPTION: Get an object from the specified cache. If cache is empty,
- * the object is allocated.
- *
- ******************************************************************************/
-
-void *
-acpi_ut_acquire_from_cache (
- u32 list_id)
-{
- struct acpi_memory_list *cache_info;
- void *object;
+ /* Object Caches, for frequently used objects */
- ACPI_FUNCTION_NAME ("ut_acquire_from_cache");
-
-
- cache_info = &acpi_gbl_memory_lists[list_id];
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
+ status =
+ acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state),
+ ACPI_MAX_STATE_CACHE_DEPTH,
+ &acpi_gbl_state_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- ACPI_MEM_TRACKING (cache_info->cache_requests++);
-
- /* Check the cache first */
-
- if (cache_info->list_head) {
- /* There is an object available, use it */
-
- object = cache_info->list_head;
- cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) object)[cache_info->link_offset])));
-
- ACPI_MEM_TRACKING (cache_info->cache_hits++);
- cache_info->cache_depth--;
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n",
- object, acpi_gbl_memory_lists[list_id].list_name));
-#endif
-
- if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
- }
-
- /* Clear (zero) the previously used Object */
-
- ACPI_MEMSET (object, 0, cache_info->object_size);
+ status =
+ acpi_os_create_cache("acpi_parse",
+ sizeof(struct acpi_parse_obj_common),
+ ACPI_MAX_PARSE_CACHE_DEPTH,
+ &acpi_gbl_ps_node_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- else {
- /* The cache is empty, create a new object */
-
- /* Avoid deadlock with ACPI_MEM_CALLOCATE */
-
- if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
- }
-
- object = ACPI_MEM_CALLOCATE (cache_info->object_size);
- ACPI_MEM_TRACKING (cache_info->total_allocated++);
+ status =
+ acpi_os_create_cache("acpi_parse_ext",
+ sizeof(struct acpi_parse_obj_named),
+ ACPI_MAX_EXTPARSE_CACHE_DEPTH,
+ &acpi_gbl_ps_node_ext_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
-#else
-
- /* Object cache is disabled; just allocate the object */
-
- object = ACPI_MEM_CALLOCATE (cache_info->object_size);
- ACPI_MEM_TRACKING (cache_info->total_allocated++);
-#endif
+ status =
+ acpi_os_create_cache("acpi_operand",
+ sizeof(union acpi_operand_object),
+ ACPI_MAX_OBJECT_CACHE_DEPTH,
+ &acpi_gbl_operand_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- return (object);
+ return (AE_OK);
}
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
/*******************************************************************************
*
- * FUNCTION: acpi_ut_delete_generic_cache
+ * FUNCTION: acpi_ut_delete_caches
*
- * PARAMETERS: list_id - Memory list ID
+ * PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Free all objects within the requested cache.
+ * DESCRIPTION: Purge and delete all local caches
*
******************************************************************************/
-void
-acpi_ut_delete_generic_cache (
- u32 list_id)
+acpi_status acpi_ut_delete_caches(void)
{
- struct acpi_memory_list *cache_info;
- char *next;
-
- ACPI_FUNCTION_ENTRY ();
+ (void)acpi_os_delete_cache(acpi_gbl_state_cache);
+ acpi_gbl_state_cache = NULL;
+ (void)acpi_os_delete_cache(acpi_gbl_operand_cache);
+ acpi_gbl_operand_cache = NULL;
- cache_info = &acpi_gbl_memory_lists[list_id];
- while (cache_info->list_head) {
- /* Delete one cached state object */
+ (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache);
+ acpi_gbl_ps_node_cache = NULL;
- next = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) cache_info->list_head)[cache_info->link_offset])));
- ACPI_MEM_FREE (cache_info->list_head);
+ (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
+ acpi_gbl_ps_node_ext_cache = NULL;
- cache_info->list_head = next;
- cache_info->cache_depth--;
- }
+ return (AE_OK);
}
-#endif
-
/*******************************************************************************
*
@@ -280,9 +182,7 @@ acpi_ut_delete_generic_cache (
*
******************************************************************************/
-acpi_status
-acpi_ut_validate_buffer (
- struct acpi_buffer *buffer)
+acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
{
/* Obviously, the structure pointer must be valid */
@@ -293,9 +193,9 @@ acpi_ut_validate_buffer (
/* Special semantics for the length */
- if ((buffer->length == ACPI_NO_BUFFER) ||
- (buffer->length == ACPI_ALLOCATE_BUFFER) ||
- (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
+ if ((buffer->length == ACPI_NO_BUFFER) ||
+ (buffer->length == ACPI_ALLOCATE_BUFFER) ||
+ (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
return (AE_OK);
}
@@ -308,7 +208,6 @@ acpi_ut_validate_buffer (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_initialize_buffer
@@ -324,12 +223,10 @@ acpi_ut_validate_buffer (
******************************************************************************/
acpi_status
-acpi_ut_initialize_buffer (
- struct acpi_buffer *buffer,
- acpi_size required_length)
+acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
+ acpi_size required_length)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
switch (buffer->length) {
case ACPI_NO_BUFFER:
@@ -339,33 +236,30 @@ acpi_ut_initialize_buffer (
status = AE_BUFFER_OVERFLOW;
break;
-
case ACPI_ALLOCATE_BUFFER:
/* Allocate a new buffer */
- buffer->pointer = acpi_os_allocate (required_length);
+ buffer->pointer = acpi_os_allocate(required_length);
if (!buffer->pointer) {
return (AE_NO_MEMORY);
}
/* Clear the buffer */
- ACPI_MEMSET (buffer->pointer, 0, required_length);
+ ACPI_MEMSET(buffer->pointer, 0, required_length);
break;
-
case ACPI_ALLOCATE_LOCAL_BUFFER:
/* Allocate a new buffer with local interface to allow tracking */
- buffer->pointer = ACPI_MEM_CALLOCATE (required_length);
+ buffer->pointer = ACPI_MEM_CALLOCATE(required_length);
if (!buffer->pointer) {
return (AE_NO_MEMORY);
}
break;
-
default:
/* Existing buffer: Validate the size of the buffer */
@@ -377,7 +271,7 @@ acpi_ut_initialize_buffer (
/* Clear the buffer */
- ACPI_MEMSET (buffer->pointer, 0, required_length);
+ ACPI_MEMSET(buffer->pointer, 0, required_length);
break;
}
@@ -385,7 +279,6 @@ acpi_ut_initialize_buffer (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_allocate
@@ -401,41 +294,34 @@ acpi_ut_initialize_buffer (
*
******************************************************************************/
-void *
-acpi_ut_allocate (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
{
- void *allocation;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size);
+ void *allocation;
+ ACPI_FUNCTION_TRACE_U32("ut_allocate", size);
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_allocate: Attempt to allocate zero bytes\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_allocate: Attempt to allocate zero bytes\n"));
size = 1;
}
- allocation = acpi_os_allocate (size);
+ allocation = acpi_os_allocate(size);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_allocate: Could not allocate size %X\n", (u32) size));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_allocate: Could not allocate size %X\n",
+ (u32) size));
- return_PTR (NULL);
+ return_PTR(NULL);
}
- return_PTR (allocation);
+ return_PTR(allocation);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_callocate
@@ -451,43 +337,36 @@ acpi_ut_allocate (
*
******************************************************************************/
-void *
-acpi_ut_callocate (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line)
{
- void *allocation;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size);
+ void *allocation;
+ ACPI_FUNCTION_TRACE_U32("ut_callocate", size);
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Attempt to allocate zero bytes\n"));
- return_PTR (NULL);
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Attempt to allocate zero bytes\n"));
+ return_PTR(NULL);
}
- allocation = acpi_os_allocate (size);
+ allocation = acpi_os_allocate(size);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Could not allocate size %X\n", (u32) size));
- return_PTR (NULL);
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Could not allocate size %X\n",
+ (u32) size));
+ return_PTR(NULL);
}
/* Clear the memory block */
- ACPI_MEMSET (allocation, 0, size);
- return_PTR (allocation);
+ 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
@@ -500,6 +379,39 @@ acpi_ut_callocate (
* 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);
+}
/*******************************************************************************
*
@@ -516,37 +428,33 @@ acpi_ut_callocate (
*
******************************************************************************/
-void *
-acpi_ut_allocate_and_track (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_allocate_and_track(acpi_size size,
+ u32 component, char *module, u32 line)
{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
- allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header),
- component, module, line);
+ allocation =
+ acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
if (!allocation) {
return (NULL);
}
- status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
- ACPI_MEM_MALLOC, component, module, line);
- if (ACPI_FAILURE (status)) {
- acpi_os_free (allocation);
+ 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_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->current_total_size += (u32) size;
- return ((void *) &allocation->user_space);
+ return ((void *)&allocation->user_space);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_callocate_and_track
@@ -562,41 +470,38 @@ acpi_ut_allocate_and_track (
*
******************************************************************************/
-void *
-acpi_ut_callocate_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)
{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
- allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header),
- component, module, line);
+ allocation =
+ acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Could not allocate size %X\n", (u32) size));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Could not allocate size %X\n",
+ (u32) size));
return (NULL);
}
- status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
- ACPI_MEM_CALLOC, component, module, line);
- if (ACPI_FAILURE (status)) {
- acpi_os_free (allocation);
+ 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_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->current_total_size += (u32) size;
- return ((void *) &allocation->user_space);
+ return ((void *)&allocation->user_space);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_free_and_track
@@ -613,53 +518,46 @@ acpi_ut_callocate_and_track (
******************************************************************************/
void
-acpi_ut_free_and_track (
- void *allocation,
- u32 component,
- char *module,
- u32 line)
+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);
+ struct acpi_debug_mem_block *debug_block;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
if (NULL == allocation) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("acpi_ut_free: Attempt to delete a NULL address\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("acpi_ut_free: Attempt to delete a NULL address\n"));
return_VOID;
}
- debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block,
- (((char *) allocation) - sizeof (struct acpi_debug_mem_header)));
+ debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
+ (((char *)allocation) -
+ sizeof(struct acpi_debug_mem_header)));
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size;
+ acpi_gbl_global_list->total_freed++;
+ acpi_gbl_global_list->current_total_size -= debug_block->size;
- status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block,
- component, module, line);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n",
- acpi_format_exception (status)));
+ status = acpi_ut_remove_allocation(debug_block,
+ component, module, line);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not free memory, %s\n",
+ acpi_format_exception(status)));
}
- acpi_os_free (debug_block);
+ acpi_os_free(debug_block);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_find_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
*
* RETURN: A list element if found; NULL otherwise.
*
@@ -667,22 +565,13 @@ acpi_ut_free_and_track (
*
******************************************************************************/
-static struct acpi_debug_mem_block *
-acpi_ut_find_allocation (
- u32 list_id,
- void *allocation)
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
{
- struct acpi_debug_mem_block *element;
-
+ struct acpi_debug_mem_block *element;
- ACPI_FUNCTION_ENTRY ();
-
-
- if (list_id > ACPI_MEM_LIST_MAX) {
- return (NULL);
- }
+ ACPI_FUNCTION_ENTRY();
- element = acpi_gbl_memory_lists[list_id].list_head;
+ element = acpi_gbl_global_list->list_head;
/* Search for the address. */
@@ -697,13 +586,11 @@ acpi_ut_find_allocation (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_track_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
* Size - Size of the allocation
* alloc_type - MEM_MALLOC or MEM_CALLOC
* Component - Component type of caller
@@ -717,64 +604,51 @@ acpi_ut_find_allocation (
******************************************************************************/
static acpi_status
-acpi_ut_track_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *allocation,
- acpi_size size,
- u8 alloc_type,
- u32 component,
- char *module,
- u32 line)
+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);
+ 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);
- if (list_id > ACPI_MEM_LIST_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- mem_list = &acpi_gbl_memory_lists[list_id];
- status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ 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 (list_id, allocation);
+ element = acpi_ut_find_allocation(allocation);
if (element) {
- ACPI_REPORT_ERROR ((
- "ut_track_allocation: Allocation already present in list! (%p)\n",
- allocation));
+ ACPI_REPORT_ERROR(("ut_track_allocation: Allocation already present in list! (%p)\n", allocation));
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n",
- element, allocation));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Element %p Address %p\n",
+ element, allocation));
goto unlock_and_exit;
}
/* Fill in the instance data. */
- allocation->size = (u32) size;
+ allocation->size = (u32) size;
allocation->alloc_type = alloc_type;
allocation->component = component;
- allocation->line = line;
+ allocation->line = line;
- ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME);
- allocation->module[ACPI_MAX_MODULE_NAME-1] = 0;
+ 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;
+ ((struct acpi_debug_mem_block *)(mem_list->list_head))->
+ previous = allocation;
}
allocation->next = mem_list->list_head;
@@ -782,19 +656,16 @@ acpi_ut_track_allocation (
mem_list->list_head = allocation;
-
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_remove_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
* Component - Component type of caller
* Module - Source file name of caller
* Line - Line number of caller
@@ -806,45 +677,34 @@ unlock_and_exit:
******************************************************************************/
static acpi_status
-acpi_ut_remove_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *allocation,
- u32 component,
- char *module,
- u32 line)
+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;
-
+ struct acpi_memory_list *mem_list;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ut_remove_allocation");
+ ACPI_FUNCTION_TRACE("ut_remove_allocation");
-
- if (list_id > ACPI_MEM_LIST_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- mem_list = &acpi_gbl_memory_lists[list_id];
+ mem_list = acpi_gbl_global_list;
if (NULL == mem_list->list_head) {
/* No allocations! */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ 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 {
+ } else {
mem_list->list_head = allocation->next;
}
@@ -854,16 +714,15 @@ acpi_ut_remove_allocation (
/* Mark the segment as deleted */
- ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size);
+ ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
- allocation->size));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
+ allocation->size));
- status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
- return_ACPI_STATUS (status);
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dump_allocation_info
@@ -877,15 +736,13 @@ acpi_ut_remove_allocation (
******************************************************************************/
#ifdef ACPI_FUTURE_USAGE
-void
-acpi_ut_dump_allocation_info (
- void)
+void acpi_ut_dump_allocation_info(void)
{
/*
struct acpi_memory_list *mem_list;
*/
- ACPI_FUNCTION_TRACE ("ut_dump_allocation_info");
+ ACPI_FUNCTION_TRACE("ut_dump_allocation_info");
/*
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
@@ -898,7 +755,6 @@ acpi_ut_dump_allocation_info (
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,
@@ -909,7 +765,6 @@ acpi_ut_dump_allocation_info (
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,
@@ -923,8 +778,7 @@ acpi_ut_dump_allocation_info (
*/
return_VOID;
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -939,84 +793,87 @@ acpi_ut_dump_allocation_info (
*
******************************************************************************/
-void
-acpi_ut_dump_allocations (
- u32 component,
- char *module)
+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");
+ 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))) {
+ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
return;
}
- element = acpi_gbl_memory_lists[0].list_head;
+ element = acpi_gbl_global_list->list_head;
while (element) {
if ((element->component & component) &&
- ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) {
+ ((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);
+ 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));
+ 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)) {
+ 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);
+ 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);
+ 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));
+ acpi_os_printf("%4.4s",
+ acpi_ut_get_node_name
+ (&descriptor->node));
break;
default:
break;
}
- acpi_os_printf ( "\n");
+ acpi_os_printf("\n");
num_outstanding++;
}
}
element = element->next;
}
- (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY);
+ (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
/* Print summary */
if (!num_outstanding) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No outstanding allocations.\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%d(%X) Outstanding allocations\n",
- num_outstanding, num_outstanding));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No outstanding allocations.\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%d(%X) Outstanding allocations\n",
+ num_outstanding, num_outstanding));
}
return_VOID;
}
-#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
-
+#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
new file mode 100644
index 000000000000..93d48681d276
--- /dev/null
+++ b/drivers/acpi/utilities/utcache.c
@@ -0,0 +1,305 @@
+/******************************************************************************
+ *
+ * Module Name: utcache - local cache allocation routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utcache")
+
+#ifdef ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_create_cache
+ *
+ * PARAMETERS: cache_name - Ascii name for the cache
+ * object_size - Size of each cached object
+ * max_depth - Maximum depth of the cache (in objects)
+ * return_cache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+acpi_status
+acpi_os_create_cache(char *cache_name,
+ u16 object_size,
+ u16 max_depth, struct acpi_memory_list **return_cache)
+{
+ struct acpi_memory_list *cache;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache_name || !return_cache || (object_size < 16)) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Create the cache object */
+
+ cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+ if (!cache) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Populate the cache object and return it */
+
+ ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+ cache->link_offset = 8;
+ cache->list_name = cache_name;
+ cache->object_size = object_size;
+ cache->max_depth = max_depth;
+
+ *return_cache = cache;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_purge_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+{
+ char *next;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* 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);
+
+ cache->list_head = next;
+ cache->current_depth--;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_delete_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ * cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Purge all objects in the cache */
+
+ status = acpi_os_purge_cache(cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Now we can delete the cache object */
+
+ acpi_os_free(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_release_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * Object - The object to be released
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ * the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache || !object) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* If cache is full, just free this object */
+
+ if (cache->current_depth >= cache->max_depth) {
+ ACPI_MEM_FREE(object);
+ ACPI_MEM_TRACKING(cache->total_freed++);
+ }
+
+ /* Otherwise put this object back into the cache */
+
+ else {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Mark the object as cached */
+
+ ACPI_MEMSET(object, 0xCA, cache->object_size);
+ ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
+
+ /* Put the object at the head of the cache list */
+
+ *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)object)[cache->
+ link_offset]))) =
+ cache->list_head;
+ cache->list_head = object;
+ cache->current_depth++;
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_acquire_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: the acquired object. NULL on error
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ * the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(struct acpi_memory_list *cache)
+{
+ acpi_status status;
+ void *object;
+
+ ACPI_FUNCTION_NAME("os_acquire_object");
+
+ if (!cache) {
+ return (NULL);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ ACPI_MEM_TRACKING(cache->requests++);
+
+ /* Check the cache first */
+
+ if (cache->list_head) {
+ /* There is an object available, use it */
+
+ object = cache->list_head;
+ cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)
+ object)[cache->
+ link_offset])));
+
+ 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)));
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ /* Clear (zero) the previously used Object */
+
+ ACPI_MEMSET(object, 0, cache->object_size);
+ } else {
+ /* The cache is empty, create a new object */
+
+ ACPI_MEM_TRACKING(cache->total_allocated++);
+
+ /* Avoid deadlock with ACPI_MEM_CALLOCATE */
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ object = ACPI_MEM_CALLOCATE(cache->object_size);
+ if (!object) {
+ return (NULL);
+ }
+ }
+
+ return (object);
+}
+#endif /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 11e884957162..5442b32de611 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -41,59 +41,46 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utcopy")
+ACPI_MODULE_NAME("utcopy")
/* Local prototypes */
-
static acpi_status
-acpi_ut_copy_isimple_to_esimple (
- union acpi_operand_object *internal_object,
- union acpi_object *external_object,
- u8 *data_space,
- acpi_size *buffer_space_used);
+acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+ union acpi_object *external_object,
+ u8 * data_space, acpi_size * buffer_space_used);
static acpi_status
-acpi_ut_copy_ielement_to_ielement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
+acpi_ut_copy_ielement_to_ielement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context);
static acpi_status
-acpi_ut_copy_ipackage_to_epackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- acpi_size *space_used);
+acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
+ u8 * buffer, acpi_size * space_used);
static acpi_status
-acpi_ut_copy_esimple_to_isimple(
- union acpi_object *user_obj,
- union acpi_operand_object **return_obj);
+acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
+ union acpi_operand_object **return_obj);
static acpi_status
-acpi_ut_copy_simple_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc);
+acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc);
static acpi_status
-acpi_ut_copy_ielement_to_eelement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
+acpi_ut_copy_ielement_to_eelement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context);
static acpi_status
-acpi_ut_copy_ipackage_to_ipackage (
- union acpi_operand_object *source_obj,
- union acpi_operand_object *dest_obj,
- struct acpi_walk_state *walk_state);
-
+acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
+ union acpi_operand_object *dest_obj,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -116,17 +103,13 @@ acpi_ut_copy_ipackage_to_ipackage (
******************************************************************************/
static acpi_status
-acpi_ut_copy_isimple_to_esimple (
- union acpi_operand_object *internal_object,
- union acpi_object *external_object,
- u8 *data_space,
- acpi_size *buffer_space_used)
+acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+ union acpi_object *external_object,
+ u8 * data_space, acpi_size * buffer_space_used)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_isimple_to_esimple");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple");
*buffer_space_used = 0;
@@ -135,54 +118,54 @@ acpi_ut_copy_isimple_to_esimple (
* package element)
*/
if (!internal_object) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Always clear the external object */
- ACPI_MEMSET (external_object, 0, sizeof (union acpi_object));
+ ACPI_MEMSET(external_object, 0, sizeof(union acpi_object));
/*
* In general, the external object will be the same type as
* the internal object
*/
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
/* However, only a limited number of external types are supported */
- switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(internal_object)) {
case ACPI_TYPE_STRING:
- external_object->string.pointer = (char *) data_space;
+ external_object->string.pointer = (char *)data_space;
external_object->string.length = internal_object->string.length;
- *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (
- (acpi_size) internal_object->string.length + 1);
-
- ACPI_MEMCPY ((void *) data_space,
- (void *) internal_object->string.pointer,
- (acpi_size) internal_object->string.length + 1);
+ *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
+ internal_object->
+ string.
+ length + 1);
+
+ ACPI_MEMCPY((void *)data_space,
+ (void *)internal_object->string.pointer,
+ (acpi_size) internal_object->string.length + 1);
break;
-
case ACPI_TYPE_BUFFER:
external_object->buffer.pointer = data_space;
external_object->buffer.length = internal_object->buffer.length;
- *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (
- internal_object->string.length);
+ *buffer_space_used =
+ ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
+ length);
- ACPI_MEMCPY ((void *) data_space,
- (void *) internal_object->buffer.pointer,
- internal_object->buffer.length);
+ ACPI_MEMCPY((void *)data_space,
+ (void *)internal_object->buffer.pointer,
+ internal_object->buffer.length);
break;
-
case ACPI_TYPE_INTEGER:
external_object->integer.value = internal_object->integer.value;
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
/*
@@ -199,41 +182,41 @@ acpi_ut_copy_isimple_to_esimple (
* to object containing a handle to an ACPI named object.
*/
external_object->type = ACPI_TYPE_ANY;
- external_object->reference.handle = internal_object->reference.node;
+ external_object->reference.handle =
+ internal_object->reference.node;
break;
}
break;
-
case ACPI_TYPE_PROCESSOR:
- external_object->processor.proc_id = internal_object->processor.proc_id;
- external_object->processor.pblk_address = internal_object->processor.address;
- external_object->processor.pblk_length = internal_object->processor.length;
+ external_object->processor.proc_id =
+ internal_object->processor.proc_id;
+ external_object->processor.pblk_address =
+ internal_object->processor.address;
+ external_object->processor.pblk_length =
+ internal_object->processor.length;
break;
-
case ACPI_TYPE_POWER:
external_object->power_resource.system_level =
- internal_object->power_resource.system_level;
+ internal_object->power_resource.system_level;
external_object->power_resource.resource_order =
- internal_object->power_resource.resource_order;
+ internal_object->power_resource.resource_order;
break;
-
default:
/*
* There is no corresponding external object type
*/
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ielement_to_eelement
@@ -247,25 +230,23 @@ acpi_ut_copy_isimple_to_esimple (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ielement_to_eelement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_copy_ielement_to_eelement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context)
{
- acpi_status status = AE_OK;
- struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
- acpi_size object_space;
- u32 this_index;
- union acpi_object *target_object;
+ acpi_status status = AE_OK;
+ struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
+ acpi_size object_space;
+ u32 this_index;
+ union acpi_object *target_object;
+ ACPI_FUNCTION_ENTRY();
- ACPI_FUNCTION_ENTRY ();
-
-
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
target_object = (union acpi_object *)
- &((union acpi_object *)(state->pkg.dest_object))->package.elements[this_index];
+ &((union acpi_object *)(state->pkg.dest_object))->package.
+ elements[this_index];
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -273,23 +254,24 @@ acpi_ut_copy_ielement_to_eelement (
/*
* This is a simple or null object
*/
- status = acpi_ut_copy_isimple_to_esimple (source_object,
- target_object, info->free_space, &object_space);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_copy_isimple_to_esimple(source_object,
+ target_object,
+ info->free_space,
+ &object_space);
+ if (ACPI_FAILURE(status)) {
return (status);
}
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/*
* Build the package object
*/
- target_object->type = ACPI_TYPE_PACKAGE;
- target_object->package.count = source_object->package.count;
+ target_object->type = ACPI_TYPE_PACKAGE;
+ target_object->package.count = source_object->package.count;
target_object->package.elements =
- ACPI_CAST_PTR (union acpi_object, info->free_space);
+ ACPI_CAST_PTR(union acpi_object, info->free_space);
/*
* Pass the new package object back to the package walk routine
@@ -300,22 +282,22 @@ acpi_ut_copy_ielement_to_eelement (
* Save space for the array of objects (Package elements)
* update the buffer length counter
*/
- object_space = ACPI_ROUND_UP_TO_NATIVE_WORD (
- (acpi_size) target_object->package.count *
- sizeof (union acpi_object));
+ object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
+ target_object->
+ package.count *
+ sizeof(union
+ acpi_object));
break;
-
default:
return (AE_BAD_PARAMETER);
}
- info->free_space += object_space;
- info->length += object_space;
+ info->free_space += object_space;
+ info->length += object_space;
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ipackage_to_epackage
@@ -336,55 +318,51 @@ acpi_ut_copy_ielement_to_eelement (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ipackage_to_epackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- acpi_size *space_used)
+acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
+ u8 * buffer, acpi_size * space_used)
{
- union acpi_object *external_object;
- acpi_status status;
- struct acpi_pkg_info info;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_ipackage_to_epackage");
+ union acpi_object *external_object;
+ acpi_status status;
+ struct acpi_pkg_info info;
+ ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage");
/*
* First package at head of the buffer
*/
- external_object = ACPI_CAST_PTR (union acpi_object, buffer);
+ external_object = ACPI_CAST_PTR(union acpi_object, buffer);
/*
* Free space begins right after the first package
*/
- info.length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
- info.free_space = buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
- sizeof (union acpi_object));
+ info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
+ info.free_space =
+ buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
info.object_space = 0;
info.num_packages = 1;
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
- external_object->package.count = internal_object->package.count;
- external_object->package.elements = ACPI_CAST_PTR (union acpi_object,
- info.free_space);
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
+ external_object->package.count = internal_object->package.count;
+ external_object->package.elements = ACPI_CAST_PTR(union acpi_object,
+ info.free_space);
/*
* Leave room for an array of ACPI_OBJECTS in the buffer
* and move the free space past it
*/
- info.length += (acpi_size) external_object->package.count *
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
+ info.length += (acpi_size) external_object->package.count *
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
info.free_space += external_object->package.count *
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
- status = acpi_ut_walk_package_tree (internal_object, external_object,
- acpi_ut_copy_ielement_to_eelement, &info);
+ status = acpi_ut_walk_package_tree(internal_object, external_object,
+ acpi_ut_copy_ielement_to_eelement,
+ &info);
*space_used = info.length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_iobject_to_eobject
@@ -400,44 +378,45 @@ acpi_ut_copy_ipackage_to_epackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_iobject_to_eobject (
- union acpi_operand_object *internal_object,
- struct acpi_buffer *ret_buffer)
+acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
+ 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) {
+ if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) {
/*
* Package object: Copy all subobjects (including
* nested packages)
*/
- status = acpi_ut_copy_ipackage_to_epackage (internal_object,
- ret_buffer->pointer, &ret_buffer->length);
- }
- else {
+ status = acpi_ut_copy_ipackage_to_epackage(internal_object,
+ ret_buffer->pointer,
+ &ret_buffer->length);
+ } else {
/*
* Build a simple object (no nested objects)
*/
- status = acpi_ut_copy_isimple_to_esimple (internal_object,
- (union acpi_object *) ret_buffer->pointer,
- ((u8 *) ret_buffer->pointer +
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object))),
- &ret_buffer->length);
+ status = acpi_ut_copy_isimple_to_esimple(internal_object,
+ (union acpi_object *)
+ ret_buffer->pointer,
+ ((u8 *) ret_buffer->
+ pointer +
+ ACPI_ROUND_UP_TO_NATIVE_WORD
+ (sizeof
+ (union
+ acpi_object))),
+ &ret_buffer->length);
/*
* build simple does not include the object size in the length
* so we add it in here
*/
- ret_buffer->length += sizeof (union acpi_object);
+ ret_buffer->length += sizeof(union acpi_object);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_esimple_to_isimple
@@ -455,15 +434,12 @@ acpi_ut_copy_iobject_to_eobject (
******************************************************************************/
static acpi_status
-acpi_ut_copy_esimple_to_isimple (
- union acpi_object *external_object,
- union acpi_operand_object **ret_internal_object)
+acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ union acpi_operand_object **ret_internal_object)
{
- union acpi_operand_object *internal_object;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_esimple_to_isimple");
+ union acpi_operand_object *internal_object;
+ ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple");
/*
* Simple types supported are: String, Buffer, Integer
@@ -473,58 +449,57 @@ acpi_ut_copy_esimple_to_isimple (
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_INTEGER:
- internal_object = acpi_ut_create_internal_object (
- (u8) external_object->type);
+ internal_object = acpi_ut_create_internal_object((u8)
+ external_object->
+ type);
if (!internal_object) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
break;
default:
/* All other types are not supported */
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
-
/* Must COPY string and buffer contents */
switch (external_object->type) {
case ACPI_TYPE_STRING:
internal_object->string.pointer =
- ACPI_MEM_CALLOCATE ((acpi_size) external_object->string.length + 1);
+ ACPI_MEM_CALLOCATE((acpi_size) external_object->string.
+ length + 1);
if (!internal_object->string.pointer) {
goto error_exit;
}
- ACPI_MEMCPY (internal_object->string.pointer,
- external_object->string.pointer,
- external_object->string.length);
+ ACPI_MEMCPY(internal_object->string.pointer,
+ external_object->string.pointer,
+ external_object->string.length);
internal_object->string.length = external_object->string.length;
break;
-
case ACPI_TYPE_BUFFER:
internal_object->buffer.pointer =
- ACPI_MEM_CALLOCATE (external_object->buffer.length);
+ ACPI_MEM_CALLOCATE(external_object->buffer.length);
if (!internal_object->buffer.pointer) {
goto error_exit;
}
- ACPI_MEMCPY (internal_object->buffer.pointer,
- external_object->buffer.pointer,
- external_object->buffer.length);
+ ACPI_MEMCPY(internal_object->buffer.pointer,
+ external_object->buffer.pointer,
+ external_object->buffer.length);
internal_object->buffer.length = external_object->buffer.length;
break;
-
case ACPI_TYPE_INTEGER:
- internal_object->integer.value = external_object->integer.value;
+ internal_object->integer.value = external_object->integer.value;
break;
default:
@@ -533,15 +508,13 @@ acpi_ut_copy_esimple_to_isimple (
}
*ret_internal_object = internal_object;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
- acpi_ut_remove_reference (internal_object);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ error_exit:
+ acpi_ut_remove_reference(internal_object);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
-
#ifdef ACPI_FUTURE_IMPLEMENTATION
/* Code to convert packages that are parameters to control methods */
@@ -565,22 +538,18 @@ error_exit:
******************************************************************************/
static acpi_status
-acpi_ut_copy_epackage_to_ipackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- u32 *space_used)
+acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
+ u8 * buffer, u32 * space_used)
{
- u8 *free_space;
- union acpi_object *external_object;
- u32 length = 0;
- u32 this_index;
- u32 object_space = 0;
- union acpi_operand_object *this_internal_obj;
- union acpi_object *this_external_obj;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_epackage_to_ipackage");
+ u8 *free_space;
+ union acpi_object *external_object;
+ u32 length = 0;
+ u32 this_index;
+ u32 object_space = 0;
+ union acpi_operand_object *this_internal_obj;
+ union acpi_object *this_external_obj;
+ ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage");
/*
* First package at head of the buffer
@@ -592,24 +561,22 @@ acpi_ut_copy_epackage_to_ipackage (
*/
free_space = buffer + sizeof(union acpi_object);
-
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
- external_object->package.count = internal_object->package.count;
- external_object->package.elements = (union acpi_object *)free_space;
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
+ external_object->package.count = internal_object->package.count;
+ external_object->package.elements = (union acpi_object *)free_space;
/*
* Build an array of ACPI_OBJECTS in the buffer
* and move the free space past it
*/
- free_space += external_object->package.count * sizeof(union acpi_object);
-
+ free_space +=
+ external_object->package.count * sizeof(union acpi_object);
/* Call walk_package */
}
-#endif /* Future implementation */
-
+#endif /* Future implementation */
/*******************************************************************************
*
@@ -625,37 +592,35 @@ acpi_ut_copy_epackage_to_ipackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_eobject_to_iobject (
- union acpi_object *external_object,
- union acpi_operand_object **internal_object)
+acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
+ union acpi_operand_object **internal_object)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_eobject_to_iobject");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject");
if (external_object->type == ACPI_TYPE_PACKAGE) {
/*
* Packages as external input to control methods are not supported,
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Packages as parameters not implemented!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Packages as parameters not implemented!\n"));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
else {
/*
* Build a simple object (no nested objects)
*/
- status = acpi_ut_copy_esimple_to_isimple (external_object, internal_object);
+ status =
+ acpi_ut_copy_esimple_to_isimple(external_object,
+ internal_object);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_simple_object
@@ -671,83 +636,75 @@ acpi_ut_copy_eobject_to_iobject (
******************************************************************************/
static acpi_status
-acpi_ut_copy_simple_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc)
+acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc)
{
- u16 reference_count;
- union acpi_operand_object *next_object;
-
+ u16 reference_count;
+ union acpi_operand_object *next_object;
/* Save fields from destination that we don't want to overwrite */
reference_count = dest_desc->common.reference_count;
next_object = dest_desc->common.next_object;
- /* Copy the entire source object over the destination object*/
+ /* Copy the entire source object over the destination object */
- ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
- sizeof (union acpi_operand_object));
+ ACPI_MEMCPY((char *)dest_desc, (char *)source_desc,
+ sizeof(union acpi_operand_object));
/* Restore the saved fields */
dest_desc->common.reference_count = reference_count;
dest_desc->common.next_object = next_object;
- /* Handle the objects with extra data */
+ /* New object is not static, regardless of source */
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
- case ACPI_TYPE_BUFFER:
+ dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- dest_desc->buffer.node = NULL;
- dest_desc->common.flags = source_desc->common.flags;
+ /* Handle the objects with extra data */
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
+ case ACPI_TYPE_BUFFER:
/*
* Allocate and copy the actual buffer if and only if:
* 1) There is a valid buffer pointer
- * 2) The buffer is not static (not in an ACPI table) (in this case,
- * the actual pointer was already copied above)
+ * 2) The buffer has a length > 0
*/
if ((source_desc->buffer.pointer) &&
- (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- dest_desc->buffer.pointer = NULL;
-
- /* Create an actual buffer only if length > 0 */
-
- if (source_desc->buffer.length) {
- dest_desc->buffer.pointer =
- ACPI_MEM_ALLOCATE (source_desc->buffer.length);
- if (!dest_desc->buffer.pointer) {
- return (AE_NO_MEMORY);
- }
+ (source_desc->buffer.length)) {
+ dest_desc->buffer.pointer =
+ ACPI_MEM_ALLOCATE(source_desc->buffer.length);
+ if (!dest_desc->buffer.pointer) {
+ return (AE_NO_MEMORY);
+ }
- /* Copy the actual buffer data */
+ /* Copy the actual buffer data */
- ACPI_MEMCPY (dest_desc->buffer.pointer,
- source_desc->buffer.pointer,
- source_desc->buffer.length);
- }
+ ACPI_MEMCPY(dest_desc->buffer.pointer,
+ source_desc->buffer.pointer,
+ source_desc->buffer.length);
}
break;
case ACPI_TYPE_STRING:
-
/*
* Allocate and copy the actual string if and only if:
* 1) There is a valid string pointer
- * 2) The string is not static (not in an ACPI table) (in this case,
- * the actual pointer was already copied above)
+ * (Pointer to a NULL string is allowed)
*/
- if ((source_desc->string.pointer) &&
- (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+ if (source_desc->string.pointer) {
dest_desc->string.pointer =
- ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
+ ACPI_MEM_ALLOCATE((acpi_size) source_desc->string.
+ length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
- ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer,
- (acpi_size) source_desc->string.length + 1);
+ /* Copy the actual string data */
+
+ ACPI_MEMCPY(dest_desc->string.pointer,
+ source_desc->string.pointer,
+ (acpi_size) source_desc->string.length + 1);
}
break;
@@ -756,7 +713,7 @@ acpi_ut_copy_simple_object (
* We copied the reference object, so we now must add a reference
* to the object pointed to by the reference
*/
- acpi_ut_add_reference (source_desc->reference.object);
+ acpi_ut_add_reference(source_desc->reference.object);
break;
default:
@@ -767,7 +724,6 @@ acpi_ut_copy_simple_object (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ielement_to_ielement
@@ -781,24 +737,21 @@ acpi_ut_copy_simple_object (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ielement_to_ielement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_copy_ielement_to_ielement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context)
{
- acpi_status status = AE_OK;
- u32 this_index;
- union acpi_operand_object **this_target_ptr;
- union acpi_operand_object *target_object;
-
+ acpi_status status = AE_OK;
+ u32 this_index;
+ union acpi_operand_object **this_target_ptr;
+ union acpi_operand_object *target_object;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
this_target_ptr = (union acpi_operand_object **)
- &state->pkg.dest_object->package.elements[this_index];
+ &state->pkg.dest_object->package.elements[this_index];
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -809,34 +762,36 @@ acpi_ut_copy_ielement_to_ielement (
/*
* This is a simple object, just copy it
*/
- target_object = acpi_ut_create_internal_object (
- ACPI_GET_OBJECT_TYPE (source_object));
+ target_object =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE
+ (source_object));
if (!target_object) {
return (AE_NO_MEMORY);
}
- status = acpi_ut_copy_simple_object (source_object, target_object);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_copy_simple_object(source_object,
+ target_object);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
*this_target_ptr = target_object;
- }
- else {
+ } else {
/* Pass through a null element */
*this_target_ptr = NULL;
}
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/*
* This object is a package - go down another nesting level
* Create and build the package object
*/
- target_object = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+ target_object =
+ acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
if (!target_object) {
return (AE_NO_MEMORY);
}
@@ -848,8 +803,8 @@ acpi_ut_copy_ielement_to_ielement (
* Create the object array
*/
target_object->package.elements =
- ACPI_MEM_CALLOCATE (((acpi_size) source_object->package.count + 1) *
- sizeof (void *));
+ ACPI_MEM_CALLOCATE(((acpi_size) source_object->package.
+ count + 1) * sizeof(void *));
if (!target_object->package.elements) {
status = AE_NO_MEMORY;
goto error_exit;
@@ -866,19 +821,17 @@ acpi_ut_copy_ielement_to_ielement (
*this_target_ptr = target_object;
break;
-
default:
return (AE_BAD_PARAMETER);
}
return (status);
-error_exit:
- acpi_ut_remove_reference (target_object);
+ error_exit:
+ acpi_ut_remove_reference(target_object);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ipackage_to_ipackage
@@ -894,49 +847,46 @@ error_exit:
******************************************************************************/
static acpi_status
-acpi_ut_copy_ipackage_to_ipackage (
- union acpi_operand_object *source_obj,
- union acpi_operand_object *dest_obj,
- struct acpi_walk_state *walk_state)
+acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
+ union acpi_operand_object *dest_obj,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
+ 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;
+ dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj);
+ dest_obj->common.flags = source_obj->common.flags;
dest_obj->package.count = source_obj->package.count;
/*
* 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_MEM_CALLOCATE(((acpi_size)
+ source_obj->package.
+ count +
+ 1) * sizeof(void *));
if (!dest_obj->package.elements) {
- ACPI_REPORT_ERROR (
- ("aml_build_copy_internal_package_object: Package allocation failure\n"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_REPORT_ERROR(("aml_build_copy_internal_package_object: Package allocation failure\n"));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Copy the package element-by-element by walking the package "tree".
* This handles nested packages of arbitrary depth.
*/
- status = acpi_ut_walk_package_tree (source_obj, dest_obj,
- acpi_ut_copy_ielement_to_ielement, walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_walk_package_tree(source_obj, dest_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);
+ acpi_ut_remove_reference(dest_obj);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_iobject_to_iobject
@@ -952,35 +902,31 @@ acpi_ut_copy_ipackage_to_ipackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_iobject_to_iobject (
- union acpi_operand_object *source_desc,
- union acpi_operand_object **dest_desc,
- struct acpi_walk_state *walk_state)
+acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
+ union acpi_operand_object **dest_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_iobject_to_iobject");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject");
/* Create the top level object */
- *dest_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (source_desc));
+ *dest_desc =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc));
if (!*dest_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the object and possible subobjects */
- if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_PACKAGE) {
- status = acpi_ut_copy_ipackage_to_ipackage (source_desc, *dest_desc,
- walk_state);
- }
- else {
- status = acpi_ut_copy_simple_object (source_desc, *dest_desc);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) {
+ status =
+ acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
+ walk_state);
+ } else {
+ status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 794c7df3f2ad..d80e92639932 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -46,15 +46,16 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utdebug")
-
+ACPI_MODULE_NAME("utdebug")
#ifdef ACPI_DEBUG_OUTPUT
+static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
+static char *acpi_gbl_fn_entry_str = "----Entry";
+static char *acpi_gbl_fn_exit_str = "----Exit-";
-static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
-static char *acpi_gbl_fn_entry_str = "----Entry";
-static char *acpi_gbl_fn_exit_str = "----Exit-";
+/* Local prototypes */
+static const char *acpi_ut_trim_function_name(const char *function_name);
/*******************************************************************************
*
@@ -68,17 +69,13 @@ static char *acpi_gbl_fn_exit_str = "----Exit-";
*
******************************************************************************/
-void
-acpi_ut_init_stack_ptr_trace (
- void)
+void acpi_ut_init_stack_ptr_trace(void)
{
- u32 current_sp;
-
+ u32 current_sp;
- acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF (&current_sp, NULL);
+ acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(&current_sp, NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_track_stack_ptr
@@ -91,14 +88,11 @@ acpi_ut_init_stack_ptr_trace (
*
******************************************************************************/
-void
-acpi_ut_track_stack_ptr (
- void)
+void acpi_ut_track_stack_ptr(void)
{
- acpi_size current_sp;
-
+ acpi_size current_sp;
- current_sp = ACPI_PTR_DIFF (&current_sp, NULL);
+ current_sp = ACPI_PTR_DIFF(&current_sp, NULL);
if (current_sp < acpi_gbl_lowest_stack_pointer) {
acpi_gbl_lowest_stack_pointer = current_sp;
@@ -109,6 +103,39 @@ acpi_ut_track_stack_ptr (
}
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_trim_function_name
+ *
+ * PARAMETERS: function_name - Ascii string containing a procedure name
+ *
+ * RETURN: Updated pointer to the function name
+ *
+ * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
+ * This allows compiler macros such as __FUNCTION__ to be used
+ * with no change to the debug output.
+ *
+ ******************************************************************************/
+
+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);
+ }
+
+ return (function_name);
+}
/*******************************************************************************
*
@@ -116,10 +143,9 @@ acpi_ut_track_stack_ptr (
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number (for error output)
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Format - Printf format field
* ... - Optional printf arguments
*
@@ -130,36 +156,33 @@ acpi_ut_track_stack_ptr (
*
******************************************************************************/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_debug_print(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *format, ...)
{
- u32 thread_id;
- va_list args;
-
+ u32 thread_id;
+ va_list args;
/*
* Stay silent if the debug level or component ID is disabled
*/
if (!(requested_debug_level & acpi_dbg_level) ||
- !(dbg_info->component_id & acpi_dbg_layer)) {
+ !(component_id & acpi_dbg_layer)) {
return;
}
/*
* Thread tracking and context switch notification
*/
- thread_id = acpi_os_get_thread_id ();
+ 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 (
- "\n**** Context Switch from TID %X to TID %X ****\n\n",
- acpi_gbl_prev_thread_id, thread_id);
+ acpi_os_printf
+ ("\n**** Context Switch from TID %X to TID %X ****\n\n",
+ acpi_gbl_prev_thread_id, thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
@@ -169,17 +192,18 @@ acpi_ut_debug_print (
* Display the module name, current line number, thread ID (if requested),
* current procedure nesting level, and the current procedure name
*/
- acpi_os_printf ("%8s-%04ld ", dbg_info->module_name, line_number);
+ acpi_os_printf("%8s-%04ld ", module_name, line_number);
if (ACPI_LV_THREADS & acpi_dbg_level) {
- acpi_os_printf ("[%04lX] ", thread_id);
+ acpi_os_printf("[%04lX] ", thread_id);
}
- acpi_os_printf ("[%02ld] %-22.22s: ",
- acpi_gbl_nesting_level, dbg_info->proc_name);
+ acpi_os_printf("[%02ld] %-22.22s: ",
+ acpi_gbl_nesting_level,
+ acpi_ut_trim_function_name(function_name));
- va_start (args, format);
- acpi_os_vprintf (format, args);
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
}
EXPORT_SYMBOL(acpi_ut_debug_print);
@@ -190,10 +214,9 @@ EXPORT_SYMBOL(acpi_ut_debug_print);
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Format - Printf format field
* ... - Optional printf arguments
*
@@ -204,37 +227,33 @@ EXPORT_SYMBOL(acpi_ut_debug_print);
*
******************************************************************************/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print_raw (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_debug_print_raw(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *format, ...)
{
- va_list args;
-
+ va_list args;
if (!(requested_debug_level & acpi_dbg_level) ||
- !(dbg_info->component_id & acpi_dbg_layer)) {
+ !(component_id & acpi_dbg_layer)) {
return;
}
- va_start (args, format);
- acpi_os_vprintf (format, args);
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
}
-EXPORT_SYMBOL(acpi_ut_debug_print_raw);
+EXPORT_SYMBOL(acpi_ut_debug_print_raw);
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
*
* RETURN: None
*
@@ -244,29 +263,28 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw);
******************************************************************************/
void
-acpi_ut_trace (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info)
+acpi_ut_trace(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s\n", acpi_gbl_fn_entry_str);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s\n", acpi_gbl_fn_entry_str);
}
-EXPORT_SYMBOL(acpi_ut_trace);
+EXPORT_SYMBOL(acpi_ut_trace);
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_ptr
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Pointer - Pointer to display
*
* RETURN: None
@@ -277,28 +295,27 @@ EXPORT_SYMBOL(acpi_ut_trace);
******************************************************************************/
void
-acpi_ut_trace_ptr (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- void *pointer)
+acpi_ut_trace_ptr(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, void *pointer)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %p\n", acpi_gbl_fn_entry_str, pointer);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %p\n", acpi_gbl_fn_entry_str,
+ pointer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_str
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* String - Additional string to display
*
* RETURN: None
@@ -309,29 +326,28 @@ acpi_ut_trace_ptr (
******************************************************************************/
void
-acpi_ut_trace_str (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *string)
+acpi_ut_trace_str(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *string)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %s\n", acpi_gbl_fn_entry_str, string);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %s\n", acpi_gbl_fn_entry_str,
+ string);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_u32
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Integer - Integer to display
*
* RETURN: None
@@ -342,29 +358,28 @@ acpi_ut_trace_str (
******************************************************************************/
void
-acpi_ut_trace_u32 (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u32 integer)
+acpi_ut_trace_u32(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u32 integer)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %08X\n", acpi_gbl_fn_entry_str, integer);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %08X\n", acpi_gbl_fn_entry_str,
+ integer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
*
* RETURN: None
*
@@ -374,28 +389,27 @@ acpi_ut_trace_u32 (
******************************************************************************/
void
-acpi_ut_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info)
+acpi_ut_exit(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s\n", acpi_gbl_fn_exit_str);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s\n", acpi_gbl_fn_exit_str);
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_exit);
+EXPORT_SYMBOL(acpi_ut_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_status_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Status - Exit status code
*
* RETURN: None
@@ -406,37 +420,38 @@ EXPORT_SYMBOL(acpi_ut_exit);
******************************************************************************/
void
-acpi_ut_status_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_status status)
+acpi_ut_status_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_status status)
{
- if (ACPI_SUCCESS (status)) {
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %s\n", acpi_gbl_fn_exit_str,
- acpi_format_exception (status));
- }
- else {
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s ****Exception****: %s\n", acpi_gbl_fn_exit_str,
- acpi_format_exception (status));
+ if (ACPI_SUCCESS(status)) {
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %s\n",
+ acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
+ } else {
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s ****Exception****: %s\n",
+ acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
}
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_status_exit);
+EXPORT_SYMBOL(acpi_ut_status_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_value_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Value - Value to be printed with exit msg
*
* RETURN: None
@@ -447,30 +462,29 @@ EXPORT_SYMBOL(acpi_ut_status_exit);
******************************************************************************/
void
-acpi_ut_value_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_integer value)
+acpi_ut_value_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_integer value)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str,
- ACPI_FORMAT_UINT64 (value));
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %8.8X%8.8X\n",
+ acpi_gbl_fn_exit_str, ACPI_FORMAT_UINT64(value));
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_value_exit);
+EXPORT_SYMBOL(acpi_ut_value_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_ptr_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Ptr - Pointer to display
*
* RETURN: None
@@ -481,21 +495,20 @@ EXPORT_SYMBOL(acpi_ut_value_exit);
******************************************************************************/
void
-acpi_ut_ptr_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u8 *ptr)
+acpi_ut_ptr_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u8 * ptr)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %p\n", acpi_gbl_fn_exit_str, ptr);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %p\n", acpi_gbl_fn_exit_str, ptr);
acpi_gbl_nesting_level--;
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dump_buffer
@@ -511,23 +524,17 @@ acpi_ut_ptr_exit (
*
******************************************************************************/
-void
-acpi_ut_dump_buffer (
- u8 *buffer,
- u32 count,
- u32 display,
- u32 component_id)
+void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
{
- acpi_native_uint i = 0;
- acpi_native_uint j;
- u32 temp32;
- u8 buf_char;
-
+ 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))) {
+ (component_id & acpi_dbg_layer))) {
return;
}
@@ -540,7 +547,7 @@ acpi_ut_dump_buffer (
while (i < count) {
/* Print current offset */
- acpi_os_printf ("%6.4X: ", (u32) i);
+ acpi_os_printf("%6.4X: ", (u32) i);
/* Print 16 hex chars */
@@ -548,73 +555,66 @@ acpi_ut_dump_buffer (
if (i + j >= count) {
/* Dump fill spaces */
- acpi_os_printf ("%*s", ((display * 2) + 1), " ");
- j += display;
+ acpi_os_printf("%*s", ((display * 2) + 1), " ");
+ j += (acpi_native_uint) display;
continue;
}
switch (display) {
- default: /* Default is BYTE display */
+ default: /* Default is BYTE display */
- acpi_os_printf ("%02X ", buffer[i + j]);
+ acpi_os_printf("%02X ", buffer[i + j]);
break;
-
case DB_WORD_DISPLAY:
- ACPI_MOVE_16_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%04X ", temp32);
+ ACPI_MOVE_16_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%04X ", temp32);
break;
-
case DB_DWORD_DISPLAY:
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%08X ", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%08X ", temp32);
break;
-
case DB_QWORD_DISPLAY:
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%08X", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%08X", temp32);
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j + 4]);
- acpi_os_printf ("%08X ", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j + 4]);
+ acpi_os_printf("%08X ", temp32);
break;
}
- j += display;
+ j += (acpi_native_uint) display;
}
/*
- * Print the ASCII equivalent characters
- * But watch out for the bad unprintable ones...
+ * Print the ASCII equivalent characters but watch out for the bad
+ * unprintable ones (printable chars are 0x20 through 0x7E)
*/
- acpi_os_printf (" ");
+ acpi_os_printf(" ");
for (j = 0; j < 16; j++) {
if (i + j >= count) {
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return;
}
buf_char = buffer[i + j];
- if ((buf_char > 0x1F && buf_char < 0x2E) ||
- (buf_char > 0x2F && buf_char < 0x61) ||
- (buf_char > 0x60 && buf_char < 0x7F)) {
- acpi_os_printf ("%c", buf_char);
- }
- else {
- acpi_os_printf (".");
+ if (ACPI_IS_PRINT(buf_char)) {
+ acpi_os_printf("%c", buf_char);
+ } else {
+ acpi_os_printf(".");
}
}
/* Done with that line. */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
i += 16;
}
return;
}
-
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index bc5403022681..2bc878f7a127 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
@@ -49,19 +48,13 @@
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utdelete")
+ACPI_MODULE_NAME("utdelete")
/* Local prototypes */
+static void acpi_ut_delete_internal_obj(union acpi_operand_object *object);
static void
-acpi_ut_delete_internal_obj (
- union acpi_operand_object *object);
-
-static void
-acpi_ut_update_ref_count (
- union acpi_operand_object *object,
- u32 action);
-
+acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action);
/*******************************************************************************
*
@@ -76,18 +69,14 @@ acpi_ut_update_ref_count (
*
******************************************************************************/
-static void
-acpi_ut_delete_internal_obj (
- union acpi_operand_object *object)
+static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
{
- void *obj_pointer = NULL;
- union acpi_operand_object *handler_desc;
- union acpi_operand_object *second_desc;
- union acpi_operand_object *next_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_delete_internal_obj", object);
+ void *obj_pointer = NULL;
+ union acpi_operand_object *handler_desc;
+ union acpi_operand_object *second_desc;
+ union acpi_operand_object *next_desc;
+ ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object);
if (!object) {
return_VOID;
@@ -97,11 +86,12 @@ acpi_ut_delete_internal_obj (
* Must delete or free any pointers within the object that are not
* actual ACPI objects (for example, a raw buffer pointer).
*/
- switch (ACPI_GET_OBJECT_TYPE (object)) {
+ switch (ACPI_GET_OBJECT_TYPE(object)) {
case ACPI_TYPE_STRING:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
- object, object->string.pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "**** String %p, ptr %p\n", object,
+ object->string.pointer));
/* Free the actual string buffer */
@@ -112,11 +102,11 @@ acpi_ut_delete_internal_obj (
}
break;
-
case ACPI_TYPE_BUFFER:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
- object, object->buffer.pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "**** Buffer %p, ptr %p\n", object,
+ object->buffer.pointer));
/* Free the actual buffer */
@@ -127,11 +117,11 @@ acpi_ut_delete_internal_obj (
}
break;
-
case ACPI_TYPE_PACKAGE:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
- object->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ " **** Package of count %X\n",
+ object->package.count));
/*
* Elements of the package are not handled here, they are deleted
@@ -143,11 +133,11 @@ acpi_ut_delete_internal_obj (
obj_pointer = object->package.elements;
break;
-
case ACPI_TYPE_DEVICE:
if (object->device.gpe_block) {
- (void) acpi_ev_delete_gpe_block (object->device.gpe_block);
+ (void)acpi_ev_delete_gpe_block(object->device.
+ gpe_block);
}
/* Walk the handler list for this device */
@@ -155,54 +145,51 @@ acpi_ut_delete_internal_obj (
handler_desc = object->device.handler;
while (handler_desc) {
next_desc = handler_desc->address_space.next;
- acpi_ut_remove_reference (handler_desc);
+ acpi_ut_remove_reference(handler_desc);
handler_desc = next_desc;
}
break;
-
case ACPI_TYPE_MUTEX:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Mutex %p, Semaphore %p\n",
- object, object->mutex.semaphore));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Mutex %p, Semaphore %p\n",
+ object, object->mutex.semaphore));
- acpi_ex_unlink_mutex (object);
- (void) acpi_os_delete_semaphore (object->mutex.semaphore);
+ acpi_ex_unlink_mutex(object);
+ (void)acpi_os_delete_semaphore(object->mutex.semaphore);
break;
-
case ACPI_TYPE_EVENT:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Event %p, Semaphore %p\n",
- object, object->event.semaphore));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Event %p, Semaphore %p\n",
+ object, object->event.semaphore));
- (void) acpi_os_delete_semaphore (object->event.semaphore);
+ (void)acpi_os_delete_semaphore(object->event.semaphore);
object->event.semaphore = NULL;
break;
-
case ACPI_TYPE_METHOD:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Method %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Method %p\n", object));
/* Delete the method semaphore if it exists */
if (object->method.semaphore) {
- (void) acpi_os_delete_semaphore (object->method.semaphore);
+ (void)acpi_os_delete_semaphore(object->method.
+ semaphore);
object->method.semaphore = NULL;
}
break;
-
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Region %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Region %p\n", object));
- second_desc = acpi_ns_get_secondary_object (object);
+ second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
/*
* Free the region_context if and only if the handler is one of the
@@ -211,32 +198,33 @@ acpi_ut_delete_internal_obj (
*/
handler_desc = object->region.handler;
if (handler_desc) {
- if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
- obj_pointer = second_desc->extra.region_context;
+ if (handler_desc->address_space.
+ hflags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
+ obj_pointer =
+ second_desc->extra.region_context;
}
- acpi_ut_remove_reference (handler_desc);
+ acpi_ut_remove_reference(handler_desc);
}
/* Now we can free the Extra object */
- acpi_ut_delete_object_desc (second_desc);
+ acpi_ut_delete_object_desc(second_desc);
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Buffer Field %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Buffer Field %p\n", object));
- second_desc = acpi_ns_get_secondary_object (object);
+ second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
- acpi_ut_delete_object_desc (second_desc);
+ acpi_ut_delete_object_desc(second_desc);
}
break;
-
default:
break;
}
@@ -244,21 +232,20 @@ acpi_ut_delete_internal_obj (
/* Free any allocated memory (pointer within the object) found above */
if (obj_pointer) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
- obj_pointer));
- ACPI_MEM_FREE (obj_pointer);
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Deleting Object Subptr %p\n", obj_pointer));
+ ACPI_MEM_FREE(obj_pointer);
}
/* Now the object can be safely deleted */
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
- object, acpi_ut_get_object_type_name (object)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
+ object, acpi_ut_get_object_type_name(object)));
- acpi_ut_delete_object_desc (object);
+ acpi_ut_delete_object_desc(object);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_delete_internal_object_list
@@ -272,29 +259,24 @@ acpi_ut_delete_internal_obj (
*
******************************************************************************/
-void
-acpi_ut_delete_internal_object_list (
- union acpi_operand_object **obj_list)
+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");
+ union acpi_operand_object **internal_obj;
+ ACPI_FUNCTION_TRACE("ut_delete_internal_object_list");
/* Walk the null-terminated internal list */
for (internal_obj = obj_list; *internal_obj; internal_obj++) {
- acpi_ut_remove_reference (*internal_obj);
+ acpi_ut_remove_reference(*internal_obj);
}
/* Free the combined parameter pointer list and object array */
- ACPI_MEM_FREE (obj_list);
+ ACPI_MEM_FREE(obj_list);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_update_ref_count
@@ -309,16 +291,12 @@ acpi_ut_delete_internal_object_list (
******************************************************************************/
static void
-acpi_ut_update_ref_count (
- union acpi_operand_object *object,
- u32 action)
+acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
{
- u16 count;
- u16 new_count;
-
-
- ACPI_FUNCTION_NAME ("ut_update_ref_count");
+ u16 count;
+ u16 new_count;
+ ACPI_FUNCTION_NAME("ut_update_ref_count");
if (!object) {
return;
@@ -338,58 +316,55 @@ acpi_ut_update_ref_count (
new_count++;
object->common.reference_count = new_count;
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, [Incremented]\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, [Incremented]\n",
+ object, new_count));
break;
-
case REF_DECREMENT:
if (count < 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
+ object, new_count));
new_count = 0;
- }
- else {
+ } else {
new_count--;
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, [Decremented]\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, [Decremented]\n",
+ object, new_count));
}
- if (ACPI_GET_OBJECT_TYPE (object) == ACPI_TYPE_METHOD) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Method Obj %p Refs=%X, [Decremented]\n",
- object, new_count));
+ if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Method Obj %p Refs=%X, [Decremented]\n",
+ object, new_count));
}
object->common.reference_count = new_count;
if (new_count == 0) {
- acpi_ut_delete_internal_obj (object);
+ acpi_ut_delete_internal_obj(object);
}
break;
-
case REF_FORCE_DELETE:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, Force delete! (Set to 0)\n",
- object, count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, Force delete! (Set to 0)\n",
+ object, count));
new_count = 0;
object->common.reference_count = new_count;
- acpi_ut_delete_internal_obj (object);
+ acpi_ut_delete_internal_obj(object);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown action (%X)\n", action));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown action (%X)\n",
+ action));
break;
}
@@ -399,15 +374,14 @@ acpi_ut_update_ref_count (
*/
if (count > ACPI_MAX_REFERENCE_COUNT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
- "**** Warning **** Large Reference Count (%X) in object %p\n\n",
- count, object));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "**** Warning **** Large Reference Count (%X) in object %p\n\n",
+ count, object));
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_update_object_reference
@@ -431,65 +405,42 @@ acpi_ut_update_ref_count (
******************************************************************************/
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;
- u32 i;
- union acpi_generic_state *state_list = NULL;
- union acpi_generic_state *state;
- union acpi_operand_object *tmp;
-
- ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object);
+ acpi_status status = AE_OK;
+ union acpi_generic_state *state_list = NULL;
+ union acpi_operand_object *next_object = NULL;
+ union acpi_generic_state *state;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object);
- /* Ignore a null object ptr */
+ while (object) {
+ /* Make sure that this isn't a namespace handle */
- if (!object) {
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Make sure that this isn't a namespace handle */
-
- if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Object %p is NS handle\n", object));
- return_ACPI_STATUS (AE_OK);
- }
-
- state = acpi_ut_create_update_state (object, action);
-
- while (state) {
- object = state->update.object;
- action = state->update.value;
- acpi_ut_delete_generic_state (state);
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Object %p is NS handle\n", object));
+ return_ACPI_STATUS(AE_OK);
+ }
/*
* All sub-objects must have their reference count incremented also.
* Different object types have different subobjects.
*/
- switch (ACPI_GET_OBJECT_TYPE (object)) {
+ switch (ACPI_GET_OBJECT_TYPE(object)) {
case ACPI_TYPE_DEVICE:
- tmp = object->device.system_notify;
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->device.system_notify = NULL;
- acpi_ut_update_ref_count (tmp, action);
-
- tmp = object->device.device_notify;
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->device.device_notify = NULL;
- acpi_ut_update_ref_count (tmp, action);
-
+ acpi_ut_update_ref_count(object->device.system_notify,
+ action);
+ acpi_ut_update_ref_count(object->device.device_notify,
+ action);
break;
-
case ACPI_TYPE_PACKAGE:
-
/*
- * We must update all the sub-objects of the package
- * (Each of whom may have their own sub-objects, etc.
+ * We must update all the sub-objects of the package,
+ * each of whom may have their own sub-objects.
*/
for (i = 0; i < object->package.count; i++) {
/*
@@ -497,116 +448,67 @@ acpi_ut_update_object_reference (
* Note: There can be null elements within the package,
* these are simply ignored
*/
- status = acpi_ut_create_update_state_and_push (
- object->package.elements[i], action, &state_list);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_create_update_state_and_push
+ (object->package.elements[i], action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->package.elements[i];
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->package.elements[i] = NULL;
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->buffer_field.buffer_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->buffer_field.buffer_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->buffer_field.buffer_obj = NULL;
+ next_object = object->buffer_field.buffer_obj;
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->field.region_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->field.region_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->field.region_obj = NULL;
- break;
-
+ next_object = object->field.region_obj;
+ break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->bank_field.bank_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
+ next_object = object->bank_field.bank_obj;
+ status =
+ acpi_ut_create_update_state_and_push(object->
+ bank_field.
+ region_obj,
+ action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->bank_field.bank_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->bank_field.bank_obj = NULL;
-
- status = acpi_ut_create_update_state_and_push (
- object->bank_field.region_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->bank_field.region_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->bank_field.region_obj = NULL;
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->index_field.index_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->index_field.index_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->index_field.index_obj = NULL;
-
- status = acpi_ut_create_update_state_and_push (
- object->index_field.data_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
+ next_object = object->index_field.index_obj;
+ status =
+ acpi_ut_create_update_state_and_push(object->
+ index_field.
+ data_obj,
+ action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->index_field.data_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->index_field.data_obj = NULL;
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
-
/*
* The target of an Index (a package, string, or buffer) must track
* changes to the ref count of the index.
*/
if (object->reference.opcode == AML_INDEX_OP) {
- status = acpi_ut_create_update_state_and_push (
- object->reference.object, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
+ next_object = object->reference.object;
}
break;
-
case ACPI_TYPE_REGION:
default:
-
- /* No subobjects */
- break;
+ break; /* No subobjects */
}
/*
@@ -614,25 +516,31 @@ acpi_ut_update_object_reference (
* happen after we update the sub-objects in case this causes the
* main object to be deleted.
*/
- acpi_ut_update_ref_count (object, action);
+ acpi_ut_update_ref_count(object, action);
+ object = NULL;
/* Move on to the next object to be updated */
- state = acpi_ut_pop_generic_state (&state_list);
+ if (next_object) {
+ object = next_object;
+ next_object = NULL;
+ } else if (state_list) {
+ state = acpi_ut_pop_generic_state(&state_list);
+ object = state->update.object;
+ acpi_ut_delete_generic_state(state);
+ }
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
- ACPI_REPORT_ERROR (("Could not update object reference count, %s\n",
- acpi_format_exception (status)));
+ ACPI_REPORT_ERROR(("Could not update object reference count, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_add_reference
@@ -646,31 +554,27 @@ error_exit:
*
******************************************************************************/
-void
-acpi_ut_add_reference (
- union acpi_operand_object *object)
+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 */
- if (!acpi_ut_valid_internal_object (object)) {
+ if (!acpi_ut_valid_internal_object(object)) {
return_VOID;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Current Refs=%X [To Be Incremented]\n",
- object, object->common.reference_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Current Refs=%X [To Be Incremented]\n",
+ object, object->common.reference_count));
/* Increment the reference count */
- (void) acpi_ut_update_object_reference (object, REF_INCREMENT);
+ (void)acpi_ut_update_object_reference(object, REF_INCREMENT);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_remove_reference
@@ -683,13 +587,10 @@ acpi_ut_add_reference (
*
******************************************************************************/
-void
-acpi_ut_remove_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
@@ -697,27 +598,25 @@ acpi_ut_remove_reference (
*
*/
if (!object ||
- (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED)) {
+ (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) {
return_VOID;
}
/* Ensure that we have a valid object */
- if (!acpi_ut_valid_internal_object (object)) {
+ if (!acpi_ut_valid_internal_object(object)) {
return_VOID;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Current Refs=%X [To Be Decremented]\n",
- object, object->common.reference_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Current Refs=%X [To Be Decremented]\n",
+ object, object->common.reference_count));
/*
* Decrement the reference count, and only actually delete the object
* if the reference count becomes 0. (Must also decrement the ref count
* of all subobjects!)
*/
- (void) acpi_ut_update_object_reference (object, REF_DECREMENT);
+ (void)acpi_ut_update_object_reference(object, REF_DECREMENT);
return_VOID;
}
-
-
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 00046dd5d925..7b81d5ef3c32 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -41,28 +41,20 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("uteval")
+ACPI_MODULE_NAME("uteval")
/* Local prototypes */
-
static void
-acpi_ut_copy_id_string (
- char *destination,
- char *source,
- acpi_size max_length);
+acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length);
static acpi_status
-acpi_ut_translate_one_cid (
- union acpi_operand_object *obj_desc,
- struct acpi_compatible_id *one_cid);
-
+acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
+ struct acpi_compatible_id *one_cid);
/*******************************************************************************
*
@@ -77,37 +69,33 @@ acpi_ut_translate_one_cid (
*
******************************************************************************/
-acpi_status
-acpi_ut_osi_implementation (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *string_desc;
- union acpi_operand_object *return_desc;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ut_osi_implementation");
+ union acpi_operand_object *string_desc;
+ union acpi_operand_object *return_desc;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ut_osi_implementation");
/* Validate the string input argument */
string_desc = walk_state->arguments[0].object;
if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Create a return object (Default value = 0) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Compare input string to table of supported strings */
for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
- if (!ACPI_STRCMP (string_desc->string.pointer,
- (char *) acpi_gbl_valid_osi_strings[i])) {
+ if (!ACPI_STRCMP(string_desc->string.pointer,
+ (char *)acpi_gbl_valid_osi_strings[i])) {
/* This string is supported */
return_desc->integer.value = 0xFFFFFFFF;
@@ -116,10 +104,9 @@ acpi_ut_osi_implementation (
}
walk_state->return_desc = return_desc;
- return_ACPI_STATUS (AE_CTRL_TERMINATE);
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_evaluate_object
@@ -140,19 +127,16 @@ acpi_ut_osi_implementation (
******************************************************************************/
acpi_status
-acpi_ut_evaluate_object (
- struct acpi_namespace_node *prefix_node,
- char *path,
- u32 expected_return_btypes,
- union acpi_operand_object **return_desc)
+acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
+ char *path,
+ u32 expected_return_btypes,
+ union acpi_operand_object **return_desc)
{
- struct acpi_parameter_info info;
- acpi_status status;
- u32 return_btype;
-
-
- ACPI_FUNCTION_TRACE ("ut_evaluate_object");
+ struct acpi_parameter_info info;
+ acpi_status status;
+ u32 return_btype;
+ ACPI_FUNCTION_TRACE("ut_evaluate_object");
info.node = prefix_node;
info.parameters = NULL;
@@ -160,36 +144,38 @@ acpi_ut_evaluate_object (
/* Evaluate the object/method */
- status = acpi_ns_evaluate_relative (path, &info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_evaluate_relative(path, &info);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
- acpi_ut_get_node_name (prefix_node), path));
- }
- else {
- ACPI_REPORT_METHOD_ERROR ("Method execution failed",
- prefix_node, path, status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%4.4s.%s] was not found\n",
+ acpi_ut_get_node_name(prefix_node),
+ path));
+ } else {
+ ACPI_REPORT_METHOD_ERROR("Method execution failed",
+ prefix_node, path, status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Did we get a return object? */
if (!info.return_object) {
if (expected_return_btypes) {
- ACPI_REPORT_METHOD_ERROR ("No object was returned from",
- prefix_node, path, AE_NOT_EXIST);
+ ACPI_REPORT_METHOD_ERROR("No object was returned from",
+ prefix_node, path,
+ AE_NOT_EXIST);
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* 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;
@@ -211,41 +197,41 @@ acpi_ut_evaluate_object (
break;
}
- if ((acpi_gbl_enable_interpreter_slack) &&
- (!expected_return_btypes)) {
+ if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
/*
* We received a return object, but one was not expected. This can
* 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);
+ return_ACPI_STATUS(AE_OK);
}
/* Is the return object one of the expected types? */
if (!(expected_return_btypes & return_btype)) {
- ACPI_REPORT_METHOD_ERROR ("Return object type is incorrect",
- prefix_node, path, AE_TYPE);
+ ACPI_REPORT_METHOD_ERROR("Return object type is incorrect",
+ prefix_node, path, AE_TYPE);
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
- path, acpi_ut_get_object_type_name (info.return_object),
- expected_return_btypes));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
+ path,
+ 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);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Object type is OK, return it */
*return_desc = info.return_object;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_evaluate_numeric_object
@@ -264,22 +250,19 @@ acpi_ut_evaluate_object (
******************************************************************************/
acpi_status
-acpi_ut_evaluate_numeric_object (
- char *object_name,
- struct acpi_namespace_node *device_node,
- acpi_integer *address)
+acpi_ut_evaluate_numeric_object(char *object_name,
+ struct acpi_namespace_node *device_node,
+ acpi_integer * address)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ 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);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, object_name,
+ ACPI_BTYPE_INTEGER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the returned Integer */
@@ -288,11 +271,10 @@ acpi_ut_evaluate_numeric_object (
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
@@ -310,10 +292,7 @@ acpi_ut_evaluate_numeric_object (
******************************************************************************/
static void
-acpi_ut_copy_id_string (
- char *destination,
- char *source,
- acpi_size max_length)
+acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length)
{
/*
@@ -328,10 +307,9 @@ acpi_ut_copy_id_string (
/* Do the actual copy */
- ACPI_STRNCPY (destination, source, max_length);
+ ACPI_STRNCPY(destination, source, max_length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
@@ -349,42 +327,39 @@ acpi_ut_copy_id_string (
******************************************************************************/
acpi_status
-acpi_ut_execute_HID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *hid)
+acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *hid)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ 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, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ 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, hid->value);
- }
- else {
+ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
+ hid->value);
+ } else {
/* Copy the String HID from the returned object */
- acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer,
- sizeof (hid->value));
+ acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer,
+ sizeof(hid->value));
}
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_translate_one_cid
@@ -403,18 +378,17 @@ acpi_ut_execute_HID (
******************************************************************************/
static acpi_status
-acpi_ut_translate_one_cid (
- union acpi_operand_object *obj_desc,
- struct acpi_compatible_id *one_cid)
+acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
+ struct acpi_compatible_id *one_cid)
{
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
/* Convert the Numeric CID to string */
- acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value);
+ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
+ one_cid->value);
return (AE_OK);
case ACPI_TYPE_STRING:
@@ -425,8 +399,8 @@ acpi_ut_translate_one_cid (
/* Copy the String CID from the returned object */
- acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer,
- ACPI_MAX_CID_LENGTH);
+ acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer,
+ ACPI_MAX_CID_LENGTH);
return (AE_OK);
default:
@@ -435,7 +409,6 @@ acpi_ut_translate_one_cid (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
@@ -453,45 +426,42 @@ acpi_ut_translate_one_cid (
******************************************************************************/
acpi_status
-acpi_ut_execute_CID (
- struct acpi_namespace_node *device_node,
- struct acpi_compatible_id_list **return_cid_list)
+acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
+ struct acpi_compatible_id_list ** return_cid_list)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u32 count;
- u32 size;
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u32 count;
+ u32 size;
struct acpi_compatible_id_list *cid_list;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_CID");
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ut_execute_CID");
/* Evaluate the _CID method for this device */
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID,
- ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
+ | ACPI_BTYPE_PACKAGE, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the number of _CIDs returned */
count = 1;
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
}
/* Allocate a worst-case buffer for the _CIDs */
- size = (((count - 1) * sizeof (struct acpi_compatible_id)) +
- sizeof (struct acpi_compatible_id_list));
+ 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_MEM_CALLOCATE((acpi_size) size);
if (!cid_list) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init CID list */
@@ -508,39 +478,38 @@ acpi_ut_execute_CID (
/* 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) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
/* Translate each package element */
for (i = 0; i < count; i++) {
- status = acpi_ut_translate_one_cid (obj_desc->package.elements[i],
- &cid_list->id[i]);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_translate_one_cid(obj_desc->package.
+ elements[i],
+ &cid_list->id[i]);
+ if (ACPI_FAILURE(status)) {
break;
}
}
- }
- else {
+ } else {
/* Only one CID, translate to a string */
- status = acpi_ut_translate_one_cid (obj_desc, cid_list->id);
+ status = acpi_ut_translate_one_cid(obj_desc, cid_list->id);
}
/* Cleanup on error */
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (cid_list);
- }
- else {
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(cid_list);
+ } else {
*return_cid_list = cid_list;
}
/* On exit, we must delete the _CID return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
@@ -558,42 +527,39 @@ acpi_ut_execute_CID (
******************************************************************************/
acpi_status
-acpi_ut_execute_UID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *uid)
+acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *uid)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_UID");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ut_execute_UID");
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__UID,
- ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ 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, uid->value);
- }
- else {
+ acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
+ uid->value);
+ } else {
/* Copy the String UID from the returned object */
- acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer,
- sizeof (uid->value));
+ acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer,
+ sizeof(uid->value));
}
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_STA
@@ -611,30 +577,26 @@ acpi_ut_execute_UID (
******************************************************************************/
acpi_status
-acpi_ut_execute_STA (
- struct acpi_namespace_node *device_node,
- u32 *flags)
+acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ 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);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
+ ACPI_BTYPE_INTEGER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
if (AE_NOT_FOUND == status) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "_STA on %4.4s was not found, assuming device is present\n",
- acpi_ut_get_node_name (device_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "_STA on %4.4s was not found, assuming device is present\n",
+ acpi_ut_get_node_name(device_node)));
*flags = 0x0F;
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Extract the status flags */
@@ -643,11 +605,10 @@ acpi_ut_execute_STA (
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_Sxds
@@ -665,44 +626,45 @@ acpi_ut_execute_STA (
******************************************************************************/
acpi_status
-acpi_ut_execute_sxds (
- struct acpi_namespace_node *device_node,
- u8 *highest)
+acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ut_execute_Sxds");
for (i = 0; i < 4; i++) {
highest[i] = 0xFF;
- status = acpi_ut_evaluate_object (device_node,
- (char *) acpi_gbl_highest_dstate_names[i],
- ACPI_BTYPE_INTEGER, &obj_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_evaluate_object(device_node,
+ (char *)
+ acpi_gbl_highest_dstate_names
+ [i], ACPI_BTYPE_INTEGER,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s on Device %4.4s, %s\n",
- (char *) acpi_gbl_highest_dstate_names[i],
- acpi_ut_get_node_name (device_node),
- acpi_format_exception (status)));
-
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%s on Device %4.4s, %s\n",
+ (char *)
+ acpi_gbl_highest_dstate_names
+ [i],
+ acpi_ut_get_node_name
+ (device_node),
+ acpi_format_exception
+ (status)));
+
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/* Extract the Dstate value */
highest[i] = (u8) obj_desc->integer.value;
/* Delete the return object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 4146019b543f..399e64b51886 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -48,8 +48,7 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utglobal")
-
+ACPI_MODULE_NAME("utglobal")
/*******************************************************************************
*
@@ -63,17 +62,12 @@
* DESCRIPTION: This function translates an ACPI exception into an ASCII string.
*
******************************************************************************/
-
-const char *
-acpi_format_exception (
- acpi_status status)
+const char *acpi_format_exception(acpi_status status)
{
- acpi_status sub_status;
- const char *exception = NULL;
-
-
- ACPI_FUNCTION_NAME ("format_exception");
+ acpi_status sub_status;
+ const char *exception = NULL;
+ ACPI_FUNCTION_NAME("format_exception");
sub_status = (status & ~AE_CODE_MASK);
@@ -81,35 +75,39 @@ acpi_format_exception (
case AE_CODE_ENVIRONMENTAL:
if (sub_status <= AE_CODE_ENV_MAX) {
- exception = acpi_gbl_exception_names_env [sub_status];
+ exception = acpi_gbl_exception_names_env[sub_status];
}
break;
case AE_CODE_PROGRAMMER:
if (sub_status <= AE_CODE_PGM_MAX) {
- exception = acpi_gbl_exception_names_pgm [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_pgm[sub_status - 1];
}
break;
case AE_CODE_ACPI_TABLES:
if (sub_status <= AE_CODE_TBL_MAX) {
- exception = acpi_gbl_exception_names_tbl [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_tbl[sub_status - 1];
}
break;
case AE_CODE_AML:
if (sub_status <= AE_CODE_AML_MAX) {
- exception = acpi_gbl_exception_names_aml [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_aml[sub_status - 1];
}
break;
case AE_CODE_CONTROL:
if (sub_status <= AE_CODE_CTRL_MAX) {
- exception = acpi_gbl_exception_names_ctrl [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_ctrl[sub_status - 1];
}
break;
@@ -120,16 +118,15 @@ acpi_format_exception (
if (!exception) {
/* Exception code was not recognized */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown exception code: 0x%8.8X\n", status));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown exception code: 0x%8.8X\n", status));
- return ((const char *) "UNKNOWN_STATUS_CODE");
+ return ((const char *)"UNKNOWN_STATUS_CODE");
}
- return ((const char *) exception);
+ return ((const char *)exception);
}
-
/*******************************************************************************
*
* Static global variable initialization.
@@ -142,34 +139,32 @@ acpi_format_exception (
*/
/* Debug switch - level and trace mask */
-u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
+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;
+u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
EXPORT_SYMBOL(acpi_dbg_layer);
-u32 acpi_gbl_nesting_level = 0;
-
+u32 acpi_gbl_nesting_level = 0;
/* Debugger globals */
-u8 acpi_gbl_db_terminate_threads = FALSE;
-u8 acpi_gbl_abort_method = FALSE;
-u8 acpi_gbl_method_executing = FALSE;
+u8 acpi_gbl_db_terminate_threads = FALSE;
+u8 acpi_gbl_abort_method = FALSE;
+u8 acpi_gbl_method_executing = FALSE;
/* System flags */
-u32 acpi_gbl_startup_flags = 0;
+u32 acpi_gbl_startup_flags = 0;
/* System starts uninitialized */
-u8 acpi_gbl_shutdown = TRUE;
+u8 acpi_gbl_shutdown = TRUE;
-const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
+const u8 acpi_gbl_decode_to8bit[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
-const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
-{
+const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S0_",
"\\_S1_",
"\\_S2_",
@@ -178,8 +173,7 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COU
"\\_S5_"
};
-const char *acpi_gbl_highest_dstate_names[4] =
-{
+const char *acpi_gbl_highest_dstate_names[4] = {
"_S1D",
"_S2D",
"_S3D",
@@ -190,8 +184,7 @@ const char *acpi_gbl_highest_dstate_names[4] =
* 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] =
-{
+const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
/* Operating System Vendor Strings */
"Linux",
@@ -209,7 +202,6 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
"Extended Address Space Descriptor"
};
-
/*******************************************************************************
*
* Namespace globals
@@ -225,74 +217,70 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
* 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
* perform a Notify() operation on it.
*/
-const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
-{ {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_SB_", ACPI_TYPE_DEVICE, NULL},
- {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_TZ_", ACPI_TYPE_THERMAL, NULL},
- {"_REV", ACPI_TYPE_INTEGER, (char *) ACPI_CA_SUPPORT_LEVEL},
- {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
- {"_GL_", ACPI_TYPE_MUTEX, (char *) 1},
+const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
+ { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_SB_", ACPI_TYPE_DEVICE, NULL},
+{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_TZ_", ACPI_TYPE_THERMAL, NULL},
+{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
+{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
+{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
- {"_OSI", ACPI_TYPE_METHOD, (char *) 1},
+{"_OSI", ACPI_TYPE_METHOD, (char *)1},
#endif
/* Table terminator */
- {NULL, ACPI_TYPE_ANY, NULL}
+{NULL, ACPI_TYPE_ANY, NULL}
};
/*
* Properties of the ACPI Object Types, both internal and external.
* The table is indexed by values of acpi_object_type
*/
-const u8 acpi_gbl_ns_properties[] =
-{
- ACPI_NS_NORMAL, /* 00 Any */
- ACPI_NS_NORMAL, /* 01 Number */
- ACPI_NS_NORMAL, /* 02 String */
- ACPI_NS_NORMAL, /* 03 Buffer */
- ACPI_NS_NORMAL, /* 04 Package */
- ACPI_NS_NORMAL, /* 05 field_unit */
- ACPI_NS_NEWSCOPE, /* 06 Device */
- ACPI_NS_NORMAL, /* 07 Event */
- ACPI_NS_NEWSCOPE, /* 08 Method */
- ACPI_NS_NORMAL, /* 09 Mutex */
- ACPI_NS_NORMAL, /* 10 Region */
- ACPI_NS_NEWSCOPE, /* 11 Power */
- ACPI_NS_NEWSCOPE, /* 12 Processor */
- ACPI_NS_NEWSCOPE, /* 13 Thermal */
- ACPI_NS_NORMAL, /* 14 buffer_field */
- ACPI_NS_NORMAL, /* 15 ddb_handle */
- ACPI_NS_NORMAL, /* 16 Debug Object */
- ACPI_NS_NORMAL, /* 17 def_field */
- ACPI_NS_NORMAL, /* 18 bank_field */
- ACPI_NS_NORMAL, /* 19 index_field */
- ACPI_NS_NORMAL, /* 20 Reference */
- ACPI_NS_NORMAL, /* 21 Alias */
- ACPI_NS_NORMAL, /* 22 method_alias */
- ACPI_NS_NORMAL, /* 23 Notify */
- ACPI_NS_NORMAL, /* 24 Address Handler */
- ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
- ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
- ACPI_NS_NEWSCOPE, /* 27 Scope */
- ACPI_NS_NORMAL, /* 28 Extra */
- ACPI_NS_NORMAL, /* 29 Data */
- ACPI_NS_NORMAL /* 30 Invalid */
+const u8 acpi_gbl_ns_properties[] = {
+ ACPI_NS_NORMAL, /* 00 Any */
+ ACPI_NS_NORMAL, /* 01 Number */
+ ACPI_NS_NORMAL, /* 02 String */
+ ACPI_NS_NORMAL, /* 03 Buffer */
+ ACPI_NS_NORMAL, /* 04 Package */
+ ACPI_NS_NORMAL, /* 05 field_unit */
+ ACPI_NS_NEWSCOPE, /* 06 Device */
+ ACPI_NS_NORMAL, /* 07 Event */
+ ACPI_NS_NEWSCOPE, /* 08 Method */
+ ACPI_NS_NORMAL, /* 09 Mutex */
+ ACPI_NS_NORMAL, /* 10 Region */
+ ACPI_NS_NEWSCOPE, /* 11 Power */
+ ACPI_NS_NEWSCOPE, /* 12 Processor */
+ ACPI_NS_NEWSCOPE, /* 13 Thermal */
+ ACPI_NS_NORMAL, /* 14 buffer_field */
+ ACPI_NS_NORMAL, /* 15 ddb_handle */
+ ACPI_NS_NORMAL, /* 16 Debug Object */
+ ACPI_NS_NORMAL, /* 17 def_field */
+ ACPI_NS_NORMAL, /* 18 bank_field */
+ ACPI_NS_NORMAL, /* 19 index_field */
+ ACPI_NS_NORMAL, /* 20 Reference */
+ ACPI_NS_NORMAL, /* 21 Alias */
+ ACPI_NS_NORMAL, /* 22 method_alias */
+ ACPI_NS_NORMAL, /* 23 Notify */
+ ACPI_NS_NORMAL, /* 24 Address Handler */
+ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
+ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
+ ACPI_NS_NEWSCOPE, /* 27 Scope */
+ ACPI_NS_NORMAL, /* 28 Extra */
+ ACPI_NS_NORMAL, /* 29 Data */
+ ACPI_NS_NORMAL /* 30 Invalid */
};
-
/* Hex to ASCII conversion table */
-static const char acpi_gbl_hex_to_ascii[] =
-{
- '0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'
+static const char acpi_gbl_hex_to_ascii[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_hex_to_ascii_char
@@ -307,16 +295,12 @@ static const char acpi_gbl_hex_to_ascii[] =
*
******************************************************************************/
-char
-acpi_ut_hex_to_ascii_char (
- acpi_integer integer,
- u32 position)
+char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position)
{
return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
}
-
/*******************************************************************************
*
* Table name globals
@@ -330,67 +314,139 @@ acpi_ut_hex_to_ascii_char (
*
******************************************************************************/
-struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
+struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
-struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] =
-{
+struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = {
/*********** 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, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
- /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE},
- /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE},
- /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE},
- /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
- /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
- /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof (RSDT_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
+ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1,
+ ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
+ ,
+ /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *)&acpi_gbl_DSDT,
+ sizeof(DSDT_SIG) - 1,
+ ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *)&acpi_gbl_FADT,
+ sizeof(FADT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}
+ ,
+ /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *)&acpi_gbl_FACS,
+ sizeof(FACS_SIG) - 1,
+ ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE}
+ ,
+ /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof(PSDT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof(SSDT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof(RSDT_SIG) - 1,
+ ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
+ ,
};
-
/******************************************************************************
*
* Event and Hardware globals
*
******************************************************************************/
-struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] =
-{
+struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = {
/* Name Parent Register Register Bit Position Register Bit Mask */
- /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_TIMER_STATUS, ACPI_BITMASK_TIMER_STATUS},
- /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_BUS_MASTER_STATUS, ACPI_BITMASK_BUS_MASTER_STATUS},
- /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_STATUS},
- /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_STATUS},
- /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS},
- /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS},
- /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS},
- /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS},
-
- /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE},
- /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
- /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_ENABLE},
- /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
- /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE},
- /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
- /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
-
- /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE},
- /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD},
- /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE},
- /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
- /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
- /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE},
-
- /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, ACPI_BITPOSITION_ARB_DISABLE, ACPI_BITMASK_ARB_DISABLE}
+ /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_TIMER_STATUS,
+ ACPI_BITMASK_TIMER_STATUS},
+ /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_BUS_MASTER_STATUS,
+ ACPI_BITMASK_BUS_MASTER_STATUS},
+ /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_GLOBAL_LOCK_STATUS,
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS},
+ /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_POWER_BUTTON_STATUS,
+ ACPI_BITMASK_POWER_BUTTON_STATUS},
+ /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_SLEEP_BUTTON_STATUS,
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS},
+ /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_RT_CLOCK_STATUS,
+ ACPI_BITMASK_RT_CLOCK_STATUS},
+ /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_WAKE_STATUS,
+ ACPI_BITMASK_WAKE_STATUS},
+ /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_PCIEXP_WAKE_STATUS,
+ ACPI_BITMASK_PCIEXP_WAKE_STATUS},
+
+ /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_TIMER_ENABLE,
+ ACPI_BITMASK_TIMER_ENABLE},
+ /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE,
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
+ /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_POWER_BUTTON_ENABLE,
+ ACPI_BITMASK_POWER_BUTTON_ENABLE},
+ /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE,
+ ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
+ /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_RT_CLOCK_ENABLE,
+ ACPI_BITMASK_RT_CLOCK_ENABLE},
+ /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
+ /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE,
+ ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
+
+ /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SCI_ENABLE,
+ ACPI_BITMASK_SCI_ENABLE},
+ /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_BUS_MASTER_RLD,
+ ACPI_BITMASK_BUS_MASTER_RLD},
+ /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE,
+ ACPI_BITMASK_GLOBAL_LOCK_RELEASE},
+ /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_TYPE_X,
+ ACPI_BITMASK_SLEEP_TYPE_X},
+ /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_TYPE_X,
+ ACPI_BITMASK_SLEEP_TYPE_X},
+ /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_ENABLE,
+ ACPI_BITMASK_SLEEP_ENABLE},
+
+ /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL,
+ ACPI_BITPOSITION_ARB_DISABLE,
+ ACPI_BITMASK_ARB_DISABLE}
};
-
-struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
-{
- /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, ACPI_BITREG_TIMER_ENABLE, ACPI_BITMASK_TIMER_STATUS, ACPI_BITMASK_TIMER_ENABLE},
- /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
- /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE},
- /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
- /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE},
+struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = {
+ /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS,
+ ACPI_BITREG_TIMER_ENABLE,
+ ACPI_BITMASK_TIMER_STATUS,
+ ACPI_BITMASK_TIMER_ENABLE},
+ /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS,
+ ACPI_BITREG_GLOBAL_LOCK_ENABLE,
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS,
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
+ /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS,
+ ACPI_BITREG_POWER_BUTTON_ENABLE,
+ ACPI_BITMASK_POWER_BUTTON_STATUS,
+ ACPI_BITMASK_POWER_BUTTON_ENABLE},
+ /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS,
+ ACPI_BITREG_SLEEP_BUTTON_ENABLE,
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS,
+ ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
+ /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS,
+ ACPI_BITREG_RT_CLOCK_ENABLE,
+ ACPI_BITMASK_RT_CLOCK_STATUS,
+ ACPI_BITMASK_RT_CLOCK_ENABLE},
};
/*******************************************************************************
@@ -407,8 +463,7 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVE
/* Region type decoding */
-const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
-{
+const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
"SystemMemory",
"SystemIO",
@@ -421,25 +476,18 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
/*! [End] no source code translation !*/
};
-
-char *
-acpi_ut_get_region_name (
- u8 space_id)
+char *acpi_ut_get_region_name(u8 space_id)
{
- if (space_id >= ACPI_USER_REGION_BEGIN)
- {
+ if (space_id >= ACPI_USER_REGION_BEGIN) {
return ("user_defined_region");
- }
- else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
- {
+ } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
return ("invalid_space_id");
}
- return ((char *) acpi_gbl_region_types[space_id]);
+ return ((char *)acpi_gbl_region_types[space_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_event_name
@@ -454,8 +502,7 @@ acpi_ut_get_region_name (
/* Event type decoding */
-static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] =
-{
+static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
"PM_Timer",
"global_lock",
"power_button",
@@ -463,21 +510,16 @@ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] =
"real_time_clock",
};
-
-char *
-acpi_ut_get_event_name (
- u32 event_id)
+char *acpi_ut_get_event_name(u32 event_id)
{
- if (event_id > ACPI_EVENT_MAX)
- {
+ if (event_id > ACPI_EVENT_MAX) {
return ("invalid_event_iD");
}
- return ((char *) acpi_gbl_event_types[event_id]);
+ return ((char *)acpi_gbl_event_types[event_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_type_name
@@ -498,12 +540,11 @@ acpi_ut_get_event_name (
* when stored in a table it really means that we have thus far seen no
* evidence to indicate what type is actually going to be stored for this entry.
*/
-static const char acpi_gbl_bad_type[] = "UNDEFINED";
+static const char acpi_gbl_bad_type[] = "UNDEFINED";
/* Printable names of the ACPI object types */
-static const char *acpi_gbl_ns_type_names[] =
-{
+static const char *acpi_gbl_ns_type_names[] = {
/* 00 */ "Untyped",
/* 01 */ "Integer",
/* 02 */ "String",
@@ -537,35 +578,26 @@ static const char *acpi_gbl_ns_type_names[] =
/* 30 */ "Invalid"
};
-
-char *
-acpi_ut_get_type_name (
- acpi_object_type type)
+char *acpi_ut_get_type_name(acpi_object_type type)
{
- if (type > ACPI_TYPE_INVALID)
- {
- return ((char *) acpi_gbl_bad_type);
+ if (type > ACPI_TYPE_INVALID) {
+ return ((char *)acpi_gbl_bad_type);
}
- return ((char *) acpi_gbl_ns_type_names[type]);
+ return ((char *)acpi_gbl_ns_type_names[type]);
}
-
-char *
-acpi_ut_get_object_type_name (
- union acpi_operand_object *obj_desc)
+char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
{
- if (!obj_desc)
- {
+ if (!obj_desc) {
return ("[NULL Object Descriptor]");
}
- return (acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)));
+ return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_node_name
@@ -578,39 +610,31 @@ acpi_ut_get_object_type_name (
*
******************************************************************************/
-char *
-acpi_ut_get_node_name (
- void *object)
+char *acpi_ut_get_node_name(void *object)
{
- struct acpi_namespace_node *node = (struct acpi_namespace_node *) object;
-
+ struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
- if (!object)
- {
+ if (!object) {
return ("NULL");
}
/* Check for Root node */
- if ((object == ACPI_ROOT_OBJECT) ||
- (object == acpi_gbl_root_node))
- {
+ if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) {
return ("\"\\\" ");
}
/* Descriptor must be a namespace node */
- if (node->descriptor != ACPI_DESC_TYPE_NAMED)
- {
+ if (node->descriptor != ACPI_DESC_TYPE_NAMED) {
return ("####");
}
/* Name must be a valid ACPI name */
- if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
- {
+ if (!acpi_ut_valid_acpi_name(*(u32 *) node->name.ascii)) {
return ("????");
}
@@ -619,7 +643,6 @@ acpi_ut_get_node_name (
return (node->name.ascii);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_descriptor_name
@@ -634,8 +657,7 @@ acpi_ut_get_node_name (
/* Printable names of object descriptor types */
-static const char *acpi_gbl_desc_type_names[] =
-{
+static const char *acpi_gbl_desc_type_names[] = {
/* 00 */ "Invalid",
/* 01 */ "Cached",
/* 02 */ "State-Generic",
@@ -654,27 +676,22 @@ static const char *acpi_gbl_desc_type_names[] =
/* 15 */ "Node"
};
-
-char *
-acpi_ut_get_descriptor_name (
- void *object)
+char *acpi_ut_get_descriptor_name(void *object)
{
- if (!object)
- {
+ if (!object) {
return ("NULL OBJECT");
}
- if (ACPI_GET_DESCRIPTOR_TYPE (object) > ACPI_DESC_TYPE_MAX)
- {
- return ((char *) acpi_gbl_bad_type);
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
+ return ((char *)acpi_gbl_bad_type);
}
- return ((char *) acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE (object)]);
+ return ((char *)
+ acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
}
-
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*
* Strings and procedures used for debug only
@@ -693,13 +710,10 @@ acpi_ut_get_descriptor_name (
*
******************************************************************************/
-char *
-acpi_ut_get_mutex_name (
- u32 mutex_id)
+char *acpi_ut_get_mutex_name(u32 mutex_id)
{
- if (mutex_id > MAX_MUTEX)
- {
+ if (mutex_id > MAX_MUTEX) {
return ("Invalid Mutex ID");
}
@@ -707,7 +721,6 @@ acpi_ut_get_mutex_name (
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_object_type
@@ -720,13 +733,10 @@ acpi_ut_get_mutex_name (
*
******************************************************************************/
-u8
-acpi_ut_valid_object_type (
- acpi_object_type type)
+u8 acpi_ut_valid_object_type(acpi_object_type type)
{
- if (type > ACPI_TYPE_LOCAL_MAX)
- {
+ if (type > ACPI_TYPE_LOCAL_MAX) {
/* Note: Assumes all TYPEs are contiguous (external/local) */
return (FALSE);
@@ -735,74 +745,6 @@ acpi_ut_valid_object_type (
return (TRUE);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_allocate_owner_id
- *
- * PARAMETERS: id_type - Type of ID (method or table)
- *
- * DESCRIPTION: Allocate a table or method owner id
- *
- * NOTE: this algorithm has a wraparound problem at 64_k method invocations, and
- * should be revisited (TBD)
- *
- ******************************************************************************/
-
-acpi_owner_id
-acpi_ut_allocate_owner_id (
- u32 id_type)
-{
- acpi_owner_id owner_id = 0xFFFF;
-
-
- ACPI_FUNCTION_TRACE ("ut_allocate_owner_id");
-
-
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES)))
- {
- return (0);
- }
-
- switch (id_type)
- {
- case ACPI_OWNER_TYPE_TABLE:
-
- owner_id = acpi_gbl_next_table_owner_id;
- acpi_gbl_next_table_owner_id++;
-
- /* Check for wraparound */
-
- if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID)
- {
- acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
- ACPI_REPORT_WARNING (("Table owner ID wraparound\n"));
- }
- break;
-
-
- case ACPI_OWNER_TYPE_METHOD:
-
- owner_id = acpi_gbl_next_method_owner_id;
- acpi_gbl_next_method_owner_id++;
-
- if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID)
- {
- /* Check for wraparound */
-
- acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
- }
- break;
-
- default:
- break;
- }
-
- (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
- return_VALUE (owner_id);
-}
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_init_globals
@@ -816,129 +758,96 @@ acpi_ut_allocate_owner_id (
*
******************************************************************************/
-void
-acpi_ut_init_globals (
- void)
+void acpi_ut_init_globals(void)
{
- u32 i;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ut_init_globals");
- ACPI_FUNCTION_TRACE ("ut_init_globals");
+ /* Create all memory caches */
-
- /* Memory allocation and cache lists */
-
- ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_generic_state *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_operand_object *) NULL)->cache.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].link_offset = (u16) ACPI_PTR_DIFF (&(((struct acpi_walk_state *) NULL)->next), NULL);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].object_size = sizeof (struct acpi_namespace_node);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].object_size = sizeof (union acpi_generic_state);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (struct acpi_parse_obj_common);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (struct acpi_parse_obj_named);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].object_size = sizeof (union acpi_operand_object);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].object_size = sizeof (struct acpi_walk_state);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].max_cache_depth = ACPI_MAX_STATE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].max_cache_depth = ACPI_MAX_PARSE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].max_cache_depth = ACPI_MAX_EXTPARSE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].max_cache_depth = ACPI_MAX_OBJECT_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].max_cache_depth = ACPI_MAX_WALK_CACHE_DEPTH;
-
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].list_name = "Global Memory Allocation");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].list_name = "Namespace Nodes");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].list_name = "State Object Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].list_name = "Parse Node Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].list_name = "Extended Parse Node Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].list_name = "Operand Object Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].list_name = "Tree Walk Node Cache");
+ status = acpi_ut_create_caches();
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
/* ACPI table structure */
- for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++)
- {
- acpi_gbl_table_lists[i].next = NULL;
- acpi_gbl_table_lists[i].count = 0;
+ for (i = 0; i < NUM_ACPI_TABLE_TYPES; 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++)
- {
- acpi_gbl_mutex_info[i].mutex = NULL;
- acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[i].use_count = 0;
+ for (i = 0; i < 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;
}
/* GPE support */
- acpi_gbl_gpe_xrupt_list_head = NULL;
- acpi_gbl_gpe_fadt_blocks[0] = NULL;
- acpi_gbl_gpe_fadt_blocks[1] = NULL;
+ acpi_gbl_gpe_xrupt_list_head = NULL;
+ acpi_gbl_gpe_fadt_blocks[0] = NULL;
+ acpi_gbl_gpe_fadt_blocks[1] = NULL;
/* Global notify handlers */
- acpi_gbl_system_notify.handler = NULL;
- acpi_gbl_device_notify.handler = NULL;
- acpi_gbl_exception_handler = NULL;
- acpi_gbl_init_handler = NULL;
+ acpi_gbl_system_notify.handler = NULL;
+ acpi_gbl_device_notify.handler = NULL;
+ acpi_gbl_exception_handler = NULL;
+ acpi_gbl_init_handler = NULL;
/* Global "typed" ACPI table pointers */
- acpi_gbl_RSDP = NULL;
- acpi_gbl_XSDT = NULL;
- acpi_gbl_FACS = NULL;
- acpi_gbl_FADT = NULL;
- acpi_gbl_DSDT = NULL;
+ acpi_gbl_RSDP = NULL;
+ acpi_gbl_XSDT = NULL;
+ acpi_gbl_FACS = NULL;
+ acpi_gbl_FADT = NULL;
+ acpi_gbl_DSDT = NULL;
/* Global Lock support */
- acpi_gbl_global_lock_acquired = FALSE;
- acpi_gbl_global_lock_thread_count = 0;
- acpi_gbl_global_lock_handle = 0;
+ acpi_gbl_global_lock_acquired = FALSE;
+ acpi_gbl_global_lock_thread_count = 0;
+ acpi_gbl_global_lock_handle = 0;
/* Miscellaneous variables */
- acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
- acpi_gbl_rsdp_original_location = 0;
- acpi_gbl_cm_single_step = FALSE;
- acpi_gbl_db_terminate_threads = FALSE;
- acpi_gbl_shutdown = FALSE;
- acpi_gbl_ns_lookup_count = 0;
- acpi_gbl_ps_find_count = 0;
- acpi_gbl_acpi_hardware_present = TRUE;
- acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
- acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
- acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
- acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
+ acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
+ acpi_gbl_rsdp_original_location = 0;
+ acpi_gbl_cm_single_step = FALSE;
+ acpi_gbl_db_terminate_threads = FALSE;
+ acpi_gbl_shutdown = FALSE;
+ acpi_gbl_ns_lookup_count = 0;
+ acpi_gbl_ps_find_count = 0;
+ acpi_gbl_acpi_hardware_present = TRUE;
+ acpi_gbl_owner_id_mask = 0;
+ acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
+ acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
/* Hardware oriented */
- acpi_gbl_events_initialized = FALSE;
- acpi_gbl_system_awake_and_running = TRUE;
+ acpi_gbl_events_initialized = FALSE;
+ acpi_gbl_system_awake_and_running = TRUE;
/* Namespace */
- acpi_gbl_root_node = NULL;
+ 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.type = ACPI_TYPE_DEVICE;
- acpi_gbl_root_node_struct.child = NULL;
- acpi_gbl_root_node_struct.peer = NULL;
- acpi_gbl_root_node_struct.object = NULL;
- acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
-
+ acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
+ acpi_gbl_root_node_struct.child = NULL;
+ acpi_gbl_root_node_struct.peer = NULL;
+ acpi_gbl_root_node_struct.object = NULL;
+ acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
#ifdef ACPI_DEBUG_OUTPUT
- acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
+ acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
#endif
return_VOID;
}
-
-
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index 7f3713889ff0..9dde82b0beaf 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -41,25 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utinit")
+ACPI_MODULE_NAME("utinit")
/* Local prototypes */
-
static void
-acpi_ut_fadt_register_error (
- char *register_name,
- u32 value,
- acpi_size offset);
-
-static void acpi_ut_terminate (
- void);
+acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset);
+static void acpi_ut_terminate(void);
/*******************************************************************************
*
@@ -76,18 +69,14 @@ static void acpi_ut_terminate (
******************************************************************************/
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, acpi_size offset)
{
- ACPI_REPORT_WARNING (
- ("Invalid FADT value %s=%X at offset %X FADT=%p\n",
- register_name, value, (u32) offset, acpi_gbl_FADT));
+ ACPI_REPORT_WARNING(("Invalid FADT value %s=%X at offset %X FADT=%p\n",
+ register_name, value, (u32) offset,
+ acpi_gbl_FADT));
}
-
/******************************************************************************
*
* FUNCTION: acpi_ut_validate_fadt
@@ -100,9 +89,7 @@ acpi_ut_fadt_register_error (
*
******************************************************************************/
-acpi_status
-acpi_ut_validate_fadt (
- void)
+acpi_status acpi_ut_validate_fadt(void)
{
/*
@@ -110,64 +97,66 @@ acpi_ut_validate_fadt (
* but don't abort on any problems, just display error
*/
if (acpi_gbl_FADT->pm1_evt_len < 4) {
- acpi_ut_fadt_register_error ("PM1_EVT_LEN",
- (u32) acpi_gbl_FADT->pm1_evt_len,
- ACPI_FADT_OFFSET (pm1_evt_len));
+ acpi_ut_fadt_register_error("PM1_EVT_LEN",
+ (u32) acpi_gbl_FADT->pm1_evt_len,
+ ACPI_FADT_OFFSET(pm1_evt_len));
}
if (!acpi_gbl_FADT->pm1_cnt_len) {
- acpi_ut_fadt_register_error ("PM1_CNT_LEN", 0,
- ACPI_FADT_OFFSET (pm1_cnt_len));
+ acpi_ut_fadt_register_error("PM1_CNT_LEN", 0,
+ ACPI_FADT_OFFSET(pm1_cnt_len));
}
if (!acpi_gbl_FADT->xpm1a_evt_blk.address) {
- acpi_ut_fadt_register_error ("X_PM1a_EVT_BLK", 0,
- ACPI_FADT_OFFSET (xpm1a_evt_blk.address));
+ acpi_ut_fadt_register_error("X_PM1a_EVT_BLK", 0,
+ ACPI_FADT_OFFSET(xpm1a_evt_blk.
+ address));
}
if (!acpi_gbl_FADT->xpm1a_cnt_blk.address) {
- acpi_ut_fadt_register_error ("X_PM1a_CNT_BLK", 0,
- ACPI_FADT_OFFSET (xpm1a_cnt_blk.address));
+ acpi_ut_fadt_register_error("X_PM1a_CNT_BLK", 0,
+ ACPI_FADT_OFFSET(xpm1a_cnt_blk.
+ address));
}
if (!acpi_gbl_FADT->xpm_tmr_blk.address) {
- acpi_ut_fadt_register_error ("X_PM_TMR_BLK", 0,
- ACPI_FADT_OFFSET (xpm_tmr_blk.address));
+ acpi_ut_fadt_register_error("X_PM_TMR_BLK", 0,
+ ACPI_FADT_OFFSET(xpm_tmr_blk.
+ address));
}
if ((acpi_gbl_FADT->xpm2_cnt_blk.address &&
- !acpi_gbl_FADT->pm2_cnt_len)) {
- acpi_ut_fadt_register_error ("PM2_CNT_LEN",
- (u32) acpi_gbl_FADT->pm2_cnt_len,
- ACPI_FADT_OFFSET (pm2_cnt_len));
+ !acpi_gbl_FADT->pm2_cnt_len)) {
+ acpi_ut_fadt_register_error("PM2_CNT_LEN",
+ (u32) acpi_gbl_FADT->pm2_cnt_len,
+ ACPI_FADT_OFFSET(pm2_cnt_len));
}
if (acpi_gbl_FADT->pm_tm_len < 4) {
- acpi_ut_fadt_register_error ("PM_TM_LEN",
- (u32) acpi_gbl_FADT->pm_tm_len,
- ACPI_FADT_OFFSET (pm_tm_len));
+ acpi_ut_fadt_register_error("PM_TM_LEN",
+ (u32) acpi_gbl_FADT->pm_tm_len,
+ ACPI_FADT_OFFSET(pm_tm_len));
}
/* Length of GPE blocks must be a multiple of 2 */
if (acpi_gbl_FADT->xgpe0_blk.address &&
- (acpi_gbl_FADT->gpe0_blk_len & 1)) {
- acpi_ut_fadt_register_error ("(x)GPE0_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe0_blk_len,
- ACPI_FADT_OFFSET (gpe0_blk_len));
+ (acpi_gbl_FADT->gpe0_blk_len & 1)) {
+ acpi_ut_fadt_register_error("(x)GPE0_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe0_blk_len,
+ ACPI_FADT_OFFSET(gpe0_blk_len));
}
if (acpi_gbl_FADT->xgpe1_blk.address &&
- (acpi_gbl_FADT->gpe1_blk_len & 1)) {
- acpi_ut_fadt_register_error ("(x)GPE1_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe1_blk_len,
- ACPI_FADT_OFFSET (gpe1_blk_len));
+ (acpi_gbl_FADT->gpe1_blk_len & 1)) {
+ acpi_ut_fadt_register_error("(x)GPE1_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe1_blk_len,
+ ACPI_FADT_OFFSET(gpe1_blk_len));
}
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ut_terminate
@@ -180,18 +169,14 @@ acpi_ut_validate_fadt (
*
******************************************************************************/
-static void
-acpi_ut_terminate (
- void)
+static void acpi_ut_terminate(void)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_block_info *next_gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
-
-
- ACPI_FUNCTION_TRACE ("ut_terminate");
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_block_info *next_gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
+ ACPI_FUNCTION_TRACE("ut_terminate");
/* Free global tables, etc. */
/* Free global GPE blocks and related info structures */
@@ -201,21 +186,20 @@ acpi_ut_terminate (
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_MEM_FREE(gpe_block->event_info);
+ ACPI_MEM_FREE(gpe_block->register_info);
+ ACPI_MEM_FREE(gpe_block);
gpe_block = next_gpe_block;
}
next_gpe_xrupt_info = gpe_xrupt_info->next;
- ACPI_MEM_FREE (gpe_xrupt_info);
+ ACPI_MEM_FREE(gpe_xrupt_info);
gpe_xrupt_info = next_gpe_xrupt_info;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_subsystem_shutdown
@@ -229,50 +213,45 @@ acpi_ut_terminate (
*
******************************************************************************/
-void
-acpi_ut_subsystem_shutdown (
- 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 */
if (acpi_gbl_shutdown) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "ACPI Subsystem is already terminated\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "ACPI Subsystem is already terminated\n"));
return_VOID;
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Shutting down ACPI Subsystem...\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n"));
/* Close the acpi_event Handling */
- acpi_ev_terminate ();
+ acpi_ev_terminate();
/* Close the Namespace */
- acpi_ns_terminate ();
+ acpi_ns_terminate();
/* Close the globals */
- acpi_ut_terminate ();
+ acpi_ut_terminate();
/* Purge the local caches */
- (void) acpi_purge_cached_objects ();
+ (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);
+ 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 0d527c91543c..68a0a6f94129 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -41,19 +41,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utmath")
+ACPI_MODULE_NAME("utmath")
/*
* Support for double-precision integer divide. This code is included here
* in order to support kernel environments where the double-precision math
* library is not available.
*/
-
#ifndef ACPI_USE_NATIVE_DIVIDE
/*******************************************************************************
*
@@ -71,27 +68,22 @@
* 32-bit remainder.
*
******************************************************************************/
-
acpi_status
-acpi_ut_short_divide (
- acpi_integer dividend,
- u32 divisor,
- acpi_integer *out_quotient,
- u32 *out_remainder)
+acpi_ut_short_divide(acpi_integer dividend,
+ u32 divisor,
+ acpi_integer * out_quotient, u32 * out_remainder)
{
- union uint64_overlay dividend_ovl;
- union uint64_overlay quotient;
- u32 remainder32;
-
-
- ACPI_FUNCTION_TRACE ("ut_short_divide");
+ union uint64_overlay dividend_ovl;
+ union uint64_overlay quotient;
+ u32 remainder32;
+ ACPI_FUNCTION_TRACE("ut_short_divide");
/* Always check for a zero divisor */
if (divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
dividend_ovl.full = dividend;
@@ -100,9 +92,9 @@ acpi_ut_short_divide (
* The quotient is 64 bits, the remainder is always 32 bits,
* and is generated by the second divide.
*/
- ACPI_DIV_64_BY_32 (0, dividend_ovl.part.hi, divisor,
+ ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
quotient.part.hi, remainder32);
- ACPI_DIV_64_BY_32 (remainder32, dividend_ovl.part.lo, divisor,
+ ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
quotient.part.lo, remainder32);
/* Return only what was requested */
@@ -114,10 +106,9 @@ acpi_ut_short_divide (
*out_remainder = remainder32;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_divide
@@ -134,34 +125,30 @@ acpi_ut_short_divide (
******************************************************************************/
acpi_status
-acpi_ut_divide (
- acpi_integer in_dividend,
- acpi_integer in_divisor,
- acpi_integer *out_quotient,
- acpi_integer *out_remainder)
+acpi_ut_divide(acpi_integer in_dividend,
+ acpi_integer in_divisor,
+ acpi_integer * out_quotient, acpi_integer * out_remainder)
{
- union uint64_overlay dividend;
- union uint64_overlay divisor;
- union uint64_overlay quotient;
- union uint64_overlay remainder;
- union uint64_overlay normalized_dividend;
- union uint64_overlay normalized_divisor;
- u32 partial1;
- union uint64_overlay partial2;
- union uint64_overlay partial3;
-
-
- ACPI_FUNCTION_TRACE ("ut_divide");
-
+ union uint64_overlay dividend;
+ union uint64_overlay divisor;
+ union uint64_overlay quotient;
+ union uint64_overlay remainder;
+ union uint64_overlay normalized_dividend;
+ union uint64_overlay normalized_divisor;
+ u32 partial1;
+ union uint64_overlay partial2;
+ union uint64_overlay partial3;
+
+ ACPI_FUNCTION_TRACE("ut_divide");
/* Always check for a zero divisor */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
- divisor.full = in_divisor;
+ divisor.full = in_divisor;
dividend.full = in_dividend;
if (divisor.part.hi == 0) {
/*
@@ -174,9 +161,9 @@ acpi_ut_divide (
* The quotient is 64 bits, the remainder is always 32 bits,
* and is generated by the second divide.
*/
- ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor.part.lo,
+ ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
quotient.part.hi, partial1);
- ACPI_DIV_64_BY_32 (partial1, dividend.part.lo, divisor.part.lo,
+ ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
quotient.part.lo, remainder.part.lo);
}
@@ -185,23 +172,23 @@ acpi_ut_divide (
* 2) The general case where the divisor is a full 64 bits
* is more difficult
*/
- quotient.part.hi = 0;
+ quotient.part.hi = 0;
normalized_dividend = dividend;
normalized_divisor = divisor;
/* Normalize the operands (shift until the divisor is < 32 bits) */
do {
- ACPI_SHIFT_RIGHT_64 (normalized_divisor.part.hi,
- normalized_divisor.part.lo);
- ACPI_SHIFT_RIGHT_64 (normalized_dividend.part.hi,
- normalized_dividend.part.lo);
+ ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
+ normalized_divisor.part.lo);
+ ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
+ normalized_dividend.part.lo);
} while (normalized_divisor.part.hi != 0);
/* Partial divide */
- ACPI_DIV_64_BY_32 (normalized_dividend.part.hi,
+ ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
normalized_dividend.part.lo,
normalized_divisor.part.lo,
quotient.part.lo, partial1);
@@ -210,8 +197,9 @@ acpi_ut_divide (
* The quotient is always 32 bits, and simply requires adjustment.
* The 64-bit remainder must be generated.
*/
- partial1 = quotient.part.lo * divisor.part.hi;
- partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo;
+ partial1 = quotient.part.lo * divisor.part.hi;
+ partial2.full =
+ (acpi_integer) quotient.part.lo * divisor.part.lo;
partial3.full = (acpi_integer) partial2.part.hi + partial1;
remainder.part.hi = partial3.part.lo;
@@ -224,16 +212,15 @@ acpi_ut_divide (
quotient.part.lo--;
remainder.full -= divisor.full;
}
- }
- else {
+ } else {
quotient.part.lo--;
remainder.full -= divisor.full;
}
}
- remainder.full = remainder.full - dividend.full;
- remainder.part.hi = (u32) -((s32) remainder.part.hi);
- remainder.part.lo = (u32) -((s32) remainder.part.lo);
+ remainder.full = remainder.full - dividend.full;
+ remainder.part.hi = (u32) - ((s32) remainder.part.hi);
+ remainder.part.lo = (u32) - ((s32) remainder.part.lo);
if (remainder.part.lo) {
remainder.part.hi--;
@@ -250,11 +237,10 @@ acpi_ut_divide (
*out_remainder = remainder.full;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#else
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_short_divide, acpi_ut_divide
@@ -269,23 +255,19 @@ acpi_ut_divide (
* perform the divide.
*
******************************************************************************/
-
acpi_status
-acpi_ut_short_divide (
- acpi_integer in_dividend,
- u32 divisor,
- acpi_integer *out_quotient,
- u32 *out_remainder)
+acpi_ut_short_divide(acpi_integer in_dividend,
+ u32 divisor,
+ 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 */
if (divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
/* Return only what was requested */
@@ -297,27 +279,23 @@ acpi_ut_short_divide (
*out_remainder = (u32) in_dividend % divisor;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
acpi_status
-acpi_ut_divide (
- acpi_integer in_dividend,
- acpi_integer in_divisor,
- acpi_integer *out_quotient,
- acpi_integer *out_remainder)
+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 */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
-
/* Return only what was requested */
if (out_quotient) {
@@ -327,9 +305,7 @@ acpi_ut_divide (
*out_remainder = in_dividend % in_divisor;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
-
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index f6de4ed3d527..0c5abc536c7a 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -41,24 +41,130 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utmisc")
+ACPI_MODULE_NAME("utmisc")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_allocate_owner_id
+ *
+ * PARAMETERS: owner_id - Where the new owner ID is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
+ * track objects created by the table or method, to be deleted
+ * 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;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
+
+ /* Guard against multiple allocations of ID to the same location */
+
+ if (*owner_id) {
+ ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n",
+ *owner_id));
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ }
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
-/* Local prototypes */
+ /* Find a free owner ID */
-static acpi_status
-acpi_ut_create_mutex (
- acpi_mutex_handle mutex_id);
+ for (i = 0; i < 32; i++) {
+ if (!(acpi_gbl_owner_id_mask & (1 << i))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
+ "Current owner_id mask: %8.8X New ID: %2.2X\n",
+ acpi_gbl_owner_id_mask,
+ (unsigned int)(i + 1)));
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id);
+ acpi_gbl_owner_id_mask |= (1 << i);
+ *owner_id = (acpi_owner_id) (i + 1);
+ goto exit;
+ }
+ }
+ /*
+ * If we are here, all owner_ids have been allocated. This probably should
+ * not happen since the IDs are reused after deallocation. The IDs are
+ * allocated upon table load (one per table) and method execution, and
+ * they are released when a table is unloaded or a method completes
+ * execution.
+ */
+ *owner_id = 0;
+ status = AE_OWNER_ID_LIMIT;
+ ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
+
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_release_owner_id
+ *
+ * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD
+ *
+ * RETURN: None. No error is returned because we are either exiting a
+ * control method or unloading a table. Either way, we would
+ * ignore any error anyway.
+ *
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32
+ *
+ ******************************************************************************/
+
+void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
+{
+ acpi_owner_id owner_id = *owner_id_ptr;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
+
+ /* Always clear the input owner_id (zero is an invalid ID) */
+
+ *owner_id_ptr = 0;
+
+ /* Zero is not a valid owner_iD */
+
+ if ((owner_id == 0) || (owner_id > 32)) {
+ ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
+ return_VOID;
+ }
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
+ }
+
+ /* Normalize the ID to zero */
+
+ owner_id--;
+
+ /* Free the owner ID only if it is valid */
+
+ if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
+ acpi_gbl_owner_id_mask ^= (1 << owner_id);
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ return_VOID;
+}
/*******************************************************************************
*
@@ -66,7 +172,7 @@ acpi_ut_delete_mutex (
*
* PARAMETERS: src_string - The source string to convert
*
- * RETURN: Converted src_string (same as input pointer)
+ * RETURN: None
*
* DESCRIPTION: Convert string to uppercase
*
@@ -74,26 +180,25 @@ acpi_ut_delete_mutex (
*
******************************************************************************/
-char *
-acpi_ut_strupr (
- char *src_string)
+void acpi_ut_strupr(char *src_string)
{
- char *string;
-
+ char *string;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ if (!src_string) {
+ return;
+ }
/* Walk entire string, uppercasing the letters */
for (string = src_string; *string; string++) {
- *string = (char) ACPI_TOUPPER (*string);
+ *string = (char)ACPI_TOUPPER(*string);
}
- return (src_string);
+ return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_print_string
@@ -108,85 +213,77 @@ acpi_ut_strupr (
*
******************************************************************************/
-void
-acpi_ut_print_string (
- char *string,
- u8 max_length)
+void acpi_ut_print_string(char *string, u8 max_length)
{
- u32 i;
-
+ u32 i;
if (!string) {
- acpi_os_printf ("<\"NULL STRING PTR\">");
+ acpi_os_printf("<\"NULL STRING PTR\">");
return;
}
- acpi_os_printf ("\"");
+ acpi_os_printf("\"");
for (i = 0; string[i] && (i < max_length); i++) {
/* Escape sequences */
switch (string[i]) {
case 0x07:
- acpi_os_printf ("\\a"); /* BELL */
+ acpi_os_printf("\\a"); /* BELL */
break;
case 0x08:
- acpi_os_printf ("\\b"); /* BACKSPACE */
+ acpi_os_printf("\\b"); /* BACKSPACE */
break;
case 0x0C:
- acpi_os_printf ("\\f"); /* FORMFEED */
+ acpi_os_printf("\\f"); /* FORMFEED */
break;
case 0x0A:
- acpi_os_printf ("\\n"); /* LINEFEED */
+ acpi_os_printf("\\n"); /* LINEFEED */
break;
case 0x0D:
- acpi_os_printf ("\\r"); /* CARRIAGE RETURN*/
+ acpi_os_printf("\\r"); /* CARRIAGE RETURN */
break;
case 0x09:
- acpi_os_printf ("\\t"); /* HORIZONTAL TAB */
+ acpi_os_printf("\\t"); /* HORIZONTAL TAB */
break;
case 0x0B:
- acpi_os_printf ("\\v"); /* VERTICAL TAB */
+ acpi_os_printf("\\v"); /* VERTICAL TAB */
break;
- case '\'': /* Single Quote */
- case '\"': /* Double Quote */
- case '\\': /* Backslash */
- acpi_os_printf ("\\%c", (int) string[i]);
+ case '\'': /* Single Quote */
+ case '\"': /* Double Quote */
+ case '\\': /* Backslash */
+ acpi_os_printf("\\%c", (int)string[i]);
break;
default:
/* Check for printable character or hex escape */
- if (ACPI_IS_PRINT (string[i]))
- {
+ if (ACPI_IS_PRINT(string[i])) {
/* This is a normal character */
- acpi_os_printf ("%c", (int) string[i]);
- }
- else
- {
+ acpi_os_printf("%c", (int)string[i]);
+ } else {
/* All others will be Hex escapes */
- acpi_os_printf ("\\x%2.2X", (s32) string[i]);
+ acpi_os_printf("\\x%2.2X", (s32) string[i]);
}
break;
}
}
- acpi_os_printf ("\"");
+ acpi_os_printf("\"");
if (i == max_length && string[i]) {
- acpi_os_printf ("...");
+ acpi_os_printf("...");
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dword_byte_swap
@@ -199,22 +296,18 @@ acpi_ut_print_string (
*
******************************************************************************/
-u32
-acpi_ut_dword_byte_swap (
- u32 value)
+u32 acpi_ut_dword_byte_swap(u32 value)
{
union {
- u32 value;
- u8 bytes[4];
+ u32 value;
+ u8 bytes[4];
} out;
union {
- u32 value;
- u8 bytes[4];
+ u32 value;
+ u8 bytes[4];
} in;
-
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
in.value = value;
@@ -226,7 +319,6 @@ acpi_ut_dword_byte_swap (
return (out.value);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_set_integer_width
@@ -242,24 +334,20 @@ acpi_ut_dword_byte_swap (
*
******************************************************************************/
-void
-acpi_ut_set_integer_width (
- u8 revision)
+void acpi_ut_set_integer_width(u8 revision)
{
if (revision <= 1) {
acpi_gbl_integer_bit_width = 32;
acpi_gbl_integer_nybble_width = 8;
acpi_gbl_integer_byte_width = 4;
- }
- else {
+ } else {
acpi_gbl_integer_bit_width = 64;
acpi_gbl_integer_nybble_width = 16;
acpi_gbl_integer_byte_width = 8;
}
}
-
#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
*
@@ -277,17 +365,14 @@ acpi_ut_set_integer_width (
******************************************************************************/
void
-acpi_ut_display_init_pathname (
- u8 type,
- struct acpi_namespace_node *obj_handle,
- char *path)
+acpi_ut_display_init_pathname(u8 type,
+ struct acpi_namespace_node *obj_handle,
+ char *path)
{
- acpi_status status;
- struct acpi_buffer buffer;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ struct acpi_buffer buffer;
+ ACPI_FUNCTION_ENTRY();
/* Only print the path if the appropriate debug level is enabled */
@@ -298,8 +383,8 @@ acpi_ut_display_init_pathname (
/* Get the full pathname to the node */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_ns_handle_to_pathname (obj_handle, &buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_handle_to_pathname(obj_handle, &buffer);
+ if (ACPI_FAILURE(status)) {
return;
}
@@ -307,31 +392,30 @@ acpi_ut_display_init_pathname (
switch (type) {
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Executing ");
+ acpi_os_printf("Executing ");
break;
default:
- acpi_os_printf ("Initializing ");
+ acpi_os_printf("Initializing ");
break;
}
/* Print the object type and pathname */
- acpi_os_printf ("%-12s %s",
- acpi_ut_get_type_name (type), (char *) buffer.pointer);
+ acpi_os_printf("%-12s %s",
+ acpi_ut_get_type_name(type), (char *)buffer.pointer);
/* Extra path is used to append names like _STA, _INI, etc. */
if (path) {
- acpi_os_printf (".%s", path);
+ acpi_os_printf(".%s", path);
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
- ACPI_MEM_FREE (buffer.pointer);
+ ACPI_MEM_FREE(buffer.pointer);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_name
@@ -347,25 +431,21 @@ acpi_ut_display_init_pathname (
*
******************************************************************************/
-u8
-acpi_ut_valid_acpi_name (
- u32 name)
+u8 acpi_ut_valid_acpi_name(u32 name)
{
- char *name_ptr = (char *) &name;
- char character;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ 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'))) {
+ (character >= 'A' && character <= 'Z') ||
+ (character >= '0' && character <= '9'))) {
return (FALSE);
}
}
@@ -373,7 +453,6 @@ acpi_ut_valid_acpi_name (
return (TRUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_character
@@ -386,19 +465,16 @@ acpi_ut_valid_acpi_name (
*
******************************************************************************/
-u8
-acpi_ut_valid_acpi_character (
- char character)
+u8 acpi_ut_valid_acpi_character(char character)
{
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
- return ((u8) ((character == '_') ||
- (character >= 'A' && character <= 'Z') ||
- (character >= '0' && character <= '9')));
+ return ((u8) ((character == '_') ||
+ (character >= 'A' && character <= 'Z') ||
+ (character >= '0' && character <= '9')));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_strtoul64
@@ -415,18 +491,13 @@ acpi_ut_valid_acpi_character (
******************************************************************************/
acpi_status
-acpi_ut_strtoul64 (
- char *string,
- u32 base,
- acpi_integer *ret_integer)
+acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
{
- u32 this_digit = 0;
- acpi_integer return_value = 0;
- acpi_integer quotient;
-
-
- ACPI_FUNCTION_TRACE ("ut_stroul64");
+ u32 this_digit = 0;
+ acpi_integer return_value = 0;
+ acpi_integer quotient;
+ ACPI_FUNCTION_TRACE("ut_stroul64");
if ((!string) || !(*string)) {
goto error_exit;
@@ -440,12 +511,12 @@ acpi_ut_strtoul64 (
default:
/* Invalid Base */
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Skip over any white space in the buffer */
- while (ACPI_IS_SPACE (*string) || *string == '\t') {
+ while (ACPI_IS_SPACE(*string) || *string == '\t') {
string++;
}
@@ -454,12 +525,10 @@ acpi_ut_strtoul64 (
* determine if it is decimal or hexadecimal:
*/
if (base == 0) {
- if ((*string == '0') &&
- (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
base = 16;
string += 2;
- }
- else {
+ } else {
base = 10;
}
}
@@ -469,8 +538,7 @@ acpi_ut_strtoul64 (
* 0 or 0x, if they are present.
*/
if ((base == 16) &&
- (*string == '0') &&
- (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
string += 2;
}
@@ -483,25 +551,23 @@ acpi_ut_strtoul64 (
/* Main loop: convert the string to a 64-bit integer */
while (*string) {
- if (ACPI_IS_DIGIT (*string)) {
+ if (ACPI_IS_DIGIT(*string)) {
/* Convert ASCII 0-9 to Decimal value */
- this_digit = ((u8) *string) - '0';
- }
- else {
+ this_digit = ((u8) * string) - '0';
+ } else {
if (base == 10) {
/* Digit is out of range */
goto error_exit;
}
- this_digit = (u8) ACPI_TOUPPER (*string);
- if (ACPI_IS_XDIGIT ((char) this_digit)) {
+ 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 {
+ } else {
/*
* We allow non-hex chars, just stop now, same as end-of-string.
* See ACPI spec, string-to-integer conversion.
@@ -512,8 +578,10 @@ acpi_ut_strtoul64 (
/* Divide the digit into the correct position */
- (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit),
- base, &quotient, NULL);
+ (void)
+ acpi_ut_short_divide((ACPI_INTEGER_MAX -
+ (acpi_integer) this_digit), base,
+ &quotient, NULL);
if (return_value > quotient) {
goto error_exit;
}
@@ -526,335 +594,18 @@ acpi_ut_strtoul64 (
/* All done, normal exit */
*ret_integer = return_value;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
/* Base was set/validated above */
if (base == 10) {
- return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
- }
- else {
- return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_mutex_initialize
- *
- * PARAMETERS: None.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create the system mutex objects.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_mutex_initialize (
- void)
-{
- u32 i;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_initialize");
-
-
- /*
- * Create each of the predefined mutex objects
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- status = acpi_ut_create_mutex (i);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
- }
-
- status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_mutex_terminate
- *
- * PARAMETERS: None.
- *
- * RETURN: None.
- *
- * DESCRIPTION: Delete all of the system mutex objects.
- *
- ******************************************************************************/
-
-void
-acpi_ut_mutex_terminate (
- void)
-{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_terminate");
-
-
- /*
- * Delete each predefined mutex object
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- (void) acpi_ut_delete_mutex (i);
- }
-
- acpi_os_delete_lock (acpi_gbl_gpe_lock);
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be created
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a mutex object.
- *
- ******************************************************************************/
-
-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);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (!acpi_gbl_mutex_info[mutex_id].mutex) {
- status = acpi_os_create_semaphore (1, 1,
- &acpi_gbl_mutex_info[mutex_id].mutex);
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[mutex_id].use_count = 0;
- }
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be deleted
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete a mutex object.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex);
-
- acpi_gbl_mutex_info[mutex_id].mutex = NULL;
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_acquire_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be acquired
- *
- * RETURN: Status
- *
- * DESCRIPTION: Acquire a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_acquire_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 this_thread_id;
-
-
- ACPI_FUNCTION_NAME ("ut_acquire_mutex");
-
-
- if (mutex_id > MAX_MUTEX) {
- return (AE_BAD_PARAMETER);
- }
-
- this_thread_id = acpi_os_get_thread_id ();
-
-#ifdef ACPI_MUTEX_DEBUG
- {
- u32 i;
- /*
- * Mutex debug code, for internal debugging only.
- *
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than or equal to this one. If so, the thread has violated
- * the mutex ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] already acquired by this thread [%X]\n",
- acpi_ut_get_mutex_name (mutex_id), this_thread_id));
-
- return (AE_ALREADY_ACQUIRED);
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (i),
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_ACQUIRE_DEADLOCK);
- }
- }
- }
-#endif
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
- "Thread %X attempting to acquire Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex,
- 1, ACPI_WAIT_FOREVER);
- if (ACPI_SUCCESS (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- acpi_gbl_mutex_info[mutex_id].use_count++;
- acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not acquire Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
- }
-
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_release_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be released
- *
- * RETURN: Status
- *
- * DESCRIPTION: Release a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_release_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 i;
- u32 this_thread_id;
-
-
- 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) {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * Mutex must be acquired in order to release it!
- */
- if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] is not acquired, cannot release\n",
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_NOT_ACQUIRED);
- }
-
- /*
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than this one. If so, the thread has violated the mutex
- * ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- continue;
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid release order: owns [%s], releasing [%s]\n",
- acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_RELEASE_DEADLOCK);
- }
- }
-
- /* Mark unlocked FIRST */
-
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1);
-
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not release Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
+ return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
+ } else {
+ return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
}
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
- }
-
- return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_update_state_and_push
@@ -870,16 +621,13 @@ acpi_ut_release_mutex (
******************************************************************************/
acpi_status
-acpi_ut_create_update_state_and_push (
- union acpi_operand_object *object,
- u16 action,
- union acpi_generic_state **state_list)
+acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
+ u16 action,
+ union acpi_generic_state **state_list)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_ENTRY();
/* Ignore null objects; these are expected */
@@ -887,371 +635,15 @@ acpi_ut_create_update_state_and_push (
return (AE_OK);
}
- state = acpi_ut_create_update_state (object, action);
+ state = acpi_ut_create_update_state(object, action);
if (!state) {
return (AE_NO_MEMORY);
}
- acpi_ut_push_generic_state (state_list, state);
+ acpi_ut_push_generic_state(state_list, state);
return (AE_OK);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_pkg_state_and_push
- *
- * PARAMETERS: Object - Object to be added to the new state
- * Action - Increment/Decrement
- * state_list - List the state will be added to
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a new state and push it
- *
- ******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_ut_create_pkg_state_and_push (
- void *internal_object,
- void *external_object,
- u16 index,
- union acpi_generic_state **state_list)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_create_pkg_state (internal_object, external_object, index);
- if (!state) {
- return (AE_NO_MEMORY);
- }
-
- acpi_ut_push_generic_state (state_list, state);
- return (AE_OK);
-}
-#endif /* ACPI_FUTURE_USAGE */
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_push_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- * State - State object to push
- *
- * RETURN: None
- *
- * DESCRIPTION: Push a state object onto a state stack
- *
- ******************************************************************************/
-
-void
-acpi_ut_push_generic_state (
- union acpi_generic_state **list_head,
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_push_generic_state");
-
-
- /* Push the state object onto the front of the list (stack) */
-
- state->common.next = *list_head;
- *list_head = state;
-
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_pop_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- *
- * RETURN: The popped state object
- *
- * DESCRIPTION: Pop a state object from a state stack
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_pop_generic_state (
- union acpi_generic_state **list_head)
-{
- union acpi_generic_state *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;
- }
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_generic_state
- *
- * PARAMETERS: None
- *
- * RETURN: The new state object. NULL on failure.
- *
- * DESCRIPTION: Create a generic state object. Attempt to obtain one from
- * the global state cache; If none available, create a new one.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_generic_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_STATE);
-
- /* Initialize */
-
- if (state) {
- state->common.data_type = ACPI_DESC_TYPE_STATE;
- }
-
- return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_thread_state
- *
- * PARAMETERS: None
- *
- * RETURN: New Thread State. NULL on failure
- *
- * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
- * to track per-thread info during method execution
- *
- ******************************************************************************/
-
-struct acpi_thread_state *
-acpi_ut_create_thread_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_thread_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
- state->thread.thread_id = acpi_os_get_thread_id ();
-
- return_PTR ((struct acpi_thread_state *) state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_update_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
- * to update reference counts and delete complex objects such
- * as packages.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_update_state (
- union acpi_operand_object *object,
- u16 action)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
- state->update.object = object;
- state->update.value = action;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_pkg_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Package State"
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_pkg_state (
- void *internal_object,
- void *external_object,
- u16 index)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_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;
- state->pkg.num_packages = 1;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_control_state
- *
- * PARAMETERS: None
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
- * to support nested IF/WHILE constructs in the AML.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_control_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_control_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the control struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
- state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state
- *
- * PARAMETERS: State - The state object to be deleted
- *
- * RETURN: None
- *
- * DESCRIPTION: Put a state object back into the global state cache. The object
- * is not actually freed at this time.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state (
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state");
-
-
- acpi_ut_release_to_cache (ACPI_MEM_LIST_STATE, state);
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_STATE);
- return_VOID;
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_walk_package_tree
@@ -1268,33 +660,29 @@ acpi_ut_delete_generic_state_cache (
******************************************************************************/
acpi_status
-acpi_ut_walk_package_tree (
- union acpi_operand_object *source_object,
- void *target_object,
- acpi_pkg_callback walk_callback,
- void *context)
+acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
+ void *target_object,
+ acpi_pkg_callback walk_callback, void *context)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *state_list = NULL;
- union acpi_generic_state *state;
- u32 this_index;
- union acpi_operand_object *this_source_obj;
-
-
- ACPI_FUNCTION_TRACE ("ut_walk_package_tree");
+ acpi_status status = AE_OK;
+ union acpi_generic_state *state_list = NULL;
+ union acpi_generic_state *state;
+ u32 this_index;
+ union acpi_operand_object *this_source_obj;
+ ACPI_FUNCTION_TRACE("ut_walk_package_tree");
- state = acpi_ut_create_pkg_state (source_object, target_object, 0);
+ state = acpi_ut_create_pkg_state(source_object, target_object, 0);
if (!state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
while (state) {
/* Get one element of the package */
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
this_source_obj = (union acpi_operand_object *)
- state->pkg.source_object->package.elements[this_index];
+ state->pkg.source_object->package.elements[this_index];
/*
* Check for:
@@ -1305,16 +693,20 @@ acpi_ut_walk_package_tree (
* case below.
*/
if ((!this_source_obj) ||
- (ACPI_GET_DESCRIPTOR_TYPE (this_source_obj) != ACPI_DESC_TYPE_OPERAND) ||
- (ACPI_GET_OBJECT_TYPE (this_source_obj) != ACPI_TYPE_PACKAGE)) {
- status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj,
- state, context);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
+ ACPI_DESC_TYPE_OPERAND)
+ || (ACPI_GET_OBJECT_TYPE(this_source_obj) !=
+ ACPI_TYPE_PACKAGE)) {
+ status =
+ walk_callback(ACPI_COPY_TYPE_SIMPLE,
+ this_source_obj, state, context);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
state->pkg.index++;
- while (state->pkg.index >= state->pkg.source_object->package.count) {
+ while (state->pkg.index >=
+ state->pkg.source_object->package.count) {
/*
* We've handled all of the objects at this level, This means
* that we have just completed a package. That package may
@@ -1322,8 +714,8 @@ acpi_ut_walk_package_tree (
*
* Delete this state and pop the previous state (package).
*/
- acpi_ut_delete_generic_state (state);
- state = acpi_ut_pop_generic_state (&state_list);
+ acpi_ut_delete_generic_state(state);
+ state = acpi_ut_pop_generic_state(&state_list);
/* Finished when there are no more states */
@@ -1333,7 +725,7 @@ acpi_ut_walk_package_tree (
* package just add the length of the package objects
* and exit
*/
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -1342,35 +734,35 @@ acpi_ut_walk_package_tree (
*/
state->pkg.index++;
}
- }
- else {
+ } else {
/* This is a subobject of type package */
- status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj,
- state, context);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ walk_callback(ACPI_COPY_TYPE_PACKAGE,
+ this_source_obj, state, context);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Push the current state and create a new one
* The callback above returned a new target package object.
*/
- acpi_ut_push_generic_state (&state_list, state);
- state = acpi_ut_create_pkg_state (this_source_obj,
- state->pkg.this_target_obj, 0);
+ acpi_ut_push_generic_state(&state_list, state);
+ state = acpi_ut_create_pkg_state(this_source_obj,
+ state->pkg.
+ this_target_obj, 0);
if (!state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
}
}
/* We should never get here */
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_generate_checksum
@@ -1384,23 +776,18 @@ acpi_ut_walk_package_tree (
*
******************************************************************************/
-u8
-acpi_ut_generate_checksum (
- u8 *buffer,
- u32 length)
+u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
{
- u32 i;
- signed char sum = 0;
-
+ u32 i;
+ signed char sum = 0;
for (i = 0; i < length; i++) {
- sum = (signed char) (sum + buffer[i]);
+ sum = (signed char)(sum + buffer[i]);
}
return ((u8) (0 - sum));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_resource_end_tag
@@ -1413,17 +800,13 @@ acpi_ut_generate_checksum (
*
******************************************************************************/
-
-u8 *
-acpi_ut_get_resource_end_tag (
- union acpi_operand_object *obj_desc)
+u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
{
- u8 buffer_byte;
- u8 *buffer;
- u8 *end_buffer;
-
+ u8 buffer_byte;
+ u8 *buffer;
+ u8 *end_buffer;
- buffer = obj_desc->buffer.pointer;
+ buffer = obj_desc->buffer.pointer;
end_buffer = buffer + obj_desc->buffer.length;
while (buffer < end_buffer) {
@@ -1431,12 +814,12 @@ acpi_ut_get_resource_end_tag (
if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
/* Large Descriptor - Length is next 2 bytes */
- buffer += ((*(buffer+1) | (*(buffer+2) << 8)) + 3);
- }
- else {
+ buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
+ } else {
/* Small Descriptor. End Tag will be found here */
- if ((buffer_byte & ACPI_RDESC_SMALL_MASK) == ACPI_RDESC_TYPE_END_TAG) {
+ if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
+ ACPI_RDESC_TYPE_END_TAG) {
/* Found the end tag descriptor, all done. */
return (buffer);
@@ -1453,7 +836,6 @@ acpi_ut_get_resource_end_tag (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_error
@@ -1468,17 +850,12 @@ acpi_ut_get_resource_end_tag (
*
******************************************************************************/
-void
-acpi_ut_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_warning
@@ -1494,16 +871,12 @@ acpi_ut_report_error (
******************************************************************************/
void
-acpi_ut_report_warning (
- char *module_name,
- u32 line_number,
- u32 component_id)
+acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_info
@@ -1518,14 +891,8 @@ acpi_ut_report_warning (
*
******************************************************************************/
-void
-acpi_ut_report_info (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
}
-
-
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
new file mode 100644
index 000000000000..90134c56ece9
--- /dev/null
+++ b/drivers/acpi/utilities/utmutex.c
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ *
+ * Module Name: utmutex - local mutex support
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utmutex")
+
+/* Local prototypes */
+static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
+
+static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_mutex_initialize
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create the system mutex objects.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_mutex_initialize(void)
+{
+ u32 i;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ut_mutex_initialize");
+
+ /*
+ * Create each of the predefined mutex objects
+ */
+ for (i = 0; i < NUM_MUTEX; i++) {
+ status = acpi_ut_create_mutex(i);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ status = acpi_os_create_lock(&acpi_gbl_gpe_lock);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_mutex_terminate
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete all of the system mutex objects.
+ *
+ ******************************************************************************/
+
+void acpi_ut_mutex_terminate(void)
+{
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ut_mutex_terminate");
+
+ /*
+ * Delete each predefined mutex object
+ */
+ for (i = 0; i < NUM_MUTEX; i++) {
+ (void)acpi_ut_delete_mutex(i);
+ }
+
+ acpi_os_delete_lock(acpi_gbl_gpe_lock);
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be created
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a mutex object.
+ *
+ ******************************************************************************/
+
+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);
+
+ if (mutex_id > MAX_MUTEX) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ if (!acpi_gbl_mutex_info[mutex_id].mutex) {
+ status = acpi_os_create_semaphore(1, 1,
+ &acpi_gbl_mutex_info
+ [mutex_id].mutex);
+ acpi_gbl_mutex_info[mutex_id].thread_id =
+ ACPI_MUTEX_NOT_ACQUIRED;
+ acpi_gbl_mutex_info[mutex_id].use_count = 0;
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_delete_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be deleted
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete a mutex object.
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id);
+
+ if (mutex_id > MAX_MUTEX) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ status = acpi_os_delete_semaphore(acpi_gbl_mutex_info[mutex_id].mutex);
+
+ acpi_gbl_mutex_info[mutex_id].mutex = NULL;
+ acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_acquire_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be acquired
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Acquire a mutex object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+ u32 this_thread_id;
+
+ ACPI_FUNCTION_NAME("ut_acquire_mutex");
+
+ if (mutex_id > MAX_MUTEX) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ this_thread_id = acpi_os_get_thread_id();
+
+#ifdef ACPI_MUTEX_DEBUG
+ {
+ u32 i;
+ /*
+ * Mutex debug code, for internal debugging only.
+ *
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than or equal to this one. If so, the thread has violated
+ * the mutex ordering rule. This indicates a coding error somewhere in
+ * the ACPI subsystem code.
+ */
+ for (i = mutex_id; i < MAX_MUTEX; i++) {
+ if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (i == mutex_id) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Mutex [%s] already acquired by this thread [%X]\n",
+ acpi_ut_get_mutex_name
+ (mutex_id),
+ this_thread_id));
+
+ return (AE_ALREADY_ACQUIRED);
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name
+ (mutex_id)));
+
+ return (AE_ACQUIRE_DEADLOCK);
+ }
+ }
+ }
+#endif
+
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X attempting to acquire Mutex [%s]\n",
+ this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
+
+ status = acpi_os_wait_semaphore(acpi_gbl_mutex_info[mutex_id].mutex,
+ 1, ACPI_WAIT_FOREVER);
+ if (ACPI_SUCCESS(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X acquired Mutex [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
+
+ acpi_gbl_mutex_info[mutex_id].use_count++;
+ acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Thread %X could not acquire Mutex [%s] %s\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id),
+ acpi_format_exception(status)));
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_release_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be released
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Release a mutex object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+ u32 this_thread_id;
+
+ 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) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Mutex must be acquired in order to release it!
+ */
+ if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Mutex [%s] is not acquired, cannot release\n",
+ acpi_ut_get_mutex_name(mutex_id)));
+
+ return (AE_NOT_ACQUIRED);
+ }
+#ifdef ACPI_MUTEX_DEBUG
+ {
+ u32 i;
+ /*
+ * Mutex debug code, for internal debugging only.
+ *
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than this one. If so, the thread has violated the mutex
+ * ordering rule. This indicates a coding error somewhere in
+ * the ACPI subsystem code.
+ */
+ for (i = mutex_id; i < MAX_MUTEX; i++) {
+ if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (i == mutex_id) {
+ continue;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid release order: owns [%s], releasing [%s]\n",
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name
+ (mutex_id)));
+
+ return (AE_RELEASE_DEADLOCK);
+ }
+ }
+ }
+#endif
+
+ /* Mark unlocked FIRST */
+
+ acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+ status =
+ acpi_os_signal_semaphore(acpi_gbl_mutex_info[mutex_id].mutex, 1);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Thread %X could not release Mutex [%s] %s\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id),
+ acpi_format_exception(status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X released Mutex [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
+ }
+
+ return (status);
+}
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index cd3899b9cc5a..3015e1540053 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -41,34 +41,26 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utobject")
+ACPI_MODULE_NAME("utobject")
/* Local prototypes */
-
static acpi_status
-acpi_ut_get_simple_object_size (
- union acpi_operand_object *obj,
- acpi_size *obj_length);
+acpi_ut_get_simple_object_size(union acpi_operand_object *obj,
+ acpi_size * obj_length);
static acpi_status
-acpi_ut_get_package_object_size (
- union acpi_operand_object *obj,
- acpi_size *obj_length);
+acpi_ut_get_package_object_size(union acpi_operand_object *obj,
+ acpi_size * obj_length);
static acpi_status
-acpi_ut_get_element_length (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
-
+acpi_ut_get_element_length(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state, void *context);
/*******************************************************************************
*
@@ -91,26 +83,25 @@ acpi_ut_get_element_length (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_internal_object_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id,
- acpi_object_type type)
+union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ acpi_object_type
+ type)
{
- union acpi_operand_object *object;
- union acpi_operand_object *second_object;
-
-
- ACPI_FUNCTION_TRACE_STR ("ut_create_internal_object_dbg",
- acpi_ut_get_type_name (type));
+ union acpi_operand_object *object;
+ union acpi_operand_object *second_object;
+ ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg",
+ acpi_ut_get_type_name(type));
/* Allocate the raw object descriptor */
- object = acpi_ut_allocate_object_desc_dbg (module_name, line_number, component_id);
+ object =
+ acpi_ut_allocate_object_desc_dbg(module_name, line_number,
+ component_id);
if (!object) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
switch (type) {
@@ -119,11 +110,12 @@ acpi_ut_create_internal_object_dbg (
/* These types require a secondary object */
- second_object = acpi_ut_allocate_object_desc_dbg (module_name,
- line_number, component_id);
+ second_object = acpi_ut_allocate_object_desc_dbg(module_name,
+ line_number,
+ component_id);
if (!second_object) {
- acpi_ut_delete_object_desc (object);
- return_PTR (NULL);
+ acpi_ut_delete_object_desc(object);
+ return_PTR(NULL);
}
second_object->common.type = ACPI_TYPE_LOCAL_EXTRA;
@@ -149,10 +141,9 @@ acpi_ut_create_internal_object_dbg (
/* Any per-type initialization should go here */
- return_PTR (object);
+ return_PTR(object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_buffer_object
@@ -165,22 +156,18 @@ acpi_ut_create_internal_object_dbg (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_buffer_object (
- acpi_size buffer_size)
+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);
+ union acpi_operand_object *buffer_desc;
+ u8 *buffer = NULL;
+ ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size);
/* Create a new Buffer object */
- buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
if (!buffer_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Create an actual buffer only if size > 0 */
@@ -188,12 +175,11 @@ acpi_ut_create_buffer_object (
if (buffer_size > 0) {
/* Allocate the actual buffer */
- buffer = ACPI_MEM_CALLOCATE (buffer_size);
+ buffer = ACPI_MEM_CALLOCATE(buffer_size);
if (!buffer) {
- ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n",
- (u32) buffer_size));
- acpi_ut_remove_reference (buffer_desc);
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("create_buffer: could not allocate size %X\n", (u32) buffer_size));
+ acpi_ut_remove_reference(buffer_desc);
+ return_PTR(NULL);
}
}
@@ -205,10 +191,9 @@ acpi_ut_create_buffer_object (
/* Return the new buffer descriptor */
- return_PTR (buffer_desc);
+ return_PTR(buffer_desc);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_string_object
@@ -223,34 +208,29 @@ acpi_ut_create_buffer_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_string_object (
- acpi_size string_size)
+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);
+ union acpi_operand_object *string_desc;
+ char *string;
+ ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size);
/* Create a new String object */
- string_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
+ string_desc = acpi_ut_create_internal_object(ACPI_TYPE_STRING);
if (!string_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/*
* 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_MEM_CALLOCATE(string_size + 1);
if (!string) {
- ACPI_REPORT_ERROR (("create_string: could not allocate size %X\n",
- (u32) string_size));
- acpi_ut_remove_reference (string_desc);
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("create_string: could not allocate size %X\n", (u32) string_size));
+ acpi_ut_remove_reference(string_desc);
+ return_PTR(NULL);
}
/* Complete string object initialization */
@@ -260,10 +240,9 @@ acpi_ut_create_string_object (
/* Return the new string descriptor */
- return_PTR (string_desc);
+ return_PTR(string_desc);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_internal_object
@@ -276,24 +255,21 @@ acpi_ut_create_string_object (
*
******************************************************************************/
-u8
-acpi_ut_valid_internal_object (
- void *object)
+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 */
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Null Object Ptr\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n"));
return (FALSE);
}
/* Check the descriptor type field */
- switch (ACPI_GET_DESCRIPTOR_TYPE (object)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(object)) {
case ACPI_DESC_TYPE_OPERAND:
/* The object appears to be a valid union acpi_operand_object */
@@ -301,16 +277,15 @@ acpi_ut_valid_internal_object (
return (TRUE);
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "%p is not not an ACPI operand obj [%s]\n",
- object, acpi_ut_get_descriptor_name (object)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "%p is not not an ACPI operand obj [%s]\n",
+ object, acpi_ut_get_descriptor_name(object)));
break;
}
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_allocate_object_desc_dbg
@@ -326,37 +301,31 @@ acpi_ut_valid_internal_object (
*
******************************************************************************/
-void *
-acpi_ut_allocate_object_desc_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void *acpi_ut_allocate_object_desc_dbg(char *module_name,
+ u32 line_number, u32 component_id)
{
- union acpi_operand_object *object;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg");
- ACPI_FUNCTION_TRACE ("ut_allocate_object_desc_dbg");
-
-
- object = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_OPERAND);
+ object = acpi_os_acquire_object(acpi_gbl_operand_cache);
if (!object) {
- _ACPI_REPORT_ERROR (module_name, line_number, component_id,
- ("Could not allocate an object descriptor\n"));
+ _ACPI_REPORT_ERROR(module_name, line_number, component_id,
+ ("Could not allocate an object descriptor\n"));
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Mark the descriptor type */
+ memset(object, 0, sizeof(union acpi_operand_object));
+ ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
- ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
+ object, (u32) sizeof(union acpi_operand_object)));
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
- object, (u32) sizeof (union acpi_operand_object)));
-
- return_PTR (object);
+ return_PTR(object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_delete_object_desc
@@ -369,54 +338,22 @@ acpi_ut_allocate_object_desc_dbg (
*
******************************************************************************/
-void
-acpi_ut_delete_object_desc (
- union acpi_operand_object *object)
+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 */
- if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%p is not an ACPI Operand object [%s]\n", object,
- acpi_ut_get_descriptor_name (object)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p is not an ACPI Operand object [%s]\n",
+ object, acpi_ut_get_descriptor_name(object)));
return_VOID;
}
- acpi_ut_release_to_cache (ACPI_MEM_LIST_OPERAND, object);
-
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_object_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_object_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_object_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_OPERAND);
+ (void)acpi_os_release_object(acpi_gbl_operand_cache, object);
return_VOID;
}
-#endif
-
/*******************************************************************************
*
@@ -436,16 +373,13 @@ acpi_ut_delete_object_cache (
******************************************************************************/
static acpi_status
-acpi_ut_get_simple_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_size length;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_get_simple_object_size", internal_object);
+ acpi_size length;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object);
/*
* Handle a null object (Could be a uninitialized package
@@ -453,18 +387,18 @@ acpi_ut_get_simple_object_size (
*/
if (!internal_object) {
*obj_length = 0;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Start with the length of the Acpi object */
- length = sizeof (union acpi_object);
+ length = sizeof(union acpi_object);
- if (ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_NAMED) {
+ 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);
- return_ACPI_STATUS (status);
+ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
+ return_ACPI_STATUS(status);
}
/*
@@ -473,19 +407,17 @@ acpi_ut_get_simple_object_size (
* must be accessed bytewise or there may be alignment problems on
* certain processors
*/
- switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(internal_object)) {
case ACPI_TYPE_STRING:
length += (acpi_size) internal_object->string.length + 1;
break;
-
case ACPI_TYPE_BUFFER:
length += (acpi_size) internal_object->buffer.length;
break;
-
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_POWER:
@@ -495,7 +427,6 @@ acpi_ut_get_simple_object_size (
*/
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
switch (internal_object->reference.opcode) {
@@ -505,8 +436,10 @@ acpi_ut_get_simple_object_size (
* Get the actual length of the full pathname to this object.
* The reference will be converted to the pathname to the object
*/
- length += ACPI_ROUND_UP_TO_NATIVE_WORD (
- acpi_ns_get_pathname_length (internal_object->reference.node));
+ length +=
+ ACPI_ROUND_UP_TO_NATIVE_WORD
+ (acpi_ns_get_pathname_length
+ (internal_object->reference.node));
break;
default:
@@ -516,19 +449,21 @@ acpi_ut_get_simple_object_size (
* Notably, Locals and Args are not supported, but this may be
* required eventually.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported Reference opcode=%X in object %p\n",
- internal_object->reference.opcode, internal_object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported Reference opcode=%X in object %p\n",
+ internal_object->reference.opcode,
+ internal_object));
status = AE_TYPE;
break;
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported type=%X in object %p\n",
- ACPI_GET_OBJECT_TYPE (internal_object), internal_object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported type=%X in object %p\n",
+ ACPI_GET_OBJECT_TYPE(internal_object),
+ internal_object));
status = AE_TYPE;
break;
}
@@ -539,11 +474,10 @@ acpi_ut_get_simple_object_size (
* on a machine word boundary. (preventing alignment faults on some
* machines.)
*/
- *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD (length);
- return_ACPI_STATUS (status);
+ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_element_length
@@ -557,16 +491,13 @@ acpi_ut_get_simple_object_size (
******************************************************************************/
static acpi_status
-acpi_ut_get_element_length (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_get_element_length(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state, void *context)
{
- acpi_status status = AE_OK;
- struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
- acpi_size object_space;
-
+ acpi_status status = AE_OK;
+ struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
+ acpi_size object_space;
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -575,15 +506,16 @@ acpi_ut_get_element_length (
* Simple object - just get the size (Null object/entry is handled
* here also) and sum it into the running package length
*/
- status = acpi_ut_get_simple_object_size (source_object, &object_space);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_get_simple_object_size(source_object,
+ &object_space);
+ if (ACPI_FAILURE(status)) {
return (status);
}
info->length += object_space;
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/* Package object - nothing much to do here, let the walk handle it */
@@ -592,7 +524,6 @@ acpi_ut_get_element_length (
state->pkg.this_target_obj = NULL;
break;
-
default:
/* No other types allowed */
@@ -603,7 +534,6 @@ acpi_ut_get_element_length (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_package_object_size
@@ -622,25 +552,22 @@ acpi_ut_get_element_length (
******************************************************************************/
static acpi_status
-acpi_ut_get_package_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_status status;
- struct acpi_pkg_info info;
+ 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.length = 0;
info.object_space = 0;
info.num_packages = 1;
- status = acpi_ut_walk_package_tree (internal_object, NULL,
- acpi_ut_get_element_length, &info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_walk_package_tree(internal_object, NULL,
+ acpi_ut_get_element_length, &info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -648,16 +575,15 @@ acpi_ut_get_package_object_size (
* just add the length of the package objects themselves.
* Round up to the next machine word.
*/
- info.length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object)) *
- (acpi_size) info.num_packages;
+ info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
+ (acpi_size) info.num_packages;
/* Return the total package length */
*obj_length = info.length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_object_size
@@ -673,25 +599,23 @@ acpi_ut_get_package_object_size (
******************************************************************************/
acpi_status
-acpi_ut_get_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if ((ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (internal_object) == ACPI_TYPE_PACKAGE)) {
- status = acpi_ut_get_package_object_size (internal_object, obj_length);
- }
- else {
- status = acpi_ut_get_simple_object_size (internal_object, obj_length);
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) {
+ status =
+ acpi_ut_get_package_object_size(internal_object,
+ obj_length);
+ } else {
+ status =
+ acpi_ut_get_simple_object_size(internal_object, obj_length);
}
return (status);
}
-
-
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
new file mode 100644
index 000000000000..c1cb27583be8
--- /dev/null
+++ b/drivers/acpi/utilities/utstate.c
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ *
+ * Module Name: utstate - state object support procedures
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utstate")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_pkg_state_and_push
+ *
+ * PARAMETERS: Object - Object to be added to the new state
+ * Action - Increment/Decrement
+ * state_list - List the state will be added to
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a new state and push it
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ut_create_pkg_state_and_push(void *internal_object,
+ void *external_object,
+ u16 index,
+ union acpi_generic_state ** state_list)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_ENTRY();
+
+ state =
+ acpi_ut_create_pkg_state(internal_object, external_object, index);
+ if (!state) {
+ return (AE_NO_MEMORY);
+ }
+
+ acpi_ut_push_generic_state(state_list, state);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_push_generic_state
+ *
+ * PARAMETERS: list_head - Head of the state stack
+ * State - State object to push
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Push a state object onto a state stack
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_push_generic_state(union acpi_generic_state **list_head,
+ union acpi_generic_state *state)
+{
+ ACPI_FUNCTION_TRACE("ut_push_generic_state");
+
+ /* Push the state object onto the front of the list (stack) */
+
+ state->common.next = *list_head;
+ *list_head = state;
+
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_pop_generic_state
+ *
+ * PARAMETERS: list_head - Head of the state stack
+ *
+ * RETURN: The popped state object
+ *
+ * DESCRIPTION: Pop a state object from a state stack
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
+ **list_head)
+{
+ union acpi_generic_state *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;
+ }
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_generic_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: The new state object. NULL on failure.
+ *
+ * DESCRIPTION: Create a generic state object. Attempt to obtain one from
+ * the global state cache; If none available, create a new one.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_generic_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_ENTRY();
+
+ 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;
+ }
+
+ return (state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_thread_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: New Thread State. NULL on failure
+ *
+ * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
+ * to track per-thread info during method execution
+ *
+ ******************************************************************************/
+
+struct acpi_thread_state *acpi_ut_create_thread_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE("ut_create_thread_state");
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
+ state->thread.thread_id = acpi_os_get_thread_id();
+
+ return_PTR((struct acpi_thread_state *)state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_update_state
+ *
+ * PARAMETERS: Object - Initial Object to be installed in the state
+ * Action - Update action to be performed
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
+ * to update reference counts and delete complex objects such
+ * as packages.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
+ *object, u16 action)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object);
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
+ state->update.object = object;
+ state->update.value = action;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_pkg_state
+ *
+ * PARAMETERS: Object - Initial Object to be installed in the state
+ * Action - Update action to be performed
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create a "Package State"
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
+ void *external_object,
+ u16 index)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object);
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_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;
+ state->pkg.num_packages = 1;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_control_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
+ * to support nested IF/WHILE constructs in the AML.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_control_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE("ut_create_control_state");
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the control struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
+ state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_delete_generic_state
+ *
+ * PARAMETERS: State - The state object to be deleted
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Put a state object back into the global state cache. The object
+ * is not actually freed at this time.
+ *
+ ******************************************************************************/
+
+void acpi_ut_delete_generic_state(union acpi_generic_state *state)
+{
+ ACPI_FUNCTION_TRACE("ut_delete_generic_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 e8803d810656..f06bd5e5e9d1 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -46,13 +46,10 @@
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
#include <acpi/acdebug.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utxface")
-
+ACPI_MODULE_NAME("utxface")
/*******************************************************************************
*
@@ -66,61 +63,54 @@
* called, so any early initialization belongs here.
*
******************************************************************************/
-
-acpi_status
-acpi_initialize_subsystem (
- void)
+acpi_status acpi_initialize_subsystem(void)
{
- acpi_status status;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_initialize_subsystem");
- ACPI_FUNCTION_TRACE ("acpi_initialize_subsystem");
+ ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
+ /* Initialize the OS-Dependent layer */
- ACPI_DEBUG_EXEC (acpi_ut_init_stack_ptr_trace ());
-
+ status = acpi_os_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("OSD failed to initialize, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
+ }
/* Initialize all globals used by the subsystem */
- acpi_ut_init_globals ();
-
- /* Initialize the OS-Dependent layer */
-
- status = acpi_os_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("OSD failed to initialize, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
- }
+ acpi_ut_init_globals();
/* Create the default mutex objects */
- status = acpi_ut_mutex_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Global mutex creation failure, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ut_mutex_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Global mutex creation failure, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
* Initialize the namespace manager and
* the root of the namespace tree
*/
- status = acpi_ns_root_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Namespace initialization failure, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ns_root_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Namespace initialization failure, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* If configured, initialize the AML debugger */
- ACPI_DEBUGGER_EXEC (status = acpi_db_initialize ());
+ ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enable_subsystem
@@ -134,41 +124,39 @@ acpi_initialize_subsystem (
*
******************************************************************************/
-acpi_status
-acpi_enable_subsystem (
- u32 flags)
+acpi_status acpi_enable_subsystem(u32 flags)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enable_subsystem");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_enable_subsystem");
/*
* We must initialize the hardware before we can enable ACPI.
* The values from the FADT are validated here.
*/
if (!(flags & ACPI_NO_HARDWARE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI hardware\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI hardware\n"));
- status = acpi_hw_initialize ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_initialize();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Enable ACPI mode */
if (!(flags & ACPI_NO_ACPI_ENABLE)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Going into ACPI mode\n"));
acpi_gbl_original_mode = acpi_hw_get_mode();
- status = acpi_enable ();
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_enable failed.\n"));
- return_ACPI_STATUS (status);
+ status = acpi_enable();
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "acpi_enable failed.\n"));
+ return_ACPI_STATUS(status);
}
}
@@ -178,12 +166,12 @@ acpi_enable_subsystem (
* install_address_space_handler interface.
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Installing default address space handlers\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing default address space handlers\n"));
- status = acpi_ev_install_region_handlers ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_region_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -196,28 +184,28 @@ acpi_enable_subsystem (
* execution!
*/
if (!(flags & ACPI_NO_EVENT_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI events\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI events\n"));
- status = acpi_ev_initialize_events ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_initialize_events();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Install the SCI handler and Global Lock handler */
if (!(flags & ACPI_NO_HANDLER_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Installing SCI/GL handlers\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing SCI/GL handlers\n"));
- status = acpi_ev_install_xrupt_handlers ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_xrupt_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -233,15 +221,11 @@ acpi_enable_subsystem (
*
******************************************************************************/
-acpi_status
-acpi_initialize_objects (
- u32 flags)
+acpi_status acpi_initialize_objects(u32 flags)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_initialize_objects");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_initialize_objects");
/*
* Run all _REG methods
@@ -251,12 +235,12 @@ acpi_initialize_objects (
* contain executable AML (see call to acpi_ns_initialize_objects below).
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Executing _REG op_region methods\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Executing _REG op_region methods\n"));
- status = acpi_ev_initialize_op_regions ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_initialize_op_regions();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -266,12 +250,12 @@ acpi_initialize_objects (
* objects: operation_regions, buffer_fields, Buffers, and Packages.
*/
if (!(flags & ACPI_NO_OBJECT_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Completing Initialization of ACPI Objects\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Completing Initialization of ACPI Objects\n"));
- status = acpi_ns_initialize_objects ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_initialize_objects();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -280,12 +264,12 @@ acpi_initialize_objects (
* This runs the _STA and _INI methods.
*/
if (!(flags & ACPI_NO_DEVICE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI Devices\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI Devices\n"));
- status = acpi_ns_initialize_devices ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_initialize_devices();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -294,13 +278,12 @@ acpi_initialize_objects (
* the table load filled them up more than they will be at runtime --
* thus wasting non-paged memory.
*/
- status = acpi_purge_cached_objects ();
+ status = acpi_purge_cached_objects();
acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_terminate
@@ -313,15 +296,11 @@ acpi_initialize_objects (
*
******************************************************************************/
-acpi_status
-acpi_terminate (
- void)
+acpi_status acpi_terminate(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_terminate");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_terminate");
/* Terminate the AML Debugger if present */
@@ -329,28 +308,25 @@ acpi_terminate (
/* Shutdown and free all resources */
- acpi_ut_subsystem_shutdown ();
-
+ acpi_ut_subsystem_shutdown();
/* Free the mutex objects */
- acpi_ut_mutex_terminate ();
-
+ acpi_ut_mutex_terminate();
#ifdef ACPI_DEBUGGER
/* Shut down the debugger */
- acpi_db_terminate ();
+ acpi_db_terminate();
#endif
/* Now we can shutdown the OS-dependent layer */
- status = acpi_os_terminate ();
- return_ACPI_STATUS (status);
+ status = acpi_os_terminate();
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -366,20 +342,16 @@ acpi_terminate (
*
******************************************************************************/
-acpi_status
-acpi_subsystem_status (
- void)
+acpi_status acpi_subsystem_status(void)
{
if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) {
return (AE_OK);
- }
- else {
+ } else {
return (AE_ERROR);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_system_info
@@ -398,64 +370,60 @@ acpi_subsystem_status (
*
******************************************************************************/
-acpi_status
-acpi_get_system_info (
- struct acpi_buffer *out_buffer)
+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");
+ struct acpi_system_info *info_ptr;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("acpi_get_system_info");
/* Parameter validation */
- status = acpi_ut_validate_buffer (out_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(out_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (out_buffer, sizeof (struct acpi_system_info));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_initialize_buffer(out_buffer,
+ sizeof(struct acpi_system_info));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Populate the return buffer
*/
- info_ptr = (struct acpi_system_info *) out_buffer->pointer;
+ info_ptr = (struct acpi_system_info *)out_buffer->pointer;
- info_ptr->acpi_ca_version = ACPI_CA_VERSION;
+ info_ptr->acpi_ca_version = ACPI_CA_VERSION;
/* System flags (ACPI capabilities) */
- info_ptr->flags = ACPI_SYS_MODE_ACPI;
+ info_ptr->flags = ACPI_SYS_MODE_ACPI;
/* Timer resolution - 24 or 32 bits */
if (!acpi_gbl_FADT) {
info_ptr->timer_resolution = 0;
- }
- else if (acpi_gbl_FADT->tmr_val_ext == 0) {
+ } else if (acpi_gbl_FADT->tmr_val_ext == 0) {
info_ptr->timer_resolution = 24;
- }
- else {
+ } else {
info_ptr->timer_resolution = 32;
}
/* Clear the reserved fields */
- info_ptr->reserved1 = 0;
- info_ptr->reserved2 = 0;
+ info_ptr->reserved1 = 0;
+ info_ptr->reserved2 = 0;
/* Current debug levels */
- info_ptr->debug_layer = acpi_dbg_layer;
- info_ptr->debug_level = acpi_dbg_level;
+ info_ptr->debug_layer = acpi_dbg_layer;
+ info_ptr->debug_level = acpi_dbg_level;
/* Current status of the ACPI tables, per table type */
@@ -464,10 +432,10 @@ acpi_get_system_info (
info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_system_info);
+EXPORT_SYMBOL(acpi_get_system_info);
/*****************************************************************************
*
@@ -485,9 +453,7 @@ EXPORT_SYMBOL(acpi_get_system_info);
****************************************************************************/
acpi_status
-acpi_install_initialization_handler (
- acpi_init_handler handler,
- u32 function)
+acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
{
if (!handler) {
@@ -502,7 +468,7 @@ acpi_install_initialization_handler (
return AE_OK;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*****************************************************************************
*
@@ -516,19 +482,13 @@ acpi_install_initialization_handler (
*
****************************************************************************/
-acpi_status
-acpi_purge_cached_objects (
- void)
+acpi_status acpi_purge_cached_objects(void)
{
- ACPI_FUNCTION_TRACE ("acpi_purge_cached_objects");
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
- acpi_ut_delete_generic_state_cache ();
- acpi_ut_delete_object_cache ();
- acpi_ds_delete_walk_state_cache ();
- acpi_ps_delete_parse_cache ();
-#endif
+ ACPI_FUNCTION_TRACE("acpi_purge_cached_objects");
- return_ACPI_STATUS (AE_OK);
+ (void)acpi_os_purge_cache(acpi_gbl_state_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_operand_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 1ce2047c3804..6458c47f7ac2 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -30,15 +30,12 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("acpi_utils")
-
+ACPI_MODULE_NAME("acpi_utils")
/* --------------------------------------------------------------------------
Object Evaluation Helpers
-------------------------------------------------------------------------- */
-
#ifdef ACPI_DEBUG_OUTPUT
#define acpi_util_eval_error(h,p,s) {\
char prefix[80] = {'\0'};\
@@ -49,26 +46,24 @@ ACPI_MODULE_NAME ("acpi_utils")
#else
#define acpi_util_eval_error(h,p,s)
#endif
-
-
acpi_status
-acpi_extract_package (
- union acpi_object *package,
- struct acpi_buffer *format,
- struct acpi_buffer *buffer)
+acpi_extract_package(union acpi_object *package,
+ struct acpi_buffer *format, struct acpi_buffer *buffer)
{
- u32 size_required = 0;
- u32 tail_offset = 0;
- char *format_string = NULL;
- u32 format_count = 0;
- u32 i = 0;
- u8 *head = NULL;
- u8 *tail = NULL;
+ u32 size_required = 0;
+ u32 tail_offset = 0;
+ char *format_string = NULL;
+ u32 format_count = 0;
+ u32 i = 0;
+ u8 *head = NULL;
+ u8 *tail = NULL;
ACPI_FUNCTION_TRACE("acpi_extract_package");
- if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n"));
+ if (!package || (package->type != ACPI_TYPE_PACKAGE)
+ || (package->package.count < 1)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid 'package' argument\n"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -82,18 +77,20 @@ acpi_extract_package (
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- format_count = (format->length/sizeof(char)) - 1;
+ format_count = (format->length / sizeof(char)) - 1;
if (format_count > package->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Format specifies more objects [%d] than exist in package [%d].",
+ format_count, package->package.count));
return_ACPI_STATUS(AE_BAD_DATA);
}
- format_string = (char*)format->pointer;
+ format_string = (char *)format->pointer;
/*
* Calculate size_required.
*/
- for (i=0; i<format_count; i++) {
+ for (i = 0; i < format_count; i++) {
union acpi_object *element = &(package->package.elements[i]);
@@ -110,11 +107,15 @@ acpi_extract_package (
tail_offset += sizeof(acpi_integer);
break;
case 'S':
- size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char);
- tail_offset += sizeof(char*);
+ size_required +=
+ sizeof(char *) + sizeof(acpi_integer) +
+ sizeof(char);
+ tail_offset += sizeof(char *);
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid package element [%d]: got number, expecing [%c].\n",
+ i, format_string[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
@@ -124,15 +125,22 @@ acpi_extract_package (
case ACPI_TYPE_BUFFER:
switch (format_string[i]) {
case 'S':
- size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char);
- tail_offset += sizeof(char*);
+ size_required +=
+ sizeof(char *) +
+ (element->string.length * sizeof(char)) +
+ sizeof(char);
+ tail_offset += sizeof(char *);
break;
case 'B':
- size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8));
- tail_offset += sizeof(u8*);
+ size_required +=
+ sizeof(u8 *) +
+ (element->buffer.length * sizeof(u8));
+ tail_offset += sizeof(u8 *);
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid package element [%d] got string/buffer, expecing [%c].\n",
+ i, format_string[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
@@ -140,7 +148,9 @@ acpi_extract_package (
case ACPI_TYPE_PACKAGE:
default:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found unsupported element at index=%d\n",
+ i));
/* TBD: handle nested packages... */
return_ACPI_STATUS(AE_SUPPORT);
break;
@@ -153,8 +163,7 @@ acpi_extract_package (
if (buffer->length < size_required) {
buffer->length = size_required;
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
- }
- else if (buffer->length != size_required || !buffer->pointer) {
+ } else if (buffer->length != size_required || !buffer->pointer) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -164,7 +173,7 @@ acpi_extract_package (
/*
* Extract package data.
*/
- for (i=0; i<format_count; i++) {
+ for (i = 0; i < format_count; i++) {
u8 **pointer = NULL;
union acpi_object *element = &(package->package.elements[i]);
@@ -178,14 +187,16 @@ acpi_extract_package (
case ACPI_TYPE_INTEGER:
switch (format_string[i]) {
case 'N':
- *((acpi_integer*)head) = element->integer.value;
+ *((acpi_integer *) head) =
+ element->integer.value;
head += sizeof(acpi_integer);
break;
case 'S':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- *((acpi_integer*)tail) = element->integer.value;
- head += sizeof(acpi_integer*);
+ *((acpi_integer *) tail) =
+ element->integer.value;
+ head += sizeof(acpi_integer *);
tail += sizeof(acpi_integer);
/* NULL terminate string */
*tail = (char)0;
@@ -201,20 +212,22 @@ acpi_extract_package (
case ACPI_TYPE_BUFFER:
switch (format_string[i]) {
case 'S':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- memcpy(tail, element->string.pointer, element->string.length);
- head += sizeof(char*);
+ memcpy(tail, element->string.pointer,
+ element->string.length);
+ head += sizeof(char *);
tail += element->string.length * sizeof(char);
/* NULL terminate string */
*tail = (char)0;
tail += sizeof(char);
break;
case 'B':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- memcpy(tail, element->buffer.pointer, element->buffer.length);
- head += sizeof(u8*);
+ memcpy(tail, element->buffer.pointer,
+ element->buffer.length);
+ head += sizeof(u8 *);
tail += element->buffer.length * sizeof(u8);
break;
default:
@@ -233,19 +246,17 @@ acpi_extract_package (
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_extract_package);
+EXPORT_SYMBOL(acpi_extract_package);
acpi_status
-acpi_evaluate_integer (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- unsigned long *data)
+acpi_evaluate_integer(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments, unsigned long *data)
{
- acpi_status status = AE_OK;
- union acpi_object *element;
- struct acpi_buffer buffer = {0,NULL};
+ acpi_status status = AE_OK;
+ union acpi_object *element;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
@@ -253,7 +264,7 @@ acpi_evaluate_integer (
return_ACPI_STATUS(AE_BAD_PARAMETER);
element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if(!element)
+ if (!element)
return_ACPI_STATUS(AE_NO_MEMORY);
memset(element, 0, sizeof(union acpi_object));
@@ -277,20 +288,18 @@ acpi_evaluate_integer (
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_evaluate_integer);
+EXPORT_SYMBOL(acpi_evaluate_integer);
#if 0
acpi_status
-acpi_evaluate_string (
- acpi_handle handle,
- acpi_string pathname,
- acpi_object_list *arguments,
- acpi_string *data)
+acpi_evaluate_string(acpi_handle handle,
+ acpi_string pathname,
+ acpi_object_list * arguments, acpi_string * data)
{
- acpi_status status = AE_OK;
- acpi_object *element = NULL;
- acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_status status = AE_OK;
+ acpi_object *element = NULL;
+ acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
ACPI_FUNCTION_TRACE("acpi_evaluate_string");
@@ -305,9 +314,9 @@ acpi_evaluate_string (
element = (acpi_object *) buffer.pointer;
- if ((element->type != ACPI_TYPE_STRING)
- || (element->type != ACPI_TYPE_BUFFER)
- || !element->string.length) {
+ if ((element->type != ACPI_TYPE_STRING)
+ || (element->type != ACPI_TYPE_BUFFER)
+ || !element->string.length) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
return_ACPI_STATUS(AE_BAD_DATA);
}
@@ -329,19 +338,17 @@ acpi_evaluate_string (
}
#endif
-
acpi_status
-acpi_evaluate_reference (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- struct acpi_handle_list *list)
+acpi_evaluate_reference(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments,
+ struct acpi_handle_list *list)
{
- acpi_status status = AE_OK;
- union acpi_object *package = NULL;
- union acpi_object *element = NULL;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- u32 i = 0;
+ acpi_status status = AE_OK;
+ union acpi_object *package = NULL;
+ union acpi_object *element = NULL;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
@@ -355,28 +362,28 @@ acpi_evaluate_reference (
if (ACPI_FAILURE(status))
goto end;
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
if ((buffer.length == 0) || !package) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No return object (len %X ptr %p)\n",
- (unsigned)buffer.length, package));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No return object (len %X ptr %p)\n",
+ (unsigned)buffer.length, package));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
}
if (package->type != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Expecting a [Package], found type %X\n",
- package->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting a [Package], found type %X\n",
+ package->type));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
}
if (!package->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "[Package] has zero elements (%p)\n",
- package));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "[Package] has zero elements (%p)\n",
+ package));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
@@ -395,9 +402,9 @@ acpi_evaluate_reference (
if (element->type != ACPI_TYPE_ANY) {
status = AE_BAD_DATA;
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Expecting a [Reference] package element, found type %X\n",
- element->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting a [Reference] package element, found type %X\n",
+ element->type));
acpi_util_eval_error(handle, pathname, status);
break;
}
@@ -406,10 +413,10 @@ acpi_evaluate_reference (
list->handles[i] = element->reference.handle;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
- list->handles[i]));
+ list->handles[i]));
}
-end:
+ end:
if (ACPI_FAILURE(status)) {
list->count = 0;
//kfree(list->handles);
@@ -419,5 +426,5 @@ end:
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_evaluate_reference);
+EXPORT_SYMBOL(acpi_evaluate_reference);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 2cf264fd52e0..e383d6109ae1 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -53,21 +53,20 @@
#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
-
#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
#define ACPI_VIDEO_HEAD_END (~0u)
-
#define _COMPONENT ACPI_VIDEO_COMPONENT
-ACPI_MODULE_NAME ("acpi_video")
+ACPI_MODULE_NAME("acpi_video")
-MODULE_AUTHOR("Bruno Ducrot");
+ MODULE_AUTHOR("Bruno Ducrot");
MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_video_bus_add (struct acpi_device *device);
-static int acpi_video_bus_remove (struct acpi_device *device, int type);
-static int acpi_video_bus_match (struct acpi_device *device, struct acpi_driver *driver);
+static int acpi_video_bus_add(struct acpi_device *device);
+static int acpi_video_bus_remove(struct acpi_device *device, int type);
+static int acpi_video_bus_match(struct acpi_device *device,
+ struct acpi_driver *driver);
static struct acpi_driver acpi_video_bus = {
.name = ACPI_VIDEO_DRIVER_NAME,
@@ -76,187 +75,192 @@ static struct acpi_driver acpi_video_bus = {
.add = acpi_video_bus_add,
.remove = acpi_video_bus_remove,
.match = acpi_video_bus_match,
- },
+ },
};
struct acpi_video_bus_flags {
- u8 multihead:1; /* can switch video heads */
- u8 rom:1; /* can retrieve a video rom */
- u8 post:1; /* can configure the head to */
- u8 reserved:5;
+ u8 multihead:1; /* can switch video heads */
+ u8 rom:1; /* can retrieve a video rom */
+ u8 post:1; /* can configure the head to */
+ u8 reserved:5;
};
struct acpi_video_bus_cap {
- u8 _DOS:1; /*Enable/Disable output switching*/
- u8 _DOD:1; /*Enumerate all devices attached to display adapter*/
- u8 _ROM:1; /*Get ROM Data*/
- u8 _GPD:1; /*Get POST Device*/
- u8 _SPD:1; /*Set POST Device*/
- u8 _VPO:1; /*Video POST Options*/
- u8 reserved:2;
+ u8 _DOS:1; /*Enable/Disable output switching */
+ u8 _DOD:1; /*Enumerate all devices attached to display adapter */
+ u8 _ROM:1; /*Get ROM Data */
+ u8 _GPD:1; /*Get POST Device */
+ u8 _SPD:1; /*Set POST Device */
+ u8 _VPO:1; /*Video POST Options */
+ u8 reserved:2;
};
-struct acpi_video_device_attrib{
- u32 display_index:4; /* A zero-based instance of the Display*/
- u32 display_port_attachment:4; /*This field differenates displays type*/
- u32 display_type:4; /*Describe the specific type in use*/
- u32 vendor_specific:4; /*Chipset Vendor Specifi*/
- u32 bios_can_detect:1; /*BIOS can detect the device*/
- u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
- the VGA device.*/
- u32 pipe_id:3; /*For VGA multiple-head devices.*/
- u32 reserved:10; /*Must be 0*/
- u32 device_id_scheme:1; /*Device ID Scheme*/
+struct acpi_video_device_attrib {
+ u32 display_index:4; /* A zero-based instance of the Display */
+ u32 display_port_attachment:4; /*This field differenates displays type */
+ u32 display_type:4; /*Describe the specific type in use */
+ u32 vendor_specific:4; /*Chipset Vendor Specifi */
+ u32 bios_can_detect:1; /*BIOS can detect the device */
+ u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
+ the VGA device. */
+ u32 pipe_id:3; /*For VGA multiple-head devices. */
+ u32 reserved:10; /*Must be 0 */
+ u32 device_id_scheme:1; /*Device ID Scheme */
};
struct acpi_video_enumerated_device {
union {
u32 int_val;
- struct acpi_video_device_attrib attrib;
+ struct acpi_video_device_attrib attrib;
} value;
struct acpi_video_device *bind_info;
};
struct acpi_video_bus {
- acpi_handle handle;
- u8 dos_setting;
+ acpi_handle handle;
+ u8 dos_setting;
struct acpi_video_enumerated_device *attached_array;
- u8 attached_count;
- struct acpi_video_bus_cap cap;
+ u8 attached_count;
+ struct acpi_video_bus_cap cap;
struct acpi_video_bus_flags flags;
- struct semaphore sem;
- struct list_head video_device_list;
- struct proc_dir_entry *dir;
+ struct semaphore sem;
+ struct list_head video_device_list;
+ struct proc_dir_entry *dir;
};
struct acpi_video_device_flags {
- u8 crt:1;
- u8 lcd:1;
- u8 tvout:1;
- u8 bios:1;
- u8 unknown:1;
- u8 reserved:3;
+ u8 crt:1;
+ u8 lcd:1;
+ u8 tvout:1;
+ u8 bios:1;
+ u8 unknown:1;
+ u8 reserved:3;
};
struct acpi_video_device_cap {
- u8 _ADR:1; /*Return the unique ID */
- u8 _BCL:1; /*Query list of brightness control levels supported*/
- u8 _BCM:1; /*Set the brightness level*/
- u8 _DDC:1; /*Return the EDID for this device*/
- u8 _DCS:1; /*Return status of output device*/
- u8 _DGS:1; /*Query graphics state*/
- u8 _DSS:1; /*Device state set*/
- u8 _reserved:1;
+ u8 _ADR:1; /*Return the unique ID */
+ u8 _BCL:1; /*Query list of brightness control levels supported */
+ u8 _BCM:1; /*Set the brightness level */
+ u8 _DDC:1; /*Return the EDID for this device */
+ u8 _DCS:1; /*Return status of output device */
+ u8 _DGS:1; /*Query graphics state */
+ u8 _DSS:1; /*Device state set */
+ u8 _reserved:1;
};
struct acpi_video_device_brightness {
- int curr;
- int count;
- int *levels;
+ int curr;
+ int count;
+ int *levels;
};
struct acpi_video_device {
- acpi_handle handle;
- unsigned long device_id;
- struct acpi_video_device_flags flags;
- struct acpi_video_device_cap cap;
- struct list_head entry;
- struct acpi_video_bus *video;
- struct acpi_device *dev;
+ acpi_handle handle;
+ unsigned long device_id;
+ struct acpi_video_device_flags flags;
+ struct acpi_video_device_cap cap;
+ struct list_head entry;
+ struct acpi_video_bus *video;
+ struct acpi_device *dev;
struct acpi_video_device_brightness *brightness;
};
-
/* bus */
static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_info_fops = {
- .open = acpi_video_bus_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_ROM_fops = {
- .open = acpi_video_bus_ROM_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_ROM_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_bus_POST_info_fops = {
- .open = acpi_video_bus_POST_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_POST_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_POST_fops = {
- .open = acpi_video_bus_POST_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_POST_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_DOS_fops = {
- .open = acpi_video_bus_DOS_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_DOS_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* device */
-static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_info_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_info_fops = {
- .open = acpi_video_device_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_state_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_state_fops = {
- .open = acpi_video_device_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_brightness_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_brightness_fops = {
- .open = acpi_video_device_brightness_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_brightness_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_EDID_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_EDID_fops = {
- .open = acpi_video_device_EDID_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_EDID_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static char device_decode[][30] = {
+static char device_decode[][30] = {
"motherboard VGA device",
"PCI VGA device",
"AGP VGA device",
"UNKNOWN",
};
-static void acpi_video_device_notify ( acpi_handle handle, u32 event, void *data);
-static void acpi_video_device_rebind( struct acpi_video_bus *video);
-static void acpi_video_device_bind( struct acpi_video_bus *video, struct acpi_video_device *device);
+static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
+static void acpi_video_device_rebind(struct acpi_video_bus *video);
+static void acpi_video_device_bind(struct acpi_video_bus *video,
+ struct acpi_video_device *device);
static int acpi_video_device_enumerate(struct acpi_video_bus *video);
-static int acpi_video_switch_output( struct acpi_video_bus *video, int event);
-static int acpi_video_get_next_level( struct acpi_video_device *device, u32 level_current,u32 event);
-static void acpi_video_switch_brightness ( struct acpi_video_device *device, int event);
-
+static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
+static int acpi_video_get_next_level(struct acpi_video_device *device,
+ u32 level_current, u32 event);
+static void acpi_video_switch_brightness(struct acpi_video_device *device,
+ int event);
/* --------------------------------------------------------------------------
Video Management
@@ -265,11 +269,9 @@ static void acpi_video_switch_brightness ( struct acpi_video_device *device, int
/* device */
static int
-acpi_video_device_query (
- struct acpi_video_device *device,
- unsigned long *state)
+acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_query");
status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
@@ -277,11 +279,10 @@ acpi_video_device_query (
}
static int
-acpi_video_device_get_state (
- struct acpi_video_device *device,
- unsigned long *state)
+acpi_video_device_get_state(struct acpi_video_device *device,
+ unsigned long *state)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_get_state");
@@ -291,31 +292,28 @@ acpi_video_device_get_state (
}
static int
-acpi_video_device_set_state (
- struct acpi_video_device *device,
- int state)
+acpi_video_device_set_state(struct acpi_video_device *device, int state)
{
- int status;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
+ unsigned long ret;
ACPI_FUNCTION_TRACE("acpi_video_device_set_state");
arg0.integer.value = state;
- status = acpi_evaluate_integer(device->handle, "_DSS", &args, NULL);
+ status = acpi_evaluate_integer(device->handle, "_DSS", &args, &ret);
return_VALUE(status);
}
static int
-acpi_video_device_lcd_query_levels (
- struct acpi_video_device *device,
- union acpi_object **levels)
+acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
+ union acpi_object **levels)
{
- int status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *obj;
-
+ int status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_query_levels");
@@ -324,7 +322,7 @@ acpi_video_device_lcd_query_levels (
status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
if (!ACPI_SUCCESS(status))
return_VALUE(status);
- obj = (union acpi_object *) buffer.pointer;
+ obj = (union acpi_object *)buffer.pointer;
if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
status = -EFAULT;
@@ -335,7 +333,7 @@ acpi_video_device_lcd_query_levels (
return_VALUE(0);
-err:
+ err:
if (buffer.pointer)
kfree(buffer.pointer);
@@ -343,13 +341,11 @@ err:
}
static int
-acpi_video_device_lcd_set_level (
- struct acpi_video_device *device,
- int level)
+acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
{
- int status;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_set_level");
@@ -361,11 +357,10 @@ acpi_video_device_lcd_set_level (
}
static int
-acpi_video_device_lcd_get_level_current (
- struct acpi_video_device *device,
- unsigned long *level)
+acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
+ unsigned long *level)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_get_level_current");
status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
@@ -374,16 +369,14 @@ acpi_video_device_lcd_get_level_current (
}
static int
-acpi_video_device_EDID (
- struct acpi_video_device *device,
- union acpi_object **edid,
- ssize_t length)
+acpi_video_device_EDID(struct acpi_video_device *device,
+ union acpi_object **edid, ssize_t length)
{
- int status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *obj;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_device_get_EDID");
@@ -402,7 +395,7 @@ acpi_video_device_EDID (
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- obj = (union acpi_object *) buffer.pointer;
+ obj = (union acpi_object *)buffer.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER)
*edid = obj;
@@ -415,18 +408,15 @@ acpi_video_device_EDID (
return_VALUE(status);
}
-
/* bus */
static int
-acpi_video_bus_set_POST (
- struct acpi_video_bus *video,
- unsigned long option)
+acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
{
- int status;
- unsigned long tmp;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ unsigned long tmp;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_bus_set_POST");
@@ -434,15 +424,13 @@ acpi_video_bus_set_POST (
status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
if (ACPI_SUCCESS(status))
- status = tmp ? (-EINVAL):(AE_OK);
+ status = tmp ? (-EINVAL) : (AE_OK);
return_VALUE(status);
}
static int
-acpi_video_bus_get_POST (
- struct acpi_video_bus *video,
- unsigned long *id)
+acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
{
int status;
@@ -454,11 +442,10 @@ acpi_video_bus_get_POST (
}
static int
-acpi_video_bus_POST_options (
- struct acpi_video_bus *video,
- unsigned long *options)
+acpi_video_bus_POST_options(struct acpi_video_bus *video,
+ unsigned long *options)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_options");
status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
@@ -489,18 +476,15 @@ acpi_video_bus_POST_options (
*/
static int
-acpi_video_bus_DOS(
- struct acpi_video_bus *video,
- int bios_flag,
- int lcd_flag)
+acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
{
- acpi_integer status = 0;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ acpi_integer status = 0;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_bus_DOS");
- if (bios_flag < 0 || bios_flag >3 || lcd_flag < 0 || lcd_flag > 1){
+ if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
status = -1;
goto Failed;
}
@@ -508,7 +492,7 @@ acpi_video_bus_DOS(
video->dos_setting = arg0.integer.value;
acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
-Failed:
+ Failed:
return_VALUE(status);
}
@@ -523,10 +507,9 @@ Failed:
* device.
*/
-static void
-acpi_video_device_find_cap (struct acpi_video_device *device)
+static void acpi_video_device_find_cap(struct acpi_video_device *device)
{
- acpi_integer status;
+ acpi_integer status;
acpi_handle h_dummy1;
int i;
union acpi_object *obj = NULL;
@@ -534,27 +517,27 @@ acpi_video_device_find_cap (struct acpi_video_device *device)
ACPI_FUNCTION_TRACE("acpi_video_device_find_cap");
- memset( &device->cap, 0, 4);
+ memset(&device->cap, 0, 4);
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
device->cap._ADR = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
- device->cap._BCL= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
+ device->cap._BCL = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
- device->cap._BCM= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
+ device->cap._BCM = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
- device->cap._DDC= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
+ device->cap._DDC = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
device->cap._DCS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
device->cap._DGS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
device->cap._DSS = 1;
}
@@ -563,34 +546,38 @@ acpi_video_device_find_cap (struct acpi_video_device *device)
if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
int count = 0;
union acpi_object *o;
-
+
br = kmalloc(sizeof(*br), GFP_KERNEL);
if (!br) {
printk(KERN_ERR "can't allocate memory\n");
} else {
memset(br, 0, sizeof(*br));
br->levels = kmalloc(obj->package.count *
- sizeof *(br->levels), GFP_KERNEL);
+ sizeof *(br->levels), GFP_KERNEL);
if (!br->levels)
goto out;
for (i = 0; i < obj->package.count; i++) {
- o = (union acpi_object *) &obj->package.elements[i];
+ o = (union acpi_object *)&obj->package.
+ elements[i];
if (o->type != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid data\n"));
continue;
}
br->levels[count] = (u32) o->integer.value;
count++;
}
-out:
+ out:
if (count < 2) {
kfree(br->levels);
kfree(br);
} else {
br->count = count;
device->brightness = br;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "found %d brightness levels\n",
+ count));
}
}
}
@@ -610,28 +597,27 @@ out:
* Find out all required AML method defined under the video bus device.
*/
-static void
-acpi_video_bus_find_cap (struct acpi_video_bus *video)
+static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
{
- acpi_handle h_dummy1;
+ acpi_handle h_dummy1;
- memset(&video->cap ,0, 4);
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
+ memset(&video->cap, 0, 4);
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
video->cap._DOS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
video->cap._DOD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
video->cap._ROM = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
video->cap._GPD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
video->cap._SPD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
video->cap._VPO = 1;
}
}
@@ -641,12 +627,9 @@ acpi_video_bus_find_cap (struct acpi_video_bus *video)
* support the desired features
*/
-static int
-acpi_video_bus_check (
- struct acpi_video_bus *video)
+static int acpi_video_bus_check(struct acpi_video_bus *video)
{
- acpi_status status = -ENOENT;
-
+ acpi_status status = -ENOENT;
ACPI_FUNCTION_TRACE("acpi_video_bus_check");
@@ -658,19 +641,19 @@ acpi_video_bus_check (
*/
/* Does this device able to support video switching ? */
- if(video->cap._DOS){
+ if (video->cap._DOS) {
video->flags.multihead = 1;
status = 0;
}
/* Does this device able to retrieve a retrieve a video ROM ? */
- if(video->cap._ROM){
+ if (video->cap._ROM) {
video->flags.rom = 1;
status = 0;
}
/* Does this device able to configure which video device to POST ? */
- if(video->cap._GPD && video->cap._SPD && video->cap._VPO){
+ if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
video->flags.post = 1;
status = 0;
}
@@ -682,16 +665,14 @@ acpi_video_bus_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_video_dir;
+static struct proc_dir_entry *acpi_video_dir;
/* video devices */
-static int
-acpi_video_device_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_device_info_seq_show");
@@ -709,30 +690,25 @@ acpi_video_device_info_seq_show (
else
seq_printf(seq, "UNKNOWN\n");
- seq_printf(seq,"known by bios: %s\n",
- dev->flags.bios ? "yes":"no");
+ seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_device_info_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_info_seq_show,
PDE(inode)->data);
}
-static int
-acpi_video_device_state_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
{
- int status;
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- unsigned long state;
+ int status;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ unsigned long state;
ACPI_FUNCTION_TRACE("acpi_video_device_state_seq_show");
@@ -753,31 +729,27 @@ acpi_video_device_state_seq_show (
else
seq_printf(seq, "<not supported>\n");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_device_state_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_state_seq_show,
PDE(inode)->data);
}
static ssize_t
-acpi_video_device_write_state (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_device_write_state(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
- char str[12] = {0};
- u32 state = 0;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ char str[12] = { 0 };
+ u32 state = 0;
ACPI_FUNCTION_TRACE("acpi_video_device_write_state");
@@ -789,7 +761,7 @@ acpi_video_device_write_state (
str[count] = 0;
state = simple_strtoul(str, NULL, 0);
- state &= ((1ul<<31) | (1ul<<30) | (1ul<<0));
+ state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
status = acpi_video_device_set_state(dev, state);
@@ -800,12 +772,11 @@ acpi_video_device_write_state (
}
static int
-acpi_video_device_brightness_seq_show (
- struct seq_file *seq,
- void *offset)
+acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- int i;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_brightness_seq_show");
@@ -823,26 +794,22 @@ acpi_video_device_brightness_seq_show (
}
static int
-acpi_video_device_brightness_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_brightness_seq_show,
PDE(inode)->data);
}
static ssize_t
-acpi_video_device_write_brightness (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_device_write_brightness(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
- char str[4] = {0};
- unsigned int level = 0;
- int i;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ char str[4] = { 0 };
+ unsigned int level = 0;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
@@ -854,14 +821,15 @@ acpi_video_device_write_brightness (
str[count] = 0;
level = simple_strtoul(str, NULL, 0);
-
+
if (level > 100)
return_VALUE(-EFAULT);
/* validate though the list of available levels */
for (i = 0; i < dev->brightness->count; i++)
if (level == dev->brightness->levels[i]) {
- if (ACPI_SUCCESS(acpi_video_device_lcd_set_level(dev, level)))
+ if (ACPI_SUCCESS
+ (acpi_video_device_lcd_set_level(dev, level)))
dev->brightness->curr = level;
break;
}
@@ -869,24 +837,22 @@ acpi_video_device_write_brightness (
return_VALUE(count);
}
-static int
-acpi_video_device_EDID_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- int status;
- int i;
- union acpi_object *edid = NULL;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ int status;
+ int i;
+ union acpi_object *edid = NULL;
ACPI_FUNCTION_TRACE("acpi_video_device_EDID_seq_show");
if (!dev)
goto out;
- status = acpi_video_device_EDID (dev, &edid, 128);
+ status = acpi_video_device_EDID(dev, &edid, 128);
if (ACPI_FAILURE(status)) {
- status = acpi_video_device_EDID (dev, &edid, 256);
+ status = acpi_video_device_EDID(dev, &edid, 256);
}
if (ACPI_FAILURE(status)) {
@@ -898,7 +864,7 @@ acpi_video_device_EDID_seq_show (
seq_putc(seq, edid->buffer.pointer[i]);
}
-out:
+ out:
if (!edid)
seq_printf(seq, "<not supported>\n");
else
@@ -908,20 +874,15 @@ out:
}
static int
-acpi_video_device_EDID_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_EDID_seq_show,
PDE(inode)->data);
}
-
-static int
-acpi_video_device_add_fs (
- struct acpi_device *device)
+static int acpi_video_device_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
struct acpi_video_device *vid_dev;
ACPI_FUNCTION_TRACE("acpi_video_device_add_fs");
@@ -929,13 +890,13 @@ acpi_video_device_add_fs (
if (!device)
return_VALUE(-ENODEV);
- vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
+ vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
if (!vid_dev)
return_VALUE(-ENODEV);
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- vid_dev->video->dir);
+ vid_dev->video->dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -945,7 +906,7 @@ acpi_video_device_add_fs (
entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'info' fs entry\n"));
+ "Unable to create 'info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_info_fops;
entry->data = acpi_driver_data(device);
@@ -953,10 +914,12 @@ acpi_video_device_add_fs (
}
/* 'state' [R/W] */
- entry = create_proc_entry("state", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'state' fs entry\n"));
+ "Unable to create 'state' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_state_fops;
entry->proc_fops->write = acpi_video_device_write_state;
@@ -965,10 +928,12 @@ acpi_video_device_add_fs (
}
/* 'brightness' [R/W] */
- entry = create_proc_entry("brightness", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'brightness' fs entry\n"));
+ "Unable to create 'brightness' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_brightness_fops;
entry->proc_fops->write = acpi_video_device_write_brightness;
@@ -980,7 +945,7 @@ acpi_video_device_add_fs (
entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'brightness' fs entry\n"));
+ "Unable to create 'brightness' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_EDID_fops;
entry->data = acpi_driver_data(device);
@@ -990,14 +955,12 @@ acpi_video_device_add_fs (
return_VALUE(0);
}
-static int
-acpi_video_device_remove_fs (
- struct acpi_device *device)
+static int acpi_video_device_remove_fs(struct acpi_device *device)
{
struct acpi_video_device *vid_dev;
ACPI_FUNCTION_TRACE("acpi_video_device_remove_fs");
- vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
+ vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
return_VALUE(-ENODEV);
@@ -1006,22 +969,17 @@ acpi_video_device_remove_fs (
remove_proc_entry("state", acpi_device_dir(device));
remove_proc_entry("brightness", acpi_device_dir(device));
remove_proc_entry("EDID", acpi_device_dir(device));
- remove_proc_entry(acpi_device_bid(device),
- vid_dev->video->dir);
+ remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
acpi_device_dir(device) = NULL;
}
return_VALUE(0);
}
-
/* video bus */
-static int
-acpi_video_bus_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_info_seq_show");
@@ -1029,30 +987,25 @@ acpi_video_bus_info_seq_show (
goto end;
seq_printf(seq, "Switching heads: %s\n",
- video->flags.multihead ? "yes":"no");
+ video->flags.multihead ? "yes" : "no");
seq_printf(seq, "Video ROM: %s\n",
- video->flags.rom ? "yes":"no");
+ video->flags.rom ? "yes" : "no");
seq_printf(seq, "Device to be POSTed on boot: %s\n",
- video->flags.post ? "yes":"no");
+ video->flags.post ? "yes" : "no");
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_info_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_info_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_info_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_ROM_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_ROM_seq_show");
@@ -1062,26 +1015,20 @@ acpi_video_bus_ROM_seq_show (
printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
seq_printf(seq, "<TODO>\n");
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_ROM_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
}
-static int
-acpi_video_bus_POST_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
- unsigned long options;
- int status;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ unsigned long options;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_info_seq_show");
@@ -1091,8 +1038,10 @@ acpi_video_bus_POST_info_seq_show (
status = acpi_video_bus_POST_options(video, &options);
if (ACPI_SUCCESS(status)) {
if (!(options & 1)) {
- printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n");
- printk(KERN_WARNING PREFIX "This indicate a BIOS bug. Please contact the manufacturer.\n");
+ printk(KERN_WARNING PREFIX
+ "The motherboard VGA device is not listed as a possible POST device.\n");
+ printk(KERN_WARNING PREFIX
+ "This indicate a BIOS bug. Please contact the manufacturer.\n");
}
printk("%lx\n", options);
seq_printf(seq, "can POST: <intgrated video>");
@@ -1103,89 +1052,74 @@ acpi_video_bus_POST_info_seq_show (
seq_putc(seq, '\n');
} else
seq_printf(seq, "<not supported>\n");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_bus_POST_info_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_POST_info_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_POST_info_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_POST_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
- int status;
- unsigned long id;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ int status;
+ unsigned long id;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_seq_show");
if (!video)
goto end;
- status = acpi_video_bus_get_POST (video, &id);
+ status = acpi_video_bus_get_POST(video, &id);
if (!ACPI_SUCCESS(status)) {
seq_printf(seq, "<not supported>\n");
goto end;
}
- seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
+ seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_DOS_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_DOS_seq_show");
- seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting );
+ seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
return_VALUE(0);
}
-static int
-acpi_video_bus_POST_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_POST_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_POST_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_DOS_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
}
static ssize_t
-acpi_video_bus_write_POST (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_bus_write_POST(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
- char str[12] = {0};
- unsigned long opt, options;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ char str[12] = { 0 };
+ unsigned long opt, options;
ACPI_FUNCTION_TRACE("acpi_video_bus_write_POST");
-
if (!video || count + 1 > sizeof str)
return_VALUE(-EINVAL);
@@ -1205,32 +1139,28 @@ acpi_video_bus_write_POST (
options |= 1;
if (options & (1ul << opt)) {
- status = acpi_video_bus_set_POST (video, opt);
+ status = acpi_video_bus_set_POST(video, opt);
if (!ACPI_SUCCESS(status))
return_VALUE(-EFAULT);
}
-
return_VALUE(count);
}
static ssize_t
-acpi_video_bus_write_DOS (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_bus_write_DOS(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
- char str[12] = {0};
- unsigned long opt;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ char str[12] = { 0 };
+ unsigned long opt;
ACPI_FUNCTION_TRACE("acpi_video_bus_write_DOS");
-
if (!video || count + 1 > sizeof str)
return_VALUE(-EINVAL);
@@ -1242,7 +1172,7 @@ acpi_video_bus_write_DOS (
if (opt > 7)
return_VALUE(-EFAULT);
- status = acpi_video_bus_DOS (video, opt & 0x3, (opt & 0x4)>>2);
+ status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
if (!ACPI_SUCCESS(status))
return_VALUE(-EFAULT);
@@ -1250,20 +1180,18 @@ acpi_video_bus_write_DOS (
return_VALUE(count);
}
-static int
-acpi_video_bus_add_fs (
- struct acpi_device *device)
+static int acpi_video_bus_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_video_bus *video;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_add_fs");
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_video_dir);
+ acpi_video_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
video->dir = acpi_device_dir(device);
@@ -1273,7 +1201,8 @@ acpi_video_bus_add_fs (
/* 'info' [R] */
entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'info' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_info_fops;
entry->data = acpi_driver_data(device);
@@ -1283,7 +1212,8 @@ acpi_video_bus_add_fs (
/* 'ROM' [R] */
entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'ROM' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'ROM' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_ROM_fops;
entry->data = acpi_driver_data(device);
@@ -1291,9 +1221,11 @@ acpi_video_bus_add_fs (
}
/* 'POST_info' [R] */
- entry = create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
+ entry =
+ create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST_info' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'POST_info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_POST_info_fops;
entry->data = acpi_driver_data(device);
@@ -1301,9 +1233,12 @@ acpi_video_bus_add_fs (
}
/* 'POST' [R/W] */
- entry = create_proc_entry("POST", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
+ acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'POST' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_POST_fops;
entry->proc_fops->write = acpi_video_bus_write_POST;
@@ -1312,9 +1247,12 @@ acpi_video_bus_add_fs (
}
/* 'DOS' [R/W] */
- entry = create_proc_entry("DOS", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
+ acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'DOS' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'DOS' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_DOS_fops;
entry->proc_fops->write = acpi_video_bus_write_DOS;
@@ -1325,15 +1263,13 @@ acpi_video_bus_add_fs (
return_VALUE(0);
}
-static int
-acpi_video_bus_remove_fs (
- struct acpi_device *device)
+static int acpi_video_bus_remove_fs(struct acpi_device *device)
{
- struct acpi_video_bus *video;
+ struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_remove_fs");
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
if (acpi_device_dir(device)) {
remove_proc_entry("info", acpi_device_dir(device));
@@ -1341,8 +1277,7 @@ acpi_video_bus_remove_fs (
remove_proc_entry("POST_info", acpi_device_dir(device));
remove_proc_entry("POST", acpi_device_dir(device));
remove_proc_entry("DOS", acpi_device_dir(device));
- remove_proc_entry(acpi_device_bid(device),
- acpi_video_dir);
+ remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
acpi_device_dir(device) = NULL;
}
@@ -1356,20 +1291,20 @@ acpi_video_bus_remove_fs (
/* device interface */
static int
-acpi_video_bus_get_one_device (
- struct acpi_device *device,
- struct acpi_video_bus *video)
+acpi_video_bus_get_one_device(struct acpi_device *device,
+ struct acpi_video_bus *video)
{
- unsigned long device_id;
- int status, result;
- struct acpi_video_device *data;
+ unsigned long device_id;
+ int status, result;
+ struct acpi_video_device *data;
ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
if (!device || !video)
return_VALUE(-EINVAL);
- status = acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+ status =
+ acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
if (ACPI_SUCCESS(status)) {
data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
@@ -1401,15 +1336,17 @@ acpi_video_bus_get_one_device (
data->flags.unknown = 1;
break;
}
-
+
acpi_video_device_bind(video, data);
acpi_video_device_find_cap(data);
status = acpi_install_notify_handler(data->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_device_notify, data);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_device_notify,
+ data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
@@ -1423,7 +1360,7 @@ acpi_video_bus_get_one_device (
return_VALUE(0);
}
-end:
+ end:
return_VALUE(-ENOENT);
}
@@ -1437,15 +1374,15 @@ end:
* Enumerate the video device list of the video bus,
* bind the ids with the corresponding video devices
* under the video bus.
- */
+ */
-static void
-acpi_video_device_rebind( struct acpi_video_bus *video)
+static void acpi_video_device_rebind(struct acpi_video_bus *video)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device * dev = container_of(node, struct acpi_video_device, entry);
- acpi_video_device_bind( video, dev);
+ struct acpi_video_device *dev =
+ container_of(node, struct acpi_video_device, entry);
+ acpi_video_device_bind(video, dev);
}
}
@@ -1460,21 +1397,21 @@ acpi_video_device_rebind( struct acpi_video_bus *video)
*
* Bind the ids with the corresponding video devices
* under the video bus.
- */
+ */
static void
-acpi_video_device_bind( struct acpi_video_bus *video,
- struct acpi_video_device *device)
+acpi_video_device_bind(struct acpi_video_bus *video,
+ struct acpi_video_device *device)
{
- int i;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_bind");
#define IDS_VAL(i) video->attached_array[i].value.int_val
#define IDS_BIND(i) video->attached_array[i].bind_info
-
- for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
- i < video->attached_count; i++) {
- if (device->device_id == (IDS_VAL(i)& 0xffff)) {
+
+ for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
+ i < video->attached_count; i++) {
+ if (device->device_id == (IDS_VAL(i) & 0xffff)) {
IDS_BIND(i) = device;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
}
@@ -1492,17 +1429,17 @@ acpi_video_device_bind( struct acpi_video_bus *video,
*
* Call _DOD to enumerate all devices attached to display adapter
*
- */
+ */
static int acpi_video_device_enumerate(struct acpi_video_bus *video)
{
- int status;
- int count;
- int i;
+ int status;
+ int count;
+ int i;
struct acpi_video_enumerated_device *active_device_list;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *dod = NULL;
- union acpi_object *obj;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *dod = NULL;
+ union acpi_object *obj;
ACPI_FUNCTION_TRACE("acpi_video_device_enumerate");
@@ -1512,7 +1449,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
return_VALUE(status);
}
- dod = (union acpi_object *) buffer.pointer;
+ dod = (union acpi_object *)buffer.pointer;
if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
status = -EFAULT;
@@ -1520,11 +1457,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
- dod->package.count));
+ dod->package.count));
- active_device_list= kmalloc(
- (1+dod->package.count)*sizeof(struct acpi_video_enumerated_device),
- GFP_KERNEL);
+ active_device_list = kmalloc((1 +
+ dod->package.count) *
+ sizeof(struct
+ acpi_video_enumerated_device),
+ GFP_KERNEL);
if (!active_device_list) {
status = -ENOMEM;
@@ -1533,25 +1472,28 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
count = 0;
for (i = 0; i < dod->package.count; i++) {
- obj = (union acpi_object *) &dod->package.elements[i];
+ obj = (union acpi_object *)&dod->package.elements[i];
if (obj->type != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
- active_device_list[i].value.int_val = ACPI_VIDEO_HEAD_INVALID;
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _DOD data\n"));
+ active_device_list[i].value.int_val =
+ ACPI_VIDEO_HEAD_INVALID;
}
active_device_list[i].value.int_val = obj->integer.value;
active_device_list[i].bind_info = NULL;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int) obj->integer.value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
+ (int)obj->integer.value));
count++;
}
active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
- if(video->attached_array)
+ if (video->attached_array)
kfree(video->attached_array);
-
+
video->attached_array = active_device_list;
video->attached_count = count;
-out:
+ out:
acpi_os_free(buffer.pointer);
return_VALUE(status);
}
@@ -1567,17 +1509,14 @@ out:
* 1. Find out the current active output device.
* 2. Identify the next output device to switch
* 3. call _DSS to do actual switch.
- */
+ */
-static int
-acpi_video_switch_output(
- struct acpi_video_bus *video,
- int event)
+static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
{
- struct list_head * node, * next;
- struct acpi_video_device *dev=NULL;
- struct acpi_video_device *dev_next=NULL;
- struct acpi_video_device *dev_prev=NULL;
+ struct list_head *node, *next;
+ struct acpi_video_device *dev = NULL;
+ struct acpi_video_device *dev_next = NULL;
+ struct acpi_video_device *dev_prev = NULL;
unsigned long state;
int status = 0;
@@ -1586,15 +1525,19 @@ acpi_video_switch_output(
list_for_each_safe(node, next, &video->video_device_list) {
dev = container_of(node, struct acpi_video_device, entry);
status = acpi_video_device_get_state(dev, &state);
- if (state & 0x2){
- dev_next = container_of(node->next, struct acpi_video_device, entry);
- dev_prev = container_of(node->prev, struct acpi_video_device, entry);
+ if (state & 0x2) {
+ dev_next =
+ container_of(node->next, struct acpi_video_device,
+ entry);
+ dev_prev =
+ container_of(node->prev, struct acpi_video_device,
+ entry);
goto out;
}
}
dev_next = container_of(node->next, struct acpi_video_device, entry);
dev_prev = container_of(node->prev, struct acpi_video_device, entry);
-out:
+ out:
switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE:
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
@@ -1611,21 +1554,16 @@ out:
return_VALUE(status);
}
-static int
-acpi_video_get_next_level(
- struct acpi_video_device *device,
- u32 level_current,
- u32 event)
+static int
+acpi_video_get_next_level(struct acpi_video_device *device,
+ u32 level_current, u32 event)
{
- /*Fix me*/
+ /*Fix me */
return level_current;
}
-
static void
-acpi_video_switch_brightness (
- struct acpi_video_device *device,
- int event)
+acpi_video_switch_brightness(struct acpi_video_device *device, int event)
{
unsigned long level_current, level_next;
acpi_video_device_lcd_get_level_current(device, &level_current);
@@ -1634,26 +1572,27 @@ acpi_video_switch_brightness (
}
static int
-acpi_video_bus_get_devices (
- struct acpi_video_bus *video,
- struct acpi_device *device)
+acpi_video_bus_get_devices(struct acpi_video_bus *video,
+ struct acpi_device *device)
{
- int status = 0;
- struct list_head *node, *next;
+ int status = 0;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_video_get_devices");
acpi_video_device_enumerate(video);
list_for_each_safe(node, next, &device->children) {
- struct acpi_device *dev = list_entry(node, struct acpi_device, node);
+ struct acpi_device *dev =
+ list_entry(node, struct acpi_device, node);
if (!dev)
continue;
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Cant attach device\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cant attach device\n"));
continue;
}
@@ -1661,10 +1600,9 @@ acpi_video_bus_get_devices (
return_VALUE(status);
}
-static int
-acpi_video_bus_put_one_device(
- struct acpi_video_device *device)
+static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
{
+ acpi_status status;
struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_put_one_device");
@@ -1679,26 +1617,33 @@ acpi_video_bus_put_one_device(
up(&video->sem);
acpi_video_device_remove_fs(device->dev);
+ status = acpi_remove_notify_handler(device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_device_notify);
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error removing notify handler\n"));
+
return_VALUE(0);
}
-static int
-acpi_video_bus_put_devices (
- struct acpi_video_bus *video)
+static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{
- int status;
- struct list_head *node, *next;
+ int status;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_video_bus_put_devices");
list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device *data = list_entry(node, struct acpi_video_device, entry);
+ struct acpi_video_device *data =
+ list_entry(node, struct acpi_video_device, entry);
if (!data)
continue;
status = acpi_video_bus_put_one_device(data);
- if(ACPI_FAILURE(status))
- printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n");
+ if (ACPI_FAILURE(status))
+ printk(KERN_WARNING PREFIX
+ "hhuuhhuu bug in acpi video driver.\n");
if (data->brightness)
kfree(data->brightness);
@@ -1711,28 +1656,20 @@ acpi_video_bus_put_devices (
/* acpi_video interface */
-static int
-acpi_video_bus_start_devices(
- struct acpi_video_bus *video)
+static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
{
return acpi_video_bus_DOS(video, 1, 0);
}
-static int
-acpi_video_bus_stop_devices(
- struct acpi_video_bus *video)
+static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
{
return acpi_video_bus_DOS(video, 0, 1);
}
-static void
-acpi_video_bus_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) data;
- struct acpi_device *device = NULL;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_notify");
printk("video bus notify\n");
@@ -1757,30 +1694,27 @@ acpi_video_bus_notify (
acpi_bus_generate_event(device, event, 0);
break;
- case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed.*/
- case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
- case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
acpi_video_switch_output(video, event);
acpi_bus_generate_event(device, event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static void
-acpi_video_device_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_device *video_device = (struct acpi_video_device *) data;
- struct acpi_device *device = NULL;
+ struct acpi_video_device *video_device =
+ (struct acpi_video_device *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_video_device_notify");
@@ -1792,36 +1726,34 @@ acpi_video_device_notify (
return_VOID;
switch (event) {
- case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
- case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
+ case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
+ case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
acpi_bus_generate_event(device, event, 0);
break;
- case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
- case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
- case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
- case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
- case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
- acpi_video_switch_brightness (video_device, event);
+ case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
+ case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
+ case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
+ case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
+ case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
+ acpi_video_switch_brightness(video_device, event);
acpi_bus_generate_event(device, event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static int
-acpi_video_bus_add (
- struct acpi_device *device)
+static int acpi_video_bus_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_video_bus *video = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_video_bus *video = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_add");
-
+
if (!device)
return_VALUE(-EINVAL);
@@ -1851,21 +1783,22 @@ acpi_video_bus_add (
acpi_video_bus_start_devices(video);
status = acpi_install_notify_handler(video->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify, video);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
- ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
- video->flags.multihead ? "yes":"no",
- video->flags.rom ? "yes":"no",
- video->flags.post ? "yes":"no");
+ ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
+ video->flags.multihead ? "yes" : "no",
+ video->flags.rom ? "yes" : "no",
+ video->flags.post ? "yes" : "no");
-end:
+ end:
if (result) {
acpi_video_bus_remove_fs(device);
kfree(video);
@@ -1874,28 +1807,26 @@ end:
return_VALUE(result);
}
-static int
-acpi_video_bus_remove (
- struct acpi_device *device,
- int type)
+static int acpi_video_bus_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_video_bus *video = NULL;
+ acpi_status status = 0;
+ struct acpi_video_bus *video = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
acpi_video_bus_stop_devices(video);
status = acpi_remove_notify_handler(video->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_bus_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
@@ -1907,15 +1838,12 @@ acpi_video_bus_remove (
return_VALUE(0);
}
-
static int
-acpi_video_bus_match (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
- acpi_handle h_dummy1;
- acpi_handle h_dummy2;
- acpi_handle h_dummy3;
+ acpi_handle h_dummy1;
+ acpi_handle h_dummy2;
+ acpi_handle h_dummy3;
ACPI_FUNCTION_TRACE("acpi_video_bus_match");
@@ -1941,22 +1869,19 @@ acpi_video_bus_match (
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
return_VALUE(0);
-
return_VALUE(-ENODEV);
}
-
-static int __init
-acpi_video_init (void)
+static int __init acpi_video_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_video_init");
/*
- acpi_dbg_level = 0xFFFFFFFF;
- acpi_dbg_layer = 0x08000000;
- */
+ acpi_dbg_level = 0xFFFFFFFF;
+ acpi_dbg_layer = 0x08000000;
+ */
acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
if (!acpi_video_dir)
@@ -1972,8 +1897,7 @@ acpi_video_init (void)
return_VALUE(0);
}
-static void __exit
-acpi_video_exit (void)
+static void __exit acpi_video_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_video_exit");
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 73c6b85299c1..d74a7c5e75dd 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -513,7 +513,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) {
// VC layer stats
atomic_inc(&atm_vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
// end of our responsability
atm_vcc->push (atm_vcc, skb);
return;
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index f2f01cb82cb4..57f1810fdccd 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -325,7 +325,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
result = -ENOBUFS;
goto done;
}
- do_gettimeofday(&new_skb->stamp);
+ __net_timestamp(new_skb);
memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
out_vcc->push(out_vcc,new_skb);
atomic_inc(&vcc->stats->tx);
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 10da36934769..c13c4d736ef5 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -537,7 +537,7 @@ static int rx_aal0(struct atm_vcc *vcc)
return 0;
}
skb_put(skb,length);
- skb->stamp = eni_vcc->timestamp;
+ skb_set_timestamp(skb, &eni_vcc->timestamp);
DPRINTK("got len %ld\n",length);
if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1;
eni_vcc->rxing++;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index b078fa548ebf..58219744f5db 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -815,7 +815,7 @@ static void process_incoming (struct fs_dev *dev, struct queue *q)
skb_put (skb, qe->p1 & 0xffff);
ATM_SKB(skb)->vcc = atm_vcc;
atomic_inc(&atm_vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb);
atm_vcc->push (atm_vcc, skb);
fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe);
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 5f702199543a..2bf723a7b6e6 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -1176,7 +1176,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
return -ENOMEM;
}
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#ifdef FORE200E_52BYTE_AAL0_SDU
if (cell_header) {
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 28250c9b32d6..fde9334059af 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1886,7 +1886,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
if (rx_skb_reserve > 0)
skb_reserve(skb, rx_skb_reserve);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
for (iov = he_vcc->iov_head;
iov < he_vcc->iov_tail; ++iov) {
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 924a2c8988bd..0cded0468003 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1034,7 +1034,7 @@ static void rx_schedule (hrz_dev * dev, int irq) {
struct atm_vcc * vcc = ATM_SKB(skb)->vcc;
// VC layer stats
atomic_inc(&vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
// end of our responsability
vcc->push (vcc, skb);
}
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index b8c260ed4b27..0aabfc2a59d9 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -50,10 +50,8 @@ static void idt77105_stats_timer_func(unsigned long);
static void idt77105_restart_timer_func(unsigned long);
-static struct timer_list stats_timer =
- TIMER_INITIALIZER(idt77105_stats_timer_func, 0, 0);
-static struct timer_list restart_timer =
- TIMER_INITIALIZER(idt77105_restart_timer_func, 0, 0);
+static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func, 0, 0);
+static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func, 0, 0);
static int start_timer = 1;
static struct idt77105_priv *idt77105_all = NULL;
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 30b7e990ed0b..b4a76cade646 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -1101,7 +1101,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
cell, ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
@@ -1179,7 +1179,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
skb_trim(skb, len);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
@@ -1201,7 +1201,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
skb_trim(skb, len);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
@@ -1340,7 +1340,7 @@ idt77252_rx_raw(struct idt77252_dev *card)
ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index a43575acb2c1..2e2e50e1167a 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -79,7 +79,7 @@ static IADEV *ia_dev[8];
static struct atm_dev *_ia_dev[8];
static int iadev_count;
static void ia_led_timer(unsigned long arg);
-static struct timer_list ia_timer = TIMER_INITIALIZER(ia_led_timer, 0, 0);
+static DEFINE_TIMER(ia_timer, ia_led_timer, 0, 0);
static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index ffe3afa723b8..51ec14787293 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1427,7 +1427,7 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
skb_put(skb, size);
vcc_rx_memcpy(skb->data, lvcc, size);
ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
atomic_inc(&lvcc->rx.atmvcc->stats->rx);
out:
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index b2a7b754fd14..c57e20dcb0f8 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -214,8 +214,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev);
static void __devinit ns_init_card_error(ns_dev *card, int error);
static scq_info *get_scq(int size, u32 scd);
static void free_scq(scq_info *scq, struct atm_vcc *vcc);
-static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
- u32 handle2, u32 addr2);
+static void push_rxbufs(ns_dev *, struct sk_buff *);
static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
static int ns_open(struct atm_vcc *vcc);
static void ns_close(struct atm_vcc *vcc);
@@ -766,6 +765,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
}
@@ -786,9 +786,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
/* Due to the implementation of push_rxbufs() this is 1, not 0 */
if (j == 1)
{
@@ -822,9 +823,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
/* Test for strange behaviour which leads to crashes */
if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min)
@@ -852,6 +854,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++;
}
@@ -1078,12 +1081,18 @@ static void free_scq(scq_info *scq, struct atm_vcc *vcc)
/* The handles passed must be pointers to the sk_buff containing the small
or large buffer(s) cast to u32. */
-static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
- u32 handle2, u32 addr2)
+static void push_rxbufs(ns_dev *card, struct sk_buff *skb)
{
+ struct ns_skb_cb *cb = NS_SKB_CB(skb);
+ u32 handle1, addr1;
+ u32 handle2, addr2;
u32 stat;
unsigned long flags;
+ /* *BARF* */
+ handle2 = addr2 = 0;
+ handle1 = (u32)skb;
+ addr1 = (u32)virt_to_bus(skb->data);
#ifdef GENERAL_DEBUG
if (!addr1)
@@ -1093,7 +1102,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
stat = readl(card->membase + STAT);
card->sbfqc = ns_stat_sfbqc_get(stat);
card->lbfqc = ns_stat_lfbqc_get(stat);
- if (type == BUF_SM)
+ if (cb->buf_type == BUF_SM)
{
if (!addr2)
{
@@ -1111,7 +1120,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
}
}
}
- else /* type == BUF_LG */
+ else /* buf_type == BUF_LG */
{
if (!addr2)
{
@@ -1132,26 +1141,26 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
if (addr2)
{
- if (type == BUF_SM)
+ if (cb->buf_type == BUF_SM)
{
if (card->sbfqc >= card->sbnr.max)
{
- skb_unlink((struct sk_buff *) handle1);
+ skb_unlink((struct sk_buff *) handle1, &card->sbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle1);
- skb_unlink((struct sk_buff *) handle2);
+ skb_unlink((struct sk_buff *) handle2, &card->sbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle2);
return;
}
else
card->sbfqc += 2;
}
- else /* (type == BUF_LG) */
+ else /* (buf_type == BUF_LG) */
{
if (card->lbfqc >= card->lbnr.max)
{
- skb_unlink((struct sk_buff *) handle1);
+ skb_unlink((struct sk_buff *) handle1, &card->lbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle1);
- skb_unlink((struct sk_buff *) handle2);
+ skb_unlink((struct sk_buff *) handle2, &card->lbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle2);
return;
}
@@ -1166,12 +1175,12 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
writel(handle2, card->membase + DR2);
writel(addr1, card->membase + DR1);
writel(handle1, card->membase + DR0);
- writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD);
+ writel(NS_CMD_WRITE_FREEBUFQ | cb->buf_type, card->membase + CMD);
spin_unlock_irqrestore(&card->res_lock, flags);
XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index,
- (type == BUF_SM ? "small" : "large"), addr1, addr2);
+ (cb->buf_type == BUF_SM ? "small" : "large"), addr1, addr2);
}
if (!card->efbie && card->sbfqc >= card->sbnr.min &&
@@ -1322,9 +1331,10 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
card->efbie = 0;
break;
}
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
card->sbfqc = i;
process_rsq(card);
@@ -1348,9 +1358,10 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
card->efbie = 0;
break;
}
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
card->lbfqc = i;
process_rsq(card);
@@ -2202,7 +2213,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
memcpy(sb->tail, cell, ATM_CELL_PAYLOAD);
skb_put(sb, ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
cell += ATM_CELL_PAYLOAD;
@@ -2227,6 +2238,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
recycle_rx_buf(card, skb);
return;
}
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
}
else
if (--card->iovpool.count < card->iovnr.min)
@@ -2234,6 +2246,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
struct sk_buff *new_iovb;
if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL)
{
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, new_iovb);
card->iovpool.count++;
}
@@ -2264,7 +2277,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
if (NS_SKB(iovb)->iovcnt == 1)
{
- if (skb->list != &card->sbpool.queue)
+ if (NS_SKB_CB(skb)->buf_type != BUF_SM)
{
printk("nicstar%d: Expected a small buffer, and this is not one.\n",
card->index);
@@ -2278,7 +2291,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
}
else /* NS_SKB(iovb)->iovcnt >= 2 */
{
- if (skb->list != &card->lbpool.queue)
+ if (NS_SKB_CB(skb)->buf_type != BUF_LG)
{
printk("nicstar%d: Expected a large buffer, and this is not one.\n",
card->index);
@@ -2322,8 +2335,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
/* skb points to a small buffer */
if (!atm_charge(vcc, skb->truesize))
{
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
+ push_rxbufs(card, skb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2334,7 +2346,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
skb->destructor = ns_sb_destructor;
#endif /* NS_USE_DESTRUCTORS */
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
}
@@ -2350,8 +2362,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
{
if (!atm_charge(vcc, sb->truesize))
{
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2362,21 +2373,19 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
sb->destructor = ns_sb_destructor;
#endif /* NS_USE_DESTRUCTORS */
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
}
- push_rxbufs(card, BUF_LG, (u32) skb,
- (u32) virt_to_bus(skb->data), 0, 0);
+ push_rxbufs(card, skb);
}
else /* len > NS_SMBUFSIZE, the usual case */
{
if (!atm_charge(vcc, skb->truesize))
{
- push_rxbufs(card, BUF_LG, (u32) skb,
- (u32) virt_to_bus(skb->data), 0, 0);
+ push_rxbufs(card, skb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2389,13 +2398,12 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
memcpy(skb->data, sb->data, NS_SMBUFSIZE);
skb_put(skb, len - NS_SMBUFSIZE);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
}
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
}
@@ -2430,6 +2438,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
card->hbpool.count++;
}
}
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
}
else
if (--card->hbpool.count < card->hbnr.min)
@@ -2437,6 +2446,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
struct sk_buff *new_hb;
if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
{
+ NS_SKB_CB(new_hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, new_hb);
card->hbpool.count++;
}
@@ -2444,6 +2454,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
{
if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
{
+ NS_SKB_CB(new_hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, new_hb);
card->hbpool.count++;
}
@@ -2473,8 +2484,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
remaining = len - iov->iov_len;
iov++;
/* Free the small buffer */
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
/* Copy all large buffers to the huge buffer and free them */
for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)
@@ -2485,8 +2495,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
skb_put(hb, tocopy);
iov++;
remaining -= tocopy;
- push_rxbufs(card, BUF_LG, (u32) lb,
- (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
#ifdef EXTRA_DEBUG
if (remaining != 0 || hb->len != len)
@@ -2496,7 +2505,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
#ifdef NS_USE_DESTRUCTORS
hb->destructor = ns_hb_destructor;
#endif /* NS_USE_DESTRUCTORS */
- do_gettimeofday(&hb->stamp);
+ __net_timestamp(hb);
vcc->push(vcc, hb);
atomic_inc(&vcc->stats->rx);
}
@@ -2527,9 +2536,10 @@ static void ns_sb_destructor(struct sk_buff *sb)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL)
break;
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
} while (card->sbfqc < card->sbnr.min);
}
@@ -2550,9 +2560,10 @@ static void ns_lb_destructor(struct sk_buff *lb)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL)
break;
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
} while (card->lbfqc < card->lbnr.min);
}
@@ -2569,6 +2580,7 @@ static void ns_hb_destructor(struct sk_buff *hb)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL)
break;
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
}
@@ -2577,45 +2589,25 @@ static void ns_hb_destructor(struct sk_buff *hb)
#endif /* NS_USE_DESTRUCTORS */
-
static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb)
{
- if (skb->list == &card->sbpool.queue)
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0);
- else if (skb->list == &card->lbpool.queue)
- push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0);
- else
- {
- printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
- dev_kfree_skb_any(skb);
- }
-}
+ struct ns_skb_cb *cb = NS_SKB_CB(skb);
+ if (unlikely(cb->buf_type == BUF_NONE)) {
+ printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
+ dev_kfree_skb_any(skb);
+ } else
+ push_rxbufs(card, skb);
+}
static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count)
{
- struct sk_buff *skb;
-
- for (; count > 0; count--)
- {
- skb = (struct sk_buff *) (iov++)->iov_base;
- if (skb->list == &card->sbpool.queue)
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
- else if (skb->list == &card->lbpool.queue)
- push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
- else
- {
- printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
- dev_kfree_skb_any(skb);
- }
- }
+ while (count-- > 0)
+ recycle_rx_buf(card, (struct sk_buff *) (iov++)->iov_base);
}
-
static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb)
{
if (card->iovpool.count < card->iovnr.max)
@@ -2631,7 +2623,7 @@ static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb)
static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
{
- skb_unlink(sb);
+ skb_unlink(sb, &card->sbpool.queue);
#ifdef NS_USE_DESTRUCTORS
if (card->sbfqc < card->sbnr.min)
#else
@@ -2640,10 +2632,10 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) new_sb,
- (u32) virt_to_bus(new_sb->data), 0, 0);
+ push_rxbufs(card, new_sb);
}
}
if (card->sbfqc < card->sbnr.init)
@@ -2652,10 +2644,10 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) new_sb,
- (u32) virt_to_bus(new_sb->data), 0, 0);
+ push_rxbufs(card, new_sb);
}
}
}
@@ -2664,7 +2656,7 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
{
- skb_unlink(lb);
+ skb_unlink(lb, &card->lbpool.queue);
#ifdef NS_USE_DESTRUCTORS
if (card->lbfqc < card->lbnr.min)
#else
@@ -2673,10 +2665,10 @@ static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) new_lb,
- (u32) virt_to_bus(new_lb->data), 0, 0);
+ push_rxbufs(card, new_lb);
}
}
if (card->lbfqc < card->lbnr.init)
@@ -2685,10 +2677,10 @@ static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) new_lb,
- (u32) virt_to_bus(new_lb->data), 0, 0);
+ push_rxbufs(card, new_lb);
}
}
}
@@ -2880,9 +2872,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL)
return -ENOMEM;
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
break;
@@ -2894,9 +2887,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL)
return -ENOMEM;
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
break;
@@ -2923,6 +2917,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL)
return -ENOMEM;
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
ns_grab_int_lock(card, flags);
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
@@ -2953,6 +2948,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
if (iovb == NULL)
return -ENOMEM;
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
ns_grab_int_lock(card, flags);
skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++;
@@ -2979,17 +2975,12 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
}
-
static void which_list(ns_dev *card, struct sk_buff *skb)
{
- printk("It's a %s buffer.\n", skb->list == &card->sbpool.queue ?
- "small" : skb->list == &card->lbpool.queue ? "large" :
- skb->list == &card->hbpool.queue ? "huge" :
- skb->list == &card->iovpool.queue ? "iovec" : "unknown");
+ printk("skb buf_type: 0x%08x\n", NS_SKB_CB(skb)->buf_type);
}
-
static void ns_poll(unsigned long arg)
{
int i;
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
index ea83c46c8ba5..5997bcb45b59 100644
--- a/drivers/atm/nicstar.h
+++ b/drivers/atm/nicstar.h
@@ -103,8 +103,14 @@
#define NS_IOREMAP_SIZE 4096
-#define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */
-#define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */
+/*
+ * BUF_XX distinguish the Rx buffers depending on their (small/large) size.
+ * BUG_SM and BUG_LG are both used by the driver and the device.
+ * BUF_NONE is only used by the driver.
+ */
+#define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */
+#define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */
+#define BUF_NONE 0xffffffff /* Software only: */
#define NS_HBUFSIZE 65568 /* Size of max. AAL5 PDU */
#define NS_MAX_IOVECS (2 + (65568 - NS_SMBUFSIZE) / \
@@ -684,6 +690,12 @@ enum ns_regs
/* Device driver structures ***************************************************/
+struct ns_skb_cb {
+ u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */
+};
+
+#define NS_SKB_CB(skb) ((struct ns_skb_cb *)((skb)->cb))
+
typedef struct tsq_info
{
void *org;
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index a2b236a966e0..55959e4d1cb7 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -400,7 +400,7 @@ unsigned long *x;
EVENT("error code 0x%x/0x%x\n",(here[3] & uPD98401_AAL5_ES) >>
uPD98401_AAL5_ES_SHIFT,error);
skb = ((struct rx_buffer_head *) bus_to_virt(here[2]))->skb;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#if 0
printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3],
((unsigned *) skb->data)[-2],((unsigned *) skb->data)[-1],
@@ -417,10 +417,12 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]);
chan = (here[3] & uPD98401_AAL5_CHAN) >>
uPD98401_AAL5_CHAN_SHIFT;
if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) {
+ int pos;
vcc = zatm_dev->rx_map[chan];
- if (skb == zatm_dev->last_free[ZATM_VCC(vcc)->pool])
- zatm_dev->last_free[ZATM_VCC(vcc)->pool] = NULL;
- skb_unlink(skb);
+ pos = ZATM_VCC(vcc)->pool;
+ if (skb == zatm_dev->last_free[pos])
+ zatm_dev->last_free[pos] = NULL;
+ skb_unlink(skb, zatm_dev->pool + pos);
}
else {
printk(KERN_ERR DEV_LABEL "(itf %d): RX indication "
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ec615d854be9..6b2eb6f39b4d 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -22,11 +22,26 @@
/* This is a private structure used to tie the classdev and the
* container .. it should never be visible outside this file */
struct internal_container {
- struct list_head node;
+ struct klist_node node;
struct attribute_container *cont;
struct class_device classdev;
};
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
/**
* attribute_container_classdev_to_container - given a classdev, return the container
*
@@ -57,7 +72,8 @@ int
attribute_container_register(struct attribute_container *cont)
{
INIT_LIST_HEAD(&cont->node);
- INIT_LIST_HEAD(&cont->containers);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
down(&attribute_container_mutex);
list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +93,13 @@ attribute_container_unregister(struct attribute_container *cont)
{
int retval = -EBUSY;
down(&attribute_container_mutex);
- if (!list_empty(&cont->containers))
+ spin_lock(&cont->containers.k_lock);
+ if (!list_empty(&cont->containers.k_list))
goto out;
retval = 0;
list_del(&cont->node);
out:
+ spin_unlock(&cont->containers.k_lock);
up(&attribute_container_mutex);
return retval;
@@ -134,13 +152,13 @@ attribute_container_add_device(struct device *dev,
if (!cont->match(cont, dev))
continue;
- ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
continue;
}
- memset(ic, 0, sizeof(struct internal_container));
- INIT_LIST_HEAD(&ic->node);
+
ic->cont = cont;
class_device_initialize(&ic->classdev);
ic->classdev.dev = get_device(dev);
@@ -151,11 +169,22 @@ attribute_container_add_device(struct device *dev,
fn(cont, dev, &ic->classdev);
else
attribute_container_add_class_device(&ic->classdev);
- list_add_tail(&ic->node, &cont->containers);
+ klist_add_tail(&ic->node, &cont->containers);
}
up(&attribute_container_mutex);
}
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+ for (klist_iter_init(head, iter); (pos = ({ \
+ struct klist_node *n = klist_next(iter); \
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
+ }) ) != NULL; )
+
+
/**
* attribute_container_remove_device - make device eligible for removal.
*
@@ -182,17 +211,19 @@ attribute_container_remove_device(struct device *dev,
down(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
- struct internal_container *ic, *tmp;
+ struct internal_container *ic;
+ struct klist_iter iter;
if (attribute_container_no_classdevs(cont))
continue;
if (!cont->match(cont, dev))
continue;
- list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
if (dev != ic->classdev.dev)
continue;
- list_del(&ic->node);
+ klist_del(&ic->node);
if (fn)
fn(cont, dev, &ic->classdev);
else {
@@ -225,12 +256,18 @@ attribute_container_device_trigger(struct device *dev,
down(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
- struct internal_container *ic, *tmp;
+ struct internal_container *ic;
+ struct klist_iter iter;
if (!cont->match(cont, dev))
continue;
- list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+ if (attribute_container_no_classdevs(cont)) {
+ fn(cont, dev, NULL);
+ continue;
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
if (dev == ic->classdev.dev)
fn(cont, dev, &ic->classdev);
}
@@ -368,6 +405,36 @@ attribute_container_class_device_del(struct class_device *classdev)
}
EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont: the container
+ * @dev: the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct class_device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (ic->classdev.dev == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+ break;
+ }
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
int __init
attribute_container_init(void)
{
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ab53832d57e5..03204bfd17af 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -156,7 +156,9 @@ static ssize_t driver_unbind(struct device_driver *drv,
device_release_driver(dev);
err = count;
}
- return err;
+ if (err)
+ return err;
+ return count;
}
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
@@ -358,7 +360,7 @@ int bus_add_device(struct device * dev)
if (bus) {
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
device_attach(dev);
- klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+ klist_add_tail(&dev->knode_bus, &bus->klist_devices);
error = device_add_attrs(bus, dev);
if (!error) {
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
@@ -446,7 +448,7 @@ int bus_add_driver(struct device_driver * drv)
}
driver_attach(drv);
- klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
+ klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
@@ -566,6 +568,36 @@ static void bus_remove_attrs(struct bus_type * bus)
}
}
+static void klist_devices_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_bus);
+
+ get_device(dev);
+}
+
+static void klist_devices_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_bus);
+
+ put_device(dev);
+}
+
+static void klist_drivers_get(struct klist_node *n)
+{
+ struct device_driver *drv = container_of(n, struct device_driver,
+ knode_bus);
+
+ get_driver(drv);
+}
+
+static void klist_drivers_put(struct klist_node *n)
+{
+ struct device_driver *drv = container_of(n, struct device_driver,
+ knode_bus);
+
+ put_driver(drv);
+}
+
/**
* bus_register - register a bus with the system.
* @bus: bus.
@@ -600,8 +632,8 @@ int bus_register(struct bus_type * bus)
if (retval)
goto bus_drivers_fail;
- klist_init(&bus->klist_devices);
- klist_init(&bus->klist_drivers);
+ klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
+ klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
bus_add_attrs(bus);
pr_debug("bus type '%s' registered\n", bus->name);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 0154a1623b21..3b112e3542f8 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -189,12 +189,11 @@ struct class *class_create(struct module *owner, char *name)
struct class *cls;
int retval;
- cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
- memset(cls, 0x00, sizeof(struct class));
cls->name = name;
cls->owner = owner;
@@ -299,10 +298,8 @@ static void class_dev_release(struct kobject * kobj)
pr_debug("device class '%s': release.\n", cd->class_id);
- if (cd->devt_attr) {
- kfree(cd->devt_attr);
- cd->devt_attr = NULL;
- }
+ kfree(cd->devt_attr);
+ cd->devt_attr = NULL;
if (cls->release)
cls->release(cd);
@@ -452,10 +449,29 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD(&class_dev->node);
}
+static char *make_class_name(struct class_device *class_dev)
+{
+ char *name;
+ int size;
+
+ size = strlen(class_dev->class->name) +
+ strlen(kobject_name(&class_dev->kobj)) + 2;
+
+ name = kmalloc(size, GFP_KERNEL);
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ strcpy(name, class_dev->class->name);
+ strcat(name, ":");
+ strcat(name, kobject_name(&class_dev->kobj));
+ return name;
+}
+
int class_device_add(struct class_device *class_dev)
{
struct class * parent = NULL;
struct class_interface * class_intf;
+ char *class_name = NULL;
int error;
class_dev = class_device_get(class_dev);
@@ -483,13 +499,13 @@ int class_device_add(struct class_device *class_dev)
/* add the needed attributes to this device */
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
- attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
}
- memset(attr, sizeof(*attr), 0x00);
+
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent->owner;
@@ -500,9 +516,13 @@ int class_device_add(struct class_device *class_dev)
}
class_device_add_attrs(class_dev);
- if (class_dev->dev)
+ if (class_dev->dev) {
+ class_name = make_class_name(class_dev);
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
+ sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+ class_name);
+ }
/* notify any interfaces this device is now here */
if (parent) {
@@ -519,6 +539,7 @@ int class_device_add(struct class_device *class_dev)
if (error && parent)
class_put(parent);
class_device_put(class_dev);
+ kfree(class_name);
return error;
}
@@ -555,12 +576,11 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
if (cls == NULL || IS_ERR(cls))
goto error;
- class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
if (!class_dev) {
retval = -ENOMEM;
goto error;
}
- memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->devt = devt;
class_dev->dev = device;
@@ -584,6 +604,7 @@ void class_device_del(struct class_device *class_dev)
{
struct class * parent = class_dev->class;
struct class_interface * class_intf;
+ char *class_name = NULL;
if (parent) {
down(&parent->sem);
@@ -594,8 +615,11 @@ void class_device_del(struct class_device *class_dev)
up(&parent->sem);
}
- if (class_dev->dev)
+ if (class_dev->dev) {
+ class_name = make_class_name(class_dev);
sysfs_remove_link(&class_dev->kobj, "device");
+ sysfs_remove_link(&class_dev->dev->kobj, class_name);
+ }
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
@@ -605,6 +629,7 @@ void class_device_del(struct class_device *class_dev)
if (parent)
class_put(parent);
+ kfree(class_name);
}
void class_device_unregister(struct class_device *class_dev)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index efe03a024a5b..6ab73f5c799a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -191,6 +191,20 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
}
}
+static void klist_children_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_parent);
+
+ get_device(dev);
+}
+
+static void klist_children_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_parent);
+
+ put_device(dev);
+}
+
/**
* device_initialize - init device structure.
@@ -207,7 +221,8 @@ void device_initialize(struct device *dev)
{
kobj_set_kset_s(dev, devices_subsys);
kobject_init(&dev->kobj);
- klist_init(&dev->klist_children);
+ klist_init(&dev->klist_children, klist_children_get,
+ klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem);
}
@@ -249,7 +264,7 @@ int device_add(struct device *dev)
if ((error = bus_add_device(dev)))
goto BusError;
if (parent)
- klist_add_tail(&parent->klist_children, &dev->knode_parent);
+ klist_add_tail(&dev->knode_parent, &parent->klist_children);
/* notify platform of device entry */
if (platform_notify)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 16323f9cbff0..d5bbce38282f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -42,7 +42,7 @@ void device_bind_driver(struct device * dev)
{
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
- klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+ klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index c4aebf2f522d..60a7ef6a201b 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -262,7 +262,8 @@ dma_pool_destroy (struct dma_pool *pool)
* If such a memory block can't be allocated, null is returned.
*/
void *
-dma_pool_alloc (struct dma_pool *pool, int mem_flags, dma_addr_t *handle)
+dma_pool_alloc (struct dma_pool *pool, unsigned int __nocast mem_flags,
+ dma_addr_t *handle)
{
unsigned long flags;
struct dma_page *page;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 291c5954a3af..ef3fe513e398 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -142,6 +142,19 @@ void put_driver(struct device_driver * drv)
kobject_put(&drv->kobj);
}
+static void klist_devices_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_driver);
+
+ get_device(dev);
+}
+
+static void klist_devices_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_driver);
+
+ put_device(dev);
+}
/**
* driver_register - register driver with bus
@@ -157,7 +170,7 @@ void put_driver(struct device_driver * drv)
*/
int driver_register(struct device_driver * drv)
{
- klist_init(&drv->klist_devices);
+ klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 652281402c92..4acb2c5733c3 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -28,6 +28,7 @@ enum {
FW_STATUS_DONE,
FW_STATUS_ABORT,
FW_STATUS_READY,
+ FW_STATUS_READY_NOHOTPLUG,
};
static int loading_timeout = 10; /* In seconds */
@@ -300,9 +301,9 @@ fw_register_class_device(struct class_device **class_dev_p,
const char *fw_name, struct device *device)
{
int retval;
- struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+ struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
- struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+ struct class_device *class_dev = kzalloc(sizeof(*class_dev),
GFP_KERNEL);
*class_dev_p = NULL;
@@ -312,8 +313,6 @@ fw_register_class_device(struct class_device **class_dev_p,
retval = -ENOMEM;
goto error_kfree;
}
- memset(fw_priv, 0, sizeof (*fw_priv));
- memset(class_dev, 0, sizeof (*class_dev));
init_completion(&fw_priv->completion);
fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -344,7 +343,7 @@ error_kfree:
static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
- const char *fw_name, struct device *device)
+ const char *fw_name, struct device *device, int hotplug)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -376,7 +375,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
goto error_unreg;
}
- set_bit(FW_STATUS_READY, &fw_priv->status);
+ if (hotplug)
+ set_bit(FW_STATUS_READY, &fw_priv->status);
+ else
+ set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
*class_dev_p = class_dev;
goto out;
@@ -386,21 +388,9 @@ out:
return retval;
}
-/**
- * request_firmware: - request firmware to hotplug and wait for it
- * Description:
- * @firmware will be used to return a firmware image by the name
- * of @name for device @device.
- *
- * Should be called from user context where sleeping is allowed.
- *
- * @name will be use as $FIRMWARE in the hotplug environment and
- * should be distinctive enough not to be confused with any other
- * firmware image for this or any other device.
- **/
-int
-request_firmware(const struct firmware **firmware_p, const char *name,
- struct device *device)
+static int
+_request_firmware(const struct firmware **firmware_p, const char *name,
+ struct device *device, int hotplug)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -410,31 +400,33 @@ request_firmware(const struct firmware **firmware_p, const char *name,
if (!firmware_p)
return -EINVAL;
- *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
__FUNCTION__);
retval = -ENOMEM;
goto out;
}
- memset(firmware, 0, sizeof (*firmware));
- retval = fw_setup_class_device(firmware, &class_dev, name, device);
+ retval = fw_setup_class_device(firmware, &class_dev, name, device,
+ hotplug);
if (retval)
goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev);
- if (loading_timeout > 0) {
- fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
- add_timer(&fw_priv->timeout);
- }
-
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
- wait_for_completion(&fw_priv->completion);
- set_bit(FW_STATUS_DONE, &fw_priv->status);
+ if (hotplug) {
+ if (loading_timeout > 0) {
+ fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
+ add_timer(&fw_priv->timeout);
+ }
- del_timer_sync(&fw_priv->timeout);
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ wait_for_completion(&fw_priv->completion);
+ set_bit(FW_STATUS_DONE, &fw_priv->status);
+ del_timer_sync(&fw_priv->timeout);
+ } else
+ wait_for_completion(&fw_priv->completion);
down(&fw_lock);
if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -455,6 +447,26 @@ out:
}
/**
+ * request_firmware: - request firmware to hotplug and wait for it
+ * Description:
+ * @firmware will be used to return a firmware image by the name
+ * of @name for device @device.
+ *
+ * Should be called from user context where sleeping is allowed.
+ *
+ * @name will be use as $FIRMWARE in the hotplug environment and
+ * should be distinctive enough not to be confused with any other
+ * firmware image for this or any other device.
+ **/
+int
+request_firmware(const struct firmware **firmware_p, const char *name,
+ struct device *device)
+{
+ int hotplug = 1;
+ return _request_firmware(firmware_p, name, device, hotplug);
+}
+
+/**
* release_firmware: - release the resource associated with a firmware image
**/
void
@@ -491,6 +503,7 @@ struct firmware_work {
struct device *device;
void *context;
void (*cont)(const struct firmware *fw, void *context);
+ int hotplug;
};
static int
@@ -503,7 +516,8 @@ request_firmware_work_func(void *arg)
return 0;
}
daemonize("%s/%s", "firmware", fw_work->name);
- request_firmware(&fw, fw_work->name, fw_work->device);
+ _request_firmware(&fw, fw_work->name, fw_work->device,
+ fw_work->hotplug);
fw_work->cont(fw, fw_work->context);
release_firmware(fw);
module_put(fw_work->module);
@@ -518,6 +532,9 @@ request_firmware_work_func(void *arg)
* Asynchronous variant of request_firmware() for contexts where
* it is not possible to sleep.
*
+ * @hotplug invokes hotplug event to copy the firmware image if this flag
+ * is non-zero else the firmware copy must be done manually.
+ *
* @cont will be called asynchronously when the firmware request is over.
*
* @context will be passed over to @cont.
@@ -527,7 +544,7 @@ request_firmware_work_func(void *arg)
**/
int
request_firmware_nowait(
- struct module *module,
+ struct module *module, int hotplug,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
@@ -548,6 +565,7 @@ request_firmware_nowait(
.device = device,
.context = context,
.cont = cont,
+ .hotplug = hotplug,
};
ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 2f455d86793c..b449dae6f0d3 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -135,7 +135,7 @@ retry:
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
- struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+ struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
int i;
if ((p == NULL) || (base == NULL)) {
@@ -144,7 +144,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
return NULL;
}
- memset(base, 0, sizeof(struct probe));
base->dev = 1;
base->range = ~0;
base->get = base_probe;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 904b27caf697..16c513aa4d48 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -39,13 +39,25 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
int n;
int nid = dev->id;
struct sysinfo i;
+ struct page_state ps;
unsigned long inactive;
unsigned long active;
unsigned long free;
si_meminfo_node(&i, nid);
+ get_page_state_node(&ps, nid);
__get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
+ /* Check for negative values in these approximate counters */
+ if ((long)ps.nr_dirty < 0)
+ ps.nr_dirty = 0;
+ if ((long)ps.nr_writeback < 0)
+ ps.nr_writeback = 0;
+ if ((long)ps.nr_mapped < 0)
+ ps.nr_mapped = 0;
+ if ((long)ps.nr_slab < 0)
+ ps.nr_slab = 0;
+
n = sprintf(buf, "\n"
"Node %d MemTotal: %8lu kB\n"
"Node %d MemFree: %8lu kB\n"
@@ -55,7 +67,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
"Node %d HighTotal: %8lu kB\n"
"Node %d HighFree: %8lu kB\n"
"Node %d LowTotal: %8lu kB\n"
- "Node %d LowFree: %8lu kB\n",
+ "Node %d LowFree: %8lu kB\n"
+ "Node %d Dirty: %8lu kB\n"
+ "Node %d Writeback: %8lu kB\n"
+ "Node %d Mapped: %8lu kB\n"
+ "Node %d Slab: %8lu kB\n",
nid, K(i.totalram),
nid, K(i.freeram),
nid, K(i.totalram - i.freeram),
@@ -64,7 +80,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
nid, K(i.totalhigh),
nid, K(i.freehigh),
nid, K(i.totalram - i.totalhigh),
- nid, K(i.freeram - i.freehigh));
+ nid, K(i.freeram - i.freehigh),
+ nid, K(ps.nr_dirty),
+ nid, K(ps.nr_writeback),
+ nid, K(ps.nr_mapped),
+ nid, K(ps.nr_slab));
n += hugetlb_report_node_meminfo(nid, buf + n);
return n;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3a5f4c991797..361e204209eb 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -225,13 +225,12 @@ struct platform_device *platform_device_register_simple(char *name, unsigned int
struct platform_object *pobj;
int retval;
- pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+ pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);
if (!pobj) {
retval = -ENOMEM;
goto error;
}
- memset(pobj, 0, sizeof(*pobj));
pobj->pdev.name = name;
pobj->pdev.id = id;
pobj->pdev.dev.release = platform_device_release_simple;
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index bdd96b03b885..0a7aa07b9a2a 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -26,11 +26,11 @@ int resume_device(struct device * dev)
down(&dev->sem);
if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
+ && dev->power.pm_parent->power.power_state.event) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
- dev->power.power_state,
+ dev->power.power_state.event,
dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
+ dev->power.pm_parent->power.power_state.event);
}
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
@@ -54,7 +54,7 @@ void dpm_resume(void)
list_add_tail(entry, &dpm_active);
up(&dpm_list_sem);
- if (!dev->power.prev_state)
+ if (!dev->power.prev_state.event)
resume_device(dev);
down(&dpm_list_sem);
put_device(dev);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 325962d80191..e8f0519f5dfa 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -13,10 +13,10 @@
static void runtime_resume(struct device * dev)
{
dev_dbg(dev, "resuming\n");
- if (!dev->power.power_state)
+ if (!dev->power.power_state.event)
return;
if (!resume_device(dev))
- dev->power.power_state = 0;
+ dev->power.power_state = PMSG_ON;
}
@@ -49,10 +49,10 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
int error = 0;
down(&dpm_sem);
- if (dev->power.power_state == state)
+ if (dev->power.power_state.event == state.event)
goto Done;
- if (dev->power.power_state)
+ if (dev->power.power_state.event)
runtime_resume(dev);
if (!(error = suspend_device(dev, state)))
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 2ccee3763acf..50501764d050 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,22 +40,22 @@ int suspend_device(struct device * dev, pm_message_t state)
int error = 0;
down(&dev->sem);
- if (dev->power.power_state) {
+ if (dev->power.power_state.event) {
dev_dbg(dev, "PM: suspend %d-->%d\n",
- dev->power.power_state, state);
+ dev->power.power_state.event, state.event);
}
if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
+ && dev->power.pm_parent->power.power_state.event) {
dev_err(dev,
"PM: suspend %d->%d, parent %s already %d\n",
- dev->power.power_state, state,
+ dev->power.power_state.event, state.event,
dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
+ dev->power.pm_parent->power.power_state.event);
}
dev->power.prev_state = dev->power.power_state;
- if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
+ if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index f82b3df9545f..8d04fb435c17 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -26,19 +26,19 @@
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
- return sprintf(buf, "%u\n", dev->power.power_state);
+ return sprintf(buf, "%u\n", dev->power.power_state.event);
}
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
- u32 state;
+ pm_message_t state;
char * rest;
int error = 0;
- state = simple_strtoul(buf, &rest, 10);
+ state.event = simple_strtoul(buf, &rest, 10);
if (*rest)
return -EINVAL;
- if (state)
+ if (state.event)
error = dpm_runtime_suspend(dev, state);
else
dpm_runtime_resume(dev);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 214b96435409..3431eb6004c3 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -288,6 +288,27 @@ void sysdev_shutdown(void)
up(&sysdev_drivers_lock);
}
+static void __sysdev_resume(struct sys_device *dev)
+{
+ struct sysdev_class *cls = dev->cls;
+ struct sysdev_driver *drv;
+
+ /* First, call the class-specific one */
+ if (cls->resume)
+ cls->resume(dev);
+
+ /* Call auxillary drivers next. */
+ list_for_each_entry(drv, &cls->drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+
+ /* Call global drivers. */
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+}
/**
* sysdev_suspend - Suspend all system devices.
@@ -305,38 +326,93 @@ void sysdev_shutdown(void)
int sysdev_suspend(pm_message_t state)
{
struct sysdev_class * cls;
+ struct sys_device *sysdev, *err_dev;
+ struct sysdev_driver *drv, *err_drv;
+ int ret;
pr_debug("Suspending System Devices\n");
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
kset.kobj.entry) {
- struct sys_device * sysdev;
pr_debug("Suspending type '%s':\n",
kobject_name(&cls->kset.kobj));
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto gbl_driver;
+ }
}
/* Call auxillary drivers next. */
list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto aux_driver;
+ }
}
/* Now call the generic one */
- if (cls->suspend)
- cls->suspend(sysdev, state);
+ if (cls->suspend) {
+ ret = cls->suspend(sysdev, state);
+ if (ret)
+ goto cls_driver;
+ }
}
}
return 0;
+ /* resume current sysdev */
+cls_driver:
+ drv = NULL;
+ printk(KERN_ERR "Class suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+
+aux_driver:
+ if (drv)
+ printk(KERN_ERR "Class driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &cls->drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ drv = NULL;
+
+gbl_driver:
+ if (drv)
+ printk(KERN_ERR "sysdev driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &sysdev_drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ /* resume other sysdevs in current class */
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ if (err_dev == sysdev)
+ break;
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ __sysdev_resume(err_dev);
+ }
+
+ /* resume other classes */
+ list_for_each_entry_continue(cls, &system_subsys.kset.list,
+ kset.kobj.entry) {
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ __sysdev_resume(err_dev);
+ }
+ }
+ return ret;
}
@@ -362,25 +438,9 @@ int sysdev_resume(void)
kobject_name(&cls->kset.kobj));
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
- /* First, call the class-specific one */
- if (cls->resume)
- cls->resume(sysdev);
-
- /* Call auxillary drivers next. */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
- /* Call global drivers. */
- list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
+ __sysdev_resume(sysdev);
}
}
return 0;
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 6c2b447a3336..f25e7c6b2d27 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -7,7 +7,7 @@
* This file is licensed under GPLv2
*
* The basic idea here is to allow any "device controller" (which
- * would most often be a Host Bus Adapter" to use the services of one
+ * would most often be a Host Bus Adapter to use the services of one
* or more tranport classes for performing transport specific
* services. Transport specific services are things that the generic
* command layer doesn't want to know about (speed settings, line
@@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
}
EXPORT_SYMBOL_GPL(transport_class_unregister);
-static int anon_transport_dummy_function(struct device *dev)
+static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
/* do nothing */
return 0;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
struct class_device *classdev)
{
struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
if (tclass->setup)
- tclass->setup(dev);
+ tclass->setup(tcont, dev, classdev);
return 0;
}
@@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
EXPORT_SYMBOL_GPL(transport_add_device);
static int transport_configure(struct attribute_container *cont,
- struct device *dev)
+ struct device *dev,
+ struct class_device *cdev)
{
struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
if (tclass->configure)
- tclass->configure(dev);
+ tclass->configure(tcont, dev, cdev);
return 0;
}
@@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
*/
void transport_configure_device(struct device *dev)
{
- attribute_container_trigger(dev, transport_configure);
+ attribute_container_device_trigger(dev, transport_configure);
}
EXPORT_SYMBOL_GPL(transport_configure_device);
@@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
struct transport_class *tclass = class_to_transport_class(cont->class);
if (tclass->remove)
- tclass->remove(dev);
+ tclass->remove(tcont, dev, classdev);
if (tclass->remove != anon_transport_dummy_function) {
if (tcont->statistics)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b594768b0241..51b0af1cebee 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -6,7 +6,7 @@ menu "Block devices"
config BLK_DEV_FD
tristate "Normal floppy disk support"
- depends on (!ARCH_S390 && !M68K && !IA64 && !UML && !ARM) || Q40 || (SUN3X && BROKEN) || ARCH_RPC || ARCH_EBSA285
+ depends on ARCH_MAY_HAVE_PC_FDC
---help---
If you want to use the floppy disk drive(s) of your PC under Linux,
say Y. Information about this driver, especially important for IBM
@@ -408,54 +408,12 @@ config BLK_DEV_INITRD
"real" root file system, etc. See <file:Documentation/initrd.txt>
for details.
-config INITRAMFS_SOURCE
- string "Initramfs source file(s)"
- default ""
- help
- This can be either a single cpio archive with a .cpio suffix or a
- space-separated list of directories and files for building the
- initramfs image. A cpio archive should contain a filesystem archive
- to be used as an initramfs image. Directories should contain a
- filesystem layout to be included in the initramfs image. Files
- should contain entries according to the format described by the
- "usr/gen_init_cpio" program in the kernel tree.
-
- When multiple directories and files are specified then the
- initramfs image will be the aggregate of all of them.
-
- See <file:Documentation/early-userspace/README for more details.
-
- If you are not sure, leave it blank.
-
-config INITRAMFS_ROOT_UID
- int "User ID to map to 0 (user root)"
- depends on INITRAMFS_SOURCE!=""
- default "0"
- help
- This setting is only meaningful if the INITRAMFS_SOURCE is
- contains a directory. Setting this user ID (UID) to something
- other than "0" will cause all files owned by that UID to be
- owned by user root in the initial ramdisk image.
-
- If you are not sure, leave it set to "0".
-
-config INITRAMFS_ROOT_GID
- int "Group ID to map to 0 (group root)"
- depends on INITRAMFS_SOURCE!=""
- default "0"
- help
- This setting is only meaningful if the INITRAMFS_SOURCE is
- contains a directory. Setting this group ID (GID) to something
- other than "0" will cause all files owned by that GID to be
- owned by group root in the initial ramdisk image.
-
- If you are not sure, leave it set to "0".
#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64
#for instance.
config LBD
bool "Support for Large Block Devices"
- depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH || UML
+ depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
help
Say Y here if you want to attach large (bigger than 2TB) discs to
your machine, or if you want to have a raid or loopback device
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index ce933de48084..0e1f34fef0c8 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -371,7 +371,7 @@ static int acsi_revalidate (struct gendisk *disk);
/************************* End of Prototypes **************************/
-struct timer_list acsi_timer = TIMER_INITIALIZER(acsi_times_out, 0, 0);
+DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
#ifdef CONFIG_ATARI_SLM
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index e3be8c31a74c..a5c1c8e871ec 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -268,7 +268,7 @@ static int slm_get_pagesize( int device, int *w, int *h );
/************************* End of Prototypes **************************/
-static struct timer_list slm_timer = TIMER_INITIALIZER(slm_test_ready, 0, 0);
+static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
static struct file_operations slm_fops = {
.owner = THIS_MODULE,
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 721ba8086043..0e9e586e9ba3 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
-#define VERSION "10"
+#define VERSION "12"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
@@ -7,12 +7,12 @@
* default is 16, which is 15 partitions plus the whole disk
*/
#ifndef AOE_PARTITIONS
-#define AOE_PARTITIONS 16
+#define AOE_PARTITIONS (16)
#endif
-#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor))
-#define AOEMAJOR(sysminor) ((sysminor) / 10)
-#define AOEMINOR(sysminor) ((sysminor) % 10)
+#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
+#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
+#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
#define WHITESPACE " \t\v\f\n"
enum {
@@ -83,7 +83,7 @@ enum {
enum {
MAXATADATA = 1024,
- NPERSHELF = 10,
+ NPERSHELF = 16, /* number of slots per shelf address */
FREETAG = -1,
MIN_BUFS = 8,
};
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 6e231c5a1199..ded33ba31acc 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -35,7 +35,7 @@ aoedev_newdev(ulong nframes)
struct aoedev *d;
struct frame *f, *e;
- d = kcalloc(1, sizeof *d, GFP_ATOMIC);
+ d = kzalloc(sizeof *d, GFP_ATOMIC);
if (d == NULL)
return NULL;
f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 9e6f51c528b0..4be976940f69 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -120,7 +120,7 @@ aoenet_xmit(struct sk_buff *sl)
* (1) len doesn't include the header by default. I want this.
*/
static int
-aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt)
+aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
{
struct aoe_hdr *h;
u32 n;
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index db05a5a99f35..22bda05fc693 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -371,16 +371,10 @@ static int floppy_release( struct inode * inode, struct file * filp );
/************************* End of Prototypes **************************/
-static struct timer_list motor_off_timer =
- TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
-static struct timer_list readtrack_timer =
- TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
-
-static struct timer_list timeout_timer =
- TIMER_INITIALIZER(fd_times_out, 0, 0);
-
-static struct timer_list fd_timer =
- TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
static inline void start_motor_off_timer(void)
{
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 418b1469d75d..c56f995aadad 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -47,14 +47,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.8)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600 P800 E400 E300");
+ " SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -83,12 +83,22 @@ static const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x4091, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
0x103C, 0x3225, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
0x103c, 0x3223, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3231, 0, 0, 0},
+ 0x103c, 0x3234, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3233, 0, 0, 0},
+ 0x103c, 0x3235, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3211, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3212, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3213, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3214, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3215, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -111,8 +121,13 @@ static struct board_type products[] = {
{ 0x40910E11, "Smart Array 6i", &SA5_access},
{ 0x3225103C, "Smart Array P600", &SA5_access},
{ 0x3223103C, "Smart Array P800", &SA5_access},
- { 0x3231103C, "Smart Array E400", &SA5_access},
- { 0x3233103C, "Smart Array E300", &SA5_access},
+ { 0x3234103C, "Smart Array P400", &SA5_access},
+ { 0x3235103C, "Smart Array P400i", &SA5_access},
+ { 0x3211103C, "Smart Array E200i", &SA5_access},
+ { 0x3212103C, "Smart Array E200", &SA5_access},
+ { 0x3213103C, "Smart Array E200i", &SA5_access},
+ { 0x3214103C, "Smart Array E200i", &SA5_access},
+ { 0x3215103C, "Smart Array E200i", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
@@ -140,15 +155,26 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
-static int deregister_disk(struct gendisk *disk);
-static int register_new_disk(ctlr_info_t *h);
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
+static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+ int withirq, unsigned int *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, unsigned int total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
+ drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+ unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
+ int cmd_type);
+
+static void fail_all_cmds(unsigned long ctlr);
#ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
@@ -265,7 +291,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
for(i=0; i<=h->highest_lun; i++) {
drv = &h->drv[i];
- if (drv->block_size == 0)
+ if (drv->heads == 0)
continue;
vol_sz = drv->nr_blocks;
@@ -363,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL;
memset(c, 0, sizeof(CommandList_struct));
+ c->cmdindex = -1;
+
c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle);
@@ -393,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct);
h->nr_allocs++;
+
+ c->cmdindex = i;
}
c->busaddr = (__u32) cmd_dma_handle;
@@ -453,6 +483,11 @@ static int cciss_open(struct inode *inode, struct file *filep)
printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
+ if (host->busy_initializing)
+ return -EBUSY;
+
+ if (host->busy_initializing || drv->busy_configuring)
+ return -EBUSY;
/*
* Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. Root is also allowed to open any
@@ -796,10 +831,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return(0);
}
case CCISS_DEREGDISK:
- return deregister_disk(disk);
+ return rebuild_lun_table(host, disk);
case CCISS_REGNEWD:
- return register_new_disk(host);
+ return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU:
{
@@ -1143,48 +1178,323 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
-static int deregister_disk(struct gendisk *disk)
+/* 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
+ * left alone for the next reboot. The exception to this is disk 0 which
+ * will always be left registered with the kernel since it is also the
+ * controller node. Any changes to disk 0 will show up on the next
+ * reboot.
+*/
+static void cciss_update_drive_info(int ctlr, int drv_index)
+ {
+ ctlr_info_t *h = hba[ctlr];
+ struct gendisk *disk;
+ ReadCapdata_struct *size_buff = NULL;
+ InquiryData_struct *inq_buff = NULL;
+ unsigned int block_size;
+ unsigned int total_size;
+ unsigned long flags = 0;
+ int ret = 0;
+
+ /* if the disk already exists then deregister it before proceeding*/
+ if (h->drv[drv_index].raid_level != -1){
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ h->drv[drv_index].busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ ret = deregister_disk(h->gendisk[drv_index],
+ &h->drv[drv_index], 0);
+ h->drv[drv_index].busy_configuring = 0;
+ }
+
+ /* If the disk is in use return */
+ if (ret)
+ return;
+
+
+ /* Get information about the disk and modify the driver sturcture */
+ size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL)
+ goto mem_msg;
+ inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL)
+ goto mem_msg;
+
+ cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ &total_size, &block_size);
+ cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+ inq_buff, &h->drv[drv_index]);
+
+ ++h->num_luns;
+ disk = h->gendisk[drv_index];
+ set_capacity(disk, h->drv[drv_index].nr_blocks);
+
+
+ /* if it's the controller it's already added */
+ if (drv_index){
+ disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+
+ /* Set up queue information */
+ disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
+ blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
+
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+
+ blk_queue_max_sectors(disk->queue, 512);
+
+ disk->queue->queuedata = hba[ctlr];
+
+ blk_queue_hardsect_size(disk->queue,
+ hba[ctlr]->drv[drv_index].block_size);
+
+ h->drv[drv_index].queue = disk->queue;
+ add_disk(disk);
+ }
+
+freeret:
+ kfree(size_buff);
+ kfree(inq_buff);
+ return;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will find the first index of the controllers drive array
+ * that has a -1 for the raid_level and will return that index. This is
+ * where new drives will be added. If the index to be returned is greater
+ * than the highest_lun index for the controller then highest_lun is set
+ * to this new index. If there are no available indexes then -1 is returned.
+*/
+static int cciss_find_free_drive_index(int ctlr)
{
+ int i;
+
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if (hba[ctlr]->drv[i].raid_level == -1){
+ if (i > hba[ctlr]->highest_lun)
+ hba[ctlr]->highest_lun = i;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* This function will add and remove logical drives from the Logical
+ * drive array of the controller and maintain persistancy of ordering
+ * so that mount points are preserved until the next reboot. This allows
+ * for the removal of logical drives in the middle of the drive array
+ * without a re-ordering of those drives.
+ * INPUT
+ * h = The controller to perform the operations on
+ * del_disk = The disk to remove if specified. If the value given
+ * is NULL then no disk is removed.
+*/
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
+{
+ int ctlr = h->ctlr;
+ int num_luns;
+ ReportLunData_struct *ld_buff = NULL;
+ drive_info_struct *drv = NULL;
+ int return_code;
+ int listlength = 0;
+ int i;
+ int drv_found;
+ int drv_index = 0;
+ __u32 lunid = 0;
unsigned long flags;
+
+ /* Set busy_configuring flag for this operation */
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ if (h->num_luns >= CISS_MAX_LUN){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EINVAL;
+ }
+
+ if (h->busy_configuring){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EBUSY;
+ }
+ h->busy_configuring = 1;
+
+ /* if del_disk is NULL then we are being called to add a new disk
+ * and update the logical drive table. If it is not NULL then
+ * we will check if the disk is in use or not.
+ */
+ if (del_disk != NULL){
+ drv = get_drv(del_disk);
+ drv->busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return_code = deregister_disk(del_disk, drv, 1);
+ drv->busy_configuring = 0;
+ h->busy_configuring = 0;
+ return return_code;
+ } else {
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ if (ld_buff == NULL)
+ goto mem_msg;
+
+ return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
+ sizeof(ReportLunData_struct), 0, 0, 0,
+ TYPE_CMD);
+
+ if (return_code == IO_OK){
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
+ listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+ } else{ /* reading number of logical volumes failed */
+ printk(KERN_WARNING "cciss: report logical volume"
+ " command failed\n");
+ listlength = 0;
+ goto freeret;
+ }
+
+ num_luns = listlength / 8; /* 8 bytes per entry */
+ if (num_luns > CISS_MAX_LUN){
+ num_luns = CISS_MAX_LUN;
+ printk(KERN_WARNING "cciss: more luns configured"
+ " on controller than can be handled by"
+ " this driver.\n");
+ }
+
+ /* Compare controller drive array to drivers drive array.
+ * Check for updates in the drive information and any new drives
+ * on the controller.
+ */
+ for (i=0; i < num_luns; i++){
+ int j;
+
+ drv_found = 0;
+
+ lunid = (0xff &
+ (unsigned int)(ld_buff->LUN[i][3])) << 24;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][2])) << 16;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ lunid |= 0xff &
+ (unsigned int)(ld_buff->LUN[i][0]);
+
+ /* Find if the LUN is already in the drive array
+ * of the controller. If so then update its info
+ * if not is use. If it does not exist then find
+ * the first free index and add it.
+ */
+ for (j=0; j <= h->highest_lun; j++){
+ if (h->drv[j].LunID == lunid){
+ drv_index = j;
+ drv_found = 1;
+ }
+ }
+
+ /* check if the drive was found already in the array */
+ if (!drv_found){
+ drv_index = cciss_find_free_drive_index(ctlr);
+ if (drv_index == -1)
+ goto freeret;
+
+ }
+ h->drv[drv_index].LunID = lunid;
+ cciss_update_drive_info(ctlr, drv_index);
+ } /* end for */
+ } /* end else */
+
+freeret:
+ kfree(ld_buff);
+ h->busy_configuring = 0;
+ /* We return -1 here to tell the ACU that we have registered/updated
+ * all of the drives that we can and to keep it from calling us
+ * additional times.
+ */
+ return -1;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will deregister the disk and it's queue from the
+ * kernel. It must be called with the controller lock held and the
+ * drv structures busy_configuring flag set. It's parameters are:
+ *
+ * disk = This is the disk to be deregistered
+ * drv = This is the drive_info_struct associated with the disk to be
+ * deregistered. It contains information about the disk used
+ * by the driver.
+ * clear_all = This flag determines whether or not the disk information
+ * is going to be completely cleared out and the highest_lun
+ * reset. Sometimes we want to clear out information about
+ * the disk in preperation for re-adding it. In this case
+ * the highest_lun should be left unchanged and the LunID
+ * should not be cleared.
+*/
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+ int clear_all)
+{
ctlr_info_t *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
- int ctlr = h->ctlr;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
/* make sure logical volume is NOT is use */
- if( drv->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if(clear_all || (h->gendisk[0] == disk)) {
+ if (drv->usage_count > 1)
return -EBUSY;
}
- drv->usage_count++;
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ else
+ if( drv->usage_count > 0 )
+ return -EBUSY;
- /* invalidate the devices and deregister the disk */
- if (disk->flags & GENHD_FL_UP)
+ /* invalidate the devices and deregister the disk. If it is disk
+ * zero do not deregister it but just zero out it's values. This
+ * allows us to delete disk zero but keep the controller registered.
+ */
+ if (h->gendisk[0] != disk){
+ if (disk->flags & GENHD_FL_UP){
+ blk_cleanup_queue(disk->queue);
del_gendisk(disk);
+ drv->queue = NULL;
+ }
+ }
+
+ --h->num_luns;
+ /* zero out the disk size info */
+ drv->nr_blocks = 0;
+ drv->block_size = 0;
+ drv->heads = 0;
+ drv->sectors = 0;
+ drv->cylinders = 0;
+ drv->raid_level = -1; /* This can be used as a flag variable to
+ * indicate that this element of the drive
+ * array is free.
+ */
+
+ if (clear_all){
/* check to see if it was the last disk */
if (drv == h->drv + h->highest_lun) {
/* if so, find the new hightest lun */
int i, newhighest =-1;
for(i=0; i<h->highest_lun; i++) {
/* if the disk has size > 0, it is available */
- if (h->drv[i].nr_blocks)
+ if (h->drv[i].heads)
newhighest = i;
}
h->highest_lun = newhighest;
-
}
- --h->num_luns;
- /* zero out the disk size info */
- drv->nr_blocks = 0;
- drv->block_size = 0;
- drv->cylinders = 0;
+
drv->LunID = 0;
+ }
return(0);
}
+
static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
size_t size,
unsigned int use_unit_num, /* 0: address the controller,
@@ -1420,8 +1730,10 @@ case CMD_HARDWARE_ERR:
}
}
/* unlock the buffers from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(h, c, 0);
return(return_status);
@@ -1495,164 +1807,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
return;
}
-static int register_new_disk(ctlr_info_t *h)
-{
- struct gendisk *disk;
- int ctlr = h->ctlr;
- int i;
- int num_luns;
- int logvol;
- int new_lun_found = 0;
- int new_lun_index = 0;
- int free_index_found = 0;
- int free_index = 0;
- ReportLunData_struct *ld_buff = NULL;
- ReadCapdata_struct *size_buff = NULL;
- InquiryData_struct *inq_buff = NULL;
- int return_code;
- int listlength = 0;
- __u32 lunid = 0;
- unsigned int block_size;
- unsigned int total_size;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- /* if we have no space in our disk array left to add anything */
- if( h->num_luns >= CISS_MAX_LUN)
- return -EINVAL;
-
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
- if (ld_buff == NULL)
- goto mem_msg;
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- goto mem_msg;
-
- return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
- sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
-
- if( return_code == IO_OK)
- {
-
- // printk("LUN Data\n--------------------------\n");
-
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
- listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
- } else /* reading number of logical volumes failed */
- {
- printk(KERN_WARNING "cciss: report logical volume"
- " command failed\n");
- listlength = 0;
- goto free_err;
- }
- num_luns = listlength / 8; // 8 bytes pre entry
- if (num_luns > CISS_MAX_LUN)
- {
- num_luns = CISS_MAX_LUN;
- }
-#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
- ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
- ld_buff->LUNListLength[3], num_luns);
-#endif
- for(i=0; i< num_luns; i++)
- {
- int j;
- int lunID_found = 0;
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
- lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-
- /* check to see if this is a new lun */
- for(j=0; j <= h->highest_lun; j++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
- lunid);
-#endif /* CCISS_DEBUG */
- if (h->drv[j].LunID == lunid)
- {
- lunID_found = 1;
- break;
- }
-
- }
- if( lunID_found == 1)
- continue;
- else
- { /* It is the new lun we have been looking for */
-#ifdef CCISS_DEBUG
- printk("new lun found at %d\n", i);
-#endif /* CCISS_DEBUG */
- new_lun_index = i;
- new_lun_found = 1;
- break;
- }
- }
- if (!new_lun_found)
- {
- printk(KERN_WARNING "cciss: New Logical Volume not found\n");
- goto free_err;
- }
- /* Now find the free index */
- for(i=0; i <CISS_MAX_LUN; i++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking Index %d\n", i);
-#endif /* CCISS_DEBUG */
- if(h->drv[i].LunID == 0)
- {
-#ifdef CCISS_DEBUG
- printk("free index found at %d\n", i);
-#endif /* CCISS_DEBUG */
- free_index_found = 1;
- free_index = i;
- break;
- }
- }
- if (!free_index_found)
- {
- printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
- goto free_err;
- }
-
- logvol = free_index;
- h->drv[logvol].LunID = lunid;
- /* there could be gaps in lun numbers, track hightest */
- if(h->highest_lun < lunid)
- h->highest_lun = logvol;
- cciss_read_capacity(ctlr, logvol, size_buff, 1,
- &total_size, &block_size);
- cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
- inq_buff, &h->drv[logvol]);
- h->drv[logvol].usage_count = 0;
- ++h->num_luns;
- /* setup partitions per disk */
- disk = h->gendisk[logvol];
- set_capacity(disk, h->drv[logvol].nr_blocks);
- /* if it's the controller it's already added */
- if(logvol)
- add_disk(disk);
-freeret:
- kfree(ld_buff);
- kfree(size_buff);
- kfree(inq_buff);
- return (logvol);
-mem_msg:
- printk(KERN_ERR "cciss: out of memory\n");
-free_err:
- logvol = -1;
- goto freeret;
-}
-
static int cciss_revalidate(struct gendisk *disk)
{
ctlr_info_t *h = get_host(disk);
@@ -1713,10 +1867,9 @@ static unsigned long pollcomplete(int ctlr)
for (i = 20 * HZ; i > 0; i--) {
done = hba[ctlr]->access.command_completed(hba[ctlr]);
- if (done == FIFO_EMPTY) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } else
+ if (done == FIFO_EMPTY)
+ schedule_timeout_uninterruptible(1);
+ else
return (done);
}
/* Invalid address to tell caller we ran out of time */
@@ -1860,8 +2013,10 @@ resend_cmd1:
cleanup1:
/* unlock the data buffer from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(info_p, c, 1);
return (status);
}
@@ -2112,7 +2267,11 @@ queue:
/* fill in the request */
drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode
- c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
+ /* got command from pool, so use the command block index instead */
+ /* for direct lookups. */
+ /* The first 2 bits are reserved for controller error reporting. */
+ c->Header.Tag.lower = (c->cmdindex << 3);
+ c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
@@ -2187,7 +2346,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
ctlr_info_t *h = dev_id;
CommandList_struct *c;
unsigned long flags;
- __u32 a, a1;
+ __u32 a, a1, a2;
int j;
int start_queue = h->next_to_run;
@@ -2205,10 +2364,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{
a1 = a;
+ if ((a & 0x04)) {
+ a2 = (a >> 3);
+ if (a2 >= NR_CMDS) {
+ printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+ fail_all_cmds(h->ctlr);
+ return IRQ_HANDLED;
+ }
+
+ c = h->cmd_pool + a2;
+ a = c->busaddr;
+
+ } else {
a &= ~3;
- if ((c = h->cmpQ) == NULL)
- {
- printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
+ if ((c = h->cmpQ) == NULL) {
+ printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
continue;
}
while(c->busaddr != a) {
@@ -2216,6 +2386,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
if (c == h->cmpQ)
break;
}
+ }
/*
* If we've found the command, take it off the
* completion Q and free it
@@ -2635,12 +2806,16 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
- for(i=0; i< hba[cntl_num]->num_luns; i++)
+// for(i=0; i< hba[cntl_num]->num_luns; i++)
+ for(i=0; i < CISS_MAX_LUN; i++)
{
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ if (i < hba[cntl_num]->num_luns){
+ lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+ << 24;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+ << 16;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+ << 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
hba[cntl_num]->drv[i].LunID = lunid;
@@ -2648,13 +2823,18 @@ static void cciss_getgeometry(int cntl_num)
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
- ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2],
- ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
+ ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+ ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+ hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
&total_size, &block_size);
- cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
- inq_buff, &hba[cntl_num]->drv[i]);
+ cciss_geometry_inquiry(cntl_num, i, 0, total_size,
+ block_size, inq_buff, &hba[cntl_num]->drv[i]);
+ } else {
+ /* initialize raid_level to indicate a free space */
+ hba[cntl_num]->drv[i].raid_level = -1;
+ }
}
kfree(ld_buff);
kfree(size_buff);
@@ -2728,6 +2908,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
i = alloc_cciss_hba();
if(i < 0)
return (-1);
+
+ hba[i]->busy_initializing = 1;
+
if (cciss_pci_init(hba[i], pdev) != 0)
goto clean1;
@@ -2850,6 +3033,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
add_disk(disk);
}
+ hba[i]->busy_initializing = 0;
return(1);
clean4:
@@ -2870,6 +3054,7 @@ clean2:
clean1:
release_io_mem(hba[i]);
free_hba(i);
+ hba[i]->busy_initializing = 0;
return(-1);
}
@@ -2914,9 +3099,10 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
- if (disk->flags & GENHD_FL_UP)
- blk_cleanup_queue(disk->queue);
+ if (disk->flags & GENHD_FL_UP) {
del_gendisk(disk);
+ blk_cleanup_queue(disk->queue);
+ }
}
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
@@ -2965,5 +3151,43 @@ static void __exit cciss_cleanup(void)
remove_proc_entry("cciss", proc_root_driver);
}
+static void fail_all_cmds(unsigned long ctlr)
+{
+ /* If we get here, the board is apparently dead. */
+ ctlr_info_t *h = hba[ctlr];
+ CommandList_struct *c;
+ unsigned long flags;
+
+ printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
+ h->alive = 0; /* the controller apparently died... */
+
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+ pci_disable_device(h->pdev); /* Make sure it is really dead. */
+
+ /* move everything off the request queue onto the completed queue */
+ while( (c = h->reqQ) != NULL ) {
+ removeQ(&(h->reqQ), c);
+ h->Qdepth--;
+ addQ (&(h->cmpQ), c);
+ }
+
+ /* Now, fail everything on the completed queue with a HW error */
+ while( (c = h->cmpQ) != NULL ) {
+ removeQ(&h->cmpQ, c);
+ c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+ if (c->cmd_type == CMD_RWREQ) {
+ complete_command(h, c, 0);
+ } else if (c->cmd_type == CMD_IOCTL_PEND)
+ complete(c->waiting);
+#ifdef CONFIG_CISS_SCSI_TAPE
+ else if (c->cmd_type == CMD_SCSI)
+ complete_scsi_command(c, 0, 0);
+#endif
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ return;
+}
+
module_init(cciss_init);
module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 566587d0a500..ef277baee9fd 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct
int heads;
int sectors;
int cylinders;
- int raid_level;
+ int raid_level; /* set to -1 to indicate that
+ * the drive is not in use/configured
+ */
+ int busy_configuring; /*This is set when the drive is being removed
+ *to prevent it from being opened or it's queue
+ *from being started.
+ */
} drive_info_struct;
struct ctlr_info
@@ -83,6 +89,7 @@ struct ctlr_info
int nr_allocs;
int nr_frees;
int busy_configuring;
+ int busy_initializing;
/* This element holds the zero based queue number of the last
* queue to be started. It is used for fairness.
@@ -94,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif
+ unsigned char alive;
};
/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a88817623..53fea549ba8b 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04
#define CMD_MSG_TIMEOUT 0x05
+/* This structure needs to be divisible by 8 for new
+ * indexing method.
+ */
+#define PADSIZE (sizeof(long) - 4)
typedef struct _CommandList_struct {
CommandListHeader_struct Header;
RequestBlock_struct Request;
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr;
int cmd_type;
+ long cmdindex;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
struct request * rq;
struct completion *waiting;
int retry_count;
-#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd;
-#endif
+ char pad[PADSIZE];
} CommandList_struct;
//Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3caed58a..e183a3ef7839 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd;
ErrorInfo_struct Err;
__u32 busaddr;
+ __u32 pad;
};
#pragma pack()
@@ -877,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
- InquiryData_struct *buf)
+ unsigned char *buf, unsigned char bufsize)
{
int rc;
CommandList_struct *cp;
@@ -900,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
cdb[1] = 0;
cdb[2] = 0;
cdb[3] = 0;
- cdb[4] = sizeof(*buf) & 0xff;
+ cdb[4] = bufsize;
cdb[5] = 0;
rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
- 6, (unsigned char *) buf,
- sizeof(*buf), XFER_READ);
+ 6, buf, bufsize, XFER_READ);
if (rc != 0) return rc; /* something went wrong */
@@ -1000,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
that though.
*/
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
ReportLunData_struct *ld_buff;
- InquiryData_struct *inq_buff;
+ unsigned char *inq_buff;
unsigned char scsi3addr[8];
ctlr_info_t *c;
__u32 num_luns=0;
@@ -1020,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
return;
}
memset(ld_buff, 0, reportlunsize);
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
@@ -1051,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
/* for each physical lun, do an inquiry */
if (ld_buff->LUN[i][3] & 0xC0) continue;
- memset(inq_buff, 0, sizeof(InquiryData_struct));
+ memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
- if (cciss_scsi_do_inquiry(hba[cntl_num],
- scsi3addr, inq_buff) != 0)
- {
+ if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
+ (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
/* Inquiry failed (msg printed already) */
devtype = 0; /* so we will skip this device. */
} else /* what kind of device is this? */
- devtype = (inq_buff->data_byte[0] & 0x1f);
+ devtype = (inq_buff[0] & 0x1f);
switch (devtype)
{
+ case 0x05: /* CD-ROM */ {
+
+ /* We don't *really* support actual CD-ROM devices,
+ * just this "One Button Disaster Recovery" tape drive
+ * which temporarily pretends to be a CD-ROM drive.
+ * So we check that the device is really an OBDR tape
+ * device by checking for "$DR-10" in bytes 43-48 of
+ * the inquiry data.
+ */
+ char obdr_sig[7];
+
+ strncpy(obdr_sig, &inq_buff[43], 6);
+ obdr_sig[6] = '\0';
+ if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+ /* Not OBDR device, ignore it. */
+ break;
+ }
+ /* fall through . . . */
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1144,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
int buflen, datalen;
ctlr_info_t *ci;
+ int i;
int cntl_num;
@@ -1136,8 +1155,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
cntl_num = ci->ctlr; /* Get our index into the hba[] array */
if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
- buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no);
-
+ buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
+ cntl_num, sh->host_no);
+
+ /* this information is needed by apps to know which cciss
+ device corresponds to which scsi host number without
+ having to open a scsi target device node. The device
+ information is not a duplicate of /proc/scsi/scsi because
+ the two may be out of sync due to scsi hotplug, rather
+ this info is for an app to be able to use to know how to
+ get them back in sync. */
+
+ for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
+ struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
+ buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ sh->host_no, sd->bus, sd->target, sd->lun,
+ sd->devtype,
+ sd->scsi3addr[0], sd->scsi3addr[1],
+ sd->scsi3addr[2], sd->scsi3addr[3],
+ sd->scsi3addr[4], sd->scsi3addr[5],
+ sd->scsi3addr[6], sd->scsi3addr[7]);
+ }
datalen = buflen - offset;
if (datalen < 0) { /* they're reading past EOF. */
datalen = 0;
@@ -1399,7 +1438,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
CPQ_TAPE_LOCK(ctlr, flags);
size = sprintf(buffer + *len,
- " Sequential access devices: %d\n\n",
+ "Sequential access devices: %d\n\n",
ccissscsi[ctlr].ndevices);
CPQ_TAPE_UNLOCK(ctlr, flags);
*pos += size; *len += size;
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
index 5be6f998d8c5..3d4261c39f16 100644
--- a/drivers/block/cryptoloop.c
+++ b/drivers/block/cryptoloop.c
@@ -57,9 +57,11 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
mode = strsep(&cmsp, "-");
if (mode == NULL || strcmp(mode, "cbc") == 0)
- tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC);
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
else if (strcmp(mode, "ecb") == 0)
- tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB);
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL)
return -EINVAL;
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index ff5201e02153..52a3ae5289a0 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -507,18 +507,15 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
const int reads = !list_empty(&dd->fifo_list[READ]);
const int writes = !list_empty(&dd->fifo_list[WRITE]);
struct deadline_rq *drq;
- int data_dir, other_dir;
+ int data_dir;
/*
* batches are currently reads XOR writes
*/
- drq = NULL;
-
- if (dd->next_drq[READ])
- drq = dd->next_drq[READ];
-
if (dd->next_drq[WRITE])
drq = dd->next_drq[WRITE];
+ else
+ drq = dd->next_drq[READ];
if (drq) {
/* we have a "next request" */
@@ -544,7 +541,6 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
goto dispatch_writes;
data_dir = READ;
- other_dir = WRITE;
goto dispatch_find_request;
}
@@ -560,7 +556,6 @@ dispatch_writes:
dd->starved = 0;
data_dir = WRITE;
- other_dir = READ;
goto dispatch_find_request;
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f0c1084b840f..00895477155e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -493,6 +493,8 @@ static struct floppy_struct user_params[N_DRIVE];
static sector_t floppy_sizes[256];
+static char floppy_device_name[] = "floppy";
+
/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
@@ -626,7 +628,7 @@ static inline void debugt(const char *message) { }
#endif /* DEBUGT */
typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
static const char *timeout_message;
@@ -1010,7 +1012,7 @@ static void schedule_bh(void (*handler) (void))
schedule_work(&floppy_work);
}
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
static void cancel_activity(void)
{
@@ -4191,18 +4193,24 @@ static int __init floppy_setup(char *str)
static int have_no_fdc = -ENODEV;
+static ssize_t floppy_cmos_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *p;
+ int drive;
+
+ p = container_of(dev, struct platform_device,dev);
+ drive = p->id;
+ return sprintf(buf, "%X\n", UDP->cmos);
+}
+DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
static void floppy_device_release(struct device *dev)
{
complete(&device_release);
}
-static struct platform_device floppy_device = {
- .name = "floppy",
- .id = 0,
- .dev = {
- .release = floppy_device_release,
- }
-};
+static struct platform_device floppy_device[N_DRIVE];
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{
@@ -4370,20 +4378,26 @@ static int __init floppy_init(void)
goto out_flush_work;
}
- err = platform_device_register(&floppy_device);
- if (err)
- goto out_flush_work;
-
for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive)))
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
+
+ floppy_device[drive].name = floppy_device_name;
+ floppy_device[drive].id = drive;
+ floppy_device[drive].dev.release = floppy_device_release;
+
+ err = platform_device_register(&floppy_device[drive]);
+ if (err)
+ goto out_flush_work;
+
+ device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
/* to be cleaned up... */
disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
- disks[drive]->driverfs_dev = &floppy_device.dev;
+ disks[drive]->driverfs_dev = &floppy_device[drive].dev;
add_disk(disks[drive]);
}
@@ -4603,10 +4617,11 @@ void cleanup_module(void)
fdc_state[FDC(drive)].version != FDC_NONE) {
del_gendisk(disks[drive]);
unregister_devfs_entries(drive);
+ device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+ platform_device_unregister(&floppy_device[drive]);
}
put_disk(disks[drive]);
}
- platform_device_unregister(&floppy_device);
devfs_remove("floppy");
del_timer_sync(&fd_timeout);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 47fd3659a061..d42840cc0d1d 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -45,7 +45,7 @@ int get_blkdev_list(char *p, int used)
struct blk_major_name *n;
int i, len;
- len = sprintf(p, "\nBlock devices:\n");
+ len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n");
down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 3c818544475e..483d71b10cf9 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -235,8 +235,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
* set defaults
*/
q->nr_requests = BLKDEV_MAX_RQ;
- q->max_phys_segments = MAX_PHYS_SEGMENTS;
- q->max_hw_segments = MAX_HW_SEGMENTS;
+ blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+ blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
q->make_request_fn = mfn;
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
@@ -284,6 +284,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
rq->special = NULL;
rq->data_len = 0;
rq->data = NULL;
+ rq->nr_phys_segments = 0;
rq->sense = NULL;
rq->end_io = NULL;
rq->end_io_data = NULL;
@@ -2115,7 +2116,7 @@ EXPORT_SYMBOL(blk_insert_request);
/**
* blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
* @q: request queue where request should be inserted
- * @rw: READ or WRITE data
+ * @rq: request structure to fill
* @ubuf: the user buffer
* @len: length of user data
*
@@ -2132,21 +2133,19 @@ EXPORT_SYMBOL(blk_insert_request);
* original bio must be passed back in to blk_rq_unmap_user() for proper
* unmapping.
*/
-struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
- unsigned int len)
+int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+ unsigned int len)
{
unsigned long uaddr;
- struct request *rq;
struct bio *bio;
+ int reading;
if (len > (q->max_sectors << 9))
- return ERR_PTR(-EINVAL);
- if ((!len && ubuf) || (len && !ubuf))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
+ if (!len || !ubuf)
+ return -EINVAL;
- rq = blk_get_request(q, rw, __GFP_WAIT);
- if (!rq)
- return ERR_PTR(-ENOMEM);
+ reading = rq_data_dir(rq) == READ;
/*
* if alignment requirement is satisfied, map in user pages for
@@ -2154,9 +2153,9 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
*/
uaddr = (unsigned long) ubuf;
if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
- bio = bio_map_user(q, NULL, uaddr, len, rw == READ);
+ bio = bio_map_user(q, NULL, uaddr, len, reading);
else
- bio = bio_copy_user(q, uaddr, len, rw == READ);
+ bio = bio_copy_user(q, uaddr, len, reading);
if (!IS_ERR(bio)) {
rq->bio = rq->biotail = bio;
@@ -2164,28 +2163,70 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
rq->buffer = rq->data = NULL;
rq->data_len = len;
- return rq;
+ return 0;
}
/*
* bio is the err-ptr
*/
- blk_put_request(rq);
- return (struct request *) bio;
+ return PTR_ERR(bio);
}
EXPORT_SYMBOL(blk_rq_map_user);
/**
+ * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage
+ * @q: request queue where request should be inserted
+ * @rq: request to map data to
+ * @iov: pointer to the iovec
+ * @iov_count: number of elements in the iovec
+ *
+ * Description:
+ * Data will be mapped directly for zero copy io, if possible. Otherwise
+ * a kernel bounce buffer is used.
+ *
+ * A matching blk_rq_unmap_user() must be issued at the end of io, while
+ * still in process context.
+ *
+ * Note: The mapped bio may need to be bounced through blk_queue_bounce()
+ * before being submitted to the device, as pages mapped may be out of
+ * reach. It's the callers responsibility to make sure this happens. The
+ * original bio must be passed back in to blk_rq_unmap_user() for proper
+ * unmapping.
+ */
+int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+ struct sg_iovec *iov, int iov_count)
+{
+ struct bio *bio;
+
+ if (!iov || iov_count <= 0)
+ return -EINVAL;
+
+ /* we don't allow misaligned data like bio_map_user() does. If the
+ * user is using sg, they're expected to know the alignment constraints
+ * and respect them accordingly */
+ bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ);
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+ rq->bio = rq->biotail = bio;
+ blk_rq_bio_prep(q, rq, bio);
+ rq->buffer = rq->data = NULL;
+ rq->data_len = bio->bi_size;
+ return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_user_iov);
+
+/**
* blk_rq_unmap_user - unmap a request with user data
- * @rq: request to be unmapped
- * @bio: bio for the request
+ * @bio: bio to be unmapped
* @ulen: length of user buffer
*
* Description:
- * Unmap a request previously mapped by blk_rq_map_user().
+ * Unmap a bio previously mapped by blk_rq_map_user().
*/
-int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
+int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
{
int ret = 0;
@@ -2196,31 +2237,89 @@ int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
ret = bio_uncopy_user(bio);
}
- blk_put_request(rq);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(blk_rq_unmap_user);
/**
+ * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage
+ * @q: request queue where request should be inserted
+ * @rq: request to fill
+ * @kbuf: the kernel buffer
+ * @len: length of user data
+ * @gfp_mask: memory allocation flags
+ */
+int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+ unsigned int len, unsigned int gfp_mask)
+{
+ struct bio *bio;
+
+ if (len > (q->max_sectors << 9))
+ return -EINVAL;
+ if (!len || !kbuf)
+ return -EINVAL;
+
+ bio = bio_map_kern(q, kbuf, len, gfp_mask);
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+ if (rq_data_dir(rq) == WRITE)
+ bio->bi_rw |= (1 << BIO_RW);
+
+ rq->bio = rq->biotail = bio;
+ blk_rq_bio_prep(q, rq, bio);
+
+ rq->buffer = rq->data = NULL;
+ rq->data_len = len;
+ return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_kern);
+
+/**
+ * blk_execute_rq_nowait - insert a request into queue for execution
+ * @q: queue to insert the request in
+ * @bd_disk: matching gendisk
+ * @rq: request to insert
+ * @at_head: insert request at head or tail of queue
+ * @done: I/O completion handler
+ *
+ * Description:
+ * Insert a fully prepared request at the back of the io scheduler queue
+ * for execution. Don't wait for completion.
+ */
+void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
+ struct request *rq, int at_head,
+ void (*done)(struct request *))
+{
+ int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+
+ rq->rq_disk = bd_disk;
+ rq->flags |= REQ_NOMERGE;
+ rq->end_io = done;
+ elv_add_request(q, rq, where, 1);
+ generic_unplug_device(q);
+}
+
+/**
* blk_execute_rq - insert a request into queue for execution
* @q: queue to insert the request in
* @bd_disk: matching gendisk
* @rq: request to insert
+ * @at_head: insert request at head or tail of queue
*
* Description:
* Insert a fully prepared request at the back of the io scheduler queue
- * for execution.
+ * for execution and wait for completion.
*/
int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
- struct request *rq)
+ struct request *rq, int at_head)
{
DECLARE_COMPLETION(wait);
char sense[SCSI_SENSE_BUFFERSIZE];
int err = 0;
- rq->rq_disk = bd_disk;
-
/*
* we need an extra reference to the request, so we can look at
* it after io completion
@@ -2233,11 +2332,8 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
rq->sense_len = 0;
}
- rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
- rq->end_io = blk_end_sync_rq;
- elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
- generic_unplug_device(q);
+ blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
wait_for_completion(&wait);
rq->waiting = NULL;
@@ -2277,6 +2373,44 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
EXPORT_SYMBOL(blkdev_issue_flush);
+/**
+ * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
+ * @q: device queue
+ * @disk: gendisk
+ * @error_sector: error offset
+ *
+ * Description:
+ * Devices understanding the SCSI command set, can use this function as
+ * a helper for issuing a cache flush. Note: driver is required to store
+ * the error offset (in case of error flushing) in ->sector of struct
+ * request.
+ */
+int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+ sector_t *error_sector)
+{
+ struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
+ int ret;
+
+ rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+ rq->sector = 0;
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd[0] = 0x35;
+ rq->cmd_len = 12;
+ rq->data = NULL;
+ rq->data_len = 0;
+ rq->timeout = 60 * HZ;
+
+ ret = blk_execute_rq(q, disk, rq, 0);
+
+ if (ret && error_sector)
+ *error_sector = rq->sector;
+
+ blk_put_request(rq);
+ return ret;
+}
+
+EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
+
static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
{
int rw = rq_data_dir(rq);
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 7289f67e9568..ac5ba462710b 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -516,8 +516,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
static void pcd_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pcd_reset(struct pcd_unit *cd)
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 060b1f2a91dd..711d2f314ac3 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -507,8 +507,7 @@ static void pf_eject(struct pf_unit *pf)
static void pf_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
/* the ATAPI standard actually specifies the contents of all 7 registers
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 84d8e291ed96..b3982395f22b 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -276,8 +276,7 @@ static inline u8 DRIVE(struct pg *dev)
static void pg_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg)
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5fe8ee86f095..d8d35233cf49 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -383,8 +383,7 @@ static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *
static void pt_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7b838342f0a3..7e22a58926b8 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -5,29 +5,41 @@
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
- * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
- * DVD-RW devices (aka an exercise in block layer masturbation)
+ * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
+ * DVD-RAM devices.
*
+ * Theory of operation:
*
- * TODO: (circa order of when I will fix it)
- * - Only able to write on CD-RW media right now.
- * - check host application code on media and set it in write page
- * - interface for UDF <-> packet to negotiate a new location when a write
- * fails.
- * - handle OPC, especially for -RW media
+ * At the lowest level, there is the standard driver for the CD/DVD device,
+ * typically ide-cd.c or sr.c. This driver can handle read and write requests,
+ * but it doesn't know anything about the special restrictions that apply to
+ * packet writing. One restriction is that write requests must be aligned to
+ * packet boundaries on the physical media, and the size of a write request
+ * must be equal to the packet size. Another restriction is that a
+ * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
+ * command, if the previous command was a write.
*
- * Theory of operation:
+ * The purpose of the packet writing driver is to hide these restrictions from
+ * higher layers, such as file systems, and present a block device that can be
+ * randomly read and written using 2kB-sized blocks.
+ *
+ * The lowest layer in the packet writing driver is the packet I/O scheduler.
+ * Its data is defined by the struct packet_iosched and includes two bio
+ * queues with pending read and write requests. These queues are processed
+ * by the pkt_iosched_process_queue() function. The write requests in this
+ * queue are already properly aligned and sized. This layer is responsible for
+ * issuing the flush cache commands and scheduling the I/O in a good order.
*
- * We use a custom make_request_fn function that forwards reads directly to
- * the underlying CD device. Write requests are either attached directly to
- * a live packet_data object, or simply stored sequentially in a list for
- * later processing by the kcdrwd kernel thread. This driver doesn't use
- * any elevator functionally as defined by the elevator_s struct, but the
- * underlying CD device uses a standard elevator.
+ * The next layer transforms unaligned write requests to aligned writes. This
+ * transformation requires reading missing pieces of data from the underlying
+ * block device, assembling the pieces to full packets and queuing them to the
+ * packet I/O scheduler.
*
- * This strategy makes it possible to do very late merging of IO requests.
- * A new bio sent to pkt_make_request can be merged with a live packet_data
- * object even if the object is in the data gathering state.
+ * At the top layer there is a custom make_request_fn function that forwards
+ * read requests directly to the iosched queue and puts write requests in the
+ * unaligned write queue. A kernel thread performs the necessary read
+ * gathering to convert the unaligned writes to aligned writes and then feeds
+ * them to the packet I/O scheduler.
*
*************************************************************************/
@@ -100,10 +112,9 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
goto no_bio;
bio_init(bio);
- bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL);
+ bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
if (!bvl)
goto no_bvl;
- memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec));
bio->bi_max_vecs = nr_iovecs;
bio->bi_io_vec = bvl;
@@ -125,10 +136,9 @@ static struct packet_data *pkt_alloc_packet_data(void)
int i;
struct packet_data *pkt;
- pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+ pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!pkt)
goto no_pkt;
- memset(pkt, 0, sizeof(struct packet_data));
pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
if (!pkt->w_bio)
@@ -659,7 +669,6 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
- BUG_ON(offs > PAGE_SIZE);
offs = 0;
p++;
}
@@ -724,12 +733,6 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 0);
atomic_set(&pkt->io_errors, 0);
- if (pkt->cache_valid) {
- VPRINTK("pkt_gather_data: zone %llx cached\n",
- (unsigned long long)pkt->sector);
- goto out_account;
- }
-
/*
* Figure out which frames we need to read before we can write.
*/
@@ -738,6 +741,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
+ pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
BUG_ON(first_frame < 0);
BUG_ON(first_frame + num_frames > pkt->frames);
for (f = first_frame; f < first_frame + num_frames; f++)
@@ -745,6 +749,12 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
}
spin_unlock(&pkt->lock);
+ if (pkt->cache_valid) {
+ VPRINTK("pkt_gather_data: zone %llx cached\n",
+ (unsigned long long)pkt->sector);
+ goto out_account;
+ }
+
/*
* Schedule reads for missing parts of the packet.
*/
@@ -778,7 +788,6 @@ out_account:
frames_read, (unsigned long long)pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
- pd->stats.secs_w += pd->settings.size;
}
/*
@@ -794,10 +803,11 @@ static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zo
list_del_init(&pkt->list);
if (pkt->sector != zone)
pkt->cache_valid = 0;
- break;
+ return pkt;
}
}
- return pkt;
+ BUG();
+ return NULL;
}
static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -941,12 +951,10 @@ try_next_bio:
}
pkt = pkt_get_packet_data(pd, zone);
- BUG_ON(!pkt);
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
pkt->frames = pd->settings.size >> 2;
- BUG_ON(pkt->frames > PACKET_MAX_SIZE);
pkt->write_size = 0;
/*
@@ -1636,6 +1644,10 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
printk("pktcdvd: detected zero packet size!\n");
pd->settings.size = 128;
}
+ if (pd->settings.size > PACKET_MAX_SECTORS) {
+ printk("pktcdvd: packet size is too big\n");
+ return -ENXIO;
+ }
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -2198,7 +2210,6 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
* No matching packet found. Store the bio in the work queue.
*/
node = mempool_alloc(pd->rb_pool, GFP_NOIO);
- BUG_ON(!node);
node->bio = bio;
spin_lock(&pd->lock);
BUG_ON(pd->bio_queue_size < 0);
@@ -2406,7 +2417,6 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
- BUG_ON(!pd);
switch (cmd) {
/*
@@ -2477,10 +2487,9 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
return -EBUSY;
}
- pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
+ pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
return ret;
- memset(pd, 0, sizeof(struct pktcdvd_device));
pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
if (!pd->rb_pool)
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 29548784cb7b..29d1518be72a 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -99,8 +99,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
static int no_int_yet;
static int ps2esdi_drives;
static u_short io_base;
-static struct timer_list esdi_timer =
- TIMER_INITIALIZER(ps2esdi_reset_timer, 0, 0);
+static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
static int reset_status;
static int ps2esdi_slot = -1;
static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 681871ca5d60..856c2278e9d0 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -123,6 +123,7 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_read(READ_12),
safe_for_read(READ_16),
safe_for_read(READ_BUFFER),
+ safe_for_read(READ_DEFECT_DATA),
safe_for_read(READ_LONG),
safe_for_read(INQUIRY),
safe_for_read(MODE_SENSE),
@@ -216,7 +217,7 @@ static int sg_io(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
{
unsigned long start_time;
- int reading, writing;
+ int writing = 0, ret = 0;
struct request *rq;
struct bio *bio;
char sense[SCSI_SENSE_BUFFERSIZE];
@@ -231,38 +232,48 @@ static int sg_io(struct file *file, request_queue_t *q,
if (verify_command(file, cmd))
return -EPERM;
- /*
- * we'll do that later
- */
- if (hdr->iovec_count)
- return -EOPNOTSUPP;
-
if (hdr->dxfer_len > (q->max_sectors << 9))
return -EIO;
- reading = writing = 0;
- if (hdr->dxfer_len) {
+ if (hdr->dxfer_len)
switch (hdr->dxfer_direction) {
default:
return -EINVAL;
case SG_DXFER_TO_FROM_DEV:
- reading = 1;
- /* fall through */
case SG_DXFER_TO_DEV:
writing = 1;
break;
case SG_DXFER_FROM_DEV:
- reading = 1;
break;
}
- rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp,
- hdr->dxfer_len);
+ rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
+ if (!rq)
+ return -ENOMEM;
+
+ if (hdr->iovec_count) {
+ const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+ struct sg_iovec *iov;
+
+ iov = kmalloc(size, GFP_KERNEL);
+ if (!iov) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(iov, hdr->dxferp, size)) {
+ kfree(iov);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
+ kfree(iov);
+ } else if (hdr->dxfer_len)
+ ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
- } else
- rq = blk_get_request(q, READ, __GFP_WAIT);
+ if (ret)
+ goto out;
/*
* fill in request structure
@@ -298,7 +309,7 @@ static int sg_io(struct file *file, request_queue_t *q,
* (if he doesn't check that is his problem).
* N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
- blk_execute_rq(q, bd_disk, rq);
+ blk_execute_rq(q, bd_disk, rq, 0);
/* write to all output members */
hdr->status = 0xff & rq->errors;
@@ -320,12 +331,14 @@ static int sg_io(struct file *file, request_queue_t *q,
hdr->sb_len_wr = len;
}
- if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len))
- return -EFAULT;
+ if (blk_rq_unmap_user(bio, hdr->dxfer_len))
+ ret = -EFAULT;
/* may not have succeeded, but output values written to control
* structure (struct sg_io_hdr). */
- return 0;
+out:
+ blk_put_request(rq);
+ return ret;
}
#define OMAX_SB_LEN 16 /* For backward compatibility */
@@ -408,7 +421,7 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
- blk_execute_rq(q, bd_disk, rq);
+ blk_execute_rq(q, bd_disk, rq, 0);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len && rq->sense) {
@@ -561,7 +574,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
rq->cmd[0] = GPCMD_START_STOP_UNIT;
rq->cmd[4] = 0x02 + (close != 0);
rq->cmd_len = 6;
- err = blk_execute_rq(q, bd_disk, rq);
+ err = blk_execute_rq(q, bd_disk, rq, 0);
blk_put_request(rq);
break;
default:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index e5f7494c00ee..e425ad3eebba 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -834,8 +834,7 @@ static int fd_eject(struct floppy_state *fs)
break;
}
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (swim3_readbit(fs, DISK_IN) == 0)
break;
}
@@ -906,8 +905,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
break;
}
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0))
@@ -992,8 +990,7 @@ static int floppy_revalidate(struct gendisk *disk)
if (signal_pending(current))
break;
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0;
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index a1283f6dc018..89e3c2f8b776 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -338,8 +338,7 @@ static int swimiop_eject(struct floppy_state *fs)
err = -EINTR;
break;
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
release_drive(fs);
return cmd->error;
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index a026567f5d18..aa0bf7ee008d 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -16,9 +16,10 @@
* -- verify the 13 conditions and do bulk resets
* -- kill last_pipe and simply do two-state clearing on both pipes
* -- verify protocol (bulk) from USB descriptors (maybe...)
- * -- highmem and sg
+ * -- highmem
* -- move top_sense and work_bcs into separate allocations (if they survive)
* for cache purists and esoteric architectures.
+ * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ?
* -- prune comments, they are too volumnous
* -- Exterminate P3 printks
* -- Resove XXX's
@@ -171,7 +172,7 @@ struct bulk_cs_wrap {
*/
struct ub_dev;
-#define UB_MAX_REQ_SG 1
+#define UB_MAX_REQ_SG 4
#define UB_MAX_SECTORS 64
/*
@@ -234,13 +235,10 @@ struct ub_scsi_cmd {
int stat_count; /* Retries getting status. */
- /*
- * We do not support transfers from highmem pages
- * because the underlying USB framework does not do what we need.
- */
- char *data; /* Requested buffer */
unsigned int len; /* Requested length */
- // struct scatterlist sgv[UB_MAX_REQ_SG];
+ unsigned int current_sg;
+ unsigned int nsg; /* sgv[nsg] */
+ struct scatterlist sgv[UB_MAX_REQ_SG];
struct ub_lun *lun;
void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
@@ -389,17 +387,18 @@ struct ub_dev {
struct bulk_cs_wrap work_bcs;
struct usb_ctrlrequest work_cr;
+ int sg_stat[UB_MAX_REQ_SG+1];
struct ub_scsi_trace tr;
};
/*
*/
static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq);
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq);
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -407,6 +406,7 @@ static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
static void ub_scsi_action(unsigned long _dev);
static void ub_scsi_dispatch(struct ub_dev *sc);
static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc);
static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -500,7 +500,8 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
}
}
-static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
+static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
+ char *page)
{
struct usb_interface *intf;
struct ub_dev *sc;
@@ -523,6 +524,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, c
cnt += sprintf(page + cnt,
"qlen %d qmax %d\n",
sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+ cnt += sprintf(page + cnt,
+ "sg %d %d %d %d %d\n",
+ sc->sg_stat[0],
+ sc->sg_stat[1],
+ sc->sg_stat[2],
+ sc->sg_stat[3],
+ sc->sg_stat[4]);
list_for_each (p, &sc->luns) {
lun = list_entry(p, struct ub_lun, link);
@@ -744,20 +752,20 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
* The request function is our main entry point
*/
-static void ub_bd_rq_fn(request_queue_t *q)
+static void ub_request_fn(request_queue_t *q)
{
struct ub_lun *lun = q->queuedata;
struct request *rq;
while ((rq = elv_next_request(q)) != NULL) {
- if (ub_bd_rq_fn_1(lun, rq) != 0) {
+ if (ub_request_fn_1(lun, rq) != 0) {
blk_stop_queue(q);
break;
}
}
}
-static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
+static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
{
struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
@@ -774,9 +782,8 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
blkdev_dequeue_request(rq);
-
if (blk_pc_request(rq)) {
- rc = ub_cmd_build_packet(sc, cmd, rq);
+ rc = ub_cmd_build_packet(sc, lun, cmd, rq);
} else {
rc = ub_cmd_build_block(sc, lun, cmd, rq);
}
@@ -791,7 +798,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
cmd->back = rq;
cmd->tag = sc->tagcnt++;
- if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
+ if (ub_submit_scsi(sc, cmd) != 0) {
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
return 0;
@@ -804,58 +811,31 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq)
{
int ub_dir;
-#if 0 /* We use rq->buffer for now */
- struct scatterlist *sg;
int n_elem;
-#endif
unsigned int block, nblks;
if (rq_data_dir(rq) == WRITE)
ub_dir = UB_DIR_WRITE;
else
ub_dir = UB_DIR_READ;
+ cmd->dir = ub_dir;
/*
* get scatterlist from block layer
*/
-#if 0 /* We use rq->buffer for now */
- sg = &cmd->sgv[0];
- n_elem = blk_rq_map_sg(q, rq, sg);
+ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
if (n_elem <= 0) {
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- blk_start_queue(q);
- return 0; /* request with no s/g entries? */
+ printk(KERN_INFO "%s: failed request map (%d)\n",
+ sc->name, n_elem); /* P3 */
+ return -1; /* request with no s/g entries? */
}
-
- if (n_elem != 1) { /* Paranoia */
+ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- blk_start_queue(q);
- return 0;
- }
-#endif
-
- /*
- * XXX Unfortunately, this check does not work. It is quite possible
- * to get bogus non-null rq->buffer if you allow sg by mistake.
- */
- if (rq->buffer == NULL) {
- /*
- * This must not happen if we set the queue right.
- * The block level must create bounce buffers for us.
- */
- static int do_print = 1;
- if (do_print) {
- printk(KERN_WARNING "%s: unmapped block request"
- " flags 0x%lx sectors %lu\n",
- sc->name, rq->flags, rq->nr_sectors);
- do_print = 0;
- }
return -1;
}
+ cmd->nsg = n_elem;
+ sc->sg_stat[n_elem]++;
/*
* build the command
@@ -876,30 +856,15 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb[8] = nblks;
cmd->cdb_len = 10;
- cmd->dir = ub_dir;
- cmd->data = rq->buffer;
cmd->len = rq->nr_sectors * 512;
return 0;
}
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq)
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq)
{
-
- if (rq->data_len != 0 && rq->data == NULL) {
- static int do_print = 1;
- if (do_print) {
- printk(KERN_WARNING "%s: unmapped packet request"
- " flags 0x%lx length %d\n",
- sc->name, rq->flags, rq->data_len);
- do_print = 0;
- }
- return -1;
- }
-
- memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
- cmd->cdb_len = rq->cmd_len;
+ int n_elem;
if (rq->data_len == 0) {
cmd->dir = UB_DIR_NONE;
@@ -908,8 +873,29 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
cmd->dir = UB_DIR_WRITE;
else
cmd->dir = UB_DIR_READ;
+
+ }
+
+ /*
+ * get scatterlist from block layer
+ */
+ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
+ if (n_elem < 0) {
+ printk(KERN_INFO "%s: failed request map (%d)\n",
+ sc->name, n_elem); /* P3 */
+ return -1;
}
- cmd->data = rq->data;
+ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
+ printk(KERN_WARNING "%s: request with %d segments\n",
+ sc->name, n_elem);
+ return -1;
+ }
+ cmd->nsg = n_elem;
+ sc->sg_stat[n_elem]++;
+
+ memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
+ cmd->cdb_len = rq->cmd_len;
+
cmd->len = rq->data_len;
return 0;
@@ -919,24 +905,34 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct request *rq = cmd->back;
struct ub_lun *lun = cmd->lun;
- struct gendisk *disk = lun->disk;
- request_queue_t *q = disk->queue;
int uptodate;
- if (blk_pc_request(rq)) {
- /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
- memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
- rq->sense_len = UB_SENSE_SIZE;
- }
-
- if (cmd->error == 0)
+ if (cmd->error == 0) {
uptodate = 1;
- else
+
+ if (blk_pc_request(rq)) {
+ if (cmd->act_len >= rq->data_len)
+ rq->data_len = 0;
+ else
+ rq->data_len -= cmd->act_len;
+ }
+ } else {
uptodate = 0;
+ if (blk_pc_request(rq)) {
+ /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
+ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
+ rq->sense_len = UB_SENSE_SIZE;
+ if (sc->top_sense[0] != 0)
+ rq->errors = SAM_STAT_CHECK_CONDITION;
+ else
+ rq->errors = DID_ERROR << 16;
+ }
+ }
+
ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
- blk_start_queue(q);
+ blk_start_queue(lun->disk->queue);
}
static void ub_end_rq(struct request *rq, int uptodate)
@@ -1014,7 +1010,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->send_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+ sc->work_urb.transfer_flags = 0;
/* Fill what we shouldn't be filling, because usb-storage did so. */
sc->work_urb.actual_length = 0;
@@ -1103,7 +1099,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs;
- int pipe;
int rc;
if (atomic_read(&sc->poison)) {
@@ -1204,38 +1199,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
goto Bad_End;
}
- if (cmd->dir == UB_DIR_NONE) {
+ if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) {
ub_state_stat(sc, cmd);
return;
}
- UB_INIT_COMPLETION(sc->work_done);
-
- if (cmd->dir == UB_DIR_READ)
- pipe = sc->recv_bulk_pipe;
- else
- pipe = sc->send_bulk_pipe;
- sc->last_pipe = pipe;
- usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
- cmd->data, cmd->len, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
- sc->work_urb.actual_length = 0;
- sc->work_urb.error_count = 0;
- sc->work_urb.status = 0;
-
- if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- /* XXX Clear stalls */
- printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
- ub_complete(&sc->work_done);
- ub_state_done(sc, cmd, rc);
- return;
- }
-
- sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
- add_timer(&sc->work_timer);
-
- cmd->state = UB_CMDST_DATA;
- ub_cmdtr_state(sc, cmd);
+ // udelay(125); // usb-storage has this
+ ub_data_start(sc, cmd);
} else if (cmd->state == UB_CMDST_DATA) {
if (urb->status == -EPIPE) {
@@ -1257,16 +1227,22 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if (urb->status == -EOVERFLOW) {
/*
* A babble? Failure, but we must transfer CSW now.
+ * XXX This is going to end in perpetual babble. Reset.
*/
cmd->error = -EOVERFLOW; /* A cheap trick... */
- } else {
- if (urb->status != 0)
- goto Bad_End;
+ ub_state_stat(sc, cmd);
+ return;
}
+ if (urb->status != 0)
+ goto Bad_End;
- cmd->act_len = urb->actual_length;
+ cmd->act_len += urb->actual_length;
ub_cmdtr_act_len(sc, cmd);
+ if (++cmd->current_sg < cmd->nsg) {
+ ub_data_start(sc, cmd);
+ return;
+ }
ub_state_stat(sc, cmd);
} else if (cmd->state == UB_CMDST_STAT) {
@@ -1401,6 +1377,46 @@ Bad_End: /* Little Excel is dead */
/*
* Factorization helper for the command state machine:
+ * Initiate a data segment transfer.
+ */
+static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+ struct scatterlist *sg = &cmd->sgv[cmd->current_sg];
+ int pipe;
+ int rc;
+
+ UB_INIT_COMPLETION(sc->work_done);
+
+ if (cmd->dir == UB_DIR_READ)
+ pipe = sc->recv_bulk_pipe;
+ else
+ pipe = sc->send_bulk_pipe;
+ sc->last_pipe = pipe;
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
+ page_address(sg->page) + sg->offset, sg->length,
+ ub_urb_complete, sc);
+ sc->work_urb.transfer_flags = 0;
+ sc->work_urb.actual_length = 0;
+ sc->work_urb.error_count = 0;
+ sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ /* XXX Clear stalls */
+ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
+ ub_complete(&sc->work_done);
+ ub_state_done(sc, cmd, rc);
+ return;
+ }
+
+ sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
+ add_timer(&sc->work_timer);
+
+ cmd->state = UB_CMDST_DATA;
+ ub_cmdtr_state(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
* Finish the command.
*/
static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
@@ -1426,7 +1442,7 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->recv_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
&sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+ sc->work_urb.transfer_flags = 0;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1484,6 +1500,7 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct ub_scsi_cmd *scmd;
+ struct scatterlist *sg;
int rc;
if (cmd->cdb[0] == REQUEST_SENSE) {
@@ -1492,12 +1509,17 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
}
scmd = &sc->top_rqs_cmd;
+ memset(scmd, 0, sizeof(struct ub_scsi_cmd));
scmd->cdb[0] = REQUEST_SENSE;
scmd->cdb[4] = UB_SENSE_SIZE;
scmd->cdb_len = 6;
scmd->dir = UB_DIR_READ;
scmd->state = UB_CMDST_INIT;
- scmd->data = sc->top_sense;
+ scmd->nsg = 1;
+ sg = &scmd->sgv[0];
+ sg->page = virt_to_page(sc->top_sense);
+ sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1);
+ sg->length = UB_SENSE_SIZE;
scmd->len = UB_SENSE_SIZE;
scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
@@ -1541,7 +1563,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
+ sc->work_urb.transfer_flags = 0;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1560,7 +1582,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
*/
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
{
- unsigned char *sense = scmd->data;
+ unsigned char *sense = sc->top_sense;
struct ub_scsi_cmd *cmd;
/*
@@ -1852,6 +1874,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret)
{
struct ub_scsi_cmd *cmd;
+ struct scatterlist *sg;
char *p;
enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };
unsigned long flags;
@@ -1872,7 +1895,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb_len = 10;
cmd->dir = UB_DIR_READ;
cmd->state = UB_CMDST_INIT;
- cmd->data = p;
+ cmd->nsg = 1;
+ sg = &cmd->sgv[0];
+ sg->page = virt_to_page(p);
+ sg->offset = (unsigned int)p & (PAGE_SIZE-1);
+ sg->length = 8;
cmd->len = 8;
cmd->lun = lun;
cmd->done = ub_probe_done;
@@ -2289,7 +2316,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */
rc = -ENOMEM;
- if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
+ if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL)
goto err_blkqinit;
disk->queue = q;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0c4c121d2e79..0f48301342da 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -34,6 +34,7 @@
* - set initialised bit then.
*/
+//#define DEBUG /* uncomment if you want debugging info (pr_debug) */
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -58,10 +59,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#define PRINTK(x...) do {} while (0)
-#define dprintk(x...) do {} while (0)
-/*#define dprintk(x...) printk(x) */
-
#define MM_MAXCARDS 4
#define MM_RAHEAD 2 /* two sectors */
#define MM_BLKSIZE 1024 /* 1k blocks */
@@ -299,7 +296,7 @@ static void mm_start_io(struct cardinfo *card)
/* make the last descriptor end the chain */
page = &card->mm_pages[card->Active];
- PRINTK("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
+ pr_debug("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
desc = &page->desc[page->cnt-1];
desc->control_bits |= cpu_to_le32(DMASCR_CHAIN_COMP_EN);
@@ -532,7 +529,7 @@ static void process_page(unsigned long data)
activate(card);
} else {
/* haven't finished with this one yet */
- PRINTK("do some more\n");
+ pr_debug("do some more\n");
mm_start_io(card);
}
out_unlock:
@@ -555,7 +552,7 @@ static void process_page(unsigned long data)
static int mm_make_request(request_queue_t *q, struct bio *bio)
{
struct cardinfo *card = q->queuedata;
- PRINTK("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
+ pr_debug("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
spin_lock_irq(&card->lock);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 46e56a25d2c8..e46ecd23b3ac 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -776,7 +776,7 @@ static int viodasd_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viodasd_device_table[] __devinitdata = {
{ "viodasd", "" },
- { 0, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, viodasd_device_table);
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 1676033da6c6..68b6d7b154cf 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -47,6 +47,7 @@
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -62,7 +63,7 @@ static int xd[5] = { -1,-1,-1,-1, };
#define XD_DONT_USE_DMA 0 /* Initial value. may be overriden using
"nodma" module option */
-#define XD_INIT_DISK_DELAY (30*HZ/1000) /* 30 ms delay during disk initialization */
+#define XD_INIT_DISK_DELAY (30) /* 30 ms delay during disk initialization */
/* Above may need to be increased if a problem with the 2nd drive detection
(ST11M controller) or resetting a controller (WD) appears */
@@ -529,10 +530,8 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
int success;
xdc_busy = 1;
- while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry))
+ schedule_timeout_uninterruptible(1);
xdc_busy = 0;
return (success);
}
@@ -633,14 +632,12 @@ static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
for (i = 0; i < XD_MAXDRIVES; i++) {
xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
if (!xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT*8)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep_interruptible(XD_INIT_DISK_DELAY);
init_drive(count);
count++;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep_interruptible(XD_INIT_DISK_DELAY);
}
}
return (count);
@@ -761,8 +758,7 @@ static void __init xd_wd_init_controller (unsigned int address)
outb(0,XD_RESET); /* reset the controller */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep(XD_INIT_DISK_DELAY);
}
static void __init xd_wd_init_drive (u_char drive)
@@ -936,8 +932,7 @@ If you need non-standard settings use the xd=... command */
xd_maxsectors = 0x01;
outb(0,XD_RESET); /* reset the controller */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep(XD_INIT_DISK_DELAY);
}
static void __init xd_xebec_init_drive (u_char drive)
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 007f6a662439..bb5e8d665a2a 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -296,7 +296,7 @@ z2_open( struct inode *inode, struct file *filp )
return 0;
err_out_kfree:
- kfree( z2ram_map );
+ kfree(z2ram_map);
err_out:
return rc;
}
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index c42d7e6ac1c5..1e9db0156ea7 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -158,7 +158,7 @@ static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
if (err) {
BT_ERR("%s bulk tx submit failed urb %p err %d",
bfusb->hdev->name, urb, err);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
usb_free_urb(urb);
} else
atomic_inc(&bfusb->pending_tx);
@@ -212,7 +212,7 @@ static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
read_lock(&bfusb->lock);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
skb_queue_tail(&bfusb->completed_q, skb);
bfusb_tx_wakeup(bfusb);
@@ -253,7 +253,7 @@ static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
if (err) {
BT_ERR("%s bulk rx submit failed urb %p err %d",
bfusb->hdev->name, urb, err);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
kfree_skb(skb);
usb_free_urb(urb);
}
@@ -330,7 +330,7 @@ static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *
}
skb->dev = (void *) bfusb->hdev;
- skb->pkt_type = pkt_type;
+ bt_cb(skb)->pkt_type = pkt_type;
bfusb->reassembly = skb;
} else {
@@ -398,7 +398,7 @@ static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
buf += len;
}
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
kfree_skb(skb);
bfusb_rx_submit(bfusb, urb);
@@ -485,7 +485,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
unsigned char buf[3];
int sent = 0, size, count;
- BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len);
+ BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!hdev) {
BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -497,7 +497,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
bfusb = (struct bfusb *) hdev->driver_data;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -510,7 +510,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
count = skb->len;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index bd2ec7e284cc..26fe9c0e1d20 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -270,7 +270,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
if (!(skb = skb_dequeue(&(info->txq))))
break;
- if (skb->pkt_type & 0x80) {
+ if (bt_cb(skb)->pkt_type & 0x80) {
/* Disable RTS */
info->ctrl_reg |= REG_CONTROL_RTS;
outb(info->ctrl_reg, iobase + REG_CONTROL);
@@ -288,13 +288,13 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
/* Mark the buffer as dirty */
clear_bit(ready_bit, &(info->tx_state));
- if (skb->pkt_type & 0x80) {
+ if (bt_cb(skb)->pkt_type & 0x80) {
DECLARE_WAIT_QUEUE_HEAD(wq);
DEFINE_WAIT(wait);
unsigned char baud_reg;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case PKT_BAUD_RATE_460800:
baud_reg = REG_CONTROL_BAUD_RATE_460800;
break;
@@ -410,9 +410,9 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = buf[i];
+ bt_cb(info->rx_skb)->pkt_type = buf[i];
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case 0x00:
/* init packet */
@@ -444,7 +444,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
default:
/* unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
@@ -586,21 +586,21 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
switch (baud) {
case 460800:
cmd[4] = 0x00;
- skb->pkt_type = PKT_BAUD_RATE_460800;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_460800;
break;
case 230400:
cmd[4] = 0x01;
- skb->pkt_type = PKT_BAUD_RATE_230400;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_230400;
break;
case 115200:
cmd[4] = 0x02;
- skb->pkt_type = PKT_BAUD_RATE_115200;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_115200;
break;
case 57600:
/* Fall through... */
default:
cmd[4] = 0x03;
- skb->pkt_type = PKT_BAUD_RATE_57600;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_57600;
break;
}
@@ -680,7 +680,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
info = (bluecard_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -693,7 +693,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
bluecard_write_wakeup(info);
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index f696da6f417b..a1bf8f066c88 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -105,7 +105,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
hci_recv_frame(skb);
}
break;
@@ -117,7 +117,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_SCODATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
hci_recv_frame(skb);
}
break;
@@ -129,7 +129,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_VENDOR_PKT;
+ bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
hci_recv_frame(skb);
}
break;
@@ -190,7 +190,7 @@ static int bpa10x_recv_event(struct bpa10x_data *data, unsigned char *buf, int s
}
skb->dev = (void *) data->hdev;
- skb->pkt_type = pkt_type;
+ bt_cb(skb)->pkt_type = pkt_type;
memcpy(skb_put(skb, size), buf, size);
@@ -307,7 +307,8 @@ unlock:
read_unlock(&data->lock);
}
-static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe, size_t size, int flags, void *data)
+static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe,
+ size_t size, unsigned int __nocast flags, void *data)
{
struct urb *urb;
struct usb_ctrlrequest *cr;
@@ -487,7 +488,7 @@ static int bpa10x_send_frame(struct sk_buff *skb)
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
struct bpa10x_data *data;
- BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len);
+ BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!hdev) {
BT_ERR("Frame for unknown HCI device");
@@ -500,9 +501,9 @@ static int bpa10x_send_frame(struct sk_buff *skb)
data = hdev->driver_data;
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
skb_queue_tail(&data->cmd_queue, skb);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index adf1750ea58d..2e0338d80f32 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -259,11 +259,11 @@ static void bt3c_receive(bt3c_info_t *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = inb(iobase + DATA_L);
+ bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L);
inb(iobase + DATA_H);
- //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);
+ //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@@ -282,7 +282,7 @@ static void bt3c_receive(bt3c_info_t *info)
default:
/* Unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
@@ -439,7 +439,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
info = (bt3c_info_t *) (hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -452,7 +452,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
spin_lock_irqsave(&(info->lock), flags);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index e4c59fdc0e12..89486ea7a021 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -211,9 +211,9 @@ static void btuart_receive(btuart_info_t *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = inb(iobase + UART_RX);
+ bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@@ -232,7 +232,7 @@ static void btuart_receive(btuart_info_t *info)
default:
/* Unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
@@ -447,7 +447,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
info = (btuart_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -460,7 +460,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
btuart_write_wakeup(info);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index e39868c3da48..84c1f8839422 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -251,7 +251,7 @@ static void dtl1_receive(dtl1_info_t *info)
info->rx_count = nsh->len + (nsh->len & 0x0001);
break;
case RECV_WAIT_DATA:
- info->rx_skb->pkt_type = nsh->type;
+ bt_cb(info->rx_skb)->pkt_type = nsh->type;
/* remove PAD byte if it exists */
if (nsh->len & 0x0001) {
@@ -262,7 +262,7 @@ static void dtl1_receive(dtl1_info_t *info)
/* remove NSH */
skb_pull(info->rx_skb, NSHL);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case 0x80:
/* control data for the Nokia Card */
dtl1_control(info, info->rx_skb);
@@ -272,12 +272,12 @@ static void dtl1_receive(dtl1_info_t *info)
case 0x84:
/* send frame to the HCI layer */
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type &= 0x0f;
+ bt_cb(info->rx_skb)->pkt_type &= 0x0f;
hci_recv_frame(info->rx_skb);
break;
default:
/* unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
kfree_skb(info->rx_skb);
break;
}
@@ -410,7 +410,7 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)
info = (dtl1_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
nsh.type = 0x81;
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 858fddb046de..0ee324e1265d 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -149,7 +149,7 @@ static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
return 0;
}
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&bcsp->rel, skb);
@@ -227,7 +227,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
if (!nskb)
return NULL;
- nskb->pkt_type = pkt_type;
+ bt_cb(nskb)->pkt_type = pkt_type;
bcsp_slip_msgdelim(nskb);
@@ -286,7 +286,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
since they have priority */
if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) {
- struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type);
+ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
if (nskb) {
kfree_skb(skb);
return nskb;
@@ -303,7 +303,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
spin_lock_irqsave(&bcsp->unack.lock, flags);
if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
- struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type);
+ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
if (nskb) {
__skb_queue_tail(&bcsp->unack, skb);
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
@@ -401,7 +401,7 @@ static void bcsp_handle_le_pkt(struct hci_uart *hu)
if (!nskb)
return;
memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4);
- nskb->pkt_type = BCSP_LE_PKT;
+ bt_cb(nskb)->pkt_type = BCSP_LE_PKT;
skb_queue_head(&bcsp->unrel, nskb);
hci_uart_tx_wakeup(hu);
@@ -483,14 +483,14 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
bcsp_pkt_cull(bcsp);
if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&
bcsp->rx_skb->data[0] & 0x80) {
- bcsp->rx_skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&
bcsp->rx_skb->data[0] & 0x80) {
- bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {
- bcsp->rx_skb->pkt_type = HCI_SCODATA_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_SCODATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
!(bcsp->rx_skb->data[0] & 0x80)) {
@@ -512,7 +512,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
hdr.evt = 0xff;
hdr.plen = bcsp->rx_skb->len;
memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
- bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
hci_recv_frame(bcsp->rx_skb);
} else {
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index 533323b60e63..cf8a22d58d96 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -112,7 +112,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&h4->txq, skb);
return 0;
}
@@ -239,7 +239,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
return 0;
}
h4->rx_skb->dev = (void *) hu->hdev;
- h4->rx_skb->pkt_type = type;
+ bt_cb(h4->rx_skb)->pkt_type = type;
}
return count;
}
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 90be2eae52e0..aed80cc22890 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -153,7 +153,7 @@ restart:
break;
}
- hci_uart_tx_complete(hu, skb->pkt_type);
+ hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
kfree_skb(skb);
}
@@ -229,7 +229,7 @@ static int hci_uart_send_frame(struct sk_buff *skb)
hu = (struct hci_uart *) hdev->driver_data;
tty = hu->tty;
- BT_DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len);
+ BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
hu->proto->enqueue(hu, skb);
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 657719b8254f..67d96b5cbb96 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -127,7 +127,7 @@ static struct usb_device_id blacklist_ids[] = {
{ } /* Terminating entry */
};
-static struct _urb *_urb_alloc(int isoc, int gfp)
+static struct _urb *_urb_alloc(int isoc, unsigned int __nocast gfp)
{
struct _urb *_urb = kmalloc(sizeof(struct _urb) +
sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
@@ -443,7 +443,7 @@ static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct usb_ctrlrequest *dr;
struct urb *urb;
@@ -451,7 +451,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
_urb = _urb_alloc(0, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
if (!dr) {
@@ -479,7 +479,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct urb *urb;
int pipe;
@@ -487,7 +487,7 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
_urb = _urb_alloc(0, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
}
urb = &_urb->urb;
@@ -505,14 +505,14 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
#ifdef CONFIG_BT_HCIUSB_SCO
static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct urb *urb;
if (!_urb) {
_urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
}
BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
@@ -601,11 +601,11 @@ static int hci_usb_send_frame(struct sk_buff *skb)
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len);
+ BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
husb = (struct hci_usb *) hdev->driver_data;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -627,7 +627,7 @@ static int hci_usb_send_frame(struct sk_buff *skb)
read_lock(&husb->completion_lock);
- skb_queue_tail(__transmit_q(husb, skb->pkt_type), skb);
+ skb_queue_tail(__transmit_q(husb, bt_cb(skb)->pkt_type), skb);
hci_usb_tx_wakeup(husb);
read_unlock(&husb->completion_lock);
@@ -682,7 +682,7 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int c
return -ENOMEM;
}
skb->dev = (void *) husb->hdev;
- skb->pkt_type = type;
+ bt_cb(skb)->pkt_type = type;
__reassembly(husb, type) = skb;
@@ -702,6 +702,7 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int c
if (!scb->expect) {
/* Complete frame */
__reassembly(husb, type) = NULL;
+ bt_cb(skb)->pkt_type = type;
hci_recv_frame(skb);
}
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index f9b956fb2b8b..52cbd45c308f 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -1,229 +1,220 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI virtual device driver.
*
- * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $
+ * Bluetooth virtual HCI driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
*/
-#define VERSION "1.1"
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
+#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/miscdevice.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#include "hci_vhci.h"
-/* HCI device part */
+#ifndef CONFIG_BT_HCIVHCI_DEBUG
+#undef BT_DBG
+#define BT_DBG(D...)
+#endif
+
+#define VERSION "1.2"
+
+static int minor = MISC_DYNAMIC_MINOR;
+
+struct vhci_data {
+ struct hci_dev *hdev;
+
+ unsigned long flags;
+
+ wait_queue_head_t read_wait;
+ struct sk_buff_head readq;
+
+ struct fasync_struct *fasync;
+};
-static int hci_vhci_open(struct hci_dev *hdev)
+#define VHCI_FASYNC 0x0010
+
+static struct miscdevice vhci_miscdev;
+
+static int vhci_open_dev(struct hci_dev *hdev)
{
set_bit(HCI_RUNNING, &hdev->flags);
- return 0;
-}
-static int hci_vhci_flush(struct hci_dev *hdev)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
- skb_queue_purge(&hci_vhci->readq);
return 0;
}
-static int hci_vhci_close(struct hci_dev *hdev)
+static int vhci_close_dev(struct hci_dev *hdev)
{
+ struct vhci_data *vhci = hdev->driver_data;
+
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
- hci_vhci_flush(hdev);
+ skb_queue_purge(&vhci->readq);
+
return 0;
}
-static void hci_vhci_destruct(struct hci_dev *hdev)
+static int vhci_flush(struct hci_dev *hdev)
{
- struct hci_vhci_struct *vhci;
+ struct vhci_data *vhci = hdev->driver_data;
- if (!hdev) return;
+ skb_queue_purge(&vhci->readq);
- vhci = (struct hci_vhci_struct *) hdev->driver_data;
- kfree(vhci);
+ return 0;
}
-static int hci_vhci_send_frame(struct sk_buff *skb)
+static int vhci_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
- struct hci_vhci_struct *hci_vhci;
+ struct vhci_data *vhci;
if (!hdev) {
- BT_ERR("Frame for uknown device (hdev=NULL)");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
+ vhci = hdev->driver_data;
+
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+ skb_queue_tail(&vhci->readq, skb);
- memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
- skb_queue_tail(&hci_vhci->readq, skb);
+ if (vhci->flags & VHCI_FASYNC)
+ kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
- if (hci_vhci->flags & VHCI_FASYNC)
- kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN);
- wake_up_interruptible(&hci_vhci->read_wait);
+ wake_up_interruptible(&vhci->read_wait);
return 0;
}
-/* Character device part */
-
-/* Poll */
-static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
-
- poll_wait(file, &hci_vhci->read_wait, wait);
-
- if (!skb_queue_empty(&hci_vhci->readq))
- return POLLIN | POLLRDNORM;
-
- return POLLOUT | POLLWRNORM;
+static void vhci_destruct(struct hci_dev *hdev)
+{
+ kfree(hdev->driver_data);
}
-/* Get packet from user space buffer(already verified) */
-static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char __user *buf, size_t count)
+static inline ssize_t vhci_get_user(struct vhci_data *vhci,
+ const char __user *buf, size_t count)
{
struct sk_buff *skb;
if (count > HCI_MAX_FRAME_SIZE)
return -EINVAL;
- if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
+ skb = bt_skb_alloc(count, GFP_KERNEL);
+ if (!skb)
return -ENOMEM;
-
+
if (copy_from_user(skb_put(skb, count), buf, count)) {
kfree_skb(skb);
return -EFAULT;
}
- skb->dev = (void *) hci_vhci->hdev;
- skb->pkt_type = *((__u8 *) skb->data);
+ skb->dev = (void *) vhci->hdev;
+ bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
hci_recv_frame(skb);
return count;
-}
-
-/* Write */
-static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf,
- size_t count, loff_t *pos)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
-
- if (!access_ok(VERIFY_READ, buf, count))
- return -EFAULT;
-
- return hci_vhci_get_user(hci_vhci, buf, count);
}
-/* Put packet to user space buffer(already verified) */
-static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci,
- struct sk_buff *skb, char __user *buf,
- int count)
+static inline ssize_t vhci_put_user(struct vhci_data *vhci,
+ struct sk_buff *skb, char __user *buf, int count)
{
- int len = count, total = 0;
char __user *ptr = buf;
+ int len, total = 0;
+
+ len = min_t(unsigned int, skb->len, count);
- len = min_t(unsigned int, skb->len, len);
if (copy_to_user(ptr, skb->data, len))
return -EFAULT;
+
total += len;
- hci_vhci->hdev->stat.byte_tx += len;
- switch (skb->pkt_type) {
- case HCI_COMMAND_PKT:
- hci_vhci->hdev->stat.cmd_tx++;
- break;
+ vhci->hdev->stat.byte_tx += len;
- case HCI_ACLDATA_PKT:
- hci_vhci->hdev->stat.acl_tx++;
- break;
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ vhci->hdev->stat.cmd_tx++;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ vhci->hdev->stat.acl_tx++;
+ break;
- case HCI_SCODATA_PKT:
- hci_vhci->hdev->stat.cmd_tx++;
- break;
+ case HCI_SCODATA_PKT:
+ vhci->hdev->stat.cmd_tx++;
+ break;
};
return total;
}
-/* Read */
-static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
+static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
DECLARE_WAITQUEUE(wait, current);
+ struct vhci_data *vhci = file->private_data;
struct sk_buff *skb;
ssize_t ret = 0;
- add_wait_queue(&hci_vhci->read_wait, &wait);
+ add_wait_queue(&vhci->read_wait, &wait);
while (count) {
set_current_state(TASK_INTERRUPTIBLE);
- /* Read frames from device queue */
- if (!(skb = skb_dequeue(&hci_vhci->readq))) {
+ skb = skb_dequeue(&vhci->readq);
+ if (!skb) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
+
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
- /* Nothing to read, let's sleep */
schedule();
continue;
}
if (access_ok(VERIFY_WRITE, buf, count))
- ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
+ ret = vhci_put_user(vhci, skb, buf, count);
else
ret = -EFAULT;
@@ -231,84 +222,90 @@ static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t c
break;
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&hci_vhci->read_wait, &wait);
+ remove_wait_queue(&vhci->read_wait, &wait);
return ret;
}
-static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
+static ssize_t vhci_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *pos)
{
- return -ESPIPE;
-}
+ struct vhci_data *vhci = file->private_data;
-static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- return -EINVAL;
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ return vhci_get_user(vhci, buf, count);
}
-static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
+static unsigned int vhci_poll(struct file *file, poll_table *wait)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
- int ret;
+ struct vhci_data *vhci = file->private_data;
- if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
- return ret;
-
- if (on)
- hci_vhci->flags |= VHCI_FASYNC;
- else
- hci_vhci->flags &= ~VHCI_FASYNC;
+ poll_wait(file, &vhci->read_wait, wait);
- return 0;
+ if (!skb_queue_empty(&vhci->readq))
+ return POLLIN | POLLRDNORM;
+
+ return POLLOUT | POLLWRNORM;
}
-static int hci_vhci_chr_open(struct inode *inode, struct file * file)
+static int vhci_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct hci_vhci_struct *hci_vhci = NULL;
+ return -EINVAL;
+}
+
+static int vhci_open(struct inode *inode, struct file *file)
+{
+ struct vhci_data *vhci;
struct hci_dev *hdev;
- if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
+ vhci = kmalloc(sizeof(struct vhci_data), GFP_KERNEL);
+ if (!vhci)
return -ENOMEM;
- memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
+ memset(vhci, 0, sizeof(struct vhci_data));
- skb_queue_head_init(&hci_vhci->readq);
- init_waitqueue_head(&hci_vhci->read_wait);
+ skb_queue_head_init(&vhci->readq);
+ init_waitqueue_head(&vhci->read_wait);
- /* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- kfree(hci_vhci);
+ kfree(vhci);
return -ENOMEM;
}
- hci_vhci->hdev = hdev;
+ vhci->hdev = hdev;
hdev->type = HCI_VHCI;
- hdev->driver_data = hci_vhci;
+ hdev->driver_data = vhci;
+ SET_HCIDEV_DEV(hdev, vhci_miscdev.dev);
- hdev->open = hci_vhci_open;
- hdev->close = hci_vhci_close;
- hdev->flush = hci_vhci_flush;
- hdev->send = hci_vhci_send_frame;
- hdev->destruct = hci_vhci_destruct;
+ hdev->open = vhci_open_dev;
+ hdev->close = vhci_close_dev;
+ hdev->flush = vhci_flush;
+ hdev->send = vhci_send_frame;
+ hdev->destruct = vhci_destruct;
hdev->owner = THIS_MODULE;
-
+
if (hci_register_dev(hdev) < 0) {
- kfree(hci_vhci);
+ BT_ERR("Can't register HCI device");
+ kfree(vhci);
hci_free_dev(hdev);
return -EBUSY;
}
- file->private_data = hci_vhci;
- return nonseekable_open(inode, file);
+ file->private_data = vhci;
+
+ return nonseekable_open(inode, file);
}
-static int hci_vhci_chr_close(struct inode *inode, struct file *file)
+static int vhci_release(struct inode *inode, struct file *file)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
- struct hci_dev *hdev = hci_vhci->hdev;
+ struct vhci_data *vhci = file->private_data;
+ struct hci_dev *hdev = vhci->hdev;
if (hci_unregister_dev(hdev) < 0) {
BT_ERR("Can't unregister HCI device %s", hdev->name);
@@ -317,48 +314,71 @@ static int hci_vhci_chr_close(struct inode *inode, struct file *file)
hci_free_dev(hdev);
file->private_data = NULL;
+
return 0;
}
-static struct file_operations hci_vhci_fops = {
- .owner = THIS_MODULE,
- .llseek = hci_vhci_chr_lseek,
- .read = hci_vhci_chr_read,
- .write = hci_vhci_chr_write,
- .poll = hci_vhci_chr_poll,
- .ioctl = hci_vhci_chr_ioctl,
- .open = hci_vhci_chr_open,
- .release = hci_vhci_chr_close,
- .fasync = hci_vhci_chr_fasync
+static int vhci_fasync(int fd, struct file *file, int on)
+{
+ struct vhci_data *vhci = file->private_data;
+ int err;
+
+ err = fasync_helper(fd, file, on, &vhci->fasync);
+ if (err < 0)
+ return err;
+
+ if (on)
+ vhci->flags |= VHCI_FASYNC;
+ else
+ vhci->flags &= ~VHCI_FASYNC;
+
+ return 0;
+}
+
+static struct file_operations vhci_fops = {
+ .owner = THIS_MODULE,
+ .llseek = vhci_llseek,
+ .read = vhci_read,
+ .write = vhci_write,
+ .poll = vhci_poll,
+ .ioctl = vhci_ioctl,
+ .open = vhci_open,
+ .release = vhci_release,
+ .fasync = vhci_fasync,
};
-static struct miscdevice hci_vhci_miscdev=
-{
- VHCI_MINOR,
- "hci_vhci",
- &hci_vhci_fops
+static struct miscdevice vhci_miscdev= {
+ .name = "vhci",
+ .fops = &vhci_fops,
};
-static int __init hci_vhci_init(void)
+static int __init vhci_init(void)
{
- BT_INFO("VHCI driver ver %s", VERSION);
+ BT_INFO("Virtual HCI driver ver %s", VERSION);
- if (misc_register(&hci_vhci_miscdev)) {
- BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
+ vhci_miscdev.minor = minor;
+
+ if (misc_register(&vhci_miscdev) < 0) {
+ BT_ERR("Can't register misc device with minor %d", minor);
return -EIO;
}
return 0;
}
-static void hci_vhci_cleanup(void)
+static void __exit vhci_exit(void)
{
- misc_deregister(&hci_vhci_miscdev);
+ if (misc_deregister(&vhci_miscdev) < 0)
+ BT_ERR("Can't unregister misc device with minor %d", minor);
}
-module_init(hci_vhci_init);
-module_exit(hci_vhci_cleanup);
+module_init(vhci_init);
+module_exit(vhci_exit);
+
+module_param(minor, int, 0444);
+MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
-MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_vhci.h b/drivers/bluetooth/hci_vhci.h
deleted file mode 100644
index 53b11f9ef76d..000000000000
--- a/drivers/bluetooth/hci_vhci.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_vhci.h,v 1.1.1.1 2002/03/08 21:03:15 maxk Exp $
- */
-
-#ifndef __HCI_VHCI_H
-#define __HCI_VHCI_H
-
-#ifdef __KERNEL__
-
-struct hci_vhci_struct {
- struct hci_dev *hdev;
- __u32 flags;
- wait_queue_head_t read_wait;
- struct sk_buff_head readq;
- struct fasync_struct *fasync;
-};
-
-/* VHCI device flags */
-#define VHCI_FASYNC 0x0010
-
-#endif /* __KERNEL__ */
-
-#define VHCI_DEV "/dev/vhci"
-#define VHCI_MINOR 250
-
-#endif /* __HCI_VHCI_H */
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index 43bf1e5dc38a..ce4a1ce59d6a 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -297,7 +297,7 @@ static char azt_auto_eject = AZT_AUTO_EJECT;
static int AztTimeout, AztTries;
static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static struct timer_list delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(delay_timer, NULL, 0, 0);
static struct azt_DiskInfo DiskInfo;
static struct azt_Toc Toc[MAX_TRACKS];
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index beaa561f2ed8..153960348414 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!q)
return -ENXIO;
+ rq = blk_get_request(q, READ, GFP_KERNEL);
+ if (!rq)
+ return -ENOMEM;
+
cdi->last_sense = 0;
while (nframes) {
@@ -2108,9 +2112,9 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
len = nr * CD_FRAMESIZE_RAW;
- rq = blk_rq_map_user(q, READ, ubuf, len);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
+ ret = blk_rq_map_user(q, rq, ubuf, len);
+ if (ret)
+ break;
memset(rq->cmd, 0, sizeof(rq->cmd));
rq->cmd[0] = GPCMD_READ_CD;
@@ -2132,13 +2136,13 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (rq->bio)
blk_queue_bounce(q, &rq->bio);
- if (blk_execute_rq(q, cdi->disk, rq)) {
+ if (blk_execute_rq(q, cdi->disk, rq, 0)) {
struct request_sense *s = rq->sense;
ret = -EIO;
cdi->last_sense = s->sense_key;
}
- if (blk_rq_unmap_user(rq, bio, len))
+ if (blk_rq_unmap_user(bio, len))
ret = -EFAULT;
if (ret)
@@ -2149,6 +2153,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
ubuf += len;
}
+ blk_put_request(rq);
return ret;
}
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index 7eac10e63b23..ad5464ab99bc 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -146,7 +146,7 @@ static int AudioStart_f;
static int AudioEnd_m;
static int AudioEnd_f;
-static struct timer_list gscd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
static DEFINE_SPINLOCK(gscd_lock);
static struct request_queue *gscd_queue;
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index 351a01dd503a..0b0eab4f40fa 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -264,7 +264,7 @@ static inline int flag_low(int flag, unsigned long timeout)
static int sleep_timeout; /* max # of ticks to sleep */
static DECLARE_WAIT_QUEUE_HEAD(waitq);
static void sleep_timer(unsigned long data);
-static struct timer_list delay_timer = TIMER_INITIALIZER(sleep_timer, 0, 0);
+static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
static DEFINE_SPINLOCK(optcd_lock);
static struct request_queue *opt_queue;
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 452d34675159..466e9c2974bd 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -742,13 +742,10 @@ static struct sbpcd_drive *current_drive = D_S;
unsigned long cli_sti; /* for saving the processor flags */
#endif
/*==========================================================================*/
-static struct timer_list delay_timer =
- TIMER_INITIALIZER(mark_timeout_delay, 0, 0);
-static struct timer_list data_timer =
- TIMER_INITIALIZER(mark_timeout_data, 0, 0);
+static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
+static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
#if 0
-static struct timer_list audio_timer =
- TIMER_INITIALIZER(mark_timeout_audio, 0, 0);
+static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
#endif
/*==========================================================================*/
/*
@@ -830,8 +827,7 @@ static void mark_timeout_audio(u_long i)
static void sbp_sleep(u_int time)
{
sti();
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(time);
+ schedule_timeout_interruptible(time);
sti();
}
/*==========================================================================*/
@@ -4219,7 +4215,8 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
- if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf);
+ if (current_drive->sbp_audsiz>0)
+ vfree(current_drive->aud_buf);
current_drive->aud_buf=NULL;
current_drive->sbp_audsiz=arg;
@@ -5913,7 +5910,8 @@ static void sbpcd_exit(void)
put_disk(D_S[j].disk);
devfs_remove("sbp/c0t%d", j);
vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
+ if (D_S[j].sbp_audsiz>0)
+ vfree(D_S[j].aud_buf);
if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
{
msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 4e7a342ec36f..74b1cadbf161 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -151,7 +151,7 @@ static struct sjcd_stat statistic;
/*
* Timer.
*/
-static struct timer_list sjcd_delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
#define SJCD_SET_TIMER( func, tmout ) \
( sjcd_delay_timer.expires = jiffies+tmout, \
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 9f22e8f1f6c0..e65659926432 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -1478,8 +1478,7 @@ static int __init sony535_init(void)
/* look for the CD-ROM, follows the procedure in the DOS driver */
inb(select_unit_reg);
/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((HZ+17)*40/18);
+ schedule_timeout_interruptible((HZ+17)*40/18);
inb(result_reg);
outb(0, read_status_reg); /* does a reset? */
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 38dd9ffbe8bc..0829db58462f 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -734,7 +734,7 @@ static int viocd_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viocd_device_table[] __devinitdata = {
{ "viocd", "" },
- { 0, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, viocd_device_table);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 7333b41d4224..c29365d5b524 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -80,7 +80,7 @@ config SERIAL_NONSTANDARD
config COMPUTONE
tristate "Computone IntelliPort Plus serial support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (BROKEN || !SPARC32)
+ depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
@@ -138,7 +138,7 @@ config CYZ_INTR
config DIGIEPCA
tristate "Digiboard Intelligent Async Support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN)
+ depends on SERIAL_NONSTANDARD
---help---
This is a driver for Digi International's Xx, Xeve, and Xem series
of cards which provide multiple serial ports. You would need
@@ -208,7 +208,7 @@ config SYNCLINK
config SYNCLINKMP
tristate "SyncLink Multiport support"
- depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32)
+ depends on SERIAL_NONSTANDARD
help
Enable support for the SyncLink Multiport (2 or 4 ports)
serial adapter, running asynchronous and HDLC communications up
@@ -735,7 +735,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32
+ depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64
---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
@@ -842,8 +842,7 @@ config SONYPI
config TANBAC_TB0219
tristate "TANBAC TB0219 base board support"
- depends TANBAC_TB0229
-
+ depends TANBAC_TB022X
menu "Ftape, the floppy tape device driver"
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 59f589d733f9..0a7624a9b1c1 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -429,7 +429,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
struct pci_dev *dev1;
int i;
unsigned size = amd64_fetch_size();
- printk(KERN_INFO "Setting up ULi AGP. \n");
+ printk(KERN_INFO "Setting up ULi AGP.\n");
dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0));
if (dev1 == NULL) {
printk(KERN_INFO PFX "Detected a ULi chipset, "
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 4d4e602fdc7e..82b43c541c8d 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -206,10 +206,9 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
bridge->driver->cleanup();
if (bridge->driver->free_gatt_table)
bridge->driver->free_gatt_table(bridge);
- if (bridge->key_list) {
- vfree(bridge->key_list);
- bridge->key_list = NULL;
- }
+
+ vfree(bridge->key_list);
+ bridge->key_list = NULL;
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f0079e991bdc..ac9da0ca36b7 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -319,7 +319,6 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
- info->mode = bridge->mode;
info->aper_base = bridge->gart_bus_addr;
info->aper_size = agp_return_size();
info->max_memory = bridge->max_memory_agp;
@@ -356,7 +355,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
return -EINVAL;
if (curr->is_bound == TRUE) {
- printk (KERN_INFO PFX "memory %p is already bound!\n", curr);
+ printk(KERN_INFO PFX "memory %p is already bound!\n", curr);
return -EINVAL;
}
if (curr->is_flushed == FALSE) {
@@ -391,7 +390,7 @@ int agp_unbind_memory(struct agp_memory *curr)
return -EINVAL;
if (curr->is_bound != TRUE) {
- printk (KERN_INFO PFX "memory %p was not bound!\n", curr);
+ printk(KERN_INFO PFX "memory %p was not bound!\n", curr);
return -EINVAL;
}
@@ -415,7 +414,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
u32 tmp;
if (*requested_mode & AGP2_RESERVED_MASK) {
- printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP2_RESERVED_MASK;
}
@@ -423,7 +422,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
tmp = *requested_mode & 7;
switch (tmp) {
case 0:
- printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
+ printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
*requested_mode |= AGPSTAT2_1X;
break;
case 1:
@@ -493,18 +492,18 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
u32 tmp;
if (*requested_mode & AGP3_RESERVED_MASK) {
- printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP3_RESERVED_MASK;
}
/* Check the speed bits make sense. */
tmp = *requested_mode & 7;
if (tmp == 0) {
- printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
+ printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
*requested_mode |= AGPSTAT3_4X;
}
if (tmp >= 3) {
- printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
+ printk(KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
*requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
}
@@ -533,7 +532,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
* AGP2.x 4x -> AGP3.0 4x.
*/
if (*requested_mode & AGPSTAT2_4X) {
- printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
+ printk(KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~AGPSTAT2_4X;
*requested_mode |= AGPSTAT3_4X;
@@ -544,7 +543,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
* but have been passed an AGP 2.x mode.
* Convert AGP 1x,2x,4x -> AGP 3.0 4x.
*/
- printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
+ printk(KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
*requested_mode |= AGPSTAT3_4X;
@@ -554,13 +553,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
if (!(*bridge_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
- printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
+ printk(KERN_INFO PFX "%s requested AGPx8 but bridge not capable.\n", current->comm);
return;
}
if (!(*vga_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
- printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
+ printk(KERN_INFO PFX "%s requested AGPx8 but graphic card not capable.\n", current->comm);
return;
}
/* All set, bridge & device can do AGP x8*/
@@ -578,13 +577,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
*bridge_agpstat |= AGPSTAT3_4X;
else {
- printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
+ printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
"[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
origbridge, origvga, *bridge_agpstat, *vga_agpstat);
if (!(*bridge_agpstat & AGPSTAT3_4X))
- printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
+ printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
if (!(*vga_agpstat & AGPSTAT3_4X))
- printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+ printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
return;
}
}
@@ -622,7 +621,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
for (;;) {
device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
if (!device) {
- printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+ printk(KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
return 0;
}
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
@@ -734,7 +733,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
pci_write_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, temp);
- printk (KERN_INFO PFX "Device is in legacy mode,"
+ printk(KERN_INFO PFX "Device is in legacy mode,"
" falling back to 2.x\n");
}
}
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 2a36561eec68..a124f8c5d062 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2053,10 +2053,6 @@ static int __init rs_init(void)
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
- /*
- if(state->port && check_region(state->port,REGION_LENGTH(state)))
- continue;
- */
printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
state->line);
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 11f9ee581124..927a5bbe112c 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -172,7 +172,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
void cleanup_module(void)
{
- int i;
+ unsigned int i;
misc_deregister(&ac_miscdev);
@@ -195,7 +195,7 @@ int __init applicom_init(void)
int i, numisa = 0;
struct pci_dev *dev = NULL;
void __iomem *RamIO;
- int boardno;
+ int boardno, ret;
printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
@@ -294,7 +294,8 @@ int __init applicom_init(void)
}
if (!numisa)
- printk(KERN_WARNING"ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem);
+ printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found "
+ "at mem 0x%lx\n", mem);
fin:
init_waitqueue_head(&FlagSleepRec);
@@ -304,7 +305,11 @@ int __init applicom_init(void)
DeviceErrorCount = 0;
if (numboards) {
- misc_register(&ac_miscdev);
+ ret = misc_register(&ac_miscdev);
+ if (ret) {
+ printk(KERN_WARNING "ac.o: Unable to register misc device\n");
+ goto out;
+ }
for (i = 0; i < MAX_BOARD; i++) {
int serial;
char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
@@ -337,6 +342,17 @@ int __init applicom_init(void)
else
return -ENXIO;
+
+out:
+ for (i = 0; i < MAX_BOARD; i++) {
+ if (!apbs[i].RamIO)
+ continue;
+ if (apbs[i].irq)
+ free_irq(apbs[i].irq, &dummy);
+ iounmap(apbs[i].RamIO);
+ }
+ pci_disable_device(dev);
+ return ret;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 6a5337bf0936..cf4c3648463d 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -865,7 +865,7 @@ static void cyz_poll(unsigned long);
static long cyz_polling_cycle = CZ_DEF_POLL;
static int cyz_timeron = 0;
-static struct timer_list cyz_timerlist = TIMER_INITIALIZER(cyz_poll, 0, 0);
+static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
#else /* CONFIG_CYZ_INTR */
static void cyz_rx_restart(unsigned long);
diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h
index 184378d23f8c..94d4eab5d3ca 100644
--- a/drivers/char/digi1.h
+++ b/drivers/char/digi1.h
@@ -1,46 +1,46 @@
/* Definitions for DigiBoard ditty(1) command. */
#if !defined(TIOCMODG)
-#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */
-#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */
+#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */
+#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */
#endif
#if !defined(TIOCMSET)
-#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */
-#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */
+#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */
+#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */
#endif
#if !defined(TIOCMBIC)
-#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */
-#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */
+#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */
+#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */
#endif
#if !defined(TIOCSDTR)
-#define TIOCSDTR ('e'<<8) | 0 /* set DTR */
-#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */
+#define TIOCSDTR (('e'<<8) | 0) /* set DTR */
+#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */
#endif
/************************************************************************
* Ioctl command arguments for DIGI parameters.
************************************************************************/
-#define DIGI_GETA ('e'<<8) | 94 /* Read params */
+#define DIGI_GETA (('e'<<8) | 94) /* Read params */
-#define DIGI_SETA ('e'<<8) | 95 /* Set params */
-#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */
-#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */
+#define DIGI_SETA (('e'<<8) | 95) /* Set params */
+#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */
+#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */
-#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */
+#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */
/* control characters */
-#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */
+#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */
/* control characters */
-#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */
+#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */
/* flow control chars */
-#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */
+#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */
/* flow control chars */
-#define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */
-#define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */
-#define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */
+#define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */
+#define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */
+#define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */
struct digiflow_struct
{
diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h
index c47d7fcb8400..3c1f1922c798 100644
--- a/drivers/char/digiFep1.h
+++ b/drivers/char/digiFep1.h
@@ -13,88 +13,88 @@
struct global_data
{
- volatile ushort cin;
- volatile ushort cout;
- volatile ushort cstart;
- volatile ushort cmax;
- volatile ushort ein;
- volatile ushort eout;
- volatile ushort istart;
- volatile ushort imax;
+ u16 cin;
+ u16 cout;
+ u16 cstart;
+ u16 cmax;
+ u16 ein;
+ u16 eout;
+ u16 istart;
+ u16 imax;
};
struct board_chan
{
- int filler1;
- int filler2;
- volatile ushort tseg;
- volatile ushort tin;
- volatile ushort tout;
- volatile ushort tmax;
-
- volatile ushort rseg;
- volatile ushort rin;
- volatile ushort rout;
- volatile ushort rmax;
-
- volatile ushort tlow;
- volatile ushort rlow;
- volatile ushort rhigh;
- volatile ushort incr;
-
- volatile ushort etime;
- volatile ushort edelay;
- volatile unchar *dev;
-
- volatile ushort iflag;
- volatile ushort oflag;
- volatile ushort cflag;
- volatile ushort gmask;
-
- volatile ushort col;
- volatile ushort delay;
- volatile ushort imask;
- volatile ushort tflush;
-
- int filler3;
- int filler4;
- int filler5;
- int filler6;
-
- volatile unchar num;
- volatile unchar ract;
- volatile unchar bstat;
- volatile unchar tbusy;
- volatile unchar iempty;
- volatile unchar ilow;
- volatile unchar idata;
- volatile unchar eflag;
-
- volatile unchar tflag;
- volatile unchar rflag;
- volatile unchar xmask;
- volatile unchar xval;
- volatile unchar mstat;
- volatile unchar mchange;
- volatile unchar mint;
- volatile unchar lstat;
-
- volatile unchar mtran;
- volatile unchar orun;
- volatile unchar startca;
- volatile unchar stopca;
- volatile unchar startc;
- volatile unchar stopc;
- volatile unchar vnext;
- volatile unchar hflow;
-
- volatile unchar fillc;
- volatile unchar ochar;
- volatile unchar omask;
-
- unchar filler7;
- unchar filler8[28];
+ u32 filler1;
+ u32 filler2;
+ u16 tseg;
+ u16 tin;
+ u16 tout;
+ u16 tmax;
+
+ u16 rseg;
+ u16 rin;
+ u16 rout;
+ u16 rmax;
+
+ u16 tlow;
+ u16 rlow;
+ u16 rhigh;
+ u16 incr;
+
+ u16 etime;
+ u16 edelay;
+ unchar *dev;
+
+ u16 iflag;
+ u16 oflag;
+ u16 cflag;
+ u16 gmask;
+
+ u16 col;
+ u16 delay;
+ u16 imask;
+ u16 tflush;
+
+ u32 filler3;
+ u32 filler4;
+ u32 filler5;
+ u32 filler6;
+
+ u8 num;
+ u8 ract;
+ u8 bstat;
+ u8 tbusy;
+ u8 iempty;
+ u8 ilow;
+ u8 idata;
+ u8 eflag;
+
+ u8 tflag;
+ u8 rflag;
+ u8 xmask;
+ u8 xval;
+ u8 mstat;
+ u8 mchange;
+ u8 mint;
+ u8 lstat;
+
+ u8 mtran;
+ u8 orun;
+ u8 startca;
+ u8 stopca;
+ u8 startc;
+ u8 stopc;
+ u8 vnext;
+ u8 hflow;
+
+ u8 fillc;
+ u8 ochar;
+ u8 omask;
+
+ u8 filler7;
+ u8 filler8[28];
};
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 123417e43040..56ace9d5e2ae 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -23,13 +23,6 @@ config DRM_TDFX
Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
graphics card. If M is selected, the module will be called tdfx.
-config DRM_GAMMA
- tristate "3dlabs GMX 2000"
- depends on DRM && BROKEN
- help
- This is the old gamma driver, please tell me if it might actually
- work.
-
config DRM_R128
tristate "ATI Rage 128"
depends on DRM && PCI
@@ -82,7 +75,7 @@ endchoice
config DRM_MGA
tristate "Matrox g200/g400"
- depends on DRM && AGP
+ depends on DRM
help
Choose this option if you have a Matrox G200, G400 or G450 graphics
card. If M is selected, the module will be called mga. AGP
@@ -103,3 +96,10 @@ config DRM_VIA
Choose this option if you have a Via unichrome or compatible video
chipset. If M is selected the module will be called via.
+config DRM_SAVAGE
+ tristate "Savage video cards"
+ depends on DRM
+ help
+ Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+ chipset. If M is selected the module will be called savage.
+
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index ddd941045b1f..e41060c76226 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -8,16 +8,16 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
drm_sysfs.o
-gamma-objs := gamma_drv.o gamma_dma.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
i810-objs := i810_drv.o i810_dma.o
i830-objs := i830_drv.o i830_dma.o i830_irq.o
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_ds.o sis_mm.o
+savage-objs := savage_drv.o savage_bci.o savage_state.o
via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
ifeq ($(CONFIG_COMPAT),y)
@@ -29,7 +29,6 @@ i915-objs += i915_ioc32.o
endif
obj-$(CONFIG_DRM) += drm.o
-obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
obj-$(CONFIG_DRM_R128) += r128.o
obj-$(CONFIG_DRM_RADEON)+= radeon.o
@@ -39,5 +38,7 @@ obj-$(CONFIG_DRM_I830) += i830.o
obj-$(CONFIG_DRM_I915) += i915.o
obj-$(CONFIG_DRM_FFB) += ffb.o
obj-$(CONFIG_DRM_SIS) += sis.o
+obj-$(CONFIG_DRM_SAVAGE)+= savage.o
obj-$(CONFIG_DRM_VIA) +=via.o
+
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index e8371dd87fbc..fc6598a81acd 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -98,7 +98,7 @@
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
-typedef unsigned long drm_handle_t;
+typedef unsigned int drm_handle_t;
typedef unsigned int drm_context_t;
typedef unsigned int drm_drawable_t;
typedef unsigned int drm_magic_t;
@@ -209,7 +209,8 @@ typedef enum drm_map_type {
_DRM_REGISTERS = 1, /**< no caching, no core dump */
_DRM_SHM = 2, /**< shared, cached */
_DRM_AGP = 3, /**< AGP/GART */
- _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
+ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
+ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
} drm_map_type_t;
@@ -368,7 +369,8 @@ typedef struct drm_buf_desc {
enum {
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
- _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
+ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
+ _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
} flags;
unsigned long agp_start; /**<
* Start address of where the AGP buffers are
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 5df09cc8c6db..121cc85f347e 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -53,7 +53,6 @@
#include <linux/init.h>
#include <linux/file.h>
#include <linux/pci.h>
-#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/smp_lock.h> /* For (un)lock_kernel */
#include <linux/mm.h>
@@ -96,6 +95,7 @@
#define DRIVER_IRQ_SHARED 0x80
#define DRIVER_IRQ_VBL 0x100
#define DRIVER_DMA_QUEUE 0x200
+#define DRIVER_FB_DMA 0x400
/***********************************************************************/
/** \name Begin the DRM... */
@@ -160,36 +160,7 @@
#define pte_unmap(pte)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
-static inline struct page * vmalloc_to_page(void * vmalloc_addr)
-{
- unsigned long addr = (unsigned long) vmalloc_addr;
- struct page *page = NULL;
- pgd_t *pgd = pgd_offset_k(addr);
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, addr);
- if (!pmd_none(*pmd)) {
- preempt_disable();
- ptep = pte_offset_map(pmd, addr);
- pte = *ptep;
- if (pte_present(pte))
- page = pte_page(pte);
- pte_unmap(ptep);
- preempt_enable();
- }
- }
- return page;
-}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define DRM_RPR_ARG(vma)
-#else
#define DRM_RPR_ARG(vma) vma,
-#endif
#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
@@ -474,7 +445,8 @@ typedef struct drm_device_dma {
unsigned long byte_count;
enum {
_DRM_DMA_USE_AGP = 0x01,
- _DRM_DMA_USE_SG = 0x02
+ _DRM_DMA_USE_SG = 0x02,
+ _DRM_DMA_USE_FB = 0x04
} flags;
} drm_device_dma_t;
@@ -525,12 +497,19 @@ 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
*/
typedef struct drm_map_list {
struct list_head head; /**< list head */
drm_map_t *map; /**< mapping */
+ unsigned int user_token;
} drm_map_list_t;
typedef drm_map_t drm_local_map_t;
@@ -578,7 +557,22 @@ struct drm_driver {
int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+
+ /**
+ * Called by \c drm_device_is_agp. Typically used to determine if a
+ * card is really attached to AGP or not.
+ *
+ * \param dev DRM device handle
+ *
+ * \returns
+ * One of three values is returned depending on whether or not the
+ * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
+ * (return of 1), or may or may not be AGP (return of 2).
+ */
+ int (*device_is_agp) (struct drm_device * dev);
+
/* these have to be filled in */
+
int (*postinit)(struct drm_device *, unsigned long flags);
irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
void (*irq_preinstall)(struct drm_device *dev);
@@ -722,12 +716,8 @@ typedef struct drm_device {
int pci_slot; /**< PCI slot number */
int pci_func; /**< PCI function number */
#ifdef __alpha__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
- struct pci_controler *hose;
-#else
struct pci_controller *hose;
#endif
-#endif
drm_sg_mem_t *sg; /**< Scatter gather memory */
unsigned long *ctx_bitmap; /**< context bitmap */
void *dev_private; /**< device private data */
@@ -736,6 +726,7 @@ typedef struct drm_device {
struct drm_driver *driver;
drm_local_map_t *agp_buffer_map;
+ unsigned int agp_buffer_token;
drm_head_t primary; /**< primary screen head */
} drm_device_t;
@@ -806,7 +797,7 @@ 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(struct agp_bridge_data *bridge, int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type);
extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
extern int drm_unbind_agp(DRM_AGP_MEM *handle);
@@ -881,11 +872,19 @@ extern int drm_lock_free(drm_device_t *dev,
unsigned int context);
/* Buffer management support (drm_bufs.h) */
+extern int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
+extern int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request);
+extern int drm_addmap(drm_device_t *dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_local_map_t **map_ptr);
+extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map);
+extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map);
+extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
extern int drm_order( unsigned long size );
-extern int drm_addmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_rmmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
extern int drm_addbufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
extern int drm_infobufs( struct inode *inode, struct file *filp,
@@ -896,6 +895,10 @@ extern int drm_freebufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
extern int drm_mapbufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
+extern unsigned long drm_get_resource_start(drm_device_t *dev,
+ unsigned int resource);
+extern unsigned long drm_get_resource_len(drm_device_t *dev,
+ unsigned int resource);
/* DMA support (drm_dma.h) */
extern int drm_dma_setup(drm_device_t *dev);
@@ -919,15 +922,18 @@ extern void drm_vbl_send_signals( drm_device_t *dev );
/* AGP/GART support (drm_agpsupport.h) */
extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
-extern int drm_agp_acquire(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern void drm_agp_do_release(drm_device_t *dev);
-extern int drm_agp_release(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_enable(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+extern int drm_agp_acquire(drm_device_t * dev);
+extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_release(drm_device_t *dev);
+extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode);
+extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info);
+extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
extern int drm_agp_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_agp_free(struct inode *inode, struct file *filp,
@@ -976,12 +982,10 @@ extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
unsigned long addr,
dma_addr_t bus_addr);
-extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
- size_t align, dma_addr_t maxaddr,
- dma_addr_t * busaddr);
-
-extern void drm_pci_free(drm_device_t * dev, size_t size,
- void *vaddr, dma_addr_t busaddr);
+extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size,
+ size_t align, dma_addr_t maxaddr);
+extern void __drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
+extern void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
/* sysfs support (drm_sysfs.c) */
struct drm_sysfs_class;
@@ -1012,17 +1016,26 @@ static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_devi
drm_ioremapfree( map->handle, map->size, dev );
}
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned int token)
{
- struct list_head *_list;
- list_for_each( _list, &dev->maplist->head ) {
- drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
- if ( _entry->map &&
- _entry->map->offset == offset ) {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head)
+ if (_entry->user_token == token)
return _entry->map;
+ return NULL;
+}
+
+static __inline__ int drm_device_is_agp(drm_device_t *dev)
+{
+ if ( dev->driver->device_is_agp != NULL ) {
+ int err = (*dev->driver->device_is_agp)( dev );
+
+ if (err != 2) {
+ return err;
}
}
- return NULL;
+
+ return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
}
static __inline__ void drm_core_dropmap(struct drm_map *map)
@@ -1058,5 +1071,9 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
extern unsigned long drm_core_get_map_ofs(drm_map_t *map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
+#ifndef pci_pretty_name
+#define pci_pretty_name(dev) ""
+#endif
+
#endif /* __KERNEL__ */
#endif
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 8d94c0b5fa44..8c215adcb4b2 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -37,7 +37,7 @@
#if __OS_HAS_AGP
/**
- * AGP information ioctl.
+ * Get AGP information.
*
* \param inode device inode.
* \param filp file pointer.
@@ -48,51 +48,56 @@
* Verifies the AGP device has been initialized and acquired and fills in the
* drm_agp_info structure with the information in drm_agp_head::agp_info.
*/
-int drm_agp_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
DRM_AGP_KERN *kern;
- drm_agp_info_t info;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
kern = &dev->agp->agp_info;
- info.agp_version_major = kern->version.major;
- info.agp_version_minor = kern->version.minor;
- info.mode = kern->mode;
- info.aperture_base = kern->aper_base;
- info.aperture_size = kern->aper_size * 1024 * 1024;
- info.memory_allowed = kern->max_memory << PAGE_SHIFT;
- info.memory_used = kern->current_memory << PAGE_SHIFT;
- info.id_vendor = kern->device->vendor;
- info.id_device = kern->device->device;
-
- if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info)))
+ info->agp_version_major = kern->version.major;
+ info->agp_version_minor = kern->version.minor;
+ info->mode = kern->mode;
+ info->aperture_base = kern->aper_base;
+ info->aperture_size = kern->aper_size * 1024 * 1024;
+ info->memory_allowed = kern->max_memory << PAGE_SHIFT;
+ info->memory_used = kern->current_memory << PAGE_SHIFT;
+ info->id_vendor = kern->device->vendor;
+ info->id_device = kern->device->device;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_agp_info);
+
+int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_info_t info;
+ int err;
+
+ err = drm_agp_info(dev, &info);
+ if (err)
+ return err;
+
+ if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
return -EFAULT;
return 0;
}
/**
- * Acquire the AGP device (ioctl).
+ * Acquire the AGP device.
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
+ * \param dev DRM device that is to acquire AGP
* \return zero on success or a negative number on failure.
*
* Verifies the AGP device hasn't been acquired before and calls
- * agp_acquire().
+ * \c agp_backend_acquire.
*/
-int drm_agp_acquire(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_acquire(drm_device_t *dev)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
-
if (!dev->agp)
return -ENODEV;
if (dev->agp->acquired)
@@ -102,9 +107,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
dev->agp->acquired = 1;
return 0;
}
+EXPORT_SYMBOL(drm_agp_acquire);
/**
- * Release the AGP device (ioctl).
+ * Acquire the AGP device (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
@@ -112,63 +118,80 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
* \param arg user argument.
* \return zero on success or a negative number on failure.
*
- * Verifies the AGP device has been acquired and calls agp_backend_release().
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
*/
-int drm_agp_release(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+
+ return drm_agp_acquire( (drm_device_t *) priv->head->dev );
+}
+/**
+ * Release the AGP device.
+ *
+ * \param dev DRM device that is to release AGP
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
+int drm_agp_release(drm_device_t *dev)
+{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
-
}
+EXPORT_SYMBOL(drm_agp_release);
-/**
- * Release the AGP device.
- *
- * Calls agp_backend_release().
- */
-void drm_agp_do_release(drm_device_t *dev)
+int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- agp_backend_release(dev->agp->bridge);
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+
+ return drm_agp_release(dev);
}
/**
* Enable the AGP bus.
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_agp_mode structure.
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
* \return zero on success or a negative number on failure.
*
* Verifies the AGP device has been acquired but not enabled, and calls
- * agp_enable().
+ * \c agp_enable.
*/
-int drm_agp_enable(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_mode_t mode;
-
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode)))
- return -EFAULT;
-
dev->agp->mode = mode.mode;
agp_enable(dev->agp->bridge, mode.mode);
dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1;
return 0;
}
+EXPORT_SYMBOL(drm_agp_enable);
+
+int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_mode_t mode;
+
+
+ if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+ return -EFAULT;
+
+ return drm_agp_enable(dev, mode);
+}
/**
* Allocate AGP memory.
@@ -206,7 +229,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request.type;
- if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
+ if (!(memory = drm_alloc_agp(dev, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM;
}
@@ -403,13 +426,8 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
return NULL;
}
head->memory = NULL;
-#if LINUX_VERSION_CODE <= 0x020408
- head->cant_use_aperture = 0;
- head->page_mask = ~(0xfff);
-#else
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
-#endif
return head;
}
@@ -436,6 +454,7 @@ int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
return -EINVAL;
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 4c6191d231b8..f28e70ae6606 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,37 +36,69 @@
#include <linux/vmalloc.h>
#include "drmP.h"
-/**
- * Compute size order. Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- *
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order( unsigned long size )
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
{
- int order;
- unsigned long tmp;
+ return pci_resource_start(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_start);
- for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
- ;
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+{
+ return pci_resource_len(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_len);
- if (size & (size - 1))
- ++order;
+static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+ drm_local_map_t *map)
+{
+ struct list_head *list;
- return order;
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+ if (entry->map && map->type == entry->map->type &&
+ entry->map->offset == map->offset) {
+ return entry;
+ }
+ }
+
+ return NULL;
}
-EXPORT_SYMBOL(drm_order);
-#ifdef CONFIG_COMPAT
/*
- * Used to allocate 32-bit handles for _DRM_SHM regions
- * The 0x10000000 value is chosen to be out of the way of
- * FB/register and GART physical addresses.
+ * Used to allocate 32-bit handles for mappings.
*/
-static unsigned int map32_handle = 0x10000000;
+#define START_RANGE 0x10000000
+#define END_RANGE 0x40000000
+
+#ifdef _LP64
+static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev)
+{
+ static unsigned int map32_handle = START_RANGE;
+ unsigned int hash;
+
+ if (lhandle & 0xffffffff00000000) {
+ hash = map32_handle;
+ map32_handle += PAGE_SIZE;
+ if (map32_handle > END_RANGE)
+ map32_handle = START_RANGE;
+ } else
+ hash = lhandle;
+
+ while (1) {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head,head) {
+ if (_entry->user_token == hash)
+ break;
+ }
+ if (&_entry->head == &dev->maplist->head)
+ return hash;
+
+ hash += PAGE_SIZE;
+ map32_handle += PAGE_SIZE;
+ }
+}
+#else
+# define HandleID(x,dev) (unsigned int)(x)
#endif
/**
@@ -82,25 +114,22 @@ static unsigned int map32_handle = 0x10000000;
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel.
*/
-int drm_addmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addmap_core(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_map_list_t **maplist)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_map_t *map;
- drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list;
-
- if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
+ drm_dma_handle_t *dmah;
map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
if ( !map )
return -ENOMEM;
- if ( copy_from_user( map, argp, sizeof(*map) ) ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
- return -EFAULT;
- }
+ map->offset = offset;
+ map->size = size;
+ map->flags = flags;
+ map->type = type;
/* Only allow shared memory to be removable since we only keep enough
* book keeping information about shared memory to allow for removal
@@ -122,7 +151,7 @@ int drm_addmap( struct inode *inode, struct file *filp,
switch ( map->type ) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
if ( map->offset + map->size < map->offset ||
map->offset < virt_to_phys(high_memory) ) {
drm_free( map, sizeof(*map), DRM_MEM_MAPS );
@@ -132,6 +161,24 @@ int drm_addmap( struct inode *inode, struct file *filp,
#ifdef __alpha__
map->offset += dev->hose->mem_space->start;
#endif
+ /* Some drivers preinitialize some maps, without the X Server
+ * needing to be aware of it. Therefore, we just return success
+ * when the server tries to create a duplicate map.
+ */
+ list = drm_find_matching_map(dev, map);
+ if (list != NULL) {
+ if (list->map->size != map->size) {
+ DRM_DEBUG("Matching maps of type %d with "
+ "mismatched sizes, (%ld vs %ld)\n",
+ map->type, map->size, list->map->size);
+ list->map->size = map->size;
+ }
+
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ *maplist = list;
+ return 0;
+ }
+
if (drm_core_has_MTRR(dev)) {
if ( map->type == _DRM_FRAME_BUFFER ||
(map->flags & _DRM_WRITE_COMBINING) ) {
@@ -178,9 +225,22 @@ int drm_addmap( struct inode *inode, struct file *filp,
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
- map->offset += dev->sg->handle;
+ map->offset += (unsigned long)dev->sg->virtual;
+ break;
+ case _DRM_CONSISTENT:
+ /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+ * As we're limiting the address to 2^32-1 (or less),
+ * casting it down to 32 bits is no problem, but we
+ * need to point to a 64bit variable first. */
+ dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+ if (!dmah) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+ map->handle = dmah->vaddr;
+ map->offset = (unsigned long)dmah->busaddr;
+ kfree(dmah);
break;
-
default:
drm_free( map, sizeof(*map), DRM_MEM_MAPS );
return -EINVAL;
@@ -196,17 +256,57 @@ int drm_addmap( struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_add(&list->head, &dev->maplist->head);
-#ifdef CONFIG_COMPAT
- /* Assign a 32-bit handle for _DRM_SHM mappings */
+ /* Assign a 32-bit handle */
/* We do it here so that dev->struct_sem protects the increment */
- if (map->type == _DRM_SHM)
- map->offset = map32_handle += PAGE_SIZE;
-#endif
+ list->user_token = HandleID(map->type==_DRM_SHM
+ ? (unsigned long)map->handle
+ : map->offset, dev);
up(&dev->struct_sem);
- if ( copy_to_user( argp, map, sizeof(*map) ) )
+ *maplist = list;
+ return 0;
+}
+
+int drm_addmap(drm_device_t *dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_local_map_t **map_ptr)
+{
+ drm_map_list_t *list;
+ int rc;
+
+ rc = drm_addmap_core(dev, offset, size, type, flags, &list);
+ if (!rc)
+ *map_ptr = list->map;
+ return rc;
+}
+EXPORT_SYMBOL(drm_addmap);
+
+int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_map_t map;
+ drm_map_list_t *maplist;
+ drm_map_t __user *argp = (void __user *)arg;
+ int err;
+
+ if (!(filp->f_mode & 3))
+ return -EACCES; /* Require read/write */
+
+ if (copy_from_user(& map, argp, sizeof(map))) {
return -EFAULT;
- if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
+ }
+
+ err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
+ &maplist);
+
+ if (err)
+ return err;
+
+ if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+ return -EFAULT;
+ if (put_user(maplist->user_token, &argp->handle))
return -EFAULT;
return 0;
}
@@ -226,81 +326,138 @@ int drm_addmap( struct inode *inode, struct file *filp,
* its being used, and free any associate resource (such as MTRR's) if it's not
* being on use.
*
- * \sa addmap().
+ * \sa drm_addmap
*/
-int drm_rmmap(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
struct list_head *list;
drm_map_list_t *r_list = NULL;
- drm_vma_entry_t *pt, *prev;
- drm_map_t *map;
+ drm_dma_handle_t dmah;
+
+ /* Find the list entry for the map and remove it */
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+
+ if (r_list->map == map) {
+ list_del(list);
+ drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+ break;
+ }
+ }
+
+ /* List has wrapped around to the head pointer, or it's empty and we
+ * didn't find anything.
+ */
+ if (list == (&dev->maplist->head)) {
+ return -EINVAL;
+ }
+
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ drm_ioremapfree(map->handle, map->size, dev);
+ /* FALLTHROUGH */
+ case _DRM_FRAME_BUFFER:
+ if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+ int retcode;
+ retcode = mtrr_del(map->mtrr, map->offset,
+ map->size);
+ DRM_DEBUG ("mtrr_del=%d\n", retcode);
+ }
+ break;
+ case _DRM_SHM:
+ vfree(map->handle);
+ break;
+ case _DRM_AGP:
+ case _DRM_SCATTER_GATHER:
+ break;
+ case _DRM_CONSISTENT:
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ __drm_pci_free(dev, &dmah);
+ break;
+ }
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_rmmap_locked);
+
+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+{
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_rmmap_locked(dev, map);
+ up(&dev->struct_sem);
+
+ 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
+ * exit uncleanly. Therefore, having userland manually remove mappings seems
+ * like a pointless exercise since they're going away anyway.
+ *
+ * One use case might be after addmap is allowed for normal users for SHM and
+ * gets used by drivers that the server doesn't need to care about. This seems
+ * unlikely.
+ */
+int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_map_t request;
- int found_maps = 0;
+ drm_local_map_t *map = NULL;
+ struct list_head *list;
+ int ret;
- if (copy_from_user(&request, (drm_map_t __user *)arg,
- sizeof(request))) {
+ if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) {
return -EFAULT;
}
down(&dev->struct_sem);
- list = &dev->maplist->head;
list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
- if(r_list->map &&
- r_list->map->offset == (unsigned long) request.handle &&
- r_list->map->flags & _DRM_REMOVABLE) break;
+ if (r_list->map &&
+ r_list->user_token == (unsigned long) request.handle &&
+ r_list->map->flags & _DRM_REMOVABLE) {
+ map = r_list->map;
+ break;
+ }
}
/* List has wrapped around to the head pointer, or its empty we didn't
* find anything.
*/
- if(list == (&dev->maplist->head)) {
+ if (list == (&dev->maplist->head)) {
up(&dev->struct_sem);
return -EINVAL;
}
- map = r_list->map;
- list_del(list);
- drm_free(list, sizeof(*list), DRM_MEM_MAPS);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
- if (pt->vma->vm_private_data == map) found_maps++;
- }
+ if (!map)
+ return -EINVAL;
- if(!found_maps) {
- switch (map->type) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev)) {
- if (map->mtrr >= 0) {
- int retcode;
- retcode = mtrr_del(map->mtrr,
- map->offset,
- map->size);
- DRM_DEBUG("mtrr_del = %d\n", retcode);
- }
- }
- drm_ioremapfree(map->handle, map->size, dev);
- break;
- case _DRM_SHM:
- vfree(map->handle);
- break;
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- break;
- }
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ /* Register and framebuffer maps are permanent */
+ if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+ up(&dev->struct_sem);
+ return 0;
}
+
+ ret = drm_rmmap_locked(dev, map);
+
up(&dev->struct_sem);
- return 0;
+
+ return ret;
}
/**
* Cleanup after an error on one of the addbufs() functions.
*
+ * \param dev DRM device.
* \param entry buffer entry where the error occurred.
*
* Frees any pages and buffers associated with the given entry.
@@ -344,25 +501,19 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
#if __OS_HAS_AGP
/**
- * Add AGP buffers for DMA transfers (ioctl).
+ * Add AGP buffers for DMA transfers.
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param dev drm_device_t to which the buffers are to be added.
+ * \param request pointer to a drm_buf_desc_t describing the request.
* \return zero on success or a negative number on failure.
*
* After some sanity checks creates a drm_buf structure for each buffer and
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
-static int drm_addbufs_agp( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
drm_buf_entry_t *entry;
drm_buf_t *buf;
unsigned long offset;
@@ -376,25 +527,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp,
int byte_count;
int i;
drm_buf_t **temp_buflist;
- drm_buf_desc_t __user *argp = (void __user *)arg;
if ( !dma ) return -EINVAL;
- if ( copy_from_user( &request, argp,
- sizeof(request) ) )
- return -EFAULT;
-
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
- alignment = (request.flags & _DRM_PAGE_ALIGN)
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
- agp_offset = dev->agp->base + request.agp_start;
+ agp_offset = dev->agp->base + request->agp_start;
DRM_DEBUG( "count: %d\n", count );
DRM_DEBUG( "order: %d\n", order );
@@ -508,26 +654,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp,
up( &dev->struct_sem );
- request.count = entry->buf_count;
- request.size = size;
-
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
dma->flags = _DRM_DMA_USE_AGP;
atomic_dec( &dev->buf_alloc );
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
-static int drm_addbufs_pci( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
int count;
int order;
int size;
@@ -543,26 +683,22 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
int page_count;
unsigned long *temp_pagelist;
drm_buf_t **temp_buflist;
- drm_buf_desc_t __user *argp = (void __user *)arg;
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
if ( !dma ) return -EINVAL;
- if ( copy_from_user( &request, argp, sizeof(request) ) )
- return -EFAULT;
-
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
- request.count, request.size, size,
+ request->count, request->size, size,
order, dev->queue_count );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
if ( dev->queue_count ) return -EBUSY; /* Not while in use */
- alignment = (request.flags & _DRM_PAGE_ALIGN)
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
@@ -740,25 +876,18 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
up( &dev->struct_sem );
- request.count = entry->buf_count;
- request.size = size;
-
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
atomic_dec( &dev->buf_alloc );
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_pci);
-static int drm_addbufs_sg( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t __user *argp = (void __user *)arg;
- drm_buf_desc_t request;
drm_buf_entry_t *entry;
drm_buf_t *buf;
unsigned long offset;
@@ -777,20 +906,17 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
if ( !dma ) return -EINVAL;
- if ( copy_from_user( &request, argp, sizeof(request) ) )
- return -EFAULT;
-
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
- alignment = (request.flags & _DRM_PAGE_ALIGN)
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
- agp_offset = request.agp_start;
+ agp_offset = request->agp_start;
DRM_DEBUG( "count: %d\n", count );
DRM_DEBUG( "order: %d\n", order );
@@ -848,7 +974,8 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+ buf->address = (void *)(agp_offset + offset
+ + (unsigned long)dev->sg->virtual);
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
@@ -905,11 +1032,8 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
up( &dev->struct_sem );
- request.count = entry->buf_count;
- request.size = size;
-
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
dma->flags = _DRM_DMA_USE_SG;
@@ -917,6 +1041,161 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
return 0;
}
+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;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+
+ if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
+
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
+
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = request->agp_start;
+
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ if (dev->queue_count)
+ return -EBUSY; /* Not while in use */
+
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
+
+ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
+
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while (entry->buf_count < count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+ temp_buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+ up(&dev->struct_sem);
+
+ request->count = entry->buf_count;
+ request->size = size;
+
+ dma->flags = _DRM_DMA_USE_FB;
+
+ atomic_dec(&dev->buf_alloc);
+ return 0;
+}
+
/**
* Add buffers for DMA transfers (ioctl).
*
@@ -937,6 +1216,7 @@ int drm_addbufs( struct inode *inode, struct file *filp,
drm_buf_desc_t request;
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
+ int ret;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@@ -947,13 +1227,23 @@ int drm_addbufs( struct inode *inode, struct file *filp,
#if __OS_HAS_AGP
if ( request.flags & _DRM_AGP_BUFFER )
- return drm_addbufs_agp( inode, filp, cmd, arg );
+ ret=drm_addbufs_agp(dev, &request);
else
#endif
if ( request.flags & _DRM_SG_BUFFER )
- return drm_addbufs_sg( inode, filp, cmd, arg );
+ ret=drm_addbufs_sg(dev, &request);
+ else if ( request.flags & _DRM_FB_BUFFER)
+ ret=drm_addbufs_fb(dev, &request);
else
- return drm_addbufs_pci( inode, filp, cmd, arg );
+ ret=drm_addbufs_pci(dev, &request);
+
+ if (ret==0) {
+ if (copy_to_user((void __user *)arg, &request,
+ sizeof(request))) {
+ ret = -EFAULT;
+ }
+ }
+ return ret;
}
@@ -1196,43 +1486,31 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
return -EFAULT;
if ( request.count >= dma->buf_count ) {
- if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
- (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
+ if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+ || (drm_core_check_feature(dev, DRIVER_SG)
+ && (dma->flags & _DRM_DMA_USE_SG))
+ || (drm_core_check_feature(dev, DRIVER_FB_DMA)
+ && (dma->flags & _DRM_DMA_USE_FB))) {
drm_map_t *map = dev->agp_buffer_map;
+ unsigned long token = dev->agp_buffer_token;
if ( !map ) {
retcode = -EINVAL;
goto done;
}
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
down_write( &current->mm->mmap_sem );
-#endif
virtual = do_mmap( filp, 0, map->size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
- (unsigned long)map->offset );
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
+ token );
up_write( &current->mm->mmap_sem );
-#endif
} else {
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
down_write( &current->mm->mmap_sem );
-#endif
virtual = do_mmap( filp, 0, dma->byte_count,
PROT_READ | PROT_WRITE,
MAP_SHARED, 0 );
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
up_write( &current->mm->mmap_sem );
-#endif
}
if ( virtual > -1024UL ) {
/* Real error */
@@ -1279,3 +1557,26 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
return retcode;
}
+/**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+int drm_order( unsigned long size )
+{
+ int order;
+ unsigned long tmp;
+
+ for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
+ ;
+
+ if (size & (size - 1))
+ ++order;
+
+ return order;
+}
+EXPORT_SYMBOL(drm_order);
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index a7cfabd1ca2e..502892794c16 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -212,6 +212,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
drm_ctx_priv_map_t request;
drm_map_t *map;
+ drm_map_list_t *_entry;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
@@ -225,7 +226,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
map = dev->context_sareas[request.ctx_id];
up(&dev->struct_sem);
- request.handle = (void *) map->offset;
+ request.handle = 0;
+ list_for_each_entry(_entry, &dev->maplist->head,head) {
+ if (_entry->map == map) {
+ request.handle = (void *)(unsigned long)_entry->user_token;
+ break;
+ }
+ }
+ if (request.handle == 0)
+ return -EINVAL;
+
+
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
@@ -262,7 +273,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
if (r_list->map
- && r_list->map->offset == (unsigned long) request.handle)
+ && r_list->user_token == (unsigned long) request.handle)
goto found;
}
bad:
@@ -297,7 +308,7 @@ found:
*
* Attempt to set drm_device::context_flag.
*/
-int drm_context_switch( drm_device_t *dev, int old, int new )
+static int drm_context_switch( drm_device_t *dev, int old, int new )
{
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
DRM_ERROR( "Reentering -- FIXME\n" );
@@ -369,7 +380,7 @@ int drm_resctx( struct inode *inode, struct file *filp,
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
ctx.handle = i;
if ( copy_to_user( &res.contexts[i],
- &i, sizeof(i) ) )
+ &ctx, sizeof(ctx) ) )
return -EFAULT;
}
}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 3333c250c4d9..6ba48f346fcf 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -70,8 +70,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl,1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
@@ -102,10 +102,10 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
#if __OS_HAS_AGP
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
@@ -127,14 +127,12 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* Frees every resource in \p dev.
*
- * \sa drm_device and setup().
+ * \sa drm_device
*/
int drm_takedown( drm_device_t *dev )
{
drm_magic_entry_t *pt, *next;
- drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list, *list_next;
drm_vma_entry_t *vma, *vma_next;
int i;
@@ -142,6 +140,7 @@ int drm_takedown( drm_device_t *dev )
if (dev->driver->pretakedown)
dev->driver->pretakedown(dev);
+ DRM_DEBUG("driver pretakedown completed\n");
if (dev->unique) {
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -178,11 +177,16 @@ int drm_takedown( drm_device_t *dev )
}
dev->agp->memory = NULL;
- if ( dev->agp->acquired ) drm_agp_do_release(dev);
+ if (dev->agp->acquired)
+ drm_agp_release(dev);
dev->agp->acquired = 0;
dev->agp->enabled = 0;
}
+ if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+ drm_sg_cleanup(dev->sg);
+ dev->sg = NULL;
+ }
/* Clear vma list (only built for debugging) */
if ( dev->vmalist ) {
@@ -194,48 +198,11 @@ int drm_takedown( drm_device_t *dev )
}
if( dev->maplist ) {
- list_for_each_safe( list, list_next, &dev->maplist->head ) {
- r_list = (drm_map_list_t *)list;
-
- if ( ( map = r_list->map ) ) {
- switch ( map->type ) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev)) {
- if ( map->mtrr >= 0 ) {
- int retcode;
- retcode = mtrr_del( map->mtrr,
- map->offset,
- map->size );
- DRM_DEBUG( "mtrr_del=%d\n", retcode );
- }
- }
- drm_ioremapfree( map->handle, map->size, dev );
- break;
- case _DRM_SHM:
- vfree(map->handle);
- break;
-
- case _DRM_AGP:
- /* Do nothing here, because this is all
- * handled in the AGP/GART driver.
- */
- break;
- case _DRM_SCATTER_GATHER:
- /* Handle it */
- if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
- drm_sg_cleanup(dev->sg);
- dev->sg = NULL;
- }
- break;
- }
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- }
- list_del( list );
- drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
- }
- drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
- dev->maplist = NULL;
+ while (!list_empty(&dev->maplist->head)) {
+ struct list_head *list = dev->maplist->head.next;
+ r_list = list_entry(list, drm_map_list_t, head);
+ drm_rmmap_locked(dev, r_list->map);
+ }
}
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
@@ -264,6 +231,7 @@ int drm_takedown( drm_device_t *dev )
}
up( &dev->struct_sem );
+ DRM_DEBUG("takedown completed\n");
return 0;
}
@@ -312,7 +280,7 @@ EXPORT_SYMBOL(drm_init);
*
* Cleans up all DRM device, calling takedown().
*
- * \sa drm_init().
+ * \sa drm_init
*/
static void drm_cleanup( drm_device_t *dev )
{
@@ -325,6 +293,11 @@ static void drm_cleanup( drm_device_t *dev )
drm_takedown( dev );
+ if (dev->maplist) {
+ drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ }
+
drm_ctxbitmap_cleanup( dev );
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 10e64fde8d78..a1f4e9cd64ed 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -71,12 +71,6 @@ static int drm_setup( drm_device_t *dev )
dev->magiclist[i].tail = NULL;
}
- dev->maplist = drm_alloc(sizeof(*dev->maplist),
- DRM_MEM_MAPS);
- if(dev->maplist == NULL) return -ENOMEM;
- memset(dev->maplist, 0, sizeof(*dev->maplist));
- INIT_LIST_HEAD(&dev->maplist->head);
-
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
DRM_MEM_CTXLIST);
if(dev->ctxlist == NULL) return -ENOMEM;
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 39afda0ccabe..d2ed3ba5aca9 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -208,7 +208,7 @@ int drm_getmap( struct inode *inode, struct file *filp,
map.size = r_list->map->size;
map.type = r_list->map->type;
map.flags = r_list->map->flags;
- map.handle = r_list->map->handle;
+ map.handle = (void *)(unsigned long) r_list->user_token;
map.mtrr = r_list->map->mtrr;
up(&dev->struct_sem);
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index ace3d42f4407..ff483fb418aa 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -142,27 +142,31 @@ void drm_free_pages(unsigned long address, int order, int area)
#if __OS_HAS_AGP
/** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
{
- return drm_agp_allocate_memory(bridge, pages, type);
+ return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
}
+EXPORT_SYMBOL(drm_alloc_agp);
/** Wrapper around agp_free_memory() */
int drm_free_agp(DRM_AGP_MEM *handle, int pages)
{
return drm_agp_free_memory(handle) ? 0 : -EINVAL;
}
+EXPORT_SYMBOL(drm_free_agp);
/** Wrapper around agp_bind_memory() */
int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
{
return drm_agp_bind_memory(handle, start);
}
+EXPORT_SYMBOL(drm_bind_agp);
/** Wrapper around agp_unbind_memory() */
int drm_unbind_agp(DRM_AGP_MEM *handle)
{
return drm_agp_unbind_memory(handle);
}
+EXPORT_SYMBOL(drm_unbind_agp);
#endif /* agp */
#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 192e8762571c..09ed712c1a7f 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -46,11 +46,11 @@
/**
* \brief Allocate a PCI consistent memory block, for DMA.
*/
-void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
- dma_addr_t maxaddr, dma_addr_t * busaddr)
+drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+ dma_addr_t maxaddr)
{
- void *address;
-#if DRM_DEBUG_MEMORY
+ drm_dma_handle_t *dmah;
+#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
spin_lock(&drm_mem_lock);
@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
return NULL;
}
- address = pci_alloc_consistent(dev->pdev, size, busaddr);
+ dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+ if (!dmah)
+ return NULL;
+
+ dmah->size = size;
+ dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
-#if DRM_DEBUG_MEMORY
- if (address == NULL) {
+#ifdef DRM_DEBUG_MEMORY
+ if (dmah->vaddr == NULL) {
spin_lock(&drm_mem_lock);
++drm_mem_stats[area].fail_count;
spin_unlock(&drm_mem_lock);
+ kfree(dmah);
return NULL;
}
@@ -90,37 +96,42 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
drm_ram_used += size;
spin_unlock(&drm_mem_lock);
#else
- if (address == NULL)
+ if (dmah->vaddr == NULL) {
+ kfree(dmah);
return NULL;
+ }
#endif
- memset(address, 0, size);
+ memset(dmah->vaddr, 0, size);
- return address;
+ return dmah;
}
EXPORT_SYMBOL(drm_pci_alloc);
/**
- * \brief Free a PCI consistent memory block.
+ * \brief Free a PCI consistent memory block with freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
*/
void
-drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
+__drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
{
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
int alloc_count;
int free_count;
#endif
- if (!vaddr) {
-#if DRM_DEBUG_MEMORY
+ if (!dmah->vaddr) {
+#ifdef DRM_DEBUG_MEMORY
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif
} else {
- pci_free_consistent(dev->pdev, size, vaddr, busaddr);
+ pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
+ dmah->busaddr);
}
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
spin_lock(&drm_mem_lock);
free_count = ++drm_mem_stats[area].free_count;
alloc_count = drm_mem_stats[area].succeed_count;
@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
#endif
}
+
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void
+drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
+{
+ __drm_pci_free(dev, dmah);
+ kfree(dmah);
+}
EXPORT_SYMBOL(drm_pci_free);
/*@}*/
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 70ca4fa55c9d..58b1747cd440 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -25,6 +25,8 @@
{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, 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}, \
@@ -33,7 +35,17 @@
{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, 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, 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, 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, 0x4E54, 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}, \
{0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
@@ -56,6 +68,7 @@
{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, 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}, \
@@ -116,9 +129,10 @@
{0, 0, 0}
#define mga_PCI_IDS \
- {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+ {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+ {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \
+ {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \
{0, 0, 0}
#define mach64_PCI_IDS \
@@ -162,9 +176,10 @@
#define viadrv_PCI_IDS \
{0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
#define i810_PCI_IDS \
@@ -181,33 +196,30 @@
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
-#define gamma_PCI_IDS \
- {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0, 0, 0}
-
#define savage_PCI_IDS \
- {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+ {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+ {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+ {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+ {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+ {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+ {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+ {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+ {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
+ {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
{0, 0, 0}
#define ffb_PCI_IDS \
@@ -223,10 +235,3 @@
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
-#define viadrv_PCI_IDS \
- {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0, 0, 0}
-
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 4774087d2e9e..32d2bb99462c 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -210,8 +210,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
/* Hardcoded from _DRM_FRAME_BUFFER,
_DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
- _DRM_SCATTER_GATHER. */
- const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+ _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+ const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
const char *type;
int i;
@@ -229,16 +229,19 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
- if(!map) continue;
- if (map->type < 0 || map->type > 4) type = "??";
- else type = types[map->type];
- DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
+ if(!map)
+ continue;
+ if (map->type < 0 || map->type > 5)
+ type = "??";
+ else
+ type = types[map->type];
+ DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
i,
map->offset,
map->size,
type,
map->flags,
- (unsigned long)map->handle);
+ r_list->user_token);
if (map->mtrr < 0) {
DRM_PROC_PRINT("none\n");
} else {
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 54fddb6ea2d1..ed267d49bc6a 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -61,6 +61,12 @@ void drm_sg_cleanup( drm_sg_mem_t *entry )
DRM_MEM_SGLISTS );
}
+#ifdef _LP64
+# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
+#else
+# define ScatterHandle(x) (unsigned int)(x)
+#endif
+
int drm_sg_alloc( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -133,12 +139,13 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
*/
memset( entry->virtual, 0, pages << PAGE_SHIFT );
- entry->handle = (unsigned long)entry->virtual;
+ entry->handle = ScatterHandle((unsigned long)entry->virtual);
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
- for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+ for (i = (unsigned long)entry->virtual, j = 0; j < pages;
+ i += PAGE_SIZE, j++) {
entry->pagelist[j] = vmalloc_to_page((void *)i);
if (!entry->pagelist[j])
goto failed;
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 48829a1a086a..95a976c96eb8 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -75,6 +75,11 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
dev->pci_func = PCI_FUNC(pdev->devfn);
dev->irq = pdev->irq;
+ dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ if (dev->maplist == NULL)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&dev->maplist->head);
+
/* the DRM has 6 basic counters */
dev->counters = 6;
dev->types[0] = _DRM_STAT_LOCK;
@@ -91,7 +96,8 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
- dev->agp = drm_agp_init(dev);
+ if (drm_device_is_agp(dev))
+ dev->agp = drm_agp_init(dev);
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
retcode = -EINVAL;
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 2fc10c4bbcdf..475cc5e555e1 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include "drm_core.h"
+#include "drmP.h"
struct drm_sysfs_class {
struct class_device_attribute attr;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 621220f3f372..ced4215e2275 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -73,12 +73,13 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
if (!map) continue;
- if (map->offset == VM_OFFSET(vma)) break;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
}
if (map && map->type == _DRM_AGP) {
unsigned long offset = address - vma->vm_start;
- unsigned long baddr = VM_OFFSET(vma) + offset;
+ unsigned long baddr = map->offset + offset;
struct drm_agp_mem *agpmem;
struct page *page;
@@ -210,6 +211,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
}
if(!found_maps) {
+ drm_dma_handle_t dmah;
+
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
@@ -228,6 +231,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
case _DRM_AGP:
case _DRM_SCATTER_GATHER:
break;
+ case _DRM_CONSISTENT:
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ __drm_pci_free(dev, &dmah);
+ break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
@@ -296,7 +305,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
offset = address - vma->vm_start;
- map_offset = map->offset - dev->sg->handle;
+ map_offset = map->offset - (unsigned long)dev->sg->virtual;
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
page = entry->pagelist[page_offset];
get_page(page);
@@ -305,8 +314,6 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
}
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
-
static struct page *drm_vm_nopage(struct vm_area_struct *vma,
unsigned long address,
int *type) {
@@ -335,35 +342,6 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
return drm_do_vm_sg_nopage(vma, address);
}
-#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */
-
-static struct page *drm_vm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
- return drm_do_vm_nopage(vma, address);
-}
-
-static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
- return drm_do_vm_shm_nopage(vma, address);
-}
-
-static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
- return drm_do_vm_dma_nopage(vma, address);
-}
-
-static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
- return drm_do_vm_sg_nopage(vma, address);
-}
-
-#endif
-
-
/** AGP virtual memory operations */
static struct vm_operations_struct drm_vm_ops = {
.nopage = drm_vm_nopage,
@@ -487,11 +465,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &drm_vm_dma_ops;
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma);
@@ -560,13 +534,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
for performance, even if the list was a
bit longer. */
list_for_each(list, &dev->maplist->head) {
- unsigned long off;
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
if (!map) continue;
- off = dev->driver->get_map_ofs(map);
- if (off == VM_OFFSET(vma)) break;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
}
if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
@@ -605,17 +578,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
/* fall through to _DRM_FRAME_BUFFER... */
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
- if (VM_OFFSET(vma) >= __pa(high_memory)) {
#if defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
- }
+ if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+ pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+ }
#elif defined(__powerpc__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+ if (map->type == _DRM_REGISTERS)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED;
#endif
- vma->vm_flags |= VM_IO; /* not in core dump */
- }
+ vma->vm_flags |= VM_IO; /* not in core dump */
#if defined(__ia64__)
if (efi_range_is_wc(vma->vm_start, vma->vm_end -
vma->vm_start))
@@ -628,12 +601,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
offset = dev->driver->get_reg_ofs(dev);
#ifdef __sparc__
if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
- (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
+ (map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
#else
if (io_remap_pfn_range(vma, vma->vm_start,
- (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
+ (map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
#endif
@@ -641,37 +614,28 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%lx\n",
map->type,
- vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
+ vma->vm_start, vma->vm_end, map->offset + offset);
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
+ case _DRM_CONSISTENT:
+ /* Consistent memory is really like shared memory. It's only
+ * allocate in a different way */
vma->vm_ops = &drm_vm_shm_ops;
vma->vm_private_data = (void *)map;
/* Don't let this area swap. Change when
DRM_KERNEL advisory is supported. */
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED;
-#else
vma->vm_flags |= VM_RESERVED;
-#endif
break;
case _DRM_SCATTER_GATHER:
vma->vm_ops = &drm_vm_sg_ops;
vma->vm_private_data = (void *)map;
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED;
-#else
vma->vm_flags |= VM_RESERVED;
-#endif
break;
default:
return -EINVAL; /* This should never happen. */
}
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma);
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index ec614fff8f04..1bd0d55ee0f0 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -152,14 +152,11 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
return NULL;
list_for_each(list, &dev->maplist->head) {
- unsigned long uoff;
-
r_list = (drm_map_list_t *)list;
map = r_list->map;
if (!map)
continue;
- uoff = (map->offset & 0xffffffff);
- if (uoff == off)
+ if (r_list->user_token == off)
return map;
}
diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
deleted file mode 100644
index d11b507f87ee..000000000000
--- a/drivers/char/drm/gamma_context.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- * ChangeLog:
- * 2001-11-16 Torsten Duwe <duwe@caldera.de>
- * added context constructor/destructor hooks,
- * needed by SiS driver's memory management.
- */
-
-/* ================================================================
- * Old-style context support -- only used by gamma.
- */
-
-
-/* The drm_read and drm_write_string code (especially that which manages
- the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
- DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
-
-ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int left;
- int avail;
- int send;
- int cur;
-
- DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
-
- while (dev->buf_rp == dev->buf_wp) {
- DRM_DEBUG(" sleeping\n");
- if (filp->f_flags & O_NONBLOCK) {
- return -EAGAIN;
- }
- interruptible_sleep_on(&dev->buf_readers);
- if (signal_pending(current)) {
- DRM_DEBUG(" interrupted\n");
- return -ERESTARTSYS;
- }
- DRM_DEBUG(" awake\n");
- }
-
- left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
- avail = DRM_BSZ - left;
- send = DRM_MIN(avail, count);
-
- while (send) {
- if (dev->buf_wp > dev->buf_rp) {
- cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
- } else {
- cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
- }
- if (copy_to_user(buf, dev->buf_rp, cur))
- return -EFAULT;
- dev->buf_rp += cur;
- if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
- send -= cur;
- }
-
- wake_up_interruptible(&dev->buf_writers);
- return DRM_MIN(avail, count);
-}
-
-
-/* In an incredibly convoluted setup, the kernel module actually calls
- * back into the X server to perform context switches on behalf of the
- * 3d clients.
- */
-int DRM(write_string)(drm_device_t *dev, const char *s)
-{
- int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
- int send = strlen(s);
- int count;
-
- DRM_DEBUG("%d left, %d to send (%p, %p)\n",
- left, send, dev->buf_rp, dev->buf_wp);
-
- if (left == 1 || dev->buf_wp != dev->buf_rp) {
- DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
- left,
- dev->buf_wp,
- dev->buf_rp);
- }
-
- while (send) {
- if (dev->buf_wp >= dev->buf_rp) {
- count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
- if (count == left) --count; /* Leave a hole */
- } else {
- count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
- }
- strncpy(dev->buf_wp, s, count);
- dev->buf_wp += count;
- if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
- send -= count;
- }
-
- if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
-
- DRM_DEBUG("waking\n");
- wake_up_interruptible(&dev->buf_readers);
- return 0;
-}
-
-unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
-
- poll_wait(filp, &dev->buf_readers, wait);
- if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
- return 0;
-}
-
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
-{
- char buf[64];
- drm_queue_t *q;
-
- if (test_and_set_bit(0, &dev->context_flag)) {
- DRM_ERROR("Reentering -- FIXME\n");
- return -EBUSY;
- }
-
- DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
- if (new >= dev->queue_count) {
- clear_bit(0, &dev->context_flag);
- return -EINVAL;
- }
-
- if (new == dev->last_context) {
- clear_bit(0, &dev->context_flag);
- return 0;
- }
-
- q = dev->queuelist[new];
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- atomic_dec(&q->use_count);
- clear_bit(0, &dev->context_flag);
- return -EINVAL;
- }
-
- /* This causes the X server to wake up & do a bunch of hardware
- * interaction to actually effect the context switch.
- */
- sprintf(buf, "C %d %d\n", old, new);
- DRM(write_string)(dev, buf);
-
- atomic_dec(&q->use_count);
-
- return 0;
-}
-
-int DRM(context_switch_complete)(drm_device_t *dev, int new)
-{
- drm_device_dma_t *dma = dev->dma;
-
- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
- dev->last_switch = jiffies;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("Lock isn't held after context switch\n");
- }
-
- if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
- if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("Cannot free lock\n");
- }
- }
-
- clear_bit(0, &dev->context_flag);
- wake_up_interruptible(&dev->context_wait);
-
- return 0;
-}
-
-static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
-{
- DRM_DEBUG("\n");
-
- if (atomic_read(&q->use_count) != 1
- || atomic_read(&q->finalization)
- || atomic_read(&q->block_count)) {
- DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
- atomic_read(&q->use_count),
- atomic_read(&q->finalization),
- atomic_read(&q->block_count));
- }
-
- atomic_set(&q->finalization, 0);
- atomic_set(&q->block_count, 0);
- atomic_set(&q->block_read, 0);
- atomic_set(&q->block_write, 0);
- atomic_set(&q->total_queued, 0);
- atomic_set(&q->total_flushed, 0);
- atomic_set(&q->total_locks, 0);
-
- init_waitqueue_head(&q->write_queue);
- init_waitqueue_head(&q->read_queue);
- init_waitqueue_head(&q->flush_queue);
-
- q->flags = ctx->flags;
-
- DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
-
- return 0;
-}
-
-
-/* drm_alloc_queue:
-PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
- disappear (so all deallocation must be done after IOCTLs are off)
- 2) dev->queue_count < dev->queue_slots
- 3) dev->queuelist[i].use_count == 0 and
- dev->queuelist[i].finalization == 0 if i not in use
-POST: 1) dev->queuelist[i].use_count == 1
- 2) dev->queue_count < dev->queue_slots */
-
-static int DRM(alloc_queue)(drm_device_t *dev)
-{
- int i;
- drm_queue_t *queue;
- int oldslots;
- int newslots;
- /* Check for a free queue */
- for (i = 0; i < dev->queue_count; i++) {
- atomic_inc(&dev->queuelist[i]->use_count);
- if (atomic_read(&dev->queuelist[i]->use_count) == 1
- && !atomic_read(&dev->queuelist[i]->finalization)) {
- DRM_DEBUG("%d (free)\n", i);
- return i;
- }
- atomic_dec(&dev->queuelist[i]->use_count);
- }
- /* Allocate a new queue */
- down(&dev->struct_sem);
-
- queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES);
- memset(queue, 0, sizeof(*queue));
- atomic_set(&queue->use_count, 1);
-
- ++dev->queue_count;
- if (dev->queue_count >= dev->queue_slots) {
- oldslots = dev->queue_slots * sizeof(*dev->queuelist);
- if (!dev->queue_slots) dev->queue_slots = 1;
- dev->queue_slots *= 2;
- newslots = dev->queue_slots * sizeof(*dev->queuelist);
-
- dev->queuelist = DRM(realloc)(dev->queuelist,
- oldslots,
- newslots,
- DRM_MEM_QUEUES);
- if (!dev->queuelist) {
- up(&dev->struct_sem);
- DRM_DEBUG("out of memory\n");
- return -ENOMEM;
- }
- }
- dev->queuelist[dev->queue_count-1] = queue;
-
- up(&dev->struct_sem);
- DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
- return dev->queue_count - 1;
-}
-
-int DRM(resctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_ctx_res_t __user *argp = (void __user *)arg;
- drm_ctx_res_t res;
- drm_ctx_t ctx;
- int i;
-
- DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- if (copy_from_user(&res, argp, sizeof(res)))
- return -EFAULT;
- if (res.count >= DRM_RESERVED_CONTEXTS) {
- memset(&ctx, 0, sizeof(ctx));
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- ctx.handle = i;
- if (copy_to_user(&res.contexts[i],
- &i,
- sizeof(i)))
- return -EFAULT;
- }
- }
- res.count = DRM_RESERVED_CONTEXTS;
- if (copy_to_user(argp, &res, sizeof(res)))
- return -EFAULT;
- return 0;
-}
-
-int DRM(addctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_ctx_t __user *argp = (void __user *)arg;
-
- if (copy_from_user(&ctx, argp, sizeof(ctx)))
- return -EFAULT;
- if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
- /* Init kernel's context and get a new one. */
- DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
- ctx.handle = DRM(alloc_queue)(dev);
- }
- DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
- DRM_DEBUG("%d\n", ctx.handle);
- if (copy_to_user(argp, &ctx, sizeof(ctx)))
- return -EFAULT;
- return 0;
-}
-
-int DRM(modctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_queue_t *q;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
-
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- if (DRM_BUFCOUNT(&q->waitlist)) {
- atomic_dec(&q->use_count);
- return -EBUSY;
- }
-
- q->flags = ctx.flags;
-
- atomic_dec(&q->use_count);
- return 0;
-}
-
-int DRM(getctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
- drm_queue_t *q;
-
- if (copy_from_user(&ctx, argp, sizeof(ctx)))
- return -EFAULT;
-
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- ctx.flags = q->flags;
- atomic_dec(&q->use_count);
-
- if (copy_to_user(argp, &ctx, sizeof(ctx)))
- return -EFAULT;
-
- return 0;
-}
-
-int DRM(switchctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
- return DRM(context_switch)(dev, dev->last_context, ctx.handle);
-}
-
-int DRM(newctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
- DRM(context_switch_complete)(dev, ctx.handle);
-
- return 0;
-}
-
-int DRM(rmctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_queue_t *q;
- drm_buf_t *buf;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- atomic_inc(&q->finalization); /* Mark queue in finalization state */
- atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
- finalization) */
-
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
- /* Remove queued buffers */
- while ((buf = DRM(waitlist_get)(&q->waitlist))) {
- DRM(free_buffer)(dev, buf);
- }
- clear_bit(0, &dev->interrupt_flag);
-
- /* Wakeup blocked processes */
- wake_up_interruptible(&q->read_queue);
- wake_up_interruptible(&q->write_queue);
- wake_up_interruptible(&q->flush_queue);
-
- /* Finalization over. Queue is made
- available when both use_count and
- finalization become 0, which won't
- happen until all the waiting processes
- stop waiting. */
- atomic_dec(&q->finalization);
- return 0;
-}
-
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
deleted file mode 100644
index e486fb8d31e9..000000000000
--- a/drivers/char/drm/gamma_dma.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include <linux/interrupt.h> /* For task queue support */
-#include <linux/delay.h>
-
-static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
- unsigned long length)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- mb();
- while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_DMAADDRESS, address);
-
- while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
-}
-
-void gamma_dma_quiescent_single(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
- GAMMA_WRITE(GAMMA_SYNC, 0);
-
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_quiescent_dual(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
- GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
- GAMMA_WRITE(GAMMA_SYNC, 0);
-
- /* Read from first MX */
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-
- /* Read from second MX */
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_ready(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-}
-
-static inline int gamma_dma_is_ready(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- return (!GAMMA_READ(GAMMA_DMACOUNT));
-}
-
-irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
-{
- drm_device_t *dev = (drm_device_t *)arg;
- drm_device_dma_t *dma = dev->dma;
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- /* FIXME: should check whether we're actually interested in the interrupt? */
- atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
- GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
- GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
- if (gamma_dma_is_ready(dev)) {
- /* Free previous buffer */
- if (test_and_set_bit(0, &dev->dma_flag))
- return IRQ_HANDLED;
- if (dma->this_buffer) {
- gamma_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = NULL;
- }
- clear_bit(0, &dev->dma_flag);
-
- /* Dispatch new buffer */
- schedule_work(&dev->work);
- }
- return IRQ_HANDLED;
-}
-
-/* Only called by gamma_dma_schedule. */
-static int gamma_do_dma(drm_device_t *dev, int locked)
-{
- unsigned long address;
- unsigned long length;
- drm_buf_t *buf;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
-
- if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
-
-
- if (!dma->next_buffer) {
- DRM_ERROR("No next_buffer\n");
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- buf = dma->next_buffer;
- /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
- /* So we pass the buffer index value into the physical page offset */
- address = buf->idx << 12;
- length = buf->used;
-
- DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
- buf->context, buf->idx, length);
-
- if (buf->list == DRM_LIST_RECLAIM) {
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return 0;
- }
-
- if (!gamma_dma_is_ready(dev)) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
-
- if (buf->while_locked) {
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("Dispatching buffer %d from pid %d"
- " \"while locked\", but no lock held\n",
- buf->idx, current->pid);
- }
- } else {
- if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
- }
-
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- /* PRE: dev->last_context != buf->context */
- if (DRM(context_switch)(dev, dev->last_context,
- buf->context)) {
- DRM(clear_next_buffer)(dev);
- DRM(free_buffer)(dev, buf);
- }
- retcode = -EBUSY;
- goto cleanup;
-
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- }
-
- gamma_clear_next_buffer(dev);
- buf->pending = 1;
- buf->waiting = 0;
- buf->list = DRM_LIST_PEND;
-
- /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
- address = buf->idx << 12;
-
- gamma_dma_dispatch(dev, address, length);
- gamma_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = buf;
-
- atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
- atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
- if (!buf->while_locked && !dev->context_flag && !locked) {
- if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
- }
-cleanup:
-
- clear_bit(0, &dev->dma_flag);
-
-
- return retcode;
-}
-
-static void gamma_dma_timer_bh(unsigned long dev)
-{
- gamma_dma_schedule((drm_device_t *)dev, 0);
-}
-
-void gamma_irq_immediate_bh(void *dev)
-{
- gamma_dma_schedule(dev, 0);
-}
-
-int gamma_dma_schedule(drm_device_t *dev, int locked)
-{
- int next;
- drm_queue_t *q;
- drm_buf_t *buf;
- int retcode = 0;
- int processed = 0;
- int missed;
- int expire = 20;
- drm_device_dma_t *dma = dev->dma;
-
- if (test_and_set_bit(0, &dev->interrupt_flag)) {
- /* Not reentrant */
- atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
- return -EBUSY;
- }
- missed = atomic_read(&dev->counts[10]);
-
-
-again:
- if (dev->context_flag) {
- clear_bit(0, &dev->interrupt_flag);
- return -EBUSY;
- }
- if (dma->next_buffer) {
- /* Unsent buffer that was previously
- selected, but that couldn't be sent
- because the lock could not be obtained
- or the DMA engine wasn't ready. Try
- again. */
- if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
- } else {
- do {
- next = gamma_select_queue(dev, gamma_dma_timer_bh);
- if (next >= 0) {
- q = dev->queuelist[next];
- buf = gamma_waitlist_get(&q->waitlist);
- dma->next_buffer = buf;
- dma->next_queue = q;
- if (buf && buf->list == DRM_LIST_RECLAIM) {
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- }
- }
- } while (next >= 0 && !dma->next_buffer);
- if (dma->next_buffer) {
- if (!(retcode = gamma_do_dma(dev, locked))) {
- ++processed;
- }
- }
- }
-
- if (--expire) {
- if (missed != atomic_read(&dev->counts[10])) {
- if (gamma_dma_is_ready(dev)) goto again;
- }
- if (processed && gamma_dma_is_ready(dev)) {
- processed = 0;
- goto again;
- }
- }
-
- clear_bit(0, &dev->interrupt_flag);
-
- return retcode;
-}
-
-static int gamma_dma_priority(struct file *filp,
- drm_device_t *dev, drm_dma_t *d)
-{
- unsigned long address;
- unsigned long length;
- int must_free = 0;
- int retcode = 0;
- int i;
- int idx;
- drm_buf_t *buf;
- drm_buf_t *last_buf = NULL;
- drm_device_dma_t *dma = dev->dma;
- int *send_indices = NULL;
- int *send_sizes = NULL;
-
- DECLARE_WAITQUEUE(entry, current);
-
- /* Turn off interrupt handling */
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- schedule();
- if (signal_pending(current)) return -EINTR;
- }
- if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
- while (!gamma_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
- ++must_free;
- }
-
- send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
- DRM_MEM_DRIVER);
- if (send_indices == NULL)
- return -ENOMEM;
- if (copy_from_user(send_indices, d->send_indices,
- d->send_count * sizeof(*send_indices))) {
- retcode = -EFAULT;
- goto cleanup;
- }
-
- send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
- DRM_MEM_DRIVER);
- if (send_sizes == NULL)
- return -ENOMEM;
- if (copy_from_user(send_sizes, d->send_sizes,
- d->send_count * sizeof(*send_sizes))) {
- retcode = -EFAULT;
- goto cleanup;
- }
-
- for (i = 0; i < d->send_count; i++) {
- idx = send_indices[i];
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- send_indices[i], dma->buf_count - 1);
- continue;
- }
- buf = dma->buflist[ idx ];
- if (buf->filp != filp) {
- DRM_ERROR("Process %d using buffer not owned\n",
- current->pid);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using buffer on list %d\n",
- current->pid, buf->list);
- retcode = -EINVAL;
- goto cleanup;
- }
- /* This isn't a race condition on
- buf->list, since our concern is the
- buffer reclaim during the time the
- process closes the /dev/drm? handle, so
- it can't also be doing DMA. */
- buf->list = DRM_LIST_PRIO;
- buf->used = send_sizes[i];
- buf->context = d->context;
- buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
- address = (unsigned long)buf->address;
- length = buf->used;
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- }
- if (buf->pending) {
- DRM_ERROR("Sending pending buffer:"
- " buffer %d, offset %d\n",
- send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->waiting) {
- DRM_ERROR("Sending waiting buffer:"
- " buffer %d, offset %d\n",
- send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
- }
- buf->pending = 1;
-
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- add_wait_queue(&dev->context_wait, &entry);
- current->state = TASK_INTERRUPTIBLE;
- /* PRE: dev->last_context != buf->context */
- DRM(context_switch)(dev, dev->last_context,
- buf->context);
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&dev->context_wait, &entry);
- if (signal_pending(current)) {
- retcode = -EINTR;
- goto cleanup;
- }
- if (dev->last_context != buf->context) {
- DRM_ERROR("Context mismatch: %d %d\n",
- dev->last_context,
- buf->context);
- }
- }
-
- gamma_dma_dispatch(dev, address, length);
- atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
- atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
- if (last_buf) {
- gamma_free_buffer(dev, last_buf);
- }
- last_buf = buf;
- }
-
-
-cleanup:
- if (last_buf) {
- gamma_dma_ready(dev);
- gamma_free_buffer(dev, last_buf);
- }
- if (send_indices)
- DRM(free)(send_indices, d->send_count * sizeof(*send_indices),
- DRM_MEM_DRIVER);
- if (send_sizes)
- DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes),
- DRM_MEM_DRIVER);
-
- if (must_free && !dev->context_flag) {
- if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
- }
- clear_bit(0, &dev->interrupt_flag);
- return retcode;
-}
-
-static int gamma_dma_send_buffers(struct file *filp,
- drm_device_t *dev, drm_dma_t *d)
-{
- DECLARE_WAITQUEUE(entry, current);
- drm_buf_t *last_buf = NULL;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
- int send_index;
-
- if (get_user(send_index, &d->send_indices[d->send_count-1]))
- return -EFAULT;
-
- if (d->flags & _DRM_DMA_BLOCK) {
- last_buf = dma->buflist[send_index];
- add_wait_queue(&last_buf->dma_wait, &entry);
- }
-
- if ((retcode = gamma_dma_enqueue(filp, d))) {
- if (d->flags & _DRM_DMA_BLOCK)
- remove_wait_queue(&last_buf->dma_wait, &entry);
- return retcode;
- }
-
- gamma_dma_schedule(dev, 0);
-
- if (d->flags & _DRM_DMA_BLOCK) {
- DRM_DEBUG("%d waiting\n", current->pid);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!last_buf->waiting && !last_buf->pending)
- break; /* finished */
- schedule();
- if (signal_pending(current)) {
- retcode = -EINTR; /* Can't restart */
- break;
- }
- }
- current->state = TASK_RUNNING;
- DRM_DEBUG("%d running\n", current->pid);
- remove_wait_queue(&last_buf->dma_wait, &entry);
- if (!retcode
- || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
- if (!waitqueue_active(&last_buf->dma_wait)) {
- gamma_free_buffer(dev, last_buf);
- }
- }
- if (retcode) {
- DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",
- d->context,
- last_buf->waiting,
- last_buf->pending,
- (long)DRM_WAITCOUNT(dev, d->context),
- last_buf->idx,
- last_buf->list,
- current->pid);
- }
- }
- return retcode;
-}
-
-int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- drm_dma_t __user *argp = (void __user *)arg;
- drm_dma_t d;
-
- if (copy_from_user(&d, argp, sizeof(d)))
- return -EFAULT;
-
- if (d.send_count < 0 || d.send_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
- current->pid, d.send_count, dma->buf_count);
- return -EINVAL;
- }
-
- if (d.request_count < 0 || d.request_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
- current->pid, d.request_count, dma->buf_count);
- return -EINVAL;
- }
-
- if (d.send_count) {
- if (d.flags & _DRM_DMA_PRIORITY)
- retcode = gamma_dma_priority(filp, dev, &d);
- else
- retcode = gamma_dma_send_buffers(filp, dev, &d);
- }
-
- d.granted_count = 0;
-
- if (!retcode && d.request_count) {
- retcode = gamma_dma_get_buffers(filp, &d);
- }
-
- DRM_DEBUG("%d returning, granted = %d\n",
- current->pid, d.granted_count);
- if (copy_to_user(argp, &d, sizeof(d)))
- return -EFAULT;
-
- return retcode;
-}
-
-/* =============================================================
- * DMA initialization, cleanup
- */
-
-static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
-{
- drm_gamma_private_t *dev_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
- int i;
- struct list_head *list;
- unsigned long *pgt;
-
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
- DRM_MEM_DRIVER );
- if ( !dev_priv )
- return -ENOMEM;
-
- dev->dev_private = (void *)dev_priv;
-
- memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
-
- dev_priv->num_rast = init->num_rast;
-
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
- if( r_list->map &&
- r_list->map->type == _DRM_SHM &&
- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
- dev_priv->sarea = r_list->map;
- break;
- }
- }
-
- dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
- dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
- dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
- dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
-
- dev_priv->sarea_priv = (drm_gamma_sarea_t *)
- ((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
-
- if (init->pcimode) {
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- pgt = buf->address;
-
- for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
- buf = dma->buflist[i];
- *pgt = virt_to_phys((void*)buf->address) | 0x07;
- pgt++;
- }
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- } else {
- dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- drm_core_ioremap( dev->agp_buffer_map, dev);
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- pgt = buf->address;
-
- for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
- buf = dma->buflist[i];
- *pgt = (unsigned long)buf->address + 0x07;
- pgt++;
- }
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
- GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
- }
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
- GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
- GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
-
- return 0;
-}
-
-int gamma_do_cleanup_dma( drm_device_t *dev )
-{
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- /* Make sure interrupts are disabled here because the uninstall ioctl
- * may not have been called from userspace and after dev_private
- * is freed, it's too late.
- */
- if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- if ( dev->irq_enabled )
- DRM(irq_uninstall)(dev);
-
- if ( dev->dev_private ) {
-
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
-
- DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
- }
-
- return 0;
-}
-
-int gamma_dma_init( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_gamma_init_t init;
-
- LOCK_TEST_WITH_RETURN( dev, filp );
-
- if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )
- return -EFAULT;
-
- switch ( init.func ) {
- case GAMMA_INIT_DMA:
- return gamma_do_init_dma( dev, &init );
- case GAMMA_CLEANUP_DMA:
- return gamma_do_cleanup_dma( dev );
- }
-
- return -EINVAL;
-}
-
-static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
-{
- drm_device_dma_t *dma = dev->dma;
- unsigned int *screenbuf;
-
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- /* We've DRM_RESTRICTED this DMA buffer */
-
- screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
-
-#if 0
- *buffer++ = 0x180; /* Tag (FilterMode) */
- *buffer++ = 0x200; /* Allow FBColor through */
- *buffer++ = 0x53B; /* Tag */
- *buffer++ = copy->Pitch;
- *buffer++ = 0x53A; /* Tag */
- *buffer++ = copy->SrcAddress;
- *buffer++ = 0x539; /* Tag */
- *buffer++ = copy->WidthHeight; /* Initiates transfer */
- *buffer++ = 0x53C; /* Tag - DMAOutputAddress */
- *buffer++ = virt_to_phys((void*)screenbuf);
- *buffer++ = 0x53D; /* Tag - DMAOutputCount */
- *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
-
- /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
- /* Now put it back to the screen */
-
- *buffer++ = 0x180; /* Tag (FilterMode) */
- *buffer++ = 0x400; /* Allow Sync through */
- *buffer++ = 0x538; /* Tag - DMARectangleReadTarget */
- *buffer++ = 0x155; /* FBSourceData | count */
- *buffer++ = 0x537; /* Tag */
- *buffer++ = copy->Pitch;
- *buffer++ = 0x536; /* Tag */
- *buffer++ = copy->DstAddress;
- *buffer++ = 0x535; /* Tag */
- *buffer++ = copy->WidthHeight; /* Initiates transfer */
- *buffer++ = 0x530; /* Tag - DMAAddr */
- *buffer++ = virt_to_phys((void*)screenbuf);
- *buffer++ = 0x531;
- *buffer++ = copy->Count; /* initiates DMA transfer of color data */
-#endif
-
- /* need to dispatch it now */
-
- return 0;
-}
-
-int gamma_dma_copy( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_gamma_copy_t copy;
-
- if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )
- return -EFAULT;
-
- return gamma_do_copy_dma( dev, &copy );
-}
-
-/* =============================================================
- * Per Context SAREA Support
- */
-
-int gamma_getsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_priv_map_t __user *argp = (void __user *)arg;
- drm_ctx_priv_map_t request;
- drm_map_t *map;
-
- if (copy_from_user(&request, argp, sizeof(request)))
- return -EFAULT;
-
- down(&dev->struct_sem);
- if ((int)request.ctx_id >= dev->max_context) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
-
- map = dev->context_sareas[request.ctx_id];
- up(&dev->struct_sem);
-
- request.handle = map->handle;
- if (copy_to_user(argp, &request, sizeof(request)))
- return -EFAULT;
- return 0;
-}
-
-int gamma_setsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_priv_map_t request;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
- struct list_head *list;
-
- if (copy_from_user(&request,
- (drm_ctx_priv_map_t __user *)arg,
- sizeof(request)))
- return -EFAULT;
-
- down(&dev->struct_sem);
- r_list = NULL;
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
- if(r_list->map &&
- r_list->map->handle == request.handle) break;
- }
- if (list == &(dev->maplist->head)) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
- map = r_list->map;
- up(&dev->struct_sem);
-
- if (!map) return -EINVAL;
-
- down(&dev->struct_sem);
- if ((int)request.ctx_id >= dev->max_context) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
- dev->context_sareas[request.ctx_id] = map;
- up(&dev->struct_sem);
- return 0;
-}
-
-void gamma_driver_irq_preinstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 );
- GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );
-}
-
-void gamma_driver_irq_postinstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 );
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 );
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 );
-}
-
-void gamma_driver_irq_uninstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- if (!dev_priv)
- return;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 );
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 );
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 );
-}
-
-extern drm_ioctl_desc_t DRM(ioctls)[];
-
-static int gamma_driver_preinit(drm_device_t *dev)
-{
- /* reset the finish ioctl */
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
- return 0;
-}
-
-static void gamma_driver_pretakedown(drm_device_t *dev)
-{
- gamma_do_cleanup_dma(dev);
-}
-
-static void gamma_driver_dma_ready(drm_device_t *dev)
-{
- gamma_dma_ready(dev);
-}
-
-static int gamma_driver_dma_quiescent(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv = (
- drm_gamma_private_t *)dev->dev_private;
- if (dev_priv->num_rast == 2)
- gamma_dma_quiescent_dual(dev);
- else gamma_dma_quiescent_single(dev);
- return 0;
-}
-
-void gamma_driver_register_fns(drm_device_t *dev)
-{
- dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
- DRM(fops).read = gamma_fops_read;
- DRM(fops).poll = gamma_fops_poll;
- dev->driver.preinit = gamma_driver_preinit;
- dev->driver.pretakedown = gamma_driver_pretakedown;
- dev->driver.dma_ready = gamma_driver_dma_ready;
- dev->driver.dma_quiescent = gamma_driver_dma_quiescent;
- dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;
- dev->driver.dma_flush_unblock = gamma_flush_unblock;
-}
diff --git a/drivers/char/drm/gamma_drm.h b/drivers/char/drm/gamma_drm.h
deleted file mode 100644
index 20819ded0e15..000000000000
--- a/drivers/char/drm/gamma_drm.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _GAMMA_DRM_H_
-#define _GAMMA_DRM_H_
-
-typedef struct _drm_gamma_tex_region {
- unsigned char next, prev; /* indices to form a circular LRU */
- unsigned char in_use; /* owned by a client, or free? */
- int age; /* tracked by clients to update local LRU's */
-} drm_gamma_tex_region_t;
-
-typedef struct {
- unsigned int GDeltaMode;
- unsigned int GDepthMode;
- unsigned int GGeometryMode;
- unsigned int GTransformMode;
-} drm_gamma_context_regs_t;
-
-typedef struct _drm_gamma_sarea {
- drm_gamma_context_regs_t context_state;
-
- unsigned int dirty;
-
-
- /* Maintain an LRU of contiguous regions of texture space. If
- * you think you own a region of texture memory, and it has an
- * age different to the one you set, then you are mistaken and
- * it has been stolen by another client. If global texAge
- * hasn't changed, there is no need to walk the list.
- *
- * These regions can be used as a proxy for the fine-grained
- * texture information of other clients - by maintaining them
- * in the same lru which is used to age their own textures,
- * clients have an approximate lru for the whole of global
- * texture space, and can make informed decisions as to which
- * areas to kick out. There is no need to choose whether to
- * kick out your own texture or someone else's - simply eject
- * them all in LRU order.
- */
-
-#define GAMMA_NR_TEX_REGIONS 64
- drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1];
- /* Last elt is sentinal */
- int texAge; /* last time texture was uploaded */
- int last_enqueue; /* last time a buffer was enqueued */
- int last_dispatch; /* age of the most recently dispatched buffer */
- int last_quiescent; /* */
- int ctxOwner; /* last context to upload state */
-
- int vertex_prim;
-} drm_gamma_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmGamma.h)
- */
-
-/* Gamma specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)
-#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t)
-
-typedef struct drm_gamma_copy {
- unsigned int DMAOutputAddress;
- unsigned int DMAOutputCount;
- unsigned int DMAReadGLINTSource;
- unsigned int DMARectangleWriteAddress;
- unsigned int DMARectangleWriteLinePitch;
- unsigned int DMARectangleWrite;
- unsigned int DMARectangleReadAddress;
- unsigned int DMARectangleReadLinePitch;
- unsigned int DMARectangleRead;
- unsigned int DMARectangleReadTarget;
-} drm_gamma_copy_t;
-
-typedef struct drm_gamma_init {
- enum {
- GAMMA_INIT_DMA = 0x01,
- GAMMA_CLEANUP_DMA = 0x02
- } func;
-
- int sarea_priv_offset;
- int pcimode;
- unsigned int mmio0;
- unsigned int mmio1;
- unsigned int mmio2;
- unsigned int mmio3;
- unsigned int buffers_offset;
- int num_rast;
-} drm_gamma_init_t;
-
-#endif /* _GAMMA_DRM_H_ */
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
deleted file mode 100644
index e7e64b62792a..000000000000
--- a/drivers/char/drm/gamma_drv.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-#include <linux/config.h>
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "gamma_context.h" /* NOTE! */
-#include "drm_dma.h"
-#include "gamma_old_dma.h" /* NOTE */
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "gamma_lists.h" /* NOTE */
-#include "drm_lock.h"
-#include "gamma_lock.h" /* NOTE */
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
deleted file mode 100644
index 146fcc6253cd..000000000000
--- a/drivers/char/drm/gamma_drv.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#ifndef _GAMMA_DRV_H_
-#define _GAMMA_DRV_H_
-
-typedef struct drm_gamma_private {
- drm_gamma_sarea_t *sarea_priv;
- drm_map_t *sarea;
- drm_map_t *mmio0;
- drm_map_t *mmio1;
- drm_map_t *mmio2;
- drm_map_t *mmio3;
- int num_rast;
-} drm_gamma_private_t;
-
- /* gamma_dma.c */
-extern int gamma_dma_init( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int gamma_dma_copy( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-extern int gamma_do_cleanup_dma( drm_device_t *dev );
-extern void gamma_dma_ready(drm_device_t *dev);
-extern void gamma_dma_quiescent_single(drm_device_t *dev);
-extern void gamma_dma_quiescent_dual(drm_device_t *dev);
-
- /* gamma_dma.c */
-extern int gamma_dma_schedule(drm_device_t *dev, int locked);
-extern int gamma_dma(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int gamma_find_devices(void);
-extern int gamma_found(void);
-
-/* Gamma-specific code pulled from drm_fops.h:
- */
-extern int DRM(finish)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int DRM(flush_unblock)(drm_device_t *dev, int context,
- drm_lock_flags_t flags);
-extern int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
- drm_lock_flags_t flags);
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-extern void DRM(clear_next_buffer)(drm_device_t *dev);
-extern int DRM(select_queue)(drm_device_t *dev,
- void (*wrapper)(unsigned long));
-extern int DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma);
-extern int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma);
-
-
-/* Gamma-specific code pulled from drm_lists.h (now renamed gamma_lists.h):
- */
-extern int DRM(waitlist_create)(drm_waitlist_t *bl, int count);
-extern int DRM(waitlist_destroy)(drm_waitlist_t *bl);
-extern int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
-extern drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl);
-extern int DRM(freelist_create)(drm_freelist_t *bl, int count);
-extern int DRM(freelist_destroy)(drm_freelist_t *bl);
-extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
- drm_buf_t *buf);
-extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
-
-/* externs for gamma changes to the ops */
-extern struct file_operations DRM(fops);
-extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
-extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
-
-
-#define GLINT_DRI_BUF_COUNT 256
-
-#define GAMMA_OFF(reg) \
- ((reg < 0x1000) \
- ? reg \
- : ((reg < 0x10000) \
- ? (reg - 0x1000) \
- : ((reg < 0x11000) \
- ? (reg - 0x10000) \
- : (reg - 0x11000))))
-
-#define GAMMA_BASE(reg) ((unsigned long) \
- ((reg < 0x1000) ? dev_priv->mmio0->handle : \
- ((reg < 0x10000) ? dev_priv->mmio1->handle : \
- ((reg < 0x11000) ? dev_priv->mmio2->handle : \
- dev_priv->mmio3->handle))))
-#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg))
-#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
-#define GAMMA_READ(reg) GAMMA_DEREF(reg)
-#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
-
-#define GAMMA_BROADCASTMASK 0x9378
-#define GAMMA_COMMANDINTENABLE 0x0c48
-#define GAMMA_DMAADDRESS 0x0028
-#define GAMMA_DMACOUNT 0x0030
-#define GAMMA_FILTERMODE 0x8c00
-#define GAMMA_GCOMMANDINTFLAGS 0x0c50
-#define GAMMA_GCOMMANDMODE 0x0c40
-#define GAMMA_QUEUED_DMA_MODE 1<<1
-#define GAMMA_GCOMMANDSTATUS 0x0c60
-#define GAMMA_GDELAYTIMER 0x0c38
-#define GAMMA_GDMACONTROL 0x0060
-#define GAMMA_USE_AGP 1<<1
-#define GAMMA_GINTENABLE 0x0808
-#define GAMMA_GINTFLAGS 0x0810
-#define GAMMA_INFIFOSPACE 0x0018
-#define GAMMA_OUTFIFOWORDS 0x0020
-#define GAMMA_OUTPUTFIFO 0x2000
-#define GAMMA_SYNC 0x8c40
-#define GAMMA_SYNC_TAG 0x0188
-#define GAMMA_PAGETABLEADDR 0x0C00
-#define GAMMA_PAGETABLELENGTH 0x0C08
-
-#define GAMMA_PASSTHROUGH 0x1FE
-#define GAMMA_DMAADDRTAG 0x530
-#define GAMMA_DMACOUNTTAG 0x531
-#define GAMMA_COMMANDINTTAG 0x532
-
-#endif
diff --git a/drivers/char/drm/gamma_lists.h b/drivers/char/drm/gamma_lists.h
deleted file mode 100644
index 2d93f412b96b..000000000000
--- a/drivers/char/drm/gamma_lists.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
- * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-
-
-int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
-{
- if (bl->count) return -EINVAL;
-
- bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
- DRM_MEM_BUFLISTS);
-
- if(!bl->bufs) return -ENOMEM;
- memset(bl->bufs, 0, sizeof(*bl->bufs));
- bl->count = count;
- bl->rp = bl->bufs;
- bl->wp = bl->bufs;
- bl->end = &bl->bufs[bl->count+1];
- spin_lock_init(&bl->write_lock);
- spin_lock_init(&bl->read_lock);
- return 0;
-}
-
-int DRM(waitlist_destroy)(drm_waitlist_t *bl)
-{
- if (bl->rp != bl->wp) return -EINVAL;
- if (bl->bufs) DRM(free)(bl->bufs,
- (bl->count + 2) * sizeof(*bl->bufs),
- DRM_MEM_BUFLISTS);
- bl->count = 0;
- bl->bufs = NULL;
- bl->rp = NULL;
- bl->wp = NULL;
- bl->end = NULL;
- return 0;
-}
-
-int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
-{
- int left;
- unsigned long flags;
-
- left = DRM_LEFTCOUNT(bl);
- if (!left) {
- DRM_ERROR("Overflow while adding buffer %d from filp %p\n",
- buf->idx, buf->filp);
- return -EINVAL;
- }
- buf->list = DRM_LIST_WAIT;
-
- spin_lock_irqsave(&bl->write_lock, flags);
- *bl->wp = buf;
- if (++bl->wp >= bl->end) bl->wp = bl->bufs;
- spin_unlock_irqrestore(&bl->write_lock, flags);
-
- return 0;
-}
-
-drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
-{
- drm_buf_t *buf;
- unsigned long flags;
-
- spin_lock_irqsave(&bl->read_lock, flags);
- buf = *bl->rp;
- if (bl->rp == bl->wp) {
- spin_unlock_irqrestore(&bl->read_lock, flags);
- return NULL;
- }
- if (++bl->rp >= bl->end) bl->rp = bl->bufs;
- spin_unlock_irqrestore(&bl->read_lock, flags);
-
- return buf;
-}
-
-int DRM(freelist_create)(drm_freelist_t *bl, int count)
-{
- atomic_set(&bl->count, 0);
- bl->next = NULL;
- init_waitqueue_head(&bl->waiting);
- bl->low_mark = 0;
- bl->high_mark = 0;
- atomic_set(&bl->wfh, 0);
- spin_lock_init(&bl->lock);
- ++bl->initialized;
- return 0;
-}
-
-int DRM(freelist_destroy)(drm_freelist_t *bl)
-{
- atomic_set(&bl->count, 0);
- bl->next = NULL;
- return 0;
-}
-
-int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
-{
- drm_device_dma_t *dma = dev->dma;
-
- if (!dma) {
- DRM_ERROR("No DMA support\n");
- return 1;
- }
-
- if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
- DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
- buf->idx, buf->waiting, buf->pending, buf->list);
- }
- if (!bl) return 1;
- buf->list = DRM_LIST_FREE;
-
- spin_lock(&bl->lock);
- buf->next = bl->next;
- bl->next = buf;
- spin_unlock(&bl->lock);
-
- atomic_inc(&bl->count);
- if (atomic_read(&bl->count) > dma->buf_count) {
- DRM_ERROR("%d of %d buffers free after addition of %d\n",
- atomic_read(&bl->count), dma->buf_count, buf->idx);
- return 1;
- }
- /* Check for high water mark */
- if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
- atomic_set(&bl->wfh, 0);
- wake_up_interruptible(&bl->waiting);
- }
- return 0;
-}
-
-static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
-{
- drm_buf_t *buf;
-
- if (!bl) return NULL;
-
- /* Get buffer */
- spin_lock(&bl->lock);
- if (!bl->next) {
- spin_unlock(&bl->lock);
- return NULL;
- }
- buf = bl->next;
- bl->next = bl->next->next;
- spin_unlock(&bl->lock);
-
- atomic_dec(&bl->count);
- buf->next = NULL;
- buf->list = DRM_LIST_NONE;
- if (buf->waiting || buf->pending) {
- DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
- buf->idx, buf->waiting, buf->pending, buf->list);
- }
-
- return buf;
-}
-
-drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
-{
- drm_buf_t *buf = NULL;
- DECLARE_WAITQUEUE(entry, current);
-
- if (!bl || !bl->initialized) return NULL;
-
- /* Check for low water mark */
- if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
- atomic_set(&bl->wfh, 1);
- if (atomic_read(&bl->wfh)) {
- if (block) {
- add_wait_queue(&bl->waiting, &entry);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!atomic_read(&bl->wfh)
- && (buf = DRM(freelist_try)(bl))) break;
- schedule();
- if (signal_pending(current)) break;
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&bl->waiting, &entry);
- }
- return buf;
- }
-
- return DRM(freelist_try)(bl);
-}
-
diff --git a/drivers/char/drm/gamma_lock.h b/drivers/char/drm/gamma_lock.h
deleted file mode 100644
index ddec67e4ed16..000000000000
--- a/drivers/char/drm/gamma_lock.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code extracted from drm_lock.h:
- */
-static int DRM(flush_queue)(drm_device_t *dev, int context)
-{
- DECLARE_WAITQUEUE(entry, current);
- int ret = 0;
- drm_queue_t *q = dev->queuelist[context];
-
- DRM_DEBUG("\n");
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) > 1) {
- atomic_inc(&q->block_write);
- add_wait_queue(&q->flush_queue, &entry);
- atomic_inc(&q->block_count);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!DRM_BUFCOUNT(&q->waitlist)) break;
- schedule();
- if (signal_pending(current)) {
- ret = -EINTR; /* Can't restart */
- break;
- }
- }
- atomic_dec(&q->block_count);
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->flush_queue, &entry);
- }
- atomic_dec(&q->use_count);
-
- /* NOTE: block_write is still incremented!
- Use drm_flush_unlock_queue to decrement. */
- return ret;
-}
-
-static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
-{
- drm_queue_t *q = dev->queuelist[context];
-
- DRM_DEBUG("\n");
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) > 1) {
- if (atomic_read(&q->block_write)) {
- atomic_dec(&q->block_write);
- wake_up_interruptible(&q->write_queue);
- }
- }
- atomic_dec(&q->use_count);
- return 0;
-}
-
-int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
- drm_lock_flags_t flags)
-{
- int ret = 0;
- int i;
-
- DRM_DEBUG("\n");
-
- if (flags & _DRM_LOCK_FLUSH) {
- ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
- if (!ret) ret = DRM(flush_queue)(dev, context);
- }
- if (flags & _DRM_LOCK_FLUSH_ALL) {
- for (i = 0; !ret && i < dev->queue_count; i++) {
- ret = DRM(flush_queue)(dev, i);
- }
- }
- return ret;
-}
-
-int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
-{
- int ret = 0;
- int i;
-
- DRM_DEBUG("\n");
-
- if (flags & _DRM_LOCK_FLUSH) {
- ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
- if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
- }
- if (flags & _DRM_LOCK_FLUSH_ALL) {
- for (i = 0; !ret && i < dev->queue_count; i++) {
- ret = DRM(flush_unblock_queue)(dev, i);
- }
- }
-
- return ret;
-}
-
-int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int ret = 0;
- drm_lock_t lock;
-
- DRM_DEBUG("\n");
-
- if (copy_from_user(&lock, (drm_lock_t __user *)arg, sizeof(lock)))
- return -EFAULT;
- ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
- DRM(flush_unblock)(dev, lock.context, lock.flags);
- return ret;
-}
diff --git a/drivers/char/drm/gamma_old_dma.h b/drivers/char/drm/gamma_old_dma.h
deleted file mode 100644
index abdd454aab9f..000000000000
--- a/drivers/char/drm/gamma_old_dma.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-
-void DRM(clear_next_buffer)(drm_device_t *dev)
-{
- drm_device_dma_t *dma = dev->dma;
-
- dma->next_buffer = NULL;
- if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
- wake_up_interruptible(&dma->next_queue->flush_queue);
- }
- dma->next_queue = NULL;
-}
-
-int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
-{
- int i;
- int candidate = -1;
- int j = jiffies;
-
- if (!dev) {
- DRM_ERROR("No device\n");
- return -1;
- }
- if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
- /* This only happens between the time the
- interrupt is initialized and the time
- the queues are initialized. */
- return -1;
- }
-
- /* Doing "while locked" DMA? */
- if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
- return DRM_KERNEL_CONTEXT;
- }
-
- /* If there are buffers on the last_context
- queue, and we have not been executing
- this context very long, continue to
- execute this context. */
- if (dev->last_switch <= j
- && dev->last_switch + DRM_TIME_SLICE > j
- && DRM_WAITCOUNT(dev, dev->last_context)) {
- return dev->last_context;
- }
-
- /* Otherwise, find a candidate */
- for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
- if (DRM_WAITCOUNT(dev, i)) {
- candidate = dev->last_checked = i;
- break;
- }
- }
-
- if (candidate < 0) {
- for (i = 0; i < dev->queue_count; i++) {
- if (DRM_WAITCOUNT(dev, i)) {
- candidate = dev->last_checked = i;
- break;
- }
- }
- }
-
- if (wrapper
- && candidate >= 0
- && candidate != dev->last_context
- && dev->last_switch <= j
- && dev->last_switch + DRM_TIME_SLICE > j) {
- if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
- del_timer(&dev->timer);
- dev->timer.function = wrapper;
- dev->timer.data = (unsigned long)dev;
- dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
- add_timer(&dev->timer);
- }
- return -1;
- }
-
- return candidate;
-}
-
-
-int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int i;
- drm_queue_t *q;
- drm_buf_t *buf;
- int idx;
- int while_locked = 0;
- drm_device_dma_t *dma = dev->dma;
- int *ind;
- int err;
- DECLARE_WAITQUEUE(entry, current);
-
- DRM_DEBUG("%d\n", d->send_count);
-
- if (d->flags & _DRM_DMA_WHILE_LOCKED) {
- int context = dev->lock.hw_lock->lock;
-
- if (!_DRM_LOCK_IS_HELD(context)) {
- DRM_ERROR("No lock held during \"while locked\""
- " request\n");
- return -EINVAL;
- }
- if (d->context != _DRM_LOCKING_CONTEXT(context)
- && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
- DRM_ERROR("Lock held by %d while %d makes"
- " \"while locked\" request\n",
- _DRM_LOCKING_CONTEXT(context),
- d->context);
- return -EINVAL;
- }
- q = dev->queuelist[DRM_KERNEL_CONTEXT];
- while_locked = 1;
- } else {
- q = dev->queuelist[d->context];
- }
-
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->block_write)) {
- add_wait_queue(&q->write_queue, &entry);
- atomic_inc(&q->block_count);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!atomic_read(&q->block_write)) break;
- schedule();
- if (signal_pending(current)) {
- atomic_dec(&q->use_count);
- remove_wait_queue(&q->write_queue, &entry);
- return -EINTR;
- }
- }
- atomic_dec(&q->block_count);
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->write_queue, &entry);
- }
-
- ind = DRM(alloc)(d->send_count * sizeof(int), DRM_MEM_DRIVER);
- if (!ind)
- return -ENOMEM;
-
- if (copy_from_user(ind, d->send_indices, d->send_count * sizeof(int))) {
- err = -EFAULT;
- goto out;
- }
-
- err = -EINVAL;
- for (i = 0; i < d->send_count; i++) {
- idx = ind[i];
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- ind[i], dma->buf_count - 1);
- goto out;
- }
- buf = dma->buflist[ idx ];
- if (buf->filp != filp) {
- DRM_ERROR("Process %d using buffer not owned\n",
- current->pid);
- goto out;
- }
- if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using buffer %d on list %d\n",
- current->pid, buf->idx, buf->list);
- goto out;
- }
- buf->used = ind[i];
- buf->while_locked = while_locked;
- buf->context = d->context;
- if (!buf->used) {
- DRM_ERROR("Queueing 0 length buffer\n");
- }
- if (buf->pending) {
- DRM_ERROR("Queueing pending buffer:"
- " buffer %d, offset %d\n",
- ind[i], i);
- goto out;
- }
- if (buf->waiting) {
- DRM_ERROR("Queueing waiting buffer:"
- " buffer %d, offset %d\n",
- ind[i], i);
- goto out;
- }
- buf->waiting = 1;
- if (atomic_read(&q->use_count) == 1
- || atomic_read(&q->finalization)) {
- DRM(free_buffer)(dev, buf);
- } else {
- DRM(waitlist_put)(&q->waitlist, buf);
- atomic_inc(&q->total_queued);
- }
- }
- atomic_dec(&q->use_count);
-
- return 0;
-
-out:
- DRM(free)(ind, d->send_count * sizeof(int), DRM_MEM_DRIVER);
- atomic_dec(&q->use_count);
- return err;
-}
-
-static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
- int order)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int i;
- drm_buf_t *buf;
- drm_device_dma_t *dma = dev->dma;
-
- for (i = d->granted_count; i < d->request_count; i++) {
- buf = DRM(freelist_get)(&dma->bufs[order].freelist,
- d->flags & _DRM_DMA_WAIT);
- if (!buf) break;
- if (buf->pending || buf->waiting) {
- DRM_ERROR("Free buffer %d in use: filp %p (w%d, p%d)\n",
- buf->idx,
- buf->filp,
- buf->waiting,
- buf->pending);
- }
- buf->filp = filp;
- if (copy_to_user(&d->request_indices[i],
- &buf->idx,
- sizeof(buf->idx)))
- return -EFAULT;
-
- if (copy_to_user(&d->request_sizes[i],
- &buf->total,
- sizeof(buf->total)))
- return -EFAULT;
-
- ++d->granted_count;
- }
- return 0;
-}
-
-
-int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma)
-{
- int order;
- int retcode = 0;
- int tmp_order;
-
- order = DRM(order)(dma->request_size);
-
- dma->granted_count = 0;
- retcode = DRM(dma_get_buffers_of_order)(filp, dma, order);
-
- if (dma->granted_count < dma->request_count
- && (dma->flags & _DRM_DMA_SMALLER_OK)) {
- for (tmp_order = order - 1;
- !retcode
- && dma->granted_count < dma->request_count
- && tmp_order >= DRM_MIN_ORDER;
- --tmp_order) {
-
- retcode = DRM(dma_get_buffers_of_order)(filp, dma,
- tmp_order);
- }
- }
-
- if (dma->granted_count < dma->request_count
- && (dma->flags & _DRM_DMA_LARGER_OK)) {
- for (tmp_order = order + 1;
- !retcode
- && dma->granted_count < dma->request_count
- && tmp_order <= DRM_MAX_ORDER;
- ++tmp_order) {
-
- retcode = DRM(dma_get_buffers_of_order)(filp, dma,
- tmp_order);
- }
- }
- return 0;
-}
-
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 18e0b7622893..2f1659b96fd1 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -45,11 +45,6 @@
#define I810_BUF_UNMAPPED 0
#define I810_BUF_MAPPED 1
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
static drm_buf_t *i810_freelist_get(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -351,6 +346,7 @@ static int i810_dma_initialize(drm_device_t *dev,
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
@@ -1383,3 +1379,19 @@ drm_ioctl_desc_t i810_ioctls[] = {
};
int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i810 is AGP.
+ */
+int i810_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
index ff51b3259af9..00609329d578 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -84,6 +84,7 @@ static struct drm_driver driver = {
.dev_priv_size = sizeof(drm_i810_buf_priv_t),
.pretakedown = i810_driver_pretakedown,
.prerelease = i810_driver_prerelease,
+ .device_is_agp = i810_driver_device_is_agp,
.release = i810_driver_release,
.dma_quiescent = i810_driver_dma_quiescent,
.reclaim_buffers = i810_reclaim_buffers,
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index 1b40538d1725..62ee4f58c59a 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -120,6 +120,7 @@ extern int i810_driver_dma_quiescent(drm_device_t *dev);
extern void i810_driver_release(drm_device_t *dev, struct file *filp);
extern void i810_driver_pretakedown(drm_device_t *dev);
extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i810_driver_device_is_agp(drm_device_t * dev);
#define I810_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index dc7733035864..6f89d5796ef3 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -47,11 +47,6 @@
#define I830_BUF_UNMAPPED 0
#define I830_BUF_MAPPED 1
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
static drm_buf_t *i830_freelist_get(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -358,6 +353,7 @@ static int i830_dma_initialize(drm_device_t *dev,
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if(!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
@@ -1586,3 +1582,19 @@ drm_ioctl_desc_t i830_ioctls[] = {
};
int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i8xx is AGP.
+ */
+int i830_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index bc36be76b8b2..0da9cd19919e 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -88,6 +88,7 @@ static struct drm_driver driver = {
.dev_priv_size = sizeof(drm_i830_buf_priv_t),
.pretakedown = i830_driver_pretakedown,
.prerelease = i830_driver_prerelease,
+ .device_is_agp = i830_driver_device_is_agp,
.release = i830_driver_release,
.dma_quiescent = i830_driver_dma_quiescent,
.reclaim_buffers = i830_reclaim_buffers,
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index df7746131dea..63f96a8b6a4a 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -137,6 +137,7 @@ extern void i830_driver_pretakedown(drm_device_t *dev);
extern void i830_driver_release(drm_device_t *dev, struct file *filp);
extern int i830_driver_dma_quiescent(drm_device_t *dev);
extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i830_driver_device_is_agp(drm_device_t * dev);
#define I830_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index acf9e52a9507..34f552f90c4a 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -95,9 +95,8 @@ static int i915_dma_cleanup(drm_device_t * dev)
drm_core_ioremapfree( &dev_priv->ring.map, dev);
}
- if (dev_priv->hw_status_page) {
- drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
- dev_priv->dma_status_page);
+ if (dev_priv->status_page_dmah) {
+ drm_pci_free(dev, dev_priv->status_page_dmah);
/* Need to rewrite hardware status page */
I915_WRITE(0x02080, 0x1ffff000);
}
@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */
- dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff,
- &dev_priv->dma_status_page);
+ dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
+ 0xffffffff);
- if (!dev_priv->hw_status_page) {
+ if (!dev_priv->status_page_dmah) {
dev->dev_private = (void *)dev_priv;
i915_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return DRM_ERR(ENOMEM);
}
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
@@ -731,3 +732,19 @@ drm_ioctl_desc_t i915_ioctls[] = {
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i9x5 is AGP.
+ */
+int i915_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 1f59d3fc79bc..106b9ec02213 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -79,6 +79,7 @@ static struct drm_driver driver = {
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.pretakedown = i915_driver_pretakedown,
.prerelease = i915_driver_prerelease,
+ .device_is_agp = i915_driver_device_is_agp,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 9c37d2367dd5..70ed4e68eac8 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -79,9 +79,10 @@ typedef struct drm_i915_private {
drm_i915_sarea_t *sarea_priv;
drm_i915_ring_buffer_t ring;
+ drm_dma_handle_t *status_page_dmah;
void *hw_status_page;
- unsigned long counter;
dma_addr_t dma_status_page;
+ unsigned long counter;
int back_offset;
int front_offset;
@@ -102,6 +103,7 @@ typedef struct drm_i915_private {
extern void i915_kernel_lost_context(drm_device_t * dev);
extern void i915_driver_pretakedown(drm_device_t *dev);
extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(drm_device_t *dev);
/* i915_irq.c */
extern int i915_irq_emit(DRM_IOCTL_ARGS);
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 832eaf8a5068..fc7d4a594bca 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -23,18 +23,21 @@
* 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Jeff Hartmann <jhartmann@valinux.com>
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- * Rewritten by:
- * Gareth Hughes <gareth@valinux.com>
+ */
+
+/**
+ * \file mga_dma.c
+ * DMA support for MGA G200 / G400.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Jeff Hartmann <jhartmann@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
*/
#include "drmP.h"
#include "drm.h"
+#include "drm_sarea.h"
#include "mga_drm.h"
#include "mga_drv.h"
@@ -148,7 +151,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv )
DRM_DEBUG( " space = 0x%06x\n", primary->space );
mga_flush_write_combine();
- MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
DRM_DEBUG( "done.\n" );
}
@@ -190,7 +193,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
DRM_DEBUG( " space = 0x%06x\n", primary->space );
mga_flush_write_combine();
- MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
set_bit( 0, &primary->wrapped );
DRM_DEBUG( "done.\n" );
@@ -396,23 +399,390 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
* DMA initialization, cleanup
*/
+
+int mga_driver_preinit(drm_device_t *dev, unsigned long flags)
+{
+ drm_mga_private_t * dev_priv;
+
+ dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ if (!dev_priv)
+ return DRM_ERR(ENOMEM);
+
+ dev->dev_private = (void *)dev_priv;
+ memset(dev_priv, 0, sizeof(drm_mga_private_t));
+
+ dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+ dev_priv->chipset = flags;
+
+ return 0;
+}
+
+#if __OS_HAS_AGP
+/**
+ * Bootstrap the driver for AGP DMA.
+ *
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory. If not, the microcode may as well always be put in PCI
+ * memory.
+ *
+ * \todo
+ * This routine needs to set dma_bs->agp_mode to the mode actually configured
+ * in the hardware. Looking just at the Linux AGP driver code, I don't see
+ * an easy way to determine this.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
+ */
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+ const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ int err;
+ unsigned offset;
+ const unsigned secondary_size = dma_bs->secondary_bin_count
+ * dma_bs->secondary_bin_size;
+ const unsigned agp_size = (dma_bs->agp_size << 20);
+ drm_buf_desc_t req;
+ drm_agp_mode_t mode;
+ drm_agp_info_t info;
+
+
+ /* Acquire AGP. */
+ err = drm_agp_acquire(dev);
+ if (err) {
+ DRM_ERROR("Unable to acquire AGP\n");
+ return err;
+ }
+
+ err = drm_agp_info(dev, &info);
+ if (err) {
+ DRM_ERROR("Unable to get AGP info\n");
+ return err;
+ }
+
+ mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
+ err = drm_agp_enable(dev, mode);
+ if (err) {
+ DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+ return err;
+ }
+
+
+ /* In addition to the usual AGP mode configuration, the G200 AGP cards
+ * need to have the AGP mode "manually" set.
+ */
+
+ if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+ if (mode.mode & 0x02) {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+ }
+ else {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+ }
+ }
+
+
+ /* Allocate and bind AGP memory. */
+ dev_priv->agp_pages = agp_size / PAGE_SIZE;
+ dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 );
+ if (dev_priv->agp_mem == NULL) {
+ dev_priv->agp_pages = 0;
+ DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+ dma_bs->agp_size);
+ return DRM_ERR(ENOMEM);
+ }
+
+ err = drm_bind_agp( dev_priv->agp_mem, 0 );
+ if (err) {
+ DRM_ERROR("Unable to bind AGP memory\n");
+ return err;
+ }
+
+ offset = 0;
+ err = drm_addmap( dev, offset, warp_size,
+ _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
+ if (err) {
+ DRM_ERROR("Unable to map WARP microcode\n");
+ return err;
+ }
+
+ offset += warp_size;
+ err = drm_addmap( dev, offset, dma_bs->primary_size,
+ _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
+ if (err) {
+ DRM_ERROR("Unable to map primary DMA region\n");
+ return err;
+ }
+
+ offset += dma_bs->primary_size;
+ err = drm_addmap( dev, offset, secondary_size,
+ _DRM_AGP, 0, & dev->agp_buffer_map );
+ if (err) {
+ DRM_ERROR("Unable to map secondary DMA region\n");
+ return err;
+ }
+
+ (void) memset( &req, 0, sizeof(req) );
+ req.count = dma_bs->secondary_bin_count;
+ req.size = dma_bs->secondary_bin_size;
+ req.flags = _DRM_AGP_BUFFER;
+ req.agp_start = offset;
+
+ err = drm_addbufs_agp( dev, & req );
+ if (err) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+ }
+
+ offset += secondary_size;
+ err = drm_addmap( dev, offset, agp_size - offset,
+ _DRM_AGP, 0, & dev_priv->agp_textures );
+ if (err) {
+ DRM_ERROR("Unable to map AGP texture region\n");
+ return err;
+ }
+
+ drm_core_ioremap(dev_priv->warp, dev);
+ drm_core_ioremap(dev_priv->primary, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+
+ if (!dev_priv->warp->handle ||
+ !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
+ DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
+ dev_priv->warp->handle, dev_priv->primary->handle,
+ dev->agp_buffer_map->handle);
+ return DRM_ERR(ENOMEM);
+ }
+
+ dev_priv->dma_access = MGA_PAGPXFER;
+ dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+ DRM_INFO("Initialized card for AGP DMA.\n");
+ return 0;
+}
+#else
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ return -EINVAL;
+}
+#endif
+
+/**
+ * Bootstrap the driver for PCI DMA.
+ *
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better. The size should be rounded up to the nearest page size, then
+ * decrease the request size by a single page each pass through the loop.
+ *
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+ const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ unsigned int primary_size;
+ unsigned int bin_count;
+ int err;
+ drm_buf_desc_t req;
+
+
+ if (dev->dma == NULL) {
+ DRM_ERROR("dev->dma is NULL\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ /* The proper alignment is 0x100 for this mapping */
+ err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
+ _DRM_READ_ONLY, &dev_priv->warp);
+ if (err != 0) {
+ DRM_ERROR("Unable to create mapping for WARP microcode\n");
+ return err;
+ }
+
+ /* Other than the bottom two bits being used to encode other
+ * information, there don't appear to be any restrictions on the
+ * alignment of the primary or secondary DMA buffers.
+ */
+
+ for ( primary_size = dma_bs->primary_size
+ ; primary_size != 0
+ ; primary_size >>= 1 ) {
+ /* The proper alignment for this mapping is 0x04 */
+ err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+ _DRM_READ_ONLY, &dev_priv->primary);
+ if (!err)
+ break;
+ }
+
+ if (err != 0) {
+ DRM_ERROR("Unable to allocate primary DMA region\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ if (dev_priv->primary->size != dma_bs->primary_size) {
+ DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+ dma_bs->primary_size,
+ (unsigned) dev_priv->primary->size);
+ dma_bs->primary_size = dev_priv->primary->size;
+ }
+
+ for ( bin_count = dma_bs->secondary_bin_count
+ ; bin_count > 0
+ ; bin_count-- ) {
+ (void) memset( &req, 0, sizeof(req) );
+ req.count = bin_count;
+ req.size = dma_bs->secondary_bin_size;
+
+ err = drm_addbufs_pci( dev, & req );
+ if (!err) {
+ break;
+ }
+ }
+
+ if (bin_count == 0) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+ }
+
+ if (bin_count != dma_bs->secondary_bin_count) {
+ DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
+ "to %u.\n", dma_bs->secondary_bin_count, bin_count);
+
+ dma_bs->secondary_bin_count = bin_count;
+ }
+
+ dev_priv->dma_access = 0;
+ dev_priv->wagp_enable = 0;
+
+ dma_bs->agp_mode = 0;
+
+ DRM_INFO("Initialized card for PCI DMA.\n");
+ return 0;
+}
+
+
+static int mga_do_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+ int err;
+ drm_mga_private_t * const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+
+ dev_priv->used_new_dma_init = 1;
+
+ /* The first steps are the same for both PCI and AGP based DMA. Map
+ * the cards MMIO registers and map a status page.
+ */
+ err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
+ _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
+ if (err) {
+ DRM_ERROR("Unable to map MMIO region\n");
+ return err;
+ }
+
+
+ err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
+ _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+ & dev_priv->status );
+ if (err) {
+ DRM_ERROR("Unable to map status region\n");
+ return err;
+ }
+
+
+ /* The DMA initialization procedure is slightly different for PCI and
+ * AGP cards. AGP cards just allocate a large block of AGP memory and
+ * carve off portions of it for internal uses. The remaining memory
+ * is returned to user-mode to be used for AGP textures.
+ */
+ if (is_agp) {
+ err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+ }
+
+ /* If we attempted to initialize the card for AGP DMA but failed,
+ * clean-up any mess that may have been created.
+ */
+
+ if (err) {
+ mga_do_cleanup_dma(dev);
+ }
+
+
+ /* Not only do we want to try and initialized PCI cards for PCI DMA,
+ * but we also try to initialized AGP cards that could not be
+ * initialized for AGP DMA. This covers the case where we have an AGP
+ * card in a system with an unsupported AGP chipset. In that case the
+ * card will be detected as AGP, but we won't be able to allocate any
+ * AGP memory, etc.
+ */
+
+ if (!is_agp || err) {
+ err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+ }
+
+
+ return err;
+}
+
+int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_dma_bootstrap_t bootstrap;
+ int err;
+
+
+ DRM_COPY_FROM_USER_IOCTL(bootstrap,
+ (drm_mga_dma_bootstrap_t __user *) data,
+ sizeof(bootstrap));
+
+ err = mga_do_dma_bootstrap(dev, & bootstrap);
+ if (! err) {
+ static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
+ const drm_mga_private_t * const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ if (dev_priv->agp_textures != NULL) {
+ bootstrap.texture_handle = dev_priv->agp_textures->offset;
+ bootstrap.texture_size = dev_priv->agp_textures->size;
+ }
+ else {
+ bootstrap.texture_handle = 0;
+ bootstrap.texture_size = 0;
+ }
+
+ bootstrap.agp_mode = modes[ bootstrap.agp_mode & 0x07 ];
+ if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap,
+ sizeof(bootstrap))) {
+ err = DRM_ERR(EFAULT);
+ }
+ }
+ else {
+ mga_do_cleanup_dma(dev);
+ }
+
+ return err;
+}
+
static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
{
drm_mga_private_t *dev_priv;
int ret;
DRM_DEBUG( "\n" );
- dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
- if ( !dev_priv )
- return DRM_ERR(ENOMEM);
-
- memset( dev_priv, 0, sizeof(drm_mga_private_t) );
- dev_priv->chipset = init->chipset;
+ dev_priv = dev->dev_private;
- dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
-
- if ( init->sgram ) {
+ if (init->sgram) {
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
} else {
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
@@ -436,88 +806,66 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
DRM_GETSAREA();
- if(!dev_priv->sarea) {
- DRM_ERROR( "failed to find sarea!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ if (!dev_priv->sarea) {
+ DRM_ERROR("failed to find sarea!\n");
return DRM_ERR(EINVAL);
}
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- if(!dev_priv->mmio) {
- DRM_ERROR( "failed to find mmio region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->status = drm_core_findmap(dev, init->status_offset);
- if(!dev_priv->status) {
- DRM_ERROR( "failed to find status page!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
- if(!dev_priv->warp) {
- DRM_ERROR( "failed to find warp microcode region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
- if(!dev_priv->primary) {
- DRM_ERROR( "failed to find primary dma region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- if(!dev->agp_buffer_map) {
- DRM_ERROR( "failed to find dma buffer region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
+ if (! dev_priv->used_new_dma_init) {
+ dev_priv->status = drm_core_findmap(dev, init->status_offset);
+ if (!dev_priv->status) {
+ DRM_ERROR("failed to find status page!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio) {
+ DRM_ERROR("failed to find mmio region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
+ if (!dev_priv->warp) {
+ DRM_ERROR("failed to find warp microcode region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
+ if (!dev_priv->primary) {
+ DRM_ERROR("failed to find primary dma region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("failed to find dma buffer region!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ drm_core_ioremap(dev_priv->warp, dev);
+ drm_core_ioremap(dev_priv->primary, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
}
dev_priv->sarea_priv =
(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
init->sarea_priv_offset);
- drm_core_ioremap( dev_priv->warp, dev );
- drm_core_ioremap( dev_priv->primary, dev );
- drm_core_ioremap( dev->agp_buffer_map, dev );
-
- if(!dev_priv->warp->handle ||
- !dev_priv->primary->handle ||
- !dev->agp_buffer_map->handle ) {
- DRM_ERROR( "failed to ioremap agp regions!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ if (!dev_priv->warp->handle ||
+ !dev_priv->primary->handle ||
+ ((dev_priv->dma_access != 0) &&
+ ((dev->agp_buffer_map == NULL) ||
+ (dev->agp_buffer_map->handle == NULL)))) {
+ DRM_ERROR("failed to ioremap agp regions!\n");
return DRM_ERR(ENOMEM);
}
- ret = mga_warp_install_microcode( dev_priv );
- if ( ret < 0 ) {
- DRM_ERROR( "failed to install WARP ucode!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ ret = mga_warp_install_microcode(dev_priv);
+ if (ret < 0) {
+ DRM_ERROR("failed to install WARP ucode!\n");
return ret;
}
- ret = mga_warp_init( dev_priv );
- if ( ret < 0 ) {
- DRM_ERROR( "failed to init WARP engine!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ ret = mga_warp_init(dev_priv);
+ if (ret < 0) {
+ DRM_ERROR("failed to init WARP engine!\n");
return ret;
}
@@ -557,22 +905,18 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
dev_priv->sarea_priv->last_frame.head = 0;
dev_priv->sarea_priv->last_frame.wrap = 0;
- if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
- DRM_ERROR( "could not initialize freelist\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ if (mga_freelist_init(dev, dev_priv) < 0) {
+ DRM_ERROR("could not initialize freelist\n");
return DRM_ERR(ENOMEM);
}
- /* Make dev_private visable to others. */
- dev->dev_private = (void *)dev_priv;
return 0;
}
static int mga_do_cleanup_dma( drm_device_t *dev )
{
- DRM_DEBUG( "\n" );
+ int err = 0;
+ DRM_DEBUG("\n");
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
@@ -583,37 +927,73 @@ static int mga_do_cleanup_dma( drm_device_t *dev )
if ( dev->dev_private ) {
drm_mga_private_t *dev_priv = dev->dev_private;
- if ( dev_priv->warp != NULL )
- drm_core_ioremapfree( dev_priv->warp, dev );
- if ( dev_priv->primary != NULL )
- drm_core_ioremapfree( dev_priv->primary, dev );
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
+ if ((dev_priv->warp != NULL)
+ && (dev_priv->mmio->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->warp, dev);
+
+ if ((dev_priv->primary != NULL)
+ && (dev_priv->primary->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->primary, dev);
+
+ if (dev->agp_buffer_map != NULL)
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
- if ( dev_priv->head != NULL ) {
- mga_freelist_cleanup( dev );
+ if (dev_priv->used_new_dma_init) {
+#if __OS_HAS_AGP
+ if (dev_priv->agp_mem != NULL) {
+ dev_priv->agp_textures = NULL;
+ drm_unbind_agp(dev_priv->agp_mem);
+
+ drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages);
+ dev_priv->agp_pages = 0;
+ dev_priv->agp_mem = NULL;
+ }
+
+ if ((dev->agp != NULL) && dev->agp->acquired) {
+ err = drm_agp_release(dev);
+ }
+#endif
+ dev_priv->used_new_dma_init = 0;
}
- drm_free( dev->dev_private, sizeof(drm_mga_private_t),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev_priv->warp = NULL;
+ dev_priv->primary = NULL;
+ dev_priv->mmio = NULL;
+ dev_priv->status = NULL;
+ dev_priv->sarea = NULL;
+ dev_priv->sarea_priv = NULL;
+ dev->agp_buffer_map = NULL;
+
+ memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+ dev_priv->warp_pipe = 0;
+ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+ if (dev_priv->head != NULL) {
+ mga_freelist_cleanup(dev);
+ }
}
- return 0;
+ return err;
}
int mga_dma_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_init_t init;
+ int err;
LOCK_TEST_WITH_RETURN( dev, filp );
- DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) );
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
+ sizeof(init));
switch ( init.func ) {
case MGA_INIT_DMA:
- return mga_do_init_dma( dev, &init );
+ err = mga_do_init_dma(dev, &init);
+ if (err) {
+ (void) mga_do_cleanup_dma(dev);
+ }
+ return err;
case MGA_CLEANUP_DMA:
return mga_do_cleanup_dma( dev );
}
@@ -742,7 +1122,21 @@ int mga_dma_buffers( DRM_IOCTL_ARGS )
return ret;
}
-void mga_driver_pretakedown(drm_device_t *dev)
+/**
+ * Called just before the module is unloaded.
+ */
+int mga_driver_postcleanup(drm_device_t * dev)
+{
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+
+ return 0;
+}
+
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_pretakedown(drm_device_t * dev)
{
mga_do_cleanup_dma( dev );
}
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
index 521d4451d012..d20aab3bd57b 100644
--- a/drivers/char/drm/mga_drm.h
+++ b/drivers/char/drm/mga_drm.h
@@ -73,7 +73,8 @@
#define MGA_CARD_TYPE_G200 1
#define MGA_CARD_TYPE_G400 2
-
+#define MGA_CARD_TYPE_G450 3 /* not currently used */
+#define MGA_CARD_TYPE_G550 4
#define MGA_FRONT 0x1
#define MGA_BACK 0x2
@@ -225,10 +226,6 @@ typedef struct _drm_mga_sarea {
} drm_mga_sarea_t;
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmMga.h)
- */
-
/* MGA specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
@@ -243,6 +240,14 @@ typedef struct _drm_mga_sarea {
#define DRM_MGA_BLIT 0x08
#define DRM_MGA_GETPARAM 0x09
+/* 3.2:
+ * ioctls for operating on fences.
+ */
+#define DRM_MGA_SET_FENCE 0x0a
+#define DRM_MGA_WAIT_FENCE 0x0b
+#define DRM_MGA_DMA_BOOTSTRAP 0x0c
+
+
#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
@@ -253,6 +258,9 @@ typedef struct _drm_mga_sarea {
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
+#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
typedef struct _drm_mga_warp_index {
int installed;
@@ -291,12 +299,72 @@ typedef struct drm_mga_init {
unsigned long buffers_offset;
} drm_mga_init_t;
-typedef struct drm_mga_fullscreen {
- enum {
- MGA_INIT_FULLSCREEN = 0x01,
- MGA_CLEANUP_FULLSCREEN = 0x02
- } func;
-} drm_mga_fullscreen_t;
+typedef struct drm_mga_dma_bootstrap {
+ /**
+ * \name AGP texture region
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
+ * be filled in with the actual AGP texture settings.
+ *
+ * \warning
+ * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
+ * is zero, it means that PCI memory (most likely through the use of
+ * an IOMMU) is being used for "AGP" textures.
+ */
+ /*@{*/
+ unsigned long texture_handle; /**< Handle used to map AGP textures. */
+ uint32_t texture_size; /**< Size of the AGP texture region. */
+ /*@}*/
+
+
+ /**
+ * Requested size of the primary DMA region.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ */
+ uint32_t primary_size;
+
+
+ /**
+ * Requested number of secondary DMA buffers.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual number of secondary DMA buffers
+ * allocated. Particularly when PCI DMA is used, this may be
+ * (subtantially) less than the number requested.
+ */
+ uint32_t secondary_bin_count;
+
+
+ /**
+ * Requested size of each secondary DMA buffer.
+ *
+ * While the kernel \b is free to reduce
+ * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
+ * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
+ */
+ uint32_t secondary_bin_size;
+
+
+ /**
+ * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X,
+ * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is
+ * zero, it means that PCI DMA should be used, even if AGP is
+ * possible.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ * (i.e., PCI DMA was used), this value will be zero.
+ */
+ uint32_t agp_mode;
+
+
+ /**
+ * Desired AGP GART size, measured in megabytes.
+ */
+ uint8_t agp_size;
+} drm_mga_dma_bootstrap_t;
typedef struct drm_mga_clear {
unsigned int flags;
@@ -341,6 +409,14 @@ typedef struct _drm_mga_blit {
*/
#define MGA_PARAM_IRQ_NR 1
+/* 3.2: Query the actual card type. The DDX only distinguishes between
+ * G200 chips and non-G200 chips, which it calls G400. It turns out that
+ * there are some very sublte differences between the G4x0 chips and the G550
+ * chips. Using this parameter query, a client-side driver can detect the
+ * difference between a G4x0 and a G550.
+ */
+#define MGA_PARAM_CARD_TYPE 2
+
typedef struct drm_mga_getparam {
int param;
void __user *value;
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 844cca9cb29d..daabbba3b297 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -38,8 +38,15 @@
#include "drm_pciids.h"
+static int mga_driver_device_is_agp(drm_device_t * dev);
static int postinit( struct drm_device *dev, unsigned long flags )
{
+ drm_mga_private_t * const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
+ dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
+
dev->counters += 3;
dev->types[6] = _DRM_STAT_IRQ;
dev->types[7] = _DRM_STAT_PRIMARY;
@@ -79,8 +86,11 @@ extern int mga_max_ioctl;
static struct drm_driver driver = {
.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .preinit = mga_driver_preinit,
+ .postcleanup = mga_driver_postcleanup,
.pretakedown = mga_driver_pretakedown,
.dma_quiescent = mga_driver_dma_quiescent,
+ .device_is_agp = mga_driver_device_is_agp,
.vblank_wait = mga_driver_vblank_wait,
.irq_preinstall = mga_driver_irq_preinstall,
.irq_postinstall = mga_driver_irq_postinstall,
@@ -128,3 +138,38 @@ module_exit(mga_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL and additional rights");
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * In addition to the usual tests performed by \c drm_device_is_agp, this
+ * function detects PCI G450 cards that appear to the system exactly like
+ * AGP G450 cards.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
+ */
+int mga_driver_device_is_agp(drm_device_t * dev)
+{
+ const struct pci_dev * const pdev = dev->pdev;
+
+
+ /* There are PCI versions of the G450. These cards have the
+ * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+ * bridge chip. We detect these cards, which are not currently
+ * supported by this driver, by looking at the device ID of the
+ * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the
+ * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+ * device.
+ */
+
+ if ( (pdev->device == 0x0525)
+ && (pdev->bus->self->vendor == 0x3388)
+ && (pdev->bus->self->device == 0x0021) ) {
+ return 0;
+ }
+
+ return 2;
+}
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 9412e2816eb7..b22fdbd4f830 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -38,10 +38,10 @@
#define DRIVER_NAME "mga"
#define DRIVER_DESC "Matrox G200/G400"
-#define DRIVER_DATE "20021029"
+#define DRIVER_DATE "20050607"
#define DRIVER_MAJOR 3
-#define DRIVER_MINOR 1
+#define DRIVER_MINOR 2
#define DRIVER_PATCHLEVEL 0
typedef struct drm_mga_primary_buffer {
@@ -87,9 +87,43 @@ typedef struct drm_mga_private {
int chipset;
int usec_timeout;
+ /**
+ * If set, the new DMA initialization sequence was used. This is
+ * primarilly used to select how the driver should uninitialized its
+ * internal DMA structures.
+ */
+ int used_new_dma_init;
+
+ /**
+ * If AGP memory is used for DMA buffers, this will be the value
+ * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer).
+ */
+ u32 dma_access;
+
+ /**
+ * If AGP memory is used for DMA buffers, this will be the value
+ * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI
+ * transfer).
+ */
+ u32 wagp_enable;
+
+ /**
+ * \name MMIO region parameters.
+ *
+ * \sa drm_mga_private_t::mmio
+ */
+ /*@{*/
+ u32 mmio_base; /**< Bus address of base of MMIO. */
+ u32 mmio_size; /**< Size of the MMIO region. */
+ /*@}*/
+
u32 clear_cmd;
u32 maccess;
+ wait_queue_head_t fence_queue;
+ atomic_t last_fence_retired;
+ u32 next_fence_to_post;
+
unsigned int fb_cpp;
unsigned int front_offset;
unsigned int front_pitch;
@@ -108,35 +142,43 @@ typedef struct drm_mga_private {
drm_local_map_t *status;
drm_local_map_t *warp;
drm_local_map_t *primary;
- drm_local_map_t *buffers;
drm_local_map_t *agp_textures;
+
+ DRM_AGP_MEM *agp_mem;
+ unsigned int agp_pages;
} drm_mga_private_t;
/* mga_dma.c */
-extern int mga_dma_init( DRM_IOCTL_ARGS );
-extern int mga_dma_flush( DRM_IOCTL_ARGS );
-extern int mga_dma_reset( DRM_IOCTL_ARGS );
-extern int mga_dma_buffers( DRM_IOCTL_ARGS );
-extern void mga_driver_pretakedown(drm_device_t *dev);
-extern int mga_driver_dma_quiescent(drm_device_t *dev);
-
-extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
-
-extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
-extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
-extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
+extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags);
+extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
+extern int mga_dma_init(DRM_IOCTL_ARGS);
+extern int mga_dma_flush(DRM_IOCTL_ARGS);
+extern int mga_dma_reset(DRM_IOCTL_ARGS);
+extern int mga_dma_buffers(DRM_IOCTL_ARGS);
+extern int mga_driver_postcleanup(drm_device_t * dev);
+extern void mga_driver_pretakedown(drm_device_t * dev);
+extern int mga_driver_dma_quiescent(drm_device_t * dev);
+
+extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
+
+extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
/* mga_warp.c */
-extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
-extern int mga_warp_init( drm_mga_private_t *dev_priv );
-
-extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
-extern void mga_driver_irq_preinstall( drm_device_t *dev );
-extern void mga_driver_irq_postinstall( drm_device_t *dev );
-extern void mga_driver_irq_uninstall( drm_device_t *dev );
+extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+extern int mga_warp_init(drm_mga_private_t * dev_priv);
+
+ /* mga_irq.c */
+extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern void mga_driver_irq_preinstall(drm_device_t * dev);
+extern void mga_driver_irq_postinstall(drm_device_t * dev);
+extern void mga_driver_irq_uninstall(drm_device_t * dev);
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -527,6 +569,12 @@ do { \
*/
#define MGA_EXEC 0x0100
+/* AGP PLL encoding (for G200 only).
+ */
+#define MGA_AGP_PLL 0x1e4c
+# define MGA_AGP2XPLL_DISABLE (0 << 0)
+# define MGA_AGP2XPLL_ENABLE (1 << 0)
+
/* Warp registers
*/
#define MGA_WR0 0x2d00
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index bc745cfa2095..77d738e75a4d 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -129,9 +129,76 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
}
+typedef struct drm_mga_drm_bootstrap32 {
+ u32 texture_handle;
+ u32 texture_size;
+ u32 primary_size;
+ u32 secondary_bin_count;
+ u32 secondary_bin_size;
+ u32 agp_mode;
+ u8 agp_size;
+} drm_mga_dma_bootstrap32_t;
+
+static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_mga_dma_bootstrap32_t dma_bootstrap32;
+ drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+ int err;
+
+ if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
+ if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
+ || __put_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __put_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __put_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __put_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __put_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+ || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+ (unsigned long)dma_bootstrap);
+ if (err)
+ return err;
+
+ if (__get_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __get_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __get_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __get_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __get_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __get_user(dma_bootstrap32.agp_mode,
+ &dma_bootstrap->agp_mode)
+ || __get_user(dma_bootstrap32.agp_size,
+ &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ return 0;
+}
+
drm_ioctl_compat_t *mga_compat_ioctls[] = {
[DRM_MGA_INIT] = compat_mga_init,
[DRM_MGA_GETPARAM] = compat_mga_getparam,
+ [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
};
/**
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index bc0b6b5d43a6..52eaa4e788f9 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -41,15 +41,40 @@ irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
drm_mga_private_t *dev_priv =
(drm_mga_private_t *)dev->dev_private;
int status;
+ int handled = 0;
+
+ status = MGA_READ(MGA_STATUS);
- status = MGA_READ( MGA_STATUS );
-
/* VBLANK interrupt */
if ( status & MGA_VLINEPEN ) {
MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals( dev );
+ drm_vbl_send_signals(dev);
+ handled = 1;
+ }
+
+ /* SOFTRAP interrupt */
+ if (status & MGA_SOFTRAPEN) {
+ const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
+ const u32 prim_end = MGA_READ(MGA_PRIMEND);
+
+
+ MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
+
+ /* In addition to clearing the interrupt-pending bit, we
+ * have to write to MGA_PRIMEND to re-start the DMA operation.
+ */
+ if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
+ MGA_WRITE(MGA_PRIMEND, prim_end);
+ }
+
+ atomic_inc(&dev_priv->last_fence_retired);
+ DRM_WAKEUP(&dev_priv->fence_queue);
+ handled = 1;
+ }
+
+ if ( handled ) {
return IRQ_HANDLED;
}
return IRQ_NONE;
@@ -73,9 +98,28 @@ int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
return ret;
}
-void mga_driver_irq_preinstall( drm_device_t *dev ) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ unsigned int cur_fence;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+ * using fences.
+ */
+ DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+ (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
+ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_fence;
+
+ return ret;
+}
+
+void mga_driver_irq_preinstall(drm_device_t * dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
/* Disable *all* interrupts */
MGA_WRITE( MGA_IEN, 0 );
@@ -83,12 +127,14 @@ void mga_driver_irq_preinstall( drm_device_t *dev ) {
MGA_WRITE( MGA_ICLEAR, ~0 );
}
-void mga_driver_irq_postinstall( drm_device_t *dev ) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+void mga_driver_irq_postinstall(drm_device_t * dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+ DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
- /* Turn on VBL interrupt */
- MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+ /* Turn on vertical blank interrupt and soft trap interrupt. */
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
}
void mga_driver_irq_uninstall( drm_device_t *dev ) {
@@ -98,5 +144,7 @@ void mga_driver_irq_uninstall( drm_device_t *dev ) {
return;
/* Disable *all* interrupts */
- MGA_WRITE( MGA_IEN, 0 );
+ MGA_WRITE(MGA_IEN, 0);
+
+ dev->irq_enabled = 0;
}
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 3c7a8f5ba501..05bbb4719376 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -53,16 +53,16 @@ static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
/* Force reset of DWGCTL on G400 (eliminates clip disable bit).
*/
- if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
- DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl,
- MGA_LEN + MGA_EXEC, 0x80000000,
- MGA_DWGCTL, ctx->dwgctl,
- MGA_LEN + MGA_EXEC, 0x80000000 );
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+ DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000,
+ MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000);
}
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_CXBNDRY, (box->x2 << 16) | box->x1,
- MGA_YTOP, box->y1 * pitch,
- MGA_YBOT, box->y2 * pitch );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+ MGA_YTOP, box->y1 * pitch,
+ MGA_YBOT, (box->y2 - 1) * pitch);
ADVANCE_DMA();
}
@@ -260,12 +260,11 @@ static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
/* Padding required to to hardware bug.
*/
- DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
- MGA_WMODE_START |
- MGA_WAGP_ENABLE) );
+ DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START | dev_priv->wagp_enable));
ADVANCE_DMA();
}
@@ -342,12 +341,11 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */
/* Padding required to to hardware bug */
- DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
- MGA_WMODE_START |
- MGA_WAGP_ENABLE) );
+ DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START | dev_priv->wagp_enable));
ADVANCE_DMA();
}
@@ -459,9 +457,9 @@ static int mga_verify_state( drm_mga_private_t *dev_priv )
if ( dirty & MGA_UPLOAD_TEX0 )
ret |= mga_verify_tex( dev_priv, 0 );
- if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
- if ( dirty & MGA_UPLOAD_TEX1 )
- ret |= mga_verify_tex( dev_priv, 1 );
+ if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+ if (dirty & MGA_UPLOAD_TEX1)
+ ret |= mga_verify_tex(dev_priv, 1);
if ( dirty & MGA_UPLOAD_PIPE )
ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
@@ -686,12 +684,12 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
BEGIN_DMA( 1 );
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_SECADDRESS, (address |
- MGA_DMA_VERTEX),
- MGA_SECEND, ((address + length) |
- MGA_PAGPXFER) );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SECADDRESS, (address |
+ MGA_DMA_VERTEX),
+ MGA_SECEND, ((address + length) |
+ dev_priv->dma_access));
ADVANCE_DMA();
} while ( ++i < sarea_priv->nbox );
@@ -733,11 +731,11 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
BEGIN_DMA( 1 );
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_SETUPADDRESS, address + start,
- MGA_SETUPEND, ((address + end) |
- MGA_PAGPXFER) );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SETUPADDRESS, address + start,
+ MGA_SETUPEND, ((address + end) |
+ dev_priv->dma_access));
ADVANCE_DMA();
} while ( ++i < sarea_priv->nbox );
@@ -764,7 +762,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
- u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
+ u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
u32 y2;
DMA_LOCALS;
DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
@@ -1095,6 +1093,9 @@ static int mga_getparam( DRM_IOCTL_ARGS )
case MGA_PARAM_IRQ_NR:
value = dev->irq;
break;
+ case MGA_PARAM_CARD_TYPE:
+ value = dev_priv->chipset;
+ break;
default:
return DRM_ERR(EINVAL);
}
@@ -1107,17 +1108,82 @@ static int mga_getparam( DRM_IOCTL_ARGS )
return 0;
}
+static int mga_set_fence(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u32 temp;
+ DMA_LOCALS;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+ /* I would normal do this assignment in the declaration of temp,
+ * but dev_priv may be NULL.
+ */
+
+ temp = dev_priv->next_fence_to_post;
+ dev_priv->next_fence_to_post++;
+
+ BEGIN_DMA(1);
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SOFTRAP, 0x00000000);
+ ADVANCE_DMA();
+
+ if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ return 0;
+}
+
+static int mga_wait_fence(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u32 fence;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32));
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+ mga_driver_fence_wait(dev, & fence);
+
+ if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ return 0;
+}
+
drm_ioctl_desc_t mga_ioctls[] = {
- [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1},
+
};
int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
index 0a3a0cc700dc..55ccc8a0ac29 100644
--- a/drivers/char/drm/mga_warp.c
+++ b/drivers/char/drm/mga_warp.c
@@ -48,65 +48,52 @@ do { \
vcbase += WARP_UCODE_SIZE( which ); \
} while (0)
-
-static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
-{
- unsigned int size;
-
- size = ( WARP_UCODE_SIZE( warp_g400_tgz ) +
- WARP_UCODE_SIZE( warp_g400_tgza ) +
- WARP_UCODE_SIZE( warp_g400_tgzaf ) +
- WARP_UCODE_SIZE( warp_g400_tgzf ) +
- WARP_UCODE_SIZE( warp_g400_tgzs ) +
- WARP_UCODE_SIZE( warp_g400_tgzsa ) +
- WARP_UCODE_SIZE( warp_g400_tgzsaf ) +
- WARP_UCODE_SIZE( warp_g400_tgzsf ) +
- WARP_UCODE_SIZE( warp_g400_t2gz ) +
- WARP_UCODE_SIZE( warp_g400_t2gza ) +
- WARP_UCODE_SIZE( warp_g400_t2gzaf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzs ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsa ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsaf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsf ) );
-
- size = PAGE_ALIGN( size );
-
- DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
- return size;
-}
-
-static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
+static const unsigned int mga_warp_g400_microcode_size =
+ (WARP_UCODE_SIZE(warp_g400_tgz) +
+ WARP_UCODE_SIZE(warp_g400_tgza) +
+ WARP_UCODE_SIZE(warp_g400_tgzaf) +
+ WARP_UCODE_SIZE(warp_g400_tgzf) +
+ WARP_UCODE_SIZE(warp_g400_tgzs) +
+ WARP_UCODE_SIZE(warp_g400_tgzsa) +
+ WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+ WARP_UCODE_SIZE(warp_g400_tgzsf) +
+ WARP_UCODE_SIZE(warp_g400_t2gz) +
+ WARP_UCODE_SIZE(warp_g400_t2gza) +
+ WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+ WARP_UCODE_SIZE(warp_g400_t2gzf) +
+ WARP_UCODE_SIZE(warp_g400_t2gzs) +
+ WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+ WARP_UCODE_SIZE(warp_g400_t2gzsaf) +
+ WARP_UCODE_SIZE(warp_g400_t2gzsf));
+
+static const unsigned int mga_warp_g200_microcode_size =
+ (WARP_UCODE_SIZE(warp_g200_tgz) +
+ WARP_UCODE_SIZE(warp_g200_tgza) +
+ WARP_UCODE_SIZE(warp_g200_tgzaf) +
+ WARP_UCODE_SIZE(warp_g200_tgzf) +
+ WARP_UCODE_SIZE(warp_g200_tgzs) +
+ WARP_UCODE_SIZE(warp_g200_tgzsa) +
+ WARP_UCODE_SIZE(warp_g200_tgzsaf) +
+ WARP_UCODE_SIZE(warp_g200_tgzsf));
+
+
+unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
{
- unsigned int size;
-
- size = ( WARP_UCODE_SIZE( warp_g200_tgz ) +
- WARP_UCODE_SIZE( warp_g200_tgza ) +
- WARP_UCODE_SIZE( warp_g200_tgzaf ) +
- WARP_UCODE_SIZE( warp_g200_tgzf ) +
- WARP_UCODE_SIZE( warp_g200_tgzs ) +
- WARP_UCODE_SIZE( warp_g200_tgzsa ) +
- WARP_UCODE_SIZE( warp_g200_tgzsaf ) +
- WARP_UCODE_SIZE( warp_g200_tgzsf ) );
-
- size = PAGE_ALIGN( size );
-
- DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
- return size;
+ switch (dev_priv->chipset) {
+ case MGA_CARD_TYPE_G400:
+ case MGA_CARD_TYPE_G550:
+ return PAGE_ALIGN(mga_warp_g400_microcode_size);
+ case MGA_CARD_TYPE_G200:
+ return PAGE_ALIGN(mga_warp_g200_microcode_size);
+ default:
+ return 0;
+ }
}
static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
{
unsigned char *vcbase = dev_priv->warp->handle;
unsigned long pcbase = dev_priv->warp->offset;
- unsigned int size;
-
- size = mga_warp_g400_microcode_size( dev_priv );
- if ( size > dev_priv->warp->size ) {
- DRM_ERROR( "microcode too large! (%u > %lu)\n",
- size, dev_priv->warp->size );
- return DRM_ERR(ENOMEM);
- }
memset( dev_priv->warp_pipe_phys, 0,
sizeof(dev_priv->warp_pipe_phys) );
@@ -136,35 +123,36 @@ static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
{
unsigned char *vcbase = dev_priv->warp->handle;
unsigned long pcbase = dev_priv->warp->offset;
- unsigned int size;
-
- size = mga_warp_g200_microcode_size( dev_priv );
- if ( size > dev_priv->warp->size ) {
- DRM_ERROR( "microcode too large! (%u > %lu)\n",
- size, dev_priv->warp->size );
- return DRM_ERR(ENOMEM);
- }
- memset( dev_priv->warp_pipe_phys, 0,
- sizeof(dev_priv->warp_pipe_phys) );
+ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
- WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ );
- WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF );
- WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA );
- WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF );
- WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS );
- WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF );
- WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA );
- WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF );
+ WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+ WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+ WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+ WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+ WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+ WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+ WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+ WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
return 0;
}
int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
{
- switch ( dev_priv->chipset ) {
+ const unsigned int size = mga_warp_microcode_size(dev_priv);
+
+ DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+ if (size > dev_priv->warp->size) {
+ DRM_ERROR("microcode too large! (%u > %lu)\n",
+ size, dev_priv->warp->size);
+ return DRM_ERR(ENOMEM);
+ }
+
+ switch (dev_priv->chipset) {
case MGA_CARD_TYPE_G400:
- return mga_warp_install_g400_microcode( dev_priv );
+ case MGA_CARD_TYPE_G550:
+ return mga_warp_install_g400_microcode(dev_priv);
case MGA_CARD_TYPE_G200:
return mga_warp_install_g200_microcode( dev_priv );
default:
@@ -182,10 +170,11 @@ int mga_warp_init( drm_mga_private_t *dev_priv )
*/
switch ( dev_priv->chipset ) {
case MGA_CARD_TYPE_G400:
- MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND );
- MGA_WRITE( MGA_WGETMSB, 0x00000E00 );
- MGA_WRITE( MGA_WVRTXSZ, 0x00001807 );
- MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 );
+ case MGA_CARD_TYPE_G550:
+ MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
+ MGA_WRITE(MGA_WGETMSB, 0x00000E00);
+ MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
+ MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
break;
case MGA_CARD_TYPE_G200:
MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 08ed8d01d9d9..895152206b31 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -326,7 +326,8 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev,
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
else
#endif
- ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
+ ring_start = dev_priv->cce_ring->offset -
+ (unsigned long)dev->sg->virtual;
R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
@@ -487,6 +488,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
r128_do_cleanup_cce( dev );
return DRM_ERR(EINVAL);
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if(!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n");
@@ -537,7 +539,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
dev_priv->cce_buffers_offset = dev->agp->base;
else
#endif
- dev_priv->cce_buffers_offset = dev->sg->handle;
+ dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 0cba17d1e0ff..b616cd3ed2cd 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -215,7 +215,7 @@ typedef struct drm_r128_sarea {
#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
-#define DRM_IOCTL_R128_GETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
+#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP)
typedef struct drm_r128_init {
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
new file mode 100644
index 000000000000..623f1f460cb5
--- /dev/null
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -0,0 +1,801 @@
+/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002.
+ * Copyright (C) 2004 Nicolai Haehnle.
+ * All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors:
+ * Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+
+#define R300_SIMULTANEOUS_CLIPRECTS 4
+
+/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
+ */
+static const int r300_cliprect_cntl[4] = {
+ 0xAAAA,
+ 0xEEEE,
+ 0xFEFE,
+ 0xFFFE
+};
+
+
+/**
+ * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
+ * buffer, starting with index n.
+ */
+static int r300_emit_cliprects(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ int n)
+{
+ drm_clip_rect_t box;
+ int nr;
+ int i;
+ RING_LOCALS;
+
+ nr = cmdbuf->nbox - n;
+ if (nr > R300_SIMULTANEOUS_CLIPRECTS)
+ nr = R300_SIMULTANEOUS_CLIPRECTS;
+
+ DRM_DEBUG("%i cliprects\n", nr);
+
+ if (nr) {
+ BEGIN_RING(6 + nr*2);
+ OUT_RING( CP_PACKET0( R300_RE_CLIPRECT_TL_0, nr*2 - 1 ) );
+
+ for(i = 0; i < nr; ++i) {
+ if (DRM_COPY_FROM_USER_UNCHECKED(&box, &cmdbuf->boxes[n+i], sizeof(box))) {
+ DRM_ERROR("copy cliprect faulted\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+
+ OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
+ (box.y1 << R300_CLIPRECT_Y_SHIFT));
+ OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
+ (box.y2 << R300_CLIPRECT_Y_SHIFT));
+ }
+
+ OUT_RING_REG( R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr-1] );
+
+ /* TODO/SECURITY: Force scissors to a safe value, otherwise the
+ * client might be able to trample over memory.
+ * The impact should be very limited, but I'd rather be safe than
+ * sorry.
+ */
+ OUT_RING( CP_PACKET0( R300_RE_SCISSORS_TL, 1 ) );
+ OUT_RING( 0 );
+ OUT_RING( R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK );
+ ADVANCE_RING();
+ } else {
+ /* Why we allow zero cliprect rendering:
+ * There are some commands in a command buffer that must be submitted
+ * even when there are no cliprects, e.g. DMA buffer discard
+ * or state setting (though state setting could be avoided by
+ * simulating a loss of context).
+ *
+ * Now since the cmdbuf interface is so chaotic right now (and is
+ * bound to remain that way for a bit until things settle down),
+ * it is basically impossible to filter out the commands that are
+ * necessary and those that aren't.
+ *
+ * So I choose the safe way and don't do any filtering at all;
+ * instead, I simply set up the engine so that all rendering
+ * can't produce any fragments.
+ */
+ BEGIN_RING(2);
+ OUT_RING_REG( R300_RE_CLIPRECT_CNTL, 0 );
+ ADVANCE_RING();
+ }
+
+ return 0;
+}
+
+u8 r300_reg_flags[0x10000>>2];
+
+
+void r300_init_reg_flags(void)
+{
+ int i;
+ memset(r300_reg_flags, 0, 0x10000>>2);
+ #define ADD_RANGE_MARK(reg, count,mark) \
+ for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
+ r300_reg_flags[i]|=(mark);
+
+ #define MARK_SAFE 1
+ #define MARK_CHECK_OFFSET 2
+
+ #define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
+
+ /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
+ ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
+ ADD_RANGE(0x2080, 1);
+ ADD_RANGE(R300_SE_VTE_CNTL, 2);
+ ADD_RANGE(0x2134, 2);
+ ADD_RANGE(0x2140, 1);
+ ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
+ ADD_RANGE(0x21DC, 1);
+ ADD_RANGE(0x221C, 1);
+ ADD_RANGE(0x2220, 4);
+ ADD_RANGE(0x2288, 1);
+ ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
+ ADD_RANGE(R300_GB_ENABLE, 1);
+ ADD_RANGE(R300_GB_MSPOS0, 5);
+ ADD_RANGE(R300_TX_ENABLE, 1);
+ ADD_RANGE(0x4200, 4);
+ ADD_RANGE(0x4214, 1);
+ ADD_RANGE(R300_RE_POINTSIZE, 1);
+ ADD_RANGE(0x4230, 3);
+ ADD_RANGE(R300_RE_LINE_CNT, 1);
+ ADD_RANGE(0x4238, 1);
+ ADD_RANGE(0x4260, 3);
+ ADD_RANGE(0x4274, 4);
+ ADD_RANGE(0x4288, 5);
+ ADD_RANGE(0x42A0, 1);
+ ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
+ ADD_RANGE(0x42B4, 1);
+ ADD_RANGE(R300_RE_CULL_CNTL, 1);
+ ADD_RANGE(0x42C0, 2);
+ ADD_RANGE(R300_RS_CNTL_0, 2);
+ ADD_RANGE(R300_RS_INTERP_0, 8);
+ ADD_RANGE(R300_RS_ROUTE_0, 8);
+ ADD_RANGE(0x43A4, 2);
+ ADD_RANGE(0x43E8, 1);
+ ADD_RANGE(R300_PFS_CNTL_0, 3);
+ ADD_RANGE(R300_PFS_NODE_0, 4);
+ ADD_RANGE(R300_PFS_TEXI_0, 64);
+ ADD_RANGE(0x46A4, 5);
+ ADD_RANGE(R300_PFS_INSTR0_0, 64);
+ ADD_RANGE(R300_PFS_INSTR1_0, 64);
+ ADD_RANGE(R300_PFS_INSTR2_0, 64);
+ ADD_RANGE(R300_PFS_INSTR3_0, 64);
+ ADD_RANGE(0x4BC0, 1);
+ ADD_RANGE(0x4BC8, 3);
+ ADD_RANGE(R300_PP_ALPHA_TEST, 2);
+ ADD_RANGE(0x4BD8, 1);
+ ADD_RANGE(R300_PFS_PARAM_0_X, 64);
+ ADD_RANGE(0x4E00, 1);
+ ADD_RANGE(R300_RB3D_CBLEND, 2);
+ ADD_RANGE(R300_RB3D_COLORMASK, 1);
+ ADD_RANGE(0x4E10, 3);
+ ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
+ ADD_RANGE(0x4E50, 9);
+ ADD_RANGE(0x4E88, 1);
+ ADD_RANGE(0x4EA0, 2);
+ ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
+ ADD_RANGE(0x4F10, 4);
+ ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
+ ADD_RANGE(0x4F28, 1);
+ ADD_RANGE(0x4F30, 2);
+ ADD_RANGE(0x4F44, 1);
+ ADD_RANGE(0x4F54, 1);
+
+ ADD_RANGE(R300_TX_FILTER_0, 16);
+ ADD_RANGE(R300_TX_UNK1_0, 16);
+ ADD_RANGE(R300_TX_SIZE_0, 16);
+ ADD_RANGE(R300_TX_FORMAT_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_BORDER_COLOR_0, 16);
+
+ /* Sporadic registers used as primitives are emitted */
+ ADD_RANGE(0x4f18, 1);
+ ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
+ ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
+ ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
+
+}
+
+static __inline__ int r300_check_range(unsigned reg, int count)
+{
+ int i;
+ if(reg & ~0xffff)return -1;
+ for(i=(reg>>2);i<(reg>>2)+count;i++)
+ if(r300_reg_flags[i]!=MARK_SAFE)return 1;
+ return 0;
+}
+
+ /* 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)
+{
+ /* we realy want to check against end of video aperture
+ 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))return 0;
+ if((offset>=dev_priv->gart_vm_start) &&
+ (offset<dev_priv->gart_vm_start+dev_priv->gart_size))return 0;
+ return 1;
+}
+
+static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int reg;
+ int sz;
+ int i;
+ int values[64];
+ RING_LOCALS;
+
+ sz = header.packet0.count;
+ reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+ if((sz>64)||(sz<0)){
+ DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", reg, sz);
+ return DRM_ERR(EINVAL);
+ }
+ for(i=0;i<sz;i++){
+ values[i]=((int __user*)cmdbuf->buf)[i];
+ switch(r300_reg_flags[(reg>>2)+i]){
+ case MARK_SAFE:
+ break;
+ case MARK_CHECK_OFFSET:
+ if(r300_check_offset(dev_priv, (u32)values[i])){
+ DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", reg, sz);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("Register %04x failed check as flag=%02x\n", reg+i*4, r300_reg_flags[(reg>>2)+i]);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ BEGIN_RING(1+sz);
+ OUT_RING( CP_PACKET0( reg, sz-1 ) );
+ OUT_RING_TABLE( values, sz );
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz*4;
+ cmdbuf->bufsz -= sz*4;
+
+ return 0;
+}
+
+/**
+ * Emits a packet0 setting arbitrary registers.
+ * Called by r300_do_cp_cmdbuf.
+ *
+ * Note that checks are performed on contents and addresses of the registers
+ */
+static __inline__ int r300_emit_packet0(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int reg;
+ int sz;
+ RING_LOCALS;
+
+ sz = header.packet0.count;
+ reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+ if (!sz)
+ return 0;
+
+ if (sz*4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ if (reg+sz*4 >= 0x10000){
+ DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz);
+ return DRM_ERR(EINVAL);
+ }
+
+ if(r300_check_range(reg, sz)){
+ /* go and check everything */
+ return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, header);
+ }
+ /* the rest of the data is safe to emit, whatever the values the user passed */
+
+ BEGIN_RING(1+sz);
+ OUT_RING( CP_PACKET0( reg, sz-1 ) );
+ OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz );
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz*4;
+ cmdbuf->bufsz -= sz*4;
+
+ return 0;
+}
+
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_vpu(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int sz;
+ int addr;
+ RING_LOCALS;
+
+ sz = header.vpu.count;
+ addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
+
+ if (!sz)
+ return 0;
+ if (sz*16 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_RING(5+sz*4);
+ /* Wait for VAP to come to senses.. */
+ /* there is no need to emit it multiple times, (only once before VAP is programmed,
+ but this optimization is for later */
+ OUT_RING_REG( R300_VAP_PVS_WAITIDLE, 0 );
+ OUT_RING_REG( R300_VAP_PVS_UPLOAD_ADDRESS, addr );
+ OUT_RING( CP_PACKET0_TABLE( R300_VAP_PVS_UPLOAD_DATA, sz*4 - 1 ) );
+ OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz*4 );
+
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz*16;
+ cmdbuf->bufsz -= sz*16;
+
+ return 0;
+}
+
+
+/**
+ * Emit a clear packet from userspace.
+ * Called by r300_emit_packet3.
+ */
+static __inline__ int r300_emit_clear(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf)
+{
+ RING_LOCALS;
+
+ if (8*4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_RING(10);
+ OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 8 ) );
+ OUT_RING( R300_PRIM_TYPE_POINT|R300_PRIM_WALK_RING|
+ (1<<R300_PRIM_NUM_VERTICES_SHIFT) );
+ OUT_RING_TABLE( (int __user*)cmdbuf->buf, 8 );
+ ADVANCE_RING();
+
+ cmdbuf->buf += 8*4;
+ cmdbuf->bufsz -= 8*4;
+
+ return 0;
+}
+
+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ u32 header)
+{
+ int count, i,k;
+ #define MAX_ARRAY_PACKET 64
+ u32 payload[MAX_ARRAY_PACKET];
+ u32 narrays;
+ RING_LOCALS;
+
+ count=(header>>16) & 0x3fff;
+
+ if((count+1)>MAX_ARRAY_PACKET){
+ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", count);
+ return DRM_ERR(EINVAL);
+ }
+ memset(payload, 0, MAX_ARRAY_PACKET*4);
+ memcpy(payload, cmdbuf->buf+4, (count+1)*4);
+
+ /* carefully check packet contents */
+
+ narrays=payload[0];
+ k=0;
+ i=1;
+ while((k<narrays) && (i<(count+1))){
+ i++; /* skip attribute field */
+ if(r300_check_offset(dev_priv, payload[i])){
+ DRM_ERROR("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ if(k==narrays)break;
+ /* have one more to process, they come in pairs */
+ if(r300_check_offset(dev_priv, payload[i])){
+ DRM_ERROR("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ }
+ /* do the counts match what we expect ? */
+ if((k!=narrays) || (i!=(count+1))){
+ DRM_ERROR("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", k, i, narrays, count+1);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* all clear, output packet */
+
+ BEGIN_RING(count+2);
+ OUT_RING(header);
+ OUT_RING_TABLE(payload, count+1);
+ ADVANCE_RING();
+
+ cmdbuf->buf += (count+2)*4;
+ cmdbuf->bufsz -= (count+2)*4;
+
+ return 0;
+}
+
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf)
+{
+ u32 header;
+ int count;
+ RING_LOCALS;
+
+ if (4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ /* Fixme !! This simply emits a packet without much checking.
+ We need to be smarter. */
+
+ /* obtain first word - actual packet3 header */
+ header = *(u32 __user*)cmdbuf->buf;
+
+ /* Is it packet 3 ? */
+ if( (header>>30)!=0x3 ) {
+ DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+ }
+
+ count=(header>>16) & 0x3fff;
+
+ /* Check again now that we know how much data to expect */
+ if ((count+2)*4 > cmdbuf->bufsz){
+ DRM_ERROR("Expected packet3 of length %d but have only %d bytes left\n",
+ (count+2)*4, cmdbuf->bufsz);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* Is it a packet type we know about ? */
+ switch(header & 0xff00){
+ case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
+ return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+
+ case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
+ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
+ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
+ case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
+ case RADEON_WAIT_FOR_IDLE:
+ case RADEON_CP_NOP:
+ /* these packets are safe */
+ break;
+ default:
+ DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+ }
+
+
+ BEGIN_RING(count+2);
+ OUT_RING(header);
+ OUT_RING_TABLE( (int __user*)(cmdbuf->buf+4), count+1);
+ ADVANCE_RING();
+
+ cmdbuf->buf += (count+2)*4;
+ cmdbuf->bufsz -= (count+2)*4;
+
+ return 0;
+}
+
+
+/**
+ * Emit a rendering packet3 from userspace.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_packet3(drm_radeon_private_t* dev_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int n;
+ int ret;
+ char __user* orig_buf = cmdbuf->buf;
+ int orig_bufsz = cmdbuf->bufsz;
+
+ /* This is a do-while-loop so that we run the interior at least once,
+ * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
+ */
+ n = 0;
+ do {
+ if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
+ ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
+ if (ret)
+ return ret;
+
+ cmdbuf->buf = orig_buf;
+ cmdbuf->bufsz = orig_bufsz;
+ }
+
+ switch(header.packet3.packet) {
+ case R300_CMD_PACKET3_CLEAR:
+ DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
+ ret = r300_emit_clear(dev_priv, cmdbuf);
+ if (ret) {
+ DRM_ERROR("r300_emit_clear failed\n");
+ return ret;
+ }
+ break;
+
+ case R300_CMD_PACKET3_RAW:
+ DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
+ ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
+ if (ret) {
+ DRM_ERROR("r300_emit_raw_packet3 failed\n");
+ return ret;
+ }
+ break;
+
+ default:
+ DRM_ERROR("bad packet3 type %i at %p\n",
+ header.packet3.packet,
+ cmdbuf->buf - sizeof(header));
+ return DRM_ERR(EINVAL);
+ }
+
+ n += R300_SIMULTANEOUS_CLIPRECTS;
+ } while(n < cmdbuf->nbox);
+
+ return 0;
+}
+
+/* Some of the R300 chips seem to be extremely touchy about the two registers
+ * that are configured in r300_pacify.
+ * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
+ * sends a command buffer that contains only state setting commands and a
+ * vertex program/parameter upload sequence, this will eventually lead to a
+ * lockup, unless the sequence is bracketed by calls to r300_pacify.
+ * So we should take great care to *always* call r300_pacify before
+ * *anything* 3D related, and again afterwards. This is what the
+ * call bracket in r300_do_cp_cmdbuf is for.
+ */
+
+/**
+ * Emit the sequence to pacify R300.
+ */
+static __inline__ void r300_pacify(drm_radeon_private_t* dev_priv)
+{
+ RING_LOCALS;
+
+ BEGIN_RING(6);
+ OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) );
+ OUT_RING( 0xa );
+ OUT_RING( CP_PACKET0( 0x4f18, 0 ) );
+ OUT_RING( 0x3 );
+ OUT_RING( CP_PACKET3( RADEON_CP_NOP, 0 ) );
+ OUT_RING( 0x0 );
+ ADVANCE_RING();
+}
+
+
+/**
+ * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
+ * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
+ * be careful about how this function is called.
+ */
+static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+
+ buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+ buf->pending = 1;
+ buf->used = 0;
+}
+
+
+/**
+ * Parses and validates a user-supplied command buffer and emits appropriate
+ * commands on the DMA ring buffer.
+ * Called by the ioctl handler function radeon_cp_cmdbuf.
+ */
+int r300_do_cp_cmdbuf(drm_device_t* dev,
+ DRMFILE filp,
+ drm_file_t* filp_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf = NULL;
+ int emit_dispatch_age = 0;
+ int ret = 0;
+
+ DRM_DEBUG("\n");
+
+ /* See the comment above r300_emit_begin3d for why this call must be here,
+ * and what the cleanup gotos are for. */
+ r300_pacify(dev_priv);
+
+ if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
+ ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
+ if (ret)
+ goto cleanup;
+ }
+
+ while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+ int idx;
+ drm_r300_cmd_header_t header;
+
+ header.u = *(unsigned int *)cmdbuf->buf;
+
+ cmdbuf->buf += sizeof(header);
+ cmdbuf->bufsz -= sizeof(header);
+
+ switch(header.header.cmd_type) {
+ case R300_CMD_PACKET0:
+ DRM_DEBUG("R300_CMD_PACKET0\n");
+ ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_packet0 failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_VPU:
+ DRM_DEBUG("R300_CMD_VPU\n");
+ ret = r300_emit_vpu(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_vpu failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_PACKET3:
+ DRM_DEBUG("R300_CMD_PACKET3\n");
+ ret = r300_emit_packet3(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_packet3 failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_END3D:
+ DRM_DEBUG("R300_CMD_END3D\n");
+ /* TODO:
+ Ideally userspace driver should not need to issue this call,
+ i.e. the drm driver should issue it automatically and prevent
+ lockups.
+
+ In practice, we do not understand why this call is needed and what
+ it does (except for some vague guesses that it has to do with cache
+ coherence) and so the user space driver does it.
+
+ Once we are sure which uses prevent lockups the code could be moved
+ into the kernel and the userspace driver will not
+ need to use this command.
+
+ Note that issuing this command does not hurt anything
+ except, possibly, performance */
+ r300_pacify(dev_priv);
+ break;
+
+ case R300_CMD_CP_DELAY:
+ /* simple enough, we can do it here */
+ DRM_DEBUG("R300_CMD_CP_DELAY\n");
+ {
+ int i;
+ RING_LOCALS;
+
+ BEGIN_RING(header.delay.count);
+ for(i=0;i<header.delay.count;i++)
+ OUT_RING(RADEON_CP_PACKET2);
+ ADVANCE_RING();
+ }
+ break;
+
+ case R300_CMD_DMA_DISCARD:
+ DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+ idx = header.dma.buf_idx;
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ idx, dma->buf_count - 1);
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+
+ buf = dma->buflist[idx];
+ if (buf->filp != filp || buf->pending) {
+ DRM_ERROR("bad buffer %p %p %d\n",
+ buf->filp, filp, buf->pending);
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+
+ emit_dispatch_age = 1;
+ r300_discard_buffer(dev, buf);
+ break;
+
+ case R300_CMD_WAIT:
+ /* simple enough, we can do it here */
+ DRM_DEBUG("R300_CMD_WAIT\n");
+ if(header.wait.flags==0)break; /* nothing to do */
+
+ {
+ RING_LOCALS;
+
+ BEGIN_RING(2);
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );
+ OUT_RING( (header.wait.flags & 0xf)<<14 );
+ ADVANCE_RING();
+ }
+ break;
+
+ default:
+ DRM_ERROR("bad cmd_type %i at %p\n",
+ header.header.cmd_type,
+ cmdbuf->buf - sizeof(header));
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+ }
+
+ DRM_DEBUG("END\n");
+
+cleanup:
+ r300_pacify(dev_priv);
+
+ /* We emit the vertex buffer age here, outside the pacifier "brackets"
+ * for two reasons:
+ * (1) This may coalesce multiple age emissions into a single one and
+ * (2) more importantly, some chips lock up hard when scratch registers
+ * are written inside the pacifier bracket.
+ */
+ if (emit_dispatch_age) {
+ RING_LOCALS;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING(2);
+ RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
+ ADVANCE_RING();
+ }
+
+ COMMIT_RING();
+
+ return ret;
+}
+
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
new file mode 100644
index 000000000000..c3e7ca3dbe3d
--- /dev/null
+++ b/drivers/char/drm/r300_reg.h
@@ -0,0 +1,1412 @@
+/**************************************************************************
+
+Copyright (C) 2004-2005 Nicolai Haehnle et al.
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 (including the next
+paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 _R300_REG_H
+#define _R300_REG_H
+
+#define R300_MC_INIT_MISC_LAT_TIMER 0x180
+# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28
+
+
+#define R300_MC_INIT_GFX_LAT_TIMER 0x154
+# define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28
+
+/*
+This file contains registers and constants for the R300. They have been
+found mostly by examining command buffers captured using glxtest, as well
+as by extrapolating some known registers and constants from the R200.
+
+I am fairly certain that they are correct unless stated otherwise in comments.
+*/
+
+#define R300_SE_VPORT_XSCALE 0x1D98
+#define R300_SE_VPORT_XOFFSET 0x1D9C
+#define R300_SE_VPORT_YSCALE 0x1DA0
+#define R300_SE_VPORT_YOFFSET 0x1DA4
+#define R300_SE_VPORT_ZSCALE 0x1DA8
+#define R300_SE_VPORT_ZOFFSET 0x1DAC
+
+
+/* This register is written directly and also starts data section in many 3d CP_PACKET3's */
+#define R300_VAP_VF_CNTL 0x2084
+
+# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0
+# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0)
+# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0)
+# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0)
+
+# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4
+ /* State based - direct writes to registers trigger vertex generation */
+# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4)
+
+ /* I don't think I saw these three used.. */
+# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6
+# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9
+# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10
+
+ /* index size - when not set the indices are assumed to be 16 bit */
+# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
+ /* number of vertices */
+# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
+
+/* BEGIN: Wild guesses */
+#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090
+# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
+
+#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+/* END */
+
+#define R300_SE_VTE_CNTL 0x20b0
+# define R300_VPORT_X_SCALE_ENA 0x00000001
+# define R300_VPORT_X_OFFSET_ENA 0x00000002
+# define R300_VPORT_Y_SCALE_ENA 0x00000004
+# define R300_VPORT_Y_OFFSET_ENA 0x00000008
+# define R300_VPORT_Z_SCALE_ENA 0x00000010
+# define R300_VPORT_Z_OFFSET_ENA 0x00000020
+# define R300_VTX_XY_FMT 0x00000100
+# define R300_VTX_Z_FMT 0x00000200
+# define R300_VTX_W0_FMT 0x00000400
+# define R300_VTX_W0_NORMALIZE 0x00000800
+# define R300_VTX_ST_DENORMALIZED 0x00001000
+
+/* BEGIN: Vertex data assembly - lots of uncertainties */
+/* gap */
+/* Where do we get our vertex data?
+//
+// Vertex data either comes either from immediate mode registers or from
+// vertex arrays.
+// There appears to be no mixed mode (though we can force the pitch of
+// vertex arrays to 0, effectively reusing the same element over and over
+// again).
+//
+// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+// if these registers influence vertex array processing.
+//
+// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+//
+// In both cases, vertex attributes are then passed through INPUT_ROUTE.
+
+// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+// into the vertex processor's input registers.
+// The first word routes the first input, the second word the second, etc.
+// The corresponding input is routed into the register with the given index.
+// The list is ended by a word with INPUT_ROUTE_END set.
+//
+// Always set COMPONENTS_4 in immediate mode. */
+
+#define R300_VAP_INPUT_ROUTE_0_0 0x2150
+# define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
+# define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8
+# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
+# define R300_VAP_INPUT_ROUTE_END (1 << 13)
+# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
+#define R300_VAP_INPUT_ROUTE_0_1 0x2154
+#define R300_VAP_INPUT_ROUTE_0_2 0x2158
+#define R300_VAP_INPUT_ROUTE_0_3 0x215C
+#define R300_VAP_INPUT_ROUTE_0_4 0x2160
+#define R300_VAP_INPUT_ROUTE_0_5 0x2164
+#define R300_VAP_INPUT_ROUTE_0_6 0x2168
+#define R300_VAP_INPUT_ROUTE_0_7 0x216C
+
+/* gap */
+/* Notes:
+// - always set up to produce at least two attributes:
+// if vertex program uses only position, fglrx will set normal, too
+// - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */
+#define R300_VAP_INPUT_CNTL_0 0x2180
+# define R300_INPUT_CNTL_0_COLOR 0x00000001
+#define R300_VAP_INPUT_CNTL_1 0x2184
+# define R300_INPUT_CNTL_POS 0x00000001
+# define R300_INPUT_CNTL_NORMAL 0x00000002
+# define R300_INPUT_CNTL_COLOR 0x00000004
+# define R300_INPUT_CNTL_TC0 0x00000400
+# define R300_INPUT_CNTL_TC1 0x00000800
+# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
+# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
+# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
+# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
+# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
+# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
+
+/* gap */
+/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
+// are set to a swizzling bit pattern, other words are 0.
+//
+// In immediate mode, the pattern is always set to xyzw. In vertex array
+// mode, the swizzling pattern is e.g. used to set zw components in texture
+// coordinates with only tweo components. */
+#define R300_VAP_INPUT_ROUTE_1_0 0x21E0
+# define R300_INPUT_ROUTE_SELECT_X 0
+# define R300_INPUT_ROUTE_SELECT_Y 1
+# define R300_INPUT_ROUTE_SELECT_Z 2
+# define R300_INPUT_ROUTE_SELECT_W 3
+# define R300_INPUT_ROUTE_SELECT_ZERO 4
+# define R300_INPUT_ROUTE_SELECT_ONE 5
+# define R300_INPUT_ROUTE_SELECT_MASK 7
+# define R300_INPUT_ROUTE_X_SHIFT 0
+# define R300_INPUT_ROUTE_Y_SHIFT 3
+# define R300_INPUT_ROUTE_Z_SHIFT 6
+# define R300_INPUT_ROUTE_W_SHIFT 9
+# define R300_INPUT_ROUTE_ENABLE (15 << 12)
+#define R300_VAP_INPUT_ROUTE_1_1 0x21E4
+#define R300_VAP_INPUT_ROUTE_1_2 0x21E8
+#define R300_VAP_INPUT_ROUTE_1_3 0x21EC
+#define R300_VAP_INPUT_ROUTE_1_4 0x21F0
+#define R300_VAP_INPUT_ROUTE_1_5 0x21F4
+#define R300_VAP_INPUT_ROUTE_1_6 0x21F8
+#define R300_VAP_INPUT_ROUTE_1_7 0x21FC
+
+/* END */
+
+/* gap */
+/* BEGIN: Upload vertex program and data
+// The programmable vertex shader unit has a memory bank of unknown size
+// that can be written to in 16 byte units by writing the address into
+// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+//
+// Pointers into the memory bank are always in multiples of 16 bytes.
+//
+// The memory bank is divided into areas with fixed meaning.
+//
+// Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+// whereas the difference between known addresses suggests size 512.
+//
+// Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+// Native reported limits and the VPI layout suggest size 256, whereas
+// difference between known addresses suggests size 512.
+//
+// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+// floating point pointsize. The exact purpose of this state is uncertain,
+// as there is also the R300_RE_POINTSIZE register.
+//
+// Multiple vertex programs and parameter sets can be loaded at once,
+// which could explain the size discrepancy. */
+#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200
+# define R300_PVS_UPLOAD_PROGRAM 0x00000000
+# define R300_PVS_UPLOAD_PARAMETERS 0x00000200
+# define R300_PVS_UPLOAD_POINTSIZE 0x00000406
+/* gap */
+#define R300_VAP_PVS_UPLOAD_DATA 0x2208
+/* END */
+
+/* gap */
+/* I do not know the purpose of this register. However, I do know that
+// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+// for normal rendering. */
+#define R300_VAP_UNKNOWN_221C 0x221C
+# define R300_221C_NORMAL 0x00000000
+# define R300_221C_CLEAR 0x0001C000
+
+/* gap */
+/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
+// rendering commands and overwriting vertex program parameters.
+// Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+// avoids bugs caused by still running shaders reading bad data from memory. */
+#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
+
+/* Absolutely no clue what this register is about. */
+#define R300_VAP_UNKNOWN_2288 0x2288
+# define R300_2288_R300 0x00750000 /* -- nh */
+# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+
+/* gap */
+/* Addresses are relative to the vertex program instruction area of the
+// memory bank. PROGRAM_END points to the last instruction of the active
+// program
+//
+// The meaning of the two UNKNOWN fields is obviously not known. However,
+// experiments so far have shown that both *must* point to an instruction
+// inside the vertex program, otherwise the GPU locks up.
+// fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
+// Most likely this is used to ignore rest of the program in cases where group of verts arent visible.
+// For some reason this "section" is sometimes accepted other instruction that have
+// no relationship with position calculations.
+*/
+#define R300_VAP_PVS_CNTL_1 0x22D0
+# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
+# define R300_PVS_CNTL_1_POS_END_SHIFT 10
+# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20
+/* Addresses are relative the the vertex program parameters area. */
+#define R300_VAP_PVS_CNTL_2 0x22D4
+# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
+# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16
+#define R300_VAP_PVS_CNTL_3 0x22D8
+# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10
+# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
+
+/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
+// immediate vertices */
+#define R300_VAP_VTX_COLOR_R 0x2464
+#define R300_VAP_VTX_COLOR_G 0x2468
+#define R300_VAP_VTX_COLOR_B 0x246C
+#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_Y_1 0x2494
+#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
+#define R300_VAP_VTX_POS_0_Y_2 0x24A4
+#define R300_VAP_VTX_POS_0_Z_2 0x24A8
+#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */
+
+/* gap */
+
+/* These are values from r300_reg/r300_reg.h - they are known to be correct
+ and are here so we can use one register file instead of several
+ - Vladimir */
+#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000
+# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16)
+
+#define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004
+ /* each of the following is 3 bits wide, specifies number
+ of components */
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+
+/* UNK30 seems to enables point to quad transformation on textures
+ (or something closely related to that).
+ This bit is rather fatal at the time being due to lackings at pixel shader side */
+#define R300_GB_ENABLE 0x4008
+# define R300_GB_POINT_STUFF_ENABLE (1<<0)
+# define R300_GB_LINE_STUFF_ENABLE (1<<1)
+# define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2)
+# define R300_GB_STENCIL_AUTO_ENABLE (1<<4)
+# define R300_GB_UNK30 (1<<30)
+ /* each of the following is 2 bits wide */
+#define R300_GB_TEX_REPLICATE 0
+#define R300_GB_TEX_ST 1
+#define R300_GB_TEX_STR 2
+# define R300_GB_TEX0_SOURCE_SHIFT 16
+# define R300_GB_TEX1_SOURCE_SHIFT 18
+# define R300_GB_TEX2_SOURCE_SHIFT 20
+# define R300_GB_TEX3_SOURCE_SHIFT 22
+# define R300_GB_TEX4_SOURCE_SHIFT 24
+# define R300_GB_TEX5_SOURCE_SHIFT 26
+# define R300_GB_TEX6_SOURCE_SHIFT 28
+# define R300_GB_TEX7_SOURCE_SHIFT 30
+
+/* MSPOS - positions for multisample antialiasing (?) */
+#define R300_GB_MSPOS0 0x4010
+ /* shifts - each of the fields is 4 bits */
+# define R300_GB_MSPOS0__MS_X0_SHIFT 0
+# define R300_GB_MSPOS0__MS_Y0_SHIFT 4
+# define R300_GB_MSPOS0__MS_X1_SHIFT 8
+# define R300_GB_MSPOS0__MS_Y1_SHIFT 12
+# define R300_GB_MSPOS0__MS_X2_SHIFT 16
+# define R300_GB_MSPOS0__MS_Y2_SHIFT 20
+# define R300_GB_MSPOS0__MSBD0_Y 24
+# define R300_GB_MSPOS0__MSBD0_X 28
+
+#define R300_GB_MSPOS1 0x4014
+# define R300_GB_MSPOS1__MS_X3_SHIFT 0
+# define R300_GB_MSPOS1__MS_Y3_SHIFT 4
+# define R300_GB_MSPOS1__MS_X4_SHIFT 8
+# define R300_GB_MSPOS1__MS_Y4_SHIFT 12
+# define R300_GB_MSPOS1__MS_X5_SHIFT 16
+# define R300_GB_MSPOS1__MS_Y5_SHIFT 20
+# define R300_GB_MSPOS1__MSBD1 24
+
+
+#define R300_GB_TILE_CONFIG 0x4018
+# define R300_GB_TILE_ENABLE (1<<0)
+# define R300_GB_TILE_PIPE_COUNT_RV300 0
+# define R300_GB_TILE_PIPE_COUNT_R300 (3<<1)
+# define R300_GB_TILE_PIPE_COUNT_R420 (7<<1)
+# define R300_GB_TILE_SIZE_8 0
+# define R300_GB_TILE_SIZE_16 (1<<4)
+# define R300_GB_TILE_SIZE_32 (2<<4)
+# define R300_GB_SUPER_SIZE_1 (0<<6)
+# define R300_GB_SUPER_SIZE_2 (1<<6)
+# define R300_GB_SUPER_SIZE_4 (2<<6)
+# define R300_GB_SUPER_SIZE_8 (3<<6)
+# define R300_GB_SUPER_SIZE_16 (4<<6)
+# define R300_GB_SUPER_SIZE_32 (5<<6)
+# define R300_GB_SUPER_SIZE_64 (6<<6)
+# define R300_GB_SUPER_SIZE_128 (7<<6)
+# define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */
+# define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */
+# define R300_GB_SUPER_TILE_A 0
+# define R300_GB_SUPER_TILE_B (1<<15)
+# define R300_GB_SUBPIXEL_1_12 0
+# define R300_GB_SUBPIXEL_1_16 (1<<16)
+
+#define R300_GB_FIFO_SIZE 0x4024
+ /* each of the following is 2 bits wide */
+#define R300_GB_FIFO_SIZE_32 0
+#define R300_GB_FIFO_SIZE_64 1
+#define R300_GB_FIFO_SIZE_128 2
+#define R300_GB_FIFO_SIZE_256 3
+# define R300_SC_IFIFO_SIZE_SHIFT 0
+# define R300_SC_TZFIFO_SIZE_SHIFT 2
+# define R300_SC_BFIFO_SIZE_SHIFT 4
+
+# define R300_US_OFIFO_SIZE_SHIFT 12
+# define R300_US_WFIFO_SIZE_SHIFT 14
+ /* the following use the same constants as above, but meaning is
+ is times 2 (i.e. instead of 32 words it means 64 */
+# define R300_RS_TFIFO_SIZE_SHIFT 6
+# define R300_RS_CFIFO_SIZE_SHIFT 8
+# define R300_US_RAM_SIZE_SHIFT 10
+ /* watermarks, 3 bits wide */
+# define R300_RS_HIGHWATER_COL_SHIFT 16
+# define R300_RS_HIGHWATER_TEX_SHIFT 19
+# define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */
+# define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24
+
+#define R300_GB_SELECT 0x401C
+# define R300_GB_FOG_SELECT_C0A 0
+# define R300_GB_FOG_SELECT_C1A 1
+# define R300_GB_FOG_SELECT_C2A 2
+# define R300_GB_FOG_SELECT_C3A 3
+# define R300_GB_FOG_SELECT_1_1_W 4
+# define R300_GB_FOG_SELECT_Z 5
+# define R300_GB_DEPTH_SELECT_Z 0
+# define R300_GB_DEPTH_SELECT_1_1_W (1<<3)
+# define R300_GB_W_SELECT_1_W 0
+# define R300_GB_W_SELECT_1 (1<<4)
+
+#define R300_GB_AA_CONFIG 0x4020
+# define R300_AA_ENABLE 0x01
+# define R300_AA_SUBSAMPLES_2 0
+# define R300_AA_SUBSAMPLES_3 (1<<1)
+# define R300_AA_SUBSAMPLES_4 (2<<1)
+# define R300_AA_SUBSAMPLES_6 (3<<1)
+
+/* END */
+
+/* gap */
+/* The upper enable bits are guessed, based on fglrx reported limits. */
+#define R300_TX_ENABLE 0x4104
+# define R300_TX_ENABLE_0 (1 << 0)
+# define R300_TX_ENABLE_1 (1 << 1)
+# define R300_TX_ENABLE_2 (1 << 2)
+# define R300_TX_ENABLE_3 (1 << 3)
+# define R300_TX_ENABLE_4 (1 << 4)
+# define R300_TX_ENABLE_5 (1 << 5)
+# define R300_TX_ENABLE_6 (1 << 6)
+# define R300_TX_ENABLE_7 (1 << 7)
+# define R300_TX_ENABLE_8 (1 << 8)
+# define R300_TX_ENABLE_9 (1 << 9)
+# define R300_TX_ENABLE_10 (1 << 10)
+# define R300_TX_ENABLE_11 (1 << 11)
+# define R300_TX_ENABLE_12 (1 << 12)
+# define R300_TX_ENABLE_13 (1 << 13)
+# define R300_TX_ENABLE_14 (1 << 14)
+# define R300_TX_ENABLE_15 (1 << 15)
+
+/* The pointsize is given in multiples of 6. The pointsize can be
+// enormous: Clear() renders a single point that fills the entire
+// framebuffer. */
+#define R300_RE_POINTSIZE 0x421C
+# define R300_POINTSIZE_Y_SHIFT 0
+# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
+# define R300_POINTSIZE_X_SHIFT 16
+# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
+# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6)
+
+/* The line width is given in multiples of 6.
+ In default mode lines are classified as vertical lines.
+ HO: horizontal
+ VE: vertical or horizontal
+ HO & VE: no classification
+*/
+#define R300_RE_LINE_CNT 0x4234
+# define R300_LINESIZE_SHIFT 0
+# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
+# define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6)
+# define R300_LINE_CNT_HO (1 << 16)
+# define R300_LINE_CNT_VE (1 << 17)
+
+/* Some sort of scale or clamp value for texcoordless textures. */
+#define R300_RE_UNK4238 0x4238
+
+#define R300_RE_SHADE_MODEL 0x4278
+# define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa
+# define R300_RE_SHADE_MODEL_FLAT 0x39595
+
+/* Dangerous */
+#define R300_RE_POLYGON_MODE 0x4288
+# define R300_PM_ENABLED (1 << 0)
+# define R300_PM_FRONT_POINT (0 << 0)
+# define R300_PM_BACK_POINT (0 << 0)
+# define R300_PM_FRONT_LINE (1 << 4)
+# define R300_PM_FRONT_FILL (1 << 5)
+# define R300_PM_BACK_LINE (1 << 7)
+# define R300_PM_BACK_FILL (1 << 8)
+
+/* Not sure why there are duplicate of factor and constant values.
+ My best guess so far is that there are seperate zbiases for test and write.
+ Ordering might be wrong.
+ Some of the tests indicate that fgl has a fallback implementation of zbias
+ via pixel shaders. */
+#define R300_RE_ZBIAS_T_FACTOR 0x42A4
+#define R300_RE_ZBIAS_T_CONSTANT 0x42A8
+#define R300_RE_ZBIAS_W_FACTOR 0x42AC
+#define R300_RE_ZBIAS_W_CONSTANT 0x42B0
+
+/* This register needs to be set to (1<<1) for RV350 to correctly
+ perform depth test (see --vb-triangles in r300_demo)
+ Don't know about other chips. - Vladimir
+ This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT).
+ One to enable depth test and one for depth write.
+ Yet this doesnt explain why depth writes work ...
+ */
+#define R300_RE_OCCLUSION_CNTL 0x42B4
+# define R300_OCCLUSION_ON (1<<1)
+
+#define R300_RE_CULL_CNTL 0x42B8
+# define R300_CULL_FRONT (1 << 0)
+# define R300_CULL_BACK (1 << 1)
+# define R300_FRONT_FACE_CCW (0 << 2)
+# define R300_FRONT_FACE_CW (1 << 2)
+
+
+/* BEGIN: Rasterization / Interpolators - many guesses
+// 0_UNKNOWN_18 has always been set except for clear operations.
+// TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+// on the vertex program, *not* the fragment program) */
+#define R300_RS_CNTL_0 0x4300
+# define R300_RS_CNTL_TC_CNT_SHIFT 2
+# define R300_RS_CNTL_TC_CNT_MASK (7 << 2)
+# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */
+# define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18)
+/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+#define R300_RS_CNTL_1 0x4304
+
+/* gap */
+/* Only used for texture coordinates.
+// Use the source field to route texture coordinate input from the vertex program
+// to the desired interpolator. Note that the source field is relative to the
+// outputs the vertex program *actually* writes. If a vertex program only writes
+// texcoord[1], this will be source index 0.
+// Set INTERP_USED on all interpolators that produce data used by the
+// fragment program. INTERP_USED looks like a swizzling mask, but
+// I haven't seen it used that way.
+//
+// Note: The _UNKNOWN constants are always set in their respective register.
+// I don't know if this is necessary. */
+#define R300_RS_INTERP_0 0x4310
+#define R300_RS_INTERP_1 0x4314
+# define R300_RS_INTERP_1_UNKNOWN 0x40
+#define R300_RS_INTERP_2 0x4318
+# define R300_RS_INTERP_2_UNKNOWN 0x80
+#define R300_RS_INTERP_3 0x431C
+# define R300_RS_INTERP_3_UNKNOWN 0xC0
+#define R300_RS_INTERP_4 0x4320
+#define R300_RS_INTERP_5 0x4324
+#define R300_RS_INTERP_6 0x4328
+#define R300_RS_INTERP_7 0x432C
+# define R300_RS_INTERP_SRC_SHIFT 2
+# define R300_RS_INTERP_SRC_MASK (7 << 2)
+# define R300_RS_INTERP_USED 0x00D10000
+
+/* These DWORDs control how vertex data is routed into fragment program
+// registers, after interpolators. */
+#define R300_RS_ROUTE_0 0x4330
+#define R300_RS_ROUTE_1 0x4334
+#define R300_RS_ROUTE_2 0x4338
+#define R300_RS_ROUTE_3 0x433C /* GUESS */
+#define R300_RS_ROUTE_4 0x4340 /* GUESS */
+#define R300_RS_ROUTE_5 0x4344 /* GUESS */
+#define R300_RS_ROUTE_6 0x4348 /* GUESS */
+#define R300_RS_ROUTE_7 0x434C /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_0 0
+# define R300_RS_ROUTE_SOURCE_INTERP_1 1
+# define R300_RS_ROUTE_SOURCE_INTERP_2 2
+# define R300_RS_ROUTE_SOURCE_INTERP_3 3
+# define R300_RS_ROUTE_SOURCE_INTERP_4 4
+# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
+# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
+# define R300_RS_ROUTE_DEST_SHIFT 6
+# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
+
+/* Special handling for color: When the fragment program uses color,
+// the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+// color register index. */
+# define R300_RS_ROUTE_0_COLOR (1 << 14)
+# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17
+# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
+/* As above, but for secondary color */
+# define R300_RS_ROUTE_1_COLOR1 (1 << 14)
+# define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
+# define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17)
+# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11)
+/* END */
+
+/* BEGIN: Scissors and cliprects
+// There are four clipping rectangles. Their corner coordinates are inclusive.
+// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+// on whether the pixel is inside cliprects 0-3, respectively. For example,
+// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+// the number 3 (binary 0011).
+// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+// the pixel is rasterized.
+//
+// In addition to this, there is a scissors rectangle. Only pixels inside the
+// scissors rectangle are drawn. (coordinates are inclusive)
+//
+// For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+// for the purpose of clipping and scissors. */
+#define R300_RE_CLIPRECT_TL_0 0x43B0
+#define R300_RE_CLIPRECT_BR_0 0x43B4
+#define R300_RE_CLIPRECT_TL_1 0x43B8
+#define R300_RE_CLIPRECT_BR_1 0x43BC
+#define R300_RE_CLIPRECT_TL_2 0x43C0
+#define R300_RE_CLIPRECT_BR_2 0x43C4
+#define R300_RE_CLIPRECT_TL_3 0x43C8
+#define R300_RE_CLIPRECT_BR_3 0x43CC
+# define R300_CLIPRECT_OFFSET 1440
+# define R300_CLIPRECT_MASK 0x1FFF
+# define R300_CLIPRECT_X_SHIFT 0
+# define R300_CLIPRECT_X_MASK (0x1FFF << 0)
+# define R300_CLIPRECT_Y_SHIFT 13
+# define R300_CLIPRECT_Y_MASK (0x1FFF << 13)
+#define R300_RE_CLIPRECT_CNTL 0x43D0
+# define R300_CLIP_OUT (1 << 0)
+# define R300_CLIP_0 (1 << 1)
+# define R300_CLIP_1 (1 << 2)
+# define R300_CLIP_10 (1 << 3)
+# define R300_CLIP_2 (1 << 4)
+# define R300_CLIP_20 (1 << 5)
+# define R300_CLIP_21 (1 << 6)
+# define R300_CLIP_210 (1 << 7)
+# define R300_CLIP_3 (1 << 8)
+# define R300_CLIP_30 (1 << 9)
+# define R300_CLIP_31 (1 << 10)
+# define R300_CLIP_310 (1 << 11)
+# define R300_CLIP_32 (1 << 12)
+# define R300_CLIP_320 (1 << 13)
+# define R300_CLIP_321 (1 << 14)
+# define R300_CLIP_3210 (1 << 15)
+
+/* gap */
+#define R300_RE_SCISSORS_TL 0x43E0
+#define R300_RE_SCISSORS_BR 0x43E4
+# define R300_SCISSORS_OFFSET 1440
+# define R300_SCISSORS_X_SHIFT 0
+# define R300_SCISSORS_X_MASK (0x1FFF << 0)
+# define R300_SCISSORS_Y_SHIFT 13
+# define R300_SCISSORS_Y_MASK (0x1FFF << 13)
+/* END */
+
+/* BEGIN: Texture specification
+// The texture specification dwords are grouped by meaning and not by texture unit.
+// This means that e.g. the offset for texture image unit N is found in register
+// TX_OFFSET_0 + (4*N) */
+#define R300_TX_FILTER_0 0x4400
+# define R300_TX_REPEAT 0
+# define R300_TX_MIRRORED 1
+# define R300_TX_CLAMP 4
+# define R300_TX_CLAMP_TO_EDGE 2
+# define R300_TX_CLAMP_TO_BORDER 6
+# define R300_TX_WRAP_S_SHIFT 0
+# define R300_TX_WRAP_S_MASK (7 << 0)
+# define R300_TX_WRAP_T_SHIFT 3
+# define R300_TX_WRAP_T_MASK (7 << 3)
+# define R300_TX_WRAP_Q_SHIFT 6
+# define R300_TX_WRAP_Q_MASK (7 << 6)
+# define R300_TX_MAG_FILTER_NEAREST (1 << 9)
+# define R300_TX_MAG_FILTER_LINEAR (2 << 9)
+# define R300_TX_MAG_FILTER_MASK (3 << 9)
+# define R300_TX_MIN_FILTER_NEAREST (1 << 11)
+# define R300_TX_MIN_FILTER_LINEAR (2 << 11)
+# define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11)
+# define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11)
+# define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11)
+# define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11)
+
+/* NOTE: NEAREST doesnt seem to exist.
+ Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ anisotropy modes because that would void selected mag filter */
+# define R300_TX_MIN_FILTER_ANISO_NEAREST ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_LINEAR ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) )
+# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21)
+# define R300_TX_MAX_ANISO_2_TO_1 (2 << 21)
+# define R300_TX_MAX_ANISO_4_TO_1 (4 << 21)
+# define R300_TX_MAX_ANISO_8_TO_1 (6 << 21)
+# 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_LOD_BIAS_MASK 0x1fff
+
+#define R300_TX_SIZE_0 0x4480
+# define R300_TX_WIDTHMASK_SHIFT 0
+# define R300_TX_WIDTHMASK_MASK (2047 << 0)
+# define R300_TX_HEIGHTMASK_SHIFT 11
+# define R300_TX_HEIGHTMASK_MASK (2047 << 11)
+# define R300_TX_UNK23 (1 << 23)
+# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */
+# define R300_TX_SIZE_MASK (15 << 26)
+#define R300_TX_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.
+ They are given meanings as R, G, B and Alpha by the swizzle
+ specification */
+# define R300_TX_FORMAT_X8 0x0
+# define R300_TX_FORMAT_X16 0x1
+# define R300_TX_FORMAT_Y4X4 0x2
+# define R300_TX_FORMAT_Y8X8 0x3
+# define R300_TX_FORMAT_Y16X16 0x4
+# define R300_TX_FORMAT_Z3Y3X2 0x5
+# define R300_TX_FORMAT_Z5Y6X5 0x6
+# define R300_TX_FORMAT_Z6Y5X5 0x7
+# define R300_TX_FORMAT_Z11Y11X10 0x8
+# define R300_TX_FORMAT_Z10Y11X11 0x9
+# define R300_TX_FORMAT_W4Z4Y4X4 0xA
+# define R300_TX_FORMAT_W1Z5Y5X5 0xB
+# define R300_TX_FORMAT_W8Z8Y8X8 0xC
+# define R300_TX_FORMAT_W2Z10Y10X10 0xD
+# define R300_TX_FORMAT_W16Z16Y16X16 0xE
+# define R300_TX_FORMAT_DXT1 0xF
+# define R300_TX_FORMAT_DXT3 0x10
+# define R300_TX_FORMAT_DXT5 0x11
+# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
+# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
+# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
+# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
+ /* 0x16 - some 16 bit green format.. ?? */
+# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */
+
+ /* gap */
+ /* Floating point formats */
+ /* Note - hardware supports both 16 and 32 bit floating point */
+# define R300_TX_FORMAT_FL_I16 0x18
+# define R300_TX_FORMAT_FL_I16A16 0x19
+# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A
+# define R300_TX_FORMAT_FL_I32 0x1B
+# define R300_TX_FORMAT_FL_I32A32 0x1C
+# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D
+ /* alpha modes, convenience mostly */
+ /* if you have alpha, pick constant appropriate to the
+ number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
+# define R300_TX_FORMAT_ALPHA_1CH 0x000
+# define R300_TX_FORMAT_ALPHA_2CH 0x200
+# define R300_TX_FORMAT_ALPHA_4CH 0x600
+# define R300_TX_FORMAT_ALPHA_NONE 0xA00
+ /* Swizzling */
+ /* constants */
+# define R300_TX_FORMAT_X 0
+# define R300_TX_FORMAT_Y 1
+# define R300_TX_FORMAT_Z 2
+# define R300_TX_FORMAT_W 3
+# define R300_TX_FORMAT_ZERO 4
+# define R300_TX_FORMAT_ONE 5
+# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */
+
+# define R300_TX_FORMAT_B_SHIFT 18
+# define R300_TX_FORMAT_G_SHIFT 15
+# define R300_TX_FORMAT_R_SHIFT 12
+# define R300_TX_FORMAT_A_SHIFT 9
+ /* Convenience macro to take care of layout and swizzling */
+# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) (\
+ ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
+ | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
+ | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
+ | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
+ | (R300_TX_FORMAT_##FMT) \
+ )
+ /* These can be ORed with result of R300_EASY_TX_FORMAT() */
+ /* We don't really know what they do. Take values from a constant color ? */
+# define R300_TX_FORMAT_CONST_X (1<<5)
+# define R300_TX_FORMAT_CONST_Y (2<<5)
+# define R300_TX_FORMAT_CONST_Z (4<<5)
+# define R300_TX_FORMAT_CONST_W (8<<5)
+
+# define R300_TX_FORMAT_YUV_MODE 0x00800000
+
+#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_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 }
+
+/* END */
+
+/* BEGIN: Fragment program instruction set
+// Fragment programs are written directly into register space.
+// There are separate instruction streams for texture instructions and ALU
+// instructions.
+// In order to synchronize these streams, the program is divided into up
+// to 4 nodes. Each node begins with a number of TEX operations, followed
+// by a number of ALU operations.
+// The first node can have zero TEX ops, all subsequent nodes must have at least
+// one TEX ops.
+// All nodes must have at least one ALU op.
+//
+// The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+// 1 node, a value of 3 means 4 nodes.
+// The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+// offsets into the respective instruction streams, while *_END points to the
+// last instruction relative to this offset. */
+#define R300_PFS_CNTL_0 0x4600
+# define R300_PFS_CNTL_LAST_NODES_SHIFT 0
+# define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0)
+# define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3)
+#define R300_PFS_CNTL_1 0x4604
+/* There is an unshifted value here which has so far always been equal to the
+// index of the highest used temporary register. */
+#define R300_PFS_CNTL_2 0x4608
+# define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0
+# define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0)
+# define R300_PFS_CNTL_ALU_END_SHIFT 6
+# define R300_PFS_CNTL_ALU_END_MASK (63 << 0)
+# define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12
+# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
+# define R300_PFS_CNTL_TEX_END_SHIFT 18
+# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
+
+/* gap */
+/* Nodes are stored backwards. The last active node is always stored in
+// PFS_NODE_3.
+// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+// first node is stored in NODE_2, the second node is stored in NODE_3.
+//
+// Offsets are relative to the master offset from PFS_CNTL_2.
+// LAST_NODE is set for the last node, and only for the last node. */
+#define R300_PFS_NODE_0 0x4610
+#define R300_PFS_NODE_1 0x4614
+#define R300_PFS_NODE_2 0x4618
+#define R300_PFS_NODE_3 0x461C
+# define R300_PFS_NODE_ALU_OFFSET_SHIFT 0
+# define R300_PFS_NODE_ALU_OFFSET_MASK (63 << 0)
+# define R300_PFS_NODE_ALU_END_SHIFT 6
+# define R300_PFS_NODE_ALU_END_MASK (63 << 6)
+# define R300_PFS_NODE_TEX_OFFSET_SHIFT 12
+# 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)
+
+/* TEX
+// As far as I can tell, texture instructions cannot write into output
+// registers directly. A subsequent ALU instruction is always necessary,
+// even if it's just MAD o0, r0, 1, 0 */
+#define R300_PFS_TEXI_0 0x4620
+# define R300_FPITX_SRC_SHIFT 0
+# define R300_FPITX_SRC_MASK (31 << 0)
+# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */
+# define R300_FPITX_DST_SHIFT 6
+# define R300_FPITX_DST_MASK (31 << 6)
+# define R300_FPITX_IMAGE_SHIFT 11
+# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */
+/* Unsure if these are opcodes, or some kind of bitfield, but this is how
+ * they were set when I checked
+ */
+# define R300_FPITX_OPCODE_SHIFT 15
+# define R300_FPITX_OP_TEX 1
+# define R300_FPITX_OP_TXP 3
+# define R300_FPITX_OP_TXB 4
+
+/* ALU
+// The ALU instructions register blocks are enumerated according to the order
+// in which fglrx. I assume there is space for 64 instructions, since
+// each block has space for a maximum of 64 DWORDs, and this matches reported
+// native limits.
+//
+// The basic functional block seems to be one MAD for each color and alpha,
+// and an adder that adds all components after the MUL.
+// - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+// - DP4: Use OUTC_DP4, OUTA_DP4
+// - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+// - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+// - CMP: If ARG2 < 0, return ARG1, else return ARG0
+// - FLR: use FRC+MAD
+// - XPD: use MAD+MAD
+// - SGE, SLT: use MAD+CMP
+// - RSQ: use ABS modifier for argument
+// - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP)
+// into color register
+// - apparently, there's no quick DST operation
+// - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+// - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+// - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+//
+// Operand selection
+// First stage selects three sources from the available registers and
+// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+// fglrx sorts the three source fields: Registers before constants,
+// lower indices before higher indices; I do not know whether this is necessary.
+// fglrx fills unused sources with "read constant 0"
+// According to specs, you cannot select more than two different constants.
+//
+// Second stage selects the operands from the sources. This is defined in
+// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+// zero and one.
+// Swizzling and negation happens in this stage, as well.
+//
+// Important: Color and alpha seem to be mostly separate, i.e. their sources
+// selection appears to be fully independent (the register storage is probably
+// physically split into a color and an alpha section).
+// However (because of the apparent physical split), there is some interaction
+// WRT swizzling. If, for example, you want to load an R component into an
+// Alpha operand, this R component is taken from a *color* source, not from
+// an alpha source. The corresponding register doesn't even have to appear in
+// the alpha sources list. (I hope this alll makes sense to you)
+//
+// Destination selection
+// The destination register index is in FPI1 (color) and FPI3 (alpha) together
+// with enable bits.
+// There are separate enable bits for writing into temporary registers
+// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT).
+// You can write to both at once, or not write at all (the same index
+// must be used for both).
+//
+// Note: There is a special form for LRP
+// - Argument order is the same as in ARB_fragment_program.
+// - Operation is MAD
+// - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+// - Set FPI0/FPI2_SPECIAL_LRP
+// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */
+#define R300_PFS_INSTR1_0 0x46C0
+# define R300_FPI1_SRC0C_SHIFT 0
+# define R300_FPI1_SRC0C_MASK (31 << 0)
+# define R300_FPI1_SRC0C_CONST (1 << 5)
+# define R300_FPI1_SRC1C_SHIFT 6
+# define R300_FPI1_SRC1C_MASK (31 << 6)
+# define R300_FPI1_SRC1C_CONST (1 << 11)
+# define R300_FPI1_SRC2C_SHIFT 12
+# define R300_FPI1_SRC2C_MASK (31 << 12)
+# 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_X (1 << 23)
+# define R300_FPI1_DSTC_REG_Y (1 << 24)
+# define R300_FPI1_DSTC_REG_Z (1 << 25)
+# define R300_FPI1_DSTC_OUTPUT_X (1 << 26)
+# define R300_FPI1_DSTC_OUTPUT_Y (1 << 27)
+# define R300_FPI1_DSTC_OUTPUT_Z (1 << 28)
+
+#define R300_PFS_INSTR3_0 0x47C0
+# define R300_FPI3_SRC0A_SHIFT 0
+# define R300_FPI3_SRC0A_MASK (31 << 0)
+# define R300_FPI3_SRC0A_CONST (1 << 5)
+# define R300_FPI3_SRC1A_SHIFT 6
+# define R300_FPI3_SRC1A_MASK (31 << 6)
+# define R300_FPI3_SRC1A_CONST (1 << 11)
+# define R300_FPI3_SRC2A_SHIFT 12
+# define R300_FPI3_SRC2A_MASK (31 << 12)
+# define R300_FPI3_SRC2A_CONST (1 << 17)
+# define R300_FPI3_DSTA_SHIFT 18
+# define R300_FPI3_DSTA_MASK (31 << 18)
+# define R300_FPI3_DSTA_REG (1 << 23)
+# define R300_FPI3_DSTA_OUTPUT (1 << 24)
+
+#define R300_PFS_INSTR0_0 0x48C0
+# define R300_FPI0_ARGC_SRC0C_XYZ 0
+# define R300_FPI0_ARGC_SRC0C_XXX 1
+# define R300_FPI0_ARGC_SRC0C_YYY 2
+# define R300_FPI0_ARGC_SRC0C_ZZZ 3
+# define R300_FPI0_ARGC_SRC1C_XYZ 4
+# define R300_FPI0_ARGC_SRC1C_XXX 5
+# define R300_FPI0_ARGC_SRC1C_YYY 6
+# define R300_FPI0_ARGC_SRC1C_ZZZ 7
+# define R300_FPI0_ARGC_SRC2C_XYZ 8
+# define R300_FPI0_ARGC_SRC2C_XXX 9
+# define R300_FPI0_ARGC_SRC2C_YYY 10
+# define R300_FPI0_ARGC_SRC2C_ZZZ 11
+# define R300_FPI0_ARGC_SRC0A 12
+# define R300_FPI0_ARGC_SRC1A 13
+# define R300_FPI0_ARGC_SRC2A 14
+# define R300_FPI0_ARGC_SRC1C_LRP 15
+# define R300_FPI0_ARGC_ZERO 20
+# define R300_FPI0_ARGC_ONE 21
+# define R300_FPI0_ARGC_HALF 22 /* GUESS */
+# define R300_FPI0_ARGC_SRC0C_YZX 23
+# define R300_FPI0_ARGC_SRC1C_YZX 24
+# define R300_FPI0_ARGC_SRC2C_YZX 25
+# define R300_FPI0_ARGC_SRC0C_ZXY 26
+# define R300_FPI0_ARGC_SRC1C_ZXY 27
+# define R300_FPI0_ARGC_SRC2C_ZXY 28
+# define R300_FPI0_ARGC_SRC0CA_WZY 29
+# define R300_FPI0_ARGC_SRC1CA_WZY 30
+# define R300_FPI0_ARGC_SRC2CA_WZY 31
+
+# define R300_FPI0_ARG0C_SHIFT 0
+# define R300_FPI0_ARG0C_MASK (31 << 0)
+# define R300_FPI0_ARG0C_NEG (1 << 5)
+# define R300_FPI0_ARG0C_ABS (1 << 6)
+# define R300_FPI0_ARG1C_SHIFT 7
+# define R300_FPI0_ARG1C_MASK (31 << 7)
+# define R300_FPI0_ARG1C_NEG (1 << 12)
+# define R300_FPI0_ARG1C_ABS (1 << 13)
+# define R300_FPI0_ARG2C_SHIFT 14
+# define R300_FPI0_ARG2C_MASK (31 << 14)
+# define R300_FPI0_ARG2C_NEG (1 << 19)
+# define R300_FPI0_ARG2C_ABS (1 << 20)
+# define R300_FPI0_SPECIAL_LRP (1 << 21)
+# define R300_FPI0_OUTC_MAD (0 << 23)
+# define R300_FPI0_OUTC_DP3 (1 << 23)
+# define R300_FPI0_OUTC_DP4 (2 << 23)
+# define R300_FPI0_OUTC_MIN (4 << 23)
+# define R300_FPI0_OUTC_MAX (5 << 23)
+# define R300_FPI0_OUTC_CMP (8 << 23)
+# 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_PFS_INSTR2_0 0x49C0
+# define R300_FPI2_ARGA_SRC0C_X 0
+# define R300_FPI2_ARGA_SRC0C_Y 1
+# define R300_FPI2_ARGA_SRC0C_Z 2
+# define R300_FPI2_ARGA_SRC1C_X 3
+# define R300_FPI2_ARGA_SRC1C_Y 4
+# define R300_FPI2_ARGA_SRC1C_Z 5
+# define R300_FPI2_ARGA_SRC2C_X 6
+# define R300_FPI2_ARGA_SRC2C_Y 7
+# define R300_FPI2_ARGA_SRC2C_Z 8
+# define R300_FPI2_ARGA_SRC0A 9
+# define R300_FPI2_ARGA_SRC1A 10
+# define R300_FPI2_ARGA_SRC2A 11
+# define R300_FPI2_ARGA_SRC1A_LRP 15
+# define R300_FPI2_ARGA_ZERO 16
+# define R300_FPI2_ARGA_ONE 17
+# define R300_FPI2_ARGA_HALF 18 /* GUESS */
+
+# define R300_FPI2_ARG0A_SHIFT 0
+# define R300_FPI2_ARG0A_MASK (31 << 0)
+# define R300_FPI2_ARG0A_NEG (1 << 5)
+# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */
+# define R300_FPI2_ARG1A_SHIFT 7
+# define R300_FPI2_ARG1A_MASK (31 << 7)
+# define R300_FPI2_ARG1A_NEG (1 << 12)
+# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */
+# define R300_FPI2_ARG2A_SHIFT 14
+# define R300_FPI2_ARG2A_MASK (31 << 14)
+# define R300_FPI2_ARG2A_NEG (1 << 19)
+# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */
+# define R300_FPI2_SPECIAL_LRP (1 << 21)
+# define R300_FPI2_OUTA_MAD (0 << 23)
+# define R300_FPI2_OUTA_DP4 (1 << 23)
+# define R300_FPI2_OUTA_MIN (2 << 23)
+# define R300_FPI2_OUTA_MAX (3 << 23)
+# define R300_FPI2_OUTA_CMP (6 << 23)
+# define R300_FPI2_OUTA_FRC (7 << 23)
+# define R300_FPI2_OUTA_EX2 (8 << 23)
+# define R300_FPI2_OUTA_LG2 (9 << 23)
+# define R300_FPI2_OUTA_RCP (10 << 23)
+# define R300_FPI2_OUTA_RSQ (11 << 23)
+# define R300_FPI2_OUTA_SAT (1 << 30)
+# define R300_FPI2_UNKNOWN_31 (1 << 31)
+/* END */
+
+/* gap */
+#define R300_PP_ALPHA_TEST 0x4BD4
+# define R300_REF_ALPHA_MASK 0x000000ff
+# define R300_ALPHA_TEST_FAIL (0 << 8)
+# define R300_ALPHA_TEST_LESS (1 << 8)
+# define R300_ALPHA_TEST_LEQUAL (3 << 8)
+# define R300_ALPHA_TEST_EQUAL (2 << 8)
+# define R300_ALPHA_TEST_GEQUAL (6 << 8)
+# define R300_ALPHA_TEST_GREATER (4 << 8)
+# define R300_ALPHA_TEST_NEQUAL (5 << 8)
+# define R300_ALPHA_TEST_PASS (7 << 8)
+# define R300_ALPHA_TEST_OP_MASK (7 << 8)
+# define R300_ALPHA_TEST_ENABLE (1 << 11)
+
+/* gap */
+/* Fragment program parameters in 7.16 floating point */
+#define R300_PFS_PARAM_0_X 0x4C00
+#define R300_PFS_PARAM_0_Y 0x4C04
+#define R300_PFS_PARAM_0_Z 0x4C08
+#define R300_PFS_PARAM_0_W 0x4C0C
+/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */
+#define R300_PFS_PARAM_31_X 0x4DF0
+#define R300_PFS_PARAM_31_Y 0x4DF4
+#define R300_PFS_PARAM_31_Z 0x4DF8
+#define R300_PFS_PARAM_31_W 0x4DFC
+
+/* Notes:
+// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application
+// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same
+// function (both registers are always set up completely in any case)
+// - Most blend flags are simply copied from R200 and not tested yet */
+#define R300_RB3D_CBLEND 0x4E04
+#define R300_RB3D_ABLEND 0x4E08
+ /* the following only appear in CBLEND */
+# define R300_BLEND_ENABLE (1 << 0)
+# define R300_BLEND_UNKNOWN (3 << 1)
+# define R300_BLEND_NO_SEPARATE (1 << 3)
+ /* the following are shared between CBLEND and ABLEND */
+# define R300_FCN_MASK (3 << 12)
+# define R300_COMB_FCN_ADD_CLAMP (0 << 12)
+# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12)
+# define R300_COMB_FCN_SUB_CLAMP (2 << 12)
+# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12)
+# define R300_SRC_BLEND_GL_ZERO (32 << 16)
+# define R300_SRC_BLEND_GL_ONE (33 << 16)
+# define R300_SRC_BLEND_GL_SRC_COLOR (34 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
+# define R300_SRC_BLEND_GL_DST_COLOR (36 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
+# define R300_SRC_BLEND_GL_SRC_ALPHA (38 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
+# define R300_SRC_BLEND_GL_DST_ALPHA (40 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
+# define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16)
+# define R300_SRC_BLEND_MASK (63 << 16)
+# define R300_DST_BLEND_GL_ZERO (32 << 24)
+# define R300_DST_BLEND_GL_ONE (33 << 24)
+# define R300_DST_BLEND_GL_SRC_COLOR (34 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
+# define R300_DST_BLEND_GL_DST_COLOR (36 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
+# define R300_DST_BLEND_GL_SRC_ALPHA (38 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
+# define R300_DST_BLEND_GL_DST_ALPHA (40 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
+# define R300_DST_BLEND_MASK (63 << 24)
+#define R300_RB3D_COLORMASK 0x4E0C
+# define R300_COLORMASK0_B (1<<0)
+# define R300_COLORMASK0_G (1<<1)
+# define R300_COLORMASK0_R (1<<2)
+# define R300_COLORMASK0_A (1<<3)
+
+/* gap */
+#define R300_RB3D_COLOROFFSET0 0x4E28
+# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
+#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
+#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
+#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
+/* gap */
+/* Bit 16: Larger tiles
+// Bit 17: 4x2 tiles
+// Bit 18: Extremely weird tile like, but some pixels duplicated? */
+#define R300_RB3D_COLORPITCH0 0x4E38
+# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+# define R300_COLOR_FORMAT_RGB565 (2 << 22)
+# define R300_COLOR_FORMAT_ARGB8888 (3 << 22)
+#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
+#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
+#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
+
+/* gap */
+/* Guess by Vladimir.
+// Set to 0A before 3D operations, set to 02 afterwards. */
+#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C
+# define R300_RB3D_DSTCACHE_02 0x00000002
+# define R300_RB3D_DSTCACHE_0A 0x0000000A
+
+/* gap */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */
+/* Bit (1<<8) is the "test" bit. so plain write is 6 - vd */
+#define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00
+# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */
+# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */
+# define R300_RB3D_Z_TEST 0x00000012
+# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
+# define R300_RB3D_Z_WRITE_ONLY 0x00000006
+
+# define R300_RB3D_Z_TEST 0x00000012
+# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
+# define R300_RB3D_Z_WRITE_ONLY 0x00000006
+# define R300_RB3D_STENCIL_ENABLE 0x00000001
+
+#define R300_RB3D_ZSTENCIL_CNTL_1 0x4F04
+ /* functions */
+# define R300_ZS_NEVER 0
+# define R300_ZS_LESS 1
+# define R300_ZS_LEQUAL 2
+# define R300_ZS_EQUAL 3
+# define R300_ZS_GEQUAL 4
+# define R300_ZS_GREATER 5
+# define R300_ZS_NOTEQUAL 6
+# define R300_ZS_ALWAYS 7
+# define R300_ZS_MASK 7
+ /* operations */
+# define R300_ZS_KEEP 0
+# define R300_ZS_ZERO 1
+# define R300_ZS_REPLACE 2
+# define R300_ZS_INCR 3
+# define R300_ZS_DECR 4
+# define R300_ZS_INVERT 5
+# define R300_ZS_INCR_WRAP 6
+# define R300_ZS_DECR_WRAP 7
+
+ /* front and back refer to operations done for front
+ and back faces, i.e. separate stencil function support */
+# define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT 0
+# define R300_RB3D_ZS1_FRONT_FUNC_SHIFT 3
+# define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT 6
+# define R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT 9
+# define R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT 12
+# define R300_RB3D_ZS1_BACK_FUNC_SHIFT 15
+# define R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT 18
+# define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT 21
+# define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT 24
+
+
+
+#define R300_RB3D_ZSTENCIL_CNTL_2 0x4F08
+# define R300_RB3D_ZS2_STENCIL_REF_SHIFT 0
+# define R300_RB3D_ZS2_STENCIL_MASK 0xFF
+# define R300_RB3D_ZS2_STENCIL_MASK_SHIFT 8
+# define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT 16
+
+/* gap */
+
+#define R300_RB3D_ZSTENCIL_FORMAT 0x4F10
+# define R300_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+# define R300_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+
+/* gap */
+#define R300_RB3D_DEPTHOFFSET 0x4F20
+#define R300_RB3D_DEPTHPITCH 0x4F24
+# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+
+/* BEGIN: Vertex program instruction set
+// Every instruction is four dwords long:
+// DWORD 0: output and opcode
+// DWORD 1: first argument
+// DWORD 2: second argument
+// DWORD 3: third argument
+//
+// Notes:
+// - ABS r, a is implemented as MAX r, a, -a
+// - MOV is implemented as ADD to zero
+// - XPD is implemented as MUL + MAD
+// - FLR is implemented as FRC + ADD
+// - apparently, fglrx tries to schedule instructions so that there is at least
+// one instruction between the write to a temporary and the first read
+// from said temporary; however, violations of this scheduling are allowed
+// - register indices seem to be unrelated with OpenGL aliasing to conventional state
+// - only one attribute and one parameter can be loaded at a time; however, the
+// same attribute/parameter can be used for more than one argument
+// - the second software argument for POW is the third hardware argument (no idea why)
+// - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+//
+// There is some magic surrounding LIT:
+// The single argument is replicated across all three inputs, but swizzled:
+// First argument: xyzy
+// Second argument: xyzx
+// Third argument: xyzw
+// Whenever the result is used later in the fragment program, fglrx forces x and w
+// to be 1.0 in the input selection; I don't know whether this is strictly necessary */
+#define R300_VPI_OUT_OP_DOT (1 << 0)
+#define R300_VPI_OUT_OP_MUL (2 << 0)
+#define R300_VPI_OUT_OP_ADD (3 << 0)
+#define R300_VPI_OUT_OP_MAD (4 << 0)
+#define R300_VPI_OUT_OP_DST (5 << 0)
+#define R300_VPI_OUT_OP_FRC (6 << 0)
+#define R300_VPI_OUT_OP_MAX (7 << 0)
+#define R300_VPI_OUT_OP_MIN (8 << 0)
+#define R300_VPI_OUT_OP_SGE (9 << 0)
+#define R300_VPI_OUT_OP_SLT (10 << 0)
+#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_EXP (65 << 0)
+#define R300_VPI_OUT_OP_LOG (66 << 0)
+#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_LIT (68 << 0)
+#define R300_VPI_OUT_OP_POW (69 << 0)
+#define R300_VPI_OUT_OP_RCP (70 << 0)
+#define R300_VPI_OUT_OP_RSQ (72 << 0)
+#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_EX2 (75 << 0)
+#define R300_VPI_OUT_OP_LG2 (76 << 0)
+#define R300_VPI_OUT_OP_MAD_2 (128 << 0)
+#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */
+
+#define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8)
+#define R300_VPI_OUT_REG_CLASS_MASK (31 << 8)
+
+#define R300_VPI_OUT_REG_INDEX_SHIFT 13
+#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */
+
+#define R300_VPI_OUT_WRITE_X (1 << 20)
+#define R300_VPI_OUT_WRITE_Y (1 << 21)
+#define R300_VPI_OUT_WRITE_Z (1 << 22)
+#define R300_VPI_OUT_WRITE_W (1 << 23)
+
+#define R300_VPI_IN_REG_CLASS_TEMPORARY (0 << 0)
+#define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0)
+#define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0)
+#define R300_VPI_IN_REG_CLASS_NONE (9 << 0)
+#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */
+
+#define R300_VPI_IN_REG_INDEX_SHIFT 5
+#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */
+
+/* The R300 can select components from the input register arbitrarily.
+// Use the following constants, shifted by the component shift you
+// want to select */
+#define R300_VPI_IN_SELECT_X 0
+#define R300_VPI_IN_SELECT_Y 1
+#define R300_VPI_IN_SELECT_Z 2
+#define R300_VPI_IN_SELECT_W 3
+#define R300_VPI_IN_SELECT_ZERO 4
+#define R300_VPI_IN_SELECT_ONE 5
+#define R300_VPI_IN_SELECT_MASK 7
+
+#define R300_VPI_IN_X_SHIFT 13
+#define R300_VPI_IN_Y_SHIFT 16
+#define R300_VPI_IN_Z_SHIFT 19
+#define R300_VPI_IN_W_SHIFT 22
+
+#define R300_VPI_IN_NEG_X (1 << 25)
+#define R300_VPI_IN_NEG_Y (1 << 26)
+#define R300_VPI_IN_NEG_Z (1 << 27)
+#define R300_VPI_IN_NEG_W (1 << 28)
+/* END */
+
+//BEGIN: Packet 3 commands
+
+// A primitive emission dword.
+#define R300_PRIM_TYPE_NONE (0 << 0)
+#define R300_PRIM_TYPE_POINT (1 << 0)
+#define R300_PRIM_TYPE_LINE (2 << 0)
+#define R300_PRIM_TYPE_LINE_STRIP (3 << 0)
+#define R300_PRIM_TYPE_TRI_LIST (4 << 0)
+#define R300_PRIM_TYPE_TRI_FAN (5 << 0)
+#define R300_PRIM_TYPE_TRI_STRIP (6 << 0)
+#define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0)
+#define R300_PRIM_TYPE_RECT_LIST (8 << 0)
+#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200)
+#define R300_PRIM_TYPE_LINE_LOOP (12 << 0)
+#define R300_PRIM_TYPE_QUADS (13 << 0)
+#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0)
+#define R300_PRIM_TYPE_POLYGON (15 << 0)
+#define R300_PRIM_TYPE_MASK 0xF
+#define R300_PRIM_WALK_IND (1 << 4)
+#define R300_PRIM_WALK_LIST (2 << 4)
+#define R300_PRIM_WALK_RING (3 << 4)
+#define R300_PRIM_WALK_MASK (3 << 4)
+#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200)
+#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS
+#define R300_PRIM_NUM_VERTICES_SHIFT 16
+
+// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+// Two parameter dwords:
+// 0. The first parameter appears to be always 0
+// 1. The second parameter is a standard primitive emission dword.
+#define R300_PACKET3_3D_DRAW_VBUF 0x00002800
+
+// Specify the full set of vertex arrays as (address, stride).
+// The first parameter is the number of vertex arrays specified.
+// The rest of the command is a variable length list of blocks, where
+// each block is three dwords long and specifies two arrays.
+// The first dword of a block is split into two words, the lower significant
+// word refers to the first array, the more significant word to the second
+// array in the block.
+// The low byte of each word contains the size of an array entry in dwords,
+// the high byte contains the stride of the array.
+// The second dword of a block contains the pointer to the first array,
+// the third dword of a block contains the pointer to the second array.
+// Note that if the total number of arrays is odd, the third dword of
+// the last block is omitted.
+#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00
+
+#define R300_PACKET3_INDX_BUFFER 0x00003300
+# define R300_EB_UNK1_SHIFT 24
+# define R300_EB_UNK1 (0x80<<24)
+# define R300_EB_UNK2 0x0810
+#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600
+
+//END
+
+#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 20bcf872b348..6d9080a3ca7e 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -32,6 +32,7 @@
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
+#include "r300_reg.h"
#define RADEON_FIFO_DEBUG 0
@@ -1151,6 +1152,8 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
#if __OS_HAS_AGP
if ( !dev_priv->is_pci ) {
+ /* 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
@@ -1407,6 +1410,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if(!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n");
@@ -1625,6 +1629,9 @@ int radeon_cp_init( DRM_IOCTL_ARGS )
DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t __user *)data, sizeof(init) );
+ if(init.func == RADEON_INIT_R300_CP)
+ r300_init_reg_flags();
+
switch ( init.func ) {
case RADEON_INIT_CP:
case RADEON_INIT_R200_CP:
@@ -2039,15 +2046,43 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
case CHIP_RV200:
case CHIP_R200:
case CHIP_R300:
+ case CHIP_R420:
dev_priv->flags |= CHIP_HAS_HIERZ;
break;
default:
/* all other chips have no hierarchical z buffer */
break;
}
+
+ if (drm_device_is_agp(dev))
+ dev_priv->flags |= CHIP_IS_AGP;
+
+ DRM_DEBUG("%s card detected\n",
+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
return ret;
}
+int radeon_presetup(struct drm_device *dev)
+{
+ int ret;
+ drm_local_map_t *map;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+ drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+ _DRM_READ_ONLY, &dev_priv->mmio);
+ if (ret != 0)
+ return ret;
+
+ ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
+ drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
+ _DRM_WRITE_COMBINING, &map);
+ if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
int radeon_driver_postcleanup(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index c1e62d047989..3792798270a4 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -195,6 +195,52 @@ typedef union {
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
+/* Allowed parameters for R300_CMD_PACKET3
+ */
+#define R300_CMD_PACKET3_CLEAR 0
+#define R300_CMD_PACKET3_RAW 1
+
+/* Commands understood by cmd_buffer ioctl for R300.
+ * The interface has not been stabilized, so some of these may be removed
+ * and eventually reordered before stabilization.
+ */
+#define R300_CMD_PACKET0 1
+#define R300_CMD_VPU 2 /* emit vertex program upload */
+#define R300_CMD_PACKET3 3 /* emit a packet3 */
+#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */
+#define R300_CMD_CP_DELAY 5
+#define R300_CMD_DMA_DISCARD 6
+#define R300_CMD_WAIT 7
+# define R300_WAIT_2D 0x1
+# define R300_WAIT_3D 0x2
+# define R300_WAIT_2D_CLEAN 0x3
+# define R300_WAIT_3D_CLEAN 0x4
+
+typedef union {
+ unsigned int u;
+ struct {
+ unsigned char cmd_type, pad0, pad1, pad2;
+ } header;
+ struct {
+ unsigned char cmd_type, count, reglo, reghi;
+ } packet0;
+ struct {
+ unsigned char cmd_type, count, adrlo, adrhi;
+ } vpu;
+ struct {
+ unsigned char cmd_type, packet, pad0, pad1;
+ } packet3;
+ struct {
+ unsigned char cmd_type, packet;
+ unsigned short count; /* amount of packet2 to emit */
+ } delay;
+ struct {
+ unsigned char cmd_type, buf_idx, pad0, pad1;
+ } dma;
+ struct {
+ unsigned char cmd_type, flags, pad0, pad1;
+ } wait;
+} drm_r300_cmd_header_t;
#define RADEON_FRONT 0x1
#define RADEON_BACK 0x2
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 18e4e5b0952f..e0682f64b400 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -76,6 +76,7 @@ static struct drm_driver driver = {
.driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.preinit = radeon_driver_preinit,
+ .presetup = radeon_presetup,
.postcleanup = radeon_driver_postcleanup,
.prerelease = radeon_driver_prerelease,
.pretakedown = radeon_driver_pretakedown,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 771aa80a5e8c..f12a963ede18 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -82,9 +82,10 @@
* - Add support for r100 cube maps
* 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
* texture filtering on r200
+ * 1.17- Add initial support for R300 (3D).
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 16
+#define DRIVER_MINOR 17
#define DRIVER_PATCHLEVEL 0
#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
@@ -106,7 +107,9 @@ enum radeon_family {
CHIP_RV280,
CHIP_R300,
CHIP_RS300,
+ CHIP_R350,
CHIP_RV350,
+ CHIP_R420,
CHIP_LAST,
};
@@ -290,6 +293,7 @@ extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
+extern int radeon_presetup(struct drm_device *dev);
extern int radeon_driver_postcleanup(struct drm_device *dev);
extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
@@ -320,6 +324,14 @@ extern int radeon_postcleanup( struct drm_device *dev );
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
+
+/* r300_cmdbuf.c */
+extern void r300_init_reg_flags(void);
+
+extern int r300_do_cp_cmdbuf(drm_device_t* dev, DRMFILE filp,
+ drm_file_t* filp_priv,
+ drm_radeon_cmd_buffer_t* cmdbuf);
+
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
@@ -357,6 +369,11 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_CRTC2_OFFSET 0x0324
#define RADEON_CRTC2_OFFSET_CNTL 0x0328
+#define RADEON_MPP_TB_CONFIG 0x01c0
+#define RADEON_MEM_CNTL 0x0140
+#define RADEON_MEM_SDRAM_MODE_REG 0x0158
+#define RADEON_AGP_BASE 0x0170
+
#define RADEON_RB3D_COLOROFFSET 0x1c40
#define RADEON_RB3D_COLORPITCH 0x1c48
@@ -651,16 +668,27 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_CP_PACKET1 0x40000000
#define RADEON_CP_PACKET2 0x80000000
#define RADEON_CP_PACKET3 0xC0000000
+# define RADEON_CP_NOP 0x00001000
+# define RADEON_CP_NEXT_CHAR 0x00001900
+# define RADEON_CP_PLY_NEXTSCAN 0x00001D00
+# define RADEON_CP_SET_SCISSORS 0x00001E00
+ /* GEN_INDX_PRIM is unsupported starting with R300 */
# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
# define RADEON_WAIT_FOR_IDLE 0x00002600
# define RADEON_3D_DRAW_VBUF 0x00002800
# define RADEON_3D_DRAW_IMMD 0x00002900
# define RADEON_3D_DRAW_INDX 0x00002A00
+# define RADEON_CP_LOAD_PALETTE 0x00002C00
# define RADEON_3D_LOAD_VBPNTR 0x00002F00
# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000
# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100
# define RADEON_3D_CLEAR_ZMASK 0x00003200
+# define RADEON_CP_INDX_BUFFER 0x00003300
+# define RADEON_CP_3D_DRAW_VBUF_2 0x00003400
+# define RADEON_CP_3D_DRAW_IMMD_2 0x00003500
+# define RADEON_CP_3D_DRAW_INDX_2 0x00003600
# define RADEON_3D_CLEAR_HIZ 0x00003700
+# define RADEON_CP_3D_CLEAR_CMASK 0x00003802
# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
# define RADEON_CNTL_PAINT_MULTI 0x00009A00
# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 1f79e249146c..64a3e3a406ef 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -1493,7 +1493,7 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
}
-#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
+#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
static int radeon_cp_dispatch_texture( DRMFILE filp,
drm_device_t *dev,
@@ -1506,10 +1506,11 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
u32 format;
u32 *buffer;
const u8 __user *data;
- int size, dwords, tex_width, blit_width;
+ int size, dwords, tex_width, blit_width, spitch;
u32 height;
int i;
u32 texpitch, microtile;
+ u32 offset;
RING_LOCALS;
DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
@@ -1530,17 +1531,6 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
-#ifdef __BIG_ENDIAN
- /* The Mesa texture functions provide the data in little endian as the
- * chip wants it, but we need to compensate for the fact that the CP
- * ring gets byte-swapped
- */
- BEGIN_RING( 2 );
- OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
- ADVANCE_RING();
-#endif
-
-
/* The compiler won't optimize away a division by a variable,
* even if the only legal values are powers of two. Thus, we'll
* use a shift instead.
@@ -1572,6 +1562,10 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
DRM_ERROR( "invalid texture format %d\n", tex->format );
return DRM_ERR(EINVAL);
}
+ spitch = blit_width >> 6;
+ if (spitch == 0 && image->height > 1)
+ return DRM_ERR(EINVAL);
+
texpitch = tex->pitch;
if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
microtile = 1;
@@ -1624,25 +1618,6 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
*/
buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
dwords = size / 4;
- buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
- buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- (format << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_HOST_DATA |
- RADEON_GMC_CLR_CMP_CNTL_DIS |
- RADEON_GMC_WR_MSK_DIS);
-
- buffer[2] = (texpitch << 22) | (tex->offset >> 10);
- buffer[3] = 0xffffffff;
- buffer[4] = 0xffffffff;
- buffer[5] = (image->y << 16) | image->x;
- buffer[6] = (height << 16) | image->width;
- buffer[7] = dwords;
- buffer += 8;
-
-
if (microtile) {
/* texture micro tiling in use, minimum texture width is thus 16 bytes.
@@ -1750,9 +1725,28 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
}
buf->filp = filp;
- buf->used = (dwords + 8) * sizeof(u32);
- radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
- radeon_cp_discard_buffer( dev, buf );
+ buf->used = size;
+ offset = dev_priv->gart_buffers_offset + buf->offset;
+ BEGIN_RING(9);
+ OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (format << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS );
+ OUT_RING((spitch << 22) | (offset >> 10));
+ OUT_RING((texpitch << 22) | (tex->offset >> 10));
+ OUT_RING(0);
+ OUT_RING((image->x << 16) | image->y);
+ OUT_RING((image->width << 16) | height);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+ ADVANCE_RING();
+
+ radeon_cp_discard_buffer(dev, buf);
/* Update the input parameters for next time */
image->y += height;
@@ -2797,6 +2791,17 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
orig_nbox = cmdbuf.nbox;
+ if(dev_priv->microcode_version == UCODE_R300) {
+ int temp;
+ temp=r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
+
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+ return temp;
+ }
+
+ /* microcode_version != r300 */
while ( cmdbuf.bufsz >= sizeof(header) ) {
header.i = *(int *)cmdbuf.buf;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
new file mode 100644
index 000000000000..2fd40bac7c97
--- /dev/null
+++ b/drivers/char/drm/savage_bci.c
@@ -0,0 +1,1096 @@
+/* savage_bci.c -- BCI support for Savage
+ *
+ * Copyright 2004 Felix Kuehling
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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 "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+/* Need a long timeout for shadow status updates can take a while
+ * and so can waiting for events when the queue is full. */
+#define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */
+#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
+#define SAVAGE_FREELIST_DEBUG 0
+
+static int
+savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n)
+{
+ uint32_t mask = dev_priv->status_used_mask;
+ uint32_t threshold = dev_priv->bci_threshold_hi;
+ uint32_t status;
+ int i;
+
+#if SAVAGE_BCI_DEBUG
+ if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold)
+ DRM_ERROR("Trying to emit %d words "
+ "(more than guaranteed space in COB)\n", n);
+#endif
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ DRM_MEMORYBARRIER();
+ status = dev_priv->status_ptr[0];
+ if ((status & mask) < threshold)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, threshold=0x%08x\n", status, threshold);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s3d(drm_savage_private_t *dev_priv, unsigned int n)
+{
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_STATUS_WORD0);
+ if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x\n", status);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s4(drm_savage_private_t *dev_priv, unsigned int n)
+{
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0);
+ if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x\n", status);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+/*
+ * Waiting for events.
+ *
+ * The BIOSresets the event tag to 0 on mode changes. Therefore we
+ * never emit 0 to the event tag. If we find a 0 event tag we know the
+ * BIOS stomped on it and return success assuming that the BIOS waited
+ * for engine idle.
+ *
+ * Note: if the Xserver uses the event tag it has to follow the same
+ * rule. Otherwise there may be glitches every 2^16 events.
+ */
+static int
+savage_bci_wait_event_shadow(drm_savage_private_t *dev_priv, uint16_t e)
+{
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+ DRM_MEMORYBARRIER();
+ status = dev_priv->status_ptr[1];
+ if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+ (status & 0xffff) == 0)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_event_reg(drm_savage_private_t *dev_priv, uint16_t e)
+{
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_STATUS_WORD1);
+ if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+ (status & 0xffff) == 0)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+ return DRM_ERR(EBUSY);
+}
+
+uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
+ unsigned int flags)
+{
+ uint16_t count;
+ BCI_LOCALS;
+
+ if (dev_priv->status_ptr) {
+ /* coordinate with Xserver */
+ count = dev_priv->status_ptr[1023];
+ if (count < dev_priv->event_counter)
+ dev_priv->event_wrap++;
+ } else {
+ count = dev_priv->event_counter;
+ }
+ count = (count + 1) & 0xffff;
+ if (count == 0) {
+ count++; /* See the comment above savage_wait_event_*. */
+ dev_priv->event_wrap++;
+ }
+ dev_priv->event_counter = count;
+ if (dev_priv->status_ptr)
+ dev_priv->status_ptr[1023] = (uint32_t)count;
+
+ if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
+ unsigned int wait_cmd = BCI_CMD_WAIT;
+ if ((flags & SAVAGE_WAIT_2D))
+ wait_cmd |= BCI_CMD_WAIT_2D;
+ if ((flags & SAVAGE_WAIT_3D))
+ wait_cmd |= BCI_CMD_WAIT_3D;
+ BEGIN_BCI(2);
+ BCI_WRITE(wait_cmd);
+ } else {
+ BEGIN_BCI(1);
+ }
+ BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t)count);
+
+ return count;
+}
+
+/*
+ * Freelist management
+ */
+static int savage_freelist_init(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_savage_buf_priv_t *entry;
+ int i;
+ DRM_DEBUG("count=%d\n", dma->buf_count);
+
+ dev_priv->head.next = &dev_priv->tail;
+ dev_priv->head.prev = NULL;
+ dev_priv->head.buf = NULL;
+
+ dev_priv->tail.next = NULL;
+ dev_priv->tail.prev = &dev_priv->head;
+ dev_priv->tail.buf = NULL;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ entry = buf->dev_private;
+
+ SET_AGE(&entry->age, 0, 0);
+ entry->buf = buf;
+
+ entry->next = dev_priv->head.next;
+ entry->prev = &dev_priv->head;
+ dev_priv->head.next->prev = entry;
+ dev_priv->head.next = entry;
+ }
+
+ return 0;
+}
+
+static drm_buf_t *savage_freelist_get(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
+ uint16_t event;
+ unsigned int wrap;
+ DRM_DEBUG("\n");
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ event = dev_priv->status_ptr[1] & 0xffff;
+ else
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ DRM_DEBUG(" tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
+ DRM_DEBUG(" head=0x%04x %d\n", event, wrap);
+
+ if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) {
+ drm_savage_buf_priv_t *next = tail->next;
+ drm_savage_buf_priv_t *prev = tail->prev;
+ prev->next = next;
+ next->prev = prev;
+ tail->next = tail->prev = NULL;
+ return tail->buf;
+ }
+
+ DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf);
+ return NULL;
+}
+
+void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
+
+ DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap);
+
+ if (entry->next != NULL || entry->prev != NULL) {
+ DRM_ERROR("entry already on freelist.\n");
+ return;
+ }
+
+ prev = &dev_priv->head;
+ next = prev->next;
+ prev->next = entry;
+ next->prev = entry;
+ entry->prev = prev;
+ entry->next = next;
+}
+
+/*
+ * Command DMA
+ */
+static int savage_dma_init(drm_savage_private_t *dev_priv)
+{
+ unsigned int i;
+
+ dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
+ (SAVAGE_DMA_PAGE_SIZE*4);
+ dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
+ dev_priv->nr_dma_pages,
+ DRM_MEM_DRIVER);
+ if (dev_priv->dma_pages == NULL)
+ return DRM_ERR(ENOMEM);
+
+ for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ SET_AGE(&dev_priv->last_dma_age, 0, 0);
+
+ dev_priv->first_dma_page = 0;
+ dev_priv->current_dma_page = 0;
+
+ return 0;
+}
+
+void savage_dma_reset(drm_savage_private_t *dev_priv)
+{
+ uint16_t event;
+ unsigned int wrap, i;
+ event = savage_bci_emit_event(dev_priv, 0);
+ wrap = dev_priv->event_wrap;
+ for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ SET_AGE(&dev_priv->last_dma_age, event, wrap);
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page)
+{
+ uint16_t event;
+ unsigned int wrap;
+
+ /* Faked DMA buffer pages don't age. */
+ if (dev_priv->cmd_dma == &dev_priv->fake_dma)
+ return;
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ event = dev_priv->status_ptr[1] & 0xffff;
+ else
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ if (dev_priv->dma_pages[page].age.wrap > wrap ||
+ (dev_priv->dma_pages[page].age.wrap == wrap &&
+ dev_priv->dma_pages[page].age.event > event)) {
+ if (dev_priv->wait_evnt(dev_priv,
+ dev_priv->dma_pages[page].age.event)
+ < 0)
+ DRM_ERROR("wait_evnt failed!\n");
+ }
+}
+
+uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n)
+{
+ unsigned int cur = dev_priv->current_dma_page;
+ unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
+ dev_priv->dma_pages[cur].used;
+ unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE-1) /
+ SAVAGE_DMA_PAGE_SIZE;
+ uint32_t *dma_ptr;
+ unsigned int i;
+
+ DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",
+ cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
+
+ if (cur + nr_pages < dev_priv->nr_dma_pages) {
+ dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+ cur*SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[cur].used;
+ if (n < rest)
+ rest = n;
+ dev_priv->dma_pages[cur].used += rest;
+ n -= rest;
+ cur++;
+ } else {
+ dev_priv->dma_flush(dev_priv);
+ nr_pages = (n + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE;
+ for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
+ dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle;
+ dev_priv->first_dma_page = cur = 0;
+ }
+ for (i = cur; nr_pages > 0; ++i, --nr_pages) {
+#if SAVAGE_DMA_DEBUG
+ if (dev_priv->dma_pages[i].used) {
+ DRM_ERROR("unflushed page %u: used=%u\n",
+ i, dev_priv->dma_pages[i].used);
+ }
+#endif
+ if (n > SAVAGE_DMA_PAGE_SIZE)
+ dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;
+ else
+ dev_priv->dma_pages[i].used = n;
+ n -= SAVAGE_DMA_PAGE_SIZE;
+ }
+ dev_priv->current_dma_page = --i;
+
+ DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",
+ i, dev_priv->dma_pages[i].used, n);
+
+ savage_dma_wait(dev_priv, dev_priv->current_dma_page);
+
+ return dma_ptr;
+}
+
+static void savage_dma_flush(drm_savage_private_t *dev_priv)
+{
+ unsigned int first = dev_priv->first_dma_page;
+ unsigned int cur = dev_priv->current_dma_page;
+ uint16_t event;
+ unsigned int wrap, pad, align, len, i;
+ unsigned long phys_addr;
+ BCI_LOCALS;
+
+ if (first == cur &&
+ dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
+ return;
+
+ /* pad length to multiples of 2 entries
+ * align start of next DMA block to multiles of 8 entries */
+ pad = -dev_priv->dma_pages[cur].used & 1;
+ align = -(dev_priv->dma_pages[cur].used + pad) & 7;
+
+ DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "
+ "pad=%u, align=%u\n",
+ first, cur, dev_priv->dma_pages[first].flushed,
+ dev_priv->dma_pages[cur].used, pad, align);
+
+ /* pad with noops */
+ if (pad) {
+ uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+ cur * SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[cur].used;
+ dev_priv->dma_pages[cur].used += pad;
+ while(pad != 0) {
+ *dma_ptr++ = BCI_CMD_WAIT;
+ pad--;
+ }
+ }
+
+ DRM_MEMORYBARRIER();
+
+ /* do flush ... */
+ phys_addr = dev_priv->cmd_dma->offset +
+ (first * SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[first].flushed) * 4;
+ len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[cur].used -
+ dev_priv->dma_pages[first].flushed;
+
+ DRM_DEBUG("phys_addr=%lx, len=%u\n",
+ phys_addr | dev_priv->dma_type, len);
+
+ BEGIN_BCI(3);
+ BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);
+ BCI_WRITE(phys_addr | dev_priv->dma_type);
+ BCI_DMA(len);
+
+ /* fix alignment of the start of the next block */
+ dev_priv->dma_pages[cur].used += align;
+
+ /* age DMA pages */
+ event = savage_bci_emit_event(dev_priv, 0);
+ wrap = dev_priv->event_wrap;
+ for (i = first; i < cur; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ /* age the current page only when it's full */
+ if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {
+ SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);
+ dev_priv->dma_pages[cur].used = 0;
+ dev_priv->dma_pages[cur].flushed = 0;
+ /* advance to next page */
+ cur++;
+ if (cur == dev_priv->nr_dma_pages)
+ cur = 0;
+ dev_priv->first_dma_page = dev_priv->current_dma_page = cur;
+ } else {
+ dev_priv->first_dma_page = cur;
+ dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;
+ }
+ SET_AGE(&dev_priv->last_dma_age, event, wrap);
+
+ DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,
+ dev_priv->dma_pages[cur].used,
+ dev_priv->dma_pages[cur].flushed);
+}
+
+static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
+{
+ unsigned int i, j;
+ BCI_LOCALS;
+
+ if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
+ dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
+ return;
+
+ DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",
+ dev_priv->first_dma_page, dev_priv->current_dma_page,
+ dev_priv->dma_pages[dev_priv->current_dma_page].used);
+
+ for (i = dev_priv->first_dma_page;
+ i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
+ ++i) {
+ uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+ i * SAVAGE_DMA_PAGE_SIZE;
+#if SAVAGE_DMA_DEBUG
+ /* Sanity check: all pages except the last one must be full. */
+ if (i < dev_priv->current_dma_page &&
+ dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {
+ DRM_ERROR("partial DMA page %u: used=%u",
+ i, dev_priv->dma_pages[i].used);
+ }
+#endif
+ BEGIN_BCI(dev_priv->dma_pages[i].used);
+ for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {
+ BCI_WRITE(dma_ptr[j]);
+ }
+ dev_priv->dma_pages[i].used = 0;
+ }
+
+ /* reset to first page */
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+/*
+ * Initalize mappings. On Savage4 and SavageIX the alignment
+ * and size of the aperture is not suitable for automatic MTRR setup
+ * in drm_addmap. Therefore we do it manually before the maps are
+ * initialized. We also need to take care of deleting the MTRRs in
+ * postcleanup.
+ */
+int savage_preinit(drm_device_t *dev, unsigned long chipset)
+{
+ drm_savage_private_t *dev_priv;
+ unsigned long mmio_base, fb_base, fb_size, aperture_base;
+ /* fb_rsrc and aper_rsrc aren't really used currently, but still exist
+ * in case we decide we need information on the BAR for BSD in the
+ * future.
+ */
+ unsigned int fb_rsrc, aper_rsrc;
+ int ret = 0;
+
+ dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+
+ memset(dev_priv, 0, sizeof(drm_savage_private_t));
+ dev->dev_private = (void *)dev_priv;
+ dev_priv->chipset = (enum savage_family)chipset;
+
+ dev_priv->mtrr[0].handle = -1;
+ dev_priv->mtrr[1].handle = -1;
+ dev_priv->mtrr[2].handle = -1;
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ fb_rsrc = 0;
+ fb_base = drm_get_resource_start(dev, 0);
+ fb_size = SAVAGE_FB_SIZE_S3;
+ mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
+ aper_rsrc = 0;
+ aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+ /* this should always be true */
+ if (drm_get_resource_len(dev, 0) == 0x08000000) {
+ /* Don't make MMIO write-cobining! We need 3
+ * MTRRs. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x01000000;
+ dev_priv->mtrr[0].handle = mtrr_add(
+ dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+ MTRR_TYPE_WRCOMB, 1);
+ dev_priv->mtrr[1].base = fb_base+0x02000000;
+ dev_priv->mtrr[1].size = 0x02000000;
+ dev_priv->mtrr[1].handle = mtrr_add(
+ dev_priv->mtrr[1].base, dev_priv->mtrr[1].size,
+ MTRR_TYPE_WRCOMB, 1);
+ dev_priv->mtrr[2].base = fb_base+0x04000000;
+ dev_priv->mtrr[2].size = 0x04000000;
+ dev_priv->mtrr[2].handle = mtrr_add(
+ dev_priv->mtrr[2].base, dev_priv->mtrr[2].size,
+ MTRR_TYPE_WRCOMB, 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 0));
+ }
+ } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
+ fb_size = SAVAGE_FB_SIZE_S4;
+ aper_rsrc = 1;
+ aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+ /* this should always be true */
+ if (drm_get_resource_len(dev, 1) == 0x08000000) {
+ /* Can use one MTRR to cover both fb and
+ * aperture. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x08000000;
+ dev_priv->mtrr[0].handle = mtrr_add(
+ dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+ MTRR_TYPE_WRCOMB, 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 1));
+ }
+ } else {
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
+ fb_size = drm_get_resource_len(dev, 1);
+ aper_rsrc = 2;
+ aperture_base = drm_get_resource_start(dev, 2);
+ /* Automatic MTRR setup will do the right thing. */
+ }
+
+ ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,
+ _DRM_READ_ONLY, &dev_priv->mmio);
+ if (ret)
+ return ret;
+
+ ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,
+ _DRM_WRITE_COMBINING, &dev_priv->fb);
+ if (ret)
+ return ret;
+
+ ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+ _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+ &dev_priv->aperture);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+/*
+ * Delete MTRRs and free device-private data.
+ */
+int savage_postcleanup(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ if (dev_priv->mtrr[i].handle >= 0)
+ mtrr_del(dev_priv->mtrr[i].handle,
+ dev_priv->mtrr[i].base,
+ dev_priv->mtrr[i].size);
+
+ drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+
+ return 0;
+}
+
+static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+ if (init->fb_bpp != 16 && init->fb_bpp != 32) {
+ DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->depth_bpp != 16 && init->depth_bpp != 32) {
+ DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->dma_type != SAVAGE_DMA_AGP &&
+ init->dma_type != SAVAGE_DMA_PCI) {
+ DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->cob_size = init->cob_size;
+ dev_priv->bci_threshold_lo = init->bci_threshold_lo;
+ dev_priv->bci_threshold_hi = init->bci_threshold_hi;
+ dev_priv->dma_type = init->dma_type;
+
+ dev_priv->fb_bpp = init->fb_bpp;
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
+ dev_priv->depth_bpp = init->depth_bpp;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+
+ dev_priv->texture_offset = init->texture_offset;
+ dev_priv->texture_size = init->texture_size;
+
+ DRM_GETSAREA();
+ if (!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->status_offset != 0) {
+ dev_priv->status = drm_core_findmap(dev, init->status_offset);
+ if (!dev_priv->status) {
+ DRM_ERROR("could not find shadow status region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->status = NULL;
+ }
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {
+ dev->agp_buffer_map = drm_core_findmap(dev,
+ init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("could not find DMA buffer region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("failed to ioremap DMA buffer region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ }
+ if (init->agp_textures_offset) {
+ dev_priv->agp_textures =
+ drm_core_findmap(dev, init->agp_textures_offset);
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->agp_textures = NULL;
+ }
+
+ if (init->cmd_dma_offset) {
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ DRM_ERROR("command DMA not supported on "
+ "Savage3D/MX/IX.\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (dev->dma && dev->dma->buflist) {
+ DRM_ERROR("command and vertex DMA not supported "
+ "at the same time.\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
+ if (!dev_priv->cmd_dma) {
+ DRM_ERROR("could not find command DMA region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
+ if (dev_priv->cmd_dma->type != _DRM_AGP) {
+ DRM_ERROR("AGP command DMA region is not a "
+ "_DRM_AGP map!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ drm_core_ioremap(dev_priv->cmd_dma, dev);
+ if (!dev_priv->cmd_dma->handle) {
+ DRM_ERROR("failed to ioremap command "
+ "DMA region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
+ DRM_ERROR("PCI command DMA region is not a "
+ "_DRM_CONSISTENT map!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->cmd_dma = NULL;
+ }
+
+ dev_priv->dma_flush = savage_dma_flush;
+ if (!dev_priv->cmd_dma) {
+ DRM_DEBUG("falling back to faked command DMA.\n");
+ dev_priv->fake_dma.offset = 0;
+ dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
+ dev_priv->fake_dma.type = _DRM_SHM;
+ dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
+ DRM_MEM_DRIVER);
+ if (!dev_priv->fake_dma.handle) {
+ DRM_ERROR("could not allocate faked DMA buffer!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->cmd_dma = &dev_priv->fake_dma;
+ dev_priv->dma_flush = savage_fake_dma_flush;
+ }
+
+ dev_priv->sarea_priv =
+ (drm_savage_sarea_t *)((uint8_t *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ /* setup bitmap descriptors */
+ {
+ unsigned int color_tile_format;
+ unsigned int depth_tile_format;
+ unsigned int front_stride, back_stride, depth_stride;
+ if (dev_priv->chipset <= S3_SAVAGE4) {
+ color_tile_format = dev_priv->fb_bpp == 16 ?
+ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ depth_tile_format = dev_priv->depth_bpp == 16 ?
+ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ } else {
+ color_tile_format = SAVAGE_BD_TILE_DEST;
+ depth_tile_format = SAVAGE_BD_TILE_DEST;
+ }
+ front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp/8);
+ back_stride = dev_priv-> back_pitch / (dev_priv->fb_bpp/8);
+ depth_stride = dev_priv->depth_pitch / (dev_priv->depth_bpp/8);
+
+ dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+ dev_priv-> back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+ dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
+ }
+
+ /* setup status and bci ptr */
+ dev_priv->event_counter = 0;
+ dev_priv->event_wrap = 0;
+ dev_priv->bci_ptr = (volatile uint32_t *)
+ ((uint8_t *)dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
+ } else {
+ dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4;
+ }
+ if (dev_priv->status != NULL) {
+ dev_priv->status_ptr =
+ (volatile uint32_t *)dev_priv->status->handle;
+ dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
+ dev_priv->wait_evnt = savage_bci_wait_event_shadow;
+ dev_priv->status_ptr[1023] = dev_priv->event_counter;
+ } else {
+ dev_priv->status_ptr = NULL;
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ dev_priv->wait_fifo = savage_bci_wait_fifo_s3d;
+ } else {
+ dev_priv->wait_fifo = savage_bci_wait_fifo_s4;
+ }
+ dev_priv->wait_evnt = savage_bci_wait_event_reg;
+ }
+
+ /* cliprect functions */
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset))
+ dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d;
+ else
+ dev_priv->emit_clip_rect = savage_emit_clip_rect_s4;
+
+ if (savage_freelist_init(dev) < 0) {
+ DRM_ERROR("could not initialize freelist\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+
+ if (savage_dma_init(dev_priv) < 0) {
+ DRM_ERROR("could not initialize command DMA\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+
+ return 0;
+}
+
+int savage_do_cleanup_bci(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+ if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
+ if (dev_priv->fake_dma.handle)
+ drm_free(dev_priv->fake_dma.handle,
+ SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+ } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
+ dev_priv->cmd_dma->type == _DRM_AGP &&
+ dev_priv->dma_type == SAVAGE_DMA_AGP)
+ drm_core_ioremapfree(dev_priv->cmd_dma, dev);
+
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP &&
+ dev->agp_buffer_map && dev->agp_buffer_map->handle) {
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ /* make sure the next instance (which may be running
+ * in PCI mode) doesn't try to use an old
+ * agp_buffer_map. */
+ dev->agp_buffer_map = NULL;
+ }
+
+ if (dev_priv->dma_pages)
+ drm_free(dev_priv->dma_pages,
+ sizeof(drm_savage_dma_page_t)*dev_priv->nr_dma_pages,
+ DRM_MEM_DRIVER);
+
+ return 0;
+}
+
+static int savage_bci_init(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_init_t init;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *)data,
+ sizeof(init));
+
+ switch (init.func) {
+ case SAVAGE_INIT_BCI:
+ return savage_do_init_bci(dev, &init);
+ case SAVAGE_CLEANUP_BCI:
+ return savage_do_cleanup_bci(dev);
+ }
+
+ return DRM_ERR(EINVAL);
+}
+
+static int savage_bci_event_emit(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_event_emit_t event;
+
+ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data,
+ sizeof(event));
+
+ event.count = savage_bci_emit_event(dev_priv, event.flags);
+ event.count |= dev_priv->event_wrap << 16;
+ DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *)data)->count,
+ event.count, sizeof(event.count));
+ return 0;
+}
+
+static int savage_bci_event_wait(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_event_wait_t event;
+ unsigned int event_e, hw_e;
+ unsigned int event_w, hw_w;
+
+ DRM_DEBUG("\n");
+
+ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *)data,
+ sizeof(event));
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ hw_e = dev_priv->status_ptr[1] & 0xffff;
+ else
+ hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ hw_w = dev_priv->event_wrap;
+ if (hw_e > dev_priv->event_counter)
+ hw_w--; /* hardware hasn't passed the last wrap yet */
+
+ event_e = event.count & 0xffff;
+ event_w = event.count >> 16;
+
+ /* Don't need to wait if
+ * - event counter wrapped since the event was emitted or
+ * - the hardware has advanced up to or over the event to wait for.
+ */
+ if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e) )
+ return 0;
+ else
+ return dev_priv->wait_evnt(dev_priv, event_e);
+}
+
+/*
+ * DMA buffer management
+ */
+
+static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
+{
+ drm_buf_t *buf;
+ int i;
+
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = savage_freelist_get(dev);
+ if (!buf)
+ return DRM_ERR(EAGAIN);
+
+ buf->filp = filp;
+
+ if (DRM_COPY_TO_USER(&d->request_indices[i],
+ &buf->idx, sizeof(buf->idx)))
+ return DRM_ERR(EFAULT);
+ if (DRM_COPY_TO_USER(&d->request_sizes[i],
+ &buf->total, sizeof(buf->total)))
+ return DRM_ERR(EFAULT);
+
+ d->granted_count++;
+ }
+ return 0;
+}
+
+int savage_bci_buffers(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_dma_t d;
+ int ret = 0;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *)data, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d.send_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* We'll send you buffers.
+ */
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d.request_count, dma->buf_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ d.granted_count = 0;
+
+ if (d.request_count) {
+ ret = savage_bci_get_buffers(filp, dev, &d);
+ }
+
+ DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *)data, d, sizeof(d));
+
+ return ret;
+}
+
+void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp) {
+ drm_device_dma_t *dma = dev->dma;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ if (!dma)
+ return;
+ if (!dev_priv)
+ return;
+ if (!dma->buflist)
+ return;
+
+ /*i830_flush_queue(dev);*/
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_savage_buf_priv_t *buf_priv = buf->dev_private;
+
+ if (buf->filp == filp && buf_priv &&
+ buf_priv->next == NULL && buf_priv->prev == NULL) {
+ uint16_t event;
+ DRM_DEBUG("reclaimed from client\n");
+ event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+ SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+ savage_freelist_put(dev, buf);
+ }
+ }
+
+ drm_core_reclaim_buffers(dev, filp);
+}
+
+
+drm_ioctl_desc_t savage_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, 1, 0},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, 1, 0},
+};
+
+int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
new file mode 100644
index 000000000000..6526c9aa7589
--- /dev/null
+++ b/drivers/char/drm/savage_drm.h
@@ -0,0 +1,209 @@
+/* savage_drm.h -- Public header for the savage driver
+ *
+ * Copyright 2004 Felix Kuehling
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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 __SAVAGE_DRM_H__
+#define __SAVAGE_DRM_H__
+
+#ifndef __SAVAGE_SAREA_DEFINES__
+#define __SAVAGE_SAREA_DEFINES__
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define SAVAGE_CARD_HEAP 0
+#define SAVAGE_AGP_HEAP 1
+#define SAVAGE_NR_TEX_HEAPS 2
+#define SAVAGE_NR_TEX_REGIONS 16
+#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
+
+#endif /* __SAVAGE_SAREA_DEFINES__ */
+
+typedef struct _drm_savage_sarea {
+ /* LRU lists for texture memory in agp space and on the card.
+ */
+ drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1];
+ unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
+
+ /* Mechanism to validate card state.
+ */
+ int ctxOwner;
+} drm_savage_sarea_t, *drm_savage_sarea_ptr;
+
+/* Savage-specific ioctls
+ */
+#define DRM_SAVAGE_BCI_INIT 0x00
+#define DRM_SAVAGE_BCI_CMDBUF 0x01
+#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02
+#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03
+
+#define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
+#define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
+#define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
+#define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
+
+#define SAVAGE_DMA_PCI 1
+#define SAVAGE_DMA_AGP 3
+typedef struct drm_savage_init {
+ enum {
+ SAVAGE_INIT_BCI = 1,
+ SAVAGE_CLEANUP_BCI = 2
+ } func;
+ unsigned int sarea_priv_offset;
+
+ /* some parameters */
+ unsigned int cob_size;
+ unsigned int bci_threshold_lo, bci_threshold_hi;
+ unsigned int dma_type;
+
+ /* frame buffer layout */
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ /* local textures */
+ unsigned int texture_offset;
+ unsigned int texture_size;
+
+ /* physical locations of non-permanent maps */
+ unsigned long status_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+ unsigned long cmd_dma_offset;
+} drm_savage_init_t;
+
+typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
+typedef struct drm_savage_cmdbuf {
+ /* command buffer in client's address space */
+ drm_savage_cmd_header_t __user *cmd_addr;
+ unsigned int size; /* size of the command buffer in 64bit units */
+
+ unsigned int dma_idx; /* DMA buffer index to use */
+ int discard; /* discard DMA buffer when done */
+ /* vertex buffer in client's address space */
+ unsigned int __user *vb_addr;
+ unsigned int vb_size; /* size of client vertex buffer in bytes */
+ unsigned int vb_stride; /* stride of vertices in 32bit words */
+ /* boxes in client's address space */
+ drm_clip_rect_t __user *box_addr;
+ unsigned int nbox; /* number of clipping boxes */
+} drm_savage_cmdbuf_t;
+
+#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */
+#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */
+#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */
+typedef struct drm_savage_event {
+ unsigned int count;
+ unsigned int flags;
+} drm_savage_event_emit_t, drm_savage_event_wait_t;
+
+/* Commands for the cmdbuf ioctl
+ */
+#define SAVAGE_CMD_STATE 0 /* a range of state registers */
+#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */
+#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */
+#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */
+#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */
+#define SAVAGE_CMD_CLEAR 5 /* clear buffers */
+#define SAVAGE_CMD_SWAP 6 /* swap buffers */
+
+/* Primitive types
+*/
+#define SAVAGE_PRIM_TRILIST 0 /* triangle list */
+#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */
+#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */
+#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat
+ * shading on s3d */
+
+/* Skip flags (vertex format)
+ */
+#define SAVAGE_SKIP_Z 0x01
+#define SAVAGE_SKIP_W 0x02
+#define SAVAGE_SKIP_C0 0x04
+#define SAVAGE_SKIP_C1 0x08
+#define SAVAGE_SKIP_S0 0x10
+#define SAVAGE_SKIP_T0 0x20
+#define SAVAGE_SKIP_ST0 0x30
+#define SAVAGE_SKIP_S1 0x40
+#define SAVAGE_SKIP_T1 0x80
+#define SAVAGE_SKIP_ST1 0xc0
+#define SAVAGE_SKIP_ALL_S3D 0x3f
+#define SAVAGE_SKIP_ALL_S4 0xff
+
+/* Buffer names for clear command
+ */
+#define SAVAGE_FRONT 0x1
+#define SAVAGE_BACK 0x2
+#define SAVAGE_DEPTH 0x4
+
+/* 64-bit command header
+ */
+union drm_savage_cmd_header {
+ struct {
+ unsigned char cmd; /* command */
+ unsigned char pad0;
+ unsigned short pad1;
+ unsigned short pad2;
+ unsigned short pad3;
+ } cmd; /* generic */
+ struct {
+ unsigned char cmd;
+ unsigned char global; /* need idle engine? */
+ unsigned short count; /* number of consecutive registers */
+ unsigned short start; /* first register */
+ unsigned short pad3;
+ } state; /* SAVAGE_CMD_STATE */
+ struct {
+ unsigned char cmd;
+ unsigned char prim; /* primitive type */
+ unsigned short skip; /* vertex format (skip flags) */
+ unsigned short count; /* number of vertices */
+ unsigned short start; /* first vertex in DMA/vertex buffer */
+ } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
+ struct {
+ unsigned char cmd;
+ unsigned char prim;
+ unsigned short skip;
+ unsigned short count; /* number of indices that follow */
+ unsigned short pad3;
+ } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
+ struct {
+ unsigned char cmd;
+ unsigned char pad0;
+ unsigned short pad1;
+ unsigned int flags;
+ } clear0; /* SAVAGE_CMD_CLEAR */
+ struct {
+ unsigned int mask;
+ unsigned int value;
+ } clear1; /* SAVAGE_CMD_CLEAR data */
+};
+
+#endif
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
new file mode 100644
index 000000000000..ac8d270427ca
--- /dev/null
+++ b/drivers/char/drm/savage_drv.c
@@ -0,0 +1,112 @@
+/* savage_drv.c -- Savage driver for Linux
+ *
+ * Copyright 2004 Felix Kuehling
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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 "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+#include "drm_pciids.h"
+
+static int postinit( struct drm_device *dev, unsigned long flags )
+{
+ DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE,
+ dev->primary.minor,
+ pci_pretty_name(dev->pdev)
+ );
+ return 0;
+}
+
+static int version( drm_version_t *version )
+{
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+ DRM_COPY( version->name, DRIVER_NAME );
+ DRM_COPY( version->date, DRIVER_DATE );
+ DRM_COPY( version->desc, DRIVER_DESC );
+ return 0;
+}
+
+static struct pci_device_id pciidlist[] = {
+ savage_PCI_IDS
+};
+
+extern drm_ioctl_desc_t savage_ioctls[];
+extern int savage_max_ioctl;
+
+static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
+ .dev_priv_size = sizeof(drm_savage_buf_priv_t),
+ .preinit = savage_preinit,
+ .postinit = postinit,
+ .postcleanup = savage_postcleanup,
+ .reclaim_buffers = savage_reclaim_buffers,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .version = version,
+ .ioctls = savage_ioctls,
+ .dma_ioctl = savage_bci_buffers,
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+ .pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ }
+};
+
+static int __init savage_init(void)
+{
+ driver.num_ioctls = savage_max_ioctl;
+ return drm_init(&driver);
+}
+
+static void __exit savage_exit(void)
+{
+ drm_exit(&driver);
+}
+
+module_init(savage_init);
+module_exit(savage_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
new file mode 100644
index 000000000000..a45434944658
--- /dev/null
+++ b/drivers/char/drm/savage_drv.h
@@ -0,0 +1,579 @@
+/* savage_drv.h -- Private header for the savage driver
+ *
+ * Copyright 2004 Felix Kuehling
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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 __SAVAGE_DRV_H__
+#define __SAVAGE_DRV_H__
+
+#define DRIVER_AUTHOR "Felix Kuehling"
+
+#define DRIVER_NAME "savage"
+#define DRIVER_DESC "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
+#define DRIVER_DATE "20050313"
+
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 4
+#define DRIVER_PATCHLEVEL 1
+/* Interface history:
+ *
+ * 1.x The DRM driver from the VIA/S3 code drop, basically a dummy
+ * 2.0 The first real DRM
+ * 2.1 Scissors registers managed by the DRM, 3D operations clipped by
+ * cliprects of the cmdbuf ioctl
+ * 2.2 Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
+ * 2.3 Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
+ * wide and thus very long lived (unlikely to ever wrap). The size
+ * in the struct was 32 bits before, but only 16 bits were used
+ * 2.4 Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
+ * actually used
+ */
+
+typedef struct drm_savage_age {
+ uint16_t event;
+ unsigned int wrap;
+} drm_savage_age_t;
+
+typedef struct drm_savage_buf_priv {
+ struct drm_savage_buf_priv *next;
+ struct drm_savage_buf_priv *prev;
+ drm_savage_age_t age;
+ drm_buf_t *buf;
+} drm_savage_buf_priv_t;
+
+typedef struct drm_savage_dma_page {
+ drm_savage_age_t age;
+ unsigned int used, flushed;
+} drm_savage_dma_page_t;
+#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
+/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
+ * size of 16kbytes or 4k entries. Minimum requirement would be
+ * 10kbytes for 255 40-byte vertices in one drawing command. */
+#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
+
+/* interesting bits of hardware state that are saved in dev_priv */
+typedef union {
+ struct drm_savage_common_state {
+ uint32_t vbaddr;
+ } common;
+ struct {
+ unsigned char pad[sizeof(struct drm_savage_common_state)];
+ uint32_t texctrl, texaddr;
+ uint32_t scstart, new_scstart;
+ uint32_t scend, new_scend;
+ } s3d;
+ struct {
+ unsigned char pad[sizeof(struct drm_savage_common_state)];
+ uint32_t texdescr, texaddr0, texaddr1;
+ uint32_t drawctrl0, new_drawctrl0;
+ uint32_t drawctrl1, new_drawctrl1;
+ } s4;
+} drm_savage_state_t;
+
+/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
+enum savage_family {
+ S3_UNKNOWN = 0,
+ S3_SAVAGE3D,
+ S3_SAVAGE_MX,
+ S3_SAVAGE4,
+ S3_PROSAVAGE,
+ S3_TWISTER,
+ S3_PROSAVAGEDDR,
+ S3_SUPERSAVAGE,
+ S3_SAVAGE2000,
+ S3_LAST
+};
+
+#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
+ || (chip==S3_PROSAVAGE) \
+ || (chip==S3_TWISTER) \
+ || (chip==S3_PROSAVAGEDDR))
+
+#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \
+ ||(chip==S3_PROSAVAGEDDR))
+
+/* flags */
+#define SAVAGE_IS_AGP 1
+
+typedef struct drm_savage_private {
+ drm_savage_sarea_t *sarea_priv;
+
+ drm_savage_buf_priv_t head, tail;
+
+ /* who am I? */
+ enum savage_family chipset;
+
+ unsigned int cob_size;
+ unsigned int bci_threshold_lo, bci_threshold_hi;
+ unsigned int dma_type;
+
+ /* frame buffer layout */
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ /* bitmap descriptors for swap and clear */
+ unsigned int front_bd, back_bd, depth_bd;
+
+ /* local textures */
+ unsigned int texture_offset;
+ unsigned int texture_size;
+
+ /* memory regions in physical memory */
+ drm_local_map_t *sarea;
+ drm_local_map_t *mmio;
+ drm_local_map_t *fb;
+ drm_local_map_t *aperture;
+ drm_local_map_t *status;
+ drm_local_map_t *agp_textures;
+ drm_local_map_t *cmd_dma;
+ drm_local_map_t fake_dma;
+
+ struct {
+ int handle;
+ unsigned long base, size;
+ } mtrr[3];
+
+ /* BCI and status-related stuff */
+ volatile uint32_t *status_ptr, *bci_ptr;
+ uint32_t status_used_mask;
+ uint16_t event_counter;
+ unsigned int event_wrap;
+
+ /* Savage4 command DMA */
+ drm_savage_dma_page_t *dma_pages;
+ unsigned int nr_dma_pages, first_dma_page, current_dma_page;
+ drm_savage_age_t last_dma_age;
+
+ /* saved hw state for global/local check on S3D */
+ uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
+ /* and for scissors (global, so don't emit if not changed) */
+ uint32_t hw_scissors_start, hw_scissors_end;
+
+ drm_savage_state_t state;
+
+ /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
+ unsigned int waiting;
+
+ /* config/hardware-dependent function pointers */
+ int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n);
+ int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e);
+ /* Err, there is a macro wait_event in include/linux/wait.h.
+ * Avoid unwanted macro expansion. */
+ void (*emit_clip_rect)(struct drm_savage_private *dev_priv,
+ drm_clip_rect_t *pbox);
+ void (*dma_flush)(struct drm_savage_private *dev_priv);
+} drm_savage_private_t;
+
+/* ioctls */
+extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS);
+extern int savage_bci_buffers(DRM_IOCTL_ARGS);
+
+/* BCI functions */
+extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
+ unsigned int flags);
+extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+extern void savage_dma_reset(drm_savage_private_t *dev_priv);
+extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page);
+extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv,
+ unsigned int n);
+extern int savage_preinit(drm_device_t *dev, unsigned long chipset);
+extern int savage_postcleanup(drm_device_t *dev);
+extern int savage_do_cleanup_bci(drm_device_t *dev);
+extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
+
+/* state functions */
+extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+ drm_clip_rect_t *pbox);
+extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+ drm_clip_rect_t *pbox);
+
+#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
+#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
+#define SAVAGE_MMIO_SIZE 0x00080000 /* 512kB */
+#define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */
+#define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */
+
+#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region
+ * inside the MMIO region */
+#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip
+ * BCI FIFO */
+
+/*
+ * MMIO registers
+ */
+#define SAVAGE_STATUS_WORD0 0x48C00
+#define SAVAGE_STATUS_WORD1 0x48C04
+#define SAVAGE_ALT_STATUS_WORD0 0x48C60
+
+#define SAVAGE_FIFO_USED_MASK_S3D 0x0001ffff
+#define SAVAGE_FIFO_USED_MASK_S4 0x001fffff
+
+/* Copied from savage_bci.h in the 2D driver with some renaming. */
+
+/* Bitmap descriptors */
+#define SAVAGE_BD_STRIDE_SHIFT 0
+#define SAVAGE_BD_BPP_SHIFT 16
+#define SAVAGE_BD_TILE_SHIFT 24
+#define SAVAGE_BD_BW_DISABLE (1<<28)
+/* common: */
+#define SAVAGE_BD_TILE_LINEAR 0
+/* savage4, MX, IX, 3D */
+#define SAVAGE_BD_TILE_16BPP 2
+#define SAVAGE_BD_TILE_32BPP 3
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_BD_TILE_DEST 1
+#define SAVAGE_BD_TILE_TEXTURE 2
+/* GBD - BCI enable */
+/* savage4, MX, IX, 3D */
+#define SAVAGE_GBD_BCI_ENABLE 8
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_GBD_BCI_ENABLE_TWISTER 0
+
+#define SAVAGE_GBD_BIG_ENDIAN 4
+#define SAVAGE_GBD_LITTLE_ENDIAN 0
+#define SAVAGE_GBD_64 1
+
+/* Global Bitmap Descriptor */
+#define SAVAGE_BCI_GLB_BD_LOW 0x8168
+#define SAVAGE_BCI_GLB_BD_HIGH 0x816C
+
+/*
+ * BCI registers
+ */
+/* Savage4/Twister/ProSavage 3D registers */
+#define SAVAGE_DRAWLOCALCTRL_S4 0x1e
+#define SAVAGE_TEXPALADDR_S4 0x1f
+#define SAVAGE_TEXCTRL0_S4 0x20
+#define SAVAGE_TEXCTRL1_S4 0x21
+#define SAVAGE_TEXADDR0_S4 0x22
+#define SAVAGE_TEXADDR1_S4 0x23
+#define SAVAGE_TEXBLEND0_S4 0x24
+#define SAVAGE_TEXBLEND1_S4 0x25
+#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
+#define SAVAGE_TEXDESCR_S4 0x27
+#define SAVAGE_FOGTABLE_S4 0x28
+#define SAVAGE_FOGCTRL_S4 0x30
+#define SAVAGE_STENCILCTRL_S4 0x31
+#define SAVAGE_ZBUFCTRL_S4 0x32
+#define SAVAGE_ZBUFOFF_S4 0x33
+#define SAVAGE_DESTCTRL_S4 0x34
+#define SAVAGE_DRAWCTRL0_S4 0x35
+#define SAVAGE_DRAWCTRL1_S4 0x36
+#define SAVAGE_ZWATERMARK_S4 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S4 0x38
+#define SAVAGE_TEXBLENDCOLOR_S4 0x39
+/* Savage3D/MX/IX 3D registers */
+#define SAVAGE_TEXPALADDR_S3D 0x18
+#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
+#define SAVAGE_TEXADDR_S3D 0x1A
+#define SAVAGE_TEXDESCR_S3D 0x1B
+#define SAVAGE_TEXCTRL_S3D 0x1C
+#define SAVAGE_FOGTABLE_S3D 0x20
+#define SAVAGE_FOGCTRL_S3D 0x30
+#define SAVAGE_DRAWCTRL_S3D 0x31
+#define SAVAGE_ZBUFCTRL_S3D 0x32
+#define SAVAGE_ZBUFOFF_S3D 0x33
+#define SAVAGE_DESTCTRL_S3D 0x34
+#define SAVAGE_SCSTART_S3D 0x35
+#define SAVAGE_SCEND_S3D 0x36
+#define SAVAGE_ZWATERMARK_S3D 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
+/* common stuff */
+#define SAVAGE_VERTBUFADDR 0x3e
+#define SAVAGE_BITPLANEWTMASK 0xd7
+#define SAVAGE_DMABUFADDR 0x51
+
+/* texture enable bits (needed for tex addr checking) */
+#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */
+#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */
+#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */
+
+/* Global fields in Savage4/Twister/ProSavage 3D registers:
+ *
+ * All texture registers and DrawLocalCtrl are local. All other
+ * registers are global. */
+
+/* Global fields in Savage3D/MX/IX 3D registers:
+ *
+ * All texture registers are local. DrawCtrl and ZBufCtrl are
+ * partially local. All other registers are global.
+ *
+ * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
+ * ZBufCtrl global fields: zCmpFunc, zBufEn
+ */
+#define SAVAGE_DRAWCTRL_S3D_GLOBAL 0x03f3c00c
+#define SAVAGE_ZBUFCTRL_S3D_GLOBAL 0x00000027
+
+/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
+ */
+#define SAVAGE_SCISSOR_MASK_S4 0x00fff7ff
+#define SAVAGE_SCISSOR_MASK_S3D 0x07ff07ff
+
+/*
+ * BCI commands
+ */
+#define BCI_CMD_NOP 0x40000000
+#define BCI_CMD_RECT 0x48000000
+#define BCI_CMD_RECT_XP 0x01000000
+#define BCI_CMD_RECT_YP 0x02000000
+#define BCI_CMD_SCANLINE 0x50000000
+#define BCI_CMD_LINE 0x5C000000
+#define BCI_CMD_LINE_LAST_PIXEL 0x58000000
+#define BCI_CMD_BYTE_TEXT 0x63000000
+#define BCI_CMD_NT_BYTE_TEXT 0x67000000
+#define BCI_CMD_BIT_TEXT 0x6C000000
+#define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR 0x00008000
+
+#define BCI_CMD_CLIP_NONE 0x00000000
+#define BCI_CMD_CLIP_CURRENT 0x00002000
+#define BCI_CMD_CLIP_LR 0x00004000
+#define BCI_CMD_CLIP_NEW 0x00006000
+
+#define BCI_CMD_DEST_GBD 0x00000000
+#define BCI_CMD_DEST_PBD 0x00000800
+#define BCI_CMD_DEST_PBD_NEW 0x00000C00
+#define BCI_CMD_DEST_SBD 0x00001000
+#define BCI_CMD_DEST_SBD_NEW 0x00001400
+
+#define BCI_CMD_SRC_TRANSPARENT 0x00000200
+#define BCI_CMD_SRC_SOLID 0x00000000
+#define BCI_CMD_SRC_GBD 0x00000020
+#define BCI_CMD_SRC_COLOR 0x00000040
+#define BCI_CMD_SRC_MONO 0x00000060
+#define BCI_CMD_SRC_PBD_COLOR 0x00000080
+#define BCI_CMD_SRC_PBD_MONO 0x000000A0
+#define BCI_CMD_SRC_PBD_COLOR_NEW 0x000000C0
+#define BCI_CMD_SRC_PBD_MONO_NEW 0x000000E0
+#define BCI_CMD_SRC_SBD_COLOR 0x00000100
+#define BCI_CMD_SRC_SBD_MONO 0x00000120
+#define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140
+#define BCI_CMD_SRC_SBD_MONO_NEW 0x00000160
+
+#define BCI_CMD_PAT_TRANSPARENT 0x00000010
+#define BCI_CMD_PAT_NONE 0x00000000
+#define BCI_CMD_PAT_COLOR 0x00000002
+#define BCI_CMD_PAT_MONO 0x00000003
+#define BCI_CMD_PAT_PBD_COLOR 0x00000004
+#define BCI_CMD_PAT_PBD_MONO 0x00000005
+#define BCI_CMD_PAT_PBD_COLOR_NEW 0x00000006
+#define BCI_CMD_PAT_PBD_MONO_NEW 0x00000007
+#define BCI_CMD_PAT_SBD_COLOR 0x00000008
+#define BCI_CMD_PAT_SBD_MONO 0x00000009
+#define BCI_CMD_PAT_SBD_COLOR_NEW 0x0000000A
+#define BCI_CMD_PAT_SBD_MONO_NEW 0x0000000B
+
+#define BCI_BD_BW_DISABLE 0x10000000
+#define BCI_BD_TILE_MASK 0x03000000
+#define BCI_BD_TILE_NONE 0x00000000
+#define BCI_BD_TILE_16 0x02000000
+#define BCI_BD_TILE_32 0x03000000
+#define BCI_BD_GET_BPP(bd) (((bd) >> 16) & 0xFF)
+#define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF)
+#define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF))
+
+#define BCI_CMD_SET_REGISTER 0x96000000
+
+#define BCI_CMD_WAIT 0xC0000000
+#define BCI_CMD_WAIT_3D 0x00010000
+#define BCI_CMD_WAIT_2D 0x00020000
+
+#define BCI_CMD_UPDATE_EVENT_TAG 0x98000000
+
+#define BCI_CMD_DRAW_PRIM 0x80000000
+#define BCI_CMD_DRAW_INDEXED_PRIM 0x88000000
+#define BCI_CMD_DRAW_CONT 0x01000000
+#define BCI_CMD_DRAW_TRILIST 0x00000000
+#define BCI_CMD_DRAW_TRISTRIP 0x02000000
+#define BCI_CMD_DRAW_TRIFAN 0x04000000
+#define BCI_CMD_DRAW_SKIPFLAGS 0x000000ff
+#define BCI_CMD_DRAW_NO_Z 0x00000001
+#define BCI_CMD_DRAW_NO_W 0x00000002
+#define BCI_CMD_DRAW_NO_CD 0x00000004
+#define BCI_CMD_DRAW_NO_CS 0x00000008
+#define BCI_CMD_DRAW_NO_U0 0x00000010
+#define BCI_CMD_DRAW_NO_V0 0x00000020
+#define BCI_CMD_DRAW_NO_UV0 0x00000030
+#define BCI_CMD_DRAW_NO_U1 0x00000040
+#define BCI_CMD_DRAW_NO_V1 0x00000080
+#define BCI_CMD_DRAW_NO_UV1 0x000000c0
+
+#define BCI_CMD_DMA 0xa8000000
+
+#define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF)
+#define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_CLIP_LR(l, r) ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l) ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r) ((((b) << 16) | (r)) & 0x0FFF0FFF)
+
+#define BCI_LINE_X_Y(x, y) (((y) << 16) | ((x) & 0xFFFF))
+#define BCI_LINE_STEPS(diag, axi) (((axi) << 16) | ((diag) & 0xFFFF))
+#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
+ (((maj) & 0x1FFF) | \
+ ((ym) ? 1<<13 : 0) | \
+ ((xp) ? 1<<14 : 0) | \
+ ((yp) ? 1<<15 : 0) | \
+ ((err) << 16))
+
+/*
+ * common commands
+ */
+#define BCI_SET_REGISTERS( first, n ) \
+ BCI_WRITE(BCI_CMD_SET_REGISTER | \
+ ((uint32_t)(n) & 0xff) << 16 | \
+ ((uint32_t)(first) & 0xffff))
+#define DMA_SET_REGISTERS( first, n ) \
+ DMA_WRITE(BCI_CMD_SET_REGISTER | \
+ ((uint32_t)(n) & 0xff) << 16 | \
+ ((uint32_t)(first) & 0xffff))
+
+#define BCI_DRAW_PRIMITIVE(n, type, skip) \
+ BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+ ((n) << 16))
+#define DMA_DRAW_PRIMITIVE(n, type, skip) \
+ DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+ ((n) << 16))
+
+#define BCI_DRAW_INDICES_S3D(n, type, i0) \
+ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
+ ((n) << 16) | (i0))
+
+#define BCI_DRAW_INDICES_S4(n, type, skip) \
+ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
+ (skip) | ((n) << 16))
+
+#define BCI_DMA(n) \
+ BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
+
+/*
+ * access to MMIO
+ */
+#define SAVAGE_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
+#define SAVAGE_WRITE(reg) DRM_WRITE32( dev_priv->mmio, (reg) )
+
+/*
+ * access to the burst command interface (BCI)
+ */
+#define SAVAGE_BCI_DEBUG 1
+
+#define BCI_LOCALS volatile uint32_t *bci_ptr;
+
+#define BEGIN_BCI( n ) do { \
+ dev_priv->wait_fifo(dev_priv, (n)); \
+ bci_ptr = dev_priv->bci_ptr; \
+} while(0)
+
+#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
+
+#define BCI_COPY_FROM_USER(src,n) do { \
+ unsigned int i; \
+ for (i = 0; i < n; ++i) { \
+ uint32_t val; \
+ DRM_GET_USER_UNCHECKED(val, &((uint32_t*)(src))[i]); \
+ BCI_WRITE(val); \
+ } \
+} while(0)
+
+/*
+ * command DMA support
+ */
+#define SAVAGE_DMA_DEBUG 1
+
+#define DMA_LOCALS uint32_t *dma_ptr;
+
+#define BEGIN_DMA( n ) do { \
+ unsigned int cur = dev_priv->current_dma_page; \
+ unsigned int rest = SAVAGE_DMA_PAGE_SIZE - \
+ dev_priv->dma_pages[cur].used; \
+ if ((n) > rest) { \
+ dma_ptr = savage_dma_alloc(dev_priv, (n)); \
+ } else { /* fast path for small allocations */ \
+ dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + \
+ cur * SAVAGE_DMA_PAGE_SIZE + \
+ dev_priv->dma_pages[cur].used; \
+ if (dev_priv->dma_pages[cur].used == 0) \
+ savage_dma_wait(dev_priv, cur); \
+ dev_priv->dma_pages[cur].used += (n); \
+ } \
+} while(0)
+
+#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
+
+#define DMA_COPY_FROM_USER(src,n) do { \
+ DRM_COPY_FROM_USER_UNCHECKED(dma_ptr, (src), (n)*4); \
+ dma_ptr += n; \
+} while(0)
+
+#if SAVAGE_DMA_DEBUG
+#define DMA_COMMIT() do { \
+ unsigned int cur = dev_priv->current_dma_page; \
+ uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle + \
+ cur * SAVAGE_DMA_PAGE_SIZE + \
+ dev_priv->dma_pages[cur].used; \
+ if (dma_ptr != expected) { \
+ DRM_ERROR("DMA allocation and use don't match: " \
+ "%p != %p\n", expected, dma_ptr); \
+ savage_dma_reset(dev_priv); \
+ } \
+} while(0)
+#else
+#define DMA_COMMIT() do {/* nothing */} while(0)
+#endif
+
+#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
+
+/* Buffer aging via event tag
+ */
+
+#define UPDATE_EVENT_COUNTER( ) do { \
+ if (dev_priv->status_ptr) { \
+ uint16_t count; \
+ /* coordinate with Xserver */ \
+ count = dev_priv->status_ptr[1023]; \
+ if (count < dev_priv->event_counter) \
+ dev_priv->event_wrap++; \
+ dev_priv->event_counter = count; \
+ } \
+} while(0)
+
+#define SET_AGE( age, e, w ) do { \
+ (age)->event = e; \
+ (age)->wrap = w; \
+} while(0)
+
+#define TEST_AGE( age, e, w ) \
+ ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
+
+#endif /* __SAVAGE_DRV_H__ */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
new file mode 100644
index 000000000000..475695a00083
--- /dev/null
+++ b/drivers/char/drm/savage_state.c
@@ -0,0 +1,1146 @@
+/* savage_state.c -- State and drawing support for Savage
+ *
+ * Copyright 2004 Felix Kuehling
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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 "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+ drm_clip_rect_t *pbox)
+{
+ uint32_t scstart = dev_priv->state.s3d.new_scstart;
+ uint32_t scend = dev_priv->state.s3d.new_scend;
+ scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
+ ((uint32_t)pbox->x1 & 0x000007ff) |
+ (((uint32_t)pbox->y1 << 16) & 0x07ff0000);
+ scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
+ (((uint32_t)pbox->x2-1) & 0x000007ff) |
+ ((((uint32_t)pbox->y2-1) << 16) & 0x07ff0000);
+ if (scstart != dev_priv->state.s3d.scstart ||
+ scend != dev_priv->state.s3d.scend) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+ DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
+ DMA_WRITE(scstart);
+ DMA_WRITE(scend);
+ dev_priv->state.s3d.scstart = scstart;
+ dev_priv->state.s3d.scend = scend;
+ dev_priv->waiting = 1;
+ DMA_COMMIT();
+ }
+}
+
+void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+ drm_clip_rect_t *pbox)
+{
+ uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
+ uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
+ drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
+ ((uint32_t)pbox->x1 & 0x000007ff) |
+ (((uint32_t)pbox->y1 << 12) & 0x00fff000);
+ drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
+ (((uint32_t)pbox->x2-1) & 0x000007ff) |
+ ((((uint32_t)pbox->y2-1) << 12) & 0x00fff000);
+ if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
+ drawctrl1 != dev_priv->state.s4.drawctrl1) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+ DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
+ DMA_WRITE(drawctrl0);
+ DMA_WRITE(drawctrl1);
+ dev_priv->state.s4.drawctrl0 = drawctrl0;
+ dev_priv->state.s4.drawctrl1 = drawctrl1;
+ dev_priv->waiting = 1;
+ DMA_COMMIT();
+ }
+}
+
+static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
+ uint32_t addr)
+{
+ if ((addr & 6) != 2) { /* reserved bits */
+ DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ if (!(addr & 1)) { /* local */
+ addr &= ~7;
+ if (addr < dev_priv->texture_offset ||
+ addr >= dev_priv->texture_offset+dev_priv->texture_size) {
+ DRM_ERROR("bad texAddr%d %08x (local addr out of range)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ } else { /* AGP */
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ addr &= ~7;
+ if (addr < dev_priv->agp_textures->offset ||
+ addr >= (dev_priv->agp_textures->offset +
+ dev_priv->agp_textures->size)) {
+ DRM_ERROR("bad texAddr%d %08x (AGP addr out of range)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+#define SAVE_STATE(reg,where) \
+ if(start <= reg && start+count > reg) \
+ DRM_GET_USER_UNCHECKED(dev_priv->state.where, &regs[reg-start])
+#define SAVE_STATE_MASK(reg,where,mask) do { \
+ if(start <= reg && start+count > reg) { \
+ uint32_t tmp; \
+ DRM_GET_USER_UNCHECKED(tmp, &regs[reg-start]); \
+ dev_priv->state.where = (tmp & (mask)) | \
+ (dev_priv->state.where & ~(mask)); \
+ } \
+} while (0)
+static int savage_verify_state_s3d(drm_savage_private_t *dev_priv,
+ unsigned int start, unsigned int count,
+ const uint32_t __user *regs)
+{
+ if (start < SAVAGE_TEXPALADDR_S3D ||
+ start+count-1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+ start, start+count-1);
+ return DRM_ERR(EINVAL);
+ }
+
+ SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
+ ~SAVAGE_SCISSOR_MASK_S3D);
+ SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend,
+ ~SAVAGE_SCISSOR_MASK_S3D);
+
+ /* if any texture regs were changed ... */
+ if (start <= SAVAGE_TEXCTRL_S3D &&
+ start+count > SAVAGE_TEXPALADDR_S3D) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
+ SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
+ if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
+ return savage_verify_texaddr(
+ dev_priv, 0, dev_priv->state.s3d.texaddr);
+ }
+
+ return 0;
+}
+
+static int savage_verify_state_s4(drm_savage_private_t *dev_priv,
+ unsigned int start, unsigned int count,
+ const uint32_t __user *regs)
+{
+ int ret = 0;
+
+ if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
+ start+count-1 > SAVAGE_TEXBLENDCOLOR_S4) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+ start, start+count-1);
+ return DRM_ERR(EINVAL);
+ }
+
+ SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
+ ~SAVAGE_SCISSOR_MASK_S4);
+ SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1,
+ ~SAVAGE_SCISSOR_MASK_S4);
+
+ /* if any texture regs were changed ... */
+ if (start <= SAVAGE_TEXDESCR_S4 &&
+ start+count > SAVAGE_TEXPALADDR_S4) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
+ SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
+ SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
+ ret |= savage_verify_texaddr(
+ dev_priv, 0, dev_priv->state.s4.texaddr0);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
+ ret |= savage_verify_texaddr(
+ dev_priv, 1, dev_priv->state.s4.texaddr1);
+ }
+
+ return ret;
+}
+#undef SAVE_STATE
+#undef SAVE_STATE_MASK
+
+static int savage_dispatch_state(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const uint32_t __user *regs)
+{
+ unsigned int count = cmd_header->state.count;
+ unsigned int start = cmd_header->state.start;
+ unsigned int count2 = 0;
+ unsigned int bci_size;
+ int ret;
+ DMA_LOCALS;
+
+ if (!count)
+ return 0;
+
+ if (DRM_VERIFYAREA_READ(regs, count*4))
+ return DRM_ERR(EFAULT);
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ ret = savage_verify_state_s3d(dev_priv, start, count, regs);
+ if (ret != 0)
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_SCSTART_S3D) {
+ if (start+count > SAVAGE_SCEND_S3D+1)
+ count2 = count - (SAVAGE_SCEND_S3D+1 - start);
+ if (start+count > SAVAGE_SCSTART_S3D)
+ count = SAVAGE_SCSTART_S3D - start;
+ } else if (start <= SAVAGE_SCEND_S3D) {
+ if (start+count > SAVAGE_SCEND_S3D+1) {
+ count -= SAVAGE_SCEND_S3D+1 - start;
+ start = SAVAGE_SCEND_S3D+1;
+ } else
+ return 0;
+ }
+ } else {
+ ret = savage_verify_state_s4(dev_priv, start, count, regs);
+ if (ret != 0)
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_DRAWCTRL0_S4) {
+ if (start+count > SAVAGE_DRAWCTRL1_S4+1)
+ count2 = count - (SAVAGE_DRAWCTRL1_S4+1 - start);
+ if (start+count > SAVAGE_DRAWCTRL0_S4)
+ count = SAVAGE_DRAWCTRL0_S4 - start;
+ } else if (start <= SAVAGE_DRAWCTRL1_S4) {
+ if (start+count > SAVAGE_DRAWCTRL1_S4+1) {
+ count -= SAVAGE_DRAWCTRL1_S4+1 - start;
+ start = SAVAGE_DRAWCTRL1_S4+1;
+ } else
+ return 0;
+ }
+ }
+
+ bci_size = count + (count+254)/255 + count2 + (count2+254)/255;
+
+ if (cmd_header->state.global) {
+ BEGIN_DMA(bci_size+1);
+ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ dev_priv->waiting = 1;
+ } else {
+ BEGIN_DMA(bci_size);
+ }
+
+ do {
+ while (count > 0) {
+ unsigned int n = count < 255 ? count : 255;
+ DMA_SET_REGISTERS(start, n);
+ DMA_COPY_FROM_USER(regs, n);
+ count -= n;
+ start += n;
+ regs += n;
+ }
+ start += 2;
+ regs += 2;
+ count = count2;
+ count2 = 0;
+ } while (count);
+
+ DMA_COMMIT();
+
+ return 0;
+}
+
+static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const drm_buf_t *dmabuf)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+ unsigned int skip = cmd_header->prim.skip;
+ unsigned int n = cmd_header->prim.count;
+ unsigned int start = cmd_header->prim.start;
+ unsigned int i;
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+ DRM_ERROR("called without dma buffers!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+ skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+ skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+ DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (start + n > dmabuf->total/32) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+ start, start + n - 1, dmabuf->total/32);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* Vertex DMA doesn't work with command DMA at the same time,
+ * so we use BCI_... to submit commands here. Flush buffered
+ * faked DMA first. */
+ DMA_FLUSH();
+
+ if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+ BEGIN_BCI(2);
+ BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+ BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+ dev_priv->state.common.vbaddr = dmabuf->bus_address;
+ }
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+ /* Workaround for what looks like a hardware bug. If a
+ * WAIT_3D_IDLE was emitted some time before the
+ * indexed drawing command then the engine will lock
+ * up. There are two known workarounds:
+ * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+ BEGIN_BCI(63);
+ for (i = 0; i < 63; ++i)
+ BCI_WRITE(BCI_CMD_WAIT);
+ dev_priv->waiting = 0;
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 indices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ if (reorder) {
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = {-1, -1, -1};
+ reorder[start%3] = 2;
+
+ BEGIN_BCI((count+1+1)/2);
+ BCI_DRAW_INDICES_S3D(count, prim, start+2);
+
+ for (i = start+1; i+1 < start+count; i += 2)
+ BCI_WRITE((i + reorder[i % 3]) |
+ ((i+1 + reorder[(i+1) % 3]) << 16));
+ if (i < start+count)
+ BCI_WRITE(i + reorder[i%3]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ BEGIN_BCI((count+1+1)/2);
+ BCI_DRAW_INDICES_S3D(count, prim, start);
+
+ for (i = start+1; i+1 < start+count; i += 2)
+ BCI_WRITE(i | ((i+1) << 16));
+ if (i < start+count)
+ BCI_WRITE(i);
+ } else {
+ BEGIN_BCI((count+2+1)/2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+ for (i = start; i+1 < start+count; i += 2)
+ BCI_WRITE(i | ((i+1) << 16));
+ if (i < start+count)
+ BCI_WRITE(i);
+ }
+
+ start += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const uint32_t __user *vtxbuf,
+ unsigned int vb_size,
+ unsigned int vb_stride)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+ unsigned int skip = cmd_header->prim.skip;
+ unsigned int n = cmd_header->prim.count;
+ unsigned int start = cmd_header->prim.start;
+ unsigned int vtx_size;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip > SAVAGE_SKIP_ALL_S3D) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+ vtx_size, vb_stride);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (start + n > vb_size / (vb_stride*4)) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+ start, start + n - 1, vb_size / (vb_stride*4));
+ return DRM_ERR(EINVAL);
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 vertices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ if (reorder) {
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = {-1, -1, -1};
+ reorder[start%3] = 2;
+
+ BEGIN_DMA(count*vtx_size+1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = start; i < start+count; ++i) {
+ unsigned int j = i + reorder[i % 3];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+ BEGIN_DMA(count*vtx_size+1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ if (vb_stride == vtx_size) {
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride*start],
+ vtx_size*count);
+ } else {
+ for (i = start; i < start+count; ++i) {
+ DMA_COPY_FROM_USER(
+ &vtxbuf[vb_stride*i],
+ vtx_size);
+ }
+ }
+
+ DMA_COMMIT();
+ }
+
+ start += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const uint16_t __user *usr_idx,
+ const drm_buf_t *dmabuf)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+ unsigned int skip = cmd_header->idx.skip;
+ unsigned int n = cmd_header->idx.count;
+ unsigned int i;
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+ DRM_ERROR("called without dma buffers!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of indices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+ skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+ skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+ DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ /* Vertex DMA doesn't work with command DMA at the same time,
+ * so we use BCI_... to submit commands here. Flush buffered
+ * faked DMA first. */
+ DMA_FLUSH();
+
+ if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+ BEGIN_BCI(2);
+ BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+ BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+ dev_priv->state.common.vbaddr = dmabuf->bus_address;
+ }
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+ /* Workaround for what looks like a hardware bug. If a
+ * WAIT_3D_IDLE was emitted some time before the
+ * indexed drawing command then the engine will lock
+ * up. There are two known workarounds:
+ * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+ BEGIN_BCI(63);
+ for (i = 0; i < 63; ++i)
+ BCI_WRITE(BCI_CMD_WAIT);
+ dev_priv->waiting = 0;
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 indices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ /* Is it ok to allocate 510 bytes on the stack in an ioctl? */
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2);
+ for (i = 0; i < count; ++i) {
+ if (idx[i] > dmabuf->total/32) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+ i, idx[i], dmabuf->total/32);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (reorder) {
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = {2, -1, -1};
+
+ BEGIN_BCI((count+1+1)/2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
+
+ for (i = 1; i+1 < count; i += 2)
+ BCI_WRITE(idx[i + reorder[i % 3]] |
+ (idx[i+1 + reorder[(i+1) % 3]] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i + reorder[i%3]]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ BEGIN_BCI((count+1+1)/2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
+
+ for (i = 1; i+1 < count; i += 2)
+ BCI_WRITE(idx[i] | (idx[i+1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ } else {
+ BEGIN_BCI((count+2+1)/2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+ for (i = 0; i+1 < count; i += 2)
+ BCI_WRITE(idx[i] | (idx[i+1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ }
+
+ usr_idx += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const uint16_t __user *usr_idx,
+ const uint32_t __user *vtxbuf,
+ unsigned int vb_size,
+ unsigned int vb_stride)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+ unsigned int skip = cmd_header->idx.skip;
+ unsigned int n = cmd_header->idx.count;
+ unsigned int vtx_size;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of indices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip > SAVAGE_SKIP_ALL_S3D) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+ vtx_size, vb_stride);
+ return DRM_ERR(EINVAL);
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 vertices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ /* Is it ok to allocate 510 bytes on the stack in an ioctl? */
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2);
+ for (i = 0; i < count; ++i) {
+ if (idx[i] > vb_size / (vb_stride*4)) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+ i, idx[i], vb_size / (vb_stride*4));
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (reorder) {
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = {2, -1, -1};
+
+ BEGIN_DMA(count*vtx_size+1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i + reorder[i % 3]];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+ BEGIN_DMA(count*vtx_size+1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ }
+
+ usr_idx += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_clear(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t *cmd_header,
+ const drm_savage_cmd_header_t __user *data,
+ unsigned int nbox,
+ const drm_clip_rect_t __user *usr_boxes)
+{
+ unsigned int flags = cmd_header->clear0.flags, mask, value;
+ unsigned int clear_cmd;
+ unsigned int i, nbufs;
+ DMA_LOCALS;
+
+ if (nbox == 0)
+ return 0;
+
+ DRM_GET_USER_UNCHECKED(mask, &((const drm_savage_cmd_header_t*)data)
+ ->clear1.mask);
+ DRM_GET_USER_UNCHECKED(value, &((const drm_savage_cmd_header_t*)data)
+ ->clear1.value);
+
+ clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+ BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
+ BCI_CMD_SET_ROP(clear_cmd,0xCC);
+
+ nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
+ ((flags & SAVAGE_BACK) ? 1 : 0) +
+ ((flags & SAVAGE_DEPTH) ? 1 : 0);
+ if (nbufs == 0)
+ return 0;
+
+ if (mask != 0xffffffff) {
+ /* set mask */
+ BEGIN_DMA(2);
+ DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+ DMA_WRITE(mask);
+ DMA_COMMIT();
+ }
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ unsigned int x, y, w, h;
+ unsigned int buf;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+ x = box.x1, y = box.y1;
+ w = box.x2 - box.x1;
+ h = box.y2 - box.y1;
+ BEGIN_DMA(nbufs*6);
+ for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
+ if (!(flags & buf))
+ continue;
+ DMA_WRITE(clear_cmd);
+ switch(buf) {
+ case SAVAGE_FRONT:
+ DMA_WRITE(dev_priv->front_offset);
+ DMA_WRITE(dev_priv->front_bd);
+ break;
+ case SAVAGE_BACK:
+ DMA_WRITE(dev_priv->back_offset);
+ DMA_WRITE(dev_priv->back_bd);
+ break;
+ case SAVAGE_DEPTH:
+ DMA_WRITE(dev_priv->depth_offset);
+ DMA_WRITE(dev_priv->depth_bd);
+ break;
+ }
+ DMA_WRITE(value);
+ DMA_WRITE(BCI_X_Y(x, y));
+ DMA_WRITE(BCI_W_H(w, h));
+ }
+ DMA_COMMIT();
+ }
+ if (mask != 0xffffffff) {
+ /* reset mask */
+ BEGIN_DMA(2);
+ DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+ DMA_WRITE(0xffffffff);
+ DMA_COMMIT();
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_swap(drm_savage_private_t *dev_priv,
+ unsigned int nbox,
+ const drm_clip_rect_t __user *usr_boxes)
+{
+ unsigned int swap_cmd;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (nbox == 0)
+ return 0;
+
+ swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+ BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
+ BCI_CMD_SET_ROP(swap_cmd,0xCC);
+
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+
+ BEGIN_DMA(6);
+ DMA_WRITE(swap_cmd);
+ DMA_WRITE(dev_priv->back_offset);
+ DMA_WRITE(dev_priv->back_bd);
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+ DMA_WRITE(BCI_W_H(box.x2-box.x1, box.y2-box.y1));
+ DMA_COMMIT();
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
+ const drm_savage_cmd_header_t __user *start,
+ const drm_savage_cmd_header_t __user *end,
+ const drm_buf_t *dmabuf,
+ const unsigned int __user *usr_vtxbuf,
+ unsigned int vb_size, unsigned int vb_stride,
+ unsigned int nbox,
+ const drm_clip_rect_t __user *usr_boxes)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ const drm_savage_cmd_header_t __user *usr_cmdbuf;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+ dev_priv->emit_clip_rect(dev_priv, &box);
+
+ usr_cmdbuf = start;
+ while (usr_cmdbuf < end) {
+ drm_savage_cmd_header_t cmd_header;
+ DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
+ sizeof(cmd_header));
+ usr_cmdbuf++;
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_DMA_PRIM:
+ ret = savage_dispatch_dma_prim(
+ dev_priv, &cmd_header, dmabuf);
+ break;
+ case SAVAGE_CMD_VB_PRIM:
+ ret = savage_dispatch_vb_prim(
+ dev_priv, &cmd_header,
+ (const uint32_t __user *)usr_vtxbuf,
+ vb_size, vb_stride);
+ break;
+ case SAVAGE_CMD_DMA_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+ ret = savage_dispatch_dma_idx(
+ dev_priv, &cmd_header,
+ (const uint16_t __user *)usr_cmdbuf,
+ dmabuf);
+ usr_cmdbuf += j;
+ break;
+ case SAVAGE_CMD_VB_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+ ret = savage_dispatch_vb_idx(
+ dev_priv, &cmd_header,
+ (const uint16_t __user *)usr_cmdbuf,
+ (const uint32_t __user *)usr_vtxbuf,
+ vb_size, vb_stride);
+ usr_cmdbuf += j;
+ break;
+ default:
+ /* What's the best return code? EFAULT? */
+ DRM_ERROR("IMPLEMENTATION ERROR: "
+ "non-drawing-command %d\n",
+ cmd_header.cmd.cmd);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *dmabuf;
+ drm_savage_cmdbuf_t cmdbuf;
+ drm_savage_cmd_header_t __user *usr_cmdbuf;
+ drm_savage_cmd_header_t __user *first_draw_cmd;
+ unsigned int __user *usr_vtxbuf;
+ drm_clip_rect_t __user *usr_boxes;
+ unsigned int i, j;
+ int ret = 0;
+
+ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data,
+ sizeof(cmdbuf));
+
+ if (dma && dma->buflist) {
+ if (cmdbuf.dma_idx > dma->buf_count) {
+ DRM_ERROR("vertex buffer index %u out of range (0-%u)\n",
+ cmdbuf.dma_idx, dma->buf_count-1);
+ return DRM_ERR(EINVAL);
+ }
+ dmabuf = dma->buflist[cmdbuf.dma_idx];
+ } else {
+ dmabuf = NULL;
+ }
+
+ usr_cmdbuf = (drm_savage_cmd_header_t __user *)cmdbuf.cmd_addr;
+ usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr;
+ usr_boxes = (drm_clip_rect_t __user *)cmdbuf.box_addr;
+ if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size*8)) ||
+ (cmdbuf.vb_size && DRM_VERIFYAREA_READ(
+ usr_vtxbuf, cmdbuf.vb_size)) ||
+ (cmdbuf.nbox && DRM_VERIFYAREA_READ(
+ usr_boxes, cmdbuf.nbox*sizeof(drm_clip_rect_t))))
+ return DRM_ERR(EFAULT);
+
+ /* Make sure writes to DMA buffers are finished before sending
+ * DMA commands to the graphics hardware. */
+ DRM_MEMORYBARRIER();
+
+ /* Coming from user space. Don't know if the Xserver has
+ * emitted wait commands. Assuming the worst. */
+ dev_priv->waiting = 1;
+
+ i = 0;
+ first_draw_cmd = NULL;
+ while (i < cmdbuf.size) {
+ drm_savage_cmd_header_t cmd_header;
+ DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
+ sizeof(cmd_header));
+ usr_cmdbuf++;
+ i++;
+
+ /* Group drawing commands with same state to minimize
+ * iterations over clip rects. */
+ j = 0;
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_DMA_IDX:
+ case SAVAGE_CMD_VB_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ if (i + j > cmdbuf.size) {
+ DRM_ERROR("indexed drawing command extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ /* fall through */
+ case SAVAGE_CMD_DMA_PRIM:
+ case SAVAGE_CMD_VB_PRIM:
+ if (!first_draw_cmd)
+ first_draw_cmd = usr_cmdbuf-1;
+ usr_cmdbuf += j;
+ i += j;
+ break;
+ default:
+ if (first_draw_cmd) {
+ ret = savage_dispatch_draw (
+ dev_priv, first_draw_cmd, usr_cmdbuf-1,
+ dmabuf, usr_vtxbuf, cmdbuf.vb_size,
+ cmdbuf.vb_stride,
+ cmdbuf.nbox, usr_boxes);
+ if (ret != 0)
+ return ret;
+ first_draw_cmd = NULL;
+ }
+ }
+ if (first_draw_cmd)
+ continue;
+
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_STATE:
+ j = (cmd_header.state.count + 1) / 2;
+ if (i + j > cmdbuf.size) {
+ DRM_ERROR("command SAVAGE_CMD_STATE extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ ret = savage_dispatch_state(
+ dev_priv, &cmd_header,
+ (uint32_t __user *)usr_cmdbuf);
+ usr_cmdbuf += j;
+ i += j;
+ break;
+ case SAVAGE_CMD_CLEAR:
+ if (i + 1 > cmdbuf.size) {
+ DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ ret = savage_dispatch_clear(dev_priv, &cmd_header,
+ usr_cmdbuf,
+ cmdbuf.nbox, usr_boxes);
+ usr_cmdbuf++;
+ i++;
+ break;
+ case SAVAGE_CMD_SWAP:
+ ret = savage_dispatch_swap(dev_priv,
+ cmdbuf.nbox, usr_boxes);
+ break;
+ default:
+ DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+
+ if (ret != 0) {
+ DMA_FLUSH();
+ return ret;
+ }
+ }
+
+ if (first_draw_cmd) {
+ ret = savage_dispatch_draw (
+ dev_priv, first_draw_cmd, usr_cmdbuf, dmabuf,
+ usr_vtxbuf, cmdbuf.vb_size, cmdbuf.vb_stride,
+ cmdbuf.nbox, usr_boxes);
+ if (ret != 0) {
+ DMA_FLUSH();
+ return ret;
+ }
+ }
+
+ DMA_FLUSH();
+
+ if (dmabuf && cmdbuf.discard) {
+ drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
+ uint16_t event;
+ event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+ SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+ savage_freelist_put(dev, dmabuf);
+ }
+
+ return 0;
+}
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 6025e1866c7e..58d3738a2b7f 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -6,6 +6,8 @@
For technical support please email digiLinux@dgii.com or
call Digi tech support at (612) 912-3456
+ ** This driver is no longer supported by Digi **
+
Much of this design and code came from epca.c which was
copyright (C) 1994, 1995 Troy De Jongh, and subsquently
modified by David Nugent, Christoph Lameter, Mike McLagan.
@@ -43,31 +45,19 @@
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif /* CONFIG_PCI */
-
-#define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2)
-#define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2)
-
-#ifdef ENABLE_PCI
+#include <linux/spinlock.h>
#include <linux/pci.h>
#include "digiPCI.h"
-#endif /* ENABLE_PCI */
+
#include "digi1.h"
#include "digiFep1.h"
#include "epca.h"
#include "epcaconfig.h"
-#if BITS_PER_LONG != 32
-# error FIXME: this driver only works on 32-bit platforms
-#endif
-
/* ---------------------- Begin defines ------------------------ */
-#define VERSION "1.3.0.1-LK"
+#define VERSION "1.3.0.1-LK2.6"
/* This major needs to be submitted to Linux to join the majors list */
@@ -81,13 +71,17 @@
/* ----------------- Begin global definitions ------------------- */
-static char mesg[100];
static int nbdevs, num_cards, liloconfig;
static int digi_poller_inhibited = 1 ;
static int setup_error_code;
static int invalid_lilo_config;
+/* The ISA boards do window flipping into the same spaces so its only sane
+ with a single lock. It's still pretty efficient */
+
+static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED;
+
/* -----------------------------------------------------------------------
MAXBOARDS is typically 12, but ISA and EISA cards are restricted to
7 below.
@@ -129,58 +123,58 @@ static struct timer_list epca_timer;
configured.
----------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win);
-static inline void memwinoff(struct board_info *b, unsigned int win);
-static inline void globalwinon(struct channel *ch);
-static inline void rxwinon(struct channel *ch);
-static inline void txwinon(struct channel *ch);
-static inline void memoff(struct channel *ch);
-static inline void assertgwinon(struct channel *ch);
-static inline void assertmemoff(struct channel *ch);
+static void memwinon(struct board_info *b, unsigned int win);
+static void memwinoff(struct board_info *b, unsigned int win);
+static void globalwinon(struct channel *ch);
+static void rxwinon(struct channel *ch);
+static void txwinon(struct channel *ch);
+static void memoff(struct channel *ch);
+static void assertgwinon(struct channel *ch);
+static void assertmemoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for cx_like products --- */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxem_globalwinon(struct channel *ch);
-static inline void pcxem_rxwinon(struct channel *ch);
-static inline void pcxem_txwinon(struct channel *ch);
-static inline void pcxem_memoff(struct channel *ch);
+static void pcxem_memwinon(struct board_info *b, unsigned int win);
+static void pcxem_memwinoff(struct board_info *b, unsigned int win);
+static void pcxem_globalwinon(struct channel *ch);
+static void pcxem_rxwinon(struct channel *ch);
+static void pcxem_txwinon(struct channel *ch);
+static void pcxem_memoff(struct channel *ch);
/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxe_globalwinon(struct channel *ch);
-static inline void pcxe_rxwinon(struct channel *ch);
-static inline void pcxe_txwinon(struct channel *ch);
-static inline void pcxe_memoff(struct channel *ch);
+static void pcxe_memwinon(struct board_info *b, unsigned int win);
+static void pcxe_memwinoff(struct board_info *b, unsigned int win);
+static void pcxe_globalwinon(struct channel *ch);
+static void pcxe_rxwinon(struct channel *ch);
+static void pcxe_txwinon(struct channel *ch);
+static void pcxe_memoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
/* Note : pc64xe and pcxi share the same windowing routines */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxi_globalwinon(struct channel *ch);
-static inline void pcxi_rxwinon(struct channel *ch);
-static inline void pcxi_txwinon(struct channel *ch);
-static inline void pcxi_memoff(struct channel *ch);
+static void pcxi_memwinon(struct board_info *b, unsigned int win);
+static void pcxi_memwinoff(struct board_info *b, unsigned int win);
+static void pcxi_globalwinon(struct channel *ch);
+static void pcxi_rxwinon(struct channel *ch);
+static void pcxi_txwinon(struct channel *ch);
+static void pcxi_memoff(struct channel *ch);
/* - Begin 'specific' do nothing memory functions needed for some cards - */
-static inline void dummy_memwinon(struct board_info *b, unsigned int win);
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win);
-static inline void dummy_globalwinon(struct channel *ch);
-static inline void dummy_rxwinon(struct channel *ch);
-static inline void dummy_txwinon(struct channel *ch);
-static inline void dummy_memoff(struct channel *ch);
-static inline void dummy_assertgwinon(struct channel *ch);
-static inline void dummy_assertmemoff(struct channel *ch);
+static void dummy_memwinon(struct board_info *b, unsigned int win);
+static void dummy_memwinoff(struct board_info *b, unsigned int win);
+static void dummy_globalwinon(struct channel *ch);
+static void dummy_rxwinon(struct channel *ch);
+static void dummy_txwinon(struct channel *ch);
+static void dummy_memoff(struct channel *ch);
+static void dummy_assertgwinon(struct channel *ch);
+static void dummy_assertmemoff(struct channel *ch);
/* ------------------- Begin declare functions ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *);
-static inline void pc_sched_event(struct channel *, int);
+static struct channel *verifyChannel(struct tty_struct *);
+static void pc_sched_event(struct channel *, int);
static void epca_error(int, char *);
static void pc_close(struct tty_struct *, struct file *);
static void shutdown(struct channel *);
@@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty);
static void digi_send_break(struct channel *ch, int msec);
static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
void epca_setup(char *, int *);
-void console_print(const char *);
static int get_termio(struct tty_struct *, struct termio __user *);
static int pc_write(struct tty_struct *, const unsigned char *, int);
-int pc_init(void);
-
-#ifdef ENABLE_PCI
+static int pc_init(void);
static int init_PCI(void);
-#endif /* ENABLE_PCI */
/* ------------------------------------------------------------------
@@ -237,41 +227,41 @@ static int init_PCI(void);
making direct calls deserves what they get.
-------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win)
+static void memwinon(struct board_info *b, unsigned int win)
{
(b->memwinon)(b, win);
}
-static inline void memwinoff(struct board_info *b, unsigned int win)
+static void memwinoff(struct board_info *b, unsigned int win)
{
(b->memwinoff)(b, win);
}
-static inline void globalwinon(struct channel *ch)
+static void globalwinon(struct channel *ch)
{
(ch->board->globalwinon)(ch);
}
-static inline void rxwinon(struct channel *ch)
+static void rxwinon(struct channel *ch)
{
(ch->board->rxwinon)(ch);
}
-static inline void txwinon(struct channel *ch)
+static void txwinon(struct channel *ch)
{
(ch->board->txwinon)(ch);
}
-static inline void memoff(struct channel *ch)
+static void memoff(struct channel *ch)
{
(ch->board->memoff)(ch);
}
-static inline void assertgwinon(struct channel *ch)
+static void assertgwinon(struct channel *ch)
{
(ch->board->assertgwinon)(ch);
}
-static inline void assertmemoff(struct channel *ch)
+static void assertmemoff(struct channel *ch)
{
(ch->board->assertmemoff)(ch);
}
@@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch)
and CX series cards.
------------------------------------------------------------ */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win)
+static void pcxem_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN|win, (int)b->port + 1);
+ outb_p(FEPWIN|win, b->port + 1);
}
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win)
+static void pcxem_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(0, (int)b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxem_globalwinon(struct channel *ch)
+static void pcxem_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxem_rxwinon(struct channel *ch)
+static void pcxem_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxem_txwinon(struct channel *ch)
+static void pcxem_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxem_memoff(struct channel *ch)
+static void pcxem_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port + 1);
}
/* ----------------- Begin pcxe memory window stuff ------------------ */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win)
+static void pcxe_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN | win, (int)b->port + 1);
+ outb_p(FEPWIN | win, b->port + 1);
}
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win)
+static void pcxe_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM,
- (int)b->port + 1);
- outb_p(0, (int)b->port + 1);
+ outb_p(inb(b->port) & ~FEPMEM,
+ b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxe_globalwinon(struct channel *ch)
+static void pcxe_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxe_rxwinon(struct channel *ch)
+static void pcxe_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxe_txwinon(struct channel *ch)
+static void pcxe_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxe_memoff(struct channel *ch)
+static void pcxe_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port);
outb_p(0, (int)ch->board->port + 1);
@@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch)
/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win)
+static void pcxi_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) | FEPMEM, (int)b->port);
+ outb_p(inb(b->port) | FEPMEM, b->port);
}
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win)
+static void pcxi_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port);
+ outb_p(inb(b->port) & ~FEPMEM, b->port);
}
-static inline void pcxi_globalwinon(struct channel *ch)
+static void pcxi_globalwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_rxwinon(struct channel *ch)
+static void pcxi_rxwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_txwinon(struct channel *ch)
+static void pcxi_txwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_memoff(struct channel *ch)
+static void pcxi_memoff(struct channel *ch)
{
- outb_p(0, (int)ch->board->port);
+ outb_p(0, ch->board->port);
}
-static inline void pcxi_assertgwinon(struct channel *ch)
+static void pcxi_assertgwinon(struct channel *ch)
{
- epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off");
+ epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
}
-static inline void pcxi_assertmemoff(struct channel *ch)
+static void pcxi_assertmemoff(struct channel *ch)
{
- epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on");
+ epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
}
@@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch)
may or may not do anything.
---------------------------------------------------------------------------*/
-static inline void dummy_memwinon(struct board_info *b, unsigned int win)
+static void dummy_memwinon(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win)
+static void dummy_memwinoff(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_globalwinon(struct channel *ch)
+static void dummy_globalwinon(struct channel *ch)
{
}
-static inline void dummy_rxwinon(struct channel *ch)
+static void dummy_rxwinon(struct channel *ch)
{
}
-static inline void dummy_txwinon(struct channel *ch)
+static void dummy_txwinon(struct channel *ch)
{
}
-static inline void dummy_memoff(struct channel *ch)
+static void dummy_memoff(struct channel *ch)
{
}
-static inline void dummy_assertgwinon(struct channel *ch)
+static void dummy_assertgwinon(struct channel *ch)
{
}
-static inline void dummy_assertmemoff(struct channel *ch)
+static void dummy_assertmemoff(struct channel *ch)
{
}
/* ----------------- Begin verifyChannel function ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *tty)
+static struct channel *verifyChannel(struct tty_struct *tty)
{ /* Begin verifyChannel */
-
/* --------------------------------------------------------------------
This routine basically provides a sanity check. It insures that
the channel returned is within the proper range of addresses as
well as properly initialized. If some bogus info gets passed in
through tty->driver_data this should catch it.
- --------------------------------------------------------------------- */
-
- if (tty)
- { /* Begin if tty */
-
- register struct channel *ch = (struct channel *)tty->driver_data;
-
- if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs]))
- {
+ --------------------------------------------------------------------- */
+ if (tty) {
+ struct channel *ch = (struct channel *)tty->driver_data;
+ if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
if (ch->magic == EPCA_MAGIC)
return ch;
}
-
- } /* End if tty */
-
- /* Else return a NULL for invalid */
+ }
return NULL;
} /* End verifyChannel */
/* ------------------ Begin pc_sched_event ------------------------- */
-static inline void pc_sched_event(struct channel *ch, int event)
-{ /* Begin pc_sched_event */
-
-
+static void pc_sched_event(struct channel *ch, int event)
+{
/* ----------------------------------------------------------------------
We call this to schedule interrupt processing on some event. The
kernel sees our request and calls the related routine in OUR driver.
-------------------------------------------------------------------------*/
-
ch->event |= 1 << event;
schedule_work(&ch->tqueue);
-
-
} /* End pc_sched_event */
/* ------------------ Begin epca_error ------------------------- */
static void epca_error(int line, char *msg)
-{ /* Begin epca_error */
-
+{
printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
- return;
-
-} /* End epca_error */
+}
/* ------------------ Begin pc_close ------------------------- */
static void pc_close(struct tty_struct * tty, struct file * filp)
-{ /* Begin pc_close */
-
+{
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
- save_flags(flags);
- cli();
-
- if (tty_hung_up_p(filp))
- {
- restore_flags(flags);
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
+ spin_lock_irqsave(&epca_lock, flags);
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
}
-
/* Check to see if the channel is open more than once */
- if (ch->count-- > 1)
- { /* Begin channel is open more than once */
-
+ if (ch->count-- > 1) {
+ /* Begin channel is open more than once */
/* -------------------------------------------------------------
Return without doing anything. Someone might still be using
the channel.
---------------------------------------------------------------- */
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
} /* End channel is open more than once */
/* Port open only once go ahead with shutdown & reset */
-
- if (ch->count < 0)
- {
- ch->count = 0;
- }
+ if (ch->count < 0)
+ BUG();
/* ---------------------------------------------------------------
Let the rest of the driver know the channel is being closed.
This becomes important if an open is attempted before close
is finished.
------------------------------------------------------------------ */
-
ch->asyncflags |= ASYNC_CLOSING;
-
tty->closing = 1;
- if (ch->asyncflags & ASYNC_INITIALIZED)
- {
+ spin_unlock_irqrestore(&epca_lock, flags);
+
+ if (ch->asyncflags & ASYNC_INITIALIZED) {
/* Setup an event to indicate when the transmit buffer empties */
setup_empty_event(tty, ch);
tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
}
-
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+
+ spin_lock_irqsave(&epca_lock, flags);
tty->closing = 0;
ch->event = 0;
ch->tty = NULL;
+ spin_unlock_irqrestore(&epca_lock, flags);
- if (ch->blocked_open)
- { /* Begin if blocked_open */
-
+ if (ch->blocked_open) { /* Begin if blocked_open */
if (ch->close_delay)
- {
msleep_interruptible(jiffies_to_msecs(ch->close_delay));
- }
-
wake_up_interruptible(&ch->open_wait);
-
} /* End if blocked_open */
-
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
ASYNC_CLOSING);
wake_up_interruptible(&ch->close_wait);
-
-
- restore_flags(flags);
-
} /* End if ch != NULL */
-
} /* End pc_close */
/* ------------------ Begin shutdown ------------------------- */
@@ -586,15 +534,14 @@ static void shutdown(struct channel *ch)
unsigned long flags;
struct tty_struct *tty;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
- save_flags(flags);
- cli();
- globalwinon(ch);
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
bc = ch->brdchan;
/* ------------------------------------------------------------------
@@ -604,20 +551,17 @@ static void shutdown(struct channel *ch)
--------------------------------------------------------------------- */
if (bc)
- bc->idata = 0;
-
+ writeb(0, &bc->idata);
tty = ch->tty;
/* ----------------------------------------------------------------
If we're a modem control device and HUPCL is on, drop RTS & DTR.
------------------------------------------------------------------ */
- if (tty->termios->c_cflag & HUPCL)
- {
+ if (tty->termios->c_cflag & HUPCL) {
ch->omodem &= ~(ch->m_rts | ch->m_dtr);
fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
}
-
memoff(ch);
/* ------------------------------------------------------------------
@@ -628,7 +572,7 @@ static void shutdown(struct channel *ch)
/* Prevent future Digi programmed interrupts from coming active */
ch->asyncflags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End shutdown */
@@ -636,7 +580,6 @@ static void shutdown(struct channel *ch)
static void pc_hangup(struct tty_struct *tty)
{ /* Begin pc_hangup */
-
struct channel *ch;
/* ---------------------------------------------------------
@@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
unsigned long flags;
- save_flags(flags);
- cli();
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+ spin_lock_irqsave(&epca_lock, flags);
ch->tty = NULL;
ch->event = 0;
ch->count = 0;
- restore_flags(flags);
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&ch->open_wait);
-
} /* End if ch != NULL */
} /* End pc_hangup */
@@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty)
static int pc_write(struct tty_struct * tty,
const unsigned char *buf, int bytesAvailable)
{ /* Begin pc_write */
-
- register unsigned int head, tail;
- register int dataLen;
- register int size;
- register int amountCopied;
-
-
+ unsigned int head, tail;
+ int dataLen;
+ int size;
+ int amountCopied;
struct channel *ch;
unsigned long flags;
int remain;
- volatile struct board_chan *bc;
-
+ struct board_chan *bc;
/* ----------------------------------------------------------------
pc_write is primarily called directly by the kernel routine
@@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty,
bc = ch->brdchan;
size = ch->txbufsize;
-
amountCopied = 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- head = bc->tin & (size - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (size - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
tail &= (size - 1);
/* If head >= tail, head has not wrapped around. */
- if (head >= tail)
- { /* Begin head has not wrapped */
-
+ if (head >= tail) { /* Begin head has not wrapped */
/* ---------------------------------------------------------------
remain (much like dataLen above) represents the total amount of
space available on the card for data. Here dataLen represents
@@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty,
buffer. This is important because a memcpy cannot be told to
automatically wrap around when it hits the buffer end.
------------------------------------------------------------------ */
-
dataLen = size - head;
remain = size - (head - tail) - 1;
-
- } /* End head has not wrapped */
- else
- { /* Begin head has wrapped around */
+ } else { /* Begin head has wrapped around */
remain = tail - head - 1;
dataLen = remain;
} /* End head has wrapped around */
-
/* -------------------------------------------------------------------
Check the space on the card. If we have more data than
space; reduce the amount of data to fit the space.
---------------------------------------------------------------------- */
-
bytesAvailable = min(remain, bytesAvailable);
-
txwinon(ch);
while (bytesAvailable > 0)
{ /* Begin while there is data to copy onto card */
@@ -767,26 +691,21 @@ static int pc_write(struct tty_struct * tty,
amountCopied += dataLen;
bytesAvailable -= dataLen;
- if (head >= size)
- {
+ if (head >= size) {
head = 0;
dataLen = tail;
}
-
} /* End while there is data to copy onto card */
-
ch->statusflags |= TXBUSY;
globalwinon(ch);
- bc->tin = head;
+ writew(head, &bc->tin);
- if ((ch->statusflags & LOWWAIT) == 0)
- {
+ if ((ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
return(amountCopied);
} /* End pc_write */
@@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty,
static void pc_put_char(struct tty_struct *tty, unsigned char c)
{ /* Begin pc_put_char */
-
-
pc_write(tty, &c, 1);
- return;
-
} /* End pc_put_char */
/* ------------------ Begin pc_write_room ------------------------- */
@@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
unsigned int head, tail;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
remain = 0;
@@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- {
- save_flags(flags);
- cli();
+ if ((ch = verifyChannel(tty)) != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- head = bc->tin & (ch->txbufsize - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
/* Wrap tail if necessary */
tail &= (ch->txbufsize - 1);
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
- if (remain && (ch->statusflags & LOWWAIT) == 0)
- {
+ if (remain && (ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
/* Return how much room is left on card */
return remain;
@@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
int remain;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
+ struct board_chan *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
@@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
if ((ch = verifyChannel(tty)) == NULL)
return(0);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- tail = bc->tout;
- head = bc->tin;
- ctail = ch->mailbox->cout;
+ tail = readw(&bc->tout);
+ head = readw(&bc->tin);
+ ctail = readw(&ch->mailbox->cout);
- if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
+ if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
chars = 0;
- else
- { /* Begin if some space on the card has been used */
-
- head = bc->tin & (ch->txbufsize - 1);
+ else { /* Begin if some space on the card has been used */
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
tail &= (ch->txbufsize - 1);
-
/* --------------------------------------------------------------
The logic here is basically opposite of the above pc_write_room
here we are finding the amount of bytes in the buffer filled.
Not the amount of bytes empty.
------------------------------------------------------------------- */
-
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
-
chars = (int)(ch->txbufsize - remain);
-
/* -------------------------------------------------------------
Make it possible to wakeup anything waiting for output
in tty_ioctl.c, etc.
@@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
If not already set. Setup an event to indicate when the
transmit buffer empties
----------------------------------------------------------------- */
-
if (!(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
} /* End if some space on the card has been used */
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
/* Return number of characters residing on card. */
return(chars);
@@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty)
unsigned int tail;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
-
+ struct board_chan *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
if ((ch = verifyChannel(tty)) == NULL)
return;
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
-
bc = ch->brdchan;
- tail = bc->tout;
-
+ tail = readw(&bc->tout);
/* Have FEP move tout pointer; effectively flushing transmit buffer */
-
fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
-
} /* End pc_flush_buffer */
/* ------------------ Begin pc_flush_chars ---------------------- */
static void pc_flush_chars(struct tty_struct *tty)
{ /* Begin pc_flush_chars */
-
struct channel * ch;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- {
+ if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
-
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* ----------------------------------------------------------------
If not already set and the transmitter is busy setup an event
to indicate when the transmit empties.
------------------------------------------------------------------- */
-
if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
} /* End pc_flush_chars */
/* ------------------ Begin block_til_ready ---------------------- */
@@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty)
static int block_til_ready(struct tty_struct *tty,
struct file *filp, struct channel *ch)
{ /* Begin block_til_ready */
-
DECLARE_WAITQUEUE(wait,current);
int retval, do_clocal = 0;
unsigned long flags;
-
- if (tty_hung_up_p(filp))
- {
+ if (tty_hung_up_p(filp)) {
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
@@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty,
If the device is in the middle of being closed, then block
until it's done, and then try again.
-------------------------------------------------------------------- */
- if (ch->asyncflags & ASYNC_CLOSING)
- {
+ if (ch->asyncflags & ASYNC_CLOSING) {
interruptible_sleep_on(&ch->close_wait);
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
@@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty,
return -ERESTARTSYS;
}
- if (filp->f_flags & O_NONBLOCK)
- {
+ if (filp->f_flags & O_NONBLOCK) {
/* -----------------------------------------------------------------
If non-blocking mode is set, then make the check up front
and then exit.
-------------------------------------------------------------------- */
-
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
return 0;
}
-
-
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
-
- /* Block waiting for the carrier detect and the line to become free */
+ /* Block waiting for the carrier detect and the line to become free */
retval = 0;
add_wait_queue(&ch->open_wait, &wait);
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* We dec count so that pc_close will know when to free things */
if (!tty_hung_up_p(filp))
ch->count--;
-
- restore_flags(flags);
-
ch->blocked_open++;
-
while(1)
{ /* Begin forever while */
-
set_current_state(TASK_INTERRUPTIBLE);
-
if (tty_hung_up_p(filp) ||
!(ch->asyncflags & ASYNC_INITIALIZED))
{
@@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty,
retval = -ERESTARTSYS;
break;
}
-
if (!(ch->asyncflags & ASYNC_CLOSING) &&
(do_clocal || (ch->imodem & ch->dcd)))
break;
-
- if (signal_pending(current))
- {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
-
+ spin_unlock_irqrestore(&epca_lock, flags);
/* ---------------------------------------------------------------
Allow someone else to be scheduled. We will occasionally go
through this loop until one of the above conditions change.
@@ -1091,25 +949,23 @@ static int block_til_ready(struct tty_struct *tty,
prevent this loop from hogging the cpu.
------------------------------------------------------------------ */
schedule();
+ spin_lock_irqsave(&epca_lock, flags);
} /* End forever while */
current->state = TASK_RUNNING;
remove_wait_queue(&ch->open_wait, &wait);
- cli();
if (!tty_hung_up_p(filp))
ch->count++;
- restore_flags(flags);
-
ch->blocked_open--;
+ spin_unlock_irqrestore(&epca_lock, flags);
+
if (retval)
return retval;
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
return 0;
-
} /* End block_til_ready */
/* ------------------ Begin pc_open ---------------------- */
@@ -1120,17 +976,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
struct channel *ch;
unsigned long flags;
int line, retval, boardnum;
- volatile struct board_chan *bc;
- volatile unsigned int head;
+ struct board_chan *bc;
+ unsigned int head;
line = tty->index;
- if (line < 0 || line >= nbdevs)
- {
- printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n");
- tty->driver_data = NULL;
- return(-ENODEV);
- }
-
+ if (line < 0 || line >= nbdevs)
+ return -ENODEV;
ch = &digi_channels[line];
boardnum = ch->boardnum;
@@ -1143,66 +994,49 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
goes here.
---------------------------------------------------------------------- */
- if (invalid_lilo_config)
- {
+ if (invalid_lilo_config) {
if (setup_error_code & INVALID_BOARD_TYPE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board type specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
if (setup_error_code & INVALID_NUM_PORTS)
- printk(KERN_ERR "<Error> - pc_open: Invalid number of ports specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
if (setup_error_code & INVALID_MEM_BASE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board memory address specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
if (setup_error_code & INVALID_PORT_BASE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board port address specified in LILO command\n");
-
+ printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
if (setup_error_code & INVALID_BOARD_STATUS)
- printk(KERN_ERR "<Error> - pc_open: Invalid board status specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
if (setup_error_code & INVALID_ALTPIN)
- printk(KERN_ERR "<Error> - pc_open: Invalid board altpin specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
tty->driver_data = NULL; /* Mark this device as 'down' */
- return(-ENODEV);
+ return -ENODEV;
}
-
- if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED))
- {
+ if (boardnum >= num_cards || boards[boardnum].status == DISABLED) {
tty->driver_data = NULL; /* Mark this device as 'down' */
return(-ENODEV);
}
- if (( bc = ch->brdchan) == 0)
- {
+ if ((bc = ch->brdchan) == 0) {
tty->driver_data = NULL;
- return(-ENODEV);
+ return -ENODEV;
}
+ spin_lock_irqsave(&epca_lock, flags);
/* ------------------------------------------------------------------
Every time a channel is opened, increment a counter. This is
necessary because we do not wish to flush and shutdown the channel
until the last app holding the channel open, closes it.
--------------------------------------------------------------------- */
-
ch->count++;
-
/* ----------------------------------------------------------------
Set a kernel structures pointer to our local channel
structure. This way we can get to it when passed only
a tty struct.
------------------------------------------------------------------ */
-
tty->driver_data = ch;
-
/* ----------------------------------------------------------------
If this is the first time the channel has been opened, initialize
the tty->termios struct otherwise let pc_close handle it.
-------------------------------------------------------------------- */
-
- save_flags(flags);
- cli();
-
globalwinon(ch);
ch->statusflags = 0;
@@ -1213,8 +1047,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
Set receive head and tail ptrs to each other. This indicates
no data available to read.
----------------------------------------------------------------- */
- head = bc->rin;
- bc->rout = head;
+ head = readw(&bc->rin);
+ writew(head, &bc->rout);
/* Set the channels associated tty structure */
ch->tty = tty;
@@ -1224,122 +1058,74 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
issues, etc.... It effect both control flags and input flags.
-------------------------------------------------------------------- */
epcaparam(tty,ch);
-
ch->asyncflags |= ASYNC_INITIALIZED;
memoff(ch);
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
retval = block_til_ready(tty, filp, ch);
if (retval)
- {
return retval;
- }
-
/* -------------------------------------------------------------
Set this again in case a hangup set it to zero while this
open() was waiting for the line...
--------------------------------------------------------------- */
+ spin_lock_irqsave(&epca_lock, flags);
ch->tty = tty;
-
- save_flags(flags);
- cli();
globalwinon(ch);
-
/* Enable Digi Data events */
- bc->idata = 1;
-
+ writeb(1, &bc->idata);
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
return 0;
-
} /* End pc_open */
-#ifdef MODULE
static int __init epca_module_init(void)
{ /* Begin init_module */
-
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- pc_init();
-
- restore_flags(flags);
-
- return(0);
+ return pc_init();
}
module_init(epca_module_init);
-#endif
-#ifdef ENABLE_PCI
static struct pci_driver epca_driver;
-#endif
-
-#ifdef MODULE
-/* -------------------- Begin cleanup_module ---------------------- */
static void __exit epca_module_exit(void)
{
-
int count, crd;
struct board_info *bd;
struct channel *ch;
- unsigned long flags;
del_timer_sync(&epca_timer);
- save_flags(flags);
- cli();
-
if ((tty_unregister_driver(pc_driver)) ||
(tty_unregister_driver(pc_info)))
{
- printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
- restore_flags(flags);
+ printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
return;
}
put_tty_driver(pc_driver);
put_tty_driver(pc_info);
- for (crd = 0; crd < num_cards; crd++)
- { /* Begin for each card */
-
+ for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */
bd = &boards[crd];
-
if (!bd)
{ /* Begin sanity check */
printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
return;
} /* End sanity check */
-
- ch = card_ptr[crd];
-
+ ch = card_ptr[crd];
for (count = 0; count < bd->numports; count++, ch++)
{ /* Begin for each port */
-
- if (ch)
- {
+ if (ch) {
if (ch->tty)
tty_hangup(ch->tty);
kfree(ch->tmp_buf);
}
-
} /* End for each port */
} /* End for each card */
-
-#ifdef ENABLE_PCI
pci_unregister_driver (&epca_driver);
-#endif
-
- restore_flags(flags);
-
}
+
module_exit(epca_module_exit);
-#endif /* MODULE */
static struct tty_operations pc_ops = {
.open = pc_open,
@@ -1371,34 +1157,15 @@ static struct tty_operations info_ops = {
/* ------------------ Begin pc_init ---------------------- */
-int __init pc_init(void)
+static int __init pc_init(void)
{ /* Begin pc_init */
-
- /* ----------------------------------------------------------------
- pc_init is called by the operating system during boot up prior to
- any open calls being made. In the older versions of Linux (Prior
- to 2.0.0) an entry is made into tty_io.c. A pointer to the last
- memory location (from kernel space) used (kmem_start) is passed
- to pc_init. It is pc_inits responsibility to modify this value
- for any memory that the Digi driver might need and then return
- this value to the operating system. For example if the driver
- wishes to allocate 1K of kernel memory, pc_init would return
- (kmem_start + 1024). This memory (Between kmem_start and kmem_start
- + 1024) would then be available for use exclusively by the driver.
- In this case our driver does not allocate any of this kernel
- memory.
- ------------------------------------------------------------------*/
-
- ulong flags;
int crd;
struct board_info *bd;
unsigned char board_id = 0;
-#ifdef ENABLE_PCI
int pci_boards_found, pci_count;
pci_count = 0;
-#endif /* ENABLE_PCI */
pc_driver = alloc_tty_driver(MAX_ALLOC);
if (!pc_driver)
@@ -1416,8 +1183,7 @@ int __init pc_init(void)
Note : If LILO has ran epca_setup then epca_setup will handle defining
num_cards as well as copying the data into the board structure.
-------------------------------------------------------------------------- */
- if (!liloconfig)
- { /* Begin driver has been configured via. epcaconfig */
+ if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */
nbdevs = NBDEVS;
num_cards = NUMCARDS;
@@ -1440,8 +1206,6 @@ int __init pc_init(void)
printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
-#ifdef ENABLE_PCI
-
/* ------------------------------------------------------------------
NOTE : This code assumes that the number of ports found in
the boards array is correct. This could be wrong if
@@ -1467,8 +1231,6 @@ int __init pc_init(void)
pci_boards_found += init_PCI();
num_cards += pci_boards_found;
-#endif /* ENABLE_PCI */
-
pc_driver->owner = THIS_MODULE;
pc_driver->name = "ttyD";
pc_driver->devfs_name = "tts/D";
@@ -1499,9 +1261,6 @@ int __init pc_init(void)
tty_set_operations(pc_info, &info_ops);
- save_flags(flags);
- cli();
-
for (crd = 0; crd < num_cards; crd++)
{ /* Begin for each card */
@@ -1610,11 +1369,7 @@ int __init pc_init(void)
if ((board_id & 0x30) == 0x30)
bd->memory_seg = 0x8000;
- } /* End it is an XI card */
- else
- {
- printk(KERN_ERR "<Error> - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
- }
+ } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
break;
} /* End switch on bd->type */
@@ -1634,9 +1389,6 @@ int __init pc_init(void)
init_timer(&epca_timer);
epca_timer.function = epcapoll;
mod_timer(&epca_timer, jiffies + HZ/25);
-
- restore_flags(flags);
-
return 0;
} /* End pc_init */
@@ -1647,10 +1399,10 @@ static void post_fep_init(unsigned int crd)
{ /* Begin post_fep_init */
int i;
- unchar *memaddr;
- volatile struct global_data *gd;
+ unsigned char *memaddr;
+ struct global_data *gd;
struct board_info *bd;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
struct channel *ch;
int shrinkmem = 0, lowwater ;
@@ -1669,9 +1421,7 @@ static void post_fep_init(unsigned int crd)
after DIGI_INIT has been called will return the proper values.
------------------------------------------------------------------- */
- if (bd->type >= PCIXEM) /* If the board in question is PCI */
- { /* Begin get PCI number of ports */
-
+ if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
/* --------------------------------------------------------------------
Below we use XEMPORTS as a memory offset regardless of which PCI
card it is. This is because all of the supported PCI cards have
@@ -1685,15 +1435,15 @@ static void post_fep_init(unsigned int crd)
(FYI - The id should be located at 0x1ac (And may use up to 4 bytes
if the box in question is a XEM or CX)).
------------------------------------------------------------------------ */
-
- bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long)
- (bd->re_map_membase + XEMPORTS));
-
-
+ /* PCI cards are already remapped at this point ISA are not */
+ bd->numports = readw(bd->re_map_membase + XEMPORTS);
epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
nbdevs += (bd->numports);
-
- } /* End get PCI number of ports */
+ } else {
+ /* Fix up the mappings for ISA/EISA etc */
+ /* FIXME: 64K - can we be smarter ? */
+ bd->re_map_membase = ioremap(bd->membase, 0x10000);
+ }
if (crd != 0)
card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
@@ -1701,19 +1451,9 @@ static void post_fep_init(unsigned int crd)
card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
ch = card_ptr[crd];
-
-
epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
- memaddr = (unchar *)bd->re_map_membase;
-
- /*
- The below command is necessary because newer kernels (2.1.x and
- up) do not have a 1:1 virtual to physical mapping. The below
- call adjust for that.
- */
-
- memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
+ memaddr = bd->re_map_membase;
/* -----------------------------------------------------------------
The below assignment will set bc to point at the BEGINING of
@@ -1721,7 +1461,7 @@ static void post_fep_init(unsigned int crd)
8 and 64 of these structures.
-------------------------------------------------------------------- */
- bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
+ bc = (struct board_chan *)(memaddr + CHANSTRUCT);
/* -------------------------------------------------------------------
The below assignment will set gd to point at the BEGINING of
@@ -1730,20 +1470,18 @@ static void post_fep_init(unsigned int crd)
pointer begins at 0xd10.
---------------------------------------------------------------------- */
- gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
+ gd = (struct global_data *)(memaddr + GLOBAL);
/* --------------------------------------------------------------------
XEPORTS (address 0xc22) points at the number of channels the
card supports. (For 64XE, XI, XEM, and XR use 0xc02)
----------------------------------------------------------------------- */
- if (((bd->type == PCXEVE) | (bd->type == PCXE)) &&
- (*(ushort *)((ulong)memaddr + XEPORTS) < 3))
+ if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
shrinkmem = 1;
if (bd->type < PCIXEM)
if (!request_region((int)bd->port, 4, board_desc[bd->type]))
return;
-
memwinon(bd, 0);
/* --------------------------------------------------------------------
@@ -1753,17 +1491,16 @@ static void post_fep_init(unsigned int crd)
/* For every port on the card do ..... */
- for (i = 0; i < bd->numports; i++, ch++, bc++)
- { /* Begin for each port */
+ for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */
+ unsigned long flags;
ch->brdchan = bc;
ch->mailbox = gd;
INIT_WORK(&ch->tqueue, do_softint, ch);
ch->board = &boards[crd];
- switch (bd->type)
- { /* Begin switch bd->type */
-
+ spin_lock_irqsave(&epca_lock, flags);
+ switch (bd->type) {
/* ----------------------------------------------------------------
Since some of the boards use different bitmaps for their
control signals we cannot hard code these values and retain
@@ -1796,14 +1533,12 @@ static void post_fep_init(unsigned int crd)
} /* End switch bd->type */
- if (boards[crd].altpin)
- {
+ if (boards[crd].altpin) {
ch->dsr = ch->m_dcd;
ch->dcd = ch->m_dsr;
ch->digiext.digi_flags |= DIGI_ALTPIN;
}
- else
- {
+ else {
ch->dcd = ch->m_dcd;
ch->dsr = ch->m_dsr;
}
@@ -1813,14 +1548,12 @@ static void post_fep_init(unsigned int crd)
ch->magic = EPCA_MAGIC;
ch->tty = NULL;
- if (shrinkmem)
- {
+ if (shrinkmem) {
fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
shrinkmem = 0;
}
- switch (bd->type)
- { /* Begin switch bd->type */
+ switch (bd->type) {
case PCIXEM:
case PCIXRJ:
@@ -1878,13 +1611,13 @@ static void post_fep_init(unsigned int crd)
fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
- bc->edelay = 100;
- bc->idata = 1;
+ writew(100, &bc->edelay);
+ writeb(1, &bc->idata);
- ch->startc = bc->startc;
- ch->stopc = bc->stopc;
- ch->startca = bc->startca;
- ch->stopca = bc->stopca;
+ ch->startc = readb(&bc->startc);
+ ch->stopc = readb(&bc->stopc);
+ ch->startca = readb(&bc->startca);
+ ch->stopca = readb(&bc->stopca);
ch->fepcflag = 0;
ch->fepiflag = 0;
@@ -1899,27 +1632,23 @@ static void post_fep_init(unsigned int crd)
ch->blocked_open = 0;
init_waitqueue_head(&ch->open_wait);
init_waitqueue_head(&ch->close_wait);
+
+ spin_unlock_irqrestore(&epca_lock, flags);
+
ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
- if (!(ch->tmp_buf))
- {
+ if (!ch->tmp_buf) {
printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i);
release_region((int)bd->port, 4);
while(i-- > 0)
kfree((ch--)->tmp_buf);
return;
- }
- else
+ } else
memset((void *)ch->tmp_buf,0,ch->txbufsize);
} /* End for each port */
printk(KERN_INFO
"Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
- sprintf(mesg,
- "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
- VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
- console_print(mesg);
-
memwinoff(bd, 0);
} /* End post_fep_init */
@@ -1943,9 +1672,6 @@ static void epcapoll(unsigned long ignored)
buffer empty) and acts on those events.
----------------------------------------------------------------------- */
- save_flags(flags);
- cli();
-
for (crd = 0; crd < num_cards; crd++)
{ /* Begin for each card */
@@ -1961,6 +1687,8 @@ static void epcapoll(unsigned long ignored)
some legacy boards.
---------------------------------------------------------------- */
+ spin_lock_irqsave(&epca_lock, flags);
+
assertmemoff(ch);
globalwinon(ch);
@@ -1970,21 +1698,19 @@ static void epcapoll(unsigned long ignored)
the transmit or receive queue.
------------------------------------------------------------------- */
- head = ch->mailbox->ein;
- tail = ch->mailbox->eout;
+ head = readw(&ch->mailbox->ein);
+ tail = readw(&ch->mailbox->eout);
/* If head isn't equal to tail we have an event */
if (head != tail)
doevent(crd);
-
memoff(ch);
- } /* End for each card */
+ spin_unlock_irqrestore(&epca_lock, flags);
+ } /* End for each card */
mod_timer(&epca_timer, jiffies + (HZ / 25));
-
- restore_flags(flags);
} /* End epcapoll */
/* --------------------- Begin doevent ------------------------ */
@@ -1992,53 +1718,42 @@ static void epcapoll(unsigned long ignored)
static void doevent(int crd)
{ /* Begin doevent */
- volatile unchar *eventbuf;
+ void *eventbuf;
struct channel *ch, *chan0;
static struct tty_struct *tty;
- volatile struct board_info *bd;
- volatile struct board_chan *bc;
- register volatile unsigned int tail, head;
- register int event, channel;
- register int mstat, lstat;
+ struct board_info *bd;
+ struct board_chan *bc;
+ unsigned int tail, head;
+ int event, channel;
+ int mstat, lstat;
/* -------------------------------------------------------------------
This subroutine is called by epcapoll when an event is detected
in the event queue. This routine responds to those events.
--------------------------------------------------------------------- */
-
bd = &boards[crd];
chan0 = card_ptr[crd];
epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-
assertgwinon(chan0);
-
- while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein))
+ while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein)))
{ /* Begin while something in event queue */
-
assertgwinon(chan0);
-
- eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART));
-
+ eventbuf = bd->re_map_membase + tail + ISTART;
/* Get the channel the event occurred on */
- channel = eventbuf[0];
-
+ channel = readb(eventbuf);
/* Get the actual event code that occurred */
- event = eventbuf[1];
-
+ event = readb(eventbuf + 1);
/* ----------------------------------------------------------------
The two assignments below get the current modem status (mstat)
and the previous modem status (lstat). These are useful becuase
an event could signal a change in modem signals itself.
------------------------------------------------------------------- */
-
- mstat = eventbuf[2];
- lstat = eventbuf[3];
+ mstat = readb(eventbuf + 2);
+ lstat = readb(eventbuf + 3);
ch = chan0 + channel;
-
- if ((unsigned)channel >= bd->numports || !ch)
- {
+ if ((unsigned)channel >= bd->numports || !ch) {
if (channel >= bd->numports)
ch = chan0;
bc = ch->brdchan;
@@ -2048,97 +1763,53 @@ static void doevent(int crd)
if ((bc = ch->brdchan) == NULL)
goto next;
- if (event & DATA_IND)
- { /* Begin DATA_IND */
-
+ if (event & DATA_IND) { /* Begin DATA_IND */
receive_data(ch);
assertgwinon(ch);
-
} /* End DATA_IND */
/* else *//* Fix for DCD transition missed bug */
- if (event & MODEMCHG_IND)
- { /* Begin MODEMCHG_IND */
-
+ if (event & MODEMCHG_IND) { /* Begin MODEMCHG_IND */
/* A modem signal change has been indicated */
-
ch->imodem = mstat;
-
- if (ch->asyncflags & ASYNC_CHECK_CD)
- {
+ if (ch->asyncflags & ASYNC_CHECK_CD) {
if (mstat & ch->dcd) /* We are now receiving dcd */
wake_up_interruptible(&ch->open_wait);
else
pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
}
-
} /* End MODEMCHG_IND */
-
tty = ch->tty;
- if (tty)
- { /* Begin if valid tty */
-
- if (event & BREAK_IND)
- { /* Begin if BREAK_IND */
-
+ if (tty) { /* Begin if valid tty */
+ if (event & BREAK_IND) { /* Begin if BREAK_IND */
/* A break has been indicated */
-
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-
*tty->flip.char_buf_ptr++ = 0;
-
tty_schedule_flip(tty);
-
- } /* End if BREAK_IND */
- else
- if (event & LOWTX_IND)
- { /* Begin LOWTX_IND */
-
+ } else if (event & LOWTX_IND) { /* Begin LOWTX_IND */
if (ch->statusflags & LOWWAIT)
{ /* Begin if LOWWAIT */
-
ch->statusflags &= ~LOWWAIT;
tty_wakeup(tty);
wake_up_interruptible(&tty->write_wait);
-
} /* End if LOWWAIT */
-
- } /* End LOWTX_IND */
- else
- if (event & EMPTYTX_IND)
- { /* Begin EMPTYTX_IND */
-
+ } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */
/* This event is generated by setup_empty_event */
-
ch->statusflags &= ~TXBUSY;
- if (ch->statusflags & EMPTYWAIT)
- { /* Begin if EMPTYWAIT */
-
+ if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */
ch->statusflags &= ~EMPTYWAIT;
tty_wakeup(tty);
-
wake_up_interruptible(&tty->write_wait);
-
} /* End if EMPTYWAIT */
-
} /* End EMPTYTX_IND */
-
} /* End if valid tty */
-
-
next:
globalwinon(ch);
-
- if (!bc)
- printk(KERN_ERR "<Error> - bc == NULL in doevent!\n");
- else
- bc->idata = 1;
-
- chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4);
+ BUG_ON(!bc);
+ writew(1, &bc->idata);
+ writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
globalwinon(chan0);
-
} /* End while something in event queue */
-
} /* End doevent */
/* --------------------- Begin fepcmd ------------------------ */
@@ -2146,7 +1817,6 @@ static void doevent(int crd)
static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
int byte2, int ncmds, int bytecmd)
{ /* Begin fepcmd */
-
unchar *memaddr;
unsigned int head, cmdTail, cmdStart, cmdMax;
long count;
@@ -2155,93 +1825,57 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
/* This is the routine in which commands may be passed to the card. */
if (ch->board->status == DISABLED)
- {
return;
- }
-
assertgwinon(ch);
-
/* Remember head (As well as max) is just an offset not a base addr */
- head = ch->mailbox->cin;
-
+ head = readw(&ch->mailbox->cin);
/* cmdStart is a base address */
- cmdStart = ch->mailbox->cstart;
-
+ cmdStart = readw(&ch->mailbox->cstart);
/* ------------------------------------------------------------------
We do the addition below because we do not want a max pointer
relative to cmdStart. We want a max pointer that points at the
physical end of the command queue.
-------------------------------------------------------------------- */
-
- cmdMax = (cmdStart + 4 + (ch->mailbox->cmax));
-
+ cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
memaddr = ch->board->re_map_membase;
- /*
- The below command is necessary because newer kernels (2.1.x and
- up) do not have a 1:1 virtual to physical mapping. The below
- call adjust for that.
- */
-
- memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
-
- if (head >= (cmdMax - cmdStart) || (head & 03))
- {
- printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__,
- cmd, head);
- printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__,
- cmdMax, cmdStart);
+ if (head >= (cmdMax - cmdStart) || (head & 03)) {
+ printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head);
+ printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart);
return;
}
-
- if (bytecmd)
- {
- *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
-
- *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
+ if (bytecmd) {
+ writeb(cmd, memaddr + head + cmdStart + 0);
+ writeb(ch->channelnum, memaddr + head + cmdStart + 1);
/* Below word_or_byte is bits to set */
- *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte;
+ writeb(word_or_byte, memaddr + head + cmdStart + 2);
/* Below byte2 is bits to reset */
- *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2;
-
- }
- else
- {
- *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
- *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
- *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte;
+ writeb(byte2, memaddr + head + cmdStart + 3);
+ } else {
+ writeb(cmd, memaddr + head + cmdStart + 0);
+ writeb(ch->channelnum, memaddr + head + cmdStart + 1);
+ writeb(word_or_byte, memaddr + head + cmdStart + 2);
}
-
head = (head + 4) & (cmdMax - cmdStart - 4);
- ch->mailbox->cin = head;
-
+ writew(head, &ch->mailbox->cin);
count = FEPTIMEOUT;
- for (;;)
- { /* Begin forever loop */
-
+ for (;;) { /* Begin forever loop */
count--;
- if (count == 0)
- {
+ if (count == 0) {
printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
return;
}
-
- head = ch->mailbox->cin;
- cmdTail = ch->mailbox->cout;
-
+ head = readw(&ch->mailbox->cin);
+ cmdTail = readw(&ch->mailbox->cout);
n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-
/* ----------------------------------------------------------
Basically this will break when the FEP acknowledges the
command by incrementing cmdTail (Making it equal to head).
------------------------------------------------------------- */
-
if (n <= ncmds * (sizeof(short) * 4))
break; /* Well nearly forever :-) */
-
} /* End forever loop */
-
} /* End fepcmd */
/* ---------------------------------------------------------------------
@@ -2255,11 +1889,9 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
{ /* Begin termios2digi_h */
-
unsigned res = 0;
- if (cflag & CRTSCTS)
- {
+ if (cflag & CRTSCTS) {
ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
res |= ((ch->m_cts) | (ch->m_rts));
}
@@ -2295,7 +1927,6 @@ static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
INPCK | ISTRIP|IXON|IXANY|IXOFF);
-
if (ch->digiext.digi_flags & DIGI_AIXON)
res |= IAIXON;
return res;
@@ -2308,28 +1939,15 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
{ /* Begin termios2digi_c */
unsigned res = 0;
-
-#ifdef SPEED_HACK
- /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
- if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200;
- if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600;
-#endif /* SPEED_HACK */
-
- if (cflag & CBAUDEX)
- { /* Begin detected CBAUDEX */
-
+ if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */
ch->digiext.digi_flags |= DIGI_FAST;
-
/* -------------------------------------------------------------
HUPCL bit is used by FEP to indicate fast baud
table is to be used.
----------------------------------------------------------------- */
-
res |= FEP_HUPCL;
-
} /* End detected CBAUDEX */
else ch->digiext.digi_flags &= ~DIGI_FAST;
-
/* -------------------------------------------------------------------
CBAUD has bit position 0x1000 set these days to indicate Linux
baud rate remap. Digi hardware can't handle the bit assignment.
@@ -2337,7 +1955,6 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
bit out.
---------------------------------------------------------------------- */
res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
/* -------------------------------------------------------------
This gets a little confusing. The Digi cards have their own
representation of c_cflags controling baud rate. For the most
@@ -2357,10 +1974,8 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
should be checked for a screened out prior to termios2digi_c
returning. Since CLOCAL isn't used by the board this can be
ignored as long as the returned value is used only by Digi hardware.
- ----------------------------------------------------------------- */
-
- if (cflag & CBAUDEX)
- {
+ ----------------------------------------------------------------- */
+ if (cflag & CBAUDEX) {
/* -------------------------------------------------------------
The below code is trying to guarantee that only baud rates
115200 and 230400 are remapped. We use exclusive or because
@@ -2371,138 +1986,96 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
(!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
- {
res += 1;
- }
}
-
return res;
} /* End termios2digi_c */
/* --------------------- Begin epcaparam ----------------------- */
+/* Caller must hold the locks */
static void epcaparam(struct tty_struct *tty, struct channel *ch)
{ /* Begin epcaparam */
unsigned int cmdHead;
struct termios *ts;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
unsigned mval, hflow, cflag, iflag;
bc = ch->brdchan;
epcaassert(bc !=0, "bc out of range");
assertgwinon(ch);
-
ts = tty->termios;
-
- if ((ts->c_cflag & CBAUD) == 0)
- { /* Begin CBAUD detected */
-
- cmdHead = bc->rin;
+ if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */
+ cmdHead = readw(&bc->rin);
bc->rout = cmdHead;
- cmdHead = bc->tin;
-
+ cmdHead = readw(&bc->tin);
/* Changing baud in mid-stream transmission can be wonderful */
/* ---------------------------------------------------------------
Flush current transmit buffer by setting cmdTail pointer (tout)
to cmdHead pointer (tin). Hopefully the transmit buffer is empty.
----------------------------------------------------------------- */
-
fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
mval = 0;
-
- } /* End CBAUD detected */
- else
- { /* Begin CBAUD not detected */
-
+ } else { /* Begin CBAUD not detected */
/* -------------------------------------------------------------------
c_cflags have changed but that change had nothing to do with BAUD.
Propagate the change to the card.
---------------------------------------------------------------------- */
-
cflag = termios2digi_c(ch, ts->c_cflag);
-
- if (cflag != ch->fepcflag)
- {
+ if (cflag != ch->fepcflag) {
ch->fepcflag = cflag;
/* Set baud rate, char size, stop bits, parity */
fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
}
-
-
/* ----------------------------------------------------------------
If the user has not forced CLOCAL and if the device is not a
CALLOUT device (Which is always CLOCAL) we set flags such that
the driver will wait on carrier detect.
------------------------------------------------------------------- */
-
if (ts->c_cflag & CLOCAL)
- { /* Begin it is a cud device or a ttyD device with CLOCAL on */
ch->asyncflags &= ~ASYNC_CHECK_CD;
- } /* End it is a cud device or a ttyD device with CLOCAL on */
else
- { /* Begin it is a ttyD device */
ch->asyncflags |= ASYNC_CHECK_CD;
- } /* End it is a ttyD device */
-
mval = ch->m_dtr | ch->m_rts;
-
} /* End CBAUD not detected */
-
iflag = termios2digi_i(ch, ts->c_iflag);
-
/* Check input mode flags */
-
- if (iflag != ch->fepiflag)
- {
+ if (iflag != ch->fepiflag) {
ch->fepiflag = iflag;
-
/* ---------------------------------------------------------------
Command sets channels iflag structure on the board. Such things
as input soft flow control, handling of parity errors, and
break handling are all set here.
------------------------------------------------------------------- */
-
/* break handling, parity handling, input stripping, flow control chars */
fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
}
-
/* ---------------------------------------------------------------
Set the board mint value for this channel. This will cause hardware
events to be generated each time the DCD signal (Described in mint)
changes.
------------------------------------------------------------------- */
- bc->mint = ch->dcd;
-
+ writeb(ch->dcd, &bc->mint);
if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
if (ch->digiext.digi_flags & DIGI_FORCEDCD)
- bc->mint = 0;
-
- ch->imodem = bc->mstat;
-
+ writeb(0, &bc->mint);
+ ch->imodem = readb(&bc->mstat);
hflow = termios2digi_h(ch, ts->c_cflag);
-
- if (hflow != ch->hflow)
- {
+ if (hflow != ch->hflow) {
ch->hflow = hflow;
-
/* --------------------------------------------------------------
Hard flow control has been selected but the board is not
using it. Activate hard flow control now.
----------------------------------------------------------------- */
-
fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
}
-
-
mval ^= ch->modemfake & (mval ^ ch->modem);
- if (ch->omodem ^ mval)
- {
+ if (ch->omodem ^ mval) {
ch->omodem = mval;
-
/* --------------------------------------------------------------
The below command sets the DTR and RTS mstat structure. If
hard flow control is NOT active these changes will drive the
@@ -2514,87 +2087,65 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
/* First reset DTR & RTS; then set them */
fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-
}
-
- if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)
- {
+ if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
ch->fepstartc = ch->startc;
ch->fepstopc = ch->stopc;
-
/* ------------------------------------------------------------
The XON / XOFF characters have changed; propagate these
changes to the card.
--------------------------------------------------------------- */
-
fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
}
-
- if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)
- {
+ if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
ch->fepstartca = ch->startca;
ch->fepstopca = ch->stopca;
-
/* ---------------------------------------------------------------
Similar to the above, this time the auxilarly XON / XOFF
characters have changed; propagate these changes to the card.
------------------------------------------------------------------ */
-
fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
-
} /* End epcaparam */
/* --------------------- Begin receive_data ----------------------- */
-
+/* Caller holds lock */
static void receive_data(struct channel *ch)
{ /* Begin receive_data */
unchar *rptr;
struct termios *ts = NULL;
struct tty_struct *tty;
- volatile struct board_chan *bc;
- register int dataToRead, wrapgap, bytesAvailable;
- register unsigned int tail, head;
+ struct board_chan *bc;
+ int dataToRead, wrapgap, bytesAvailable;
+ unsigned int tail, head;
unsigned int wrapmask;
int rc;
-
/* ---------------------------------------------------------------
This routine is called by doint when a receive data event
has taken place.
------------------------------------------------------------------- */
globalwinon(ch);
-
if (ch->statusflags & RXSTOPPED)
return;
-
tty = ch->tty;
if (tty)
ts = tty->termios;
-
bc = ch->brdchan;
-
- if (!bc)
- {
- printk(KERN_ERR "<Error> - bc is NULL in receive_data!\n");
- return;
- }
-
+ BUG_ON(!bc);
wrapmask = ch->rxbufsize - 1;
/* ---------------------------------------------------------------------
Get the head and tail pointers to the receiver queue. Wrap the
head pointer if it has reached the end of the buffer.
------------------------------------------------------------------------ */
-
- head = bc->rin;
+ head = readw(&bc->rin);
head &= wrapmask;
- tail = bc->rout & wrapmask;
+ tail = readw(&bc->rout) & wrapmask;
bytesAvailable = (head - tail) & wrapmask;
-
if (bytesAvailable == 0)
return;
@@ -2602,8 +2153,7 @@ static void receive_data(struct channel *ch)
If CREAD bit is off or device not open, set TX tail to head
--------------------------------------------------------------------- */
- if (!tty || !ts || !(ts->c_cflag & CREAD))
- {
+ if (!tty || !ts || !(ts->c_cflag & CREAD)) {
bc->rout = head;
return;
}
@@ -2611,64 +2161,45 @@ static void receive_data(struct channel *ch)
if (tty->flip.count == TTY_FLIPBUF_SIZE)
return;
- if (bc->orun)
- {
- bc->orun = 0;
- printk(KERN_WARNING "overrun! DigiBoard device %s\n",tty->name);
+ if (readb(&bc->orun)) {
+ writeb(0, &bc->orun);
+ printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
}
-
rxwinon(ch);
rptr = tty->flip.char_buf_ptr;
rc = tty->flip.count;
-
- while (bytesAvailable > 0)
- { /* Begin while there is data on the card */
-
+ while (bytesAvailable > 0) { /* Begin while there is data on the card */
wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-
/* ---------------------------------------------------------------
Even if head has wrapped around only report the amount of
data to be equal to the size - tail. Remember memcpy can't
automaticly wrap around the receive buffer.
----------------------------------------------------------------- */
-
dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
-
/* --------------------------------------------------------------
Make sure we don't overflow the buffer
----------------------------------------------------------------- */
-
if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
dataToRead = TTY_FLIPBUF_SIZE - rc;
-
if (dataToRead == 0)
break;
-
/* ---------------------------------------------------------------
Move data read from our card into the line disciplines buffer
for translation if necessary.
------------------------------------------------------------------ */
-
- if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr)
- printk(KERN_ERR "<Error> - receive_data : memcpy failed\n");
-
+ memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
rc += dataToRead;
rptr += dataToRead;
tail = (tail + dataToRead) & wrapmask;
bytesAvailable -= dataToRead;
-
} /* End while there is data on the card */
-
-
tty->flip.count = rc;
tty->flip.char_buf_ptr = rptr;
globalwinon(ch);
- bc->rout = tail;
-
+ writew(tail, &bc->rout);
/* Must be called with global data */
tty_schedule_flip(ch->tty);
return;
-
} /* End receive_data */
static int info_ioctl(struct tty_struct *tty, struct file * file,
@@ -2676,17 +2207,15 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
{
switch (cmd)
{ /* Begin switch cmd */
-
case DIGI_GETINFO:
{ /* Begin case DIGI_GETINFO */
-
struct digi_info di ;
int brd;
- getUser(brd, (unsigned int __user *)arg);
-
- if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
- return (-ENODEV);
+ if(get_user(brd, (unsigned int __user *)arg))
+ return -EFAULT;
+ if (brd < 0 || brd >= num_cards || num_cards == 0)
+ return -ENODEV;
memset(&di, 0, sizeof(di));
@@ -2694,8 +2223,9 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
di.status = boards[brd].status;
di.type = boards[brd].type ;
di.numports = boards[brd].numports ;
- di.port = boards[brd].port ;
- di.membase = boards[brd].membase ;
+ /* Legacy fixups - just move along nothing to see */
+ di.port = (unsigned char *)boards[brd].port ;
+ di.membase = (unsigned char *)boards[brd].membase ;
if (copy_to_user((void __user *)arg, &di, sizeof (di)))
return -EFAULT;
@@ -2709,39 +2239,29 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
int brd = arg & 0xff000000 >> 16 ;
unsigned char state = arg & 0xff ;
- if ((brd < 0) || (brd >= num_cards))
- {
- printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
+ if (brd < 0 || brd >= num_cards) {
+ printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
return (-ENODEV);
}
-
digi_poller_inhibited = state ;
break ;
-
} /* End case DIGI_POLLER */
case DIGI_INIT:
{ /* Begin case DIGI_INIT */
-
/* ------------------------------------------------------------
This call is made by the apps to complete the initilization
of the board(s). This routine is responsible for setting
the card to its initial state and setting the drivers control
fields to the sutianle settings for the card in question.
---------------------------------------------------------------- */
-
int crd ;
for (crd = 0; crd < num_cards; crd++)
post_fep_init (crd);
-
break ;
-
} /* End case DIGI_INIT */
-
-
default:
- return -ENOIOCTLCMD;
-
+ return -ENOTTY;
} /* End switch cmd */
return (0) ;
}
@@ -2750,43 +2270,33 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
struct channel *ch = (struct channel *) tty->driver_data;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
unsigned int mstat, mflag = 0;
unsigned long flags;
if (ch)
bc = ch->brdchan;
else
- {
- printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n");
- return(-EINVAL);
- }
+ return -EINVAL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- mstat = bc->mstat;
+ mstat = readb(&bc->mstat);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
if (mstat & ch->m_dtr)
mflag |= TIOCM_DTR;
-
if (mstat & ch->m_rts)
mflag |= TIOCM_RTS;
-
if (mstat & ch->m_cts)
mflag |= TIOCM_CTS;
-
if (mstat & ch->dsr)
mflag |= TIOCM_DSR;
-
if (mstat & ch->m_ri)
mflag |= TIOCM_RI;
-
if (mstat & ch->dcd)
mflag |= TIOCM_CD;
-
return mflag;
}
@@ -2796,13 +2306,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
struct channel *ch = (struct channel *) tty->driver_data;
unsigned long flags;
- if (!ch) {
- printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n");
- return(-EINVAL);
- }
+ if (!ch)
+ return -EINVAL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
/*
* I think this modemfake stuff is broken. It doesn't
* correctly reflect the behaviour desired by the TIOCM*
@@ -2824,17 +2331,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
ch->modemfake |= ch->m_dtr;
ch->modem &= ~ch->m_dtr;
}
-
globalwinon(ch);
-
/* --------------------------------------------------------------
The below routine generally sets up parity, baud, flow control
issues, etc.... It effect both control flags and input flags.
------------------------------------------------------------------ */
-
epcaparam(tty,ch);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
return 0;
}
@@ -2847,19 +2351,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
struct channel *ch = (struct channel *) tty->driver_data;
void __user *argp = (void __user *)arg;
if (ch)
bc = ch->brdchan;
else
- {
- printk(KERN_ERR "<Error> - ch is NULL in pc_ioctl!\n");
- return(-EINVAL);
- }
-
- save_flags(flags);
+ return -EINVAL;
/* -------------------------------------------------------------------
For POSIX compliance we need to add more ioctls. See tty_ioctl.c
@@ -2871,46 +2370,39 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
{ /* Begin switch cmd */
case TCGETS:
- if (copy_to_user(argp,
- tty->termios, sizeof(struct termios)))
+ if (copy_to_user(argp, tty->termios, sizeof(struct termios)))
return -EFAULT;
- return(0);
-
+ return 0;
case TCGETA:
return get_termio(tty, argp);
-
case TCSBRK: /* SVID version: non-zero arg --> no break */
-
retval = tty_check_change(tty);
if (retval)
return retval;
-
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
if (!arg)
digi_send_break(ch, HZ/4); /* 1/4 second */
return 0;
-
case TCSBRKP: /* support for POSIX tcsendbreak() */
-
retval = tty_check_change(tty);
if (retval)
return retval;
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
return 0;
-
case TIOCGSOFTCAR:
if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
return -EFAULT;
return 0;
-
case TIOCSSOFTCAR:
{
unsigned int value;
@@ -2922,75 +2414,63 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
(value ? CLOCAL : 0));
return 0;
}
-
case TIOCMODG:
mflag = pc_tiocmget(tty, file);
if (put_user(mflag, (unsigned long __user *)argp))
return -EFAULT;
break;
-
case TIOCMODS:
if (get_user(mstat, (unsigned __user *)argp))
return -EFAULT;
return pc_tiocmset(tty, file, mstat, ~mstat);
-
case TIOCSDTR:
+ spin_lock_irqsave(&epca_lock, flags);
ch->omodem |= ch->m_dtr;
- cli();
globalwinon(ch);
fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
case TIOCCDTR:
+ spin_lock_irqsave(&epca_lock, flags);
ch->omodem &= ~ch->m_dtr;
- cli();
globalwinon(ch);
fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
-
case DIGI_GETA:
if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
return -EFAULT;
break;
-
case DIGI_SETAW:
case DIGI_SETAF:
- if ((cmd) == (DIGI_SETAW))
- {
+ if (cmd == DIGI_SETAW) {
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
- }
- else
- {
+ } else {
/* ldisc lock already held in ioctl */
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
}
-
/* Fall Thru */
-
case DIGI_SETA:
if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
return -EFAULT;
- if (ch->digiext.digi_flags & DIGI_ALTPIN)
- {
+ if (ch->digiext.digi_flags & DIGI_ALTPIN) {
ch->dcd = ch->m_dsr;
ch->dsr = ch->m_dcd;
- }
- else
- {
+ } else {
ch->dcd = ch->m_dcd;
ch->dsr = ch->m_dsr;
}
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
/* -----------------------------------------------------------------
@@ -3000,25 +2480,22 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
epcaparam(tty,ch);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
case DIGI_GETFLOW:
case DIGI_GETAFLOW:
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- if ((cmd) == (DIGI_GETFLOW))
- {
- dflow.startc = bc->startc;
- dflow.stopc = bc->stopc;
- }
- else
- {
- dflow.startc = bc->startca;
- dflow.stopc = bc->stopca;
+ if (cmd == DIGI_GETFLOW) {
+ dflow.startc = readb(&bc->startc);
+ dflow.stopc = readb(&bc->stopc);
+ } else {
+ dflow.startc = readb(&bc->startca);
+ dflow.stopc = readb(&bc->stopca);
}
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
if (copy_to_user(argp, &dflow, sizeof(dflow)))
return -EFAULT;
@@ -3026,13 +2503,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
case DIGI_SETAFLOW:
case DIGI_SETFLOW:
- if ((cmd) == (DIGI_SETFLOW))
- {
+ if (cmd == DIGI_SETFLOW) {
startc = ch->startc;
stopc = ch->stopc;
- }
- else
- {
+ } else {
startc = ch->startca;
stopc = ch->stopca;
}
@@ -3040,40 +2514,31 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
if (copy_from_user(&dflow, argp, sizeof(dflow)))
return -EFAULT;
- if (dflow.startc != startc || dflow.stopc != stopc)
- { /* Begin if setflow toggled */
- cli();
+ if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- if ((cmd) == (DIGI_SETFLOW))
- {
+ if (cmd == DIGI_SETFLOW) {
ch->fepstartc = ch->startc = dflow.startc;
ch->fepstopc = ch->stopc = dflow.stopc;
fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
- }
- else
- {
+ } else {
ch->fepstartca = ch->startca = dflow.startc;
ch->fepstopca = ch->stopca = dflow.stopc;
fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
- if (ch->statusflags & TXSTOPPED)
+ if (ch->statusflags & TXSTOPPED)
pc_start(tty);
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if setflow toggled */
break;
-
default:
return -ENOIOCTLCMD;
-
} /* End switch cmd */
-
return 0;
-
} /* End pc_ioctl */
/* --------------------- Begin pc_set_termios ----------------------- */
@@ -3083,20 +2548,16 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
- save_flags(flags);
- cli();
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
epcaparam(tty, ch);
memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
((tty->termios->c_cflag & CRTSCTS) == 0))
@@ -3106,8 +2567,6 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
(tty->termios->c_cflag & CLOCAL))
wake_up_interruptible(&ch->open_wait);
- restore_flags(flags);
-
} /* End if channel valid */
} /* End pc_set_termios */
@@ -3116,29 +2575,18 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
static void do_softint(void *private_)
{ /* Begin do_softint */
-
struct channel *ch = (struct channel *) private_;
-
-
/* Called in response to a modem change event */
-
- if (ch && ch->magic == EPCA_MAGIC)
- { /* Begin EPCA_MAGIC */
-
+ if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */
struct tty_struct *tty = ch->tty;
- if (tty && tty->driver_data)
- {
- if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event))
- { /* Begin if clear_bit */
-
+ if (tty && tty->driver_data) {
+ if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
wake_up_interruptible(&ch->open_wait);
ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-
} /* End if clear_bit */
}
-
} /* End EPCA_MAGIC */
} /* End do_softint */
@@ -3154,82 +2602,49 @@ static void pc_stop(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if valid channel */
-
- save_flags(flags);
- cli();
-
- if ((ch->statusflags & TXSTOPPED) == 0)
- { /* Begin if transmit stop requested */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if valid channel */
+ spin_lock_irqsave(&epca_lock, flags);
+ if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
globalwinon(ch);
-
/* STOP transmitting now !! */
-
fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-
ch->statusflags |= TXSTOPPED;
memoff(ch);
-
} /* End if transmit stop requested */
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if valid channel */
-
} /* End pc_stop */
/* --------------------- Begin pc_start ----------------------- */
static void pc_start(struct tty_struct *tty)
{ /* Begin pc_start */
-
struct channel *ch;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
unsigned long flags;
-
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* Just in case output was resumed because of a change in Digi-flow */
- if (ch->statusflags & TXSTOPPED)
- { /* Begin transmit resume requested */
-
- volatile struct board_chan *bc;
-
+ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */
+ struct board_chan *bc;
globalwinon(ch);
bc = ch->brdchan;
if (ch->statusflags & LOWWAIT)
- bc->ilow = 1;
-
+ writeb(1, &bc->ilow);
/* Okay, you can start transmitting again... */
-
fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-
ch->statusflags &= ~TXSTOPPED;
memoff(ch);
-
} /* End transmit resume requested */
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_start */
/* ------------------------------------------------------------------
@@ -3244,86 +2659,55 @@ ______________________________________________________________________ */
static void pc_throttle(struct tty_struct * tty)
{ /* Begin pc_throttle */
-
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
-
- save_flags(flags);
- cli();
-
- if ((ch->statusflags & RXSTOPPED) == 0)
- {
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ spin_lock_irqsave(&epca_lock, flags);
+ if ((ch->statusflags & RXSTOPPED) == 0) {
globalwinon(ch);
fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-
ch->statusflags |= RXSTOPPED;
memoff(ch);
}
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_throttle */
/* --------------------- Begin unthrottle ----------------------- */
static void pc_unthrottle(struct tty_struct *tty)
{ /* Begin pc_unthrottle */
-
struct channel *ch;
unsigned long flags;
- volatile struct board_chan *bc;
-
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
/* Just in case output was resumed because of a change in Digi-flow */
- save_flags(flags);
- cli();
-
- if (ch->statusflags & RXSTOPPED)
- {
-
+ spin_lock_irqsave(&epca_lock, flags);
+ if (ch->statusflags & RXSTOPPED) {
globalwinon(ch);
- bc = ch->brdchan;
fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-
ch->statusflags &= ~RXSTOPPED;
memoff(ch);
}
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_unthrottle */
/* --------------------- Begin digi_send_break ----------------------- */
void digi_send_break(struct channel *ch, int msec)
{ /* Begin digi_send_break */
-
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
-
/* --------------------------------------------------------------------
Maybe I should send an infinite break here, schedule() for
msec amount of time, and then stop the break. This way,
@@ -3331,36 +2715,28 @@ void digi_send_break(struct channel *ch, int msec)
to be called (i.e. via an ioctl()) more than once in msec amount
of time. Try this for now...
------------------------------------------------------------------------ */
-
fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
memoff(ch);
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End digi_send_break */
/* --------------------- Begin setup_empty_event ----------------------- */
+/* Caller MUST hold the lock */
+
static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
{ /* Begin setup_empty_event */
- volatile struct board_chan *bc = ch->brdchan;
- unsigned long int flags;
+ struct board_chan *bc = ch->brdchan;
- save_flags(flags);
- cli();
globalwinon(ch);
ch->statusflags |= EMPTYWAIT;
-
/* ------------------------------------------------------------------
When set the iempty flag request a event to be generated when the
transmit buffer is empty (If there is no BREAK in progress).
--------------------------------------------------------------------- */
-
- bc->iempty = 1;
+ writeb(1, &bc->iempty);
memoff(ch);
- restore_flags(flags);
-
} /* End setup_empty_event */
/* --------------------- Begin get_termio ----------------------- */
@@ -3369,10 +2745,10 @@ static int get_termio(struct tty_struct * tty, struct termio __user * termio)
{ /* Begin get_termio */
return kernel_termios_to_user_termio(termio, tty->termios);
} /* End get_termio */
+
/* ---------------------- Begin epca_setup -------------------------- */
void epca_setup(char *str, int *ints)
{ /* Begin epca_setup */
-
struct board_info board;
int index, loop, last;
char *temp, *t2;
@@ -3394,49 +2770,41 @@ void epca_setup(char *str, int *ints)
for (last = 0, index = 1; index <= ints[0]; index++)
switch(index)
{ /* Begin parse switch */
-
case 1:
board.status = ints[index];
-
/* ---------------------------------------------------------
We check for 2 (As opposed to 1; because 2 is a flag
instructing the driver to ignore epcaconfig.) For this
reason we check for 2.
------------------------------------------------------------ */
- if (board.status == 2)
- { /* Begin ignore epcaconfig as well as lilo cmd line */
+ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
nbdevs = 0;
num_cards = 0;
return;
} /* End ignore epcaconfig as well as lilo cmd line */
- if (board.status > 2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board status 0x%x\n", board.status);
+ if (board.status > 2) {
+ printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_STATUS;
return;
}
last = index;
break;
-
case 2:
board.type = ints[index];
- if (board.type >= PCIXEM)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board type 0x%x\n", board.type);
+ if (board.type >= PCIXEM) {
+ printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_TYPE;
return;
}
last = index;
break;
-
case 3:
board.altpin = ints[index];
- if (board.altpin > 1)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board altpin 0x%x\n", board.altpin);
+ if (board.altpin > 1) {
+ printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
invalid_lilo_config = 1;
setup_error_code |= INVALID_ALTPIN;
return;
@@ -3446,9 +2814,8 @@ void epca_setup(char *str, int *ints)
case 4:
board.numports = ints[index];
- if ((board.numports < 2) || (board.numports > 256))
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board numports 0x%x\n", board.numports);
+ if (board.numports < 2 || board.numports > 256) {
+ printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
invalid_lilo_config = 1;
setup_error_code |= INVALID_NUM_PORTS;
return;
@@ -3458,10 +2825,9 @@ void epca_setup(char *str, int *ints)
break;
case 5:
- board.port = (unsigned char *)ints[index];
- if (ints[index] <= 0)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
+ board.port = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
invalid_lilo_config = 1;
setup_error_code |= INVALID_PORT_BASE;
return;
@@ -3470,10 +2836,9 @@ void epca_setup(char *str, int *ints)
break;
case 6:
- board.membase = (unsigned char *)ints[index];
- if (ints[index] <= 0)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+ board.membase = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
invalid_lilo_config = 1;
setup_error_code |= INVALID_MEM_BASE;
return;
@@ -3487,21 +2852,16 @@ void epca_setup(char *str, int *ints)
} /* End parse switch */
- while (str && *str)
- { /* Begin while there is a string arg */
-
+ while (str && *str) { /* Begin while there is a string arg */
/* find the next comma or terminator */
temp = str;
-
/* While string is not null, and a comma hasn't been found */
while (*temp && (*temp != ','))
temp++;
-
if (!*temp)
temp = NULL;
else
*temp++ = 0;
-
/* Set index to the number of args + 1 */
index = last + 1;
@@ -3511,12 +2871,10 @@ void epca_setup(char *str, int *ints)
len = strlen(str);
if (strncmp("Disable", str, len) == 0)
board.status = 0;
- else
- if (strncmp("Enable", str, len) == 0)
+ else if (strncmp("Enable", str, len) == 0)
board.status = 1;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid status %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_STATUS;
return;
@@ -3525,22 +2883,17 @@ void epca_setup(char *str, int *ints)
break;
case 2:
-
for(loop = 0; loop < EPCA_NUM_TYPES; loop++)
if (strcmp(board_desc[loop], str) == 0)
break;
-
-
/* ---------------------------------------------------------------
If the index incremented above refers to a legitamate board
type set it here.
------------------------------------------------------------------*/
-
if (index < EPCA_NUM_TYPES)
board.type = loop;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board type: %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_TYPE;
return;
@@ -3552,12 +2905,10 @@ void epca_setup(char *str, int *ints)
len = strlen(str);
if (strncmp("Disable", str, len) == 0)
board.altpin = 0;
- else
- if (strncmp("Enable", str, len) == 0)
+ else if (strncmp("Enable", str, len) == 0)
board.altpin = 1;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid altpin %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_ALTPIN;
return;
@@ -3570,9 +2921,8 @@ void epca_setup(char *str, int *ints)
while (isdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid port count %s\n", str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_NUM_PORTS;
return;
@@ -3601,15 +2951,14 @@ void epca_setup(char *str, int *ints)
while (isxdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid i/o address %s\n", str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_PORT_BASE;
return;
}
- board.port = (unsigned char *)simple_strtoul(str, NULL, 16);
+ board.port = simple_strtoul(str, NULL, 16);
last = index;
break;
@@ -3618,52 +2967,38 @@ void epca_setup(char *str, int *ints)
while (isxdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid memory base %s\n",str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_MEM_BASE;
return;
}
-
- board.membase = (unsigned char *)simple_strtoul(str, NULL, 16);
+ board.membase = simple_strtoul(str, NULL, 16);
last = index;
break;
-
default:
- printk(KERN_ERR "PC/Xx: Too many string parms\n");
+ printk(KERN_ERR "epca: Too many string parms\n");
return;
}
str = temp;
-
} /* End while there is a string arg */
-
- if (last < 6)
- {
- printk(KERN_ERR "PC/Xx: Insufficient parms specified\n");
+ if (last < 6) {
+ printk(KERN_ERR "epca: Insufficient parms specified\n");
return;
}
/* I should REALLY validate the stuff here */
-
/* Copies our local copy of board into boards */
memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
-
-
/* Does this get called once per lilo arg are what ? */
-
printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
num_cards, board_desc[board.type],
board.numports, (int)board.port, (unsigned int) board.membase);
-
num_cards++;
-
} /* End epca_setup */
-
-#ifdef ENABLE_PCI
/* ------------------------ Begin init_PCI --------------------------- */
enum epic_board_types {
@@ -3685,7 +3020,6 @@ static struct {
{ PCIXRJ, 2, },
};
-
static int __devinit epca_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3711,10 +3045,8 @@ static int __devinit epca_init_one (struct pci_dev *pdev,
boards[board_idx].status = ENABLED;
boards[board_idx].type = epca_info_tbl[info_idx].board_type;
boards[board_idx].numports = 0x0;
- boards[board_idx].port =
- (unsigned char *)((char *) addr + PCI_IO_OFFSET);
- boards[board_idx].membase =
- (unsigned char *)((char *) addr);
+ boards[board_idx].port = addr + PCI_IO_OFFSET;
+ boards[board_idx].membase = addr;
if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
@@ -3775,15 +3107,13 @@ static struct pci_device_id epca_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
int __init init_PCI (void)
-{ /* Begin init_PCI */
+{ /* Begin init_PCI */
memset (&epca_driver, 0, sizeof (epca_driver));
epca_driver.name = "epca";
epca_driver.id_table = epca_pci_tbl;
epca_driver.probe = epca_init_one;
return pci_register_driver(&epca_driver);
-} /* End init_PCI */
-
-#endif /* ENABLE_PCI */
+}
MODULE_LICENSE("GPL");
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
index 52205ef71314..20eeb5a70e1a 100644
--- a/drivers/char/epca.h
+++ b/drivers/char/epca.h
@@ -85,73 +85,73 @@ static char *board_desc[] =
struct channel
{
long magic;
- unchar boardnum;
- unchar channelnum;
- unchar omodem; /* FEP output modem status */
- unchar imodem; /* FEP input modem status */
- unchar modemfake; /* Modem values to be forced */
- unchar modem; /* Force values */
- unchar hflow;
- unchar dsr;
- unchar dcd;
- unchar m_rts ; /* The bits used in whatever FEP */
- unchar m_dcd ; /* is indiginous to this board to */
- unchar m_dsr ; /* represent each of the physical */
- unchar m_cts ; /* handshake lines */
- unchar m_ri ;
- unchar m_dtr ;
- unchar stopc;
- unchar startc;
- unchar stopca;
- unchar startca;
- unchar fepstopc;
- unchar fepstartc;
- unchar fepstopca;
- unchar fepstartca;
- unchar txwin;
- unchar rxwin;
- ushort fepiflag;
- ushort fepcflag;
- ushort fepoflag;
- ushort txbufhead;
- ushort txbufsize;
- ushort rxbufhead;
- ushort rxbufsize;
+ unsigned char boardnum;
+ unsigned char channelnum;
+ unsigned char omodem; /* FEP output modem status */
+ unsigned char imodem; /* FEP input modem status */
+ unsigned char modemfake; /* Modem values to be forced */
+ unsigned char modem; /* Force values */
+ unsigned char hflow;
+ unsigned char dsr;
+ unsigned char dcd;
+ unsigned char m_rts ; /* The bits used in whatever FEP */
+ unsigned char m_dcd ; /* is indiginous to this board to */
+ unsigned char m_dsr ; /* represent each of the physical */
+ unsigned char m_cts ; /* handshake lines */
+ unsigned char m_ri ;
+ unsigned char m_dtr ;
+ unsigned char stopc;
+ unsigned char startc;
+ unsigned char stopca;
+ unsigned char startca;
+ unsigned char fepstopc;
+ unsigned char fepstartc;
+ unsigned char fepstopca;
+ unsigned char fepstartca;
+ unsigned char txwin;
+ unsigned char rxwin;
+ unsigned short fepiflag;
+ unsigned short fepcflag;
+ unsigned short fepoflag;
+ unsigned short txbufhead;
+ unsigned short txbufsize;
+ unsigned short rxbufhead;
+ unsigned short rxbufsize;
int close_delay;
int count;
int blocked_open;
- ulong event;
+ unsigned long event;
int asyncflags;
uint dev;
- ulong statusflags;
- ulong c_iflag;
- ulong c_cflag;
- ulong c_lflag;
- ulong c_oflag;
- unchar *txptr;
- unchar *rxptr;
- unchar *tmp_buf;
+ unsigned long statusflags;
+ unsigned long c_iflag;
+ unsigned long c_cflag;
+ unsigned long c_lflag;
+ unsigned long c_oflag;
+ unsigned char *txptr;
+ unsigned char *rxptr;
+ unsigned char *tmp_buf;
struct board_info *board;
- volatile struct board_chan *brdchan;
+ struct board_chan *brdchan;
struct digi_struct digiext;
struct tty_struct *tty;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
- struct work_struct tqueue;
- volatile struct global_data *mailbox;
+ struct work_struct tqueue;
+ struct global_data *mailbox;
};
struct board_info
{
- unchar status;
- unchar type;
- unchar altpin;
- ushort numports;
- unchar *port;
- unchar *membase;
- unchar __iomem *re_map_port;
- unchar *re_map_membase;
- ulong memory_seg;
+ unsigned char status;
+ unsigned char type;
+ unsigned char altpin;
+ unsigned short numports;
+ unsigned long port;
+ unsigned long membase;
+ unsigned char __iomem *re_map_port;
+ unsigned char *re_map_membase;
+ unsigned long memory_seg;
void ( * memwinon ) (struct board_info *, unsigned int) ;
void ( * memwinoff ) (struct board_info *, unsigned int) ;
void ( * globalwinon ) (struct channel *) ;
@@ -160,6 +160,6 @@ struct board_info
void ( * memoff ) (struct channel *) ;
void ( * assertgwinon ) (struct channel *) ;
void ( * assertmemoff ) (struct channel *) ;
- unchar poller_inhibited ;
+ unsigned char poller_inhibited ;
};
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 1704a2a57048..b2e0928e8428 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -387,10 +387,8 @@ int fdc_interrupt_wait(unsigned int time)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&ftape_wait_intr, &wait);
- while (!ft_interrupt_seen && timeout) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
+ while (!ft_interrupt_seen && timeout)
+ timeout = schedule_timeout_interruptible(timeout);
spin_lock_irq(&current->sighand->siglock);
current->blocked = old_sigmask;
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 81d811edf3c5..a54bc93353af 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -149,8 +149,7 @@ static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
static void hangcheck_fire(unsigned long);
-static struct timer_list hangcheck_ticktock =
- TIMER_INITIALIZER(hangcheck_fire, 0, 0);
+static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
static void hangcheck_fire(unsigned long data)
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 762fa430fb5b..de0379b6d502 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -44,7 +44,7 @@
/*
* The High Precision Event Timer driver.
* This driver is closely modelled after the rtc.c driver.
- * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
+ * http://www.intel.com/hardwaredesign/hpetspec.htm
*/
#define HPET_USER_FREQ (64)
#define HPET_DRIFT (500)
@@ -100,14 +100,14 @@ static struct hpets *hpets;
#endif
#ifndef readq
-static unsigned long long __inline readq(void __iomem *addr)
+static inline unsigned long long readq(void __iomem *addr)
{
return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
}
#endif
#ifndef writeq
-static void __inline writeq(unsigned long long v, void __iomem *addr)
+static inline void writeq(unsigned long long v, void __iomem *addr)
{
writel(v & 0xffffffff, addr);
writel(v >> 32, addr + 4);
@@ -712,7 +712,7 @@ static void hpet_register_interpolator(struct hpets *hpetp)
ti->shift = 10;
ti->addr = &hpetp->hp_hpet->hpet_mc;
ti->frequency = hpet_time_div(hpets->hp_period);
- ti->drift = ti->frequency * HPET_DRIFT / 1000000;
+ ti->drift = HPET_DRIFT;
ti->mask = -1;
hpetp->hp_interpolator = ti;
@@ -906,11 +906,15 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
if (irqp->number_of_interrupts > 0) {
hdp->hd_nirqs = irqp->number_of_interrupts;
- for (i = 0; i < hdp->hd_nirqs; i++)
- hdp->hd_irq[i] =
+ for (i = 0; i < hdp->hd_nirqs; i++) {
+ int rc =
acpi_register_gsi(irqp->interrupts[i],
irqp->edge_level,
irqp->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ hdp->hd_irq[i] = rc;
+ }
}
}
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index 60bb9152b832..78d681dc35a8 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -39,7 +39,7 @@ char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = {
{"serial", "hvterm1"},
- { NULL, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, hvc_driver_table);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 3236d2404905..f47f009f9259 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -527,7 +527,7 @@ static int khvcsd(void *unused)
static struct vio_device_id hvcs_driver_table[] __devinitdata= {
{"serial-server", "hvterm2"},
- { NULL, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 3480535a09c5..6f673d2de0b1 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -513,10 +513,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
return ret ? : -EAGAIN;
if(need_resched())
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
+ schedule_timeout_interruptible(1);
else
udelay(200); /* FIXME: We could poll for 250uS ?? */
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 82c5f30375ac..ba85eb1b6ec7 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -655,8 +655,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
timeout--; // So negative values == forever
if (!in_interrupt()) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1); // short nap
+ schedule_timeout_interruptible(1); // short nap
} else {
// we cannot sched/sleep in interrrupt silly
return 0;
@@ -1132,8 +1131,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user )
ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2);
+ schedule_timeout_interruptible(2);
if (signal_pending(current)) {
break;
}
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index cf0cd58d6305..9e4e26aef94e 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -120,7 +120,6 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <asm/serial.h>
#include <asm/uaccess.h>
@@ -255,7 +254,7 @@ static unsigned long bh_counter = 0;
* selected, the board is serviced periodically to see if anything needs doing.
*/
#define POLL_TIMEOUT (jiffies + 1)
-static struct timer_list PollTimer = TIMER_INITIALIZER(ip2_poll, 0, 0);
+static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
static char TimerOn;
#ifdef IP2DEBUG_TRACE
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 5ce9c6269033..33862670e285 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -31,8 +31,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_BT_VERSION "v33"
-
static int bt_debug = 0x00; /* Production value 0, see following flags */
#define BT_DEBUG_ENABLE 1
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
{
unsigned int i;
- if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1;
+ if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+ return -1;
if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
return -2;
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
if (bt_debug & BT_DEBUG_MSG) {
printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
- for (i = 0; i < size; i ++) printk (" %02x", data[i]);
+ for (i = 0; i < size; i ++)
+ printk (" %02x", data[i]);
printk("\n");
}
bt->write_data[0] = size + 1; /* all data plus seq byte */
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt,
} else {
data[0] = bt->read_data[1];
data[1] = bt->read_data[3];
- if (length < msg_len) bt->truncated = 1;
+ if (length < msg_len)
+ bt->truncated = 1;
if (bt->truncated) { /* can be set in read_all_bytes() */
data[2] = IPMI_ERR_MSG_TRUNCATED;
msg_len = 3;
- } else memcpy(data + 2, bt->read_data + 4, msg_len - 2);
+ } else
+ memcpy(data + 2, bt->read_data + 4, msg_len - 2);
if (bt_debug & BT_DEBUG_MSG) {
printk (KERN_WARNING "BT: res (raw)");
- for (i = 0; i < msg_len; i++) printk(" %02x", data[i]);
+ for (i = 0; i < msg_len; i++)
+ printk(" %02x", data[i]);
printk ("\n");
}
}
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt,
static void reset_flags(struct si_sm_data *bt)
{
- if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY);
- if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
+ if (BT_STATUS & BT_H_BUSY)
+ BT_CONTROL(BT_H_BUSY);
+ if (BT_STATUS & BT_B_BUSY)
+ BT_CONTROL(BT_B_BUSY);
BT_CONTROL(BT_CLR_WR_PTR);
BT_CONTROL(BT_SMS_ATN);
#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt)
BT_CONTROL(BT_H_BUSY);
BT_CONTROL(BT_B2H_ATN);
BT_CONTROL(BT_CLR_RD_PTR);
- for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST;
+ for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++)
+ BMC2HOST;
BT_CONTROL(BT_H_BUSY);
}
#endif
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt)
printk (" %02x", bt->write_data[i]);
printk ("\n");
}
- for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]);
+ for (i = 0; i < bt->write_count; i++)
+ HOST2BMC(bt->write_data[i]);
}
static inline int read_all_bytes(struct si_sm_data *bt)
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
bt->truncated = 1;
return 1; /* let next XACTION START clean it up */
}
- for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST;
+ for (i = 1; i <= bt->read_count; i++)
+ bt->read_data[i] = BMC2HOST;
bt->read_count++; /* account for the length byte */
if (bt_debug & BT_DEBUG_MSG) {
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
return 1;
- if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: "
+ if (bt_debug & BT_DEBUG_MSG)
+ printk(KERN_WARNING "BT: bad packet: "
"want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
bt->write_data[1], bt->write_data[2], bt->write_data[3],
bt->read_data[1], bt->read_data[2], bt->read_data[3]);
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
time);
bt->last_state = bt->state;
- if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED;
+ if (bt->state == BT_STATE_HOSED)
+ return SI_SM_HOSED;
if (bt->state != BT_STATE_IDLE) { /* do timeout test */
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
/* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
(noticed in ipmi_smic_sm.c January 2004) */
- if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100;
+ if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
+ time = 100;
bt->timeout -= time;
if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
error_recovery(bt, "timed out");
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
BT_CONTROL(BT_H_BUSY);
break;
}
- if (status & BT_B2H_ATN) break;
+ if (status & BT_B2H_ATN)
+ break;
bt->state = BT_STATE_WRITE_BYTES;
return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
case BT_STATE_WRITE_BYTES:
- if (status & (BT_B_BUSY | BT_H2B_ATN)) break;
+ if (status & (BT_B_BUSY | BT_H2B_ATN))
+ break;
BT_CONTROL(BT_CLR_WR_PTR);
write_all_bytes(bt);
BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
- if (status & (BT_H2B_ATN | BT_B_BUSY)) break;
+ if (status & (BT_H2B_ATN | BT_B_BUSY))
+ break;
bt->state = BT_STATE_B2H_WAIT;
/* fall through with status */
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
case BT_STATE_B2H_WAIT:
- if (!(status & BT_B2H_ATN)) break;
+ if (!(status & BT_B2H_ATN))
+ break;
/* Assume ordered, uncached writes: no need to wait */
- if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */
+ if (!(status & BT_H_BUSY))
+ BT_CONTROL(BT_H_BUSY); /* set */
BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */
BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */
i = read_all_bytes(bt);
BT_CONTROL(BT_H_BUSY); /* clear */
- if (!i) break; /* Try this state again */
+ if (!i) /* Try this state again */
+ break;
bt->state = BT_STATE_READ_END;
return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
#ifdef MAKE_THIS_TRUE_IF_NECESSARY
- if (status & BT_H_BUSY) break;
+ if (status & BT_H_BUSY)
+ break;
#endif
bt->seq++;
bt->state = BT_STATE_IDLE;
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
break;
case BT_STATE_RESET3:
- if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY;
+ if (bt->timeout > 0)
+ return SI_SM_CALL_WITH_DELAY;
bt->state = BT_STATE_RESTART; /* printk in debug modes */
break;
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt)
but that's what you get from reading a bogus address, so we
test that first. The calling routine uses negative logic. */
- if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1;
+ if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
+ return 1;
reset_flags(bt);
return 0;
}
@@ -501,7 +521,6 @@ static int bt_size(void)
struct si_sm_handlers bt_smi_handlers =
{
- .version = IPMI_BT_VERSION,
.init_data = bt_init_data,
.start_transaction = bt_start_transaction,
.get_result = bt_get_result,
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index e0a53570fea1..a09ff1080687 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -47,8 +47,6 @@
#include <linux/device.h>
#include <linux/compat.h>
-#define IPMI_DEVINTF_VERSION "v33"
-
struct ipmi_file_private
{
ipmi_user_t user;
@@ -411,6 +409,7 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
+ /* The next four are legacy, not per-channel. */
case IPMICTL_SET_MY_ADDRESS_CMD:
{
unsigned int val;
@@ -420,22 +419,25 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
- ipmi_set_my_address(priv->user, val);
- rv = 0;
+ rv = ipmi_set_my_address(priv->user, 0, val);
break;
}
case IPMICTL_GET_MY_ADDRESS_CMD:
{
- unsigned int val;
+ unsigned int val;
+ unsigned char rval;
+
+ rv = ipmi_get_my_address(priv->user, 0, &rval);
+ if (rv)
+ break;
- val = ipmi_get_my_address(priv->user);
+ val = rval;
if (copy_to_user(arg, &val, sizeof(val))) {
rv = -EFAULT;
break;
}
- rv = 0;
break;
}
@@ -448,24 +450,94 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
- ipmi_set_my_LUN(priv->user, val);
- rv = 0;
+ rv = ipmi_set_my_LUN(priv->user, 0, val);
break;
}
case IPMICTL_GET_MY_LUN_CMD:
{
- unsigned int val;
+ unsigned int val;
+ unsigned char rval;
- val = ipmi_get_my_LUN(priv->user);
+ rv = ipmi_get_my_LUN(priv->user, 0, &rval);
+ if (rv)
+ break;
+
+ val = rval;
+
+ if (copy_to_user(arg, &val, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+ break;
+ }
+
+ case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ return ipmi_set_my_address(priv->user, val.channel, val.value);
+ break;
+ }
+
+ case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
+ if (rv)
+ break;
+
+ if (copy_to_user(arg, &val, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+ break;
+ }
+
+ case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
+ break;
+ }
+
+ case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
+ if (rv)
+ break;
if (copy_to_user(arg, &val, sizeof(val))) {
rv = -EFAULT;
break;
}
- rv = 0;
break;
}
+
case IPMICTL_SET_TIMING_PARMS_CMD:
{
struct ipmi_timing_parms parms;
@@ -663,7 +735,8 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
case COMPAT_IPMICTL_RECEIVE_MSG:
case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
{
- struct ipmi_recv *precv64, recv64;
+ struct ipmi_recv __user *precv64;
+ struct ipmi_recv recv64;
if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
return -EFAULT;
@@ -676,7 +749,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
? IPMICTL_RECEIVE_MSG
: IPMICTL_RECEIVE_MSG_TRUNC),
- (long) precv64);
+ (unsigned long) precv64);
if (rc != 0)
return rc;
@@ -748,8 +821,7 @@ static __init int init_ipmi_devintf(void)
if (ipmi_major < 0)
return -EINVAL;
- printk(KERN_INFO "ipmi device interface version "
- IPMI_DEVINTF_VERSION "\n");
+ printk(KERN_INFO "ipmi device interface\n");
ipmi_class = class_create(THIS_MODULE, "ipmi");
if (IS_ERR(ipmi_class)) {
@@ -792,3 +864,5 @@ static __exit void cleanup_ipmi(void)
module_exit(cleanup_ipmi);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index 48cce24329be..d21853a594a3 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -42,8 +42,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_KCS_VERSION "v33"
-
/* Set this if you want a printout of why the state machine was hosed
when it gets hosed. */
#define DEBUG_HOSED_REASON
@@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs)
struct si_sm_handlers kcs_smi_handlers =
{
- .version = IPMI_KCS_VERSION,
.init_data = init_kcs_data,
.start_transaction = start_kcs_transaction,
.get_result = get_kcs_result,
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e16c13fe698d..463351d4f942 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -47,7 +47,8 @@
#include <linux/proc_fs.h>
#define PFX "IPMI message handler: "
-#define IPMI_MSGHANDLER_VERSION "v33"
+
+#define IPMI_DRIVER_VERSION "36.0"
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
@@ -116,7 +117,7 @@ struct seq_table
do { \
seq = ((msgid >> 26) & 0x3f); \
seqid = (msgid & 0x3fffff); \
- } while(0)
+ } while (0)
#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
@@ -124,6 +125,14 @@ struct ipmi_channel
{
unsigned char medium;
unsigned char protocol;
+
+ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
+ but may be changed by the user. */
+ unsigned char address;
+
+ /* My LUN. This should generally stay the SMS LUN, but just in
+ case... */
+ unsigned char lun;
};
#ifdef CONFIG_PROC_FS
@@ -135,7 +144,7 @@ struct ipmi_proc_entry
#endif
#define IPMI_IPMB_NUM_SEQ 64
-#define IPMI_MAX_CHANNELS 8
+#define IPMI_MAX_CHANNELS 16
struct ipmi_smi
{
/* What interface number are we? */
@@ -193,20 +202,6 @@ struct ipmi_smi
struct list_head waiting_events;
unsigned int waiting_events_count; /* How many events in queue? */
- /* This will be non-null if someone registers to receive all
- IPMI commands (this is for interface emulation). There
- may not be any things in the cmd_rcvrs list above when
- this is registered. */
- ipmi_user_t all_cmd_rcvr;
-
- /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
- but may be changed by the user. */
- unsigned char my_address;
-
- /* My LUN. This should generally stay the SMS LUN, but just in
- case... */
- unsigned char my_lun;
-
/* The event receiver for my BMC, only really used at panic
shutdown as a place to store this. */
unsigned char event_receiver;
@@ -218,7 +213,7 @@ struct ipmi_smi
interface comes in with a NULL user, call this routine with
it. Note that the message will still be freed by the
caller. This only works on the system interface. */
- void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
+ void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);
/* When we are scanning the channels for an SMI, this will
tell which channel we are scanning. */
@@ -325,7 +320,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
down_read(&interfaces_sem);
down_write(&smi_watchers_sem);
list_add(&(watcher->link), &smi_watchers);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] != NULL) {
watcher->new_smi(i);
}
@@ -458,7 +453,27 @@ unsigned int ipmi_addr_length(int addr_type)
static void deliver_response(struct ipmi_recv_msg *msg)
{
- msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
+ if (! msg->user) {
+ ipmi_smi_t intf = msg->user_msg_data;
+ unsigned long flags;
+
+ /* Special handling for NULL users. */
+ if (intf->null_user_handler) {
+ intf->null_user_handler(intf, msg);
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->handled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
+ } else {
+ /* No handler, so give up. */
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->unhandled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
+ }
+ ipmi_free_recv_msg(msg);
+ } else {
+ msg->user->handler->ipmi_recv_hndl(msg,
+ msg->user->handler_data);
+ }
}
/* Find the next sequence number not being used and add the given
@@ -475,9 +490,9 @@ static int intf_next_seq(ipmi_smi_t intf,
int rv = 0;
unsigned int i;
- for (i=intf->curr_seq;
+ for (i = intf->curr_seq;
(i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
- i=(i+1)%IPMI_IPMB_NUM_SEQ)
+ i = (i+1)%IPMI_IPMB_NUM_SEQ)
{
if (! intf->seq_table[i].inuse)
break;
@@ -712,7 +727,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user)
/* Remove the user from the interfaces sequence table. */
spin_lock_irqsave(&(user->intf->seq_lock), flags);
- for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
if (user->intf->seq_table[i].inuse
&& (user->intf->seq_table[i].recv_msg->user == user))
{
@@ -766,26 +781,44 @@ void ipmi_get_version(ipmi_user_t user,
*minor = user->intf->version_minor;
}
-void ipmi_set_my_address(ipmi_user_t user,
- unsigned char address)
+int ipmi_set_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char address)
{
- user->intf->my_address = address;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ user->intf->channels[channel].address = address;
+ return 0;
}
-unsigned char ipmi_get_my_address(ipmi_user_t user)
+int ipmi_get_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *address)
{
- return user->intf->my_address;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *address = user->intf->channels[channel].address;
+ return 0;
}
-void ipmi_set_my_LUN(ipmi_user_t user,
- unsigned char LUN)
+int ipmi_set_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char LUN)
{
- user->intf->my_lun = LUN & 0x3;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ user->intf->channels[channel].lun = LUN & 0x3;
+ return 0;
}
-unsigned char ipmi_get_my_LUN(ipmi_user_t user)
+int ipmi_get_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *address)
{
- return user->intf->my_lun;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *address = user->intf->channels[channel].lun;
+ return 0;
}
int ipmi_set_gets_events(ipmi_user_t user, int val)
@@ -828,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t user,
read_lock(&(user->intf->users_lock));
write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
- if (user->intf->all_cmd_rcvr != NULL) {
- rv = -EBUSY;
- goto out_unlock;
- }
-
/* Make sure the command/netfn is not already registered. */
list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {
if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
@@ -847,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
rcvr->user = user;
list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
}
- out_unlock:
+
write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
read_unlock(&(user->intf->users_lock));
@@ -1213,7 +1241,7 @@ static inline int i_ipmi_request(ipmi_user_t user,
unsigned char ipmb_seq;
long seqid;
- if (addr->channel > IPMI_NUM_CHANNELS) {
+ if (addr->channel >= IPMI_NUM_CHANNELS) {
spin_lock_irqsave(&intf->counter_lock, flags);
intf->sent_invalid_commands++;
spin_unlock_irqrestore(&intf->counter_lock, flags);
@@ -1331,7 +1359,7 @@ static inline int i_ipmi_request(ipmi_user_t user,
#ifdef DEBUG_MSGING
{
int m;
- for (m=0; m<smi_msg->data_size; m++)
+ for (m = 0; m < smi_msg->data_size; m++)
printk(" %2.2x", smi_msg->data[m]);
printk("\n");
}
@@ -1346,6 +1374,18 @@ static inline int i_ipmi_request(ipmi_user_t user,
return rv;
}
+static int check_addr(ipmi_smi_t intf,
+ struct ipmi_addr *addr,
+ unsigned char *saddr,
+ unsigned char *lun)
+{
+ if (addr->channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *lun = intf->channels[addr->channel].lun;
+ *saddr = intf->channels[addr->channel].address;
+ return 0;
+}
+
int ipmi_request_settime(ipmi_user_t user,
struct ipmi_addr *addr,
long msgid,
@@ -1355,6 +1395,14 @@ int ipmi_request_settime(ipmi_user_t user,
int retries,
unsigned int retry_time_ms)
{
+ unsigned char saddr, lun;
+ int rv;
+
+ if (! user)
+ return -EINVAL;
+ rv = check_addr(user->intf, addr, &saddr, &lun);
+ if (rv)
+ return rv;
return i_ipmi_request(user,
user->intf,
addr,
@@ -1363,8 +1411,8 @@ int ipmi_request_settime(ipmi_user_t user,
user_msg_data,
NULL, NULL,
priority,
- user->intf->my_address,
- user->intf->my_lun,
+ saddr,
+ lun,
retries,
retry_time_ms);
}
@@ -1378,6 +1426,14 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
struct ipmi_recv_msg *supplied_recv,
int priority)
{
+ unsigned char saddr, lun;
+ int rv;
+
+ if (! user)
+ return -EINVAL;
+ rv = check_addr(user->intf, addr, &saddr, &lun);
+ if (rv)
+ return rv;
return i_ipmi_request(user,
user->intf,
addr,
@@ -1387,8 +1443,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
supplied_smi,
supplied_recv,
priority,
- user->intf->my_address,
- user->intf->my_lun,
+ saddr,
+ lun,
-1, 0);
}
@@ -1397,8 +1453,15 @@ 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;
- return sprintf(out, "%x\n", intf->my_address);
+ for (i = 0; i < IPMI_MAX_CHANNELS; i++)
+ rv += sprintf(out+rv, "%x ", intf->channels[i].address);
+ out[rv-1] = '\n'; /* Replace the final space with a newline */
+ out[rv] = '\0';
+ rv++;
+ return rv;
}
static int version_file_read_proc(char *page, char **start, off_t off,
@@ -1588,29 +1651,30 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan)
(struct ipmi_addr *) &si,
0,
&msg,
- NULL,
+ intf,
NULL,
NULL,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
-1, 0);
}
static void
-channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
int rv = 0;
int chan;
- if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
{
/* It's the one we want */
- if (msg->rsp[2] != 0) {
+ if (msg->msg.data[0] != 0) {
/* Got an error from the channel, just go on. */
- if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {
+ if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
/* If the MC does not support this
command, that is legal. We just
assume it has one IPMB at channel
@@ -1627,13 +1691,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
}
goto next_channel;
}
- if (msg->rsp_size < 6) {
+ if (msg->msg.data_len < 4) {
/* Message not big enough, just go on. */
goto next_channel;
}
chan = intf->curr_channel;
- intf->channels[chan].medium = msg->rsp[4] & 0x7f;
- intf->channels[chan].protocol = msg->rsp[5] & 0x1f;
+ intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
+ intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
next_channel:
intf->curr_channel++;
@@ -1691,22 +1755,24 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
rv = -ENOMEM;
down_write(&interfaces_sem);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == NULL) {
new_intf->intf_num = i;
new_intf->version_major = version_major;
new_intf->version_minor = version_minor;
- if (slave_addr == 0)
- new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
- else
- new_intf->my_address = slave_addr;
- new_intf->my_lun = 2; /* the SMS LUN. */
+ for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
+ new_intf->channels[j].address
+ = IPMI_BMC_SLAVE_ADDR;
+ new_intf->channels[j].lun = 2;
+ }
+ if (slave_addr != 0)
+ new_intf->channels[0].address = slave_addr;
rwlock_init(&(new_intf->users_lock));
INIT_LIST_HEAD(&(new_intf->users));
new_intf->handlers = handlers;
new_intf->send_info = send_info;
spin_lock_init(&(new_intf->seq_lock));
- for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
new_intf->seq_table[j].inuse = 0;
new_intf->seq_table[j].seqid = 0;
}
@@ -1722,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
rwlock_init(&(new_intf->cmd_rcvr_lock));
init_waitqueue_head(&new_intf->waitq);
INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
- new_intf->all_cmd_rcvr = NULL;
spin_lock_init(&(new_intf->counter_lock));
@@ -1814,7 +1879,7 @@ static void clean_up_interface_data(ipmi_smi_t intf)
free_recv_msg_list(&(intf->waiting_events));
free_cmd_rcvr_list(&(intf->cmd_rcvrs));
- for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
if ((intf->seq_table[i].inuse)
&& (intf->seq_table[i].recv_msg))
{
@@ -1833,7 +1898,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
down_write(&interfaces_sem);
if (list_empty(&(intf->users)))
{
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == intf) {
remove_proc_entries(intf);
spin_lock_irqsave(&interfaces_lock, flags);
@@ -1960,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
read_lock(&(intf->cmd_rcvr_lock));
- if (intf->all_cmd_rcvr) {
- user = intf->all_cmd_rcvr;
- } else {
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
+ /* Find the command/netfn. */
+ list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+ user = rcvr->user;
+ break;
}
}
read_unlock(&(intf->cmd_rcvr_lock));
@@ -1985,7 +2046,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
msg->data[3] = msg->rsp[6];
msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
- msg->data[6] = intf->my_address;
+ msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
/* rqseq/lun */
msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
msg->data[8] = msg->rsp[8]; /* cmd */
@@ -1997,7 +2058,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
{
int m;
printk("Invalid command:");
- for (m=0; m<msg->data_size; m++)
+ for (m = 0; m < msg->data_size; m++)
printk(" %2.2x", msg->data[m]);
printk("\n");
}
@@ -2145,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
read_lock(&(intf->cmd_rcvr_lock));
- if (intf->all_cmd_rcvr) {
- user = intf->all_cmd_rcvr;
- } else {
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
+ /* Find the command/netfn. */
+ list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+ user = rcvr->user;
+ break;
}
}
read_unlock(&(intf->cmd_rcvr_lock));
@@ -2330,6 +2387,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
unsigned long flags;
recv_msg = (struct ipmi_recv_msg *) msg->user_data;
+ if (recv_msg == NULL)
+ {
+ printk(KERN_WARNING"IPMI message received with no owner. This\n"
+ "could be because of a malformed message, or\n"
+ "because of a hardware error. Contact your\n"
+ "hardware vender for assistance\n");
+ return 0;
+ }
/* Make sure the user still exists. */
list_for_each_entry(user, &(intf->users), link) {
@@ -2340,19 +2405,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
}
}
- if (!found) {
- /* Special handling for NULL users. */
- if (!recv_msg->user && intf->null_user_handler){
- intf->null_user_handler(intf, msg);
- spin_lock_irqsave(&intf->counter_lock, flags);
- intf->handled_local_responses++;
- spin_unlock_irqrestore(&intf->counter_lock, flags);
- }else{
- /* The user for the message went away, so give up. */
- spin_lock_irqsave(&intf->counter_lock, flags);
- intf->unhandled_local_responses++;
- spin_unlock_irqrestore(&intf->counter_lock, flags);
- }
+ if ((! found) && recv_msg->user) {
+ /* The user for the message went away, so give up. */
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->unhandled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
ipmi_free_recv_msg(recv_msg);
} else {
struct ipmi_system_interface_addr *smi_addr;
@@ -2392,7 +2449,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
#ifdef DEBUG_MSGING
int m;
printk("Recv:");
- for (m=0; m<msg->rsp_size; m++)
+ for (m = 0; m < msg->rsp_size; m++)
printk(" %2.2x", msg->rsp[m]);
printk("\n");
#endif
@@ -2626,7 +2683,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
{
int m;
printk("Resend: ");
- for (m=0; m<smi_msg->data_size; m++)
+ for (m = 0; m < smi_msg->data_size; m++)
printk(" %2.2x", smi_msg->data[m]);
printk("\n");
}
@@ -2647,7 +2704,7 @@ ipmi_timeout_handler(long timeout_period)
INIT_LIST_HEAD(&timeouts);
spin_lock(&interfaces_lock);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2672,7 +2729,7 @@ ipmi_timeout_handler(long timeout_period)
have timed out, putting them in the timeouts
list. */
spin_lock_irqsave(&(intf->seq_lock), flags);
- for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
struct seq_table *ent = &(intf->seq_table[j]);
if (!ent->inuse)
continue;
@@ -2712,7 +2769,7 @@ ipmi_timeout_handler(long timeout_period)
spin_unlock(&intf->counter_lock);
smi_msg = smi_from_recv_msg(intf,
ent->recv_msg, j, ent->seqid);
- if(!smi_msg)
+ if (! smi_msg)
continue;
spin_unlock_irqrestore(&(intf->seq_lock),flags);
@@ -2743,7 +2800,7 @@ static void ipmi_request_event(void)
int i;
spin_lock(&interfaces_lock);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2838,28 +2895,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
}
#ifdef CONFIG_IPMI_PANIC_STRING
-static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
- if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
- && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD)
+ && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
{
/* A get event receiver command, save it. */
- intf->event_receiver = msg->rsp[3];
- intf->event_receiver_lun = msg->rsp[4] & 0x3;
+ intf->event_receiver = msg->msg.data[1];
+ intf->event_receiver_lun = msg->msg.data[2] & 0x3;
}
}
-static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
- if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
- && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD)
+ && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
{
/* A get device id command, save if we are an event
receiver or generator. */
- intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
- intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
+ intf->local_sel_device = (msg->msg.data[6] >> 2) & 1;
+ intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
}
}
#endif
@@ -2903,7 +2962,7 @@ static void send_panic_events(char *str)
recv_msg.done = dummy_recv_done_handler;
/* For every registered interface, send the event. */
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2915,12 +2974,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* Don't retry, and don't wait. */
}
@@ -2930,7 +2989,7 @@ static void send_panic_events(char *str)
if (!str)
return;
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
char *p = str;
struct ipmi_ipmb_addr *ipmb;
int j;
@@ -2961,12 +3020,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* Don't retry, and don't wait. */
if (intf->local_event_generator) {
@@ -2981,12 +3040,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* no retry, and no wait. */
}
intf->null_user_handler = NULL;
@@ -2996,7 +3055,7 @@ static void send_panic_events(char *str)
be zero, and it must not be my address. */
if (((intf->event_receiver & 1) == 0)
&& (intf->event_receiver != 0)
- && (intf->event_receiver != intf->my_address))
+ && (intf->event_receiver != intf->channels[0].address))
{
/* The event receiver is valid, send an IPMB
message. */
@@ -3031,7 +3090,7 @@ static void send_panic_events(char *str)
data[0] = 0;
data[1] = 0;
data[2] = 0xf0; /* OEM event without timestamp. */
- data[3] = intf->my_address;
+ data[3] = intf->channels[0].address;
data[4] = j++; /* sequence # */
/* Always give 11 bytes, so strncpy will fill
it with zeroes for me. */
@@ -3043,12 +3102,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* no retry, and no wait. */
}
}
@@ -3070,7 +3129,7 @@ static int panic_event(struct notifier_block *this,
has_paniced = 1;
/* For every registered interface, set it to run to completion. */
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -3099,9 +3158,9 @@ static int ipmi_init_msghandler(void)
return 0;
printk(KERN_INFO "ipmi message handler version "
- IPMI_MSGHANDLER_VERSION "\n");
+ IPMI_DRIVER_VERSION "\n");
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
ipmi_interfaces[i] = NULL;
}
@@ -3171,6 +3230,9 @@ module_exit(cleanup_ipmi);
module_init(ipmi_init_msghandler_mod);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface.");
+MODULE_VERSION(IPMI_DRIVER_VERSION);
EXPORT_SYMBOL(ipmi_create_user);
EXPORT_SYMBOL(ipmi_destroy_user);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index f951c30236c9..e82a96ba396b 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -42,7 +42,6 @@
#include <linux/ipmi_smi.h>
#define PFX "IPMI poweroff: "
-#define IPMI_POWEROFF_VERSION "v33"
/* Where to we insert our poweroff function? */
extern void (*pm_power_off)(void);
@@ -53,16 +52,17 @@ extern void (*pm_power_off)(void);
#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
/* the IPMI data command */
-static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+static int poweroff_powercycle;
/* parameter definition to allow user to flag power cycle */
-module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
-MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+module_param(poweroff_powercycle, int, 0);
+MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
/* Stuff from the get device id command. */
static unsigned int mfg_id;
static unsigned int prod_id;
static unsigned char capabilities;
+static unsigned char ipmi_version;
/* We use our own messages for this operation, we don't let the system
allocate them, since we may be in a panic situation. The whole
@@ -338,6 +338,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
}
/*
+ * ipmi_dell_chassis_detect()
+ * Dell systems with IPMI < 1.5 don't set the chassis capability bit
+ * but they can handle a chassis poweroff or powercycle command.
+ */
+
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+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;
+ if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
+ ipmi_version_major <= 1 &&
+ ipmi_version_minor < 5)
+ return 1;
+ return 0;
+}
+
+/*
* Standard chassis support
*/
@@ -366,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
powercyclefailed:
printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
- ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
+ (poweroff_powercycle ? "cycle" : "down"));
/*
* Power down
*/
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
- data[0] = poweroff_control;
+ if (poweroff_powercycle)
+ data[0] = IPMI_CHASSIS_POWER_CYCLE;
+ else
+ data[0] = IPMI_CHASSIS_POWER_DOWN;
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
(struct ipmi_addr *) &smi_addr,
&send_msg);
if (rv) {
- switch (poweroff_control) {
- case IPMI_CHASSIS_POWER_CYCLE:
- /* power cycle failed, default to power down */
- printk(KERN_ERR PFX "Unable to send chassis power " \
- "cycle message, IPMI error 0x%x\n", rv);
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- goto powercyclefailed;
-
- case IPMI_CHASSIS_POWER_DOWN:
- default:
- printk(KERN_ERR PFX "Unable to send chassis power " \
- "down message, IPMI error 0x%x\n", rv);
- break;
+ if (poweroff_powercycle) {
+ /* power cycle failed, default to power down */
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "cycle message, IPMI error 0x%x\n", rv);
+ poweroff_powercycle = 0;
+ goto powercyclefailed;
}
- }
- return;
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "down message, IPMI error 0x%x\n", rv);
+ }
}
@@ -414,6 +430,9 @@ static struct poweroff_function poweroff_functions[] = {
{ .platform_type = "CPI1",
.detect = ipmi_cpi1_detect,
.poweroff_func = ipmi_poweroff_cpi1 },
+ { .platform_type = "chassis",
+ .detect = ipmi_dell_chassis_detect,
+ .poweroff_func = ipmi_poweroff_chassis },
/* Chassis should generally be last, other things should override
it. */
{ .platform_type = "chassis",
@@ -499,10 +518,11 @@ static void ipmi_po_new_smi(int if_num)
prod_id = (halt_recv_msg.msg.data[10]
| (halt_recv_msg.msg.data[11] << 8));
capabilities = halt_recv_msg.msg.data[6];
+ ipmi_version = halt_recv_msg.msg.data[5];
/* Scan for a poweroff method */
- for (i=0; i<NUM_PO_FUNCS; i++) {
+ for (i = 0; i < NUM_PO_FUNCS; i++) {
if (poweroff_functions[i].detect(ipmi_user))
goto found;
}
@@ -538,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher =
#ifdef CONFIG_PROC_FS
-/* displays properties to proc */
-static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
- poweroff_control);
-}
+#include <linux/sysctl.h>
+
+static ctl_table ipmi_table[] = {
+ { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE,
+ .procname = "poweroff_powercycle",
+ .data = &poweroff_powercycle,
+ .maxlen = sizeof(poweroff_powercycle),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec },
+ { }
+};
-/* process property writes from proc */
-static int proc_write_chassctrl(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int rv = count;
- unsigned int newval = 0;
-
- sscanf(buffer, "%d", &newval);
- switch (newval) {
- case IPMI_CHASSIS_POWER_CYCLE:
- printk(KERN_INFO PFX "power cycle is now enabled\n");
- poweroff_control = newval;
- break;
-
- case IPMI_CHASSIS_POWER_DOWN:
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- break;
-
- default:
- rv = -EINVAL;
- break;
- }
+static ctl_table ipmi_dir_table[] = {
+ { .ctl_name = DEV_IPMI,
+ .procname = "ipmi",
+ .mode = 0555,
+ .child = ipmi_table },
+ { }
+};
- return rv;
-}
+static ctl_table ipmi_root_table[] = {
+ { .ctl_name = CTL_DEV,
+ .procname = "dev",
+ .mode = 0555,
+ .child = ipmi_dir_table },
+ { }
+};
+
+static struct ctl_table_header *ipmi_table_header;
#endif /* CONFIG_PROC_FS */
/*
@@ -578,42 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer,
*/
static int ipmi_poweroff_init (void)
{
- int rv;
- struct proc_dir_entry *file;
+ int rv;
printk ("Copyright (C) 2004 MontaVista Software -"
- " IPMI Powerdown via sys_reboot version "
- IPMI_POWEROFF_VERSION ".\n");
-
- switch (poweroff_control) {
- case IPMI_CHASSIS_POWER_CYCLE:
- printk(KERN_INFO PFX "Power cycle is enabled.\n");
- break;
-
- case IPMI_CHASSIS_POWER_DOWN:
- default:
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- break;
+ " IPMI Powerdown via sys_reboot.\n");
+
+ if (poweroff_powercycle)
+ printk(KERN_INFO PFX "Power cycle is enabled.\n");
+
+#ifdef CONFIG_PROC_FS
+ ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
+ if (!ipmi_table_header) {
+ printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
+ rv = -ENOMEM;
+ goto out_err;
}
+#endif
+#ifdef CONFIG_PROC_FS
rv = ipmi_smi_watcher_register(&smi_watcher);
+#endif
if (rv) {
+ unregister_sysctl_table(ipmi_table_header);
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
goto out_err;
}
-#ifdef CONFIG_PROC_FS
- file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
- if (!file) {
- printk(KERN_ERR PFX "Unable to create proc power control\n");
- } else {
- file->nlink = 1;
- file->read_proc = proc_read_chassctrl;
- file->write_proc = proc_write_chassctrl;
- file->owner = THIS_MODULE;
- }
-#endif
-
out_err:
return rv;
}
@@ -624,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void)
int rv;
#ifdef CONFIG_PROC_FS
- remove_proc_entry("poweroff_control", proc_ipmi_root);
+ unregister_sysctl_table(ipmi_table_header);
#endif
ipmi_smi_watcher_unregister(&smi_watcher);
@@ -642,3 +648,5 @@ module_exit(ipmi_poweroff_cleanup);
module_init(ipmi_poweroff_init);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a44b97304e95..b6e5cbfb09f8 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -61,11 +61,11 @@
# endif
static inline void add_usec_to_timer(struct timer_list *t, long v)
{
- t->sub_expires += nsec_to_arch_cycle(v * 1000);
- while (t->sub_expires >= arch_cycles_per_jiffy)
+ t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000);
+ while (t->arch_cycle_expires >= arch_cycles_per_jiffy)
{
t->expires++;
- t->sub_expires -= arch_cycles_per_jiffy;
+ t->arch_cycle_expires -= arch_cycles_per_jiffy;
}
}
#endif
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v)
#include <asm/io.h>
#include "ipmi_si_sm.h"
#include <linux/init.h>
-
-#define IPMI_SI_VERSION "v33"
+#include <linux/dmi.h>
/* Measure times between events in the driver. */
#undef DEBUG_TIMING
@@ -109,6 +108,21 @@ enum si_type {
SI_KCS, SI_SMIC, SI_BT
};
+struct ipmi_device_id {
+ unsigned char device_id;
+ unsigned char device_revision;
+ unsigned char firmware_revision_1;
+ unsigned char firmware_revision_2;
+ unsigned char ipmi_version;
+ unsigned char additional_device_support;
+ unsigned char manufacturer_id[3];
+ unsigned char product_id[2];
+ unsigned char aux_firmware_revision[4];
+} __attribute__((packed));
+
+#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
+#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
+
struct smi_info
{
ipmi_smi_t intf;
@@ -131,12 +145,24 @@ struct smi_info
void (*irq_cleanup)(struct smi_info *info);
unsigned int io_size;
+ /* Per-OEM handler, called from handle_flags().
+ Returns 1 when handle_flags() needs to be re-run
+ or 0 indicating it set si_state itself.
+ */
+ int (*oem_data_avail_handler)(struct smi_info *smi_info);
+
/* Flags from the last GET_MSG_FLAGS command, used when an ATTN
is set to hold the flags until we are done handling everything
from the flags. */
#define RECEIVE_MSG_AVAIL 0x01
#define EVENT_MSG_BUFFER_FULL 0x02
#define WDT_PRE_TIMEOUT_INT 0x08
+#define OEM0_DATA_AVAIL 0x20
+#define OEM1_DATA_AVAIL 0x40
+#define OEM2_DATA_AVAIL 0x80
+#define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \
+ OEM1_DATA_AVAIL | \
+ OEM2_DATA_AVAIL)
unsigned char msg_flags;
/* If set to true, this will request events the next time the
@@ -175,11 +201,7 @@ struct smi_info
interrupts. */
int interrupt_disabled;
- unsigned char ipmi_si_dev_rev;
- unsigned char ipmi_si_fw_rev_major;
- unsigned char ipmi_si_fw_rev_minor;
- unsigned char ipmi_version_major;
- unsigned char ipmi_version_minor;
+ struct ipmi_device_id device_id;
/* Slave address, could be reported from DMI. */
unsigned char slave_addr;
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
entry = smi_info->xmit_msgs.next;
}
- if (!entry) {
+ if (! entry) {
smi_info->curr_msg = NULL;
rv = SI_SM_IDLE;
} else {
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info)
memory, we will re-enable the interrupt. */
static inline void disable_si_irq(struct smi_info *smi_info)
{
- if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+ if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
disable_irq_nosync(smi_info->irq);
smi_info->interrupt_disabled = 1;
}
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info)
static void handle_flags(struct smi_info *smi_info)
{
+ retry:
if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
/* Watchdog pre-timeout */
spin_lock(&smi_info->count_lock);
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
/* Messages available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (!smi_info->curr_msg) {
+ if (! smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
/* Events available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (!smi_info->curr_msg) {
+ if (! smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info)
smi_info->curr_msg->data,
smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_EVENTS;
+ } else if (smi_info->msg_flags & OEM_DATA_AVAIL) {
+ if (smi_info->oem_data_avail_handler)
+ if (smi_info->oem_data_avail_handler(smi_info))
+ goto retry;
} else {
smi_info->si_state = SI_NORMAL;
}
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
#endif
switch (smi_info->si_state) {
case SI_NORMAL:
- if (!smi_info->curr_msg)
+ if (! smi_info->curr_msg)
break;
smi_info->curr_msg->rsp_size
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info)
#if defined(CONFIG_HIGH_RES_TIMERS)
unsigned long flags;
unsigned long jiffies_now;
+ unsigned long seq;
if (del_timer(&(smi_info->si_timer))) {
/* If we don't delete the timer, then it will go off
immediately, anyway. So we only process if we
actually delete the timer. */
- /* We already have irqsave on, so no need for it
- here. */
- read_lock(&xtime_lock);
- jiffies_now = jiffies;
- smi_info->si_timer.expires = jiffies_now;
- smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now);
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ jiffies_now = jiffies;
+ smi_info->si_timer.expires = jiffies_now;
+ smi_info->si_timer.arch_cycle_expires
+ = get_arch_cycles(jiffies_now);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data)
/* If the state machine asks for a short delay, then shorten
the timer timeout. */
if (smi_result == SI_SM_CALL_WITH_DELAY) {
+#if defined(CONFIG_HIGH_RES_TIMERS)
+ unsigned long seq;
+#endif
spin_lock_irqsave(&smi_info->count_lock, flags);
smi_info->short_timeouts++;
spin_unlock_irqrestore(&smi_info->count_lock, flags);
#if defined(CONFIG_HIGH_RES_TIMERS)
- read_lock(&xtime_lock);
- smi_info->si_timer.expires = jiffies;
- smi_info->si_timer.sub_expires
- = get_arch_cycles(smi_info->si_timer.expires);
- read_unlock(&xtime_lock);
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ smi_info->si_timer.expires = jiffies;
+ smi_info->si_timer.arch_cycle_expires
+ = get_arch_cycles(smi_info->si_timer.expires);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
#else
smi_info->si_timer.expires = jiffies + 1;
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data)
spin_unlock_irqrestore(&smi_info->count_lock, flags);
smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
#if defined(CONFIG_HIGH_RES_TIMERS)
- smi_info->si_timer.sub_expires = 0;
+ smi_info->si_timer.arch_cycle_expires = 0;
#endif
}
@@ -986,7 +1019,7 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
#define IPMI_MEM_ADDR_SPACE 1
#define IPMI_IO_ADDR_SPACE 2
-#if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI)
+#if defined(CONFIG_ACPI) || defined(CONFIG_X86) || defined(CONFIG_PCI)
static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
{
int i;
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info)
{
int rv;
- if (!info->irq)
+ if (! info->irq)
return 0;
if (info->si_type == SI_BT) {
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info)
SA_INTERRUPT,
DEVICE_NAME,
info);
- if (!rv)
+ if (! rv)
/* Enable the interrupt in the BT interface. */
info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info)
static void std_irq_cleanup(struct smi_info *info)
{
- if (!info->irq)
+ if (! info->irq)
return;
if (info->si_type == SI_BT)
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info)
unsigned int *addr = info->io.info;
int mapsize;
- if (!addr || (!*addr))
+ if (! addr || (! *addr))
return -ENODEV;
info->io_cleanup = port_cleanup;
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
{
struct smi_info *info;
- if (!ports[intf_num])
+ if (! ports[intf_num])
return -ENODEV;
- if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
+ if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
ports[intf_num]))
return -ENODEV;
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n");
return -ENOMEM;
}
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
info->io.info = &(ports[intf_num]);
info->io.addr = NULL;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = regsizes[intf_num];
- if (!info->io.regsize)
+ if (! info->io.regsize)
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
info->irq = 0;
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info)
unsigned long *addr = info->io.info;
int mapsize;
- if (!addr || (!*addr))
+ if (! addr || (! *addr))
return -ENODEV;
info->io_cleanup = mem_cleanup;
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
{
struct smi_info *info;
- if (!addrs[intf_num])
+ if (! addrs[intf_num])
return -ENODEV;
- if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
+ if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
addrs[intf_num]))
return -ENODEV;
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n");
return -ENOMEM;
}
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
info->io.info = &addrs[intf_num];
info->io.addr = NULL;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = regsizes[intf_num];
- if (!info->io.regsize)
+ if (! info->io.regsize)
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
info->irq = 0;
@@ -1362,7 +1395,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
}
-#ifdef CONFIG_ACPI_INTERPRETER
+#ifdef CONFIG_ACPI
#include <linux/acpi.h>
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
{
acpi_status status;
- if (!info->irq)
+ if (! info->irq)
return 0;
/* FIXME - is level triggered right? */
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
static void acpi_gpe_irq_cleanup(struct smi_info *info)
{
- if (!info->irq)
+ if (! info->irq)
return;
acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe);
@@ -1484,6 +1517,9 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
char *io_type;
u8 addr_space;
+ if (acpi_disabled)
+ return -ENODEV;
+
if (acpi_failure)
return -ENODEV;
@@ -1504,10 +1540,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
addr_space = IPMI_MEM_ADDR_SPACE;
else
addr_space = IPMI_IO_ADDR_SPACE;
- if (!is_new_interface(-1, addr_space, spmi->addr.address))
+ if (! is_new_interface(-1, addr_space, spmi->addr.address))
return -ENODEV;
- if (!spmi->addr.register_bit_width) {
+ if (! spmi->addr.register_bit_width) {
acpi_failure = 1;
return -ENODEV;
}
@@ -1534,7 +1570,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
return -ENOMEM;
}
@@ -1610,22 +1646,15 @@ typedef struct dmi_ipmi_data
static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
static int dmi_data_entries;
-typedef struct dmi_header
-{
- u8 type;
- u8 length;
- u16 handle;
-} dmi_header_t;
-
-static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
+static int __init decode_dmi(struct dmi_header *dm, int intf_num)
{
- u8 __iomem *data = (u8 __iomem *)dm;
+ u8 *data = (u8 *)dm;
unsigned long base_addr;
u8 reg_spacing;
- u8 len = readb(&dm->length);
+ u8 len = dm->length;
dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- ipmi_data->type = readb(&data[4]);
+ ipmi_data->type = data[4];
memcpy(&base_addr, data+8, sizeof(unsigned long));
if (len >= 0x11) {
@@ -1640,12 +1669,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
}
/* If bit 4 of byte 0x10 is set, then the lsb for the address
is odd. */
- ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
+ ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
- ipmi_data->irq = readb(&data[0x11]);
+ ipmi_data->irq = data[0x11];
/* The top two bits of byte 0x10 hold the register spacing. */
- reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
+ reg_spacing = (data[0x10] & 0xC0) >> 6;
switch(reg_spacing){
case 0x00: /* Byte boundaries */
ipmi_data->offset = 1;
@@ -1673,7 +1702,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
ipmi_data->offset = 1;
}
- ipmi_data->slave_addr = readb(&data[6]);
+ ipmi_data->slave_addr = data[6];
if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
dmi_data_entries++;
@@ -1685,94 +1714,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
return -1;
}
-static int dmi_table(u32 base, int len, int num)
+static void __init dmi_find_bmc(void)
{
- u8 __iomem *buf;
- struct dmi_header __iomem *dm;
- u8 __iomem *data;
- int i=1;
- int status=-1;
+ struct dmi_device *dev = NULL;
int intf_num = 0;
- buf = ioremap(base, len);
- if(buf==NULL)
- return -1;
-
- data = buf;
-
- while(i<num && (data - buf) < len)
- {
- dm=(dmi_header_t __iomem *)data;
-
- if((data-buf+readb(&dm->length)) >= len)
- break;
-
- if (readb(&dm->type) == 38) {
- if (decode_dmi(dm, intf_num) == 0) {
- intf_num++;
- if (intf_num >= SI_MAX_DRIVERS)
- break;
- }
- }
-
- data+=readb(&dm->length);
- while((data-buf) < len && (readb(data)||readb(data+1)))
- data++;
- data+=2;
- i++;
- }
- iounmap(buf);
-
- return status;
-}
-
-static inline int dmi_checksum(u8 *buf)
-{
- u8 sum=0;
- int a;
-
- for(a=0; a<15; a++)
- sum+=buf[a];
- return (sum==0);
-}
-
-static int dmi_decode(void)
-{
- u8 buf[15];
- u32 fp=0xF0000;
-
-#ifdef CONFIG_SIMNOW
- return -1;
-#endif
-
- while(fp < 0xFFFFF)
- {
- isa_memcpy_fromio(buf, fp, 15);
- if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
- {
- u16 num=buf[13]<<8|buf[12];
- u16 len=buf[7]<<8|buf[6];
- u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+ while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
+ if (intf_num >= SI_MAX_DRIVERS)
+ break;
- if(dmi_table(base, len, num) == 0)
- return 0;
- }
- fp+=16;
+ decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
}
-
- return -1;
}
static int try_init_smbios(int intf_num, struct smi_info **new_info)
{
- struct smi_info *info;
- dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- char *io_type;
+ struct smi_info *info;
+ dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
+ char *io_type;
if (intf_num >= dmi_data_entries)
return -ENODEV;
- switch(ipmi_data->type) {
+ switch (ipmi_data->type) {
case 0x01: /* KCS */
si_type[intf_num] = "kcs";
break;
@@ -1787,7 +1751,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n");
return -ENOMEM;
}
@@ -1811,7 +1775,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
regspacings[intf_num] = ipmi_data->offset;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
@@ -1853,14 +1817,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
pci_smic_checked = 1;
- if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID,
- NULL)))
- ;
- else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) &&
- pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)
- fe_rmc = 1;
- else
- return -ENODEV;
+ pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL);
+ if (! pci_dev) {
+ pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL);
+ if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID))
+ fe_rmc = 1;
+ else
+ return -ENODEV;
+ }
error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr);
if (error)
@@ -1873,7 +1837,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
}
/* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */
- if (!(base_addr & 0x0001))
+ if (! (base_addr & 0x0001))
{
pci_dev_put(pci_dev);
printk(KERN_ERR
@@ -1883,17 +1847,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
}
base_addr &= 0xFFFE;
- if (!fe_rmc)
+ if (! fe_rmc)
/* Data register starts at base address + 1 in eRMC */
++base_addr;
- if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
+ if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
pci_dev_put(pci_dev);
return -ENODEV;
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
pci_dev_put(pci_dev);
printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n");
return -ENOMEM;
@@ -1904,7 +1868,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
ports[intf_num] = base_addr;
info->io.info = &(ports[intf_num]);
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
@@ -1925,7 +1889,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
static int try_init_plug_and_play(int intf_num, struct smi_info **new_info)
{
#ifdef CONFIG_PCI
- if (find_pci_smic(intf_num, new_info)==0)
+ if (find_pci_smic(intf_num, new_info) == 0)
return 0;
#endif
/* Include other methods here. */
@@ -1943,7 +1907,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
int rv = 0;
resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
- if (!resp)
+ if (! resp)
return -ENOMEM;
/* Do a Get Device ID command, since it comes back with some
@@ -1956,8 +1920,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
for (;;)
{
if (smi_result == SI_SM_CALL_WITH_DELAY) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
smi_result = smi_info->handlers->event(
smi_info->si_sm, 100);
}
@@ -1992,11 +1955,8 @@ static int try_get_dev_id(struct smi_info *smi_info)
}
/* Record info from the get device id, in case we need it. */
- smi_info->ipmi_si_dev_rev = resp[4] & 0xf;
- smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f;
- smi_info->ipmi_si_fw_rev_minor = resp[6];
- smi_info->ipmi_version_major = resp[7] & 0xf;
- smi_info->ipmi_version_minor = resp[7] >> 4;
+ memcpy(&smi_info->device_id, &resp[3],
+ min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id)));
out:
kfree(resp);
@@ -2028,7 +1988,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
struct smi_info *smi = data;
out += sprintf(out, "interrupts_enabled: %d\n",
- smi->irq && !smi->interrupt_disabled);
+ smi->irq && ! smi->interrupt_disabled);
out += sprintf(out, "short_timeouts: %ld\n",
smi->short_timeouts);
out += sprintf(out, "long_timeouts: %ld\n",
@@ -2057,6 +2017,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
return (out - ((char *) page));
}
+/*
+ * oem_data_avail_to_receive_msg_avail
+ * @info - smi_info structure with msg_flags set
+ *
+ * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL
+ * Returns 1 indicating need to re-run handle_flags().
+ */
+static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
+{
+ smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) |
+ RECEIVE_MSG_AVAIL);
+ return 1;
+}
+
+/*
+ * setup_dell_poweredge_oem_data_handler
+ * @info - smi_info.device_id must be populated
+ *
+ * Systems that match, but have firmware version < 1.40 may assert
+ * OEM0_DATA_AVAIL on their own, without being told via Set Flags that
+ * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL
+ * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags
+ * as RECEIVE_MSG_AVAIL instead.
+ *
+ * As Dell has no plans to release IPMI 1.5 firmware that *ever*
+ * assert the OEM[012] bits, and if it did, the driver would have to
+ * change to handle that properly, we don't actually check for the
+ * firmware version.
+ * Device ID = 0x20 BMC on PowerEdge 8G servers
+ * Device Revision = 0x80
+ * Firmware Revision1 = 0x01 BMC version 1.40
+ * Firmware Revision2 = 0x40 BCD encoded
+ * IPMI Version = 0x51 IPMI 1.5
+ * Manufacturer ID = A2 02 00 Dell IANA
+ *
+ */
+#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20
+#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
+#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
+{
+ struct ipmi_device_id *id = &smi_info->device_id;
+ const char mfr[3]=DELL_IANA_MFR_ID;
+ if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))
+ && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID)
+ && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV)
+ && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION))
+ {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+ }
+}
+
+/*
+ * setup_oem_data_handler
+ * @info - smi_info.device_id must be filled in already
+ *
+ * Fills in smi_info.device_id.oem_data_available_handler
+ * when we know what function to use there.
+ */
+
+static void setup_oem_data_handler(struct smi_info *smi_info)
+{
+ setup_dell_poweredge_oem_data_handler(smi_info);
+}
+
/* Returns 0 if initialized, or negative on an error. */
static int init_one_smi(int intf_num, struct smi_info **smi)
{
@@ -2067,20 +2094,16 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
rv = try_init_mem(intf_num, &new_smi);
if (rv)
rv = try_init_port(intf_num, &new_smi);
-#ifdef CONFIG_ACPI_INTERPRETER
- if ((rv) && (si_trydefaults)) {
+#ifdef CONFIG_ACPI
+ if (rv && si_trydefaults)
rv = try_init_acpi(intf_num, &new_smi);
- }
#endif
#ifdef CONFIG_X86
- if ((rv) && (si_trydefaults)) {
+ if (rv && si_trydefaults)
rv = try_init_smbios(intf_num, &new_smi);
- }
#endif
- if ((rv) && (si_trydefaults)) {
+ if (rv && si_trydefaults)
rv = try_init_plug_and_play(intf_num, &new_smi);
- }
-
if (rv)
return rv;
@@ -2090,7 +2113,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->si_sm = NULL;
new_smi->handlers = NULL;
- if (!new_smi->irq_setup) {
+ if (! new_smi->irq_setup) {
new_smi->irq = irqs[intf_num];
new_smi->irq_setup = std_irq_setup;
new_smi->irq_cleanup = std_irq_cleanup;
@@ -2124,7 +2147,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Allocate the state machine's data and initialize it. */
new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
- if (!new_smi->si_sm) {
+ if (! new_smi->si_sm) {
printk(" Could not allocate state machine memory\n");
rv = -ENOMEM;
goto out_err;
@@ -2155,6 +2178,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
if (rv)
goto out_err;
+ setup_oem_data_handler(new_smi);
+
/* Try to claim any interrupts. */
new_smi->irq_setup(new_smi);
@@ -2188,8 +2213,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
rv = ipmi_register_smi(&handlers,
new_smi,
- new_smi->ipmi_version_major,
- new_smi->ipmi_version_minor,
+ ipmi_version_major(&new_smi->device_id),
+ ipmi_version_minor(&new_smi->device_id),
new_smi->slave_addr,
&(new_smi->intf));
if (rv) {
@@ -2230,10 +2255,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Wait for the timer to stop. This avoids problems with race
conditions removing the timer here. */
- while (!new_smi->timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (!new_smi->timer_stopped)
+ schedule_timeout_uninterruptible(1);
out_err:
if (new_smi->intf)
@@ -2270,7 +2293,7 @@ static __init int init_ipmi_si(void)
/* Parse out the si_type string into its components. */
str = si_type_str;
if (*str != '\0') {
- for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) {
+ for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) {
si_type[i] = str;
str = strchr(str, ',');
if (str) {
@@ -2282,22 +2305,14 @@ static __init int init_ipmi_si(void)
}
}
- printk(KERN_INFO "IPMI System Interface driver version "
- IPMI_SI_VERSION);
- if (kcs_smi_handlers.version)
- printk(", KCS version %s", kcs_smi_handlers.version);
- if (smic_smi_handlers.version)
- printk(", SMIC version %s", smic_smi_handlers.version);
- if (bt_smi_handlers.version)
- printk(", BT version %s", bt_smi_handlers.version);
- printk("\n");
+ printk(KERN_INFO "IPMI System Interface driver.\n");
#ifdef CONFIG_X86
- dmi_decode();
+ dmi_find_bmc();
#endif
rv = init_one_smi(0, &(smi_infos[pos]));
- if (rv && !ports[0] && si_trydefaults) {
+ if (rv && ! ports[0] && si_trydefaults) {
/* If we are trying defaults and the initial port is
not set, then set it. */
si_type[0] = "kcs";
@@ -2319,7 +2334,7 @@ static __init int init_ipmi_si(void)
if (rv == 0)
pos++;
- for (i=1; i < SI_MAX_PARMS; i++) {
+ for (i = 1; i < SI_MAX_PARMS; i++) {
rv = init_one_smi(i, &(smi_infos[pos]));
if (rv == 0)
pos++;
@@ -2361,17 +2376,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
/* Wait for the timer to stop. This avoids problems with race
conditions removing the timer here. */
- while (!to_clean->timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (!to_clean->timer_stopped)
+ schedule_timeout_uninterruptible(1);
/* Interrupts and timeouts are stopped, now make sure the
interface is in a clean state. */
- while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) {
+ while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
poll(to_clean);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
rv = ipmi_unregister_smi(to_clean->intf);
@@ -2392,13 +2404,15 @@ static __exit void cleanup_ipmi_si(void)
{
int i;
- if (!initialized)
+ if (! initialized)
return;
- for (i=0; i<SI_MAX_DRIVERS; i++) {
+ for (i = 0; i < SI_MAX_DRIVERS; i++) {
cleanup_one_si(smi_infos[i]);
}
}
module_exit(cleanup_ipmi_si);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces.");
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
index ae18747e670b..add2aa2732f0 100644
--- a/drivers/char/ipmi/ipmi_smic_sm.c
+++ b/drivers/char/ipmi/ipmi_smic_sm.c
@@ -46,8 +46,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_SMIC_VERSION "v33"
-
/* smic_debug is a bit-field
* SMIC_DEBUG_ENABLE - turned on for now
* SMIC_DEBUG_MSG - commands and their responses
@@ -588,7 +586,6 @@ static int smic_size(void)
struct si_sm_handlers smic_smi_handlers =
{
- .version = IPMI_SMIC_VERSION,
.init_data = init_smic_data,
.start_transaction = start_smic_transaction,
.get_result = smic_get_result,
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index d35a953961cb..2da64bf7469c 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -53,8 +53,6 @@
#define PFX "IPMI Watchdog: "
-#define IPMI_WATCHDOG_VERSION "v33"
-
/*
* The IPMI command/response information for the watchdog timer.
*/
@@ -259,7 +257,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
data[1] = 0;
WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
- if (pretimeout > 0) {
+ if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) {
WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
data[2] = pretimeout;
} else {
@@ -659,19 +657,18 @@ static ssize_t ipmi_read(struct file *file,
static int ipmi_open(struct inode *ino, struct file *filep)
{
- switch (iminor(ino))
- {
- case WATCHDOG_MINOR:
- if(test_and_set_bit(0, &ipmi_wdog_open))
+ switch (iminor(ino)) {
+ case WATCHDOG_MINOR:
+ if (test_and_set_bit(0, &ipmi_wdog_open))
return -EBUSY;
- /* Don't start the timer now, let it start on the
- first heartbeat. */
- ipmi_start_timer_on_heartbeat = 1;
- return nonseekable_open(ino, filep);
+ /* Don't start the timer now, let it start on the
+ first heartbeat. */
+ ipmi_start_timer_on_heartbeat = 1;
+ return nonseekable_open(ino, filep);
- default:
- return (-ENODEV);
+ default:
+ return (-ENODEV);
}
}
@@ -817,15 +814,19 @@ static void ipmi_register_watchdog(int ipmi_intf)
static int
ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
{
+ /* If we are not expecting a timeout, ignore it. */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+ return NOTIFY_DONE;
+
/* If no one else handled the NMI, we assume it was the IPMI
watchdog. */
- if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
+ if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
+ /* On some machines, the heartbeat will give
+ an error and not work unless we re-enable
+ the timer. So do so. */
+ pretimeout_since_last_heartbeat = 1;
panic(PFX "pre-timeout");
-
- /* On some machines, the heartbeat will give
- an error and not work unless we re-enable
- the timer. So do so. */
- pretimeout_since_last_heartbeat = 1;
+ }
return NOTIFY_DONE;
}
@@ -924,9 +925,6 @@ static int __init ipmi_wdog_init(void)
{
int rv;
- printk(KERN_INFO PFX "driver version "
- IPMI_WATCHDOG_VERSION "\n");
-
if (strcmp(action, "reset") == 0) {
action_val = WDOG_TIMEOUT_RESET;
} else if (strcmp(action, "none") == 0) {
@@ -1011,6 +1009,8 @@ static int __init ipmi_wdog_init(void)
register_reboot_notifier(&wdog_reboot_notifier);
notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
+ printk(KERN_INFO PFX "driver initialized\n");
+
return 0;
}
@@ -1037,10 +1037,8 @@ static __exit void ipmi_unregister_watchdog(void)
/* Wait to make sure the message makes it out. The lower layer has
pointers to our buffers, we want to make sure they are done before
we release our memory. */
- while (atomic_read(&set_timeout_tofree)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (atomic_read(&set_timeout_tofree))
+ schedule_timeout_uninterruptible(1);
/* Disconnect from IPMI. */
rv = ipmi_destroy_user(watchdog_user);
@@ -1062,3 +1060,5 @@ static void __exit ipmi_wdog_exit(void)
module_exit(ipmi_wdog_exit);
module_init(ipmi_wdog_init);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface.");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 52a073eee201..9c19e5435a11 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -780,7 +780,7 @@ static struct file_operations stli_fsiomem = {
* much cheaper on host cpu than using interrupts. It turns out to
* not increase character latency by much either...
*/
-static struct timer_list stli_timerlist = TIMER_INITIALIZER(stli_poll, 0, 0);
+static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
static int stli_timeron;
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 523fd3c8bbaa..449d029ad4f4 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -14,7 +14,7 @@
* `Sticky' modifier keys, 951006.
*
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
- *
+ *
* Modified to provide 'generic' keyboard support by Hamish Macdonald
* Merge with the m68k keyboard driver and split-off of the PC low-level
* parts by Geert Uytterhoeven, May 1997
@@ -52,7 +52,7 @@ extern void ctrl_alt_del(void);
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
* This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the keypad
+ * of PARISC machines however there is no NumLock key and everyone expects the keypad
* to be used for numbers.
*/
@@ -76,17 +76,17 @@ void compute_shiftstate(void);
k_meta, k_ascii, k_lock, k_lowercase,\
k_slock, k_dead2, k_ignore, k_ignore
-typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
+typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag, struct pt_regs *regs);
static k_handler_fn K_HANDLERS;
static k_handler_fn *k_handler[16] = { K_HANDLERS };
#define FN_HANDLERS\
- fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
- fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
- fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
- fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
- fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
+ fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
+ fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
+ fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
+ fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
+ fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs);
static fn_handler_fn FN_HANDLERS;
@@ -159,13 +159,13 @@ static int sysrq_alt;
*/
int getkeycode(unsigned int scancode)
{
- struct list_head * node;
+ struct list_head *node;
struct input_dev *dev = NULL;
- list_for_each(node,&kbd_handler.h_list) {
- struct input_handle * handle = to_handle_h(node);
- if (handle->dev->keycodesize) {
- dev = handle->dev;
+ list_for_each(node, &kbd_handler.h_list) {
+ struct input_handle *handle = to_handle_h(node);
+ if (handle->dev->keycodesize) {
+ dev = handle->dev;
break;
}
}
@@ -181,15 +181,15 @@ int getkeycode(unsigned int scancode)
int setkeycode(unsigned int scancode, unsigned int keycode)
{
- struct list_head * node;
+ struct list_head *node;
struct input_dev *dev = NULL;
unsigned int i, oldkey;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
- if (handle->dev->keycodesize) {
- dev = handle->dev;
- break;
+ if (handle->dev->keycodesize) {
+ dev = handle->dev;
+ break;
}
}
@@ -200,7 +200,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
return -EINVAL;
if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
- if (keycode >> (dev->keycodesize * 8))
+ if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
return -EINVAL;
oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -216,11 +216,11 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
}
/*
- * Making beeps and bells.
+ * Making beeps and bells.
*/
static void kd_nosound(unsigned long ignored)
{
- struct list_head * node;
+ struct list_head *node;
list_for_each(node,&kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
@@ -233,17 +233,16 @@ static void kd_nosound(unsigned long ignored)
}
}
-static struct timer_list kd_mksound_timer =
- TIMER_INITIALIZER(kd_nosound, 0, 0);
+static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
void kd_mksound(unsigned int hz, unsigned int ticks)
{
- struct list_head * node;
+ struct list_head *node;
del_timer(&kd_mksound_timer);
if (hz) {
- list_for_each_prev(node,&kbd_handler.h_list) {
+ list_for_each_prev(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
@@ -338,19 +337,19 @@ static void to_utf8(struct vc_data *vc, ushort c)
if (c < 0x80)
/* 0******* */
put_queue(vc, c);
- else if (c < 0x800) {
+ else if (c < 0x800) {
/* 110***** 10****** */
- put_queue(vc, 0xc0 | (c >> 6));
+ put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
- } else {
+ } else {
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
- }
+ }
}
-/*
+/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
* undefined, so that shiftkey release is seen
@@ -361,7 +360,7 @@ void compute_shiftstate(void)
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
-
+
for (i = 0; i < ARRAY_SIZE(key_down); i++) {
if (!key_down[i])
@@ -500,9 +499,9 @@ static void fn_dec_console(struct vc_data *vc, struct pt_regs *regs)
if (want_console != -1)
cur = want_console;
- for (i = cur-1; i != cur; i--) {
+ for (i = cur - 1; i != cur; i--) {
if (i == -1)
- i = MAX_NR_CONSOLES-1;
+ i = MAX_NR_CONSOLES - 1;
if (vc_cons_allocated(i))
break;
}
@@ -568,9 +567,9 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
{
- if (spawnpid)
- if(kill_proc(spawnpid, spawnsig, 1))
- spawnpid = 0;
+ if (spawnpid)
+ if (kill_proc(spawnpid, spawnsig, 1))
+ spawnpid = 0;
}
static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
@@ -604,8 +603,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag, struct
return;
if (value >= ARRAY_SIZE(fn_handler))
return;
- if ((kbd->kbdmode == VC_RAW ||
- kbd->kbdmode == VC_MEDIUMRAW) &&
+ if ((kbd->kbdmode == VC_RAW ||
+ kbd->kbdmode == VC_MEDIUMRAW) &&
value != KVAL(K_SAK))
return; /* SAK is allowed even in raw mode */
fn_handler[value](vc, regs);
@@ -895,11 +894,11 @@ static inline unsigned char getleds(void)
static void kbd_bh(unsigned long dummy)
{
- struct list_head * node;
+ struct list_head *node;
unsigned char leds = getleds();
if (leds != ledstate) {
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle * handle = to_handle_h(node);
input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
@@ -964,11 +963,11 @@ static int sparc_l1_a_state = 0;
extern void sun_do_break(void);
#endif
-static int emulate_raw(struct vc_data *vc, unsigned int keycode,
+static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ return -1;
switch (keycode) {
case KEY_PAUSE:
@@ -982,7 +981,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
case KEY_HANJA:
if (!up_flag) put_queue(vc, 0xf2);
return 0;
- }
+ }
if (keycode == KEY_SYSRQ && sysrq_alt) {
put_queue(vc, 0x54 | up_flag);
@@ -1105,11 +1104,12 @@ static void kbd_keycode(unsigned int keycode, int down,
else
clear_bit(keycode, key_down);
- if (rep && (!vc_kbd_mode(kbd, VC_REPEAT) || (tty &&
- (!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) {
+ if (rep &&
+ (!vc_kbd_mode(kbd, VC_REPEAT) ||
+ (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
/*
* Don't repeat a key if the input buffers are not empty and the
- * characters get aren't echoed locally. This makes key repeat
+ * characters get aren't echoed locally. This makes key repeat
* usable with slow applications and under heavy loads.
*/
return;
@@ -1131,7 +1131,8 @@ static void kbd_keycode(unsigned int keycode, int down,
type = KTYP(keysym);
if (type < 0xf0) {
- if (down && !raw_mode) to_utf8(vc, keysym);
+ if (down && !raw_mode)
+ to_utf8(vc, keysym);
return;
}
@@ -1155,7 +1156,7 @@ static void kbd_keycode(unsigned int keycode, int down,
kbd->slockstate = 0;
}
-static void kbd_event(struct input_handle *handle, unsigned int event_type,
+static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int event_code, int value)
{
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
@@ -1167,15 +1168,13 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
schedule_console_callback();
}
-static char kbd_name[] = "kbd";
-
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
* likes it, it can open it and get events from it. In this (kbd_connect)
* function, we should decide which VT to bind that keyboard to initially.
*/
-static struct input_handle *kbd_connect(struct input_handler *handler,
+static struct input_handle *kbd_connect(struct input_handler *handler,
struct input_dev *dev,
struct input_device_id *id)
{
@@ -1183,18 +1182,19 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
- if (test_bit(i, dev->keybit)) break;
+ if (test_bit(i, dev->keybit))
+ break;
- if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
+ if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
- handle->name = kbd_name;
+ handle->name = "kbd";
input_open_device(handle);
kbd_refresh_leds(handle);
@@ -1213,11 +1213,11 @@ static struct input_device_id kbd_ids[] = {
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_KEY) },
},
-
+
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_SND) },
- },
+ },
{ }, /* Terminating entry */
};
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index cf01a720eb2e..b77161146144 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -613,10 +613,15 @@ static struct miscdevice lcd_dev = {
static int lcd_init(void)
{
+ int ret;
unsigned long data;
pr_info("%s\n", LCD_DRIVER);
- misc_register(&lcd_dev);
+ ret = misc_register(&lcd_dev);
+ if (ret) {
+ printk(KERN_WARNING LCD "Unable to register misc device.\n");
+ return ret;
+ }
/* Check region? Naaah! Just snarf it up. */
/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 59eebe5a035f..2afb9038dbc5 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -128,6 +128,7 @@
#include <linux/console.h>
#include <linux/device.h>
#include <linux/wait.h>
+#include <linux/jiffies.h>
#include <linux/parport.h>
#undef LP_STATS
@@ -307,7 +308,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
(LP_F(minor) & LP_ABORT));
#ifdef LP_STATS
- if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+ if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
lp_table[minor].runchars = 0;
lp_table[minor].lastcall = jiffies;
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 115dbb35334b..3fa64c631108 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -750,7 +750,7 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
dev->soft = NULL;
- soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL);
+ soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL);
if (soft == NULL)
return -ENOMEM;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 850a78c9c4bc..f182752fe918 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -35,10 +35,6 @@
# include <linux/efi.h>
#endif
-#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
-extern void tapechar_init(void);
-#endif
-
/*
* Architectures vary in how they handle caching for addresses
* outside of main memory.
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 931efd58f87a..0c8375165e29 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -63,8 +63,6 @@ static DECLARE_MUTEX(misc_sem);
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
-extern int rtc_DP8570A_init(void);
-extern int rtc_MK48T08_init(void);
extern int pmu_device_init(void);
#ifdef CONFIG_PROC_FS
@@ -303,12 +301,7 @@ static int __init misc_init(void)
misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
-#ifdef CONFIG_MVME16x
- rtc_MK48T08_init();
-#endif
-#ifdef CONFIG_BVME6000
- rtc_DP8570A_init();
-#endif
+
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 95f7046ff059..79e490ef2cf2 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -339,7 +339,7 @@ static int __init moxa_init(void)
init_MUTEX(&moxaBuffSem);
moxaDriver->owner = THIS_MODULE;
- moxaDriver->name = "ttya";
+ moxaDriver->name = "ttyMX";
moxaDriver->devfs_name = "tts/a";
moxaDriver->major = ttymajor;
moxaDriver->minor_start = 0;
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d568991ac6b3..8666171e187b 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -57,6 +57,7 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+#include <linux/serial_8250.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
@@ -410,8 +411,8 @@ static ssize_t mwave_write(struct file *file, const char __user *buf,
static int register_serial_portandirq(unsigned int port, int irq)
{
- struct serial_struct serial;
-
+ struct uart_port uart;
+
switch ( port ) {
case 0x3f8:
case 0x2f8:
@@ -442,12 +443,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
} /* switch */
/* irq is okay */
- memset(&serial, 0, sizeof(serial));
- serial.port = port;
- serial.irq = irq;
- serial.flags = ASYNC_SHARE_IRQ;
-
- return register_serial(&serial);
+ memset(&uart, 0, sizeof(struct uart_port));
+
+ uart.uartclk = 1843200;
+ uart.iobase = port;
+ uart.irq = irq;
+ uart.iotype = UPIO_PORT;
+ uart.flags = UPF_SHARE_IRQ;
+ return serial8250_register_port(&uart);
}
@@ -523,7 +526,7 @@ static void mwave_exit(void)
#endif
if ( pDrvData->sLine >= 0 ) {
- unregister_serial(pDrvData->sLine);
+ serial8250_unregister_port(pDrvData->sLine);
}
if (pDrvData->bMwaveDevRegistered) {
misc_deregister(&mwave_misc_dev);
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index f022f0944434..45d012d85e8c 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -63,7 +63,6 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
@@ -1059,8 +1058,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
*/
timeout = jiffies + HZ;
while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(5);
+ schedule_timeout_interruptible(5);
if (time_after(jiffies, timeout))
break;
}
@@ -1081,10 +1079,8 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
info->event = 0;
info->tty = NULL;
if (info->blocked_open) {
- if (info->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
- }
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
}
@@ -1802,8 +1798,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ schedule_timeout_interruptible(char_time);
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 09103b3d8f05..c9bdf544ed2c 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -62,7 +62,7 @@
static inline unsigned char *alloc_buf(void)
{
- int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
if (PAGE_SIZE != N_TTY_BUF_SIZE)
return kmalloc(N_TTY_BUF_SIZE, prio);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 7a0c74648124..02d7f046c10a 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/pcmcia/synclink_cs.c
*
- * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.34 2005/09/08 13:20:54 paulkf Exp $
*
* Device driver for Microgate SyncLink PC Card
* multiprotocol serial adapter.
@@ -472,7 +472,7 @@ module_param_array(dosyncppp, int, NULL, 0);
MODULE_LICENSE("GPL");
static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.26 $";
+static char *driver_version = "$Revision: 4.34 $";
static struct tty_driver *serial_driver;
@@ -1457,6 +1457,8 @@ static int startup(MGSLPC_INFO * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
init_timer(&info->tx_timer);
info->tx_timer.data = (unsigned long)info;
info->tx_timer.function = tx_timeout;
@@ -1946,9 +1948,13 @@ static int get_stats(MGSLPC_INFO * info, struct mgsl_icount __user *user_icount)
int err;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("get_params(%s)\n", info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err)
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
+ }
return 0;
}
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index da32889d22c0..49f3997fd251 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -149,15 +149,14 @@ static int pty_write_room(struct tty_struct *tty)
static int pty_chars_in_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
- ssize_t (*chars_in_buffer)(struct tty_struct *);
int count;
/* We should get the line discipline lock for "tty->link" */
- if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer))
+ if (!to || !to->ldisc.chars_in_buffer)
return 0;
/* The ldisc must report 0 if no characters available to be read */
- count = chars_in_buffer(to);
+ count = to->ldisc.chars_in_buffer(to);
if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 6b11d6b2129f..7999da25fe40 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1589,6 +1589,40 @@ u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dp
EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
#endif
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
+/* Similar to secure_tcp_sequence_number but generate a 48 bit value
+ * bit's 32-47 increase every key exchange
+ * 0-31 hash(source, dest)
+ */
+u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport)
+{
+ struct timeval tv;
+ u64 seq;
+ __u32 hash[4];
+ struct keydata *keyptr = get_keyptr();
+
+ hash[0] = saddr;
+ hash[1] = daddr;
+ hash[2] = (sport << 16) + dport;
+ hash[3] = keyptr->secret[11];
+
+ seq = half_md4_transform(hash, keyptr->secret);
+ seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
+
+ do_gettimeofday(&tv);
+ seq += tv.tv_usec + tv.tv_sec * 1000000;
+ seq &= (1ull << 48) - 1;
+#if 0
+ printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
+ saddr, daddr, sport, dport, seq);
+#endif
+ return seq;
+}
+
+EXPORT_SYMBOL(secure_dccp_sequence_number);
+#endif
+
#endif /* CONFIG_INET */
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index cd4fe8b1709f..63fff7c1244a 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -938,10 +938,9 @@ found:
/*
* XXX Interrupt pin #7 in Espresso is shared between RTC and
- * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
- * is asking for trouble with add-on boards. Change to SA_SHIRQ.
+ * PCI Slot 2 INTA# (and some INTx# in Slot 1).
*/
- if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+ if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) {
/*
* Standard way for sparc to print irq's is to use
* __irq_itoa(). I think for EBus it's ok to use %d.
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index d692af57213a..baaa365285fa 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/byteorder/generic.h>
#include <asm/sn/sn_sal.h>
+#include <asm/unaligned.h>
#include "snsc.h"
static struct subch_data_s *event_sd;
@@ -62,13 +63,16 @@ static int
scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
{
char *desc_end;
+ __be32 from_buf;
/* record event source address */
- *src = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *src = be32_to_cpup(&from_buf);
event += 4; /* move on to event code */
/* record the system controller's event code */
- *code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *code = be32_to_cpup(&from_buf);
event += 4; /* move on to event arguments */
/* how many arguments are in the packet? */
@@ -82,7 +86,8 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
/* not an integer argument, so give up */
return -1;
}
- *esp_code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *esp_code = be32_to_cpup(&from_buf);
event += 4;
/* parse out the event description */
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index cefbe985e55c..36ae9ad2598c 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -98,12 +98,13 @@ MODULE_PARM_DESC(useinput,
#define SONYPI_DEVICE_MODEL_TYPE1 1
#define SONYPI_DEVICE_MODEL_TYPE2 2
+#define SONYPI_DEVICE_MODEL_TYPE3 3
/* type1 models use those */
#define SONYPI_IRQ_PORT 0x8034
#define SONYPI_IRQ_SHIFT 22
-#define SONYPI_BASE 0x50
-#define SONYPI_G10A (SONYPI_BASE+0x14)
+#define SONYPI_TYPE1_BASE 0x50
+#define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14)
#define SONYPI_TYPE1_REGION_SIZE 0x08
#define SONYPI_TYPE1_EVTYPE_OFFSET 0x04
@@ -114,6 +115,13 @@ MODULE_PARM_DESC(useinput,
#define SONYPI_TYPE2_REGION_SIZE 0x20
#define SONYPI_TYPE2_EVTYPE_OFFSET 0x12
+/* type3 series specifics */
+#define SONYPI_TYPE3_BASE 0x40
+#define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */
+#define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */
+#define SONYPI_TYPE3_REGION_SIZE 0x20
+#define SONYPI_TYPE3_EVTYPE_OFFSET 0x12
+
/* battery / brightness addresses */
#define SONYPI_BAT_FLAGS 0x81
#define SONYPI_LCD_LIGHT 0x96
@@ -159,6 +167,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = {
{ 0x0, 0x0 }
};
+/* same as in type 2 models */
+static struct sonypi_ioport_list *sonypi_type3_ioport_list =
+ sonypi_type2_ioport_list;
+
/* The set of possible interrupts */
struct sonypi_irq_list {
u16 irq;
@@ -180,6 +192,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
{ 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */
};
+/* same as in type2 models */
+static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list;
+
#define SONYPI_CAMERA_BRIGHTNESS 0
#define SONYPI_CAMERA_CONTRAST 1
#define SONYPI_CAMERA_HUE 2
@@ -223,6 +238,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
#define SONYPI_MEYE_MASK 0x00000400
#define SONYPI_MEMORYSTICK_MASK 0x00000800
#define SONYPI_BATTERY_MASK 0x00001000
+#define SONYPI_WIRELESS_MASK 0x00002000
struct sonypi_event {
u8 data;
@@ -305,6 +321,13 @@ static struct sonypi_event sonypi_blueev[] = {
{ 0, 0 }
};
+/* The set of possible wireless events */
+static struct sonypi_event sonypi_wlessev[] = {
+ { 0x59, SONYPI_EVENT_WIRELESS_ON },
+ { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+ { 0, 0 }
+};
+
/* The set of possible back button events */
static struct sonypi_event sonypi_backev[] = {
{ 0x20, SONYPI_EVENT_BACK_PRESSED },
@@ -383,7 +406,6 @@ static struct sonypi_eventtypes {
{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
- { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
@@ -391,6 +413,12 @@ static struct sonypi_eventtypes {
{ SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
{ 0 }
};
@@ -563,6 +591,23 @@ static void sonypi_type2_srs(void)
udelay(10);
}
+static void sonypi_type3_srs(void)
+{
+ u16 v16;
+ u8 v8;
+
+ /* This model type uses the same initialiazation of
+ * the embedded controller as the type2 models. */
+ sonypi_type2_srs();
+
+ /* Initialization of PCI config space of the LPC interface bridge. */
+ v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01;
+ pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16);
+ pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8);
+ v8 = (v8 & 0xCF) | 0x10;
+ pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8);
+}
+
/* Disables the device - this comes from the AML code in the ACPI bios */
static void sonypi_type1_dis(void)
{
@@ -587,6 +632,13 @@ static void sonypi_type2_dis(void)
printk(KERN_WARNING "ec_write failed\n");
}
+static void sonypi_type3_dis(void)
+{
+ sonypi_type2_dis();
+ udelay(10);
+ pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0);
+}
+
static u8 sonypi_call1(u8 dev)
{
u8 v1, v2;
@@ -1067,10 +1119,17 @@ static struct miscdevice sonypi_misc_device = {
static void sonypi_enable(unsigned int camera_on)
{
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
- sonypi_type2_srs();
- else
+ switch (sonypi_device.model) {
+ case SONYPI_DEVICE_MODEL_TYPE1:
sonypi_type1_srs();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE2:
+ sonypi_type2_srs();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE3:
+ sonypi_type3_srs();
+ break;
+ }
sonypi_call1(0x82);
sonypi_call2(0x81, 0xff);
@@ -1094,10 +1153,18 @@ static int sonypi_disable(void)
if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf1, 0xb2);
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
- sonypi_type2_dis();
- else
+ switch (sonypi_device.model) {
+ case SONYPI_DEVICE_MODEL_TYPE1:
sonypi_type1_dis();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE2:
+ sonypi_type2_dis();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE3:
+ sonypi_type3_dis();
+ break;
+ }
+
return 0;
}
@@ -1143,12 +1210,16 @@ static int __devinit sonypi_probe(void)
struct sonypi_irq_list *irq_list;
struct pci_dev *pcidev;
- pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
+ 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
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
sonypi_device.dev = pcidev;
- sonypi_device.model = pcidev ?
- SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2;
spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
@@ -1176,16 +1247,22 @@ static int __devinit sonypi_probe(void)
goto out_miscreg;
}
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
+
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
+ ioport_list = sonypi_type1_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
+ sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
+ irq_list = sonypi_type1_irq_list;
+ } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
ioport_list = sonypi_type2_ioport_list;
sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET;
irq_list = sonypi_type2_irq_list;
} else {
- ioport_list = sonypi_type1_ioport_list;
- sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
- sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
- irq_list = sonypi_type1_irq_list;
+ ioport_list = sonypi_type3_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE;
+ sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET;
+ irq_list = sonypi_type3_irq_list;
}
for (i = 0; ioport_list[i].port1; i++) {
@@ -1274,11 +1351,10 @@ static int __devinit sonypi_probe(void)
printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
"v%s.\n", SONYPI_DRIVER_VERSION);
- printk(KERN_INFO "sonypi: detected %s model, "
+ printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
"compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
- (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
- "type1" : "type2",
+ sonypi_device.model,
verbose,
fnkeyinit ? "on" : "off",
camera ? "on" : "off",
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 37c8bea8e2b0..ea2d54be4843 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/synclink.c
*
- * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
+ * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
* high speed multiprotocol serial adapters.
@@ -141,9 +141,9 @@ static MGSL_PARAMS default_params = {
typedef struct _DMABUFFERENTRY
{
u32 phys_addr; /* 32-bit flat physical address of data buffer */
- u16 count; /* buffer size/data count */
- u16 status; /* Control/status field */
- u16 rcc; /* character count field */
+ volatile u16 count; /* buffer size/data count */
+ volatile u16 status; /* Control/status field */
+ volatile u16 rcc; /* character count field */
u16 reserved; /* padding required by 16C32 */
u32 link; /* 32-bit flat link to next buffer entry */
char *virt_addr; /* virtual address of data buffer */
@@ -896,7 +896,7 @@ module_param_array(txdmabufs, int, NULL, 0);
module_param_array(txholdbufs, int, NULL, 0);
static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.28 $";
+static char *driver_version = "$Revision: 4.37 $";
static int synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent);
@@ -1814,6 +1814,8 @@ static int startup(struct mgsl_struct * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
init_timer(&info->tx_timer);
info->tx_timer.data = (unsigned long)info;
info->tx_timer.function = mgsl_tx_timeout;
@@ -2470,12 +2472,12 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *
printk("%s(%d):mgsl_get_params(%s)\n",
__FILE__,__LINE__, info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):mgsl_get_stats(%s) user buffer copy failed\n",
- __FILE__,__LINE__,info->device_name);
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
}
return 0;
@@ -6149,6 +6151,11 @@ static void usc_set_async_mode( struct mgsl_struct *info )
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
}
+ if (info->params.loopback) {
+ info->loopback_bits = 0x300;
+ outw(0x0300, info->io_base + CCAR);
+ }
+
} /* end of usc_set_async_mode() */
/* usc_loopback_frame()
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ec949e4c070f..6fb165cf8a61 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
*
* Device driver for Microgate SyncLink Multiport
* high speed multiprotocol serial adapter.
@@ -55,7 +55,6 @@
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <asm/serial.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
@@ -487,7 +486,7 @@ module_param_array(maxframe, int, NULL, 0);
module_param_array(dosyncppp, int, NULL, 0);
static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.34 $";
+static char *driver_version = "$Revision: 4.38 $";
static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -556,7 +555,6 @@ static int set_txidle(SLMP_INFO *info, int idle_mode);
static int tx_enable(SLMP_INFO *info, int enable);
static int tx_abort(SLMP_INFO *info);
static int rx_enable(SLMP_INFO *info, int enable);
-static int map_status(int signals);
static int modem_input_wait(SLMP_INFO *info,int arg);
static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
@@ -645,7 +643,7 @@ static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation le
static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes
static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x00800029;
+static u32 lcr1_brdr_value = 0x00800028;
static u32 read_ahead_count = 8;
@@ -2750,6 +2748,8 @@ static int startup(SLMP_INFO * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
/* program hardware for current parameters */
reset_port(info);
@@ -2953,12 +2953,12 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
printk("%s(%d):%s get_params()\n",
__FILE__,__LINE__, info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):%s get_stats() user buffer copy failed\n",
- __FILE__,__LINE__,info->device_name);
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
}
return 0;
@@ -3109,16 +3109,6 @@ static int rx_enable(SLMP_INFO * info, int enable)
return 0;
}
-static int map_status(int signals)
-{
- /* Map status bits to API event bits */
-
- return ((signals & SerialSignal_DSR) ? MgslEvent_DsrActive : MgslEvent_DsrInactive) +
- ((signals & SerialSignal_CTS) ? MgslEvent_CtsActive : MgslEvent_CtsInactive) +
- ((signals & SerialSignal_DCD) ? MgslEvent_DcdActive : MgslEvent_DcdInactive) +
- ((signals & SerialSignal_RI) ? MgslEvent_RiActive : MgslEvent_RiInactive);
-}
-
/* wait for specified event to occur
*/
static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
@@ -3145,7 +3135,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
/* return immediately if state matches requested events */
get_signals(info);
- s = map_status(info->serial_signals);
+ s = info->serial_signals;
events = mask &
( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
@@ -4489,11 +4479,13 @@ void async_mode(SLMP_INFO *info)
/* MD2, Mode Register 2
*
* 07..02 Reserved, must be 0
- * 01..00 CNCT<1..0> Channel connection, 0=normal
+ * 01..00 CNCT<1..0> Channel connection, 00=normal 11=local loopback
*
* 0000 0000
*/
RegValue = 0x00;
+ if (info->params.loopback)
+ RegValue |= (BIT1 + BIT0);
write_reg(info, MD2, RegValue);
/* RXS, Receive clock source
@@ -4574,9 +4566,6 @@ void async_mode(SLMP_INFO *info)
write_reg(info, IE2, info->ie2_value);
set_rate( info, info->params.data_rate * 16 );
-
- if (info->params.loopback)
- enable_loopback(info,1);
}
/* Program the SCA for HDLC communications.
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 79e9832ef1f3..b58adfe3ed19 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -17,7 +17,7 @@ config TCG_TPM
obtained at: <http://sourceforge.net/projects/trousers>. To
compile this driver as a module, choose M here; the module
will be called tpm. If unsure, say N.
- Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS
+ Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
config TCG_NSC
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index cc2cc77fd174..c0d64914595f 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -206,6 +206,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
{PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
{0,}
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index dc8c540391fd..939e51e119e6 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -14,7 +14,6 @@
* License.
*/
-#include <acpi/acpi_bus.h>
#include <linux/pnp.h>
#include "tpm.h"
@@ -29,9 +28,10 @@
#define TPM_MAX_TRIES 5000
#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
-/* These values will be filled after ACPI-call */
+/* These values will be filled after PnP-call */
static int TPM_INF_DATA = 0;
static int TPM_INF_ADDR = 0;
+static int pnp_registered = 0;
/* TPM header definitions */
enum infineon_tpm_header {
@@ -356,24 +356,26 @@ static const struct pnp_device_id tpm_pnp_tbl[] = {
{"IFX0102", 0},
{"", 0}
};
+MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
-static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev,
+static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id)
{
- TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
- TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
- tpm_inf.base = pnp_port_start(dev, 1);
- dev_info(&dev->dev, "Found %s with ID %s\n",
- dev->name, dev_id->id);
- if (!((tpm_inf.base >> 8) & 0xff))
- tpm_inf.base = 0;
- return 0;
+ if (pnp_port_valid(dev, 0)) {
+ TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
+ TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
+ tpm_inf.base = pnp_port_start(dev, 1);
+ dev_info(&dev->dev, "Found %s with ID %s\n",
+ dev->name, dev_id->id);
+ return 0;
+ }
+ return -ENODEV;
}
static struct pnp_driver tpm_inf_pnp = {
.name = "tpm_inf_pnp",
.id_table = tpm_pnp_tbl,
- .probe = tpm_inf_acpi_probe,
+ .probe = tpm_inf_pnp_probe,
};
static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
@@ -386,19 +388,30 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
int productid[2];
char chipname[20];
- if (pci_enable_device(pci_dev))
- return -EIO;
+ rc = pci_enable_device(pci_dev);
+ if (rc)
+ return rc;
dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
- /* read IO-ports from ACPI */
- pnp_register_driver(&tpm_inf_pnp);
- pnp_unregister_driver(&tpm_inf_pnp);
+ /* read IO-ports from PnP */
+ rc = pnp_register_driver(&tpm_inf_pnp);
+ if (rc < 0) {
+ dev_err(&pci_dev->dev,
+ "Error %x from pnp_register_driver!\n",rc);
+ goto error2;
+ }
+ if (!rc) {
+ dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
+ goto error;
+ } else {
+ pnp_registered = 1;
+ }
/* Make sure, we have received valid config ports */
if (!TPM_INF_ADDR) {
- pci_disable_device(pci_dev);
- return -EIO;
+ dev_err(&pci_dev->dev, "No valid IO-ports received!\n");
+ goto error;
}
/* query chip for its vendor, its version number a.s.o. */
@@ -418,23 +431,21 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
switch ((productid[0] << 8) | productid[1]) {
case 6:
- sprintf(chipname, " (SLD 9630 TT 1.1)");
+ snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
break;
case 11:
- sprintf(chipname, " (SLB 9635 TT 1.2)");
+ snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
break;
default:
- sprintf(chipname, " (unknown chip)");
+ snprintf(chipname, sizeof(chipname), " (unknown chip)");
break;
}
- chipname[19] = 0;
if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
if (tpm_inf.base == 0) {
dev_err(&pci_dev->dev, "No IO-ports found!\n");
- pci_disable_device(pci_dev);
- return -EIO;
+ goto error;
}
/* configure TPM with IO-ports */
outb(IOLIMH, TPM_INF_ADDR);
@@ -452,8 +463,7 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
dev_err(&pci_dev->dev,
"Could not set IO-ports to %04x\n",
tpm_inf.base);
- pci_disable_device(pci_dev);
- return -EIO;
+ goto error;
}
/* activate register */
@@ -479,14 +489,16 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
productid[0], productid[1], chipname);
rc = tpm_register_hardware(pci_dev, &tpm_inf);
- if (rc < 0) {
- pci_disable_device(pci_dev);
- return -ENODEV;
- }
+ if (rc < 0)
+ goto error;
return 0;
} else {
dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
+error:
+ pnp_unregister_driver(&tpm_inf_pnp);
+error2:
pci_disable_device(pci_dev);
+ pnp_registered = 0;
return -ENODEV;
}
}
@@ -521,6 +533,8 @@ static int __init init_inf(void)
static void __exit cleanup_inf(void)
{
+ if (pnp_registered)
+ pnp_unregister_driver(&tpm_inf_pnp);
pci_unregister_driver(&inf_pci_driver);
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6e4be3bb2d89..e5953f3433f3 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -153,7 +153,6 @@ static int tty_release(struct inode *, struct file *);
int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int tty_fasync(int fd, struct file * filp, int on);
-extern void rs_360_init(void);
static void release_mem(struct tty_struct *tty, int idx);
@@ -470,21 +469,19 @@ static void tty_ldisc_enable(struct tty_struct *tty)
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
{
- int retval = 0;
- struct tty_ldisc o_ldisc;
+ int retval = 0;
+ struct tty_ldisc o_ldisc;
char buf[64];
int work;
unsigned long flags;
struct tty_ldisc *ld;
+ struct tty_struct *o_tty;
if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
return -EINVAL;
restart:
- if (tty->ldisc.num == ldisc)
- return 0; /* We are already in the desired discipline */
-
ld = tty_ldisc_get(ldisc);
/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
/* Cyrus Durgin <cider@speakeasy.org> */
@@ -495,45 +492,74 @@ restart:
if (ld == NULL)
return -EINVAL;
- o_ldisc = tty->ldisc;
-
tty_wait_until_sent(tty, 0);
+ if (tty->ldisc.num == ldisc) {
+ tty_ldisc_put(ldisc);
+ return 0;
+ }
+
+ o_ldisc = tty->ldisc;
+ o_tty = tty->link;
+
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
* prevents anyone taking a reference once it is clear.
* We need the lock to avoid racing reference takers.
*/
-
+
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if(tty->ldisc.refcount)
- {
- /* Free the new ldisc we grabbed. Must drop the lock
- first. */
+ if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+ if(tty->ldisc.refcount) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ /*
+ * There are several reasons we may be busy, including
+ * random momentary I/O traffic. We must therefore
+ * retry. We could distinguish between blocking ops
+ * and retries if we made tty_ldisc_wait() smarter. That
+ * is up for discussion.
+ */
+ if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ if(o_tty && o_tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ }
+
+ /* if the TTY_LDISC bit is set, then we are racing against another ldisc change */
+
+ if (!test_bit(TTY_LDISC, &tty->flags)) {
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
tty_ldisc_put(ldisc);
- /*
- * There are several reasons we may be busy, including
- * random momentary I/O traffic. We must therefore
- * retry. We could distinguish between blocking ops
- * and retries if we made tty_ldisc_wait() smarter. That
- * is up for discussion.
- */
- if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
+ ld = tty_ldisc_ref_wait(tty);
+ tty_ldisc_deref(ld);
goto restart;
}
- clear_bit(TTY_LDISC, &tty->flags);
+
+ clear_bit(TTY_LDISC, &tty->flags);
clear_bit(TTY_DONT_FLIP, &tty->flags);
+ if (o_tty) {
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ clear_bit(TTY_DONT_FLIP, &o_tty->flags);
+ }
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
+
/*
* From this point on we know nobody has an ldisc
* usage reference, nor can they obtain one until
* we say so later on.
*/
-
+
work = cancel_delayed_work(&tty->flip.work);
/*
* Wait for ->hangup_work and ->flip.work handlers to terminate
@@ -584,10 +610,12 @@ restart:
*/
tty_ldisc_enable(tty);
+ if (o_tty)
+ tty_ldisc_enable(o_tty);
/* Restart it in case no characters kick it off. Safe if
already running */
- if(work)
+ if (work)
schedule_delayed_work(&tty->flip.work, 1);
return retval;
}
@@ -2426,6 +2454,7 @@ static void __do_SAK(void *arg)
int i;
struct file *filp;
struct tty_ldisc *disc;
+ struct fdtable *fdt;
if (!tty)
return;
@@ -2451,8 +2480,9 @@ static void __do_SAK(void *arg)
}
task_lock(p);
if (p->files) {
- spin_lock(&p->files->file_lock);
- for (i=0; i < p->files->max_fds; i++) {
+ rcu_read_lock();
+ fdt = files_fdtable(p->files);
+ for (i=0; i < fdt->max_fds; i++) {
filp = fcheck_files(p->files, i);
if (!filp)
continue;
@@ -2465,7 +2495,7 @@ static void __do_SAK(void *arg)
break;
}
}
- spin_unlock(&p->files->file_lock);
+ rcu_read_unlock();
}
task_unlock(p);
} while_each_task_pid(session, PIDTYPE_SID, p);
@@ -2911,11 +2941,6 @@ void __init console_init(void)
#ifdef CONFIG_EARLY_PRINTK
disable_early_printk();
#endif
-#ifdef CONFIG_SERIAL_68360
- /* This is not a console initcall. I know not what it's doing here.
- So I haven't moved it. dwmw2 */
- rs_360_init();
-#endif
call = __con_initcall_start;
while (call < __con_initcall_end) {
(*call)();
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 4764b4f9555d..0aff45fac2e6 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -991,7 +991,7 @@ static int viotape_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viotape_device_table[] __devinitdata = {
{ "viotape", "" },
- { 0, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, viotape_device_table);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 30d96739fb23..1e33cb032e07 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
/* used by selection: complement pointer position */
void complement_pos(struct vc_data *vc, int offset)
{
- static unsigned short *p;
+ static int old_offset = -1;
static unsigned short old;
static unsigned short oldx, oldy;
WARN_CONSOLE_UNLOCKED();
- if (p) {
- scr_writew(old, p);
+ if (old_offset != -1 && old_offset >= 0 &&
+ old_offset < vc->vc_screenbuf_size) {
+ scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
}
- if (offset == -1)
- p = NULL;
- else {
+
+ old_offset = offset;
+
+ if (offset != -1 && offset >= 0 &&
+ offset < vc->vc_screenbuf_size) {
unsigned short new;
+ unsigned short *p;
p = screenpos(vc, offset, 1);
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
@@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset)
vc->vc_sw->con_putc(vc, new, oldy, oldx);
}
}
+
}
static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -746,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+ unsigned int end;
unsigned short *newscreen;
WARN_CONSOLE_UNLOCKED();
@@ -789,20 +795,44 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
old_origin = vc->vc_origin;
new_origin = (long) newscreen;
new_scr_end = new_origin + new_screen_size;
- if (new_rows < old_rows)
- old_origin += (old_rows - new_rows) * old_row_size;
+
+ if (vc->vc_y > new_rows) {
+ if (old_rows - vc->vc_y < new_rows) {
+ /*
+ * Cursor near the bottom, copy contents from the
+ * bottom of buffer
+ */
+ old_origin += (old_rows - new_rows) * old_row_size;
+ end = vc->vc_scr_end;
+ } else {
+ /*
+ * Cursor is in no man's land, copy 1/2 screenful
+ * from the top and bottom of cursor position
+ */
+ old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+ end = old_origin + new_screen_size;
+ }
+ } else
+ /*
+ * Cursor near the top, copy contents from the top of buffer
+ */
+ end = (old_rows > new_rows) ? old_origin + new_screen_size :
+ vc->vc_scr_end;
update_attr(vc);
- while (old_origin < vc->vc_scr_end) {
- scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
+ while (old_origin < end) {
+ scr_memcpyw((unsigned short *) new_origin,
+ (unsigned short *) old_origin, rlth);
if (rrem)
- scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
+ scr_memsetw((void *)(new_origin + rlth),
+ vc->vc_video_erase_char, rrem);
old_origin += old_row_size;
new_origin += new_row_size;
}
if (new_scr_end > new_origin)
- scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+ scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+ new_scr_end - new_origin);
if (vc->vc_kmalloced)
kfree(vc->vc_screenbuf);
vc->vc_screenbuf = newscreen;
@@ -2272,7 +2302,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
ret = paste_selection(tty);
break;
case TIOCL_UNBLANKSCREEN:
+ acquire_console_sem();
unblank_screen();
+ release_console_sem();
break;
case TIOCL_SELLOADLUT:
ret = sel_loadlut(p);
@@ -2317,8 +2349,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
}
break;
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+ acquire_console_sem();
ignore_poke = 1;
do_blank_screen(0);
+ release_console_sem();
break;
case TIOCL_BLANKEDSCREEN:
ret = console_blanked;
@@ -2433,7 +2467,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
int ret = 0;
acquire_console_sem();
- if (tty->count == 1) {
+ if (tty->driver_data == NULL) {
ret = vc_allocate(currcons);
if (ret == 0) {
struct vc_data *vc = vc_cons[currcons].d;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index b53e2e2b5aee..344001b45af9 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -84,6 +84,17 @@ config 977_WATCHDOG
Not sure? It's safe to say N.
+config IXP2000_WATCHDOG
+ tristate "IXP2000 Watchdog"
+ depends on WATCHDOG && ARCH_IXP2000
+ help
+ Say Y here if to include support for the watchdog timer
+ in the Intel IXP2000(2400, 2800, 2850) network processors.
+ This driver can be built as a module by choosing M. The module
+ will be called ixp2000_wdt.
+
+ Say N if you are unsure.
+
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on WATCHDOG && ARCH_IXP4XX
@@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG
Say N if you are unsure.
-config IXP2000_WATCHDOG
- tristate "IXP2000 Watchdog"
- depends on WATCHDOG && ARCH_IXP2000
- help
- Say Y here if to include support for the watchdog timer
- in the Intel IXP2000(2400, 2800, 2850) network processors.
- This driver can be built as a module by choosing M. The module
- will be called ixp2000_wdt.
-
- Say N if you are unsure.
-
config S3C2410_WATCHDOG
tristate "S3C2410 Watchdog"
depends on WATCHDOG && ARCH_S3C2410
@@ -139,6 +139,15 @@ config SA1100_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called sa1100_wdt.
+config MPCORE_WATCHDOG
+ tristate "MPcore watchdog"
+ depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+ help
+ Watchdog timer embedded into the MPcore system.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mpcore_wdt.
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
@@ -224,6 +233,16 @@ config IB700_WDT
Most people will say N.
+config IBMASR
+ tristate "IBM Automatic Server Restart"
+ depends on WATCHDOG && X86
+ help
+ This is the driver for the IBM Automatic Server Restart watchdog
+ timer builtin into some eServer xSeries machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmasr.
+
config WAFER_WDT
tristate "ICP Wafer 5823 Single Board Computer Watchdog"
depends on WATCHDOG && X86
@@ -234,6 +253,16 @@ config WAFER_WDT
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
+config I6300ESB_WDT
+ tristate "Intel 6300ESB Timer/Watchdog"
+ depends on WATCHDOG && X86 && PCI
+ ---help---
+ Hardware driver for the watchdog timer built into the Intel
+ 6300ESB controller hub.
+
+ To compile this driver as a module, choose M here: the
+ module will be called i6300esb.
+
config I8XX_TCO
tristate "Intel i8xx TCO Timer/Watchdog"
depends on WATCHDOG && (X86 || IA64) && PCI
@@ -289,6 +318,19 @@ config 60XX_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called sbc60xxwdt.
+config SBC8360_WDT
+ tristate "SBC8360 Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+
+ This is the driver for the hardware watchdog on the SBC8360 Single
+ Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc8360.ko.
+
+ Most people will say N.
+
config CPU5_WDT
tristate "SMA CPU5 Watchdog"
depends on WATCHDOG && X86
@@ -327,6 +369,19 @@ config W83877F_WDT
Most people will say N.
+config W83977F_WDT
+ tristate "W83977F (PCM-5335) Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the hardware watchdog on the W83977F I/O chip
+ as used in AAEON's PCM-5335 SBC (and likely others). This
+ watchdog simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called w83977f_wdt.
+
config MACHZ_WDT
tristate "ZF MachZ Watchdog"
depends on WATCHDOG && X86
@@ -346,6 +401,28 @@ config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config MV64X60_WDT
+ tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+ depends on WATCHDOG && MV64X60
+
+config BOOKE_WDT
+ tristate "PowerPC Book-E Watchdog Timer"
+ depends on WATCHDOG && (BOOKE || 4xx)
+ ---help---
+ Please see Documentation/watchdog/watchdog-api.txt for
+ more information.
+
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on WATCHDOG && PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
# MIPS Architecture
config INDYDOG
@@ -414,16 +491,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# ppc64 RTAS watchdog
-config WATCHDOG_RTAS
- tristate "RTAS watchdog"
- depends on WATCHDOG && PPC_RTAS
- help
- This driver adds watchdog support for the RTAS watchdog.
-
- To compile this driver as a module, choose M here. The module
- will be called wdrtas.
-
#
# ISA-based Watchdog Cards
#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index c1838834ea7f..cfd0a3987710 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -2,42 +2,74 @@
# Makefile for the WatchDog device drivers.
#
+# Only one watchdog can succeed. We probe the ISA/PCI/USB based
+# watchdog-cards first, then the architecture specific watchdog
+# drivers and then the architecture independant "softdog" driver.
+# This means that if your ISA/PCI/USB card isn't detected that
+# you can fall back to an architecture specific driver and if
+# that also fails then you can fall back to the software watchdog
+# to give you some cover.
+
+# ISA-based Watchdog Cards
obj-$(CONFIG_PCWATCHDOG) += pcwd.o
-obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
-obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
-obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
-obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
-obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_WDT) += wdt.o
+
+# PCI-based Watchdog Cards
+obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
obj-$(CONFIG_WDTPCI) += wdt_pci.o
+
+# USB-based Watchdog Cards
+obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
+
+# ARM Architecture
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
-obj-$(CONFIG_MACHZ_WDT) += machzwd.o
-obj-$(CONFIG_SH_WDT) += shwdt.o
+obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
-obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
-obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
-obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
-obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
-obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+
+# X86 (i386 + ia64 + x86_64) Architecture
+obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
-obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
+obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
+obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
+obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
+obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
+obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
+obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
-obj-$(CONFIG_INDYDOG) += indydog.o
-obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
-obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
-obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
-obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
+obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
+obj-$(CONFIG_MACHZ_WDT) += machzwd.o
+
+# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
+
+# PPC64 Architecture
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-# Only one watchdog can succeed. We probe the hardware watchdog
-# drivers first, then the softdog driver. This means if your hardware
-# watchdog dies or is 'borrowed' for some reason the software watchdog
-# still gives you some cover.
+# MIPS Architecture
+obj-$(CONFIG_INDYDOG) += indydog.o
+
+# S390 Architecture
+
+# SUPERH Architecture
+obj-$(CONFIG_SH_WDT) += shwdt.o
+
+# SPARC64 Architecture
+# Architecture Independant
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
new file mode 100644
index 000000000000..abc30cca6645
--- /dev/null
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -0,0 +1,192 @@
+/*
+ * drivers/char/watchdog/booke_wdt.c
+ *
+ * Watchdog timer for PowerPC Book-E systems
+ *
+ * Author: Matthew McClintock
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/notifier.h>
+#include <linux/watchdog.h>
+
+#include <asm/reg_booke.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot.
+ * Also, the wdt_period sets the watchdog timer period timeout.
+ * For E500 cpus the wdt_period sets which bit changing from 0->1 will
+ * trigger a watchog timeout. This watchdog timeout will occur 3 times, the
+ * first time nothing will happen, the second time a watchdog exception will
+ * occur, and the final time the board will reset.
+ */
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */
+#else
+#define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */
+#endif /* for timing information */
+
+u32 booke_wdt_enabled = 0;
+u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
+#else
+#define WDTP(x) (TCR_WP(x))
+#endif
+
+/*
+ * booke_wdt_enable:
+ */
+static __inline__ void booke_wdt_enable(void)
+{
+ u32 val;
+
+ val = mfspr(SPRN_TCR);
+ val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
+
+ mtspr(SPRN_TCR, val);
+}
+
+/*
+ * booke_wdt_ping:
+ */
+static __inline__ void booke_wdt_ping(void)
+{
+ mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
+}
+
+/*
+ * booke_wdt_write:
+ */
+static ssize_t booke_wdt_write (struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ booke_wdt_ping();
+ return count;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "PowerPC Book-E Watchdog",
+};
+
+/*
+ * booke_wdt_ioctl:
+ */
+static int booke_wdt_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ u32 tmp = 0;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user ((struct watchdog_info *) arg, &ident,
+ sizeof(struct watchdog_info)))
+ return -EFAULT;
+ case WDIOC_GETSTATUS:
+ return put_user(ident.options, (u32 *) arg);
+ case WDIOC_GETBOOTSTATUS:
+ /* XXX: something is clearing TSR */
+ tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
+ /* returns 1 if last reset was caused by the WDT */
+ return (tmp ? 1 : 0);
+ case WDIOC_KEEPALIVE:
+ booke_wdt_ping();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(booke_wdt_period, (u32 *) arg))
+ return -EFAULT;
+ mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(booke_wdt_period, (u32 *) arg);
+ case WDIOC_SETOPTIONS:
+ if (get_user(tmp, (u32 *) arg))
+ return -EINVAL;
+ if (tmp == WDIOS_ENABLECARD) {
+ booke_wdt_ping();
+ break;
+ } else
+ return -EINVAL;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+/*
+ * booke_wdt_open:
+ */
+static int booke_wdt_open (struct inode *inode, struct file *file)
+{
+ if (booke_wdt_enabled == 0) {
+ booke_wdt_enabled = 1;
+ booke_wdt_enable();
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+ booke_wdt_period);
+ }
+
+ return 0;
+}
+
+static struct file_operations booke_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = booke_wdt_write,
+ .ioctl = booke_wdt_ioctl,
+ .open = booke_wdt_open,
+};
+
+static struct miscdevice booke_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &booke_wdt_fops,
+};
+
+static void __exit booke_wdt_exit(void)
+{
+ misc_deregister(&booke_wdt_miscdev);
+}
+
+/*
+ * booke_wdt_init:
+ */
+static int __init booke_wdt_init(void)
+{
+ int ret = 0;
+
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
+ ident.firmware_version = cpu_specs[0].pvr_value;
+
+ ret = misc_register(&booke_wdt_miscdev);
+ if (ret) {
+ printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ return ret;
+ }
+
+ if (booke_wdt_enabled == 1) {
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+ booke_wdt_period);
+ booke_wdt_enable();
+ }
+
+ return ret;
+}
+device_initcall(booke_wdt_init);
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
new file mode 100644
index 000000000000..93785f13242e
--- /dev/null
+++ b/drivers/char/watchdog/i6300esb.c
@@ -0,0 +1,527 @@
+/*
+ * i6300esb: Watchdog timer driver for Intel 6300ESB chipset
+ *
+ * (c) Copyright 2004 Google Inc.
+ * (c) Copyright 2005 David Härdeman <david@2gen.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * based on i810-tco.c which is in turn based on softdog.c
+ *
+ * The timer is implemented in the following I/O controller hubs:
+ * (See the intel documentation on http://developer.intel.com.)
+ * 6300ESB chip : document number 300641-003
+ *
+ * 2004YYZZ Ross Biro
+ * Initial version 0.01
+ * 2004YYZZ Ross Biro
+ * Version 0.02
+ * 20050210 David Härdeman <david@2gen.com>
+ * Ported driver to kernel 2.6
+ */
+
+/*
+ * Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG 0x60 /* Config register */
+#define ESB_LOCK_REG 0x68 /* WDT lock register */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */
+#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */
+#define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */
+#define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */
+#define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */
+#define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */
+
+/* Magic constants */
+#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
+#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+ writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+ writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+ u8 val;
+
+ /* Enable or Enable + Lock? */
+ val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+ u8 val;
+
+ spin_lock(&esb_lock);
+ /* First, reset timers as suggested by the docs */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* Then disable the WDT */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+ spin_unlock(&esb_lock);
+
+ /* Returns 0 if the timer was disabled, non-zero otherwise */
+ return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+ spin_lock(&esb_lock);
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* FIXME: Do we need to flush anything here? */
+ spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+ u32 val;
+
+ if (time < 0x1 || time > (2 * 0x03ff))
+ return -EINVAL;
+
+ spin_lock(&esb_lock);
+
+ /* We shift by 9, so if we are passed a value of 1 sec,
+ * val will be 1 << 9 = 512, then write that to two
+ * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+ */
+ val = time << 9;
+
+ /* Write timer 1 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER1_REG);
+
+ /* Write timer 2 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER2_REG);
+
+ /* Reload */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+ /* FIXME: Do we need to flush everything out? */
+
+ /* Done */
+ heartbeat = time;
+ spin_unlock(&esb_lock);
+ return 0;
+}
+
+static int esb_timer_read (void)
+{
+ u32 count;
+
+ /* This isn't documented, and doesn't take into
+ * acount which stage is running, but it looks
+ * like a 20 bit count down, so we might as well report it.
+ */
+ pci_read_config_dword(esb_pci, 0x64, &count);
+ return (int)count;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &timer_alive))
+ return -EBUSY;
+
+ /* Reload and activate timer */
+ esb_timer_keepalive ();
+ esb_timer_start ();
+
+ return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+ /* Shut off the timer. */
+ if (esb_expect_close == 42) {
+ esb_timer_stop ();
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ esb_timer_keepalive ();
+ }
+ clear_bit(0, &timer_alive);
+ esb_expect_close = 0;
+ return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+ size_t len, loff_t * ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* note: just in case someone wrote the magic character
+ * five months ago... */
+ esb_expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if(get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ esb_expect_close = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ esb_timer_keepalive ();
+ }
+ return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int new_options, retval = -EINVAL;
+ int new_heartbeat;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = ESB_MODULE_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof (ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user (esb_timer_read(), p);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user (triggered, p);
+
+ case WDIOC_KEEPALIVE:
+ esb_timer_keepalive ();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ {
+ if (get_user (new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ esb_timer_stop ();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ esb_timer_keepalive ();
+ esb_timer_start ();
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ {
+ if (get_user(new_heartbeat, p))
+ return -EFAULT;
+
+ if (esb_timer_set_heartbeat(new_heartbeat))
+ return -EINVAL;
+
+ esb_timer_keepalive ();
+ /* Fall */
+ }
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT) {
+ /* Turn the WDT off */
+ esb_timer_stop ();
+ }
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations esb_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = esb_write,
+ .ioctl = esb_ioctl,
+ .open = esb_open,
+ .release = esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+ .notifier_call = esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+ { 0, }, /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ * Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+ u8 val1;
+ unsigned short val2;
+
+ struct pci_dev *dev = NULL;
+ /*
+ * Find the PCI device
+ */
+
+ for_each_pci_dev(dev) {
+ if (pci_match_id(esb_pci_tbl, dev)) {
+ esb_pci = dev;
+ break;
+ }
+ }
+
+ if (esb_pci) {
+ if (pci_enable_device(esb_pci)) {
+ printk (KERN_ERR PFX "failed to enable device\n");
+ goto err_devput;
+ }
+
+ if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+ printk (KERN_ERR PFX "failed to request region\n");
+ goto err_disable;
+ }
+
+ BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+ pci_resource_len(esb_pci, 0));
+ if (BASEADDR == NULL) {
+ /* Something's wrong here, BASEADDR has to be set */
+ printk (KERN_ERR PFX "failed to get BASEADDR\n");
+ goto err_release;
+ }
+
+ /*
+ * The watchdog has two timers, it can be setup so that the
+ * expiry of timer1 results in an interrupt and the expiry of
+ * timer2 results in a reboot. We set it to not generate
+ * any interrupts as there is not much we can do with it
+ * right now.
+ *
+ * We also enable reboots and set the timer frequency to
+ * the PCI clock divided by 2^15 (approx 1KHz).
+ */
+ pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+ /* Check that the WDT isn't already locked */
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+ if (val1 & ESB_WDT_LOCK)
+ printk (KERN_WARNING PFX "nowayout already set\n");
+
+ /* Set the timer to watchdog mode and disable it for now */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+ /* Check if the watchdog was previously triggered */
+ esb_unlock_registers();
+ val2 = readw(ESB_RELOAD_REG);
+ triggered = (val2 & (0x01 << 9) >> 9);
+
+ /* Reset trigger flag and timers */
+ esb_unlock_registers();
+ writew((0x11 << 8), ESB_RELOAD_REG);
+
+ /* Done */
+ return 1;
+
+err_release:
+ pci_release_region(esb_pci, 0);
+err_disable:
+ pci_disable_device(esb_pci);
+err_devput:
+ pci_dev_put(esb_pci);
+ }
+ return 0;
+}
+
+static int __init watchdog_init (void)
+{
+ int ret;
+
+ spin_lock_init(&esb_lock);
+
+ /* Check whether or not the hardware watchdog is there */
+ if (!esb_getdevice () || esb_pci == NULL)
+ return -ENODEV;
+
+ /* Check that the heartbeat value is within it's range ; if not reset to the default */
+ if (esb_timer_set_heartbeat (heartbeat)) {
+ esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+ heartbeat);
+ }
+
+ ret = register_reboot_notifier(&esb_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ ret);
+ goto err_unmap;
+ }
+
+ ret = misc_register(&esb_miscdev);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_notifier;
+ }
+
+ esb_timer_stop ();
+
+ printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+ BASEADDR, heartbeat, nowayout);
+
+ return 0;
+
+err_notifier:
+ unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+ iounmap(BASEADDR);
+/* err_release: */
+ pci_release_region(esb_pci, 0);
+/* err_disable: */
+ pci_disable_device(esb_pci);
+/* err_devput: */
+ pci_dev_put(esb_pci);
+ return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ esb_timer_stop ();
+
+ /* Deregister */
+ misc_deregister(&esb_miscdev);
+ unregister_reboot_notifier(&esb_notifier);
+ iounmap(BASEADDR);
+ pci_release_region(esb_pci, 0);
+ pci_disable_device(esb_pci);
+ pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
new file mode 100644
index 000000000000..294c474ae485
--- /dev/null
+++ b/drivers/char/watchdog/ibmasr.c
@@ -0,0 +1,405 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+ ASMTYPE_UNKNOWN,
+ ASMTYPE_TOPAZ,
+ ASMTYPE_JASPER,
+ ASMTYPE_PEARL,
+ ASMTYPE_JUNIPER,
+ ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET 4
+#define TOPAZ_ASR_TOGGLE 0x40
+#define TOPAZ_ASR_DISABLE 0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE 0xe04
+#define PEARL_WRITE 0xe06
+#define PEARL_READ 0xe07
+
+#define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET 0x38
+
+#define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+ unsigned char reg;
+
+ if (asr_type == ASMTYPE_TOPAZ) {
+ /* asr_write_addr == asr_read_addr */
+ reg = inb(asr_read_addr);
+ outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+ asr_read_addr);
+ } else {
+ /*
+ * First make sure the hardware timer is reset by toggling
+ * ASR hardware timer line.
+ */
+ asr_toggle();
+
+ reg = inb(asr_read_addr);
+ outb(reg & ~asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ if (asr_type == ASMTYPE_TOPAZ)
+ /* asr_write_addr == asr_read_addr */
+ outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+ asr_read_addr);
+ else {
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+ unsigned char low, high;
+ const char *type = "";
+
+ asr_length = 1;
+
+ switch (asr_type) {
+ case ASMTYPE_TOPAZ:
+ /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+ outb(0x07, 0x2e);
+ outb(0x07, 0x2f);
+
+ /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x60, 0x2e);
+ high = inb(0x2f);
+
+ /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x61, 0x2e);
+ low = inb(0x2f);
+
+ asr_base = (high << 16) | low;
+ asr_read_addr = asr_write_addr =
+ asr_base + TOPAZ_ASR_REG_OFFSET;
+ asr_length = 5;
+
+ break;
+
+ case ASMTYPE_JASPER:
+ type = "Jaspers ";
+
+ /* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/* spin_lock_irqsave(&pci_config_lock, flags);*/
+
+ /* Select the SuperIO chip in the PCI I/O port register */
+ outl(0x8000f858, 0xcf8);
+
+ /*
+ * Read the base address for the SuperIO chip.
+ * Only the lower 16 bits are valid, but the address is word
+ * aligned so the last bit must be masked off.
+ */
+ asr_base = inl(0xcfc) & 0xfffe;
+
+/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+ asr_read_addr = asr_write_addr =
+ asr_base + JASPER_ASR_REG_OFFSET;
+ asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+ asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+ break;
+
+ case ASMTYPE_PEARL:
+ type = "Pearls ";
+ asr_base = PEARL_BASE;
+ asr_read_addr = PEARL_READ;
+ asr_write_addr = PEARL_WRITE;
+ asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+ asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+ asr_length = 4;
+ break;
+
+ case ASMTYPE_JUNIPER:
+ type = "Junipers ";
+ asr_base = JUNIPER_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+ break;
+
+ case ASMTYPE_SPRUCE:
+ type = "Spruce's ";
+ asr_base = SPRUCE_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+ asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+ break;
+ }
+
+ if (!request_region(asr_base, asr_length, "ibmasr")) {
+ printk(KERN_ERR PFX "address %#x already in use\n",
+ asr_base);
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+ return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ asr_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ asr_expect_close = 42;
+ }
+ }
+ asr_toggle();
+ }
+ return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "IBM ASR"
+ };
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int heartbeat;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ?
+ -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ asr_toggle();
+ return 0;
+
+ /*
+ * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+ * and WDIOC_GETTIMEOUT always returns 256.
+ */
+ case WDIOC_GETTIMEOUT:
+ heartbeat = 256;
+ return put_user(heartbeat, p);
+
+ case WDIOC_SETOPTIONS: {
+ int new_options, retval = -EINVAL;
+
+ if (get_user(new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ asr_disable();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ asr_enable();
+ asr_toggle();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+ if(test_and_set_bit(0, &asr_is_open))
+ return -EBUSY;
+
+ asr_toggle();
+ asr_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+ if (asr_expect_close == 42)
+ asr_disable();
+ else {
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ asr_toggle();
+ }
+ clear_bit(0, &asr_is_open);
+ asr_expect_close = 0;
+ return 0;
+}
+
+static struct file_operations asr_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = asr_write,
+ .ioctl = asr_ioctl,
+ .open = asr_open,
+ .release = asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &asr_fops,
+};
+
+
+struct ibmasr_id {
+ const char *desc;
+ int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+ { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+ { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+ { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+ { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+ { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+ { NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+ struct ibmasr_id *id;
+ int rc;
+
+ for (id = ibmasr_id_table; id->desc; id++) {
+ if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+ asr_type = id->type;
+ break;
+ }
+ }
+
+ if (!asr_type)
+ return -ENODEV;
+
+ rc = misc_register(&asr_miscdev);
+ if (rc < 0) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ return rc;
+ }
+
+ rc = asr_get_base_address();
+ if (rc) {
+ misc_deregister(&asr_miscdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+ if (!nowayout)
+ asr_disable();
+
+ misc_deregister(&asr_miscdev);
+
+ release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index e7640bc4904b..0cfb9b9c4a4b 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -182,7 +182,7 @@ static struct file_operations ixp2000_wdt_fops =
static struct miscdevice ixp2000_wdt_miscdev =
{
.minor = WATCHDOG_MINOR,
- .name = "IXP2000 Watchdog",
+ .name = "watchdog",
.fops = &ixp2000_wdt_fops,
};
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index 8d916afbf4fa..b5be8b11104a 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -176,7 +176,7 @@ static struct file_operations ixp4xx_wdt_fops =
static struct miscdevice ixp4xx_wdt_miscdev =
{
.minor = WATCHDOG_MINOR,
- .name = "IXP4xx Watchdog",
+ .name = "watchdog",
.fops = &ixp4xx_wdt_fops,
};
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index c9b301dccec3..7fc2188386d9 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -59,7 +59,7 @@ static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
static int watchdog_port;
static int mixcomwd_timer_alive;
-static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0);
static char expect_close;
static int nowayout = WATCHDOG_NOWAYOUT;
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
new file mode 100644
index 000000000000..c694eee1fb24
--- /dev/null
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -0,0 +1,434 @@
+/*
+ * Watchdog driver for the mpcore watchdog timer
+ *
+ * (c) Copyright 2004 ARM Limited
+ *
+ * Based on the SoftDog driver:
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+
+struct mpcore_wdt {
+ unsigned long timer_alive;
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+ unsigned int perturb;
+ char expect_close;
+};
+
+static struct platform_device *mpcore_wdt_dev;
+
+extern unsigned int mpcore_timer_rate;
+
+#define TIMER_MARGIN 60
+static int mpcore_margin = TIMER_MARGIN;
+module_param(mpcore_margin, int, 0);
+MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define ONLY_TESTING 0
+static int mpcore_noboot = ONLY_TESTING;
+module_param(mpcore_noboot, int, 0);
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+
+/*
+ * This is the interrupt handler. Note that we only use this
+ * in testing mode, so don't actually do a reboot here.
+ */
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
+{
+ struct mpcore_wdt *wdt = arg;
+
+ /* Check it really was our interrupt */
+ if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
+ dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
+
+ /* Clear the interrupt on the watchdog */
+ writel(1, wdt->base + TWD_WDOG_INTSTAT);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * mpcore_wdt_keepalive - reload the timer
+ *
+ * Note that the spec says a DIFFERENT value must be written to the reload
+ * register each time. The "perturb" variable deals with this by adding 1
+ * to the count every other time the function is called.
+ */
+static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
+{
+ unsigned int count;
+
+ /* Assume prescale is set to 256 */
+ count = (mpcore_timer_rate / 256) * mpcore_margin;
+
+ /* Reload the counter */
+ writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
+
+ wdt->perturb = wdt->perturb ? 0 : 1;
+}
+
+static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
+{
+ writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
+ writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
+ writel(0x0, wdt->base + TWD_WDOG_CONTROL);
+}
+
+static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+{
+ dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+ /* This loads the count register but does NOT start the count yet */
+ mpcore_wdt_keepalive(wdt);
+
+ if (mpcore_noboot) {
+ /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+ writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+ } else {
+ /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+ writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+ }
+}
+
+static int mpcore_wdt_set_heartbeat(int t)
+{
+ if (t < 0x0001 || t > 0xFFFF)
+ return -EINVAL;
+
+ mpcore_margin = t;
+ return 0;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+static int mpcore_wdt_open(struct inode *inode, struct file *file)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(&mpcore_wdt_dev->dev);
+
+ if (test_and_set_bit(0, &wdt->timer_alive))
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ file->private_data = wdt;
+
+ /*
+ * Activate timer
+ */
+ mpcore_wdt_start(wdt);
+
+ return nonseekable_open(inode, file);
+}
+
+static int mpcore_wdt_release(struct inode *inode, struct file *file)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (wdt->expect_close == 42) {
+ mpcore_wdt_stop(wdt);
+ } else {
+ dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
+ mpcore_wdt_keepalive(wdt);
+ }
+ clear_bit(0, &wdt->timer_alive);
+ wdt->expect_close = 0;
+ return 0;
+}
+
+static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ /*
+ * Refresh the timer.
+ */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ wdt->expect_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ wdt->expect_close = 42;
+ }
+ }
+ mpcore_wdt_keepalive(wdt);
+ }
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "MPcore Watchdog",
+};
+
+static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+ int ret;
+ union {
+ struct watchdog_info ident;
+ int i;
+ } uarg;
+
+ if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+ return -ENOIOCTLCMD;
+
+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+ if (ret)
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ uarg.ident = ident;
+ ret = 0;
+ break;
+
+ case WDIOC_SETOPTIONS:
+ ret = -EINVAL;
+ if (uarg.i & WDIOS_DISABLECARD) {
+ mpcore_wdt_stop(wdt);
+ ret = 0;
+ }
+ if (uarg.i & WDIOS_ENABLECARD) {
+ mpcore_wdt_start(wdt);
+ ret = 0;
+ }
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ uarg.i = 0;
+ ret = 0;
+ break;
+
+ case WDIOC_KEEPALIVE:
+ mpcore_wdt_keepalive(wdt);
+ ret = 0;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ ret = mpcore_wdt_set_heartbeat(uarg.i);
+ if (ret)
+ break;
+
+ mpcore_wdt_keepalive(wdt);
+ /* Fall */
+ case WDIOC_GETTIMEOUT:
+ uarg.i = mpcore_margin;
+ ret = 0;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+ ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
+ if (ret)
+ ret = -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * System shutdown handler. Turn off the watchdog if we're
+ * restarting or halting the system.
+ */
+static void mpcore_wdt_shutdown(struct device *_dev)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(_dev);
+
+ if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
+ mpcore_wdt_stop(wdt);
+}
+
+/*
+ * Kernel Interfaces
+ */
+static struct file_operations mpcore_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mpcore_wdt_write,
+ .ioctl = mpcore_wdt_ioctl,
+ .open = mpcore_wdt_open,
+ .release = mpcore_wdt_release,
+};
+
+static struct miscdevice mpcore_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mpcore_wdt_fops,
+};
+
+static int __devinit mpcore_wdt_probe(struct device *_dev)
+{
+ struct platform_device *dev = to_platform_device(_dev);
+ struct mpcore_wdt *wdt;
+ struct resource *res;
+ int ret;
+
+ /* We only accept one device, and it must have an id of -1 */
+ if (dev->id != -1)
+ return -ENODEV;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
+ if (!wdt) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+ memset(wdt, 0, sizeof(struct mpcore_wdt));
+
+ wdt->dev = &dev->dev;
+ wdt->irq = platform_get_irq(dev, 0);
+ wdt->base = ioremap(res->start, res->end - res->start + 1);
+ if (!wdt->base) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ mpcore_wdt_miscdev.dev = &dev->dev;
+ ret = misc_register(&mpcore_wdt_miscdev);
+ if (ret) {
+ dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_misc;
+ }
+
+ ret = request_irq(wdt->irq, mpcore_wdt_fire, SA_INTERRUPT, "mpcore_wdt", wdt);
+ if (ret) {
+ dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
+ goto err_irq;
+ }
+
+ mpcore_wdt_stop(wdt);
+ dev_set_drvdata(&dev->dev, wdt);
+ mpcore_wdt_dev = dev;
+
+ return 0;
+
+ err_irq:
+ misc_deregister(&mpcore_wdt_miscdev);
+ err_misc:
+ iounmap(wdt->base);
+ err_free:
+ kfree(wdt);
+ err_out:
+ return ret;
+}
+
+static int __devexit mpcore_wdt_remove(struct device *dev)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ misc_deregister(&mpcore_wdt_miscdev);
+
+ mpcore_wdt_dev = NULL;
+
+ free_irq(wdt->irq, wdt);
+ iounmap(wdt->base);
+ kfree(wdt);
+ return 0;
+}
+
+static struct device_driver mpcore_wdt_driver = {
+ .name = "mpcore_wdt",
+ .bus = &platform_bus_type,
+ .probe = mpcore_wdt_probe,
+ .remove = __devexit_p(mpcore_wdt_remove),
+ .shutdown = mpcore_wdt_shutdown,
+};
+
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+
+static int __init mpcore_wdt_init(void)
+{
+ /*
+ * Check that the margin value is within it's range;
+ * if not reset to the default
+ */
+ if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
+ mpcore_wdt_set_heartbeat(TIMER_MARGIN);
+ printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
+ TIMER_MARGIN);
+ }
+
+ printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+
+ return driver_register(&mpcore_wdt_driver);
+}
+
+static void __exit mpcore_wdt_exit(void)
+{
+ driver_unregister(&mpcore_wdt_driver);
+}
+
+module_init(mpcore_wdt_init);
+module_exit(mpcore_wdt_exit);
+
+MODULE_AUTHOR("ARM Limited");
+MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
new file mode 100644
index 000000000000..1436aea3b28f
--- /dev/null
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -0,0 +1,252 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required. This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/mv64x60.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* MV64x60 WDC (config) register access definitions */
+#define MV64x60_WDC_CTL1_MASK (3 << 24)
+#define MV64x60_WDC_CTL1(val) ((val & 3) << 24)
+#define MV64x60_WDC_CTL2_MASK (3 << 26)
+#define MV64x60_WDC_CTL2(val) ((val & 3) << 26)
+
+/* Flags bits */
+#define MV64x60_WDOG_FLAG_OPENED 0
+#define MV64x60_WDOG_FLAG_ENABLED 1
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *mv64x60_regs;
+static int mv64x60_wdt_timeout;
+
+static void mv64x60_wdt_reg_write(u32 val)
+{
+ /* Allow write only to CTL1 / CTL2 fields, retaining values in
+ * other fields.
+ */
+ u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
+ data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
+ data |= val;
+ writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+}
+
+static void mv64x60_wdt_service(void)
+{
+ /* Write 01 followed by 10 to CTL2 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+}
+
+static void mv64x60_wdt_handler_disable(void)
+{
+ if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+ }
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+ if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+ }
+}
+
+static int mv64x60_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+ return -EBUSY;
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_enable();
+
+ return 0;
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+ mv64x60_wdt_service();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+ mv64x60_wdt_handler_disable();
+#endif
+
+ clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
+
+ return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t * ppos)
+{
+ if (*ppos != file->f_pos)
+ return -ESPIPE;
+
+ if (len)
+ mv64x60_wdt_service();
+
+ return len;
+}
+
+static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int timeout;
+ static struct watchdog_info info = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "MV64x60 watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(wdt_status, (int *)arg))
+ return -EFAULT;
+ wdt_status &= ~WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_GETTEMP:
+ return -EOPNOTSUPP;
+
+ case WDIOC_SETOPTIONS:
+ return -EOPNOTSUPP;
+
+ case WDIOC_KEEPALIVE:
+ mv64x60_wdt_service();
+ wdt_status |= WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ return -EOPNOTSUPP;
+
+ case WDIOC_GETTIMEOUT:
+ timeout = mv64x60_wdt_timeout * HZ;
+ if (put_user(timeout, (int *)arg))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static struct file_operations mv64x60_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mv64x60_wdt_write,
+ .ioctl = mv64x60_wdt_ioctl,
+ .open = mv64x60_wdt_open,
+ .release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct device *dev)
+{
+ struct platform_device *pd = to_platform_device(dev);
+ struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data;
+ int bus_clk = 133;
+
+ mv64x60_wdt_timeout = 10;
+ if (pdata) {
+ mv64x60_wdt_timeout = pdata->timeout;
+ bus_clk = pdata->bus_clk;
+ }
+
+ mv64x60_regs = mv64x60_get_bridge_vbase();
+
+ writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
+ mv64x60_regs + MV64x60_WDT_WDC);
+
+ return misc_register(&mv64x60_wdt_miscdev);
+}
+
+static int __devexit mv64x60_wdt_remove(struct device *dev)
+{
+ misc_deregister(&mv64x60_wdt_miscdev);
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_disable();
+
+ return 0;
+}
+
+static struct device_driver mv64x60_wdt_driver = {
+ .name = MV64x60_WDT_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64x60_wdt_probe,
+ .remove = __devexit_p(mv64x60_wdt_remove),
+};
+
+static struct platform_device *mv64x60_wdt_dev;
+
+static int __init mv64x60_wdt_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+ mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
+ -1, NULL, 0);
+ if (IS_ERR(mv64x60_wdt_dev)) {
+ ret = PTR_ERR(mv64x60_wdt_dev);
+ goto out;
+ }
+
+ ret = driver_register(&mv64x60_wdt_driver);
+ out:
+ return ret;
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+ driver_unregister(&mv64x60_wdt_driver);
+ platform_device_unregister(mv64x60_wdt_dev);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 2b13afb09c5d..5a80adbf8032 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -29,27 +29,29 @@
* Includes, defines, variables, module parameters, ...
*/
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/pci.h> /* For pci functions */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
+
+#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.01"
-#define WATCHDOG_DATE "15 Mar 2005"
+#define WATCHDOG_DATE "02 Sep 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
@@ -335,12 +337,14 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
- pcipcwd_stop();
+ if (pcipcwd_stop())
+ return -EIO;
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
- pcipcwd_start();
+ if (pcipcwd_start())
+ return -EIO;
retval = 0;
}
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index f85ac898a49a..3625b2601b42 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -27,7 +27,10 @@
* Fixed tmr_count / wdt_count confusion
* Added configurable debug
*
- * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code
+ * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code
+ *
+ * 25-Jan-2005 DA Added suspend/resume support
+ * Replaced reboot notifier with .shutdown method
*
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
@@ -40,8 +43,6 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -317,20 +318,6 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file,
}
}
-/*
- * Notifier for system down
- */
-
-static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- if(code==SYS_DOWN || code==SYS_HALT) {
- /* Turn the WDT off */
- s3c2410wdt_stop();
- }
- return NOTIFY_DONE;
-}
-
/* kernel interface */
static struct file_operations s3c2410wdt_fops = {
@@ -348,10 +335,6 @@ static struct miscdevice s3c2410wdt_miscdev = {
.fops = &s3c2410wdt_fops,
};
-static struct notifier_block s3c2410wdt_notifier = {
- .notifier_call = s3c2410wdt_notify_sys,
-};
-
/* interrupt handler code */
static irqreturn_t s3c2410wdt_irq(int irqno, void *param,
@@ -432,18 +415,10 @@ static int s3c2410wdt_probe(struct device *dev)
}
}
- ret = register_reboot_notifier(&s3c2410wdt_notifier);
- if (ret) {
- printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n",
- ret);
- return ret;
- }
-
ret = misc_register(&s3c2410wdt_miscdev);
if (ret) {
printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
- unregister_reboot_notifier(&s3c2410wdt_notifier);
return ret;
}
@@ -479,15 +454,63 @@ static int s3c2410wdt_remove(struct device *dev)
return 0;
}
+static void s3c2410wdt_shutdown(struct device *dev)
+{
+ s3c2410wdt_stop();
+}
+
+#ifdef CONFIG_PM
+
+static unsigned long wtcon_save;
+static unsigned long wtdat_save;
+
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ /* Save watchdog state, and turn it off. */
+ wtcon_save = readl(wdt_base + S3C2410_WTCON);
+ wtdat_save = readl(wdt_base + S3C2410_WTDAT);
+
+ /* Note that WTCNT doesn't need to be saved. */
+ s3c2410wdt_stop();
+ }
+
+ return 0;
+}
+
+static int s3c2410wdt_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_POWER_ON) {
+ /* Restore watchdog state. */
+
+ writel(wtdat_save, wdt_base + S3C2410_WTDAT);
+ writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
+ writel(wtcon_save, wdt_base + S3C2410_WTCON);
+
+ printk(KERN_INFO PFX "watchdog %sabled\n",
+ (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+ }
+
+ return 0;
+}
+
+#else
+#define s3c2410wdt_suspend NULL
+#define s3c2410wdt_resume NULL
+#endif /* CONFIG_PM */
+
+
static struct device_driver s3c2410wdt_driver = {
.name = "s3c2410-wdt",
.bus = &platform_bus_type,
.probe = s3c2410wdt_probe,
.remove = s3c2410wdt_remove,
+ .shutdown = s3c2410wdt_shutdown,
+ .suspend = s3c2410wdt_suspend,
+ .resume = s3c2410wdt_resume,
};
-
static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
static int __init watchdog_init(void)
@@ -499,13 +522,13 @@ static int __init watchdog_init(void)
static void __exit watchdog_exit(void)
{
driver_unregister(&s3c2410wdt_driver);
- unregister_reboot_notifier(&s3c2410wdt_notifier);
}
module_init(watchdog_init);
module_exit(watchdog_exit);
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, "
+ "Dimitry Andric <dimitry.andric@tomtom.com>");
MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
new file mode 100644
index 000000000000..c6cbf808d8c2
--- /dev/null
+++ b/drivers/char/watchdog/sbc8360.c
@@ -0,0 +1,414 @@
+/*
+ * SBC8360 Watchdog driver
+ *
+ * (c) Copyright 2005 Webcon, Inc.
+ *
+ * Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ * on acquirewdt.c which is based on wdt.c.
+ *
+ * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ * Based on advantechwdt.c which is based on acquirewdt.c which
+ * is based on wdt.c.
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * Based on acquirewdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@redhat.com>
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H. To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ * N
+ * M | 1 2 3 4
+ * --|----------------------------------
+ * 0 | 0.5s 5s 50s 100s
+ * 1 | 1s 10s 100s 200s
+ * 2 | 1.5s 15s 150s 300s
+ * 3 | 2s 20s 200s 400s
+ * 4 | 2.5s 25s 250s 500s
+ * 5 | 3s 30s 300s 600s
+ * 6 | 3.5s 35s 350s 700s
+ * 7 | 4s 40s 400s 800s
+ * 8 | 4.5s 45s 450s 900s
+ * 9 | 5s 50s 500s 1000s
+ * A | 5.5s 55s 550s 1100s
+ * B | 6s 60s 600s 1200s
+ * C | 6.5s 65s 650s 1300s
+ * D | 7s 70s 700s 1400s
+ * E | 7.5s 75s 750s 1500s
+ * F | 8s 80s 800s 1600s
+ *
+ * Another way to say the same things is:
+ * For N=1, Timeout = (M+1) * 0.5s
+ * For N=2, Timeout = (M+1) * 5s
+ * For N=3, Timeout = (M+1) * 50s
+ * For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+ {0, 1}, /* 0 = 0.5s */
+ {1, 1}, /* 1 = 1s */
+ {2, 1}, /* 2 = 1.5s */
+ {3, 1}, /* 3 = 2s */
+ {4, 1}, /* 4 = 2.5s */
+ {5, 1}, /* 5 = 3s */
+ {6, 1}, /* 6 = 3.5s */
+ {7, 1}, /* 7 = 4s */
+ {8, 1}, /* 8 = 4.5s */
+ {9, 1}, /* 9 = 5s */
+ {0xA, 1}, /* 10 = 5.5s */
+ {0xB, 1}, /* 11 = 6s */
+ {0xC, 1}, /* 12 = 6.5s */
+ {0xD, 1}, /* 13 = 7s */
+ {0xE, 1}, /* 14 = 7.5s */
+ {0xF, 1}, /* 15 = 8s */
+ {0, 2}, /* 16 = 5s */
+ {1, 2}, /* 17 = 10s */
+ {2, 2}, /* 18 = 15s */
+ {3, 2}, /* 19 = 20s */
+ {4, 2}, /* 20 = 25s */
+ {5, 2}, /* 21 = 30s */
+ {6, 2}, /* 22 = 35s */
+ {7, 2}, /* 23 = 40s */
+ {8, 2}, /* 24 = 45s */
+ {9, 2}, /* 25 = 50s */
+ {0xA, 2}, /* 26 = 55s */
+ {0xB, 2}, /* 27 = 60s */
+ {0xC, 2}, /* 28 = 65s */
+ {0xD, 2}, /* 29 = 70s */
+ {0xE, 2}, /* 30 = 75s */
+ {0xF, 2}, /* 31 = 80s */
+ {0, 3}, /* 32 = 50s */
+ {1, 3}, /* 33 = 100s */
+ {2, 3}, /* 34 = 150s */
+ {3, 3}, /* 35 = 200s */
+ {4, 3}, /* 36 = 250s */
+ {5, 3}, /* 37 = 300s */
+ {6, 3}, /* 38 = 350s */
+ {7, 3}, /* 39 = 400s */
+ {8, 3}, /* 40 = 450s */
+ {9, 3}, /* 41 = 500s */
+ {0xA, 3}, /* 42 = 550s */
+ {0xB, 3}, /* 43 = 600s */
+ {0xC, 3}, /* 44 = 650s */
+ {0xD, 3}, /* 45 = 700s */
+ {0xE, 3}, /* 46 = 750s */
+ {0xF, 3}, /* 47 = 800s */
+ {0, 4}, /* 48 = 100s */
+ {1, 4}, /* 49 = 200s */
+ {2, 4}, /* 50 = 300s */
+ {3, 4}, /* 51 = 400s */
+ {4, 4}, /* 52 = 500s */
+ {5, 4}, /* 53 = 600s */
+ {6, 4}, /* 54 = 700s */
+ {7, 4}, /* 55 = 800s */
+ {8, 4}, /* 56 = 900s */
+ {9, 4}, /* 57 = 1000s */
+ {0xA, 4}, /* 58 = 1100s */
+ {0xB, 4}, /* 59 = 1200s */
+ {0xC, 4}, /* 60 = 1300s */
+ {0xD, 4}, /* 61 = 1400s */
+ {0xE, 4}, /* 62 = 1500s */
+ {0xF, 4} /* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 27);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+ /* Enable the watchdog */
+ outb(0x0A, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ outb(0x0B, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Set timeout multiplier */
+ outb(wd_multiplier, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+ /* Write the base timer register */
+ outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ sbc8360_ping();
+ }
+ return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (test_and_set_bit(0, &sbc8360_is_open)) {
+ spin_unlock(&sbc8360_lock);
+ return -EBUSY;
+ }
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate and ping once to start the countdown */
+ spin_unlock(&sbc8360_lock);
+ sbc8360_activate();
+ sbc8360_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (expect_close == 42)
+ outb(0, SBC8360_ENABLE);
+ else
+ printk(KERN_CRIT PFX
+ "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
+
+ clear_bit(0, &sbc8360_is_open);
+ expect_close = 0;
+ spin_unlock(&sbc8360_lock);
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Disable the SBC8360 Watchdog */
+ outb(0, SBC8360_ENABLE);
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations sbc8360_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = sbc8360_write,
+ .open = sbc8360_open,
+ .release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &sbc8360_fops,
+};
+
+/*
+ * The SBC8360 needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+ .notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+ int res;
+ unsigned long int mseconds = 60000;
+
+ spin_lock_init(&sbc8360_lock);
+ res = misc_register(&sbc8360_miscdev);
+ if (res) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ goto out_nomisc;
+ }
+
+ if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+ printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+ SBC8360_ENABLE);
+ res = -EIO;
+ goto out_noenablereg;
+ }
+ if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+ printk(KERN_ERR PFX
+ "BASETIME method I/O %X is not available.\n",
+ SBC8360_BASETIME);
+ res = -EIO;
+ goto out_nobasetimereg;
+ }
+
+ res = register_reboot_notifier(&sbc8360_notifier);
+ if (res) {
+ printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+ goto out_noreboot;
+ }
+
+ if (timeout < 0 || timeout > 63) {
+ printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+ res = -EINVAL;
+ goto out_noreboot;
+ }
+
+ wd_margin = wd_times[timeout][0];
+ wd_multiplier = wd_times[timeout][1];
+
+ if (wd_multiplier == 1)
+ mseconds = (wd_margin + 1) * 500;
+ else if (wd_multiplier == 2)
+ mseconds = (wd_margin + 1) * 5000;
+ else if (wd_multiplier == 3)
+ mseconds = (wd_margin + 1) * 50000;
+ else if (wd_multiplier == 4)
+ mseconds = (wd_margin + 1) * 100000;
+
+ /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+ printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+ return 0;
+
+ out_noreboot:
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+ out_noenablereg:
+ out_nobasetimereg:
+ misc_deregister(&sbc8360_miscdev);
+ out_nomisc:
+ return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+ misc_deregister(&sbc8360_miscdev);
+ unregister_reboot_notifier(&sbc8360_notifier);
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of sbc8360.c */
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index c4568569f3a8..b4a102a2d7e3 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -206,7 +206,7 @@ static struct file_operations scx200_wdt_fops = {
static struct miscdevice scx200_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
- .name = NAME,
+ .name = "watchdog",
.fops = &scx200_wdt_fops,
};
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index 4d7ed931f5c6..20e5eb8667f2 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -77,7 +77,7 @@ static void watchdog_fire(unsigned long);
static struct timer_list watchdog_ticktock =
TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long timer_alive;
+static unsigned long driver_open, orphan_timer;
static char expect_close;
@@ -87,6 +87,9 @@ static char expect_close;
static void watchdog_fire(unsigned long data)
{
+ if (test_and_clear_bit(0, &orphan_timer))
+ module_put(THIS_MODULE);
+
if (soft_noboot)
printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
else
@@ -128,9 +131,9 @@ static int softdog_set_heartbeat(int t)
static int softdog_open(struct inode *inode, struct file *file)
{
- if(test_and_set_bit(0, &timer_alive))
+ if (test_and_set_bit(0, &driver_open))
return -EBUSY;
- if (nowayout)
+ if (!test_and_clear_bit(0, &orphan_timer))
__module_get(THIS_MODULE);
/*
* Activate timer
@@ -147,11 +150,13 @@ static int softdog_release(struct inode *inode, struct file *file)
*/
if (expect_close == 42) {
softdog_stop();
+ module_put(THIS_MODULE);
} else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ set_bit(0, &orphan_timer);
softdog_keepalive();
}
- clear_bit(0, &timer_alive);
+ clear_bit(0, &driver_open);
expect_close = 0;
return 0;
}
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 465e0fd0423d..b5d821015421 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -93,6 +93,12 @@ w83627hf_init(void)
w83627hf_select_wd_register();
+ outb_p(0xF6, WDT_EFER); /* Select CRF6 */
+ t=inb_p(WDT_EFDR); /* read CRF6 */
+ if (t != 0) {
+ printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout);
+ outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
+ }
outb_p(0xF5, WDT_EFER); /* Select CRF5 */
t=inb_p(WDT_EFDR); /* read CRF5 */
t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
new file mode 100644
index 000000000000..a7ff64c8921f
--- /dev/null
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -0,0 +1,543 @@
+/*
+ * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on w83877f_wdt.c by Scott Jennings,
+ * and wdt977.c by Woody Suwalski
+ *
+ * -----------------------
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION "1.00"
+#define WATCHDOG_NAME "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x3F0
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
+#define DEFAULT_TIMEOUT 45 /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutW; /* timeout in watchdog counter units */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 has the timeout in watchdog counter units.
+ * F3 is set to enable watchdog LED blink at timeout.
+ * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /* Set device Aux2 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+ * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+ * Map GP16 at pin 119.
+ * In test mode watch the bit 0 on F4 to indicate "triggered" or
+ * check watchdog LED on SBC.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ unsigned pin_map;
+
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x0A,IO_DATA_PORT);
+ outb_p(0x2C,IO_INDEX_PORT);
+ pin_map = inb_p(IO_DATA_PORT);
+ pin_map |= 0x10;
+ pin_map &= ~(0x20);
+ outb_p(0x2C,IO_INDEX_PORT);
+ outb_p(pin_map,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+
+ /* Set device Aux1 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "activated.\n");
+
+ return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 is reset to its default value (watchdog timer disabled).
+ * F3 is reset to its default state.
+ * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0xFF,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
+ * Gp13 (in reg E3) as inputs.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "shutdown.\n");
+
+ return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to kick watchdog reg F2 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+ int tmrval;
+
+ /*
+ * Convert seconds to watchdog counter time units, rounding up.
+ * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
+ * value. This information is supplied in the PCM-5335 manual and was
+ * checked by me on a real board. This is a bit strange because W83977f
+ * datasheet says counter unit is in minutes!
+ */
+ if (t < 15)
+ return -EINVAL;
+
+ tmrval = ((t + 15) + 29) / 30;
+
+ if (tmrval > 255)
+ return -EINVAL;
+
+ /*
+ * timeout is the timeout in seconds,
+ * timeoutW is the timeout in watchdog counter units.
+ */
+ timeoutW = tmrval;
+ timeout = (timeoutW * 30) - 15;
+ return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+ int new_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to read watchdog reg F4 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ new_status = inb_p(IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status = 0;
+ if (new_status & 1)
+ *status |= WDIOF_CARDRESET;
+
+ return 0;
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ /* If the watchdog is alive we don't need to start it again */
+ if( test_and_set_bit(0, &timer_alive) )
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (expect_close == 42)
+ {
+ wdt_stop();
+ clear_bit(0, &timer_alive);
+ } else {
+ wdt_keepalive();
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ }
+ expect_close = 0;
+ return 0;
+}
+
+/*
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if(count)
+ {
+ if (!nowayout)
+ {
+ size_t ofs;
+
+ /* note: just in case someone wrote the magic character long ago */
+ expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for(ofs = 0; ofs != count; ofs++)
+ {
+ char c;
+ if (get_user(c, buf + ofs))
+ return -EFAULT;
+ if (c == 'V') {
+ expect_close = 42;
+ }
+ }
+ }
+
+ /* someone wrote to us, we should restart timer */
+ wdt_keepalive();
+ }
+ return count;
+}
+
+/*
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features.
+ */
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int status;
+ int new_options, retval = -EINVAL;
+ int new_timeout;
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ uarg.i = (int __user *)arg;
+
+ switch(cmd)
+ {
+ default:
+ return -ENOIOCTLCMD;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ wdt_get_status(&status);
+ return put_user(status, uarg.i);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, uarg.i);
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user (new_options, uarg.i))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ wdt_stop();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ wdt_start();
+ retval = 0;
+ }
+
+ return retval;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+
+ if (wdt_set_timeout(new_timeout))
+ return -EINVAL;
+
+ wdt_keepalive();
+ /* Fall */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, uarg.i);
+
+ }
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT)
+ wdt_stop();
+ return NOTIFY_DONE;
+}
+
+static struct file_operations wdt_fops=
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .ioctl = wdt_ioctl,
+ .open = wdt_open,
+ .release = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static int __init w83977f_wdt_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO PFX DRIVER_VERSION);
+
+ spin_lock_init(&spinlock);
+
+ /*
+ * Check that the timeout value is within it's range ;
+ * if not reset to the default
+ */
+ if (wdt_set_timeout(timeout)) {
+ wdt_set_timeout(DEFAULT_TIMEOUT);
+ printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+ DEFAULT_TIMEOUT);
+ }
+
+ if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+ {
+ printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ IO_INDEX_PORT);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ rc = misc_register(&wdt_miscdev);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ wdt_miscdev.minor, rc);
+ goto err_out_region;
+ }
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ rc);
+ goto err_out_miscdev;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+ timeout, nowayout, testmode);
+
+ return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt_miscdev);
+err_out_region:
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+ wdt_stop();
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
new file mode 100644
index 000000000000..0bc2059c1e08
--- /dev/null
+++ b/drivers/connector/Kconfig
@@ -0,0 +1,13 @@
+menu "Connector - unified userspace <-> kernelspace linker"
+
+config CONNECTOR
+ tristate "Connector - unified userspace <-> kernelspace linker"
+ depends on NET
+ ---help---
+ This is unified userspace <-> kernelspace connector working on top
+ of the netlink socket protocol.
+
+ Connector support can also be built as a module. If so, the module
+ will be called cn.ko.
+
+endmenu
diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile
new file mode 100644
index 000000000000..12ca79e8234d
--- /dev/null
+++ b/drivers/connector/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_CONNECTOR) += cn.o
+
+cn-y += cn_queue.o connector.o
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
new file mode 100644
index 000000000000..966632182e2d
--- /dev/null
+++ b/drivers/connector/cn_queue.c
@@ -0,0 +1,173 @@
+/*
+ * cn_queue.c
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/suspend.h>
+#include <linux/connector.h>
+#include <linux/delay.h>
+
+static void cn_queue_wrapper(void *data)
+{
+ struct cn_callback_entry *cbq = data;
+
+ cbq->cb->callback(cbq->cb->priv);
+ cbq->destruct_data(cbq->ddata);
+ cbq->ddata = NULL;
+}
+
+static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb)
+{
+ struct cn_callback_entry *cbq;
+
+ cbq = kzalloc(sizeof(*cbq), GFP_KERNEL);
+ if (!cbq) {
+ printk(KERN_ERR "Failed to create new callback queue.\n");
+ return NULL;
+ }
+
+ cbq->cb = cb;
+ INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq);
+ return cbq;
+}
+
+static void cn_queue_free_callback(struct cn_callback_entry *cbq)
+{
+ cancel_delayed_work(&cbq->work);
+ flush_workqueue(cbq->pdev->cn_queue);
+
+ kfree(cbq);
+}
+
+int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
+{
+ return ((i1->idx == i2->idx) && (i1->val == i2->val));
+}
+
+int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
+{
+ struct cn_callback_entry *cbq, *__cbq;
+ int found = 0;
+
+ cbq = cn_queue_alloc_callback_entry(cb);
+ if (!cbq)
+ return -ENOMEM;
+
+ atomic_inc(&dev->refcnt);
+ cbq->pdev = dev;
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
+ if (cn_cb_equal(&__cbq->cb->id, &cb->id)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ list_add_tail(&cbq->callback_entry, &dev->queue_list);
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (found) {
+ atomic_dec(&dev->refcnt);
+ cn_queue_free_callback(cbq);
+ return -EINVAL;
+ }
+
+ cbq->nls = dev->nls;
+ cbq->seq = 0;
+ cbq->group = cbq->cb->id.idx;
+
+ return 0;
+}
+
+void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
+{
+ struct cn_callback_entry *cbq, *n;
+ int found = 0;
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
+ if (cn_cb_equal(&cbq->cb->id, id)) {
+ list_del(&cbq->callback_entry);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (found) {
+ cn_queue_free_callback(cbq);
+ atomic_dec_and_test(&dev->refcnt);
+ }
+}
+
+struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+{
+ struct cn_queue_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ snprintf(dev->name, sizeof(dev->name), "%s", name);
+ atomic_set(&dev->refcnt, 0);
+ INIT_LIST_HEAD(&dev->queue_list);
+ spin_lock_init(&dev->queue_lock);
+
+ dev->nls = nls;
+ dev->netlink_groups = 0;
+
+ dev->cn_queue = create_workqueue(dev->name);
+ if (!dev->cn_queue) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+
+void cn_queue_free_dev(struct cn_queue_dev *dev)
+{
+ struct cn_callback_entry *cbq, *n;
+
+ flush_workqueue(dev->cn_queue);
+ destroy_workqueue(dev->cn_queue);
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)
+ list_del(&cbq->callback_entry);
+ spin_unlock_bh(&dev->queue_lock);
+
+ while (atomic_read(&dev->refcnt)) {
+ printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+ dev->name, atomic_read(&dev->refcnt));
+ msleep(1000);
+ }
+
+ kfree(dev);
+ dev = NULL;
+}
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
new file mode 100644
index 000000000000..aaf6d468a8b9
--- /dev/null
+++ b/drivers/connector/connector.c
@@ -0,0 +1,486 @@
+/*
+ * connector.c
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/moduleparam.h>
+#include <linux/connector.h>
+
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+
+static u32 cn_idx = CN_IDX_CONNECTOR;
+static u32 cn_val = CN_VAL_CONNECTOR;
+
+module_param(cn_idx, uint, 0);
+module_param(cn_val, uint, 0);
+MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
+MODULE_PARM_DESC(cn_val, "Connector's main device val.");
+
+static DECLARE_MUTEX(notify_lock);
+static LIST_HEAD(notify_list);
+
+static struct cn_dev cdev;
+
+int cn_already_initialized = 0;
+
+/*
+ * msg->seq and msg->ack are used to determine message genealogy.
+ * When someone sends message it puts there locally unique sequence
+ * and random acknowledge numbers. Sequence number may be copied into
+ * nlmsghdr->nlmsg_seq too.
+ *
+ * Sequence number is incremented with each message to be sent.
+ *
+ * If we expect reply to our message then the sequence number in
+ * received message MUST be the same as in original message, and
+ * acknowledge number MUST be the same + 1.
+ *
+ * If we receive a message and its sequence number is not equal to the
+ * one we are expecting then it is a new message.
+ *
+ * If we receive a message and its sequence number is the same as one
+ * we are expecting but it's acknowledgement number is not equal to
+ * the acknowledgement number in the original message + 1, then it is
+ * a new message.
+ *
+ */
+int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
+{
+ struct cn_callback_entry *__cbq;
+ unsigned int size;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct cn_msg *data;
+ struct cn_dev *dev = &cdev;
+ u32 group = 0;
+ int found = 0;
+
+ if (!__group) {
+ spin_lock_bh(&dev->cbdev->queue_lock);
+ list_for_each_entry(__cbq, &dev->cbdev->queue_list,
+ callback_entry) {
+ if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
+ found = 1;
+ group = __cbq->group;
+ }
+ }
+ spin_unlock_bh(&dev->cbdev->queue_lock);
+
+ if (!found)
+ return -ENODEV;
+ } else {
+ group = __group;
+ }
+
+ size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+
+ skb = alloc_skb(size, gfp_mask);
+ if (!skb)
+ return -ENOMEM;
+
+ nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
+
+ data = NLMSG_DATA(nlh);
+
+ memcpy(data, msg, sizeof(*data) + msg->len);
+
+ NETLINK_CB(skb).dst_group = group;
+
+ netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
+
+ return 0;
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/*
+ * Callback helper - queues work and setup destructor for given data.
+ */
+static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
+{
+ struct cn_callback_entry *__cbq;
+ struct cn_dev *dev = &cdev;
+ int found = 0;
+
+ spin_lock_bh(&dev->cbdev->queue_lock);
+ list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
+ if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
+ /*
+ * Let's scream if there is some magic and the
+ * data will arrive asynchronously here.
+ * [i.e. netlink messages will be queued].
+ * After the first warning I will fix it
+ * quickly, but now I think it is
+ * impossible. --zbr (2004_04_27).
+ */
+ if (likely(!test_bit(0, &__cbq->work.pending) &&
+ __cbq->ddata == NULL)) {
+ __cbq->cb->priv = msg;
+
+ __cbq->ddata = data;
+ __cbq->destruct_data = destruct_data;
+
+ if (queue_work(dev->cbdev->cn_queue,
+ &__cbq->work))
+ found = 1;
+ } else {
+ printk("%s: cbq->data=%p, "
+ "work->pending=%08lx.\n",
+ __func__, __cbq->ddata,
+ __cbq->work.pending);
+ WARN_ON(1);
+ }
+ break;
+ }
+ }
+ spin_unlock_bh(&dev->cbdev->queue_lock);
+
+ return found ? 0 : -ENODEV;
+}
+
+/*
+ * Skb receive helper - checks skb and msg size and calls callback
+ * helper.
+ */
+static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ u32 pid, uid, seq, group;
+ struct cn_msg *msg;
+
+ pid = NETLINK_CREDS(skb)->pid;
+ uid = NETLINK_CREDS(skb)->uid;
+ seq = nlh->nlmsg_seq;
+ group = NETLINK_CB((skb)).dst_group;
+ msg = NLMSG_DATA(nlh);
+
+ return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+}
+
+/*
+ * Main netlink receiving function.
+ *
+ * It checks skb and netlink header sizes and calls the skb receive
+ * helper with a shared skb.
+ */
+static void cn_rx_skb(struct sk_buff *__skb)
+{
+ struct nlmsghdr *nlh;
+ u32 len;
+ int err;
+ struct sk_buff *skb;
+
+ skb = skb_get(__skb);
+
+ if (skb->len >= NLMSG_SPACE(0)) {
+ nlh = (struct nlmsghdr *)skb->data;
+
+ if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
+ skb->len < nlh->nlmsg_len ||
+ nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
+ kfree_skb(skb);
+ goto out;
+ }
+
+ len = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (len > skb->len)
+ len = skb->len;
+
+ err = __cn_rx_skb(skb, nlh);
+ if (err < 0)
+ kfree_skb(skb);
+ }
+
+out:
+ kfree_skb(__skb);
+}
+
+/*
+ * Netlink socket input callback - dequeues the skbs and calls the
+ * main netlink receiving function.
+ */
+static void cn_input(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
+ cn_rx_skb(skb);
+}
+
+/*
+ * Notification routing.
+ *
+ * Gets id and checks if there are notification request for it's idx
+ * and val. If there are such requests notify the listeners with the
+ * given notify event.
+ *
+ */
+static void cn_notify(struct cb_id *id, u32 notify_event)
+{
+ struct cn_ctl_entry *ent;
+
+ down(&notify_lock);
+ list_for_each_entry(ent, &notify_list, notify_entry) {
+ int i;
+ struct cn_notify_req *req;
+ struct cn_ctl_msg *ctl = ent->msg;
+ int idx_found, val_found;
+
+ idx_found = val_found = 0;
+
+ req = (struct cn_notify_req *)ctl->data;
+ for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
+ if (id->idx >= req->first &&
+ id->idx < req->first + req->range) {
+ idx_found = 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
+ if (id->val >= req->first &&
+ id->val < req->first + req->range) {
+ val_found = 1;
+ break;
+ }
+ }
+
+ if (idx_found && val_found) {
+ struct cn_msg m = { .ack = notify_event, };
+
+ memcpy(&m.id, id, sizeof(m.id));
+ cn_netlink_send(&m, ctl->group, GFP_KERNEL);
+ }
+ }
+ up(&notify_lock);
+}
+
+/*
+ * Callback add routing - adds callback with given ID and name.
+ * If there is registered callback with the same ID it will not be added.
+ *
+ * May sleep.
+ */
+int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
+{
+ int err;
+ struct cn_dev *dev = &cdev;
+ struct cn_callback *cb;
+
+ cb = kzalloc(sizeof(*cb), GFP_KERNEL);
+ if (!cb)
+ return -ENOMEM;
+
+ scnprintf(cb->name, sizeof(cb->name), "%s", name);
+
+ memcpy(&cb->id, id, sizeof(cb->id));
+ cb->callback = callback;
+
+ err = cn_queue_add_callback(dev->cbdev, cb);
+ if (err) {
+ kfree(cb);
+ return err;
+ }
+
+ cn_notify(id, 0);
+
+ return 0;
+}
+
+/*
+ * Callback remove routing - removes callback
+ * with given ID.
+ * If there is no registered callback with given
+ * ID nothing happens.
+ *
+ * May sleep while waiting for reference counter to become zero.
+ */
+void cn_del_callback(struct cb_id *id)
+{
+ struct cn_dev *dev = &cdev;
+
+ cn_queue_del_callback(dev->cbdev, id);
+ cn_notify(id, 1);
+}
+
+/*
+ * Checks two connector's control messages to be the same.
+ * Returns 1 if they are the same or if the first one is corrupted.
+ */
+static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
+{
+ int i;
+ struct cn_notify_req *req1, *req2;
+
+ if (m1->idx_notify_num != m2->idx_notify_num)
+ return 0;
+
+ if (m1->val_notify_num != m2->val_notify_num)
+ return 0;
+
+ if (m1->len != m2->len)
+ return 0;
+
+ if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
+ m1->len)
+ return 1;
+
+ req1 = (struct cn_notify_req *)m1->data;
+ req2 = (struct cn_notify_req *)m2->data;
+
+ for (i = 0; i < m1->idx_notify_num; ++i) {
+ if (req1->first != req2->first || req1->range != req2->range)
+ return 0;
+ req1++;
+ req2++;
+ }
+
+ for (i = 0; i < m1->val_notify_num; ++i) {
+ if (req1->first != req2->first || req1->range != req2->range)
+ return 0;
+ req1++;
+ req2++;
+ }
+
+ return 1;
+}
+
+/*
+ * Main connector device's callback.
+ *
+ * Used for notification of a request's processing.
+ */
+static void cn_callback(void *data)
+{
+ struct cn_msg *msg = data;
+ struct cn_ctl_msg *ctl;
+ struct cn_ctl_entry *ent;
+ u32 size;
+
+ if (msg->len < sizeof(*ctl))
+ return;
+
+ ctl = (struct cn_ctl_msg *)msg->data;
+
+ size = (sizeof(*ctl) + ((ctl->idx_notify_num +
+ ctl->val_notify_num) *
+ sizeof(struct cn_notify_req)));
+
+ if (msg->len != size)
+ return;
+
+ if (ctl->len + sizeof(*ctl) != msg->len)
+ return;
+
+ /*
+ * Remove notification.
+ */
+ if (ctl->group == 0) {
+ struct cn_ctl_entry *n;
+
+ down(&notify_lock);
+ list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
+ if (cn_ctl_msg_equals(ent->msg, ctl)) {
+ list_del(&ent->notify_entry);
+ kfree(ent);
+ }
+ }
+ up(&notify_lock);
+
+ return;
+ }
+
+ size += sizeof(*ent);
+
+ ent = kzalloc(size, GFP_KERNEL);
+ if (!ent)
+ return;
+
+ ent->msg = (struct cn_ctl_msg *)(ent + 1);
+
+ memcpy(ent->msg, ctl, size - sizeof(*ent));
+
+ down(&notify_lock);
+ list_add(&ent->notify_entry, &notify_list);
+ up(&notify_lock);
+}
+
+static int __init cn_init(void)
+{
+ struct cn_dev *dev = &cdev;
+ int err;
+
+ dev->input = cn_input;
+ dev->id.idx = cn_idx;
+ dev->id.val = cn_val;
+
+ dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
+ CN_NETLINK_USERS + 0xf,
+ dev->input, THIS_MODULE);
+ if (!dev->nls)
+ return -EIO;
+
+ dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
+ if (!dev->cbdev) {
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+ return -EINVAL;
+ }
+
+ err = cn_add_callback(&dev->id, "connector", &cn_callback);
+ if (err) {
+ cn_queue_free_dev(dev->cbdev);
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+ return -EINVAL;
+ }
+
+ cn_already_initialized = 1;
+
+ return 0;
+}
+
+static void __exit cn_fini(void)
+{
+ struct cn_dev *dev = &cdev;
+
+ cn_already_initialized = 0;
+
+ cn_del_callback(&dev->id);
+ cn_queue_free_dev(dev->cbdev);
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+}
+
+module_init(cn_init);
+module_exit(cn_fini);
+
+EXPORT_SYMBOL_GPL(cn_add_callback);
+EXPORT_SYMBOL_GPL(cn_del_callback);
+EXPORT_SYMBOL_GPL(cn_netlink_send);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 10b014982381..109d62ccf651 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -627,7 +627,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
ret = kobject_register(&policy->kobj);
if (ret)
- goto err_out;
+ goto err_out_driver_exit;
/* set up files for this cpu device */
drv_attr = cpufreq_driver->attr;
@@ -673,6 +673,10 @@ err_out_unregister:
kobject_unregister(&policy->kobj);
wait_for_completion(&policy->kobj_unregister);
+err_out_driver_exit:
+ if (cpufreq_driver->exit)
+ cpufreq_driver->exit(policy);
+
err_out:
kfree(policy);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 5b29c3b2a331..327b58e64875 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -58,4 +58,31 @@ config EFI_PCDP
See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf>
+config DELL_RBU
+ tristate "BIOS update support for DELL systems via sysfs"
+ select FW_LOADER
+ help
+ Say m if you want to have the option of updating the BIOS for your
+ DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
+ supporting application to comunicate with the BIOS regarding the new
+ image for the image update to take effect.
+ See <file:Documentation/dell_rbu.txt> for more details on the driver.
+
+config DCDBAS
+ tristate "Dell Systems Management Base Driver"
+ depends on X86 || X86_64
+ default m
+ help
+ The Dell Systems Management Base Driver provides a sysfs interface
+ for systems management software to perform System Management
+ Interrupts (SMIs) and Host Control Actions (system power cycle or
+ power off after OS shutdown) on certain Dell systems.
+
+ See <file:Documentation/dcdbas.txt> for more details on the driver
+ and the Dell systems on which Dell systems management software makes
+ use of this driver.
+
+ Say Y or M here to enable the driver for use by Dell systems
+ management software such as Dell OpenManage.
+
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 90fd0b26db8b..85429979d0db 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -4,3 +4,5 @@
obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
+obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+obj-$(CONFIG_DCDBAS) += dcdbas.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
new file mode 100644
index 000000000000..955537fe9958
--- /dev/null
+++ b/drivers/firmware/dcdbas.c
@@ -0,0 +1,596 @@
+/*
+ * dcdbas.c: Dell Systems Management Base Driver
+ *
+ * The Dell Systems Management Base Driver provides a sysfs interface for
+ * systems management software to perform System Management Interrupts (SMIs)
+ * and Host Control Actions (power cycle or power off after OS shutdown) on
+ * Dell systems.
+ *
+ * See Documentation/dcdbas.txt for more information.
+ *
+ * Copyright (C) 1995-2005 Dell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#include "dcdbas.h"
+
+#define DRIVER_NAME "dcdbas"
+#define DRIVER_VERSION "5.6.0-1"
+#define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
+
+static struct platform_device *dcdbas_pdev;
+
+static u8 *smi_data_buf;
+static dma_addr_t smi_data_buf_handle;
+static unsigned long smi_data_buf_size;
+static u32 smi_data_buf_phys_addr;
+static DECLARE_MUTEX(smi_data_lock);
+
+static unsigned int host_control_action;
+static unsigned int host_control_smi_type;
+static unsigned int host_control_on_shutdown;
+
+/**
+ * smi_data_buf_free: free SMI data buffer
+ */
+static void smi_data_buf_free(void)
+{
+ if (!smi_data_buf)
+ return;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+ __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+ smi_data_buf_handle);
+ smi_data_buf = NULL;
+ smi_data_buf_handle = 0;
+ smi_data_buf_phys_addr = 0;
+ smi_data_buf_size = 0;
+}
+
+/**
+ * smi_data_buf_realloc: grow SMI data buffer if needed
+ */
+static int smi_data_buf_realloc(unsigned long size)
+{
+ void *buf;
+ dma_addr_t handle;
+
+ if (smi_data_buf_size >= size)
+ return 0;
+
+ if (size > MAX_SMI_DATA_BUF_SIZE)
+ return -EINVAL;
+
+ /* new buffer is needed */
+ buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
+ if (!buf) {
+ dev_dbg(&dcdbas_pdev->dev,
+ "%s: failed to allocate memory size %lu\n",
+ __FUNCTION__, size);
+ return -ENOMEM;
+ }
+ /* memory zeroed by dma_alloc_coherent */
+
+ if (smi_data_buf)
+ memcpy(buf, smi_data_buf, smi_data_buf_size);
+
+ /* free any existing buffer */
+ smi_data_buf_free();
+
+ /* set up new buffer for use */
+ smi_data_buf = buf;
+ smi_data_buf_handle = handle;
+ smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
+ smi_data_buf_size = size;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+ __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ return 0;
+}
+
+static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
+}
+
+static ssize_t smi_data_buf_size_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%lu\n", smi_data_buf_size);
+}
+
+static ssize_t smi_data_buf_size_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long buf_size;
+ ssize_t ret;
+
+ buf_size = simple_strtoul(buf, NULL, 10);
+
+ /* make sure SMI data buffer is at least buf_size */
+ down(&smi_data_lock);
+ ret = smi_data_buf_realloc(buf_size);
+ up(&smi_data_lock);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
+ size_t count)
+{
+ size_t max_read;
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ if (pos >= smi_data_buf_size) {
+ ret = 0;
+ goto out;
+ }
+
+ max_read = smi_data_buf_size - pos;
+ ret = min(max_read, count);
+ memcpy(buf, smi_data_buf + pos, ret);
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
+ size_t count)
+{
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ ret = smi_data_buf_realloc(pos + count);
+ if (ret)
+ goto out;
+
+ memcpy(smi_data_buf + pos, buf, count);
+ ret = count;
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+static ssize_t host_control_action_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_action);
+}
+
+static ssize_t host_control_action_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+
+ /* make sure buffer is available for host control command */
+ down(&smi_data_lock);
+ ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
+ up(&smi_data_lock);
+ if (ret)
+ return ret;
+
+ host_control_action = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+static ssize_t host_control_smi_type_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_smi_type);
+}
+
+static ssize_t host_control_smi_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ host_control_smi_type = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+static ssize_t host_control_on_shutdown_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_on_shutdown);
+}
+
+static ssize_t host_control_on_shutdown_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+/**
+ * smi_request: generate SMI request
+ *
+ * Called with smi_data_lock.
+ */
+static int smi_request(struct smi_cmd *smi_cmd)
+{
+ cpumask_t old_mask;
+ int ret = 0;
+
+ if (smi_cmd->magic != SMI_CMD_MAGIC) {
+ dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+ __FUNCTION__);
+ return -EBADR;
+ }
+
+ /* SMI requires CPU 0 */
+ old_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(0));
+ if (smp_processor_id() != 0) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+ __FUNCTION__);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* generate SMI */
+ asm volatile (
+ "outb %b0,%w1"
+ : /* no output args */
+ : "a" (smi_cmd->command_code),
+ "d" (smi_cmd->command_address),
+ "b" (smi_cmd->ebx),
+ "c" (smi_cmd->ecx)
+ : "memory"
+ );
+
+out:
+ set_cpus_allowed(current, old_mask);
+ return ret;
+}
+
+/**
+ * smi_request_store:
+ *
+ * The valid values are:
+ * 0: zero SMI data buffer
+ * 1: generate calling interface SMI
+ * 2: generate raw SMI
+ *
+ * User application writes smi_cmd to smi_data before telling driver
+ * to generate SMI.
+ */
+static ssize_t smi_request_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct smi_cmd *smi_cmd;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ if (smi_data_buf_size < sizeof(struct smi_cmd)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ smi_cmd = (struct smi_cmd *)smi_data_buf;
+
+ switch (val) {
+ case 2:
+ /* Raw SMI */
+ ret = smi_request(smi_cmd);
+ if (!ret)
+ ret = count;
+ break;
+ case 1:
+ /* Calling Interface SMI */
+ smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
+ ret = smi_request(smi_cmd);
+ if (!ret)
+ ret = count;
+ break;
+ case 0:
+ memset(smi_data_buf, 0, smi_data_buf_size);
+ ret = count;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+/**
+ * host_control_smi: generate host control SMI
+ *
+ * Caller must set up the host control command in smi_data_buf.
+ */
+static int host_control_smi(void)
+{
+ struct apm_cmd *apm_cmd;
+ u8 *data;
+ unsigned long flags;
+ u32 num_ticks;
+ s8 cmd_status;
+ u8 index;
+
+ apm_cmd = (struct apm_cmd *)smi_data_buf;
+ apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
+
+ switch (host_control_smi_type) {
+ case HC_SMITYPE_TYPE1:
+ spin_lock_irqsave(&rtc_lock, flags);
+ /* write SMI data buffer physical address */
+ data = (u8 *)&smi_data_buf_phys_addr;
+ for (index = PE1300_CMOS_CMD_STRUCT_PTR;
+ index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
+ index++, data++) {
+ outb(index,
+ (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
+ outb(*data,
+ (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
+ }
+
+ /* first set status to -1 as called by spec */
+ cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
+ outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
+
+ /* generate SMM call */
+ outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ /* wait a few to see if it executed */
+ num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+ while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
+ == ESM_STATUS_CMD_UNSUCCESSFUL) {
+ num_ticks--;
+ if (num_ticks == EXPIRED_TIMER)
+ return -ETIME;
+ }
+ break;
+
+ case HC_SMITYPE_TYPE2:
+ case HC_SMITYPE_TYPE3:
+ spin_lock_irqsave(&rtc_lock, flags);
+ /* write SMI data buffer physical address */
+ data = (u8 *)&smi_data_buf_phys_addr;
+ for (index = PE1400_CMOS_CMD_STRUCT_PTR;
+ index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
+ index++, data++) {
+ outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
+ outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
+ }
+
+ /* generate SMM call */
+ if (host_control_smi_type == HC_SMITYPE_TYPE3)
+ outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+ else
+ outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
+
+ /* restore RTC index pointer since it was written to above */
+ CMOS_READ(RTC_REG_C);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ /* read control port back to serialize write */
+ cmd_status = inb(PE1400_APM_CONTROL_PORT);
+
+ /* wait a few to see if it executed */
+ num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+ while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
+ num_ticks--;
+ if (num_ticks == EXPIRED_TIMER)
+ return -ETIME;
+ }
+ break;
+
+ default:
+ dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+ __FUNCTION__, host_control_smi_type);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+/**
+ * dcdbas_host_control: initiate host control
+ *
+ * This function is called by the driver after the system has
+ * finished shutting down if the user application specified a
+ * host control action to perform on shutdown. It is safe to
+ * use smi_data_buf at this point because the system has finished
+ * shutting down and no userspace apps are running.
+ */
+static void dcdbas_host_control(void)
+{
+ struct apm_cmd *apm_cmd;
+ u8 action;
+
+ if (host_control_action == HC_ACTION_NONE)
+ return;
+
+ action = host_control_action;
+ host_control_action = HC_ACTION_NONE;
+
+ if (!smi_data_buf) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__);
+ return;
+ }
+
+ if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+ __FUNCTION__);
+ return;
+ }
+
+ apm_cmd = (struct apm_cmd *)smi_data_buf;
+
+ /* power off takes precedence */
+ if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
+ apm_cmd->command = ESM_APM_POWER_CYCLE;
+ apm_cmd->reserved = 0;
+ *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
+ host_control_smi();
+ } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
+ apm_cmd->command = ESM_APM_POWER_CYCLE;
+ apm_cmd->reserved = 0;
+ *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
+ host_control_smi();
+ }
+}
+
+/**
+ * dcdbas_reboot_notify: handle reboot notification for host control
+ */
+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);
+ }
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block dcdbas_reboot_nb = {
+ .notifier_call = dcdbas_reboot_notify,
+ .next = NULL,
+ .priority = 0
+};
+
+static DCDBAS_BIN_ATTR_RW(smi_data);
+
+static struct bin_attribute *dcdbas_bin_attrs[] = {
+ &bin_attr_smi_data,
+ NULL
+};
+
+static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
+static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
+static DCDBAS_DEV_ATTR_WO(smi_request);
+static DCDBAS_DEV_ATTR_RW(host_control_action);
+static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
+static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
+
+static struct device_attribute *dcdbas_dev_attrs[] = {
+ &dev_attr_smi_data_buf_size,
+ &dev_attr_smi_data_buf_phys_addr,
+ &dev_attr_smi_request,
+ &dev_attr_host_control_action,
+ &dev_attr_host_control_smi_type,
+ &dev_attr_host_control_on_shutdown,
+ NULL
+};
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+ int i;
+
+ host_control_action = HC_ACTION_NONE;
+ host_control_smi_type = HC_SMITYPE_NONE;
+
+ dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (IS_ERR(dcdbas_pdev))
+ return PTR_ERR(dcdbas_pdev);
+
+ /*
+ * BIOS SMI calls require buffer addresses be in 32-bit address space.
+ * This is done by setting the DMA mask below.
+ */
+ dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
+ dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
+
+ register_reboot_notifier(&dcdbas_reboot_nb);
+
+ for (i = 0; dcdbas_bin_attrs[i]; i++)
+ sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
+ dcdbas_bin_attrs[i]);
+
+ for (i = 0; dcdbas_dev_attrs[i]; i++)
+ device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
+
+ dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
+ DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+ return 0;
+}
+
+/**
+ * dcdbas_exit: perform driver cleanup
+ */
+static void __exit dcdbas_exit(void)
+{
+ platform_device_unregister(dcdbas_pdev);
+ unregister_reboot_notifier(&dcdbas_reboot_nb);
+ smi_data_buf_free();
+}
+
+module_init(dcdbas_init);
+module_exit(dcdbas_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Dell Inc.");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
new file mode 100644
index 000000000000..58a85182b3e8
--- /dev/null
+++ b/drivers/firmware/dcdbas.h
@@ -0,0 +1,107 @@
+/*
+ * dcdbas.h: Definitions for Dell Systems Management Base driver
+ *
+ * Copyright (C) 1995-2005 Dell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DCDBAS_H_
+#define _DCDBAS_H_
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define MAX_SMI_DATA_BUF_SIZE (256 * 1024)
+
+#define HC_ACTION_NONE (0)
+#define HC_ACTION_HOST_CONTROL_POWEROFF BIT(1)
+#define HC_ACTION_HOST_CONTROL_POWERCYCLE BIT(2)
+
+#define HC_SMITYPE_NONE (0)
+#define HC_SMITYPE_TYPE1 (1)
+#define HC_SMITYPE_TYPE2 (2)
+#define HC_SMITYPE_TYPE3 (3)
+
+#define ESM_APM_CMD (0x0A0)
+#define ESM_APM_POWER_CYCLE (0x10)
+#define ESM_STATUS_CMD_UNSUCCESSFUL (-1)
+
+#define CMOS_BASE_PORT (0x070)
+#define CMOS_PAGE1_INDEX_PORT (0)
+#define CMOS_PAGE1_DATA_PORT (1)
+#define CMOS_PAGE2_INDEX_PORT_PIIX4 (2)
+#define CMOS_PAGE2_DATA_PORT_PIIX4 (3)
+#define PE1400_APM_CONTROL_PORT (0x0B0)
+#define PCAT_APM_CONTROL_PORT (0x0B2)
+#define PCAT_APM_STATUS_PORT (0x0B3)
+#define PE1300_CMOS_CMD_STRUCT_PTR (0x38)
+#define PE1400_CMOS_CMD_STRUCT_PTR (0x70)
+
+#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN (14)
+#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM (16)
+
+#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING (10000)
+#define EXPIRED_TIMER (0)
+
+#define SMI_CMD_MAGIC (0x534D4931)
+
+#define DCDBAS_DEV_ATTR_RW(_name) \
+ DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
+
+#define DCDBAS_DEV_ATTR_RO(_name) \
+ DEVICE_ATTR(_name,0400,_name##_show,NULL);
+
+#define DCDBAS_DEV_ATTR_WO(_name) \
+ DEVICE_ATTR(_name,0200,NULL,_name##_store);
+
+#define DCDBAS_BIN_ATTR_RW(_name) \
+struct bin_attribute bin_attr_##_name = { \
+ .attr = { .name = __stringify(_name), \
+ .mode = 0600, \
+ .owner = THIS_MODULE }, \
+ .read = _name##_read, \
+ .write = _name##_write, \
+}
+
+struct smi_cmd {
+ __u32 magic;
+ __u32 ebx;
+ __u32 ecx;
+ __u16 command_address;
+ __u8 command_code;
+ __u8 reserved;
+ __u8 command_buffer[1];
+} __attribute__ ((packed));
+
+struct apm_cmd {
+ __u8 command;
+ __s8 status;
+ __u16 reserved;
+ union {
+ struct {
+ __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
+ } __attribute__ ((packed)) shortreq;
+
+ struct {
+ __u16 num_sg_entries;
+ struct {
+ __u32 size;
+ __u64 addr;
+ } __attribute__ ((packed))
+ sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
+ } __attribute__ ((packed)) longreq;
+ } __attribute__ ((packed)) parameters;
+} __attribute__ ((packed));
+
+#endif /* _DCDBAS_H_ */
+
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
new file mode 100644
index 000000000000..3b865f34a095
--- /dev/null
+++ b/drivers/firmware/dell_rbu.c
@@ -0,0 +1,634 @@
+/*
+ * dell_rbu.c
+ * Bios Update driver for Dell systems
+ * Author: Dell Inc
+ * Abhay Salunke <abhay_salunke@dell.com>
+ *
+ * Copyright (C) 2005 Dell Inc.
+ *
+ * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
+ * creating entries in the /sys file systems on Linux 2.6 and higher
+ * kernels. The driver supports two mechanism to update the BIOS namely
+ * contiguous and packetized. Both these methods still require having some
+ * application to set the CMOS bit indicating the BIOS to update itself
+ * after a reboot.
+ *
+ * Contiguous method:
+ * This driver writes the incoming data in a monolithic image by allocating
+ * contiguous physical pages large enough to accommodate the incoming BIOS
+ * image size.
+ *
+ * Packetized method:
+ * The driver writes the incoming packet image by allocating a new packet
+ * on every time the packet data is written. This driver requires an
+ * application to break the BIOS image in to fixed sized packet chunks.
+ *
+ * See Documentation/dell_rbu.txt for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+
+MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
+MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+
+#define BIOS_SCAN_LIMIT 0xffffffff
+#define MAX_IMAGE_LENGTH 16
+static struct _rbu_data {
+ void *image_update_buffer;
+ unsigned long image_update_buffer_size;
+ unsigned long bios_image_size;
+ int image_update_ordernum;
+ int dma_alloc;
+ spinlock_t lock;
+ unsigned long packet_read_count;
+ unsigned long packet_write_count;
+ unsigned long num_packets;
+ unsigned long packetsize;
+} rbu_data;
+
+static char image_type[MAX_IMAGE_LENGTH] = "mono";
+module_param_string(image_type, image_type, sizeof(image_type), 0);
+MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
+
+struct packet_data {
+ struct list_head list;
+ size_t length;
+ void *data;
+ int ordernum;
+};
+
+static struct packet_data packet_data_head;
+
+static struct platform_device *rbu_device;
+static int context;
+static dma_addr_t dell_rbu_dmaaddr;
+
+static void init_packet_head(void)
+{
+ INIT_LIST_HEAD(&packet_data_head.list);
+ rbu_data.packet_write_count = 0;
+ rbu_data.packet_read_count = 0;
+ rbu_data.num_packets = 0;
+ rbu_data.packetsize = 0;
+}
+
+static int fill_last_packet(void *data, size_t length)
+{
+ struct list_head *ptemp_list;
+ struct packet_data *packet = NULL;
+ int packet_count = 0;
+
+ pr_debug("fill_last_packet: entry \n");
+
+ if (!rbu_data.num_packets) {
+ pr_debug("fill_last_packet: num_packets=0\n");
+ return -ENOMEM;
+ }
+
+ packet_count = rbu_data.num_packets;
+
+ ptemp_list = (&packet_data_head.list)->prev;
+
+ packet = list_entry(ptemp_list, struct packet_data, list);
+
+ if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
+ pr_debug("dell_rbu:%s: packet size data "
+ "overrun\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ pr_debug("fill_last_packet : buffer = %p\n", packet->data);
+
+ memcpy((packet->data + rbu_data.packet_write_count), data, length);
+
+ if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) {
+ /*
+ * this was the last data chunk in the packet
+ * so reinitialize the packet data counter to zero
+ */
+ rbu_data.packet_write_count = 0;
+ } else
+ rbu_data.packet_write_count += length;
+
+ pr_debug("fill_last_packet: exit \n");
+ return 0;
+}
+
+static int create_packet(size_t length)
+{
+ struct packet_data *newpacket;
+ int ordernum = 0;
+
+ pr_debug("create_packet: entry \n");
+
+ if (!rbu_data.packetsize) {
+ pr_debug("create_packet: packetsize not specified\n");
+ return -EINVAL;
+ }
+
+ newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+ if (!newpacket) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ ordernum = get_order(length);
+ /*
+ * there is no upper limit on memory
+ * address for packetized mechanism
+ */
+ newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
+ ordernum);
+
+ pr_debug("create_packet: newpacket %p\n", newpacket->data);
+
+ if (!newpacket->data) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
+ kfree(newpacket);
+ return -ENOMEM;
+ }
+
+ newpacket->ordernum = ordernum;
+ ++rbu_data.num_packets;
+ /*
+ * initialize the newly created packet headers
+ */
+ INIT_LIST_HEAD(&newpacket->list);
+ list_add_tail(&newpacket->list, &packet_data_head.list);
+ /*
+ * packets have fixed size
+ */
+ newpacket->length = rbu_data.packetsize;
+
+ pr_debug("create_packet: exit \n");
+
+ return 0;
+}
+
+static int packetize_data(void *data, size_t length)
+{
+ int rc = 0;
+
+ if (!rbu_data.packet_write_count) {
+ if ((rc = create_packet(length)))
+ return rc;
+ }
+ if ((rc = fill_last_packet(data, length)))
+ return rc;
+
+ return rc;
+}
+
+static int
+do_packet_read(char *data, struct list_head *ptemp_list,
+ int length, int bytes_read, int *list_read_count)
+{
+ void *ptemp_buf;
+ struct packet_data *newpacket = NULL;
+ int bytes_copied = 0;
+ int j = 0;
+
+ newpacket = list_entry(ptemp_list, struct packet_data, list);
+ *list_read_count += newpacket->length;
+
+ if (*list_read_count > bytes_read) {
+ /* point to the start of unread data */
+ j = newpacket->length - (*list_read_count - bytes_read);
+ /* point to the offset in the packet buffer */
+ ptemp_buf = (u8 *) newpacket->data + j;
+ /*
+ * check if there is enough room in
+ * * the incoming buffer
+ */
+ if (length > (*list_read_count - bytes_read))
+ /*
+ * copy what ever is there in this
+ * packet and move on
+ */
+ bytes_copied = (*list_read_count - bytes_read);
+ else
+ /* copy the remaining */
+ bytes_copied = length;
+ memcpy(data, ptemp_buf, bytes_copied);
+ }
+ return bytes_copied;
+}
+
+static int packet_read_list(char *data, size_t * pread_length)
+{
+ struct list_head *ptemp_list;
+ int temp_count = 0;
+ int bytes_copied = 0;
+ int bytes_read = 0;
+ int remaining_bytes = 0;
+ char *pdest = data;
+
+ /* check if we have any packets */
+ if (0 == rbu_data.num_packets)
+ return -ENOMEM;
+
+ remaining_bytes = *pread_length;
+ bytes_read = rbu_data.packet_read_count;
+
+ ptemp_list = (&packet_data_head.list)->next;
+ while (!list_empty(ptemp_list)) {
+ bytes_copied = do_packet_read(pdest, ptemp_list,
+ remaining_bytes, bytes_read,
+ &temp_count);
+ remaining_bytes -= bytes_copied;
+ bytes_read += bytes_copied;
+ pdest += bytes_copied;
+ /*
+ * check if we reached end of buffer before reaching the
+ * last packet
+ */
+ if (remaining_bytes == 0)
+ break;
+
+ ptemp_list = ptemp_list->next;
+ }
+ /*finally set the bytes read */
+ *pread_length = bytes_read - rbu_data.packet_read_count;
+ rbu_data.packet_read_count = bytes_read;
+ return 0;
+}
+
+static void packet_empty_list(void)
+{
+ struct list_head *ptemp_list;
+ struct list_head *pnext_list;
+ struct packet_data *newpacket;
+
+ ptemp_list = (&packet_data_head.list)->next;
+ while (!list_empty(ptemp_list)) {
+ newpacket =
+ list_entry(ptemp_list, struct packet_data, list);
+ pnext_list = ptemp_list->next;
+ list_del(ptemp_list);
+ ptemp_list = pnext_list;
+ /*
+ * zero out the RBU packet memory before freeing
+ * to make sure there are no stale RBU packets left in memory
+ */
+ memset(newpacket->data, 0, rbu_data.packetsize);
+ free_pages((unsigned long)newpacket->data,
+ newpacket->ordernum);
+ kfree(newpacket);
+ }
+ rbu_data.packet_write_count = 0;
+ rbu_data.packet_read_count = 0;
+ rbu_data.num_packets = 0;
+ rbu_data.packetsize = 0;
+}
+
+/*
+ * img_update_free: Frees the buffer allocated for storing BIOS image
+ * Always called with lock held and returned with lock held
+ */
+static void img_update_free(void)
+{
+ if (!rbu_data.image_update_buffer)
+ return;
+ /*
+ * zero out this buffer before freeing it to get rid of any stale
+ * BIOS image copied in memory.
+ */
+ memset(rbu_data.image_update_buffer, 0,
+ rbu_data.image_update_buffer_size);
+ if (rbu_data.dma_alloc == 1)
+ dma_free_coherent(NULL, rbu_data.bios_image_size,
+ rbu_data.image_update_buffer,
+ dell_rbu_dmaaddr);
+ else
+ free_pages((unsigned long)rbu_data.image_update_buffer,
+ rbu_data.image_update_ordernum);
+
+ /*
+ * Re-initialize the rbu_data variables after a free
+ */
+ rbu_data.image_update_ordernum = -1;
+ rbu_data.image_update_buffer = NULL;
+ rbu_data.image_update_buffer_size = 0;
+ rbu_data.bios_image_size = 0;
+ rbu_data.dma_alloc = 0;
+}
+
+/*
+ * img_update_realloc: This function allocates the contiguous pages to
+ * accommodate the requested size of data. The memory address and size
+ * values are stored globally and on every call to this function the new
+ * size is checked to see if more data is required than the existing size.
+ * If true the previous memory is freed and new allocation is done to
+ * accommodate the new size. If the incoming size is less then than the
+ * already allocated size, then that memory is reused. This function is
+ * called with lock held and returns with lock held.
+ */
+static int img_update_realloc(unsigned long size)
+{
+ unsigned char *image_update_buffer = NULL;
+ unsigned long rc;
+ unsigned long img_buf_phys_addr;
+ int ordernum;
+ int dma_alloc = 0;
+
+ /*
+ * check if the buffer of sufficient size has been
+ * already allocated
+ */
+ if (rbu_data.image_update_buffer_size >= size) {
+ /*
+ * check for corruption
+ */
+ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+ printk(KERN_ERR "dell_rbu:%s: corruption "
+ "check failed\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ /*
+ * we have a valid pre-allocated buffer with
+ * sufficient size
+ */
+ return 0;
+ }
+
+ /*
+ * free any previously allocated buffer
+ */
+ img_update_free();
+
+ spin_unlock(&rbu_data.lock);
+
+ ordernum = get_order(size);
+ image_update_buffer =
+ (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
+
+ img_buf_phys_addr =
+ (unsigned long)virt_to_phys(image_update_buffer);
+
+ if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+ free_pages((unsigned long)image_update_buffer, ordernum);
+ ordernum = -1;
+ image_update_buffer = dma_alloc_coherent(NULL, size,
+ &dell_rbu_dmaaddr,
+ GFP_KERNEL);
+ dma_alloc = 1;
+ }
+
+ spin_lock(&rbu_data.lock);
+
+ if (image_update_buffer != NULL) {
+ rbu_data.image_update_buffer = image_update_buffer;
+ rbu_data.image_update_buffer_size = size;
+ rbu_data.bios_image_size =
+ rbu_data.image_update_buffer_size;
+ rbu_data.image_update_ordernum = ordernum;
+ rbu_data.dma_alloc = dma_alloc;
+ rc = 0;
+ } else {
+ pr_debug("Not enough memory for image update:"
+ "size = %ld\n", size);
+ rc = -ENOMEM;
+ }
+
+ return rc;
+}
+
+static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
+{
+ int retval;
+ size_t bytes_left;
+ size_t data_length;
+ char *ptempBuf = buffer;
+ unsigned long imagesize;
+
+ /* check to see if we have something to return */
+ if (rbu_data.num_packets == 0) {
+ pr_debug("read_packet_data: no packets written\n");
+ retval = -ENOMEM;
+ goto read_rbu_data_exit;
+ }
+
+ imagesize = rbu_data.num_packets * rbu_data.packetsize;
+
+ if (pos > imagesize) {
+ retval = 0;
+ printk(KERN_WARNING "dell_rbu:read_packet_data: "
+ "data underrun\n");
+ goto read_rbu_data_exit;
+ }
+
+ bytes_left = imagesize - pos;
+ data_length = min(bytes_left, count);
+
+ if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
+ goto read_rbu_data_exit;
+
+ if ((pos + count) > imagesize) {
+ rbu_data.packet_read_count = 0;
+ /* this was the last copy */
+ retval = bytes_left;
+ } else
+ retval = count;
+
+ read_rbu_data_exit:
+ return retval;
+}
+
+static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
+{
+ unsigned char *ptemp = NULL;
+ size_t bytes_left = 0;
+ size_t data_length = 0;
+ ssize_t ret_count = 0;
+
+ /* check to see if we have something to return */
+ if ((rbu_data.image_update_buffer == NULL) ||
+ (rbu_data.bios_image_size == 0)) {
+ pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
+ "bios_image_size %lu\n",
+ rbu_data.image_update_buffer,
+ rbu_data.bios_image_size);
+ ret_count = -ENOMEM;
+ goto read_rbu_data_exit;
+ }
+
+ if (pos > rbu_data.bios_image_size) {
+ ret_count = 0;
+ goto read_rbu_data_exit;
+ }
+
+ bytes_left = rbu_data.bios_image_size - pos;
+ data_length = min(bytes_left, count);
+
+ ptemp = rbu_data.image_update_buffer;
+ memcpy(buffer, (ptemp + pos), data_length);
+
+ if ((pos + count) > rbu_data.bios_image_size)
+ /* this was the last copy */
+ ret_count = bytes_left;
+ else
+ ret_count = count;
+ read_rbu_data_exit:
+ return ret_count;
+}
+
+static ssize_t
+read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
+{
+ ssize_t ret_count = 0;
+
+ spin_lock(&rbu_data.lock);
+
+ if (!strcmp(image_type, "mono"))
+ ret_count = read_rbu_mono_data(buffer, pos, count);
+ else if (!strcmp(image_type, "packet"))
+ ret_count = read_packet_data(buffer, pos, count);
+ else
+ pr_debug("read_rbu_data: invalid image type specified\n");
+
+ spin_unlock(&rbu_data.lock);
+ return ret_count;
+}
+
+static ssize_t
+read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
+ size_t count)
+{
+ int size = 0;
+ if (!pos)
+ size = sprintf(buffer, "%s\n", image_type);
+ return size;
+}
+
+static ssize_t
+write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
+ size_t count)
+{
+ int rc = count;
+ spin_lock(&rbu_data.lock);
+
+ if (strlen(buffer) < MAX_IMAGE_LENGTH)
+ sscanf(buffer, "%s", image_type);
+ else
+ printk(KERN_WARNING "dell_rbu: image_type is invalid"
+ "max chars = %d, \n incoming str--%s-- \n",
+ MAX_IMAGE_LENGTH, buffer);
+
+ /* we must free all previous allocations */
+ packet_empty_list();
+ img_update_free();
+
+ spin_unlock(&rbu_data.lock);
+ return rc;
+
+}
+
+static struct bin_attribute rbu_data_attr = {
+ .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+ .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+ .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+ .read = read_rbu_image_type,
+ .write = write_rbu_image_type,
+};
+
+static void callbackfn_rbu(const struct firmware *fw, void *context)
+{
+ int rc = 0;
+
+ if (!fw || !fw->size)
+ return;
+
+ spin_lock(&rbu_data.lock);
+ if (!strcmp(image_type, "mono")) {
+ if (!img_update_realloc(fw->size))
+ memcpy(rbu_data.image_update_buffer,
+ fw->data, fw->size);
+ } else if (!strcmp(image_type, "packet")) {
+ if (!rbu_data.packetsize)
+ rbu_data.packetsize = fw->size;
+ else if (rbu_data.packetsize != fw->size) {
+ packet_empty_list();
+ rbu_data.packetsize = fw->size;
+ }
+ packetize_data(fw->data, fw->size);
+ } else
+ pr_debug("invalid image type specified.\n");
+ spin_unlock(&rbu_data.lock);
+
+ rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "dell_rbu", &rbu_device->dev,
+ &context, callbackfn_rbu);
+ if (rc)
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait failed"
+ " %d\n", __FUNCTION__, rc);
+}
+
+static int __init dcdrbu_init(void)
+{
+ int rc = 0;
+ spin_lock_init(&rbu_data.lock);
+
+ init_packet_head();
+ rbu_device =
+ platform_device_register_simple("dell_rbu", -1, NULL, 0);
+ if (!rbu_device) {
+ printk(KERN_ERR
+ "dell_rbu:%s:platform_device_register_simple "
+ "failed\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+ sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+
+ rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "dell_rbu", &rbu_device->dev,
+ &context, callbackfn_rbu);
+ if (rc)
+ printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
+ " failed %d\n", __FUNCTION__, rc);
+
+ return rc;
+
+}
+
+static __exit void dcdrbu_exit(void)
+{
+ spin_lock(&rbu_data.lock);
+ packet_empty_list();
+ img_update_free();
+ spin_unlock(&rbu_data.lock);
+ platform_device_unregister(rbu_device);
+}
+
+module_exit(dcdrbu_exit);
+module_init(dcdrbu_init);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 140d5f851a5b..7e72e922b41c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -12,12 +12,20 @@ config HWMON
of a system. Most modern motherboards include such a device. It
can include temperature sensors, voltage sensors, fan speed
sensors and various additional features such as the ability to
- control the speed of the fans.
+ control the speed of the fans. If you want this support you
+ should say Y here and also to the specific driver(s) for your
+ sensors chip(s) below.
+
+ This support can also be built as a module. If so, the module
+ will be called hwmon.
+
+config HWMON_VID
+ tristate
+ default n
config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -30,7 +38,7 @@ config SENSORS_ADM1021
config SENSORS_ADM1025
tristate "Analog Devices ADM1025 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM1025
and Philips NE1619 sensor chips.
@@ -41,7 +49,7 @@ config SENSORS_ADM1025
config SENSORS_ADM1026
tristate "Analog Devices ADM1026 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM1026
sensor chip.
@@ -52,7 +60,6 @@ config SENSORS_ADM1026
config SENSORS_ADM1031
tristate "Analog Devices ADM1031 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1031
and ADM1030 sensor chips.
@@ -63,7 +70,7 @@ config SENSORS_ADM1031
config SENSORS_ADM9240
tristate "Analog Devices ADM9240 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM9240,
Dallas DS1780, National Semiconductor LM81 sensor chips.
@@ -74,7 +81,7 @@ config SENSORS_ADM9240
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for the ASB100 Bach sensor
chip found on some Asus mainboards.
@@ -85,7 +92,7 @@ config SENSORS_ASB100
config SENSORS_ATXP1
tristate "Attansic ATXP1 VID controller"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for the Attansic ATXP1 VID
controller.
@@ -99,7 +106,6 @@ config SENSORS_ATXP1
config SENSORS_DS1621
tristate "Dallas Semiconductor DS1621 and DS1625"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1621 and DS1625 sensor chips.
@@ -110,7 +116,6 @@ config SENSORS_DS1621
config SENSORS_FSCHER
tristate "FSC Hermes"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Fujitsu Siemens
Computers Hermes sensor chips.
@@ -121,7 +126,6 @@ config SENSORS_FSCHER
config SENSORS_FSCPOS
tristate "FSC Poseidon"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Fujitsu Siemens
Computers Poseidon sensor chips.
@@ -132,7 +136,6 @@ config SENSORS_FSCPOS
config SENSORS_GL518SM
tristate "Genesys Logic GL518SM"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for Genesys Logic GL518SM
sensor chips.
@@ -143,7 +146,7 @@ config SENSORS_GL518SM
config SENSORS_GL520SM
tristate "Genesys Logic GL520SM"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Genesys Logic GL520SM
sensor chips.
@@ -154,7 +157,8 @@ config SENSORS_GL520SM
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for ITE IT87xx sensor chips
and clones: SiS960.
@@ -165,7 +169,6 @@ config SENSORS_IT87
config SENSORS_LM63
tristate "National Semiconductor LM63"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the National Semiconductor
LM63 remote diode digital temperature sensor with integrated fan
@@ -178,7 +181,6 @@ config SENSORS_LM63
config SENSORS_LM75
tristate "National Semiconductor LM75 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM75
sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
@@ -194,7 +196,6 @@ config SENSORS_LM75
config SENSORS_LM77
tristate "National Semiconductor LM77"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM77
sensor chips.
@@ -205,7 +206,8 @@ config SENSORS_LM77
config SENSORS_LM78
tristate "National Semiconductor LM78 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM78,
LM78-J and LM79.
@@ -216,7 +218,6 @@ config SENSORS_LM78
config SENSORS_LM80
tristate "National Semiconductor LM80"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM80 sensor chips.
@@ -227,7 +228,6 @@ config SENSORS_LM80
config SENSORS_LM83
tristate "National Semiconductor LM83"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM83 sensor chips.
@@ -238,7 +238,7 @@ config SENSORS_LM83
config SENSORS_LM85
tristate "National Semiconductor LM85 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM85
sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
@@ -249,7 +249,7 @@ config SENSORS_LM85
config SENSORS_LM87
tristate "National Semiconductor LM87"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM87
sensor chips.
@@ -260,7 +260,6 @@ config SENSORS_LM87
config SENSORS_LM90
tristate "National Semiconductor LM90 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM90,
LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
@@ -275,7 +274,6 @@ config SENSORS_LM90
config SENSORS_LM92
tristate "National Semiconductor LM92 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM92
and Maxim MAX6635 sensor chips.
@@ -286,7 +284,6 @@ config SENSORS_LM92
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for MAX1619 sensor chip.
@@ -296,8 +293,8 @@ config SENSORS_MAX1619
config SENSORS_PC87360
tristate "National Semiconductor PC87360 family"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get access to the hardware monitoring
functions of the National Semiconductor PC8736x Super-I/O chips.
@@ -311,7 +308,6 @@ config SENSORS_PC87360
config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595"
depends on HWMON && I2C && PCI && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated sensors in
@@ -323,7 +319,6 @@ config SENSORS_SIS5595
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated fan
@@ -336,7 +331,6 @@ config SENSORS_SMSC47M1
config SENSORS_SMSC47B397
tristate "SMSC LPC47B397-NC"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the SMSC LPC47B397-NC
@@ -348,7 +342,6 @@ config SENSORS_SMSC47B397
config SENSORS_VIA686A
tristate "VIA686A"
depends on HWMON && I2C && PCI
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated sensors in
@@ -360,7 +353,8 @@ config SENSORS_VIA686A
config SENSORS_W83781D
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
depends on HWMON && I2C
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for the Winbond W8378x series
of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
@@ -369,10 +363,18 @@ config SENSORS_W83781D
This driver can also be built as a module. If so, the module
will be called w83781d.
+config SENSORS_W83792D
+ tristate "Winbond W83792D"
+ depends on HWMON && I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Winbond W83792D chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83792d.
+
config SENSORS_W83L785TS
tristate "Winbond W83L785TS-S"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the Winbond W83L785TS-S
sensor chip, which is used on the Asus A7N8X, among other
@@ -384,8 +386,8 @@ config SENSORS_W83L785TS
config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -396,7 +398,6 @@ config SENSORS_W83627HF
config SENSORS_W83627EHF
tristate "Winbond W83627EHF"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get preliminary support for the hardware
@@ -404,9 +405,29 @@ config SENSORS_W83627EHF
Only fan and temperature inputs are supported at the moment, while
the chip does much more than that.
+ This driver also supports the W83627EHG, which is the lead-free
+ version of the W83627EHF.
+
This driver can also be built as a module. If so, the module
will be called w83627ehf.
+config SENSORS_HDAPS
+ tristate "IBM Hard Drive Active Protection System (hdaps)"
+ depends on HWMON && INPUT && X86
+ default n
+ help
+ This driver provides support for the IBM Hard Drive Active Protection
+ System (hdaps), which provides an accelerometer and other misc. data.
+ Supported laptops include the IBM ThinkPad T41, T42, T43, and R51.
+ The accelerometer data is readable via sysfs.
+
+ This driver also provides an input class device, allowing the
+ laptop to act as a pinball machine-esque mouse. This is off by
+ default but enabled via sysfs or the module parameter "mousedev".
+
+ Say Y here if you have an applicable laptop and want to experience
+ the awesome power of hdaps.
+
config HWMON_DEBUG_CHIP
bool "Hardware Monitoring Chip debugging messages"
depends on HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 2781403a0236..f7d6a2f61ee7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -2,9 +2,13 @@
# Makefile for sensor chip drivers.
#
+obj-$(CONFIG_HWMON) += hwmon.o
+obj-$(CONFIG_HWMON_VID) += hwmon-vid.o
+
# asb100, then w83781d go first, as they can override other drivers' addresses.
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
+obj-$(CONFIG_SENSORS_W83792D) += w83792d.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
@@ -18,6 +22,7 @@ obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index d2c774c32f45..e928cdb041cb 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -24,7 +24,8 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
@@ -32,10 +33,9 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
/* adm1021 constants specified below */
@@ -89,6 +89,7 @@ clearing it. Weird, ey? --Phil */
/* Each client has this additional data */
struct adm1021_data {
struct i2c_client client;
+ struct class_device *class_dev;
enum chips type;
struct semaphore update_lock;
@@ -185,7 +186,7 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1021_detect);
+ return i2c_probe(adapter, &addr_data, adm1021_detect);
}
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -196,15 +197,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
const char *type_name = "";
- /* Make sure we aren't probing the ISA bus!! This is just a safety check
- at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
- if (i2c_is_isa_adapter(adapter)) {
- dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
- return 0;
- }
-#endif
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto error0;
@@ -295,6 +287,12 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
adm1021_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error2;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
@@ -305,6 +303,8 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error2:
+ i2c_detach_client(new_client);
error1:
kfree(data);
error0:
@@ -322,14 +322,15 @@ static void adm1021_init_client(struct i2c_client *client)
static int adm1021_detach_client(struct i2c_client *client)
{
+ struct adm1021_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index e452d0daf906..526b7ff179eb 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -50,8 +50,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -60,13 +61,12 @@
*/
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_2(adm1025, ne1619);
+I2C_CLIENT_INSMOD_2(adm1025, ne1619);
/*
* The ADM1025 registers
@@ -132,6 +132,7 @@ static struct i2c_driver adm1025_driver = {
struct adm1025_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -312,7 +313,7 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1025_detect);
+ return i2c_probe(adapter, &addr_data, adm1025_detect);
}
/*
@@ -416,6 +417,12 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
adm1025_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -452,6 +459,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -464,7 +473,7 @@ static void adm1025_init_client(struct i2c_client *client)
struct adm1025_data *data = i2c_get_clientdata(client);
int i;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/*
* Set high limits
@@ -502,15 +511,15 @@ static void adm1025_init_client(struct i2c_client *client)
static int adm1025_detach_client(struct i2c_client *client)
{
+ struct adm1025_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index c8a7f47911f9..625158110fd4 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -28,16 +28,16 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(adm1026);
+I2C_CLIENT_INSMOD_1(adm1026);
static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
@@ -259,6 +259,7 @@ struct pwm_data {
struct adm1026_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -319,13 +320,15 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
if (!(adapter->class & I2C_CLASS_HWMON)) {
return 0;
}
- return i2c_detect(adapter, &addr_data, adm1026_detect);
+ return i2c_probe(adapter, &addr_data, adm1026_detect);
}
int adm1026_detach_client(struct i2c_client *client)
{
+ struct adm1026_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -1549,12 +1552,18 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
goto exitfree;
/* Set the VRM version */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/* Initialize the ADM1026 chip */
adm1026_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exitdetach;
+ }
+
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
@@ -1690,6 +1699,8 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
return 0;
/* Error out and cleanup code */
+exitdetach:
+ i2c_detach_client(new_client);
exitfree:
kfree(data);
exit:
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 936250957270..58338ed7c8a1 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -26,7 +26,8 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Following macros takes channel parameter starting from 0 to 2 */
#define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr))
@@ -59,16 +60,16 @@
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(adm1030, adm1031);
+I2C_CLIENT_INSMOD_2(adm1030, adm1031);
typedef u8 auto_chan_table_t[8][2];
/* Each client has this additional data */
struct adm1031_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
int chip_type;
char valid; /* !=0 if following fields are valid */
@@ -725,10 +726,10 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1031_detect);
+ return i2c_probe(adapter, &addr_data, adm1031_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -788,6 +789,12 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
adm1031_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -833,6 +840,8 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -841,11 +850,14 @@ exit:
static int adm1031_detach_client(struct i2c_client *client)
{
+ struct adm1031_data *data = i2c_get_clientdata(client);
int ret;
+
+ hwmon_device_unregister(data->class_dev);
if ((ret = i2c_detach_client(client)) != 0) {
return ret;
}
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index ce2a6eb93f6e..bc7faef162f7 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -45,17 +45,16 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
/* Insmod parameters */
-SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
/* ADM9240 registers */
#define ADM9240_REG_MAN_ID 0x3e
@@ -150,6 +149,7 @@ static struct i2c_driver adm9240_driver = {
struct adm9240_data {
enum chips type;
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid;
unsigned long last_updated_measure;
@@ -582,6 +582,12 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
adm9240_init_client(new_client);
/* populate sysfs filesystem */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -615,6 +621,9 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
return 0;
+
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -625,20 +634,20 @@ static int adm9240_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm9240_detect);
+ return i2c_probe(adapter, &addr_data, adm9240_detect);
}
static int adm9240_detach_client(struct i2c_client *client)
{
+ struct adm9240_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -648,7 +657,7 @@ static void adm9240_init_client(struct i2c_client *client)
u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
- data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+ data->vrm = vid_which_vrm(); /* need this to report vid as mV */
dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
data->vrm % 10);
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 70d996d6fe0a..8e34855a6274 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -39,8 +39,9 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include "lm75.h"
@@ -54,11 +55,8 @@
/* I2C addresses to scan */
static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
-/* ISA addresses to scan (none) */
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
/* Insmod parameters */
-SENSORS_INSMOD_1(asb100);
+I2C_CLIENT_INSMOD_1(asb100);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
@@ -183,6 +181,7 @@ static u8 DIV_TO_REG(long val)
dynamically allocated, at the same time the client itself is allocated. */
struct asb100_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -621,7 +620,7 @@ static int asb100_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, asb100_detect);
+ return i2c_probe(adapter, &addr_data, asb100_detect);
}
static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
@@ -714,14 +713,6 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *new_client;
struct asb100_data *data;
- /* asb100 is SMBus only */
- if (i2c_is_isa_adapter(adapter)) {
- pr_debug("asb100.o: detect failed, "
- "cannot attach to legacy adapter!\n");
- err = -ENODEV;
- goto ERROR0;
- }
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, "
"smbus byte data not supported!\n");
@@ -821,6 +812,12 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file_in(new_client, 0);
device_create_file_in(new_client, 1);
device_create_file_in(new_client, 2);
@@ -847,6 +844,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR3:
+ i2c_detach_client(data->lm75[1]);
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[1]);
+ kfree(data->lm75[0]);
ERROR2:
i2c_detach_client(new_client);
ERROR1:
@@ -857,21 +859,23 @@ ERROR0:
static int asb100_detach_client(struct i2c_client *client)
{
+ struct asb100_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "client deregistration failed; "
- "client not detached.\n");
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_get_clientdata(client)==NULL) {
- /* subclients */
+ /* main client */
+ if (data)
+ kfree(data);
+
+ /* subclient */
+ else
kfree(client);
- } else {
- /* main client */
- kfree(i2c_get_clientdata(client));
- }
return 0;
}
@@ -969,7 +973,7 @@ static void asb100_init_client(struct i2c_client *client)
vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
vid = vid_from_reg(vid, data->vrm);
/* Start monitoring */
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index fca3fc1cef72..deb4d34c9539 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -23,8 +23,9 @@
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -40,9 +41,8 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
#define ATXP1_GPIO1MASK 0x0f
static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-SENSORS_INSMOD_1(atxp1);
+I2C_CLIENT_INSMOD_1(atxp1);
static int atxp1_attach_adapter(struct i2c_adapter * adapter);
static int atxp1_detach_client(struct i2c_client * client);
@@ -59,6 +59,7 @@ static struct i2c_driver atxp1_driver = {
struct atxp1_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
unsigned long last_updated;
u8 valid;
@@ -252,7 +253,7 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, &atxp1_detect);
+ return i2c_probe(adapter, &addr_data, &atxp1_detect);
};
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -295,7 +296,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Get VRM */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if ((data->vrm != 90) && (data->vrm != 91)) {
dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
@@ -317,6 +318,12 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_free;
}
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_gpio1);
device_create_file(&new_client->dev, &dev_attr_gpio2);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
@@ -326,6 +333,8 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -334,14 +343,17 @@ exit:
static int atxp1_detach_client(struct i2c_client * client)
{
+ struct atxp1_data * data = i2c_get_clientdata(client);
int err;
+ hwmon_device_unregister(data->class_dev);
+
err = i2c_detach_client(client);
if (err)
dev_err(&client->dev, "Failed to detach client.\n");
else
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return err;
};
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 5360d58804f6..b0199e063d0e 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -26,16 +26,16 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include "lm75.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(ds1621);
+I2C_CLIENT_INSMOD_1(ds1621);
static int polarity = -1;
module_param(polarity, int, 0);
MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
@@ -71,6 +71,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
/* Each client has this additional data */
struct ds1621_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -179,10 +180,10 @@ static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, ds1621_detect);
+ return i2c_probe(adapter, &addr_data, ds1621_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int ds1621_detect(struct i2c_adapter *adapter, int address,
int kind)
{
@@ -250,6 +251,12 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
ds1621_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -259,6 +266,8 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
+ exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -267,15 +276,15 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
static int ds1621_detach_client(struct i2c_client *client)
{
+ struct ds1621_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index da411741c2c5..eef6061d786b 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -31,20 +31,20 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
*/
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(fscher);
+I2C_CLIENT_INSMOD_1(fscher);
/*
* The FSCHER registers
@@ -132,6 +132,7 @@ static struct i2c_driver fscher_driver = {
struct fscher_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -287,7 +288,7 @@ static int fscher_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, fscher_detect);
+ return i2c_probe(adapter, &addr_data, fscher_detect);
}
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -341,6 +342,12 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
fscher_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file_revision(new_client);
device_create_file_alarms(new_client);
device_create_file_control(new_client);
@@ -360,6 +367,8 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -368,15 +377,15 @@ exit:
static int fscher_detach_client(struct i2c_client *client)
{
+ struct fscher_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 301ae98bd0ad..5fc77a5fed07 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -34,19 +34,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
*/
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(fscpos);
+I2C_CLIENT_INSMOD_1(fscpos);
/*
* The FSCPOS registers
@@ -113,6 +113,7 @@ static struct i2c_driver fscpos_driver = {
*/
struct fscpos_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* 0 until following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -434,7 +435,7 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, fscpos_detect);
+ return i2c_probe(adapter, &addr_data, fscpos_detect);
}
int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -496,6 +497,12 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_event);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -526,6 +533,8 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -534,14 +543,14 @@ exit:
static int fscpos_detach_client(struct i2c_client *client)
{
+ struct fscpos_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, client"
- " not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 6bedf729dcf5..256b9323c84b 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -41,14 +41,14 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
+I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
/* Many GL518 constants specified below */
@@ -117,6 +117,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
/* Each client has this additional data */
struct gl518_data {
struct i2c_client client;
+ struct class_device *class_dev;
enum chips type;
struct semaphore update_lock;
@@ -346,7 +347,7 @@ static int gl518_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, gl518_detect);
+ return i2c_probe(adapter, &addr_data, gl518_detect);
}
static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -419,6 +420,12 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
gl518_init_client((struct i2c_client *) new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -450,6 +457,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -477,16 +486,15 @@ static void gl518_init_client(struct i2c_client *client)
static int gl518_detach_client(struct i2c_client *client)
{
+ struct gl518_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
- return err;
- }
+ hwmon_device_unregister(data->class_dev);
- kfree(i2c_get_clientdata(client));
+ if ((err = i2c_detach_client(client)))
+ return err;
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 80ae8d30c2af..12fd757066fc 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -26,8 +26,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Type of the extra sensor */
static unsigned short extra_sensor_type;
@@ -36,10 +37,9 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(gl520sm);
+I2C_CLIENT_INSMOD_1(gl520sm);
/* Many GL520 constants specified below
One of the inputs can be configured as either temp or voltage.
@@ -120,6 +120,7 @@ static struct i2c_driver gl520_driver = {
/* Client data */
struct gl520_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until the following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -518,7 +519,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, gl520_detect);
+ return i2c_probe(adapter, &addr_data, gl520_detect);
}
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -571,6 +572,12 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
gl520_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file_vid(new_client, 0);
device_create_file_in(new_client, 0);
@@ -592,6 +599,8 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -608,7 +617,7 @@ static void gl520_init_client(struct i2c_client *client)
conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
data->alarm_mask = 0xff;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if (extra_sensor_type == 1)
conf &= ~0x10;
@@ -639,15 +648,15 @@ static void gl520_init_client(struct i2c_client *client)
static int gl520_detach_client(struct i2c_client *client)
{
+ struct gl520_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
new file mode 100644
index 000000000000..eaebfc14c933
--- /dev/null
+++ b/drivers/hwmon/hdaps.c
@@ -0,0 +1,739 @@
+/*
+ * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
+ *
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
+ * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis
+ * accelerometer and other data, such as the device's temperature.
+ *
+ * Based on the document by Mark A. Smith available at
+ * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
+ * and error.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
+#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */
+
+#define STATE_FRESH 0x50 /* accelerometer data is fresh */
+
+#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */
+#define REFRESH_SYNC 0x01 /* do synchronous refresh */
+
+#define HDAPS_PORT_STATE 0x1611 /* device state */
+#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
+#define HDAPS_PORT_XPOS 0x1614 /* x-axis position */
+#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */
+#define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */
+#define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */
+#define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */
+#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
+#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
+
+#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */
+
+#define KEYBD_MASK 0x20 /* set if keyboard activity */
+#define MOUSE_MASK 0x40 /* set if mouse activity */
+#define KEYBD_ISSET(n) (!! (n & KEYBD_MASK)) /* keyboard used? */
+#define MOUSE_ISSET(n) (!! (n & MOUSE_MASK)) /* mouse used? */
+
+#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
+#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
+
+static struct platform_device *pdev;
+static struct input_dev hdaps_idev;
+static struct timer_list hdaps_timer;
+static unsigned int hdaps_mousedev_threshold = 4;
+static unsigned long hdaps_poll_ms = 50;
+static unsigned int hdaps_mousedev;
+static unsigned int hdaps_invert;
+static u8 km_activity;
+static int rest_x;
+static int rest_y;
+
+static DECLARE_MUTEX(hdaps_sem);
+
+/*
+ * __get_latch - Get the value from a given port. Callers must hold hdaps_sem.
+ */
+static inline u8 __get_latch(u16 port)
+{
+ return inb(port) & HDAPS_READ_MASK;
+}
+
+/*
+ * __check_latch - Check a port latch for a given value. Callers must hold
+ * hdaps_sem. Returns zero if the port contains the given value.
+ */
+static inline unsigned int __check_latch(u16 port, u8 val)
+{
+ if (__get_latch(port) == val)
+ return 0;
+ return -EINVAL;
+}
+
+/*
+ * __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_sem.
+ */
+static unsigned int __wait_latch(u16 port, u8 val)
+{
+ unsigned int i;
+
+ for (i = 0; i < 20; i++) {
+ if (!__check_latch(port, val))
+ return 0;
+ udelay(5);
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * __device_refresh - Request a refresh from the accelerometer.
+ *
+ * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
+ * Returns zero if successful and nonzero on error.
+ *
+ * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
+ * not up-to-date. Always returns zero.
+ *
+ * Callers must hold hdaps_sem.
+ */
+static int __device_refresh(unsigned int sync)
+{
+ u8 state;
+
+ udelay(100);
+
+ state = inb(0x1604);
+ if (state == STATE_FRESH)
+ return 0;
+
+ outb(0x11, 0x1610);
+ outb(0x01, 0x161f);
+ if (sync == REFRESH_ASYNC)
+ return 0;
+
+ return __wait_latch(0x1604, STATE_FRESH);
+}
+
+/*
+ * __device_complete - Indicate to the accelerometer that we are done reading
+ * data, and then initiate an async refresh. Callers must hold hdaps_sem.
+ */
+static inline void __device_complete(void)
+{
+ inb(0x161f);
+ inb(0x1604);
+ __device_refresh(REFRESH_ASYNC);
+}
+
+static int __hdaps_readb_one(unsigned int port, u8 *val)
+{
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ if (__device_refresh(REFRESH_SYNC))
+ return -EIO;
+
+ *val = inb(port);
+ __device_complete();
+
+ return 0;
+}
+
+/*
+ * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
+ * the given pointer. Returns zero on success or a negative error on failure.
+ * Can sleep.
+ */
+static int hdaps_readb_one(unsigned int port, u8 *val)
+{
+ int ret;
+
+ down(&hdaps_sem);
+ ret = __hdaps_readb_one(port, val);
+ up(&hdaps_sem);
+
+ return ret;
+}
+
+static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
+ int *x, int *y)
+{
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ if (__device_refresh(REFRESH_SYNC))
+ return -EIO;
+
+ *y = inw(port2);
+ *x = inw(port1);
+ km_activity = inb(HDAPS_PORT_KMACT);
+ __device_complete();
+
+ /* if hdaps_invert is set, negate the two values */
+ if (hdaps_invert) {
+ *x = -*x;
+ *y = -*y;
+ }
+
+ return 0;
+}
+
+/*
+ * hdaps_read_pair - reads the values from a pair of ports, placing the values
+ * in the given pointers. Returns zero on success. Can sleep.
+ */
+static int hdaps_read_pair(unsigned int port1, unsigned int port2,
+ int *val1, int *val2)
+{
+ int ret;
+
+ down(&hdaps_sem);
+ ret = __hdaps_read_pair(port1, port2, val1, val2);
+ up(&hdaps_sem);
+
+ return ret;
+}
+
+/* initialize the accelerometer */
+static int hdaps_device_init(void)
+{
+ unsigned int total_msecs = INIT_TIMEOUT_MSECS;
+ int ret = -ENXIO;
+
+ down(&hdaps_sem);
+
+ outb(0x13, 0x1610);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+
+ /*
+ * The 0x03 value appears to only work on some thinkpads, such as the
+ * T42p. Others return 0x01.
+ *
+ * The 0x02 value occurs when the chip has been previously initialized.
+ */
+ if (__check_latch(0x1611, 0x03) &&
+ __check_latch(0x1611, 0x02) &&
+ __check_latch(0x1611, 0x01))
+ goto out;
+
+ printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
+ __get_latch(0x1611));
+
+ outb(0x17, 0x1610);
+ outb(0x81, 0x1611);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ if (__wait_latch(0x1611, 0x00))
+ goto out;
+ if (__wait_latch(0x1612, 0x60))
+ goto out;
+ if (__wait_latch(0x1613, 0x00))
+ goto out;
+ outb(0x14, 0x1610);
+ outb(0x01, 0x1611);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ outb(0x10, 0x1610);
+ outb(0xc8, 0x1611);
+ outb(0x00, 0x1612);
+ outb(0x02, 0x1613);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ if (__device_refresh(REFRESH_SYNC))
+ goto out;
+ if (__wait_latch(0x1611, 0x00))
+ goto out;
+
+ /* we have done our dance, now let's wait for the applause */
+ while (total_msecs > 0) {
+ u8 ignored;
+
+ /* a read of the device helps push it into action */
+ __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+ if (!__wait_latch(0x1611, 0x02)) {
+ ret = 0;
+ break;
+ }
+
+ msleep(INIT_WAIT_MSECS);
+ total_msecs -= INIT_WAIT_MSECS;
+ }
+
+out:
+ up(&hdaps_sem);
+ return ret;
+}
+
+
+/* Input class stuff */
+
+/*
+ * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+ int x, y;
+
+ if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+ return;
+
+ rest_x = x;
+ rest_y = y;
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+ int x, y;
+
+ /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
+ if (down_trylock(&hdaps_sem)) {
+ mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
+ return;
+ }
+
+ if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+ goto out;
+
+ x -= rest_x;
+ y -= rest_y;
+ if (abs(x) > hdaps_mousedev_threshold)
+ input_report_rel(&hdaps_idev, REL_X, x);
+ if (abs(y) > hdaps_mousedev_threshold)
+ input_report_rel(&hdaps_idev, REL_Y, y);
+ input_sync(&hdaps_idev);
+
+ mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
+
+out:
+ up(&hdaps_sem);
+}
+
+/*
+ * hdaps_mousedev_enable - enable the input class device. Can sleep.
+ */
+static void hdaps_mousedev_enable(void)
+{
+ down(&hdaps_sem);
+
+ /* calibrate the device before enabling */
+ hdaps_calibrate();
+
+ /* initialize the input class */
+ init_input_dev(&hdaps_idev);
+ hdaps_idev.dev = &pdev->dev;
+ hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
+ input_register_device(&hdaps_idev);
+
+ /* start up our timer */
+ init_timer(&hdaps_timer);
+ hdaps_timer.function = hdaps_mousedev_poll;
+ hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
+ add_timer(&hdaps_timer);
+
+ hdaps_mousedev = 1;
+
+ up(&hdaps_sem);
+
+ printk(KERN_INFO "hdaps: input device enabled.\n");
+}
+
+/*
+ * hdaps_mousedev_disable - disable the input class device. Caller must hold
+ * hdaps_sem.
+ */
+static void hdaps_mousedev_disable(void)
+{
+ down(&hdaps_sem);
+ if (hdaps_mousedev) {
+ hdaps_mousedev = 0;
+ del_timer_sync(&hdaps_timer);
+ input_unregister_device(&hdaps_idev);
+ }
+ up(&hdaps_sem);
+}
+
+
+/* Device model stuff */
+
+static int hdaps_probe(struct device *dev)
+{
+ int ret;
+
+ ret = hdaps_device_init();
+ if (ret)
+ return ret;
+
+ printk(KERN_INFO "hdaps: device successfully initialized.\n");
+ return 0;
+}
+
+static int hdaps_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_ENABLE)
+ return hdaps_device_init();
+ return 0;
+}
+
+static struct device_driver hdaps_driver = {
+ .name = "hdaps",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .probe = hdaps_probe,
+ .resume = hdaps_resume
+};
+
+
+/* Sysfs Files */
+
+static ssize_t hdaps_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret, x, y;
+
+ ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_variance_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret, x, y;
+
+ ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_temp1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 temp;
+ int ret;
+
+ ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_temp2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 temp;
+ int ret;
+
+ ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_keyboard_activity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
+}
+
+static ssize_t hdaps_mouse_activity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
+}
+
+static ssize_t hdaps_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t hdaps_calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ down(&hdaps_sem);
+ hdaps_calibrate();
+ up(&hdaps_sem);
+
+ return count;
+}
+
+static ssize_t hdaps_invert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", hdaps_invert);
+}
+
+static ssize_t hdaps_invert_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int invert;
+
+ if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0))
+ return -EINVAL;
+
+ hdaps_invert = invert;
+ hdaps_calibrate();
+
+ return count;
+}
+
+static ssize_t hdaps_mousedev_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", hdaps_mousedev);
+}
+
+static ssize_t hdaps_mousedev_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int enable;
+
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
+ if (enable == 1)
+ hdaps_mousedev_enable();
+ else if (enable == 0)
+ hdaps_mousedev_disable();
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t hdaps_poll_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", hdaps_poll_ms);
+}
+
+static ssize_t hdaps_poll_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int poll;
+
+ if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
+ return -EINVAL;
+ hdaps_poll_ms = poll;
+
+ return count;
+}
+
+static ssize_t hdaps_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
+}
+
+static ssize_t hdaps_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int threshold;
+
+ if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
+ return -EINVAL;
+ hdaps_mousedev_threshold = threshold;
+
+ return count;
+}
+
+static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
+static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
+static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
+static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
+static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
+static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
+static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
+static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
+static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
+static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
+static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
+ hdaps_threshold_store);
+
+static struct attribute *hdaps_attributes[] = {
+ &dev_attr_position.attr,
+ &dev_attr_variance.attr,
+ &dev_attr_temp1.attr,
+ &dev_attr_temp2.attr,
+ &dev_attr_keyboard_activity.attr,
+ &dev_attr_mouse_activity.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_mousedev.attr,
+ &dev_attr_mousedev_threshold.attr,
+ &dev_attr_mousedev_poll_ms.attr,
+ &dev_attr_invert.attr,
+ NULL,
+};
+
+static struct attribute_group hdaps_attribute_group = {
+ .attrs = hdaps_attributes,
+};
+
+
+/* Module stuff */
+
+/*
+ * XXX: We should be able to return nonzero and halt the detection process.
+ * But there is a bug in dmi_check_system() where a nonzero return from the
+ * first match will result in a return of failure from dmi_check_system().
+ * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make
+ * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
+ */
+static int hdaps_dmi_match(struct dmi_system_id *id)
+{
+ printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
+ return 0;
+}
+
+static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+{
+ hdaps_invert = 1;
+ printk(KERN_INFO "hdaps: inverting axis readings.\n");
+ return 0;
+}
+
+#define HDAPS_DMI_MATCH_NORMAL(model) { \
+ .ident = "IBM " model, \
+ .callback = hdaps_dmi_match, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_PRODUCT_VERSION, model) \
+ } \
+}
+
+#define HDAPS_DMI_MATCH_INVERT(model) { \
+ .ident = "IBM " model, \
+ .callback = hdaps_dmi_match_invert, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ 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_INVERT("ThinkPad R50p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
+ HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
+ HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+ { .ident = NULL }
+ };
+
+ if (!dmi_check_system(hdaps_whitelist)) {
+ printk(KERN_WARNING "hdaps: supported laptop not found!\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
+ ret = -ENXIO;
+ goto out;
+ }
+
+ ret = driver_register(&hdaps_driver);
+ if (ret)
+ goto out_region;
+
+ pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ ret = PTR_ERR(pdev);
+ goto out_driver;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
+ if (ret)
+ goto out_device;
+
+ if (hdaps_mousedev)
+ hdaps_mousedev_enable();
+
+ printk(KERN_INFO "hdaps: driver successfully loaded.\n");
+ return 0;
+
+out_device:
+ platform_device_unregister(pdev);
+out_driver:
+ driver_unregister(&hdaps_driver);
+out_region:
+ release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+out:
+ printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
+ return ret;
+}
+
+static void __exit hdaps_exit(void)
+{
+ hdaps_mousedev_disable();
+
+ sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+ platform_device_unregister(pdev);
+ driver_unregister(&hdaps_driver);
+ release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+
+ printk(KERN_INFO "hdaps: driver unloaded.\n");
+}
+
+module_init(hdaps_init);
+module_exit(hdaps_exit);
+
+module_param_named(mousedev, hdaps_mousedev, bool, 0);
+MODULE_PARM_DESC(mousedev, "enable the input class device");
+
+module_param_named(invert, hdaps_invert, bool, 0);
+MODULE_PARM_DESC(invert, "invert data along each axis");
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
new file mode 100644
index 000000000000..312769ad4dab
--- /dev/null
+++ b/drivers/hwmon/hwmon-vid.c
@@ -0,0 +1,189 @@
+/*
+ hwmon-vid.c - VID/VRM/VRD voltage conversions
+
+ Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+
+ Partly imported from i2c-vid.h of the lm_sensors project
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon-vid.h>
+
+/*
+ Common code for decoding VID pins.
+
+ References:
+
+ For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
+ available at http://developer.intel.com/.
+
+ For VRD 10.0 and up, "VRD x.y Design Guide",
+ available at http://developer.intel.com/.
+
+ AMD Opteron processors don't follow the Intel specifications.
+ I'm going to "make up" 2.4 as the spec number for the Opterons.
+ No good reason just a mnemonic for the 24x Opteron processor
+ series.
+
+ Opteron VID encoding is:
+ 00000 = 1.550 V
+ 00001 = 1.525 V
+ . . . .
+ 11110 = 0.800 V
+ 11111 = 0.000 V (off)
+*/
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+ val is the 4-, 5- or 6-bit VID code.
+ Returned value is in mV to avoid floating point in the kernel. */
+int vid_from_reg(int val, int vrm)
+{
+ int vid;
+
+ switch(vrm) {
+
+ case 0:
+ return 0;
+
+ case 100: /* VRD 10.0 */
+ if((val & 0x1f) == 0x1f)
+ return 0;
+ if((val & 0x1f) <= 0x09 || val == 0x0a)
+ vid = 10875 - (val & 0x1f) * 250;
+ else
+ vid = 18625 - (val & 0x1f) * 250;
+ if(val & 0x20)
+ vid -= 125;
+ vid /= 10; /* only return 3 dec. places for now */
+ return vid;
+
+ case 24: /* Opteron processor */
+ return(val == 0x1f ? 0 : 1550 - val * 25);
+
+ case 91: /* VRM 9.1 */
+ case 90: /* VRM 9.0 */
+ return(val == 0x1f ? 0 :
+ 1850 - val * 25);
+
+ case 85: /* VRM 8.5 */
+ return((val & 0x10 ? 25 : 0) +
+ ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+ ((val & 0x0f) * 50));
+
+ case 84: /* VRM 8.4 */
+ val &= 0x0f;
+ /* fall through */
+ default: /* VRM 8.2 */
+ return(val == 0x1f ? 0 :
+ val & 0x10 ? 5100 - (val) * 100 :
+ 2050 - (val) * 50);
+ }
+}
+
+
+/*
+ After this point is the code to automatically determine which
+ VRM/VRD specification should be used depending on the CPU.
+*/
+
+struct vrm_model {
+ u8 vendor;
+ u8 eff_family;
+ u8 eff_model;
+ int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+ {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
+ {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
+ {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
+ {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */
+ {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
+ {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
+ {X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */
+ {X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */
+ {X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */
+ {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
+ {X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */
+ {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
+ {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
+};
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+ int i = 0;
+
+ while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+ if (vrm_models[i].vendor==vendor)
+ if ((vrm_models[i].eff_family==eff_family)
+ && ((vrm_models[i].eff_model==eff_model) ||
+ (vrm_models[i].eff_model==ANY)))
+ return vrm_models[i].vrm_type;
+ i++;
+ }
+
+ return 0;
+}
+
+int vid_which_vrm(void)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+ u32 eax;
+ u8 eff_family, eff_model;
+ int vrm_ret;
+
+ if (c->x86 < 6) /* Any CPU with family lower than 6 */
+ return 0; /* doesn't have VID and/or CPUID */
+
+ eax = cpuid_eax(1);
+ eff_family = ((eax & 0x00000F00)>>8);
+ eff_model = ((eax & 0x000000F0)>>4);
+ if (eff_family == 0xF) { /* use extended model & family */
+ eff_family += ((eax & 0x00F00000)>>20);
+ eff_model += ((eax & 0x000F0000)>>16)<<4;
+ }
+ vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+ if (vrm_ret == 0)
+ printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
+ "x86 CPU\n");
+ return vrm_ret;
+}
+
+/* and now something completely different for the non-x86 world */
+#else
+int vid_which_vrm(void)
+{
+ printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
+ return 0;
+}
+#endif
+
+EXPORT_SYMBOL(vid_from_reg);
+EXPORT_SYMBOL(vid_which_vrm);
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("hwmon-vid driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
new file mode 100644
index 000000000000..9b41c9bd805f
--- /dev/null
+++ b/drivers/hwmon/hwmon.c
@@ -0,0 +1,98 @@
+/*
+ hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+ This file defines the sysfs class "hwmon", for use by sensors drivers.
+
+ Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+#include <linux/hwmon.h>
+
+#define HWMON_ID_PREFIX "hwmon"
+#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
+
+static struct class *hwmon_class;
+
+static DEFINE_IDR(hwmon_idr);
+
+/**
+ * hwmon_device_register - register w/ hwmon sysfs class
+ * @dev: the device to register
+ *
+ * hwmon_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct class_device *hwmon_device_register(struct device *dev)
+{
+ struct class_device *cdev;
+ int id;
+
+ if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)
+ return ERR_PTR(-ENOMEM);
+
+ if (idr_get_new(&hwmon_idr, NULL, &id) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ id = id & MAX_ID_MASK;
+ cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+ HWMON_ID_FORMAT, id);
+
+ if (IS_ERR(cdev))
+ idr_remove(&hwmon_idr, id);
+
+ return cdev;
+}
+
+/**
+ * hwmon_device_unregister - removes the previously registered class device
+ *
+ * @cdev: the class device to destroy
+ */
+void hwmon_device_unregister(struct class_device *cdev)
+{
+ int id;
+
+ if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) {
+ class_device_unregister(cdev);
+ idr_remove(&hwmon_idr, id);
+ } else
+ dev_dbg(cdev->dev,
+ "hwmon_device_unregister() failed: bad class ID!\n");
+}
+
+static int __init hwmon_init(void)
+{
+ hwmon_class = class_create(THIS_MODULE, "hwmon");
+ if (IS_ERR(hwmon_class)) {
+ printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
+ return PTR_ERR(hwmon_class);
+ }
+ return 0;
+}
+
+static void __exit hwmon_exit(void)
+{
+ class_destroy(hwmon_class);
+}
+
+module_init(hwmon_init);
+module_exit(hwmon_exit);
+
+EXPORT_SYMBOL_GPL(hwmon_device_register);
+EXPORT_SYMBOL_GPL(hwmon_device_unregister);
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index db20c9e47393..53cc2b6d6385 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -36,19 +36,21 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
/* Insmod parameters */
-SENSORS_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_2(it87, it8712);
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
@@ -192,6 +194,7 @@ static int DIV_TO_REG(int val)
allocated. */
struct it87_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -218,7 +221,7 @@ struct it87_data {
static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_find(int *address);
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
static int it87_detach_client(struct i2c_client *client);
@@ -239,6 +242,14 @@ static struct i2c_driver it87_driver = {
.detach_client = it87_detach_client,
};
+static struct i2c_driver it87_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "it87-isa",
+ .attach_adapter = it87_isa_attach_adapter,
+ .detach_client = it87_detach_client,
+};
+
+
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -686,11 +697,16 @@ static int it87_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, it87_detect);
+ return i2c_probe(adapter, &addr_data, it87_detect);
}
-/* SuperIO detection - will change normal_isa[0] if a chip is found */
-static int it87_find(int *address)
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return it87_detect(adapter, isa_address, -1);
+}
+
+/* SuperIO detection - will change isa_address if a chip is found */
+static int __init it87_find(int *address)
{
int err = -ENODEV;
@@ -721,7 +737,7 @@ exit:
return err;
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int it87_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
@@ -738,7 +754,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, IT87_EXTENT, it87_driver.name))
+ if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
goto ERROR0;
/* Probe whether there is anything available on this address. Already
@@ -784,7 +800,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
- new_client->driver = &it87_driver;
+ new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -840,6 +856,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
it87_init_client(new_client, data);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
@@ -897,13 +919,15 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->type == it8712) {
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
device_create_file_vrm(new_client);
device_create_file_vid(new_client);
}
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
@@ -915,17 +939,17 @@ ERROR0:
static int it87_detach_client(struct i2c_client *client)
{
+ struct it87_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
if(i2c_is_isa_client(client))
release_region(client->addr, IT87_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -1158,16 +1182,28 @@ static struct it87_data *it87_update_device(struct device *dev)
static int __init sm_it87_init(void)
{
- int addr;
+ int addr, res;
if (!it87_find(&addr)) {
- normal_isa[0] = addr;
+ isa_address = addr;
+ }
+
+ res = i2c_add_driver(&it87_driver);
+ if (res)
+ return res;
+
+ res = i2c_isa_add_driver(&it87_isa_driver);
+ if (res) {
+ i2c_del_driver(&it87_driver);
+ return res;
}
- return i2c_add_driver(&it87_driver);
+
+ return 0;
}
static void __exit sm_it87_exit(void)
{
+ i2c_isa_del_driver(&it87_isa_driver);
i2c_del_driver(&it87_driver);
}
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 7c6f9ea5a254..be5c7095ecbb 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -42,8 +42,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -51,13 +52,12 @@
*/
static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm63);
+I2C_CLIENT_INSMOD_1(lm63);
/*
* The LM63 registers
@@ -152,6 +152,7 @@ static struct i2c_driver lm63_driver = {
struct lm63_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -358,7 +359,7 @@ static int lm63_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm63_detect);
+ return i2c_probe(adapter, &addr_data, lm63_detect);
}
/*
@@ -437,6 +438,12 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
lm63_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
if (data->config & 0x04) { /* tachometer enabled */
device_create_file(&new_client->dev,
&sensor_dev_attr_fan1_input.dev_attr);
@@ -462,6 +469,8 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -505,15 +514,15 @@ static void lm63_init_client(struct i2c_client *client)
static int lm63_detach_client(struct i2c_client *client)
{
+ struct lm63_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 5be164ed278e..9a3ebdf583f4 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -23,17 +23,17 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include "lm75.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm75);
+I2C_CLIENT_INSMOD_1(lm75);
/* Many LM75 constants specified below */
@@ -46,6 +46,7 @@ SENSORS_INSMOD_1(lm75);
/* Each client has this additional data */
struct lm75_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -107,10 +108,10 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm75_detect);
+ return i2c_probe(adapter, &addr_data, lm75_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
@@ -119,16 +120,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
const char *name = "";
- /* Make sure we aren't probing the ISA bus!! This is just a safety check
- at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
- if (i2c_is_isa_adapter(adapter)) {
- dev_dbg(&adapter->dev,
- "lm75_detect called for an ISA bus adapter?!?\n");
- goto exit;
- }
-#endif
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
goto exit;
@@ -208,12 +199,20 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
lm75_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -222,8 +221,10 @@ exit:
static int lm75_detach_client(struct i2c_client *client)
{
+ struct lm75_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -251,8 +252,12 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
static void lm75_init_client(struct i2c_client *client)
{
- /* Initialize the LM75 chip */
- lm75_write_value(client, LM75_REG_CONF, 0);
+ int reg;
+
+ /* Enable if in shutdown mode */
+ reg = lm75_read_value(client, LM75_REG_CONF);
+ if (reg >= 0 && (reg & 0x01))
+ lm75_write_value(client, LM75_REG_CONF, reg & 0xfe);
}
static struct lm75_data *lm75_update_device(struct device *dev)
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h
index 63e3f2fb4c21..af7dc650ee15 100644
--- a/drivers/hwmon/lm75.h
+++ b/drivers/hwmon/lm75.h
@@ -25,7 +25,7 @@
which contains this code, we don't worry about the wasted space.
*/
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
/* straight from the datasheet */
#define LM75_TEMP_MIN (-55000)
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index b98f44952997..866eab96a6f6 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -30,15 +30,14 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm77);
+I2C_CLIENT_INSMOD_1(lm77);
/* The LM77 registers */
#define LM77_REG_TEMP 0x00
@@ -51,6 +50,7 @@ SENSORS_INSMOD_1(lm77);
/* Each client has this additional data */
struct lm77_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
@@ -208,10 +208,10 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm77_detect);
+ return i2c_probe(adapter, &addr_data, lm77_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -317,6 +317,12 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
lm77_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -327,6 +333,8 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -335,8 +343,10 @@ exit:
static int lm77_detach_client(struct i2c_client *client)
{
+ struct lm77_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 29241469dcba..f6730dc3573b 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -23,7 +23,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
/* Addresses to scan */
@@ -31,10 +34,10 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29,
0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
/* Insmod parameters */
-SENSORS_INSMOD_3(lm78, lm78j, lm79);
+I2C_CLIENT_INSMOD_2(lm78, lm79);
/* Many LM78 constants specified below */
@@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val)
return val * 1000;
}
-/* VID: mV
- REG: (see doc/vid) */
-static inline int VID_FROM_REG(u8 val)
-{
- return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
-}
-
#define DIV_FROM_REG(val) (1 << (val))
/* There are some complications in a module like this. First off, LM78 chips
@@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val)
allocated. */
struct lm78_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -156,6 +153,7 @@ struct lm78_data {
static int lm78_attach_adapter(struct i2c_adapter *adapter);
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
static int lm78_detach_client(struct i2c_client *client);
@@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = {
.detach_client = lm78_detach_client,
};
+static struct i2c_driver lm78_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm78-isa",
+ .attach_adapter = lm78_isa_attach_adapter,
+ .detach_client = lm78_detach_client,
+};
+
+
/* 7 Voltages */
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
@@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
- return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
+ return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
@@ -465,10 +471,15 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm78_detect);
+ return i2c_probe(adapter, &addr_data, lm78_detect);
+}
+
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return lm78_detect(adapter, isa_address, -1);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, err;
@@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
+ if (!request_region(address, LM78_EXTENT,
+ lm78_isa_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -540,7 +552,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
- new_client->driver = &lm78_driver;
+ new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -559,10 +571,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Determine the chip type. */
if (kind <= 0) {
i = lm78_read_value(new_client, LM78_REG_CHIPID);
- if (i == 0x00 || i == 0x20)
+ if (i == 0x00 || i == 0x20 /* LM78 */
+ || i == 0x40) /* LM78-J */
kind = lm78;
- else if (i == 0x40)
- kind = lm78j;
else if ((i & 0xfe) == 0xc0)
kind = lm79;
else {
@@ -578,8 +589,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == lm78) {
client_name = "lm78";
- } else if (kind == lm78j) {
- client_name = "lm78-j";
} else if (kind == lm79) {
client_name = "lm79";
}
@@ -605,6 +614,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -643,6 +658,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
@@ -654,18 +671,18 @@ ERROR0:
static int lm78_detach_client(struct i2c_client *client)
{
+ struct lm78_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
if(i2c_is_isa_client(client))
release_region(client->addr, LM78_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -777,18 +794,31 @@ static struct lm78_data *lm78_update_device(struct device *dev)
static int __init sm_lm78_init(void)
{
- return i2c_add_driver(&lm78_driver);
+ int res;
+
+ res = i2c_add_driver(&lm78_driver);
+ if (res)
+ return res;
+
+ res = i2c_isa_add_driver(&lm78_isa_driver);
+ if (res) {
+ i2c_del_driver(&lm78_driver);
+ return res;
+ }
+
+ return 0;
}
static void __exit sm_lm78_exit(void)
{
+ i2c_isa_del_driver(&lm78_isa_driver);
i2c_del_driver(&lm78_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
+MODULE_DESCRIPTION("LM78/LM79 driver");
MODULE_LICENSE("GPL");
module_init(sm_lm78_init);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 8100595feb44..83af8b3a0cac 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -26,15 +26,15 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm80);
+I2C_CLIENT_INSMOD_1(lm80);
/* Many LM80 constants specified below */
@@ -107,6 +107,7 @@ static inline long TEMP_FROM_REG(u16 temp)
struct lm80_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -389,7 +390,7 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm80_detect);
+ return i2c_probe(adapter, &addr_data, lm80_detect);
}
int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -451,6 +452,12 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
@@ -487,6 +494,8 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
kfree(data);
exit:
@@ -495,15 +504,15 @@ exit:
static int lm80_detach_client(struct i2c_client *client)
{
+ struct lm80_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index a49008b444c8..d74b2c20c719 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -32,8 +32,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -45,13 +46,12 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm83);
+I2C_CLIENT_INSMOD_1(lm83);
/*
* The LM83 registers
@@ -138,6 +138,7 @@ static struct i2c_driver lm83_driver = {
struct lm83_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -212,7 +213,7 @@ static int lm83_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm83_detect);
+ return i2c_probe(adapter, &addr_data, lm83_detect);
}
/*
@@ -312,6 +313,12 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&new_client->dev,
@@ -340,6 +347,8 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -348,15 +357,15 @@ exit:
static int lm83_detach_client(struct i2c_client *client)
{
+ struct lm83_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index b4d7fd418264..ab214df9624b 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -28,15 +28,15 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
+I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
/* The LM85 registers */
@@ -281,15 +281,6 @@ static int ZONE_TO_REG( int zone )
#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
-/* i2c-vid.h defines vid_from_reg() */
-#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
-
-/* Unlike some other drivers we DO NOT set initial limits. Use
- * the config file to set limits. Some users have reported
- * motherboards shutting down when we set limits in a previous
- * version of the driver.
- */
-
/* Chip sampling rates
*
* Some sensors are not updated more frequently than once per second
@@ -339,6 +330,7 @@ struct lm85_autofan {
struct lm85_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -1019,7 +1011,7 @@ int lm85_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm85_detect);
+ return i2c_probe(adapter, &addr_data, lm85_detect);
}
int lm85_detect(struct i2c_adapter *adapter, int address,
@@ -1031,11 +1023,6 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
int err = 0;
const char *type_name = "";
- if (i2c_is_isa_adapter(adapter)) {
- /* This chip has no ISA interface */
- goto ERROR0 ;
- };
-
if (!i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */
@@ -1160,12 +1147,18 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
goto ERROR1;
/* Set the VRM version */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/* Initialize the LM85 chip */
lm85_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR2;
+ }
+
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan3_input);
@@ -1235,6 +1228,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
return 0;
/* Error out and cleanup code */
+ ERROR2:
+ i2c_detach_client(new_client);
ERROR1:
kfree(data);
ERROR0:
@@ -1243,8 +1238,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
int lm85_detach_client(struct i2c_client *client)
{
+ struct lm85_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 1921ed1af182..dca996de4c33 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -57,8 +57,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -66,13 +67,12 @@
*/
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm87);
+I2C_CLIENT_INSMOD_1(lm87);
/*
* The LM87 registers
@@ -175,6 +175,7 @@ static struct i2c_driver lm87_driver = {
struct lm87_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -537,7 +538,7 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm87_detect);
+ return i2c_probe(adapter, &addr_data, lm87_detect);
}
/*
@@ -608,6 +609,12 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
data->in_scale[7] = 1875;
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in1_max);
@@ -673,6 +680,8 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -685,7 +694,7 @@ static void lm87_init_client(struct i2c_client *client)
u8 config;
data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
config = lm87_read_value(client, LM87_REG_CONFIG);
if (!(config & 0x01)) {
@@ -719,15 +728,15 @@ static void lm87_init_client(struct i2c_client *client)
static int lm87_detach_client(struct i2c_client *client)
{
+ struct lm87_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index a67dcadf7cb0..14de05fcd431 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -75,8 +75,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -89,13 +90,12 @@
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
+I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
/*
* The LM90 registers
@@ -200,6 +200,7 @@ static struct i2c_driver lm90_driver = {
struct lm90_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -352,7 +353,7 @@ static int lm90_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm90_detect);
+ return i2c_probe(adapter, &addr_data, lm90_detect);
}
/*
@@ -500,6 +501,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
lm90_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&new_client->dev,
@@ -524,6 +531,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -547,15 +556,15 @@ static void lm90_init_client(struct i2c_client *client)
static int lm90_detach_client(struct i2c_client *client)
{
+ struct lm90_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 215c8e40ffdd..647b7c7cd575 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -44,17 +44,16 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* The LM92 and MAX6635 have 2 two-state pins for address selection,
resulting in 4 possible addresses. */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm92);
+I2C_CLIENT_INSMOD_1(lm92);
/* The LM92 registers */
#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
@@ -96,6 +95,7 @@ static struct i2c_driver lm92_driver;
/* Client data (each client gets its own) */
struct lm92_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -359,6 +359,12 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
lm92_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
@@ -370,6 +376,8 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -380,20 +388,20 @@ static int lm92_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm92_detect);
+ return i2c_probe(adapter, &addr_data, lm92_detect);
}
static int lm92_detach_client(struct i2c_client *client)
{
+ struct lm92_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 3c159f1d49ee..16bf71f3a04d 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -31,20 +31,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(max1619);
+I2C_CLIENT_INSMOD_1(max1619);
/*
* The MAX1619 registers
@@ -104,6 +103,7 @@ static struct i2c_driver max1619_driver = {
struct max1619_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -179,7 +179,7 @@ static int max1619_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, max1619_detect);
+ return i2c_probe(adapter, &addr_data, max1619_detect);
}
/*
@@ -275,6 +275,12 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
max1619_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
@@ -285,6 +291,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -308,15 +316,15 @@ static void max1619_init_client(struct i2c_client *client)
static int max1619_detach_client(struct i2c_client *client)
{
+ struct max1619_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index fa4032d53b79..cf2a35799c7c 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -38,23 +38,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{ NULL }};
static u8 devid;
-static unsigned int extra_isa[3];
+static unsigned short address;
+static unsigned short extra_isa[3];
static u8 confreg[4];
enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .forces = forces,
-};
static int init = 1;
module_param(init, int, 0);
@@ -186,6 +182,7 @@ static inline u8 PWM_TO_REG(int val, int inv)
struct pc87360_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
@@ -224,8 +221,7 @@ struct pc87360_data {
* Functions declaration
*/
-static int pc87360_attach_adapter(struct i2c_adapter *adapter);
-static int pc87360_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pc87360_detect(struct i2c_adapter *adapter);
static int pc87360_detach_client(struct i2c_client *client);
static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
@@ -242,8 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
static struct i2c_driver pc87360_driver = {
.owner = THIS_MODULE,
.name = "pc87360",
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = pc87360_attach_adapter,
+ .attach_adapter = pc87360_detect,
.detach_client = pc87360_detach_client,
};
@@ -251,168 +246,178 @@ static struct i2c_driver pc87360_driver = {
* Sysfs stuff
*/
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
+ FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
+ FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ FAN_DIV_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct pc87360_data *data = i2c_get_clientdata(client);
long fan_min = simple_strtol(buf, NULL, 10);
down(&data->update_lock);
- fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[nr]));
+ fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
/* If it wouldn't fit, change clock divisor */
while (fan_min > 255
- && (data->fan_status[nr] & 0x60) != 0x60) {
+ && (data->fan_status[attr->index] & 0x60) != 0x60) {
fan_min >>= 1;
- data->fan[nr] >>= 1;
- data->fan_status[nr] += 0x20;
+ data->fan[attr->index] >>= 1;
+ data->fan_status[attr->index] += 0x20;
}
- data->fan_min[nr] = fan_min > 255 ? 255 : fan_min;
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(nr),
- data->fan_min[nr]);
+ data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index),
+ data->fan_min[attr->index]);
/* Write new divider, preserve alarm bits */
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(nr),
- data->fan_status[nr] & 0xF9);
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
+ data->fan_status[attr->index] & 0xF9);
up(&data->update_lock);
return count;
}
#define show_and_set_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
- FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
- FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_fan_min(dev, buf, count, offset-1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
- show_fan##offset##_input, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
- show_fan##offset##_min, set_fan##offset##_min); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
- show_fan##offset##_div, NULL); \
-static DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
- show_fan##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
+ show_fan_min, set_fan_min, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+ show_fan_div, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
+ show_fan_status, NULL, offset-1);
show_and_set_fan(1)
show_and_set_fan(2)
show_and_set_fan(3)
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ PWM_FROM_REG(data->pwm[attr->index],
+ FAN_CONFIG_INVERT(data->fan_conf,
+ attr->index)));
+}
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->pwm[attr->index] = PWM_TO_REG(val,
+ FAN_CONFIG_INVERT(data->fan_conf, attr->index));
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
+ data->pwm[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_pwm(offset) \
-static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- PWM_FROM_REG(data->pwm[offset-1], \
- FAN_CONFIG_INVERT(data->fan_conf, \
- offset-1))); \
-} \
-static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->pwm[offset-1] = PWM_TO_REG(val, \
- FAN_CONFIG_INVERT(data->fan_conf, offset-1)); \
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(offset-1), \
- data->pwm[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
- show_pwm##offset, set_pwm##offset);
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
+ show_pwm, set_pwm, offset-1);
show_and_set_pwm(1)
show_and_set_pwm(2)
show_and_set_pwm(3)
+static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
+ data->in_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[attr->index] = IN_TO_REG(val,
+ data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
+ data->in_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", data->in_status[offset]); \
-} \
-static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_min[offset] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MIN, \
- data->in_min[offset]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_max[offset] = IN_TO_REG(val, \
- data->in_vref); \
- pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MAX, \
- data->in_max[offset]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
- show_in##offset##_input, NULL); \
-static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
- show_in##offset##_max, set_in##offset##_max); \
-static DEVICE_ATTR(in##offset##_status, S_IRUGO, \
- show_in##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in_input, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
+ show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
+ show_in_max, set_in_max, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \
+ show_in_status, NULL, offset);
show_and_set_in(0)
show_and_set_in(1)
show_and_set_in(2)
@@ -425,88 +430,97 @@ show_and_set_in(8)
show_and_set_in(9)
show_and_set_in(10)
+static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
+ data->in_vref));
+}
+static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
+ data->in_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
+ data->in_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
+ data->in_crit[attr->index-11]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_therm(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", data->in_status[offset+7]); \
-} \
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_min[offset+7] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MIN, \
- data->in_min[offset+7]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_max[offset+7] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MAX, \
- data->in_max[offset+7]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_crit[offset-4] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_CRIT, \
- data->in_crit[offset-4]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
- show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
- show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
- show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
- show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_therm_input, NULL, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+ show_therm_min, set_therm_min, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+ show_therm_max, set_therm_max, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+ show_therm_crit, set_therm_crit, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+ show_therm_status, NULL, 11+offset-4);
show_and_set_therm(4)
show_and_set_therm(5)
show_and_set_therm(6)
@@ -539,84 +553,93 @@ static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
+}
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
+}
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
+}
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index]));
+}
+static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_status[attr->index]);
+}
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
+ data->temp_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
+ data->temp_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_crit[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
+ data->temp_crit[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
-}\
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
-}\
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
-}\
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_min[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MIN, \
- data->temp_min[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_max[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MAX, \
- data->temp_max[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_crit[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_CRIT, \
- data->temp_crit[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
- show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
- show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
- show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
- show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+ show_temp_min, set_temp_min, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+ show_temp_max, set_temp_max, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+ show_temp_crit, set_temp_crit, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+ show_temp_status, NULL, offset-1);
show_and_set_temp(1)
show_and_set_temp(2)
show_and_set_temp(3)
@@ -632,12 +655,7 @@ static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
* Device detection, registration and update
*/
-static int pc87360_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_detect(adapter, &addr_data, pc87360_detect);
-}
-
-static int pc87360_find(int sioaddr, u8 *devid, int *address)
+static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
{
u16 val;
int i;
@@ -683,7 +701,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
continue;
}
- address[i] = val;
+ addresses[i] = val;
if (i==0) { /* Fans */
confreg[0] = superio_inb(sioaddr, 0xF0);
@@ -727,9 +745,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
return 0;
}
-/* We don't really care about the address.
- Read from extra_isa instead. */
-int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pc87360_detect(struct i2c_adapter *adapter)
{
int i;
struct i2c_client *new_client;
@@ -738,9 +754,6 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
const char *name = "pc87360";
int use_thermistors = 0;
- if (!i2c_is_isa_adapter(adapter))
- return -ENODEV;
-
if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
return -ENOMEM;
memset(data, 0x00, sizeof(struct pc87360_data));
@@ -838,51 +851,57 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
if (data->innr) {
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in6_input);
- device_create_file(&new_client->dev, &dev_attr_in7_input);
- device_create_file(&new_client->dev, &dev_attr_in8_input);
- device_create_file(&new_client->dev, &dev_attr_in9_input);
- device_create_file(&new_client->dev, &dev_attr_in10_input);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in6_min);
- device_create_file(&new_client->dev, &dev_attr_in7_min);
- device_create_file(&new_client->dev, &dev_attr_in8_min);
- device_create_file(&new_client->dev, &dev_attr_in9_min);
- device_create_file(&new_client->dev, &dev_attr_in10_min);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_in6_max);
- device_create_file(&new_client->dev, &dev_attr_in7_max);
- device_create_file(&new_client->dev, &dev_attr_in8_max);
- device_create_file(&new_client->dev, &dev_attr_in9_max);
- device_create_file(&new_client->dev, &dev_attr_in10_max);
- device_create_file(&new_client->dev, &dev_attr_in0_status);
- device_create_file(&new_client->dev, &dev_attr_in1_status);
- device_create_file(&new_client->dev, &dev_attr_in2_status);
- device_create_file(&new_client->dev, &dev_attr_in3_status);
- device_create_file(&new_client->dev, &dev_attr_in4_status);
- device_create_file(&new_client->dev, &dev_attr_in5_status);
- device_create_file(&new_client->dev, &dev_attr_in6_status);
- device_create_file(&new_client->dev, &dev_attr_in7_status);
- device_create_file(&new_client->dev, &dev_attr_in8_status);
- device_create_file(&new_client->dev, &dev_attr_in9_status);
- device_create_file(&new_client->dev, &dev_attr_in10_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
@@ -890,90 +909,92 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->tempnr) {
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_min);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
- device_create_file(&new_client->dev, &dev_attr_temp1_status);
- device_create_file(&new_client->dev, &dev_attr_temp2_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms_temp);
}
if (data->tempnr == 3) {
- device_create_file(&new_client->dev, &dev_attr_temp3_input);
- device_create_file(&new_client->dev, &dev_attr_temp3_min);
- device_create_file(&new_client->dev, &dev_attr_temp3_max);
- device_create_file(&new_client->dev, &dev_attr_temp3_crit);
- device_create_file(&new_client->dev, &dev_attr_temp3_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr);
}
if (data->innr == 14) {
- device_create_file(&new_client->dev, &dev_attr_temp4_input);
- device_create_file(&new_client->dev, &dev_attr_temp5_input);
- device_create_file(&new_client->dev, &dev_attr_temp6_input);
- device_create_file(&new_client->dev, &dev_attr_temp4_min);
- device_create_file(&new_client->dev, &dev_attr_temp5_min);
- device_create_file(&new_client->dev, &dev_attr_temp6_min);
- device_create_file(&new_client->dev, &dev_attr_temp4_max);
- device_create_file(&new_client->dev, &dev_attr_temp5_max);
- device_create_file(&new_client->dev, &dev_attr_temp6_max);
- device_create_file(&new_client->dev, &dev_attr_temp4_crit);
- device_create_file(&new_client->dev, &dev_attr_temp5_crit);
- device_create_file(&new_client->dev, &dev_attr_temp6_crit);
- device_create_file(&new_client->dev, &dev_attr_temp4_status);
- device_create_file(&new_client->dev, &dev_attr_temp5_status);
- device_create_file(&new_client->dev, &dev_attr_temp6_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr);
}
if (data->fannr) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) {
device_create_file(&new_client->dev,
- &dev_attr_fan1_input);
+ &sensor_dev_attr_fan1_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_min);
+ &sensor_dev_attr_fan1_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_div);
+ &sensor_dev_attr_fan1_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_status);
+ &sensor_dev_attr_fan1_status.dev_attr);
}
if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) {
device_create_file(&new_client->dev,
- &dev_attr_fan2_input);
+ &sensor_dev_attr_fan2_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_min);
+ &sensor_dev_attr_fan2_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_div);
+ &sensor_dev_attr_fan2_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_status);
+ &sensor_dev_attr_fan2_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
- device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
- device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
}
if (data->fannr == 3) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
device_create_file(&new_client->dev,
- &dev_attr_fan3_input);
+ &sensor_dev_attr_fan3_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_min);
+ &sensor_dev_attr_fan3_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_div);
+ &sensor_dev_attr_fan3_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_status);
+ &sensor_dev_attr_fan3_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
- device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
}
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
for (i = 0; i < 3; i++) {
if (data->address[i]) {
@@ -990,11 +1011,10 @@ static int pc87360_detach_client(struct i2c_client *client)
struct pc87360_data *data = i2c_get_clientdata(client);
int i;
- if ((i = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((i = i2c_detach_client(client)))
return i;
- }
for (i = 0; i < 3; i++) {
if (data->address[i]) {
@@ -1320,23 +1340,23 @@ static int __init pc87360_init(void)
/* Arbitrarily pick one of the addresses */
for (i = 0; i < 3; i++) {
if (extra_isa[i] != 0x0000) {
- normal_isa[0] = extra_isa[i];
+ address = extra_isa[i];
break;
}
}
- if (normal_isa[0] == 0x0000) {
+ if (address == 0x0000) {
printk(KERN_WARNING "pc87360: No active logical device, "
"module not inserted.\n");
return -ENODEV;
}
- return i2c_add_driver(&pc87360_driver);
+ return i2c_isa_add_driver(&pc87360_driver);
}
static void __exit pc87360_exit(void)
{
- i2c_del_driver(&pc87360_driver);
+ i2c_isa_del_driver(&pc87360_driver);
}
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 6bbfc8fb4f13..21aa9a41f62c 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -55,7 +55,9 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <asm/io.h>
@@ -68,14 +70,10 @@ module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
-/* Addresses to scan.
+/* Device address
Note that we can't determine the ISA address until we have initialized
our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(sis5595);
+static unsigned short address;
/* Many SIS5595 constants specified below */
@@ -168,6 +166,7 @@ static inline u8 DIV_TO_REG(int val)
allocated. */
struct sis5595_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -190,8 +189,7 @@ struct sis5595_data {
static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter);
-static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detect(struct i2c_adapter *adapter);
static int sis5595_detach_client(struct i2c_client *client);
static int sis5595_read_value(struct i2c_client *client, u8 register);
@@ -202,9 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
static struct i2c_driver sis5595_driver = {
.owner = THIS_MODULE,
.name = "sis5595",
- .id = I2C_DRIVERID_SIS5595,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = sis5595_attach_adapter,
+ .attach_adapter = sis5595_detect,
.detach_client = sis5595_detach_client,
};
@@ -476,14 +472,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* This is called when the module is loaded */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, sis5595_detect);
-}
-
-int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+static int sis5595_detect(struct i2c_adapter *adapter)
{
int err = 0;
int i;
@@ -492,10 +481,6 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
char val;
u16 a;
- /* Make sure we are probing the ISA bus!! */
- if (!i2c_is_isa_adapter(adapter))
- goto exit;
-
if (force_addr)
address = force_addr & ~(SIS5595_EXTENT - 1);
/* Reserve the ISA region */
@@ -578,6 +563,12 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -608,7 +599,9 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
}
return 0;
-
+
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit_release:
@@ -619,18 +612,17 @@ exit:
static int sis5595_detach_client(struct i2c_client *client)
{
+ struct sis5595_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_is_isa_client(client))
- release_region(client->addr, SIS5595_EXTENT);
+ release_region(client->addr, SIS5595_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -745,7 +737,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
{
u16 val;
int *i;
- int addr = 0;
for (i = blacklist; *i != 0; i++) {
struct pci_dev *dev;
@@ -761,22 +752,14 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
pci_read_config_word(dev, SIS5595_BASE_REG, &val))
return -ENODEV;
- addr = val & ~(SIS5595_EXTENT - 1);
- if (addr == 0 && force_addr == 0) {
+ address = val & ~(SIS5595_EXTENT - 1);
+ if (address == 0 && force_addr == 0) {
dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
}
- if (force_addr)
- addr = force_addr; /* so detect will get called */
-
- if (!addr) {
- dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
- return -ENODEV;
- }
- normal_isa[0] = addr;
s_bridge = pci_dev_get(dev);
- if (i2c_add_driver(&sis5595_driver)) {
+ if (i2c_isa_add_driver(&sis5595_driver)) {
pci_dev_put(s_bridge);
s_bridge = NULL;
}
@@ -803,7 +786,7 @@ static void __exit sm_sis5595_exit(void)
{
pci_unregister_driver(&sis5595_pci_driver);
if (s_bridge != NULL) {
- i2c_del_driver(&sis5595_driver);
+ i2c_isa_del_driver(&sis5595_driver);
pci_dev_put(s_bridge);
s_bridge = NULL;
}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index fdeeb3ab6f2f..7fe71576dea4 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -31,23 +31,14 @@
#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47b397 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .probe = normal_i2c, /* cheat */
- .ignore = normal_i2c, /* cheat */
- .forces = forces,
-};
+static unsigned short address;
/* Super-I/0 registers and commands */
@@ -100,6 +91,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
struct smsc47b397_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -215,52 +207,40 @@ sysfs_fan(4);
#define device_create_file_fan(client, num) \
device_create_file(&client->dev, &dev_attr_fan##num##_input)
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
-
-static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, smsc47b397_detect);
-}
-
static int smsc47b397_detach_client(struct i2c_client *client)
{
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, SMSC_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
+static int smsc47b397_detect(struct i2c_adapter *adapter);
+
static struct i2c_driver smsc47b397_driver = {
.owner = THIS_MODULE,
.name = "smsc47b397",
- .id = I2C_DRIVERID_SMSC47B397,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = smsc47b397_attach_adapter,
+ .attach_adapter = smsc47b397_detect,
.detach_client = smsc47b397_detach_client,
};
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int smsc47b397_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct smsc47b397_data *data;
int err = 0;
- if (!i2c_is_isa_adapter(adapter)) {
- return 0;
- }
-
- if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
- dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+ if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+ dev_err(&adapter->dev, "Region 0x%x already in use!\n",
+ address);
return -EBUSY;
}
@@ -272,7 +252,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
new_client = &data->client;
i2c_set_clientdata(new_client, data);
- new_client->addr = addr;
+ new_client->addr = address;
init_MUTEX(&data->lock);
new_client->adapter = adapter;
new_client->driver = &smsc47b397_driver;
@@ -285,6 +265,12 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
if ((err = i2c_attach_client(new_client)))
goto error_free;
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
device_create_file_temp(new_client, 1);
device_create_file_temp(new_client, 2);
device_create_file_temp(new_client, 3);
@@ -297,14 +283,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
kfree(data);
error_release:
- release_region(addr, SMSC_EXTENT);
+ release_region(address, SMSC_EXTENT);
return err;
}
-static int __init smsc47b397_find(unsigned int *addr)
+static int __init smsc47b397_find(unsigned short *addr)
{
u8 id, rev;
@@ -333,15 +321,15 @@ static int __init smsc47b397_init(void)
{
int ret;
- if ((ret = smsc47b397_find(normal_isa)))
+ if ((ret = smsc47b397_find(&address)))
return ret;
- return i2c_add_driver(&smsc47b397_driver);
+ return i2c_isa_add_driver(&smsc47b397_driver);
}
static void __exit smsc47b397_exit(void)
{
- i2c_del_driver(&smsc47b397_driver);
+ i2c_isa_del_driver(&smsc47b397_driver);
}
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 7166ad0b2fda..c9cc683eba4a 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -2,8 +2,8 @@
smsc47m1.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
- Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
- Super-I/O chips.
+ Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
+ LPC47M15x and LPC47M192 Super-I/O chips.
Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -30,21 +30,14 @@
#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47m1 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .forces = forces,
-};
+static unsigned short address;
/* Super-I/0 registers and commands */
@@ -108,6 +101,7 @@ superio_exit(void)
struct smsc47m1_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -121,9 +115,7 @@ struct smsc47m1_data {
};
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
-static int smsc47m1_find(int *address);
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detect(struct i2c_adapter *adapter);
static int smsc47m1_detach_client(struct i2c_client *client);
static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
@@ -136,9 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static struct i2c_driver smsc47m1_driver = {
.owner = THIS_MODULE,
.name = "smsc47m1",
- .id = I2C_DRIVERID_SMSC47M1,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = smsc47m1_attach_adapter,
+ .attach_adapter = smsc47m1_detect,
.detach_client = smsc47m1_detach_client,
};
@@ -354,14 +344,7 @@ fan_present(2);
static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, smsc47m1_detect);
-}
-
-static int smsc47m1_find(int *address)
+static int __init smsc47m1_find(unsigned short *addr)
{
u8 val;
@@ -388,10 +371,10 @@ static int smsc47m1_find(int *address)
}
superio_select();
- *address = (superio_inb(SUPERIO_REG_BASE) << 8)
- | superio_inb(SUPERIO_REG_BASE + 1);
+ *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+ | superio_inb(SUPERIO_REG_BASE + 1);
val = superio_inb(SUPERIO_REG_ACT);
- if (*address == 0 || (val & 0x01) == 0) {
+ if (*addr == 0 || (val & 0x01) == 0) {
printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
superio_exit();
return -ENODEV;
@@ -401,17 +384,13 @@ static int smsc47m1_find(int *address)
return 0;
}
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+static int smsc47m1_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct smsc47m1_data *data;
int err = 0;
int fan1, fan2, pwm1, pwm2;
- if (!i2c_is_isa_adapter(adapter)) {
- return 0;
- }
-
if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
@@ -461,6 +440,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
function. */
smsc47m1_update_device(&new_client->dev, 1);
+ /* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
if (fan1) {
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -494,6 +480,8 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
kfree(data);
error_release:
@@ -503,16 +491,16 @@ error_release:
static int smsc47m1_detach_client(struct i2c_client *client)
{
+ struct smsc47m1_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, SMSC_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -573,16 +561,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static int __init sm_smsc47m1_init(void)
{
- if (smsc47m1_find(normal_isa)) {
+ if (smsc47m1_find(&address)) {
return -ENODEV;
}
- return i2c_add_driver(&smsc47m1_driver);
+ return i2c_isa_add_driver(&smsc47m1_driver);
}
static void __exit sm_smsc47m1_exit(void)
{
- i2c_del_driver(&smsc47m1_driver);
+ i2c_isa_del_driver(&smsc47m1_driver);
}
MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 164d47948390..05ddc88e7dd2 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -35,7 +35,9 @@
#include <linux/pci.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -47,14 +49,10 @@ module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
-/* Addresses to scan.
+/* Device address
Note that we can't determine the ISA address until we have initialized
our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(via686a);
+static unsigned short address;
/*
The Via 686a southbridge has a LM78-like chip integrated on the same IC.
@@ -297,6 +295,7 @@ static inline long TEMP_FROM_REG10(u16 val)
via686a client is allocated. */
struct via686a_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -315,8 +314,7 @@ struct via686a_data {
static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
-static int via686a_attach_adapter(struct i2c_adapter *adapter);
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
+static int via686a_detect(struct i2c_adapter *adapter);
static int via686a_detach_client(struct i2c_client *client);
static inline int via686a_read_value(struct i2c_client *client, u8 reg)
@@ -576,22 +574,13 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static struct i2c_driver via686a_driver = {
.owner = THIS_MODULE,
.name = "via686a",
- .id = I2C_DRIVERID_VIA686A,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = via686a_attach_adapter,
+ .attach_adapter = via686a_detect,
.detach_client = via686a_detach_client,
};
/* This is called when the module is loaded */
-static int via686a_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, via686a_detect);
-}
-
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
+static int via686a_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct via686a_data *data;
@@ -599,13 +588,6 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
const char client_name[] = "via686a";
u16 val;
- /* Make sure we are probing the ISA bus!! */
- if (!i2c_is_isa_adapter(adapter)) {
- dev_err(&adapter->dev,
- "via686a_detect called for an I2C bus adapter?!?\n");
- return 0;
- }
-
/* 8231 requires multiple of 256, we enforce that on 686 as well */
if (force_addr)
address = force_addr & 0xFF00;
@@ -637,7 +619,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
err = -ENOMEM;
- goto ERROR0;
+ goto exit_release;
}
memset(data, 0, sizeof(struct via686a_data));
@@ -655,12 +637,18 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
- goto ERROR3;
+ goto exit_free;
/* Initialize the VIA686A chip */
via686a_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -695,25 +683,27 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
-ERROR3:
+exit_detach:
+ i2c_detach_client(new_client);
+exit_free:
kfree(data);
-ERROR0:
+exit_release:
release_region(address, VIA686A_EXTENT);
return err;
}
static int via686a_detach_client(struct i2c_client *client)
{
+ struct via686a_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, VIA686A_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -810,29 +800,20 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 val;
- int addr = 0;
if (PCIBIOS_SUCCESSFUL !=
pci_read_config_word(dev, VIA686A_BASE_REG, &val))
return -ENODEV;
- addr = val & ~(VIA686A_EXTENT - 1);
- if (addr == 0 && force_addr == 0) {
+ address = val & ~(VIA686A_EXTENT - 1);
+ if (address == 0 && force_addr == 0) {
dev_err(&dev->dev, "base address not set - upgrade BIOS "
"or use force_addr=0xaddr\n");
return -ENODEV;
}
- if (force_addr)
- addr = force_addr; /* so detect will get called */
-
- if (!addr) {
- dev_err(&dev->dev, "No Via 686A sensors found.\n");
- return -ENODEV;
- }
- normal_isa[0] = addr;
s_bridge = pci_dev_get(dev);
- if (i2c_add_driver(&via686a_driver)) {
+ if (i2c_isa_add_driver(&via686a_driver)) {
pci_dev_put(s_bridge);
s_bridge = NULL;
}
@@ -859,7 +840,7 @@ static void __exit sm_via686a_exit(void)
{
pci_unregister_driver(&via686a_pci_driver);
if (s_bridge != NULL) {
- i2c_del_driver(&via686a_driver);
+ i2c_isa_del_driver(&via686a_driver);
pci_dev_put(s_bridge);
s_bridge = NULL;
}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 8a40b6976e1a..b60efe8f8b26 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -9,6 +9,9 @@
Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
in testing and debugging this driver.
+ This driver also supports the W83627EHG, which is the lead-free
+ version of the W83627EHF.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -37,17 +40,14 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
-/* Addresses to scan
- The actual ISA address is read from Super-I/O configuration space */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(w83627ehf);
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
/*
* Super-I/O constants and functions
@@ -174,6 +174,7 @@ temp1_to_reg(int temp)
struct w83627ehf_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -666,15 +667,12 @@ static void w83627ehf_init_client(struct i2c_client *client)
}
}
-static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+static int w83627ehf_detect(struct i2c_adapter *adapter)
{
struct i2c_client *client;
struct w83627ehf_data *data;
int i, err = 0;
- if (!i2c_is_isa_adapter(adapter))
- return 0;
-
if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
err = -EBUSY;
goto exit;
@@ -720,6 +718,12 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
data->has_fan |= (1 << 4);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&client->dev, &dev_attr_fan1_input);
device_create_file(&client->dev, &dev_attr_fan1_min);
device_create_file(&client->dev, &dev_attr_fan1_div);
@@ -753,6 +757,8 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(client);
exit_free:
kfree(data);
exit_release:
@@ -761,24 +767,17 @@ exit:
return err;
}
-static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, w83627ehf_detect);
-}
-
static int w83627ehf_detach_client(struct i2c_client *client)
{
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, REGION_LENGTH);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -786,12 +785,11 @@ static int w83627ehf_detach_client(struct i2c_client *client)
static struct i2c_driver w83627ehf_driver = {
.owner = THIS_MODULE,
.name = "w83627ehf",
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = w83627ehf_attach_adapter,
+ .attach_adapter = w83627ehf_detect,
.detach_client = w83627ehf_detach_client,
};
-static int __init w83627ehf_find(int sioaddr, int *address)
+static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
{
u16 val;
@@ -809,8 +807,8 @@ static int __init w83627ehf_find(int sioaddr, int *address)
superio_select(W83627EHF_LD_HWM);
val = (superio_inb(SIO_REG_ADDR) << 8)
| superio_inb(SIO_REG_ADDR + 1);
- *address = val & ~(REGION_LENGTH - 1);
- if (*address == 0) {
+ *addr = val & ~(REGION_LENGTH - 1);
+ if (*addr == 0) {
superio_exit();
return -ENODEV;
}
@@ -826,16 +824,16 @@ static int __init w83627ehf_find(int sioaddr, int *address)
static int __init sensors_w83627ehf_init(void)
{
- if (w83627ehf_find(0x2e, &normal_isa[0])
- && w83627ehf_find(0x4e, &normal_isa[0]))
+ if (w83627ehf_find(0x2e, &address)
+ && w83627ehf_find(0x4e, &address))
return -ENODEV;
- return i2c_add_driver(&w83627ehf_driver);
+ return i2c_isa_add_driver(&w83627ehf_driver);
}
static void __exit sensors_w83627ehf_exit(void)
{
- i2c_del_driver(&w83627ehf_driver);
+ i2c_isa_del_driver(&w83627ehf_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bd87a42e068a..3479dc5208e2 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -42,8 +42,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
@@ -56,12 +58,15 @@ module_param(force_i2c, byte, 0);
MODULE_PARM_DESC(force_i2c,
"Initialize the i2c address of the sensors");
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
/* Insmod parameters */
-SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
static int init = 1;
module_param(init, bool, 0);
@@ -277,6 +282,7 @@ static inline u8 DIV_TO_REG(long val)
dynamically allocated, at the same time when a new client is allocated. */
struct w83627hf_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -314,9 +320,7 @@ struct w83627hf_data {
};
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
-static int w83627hf_detect(struct i2c_adapter *adapter, int address,
- int kind);
+static int w83627hf_detect(struct i2c_adapter *adapter);
static int w83627hf_detach_client(struct i2c_client *client);
static int w83627hf_read_value(struct i2c_client *client, u16 register);
@@ -328,9 +332,7 @@ static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
.owner = THIS_MODULE,
.name = "w83627hf",
- .id = I2C_DRIVERID_W83627HF,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = w83627hf_attach_adapter,
+ .attach_adapter = w83627hf_detect,
.detach_client = w83627hf_detach_client,
};
@@ -959,16 +961,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
-/* This function is called when:
- * w83627hf_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and w83627hf_driver is still present) */
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_detect(adapter, &addr_data, w83627hf_detect);
-}
-
-static int w83627hf_find(int sioaddr, int *address)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr)
{
u16 val;
@@ -988,32 +981,24 @@ static int w83627hf_find(int sioaddr, int *address)
superio_select(W83627HF_LD_HWM);
val = (superio_inb(WINB_BASE_REG) << 8) |
superio_inb(WINB_BASE_REG + 1);
- *address = val & ~(WINB_EXTENT - 1);
- if (*address == 0 && force_addr == 0) {
+ *addr = val & ~(WINB_EXTENT - 1);
+ if (*addr == 0 && force_addr == 0) {
superio_exit();
return -ENODEV;
}
- if (force_addr)
- *address = force_addr; /* so detect will get called */
superio_exit();
return 0;
}
-int w83627hf_detect(struct i2c_adapter *adapter, int address,
- int kind)
+static int w83627hf_detect(struct i2c_adapter *adapter)
{
- int val;
+ int val, kind;
struct i2c_client *new_client;
struct w83627hf_data *data;
int err = 0;
const char *client_name = "";
- if (!i2c_is_isa_adapter(adapter)) {
- err = -ENODEV;
- goto ERROR0;
- }
-
if(force_addr)
address = force_addr & ~(WINB_EXTENT - 1);
@@ -1102,6 +1087,12 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file_in(new_client, 0);
if (kind != w83697hf)
device_create_file_in(new_client, 1);
@@ -1152,6 +1143,8 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
return 0;
+ ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
@@ -1162,16 +1155,16 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
static int w83627hf_detach_client(struct i2c_client *client)
{
+ struct w83627hf_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, WINB_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -1290,7 +1283,15 @@ static void w83627hf_init_client(struct i2c_client *client)
int type = data->type;
u8 tmp;
- if(init) {
+ if (reset) {
+ /* Resetting the chip has been the default for a long time,
+ but repeatedly caused problems (fans going to full
+ speed...) so it is now optional. It might even go away if
+ nobody reports it as being useful, as I see very little
+ reason why this would be needed at all. */
+ dev_info(&client->dev, "If reset=1 solved a problem you were "
+ "having, please report!\n");
+
/* save this register */
i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
/* Reset all except Watchdog values and last conversion values
@@ -1327,7 +1328,7 @@ static void w83627hf_init_client(struct i2c_client *client)
data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
} else {
/* Convert VID to voltage based on default VRM */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
}
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
@@ -1485,20 +1486,17 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
static int __init sensors_w83627hf_init(void)
{
- int addr;
-
- if (w83627hf_find(0x2e, &addr)
- && w83627hf_find(0x4e, &addr)) {
+ if (w83627hf_find(0x2e, &address)
+ && w83627hf_find(0x4e, &address)) {
return -ENODEV;
}
- normal_isa[0] = addr;
- return i2c_add_driver(&w83627hf_driver);
+ return i2c_isa_add_driver(&w83627hf_driver);
}
static void __exit sensors_w83627hf_exit(void)
{
- i2c_del_driver(&w83627hf_driver);
+ i2c_isa_del_driver(&w83627hf_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 0bb131ce09eb..4c43337ca780 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -38,8 +38,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
@@ -47,10 +49,10 @@
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
/* Insmod parameters */
-SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
@@ -218,6 +220,7 @@ DIV_TO_REG(long val, enum chips type)
allocated. */
struct w83781d_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -255,6 +258,7 @@ struct w83781d_data {
};
static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
static int w83781d_detach_client(struct i2c_client *client);
@@ -273,6 +277,14 @@ static struct i2c_driver w83781d_driver = {
.detach_client = w83781d_detach_client,
};
+static struct i2c_driver w83781d_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83781d-isa",
+ .attach_adapter = w83781d_isa_attach_adapter,
+ .detach_client = w83781d_detach_client,
+};
+
+
/* following are the sysfs callback functions */
#define show_in_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
@@ -856,7 +868,13 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, w83781d_detect);
+ return i2c_probe(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return w83781d_detect(adapter, isa_address, -1);
}
/* Assumes that adapter is of I2C, not ISA variety.
@@ -961,10 +979,10 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
ERROR_SC_3:
i2c_detach_client(data->lm75[0]);
ERROR_SC_2:
- if (NULL != data->lm75[1])
+ if (data->lm75[1])
kfree(data->lm75[1]);
ERROR_SC_1:
- if (NULL != data->lm75[0])
+ if (data->lm75[0])
kfree(data->lm75[0]);
ERROR_SC_0:
return err;
@@ -999,7 +1017,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa)
if (!request_region(address, W83781D_EXTENT,
- w83781d_driver.name)) {
+ w83781d_isa_driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
@@ -1057,7 +1075,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
new_client->addr = address;
init_MUTEX(&data->lock);
new_client->adapter = adapter;
- new_client->driver = &w83781d_driver;
+ new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -1189,6 +1207,12 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
data->pwmenable[i] = 1;
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR4;
+ }
+
device_create_file_in(new_client, 0);
if (kind != w83783s)
device_create_file_in(new_client, 1);
@@ -1241,6 +1265,15 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR4:
+ if (data->lm75[1]) {
+ i2c_detach_client(data->lm75[1]);
+ kfree(data->lm75[1]);
+ }
+ if (data->lm75[0]) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
ERROR3:
i2c_detach_client(new_client);
ERROR2:
@@ -1255,24 +1288,26 @@ ERROR0:
static int
w83781d_detach_client(struct i2c_client *client)
{
+ struct w83781d_data *data = i2c_get_clientdata(client);
int err;
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
if (i2c_is_isa_client(client))
release_region(client->addr, W83781D_EXTENT);
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_get_clientdata(client)==NULL) {
- /* subclients */
+ /* main client */
+ if (data)
+ kfree(data);
+
+ /* subclient */
+ else
kfree(client);
- } else {
- /* main client */
- kfree(i2c_get_clientdata(client));
- }
return 0;
}
@@ -1443,7 +1478,7 @@ w83781d_init_client(struct i2c_client *client)
w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
}
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if ((type != w83781d) && (type != as99127f)) {
tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1613,12 +1648,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
static int __init
sensors_w83781d_init(void)
{
- return i2c_add_driver(&w83781d_driver);
+ int res;
+
+ res = i2c_add_driver(&w83781d_driver);
+ if (res)
+ return res;
+
+ res = i2c_isa_add_driver(&w83781d_isa_driver);
+ if (res) {
+ i2c_del_driver(&w83781d_driver);
+ return res;
+ }
+
+ return 0;
}
static void __exit
sensors_w83781d_exit(void)
{
+ i2c_isa_del_driver(&w83781d_isa_driver);
i2c_del_driver(&w83781d_driver);
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
new file mode 100644
index 000000000000..ba0c28015f6a
--- /dev/null
+++ b/drivers/hwmon/w83792d.c
@@ -0,0 +1,1649 @@
+/*
+ w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (C) 2004, 2005 Winbond Electronics Corp.
+ Chunhao Huang <DZShen@Winbond.com.tw>,
+ Rudolf Marek <r.marek@sh.cvut.cz>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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.
+
+ Note:
+ 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver.
+ 2. This driver is only for Winbond W83792D C version device, there
+ are also some motherboards with B version W83792D device. The
+ calculation method to in6-in7(measured value, limits) is a little
+ different between C and B version. C or B version can be identified
+ by CR[0x49h].
+*/
+
+/*
+ Supports following chips:
+
+ Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ w83792d 9 7 7 3 0x7a 0x5ca3 yes no
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83792d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+ "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force chip initialization");
+
+/* The W83792D registers */
+static const u8 W83792D_REG_IN[9] = {
+ 0x20, /* Vcore A in DataSheet */
+ 0x21, /* Vcore B in DataSheet */
+ 0x22, /* VIN0 in DataSheet */
+ 0x23, /* VIN1 in DataSheet */
+ 0x24, /* VIN2 in DataSheet */
+ 0x25, /* VIN3 in DataSheet */
+ 0x26, /* 5VCC in DataSheet */
+ 0xB0, /* 5VSB in DataSheet */
+ 0xB1 /* VBAT in DataSheet */
+};
+#define W83792D_REG_LOW_BITS1 0x3E /* Low Bits I in DataSheet */
+#define W83792D_REG_LOW_BITS2 0x3F /* Low Bits II in DataSheet */
+static const u8 W83792D_REG_IN_MAX[9] = {
+ 0x2B, /* Vcore A High Limit in DataSheet */
+ 0x2D, /* Vcore B High Limit in DataSheet */
+ 0x2F, /* VIN0 High Limit in DataSheet */
+ 0x31, /* VIN1 High Limit in DataSheet */
+ 0x33, /* VIN2 High Limit in DataSheet */
+ 0x35, /* VIN3 High Limit in DataSheet */
+ 0x37, /* 5VCC High Limit in DataSheet */
+ 0xB4, /* 5VSB High Limit in DataSheet */
+ 0xB6 /* VBAT High Limit in DataSheet */
+};
+static const u8 W83792D_REG_IN_MIN[9] = {
+ 0x2C, /* Vcore A Low Limit in DataSheet */
+ 0x2E, /* Vcore B Low Limit in DataSheet */
+ 0x30, /* VIN0 Low Limit in DataSheet */
+ 0x32, /* VIN1 Low Limit in DataSheet */
+ 0x34, /* VIN2 Low Limit in DataSheet */
+ 0x36, /* VIN3 Low Limit in DataSheet */
+ 0x38, /* 5VCC Low Limit in DataSheet */
+ 0xB5, /* 5VSB Low Limit in DataSheet */
+ 0xB7 /* VBAT Low Limit in DataSheet */
+};
+static const u8 W83792D_REG_FAN[7] = {
+ 0x28, /* FAN 1 Count in DataSheet */
+ 0x29, /* FAN 2 Count in DataSheet */
+ 0x2A, /* FAN 3 Count in DataSheet */
+ 0xB8, /* FAN 4 Count in DataSheet */
+ 0xB9, /* FAN 5 Count in DataSheet */
+ 0xBA, /* FAN 6 Count in DataSheet */
+ 0xBE /* FAN 7 Count in DataSheet */
+};
+static const u8 W83792D_REG_FAN_MIN[7] = {
+ 0x3B, /* FAN 1 Count Low Limit in DataSheet */
+ 0x3C, /* FAN 2 Count Low Limit in DataSheet */
+ 0x3D, /* FAN 3 Count Low Limit in DataSheet */
+ 0xBB, /* FAN 4 Count Low Limit in DataSheet */
+ 0xBC, /* FAN 5 Count Low Limit in DataSheet */
+ 0xBD, /* FAN 6 Count Low Limit in DataSheet */
+ 0xBF /* FAN 7 Count Low Limit in DataSheet */
+};
+#define W83792D_REG_FAN_CFG 0x84 /* FAN Configuration in DataSheet */
+static const u8 W83792D_REG_FAN_DIV[4] = {
+ 0x47, /* contains FAN2 and FAN1 Divisor */
+ 0x5B, /* contains FAN4 and FAN3 Divisor */
+ 0x5C, /* contains FAN6 and FAN5 Divisor */
+ 0x9E /* contains FAN7 Divisor. */
+};
+static const u8 W83792D_REG_PWM[7] = {
+ 0x81, /* FAN 1 Duty Cycle, be used to control */
+ 0x83, /* FAN 2 Duty Cycle, be used to control */
+ 0x94, /* FAN 3 Duty Cycle, be used to control */
+ 0xA3, /* FAN 4 Duty Cycle, be used to control */
+ 0xA4, /* FAN 5 Duty Cycle, be used to control */
+ 0xA5, /* FAN 6 Duty Cycle, be used to control */
+ 0xA6 /* FAN 7 Duty Cycle, be used to control */
+};
+#define W83792D_REG_BANK 0x4E
+#define W83792D_REG_TEMP2_CONFIG 0xC2
+#define W83792D_REG_TEMP3_CONFIG 0xCA
+
+static const u8 W83792D_REG_TEMP1[3] = {
+ 0x27, /* TEMP 1 in DataSheet */
+ 0x39, /* TEMP 1 Over in DataSheet */
+ 0x3A, /* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83792D_REG_TEMP_ADD[2][6] = {
+ { 0xC0, /* TEMP 2 in DataSheet */
+ 0xC1, /* TEMP 2(0.5 deg) in DataSheet */
+ 0xC5, /* TEMP 2 Over High part in DataSheet */
+ 0xC6, /* TEMP 2 Over Low part in DataSheet */
+ 0xC3, /* TEMP 2 Thyst High part in DataSheet */
+ 0xC4 }, /* TEMP 2 Thyst Low part in DataSheet */
+ { 0xC8, /* TEMP 3 in DataSheet */
+ 0xC9, /* TEMP 3(0.5 deg) in DataSheet */
+ 0xCD, /* TEMP 3 Over High part in DataSheet */
+ 0xCE, /* TEMP 3 Over Low part in DataSheet */
+ 0xCB, /* TEMP 3 Thyst High part in DataSheet */
+ 0xCC } /* TEMP 3 Thyst Low part in DataSheet */
+};
+
+static const u8 W83792D_REG_THERMAL[3] = {
+ 0x85, /* SmartFanI: Fan1 target value */
+ 0x86, /* SmartFanI: Fan2 target value */
+ 0x96 /* SmartFanI: Fan3 target value */
+};
+
+static const u8 W83792D_REG_TOLERANCE[3] = {
+ 0x87, /* (bit3-0)SmartFan Fan1 tolerance */
+ 0x87, /* (bit7-4)SmartFan Fan2 tolerance */
+ 0x97 /* (bit3-0)SmartFan Fan3 tolerance */
+};
+
+static const u8 W83792D_REG_POINTS[3][4] = {
+ { 0x85, /* SmartFanII: Fan1 temp point 1 */
+ 0xE3, /* SmartFanII: Fan1 temp point 2 */
+ 0xE4, /* SmartFanII: Fan1 temp point 3 */
+ 0xE5 }, /* SmartFanII: Fan1 temp point 4 */
+ { 0x86, /* SmartFanII: Fan2 temp point 1 */
+ 0xE6, /* SmartFanII: Fan2 temp point 2 */
+ 0xE7, /* SmartFanII: Fan2 temp point 3 */
+ 0xE8 }, /* SmartFanII: Fan2 temp point 4 */
+ { 0x96, /* SmartFanII: Fan3 temp point 1 */
+ 0xE9, /* SmartFanII: Fan3 temp point 2 */
+ 0xEA, /* SmartFanII: Fan3 temp point 3 */
+ 0xEB } /* SmartFanII: Fan3 temp point 4 */
+};
+
+static const u8 W83792D_REG_LEVELS[3][4] = {
+ { 0x88, /* (bit3-0) SmartFanII: Fan1 Non-Stop */
+ 0x88, /* (bit7-4) SmartFanII: Fan1 Level 1 */
+ 0xE0, /* (bit7-4) SmartFanII: Fan1 Level 2 */
+ 0xE0 }, /* (bit3-0) SmartFanII: Fan1 Level 3 */
+ { 0x89, /* (bit3-0) SmartFanII: Fan2 Non-Stop */
+ 0x89, /* (bit7-4) SmartFanII: Fan2 Level 1 */
+ 0xE1, /* (bit7-4) SmartFanII: Fan2 Level 2 */
+ 0xE1 }, /* (bit3-0) SmartFanII: Fan2 Level 3 */
+ { 0x98, /* (bit3-0) SmartFanII: Fan3 Non-Stop */
+ 0x98, /* (bit7-4) SmartFanII: Fan3 Level 1 */
+ 0xE2, /* (bit7-4) SmartFanII: Fan3 Level 2 */
+ 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */
+};
+
+#define W83792D_REG_CONFIG 0x40
+#define W83792D_REG_VID_FANDIV 0x47
+#define W83792D_REG_CHIPID 0x49
+#define W83792D_REG_WCHIPID 0x58
+#define W83792D_REG_CHIPMAN 0x4F
+#define W83792D_REG_PIN 0x4B
+#define W83792D_REG_I2C_SUBADDR 0x4A
+
+#define W83792D_REG_ALARM1 0xA9 /* realtime status register1 */
+#define W83792D_REG_ALARM2 0xAA /* realtime status register2 */
+#define W83792D_REG_ALARM3 0xAB /* realtime status register3 */
+#define W83792D_REG_CHASSIS 0x42 /* Bit 5: Case Open status bit */
+#define W83792D_REG_CHASSIS_CLR 0x44 /* Bit 7: Case Open CLR_CHS/Reset bit */
+
+/* control in0/in1 's limit modifiability */
+#define W83792D_REG_VID_IN_B 0x17
+
+#define W83792D_REG_VBAT 0x5D
+#define W83792D_REG_I2C_ADDR 0x48
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ Fixing this is just not worth it. */
+#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
+ ((((nr)==6)||((nr)==7))?(val*6):(val*4)))
+#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
+ ((((nr)==6)||((nr)==7))?(val/6):(val/4)))
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 255;
+ rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+ return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \
+ ((val) == 255 ? 0 : \
+ 1350000 / ((val) * (div))))
+
+/* for temp1 */
+#define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+ : (val)) / 1000, 0, 0xff))
+#define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+/* for temp2 and temp3, because they need addtional resolution */
+#define TEMP_ADD_FROM_REG(val1, val2) \
+ ((((val1) & 0x80 ? (val1)-0x100 \
+ : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
+#define TEMP_ADD_TO_REG_HIGH(val) \
+ (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+ : (val)) / 1000, 0, 0xff))
+#define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00)
+
+#define PWM_FROM_REG(val) (val)
+#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
+#define DIV_FROM_REG(val) (1 << (val))
+
+static inline u8
+DIV_TO_REG(long val)
+{
+ int i;
+ val = SENSORS_LIMIT(val, 1, 128) >> 1;
+ for (i = 0; i < 6; i++) {
+ if (val == 0)
+ break;
+ val >>= 1;
+ }
+ return ((u8) i);
+}
+
+struct w83792d_data {
+ struct i2c_client client;
+ struct class_device *class_dev;
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ /* array of 2 pointers to subclients */
+ struct i2c_client *lm75[2];
+
+ u8 in[9]; /* Register value */
+ u8 in_max[9]; /* Register value */
+ u8 in_min[9]; /* Register value */
+ u8 low_bits[2]; /* Additional resolution to voltage in0-6 */
+ u8 fan[7]; /* Register value */
+ u8 fan_min[7]; /* Register value */
+ u8 temp1[3]; /* current, over, thyst */
+ u8 temp_add[2][6]; /* Register value */
+ u8 fan_div[7]; /* Register encoding, shifted right */
+ u8 pwm[7]; /* We only consider the first 3 set of pwm,
+ although 792 chip has 7 set of pwm. */
+ u8 pwmenable[3];
+ u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */
+ u32 alarms; /* realtime status register encoding,combined */
+ u8 chassis; /* Chassis status */
+ u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */
+ u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */
+ u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */
+ u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */
+ u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */
+};
+
+static int w83792d_attach_adapter(struct i2c_adapter *adapter);
+static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83792d_detach_client(struct i2c_client *client);
+
+static int w83792d_read_value(struct i2c_client *client, u8 register);
+static int w83792d_write_value(struct i2c_client *client, u8 register,
+ u8 value);
+static struct w83792d_data *w83792d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
+#endif
+
+static void w83792d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83792d_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83792d",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = w83792d_attach_adapter,
+ .detach_client = w83792d_detach_client,
+};
+
+static long in_count_from_reg(int nr, struct w83792d_data *data)
+{
+ u16 vol_count = data->in[nr];
+ u16 low_bits = 0;
+ vol_count = (vol_count << 2);
+ switch (nr)
+ {
+ case 0: /* vin0 */
+ low_bits = (data->low_bits[0]) & 0x03;
+ break;
+ case 1: /* vin1 */
+ low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
+ break;
+ case 2: /* vin2 */
+ low_bits = ((data->low_bits[0]) & 0x30) >> 4;
+ break;
+ case 3: /* vin3 */
+ low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
+ break;
+ case 4: /* vin4 */
+ low_bits = (data->low_bits[1]) & 0x03;
+ break;
+ case 5: /* vin5 */
+ low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
+ break;
+ case 6: /* vin6 */
+ low_bits = ((data->low_bits[1]) & 0x30) >> 4;
+ default:
+ break;
+ }
+ vol_count = vol_count | low_bits;
+ return vol_count;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
+}
+
+#define show_in_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+ int nr = sensor_attr->index; \
+ struct w83792d_data *data = w83792d_update_device(dev); \
+ return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \
+}
+
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+ int nr = sensor_attr->index; \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83792d_data *data = i2c_get_clientdata(client); \
+ u32 val; \
+ \
+ val = simple_strtoul(buf, NULL, 10); \
+ data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
+ w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+ \
+ return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_reg(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \
+ NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, store_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, store_in_max, offset);
+
+sysfs_in_reg(0);
+sysfs_in_reg(1);
+sysfs_in_reg(2);
+sysfs_in_reg(3);
+sysfs_in_reg(4);
+sysfs_in_reg(5);
+sysfs_in_reg(6);
+sysfs_in_reg(7);
+sysfs_in_reg(8);
+
+#define device_create_file_in(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \
+} while (0)
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+ int nr = sensor_attr->index - 1; \
+ struct w83792d_data *data = w83792d_update_device(dev); \
+ return sprintf(buf,"%d\n", \
+ FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
+ data->fan_min[nr]);
+
+ return count;
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+ determined in part by the fan divisor. This follows the principle of
+ least suprise; the user doesn't expect the fan minimum to change just
+ because the divisor changed. */
+static ssize_t
+store_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ unsigned long min;
+ /*u8 reg;*/
+ u8 fan_div_reg = 0;
+ u8 tmp_fan_div;
+
+ /* Save fan_min */
+ min = FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr]));
+
+ data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+ fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
+ fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8;
+ tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70)
+ : ((data->fan_div[nr]) & 0x07);
+ w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1],
+ fan_div_reg | tmp_fan_div);
+
+ /* Restore fan_min */
+ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+ w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+ return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+ offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, store_fan_div, offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, store_fan_min, offset);
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+sysfs_fan(5);
+sysfs_fan(6);
+sysfs_fan(7);
+
+#define device_create_file_fan(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature1, includes measured value and limits */
+
+static ssize_t show_temp1(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ s32 val;
+
+ val = simple_strtol(buf, NULL, 10);
+
+ data->temp1[nr] = TEMP1_TO_REG(val);
+ w83792d_write_value(client, W83792D_REG_TEMP1[nr],
+ data->temp1[nr]);
+
+ return count;
+}
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1,
+ store_temp1, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1,
+ store_temp1, 2);
+
+#define device_create_file_temp1(client) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature2-3, includes measured value and limits */
+
+static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf,"%ld\n",
+ (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index],
+ data->temp_add[nr][index+1]));
+}
+
+static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ s32 val;
+
+ val = simple_strtol(buf, NULL, 10);
+
+ data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
+ data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
+ w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index],
+ data->temp_add[nr][index]);
+ w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1],
+ data->temp_add[nr][index+1]);
+
+ return count;
+}
+
+#define sysfs_temp23(name,idx) \
+static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \
+ idx, 0); \
+static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \
+ show_temp23, store_temp23, idx, 2); \
+static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp23, store_temp23, idx, 4);
+
+sysfs_temp23(temp2,0)
+sysfs_temp23(temp3,1)
+
+#define device_create_file_temp_add(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \
+device_create_file(&client->dev, \
+&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \
+} while (0)
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->alarms);
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+
+
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1]));
+}
+
+static ssize_t
+show_pwmenable(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ long pwm_enable_tmp = 1;
+
+ switch (data->pwmenable[nr]) {
+ case 0:
+ pwm_enable_tmp = 1; /* manual mode */
+ break;
+ case 1:
+ pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */
+ break;
+ case 2:
+ pwm_enable_tmp = 2; /* Smart Fan II */
+ break;
+ }
+
+ return sprintf(buf, "%ld\n", pwm_enable_tmp);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->pwm[nr] = PWM_TO_REG(val);
+ w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+
+ return count;
+}
+
+static ssize_t
+store_pwmenable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
+
+ val = simple_strtoul(buf, NULL, 10);
+ switch (val) {
+ case 1:
+ data->pwmenable[nr] = 0; /* manual mode */
+ break;
+ case 2:
+ data->pwmenable[nr] = 2; /* Smart Fan II */
+ break;
+ case 3:
+ data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */
+ break;
+ default:
+ return -EINVAL;
+ }
+ cfg1_tmp = data->pwmenable[0];
+ cfg2_tmp = (data->pwmenable[1]) << 2;
+ cfg3_tmp = (data->pwmenable[2]) << 4;
+ cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
+ fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
+ w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
+
+ return count;
+}
+
+#define sysfs_pwm(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm, store_pwm, offset); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+ show_pwmenable, store_pwmenable, offset); \
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwm(3);
+
+
+#define device_create_file_pwm(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \
+} while (0)
+
+#define device_create_file_pwmenable(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_mode[nr-1]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 pwm_mode_mask = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
+ pwm_mode_mask = w83792d_read_value(client,
+ W83792D_REG_PWM[nr]) & 0x7f;
+ w83792d_write_value(client, W83792D_REG_PWM[nr],
+ ((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
+
+ return count;
+}
+
+#define sysfs_pwm_mode(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \
+ show_pwm_mode, store_pwm_mode, offset);
+
+sysfs_pwm_mode(1);
+sysfs_pwm_mode(2);
+sysfs_pwm_mode(3);
+
+#define device_create_file_pwm_mode(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_regs_chassis(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->chassis);
+}
+
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+
+#define device_create_file_chassis(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis); \
+} while (0)
+
+
+static ssize_t
+show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->chassis_clear);
+}
+
+static ssize_t
+store_chassis_clear(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 temp1 = 0, temp2 = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
+ temp1 = ((data->chassis_clear) << 7) & 0x80;
+ temp2 = w83792d_read_value(client,
+ W83792D_REG_CHASSIS_CLR) & 0x7f;
+ w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
+
+ return count;
+}
+
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+ show_chassis_clear, store_chassis_clear);
+
+#define device_create_file_chassis_clear(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis_clear); \
+} while (0)
+
+
+
+/* For Smart Fan I / Thermal Cruise */
+static ssize_t
+show_thermal_cruise(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]);
+}
+
+static ssize_t
+store_thermal_cruise(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 target_tmp=0, target_mask=0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ target_tmp = val;
+ target_tmp = target_tmp & 0x7f;
+ target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
+ data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
+ w83792d_write_value(client, W83792D_REG_THERMAL[nr],
+ (data->thermal_cruise[nr]) | target_mask);
+
+ return count;
+}
+
+#define sysfs_thermal_cruise(offset) \
+static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \
+ show_thermal_cruise, store_thermal_cruise, offset);
+
+sysfs_thermal_cruise(1);
+sysfs_thermal_cruise(2);
+sysfs_thermal_cruise(3);
+
+#define device_create_file_thermal_cruise(client, offset) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_thermal_cruise##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan I/Thermal Cruise and Smart Fan II */
+static ssize_t
+show_tolerance(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]);
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 tol_tmp, tol_mask;
+
+ val = simple_strtoul(buf, NULL, 10);
+ tol_mask = w83792d_read_value(client,
+ W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
+ tol_tmp = SENSORS_LIMIT(val, 0, 15);
+ tol_tmp &= 0x0f;
+ data->tolerance[nr] = tol_tmp;
+ if (nr == 1) {
+ tol_tmp <<= 4;
+ }
+ w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
+ tol_mask | tol_tmp);
+
+ return count;
+}
+
+#define sysfs_tolerance(offset) \
+static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \
+ show_tolerance, store_tolerance, offset);
+
+sysfs_tolerance(1);
+sysfs_tolerance(2);
+sysfs_tolerance(3);
+
+#define device_create_file_tolerance(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan II */
+static ssize_t
+show_sf2_point(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]);
+}
+
+static ssize_t
+store_sf2_point(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr - 1;
+ int index = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 mask_tmp = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
+ mask_tmp = w83792d_read_value(client,
+ W83792D_REG_POINTS[index][nr]) & 0x80;
+ w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
+ mask_tmp|data->sf2_points[index][nr]);
+
+ return count;
+}
+
+#define sysfs_sf2_point(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \
+ show_sf2_point, store_sf2_point, offset, index);
+
+sysfs_sf2_point(1, 1); /* Fan1 */
+sysfs_sf2_point(2, 1); /* Fan1 */
+sysfs_sf2_point(3, 1); /* Fan1 */
+sysfs_sf2_point(4, 1); /* Fan1 */
+sysfs_sf2_point(1, 2); /* Fan2 */
+sysfs_sf2_point(2, 2); /* Fan2 */
+sysfs_sf2_point(3, 2); /* Fan2 */
+sysfs_sf2_point(4, 2); /* Fan2 */
+sysfs_sf2_point(1, 3); /* Fan3 */
+sysfs_sf2_point(2, 3); /* Fan3 */
+sysfs_sf2_point(3, 3); /* Fan3 */
+sysfs_sf2_point(4, 3); /* Fan3 */
+
+#define device_create_file_sf2_point(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_sf2_level(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n",
+ (((data->sf2_levels[index-1][nr]) * 100) / 15));
+}
+
+static ssize_t
+store_sf2_level(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 mask_tmp=0, level_tmp=0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
+ mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
+ & ((nr==3) ? 0xf0 : 0x0f);
+ if (nr==3) {
+ level_tmp = data->sf2_levels[index][nr];
+ } else {
+ level_tmp = data->sf2_levels[index][nr] << 4;
+ }
+ w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+
+ return count;
+}
+
+#define sysfs_sf2_level(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \
+ show_sf2_level, store_sf2_level, offset, index);
+
+sysfs_sf2_level(1, 1); /* Fan1 */
+sysfs_sf2_level(2, 1); /* Fan1 */
+sysfs_sf2_level(3, 1); /* Fan1 */
+sysfs_sf2_level(1, 2); /* Fan2 */
+sysfs_sf2_level(2, 2); /* Fan2 */
+sysfs_sf2_level(3, 2); /* Fan2 */
+sysfs_sf2_level(1, 3); /* Fan3 */
+sysfs_sf2_level(2, 3); /* Fan3 */
+sysfs_sf2_level(3, 3); /* Fan3 */
+
+#define device_create_file_sf2_level(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+/* This function is called when:
+ * w83792d_driver is inserted (when this module is loaded), for each
+ available adapter
+ * when a new adapter is inserted (and w83792d_driver is still present) */
+static int
+w83792d_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, w83792d_detect);
+}
+
+
+static int
+w83792d_create_subclient(struct i2c_adapter *adapter,
+ struct i2c_client *new_client, int addr,
+ struct i2c_client **sub_cli)
+{
+ int err;
+ struct i2c_client *sub_client;
+
+ (*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!(sub_client)) {
+ return -ENOMEM;
+ }
+ memset(sub_client, 0x00, sizeof(struct i2c_client));
+ sub_client->addr = 0x48 + addr;
+ i2c_set_clientdata(sub_client, NULL);
+ sub_client->adapter = adapter;
+ sub_client->driver = &w83792d_driver;
+ sub_client->flags = 0;
+ strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE);
+ if ((err = i2c_attach_client(sub_client))) {
+ dev_err(&new_client->dev, "subclient registration "
+ "at address 0x%x failed\n", sub_client->addr);
+ kfree(sub_client);
+ return err;
+ }
+ return 0;
+}
+
+
+static int
+w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
+ struct i2c_client *new_client)
+{
+ int i, id, err;
+ u8 val;
+ struct w83792d_data *data = i2c_get_clientdata(new_client);
+
+ id = i2c_adapter_id(adapter);
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48 ||
+ force_subclients[i] > 0x4f) {
+ dev_err(&new_client->dev, "invalid subclient "
+ "address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ err = -ENODEV;
+ goto ERROR_SC_0;
+ }
+ }
+ w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) << 4));
+ }
+
+ val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
+ if (!(val & 0x08)) {
+ err = w83792d_create_subclient(adapter, new_client, val & 0x7,
+ &data->lm75[0]);
+ if (err < 0)
+ goto ERROR_SC_0;
+ }
+ if (!(val & 0x80)) {
+ if ((data->lm75[0] != NULL) &&
+ ((val & 0x7) == ((val >> 4) & 0x7))) {
+ dev_err(&new_client->dev, "duplicate addresses 0x%x, "
+ "use force_subclient\n", data->lm75[0]->addr);
+ err = -ENODEV;
+ goto ERROR_SC_1;
+ }
+ err = w83792d_create_subclient(adapter, new_client,
+ (val >> 4) & 0x7, &data->lm75[1]);
+ if (err < 0)
+ goto ERROR_SC_1;
+ }
+
+ return 0;
+
+/* Undo inits in case of errors */
+
+ERROR_SC_1:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ERROR_SC_0:
+ return err;
+}
+
+
+static int
+w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int i = 0, val1 = 0, val2;
+ struct i2c_client *new_client;
+ struct w83792d_data *data;
+ int err = 0;
+ const char *client_name = "";
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ goto ERROR0;
+ }
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access w83792d_{read,write}_value. */
+
+ if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+ memset(data, 0, sizeof(struct w83792d_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ init_MUTEX(&data->lock);
+ new_client->adapter = adapter;
+ new_client->driver = &w83792d_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ /* The w83792d may be stuck in some other bank than bank 0. This may
+ make reading other information impossible. Specify a force=... or
+ force_*=... parameter, and the Winbond will be reset to the right
+ bank. */
+ if (kind < 0) {
+ if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) {
+ dev_warn(&new_client->dev, "Detection failed at step "
+ "3\n");
+ goto ERROR1;
+ }
+ val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
+ val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+ /* Check for Winbond ID if in bank 0 */
+ if (!(val1 & 0x07)) { /* is Bank0 */
+ if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
+ ((val1 & 0x80) && (val2 != 0x5c))) {
+ goto ERROR1;
+ }
+ }
+ /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
+ should match */
+ if (w83792d_read_value(new_client,
+ W83792D_REG_I2C_ADDR) != address) {
+ dev_warn(&new_client->dev, "Detection failed "
+ "at step 5\n");
+ goto ERROR1;
+ }
+ }
+
+ /* We have either had a force parameter, or we have already detected the
+ Winbond. Put it now into bank 0 and Vendor ID High Byte */
+ w83792d_write_value(new_client,
+ W83792D_REG_BANK,
+ (w83792d_read_value(new_client,
+ W83792D_REG_BANK) & 0x78) | 0x80);
+
+ /* Determine the chip type. */
+ if (kind <= 0) {
+ /* get vendor ID */
+ val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+ if (val2 != 0x5c) { /* the vendor is NOT Winbond */
+ goto ERROR1;
+ }
+ val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
+ if (val1 == 0x7a && address >= 0x2c) {
+ kind = w83792d;
+ } else {
+ if (kind == 0)
+ dev_warn(&new_client->dev,
+ "w83792d: Ignoring 'force' parameter for"
+ " unknown chip at adapter %d, address"
+ " 0x%02x\n", i2c_adapter_id(adapter),
+ address);
+ goto ERROR1;
+ }
+ }
+
+ if (kind == w83792d) {
+ client_name = "w83792d";
+ } else {
+ dev_err(&new_client->dev, "w83792d: Internal error: unknown"
+ " kind (%d)?!?", kind);
+ goto ERROR1;
+ }
+
+ /* Fill in the remaining client fields and put into the global list */
+ strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+ data->type = kind;
+
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR1;
+
+ if ((err = w83792d_detect_subclients(adapter, address,
+ kind, new_client)))
+ goto ERROR2;
+
+ /* Initialize the chip */
+ w83792d_init_client(new_client);
+
+ /* A few vars need to be filled upon startup */
+ for (i = 1; i <= 7; i++) {
+ data->fan_min[i - 1] = w83792d_read_value(new_client,
+ W83792D_REG_FAN_MIN[i]);
+ }
+
+ /* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+ device_create_file_in(new_client, 0);
+ device_create_file_in(new_client, 1);
+ device_create_file_in(new_client, 2);
+ device_create_file_in(new_client, 3);
+ device_create_file_in(new_client, 4);
+ device_create_file_in(new_client, 5);
+ device_create_file_in(new_client, 6);
+ device_create_file_in(new_client, 7);
+ device_create_file_in(new_client, 8);
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ device_create_file_fan(new_client, 3);
+ device_create_file_fan(new_client, 4);
+ device_create_file_fan(new_client, 5);
+ device_create_file_fan(new_client, 6);
+ device_create_file_fan(new_client, 7);
+
+ device_create_file_temp1(new_client); /* Temp1 */
+ device_create_file_temp_add(new_client, 2); /* Temp2 */
+ device_create_file_temp_add(new_client, 3); /* Temp3 */
+
+ device_create_file_alarms(new_client);
+
+ device_create_file_pwm(new_client, 1);
+ device_create_file_pwm(new_client, 2);
+ device_create_file_pwm(new_client, 3);
+
+ device_create_file_pwmenable(new_client, 1);
+ device_create_file_pwmenable(new_client, 2);
+ device_create_file_pwmenable(new_client, 3);
+
+ device_create_file_pwm_mode(new_client, 1);
+ device_create_file_pwm_mode(new_client, 2);
+ device_create_file_pwm_mode(new_client, 3);
+
+ device_create_file_chassis(new_client);
+ device_create_file_chassis_clear(new_client);
+
+ device_create_file_thermal_cruise(new_client, 1);
+ device_create_file_thermal_cruise(new_client, 2);
+ device_create_file_thermal_cruise(new_client, 3);
+
+ device_create_file_tolerance(new_client, 1);
+ device_create_file_tolerance(new_client, 2);
+ device_create_file_tolerance(new_client, 3);
+
+ device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */
+
+ device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */
+ device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */
+ device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */
+
+ return 0;
+
+ERROR3:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ if (data->lm75[1] != NULL) {
+ i2c_detach_client(data->lm75[1]);
+ kfree(data->lm75[1]);
+ }
+ERROR2:
+ i2c_detach_client(new_client);
+ERROR1:
+ kfree(data);
+ERROR0:
+ return err;
+}
+
+static int
+w83792d_detach_client(struct i2c_client *client)
+{
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ int err;
+
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ /* main client */
+ if (data)
+ kfree(data);
+ /* subclient */
+ else
+ kfree(client);
+
+ return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+ bank switches. ISA access must always be locked explicitly!
+ We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
+ would slow down the W83792D access and should not be necessary.
+ There are some ugly typecasts here, but the good news is - they should
+ nowhere else be necessary! */
+static int
+w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+ int res=0;
+ res = i2c_smbus_read_byte_data(client, reg);
+
+ return res;
+}
+
+static int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ i2c_smbus_write_byte_data(client, reg, value);
+ return 0;
+}
+
+/* Called when we have found a new W83792D. It should set limits, etc. */
+static void
+w83792d_init_client(struct i2c_client *client)
+{
+ u8 temp2_cfg, temp3_cfg, vid_in_b;
+
+ if (init) {
+ w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
+ }
+ /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
+ W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
+ vin0/vin1 can be modified by user;
+ W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
+ vin0/vin1 auto-updated, can NOT be modified by user. */
+ vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
+ w83792d_write_value(client, W83792D_REG_VID_IN_B,
+ vid_in_b & 0xbf);
+
+ temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG);
+ temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG);
+ w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG,
+ temp2_cfg & 0xe6);
+ w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG,
+ temp3_cfg & 0xe6);
+
+ /* Start monitoring */
+ w83792d_write_value(client, W83792D_REG_CONFIG,
+ (w83792d_read_value(client,
+ W83792D_REG_CONFIG) & 0xf7)
+ | 0x01);
+}
+
+static struct w83792d_data *w83792d_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ int i, j;
+ u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
+
+ down(&data->update_lock);
+
+ if (time_after
+ (jiffies - data->last_updated, (unsigned long) (HZ * 3))
+ || time_before(jiffies, data->last_updated) || !data->valid) {
+ dev_dbg(dev, "Starting device update\n");
+
+ /* Update the voltages measured value and limits */
+ for (i = 0; i < 9; i++) {
+ data->in[i] = w83792d_read_value(client,
+ W83792D_REG_IN[i]);
+ data->in_max[i] = w83792d_read_value(client,
+ W83792D_REG_IN_MAX[i]);
+ data->in_min[i] = w83792d_read_value(client,
+ W83792D_REG_IN_MIN[i]);
+ }
+ data->low_bits[0] = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS1);
+ data->low_bits[1] = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS2);
+ for (i = 0; i < 7; i++) {
+ /* Update the Fan measured value and limits */
+ data->fan[i] = w83792d_read_value(client,
+ W83792D_REG_FAN[i]);
+ data->fan_min[i] = w83792d_read_value(client,
+ W83792D_REG_FAN_MIN[i]);
+ /* Update the PWM/DC Value and PWM/DC flag */
+ pwm_array_tmp[i] = w83792d_read_value(client,
+ W83792D_REG_PWM[i]);
+ data->pwm[i] = pwm_array_tmp[i] & 0x0f;
+ data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+ }
+
+ reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
+ data->pwmenable[0] = reg_tmp & 0x03;
+ data->pwmenable[1] = (reg_tmp>>2) & 0x03;
+ data->pwmenable[2] = (reg_tmp>>4) & 0x03;
+
+ for (i = 0; i < 3; i++) {
+ data->temp1[i] = w83792d_read_value(client,
+ W83792D_REG_TEMP1[i]);
+ }
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 6; j++) {
+ data->temp_add[i][j] = w83792d_read_value(
+ client,W83792D_REG_TEMP_ADD[i][j]);
+ }
+ }
+
+ /* Update the Fan Divisor */
+ for (i = 0; i < 4; i++) {
+ reg_array_tmp[i] = w83792d_read_value(client,
+ W83792D_REG_FAN_DIV[i]);
+ }
+ data->fan_div[0] = reg_array_tmp[0] & 0x07;
+ data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
+ data->fan_div[2] = reg_array_tmp[1] & 0x07;
+ data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
+ data->fan_div[4] = reg_array_tmp[2] & 0x07;
+ data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
+ data->fan_div[6] = reg_array_tmp[3] & 0x07;
+
+ /* Update the realtime status */
+ data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
+ (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
+ (w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
+
+ /* Update CaseOpen status and it's CLR_CHS. */
+ data->chassis = (w83792d_read_value(client,
+ W83792D_REG_CHASSIS) >> 5) & 0x01;
+ data->chassis_clear = (w83792d_read_value(client,
+ W83792D_REG_CHASSIS_CLR) >> 7) & 0x01;
+
+ /* Update Thermal Cruise/Smart Fan I target value */
+ for (i = 0; i < 3; i++) {
+ data->thermal_cruise[i] =
+ w83792d_read_value(client,
+ W83792D_REG_THERMAL[i]) & 0x7f;
+ }
+
+ /* Update Smart Fan I/II tolerance */
+ reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]);
+ data->tolerance[0] = reg_tmp & 0x0f;
+ data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+ data->tolerance[2] = w83792d_read_value(client,
+ W83792D_REG_TOLERANCE[2]) & 0x0f;
+
+ /* Update Smart Fan II temperature points */
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 4; j++) {
+ data->sf2_points[i][j] = w83792d_read_value(
+ client,W83792D_REG_POINTS[i][j]) & 0x7f;
+ }
+ }
+
+ /* Update Smart Fan II duty cycle levels */
+ for (i = 0; i < 3; i++) {
+ reg_tmp = w83792d_read_value(client,
+ W83792D_REG_LEVELS[i][0]);
+ data->sf2_levels[i][0] = reg_tmp & 0x0f;
+ data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
+ reg_tmp = w83792d_read_value(client,
+ W83792D_REG_LEVELS[i][2]);
+ data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
+ data->sf2_levels[i][3] = reg_tmp & 0x0f;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+#ifdef DEBUG
+ w83792d_print_debug(data, dev);
+#endif
+
+ return data;
+}
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
+{
+ int i=0, j=0;
+ dev_dbg(dev, "==========The following is the debug message...========\n");
+ dev_dbg(dev, "9 set of Voltages: =====>\n");
+ for (i=0; i<9; i++) {
+ dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]);
+ dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
+ dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
+ }
+ dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
+ dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+ dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
+ for (i=0; i<7; i++) {
+ dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
+ dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
+ dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]);
+ dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]);
+ }
+ dev_dbg(dev, "3 set of Temperatures: =====>\n");
+ for (i=0; i<3; i++) {
+ dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]);
+ }
+
+ for (i=0; i<2; i++) {
+ for (j=0; j<6; j++) {
+ dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j,
+ data->temp_add[i][j]);
+ }
+ }
+
+ for (i=0; i<7; i++) {
+ dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
+ }
+ dev_dbg(dev, "==========End of the debug message...==================\n");
+ dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init
+sensors_w83792d_init(void)
+{
+ return i2c_add_driver(&w83792d_driver);
+}
+
+static void __exit
+sensors_w83792d_exit(void)
+{
+ i2c_del_driver(&w83792d_driver);
+}
+
+MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>");
+MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83792d_init);
+module_exit(sensors_w83792d_exit);
+
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 4469d52aba4c..133e34ab1d0a 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -36,7 +36,8 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* How many retries on register read error */
#define MAX_RETRIES 5
@@ -47,13 +48,12 @@
*/
static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(w83l785ts);
+I2C_CLIENT_INSMOD_1(w83l785ts);
/*
* The W83L785TS-S registers
@@ -105,6 +105,7 @@ static struct i2c_driver w83l785ts_driver = {
struct w83l785ts_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -140,7 +141,7 @@ static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, w83l785ts_detect);
+ return i2c_probe(adapter, &addr_data, w83l785ts_detect);
}
/*
@@ -239,11 +240,19 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -252,15 +261,15 @@ exit:
static int w83l785ts_detach_client(struct i2c_client *client)
{
+ struct w83l785ts_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index cd170395a8c7..71c5a854ac5d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -4,12 +4,8 @@
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
-obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
obj-y += busses/ chips/ algos/
-i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
-
-
ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index fb5b732238ed..df05df1a0ef6 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -519,8 +519,6 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_bit_algo = {
- .name = "Bit-shift algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = bit_xfer,
.functionality = bit_func,
};
@@ -541,8 +539,6 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
-
- adap->id |= i2c_bit_algo.id;
adap->algo = &i2c_bit_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index e6cae39f47aa..2db7bfc85225 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -713,8 +713,6 @@ static u32 iic_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm iic_algo = {
- .name = "ITE IIC algorithm",
- .id = I2C_ALGO_IIC,
.master_xfer = iic_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = iic_func,
@@ -738,8 +736,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
adap->name));
/* register new adapter to i2c module... */
-
- adap->id |= iic_algo.id;
adap->algo = &iic_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index cc3a952401f2..beb10edfe9c1 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -187,12 +187,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
int numbytes = 0;
int state;
int ret;
+ int timeout = 100;
- state = pca_status(adap);
- if ( state != 0xF8 ) {
- dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
- /* FIXME: what to do. Force stop ? */
- return -EREMOTEIO;
+ while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+ msleep(10);
+ }
+ if (state != 0xf8) {
+ dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
+ return -EIO;
}
DEB1("{{{ XFER %d messages\n", num);
@@ -354,8 +356,6 @@ static int pca_init(struct i2c_algo_pca_data *adap)
}
static struct i2c_algorithm pca_algo = {
- .name = "PCA9564 algorithm",
- .id = I2C_ALGO_PCA,
.master_xfer = pca_xfer,
.functionality = pca_func,
};
@@ -369,8 +369,6 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
int rval;
/* register new adapter to i2c module... */
-
- adap->id |= pca_algo.id;
adap->algo = &pca_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 8d087dac32af..6e498df1f717 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -459,8 +459,6 @@ static u32 pcf_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm pcf_algo = {
- .name = "PCF8584 algorithm",
- .id = I2C_ALGO_PCF,
.master_xfer = pcf_xfer,
.functionality = pcf_func,
};
@@ -476,8 +474,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
-
- adap->id |= pcf_algo.id;
adap->algo = &pcf_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index 422721b241e5..932c4fa86c73 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -149,7 +149,7 @@ static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
err = i2c_write(adap, p->buf, p->len);
}
- return err;
+ return (err < 0) ? err : i;
}
static u32 sgi_func(struct i2c_adapter *adap)
@@ -158,8 +158,6 @@ static u32 sgi_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm sgi_algo = {
- .name = "SGI algorithm",
- .id = I2C_ALGO_SGI,
.master_xfer = sgi_xfer,
.functionality = sgi_func,
};
@@ -169,7 +167,6 @@ static struct i2c_algorithm sgi_algo = {
*/
int i2c_sgi_add_bus(struct i2c_adapter *adap)
{
- adap->id |= sgi_algo.id;
adap->algo = &sgi_algo;
return i2c_add_adapter(adap);
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index f2785499237b..8ed5ad12552f 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -135,8 +135,6 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_sibyte_algo = {
- .name = "SiByte algorithm",
- .id = I2C_ALGO_SIBYTE,
.smbus_xfer = smbus_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = bit_func,
@@ -151,8 +149,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
/* register new adapter to i2c module... */
-
- i2c_adap->id |= i2c_sibyte_algo.id;
i2c_adap->algo = &i2c_sibyte_algo;
/* Set the frequency to 100 kHz */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 916ba5e40a96..8334496a7e0a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -144,6 +144,22 @@ config I2C_I810
This driver can also be built as a module. If so, the module
will be called i2c-i810.
+config I2C_PXA
+ tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
+ depends on I2C && EXPERIMENTAL && ARCH_PXA
+ help
+ If you have devices in the PXA I2C bus, say yes to this option.
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pxa.
+
+config I2C_PXA_SLAVE
+ bool "Intel PXA2XX I2C Slave comms support"
+ depends on I2C_PXA
+ help
+ Support I2C slave mode communications on the PXA I2C bus. This
+ is necessary for systems where the PXA may be a target on the
+ I2C bus.
+
config I2C_PIIX4
tristate "Intel PIIX4"
depends on I2C && PCI
@@ -182,14 +198,8 @@ config I2C_IOP3XX
will be called i2c-iop3xx.
config I2C_ISA
- tristate "ISA Bus support"
+ tristate
depends on I2C
- help
- If you say yes to this option, support will be included for i2c
- interfaces that are on the ISA bus.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-isa.
config I2C_ITE
tristate "ITE I2C Adapter"
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 42d6d814da72..980b3e983670 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
+obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f634a0780cf0..f021acd2674e 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -472,8 +472,6 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-i2c SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali1535_access,
.functionality = ali1535_func,
};
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index fdd881aee618..86947504aea1 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -366,8 +366,6 @@ static void ali1563_shutdown(struct pci_dev *dev)
}
static struct i2c_algorithm ali1563_algorithm = {
- .name = "Non-i2c SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali1563_access,
.functionality = ali1563_func,
};
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 0f781a1a3323..b3f50bff39a0 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -462,8 +462,6 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali15x3_access,
.functionality = ali15x3_func,
};
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6347ebc6fb53..6ad0603384b8 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -295,8 +295,6 @@ static u32 amd756_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = amd756_access,
.functionality = amd756_func,
};
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index d6644481d2a0..45ea24ba14d5 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -323,8 +323,6 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus 2.0 adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = amd8111_access,
.functionality = amd8111_func,
};
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index a7ff112e49bf..d06edce03bf4 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -283,8 +283,6 @@ au1550_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm au1550_algo = {
- .name = "Au1550 algorithm",
- .id = I2C_ALGO_AU1550,
.master_xfer = au1550_xfer,
.functionality = au1550_func,
};
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1ab41313ce51..709beab76609 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -535,8 +535,6 @@ static u32 i801_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = i801_access,
.functionality = i801_func,
};
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 93ca36dc777e..a3ed9590f028 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -627,8 +627,6 @@ static u32 iic_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm iic_algo = {
- .name = "IBM IIC algorithm",
- .id = I2C_ALGO_OCP,
.master_xfer = iic_xfer,
.functionality = iic_func
};
@@ -727,7 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
adap = &dev->adap;
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
- adap->id = I2C_HW_OCP | iic_algo.id;
+ adap->id = I2C_HW_OCP;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 6b682e903f09..7bd9102db701 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -399,8 +399,6 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm iop3xx_i2c_algo = {
- .name = "IOP3xx I2C algorithm",
- .id = I2C_ALGO_IOP3XX,
.master_xfer = iop3xx_i2c_master_xfer,
.algo_control = iop3xx_i2c_algo_control,
.functionality = iop3xx_i2c_func,
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 00e7f7157b75..bdc6806dafae 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -1,6 +1,8 @@
/*
- i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
+ i2c-isa.c - an i2c-core-like thing for ISA hardware monitoring chips
+ Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+
+ Based on the i2c-isa pseudo-adapter from the lm_sensors project
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
This program is free software; you can redistribute it and/or modify
@@ -18,30 +20,36 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
- on first sight very useful; almost no functionality is preserved.
- Except that it makes writing drivers for chips which can be on both
- the SMBus and the ISA bus very much easier. See lm78.c for an example
- of this. */
+/* This implements an i2c-core-like thing for ISA hardware monitoring
+ chips. Such chips are linked to the i2c subsystem for historical
+ reasons (because the early ISA hardware monitoring chips such as the
+ LM78 had both an I2C and an ISA interface). They used to be
+ registered with the main i2c-core, but as a first step in the
+ direction of a clean separation between I2C and ISA chip drivers,
+ we now have this separate core for ISA ones. It is significantly
+ more simple than the real one, of course, because we don't have to
+ handle multiple busses: there is only one (fake) ISA adapter.
+ It is worth noting that we still rely on i2c-core for some things
+ at the moment - but hopefully this won't last. */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/i2c.h>
+#include <linux/i2c-isa.h>
static u32 isa_func(struct i2c_adapter *adapter);
/* This is the actual algorithm we define */
static struct i2c_algorithm isa_algorithm = {
- .name = "ISA bus algorithm",
- .id = I2C_ALGO_ISA,
.functionality = isa_func,
};
/* There can only be one... */
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
+ .id = I2C_HW_ISA,
.class = I2C_CLASS_HWMON,
.algo = &isa_algorithm,
.name = "ISA main adapter",
@@ -53,17 +61,146 @@ static u32 isa_func(struct i2c_adapter *adapter)
return 0;
}
+
+/* Copied from i2c-core */
+static ssize_t show_adapter_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
+ return sprintf(buf, "%s\n", adap->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+
+static int i2c_isa_device_probe(struct device *dev)
+{
+ return -ENODEV;
+}
+
+static int i2c_isa_device_remove(struct device *dev)
+{
+ return 0;
+}
+
+
+/* We implement an interface which resembles i2c_{add,del}_driver,
+ but for i2c-isa drivers. We don't have to remember and handle lists
+ of drivers and adapters so this is much more simple, of course. */
+
+int i2c_isa_add_driver(struct i2c_driver *driver)
+{
+ int res;
+
+ /* Add the driver to the list of i2c drivers in the driver core */
+ driver->driver.name = driver->name;
+ driver->driver.bus = &i2c_bus_type;
+ driver->driver.probe = i2c_isa_device_probe;
+ driver->driver.remove = i2c_isa_device_remove;
+ res = driver_register(&driver->driver);
+ if (res)
+ return res;
+ dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
+
+ /* Now look for clients */
+ driver->attach_adapter(&isa_adapter);
+
+ return 0;
+}
+
+int i2c_isa_del_driver(struct i2c_driver *driver)
+{
+ struct list_head *item, *_n;
+ struct i2c_client *client;
+ int res;
+
+ /* Detach all clients belonging to this one driver */
+ list_for_each_safe(item, _n, &isa_adapter.clients) {
+ client = list_entry(item, struct i2c_client, list);
+ if (client->driver != driver)
+ continue;
+ dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
+ client->name, client->addr);
+ if ((res = driver->detach_client(client))) {
+ dev_err(&isa_adapter.dev, "Failed, driver "
+ "%s not unregistered!\n",
+ driver->name);
+ return res;
+ }
+ }
+
+ /* Get the driver off the core list */
+ driver_unregister(&driver->driver);
+ dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
+
+ return 0;
+}
+
+
static int __init i2c_isa_init(void)
{
- return i2c_add_adapter(&isa_adapter);
+ init_MUTEX(&isa_adapter.clist_lock);
+ INIT_LIST_HEAD(&isa_adapter.clients);
+
+ isa_adapter.nr = ANY_I2C_ISA_BUS;
+ isa_adapter.dev.parent = &platform_bus;
+ sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
+ isa_adapter.dev.driver = &i2c_adapter_driver;
+ isa_adapter.dev.release = &i2c_adapter_dev_release;
+ device_register(&isa_adapter.dev);
+ device_create_file(&isa_adapter.dev, &dev_attr_name);
+
+ /* Add this adapter to the i2c_adapter class */
+ memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
+ isa_adapter.class_dev.dev = &isa_adapter.dev;
+ isa_adapter.class_dev.class = &i2c_adapter_class;
+ strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
+ BUS_ID_SIZE);
+ class_device_register(&isa_adapter.class_dev);
+
+ dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
+
+ return 0;
}
static void __exit i2c_isa_exit(void)
{
- i2c_del_adapter(&isa_adapter);
+#ifdef DEBUG
+ struct list_head *item, *_n;
+ struct i2c_client *client = NULL;
+#endif
+
+ /* There should be no more active client */
+#ifdef DEBUG
+ dev_dbg(&isa_adapter.dev, "Looking for clients\n");
+ list_for_each_safe(item, _n, &isa_adapter.clients) {
+ client = list_entry(item, struct i2c_client, list);
+ dev_err(&isa_adapter.dev, "Driver %s still has an active "
+ "ISA client at 0x%x\n", client->driver->name,
+ client->addr);
+ }
+ if (client != NULL)
+ return;
+#endif
+
+ /* Clean up the sysfs representation */
+ dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
+ init_completion(&isa_adapter.dev_released);
+ init_completion(&isa_adapter.class_dev_released);
+ class_device_unregister(&isa_adapter.class_dev);
+ device_remove_file(&isa_adapter.dev, &dev_attr_name);
+ device_unregister(&isa_adapter.dev);
+
+ /* Wait for sysfs to drop all references */
+ dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
+ wait_for_completion(&isa_adapter.dev_released);
+ wait_for_completion(&isa_adapter.class_dev_released);
+
+ dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
}
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+EXPORT_SYMBOL(i2c_isa_add_driver);
+EXPORT_SYMBOL(i2c_isa_del_driver);
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("ISA bus access through i2c");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 94ae808314f7..eff5896ce865 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -87,12 +87,9 @@ static const char *__kw_state_names[] = {
};
#endif /* DEBUG */
-static int probe;
-
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
MODULE_LICENSE("GPL");
-module_param(probe, bool, 0);
#ifdef POLLED_MODE
/* Don't schedule, the g5 fan controller is too
@@ -498,8 +495,6 @@ keywest_func(struct i2c_adapter * adapter)
/* For now, we only handle combined mode (smbus) */
static struct i2c_algorithm keywest_algorithm = {
- .name = "Keywest i2c",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = keywest_smbus_xfer,
.master_xfer = keywest_xfer,
.functionality = keywest_func,
@@ -616,12 +611,10 @@ create_iface(struct device_node *np, struct device *dev)
for (i=0; i<nchan; i++) {
struct keywest_chan* chan = &iface->channels[i];
- u8 addr;
sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
chan->iface = iface;
chan->chan_no = i;
- chan->adapter.id = I2C_ALGO_SMBUS;
chan->adapter.algo = &keywest_algorithm;
chan->adapter.algo_data = NULL;
chan->adapter.client_register = NULL;
@@ -635,15 +628,6 @@ create_iface(struct device_node *np, struct device *dev)
chan->adapter.name);
i2c_set_adapdata(&chan->adapter, NULL);
}
- if (probe) {
- printk("Probe: ");
- for (addr = 0x00; addr <= 0x7f; addr++) {
- if (i2c_smbus_xfer(&chan->adapter,addr,
- 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- printk("%02x ", addr);
- }
- printk("\n");
- }
}
printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 9ad3e9262e8a..f065583ddcf1 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -272,8 +272,6 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
}
static struct i2c_algorithm mpc_algo = {
- .name = "MPC algorithm",
- .id = I2C_ALGO_MPC107,
.master_xfer = mpc_xfer,
.functionality = mpc_functionality,
};
@@ -281,7 +279,7 @@ static struct i2c_algorithm mpc_algo = {
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.name = "MPC adapter",
- .id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
+ .id = I2C_HW_MPC107,
.algo = &mpc_algo,
.class = I2C_CLASS_HWMON,
.timeout = 1,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5b852782d2f5..99abca45fece 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -423,18 +423,16 @@ static int
mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
- int i, rc = 0;
+ int i, rc;
for (i=0; i<num; i++)
- if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
- break;
+ if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0)
+ return rc;
- return rc;
+ return num;
}
static struct i2c_algorithm mv64xxx_i2c_algo = {
- .name = MV64XXX_I2C_CTLR_NAME " algorithm",
- .id = I2C_ALGO_MV64XXX,
.master_xfer = mv64xxx_i2c_xfer,
.functionality = mv64xxx_i2c_functionality,
};
@@ -523,7 +521,7 @@ mv64xxx_i2c_probe(struct device *dev)
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
- drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
+ drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 74eb89aa9350..fe9c0f42a2b7 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -98,11 +98,6 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_PEC 0x80
-/* Other settings */
-#define MAX_TIMEOUT 256
-
-
-
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data);
@@ -110,8 +105,6 @@ static u32 nforce2_func(struct i2c_adapter *adapter);
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = nforce2_access,
.functionality = nforce2_func,
};
@@ -131,7 +124,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec, temp;
unsigned char len = 0; /* to keep the compiler quiet */
- int timeout = 0;
int i;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
@@ -191,29 +183,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
- /*
- outb_p(command, NVIDIA_SMB_CMD);
- outb_p(data->word, NVIDIA_SMB_DATA);
- outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
- protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec;
- read_write = I2C_SMBUS_READ;
- break;
- */
case I2C_SMBUS_BLOCK_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
return -1;
- /*
- protocol |= pec;
- len = min_t(u8, data->block[0], 31);
- outb_p(command, NVIDIA_SMB_CMD);
- outb_p(len, NVIDIA_SMB_BCNT);
- for (i = 0; i < len; i++)
- outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i);
- protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec;
- read_write = I2C_SMBUS_READ;
- break;
- */
case I2C_SMBUS_WORD_DATA_PEC:
case I2C_SMBUS_BLOCK_DATA_PEC:
@@ -232,12 +205,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
temp = inb_p(NVIDIA_SMB_STS);
-#if 0
- do {
- i2c_do_pause(1);
- temp = inb_p(NVIDIA_SMB_STS);
- } while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
-#endif
if (~temp & NVIDIA_SMB_STS_DONE) {
udelay(500);
temp = inb_p(NVIDIA_SMB_STS);
@@ -247,9 +214,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
temp = inb_p(NVIDIA_SMB_STS);
}
- if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE)
- || (temp & NVIDIA_SMB_STS_STATUS))
+ if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
+ dev_dbg(&adap->dev, "SMBus Timeout! (0x%02x)\n", temp);
return -1;
+ }
if (read_write == I2C_SMBUS_WRITE)
return 0;
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d34ee381ce1..6d48a4da7bed 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -399,8 +399,6 @@ static u32 piix4_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = piix4_access,
.functionality = piix4_func,
};
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
new file mode 100644
index 000000000000..fdf53ce04248
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -0,0 +1,1022 @@
+/*
+ * i2c_adap_pxa.c
+ *
+ * I2C adapter for the PXA I2C bus access.
+ *
+ * Copyright (C) 2002 Intrinsyc Software Inc.
+ * Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * History:
+ * Apr 2002: Initial version [CS]
+ * Jun 2002: Properly seperated algo/adap [FB]
+ * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
+ * Sep 2004: Major rework to ensure efficient bus handling [RMK]
+ * Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood]
+ * Feb 2005: Rework slave mode handling [RMK]
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-pxa.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/pxa-regs.h>
+
+struct pxa_i2c {
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ struct i2c_msg *msg;
+ unsigned int msg_num;
+ unsigned int msg_idx;
+ unsigned int msg_ptr;
+ unsigned int slave_addr;
+
+ struct i2c_adapter adap;
+#ifdef CONFIG_I2C_PXA_SLAVE
+ struct i2c_slave_client *slave;
+#endif
+
+ unsigned int irqlogidx;
+ u32 isrlog[32];
+ u32 icrlog[32];
+};
+
+/*
+ * I2C Slave mode address
+ */
+#define I2C_PXA_SLAVE_ADDR 0x1
+
+#ifdef DEBUG
+
+struct bits {
+ u32 mask;
+ const char *set;
+ const char *unset;
+};
+#define BIT(m, s, u) { .mask = m, .set = s, .unset = u }
+
+static inline void
+decode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
+{
+ printk("%s %08x: ", prefix, val);
+ while (num--) {
+ const char *str = val & bits->mask ? bits->set : bits->unset;
+ if (str)
+ printk("%s ", str);
+ bits++;
+ }
+}
+
+static const struct bits isr_bits[] = {
+ BIT(ISR_RWM, "RX", "TX"),
+ BIT(ISR_ACKNAK, "NAK", "ACK"),
+ BIT(ISR_UB, "Bsy", "Rdy"),
+ BIT(ISR_IBB, "BusBsy", "BusRdy"),
+ BIT(ISR_SSD, "SlaveStop", NULL),
+ BIT(ISR_ALD, "ALD", NULL),
+ BIT(ISR_ITE, "TxEmpty", NULL),
+ BIT(ISR_IRF, "RxFull", NULL),
+ BIT(ISR_GCAD, "GenCall", NULL),
+ BIT(ISR_SAD, "SlaveAddr", NULL),
+ BIT(ISR_BED, "BusErr", NULL),
+};
+
+static void decode_ISR(unsigned int val)
+{
+ decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val);
+ printk("\n");
+}
+
+static const struct bits icr_bits[] = {
+ BIT(ICR_START, "START", NULL),
+ BIT(ICR_STOP, "STOP", NULL),
+ BIT(ICR_ACKNAK, "ACKNAK", NULL),
+ BIT(ICR_TB, "TB", NULL),
+ BIT(ICR_MA, "MA", NULL),
+ BIT(ICR_SCLE, "SCLE", "scle"),
+ BIT(ICR_IUE, "IUE", "iue"),
+ BIT(ICR_GCD, "GCD", NULL),
+ BIT(ICR_ITEIE, "ITEIE", NULL),
+ BIT(ICR_IRFIE, "IRFIE", NULL),
+ BIT(ICR_BEIE, "BEIE", NULL),
+ BIT(ICR_SSDIE, "SSDIE", NULL),
+ BIT(ICR_ALDIE, "ALDIE", NULL),
+ BIT(ICR_SADIE, "SADIE", NULL),
+ BIT(ICR_UR, "UR", "ur"),
+};
+
+static void decode_ICR(unsigned int val)
+{
+ decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val);
+ printk("\n");
+}
+
+static unsigned int i2c_debug = DEBUG;
+
+static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
+{
+ dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
+}
+
+#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
+#else
+#define i2c_debug 0
+
+#define show_state(i2c) do { } while (0)
+#define decode_ISR(val) do { } while (0)
+#define decode_ICR(val) do { } while (0)
+#endif
+
+#define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0)
+
+static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
+
+static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
+{
+ unsigned int i;
+ printk("i2c: error: %s\n", why);
+ printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
+ i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
+ printk("i2c: ICR: %08x ISR: %08x\n"
+ "i2c: log: ", ICR, ISR);
+ for (i = 0; i < i2c->irqlogidx; i++)
+ printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
+ printk("\n");
+}
+
+static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
+{
+ return !(ICR & ICR_SCLE);
+}
+
+static void i2c_pxa_abort(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ/4;
+
+ if (i2c_pxa_is_slavemode(i2c)) {
+ dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__);
+ return;
+ }
+
+ while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) {
+ unsigned long icr = ICR;
+
+ icr &= ~ICR_START;
+ icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
+
+ ICR = icr;
+
+ show_state(i2c);
+
+ msleep(1);
+ }
+
+ ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+}
+
+static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
+{
+ int timeout = DEF_TIMEOUT;
+
+ while (timeout-- && ISR & (ISR_IBB | ISR_UB)) {
+ if ((ISR & ISR_SAD) != 0)
+ timeout += 4;
+
+ msleep(2);
+ show_state(i2c);
+ }
+
+ if (timeout <= 0)
+ show_state(i2c);
+
+ return timeout <= 0 ? I2C_RETRY : 0;
+}
+
+static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ*4;
+
+ while (time_before(jiffies, timeout)) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, (long)jiffies, ISR, ICR, IBMR);
+
+ if (ISR & ISR_SAD) {
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
+ goto out;
+ }
+
+ /* wait for unit and bus being not busy, and we also do a
+ * quick check of the i2c lines themselves to ensure they've
+ * gone high...
+ */
+ if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) {
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
+ return 1;
+ }
+
+ msleep(1);
+ }
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
+ out:
+ return 0;
+}
+
+static int i2c_pxa_set_master(struct pxa_i2c *i2c)
+{
+ if (i2c_debug)
+ dev_dbg(&i2c->adap.dev, "setting to bus master\n");
+
+ if ((ISR & (ISR_UB | ISR_IBB)) != 0) {
+ dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
+ if (!i2c_pxa_wait_master(i2c)) {
+ dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
+ return I2C_RETRY;
+ }
+ }
+
+ ICR |= ICR_SCLE;
+ return 0;
+}
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ*1;
+
+ /* wait for stop */
+
+ show_state(i2c);
+
+ while (time_before(jiffies, timeout)) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, (long)jiffies, ISR, ICR, IBMR);
+
+ if ((ISR & (ISR_UB|ISR_IBB|ISR_SAD)) == ISR_SAD ||
+ (ICR & ICR_SCLE) == 0) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
+ return 1;
+ }
+
+ msleep(1);
+ }
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
+ return 0;
+}
+
+/*
+ * clear the hold on the bus, and take of anything else
+ * that has been configured
+ */
+static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
+{
+ show_state(i2c);
+
+ if (errcode < 0) {
+ udelay(100); /* simple delay */
+ } else {
+ /* we need to wait for the stop condition to end */
+
+ /* if we where in stop, then clear... */
+ if (ICR & ICR_STOP) {
+ udelay(100);
+ ICR &= ~ICR_STOP;
+ }
+
+ if (!i2c_pxa_wait_slave(i2c)) {
+ dev_err(&i2c->adap.dev, "%s: wait timedout\n",
+ __func__);
+ return;
+ }
+ }
+
+ ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA);
+ ICR &= ~ICR_SCLE;
+
+ if (i2c_debug) {
+ dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR);
+ decode_ICR(ICR);
+ }
+}
+#else
+#define i2c_pxa_set_slave(i2c, err) do { } while (0)
+#endif
+
+static void i2c_pxa_reset(struct pxa_i2c *i2c)
+{
+ pr_debug("Resetting I2C Controller Unit\n");
+
+ /* abort any transfer currently under way */
+ i2c_pxa_abort(i2c);
+
+ /* reset according to 9.8 */
+ ICR = ICR_UR;
+ ISR = I2C_ISR_INIT;
+ ICR &= ~ICR_UR;
+
+ ISAR = i2c->slave_addr;
+
+ /* set control register values */
+ ICR = I2C_ICR_INIT;
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ dev_info(&i2c->adap.dev, "Enabling slave mode\n");
+ ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE;
+#endif
+
+ i2c_pxa_set_slave(i2c, 0);
+
+ /* enable unit */
+ ICR |= ICR_IUE;
+ udelay(100);
+}
+
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+/*
+ * I2C EEPROM emulation.
+ */
+static struct i2c_eeprom_emu eeprom = {
+ .size = I2C_EEPROM_EMU_SIZE,
+ .watch = LIST_HEAD_INIT(eeprom.watch),
+};
+
+struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void)
+{
+ return &eeprom;
+}
+
+int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data,
+ unsigned int addr, unsigned int size,
+ struct i2c_eeprom_emu_watcher *watcher)
+{
+ struct i2c_eeprom_emu_watch *watch;
+ unsigned long flags;
+
+ if (addr + size > emu->size)
+ return -EINVAL;
+
+ watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL);
+ if (watch) {
+ watch->start = addr;
+ watch->end = addr + size - 1;
+ watch->ops = watcher;
+ watch->data = data;
+
+ local_irq_save(flags);
+ list_add(&watch->node, &emu->watch);
+ local_irq_restore(flags);
+ }
+
+ return watch ? 0 : -ENOMEM;
+}
+
+void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data,
+ struct i2c_eeprom_emu_watcher *watcher)
+{
+ struct i2c_eeprom_emu_watch *watch, *n;
+ unsigned long flags;
+
+ list_for_each_entry_safe(watch, n, &emu->watch, node) {
+ if (watch->ops == watcher && watch->data == data) {
+ local_irq_save(flags);
+ list_del(&watch->node);
+ local_irq_restore(flags);
+ kfree(watch);
+ }
+ }
+}
+
+static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+
+ eedbg(3, "i2c_eeprom_emu_event: %d\n", event);
+
+ switch (event) {
+ case I2C_SLAVE_EVENT_START_WRITE:
+ emu->seen_start = 1;
+ eedbg(2, "i2c_eeprom: write initiated\n");
+ break;
+
+ case I2C_SLAVE_EVENT_START_READ:
+ emu->seen_start = 0;
+ eedbg(2, "i2c_eeprom: read initiated\n");
+ break;
+
+ case I2C_SLAVE_EVENT_STOP:
+ emu->seen_start = 0;
+ eedbg(2, "i2c_eeprom: received stop\n");
+ break;
+
+ default:
+ eedbg(0, "i2c_eeprom: unhandled event\n");
+ break;
+ }
+}
+
+static int i2c_eeprom_emu_read(void *ptr)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+ int ret;
+
+ ret = emu->bytes[emu->ptr];
+ emu->ptr = (emu->ptr + 1) % emu->size;
+
+ return ret;
+}
+
+static void i2c_eeprom_emu_write(void *ptr, unsigned int val)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+ struct i2c_eeprom_emu_watch *watch;
+
+ if (emu->seen_start != 0) {
+ eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val);
+ emu->ptr = val;
+ emu->seen_start = 0;
+ return;
+ }
+
+ emu->bytes[emu->ptr] = val;
+
+ eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n",
+ emu->ptr, val);
+
+ list_for_each_entry(watch, &emu->watch, node) {
+ if (!watch->ops || !watch->ops->write)
+ continue;
+ if (watch->start <= emu->ptr && watch->end >= emu->ptr)
+ watch->ops->write(watch->data, emu->ptr, val);
+ }
+
+ emu->ptr = (emu->ptr + 1) % emu->size;
+}
+
+struct i2c_slave_client eeprom_client = {
+ .data = &eeprom,
+ .event = i2c_eeprom_emu_event,
+ .read = i2c_eeprom_emu_read,
+ .write = i2c_eeprom_emu_write
+};
+
+/*
+ * PXA I2C Slave mode
+ */
+
+static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ if (isr & ISR_BED) {
+ /* what should we do here? */
+ } else {
+ int ret = i2c->slave->read(i2c->slave->data);
+
+ IDBR = ret;
+ ICR |= ICR_TB; /* allow next byte */
+ }
+}
+
+static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ unsigned int byte = IDBR;
+
+ if (i2c->slave != NULL)
+ i2c->slave->write(i2c->slave->data, byte);
+
+ ICR |= ICR_TB;
+}
+
+static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
+{
+ int timeout;
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n",
+ (isr & ISR_RWM) ? 'r' : 't');
+
+ if (i2c->slave != NULL)
+ i2c->slave->event(i2c->slave->data,
+ (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE);
+
+ /*
+ * slave could interrupt in the middle of us generating a
+ * start condition... if this happens, we'd better back off
+ * and stop holding the poor thing up
+ */
+ ICR &= ~(ICR_START|ICR_STOP);
+ ICR |= ICR_TB;
+
+ timeout = 0x10000;
+
+ while (1) {
+ if ((IBMR & 2) == 2)
+ break;
+
+ timeout--;
+
+ if (timeout <= 0) {
+ dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
+ break;
+ }
+ }
+
+ ICR &= ~ICR_SCLE;
+}
+
+static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
+{
+ if (i2c_debug > 2)
+ dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n");
+
+ if (i2c->slave != NULL)
+ i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP);
+
+ if (i2c_debug > 2)
+ dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n");
+
+ /*
+ * If we have a master-mode message waiting,
+ * kick it off now that the slave has completed.
+ */
+ if (i2c->msg)
+ i2c_pxa_master_complete(i2c, I2C_RETRY);
+}
+#else
+static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ if (isr & ISR_BED) {
+ /* what should we do here? */
+ } else {
+ IDBR = 0;
+ ICR |= ICR_TB;
+ }
+}
+
+static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ ICR |= ICR_TB | ICR_ACKNAK;
+}
+
+static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
+{
+ int timeout;
+
+ /*
+ * slave could interrupt in the middle of us generating a
+ * start condition... if this happens, we'd better back off
+ * and stop holding the poor thing up
+ */
+ ICR &= ~(ICR_START|ICR_STOP);
+ ICR |= ICR_TB | ICR_ACKNAK;
+
+ timeout = 0x10000;
+
+ while (1) {
+ if ((IBMR & 2) == 2)
+ break;
+
+ timeout--;
+
+ if (timeout <= 0) {
+ dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
+ break;
+ }
+ }
+
+ ICR &= ~ICR_SCLE;
+}
+
+static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
+{
+ if (i2c->msg)
+ i2c_pxa_master_complete(i2c, I2C_RETRY);
+}
+#endif
+
+/*
+ * PXA I2C Master mode
+ */
+
+static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg)
+{
+ unsigned int addr = (msg->addr & 0x7f) << 1;
+
+ if (msg->flags & I2C_M_RD)
+ addr |= 1;
+
+ return addr;
+}
+
+static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
+{
+ u32 icr;
+
+ /*
+ * Step 1: target slave address into IDBR
+ */
+ IDBR = i2c_pxa_addr_byte(i2c->msg);
+
+ /*
+ * Step 2: initiate the write.
+ */
+ icr = ICR & ~(ICR_STOP | ICR_ALDIE);
+ ICR = icr | ICR_START | ICR_TB;
+}
+
+/*
+ * We are protected by the adapter bus semaphore.
+ */
+static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
+{
+ long timeout;
+ int ret;
+
+ /*
+ * Wait for the bus to become free.
+ */
+ ret = i2c_pxa_wait_bus_not_busy(i2c);
+ if (ret) {
+ dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n");
+ goto out;
+ }
+
+ /*
+ * Set master mode.
+ */
+ ret = i2c_pxa_set_master(i2c);
+ if (ret) {
+ dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret);
+ goto out;
+ }
+
+ spin_lock_irq(&i2c->lock);
+
+ i2c->msg = msg;
+ i2c->msg_num = num;
+ i2c->msg_idx = 0;
+ i2c->msg_ptr = 0;
+ i2c->irqlogidx = 0;
+
+ i2c_pxa_start_message(i2c);
+
+ spin_unlock_irq(&i2c->lock);
+
+ /*
+ * The rest of the processing occurs in the interrupt handler.
+ */
+ timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
+
+ /*
+ * We place the return code in i2c->msg_idx.
+ */
+ ret = i2c->msg_idx;
+
+ if (timeout == 0)
+ i2c_pxa_scream_blue_murder(i2c, "timeout");
+
+ out:
+ return ret;
+}
+
+/*
+ * i2c_pxa_master_complete - complete the message and wake up.
+ */
+static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
+{
+ i2c->msg_ptr = 0;
+ i2c->msg = NULL;
+ i2c->msg_idx ++;
+ i2c->msg_num = 0;
+ if (ret)
+ i2c->msg_idx = ret;
+ wake_up(&i2c->wait);
+}
+
+static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+
+ again:
+ /*
+ * If ISR_ALD is set, we lost arbitration.
+ */
+ if (isr & ISR_ALD) {
+ /*
+ * Do we need to do anything here? The PXA docs
+ * are vague about what happens.
+ */
+ i2c_pxa_scream_blue_murder(i2c, "ALD set");
+
+ /*
+ * We ignore this error. We seem to see spurious ALDs
+ * for seemingly no reason. If we handle them as I think
+ * they should, we end up causing an I2C error, which
+ * is painful for some systems.
+ */
+ return; /* ignore */
+ }
+
+ if (isr & ISR_BED) {
+ int ret = BUS_ERROR;
+
+ /*
+ * I2C bus error - either the device NAK'd us, or
+ * something more serious happened. If we were NAK'd
+ * on the initial address phase, we can retry.
+ */
+ if (isr & ISR_ACKNAK) {
+ if (i2c->msg_ptr == 0 && i2c->msg_idx == 0)
+ ret = I2C_RETRY;
+ else
+ ret = XFER_NAKED;
+ }
+ i2c_pxa_master_complete(i2c, ret);
+ } else if (isr & ISR_RWM) {
+ /*
+ * Read mode. We have just sent the address byte, and
+ * now we must initiate the transfer.
+ */
+ if (i2c->msg_ptr == i2c->msg->len - 1 &&
+ i2c->msg_idx == i2c->msg_num - 1)
+ icr |= ICR_STOP | ICR_ACKNAK;
+
+ icr |= ICR_ALDIE | ICR_TB;
+ } else if (i2c->msg_ptr < i2c->msg->len) {
+ /*
+ * Write mode. Write the next data byte.
+ */
+ IDBR = i2c->msg->buf[i2c->msg_ptr++];
+
+ icr |= ICR_ALDIE | ICR_TB;
+
+ /*
+ * If this is the last byte of the last message, send
+ * a STOP.
+ */
+ if (i2c->msg_ptr == i2c->msg->len &&
+ i2c->msg_idx == i2c->msg_num - 1)
+ icr |= ICR_STOP;
+ } else if (i2c->msg_idx < i2c->msg_num - 1) {
+ /*
+ * Next segment of the message.
+ */
+ i2c->msg_ptr = 0;
+ i2c->msg_idx ++;
+ i2c->msg++;
+
+ /*
+ * If we aren't doing a repeated start and address,
+ * go back and try to send the next byte. Note that
+ * we do not support switching the R/W direction here.
+ */
+ if (i2c->msg->flags & I2C_M_NOSTART)
+ goto again;
+
+ /*
+ * Write the next address.
+ */
+ IDBR = i2c_pxa_addr_byte(i2c->msg);
+
+ /*
+ * And trigger a repeated start, and send the byte.
+ */
+ icr &= ~ICR_ALDIE;
+ icr |= ICR_START | ICR_TB;
+ } else {
+ if (i2c->msg->len == 0) {
+ /*
+ * Device probes have a message length of zero
+ * and need the bus to be reset before it can
+ * be used again.
+ */
+ i2c_pxa_reset(i2c);
+ }
+ i2c_pxa_master_complete(i2c, 0);
+ }
+
+ i2c->icrlog[i2c->irqlogidx-1] = icr;
+
+ ICR = icr;
+ show_state(i2c);
+}
+
+static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+
+ /*
+ * Read the byte.
+ */
+ i2c->msg->buf[i2c->msg_ptr++] = IDBR;
+
+ if (i2c->msg_ptr < i2c->msg->len) {
+ /*
+ * If this is the last byte of the last
+ * message, send a STOP.
+ */
+ if (i2c->msg_ptr == i2c->msg->len - 1)
+ icr |= ICR_STOP | ICR_ACKNAK;
+
+ icr |= ICR_ALDIE | ICR_TB;
+ } else {
+ i2c_pxa_master_complete(i2c, 0);
+ }
+
+ i2c->icrlog[i2c->irqlogidx-1] = icr;
+
+ ICR = icr;
+}
+
+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pxa_i2c *i2c = dev_id;
+ u32 isr = ISR;
+
+ if (i2c_debug > 2 && 0) {
+ dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, isr, ICR, IBMR);
+ decode_ISR(isr);
+ }
+
+ if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
+ i2c->isrlog[i2c->irqlogidx++] = isr;
+
+ show_state(i2c);
+
+ /*
+ * Always clear all pending IRQs.
+ */
+ ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED);
+
+ if (isr & ISR_SAD)
+ i2c_pxa_slave_start(i2c, isr);
+ if (isr & ISR_SSD)
+ i2c_pxa_slave_stop(i2c);
+
+ if (i2c_pxa_is_slavemode(i2c)) {
+ if (isr & ISR_ITE)
+ i2c_pxa_slave_txempty(i2c, isr);
+ if (isr & ISR_IRF)
+ i2c_pxa_slave_rxfull(i2c, isr);
+ } else if (i2c->msg) {
+ if (isr & ISR_ITE)
+ i2c_pxa_irq_txempty(i2c, isr);
+ if (isr & ISR_IRF)
+ i2c_pxa_irq_rxfull(i2c, isr);
+ } else {
+ i2c_pxa_scream_blue_murder(i2c, "spurious irq");
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+ struct pxa_i2c *i2c = adap->algo_data;
+ int ret, i;
+
+ for (i = adap->retries; i >= 0; i--) {
+ ret = i2c_pxa_do_xfer(i2c, msgs, num);
+ if (ret != I2C_RETRY)
+ goto out;
+
+ if (i2c_debug)
+ dev_dbg(&adap->dev, "Retrying transmission\n");
+ udelay(100);
+ }
+ i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
+ ret = -EREMOTEIO;
+ out:
+ i2c_pxa_set_slave(i2c, ret);
+ return ret;
+}
+
+static struct i2c_algorithm i2c_pxa_algorithm = {
+ .name = "PXA-I2C-Algorithm",
+ .id = I2C_ALGO_PXA,
+ .master_xfer = i2c_pxa_xfer,
+};
+
+static struct pxa_i2c i2c_pxa = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
+ .adap = {
+ .name = "pxa2xx-i2c",
+ .id = I2C_ALGO_PXA,
+ .algo = &i2c_pxa_algorithm,
+ .retries = 5,
+ },
+};
+
+static int i2c_pxa_probe(struct device *dev)
+{
+ struct pxa_i2c *i2c = &i2c_pxa;
+ struct i2c_pxa_platform_data *plat = dev->platform_data;
+ int ret;
+
+#ifdef CONFIG_PXA27x
+ pxa_gpio_mode(GPIO117_I2CSCL_MD);
+ pxa_gpio_mode(GPIO118_I2CSDA_MD);
+ udelay(100);
+#endif
+
+ i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ i2c->slave = &eeprom_client;
+ if (plat) {
+ i2c->slave_addr = plat->slave_addr;
+ if (plat->slave)
+ i2c->slave = plat->slave;
+ }
+#endif
+
+ pxa_set_cken(CKEN14_I2C, 1);
+ ret = request_irq(IRQ_I2C, i2c_pxa_handler, SA_INTERRUPT,
+ "pxa2xx-i2c", i2c);
+ if (ret)
+ goto out;
+
+ i2c_pxa_reset(i2c);
+
+ i2c->adap.algo_data = i2c;
+ i2c->adap.dev.parent = dev;
+
+ ret = i2c_add_adapter(&i2c->adap);
+ if (ret < 0) {
+ printk(KERN_INFO "I2C: Failed to add bus\n");
+ goto err_irq;
+ }
+
+ dev_set_drvdata(dev, i2c);
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n",
+ i2c->adap.dev.bus_id, i2c->slave_addr);
+#else
+ printk(KERN_INFO "I2C: %s: PXA I2C adapter\n",
+ i2c->adap.dev.bus_id);
+#endif
+ return 0;
+
+ err_irq:
+ free_irq(IRQ_I2C, i2c);
+ out:
+ return ret;
+}
+
+static int i2c_pxa_remove(struct device *dev)
+{
+ struct pxa_i2c *i2c = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ i2c_del_adapter(&i2c->adap);
+ free_irq(IRQ_I2C, i2c);
+ pxa_set_cken(CKEN14_I2C, 0);
+
+ return 0;
+}
+
+static struct device_driver i2c_pxa_driver = {
+ .name = "pxa2xx-i2c",
+ .bus = &platform_bus_type,
+ .probe = i2c_pxa_probe,
+ .remove = i2c_pxa_remove,
+};
+
+static int __init i2c_adap_pxa_init(void)
+{
+ return driver_register(&i2c_pxa_driver);
+}
+
+static void i2c_adap_pxa_exit(void)
+{
+ return driver_unregister(&i2c_pxa_driver);
+}
+
+module_init(i2c_adap_pxa_init);
+module_exit(i2c_adap_pxa_exit);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index a3b38257cc3d..73a092fb0e7e 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -568,7 +568,6 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
/* i2c bus registration info */
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
- .name = "S3C2410-I2C-Algorithm",
.master_xfer = s3c24xx_i2c_xfer,
.functionality = s3c24xx_i2c_func,
};
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index bbd5e4e52f09..080318d6f54b 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -357,8 +357,6 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis5595_access,
.functionality = sis5595_func,
};
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index f58455e7689e..86f0f448fa0b 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -448,8 +448,6 @@ exit:
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis630_access,
.functionality = sis630_func,
};
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 6484792e23a1..ead2ff3cf60e 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -249,8 +249,6 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis96x_access,
.functionality = sis96x_func,
};
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 00d94e886955..73f481e93a36 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -109,8 +109,6 @@ static u32 stub_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.functionality = stub_func,
.smbus_xfer = stub_xfer,
};
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 6b5008005c6f..99d209e0485a 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -286,8 +286,6 @@ static u32 vt596_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = vt596_access,
.functionality = vt596_func,
};
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index a18bdd9aa7ba..a1d580e05361 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -395,8 +395,6 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
/* For now, we only handle combined mode (smbus) */
static struct i2c_algorithm scx200_acb_algorithm = {
- .name = "NatSemi SCx200 ACCESS.bus",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = scx200_acb_smbus_xfer,
.functionality = scx200_acb_func,
};
@@ -456,7 +454,7 @@ static int __init scx200_acb_create(int base, int index)
i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
- adapter->id = I2C_ALGO_SMBUS;
+ adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON;
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 43f70dbfc03f..6bd44a44cd28 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -2,17 +2,12 @@
# Miscellaneous I2C chip drivers configuration
#
-config I2C_SENSOR
- tristate
- default n
-
menu "Miscellaneous I2C Chip support"
depends on I2C
config SENSORS_DS1337
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1337 and DS1339 real-time clock chips.
@@ -23,7 +18,6 @@ config SENSORS_DS1337
config SENSORS_DS1374
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1374 real-time clock chips.
@@ -34,7 +28,6 @@ config SENSORS_DS1374
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get read-only access to the EEPROM data
available on modern memory DIMMs and Sony Vaio laptops. Such
@@ -46,7 +39,6 @@ config SENSORS_EEPROM
config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Philips PCF8574 and
PCF8574A chips.
@@ -67,7 +59,6 @@ config SENSORS_PCA9539
config SENSORS_PCF8591
tristate "Philips PCF8591"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Philips PCF8591 chips.
@@ -77,7 +68,6 @@ config SENSORS_PCF8591
config SENSORS_RTC8564
tristate "Epson 8564 RTC chip"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the Epson 8564 RTC chip.
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 82cf959989fd..9d3175c03395 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -17,7 +17,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/string.h>
#include <linux/rtc.h> /* get the user-level API */
#include <linux/bcd.h>
@@ -39,9 +38,8 @@
* Functions declaration
*/
static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-SENSORS_INSMOD_1(ds1337);
+I2C_CLIENT_INSMOD_1(ds1337);
static int ds1337_attach_adapter(struct i2c_adapter *adapter);
static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
@@ -227,7 +225,7 @@ int ds1337_do_command(int bus, int cmd, void *arg)
static int ds1337_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, ds1337_detect);
+ return i2c_probe(adapter, &addr_data, ds1337_detect);
}
/*
@@ -354,11 +352,8 @@ static int ds1337_detach_client(struct i2c_client *client)
int err;
struct ds1337_data *data = i2c_get_clientdata(client);
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
list_del(&data->list);
kfree(data);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index a445736d8838..0936327a946d 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -53,7 +53,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
static ulong ds1374_read_rtc(void)
@@ -166,7 +165,7 @@ static void ds1374_set_tlet(ulong arg)
"can't confirm time set from rtc chip\n");
}
-ulong new_time;
+static ulong new_time;
DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index a2da31b0dd7b..d58403a47908 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -33,15 +33,13 @@
#include <linux/sched.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(eeprom);
+I2C_CLIENT_INSMOD_1(eeprom);
/* Size of EEPROM in bytes */
@@ -153,21 +151,16 @@ static struct bin_attribute eeprom_attr = {
static int eeprom_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, eeprom_detect);
+ return i2c_probe(adapter, &addr_data, eeprom_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct eeprom_data *data;
int err = 0;
- /* prevent 24RF08 corruption */
- if (kind < 0)
- i2c_smbus_xfer(adapter, address, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL);
-
/* There are three ways we can read the EEPROM data:
(1) I2C block reads (faster, but unsupported by most adapters)
(2) Consecutive byte reads (100% overhead)
@@ -231,10 +224,8 @@ static int eeprom_detach_client(struct i2c_client *client)
int err;
err = i2c_detach_client(client);
- if (err) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ if (err)
return err;
- }
kfree(i2c_get_clientdata(client));
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 354a26295672..8ee56d4b3891 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1489,7 +1489,7 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
if (the_transceiver)
return 0;
- isp = kcalloc(1, sizeof *isp, GFP_KERNEL);
+ isp = kzalloc(sizeof *isp, GFP_KERNEL);
if (!isp)
return 0;
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 778d7e12859d..3f14528a52a9 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -42,7 +42,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
ulong
@@ -145,7 +144,7 @@ m41t00_set_tlet(ulong arg)
return;
}
-ulong new_time;
+static ulong new_time;
DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 0230375f72e5..9e1aeb69abf9 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -5,97 +5,60 @@
Based on i2c/chips/eeprom.c
- The MAX6875 has two EEPROM sections: config and user.
- At reset, the config EEPROM is read into the registers.
+ The MAX6875 has a bank of registers and two banks of EEPROM.
+ Address ranges are defined as follows:
+ * 0x0000 - 0x0046 = configuration registers
+ * 0x8000 - 0x8046 = configuration EEPROM
+ * 0x8100 - 0x82FF = user EEPROM
- This driver make 3 binary files available in sysfs:
- reg_config - direct access to the registers
- eeprom_config - acesses configuration eeprom space
- eeprom_user - free for application use
+ This driver makes the user EEPROM available for read.
- In our application, we put device serial & model numbers in user eeprom.
+ The registers & config EEPROM should be accessed via i2c-dev.
- Notes:
- 1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
- be overwritten, so the driver explicitly prevents that.
- 2) It's a good idea to keep the config (0x45) locked in config EEPROM.
- You can temporarily enable config writes by changing register 0x45.
+ The MAX6875 ignores the lowest address bit, so each chip responds to
+ two addresses - 0x50/0x51 and 0x52/0x53.
+
+ Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
+ address, so this driver is destructive if loaded for the wrong EEPROM 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; version 2 of the License.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <asm/semaphore.h>
-/* Addresses to scan */
-/* No address scanned by default, as this could corrupt standard EEPROMS. */
+/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
/* Insmod parameters */
-SENSORS_INSMOD_1(max6875);
-
-/* this param will prevent 'accidental' writes to the eeprom */
-static int allow_write = 0;
-module_param(allow_write, int, 0);
-MODULE_PARM_DESC(allow_write,
- "Enable write access:\n"
- "*0: Read only\n"
- " 1: Read/Write access");
+I2C_CLIENT_INSMOD_1(max6875);
/* The MAX6875 can only read/write 16 bytes at a time */
#define SLICE_SIZE 16
#define SLICE_BITS 4
-/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
-#define CONFIG_EEPROM_BASE 0x8000
-#define CONFIG_EEPROM_SIZE 0x0046
-#define CONFIG_EEPROM_SLICES 5
-
/* USER EEPROM is at addresses 0x8100 - 0x82FF */
#define USER_EEPROM_BASE 0x8100
#define USER_EEPROM_SIZE 0x0200
#define USER_EEPROM_SLICES 32
/* MAX6875 commands */
-#define MAX6875_CMD_BLOCK_WRITE 0x83
-#define MAX6875_CMD_BLOCK_READ 0x84
-#define MAX6875_CMD_REBOOT 0x88
-
-enum max6875_area_type {
- max6875_register_config=0,
- max6875_eeprom_config,
- max6875_eeprom_user,
- max6857_max
-};
-
-struct eeprom_block {
- enum max6875_area_type type;
- u8 slices;
- u32 size;
- u32 valid;
- u32 base;
- unsigned long *updated;
- u8 *data;
-};
+#define MAX6875_CMD_BLK_READ 0x84
/* Each client has this additional data */
struct max6875_data {
struct i2c_client client;
struct semaphore update_lock;
- struct eeprom_block blocks[max6857_max];
- /* the above structs point into the arrays below */
- u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
- unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+
+ u32 valid;
+ u8 data[USER_EEPROM_SIZE];
+ unsigned long last_updated[USER_EEPROM_SLICES];
};
static int max6875_attach_adapter(struct i2c_adapter *adapter);
@@ -111,337 +74,160 @@ static struct i2c_driver max6875_driver = {
.detach_client = max6875_detach_client,
};
-static int max6875_update_slice(struct i2c_client *client,
- struct eeprom_block *blk,
- int slice)
+static void max6875_update_slice(struct i2c_client *client, int slice)
{
struct max6875_data *data = i2c_get_clientdata(client);
- int i, j, addr, count;
- u8 rdbuf[SLICE_SIZE];
- int retval = 0;
+ int i, j, addr;
+ u8 *buf;
- if (slice >= blk->slices)
- return -1;
+ if (slice >= USER_EEPROM_SLICES)
+ return;
down(&data->update_lock);
- if (!(blk->valid & (1 << slice)) ||
- (jiffies - blk->updated[slice] > 300 * HZ) ||
- (jiffies < blk->updated[slice])) {
- dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
- slice, blk->base);
+ buf = &data->data[slice << SLICE_BITS];
- addr = blk->base + (slice << SLICE_BITS);
- count = blk->size - (slice << SLICE_BITS);
- if (count > SLICE_SIZE) {
- count = SLICE_SIZE;
- }
+ if (!(data->valid & (1 << slice)) ||
+ time_after(jiffies, data->last_updated[slice])) {
- /* Preset the read address */
- if (addr < 0x100) {
- /* select the register */
- if (i2c_smbus_write_byte(client, addr & 0xFF)) {
- dev_dbg(&client->dev, "max6875 register select has failed!\n");
- retval = -1;
- goto exit;
- }
- } else {
- /* select the eeprom */
- if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
- dev_dbg(&client->dev, "max6875 address set has failed!\n");
- retval = -1;
- goto exit;
- }
+ dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
+
+ data->valid &= ~(1 << slice);
+
+ addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
+
+ /* select the eeprom address */
+ if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+ dev_err(&client->dev, "address set failed\n");
+ goto exit_up;
}
- if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
- rdbuf) != SLICE_SIZE)
- {
- retval = -1;
- goto exit;
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ if (i2c_smbus_read_i2c_block_data(client,
+ MAX6875_CMD_BLK_READ,
+ buf) != SLICE_SIZE) {
+ goto exit_up;
}
-
- memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
} else {
- for (i = 0; i < count; i++) {
+ for (i = 0; i < SLICE_SIZE; i++) {
j = i2c_smbus_read_byte(client);
- if (j < 0)
- {
- retval = -1;
- goto exit;
+ if (j < 0) {
+ goto exit_up;
}
- blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+ buf[i] = j;
}
}
- blk->updated[slice] = jiffies;
- blk->valid |= (1 << slice);
+ data->last_updated[slice] = jiffies;
+ data->valid |= (1 << slice);
}
- exit:
+exit_up:
up(&data->update_lock);
- return retval;
}
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
- enum max6875_area_type area_type)
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
- struct eeprom_block *blk;
- int slice;
-
- blk = &data->blocks[area_type];
+ int slice, max_slice;
- if (off > blk->size)
+ if (off > USER_EEPROM_SIZE)
return 0;
- if (off + count > blk->size)
- count = blk->size - off;
- /* Only refresh slices which contain requested bytes */
- for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
- max6875_update_slice(client, blk, slice);
+ if (off + count > USER_EEPROM_SIZE)
+ count = USER_EEPROM_SIZE - off;
- memcpy(buf, &blk->data[off], count);
+ /* refresh slices which contain requested bytes */
+ max_slice = (off + count - 1) >> SLICE_BITS;
+ for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
+ max6875_update_slice(client, slice);
- return count;
-}
-
-static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_register_config);
-}
-
-
-static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
- enum max6875_area_type area_type)
-{
- struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
- struct max6875_data *data = i2c_get_clientdata(client);
- struct eeprom_block *blk;
- int slice, addr, retval;
- ssize_t sent = 0;
-
- blk = &data->blocks[area_type];
-
- if (off > blk->size)
- return 0;
- if ((off + count) > blk->size)
- count = blk->size - off;
-
- if (down_interruptible(&data->update_lock))
- return -EAGAIN;
-
- /* writing to a register is done with i2c_smbus_write_byte_data() */
- if (blk->type == max6875_register_config) {
- for (sent = 0; sent < count; sent++) {
- addr = off + sent;
- if (addr == 0x44)
- continue;
-
- retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
- }
- } else {
- int cmd, val;
-
- /* We are writing to EEPROM */
- for (sent = 0; sent < count; sent++) {
- addr = blk->base + off + sent;
- cmd = addr >> 8;
- val = (addr & 0xff) | (buf[sent] << 8); // reversed
-
- if (addr == 0x8044)
- continue;
-
- retval = i2c_smbus_write_word_data(client, cmd, val);
-
- if (retval) {
- goto error_exit;
- }
+ memcpy(buf, &data->data[off], count);
- /* A write takes up to 11 ms */
- msleep(11);
- }
- }
-
- /* Invalidate the scratch buffer */
- for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
- blk->valid &= ~(1 << slice);
-
- error_exit:
- up(&data->update_lock);
-
- return sent;
-}
-
-static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_register_config);
+ return count;
}
static struct bin_attribute user_eeprom_attr = {
.attr = {
- .name = "eeprom_user",
- .mode = S_IRUGO | S_IWUSR | S_IWGRP,
- .owner = THIS_MODULE,
- },
- .size = USER_EEPROM_SIZE,
- .read = max6875_user_read,
- .write = max6875_user_write,
-};
-
-static struct bin_attribute config_eeprom_attr = {
- .attr = {
- .name = "eeprom_config",
- .mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
- },
- .size = CONFIG_EEPROM_SIZE,
- .read = max6875_config_read,
- .write = max6875_config_write,
-};
-
-static struct bin_attribute config_register_attr = {
- .attr = {
- .name = "reg_config",
- .mode = S_IRUGO | S_IWUSR,
+ .name = "eeprom",
+ .mode = S_IRUGO,
.owner = THIS_MODULE,
},
- .size = CONFIG_EEPROM_SIZE,
- .read = max6875_cfgreg_read,
- .write = max6875_cfgreg_write,
+ .size = USER_EEPROM_SIZE,
+ .read = max6875_read,
};
static int max6875_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, max6875_detect);
+ return i2c_probe(adapter, &addr_data, max6875_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
{
- struct i2c_client *new_client;
+ struct i2c_client *real_client;
+ struct i2c_client *fake_client;
struct max6875_data *data;
int err = 0;
- /* Prevent 24RF08 corruption (in case of user error) */
- if (kind < 0)
- i2c_smbus_xfer(adapter, address, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL);
-
- /* There are three ways we can read the EEPROM data:
- (1) I2C block reads (faster, but unsupported by most adapters)
- (2) Consecutive byte reads (100% overhead)
- (3) Regular byte data reads (200% overhead)
- The third method is not implemented by this driver because all
- known adapters support at least the second. */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
- goto exit;
-
- /* OK. For now, we presume we have a valid client. We now create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access eeprom_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BYTE))
+ return 0;
+
+ /* Only check even addresses */
+ if (address & 1)
+ return 0;
+
+ if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+ return -ENOMEM;
memset(data, 0, sizeof(struct max6875_data));
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &max6875_driver;
- new_client->flags = 0;
-
- /* Setup the user section */
- data->blocks[max6875_eeprom_user].type = max6875_eeprom_user;
- data->blocks[max6875_eeprom_user].slices = USER_EEPROM_SLICES;
- data->blocks[max6875_eeprom_user].size = USER_EEPROM_SIZE;
- data->blocks[max6875_eeprom_user].base = USER_EEPROM_BASE;
- data->blocks[max6875_eeprom_user].data = data->data;
- data->blocks[max6875_eeprom_user].updated = data->last_updated;
-
- /* Setup the config section */
- data->blocks[max6875_eeprom_config].type = max6875_eeprom_config;
- data->blocks[max6875_eeprom_config].slices = CONFIG_EEPROM_SLICES;
- data->blocks[max6875_eeprom_config].size = CONFIG_EEPROM_SIZE;
- data->blocks[max6875_eeprom_config].base = CONFIG_EEPROM_BASE;
- data->blocks[max6875_eeprom_config].data = &data->data[USER_EEPROM_SIZE];
- data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
-
- /* Setup the register section */
- data->blocks[max6875_register_config].type = max6875_register_config;
- data->blocks[max6875_register_config].slices = CONFIG_EEPROM_SLICES;
- data->blocks[max6875_register_config].size = CONFIG_EEPROM_SIZE;
- data->blocks[max6875_register_config].base = 0;
- data->blocks[max6875_register_config].data = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
- data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
-
- /* Init the data */
- memset(data->data, 0xff, sizeof(data->data));
-
- /* Fill in the remaining client fields */
- strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+ /* A fake client is created on the odd address */
+ if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit_kfree1;
+ }
+ memset(fake_client, 0, sizeof(struct i2c_client));
+
+ /* Init real i2c_client */
+ real_client = &data->client;
+ i2c_set_clientdata(real_client, data);
+ real_client->addr = address;
+ real_client->adapter = adapter;
+ real_client->driver = &max6875_driver;
+ real_client->flags = 0;
+ strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock);
- /* Verify that the chip is really what we think it is */
- if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
- (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
- goto exit_kfree;
-
- /* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
- if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
- (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
- (data->blocks[max6875_register_config].data[0x41] != 0) ||
- (data->blocks[max6875_register_config].data[0x42] != 0) ||
- (data->blocks[max6875_eeprom_config].data[0x40] !=
- data->blocks[max6875_register_config].data[0x40]))
- goto exit_kfree;
-
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_kfree;
-
- /* create the sysfs eeprom files with the correct permissions */
- if (allow_write == 0) {
- user_eeprom_attr.attr.mode &= ~S_IWUGO;
- user_eeprom_attr.write = NULL;
- config_eeprom_attr.attr.mode &= ~S_IWUGO;
- config_eeprom_attr.write = NULL;
- config_register_attr.attr.mode &= ~S_IWUGO;
- config_register_attr.write = NULL;
- }
- sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
- sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
- sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+ /* Init fake client data */
+ /* set the client data to the i2c_client so that it will get freed */
+ i2c_set_clientdata(fake_client, fake_client);
+ fake_client->addr = address | 1;
+ fake_client->adapter = adapter;
+ fake_client->driver = &max6875_driver;
+ fake_client->flags = 0;
+ strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
+
+ /* Prevent 24RF08 corruption (in case of user error) */
+ i2c_smbus_write_quick(real_client, 0);
+
+ if ((err = i2c_attach_client(real_client)) != 0)
+ goto exit_kfree2;
+
+ if ((err = i2c_attach_client(fake_client)) != 0)
+ goto exit_detach;
+
+ sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
return 0;
-exit_kfree:
+exit_detach:
+ i2c_detach_client(real_client);
+exit_kfree2:
+ kfree(fake_client);
+exit_kfree1:
kfree(data);
-exit:
return err;
}
@@ -450,13 +236,9 @@ static int max6875_detach_client(struct i2c_client *client)
int err;
err = i2c_detach_client(client);
- if (err) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ if (err)
return err;
- }
-
kfree(i2c_get_clientdata(client));
-
return 0;
}
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 9f3ad45daae2..225577fdda4d 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -13,14 +13,12 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
/* Insmod parameters */
-SENSORS_INSMOD_1(pca9539);
+I2C_CLIENT_INSMOD_1(pca9539);
enum pca9539_cmd
{
@@ -109,10 +107,10 @@ static struct attribute_group pca9539_defattr_group = {
static int pca9539_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pca9539_detect);
+ return i2c_probe(adapter, &addr_data, pca9539_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -164,10 +162,8 @@ static int pca9539_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index cfcf64654080..6525743ff9fd 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -39,16 +39,14 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(pcf8574, pcf8574a);
+I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
/* Initial values */
#define PCF8574_INIT 255 /* All outputs on (input mode) */
@@ -113,10 +111,10 @@ static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pcf8574_detect);
+ return i2c_probe(adapter, &addr_data, pcf8574_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -186,11 +184,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index db812ade8564..80f1df9a4500 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -24,15 +24,13 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(pcf8591);
+I2C_CLIENT_INSMOD_1(pcf8591);
static int input_mode;
module_param(input_mode, int, 0);
@@ -164,10 +162,10 @@ static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
*/
static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pcf8591_detect);
+ return i2c_probe(adapter, &addr_data, pcf8591_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -241,11 +239,8 @@ static int pcf8591_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 588fc2261a91..0b5385c892b1 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -67,7 +67,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 4a9ead277596..dda472e5e8be 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -61,7 +61,7 @@ static int i2c_bus_resume(struct device * dev)
return rc;
}
-static struct bus_type i2c_bus_type = {
+struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.suspend = i2c_bus_suspend,
@@ -78,13 +78,13 @@ static int i2c_device_remove(struct device *dev)
return 0;
}
-static void i2c_adapter_dev_release(struct device *dev)
+void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
complete(&adap->dev_released);
}
-static struct device_driver i2c_adapter_driver = {
+struct device_driver i2c_adapter_driver = {
.name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
@@ -97,7 +97,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
complete(&adap->class_dev_released);
}
-static struct class i2c_adapter_class = {
+struct class i2c_adapter_class = {
.name = "i2c-adapter",
.release = &i2c_adapter_class_dev_release,
};
@@ -188,6 +188,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
class_device_register(&adap->class_dev);
+ dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
+
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
@@ -196,8 +198,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
driver->attach_adapter(adap);
}
- dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-
out_unlock:
up(&core_lists);
return res;
@@ -220,8 +220,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
break;
}
if (adap_from_list != adap) {
- pr_debug("I2C: Attempting to delete an unregistered "
- "adapter\n");
+ pr_debug("i2c-core: attempting to delete unregistered "
+ "adapter [%s]\n", adap->name);
res = -EINVAL;
goto out_unlock;
}
@@ -230,9 +230,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
driver = list_entry(item, struct i2c_driver, list);
if (driver->detach_adapter)
if ((res = driver->detach_adapter(adap))) {
- dev_warn(&adap->dev, "can't detach adapter "
- "while detaching driver %s: driver "
- "not detached!\n", driver->name);
+ dev_err(&adap->dev, "detach_adapter failed "
+ "for driver [%s]\n", driver->name);
goto out_unlock;
}
}
@@ -247,9 +246,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
* must be deleted, as this would cause invalid states.
*/
if ((res=client->driver->detach_client(client))) {
- dev_err(&adap->dev, "adapter not "
- "unregistered, because client at "
- "address %02x can't be detached. ",
+ dev_err(&adap->dev, "detach_client failed for client "
+ "[%s] at address 0x%02x\n", client->name,
client->addr);
goto out_unlock;
}
@@ -270,7 +268,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* free dynamically allocated bus id */
idr_remove(&i2c_adapter_idr, adap->nr);
- dev_dbg(&adap->dev, "adapter unregistered\n");
+ dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
out_unlock:
up(&core_lists);
@@ -303,7 +301,7 @@ int i2c_add_driver(struct i2c_driver *driver)
goto out_unlock;
list_add_tail(&driver->list,&drivers);
- pr_debug("i2c-core: driver %s registered.\n", driver->name);
+ pr_debug("i2c-core: driver [%s] registered\n", driver->name);
/* now look for instances of driver on our adapters */
if (driver->flags & I2C_DF_NOTIFY) {
@@ -331,21 +329,17 @@ int i2c_del_driver(struct i2c_driver *driver)
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
- */
- pr_debug("i2c-core: unregister_driver - looking for clients.\n");
- /* removing clients does not depend on the notify flag, else
+ *
+ * Removing clients does not depend on the notify flag, else
* invalid operation might (will!) result, when using stale client
* pointers.
*/
list_for_each(item1,&adapters) {
adap = list_entry(item1, struct i2c_adapter, list);
- dev_dbg(&adap->dev, "examining adapter\n");
if (driver->detach_adapter) {
if ((res = driver->detach_adapter(adap))) {
- dev_warn(&adap->dev, "while unregistering "
- "dummy driver %s, adapter could "
- "not be detached properly; driver "
- "not unloaded!",driver->name);
+ dev_err(&adap->dev, "detach_adapter failed "
+ "for driver [%s]\n", driver->name);
goto out_unlock;
}
} else {
@@ -353,16 +347,13 @@ int i2c_del_driver(struct i2c_driver *driver)
client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver)
continue;
- pr_debug("i2c-core.o: detaching client %s:\n", client->name);
+ dev_dbg(&adap->dev, "detaching client [%s] "
+ "at 0x%02x\n", client->name,
+ client->addr);
if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "while "
- "unregistering driver "
- "`%s', the client at "
- "address %02x of "
- "adapter could not "
- "be detached; driver "
- "not unloaded!",
- driver->name,
+ dev_err(&adap->dev, "detach_client "
+ "failed for client [%s] at "
+ "0x%02x\n", client->name,
client->addr);
goto out_unlock;
}
@@ -372,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver)
driver_unregister(&driver->driver);
list_del(&driver->list);
- pr_debug("i2c-core: driver unregistered: %s\n", driver->name);
+ pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
out_unlock:
up(&core_lists);
@@ -417,15 +408,12 @@ int i2c_attach_client(struct i2c_client *client)
if (adapter->client_register) {
if (adapter->client_register(client)) {
- dev_warn(&adapter->dev, "warning: client_register "
- "seems to have failed for client %02x\n",
- client->addr);
+ dev_dbg(&adapter->dev, "client_register "
+ "failed for client [%s] at 0x%02x\n",
+ client->name, client->addr);
}
}
- dev_dbg(&adapter->dev, "client [%s] registered to adapter\n",
- client->name);
-
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -436,7 +424,8 @@ int i2c_attach_client(struct i2c_client *client)
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
"%d-%04x", i2c_adapter_id(adapter), client->addr);
- pr_debug("registering %s\n", client->dev.bus_id);
+ dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+ client->name, client->dev.bus_id);
device_register(&client->dev);
device_create_file(&client->dev, &dev_attr_client_name);
@@ -449,8 +438,12 @@ int i2c_detach_client(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
int res = 0;
- if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
+ if ((client->flags & I2C_CLIENT_ALLOW_USE)
+ && (client->usage_count > 0)) {
+ dev_warn(&client->dev, "Client [%s] still busy, "
+ "can't detach\n", client->name);
return -EBUSY;
+ }
if (adapter->client_unregister) {
res = adapter->client_unregister(client);
@@ -669,98 +662,128 @@ int i2c_control(struct i2c_client *client,
* Will not work for 10-bit addresses!
* ----------------------------------------------------
*/
+static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+ int (*found_proc) (struct i2c_adapter *, int, int))
+{
+ int err;
+
+ /* Make sure the address is valid */
+ if (addr < 0x03 || addr > 0x77) {
+ dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
+ addr);
+ return -EINVAL;
+ }
+
+ /* Skip if already in use */
+ if (i2c_check_addr(adapter, addr))
+ return 0;
+
+ /* Make sure there is something at this address, unless forced */
+ if (kind < 0) {
+ if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+ I2C_SMBUS_QUICK, NULL) < 0)
+ return 0;
+
+ /* prevent 24RF08 corruption */
+ if ((addr & ~0x0f) == 0x50)
+ i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+ I2C_SMBUS_QUICK, NULL);
+ }
+
+ /* Finally call the custom detection function */
+ err = found_proc(adapter, addr, kind);
+
+ /* -ENODEV can be returned if there is a chip at the given address
+ but it isn't supported by this chip driver. We catch it here as
+ this isn't an error. */
+ return (err == -ENODEV) ? 0 : err;
+}
+
int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
int (*found_proc) (struct i2c_adapter *, int, int))
{
- int addr,i,found,err;
+ int i, err;
int adap_id = i2c_adapter_id(adapter);
/* Forget it if we can't probe using SMBUS_QUICK */
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
return -1;
- for (addr = 0x00; addr <= 0x7f; addr++) {
-
- /* Skip if already in use */
- if (i2c_check_addr(adapter,addr))
- continue;
-
- /* If it is in one of the force entries, we don't do any detection
- at all */
- found = 0;
-
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
- if (((adap_id == address_data->force[i]) ||
- (address_data->force[i] == ANY_I2C_BUS)) &&
- (addr == address_data->force[i+1])) {
- dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n",
- adap_id, addr);
- if ((err = found_proc(adapter,addr,0)))
- return err;
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about
- it right now */
- for (i = 0;
- !found && (address_data->ignore[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == ANY_I2C_BUS))) &&
- (addr == address_data->ignore[i+1])) {
- dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
- "addr %04x\n", adap_id ,addr);
- found = 1;
+ /* Force entries are done first, and are not affected by ignore
+ entries */
+ if (address_data->forces) {
+ unsigned short **forces = address_data->forces;
+ int kind;
+
+ for (kind = 0; forces[kind]; kind++) {
+ for (i = 0; forces[kind][i] != I2C_CLIENT_END;
+ i += 2) {
+ if (forces[kind][i] == adap_id
+ || forces[kind][i] == ANY_I2C_BUS) {
+ dev_dbg(&adapter->dev, "found force "
+ "parameter for adapter %d, "
+ "addr 0x%02x, kind %d\n",
+ adap_id, forces[kind][i + 1],
+ kind);
+ err = i2c_probe_address(adapter,
+ forces[kind][i + 1],
+ kind, found_proc);
+ if (err)
+ return err;
+ }
}
}
- if (found)
- continue;
+ }
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- for (i = 0;
- !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
- i += 1) {
- if (addr == address_data->normal_i2c[i]) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
- "addr %02x\n", adap_id, addr);
- }
+ /* Probe entries are done second, and are not affected by ignore
+ entries either */
+ for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
+ if (address_data->probe[i] == adap_id
+ || address_data->probe[i] == ANY_I2C_BUS) {
+ dev_dbg(&adapter->dev, "found probe parameter for "
+ "adapter %d, addr 0x%02x\n", adap_id,
+ address_data->probe[i + 1]);
+ err = i2c_probe_address(adapter,
+ address_data->probe[i + 1],
+ -1, found_proc);
+ if (err)
+ return err;
}
+ }
- for (i = 0;
- !found && (address_data->probe[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->probe[i]) ||
- ((address_data->probe[i] == ANY_I2C_BUS))) &&
- (addr == address_data->probe[i+1])) {
- found = 1;
- dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
- "addr %04x\n", adap_id,addr);
+ /* Normal entries are done last, unless shadowed by an ignore entry */
+ for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
+ int j, ignore;
+
+ ignore = 0;
+ for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
+ j += 2) {
+ if ((address_data->ignore[j] == adap_id ||
+ address_data->ignore[j] == ANY_I2C_BUS)
+ && address_data->ignore[j + 1]
+ == address_data->normal_i2c[i]) {
+ dev_dbg(&adapter->dev, "found ignore "
+ "parameter for adapter %d, "
+ "addr 0x%02x\n", adap_id,
+ address_data->ignore[j + 1]);
}
+ ignore = 1;
+ break;
}
- if (!found)
+ if (ignore)
continue;
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- if ((err = found_proc(adapter,addr,-1)))
- return err;
+ dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
+ "addr 0x%02x\n", adap_id,
+ address_data->normal_i2c[i]);
+ err = i2c_probe_address(adapter, address_data->normal_i2c[i],
+ -1, found_proc);
+ if (err)
+ return err;
}
- return 0;
-}
-/*
- * return id number for a specific adapter
- */
-int i2c_adapter_id(struct i2c_adapter *adap)
-{
- return adap->nr;
+ return 0;
}
struct i2c_adapter* i2c_get_adapter(int id)
@@ -1171,6 +1194,12 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
}
+/* Next four are needed by i2c-isa */
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
+EXPORT_SYMBOL_GPL(i2c_adapter_driver);
+EXPORT_SYMBOL_GPL(i2c_adapter_class);
+EXPORT_SYMBOL_GPL(i2c_bus_type);
+
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
EXPORT_SYMBOL(i2c_add_driver);
@@ -1186,7 +1215,6 @@ EXPORT_SYMBOL(i2c_master_send);
EXPORT_SYMBOL(i2c_master_recv);
EXPORT_SYMBOL(i2c_control);
EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_adapter_id);
EXPORT_SYMBOL(i2c_get_adapter);
EXPORT_SYMBOL(i2c_put_adapter);
EXPORT_SYMBOL(i2c_probe);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index bc5d557e5dd9..aa7a4fadef64 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -434,7 +434,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
- dev_dbg(&adap->dev, "Registered as minor %d\n", i2c_dev->minor);
+ pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+ adap->name, i2c_dev->minor);
/* register this i2c device with the driver core */
i2c_dev->adap = adap;
@@ -471,7 +472,7 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
wait_for_completion(&i2c_dev->released);
kfree(i2c_dev);
- dev_dbg(&adap->dev, "Adapter unregistered\n");
+ pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
return 0;
}
diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
deleted file mode 100644
index f99a8161a9f1..000000000000
--- a/drivers/i2c/i2c-sensor-detect.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
- Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
- Mark D. Studebaker <mdsxyz123@yahoo.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
-static unsigned short empty[] = {I2C_CLIENT_END};
-static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
-
-/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
-int i2c_detect(struct i2c_adapter *adapter,
- struct i2c_address_data *address_data,
- int (*found_proc) (struct i2c_adapter *, int, int))
-{
- int addr, i, found, j, err;
- struct i2c_force_data *this_force;
- int is_isa = i2c_is_isa_adapter(adapter);
- int adapter_id =
- is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
- unsigned short *normal_i2c;
- unsigned int *normal_isa;
- unsigned short *probe;
- unsigned short *ignore;
-
- /* Forget it if we can't probe using SMBUS_QUICK */
- if ((!is_isa) &&
- !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
- return -1;
-
- /* Use default "empty" list if the adapter doesn't specify any */
- normal_i2c = probe = ignore = empty;
- normal_isa = empty_isa;
- if (address_data->normal_i2c)
- normal_i2c = address_data->normal_i2c;
- if (address_data->normal_isa)
- normal_isa = address_data->normal_isa;
- if (address_data->probe)
- probe = address_data->probe;
- if (address_data->ignore)
- ignore = address_data->ignore;
-
- for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
- if (!is_isa && i2c_check_addr(adapter, addr))
- continue;
-
- /* If it is in one of the force entries, we don't do any
- detection at all */
- found = 0;
- for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
- for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
- if ( ((adapter_id == this_force->force[j]) ||
- ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
- (addr == this_force->force[j + 1]) ) {
- dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
- if ((err = found_proc(adapter, addr, this_force->kind)))
- return err;
- found = 1;
- }
- }
- }
- if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about it
- right now */
- for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) {
- if ( ((adapter_id == ignore[i]) ||
- ((ignore[i] == ANY_I2C_BUS) &&
- !is_isa)) &&
- (addr == ignore[i + 1])) {
- dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- if (is_isa) {
- for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
- if (addr == normal_isa[i]) {
- dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- } else {
- for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) {
- if (addr == normal_i2c[i]) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr);
- }
- }
- }
-
- for (i = 0;
- !found && (probe[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adapter_id == probe[i]) ||
- ((probe[i] == ANY_I2C_BUS) && !is_isa))
- && (addr == probe[i + 1])) {
- dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (is_isa ||
- (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
- if ((err = found_proc(adapter, addr, -1)))
- return err;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
- "Rudolf Marek <r.marek@sh.cvut.cz>");
-
-MODULE_DESCRIPTION("i2c-sensor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
deleted file mode 100644
index 922e22f054bb..000000000000
--- a/drivers/i2c/i2c-sensor-vid.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- i2c-sensor-vid.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
-
- Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-struct vrm_model {
- u8 vendor;
- u8 eff_family;
- u8 eff_model;
- int vrm_type;
-};
-
-#define ANY 0xFF
-
-#ifdef CONFIG_X86
-
-static struct vrm_model vrm_models[] = {
- {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
- {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
- {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */
- {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
- {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
- {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
- {X86_VENDOR_INTEL, 0xF, ANY, 90}, /* P4 before Prescott */
- {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
- {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
- };
-
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
-{
- int i = 0;
-
- while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
- if (vrm_models[i].vendor==vendor)
- if ((vrm_models[i].eff_family==eff_family)&& \
- ((vrm_models[i].eff_model==eff_model)|| \
- (vrm_models[i].eff_model==ANY)))
- return vrm_models[i].vrm_type;
- i++;
- }
-
- return 0;
-}
-
-int i2c_which_vrm(void)
-{
- struct cpuinfo_x86 *c = cpu_data;
- u32 eax;
- u8 eff_family, eff_model;
- int vrm_ret;
-
- if (c->x86 < 6) return 0; /* any CPU with familly lower than 6
- dont have VID and/or CPUID */
- eax = cpuid_eax(1);
- eff_family = ((eax & 0x00000F00)>>8);
- eff_model = ((eax & 0x000000F0)>>4);
- if (eff_family == 0xF) { /* use extended model & family */
- eff_family += ((eax & 0x00F00000)>>20);
- eff_model += ((eax & 0x000F0000)>>16)<<4;
- }
- vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
- if (vrm_ret == 0)
- printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
- " x86 CPU\n");
- return vrm_ret;
-}
-
-/* and now for something completely different for Non-x86 world*/
-#else
-int i2c_which_vrm(void)
-{
- printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
- return 0;
-}
-#endif
-
-EXPORT_SYMBOL(i2c_which_vrm);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index c9d3a00a3c0c..234f5de3e929 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -754,7 +754,7 @@ static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
idedisk_prepare_flush(q, rq);
- ret = blk_execute_rq(q, disk, rq);
+ ret = blk_execute_rq(q, disk, rq, 0);
/*
* if we failed and caller wants error offset, get it
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 248e3cc8b352..9e9cf1407311 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -150,7 +150,7 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
switch (rq->pm->pm_step) {
case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
- if (rq->pm->pm_state == 4)
+ if (rq->pm->pm_state == PM_EVENT_FREEZE)
rq->pm->pm_step = ide_pm_state_completed;
else
rq->pm->pm_step = idedisk_pm_standby;
@@ -560,7 +560,7 @@ ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
EXPORT_SYMBOL_GPL(__ide_abort);
/**
- * ide_abort - abort pending IDE operatins
+ * ide_abort - abort pending IDE operations
* @drive: drive the error occurred on
* @msg: message to report
*
@@ -623,7 +623,7 @@ static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
* @drive: drive the completion interrupt occurred on
*
* drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- * We do any necessary daya reading and then wait for the drive to
+ * We do any necessary data reading and then wait for the drive to
* go non busy. At that point we may read the error data and complete
* the request
*/
@@ -773,7 +773,7 @@ EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
/**
* execute_drive_command - issue special drive command
- * @drive: the drive to issue th command on
+ * @drive: the drive to issue the command on
* @rq: the request structure holding the command
*
* execute_drive_cmd() issues a special drive command, usually
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b443b04a4c5a..0b0aa4f51628 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -601,44 +601,15 @@ EXPORT_SYMBOL(ide_wait_stat);
*/
u8 eighty_ninty_three (ide_drive_t *drive)
{
-#if 0
- if (!HWIF(drive)->udma_four)
+ if(HWIF(drive)->udma_four == 0)
+ return 0;
+ if (!(drive->id->hw_config & 0x6000))
return 0;
-
- if (drive->id->major_rev_num) {
- int hssbd = 0;
- int i;
- /*
- * Determine highest Supported SPEC
- */
- for (i=1; i<=15; i++)
- if (drive->id->major_rev_num & (1<<i))
- hssbd++;
-
- switch (hssbd) {
- case 7:
- case 6:
- case 5:
- /* ATA-4 and older do not support above Ultra 33 */
- default:
- return 0;
- }
- }
-
- return ((u8) (
-#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-
-#else
-
- return ((u8) ((HWIF(drive)->udma_four) &&
#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
+ if(!(drive->id->hw_config & 0x4000))
+ return 0;
#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-#endif
+ return 1;
}
EXPORT_SYMBOL(eighty_ninty_three);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 5a3dc46008e6..ee38e6b143a4 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2903,8 +2903,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
(tape->ascq == 1 || tape->ascq == 8)))
return -EIO;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 10);
+ msleep(100);
}
return -EIO;
}
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c1196ce15b4d..2fcfac6e967a 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -27,6 +27,7 @@
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
+#include <linux/kernel.h>
#include <linux/hdreg.h>
#define XFER_PIO_5 0x0d
@@ -96,11 +97,9 @@ static struct ide_timing ide_timing[] = {
#define IDE_TIMING_UDMA 0x80
#define IDE_TIMING_ALL 0xff
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#define FIT(v,min,max) MAX(MIN(v,max),min)
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
+#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
+#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
#define XFER_UDMA_133 0x48
@@ -188,14 +187,14 @@ static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int
static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
{
- if (what & IDE_TIMING_SETUP ) m->setup = MAX(a->setup, b->setup);
- if (what & IDE_TIMING_ACT8B ) m->act8b = MAX(a->act8b, b->act8b);
- if (what & IDE_TIMING_REC8B ) m->rec8b = MAX(a->rec8b, b->rec8b);
- if (what & IDE_TIMING_CYC8B ) m->cyc8b = MAX(a->cyc8b, b->cyc8b);
- if (what & IDE_TIMING_ACTIVE ) m->active = MAX(a->active, b->active);
- if (what & IDE_TIMING_RECOVER) m->recover = MAX(a->recover, b->recover);
- if (what & IDE_TIMING_CYCLE ) m->cycle = MAX(a->cycle, b->cycle);
- if (what & IDE_TIMING_UDMA ) m->udma = MAX(a->udma, b->udma);
+ if (what & IDE_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
+ if (what & IDE_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
+ if (what & IDE_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
+ if (what & IDE_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
+ if (what & IDE_TIMING_ACTIVE ) m->active = max(a->active, b->active);
+ if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & IDE_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
+ if (what & IDE_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
static struct ide_timing* ide_timing_find_mode(short speed)
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index dae1bd5b8c3e..73ca8f73917d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1229,7 +1229,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state)
rq.special = &args;
rq.pm = &rqpm;
rqpm.pm_step = ide_pm_state_start_suspend;
- rqpm.pm_state = state;
+ rqpm.pm_state = state.event;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -1248,7 +1248,7 @@ static int generic_ide_resume(struct device *dev)
rq.special = &args;
rq.pm = &rqpm;
rqpm.pm_step = ide_pm_state_start_resume;
- rqpm.pm_state = 0;
+ rqpm.pm_state = PM_EVENT_ON;
return ide_do_drive_cmd(drive, &rq, ide_head_wait);
}
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index f1d1ec4e9677..0ccf85fcee34 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -43,6 +43,7 @@
#include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/major.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -340,8 +341,7 @@ static void ide_config(dev_link_t *link)
break;
}
}
- __set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
}
if (hd < 0) {
@@ -454,9 +454,12 @@ int ide_event(event_t event, int priority,
static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4),
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
+ PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */
PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
@@ -481,6 +484,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+ PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
PCMCIA_DEVICE_NULL,
};
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3de9ab897e42..3d9c7afc8695 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -608,7 +608,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
#ifdef __i386__
if (dev->resource[PCI_ROM_RESOURCE].start) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
#endif
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index bbde46279984..be334da7a754 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -173,7 +173,7 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
if (cmd & PCI_COMMAND_MEMORY) {
if (pci_resource_start(dev, PCI_ROM_RESOURCE)) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n",
dev->resource[PCI_ROM_RESOURCE].start);
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 7b64db10d1b0..127619a109ed 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1334,9 +1334,13 @@ static int __devinit init_hpt366(struct pci_dev *dev)
static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{
int ret = 0;
- /* FIXME: Not portable */
+
+ /*
+ * FIXME: Not portable. Also, why do we enable the ROM in the first place?
+ * We don't seem to be using it.
+ */
if (dev->resource[PCI_ROM_RESOURCE].start)
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 10592cec6c43..24e21b2838c1 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -350,9 +350,9 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
{
ide_hwif_t *hwif = NULL;
- printk("SC1200: suspend(%u)\n", state);
+ printk("SC1200: suspend(%u)\n", state.event);
- if (state == 0) {
+ if (state.event == PM_EVENT_ON) {
// we only save state when going from full power to less
//
@@ -386,8 +386,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
/* You don't need to iterate over disks -- sysfs should have done that for you already */
pci_disable_device(dev);
- pci_set_power_state(dev,state);
- dev->current_state = state;
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ dev->current_state = state.event;
return 0;
}
@@ -396,8 +396,8 @@ static int sc1200_resume (struct pci_dev *dev)
ide_hwif_t *hwif = NULL;
printk("SC1200: resume\n");
- pci_set_power_state(dev,0); // bring chip back from sleep state
- dev->current_state = 0;
+ pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state
+ dev->current_state = PM_EVENT_ON;
pci_enable_device(dev);
//
// loop over all interfaces that are part of this pci device:
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index ea65b070a367..87d1f8a1f41e 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1504,12 +1504,12 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
}
static int
-pmac_ide_macio_suspend(struct macio_dev *mdev, u32 state)
+pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t state)
{
ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
int rc = 0;
- if (state != mdev->ofdev.dev.power.power_state && state >= 2) {
+ if (state.event != mdev->ofdev.dev.power.power_state.event && state.event >= PM_EVENT_SUSPEND) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = state;
@@ -1524,10 +1524,10 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
int rc = 0;
- if (mdev->ofdev.dev.power.power_state != 0) {
+ if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
rc = pmac_ide_do_resume(hwif);
if (rc == 0)
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state = PMSG_ON;
}
return rc;
@@ -1608,12 +1608,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
}
static int
-pmac_ide_pci_suspend(struct pci_dev *pdev, u32 state)
+pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
int rc = 0;
- if (state != pdev->dev.power.power_state && state >= 2) {
+ if (state.event != pdev->dev.power.power_state.event && state.event >= 2) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
pdev->dev.power.power_state = state;
@@ -1628,10 +1628,10 @@ pmac_ide_pci_resume(struct pci_dev *pdev)
ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
int rc = 0;
- if (pdev->dev.power.power_state != 0) {
+ if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
rc = pmac_ide_do_resume(hwif);
if (rc == 0)
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
}
return rc;
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index b248d89de8b4..d633770fac8e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -681,7 +681,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
return;
}
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &host->pending_packet_queue);
if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
@@ -989,7 +989,7 @@ void abort_timedouts(unsigned long __opaque)
packet = (struct hpsb_packet *)skb->data;
if (time_before(packet->sendtime + expire, jiffies)) {
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &host->pending_packet_queue);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
queue_packet_complete(packet);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index bebcc47ab06c..b23322523ef5 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1068,6 +1068,8 @@ static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
struct unit_directory *ud;
int i = 0;
int length = 0;
+ /* ieee1394:venNmoNspNverN */
+ char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
if (!cdev)
return -ENODEV;
@@ -1094,6 +1096,12 @@ do { \
PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);
PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);
PUT_ENVP("VERSION=%06x", ud->version);
+ snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
+ ud->vendor_id,
+ ud->model_id,
+ ud->specifier_id,
+ ud->version);
+ PUT_ENVP("MODALIAS=%s", buf);
#undef PUT_ENVP
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 36074e6eeebb..6b1ab875333b 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1464,26 +1464,6 @@ static int __devinit add_card(struct pci_dev *dev,
{ 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
};
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- union i2c_smbus_data data;
-
- if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
- PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
- else
- {
- u16 addr;
- for (addr=0x00; addr < 0x100; addr++) {
- if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
- PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
- break;
- }
- else
- PRINT(KERN_DEBUG, lynx->id,"got serial eeprom data at %x: %x",addr, data.byte);
- }
- }
-#endif
-
/* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
do it more efficiently in one transaction rather then using several reads */
if (i2c_transfer(i2c_ad, msg, 2) < 0) {
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 627af507643a..de88218ef7cc 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -790,7 +790,7 @@ static void sbp2_host_reset(struct hpsb_host *host)
static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- struct scsi_device *sdev;
+ int error;
SBP2_DEBUG("sbp2_start_device");
@@ -939,10 +939,10 @@ alloc_fail:
sbp2_max_speed_and_size(scsi_id);
/* Add this device to the scsi layer now */
- sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
- if (IS_ERR(sdev)) {
+ error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
+ if (error) {
SBP2_ERR("scsi_add_device failed");
- return PTR_ERR(sdev);
+ return error;
}
return 0;
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 06759b36afea..9d6facf2f78f 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -883,7 +883,7 @@ static int __video1394_ioctl(struct file *file,
v.channel);
}
- if (copy_to_user((void *)arg, &v, sizeof(v))) {
+ if (copy_to_user(argp, &v, sizeof(v))) {
/* FIXME : free allocated dma resources */
return -EFAULT;
}
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 32cdfb30e9b4..325d502e25cd 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -8,15 +8,26 @@ config INFINIBAND
any protocols you wish to use as well as drivers for your
InfiniBand hardware.
-config INFINIBAND_USER_VERBS
- tristate "InfiniBand userspace verbs support"
+config INFINIBAND_USER_MAD
+ tristate "InfiniBand userspace MAD support"
depends on INFINIBAND
---help---
- Userspace InfiniBand verbs support. This is the kernel side
- of userspace verbs, which allows userspace processes to
- directly access InfiniBand hardware for fast-path
- operations. You will also need libibverbs and a hardware
- driver library from <http://www.openib.org>.
+ Userspace InfiniBand Management Datagram (MAD) support. This
+ is the kernel side of the userspace MAD support, which allows
+ userspace processes to send and receive MADs. You will also
+ need libibumad from <http://www.openib.org>.
+
+config INFINIBAND_USER_ACCESS
+ tristate "InfiniBand userspace access (verbs and CM)"
+ depends on INFINIBAND
+ ---help---
+ Userspace InfiniBand access support. This enables the
+ kernel side of userspace verbs and the userspace
+ communication manager (CM). This allows userspace processes
+ to set up connections and directly access InfiniBand
+ hardware for fast-path operations. You will also need
+ libibverbs, libibcm and a hardware driver library from
+ <http://www.openib.org>.
source "drivers/infiniband/hw/mthca/Kconfig"
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 10be36731ed7..ec3353f24b27 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -1,8 +1,7 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
- ib_cm.o ib_umad.o ib_ucm.o
-obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
+ ib_cm.o
+obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
+obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
device.o fmr_pool.o cache.o
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 729f0b0d983a..5ac86f566dc0 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * 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, 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -40,7 +41,7 @@
#include <asm/bug.h>
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
#include "smi.h"
#include "agent_priv.h"
diff --git a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
index 17435af1e914..2ec6d7f1b7d0 100644
--- a/drivers/infiniband/core/agent_priv.h
+++ b/drivers/infiniband/core/agent_priv.h
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * 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, 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 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
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 3042360c97e1..f014e639088c 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -1,5 +1,8 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 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
@@ -32,12 +35,11 @@
* $Id: cache.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "core_priv.h"
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 403ed125d8f4..54db6d4831f1 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -43,8 +43,8 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <ib_cache.h>
-#include <ib_cm.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
#include "cm_msgs.h"
MODULE_AUTHOR("Sean Hefty");
@@ -83,7 +83,7 @@ struct cm_port {
struct cm_device {
struct list_head list;
struct ib_device *device;
- u64 ca_guid;
+ __be64 ca_guid;
struct cm_port port[0];
};
@@ -100,8 +100,8 @@ struct cm_work {
struct list_head list;
struct cm_port *port;
struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */
- u32 local_id; /* Established / timewait */
- u32 remote_id;
+ __be32 local_id; /* Established / timewait */
+ __be32 remote_id;
struct ib_cm_event cm_event;
struct ib_sa_path_rec path[0];
};
@@ -110,8 +110,8 @@ struct cm_timewait_info {
struct cm_work work; /* Must be first. */
struct rb_node remote_qp_node;
struct rb_node remote_id_node;
- u64 remote_ca_guid;
- u32 remote_qpn;
+ __be64 remote_ca_guid;
+ __be32 remote_qpn;
u8 inserted_remote_qp;
u8 inserted_remote_id;
};
@@ -132,11 +132,11 @@ struct cm_id_private {
struct cm_av alt_av;
void *private_data;
- u64 tid;
- u32 local_qpn;
- u32 remote_qpn;
- u32 sq_psn;
- u32 rq_psn;
+ __be64 tid;
+ __be32 local_qpn;
+ __be32 remote_qpn;
+ __be32 sq_psn;
+ __be32 rq_psn;
int timeout_ms;
enum ib_mtu path_mtu;
u8 private_data_len;
@@ -173,7 +173,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
if (IS_ERR(ah))
return PTR_ERR(ah);
- m = ib_create_send_mad(mad_agent, 1, cm_id_priv->av.pkey_index,
+ m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
+ cm_id_priv->av.pkey_index,
ah, 0, sizeof(struct ib_mad_hdr),
sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
GFP_ATOMIC);
@@ -253,7 +254,7 @@ static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
u16 dlid, u8 sl, u16 src_path_bits)
{
memset(ah_attr, 0, sizeof ah_attr);
- ah_attr->dlid = be16_to_cpu(dlid);
+ ah_attr->dlid = dlid;
ah_attr->sl = sl;
ah_attr->src_path_bits = src_path_bits;
ah_attr->port_num = port_num;
@@ -264,7 +265,7 @@ static void cm_init_av_for_response(struct cm_port *port,
{
av->port = port;
av->pkey_index = wc->pkey_index;
- cm_set_ah_attr(&av->ah_attr, port->port_num, cpu_to_be16(wc->slid),
+ cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
wc->sl, wc->dlid_path_bits);
}
@@ -295,8 +296,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
return ret;
av->port = port;
- cm_set_ah_attr(&av->ah_attr, av->port->port_num, path->dlid,
- path->sl, path->slid & 0x7F);
+ cm_set_ah_attr(&av->ah_attr, av->port->port_num,
+ be16_to_cpu(path->dlid), path->sl,
+ be16_to_cpu(path->slid) & 0x7F);
av->packet_life_time = path->packet_life_time;
return 0;
}
@@ -309,26 +311,26 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
do {
spin_lock_irqsave(&cm.lock, flags);
ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
- (int *) &cm_id_priv->id.local_id);
+ (__force int *) &cm_id_priv->id.local_id);
spin_unlock_irqrestore(&cm.lock, flags);
} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
return ret;
}
-static void cm_free_id(u32 local_id)
+static void cm_free_id(__be32 local_id)
{
unsigned long flags;
spin_lock_irqsave(&cm.lock, flags);
- idr_remove(&cm.local_id_table, (int) local_id);
+ idr_remove(&cm.local_id_table, (__force int) local_id);
spin_unlock_irqrestore(&cm.lock, flags);
}
-static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
{
struct cm_id_private *cm_id_priv;
- cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
+ cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id);
if (cm_id_priv) {
if (cm_id_priv->id.remote_id == remote_id)
atomic_inc(&cm_id_priv->refcount);
@@ -339,7 +341,7 @@ static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
return cm_id_priv;
}
-static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
{
struct cm_id_private *cm_id_priv;
unsigned long flags;
@@ -356,8 +358,8 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
struct rb_node **link = &cm.listen_service_table.rb_node;
struct rb_node *parent = NULL;
struct cm_id_private *cur_cm_id_priv;
- u64 service_id = cm_id_priv->id.service_id;
- u64 service_mask = cm_id_priv->id.service_mask;
+ __be64 service_id = cm_id_priv->id.service_id;
+ __be64 service_mask = cm_id_priv->id.service_mask;
while (*link) {
parent = *link;
@@ -376,7 +378,7 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
return NULL;
}
-static struct cm_id_private * cm_find_listen(u64 service_id)
+static struct cm_id_private * cm_find_listen(__be64 service_id)
{
struct rb_node *node = cm.listen_service_table.rb_node;
struct cm_id_private *cm_id_priv;
@@ -400,8 +402,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
struct rb_node **link = &cm.remote_id_table.rb_node;
struct rb_node *parent = NULL;
struct cm_timewait_info *cur_timewait_info;
- u64 remote_ca_guid = timewait_info->remote_ca_guid;
- u32 remote_id = timewait_info->work.remote_id;
+ __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+ __be32 remote_id = timewait_info->work.remote_id;
while (*link) {
parent = *link;
@@ -424,8 +426,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
return NULL;
}
-static struct cm_timewait_info * cm_find_remote_id(u64 remote_ca_guid,
- u32 remote_id)
+static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
+ __be32 remote_id)
{
struct rb_node *node = cm.remote_id_table.rb_node;
struct cm_timewait_info *timewait_info;
@@ -453,8 +455,8 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
struct rb_node **link = &cm.remote_qp_table.rb_node;
struct rb_node *parent = NULL;
struct cm_timewait_info *cur_timewait_info;
- u64 remote_ca_guid = timewait_info->remote_ca_guid;
- u32 remote_qpn = timewait_info->remote_qpn;
+ __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+ __be32 remote_qpn = timewait_info->remote_qpn;
while (*link) {
parent = *link;
@@ -484,7 +486,7 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
struct rb_node *parent = NULL;
struct cm_id_private *cur_cm_id_priv;
union ib_gid *port_gid = &cm_id_priv->av.dgid;
- u32 remote_id = cm_id_priv->id.remote_id;
+ __be32 remote_id = cm_id_priv->id.remote_id;
while (*link) {
parent = *link;
@@ -535,6 +537,7 @@ struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
cm_id_priv->id.state = IB_CM_IDLE;
cm_id_priv->id.cm_handler = cm_handler;
cm_id_priv->id.context = context;
+ cm_id_priv->id.remote_cm_qpn = 1;
ret = cm_alloc_id(cm_id_priv);
if (ret)
goto error;
@@ -598,7 +601,7 @@ static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
spin_unlock_irqrestore(&cm.lock, flags);
}
-static struct cm_timewait_info * cm_create_timewait_info(u32 local_id)
+static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
{
struct cm_timewait_info *timewait_info;
@@ -715,14 +718,15 @@ retest:
EXPORT_SYMBOL(ib_destroy_cm_id);
int ib_cm_listen(struct ib_cm_id *cm_id,
- u64 service_id,
- u64 service_mask)
+ __be64 service_id,
+ __be64 service_mask)
{
struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
unsigned long flags;
int ret = 0;
- service_mask = service_mask ? service_mask : ~0ULL;
+ service_mask = service_mask ? service_mask :
+ __constant_cpu_to_be64(~0ULL);
service_id &= service_mask;
if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID &&
(service_id != IB_CM_ASSIGN_SERVICE_ID))
@@ -735,8 +739,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
spin_lock_irqsave(&cm.lock, flags);
if (service_id == IB_CM_ASSIGN_SERVICE_ID) {
- cm_id->service_id = __cpu_to_be64(cm.listen_service_id++);
- cm_id->service_mask = ~0ULL;
+ cm_id->service_id = cpu_to_be64(cm.listen_service_id++);
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
} else {
cm_id->service_id = service_id;
cm_id->service_mask = service_mask;
@@ -752,18 +756,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_listen);
-static u64 cm_form_tid(struct cm_id_private *cm_id_priv,
- enum cm_msg_sequence msg_seq)
+static __be64 cm_form_tid(struct cm_id_private *cm_id_priv,
+ enum cm_msg_sequence msg_seq)
{
u64 hi_tid, low_tid;
hi_tid = ((u64) cm_id_priv->av.port->mad_agent->hi_tid) << 32;
- low_tid = (u64) (cm_id_priv->id.local_id | (msg_seq << 30));
+ low_tid = (u64) ((__force u32)cm_id_priv->id.local_id |
+ (msg_seq << 30));
return cpu_to_be64(hi_tid | low_tid);
}
static void cm_format_mad_hdr(struct ib_mad_hdr *hdr,
- enum cm_msg_attr_id attr_id, u64 tid)
+ __be16 attr_id, __be64 tid)
{
hdr->base_version = IB_MGMT_BASE_VERSION;
hdr->mgmt_class = IB_MGMT_CLASS_CM;
@@ -896,7 +901,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
goto error1;
}
cm_id->service_id = param->service_id;
- cm_id->service_mask = ~0ULL;
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
cm_id_priv->timeout_ms = cm_convert_to_ms(
param->primary_path->packet_life_time) * 2 +
cm_convert_to_ms(
@@ -963,7 +968,7 @@ static int cm_issue_rej(struct cm_port *port,
rej_msg->remote_comm_id = rcv_msg->local_comm_id;
rej_msg->local_comm_id = rcv_msg->remote_comm_id;
cm_rej_set_msg_rejected(rej_msg, msg_rejected);
- rej_msg->reason = reason;
+ rej_msg->reason = cpu_to_be16(reason);
if (ari && ari_length) {
cm_rej_set_reject_info_len(rej_msg, ari_length);
@@ -977,8 +982,8 @@ static int cm_issue_rej(struct cm_port *port,
return ret;
}
-static inline int cm_is_active_peer(u64 local_ca_guid, u64 remote_ca_guid,
- u32 local_qpn, u32 remote_qpn)
+static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
+ __be32 local_qpn, __be32 remote_qpn)
{
return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||
((local_ca_guid == remote_ca_guid) &&
@@ -1137,7 +1142,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
break;
}
- rej_msg->reason = reason;
+ rej_msg->reason = cpu_to_be16(reason);
if (ari && ari_length) {
cm_rej_set_reject_info_len(rej_msg, ari_length);
memcpy(rej_msg->ari, ari, ari_length);
@@ -1276,7 +1281,7 @@ static int cm_req_handler(struct cm_work *work)
cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
cm_id_priv->id.context = listen_cm_id_priv->id.context;
cm_id_priv->id.service_id = req_msg->service_id;
- cm_id_priv->id.service_mask = ~0ULL;
+ cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
@@ -1310,6 +1315,7 @@ error3: atomic_dec(&cm_id_priv->refcount);
cm_deref_id(listen_cm_id_priv);
cm_cleanup_timewait(cm_id_priv->timewait_info);
error2: kfree(cm_id_priv->timewait_info);
+ cm_id_priv->timewait_info = NULL;
error1: ib_destroy_cm_id(&cm_id_priv->id);
return ret;
}
@@ -1969,7 +1975,7 @@ static void cm_format_rej_event(struct cm_work *work)
param = &work->cm_event.param.rej_rcvd;
param->ari = rej_msg->ari;
param->ari_length = cm_rej_get_reject_info_len(rej_msg);
- param->reason = rej_msg->reason;
+ param->reason = __be16_to_cpu(rej_msg->reason);
work->cm_event.private_data = &rej_msg->private_data;
}
@@ -1978,20 +1984,20 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
struct cm_timewait_info *timewait_info;
struct cm_id_private *cm_id_priv;
unsigned long flags;
- u32 remote_id;
+ __be32 remote_id;
remote_id = rej_msg->local_comm_id;
- if (rej_msg->reason == IB_CM_REJ_TIMEOUT) {
+ if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
spin_lock_irqsave(&cm.lock, flags);
- timewait_info = cm_find_remote_id( *((u64 *) rej_msg->ari),
+ timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
remote_id);
if (!timewait_info) {
spin_unlock_irqrestore(&cm.lock, flags);
return NULL;
}
cm_id_priv = idr_find(&cm.local_id_table,
- (int) timewait_info->work.local_id);
+ (__force int) timewait_info->work.local_id);
if (cm_id_priv) {
if (cm_id_priv->id.remote_id == remote_id)
atomic_inc(&cm_id_priv->refcount);
@@ -2032,7 +2038,7 @@ static int cm_rej_handler(struct cm_work *work)
/* fall through */
case IB_CM_REQ_RCVD:
case IB_CM_MRA_REQ_SENT:
- if (rej_msg->reason == IB_CM_REJ_STALE_CONN)
+ if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)
cm_enter_timewait(cm_id_priv);
else
cm_reset_to_idle(cm_id_priv);
@@ -2553,7 +2559,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
sidr_req_msg->request_id = cm_id_priv->id.local_id;
- sidr_req_msg->pkey = param->pkey;
+ sidr_req_msg->pkey = cpu_to_be16(param->pkey);
sidr_req_msg->service_id = param->service_id;
if (param->private_data && param->private_data_len)
@@ -2580,7 +2586,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
goto out;
cm_id->service_id = param->service_id;
- cm_id->service_mask = ~0ULL;
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
cm_id_priv->timeout_ms = param->timeout_ms;
cm_id_priv->max_cm_retries = param->max_cm_retries;
ret = cm_alloc_msg(cm_id_priv, &msg);
@@ -2621,7 +2627,7 @@ static void cm_format_sidr_req_event(struct cm_work *work,
sidr_req_msg = (struct cm_sidr_req_msg *)
work->mad_recv_wc->recv_buf.mad;
param = &work->cm_event.param.sidr_req_rcvd;
- param->pkey = sidr_req_msg->pkey;
+ param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
param->listen_id = listen_id;
param->device = work->port->mad_agent->device;
param->port = work->port->port_num;
@@ -2645,7 +2651,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
sidr_req_msg = (struct cm_sidr_req_msg *)
work->mad_recv_wc->recv_buf.mad;
wc = work->mad_recv_wc->wc;
- cm_id_priv->av.dgid.global.subnet_prefix = wc->slid;
+ cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
cm_id_priv->av.dgid.global.interface_id = 0;
cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
&cm_id_priv->av);
@@ -2673,7 +2679,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
cm_id_priv->id.context = cur_cm_id_priv->id.context;
cm_id_priv->id.service_id = sidr_req_msg->service_id;
- cm_id_priv->id.service_mask = ~0ULL;
+ cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
cm_process_work(cm_id_priv, work);
@@ -3175,10 +3181,10 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
-static u64 cm_get_ca_guid(struct ib_device *device)
+static __be64 cm_get_ca_guid(struct ib_device *device)
{
struct ib_device_attr *device_attr;
- u64 guid;
+ __be64 guid;
int ret;
device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 15a309a77b2b..813ab70bf6d5 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -34,7 +34,7 @@
#if !defined(CM_MSGS_H)
#define CM_MSGS_H
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
/*
* Parameters to routines below should be in network-byte order, and values
@@ -43,19 +43,17 @@
#define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */
-enum cm_msg_attr_id {
- CM_REQ_ATTR_ID = __constant_htons(0x0010),
- CM_MRA_ATTR_ID = __constant_htons(0x0011),
- CM_REJ_ATTR_ID = __constant_htons(0x0012),
- CM_REP_ATTR_ID = __constant_htons(0x0013),
- CM_RTU_ATTR_ID = __constant_htons(0x0014),
- CM_DREQ_ATTR_ID = __constant_htons(0x0015),
- CM_DREP_ATTR_ID = __constant_htons(0x0016),
- CM_SIDR_REQ_ATTR_ID = __constant_htons(0x0017),
- CM_SIDR_REP_ATTR_ID = __constant_htons(0x0018),
- CM_LAP_ATTR_ID = __constant_htons(0x0019),
- CM_APR_ATTR_ID = __constant_htons(0x001A)
-};
+#define CM_REQ_ATTR_ID __constant_htons(0x0010)
+#define CM_MRA_ATTR_ID __constant_htons(0x0011)
+#define CM_REJ_ATTR_ID __constant_htons(0x0012)
+#define CM_REP_ATTR_ID __constant_htons(0x0013)
+#define CM_RTU_ATTR_ID __constant_htons(0x0014)
+#define CM_DREQ_ATTR_ID __constant_htons(0x0015)
+#define CM_DREP_ATTR_ID __constant_htons(0x0016)
+#define CM_SIDR_REQ_ATTR_ID __constant_htons(0x0017)
+#define CM_SIDR_REP_ATTR_ID __constant_htons(0x0018)
+#define CM_LAP_ATTR_ID __constant_htons(0x0019)
+#define CM_APR_ATTR_ID __constant_htons(0x001A)
enum cm_msg_sequence {
CM_MSG_SEQUENCE_REQ,
@@ -67,35 +65,35 @@ enum cm_msg_sequence {
struct cm_req_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 rsvd4;
- u64 service_id;
- u64 local_ca_guid;
- u32 rsvd24;
- u32 local_qkey;
+ __be32 local_comm_id;
+ __be32 rsvd4;
+ __be64 service_id;
+ __be64 local_ca_guid;
+ __be32 rsvd24;
+ __be32 local_qkey;
/* local QPN:24, responder resources:8 */
- u32 offset32;
+ __be32 offset32;
/* local EECN:24, initiator depth:8 */
- u32 offset36;
+ __be32 offset36;
/*
* remote EECN:24, remote CM response timeout:5,
* transport service type:2, end-to-end flow control:1
*/
- u32 offset40;
+ __be32 offset40;
/* starting PSN:24, local CM response timeout:5, retry count:3 */
- u32 offset44;
- u16 pkey;
+ __be32 offset44;
+ __be16 pkey;
/* path MTU:4, RDC exists:1, RNR retry count:3. */
u8 offset50;
/* max CM Retries:4, SRQ:1, rsvd:3 */
u8 offset51;
- u16 primary_local_lid;
- u16 primary_remote_lid;
+ __be16 primary_local_lid;
+ __be16 primary_remote_lid;
union ib_gid primary_local_gid;
union ib_gid primary_remote_gid;
/* flow label:20, rsvd:6, packet rate:6 */
- u32 primary_offset88;
+ __be32 primary_offset88;
u8 primary_traffic_class;
u8 primary_hop_limit;
/* SL:4, subnet local:1, rsvd:3 */
@@ -103,12 +101,12 @@ struct cm_req_msg {
/* local ACK timeout:5, rsvd:3 */
u8 primary_offset95;
- u16 alt_local_lid;
- u16 alt_remote_lid;
+ __be16 alt_local_lid;
+ __be16 alt_remote_lid;
union ib_gid alt_local_gid;
union ib_gid alt_remote_gid;
/* flow label:20, rsvd:6, packet rate:6 */
- u32 alt_offset132;
+ __be32 alt_offset132;
u8 alt_traffic_class;
u8 alt_hop_limit;
/* SL:4, subnet local:1, rsvd:3 */
@@ -120,12 +118,12 @@ struct cm_req_msg {
} __attribute__ ((packed));
-static inline u32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
{
return cpu_to_be32(be32_to_cpu(req_msg->offset32) >> 8);
}
-static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, u32 qpn)
+static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, __be32 qpn)
{
req_msg->offset32 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(req_msg->offset32) &
@@ -208,13 +206,13 @@ static inline void cm_req_set_flow_ctrl(struct cm_req_msg *req_msg,
0xFFFFFFFE));
}
-static inline u32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
{
return cpu_to_be32(be32_to_cpu(req_msg->offset44) >> 8);
}
static inline void cm_req_set_starting_psn(struct cm_req_msg *req_msg,
- u32 starting_psn)
+ __be32 starting_psn)
{
req_msg->offset44 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
(be32_to_cpu(req_msg->offset44) & 0x000000FF));
@@ -288,13 +286,13 @@ static inline void cm_req_set_srq(struct cm_req_msg *req_msg, u8 srq)
((srq & 0x1) << 3));
}
-static inline u32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
{
- return cpu_to_be32((be32_to_cpu(req_msg->primary_offset88) >> 12));
+ return cpu_to_be32(be32_to_cpu(req_msg->primary_offset88) >> 12);
}
static inline void cm_req_set_primary_flow_label(struct cm_req_msg *req_msg,
- u32 flow_label)
+ __be32 flow_label)
{
req_msg->primary_offset88 = cpu_to_be32(
(be32_to_cpu(req_msg->primary_offset88) &
@@ -350,13 +348,13 @@ static inline void cm_req_set_primary_local_ack_timeout(struct cm_req_msg *req_m
(local_ack_timeout << 3));
}
-static inline u32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
{
- return cpu_to_be32((be32_to_cpu(req_msg->alt_offset132) >> 12));
+ return cpu_to_be32(be32_to_cpu(req_msg->alt_offset132) >> 12);
}
static inline void cm_req_set_alt_flow_label(struct cm_req_msg *req_msg,
- u32 flow_label)
+ __be32 flow_label)
{
req_msg->alt_offset132 = cpu_to_be32(
(be32_to_cpu(req_msg->alt_offset132) &
@@ -422,8 +420,8 @@ enum cm_msg_response {
struct cm_mra_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* message MRAed:2, rsvd:6 */
u8 offset8;
/* service timeout:5, rsvd:3 */
@@ -458,13 +456,13 @@ static inline void cm_mra_set_service_timeout(struct cm_mra_msg *mra_msg,
struct cm_rej_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* message REJected:2, rsvd:6 */
u8 offset8;
/* reject info length:7, rsvd:1. */
u8 offset9;
- u16 reason;
+ __be16 reason;
u8 ari[IB_CM_REJ_ARI_LENGTH];
u8 private_data[IB_CM_REJ_PRIVATE_DATA_SIZE];
@@ -495,45 +493,45 @@ static inline void cm_rej_set_reject_info_len(struct cm_rej_msg *rej_msg,
struct cm_rep_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
- u32 local_qkey;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
+ __be32 local_qkey;
/* local QPN:24, rsvd:8 */
- u32 offset12;
+ __be32 offset12;
/* local EECN:24, rsvd:8 */
- u32 offset16;
+ __be32 offset16;
/* starting PSN:24 rsvd:8 */
- u32 offset20;
+ __be32 offset20;
u8 resp_resources;
u8 initiator_depth;
/* target ACK delay:5, failover accepted:2, end-to-end flow control:1 */
u8 offset26;
/* RNR retry count:3, SRQ:1, rsvd:5 */
u8 offset27;
- u64 local_ca_guid;
+ __be64 local_ca_guid;
u8 private_data[IB_CM_REP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset12) >> 8);
}
-static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, u32 qpn)
+static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
{
rep_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
}
-static inline u32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
}
static inline void cm_rep_set_starting_psn(struct cm_rep_msg *rep_msg,
- u32 starting_psn)
+ __be32 starting_psn)
{
rep_msg->offset20 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
(be32_to_cpu(rep_msg->offset20) & 0x000000FF));
@@ -600,8 +598,8 @@ static inline void cm_rep_set_srq(struct cm_rep_msg *rep_msg, u8 srq)
struct cm_rtu_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 private_data[IB_CM_RTU_PRIVATE_DATA_SIZE];
@@ -610,21 +608,21 @@ struct cm_rtu_msg {
struct cm_dreq_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* remote QPN/EECN:24, rsvd:8 */
- u32 offset8;
+ __be32 offset8;
u8 private_data[IB_CM_DREQ_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
+static inline __be32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
{
return cpu_to_be32(be32_to_cpu(dreq_msg->offset8) >> 8);
}
-static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
+static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, __be32 qpn)
{
dreq_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(dreq_msg->offset8) & 0x000000FF));
@@ -633,8 +631,8 @@ static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
struct cm_drep_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 private_data[IB_CM_DREP_PRIVATE_DATA_SIZE];
@@ -643,37 +641,37 @@ struct cm_drep_msg {
struct cm_lap_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
- u32 rsvd8;
+ __be32 rsvd8;
/* remote QPN/EECN:24, remote CM response timeout:5, rsvd:3 */
- u32 offset12;
- u32 rsvd16;
+ __be32 offset12;
+ __be32 rsvd16;
- u16 alt_local_lid;
- u16 alt_remote_lid;
+ __be16 alt_local_lid;
+ __be16 alt_remote_lid;
union ib_gid alt_local_gid;
union ib_gid alt_remote_gid;
/* flow label:20, rsvd:4, traffic class:8 */
- u32 offset56;
+ __be32 offset56;
u8 alt_hop_limit;
/* rsvd:2, packet rate:6 */
- uint8_t offset61;
+ u8 offset61;
/* SL:4, subnet local:1, rsvd:3 */
- uint8_t offset62;
+ u8 offset62;
/* local ACK timeout:5, rsvd:3 */
- uint8_t offset63;
+ u8 offset63;
u8 private_data[IB_CM_LAP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
{
return cpu_to_be32(be32_to_cpu(lap_msg->offset12) >> 8);
}
-static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, u32 qpn)
+static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, __be32 qpn)
{
lap_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(lap_msg->offset12) &
@@ -693,17 +691,17 @@ static inline void cm_lap_set_remote_resp_timeout(struct cm_lap_msg *lap_msg,
0xFFFFFF07));
}
-static inline u32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
{
- return be32_to_cpu(lap_msg->offset56) >> 12;
+ return cpu_to_be32(be32_to_cpu(lap_msg->offset56) >> 12);
}
static inline void cm_lap_set_flow_label(struct cm_lap_msg *lap_msg,
- u32 flow_label)
+ __be32 flow_label)
{
- lap_msg->offset56 = cpu_to_be32((flow_label << 12) |
- (be32_to_cpu(lap_msg->offset56) &
- 0x00000FFF));
+ lap_msg->offset56 = cpu_to_be32(
+ (be32_to_cpu(lap_msg->offset56) & 0x00000FFF) |
+ (be32_to_cpu(flow_label) << 12));
}
static inline u8 cm_lap_get_traffic_class(struct cm_lap_msg *lap_msg)
@@ -766,8 +764,8 @@ static inline void cm_lap_set_local_ack_timeout(struct cm_lap_msg *lap_msg,
struct cm_apr_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 info_length;
u8 ap_status;
@@ -779,10 +777,10 @@ struct cm_apr_msg {
struct cm_sidr_req_msg {
struct ib_mad_hdr hdr;
- u32 request_id;
- u16 pkey;
- u16 rsvd;
- u64 service_id;
+ __be32 request_id;
+ __be16 pkey;
+ __be16 rsvd;
+ __be64 service_id;
u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
@@ -790,26 +788,26 @@ struct cm_sidr_req_msg {
struct cm_sidr_rep_msg {
struct ib_mad_hdr hdr;
- u32 request_id;
+ __be32 request_id;
u8 status;
u8 info_length;
- u16 rsvd;
+ __be16 rsvd;
/* QPN:24, rsvd:8 */
- u32 offset8;
- u64 service_id;
- u32 qkey;
+ __be32 offset8;
+ __be64 service_id;
+ __be32 qkey;
u8 info[IB_CM_SIDR_REP_INFO_LENGTH];
u8 private_data[IB_CM_SIDR_REP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
+static inline __be32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
{
return cpu_to_be32(be32_to_cpu(sidr_rep_msg->offset8) >> 8);
}
static inline void cm_sidr_rep_set_qpn(struct cm_sidr_rep_msg *sidr_rep_msg,
- u32 qpn)
+ __be32 qpn)
{
sidr_rep_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(sidr_rep_msg->offset8) &
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 797049626ff6..7ad47a4b166b 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -38,7 +38,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
int ib_device_register_sysfs(struct ib_device *device);
void ib_device_unregister_sysfs(struct ib_device *device);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 9197e92d708a..d3cf84e01587 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 7763b31abba7..d34a6f1c4f4c 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -39,7 +39,7 @@
#include <linux/jhash.h>
#include <linux/kthread.h>
-#include <ib_fmr_pool.h>
+#include <rdma/ib_fmr_pool.h>
#include "core_priv.h"
@@ -334,6 +334,7 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
{
struct ib_pool_fmr *fmr;
struct ib_pool_fmr *tmp;
+ LIST_HEAD(fmr_list);
int i;
kthread_stop(pool->thread);
@@ -341,6 +342,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
i = 0;
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+ if (fmr->remap_count) {
+ INIT_LIST_HEAD(&fmr_list);
+ list_add_tail(&fmr->fmr->list, &fmr_list);
+ ib_unmap_fmr(&fmr_list);
+ }
ib_dealloc_fmr(fmr->fmr);
list_del(&fmr->list);
kfree(fmr);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b97e210ce9c8..a4a4d9c1eef3 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -693,7 +693,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
goto out;
}
- build_smp_wc(send_wr->wr_id, smp->dr_slid, send_wr->wr.ud.pkey_index,
+ build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
+ send_wr->wr.ud.pkey_index,
send_wr->wr.ud.port_num, &mad_wc);
/* No GRH for DR SMP */
@@ -1554,7 +1555,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
}
struct ib_mad_send_wr_private*
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
{
struct ib_mad_send_wr_private *mad_send_wr;
@@ -1597,7 +1598,7 @@ 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;
- u64 tid;
+ __be64 tid;
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
@@ -2165,7 +2166,8 @@ static void local_completions(void *data)
* Defined behavior is to complete response
* before request
*/
- build_smp_wc(local->wr_id, IB_LID_PERMISSIVE,
+ build_smp_wc(local->wr_id,
+ be16_to_cpu(IB_LID_PERMISSIVE),
0 /* pkey index */,
recv_mad_agent->agent.port_num, &wc);
@@ -2294,7 +2296,7 @@ static void timeout_sends(void *data)
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
}
-static void ib_mad_thread_completion_handler(struct ib_cq *cq)
+static void ib_mad_thread_completion_handler(struct ib_cq *cq, void *arg)
{
struct ib_mad_port_private *port_priv = cq->cq_context;
@@ -2574,8 +2576,7 @@ static int ib_mad_port_open(struct ib_device *device,
cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
port_priv->cq = ib_create_cq(port_priv->device,
- (ib_comp_handler)
- ib_mad_thread_completion_handler,
+ ib_mad_thread_completion_handler,
NULL, port_priv, cq_size);
if (IS_ERR(port_priv->cq)) {
printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 568da10b05ab..f1ba794e0daa 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -40,8 +40,8 @@
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
#define PFX "ib_mad: "
@@ -121,7 +121,7 @@ struct ib_mad_send_wr_private {
struct ib_send_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
u64 wr_id; /* client WR ID */
- u64 tid;
+ __be64 tid;
unsigned long timeout;
int retries;
int retry;
@@ -144,7 +144,7 @@ struct ib_mad_local_private {
struct ib_send_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
u64 wr_id; /* client WR ID */
- u64 tid;
+ __be64 tid;
};
struct ib_mad_mgmt_method_table {
@@ -210,7 +210,7 @@ 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, u64 tid);
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid);
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 8f1eb80e421f..2bd8b1cc57c4 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -61,7 +61,7 @@ struct mad_rmpp_recv {
int seg_num;
int newwin;
- u64 tid;
+ __be64 tid;
u32 src_qp;
u16 slid;
u8 mgmt_class;
@@ -100,6 +100,121 @@ 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 offsetof(struct ib_sa_mad, data);
+ else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+ (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
+ return offsetof(struct ib_vendor_mad, data);
+ else
+ return offsetof(struct ib_rmpp_mad, data);
+}
+
+static void format_ack(struct ib_rmpp_mad *ack,
+ struct ib_rmpp_mad *data,
+ struct mad_rmpp_recv *rmpp_recv)
+{
+ unsigned long flags;
+
+ memcpy(&ack->mad_hdr, &data->mad_hdr,
+ data_offset(data->mad_hdr.mgmt_class));
+
+ ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+ ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
+ ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+
+ spin_lock_irqsave(&rmpp_recv->lock, flags);
+ rmpp_recv->last_ack = rmpp_recv->seg_num;
+ ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
+ ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
+ spin_unlock_irqrestore(&rmpp_recv->lock, flags);
+}
+
+static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
+ struct ib_mad_recv_wc *recv_wc)
+{
+ struct ib_mad_send_buf *msg;
+ struct ib_send_wr *bad_send_wr;
+ int hdr_len, ret;
+
+ hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
+ msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
+ recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
+ hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
+ GFP_KERNEL);
+ if (!msg)
+ return;
+
+ format_ack((struct ib_rmpp_mad *) msg->mad,
+ (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
+ ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
+ &bad_send_wr);
+ if (ret)
+ ib_free_send_mad(msg);
+}
+
+static int alloc_response_msg(struct ib_mad_agent *agent,
+ struct ib_mad_recv_wc *recv_wc,
+ struct ib_mad_send_buf **msg)
+{
+ struct ib_mad_send_buf *m;
+ struct ib_ah *ah;
+ int hdr_len;
+
+ ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
+ recv_wc->recv_buf.grh, agent->port_num);
+ if (IS_ERR(ah))
+ return PTR_ERR(ah);
+
+ hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
+ m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
+ recv_wc->wc->pkey_index, ah, 1, hdr_len,
+ sizeof(struct ib_rmpp_mad) - hdr_len,
+ GFP_KERNEL);
+ if (IS_ERR(m)) {
+ ib_destroy_ah(ah);
+ return PTR_ERR(m);
+ }
+ *msg = m;
+ return 0;
+}
+
+static void free_msg(struct ib_mad_send_buf *msg)
+{
+ ib_destroy_ah(msg->send_wr.wr.ud.ah);
+ ib_free_send_mad(msg);
+}
+
+static void nack_recv(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *recv_wc, u8 rmpp_status)
+{
+ struct ib_mad_send_buf *msg;
+ struct ib_rmpp_mad *rmpp_mad;
+ struct ib_send_wr *bad_send_wr;
+ int ret;
+
+ ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
+ if (ret)
+ return;
+
+ rmpp_mad = (struct ib_rmpp_mad *) msg->mad;
+ memcpy(rmpp_mad, recv_wc->recv_buf.mad,
+ data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
+
+ rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+ rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION;
+ rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ABORT;
+ ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+ rmpp_mad->rmpp_hdr.rmpp_status = rmpp_status;
+ rmpp_mad->rmpp_hdr.seg_num = 0;
+ rmpp_mad->rmpp_hdr.paylen_newwin = 0;
+
+ ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr);
+ if (ret)
+ free_msg(msg);
+}
+
static void recv_timeout_handler(void *data)
{
struct mad_rmpp_recv *rmpp_recv = data;
@@ -115,8 +230,8 @@ static void recv_timeout_handler(void *data)
list_del(&rmpp_recv->list);
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
- /* TODO: send abort. */
rmpp_wc = rmpp_recv->rmpp_wc;
+ nack_recv(rmpp_recv->agent, rmpp_wc, IB_MGMT_RMPP_STATUS_T2L);
destroy_rmpp_recv(rmpp_recv);
ib_free_recv_mad(rmpp_wc);
}
@@ -230,60 +345,6 @@ insert_rmpp_recv(struct ib_mad_agent_private *agent,
return cur_rmpp_recv;
}
-static int data_offset(u8 mgmt_class)
-{
- if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
- return offsetof(struct ib_sa_mad, data);
- else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
- (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
- return offsetof(struct ib_vendor_mad, data);
- else
- return offsetof(struct ib_rmpp_mad, data);
-}
-
-static void format_ack(struct ib_rmpp_mad *ack,
- struct ib_rmpp_mad *data,
- struct mad_rmpp_recv *rmpp_recv)
-{
- unsigned long flags;
-
- memcpy(&ack->mad_hdr, &data->mad_hdr,
- data_offset(data->mad_hdr.mgmt_class));
-
- ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
- ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
- ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
-
- spin_lock_irqsave(&rmpp_recv->lock, flags);
- rmpp_recv->last_ack = rmpp_recv->seg_num;
- ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
- ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
- spin_unlock_irqrestore(&rmpp_recv->lock, flags);
-}
-
-static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
- struct ib_mad_recv_wc *recv_wc)
-{
- struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
- int hdr_len, ret;
-
- hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
- msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
- recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
- hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
- GFP_KERNEL);
- if (!msg)
- return;
-
- format_ack((struct ib_rmpp_mad *) msg->mad,
- (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
- ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
- &bad_send_wr);
- if (ret)
- ib_free_send_mad(msg);
-}
-
static inline int get_last_flag(struct ib_mad_recv_buf *seg)
{
struct ib_rmpp_mad *rmpp_mad;
@@ -532,7 +593,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
rmpp_mad->rmpp_hdr.paylen_newwin =
cpu_to_be32(mad_send_wr->total_seg *
(sizeof(struct ib_rmpp_mad) -
- offsetof(struct ib_rmpp_mad, data)));
+ offsetof(struct ib_rmpp_mad, data)) -
+ mad_send_wr->pad);
mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
} else {
mad_send_wr->send_wr.num_sge = 2;
@@ -541,6 +603,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
mad_send_wr->data_offset;
mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
+ rmpp_mad->rmpp_hdr.paylen_newwin = 0;
}
if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
@@ -559,6 +622,34 @@ 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)
+{
+ 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);
+ if (!mad_send_wr)
+ goto out; /* Unmatched send */
+
+ if ((mad_send_wr->last_ack == mad_send_wr->total_seg) ||
+ (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
+ goto out; /* Send is already done */
+
+ ib_mark_mad_done(mad_send_wr);
+ spin_unlock_irqrestore(&agent->lock, flags);
+
+ wc.status = IB_WC_REM_ABORT_ERR;
+ wc.vendor_err = rmpp_status;
+ wc.wr_id = mad_send_wr->wr_id;
+ ib_mad_complete_send_wr(mad_send_wr, &wc);
+ return;
+out:
+ spin_unlock_irqrestore(&agent->lock, flags);
+}
+
static void process_rmpp_ack(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
{
@@ -568,11 +659,21 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
int seg_num, newwin, ret;
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
- if (rmpp_mad->rmpp_hdr.rmpp_status)
+ if (rmpp_mad->rmpp_hdr.rmpp_status) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
return;
+ }
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);
+ 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);
@@ -583,8 +684,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
(!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
goto out; /* Send is already done */
- if (seg_num > mad_send_wr->total_seg)
- goto out; /* Bad ACK */
+ if (seg_num > mad_send_wr->total_seg || 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);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
+ return;
+ }
if (newwin < mad_send_wr->newwin || seg_num < mad_send_wr->last_ack)
goto out; /* Old ACK */
@@ -628,6 +734,72 @@ out:
spin_unlock_irqrestore(&agent->lock, flags);
}
+static struct ib_mad_recv_wc *
+process_rmpp_data(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_hdr *rmpp_hdr;
+ u8 rmpp_status;
+
+ rmpp_hdr = &((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr;
+
+ if (rmpp_hdr->rmpp_status) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_STATUS;
+ goto bad;
+ }
+
+ if (rmpp_hdr->seg_num == __constant_htonl(1)) {
+ if (!(ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST)) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+ goto bad;
+ }
+ return start_rmpp(agent, mad_recv_wc);
+ } else {
+ if (ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+ goto bad;
+ }
+ return continue_rmpp(agent, mad_recv_wc);
+ }
+bad:
+ nack_recv(agent, mad_recv_wc, rmpp_status);
+ ib_free_recv_mad(mad_recv_wc);
+ return NULL;
+}
+
+static void process_rmpp_stop(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_mad *rmpp_mad;
+
+ 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);
+ 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);
+}
+
+static void process_rmpp_abort(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_mad *rmpp_mad;
+
+ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+ 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);
+ 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);
+}
+
struct ib_mad_recv_wc *
ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
@@ -638,23 +810,29 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
if (!(rmpp_mad->rmpp_hdr.rmpp_rtime_flags & IB_MGMT_RMPP_FLAG_ACTIVE))
return mad_recv_wc;
- if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION)
+ if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_UNV);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
goto out;
+ }
switch (rmpp_mad->rmpp_hdr.rmpp_type) {
case IB_MGMT_RMPP_TYPE_DATA:
- if (rmpp_mad->rmpp_hdr.seg_num == __constant_htonl(1))
- return start_rmpp(agent, mad_recv_wc);
- else
- return continue_rmpp(agent, mad_recv_wc);
+ return process_rmpp_data(agent, mad_recv_wc);
case IB_MGMT_RMPP_TYPE_ACK:
process_rmpp_ack(agent, mad_recv_wc);
break;
case IB_MGMT_RMPP_TYPE_STOP:
+ process_rmpp_stop(agent, mad_recv_wc);
+ break;
case IB_MGMT_RMPP_TYPE_ABORT:
- /* TODO: process_rmpp_nack(agent, mad_recv_wc); */
+ process_rmpp_abort(agent, mad_recv_wc);
break;
default:
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BADT);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
break;
}
out:
@@ -714,7 +892,10 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
msg = (struct ib_mad_send_buf *) (unsigned long)
mad_send_wc->wr_id;
- ib_free_send_mad(msg);
+ if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
+ ib_free_send_mad(msg);
+ else
+ free_msg(msg);
return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */
}
diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c
index eb5ff54c10d7..35df5010e723 100644
--- a/drivers/infiniband/core/packer.c
+++ b/drivers/infiniband/core/packer.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -32,7 +33,7 @@
* $Id: packer.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
static u64 value_read(int offset, int size, void *structure)
{
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 795184931c83..78de2dd1a4f2 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 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
@@ -44,8 +44,8 @@
#include <linux/kref.h>
#include <linux/idr.h>
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -113,32 +113,6 @@ static DEFINE_IDR(query_idr);
static spinlock_t tid_lock;
static u32 tid;
-enum {
- IB_SA_ATTR_CLASS_PORTINFO = 0x01,
- IB_SA_ATTR_NOTICE = 0x02,
- IB_SA_ATTR_INFORM_INFO = 0x03,
- IB_SA_ATTR_NODE_REC = 0x11,
- IB_SA_ATTR_PORT_INFO_REC = 0x12,
- IB_SA_ATTR_SL2VL_REC = 0x13,
- IB_SA_ATTR_SWITCH_REC = 0x14,
- IB_SA_ATTR_LINEAR_FDB_REC = 0x15,
- IB_SA_ATTR_RANDOM_FDB_REC = 0x16,
- IB_SA_ATTR_MCAST_FDB_REC = 0x17,
- IB_SA_ATTR_SM_INFO_REC = 0x18,
- IB_SA_ATTR_LINK_REC = 0x20,
- IB_SA_ATTR_GUID_INFO_REC = 0x30,
- IB_SA_ATTR_SERVICE_REC = 0x31,
- IB_SA_ATTR_PARTITION_REC = 0x33,
- IB_SA_ATTR_RANGE_REC = 0x34,
- IB_SA_ATTR_PATH_REC = 0x35,
- IB_SA_ATTR_VL_ARB_REC = 0x36,
- IB_SA_ATTR_MC_GROUP_REC = 0x37,
- IB_SA_ATTR_MC_MEMBER_REC = 0x38,
- IB_SA_ATTR_TRACE_REC = 0x39,
- IB_SA_ATTR_MULTI_PATH_REC = 0x3a,
- IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b
-};
-
#define PATH_REC_FIELD(field) \
.struct_offset_bytes = offsetof(struct ib_sa_path_rec, field), \
.struct_size_bytes = sizeof ((struct ib_sa_path_rec *) 0)->field, \
@@ -431,8 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_SM_CHANGE) {
- struct ib_sa_device *sa_dev =
- ib_get_client_data(event->device, &sa_client);
+ struct ib_sa_device *sa_dev;
+ sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
schedule_work(&sa_dev->port[event->element.port_num -
sa_dev->start_port].update_task);
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index b4b284324a33..35852e794e26 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * 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, 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -36,7 +37,7 @@
* $Id: smi.c 1389 2004-12-27 22:56:47Z roland $
*/
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
#include "smi.h"
/*
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 90d51b179abe..211ba3223f65 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -34,7 +36,7 @@
#include "core_priv.h"
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
struct ib_port {
struct kobject kobj;
@@ -253,14 +255,14 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) gid.raw)[0]),
- be16_to_cpu(((u16 *) gid.raw)[1]),
- be16_to_cpu(((u16 *) gid.raw)[2]),
- be16_to_cpu(((u16 *) gid.raw)[3]),
- be16_to_cpu(((u16 *) gid.raw)[4]),
- be16_to_cpu(((u16 *) gid.raw)[5]),
- be16_to_cpu(((u16 *) gid.raw)[6]),
- be16_to_cpu(((u16 *) gid.raw)[7]));
+ be16_to_cpu(((__be16 *) gid.raw)[0]),
+ be16_to_cpu(((__be16 *) gid.raw)[1]),
+ be16_to_cpu(((__be16 *) gid.raw)[2]),
+ be16_to_cpu(((__be16 *) gid.raw)[3]),
+ be16_to_cpu(((__be16 *) gid.raw)[4]),
+ be16_to_cpu(((__be16 *) gid.raw)[5]),
+ be16_to_cpu(((__be16 *) gid.raw)[6]),
+ be16_to_cpu(((__be16 *) gid.raw)[7]));
}
static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
@@ -332,11 +334,11 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
break;
case 16:
ret = sprintf(buf, "%u\n",
- be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8)));
+ be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
break;
case 32:
ret = sprintf(buf, "%u\n",
- be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8)));
+ be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
break;
default:
ret = 0;
@@ -461,7 +463,7 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
return NULL;
for (i = 0; i < len; i++) {
- element = kcalloc(1, sizeof(struct port_table_attribute),
+ element = kzalloc(sizeof(struct port_table_attribute),
GFP_KERNEL);
if (!element)
goto err;
@@ -598,10 +600,10 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[3]));
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
}
static ssize_t show_node_guid(struct class_device *cdev, char *buf)
@@ -615,10 +617,10 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) &attr.node_guid)[0]),
- be16_to_cpu(((u16 *) &attr.node_guid)[1]),
- be16_to_cpu(((u16 *) &attr.node_guid)[2]),
- be16_to_cpu(((u16 *) &attr.node_guid)[3]));
+ be16_to_cpu(((__be16 *) &attr.node_guid)[0]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[1]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[2]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[3]));
}
static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 61d07c732f49..d0f0b0a2edd3 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel 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
@@ -71,16 +72,19 @@ enum {
static struct semaphore ctx_id_mutex;
static struct idr ctx_id_table;
-static int ctx_id_rover = 0;
-static struct ib_ucm_context *ib_ucm_ctx_get(int id)
+static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
{
struct ib_ucm_context *ctx;
down(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, id);
- if (ctx)
- ctx->ref++;
+ if (!ctx)
+ ctx = ERR_PTR(-ENOENT);
+ else if (ctx->file != file)
+ ctx = ERR_PTR(-EINVAL);
+ else
+ atomic_inc(&ctx->ref);
up(&ctx_id_mutex);
return ctx;
@@ -88,21 +92,20 @@ static struct ib_ucm_context *ib_ucm_ctx_get(int id)
static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
{
- struct ib_ucm_event *uevent;
-
- down(&ctx_id_mutex);
-
- ctx->ref--;
- if (!ctx->ref)
- idr_remove(&ctx_id_table, ctx->id);
+ if (atomic_dec_and_test(&ctx->ref))
+ wake_up(&ctx->wait);
+}
- up(&ctx_id_mutex);
+static inline int ib_ucm_new_cm_id(int event)
+{
+ return event == IB_CM_REQ_RECEIVED || event == IB_CM_SIDR_REQ_RECEIVED;
+}
- if (ctx->ref)
- return;
+static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
+{
+ struct ib_ucm_event *uevent;
down(&ctx->file->mutex);
-
list_del(&ctx->file_list);
while (!list_empty(&ctx->events)) {
@@ -112,18 +115,12 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
list_del(&uevent->ctx_list);
/* clear incoming connections. */
- if (uevent->cm_id)
+ if (ib_ucm_new_cm_id(uevent->resp.event))
ib_destroy_cm_id(uevent->cm_id);
kfree(uevent);
}
-
up(&ctx->file->mutex);
-
- ucm_dbg("Destroyed CM ID <%d>\n", ctx->id);
-
- ib_destroy_cm_id(ctx->cm_id);
- kfree(ctx);
}
static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -135,36 +132,31 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
if (!ctx)
return NULL;
- ctx->ref = 1; /* user reference */
+ memset(ctx, 0, sizeof *ctx);
+ atomic_set(&ctx->ref, 1);
+ init_waitqueue_head(&ctx->wait);
ctx->file = file;
-
INIT_LIST_HEAD(&ctx->events);
- init_MUTEX(&ctx->mutex);
-
- list_add_tail(&ctx->file_list, &file->ctxs);
- ctx_id_rover = (ctx_id_rover + 1) & INT_MAX;
-retry:
- result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
- if (!result)
- goto error;
+ do {
+ result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
+ if (!result)
+ goto error;
- down(&ctx_id_mutex);
- result = idr_get_new_above(&ctx_id_table, ctx, ctx_id_rover, &ctx->id);
- up(&ctx_id_mutex);
+ down(&ctx_id_mutex);
+ result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
+ up(&ctx_id_mutex);
+ } while (result == -EAGAIN);
- if (result == -EAGAIN)
- goto retry;
if (result)
goto error;
+ list_add_tail(&ctx->file_list, &file->ctxs);
ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
-
return ctx;
+
error:
- list_del(&ctx->file_list);
kfree(ctx);
-
return NULL;
}
/*
@@ -177,8 +169,8 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
if (!kpath || !upath)
return;
- memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid));
- memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid));
+ memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
+ memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
upath->dlid = kpath->dlid;
upath->slid = kpath->slid;
@@ -204,8 +196,6 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
struct ib_cm_req_event_param *kreq)
{
- ureq->listen_id = (long)kreq->listen_id->context;
-
ureq->remote_ca_guid = kreq->remote_ca_guid;
ureq->remote_qkey = kreq->remote_qkey;
ureq->remote_qpn = kreq->remote_qpn;
@@ -240,37 +230,6 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
urep->srq = krep->srq;
}
-static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej,
- struct ib_cm_rej_event_param *krej)
-{
- urej->reason = krej->reason;
-}
-
-static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra,
- struct ib_cm_mra_event_param *kmra)
-{
- umra->timeout = kmra->service_timeout;
-}
-
-static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap,
- struct ib_cm_lap_event_param *klap)
-{
- ib_ucm_event_path_get(&ulap->path, klap->alternate_path);
-}
-
-static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr,
- struct ib_cm_apr_event_param *kapr)
-{
- uapr->status = kapr->ap_status;
-}
-
-static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq,
- struct ib_cm_sidr_req_event_param *kreq)
-{
- ureq->listen_id = (long)kreq->listen_id->context;
- ureq->pkey = kreq->pkey;
-}
-
static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
struct ib_cm_sidr_rep_event_param *krep)
{
@@ -283,15 +242,13 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
struct ib_ucm_event *uvt)
{
void *info = NULL;
- int result;
switch (evt->event) {
case IB_CM_REQ_RECEIVED:
ib_ucm_event_req_get(&uvt->resp.u.req_resp,
&evt->param.req_rcvd);
uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE;
- uvt->resp.present |= (evt->param.req_rcvd.primary_path ?
- IB_UCM_PRES_PRIMARY : 0);
+ uvt->resp.present = IB_UCM_PRES_PRIMARY;
uvt->resp.present |= (evt->param.req_rcvd.alternate_path ?
IB_UCM_PRES_ALTERNATE : 0);
break;
@@ -299,57 +256,46 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
ib_ucm_event_rep_get(&uvt->resp.u.rep_resp,
&evt->param.rep_rcvd);
uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_RTU_RECEIVED:
uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_DREQ_RECEIVED:
uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_DREP_RECEIVED:
uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_MRA_RECEIVED:
- ib_ucm_event_mra_get(&uvt->resp.u.mra_resp,
- &evt->param.mra_rcvd);
+ uvt->resp.u.mra_resp.timeout =
+ evt->param.mra_rcvd.service_timeout;
uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_REJ_RECEIVED:
- ib_ucm_event_rej_get(&uvt->resp.u.rej_resp,
- &evt->param.rej_rcvd);
+ uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason;
uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.rej_rcvd.ari_length;
info = evt->param.rej_rcvd.ari;
-
break;
case IB_CM_LAP_RECEIVED:
- ib_ucm_event_lap_get(&uvt->resp.u.lap_resp,
- &evt->param.lap_rcvd);
+ ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
+ evt->param.lap_rcvd.alternate_path);
uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
- uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ?
- IB_UCM_PRES_ALTERNATE : 0);
+ uvt->resp.present = IB_UCM_PRES_ALTERNATE;
break;
case IB_CM_APR_RECEIVED:
- ib_ucm_event_apr_get(&uvt->resp.u.apr_resp,
- &evt->param.apr_rcvd);
+ uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status;
uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.apr_rcvd.info_len;
info = evt->param.apr_rcvd.apr_info;
-
break;
case IB_CM_SIDR_REQ_RECEIVED:
- ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp,
- &evt->param.sidr_req_rcvd);
+ uvt->resp.u.sidr_req_resp.pkey =
+ evt->param.sidr_req_rcvd.pkey;
uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_SIDR_REP_RECEIVED:
ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp,
@@ -357,43 +303,35 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.sidr_rep_rcvd.info_len;
info = evt->param.sidr_rep_rcvd.info;
-
break;
default:
uvt->resp.u.send_status = evt->param.send_status;
-
break;
}
- if (uvt->data_len && evt->private_data) {
-
+ if (uvt->data_len) {
uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
- if (!uvt->data) {
- result = -ENOMEM;
- goto error;
- }
+ if (!uvt->data)
+ goto err1;
memcpy(uvt->data, evt->private_data, uvt->data_len);
uvt->resp.present |= IB_UCM_PRES_DATA;
}
- if (uvt->info_len && info) {
-
+ if (uvt->info_len) {
uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
- if (!uvt->info) {
- result = -ENOMEM;
- goto error;
- }
+ if (!uvt->info)
+ goto err2;
memcpy(uvt->info, info, uvt->info_len);
uvt->resp.present |= IB_UCM_PRES_INFO;
}
-
return 0;
-error:
- kfree(uvt->info);
+
+err2:
kfree(uvt->data);
- return result;
+err1:
+ return -ENOMEM;
}
static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
@@ -402,64 +340,36 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
struct ib_ucm_event *uevent;
struct ib_ucm_context *ctx;
int result = 0;
- int id;
- /*
- * lookup correct context based on event type.
- */
- switch (event->event) {
- case IB_CM_REQ_RECEIVED:
- id = (long)event->param.req_rcvd.listen_id->context;
- break;
- case IB_CM_SIDR_REQ_RECEIVED:
- id = (long)event->param.sidr_req_rcvd.listen_id->context;
- break;
- default:
- id = (long)cm_id->context;
- break;
- }
- ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event);
-
- ctx = ib_ucm_ctx_get(id);
- if (!ctx)
- return -ENOENT;
-
- if (event->event == IB_CM_REQ_RECEIVED ||
- event->event == IB_CM_SIDR_REQ_RECEIVED)
- id = IB_UCM_CM_ID_INVALID;
+ ctx = cm_id->context;
uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
- if (!uevent) {
- result = -ENOMEM;
- goto done;
- }
+ if (!uevent)
+ goto err1;
memset(uevent, 0, sizeof(*uevent));
-
- uevent->resp.id = id;
+ uevent->ctx = ctx;
+ uevent->cm_id = cm_id;
+ uevent->resp.uid = ctx->uid;
+ uevent->resp.id = ctx->id;
uevent->resp.event = event->event;
result = ib_ucm_event_process(event, uevent);
if (result)
- goto done;
-
- uevent->ctx = ctx;
- uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED ||
- event->event == IB_CM_SIDR_REQ_RECEIVED ) ?
- cm_id : NULL);
+ goto err2;
down(&ctx->file->mutex);
-
list_add_tail(&uevent->file_list, &ctx->file->events);
list_add_tail(&uevent->ctx_list, &ctx->events);
-
wake_up_interruptible(&ctx->file->poll_wait);
-
up(&ctx->file->mutex);
-done:
- ctx->error = result;
- ib_ucm_ctx_put(ctx); /* func reference */
- return result;
+ return 0;
+
+err2:
+ kfree(uevent);
+err1:
+ /* Destroy new cm_id's */
+ return ib_ucm_new_cm_id(event->event);
}
static ssize_t ib_ucm_event(struct ib_ucm_file *file,
@@ -468,7 +378,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
{
struct ib_ucm_context *ctx;
struct ib_ucm_event_get cmd;
- struct ib_ucm_event *uevent = NULL;
+ struct ib_ucm_event *uevent;
int result = 0;
DEFINE_WAIT(wait);
@@ -481,7 +391,6 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
* wait
*/
down(&file->mutex);
-
while (list_empty(&file->events)) {
if (file->filp->f_flags & O_NONBLOCK) {
@@ -508,22 +417,18 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
uevent = list_entry(file->events.next, struct ib_ucm_event, file_list);
- if (!uevent->cm_id)
- goto user;
+ if (ib_ucm_new_cm_id(uevent->resp.event)) {
+ ctx = ib_ucm_ctx_alloc(file);
+ if (!ctx) {
+ result = -ENOMEM;
+ goto done;
+ }
- ctx = ib_ucm_ctx_alloc(file);
- if (!ctx) {
- result = -ENOMEM;
- goto done;
+ ctx->cm_id = uevent->cm_id;
+ ctx->cm_id->context = ctx;
+ uevent->resp.id = ctx->id;
}
- ctx->cm_id = uevent->cm_id;
- ctx->cm_id->cm_handler = ib_ucm_event_handler;
- ctx->cm_id->context = (void *)(unsigned long)ctx->id;
-
- uevent->resp.id = ctx->id;
-
-user:
if (copy_to_user((void __user *)(unsigned long)cmd.response,
&uevent->resp, sizeof(uevent->resp))) {
result = -EFAULT;
@@ -531,12 +436,10 @@ user:
}
if (uevent->data) {
-
if (cmd.data_len < uevent->data_len) {
result = -ENOMEM;
goto done;
}
-
if (copy_to_user((void __user *)(unsigned long)cmd.data,
uevent->data, uevent->data_len)) {
result = -EFAULT;
@@ -545,12 +448,10 @@ user:
}
if (uevent->info) {
-
if (cmd.info_len < uevent->info_len) {
result = -ENOMEM;
goto done;
}
-
if (copy_to_user((void __user *)(unsigned long)cmd.info,
uevent->info, uevent->info_len)) {
result = -EFAULT;
@@ -560,6 +461,7 @@ user:
list_del(&uevent->file_list);
list_del(&uevent->ctx_list);
+ uevent->ctx->events_reported++;
kfree(uevent->data);
kfree(uevent->info);
@@ -585,30 +487,37 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
+ down(&file->mutex);
ctx = ib_ucm_ctx_alloc(file);
+ up(&file->mutex);
if (!ctx)
return -ENOMEM;
- ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler,
- (void *)(unsigned long)ctx->id);
- if (!ctx->cm_id) {
- result = -ENOMEM;
- goto err_cm;
+ ctx->uid = cmd.uid;
+ ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
+ if (IS_ERR(ctx->cm_id)) {
+ result = PTR_ERR(ctx->cm_id);
+ goto err;
}
resp.id = ctx->id;
if (copy_to_user((void __user *)(unsigned long)cmd.response,
&resp, sizeof(resp))) {
result = -EFAULT;
- goto err_ret;
+ goto err;
}
return 0;
-err_ret:
- ib_destroy_cm_id(ctx->cm_id);
-err_cm:
- ib_ucm_ctx_put(ctx); /* user reference */
+err:
+ down(&ctx_id_mutex);
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
+
+ if (!IS_ERR(ctx->cm_id))
+ ib_destroy_cm_id(ctx->cm_id);
+
+ kfree(ctx);
return result;
}
@@ -617,19 +526,44 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
int in_len, int out_len)
{
struct ib_ucm_destroy_id cmd;
+ struct ib_ucm_destroy_id_resp resp;
struct ib_ucm_context *ctx;
+ int result = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
+ down(&ctx_id_mutex);
+ ctx = idr_find(&ctx_id_table, cmd.id);
if (!ctx)
- return -ENOENT;
+ ctx = ERR_PTR(-ENOENT);
+ else if (ctx->file != file)
+ ctx = ERR_PTR(-EINVAL);
+ else
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
- ib_ucm_ctx_put(ctx); /* user reference */
- ib_ucm_ctx_put(ctx); /* func reference */
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- return 0;
+ atomic_dec(&ctx->ref);
+ wait_event(ctx->wait, !atomic_read(&ctx->ref));
+
+ /* No new events will be generated after destroying the cm_id. */
+ ib_destroy_cm_id(ctx->cm_id);
+ /* Cleanup events not yet reported to the user. */
+ ib_ucm_cleanup_events(ctx);
+
+ resp.events_reported = ctx->events_reported;
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ result = -EFAULT;
+
+ kfree(ctx);
+ return result;
}
static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
@@ -647,15 +581,9 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
-
- down(&ctx->file->mutex);
- if (ctx->file != file) {
- result = -EINVAL;
- goto done;
- }
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
resp.service_id = ctx->cm_id->service_id;
resp.service_mask = ctx->cm_id->service_mask;
@@ -666,9 +594,99 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
&resp, sizeof(resp)))
result = -EFAULT;
-done:
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ ib_ucm_ctx_put(ctx);
+ return result;
+}
+
+static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
+ struct ib_ah_attr *src_attr)
+{
+ memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
+ sizeof src_attr->grh.dgid);
+ dest_attr->grh_flow_label = src_attr->grh.flow_label;
+ dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
+ dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
+ dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
+
+ dest_attr->dlid = src_attr->dlid;
+ dest_attr->sl = src_attr->sl;
+ dest_attr->src_path_bits = src_attr->src_path_bits;
+ dest_attr->static_rate = src_attr->static_rate;
+ dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
+ dest_attr->port_num = src_attr->port_num;
+}
+
+static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
+ struct ib_qp_attr *src_attr)
+{
+ dest_attr->cur_qp_state = src_attr->cur_qp_state;
+ dest_attr->path_mtu = src_attr->path_mtu;
+ dest_attr->path_mig_state = src_attr->path_mig_state;
+ dest_attr->qkey = src_attr->qkey;
+ dest_attr->rq_psn = src_attr->rq_psn;
+ dest_attr->sq_psn = src_attr->sq_psn;
+ dest_attr->dest_qp_num = src_attr->dest_qp_num;
+ dest_attr->qp_access_flags = src_attr->qp_access_flags;
+
+ dest_attr->max_send_wr = src_attr->cap.max_send_wr;
+ dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
+ dest_attr->max_send_sge = src_attr->cap.max_send_sge;
+ dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
+ dest_attr->max_inline_data = src_attr->cap.max_inline_data;
+
+ ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
+ ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
+
+ dest_attr->pkey_index = src_attr->pkey_index;
+ dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
+ dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
+ dest_attr->sq_draining = src_attr->sq_draining;
+ dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
+ dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
+ dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
+ dest_attr->port_num = src_attr->port_num;
+ dest_attr->timeout = src_attr->timeout;
+ dest_attr->retry_cnt = src_attr->retry_cnt;
+ dest_attr->rnr_retry = src_attr->rnr_retry;
+ dest_attr->alt_port_num = src_attr->alt_port_num;
+ dest_attr->alt_timeout = src_attr->alt_timeout;
+}
+
+static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct ib_ucm_init_qp_attr_resp resp;
+ struct ib_ucm_init_qp_attr cmd;
+ struct ib_ucm_context *ctx;
+ struct ib_qp_attr qp_attr;
+ int result = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ resp.qp_attr_mask = 0;
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_state = cmd.qp_state;
+ result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
+ if (result)
+ goto out;
+
+ ib_ucm_copy_qp_attr(&resp, &qp_attr);
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ result = -EFAULT;
+
+out:
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -683,19 +701,12 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_cm_listen(ctx->cm_id, cmd.service_id,
- cmd.service_mask);
-
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -710,18 +721,12 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_cm_establish(ctx->cm_id);
-
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ result = ib_cm_establish(ctx->cm_id);
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -768,8 +773,8 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
return -EFAULT;
}
- memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid));
- memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid));
+ memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
+ memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
sa_path->dlid = ucm_path.dlid;
sa_path->slid = ucm_path.slid;
@@ -839,25 +844,17 @@ static ssize_t ib_ucm_send_req(struct ib_ucm_file *file,
param.max_cm_retries = cmd.max_cm_retries;
param.srq = cmd.srq;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_req(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.primary_path);
kfree(param.alternate_path);
-
return result;
}
@@ -890,23 +887,15 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
param.rnr_retry_count = cmd.rnr_retry_count;
param.srq = cmd.srq;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ ctx->uid = cmd.uid;
result = ib_send_cm_rep(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(param.private_data);
-
return result;
}
@@ -928,23 +917,14 @@ static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file,
if (result)
return result;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = func(ctx->cm_id, private_data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(private_data);
-
return result;
}
@@ -995,26 +975,17 @@ static ssize_t ib_ucm_send_info(struct ib_ucm_file *file,
if (result)
goto done;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = func(ctx->cm_id, cmd.status,
- info, cmd.info_len,
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ result = func(ctx->cm_id, cmd.status, info, cmd.info_len,
data, cmd.data_len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(data);
kfree(info);
-
return result;
}
@@ -1048,24 +1019,14 @@ static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file,
if (result)
return result;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_send_cm_mra(ctx->cm_id, cmd.timeout,
- data, cmd.len);
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(data);
-
return result;
}
@@ -1090,24 +1051,16 @@ static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file,
if (result)
goto done;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(data);
kfree(path);
-
return result;
}
@@ -1140,24 +1093,16 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
param.max_cm_retries = cmd.max_cm_retries;
param.pkey = cmd.pkey;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_sidr_req(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.path);
-
return result;
}
@@ -1184,30 +1129,22 @@ static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file,
if (result)
goto done;
- param.qp_num = cmd.qpn;
- param.qkey = cmd.qkey;
- param.status = cmd.status;
- param.info_length = cmd.info_len;
- param.private_data_len = cmd.data_len;
+ param.qp_num = cmd.qpn;
+ param.qkey = cmd.qkey;
+ param.status = cmd.status;
+ param.info_length = cmd.info_len;
+ param.private_data_len = cmd.data_len;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_sidr_rep(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.info);
-
return result;
}
@@ -1231,6 +1168,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
[IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req,
[IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep,
[IB_USER_CM_CMD_EVENT] = ib_ucm_event,
+ [IB_USER_CM_CMD_INIT_QP_ATTR] = ib_ucm_init_qp_attr,
};
static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
@@ -1305,22 +1243,23 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
struct ib_ucm_context *ctx;
down(&file->mutex);
-
while (!list_empty(&file->ctxs)) {
-
ctx = list_entry(file->ctxs.next,
struct ib_ucm_context, file_list);
+ up(&file->mutex);
+
+ down(&ctx_id_mutex);
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
+
+ ib_destroy_cm_id(ctx->cm_id);
+ ib_ucm_cleanup_events(ctx);
+ kfree(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* user reference */
down(&file->mutex);
}
-
up(&file->mutex);
-
kfree(file);
-
- ucm_dbg("Deleted struct\n");
return 0;
}
diff --git a/drivers/infiniband/core/ucm.h b/drivers/infiniband/core/ucm.h
index 6d36606151b2..f46f37bc1201 100644
--- a/drivers/infiniband/core/ucm.h
+++ b/drivers/infiniband/core/ucm.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel 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
@@ -40,17 +41,13 @@
#include <linux/cdev.h>
#include <linux/idr.h>
-#include <ib_cm.h>
-#include <ib_user_cm.h>
-
-#define IB_UCM_CM_ID_INVALID 0xffffffff
+#include <rdma/ib_cm.h>
+#include <rdma/ib_user_cm.h>
struct ib_ucm_file {
struct semaphore mutex;
struct file *filp;
- /*
- * list of pending events
- */
+
struct list_head ctxs; /* list of active connections */
struct list_head events; /* list of pending events */
wait_queue_head_t poll_wait;
@@ -58,12 +55,13 @@ struct ib_ucm_file {
struct ib_ucm_context {
int id;
- int ref;
- int error;
+ wait_queue_head_t wait;
+ atomic_t ref;
+ int events_reported;
struct ib_ucm_file *file;
struct ib_cm_id *cm_id;
- struct semaphore mutex;
+ __u64 uid;
struct list_head events; /* list of pending events. */
struct list_head file_list; /* member in file ctx list */
@@ -74,16 +72,12 @@ struct ib_ucm_event {
struct list_head file_list; /* member in file event list */
struct list_head ctx_list; /* member in ctx event list */
+ struct ib_cm_id *cm_id;
struct ib_ucm_event_resp resp;
void *data;
void *info;
int data_len;
int info_len;
- /*
- * new connection identifiers needs to be saved until
- * userspace can get a handle on them.
- */
- struct ib_cm_id *cm_id;
};
#endif /* UCM_H */
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index dc4eb1db5e96..527b23450ab3 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -34,7 +35,7 @@
#include <linux/errno.h>
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
#define STRUCT_FIELD(header, field) \
.struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \
@@ -194,6 +195,7 @@ void ib_ud_header_init(int payload_bytes,
struct ib_ud_header *header)
{
int header_len;
+ u16 packet_length;
memset(header, 0, sizeof *header);
@@ -208,7 +210,7 @@ void ib_ud_header_init(int payload_bytes,
header->lrh.link_version = 0;
header->lrh.link_next_header =
grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
- header->lrh.packet_length = (IB_LRH_BYTES +
+ packet_length = (IB_LRH_BYTES +
IB_BTH_BYTES +
IB_DETH_BYTES +
payload_bytes +
@@ -217,8 +219,7 @@ void ib_ud_header_init(int payload_bytes,
header->grh_present = grh_present;
if (grh_present) {
- header->lrh.packet_length += IB_GRH_BYTES / 4;
-
+ packet_length += IB_GRH_BYTES / 4;
header->grh.ip_version = 6;
header->grh.payload_length =
cpu_to_be16((IB_BTH_BYTES +
@@ -229,7 +230,7 @@ void ib_ud_header_init(int payload_bytes,
header->grh.next_header = 0x1b;
}
- cpu_to_be16s(&header->lrh.packet_length);
+ header->lrh.packet_length = cpu_to_be16(packet_length);
if (header->immediate_present)
header->bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 2e38792df533..7c2f03057ddb 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -49,8 +49,8 @@
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <ib_mad.h>
-#include <ib_user_mad.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_mad.h>
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
@@ -271,7 +271,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
struct ib_send_wr *bad_wr;
struct ib_rmpp_mad *rmpp_mad;
u8 method;
- u64 *tid;
+ __be64 *tid;
int ret, length, hdr_len, data_len, rmpp_hdr_size;
int rmpp_active = 0;
@@ -316,7 +316,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
if (packet->mad.hdr.grh_present) {
ah_attr.ah_flags = IB_AH_GRH;
memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
- ah_attr.grh.flow_label = packet->mad.hdr.flow_label;
+ ah_attr.grh.flow_label = be32_to_cpu(packet->mad.hdr.flow_label);
ah_attr.grh.hop_limit = packet->mad.hdr.hop_limit;
ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 7696022f9a4e..b1897bed14ad 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 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
@@ -43,8 +45,8 @@
#include <linux/kref.h>
#include <linux/idr.h>
-#include <ib_verbs.h>
-#include <ib_user_verbs.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
struct ib_uverbs_device {
int devnum;
@@ -74,20 +76,28 @@ struct ib_uverbs_file {
struct ib_uverbs_event_file comp_file[1];
};
-struct ib_uverbs_async_event {
- struct ib_uverbs_async_event_desc desc;
+struct ib_uverbs_event {
+ union {
+ struct ib_uverbs_async_event_desc async;
+ struct ib_uverbs_comp_event_desc comp;
+ } desc;
struct list_head list;
+ struct list_head obj_list;
+ u32 *counter;
};
-struct ib_uverbs_comp_event {
- struct ib_uverbs_comp_event_desc desc;
- struct list_head list;
+struct ib_uevent_object {
+ struct ib_uobject uobject;
+ struct list_head event_list;
+ u32 events_reported;
};
-struct ib_uobject_mr {
- struct ib_uobject uobj;
- struct page *page_list;
- struct scatterlist *sg_list;
+struct ib_ucq_object {
+ struct ib_uobject uobject;
+ struct list_head comp_list;
+ struct list_head async_list;
+ u32 comp_events_reported;
+ u32 async_events_reported;
};
extern struct semaphore ib_uverbs_idr_mutex;
@@ -97,10 +107,12 @@ extern struct idr ib_uverbs_mw_idr;
extern struct idr ib_uverbs_ah_idr;
extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr;
+extern struct idr ib_uverbs_srq_idr;
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
void *addr, size_t size, int write);
@@ -129,5 +141,8 @@ IB_UVERBS_DECLARE_CMD(modify_qp);
IB_UVERBS_DECLARE_CMD(destroy_qp);
IB_UVERBS_DECLARE_CMD(attach_mcast);
IB_UVERBS_DECLARE_CMD(detach_mcast);
+IB_UVERBS_DECLARE_CMD(create_srq);
+IB_UVERBS_DECLARE_CMD(modify_srq);
+IB_UVERBS_DECLARE_CMD(destroy_srq);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5f2bbcda4c73..e91ebde46481 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -590,7 +590,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_create_cq_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_ucq_object *uobj;
struct ib_cq *cq;
int ret;
@@ -611,8 +611,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->comp_events_reported = 0;
+ uobj->async_events_reported = 0;
+ INIT_LIST_HEAD(&uobj->comp_list);
+ INIT_LIST_HEAD(&uobj->async_list);
cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
file->ucontext, &udata);
@@ -622,7 +626,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
}
cq->device = file->device->ib_dev;
- cq->uobject = uobj;
+ cq->uobject = &uobj->uobject;
cq->comp_handler = ib_uverbs_comp_handler;
cq->event_handler = ib_uverbs_cq_event_handler;
cq->cq_context = file;
@@ -635,7 +639,7 @@ retry:
}
down(&ib_uverbs_idr_mutex);
- ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
up(&ib_uverbs_idr_mutex);
if (ret == -EAGAIN)
@@ -644,11 +648,11 @@ retry:
goto err_cq;
spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->cq_list);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
spin_unlock_irq(&file->ucontext->lock);
memset(&resp, 0, sizeof resp);
- resp.cq_handle = uobj->id;
+ resp.cq_handle = uobj->uobject.id;
resp.cqe = cq->cqe;
if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -661,11 +665,11 @@ retry:
err_list:
spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
+ list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
down(&ib_uverbs_idr_mutex);
- idr_remove(&ib_uverbs_cq_idr, uobj->id);
+ idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
up(&ib_uverbs_idr_mutex);
err_cq:
@@ -680,21 +684,27 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_cq cmd;
- struct ib_cq *cq;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_cq cmd;
+ struct ib_uverbs_destroy_cq_resp resp;
+ struct ib_cq *cq;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ u64 user_handle;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext)
goto out;
- uobj = cq->uobject;
+ user_handle = cq->uobject->user_handle;
+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
ret = ib_destroy_cq(cq);
if (ret)
@@ -703,11 +713,32 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
+ list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
+ spin_lock_irq(&file->comp_file[0].lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->comp_file[0].lock);
+
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.comp_events_reported = uobj->comp_events_reported;
+ resp.async_events_reported = uobj->async_events_reported;
+
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);
@@ -721,9 +752,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
struct ib_uverbs_create_qp cmd;
struct ib_uverbs_create_qp_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_uevent_object *uobj;
struct ib_pd *pd;
struct ib_cq *scq, *rcq;
+ struct ib_srq *srq;
struct ib_qp *qp;
struct ib_qp_init_attr attr;
int ret;
@@ -747,10 +779,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
+ srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
if (!pd || pd->uobject->context != file->ucontext ||
!scq || scq->uobject->context != file->ucontext ||
- !rcq || rcq->uobject->context != file->ucontext) {
+ !rcq || rcq->uobject->context != file->ucontext ||
+ (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
ret = -EINVAL;
goto err_up;
}
@@ -759,7 +793,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.qp_context = file;
attr.send_cq = scq;
attr.recv_cq = rcq;
- attr.srq = NULL;
+ attr.srq = srq;
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
attr.qp_type = cmd.qp_type;
@@ -769,8 +803,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.cap.max_recv_sge = cmd.max_recv_sge;
attr.cap.max_inline_data = cmd.max_inline_data;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
qp = pd->device->create_qp(pd, &attr, &udata);
if (IS_ERR(qp)) {
@@ -783,7 +819,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
qp->send_cq = attr.send_cq;
qp->recv_cq = attr.recv_cq;
qp->srq = attr.srq;
- qp->uobject = uobj;
+ qp->uobject = &uobj->uobject;
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
@@ -802,17 +838,17 @@ retry:
goto err_destroy;
}
- ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
if (ret == -EAGAIN)
goto retry;
if (ret)
goto err_destroy;
- resp.qp_handle = uobj->id;
+ resp.qp_handle = uobj->uobject.id;
spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->qp_list);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
spin_unlock_irq(&file->ucontext->lock);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -827,7 +863,7 @@ retry:
err_list:
spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
+ list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
err_destroy:
@@ -927,21 +963,25 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_qp cmd;
- struct ib_qp *qp;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_qp cmd;
+ struct ib_uverbs_destroy_qp_resp resp;
+ struct ib_qp *qp;
+ struct ib_uevent_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
goto out;
- uobj = qp->uobject;
+ uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
ret = ib_destroy_qp(qp);
if (ret)
@@ -950,11 +990,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
+ list_del(&uobj->uobject.list);
spin_unlock_irq(&file->ucontext->lock);
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.events_reported = uobj->events_reported;
+
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);
@@ -1004,3 +1057,197 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
return ret ? ret : in_len;
}
+
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_srq cmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ struct ib_uevent_object *uobj;
+ struct ib_pd *pd;
+ struct ib_srq *srq;
+ struct ib_srq_init_attr attr;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+ if (!uobj)
+ return -ENOMEM;
+
+ down(&ib_uverbs_idr_mutex);
+
+ pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+
+ if (!pd || pd->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto err_up;
+ }
+
+ attr.event_handler = ib_uverbs_srq_event_handler;
+ attr.srq_context = file;
+ attr.attr.max_wr = cmd.max_wr;
+ attr.attr.max_sge = cmd.max_sge;
+ attr.attr.srq_limit = cmd.srq_limit;
+
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
+
+ srq = pd->device->create_srq(pd, &attr, &udata);
+ if (IS_ERR(srq)) {
+ ret = PTR_ERR(srq);
+ goto err_up;
+ }
+
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->uobject = &uobj->uobject;
+ srq->event_handler = attr.event_handler;
+ srq->srq_context = attr.srq_context;
+ atomic_inc(&pd->usecnt);
+ atomic_set(&srq->usecnt, 0);
+
+ memset(&resp, 0, sizeof resp);
+
+retry:
+ if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto err_destroy;
+ }
+
+ ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
+
+ if (ret == -EAGAIN)
+ goto retry;
+ if (ret)
+ goto err_destroy;
+
+ resp.srq_handle = uobj->uobject.id;
+
+ spin_lock_irq(&file->ucontext->lock);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+ spin_unlock_irq(&file->ucontext->lock);
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_list;
+ }
+
+ up(&ib_uverbs_idr_mutex);
+
+ return in_len;
+
+err_list:
+ spin_lock_irq(&file->ucontext->lock);
+ list_del(&uobj->uobject.list);
+ spin_unlock_irq(&file->ucontext->lock);
+
+err_destroy:
+ ib_destroy_srq(srq);
+
+err_up:
+ up(&ib_uverbs_idr_mutex);
+
+ kfree(uobj);
+ return ret;
+}
+
+ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_modify_srq cmd;
+ struct ib_srq *srq;
+ struct ib_srq_attr attr;
+ int ret;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+
+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+ if (!srq || srq->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ attr.max_wr = cmd.max_wr;
+ attr.max_sge = cmd.max_sge;
+ attr.srq_limit = cmd.srq_limit;
+
+ ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_destroy_srq cmd;
+ struct ib_uverbs_destroy_srq_resp resp;
+ struct ib_srq *srq;
+ struct ib_uevent_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ int ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+
+ memset(&resp, 0, sizeof resp);
+
+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+ if (!srq || srq->uobject->context != file->ucontext)
+ goto out;
+
+ uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
+
+ ret = ib_destroy_srq(srq);
+ if (ret)
+ goto out;
+
+ idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+
+ spin_lock_irq(&file->ucontext->lock);
+ list_del(&uobj->uobject.list);
+ spin_unlock_irq(&file->ucontext->lock);
+
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.events_reported = uobj->events_reported;
+
+ kfree(uobj);
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ return ret ? ret : in_len;
+}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 5f6e9ea29cd7..ce5bdb7af306 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 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
@@ -67,6 +69,7 @@ DEFINE_IDR(ib_uverbs_mw_idr);
DEFINE_IDR(ib_uverbs_ah_idr);
DEFINE_IDR(ib_uverbs_cq_idr);
DEFINE_IDR(ib_uverbs_qp_idr);
+DEFINE_IDR(ib_uverbs_srq_idr);
static spinlock_t map_lock;
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -91,6 +94,9 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
[IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
[IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
+ [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
+ [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
+ [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
};
static struct vfsmount *uverbs_event_mnt;
@@ -114,7 +120,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
idr_remove(&ib_uverbs_qp_idr, uobj->id);
ib_destroy_qp(qp);
list_del(&uobj->list);
- kfree(uobj);
+ kfree(container_of(uobj, struct ib_uevent_object, uobject));
}
list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -122,10 +128,17 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
idr_remove(&ib_uverbs_cq_idr, uobj->id);
ib_destroy_cq(cq);
list_del(&uobj->list);
- kfree(uobj);
+ kfree(container_of(uobj, struct ib_ucq_object, uobject));
+ }
+
+ list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+ struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+ idr_remove(&ib_uverbs_srq_idr, uobj->id);
+ ib_destroy_srq(srq);
+ list_del(&uobj->list);
+ kfree(container_of(uobj, struct ib_uevent_object, uobject));
}
- /* XXX Free SRQs */
/* XXX Free MWs */
list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
@@ -169,7 +182,7 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
{
struct ib_uverbs_event_file *file = filp->private_data;
- void *event;
+ struct ib_uverbs_event *event;
int eventsz;
int ret = 0;
@@ -194,21 +207,23 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
return -ENODEV;
}
- if (file->is_async) {
- event = list_entry(file->event_list.next,
- struct ib_uverbs_async_event, list);
+ event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
+
+ if (file->is_async)
eventsz = sizeof (struct ib_uverbs_async_event_desc);
- } else {
- event = list_entry(file->event_list.next,
- struct ib_uverbs_comp_event, list);
+ else
eventsz = sizeof (struct ib_uverbs_comp_event_desc);
- }
if (eventsz > count) {
ret = -EINVAL;
event = NULL;
- } else
+ } else {
list_del(file->event_list.next);
+ if (event->counter) {
+ ++(*event->counter);
+ list_del(&event->obj_list);
+ }
+ }
spin_unlock_irq(&file->lock);
@@ -244,16 +259,13 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
{
- struct list_head *entry, *tmp;
+ struct ib_uverbs_event *entry, *tmp;
spin_lock_irq(&file->lock);
if (file->fd != -1) {
file->fd = -1;
- list_for_each_safe(entry, tmp, &file->event_list)
- if (file->is_async)
- kfree(list_entry(entry, struct ib_uverbs_async_event, list));
- else
- kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
+ list_for_each_entry_safe(entry, tmp, &file->event_list, list)
+ kfree(entry);
}
spin_unlock_irq(&file->lock);
}
@@ -291,18 +303,23 @@ static struct file_operations uverbs_event_fops = {
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
{
- struct ib_uverbs_file *file = cq_context;
- struct ib_uverbs_comp_event *entry;
- unsigned long flags;
+ struct ib_uverbs_file *file = cq_context;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event *entry;
+ unsigned long flags;
entry = kmalloc(sizeof *entry, GFP_ATOMIC);
if (!entry)
return;
- entry->desc.cq_handle = cq->uobject->user_handle;
+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
+
+ entry->desc.comp.cq_handle = cq->uobject->user_handle;
+ entry->counter = &uobj->comp_events_reported;
spin_lock_irqsave(&file->comp_file[0].lock, flags);
list_add_tail(&entry->list, &file->comp_file[0].event_list);
+ list_add_tail(&entry->obj_list, &uobj->comp_list);
spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
wake_up_interruptible(&file->comp_file[0].poll_wait);
@@ -310,20 +327,25 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
}
static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
- __u64 element, __u64 event)
+ __u64 element, __u64 event,
+ struct list_head *obj_list,
+ u32 *counter)
{
- struct ib_uverbs_async_event *entry;
+ struct ib_uverbs_event *entry;
unsigned long flags;
entry = kmalloc(sizeof *entry, GFP_ATOMIC);
if (!entry)
return;
- entry->desc.element = element;
- entry->desc.event_type = event;
+ entry->desc.async.element = element;
+ entry->desc.async.event_type = event;
+ entry->counter = counter;
spin_lock_irqsave(&file->async_file.lock, flags);
list_add_tail(&entry->list, &file->async_file.event_list);
+ if (obj_list)
+ list_add_tail(&entry->obj_list, obj_list);
spin_unlock_irqrestore(&file->async_file.lock, flags);
wake_up_interruptible(&file->async_file.poll_wait);
@@ -332,16 +354,39 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
{
- ib_uverbs_async_handler(context_ptr,
- event->element.cq->uobject->user_handle,
- event->event);
+ struct ib_ucq_object *uobj;
+
+ uobj = container_of(event->element.cq->uobject,
+ struct ib_ucq_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->async_list,
+ &uobj->async_events_reported);
+
}
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
{
- ib_uverbs_async_handler(context_ptr,
- event->element.qp->uobject->user_handle,
- event->event);
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.qp->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
+}
+
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
+{
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.srq->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
}
static void ib_uverbs_event_handler(struct ib_event_handler *handler,
@@ -350,7 +395,8 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_uverbs_file *file =
container_of(handler, struct ib_uverbs_file, event_handler);
- ib_uverbs_async_handler(file, event->element.port_num, event->event);
+ ib_uverbs_async_handler(file, event->element.port_num, event->event,
+ NULL, NULL);
}
static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
index ed550f6595bd..36a32c315668 100644
--- a/drivers/infiniband/core/uverbs_mem.c
+++ b/drivers/infiniband/core/uverbs_mem.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 506fdf1f2a26..5081d903e561 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -4,6 +4,7 @@
* 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) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -40,8 +41,8 @@
#include <linux/errno.h>
#include <linux/err.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
/* Protection domains */
@@ -153,6 +154,66 @@ int ib_destroy_ah(struct ib_ah *ah)
}
EXPORT_SYMBOL(ib_destroy_ah);
+/* Shared receive queues */
+
+struct ib_srq *ib_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *srq_init_attr)
+{
+ struct ib_srq *srq;
+
+ if (!pd->device->create_srq)
+ return ERR_PTR(-ENOSYS);
+
+ srq = pd->device->create_srq(pd, srq_init_attr, NULL);
+
+ if (!IS_ERR(srq)) {
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->uobject = NULL;
+ srq->event_handler = srq_init_attr->event_handler;
+ srq->srq_context = srq_init_attr->srq_context;
+ atomic_inc(&pd->usecnt);
+ atomic_set(&srq->usecnt, 0);
+ }
+
+ return srq;
+}
+EXPORT_SYMBOL(ib_create_srq);
+
+int ib_modify_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask)
+{
+ return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);
+}
+EXPORT_SYMBOL(ib_modify_srq);
+
+int ib_query_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr)
+{
+ return srq->device->query_srq ?
+ srq->device->query_srq(srq, srq_attr) : -ENOSYS;
+}
+EXPORT_SYMBOL(ib_query_srq);
+
+int ib_destroy_srq(struct ib_srq *srq)
+{
+ struct ib_pd *pd;
+ int ret;
+
+ if (atomic_read(&srq->usecnt))
+ return -EBUSY;
+
+ pd = srq->pd;
+
+ ret = srq->device->destroy_srq(srq);
+ if (!ret)
+ atomic_dec(&pd->usecnt);
+
+ return ret;
+}
+EXPORT_SYMBOL(ib_destroy_srq);
+
/* Queue pairs */
struct ib_qp *ib_create_qp(struct ib_pd *pd,
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index 5dcbd43073e2..c44f7bae5424 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
EXTRA_CFLAGS += -DDEBUG
endif
@@ -9,4 +7,4 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
- mthca_provider.o mthca_memfree.o mthca_uar.o
+ mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index b1db48dd91d6..9ba3211cef7c 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -177,3 +177,119 @@ void mthca_array_cleanup(struct mthca_array *array, int nent)
kfree(array->page_list);
}
+
+/*
+ * Handling for queue buffers -- we allocate a bunch of memory and
+ * register it in a memory region at HCA virtual address 0. If the
+ * requested size is > max_direct, we split the allocation into
+ * multiple pages, so we don't require too much contiguous memory.
+ */
+
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+ union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+ int hca_write, struct mthca_mr *mr)
+{
+ int err = -ENOMEM;
+ int npages, shift;
+ u64 *dma_list = NULL;
+ dma_addr_t t;
+ int i;
+
+ if (size <= max_direct) {
+ *is_direct = 1;
+ npages = 1;
+ shift = get_order(size) + PAGE_SHIFT;
+
+ buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev,
+ size, &t, GFP_KERNEL);
+ if (!buf->direct.buf)
+ return -ENOMEM;
+
+ pci_unmap_addr_set(&buf->direct, mapping, t);
+
+ memset(buf->direct.buf, 0, size);
+
+ while (t & ((1 << shift) - 1)) {
+ --shift;
+ npages *= 2;
+ }
+
+ dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ if (!dma_list)
+ goto err_free;
+
+ for (i = 0; i < npages; ++i)
+ dma_list[i] = t + i * (1 << shift);
+ } else {
+ *is_direct = 0;
+ npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ shift = PAGE_SHIFT;
+
+ dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ if (!dma_list)
+ return -ENOMEM;
+
+ buf->page_list = kmalloc(npages * sizeof *buf->page_list,
+ GFP_KERNEL);
+ if (!buf->page_list)
+ goto err_out;
+
+ for (i = 0; i < npages; ++i)
+ buf->page_list[i].buf = NULL;
+
+ for (i = 0; i < npages; ++i) {
+ buf->page_list[i].buf =
+ dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
+ &t, GFP_KERNEL);
+ if (!buf->page_list[i].buf)
+ goto err_free;
+
+ dma_list[i] = t;
+ pci_unmap_addr_set(&buf->page_list[i], mapping, t);
+
+ memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+ }
+ }
+
+ err = mthca_mr_alloc_phys(dev, pd->pd_num,
+ dma_list, shift, npages,
+ 0, size,
+ MTHCA_MPT_FLAG_LOCAL_READ |
+ (hca_write ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0),
+ mr);
+ if (err)
+ goto err_free;
+
+ kfree(dma_list);
+
+ return 0;
+
+err_free:
+ mthca_buf_free(dev, size, buf, *is_direct, NULL);
+
+err_out:
+ kfree(dma_list);
+
+ return err;
+}
+
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+ int is_direct, struct mthca_mr *mr)
+{
+ int i;
+
+ if (mr)
+ mthca_free_mr(dev, mr);
+
+ if (is_direct)
+ dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
+ pci_unmap_addr(&buf->direct, mapping));
+ else {
+ for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ buf->page_list[i].buf,
+ pci_unmap_addr(&buf->page_list[i],
+ mapping));
+ kfree(buf->page_list);
+ }
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index d58dcbe66488..889e85096736 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -35,22 +35,22 @@
#include <linux/init.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
#include "mthca_dev.h"
struct mthca_av {
- u32 port_pd;
- u8 reserved1;
- u8 g_slid;
- u16 dlid;
- u8 reserved2;
- u8 gid_index;
- u8 msg_sr;
- u8 hop_limit;
- u32 sl_tclass_flowlabel;
- u32 dgid[4];
+ __be32 port_pd;
+ u8 reserved1;
+ u8 g_slid;
+ __be16 dlid;
+ u8 reserved2;
+ u8 gid_index;
+ u8 msg_sr;
+ u8 hop_limit;
+ __be32 sl_tclass_flowlabel;
+ __be32 dgid[4];
};
int mthca_create_ah(struct mthca_dev *dev,
@@ -128,7 +128,7 @@ on_hca_fail:
av, (unsigned long) ah->avdma);
for (j = 0; j < 8; ++j)
printk(KERN_DEBUG " [%2x] %08x\n",
- j * 4, be32_to_cpu(((u32 *) av)[j]));
+ j * 4, be32_to_cpu(((__be32 *) av)[j]));
}
if (ah->type == MTHCA_AH_ON_HCA) {
@@ -169,7 +169,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
header->lrh.destination_lid = ah->av->dlid;
- header->lrh.source_lid = ah->av->g_slid & 0x7f;
+ header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f);
if (ah->av->g_slid & 0x80) {
header->grh_present = 1;
header->grh.traffic_class =
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 1557a522d831..cc758a2d2bc6 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -36,7 +37,7 @@
#include <linux/pci.h>
#include <linux/errno.h>
#include <asm/io.h>
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
#include "mthca_dev.h"
#include "mthca_config_reg.h"
@@ -108,6 +109,7 @@ enum {
CMD_SW2HW_SRQ = 0x35,
CMD_HW2SW_SRQ = 0x36,
CMD_QUERY_SRQ = 0x37,
+ CMD_ARM_SRQ = 0x40,
/* QP/EE commands */
CMD_RST2INIT_QPEE = 0x19,
@@ -219,20 +221,20 @@ static int mthca_cmd_post(struct mthca_dev *dev,
* (and some architectures such as ia64 implement memcpy_toio
* in terms of writeb).
*/
- __raw_writel(cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
- __raw_writel(cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
- __raw_writel(cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
- __raw_writel(cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
- __raw_writel(cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
- __raw_writel(cpu_to_be32(token << 16), dev->hcr + 5 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
+ __raw_writel((__force u32) cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
+ __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
+ __raw_writel((__force u32) cpu_to_be32(token << 16), dev->hcr + 5 * 4);
/* __raw_writel may not order writes. */
wmb();
- __raw_writel(cpu_to_be32((1 << HCR_GO_BIT) |
- (event ? (1 << HCA_E_BIT) : 0) |
- (op_modifier << HCR_OPMOD_SHIFT) |
- op), dev->hcr + 6 * 4);
+ __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
+ (event ? (1 << HCA_E_BIT) : 0) |
+ (op_modifier << HCR_OPMOD_SHIFT) |
+ op), dev->hcr + 6 * 4);
out:
up(&dev->cmd.hcr_sem);
@@ -273,12 +275,14 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
goto out;
}
- if (out_is_imm) {
- memcpy_fromio(out_param, dev->hcr + HCR_OUT_PARAM_OFFSET, sizeof (u64));
- be64_to_cpus(out_param);
- }
+ if (out_is_imm)
+ *out_param =
+ (u64) be32_to_cpu((__force __be32)
+ __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
+ (u64) be32_to_cpu((__force __be32)
+ __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
- *status = be32_to_cpu(__raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
out:
up(&dev->cmd.poll_sem);
@@ -1029,6 +1033,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
+ mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
+ dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
@@ -1082,6 +1088,34 @@ out:
return err;
}
+static void get_board_id(void *vsd, char *board_id)
+{
+ int i;
+
+#define VSD_OFFSET_SIG1 0x00
+#define VSD_OFFSET_SIG2 0xde
+#define VSD_OFFSET_MLX_BOARD_ID 0xd0
+#define VSD_OFFSET_TS_BOARD_ID 0x20
+
+#define VSD_SIGNATURE_TOPSPIN 0x5ad
+
+ memset(board_id, 0, MTHCA_BOARD_ID_LEN);
+
+ if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
+ be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
+ strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
+ } else {
+ /*
+ * The board ID is a string but the firmware byte
+ * swaps each 4-byte word before passing it back to
+ * us. Therefore we need to swab it before printing.
+ */
+ for (i = 0; i < 4; ++i)
+ ((u32 *) board_id)[i] =
+ swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
+ }
+}
+
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
struct mthca_adapter *adapter, u8 *status)
{
@@ -1094,6 +1128,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04
#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
+#define QUERY_ADAPTER_VSD_OFFSET 0x20
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -1111,6 +1146,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
+ get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
+ adapter->board_id);
+
out:
mthca_free_mailbox(dev, mailbox);
return err;
@@ -1121,7 +1159,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
u8 *status)
{
struct mthca_mailbox *mailbox;
- u32 *inbox;
+ __be32 *inbox;
int err;
#define INIT_HCA_IN_SIZE 0x200
@@ -1247,10 +1285,8 @@ int mthca_INIT_IB(struct mthca_dev *dev,
#define INIT_IB_FLAG_SIG (1 << 18)
#define INIT_IB_FLAG_NG (1 << 17)
#define INIT_IB_FLAG_G0 (1 << 16)
-#define INIT_IB_FLAG_1X (1 << 8)
-#define INIT_IB_FLAG_4X (1 << 9)
-#define INIT_IB_FLAG_12X (1 << 11)
#define INIT_IB_VL_SHIFT 4
+#define INIT_IB_PORT_WIDTH_SHIFT 8
#define INIT_IB_MTU_SHIFT 12
#define INIT_IB_MAX_GID_OFFSET 0x06
#define INIT_IB_MAX_PKEY_OFFSET 0x0a
@@ -1266,12 +1302,11 @@ int mthca_INIT_IB(struct mthca_dev *dev,
memset(inbox, 0, INIT_IB_IN_SIZE);
flags = 0;
- flags |= param->enable_1x ? INIT_IB_FLAG_1X : 0;
- flags |= param->enable_4x ? INIT_IB_FLAG_4X : 0;
flags |= param->set_guid0 ? INIT_IB_FLAG_G0 : 0;
flags |= param->set_node_guid ? INIT_IB_FLAG_NG : 0;
flags |= param->set_si_guid ? INIT_IB_FLAG_SIG : 0;
flags |= param->vl_cap << INIT_IB_VL_SHIFT;
+ flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT;
flags |= param->mtu_cap << INIT_IB_MTU_SHIFT;
MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET);
@@ -1342,7 +1377,7 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st
int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
{
struct mthca_mailbox *mailbox;
- u64 *inbox;
+ __be64 *inbox;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -1468,6 +1503,27 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
CMD_TIME_CLASS_A, status);
}
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status)
+{
+ return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
+ CMD_TIME_CLASS_A, status);
+}
+
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status)
+{
+ return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
+ CMD_HW2SW_SRQ,
+ CMD_TIME_CLASS_A, status);
+}
+
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+{
+ return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
+ CMD_TIME_CLASS_B, status);
+}
+
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
u8 *status)
@@ -1513,7 +1569,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
if (i % 8 == 0)
printk(" [%02x] ", i * 4);
printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
@@ -1533,7 +1589,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
if (i % 8 == 0)
printk("[%02x] ", i * 4);
printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index ed517f175dd6..65f976a13e02 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -35,7 +36,7 @@
#ifndef MTHCA_CMD_H
#define MTHCA_CMD_H
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
#define MTHCA_MAILBOX_SIZE 4096
@@ -183,10 +184,11 @@ struct mthca_dev_lim {
};
struct mthca_adapter {
- u32 vendor_id;
- u32 device_id;
- u32 revision_id;
- u8 inta_pin;
+ u32 vendor_id;
+ u32 device_id;
+ u32 revision_id;
+ char board_id[MTHCA_BOARD_ID_LEN];
+ u8 inta_pin;
};
struct mthca_init_hca_param {
@@ -218,8 +220,7 @@ struct mthca_init_hca_param {
};
struct mthca_init_ib_param {
- int enable_1x;
- int enable_4x;
+ int port_width;
int vl_cap;
int mtu_cap;
u16 gid_cap;
@@ -297,6 +298,11 @@ int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
int cq_num, u8 *status);
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
int cq_num, u8 *status);
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status);
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
u8 *status);
diff --git a/drivers/infiniband/hw/mthca/mthca_config_reg.h b/drivers/infiniband/hw/mthca/mthca_config_reg.h
index b4bfbbfe2c3d..afa56bfaab2e 100644
--- a/drivers/infiniband/hw/mthca/mthca_config_reg.h
+++ b/drivers/infiniband/hw/mthca/mthca_config_reg.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 5687c3014522..8600b6c3e0c2 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 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
@@ -37,7 +39,7 @@
#include <linux/init.h>
#include <linux/hardirq.h>
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -55,21 +57,21 @@ enum {
* Must be packed because start is 64 bits but only aligned to 32 bits.
*/
struct mthca_cq_context {
- u32 flags;
- u64 start;
- u32 logsize_usrpage;
- u32 error_eqn; /* Tavor only */
- u32 comp_eqn;
- u32 pd;
- u32 lkey;
- u32 last_notified_index;
- u32 solicit_producer_index;
- u32 consumer_index;
- u32 producer_index;
- u32 cqn;
- u32 ci_db; /* Arbel only */
- u32 state_db; /* Arbel only */
- u32 reserved;
+ __be32 flags;
+ __be64 start;
+ __be32 logsize_usrpage;
+ __be32 error_eqn; /* Tavor only */
+ __be32 comp_eqn;
+ __be32 pd;
+ __be32 lkey;
+ __be32 last_notified_index;
+ __be32 solicit_producer_index;
+ __be32 consumer_index;
+ __be32 producer_index;
+ __be32 cqn;
+ __be32 ci_db; /* Arbel only */
+ __be32 state_db; /* Arbel only */
+ u32 reserved;
} __attribute__((packed));
#define MTHCA_CQ_STATUS_OK ( 0 << 28)
@@ -108,31 +110,31 @@ enum {
};
struct mthca_cqe {
- u32 my_qpn;
- u32 my_ee;
- u32 rqpn;
- u16 sl_g_mlpath;
- u16 rlid;
- u32 imm_etype_pkey_eec;
- u32 byte_cnt;
- u32 wqe;
- u8 opcode;
- u8 is_send;
- u8 reserved;
- u8 owner;
+ __be32 my_qpn;
+ __be32 my_ee;
+ __be32 rqpn;
+ __be16 sl_g_mlpath;
+ __be16 rlid;
+ __be32 imm_etype_pkey_eec;
+ __be32 byte_cnt;
+ __be32 wqe;
+ u8 opcode;
+ u8 is_send;
+ u8 reserved;
+ u8 owner;
};
struct mthca_err_cqe {
- u32 my_qpn;
- u32 reserved1[3];
- u8 syndrome;
- u8 reserved2;
- u16 db_cnt;
- u32 reserved3;
- u32 wqe;
- u8 opcode;
- u8 reserved4[2];
- u8 owner;
+ __be32 my_qpn;
+ u32 reserved1[3];
+ u8 syndrome;
+ u8 reserved2;
+ __be16 db_cnt;
+ u32 reserved3;
+ __be32 wqe;
+ u8 opcode;
+ u8 reserved4[2];
+ u8 owner;
};
#define MTHCA_CQ_ENTRY_OWNER_SW (0 << 7)
@@ -191,7 +193,7 @@ static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
int incr)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
if (mthca_is_memfree(dev)) {
*cq->set_ci_db = cpu_to_be32(cq->cons_index);
@@ -222,7 +224,8 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
}
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+ struct mthca_srq *srq)
{
struct mthca_cq *cq;
struct mthca_cqe *cqe;
@@ -263,8 +266,11 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
*/
while (prod_index > cq->cons_index) {
cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe);
- if (cqe->my_qpn == cpu_to_be32(qpn))
+ if (cqe->my_qpn == cpu_to_be32(qpn)) {
+ if (srq)
+ mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
++nfreed;
+ }
else if (nfreed)
memcpy(get_cqe(cq, (prod_index - 1 + nfreed) &
cq->ibcq.cqe),
@@ -291,7 +297,7 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
{
int err;
int dbd;
- u32 new_wqe;
+ __be32 new_wqe;
if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
mthca_dbg(dev, "local QP operation err "
@@ -365,6 +371,13 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
break;
}
+ /*
+ * Mem-free HCAs always generate one CQE per WQE, even in the
+ * error case, so we don't have to check the doorbell count, etc.
+ */
+ if (mthca_is_memfree(dev))
+ return 0;
+
err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
if (err)
return err;
@@ -373,12 +386,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
* If we're at the end of the WQE chain, or we've used up our
* doorbell count, free the CQE. Otherwise just update it for
* the next poll operation.
- *
- * This does not apply to mem-free HCAs: they don't use the
- * doorbell count field, and so we should always free the CQE.
*/
- if (mthca_is_memfree(dev) ||
- !(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
+ if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
return 0;
cqe->db_cnt = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd);
@@ -450,23 +459,27 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
>> wq->wqe_shift);
entry->wr_id = (*cur_qp)->wrid[wqe_index +
(*cur_qp)->rq.max];
+ } else if ((*cur_qp)->ibqp.srq) {
+ struct mthca_srq *srq = to_msrq((*cur_qp)->ibqp.srq);
+ u32 wqe = be32_to_cpu(cqe->wqe);
+ wq = NULL;
+ wqe_index = wqe >> srq->wqe_shift;
+ entry->wr_id = srq->wrid[wqe_index];
+ mthca_free_srq_wqe(srq, wqe);
} else {
wq = &(*cur_qp)->rq;
wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
entry->wr_id = (*cur_qp)->wrid[wqe_index];
}
- if (wq->last_comp < wqe_index)
- wq->tail += wqe_index - wq->last_comp;
- else
- wq->tail += wqe_index + wq->max - wq->last_comp;
-
- wq->last_comp = wqe_index;
+ if (wq) {
+ if (wq->last_comp < wqe_index)
+ wq->tail += wqe_index - wq->last_comp;
+ else
+ wq->tail += wqe_index + wq->max - wq->last_comp;
- if (0)
- mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
- is_send ? "Send" : "Receive",
- (*cur_qp)->qpn, wqe_index, wq->max);
+ wq->last_comp = wqe_index;
+ }
if (is_error) {
err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
@@ -584,13 +597,13 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
MTHCA_TAVOR_CQ_DB_REQ_NOT) |
to_mcq(cq)->cqn);
- doorbell[1] = 0xffffffff;
+ doorbell[1] = (__force __be32) 0xffffffff;
mthca_write64(doorbell,
to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
@@ -602,9 +615,9 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
{
struct mthca_cq *cq = to_mcq(ibcq);
- u32 doorbell[2];
+ __be32 doorbell[2];
u32 sn;
- u32 ci;
+ __be32 ci;
sn = cq->arm_sn & 3;
ci = cpu_to_be32(cq->cons_index);
@@ -637,113 +650,8 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
{
- int i;
- int size;
-
- if (cq->is_direct)
- dma_free_coherent(&dev->pdev->dev,
- (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
- cq->queue.direct.buf,
- pci_unmap_addr(&cq->queue.direct,
- mapping));
- else {
- size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
- for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
- if (cq->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- cq->queue.page_list[i].buf,
- pci_unmap_addr(&cq->queue.page_list[i],
- mapping));
-
- kfree(cq->queue.page_list);
- }
-}
-
-static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
- struct mthca_cq *cq)
-{
- int err = -ENOMEM;
- int npages, shift;
- u64 *dma_list = NULL;
- dma_addr_t t;
- int i;
-
- if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
- cq->is_direct = 1;
- npages = 1;
- shift = get_order(size) + PAGE_SHIFT;
-
- cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev,
- size, &t, GFP_KERNEL);
- if (!cq->queue.direct.buf)
- return -ENOMEM;
-
- pci_unmap_addr_set(&cq->queue.direct, mapping, t);
-
- memset(cq->queue.direct.buf, 0, size);
-
- while (t & ((1 << shift) - 1)) {
- --shift;
- npages *= 2;
- }
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_free;
-
- for (i = 0; i < npages; ++i)
- dma_list[i] = t + i * (1 << shift);
- } else {
- cq->is_direct = 0;
- npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
- shift = PAGE_SHIFT;
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- return -ENOMEM;
-
- cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
- GFP_KERNEL);
- if (!cq->queue.page_list)
- goto err_out;
-
- for (i = 0; i < npages; ++i)
- cq->queue.page_list[i].buf = NULL;
-
- for (i = 0; i < npages; ++i) {
- cq->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
- if (!cq->queue.page_list[i].buf)
- goto err_free;
-
- dma_list[i] = t;
- pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
-
- memset(cq->queue.page_list[i].buf, 0, PAGE_SIZE);
- }
- }
-
- err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
- dma_list, shift, npages,
- 0, size,
- MTHCA_MPT_FLAG_LOCAL_WRITE |
- MTHCA_MPT_FLAG_LOCAL_READ,
- &cq->mr);
- if (err)
- goto err_free;
-
- kfree(dma_list);
-
- return 0;
-
-err_free:
- mthca_free_cq_buf(dev, cq);
-
-err_out:
- kfree(dma_list);
-
- return err;
+ mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+ &cq->queue, cq->is_direct, &cq->mr);
}
int mthca_init_cq(struct mthca_dev *dev, int nent,
@@ -795,7 +703,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context = mailbox->buf;
if (cq->is_kernel) {
- err = mthca_alloc_cq_buf(dev, size, cq);
+ err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE,
+ &cq->queue, &cq->is_direct,
+ &dev->driver_pd, 1, &cq->mr);
if (err)
goto err_out_mailbox;
@@ -811,7 +721,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context->flags = cpu_to_be32(MTHCA_CQ_STATUS_OK |
MTHCA_CQ_STATE_DISARMED |
MTHCA_CQ_FLAG_TR);
- cq_context->start = cpu_to_be64(0);
cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
if (ctx)
cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
@@ -857,10 +766,8 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
return 0;
err_out_free_mr:
- if (cq->is_kernel) {
- mthca_free_mr(dev, &cq->mr);
+ if (cq->is_kernel)
mthca_free_cq_buf(dev, cq);
- }
err_out_mailbox:
mthca_free_mailbox(dev, mailbox);
@@ -904,7 +811,7 @@ void mthca_free_cq(struct mthca_dev *dev,
mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
if (0) {
- u32 *ctx = mailbox->buf;
+ __be32 *ctx = mailbox->buf;
int j;
printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
@@ -928,7 +835,6 @@ void mthca_free_cq(struct mthca_dev *dev,
wait_event(cq->wait, !atomic_read(&cq->refcount));
if (cq->is_kernel) {
- mthca_free_mr(dev, &cq->mr);
mthca_free_cq_buf(dev, cq);
if (mthca_is_memfree(dev)) {
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 5ecdd2eeeb0f..7bff5a8425f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 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
@@ -67,6 +69,10 @@ enum {
};
enum {
+ MTHCA_BOARD_ID_LEN = 64
+};
+
+enum {
MTHCA_EQ_CONTEXT_SIZE = 0x40,
MTHCA_CQ_CONTEXT_SIZE = 0x40,
MTHCA_QP_CONTEXT_SIZE = 0x200,
@@ -142,6 +148,7 @@ struct mthca_limits {
int reserved_mcgs;
int num_pds;
int reserved_pds;
+ u8 port_width_cap;
};
struct mthca_alloc {
@@ -211,6 +218,13 @@ struct mthca_cq_table {
struct mthca_icm_table *table;
};
+struct mthca_srq_table {
+ struct mthca_alloc alloc;
+ spinlock_t lock;
+ struct mthca_array srq;
+ struct mthca_icm_table *table;
+};
+
struct mthca_qp_table {
struct mthca_alloc alloc;
u32 rdb_base;
@@ -246,6 +260,7 @@ struct mthca_dev {
unsigned long device_cap_flags;
u32 rev_id;
+ char board_id[MTHCA_BOARD_ID_LEN];
/* firmware info */
u64 fw_ver;
@@ -291,6 +306,7 @@ struct mthca_dev {
struct mthca_mr_table mr_table;
struct mthca_eq_table eq_table;
struct mthca_cq_table cq_table;
+ struct mthca_srq_table srq_table;
struct mthca_qp_table qp_table;
struct mthca_av_table av_table;
struct mthca_mcg_table mcg_table;
@@ -331,14 +347,13 @@ extern void __buggy_use_of_MTHCA_PUT(void);
#define MTHCA_PUT(dest, source, offset) \
do { \
- __typeof__(source) *__p = \
- (__typeof__(source) *) ((char *) (dest) + (offset)); \
+ void *__d = ((char *) (dest) + (offset)); \
switch (sizeof(source)) { \
- case 1: *__p = (source); break; \
- case 2: *__p = cpu_to_be16(source); break; \
- case 4: *__p = cpu_to_be32(source); break; \
- case 8: *__p = cpu_to_be64(source); break; \
- default: __buggy_use_of_MTHCA_PUT(); \
+ case 1: *(u8 *) __d = (source); break; \
+ case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
+ case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
+ case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
+ default: __buggy_use_of_MTHCA_PUT(); \
} \
} while (0)
@@ -354,12 +369,18 @@ int mthca_array_set(struct mthca_array *array, int index, void *value);
void mthca_array_clear(struct mthca_array *array, int index);
int mthca_array_init(struct mthca_array *array, int nent);
void mthca_array_cleanup(struct mthca_array *array, int nent);
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+ union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+ int hca_write, struct mthca_mr *mr);
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+ int is_direct, struct mthca_mr *mr);
int mthca_init_uar_table(struct mthca_dev *dev);
int mthca_init_pd_table(struct mthca_dev *dev);
int mthca_init_mr_table(struct mthca_dev *dev);
int mthca_init_eq_table(struct mthca_dev *dev);
int mthca_init_cq_table(struct mthca_dev *dev);
+int mthca_init_srq_table(struct mthca_dev *dev);
int mthca_init_qp_table(struct mthca_dev *dev);
int mthca_init_av_table(struct mthca_dev *dev);
int mthca_init_mcg_table(struct mthca_dev *dev);
@@ -369,6 +390,7 @@ void mthca_cleanup_pd_table(struct mthca_dev *dev);
void mthca_cleanup_mr_table(struct mthca_dev *dev);
void mthca_cleanup_eq_table(struct mthca_dev *dev);
void mthca_cleanup_cq_table(struct mthca_dev *dev);
+void mthca_cleanup_srq_table(struct mthca_dev *dev);
void mthca_cleanup_qp_table(struct mthca_dev *dev);
void mthca_cleanup_av_table(struct mthca_dev *dev);
void mthca_cleanup_mcg_table(struct mthca_dev *dev);
@@ -419,7 +441,19 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
void mthca_free_cq(struct mthca_dev *dev,
struct mthca_cq *cq);
void mthca_cq_event(struct mthca_dev *dev, u32 cqn);
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn);
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+ struct mthca_srq *srq);
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct ib_srq_attr *attr, struct mthca_srq *srq);
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
+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);
+int mthca_tavor_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+int mthca_arbel_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
enum ib_event_type event_type);
@@ -433,7 +467,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
struct ib_recv_wr **bad_wr);
int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
- int index, int *dbd, u32 *new_wqe);
+ int index, int *dbd, __be32 *new_wqe);
int mthca_alloc_qp(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
diff --git a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h
index 535fad7710fb..dd9a44d170c9 100644
--- a/drivers/infiniband/hw/mthca/mthca_doorbell.h
+++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -57,13 +58,13 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writeq((__force u64) val, dest);
}
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
__raw_writeq(*(u64 *) val, dest);
}
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
{
*(u64 *) db = *(u64 *) val;
}
@@ -86,18 +87,18 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writel(((__force u32 *) &val)[1], dest + 4);
}
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
unsigned long flags;
spin_lock_irqsave(doorbell_lock, flags);
- __raw_writel(val[0], dest);
- __raw_writel(val[1], dest + 4);
+ __raw_writel((__force u32) val[0], dest);
+ __raw_writel((__force u32) val[1], dest + 4);
spin_unlock_irqrestore(doorbell_lock, flags);
}
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
{
db[0] = val[0];
wmb();
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index cbcf2b4722e4..18f0981eb0c1 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -51,18 +52,18 @@ enum {
* Must be packed because start is 64 bits but only aligned to 32 bits.
*/
struct mthca_eq_context {
- u32 flags;
- u64 start;
- u32 logsize_usrpage;
- u32 tavor_pd; /* reserved for Arbel */
- u8 reserved1[3];
- u8 intr;
- u32 arbel_pd; /* lost_count for Tavor */
- u32 lkey;
- u32 reserved2[2];
- u32 consumer_index;
- u32 producer_index;
- u32 reserved3[4];
+ __be32 flags;
+ __be64 start;
+ __be32 logsize_usrpage;
+ __be32 tavor_pd; /* reserved for Arbel */
+ u8 reserved1[3];
+ u8 intr;
+ __be32 arbel_pd; /* lost_count for Tavor */
+ __be32 lkey;
+ u32 reserved2[2];
+ __be32 consumer_index;
+ __be32 producer_index;
+ u32 reserved3[4];
} __attribute__((packed));
#define MTHCA_EQ_STATUS_OK ( 0 << 28)
@@ -127,28 +128,28 @@ struct mthca_eqe {
union {
u32 raw[6];
struct {
- u32 cqn;
+ __be32 cqn;
} __attribute__((packed)) comp;
struct {
- u16 reserved1;
- u16 token;
- u32 reserved2;
- u8 reserved3[3];
- u8 status;
- u64 out_param;
+ u16 reserved1;
+ __be16 token;
+ u32 reserved2;
+ u8 reserved3[3];
+ u8 status;
+ __be64 out_param;
} __attribute__((packed)) cmd;
struct {
- u32 qpn;
+ __be32 qpn;
} __attribute__((packed)) qp;
struct {
- u32 cqn;
- u32 reserved1;
- u8 reserved2[3];
- u8 syndrome;
+ __be32 cqn;
+ u32 reserved1;
+ u8 reserved2[3];
+ u8 syndrome;
} __attribute__((packed)) cq_err;
struct {
- u32 reserved1[2];
- u32 port;
+ u32 reserved1[2];
+ __be32 port;
} __attribute__((packed)) port_change;
} event;
u8 reserved3[3];
@@ -167,7 +168,7 @@ static inline u64 async_mask(struct mthca_dev *dev)
static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
@@ -190,8 +191,8 @@ static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u
{
/* See comment in tavor_set_eq_ci() above. */
wmb();
- __raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
- eq->eqn * 8);
+ __raw_writel((__force u32) cpu_to_be32(ci),
+ dev->eq_regs.arbel.eq_set_ci_base + eq->eqn * 8);
/* We still want ordering, just not swabbing, so add a barrier */
mb();
}
@@ -206,7 +207,7 @@ static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_REQ_NOT | eqn);
doorbell[1] = 0;
@@ -224,7 +225,7 @@ static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
{
if (!mthca_is_memfree(dev)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
doorbell[1] = cpu_to_be32(cqn);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 7df223642015..9804174f7f3c 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 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
@@ -32,9 +34,9 @@
* $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_verbs.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -192,7 +194,7 @@ int mthca_process_mad(struct ib_device *ibdev,
{
int err;
u8 status;
- u16 slid = in_wc ? in_wc->slid : IB_LID_PERMISSIVE;
+ u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
/* Forward locally generated traps to the SM */
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 2ef916859e17..ffbcd40418d5 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -34,7 +35,6 @@
*/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -171,6 +171,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.reserved_mrws = dev_lim->reserved_mrws;
mdev->limits.reserved_uars = dev_lim->reserved_uars;
mdev->limits.reserved_pds = dev_lim->reserved_pds;
+ mdev->limits.port_width_cap = dev_lim->max_port_width;
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
May be doable since hardware supports it for SRQ.
@@ -212,7 +213,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- struct mthca_adapter adapter;
err = mthca_SYS_EN(mdev, &status);
if (err) {
@@ -253,6 +253,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.uarc_size = 0;
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ profile.num_srq = dev_lim.max_srqs;
err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
if (err < 0)
@@ -270,26 +272,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable;
}
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
- if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_close;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
- goto err_close;
- }
-
- mdev->eq_table.inta_pin = adapter.inta_pin;
- mdev->rev_id = adapter.revision_id;
-
return 0;
-err_close:
- mthca_CLOSE_HCA(mdev, 0, &status);
-
err_disable:
mthca_SYS_DIS(mdev, &status);
@@ -442,15 +426,29 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
- dev_lim->cqc_entry_sz,
- mdev->limits.num_cqs,
- mdev->limits.reserved_cqs, 0);
+ dev_lim->cqc_entry_sz,
+ mdev->limits.num_cqs,
+ mdev->limits.reserved_cqs, 0);
if (!mdev->cq_table.table) {
mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
err = -ENOMEM;
goto err_unmap_rdb;
}
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ) {
+ mdev->srq_table.table =
+ mthca_alloc_icm_table(mdev, init_hca->srqc_base,
+ dev_lim->srq_entry_sz,
+ mdev->limits.num_srqs,
+ mdev->limits.reserved_srqs, 0);
+ if (!mdev->srq_table.table) {
+ mthca_err(mdev, "Failed to map SRQ context memory, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_unmap_cq;
+ }
+ }
+
/*
* It's not strictly required, but for simplicity just map the
* whole multicast group table now. The table isn't very big
@@ -466,11 +464,15 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
if (!mdev->mcg_table.table) {
mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
err = -ENOMEM;
- goto err_unmap_cq;
+ goto err_unmap_srq;
}
return 0;
+err_unmap_srq:
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ mthca_free_icm_table(mdev, mdev->srq_table.table);
+
err_unmap_cq:
mthca_free_icm_table(mdev, mdev->cq_table.table);
@@ -506,7 +508,6 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- struct mthca_adapter adapter;
u64 icm_size;
u8 status;
int err;
@@ -551,6 +552,8 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.num_udav = 0;
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ profile.num_srq = dev_lim.max_srqs;
icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
if ((int) icm_size < 0) {
@@ -574,24 +577,11 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
goto err_free_icm;
}
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
- if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_free_icm;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
- goto err_free_icm;
- }
-
- mdev->eq_table.inta_pin = adapter.inta_pin;
- mdev->rev_id = adapter.revision_id;
-
return 0;
err_free_icm:
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ mthca_free_icm_table(mdev, mdev->srq_table.table);
mthca_free_icm_table(mdev, mdev->cq_table.table);
mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
@@ -614,12 +604,70 @@ err_disable:
return err;
}
+static void mthca_close_hca(struct mthca_dev *mdev)
+{
+ u8 status;
+
+ mthca_CLOSE_HCA(mdev, 0, &status);
+
+ if (mthca_is_memfree(mdev)) {
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ mthca_free_icm_table(mdev, mdev->srq_table.table);
+ mthca_free_icm_table(mdev, mdev->cq_table.table);
+ mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
+ mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
+ mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
+ mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
+ mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
+ mthca_unmap_eq_icm(mdev);
+
+ mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+
+ mthca_UNMAP_FA(mdev, &status);
+ mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+
+ if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
+ mthca_DISABLE_LAM(mdev, &status);
+ } else
+ mthca_SYS_DIS(mdev, &status);
+}
+
static int __devinit mthca_init_hca(struct mthca_dev *mdev)
{
+ u8 status;
+ int err;
+ struct mthca_adapter adapter;
+
if (mthca_is_memfree(mdev))
- return mthca_init_arbel(mdev);
+ err = mthca_init_arbel(mdev);
else
- return mthca_init_tavor(mdev);
+ err = mthca_init_tavor(mdev);
+
+ if (err)
+ return err;
+
+ err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+ if (err) {
+ mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
+ goto err_close;
+ }
+ if (status) {
+ mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
+ "aborting.\n", status);
+ err = -EINVAL;
+ goto err_close;
+ }
+
+ mdev->eq_table.inta_pin = adapter.inta_pin;
+ mdev->rev_id = adapter.revision_id;
+ memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
+
+ return 0;
+
+err_close:
+ mthca_close_hca(mdev);
+ return err;
}
static int __devinit mthca_setup_hca(struct mthca_dev *dev)
@@ -709,11 +757,18 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
goto err_cmd_poll;
}
+ err = mthca_init_srq_table(dev);
+ if (err) {
+ mthca_err(dev, "Failed to initialize "
+ "shared receive queue table, aborting.\n");
+ goto err_cq_table_free;
+ }
+
err = mthca_init_qp_table(dev);
if (err) {
mthca_err(dev, "Failed to initialize "
"queue pair table, aborting.\n");
- goto err_cq_table_free;
+ goto err_srq_table_free;
}
err = mthca_init_av_table(dev);
@@ -738,6 +793,9 @@ err_av_table_free:
err_qp_table_free:
mthca_cleanup_qp_table(dev);
+err_srq_table_free:
+ mthca_cleanup_srq_table(dev);
+
err_cq_table_free:
mthca_cleanup_cq_table(dev);
@@ -844,33 +902,6 @@ static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev)
return 0;
}
-static void mthca_close_hca(struct mthca_dev *mdev)
-{
- u8 status;
-
- mthca_CLOSE_HCA(mdev, 0, &status);
-
- if (mthca_is_memfree(mdev)) {
- mthca_free_icm_table(mdev, mdev->cq_table.table);
- mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
- mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
- mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
- mthca_unmap_eq_icm(mdev);
-
- mthca_UNMAP_ICM_AUX(mdev, &status);
- mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
-
- mthca_UNMAP_FA(mdev, &status);
- mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
-
- if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
- } else
- mthca_SYS_DIS(mdev, &status);
-}
-
/* Types of supported HCA */
enum {
TAVOR, /* MT23108 */
@@ -887,9 +918,9 @@ static struct {
int is_memfree;
int is_pcie;
} mthca_hca_table[] = {
- [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 2), .is_memfree = 0, .is_pcie = 0 },
- [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 6, 2), .is_memfree = 0, .is_pcie = 1 },
- [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 0, 1), .is_memfree = 1, .is_pcie = 1 },
+ [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 },
+ [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 },
+ [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 },
[SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 }
};
@@ -906,12 +937,12 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
++mthca_version_printed;
}
- printk(KERN_INFO PFX "Initializing %s (%s)\n",
- pci_pretty_name(pdev), pci_name(pdev));
+ printk(KERN_INFO PFX "Initializing %s\n",
+ pci_name(pdev));
if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) {
- printk(KERN_ERR PFX "%s (%s) has invalid driver data %lx\n",
- pci_pretty_name(pdev), pci_name(pdev), id->driver_data);
+ printk(KERN_ERR PFX "%s has invalid driver data %lx\n",
+ pci_name(pdev), id->driver_data);
return -ENODEV;
}
@@ -1051,6 +1082,7 @@ err_cleanup:
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
mthca_cleanup_qp_table(mdev);
+ mthca_cleanup_srq_table(mdev);
mthca_cleanup_cq_table(mdev);
mthca_cmd_use_polling(mdev);
mthca_cleanup_eq_table(mdev);
@@ -1100,6 +1132,7 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev)
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
mthca_cleanup_qp_table(mdev);
+ mthca_cleanup_srq_table(mdev);
mthca_cleanup_cq_table(mdev);
mthca_cmd_use_polling(mdev);
mthca_cleanup_eq_table(mdev);
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 5be7d949dbf6..a2707605f4c8 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -42,10 +42,10 @@ enum {
};
struct mthca_mgm {
- u32 next_gid_index;
- u32 reserved[3];
- u8 gid[16];
- u32 qp[MTHCA_QP_PER_MGM];
+ __be32 next_gid_index;
+ u32 reserved[3];
+ u8 gid[16];
+ __be32 qp[MTHCA_QP_PER_MGM];
};
static const u8 zero_gid[16]; /* automatically initialized to 0 */
@@ -94,10 +94,14 @@ static int find_mgm(struct mthca_dev *dev,
if (0)
mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
"%04x:%04x:%04x:%04x is %04x\n",
- be16_to_cpu(((u16 *) gid)[0]), be16_to_cpu(((u16 *) gid)[1]),
- be16_to_cpu(((u16 *) gid)[2]), be16_to_cpu(((u16 *) gid)[3]),
- be16_to_cpu(((u16 *) gid)[4]), be16_to_cpu(((u16 *) gid)[5]),
- be16_to_cpu(((u16 *) gid)[6]), be16_to_cpu(((u16 *) gid)[7]),
+ be16_to_cpu(((__be16 *) gid)[0]),
+ be16_to_cpu(((__be16 *) gid)[1]),
+ be16_to_cpu(((__be16 *) gid)[2]),
+ be16_to_cpu(((__be16 *) gid)[3]),
+ be16_to_cpu(((__be16 *) gid)[4]),
+ be16_to_cpu(((__be16 *) gid)[5]),
+ be16_to_cpu(((__be16 *) gid)[6]),
+ be16_to_cpu(((__be16 *) gid)[7]),
*hash);
*index = *hash;
@@ -258,14 +262,14 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (index == -1) {
mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"not found\n",
- be16_to_cpu(((u16 *) gid->raw)[0]),
- be16_to_cpu(((u16 *) gid->raw)[1]),
- be16_to_cpu(((u16 *) gid->raw)[2]),
- be16_to_cpu(((u16 *) gid->raw)[3]),
- be16_to_cpu(((u16 *) gid->raw)[4]),
- be16_to_cpu(((u16 *) gid->raw)[5]),
- be16_to_cpu(((u16 *) gid->raw)[6]),
- be16_to_cpu(((u16 *) gid->raw)[7]));
+ be16_to_cpu(((__be16 *) gid->raw)[0]),
+ be16_to_cpu(((__be16 *) gid->raw)[1]),
+ be16_to_cpu(((__be16 *) gid->raw)[2]),
+ be16_to_cpu(((__be16 *) gid->raw)[3]),
+ be16_to_cpu(((__be16 *) gid->raw)[4]),
+ be16_to_cpu(((__be16 *) gid->raw)[5]),
+ be16_to_cpu(((__be16 *) gid->raw)[6]),
+ be16_to_cpu(((__be16 *) gid->raw)[7]));
err = -EINVAL;
goto out;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 2a8646150355..1827400f189b 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -285,6 +286,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
{
struct mthca_icm_table *table;
int num_icm;
+ unsigned chunk_size;
int i;
u8 status;
@@ -305,7 +307,11 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
table->icm[i] = NULL;
for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
- table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
+ chunk_size = MTHCA_TABLE_CHUNK_SIZE;
+ if ((i + 1) * MTHCA_TABLE_CHUNK_SIZE > nobj * obj_size)
+ chunk_size = nobj * obj_size - i * MTHCA_TABLE_CHUNK_SIZE;
+
+ table->icm[i] = mthca_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
__GFP_NOWARN);
if (!table->icm[i])
@@ -481,7 +487,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
}
}
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
{
int group;
int start, end, dir;
@@ -564,7 +570,7 @@ found:
page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
- *db = (u32 *) &page->db_rec[j];
+ *db = (__be32 *) &page->db_rec[j];
out:
up(&dev->db_tab->mutex);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 4761d844cb5f..bafa51544aa3 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -137,7 +138,7 @@ enum {
struct mthca_db_page {
DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE);
- u64 *db_rec;
+ __be64 *db_rec;
dma_addr_t mapping;
};
@@ -172,7 +173,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
int mthca_init_db_tab(struct mthca_dev *dev);
void mthca_cleanup_db_tab(struct mthca_dev *dev);
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db);
void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
#endif /* MTHCA_MEMFREE_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index cbe50feaf680..1f97a44477f5 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -50,18 +51,18 @@ struct mthca_mtt {
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
*/
struct mthca_mpt_entry {
- u32 flags;
- u32 page_size;
- u32 key;
- u32 pd;
- u64 start;
- u64 length;
- u32 lkey;
- u32 window_count;
- u32 window_count_limit;
- u64 mtt_seg;
- u32 mtt_sz; /* Arbel only */
- u32 reserved[2];
+ __be32 flags;
+ __be32 page_size;
+ __be32 key;
+ __be32 pd;
+ __be64 start;
+ __be64 length;
+ __be32 lkey;
+ __be32 window_count;
+ __be32 window_count_limit;
+ __be64 mtt_seg;
+ __be32 mtt_sz; /* Arbel only */
+ u32 reserved[2];
} __attribute__((packed));
#define MTHCA_MPT_FLAG_SW_OWNS (0xfUL << 28)
@@ -247,7 +248,7 @@ int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
int start_index, u64 *buffer_list, int list_len)
{
struct mthca_mailbox *mailbox;
- u64 *mtt_entry;
+ __be64 *mtt_entry;
int err = 0;
u8 status;
int i;
@@ -389,7 +390,7 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
if (i % 4 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+ printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
if ((i + 1) % 4 == 0)
printk("\n");
}
@@ -458,7 +459,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
{
mthca_table_put(dev, dev->mr_table.mpt_table,
- arbel_key_to_hw_index(lkey));
+ key_to_hw_index(dev, lkey));
mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey));
}
@@ -562,7 +563,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
if (i % 4 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+ printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
if ((i + 1) % 4 == 0)
printk("\n");
}
@@ -669,7 +670,7 @@ int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size));
mpt_entry.start = cpu_to_be64(iova);
- writel(mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
+ __raw_writel((__force u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
memcpy_toio(&fmr->mem.tavor.mpt->start, &mpt_entry.start,
offsetof(struct mthca_mpt_entry, window_count) -
offsetof(struct mthca_mpt_entry, start));
diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c
index c2c899844e98..3dbf06a6e6f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_pd.c
+++ b/drivers/infiniband/hw/mthca/mthca_pd.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 4fedc32d5871..0576056b34f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -101,6 +102,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
profile[MTHCA_RES_UARC].size = request->uarc_size;
profile[MTHCA_RES_QP].num = request->num_qp;
+ profile[MTHCA_RES_SRQ].num = request->num_srq;
profile[MTHCA_RES_EQP].num = request->num_qp;
profile[MTHCA_RES_RDB].num = request->num_qp * request->rdb_per_qp;
profile[MTHCA_RES_CQ].num = request->num_cq;
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.h b/drivers/infiniband/hw/mthca/mthca_profile.h
index 17aef3357661..94641808f97f 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.h
+++ b/drivers/infiniband/hw/mthca/mthca_profile.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -41,6 +42,7 @@
struct mthca_profile {
int num_qp;
int rdb_per_qp;
+ int num_srq;
int num_cq;
int num_mcg;
int num_mpt;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 81919a7b4935..1c1c2e230871 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 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
@@ -34,7 +36,7 @@
* $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $
*/
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
#include <linux/mm.h>
#include "mthca_dev.h"
@@ -79,10 +81,10 @@ static int mthca_query_device(struct ib_device *ibdev,
}
props->device_cap_flags = mdev->device_cap_flags;
- props->vendor_id = be32_to_cpup((u32 *) (out_mad->data + 36)) &
+ props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
- props->vendor_part_id = be16_to_cpup((u16 *) (out_mad->data + 30));
- props->hw_ver = be16_to_cpup((u16 *) (out_mad->data + 32));
+ props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30));
+ props->hw_ver = be16_to_cpup((__be16 *) (out_mad->data + 32));
memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
memcpy(&props->node_guid, out_mad->data + 12, 8);
@@ -118,6 +120,8 @@ static int mthca_query_port(struct ib_device *ibdev,
if (!in_mad || !out_mad)
goto out;
+ memset(props, 0, sizeof *props);
+
memset(in_mad, 0, sizeof *in_mad);
in_mad->base_version = 1;
in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
@@ -136,16 +140,17 @@ static int mthca_query_port(struct ib_device *ibdev,
goto out;
}
- props->lid = be16_to_cpup((u16 *) (out_mad->data + 16));
+ props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
- props->sm_lid = be16_to_cpup((u16 *) (out_mad->data + 18));
+ props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
props->sm_sl = out_mad->data[36] & 0xf;
props->state = out_mad->data[32] & 0xf;
props->phys_state = out_mad->data[33] >> 4;
- props->port_cap_flags = be32_to_cpup((u32 *) (out_mad->data + 20));
+ props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20));
props->gid_tbl_len = to_mdev(ibdev)->limits.gid_table_len;
+ props->max_msg_sz = 0x80000000;
props->pkey_tbl_len = to_mdev(ibdev)->limits.pkey_table_len;
- props->qkey_viol_cntr = be16_to_cpup((u16 *) (out_mad->data + 48));
+ props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
props->active_width = out_mad->data[31] & 0xf;
props->active_speed = out_mad->data[35] >> 4;
@@ -221,7 +226,7 @@ static int mthca_query_pkey(struct ib_device *ibdev,
goto out;
}
- *pkey = be16_to_cpu(((u16 *) out_mad->data)[index % 32]);
+ *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
out:
kfree(in_mad);
@@ -420,6 +425,77 @@ static int mthca_ah_destroy(struct ib_ah *ah)
return 0;
}
+static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct mthca_create_srq ucmd;
+ struct mthca_ucontext *context = NULL;
+ struct mthca_srq *srq;
+ int err;
+
+ srq = kmalloc(sizeof *srq, GFP_KERNEL);
+ if (!srq)
+ return ERR_PTR(-ENOMEM);
+
+ if (pd->uobject) {
+ context = to_mucontext(pd->uobject->context);
+
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+ return ERR_PTR(-EFAULT);
+
+ err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+ context->db_tab, ucmd.db_index,
+ ucmd.db_page);
+
+ if (err)
+ goto err_free;
+
+ srq->mr.ibmr.lkey = ucmd.lkey;
+ srq->db_index = ucmd.db_index;
+ }
+
+ err = mthca_alloc_srq(to_mdev(pd->device), to_mpd(pd),
+ &init_attr->attr, srq);
+
+ if (err && pd->uobject)
+ mthca_unmap_user_db(to_mdev(pd->device), &context->uar,
+ context->db_tab, ucmd.db_index);
+
+ if (err)
+ goto err_free;
+
+ if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof (__u32))) {
+ mthca_free_srq(to_mdev(pd->device), srq);
+ err = -EFAULT;
+ goto err_free;
+ }
+
+ return &srq->ibsrq;
+
+err_free:
+ kfree(srq);
+
+ return ERR_PTR(err);
+}
+
+static int mthca_destroy_srq(struct ib_srq *srq)
+{
+ struct mthca_ucontext *context;
+
+ if (srq->uobject) {
+ context = to_mucontext(srq->uobject->context);
+
+ mthca_unmap_user_db(to_mdev(srq->device), &context->uar,
+ context->db_tab, to_msrq(srq)->db_index);
+ }
+
+ mthca_free_srq(to_mdev(srq->device), to_msrq(srq));
+ kfree(srq);
+
+ return 0;
+}
+
static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata)
@@ -956,14 +1032,22 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
}
}
+static ssize_t show_board(struct class_device *cdev, char *buf)
+{
+ struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
+ return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
+}
+
static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct class_device_attribute *mthca_class_attributes[] = {
&class_device_attr_hw_rev,
&class_device_attr_fw_ver,
- &class_device_attr_hca_type
+ &class_device_attr_hca_type,
+ &class_device_attr_board_id
};
int mthca_register_device(struct mthca_dev *dev)
@@ -990,6 +1074,17 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.dealloc_pd = mthca_dealloc_pd;
dev->ib_dev.create_ah = mthca_ah_create;
dev->ib_dev.destroy_ah = mthca_ah_destroy;
+
+ if (dev->mthca_flags & MTHCA_FLAG_SRQ) {
+ dev->ib_dev.create_srq = mthca_create_srq;
+ dev->ib_dev.destroy_srq = mthca_destroy_srq;
+
+ if (mthca_is_memfree(dev))
+ dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;
+ else
+ dev->ib_dev.post_srq_recv = mthca_tavor_post_srq_recv;
+ }
+
dev->ib_dev.create_qp = mthca_create_qp;
dev->ib_dev.modify_qp = mthca_modify_qp;
dev->ib_dev.destroy_qp = mthca_destroy_qp;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 1d032791cc8b..bcd4b01a339c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -36,8 +37,8 @@
#ifndef MTHCA_PROVIDER_H
#define MTHCA_PROVIDER_H
-#include <ib_verbs.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
#define MTHCA_MPT_FLAG_ATOMIC (1 << 14)
#define MTHCA_MPT_FLAG_REMOTE_WRITE (1 << 13)
@@ -50,6 +51,11 @@ struct mthca_buf_list {
DECLARE_PCI_UNMAP_ADDR(mapping)
};
+union mthca_buf {
+ struct mthca_buf_list direct;
+ struct mthca_buf_list *page_list;
+};
+
struct mthca_uar {
unsigned long pfn;
int index;
@@ -181,19 +187,39 @@ struct mthca_cq {
/* Next fields are Arbel only */
int set_ci_db_index;
- u32 *set_ci_db;
+ __be32 *set_ci_db;
int arm_db_index;
- u32 *arm_db;
+ __be32 *arm_db;
int arm_sn;
- union {
- struct mthca_buf_list direct;
- struct mthca_buf_list *page_list;
- } queue;
+ union mthca_buf queue;
struct mthca_mr mr;
wait_queue_head_t wait;
};
+struct mthca_srq {
+ struct ib_srq ibsrq;
+ spinlock_t lock;
+ atomic_t refcount;
+ int srqn;
+ int max;
+ int max_gs;
+ int wqe_shift;
+ int first_free;
+ int last_free;
+ u16 counter; /* Arbel only */
+ int db_index; /* Arbel only */
+ __be32 *db; /* Arbel only */
+ void *last;
+
+ int is_direct;
+ u64 *wrid;
+ union mthca_buf queue;
+ struct mthca_mr mr;
+
+ wait_queue_head_t wait;
+};
+
struct mthca_wq {
spinlock_t lock;
int max;
@@ -206,7 +232,7 @@ struct mthca_wq {
int wqe_shift;
int db_index; /* Arbel only */
- u32 *db;
+ __be32 *db;
};
struct mthca_qp {
@@ -227,10 +253,7 @@ struct mthca_qp {
int send_wqe_offset;
u64 *wrid;
- union {
- struct mthca_buf_list direct;
- struct mthca_buf_list *page_list;
- } queue;
+ union mthca_buf queue;
wait_queue_head_t wait;
};
@@ -277,6 +300,11 @@ static inline struct mthca_cq *to_mcq(struct ib_cq *ibcq)
return container_of(ibcq, struct mthca_cq, ibcq);
}
+static inline struct mthca_srq *to_msrq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct mthca_srq, ibsrq);
+}
+
static inline struct mthca_qp *to_mqp(struct ib_qp *ibqp)
{
return container_of(ibqp, struct mthca_qp, ibqp);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index f7126b14d5ae..bcef06bf15e7 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 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
@@ -35,13 +37,14 @@
#include <linux/init.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_pack.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
#include "mthca_memfree.h"
+#include "mthca_wqe.h"
enum {
MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
@@ -95,62 +98,62 @@ enum {
};
struct mthca_qp_path {
- u32 port_pkey;
- u8 rnr_retry;
- u8 g_mylmc;
- u16 rlid;
- u8 ackto;
- u8 mgid_index;
- u8 static_rate;
- u8 hop_limit;
- u32 sl_tclass_flowlabel;
- u8 rgid[16];
+ __be32 port_pkey;
+ u8 rnr_retry;
+ u8 g_mylmc;
+ __be16 rlid;
+ u8 ackto;
+ u8 mgid_index;
+ u8 static_rate;
+ u8 hop_limit;
+ __be32 sl_tclass_flowlabel;
+ u8 rgid[16];
} __attribute__((packed));
struct mthca_qp_context {
- u32 flags;
- u32 tavor_sched_queue; /* Reserved on Arbel */
- u8 mtu_msgmax;
- u8 rq_size_stride; /* Reserved on Tavor */
- u8 sq_size_stride; /* Reserved on Tavor */
- u8 rlkey_arbel_sched_queue; /* Reserved on Tavor */
- u32 usr_page;
- u32 local_qpn;
- u32 remote_qpn;
- u32 reserved1[2];
+ __be32 flags;
+ __be32 tavor_sched_queue; /* Reserved on Arbel */
+ u8 mtu_msgmax;
+ u8 rq_size_stride; /* Reserved on Tavor */
+ u8 sq_size_stride; /* Reserved on Tavor */
+ u8 rlkey_arbel_sched_queue; /* Reserved on Tavor */
+ __be32 usr_page;
+ __be32 local_qpn;
+ __be32 remote_qpn;
+ u32 reserved1[2];
struct mthca_qp_path pri_path;
struct mthca_qp_path alt_path;
- u32 rdd;
- u32 pd;
- u32 wqe_base;
- u32 wqe_lkey;
- u32 params1;
- u32 reserved2;
- u32 next_send_psn;
- u32 cqn_snd;
- u32 snd_wqe_base_l; /* Next send WQE on Tavor */
- u32 snd_db_index; /* (debugging only entries) */
- u32 last_acked_psn;
- u32 ssn;
- u32 params2;
- u32 rnr_nextrecvpsn;
- u32 ra_buff_indx;
- u32 cqn_rcv;
- u32 rcv_wqe_base_l; /* Next recv WQE on Tavor */
- u32 rcv_db_index; /* (debugging only entries) */
- u32 qkey;
- u32 srqn;
- u32 rmsn;
- u16 rq_wqe_counter; /* reserved on Tavor */
- u16 sq_wqe_counter; /* reserved on Tavor */
- u32 reserved3[18];
+ __be32 rdd;
+ __be32 pd;
+ __be32 wqe_base;
+ __be32 wqe_lkey;
+ __be32 params1;
+ __be32 reserved2;
+ __be32 next_send_psn;
+ __be32 cqn_snd;
+ __be32 snd_wqe_base_l; /* Next send WQE on Tavor */
+ __be32 snd_db_index; /* (debugging only entries) */
+ __be32 last_acked_psn;
+ __be32 ssn;
+ __be32 params2;
+ __be32 rnr_nextrecvpsn;
+ __be32 ra_buff_indx;
+ __be32 cqn_rcv;
+ __be32 rcv_wqe_base_l; /* Next recv WQE on Tavor */
+ __be32 rcv_db_index; /* (debugging only entries) */
+ __be32 qkey;
+ __be32 srqn;
+ __be32 rmsn;
+ __be16 rq_wqe_counter; /* reserved on Tavor */
+ __be16 sq_wqe_counter; /* reserved on Tavor */
+ u32 reserved3[18];
} __attribute__((packed));
struct mthca_qp_param {
- u32 opt_param_mask;
- u32 reserved1;
+ __be32 opt_param_mask;
+ u32 reserved1;
struct mthca_qp_context context;
- u32 reserved2[62];
+ u32 reserved2[62];
} __attribute__((packed));
enum {
@@ -173,80 +176,6 @@ enum {
MTHCA_QP_OPTPAR_SCHED_QUEUE = 1 << 16
};
-enum {
- MTHCA_NEXT_DBD = 1 << 7,
- MTHCA_NEXT_FENCE = 1 << 6,
- MTHCA_NEXT_CQ_UPDATE = 1 << 3,
- MTHCA_NEXT_EVENT_GEN = 1 << 2,
- MTHCA_NEXT_SOLICIT = 1 << 1,
-
- MTHCA_MLX_VL15 = 1 << 17,
- MTHCA_MLX_SLR = 1 << 16
-};
-
-enum {
- MTHCA_INVAL_LKEY = 0x100
-};
-
-struct mthca_next_seg {
- u32 nda_op; /* [31:6] next WQE [4:0] next opcode */
- u32 ee_nds; /* [31:8] next EE [7] DBD [6] F [5:0] next WQE size */
- u32 flags; /* [3] CQ [2] Event [1] Solicit */
- u32 imm; /* immediate data */
-};
-
-struct mthca_tavor_ud_seg {
- u32 reserved1;
- u32 lkey;
- u64 av_addr;
- u32 reserved2[4];
- u32 dqpn;
- u32 qkey;
- u32 reserved3[2];
-};
-
-struct mthca_arbel_ud_seg {
- u32 av[8];
- u32 dqpn;
- u32 qkey;
- u32 reserved[2];
-};
-
-struct mthca_bind_seg {
- u32 flags; /* [31] Atomic [30] rem write [29] rem read */
- u32 reserved;
- u32 new_rkey;
- u32 lkey;
- u64 addr;
- u64 length;
-};
-
-struct mthca_raddr_seg {
- u64 raddr;
- u32 rkey;
- u32 reserved;
-};
-
-struct mthca_atomic_seg {
- u64 swap_add;
- u64 compare;
-};
-
-struct mthca_data_seg {
- u32 byte_count;
- u32 lkey;
- u64 addr;
-};
-
-struct mthca_mlx_seg {
- u32 nda_op;
- u32 nds;
- u32 flags; /* [17] VL15 [16] SLR [14:12] static rate
- [11:8] SL [3] C [2] E */
- u16 rlid;
- u16 vcrc;
-};
-
static const u8 mthca_opcode[] = {
[IB_WR_SEND] = MTHCA_OPCODE_SEND,
[IB_WR_SEND_WITH_IMM] = MTHCA_OPCODE_SEND_IMM,
@@ -291,6 +220,16 @@ static void *get_send_wqe(struct mthca_qp *qp, int n)
(PAGE_SIZE - 1));
}
+static void mthca_wq_init(struct mthca_wq *wq)
+{
+ spin_lock_init(&wq->lock);
+ wq->next_ind = 0;
+ wq->last_comp = wq->max - 1;
+ wq->head = 0;
+ wq->tail = 0;
+ wq->last = NULL;
+}
+
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
enum ib_event_type event_type)
{
@@ -573,12 +512,11 @@ static void init_port(struct mthca_dev *dev, int port)
memset(&param, 0, sizeof param);
- param.enable_1x = 1;
- param.enable_4x = 1;
- param.vl_cap = dev->limits.vl_cap;
- param.mtu_cap = dev->limits.mtu_cap;
- param.gid_cap = dev->limits.gid_table_len;
- param.pkey_cap = dev->limits.pkey_table_len;
+ param.port_width = dev->limits.port_width_cap;
+ param.vl_cap = dev->limits.vl_cap;
+ param.mtu_cap = dev->limits.mtu_cap;
+ param.gid_cap = dev->limits.gid_table_len;
+ param.pkey_cap = dev->limits.pkey_table_len;
err = mthca_INIT_IB(dev, &param, port, &status);
if (err)
@@ -684,10 +622,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
if (mthca_is_memfree(dev)) {
- qp_context->rq_size_stride =
- ((ffs(qp->rq.max) - 1) << 3) | (qp->rq.wqe_shift - 4);
- qp_context->sq_size_stride =
- ((ffs(qp->sq.max) - 1) << 3) | (qp->sq.wqe_shift - 4);
+ if (qp->rq.max)
+ qp_context->rq_size_stride = long_log2(qp->rq.max) << 3;
+ qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
+
+ if (qp->sq.max)
+ qp_context->sq_size_stride = long_log2(qp->sq.max) << 3;
+ qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
}
/* leave arbel_sched_queue as 0 */
@@ -856,6 +797,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+ if (ibqp->srq)
+ qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RIC);
+
if (attr_mask & IB_QP_MIN_RNR_TIMER) {
qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
@@ -878,6 +822,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
}
+ if (ibqp->srq)
+ qp_context->srqn = cpu_to_be32(1 << 24 |
+ to_msrq(ibqp->srq)->srqn);
+
err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans,
qp->qpn, 0, mailbox, 0, &status);
if (status) {
@@ -895,8 +843,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
store_attrs(to_msqp(qp), attr, attr_mask);
/*
- * If we are moving QP0 to RTR, bring the IB link up; if we
- * are moving QP0 to RESET or ERROR, bring the link back down.
+ * If we moved QP0 to RTR, bring the IB link up; if we moved
+ * QP0 to RESET or ERROR, bring the link back down.
*/
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR &&
@@ -910,6 +858,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
}
+ /*
+ * If we moved a kernel QP to RESET, clean up all old CQ
+ * entries and reinitialize the QP.
+ */
+ if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, 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,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+
+ mthca_wq_init(&qp->sq);
+ mthca_wq_init(&qp->rq);
+
+ if (mthca_is_memfree(dev)) {
+ *qp->sq.db = 0;
+ *qp->rq.db = 0;
+ }
+ }
+
return err;
}
@@ -925,10 +893,6 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
struct mthca_qp *qp)
{
int size;
- int i;
- int npages, shift;
- dma_addr_t t;
- u64 *dma_list = NULL;
int err = -ENOMEM;
size = sizeof (struct mthca_next_seg) +
@@ -978,116 +942,24 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
if (!qp->wrid)
goto err_out;
- if (size <= MTHCA_MAX_DIRECT_QP_SIZE) {
- qp->is_direct = 1;
- npages = 1;
- shift = get_order(size) + PAGE_SHIFT;
-
- if (0)
- mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n",
- size, shift);
-
- qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size,
- &t, GFP_KERNEL);
- if (!qp->queue.direct.buf)
- goto err_out;
-
- pci_unmap_addr_set(&qp->queue.direct, mapping, t);
-
- memset(qp->queue.direct.buf, 0, size);
-
- while (t & ((1 << shift) - 1)) {
- --shift;
- npages *= 2;
- }
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_out_free;
-
- for (i = 0; i < npages; ++i)
- dma_list[i] = t + i * (1 << shift);
- } else {
- qp->is_direct = 0;
- npages = size / PAGE_SIZE;
- shift = PAGE_SHIFT;
-
- if (0)
- mthca_dbg(dev, "Creating indirect QP with %d pages\n", npages);
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_out;
-
- qp->queue.page_list = kmalloc(npages *
- sizeof *qp->queue.page_list,
- GFP_KERNEL);
- if (!qp->queue.page_list)
- goto err_out;
-
- for (i = 0; i < npages; ++i) {
- qp->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
- if (!qp->queue.page_list[i].buf)
- goto err_out_free;
-
- memset(qp->queue.page_list[i].buf, 0, PAGE_SIZE);
-
- pci_unmap_addr_set(&qp->queue.page_list[i], mapping, t);
- dma_list[i] = t;
- }
- }
-
- err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
- npages, 0, size,
- MTHCA_MPT_FLAG_LOCAL_READ,
- &qp->mr);
+ err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_QP_SIZE,
+ &qp->queue, &qp->is_direct, pd, 0, &qp->mr);
if (err)
- goto err_out_free;
+ goto err_out;
- kfree(dma_list);
return 0;
- err_out_free:
- if (qp->is_direct) {
- dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
- pci_unmap_addr(&qp->queue.direct, mapping));
- } else
- for (i = 0; i < npages; ++i) {
- if (qp->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- qp->queue.page_list[i].buf,
- pci_unmap_addr(&qp->queue.page_list[i],
- mapping));
-
- }
-
- err_out:
+err_out:
kfree(qp->wrid);
- kfree(dma_list);
return err;
}
static void mthca_free_wqe_buf(struct mthca_dev *dev,
struct mthca_qp *qp)
{
- int i;
- int size = PAGE_ALIGN(qp->send_wqe_offset +
- (qp->sq.max << qp->sq.wqe_shift));
-
- if (qp->is_direct) {
- dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
- pci_unmap_addr(&qp->queue.direct, mapping));
- } else {
- for (i = 0; i < size / PAGE_SIZE; ++i) {
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- qp->queue.page_list[i].buf,
- pci_unmap_addr(&qp->queue.page_list[i],
- mapping));
- }
- }
-
+ mthca_buf_free(dev, PAGE_ALIGN(qp->send_wqe_offset +
+ (qp->sq.max << qp->sq.wqe_shift)),
+ &qp->queue, qp->is_direct, &qp->mr);
kfree(qp->wrid);
}
@@ -1161,16 +1033,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
}
}
-static void mthca_wq_init(struct mthca_wq* wq)
-{
- spin_lock_init(&wq->lock);
- wq->next_ind = 0;
- wq->last_comp = wq->max - 1;
- wq->head = 0;
- wq->tail = 0;
- wq->last = NULL;
-}
-
static int mthca_alloc_qp_common(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
@@ -1182,6 +1044,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
int i;
atomic_set(&qp->refcount, 1);
+ init_waitqueue_head(&qp->wait);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
qp->resp_depth = 0;
@@ -1428,11 +1291,12 @@ 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)->cqn, 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)->cqn, qp->qpn,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
- mthca_free_mr(dev, &qp->mr);
mthca_free_memfree(dev, qp);
mthca_free_wqe_buf(dev, qp);
}
@@ -1457,6 +1321,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
{
int header_size;
int err;
+ u16 pkey;
ib_ud_header_init(256, /* assume a MAD */
sqp->ud_header.grh_present,
@@ -1467,8 +1332,8 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
return err;
mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MTHCA_MLX_VL15 : 0) |
- (sqp->ud_header.lrh.destination_lid == 0xffff ?
- MTHCA_MLX_SLR : 0) |
+ (sqp->ud_header.lrh.destination_lid ==
+ IB_LID_PERMISSIVE ? MTHCA_MLX_SLR : 0) |
(sqp->ud_header.lrh.service_level << 8));
mlx->rlid = sqp->ud_header.lrh.destination_lid;
mlx->vcrc = 0;
@@ -1488,18 +1353,16 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
}
sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0;
- if (sqp->ud_header.lrh.destination_lid == 0xffff)
- sqp->ud_header.lrh.source_lid = 0xffff;
+ if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
+ 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,
- sqp->pkey_index,
- &sqp->ud_header.bth.pkey);
+ sqp->pkey_index, &pkey);
else
ib_get_cached_pkey(&dev->ib_dev, sqp->port,
- wr->wr.ud.pkey_index,
- &sqp->ud_header.bth.pkey);
- cpu_to_be16s(&sqp->ud_header.bth.pkey);
+ 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);
sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
@@ -1742,7 +1605,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
qp->send_wqe_offset) | f0 | op0);
@@ -1843,7 +1706,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
@@ -2064,7 +1927,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((nreq << 24) |
((qp->sq.head & 0xffff) << 8) |
@@ -2174,19 +2037,25 @@ out:
}
int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
- int index, int *dbd, u32 *new_wqe)
+ int index, int *dbd, __be32 *new_wqe)
{
struct mthca_next_seg *next;
+ /*
+ * For SRQs, all WQEs generate a CQE, so we're always at the
+ * end of the doorbell chain.
+ */
+ if (qp->ibqp.srq) {
+ *new_wqe = 0;
+ return 0;
+ }
+
if (is_send)
next = get_send_wqe(qp, index);
else
next = get_recv_wqe(qp, index);
- if (mthca_is_memfree(dev))
- *dbd = 1;
- else
- *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
+ *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
if (next->ee_nds & cpu_to_be32(0x3f))
*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
(next->ee_nds & cpu_to_be32(0x3f));
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 8ea801271a41..4f995391dd1d 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -71,8 +71,8 @@ int mthca_reset(struct mthca_dev *mdev)
bridge)) != NULL) {
if (bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
bridge->subordinate == mdev->pdev->bus) {
- mthca_dbg(mdev, "Found bridge: %s (%s)\n",
- pci_pretty_name(bridge), pci_name(bridge));
+ mthca_dbg(mdev, "Found bridge: %s\n",
+ pci_name(bridge));
break;
}
}
@@ -83,8 +83,8 @@ int mthca_reset(struct mthca_dev *mdev)
* assume we're in no-bridge mode and hope for
* the best.
*/
- mthca_warn(mdev, "No bridge found for %s (%s)\n",
- pci_pretty_name(mdev->pdev), pci_name(mdev->pdev));
+ mthca_warn(mdev, "No bridge found for %s\n",
+ pci_name(mdev->pdev));
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
new file mode 100644
index 000000000000..75cd2d84ef12
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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.
+ *
+ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#include "mthca_dev.h"
+#include "mthca_cmd.h"
+#include "mthca_memfree.h"
+#include "mthca_wqe.h"
+
+enum {
+ MTHCA_MAX_DIRECT_SRQ_SIZE = 4 * PAGE_SIZE
+};
+
+struct mthca_tavor_srq_context {
+ __be64 wqe_base_ds; /* low 6 bits is descriptor size */
+ __be32 state_pd;
+ __be32 lkey;
+ __be32 uar;
+ __be32 wqe_cnt;
+ u32 reserved[2];
+};
+
+struct mthca_arbel_srq_context {
+ __be32 state_logsize_srqn;
+ __be32 lkey;
+ __be32 db_index;
+ __be32 logstride_usrpage;
+ __be64 wqe_base;
+ __be32 eq_pd;
+ __be16 limit_watermark;
+ __be16 wqe_cnt;
+ u16 reserved1;
+ __be16 wqe_counter;
+ u32 reserved2[3];
+};
+
+static void *get_wqe(struct mthca_srq *srq, int n)
+{
+ if (srq->is_direct)
+ return srq->queue.direct.buf + (n << srq->wqe_shift);
+ else
+ return srq->queue.page_list[(n << srq->wqe_shift) >> PAGE_SHIFT].buf +
+ ((n << srq->wqe_shift) & (PAGE_SIZE - 1));
+}
+
+/*
+ * Return a pointer to the location within a WQE that we're using as a
+ * link when the WQE is in the free list. We use an offset of 4
+ * because in the Tavor case, posting a WQE may overwrite the first
+ * four bytes of the previous WQE. The offset avoids corrupting our
+ * free list if the WQE has already completed and been put on the free
+ * list when we post the next WQE.
+ */
+static inline int *wqe_to_link(void *wqe)
+{
+ return (int *) (wqe + 4);
+}
+
+static void mthca_tavor_init_srq_context(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_srq *srq,
+ struct mthca_tavor_srq_context *context)
+{
+ memset(context, 0, sizeof *context);
+
+ context->wqe_base_ds = cpu_to_be64(1 << (srq->wqe_shift - 4));
+ context->state_pd = cpu_to_be32(pd->pd_num);
+ context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
+
+ if (pd->ibpd.uobject)
+ context->uar =
+ cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+ else
+ context->uar = cpu_to_be32(dev->driver_uar.index);
+}
+
+static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_srq *srq,
+ struct mthca_arbel_srq_context *context)
+{
+ int logsize;
+
+ memset(context, 0, sizeof *context);
+
+ logsize = long_log2(srq->max) + srq->wqe_shift;
+ context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
+ context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
+ context->db_index = cpu_to_be32(srq->db_index);
+ context->logstride_usrpage = cpu_to_be32((srq->wqe_shift - 4) << 29);
+ if (pd->ibpd.uobject)
+ context->logstride_usrpage |=
+ cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+ else
+ context->logstride_usrpage |= cpu_to_be32(dev->driver_uar.index);
+ context->eq_pd = cpu_to_be32(MTHCA_EQ_ASYNC << 24 | pd->pd_num);
+}
+
+static void mthca_free_srq_buf(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+ mthca_buf_free(dev, srq->max << srq->wqe_shift, &srq->queue,
+ srq->is_direct, &srq->mr);
+ kfree(srq->wrid);
+}
+
+static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct mthca_srq *srq)
+{
+ struct mthca_data_seg *scatter;
+ void *wqe;
+ int err;
+ int i;
+
+ if (pd->ibpd.uobject)
+ return 0;
+
+ srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL);
+ if (!srq->wrid)
+ return -ENOMEM;
+
+ err = mthca_buf_alloc(dev, srq->max << srq->wqe_shift,
+ MTHCA_MAX_DIRECT_SRQ_SIZE,
+ &srq->queue, &srq->is_direct, pd, 1, &srq->mr);
+ if (err) {
+ kfree(srq->wrid);
+ return err;
+ }
+
+ /*
+ * Now initialize the SRQ buffer so that all of the WQEs are
+ * linked into the list of free WQEs. In addition, set the
+ * scatter list L_Keys to the sentry value of 0x100.
+ */
+ for (i = 0; i < srq->max; ++i) {
+ wqe = get_wqe(srq, i);
+
+ *wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
+
+ for (scatter = wqe + sizeof (struct mthca_next_seg);
+ (void *) scatter < wqe + (1 << srq->wqe_shift);
+ ++scatter)
+ scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ }
+
+ return 0;
+}
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct ib_srq_attr *attr, struct mthca_srq *srq)
+{
+ struct mthca_mailbox *mailbox;
+ u8 status;
+ int ds;
+ int err;
+
+ /* Sanity check SRQ size before proceeding */
+ if (attr->max_wr > 16 << 20 || attr->max_sge > 64)
+ return -EINVAL;
+
+ srq->max = attr->max_wr;
+ srq->max_gs = attr->max_sge;
+ srq->last = NULL;
+ srq->counter = 0;
+
+ if (mthca_is_memfree(dev))
+ srq->max = roundup_pow_of_two(srq->max + 1);
+
+ ds = min(64UL,
+ roundup_pow_of_two(sizeof (struct mthca_next_seg) +
+ srq->max_gs * sizeof (struct mthca_data_seg)));
+ srq->wqe_shift = long_log2(ds);
+
+ srq->srqn = mthca_alloc(&dev->srq_table.alloc);
+ if (srq->srqn == -1)
+ return -ENOMEM;
+
+ if (mthca_is_memfree(dev)) {
+ err = mthca_table_get(dev, dev->srq_table.table, srq->srqn);
+ if (err)
+ goto err_out;
+
+ if (!pd->ibpd.uobject) {
+ srq->db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SRQ,
+ srq->srqn, &srq->db);
+ if (srq->db_index < 0) {
+ err = -ENOMEM;
+ goto err_out_icm;
+ }
+ }
+ }
+
+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+ if (IS_ERR(mailbox)) {
+ err = PTR_ERR(mailbox);
+ goto err_out_db;
+ }
+
+ err = mthca_alloc_srq_buf(dev, pd, srq);
+ if (err)
+ goto err_out_mailbox;
+
+ spin_lock_init(&srq->lock);
+ atomic_set(&srq->refcount, 1);
+ init_waitqueue_head(&srq->wait);
+
+ if (mthca_is_memfree(dev))
+ mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
+ else
+ mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
+
+ err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+
+ if (err) {
+ mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
+ goto err_out_free_buf;
+ }
+ if (status) {
+ mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
+ status);
+ err = -EINVAL;
+ goto err_out_free_buf;
+ }
+
+ spin_lock_irq(&dev->srq_table.lock);
+ if (mthca_array_set(&dev->srq_table.srq,
+ srq->srqn & (dev->limits.num_srqs - 1),
+ srq)) {
+ spin_unlock_irq(&dev->srq_table.lock);
+ goto err_out_free_srq;
+ }
+ spin_unlock_irq(&dev->srq_table.lock);
+
+ mthca_free_mailbox(dev, mailbox);
+
+ srq->first_free = 0;
+ srq->last_free = srq->max - 1;
+
+ return 0;
+
+err_out_free_srq:
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ if (err)
+ mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+ else if (status)
+ mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+err_out_free_buf:
+ if (!pd->ibpd.uobject)
+ mthca_free_srq_buf(dev, srq);
+
+err_out_mailbox:
+ mthca_free_mailbox(dev, mailbox);
+
+err_out_db:
+ if (!pd->ibpd.uobject && mthca_is_memfree(dev))
+ mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+
+err_out_icm:
+ mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+
+err_out:
+ mthca_free(&dev->srq_table.alloc, srq->srqn);
+
+ return err;
+}
+
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+ struct mthca_mailbox *mailbox;
+ int err;
+ u8 status;
+
+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+ if (IS_ERR(mailbox)) {
+ mthca_warn(dev, "No memory for mailbox to free SRQ.\n");
+ return;
+ }
+
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ if (err)
+ mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+ else if (status)
+ mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+ spin_lock_irq(&dev->srq_table.lock);
+ mthca_array_clear(&dev->srq_table.srq,
+ srq->srqn & (dev->limits.num_srqs - 1));
+ spin_unlock_irq(&dev->srq_table.lock);
+
+ atomic_dec(&srq->refcount);
+ wait_event(srq->wait, !atomic_read(&srq->refcount));
+
+ if (!srq->ibsrq.uobject) {
+ mthca_free_srq_buf(dev, srq);
+ if (mthca_is_memfree(dev))
+ mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+ }
+
+ mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+ mthca_free(&dev->srq_table.alloc, srq->srqn);
+ mthca_free_mailbox(dev, mailbox);
+}
+
+void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
+ enum ib_event_type event_type)
+{
+ struct mthca_srq *srq;
+ struct ib_event event;
+
+ 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);
+ spin_unlock(&dev->srq_table.lock);
+
+ if (!srq) {
+ mthca_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
+ return;
+ }
+
+ if (!srq->ibsrq.event_handler)
+ goto out;
+
+ event.device = &dev->ib_dev;
+ event.event = event_type;
+ event.element.srq = &srq->ibsrq;
+ srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
+
+out:
+ if (atomic_dec_and_test(&srq->refcount))
+ wake_up(&srq->wait);
+}
+
+/*
+ * This function must be called with IRQs disabled.
+ */
+void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr)
+{
+ int ind;
+
+ ind = wqe_addr >> srq->wqe_shift;
+
+ spin_lock(&srq->lock);
+
+ if (likely(srq->first_free >= 0))
+ *wqe_to_link(get_wqe(srq, srq->last_free)) = ind;
+ else
+ srq->first_free = ind;
+
+ *wqe_to_link(get_wqe(srq, ind)) = -1;
+ srq->last_free = ind;
+
+ spin_unlock(&srq->lock);
+}
+
+int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibsrq->device);
+ struct mthca_srq *srq = to_msrq(ibsrq);
+ unsigned long flags;
+ int err = 0;
+ int first_ind;
+ int ind;
+ int next_ind;
+ int nreq;
+ int i;
+ void *wqe;
+ void *prev_wqe;
+
+ spin_lock_irqsave(&srq->lock, flags);
+
+ first_ind = srq->first_free;
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ ind = srq->first_free;
+
+ if (ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ return nreq;
+ }
+
+ wqe = get_wqe(srq, ind);
+ next_ind = *wqe_to_link(wqe);
+ prev_wqe = srq->last;
+ srq->last = wqe;
+
+ ((struct mthca_next_seg *) wqe)->nda_op = 0;
+ ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ /* flags field will always remain 0 */
+
+ wqe += sizeof (struct mthca_next_seg);
+
+ if (unlikely(wr->num_sge > srq->max_gs)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ srq->last = prev_wqe;
+ return nreq;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ }
+
+ if (i < srq->max_gs) {
+ ((struct mthca_data_seg *) wqe)->byte_count = 0;
+ ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ ((struct mthca_data_seg *) wqe)->addr = 0;
+ }
+
+ if (likely(prev_wqe)) {
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32((ind << srq->wqe_shift) | 1);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32(MTHCA_NEXT_DBD);
+ }
+
+ srq->wrid[ind] = wr->wr_id;
+ srq->first_free = next_ind;
+ }
+
+ return nreq;
+
+ if (likely(nreq)) {
+ __be32 doorbell[2];
+
+ doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+ doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq);
+
+ /*
+ * Make sure that descriptors are written before
+ * doorbell is rung.
+ */
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ }
+
+ spin_unlock_irqrestore(&srq->lock, flags);
+ return err;
+}
+
+int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibsrq->device);
+ struct mthca_srq *srq = to_msrq(ibsrq);
+ unsigned long flags;
+ int err = 0;
+ int ind;
+ int next_ind;
+ int nreq;
+ int i;
+ void *wqe;
+
+ spin_lock_irqsave(&srq->lock, flags);
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ ind = srq->first_free;
+
+ if (ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ return nreq;
+ }
+
+ wqe = get_wqe(srq, ind);
+ next_ind = *wqe_to_link(wqe);
+
+ ((struct mthca_next_seg *) wqe)->nda_op =
+ cpu_to_be32((next_ind << srq->wqe_shift) | 1);
+ ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ /* flags field will always remain 0 */
+
+ wqe += sizeof (struct mthca_next_seg);
+
+ if (unlikely(wr->num_sge > srq->max_gs)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ return nreq;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ }
+
+ if (i < srq->max_gs) {
+ ((struct mthca_data_seg *) wqe)->byte_count = 0;
+ ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ ((struct mthca_data_seg *) wqe)->addr = 0;
+ }
+
+ srq->wrid[ind] = wr->wr_id;
+ srq->first_free = next_ind;
+ }
+
+ if (likely(nreq)) {
+ srq->counter += nreq;
+
+ /*
+ * Make sure that descriptors are written before
+ * we write doorbell record.
+ */
+ wmb();
+ *srq->db = cpu_to_be32(srq->counter);
+ }
+
+ spin_unlock_irqrestore(&srq->lock, flags);
+ return err;
+}
+
+int __devinit mthca_init_srq_table(struct mthca_dev *dev)
+{
+ int err;
+
+ if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+ return 0;
+
+ spin_lock_init(&dev->srq_table.lock);
+
+ err = mthca_alloc_init(&dev->srq_table.alloc,
+ dev->limits.num_srqs,
+ dev->limits.num_srqs - 1,
+ dev->limits.reserved_srqs);
+ if (err)
+ return err;
+
+ err = mthca_array_init(&dev->srq_table.srq,
+ dev->limits.num_srqs);
+ if (err)
+ mthca_alloc_cleanup(&dev->srq_table.alloc);
+
+ return err;
+}
+
+void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev)
+{
+ if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+ return;
+
+ mthca_array_cleanup(&dev->srq_table.srq, dev->limits.num_srqs);
+ mthca_alloc_cleanup(&dev->srq_table.alloc);
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h b/drivers/infiniband/hw/mthca/mthca_user.h
index 3024c1b4547d..41613ec8a04e 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -69,6 +69,17 @@ struct mthca_create_cq_resp {
__u32 reserved;
};
+struct mthca_create_srq {
+ __u32 lkey;
+ __u32 db_index;
+ __u64 db_page;
+};
+
+struct mthca_create_srq_resp {
+ __u32 srqn;
+ __u32 reserved;
+};
+
struct mthca_create_qp {
__u32 lkey;
__u32 reserved;
diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
new file mode 100644
index 000000000000..1f4c0ff28f79
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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.
+ *
+ * $Id: mthca_wqe.h 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#ifndef MTHCA_WQE_H
+#define MTHCA_WQE_H
+
+#include <linux/types.h>
+
+enum {
+ MTHCA_NEXT_DBD = 1 << 7,
+ MTHCA_NEXT_FENCE = 1 << 6,
+ MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+ MTHCA_NEXT_EVENT_GEN = 1 << 2,
+ MTHCA_NEXT_SOLICIT = 1 << 1,
+
+ MTHCA_MLX_VL15 = 1 << 17,
+ MTHCA_MLX_SLR = 1 << 16
+};
+
+enum {
+ MTHCA_INVAL_LKEY = 0x100
+};
+
+struct mthca_next_seg {
+ __be32 nda_op; /* [31:6] next WQE [4:0] next opcode */
+ __be32 ee_nds; /* [31:8] next EE [7] DBD [6] F [5:0] next WQE size */
+ __be32 flags; /* [3] CQ [2] Event [1] Solicit */
+ __be32 imm; /* immediate data */
+};
+
+struct mthca_tavor_ud_seg {
+ u32 reserved1;
+ __be32 lkey;
+ __be64 av_addr;
+ u32 reserved2[4];
+ __be32 dqpn;
+ __be32 qkey;
+ u32 reserved3[2];
+};
+
+struct mthca_arbel_ud_seg {
+ __be32 av[8];
+ __be32 dqpn;
+ __be32 qkey;
+ u32 reserved[2];
+};
+
+struct mthca_bind_seg {
+ __be32 flags; /* [31] Atomic [30] rem write [29] rem read */
+ u32 reserved;
+ __be32 new_rkey;
+ __be32 lkey;
+ __be64 addr;
+ __be64 length;
+};
+
+struct mthca_raddr_seg {
+ __be64 raddr;
+ __be32 rkey;
+ u32 reserved;
+};
+
+struct mthca_atomic_seg {
+ __be64 swap_add;
+ __be64 compare;
+};
+
+struct mthca_data_seg {
+ __be32 byte_count;
+ __be32 lkey;
+ __be64 addr;
+};
+
+struct mthca_mlx_seg {
+ __be32 nda_op;
+ __be32 nds;
+ __be32 flags; /* [17] VL15 [16] SLR [14:12] static rate
+ [11:8] SL [3] C [2] E */
+ __be16 rlid;
+ __be16 vcrc;
+};
+
+#endif /* MTHCA_WQE_H */
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
index 394bc08abc6f..8935e74ae3f8 100644
--- a/drivers/infiniband/ulp/ipoib/Makefile
+++ b/drivers/infiniband/ulp/ipoib/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
obj-$(CONFIG_INFINIBAND_IPOIB) += ib_ipoib.o
ib_ipoib-y := ipoib_main.o \
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 04c98f54e9c4..bea960b8191f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 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,9 +51,9 @@
#include <asm/atomic.h>
#include <asm/semaphore.h>
-#include <ib_verbs.h>
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
/* constants */
@@ -88,8 +90,8 @@ enum {
/* structs */
struct ipoib_header {
- u16 proto;
- u16 reserved;
+ __be16 proto;
+ u16 reserved;
};
struct ipoib_pseudoheader {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index a84e5fe0f193..38b150f775e7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -97,7 +97,7 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
for (n = 0, i = 0; i < sizeof mgid / 2; ++i) {
n += sprintf(gid_buf + n, "%x",
- be16_to_cpu(((u16 *)mgid.raw)[i]));
+ be16_to_cpu(((__be16 *) mgid.raw)[i]));
if (i < sizeof mgid / 2 - 1)
gid_buf[n++] = ':';
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index eee82363167d..ef0e3894863c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -1,5 +1,8 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004, 2005 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
@@ -35,7 +38,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "ipoib.h"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fa00816a3cf7..49d120d2b92c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 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
@@ -34,7 +36,6 @@
#include "ipoib.h"
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -607,8 +608,8 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x "
IPOIB_GID_FMT "\n",
skb->dst ? "neigh" : "dst",
- be16_to_cpup((u16 *) skb->data),
- be32_to_cpup((u32 *) phdr->hwaddr),
+ be16_to_cpup((__be16 *) skb->data),
+ be32_to_cpup((__be32 *) phdr->hwaddr),
IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4)));
dev_kfree_skb_any(skb);
++priv->stats.tx_dropped;
@@ -671,7 +672,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- schedule_work(&priv->restart_task);
+ queue_work(ipoib_workqueue, &priv->restart_task);
}
static void ipoib_neigh_destructor(struct neighbour *n)
@@ -780,15 +781,11 @@ void ipoib_dev_cleanup(struct net_device *dev)
ipoib_ib_dev_cleanup(dev);
- if (priv->rx_ring) {
- kfree(priv->rx_ring);
- priv->rx_ring = NULL;
- }
+ kfree(priv->rx_ring);
+ kfree(priv->tx_ring);
- if (priv->tx_ring) {
- kfree(priv->tx_ring);
- priv->tx_ring = NULL;
- }
+ priv->rx_ring = NULL;
+ priv->tx_ring = NULL;
}
static void ipoib_setup(struct net_device *dev)
@@ -886,6 +883,12 @@ static ssize_t create_child(struct class_device *cdev,
if (pkey < 0 || pkey > 0xffff)
return -EINVAL;
+ /*
+ * Set the full membership bit, so that we join the right
+ * broadcast group, etc.
+ */
+ pkey |= 0x8000;
+
ret = ipoib_vlan_add(container_of(cdev, struct net_device, class_dev),
pkey);
@@ -938,6 +941,12 @@ static struct net_device *ipoib_add_port(const char *format,
goto alloc_mem_failed;
}
+ /*
+ * Set the full membership bit, so that we join the right
+ * broadcast group, etc.
+ */
+ priv->pkey |= 0x8000;
+
priv->dev->broadcast[8] = priv->pkey >> 8;
priv->dev->broadcast[9] = priv->pkey & 0xff;
@@ -1053,6 +1062,8 @@ static void ipoib_remove_one(struct ib_device *device)
ipoib_dev_cleanup(priv->dev);
free_netdev(priv->dev);
}
+
+ kfree(dev_list);
}
static int __init ipoib_init_module(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 70208c3d21e2..aca7aea18a69 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 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
@@ -357,7 +359,7 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec,
IB_SA_MCMEMBER_REC_MGID |
@@ -457,7 +459,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
comp_mask =
IB_SA_MCMEMBER_REC_MGID |
@@ -646,7 +648,7 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
/* Remove ourselves from the multicast group */
ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 4933edf062c2..79f59d0563ed 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -32,7 +33,7 @@
* $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "ipoib.h"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 94b8ea812fef..332d730e60c2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -32,7 +32,6 @@
* $Id: ipoib_vlan.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 20e3a165989f..3738d173f9a6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -160,6 +160,8 @@ struct input_event_compat {
# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
#elif defined(CONFIG_ARCH_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
+#elif defined(CONFIG_MIPS)
+# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
@@ -320,7 +322,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
if (get_user(v, ip + 1)) return -EFAULT;
if (v < 0 || v > KEY_MAX) return -EINVAL;
- if (v >> (dev->keycodesize * 8)) return -EINVAL;
+ if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
u = SET_INPUT_KEYCODE(dev, t, v);
clear_bit(u, dev->keybit);
set_bit(v, dev->keybit);
@@ -391,6 +393,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; len = SW_MAX; break;
default: return -EINVAL;
}
len = NBITS(len) * sizeof(long);
@@ -419,6 +422,13 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
}
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
+ int len;
+ len = NBITS(SW_MAX) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
+ }
+
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
int len;
if (!dev->name) return -ENOENT;
@@ -499,7 +509,7 @@ do { \
int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
for (i = 0; i < len / sizeof(compat_long_t); i++) \
- if (copy_to_user((compat_long_t*) p + i, \
+ if (copy_to_user((compat_long_t __user *) p + i, \
(compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
sizeof(compat_long_t))) \
return -EFAULT; \
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index a0118038330a..462f8d300aae 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -75,7 +75,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
if (!request_region(ioport, iolen, "emu10k1-gp"))
return -EBUSY;
- emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
port = gameport_allocate_port();
if (!emu || !port) {
printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 57615bc63906..47e93daa0fa7 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -83,7 +83,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
struct fm801_gp *gp;
struct gameport *port;
- gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+ gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL);
port = gameport_allocate_port();
if (!gp || !port) {
printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 70f051894a3c..d2e55dc956ba 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -142,7 +142,7 @@ static int ns558_isa_probe(int io)
return -EBUSY;
}
- ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
port = gameport_allocate_port();
if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed.\n");
@@ -215,7 +215,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
if (!request_region(ioport, iolen, "ns558-pnp"))
return -EBUSY;
- ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
port = gameport_allocate_port();
if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed\n");
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a275211c8e1e..88636a204525 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -89,6 +89,15 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
break;
+ case EV_SW:
+
+ if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
+ return;
+
+ change_bit(code, dev->sw);
+
+ break;
+
case EV_ABS:
if (code > ABS_MAX || !test_bit(code, dev->absbit))
@@ -402,6 +411,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
+ SPRINTF_BIT_A2(swbit, "SW=", SW_MAX, EV_SW);
envp[i++] = NULL;
@@ -490,6 +500,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
+ SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW);
len += sprintf(buf + len, "\n");
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index bf34f75b9467..bf65430181fa 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -269,7 +269,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
int i;
int err;
- if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+ if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL)))
return -ENOMEM;
a3d->gameport = gameport;
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 265962956c63..cf35ae638a0d 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -469,7 +469,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
int i;
int err;
- if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+ if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL)))
return -ENOMEM;
port->gameport = gameport;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index c3a5739030c3..64b1313a3c66 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -655,7 +655,7 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
int i;
int err;
- if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+ if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
return - ENOMEM;
err = analog_init_port(gameport, drv, port);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index a6002205328f..0b2e9fa26579 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -163,7 +163,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
int i, j;
int err;
- if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+ if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL)))
return -ENOMEM;
cobra->gameport = gameport;
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index fbd3eed07f90..2a3e4bb2da50 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -572,7 +572,7 @@ static struct db9 __init *db9_probe(int *config, int nargs)
}
}
- if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) {
+ if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 95bbdd302aad..5427bf9fc862 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -554,7 +554,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
return NULL;
}
- if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
+ if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 7d969420066c..8e4f92b115e6 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -242,7 +242,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
unsigned char data[GF2K_LENGTH];
int i, err;
- if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
+ if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL)))
return -ENOMEM;
gf2k->gameport = gameport;
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index d1500d2562d6..9d3f910dd568 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -301,7 +301,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
int i, j, t;
int err;
- if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+ if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
return -ENOMEM;
grip->gameport = gameport;
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 0da7bd133ccf..da17eee6f574 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -607,7 +607,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
struct grip_mp *grip;
int err;
- if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+ if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
return -ENOMEM;
grip->gameport = gameport;
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index f93da7bc082d..6a70ec429f06 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -183,7 +183,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
int i, t;
int err;
- if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
+ if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL)))
return -ENOMEM;
guillemot->gameport = gameport;
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 58728ebaaf80..e5a31e55d3e2 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -249,9 +249,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
int iforce_get_id_packet(struct iforce *iforce, char *packet)
{
- DECLARE_WAITQUEUE(wait, current);
- int timeout = HZ; /* 1 second */
-
switch (iforce->bus) {
case IFORCE_USB:
@@ -260,22 +257,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->cr.bRequest = packet[0];
iforce->ctrl->dev = iforce->usbdev;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&iforce->wait, &wait);
-
- if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
+ if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
return -1;
- }
- while (timeout && iforce->ctrl->status == -EINPROGRESS)
- timeout = schedule_timeout(timeout);
+ wait_event_interruptible_timeout(iforce->wait,
+ iforce->ctrl->status != -EINPROGRESS, HZ);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
-
- if (!timeout) {
+ if (iforce->ctrl->status != -EINPROGRESS) {
usb_unlink_urb(iforce->ctrl);
return -1;
}
@@ -290,16 +278,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->expect_packet = FF_CMD_QUERY;
iforce_send_packet(iforce, FF_CMD_QUERY, packet);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&iforce->wait, &wait);
-
- while (timeout && iforce->expect_packet)
- timeout = schedule_timeout(timeout);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
+ wait_event_interruptible_timeout(iforce->wait,
+ !iforce->expect_packet, HZ);
- if (!timeout) {
+ if (iforce->expect_packet) {
iforce->expect_packet = 0;
return -1;
}
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6369a24684fe..58600f91eff5 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,6 +95,7 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
+ wake_up(&iforce->wait);
iforce_process_packet(iforce,
(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index 9d3f8c38cb09..d7b3472bd686 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -212,7 +212,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
int i, t;
int err;
- if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
+ if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL)))
return -ENOMEM;
interact->gameport = gameport;
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 47144a7ed9e7..9e0353721a35 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -590,7 +590,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
comment[0] = 0;
- sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
+ sw = kzalloc(sizeof(struct sw), GFP_KERNEL);
buf = kmalloc(SW_LENGTH, GFP_KERNEL);
idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
if (!sw || !buf || !idbuf) {
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 9eb9954cac6e..7431efc4330e 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -262,7 +262,7 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
int i, j, k, l, m;
int err;
- if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+ if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
return -ENOMEM;
tmdc->gameport = gameport;
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 28100d461cb7..0c5b9c8297cd 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -178,7 +178,7 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return NULL;
}
- if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
+ if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index e55dee390775..444f7756fee6 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -132,6 +132,17 @@ config KEYBOARD_CORGI
To compile this driver as a module, choose M here: the
module will be called corgikbd.
+config KEYBOARD_SPITZ
+ tristate "Spitz keyboard"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+ SL-C3000 and Sl-C3100 series of PDAs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called spitzkbd.
+
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b02eeceea3c3..9ce0b87f2fac 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4d4985b59abf..1ad8c2ee7dbf 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -208,6 +208,7 @@ struct atkbd {
unsigned char resend;
unsigned char release;
unsigned char bat_xl;
+ unsigned char err_xl;
unsigned int last;
unsigned long time;
};
@@ -296,15 +297,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (atkbd->emul ||
!(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
- code == ATKBD_RET_ERR ||
+ (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
(code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
atkbd->release = code >> 7;
code &= 0x7f;
}
- if (!atkbd->emul &&
- (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
+ if (!atkbd->emul) {
+ if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
atkbd->bat_xl = !atkbd->release;
+ if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
+ atkbd->err_xl = !atkbd->release;
+ }
}
switch (code) {
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index a8551711e8d6..cd4b6e795013 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/irq.h>
@@ -32,7 +33,6 @@
/* 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)
-#define CORGIKBD_PRESSED 1
#define HINGE_SCAN_INTERVAL (HZ/4)
@@ -73,25 +73,13 @@ struct corgikbd {
struct input_dev input;
char phys[32];
- unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
spinlock_t lock;
-
struct timer_list timer;
struct timer_list htimer;
-};
-static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
-{
- if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
- corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
- input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
- if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
- input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
- } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
- corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
- input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
- }
-}
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
#define KB_DISCHARGE_DELAY 10
#define KB_ACTIVATE_DELAY 10
@@ -105,36 +93,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c
*/
static inline void corgikbd_discharge_all(void)
{
- // STROBE All HiZ
+ /* STROBE All HiZ */
GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
}
static inline void corgikbd_activate_all(void)
{
- // STROBE ALL -> High
+ /* STROBE ALL -> High */
GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
udelay(KB_DISCHARGE_DELAY);
- // Clear any interrupts we may have triggered when altering the GPIO lines
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
}
static inline void corgikbd_activate_col(int col)
{
- // STROBE col -> High, not col -> HiZ
+ /* STROBE col -> High, not col -> HiZ */
GPSR2 = CORGI_GPIO_STROBE_BIT(col);
GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
}
static inline void corgikbd_reset_col(int col)
{
- // STROBE col -> Low
+ /* STROBE col -> Low */
GPCR2 = CORGI_GPIO_STROBE_BIT(col);
- // STROBE col -> out, not col -> HiZ
+ /* STROBE col -> out, not col -> HiZ */
GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
}
@@ -149,10 +137,13 @@ static inline void corgikbd_reset_col(int col)
/* Scan the hardware keyboard and push any changes up through the input layer */
static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
{
- unsigned int row, col, rowd, scancode;
+ unsigned int row, col, rowd;
unsigned long flags;
unsigned int num_pressed;
+ if (corgikbd_data->suspended)
+ return;
+
spin_lock_irqsave(&corgikbd_data->lock, flags);
if (regs)
@@ -173,10 +164,21 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
rowd = GET_ROWS_STATUS(col);
for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
scancode = SCANCODE(row, col);
- handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
- if (rowd & KB_ROWMASK(row))
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
+
+ if (pressed)
num_pressed++;
+
+ if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
+ && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
+ input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+ corgikbd_data->suspend_jiffies=jiffies;
+ }
}
corgikbd_reset_col(col);
}
@@ -221,8 +223,11 @@ static void corgikbd_timer_callback(unsigned long data)
* The hinge switches generate no interrupt so they need to be
* monitored by a timer.
*
- * When we detect changes, we debounce it and then pass the three
- * positions the system can take as keypresses to the input system.
+ * We debounce the switches and pass them to the input system.
+ *
+ * gprr == 0x00 - Keyboard with Landscape Screen
+ * 0x08 - No Keyboard with Portrait Screen
+ * 0x0c - Keyboard and Screen Closed
*/
#define HINGE_STABLE_COUNT 2
@@ -235,7 +240,7 @@ static void corgikbd_hinge_timer(unsigned long data)
unsigned long gprr;
unsigned long flags;
- gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+ gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
if (gprr != sharpsl_hinge_state) {
hinge_count = 0;
sharpsl_hinge_state = gprr;
@@ -244,9 +249,8 @@ static void corgikbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&corgikbd_data->lock, flags);
- handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
- handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
- handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
+ 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_sync(&corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags);
@@ -255,19 +259,45 @@ static void corgikbd_hinge_timer(unsigned long data)
mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
}
+#ifdef CONFIG_PM
+static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+ corgikbd->suspended = 1;
+ }
+ return 0;
+}
+
+static int corgikbd_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ corgikbd->suspend_jiffies=jiffies;
+ corgikbd->suspended = 0;
+ }
+ return 0;
+}
+#else
+#define corgikbd_suspend NULL
+#define corgikbd_resume NULL
+#endif
+
static int __init corgikbd_probe(struct device *dev)
{
int i;
struct corgikbd *corgikbd;
- corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
+ corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
if (!corgikbd)
return -ENOMEM;
dev_set_drvdata(dev,corgikbd);
strcpy(corgikbd->phys, "corgikbd/input0");
- spin_lock_init(corgikbd->lock);
+ spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
init_timer(&corgikbd->timer);
@@ -279,6 +309,8 @@ static int __init corgikbd_probe(struct device *dev)
corgikbd->htimer.function = corgikbd_hinge_timer;
corgikbd->htimer.data = (unsigned long) corgikbd;
+ corgikbd->suspend_jiffies=jiffies;
+
init_input_dev(&corgikbd->input);
corgikbd->input.private = corgikbd;
corgikbd->input.name = "Corgi Keyboard";
@@ -288,7 +320,7 @@ static int __init corgikbd_probe(struct device *dev)
corgikbd->input.id.vendor = 0x0001;
corgikbd->input.id.product = 0x0001;
corgikbd->input.id.version = 0x0100;
- corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
+ corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
corgikbd->input.keycode = corgikbd->keycode;
corgikbd->input.keycodesize = sizeof(unsigned char);
corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
@@ -297,6 +329,8 @@ static int __init corgikbd_probe(struct device *dev)
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
clear_bit(0, corgikbd->input.keybit);
+ set_bit(SW_0, corgikbd->input.swbit);
+ set_bit(SW_1, corgikbd->input.swbit);
input_register_device(&corgikbd->input);
mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
@@ -343,6 +377,8 @@ static struct device_driver corgikbd_driver = {
.bus = &platform_bus_type,
.probe = corgikbd_probe,
.remove = corgikbd_remove,
+ .suspend = corgikbd_suspend,
+ .resume = corgikbd_resume,
};
static int __devinit corgikbd_init(void)
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
new file mode 100644
index 000000000000..1714045a182b
--- /dev/null
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -0,0 +1,478 @@
+/*
+ * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on corgikbd.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/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/spitz.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define KB_ROWS 7
+#define KB_COLS 11
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) (((r)<<4) + (c) + 1)
+#define NR_SCANCODES ((KB_ROWS<<4) + 1)
+
+#define HINGE_SCAN_INTERVAL (150) /* ms */
+
+#define SPITZ_KEY_CALENDER KEY_F1
+#define SPITZ_KEY_ADDRESS KEY_F2
+#define SPITZ_KEY_FN KEY_F3
+#define SPITZ_KEY_CANCEL KEY_F4
+#define SPITZ_KEY_EXOK KEY_F5
+#define SPITZ_KEY_EXCANCEL KEY_F6
+#define SPITZ_KEY_EXJOGDOWN KEY_F7
+#define SPITZ_KEY_EXJOGUP KEY_F8
+#define SPITZ_KEY_JAP1 KEY_LEFTALT
+#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL
+#define SPITZ_KEY_SYNC KEY_F9
+#define SPITZ_KEY_MAIL KEY_F10
+#define SPITZ_KEY_OK KEY_F11
+#define SPITZ_KEY_MENU KEY_F12
+
+static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
+ 0, /* 0 */
+ 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, 0, KEY_RIGHTSHIFT, 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_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 */
+};
+
+static int spitz_strobes[] = {
+ SPITZ_GPIO_KEY_STROBE0,
+ SPITZ_GPIO_KEY_STROBE1,
+ SPITZ_GPIO_KEY_STROBE2,
+ SPITZ_GPIO_KEY_STROBE3,
+ SPITZ_GPIO_KEY_STROBE4,
+ SPITZ_GPIO_KEY_STROBE5,
+ SPITZ_GPIO_KEY_STROBE6,
+ SPITZ_GPIO_KEY_STROBE7,
+ SPITZ_GPIO_KEY_STROBE8,
+ SPITZ_GPIO_KEY_STROBE9,
+ SPITZ_GPIO_KEY_STROBE10,
+};
+
+static int spitz_senses[] = {
+ SPITZ_GPIO_KEY_SENSE0,
+ SPITZ_GPIO_KEY_SENSE1,
+ SPITZ_GPIO_KEY_SENSE2,
+ SPITZ_GPIO_KEY_SENSE3,
+ SPITZ_GPIO_KEY_SENSE4,
+ SPITZ_GPIO_KEY_SENSE5,
+ SPITZ_GPIO_KEY_SENSE6,
+};
+
+struct spitzkbd {
+ unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
+ struct input_dev input;
+ char phys[32];
+
+ spinlock_t lock;
+ struct timer_list timer;
+ struct timer_list htimer;
+
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+#define KB_DISCHARGE_DELAY 10
+#define KB_ACTIVATE_DELAY 10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ * requires a function call per GPIO bit which is excessive
+ * when we need to access 11 bits at once, multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void spitzkbd_discharge_all(void)
+{
+ /* STROBE All HiZ */
+ GPCR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPCR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPCR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPCR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+}
+
+static inline void spitzkbd_activate_all(void)
+{
+ /* STROBE ALL -> High */
+ GPSR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT;
+ GPSR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT;
+ GPSR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT;
+ GPSR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT;
+
+ udelay(KB_DISCHARGE_DELAY);
+
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
+ GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
+ GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
+ GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
+ GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
+}
+
+static inline void spitzkbd_activate_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPSR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline void spitzkbd_reset_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPCR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline int spitzkbd_get_row_status(int col)
+{
+ return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
+ | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
+ | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
+}
+
+/*
+ * The spitz keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd;
+ unsigned long flags;
+ unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
+
+ if (spitzkbd_data->suspended)
+ return;
+
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ if (regs)
+ input_regs(&spitzkbd_data->input, regs);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+ /*
+ * Discharge the output driver capacitatance
+ * in the keyboard matrix. (Yes it is significant..)
+ */
+
+ spitzkbd_discharge_all();
+ udelay(KB_DISCHARGE_DELAY);
+
+ spitzkbd_activate_col(col);
+ udelay(KB_ACTIVATE_DELAY);
+
+ rowd = spitzkbd_get_row_status(col);
+ for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
+ scancode = SCANCODE(row, col);
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+
+ if (pressed)
+ num_pressed++;
+ }
+ spitzkbd_reset_col(col);
+ }
+
+ spitzkbd_activate_all();
+
+ input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+ input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+
+ if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
+ input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+ spitzkbd_data->suspend_jiffies = jiffies;
+ }
+
+ input_sync(&spitzkbd_data->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+}
+
+/*
+ * spitz keyboard interrupt handler.
+ */
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->timer)) {
+ /** wait chattering delay **/
+ udelay(20);
+ spitzkbd_scankeyboard(spitzkbd_data, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * spitz timer checking for released keys
+ */
+static void spitzkbd_timer_callback(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ spitzkbd_scankeyboard(spitzkbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate an interrupt.
+ * We debounce the switches and pass them to the input system.
+ */
+
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->htimer))
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ return IRQ_HANDLED;
+}
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void spitzkbd_hinge_timer(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ unsigned long state;
+ unsigned long flags;
+
+ state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+ if (state != sharpsl_hinge_state) {
+ hinge_count = 0;
+ sharpsl_hinge_state = state;
+ } else if (hinge_count < HINGE_STABLE_COUNT) {
+ hinge_count++;
+ }
+
+ 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_sync(&spitzkbd_data->input);
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+ } else {
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+ }
+}
+
+#ifdef CONFIG_PM
+static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ spitzkbd->suspended = 1;
+
+ /* Set Strobe lines as inputs - *except* strobe line 0 leave this
+ enabled so we can detect a power button press for resume */
+ for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+ }
+ return 0;
+}
+
+static int spitzkbd_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ spitzkbd->suspend_jiffies = jiffies;
+ spitzkbd->suspended = 0;
+ }
+ return 0;
+}
+#else
+#define spitzkbd_suspend NULL
+#define spitzkbd_resume NULL
+#endif
+
+static int __init spitzkbd_probe(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd;
+
+ spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
+ if (!spitzkbd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev,spitzkbd);
+ strcpy(spitzkbd->phys, "spitzkbd/input0");
+
+ spin_lock_init(&spitzkbd->lock);
+
+ /* Init Keyboard rescan timer */
+ init_timer(&spitzkbd->timer);
+ spitzkbd->timer.function = spitzkbd_timer_callback;
+ spitzkbd->timer.data = (unsigned long) spitzkbd;
+
+ /* Init Hinge Timer */
+ init_timer(&spitzkbd->htimer);
+ spitzkbd->htimer.function = spitzkbd_hinge_timer;
+ spitzkbd->htimer.data = (unsigned long) spitzkbd;
+
+ spitzkbd->suspend_jiffies=jiffies;
+
+ init_input_dev(&spitzkbd->input);
+ spitzkbd->input.private = spitzkbd;
+ spitzkbd->input.name = "Spitz Keyboard";
+ spitzkbd->input.dev = dev;
+ spitzkbd->input.phys = spitzkbd->phys;
+ spitzkbd->input.id.bustype = BUS_HOST;
+ spitzkbd->input.id.vendor = 0x0001;
+ spitzkbd->input.id.product = 0x0001;
+ spitzkbd->input.id.version = 0x0100;
+ spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ spitzkbd->input.keycode = spitzkbd->keycode;
+ spitzkbd->input.keycodesize = sizeof(unsigned char);
+ spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+
+ memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
+ for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
+ set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
+ clear_bit(0, spitzkbd->input.keybit);
+ set_bit(SW_0, spitzkbd->input.swbit);
+ set_bit(SW_1, spitzkbd->input.swbit);
+
+ input_register_device(&spitzkbd->input);
+ mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
+ pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
+ if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
+ SA_INTERRUPT, "Spitzkbd Sense", spitzkbd))
+ printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
+ else
+ set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING);
+ }
+
+ /* Set Strobe lines as outputs - set high */
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
+
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd);
+
+ set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE);
+
+ printk(KERN_INFO "input: Spitz Keyboard Registered\n");
+
+ return 0;
+}
+
+static int spitzkbd_remove(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
+ free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
+
+ free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+
+ del_timer_sync(&spitzkbd->htimer);
+ del_timer_sync(&spitzkbd->timer);
+
+ input_unregister_device(&spitzkbd->input);
+
+ kfree(spitzkbd);
+
+ return 0;
+}
+
+static struct device_driver spitzkbd_driver = {
+ .name = "spitz-keyboard",
+ .bus = &platform_bus_type,
+ .probe = spitzkbd_probe,
+ .remove = spitzkbd_remove,
+ .suspend = spitzkbd_suspend,
+ .resume = spitzkbd_resume,
+};
+
+static int __devinit spitzkbd_init(void)
+{
+ return driver_register(&spitzkbd_driver);
+}
+
+static void __exit spitzkbd_exit(void)
+{
+ driver_unregister(&spitzkbd_driver);
+}
+
+module_init(spitzkbd_init);
+module_exit(spitzkbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Spitz Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 596964ceb96d..4bae5d89348d 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static unsigned char sunkbd_keycode[128] = {
- 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0,
+ 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c4909b49337d..82b330bbf068 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
+psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0d68e5e0182a..b20783f9748a 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -170,7 +170,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
if (priv->i->flags & ALPS_WHEEL)
- input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
+ input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, forward);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 48d2b20d2642..7df96525222e 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -150,12 +150,12 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
}
-static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf)
+static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
{
return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
}
-static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char
return count;
}
-PSMOUSE_DEFINE_ATTR(smartscroll);
+PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
+ ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
/*
* Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -194,7 +195,7 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
static void ps2pp_disconnect(struct psmouse *psmouse)
{
- device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+ device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
}
static struct ps2pp_info *get_model_info(unsigned char model)
@@ -222,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
@@ -379,7 +381,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
- device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+ device_create_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_smartscroll.dattr);
}
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 2bb2fe78bdca..af24313ff5bb 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -25,6 +25,7 @@
#include "logips2pp.h"
#include "alps.h"
#include "lifebook.h"
+#include "trackpoint.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -57,10 +58,30 @@ static unsigned int psmouse_resetafter;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
-PSMOUSE_DEFINE_ATTR(protocol);
-PSMOUSE_DEFINE_ATTR(rate);
-PSMOUSE_DEFINE_ATTR(resolution);
-PSMOUSE_DEFINE_ATTR(resetafter);
+PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
+ NULL,
+ psmouse_attr_show_protocol, psmouse_attr_set_protocol);
+PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, rate),
+ psmouse_show_int_attr, psmouse_attr_set_rate);
+PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resolution),
+ psmouse_show_int_attr, psmouse_attr_set_resolution);
+PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resetafter),
+ psmouse_show_int_attr, psmouse_set_int_attr);
+
+static struct attribute *psmouse_attributes[] = {
+ &psmouse_attr_protocol.dattr.attr,
+ &psmouse_attr_rate.dattr.attr,
+ &psmouse_attr_resolution.dattr.attr,
+ &psmouse_attr_resetafter.dattr.attr,
+ NULL
+};
+
+static struct attribute_group psmouse_attribute_group = {
+ .attrs = psmouse_attributes,
+};
__obsolete_setup("psmouse_noext");
__obsolete_setup("psmouse_resolution=");
@@ -520,6 +541,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_IMPS;
/*
+ * Try to initialize the IBM TrackPoint
+ */
+ if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TRACKPOINT;
+
+/*
* Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3.
*/
@@ -600,6 +627,12 @@ static struct psmouse_protocol psmouse_protocols[] = {
.init = lifebook_init,
},
{
+ .type = PSMOUSE_TRACKPOINT,
+ .name = "TPPS/2",
+ .alias = "trackpoint",
+ .detect = trackpoint_detect,
+ },
+ {
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
@@ -787,10 +820,7 @@ static void psmouse_disconnect(struct serio *serio)
psmouse = serio_get_drvdata(serio);
- device_remove_file(&serio->dev, &psmouse_attr_protocol);
- device_remove_file(&serio->dev, &psmouse_attr_rate);
- device_remove_file(&serio->dev, &psmouse_attr_resolution);
- device_remove_file(&serio->dev, &psmouse_attr_resetafter);
+ sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
down(&psmouse_sem);
@@ -883,7 +913,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
+ if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) {
retval = -ENOMEM;
goto out;
}
@@ -927,10 +957,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
if (parent && parent->pt_activate)
parent->pt_activate(parent);
- device_create_file(&serio->dev, &psmouse_attr_protocol);
- device_create_file(&serio->dev, &psmouse_attr_rate);
- device_create_file(&serio->dev, &psmouse_attr_resolution);
- device_create_file(&serio->dev, &psmouse_attr_resetafter);
+ sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
psmouse_activate(psmouse);
@@ -1027,10 +1054,12 @@ static struct serio_driver psmouse_drv = {
.cleanup = psmouse_cleanup,
};
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
- ssize_t (*handler)(struct psmouse *, char *))
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct serio *serio = to_serio_port(dev);
+ struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+ struct psmouse *psmouse;
int retval;
retval = serio_pin_driver(serio);
@@ -1042,19 +1071,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
goto out;
}
- retval = handler(serio_get_drvdata(serio), buf);
+ psmouse = serio_get_drvdata(serio);
+
+ retval = attr->show(psmouse, attr->data, buf);
out:
serio_unpin_driver(serio);
return retval;
}
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
- ssize_t (*handler)(struct psmouse *, const char *, size_t))
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
- struct psmouse *psmouse = serio_get_drvdata(serio);
- struct psmouse *parent = NULL;
+ struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+ struct psmouse *psmouse, *parent = NULL;
int retval;
retval = serio_pin_driver(serio);
@@ -1070,6 +1101,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
if (retval)
goto out_unpin;
+ psmouse = serio_get_drvdata(serio);
+
if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV;
goto out_up;
@@ -1082,7 +1115,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
psmouse_deactivate(psmouse);
- retval = handler(psmouse, buf, count);
+ retval = attr->set(psmouse, attr->data, buf, count);
if (retval != -ENODEV)
psmouse_activate(psmouse);
@@ -1097,12 +1130,34 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
return retval;
}
-static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
+static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
+{
+ unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+
+ return sprintf(buf, "%lu\n", *field);
+}
+
+static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
+{
+ unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+ unsigned long value;
+ char *rest;
+
+ value = simple_strtoul(buf, &rest, 10);
+ if (*rest)
+ return -EINVAL;
+
+ *field = value;
+
+ return count;
+}
+
+static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
{
return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
}
-static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
struct serio *serio = psmouse->ps2dev.serio;
struct psmouse *parent = NULL;
@@ -1166,12 +1221,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
return count;
}
-static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->rate);
-}
-
-static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -1184,12 +1234,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s
return count;
}
-static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->resolution);
-}
-
-static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -1202,23 +1247,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *
return count;
}
-static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->resetafter);
-}
-
-static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
-{
- unsigned long value;
- char *rest;
-
- value = simple_strtoul(buf, &rest, 10);
- if (*rest)
- return -EINVAL;
-
- psmouse->resetafter = value;
- return count;
-}
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
{
@@ -1234,7 +1262,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
*((unsigned int *)kp->arg) = proto->type;
- return 0; \
+ return 0;
}
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 86691cf43433..45d2bd774f00 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -78,6 +78,7 @@ enum psmouse_type {
PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS,
PSMOUSE_LIFEBOOK,
+ PSMOUSE_TRACKPOINT,
PSMOUSE_AUTO /* This one should always be last */
};
@@ -85,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
- ssize_t (*handler)(struct psmouse *, char *));
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
- ssize_t (*handler)(struct psmouse *, const char *, size_t));
-
-#define PSMOUSE_DEFINE_ATTR(_name) \
-static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \
-static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
-static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \
-{ \
- return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \
-} \
-static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
-{ \
- return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
-} \
-static struct device_attribute psmouse_attr_##_name = \
- __ATTR(_name, S_IWUSR | S_IRUGO, \
- psmouse_do_show_##_name, psmouse_do_set_##_name);
+
+struct psmouse_attribute {
+ struct device_attribute dattr;
+ void *data;
+ ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
+ ssize_t (*set)(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count);
+};
+#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
+
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+
+#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
+static ssize_t _show(struct psmouse *, void *data, char *); \
+static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \
+static struct psmouse_attribute psmouse_attr_##_name = { \
+ .dattr = { \
+ .attr = { \
+ .name = __stringify(_name), \
+ .mode = _mode, \
+ .owner = THIS_MODULE, \
+ }, \
+ .show = psmouse_attr_show_helper, \
+ .store = psmouse_attr_set_helper, \
+ }, \
+ .data = _data, \
+ .show = _show, \
+ .set = _set, \
+}
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
new file mode 100644
index 000000000000..b4898d8a68e2
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.c
@@ -0,0 +1,304 @@
+/*
+ * Stephen Evanchik <evanchsa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Trademarks are the property of their respective owners.
+ */
+
+#include <linux/delay.h>
+#include <linux/serio.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/libps2.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "psmouse.h"
+#include "trackpoint.h"
+
+/*
+ * Device IO: read, write and toggle bit
+ */
+static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results)
+{
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val)
+{
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask)
+{
+ /* Bad things will happen if the loc param isn't in this range */
+ if (loc < 0x20 || loc >= 0x2F)
+ return -1;
+
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Trackpoint-specific attributes
+ */
+struct trackpoint_attr_data {
+ size_t field_offset;
+ unsigned char command;
+ unsigned char mask;
+};
+
+static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ struct trackpoint_attr_data *attr = data;
+ unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+
+ return sprintf(buf, "%u\n", *field);
+}
+
+static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ struct trackpoint_attr_data *attr = data;
+ unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+ unsigned long value;
+ char *rest;
+
+ value = simple_strtoul(buf, &rest, 10);
+ if (*rest || value > 255)
+ return -EINVAL;
+
+ *field = value;
+ trackpoint_write(&psmouse->ps2dev, attr->command, value);
+
+ return count;
+}
+
+#define TRACKPOINT_INT_ATTR(_name, _command) \
+ static struct trackpoint_attr_data trackpoint_attr_##_name = { \
+ .field_offset = offsetof(struct trackpoint_data, _name), \
+ .command = _command, \
+ }; \
+ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
+ &trackpoint_attr_##_name, \
+ trackpoint_show_int_attr, trackpoint_set_int_attr)
+
+static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ struct trackpoint_attr_data *attr = data;
+ unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+ unsigned long value;
+ char *rest;
+
+ value = simple_strtoul(buf, &rest, 10);
+ if (*rest || value > 1)
+ return -EINVAL;
+
+ if (*field != value) {
+ *field = value;
+ trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
+ }
+
+ return count;
+}
+
+
+#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
+ static struct trackpoint_attr_data trackpoint_attr_##_name = { \
+ .field_offset = offsetof(struct trackpoint_data, _name), \
+ .command = _command, \
+ .mask = _mask, \
+ }; \
+ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
+ &trackpoint_attr_##_name, \
+ trackpoint_show_int_attr, trackpoint_set_bit_attr)
+
+TRACKPOINT_INT_ATTR(sensitivity, TP_SENS);
+TRACKPOINT_INT_ATTR(speed, TP_SPEED);
+TRACKPOINT_INT_ATTR(inertia, TP_INERTIA);
+TRACKPOINT_INT_ATTR(reach, TP_REACH);
+TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS);
+TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG);
+TRACKPOINT_INT_ATTR(thresh, TP_THRESH);
+TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
+TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
+TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
+
+TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+static struct attribute *trackpoint_attrs[] = {
+ &psmouse_attr_sensitivity.dattr.attr,
+ &psmouse_attr_speed.dattr.attr,
+ &psmouse_attr_inertia.dattr.attr,
+ &psmouse_attr_reach.dattr.attr,
+ &psmouse_attr_draghys.dattr.attr,
+ &psmouse_attr_mindrag.dattr.attr,
+ &psmouse_attr_thresh.dattr.attr,
+ &psmouse_attr_upthresh.dattr.attr,
+ &psmouse_attr_ztime.dattr.attr,
+ &psmouse_attr_jenks.dattr.attr,
+ &psmouse_attr_press_to_select.dattr.attr,
+ &psmouse_attr_skipback.dattr.attr,
+ &psmouse_attr_ext_dev.dattr.attr,
+ NULL
+};
+
+static struct attribute_group trackpoint_attr_group = {
+ .attrs = trackpoint_attrs,
+};
+
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+ kfree(psmouse->private);
+ psmouse->private = NULL;
+}
+
+static int trackpoint_sync(struct psmouse *psmouse)
+{
+ unsigned char toggle;
+ struct trackpoint_data *tp = psmouse->private;
+
+ if (!tp)
+ return -1;
+
+ /* Disable features that may make device unusable with this driver */
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
+ if (toggle & TP_MASK_TWOHAND)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
+ if (toggle & TP_MASK_SOURCE_TAG)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
+ if (toggle & TP_MASK_MB)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
+
+ /* Push the config to the device */
+ trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity);
+ trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
+ trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
+
+ trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
+ trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
+ trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
+
+ trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
+ trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh);
+
+ trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime);
+ trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
+ if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
+ if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
+ if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+ return 0;
+}
+
+static void trackpoint_defaults(struct trackpoint_data *tp)
+{
+ tp->press_to_select = TP_DEF_PTSON;
+ tp->sensitivity = TP_DEF_SENS;
+ tp->speed = TP_DEF_SPEED;
+ tp->reach = TP_DEF_REACH;
+
+ tp->draghys = TP_DEF_DRAGHYS;
+ tp->mindrag = TP_DEF_MINDRAG;
+
+ tp->thresh = TP_DEF_THRESH;
+ tp->upthresh = TP_DEF_UP_THRESH;
+
+ tp->ztime = TP_DEF_Z_TIME;
+ tp->jenks = TP_DEF_JENKS_CURV;
+
+ tp->inertia = TP_DEF_INERTIA;
+ tp->skipback = TP_DEF_SKIPBACK;
+ tp->ext_dev = TP_DEF_EXT_DEV;
+}
+
+int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+ struct trackpoint_data *priv;
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char firmware_id;
+ unsigned char button_info;
+ unsigned char param[2];
+
+ param[0] = param[1] = 0;
+
+ if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+ return -1;
+
+ if (param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ if (!set_properties)
+ return 0;
+
+ firmware_id = param[1];
+
+ if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
+ printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
+ button_info = 0;
+ }
+
+ psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
+ if (!priv)
+ return -1;
+
+ psmouse->vendor = "IBM";
+ psmouse->name = "TrackPoint";
+
+ psmouse->reconnect = trackpoint_sync;
+ psmouse->disconnect = trackpoint_disconnect;
+
+ trackpoint_defaults(priv);
+ trackpoint_sync(psmouse);
+
+ sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+
+ printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
+ firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
+
+ return 0;
+}
+
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
new file mode 100644
index 000000000000..9857d8b6ad66
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.h
@@ -0,0 +1,147 @@
+/*
+ * IBM TrackPoint PS/2 mouse driver
+ *
+ * Stephen Evanchik <evanchsa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _TRACKPOINT_H
+#define _TRACKPOINT_H
+
+/*
+ * These constants are from the TrackPoint System
+ * Engineering documentation Version 4 from IBM Watson
+ * research:
+ * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
+
+#define TP_COMMAND 0xE2 /* Commands start with this */
+
+#define TP_READ_ID 0xE1 /* Sent for device identification */
+#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */
+ /* by the firmware ID */
+
+
+/*
+ * Commands
+ */
+#define TP_RECALIB 0x51 /* Recalibrate */
+#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */
+#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */
+#define TP_EXT_BTN 0x4B /* Read extended button status */
+#define TP_POR 0x7F /* Execute Power on Reset */
+#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */
+#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */
+#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */
+
+/*
+ * Mode manipulation
+ */
+#define TP_SET_SOFT_TRANS 0x4E /* Set mode */
+#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */
+#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */
+
+
+/*
+ * Register oriented commands/properties
+ */
+#define TP_WRITE_MEM 0x81
+#define TP_READ_MEM 0x80 /* Not used in this implementation */
+
+/*
+* RAM Locations for properties
+ */
+#define TP_SENS 0x4A /* Sensitivity */
+#define TP_MB 0x4C /* Read Middle Button Status (RO) */
+#define TP_INERTIA 0x4D /* Negative Inertia */
+#define TP_SPEED 0x60 /* Speed of TP Cursor */
+#define TP_REACH 0x57 /* Backup for Z-axis press */
+#define TP_DRAGHYS 0x58 /* Drag Hysteresis */
+ /* (how hard it is to drag */
+ /* with Z-axis pressed) */
+
+#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
+ /* to trigger dragging */
+
+#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */
+#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */
+#define TP_Z_TIME 0x5E /* How sharp of a press */
+#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */
+
+/*
+ * Toggling Flag bits
+ */
+#define TP_TOGGLE 0x47 /* Toggle command */
+
+#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
+#define TP_MASK_MB 0x01
+#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
+#define TP_MASK_EXT_DEV 0x02
+#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
+#define TP_MASK_DRIFT 0x80
+#define TP_TOGGLE_BURST 0x28 /* Burst Mode */
+#define TP_MASK_BURST 0x80
+#define TP_TOGGLE_PTSON 0x2C /* Press to Select */
+#define TP_MASK_PTSON 0x01
+#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */
+#define TP_MASK_HARD_TRANS 0x80
+#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */
+#define TP_MASK_TWOHAND 0x01
+#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */
+#define TP_MASK_STICKY_TWO 0x04
+#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */
+#define TP_MASK_SKIPBACK 0x08
+#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to
+ to the origin of the packet (external or TP) */
+#define TP_MASK_SOURCE_TAG 0x80
+#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the
+ external device will be forced to 1 */
+#define TP_MASK_EXT_TAG 0x04
+
+
+/* Power on Self Test Results */
+#define TP_POR_SUCCESS 0x3B
+
+/*
+ * Default power on values
+ */
+#define TP_DEF_SENS 0x80
+#define TP_DEF_INERTIA 0x06
+#define TP_DEF_SPEED 0x61
+#define TP_DEF_REACH 0x0A
+
+#define TP_DEF_DRAGHYS 0xFF
+#define TP_DEF_MINDRAG 0x14
+
+#define TP_DEF_THRESH 0x08
+#define TP_DEF_UP_THRESH 0xFF
+#define TP_DEF_Z_TIME 0x26
+#define TP_DEF_JENKS_CURV 0x87
+
+/* Toggles */
+#define TP_DEF_MB 0x00
+#define TP_DEF_PTSON 0x00
+#define TP_DEF_SKIPBACK 0x00
+#define TP_DEF_EXT_DEV 0x01
+
+#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
+
+struct trackpoint_data
+{
+ unsigned char sensitivity, speed, inertia, reach;
+ unsigned char draghys, mindrag;
+ unsigned char thresh, upthresh;
+ unsigned char ztime, jenks;
+
+ unsigned char press_to_select;
+ unsigned char skipback;
+
+ unsigned char ext_dev;
+};
+
+extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+
+#endif /* _TRACKPOINT_H */
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index c9e633d21d90..9a9221644250 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -69,16 +69,16 @@ static inline int i8042_platform_init(void)
*/
#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
- return -1;
+ return -EBUSY;
#endif
i8042_reset = 1;
#if defined(CONFIG_PPC64)
if (check_legacy_ioport(I8042_DATA_REG))
- return -1;
+ return -EBUSY;
if (!request_region(I8042_DATA_REG, 16, "i8042"))
- return -1;
+ return -EBUSY;
#endif
return 0;
}
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index 863b9c95fbb8..ee1ad27d6ed0 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -58,7 +58,7 @@ static inline int i8042_platform_init(void)
#if 0
/* XXX sgi_kh is a virtual address */
if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
- return 1;
+ return -EBUSY;
#endif
i8042_reset = 1;
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
index 5c20ab131488..13fd7108eb28 100644
--- a/drivers/input/serio/i8042-jazzio.h
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -53,7 +53,7 @@ static inline int i8042_platform_init(void)
#if 0
/* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
- return 1;
+ return -EBUSY;
#endif
return 0;
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index da2a19812485..ed9446f6d7e3 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -48,10 +48,10 @@ static inline void i8042_write_command(int val)
#define OBP_PS2MS_NAME1 "kdmouse"
#define OBP_PS2MS_NAME2 "mouse"
-static int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
{
#ifndef CONFIG_PCI
- return -1;
+ return -ENODEV;
#else
char prop[128];
int len;
@@ -59,14 +59,14 @@ static int i8042_platform_init(void)
len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
if (len < 0) {
printk("i8042: Cannot get name property of root OBP node.\n");
- return -1;
+ return -ENODEV;
}
if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
/* Hardcoded values for MrCoffee. */
i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
kbd_iobase = ioremap(0x71300060, 8);
if (!kbd_iobase)
- return -1;
+ return -ENODEV;
} else {
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
@@ -78,7 +78,7 @@ static int i8042_platform_init(void)
goto edev_found;
}
}
- return -1;
+ return -ENODEV;
edev_found:
for_each_edevchild(edev, child) {
@@ -96,7 +96,7 @@ static int i8042_platform_init(void)
i8042_aux_irq == -1) {
printk("i8042: Error, 8042 device lacks both kbd and "
"mouse nodes.\n");
- return -1;
+ return -ENODEV;
}
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 03877c84e6ff..273bb3b08cfa 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -138,6 +138,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ .ident = "Fujitsu-Siemens Lifebook E4010",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
+ },
+ },
+ {
.ident = "Toshiba P10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -256,9 +263,10 @@ static void i8042_pnp_exit(void)
}
}
-static int i8042_pnp_init(void)
+static int __init i8042_pnp_init(void)
{
- int result_kbd, result_aux;
+ int result_kbd = 0, result_aux = 0;
+ char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
if (i8042_nopnp) {
printk(KERN_INFO "i8042: PNP detection disabled\n");
@@ -267,6 +275,7 @@ static int i8042_pnp_init(void)
if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
i8042_pnp_kbd_registered = 1;
+
if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
i8042_pnp_aux_registered = 1;
@@ -280,6 +289,27 @@ static int i8042_pnp_init(void)
#endif
}
+ if (result_kbd > 0)
+ snprintf(kbd_irq_str, sizeof(kbd_irq_str),
+ "%d", i8042_pnp_kbd_irq);
+ if (result_aux > 0)
+ 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_aux_name,
+ i8042_pnp_data_reg, i8042_pnp_command_reg,
+ kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+ aux_irq_str);
+
+#if defined(__ia64__)
+ if (result_kbd <= 0)
+ i8042_nokbd = 1;
+ if (result_aux <= 0)
+ i8042_noaux = 1;
+#endif
+
if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
@@ -294,53 +324,47 @@ static int i8042_pnp_init(void)
i8042_pnp_command_reg = i8042_command_reg;
}
- if (!i8042_pnp_kbd_irq) {
- printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+ if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq);
i8042_pnp_kbd_irq = i8042_kbd_irq;
}
- if (!i8042_pnp_aux_irq) {
- printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+ if (!i8042_noaux && !i8042_pnp_aux_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq);
i8042_pnp_aux_irq = i8042_aux_irq;
}
-#if defined(__ia64__)
- if (result_aux <= 0)
- i8042_noaux = 1;
-#endif
-
i8042_data_reg = i8042_pnp_data_reg;
i8042_command_reg = i8042_pnp_command_reg;
i8042_kbd_irq = i8042_pnp_kbd_irq;
i8042_aux_irq = i8042_pnp_aux_irq;
- printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
- i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
- i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
- (result_aux > 0) ? "," : "", i8042_aux_irq);
-
return 0;
}
+#else
+static inline int i8042_pnp_init(void) { return 0; }
+static inline void i8042_pnp_exit(void) { }
#endif
-static inline int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
{
+ int retval;
+
/*
* On ix86 platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on ix86 boxes.
*
* if (!request_region(I8042_DATA_REG, 16, "i8042"))
- * return -1;
+ * return -EBUSY;
*/
i8042_kbd_irq = I8042_MAP_IRQ(1);
i8042_aux_irq = I8042_MAP_IRQ(12);
-#ifdef CONFIG_PNP
- if (i8042_pnp_init())
- return -1;
-#endif
+ retval = i8042_pnp_init();
+ if (retval)
+ return retval;
#if defined(__ia64__)
i8042_reset = 1;
@@ -354,14 +378,12 @@ static inline int i8042_platform_init(void)
i8042_nomux = 1;
#endif
- return 0;
+ return retval;
}
static inline void i8042_platform_exit(void)
{
-#ifdef CONFIG_PNP
i8042_pnp_exit();
-#endif
}
#endif /* _I8042_X86IA64IO_H */
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 708a1d3beab9..40d451ce07ff 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
MODULE_LICENSE("GPL");
+static unsigned int i8042_nokbd;
+module_param_named(nokbd, i8042_nokbd, bool, 0);
+MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port.");
+
static unsigned int i8042_noaux;
module_param_named(noaux, i8042_noaux, bool, 0);
MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
@@ -338,10 +342,10 @@ static int i8042_open(struct serio *serio)
return 0;
-activate_fail:
+ activate_fail:
free_irq(port->irq, i8042_request_irq_cookie);
-irq_fail:
+ irq_fail:
serio_unregister_port_delayed(serio);
return -1;
@@ -485,7 +489,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
serio_interrupt(port->serio, data, dfl, regs);
ret = 1;
-out:
+ out:
return IRQ_RETVAL(ret);
}
@@ -552,7 +556,7 @@ static int i8042_enable_mux_ports(void)
* Enable all muxed ports.
*/
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
i8042_command(&param, I8042_CMD_MUX_PFX + i);
i8042_command(&param, I8042_CMD_AUX_ENABLE);
}
@@ -682,7 +686,7 @@ static int __init i8042_port_register(struct i8042_port *port)
kfree(port->serio);
port->serio = NULL;
i8042_ctr |= port->disable;
- return -1;
+ return -EIO;
}
printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
@@ -977,85 +981,88 @@ static struct device_driver i8042_driver = {
.shutdown = i8042_shutdown,
};
-static void __init i8042_create_kbd_port(void)
+static int __init i8042_create_kbd_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
- serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
- strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
-
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+ serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
+ strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
-static void __init i8042_create_aux_port(void)
+static int __init i8042_create_aux_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->write = i8042_aux_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
- strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
-
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = SERIO_8042;
+ serio->write = i8042_aux_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
+ strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
-static void __init i8042_create_mux_port(int index)
+static int __init i8042_create_mux_port(int index)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->write = i8042_aux_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
- snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
-
- *port = i8042_ports[I8042_AUX_PORT_NO];
- port->exists = 0;
- snprintf(port->name, sizeof(port->name), "AUX%d", index);
- port->mux = index;
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = SERIO_8042;
+ serio->write = i8042_aux_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
+ snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
+
+ *port = i8042_ports[I8042_AUX_PORT_NO];
+ port->exists = 0;
+ snprintf(port->name, sizeof(port->name), "AUX%d", index);
+ port->mux = index;
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
static int __init i8042_init(void)
{
- int i;
+ int i, have_ports = 0;
int err;
dbg_init();
@@ -1063,43 +1070,73 @@ static int __init i8042_init(void)
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
- if (i8042_platform_init())
- return -EBUSY;
+ err = i8042_platform_init();
+ if (err)
+ return err;
i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
if (i8042_controller_init()) {
- i8042_platform_exit();
- return -ENODEV;
+ err = -ENODEV;
+ goto err_platform_exit;
}
err = driver_register(&i8042_driver);
- if (err) {
- i8042_platform_exit();
- return err;
- }
+ if (err)
+ goto err_controller_cleanup;
i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
if (IS_ERR(i8042_platform_device)) {
- driver_unregister(&i8042_driver);
- i8042_platform_exit();
- return PTR_ERR(i8042_platform_device);
+ err = PTR_ERR(i8042_platform_device);
+ goto err_unregister_driver;
}
if (!i8042_noaux && !i8042_check_aux()) {
- if (!i8042_nomux && !i8042_check_mux())
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
- i8042_create_mux_port(i);
- else
- i8042_create_aux_port();
+ if (!i8042_nomux && !i8042_check_mux()) {
+ for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
+ err = i8042_create_mux_port(i);
+ if (err)
+ goto err_unregister_ports;
+ }
+ } else {
+ err = i8042_create_aux_port();
+ if (err)
+ goto err_unregister_ports;
+ }
+ have_ports = 1;
}
- i8042_create_kbd_port();
+ if (!i8042_nokbd) {
+ err = i8042_create_kbd_port();
+ if (err)
+ goto err_unregister_ports;
+ have_ports = 1;
+ }
+
+ if (!have_ports) {
+ err = -ENODEV;
+ goto err_unregister_device;
+ }
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return 0;
+
+ err_unregister_ports:
+ for (i = 0; i < I8042_NUM_PORTS; i++)
+ if (i8042_ports[i].serio)
+ serio_unregister_port(i8042_ports[i].serio);
+ err_unregister_device:
+ platform_device_unregister(i8042_platform_device);
+ err_unregister_driver:
+ driver_unregister(&i8042_driver);
+ err_controller_cleanup:
+ i8042_controller_cleanup();
+ err_platform_exit:
+ i8042_platform_exit();
+
+ return err;
}
static void __exit i8042_exit(void)
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 79ca38469159..1bd88fca0542 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -87,7 +87,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL);
+ serport = kzalloc(sizeof(struct serport), GFP_KERNEL);
if (!serport)
return -ENOMEM;
@@ -165,7 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
return -EBUSY;
- serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
+ serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0489af5a80c9..21d55ed4b88a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -24,17 +24,17 @@ config TOUCHSCREEN_BITSY
module will be called h3600_ts_input.
config TOUCHSCREEN_CORGI
- tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the driver for the touchscreen on the
- Sharp SL-C7xx series of PDAs.
+ Sharp SL-C7xx and SL-Cxx00 series of PDAs.
If unsure, say N.
To compile this driver as a module, choose M here: the
- module will be called ads7846_ts.
+ module will be called corgi_ts.
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 3f8b61cfbc37..4c7fbe550365 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -1,5 +1,5 @@
/*
- * Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models
*
* Copyright (c) 2004-2005 Richard Purdie
*
@@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <asm/irq.h>
-#include <asm/arch/corgi.h>
+#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -47,18 +47,20 @@ struct corgi_ts {
struct ts_event tc;
int pendown;
int power_mode;
+ int irq_gpio;
+ struct corgits_machinfo *machinfo;
};
-#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
-
-#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#ifdef CONFIG_PXA25x
#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
-#define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-#define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-
-#define WAIT_HS_400_VGA 7013U // 17.615us
-#define WAIT_HS_400_QVGA 16622U // 41.750us
-
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
+#endif
+#ifdef CONFIG_PXA27x
+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x))
+#endif
/* ADS7846 Touch Screen Controller bit definitions */
#define ADSCTRL_PD0 (1u << 0) /* PD0 */
@@ -69,43 +71,31 @@ struct corgi_ts {
#define ADSCTRL_STS (1u << 7) /* Start Bit */
/* External Functions */
-extern int w100fb_get_xres(void);
-extern int w100fb_get_blanking(void);
-extern int w100fb_get_fastsysclk(void);
extern unsigned int get_clk_frequency_khz(int info);
-static unsigned long calc_waittime(void)
+static unsigned long calc_waittime(struct corgi_ts *corgi_ts)
{
- int w100fb_xres = w100fb_get_xres();
- unsigned int waittime = 0;
-
- if (w100fb_xres == 480 || w100fb_xres == 640) {
- waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
-
- if (w100fb_get_fastsysclk() == 100)
- waittime = waittime * 75 / 100;
-
- if (w100fb_xres == 640)
- waittime *= 3;
+ unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len();
- return waittime;
- }
-
- return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
+ if (hsync_len)
+ return get_clk_frequency_khz(0)*1000/hsync_len;
+ else
+ return 0;
}
-static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend,
+ unsigned int address, unsigned long wait_time)
{
+ unsigned long timer1 = 0, timer2, pmnc = 0;
int pos = 0;
- unsigned long timer1 = 0, timer2;
- int dosleep;
- dosleep = !w100fb_get_blanking();
+ if (wait_time && doSend) {
+ PMNC_GET(pmnc);
+ if (!(pmnc & 0x01))
+ PMNC_SET(0x01);
- if (dosleep && doSend) {
- CCNT_ON();
/* polling HSync */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get CCNT */
CCNT(timer1);
}
@@ -119,12 +109,12 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
corgi_ssp_ads7846_put(cmd);
corgi_ssp_ads7846_get();
- if (dosleep) {
+ if (wait_time) {
/* Wait after HSync */
CCNT(timer2);
if (timer2-timer1 > wait_time) {
- /* timeout */
- SyncHS();
+ /* too slow - timeout, try again */
+ corgi_ts->machinfo->wait_hsync();
/* get OSCR */
CCNT(timer1);
/* Wait after HSync */
@@ -134,8 +124,8 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
CCNT(timer2);
}
corgi_ssp_ads7846_put(cmd);
- if (dosleep)
- CCNT_OFF();
+ if (wait_time && !(pmnc & 0x01))
+ PMNC_SET(pmnc);
}
return pos;
}
@@ -148,23 +138,23 @@ static int read_xydata(struct corgi_ts *corgi_ts)
/* critical section */
local_irq_save(flags);
corgi_ssp_ads7846_lock();
- wait_time=calc_waittime();
+ wait_time = calc_waittime(corgi_ts);
/* Y-axis */
- sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time);
/* Y-axis */
- sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time);
/* X-axis */
- y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+ y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time);
/* Z1 */
- x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+ x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time);
/* Z2 */
- z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
- z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+ z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time);
+ z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time);
/* Power-Down Enable */
corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -204,9 +194,9 @@ static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
{
- if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+ if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
/* Disable Interrupt */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
if (read_xydata(corgi_ts)) {
corgi_ts->pendown = 1;
new_data(corgi_ts, regs);
@@ -225,7 +215,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->pendown = 0;
}
}
@@ -244,7 +234,7 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
#ifdef CONFIG_PM
-static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+static int corgits_suspend(struct device *dev, pm_message_t state, uint32_t level)
{
if (level == SUSPEND_POWER_DOWN) {
struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
@@ -269,7 +259,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
}
return 0;
@@ -282,6 +272,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
static int __init corgits_probe(struct device *dev)
{
struct corgi_ts *corgi_ts;
+ struct platform_device *pdev = to_platform_device(dev);
if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
return -ENOMEM;
@@ -290,6 +281,14 @@ static int __init corgits_probe(struct device *dev)
memset(corgi_ts, 0, sizeof(struct corgi_ts));
+ corgi_ts->machinfo = dev->platform_data;
+ corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
+
+ if (corgi_ts->irq_gpio < 0) {
+ kfree(corgi_ts);
+ return -ENODEV;
+ }
+
init_input_dev(&corgi_ts->input);
corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
@@ -308,8 +307,7 @@ static int __init corgits_probe(struct device *dev)
corgi_ts->input.id.product = 0x0002;
corgi_ts->input.id.version = 0x0100;
- pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
- pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+ pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
/* Initiaize ADS7846 Difference Reference mode */
corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -328,14 +326,14 @@ static int __init corgits_probe(struct device *dev)
input_register_device(&corgi_ts->input);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
- if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+ if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return -EBUSY;
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
@@ -346,8 +344,9 @@ static int corgits_remove(struct device *dev)
{
struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+ free_irq(corgi_ts->irq_gpio, NULL);
del_timer_sync(&corgi_ts->timer);
+ corgi_ts->machinfo->put_hsync();
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return 0;
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index afa46681f983..6ae6eb322111 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -606,7 +606,7 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
(m->msg.data_b3_req.blocknr == blocknr)) {
/* found corresponding DATA_B3_REQ */
- skb_unlink(tmp);
+ skb_unlink(tmp, &card->ackq);
chan->queued -= m->msg.data_b3_req.datalen;
if (m->msg.data_b3_req.flags)
ret = m->msg.data_b3_req.datalen;
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index f8570fd9d2ab..3abd7fc6e5ef 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -191,8 +191,10 @@ static int __init capifs_init(void)
err = register_filesystem(&capifs_fs_type);
if (!err) {
capifs_mnt = kern_mount(&capifs_fs_type);
- if (IS_ERR(capifs_mnt))
+ if (IS_ERR(capifs_mnt)) {
err = PTR_ERR(capifs_mnt);
+ unregister_filesystem(&capifs_fs_type);
+ }
}
if (!err)
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 17cf7663c582..26c545fa223b 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -10,7 +10,6 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -1242,6 +1241,8 @@ struct IsdnCardState {
#ifdef CONFIG_HISAX_ENTERNOW_PCI
#define CARD_FN_ENTERNOW_PCI 1
+#else
+#define CARD_FN_ENTERNOW_PCI 0
#endif
#define TEI_PER_CARD 1
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index baf4bcad9bf9..0afe442db3b0 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -283,23 +283,19 @@ static void bsd_free (void *state)
/*
* Release the dictionary
*/
- if (db->dict) {
- vfree (db->dict);
- db->dict = NULL;
- }
+ vfree(db->dict);
+ db->dict = NULL;
/*
* Release the string buffer
*/
- if (db->lens) {
- vfree (db->lens);
- db->lens = NULL;
- }
+ vfree(db->lens);
+ db->lens = NULL;
/*
* Finally release the structure itself.
*/
- kfree (db);
+ kfree(db);
}
}
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index eebcb0b97f0e..8a7d54a5c97d 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1953,7 +1953,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
kfree(d->rcvcount);
if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
- if (!adding) kfree(d->rcverr);
+ if (!adding)
+ kfree(d->rcverr);
return -1;
}
memset((char *) d->rcvcount, 0, sizeof(int) * m);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index f30e8e63ae0d..96c115e13389 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1786,7 +1786,6 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
lp->stats.rx_bytes += skb->len;
}
skb->dev = ndev;
- skb->input_dev = ndev;
skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data;
#ifdef ISDN_DEBUG_NET_DUMP
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 260a323a96d3..d97a9be5469c 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1177,7 +1177,6 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
mlp->huptimer = 0;
#endif /* CONFIG_IPPP_FILTER */
skb->dev = dev;
- skb->input_dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
index f47f2b9846d8..38619e8cd823 100644
--- a/drivers/isdn/i4l/isdn_v110.c
+++ b/drivers/isdn/i4l/isdn_v110.c
@@ -516,11 +516,11 @@ buffer_full:
}
int
-isdn_v110_stat_callback(int idx, isdn_ctrl * c)
+isdn_v110_stat_callback(int idx, isdn_ctrl *c)
{
isdn_v110_stream *v = NULL;
int i;
- int ret;
+ int ret = 0;
if (idx < 0)
return 0;
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 40b0df04ed9f..1ebed041672d 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -87,7 +87,7 @@ static int __init sc_init(void)
*/
for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
if(!request_region(io[b] + i * 0x400, 1, "sc test")) {
- pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400);
+ pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
io[b] = 0;
break;
} else
@@ -181,7 +181,7 @@ static int __init sc_init(void)
for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) {
pr_debug("Checking RAM address 0x%x...\n", i);
if(request_region(i, SRAM_PAGESIZE, "sc test")) {
- pr_debug(" check_region succeeded\n");
+ pr_debug(" request_region succeeded\n");
model = identify_board(i, io[b]);
release_region(i, SRAM_PAGESIZE);
if (model >= 0) {
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 7c16c25fc5d4..c0712a1ea5af 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -708,7 +708,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
{
struct media_bay_info *bay = macio_get_drvdata(mdev);
- if (state != mdev->ofdev.dev.power.power_state && state == PM_SUSPEND_MEM) {
+ if (state.event != mdev->ofdev.dev.power.power_state.event && state.event == PM_EVENT_SUSPEND) {
down(&bay->lock);
bay->sleeping = 1;
set_mb_power(bay, 0);
@@ -723,8 +723,8 @@ static int __pmac media_bay_resume(struct macio_dev *mdev)
{
struct media_bay_info *bay = macio_get_drvdata(mdev);
- if (mdev->ofdev.dev.power.power_state != 0) {
- mdev->ofdev.dev.power.power_state = 0;
+ if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
+ mdev->ofdev.dev.power.power_state = PMSG_ON;
/* We re-enable the bay using it's previous content
only if it did not change. Note those bozo timings,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4a0a0ad2d03c..645a2e5c70ab 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -3065,7 +3065,7 @@ static int pmu_sys_suspended = 0;
static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
{
- if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+ if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended)
return 0;
/* Suspend PMU event interrupts */
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 41df4cda66e2..2fba2bbe72d8 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -270,19 +270,20 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
if (!page)
return ERR_PTR(-ENOMEM);
- do {
- ITERATE_RDEV(mddev, rdev, tmp)
- if (rdev->in_sync && !rdev->faulty)
- goto found;
- return ERR_PTR(-EIO);
- found:
+ ITERATE_RDEV(mddev, rdev, tmp) {
+ if (! rdev->in_sync || rdev->faulty)
+ continue;
+
target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
- } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+ if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+ page->index = index;
+ return page;
+ }
+ }
+ return ERR_PTR(-EIO);
- page->index = index;
- return page;
}
static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
@@ -437,6 +438,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
printk(KERN_DEBUG " daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
printk(KERN_DEBUG " sync size: %llu KB\n",
(unsigned long long)le64_to_cpu(sb->sync_size)/2);
+ printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
kunmap(bitmap->sb_page);
}
@@ -445,7 +447,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
{
char *reason = NULL;
bitmap_super_t *sb;
- unsigned long chunksize, daemon_sleep;
+ unsigned long chunksize, daemon_sleep, write_behind;
unsigned long bytes_read;
unsigned long long events;
int err = -EINVAL;
@@ -474,6 +476,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
chunksize = le32_to_cpu(sb->chunksize);
daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+ write_behind = le32_to_cpu(sb->write_behind);
/* verify that the bitmap-specific fields are valid */
if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -485,7 +488,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
else if ((1 << ffz(~chunksize)) != chunksize)
reason = "bitmap chunksize not a power of 2";
else if (daemon_sleep < 1 || daemon_sleep > 15)
- reason = "daemon sleep period out of range";
+ reason = "daemon sleep period out of range (1-15s)";
+ else if (write_behind > COUNTER_MAX)
+ reason = "write-behind limit out of range (0 - 16383)";
if (reason) {
printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
bmname(bitmap), reason);
@@ -518,8 +523,12 @@ success:
/* assign fields using values from superblock */
bitmap->chunksize = chunksize;
bitmap->daemon_sleep = daemon_sleep;
+ bitmap->daemon_lastrun = jiffies;
+ bitmap->max_write_behind = write_behind;
bitmap->flags |= sb->state;
bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+ if (sb->state & BITMAP_STALE)
+ bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
kunmap(bitmap->sb_page);
@@ -617,7 +626,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
page_cache_release(sb_page);
}
-static void bitmap_stop_daemons(struct bitmap *bitmap);
+static void bitmap_stop_daemon(struct bitmap *bitmap);
/* dequeue the next item in a page list -- don't call from irq context */
static struct page_list *dequeue_page(struct bitmap *bitmap)
@@ -659,7 +668,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
bitmap->file = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags);
- bitmap_stop_daemons(bitmap);
+ bitmap_stop_daemon(bitmap);
drain_write_queues(bitmap);
@@ -818,7 +827,7 @@ int bitmap_unplug(struct bitmap *bitmap)
return 0;
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file
@@ -826,8 +835,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
* if there's no bitmap file, or if the bitmap file had been
* previously kicked from the array, we mark all the bits as
* 1's in order to cause a full resync.
+ *
+ * We ignore all bits for sectors that end earlier than 'start'.
+ * This is used when reading an out-of-date bitmap...
*/
-static int bitmap_init_from_disk(struct bitmap *bitmap)
+static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
{
unsigned long i, chunks, index, oldindex, bit;
struct page *page = NULL, *oldpage = NULL;
@@ -914,7 +926,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
* whole page and write it out
*/
memset(page_address(page) + offset, 0xff,
- PAGE_SIZE - offset);
+ PAGE_SIZE - offset);
ret = write_page(bitmap, page, 1);
if (ret) {
kunmap(page);
@@ -928,8 +940,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
}
if (test_bit(bit, page_address(page))) {
/* if the disk bit is set, set the memory bit */
- bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
+ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
+ ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
+ );
bit_cnt++;
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
}
@@ -1141,6 +1156,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
err = -EINTR;
goto out;
}
+ if (bitmap == NULL)
+ /* about to be stopped. */
+ return;
PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
/* wait on bitmap page writebacks */
@@ -1170,21 +1188,12 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
}
}
-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
void (*func)(mddev_t *), char *name)
{
mdk_thread_t *daemon;
- unsigned long flags;
char namebuf[32];
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = NULL;
-
- if (!bitmap->file) /* no need for daemon if there's no backing file */
- goto out_unlock;
-
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
#ifdef INJECT_FATAL_FAULT_2
daemon = NULL;
#else
@@ -1194,47 +1203,32 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
if (!daemon) {
printk(KERN_ERR "%s: failed to start bitmap daemon\n",
bmname(bitmap));
- return -ECHILD;
+ return ERR_PTR(-ECHILD);
}
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = daemon;
-
md_wakeup_thread(daemon); /* start it running */
PRINTK("%s: %s daemon (pid %d) started...\n",
bmname(bitmap), name, daemon->tsk->pid);
-out_unlock:
- spin_unlock_irqrestore(&bitmap->lock, flags);
- return 0;
-}
-static int bitmap_start_daemons(struct bitmap *bitmap)
-{
- int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
- bitmap_writeback_daemon, "bitmap_wb");
- return err;
+ return daemon;
}
-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+static void bitmap_stop_daemon(struct bitmap *bitmap)
{
- mdk_thread_t *daemon;
- unsigned long flags;
-
- spin_lock_irqsave(&bitmap->lock, flags);
- daemon = *ptr;
- *ptr = NULL;
- spin_unlock_irqrestore(&bitmap->lock, flags);
- if (daemon)
- md_unregister_thread(daemon); /* destroy the thread */
-}
+ /* the daemon can't stop itself... it'll just exit instead... */
+ if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+ current->pid != bitmap->writeback_daemon->tsk->pid) {
+ mdk_thread_t *daemon;
+ unsigned long flags;
-static void bitmap_stop_daemons(struct bitmap *bitmap)
-{
- /* the daemons can't stop themselves... they'll just exit instead... */
- if (bitmap->writeback_daemon &&
- current->pid != bitmap->writeback_daemon->tsk->pid)
- bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+ spin_lock_irqsave(&bitmap->lock, flags);
+ daemon = bitmap->writeback_daemon;
+ bitmap->writeback_daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (daemon && ! IS_ERR(daemon))
+ md_unregister_thread(daemon); /* destroy the thread */
+ }
}
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1274,9 +1268,16 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
}
}
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
{
if (!bitmap) return 0;
+
+ if (behind) {
+ atomic_inc(&bitmap->behind_writes);
+ PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
+ atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ }
+
while (sectors) {
int blocks;
bitmap_counter_t *bmc;
@@ -1311,9 +1312,15 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
}
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
- int success)
+ int success, int behind)
{
if (!bitmap) return;
+ if (behind) {
+ atomic_dec(&bitmap->behind_writes);
+ PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
+ atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ }
+
while (sectors) {
int blocks;
unsigned long flags;
@@ -1424,7 +1431,7 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
{
/* For each chunk covered by any of these sectors, set the
* counter to 1 and set resync_needed. They should all
@@ -1441,7 +1448,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
}
if (! *bmc) {
struct page *page;
- *bmc = 1 | NEEDED_MASK;
+ *bmc = 1 | (needed?NEEDED_MASK:0);
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
@@ -1476,17 +1483,14 @@ void bitmap_flush(mddev_t *mddev)
/*
* free memory that was allocated
*/
-void bitmap_destroy(mddev_t *mddev)
+static void bitmap_free(struct bitmap *bitmap)
{
unsigned long k, pages;
struct bitmap_page *bp;
- struct bitmap *bitmap = mddev->bitmap;
if (!bitmap) /* there was no bitmap */
return;
- mddev->bitmap = NULL; /* disconnect from the md device */
-
/* release the bitmap file and kill the daemon */
bitmap_file_put(bitmap);
@@ -1504,6 +1508,17 @@ void bitmap_destroy(mddev_t *mddev)
kfree(bp);
kfree(bitmap);
}
+void bitmap_destroy(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+
+ if (!bitmap) /* there was no bitmap */
+ return;
+
+ mddev->bitmap = NULL; /* disconnect from the md device */
+
+ bitmap_free(bitmap);
+}
/*
* initialize the bitmap structure
@@ -1517,6 +1532,7 @@ int bitmap_create(mddev_t *mddev)
unsigned long pages;
struct file *file = mddev->bitmap_file;
int err;
+ sector_t start;
BUG_ON(sizeof(bitmap_super_t) != 256);
@@ -1533,15 +1549,15 @@ int bitmap_create(mddev_t *mddev)
spin_lock_init(&bitmap->lock);
bitmap->mddev = mddev;
- mddev->bitmap = bitmap;
spin_lock_init(&bitmap->write_lock);
INIT_LIST_HEAD(&bitmap->complete_pages);
init_waitqueue_head(&bitmap->write_wait);
bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
write_pool_free, NULL);
+ err = -ENOMEM;
if (!bitmap->write_pool)
- return -ENOMEM;
+ goto error;
bitmap->file = file;
bitmap->offset = mddev->bitmap_offset;
@@ -1549,7 +1565,7 @@ int bitmap_create(mddev_t *mddev)
/* read superblock from bitmap file (this sets bitmap->chunksize) */
err = bitmap_read_sb(bitmap);
if (err)
- return err;
+ goto error;
bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
sizeof(bitmap->chunksize));
@@ -1573,27 +1589,44 @@ int bitmap_create(mddev_t *mddev)
#else
bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
#endif
+ err = -ENOMEM;
if (!bitmap->bp)
- return -ENOMEM;
+ goto error;
memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
bitmap->flags |= BITMAP_ACTIVE;
/* now that we have some pages available, initialize the in-memory
* bitmap from the on-disk bitmap */
- err = bitmap_init_from_disk(bitmap);
+ start = 0;
+ if (mddev->degraded == 0
+ || bitmap->events_cleared == mddev->events)
+ /* no need to keep dirty bits to optimise a re-add of a missing device */
+ start = mddev->recovery_cp;
+ err = bitmap_init_from_disk(bitmap, start);
if (err)
- return err;
+ goto error;
printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
pages, bmname(bitmap));
- /* kick off the bitmap daemons */
- err = bitmap_start_daemons(bitmap);
- if (err)
- return err;
+ mddev->bitmap = bitmap;
+
+ if (file)
+ /* kick off the bitmap writeback daemon */
+ bitmap->writeback_daemon =
+ bitmap_start_daemon(bitmap,
+ bitmap_writeback_daemon,
+ "bitmap_wb");
+
+ if (IS_ERR(bitmap->writeback_daemon))
+ return PTR_ERR(bitmap->writeback_daemon);
return bitmap_update_sb(bitmap);
+
+ error:
+ bitmap_free(bitmap);
+ return err;
}
/* the bitmap API -- for raid personalities */
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index d0a4bab220e5..b82bc3150476 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -144,7 +144,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
}
/* Hash the cipher key with the given hash algorithm */
- hash_tfm = crypto_alloc_tfm(opts, 0);
+ hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP);
if (hash_tfm == NULL) {
ti->error = PFX "Error initializing ESSIV hash";
return -EINVAL;
@@ -172,7 +172,8 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
/* Setup the essiv_tfm with the given salt */
essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm),
- CRYPTO_TFM_MODE_ECB);
+ CRYPTO_TFM_MODE_ECB |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
if (essiv_tfm == NULL) {
ti->error = PFX "Error allocating crypto tfm for ESSIV";
kfree(salt);
@@ -587,7 +588,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad1;
}
- tfm = crypto_alloc_tfm(cipher, crypto_flags);
+ tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP);
if (!tfm) {
ti->error = PFX "Error allocating crypto tfm";
goto bad1;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 17212b4201a1..cc07bbebbb16 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -568,12 +568,9 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
bad:
dm_io_put(sectors_to_pages(chunk_size));
- if (ps) {
- if (ps->area)
- free_area(ps);
-
- kfree(ps);
- }
+ if (ps && ps->area)
+ free_area(ps);
+ kfree(ps);
return r;
}
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 45754bb6a799..9de000131a8a 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -239,6 +239,11 @@ static void vm_dp_init(struct dpages *dp, void *data)
dp->context_ptr = data;
}
+static void dm_bio_destructor(struct bio *bio)
+{
+ bio_free(bio, _bios);
+}
+
/*-----------------------------------------------------------------
* IO routines that accept a list of pages.
*---------------------------------------------------------------*/
@@ -263,6 +268,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
bio->bi_bdev = where->bdev;
bio->bi_end_io = endio;
bio->bi_private = io;
+ bio->bi_destructor = dm_bio_destructor;
bio_set_region(bio, region);
/*
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index b08df8b9b2ca..863282513753 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -375,16 +375,18 @@ static void rh_inc(struct region_hash *rh, region_t region)
read_lock(&rh->hash_lock);
reg = __rh_find(rh, region);
+
+ atomic_inc(&reg->pending);
+
+ spin_lock_irq(&rh->region_lock);
if (reg->state == RH_CLEAN) {
rh->log->type->mark_region(rh->log, reg->key);
- spin_lock_irq(&rh->region_lock);
reg->state = RH_DIRTY;
list_del_init(&reg->list); /* take off the clean list */
- spin_unlock_irq(&rh->region_lock);
}
+ spin_unlock_irq(&rh->region_lock);
- atomic_inc(&reg->pending);
read_unlock(&rh->hash_lock);
}
@@ -408,6 +410,10 @@ static void rh_dec(struct region_hash *rh, region_t region)
if (atomic_dec_and_test(&reg->pending)) {
spin_lock_irqsave(&rh->region_lock, flags);
+ if (atomic_read(&reg->pending)) { /* check race */
+ spin_unlock_irqrestore(&rh->region_lock, flags);
+ return;
+ }
if (reg->state == RH_RECOVERING) {
list_add_tail(&reg->list, &rh->quiesced_regions);
} else {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d487d9deb98e..930b9fc27953 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -399,6 +399,11 @@ struct clone_info {
unsigned short idx;
};
+static void dm_bio_destructor(struct bio *bio)
+{
+ bio_free(bio, dm_set);
+}
+
/*
* Creates a little bio that is just does part of a bvec.
*/
@@ -410,6 +415,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
struct bio_vec *bv = bio->bi_io_vec + idx;
clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set);
+ clone->bi_destructor = dm_bio_destructor;
*clone->bi_io_vec = *bv;
clone->bi_sector = sector;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 8d740013d74d..bb279fad2fd2 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -38,7 +38,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
/*
* sector_div(a,b) returns the remainer and sets a to a/b
*/
- (void)sector_div(block, conf->smallest->size);
+ block >>= conf->preshift;
+ (void)sector_div(block, conf->hash_spacing);
hash = conf->hash_table[block];
while ((sector>>1) >= (hash->size + hash->offset))
@@ -47,7 +48,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
}
/**
- * linear_mergeable_bvec -- tell bio layer if a two requests can be merged
+ * linear_mergeable_bvec -- tell bio layer if two requests can be merged
* @q: request queue
* @bio: the buffer head that's been built up so far
* @biovec: the request that could be merged to it.
@@ -116,7 +117,7 @@ static int linear_run (mddev_t *mddev)
dev_info_t **table;
mdk_rdev_t *rdev;
int i, nb_zone, cnt;
- sector_t start;
+ sector_t min_spacing;
sector_t curr_offset;
struct list_head *tmp;
@@ -127,11 +128,6 @@ static int linear_run (mddev_t *mddev)
memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
mddev->private = conf;
- /*
- * Find the smallest device.
- */
-
- conf->smallest = NULL;
cnt = 0;
mddev->array_size = 0;
@@ -159,8 +155,6 @@ static int linear_run (mddev_t *mddev)
disk->size = rdev->size;
mddev->array_size += rdev->size;
- if (!conf->smallest || (disk->size < conf->smallest->size))
- conf->smallest = disk;
cnt++;
}
if (cnt != mddev->raid_disks) {
@@ -168,6 +162,36 @@ static int linear_run (mddev_t *mddev)
goto out;
}
+ min_spacing = mddev->array_size;
+ sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+
+ /* min_spacing is the minimum spacing that will fit the hash
+ * table in one PAGE. This may be much smaller than needed.
+ * We find the smallest non-terminal set of consecutive devices
+ * that is larger than min_spacing as use the size of that as
+ * the actual spacing
+ */
+ conf->hash_spacing = mddev->array_size;
+ for (i=0; i < cnt-1 ; i++) {
+ sector_t sz = 0;
+ int j;
+ for (j=i; i<cnt-1 && sz < min_spacing ; j++)
+ sz += conf->disks[j].size;
+ if (sz >= min_spacing && sz < conf->hash_spacing)
+ conf->hash_spacing = sz;
+ }
+
+ /* hash_spacing may be too large for sector_div to work with,
+ * so we might need to pre-shift
+ */
+ conf->preshift = 0;
+ if (sizeof(sector_t) > sizeof(u32)) {
+ sector_t space = conf->hash_spacing;
+ while (space > (sector_t)(~(u32)0)) {
+ space >>= 1;
+ conf->preshift++;
+ }
+ }
/*
* This code was restructured to work around a gcc-2.95.3 internal
* compiler error. Alter it with care.
@@ -177,39 +201,52 @@ static int linear_run (mddev_t *mddev)
unsigned round;
unsigned long base;
- sz = mddev->array_size;
- base = conf->smallest->size;
+ sz = mddev->array_size >> conf->preshift;
+ sz += 1; /* force round-up */
+ base = conf->hash_spacing >> conf->preshift;
round = sector_div(sz, base);
- nb_zone = conf->nr_zones = sz + (round ? 1 : 0);
+ nb_zone = sz + (round ? 1 : 0);
}
-
- conf->hash_table = kmalloc (sizeof (dev_info_t*) * nb_zone,
+ BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
+
+ conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
GFP_KERNEL);
if (!conf->hash_table)
goto out;
/*
* Here we generate the linear hash table
+ * First calculate the device offsets.
*/
+ conf->disks[0].offset = 0;
+ for (i=1; i<mddev->raid_disks; i++)
+ conf->disks[i].offset =
+ conf->disks[i-1].offset +
+ conf->disks[i-1].size;
+
table = conf->hash_table;
- start = 0;
curr_offset = 0;
- for (i = 0; i < cnt; i++) {
- dev_info_t *disk = conf->disks + i;
+ i = 0;
+ for (curr_offset = 0;
+ curr_offset < mddev->array_size;
+ curr_offset += conf->hash_spacing) {
- disk->offset = curr_offset;
- curr_offset += disk->size;
+ while (i < mddev->raid_disks-1 &&
+ curr_offset >= conf->disks[i+1].offset)
+ i++;
- /* 'curr_offset' is the end of this disk
- * 'start' is the start of table
+ *table ++ = conf->disks + i;
+ }
+
+ if (conf->preshift) {
+ conf->hash_spacing >>= conf->preshift;
+ /* round hash_spacing up so that when we divide by it,
+ * we err on the side of "too-low", which is safest.
*/
- while (start < curr_offset) {
- *table++ = disk;
- start += conf->smallest->size;
- }
+ conf->hash_spacing++;
}
- if (table-conf->hash_table != nb_zone)
- BUG();
+
+ BUG_ON(table - conf->hash_table > nb_zone);
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->unplug_fn = linear_unplug;
@@ -238,6 +275,11 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
dev_info_t *tmp_dev;
sector_t block;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
if (bio_data_dir(bio)==WRITE) {
disk_stat_inc(mddev->gendisk, writes);
disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
@@ -294,7 +336,7 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
sector_t s = 0;
seq_printf(seq, " ");
- for (j = 0; j < conf->nr_zones; j++)
+ for (j = 0; j < mddev->raid_disks; j++)
{
char b[BDEVNAME_SIZE];
s += conf->smallest_size;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 20ca80b7dc20..2897df90df44 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/config.h>
+#include <linux/kthread.h>
#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/raid/bitmap.h>
@@ -73,7 +74,7 @@ static DEFINE_SPINLOCK(pers_lock);
* Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit'
* is 1000 KB/sec, so the extra system load does not show up that much.
* Increase it if you want to have more _guaranteed_ speed. Note that
- * the RAID driver will use the maximum available bandwith if the IO
+ * the RAID driver will use the maximum available bandwidth if the IO
* subsystem is idle. There is also an 'absolute maximum' reconstruction
* speed limit - in case reconstruction slows down your system despite
* idle IO detection.
@@ -393,7 +394,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
return ret;
}
-static int read_disk_sb(mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev, int size)
{
char b[BDEVNAME_SIZE];
if (!rdev->sb_page) {
@@ -404,7 +405,7 @@ static int read_disk_sb(mdk_rdev_t * rdev)
return 0;
- if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
+ if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
goto fail;
rdev->sb_loaded = 1;
return 0;
@@ -531,7 +532,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ ret = read_disk_sb(rdev, MD_SB_BYTES);
if (ret) return ret;
ret = -EINVAL;
@@ -564,6 +565,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
rdev->preferred_minor = sb->md_minor;
rdev->data_offset = 0;
+ rdev->sb_size = MD_SB_BYTES;
if (sb->level == LEVEL_MULTIPATH)
rdev->desc_nr = -1;
@@ -623,6 +625,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->size = sb->size;
mddev->events = md_event(sb);
mddev->bitmap_offset = 0;
+ mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
if (sb->state & (1<<MD_SB_CLEAN))
mddev->recovery_cp = MaxSector;
@@ -643,12 +646,12 @@ 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) {
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps only support for raid1\n");
return -EINVAL;
}
- mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+ mddev->bitmap_offset = mddev->default_bitmap_offset;
}
} else if (mddev->pers == NULL) {
@@ -669,6 +672,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (mddev->level != LEVEL_MULTIPATH) {
rdev->faulty = 0;
+ rdev->flags = 0;
desc = sb->disks + rdev->desc_nr;
if (desc->state & (1<<MD_DISK_FAULTY))
@@ -678,6 +682,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 1;
rdev->raid_disk = desc->raid_disk;
}
+ if (desc->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
} else /* MULTIPATH are always insync */
rdev->in_sync = 1;
return 0;
@@ -706,6 +712,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
int i;
int active=0, working=0,failed=0,spare=0,nr_disks=0;
+ rdev->sb_size = MD_SB_BYTES;
+
sb = (mdp_super_t*)page_address(rdev->sb_page);
memset(sb, 0, sizeof(*sb));
@@ -776,6 +784,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
spare++;
working++;
}
+ if (test_bit(WriteMostly, &rdev2->flags))
+ d->state |= (1<<MD_DISK_WRITEMOSTLY);
}
/* now set the "removed" and "faulty" bits on any missing devices */
@@ -831,6 +841,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
int ret;
sector_t sb_offset;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+ int bmask;
/*
* Calculate the position of the superblock.
@@ -859,7 +870,10 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
}
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ /* superblock is rarely larger than 1K, but it can be larger,
+ * and it is safe to read 4k, so we do that
+ */
+ ret = read_disk_sb(rdev, 4096);
if (ret) return ret;
@@ -869,7 +883,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
sb->major_version != cpu_to_le32(1) ||
le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
- sb->feature_map != 0)
+ (le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
return -EINVAL;
if (calc_sb_1_csum(sb) != sb->sb_csum) {
@@ -885,6 +899,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
+ rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
+ bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+ if (rdev->sb_size & bmask)
+ rdev-> sb_size = (rdev->sb_size | bmask)+1;
+
if (refdev == 0)
return 1;
else {
@@ -939,13 +958,15 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events);
mddev->bitmap_offset = 0;
+ mddev->default_bitmap_offset = 0;
+ mddev->default_bitmap_offset = 1024;
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
memcpy(mddev->uuid, sb->set_uuid, 16);
mddev->max_disks = (4096-256)/2;
- if ((le32_to_cpu(sb->feature_map) & 1) &&
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
mddev->bitmap_file == NULL ) {
if (mddev->level != 1) {
printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
@@ -986,6 +1007,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->raid_disk = role;
break;
}
+ rdev->flags = 0;
+ if (sb->devflags & WriteMostly1)
+ set_bit(WriteMostly, &rdev->flags);
} else /* MULTIPATH are always insync */
rdev->in_sync = 1;
@@ -1017,7 +1041,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
if (mddev->bitmap && mddev->bitmap_file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
- sb->feature_map = cpu_to_le32(1);
+ sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
max_dev = 0;
@@ -1363,7 +1387,7 @@ repeat:
dprintk("%s ", bdevname(rdev->bdev,b));
if (!rdev->faulty) {
md_super_write(mddev,rdev,
- rdev->sb_offset<<1, MD_SB_BYTES,
+ rdev->sb_offset<<1, rdev->sb_size,
rdev->sb_page);
dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
bdevname(rdev->bdev,b),
@@ -2073,6 +2097,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
info.state = 0;
if (mddev->in_sync)
info.state = (1<<MD_SB_CLEAN);
+ if (mddev->bitmap && mddev->bitmap_offset)
+ info.state = (1<<MD_SB_BITMAP_PRESENT);
info.active_disks = active;
info.working_disks = working;
info.failed_disks = failed;
@@ -2087,7 +2113,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
return 0;
}
-static int get_bitmap_file(mddev_t * mddev, void * arg)
+static int get_bitmap_file(mddev_t * mddev, void __user * arg)
{
mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
char *ptr, *buf = NULL;
@@ -2146,6 +2172,8 @@ static int get_disk_info(mddev_t * mddev, void __user * arg)
info.state |= (1<<MD_DISK_ACTIVE);
info.state |= (1<<MD_DISK_SYNC);
}
+ if (test_bit(WriteMostly, &rdev->flags))
+ info.state |= (1<<MD_DISK_WRITEMOSTLY);
} else {
info.major = info.minor = 0;
info.raid_disk = -1;
@@ -2210,8 +2238,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
mdname(mddev));
return -EINVAL;
}
- rdev = md_import_device(dev, mddev->major_version,
- mddev->minor_version);
+ if (mddev->persistent)
+ rdev = md_import_device(dev, mddev->major_version,
+ mddev->minor_version);
+ else
+ rdev = md_import_device(dev, -1, -1);
if (IS_ERR(rdev)) {
printk(KERN_WARNING
"md: md_import_device returned %ld\n",
@@ -2231,6 +2262,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
rdev->saved_raid_disk = rdev->raid_disk;
rdev->in_sync = 0; /* just to be sure */
+ if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
+
rdev->raid_disk = -1;
err = bind_rdev_to_array(rdev, mddev);
if (err)
@@ -2271,6 +2305,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
else
rdev->in_sync = 0;
+ if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
+
err = bind_rdev_to_array(rdev, mddev);
if (err) {
export_rdev(rdev);
@@ -2430,25 +2467,51 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
{
int err;
- if (mddev->pers)
- return -EBUSY;
+ if (mddev->pers) {
+ if (!mddev->pers->quiesce)
+ return -EBUSY;
+ if (mddev->recovery || mddev->sync_thread)
+ return -EBUSY;
+ /* we should be able to change the bitmap.. */
+ }
- mddev->bitmap_file = fget(fd);
- if (mddev->bitmap_file == NULL) {
- printk(KERN_ERR "%s: error: failed to get bitmap file\n",
- mdname(mddev));
- return -EBADF;
- }
+ if (fd >= 0) {
+ if (mddev->bitmap)
+ return -EEXIST; /* cannot add when bitmap is present */
+ mddev->bitmap_file = fget(fd);
- err = deny_bitmap_write_access(mddev->bitmap_file);
- if (err) {
- printk(KERN_ERR "%s: error: bitmap file is already in use\n",
- mdname(mddev));
- fput(mddev->bitmap_file);
- mddev->bitmap_file = NULL;
- } else
+ if (mddev->bitmap_file == NULL) {
+ printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+ mdname(mddev));
+ return -EBADF;
+ }
+
+ err = deny_bitmap_write_access(mddev->bitmap_file);
+ if (err) {
+ printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+ mdname(mddev));
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ return err;
+ }
mddev->bitmap_offset = 0; /* file overrides offset */
+ } else if (mddev->bitmap == NULL)
+ return -ENOENT; /* cannot remove what isn't there */
+ err = 0;
+ if (mddev->pers) {
+ mddev->pers->quiesce(mddev, 1);
+ if (fd >= 0)
+ err = bitmap_create(mddev);
+ if (fd < 0 || err)
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ } else if (fd < 0) {
+ if (mddev->bitmap_file)
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ }
+
return err;
}
@@ -2528,6 +2591,11 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
{
int rv = 0;
int cnt = 0;
+ int state = 0;
+
+ /* calculate expected state,ignoring low bits */
+ if (mddev->bitmap && mddev->bitmap_offset)
+ state |= (1 << MD_SB_BITMAP_PRESENT);
if (mddev->major_version != info->major_version ||
mddev->minor_version != info->minor_version ||
@@ -2536,12 +2604,16 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
mddev->level != info->level ||
/* mddev->layout != info->layout || */
!mddev->persistent != info->not_persistent||
- mddev->chunk_size != info->chunk_size )
+ mddev->chunk_size != info->chunk_size ||
+ /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
+ ((state^info->state) & 0xfffffe00)
+ )
return -EINVAL;
/* Check there is only one change */
if (mddev->size != info->size) cnt++;
if (mddev->raid_disks != info->raid_disks) cnt++;
if (mddev->layout != info->layout) cnt++;
+ if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
if (cnt == 0) return 0;
if (cnt > 1) return -EINVAL;
@@ -2620,6 +2692,35 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
}
}
}
+ if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (mddev->recovery || mddev->sync_thread)
+ return -EBUSY;
+ if (info->state & (1<<MD_SB_BITMAP_PRESENT)) {
+ /* add the bitmap */
+ if (mddev->bitmap)
+ return -EEXIST;
+ if (mddev->default_bitmap_offset == 0)
+ return -EINVAL;
+ mddev->bitmap_offset = mddev->default_bitmap_offset;
+ mddev->pers->quiesce(mddev, 1);
+ rv = bitmap_create(mddev);
+ if (rv)
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ } else {
+ /* remove the bitmap */
+ if (!mddev->bitmap)
+ return -ENOENT;
+ if (mddev->bitmap->file)
+ return -EINVAL;
+ mddev->pers->quiesce(mddev, 1);
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ mddev->bitmap_offset = 0;
+ }
+ }
md_update_sb(mddev);
return rv;
}
@@ -2781,7 +2882,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case GET_BITMAP_FILE:
- err = get_bitmap_file(mddev, (void *)arg);
+ err = get_bitmap_file(mddev, argp);
goto done_unlock;
case GET_DISK_INFO:
@@ -2950,18 +3051,6 @@ static int md_thread(void * arg)
{
mdk_thread_t *thread = arg;
- lock_kernel();
-
- /*
- * Detach thread
- */
-
- daemonize(thread->name, mdname(thread->mddev));
-
- current->exit_signal = SIGCHLD;
- allow_signal(SIGKILL);
- thread->tsk = current;
-
/*
* md_thread is a 'system-thread', it's priority should be very
* high. We avoid resource deadlocks individually in each
@@ -2973,14 +3062,14 @@ static int md_thread(void * arg)
* bdflush, otherwise bdflush will deadlock if there are too
* many dirty RAID5 blocks.
*/
- unlock_kernel();
complete(thread->event);
- while (thread->run) {
+ while (!kthread_should_stop()) {
void (*run)(mddev_t *);
wait_event_interruptible_timeout(thread->wqueue,
- test_bit(THREAD_WAKEUP, &thread->flags),
+ test_bit(THREAD_WAKEUP, &thread->flags)
+ || kthread_should_stop(),
thread->timeout);
try_to_freeze();
@@ -2989,11 +3078,8 @@ static int md_thread(void * arg)
run = thread->run;
if (run)
run(thread->mddev);
-
- if (signal_pending(current))
- flush_signals(current);
}
- complete(thread->event);
+
return 0;
}
@@ -3010,11 +3096,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
const char *name)
{
mdk_thread_t *thread;
- int ret;
struct completion event;
- thread = (mdk_thread_t *) kmalloc
- (sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
@@ -3027,8 +3111,8 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
thread->mddev = mddev;
thread->name = name;
thread->timeout = MAX_SCHEDULE_TIMEOUT;
- ret = kernel_thread(md_thread, thread, 0);
- if (ret < 0) {
+ thread->tsk = kthread_run(md_thread, thread, mdname(thread->mddev));
+ if (IS_ERR(thread->tsk)) {
kfree(thread);
return NULL;
}
@@ -3038,21 +3122,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
void md_unregister_thread(mdk_thread_t *thread)
{
- struct completion event;
-
- init_completion(&event);
-
- thread->event = &event;
-
- /* As soon as ->run is set to NULL, the task could disappear,
- * so we need to hold tasklist_lock until we have sent the signal
- */
dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
- read_lock(&tasklist_lock);
- thread->run = NULL;
- send_sig(SIGKILL, thread->tsk, 1);
- read_unlock(&tasklist_lock);
- wait_for_completion(&event);
+
+ kthread_stop(thread->tsk);
kfree(thread);
}
@@ -3259,10 +3331,13 @@ static int md_seq_show(struct seq_file *seq, void *v)
char b[BDEVNAME_SIZE];
seq_printf(seq, " %s[%d]",
bdevname(rdev->bdev,b), rdev->desc_nr);
+ if (test_bit(WriteMostly, &rdev->flags))
+ seq_printf(seq, "(W)");
if (rdev->faulty) {
seq_printf(seq, "(F)");
continue;
- }
+ } else if (rdev->raid_disk < 0)
+ seq_printf(seq, "(S)"); /* spare */
size += rdev->size;
}
@@ -3274,6 +3349,15 @@ static int md_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n %llu blocks",
(unsigned long long)size);
}
+ if (mddev->persistent) {
+ if (mddev->major_version != 0 ||
+ mddev->minor_version != 90) {
+ seq_printf(seq," super %d.%d",
+ mddev->major_version,
+ mddev->minor_version);
+ }
+ } else
+ seq_printf(seq, " super non-persistent");
if (mddev->pers) {
mddev->pers->status (seq, mddev);
@@ -3416,7 +3500,6 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
*/
void md_write_start(mddev_t *mddev, struct bio *bi)
{
- DEFINE_WAIT(w);
if (bio_data_dir(bi) != WRITE)
return;
@@ -3533,7 +3616,7 @@ static void md_do_sync(mddev_t *mddev)
printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
" %d KB/sec/disc.\n", sysctl_speed_limit_min);
- printk(KERN_INFO "md: using maximum available idle IO bandwith "
+ printk(KERN_INFO "md: using maximum available idle IO bandwidth "
"(but not more than %d KB/sec) for reconstruction.\n",
sysctl_speed_limit_max);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 2d2ca7fa0265..286342375fb7 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -169,6 +169,11 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
mp_bh->master_bio = bio;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 2120710172c5..f6757259ce7f 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -404,6 +404,11 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
unsigned long chunk;
sector_t block, rsect;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
if (bio_data_dir(bio)==WRITE) {
disk_stat_inc(mddev->gendisk, writes);
disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 51d9645ed09c..a93ca478142a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -222,8 +222,17 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
{
struct bio *bio = r1_bio->master_bio;
- bio_endio(bio, bio->bi_size,
- test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+ /* if nobody has done the final endio yet, do it now */
+ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+ PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
+ (bio_data_dir(bio) == WRITE) ? "write" : "read",
+ (unsigned long long) bio->bi_sector,
+ (unsigned long long) bio->bi_sector +
+ (bio->bi_size >> 9) - 1);
+
+ bio_endio(bio, bio->bi_size,
+ test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+ }
free_r1bio(r1_bio);
}
@@ -292,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
- int mirror;
+ int mirror, behind;
conf_t *conf = mddev_to_conf(r1_bio->mddev);
if (bio->bi_size)
@@ -323,16 +332,46 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
update_head_pos(mirror, r1_bio);
+ behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
+ if (behind) {
+ if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+ atomic_dec(&r1_bio->behind_remaining);
+
+ /* In behind mode, we ACK the master bio once the I/O has safely
+ * reached all non-writemostly disks. Setting the Returned bit
+ * ensures that this gets done only once -- we don't ever want to
+ * return -EIO here, instead we'll wait */
+
+ if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+ test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+ /* Maybe we can return now */
+ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+ struct bio *mbio = r1_bio->master_bio;
+ PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+ (unsigned long long) mbio->bi_sector,
+ (unsigned long long) mbio->bi_sector +
+ (mbio->bi_size >> 9) - 1);
+ bio_endio(mbio, mbio->bi_size, 0);
+ }
+ }
+ }
/*
*
* Let's see if all mirrored write operations have finished
* already.
*/
if (atomic_dec_and_test(&r1_bio->remaining)) {
+ if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+ /* free extra copy of the data pages */
+ int i = bio->bi_vcnt;
+ while (i--)
+ __free_page(bio->bi_io_vec[i].bv_page);
+ }
/* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
r1_bio->sectors,
- !test_bit(R1BIO_Degraded, &r1_bio->state));
+ !test_bit(R1BIO_Degraded, &r1_bio->state),
+ behind);
md_write_end(r1_bio->mddev);
raid_end_bio_io(r1_bio);
}
@@ -360,13 +399,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
{
const unsigned long this_sector = r1_bio->sector;
int new_disk = conf->last_used, disk = new_disk;
+ int wonly_disk = -1;
const int sectors = r1_bio->sectors;
sector_t new_distance, current_distance;
- mdk_rdev_t *new_rdev, *rdev;
+ mdk_rdev_t *rdev;
rcu_read_lock();
/*
- * Check if it if we can balance. We can balance on the whole
+ * Check if we can balance. We can balance on the whole
* device if no resync is going on, or below the resync window.
* We take the first readable disk when above the resync window.
*/
@@ -376,11 +416,16 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* Choose the first operation device, for consistancy */
new_disk = 0;
- while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
- !new_rdev->in_sync) {
- new_disk++;
- if (new_disk == conf->raid_disks) {
- new_disk = -1;
+ for (rdev = conf->mirrors[new_disk].rdev;
+ !rdev || !rdev->in_sync
+ || test_bit(WriteMostly, &rdev->flags);
+ rdev = conf->mirrors[++new_disk].rdev) {
+
+ if (rdev && rdev->in_sync)
+ wonly_disk = new_disk;
+
+ if (new_disk == conf->raid_disks - 1) {
+ new_disk = wonly_disk;
break;
}
}
@@ -389,16 +434,26 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */
- while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
- !new_rdev->in_sync) {
+ for (rdev = conf->mirrors[new_disk].rdev;
+ !rdev || !rdev->in_sync ||
+ test_bit(WriteMostly, &rdev->flags);
+ rdev = conf->mirrors[new_disk].rdev) {
+
+ if (rdev && rdev->in_sync)
+ wonly_disk = new_disk;
+
if (new_disk <= 0)
new_disk = conf->raid_disks;
new_disk--;
if (new_disk == disk) {
- new_disk = -1;
- goto rb_out;
+ new_disk = wonly_disk;
+ break;
}
}
+
+ if (new_disk < 0)
+ goto rb_out;
+
disk = new_disk;
/* now disk == new_disk == starting point for search */
@@ -419,37 +474,41 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
disk = conf->raid_disks;
disk--;
- if ((rdev=conf->mirrors[disk].rdev) == NULL ||
- !rdev->in_sync)
+ rdev = conf->mirrors[disk].rdev;
+
+ if (!rdev ||
+ !rdev->in_sync ||
+ test_bit(WriteMostly, &rdev->flags))
continue;
if (!atomic_read(&rdev->nr_pending)) {
new_disk = disk;
- new_rdev = rdev;
break;
}
new_distance = abs(this_sector - conf->mirrors[disk].head_position);
if (new_distance < current_distance) {
current_distance = new_distance;
new_disk = disk;
- new_rdev = rdev;
}
} while (disk != conf->last_used);
-rb_out:
+ rb_out:
if (new_disk >= 0) {
- conf->next_seq_sect = this_sector + sectors;
- conf->last_used = new_disk;
- atomic_inc(&new_rdev->nr_pending);
- if (!new_rdev->in_sync) {
+ rdev = conf->mirrors[new_disk].rdev;
+ if (!rdev)
+ goto retry;
+ atomic_inc(&rdev->nr_pending);
+ if (!rdev->in_sync) {
/* cannot risk returning a device that failed
* before we inc'ed nr_pending
*/
- atomic_dec(&new_rdev->nr_pending);
+ atomic_dec(&rdev->nr_pending);
goto retry;
}
+ conf->next_seq_sect = this_sector + sectors;
+ conf->last_used = new_disk;
}
rcu_read_unlock();
@@ -542,6 +601,39 @@ static void device_barrier(conf_t *conf, sector_t sect)
spin_unlock_irq(&conf->resync_lock);
}
+/* duplicate the data pages for behind I/O */
+static struct page **alloc_behind_pages(struct bio *bio)
+{
+ int i;
+ struct bio_vec *bvec;
+ struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
+ GFP_NOIO);
+ if (unlikely(!pages))
+ goto do_sync_io;
+
+ memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
+
+ bio_for_each_segment(bvec, bio, i) {
+ pages[i] = alloc_page(GFP_NOIO);
+ if (unlikely(!pages[i]))
+ goto do_sync_io;
+ memcpy(kmap(pages[i]) + bvec->bv_offset,
+ kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
+ kunmap(pages[i]);
+ kunmap(bvec->bv_page);
+ }
+
+ return pages;
+
+do_sync_io:
+ if (pages)
+ for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
+ __free_page(pages[i]);
+ kfree(pages);
+ PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+ return NULL;
+}
+
static int make_request(request_queue_t *q, struct bio * bio)
{
mddev_t *mddev = q->queuedata;
@@ -554,7 +646,12 @@ static int make_request(request_queue_t *q, struct bio * bio)
struct bitmap *bitmap = mddev->bitmap;
unsigned long flags;
struct bio_list bl;
+ struct page **behind_pages = NULL;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
/*
* Register the new request and wait if the reconstruction
@@ -589,8 +686,6 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1_bio->mddev = mddev;
r1_bio->sector = bio->bi_sector;
- r1_bio->state = 0;
-
if (bio_data_dir(bio) == READ) {
/*
* read balancing logic:
@@ -651,13 +746,22 @@ static int make_request(request_queue_t *q, struct bio * bio)
}
rcu_read_unlock();
+ BUG_ON(targets == 0); /* we never fail the last device */
+
if (targets < conf->raid_disks) {
/* array is degraded, we will not clear the bitmap
* on I/O completion (see raid1_end_write_request) */
set_bit(R1BIO_Degraded, &r1_bio->state);
}
+ /* do behind I/O ? */
+ if (bitmap &&
+ atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind &&
+ (behind_pages = alloc_behind_pages(bio)) != NULL)
+ set_bit(R1BIO_BehindIO, &r1_bio->state);
+
atomic_set(&r1_bio->remaining, 0);
+ atomic_set(&r1_bio->behind_remaining, 0);
bio_list_init(&bl);
for (i = 0; i < disks; i++) {
@@ -674,12 +778,31 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_rw = WRITE;
mbio->bi_private = r1_bio;
+ if (behind_pages) {
+ struct bio_vec *bvec;
+ int j;
+
+ /* Yes, I really want the '__' version so that
+ * we clear any unused pointer in the io_vec, rather
+ * than leave them unchanged. This is important
+ * because when we come to free the pages, we won't
+ * know the originial bi_idx, so we just free
+ * them all
+ */
+ __bio_for_each_segment(bvec, mbio, j, 0)
+ bvec->bv_page = behind_pages[j];
+ if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags))
+ atomic_inc(&r1_bio->behind_remaining);
+ }
+
atomic_inc(&r1_bio->remaining);
bio_list_add(&bl, mbio);
}
+ kfree(behind_pages); /* the behind pages are attached to the bios now */
- bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+ bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
+ test_bit(R1BIO_BehindIO, &r1_bio->state));
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_merge(&conf->pending_bio_list, &bl);
bio_list_init(&bl);
@@ -1105,6 +1228,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t max_sector, nr_sectors;
int disk;
int i;
+ int wonly;
int write_targets = 0;
int sync_blocks;
int still_degraded = 0;
@@ -1160,14 +1284,21 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*/
disk = conf->last_used;
/* make sure disk is operational */
-
+ wonly = disk;
while (conf->mirrors[disk].rdev == NULL ||
- !conf->mirrors[disk].rdev->in_sync) {
+ !conf->mirrors[disk].rdev->in_sync ||
+ test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
+ ) {
+ if (conf->mirrors[disk].rdev &&
+ conf->mirrors[disk].rdev->in_sync)
+ wonly = disk;
if (disk <= 0)
disk = conf->raid_disks;
disk--;
- if (disk == conf->last_used)
+ if (disk == conf->last_used) {
+ disk = wonly;
break;
+ }
}
conf->last_used = disk;
atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
@@ -1439,6 +1570,17 @@ out:
static int stop(mddev_t *mddev)
{
conf_t *conf = mddev_to_conf(mddev);
+ struct bitmap *bitmap = mddev->bitmap;
+ int behind_wait = 0;
+
+ /* wait for behind writes to complete */
+ while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+ behind_wait++;
+ printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ); /* wait a second */
+ /* need to kick something here to make sure I/O goes? */
+ }
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
@@ -1561,6 +1703,35 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
return 0;
}
+static void raid1_quiesce(mddev_t *mddev, int state)
+{
+ conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1:
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+ conf->resync_lock, raid1_unplug(mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+ break;
+ case 0:
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ spin_unlock_irq(&conf->resync_lock);
+ wake_up(&conf->wait_resume);
+ wake_up(&conf->wait_idle);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
+
static mdk_personality_t raid1_personality =
{
@@ -1577,6 +1748,7 @@ static mdk_personality_t raid1_personality =
.sync_request = sync_request,
.resize = raid1_resize,
.reshape = raid1_reshape,
+ .quiesce = raid1_quiesce,
};
static int __init raid_init(void)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 62ebb1bc72be..5bd1e9ec899d 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -538,7 +538,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
}
- current_distance = abs(this_sector - conf->mirrors[disk].head_position);
+ current_distance = abs(r10_bio->devs[slot].addr -
+ conf->mirrors[disk].head_position);
/* Find the disk whose head is closest */
@@ -668,6 +669,11 @@ static int make_request(request_queue_t *q, struct bio * bio)
int i;
int chunk_sects = conf->chunk_mask + 1;
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
/* If this request crosses a chunk boundary, we need to
* split it. This will only happen for 1 PAGE (or less) requests.
*/
@@ -900,6 +906,27 @@ static void close_sync(conf_t *conf)
conf->r10buf_pool = NULL;
}
+/* check if there are enough drives for
+ * every block to appear on atleast one
+ */
+static int enough(conf_t *conf)
+{
+ int first = 0;
+
+ do {
+ int n = conf->copies;
+ int cnt = 0;
+ while (n--) {
+ if (conf->mirrors[first].rdev)
+ cnt++;
+ first = (first+1) % conf->raid_disks;
+ }
+ if (cnt == 0)
+ return 0;
+ } while (first != 0);
+ return 1;
+}
+
static int raid10_spare_active(mddev_t *mddev)
{
int i;
@@ -938,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
* very different from resync
*/
return 0;
+ if (!enough(conf))
+ return 0;
for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -1445,7 +1474,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
}
}
if (j == conf->copies) {
- BUG();
+ /* Cannot recover, so abort the recovery */
+ put_buf(r10_bio);
+ r10_bio = rb2;
+ if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery))
+ printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n",
+ mdname(mddev));
+ break;
}
}
if (biolist == NULL) {
@@ -1678,9 +1713,10 @@ static int run(mddev_t *mddev)
init_waitqueue_head(&conf->wait_idle);
init_waitqueue_head(&conf->wait_resume);
- if (!conf->working_disks) {
- printk(KERN_ERR "raid10: no operational mirrors for %s\n",
- mdname(mddev));
+ /* need to check that every block has at least one working mirror */
+ if (!enough(conf)) {
+ printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
+ mdname(mddev));
goto out_free_conf;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 43f231a467d5..4683ca24c046 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -24,6 +24,8 @@
#include <linux/bitops.h>
#include <asm/atomic.h>
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -79,8 +81,13 @@ static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -244,6 +251,9 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -803,6 +813,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
{
struct bio **bip;
raid5_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -811,9 +822,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -836,6 +849,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -958,12 +978,13 @@ static void handle_stripe(struct stripe_head *sh)
* need to be failed
*/
if (failed > 1 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -981,6 +1002,7 @@ static void handle_stripe(struct stripe_head *sh)
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1009,8 +1031,11 @@ static void handle_stripe(struct stripe_head *sh)
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 1 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1038,6 +1063,7 @@ static void handle_stripe(struct stripe_head *sh)
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
struct bio *wbi, *wbi2;
+ int bitmap_end = 0;
PRINTK("Return write for disc %d\n", i);
spin_lock_irq(&conf->device_lock);
wbi = dev->written;
@@ -1051,7 +1077,13 @@ static void handle_stripe(struct stripe_head *sh)
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1175,7 +1207,8 @@ static void handle_stripe(struct stripe_head *sh)
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && (rcw == 0 ||rmw == 0)) {
+ if (locked == 0 && (rcw == 0 ||rmw == 0) &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
PRINTK("Computing parity...\n");
compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
/* now every locked buffer is ready to be written */
@@ -1231,6 +1264,7 @@ static void handle_stripe(struct stripe_head *sh)
dev = &sh->dev[failed_num];
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantwrite, &dev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
locked++;
set_bit(STRIPE_INSYNC, &sh->state);
set_bit(R5_Syncio, &dev->flags);
@@ -1298,6 +1332,8 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1322,6 +1358,20 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
}
}
+static inline void activate_bit_delay(raid5_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -1354,8 +1404,10 @@ static void raid5_unplug_device(request_queue_t *q)
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid5_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1411,6 +1463,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ if (unlikely(bio_barrier(bi))) {
+ bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
md_write_start(mddev, bi);
if (bio_data_dir(bi)==WRITE) {
@@ -1488,10 +1545,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks-1;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there is 1 or more failed drives and we are trying
@@ -1503,6 +1570,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1520,6 +1594,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1553,6 +1628,13 @@ static void raid5d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1586,7 +1668,7 @@ static void raid5d (mddev_t *mddev)
PRINTK("--- raid5d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid5_conf_t *conf;
int raid_disk, memory;
@@ -1616,6 +1698,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1727,6 +1810,9 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
/* Ok, everything is just fine now */
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
@@ -1907,6 +1993,8 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -1936,6 +2024,35 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+static void raid5_quiesce(mddev_t *mddev, int state)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid5_personality=
{
.name = "raid5",
@@ -1950,6 +2067,7 @@ static mdk_personality_t raid5_personality=
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+ .quiesce = raid5_quiesce,
};
static int __init raid5_init (void)
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 495dee1d1e83..267eb1430c83 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -29,6 +29,8 @@
#include <asm/atomic.h>
#include "raid6.h"
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -98,8 +100,13 @@ static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -262,6 +269,9 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -906,6 +916,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
{
struct bio **bip;
raid6_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -914,9 +925,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -939,6 +952,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -1066,12 +1086,13 @@ static void handle_stripe(struct stripe_head *sh)
* need to be failed
*/
if (failed > 2 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -1089,6 +1110,7 @@ static void handle_stripe(struct stripe_head *sh)
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1117,8 +1139,11 @@ static void handle_stripe(struct stripe_head *sh)
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 2 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1155,6 +1180,7 @@ static void handle_stripe(struct stripe_head *sh)
if (!test_bit(R5_LOCKED, &dev->flags) &&
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
+ int bitmap_end = 0;
struct bio *wbi, *wbi2;
PRINTK("Return write for stripe %llu disc %d\n",
(unsigned long long)sh->sector, i);
@@ -1170,7 +1196,13 @@ static void handle_stripe(struct stripe_head *sh)
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1285,7 +1317,8 @@ static void handle_stripe(struct stripe_head *sh)
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && rcw == 0) {
+ if (locked == 0 && rcw == 0 &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
if ( must_compute > 0 ) {
/* We have failed blocks and need to compute them */
switch ( failed ) {
@@ -1388,6 +1421,7 @@ static void handle_stripe(struct stripe_head *sh)
bdev = &sh->dev[failed_num[1]];
locked += !test_bit(R5_LOCKED, &bdev->flags);
set_bit(R5_LOCKED, &bdev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
set_bit(R5_Wantwrite, &bdev->flags);
set_bit(STRIPE_INSYNC, &sh->state);
@@ -1457,6 +1491,8 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1481,6 +1517,20 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
}
}
+static inline void activate_bit_delay(raid6_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
@@ -1513,8 +1563,10 @@ static void raid6_unplug_device(request_queue_t *q)
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid6_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1570,6 +1622,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ if (unlikely(bio_barrier(bi))) {
+ bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
md_write_start(mddev, bi);
if (bio_data_dir(bi)==WRITE) {
@@ -1647,10 +1704,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks - 2;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there are 2 or more failed drives and we are trying
@@ -1662,6 +1729,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1679,6 +1753,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1712,6 +1787,13 @@ static void raid6d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1745,7 +1827,7 @@ static void raid6d (mddev_t *mddev)
PRINTK("--- raid6d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid6_conf_t *conf;
int raid_disk, memory;
@@ -1775,6 +1857,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1894,6 +1977,9 @@ static int run (mddev_t *mddev)
/* Ok, everything is just fine now */
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid6_unplug_device;
mddev->queue->issue_flush_fn = raid6_issue_flush;
return 0;
@@ -2071,6 +2157,8 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -2100,6 +2188,35 @@ static int raid6_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+static void raid6_quiesce(mddev_t *mddev, int state)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid6_personality=
{
.name = "raid6",
@@ -2114,6 +2231,7 @@ static mdk_personality_t raid6_personality=
.spare_active = raid6_spare_active,
.sync_request = sync_request,
.resize = raid6_resize,
+ .quiesce = raid6_quiesce,
};
static int __init raid6_init (void)
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 772d6112fb3b..c578a529e7a8 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -2,4 +2,7 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := video/ radio/ dvb/ common/
+obj-y := common/
+obj-$(CONFIG_VIDEO_DEV) += video/
+obj-$(CONFIG_VIDEO_DEV) += radio/
+obj-$(CONFIG_DVB) += dvb/
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index ab7a1fba4427..a0e700d7a4a4 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-common.c,v 1.11 2005/07/07 14:44:43 mchehab Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -335,6 +334,72 @@ int ir_dump_samples(u32 *samples, int count)
return 0;
}
+/* decode raw samples, pulse distance coding used by NEC remotes */
+int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
+{
+ int i,last,bit,len;
+ u32 curBit;
+ u32 value;
+
+ /* find start burst */
+ for (i = len = 0; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (bit) {
+ len++;
+ } else {
+ if (len >= 29)
+ break;
+ len = 0;
+ }
+ }
+
+ /* start burst to short */
+ if (len < 29)
+ return 0xffffffff;
+
+ /* find start silence */
+ for (len = 0; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (bit) {
+ break;
+ } else {
+ len++;
+ }
+ }
+
+ /* silence to short */
+ if (len < 7)
+ return 0xffffffff;
+
+ /* go decoding */
+ len = 0;
+ last = 1;
+ value = 0; curBit = 1;
+ for (; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (last) {
+ if(bit) {
+ continue;
+ } else {
+ len = 1;
+ }
+ } else {
+ if (bit) {
+ if (len > (low + high) /2)
+ value |= curBit;
+ curBit <<= 1;
+ if (curBit == 1)
+ break;
+ } else {
+ len++;
+ }
+ }
+ last = bit;
+ }
+
+ return value;
+}
+
/* decode raw samples, biphase coding, used by rc5 for example */
int ir_decode_biphase(u32 *samples, int count, int low, int high)
{
@@ -383,6 +448,7 @@ EXPORT_SYMBOL_GPL(ir_input_keydown);
EXPORT_SYMBOL_GPL(ir_extract_bits);
EXPORT_SYMBOL_GPL(ir_dump_samples);
EXPORT_SYMBOL_GPL(ir_decode_biphase);
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
/*
* Local variables:
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index cd5828b5e9e3..206cc2f61f26 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -168,10 +168,8 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
return;
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
pt->cpu = NULL;
- if (NULL != pt->slist) {
- kfree(pt->slist);
- pt->slist = NULL;
- }
+ kfree(pt->slist);
+ pt->slist = NULL;
}
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index c04fd11526e0..37888989ea2e 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -1,5 +1,4 @@
#include <media/saa7146_vv.h>
-#include <linux/version.h>
#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 781f23f0cbcc..fec6beab8c28 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -1,4 +1,3 @@
-#include <linux/version.h>
#include <media/saa7146_vv.h>
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
@@ -387,8 +386,6 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in
/* exported algorithm data */
static struct i2c_algorithm saa7146_algo = {
- .name = "saa7146 i2c algorithm",
- .id = I2C_ALGO_SAA7146,
.master_xfer = saa7146_i2c_xfer,
.functionality = saa7146_i2c_func,
};
@@ -404,15 +401,12 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- i2c_adapter->data = dev;
-#else
BUG_ON(!i2c_adapter->class);
i2c_set_adapdata(i2c_adapter,dev);
-#endif
+ i2c_adapter->dev.parent = &dev->pci->dev;
i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL;
- i2c_adapter->id = I2C_ALGO_SAA7146;
+ i2c_adapter->id = I2C_HW_SAA7146;
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
i2c_adapter->retries = SAA7146_I2C_RETRIES;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 0410cc96a48e..47e28b0ee951 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -164,12 +164,11 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
return 0;
}
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- struct flexcop_device *fc = fe->dvb->priv;
div = params->frequency / 125;
@@ -180,7 +179,7 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_fronten
if (params->frequency < 1500000) buf[3] |= 0x10;
- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -335,8 +334,103 @@ static struct mt312_config skystar23_samsung_tbdu18132_config = {
.pll_set = skystar23_samsung_tbdu18132_pll_set,
};
+
+static u8 alps_tdee4_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0xf8,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
+
static struct stv0297_config alps_tdee4_stv0297_config = {
.demod_address = 0x1c,
+ .inittab = alps_tdee4_stv0297_inittab,
// .invert = 1,
// .pll_set = alps_tdee4_stv0297_pll_set,
};
@@ -370,7 +464,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
} else
/* try the cable dvb (stv0297) */
- if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
+ if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_CABLE;
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
} else
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index be4266d4ae91..56495cb6cd02 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -172,8 +172,6 @@ static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm flexcop_algo = {
- .name = "FlexCop I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = flexcop_master_xfer,
.functionality = flexcop_i2c_func,
};
@@ -192,7 +190,6 @@ int flexcop_i2c_init(struct flexcop_device *fc)
fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
fc->i2c_adap.algo = &flexcop_algo;
fc->i2c_adap.algo_data = NULL;
- fc->i2c_adap.id = I2C_ALGO_BIT;
if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
return ret;
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index b12545f093f8..1e85d16491b0 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -1,5 +1,5 @@
config DVB_BT8XX
- tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards"
+ tristate "BT8xx based PCI cards"
depends on DVB_CORE && PCI && VIDEO_BT848
select DVB_MT352
select DVB_SP887X
@@ -8,8 +8,8 @@ config DVB_BT8XX
select DVB_OR51211
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
- the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
- pcHDTV HD2000 cards.
+ the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
+ the pcHDTV HD2000 cards, and certain AVerMedia cards.
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 3c5a8e273c4a..f29571450038 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -1,7 +1,7 @@
/*
* bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
*
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
*
* large parts based on the bttv driver
* Copyright (C) 1996,97,98 Ralph Metzler (rjkm@metzlerbros.de)
@@ -219,7 +219,7 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
controlreg &= ~0x1f;
controlreg |= 0x1b;
- btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START);
+ btwrite(bt->risc_dma, BT878_ARISC_START);
/* original int mask had :
* 6 2 8 4 0
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index 837623f7fcdf..a73baf00ca39 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -1,7 +1,7 @@
/*
bt878.h - Bt878 audio module (register offsets)
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.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
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 07a0b0a968a6..34a837a1abf4 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1,5 +1,4 @@
/*
-
Frontend/Card driver for TwinHan DST Frontend
Copyright (C) 2003 Jamie Honan
Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
@@ -19,7 +18,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -28,31 +26,45 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <asm/div64.h>
-
#include "dvb_frontend.h"
#include "dst_priv.h"
#include "dst_common.h"
-
static unsigned int verbose = 1;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
-
static unsigned int dst_addons;
module_param(dst_addons, int, 0644);
MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
-#define dprintk if (debug) printk
-
-#define HAS_LOCK 1
-#define ATTEMPT_TUNE 2
-#define HAS_POWER 4
-
-static void dst_packsize(struct dst_state* state, int psize)
+#define HAS_LOCK 1
+#define ATTEMPT_TUNE 2
+#define HAS_POWER 4
+
+#define DST_ERROR 0
+#define DST_NOTICE 1
+#define DST_INFO 2
+#define DST_DEBUG 3
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_ERROR) && (x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_INFO) && (x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ##arg); \
+ } \
+} while(0)
+
+
+static void dst_packsize(struct dst_state *state, int psize)
{
union dst_gpio_packet bits;
@@ -60,7 +72,7 @@ static void dst_packsize(struct dst_state* state, int psize)
bt878_device_control(state->bt, DST_IG_TS, &bits);
}
-int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay)
+int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay)
{
union dst_gpio_packet enb;
union dst_gpio_packet bits;
@@ -68,63 +80,55 @@ int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int
enb.enb.mask = mask;
enb.enb.enable = enbb;
- if (verbose > 4)
- dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", __FUNCTION__, mask, enbb, outhigh);
+ dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
- dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", __FUNCTION__, err, mask, enbb);
+ dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
return -EREMOTEIO;
}
udelay(1000);
/* because complete disabling means no output, no need to do output packet */
if (enbb == 0)
return 0;
-
if (delay)
msleep(10);
-
bits.outp.mask = enbb;
bits.outp.highvals = outhigh;
-
if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
- dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
+ dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
return -EREMOTEIO;
}
+
return 0;
}
EXPORT_SYMBOL(dst_gpio_outb);
-int dst_gpio_inb(struct dst_state *state, u8 * result)
+int dst_gpio_inb(struct dst_state *state, u8 *result)
{
union dst_gpio_packet rd_packet;
int err;
*result = 0;
-
if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
- dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
return -EREMOTEIO;
}
-
*result = (u8) rd_packet.rd.value;
+
return 0;
}
EXPORT_SYMBOL(dst_gpio_inb);
int rdc_reset_state(struct dst_state *state)
{
- if (verbose > 1)
- dprintk("%s: Resetting state machine\n", __FUNCTION__);
-
+ dprintk(verbose, DST_INFO, 1, "Resetting state machine");
if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
-
msleep(10);
-
if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
msleep(10);
return -1;
}
@@ -135,16 +139,14 @@ EXPORT_SYMBOL(rdc_reset_state);
int rdc_8820_reset(struct dst_state *state)
{
- if (verbose > 1)
- dprintk("%s: Resetting DST\n", __FUNCTION__);
-
+ dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
udelay(1000);
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
@@ -155,10 +157,11 @@ EXPORT_SYMBOL(rdc_8820_reset);
int dst_pio_enable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
udelay(1000);
+
return 0;
}
EXPORT_SYMBOL(dst_pio_enable);
@@ -166,7 +169,7 @@ EXPORT_SYMBOL(dst_pio_enable);
int dst_pio_disable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -183,19 +186,16 @@ int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
for (i = 0; i < 200; i++) {
if (dst_gpio_inb(state, &reply) < 0) {
- dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
return -1;
}
-
if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
- if (verbose > 4)
- dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
+ dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
return 1;
}
msleep(10);
}
- if (verbose > 1)
- dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+ dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
return 0;
}
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(dst_wait_dst_ready);
int dst_error_recovery(struct dst_state *state)
{
- dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
+ dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
dst_pio_disable(state);
msleep(10);
dst_pio_enable(state);
@@ -215,7 +215,7 @@ EXPORT_SYMBOL(dst_error_recovery);
int dst_error_bailout(struct dst_state *state)
{
- dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
rdc_8820_reset(state);
dst_pio_disable(state);
msleep(10);
@@ -224,17 +224,15 @@ int dst_error_bailout(struct dst_state *state)
}
EXPORT_SYMBOL(dst_error_bailout);
-
-int dst_comm_init(struct dst_state* state)
+int dst_comm_init(struct dst_state *state)
{
- if (verbose > 1)
- dprintk ("%s: Initializing DST..\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Initializing DST.");
if ((dst_pio_enable(state)) < 0) {
- dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
return -1;
}
if ((rdc_reset_state(state)) < 0) {
- dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -246,36 +244,33 @@ int dst_comm_init(struct dst_state* state)
}
EXPORT_SYMBOL(dst_comm_init);
-
int write_dst(struct dst_state *state, u8 *data, u8 len)
{
struct i2c_msg msg = {
- .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = data,
+ .len = len
};
int err;
- int cnt;
- if (debug && (verbose > 4)) {
- u8 i;
- if (verbose > 4) {
- dprintk("%s writing [ ", __FUNCTION__);
- for (i = 0; i < len; i++)
- dprintk("%02x ", data[i]);
- dprintk("]\n");
- }
- }
+ u8 cnt, i;
+
+ dprintk(verbose, DST_NOTICE, 0, "writing [ ");
+ for (i = 0; i < len; i++)
+ dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
+ dprintk(verbose, DST_NOTICE, 0, "]\n");
+
for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
- dprintk("%s: _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+ dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
dst_error_recovery(state);
continue;
} else
break;
}
-
if (cnt >= 2) {
- if (verbose > 1)
- printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
dst_error_bailout(state);
return -1;
@@ -285,36 +280,37 @@ int write_dst(struct dst_state *state, u8 *data, u8 len)
}
EXPORT_SYMBOL(write_dst);
-int read_dst(struct dst_state *state, u8 * ret, u8 len)
+int read_dst(struct dst_state *state, u8 *ret, u8 len)
{
- struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = ret,
+ .len = len
+ };
+
int err;
int cnt;
for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-
- dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
+ dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
dst_error_recovery(state);
-
continue;
} else
break;
}
if (cnt >= 2) {
- if (verbose > 1)
- printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
dst_error_bailout(state);
return -1;
}
- if (debug && (verbose > 4)) {
- dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
- for (err = 1; err < len; err++)
- dprintk(" 0x%x", ret[err]);
- if (err > 1)
- dprintk("\n");
- }
+ dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
+ for (err = 1; err < len; err++)
+ dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
+ if (err > 1)
+ dprintk(verbose, DST_DEBUG, 0, "\n");
return 0;
}
@@ -323,19 +319,16 @@ EXPORT_SYMBOL(read_dst);
static int dst_set_polarization(struct dst_state *state)
{
switch (state->voltage) {
- case SEC_VOLTAGE_13: // vertical
- printk("%s: Polarization=[Vertical]\n", __FUNCTION__);
- state->tx_tuna[8] &= ~0x40; //1
- break;
-
- case SEC_VOLTAGE_18: // horizontal
- printk("%s: Polarization=[Horizontal]\n", __FUNCTION__);
- state->tx_tuna[8] |= 0x40; // 0
- break;
-
- case SEC_VOLTAGE_OFF:
-
- break;
+ case SEC_VOLTAGE_13: /* Vertical */
+ dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
+ state->tx_tuna[8] &= ~0x40;
+ break;
+ case SEC_VOLTAGE_18: /* Horizontal */
+ dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
+ state->tx_tuna[8] |= 0x40;
+ break;
+ case SEC_VOLTAGE_OFF:
+ break;
}
return 0;
@@ -344,14 +337,12 @@ static int dst_set_polarization(struct dst_state *state)
static int dst_set_freq(struct dst_state *state, u32 freq)
{
state->frequency = freq;
- if (debug > 4)
- dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
+ dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
if (state->dst_type == DST_TYPE_IS_SAT) {
freq = freq / 1000;
if (freq < 950 || freq > 2150)
return -EINVAL;
-
state->tx_tuna[2] = (freq >> 8);
state->tx_tuna[3] = (u8) freq;
state->tx_tuna[4] = 0x01;
@@ -360,27 +351,25 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
if (freq < 1531)
state->tx_tuna[8] |= 0x04;
}
-
} else if (state->dst_type == DST_TYPE_IS_TERR) {
freq = freq / 1000;
if (freq < 137000 || freq > 858000)
return -EINVAL;
-
state->tx_tuna[2] = (freq >> 16) & 0xff;
state->tx_tuna[3] = (freq >> 8) & 0xff;
state->tx_tuna[4] = (u8) freq;
-
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ freq = freq / 1000;
state->tx_tuna[2] = (freq >> 16) & 0xff;
state->tx_tuna[3] = (freq >> 8) & 0xff;
state->tx_tuna[4] = (u8) freq;
-
} else
return -EINVAL;
+
return 0;
}
-static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
+static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
{
state->bandwidth = bandwidth;
@@ -388,103 +377,95 @@ static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
return 0;
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x06;
- else {
- state->tx_tuna[6] = 0x06;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- case BANDWIDTH_7_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x07;
- else {
- state->tx_tuna[6] = 0x07;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- case BANDWIDTH_8_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x08;
- else {
- state->tx_tuna[6] = 0x08;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- default:
- return -EINVAL;
+ case BANDWIDTH_6_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x06;
+ else {
+ state->tx_tuna[6] = 0x06;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ case BANDWIDTH_7_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x07;
+ else {
+ state->tx_tuna[6] = 0x07;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ case BANDWIDTH_8_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x08;
+ else {
+ state->tx_tuna[6] = 0x08;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ default:
+ return -EINVAL;
}
+
return 0;
}
-static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion)
+static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
{
state->inversion = inversion;
switch (inversion) {
- case INVERSION_OFF: // Inversion = Normal
- state->tx_tuna[8] &= ~0x80;
- break;
-
- case INVERSION_ON:
- state->tx_tuna[8] |= 0x80;
- break;
- default:
- return -EINVAL;
+ case INVERSION_OFF: /* Inversion = Normal */
+ state->tx_tuna[8] &= ~0x80;
+ break;
+ case INVERSION_ON:
+ state->tx_tuna[8] |= 0x80;
+ break;
+ default:
+ return -EINVAL;
}
+
return 0;
}
-static int dst_set_fec(struct dst_state* state, fe_code_rate_t fec)
+static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
{
state->fec = fec;
return 0;
}
-static fe_code_rate_t dst_get_fec(struct dst_state* state)
+static fe_code_rate_t dst_get_fec(struct dst_state *state)
{
return state->fec;
}
-static int dst_set_symbolrate(struct dst_state* state, u32 srate)
+static int dst_set_symbolrate(struct dst_state *state, u32 srate)
{
- u8 *val;
u32 symcalc;
u64 sval;
state->symbol_rate = srate;
-
if (state->dst_type == DST_TYPE_IS_TERR) {
return 0;
}
- if (debug > 4)
- dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
+ dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
srate /= 1000;
- val = &state->tx_tuna[0];
-
if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
sval = srate;
sval <<= 20;
do_div(sval, 88000);
symcalc = (u32) sval;
-
- if (debug > 4)
- dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
-
- val[5] = (u8) (symcalc >> 12);
- val[6] = (u8) (symcalc >> 4);
- val[7] = (u8) (symcalc << 4);
+ dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+ state->tx_tuna[5] = (u8) (symcalc >> 12);
+ state->tx_tuna[6] = (u8) (symcalc >> 4);
+ state->tx_tuna[7] = (u8) (symcalc << 4);
} else {
- val[5] = (u8) (srate >> 16) & 0x7f;
- val[6] = (u8) (srate >> 8);
- val[7] = (u8) srate;
+ state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+ state->tx_tuna[6] = (u8) (srate >> 8);
+ state->tx_tuna[7] = (u8) srate;
+ }
+ state->tx_tuna[8] &= ~0x20;
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+ if (srate > 8000)
+ state->tx_tuna[8] |= 0x20;
}
- val[8] &= ~0x20;
- if (srate > 8000)
- val[8] |= 0x20;
return 0;
}
@@ -496,32 +477,27 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
state->modulation = modulation;
switch (modulation) {
- case QAM_16:
- state->tx_tuna[8] = 0x10;
- break;
-
- case QAM_32:
- state->tx_tuna[8] = 0x20;
- break;
-
- case QAM_64:
- state->tx_tuna[8] = 0x40;
- break;
-
- case QAM_128:
- state->tx_tuna[8] = 0x80;
- break;
-
- case QAM_256:
- state->tx_tuna[8] = 0x00;
- break;
-
- case QPSK:
- case QAM_AUTO:
- case VSB_8:
- case VSB_16:
- default:
- return -EINVAL;
+ case QAM_16:
+ state->tx_tuna[8] = 0x10;
+ break;
+ case QAM_32:
+ state->tx_tuna[8] = 0x20;
+ break;
+ case QAM_64:
+ state->tx_tuna[8] = 0x40;
+ break;
+ case QAM_128:
+ state->tx_tuna[8] = 0x80;
+ break;
+ case QAM_256:
+ state->tx_tuna[8] = 0x00;
+ break;
+ case QPSK:
+ case QAM_AUTO:
+ case VSB_8:
+ case VSB_16:
+ default:
+ return -EINVAL;
}
@@ -534,7 +510,7 @@ static fe_modulation_t dst_get_modulation(struct dst_state *state)
}
-u8 dst_check_sum(u8 * buf, u32 len)
+u8 dst_check_sum(u8 *buf, u32 len)
{
u32 i;
u8 val = 0;
@@ -549,26 +525,24 @@ EXPORT_SYMBOL(dst_check_sum);
static void dst_type_flags_print(u32 type_flags)
{
- printk("DST type flags :");
+ dprintk(verbose, DST_ERROR, 0, "DST type flags :");
if (type_flags & DST_TYPE_HAS_NEWTUNE)
- printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
if (type_flags & DST_TYPE_HAS_TS204)
- printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
if (type_flags & DST_TYPE_HAS_SYMDIV)
- printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
if (type_flags & DST_TYPE_HAS_FW_1)
- printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
if (type_flags & DST_TYPE_HAS_FW_2)
- printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
if (type_flags & DST_TYPE_HAS_FW_3)
- printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
-// if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
-
- printk("\n");
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+ dprintk(verbose, DST_ERROR, 0, "\n");
}
-static int dst_type_print (u8 type)
+static int dst_type_print(u8 type)
{
char *otype;
switch (type) {
@@ -585,10 +559,10 @@ static int dst_type_print (u8 type)
break;
default:
- printk("%s: invalid dst type %d\n", __FUNCTION__, type);
+ dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
return -EINVAL;
}
- printk("DST type : %s\n", otype);
+ dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
return 0;
}
@@ -700,7 +674,7 @@ struct dst_types dst_tlist[] = {
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
- | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ | DST_TYPE_HAS_FW_2,
.dst_feature = DST_TYPE_HAS_CA
},
@@ -708,7 +682,7 @@ struct dst_types dst_tlist[] = {
.device_id = "DCTNEW",
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
- .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
+ .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
.dst_feature = 0
},
@@ -716,7 +690,7 @@ struct dst_types dst_tlist[] = {
.device_id = "DTT-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
.dst_feature = 0
},
@@ -756,6 +730,71 @@ struct dst_types dst_tlist[] = {
};
+static int dst_get_mac(struct dst_state *state)
+{
+ u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_mac[7] = dst_check_sum(get_mac, 7);
+ if (dst_command(state, get_mac, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->mac_address, '\0', 8);
+ memcpy(&state->mac_address, &state->rxbuffer, 6);
+ dprintk(verbose, DST_ERROR, 1, "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]",
+ state->mac_address[0], state->mac_address[1], state->mac_address[2],
+ state->mac_address[4], state->mac_address[5], state->mac_address[6]);
+
+ return 0;
+}
+
+static int dst_fw_ver(struct dst_state *state)
+{
+ u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_ver[7] = dst_check_sum(get_ver, 7);
+ if (dst_command(state, get_ver, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->fw_version, '\0', 8);
+ memcpy(&state->fw_version, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
+ state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
+ state->fw_version[1],
+ state->fw_version[5], state->fw_version[6],
+ state->fw_version[4], state->fw_version[3], state->fw_version[2]);
+
+ return 0;
+}
+
+static int dst_card_type(struct dst_state *state)
+{
+ u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_type[7] = dst_check_sum(get_type, 7);
+ if (dst_command(state, get_type, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->card_info, '\0', 8);
+ memcpy(&state->card_info, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+
+ return 0;
+}
+
+static int dst_get_vendor(struct dst_state *state)
+{
+ u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_vendor[7] = dst_check_sum(get_vendor, 7);
+ if (dst_command(state, get_vendor, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->vendor, '\0', 8);
+ memcpy(&state->vendor, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
+
+ return 0;
+}
static int dst_get_device_id(struct dst_state *state)
{
@@ -772,53 +811,45 @@ static int dst_get_device_id(struct dst_state *state)
if (write_dst(state, device_type, FIXED_COMM))
return -1; /* Write failed */
-
if ((dst_pio_disable(state)) < 0)
return -1;
-
if (read_dst(state, &reply, GET_ACK))
return -1; /* Read failure */
-
if (reply != ACK) {
- dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", __FUNCTION__, reply);
+ dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
return -1; /* Unack'd write */
}
-
if (!dst_wait_dst_ready(state, DEVICE_INIT))
return -1; /* DST not ready yet */
-
if (read_dst(state, state->rxbuffer, FIXED_COMM))
return -1;
dst_pio_disable(state);
-
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
- dprintk("%s: Checksum failure! \n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Checksum failure!");
return -1; /* Checksum failure */
}
-
state->rxbuffer[7] = '\0';
- for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, p_dst_type++) {
+ for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
use_type_flags = p_dst_type->type_flags;
use_dst_type = p_dst_type->dst_type;
/* Card capabilities */
state->dst_hw_cap = p_dst_type->dst_feature;
- printk ("%s: Recognise [%s]\n", __FUNCTION__, p_dst_type->device_id);
+ dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
break;
}
}
if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
- printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, &state->rxbuffer[0], &state->rxbuffer[1]);
- printk("%s: please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
+ dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
use_dst_type = DST_TYPE_IS_SAT;
use_type_flags = DST_TYPE_HAS_SYMDIV;
}
-
dst_type_print(use_dst_type);
state->type_flags = use_type_flags;
state->dst_type = use_dst_type;
@@ -834,7 +865,7 @@ static int dst_get_device_id(struct dst_state *state)
static int dst_probe(struct dst_state *state)
{
if ((rdc_8820_reset(state)) < 0) {
- dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
return -1;
}
if (dst_addons & DST_TYPE_HAS_CA)
@@ -843,80 +874,87 @@ static int dst_probe(struct dst_state *state)
msleep(100);
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
return -1;
}
msleep(100);
if (dst_get_device_id(state) < 0) {
- dprintk("%s: unknown device.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "unknown device.");
return -1;
}
+ if (dst_get_mac(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
+ return 0;
+ }
+ if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
+ if (dst_fw_ver(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
+ return 0;
+ }
+ if (dst_card_type(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
+ return 0;
+ }
+ if (dst_get_vendor(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
+ return 0;
+ }
+ }
return 0;
}
-int dst_command(struct dst_state* state, u8 * data, u8 len)
+int dst_command(struct dst_state *state, u8 *data, u8 len)
{
u8 reply;
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Communication Initialization Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
return -1;
}
-
if (write_dst(state, data, len)) {
- if (verbose > 1)
- dprintk("%s: Tring to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
return -1;
}
return -1;
}
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
-
if (read_dst(state, &reply, GET_ACK)) {
- if (verbose > 1)
- dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
return -1;
}
return -1;
}
-
if (reply != ACK) {
- dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+ dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
return -1;
}
if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
return 0;
-
-// udelay(3000);
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
else
udelay(2000);
-
if (!dst_wait_dst_ready(state, NO_DELAY))
return -1;
-
if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
- if (verbose > 1)
- dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Recovery failed.");
return -1;
}
return -1;
}
-
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
- dprintk("%s: checksum failure\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure");
return -1;
}
@@ -924,11 +962,11 @@ int dst_command(struct dst_state* state, u8 * data, u8 len)
}
EXPORT_SYMBOL(dst_command);
-static int dst_get_signal(struct dst_state* state)
+static int dst_get_signal(struct dst_state *state)
{
int retval;
u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
- dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+ //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
state->decode_lock = state->decode_strength = state->decode_snr = 0;
return 0;
@@ -955,13 +993,12 @@ static int dst_get_signal(struct dst_state* state)
return 0;
}
-static int dst_tone_power_cmd(struct dst_state* state)
+static int dst_tone_power_cmd(struct dst_state *state)
{
u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
if (state->dst_type == DST_TYPE_IS_TERR)
return 0;
-
paket[4] = state->tx_tuna[4];
paket[2] = state->tx_tuna[2];
paket[3] = state->tx_tuna[3];
@@ -971,61 +1008,53 @@ static int dst_tone_power_cmd(struct dst_state* state)
return 0;
}
-static int dst_get_tuna(struct dst_state* state)
+static int dst_get_tuna(struct dst_state *state)
{
int retval;
if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
return 0;
-
state->diseq_flags &= ~(HAS_LOCK);
if (!dst_wait_dst_ready(state, NO_DELAY))
return 0;
-
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+ if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
/* how to get variable length reply ???? */
retval = read_dst(state, state->rx_tuna, 10);
- } else {
+ else
retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
- }
-
if (retval < 0) {
- dprintk("%s: read not successful\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "read not successful");
return 0;
}
-
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
- dprintk("%s: checksum failure?\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
return 0;
}
} else {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
- dprintk("%s: checksum failure?\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure? ");
return 0;
}
}
if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
return 0;
state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
-
state->decode_lock = 1;
state->diseq_flags |= HAS_LOCK;
return 1;
}
-static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-static int dst_write_tuna(struct dvb_frontend* fe)
+static int dst_write_tuna(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
int retval;
u8 reply;
- if (debug > 4)
- dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
-
+ dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
state->decode_freq = 0;
state->decode_lock = state->decode_strength = state->decode_snr = 0;
if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1035,35 +1064,31 @@ static int dst_write_tuna(struct dvb_frontend* fe)
state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Communication initialization failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
return -1;
}
-
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
retval = write_dst(state, &state->tx_tuna[0], 10);
-
} else {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
}
if (retval < 0) {
dst_pio_disable(state);
- dprintk("%s: write not successful\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "write not successful");
return retval;
}
-
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
return -1;
}
-
if ((read_dst(state, &reply, GET_ACK) < 0)) {
- dprintk("%s: read verify not successful.\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
return -1;
}
if (reply != ACK) {
- dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+ dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
return 0;
}
state->diseq_flags |= ATTEMPT_TUNE;
@@ -1085,14 +1110,13 @@ static int dst_write_tuna(struct dvb_frontend* fe)
* Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
*/
-static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
-
if (cmd->msg_len == 0 || cmd->msg_len > 4)
return -EINVAL;
memcpy(&paket[3], cmd->msg, cmd->msg_len);
@@ -1101,65 +1125,61 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd*
return 0;
}
-static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
int need_cmd;
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
state->voltage = voltage;
-
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
need_cmd = 0;
- switch (voltage) {
- case SEC_VOLTAGE_13:
- case SEC_VOLTAGE_18:
- if ((state->diseq_flags & HAS_POWER) == 0)
- need_cmd = 1;
- state->diseq_flags |= HAS_POWER;
- state->tx_tuna[4] = 0x01;
- break;
- case SEC_VOLTAGE_OFF:
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ case SEC_VOLTAGE_18:
+ if ((state->diseq_flags & HAS_POWER) == 0)
need_cmd = 1;
- state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
- state->tx_tuna[4] = 0x00;
- break;
-
- default:
- return -EINVAL;
+ state->diseq_flags |= HAS_POWER;
+ state->tx_tuna[4] = 0x01;
+ break;
+ case SEC_VOLTAGE_OFF:
+ need_cmd = 1;
+ state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+ state->tx_tuna[4] = 0x00;
+ break;
+ default:
+ return -EINVAL;
}
+
if (need_cmd)
dst_tone_power_cmd(state);
return 0;
}
-static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
state->tone = tone;
-
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
switch (tone) {
- case SEC_TONE_OFF:
- if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
- state->tx_tuna[2] = 0x00;
- else
- state->tx_tuna[2] = 0xff;
-
- break;
-
- case SEC_TONE_ON:
- state->tx_tuna[2] = 0x02;
- break;
+ case SEC_TONE_OFF:
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+ state->tx_tuna[2] = 0x00;
+ else
+ state->tx_tuna[2] = 0xff;
+ break;
- default:
- return -EINVAL;
+ case SEC_TONE_ON:
+ state->tx_tuna[2] = 0x02;
+ break;
+ default:
+ return -EINVAL;
}
dst_tone_power_cmd(state);
@@ -1172,16 +1192,14 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
-
state->minicmd = minicmd;
-
switch (minicmd) {
- case SEC_MINI_A:
- state->tx_tuna[3] = 0x02;
- break;
- case SEC_MINI_B:
- state->tx_tuna[3] = 0xff;
- break;
+ case SEC_MINI_A:
+ state->tx_tuna[3] = 0x02;
+ break;
+ case SEC_MINI_B:
+ state->tx_tuna[3] = 0xff;
+ break;
}
dst_tone_power_cmd(state);
@@ -1189,42 +1207,37 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
}
-static int dst_init(struct dvb_frontend* fe)
+static int dst_init(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
- static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
- static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
- static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-// state->inversion = INVERSION_ON;
+ struct dst_state *state = fe->demodulator_priv;
+
+ static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
+ static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
+ static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+
state->inversion = INVERSION_OFF;
state->voltage = SEC_VOLTAGE_13;
state->tone = SEC_TONE_OFF;
- state->symbol_rate = 29473000;
- state->fec = FEC_AUTO;
state->diseq_flags = 0;
state->k22 = 0x02;
state->bandwidth = BANDWIDTH_7_MHZ;
state->cur_jiff = jiffies;
- if (state->dst_type == DST_TYPE_IS_SAT) {
- state->frequency = 950000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna));
- } else if (state->dst_type == DST_TYPE_IS_TERR) {
- state->frequency = 137000000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna));
- } else if (state->dst_type == DST_TYPE_IS_CABLE) {
- state->frequency = 51000000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna));
- }
+ if (state->dst_type == DST_TYPE_IS_SAT)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+ else if (state->dst_type == DST_TYPE_IS_TERR)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+ else if (state->dst_type == DST_TYPE_IS_CABLE)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
return 0;
}
-static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
*status = 0;
if (state->diseq_flags & HAS_LOCK) {
@@ -1236,9 +1249,9 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_get_signal(state);
*strength = state->decode_strength;
@@ -1246,9 +1259,9 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
return 0;
}
-static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
+static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_get_signal(state);
*snr = state->decode_snr;
@@ -1256,28 +1269,24 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
-static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_set_freq(state, p->frequency);
- if (verbose > 4)
- dprintk("Set Frequency=[%d]\n", p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
-// dst_set_inversion(state, p->inversion);
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
-
dst_set_fec(state, p->u.qpsk.fec_inner);
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
dst_set_polarization(state);
- if (verbose > 4)
- dprintk("Set Symbolrate=[%d]\n", p->u.qpsk.symbol_rate);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
- } else if (state->dst_type == DST_TYPE_IS_TERR) {
+ } else if (state->dst_type == DST_TYPE_IS_TERR)
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
- } else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ else if (state->dst_type == DST_TYPE_IS_CABLE) {
dst_set_fec(state, p->u.qam.fec_inner);
dst_set_symbolrate(state, p->u.qam.symbol_rate);
dst_set_modulation(state, p->u.qam.modulation);
@@ -1287,16 +1296,14 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
return 0;
}
-static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
p->frequency = state->decode_freq;
-// p->inversion = state->inversion;
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
p->inversion = state->inversion;
-
p->u.qpsk.symbol_rate = state->symbol_rate;
p->u.qpsk.fec_inner = dst_get_fec(state);
} else if (state->dst_type == DST_TYPE_IS_TERR) {
@@ -1304,16 +1311,15 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
p->u.qam.symbol_rate = state->symbol_rate;
p->u.qam.fec_inner = dst_get_fec(state);
-// p->u.qam.modulation = QAM_AUTO;
p->u.qam.modulation = dst_get_modulation(state);
}
return 0;
}
-static void dst_release(struct dvb_frontend* fe)
+static void dst_release(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
kfree(state);
}
@@ -1321,9 +1327,8 @@ static struct dvb_frontend_ops dst_dvbt_ops;
static struct dvb_frontend_ops dst_dvbs_ops;
static struct dvb_frontend_ops dst_dvbc_ops;
-struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
+struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
{
-
/* check if the ASIC is there */
if (dst_probe(state) < 0) {
if (state)
@@ -1336,17 +1341,14 @@ struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
case DST_TYPE_IS_TERR:
memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
break;
-
case DST_TYPE_IS_CABLE:
memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
break;
-
case DST_TYPE_IS_SAT:
memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
break;
-
default:
- printk("%s: unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
if (state)
kfree(state);
@@ -1374,12 +1376,9 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
@@ -1401,16 +1400,12 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
-
.diseqc_send_burst = dst_send_burst,
.diseqc_send_master_cmd = dst_set_diseqc,
.set_voltage = dst_set_voltage,
@@ -1432,18 +1427,14 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
};
-
MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
MODULE_AUTHOR("Jamie Honan, Manu Abraham");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index bfaacd5fc20f..6776a592045f 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -18,30 +18,42 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
-
#include <linux/dvb/ca.h>
#include "dvbdev.h"
#include "dvb_frontend.h"
-
#include "dst_ca.h"
#include "dst_common.h"
+#define DST_CA_ERROR 0
+#define DST_CA_NOTICE 1
+#define DST_CA_INFO 2
+#define DST_CA_DEBUG 3
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_CA_ERROR) && (x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_INFO) && (x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ## arg); \
+ } \
+} while(0)
+
+
static unsigned int verbose = 5;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
-
-#define dprintk if (debug) printk
-
/* Need some more work */
static int ca_set_slot_descr(void)
{
@@ -61,27 +73,20 @@ static int put_checksum(u8 *check_string, int length)
{
u8 i = 0, checksum = 0;
- if (verbose > 3) {
- dprintk("%s: ========================= Checksum calculation ===========================\n", __FUNCTION__);
- dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ========================= Checksum calculation ===========================");
+ dprintk(verbose, DST_CA_DEBUG, 1, " String Length=[0x%02x]", length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " String=[");
- dprintk("%s: String=[", __FUNCTION__);
- }
while (i < length) {
- if (verbose > 3)
- dprintk(" %02x", check_string[i]);
+ dprintk(verbose, DST_CA_DEBUG, 0, " %02x", check_string[i]);
checksum += check_string[i];
i++;
}
- if (verbose > 3) {
- dprintk(" ]\n");
- dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
- }
+ dprintk(verbose, DST_CA_DEBUG, 0, " ]\n");
+ dprintk(verbose, DST_CA_DEBUG, 1, "Sum=[%02x]\n", checksum);
check_string[length] = ~checksum + 1;
- if (verbose > 3) {
- dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, check_string[length]);
- dprintk("%s: ==========================================================================\n", __FUNCTION__);
- }
+ dprintk(verbose, DST_CA_DEBUG, 1, " Checksum=[%02x]", check_string[length]);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ==========================================================================");
return 0;
}
@@ -94,30 +99,26 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8
msleep(65);
if (write_dst(state, data, len)) {
- dprintk("%s: Write not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
-
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
return -1;
}
-
if (read_dst(state, &reply, GET_ACK) < 0) {
- dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
-
if (read) {
if (! dst_wait_dst_ready(state, LONG_DELAY)) {
- dprintk("%s: 8820 not ready\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
return -1;
}
-
if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
- dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
@@ -133,8 +134,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
while (dst_ca_comm_err < RETRIES) {
dst_comm_init(state);
- if (verbose > 2)
- dprintk("%s: Put Command\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
if (dst_ci_command(state, data, ca_string, len, read)) { // If error
dst_error_recovery(state);
dst_ca_comm_err++; // work required here.
@@ -153,18 +153,15 @@ static int ca_get_app_info(struct dst_state *state)
put_checksum(&command[0], command[0]);
if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1) {
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
-
- dprintk("%s: ================================ CI Module Application Info ======================================\n", __FUNCTION__);
- dprintk("%s: Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]\n",
- __FUNCTION__, state->messages[7], (state->messages[8] << 8) | state->messages[9],
- (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
- dprintk("%s: ==================================================================================================\n", __FUNCTION__);
- }
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+ dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+ dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+ state->messages[7], (state->messages[8] << 8) | state->messages[9],
+ (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+ dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
return 0;
}
@@ -177,31 +174,26 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
put_checksum(&slot_command[0], slot_command[0]);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1)
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
/* Will implement the rest soon */
- if (verbose > 1) {
- dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
- dprintk("===================================\n");
- for (i = 0; i < 8; i++)
- dprintk(" %d", slot_cap[i]);
- dprintk("\n");
- }
+ dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
+ dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
+ dprintk(verbose, DST_CA_INFO, 0, "\n");
p_ca_caps->slot_num = 1;
p_ca_caps->slot_type = 1;
p_ca_caps->descr_num = slot_cap[7];
p_ca_caps->descr_type = 1;
-
- if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) {
+ if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps)))
return -EFAULT;
- }
return 0;
}
@@ -222,46 +214,37 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s
put_checksum(&slot_command[0], 7);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1)
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
/* Will implement the rest soon */
- if (verbose > 1) {
- dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
- dprintk("===================================\n");
- for (i = 0; i < 8; i++)
- dprintk(" %d", slot_info[i]);
- dprintk("\n");
- }
+ dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
+ dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
+ dprintk(verbose, DST_CA_INFO, 0, "\n");
if (slot_info[4] & 0x80) {
p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
p_ca_slot_info->num = 1;
p_ca_slot_info->type = CA_CI;
- }
- else if (slot_info[4] & 0x40) {
+ } else if (slot_info[4] & 0x40) {
p_ca_slot_info->flags = CA_CI_MODULE_READY;
p_ca_slot_info->num = 1;
p_ca_slot_info->type = CA_CI;
- }
- else {
+ } else
p_ca_slot_info->flags = 0;
- }
- if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) {
+ if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
return -EFAULT;
- }
return 0;
}
-
-
static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
{
u8 i = 0;
@@ -270,24 +253,21 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
return -EFAULT;
-
if (p_ca_message->msg) {
- if (verbose > 3)
- dprintk("Message = [%02x %02x %02x]\n", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
for (i = 0; i < 3; i++) {
command = command | p_ca_message->msg[i];
if (i < 2)
command = command << 8;
}
- if (verbose > 3)
- dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
switch (command) {
- case CA_APP_INFO:
- memcpy(p_ca_message->msg, state->messages, 128);
- if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
- return -EFAULT;
+ case CA_APP_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
break;
}
}
@@ -298,10 +278,13 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
{
if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
- hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
- hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
- }
- else {
+ hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
+ hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
+ } else {
+ if (length > 247) {
+ dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
+ return -1;
+ }
hw_buffer->msg[0] = (length & 0xff) + 7;
hw_buffer->msg[1] = 0x40;
hw_buffer->msg[2] = 0x03;
@@ -309,6 +292,11 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
hw_buffer->msg[4] = 0x03;
hw_buffer->msg[5] = length & 0xff;
hw_buffer->msg[6] = 0x00;
+ /*
+ * Need to compute length for EN50221 section 8.3.2, for the time being
+ * assuming 8.3.2 is not applicable
+ */
+ memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
}
return 0;
}
@@ -317,13 +305,12 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
{
if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
- dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
- dprintk("%s: Resetting DST.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
+ dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
rdc_reset_state(state);
return -1;
}
- if (verbose > 2)
- dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
return 0;
}
@@ -334,130 +321,47 @@ u32 asn_1_decode(u8 *asn_1_array)
u32 length = 0;
length_field = asn_1_array[0];
- dprintk("%s: Length field=[%02x]\n", __FUNCTION__, length_field);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
if (length_field < 0x80) {
length = length_field & 0x7f;
- dprintk("%s: Length=[%02x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
} else {
word_count = length_field & 0x7f;
for (count = 0; count < word_count; count++) {
length = (length | asn_1_array[count + 1]) << 8;
- dprintk("%s: Length=[%04x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
}
}
return length;
}
-static int init_buffer(u8 *buffer, u32 length)
-{
- u32 i;
- for (i = 0; i < length; i++)
- buffer[i] = 0;
-
- return 0;
-}
-
static int debug_string(u8 *msg, u32 length, u32 offset)
{
u32 i;
- dprintk(" String=[ ");
+ dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
for (i = offset; i < length; i++)
- dprintk("%02x ", msg[i]);
- dprintk("]\n");
-
- return 0;
-}
-
-static int copy_string(u8 *destination, u8 *source, u32 dest_offset, u32 source_offset, u32 length)
-{
- u32 i;
- dprintk("%s: Copying [", __FUNCTION__);
- for (i = 0; i < length; i++) {
- destination[i + dest_offset] = source[i + source_offset];
- dprintk(" %02x", source[i + source_offset]);
- }
- dprintk("]\n");
-
- return i;
-}
-
-static int modify_4_bits(u8 *message, u32 pos)
-{
- message[pos] &= 0x0f;
+ dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
+ dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
return 0;
}
-
-
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
{
- u32 length = 0, count = 0;
- u8 asn_1_words, program_header_length;
- u16 program_info_length = 0, es_info_length = 0;
- u32 hw_offset = 0, buf_offset = 0, i;
- u8 dst_tag_length;
+ u32 length = 0;
+ u8 tag_length = 8;
length = asn_1_decode(&p_ca_message->msg[3]);
- dprintk("%s: CA Message length=[%d]\n", __FUNCTION__, length);
- dprintk("%s: ASN.1 ", __FUNCTION__);
- debug_string(&p_ca_message->msg[4], length, 0); // length does not include tag and length
+ dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
+ debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */
- init_buffer(hw_buffer->msg, length);
+ memset(hw_buffer->msg, '\0', length);
handle_dst_tag(state, p_ca_message, hw_buffer, length);
+ put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
- hw_offset = 7;
- asn_1_words = 1; // just a hack to test, should compute this one
- buf_offset = 3;
- program_header_length = 6;
- dst_tag_length = 7;
-
-// debug_twinhan_ca_params(state, p_ca_message, hw_buffer, reply, query, length, hw_offset, buf_offset);
-// dprintk("%s: Program Header(BUF)", __FUNCTION__);
-// debug_string(&p_ca_message->msg[4], program_header_length, 0);
-// dprintk("%s: Copying Program header\n", __FUNCTION__);
- copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + asn_1_words), program_header_length);
- buf_offset += program_header_length, hw_offset += program_header_length;
- modify_4_bits(hw_buffer->msg, (hw_offset - 2));
- if (state->type_flags & DST_TYPE_HAS_INC_COUNT) { // workaround
- dprintk("%s: Probably an ASIC bug !!!\n", __FUNCTION__);
- debug_string(hw_buffer->msg, (hw_offset + program_header_length), 0);
- hw_buffer->msg[hw_offset - 1] += 1;
- }
-
-// dprintk("%s: Program Header(HW), Count=[%d]", __FUNCTION__, count);
-// debug_string(hw_buffer->msg, hw_offset, 0);
-
- program_info_length = ((program_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
- dprintk("%s: Program info length=[%02x]\n", __FUNCTION__, program_info_length);
- if (program_info_length) {
- count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + 1), (program_info_length + 1) ); // copy next elem, not current
- buf_offset += count, hw_offset += count;
-// dprintk("%s: Program level ", __FUNCTION__);
-// debug_string(hw_buffer->msg, hw_offset, 0);
- }
-
- buf_offset += 1;// hw_offset += 1;
- for (i = buf_offset; i < length; i++) {
-// dprintk("%s: Stream Header ", __FUNCTION__);
- count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, buf_offset, 5);
- modify_4_bits(hw_buffer->msg, (hw_offset + 3));
-
- hw_offset += 5, buf_offset += 5, i += 4;
-// debug_string(hw_buffer->msg, hw_offset, (hw_offset - 5));
- es_info_length = ((es_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
- dprintk("%s: ES info length=[%02x]\n", __FUNCTION__, es_info_length);
- if (es_info_length) {
- // copy descriptors @ STREAM level
- dprintk("%s: Descriptors @ STREAM level...!!! \n", __FUNCTION__);
- }
-
- }
- hw_buffer->msg[length + dst_tag_length] = dst_check_sum(hw_buffer->msg, (length + dst_tag_length));
-// dprintk("%s: Total length=[%d], Checksum=[%02x]\n", __FUNCTION__, (length + dst_tag_length), hw_buffer->msg[length + dst_tag_length]);
- debug_string(hw_buffer->msg, (length + dst_tag_length + 1), 0); // dst tags also
- write_to_8820(state, hw_buffer, (length + dst_tag_length + 1), reply); // checksum
+ debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */
+ write_to_8820(state, hw_buffer, (length + tag_length), reply);
return 0;
}
@@ -471,26 +375,24 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message
/* Do test board */
/* Not there yet but soon */
-
/* CA PMT Reply capable */
if (ca_pmt_reply_test) {
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
- dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
return -1;
}
/* Process CA PMT Reply */
/* will implement soon */
- dprintk("%s: Not there yet\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
}
/* CA PMT Reply not capable */
if (!ca_pmt_reply_test) {
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
- dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
return -1;
}
- if (verbose > 3)
- dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
/* put a dummy message */
}
@@ -506,11 +408,10 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
struct ca_msg *hw_buffer;
if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
- if (verbose > 3)
- dprintk("%s\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ");
if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
return -EFAULT;
@@ -525,51 +426,35 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (i < 2)
command = command << 8;
}
- if (verbose > 3)
- dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
switch (command) {
- case CA_PMT:
- if (verbose > 3)
-// dprintk("Command = SEND_CA_PMT\n");
- dprintk("Command = SEND_CA_PMT\n");
-// if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
- if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
- dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_PMT Success !\n", __FUNCTION__);
-// retval = dummy_set_pmt(state, p_ca_message, hw_buffer, 0, 0);
-
- break;
-
- case CA_PMT_REPLY:
- if (verbose > 3)
- dprintk("Command = CA_PMT_REPLY\n");
- /* Have to handle the 2 basic types of cards here */
- if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
- dprintk("%s: -->CA_PMT_REPLY Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_PMT_REPLY Success !\n", __FUNCTION__);
-
- /* Certain boards do behave different ? */
-// retval = ca_set_pmt(state, p_ca_message, hw_buffer, 1, 1);
-
- case CA_APP_INFO_ENQUIRY: // only for debugging
- if (verbose > 3)
- dprintk("%s: Getting Cam Application information\n", __FUNCTION__);
-
- if ((ca_get_app_info(state)) < 0) {
- dprintk("%s: -->CA_APP_INFO_ENQUIRY Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
-
- break;
+ case CA_PMT:
+ dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
+ break;
+ case CA_PMT_REPLY:
+ dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
+ /* Have to handle the 2 basic types of cards here */
+ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
+ break;
+ case CA_APP_INFO_ENQUIRY: // only for debugging
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
+
+ if ((ca_get_app_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
+ break;
}
}
return 0;
@@ -584,121 +469,88 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct ca_msg *p_ca_message;
if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */
switch (cmd) {
- case CA_SEND_MSG:
- if (verbose > 1)
- dprintk("%s: Sending message\n", __FUNCTION__);
- if ((ca_send_message(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_SEND_MSG Failed !\n", __FUNCTION__);
- return -1;
- }
-
- break;
-
- case CA_GET_MSG:
- if (verbose > 1)
- dprintk("%s: Getting message\n", __FUNCTION__);
- if ((ca_get_message(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_GET_MSG Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_MSG Success !\n", __FUNCTION__);
-
- break;
-
- case CA_RESET:
- if (verbose > 1)
- dprintk("%s: Resetting DST\n", __FUNCTION__);
- dst_error_bailout(state);
- msleep(4000);
-
- break;
-
- case CA_GET_SLOT_INFO:
- if (verbose > 1)
- dprintk("%s: Getting Slot info\n", __FUNCTION__);
- if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
- dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", __FUNCTION__);
-
- break;
-
- case CA_GET_CAP:
- if (verbose > 1)
- dprintk("%s: Getting Slot capabilities\n", __FUNCTION__);
- if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
- dprintk("%s: -->CA_GET_CAP Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_CAP Success !\n", __FUNCTION__);
-
- break;
-
- case CA_GET_DESCR_INFO:
- if (verbose > 1)
- dprintk("%s: Getting descrambler description\n", __FUNCTION__);
- if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", __FUNCTION__);
-
- break;
-
- case CA_SET_DESCR:
- if (verbose > 1)
- dprintk("%s: Setting descrambler\n", __FUNCTION__);
- if ((ca_set_slot_descr()) < 0) {
- dprintk("%s: -->CA_SET_DESCR Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_SET_DESCR Success !\n", __FUNCTION__);
-
- break;
-
- case CA_SET_PID:
- if (verbose > 1)
- dprintk("%s: Setting PID\n", __FUNCTION__);
- if ((ca_set_pid()) < 0) {
- dprintk("%s: -->CA_SET_PID Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_SET_PID Success !\n", __FUNCTION__);
-
- default:
- return -EOPNOTSUPP;
- };
+ case CA_SEND_MSG:
+ dprintk(verbose, DST_CA_INFO, 1, " Sending message");
+ if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
+ return -1;
+ }
+ break;
+ case CA_GET_MSG:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting message");
+ if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
+ break;
+ case CA_RESET:
+ dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
+ dst_error_bailout(state);
+ msleep(4000);
+ break;
+ case CA_GET_SLOT_INFO:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
+ if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
+ break;
+ case CA_GET_CAP:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
+ if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
+ break;
+ case CA_GET_DESCR_INFO:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
+ if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
+ break;
+ case CA_SET_DESCR:
+ dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
+ if ((ca_set_slot_descr()) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
+ break;
+ case CA_SET_PID:
+ dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
+ if ((ca_set_pid()) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
+ default:
+ return -EOPNOTSUPP;
+ };
return 0;
}
static int dst_ca_open(struct inode *inode, struct file *file)
{
- if (verbose > 4)
- dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
try_module_get(THIS_MODULE);
return 0;
@@ -706,27 +558,24 @@ static int dst_ca_open(struct inode *inode, struct file *file)
static int dst_ca_release(struct inode *inode, struct file *file)
{
- if (verbose > 4)
- dprintk("%s:Device closed.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
module_put(THIS_MODULE);
return 0;
}
-static int dst_ca_read(struct file *file, char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
int bytes_read = 0;
- if (verbose > 4)
- dprintk("%s:Device read.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
return bytes_read;
}
-static int dst_ca_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
{
- if (verbose > 4)
- dprintk("%s:Device write.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
return 0;
}
@@ -751,8 +600,7 @@ static struct dvb_device dvbdev_ca = {
int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
{
struct dvb_device *dvbdev;
- if (verbose > 4)
- dprintk("%s:registering DST-CA device\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
return 0;
}
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index ef532a6aceaa..3281a6ca3685 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -61,7 +61,6 @@
#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
#define DST_TYPE_HAS_SESSION 128
-
#define RDC_8820_PIO_0_DISABLE 0
#define RDC_8820_PIO_0_ENABLE 1
#define RDC_8820_INT 2
@@ -114,6 +113,10 @@ struct dst_state {
fe_sec_mini_cmd_t minicmd;
fe_modulation_t modulation;
u8 messages[256];
+ u8 mac_address[8];
+ u8 fw_version[8];
+ u8 card_info[8];
+ u8 vendor[8];
};
struct dst_types {
@@ -124,15 +127,12 @@ struct dst_types {
u32 dst_feature;
};
-
-
struct dst_config
{
/* the ASIC i2c address */
u8 demod_address;
};
-
int rdc_reset_state(struct dst_state *state);
int rdc_8820_reset(struct dst_state *state);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 6f857c6091f3..c5c7672cd538 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -32,9 +32,7 @@
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
-
#include "dvb-bt8xx.h"
-
#include "bt878.h"
static int debug;
@@ -43,9 +41,11 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk( args... ) \
- do { \
+ do \
if (debug) printk(KERN_DEBUG args); \
- } while (0)
+ while (0)
+
+#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
static void dvb_bt8xx_task(unsigned long data)
{
@@ -119,14 +119,12 @@ static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci
unsigned int card_nr;
/* Hmm, n squared. Hope n is small */
- for (card_nr = 0; card_nr < bt878_num; card_nr++) {
+ for (card_nr = 0; card_nr < bt878_num; card_nr++)
if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
return &bt878[card_nr];
- }
return NULL;
}
-
static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
@@ -154,16 +152,21 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
unsigned char bs = 0;
unsigned char cp = 0;
- #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 542000000) cp = 0xb4;
- else if (params->frequency < 771000000) cp = 0xbc;
- else cp = 0xf4;
+ if (params->frequency < 542000000)
+ cp = 0xb4;
+ else if (params->frequency < 771000000)
+ cp = 0xbc;
+ else
+ cp = 0xf4;
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x08;
+ if (params->frequency == 0)
+ bs = 0x03;
+ else if (params->frequency < 443250000)
+ bs = 0x02;
+ else
+ bs = 0x08;
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
@@ -175,7 +178,6 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
}
static struct mt352_config thomson_dtt7579_config = {
-
.demod_address = 0x0f,
.demod_init = thomson_dtt7579_demod_init,
.pll_set = thomson_dtt7579_pll_set,
@@ -183,25 +185,26 @@ static struct mt352_config thomson_dtt7579_config = {
static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
- u32 freq = params->frequency;
-
- int i, a, n, pump;
- u32 band, pll;
+ u32 freq = params->frequency;
+ int i, a, n, pump;
+ u32 band, pll;
- u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
- 1576000,1718000,1856000,2036000,2150000};
- u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
- 0x00102000,0x00104000,0x00108000,0x00110000,
- 0x00120000,0x00140000};
+ u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
+ 1576000,1718000,1856000,2036000,2150000};
+ u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
+ 0x00102000,0x00104000,0x00108000,0x00110000,
+ 0x00120000,0x00140000};
-#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
+ #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
/* This is really the bit driving the tuner chip cx24108 */
- if(freq<950000) freq=950000; /* kHz */
- if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
+ if (freq<950000)
+ freq = 950000; /* kHz */
+ else if (freq>2150000)
+ freq = 2150000; /* satellite IF is 950..2150MHz */
/* decide which VCO to use for the input frequency */
for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
@@ -228,25 +231,22 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
cx24110_pll_write(fe,0x500c0000);
cx24110_pll_write(fe,0x83f1f800);
cx24110_pll_write(fe,pll);
-/* writereg(client,0x56,0x7f);*/
+ //writereg(client,0x56,0x7f);
return 0;
}
static int pinnsat_pll_init(struct dvb_frontend* fe)
{
- return 0;
+ return 0;
}
-
static struct cx24110_config pctvsat_config = {
-
.demod_address = 0x55,
.pll_init = pinnsat_pll_init,
.pll_set = cx24108_pll_set,
};
-
static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -258,15 +258,23 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
div = (36000000 + params->frequency + 83333) / 166666;
cfg = 0x88;
- if (params->frequency < 175000000) cpump = 2;
- else if (params->frequency < 390000000) cpump = 1;
- else if (params->frequency < 470000000) cpump = 2;
- else if (params->frequency < 750000000) cpump = 2;
- else cpump = 3;
+ if (params->frequency < 175000000)
+ cpump = 2;
+ else if (params->frequency < 390000000)
+ cpump = 1;
+ else if (params->frequency < 470000000)
+ cpump = 2;
+ else if (params->frequency < 750000000)
+ cpump = 2;
+ else
+ cpump = 3;
- if (params->frequency < 175000000) band_select = 0x0e;
- else if (params->frequency < 470000000) band_select = 0x05;
- else band_select = 0x03;
+ if (params->frequency < 175000000)
+ band_select = 0x0e;
+ else if (params->frequency < 470000000)
+ band_select = 0x05;
+ else
+ band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
@@ -285,14 +293,11 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
}
static struct sp887x_config microtune_mt7202dtf_config = {
-
.demod_address = 0x70,
.pll_set = microtune_mt7202dtf_pll_set,
.request_firmware = microtune_mt7202dtf_request_firmware,
};
-
-
static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
@@ -303,7 +308,6 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
udelay(2000);
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
@@ -323,28 +327,45 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
unsigned char bs = 0;
unsigned char cp = 0;
- #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 150000000) cp = 0xB4;
- else if (params->frequency < 173000000) cp = 0xBC;
- else if (params->frequency < 250000000) cp = 0xB4;
- else if (params->frequency < 400000000) cp = 0xBC;
- else if (params->frequency < 420000000) cp = 0xF4;
- else if (params->frequency < 470000000) cp = 0xFC;
- else if (params->frequency < 600000000) cp = 0xBC;
- else if (params->frequency < 730000000) cp = 0xF4;
- else cp = 0xFC;
-
- if (params->frequency < 150000000) bs = 0x01;
- else if (params->frequency < 173000000) bs = 0x01;
- else if (params->frequency < 250000000) bs = 0x02;
- else if (params->frequency < 400000000) bs = 0x02;
- else if (params->frequency < 420000000) bs = 0x02;
- else if (params->frequency < 470000000) bs = 0x02;
- else if (params->frequency < 600000000) bs = 0x08;
- else if (params->frequency < 730000000) bs = 0x08;
- else bs = 0x08;
+ if (params->frequency < 150000000)
+ cp = 0xB4;
+ else if (params->frequency < 173000000)
+ cp = 0xBC;
+ else if (params->frequency < 250000000)
+ cp = 0xB4;
+ else if (params->frequency < 400000000)
+ cp = 0xBC;
+ else if (params->frequency < 420000000)
+ cp = 0xF4;
+ else if (params->frequency < 470000000)
+ cp = 0xFC;
+ else if (params->frequency < 600000000)
+ cp = 0xBC;
+ else if (params->frequency < 730000000)
+ cp = 0xF4;
+ else
+ cp = 0xFC;
+
+ if (params->frequency < 150000000)
+ bs = 0x01;
+ else if (params->frequency < 173000000)
+ bs = 0x01;
+ else if (params->frequency < 250000000)
+ bs = 0x02;
+ else if (params->frequency < 400000000)
+ bs = 0x02;
+ else if (params->frequency < 420000000)
+ bs = 0x02;
+ else if (params->frequency < 470000000)
+ bs = 0x02;
+ else if (params->frequency < 600000000)
+ bs = 0x08;
+ else if (params->frequency < 730000000)
+ bs = 0x08;
+ else
+ bs = 0x08;
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
@@ -356,19 +377,15 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
}
static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
-
.demod_address = 0x0f,
.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
};
-
static struct dst_config dst_config = {
-
.demod_address = 0x55,
};
-
static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
{
struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
@@ -398,10 +415,8 @@ static void or51211_reset(struct dvb_frontend * fe)
*/
/* reset & PRM1,2&4 are outputs */
int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
- if (ret != 0) {
- printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR "
- "(%i)\n", ret);
- }
+ if (ret != 0)
+ printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000); /* Reset */
msleep(20);
/* Now set for normal operation */
@@ -417,7 +432,6 @@ static void or51211_sleep(struct dvb_frontend * fe)
}
static struct or51211_config or51211_config = {
-
.demod_address = 0x15,
.request_firmware = or51211_request_firmware,
.setmode = or51211_setmode,
@@ -425,7 +439,6 @@ static struct or51211_config or51211_config = {
.sleep = or51211_sleep,
};
-
static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -454,12 +467,84 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
}
static struct nxt6000_config vp3021_alps_tded4_config = {
-
.demod_address = 0x0a,
.clock_inversion = 1,
.pll_set = vp3021_alps_tded4_pll_set,
};
+static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
+{
+ static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
+ static u8 mt352_reset [] = { 0x50, 0x80 };
+ static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };
+ static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ udelay(2000);
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+ mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
+ mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+ return 0;
+}
+
+static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+{
+ u32 div;
+ struct dvb_ofdm_parameters *op = &params->u.ofdm;
+
+ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+ pllbuf[0] = 0xc2;
+ pllbuf[1] = (div >> 8) & 0x7F;
+ pllbuf[2] = div & 0xFF;
+ pllbuf[3] = 0x85;
+
+ dprintk("frequency %u, div %u\n", params->frequency, div);
+
+ if (params->frequency < 470000000)
+ pllbuf[4] = 0x02;
+ else if (params->frequency > 823000000)
+ pllbuf[4] = 0x88;
+ else
+ pllbuf[4] = 0x08;
+
+ if (op->bandwidth == 8)
+ pllbuf[4] |= 0x04;
+
+ return 0;
+}
+
+static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
+{
+ /*
+ * Reset the frontend, must be called before trying
+ * to initialise the MT352 or mt352_attach
+ * will fail.
+ *
+ * Presumably not required for the NXT6000 frontend.
+ *
+ */
+
+ int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
+ if (ret != 0)
+ printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
+
+ /* Pulse the reset line */
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low */
+ msleep(100);
+
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+}
+
+static struct mt352_config digitv_alps_tded4_config = {
+ .demod_address = 0x0a,
+ .demod_init = digitv_alps_tded4_demod_init,
+ .pll_set = digitv_alps_tded4_pll_set,
+};
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
{
@@ -473,7 +558,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
- break;
}
break;
#endif
@@ -483,17 +567,28 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
#else
case BTTV_NEBULA_DIGITV:
#endif
+ /*
+ * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
+ * this would be a cleaner solution than trying each frontend in turn.
+ */
+
+ /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
if (card->fe != NULL) {
+ dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
break;
}
+
+ /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
+ digitv_alps_tded4_reset(card);
+ card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+
+ if (card->fe != NULL)
+ dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
break;
case BTTV_AVDVBT_761:
card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_AVDVBT_771:
@@ -501,7 +596,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
- break;
}
break;
@@ -522,54 +616,41 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
/* Attach other DST peripherals if any */
/* Conditional Access device */
- if (state->dst_hw_cap & DST_TYPE_HAS_CA) {
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
ret = dst_ca_attach(state, &card->dvb_adapter);
- }
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_PINNACLESAT:
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_PC_HDTV:
card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
}
- if (card->fe == NULL) {
+ if (card->fe == NULL)
printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
card->bt->dev->vendor,
card->bt->dev->device,
card->bt->dev->subsystem_vendor,
card->bt->dev->subsystem_device);
- } else {
+ else
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
printk("dvb-bt8xx: Frontend registration failed!\n");
if (card->fe->ops->release)
card->fe->ops->release(card->fe);
card->fe = NULL;
}
- }
}
static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
- THIS_MODULE)) < 0) {
+ if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
-
}
card->dvb_adapter.priv = card;
@@ -664,8 +745,7 @@ static int dvb_bt8xx_probe(struct device *dev)
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
card->i2c_adapter = &sub->core->i2c_adap;
- switch(sub->core->type)
- {
+ switch(sub->core->type) {
case BTTV_PINNACLESAT:
card->gpio_mode = 0x0400c060;
/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
@@ -751,7 +831,6 @@ static int dvb_bt8xx_probe(struct device *dev)
kfree(card);
return -EFAULT;
-
}
init_MUTEX(&card->bt->gpio_lock);
@@ -779,7 +858,8 @@ static int dvb_bt8xx_remove(struct device *dev)
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
- if (card->fe) dvb_unregister_frontend(card->fe);
+ if (card->fe)
+ dvb_unregister_frontend(card->fe);
dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 2923b3b0dd3c..9ec8e5bd6c1f 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -2,7 +2,7 @@
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
* Copyright (C) 1999-2001 Ralph Metzler & Marcus Metzler for convergence integrated media GmbH
* Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
*
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 226714085f58..7cf4c4a888ec 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
config DVB_CINERGYT2_RC_QUERY_INTERVAL
int "Infrared Remote Controller update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
- default "100"
+ default "50"
help
If you have a very fast-repeating remote control you can try lower
values, for normal consumer receivers the default value should be
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 7d8b3cad350b..6db0929ef53d 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -25,7 +25,6 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/pci.h>
@@ -36,7 +35,6 @@
#include "dvb_demux.h"
#include "dvb_net.h"
-
#ifdef CONFIG_DVB_CINERGYT2_TUNING
#define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
#define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
@@ -49,7 +47,7 @@
#define STREAM_URB_COUNT (32)
#define STREAM_BUF_SIZE (512) /* bytes */
#define ENABLE_RC (1)
- #define RC_QUERY_INTERVAL (100) /* milliseconds */
+ #define RC_QUERY_INTERVAL (50) /* milliseconds */
#define QUERY_INTERVAL (333) /* milliseconds */
#endif
@@ -142,6 +140,8 @@ struct cinergyt2 {
struct input_dev rc_input_dev;
struct work_struct rc_query_work;
int rc_input_event;
+ u32 rc_last_code;
+ unsigned long last_event_jiffies;
#endif
};
@@ -156,7 +156,7 @@ struct cinergyt2_rc_event {
uint32_t value;
} __attribute__((packed));
-static const uint32_t rc_keys [] = {
+static const uint32_t rc_keys[] = {
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
@@ -685,52 +685,68 @@ static struct dvb_device cinergyt2_fe_template = {
#ifdef ENABLE_RC
static void cinergyt2_query_rc (void *data)
{
- struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
- char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS };
+ struct cinergyt2 *cinergyt2 = data;
+ char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
struct cinergyt2_rc_event rc_events[12];
- int n, len;
+ int n, len, i;
if (down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
- (char *) rc_events, sizeof(rc_events));
-
- for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
- int i;
+ (char *) rc_events, sizeof(rc_events));
+ if (len < 0)
+ goto out;
+ if (len == 0) {
+ if (time_after(jiffies, cinergyt2->last_event_jiffies +
+ msecs_to_jiffies(150))) {
+ /* stop key repeat */
+ if (cinergyt2->rc_input_event != KEY_MAX) {
+ dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
+ input_report_key(&cinergyt2->rc_input_dev,
+ cinergyt2->rc_input_event, 0);
+ cinergyt2->rc_input_event = KEY_MAX;
+ }
+ cinergyt2->rc_last_code = ~0;
+ }
+ goto out;
+ }
+ cinergyt2->last_event_jiffies = jiffies;
-/* dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/
+ for (n = 0; n < (len / sizeof(rc_events[0])); n++) {
+ dprintk(1, "rc_events[%d].value = %x, type=%x\n",
+ n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
- rc_events[n].value == ~0)
- {
- /**
- * keyrepeat bit. If we would handle this properly
- * we would need to emit down events as long the
- * keyrepeat goes, a up event if no further
- * repeat bits occur. Would need a timer to implement
- * and no other driver does this, so we simply
- * emit the last key up/down sequence again.
- */
+ rc_events[n].value == ~0) {
+ /* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
- for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) {
- if (rc_keys[i+0] == rc_events[n].type &&
- rc_keys[i+1] == le32_to_cpu(rc_events[n].value))
- {
- cinergyt2->rc_input_event = rc_keys[i+2];
+ for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
+ if (rc_keys[i + 0] == rc_events[n].type &&
+ rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
+ cinergyt2->rc_input_event = rc_keys[i + 2];
break;
}
}
}
if (cinergyt2->rc_input_event != KEY_MAX) {
- input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
- input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
- input_sync(&cinergyt2->rc_input_dev);
+ if (rc_events[n].value == cinergyt2->rc_last_code &&
+ cinergyt2->rc_last_code != ~0) {
+ /* emit a key-up so the double event is recognized */
+ dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
+ input_report_key(&cinergyt2->rc_input_dev,
+ cinergyt2->rc_input_event, 0);
+ }
+ dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
+ input_report_key(&cinergyt2->rc_input_dev,
+ cinergyt2->rc_input_event, 1);
+ cinergyt2->rc_last_code = rc_events[n].value;
}
}
+out:
schedule_delayed_work(&cinergyt2->rc_query_work,
msecs_to_jiffies(RC_QUERY_INTERVAL));
@@ -772,7 +788,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
const struct usb_device_id *id)
{
struct cinergyt2 *cinergyt2;
- int i, err;
+ int err;
+#ifdef ENABLE_RC
+ int i;
+#endif
if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
dprintk(1, "out of memory?!?\n");
@@ -828,19 +847,18 @@ static int cinergyt2_probe (struct usb_interface *intf,
DVB_DEVICE_FRONTEND);
#ifdef ENABLE_RC
- init_input_dev(&cinergyt2->rc_input_dev);
-
- cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
- cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
- cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
+ cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ cinergyt2->rc_input_dev.keycodesize = 0;
+ cinergyt2->rc_input_dev.keycodemax = 0;
cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
- for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3)
- set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit);
+ for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
+ set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
input_register_device(&cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
+ cinergyt2->rc_last_code = ~0;
INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
@@ -888,7 +906,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
- if (state > 0) { /* state 0 seems to mean DEVICE_PM_ON */
+ if (state.event > PM_EVENT_ON) {
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
#ifdef ENABLE_RC
cancel_delayed_work(&cinergyt2->rc_query_work);
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fb55eaa5c8e7..9719a3b30f78 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -30,6 +30,7 @@
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/time.h>
+#include <linux/dvb/dmx.h>
/*--------------------------------------------------------------------------*/
/* Common definitions */
@@ -124,9 +125,7 @@ struct dmx_ts_feed {
u16 pid,
int type,
enum dmx_ts_pes pes_type,
- size_t callback_length,
size_t circular_buffer_size,
- int descramble,
struct timespec timeout);
int (*start_filtering) (struct dmx_ts_feed* feed);
int (*stop_filtering) (struct dmx_ts_feed* feed);
@@ -159,7 +158,6 @@ struct dmx_section_feed {
int (*set) (struct dmx_section_feed* feed,
u16 pid,
size_t circular_buffer_size,
- int descramble,
int check_crc);
int (*allocate_filter) (struct dmx_section_feed* feed,
struct dmx_section_filter** filter);
@@ -207,7 +205,6 @@ struct dmx_frontend {
struct list_head connectivity_list; /* List of front-ends that can
be connected to a particular
demux */
- void* priv; /* Pointer to private data of the API client */
enum dmx_frontend_source source;
};
@@ -225,8 +222,6 @@ struct dmx_frontend {
#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
#define DMX_CRC_CHECKING 16
#define DMX_TS_DESCRAMBLING 32
-#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64
-#define DMX_MAC_ADDRESS_DESCRAMBLING 128
/*
* Demux resource type identifier.
@@ -244,9 +239,7 @@ struct dmx_frontend {
struct dmx_demux {
u32 capabilities; /* Bitfield of capability flags */
struct dmx_frontend* frontend; /* Front-end connected to the demux */
- struct list_head reg_list; /* List of registered demuxes */
void* priv; /* Pointer to private data of the API client */
- int users; /* Number of users */
int (*open) (struct dmx_demux* demux);
int (*close) (struct dmx_demux* demux);
int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
@@ -260,17 +253,6 @@ struct dmx_demux {
dmx_section_cb callback);
int (*release_section_feed) (struct dmx_demux* demux,
struct dmx_section_feed* feed);
- int (*descramble_mac_address) (struct dmx_demux* demux,
- u8* buffer1,
- size_t buffer1_length,
- u8* buffer2,
- size_t buffer2_length,
- u16 pid);
- int (*descramble_section_payload) (struct dmx_demux* demux,
- u8* buffer1,
- size_t buffer1_length,
- u8* buffer2, size_t buffer2_length,
- u16 pid);
int (*add_frontend) (struct dmx_demux* demux,
struct dmx_frontend* frontend);
int (*remove_frontend) (struct dmx_demux* demux,
@@ -282,20 +264,12 @@ struct dmx_demux {
int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
+ int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
+
+ int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
+
int (*get_stc) (struct dmx_demux* demux, unsigned int num,
u64 *stc, unsigned int *base);
};
-/*--------------------------------------------------------------------------*/
-/* Demux directory */
-/*--------------------------------------------------------------------------*/
-
-/*
- * DMX_DIR_ENTRY(): Casts elements in the list of registered
- * demuxes from the generic type struct list_head* to the type struct dmx_demux
- *.
- */
-
-#define DMX_DIR_ENTRY(list) list_entry(list, struct dmx_demux, reg_list)
-
#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 68050cd527cb..8028c3a5e287 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -571,7 +571,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
return ret;
}
- ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0,
+ ret=(*secfeed)->set(*secfeed, para->pid, 32768,
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
if (ret<0) {
@@ -654,7 +654,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
(*tsfeed)->priv = (void *) filter;
ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
- 188, 32768, 0, timeout);
+ 32768, timeout);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed);
@@ -929,6 +929,22 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg);
break;
+ case DMX_GET_CAPS:
+ if (!dmxdev->demux->get_caps) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
+ break;
+
+ case DMX_SET_SOURCE:
+ if (!dmxdev->demux->set_source) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = dmxdev->demux->set_source(dmxdev->demux, parg);
+ break;
+
case DMX_GET_STC:
if (!dmxdev->demux->get_stc) {
ret=-EINVAL;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 0eb9aa711fb0..88757e2634e5 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -47,7 +47,7 @@ MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
#define dprintk if (dvb_ca_en50221_debug) printk
-#define INIT_TIMEOUT_SECS 5
+#define INIT_TIMEOUT_SECS 10
#define HOST_LINK_BUF_SIZE 0x200
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index ac9889d22288..dc476dda2b71 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -38,82 +38,52 @@
*/
// #define DVB_DEMUX_SECTION_LOSS_LOG
-
-static LIST_HEAD(dmx_muxs);
-
-
-static int dmx_register_demux(struct dmx_demux *demux)
-{
- demux->users = 0;
- list_add(&demux->reg_list, &dmx_muxs);
- return 0;
-}
-
-static int dmx_unregister_demux(struct dmx_demux* demux)
-{
- struct list_head *pos, *n, *head=&dmx_muxs;
-
- list_for_each_safe (pos, n, head) {
- if (DMX_DIR_ENTRY(pos) == demux) {
- if (demux->users>0)
- return -EINVAL;
- list_del(pos);
- return 0;
- }
- }
-
- return -ENODEV;
-}
-
-
/******************************************************************************
* static inlined helper functions
******************************************************************************/
-
static inline u16 section_length(const u8 *buf)
{
- return 3+((buf[1]&0x0f)<<8)+buf[2];
+ return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
}
-
static inline u16 ts_pid(const u8 *buf)
{
- return ((buf[1]&0x1f)<<8)+buf[2];
+ return ((buf[1] & 0x1f) << 8) + buf[2];
}
-
static inline u8 payload(const u8 *tsp)
{
- if (!(tsp[3] & 0x10)) // no payload?
+ if (!(tsp[3] & 0x10)) // no payload?
return 0;
- if (tsp[3] & 0x20) { // adaptation field?
- if (tsp[4] > 183) // corrupted data?
+
+ if (tsp[3] & 0x20) { // adaptation field?
+ if (tsp[4] > 183) // corrupted data?
return 0;
else
- return 184-1-tsp[4];
+ return 184 - 1 - tsp[4];
}
+
return 184;
}
-
-static u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len)
+static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len)
{
- return (f->feed.sec.crc_val = crc32_be (f->feed.sec.crc_val, src, len));
+ return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len));
}
-
-static void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_t len)
+static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s,
+ size_t len)
{
- memcpy (d, s, len);
+ memcpy(d, s, len);
}
-
/******************************************************************************
* Software filter functions
******************************************************************************/
-static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf)
+static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
int count = payload(buf);
int p;
@@ -123,32 +93,31 @@ static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u
if (count == 0)
return -1;
- p = 188-count;
+ p = 188 - count;
/*
- cc=buf[3]&0x0f;
- ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
- dvbdmxfeed->cc=cc;
+ cc = buf[3] & 0x0f;
+ ccok = ((feed->cc + 1) & 0x0f) == cc;
+ feed->cc = cc;
if (!ccok)
printk("missed packet!\n");
*/
- if (buf[1] & 0x40) // PUSI ?
+ if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa;
feed->peslen += count;
- return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+ return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
}
-
-static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
- struct dvb_demux_filter *f)
+static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
+ struct dvb_demux_filter *f)
{
u8 neq = 0;
int i;
- for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
if (f->maskandmode[i] & xor)
@@ -160,12 +129,11 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
if (f->doneq && !neq)
return 0;
- return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
- NULL, 0, &f->filter, DMX_OK);
+ return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
+ NULL, 0, &f->filter, DMX_OK);
}
-
-static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
+static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct dvb_demux_filter *f = feed->filter;
@@ -195,26 +163,24 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
return 0;
}
-
static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
{
struct dmx_section_feed *sec = &feed->feed.sec;
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- if(sec->secbufp < sec->tsfeedp)
- {
+ if (sec->secbufp < sec->tsfeedp) {
int i, n = sec->tsfeedp - sec->secbufp;
- /* section padding is done with 0xff bytes entirely.
- ** due to speed reasons, we won't check all of them
- ** but just first and last
- */
- if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff)
- {
+ /*
+ * Section padding is done with 0xff bytes entirely.
+ * Due to speed reasons, we won't check all of them
+ * but just first and last.
+ */
+ if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
printk("dvb_demux.c section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
printk("dvb_demux.c pad data:");
- for(i = 0; i < n; i++)
+ for (i = 0; i < n; i++)
printk(" %02x", sec->secbuf[i]);
printk("\n");
}
@@ -226,82 +192,81 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
}
/*
-** Losless Section Demux 1.4.1 by Emard
-** Valsecchi Patrick:
-** - middle of section A (no PUSI)
-** - end of section A and start of section B
-** (with PUSI pointing to the start of the second section)
-**
-** In this case, without feed->pusi_seen you'll receive a garbage section
-** consisting of the end of section A. Basically because tsfeedp
-** is incemented and the use=0 condition is not raised
-** when the second packet arrives.
-**
-** Fix:
-** when demux is started, let feed->pusi_seen = 0 to
-** prevent initial feeding of garbage from the end of
-** previous section. When you for the first time see PUSI=1
-** then set feed->pusi_seen = 1
-*/
-static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+ * Losless Section Demux 1.4.1 by Emard
+ * Valsecchi Patrick:
+ * - middle of section A (no PUSI)
+ * - end of section A and start of section B
+ * (with PUSI pointing to the start of the second section)
+ *
+ * In this case, without feed->pusi_seen you'll receive a garbage section
+ * consisting of the end of section A. Basically because tsfeedp
+ * is incemented and the use=0 condition is not raised
+ * when the second packet arrives.
+ *
+ * Fix:
+ * when demux is started, let feed->pusi_seen = 0 to
+ * prevent initial feeding of garbage from the end of
+ * previous section. When you for the first time see PUSI=1
+ * then set feed->pusi_seen = 1
+ */
+static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
+ const u8 *buf, u8 len)
{
struct dvb_demux *demux = feed->demux;
struct dmx_section_feed *sec = &feed->feed.sec;
u16 limit, seclen, n;
- if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
+ if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0;
- if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE)
- {
+ if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
printk("dvb_demux.c section buffer full loss: %d/%d\n",
- sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE);
+ sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
+ DMX_MAX_SECFEED_SIZE);
#endif
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
}
- if(len <= 0)
+ if (len <= 0)
return 0;
demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
sec->tsfeedp += len;
- /* -----------------------------------------------------
- ** Dump all the sections we can find in the data (Emard)
- */
-
+ /*
+ * Dump all the sections we can find in the data (Emard)
+ */
limit = sec->tsfeedp;
- if(limit > DMX_MAX_SECFEED_SIZE)
- return -1; /* internal error should never happen */
+ if (limit > DMX_MAX_SECFEED_SIZE)
+ return -1; /* internal error should never happen */
/* to be sure always set secbuf */
sec->secbuf = sec->secbuf_base + sec->secbufp;
- for(n = 0; sec->secbufp + 2 < limit; n++)
- {
+ for (n = 0; sec->secbufp + 2 < limit; n++) {
seclen = section_length(sec->secbuf);
- if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
- || seclen + sec->secbufp > limit)
+ if (seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
+ || seclen + sec->secbufp > limit)
return 0;
sec->seclen = seclen;
sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */
- if(feed->pusi_seen)
+ if (feed->pusi_seen)
dvb_dmx_swfilter_section_feed(feed);
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
else
printk("dvb_demux.c pusi not seen, discarding section data\n");
#endif
- sec->secbufp += seclen; /* secbufp and secbuf moving together is */
- sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
+ sec->secbufp += seclen; /* secbufp and secbuf moving together is */
+ sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
}
return 0;
}
-
-static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
+static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
u8 p, count;
int ccok, dc_i = 0;
@@ -309,10 +274,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
count = payload(buf);
- if (count == 0) /* count == 0 if no payload or out of range */
+ if (count == 0) /* count == 0 if no payload or out of range */
return -1;
- p = 188 - count; /* payload start */
+ p = 188 - count; /* payload start */
cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc;
@@ -326,52 +291,53 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
if (!ccok || dc_i) {
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- printk("dvb_demux.c discontinuity detected %d bytes lost\n", count);
- /* those bytes under sume circumstances will again be reported
- ** in the following dvb_dmx_swfilter_section_new
- */
+ printk("dvb_demux.c discontinuity detected %d bytes lost\n",
+ count);
+ /*
+ * those bytes under sume circumstances will again be reported
+ * in the following dvb_dmx_swfilter_section_new
+ */
#endif
- /* Discontinuity detected. Reset pusi_seen = 0 to
- ** stop feeding of suspicious data until next PUSI=1 arrives
- */
+ /*
+ * Discontinuity detected. Reset pusi_seen = 0 to
+ * stop feeding of suspicious data until next PUSI=1 arrives
+ */
feed->pusi_seen = 0;
dvb_dmx_swfilter_section_new(feed);
- return 0;
}
if (buf[1] & 0x40) {
- // PUSI=1 (is set), section boundary is here
+ /* PUSI=1 (is set), section boundary is here */
if (count > 1 && buf[p] < count) {
- const u8 *before = buf+p+1;
+ const u8 *before = &buf[p + 1];
u8 before_len = buf[p];
- const u8 *after = before+before_len;
- u8 after_len = count-1-before_len;
+ const u8 *after = &before[before_len];
+ u8 after_len = count - 1 - before_len;
- dvb_dmx_swfilter_section_copy_dump(feed, before, before_len);
+ dvb_dmx_swfilter_section_copy_dump(feed, before,
+ before_len);
/* before start of new section, set pusi_seen = 1 */
feed->pusi_seen = 1;
dvb_dmx_swfilter_section_new(feed);
- dvb_dmx_swfilter_section_copy_dump(feed, after, after_len);
+ dvb_dmx_swfilter_section_copy_dump(feed, after,
+ after_len);
}
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- else
- if (count > 0)
- printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+ else if (count > 0)
+ printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
#endif
} else {
- // PUSI=0 (is not set), no section boundary
- const u8 *entire = buf+p;
- u8 entire_len = count;
-
- dvb_dmx_swfilter_section_copy_dump(feed, entire, entire_len);
+ /* PUSI=0 (is not set), no section boundary */
+ dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
}
+
return 0;
}
-
-static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf)
+static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
- switch(feed->type) {
+ switch (feed->type) {
case DMX_TYPE_TS:
if (!feed->feed.ts.is_filtering)
break;
@@ -379,7 +345,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
- feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+ DMX_OK);
}
if (feed->ts_type & TS_DECODER)
if (feed->demux->write_to_decoder)
@@ -390,7 +357,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
if (!feed->feed.sec.is_filtering)
break;
if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
- feed->feed.sec.seclen = feed->feed.sec.secbufp=0;
+ feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
break;
default:
@@ -406,7 +373,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
{
struct dvb_demux_feed *feed;
- struct list_head *pos, *head=&demux->feed_list;
+ struct list_head *pos, *head = &demux->feed_list;
u16 pid = ts_pid(buf);
int dvr_done = 0;
@@ -432,21 +399,21 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
}
}
-void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
+ size_t count)
{
spin_lock(&demux->lock);
while (count--) {
- if(buf[0] == 0x47) {
- dvb_dmx_swfilter_packet(demux, buf);
- }
+ if (buf[0] == 0x47)
+ dvb_dmx_swfilter_packet(demux, buf);
buf += 188;
}
spin_unlock(&demux->lock);
}
-EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
@@ -454,8 +421,10 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
spin_lock(&demux->lock);
- if ((i = demux->tsbufp)) {
- if (count < (j=188-i)) {
+ if (demux->tsbufp) {
+ i = demux->tsbufp;
+ j = 188 - i;
+ if (count < j) {
memcpy(&demux->tsbuf[i], buf, count);
demux->tsbufp += count;
goto bailout;
@@ -469,13 +438,13 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
while (p < count) {
if (buf[p] == 0x47) {
- if (count-p >= 188) {
- dvb_dmx_swfilter_packet(demux, buf+p);
+ if (count - p >= 188) {
+ dvb_dmx_swfilter_packet(demux, &buf[p]);
p += 188;
} else {
- i = count-p;
- memcpy(demux->tsbuf, buf+p, i);
- demux->tsbufp=i;
+ i = count - p;
+ memcpy(demux->tsbuf, &buf[p], i);
+ demux->tsbufp = i;
goto bailout;
}
} else
@@ -485,24 +454,29 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
bailout:
spin_unlock(&demux->lock);
}
+
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- int p = 0,i, j;
+ int p = 0, i, j;
u8 tmppack[188];
+
spin_lock(&demux->lock);
- if ((i = demux->tsbufp)) {
- if (count < (j=204-i)) {
+ if (demux->tsbufp) {
+ i = demux->tsbufp;
+ j = 204 - i;
+ if (count < j) {
memcpy(&demux->tsbuf[i], buf, count);
demux->tsbufp += count;
goto bailout;
}
memcpy(&demux->tsbuf[i], buf, j);
- if ((demux->tsbuf[0] == 0x47)|(demux->tsbuf[0]==0xB8)) {
+ if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
memcpy(tmppack, demux->tsbuf, 188);
- if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+ if (tmppack[0] == 0xB8)
+ tmppack[0] = 0x47;
dvb_dmx_swfilter_packet(demux, tmppack);
}
demux->tsbufp = 0;
@@ -510,16 +484,17 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
while (p < count) {
- if ((buf[p] == 0x47)|(buf[p] == 0xB8)) {
- if (count-p >= 204) {
- memcpy(tmppack, buf+p, 188);
- if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+ if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+ if (count - p >= 204) {
+ memcpy(tmppack, &buf[p], 188);
+ if (tmppack[0] == 0xB8)
+ tmppack[0] = 0x47;
dvb_dmx_swfilter_packet(demux, tmppack);
p += 204;
} else {
- i = count-p;
- memcpy(demux->tsbuf, buf+p, i);
- demux->tsbufp=i;
+ i = count - p;
+ memcpy(demux->tsbuf, &buf[p], i);
+ demux->tsbufp = i;
goto bailout;
}
} else {
@@ -530,14 +505,14 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
bailout:
spin_unlock(&demux->lock);
}
-EXPORT_SYMBOL(dvb_dmx_swfilter_204);
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
-static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
+static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
{
int i;
- for (i=0; i<demux->filternum; i++)
+ for (i = 0; i < demux->filternum; i++)
if (demux->filter[i].state == DMX_STATE_FREE)
break;
@@ -549,11 +524,11 @@ static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
return &demux->filter[i];
}
-static struct dvb_demux_feed * dvb_dmx_feed_alloc(struct dvb_demux *demux)
+static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux)
{
int i;
- for (i=0; i<demux->feednum; i++)
+ for (i = 0; i < demux->feednum; i++)
if (demux->feed[i].state == DMX_STATE_FREE)
break;
@@ -581,7 +556,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __FUNCTION__, feed->type, feed->state, feed->pid);
goto out;
}
@@ -595,7 +570,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __FUNCTION__, feed->type, feed->state, feed->pid);
goto out;
}
@@ -604,18 +579,17 @@ out:
spin_unlock_irq(&feed->demux->lock);
}
-static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
- enum dmx_ts_pes pes_type, size_t callback_length,
- size_t circular_buffer_size, int descramble,
- struct timespec timeout)
+static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
+ enum dmx_ts_pes pes_type,
+ size_t circular_buffer_size, struct timespec timeout)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
if (pid > DMX_MAX_PID)
return -EINVAL;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (ts_type & TS_DECODER) {
@@ -638,20 +612,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
feed->pid = pid;
feed->buffer_size = circular_buffer_size;
- feed->descramble = descramble;
feed->timeout = timeout;
- feed->cb_length = callback_length;
feed->ts_type = ts_type;
feed->pes_type = pes_type;
- if (feed->descramble) {
- up(&demux->mutex);
- return -ENOSYS;
- }
-
if (feed->buffer_size) {
#ifdef NOBUFS
- feed->buffer=NULL;
+ feed->buffer = NULL;
#else
feed->buffer = vmalloc(feed->buffer_size);
if (!feed->buffer) {
@@ -667,14 +634,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
return 0;
}
-
-static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
+static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
int ret;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
@@ -701,13 +667,13 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
return 0;
}
-static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
+static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
int ret;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state < DMX_STATE_GO) {
@@ -731,13 +697,14 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
return ret;
}
-static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed,
- dmx_ts_cb callback)
+static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
+ struct dmx_ts_feed **ts_feed,
+ dmx_ts_cb callback)
{
- struct dvb_demux *demux = (struct dvb_demux *) dmx;
+ struct dvb_demux *demux = (struct dvb_demux *)dmx;
struct dvb_demux_feed *feed;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (!(feed = dvb_dmx_feed_alloc(demux))) {
@@ -760,7 +727,6 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
(*ts_feed)->set = dmx_ts_feed_set;
-
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
feed->state = DMX_STATE_FREE;
up(&demux->mutex);
@@ -776,22 +742,22 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
return 0;
}
-static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_feed)
+static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
+ struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux *demux = (struct dvb_demux *) dmx;
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux *demux = (struct dvb_demux *)dmx;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state == DMX_STATE_FREE) {
up(&demux->mutex);
return -EINVAL;
}
-
#ifndef NOBUFS
vfree(feed->buffer);
- feed->buffer=0;
+ feed->buffer = NULL;
#endif
feed->state = DMX_STATE_FREE;
@@ -808,19 +774,18 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
return 0;
}
-
/******************************************************************************
* dmx_section_feed API calls
******************************************************************************/
-static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
- struct dmx_section_filter** filter)
+static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
+ struct dmx_section_filter **filter)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
struct dvb_demux_filter *dvbdmxfilter;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
@@ -844,36 +809,29 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
return 0;
}
-
-static int dmx_section_feed_set(struct dmx_section_feed* feed,
- u16 pid, size_t circular_buffer_size,
- int descramble, int check_crc)
+static int dmx_section_feed_set(struct dmx_section_feed *feed,
+ u16 pid, size_t circular_buffer_size,
+ int check_crc)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
if (pid > 0x1fff)
return -EINVAL;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
dvb_demux_feed_add(dvbdmxfeed);
dvbdmxfeed->pid = pid;
dvbdmxfeed->buffer_size = circular_buffer_size;
- dvbdmxfeed->descramble = descramble;
- if (dvbdmxfeed->descramble) {
- up(&dvbdmx->mutex);
- return -ENOSYS;
- }
-
dvbdmxfeed->feed.sec.check_crc = check_crc;
#ifdef NOBUFS
dvbdmxfeed->buffer = NULL;
#else
- dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
+ dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
if (!dvbdmxfeed->buffer) {
up(&dvbdmx->mutex);
return -ENOMEM;
@@ -885,7 +843,6 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
return 0;
}
-
static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
{
int i;
@@ -893,12 +850,12 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
struct dmx_section_filter *sf;
u8 mask, mode, doneq;
- if (!(f=dvbdmxfeed->filter))
+ if (!(f = dvbdmxfeed->filter))
return;
do {
sf = &f->filter;
doneq = 0;
- for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
mode = sf->filter_mode[i];
mask = sf->filter_mask[i];
f->maskandmode[i] = mask & mode;
@@ -908,14 +865,13 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
} while ((f = f->next));
}
-
static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (feed->is_filtering) {
@@ -954,14 +910,13 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
return 0;
}
-
-static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
+static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (!dvbdmx->stop_feed) {
@@ -980,15 +935,14 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
return ret;
}
-
static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
- struct dmx_section_filter* filter)
+ struct dmx_section_filter *filter)
{
- struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *) filter, *f;
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (dvbdmxfilter->feed != dvbdmxfeed) {
@@ -1005,7 +959,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
if (f == dvbdmxfilter) {
dvbdmxfeed->filter = dvbdmxfilter->next;
} else {
- while(f->next != dvbdmxfilter)
+ while (f->next != dvbdmxfilter)
f = f->next;
f->next = f->next->next;
}
@@ -1020,10 +974,10 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback)
{
- struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
struct dvb_demux_feed *dvbdmxfeed;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
@@ -1041,7 +995,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
dvbdmxfeed->filter = NULL;
dvbdmxfeed->buffer = NULL;
- (*feed)=&dvbdmxfeed->feed.sec;
+ (*feed) = &dvbdmxfeed->feed.sec;
(*feed)->is_filtering = 0;
(*feed)->parent = demux;
(*feed)->priv = NULL;
@@ -1059,21 +1013,21 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
static int dvbdmx_release_section_feed(struct dmx_demux *demux,
struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
- if (dvbdmxfeed->state==DMX_STATE_FREE) {
+ if (dvbdmxfeed->state == DMX_STATE_FREE) {
up(&dvbdmx->mutex);
return -EINVAL;
}
#ifndef NOBUFS
vfree(dvbdmxfeed->buffer);
- dvbdmxfeed->buffer=0;
+ dvbdmxfeed->buffer = NULL;
#endif
- dvbdmxfeed->state=DMX_STATE_FREE;
+ dvbdmxfeed->state = DMX_STATE_FREE;
dvb_demux_feed_del(dvbdmxfeed);
@@ -1083,14 +1037,13 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
return 0;
}
-
/******************************************************************************
* dvb_demux kernel data API calls
******************************************************************************/
static int dvbdmx_open(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
return -EUSERS;
@@ -1099,10 +1052,9 @@ static int dvbdmx_open(struct dmx_demux *demux)
return 0;
}
-
static int dvbdmx_close(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (dvbdemux->users == 0)
return -ENODEV;
@@ -1112,15 +1064,14 @@ static int dvbdmx_close(struct dmx_demux *demux)
return 0;
}
-
static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
return -EINVAL;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
dvb_dmx_swfilter(dvbdemux, buf, count);
up(&dvbdemux->mutex);
@@ -1130,10 +1081,10 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
return count;
}
-
-static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_add_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
struct list_head *head = &dvbdemux->frontend_list;
list_add(&(frontend->connectivity_list), head);
@@ -1141,13 +1092,13 @@ static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *fro
return 0;
}
-
-static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_remove_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
- list_for_each_safe (pos, n, head) {
+ list_for_each_safe(pos, n, head) {
if (DMX_FE_ENTRY(pos) == frontend) {
list_del(pos);
return 0;
@@ -1157,25 +1108,25 @@ static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *
return -ENODEV;
}
-
-static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux)
+static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (list_empty(&dvbdemux->frontend_list))
return NULL;
+
return &dvbdemux->frontend_list;
}
-
-static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_connect_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (demux->frontend)
return -EINVAL;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
demux->frontend = frontend;
@@ -1183,12 +1134,11 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend
return 0;
}
-
static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
demux->frontend = NULL;
@@ -1196,44 +1146,42 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
return 0;
}
-
-static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
+static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
+ memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
return 0;
}
-
int dvb_dmx_init(struct dvb_demux *dvbdemux)
{
- int i, err;
+ int i;
struct dmx_demux *dmx = &dvbdemux->dmx;
dvbdemux->users = 0;
- dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
+ dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
if (!dvbdemux->filter)
return -ENOMEM;
- dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
+ dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
if (!dvbdemux->feed) {
vfree(dvbdemux->filter);
return -ENOMEM;
}
- for (i=0; i<dvbdemux->filternum; i++) {
+ for (i = 0; i < dvbdemux->filternum; i++) {
dvbdemux->filter[i].state = DMX_STATE_FREE;
dvbdemux->filter[i].index = i;
}
- for (i=0; i<dvbdemux->feednum; i++) {
+ for (i = 0; i < dvbdemux->feednum; i++) {
dvbdemux->feed[i].state = DMX_STATE_FREE;
dvbdemux->feed[i].index = i;
}
- dvbdemux->frontend_list.next=
- dvbdemux->frontend_list.prev=
- &dvbdemux->frontend_list;
- for (i=0; i<DMX_TS_PES_OTHER; i++) {
+
+ INIT_LIST_HEAD(&dvbdemux->frontend_list);
+
+ for (i = 0; i < DMX_TS_PES_OTHER; i++) {
dvbdemux->pesfilter[i] = NULL;
dvbdemux->pids[i] = 0xffff;
}
@@ -1247,12 +1195,11 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
if (!dvbdemux->check_crc32)
dvbdemux->check_crc32 = dvb_dmx_crc32;
- if (!dvbdemux->memcopy)
- dvbdemux->memcopy = dvb_dmx_memcopy;
+ if (!dvbdemux->memcopy)
+ dvbdemux->memcopy = dvb_dmx_memcopy;
dmx->frontend = NULL;
- dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list;
- dmx->priv = (void *) dvbdemux;
+ dmx->priv = dvbdemux;
dmx->open = dvbdmx_open;
dmx->close = dvbdmx_close;
dmx->write = dvbdmx_write;
@@ -1261,9 +1208,6 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
dmx->release_section_feed = dvbdmx_release_section_feed;
- dmx->descramble_mac_address = NULL;
- dmx->descramble_section_payload = NULL;
-
dmx->add_frontend = dvbdmx_add_frontend;
dmx->remove_frontend = dvbdmx_remove_frontend;
dmx->get_frontends = dvbdmx_get_frontends;
@@ -1274,21 +1218,15 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
sema_init(&dvbdemux->mutex, 1);
spin_lock_init(&dvbdemux->lock);
- if ((err = dmx_register_demux(dmx)) < 0)
- return err;
-
return 0;
}
-EXPORT_SYMBOL(dvb_dmx_init);
+EXPORT_SYMBOL(dvb_dmx_init);
-int dvb_dmx_release(struct dvb_demux *dvbdemux)
+void dvb_dmx_release(struct dvb_demux *dvbdemux)
{
- struct dmx_demux *dmx = &dvbdemux->dmx;
-
- dmx_unregister_demux(dmx);
vfree(dvbdemux->filter);
vfree(dvbdemux->feed);
- return 0;
}
+
EXPORT_SYMBOL(dvb_dmx_release);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index c09beb391622..0cc888339d52 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -20,7 +20,6 @@
*
*/
-
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
@@ -44,103 +43,98 @@
#define DVB_DEMUX_MASK_MAX 18
struct dvb_demux_filter {
- struct dmx_section_filter filter;
- u8 maskandmode [DMX_MAX_FILTER_SIZE];
- u8 maskandnotmode [DMX_MAX_FILTER_SIZE];
+ struct dmx_section_filter filter;
+ u8 maskandmode[DMX_MAX_FILTER_SIZE];
+ u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
int doneq;
- struct dvb_demux_filter *next;
- struct dvb_demux_feed *feed;
- int index;
- int state;
- int type;
- int pesto;
-
- u16 handle;
- u16 hw_handle;
- struct timer_list timer;
- int ts_state;
-};
+ struct dvb_demux_filter *next;
+ struct dvb_demux_feed *feed;
+ int index;
+ int state;
+ int type;
+ u16 hw_handle;
+ struct timer_list timer;
+};
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
struct dvb_demux_feed {
- union {
- struct dmx_ts_feed ts;
- struct dmx_section_feed sec;
+ union {
+ struct dmx_ts_feed ts;
+ struct dmx_section_feed sec;
} feed;
- union {
- dmx_ts_cb ts;
- dmx_section_cb sec;
+ union {
+ dmx_ts_cb ts;
+ dmx_section_cb sec;
} cb;
- struct dvb_demux *demux;
+ struct dvb_demux *demux;
void *priv;
- int type;
- int state;
- u16 pid;
- u8 *buffer;
- int buffer_size;
- int descramble;
+ int type;
+ int state;
+ u16 pid;
+ u8 *buffer;
+ int buffer_size;
- struct timespec timeout;
- struct dvb_demux_filter *filter;
- int cb_length;
+ struct timespec timeout;
+ struct dvb_demux_filter *filter;
- int ts_type;
- enum dmx_ts_pes pes_type;
+ int ts_type;
+ enum dmx_ts_pes pes_type;
- int cc;
- int pusi_seen; /* prevents feeding of garbage from previous section */
+ int cc;
+ int pusi_seen; /* prevents feeding of garbage from previous section */
- u16 peslen;
+ u16 peslen;
struct list_head list_head;
- int index; /* a unique index for each feed (can be used as hardware pid filter index) */
+ unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
};
struct dvb_demux {
- struct dmx_demux dmx;
- void *priv;
- int filternum;
- int feednum;
- int (*start_feed) (struct dvb_demux_feed *feed);
- int (*stop_feed) (struct dvb_demux_feed *feed);
- int (*write_to_decoder) (struct dvb_demux_feed *feed,
+ struct dmx_demux dmx;
+ void *priv;
+ int filternum;
+ int feednum;
+ int (*start_feed)(struct dvb_demux_feed *feed);
+ int (*stop_feed)(struct dvb_demux_feed *feed);
+ int (*write_to_decoder)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
- u32 (*check_crc32) (struct dvb_demux_feed *feed,
+ u32 (*check_crc32)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
- void (*memcopy) (struct dvb_demux_feed *feed, u8 *dst,
+ void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
- int users;
+ int users;
#define MAX_DVB_DEMUX_USERS 10
- struct dvb_demux_filter *filter;
- struct dvb_demux_feed *feed;
+ struct dvb_demux_filter *filter;
+ struct dvb_demux_feed *feed;
- struct list_head frontend_list;
+ struct list_head frontend_list;
- struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
- u16 pids[DMX_TS_PES_OTHER];
- int playing;
- int recording;
+ struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
+ u16 pids[DMX_TS_PES_OTHER];
+ int playing;
+ int recording;
#define DMX_MAX_PID 0x2000
struct list_head feed_list;
- u8 tsbuf[204];
- int tsbufp;
+ u8 tsbuf[204];
+ int tsbufp;
struct semaphore mutex;
spinlock_t lock;
};
-
int dvb_dmx_init(struct dvb_demux *dvbdemux);
-int dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
+void dvb_dmx_release(struct dvb_demux *dvbdemux);
+void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
+ size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count);
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
+ size_t count);
#endif /* _DVB_DEMUX_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 6a968c346a36..87935490bfb2 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -62,7 +62,6 @@
#include <linux/uio.h>
#include <asm/uaccess.h>
#include <linux/crc32.h>
-#include <linux/version.h>
#include "dvb_demux.h"
#include "dvb_net.h"
@@ -171,11 +170,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
skb->mac.raw=skb->data;
skb_pull(skb,dev->hard_header_len);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
- eth = skb->mac.ethernet;
-#else
eth = eth_hdr(skb);
-#endif
if (*eth->h_dest & 1) {
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -908,7 +903,7 @@ static int dvb_net_feed_start(struct net_device *dev)
return ret;
}
- ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+ ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
if (ret<0) {
printk("%s: could not set section feed\n", dev->name);
@@ -960,9 +955,7 @@ static int dvb_net_feed_start(struct net_device *dev)
priv->tsfeed->priv = (void *)dev;
ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
TS_PACKET, DMX_TS_PES_OTHER,
- 188 * 100, /* nr. of bytes delivered per callback */
32768, /* circular buffer size */
- 0, /* descramble */
timeout);
if (ret < 0) {
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 612e5b087b1c..54e2b29076b1 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -93,13 +93,30 @@ config DVB_USB_DIGITV
Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
config DVB_USB_VP7045
- tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+ tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
depends on DVB_USB
help
Say Y here to support the
+
TwinhanDTV Alpha (stick) (VP-7045),
- TwinhanDTV MagicBox II (VP-7046) and
- DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+ TwinhanDTV MagicBox II (VP-7046),
+ DigitalNow TinyUSB 2 DVB-t,
+ DigitalRise USB 2.0 Ter (Beetle) and
+ TYPHOON DVB-T USB DRIVE
+
+ DVB-T USB2.0 receivers.
+
+config DVB_USB_VP702X
+ tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the
+
+ TwinhanDTV StarBox,
+ DigitalRise USB Starbox and
+ TYPHOON DVB-S USB 2.0 BOX
+
+ DVB-S USB2.0 receivers.
config DVB_USB_NOVA_T_USB2
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 746d87ed6f32..2dc9aad9681e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -4,6 +4,9 @@ obj-$(CONFIG_DVB_USB) += dvb-usb.o
dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
+obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
+
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index f2fcc2f1f846..e55322ef76b3 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -90,7 +90,7 @@ static struct dvb_usb_properties a800_properties;
static int a800_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index c3e1b661aae6..3fe383f4bb4c 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -48,35 +48,26 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
return 0;
}
-/* I2C */
-static void cxusb_set_i2c_path(struct dvb_usb_device *d, enum cxusb_i2c_pathes path)
+/* GPIO */
+static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
{
struct cxusb_state *st = d->priv;
u8 o[2],i;
- if (path == st->cur_i2c_path)
+ if (st->gpio_write_state[GPIO_TUNER] == onoff)
return;
- o[0] = IOCTL_SET_I2C_PATH;
- switch (path) {
- case PATH_CX22702:
- o[1] = 0;
- break;
- case PATH_TUNER_OTHER:
- o[1] = 1;
- break;
- default:
- err("unkown i2c path");
- return;
- }
- cxusb_ctrl_msg(d,CMD_IOCTL,o,2,&i,1);
+ o[0] = GPIO_TUNER;
+ o[1] = onoff;
+ cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
if (i != 0x01)
- deb_info("i2c_path setting failed.\n");
+ deb_info("gpio_write failed.\n");
- st->cur_i2c_path = path;
+ st->gpio_write_state[GPIO_TUNER] = onoff;
}
+/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -92,10 +83,10 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
switch (msg[i].addr) {
case 0x63:
- cxusb_set_i2c_path(d,PATH_CX22702);
+ cxusb_gpio_tuner(d,0);
break;
default:
- cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
+ cxusb_gpio_tuner(d,1);
break;
}
@@ -141,24 +132,26 @@ static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm cxusb_i2c_algo = {
- .name = "Conexant USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = cxusb_i2c_xfer,
.functionality = cxusb_i2c_func,
};
static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
{
- return 0;
+ u8 b = 0;
+ if (onoff)
+ return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
+ else
+ return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
}
static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
if (onoff)
- cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
+ cxusb_ctrl_msg(d,CMD_STREAMING_ON, buf, 2, NULL, 0);
else
- cxusb_ctrl_msg(d,0x37, NULL, 0, NULL, 0);
+ cxusb_ctrl_msg(d,CMD_STREAMING_OFF, NULL, 0, NULL, 0);
return 0;
}
@@ -184,22 +177,11 @@ static int cxusb_tuner_attach(struct dvb_usb_device *d)
static int cxusb_frontend_attach(struct dvb_usb_device *d)
{
- u8 buf[2] = { 0x03, 0x00 };
- u8 b = 0;
-
- if (usb_set_interface(d->udev,0,0) < 0)
- err("set interface to alts=0 failed");
-
- cxusb_ctrl_msg(d,0xde,&b,0,NULL,0);
- cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
- cxusb_ctrl_msg(d,CMD_POWER_OFF, NULL, 0, &b, 1);
-
+ u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
err("set interface failed");
- cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
- cxusb_set_i2c_path(d,PATH_CX22702);
- cxusb_ctrl_msg(d,CMD_POWER_ON, NULL, 0, &b, 1);
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
return 0;
@@ -213,7 +195,7 @@ static struct dvb_usb_properties cxusb_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL);
}
static struct usb_device_id cxusb_table [] = {
@@ -239,14 +221,12 @@ static struct dvb_usb_properties cxusb_properties = {
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
- .type = DVB_USB_ISOC,
+ .type = DVB_USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
- .isoc = {
- .framesperurb = 32,
- .framesize = 940,
- .interval = 5,
+ .bulk = {
+ .buffersize = 8192,
}
}
},
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 1d79016e3195..135c2a81f581 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -1,30 +1,31 @@
#ifndef _DVB_USB_CXUSB_H_
#define _DVB_USB_CXUSB_H_
-#define DVB_USB_LOG_PREFIX "digitv"
+#define DVB_USB_LOG_PREFIX "cxusb"
#include "dvb-usb.h"
extern int dvb_usb_cxusb_debug;
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
/* usb commands - some of it are guesses, don't have a reference yet */
-#define CMD_I2C_WRITE 0x08
-#define CMD_I2C_READ 0x09
+#define CMD_I2C_WRITE 0x08
+#define CMD_I2C_READ 0x09
-#define CMD_IOCTL 0x0e
-#define IOCTL_SET_I2C_PATH 0x02
+#define CMD_GPIO_READ 0x0d
+#define CMD_GPIO_WRITE 0x0e
+#define GPIO_TUNER 0x02
-#define CMD_POWER_OFF 0x50
-#define CMD_POWER_ON 0x51
+#define CMD_POWER_OFF 0xdc
+#define CMD_POWER_ON 0xde
-enum cxusb_i2c_pathes {
- PATH_UNDEF = 0x00,
- PATH_CX22702 = 0x01,
- PATH_TUNER_OTHER = 0x02,
-};
+#define CMD_STREAMING_ON 0x36
+#define CMD_STREAMING_OFF 0x37
+
+#define CMD_ANALOG 0x50
+#define CMD_DIGITAL 0x51
struct cxusb_state {
- enum cxusb_i2c_pathes cur_i2c_path;
+ u8 gpio_write_state[3];
};
#endif
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 63b626f70c81..00b946419b40 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -70,13 +70,22 @@ EXPORT_SYMBOL(dibusb_power_ctrl);
int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
- u8 b[2];
- b[0] = DIBUSB_REQ_SET_IOCTL;
- b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+ u8 b[3] = { 0 };
+ int ret;
+
+ if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0)
+ return ret;
- dvb_usb_generic_write(d,b,3);
+ if (onoff) {
+ b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
+ b[1] = 0x00;
+ if ((ret = dvb_usb_generic_write(d,b,2)) < 0)
+ return ret;
+ }
- return dibusb_streaming_ctrl(d,onoff);
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+ return dvb_usb_generic_write(d,b,3);
}
EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
@@ -147,8 +156,6 @@ static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
}
struct i2c_algorithm dibusb_i2c_algo = {
- .name = "DiBcom USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = dibusb_i2c_xfer,
.functionality = dibusb_i2c_func,
};
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 828b5182e16c..0058505634a0 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -86,9 +86,9 @@ static struct dvb_usb_properties dibusb2_0b_properties;
static int dibusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
- dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
- dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0)
return 0;
return -EINVAL;
@@ -126,10 +126,12 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
+/* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) },
+
// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
-/* 27 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+/* 28 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
{ } /* Terminating entry */
};
@@ -262,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
},
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
- { &dibusb_dib3000mb_table[27], NULL },
+ { &dibusb_dib3000mb_table[28], NULL },
{ NULL },
},
#endif
@@ -306,12 +308,16 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
}
},
- .num_device_descs = 1,
+ .num_device_descs = 2,
.devices = {
- { "KWorld/ADSTech Instant DVB-T USB 2.0",
+ { "KWorld/ADSTech Instant DVB-T USB2.0",
{ &dibusb_dib3000mb_table[23], NULL },
{ &dibusb_dib3000mb_table[24], NULL },
},
+ { "KWorld Xpert DVB-T USB2.0",
+ { &dibusb_dib3000mb_table[27], NULL },
+ { NULL }
+ },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index e9dac430f37d..6a0912eab396 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -20,7 +20,7 @@ static struct dvb_usb_properties dibusb_mc_properties;
static int dibusb_mc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 9a676afc1d6e..74545f82eff1 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -77,8 +77,6 @@ static u32 digitv_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm digitv_i2c_algo = {
- .name = "Nebula DigiTV USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = digitv_i2c_xfer,
.functionality = digitv_i2c_func,
};
@@ -113,31 +111,28 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
}
static struct mt352_config digitv_mt352_config = {
- .demod_address = 0x0, /* ignored by the digitv anyway */
.demod_init = digitv_mt352_demod_init,
.pll_set = dvb_usb_pll_set,
};
-static struct nxt6000_config digitv_nxt6000_config = {
- .demod_address = 0x0, /* ignored by the digitv anyway */
- .clock_inversion = 0x0,
+static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+ u8 b[5];
+ dvb_usb_pll_set(fe,fep,b);
+ return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
+}
- .pll_init = NULL,
- .pll_set = NULL,
+static struct nxt6000_config digitv_nxt6000_config = {
+ .clock_inversion = 1,
+ .pll_set = digitv_nxt6000_pll_set,
};
static int digitv_frontend_attach(struct dvb_usb_device *d)
{
- if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL)
+ if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
+ (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
return 0;
- if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
-
- warn("nxt6000 support is not done yet, in fact you are one of the first "
- "person who wants to use this device in Linux. Please report to "
- "linux-dvb@linuxtv.org");
-
- return 0;
- }
return -EIO;
}
@@ -175,7 +170,18 @@ static struct dvb_usb_properties digitv_properties;
static int digitv_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+ struct dvb_usb_device *d;
+ int ret;
+ if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+ u8 b[4] = { 0 };
+
+ b[0] = 1;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+
+ b[0] = 0;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ }
+ return ret;
}
static struct usb_device_id digitv_table [] = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index b032523b07bc..0a94ec22aeb8 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -18,6 +18,7 @@ struct dtt200u_fe_state {
struct dvb_frontend_parameters fep;
struct dvb_frontend frontend;
+ struct dvb_frontend_ops ops;
};
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,8 +164,9 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
deb_info("attaching frontend dtt200u\n");
state->d = d;
+ memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
- state->frontend.ops = &dtt200u_fe_ops;
+ state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
goto success;
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 47dba6e45968..5aa12ebab34f 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -98,20 +98,19 @@ static struct dvb_usb_properties wt220u_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) == 0 ||
- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
return 0;
return -ENODEV;
}
static struct usb_device_id dtt200u_usb_table [] = {
-// { USB_DEVICE(0x04b4,0x8613) },
- { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
- { 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) },
- { 0 },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
+ { 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) },
+ { 0 },
};
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -189,7 +188,7 @@ static struct dvb_usb_properties wt220u_properties = {
.num_device_descs = 1,
.devices = {
- { .name = "WideView WT-220U PenType Receiver (and clones)",
+ { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
@@ -201,9 +200,9 @@ static struct dvb_usb_properties wt220u_properties = {
static struct usb_driver dtt200u_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dtt200u",
- .probe = dtt200u_usb_probe,
+ .probe = dtt200u_usb_probe,
.disconnect = dvb_usb_device_exit,
- .id_table = dtt200u_usb_table,
+ .id_table = dtt200u_usb_table,
};
/* module stuff */
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 3491ff40885c..6fa92100248b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -23,12 +23,12 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
*/
if (newfeedcount == 0) {
deb_ts("stop feeding\n");
+ dvb_usb_urb_kill(d);
if (d->props.streaming_ctrl != NULL)
if ((ret = d->props.streaming_ctrl(d,0)))
err("error while stopping stream.");
- dvb_usb_urb_kill(d);
}
d->feedcount = newfeedcount;
@@ -44,6 +44,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
* for reception.
*/
if (d->feedcount == onoff && d->feedcount > 0) {
+ deb_ts("submitting all URBs\n");
+ dvb_usb_urb_submit(d);
deb_ts("controlling pid parser\n");
if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
@@ -59,7 +61,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
return -ENODEV;
}
- dvb_usb_urb_submit(d);
}
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 9f0a8d90d146..da970947dfc7 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -27,7 +27,6 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
#endif
d->i2c_adap.algo = d->props.i2c_algo;
d->i2c_adap.algo_data = NULL;
- d->i2c_adap.id = I2C_ALGO_BIT;
i2c_set_adapdata(&d->i2c_adap, d);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 794d513a8480..0818996bf150 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -24,8 +24,10 @@
#define USB_VID_HANFTEK 0x15f4
#define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025
+#define USB_VID_KWORLD 0xeb2a
#define USB_VID_KYE 0x0458
#define USB_VID_MEDION 0x1660
+#define USB_VID_PINNACLE 0x2304
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
@@ -52,12 +54,14 @@
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
+#define USB_PID_TWINHAN_VP7020_COLD 0x3203
+#define USB_PID_TWINHAN_VP7020_WARM 0x3204
#define USB_PID_TWINHAN_VP7045_COLD 0x3205
#define USB_PID_TWINHAN_VP7045_WARM 0x3206
-#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
-#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
+#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
@@ -85,5 +89,7 @@
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
+#define USB_PID_PCTV_200E 0x020e
+#define USB_PID_PCTV_400E 0x020f
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index 65f0c095abc9..a902059812a2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -128,7 +128,9 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
/*
* USB
*/
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
+
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
+ *props, struct module *owner,struct dvb_usb_device **du)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_device *d = NULL;
@@ -170,6 +172,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *p
usb_set_intfdata(intf, d);
+ if (du != NULL)
+ *du = d;
+
ret = dvb_usb_init(d);
}
@@ -196,19 +201,6 @@ void dvb_usb_device_exit(struct usb_interface *intf)
}
EXPORT_SYMBOL(dvb_usb_device_exit);
-/* module stuff */
-static int __init dvb_usb_module_init(void)
-{
- return 0;
-}
-
-static void __exit dvb_usb_module_exit(void)
-{
-}
-
-module_init (dvb_usb_module_init);
-module_exit (dvb_usb_module_exit);
-
MODULE_VERSION("0.3");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index a80567caf508..0e4f1035b0dd 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -127,7 +127,7 @@ struct dvb_usb_device;
* helper functions.
*
* @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
- * Currently only BULK is implemented
+ * (BULK or ISOC)
*
* @num_device_descs: number of struct dvb_usb_device_description in @devices
* @devices: array of struct dvb_usb_device_description compatibles with these
@@ -310,7 +310,7 @@ struct dvb_usb_device {
void *priv;
};
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *, struct dvb_usb_device **);
extern void dvb_usb_device_exit(struct usb_interface *);
/* the generic read/write method for device control */
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 258a92bfbcc7..1841a66427bf 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -144,7 +144,7 @@ static struct dvb_usb_properties nova_t_properties;
static int nova_t_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 2112ac3cf5e2..6fd67657c269 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -77,7 +77,7 @@ static struct dvb_usb_properties umt_properties;
static int umt_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
return 0;
return -EINVAL;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
new file mode 100644
index 000000000000..f20d8dbd0be8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -0,0 +1,339 @@
+/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
+ * DVB-S receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ * Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * This file can be removed soon, after the DST-driver is rewritten to provice
+ * the frontend-controlling separately.
+ *
+ * This program is free software; 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ *
+ */
+#include "vp702x.h"
+
+struct vp702x_fe_state {
+ struct dvb_frontend fe;
+ struct dvb_usb_device *d;
+
+ fe_sec_voltage_t voltage;
+ fe_sec_tone_mode_t tone_mode;
+
+ u8 lnb_buf[8];
+
+ u8 lock;
+ u8 sig;
+ u8 snr;
+
+ unsigned long next_status_check;
+ unsigned long status_check_interval;
+};
+
+static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
+{
+ u8 buf[10];
+ if (time_after(jiffies,st->next_status_check)) {
+ vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
+
+ st->lock = buf[4];
+ vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
+ vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
+
+ st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+ }
+ return 0;
+}
+
+static u8 vp702x_chksum(u8 *buf,int f, int count)
+{
+ u8 s = 0;
+ int i;
+ for (i = f; i < f+count; i++)
+ s += buf[i];
+ return ~s+1;
+}
+
+static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ deb_fe("%s\n",__FUNCTION__);
+
+ if (st->lock == 0)
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+ else
+ *status = 0;
+
+ deb_fe("real state: %x\n",*status);
+ *status = 0x1f;
+
+ if (*status & FE_HAS_LOCK)
+ st->status_check_interval = 1000;
+ else
+ st->status_check_interval = 250;
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ *ber = 0;
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ *unc = 0;
+ return 0;
+}
+
+static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+
+ *strength = (st->sig << 8) | st->sig;
+ return 0;
+}
+
+static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ u8 _snr;
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+
+ _snr = (st->snr & 0x1f) * 0xff / 0x1f;
+ *snr = (_snr << 8) | _snr;
+ return 0;
+}
+
+static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ tune->min_delay_ms = 2000;
+ return 0;
+}
+
+static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u32 freq = fep->frequency/1000;
+ /*CalFrequency*/
+/* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
+ u64 sr;
+ u8 cmd[8] = { 0 },ibuf[10];
+
+ cmd[0] = (freq >> 8) & 0x7f;
+ cmd[1] = freq & 0xff;
+ cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
+
+ sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
+ do_div(sr,88000);
+ cmd[3] = (sr >> 12) & 0xff;
+ 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);
+
+/* if (fep->inversion == INVERSION_ON)
+ cmd[6] |= 0x80; */
+
+ if (st->voltage == SEC_VOLTAGE_18)
+ cmd[6] |= 0x40;
+
+/* if (fep->u.qpsk.symbol_rate > 8000000)
+ cmd[6] |= 0x20;
+
+ if (fep->frequency < 1531000)
+ cmd[6] |= 0x04;
+
+ if (st->tone_mode == SEC_TONE_ON)
+ cmd[6] |= 0x01;*/
+
+ cmd[7] = vp702x_chksum(cmd,0,7);
+
+ st->status_check_interval = 250;
+ st->next_status_check = jiffies;
+
+ vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+ msleep(30);
+ vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("tuning failed.\n");
+ else
+ deb_fe("tuning succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ return 0;
+}
+
+static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *m)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 cmd[8],ibuf[10];
+ memset(cmd,0,8);
+
+ deb_fe("%s\n",__FUNCTION__);
+
+ if (m->msg_len > 4)
+ return -EINVAL;
+
+ cmd[1] = SET_DISEQC_CMD;
+ cmd[2] = m->msg_len;
+ memcpy(&cmd[3], m->msg, m->msg_len);
+ cmd[7] = vp702x_chksum(cmd,0,7);
+
+ vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("diseqc cmd failed.\n");
+ else
+ deb_fe("diseqc cmd succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ return 0;
+}
+
+static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+ deb_fe("%s\n",__FUNCTION__);
+
+ st->tone_mode = tone;
+
+ if (tone == SEC_TONE_ON)
+ st->lnb_buf[2] = 0x02;
+ else
+ st->lnb_buf[2] = 0x00;
+
+ st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+ vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("set_tone cmd failed.\n");
+ else
+ deb_fe("set_tone cmd succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+ voltage)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+ deb_fe("%s\n",__FUNCTION__);
+
+ st->voltage = voltage;
+
+ if (voltage != SEC_VOLTAGE_OFF)
+ st->lnb_buf[4] = 0x01;
+ else
+ st->lnb_buf[4] = 0x00;
+
+ st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+ vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("set_voltage cmd failed.\n");
+ else
+ deb_fe("set_voltage cmd succeeded.\n");
+
+ return 0;
+}
+
+static void vp702x_fe_release(struct dvb_frontend* fe)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ kfree(st);
+}
+
+static struct dvb_frontend_ops vp702x_fe_ops;
+
+struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
+{
+ struct vp702x_fe_state *s = kmalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+ memset(s,0,sizeof(struct vp702x_fe_state));
+
+ s->d = d;
+ s->fe.ops = &vp702x_fe_ops;
+ s->fe.demodulator_priv = s;
+
+ s->lnb_buf[1] = SET_LNB_POWER;
+ s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
+
+ goto success;
+error:
+ return NULL;
+success:
+ return &s->fe;
+}
+
+
+static struct dvb_frontend_ops vp702x_fe_ops = {
+ .info = {
+ .name = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1000, /* kHz for QPSK frontends */
+ .frequency_tolerance = 0,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .symbol_rate_tolerance = 500, /* ppm */
+ .caps = 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_QPSK |
+ FE_CAN_FEC_AUTO
+ },
+ .release = vp702x_fe_release,
+
+ .init = NULL,
+ .sleep = NULL,
+
+ .set_frontend = vp702x_fe_set_frontend,
+ .get_frontend = vp702x_fe_get_frontend,
+ .get_tune_settings = vp702x_fe_get_tune_settings,
+
+ .read_status = vp702x_fe_read_status,
+ .read_ber = vp702x_fe_read_ber,
+ .read_signal_strength = vp702x_fe_read_signal_strength,
+ .read_snr = vp702x_fe_read_snr,
+ .read_ucblocks = vp702x_fe_read_unc_blocks,
+
+ .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
+ .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
+ .set_tone = vp702x_fe_set_tone,
+ .set_voltage = vp702x_fe_set_voltage,
+};
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
new file mode 100644
index 000000000000..de13c04e8e64
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -0,0 +1,290 @@
+/* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S
+ * receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ * Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * This program is free software; 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "vp702x.h"
+
+/* debug */
+int dvb_usb_vp702x_debug;
+module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+struct vp702x_state {
+ u8 pid_table[17]; /* [16] controls the pid_table state */
+};
+
+/* check for mutex FIXME */
+int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ int ret = 0,try = 0;
+
+ while (ret >= 0 && ret != blen && try < 3) {
+ ret = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value,index,b,blen,
+ 2000);
+ deb_info("reading number %d (ret: %d)\n",try,ret);
+ try++;
+ }
+
+ if (ret < 0 || ret != blen) {
+ warn("usb in operation failed.");
+ ret = -EIO;
+ } else
+ ret = 0;
+
+ deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ return ret;
+}
+
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ if (usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ value,index,b,blen,
+ 2000) != blen) {
+ warn("usb out operation failed.");
+ return -EIO;
+ } else
+ return 0;
+}
+
+int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+ int ret;
+
+ if ((ret = down_interruptible(&d->usb_sem)))
+ return ret;
+
+ if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0)
+ goto unlock;
+ msleep(msec);
+ ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
+
+unlock:
+ up(&d->usb_sem);
+
+ return ret;
+}
+
+int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+ u8 bout[olen+2];
+ u8 bin[ilen+1];
+ int ret = 0;
+
+ bout[0] = 0x00;
+ bout[1] = cmd;
+ memcpy(&bout[2],o,olen);
+
+ ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
+
+ if (ret == 0)
+ memcpy(i,&bin[1],ilen);
+
+ return ret;
+}
+
+static int vp702x_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+ struct vp702x_state *st = d->priv;
+ u8 buf[9];
+
+ if (onoff) {
+ st->pid_table[16] |= 1 << index;
+ st->pid_table[index*2] = (pid >> 8) & 0xff;
+ st->pid_table[index*2+1] = pid & 0xff;
+ } else {
+ st->pid_table[16] &= ~(1 << index);
+ st->pid_table[index*2] = st->pid_table[index*2+1] = 0;
+ }
+
+ return vp702x_usb_inout_cmd(d,SET_PID_FILTER,st->pid_table,17,buf,9,10);
+}
+
+static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0);
+
+ vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+ return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+}
+
+/* keys for the enclosed remote control */
+static struct dvb_usb_rc_key vp702x_rc_keys[] = {
+ { 0x00, 0x01, KEY_1 },
+ { 0x00, 0x02, KEY_2 },
+};
+
+/* remote control stuff (does not work with my box) */
+static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[10];
+ int i;
+
+/* remove the following return to enabled remote querying */
+ return 0;
+
+ vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
+
+ deb_rc("remote query key: %x %d\n",key[1],key[1]);
+
+ if (key[1] == 0x44) {
+ *state = REMOTE_NO_KEY_PRESSED;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++)
+ if (vp702x_rc_keys[i].custom == key[1]) {
+ *state = REMOTE_KEY_PRESSED;
+ *event = vp702x_rc_keys[i].event;
+ break;
+ }
+ return 0;
+}
+
+static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
+{
+ u8 macb[9];
+ if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10))
+ return -EIO;
+ memcpy(mac,&macb[3],6);
+ return 0;
+}
+
+static int vp702x_frontend_attach(struct dvb_usb_device *d)
+{
+ u8 buf[9] = { 0 };
+
+ if (vp702x_usb_inout_cmd(d, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10))
+ return -EIO;
+
+ buf[8] = '\0';
+ info("system string: %s",&buf[1]);
+
+ d->fe = vp702x_fe_attach(d);
+ return 0;
+}
+
+static struct dvb_usb_properties vp702x_properties;
+
+static int vp702x_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ usb_clear_halt(udev,usb_sndctrlpipe(udev,0));
+ usb_clear_halt(udev,usb_rcvctrlpipe(udev,0));
+
+ return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id vp702x_usb_table [] = {
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
+
+static struct dvb_usb_properties vp702x_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+ .pid_filter_count = 8, /* !!! */
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-vp702x-01.fw",
+
+ .pid_filter = vp702x_pid_filter,
+ .power_ctrl = vp702x_power_ctrl,
+ .frontend_attach = vp702x_frontend_attach,
+ .read_mac_address = vp702x_read_mac_addr,
+
+ .rc_key_map = vp702x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(vp702x_rc_keys),
+ .rc_interval = 400,
+ .rc_query = vp702x_rc_query,
+
+ .size_of_priv = sizeof(struct vp702x_state),
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
+ .cold_ids = { &vp702x_usb_table[0], NULL },
+ .warm_ids = { &vp702x_usb_table[1], NULL },
+ },
+ { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
+ .cold_ids = { &vp702x_usb_table[2], NULL },
+ .warm_ids = { &vp702x_usb_table[3], NULL },
+ },
+ { 0 },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vp702x_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "dvb-usb-vp702x",
+ .probe = vp702x_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = vp702x_usb_table,
+};
+
+/* module stuff */
+static int __init vp702x_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&vp702x_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit vp702x_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&vp702x_usb_driver);
+}
+
+module_init(vp702x_usb_module_init);
+module_exit(vp702x_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
new file mode 100644
index 000000000000..4a3e8c7eca2b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -0,0 +1,109 @@
+#ifndef _DVB_USB_VP7021_H_
+#define _DVB_USB_VP7021_H_
+
+#define DVB_USB_LOG_PREFIX "vp702x"
+#include "dvb-usb.h"
+
+extern int dvb_usb_vp702x_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_vp702x_debug,0x04,args)
+#define deb_fe(args...) dprintk(dvb_usb_vp702x_debug,0x08,args)
+
+/* commands are read and written with USB control messages */
+
+/* consecutive read/write operation */
+#define REQUEST_OUT 0xB2
+#define REQUEST_IN 0xB3
+
+/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
+ * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
+ * the returning buffer looks as follows
+ * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
+
+#define GET_TUNER_STATUS 0x05
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
+
+#define GET_SYSTEM_STRING 0x06
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
+
+#define SET_DISEQC_CMD 0x08
+/* additional out buffer:
+ * 0 1 2 3 4
+ * len X1 X2 X3 X4
+ * additional in buffer:
+ * 0 1 2
+ * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+
+#define SET_LNB_POWER 0x09
+/* additional out buffer:
+ * 0 1 2
+ * 0x00 0xff 1 = on, 0 = off
+ * additional in buffer:
+ * 0 1 2
+ * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+
+#define GET_MAC_ADDRESS 0x0A
+/* #define GET_MAC_ADDRESS 0x0B */
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
+
+#define SET_PID_FILTER 0x11
+/* additional in buffer:
+ * 0 1 ... 14 15 16
+ * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
+
+/* request: 0xB2; i: 0; v: 0;
+ * b[0] != 0 -> tune and lock a channel
+ * 0 1 2 3 4 5 6 7
+ * freq0 freq1 divstep srate0 srate1 srate2 flag chksum
+ */
+
+
+/* one direction requests */
+#define READ_REMOTE_REQ 0xB4
+/* IN i: 0; v: 0; b[0] == request, b[1] == key */
+
+#define READ_PID_NUMBER_REQ 0xB5
+/* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
+
+#define WRITE_EEPROM_REQ 0xB6
+/* OUT i: offset; v: value to write; no extra buffer */
+
+#define READ_EEPROM_REQ 0xB7
+/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
+
+#define READ_STATUS 0xB8
+/* IN i: 0; v: 0; bufferlen 10 */
+
+#define READ_TUNER_REG_REQ 0xB9
+/* IN i: 0; v: register; b[0] = value */
+
+#define READ_FX2_REG_REQ 0xBA
+/* IN i: offset; v: 0; b[0] = value */
+
+#define WRITE_FX2_REG_REQ 0xBB
+/* OUT i: offset; v: value to write; 1 byte extra buffer */
+
+#define SET_TUNER_POWER_REQ 0xBC
+/* IN i: 0 = power off, 1 = power on */
+
+#define WRITE_TUNER_REG_REQ 0xBD
+/* IN i: register, v: value to write, no extra buffer */
+
+#define RESET_TUNER 0xBE
+/* IN i: 0, v: 0, no extra buffer */
+
+extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
+
+extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 9ac95f54f9fc..0f57abeb6d6b 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -164,7 +164,6 @@ static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int off
return 0;
}
-
static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{
return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
@@ -199,7 +198,7 @@ static struct dvb_usb_properties vp7045_properties;
static int vp7045_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
}
static struct usb_device_id vp7045_usb_table [] = {
@@ -256,9 +255,9 @@ static struct dvb_usb_properties vp7045_properties = {
static struct usb_driver vp7045_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_vp7045",
- .probe = vp7045_usb_probe,
+ .probe = vp7045_usb_probe,
.disconnect = dvb_usb_device_exit,
- .id_table = vp7045_usb_table,
+ .id_table = vp7045_usb_table,
};
/* module stuff */
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 8222b88cb486..d4b97989e3ed 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -1,7 +1,7 @@
/*
cx24110 - Single Chip Satellite Channel Receiver driver module
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
work
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
@@ -387,8 +387,9 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- int rv, bit, i;
+ int rv, bit;
struct cx24110_state *state = fe->demodulator_priv;
+ unsigned long timeout;
if (burst == SEC_MINI_A)
bit = 0x00;
@@ -398,12 +399,14 @@ static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
return -EINVAL;
rv = cx24110_readreg(state, 0x77);
- cx24110_writereg(state, 0x77, rv|0x04);
+ if (!(rv & 0x04))
+ cx24110_writereg(state, 0x77, rv | 0x04);
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
- for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
- ; /* wait for LNB ready */
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
+ ; /* wait for LNB ready */
return 0;
}
@@ -413,17 +416,22 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
{
int i, rv;
struct cx24110_state *state = fe->demodulator_priv;
+ unsigned long timeout;
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
rv = cx24110_readreg(state, 0x77);
- cx24110_writereg(state, 0x77, rv|0x04);
+ if (rv & 0x04) {
+ cx24110_writereg(state, 0x77, rv & ~0x04);
+ msleep(30); /* reportedly fixes switching problems */
+ }
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
- for (i=500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40);)
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
; /* wait for LNB ready */
return 0;
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
index 6b663f4744e0..b63ecf26421a 100644
--- a/drivers/media/dvb/frontends/cx24110.h
+++ b/drivers/media/dvb/frontends/cx24110.h
@@ -1,7 +1,7 @@
/*
cx24110 - Single Chip Satellite Channel Receiver driver module
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
work
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index cd434b7cf9db..21433e1831e7 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -23,7 +23,6 @@
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index cd33705a4320..441de665fec3 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -22,7 +22,6 @@
*/
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 1f1cd7a8d500..7142b9c51dd2 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -69,8 +69,8 @@ struct lgdt330x_state
};
static int i2c_write_demod_bytes (struct lgdt330x_state* state,
- u8 *buf, /* data bytes to send */
- int len /* number of bytes to send */ )
+ u8 *buf, /* data bytes to send */
+ int len /* number of bytes to send */ )
{
struct i2c_msg msg =
{ .addr = state->config->demod_address,
@@ -129,13 +129,13 @@ static int lgdt3302_SwReset(struct lgdt330x_state* state)
};
ret = i2c_write_demod_bytes(state,
- reset, sizeof(reset));
+ reset, sizeof(reset));
if (ret == 0) {
/* force reset high (inactive) and unmask interrupts */
reset[1] = 0x7f;
ret = i2c_write_demod_bytes(state,
- reset, sizeof(reset));
+ reset, sizeof(reset));
}
return ret;
}
@@ -149,13 +149,13 @@ static int lgdt3303_SwReset(struct lgdt330x_state* state)
};
ret = i2c_write_demod_bytes(state,
- reset, sizeof(reset));
+ reset, sizeof(reset));
if (ret == 0) {
/* force reset high (inactive) */
reset[1] = 0x01;
ret = i2c_write_demod_bytes(state,
- reset, sizeof(reset));
+ reset, sizeof(reset));
}
return ret;
}
@@ -172,7 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state)
}
}
-
static int lgdt330x_init(struct dvb_frontend* fe)
{
/* Hardware reset is done using gpio[0] of cx23880x chip.
@@ -229,13 +228,13 @@ static int lgdt330x_init(struct dvb_frontend* fe)
case LGDT3302:
chip_name = "LGDT3302";
err = i2c_write_demod_bytes(state, lgdt3302_init_data,
- sizeof(lgdt3302_init_data));
- break;
+ sizeof(lgdt3302_init_data));
+ break;
case LGDT3303:
chip_name = "LGDT3303";
err = i2c_write_demod_bytes(state, lgdt3303_init_data,
- sizeof(lgdt3303_init_data));
- break;
+ sizeof(lgdt3303_init_data));
+ break;
default:
chip_name = "undefined";
printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
@@ -262,15 +261,15 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
switch (state->config->demod_chip) {
case LGDT3302:
err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
- buf, sizeof(buf));
- break;
+ buf, sizeof(buf));
+ break;
case LGDT3303:
err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
- buf, sizeof(buf));
- break;
+ buf, sizeof(buf));
+ break;
default:
printk(KERN_WARNING
- "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ "Only LGDT3302 and LGDT3303 are supported chips.\n");
err = -ENODEV;
}
@@ -330,7 +329,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
if (state->config->demod_chip == LGDT3303) {
err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
- sizeof(lgdt3303_8vsb_44_data));
+ sizeof(lgdt3303_8vsb_44_data));
}
break;
@@ -378,18 +377,19 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
/* Select the requested mode */
i2c_write_demod_bytes(state, top_ctrl_cfg,
- sizeof(top_ctrl_cfg));
- state->config->set_ts_params(fe, 0);
+ sizeof(top_ctrl_cfg));
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
state->current_modulation = param->u.vsb.modulation;
}
- /* Change only if we are actually changing the channel */
- if (state->current_frequency != param->frequency) {
- /* Tune to the new frequency */
+ /* Tune to the specified frequency */
+ if (state->config->pll_set)
state->config->pll_set(fe, param);
- /* Keep track of the new frequency */
- state->current_frequency = param->frequency;
- }
+
+ /* Keep track of the new frequency */
+ state->current_frequency = param->frequency;
+
lgdt330x_SwReset(state);
return 0;
}
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index d32dc4de9e7f..cc1bc0edd65e 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -462,9 +462,11 @@ static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct mt352_state* state = fe->demodulator_priv;
- u16 signal = ((mt352_read_register(state, AGC_GAIN_1) << 8) & 0x0f) |
- (mt352_read_register(state, AGC_GAIN_0));
+ /* align the 12 bit AGC gain with the most significant bits */
+ u16 signal = ((mt352_read_register(state, AGC_GAIN_1) & 0x0f) << 12) |
+ (mt352_read_register(state, AGC_GAIN_0) << 4);
+ /* inverse of gain is signal strength */
*strength = ~signal;
return 0;
}
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index 966de9853d18..88a57b791112 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -482,6 +482,7 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
return result;
+ msleep(500);
return 0;
}
@@ -525,6 +526,12 @@ static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
return 0;
}
+static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 500;
+ return 0;
+}
+
static struct dvb_frontend_ops nxt6000_ops;
struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -578,6 +585,8 @@ static struct dvb_frontend_ops nxt6000_ops = {
.init = nxt6000_init,
+ .get_tune_settings = nxt6000_fe_get_tune_settings,
+
.set_frontend = nxt6000_set_frontend,
.read_status = nxt6000_read_status,
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index cc0a77c790f1..b6d0eecc59eb 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -370,22 +370,19 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
or51132_setmode(fe);
}
- /* Change only if we are actually changing the channel */
- if (state->current_frequency != param->frequency) {
- dvb_pll_configure(state->config->pll_desc, buf,
- param->frequency, 0);
- dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
- if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
- printk(KERN_WARNING "or51132: set_parameters error "
- "writing to tuner\n");
-
- /* Set to current mode */
- or51132_setmode(fe);
-
- /* Update current frequency */
- state->current_frequency = param->frequency;
- }
+ dvb_pll_configure(state->config->pll_desc, buf,
+ param->frequency, 0);
+ dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
+ "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
+ if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
+ printk(KERN_WARNING "or51132: set_parameters error "
+ "writing to tuner\n");
+
+ /* Set to current mode */
+ or51132_setmode(fe);
+
+ /* Update current frequency */
+ state->current_frequency = param->frequency;
return 0;
}
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 4f396ac8de77..c7fe27fd530c 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -48,7 +48,8 @@ struct s5h1420_state {
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings);
static int debug = 0;
@@ -91,7 +92,8 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
switch(voltage) {
case SEC_VOLTAGE_13:
- s5h1420_writereg(state, 0x3c, (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
+ s5h1420_writereg(state, 0x3c,
+ (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
break;
case SEC_VOLTAGE_18:
@@ -112,18 +114,21 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
switch(tone) {
case SEC_TONE_ON:
- s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
+ s5h1420_writereg(state, 0x3b,
+ (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
break;
case SEC_TONE_OFF:
- s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+ s5h1420_writereg(state, 0x3b,
+ (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
break;
}
return 0;
}
-static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd* cmd)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -131,6 +136,9 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
unsigned long timeout;
int result = 0;
+ if (cmd->msg_len > 8)
+ return -EINVAL;
+
/* setup for DISEQC */
val = s5h1420_readreg(state, 0x3b);
s5h1420_writereg(state, 0x3b, 0x02);
@@ -138,16 +146,17 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
/* write the DISEQC command bytes */
for(i=0; i< cmd->msg_len; i++) {
- s5h1420_writereg(state, 0x3c + i, cmd->msg[i]);
+ s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
}
/* kick off transmission */
- s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | ((cmd->msg_len-1) << 4) | 0x08);
+ s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
+ ((cmd->msg_len-1) << 4) | 0x08);
/* wait for transmission to complete */
timeout = jiffies + ((100*HZ) / 1000);
while(time_before(jiffies, timeout)) {
- if (s5h1420_readreg(state, 0x3b) & 0x08)
+ if (!(s5h1420_readreg(state, 0x3b) & 0x08))
break;
msleep(5);
@@ -161,7 +170,8 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
return result;
}
-static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply)
+static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
+ struct dvb_diseqc_slave_reply* reply)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -205,7 +215,7 @@ static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_
/* extract data */
for(i=0; i< length; i++) {
- reply->msg[i] = s5h1420_readreg(state, 0x3c + i);
+ reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
}
exit:
@@ -236,7 +246,7 @@ static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicm
s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
/* wait for transmission to complete */
- timeout = jiffies + ((20*HZ) / 1000);
+ timeout = jiffies + ((100*HZ) / 1000);
while(time_before(jiffies, timeout)) {
if (!(s5h1420_readreg(state, 0x3b) & 0x08))
break;
@@ -259,9 +269,9 @@ static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
val = s5h1420_readreg(state, 0x14);
if (val & 0x02)
- status |= FE_HAS_SIGNAL; // FIXME: not sure if this is right
+ status |= FE_HAS_SIGNAL;
if (val & 0x01)
- status |= FE_HAS_CARRIER; // FIXME: not sure if this is right
+ status |= FE_HAS_CARRIER;
val = s5h1420_readreg(state, 0x36);
if (val & 0x01)
status |= FE_HAS_VITERBI;
@@ -284,8 +294,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* determine lock state */
*status = s5h1420_get_status_bits(state);
- /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion,
- wait a bit and check again */
+ /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+ the inversion, wait a bit and check again */
if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
val = s5h1420_readreg(state, 0x32);
if ((val & 0x07) == 0x03) {
@@ -330,6 +340,10 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
tmp = (tmp * 2 * 7) / 8;
break;
}
+ if (tmp == 0) {
+ printk("s5h1420: avoided division by 0\n");
+ tmp = 1;
+ }
tmp = state->fclk / tmp;
/* set the MPEG_CLK_INTL for the calculated data rate */
@@ -368,16 +382,21 @@ static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
s5h1420_writereg(state, 0x46, 0x1d);
mdelay(25);
- return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ *ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ return 0;
}
static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct s5h1420_state* state = fe->demodulator_priv;
- u8 val = 0xff - s5h1420_readreg(state, 0x15);
+ u8 val = s5h1420_readreg(state, 0x15);
- return (int) ((val << 8) | val);
+ *strength = (u16) ((val << 8) | val);
+
+ return 0;
}
static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
@@ -386,7 +405,10 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
s5h1420_writereg(state, 0x46, 0x1f);
mdelay(25);
- return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ *ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ return 0;
}
static void s5h1420_reset(struct s5h1420_state* state)
@@ -396,11 +418,12 @@ static void s5h1420_reset(struct s5h1420_state* state)
udelay(10);
}
-static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
{
u64 val;
- val = (p->u.qpsk.symbol_rate / 1000) * (1<<24);
+ val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
if (p->u.qpsk.symbol_rate <= 21000000) {
val *= 2;
}
@@ -415,7 +438,7 @@ static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_fronte
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
{
- u64 val;
+ u64 val = 0;
int sampling = 2;
if (s5h1420_readreg(state, 0x05) & 0x2)
@@ -427,10 +450,10 @@ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
val |= s5h1420_readreg(state, 0x13);
s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
- val *= (state->fclk / 1000);
+ val *= (state->fclk / 1000ULL);
do_div(val, ((1<<24) * sampling));
- return (u32) (val * 1000);
+ return (u32) (val * 1000ULL);
}
static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
@@ -463,46 +486,55 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
* divide fclk by 1000000 to get the correct value. */
- val = - ((val * (state->fclk/1000000)) / (1<<24));
+ val = (((-val) * (state->fclk/1000000)) / (1<<24));
return val;
}
-static void s5h1420_setfec(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
{
+ u8 inversion = 0;
+
+ if (p->inversion == INVERSION_OFF) {
+ inversion = state->config->invert ? 0x08 : 0;
+ } else if (p->inversion == INVERSION_ON) {
+ inversion = state->config->invert ? 0 : 0x08;
+ }
+
if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
- s5h1420_writereg(state, 0x31, 0x00);
s5h1420_writereg(state, 0x30, 0x3f);
+ s5h1420_writereg(state, 0x31, 0x00 | inversion);
} else {
switch(p->u.qpsk.fec_inner) {
case FEC_1_2:
- s5h1420_writereg(state, 0x31, 0x10);
s5h1420_writereg(state, 0x30, 0x01);
+ s5h1420_writereg(state, 0x31, 0x10 | inversion);
break;
case FEC_2_3:
- s5h1420_writereg(state, 0x31, 0x11);
s5h1420_writereg(state, 0x30, 0x02);
+ s5h1420_writereg(state, 0x31, 0x11 | inversion);
break;
case FEC_3_4:
- s5h1420_writereg(state, 0x31, 0x12);
s5h1420_writereg(state, 0x30, 0x04);
- break;
+ s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ break;
case FEC_5_6:
- s5h1420_writereg(state, 0x31, 0x13);
s5h1420_writereg(state, 0x30, 0x08);
+ s5h1420_writereg(state, 0x31, 0x13 | inversion);
break;
case FEC_6_7:
- s5h1420_writereg(state, 0x31, 0x14);
s5h1420_writereg(state, 0x30, 0x10);
+ s5h1420_writereg(state, 0x31, 0x14 | inversion);
break;
case FEC_7_8:
- s5h1420_writereg(state, 0x31, 0x15);
s5h1420_writereg(state, 0x30, 0x20);
+ s5h1420_writereg(state, 0x31, 0x15 | inversion);
break;
default:
@@ -536,22 +568,6 @@ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
return FEC_NONE;
}
-static void s5h1420_setinversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
-{
- if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
- s5h1420_writereg(state, 0x31, 0x00);
- s5h1420_writereg(state, 0x30, 0x3f);
- } else {
- u8 tmp = s5h1420_readreg(state, 0x31) & 0xf7;
- tmp |= 0x10;
-
- if (p->inversion == INVERSION_ON)
- tmp |= 0x80;
-
- s5h1420_writereg(state, 0x31, tmp);
- }
-}
-
static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
{
if (s5h1420_readreg(state, 0x32) & 0x08)
@@ -560,35 +576,35 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
return INVERSION_OFF;
}
-static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
{
struct s5h1420_state* state = fe->demodulator_priv;
- u32 frequency_delta;
+ int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
+ u32 tmp;
/* check if we should do a fast-tune */
memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
s5h1420_get_tune_settings(fe, &fesettings);
frequency_delta = p->frequency - state->tunedfreq;
- if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) &&
+ if ((frequency_delta > -fesettings.max_drift) &&
+ (frequency_delta < fesettings.max_drift) &&
(frequency_delta != 0) &&
(state->fec_inner == p->u.qpsk.fec_inner) &&
(state->symbol_rate == p->u.qpsk.symbol_rate)) {
- s5h1420_setfreqoffset(state, frequency_delta);
+ if (state->config->pll_set) {
+ s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+ state->config->pll_set(fe, p, &tmp);
+ s5h1420_setfreqoffset(state, p->frequency - tmp);
+ }
return 0;
}
/* first of all, software reset */
s5h1420_reset(state);
- /* set tuner PLL */
- if (state->config->pll_set) {
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- state->config->pll_set(fe, p, &state->tunedfreq);
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
- }
-
/* set s5h1420 fclk PLL according to desired symbol rate */
if (p->u.qpsk.symbol_rate > 28000000) {
state->fclk = 88000000;
@@ -609,8 +625,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* set misc registers */
s5h1420_writereg(state, 0x02, 0x00);
+ s5h1420_writereg(state, 0x06, 0x00);
s5h1420_writereg(state, 0x07, 0xb0);
- s5h1420_writereg(state, 0x0a, 0x67);
+ s5h1420_writereg(state, 0x0a, 0xe7);
s5h1420_writereg(state, 0x0b, 0x78);
s5h1420_writereg(state, 0x0c, 0x48);
s5h1420_writereg(state, 0x0d, 0x6b);
@@ -626,21 +643,26 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* start QPSK */
s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
- /* set the frequency offset to adjust for PLL inaccuracy */
- s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq);
+ /* set tuner PLL */
+ if (state->config->pll_set) {
+ s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+ state->config->pll_set(fe, p, &tmp);
+ s5h1420_setfreqoffset(state, 0);
+ }
/* set the reset of the parameters */
s5h1420_setsymbolrate(state, p);
- s5h1420_setinversion(state, p);
- s5h1420_setfec(state, p);
+ s5h1420_setfec_inversion(state, p);
state->fec_inner = p->u.qpsk.fec_inner;
state->symbol_rate = p->u.qpsk.symbol_rate;
state->postlocked = 0;
+ state->tunedfreq = p->frequency;
return 0;
}
-static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
{
struct s5h1420_state* state = fe->demodulator_priv;
@@ -652,7 +674,8 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
{
if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
fesettings->min_delay_ms = 50;
@@ -717,7 +740,8 @@ static void s5h1420_release(struct dvb_frontend* fe)
static struct dvb_frontend_ops s5h1420_ops;
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c)
+struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ struct i2c_adapter* i2c)
{
struct s5h1420_state* state = NULL;
u8 identity;
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index b687fc77ceb3..872028ddf2a2 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -30,6 +30,9 @@ struct s5h1420_config
/* the demodulator's i2c address */
u8 demod_address;
+ /* does the inversion require inversion? */
+ u8 invert:1;
+
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 928aca052afe..8d09afd7545d 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -35,7 +35,6 @@ struct stv0297_state {
struct dvb_frontend frontend;
unsigned long base_freq;
- u8 pwm;
};
#if 1
@@ -46,94 +45,6 @@ struct stv0297_state {
#define STV0297_CLOCK_KHZ 28900
-static u8 init_tab[] = {
- 0x00, 0x09,
- 0x01, 0x69,
- 0x03, 0x00,
- 0x04, 0x00,
- 0x07, 0x00,
- 0x08, 0x00,
- 0x20, 0x00,
- 0x21, 0x40,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x24, 0x40,
- 0x25, 0x88,
- 0x30, 0xff,
- 0x31, 0x00,
- 0x32, 0xff,
- 0x33, 0x00,
- 0x34, 0x50,
- 0x35, 0x7f,
- 0x36, 0x00,
- 0x37, 0x20,
- 0x38, 0x00,
- 0x40, 0x1c,
- 0x41, 0xff,
- 0x42, 0x29,
- 0x43, 0x00,
- 0x44, 0xff,
- 0x45, 0x00,
- 0x46, 0x00,
- 0x49, 0x04,
- 0x4a, 0xff,
- 0x4b, 0x7f,
- 0x52, 0x30,
- 0x55, 0xae,
- 0x56, 0x47,
- 0x57, 0xe1,
- 0x58, 0x3a,
- 0x5a, 0x1e,
- 0x5b, 0x34,
- 0x60, 0x00,
- 0x63, 0x00,
- 0x64, 0x00,
- 0x65, 0x00,
- 0x66, 0x00,
- 0x67, 0x00,
- 0x68, 0x00,
- 0x69, 0x00,
- 0x6a, 0x02,
- 0x6b, 0x00,
- 0x70, 0xff,
- 0x71, 0x00,
- 0x72, 0x00,
- 0x73, 0x00,
- 0x74, 0x0c,
- 0x80, 0x00,
- 0x81, 0x00,
- 0x82, 0x00,
- 0x83, 0x00,
- 0x84, 0x04,
- 0x85, 0x80,
- 0x86, 0x24,
- 0x87, 0x78,
- 0x88, 0x00,
- 0x89, 0x00,
- 0x90, 0x01,
- 0x91, 0x01,
- 0xa0, 0x00,
- 0xa1, 0x00,
- 0xa2, 0x00,
- 0xb0, 0x91,
- 0xb1, 0x0b,
- 0xc0, 0x53,
- 0xc1, 0x70,
- 0xc2, 0x12,
- 0xd0, 0x00,
- 0xd1, 0x00,
- 0xd2, 0x00,
- 0xd3, 0x00,
- 0xd4, 0x00,
- 0xd5, 0x00,
- 0xde, 0x00,
- 0xdf, 0x00,
- 0x61, 0x49,
- 0x62, 0x0b,
- 0x53, 0x08,
- 0x59, 0x08,
-};
-
static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
{
@@ -378,34 +289,9 @@ static int stv0297_init(struct dvb_frontend *fe)
struct stv0297_state *state = fe->demodulator_priv;
int i;
- /* soft reset */
- stv0297_writereg_mask(state, 0x80, 1, 1);
- stv0297_writereg_mask(state, 0x80, 1, 0);
-
- /* reset deinterleaver */
- stv0297_writereg_mask(state, 0x81, 1, 1);
- stv0297_writereg_mask(state, 0x81, 1, 0);
-
/* load init table */
- for (i = 0; i < sizeof(init_tab); i += 2) {
- stv0297_writereg(state, init_tab[i], init_tab[i + 1]);
- }
-
- /* set a dummy symbol rate */
- stv0297_set_symbolrate(state, 6900);
-
- /* invert AGC1 polarity */
- stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
-
- /* setup bit error counting */
- stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
-
- /* min + max PWM */
- stv0297_writereg(state, 0x4a, 0x00);
- stv0297_writereg(state, 0x4b, state->pwm);
+ for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+ stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
msleep(200);
if (state->config->pll_init)
@@ -606,7 +492,13 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
stv0297_set_inversion(state, inversion);
/* kick off lock */
- stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+ /* Disable corner detection for higher QAMs */
+ if (p->u.qam.modulation == QAM_128 ||
+ p->u.qam.modulation == QAM_256)
+ stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
+ else
+ stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+
stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
@@ -732,7 +624,7 @@ static void stv0297_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops stv0297_ops;
struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
- struct i2c_adapter *i2c, int pwm)
+ struct i2c_adapter *i2c)
{
struct stv0297_state *state = NULL;
@@ -746,7 +638,6 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
state->i2c = i2c;
memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
state->base_freq = 0;
- state->pwm = pwm;
/* check if the demod is there */
if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
index 3be535989302..9e53f019db71 100644
--- a/drivers/media/dvb/frontends/stv0297.h
+++ b/drivers/media/dvb/frontends/stv0297.h
@@ -29,6 +29,12 @@ struct stv0297_config
/* the demodulator's i2c address */
u8 demod_address;
+ /* inittab - array of pairs of values.
+ * First of each pair is the register, second is the value.
+ * List should be terminated with an 0xff, 0xff pair.
+ */
+ u8* inittab;
+
/* does the "inversion" need inverted? */
u8 invert:1;
@@ -38,7 +44,7 @@ struct stv0297_config
};
extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
- struct i2c_adapter* i2c, int pwm);
+ struct i2c_adapter* i2c);
extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
#endif // STV0297_H
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index cfa3928bb487..2d62931f20b5 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -63,12 +63,8 @@ struct stv0299_state {
u32 tuner_frequency;
u32 symbol_rate;
fe_code_rate_t fec_inner;
- int errmode;
};
-#define STATUS_BER 0
-#define STATUS_UCBLOCKS 1
-
static int debug;
static int debug_legacy_dish_switch;
#define dprintk(args...) \
@@ -481,7 +477,7 @@ static int stv0299_init (struct dvb_frontend* fe)
if (state->config->pll_init) {
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_init(fe);
+ state->config->pll_init(fe, state->i2c);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
}
@@ -520,7 +516,8 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_BER) return 0;
+ stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10);
+ msleep(100);
*ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
@@ -559,8 +556,9 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
- else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30);
+ msleep(100);
+ *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
}
@@ -603,7 +601,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
} else {
/* A "normal" tune is requested */
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, p);
+ state->config->pll_set(fe, state->i2c, p);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
stv0299_writeregI(state, 0x32, 0x80);
@@ -615,7 +613,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
}
} else {
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, p);
+ state->config->pll_set(fe, state->i2c, p);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
stv0299_set_FEC (state, p->u.qpsk.fec_inner);
@@ -709,7 +707,6 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
state->tuner_frequency = 0;
state->symbol_rate = 0;
state->fec_inner = 0;
- state->errmode = STATUS_BER;
/* check if the demod is there */
stv0299_writeregI(state, 0x02, 0x34); /* standby off */
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 79457a80a11f..d0c4484861e1 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -92,8 +92,8 @@ struct stv0299_config
int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
/* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
+ int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index ab0c032472cc..74cea9f8d721 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -1046,8 +1046,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
tmp = tda1004x_read_byte(state, TDA1004X_SNR);
if (tmp < 0)
return -EIO;
- if (tmp)
- tmp = 255 - tmp;
+ tmp = 255 - tmp;
*snr = ((tmp << 8) | tmp);
dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
index 88e125079ca1..d1cabb6a0a13 100644
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ b/drivers/media/dvb/frontends/tda80xx.c
@@ -30,6 +30,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <asm/irq.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 70fb44b391a7..c6d276618e86 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -194,19 +194,18 @@ static int ves1820_init(struct dvb_frontend* fe)
{
struct ves1820_state* state = fe->demodulator_priv;
int i;
- int val;
ves1820_writereg(state, 0, 0);
- for (i = 0; i < 53; i++) {
- val = ves1820_inittab[i];
- if ((i == 2) && (state->config->selagc)) val |= 0x08;
- ves1820_writereg(state, i, val);
- }
+ for (i = 0; i < sizeof(ves1820_inittab); i++)
+ ves1820_writereg(state, i, ves1820_inittab[i]);
+ if (state->config->selagc)
+ ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
ves1820_writereg(state, 0x34, state->pwm);
- if (state->config->pll_init) state->config->pll_init(fe);
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
return 0;
}
@@ -234,7 +233,7 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
ves1820_writereg(state, 0x09, reg0x09[real_qam]);
ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
-
+ ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
return 0;
}
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 706e0bcb5ede..85b437bbddcd 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -633,7 +633,6 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
i2c_set_adapdata(&pluto->i2c_adap, pluto);
strcpy(pluto->i2c_adap.name, DRIVER_NAME);
pluto->i2c_adap.owner = THIS_MODULE;
- pluto->i2c_adap.id = I2C_ALGO_BIT;
pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
pluto->i2c_adap.dev.parent = &pdev->dev;
pluto->i2c_adap.algo_data = &pluto->i2c_bit;
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index bf3c011d2cfb..d8bf65877897 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -102,6 +102,9 @@ config DVB_BUDGET_AV
select VIDEO_DEV
select VIDEO_SAA7146_VV
select DVB_STV0299
+ select DVB_TDA1004X
+ select DVB_TDA10021
+ select FW_LOADER
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index e4c6e87f6c5d..22b203f8ff27 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -168,7 +168,9 @@ static void init_av7110_av(struct av7110 *av7110)
if (ret < 0)
printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
if (rgb_on &&
- (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
+ ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
+ (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
+ (av7110->dev->pci->subsystem_device == 0x0000)) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
//saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
}
@@ -177,9 +179,6 @@ static void init_av7110_av(struct av7110 *av7110)
ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
if (ret < 0)
printk("dvb-ttpci:cannot set volume :%d\n",ret);
- ret = av7110_setup_irc_config(av7110, 0);
- if (ret < 0)
- printk("dvb-ttpci:cannot setup irc config :%d\n",ret);
}
static void recover_arm(struct av7110 *av7110)
@@ -265,60 +264,6 @@ static int arm_thread(void *data)
}
-/**
- * Hack! we save the last av7110 ptr. This should be ok, since
- * you rarely will use more then one IR control.
- *
- * If we want to support multiple controls we would have to do much more...
- */
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
- int ret = 0;
- static struct av7110 *last;
-
- dprintk(4, "%p\n", av7110);
-
- if (!av7110)
- av7110 = last;
- else
- last = av7110;
-
- if (av7110) {
- ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
- av7110->ir_config = ir_config;
- }
- return ret;
-}
-
-static void (*irc_handler)(u32);
-
-void av7110_register_irc_handler(void (*func)(u32))
-{
- dprintk(4, "registering %p\n", func);
- irc_handler = func;
-}
-
-void av7110_unregister_irc_handler(void (*func)(u32))
-{
- dprintk(4, "unregistering %p\n", func);
- irc_handler = NULL;
-}
-
-static void run_handlers(unsigned long ircom)
-{
- if (irc_handler != NULL)
- (*irc_handler)((u32) ircom);
-}
-
-static DECLARE_TASKLET(irtask, run_handlers, 0);
-
-static void IR_handle(struct av7110 *av7110, u32 ircom)
-{
- dprintk(4, "ircommand = %08x\n", ircom);
- irtask.data = (unsigned long) ircom;
- tasklet_schedule(&irtask);
-}
-
/****************************************************************************
* IRQ handling
****************************************************************************/
@@ -711,8 +656,9 @@ static void gpioirq(unsigned long data)
return;
case DATA_IRCOMMAND:
- IR_handle(av7110,
- swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
+ if (av7110->ir_handler)
+ av7110->ir_handler(av7110,
+ swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
break;
@@ -1668,9 +1614,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
u8 data[4];
u32 div;
@@ -1687,7 +1632,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ ret = i2c_transfer(i2c, &msg, 1);
if (ret != 1)
return -EIO;
return 0;
@@ -1751,9 +1696,8 @@ static u8 alps_bsbe1_inittab[] = {
0xff, 0xff
};
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
u8 data[4];
u32 div;
@@ -1768,7 +1712,7 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
- ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ ret = i2c_transfer(i2c, &msg, 1);
return (ret != 1) ? -EIO : 0;
}
@@ -1936,6 +1880,98 @@ static struct sp8870_config alps_tdlb7_config = {
};
+static u8 nexusca_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0x7b,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
@@ -1984,6 +2020,7 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
static struct stv0297_config nexusca_stv0297_config = {
.demod_address = 0x1C,
+ .inittab = nexusca_stv0297_inittab,
.invert = 1,
.pll_set = nexusca_stv0297_pll_set,
};
@@ -2261,7 +2298,7 @@ static int frontend_init(struct av7110 *av7110)
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
- av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b);
+ av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
if (av7110->fe) {
/* set TDA9819 into DVB mode */
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
@@ -2692,7 +2729,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
goto err_av7110_exit_v4l_12;
#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
- av7110_ir_init();
+ av7110_ir_init(av7110);
#endif
printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
av7110_num++;
@@ -2734,6 +2771,9 @@ static int av7110_detach(struct saa7146_dev* saa)
struct av7110 *av7110 = saa->ext_priv;
dprintk(4, "%p\n", av7110);
+#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
+ av7110_ir_exit(av7110);
+#endif
if (budgetpatch) {
/* Disable RPS1 */
saa7146_write(saa, MC1, MASK_29);
@@ -2830,7 +2870,7 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = x_name, \
.ext = &av7110_extension }
-MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X");
+MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
@@ -2842,16 +2882,16 @@ MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
static struct pci_device_id pci_tbl[] = {
- MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
- MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000),
- MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
- MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
- MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
- MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
- MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
- MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
- MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
- MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
+ MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
+ MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
+ MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
+ MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
+ MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
+ MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
+ MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
+ MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
+ MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
+ MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
@@ -2889,9 +2929,6 @@ static int __init av7110_init(void)
static void __exit av7110_exit(void)
{
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
- av7110_ir_exit();
-#endif
saa7146_unregister_extension(&av7110_extension);
}
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 508b7739c609..cce00ef293e9 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -228,7 +228,10 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
- u32 ir_config;
+ u32 ir_config;
+ u32 ir_command;
+ void (*ir_handler)(struct av7110 *av7110, u32 ircom);
+ struct tasklet_struct ir_tasklet;
/* firmware stuff */
unsigned char *bin_fw;
@@ -257,12 +260,10 @@ struct av7110 {
extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid);
-extern void av7110_register_irc_handler(void (*func)(u32));
-extern void av7110_unregister_irc_handler(void (*func)(u32));
extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
-extern int av7110_ir_init (void);
-extern void av7110_ir_exit (void);
+extern int av7110_ir_init(struct av7110 *av7110);
+extern void av7110_ir_exit(struct av7110 *av7110);
/* msp3400 i2c subaddresses */
#define MSP_WR_DEM 0x10
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 1220826696c5..7442f56a72ec 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -41,6 +41,8 @@
#include "av7110.h"
#include "av7110_hw.h"
+#define _NOHANDSHAKE
+
/****************************************************************************
* DEBI functions
****************************************************************************/
@@ -364,7 +366,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
msleep(1);
}
- wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
#ifndef _NOHANDSHAKE
start = jiffies;
@@ -437,7 +440,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
- wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
#ifdef COM_DEBUG
start = jiffies;
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 665cdb8a3f71..357a3728ec68 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -7,16 +7,16 @@
#include <asm/bitops.h>
#include "av7110.h"
+#include "av7110_hw.h"
-#define UP_TIMEOUT (HZ/4)
+#define UP_TIMEOUT (HZ*7/25)
/* enable ir debugging by or'ing debug with 16 */
-static int ir_initialized;
+static int av_cnt;
+static struct av7110 *av_list[4];
static struct input_dev input_dev;
-static u32 ir_config;
-
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
@@ -53,8 +53,11 @@ static void av7110_emit_keyup(unsigned long data)
static struct timer_list keyup_timer = { .function = av7110_emit_keyup };
-static void av7110_emit_key(u32 ircom)
+static void av7110_emit_key(unsigned long parm)
{
+ struct av7110 *av7110 = (struct av7110 *) parm;
+ u32 ir_config = av7110->ir_config;
+ u32 ircom = av7110->ir_command;
u8 data;
u8 addr;
static u16 old_toggle = 0;
@@ -62,19 +65,33 @@ static void av7110_emit_key(u32 ircom)
u16 keycode;
/* extract device address and data */
- if (ir_config & 0x0001) {
- /* TODO RCMM: ? bits device address, 8 bits data */
+ switch (ir_config & 0x0003) {
+ case 0: /* RC5: 5 bits device address, 6 bits data */
+ data = ircom & 0x3f;
+ addr = (ircom >> 6) & 0x1f;
+ break;
+
+ case 1: /* RCMM: 8(?) bits device address, 8(?) bits data */
data = ircom & 0xff;
addr = (ircom >> 8) & 0xff;
- } else {
- /* RC5: 5 bits device address, 6 bits data */
+ break;
+
+ case 2: /* extended RC5: 5 bits device address, 7 bits data */
data = ircom & 0x3f;
addr = (ircom >> 6) & 0x1f;
+ /* invert 7th data bit for backward compatibility with RC5 keymaps */
+ if (!(ircom & 0x1000))
+ data |= 0x40;
+ break;
+
+ default:
+ printk("invalid ir_config %x\n", ir_config);
+ return;
}
keycode = key_map[data];
- dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
+ dprintk(16, "code %08x -> addr %i data 0x%02x -> keycode %i\n",
ircom, addr, data, keycode);
/* check device address (if selected) */
@@ -87,10 +104,10 @@ static void av7110_emit_key(u32 ircom)
return;
}
- if (ir_config & 0x0001)
+ if ((ir_config & 0x0003) == 1)
new_toggle = 0; /* RCMM */
else
- new_toggle = (ircom & 0x800); /* RC5 */
+ new_toggle = (ircom & 0x800); /* RC5, extended RC5 */
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
@@ -137,6 +154,8 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
{
char *page;
int size = 4 + 256 * sizeof(u16);
+ u32 ir_config;
+ int i;
if (count < size)
return -EINVAL;
@@ -153,60 +172,95 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
memcpy(&ir_config, page, 4);
memcpy(&key_map, page + 4, 256 * sizeof(u16));
vfree(page);
- av7110_setup_irc_config(NULL, ir_config);
+ if (FW_VERSION(av_list[0]->arm_app) >= 0x2620 && !(ir_config & 0x0001))
+ ir_config |= 0x0002; /* enable extended RC5 */
+ for (i = 0; i < av_cnt; i++)
+ av7110_setup_irc_config(av_list[i], ir_config);
input_register_keys();
return count;
}
-int __init av7110_ir_init(void)
+int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
{
- static struct proc_dir_entry *e;
+ int ret = 0;
- if (ir_initialized)
- return 0;
+ dprintk(4, "%p\n", av7110);
+ if (av7110) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+ av7110->ir_config = ir_config;
+ }
+ return ret;
+}
- init_timer(&keyup_timer);
- keyup_timer.data = 0;
- input_dev.name = "DVB on-card IR receiver";
+static void ir_handler(struct av7110 *av7110, u32 ircom)
+{
+ dprintk(4, "ircommand = %08x\n", ircom);
+ av7110->ir_command = ircom;
+ tasklet_schedule(&av7110->ir_tasklet);
+}
- /**
- * enable keys
- */
- set_bit(EV_KEY, input_dev.evbit);
- set_bit(EV_REP, input_dev.evbit);
- input_register_keys();
+int __init av7110_ir_init(struct av7110 *av7110)
+{
+ static struct proc_dir_entry *e;
- input_register_device(&input_dev);
- input_dev.timer.function = input_repeat_key;
+ if (av_cnt >= sizeof av_list/sizeof av_list[0])
+ return -ENOSPC;
- av7110_setup_irc_config(NULL, 0x0001);
- av7110_register_irc_handler(av7110_emit_key);
+ av7110_setup_irc_config(av7110, 0x0001);
+ av_list[av_cnt++] = av7110;
- e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
- if (e) {
- e->write_proc = av7110_ir_write_proc;
- e->size = 4 + 256 * sizeof(u16);
+ if (av_cnt == 1) {
+ init_timer(&keyup_timer);
+ keyup_timer.data = 0;
+
+ input_dev.name = "DVB on-card IR receiver";
+ set_bit(EV_KEY, input_dev.evbit);
+ set_bit(EV_REP, input_dev.evbit);
+ input_register_keys();
+ input_register_device(&input_dev);
+ input_dev.timer.function = input_repeat_key;
+
+ e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+ if (e) {
+ e->write_proc = av7110_ir_write_proc;
+ e->size = 4 + 256 * sizeof(u16);
+ }
}
- ir_initialized = 1;
+ tasklet_init(&av7110->ir_tasklet, av7110_emit_key, (unsigned long) av7110);
+ av7110->ir_handler = ir_handler;
+
return 0;
}
-void __exit av7110_ir_exit(void)
+void __exit av7110_ir_exit(struct av7110 *av7110)
{
- if (ir_initialized == 0)
+ int i;
+
+ if (av_cnt == 0)
return;
- del_timer_sync(&keyup_timer);
- remove_proc_entry("av7110_ir", NULL);
- av7110_unregister_irc_handler(av7110_emit_key);
- input_unregister_device(&input_dev);
- ir_initialized = 0;
+
+ av7110->ir_handler = NULL;
+ tasklet_kill(&av7110->ir_tasklet);
+ for (i = 0; i < av_cnt; i++)
+ if (av_list[i] == av7110) {
+ av_list[i] = av_list[av_cnt-1];
+ av_list[av_cnt-1] = NULL;
+ break;
+ }
+
+ if (av_cnt == 1) {
+ del_timer_sync(&keyup_timer);
+ remove_proc_entry("av7110_ir", NULL);
+ input_unregister_device(&input_dev);
+ }
+
+ av_cnt--;
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
//MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index e65fc36e2ce8..6af74f78b3e5 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -70,7 +70,7 @@ static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
return 0;
}
-static struct v4l2_input inputs[2] = {
+static struct v4l2_input inputs[4] = {
{
.index = 0,
.name = "DVB",
@@ -87,6 +87,22 @@ static struct v4l2_input inputs[2] = {
.tuner = 0,
.std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
.status = 0,
+ }, {
+ .index = 2,
+ .name = "Video",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ }, {
+ .index = 3,
+ .name = "Y/C",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
}
};
@@ -212,24 +228,44 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
}
if (0 != av7110->current_input) {
+ dprintk(1, "switching to analog TV:\n");
adswitch = 1;
source = SAA7146_HPS_SOURCE_PORT_B;
sync = SAA7146_HPS_SYNC_PORT_B;
memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
- dprintk(1, "switching to analog TV\n");
- msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
- msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
- msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
- msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
- msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
- msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
- if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
- if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
- dprintk(1, "setting band in demodulator failed.\n");
- } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ switch (av7110->current_input) {
+ case 1:
+ dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
+
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+ if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
+ dprintk(1, "setting band in demodulator failed.\n");
+ } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ }
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 2:
+ dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 3:
+ dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ default:
+ dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
}
} else {
adswitch = 0;
@@ -300,7 +336,6 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
// FIXME: standard / stereo detection is still broken
msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
-
msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
stereo = (s8)(stereo_det >> 8);
@@ -310,7 +345,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
t->audmode = V4L2_TUNER_MODE_STEREO;
}
else if (stereo < -0x10) {
- /* bilingual*/
+ /* bilingual */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
}
@@ -344,7 +379,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
fm_matrix = 0x3000; // mono
src = 0x0010;
break;
- default: /* case V4L2_TUNER_MODE_MONO: {*/
+ default: /* case V4L2_TUNER_MODE_MONO: */
dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
fm_matrix = 0x3000; // mono
src = 0x0030;
@@ -406,7 +441,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
if (av7110->analog_tuner_flags) {
- if (i->index < 0 || i->index >= 2)
+ if (i->index < 0 || i->index >= 4)
return -EINVAL;
} else {
if (i->index != 0)
@@ -433,10 +468,9 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
if (!av7110->analog_tuner_flags)
return 0;
- if (input < 0 || input >= 2)
+ if (input < 0 || input >= 4)
return -EINVAL;
- /* FIXME: switch inputs here */
av7110->current_input = input;
return av7110_dvb_c_switch(fh);
}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9746d2bb916f..7692cd23f839 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int timeout = 50; // 5 seconds (4.4.6 Ready)
+ int timeout = 500; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@@ -217,7 +217,6 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
return -ETIMEDOUT;
}
@@ -276,7 +275,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
printk(KERN_INFO "budget-av: cam ejected\n");
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
budget_av->slot_status = 0;
}
}
@@ -453,9 +451,9 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
}
static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
struct dvb_frontend_parameters *params)
{
- struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -481,7 +479,7 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -745,6 +743,7 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBT_KNC1_PLUS:
// Enable / PowerON Frontend
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index a1267054bc01..2980db3ef22f 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -40,6 +40,7 @@
#include "dvb_ca_en50221.h"
#include "stv0299.h"
+#include "stv0297.h"
#include "tda1004x.h"
#define DEBIADDR_IR 0x1234
@@ -548,9 +549,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -567,7 +567,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_param
if (params->frequency > 1530000)
buf[3] = 0xc0;
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -669,9 +669,9 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
}
static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
struct dvb_frontend_parameters *params)
{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -697,7 +697,7 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -848,6 +848,180 @@ static struct tda1004x_config philips_tdm1316l_config = {
.request_firmware = philips_tdm1316l_request_firmware,
};
+static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+ u8 tuner_buf[5];
+ struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
+ .flags = 0,
+ .buf = tuner_buf,
+ .len = sizeof(tuner_buf) };
+ int tuner_frequency = 0;
+ u8 band, cp, filter;
+
+ // determine charge pump
+ tuner_frequency = params->frequency + 36125000;
+ if (tuner_frequency < 87000000)
+ return -EINVAL;
+ else if (tuner_frequency < 130000000) {
+ cp = 3;
+ band = 1;
+ } else if (tuner_frequency < 160000000) {
+ cp = 5;
+ band = 1;
+ } else if (tuner_frequency < 200000000) {
+ cp = 6;
+ band = 1;
+ } else if (tuner_frequency < 290000000) {
+ cp = 3;
+ band = 2;
+ } else if (tuner_frequency < 420000000) {
+ cp = 5;
+ band = 2;
+ } else if (tuner_frequency < 480000000) {
+ cp = 6;
+ band = 2;
+ } else if (tuner_frequency < 620000000) {
+ cp = 3;
+ band = 4;
+ } else if (tuner_frequency < 830000000) {
+ cp = 5;
+ band = 4;
+ } else if (tuner_frequency < 895000000) {
+ cp = 7;
+ band = 4;
+ } else
+ return -EINVAL;
+
+ // assume PLL filter should always be 8MHz for the moment.
+ filter = 1;
+
+ // calculate divisor
+ tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+
+ // setup tuner buffer
+ tuner_buf[0] = tuner_frequency >> 8;
+ tuner_buf[1] = tuner_frequency & 0xff;
+ tuner_buf[2] = 0xc8;
+ tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ tuner_buf[4] = 0x80;
+
+ stv0297_enable_plli2c(fe);
+ if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ msleep(50);
+
+ stv0297_enable_plli2c(fe);
+ if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ msleep(1);
+
+ return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x20,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0x7b,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x38,
+ 0x62, 0x0a,
+ 0x53, 0x13,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+ .demod_address = 0x1c,
+ .inittab = dvbc_philips_tdm1316l_inittab,
+ .invert = 0,
+ .pll_set = dvbc_philips_tdm1316l_pll_set,
+};
+
+
static void frontend_init(struct budget_ci *budget_ci)
@@ -869,6 +1043,15 @@ static void frontend_init(struct budget_ci *budget_ci)
}
break;
+ case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
+ budget_ci->tuner_pll_address = 0x61;
+ budget_ci->budget.dvb_frontend =
+ stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+ if (budget_ci->budget.dvb_frontend) {
+ break;
+ }
+ break;
+
case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
budget_ci->tuner_pll_address = 0x63;
budget_ci->budget.dvb_frontend =
@@ -878,7 +1061,7 @@ static void frontend_init(struct budget_ci *budget_ci)
}
break;
- case 0x1012: // Hauppauge/TT Nova-T CI budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+ case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
budget_ci->tuner_pll_address = 0x60;
budget_ci->budget.dvb_frontend =
tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
@@ -966,10 +1149,12 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
+ MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
{
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 8142e26b47f5..b1f21ef0e3b3 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -353,9 +353,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -370,7 +369,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 9961917e8a7f..43d6c8268642 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -332,9 +332,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct budget* budget = (struct budget*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -349,7 +348,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
return 0;
}
@@ -481,6 +480,7 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
static struct s5h1420_config s5h1420_config = {
.demod_address = 0x53,
+ .invert = 1,
.pll_set = s5h1420_pll_set,
};
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index aa43b5fcb8e7..d200ab0ad9e7 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/errno.h>
+#include <linux/jiffies.h>
#include <asm/semaphore.h>
#include "dvb_frontend.h"
@@ -570,7 +571,8 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
const u8 * data, int len);
#endif
-static int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid;
+static int numpkt = 0, numts, numstuff, numsec, numinvalid;
+static unsigned long lastj;
static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
int len)
@@ -779,7 +781,7 @@ static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
u8 *data;
int len;
numpkt++;
- if ((jiffies - lastj) >= HZ) {
+ if (time_after_eq(jiffies, lastj + HZ)) {
#if DEBUG > 2
printk
("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
@@ -1299,7 +1301,7 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
return 0;
}
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
@@ -1322,7 +1324,7 @@ static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
if (ttusb->revision == TTUSB_REV_2_2)
buf[3] |= 0x20;
- if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1472,8 +1474,6 @@ static void frontend_init(struct ttusb* ttusb)
static struct i2c_algorithm ttusb_dec_algo = {
- .name = "ttusb dec i2c algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = master_xfer,
.functionality = functionality,
};
@@ -1525,7 +1525,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
#endif
ttusb->i2c_adap.algo = &ttusb_dec_algo;
ttusb->i2c_adap.algo_data = NULL;
- ttusb->i2c_adap.id = I2C_ALGO_BIT;
result = i2c_add_adapter(&ttusb->i2c_adap);
if (result) {
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 45c9a9a08e4d..3d08fc83a754 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -28,7 +28,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
-#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 8b4ad70dd1b2..877c770558e9 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 013c835ed910..5319a9c9a979 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,7 +26,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 53d399b6652b..022913da8c59 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 202bfe6819b8..6418f03b9ce4 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -17,7 +17,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index c00245d4d249..b2256d675b44 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -10,7 +10,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 3a464a09221f..6f03ce4dd7b0 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h> /* __setup */
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/isapnp.h>
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0732efda6a98..71971e9bb342 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -14,7 +14,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 248d67fde037..b03573c6840e 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -25,7 +25,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index d7da901ebe90..f304f3c14763 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -31,7 +31,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/proc_fs.h> /* radio card status report */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 342f92df4aba..4c6d6fb49034 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -28,7 +28,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay, msleep */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 3f5742396096..93570355819a 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -22,12 +22,21 @@ config VIDEO_BT848
the Miro, Hauppauge and STB boards. Please read the material in
<file:Documentation/video4linux/bttv/> for more information.
- If you say Y or M here, you need to say Y or M to "I2C support" and
- "I2C bit-banging interfaces" in the device drivers section.
-
To compile this driver as a module, choose M here: the
module will be called bttv.
+config VIDEO_SAA6588
+ tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
+ depends on VIDEO_DEV && I2C && VIDEO_BT848
+
+ help
+ Support for Radio Data System (RDS) decoder. This allows seeing
+ radio station identification transmitted using this standard.
+ Currentlly, it works only with bt8x8 chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa6588.
+
config VIDEO_PMS
tristate "Mediavision Pro Movie Studio Video For Linux"
depends on VIDEO_DEV && ISA
@@ -254,6 +263,7 @@ config VIDEO_SAA7134_DVB
select VIDEO_BUF_DVB
select DVB_MT352
select DVB_CX22702
+ select DVB_TDA1004X
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 810e7aac0a53..046b82de9285 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -5,6 +5,7 @@
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
+rds-objs := saa6588.o
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
+obj-$(CONFIG_VIDEO_SAA6588) += rds.o
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
@@ -29,7 +31,7 @@ obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
obj-$(CONFIG_VIDEO_PMS) += pms.o
obj-$(CONFIG_VIDEO_PLANB) += planb.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o saa7191.o indycam.o
obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 48989eda2400..1ca2b67aedfb 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -391,7 +390,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7170;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index f898b6586374..173bca1e0295 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -39,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -441,7 +440,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7175;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 8733588f6db3..3ee0afca76a7 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -507,7 +506,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_bt819;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index a070417e65e6..76c1b63ebdf2 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -188,7 +188,7 @@ static int bt832_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, bt832_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, bt832_attach);
#endif
return 0;
@@ -241,7 +241,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("bt832"),
+ .name = "bt832",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index a5d529ccf3ad..8eb871d0e85b 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -295,7 +294,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_bt856;
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index 7f2d515d2873..a48de3c0e3f0 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -1,5 +1,4 @@
/*
- $Id: btcx-risc.c,v 1.6 2005/02/21 13:57:59 kraxel Exp $
btcx-risc.c
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h
index 41f60395a520..503e6c6d7b69 100644
--- a/drivers/media/video/btcx-risc.h
+++ b/drivers/media/video/btcx-risc.h
@@ -1,5 +1,4 @@
/*
- * $Id: btcx-risc.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
*/
struct btcx_riscmem {
unsigned int size;
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index a97b9b958ed6..190977a1e549 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-cards.c,v 1.54 2005/07/19 18:26:46 mkrufky Exp $
bttv-cards.c
@@ -169,10 +168,10 @@ static struct CARD {
{ 0xd01810fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" },
{ 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
- // some cards ship with byteswapped IDs ...
+ /* some cards ship with byteswapped IDs ... */
{ 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
{ 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
- // this seems to happen as well ...
+ /* this seems to happen as well ... */
{ 0xff1211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
@@ -200,12 +199,12 @@ static struct CARD {
{ 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV Radio+" },
{ 0x1127153b, BTTV_TERRATV, "Terratec TV+ (V1.05)" },
- // clashes with FlyVideo
- //{ 0x18521852, BTTV_TERRATV, "Terratec TV+ (V1.10)" },
+ /* clashes with FlyVideo
+ *{ 0x18521852, BTTV_TERRATV, "Terratec TV+ (V1.10)" }, */
{ 0x1134153b, BTTV_TERRATVALUE, "Terratec TValue (LR102)" },
- { 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, // LR102
- { 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" }, // ??
- { 0xff3b153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, // ??
+ { 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */
+ { 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" }, /* ?? */
+ { 0xff3b153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */
{ 0x400015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
@@ -287,10 +286,12 @@ static struct CARD {
{ 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
{ 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
- // likely broken, vendor id doesn't match the other magic views ...
- //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+ { 0x15409511, BTTV_ACORP_Y878F, "Acorp Y878F" },
- // DVB cards (using pci function .1 for mpeg data xfer)
+ /* likely broken, vendor id doesn't match the other magic views ...
+ * { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+
+ /* DVB cards (using pci function .1 for mpeg data xfer) */
{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
{ 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" },
@@ -298,7 +299,8 @@ static struct CARD {
{ 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB" },
{ 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
- { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DVICO FusionHDTV DVB-T Lite" },
+ { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
+ { 0xd50018ac, BTTV_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0, -1, NULL }
};
@@ -316,6 +318,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1, 0},
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MIRO PCTV",
.video_inputs = 4,
@@ -327,6 +330,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 2, 0, 0, 0, 10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Hauppauge (bt848)",
.video_inputs = 4,
@@ -338,6 +342,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "STB, Gateway P/N 6000699 (bt848)",
.video_inputs = 3,
@@ -350,6 +355,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -365,6 +371,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Diamond DTV2000",
.video_inputs = 4,
@@ -376,6 +383,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 0, 1, 3},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "AVerMedia TVPhone",
.video_inputs = 3,
@@ -388,6 +396,7 @@ struct tvcard bttv_tvcards[] = {
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = avermedia_tvphone_audio,
.has_remote = 1,
},{
@@ -401,6 +410,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0 },
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x08 ---------------------------------- */
@@ -415,6 +425,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "IMS/IXmicro TurboTV",
.video_inputs = 3,
@@ -427,6 +438,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Hauppauge (bt878)",
.video_inputs = 4,
@@ -439,6 +451,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MIRO PCTV pro",
.video_inputs = 3,
@@ -450,6 +463,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20001,0x10001, 0, 0,10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x0c ---------------------------------- */
@@ -463,6 +477,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 13, 14, 11, 7, 0, 0},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "AVerMedia TVCapture 98",
.video_inputs = 3,
@@ -476,6 +491,7 @@ struct tvcard bttv_tvcards[] = {
.msp34xx_alt = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = avermedia_tv_stereo_audio,
},{
.name = "Aimslab Video Highway Xtreme (VHX)",
@@ -489,6 +505,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Zoltrix TV-Max",
.video_inputs = 3,
@@ -500,6 +517,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0 , 0, 1 , 0, 10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x10 ---------------------------------- */
@@ -510,7 +528,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x01fe00,
.muxsel = { 2, 3, 1, 1},
- // 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru>
+ /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
.audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -526,6 +544,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = winview_audio,
.has_radio = 1,
},{
@@ -539,6 +558,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {1, 0, 0, 0, 0},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
.video_inputs = 4,
@@ -550,6 +570,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.no_msp34xx = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x14 ---------------------------------- */
@@ -560,10 +581,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = {2, 3, 1, 1},
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
.video_inputs = 4,
- .audio_inputs = 2, // tuner, line in
+ .audio_inputs = 2, /* tuner, line in */
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
@@ -571,6 +593,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Askey CPH050/ Phoebe Tv Master + FM",
.video_inputs = 3,
@@ -583,6 +606,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
.video_inputs = 3,
@@ -591,11 +615,12 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 7,
.muxsel = { 2, 3, -1 },
- .digital_mode = DIGITAL_MODE_CAMERA,
+ .digital_mode = DIGITAL_MODE_CAMERA,
.audiomux = { 0, 0, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSBB5_PAL_I,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x18 ---------------------------------- */
@@ -610,6 +635,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
},{
.name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
@@ -622,6 +648,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000},
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
},{
.name = "Hauppauge WinCam newer (bt878)",
@@ -634,6 +661,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
.video_inputs = 4,
@@ -645,6 +673,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_SECAM,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x1c ---------------------------------- */
@@ -658,37 +687,38 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
/* GPIO wiring:
- External 20 pin connector (for Active Radio Upgrade board)
- gpio00: i2c-sda
- gpio01: i2c-scl
- gpio02: om5610-data
- gpio03: om5610-clk
- gpio04: om5610-wre
- gpio05: om5610-stereo
- gpio06: rds6588-davn
- gpio07: Pin 7 n.c.
- gpio08: nIOW
- gpio09+10: nIOR, nSEL ?? (bt878)
- gpio09: nIOR (bt848)
- gpio10: nSEL (bt848)
- Sound Routing:
- gpio16: u2-A0 (1st 4052bt)
- gpio17: u2-A1
- gpio18: u2-nEN
- gpio19: u4-A0 (2nd 4052)
- gpio20: u4-A1
- u4-nEN - GND
- Btspy:
- 00000 : Cdrom (internal audio input)
+ External 20 pin connector (for Active Radio Upgrade board)
+ gpio00: i2c-sda
+ gpio01: i2c-scl
+ gpio02: om5610-data
+ gpio03: om5610-clk
+ gpio04: om5610-wre
+ gpio05: om5610-stereo
+ gpio06: rds6588-davn
+ gpio07: Pin 7 n.c.
+ gpio08: nIOW
+ gpio09+10: nIOR, nSEL ?? (bt878)
+ gpio09: nIOR (bt848)
+ gpio10: nSEL (bt848)
+ Sound Routing:
+ gpio16: u2-A0 (1st 4052bt)
+ gpio17: u2-A1
+ gpio18: u2-nEN
+ gpio19: u4-A0 (2nd 4052)
+ gpio20: u4-A1
+ u4-nEN - GND
+ Btspy:
+ 00000 : Cdrom (internal audio input)
10000 : ext. Video audio input
20000 : TV Mono
a0000 : TV Mono/2
- 1a0000 : TV Stereo
+ 1a0000 : TV Stereo
30000 : Radio
40000 : Mute
- */
+*/
},{
/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
@@ -702,6 +732,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.muxsel_hook = PXC200_muxsel,
},{
@@ -710,11 +741,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .gpiomask = 0x1800, //0x8dfe00
+ .gpiomask = 0x1800, /* 0x8dfe00 */
.muxsel = { 2, 3, 1, 1},
.audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Formac iProTV, Formac ProTV I (bt848)",
.video_inputs = 4,
@@ -726,6 +758,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 1, 0, 0, 0, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x20 ---------------------------------- */
@@ -739,6 +772,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TerraTValue Version Bt878",
.video_inputs = 3,
@@ -751,31 +785,33 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Leadtek WinFast 2000/ WinFast 2000 XP",
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1, 0}, // TV, CVid, SVid, CVid over SVid connector
+ .muxsel = { 2, 3, 1, 1, 0}, /* TV, CVid, SVid, CVid over SVid connector */
/* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
.gpiomask = 0xb33000,
.audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 },
/* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
gpio23 -- hef4052:nEnable (0x800000)
gpio12 -- hef4052:A1
- gpio13 -- hef4052:A0
- 0x0000: external audio
- 0x1000: FM
- 0x2000: TV
- 0x3000: n.c.
- Note: There exists another variant "Winfast 2000" with tv stereo !?
- Note: eeprom only contains FF and pci subsystem id 107d:6606
- */
+ gpio13 -- hef4052:A0
+ 0x0000: external audio
+ 0x1000: FM
+ 0x2000: TV
+ 0x3000: n.c.
+ Note: There exists another variant "Winfast 2000" with tv stereo !?
+ Note: eeprom only contains FF and pci subsystem id 107d:6606
+ */
.needs_tvaudio = 0,
.pll = PLL_28,
.has_radio = 1,
- .tuner_type = 5, // default for now, gpio reads BFFF06 for Pal bg+dk
+ .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+ .tuner_addr = ADDR_UNSET,
.audio_hook = winfast2000_audio,
.has_remote = 1,
},{
@@ -789,6 +825,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x24 ---------------------------------- */
@@ -802,6 +839,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
.name = "Prolink PixelView PlayTV pro",
@@ -815,6 +853,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Askey CPH06X TView99",
.video_inputs = 4,
@@ -827,6 +866,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
},{
.name = "Pinnacle PCTV Studio/Rave",
@@ -840,6 +880,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x28 ---------------------------------- */
@@ -854,6 +895,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -868,6 +910,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
.audio_hook = avermedia_tvphone_audio,
},{
@@ -883,6 +926,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Little OnAir TV",
.video_inputs = 3,
@@ -894,6 +938,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
.no_msp34xx = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x2c ---------------------------------- */
@@ -908,6 +953,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_NONE,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MATRIX-Vision MV-Delta 2",
.video_inputs = 5,
@@ -920,6 +966,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Zoltrix Genie TV/FM",
.video_inputs = 3,
@@ -932,6 +979,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 21,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TV/Radio+",
.video_inputs = 3,
@@ -945,6 +993,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_35,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
@@ -960,6 +1009,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "IODATA GV-BCTV3/PCI",
.video_inputs = 3,
@@ -972,6 +1022,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
},{
.name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
@@ -986,6 +1037,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
/* GPIO wiring: (different from Rev.4C !)
GPIO17: U4.A0 (first hef4052bt)
@@ -994,8 +1046,8 @@ struct tvcard bttv_tvcards[] = {
GPIO21: U4.nEN
GPIO22: BT832 Reset Line
GPIO23: A5,A0, U5,nEN
- Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
- */
+ Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
+ */
},{
.name = "Eagle Wireless Capricorn2 (bt878A)",
.video_inputs = 4,
@@ -1007,6 +1059,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.pll = PLL_28,
.tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x34 ---------------------------------- */
@@ -1020,20 +1073,21 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1},
.audiomux = { 1, 0xd0001, 0, 0, 10},
/* sound path (5 sources):
- MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
+ MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
0= ext. Audio IN
1= from MUX2
2= Mono TV sound from Tuner
3= not connected
- MUX2 (mask 0x30000):
+ MUX2 (mask 0x30000):
0,2,3= from MSP34xx
1= FM stereo Radio from Tuner */
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Claas Langbehn <claas@bigfoot.com>,
- Sven Grothklags <sven@upb.de> */
+ Sven Grothklags <sven@upb.de> */
.name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
.video_inputs = 4,
.audio_inputs = 3,
@@ -1045,10 +1099,11 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
/* Tim Röstermundt <rosterm@uni-muenster.de>
- in de.comp.os.unix.linux.hardware:
+ in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
options tuner type=5 */
@@ -1060,15 +1115,16 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x18e0,
.muxsel = { 2, 3, 1, 1},
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
- /* For cards with tda9820/tda9821:
- 0x0000: Tuner normal stereo
- 0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
- 0x0880: Tuner A2 stereo */
+ /* For cards with tda9820/tda9821:
+ 0x0000: Tuner normal stereo
+ 0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
+ 0x0880: Tuner A2 stereo */
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
- old Easy TV BT848 version (model CPH031) */
+ old Easy TV BT848 version (model CPH031) */
.name = "Askey CPH031/ BESTBUY Easy TV",
.video_inputs = 4,
.audio_inputs = 1,
@@ -1080,6 +1136,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x38 ---------------------------------- */
@@ -1094,10 +1151,11 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
},{
/* This is the ultimate cheapo capture card
- * just a BT848A on a small PCB!
- * Steve Hosgood <steve@equiinet.com> */
+ * just a BT848A on a small PCB!
+ * Steve Hosgood <steve@equiinet.com> */
.name = "GrandTec 'Grand Video Capture' (Bt848)",
.video_inputs = 2,
.audio_inputs = 0,
@@ -1110,19 +1168,21 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_35,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- /* Daniel Herrington <daniel.herrington@home.com> */
- .name = "Askey CPH060/ Phoebe TV Master Only (No FM)",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0xe00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = TUNER_TEMIC_4036FY5_NTSC,
+ /* Daniel Herrington <daniel.herrington@home.com> */
+ .name = "Askey CPH060/ Phoebe TV Master Only (No FM)",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0xe00,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = TUNER_TEMIC_4036FY5_NTSC,
+ .tuner_addr = ADDR_UNSET,
},{
/* Matti Mottus <mottus@physic.ut.ee> */
.name = "Askey CPH03x TV Capturer",
@@ -1130,11 +1190,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .gpiomask = 0x03000F,
+ .gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 0},
- .audiomux = { 2,0,0,0,1 },
+ .audiomux = { 2,0,0,0,1 },
.pll = PLL_28,
.tuner_type = 0,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x3c ---------------------------------- */
@@ -1149,7 +1210,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 2, 0, 0, 1, 8},
.pll = PLL_35,
.tuner_type = TUNER_TEMIC_PAL,
-
+ .tuner_addr = ADDR_UNSET,
},{
/* Adrian Cox <adrian@humboldt.co.uk */
.name = "AG Electronics GMV1",
@@ -1164,10 +1225,11 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
- new Easy TV BT878 version (model CPH061)
- special thanks to Informatica Mieres for providing the card */
+ new Easy TV BT878 version (model CPH061)
+ special thanks to Informatica Mieres for providing the card */
.name = "Askey CPH061/ BESTBUY Easy TV (bt878)",
.video_inputs = 3,
.audio_inputs = 2,
@@ -1179,6 +1241,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* Lukas Gebauer <geby@volny.cz> */
.name = "ATI TV-Wonder",
@@ -1191,6 +1254,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe},
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x40 ---------------------------------- */
@@ -1206,6 +1270,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* DeeJay <deejay@westel900.net (2000S) */
.name = "Lifeview FlyVideo 2000S LR90",
@@ -1216,7 +1281,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x18e0,
.muxsel = { 2, 3, 0, 1},
/* Radio changed from 1e80 to 0x800 to make
- FlyVideo2000S in .hu happy (gm)*/
+ FlyVideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 },
.audio_hook = fv2000s_audio,
@@ -1225,6 +1290,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TValueRadio",
.video_inputs = 3,
@@ -1237,6 +1303,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
/* TANAKA Kei <peg00625@nifty.com> */
@@ -1251,25 +1318,27 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
},{
/* ---- card 0x44 ---------------------------------- */
- .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
- // try "insmod msp3400 simple=0" if you have
- // sound problems with this card.
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = -1,
- .gpiomask = 0x4f8a00,
- // 0x100000: 1=MSP enabled (0=disable again)
- // 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC)
- .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
- // tvtuner, radio, external,internal, mute, stereo
- /* tuner, Composit, SVid, Composit-on-Svid-adapter*/
- .muxsel = { 2, 3 ,0 ,1},
- .tuner_type = TUNER_MT2032,
+ .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+ /* try "insmod msp3400 simple=0" if you have
+ * sound problems with this card. */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = -1,
+ .gpiomask = 0x4f8a00,
+ /* 0x100000: 1=MSP enabled (0=disable again)
+ * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+ .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
+ /* tvtuner, radio, external,internal, mute, stereo
+ * tuner, Composit, SVid, Composit-on-Svid-adapter */
+ .muxsel = { 2, 3 ,0 ,1},
+ .tuner_type = TUNER_MT2032,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -1279,22 +1348,24 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.muxsel = { 2 },
.gpiomask = 0
},{
- /* Tomasz Pyra <hellfire@sedez.iq.pl> */
- .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
- .video_inputs = 3,
- .audio_inputs = 4,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0, 11, 7, 13, 0}, // TV and Radio with same GPIO !
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = 25,
+ /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+ .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
+ .video_inputs = 3,
+ .audio_inputs = 4,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 15,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = 25,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
/* GPIO wiring:
GPIO0: U4.A0 (hef4052bt)
@@ -1302,16 +1373,18 @@ struct tvcard bttv_tvcards[] = {
GPIO2: U4.A1 (second hef4052bt)
GPIO3: U4.nEN, U5.A0, A5.nEN
GPIO8-15: vrd866b ?
- */
+ */
},{
.name = "Lifeview FlyVideo 98EZ (capture only) LR51",
.video_inputs = 4,
.audio_inputs = 0,
.tuner = -1,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
+ .muxsel = { 2, 3, 1, 1}, /* AV1, AV2, SVHS, CVid adapter on SVHS */
.pll = PLL_28,
.no_msp34xx = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x48 ---------------------------------- */
@@ -1329,8 +1402,9 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.pll = PLL_28,
.tuner_type = 5,
- .audio_hook = pvbt878p9b_audio, // Note: not all cards have stereo
- .has_radio = 1, // Note: not all cards have radio
+ .tuner_addr = ADDR_UNSET,
+ .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */
+ .has_radio = 1, /* Note: not all cards have radio */
.has_remote = 1,
/* GPIO wiring:
GPIO0: A0 hef4052
@@ -1338,7 +1412,7 @@ struct tvcard bttv_tvcards[] = {
GPIO3: nEN hef4052
GPIO8-15: vrd866b
GPIO20,22,23: R30,R29,R28
- */
+ */
},{
/* Clay Kunz <ckunz@mail.arc.nasa.gov> */
/* you must jumper JP5 for the card to work */
@@ -1352,6 +1426,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Freitas <miguel@cetuc.puc-rio.br> */
.name = "RemoteVision MX (RV605)",
@@ -1362,71 +1437,78 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x00,
.gpiomask2 = 0x07ff,
.muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
- 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
+ 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.muxsel_hook = rv605_muxsel,
},{
- .name = "Powercolor MTV878/ MTV878R/ MTV878F",
- .video_inputs = 3,
- .audio_inputs = 2,
+ .name = "Powercolor MTV878/ MTV878R/ MTV878F",
+ .video_inputs = 3,
+ .audio_inputs = 2,
.tuner = 0,
- .svhs = 2,
- .gpiomask = 0x1C800F, // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
- .muxsel = { 2, 1, 1, },
- .audiomux = { 0, 1, 2, 2, 4 },
- .needs_tvaudio = 0,
- .tuner_type = TUNER_PHILIPS_PAL,
+ .svhs = 2,
+ .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
+ .muxsel = { 2, 1, 1, },
+ .audiomux = { 0, 1, 2, 2, 4 },
+ .needs_tvaudio = 0,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
/* ---- card 0x4c ---------------------------------- */
- /* Masaki Suzuki <masaki@btree.org> */
- .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x140007,
- .muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4, 0 },
- .tuner_type = TUNER_PHILIPS_NTSC,
- .audio_hook = windvr_audio,
-},{
- .name = "GrandTec Multi Capture Card (Bt878)",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .gpiomask = 0,
- .muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = -1,
-},{
- .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
- .video_inputs = 4,
- .audio_inputs = 3,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 7,
- .muxsel = { 2, 3, 1, 1 }, // Tuner, SVid, SVHS, SVid to SVHS connector
- .audiomux = { 0 ,0 ,4, 4,4,4},// Yes, this tuner uses the same audio output for TV and FM radio!
- // This card lacks external Audio In, so we mute it on Ext. & Int.
- // The PCB can take a sbx1637/sbx1673, wiring unknown.
- // This card lacks PCI subsystem ID, sigh.
- // audiomux=1: lower volume, 2+3: mute
- // btwincap uses 0x80000/0x80003
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = 5, // Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
- // radio signal strength indicators work fine.
- .has_radio = 1,
+ /* Masaki Suzuki <masaki@btree.org> */
+ .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x140007,
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4, 0 },
+ .tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
+ .audio_hook = windvr_audio,
+},{
+ .name = "GrandTec Multi Capture Card (Bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+},{
+ .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
+ .video_inputs = 4,
+ .audio_inputs = 3,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */
+ .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio!
+ * This card lacks external Audio In, so we mute it on Ext. & Int.
+ * The PCB can take a sbx1637/sbx1673, wiring unknown.
+ * This card lacks PCI subsystem ID, sigh.
+ * audiomux=1: lower volume, 2+3: mute
+ * btwincap uses 0x80000/0x80003
+ */
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
+ /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
+ radio signal strength indicators work fine. */
+ .has_radio = 1,
/* GPIO Info:
GPIO0,1: HEF4052 A0,A1
GPIO2: HEF4052 nENABLE
@@ -1437,25 +1519,27 @@ struct tvcard bttv_tvcards[] = {
GPIO22,23: ??
?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
},{
- /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
- .name = "DSP Design TCVIDEO",
- .video_inputs = 4,
- .svhs = -1,
- .muxsel = { 2, 3, 1, 0},
- .pll = PLL_28,
- .tuner_type = -1,
+ /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
+ .name = "DSP Design TCVIDEO",
+ .video_inputs = 4,
+ .svhs = -1,
+ .muxsel = { 2, 3, 1, 0},
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- /* ---- card 0x50 ---------------------------------- */
+ /* ---- card 0x50 ---------------------------------- */
.name = "Hauppauge WinTV PVR",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 0, 1, 1},
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = -1,
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 0, 1, 1},
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.gpiomask = 7,
.audiomux = {7},
@@ -1471,6 +1555,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv5pci_audio,
.has_radio = 1,
},{
@@ -1482,9 +1567,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 3, 2, 0, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
.video_inputs = 3,
@@ -1494,9 +1580,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x54 ---------------------------------- */
@@ -1508,9 +1595,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 3, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */
.video_inputs = 1,
@@ -1520,9 +1608,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 0 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */
.video_inputs = 2,
@@ -1532,9 +1621,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 0, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */
.video_inputs = 1,
@@ -1543,10 +1633,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.muxsel = { 0 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x58 ---------------------------------- */
@@ -1557,10 +1648,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 0, 1 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */
.video_inputs = 2,
@@ -1569,10 +1661,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 500", /* 500 */
.video_inputs = 2,
@@ -1582,19 +1675,21 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
- .name = "Osprey 540", /* 540 */
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = -1,
- .pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .name = "Osprey 540", /* 540 */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = -1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x5C ---------------------------------- */
@@ -1605,10 +1700,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */
},{
/* M G Berberich <berberic@forwiss.uni-passau.de> */
.name = "IDS Eagle",
@@ -1616,6 +1712,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
.gpiomask = 0,
.muxsel = { 0, 1, 2, 3 },
@@ -1630,6 +1727,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -1641,38 +1739,40 @@ struct tvcard bttv_tvcards[] = {
.no_gpioirq = 1,
.has_dvb = 1,
},{
- .name = "Formac ProTV II (bt878)",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 3,
- .gpiomask = 2,
- // TV, Comp1, Composite over SVID con, SVID
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 2, 0, 0, 0 },
- .pll = PLL_28,
+ .name = "Formac ProTV II (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 3,
+ .gpiomask = 2,
+ /* TV, Comp1, Composite over SVID con, SVID */
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 2, 2, 0, 0, 0 },
+ .pll = PLL_28,
.has_radio = 1,
- .tuner_type = TUNER_PHILIPS_PAL,
- /* sound routing:
- GPIO=0x00,0x01,0x03: mute (?)
- 0x02: both TV and radio (tuner: FM1216/I)
- The card has onboard audio connectors labeled "cdrom" and "board",
- not soldered here, though unknown wiring.
- Card lacks: external audio in, pci subsystem id.
- */
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
+/* sound routing:
+ GPIO=0x00,0x01,0x03: mute (?)
+ 0x02: both TV and radio (tuner: FM1216/I)
+ The card has onboard audio connectors labeled "cdrom" and "board",
+ not soldered here, though unknown wiring.
+ Card lacks: external audio in, pci subsystem id.
+*/
},{
/* ---- card 0x60 ---------------------------------- */
.name = "MachTV",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = -1,
- .gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
- .needs_tvaudio = 1,
- .tuner_type = 5,
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = -1,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0, 1, 2, 3, 4},
+ .needs_tvaudio = 1,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
.pll = 1,
},{
.name = "Euresys Picolo",
@@ -1686,6 +1786,8 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.muxsel = { 2, 0, 1},
.pll = PLL_28,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* Luc Van Hoeylandt <luc@e-magic.be> */
.name = "ProVideo PV150", /* 0x4f */
@@ -1699,7 +1801,8 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* Hiroshi Takekawa <sian@big.or.jp> */
/* This card lacks subsystem ID */
@@ -1716,78 +1819,85 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 2,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = adtvk503_audio,
},{
/* ---- card 0x64 ---------------------------------- */
- .name = "Hercules Smart TV Stereo",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 1 },
- .needs_tvaudio = 1,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = 5,
+ .name = "Hercules Smart TV Stereo",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x00,
+ .muxsel = { 2, 3, 1, 1 },
+ .needs_tvaudio = 1,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
/* Notes:
- - card lacks subsystem ID
- - stereo variant w/ daughter board with tda9874a @0xb0
- - Audio Routing:
+ - card lacks subsystem ID
+ - stereo variant w/ daughter board with tda9874a @0xb0
+ - Audio Routing:
always from tda9874 independent of GPIO (?)
external line in: unknown
- - Other chips: em78p156elp @ 0x96 (probably IR remote control)
- hef4053 (instead 4052) for unknown function
+ - Other chips: em78p156elp @ 0x96 (probably IR remote control)
+ hef4053 (instead 4052) for unknown function
+ */
+},{
+ .name = "Pace TV & Radio Card",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */
+ .gpiomask = 0,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
+ .has_radio = 1,
+ .pll = PLL_28,
+ /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+ only internal line out: (4pin header) RGGL
+ Radio must be decoded by msp3410d (not routed through)*/
+ /*
+ .digital_mode = DIGITAL_MODE_CAMERA, todo!
*/
},{
- .name = "Pace TV & Radio Card",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 1}, // Tuner, CVid, SVid, CVid over SVid connector
- .gpiomask = 0,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = 1,
- .has_radio = 1,
- .pll = PLL_28,
- /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
- only internal line out: (4pin header) RGGL
- Radio must be decoded by msp3410d (not routed through)*/
- // .digital_mode = DIGITAL_MODE_CAMERA, // todo!
-},{
- /* Chris Willing <chris@vislab.usyd.edu.au> */
- .name = "IVC-200",
- .video_inputs = 1,
- .audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
- .svhs = -1,
- .gpiomask = 0xdf,
- .muxsel = { 2 },
- .pll = PLL_28,
+ /* Chris Willing <chris@vislab.usyd.edu.au> */
+ .name = "IVC-200",
+ .video_inputs = 1,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .svhs = -1,
+ .gpiomask = 0xdf,
+ .muxsel = { 2 },
+ .pll = PLL_28,
},{
.name = "Grand X-Guard / Trust 814PCI",
.video_inputs = 16,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
.tuner_type = 4,
- .gpiomask2 = 0xff,
+ .tuner_addr = ADDR_UNSET,
+ .gpiomask2 = 0xff,
.muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 },
.muxsel_hook = xguard_muxsel,
.no_msp34xx = 1,
.no_tda9875 = 1,
- .no_tda7432 = 1,
+ .no_tda7432 = 1,
.pll = PLL_28,
},{
/* ---- card 0x68 ---------------------------------- */
.name = "Nebula Electronics DigiTV",
.video_inputs = 1,
- .tuner = -1,
+ .tuner = -1,
.svhs = -1,
.muxsel = { 2, 3, 1, 0},
.no_msp34xx = 1,
@@ -1795,22 +1905,24 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
.no_gpioirq = 1,
},{
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
.name = "ProVideo PV143",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .gpiomask = 0,
- .muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = -1,
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* M.Klahr@phytec.de */
.name = "PHYTEC VD-009-X1 MiniDIN (bt878)",
@@ -1824,6 +1936,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "PHYTEC VD-009-X1 Combi (bt878)",
.video_inputs = 4,
@@ -1836,6 +1949,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x6c ---------------------------------- */
@@ -1846,13 +1960,14 @@ struct tvcard bttv_tvcards[] = {
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
- via the upper nibble of muxsel. here: used for
- xternal video-mux */
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "PHYTEC VD-009 Combi (bt878)",
.video_inputs = 10,
@@ -1861,23 +1976,25 @@ struct tvcard bttv_tvcards[] = {
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
- via the upper nibble of muxsel. here: used for
- xternal video-mux */
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- .name = "IVC-100",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
- .svhs = -1,
- .gpiomask = 0xdf,
- .muxsel = { 2, 3, 1, 0 },
- .pll = PLL_28,
+ .name = "IVC-100",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .svhs = -1,
+ .gpiomask = 0xdf,
+ .muxsel = { 2, 3, 1, 0 },
+ .pll = PLL_28,
},{
/* IVC-120G - Alan Garfield <alan@fromorbit.com> */
.name = "IVC-120G",
@@ -1885,6 +2002,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0, /* card has no audio */
.tuner = -1, /* card has no tuner */
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1, /* card has no svhs */
.needs_tvaudio = 0,
.no_msp34xx = 1,
@@ -1892,7 +2010,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.gpiomask = 0x00,
.muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
.muxsel_hook = ivc120_muxsel,
.pll = PLL_28,
},{
@@ -1905,6 +2023,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1, 0},
.tuner_type = TUNER_PHILIPS_ATSC,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
},{
.name = "Twinhan DST + clones",
@@ -1912,19 +2031,21 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.no_tda7432 = 1,
.tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
.no_video = 1,
.has_dvb = 1,
},{
- .name = "Winfast VC100",
+ .name = "Winfast VC100",
.video_inputs = 3,
.audio_inputs = 0,
.svhs = 1,
- .tuner = -1, // no tuner
- .muxsel = { 3, 1, 1, 3}, // Vid In, SVid In, Vid over SVid in connector
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = TUNER_ABSENT,
+ .tuner = -1,
+ .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
},{
.name = "Teppro TEV-560/InterVision IV-560",
@@ -1937,44 +2058,49 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 1, 1, 1, 1, 0},
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_35,
},{
/* ---- card 0x74 ---------------------------------- */
- .name = "SIMUS GVC1100",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .tuner_type = -1,
- .pll = PLL_28,
- .muxsel = { 2, 2, 2, 2},
- .gpiomask = 0x3F,
+ .name = "SIMUS GVC1100",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .muxsel = { 2, 2, 2, 2},
+ .gpiomask = 0x3F,
.muxsel_hook = gvc1100_muxsel,
},{
- /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
- .name = "NGS NGSTV+",
- .video_inputs = 3,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x008007,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0, 0, 0, 0, 0x000003, 0},
- .pll = PLL_28,
- .tuner_type = TUNER_PHILIPS_PAL,
- .has_remote = 1,
-},{
- /* http://linuxmedialabs.com */
- .name = "LMLBT4",
- .video_inputs = 4, /* IN1,IN2,IN3,IN4 */
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .muxsel = { 2, 3, 1, 0 },
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .needs_tvaudio = 0,
+ /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
+ .name = "NGS NGSTV+",
+ .video_inputs = 3,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x008007,
+ .muxsel = {2, 3, 0, 0},
+ .audiomux = {0, 0, 0, 0, 0x000003, 0},
+ .pll = PLL_28,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
+ .has_remote = 1,
+},{
+ /* http://linuxmedialabs.com */
+ .name = "LMLBT4",
+ .video_inputs = 4, /* IN1,IN2,IN3,IN4 */
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .muxsel = { 2, 3, 1, 0 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .needs_tvaudio = 0,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Helmroos Harri <harri.helmroos@pp.inet.fi> */
.name = "Tekram M205 PRO",
@@ -1982,6 +2108,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.svhs = 2,
.needs_tvaudio = 0,
.gpiomask = 0x68,
@@ -2004,6 +2131,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
.has_radio = 1,
},{
@@ -2026,6 +2154,8 @@ struct tvcard bttv_tvcards[] = {
.pll = PLL_28,
.needs_tvaudio = 0,
.muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Spirit TV Tuner from http://spiritmodems.com.au */
/* Stafford Goodsell <surge@goliath.homeunix.org> */
@@ -2038,23 +2168,25 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 1, 1 },
.audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00},
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
.no_msp34xx = 1,
.no_tda9875 = 1,
},{
/* Wolfram Joost <wojo@frokaschwei.de> */
- .name = "AVerMedia AVerTV DVB-T 771",
- .video_inputs = 2,
- .svhs = 1,
- .tuner = -1,
- .tuner_type = TUNER_ABSENT,
- .muxsel = { 3 , 3 },
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .pll = PLL_28,
- .has_dvb = 1,
- .no_gpioirq = 1,
- .has_remote = 1,
+ .name = "AVerMedia AVerTV DVB-T 771",
+ .video_inputs = 2,
+ .svhs = 1,
+ .tuner = -1,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
+ .muxsel = { 3 , 3 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .pll = PLL_28,
+ .has_dvb = 1,
+ .no_gpioirq = 1,
+ .has_remote = 1,
},{
/* ---- card 0x7c ---------------------------------- */
/* Matt Jesson <dvb@jesson.eclipse.co.uk> */
@@ -2069,6 +2201,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
.no_gpioirq = 1,
.has_remote = 1,
@@ -2081,12 +2214,13 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0x0,
.muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3 },
+ 3, 3, 3, 3, 3, 3, 3, 3 },
.muxsel_hook = sigmaSQ_muxsel,
.audiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* andre.schwarz@matrix-vision.de */
.name = "MATRIX Vision Sigma-SLC",
@@ -2101,6 +2235,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* BTTV_APAC_VIEWCOMP */
/* Attila Kondoros <attila.kondoros@chello.hu> */
@@ -2116,13 +2251,14 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */
.has_radio = 1, /* not every card has radio */
},{
/* ---- card 0x80 ---------------------------------- */
/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
- .name = "DVICO FusionHDTV DVB-T Lite",
+ .name = "DViCO FusionHDTV DVB-T Lite",
.tuner = -1,
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -2131,6 +2267,7 @@ struct tvcard bttv_tvcards[] = {
.no_video = 1,
.has_dvb = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Steven <photon38@pchome.com.tw> */
.name = "V-Gear MyVCD",
@@ -2144,62 +2281,65 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 0,
- // .has_remote = 1,
},{
/* Rick C <cryptdragoon@gmail.com> */
- .name = "Super TV Tuner",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 0},
- .tuner_type = TUNER_PHILIPS_NTSC,
- .gpiomask = 0x008007,
- .audiomux = { 0, 0x000001,0,0, 0},
- .needs_tvaudio = 1,
- .has_radio = 1,
-},{
- /* Chris Fanning <video4linux@haydon.net> */
- .name = "Tibet Systems 'Progress DVR' CS16",
- .video_inputs = 16,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
- .pll = PLL_28,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = -1,
- .muxsel_hook = tibetCS16_muxsel,
+ .name = "Super TV Tuner",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0},
+ .tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
+ .gpiomask = 0x008007,
+ .audiomux = { 0, 0x000001,0,0, 0},
+ .needs_tvaudio = 1,
+ .has_radio = 1,
+},{
+ /* Chris Fanning <video4linux@haydon.net> */
+ .name = "Tibet Systems 'Progress DVR' CS16",
+ .video_inputs = 16,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ .pll = PLL_28,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .muxsel_hook = tibetCS16_muxsel,
},
{
/* Bill Brack <wbrack@mmm.com.hk> */
/*
- * Note that, because of the card's wiring, the "master"
- * BT878A chip (i.e. the one which controls the analog switch
- * and must use this card type) is the 2nd one detected. The
- * other 3 chips should use card type 0x85, whose description
- * follows this one. There is a EEPROM on the card (which is
- * connected to the I2C of one of those other chips), but is
- * not currently handled. There is also a facility for a
- * "monitor", which is also not currently implemented.
- */
- .name = "Kodicom 4400R (master)",
+ * Note that, because of the card's wiring, the "master"
+ * BT878A chip (i.e. the one which controls the analog switch
+ * and must use this card type) is the 2nd one detected. The
+ * other 3 chips should use card type 0x85, whose description
+ * follows this one. There is a EEPROM on the card (which is
+ * connected to the I2C of one of those other chips), but is
+ * not currently handled. There is also a facility for a
+ * "monitor", which is also not currently implemented.
+ */
+ .name = "Kodicom 4400R (master)",
.video_inputs = 16,
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
/* GPIO bits 0-9 used for analog switch:
- * 00 - 03: camera selector
- * 04 - 06: channel (controller) selector
- * 07: data (1->on, 0->off)
- * 08: strobe
- * 09: reset
- * bit 16 is input from sync separator for the channel
- */
+ * 00 - 03: camera selector
+ * 04 - 06: channel (controller) selector
+ * 07: data (1->on, 0->off)
+ * 08: strobe
+ * 09: reset
+ * bit 16 is input from sync separator for the channel
+ */
.gpiomask = 0x0003ff,
.no_gpioirq = 1,
.muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
@@ -2212,15 +2352,16 @@ struct tvcard bttv_tvcards[] = {
{
/* Bill Brack <wbrack@mmm.com.hk> */
/* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
- * one which controls the analog switch, and must use the card type)
- * is the 2nd one detected. The other 3 chips should use this card
- * type
- */
+ * one which controls the analog switch, and must use the card type)
+ * is the 2nd one detected. The other 3 chips should use this card
+ * type
+ */
.name = "Kodicom 4400R (slave)",
.video_inputs = 16,
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
.gpiomask = 0x010000,
.no_gpioirq = 1,
@@ -2232,18 +2373,51 @@ struct tvcard bttv_tvcards[] = {
.muxsel_hook = kodicom4400r_muxsel,
},
{
- /* ---- card 0x85---------------------------------- */
- /* Michael Henson <mhenson@clarityvi.com> */
- /* Adlink RTV24 with special unlock codes */
- .name = "Adlink RTV24",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 0},
- .tuner_type = -1,
- .pll = PLL_28,
-
+ /* ---- card 0x86---------------------------------- */
+ /* Michael Henson <mhenson@clarityvi.com> */
+ /* Adlink RTV24 with special unlock codes */
+ .name = "Adlink RTV24",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0},
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .pll = PLL_28,
+},
+{
+ /* ---- card 0x87---------------------------------- */
+ /* Michael Krufky <mkrufky@m1k.net> */
+ .name = "DViCO FusionHDTV 5 Lite",
+ .tuner = 0,
+ .tuner_type = TUNER_LG_TDVS_H062F,
+ .tuner_addr = ADDR_UNSET,
+ .video_inputs = 2,
+ .audio_inputs = 1,
+ .svhs = 2,
+ .muxsel = { 2, 3 },
+ .gpiomask = 0x00e00007,
+ .audiomux = { 0x00400005, 0, 0, 0, 0, 0 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+},{
+ /* ---- card 0x88---------------------------------- */
+ /* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */
+ .name = "Acorp Y878F",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x01fe00,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = TUNER_YMEC_TVF66T5_B_DFF,
+ .tuner_addr = 0xc1 >>1,
+ .has_radio = 1,
}};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2355,32 +2529,32 @@ static void flyvideo_gpio(struct bttv *btv)
int tuner=-1,ttype;
gpio_inout(0xffffff, 0);
- udelay(8); // without this we would see the 0x1800 mask
+ udelay(8); /* without this we would see the 0x1800 mask */
gpio = gpio_read();
/* FIXME: must restore OUR_EN ??? */
- // all cards provide GPIO info, some have an additional eeprom
- // LR50: GPIO coding can be found lower right CP1 .. CP9
- // CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
- // GPIO14-12: n.c.
- // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-
- // lowest 3 bytes are remote control codes (no handshake needed)
- // xxxFFF: No remote control chip soldered
- // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
- // Note: Some bits are Audio_Mask !
+ /* all cards provide GPIO info, some have an additional eeprom
+ * LR50: GPIO coding can be found lower right CP1 .. CP9
+ * CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
+ * GPIO14-12: n.c.
+ * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
+ * lowest 3 bytes are remote control codes (no handshake needed)
+ * xxxFFF: No remote control chip soldered
+ * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
+ * Note: Some bits are Audio_Mask !
+ */
ttype=(gpio&0x0f0000)>>16;
switch(ttype) {
- case 0x0: tuner=2; // NTSC, e.g. TPI8NSR11P
+ case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
break;
- case 0x2: tuner=39;// LG NTSC (newer TAPC series) TAPC-H701P
+ case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
break;
- case 0x4: tuner=5; // Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216
+ case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
break;
- case 0x6: tuner=37; // LG PAL (newer TAPC series) TAPC-G702P
+ case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
break;
- case 0xC: tuner=3; // Philips SECAM(+PAL) FQ1216ME or FI1216MF
+ case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
@@ -2388,15 +2562,16 @@ static void flyvideo_gpio(struct bttv *btv)
has_remote = gpio & 0x800000;
has_radio = gpio & 0x400000;
- // unknown 0x200000;
- // unknown2 0x100000;
- is_capture_only = !(gpio & 0x008000); //GPIO15
+ /* unknown 0x200000;
+ * unknown2 0x100000; */
+ is_capture_only = !(gpio & 0x008000); /* GPIO15 */
has_tda9820_tda9821 = !(gpio & 0x004000);
- is_lr90 = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only)
- // gpio & 0x001000 // output bit for audio routing
+ is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
+ /*
+ * gpio & 0x001000 output bit for audio routing */
if(is_capture_only)
- tuner=4; // No tuner present
+ tuner=4; /* No tuner present */
printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
@@ -2404,15 +2579,15 @@ static void flyvideo_gpio(struct bttv *btv)
btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
is_capture_only?"yes":"no ");
- if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through
+ if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */
btv->tuner_type = tuner;
btv->has_radio = has_radio;
- // LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
- // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
- // Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute
+ /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
+ * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
+ * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio;
- //todo: if(has_tda9874) btv->audio_hook = fv2000s_audio;
+ /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */
}
static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1,
@@ -2633,6 +2808,8 @@ void __devinit bttv_init_card1(struct bttv *btv)
void __devinit bttv_init_card2(struct bttv *btv)
{
int tda9887;
+ int addr=ADDR_UNSET;
+
btv->tuner_type = -1;
if (BTTV_UNKNOWN == btv->c.type) {
@@ -2773,9 +2950,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->pll.pll_current = -1;
/* tuner configuration (from card list / autodetect / insmod option) */
- if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
+ if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+ addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+ if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
if(UNSET == btv->tuner_type)
- btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
+ btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
if (UNSET != tuner[btv->c.nr])
btv->tuner_type = tuner[btv->c.nr];
printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type);
@@ -2787,7 +2967,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = btv->tuner_type;
- tun_setup.addr = ADDR_UNSET;
+ tun_setup.addr = addr;
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
}
@@ -2880,7 +3060,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&tv, eeprom_data);
+ tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
}
@@ -2902,7 +3082,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
btv->mbox_csel = 1 << 10;
freq=88000/62.5;
- tea5757_write(btv, 5 * freq + 0x358); // write 0x1ed8
+ tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
if (0x1ed8 == tea5757_read(btv)) {
printk("bttv%d: Terratec Active Radio Upgrade found.\n",
btv->c.nr);
@@ -3073,7 +3253,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
case 0x0060:
case 0x0070:
btv->c.type = BTTV_OSPREY2x0;
- //enable output on select control lines
+ /* enable output on select control lines */
gpio_inout(0xffffff,0x000303);
break;
default:
@@ -3105,7 +3285,7 @@ static int tuner_1_table[] = {
TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
- TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
+ TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
static void __devinit avermedia_eeprom(struct bttv *btv)
@@ -3126,7 +3306,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
if (tuner_make == 4)
if(tuner_format == 0x09)
- tuner = TUNER_LG_NTSC_NEW_TAPC; // TAPC-G702P
+ tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
@@ -3143,7 +3323,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
- // fix up our card entry
+ /* fix up our card entry */
if(norm==VIDEO_MODE_NTSC) {
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x957fff;
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x957fff;
@@ -3154,7 +3334,7 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm)
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x947fff;
dprintk("bttv_tda9880_setnorm to PAL\n");
}
- // set GPIO according
+ /* set GPIO according */
gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].audiomux[btv->audio]);
}
@@ -3447,7 +3627,7 @@ static int tea5757_read(struct bttv *btv)
udelay(10);
timeout= jiffies + HZ;
- // wait for DATA line to go low; error if it doesn't
+ /* wait for DATA line to go low; error if it doesn't */
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
schedule();
if (bus_in(btv,btv->mbox_data)) {
@@ -3574,8 +3754,8 @@ gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set)
con = 0x300;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x200;
-// if (v->mode & VIDEO_SOUND_MONO)
-// con = 0x100;
+/* if (v->mode & VIDEO_SOUND_MONO)
+ * con = 0x100; */
gpio_bits(0x300, con);
} else {
v->mode = VIDEO_SOUND_STEREO |
@@ -3718,7 +3898,7 @@ lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
}
}
-// TDA9821 on TerraTV+ Bt848, Bt878
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
static void
terratv_audio(struct bttv *btv, struct video_audio *v, int set)
{
@@ -3818,7 +3998,7 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
- val = 0x1080; //-dk-???: 0x0880, 0x0080, 0x1800 ...
+ val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
}
if (val != 0xffff) {
gpio_bits(0x1800, val);
@@ -3869,10 +4049,10 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0xffffff;
- //btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN);
+ /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
if (set) {
- //btor(***, BT848_GPIO_OUT_EN);
+ /* btor(***, BT848_GPIO_OUT_EN); */
if (v->mode & VIDEO_SOUND_LANG1)
con = 0x00000000;
if (v->mode & VIDEO_SOUND_LANG2)
@@ -4079,14 +4259,14 @@ static void kodicom4400r_init(struct bttv *btv)
master[btv->c.nr+2] = btv;
}
-// The Grandtec X-Guard framegrabber card uses two Dual 4-channel
-// video multiplexers to provide up to 16 video inputs. These
-// multiplexers are controlled by the lower 8 GPIO pins of the
-// bt878. The multiplexers probably Pericom PI5V331Q or similar.
-
-// xxx0 is pin xxx of multiplexer U5,
-// yyy1 is pin yyy of multiplexer U2
+/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+ * video multiplexers to provide up to 16 video inputs. These
+ * multiplexers are controlled by the lower 8 GPIO pins of the
+ * bt878. The multiplexers probably Pericom PI5V331Q or similar.
+ * xxx0 is pin xxx of multiplexer U5,
+ * yyy1 is pin yyy of multiplexer U2
+ */
#define ENA0 0x01
#define ENB0 0x02
#define ENA1 0x04
@@ -4157,14 +4337,14 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
static void ivc120_muxsel(struct bttv *btv, unsigned int input)
{
- // Simple maths
+ /* Simple maths */
int key = input % 4;
int matrix = input / 4;
dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
btv->c.nr, input, matrix, key);
- // Handles the input selection on the TDA8540's
+ /* Handles the input selection on the TDA8540's */
bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
((matrix == 3) ? (key | key << 2) : 0x00), 1);
bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
@@ -4174,17 +4354,17 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
((matrix == 2) ? (key | key << 2) : 0x00), 1);
- // Handles the output enables on the TDA8540's
+ /* Handles the output enables on the TDA8540's */
bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
- ((matrix == 3) ? 0x03 : 0x00), 1); // 13 - 16
+ ((matrix == 3) ? 0x03 : 0x00), 1); /* 13 - 16 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
- ((matrix == 0) ? 0x03 : 0x00), 1); // 1-4
+ ((matrix == 0) ? 0x03 : 0x00), 1); /* 1-4 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
- ((matrix == 1) ? 0x03 : 0x00), 1); // 5-8
+ ((matrix == 1) ? 0x03 : 0x00), 1); /* 5-8 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
- ((matrix == 2) ? 0x03 : 0x00), 1); // 9-12
+ ((matrix == 2) ? 0x03 : 0x00), 1); /* 9-12 */
- // Selects MUX0 for input on the 878
+ /* Selects MUX0 for input on the 878 */
btaor((0)<<5, ~(3<<5), BT848_IFORM);
}
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index eee9322ce21b..a564321db2f0 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $
bttv - Bt848 frame grabber driver
@@ -42,6 +41,9 @@
#include "bttvp.h"
+#include "rds.h"
+
+
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
@@ -3128,15 +3130,12 @@ static int radio_open(struct inode *inode, struct file *file)
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
down(&btv->lock);
- if (btv->radio_user) {
- up(&btv->lock);
- return -EBUSY;
- }
+
btv->radio_user++;
+
file->private_data = btv;
- i2c_vidiocschan(btv);
- bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
+ bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
audio_mux(btv,AUDIO_RADIO);
up(&btv->lock);
@@ -3145,9 +3144,13 @@ static int radio_open(struct inode *inode, struct file *file)
static int radio_release(struct inode *inode, struct file *file)
{
- struct bttv *btv = file->private_data;
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
btv->radio_user--;
+
+ bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+
return 0;
}
@@ -3203,13 +3206,42 @@ static int radio_ioctl(struct inode *inode, struct file *file,
return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
}
+static ssize_t radio_read(struct file *file, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
+ cmd.block_count = count/3;
+ cmd.buffer = data;
+ cmd.instance = file;
+ cmd.result = -ENODEV;
+
+ bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
+
+ return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
+ cmd.instance = file;
+ cmd.event_list = wait;
+ cmd.result = -ENODEV;
+ bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
+
+ return cmd.result;
+}
+
static struct file_operations radio_fops =
{
.owner = THIS_MODULE,
.open = radio_open,
+ .read = radio_read,
.release = radio_release,
.ioctl = radio_ioctl,
.llseek = no_llseek,
+ .poll = radio_poll,
};
static struct video_device radio_template =
@@ -4047,7 +4079,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
struct bttv_buffer_set idle;
unsigned long flags;
- dprintk("bttv%d: suspend %d\n", btv->c.nr, state);
+ dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4080,15 +4112,29 @@ static int bttv_resume(struct pci_dev *pci_dev)
{
struct bttv *btv = pci_get_drvdata(pci_dev);
unsigned long flags;
+ int err;
dprintk("bttv%d: resume\n", btv->c.nr);
/* restore pci state */
if (btv->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+ btv->c.nr);
+ return err;
+ }
btv->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err=pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ pci_disable_device(pci_dev);
+ printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+ btv->c.nr);
+ btv->state.disabled = 1;
+ return err;
+ }
+
pci_restore_state(pci_dev);
/* restore bt878 state */
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index 77320cdf205f..6b280c03e398 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-gpio.c,v 1.7 2005/02/16 12:14:10 kraxel Exp $
bttv-gpio.c -- gpio sub drivers
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 234a85563769..e684df37eb0e 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-i2c.c,v 1.25 2005/07/05 17:37:35 nsh Exp $
bttv-i2c.c -- all the i2c code is here
@@ -109,7 +108,7 @@ static struct i2c_adapter bttv_i2c_adap_sw_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("bt848"),
+ .name = "bt848",
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
@@ -270,8 +269,6 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int
}
static struct i2c_algorithm bttv_algo = {
- .name = "bt878",
- .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.master_xfer = bttv_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
@@ -282,8 +279,8 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("bt878"),
- .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
+ .name = "bt878",
+ .id = I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
.client_register = attach_inform,
};
@@ -298,7 +295,7 @@ static int attach_inform(struct i2c_client *client)
if (bttv_debug)
printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
btv->c.nr,client->driver->name,client->addr,
- i2c_clientname(client));
+ client->name);
if (!client->driver->command)
return 0;
@@ -326,7 +323,7 @@ void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
}
static struct i2c_client bttv_i2c_client_template = {
- I2C_DEVNAME("bttv internal"),
+ .name = "bttv internal",
};
@@ -383,6 +380,7 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
}
static char *i2c_devs[128] = {
+ [ 0x1c >> 1 ] = "lgdt330x",
[ 0x30 >> 1 ] = "IR (hauppauge)",
[ 0x80 >> 1 ] = "msp34xx",
[ 0x86 >> 1 ] = "tda9887",
diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c
index f7b5543a96a1..e8aada772b89 100644
--- a/drivers/media/video/bttv-if.c
+++ b/drivers/media/video/bttv-if.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-if.c,v 1.4 2004/11/17 18:47:47 kraxel Exp $
bttv-if.c -- old gpio interface to other kernel modules
don't use in new code, will go away in 2.7
diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
index 9ed21fd190c6..a5ed99b89445 100644
--- a/drivers/media/video/bttv-risc.c
+++ b/drivers/media/video/bttv-risc.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-risc.c,v 1.10 2004/11/19 18:07:12 kraxel Exp $
bttv-risc.c -- interfaces to other kernel modules
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
index 06f3e62b3e8d..f4f58c60f152 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bttv-vbi.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-vbi.c,v 1.9 2005/01/13 17:22:33 kraxel Exp $
bttv - Bt848 frame grabber driver
vbi interface
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index f2af9e1454f0..d254e90e3bb9 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,4 @@
/*
- * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $
*
* bttv - Bt848 frame grabber driver
*
@@ -218,6 +217,8 @@ struct tvcard
#define PLL_35 2
unsigned int tuner_type;
+ unsigned int tuner_addr;
+
unsigned int has_radio;
void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index aab094bc243d..9b0b7ca035f8 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -1,5 +1,4 @@
/*
- $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $
bttv - Bt848 frame grabber driver
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index cdda423386c5..9774e94d1e7d 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -445,10 +445,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
ucpia->sbuf[1].urb = NULL;
}
- if (ucpia->sbuf[1].data) {
- kfree(ucpia->sbuf[1].data);
- ucpia->sbuf[1].data = NULL;
- }
+ kfree(ucpia->sbuf[1].data);
+ ucpia->sbuf[1].data = NULL;
if (ucpia->sbuf[0].urb) {
usb_kill_urb(ucpia->sbuf[0].urb);
@@ -456,10 +454,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
ucpia->sbuf[0].urb = NULL;
}
- if (ucpia->sbuf[0].data) {
- kfree(ucpia->sbuf[0].data);
- ucpia->sbuf[0].data = NULL;
- }
+ kfree(ucpia->sbuf[0].data);
+ ucpia->sbuf[0].data = NULL;
}
static int cpia_usb_close(void *privdata)
@@ -623,20 +619,14 @@ static void cpia_disconnect(struct usb_interface *intf)
ucpia->curbuff = ucpia->workbuff = NULL;
- if (ucpia->buffers[2]) {
- vfree(ucpia->buffers[2]);
- ucpia->buffers[2] = NULL;
- }
+ vfree(ucpia->buffers[2]);
+ ucpia->buffers[2] = NULL;
- if (ucpia->buffers[1]) {
- vfree(ucpia->buffers[1]);
- ucpia->buffers[1] = NULL;
- }
+ vfree(ucpia->buffers[1]);
+ ucpia->buffers[1] = NULL;
- if (ucpia->buffers[0]) {
- vfree(ucpia->buffers[0]);
- ucpia->buffers[0] = NULL;
- }
+ vfree(ucpia->buffers[0]);
+ ucpia->buffers[0] = NULL;
cam->lowlevel_data = NULL;
kfree(ucpia);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 4f39688f780a..0c0c59e94774 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -62,7 +61,6 @@ static LIST_HEAD(cx8802_devlist);
#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
/* Firmware API commands */
-/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
#define IVTV_API_STD_TIMEOUT 500
#define BLACKBIRD_API_PING 0x80
@@ -696,7 +694,6 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
/* assign stream type */
blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
- /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
/* assign output port */
blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
@@ -824,7 +821,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
+ /* initialize the video input */
+ blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0);
msleep(1);
@@ -833,11 +831,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
msleep(1);
- /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
+ /* start capturing to the host interface */
+ /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */
blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE
- ); /* start capturing to the host interface */
+ );
msleep(10);
blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
@@ -851,8 +850,8 @@ static int bb_buf_setup(struct videobuf_queue *q,
{
struct cx8802_fh *fh = q->priv_data;
- fh->dev->ts_packet_size = 512;
- fh->dev->ts_packet_count = 100;
+ fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
+ fh->dev->ts_packet_count = 32; /* was: 100 */
*size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
if (0 == *count)
@@ -900,12 +899,36 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
{
struct cx8802_fh *fh = file->private_data;
struct cx8802_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
if (debug > 1)
- cx88_print_ioctl(dev->core->name,cmd);
+ cx88_print_ioctl(core->name,cmd);
switch (cmd) {
+ /* --- capabilities ------------------------------------------ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap,0,sizeof(*cap));
+ strcpy(cap->driver, "cx88_blackbird");
+ strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+ sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+ cap->version = CX88_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
+ 0;
+ if (UNSET != core->tuner_type)
+ cap->capabilities |= V4L2_CAP_TUNER;
+
+ return 0;
+ }
+
/* --- capture ioctls ---------------------------------------- */
case VIDIOC_ENUM_FMT:
{
@@ -935,7 +958,11 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage = 188 * 4 * 1024; /* 1024 * 512 */ /* FIXME: BUFFER_SIZE */;
+ f->fmt.pix.colorspace = 0;
+ return 0;
}
/* --- streaming capture ------------------------------------- */
@@ -959,15 +986,25 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
return videobuf_streamoff(&fh->mpegq);
default:
- return -EINVAL;
+ return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
}
return 0;
}
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
+static unsigned int mpeg_translate_ioctl(unsigned int cmd)
+{
+ return cmd;
+}
+
static int mpeg_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+ cmd = cx88_ioctl_translator( cmd );
+ return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
}
static int mpeg_open(struct inode *inode, struct file *file)
@@ -1135,7 +1172,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
dev->pci = pci_dev;
dev->core = core;
dev->width = 720;
- dev->height = 480;
+ dev->height = 576;
err = cx8802_init_common(dev);
if (0 != err)
@@ -1148,6 +1185,9 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
list_add_tail(&dev->devlist,&cx8802_devlist);
blackbird_register_video(dev);
+
+ /* initial device configuration: needed ? */
+
return 0;
fail_free:
@@ -1202,6 +1242,8 @@ static int blackbird_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
+ cx88_ioctl_hook = mpeg_do_ioctl;
+ cx88_ioctl_translator = mpeg_translate_ioctl;
return pci_register_driver(&blackbird_pci_driver);
}
@@ -1213,6 +1255,9 @@ static void blackbird_fini(void)
module_init(blackbird_init);
module_exit(blackbird_fini);
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index ebf02a7f81e8..4da91d535a5b 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -499,9 +498,6 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
- },{
- .type = CX88_VMUX_SVIDEO,
- .vmux = 2,
}},
.dvb = 1,
},
@@ -614,12 +610,12 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0xed12, // internal decoder
+ .gpio0 = 0xed12, /* internal decoder */
.gpio2 = 0x00ff,
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
- .gpio0 = 0xff01, // mono from tuner chip
+ .gpio0 = 0xff01, /* mono from tuner chip */
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -715,19 +711,18 @@ struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0f0d,
+ .gpio0 = 0x97ed,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x97e9,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x97e9,
}},
.dvb = 1,
},
@@ -765,20 +760,21 @@ struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0f0d,
+ .gpio0 = 0x87fd,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x87f9,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x87f9,
}},
+ .dvb = 1,
},
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -949,7 +945,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&tv, eeprom_data);
+ tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
core->tuner_type = tv.tuner_type;
core->has_radio = tv.has_radio;
}
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 5e868f5cd0c0..dc5c5c1f3461 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-core.c,v 1.33 2005/07/07 14:17:47 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
@@ -876,7 +875,7 @@ static int set_tvaudio(struct cx88_core *core)
cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
cx88_set_tvaudio(core);
- // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
+ /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
@@ -1087,10 +1086,17 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
core->pci_irqmask = 0x00fc00;
+ init_MUTEX(&core->lock);
core->nr = cx88_devcount++;
sprintf(core->name,"cx88[%d]",core->nr);
if (0 != get_ressources(core,pci)) {
+ printk(KERN_ERR "CORE %s No more PCI ressources for "
+ "subsystem: %04x:%04x, board: %s\n",
+ core->name,pci->subsystem_vendor,
+ pci->subsystem_device,
+ cx88_boards[core->board].name);
+
cx88_devcount--;
goto fail_free;
}
@@ -1114,11 +1120,11 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
core->board = CX88_BOARD_UNKNOWN;
cx88_card_list(core,pci);
}
- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
- core->name,pci->subsystem_vendor,
- pci->subsystem_device,cx88_boards[core->board].name,
- core->board, card[core->nr] == core->board ?
- "insmod option" : "autodetected");
+ printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ core->name,pci->subsystem_vendor,
+ pci->subsystem_device,cx88_boards[core->board].name,
+ core->board, card[core->nr] == core->board ?
+ "insmod option" : "autodetected");
core->tuner_type = tuner[core->nr];
core->radio_type = radio[core->nr];
@@ -1202,4 +1208,5 @@ EXPORT_SYMBOL(cx88_core_put);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 78d223257a68..4334744652de 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
@@ -29,7 +28,7 @@
#include <linux/kthread.h>
#include <linux/file.h>
#include <linux/suspend.h>
-#include <linux/config.h>
+
#include "cx88.h"
#include "dvb-pll.h"
@@ -210,16 +209,24 @@ static struct or51132_config pchdtv_hd3000 = {
static int lgdt330x_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params)
{
+ /* FIXME make this routine use the tuner-simple code.
+ * It could probably be shared with a number of ATSC
+ * frontends. Many share the same tuner with analog TV. */
+
struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
u8 buf[4];
struct i2c_msg msg =
{ .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
int err;
- dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0);
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
+ dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
- if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
printk(KERN_WARNING "cx88-dvb: %s error "
"(addr %02x <- %02x, err = %i)\n",
__FUNCTION__, buf[0], buf[1], err);
@@ -228,6 +235,13 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe,
else
return -EREMOTEIO;
}
+ if (core->tuner_type == TUNER_LG_TDVS_H062F) {
+ /* Set the Auxiliary Byte. */
+ buf[2] &= ~0x20;
+ buf[2] |= 0x18;
+ buf[3] = 0x50;
+ i2c_transfer(&core->i2c_adap, &msg, 1);
+ }
return 0;
}
@@ -261,6 +275,14 @@ static struct lgdt330x_config fusionhdtv_3_gold = {
.pll_set = lgdt330x_pll_set,
.set_ts_params = lgdt330x_set_ts_param,
};
+
+static struct lgdt330x_config fusionhdtv_5_gold = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+ .pll_set = lgdt330x_pll_set,
+ .set_ts_params = lgdt330x_set_ts_param,
+};
#endif
static int dvb_register(struct cx8802_dev *dev)
@@ -346,6 +368,22 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
}
break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+ dev->ts_gen_cntrl = 0x08;
+ {
+ /* Do a hardware reset of chip before using it. */
+ struct cx88_core *core = dev->core;
+
+ cx_clear(MO_GP0_IO, 1);
+ mdelay(100);
+ cx_set(MO_GP0_IO, 1);
+ mdelay(200);
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
+ dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
+ &dev->core->i2c_adap);
+ }
+ break;
#endif
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
@@ -362,10 +400,8 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
}
- /* Copy the board name into the DVB structure */
- strlcpy(dev->dvb.frontend->ops->info.name,
- cx88_boards[dev->core->board].name,
- sizeof(dev->dvb.frontend->ops->info.name));
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
/* register everything */
return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index a628a55299c6..761cebd40dbd 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,4 @@
/*
- $Id: cx88-i2c.c,v 1.30 2005/07/25 05:10:13 mkrufky Exp $
cx88-i2c.c -- all the i2c code is here
@@ -95,7 +94,7 @@ static int attach_inform(struct i2c_client *client)
struct cx88_core *core = i2c_get_adapdata(client->adapter);
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name,client->addr,i2c_clientname(client));
+ client->driver->name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -128,7 +127,7 @@ static int detach_inform(struct i2c_client *client)
{
struct cx88_core *core = i2c_get_adapdata(client->adapter);
- dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client));
+ dprintk(1, "i2c detach [client=%s]\n", client->name);
return 0;
}
@@ -152,7 +151,7 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
/* ----------------------------------------------------------------------- */
static struct i2c_adapter cx8800_i2c_adap_template = {
- I2C_DEVNAME("cx2388x"),
+ .name = "cx2388x",
.owner = THIS_MODULE,
.id = I2C_HW_B_CX2388x,
.client_register = attach_inform,
@@ -160,7 +159,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = {
};
static struct i2c_client cx8800_i2c_client_template = {
- I2C_DEVNAME("cx88xx internal"),
+ .name = "cx88xx internal",
};
static char *i2c_devs[128] = {
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 214887798192..d81b21d6e05d 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-input.c,v 1.15 2005/07/07 13:58:38 mchehab Exp $
*
* Device driver for GPIO attached remote control interfaces
* on Conexant 2388x based TV/DVB cards.
@@ -212,6 +211,53 @@ static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
+/* Cinergy 1400 DVB-T */
+static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
+ [0x01] = KEY_POWER,
+ [0x02] = KEY_1,
+ [0x03] = KEY_2,
+ [0x04] = KEY_3,
+ [0x05] = KEY_4,
+ [0x06] = KEY_5,
+ [0x07] = KEY_6,
+ [0x08] = KEY_7,
+ [0x09] = KEY_8,
+ [0x0a] = KEY_9,
+ [0x0c] = KEY_0,
+
+ [0x0b] = KEY_VIDEO,
+ [0x0d] = KEY_REFRESH,
+ [0x0e] = KEY_SELECT,
+ [0x0f] = KEY_EPG,
+ [0x10] = KEY_UP,
+ [0x11] = KEY_LEFT,
+ [0x12] = KEY_OK,
+ [0x13] = KEY_RIGHT,
+ [0x14] = KEY_DOWN,
+ [0x15] = KEY_TEXT,
+ [0x16] = KEY_INFO,
+
+ [0x17] = KEY_RED,
+ [0x18] = KEY_GREEN,
+ [0x19] = KEY_YELLOW,
+ [0x1a] = KEY_BLUE,
+
+ [0x1b] = KEY_CHANNELUP,
+ [0x1c] = KEY_VOLUMEUP,
+ [0x1d] = KEY_MUTE,
+ [0x1e] = KEY_VOLUMEDOWN,
+ [0x1f] = KEY_CHANNELDOWN,
+
+ [0x40] = KEY_PAUSE,
+ [0x4c] = KEY_PLAY,
+ [0x58] = KEY_RECORD,
+ [0x54] = KEY_PREVIOUS,
+ [0x48] = KEY_STOP,
+ [0x5c] = KEY_NEXT,
+};
+
+/* ---------------------------------------------------------------------- */
+
struct cx88_IR {
struct cx88_core *core;
struct input_dev input;
@@ -241,7 +287,7 @@ module_param(ir_debug, int, 0644); /* debug level [IR] */
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define ir_dprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
+ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
/* ---------------------------------------------------------------------- */
@@ -329,6 +375,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keyup = 0x60;
ir->polling = 50; /* ms */
break;
+ case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ ir_codes = ir_codes_cinergy_1400;
+ ir_type = IR_TYPE_PD;
+ ir->sampling = 1;
+ break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
ir_codes = ir_codes_hauppauge_new;
@@ -394,6 +445,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->input.id.vendor = pci->vendor;
ir->input.id.product = pci->device;
}
+ ir->input.dev = &pci->dev;
/* record handles to ourself */
ir->core = core;
@@ -445,7 +497,7 @@ int cx88_ir_fini(struct cx88_core *core)
void cx88_ir_irq(struct cx88_core *core)
{
struct cx88_IR *ir = core->ir;
- u32 samples, rc5;
+ u32 samples, ircode;
int i;
if (NULL == ir)
@@ -477,13 +529,44 @@ void cx88_ir_irq(struct cx88_core *core)
/* decode it */
switch (core->board) {
+ case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
+
+ if (ircode == 0xffffffff) { /* decoding error */
+ ir_dprintk("pulse distance decoding error\n");
+ break;
+ }
+
+ ir_dprintk("pulse distance decoded: %x\n", ircode);
+
+ if (ircode == 0) { /* key still pressed */
+ ir_dprintk("pulse distance decoded repeat code\n");
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
+ }
+
+ if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+ ir_dprintk("pulse distance decoded wrong address\n");
+ break;
+ }
+
+ if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
+ ir_dprintk("pulse distance decoded wrong check sum\n");
+ break;
+ }
+
+ ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);
+
+ ir_input_keydown(&ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
- rc5 = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
- ir_dprintk("biphase decoded: %x\n", rc5);
- if ((rc5 & 0xfffff000) != 0x3000)
+ ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+ ir_dprintk("biphase decoded: %x\n", ircode);
+ if ((ircode & 0xfffff000) != 0x3000)
break;
- ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
+ ir_input_keydown(&ir->input, &ir->ir, ircode & 0x3f, ircode);
ir->release = jiffies + msecs_to_jiffies(120);
break;
}
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index fe2767c0ff94..ee2300e1ae0b 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-mpeg.c,v 1.31 2005/07/07 14:17:47 mchehab Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
@@ -73,11 +72,15 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
udelay(100);
cx_write(MO_PINMUX_IO, 0x00);
cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
- if ((core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q) ||
- (core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T)) {
+ switch (core->board) {
+ case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+ case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
cx_write(TS_SOP_STAT, 1<<13);
- } else {
+ break;
+ default:
cx_write(TS_SOP_STAT, 0x00);
+ break;
}
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
udelay(100);
@@ -86,12 +89,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
if (cx88_boards[core->board].blackbird) {
cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
- // cx_write(TS_F2_CMD_STAT_MM, 0x2900106); /* F2_CMD_STAT_MM defaults + master + memory space */
cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
udelay(100);
cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
- //cx_write(TS_HW_SOP_CNTRL, 0x2F0BC0); /* mpeg start byte ts: 0x2F0BC0 ? */
cx_write(TS_VALERR_CNTRL, 0x2000);
cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
@@ -106,7 +107,6 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
dprintk( 0, "setting the interrupt mask\n" );
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
cx_set(MO_TS_INTMSK, 0x1f0011);
- //cx_write(MO_TS_INTMSK, 0x0f0011);
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
@@ -206,7 +206,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(0,"[%p/%d] %s - first active\n",
buf, buf->vb.i, __FUNCTION__);
- //udelay(100);
} else {
dprintk( 1, "queue is not empty - append to active\n" );
@@ -217,7 +216,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __FUNCTION__);
- //udelay(100);
}
}
@@ -387,7 +385,6 @@ int cx8802_init_common(struct cx8802_dev *dev)
dev->pci_lat,pci_resource_start(dev->pci,0));
/* initialize driver struct */
- init_MUTEX(&dev->lock);
spin_lock_init(&dev->slock);
/* init dma queue */
@@ -458,14 +455,28 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
int cx8802_resume_common(struct pci_dev *pci_dev)
{
- struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
+ int err;
if (dev->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ dev->core->name);
+ return err;
+ }
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err=pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ dev->core->name);
+ pci_disable_device(pci_dev);
+ dev->state.disabled = 1;
+
+ return err;
+ }
pci_restore_state(pci_dev);
/* FIXME: re-initialize hardware */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index 37f82662d265..0a3a62fc9bbb 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -1,5 +1,4 @@
/*
- $Id: cx88-reg.h,v 1.8 2005/07/07 13:58:38 mchehab Exp $
cx88x-hw.h - CX2388x register offsets
@@ -40,6 +39,29 @@
#define CX88X_EN_TBFX 0x02
#define CX88X_EN_VSFX 0x04
+/* ---------------------------------------------------------------------- */
+/* PCI controller registers */
+
+/* Command and Status Register */
+#define F0_CMD_STAT_MM 0x2f0004
+#define F1_CMD_STAT_MM 0x2f0104
+#define F2_CMD_STAT_MM 0x2f0204
+#define F3_CMD_STAT_MM 0x2f0304
+#define F4_CMD_STAT_MM 0x2f0404
+
+/* Device Control #1 */
+#define F0_DEV_CNTRL1_MM 0x2f0040
+#define F1_DEV_CNTRL1_MM 0x2f0140
+#define F2_DEV_CNTRL1_MM 0x2f0240
+#define F3_DEV_CNTRL1_MM 0x2f0340
+#define F4_DEV_CNTRL1_MM 0x2f0440
+
+/* Device Control #1 */
+#define F0_BAR0_MM 0x2f0010
+#define F1_BAR0_MM 0x2f0110
+#define F2_BAR0_MM 0x2f0210
+#define F3_BAR0_MM 0x2f0310
+#define F4_BAR0_MM 0x2f0410
/* ---------------------------------------------------------------------- */
/* DMA Controller registers */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 91207f10bae7..2765acee0285 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,4 @@
/*
- $Id: cx88-tvaudio.c,v 1.37 2005/07/07 13:58:38 mchehab Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
@@ -121,25 +120,19 @@ static void set_audio_registers(struct cx88_core *core,
}
static void set_audio_start(struct cx88_core *core,
- u32 mode, u32 ctl)
+ u32 mode)
{
// mute
cx_write(AUD_VOL_CTL, (1 << 6));
- // increase level of input by 12dB
-// cx_write(AUD_AFE_12DB_EN, 0x0001);
- cx_write(AUD_AFE_12DB_EN, 0x0000);
-
// start programming
cx_write(AUD_CTL, 0x0000);
cx_write(AUD_INIT, mode);
cx_write(AUD_INIT_LD, 0x0001);
cx_write(AUD_SOFT_RESET, 0x0001);
-
- cx_write(AUD_CTL, ctl);
}
-static void set_audio_finish(struct cx88_core *core)
+static void set_audio_finish(struct cx88_core *core, u32 ctl)
{
u32 volume;
@@ -154,25 +147,25 @@ static void set_audio_finish(struct cx88_core *core)
cx_write(AUD_I2SOUTPUTCNTL, 1);
cx_write(AUD_I2SCNTL, 0);
//cx_write(AUD_APB_IN_RATE_ADJ, 0);
+ } else {
+ ctl |= EN_DAC_ENABLE;
+ cx_write(AUD_CTL, ctl);
}
- // finish programming
+ /* finish programming */
cx_write(AUD_SOFT_RESET, 0x0000);
- // start audio processing
- cx_set(AUD_CTL, EN_DAC_ENABLE);
-
- // unmute
+ /* unmute */
volume = cx_sread(SHADOW_AUD_VOL_CTL);
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
}
/* ----------------------------------------------------------- */
-static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
+static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u32 mode)
{
static const struct rlist btsc[] = {
- /* from dscaler */
+ { AUD_AFE_12DB_EN, 0x00000001 },
{ AUD_OUT1_SEL, 0x00000013 },
{ AUD_OUT1_SHIFT, 0x00000000 },
{ AUD_POLY0_DDS_CONSTANT, 0x0012010c },
@@ -206,9 +199,10 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
{ AUD_RDSI_SHIFT, 0x00000000 },
{ AUD_RDSQ_SHIFT, 0x00000000 },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
- { /* end of list */ },
+ { /* end of list */ },
};
static const struct rlist btsc_sap[] = {
+ { AUD_AFE_12DB_EN, 0x00000001 },
{ AUD_DBX_IN_GAIN, 0x00007200 },
{ AUD_DBX_WBE_GAIN, 0x00006200 },
{ AUD_DBX_SE_GAIN, 0x00006200 },
@@ -259,371 +253,400 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
{ AUD_RDSI_SHIFT, 0x00000000 },
{ AUD_RDSQ_SHIFT, 0x00000000 },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
- { /* end of list */ },
+ { /* end of list */ },
};
- // dscaler: exactly taken from driver,
- // dscaler: don't know why to set EN_FMRADIO_EN_RDS
+ mode |= EN_FMRADIO_EN_RDS;
+
if (sap) {
dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0001,
- EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
+ set_audio_start(core, SEL_SAP);
set_audio_registers(core, btsc_sap);
+ set_audio_finish(core, mode);
} else {
dprintk("%s (status: known-good)\n",__FUNCTION__);
- set_audio_start(core, 0x0001,
- EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
+ set_audio_start(core, SEL_BTSC);
set_audio_registers(core, btsc);
+ set_audio_finish(core, mode);
}
- set_audio_finish(core);
}
static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
{
- /* This is probably weird..
- * Let's operate and find out. */
-
- static const struct rlist nicam_l_mono[] = {
- { AUD_ERRLOGPERIOD_R, 0x00000064 },
- { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
- { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
-
- { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
- { AUD_QAM_MODE, 0x00 },
- { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x4a },
-
- { AUD_DEEMPHGAIN_R, 0x6680 },
- { AUD_DEEMPHNUMER1_R, 0x353DE },
- { AUD_DEEMPHNUMER2_R, 0x1B1 },
- { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
- { AUD_DEEMPHDENOM2_R, 0x0 },
- { AUD_FM_MODE_ENABLE, 0x7 },
- { AUD_POLYPH80SCALEFAC, 0x3 },
- { AUD_AFE_12DB_EN, 0x1 },
- { AAGC_GAIN, 0x0 },
- { AAGC_HYST, 0x18 },
- { AAGC_DEF, 0x20 },
- { AUD_DN0_FREQ, 0x0 },
- { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
- { AUD_DCOC_0_SRC, 0x21 },
- { AUD_IIR1_0_SEL, 0x0 },
- { AUD_IIR1_0_SHIFT, 0x7 },
- { AUD_IIR1_1_SEL, 0x2 },
- { AUD_IIR1_1_SHIFT, 0x0 },
- { AUD_DCOC_1_SRC, 0x3 },
- { AUD_DCOC1_SHIFT, 0x0 },
- { AUD_DCOC_PASS_IN, 0x0 },
- { AUD_IIR1_2_SEL, 0x23 },
- { AUD_IIR1_2_SHIFT, 0x0 },
- { AUD_IIR1_3_SEL, 0x4 },
- { AUD_IIR1_3_SHIFT, 0x7 },
- { AUD_IIR1_4_SEL, 0x5 },
- { AUD_IIR1_4_SHIFT, 0x7 },
- { AUD_IIR3_0_SEL, 0x7 },
- { AUD_IIR3_0_SHIFT, 0x0 },
- { AUD_DEEMPH0_SRC_SEL, 0x11 },
- { AUD_DEEMPH0_SHIFT, 0x0 },
- { AUD_DEEMPH0_G0, 0x7000 },
- { AUD_DEEMPH0_A0, 0x0 },
- { AUD_DEEMPH0_B0, 0x0 },
- { AUD_DEEMPH0_A1, 0x0 },
- { AUD_DEEMPH0_B1, 0x0 },
- { AUD_DEEMPH1_SRC_SEL, 0x11 },
- { AUD_DEEMPH1_SHIFT, 0x0 },
- { AUD_DEEMPH1_G0, 0x7000 },
- { AUD_DEEMPH1_A0, 0x0 },
- { AUD_DEEMPH1_B0, 0x0 },
- { AUD_DEEMPH1_A1, 0x0 },
- { AUD_DEEMPH1_B1, 0x0 },
- { AUD_OUT0_SEL, 0x3F },
- { AUD_OUT1_SEL, 0x3F },
- { AUD_DMD_RA_DDS, 0x0F5C285 },
- { AUD_PLL_INT, 0x1E },
- { AUD_PLL_DDS, 0x0 },
- { AUD_PLL_FRAC, 0x0E542 },
-
- // setup QAM registers
- { AUD_RATE_ADJ1, 0x00000100 },
- { AUD_RATE_ADJ2, 0x00000200 },
- { AUD_RATE_ADJ3, 0x00000300 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00000500 },
- { AUD_RATE_THRES_DMD, 0x000000C0 },
- { /* end of list */ },
- };
-
- static const struct rlist nicam_l[] = {
- // setup QAM registers
- { AUD_RATE_ADJ1, 0x00000060 },
- { AUD_RATE_ADJ2, 0x000000F9 },
- { AUD_RATE_ADJ3, 0x000001CC },
- { AUD_RATE_ADJ4, 0x000002B3 },
- { AUD_RATE_ADJ5, 0x00000726 },
- { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_ERRLOGPERIOD_R, 0x00000064 },
- { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
- { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
- { AUD_POLYPH80SCALEFAC, 0x00000003 },
- { AUD_DMD_RA_DDS, 0x00C00000 },
- { AUD_PLL_INT, 0x0000001E },
- { AUD_PLL_DDS, 0x00000000 },
- { AUD_PLL_FRAC, 0x0000E542 },
- { AUD_START_TIMER, 0x00000000 },
- { AUD_DEEMPHNUMER1_R, 0x000353DE },
- { AUD_DEEMPHNUMER2_R, 0x000001B1 },
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_PHACC_FREQ_8MSB, 0x34 },
- { AUD_PHACC_FREQ_8LSB, 0x4C },
- { AUD_DEEMPHGAIN_R, 0x00006680 },
- { AUD_RATE_THRES_DMD, 0x000000C0 },
- { /* end of list */ },
- } ;
- dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
- if (!stereo) {
- /* AM mono sound */
- set_audio_start(core, 0x0004,
- 0x100c /* FIXME again */);
- set_audio_registers(core, nicam_l_mono);
- } else {
- set_audio_start(core, 0x0010,
- 0x1924 /* FIXME again */);
- set_audio_registers(core, nicam_l);
- }
- set_audio_finish(core);
+ /* This is probably weird..
+ * Let's operate and find out. */
+
+ static const struct rlist nicam_l_mono[] = {
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+
+ { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
+ { AUD_QAM_MODE, 0x00 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x4a },
+
+ { AUD_DEEMPHGAIN_R, 0x6680 },
+ { AUD_DEEMPHNUMER1_R, 0x353DE },
+ { AUD_DEEMPHNUMER2_R, 0x1B1 },
+ { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x0 },
+ { AUD_FM_MODE_ENABLE, 0x7 },
+ { AUD_POLYPH80SCALEFAC, 0x3 },
+ { AUD_AFE_12DB_EN, 0x1 },
+ { AAGC_GAIN, 0x0 },
+ { AAGC_HYST, 0x18 },
+ { AAGC_DEF, 0x20 },
+ { AUD_DN0_FREQ, 0x0 },
+ { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
+ { AUD_DCOC_0_SRC, 0x21 },
+ { AUD_IIR1_0_SEL, 0x0 },
+ { AUD_IIR1_0_SHIFT, 0x7 },
+ { AUD_IIR1_1_SEL, 0x2 },
+ { AUD_IIR1_1_SHIFT, 0x0 },
+ { AUD_DCOC_1_SRC, 0x3 },
+ { AUD_DCOC1_SHIFT, 0x0 },
+ { AUD_DCOC_PASS_IN, 0x0 },
+ { AUD_IIR1_2_SEL, 0x23 },
+ { AUD_IIR1_2_SHIFT, 0x0 },
+ { AUD_IIR1_3_SEL, 0x4 },
+ { AUD_IIR1_3_SHIFT, 0x7 },
+ { AUD_IIR1_4_SEL, 0x5 },
+ { AUD_IIR1_4_SHIFT, 0x7 },
+ { AUD_IIR3_0_SEL, 0x7 },
+ { AUD_IIR3_0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_SRC_SEL, 0x11 },
+ { AUD_DEEMPH0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_G0, 0x7000 },
+ { AUD_DEEMPH0_A0, 0x0 },
+ { AUD_DEEMPH0_B0, 0x0 },
+ { AUD_DEEMPH0_A1, 0x0 },
+ { AUD_DEEMPH0_B1, 0x0 },
+ { AUD_DEEMPH1_SRC_SEL, 0x11 },
+ { AUD_DEEMPH1_SHIFT, 0x0 },
+ { AUD_DEEMPH1_G0, 0x7000 },
+ { AUD_DEEMPH1_A0, 0x0 },
+ { AUD_DEEMPH1_B0, 0x0 },
+ { AUD_DEEMPH1_A1, 0x0 },
+ { AUD_DEEMPH1_B1, 0x0 },
+ { AUD_OUT0_SEL, 0x3F },
+ { AUD_OUT1_SEL, 0x3F },
+ { AUD_DMD_RA_DDS, 0x0F5C285 },
+ { AUD_PLL_INT, 0x1E },
+ { AUD_PLL_DDS, 0x0 },
+ { AUD_PLL_FRAC, 0x0E542 },
+
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000100 },
+ { AUD_RATE_ADJ2, 0x00000200 },
+ { AUD_RATE_ADJ3, 0x00000300 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00000500 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ };
+ static const struct rlist nicam_l[] = {
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000060 },
+ { AUD_RATE_ADJ2, 0x000000F9 },
+ { AUD_RATE_ADJ3, 0x000001CC },
+ { AUD_RATE_ADJ4, 0x000002B3 },
+ { AUD_RATE_ADJ5, 0x00000726 },
+ { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_DMD_RA_DDS, 0x00C00000 },
+ { AUD_PLL_INT, 0x0000001E },
+ { AUD_PLL_DDS, 0x00000000 },
+ { AUD_PLL_FRAC, 0x0000E542 },
+ { AUD_START_TIMER, 0x00000000 },
+ { AUD_DEEMPHNUMER1_R, 0x000353DE },
+ { AUD_DEEMPHNUMER2_R, 0x000001B1 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x34 },
+ { AUD_PHACC_FREQ_8LSB, 0x4C },
+ { AUD_DEEMPHGAIN_R, 0x00006680 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ } ;
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* AM Mono */
+ set_audio_start(core, SEL_A2);
+ set_audio_registers(core, nicam_l_mono);
+ set_audio_finish(core, EN_A2_FORCE_MONO1);
+ } else {
+ /* Nicam Stereo */
+ set_audio_start(core, SEL_NICAM);
+ set_audio_registers(core, nicam_l);
+ set_audio_finish(core, 0x1924); /* FIXME */
+ }
}
static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
{
static const struct rlist pal_i_fm_mono[] = {
- {AUD_ERRLOGPERIOD_R, 0x00000064},
- {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
- {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
- {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
- {AUD_PDF_DDS_CNST_BYTE2, 0x06},
- {AUD_PDF_DDS_CNST_BYTE1, 0x82},
- {AUD_PDF_DDS_CNST_BYTE0, 0x12},
- {AUD_QAM_MODE, 0x05},
- {AUD_PHACC_FREQ_8MSB, 0x3a},
- {AUD_PHACC_FREQ_8LSB, 0x93},
- {AUD_DMD_RA_DDS, 0x002a4f2f},
- {AUD_PLL_INT, 0x0000001e},
- {AUD_PLL_DDS, 0x00000004},
- {AUD_PLL_FRAC, 0x0000e542},
- {AUD_RATE_ADJ1, 0x00000100},
- {AUD_RATE_ADJ2, 0x00000200},
- {AUD_RATE_ADJ3, 0x00000300},
- {AUD_RATE_ADJ4, 0x00000400},
- {AUD_RATE_ADJ5, 0x00000500},
- {AUD_THR_FR, 0x00000000},
- {AUD_PILOT_BQD_1_K0, 0x0000755b},
- {AUD_PILOT_BQD_1_K1, 0x00551340},
- {AUD_PILOT_BQD_1_K2, 0x006d30be},
- {AUD_PILOT_BQD_1_K3, 0xffd394af},
- {AUD_PILOT_BQD_1_K4, 0x00400000},
- {AUD_PILOT_BQD_2_K0, 0x00040000},
- {AUD_PILOT_BQD_2_K1, 0x002a4841},
- {AUD_PILOT_BQD_2_K2, 0x00400000},
- {AUD_PILOT_BQD_2_K3, 0x00000000},
- {AUD_PILOT_BQD_2_K4, 0x00000000},
- {AUD_MODE_CHG_TIMER, 0x00000060},
- {AUD_AFE_12DB_EN, 0x00000001},
- {AAGC_HYST, 0x0000000a},
- {AUD_CORDIC_SHIFT_0, 0x00000007},
- {AUD_CORDIC_SHIFT_1, 0x00000007},
- {AUD_C1_UP_THR, 0x00007000},
- {AUD_C1_LO_THR, 0x00005400},
- {AUD_C2_UP_THR, 0x00005400},
- {AUD_C2_LO_THR, 0x00003000},
- {AUD_DCOC_0_SRC, 0x0000001a},
- {AUD_DCOC0_SHIFT, 0x00000000},
- {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
- {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
- {AUD_DCOC_PASS_IN, 0x00000003},
- {AUD_IIR3_0_SEL, 0x00000021},
- {AUD_DN2_AFC, 0x00000002},
- {AUD_DCOC_1_SRC, 0x0000001b},
- {AUD_DCOC1_SHIFT, 0x00000000},
- {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
- {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
- {AUD_IIR3_1_SEL, 0x00000023},
- {AUD_DN0_FREQ, 0x000035a3},
- {AUD_DN2_FREQ, 0x000029c7},
- {AUD_CRDC0_SRC_SEL, 0x00000511},
- {AUD_IIR1_0_SEL, 0x00000001},
- {AUD_IIR1_1_SEL, 0x00000000},
- {AUD_IIR3_2_SEL, 0x00000003},
- {AUD_IIR3_2_SHIFT, 0x00000000},
- {AUD_IIR3_0_SEL, 0x00000002},
- {AUD_IIR2_0_SEL, 0x00000021},
- {AUD_IIR2_0_SHIFT, 0x00000002},
- {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
- {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
- {AUD_POLYPH80SCALEFAC, 0x00000001},
- {AUD_START_TIMER, 0x00000000},
- { /* end of list */ },
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x3a},
+ {AUD_PHACC_FREQ_8LSB, 0x93},
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000004},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000060},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AAGC_HYST, 0x0000000a},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_DN0_FREQ, 0x000035a3},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_CRDC0_SRC_SEL, 0x00000511},
+ {AUD_IIR1_0_SEL, 0x00000001},
+ {AUD_IIR1_1_SEL, 0x00000000},
+ {AUD_IIR3_2_SEL, 0x00000003},
+ {AUD_IIR3_2_SHIFT, 0x00000000},
+ {AUD_IIR3_0_SEL, 0x00000002},
+ {AUD_IIR2_0_SEL, 0x00000021},
+ {AUD_IIR2_0_SHIFT, 0x00000002},
+ {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+ {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
};
static const struct rlist pal_i_nicam[] = {
- { AUD_RATE_ADJ1, 0x00000010 },
- { AUD_RATE_ADJ2, 0x00000040 },
- { AUD_RATE_ADJ3, 0x00000100 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00001000 },
- // { AUD_DMD_RA_DDS, 0x00c0d5ce },
- { AUD_DEEMPHGAIN_R, 0x000023c2 },
- { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
- { AUD_DEEMPHNUMER2_R, 0x0003023e },
- { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_ERRLOGPERIOD_R, 0x00000fff },
- { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
- { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
- { AUD_POLYPH80SCALEFAC, 0x00000003 },
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x93 },
- { /* end of list */ },
- };
-
- dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
- if (!stereo) {
- // FM mono
- set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ { AUD_RATE_ADJ1, 0x00000010 },
+ { AUD_RATE_ADJ2, 0x00000040 },
+ { AUD_RATE_ADJ3, 0x00000100 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00001000 },
+ // { AUD_DMD_RA_DDS, 0x00c0d5ce },
+ { AUD_DEEMPHGAIN_R, 0x000023c2 },
+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
+ { AUD_DEEMPHNUMER2_R, 0x0003023e },
+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000fff },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x93 },
+ { /* end of list */ },
+ };
+
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* FM Mono */
+ set_audio_start(core, SEL_A2);
set_audio_registers(core, pal_i_fm_mono);
- } else {
- // Nicam Stereo
- set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ set_audio_finish(core, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ } else {
+ /* Nicam Stereo */
+ set_audio_start(core, SEL_NICAM);
set_audio_registers(core, pal_i_nicam);
- }
- set_audio_finish(core);
+ set_audio_finish(core, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ }
}
-static void set_audio_standard_A2(struct cx88_core *core)
+static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
{
- /* from dscaler cvs */
static const struct rlist a2_common[] = {
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PHACC_FREQ_8MSB, 0x34 },
- { AUD_PHACC_FREQ_8LSB, 0x4c },
-
- { AUD_RATE_ADJ1, 0x00001000 },
- { AUD_RATE_ADJ2, 0x00002000 },
- { AUD_RATE_ADJ3, 0x00003000 },
- { AUD_RATE_ADJ4, 0x00004000 },
- { AUD_RATE_ADJ5, 0x00005000 },
- { AUD_THR_FR, 0x00000000 },
- { AAGC_HYST, 0x0000001a },
- { AUD_PILOT_BQD_1_K0, 0x0000755b },
- { AUD_PILOT_BQD_1_K1, 0x00551340 },
- { AUD_PILOT_BQD_1_K2, 0x006d30be },
- { AUD_PILOT_BQD_1_K3, 0xffd394af },
- { AUD_PILOT_BQD_1_K4, 0x00400000 },
- { AUD_PILOT_BQD_2_K0, 0x00040000 },
- { AUD_PILOT_BQD_2_K1, 0x002a4841 },
- { AUD_PILOT_BQD_2_K2, 0x00400000 },
- { AUD_PILOT_BQD_2_K3, 0x00000000 },
- { AUD_PILOT_BQD_2_K4, 0x00000000 },
- { AUD_MODE_CHG_TIMER, 0x00000040 },
- { AUD_START_TIMER, 0x00000200 },
- { AUD_AFE_12DB_EN, 0x00000000 },
- { AUD_CORDIC_SHIFT_0, 0x00000007 },
- { AUD_CORDIC_SHIFT_1, 0x00000007 },
- { AUD_DEEMPH0_G0, 0x00000380 },
- { AUD_DEEMPH1_G0, 0x00000380 },
- { AUD_DCOC_0_SRC, 0x0000001a },
- { AUD_DCOC0_SHIFT, 0x00000000 },
- { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000003 },
- { AUD_IIR3_0_SEL, 0x00000021 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DCOC_1_SRC, 0x0000001b },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_RDSI_SEL, 0x00000017 },
- { AUD_RDSI_SHIFT, 0x00000000 },
- { AUD_RDSQ_SEL, 0x00000017 },
- { AUD_RDSQ_SHIFT, 0x00000000 },
- { AUD_POLYPH80SCALEFAC, 0x00000001 },
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x34},
+ {AUD_PHACC_FREQ_8LSB, 0x4c},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AAGC_HYST, 0x0000001a},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000040},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_DEEMPH0_G0, 0x00000380},
+ {AUD_DEEMPH1_G0, 0x00000380},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_RDSI_SEL, 0x00000017},
+ {AUD_RDSI_SHIFT, 0x00000000},
+ {AUD_RDSQ_SEL, 0x00000017},
+ {AUD_RDSQ_SHIFT, 0x00000000},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000000},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
+ };
+ static const struct rlist a2_bg[] = {
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
{ /* end of list */ },
};
- static const struct rlist a2_table1[] = {
- // PAL-BG
- { AUD_DMD_RA_DDS, 0x002a73bd },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C1_LO_THR, 0x00005400 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
+ static const struct rlist a2_dk[] = {
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DN0_FREQ, 0x00003a1c},
+ {AUD_DN2_FREQ, 0x0000d2e0},
{ /* end of list */ },
};
- static const struct rlist a2_table2[] = {
- // PAL-DK
- { AUD_DMD_RA_DDS, 0x002a73bd },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C1_LO_THR, 0x00005400 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
- { AUD_DN0_FREQ, 0x00003a1c },
- { AUD_DN2_FREQ, 0x0000d2e0 },
+/* unknown, probably NTSC-M */
+ static const struct rlist a2_m[] = {
+ {AUD_DMD_RA_DDS, 0x002a0425},
+ {AUD_C1_UP_THR, 0x00003c00},
+ {AUD_C1_LO_THR, 0x00003000},
+ {AUD_C2_UP_THR, 0x00006000},
+ {AUD_C2_LO_THR, 0x00003c00},
+ {AUD_DEEMPH0_A0, 0x00007a80},
+ {AUD_DEEMPH1_A0, 0x00007a80},
+ {AUD_DEEMPH0_G0, 0x00001200},
+ {AUD_DEEMPH1_G0, 0x00001200},
+ {AUD_DN0_FREQ, 0x0000283b},
+ {AUD_DN1_FREQ, 0x00003418},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_POLY0_DDS_CONSTANT, 0x000a7540},
{ /* end of list */ },
};
- static const struct rlist a2_table3[] = {
- // unknown, probably NTSC-M
- { AUD_DMD_RA_DDS, 0x002a2873 },
- { AUD_C1_UP_THR, 0x00003c00 },
- { AUD_C1_LO_THR, 0x00003000 },
- { AUD_C2_UP_THR, 0x00006000 },
- { AUD_C2_LO_THR, 0x00003c00 },
- { AUD_DN0_FREQ, 0x00002836 },
- { AUD_DN1_FREQ, 0x00003418 },
- { AUD_DN2_FREQ, 0x000029c7 },
- { AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
+
+ static const struct rlist a2_deemph50[] = {
+ {AUD_DEEMPH0_G0, 0x00000380},
+ {AUD_DEEMPH1_G0, 0x00000380},
+ {AUD_DEEMPHGAIN_R, 0x000011e1},
+ {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+ {AUD_DEEMPHNUMER2_R, 0x0003023c},
+ { /* end of list */ },
+ };
+
+ static const struct rlist a2_deemph75[] = {
+ {AUD_DEEMPH0_G0, 0x00000480},
+ {AUD_DEEMPH1_G0, 0x00000480},
+ {AUD_DEEMPHGAIN_R, 0x00009000},
+ {AUD_DEEMPHNUMER1_R, 0x000353de},
+ {AUD_DEEMPHNUMER2_R, 0x000001b1},
{ /* end of list */ },
};
- set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
+ set_audio_start(core, SEL_A2);
set_audio_registers(core, a2_common);
switch (core->tvaudio) {
case WW_A2_BG:
dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
- set_audio_registers(core, a2_table1);
+ set_audio_registers(core, a2_bg);
+ set_audio_registers(core, a2_deemph50);
break;
case WW_A2_DK:
dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
- set_audio_registers(core, a2_table2);
+ set_audio_registers(core, a2_dk);
+ set_audio_registers(core, a2_deemph50);
break;
case WW_A2_M:
dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
- set_audio_registers(core, a2_table3);
+ set_audio_registers(core, a2_m);
+ set_audio_registers(core, a2_deemph75);
break;
};
- set_audio_finish(core);
+
+ mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
+ set_audio_finish(core, mode);
}
static void set_audio_standard_EIAJ(struct cx88_core *core)
@@ -635,9 +658,9 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
};
dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0002, EN_EIAJ_AUTO_STEREO);
+ set_audio_start(core, SEL_EIAJ);
set_audio_registers(core, eiaj);
- set_audio_finish(core);
+ set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
}
static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
@@ -683,7 +706,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
};
dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
+ set_audio_start(core, SEL_FMRADIO);
switch (deemph)
{
@@ -700,7 +723,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
break;
}
- set_audio_finish(core);
+ set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
}
/* ----------------------------------------------------------- */
@@ -709,7 +732,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
{
switch (core->tvaudio) {
case WW_BTSC:
- set_audio_standard_BTSC(core,0);
+ set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
break;
case WW_NICAM_BGDKL:
set_audio_standard_NICAM_L(core,0);
@@ -720,7 +743,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
- set_audio_standard_A2(core);
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
break;
case WW_EIAJ:
set_audio_standard_EIAJ(core);
@@ -734,7 +757,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_NONE:
default:
printk("%s/0: unknown tv audio mode [%d]\n",
- core->name, core->tvaudio);
+ core->name, core->tvaudio);
break;
}
return;
@@ -769,6 +792,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
aud_ctl_names[cx_read(AUD_CTL) & 63]);
core->astat = reg;
+/* TODO
+ Reading from AUD_STATUS is not enough
+ for auto-detecting sap/dual-fm/nicam.
+ Add some code here later.
+*/
+
+# if 0
t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
t->rxsubchans = V4L2_TUNER_SUB_MONO;
@@ -779,7 +809,7 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
t->capability = V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_SAP;
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
- if (1 == pilot) {
+ if (1 == pilot) {
/* SAP */
t->rxsubchans |= V4L2_TUNER_SUB_SAP;
}
@@ -787,13 +817,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
- if (1 == pilot) {
+ if (1 == pilot) {
/* stereo */
t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
if (0 == mode)
t->audmode = V4L2_TUNER_MODE_STEREO;
}
- if (2 == pilot) {
+ if (2 == pilot) {
/* dual language -- FIXME */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
@@ -805,16 +835,17 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
break;
- case WW_SYSTEM_L_AM:
- if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
- t->audmode = V4L2_TUNER_MODE_STEREO;
+ case WW_SYSTEM_L_AM:
+ if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
- break ;
+ break ;
default:
/* nothing */
break;
}
+# endif
return;
}
@@ -835,16 +866,16 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
case WW_BTSC:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
- ctl = EN_BTSC_FORCE_MONO;
- mask = 0x3f;
+ set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
break;
- case V4L2_TUNER_MODE_SAP:
- ctl = EN_BTSC_FORCE_SAP;
- mask = 0x3f;
+ case V4L2_TUNER_MODE_LANG1:
+ set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
break;
case V4L2_TUNER_MODE_STEREO:
- ctl = EN_BTSC_AUTO_STEREO;
- mask = 0x3f;
+ set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
break;
}
break;
@@ -854,16 +885,13 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
- ctl = EN_A2_FORCE_MONO1;
- mask = 0x3f;
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
break;
case V4L2_TUNER_MODE_LANG2:
- ctl = EN_A2_AUTO_MONO2;
- mask = 0x3f;
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO2);
break;
case V4L2_TUNER_MODE_STEREO:
- ctl = EN_A2_AUTO_STEREO | EN_DMTRX_SUMR;
- mask = 0x8bf;
+ set_audio_standard_A2(core, EN_A2_FORCE_STEREO);
break;
}
break;
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 320d57888bbd..9bc6c8995581 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 5f58c103198a..3dbc074fb515 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -66,7 +65,7 @@ module_param(vid_limit,int,0644);
MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
#define dprintk(level,fmt, arg...) if (video_debug >= level) \
- printk(KERN_DEBUG "%s/0: " fmt, dev->core->name , ## arg)
+ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
/* ------------------------------------------------------------------ */
@@ -326,22 +325,23 @@ static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
{
+ struct cx88_core *core = dev->core;
if (fh->resources & bit)
/* have it already allocated */
return 1;
/* is it free? */
- down(&dev->lock);
+ down(&core->lock);
if (dev->resources & bit) {
/* no, someone else uses it */
- up(&dev->lock);
+ up(&core->lock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
dev->resources |= bit;
dprintk(1,"res: get %d\n",bit);
- up(&dev->lock);
+ up(&core->lock);
return 1;
}
@@ -360,27 +360,29 @@ int res_locked(struct cx8800_dev *dev, unsigned int bit)
static
void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
{
+ struct cx88_core *core = dev->core;
if ((fh->resources & bits) != bits)
BUG();
- down(&dev->lock);
+ down(&core->lock);
fh->resources &= ~bits;
dev->resources &= ~bits;
dprintk(1,"res: put %d\n",bits);
- up(&dev->lock);
+ up(&core->lock);
}
/* ------------------------------------------------------------------ */
-static int video_mux(struct cx8800_dev *dev, unsigned int input)
+/* static int video_mux(struct cx8800_dev *dev, unsigned int input) */
+static int video_mux(struct cx88_core *core, unsigned int input)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
input, INPUT(input)->vmux,
INPUT(input)->gpio0,INPUT(input)->gpio1,
INPUT(input)->gpio2,INPUT(input)->gpio3);
- dev->core->input = input;
+ core->input = input;
cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14);
cx_write(MO_GP3_IO, INPUT(input)->gpio3);
cx_write(MO_GP0_IO, INPUT(input)->gpio0);
@@ -413,9 +415,9 @@ static int start_video_dma(struct cx8800_dev *dev,
struct cx88_core *core = dev->core;
/* setup fifo + format */
- cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH21],
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- cx88_set_scale(dev->core, buf->vb.width, buf->vb.height, buf->vb.field);
+ cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
/* reset counter */
@@ -424,6 +426,14 @@ static int start_video_dma(struct cx8800_dev *dev,
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
+
+ /* Enables corresponding bits at PCI_INT_STAT:
+ bits 0 to 4: video, audio, transport stream, VIP, Host
+ bit 7: timer
+ bits 8 and 9: DMA complete for: SRC, DST
+ bits 10 and 11: BERR signal asserted for RISC: RD, WR
+ bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+ */
cx_set(MO_VID_INTMSK, 0x0f0011);
/* enable capture */
@@ -431,7 +441,7 @@ static int start_video_dma(struct cx8800_dev *dev,
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
- cx_set(MO_VID_DMACNTRL, 0x11);
+ cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
return 0;
}
@@ -455,6 +465,7 @@ static int stop_video_dma(struct cx8800_dev *dev)
static int restart_video_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
{
+ struct cx88_core *core = dev->core;
struct cx88_buffer *buf, *prev;
struct list_head *item;
@@ -524,12 +535,13 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
{
struct cx8800_fh *fh = q->priv_data;
struct cx8800_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
int rc, init_buffer = 0;
BUG_ON(NULL == fh->fmt);
- if (fh->width < 48 || fh->width > norm_maxw(dev->core->tvnorm) ||
- fh->height < 32 || fh->height > norm_maxh(dev->core->tvnorm))
+ if (fh->width < 48 || fh->width > norm_maxw(core->tvnorm) ||
+ fh->height < 32 || fh->height > norm_maxh(core->tvnorm))
return -EINVAL;
buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
@@ -609,6 +621,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
struct cx88_buffer *prev;
struct cx8800_fh *fh = vq->priv_data;
struct cx8800_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
/* add jump to stopper */
@@ -701,6 +714,7 @@ static int video_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct cx8800_dev *h,*dev = NULL;
+ struct cx88_core *core;
struct cx8800_fh *fh;
struct list_head *list;
enum v4l2_buf_type type = 0;
@@ -725,6 +739,8 @@ static int video_open(struct inode *inode, struct file *file)
if (NULL == dev)
return -ENODEV;
+ core = dev->core;
+
dprintk(1,"open minor=%d radio=%d type=%s\n",
minor,radio,v4l2_type_names[type]);
@@ -755,17 +771,16 @@ static int video_open(struct inode *inode, struct file *file)
fh);
if (fh->radio) {
- struct cx88_core *core = dev->core;
int board = core->board;
dprintk(1,"video_open: setting radio device\n");
cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
- dev->core->tvaudio = WW_FM;
+ core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
- cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
+ cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
}
return 0;
@@ -857,6 +872,9 @@ static int video_release(struct inode *inode, struct file *file)
videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
+
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
return 0;
}
@@ -870,9 +888,10 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */
-static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
u32 value;
int i;
@@ -898,9 +917,10 @@ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return 0;
}
-static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
u32 v_sat_value;
u32 value;
@@ -913,9 +933,9 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return -EINVAL;
if (ctl->value < c->v.minimum)
- return -ERANGE;
+ ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum)
- return -ERANGE;
+ ctl->value = c->v.maximum;
switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE:
value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
@@ -946,7 +966,8 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return 0;
}
-static void init_controls(struct cx8800_dev *dev)
+/* static void init_controls(struct cx8800_dev *dev) */
+static void init_controls(struct cx88_core *core)
{
static struct v4l2_control mute = {
.id = V4L2_CID_AUDIO_MUTE,
@@ -969,11 +990,11 @@ static void init_controls(struct cx8800_dev *dev)
.value = 0x80,
};
- set_control(dev,&mute);
- set_control(dev,&volume);
- set_control(dev,&hue);
- set_control(dev,&contrast);
- set_control(dev,&brightness);
+ set_control(core,&mute);
+ set_control(core,&volume);
+ set_control(core,&hue);
+ set_control(core,&contrast);
+ set_control(core,&brightness);
}
/* ------------------------------------------------------------------ */
@@ -1004,6 +1025,8 @@ static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
struct v4l2_format *f)
{
+ struct cx88_core *core = dev->core;
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
@@ -1016,8 +1039,8 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
return -EINVAL;
field = f->fmt.pix.field;
- maxw = norm_maxw(dev->core->tvnorm);
- maxh = norm_maxh(dev->core->tvnorm);
+ maxw = norm_maxw(core->tvnorm);
+ maxh = norm_maxh(core->tvnorm);
if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2)
@@ -1101,12 +1124,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (video_debug > 1)
cx88_print_ioctl(core->name,cmd);
switch (cmd) {
+
+ /* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "cx8800");
+ strcpy(cap->driver, "cx8800");
strlcpy(cap->card, cx88_boards[core->board].name,
sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
@@ -1116,12 +1141,128 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
+ /* --- capture ioctls ---------------------------------------- */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ enum v4l2_buf_type type;
+ unsigned int index;
+
+ index = f->index;
+ type = f->type;
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (index >= ARRAY_SIZE(formats))
+ return -EINVAL;
+ memset(f,0,sizeof(*f));
+ f->index = index;
+ f->type = type;
+ strlcpy(f->description,formats[index].name,sizeof(f->description));
+ f->pixelformat = formats[index].fourcc;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_g_fmt(dev,fh,f);
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_s_fmt(dev,fh,f);
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_try_fmt(dev,fh,f);
+ }
+
+ /* --- streaming capture ------------------------------------- */
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf *mbuf = arg;
+ struct videobuf_queue *q;
+ struct v4l2_requestbuffers req;
+ unsigned int i;
+
+ q = get_queue(fh);
+ memset(&req,0,sizeof(req));
+ req.type = q->type;
+ req.count = 8;
+ req.memory = V4L2_MEMORY_MMAP;
+ err = videobuf_reqbufs(q,&req);
+ if (err < 0)
+ return err;
+ memset(mbuf,0,sizeof(*mbuf));
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
+ }
+ return 0;
+ }
+ case VIDIOC_REQBUFS:
+ return videobuf_reqbufs(get_queue(fh), arg);
+
+ case VIDIOC_QUERYBUF:
+ return videobuf_querybuf(get_queue(fh), arg);
+
+ case VIDIOC_QBUF:
+ return videobuf_qbuf(get_queue(fh), arg);
+
+ case VIDIOC_DQBUF:
+ return videobuf_dqbuf(get_queue(fh), arg,
+ file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_STREAMON:
+ {
+ int res = get_ressource(fh);
+
+ if (!res_get(dev,fh,res))
+ return -EBUSY;
+ return videobuf_streamon(get_queue(fh));
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ int res = get_ressource(fh);
+
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev,fh,res);
+ return 0;
+ }
+
+ default:
+ return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
+ }
+ return 0;
+}
+
+int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+ struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+{
+ int err;
+
+ if (video_debug > 1)
+ cx88_print_ioctl(core->name,cmd);
+ printk( KERN_INFO "CORE IOCTL: 0x%x\n", cmd );
+ cx88_print_ioctl(core->name,cmd);
+ dprintk( 1, "CORE IOCTL: 0x%x\n", cmd );
+
+ switch (cmd) {
/* ---------- tv norms ---------- */
case VIDIOC_ENUMSTD:
{
@@ -1156,9 +1297,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (i == ARRAY_SIZE(tvnorms))
return -EINVAL;
- down(&dev->lock);
- cx88_set_tvnorm(dev->core,&tvnorms[i]);
- up(&dev->lock);
+ down(&core->lock);
+ cx88_set_tvnorm(core,&tvnorms[i]);
+ up(&core->lock);
return 0;
}
@@ -1199,7 +1340,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{
unsigned int *i = arg;
- *i = dev->core->input;
+ *i = core->input;
return 0;
}
case VIDIOC_S_INPUT:
@@ -1208,55 +1349,15 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (*i >= 4)
return -EINVAL;
- down(&dev->lock);
+ down(&core->lock);
cx88_newstation(core);
- video_mux(dev,*i);
- up(&dev->lock);
+ video_mux(core,*i);
+ up(&core->lock);
return 0;
}
- /* --- capture ioctls ---------------------------------------- */
- case VIDIOC_ENUM_FMT:
- {
- struct v4l2_fmtdesc *f = arg;
- enum v4l2_buf_type type;
- unsigned int index;
-
- index = f->index;
- type = f->type;
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (index >= ARRAY_SIZE(formats))
- return -EINVAL;
- memset(f,0,sizeof(*f));
- f->index = index;
- f->type = type;
- strlcpy(f->description,formats[index].name,sizeof(f->description));
- f->pixelformat = formats[index].fourcc;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- case VIDIOC_G_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_g_fmt(dev,fh,f);
- }
- case VIDIOC_S_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_s_fmt(dev,fh,f);
- }
- case VIDIOC_TRY_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_try_fmt(dev,fh,f);
- }
-
/* --- controls ---------------------------------------------- */
case VIDIOC_QUERYCTRL:
{
@@ -1277,9 +1378,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
case VIDIOC_G_CTRL:
- return get_control(dev,arg);
+ return get_control(core,arg);
case VIDIOC_S_CTRL:
- return set_control(dev,arg);
+ return set_control(core,arg);
/* --- tuner ioctls ------------------------------------------ */
case VIDIOC_G_TUNER:
@@ -1323,10 +1424,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (UNSET == core->tuner_type)
return -EINVAL;
- f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
- f->frequency = dev->freq;
+ /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+ f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ f->frequency = core->freq;
- cx88_call_i2c_clients(dev->core,VIDIOC_G_FREQUENCY,f);
+ cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
return 0;
}
@@ -1338,83 +1440,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (f->tuner != 0)
return -EINVAL;
- if (0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)
+ if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
return -EINVAL;
- if (1 == fh->radio && f->type != V4L2_TUNER_RADIO)
+ if (1 == radio && f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- down(&dev->lock);
- dev->freq = f->frequency;
+ down(&core->lock);
+ core->freq = f->frequency;
cx88_newstation(core);
- cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
+ cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
/* When changing channels it is required to reset TVAUDIO */
msleep (10);
cx88_set_tvaudio(core);
- up(&dev->lock);
- return 0;
- }
-
- /* --- streaming capture ------------------------------------- */
- case VIDIOCGMBUF:
- {
- struct video_mbuf *mbuf = arg;
- struct videobuf_queue *q;
- struct v4l2_requestbuffers req;
- unsigned int i;
-
- q = get_queue(fh);
- memset(&req,0,sizeof(req));
- req.type = q->type;
- req.count = 8;
- req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(q,&req);
- if (err < 0)
- return err;
- memset(mbuf,0,sizeof(*mbuf));
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return 0;
- }
- case VIDIOC_REQBUFS:
- return videobuf_reqbufs(get_queue(fh), arg);
-
- case VIDIOC_QUERYBUF:
- return videobuf_querybuf(get_queue(fh), arg);
-
- case VIDIOC_QBUF:
- return videobuf_qbuf(get_queue(fh), arg);
-
- case VIDIOC_DQBUF:
- return videobuf_dqbuf(get_queue(fh), arg,
- file->f_flags & O_NONBLOCK);
-
- case VIDIOC_STREAMON:
- {
- int res = get_ressource(fh);
-
- if (!res_get(dev,fh,res))
- return -EBUSY;
- return videobuf_streamon(get_queue(fh));
- }
- case VIDIOC_STREAMOFF:
- {
- int res = get_ressource(fh);
-
- err = videobuf_streamoff(get_queue(fh));
- if (err < 0)
- return err;
- res_free(dev,fh,res);
+ up(&core->lock);
return 0;
}
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
- video_do_ioctl);
+ driver_ioctl);
}
return 0;
}
@@ -1461,7 +1506,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
memset(t,0,sizeof(*t));
strcpy(t->name, "Radio");
- cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t);
+ cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
return 0;
}
case VIDIOC_ENUMINPUT:
@@ -1501,8 +1546,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
if (v->tuner) /* Only tuner 0 */
return -EINVAL;
- cx88_call_i2c_clients(dev->core,VIDIOCSTUNER,v);
- return 0;
+ cx88_call_i2c_clients(core,VIDIOCSTUNER,v);
+ return 0;
}
case VIDIOC_S_TUNER:
{
@@ -1511,7 +1556,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
if (0 != t->index)
return -EINVAL;
- cx88_call_i2c_clients(dev->core,VIDIOC_S_TUNER,t);
+ cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
return 0;
}
@@ -1569,7 +1614,7 @@ static void cx8800_vid_timeout(unsigned long data)
struct cx88_buffer *buf;
unsigned long flags;
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
@@ -1614,14 +1659,14 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
}
/* risc1 y */
if (status & 0x01) {
spin_lock(&dev->slock);
count = cx_read(MO_VIDY_GPCNT);
- cx88_wakeup(dev->core, &dev->vidq, count);
+ cx88_wakeup(core, &dev->vidq, count);
spin_unlock(&dev->slock);
}
@@ -1629,7 +1674,7 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
if (status & 0x08) {
spin_lock(&dev->slock);
count = cx_read(MO_VBI_GPCNT);
- cx88_wakeup(dev->core, &dev->vbiq, count);
+ cx88_wakeup(core, &dev->vbiq, count);
spin_unlock(&dev->slock);
}
@@ -1798,7 +1843,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
}
/* initialize driver struct */
- init_MUTEX(&dev->lock);
spin_lock_init(&dev->slock);
core->tvnorm = tvnorms;
@@ -1835,6 +1879,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
request_module("tuner");
if (core->tda9887_conf)
request_module("tda9887");
+
/* register v4l devices */
dev->video_dev = cx88_vdev_init(core,dev->pci,
&cx8800_video_template,"video");
@@ -1878,11 +1923,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
pci_set_drvdata(pci_dev,dev);
/* initial device configuration */
- down(&dev->lock);
- init_controls(dev);
- cx88_set_tvnorm(dev->core,tvnorms);
- video_mux(dev,0);
- up(&dev->lock);
+ down(&core->lock);
+ init_controls(core);
+ cx88_set_tvnorm(core,tvnorms);
+ video_mux(core,0);
+ up(&core->lock);
/* start tvaudio thread */
if (core->tuner_type != TUNER_ABSENT)
@@ -1902,14 +1947,15 @@ fail_free:
static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx88_core *core = dev->core;
/* stop thread */
- if (dev->core->kthread) {
- kthread_stop(dev->core->kthread);
- dev->core->kthread = NULL;
+ if (core->kthread) {
+ kthread_stop(core->kthread);
+ core->kthread = NULL;
}
- cx88_shutdown(dev->core); /* FIXME */
+ cx88_shutdown(core); /* FIXME */
pci_disable_device(pci_dev);
/* unregister stuff */
@@ -1921,7 +1967,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
/* free memory */
btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
list_del(&dev->devlist);
- cx88_core_put(dev->core,dev->pci);
+ cx88_core_put(core,dev->pci);
kfree(dev);
}
@@ -1945,7 +1991,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
spin_unlock(&dev->slock);
/* FIXME -- shutdown device */
- cx88_shutdown(dev->core);
+ cx88_shutdown(core);
pci_save_state(pci_dev);
if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
@@ -1959,16 +2005,32 @@ static int cx8800_resume(struct pci_dev *pci_dev)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
+ int err;
if (dev->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ core->name);
+ return err;
+ }
+
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err= pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ core->name);
+
+ pci_disable_device(pci_dev);
+ dev->state.disabled = 1;
+
+ return err;
+ }
pci_restore_state(pci_dev);
/* FIXME: re-initialize hardware */
- cx88_reset(dev->core);
+ cx88_reset(core);
/* restart video+vbi capture */
spin_lock(&dev->slock);
@@ -2030,6 +2092,8 @@ static void cx8800_fini(void)
module_init(cx8800_init);
module_exit(cx8800_fini);
+EXPORT_SYMBOL(cx88_do_ioctl);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index da65dc92787c..f48dd4353568 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,4 @@
/*
- * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -35,7 +34,7 @@
#include "btcx-risc.h"
#include "cx88-reg.h"
-#include <linux/utsname.h>
+#include <linux/version.h>
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
#ifndef TRUE
@@ -48,6 +47,9 @@
#define CX88_MAXBOARDS 8
+/* Max number of inputs by card */
+#define MAX_CX88_INPUT 8
+
/* ----------------------------------------------------------- */
/* defines and enums */
@@ -199,7 +201,7 @@ struct cx88_board {
unsigned char tuner_addr;
unsigned char radio_addr;
int tda9887_conf;
- struct cx88_input input[8];
+ struct cx88_input input[MAX_CX88_INPUT];
struct cx88_input radio;
int blackbird:1;
int dvb:1;
@@ -288,6 +290,11 @@ struct cx88_core {
/* IR remote control state */
struct cx88_IR *ir;
+
+ struct semaphore lock;
+
+ /* various v4l controls */
+ u32 freq;
};
struct cx8800_dev;
@@ -323,8 +330,7 @@ struct cx8800_suspend_state {
struct cx8800_dev {
struct cx88_core *core;
struct list_head devlist;
- struct semaphore lock;
- spinlock_t slock;
+ spinlock_t slock;
/* various device info */
unsigned int resources;
@@ -342,7 +348,6 @@ struct cx8800_dev {
struct cx88_dmaqueue vbiq;
/* various v4l controls */
- u32 freq;
/* other global state info */
struct cx8800_suspend_state state;
@@ -350,14 +355,8 @@ struct cx8800_dev {
/* ----------------------------------------------------------- */
/* function 1: audio/alsa stuff */
+/* =============> moved to cx88-alsa.c <====================== */
-struct cx8801_dev {
- struct cx88_core *core;
-
- /* pci i/o */
- struct pci_dev *pci;
- unsigned char pci_rev,pci_lat;
-};
/* ----------------------------------------------------------- */
/* function 2: mpeg stuff */
@@ -373,8 +372,7 @@ struct cx8802_suspend_state {
struct cx8802_dev {
struct cx88_core *core;
- struct semaphore lock;
- spinlock_t slock;
+ spinlock_t slock;
/* pci i/o */
struct pci_dev *pci;
@@ -553,8 +551,21 @@ void cx8802_fini_common(struct cx8802_dev *dev);
int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
int cx8802_resume_common(struct pci_dev *pci_dev);
+/* ----------------------------------------------------------- */
+/* cx88-video.c */
+extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+ struct cx88_core *core, unsigned int cmd,
+ void *arg, v4l2_kioctl driver_ioctl);
+
+/* ----------------------------------------------------------- */
+/* cx88-blackbird.c */
+extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
/*
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
new file mode 100644
index 000000000000..b2b0384cd4b9
--- /dev/null
+++ b/drivers/media/video/indycam.c
@@ -0,0 +1,412 @@
+/*
+ * indycam.c - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+/* IndyCam decodes stream of photons into digital image representation ;-) */
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "indycam.h"
+
+//#define INDYCAM_DEBUG
+
+#define INDYCAM_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("SGI IndyCam driver");
+MODULE_VERSION(INDYCAM_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#ifdef INDYCAM_DEBUG
+#define dprintk(x...) printk("IndyCam: " x);
+#define indycam_regdump(client) indycam_regdump_debug(client)
+#else
+#define dprintk(x...)
+#define indycam_regdump(client)
+#endif
+
+#define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO)
+
+struct indycam {
+ struct i2c_client *client;
+ int version;
+};
+
+static struct i2c_driver i2c_driver_indycam;
+
+static const unsigned char initseq[] = {
+ INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
+ INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */
+ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */
+ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */
+ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */
+ INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */
+ INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */
+ INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
+};
+
+/* IndyCam register handling */
+
+static int indycam_read_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char *value)
+{
+ int ret;
+
+ if (reg == INDYCAM_RESET) {
+ dprintk("indycam_read_reg(): "
+ "skipping write-only register %d\n", reg);
+ *value = 0;
+ return 0;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
+ "register = 0x%02x\n", reg);
+ return ret;
+ }
+
+ *value = (unsigned char)ret;
+
+ return 0;
+}
+
+static int indycam_write_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char value)
+{
+ int err;
+
+ if ((reg == INDYCAM_BRIGHTNESS)
+ || (reg == INDYCAM_VERSION)) {
+ dprintk("indycam_write_reg(): "
+ "skipping read-only register %d\n", reg);
+ return 0;
+ }
+
+ dprintk("Writing Reg %d = 0x%02x\n", reg, value);
+ err = i2c_smbus_write_byte_data(client, reg, value);
+ if (err) {
+ printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
+ "register = 0x%02x, value = 0x%02x\n", reg, value);
+ }
+ return err;
+}
+
+static int indycam_write_block(struct i2c_client *client, unsigned char reg,
+ unsigned char length, unsigned char *data)
+{
+ unsigned char i;
+ int err;
+
+ for (i = reg; i < length; i++) {
+ err = indycam_write_reg(client, reg + i, data[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+#ifdef INDYCAM_DEBUG
+static void indycam_regdump_debug(struct i2c_client *client)
+{
+ int i;
+ unsigned char val;
+
+ for (i = 0; i < 9; i++) {
+ indycam_read_reg(client, i, &val);
+ dprintk("Reg %d = 0x%02x\n", i, val);
+ }
+}
+#endif
+
+static int indycam_get_controls(struct i2c_client *client,
+ struct indycam_control *ctrl)
+{
+ unsigned char ctrl_reg;
+
+ indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+ ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA)
+ ? INDYCAM_VALUE_ENABLED
+ : INDYCAM_VALUE_DISABLED;
+ ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL)
+ ? INDYCAM_VALUE_ENABLED
+ : INDYCAM_VALUE_DISABLED;
+ indycam_read_reg(client, INDYCAM_SHUTTER,
+ (unsigned char *)&ctrl->shutter);
+ indycam_read_reg(client, INDYCAM_GAIN,
+ (unsigned char *)&ctrl->gain);
+ indycam_read_reg(client, INDYCAM_RED_BALANCE,
+ (unsigned char *)&ctrl->red_balance);
+ indycam_read_reg(client, INDYCAM_BLUE_BALANCE,
+ (unsigned char *)&ctrl->blue_balance);
+ indycam_read_reg(client, INDYCAM_RED_SATURATION,
+ (unsigned char *)&ctrl->red_saturation);
+ indycam_read_reg(client, INDYCAM_BLUE_SATURATION,
+ (unsigned char *)&ctrl->blue_saturation);
+ indycam_read_reg(client, INDYCAM_GAMMA,
+ (unsigned char *)&ctrl->gamma);
+
+ return 0;
+}
+
+static int indycam_set_controls(struct i2c_client *client,
+ struct indycam_control *ctrl)
+{
+ unsigned char ctrl_reg;
+
+ indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+ if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) {
+ if (ctrl->agc)
+ ctrl_reg |= INDYCAM_CONTROL_AGCENA;
+ else
+ ctrl_reg &= ~INDYCAM_CONTROL_AGCENA;
+ }
+ if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) {
+ if (ctrl->awb)
+ ctrl_reg |= INDYCAM_CONTROL_AWBCTL;
+ else
+ ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL;
+ }
+ indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg);
+
+ if (ctrl->shutter >= 0)
+ indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter);
+ if (ctrl->gain >= 0)
+ indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain);
+ if (ctrl->red_balance >= 0)
+ indycam_write_reg(client, INDYCAM_RED_BALANCE,
+ ctrl->red_balance);
+ if (ctrl->blue_balance >= 0)
+ indycam_write_reg(client, INDYCAM_BLUE_BALANCE,
+ ctrl->blue_balance);
+ if (ctrl->red_saturation >= 0)
+ indycam_write_reg(client, INDYCAM_RED_SATURATION,
+ ctrl->red_saturation);
+ if (ctrl->blue_saturation >= 0)
+ indycam_write_reg(client, INDYCAM_BLUE_SATURATION,
+ ctrl->blue_saturation);
+ if (ctrl->gamma >= 0)
+ indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma);
+
+ return 0;
+}
+
+/* I2C-interface */
+
+static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ int err = 0;
+ struct indycam *camera;
+ struct i2c_client *client;
+
+ printk(KERN_INFO "SGI IndyCam driver version %s\n",
+ INDYCAM_MODULE_VERSION);
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+ camera = kmalloc(sizeof(struct indycam), GFP_KERNEL);
+ if (!camera) {
+ err = -ENOMEM;
+ goto out_free_client;
+ }
+
+ memset(client, 0, sizeof(struct i2c_client));
+ memset(camera, 0, sizeof(struct indycam));
+
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &i2c_driver_indycam;
+ client->flags = 0;
+ strcpy(client->name, "IndyCam client");
+ i2c_set_clientdata(client, camera);
+
+ camera->client = client;
+
+ err = i2c_attach_client(client);
+ if (err)
+ goto out_free_camera;
+
+ camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION);
+ if (camera->version != CAMERA_VERSION_INDY &&
+ camera->version != CAMERA_VERSION_MOOSE) {
+ err = -ENODEV;
+ goto out_detach_client;
+ }
+ printk(KERN_INFO "IndyCam v%d.%d detected\n",
+ INDYCAM_VERSION_MAJOR(camera->version),
+ INDYCAM_VERSION_MINOR(camera->version));
+
+ indycam_regdump(client);
+
+ // initialize
+ err = indycam_write_block(client, 0, sizeof(initseq),
+ (unsigned char *)&initseq);
+ if (err) {
+ printk(KERN_ERR "IndyCam initalization failed\n");
+ err = -EIO;
+ goto out_detach_client;
+ }
+
+ indycam_regdump(client);
+
+ // white balance
+ err = indycam_write_reg(client, INDYCAM_CONTROL,
+ INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
+ if (err) {
+ printk(KERN_ERR "IndyCam white balance "
+ "initialization failed\n");
+ err = -EIO;
+ goto out_detach_client;
+ }
+
+ indycam_regdump(client);
+
+ printk(KERN_INFO "IndyCam initialized\n");
+
+ return 0;
+
+out_detach_client:
+ i2c_detach_client(client);
+out_free_camera:
+ kfree(camera);
+out_free_client:
+ kfree(client);
+ return err;
+}
+
+static int indycam_probe(struct i2c_adapter *adap)
+{
+ /* Indy specific crap */
+ if (adap->id == VINO_ADAPTER)
+ return indycam_attach(adap, INDYCAM_ADDR, 0);
+ /* Feel free to add probe here :-) */
+ return -ENODEV;
+}
+
+static int indycam_detach(struct i2c_client *client)
+{
+ struct indycam *camera = i2c_get_clientdata(client);
+
+ i2c_detach_client(client);
+ kfree(camera);
+ kfree(client);
+ return 0;
+}
+
+static int indycam_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ // struct indycam *camera = i2c_get_clientdata(client);
+
+ /* The old video_decoder interface just isn't enough,
+ * so we'll use some custom commands. */
+ switch (cmd) {
+ case DECODER_GET_CAPABILITIES: {
+ struct video_decoder_capability *cap = arg;
+
+ cap->flags = VIDEO_DECODER_NTSC;
+ cap->inputs = 1;
+ cap->outputs = 1;
+ break;
+ }
+ case DECODER_GET_STATUS: {
+ int *iarg = arg;
+
+ *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
+ DECODER_STATUS_COLOR;
+ break;
+ }
+ case DECODER_SET_NORM: {
+ int *iarg = arg;
+
+ switch (*iarg) {
+ case VIDEO_MODE_NTSC:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_INPUT: {
+ int *iarg = arg;
+
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_SET_OUTPUT: {
+ int *iarg = arg;
+
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_ENABLE_OUTPUT: {
+ /* Always enabled */
+ break;
+ }
+ case DECODER_SET_PICTURE: {
+ // struct video_picture *pic = arg;
+ /* TODO: convert values for indycam_set_controls() */
+ break;
+ }
+ case DECODER_INDYCAM_GET_CONTROLS: {
+ struct indycam_control *ctrl = arg;
+ indycam_get_controls(client, ctrl);
+ }
+ case DECODER_INDYCAM_SET_CONTROLS: {
+ struct indycam_control *ctrl = arg;
+ indycam_set_controls(client, ctrl);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver i2c_driver_indycam = {
+ .owner = THIS_MODULE,
+ .name = "indycam",
+ .id = I2C_DRIVERID_INDYCAM,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = indycam_probe,
+ .detach_client = indycam_detach,
+ .command = indycam_command,
+};
+
+static int __init indycam_init(void)
+{
+ return i2c_add_driver(&i2c_driver_indycam);
+}
+
+static void __exit indycam_exit(void)
+{
+ i2c_del_driver(&i2c_driver_indycam);
+}
+
+module_init(indycam_init);
+module_exit(indycam_exit);
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h
new file mode 100644
index 000000000000..d9ddb6b79a03
--- /dev/null
+++ b/drivers/media/video/indycam.h
@@ -0,0 +1,112 @@
+/*
+ * indycam.h - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _INDYCAM_H_
+#define _INDYCAM_H_
+
+/* I2C address for the Guinness Camera */
+#define INDYCAM_ADDR 0x56
+
+/* Camera version */
+#define CAMERA_VERSION_INDY 0x10 /* v1.0 */
+#define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */
+#define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4)
+#define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f)
+
+/* Register bus addresses */
+#define INDYCAM_CONTROL 0x00
+#define INDYCAM_SHUTTER 0x01
+#define INDYCAM_GAIN 0x02
+#define INDYCAM_BRIGHTNESS 0x03 /* read-only */
+#define INDYCAM_RED_BALANCE 0x04
+#define INDYCAM_BLUE_BALANCE 0x05
+#define INDYCAM_RED_SATURATION 0x06
+#define INDYCAM_BLUE_SATURATION 0x07
+#define INDYCAM_GAMMA 0x08
+#define INDYCAM_VERSION 0x0e /* read-only */
+#define INDYCAM_RESET 0x0f /* write-only */
+
+#define INDYCAM_LED 0x46
+#define INDYCAM_ORIENTATION 0x47
+#define INDYCAM_BUTTON 0x48
+
+/* Field definitions of registers */
+#define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */
+#define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */
+ /* 2-3 are reserved */
+#define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */
+
+#define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */
+#define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */
+#define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */
+#define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */
+#define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */
+#define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */
+#define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */
+#define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */
+#define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */
+
+#define INDYCAM_LED_ACTIVE 0x10
+#define INDYCAM_LED_INACTIVE 0x30
+#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40
+#define INDYCAM_BUTTON_RELEASED 0x10
+
+#define INDYCAM_SHUTTER_MIN 0x00
+#define INDYCAM_SHUTTER_MAX 0xff
+#define INDYCAM_GAIN_MIN 0x00
+#define INDYCAM_GAIN_MAX 0xff
+#define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */
+#define INDYCAM_RED_BALANCE_MAX 0xff
+#define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */
+#define INDYCAM_BLUE_BALANCE_MAX 0xff
+#define INDYCAM_RED_SATURATION_MIN 0x00
+#define INDYCAM_RED_SATURATION_MAX 0xff
+#define INDYCAM_BLUE_SATURATION_MIN 0x00
+#define INDYCAM_BLUE_SATURATION_MAX 0xff
+#define INDYCAM_GAMMA_MIN 0x00
+#define INDYCAM_GAMMA_MAX 0xff
+
+/* Driver interface definitions */
+
+#define INDYCAM_VALUE_ENABLED 1
+#define INDYCAM_VALUE_DISABLED 0
+#define INDYCAM_VALUE_UNCHANGED -1
+
+/* When setting controls, a value of -1 leaves the control unchanged. */
+struct indycam_control {
+ int agc; /* boolean */
+ int awb; /* boolean */
+ int shutter;
+ int gain;
+ int red_balance;
+ int blue_balance;
+ int red_saturation;
+ int blue_saturation;
+ int gamma;
+};
+
+#define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control)
+#define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control)
+
+/* Default values for controls */
+
+#define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED
+#define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED
+
+#define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60
+#define INDYCAM_GAIN_DEFAULT 0x80
+#define INDYCAM_RED_BALANCE_DEFAULT 0x18
+#define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4
+#define INDYCAM_RED_SATURATION_DEFAULT 0x80
+#define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0
+#define INDYCAM_GAMMA_DEFAULT 0x80
+
+#endif
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index a565823330aa..cf292da8fdd5 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
*
* Copyright (c) 2003 Gerd Knorr
* Copyright (c) 2003 Pavel Machek
@@ -354,6 +353,7 @@ static int ir_probe(struct device *dev)
ir->input.id.vendor = sub->core->pci->vendor;
ir->input.id.product = sub->core->pci->device;
}
+ ir->input.dev = &sub->core->pci->dev;
if (ir->polling) {
INIT_WORK(&ir->work, ir_work, ir);
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 9fc5055e001c..67105b9804a2 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-kbd-i2c.c,v 1.11 2005/07/07 16:42:11 mchehab Exp $
*
* keyboard input driver for i2c IR remote controls
*
@@ -308,7 +307,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("unset"),
+ .name = "unset",
.driver = &driver
};
@@ -429,10 +428,10 @@ static int ir_probe(struct i2c_adapter *adap)
struct i2c_client c; char buf; int i,rc;
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
+ case I2C_HW_B_BT848:
probe = probe_bttv;
break;
- case I2C_ALGO_SAA7134:
+ case I2C_HW_SAA7134:
probe = probe_saa7134;
break;
}
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index fe194012bccf..3f2a882bc20a 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
#include "meye.h"
#include <linux/meye.h>
@@ -121,7 +122,7 @@ static int ptable_alloc(void)
memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
/* give only 32 bit DMA addresses */
- if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff))
+ if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK))
return -1;
meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 62f1b8ddb98b..f0d43fc2632f 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -124,10 +124,14 @@ module_param(standard, int, 0644);
module_param(amsound, int, 0644);
module_param(dolby, int, 0644);
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Simple, 2=Simpler");
MODULE_PARM_DESC(once, "No continuous stereo monitoring");
MODULE_PARM_DESC(debug, "Enable debug messages");
+MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo");
MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
+MODULE_PARM_DESC(dolby, "Activates Dolby processsing");
+
MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
MODULE_AUTHOR("Gerd Knorr");
@@ -1416,7 +1420,7 @@ static int msp_detach(struct i2c_client *client);
static int msp_probe(struct i2c_adapter *adap);
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
-static int msp_suspend(struct device * dev, u32 state, u32 level);
+static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
static int msp_resume(struct device * dev, u32 level);
static void msp_wake_thread(struct i2c_client *client);
@@ -1437,7 +1441,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
@@ -1452,7 +1456,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
if (-1 == msp3400c_reset(&client_template)) {
- dprintk("msp3400: no chip found\n");
+ dprintk("msp34xx: no chip found\n");
return -1;
}
@@ -1478,7 +1482,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
if (-1 == msp3400c_reset(c)) {
kfree(msp);
kfree(c);
- dprintk("msp3400: no chip found\n");
+ dprintk("msp34xx: no chip found\n");
return -1;
}
@@ -1488,7 +1492,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
kfree(msp);
kfree(c);
- printk("msp3400: error while reading chip version\n");
+ dprintk("msp34xx: error while reading chip version\n");
return -1;
}
@@ -1509,7 +1513,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
}
/* hello world :-) */
- printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c));
+ printk(KERN_INFO "msp34xx: init: chip=%s", c->name);
if (HAVE_NICAM(msp))
printk(" +nicam");
if (HAVE_SIMPLE(msp))
@@ -1817,7 +1821,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int msp_suspend(struct device * dev, u32 state, u32 level)
+static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index 023f33056a4f..2d9ff40f0b09 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -1,5 +1,4 @@
/*
- * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
*/
#ifndef MSP3400_H
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 2fb7c2d1787a..972aa5e0aeef 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -1,5 +1,4 @@
/*
- * $Id: mt20xx.c,v 1.5 2005/06/16 08:29:49 nsh Exp $
*
* i2c tv tuner chip device driver
* controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -494,6 +493,7 @@ int microtune_init(struct i2c_client *c)
memset(buf,0,sizeof(buf));
t->tv_freq = NULL;
t->radio_freq = NULL;
+ t->standby = NULL;
name = "unknown";
i2c_master_send(c,buf,1);
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
index 3433619ad93f..b3f4d266cede 100644
--- a/drivers/media/video/ovcamchip/ov6x20.c
+++ b/drivers/media/video/ovcamchip/ov6x20.c
@@ -164,10 +164,10 @@ static int ov6x20_init(struct i2c_client *c)
DDEBUG(4, &c->dev, "entered");
switch (c->adapter->id) {
- case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511:
+ case I2C_HW_SMBUS_OV511:
rc = ov_write_regvals(c, regvals_init_6x20_511);
break;
- case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518:
+ case I2C_HW_SMBUS_OV518:
rc = ov_write_regvals(c, regvals_init_6x20_518);
break;
default:
@@ -338,7 +338,7 @@ static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
/******** Palette-specific regs ********/
/* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
if (win->format == VIDEO_PALETTE_GREY)
ov_write_mask(c, 0x13, 0x00, 0x20);
else
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
index 44a842379b45..6eab458ab792 100644
--- a/drivers/media/video/ovcamchip/ov6x30.c
+++ b/drivers/media/video/ovcamchip/ov6x30.c
@@ -301,7 +301,7 @@ static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
/******** Palette-specific regs ********/
if (win->format == VIDEO_PALETTE_GREY) {
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
/* Do nothing - we're already in 8-bit mode */
} else {
ov_write_mask(c, 0x13, 0x20, 0x20);
@@ -313,7 +313,7 @@ static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
* Therefore, the OV6630 needs to be in 8-bit multiplexed
* output mode */
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
/* Do nothing - we want to stay in 8-bit mode */
/* Warning: Messing with reg 0x13 breaks OV518 color */
} else {
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 54dd5612d3b8..2de34ebf0673 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -296,10 +296,10 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
* attach to adapters that are known to contain OV camera chips. */
switch (adap->id) {
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OVFX2):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF):
+ case I2C_HW_SMBUS_OV511:
+ case I2C_HW_SMBUS_OV518:
+ case I2C_HW_SMBUS_OVFX2:
+ case I2C_HW_SMBUS_W9968CF:
PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
break;
default:
@@ -314,7 +314,7 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
}
memcpy(c, &client_template, sizeof *c);
c->adapter = adap;
- strcpy(i2c_clientname(c), "OV????");
+ strcpy(c->name, "OV????");
ov = kmalloc(sizeof *ov, GFP_KERNEL);
if (!ov) {
@@ -328,7 +328,7 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
if (rc < 0)
goto error;
- strcpy(i2c_clientname(c), chip_names[ov->subtype]);
+ strcpy(c->name, chip_names[ov->subtype]);
PDEBUG(1, "Camera chip detection complete");
@@ -421,7 +421,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.driver = &driver,
};
diff --git a/drivers/media/video/rds.h b/drivers/media/video/rds.h
new file mode 100644
index 000000000000..30337d0f1a87
--- /dev/null
+++ b/drivers/media/video/rds.h
@@ -0,0 +1,48 @@
+/*
+
+ Types and defines needed for RDS. This is included by
+ saa6588.c and every driver (e.g. bttv-driver.c) that wants
+ to use the saa6588 module.
+
+ Instead of having a seperate rds.h, I'd prefer to include
+ this stuff in one of the already existing files like tuner.h
+
+ (c) 2005 by Hans J. Koch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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 _RDS_H
+#define _RDS_H
+
+struct rds_command {
+ unsigned int block_count;
+ int result;
+ unsigned char *buffer;
+ struct file *instance;
+ poll_table *event_list;
+};
+
+#define RDS_CMD_OPEN _IOW('R',1,int)
+#define RDS_CMD_CLOSE _IOW('R',2,int)
+#define RDS_CMD_READ _IOR('R',3,int)
+#define RDS_CMD_POLL _IOR('R',4,int)
+
+#endif
+
+
+
+
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
new file mode 100644
index 000000000000..1a657a70ff43
--- /dev/null
+++ b/drivers/media/video/saa6588.c
@@ -0,0 +1,534 @@
+/*
+ Driver for SAA6588 RDS decoder
+
+ (c) 2005 Hans J. Koch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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/kernel.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include <media/id.h>
+
+#include "rds.h"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {
+ 0x20 >> 1,
+ 0x22 >> 1,
+ I2C_CLIENT_END,
+};
+
+I2C_CLIENT_INSMOD;
+
+/* insmod options */
+static unsigned int debug = 0;
+static unsigned int xtal = 0;
+static unsigned int rbds = 0;
+static unsigned int plvl = 0;
+static unsigned int bufblocks = 100;
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "enable debug messages");
+MODULE_PARM(xtal, "i");
+MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
+MODULE_PARM(rbds, "i");
+MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
+MODULE_PARM(plvl, "i");
+MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
+MODULE_PARM(bufblocks, "i");
+MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
+
+MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
+MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>");
+
+MODULE_LICENSE("GPL");
+
+/* ---------------------------------------------------------------------- */
+
+#define UNSET (-1U)
+#define PREFIX "saa6588: "
+#define dprintk if (debug) printk
+
+struct saa6588 {
+ struct i2c_client client;
+ struct work_struct work;
+ struct timer_list timer;
+ spinlock_t lock;
+ unsigned char *buffer;
+ unsigned int buf_size;
+ unsigned int rd_index;
+ unsigned int wr_index;
+ unsigned int block_count;
+ unsigned char last_blocknum;
+ wait_queue_head_t read_queue;
+ int data_available_for_read;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * SAA6588 defines
+ */
+
+/* Initialization and mode control byte (0w) */
+
+/* bit 0+1 (DAC0/DAC1) */
+#define cModeStandard 0x00
+#define cModeFastPI 0x01
+#define cModeReducedRequest 0x02
+#define cModeInvalid 0x03
+
+/* bit 2 (RBDS) */
+#define cProcessingModeRDS 0x00
+#define cProcessingModeRBDS 0x04
+
+/* bit 3+4 (SYM0/SYM1) */
+#define cErrCorrectionNone 0x00
+#define cErrCorrection2Bits 0x08
+#define cErrCorrection5Bits 0x10
+#define cErrCorrectionNoneRBDS 0x18
+
+/* bit 5 (NWSY) */
+#define cSyncNormal 0x00
+#define cSyncRestart 0x20
+
+/* bit 6 (TSQD) */
+#define cSigQualityDetectOFF 0x00
+#define cSigQualityDetectON 0x40
+
+/* bit 7 (SQCM) */
+#define cSigQualityTriggered 0x00
+#define cSigQualityContinous 0x80
+
+/* Pause level and flywheel control byte (1w) */
+
+/* bits 0..5 (FEB0..FEB5) */
+#define cFlywheelMaxBlocksMask 0x3F
+#define cFlywheelDefault 0x20
+
+/* bits 6+7 (PL0/PL1) */
+#define cPauseLevel_11mV 0x00
+#define cPauseLevel_17mV 0x40
+#define cPauseLevel_27mV 0x80
+#define cPauseLevel_43mV 0xC0
+
+/* Pause time/oscillator frequency/quality detector control byte (1w) */
+
+/* bits 0..4 (SQS0..SQS4) */
+#define cQualityDetectSensMask 0x1F
+#define cQualityDetectDefault 0x0F
+
+/* bit 5 (SOSC) */
+#define cSelectOscFreqOFF 0x00
+#define cSelectOscFreqON 0x20
+
+/* bit 6+7 (PTF0/PTF1) */
+#define cOscFreq_4332kHz 0x00
+#define cOscFreq_8664kHz 0x40
+#define cOscFreq_12996kHz 0x80
+#define cOscFreq_17328kHz 0xC0
+
+/* ---------------------------------------------------------------------- */
+
+static int block_to_user_buf(struct saa6588 *s, unsigned char *user_buf)
+{
+ int i;
+
+ if (s->rd_index == s->wr_index) {
+ if (debug > 2)
+ dprintk(PREFIX "Read: buffer empty.\n");
+ return 0;
+ }
+
+ if (debug > 2) {
+ dprintk(PREFIX "Read: ");
+ for (i = s->rd_index; i < s->rd_index + 3; i++)
+ dprintk("0x%02x ", s->buffer[i]);
+ }
+
+ if (copy_to_user(user_buf, &s->buffer[s->rd_index], 3))
+ return -EFAULT;
+
+ s->rd_index += 3;
+ if (s->rd_index >= s->buf_size)
+ s->rd_index = 0;
+ s->block_count--;
+
+ if (debug > 2)
+ dprintk("%d blocks total.\n", s->block_count);
+
+ return 1;
+}
+
+static void read_from_buf(struct saa6588 *s, struct rds_command *a)
+{
+ unsigned long flags;
+
+ unsigned char *buf_ptr = a->buffer; /* This is a user space buffer! */
+ unsigned int i;
+ unsigned int rd_blocks;
+
+ a->result = 0;
+ if (!a->buffer)
+ return;
+
+ while (!s->data_available_for_read) {
+ int ret = wait_event_interruptible(s->read_queue,
+ s->data_available_for_read);
+ if (ret == -ERESTARTSYS) {
+ a->result = -EINTR;
+ return;
+ }
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+ rd_blocks = a->block_count;
+ if (rd_blocks > s->block_count)
+ rd_blocks = s->block_count;
+
+ if (!rd_blocks)
+ return;
+
+ for (i = 0; i < rd_blocks; i++) {
+ if (block_to_user_buf(s, buf_ptr)) {
+ buf_ptr += 3;
+ a->result++;
+ } else
+ break;
+ }
+ a->result *= 3;
+ s->data_available_for_read = (s->block_count > 0);
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf)
+{
+ unsigned int i;
+
+ if (debug > 3)
+ dprintk(PREFIX "New block: ");
+
+ for (i = 0; i < 3; ++i) {
+ if (debug > 3)
+ dprintk("0x%02x ", blockbuf[i]);
+ s->buffer[s->wr_index] = blockbuf[i];
+ s->wr_index++;
+ }
+
+ if (s->wr_index >= s->buf_size)
+ s->wr_index = 0;
+
+ if (s->wr_index == s->rd_index) {
+ s->rd_index++;
+ if (s->rd_index >= s->buf_size)
+ s->rd_index = 0;
+ } else
+ s->block_count++;
+
+ if (debug > 3)
+ dprintk("%d blocks total.\n", s->block_count);
+}
+
+static void saa6588_i2c_poll(struct saa6588 *s)
+{
+ unsigned long flags;
+ unsigned char tmpbuf[6];
+ unsigned char blocknum;
+ unsigned char tmp;
+
+ /* Although we only need 3 bytes, we have to read at least 6.
+ SAA6588 returns garbage otherwise */
+ if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) {
+ if (debug > 1)
+ dprintk(PREFIX "read error!\n");
+ return;
+ }
+
+ blocknum = tmpbuf[0] >> 5;
+ if (blocknum == s->last_blocknum) {
+ if (debug > 3)
+ dprintk("Saw block %d again.\n", blocknum);
+ return;
+ }
+
+ s->last_blocknum = blocknum;
+
+ /*
+ Byte order according to v4l2 specification:
+
+ Byte 0: Least Significant Byte of RDS Block
+ Byte 1: Most Significant Byte of RDS Block
+ Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error
+ occurred during reception of this block.
+ Bit 6: Corrected bit. Indicates that an error was
+ corrected for this data block.
+ Bits 5-3: Received Offset. Indicates the offset received
+ by the sync system.
+ Bits 2-0: Offset Name. Indicates the offset applied to this data.
+
+ SAA6588 byte order is Status-MSB-LSB, so we have to swap the
+ first and the last of the 3 bytes block.
+ */
+
+ tmp = tmpbuf[2];
+ tmpbuf[2] = tmpbuf[0];
+ tmpbuf[0] = tmp;
+
+ tmp = blocknum;
+ tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */
+ if ((tmpbuf[2] & 0x03) == 0x03)
+ tmp |= 0x80; /* uncorrectable error */
+ else if ((tmpbuf[2] & 0x03) != 0x00)
+ tmp |= 0x40; /* corrected error */
+ tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */
+
+ spin_lock_irqsave(&s->lock, flags);
+ block_to_buf(s, tmpbuf);
+ spin_unlock_irqrestore(&s->lock, flags);
+ s->data_available_for_read = 1;
+ wake_up_interruptible(&s->read_queue);
+}
+
+static void saa6588_timer(unsigned long data)
+{
+ struct saa6588 *s = (struct saa6588 *)data;
+
+ schedule_work(&s->work);
+}
+
+static void saa6588_work(void *data)
+{
+ struct saa6588 *s = (struct saa6588 *)data;
+
+ saa6588_i2c_poll(s);
+ mod_timer(&s->timer, jiffies + HZ / 50); /* 20 msec */
+}
+
+static int saa6588_configure(struct saa6588 *s)
+{
+ unsigned char buf[3];
+ int rc;
+
+ buf[0] = cSyncRestart;
+ if (rbds)
+ buf[0] |= cProcessingModeRBDS;
+
+ buf[1] = cFlywheelDefault;
+ switch (plvl) {
+ case 0:
+ buf[1] |= cPauseLevel_11mV;
+ break;
+ case 1:
+ buf[1] |= cPauseLevel_17mV;
+ break;
+ case 2:
+ buf[1] |= cPauseLevel_27mV;
+ break;
+ case 3:
+ buf[1] |= cPauseLevel_43mV;
+ break;
+ default: /* nothing */
+ break;
+ }
+
+ buf[2] = cQualityDetectDefault | cSelectOscFreqON;
+
+ switch (xtal) {
+ case 0:
+ buf[2] |= cOscFreq_4332kHz;
+ break;
+ case 1:
+ buf[2] |= cOscFreq_8664kHz;
+ break;
+ case 2:
+ buf[2] |= cOscFreq_12996kHz;
+ break;
+ case 3:
+ buf[2] |= cOscFreq_17328kHz;
+ break;
+ default: /* nothing */
+ break;
+ }
+
+ dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",
+ buf[0], buf[1], buf[2]);
+
+ if (3 != (rc = i2c_master_send(&s->client, buf, 3)))
+ printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct saa6588 *s;
+ client_template.adapter = adap;
+ client_template.addr = addr;
+
+ printk(PREFIX "chip found @ 0x%x\n", addr << 1);
+
+ if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL)))
+ return -ENOMEM;
+
+ s->buf_size = bufblocks * 3;
+
+ if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) {
+ kfree(s);
+ return -ENOMEM;
+ }
+ s->client = client_template;
+ s->block_count = 0;
+ s->wr_index = 0;
+ s->rd_index = 0;
+ s->last_blocknum = 0xff;
+ init_waitqueue_head(&s->read_queue);
+ s->data_available_for_read = 0;
+ i2c_set_clientdata(&s->client, s);
+ i2c_attach_client(&s->client);
+
+ saa6588_configure(s);
+
+ /* start polling via eventd */
+ INIT_WORK(&s->work, saa6588_work, s);
+ init_timer(&s->timer);
+ s->timer.function = saa6588_timer;
+ s->timer.data = (unsigned long)s;
+ schedule_work(&s->work);
+
+ return 0;
+}
+
+static int saa6588_probe(struct i2c_adapter *adap)
+{
+#ifdef I2C_CLASS_TV_ANALOG
+ if (adap->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, saa6588_attach);
+#else
+ switch (adap->id) {
+ case I2C_ALGO_BIT | I2C_HW_B_BT848:
+ case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+ case I2C_ALGO_SAA7134:
+ return i2c_probe(adap, &addr_data, saa6588_attach);
+ break;
+ }
+#endif
+ return 0;
+}
+
+static int saa6588_detach(struct i2c_client *client)
+{
+ struct saa6588 *s = i2c_get_clientdata(client);
+
+ del_timer_sync(&s->timer);
+ flush_scheduled_work();
+
+ i2c_detach_client(client);
+ kfree(s->buffer);
+ kfree(s);
+ return 0;
+}
+
+static int saa6588_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ struct saa6588 *s = i2c_get_clientdata(client);
+ struct rds_command *a = (struct rds_command *)arg;
+
+ switch (cmd) {
+ /* --- open() for /dev/radio --- */
+ case RDS_CMD_OPEN:
+ a->result = 0; /* return error if chip doesn't work ??? */
+ break;
+ /* --- close() for /dev/radio --- */
+ case RDS_CMD_CLOSE:
+ s->data_available_for_read = 1;
+ wake_up_interruptible(&s->read_queue);
+ a->result = 0;
+ break;
+ /* --- read() for /dev/radio --- */
+ case RDS_CMD_READ:
+ read_from_buf(s, a);
+ break;
+ /* --- poll() for /dev/radio --- */
+ case RDS_CMD_POLL:
+ a->result = 0;
+ if (s->data_available_for_read) {
+ a->result |= POLLIN | POLLRDNORM;
+ }
+ poll_wait(a->instance, &s->read_queue, a->event_list);
+ break;
+
+ default:
+ /* nothing */
+ break;
+ }
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver driver = {
+ .owner = THIS_MODULE,
+ .name = "i2c saa6588 driver",
+ .id = -1, /* FIXME */
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = saa6588_probe,
+ .detach_client = saa6588_detach,
+ .command = saa6588_command,
+};
+
+static struct i2c_client client_template = {
+ .name = "saa6588",
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
+};
+
+static int __init saa6588_init_module(void)
+{
+ return i2c_add_driver(&driver);
+}
+
+static void __exit saa6588_cleanup_module(void)
+{
+ i2c_del_driver(&driver);
+}
+
+module_init(saa6588_init_module);
+module_exit(saa6588_cleanup_module);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 22d055d8a695..e116bdbed310 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -470,7 +470,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7110;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fcd897382fcf..fe8a5e453969 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -42,7 +42,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -489,7 +488,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7111;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 2ba997f5ef1d..d9f50e2f7b92 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -45,7 +45,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -827,7 +826,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7114;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 79d05ea1b69b..382911c6ef22 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -598,7 +598,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("saa6752hs"),
+ .name = "saa6752hs",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 88b71a20b602..acc7a4335e23 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-cards.c,v 1.80 2005/07/07 01:49:30 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* card-specific stuff.
@@ -1373,7 +1372,7 @@ struct saa7134_board saa7134_boards[] = {
.inputs = {{
.name = name_comp1,
.vmux = 1,
- .amux = LINE2,
+ .amux = LINE1,
},{
.name = name_tv,
.vmux = 3,
@@ -1382,7 +1381,7 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE2,
+ .amux = LINE1,
}},
.radio = {
.name = name_radio,
@@ -2001,6 +2000,115 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000,
},
},
+ [SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
+ .name = "FlyTV mini Asus Digimatrix",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_LG_NTSC_TALN_MINI,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio, /* radio unconfirmed */
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_KWORLD_TERMINATOR] = {
+ /* Kworld V-Stream Studio TV Terminator */
+ /* "James Webb <jrwebb@qwest.net> */
+ .name = "V-Stream Studio TV Terminator",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 1 << 21,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x0000000,
+ .tv = 1,
+ },{
+ .name = name_comp1, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ .gpio = 0x0000000,
+ },{
+ .name = name_svideo, /* S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ .gpio = 0x0000000,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_YUAN_TUN900] = {
+ /* FIXME:
+ * S-Video and composite sources untested.
+ * Radio not working.
+ * Remote control not yet implemented.
+ * From : codemaster@webgeeks.be */
+ .name = "Yuan TUN-900 (saa7135)",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr= ADDR_UNSET,
+ .radio_addr= ADDR_UNSET,
+ .gpiomask = 0x00010003,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x01,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ .gpio = 0x02,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE2,
+ .gpio = 0x02,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x00010003,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x01,
+ },
+ },
};
@@ -2272,12 +2380,6 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
- .subvendor = 0x1131,
- .subdevice = 0,
- .driver_data = SAA7134_BOARD_SABRENT_SBTTVFM,
- },{
- .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x1461, /* Avermedia Technologies Inc */
.subdevice = 0x9715,
@@ -2346,6 +2448,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x4e42,
.subdevice = 0x0502,
.driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1043,
+ .subdevice = 0x0210, /* mini pci NTSC version */
+ .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1043,
+ .subdevice = 0x0210, /* mini pci PAL/SECAM version */
+ .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX,
},{
/* --- boards without eeprom + subsystem ID --- */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 1dbe61755e9f..e5e36f3c6250 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-core.c,v 1.39 2005/07/05 17:37:35 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* driver core
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 8be6a90358c8..639ae51a052d 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-dvb.c,v 1.23 2005/07/24 22:12:47 mkrufky Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
@@ -29,7 +28,6 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/suspend.h>
-#include <linux/config.h>
#include "saa7134-reg.h"
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index c85348d0239f..77b627eb6483 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 1203b93a572c..711aa8e85fac 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* i2c interface support
@@ -334,7 +333,7 @@ static int attach_inform(struct i2c_client *client)
struct tuner_setup tun_setup;
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name,client->addr,i2c_clientname(client));
+ client->driver->name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -370,8 +369,6 @@ static int attach_inform(struct i2c_client *client)
}
static struct i2c_algorithm saa7134_algo = {
- .name = "saa7134",
- .id = I2C_ALGO_SAA7134,
.master_xfer = saa7134_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
@@ -382,14 +379,14 @@ static struct i2c_adapter saa7134_adap_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("saa7134"),
- .id = I2C_ALGO_SAA7134,
+ .name = "saa7134",
+ .id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
.client_register = attach_inform,
};
static struct i2c_client saa7134_client_template = {
- I2C_DEVNAME("saa7134 internal"),
+ .name = "saa7134 internal",
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 213740122fe6..1f456c4d76f2 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-input.c,v 1.21 2005/06/22 23:37:34 nsh Exp $
*
* handle saa7134 IR remotes via linux kernel input layer.
*
@@ -565,6 +564,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
ir->dev.id.vendor = dev->pci->vendor;
ir->dev.id.product = dev->pci->device;
}
+ ir->dev.dev = &dev->pci->dev;
/* all done */
dev->remote = ir;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index b5bede95dbf5..c20630c82f1c 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-oss.c,v 1.17 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* oss dsp interface
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
index 87734f22af7d..ae0c7a165390 100644
--- a/drivers/media/video/saa7134/saa7134-reg.h
+++ b/drivers/media/video/saa7134/saa7134-reg.h
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-reg.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
*
* philips saa7134 registers
*/
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 4dd9f1b23928..463885601ab4 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-ts.c,v 1.15 2005/06/14 22:48:18 hhackmann Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index eeafa5a71d2b..badf2f9e3072 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-tvaudio.c,v 1.30 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* tv audio decoder (fm stereo, nicam, ...)
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 29e51cad2aaf..f4aee0af80e1 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index a4c2f751d097..35e5e85f669a 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-video.c,v 1.36 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -1368,29 +1367,7 @@ static int video_release(struct inode *inode, struct file *file)
saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
- if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
- u8 data[2];
- int ret;
- struct i2c_msg msg = {.addr=I2C_ADDR_TDA8290, .flags=0, .buf=data, .len = 2};
- data[0] = 0x21;
- data[1] = 0xc0;
- ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
- if (ret != 1)
- printk(KERN_ERR "TDA8290 access failure\n");
- msg.addr = I2C_ADDR_TDA8275;
- data[0] = 0x30;
- data[1] = 0xd0;
- ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
- if (ret != 1)
- printk(KERN_ERR "TDA8275 access failure\n");
- msg.addr = I2C_ADDR_TDA8290;
- data[0] = 0x21;
- data[1] = 0x80;
- i2c_transfer(&dev->i2c_adap, &msg, 1);
- data[0] = 0x00;
- data[1] = 0x02;
- i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
+ saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
/* free stuff */
videobuf_mmap_free(&fh->cap);
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 2af0cb2a731b..3ea09142ec9c 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $
*
* v4l2 device driver for philips saa7134 based TV cards
*
@@ -185,6 +184,9 @@ struct saa7134_format {
#define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63
+#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
+#define SAA7134_BOARD_KWORLD_TERMINATOR 65
+#define SAA7134_BOARD_YUAN_TUN900 66
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 108e7a4a0273..132aa7943c16 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -39,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -387,7 +386,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7185;
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
new file mode 100644
index 000000000000..454f5c1199b4
--- /dev/null
+++ b/drivers/media/video/saa7191.c
@@ -0,0 +1,512 @@
+/*
+ * saa7191.c - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO)
+
+struct saa7191 {
+ struct i2c_client *client;
+
+ /* the register values are stored here as the actual
+ * I2C-registers are write-only */
+ unsigned char reg[25];
+
+ unsigned char norm;
+ unsigned char input;
+};
+
+static struct i2c_driver i2c_driver_saa7191;
+
+static const unsigned char initseq[] = {
+ 0, /* Subaddress */
+ 0x50, /* SAA7191_REG_IDEL */
+ 0x30, /* SAA7191_REG_HSYB */
+ 0x00, /* SAA7191_REG_HSYS */
+ 0xe8, /* SAA7191_REG_HCLB */
+ 0xb6, /* SAA7191_REG_HCLS */
+ 0xf4, /* SAA7191_REG_HPHI */
+ 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */
+ 0x00, /* SAA7191_REG_HUEC */
+ 0xf8, /* SAA7191_REG_CKTQ */
+ 0xf8, /* SAA7191_REG_CKTS */
+ 0x90, /* SAA7191_REG_PLSE */
+ 0x90, /* SAA7191_REG_SESE */
+ 0x00, /* SAA7191_REG_GAIN */
+ 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */
+ 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */
+ 0x99, /* SAA7191_REG_CTL3 - automatic field detection */
+ 0x00, /* SAA7191_REG_CTL4 */
+ 0x2c, /* SAA7191_REG_CHCV */
+ 0x00, /* unused */
+ 0x00, /* unused */
+ 0x34, /* SAA7191_REG_HS6B */
+ 0x0a, /* SAA7191_REG_HS6S */
+ 0xf4, /* SAA7191_REG_HC6B */
+ 0xce, /* SAA7191_REG_HC6S */
+ 0xf4, /* SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static unsigned char saa7191_read_reg(struct i2c_client *client,
+ unsigned char reg)
+{
+ return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
+}
+
+static int saa7191_read_status(struct i2c_client *client,
+ unsigned char *value)
+{
+ int ret;
+
+ ret = i2c_master_recv(client, value, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int saa7191_write_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char value)
+{
+
+ ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* the first byte of data must be the first subaddress number (register) */
+static int saa7191_write_block(struct i2c_client *client,
+ unsigned char length, unsigned char *data)
+{
+ int i;
+ int ret;
+
+ struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
+ for (i = 0; i < (length - 1); i++) {
+ decoder->reg[data[0] + i] = data[i + 1];
+ }
+
+ ret = i2c_master_send(client, data, length);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+ "write failed");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_set_input(struct i2c_client *client, int input)
+{
+ unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
+ unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
+ int err;
+
+ switch (input) {
+ case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+ | SAA7191_IOCK_GPSW2);
+ /* Chrominance trap active */
+ luma &= ~SAA7191_LUMA_BYPS;
+ break;
+ case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+ iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+ /* Chrominance trap bypassed */
+ luma |= SAA7191_LUMA_BYPS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
+ if (err)
+ return -EIO;
+
+ return 0;
+}
+
+static int saa7191_set_norm(struct i2c_client *client, int norm)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+ unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+ unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
+ unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
+ int err;
+
+ switch(norm) {
+ case SAA7191_NORM_AUTO: {
+ unsigned char status;
+
+ // does status depend on current norm ?
+ if (saa7191_read_status(client, &status))
+ return -EIO;
+
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~SAA7191_CTL3_FSEL;
+ ctl3 |= SAA7191_CTL3_AUFD;
+ chcv = (status & SAA7191_STATUS_FIDT)
+ ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL;
+ break;
+ }
+ case SAA7191_NORM_PAL:
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ break;
+ case SAA7191_NORM_NTSC:
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~SAA7191_CTL3_AUFD;
+ ctl3 |= SAA7191_CTL3_FSEL;
+ chcv = SAA7191_CHCV_NTSC;
+ break;
+ case SAA7191_NORM_SECAM:
+ stdc |= SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
+ if (err)
+ return -EIO;
+
+ decoder->norm = norm;
+
+ return 0;
+}
+
+static int saa7191_get_controls(struct i2c_client *client,
+ struct saa7191_control *ctrl)
+{
+ unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC);
+ unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+
+ if (hue < 0x80) {
+ hue += 0x80;
+ } else {
+ hue -= 0x80;
+ }
+ ctrl->hue = hue;
+
+ ctrl->vtrc = (stdc & SAA7191_STDC_VTRC)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+ return 0;
+}
+
+static int saa7191_set_controls(struct i2c_client *client,
+ struct saa7191_control *ctrl)
+{
+ int err;
+
+ if (ctrl->hue >= 0) {
+ unsigned char hue = ctrl->hue & 0xff;
+ if (hue < 0x80) {
+ hue += 0x80;
+ } else {
+ hue -= 0x80;
+ }
+ err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue);
+ if (err)
+ return -EIO;
+ }
+ if (ctrl->vtrc >= 0) {
+ unsigned char stdc =
+ saa7191_read_reg(client, SAA7191_REG_STDC);
+
+ if (ctrl->vtrc) {
+ stdc |= SAA7191_STDC_VTRC;
+ } else {
+ stdc &= ~SAA7191_STDC_VTRC;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ if (err)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* I2C-interface */
+
+static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ int err = 0;
+ struct saa7191 *decoder;
+ struct i2c_client *client;
+
+ printk(KERN_INFO "Philips SAA7191 driver version %s\n",
+ SAA7191_MODULE_VERSION);
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+ decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+ if (!decoder) {
+ err = -ENOMEM;
+ goto out_free_client;
+ }
+
+ memset(client, 0, sizeof(struct i2c_client));
+ memset(decoder, 0, sizeof(struct saa7191));
+
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &i2c_driver_saa7191;
+ client->flags = 0;
+ strcpy(client->name, "saa7191 client");
+ i2c_set_clientdata(client, decoder);
+
+ decoder->client = client;
+
+ err = i2c_attach_client(client);
+ if (err)
+ goto out_free_decoder;
+
+ decoder->input = SAA7191_INPUT_COMPOSITE;
+ decoder->norm = SAA7191_NORM_AUTO;
+
+ err = saa7191_write_block(client, sizeof(initseq),
+ (unsigned char *)initseq);
+ if (err) {
+ printk(KERN_ERR "SAA7191 initialization failed\n");
+ goto out_detach_client;
+ }
+
+ printk(KERN_INFO "SAA7191 initialized\n");
+
+ return 0;
+
+out_detach_client:
+ i2c_detach_client(client);
+out_free_decoder:
+ kfree(decoder);
+out_free_client:
+ kfree(client);
+ return err;
+}
+
+static int saa7191_probe(struct i2c_adapter *adap)
+{
+ /* Always connected to VINO */
+ if (adap->id == VINO_ADAPTER)
+ return saa7191_attach(adap, SAA7191_ADDR, 0);
+ /* Feel free to add probe here :-) */
+ return -ENODEV;
+}
+
+static int saa7191_detach(struct i2c_client *client)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+
+ i2c_detach_client(client);
+ kfree(decoder);
+ kfree(client);
+ return 0;
+}
+
+static int saa7191_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case DECODER_GET_CAPABILITIES: {
+ struct video_decoder_capability *cap = arg;
+
+ cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
+ VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
+ cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1;
+ cap->outputs = 1;
+ break;
+ }
+ case DECODER_GET_STATUS: {
+ int *iarg = arg;
+ unsigned char status;
+ int res = 0;
+
+ if (saa7191_read_status(client, &status)) {
+ return -EIO;
+ }
+ if ((status & SAA7191_STATUS_HLCK) == 0)
+ res |= DECODER_STATUS_GOOD;
+ if (status & SAA7191_STATUS_CODE)
+ res |= DECODER_STATUS_COLOR;
+ switch (decoder->norm) {
+ case SAA7191_NORM_NTSC:
+ res |= DECODER_STATUS_NTSC;
+ break;
+ case SAA7191_NORM_PAL:
+ res |= DECODER_STATUS_PAL;
+ break;
+ case SAA7191_NORM_SECAM:
+ res |= DECODER_STATUS_SECAM;
+ break;
+ case SAA7191_NORM_AUTO:
+ default:
+ if (status & SAA7191_STATUS_FIDT)
+ res |= DECODER_STATUS_NTSC;
+ else
+ res |= DECODER_STATUS_PAL;
+ break;
+ }
+ *iarg = res;
+ break;
+ }
+ case DECODER_SET_NORM: {
+ int *iarg = arg;
+
+ switch (*iarg) {
+ case VIDEO_MODE_AUTO:
+ return saa7191_set_norm(client, SAA7191_NORM_AUTO);
+ case VIDEO_MODE_PAL:
+ return saa7191_set_norm(client, SAA7191_NORM_PAL);
+ case VIDEO_MODE_NTSC:
+ return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+ case VIDEO_MODE_SECAM:
+ return saa7191_set_norm(client, SAA7191_NORM_SECAM);
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_INPUT: {
+ int *iarg = arg;
+
+ switch (client->adapter->id) {
+ case VINO_ADAPTER:
+ return saa7191_set_input(client, *iarg);
+ default:
+ if (*iarg != 0)
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_OUTPUT: {
+ int *iarg = arg;
+
+ /* not much choice of outputs */
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_ENABLE_OUTPUT: {
+ /* Always enabled */
+ break;
+ }
+ case DECODER_SET_PICTURE: {
+ struct video_picture *pic = arg;
+ unsigned val;
+ int err;
+
+ val = (pic->hue >> 8) - 0x80;
+ err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
+ if (err)
+ return -EIO;
+ break;
+ }
+ case DECODER_SAA7191_GET_STATUS: {
+ struct saa7191_status *status = arg;
+ unsigned char status_reg;
+
+ if (saa7191_read_status(client, &status_reg))
+ return -EIO;
+ status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+ status->ntsc = (status_reg & SAA7191_STATUS_FIDT)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+ status->color = (status_reg & SAA7191_STATUS_CODE)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+ status->input = decoder->input;
+ status->norm = decoder->norm;
+ }
+ case DECODER_SAA7191_SET_NORM: {
+ int *norm = arg;
+ return saa7191_set_norm(client, *norm);
+ }
+ case DECODER_SAA7191_GET_CONTROLS: {
+ struct saa7191_control *ctrl = arg;
+ return saa7191_get_controls(client, ctrl);
+ }
+ case DECODER_SAA7191_SET_CONTROLS: {
+ struct saa7191_control *ctrl = arg;
+ return saa7191_set_controls(client, ctrl);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver i2c_driver_saa7191 = {
+ .owner = THIS_MODULE,
+ .name = "saa7191",
+ .id = I2C_DRIVERID_SAA7191,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = saa7191_probe,
+ .detach_client = saa7191_detach,
+ .command = saa7191_command
+};
+
+static int saa7191_init(void)
+{
+ return i2c_add_driver(&i2c_driver_saa7191);
+}
+
+static void saa7191_exit(void)
+{
+ i2c_del_driver(&i2c_driver_saa7191);
+}
+
+module_init(saa7191_init);
+module_exit(saa7191_exit);
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h
new file mode 100644
index 000000000000..272045031435
--- /dev/null
+++ b/drivers/media/video/saa7191.h
@@ -0,0 +1,139 @@
+/*
+ * saa7191.h - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR 0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL 0x00
+#define SAA7191_REG_HSYB 0x01
+#define SAA7191_REG_HSYS 0x02
+#define SAA7191_REG_HCLB 0x03
+#define SAA7191_REG_HCLS 0x04
+#define SAA7191_REG_HPHI 0x05
+#define SAA7191_REG_LUMA 0x06
+#define SAA7191_REG_HUEC 0x07
+#define SAA7191_REG_CKTQ 0x08
+#define SAA7191_REG_CKTS 0x09
+#define SAA7191_REG_PLSE 0x0a
+#define SAA7191_REG_SESE 0x0b
+#define SAA7191_REG_GAIN 0x0c
+#define SAA7191_REG_STDC 0x0d
+#define SAA7191_REG_IOCK 0x0e
+#define SAA7191_REG_CTL3 0x0f
+#define SAA7191_REG_CTL4 0x10
+#define SAA7191_REG_CHCV 0x11
+#define SAA7191_REG_HS6B 0x14
+#define SAA7191_REG_HS6S 0x15
+#define SAA7191_REG_HC6B 0x16
+#define SAA7191_REG_HC6S 0x17
+#define SAA7191_REG_HP6I 0x18
+#define SAA7191_REG_STATUS 0xff /* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE 0x01 /* color detected flag */
+#define SAA7191_STATUS_FIDT 0x20 /* format type NTSC/PAL */
+#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked/locked */
+#define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+#define SAA7191_LUMA_BYPS 0x80
+
+/* Chroma Gain Control Settings Register definitions */
+/* 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO 0x80
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC 0x80
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS 0x01
+/* the bit fields above must be or'd with this value */
+#define SAA7191_STDC_VALUE 0x0c
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL 0x80
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS 0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2 0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1 0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD 0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL 0x40
+/* the bit fields above must be or'd with this value */
+#define SAA7191_CTL3_VALUE 0x19
+
+/* Chrominance Gain Control Register definitions
+ * (nominal value for UV CCIR level) */
+#define SAA7191_CHCV_NTSC 0x2c
+#define SAA7191_CHCV_PAL 0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE 0
+#define SAA7191_INPUT_SVIDEO 1
+
+#define SAA7191_NORM_AUTO 0
+#define SAA7191_NORM_PAL 1
+#define SAA7191_NORM_NTSC 2
+#define SAA7191_NORM_SECAM 3
+
+#define SAA7191_VALUE_ENABLED 1
+#define SAA7191_VALUE_DISABLED 0
+#define SAA7191_VALUE_UNCHANGED -1
+
+struct saa7191_status {
+ /* 0=no signal, 1=signal active*/
+ int signal;
+ /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+ int ntsc;
+ /* 0=no color detected, 1=color detected */
+ int color;
+
+ /* current SAA7191_INPUT_ */
+ int input;
+ /* current SAA7191_NORM_ */
+ int norm;
+};
+
+#define SAA7191_HUE_MIN 0x00
+#define SAA7191_HUE_MAX 0xff
+#define SAA7191_HUE_DEFAULT 0x80
+
+#define SAA7191_VTRC_MIN 0x00
+#define SAA7191_VTRC_MAX 0x01
+#define SAA7191_VTRC_DEFAULT 0x00
+
+struct saa7191_control {
+ int hue;
+ int vtrc;
+};
+
+#define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status)
+#define DECODER_SAA7191_SET_NORM _IOW('d', 196, int)
+#define DECODER_SAA7191_GET_CONTROLS _IOR('d', 197, struct saa7191_control)
+#define DECODER_SAA7191_SET_CONTROLS _IOW('d', 198, struct saa7191_control)
+
+#endif
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index b57743571087..d4497dbae05c 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2184,30 +2184,18 @@ static void release_saa(void)
vfree(saa->vidbuf);
vfree(saa->audbuf);
vfree(saa->osdbuf);
- if (saa->dmavid2)
- kfree((void *) saa->dmavid2);
+ kfree(saa->dmavid2);
saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
saa->dmavid2 = NULL;
- if (saa->dmadebi)
- kfree((void *) saa->dmadebi);
- if (saa->dmavid1)
- kfree((void *) saa->dmavid1);
- if (saa->dmavid2)
- kfree((void *) saa->dmavid2);
- if (saa->dmavid3)
- kfree((void *) saa->dmavid3);
- if (saa->dmaa1in)
- kfree((void *) saa->dmaa1in);
- if (saa->dmaa1out)
- kfree((void *) saa->dmaa1out);
- if (saa->dmaa2in)
- kfree((void *) saa->dmaa2in);
- if (saa->dmaa2out)
- kfree((void *) saa->dmaa2out);
- if (saa->dmaRPS1)
- kfree((void *) saa->dmaRPS1);
- if (saa->dmaRPS2)
- kfree((void *) saa->dmaRPS2);
+ kfree(saa->dmadebi);
+ kfree(saa->dmavid1);
+ kfree(saa->dmavid3);
+ kfree(saa->dmaa1in);
+ kfree(saa->dmaa1out);
+ kfree(saa->dmaa2in);
+ kfree(saa->dmaa2out);
+ kfree(saa->dmaRPS1);
+ kfree(saa->dmaRPS2);
free_irq(saa->irq, saa);
if (saa->saa7146_mem)
iounmap(saa->saa7146_mem);
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 7cb1fb3e66f9..255b6088ebf9 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -328,7 +328,7 @@ static int tda7432_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda7432_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, tda7432_attach);
#endif
return 0;
@@ -513,7 +513,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda7432"),
+ .name = "tda7432",
.driver = &driver,
};
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index a8b6a8df5109..c65f0c7680a2 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -1,5 +1,4 @@
/*
- * $Id: tda8290.c,v 1.15 2005/07/08 20:21:33 mchehab Exp $
*
* i2c tv tuner chip device driver
* controls the philips tda8290+75 tuner chip combo.
@@ -9,6 +8,9 @@
#include <linux/delay.h>
#include <media/tuner.h>
+#define I2C_ADDR_TDA8290 0x4b
+#define I2C_ADDR_TDA8275 0x61
+
/* ---------------------------------------------------------------------- */
struct freq_entry {
@@ -75,10 +77,12 @@ static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00,
static unsigned char i2c_set_VS[2] = { 0x30, 0x6F };
static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B };
static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 };
+static unsigned char i2c_tda8290_standby[2] = { 0x00, 0x02 };
static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 };
static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 };
static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 };
static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF };
+static unsigned char i2c_cb1_D0[2] = { 0x30, 0xD0 };
static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 };
static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 };
static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 };
@@ -117,6 +121,13 @@ static struct i2c_msg i2c_msg_epilog[] = {
{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on },
};
+static struct i2c_msg i2c_msg_standby[] = {
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D0), i2c_cb1_D0 },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_standby), i2c_tda8290_standby },
+};
+
static int tda8290_tune(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -205,6 +216,11 @@ static int has_signal(struct i2c_client *c)
return (afc & 0x80)? 65535:0;
}
+static void standby(struct i2c_client *c)
+{
+ i2c_transfer(c->adapter, i2c_msg_standby, ARRAY_SIZE(i2c_msg_standby));
+}
+
int tda8290_init(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -214,6 +230,7 @@ int tda8290_init(struct i2c_client *c)
t->tv_freq = set_tv_freq;
t->radio_freq = set_radio_freq;
t->has_signal = has_signal;
+ t->standby = standby;
i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge));
i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init));
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index c29bdfc3244e..1794686612c6 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -205,7 +205,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ if (adapter->id != I2C_HW_SAA7146) {
dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
return -ENODEV;
}
@@ -231,7 +231,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tda9840"),
+ .name = "tda9840",
.driver = &driver,
};
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 566e1a5ca135..7e3dcdb262b0 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -262,7 +262,7 @@ static int tda9875_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9875_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, tda9875_attach);
#endif
return 0;
@@ -384,7 +384,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda9875"),
+ .name = "tda9875",
.driver = &driver,
};
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 108c3ad7d622..0456dda2624d 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -23,6 +23,7 @@
TDA9887 (world), TDA9885 (USA)
Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
- KNC One TV-Station RDS (saa7134)
+ - Hauppauge PVR-150/500 (possibly more)
*/
@@ -49,7 +50,7 @@ MODULE_LICENSE("GPL");
struct tda9887 {
struct i2c_client client;
v4l2_std_id std;
- unsigned int radio;
+ enum tuner_mode mode;
unsigned int config;
unsigned int pinnacle_id;
unsigned int using_v4l2;
@@ -196,7 +197,7 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
+ cDeemphasis75 ),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_45_75 ),
@@ -364,7 +365,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
struct tvnorm *norm = NULL;
int i;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
if (t->radio_mode == V4L2_TUNER_MODE_MONO)
norm = &radio_mono;
else
@@ -378,7 +379,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
}
}
if (NULL == norm) {
- dprintk(PREFIX "Oops: no tvnorm entry found\n");
+ dprintk(PREFIX "Unsupported tvnorm entry - audio muted\n");
return -1;
}
@@ -519,6 +520,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n");
t->std = V4L2_STD_PAL_DK;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ printk(PREFIX "pal= argument not recognised\n");
+ break;
}
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -535,6 +542,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n");
t->std = V4L2_STD_SECAM_L;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ printk(PREFIX "secam= argument not recognised\n");
+ break;
}
}
return 0;
@@ -569,6 +582,10 @@ static int tda9887_configure(struct tda9887 *t)
tda9887_set_config(t,buf);
tda9887_set_insmod(t,buf);
+ if (t->mode == T_STANDBY) {
+ buf[1] |= cForcedMuteAudioON;
+ }
+
dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
buf[1],buf[2],buf[3]);
@@ -618,9 +635,9 @@ static int tda9887_probe(struct i2c_adapter *adap)
return i2c_probe(adap, &addr_data, tda9887_attach);
#else
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
+ case I2C_HW_SAA7134:
return i2c_probe(adap, &addr_data, tda9887_attach);
break;
}
@@ -653,10 +670,17 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* --- configuration --- */
case AUDC_SET_RADIO:
- t->radio = 1;
+ {
+ t->mode = T_RADIO;
tda9887_configure(t);
break;
-
+ }
+ case TUNER_SET_STANDBY:
+ {
+ t->mode = T_STANDBY;
+ tda9887_configure(t);
+ break;
+ }
case AUDC_CONFIG_PINNACLE:
{
int *i = arg;
@@ -689,7 +713,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct video_channel *vc = arg;
CHECK_V4L2;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tda9887_fixup_std(t);
@@ -701,7 +725,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
v4l2_std_id *id = arg;
SWITCH_V4L2;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
t->std = *id;
tda9887_fixup_std(t);
tda9887_configure(t);
@@ -713,14 +737,14 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
SWITCH_V4L2;
if (V4L2_TUNER_ANALOG_TV == f->type) {
- if (t->radio == 0)
+ if (t->mode == T_ANALOG_TV)
return 0;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
}
if (V4L2_TUNER_RADIO == f->type) {
- if (t->radio == 1)
+ if (t->mode == T_RADIO)
return 0;
- t->radio = 1;
+ t->mode = T_RADIO;
}
tda9887_configure(t);
break;
@@ -735,7 +759,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
};
struct v4l2_tuner* tuner = arg;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
__u8 reg = 0;
tuner->afc=0;
if (1 == i2c_master_recv(&t->client,&reg,1))
@@ -747,7 +771,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner* tuner = arg;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
t->radio_mode = tuner->audmode;
tda9887_configure (t);
}
@@ -760,7 +784,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tda9887_suspend(struct device * dev, u32 state, u32 level)
+static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
{
dprintk("tda9887: suspend\n");
return 0;
@@ -793,7 +817,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda9887"),
+ .name = "tda9887",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index cebcc1fa68d1..38bf50943798 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -2,7 +2,6 @@
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
* I2C address is allways 0xC0.
*
- * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $
*
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
* This code is placed under the terms of the GNU General Public License
@@ -205,11 +204,6 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
buffer[4] = 0;
- if (t->mode == T_STANDBY) {
- tuner_dbg("TEA5767 set to standby mode\n");
- buffer[3] |= TEA5767_STDBY;
- }
-
if (t->audmode == V4L2_TUNER_MODE_MONO) {
tuner_dbg("TEA5767 set to mono\n");
buffer[2] |= TEA5767_MONO;
@@ -290,13 +284,31 @@ static int tea5767_stereo(struct i2c_client *c)
return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0);
}
+static void tea5767_standby(struct i2c_client *c)
+{
+ unsigned char buffer[5];
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned div, rc;
+
+ div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
+ buffer[0] = (div >> 8) & 0x3f;
+ buffer[1] = div & 0xff;
+ buffer[2] = TEA5767_PORT1_HIGH;
+ buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
+ TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
+ buffer[4] = 0;
+
+ if (5 != (rc = i2c_master_send(c, buffer, 5)))
+ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+}
+
int tea5767_autodetection(struct i2c_client *c)
{
unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int rc;
struct tuner *t = i2c_get_clientdata(c);
- if (7 != (rc = i2c_master_recv(c, buffer, 7))) {
+ if ((rc = i2c_master_recv(c, buffer, 7))< 5) {
tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
return EINVAL;
}
@@ -313,15 +325,10 @@ int tea5767_autodetection(struct i2c_client *c)
* bit 0 : internally set to 0
* Byte 5: bit 7:0 : == 0
*/
- if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
+ if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
return EINVAL;
}
- /* It seems that tea5767 returns 0xff after the 5th byte */
- if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
- tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
- return EINVAL;
- }
/* It seems that tea5767 returns 0xff after the 5th byte */
if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
@@ -337,14 +344,14 @@ int tea5767_tuner_init(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
- tuner_info("type set to %d (%s)\n", t->type,
- "Philips TEA5767HN FM Radio");
+ tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
strlcpy(c->name, "tea5767", sizeof(c->name));
t->tv_freq = set_tv_freq;
t->radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
+ t->standby = tea5767_standby;
return (0);
}
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index b44db8a7b94d..ee3688348b66 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -86,7 +86,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ if (adapter->id != I2C_HW_SAA7146) {
dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
return -ENODEV;
}
@@ -200,7 +200,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tea6415c"),
+ .name = "tea6415c",
.driver = &driver,
};
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 48d4db7d507b..17975c19da5e 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -135,7 +135,7 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ if (adapter->id != I2C_HW_SAA7146) {
dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
return -ENODEV;
}
@@ -177,7 +177,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tea6420"),
+ .name = "tea6420",
.driver = &driver,
};
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 7d825e510ffd..79203595b9c1 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -41,7 +41,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
/* ---------------------------------------------------------------------- */
@@ -166,7 +165,7 @@ static int
tuner_probe(struct i2c_adapter *adap)
{
this_adap = 0;
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_LP))
+ if (adap->id == I2C_HW_B_LP)
return i2c_probe(adap, &addr_data, tuner_attach);
return 0;
}
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f0a579827a24..05572020af4d 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -182,6 +181,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
i2c_master_send(c, buffer, 4);
default_tuner_init(c);
break;
+ case TUNER_LG_TDVS_H062F:
+ /* Set the Auxiliary Byte. */
+ buffer[2] &= ~0x20;
+ buffer[2] |= 0x18;
+ buffer[3] = 0x20;
+ i2c_master_send(c, buffer, 4);
+ default_tuner_init(c);
+ break;
default:
default_tuner_init(c);
break;
@@ -208,31 +215,31 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
{
struct tuner *t = i2c_get_clientdata(c);
- if (tun_setup->addr == ADDR_UNSET) {
- if (t->mode_mask & tun_setup->mode_mask)
+ if ((tun_setup->addr == ADDR_UNSET &&
+ (t->mode_mask & tun_setup->mode_mask)) ||
+ tun_setup->addr == c->addr) {
set_type(c, tun_setup->type, tun_setup->mode_mask);
- } else if (tun_setup->addr == c->addr) {
- set_type(c, tun_setup->type, tun_setup->mode_mask);
}
}
static inline int check_mode(struct tuner *t, char *cmd)
{
- if (1 << t->mode & t->mode_mask) {
- switch (t->mode) {
- case V4L2_TUNER_RADIO:
- tuner_dbg("Cmd %s accepted for radio\n", cmd);
- break;
- case V4L2_TUNER_ANALOG_TV:
- tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
- break;
- case V4L2_TUNER_DIGITAL_TV:
- tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
- break;
- }
- return 0;
+ if ((1 << t->mode & t->mode_mask) == 0) {
+ return EINVAL;
+ }
+
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO:
+ tuner_dbg("Cmd %s accepted for radio\n", cmd);
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
+ break;
+ case V4L2_TUNER_DIGITAL_TV:
+ tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
+ break;
}
- return EINVAL;
+ return 0;
}
static char pal[] = "-";
@@ -274,6 +281,12 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg ("insmod fixup: PAL => PAL-N\n");
t->std = V4L2_STD_PAL_N;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_warn ("pal= argument not recognised\n");
+ break;
}
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -290,6 +303,12 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
t->std = V4L2_STD_SECAM_L;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_warn ("secam= argument not recognised\n");
+ break;
}
}
@@ -406,20 +425,18 @@ static int tuner_detach(struct i2c_client *client)
static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
{
- if (mode != t->mode) {
-
- t->mode = mode;
- if (check_mode(t, cmd) == EINVAL) {
- t->mode = T_STANDBY;
- if (V4L2_TUNER_RADIO == mode) {
- set_tv_freq(client, 400 * 16);
- } else {
- set_radio_freq(client, 87.5 * 16000);
- }
- return EINVAL;
- }
- }
- return 0;
+ if (mode == t->mode)
+ return 0;
+
+ t->mode = mode;
+
+ if (check_mode(t, cmd) == EINVAL) {
+ t->mode = T_STANDBY;
+ if (t->standby)
+ t->standby (client);
+ return EINVAL;
+ }
+ return 0;
}
#define switch_v4l2() if (!t->using_v4l2) \
@@ -453,6 +470,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
case AUDC_SET_RADIO:
set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
break;
+ case TUNER_SET_STANDBY:
+ {
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
+ break;
+ }
case AUDC_CONFIG_PINNACLE:
if (check_mode(t, "AUDC_CONFIG_PINNACLE") == EINVAL)
return 0;
@@ -672,7 +697,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tuner_suspend(struct device *dev, u32 state, u32 level)
+static int tuner_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
@@ -709,7 +734,7 @@ static struct i2c_driver driver = {
},
};
static struct i2c_client client_template = {
- I2C_DEVNAME("(tuner unset)"),
+ .name = "(tuner unset)",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index de0c93aeb75d..8edd73abe1d8 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,4 @@
/*
- * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -102,6 +101,7 @@ struct tunertype
* "no float in kernel" rule.
*/
static struct tunertype tuners[] = {
+ /* 0-9 */
{ "Temic PAL (4002 FH5)", TEMIC, PAL,
16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
{ "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I,
@@ -110,7 +110,6 @@ static struct tunertype tuners[] = {
16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
{ "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM,
16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
-
{ "NoTuner", NoTuner, NOTUNER,
0,0,0x00,0x00,0x00,0x00,0x00},
{ "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL,
@@ -119,34 +118,34 @@ static struct tunertype tuners[] = {
16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
-
{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
{ "Alps HSBH1", TEMIC, NTSC,
16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
- { "Alps TSBE1",TEMIC,PAL,
+
+ /* 10-19 */
+ { "Alps TSBE1", TEMIC, PAL,
16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
{ "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
-
{ "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
{ "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
- { "Alps TSCH6",Alps,NTSC,
+ { "Alps TSCH6", Alps, NTSC,
16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
-
- { "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
+ { "Temic PAL_DK (4016 FY5)", TEMIC, PAL,
16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
- { "Philips NTSC_M (MK2)",Philips,NTSC,
+ { "Philips NTSC_M (MK2)", Philips, NTSC,
16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+ /* 20-29 */
{ "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic NTSC (4039 FR5)", TEMIC, NTSC,
@@ -155,7 +154,6 @@ static struct tunertype tuners[] = {
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
{ "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-
{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
@@ -164,25 +162,24 @@ static struct tunertype tuners[] = {
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
-
{ "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+
+ /* 30-39 */
{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
-
- { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
+ { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
16*169,16*464,0xA0,0x90,0x30,0x8e,623},
- { "MT20xx universal", Microtune,PAL|NTSC,
+ { "MT20xx universal", Microtune, PAL|NTSC,
/* see mt20xx.c for details */ },
{ "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
-
{ "Temic NTSC (4136 FY5)", TEMIC, NTSC,
16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
{ "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
@@ -192,42 +189,41 @@ static struct tunertype tuners[] = {
{ "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
+ /* 40-49 */
{ "HITACHI V7-J180AT", HITACHI, NTSC,
16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
- { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
+ { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC,
16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-
{ "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
- { "Microtune 4049 FM5",Microtune,PAL,
+ { "Microtune 4049 FM5", Microtune, PAL,
16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
{ "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
-
{ "Tenna TNF 8831 BGFF)", Philips, PAL,
16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
{ "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
+
+ /* 50-59 */
{ "TCL 2002N", TCL, NTSC,
16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
{ "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
-
{ "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC,
16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
{ "Philips FQ1286", Philips, NTSC,
- 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested
- { "tda8290+75", Philips,PAL|NTSC,
+ 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, /* UHF band untested */
+ { "tda8290+75", Philips, PAL|NTSC,
/* see tda8290.c for details */ },
{ "LG PAL (TAPE series)", LGINNOTEK, PAL,
16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
-
{ "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
{ "Philips FQ1236A MK4", Philips, NTSC,
@@ -237,6 +233,7 @@ static struct tunertype tuners[] = {
{ "Ymec TVision TVF-5533MF", Philips, NTSC,
16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
+ /* 60-66 */
{ "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
{ "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL,
@@ -245,12 +242,12 @@ static struct tunertype tuners[] = {
/* see tea5767.c for details */},
{ "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
-
- { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC,
+ { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC,
16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732},
-
{ "Ymec TVF66T5-B/DFF", Philips, PAL,
16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623},
+ { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC,
+ 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 },
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -471,6 +468,10 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
case TUNER_LG_PAL_FM:
buffer[3] = 0xa5;
break;
+ case TUNER_MICROTUNE_4049FM5:
+ div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
+ buffer[3] = 0xa4;
+ break;
default:
buffer[3] = 0xa4;
break;
@@ -497,6 +498,7 @@ int default_tuner_init(struct i2c_client *c)
t->radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
t->is_stereo = tuner_stereo;
+ t->standby = NULL;
return 0;
}
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index f42a1efa8fcf..1c31ef52f863 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -46,7 +46,17 @@ MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
MODULE_LICENSE("GPL");
#define UNSET (-1U)
-#define dprintk if (debug) printk
+
+#define tvaudio_info(fmt, arg...) do {\
+ printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_dbg(fmt, arg...) do {\
+ if (debug) \
+ printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
/* ---------------------------------------------------------------------- */
/* our structs */
@@ -162,24 +172,24 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
unsigned char buffer[2];
if (-1 == subaddr) {
- dprintk("%s: chip_write: 0x%x\n",
- i2c_clientname(&chip->c), val);
+ tvaudio_dbg("%s: chip_write: 0x%x\n",
+ chip->c.name, val);
chip->shadow.bytes[1] = val;
buffer[0] = val;
if (1 != i2c_master_send(&chip->c,buffer,1)) {
- printk(KERN_WARNING "%s: I/O error (write 0x%x)\n",
- i2c_clientname(&chip->c), val);
+ tvaudio_warn("%s: I/O error (write 0x%x)\n",
+ chip->c.name, val);
return -1;
}
} else {
- dprintk("%s: chip_write: reg%d=0x%x\n",
- i2c_clientname(&chip->c), subaddr, val);
+ tvaudio_dbg("%s: chip_write: reg%d=0x%x\n",
+ chip->c.name, subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
buffer[0] = subaddr;
buffer[1] = val;
if (2 != i2c_master_send(&chip->c,buffer,2)) {
- printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n",
- i2c_clientname(&chip->c), subaddr, val);
+ tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n",
+ chip->c.name, subaddr, val);
return -1;
}
}
@@ -203,31 +213,30 @@ static int chip_read(struct CHIPSTATE *chip)
unsigned char buffer;
if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
- printk(KERN_WARNING "%s: I/O error (read)\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: I/O error (read)\n",
+ chip->c.name);
return -1;
}
- dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer);
+ tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name,buffer);
return buffer;
}
static int chip_read2(struct CHIPSTATE *chip, int subaddr)
{
- unsigned char write[1];
- unsigned char read[1];
- struct i2c_msg msgs[2] = {
- { chip->c.addr, 0, 1, write },
- { chip->c.addr, I2C_M_RD, 1, read }
- };
- write[0] = subaddr;
+ unsigned char write[1];
+ unsigned char read[1];
+ struct i2c_msg msgs[2] = {
+ { chip->c.addr, 0, 1, write },
+ { chip->c.addr, I2C_M_RD, 1, read }
+ };
+ write[0] = subaddr;
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
- printk(KERN_WARNING "%s: I/O error (read2)\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: I/O error (read2)\n", chip->c.name);
return -1;
}
- dprintk("%s: chip_read2: reg%d=0x%x\n",
- i2c_clientname(&chip->c),subaddr,read[0]);
+ tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n",
+ chip->c.name,subaddr,read[0]);
return read[0];
}
@@ -239,17 +248,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
return 0;
/* update our shadow register set; print bytes if (debug > 0) */
- dprintk("%s: chip_cmd(%s): reg=%d, data:",
- i2c_clientname(&chip->c),name,cmd->bytes[0]);
+ tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:",
+ chip->c.name,name,cmd->bytes[0]);
for (i = 1; i < cmd->count; i++) {
- dprintk(" 0x%x",cmd->bytes[i]);
+ if (debug)
+ printk(" 0x%x",cmd->bytes[i]);
chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
}
- dprintk("\n");
+ if (debug)
+ printk("\n");
/* send data to the chip */
if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
- printk(KERN_WARNING "%s: I/O error (%s)\n", i2c_clientname(&chip->c), name);
+ tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name);
return -1;
}
return 0;
@@ -264,19 +275,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
static void chip_thread_wake(unsigned long data)
{
- struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+ struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
wake_up_interruptible(&chip->wq);
}
static int chip_thread(void *data)
{
DECLARE_WAITQUEUE(wait, current);
- struct CHIPSTATE *chip = data;
+ struct CHIPSTATE *chip = data;
struct CHIPDESC *desc = chiplist + chip->type;
- daemonize("%s",i2c_clientname(&chip->c));
+ daemonize("%s", chip->c.name);
allow_signal(SIGTERM);
- dprintk("%s: thread started\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread started\n", chip->c.name);
for (;;) {
add_wait_queue(&chip->wq, &wait);
@@ -288,7 +299,7 @@ static int chip_thread(void *data)
try_to_freeze();
if (chip->done || signal_pending(current))
break;
- dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread wakeup\n", chip->c.name);
/* don't do anything for radio or if mode != auto */
if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
@@ -301,8 +312,8 @@ static int chip_thread(void *data)
mod_timer(&chip->wt, jiffies+2*HZ);
}
- dprintk("%s: thread exiting\n", i2c_clientname(&chip->c));
- complete_and_exit(&chip->texit, 0);
+ tvaudio_dbg("%s: thread exiting\n", chip->c.name);
+ complete_and_exit(&chip->texit, 0);
return 0;
}
@@ -312,9 +323,9 @@ static void generic_checkmode(struct CHIPSTATE *chip)
int mode = desc->getmode(chip);
if (mode == chip->prevmode)
- return;
+ return;
- dprintk("%s: thread checkmode\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread checkmode\n", chip->c.name);
chip->prevmode = mode;
if (mode & VIDEO_SOUND_STEREO)
@@ -361,8 +372,8 @@ static int tda9840_getmode(struct CHIPSTATE *chip)
if (val & TDA9840_ST_STEREO)
mode |= VIDEO_SOUND_STEREO;
- dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
- val, mode);
+ tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+ val, mode);
return mode;
}
@@ -657,8 +668,8 @@ static int tda9873_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_STEREO;
if (val & TDA9873_DUAL)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
- dprintk ("tda9873_getmode(): raw chip read: %d, return: %d\n",
- val, mode);
+ tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n",
+ val, mode);
return mode;
}
@@ -668,12 +679,12 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
/* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) {
- dprintk("tda9873_setmode(): external input\n");
+ tvaudio_dbg("tda9873_setmode(): external input\n");
return;
}
- dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
- dprintk("tda9873_setmode(): sw_data = %d\n", sw_data);
+ tvaudio_dbg("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+ tvaudio_dbg("tda9873_setmode(): sw_data = %d\n", sw_data);
switch (mode) {
case VIDEO_SOUND_MONO:
@@ -694,7 +705,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
}
chip_write(chip, TDA9873_SW, sw_data);
- dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n",
+ tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n",
mode, sw_data);
}
@@ -831,9 +842,9 @@ static int tda9874a_setup(struct CHIPSTATE *chip)
} else { /* dic == 0x07 */
chip_write(chip, TDA9874A_AMCONR, 0xfb);
chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
- chip_write(chip, TDA9874A_AOSR, 0x00); // or 0x10
+ chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
}
- dprintk("tda9874a_setup(): %s [0x%02X].\n",
+ tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n",
tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
return 1;
}
@@ -876,7 +887,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
- dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+ tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
dsr, nsr, necr, mode);
return mode;
}
@@ -922,7 +933,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_AOSR, aosr);
chip_write(chip, TDA9874A_MDACOSR, mdacosr);
- dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+ tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
mode, aosr, mdacosr);
} else { /* dic == 0x07 */
@@ -957,7 +968,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_FMMR, fmmr);
chip_write(chip, TDA9874A_AOSR, aosr);
- dprintk("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+ tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
mode, fmmr, aosr);
}
}
@@ -971,10 +982,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
return 0;
- dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+ tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
if((dic == 0x11)||(dic == 0x07)) {
- printk("tvaudio: found tda9874%s.\n", (dic == 0x11) ? "a":"h");
+ tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h");
tda9874a_dic = dic; /* remember device id. */
return 1;
}
@@ -1098,7 +1109,7 @@ static int tda8425_initialize(struct CHIPSTATE *chip)
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF,
/* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2};
- if (chip->c.adapter->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) {
+ if (chip->c.adapter->id == I2C_HW_B_RIVA) {
memcpy (desc->inputmap, inputmap, sizeof (inputmap));
}
return 0;
@@ -1149,7 +1160,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for TA8874Z */
-// write 1st byte
+/* write 1st byte */
#define TA8874Z_LED_STE 0x80
#define TA8874Z_LED_BIL 0x40
#define TA8874Z_LED_EXT 0x20
@@ -1159,21 +1170,22 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
#define TA8874Z_MODE_SUB 0x02
#define TA8874Z_MODE_MAIN 0x01
-// write 2nd byte
-//#define TA8874Z_TI 0x80 // test mode
+/* write 2nd byte */
+/*#define TA8874Z_TI 0x80 */ /* test mode */
#define TA8874Z_SEPARATION 0x3f
#define TA8874Z_SEPARATION_DEFAULT 0x10
-// read
+/* read */
#define TA8874Z_B1 0x80
#define TA8874Z_B0 0x40
#define TA8874Z_CHAG_FLAG 0x20
-// B1 B0
-// mono L H
-// stereo L L
-// BIL H L
-
+/*
+ * B1 B0
+ * mono L H
+ * stereo L L
+ * BIL H L
+ */
static int ta8874z_getmode(struct CHIPSTATE *chip)
{
int val, mode;
@@ -1185,7 +1197,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip)
}else if (!(val & TA8874Z_B0)){
mode |= VIDEO_SOUND_STEREO;
}
- //dprintk ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode);
+ /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
return mode;
}
@@ -1198,7 +1210,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
{
int update = 1;
audiocmd *t = NULL;
- dprintk("ta8874z_setmode(): mode: 0x%02x\n", mode);
+ tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode);
switch(mode){
case VIDEO_SOUND_MONO:
@@ -1238,11 +1250,11 @@ static int tda9850 = 1;
static int tda9855 = 1;
static int tda9873 = 1;
static int tda9874a = 1;
-static int tea6300 = 0; // address clash with msp34xx
-static int tea6320 = 0; // address clash with msp34xx
+static int tea6300 = 0; /* address clash with msp34xx */
+static int tea6320 = 0; /* address clash with msp34xx */
static int tea6420 = 1;
static int pic16c54 = 1;
-static int ta8874z = 0; // address clash with tda9840
+static int ta8874z = 0; /* address clash with tda9840 */
module_param(tda8425, int, 0444);
module_param(tda9840, int, 0444);
@@ -1444,7 +1456,7 @@ static struct CHIPDESC chiplist[] = {
{
.name = "ta8874z",
.id = -1,
- //.id = I2C_DRIVERID_TA8874Z,
+ /*.id = I2C_DRIVERID_TA8874Z, */
.checkit = ta8874z_checkit,
.insmodopt = &ta8874z,
.addr_lo = I2C_TDA9840 >> 1,
@@ -1479,7 +1491,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(&chip->c, chip);
/* find description for the chip */
- dprintk("tvaudio: chip found @ i2c-addr=0x%x\n", addr<<1);
+ tvaudio_dbg("chip found @ 0x%x\n", addr<<1);
for (desc = chiplist; desc->name != NULL; desc++) {
if (0 == *(desc->insmodopt))
continue;
@@ -1491,17 +1503,19 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
break;
}
if (desc->name == NULL) {
- dprintk("tvaudio: no matching chip description found\n");
+ tvaudio_dbg("no matching chip description found\n");
return -EIO;
}
- printk("tvaudio: found %s @ 0x%x\n", desc->name, addr<<1);
- dprintk("tvaudio: matches:%s%s%s.\n",
- (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
- (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
- (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
+ tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
+ if (desc->flags) {
+ tvaudio_dbg("matches:%s%s%s.\n",
+ (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
+ (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
+ (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
+ }
/* fill required data structures */
- strcpy(i2c_clientname(&chip->c),desc->name);
+ strcpy(chip->c.name,desc->name);
chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
@@ -1537,8 +1551,8 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
init_completion(&chip->texit);
chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
if (chip->tpid < 0)
- printk(KERN_WARNING "%s: kernel_thread() failed\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: kernel_thread() failed\n",
+ chip->c.name);
wake_up_interruptible(&chip->wq);
}
return 0;
@@ -1548,16 +1562,16 @@ static int chip_probe(struct i2c_adapter *adap)
{
/* don't attach on saa7146 based cards,
because dedicated drivers are used */
- if ((adap->id & I2C_ALGO_SAA7146))
+ if ((adap->id == I2C_HW_SAA7146))
return 0;
#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, chip_attach);
#else
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
+ case I2C_HW_SAA7134:
return i2c_probe(adap, &addr_data, chip_attach);
}
#endif
@@ -1587,11 +1601,11 @@ static int chip_detach(struct i2c_client *client)
static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
- __u16 *sarg = arg;
+ __u16 *sarg = arg;
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
- dprintk("%s: chip_command 0x%x\n",i2c_clientname(&chip->c),cmd);
+ tvaudio_dbg("%s: chip_command 0x%x\n",chip->c.name,cmd);
switch (cmd) {
case AUDC_SET_INPUT:
@@ -1604,7 +1618,6 @@ static int chip_command(struct i2c_client *client,
break;
case AUDC_SET_RADIO:
- dprintk(KERN_DEBUG "tvaudio: AUDC_SET_RADIO\n");
chip->norm = VIDEO_MODE_RADIO;
chip->watch_stereo = 0;
/* del_timer(&chip->wt); */
@@ -1612,7 +1625,7 @@ static int chip_command(struct i2c_client *client,
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
+ kernel pointer here... */
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
@@ -1646,9 +1659,9 @@ static int chip_command(struct i2c_client *client,
if (desc->flags & CHIP_HAS_VOLUME) {
chip->left = (min(65536 - va->balance,32768) *
- va->volume) / 32768;
+ va->volume) / 32768;
chip->right = (min(va->balance,(__u16)32768) *
- va->volume) / 32768;
+ va->volume) / 32768;
chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
}
@@ -1670,17 +1683,16 @@ static int chip_command(struct i2c_client *client,
{
struct video_channel *vc = arg;
- dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n");
chip->norm = vc->norm;
break;
}
case VIDIOCSFREQ:
{
- chip->mode = 0; /* automatic */
+ chip->mode = 0; /* automatic */
if (desc->checkmode) {
desc->setmode(chip,VIDEO_SOUND_MONO);
- if (chip->prevmode != VIDEO_SOUND_MONO)
- chip->prevmode = -1; /* reset previous mode */
+ if (chip->prevmode != VIDEO_SOUND_MONO)
+ chip->prevmode = -1; /* reset previous mode */
mod_timer(&chip->wt, jiffies+2*HZ);
/* the thread will call checkmode() later */
}
@@ -1692,29 +1704,32 @@ static int chip_command(struct i2c_client *client,
static struct i2c_driver driver = {
.owner = THIS_MODULE,
- .name = "generic i2c audio driver",
- .id = I2C_DRIVERID_TVAUDIO,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = chip_probe,
- .detach_client = chip_detach,
- .command = chip_command,
+ .name = "generic i2c audio driver",
+ .id = I2C_DRIVERID_TVAUDIO,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = chip_probe,
+ .detach_client = chip_detach,
+ .command = chip_command,
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
+ .driver = &driver,
};
static int __init audiochip_init_module(void)
{
struct CHIPDESC *desc;
- printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
- printk(KERN_INFO "tvaudio: known chips: ");
- for (desc = chiplist; desc->name != NULL; desc++)
- printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);
- printk("\n");
+
+ if (debug) {
+ printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
+ printk(KERN_INFO "tvaudio: known chips: ");
+ for (desc = chiplist; desc->name != NULL; desc++)
+ printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name);
+ printk("\n");
+ }
return i2c_add_driver(&driver);
}
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 127ec38ebd60..5344d5592199 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -47,18 +47,21 @@ MODULE_LICENSE("GPL");
static int debug = 0;
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-2)");
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
-#define dprintk(num, args...) \
- do { \
- if (debug >= num) \
- printk(KERN_INFO "tveeprom: " args); \
- } while (0)
+#define tveeprom_info(fmt, arg...) do {\
+ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_dbg(fmt, arg...) do {\
+ if (debug) \
+ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
-#define TVEEPROM_KERN_ERR(args...) printk(KERN_ERR "tveeprom: " args);
-#define TVEEPROM_KERN_INFO(args...) printk(KERN_INFO "tveeprom: " args);
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
@@ -70,14 +73,14 @@ static struct HAUPPAUGE_TUNER_FMT
}
hauppauge_tuner_fmt[] =
{
- { 0x00000000, "unknown1" },
- { 0x00000000, "unknown2" },
- { 0x00000007, "PAL(B/G)" },
- { 0x00001000, "NTSC(M)" },
- { 0x00000010, "PAL(I)" },
- { 0x00400000, "SECAM(L/L´)" },
- { 0x00000e00, "PAL(D/K)" },
- { 0x03000000, "ATSC Digital" },
+ { 0x00000000, " unknown1" },
+ { 0x00000000, " unknown2" },
+ { 0x00000007, " PAL(B/G)" },
+ { 0x00001000, " NTSC(M)" },
+ { 0x00000010, " PAL(I)" },
+ { 0x00400000, " SECAM(L/L')" },
+ { 0x00000e00, " PAL(D/K)" },
+ { 0x03000000, " ATSC Digital" },
};
/* This is the full list of possible tuners. Many thanks to Hauppauge for
@@ -152,13 +155,13 @@ hauppauge_tuner[] =
{ TUNER_MICROTUNE_4049FM5, "Microtune 4049 FM5"},
{ TUNER_ABSENT, "LG TPI8NSR11F"},
{ TUNER_ABSENT, "Microtune 4049 FM5 Alt I2C"},
- { TUNER_ABSENT, "Philips FQ1216ME MK3"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216ME MK3"},
{ TUNER_ABSENT, "Philips FI1236 MK3"},
{ TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216 ME MK3"},
- { TUNER_ABSENT, "Philips FM1236 MK3"},
+ { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK3"},
{ TUNER_ABSENT, "Philips FM1216MP MK3"},
/* 60-69 */
- { TUNER_ABSENT, "LG S001D MK3"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "LG S001D MK3"},
{ TUNER_ABSENT, "LG M001D MK3"},
{ TUNER_ABSENT, "LG S701D MK3"},
{ TUNER_ABSENT, "LG M701D MK3"},
@@ -167,7 +170,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Temic 4106FH5"},
{ TUNER_ABSENT, "Philips FQ1216LMP MK3"},
{ TUNER_LG_NTSC_TAPE, "LG TAPE H001F MK3"},
- { TUNER_ABSENT, "LG TAPE H701F MK3"},
+ { TUNER_LG_NTSC_TAPE, "LG TAPE H701F MK3"},
/* 70-79 */
{ TUNER_ABSENT, "LG TALN H200T"},
{ TUNER_ABSENT, "LG TALN H250T"},
@@ -183,8 +186,8 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Philips FQ1216LME MK3"},
{ TUNER_ABSENT, "LG TAPC G701D"},
{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
- { TUNER_ABSENT, "TCL 2002MB 3"},
- { TUNER_ABSENT, "TCL 2002MI 3"},
+ { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
+ { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
{ TUNER_TCL_2002N, "TCL 2002N 6A"},
{ TUNER_ABSENT, "Philips FQ1236 MK3"},
{ TUNER_ABSENT, "Samsung TCPN 2121P30A"},
@@ -199,17 +202,51 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Philips FQ1236 MK5"},
{ TUNER_ABSENT, "Unspecified"},
{ TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"},
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_TCL_2002N, "TCL 2002N 5H"},
+ /* 100-103 */
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_TEA5767, "Philips TEA5767HN FM Radio"},
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"},
};
-static char *sndtype[] = {
- "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C", "MSP3410D",
- "MSP3415", "MSP3430", "MSP3438", "CS5331", "MSP3435", "MSP3440",
- "MSP3445", "MSP3411", "MSP3416", "MSP3425",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *audioIC[] = {
+ /* 0-4 */
+ "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C",
+ /* 5-9 */
+ "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331",
+ /* 10-14 */
+ "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416",
+ /* 15-19 */
+ "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716",
+ /* 20-24 */
+ "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408",
+ /* 25-29 */
+ "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d",
+ /* 30-34 */
+ "CX880", "CX881", "CX883", "CX882", "CX25840",
+ /* 35-38 */
+ "CX25841", "CX25842", "CX25843", "CX23418",
+};
- "Type 0x10","Type 0x11","Type 0x12","Type 0x13",
- "Type 0x14","Type 0x15","Type 0x16","Type 0x17",
- "Type 0x18","MSP4418","Type 0x1a","MSP4448",
- "Type 0x1c","Type 0x1d","Type 0x1e","Type 0x1f",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *decoderIC[] = {
+ /* 0-4 */
+ "None", "BT815", "BT817", "BT819", "BT815A",
+ /* 5-9 */
+ "BT817A", "BT819A", "BT827", "BT829", "BT848",
+ /* 10-14 */
+ "BT848A", "BT849A", "BT829A", "BT827A", "BT878",
+ /* 15-19 */
+ "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
+ /* 20-24 */
+ "CX880", "CX881", "CX883", "SAA7111", "SAA7113",
+ /* 25-29 */
+ "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
+ /* 30-31 */
+ "CX25843", "CX23418",
};
static int hasRadioTuner(int tunerType)
@@ -250,7 +287,8 @@ static int hasRadioTuner(int tunerType)
return 0;
}
-void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data)
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
+ unsigned char *eeprom_data)
{
/* ----------------------------------------------
** The hauppauge eeprom format is tagged
@@ -260,10 +298,11 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
**
** In our (ivtv) case we're interested in the following:
- ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
- ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
- ** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM)
- ** audio proc: tag [02].01 or [05].00 (lower nibble indexes lut?)
+ ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
+ ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
+ ** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM)
+ ** audio proc: tag [02].01 or [05].00 (mask with 0x7f)
+ ** decoder proc: tag [09].01)
** Fun info:
** model: tag [00].07-08 or [06].00-01
@@ -273,20 +312,24 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** # of inputs/outputs ???
*/
- int i, j, len, done, beenhere, tag, tuner = 0, t_format = 0;
- char *t_name = NULL, *t_fmt_name = NULL;
+ int i, j, len, done, beenhere, tag;
- dprintk(1, "%s\n",__FUNCTION__);
- tvee->revision = done = len = beenhere = 0;
- for (i = 0; !done && i < 256; i += len) {
- dprintk(2, "processing pos = %02x (%02x, %02x)\n",
- i, eeprom_data[i], eeprom_data[i + 1]);
+ int tuner1 = 0, t_format1 = 0;
+ char *t_name1 = NULL;
+ const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
+ int tuner2 = 0, t_format2 = 0;
+ char *t_name2 = NULL;
+ const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
+
+ memset(tvee, 0, sizeof(*tvee));
+ done = len = beenhere = 0;
+ for (i = 0; !done && i < 256; i += len) {
if (eeprom_data[i] == 0x84) {
len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
- i+=3;
+ i += 3;
} else if ((eeprom_data[i] & 0xf0) == 0x70) {
- if ((eeprom_data[i] & 0x08)) {
+ if (eeprom_data[i] & 0x08) {
/* verify checksum! */
done = 1;
break;
@@ -294,24 +337,30 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
len = eeprom_data[i] & 0x07;
++i;
} else {
- TVEEPROM_KERN_ERR("Encountered bad packet header [%02x]. "
+ tveeprom_warn("Encountered bad packet header [%02x]. "
"Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]);
return;
}
- dprintk(1, "%3d [%02x] ", len, eeprom_data[i]);
- for(j = 1; j < len; j++) {
- dprintk(1, "%02x ", eeprom_data[i + j]);
- }
- dprintk(1, "\n");
+ if (debug) {
+ tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1);
+ for(j = 1; j < len; j++) {
+ printk(" %02x", eeprom_data[i + j]);
+ }
+ printk("\n");
+ }
/* process by tag */
tag = eeprom_data[i];
switch (tag) {
case 0x00:
- tuner = eeprom_data[i+6];
- t_format = eeprom_data[i+5];
+ /* tag: 'Comprehensive' */
+ tuner1 = eeprom_data[i+6];
+ t_format1 = eeprom_data[i+5];
tvee->has_radio = eeprom_data[i+len-1];
+ /* old style tag, don't know how to detect
+ IR presence, mark as unknown. */
+ tvee->has_ir = 2;
tvee->model =
eeprom_data[i+8] +
(eeprom_data[i+9] << 8);
@@ -319,25 +368,43 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
(eeprom_data[i+11] << 8) +
(eeprom_data[i+12] << 16);
break;
+
case 0x01:
+ /* tag: 'SerialID' */
tvee->serial_number =
eeprom_data[i+6] +
(eeprom_data[i+7] << 8) +
(eeprom_data[i+8] << 16);
break;
+
case 0x02:
- tvee->audio_processor = eeprom_data[i+2] & 0x0f;
+ /* tag 'AudioInfo'
+ Note mask with 0x7F, high bit used on some older models
+ to indicate 4052 mux was removed in favor of using MSP
+ inputs directly. */
+ tvee->audio_processor = eeprom_data[i+2] & 0x7f;
break;
+
+ /* case 0x03: tag 'EEInfo' */
+
case 0x04:
+ /* tag 'SerialID2' */
tvee->serial_number =
eeprom_data[i+5] +
(eeprom_data[i+6] << 8) +
(eeprom_data[i+7] << 16);
break;
+
case 0x05:
- tvee->audio_processor = eeprom_data[i+1] & 0x0f;
+ /* tag 'Audio2'
+ Note mask with 0x7F, high bit used on some older models
+ to indicate 4052 mux was removed in favor of using MSP
+ inputs directly. */
+ tvee->audio_processor = eeprom_data[i+1] & 0x7f;
break;
+
case 0x06:
+ /* tag 'ModelRev' */
tvee->model =
eeprom_data[i+1] +
(eeprom_data[i+2] << 8);
@@ -345,27 +412,66 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
(eeprom_data[i+6] << 8) +
(eeprom_data[i+7] << 16);
break;
+
+ case 0x07:
+ /* tag 'Details': according to Hauppauge not interesting
+ on any PCI-era or later boards. */
+ break;
+
+ /* there is no tag 0x08 defined */
+
+ case 0x09:
+ /* tag 'Video' */
+ tvee->decoder_processor = eeprom_data[i + 1];
+ break;
+
case 0x0a:
- if(beenhere == 0) {
- tuner = eeprom_data[i+2];
- t_format = eeprom_data[i+1];
+ /* tag 'Tuner' */
+ if (beenhere == 0) {
+ tuner1 = eeprom_data[i+2];
+ t_format1 = eeprom_data[i+1];
beenhere = 1;
- break;
} else {
- break;
- }
+ /* a second (radio) tuner may be present */
+ tuner2 = eeprom_data[i+2];
+ t_format2 = eeprom_data[i+1];
+ if (t_format2 == 0) { /* not a TV tuner? */
+ tvee->has_radio = 1; /* must be radio */
+ }
+ }
+ break;
+
+ case 0x0b:
+ /* tag 'Inputs': according to Hauppauge this is specific
+ to each driver family, so no good assumptions can be
+ made. */
+ break;
+
+ /* case 0x0c: tag 'Balun' */
+ /* case 0x0d: tag 'Teletext' */
+
case 0x0e:
+ /* tag: 'Radio' */
tvee->has_radio = eeprom_data[i+1];
break;
+
+ case 0x0f:
+ /* tag 'IRInfo' */
+ tvee->has_ir = eeprom_data[i+1];
+ break;
+
+ /* case 0x10: tag 'VBIInfo' */
+ /* case 0x11: tag 'QCInfo' */
+ /* case 0x12: tag 'InfoBits' */
+
default:
- dprintk(1, "Not sure what to do with tag [%02x]\n", tag);
+ tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag);
/* dump the rest of the packet? */
}
-
}
if (!done) {
- TVEEPROM_KERN_ERR("Ran out of data!\n");
+ tveeprom_warn("Ran out of data!\n");
return;
}
@@ -377,47 +483,72 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
tvee->rev_str[4] = 0;
}
- if (hasRadioTuner(tuner) && !tvee->has_radio) {
- TVEEPROM_KERN_INFO("The eeprom says no radio is present, but the tuner type\n");
- TVEEPROM_KERN_INFO("indicates otherwise. I will assume that radio is present.\n");
+ if (hasRadioTuner(tuner1) && !tvee->has_radio) {
+ tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
+ tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
tvee->has_radio = 1;
}
- if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
- tvee->tuner_type = hauppauge_tuner[tuner].id;
- t_name = hauppauge_tuner[tuner].name;
+ if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+ tvee->tuner_type = hauppauge_tuner[tuner1].id;
+ t_name1 = hauppauge_tuner[tuner1].name;
} else {
- t_name = "<unknown>";
+ t_name1 = "unknown";
+ }
+
+ if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+ tvee->tuner2_type = hauppauge_tuner[tuner2].id;
+ t_name2 = hauppauge_tuner[tuner2].name;
+ } else {
+ t_name2 = "unknown";
}
tvee->tuner_formats = 0;
- t_fmt_name = "<none>";
- for (i = 0; i < 8; i++) {
- if (t_format & (1<<i)) {
+ tvee->tuner2_formats = 0;
+ for (i = j = 0; i < 8; i++) {
+ if (t_format1 & (1 << i)) {
tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
- /* yuck */
- t_fmt_name = hauppauge_tuner_fmt[i].name;
+ t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
}
+ if (t_format2 & (1 << i)) {
+ tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
+ t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
+ }
}
-
- TVEEPROM_KERN_INFO("Hauppauge: model = %d, rev = %s, serial# = %d\n",
- tvee->model,
- tvee->rev_str,
- tvee->serial_number);
- TVEEPROM_KERN_INFO("tuner = %s (idx = %d, type = %d)\n",
- t_name,
- tuner,
- tvee->tuner_type);
- TVEEPROM_KERN_INFO("tuner fmt = %s (eeprom = 0x%02x, v4l2 = 0x%08x)\n",
- t_fmt_name,
- t_format,
- tvee->tuner_formats);
-
- TVEEPROM_KERN_INFO("audio_processor = %s (type = %d)\n",
- STRM(sndtype,tvee->audio_processor),
+ tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
+ tvee->model, tvee->rev_str, tvee->serial_number);
+ tveeprom_info("tuner model is %s (idx %d, type %d)\n",
+ t_name1, tuner1, tvee->tuner_type);
+ tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+ t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3],
+ t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7],
+ t_format1);
+ if (tuner2) {
+ tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
+ t_name2, tuner2, tvee->tuner2_type);
+ }
+ if (t_format2) {
+ tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+ t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3],
+ t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7],
+ t_format2);
+ }
+ tveeprom_info("audio processor is %s (idx %d)\n",
+ STRM(audioIC, tvee->audio_processor),
tvee->audio_processor);
-
+ if (tvee->decoder_processor) {
+ tveeprom_info("decoder processor is %s (idx %d)\n",
+ STRM(decoderIC, tvee->decoder_processor),
+ tvee->decoder_processor);
+ }
+ if (tvee->has_ir == 2)
+ tveeprom_info("has %sradio\n",
+ tvee->has_radio ? "" : "no ");
+ else
+ tveeprom_info("has %sradio, has %sIR remote\n",
+ tvee->has_radio ? "" : "no ",
+ tvee->has_ir ? "" : "no ");
}
EXPORT_SYMBOL(tveeprom_hauppauge_analog);
@@ -429,40 +560,31 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
unsigned char buf;
int err;
- dprintk(1, "%s\n",__FUNCTION__);
buf = 0;
- if (1 != (err = i2c_master_send(c,&buf,1))) {
- printk(KERN_INFO "tveeprom(%s): Huh, no eeprom present (err=%d)?\n",
- c->name,err);
+ if (1 != (err = i2c_master_send(c, &buf, 1))) {
+ tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
return -1;
}
- if (len != (err = i2c_master_recv(c,eedata,len))) {
- printk(KERN_WARNING "tveeprom(%s): i2c eeprom read error (err=%d)\n",
- c->name,err);
+ if (len != (err = i2c_master_recv(c, eedata, len))) {
+ tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
return -1;
}
+ if (debug) {
+ int i;
+
+ tveeprom_info("full 256-byte eeprom dump:\n");
+ for (i = 0; i < len; i++) {
+ if (0 == (i % 16))
+ tveeprom_info("%02x:", i);
+ printk(" %02x", eedata[i]);
+ if (15 == (i % 16))
+ printk("\n");
+ }
+ }
return 0;
}
EXPORT_SYMBOL(tveeprom_read);
-#if 0
-int tveeprom_dump(unsigned char *eedata, int len)
-{
- int i;
-
- dprintk(1, "%s\n",__FUNCTION__);
- for (i = 0; i < len; i++) {
- if (0 == (i % 16))
- printk(KERN_INFO "tveeprom: %02x:",i);
- printk(" %02x",eedata[i]);
- if (15 == (i % 16))
- printk("\n");
- }
- return 0;
-}
-EXPORT_SYMBOL(tveeprom_dump);
-#endif /* 0 */
-
/* ----------------------------------------------------------------------- */
/* needed for ivtv.sf.net at the moment. Should go away in the long */
/* run, just call the exported tveeprom_* directly, there is no point in */
@@ -495,12 +617,13 @@ tveeprom_command(struct i2c_client *client,
buf = kmalloc(256,GFP_KERNEL);
memset(buf,0,256);
tveeprom_read(client,buf,256);
- tveeprom_hauppauge_analog(&eeprom,buf);
+ tveeprom_hauppauge_analog(client, &eeprom,buf);
kfree(buf);
eeprom_props[0] = eeprom.tuner_type;
eeprom_props[1] = eeprom.tuner_formats;
eeprom_props[2] = eeprom.model;
eeprom_props[3] = eeprom.revision;
+ eeprom_props[4] = eeprom.has_radio;
break;
default:
return -EINVAL;
@@ -515,8 +638,6 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
{
struct i2c_client *client;
- dprintk(1,"%s: id 0x%x @ 0x%x\n",__FUNCTION__,
- adapter->id, address << 1);
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (NULL == client)
return -ENOMEM;
@@ -533,8 +654,7 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
static int
tveeprom_attach_adapter (struct i2c_adapter *adapter)
{
- dprintk(1,"%s: id 0x%x\n",__FUNCTION__,adapter->id);
- if (adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adapter->id != I2C_HW_B_BT848)
return 0;
return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
}
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 51b99cdbf29e..d86e08ebddfc 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -1,5 +1,4 @@
/*
- * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
*/
#include <linux/module.h>
@@ -91,7 +90,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
strlcpy(info.id, "tv card", sizeof(info.id));
- strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+ strlcpy(info.name, client->name, sizeof(info.name));
info.modify_counter = 42 /* FIXME */;
if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
@@ -100,7 +99,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
strlcpy(info.id, "tv card", sizeof(info.id));
- strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+ strlcpy(info.name, client->name, sizeof(info.name));
if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -276,9 +275,9 @@ static int tvmixer_clients(struct i2c_client *client)
#else
/* TV card ??? */
switch (client->adapter->id) {
- case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+ case I2C_HW_SMBUS_VOODOO3:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
/* ok, have a look ... */
break;
default:
@@ -295,7 +294,7 @@ static int tvmixer_clients(struct i2c_client *client)
devices[i].dev = NULL;
devices[i].minor = -1;
printk("tvmixer: %s unregistered (#1)\n",
- i2c_clientname(client));
+ client->name);
return 0;
}
}
@@ -354,7 +353,7 @@ static void __exit tvmixer_cleanup_module(void)
if (devices[i].minor != -1) {
unregister_sound_mixer(devices[i].minor);
printk("tvmixer: %s unregistered (#2)\n",
- i2c_clientname(devices[i].dev));
+ devices[i].dev->name);
}
}
}
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 70ecbdb80277..59bb71381a1b 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1,5 +1,4 @@
/*
- * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
*
* Video for Linux Two
* Backward Compatibility Layer
@@ -604,9 +603,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
break;
}
-#if 0 /* FIXME */
- pict->depth = fmt2->fmt.pix.depth;
-#endif
pict->palette = pixelformat_to_palette(
fmt2->fmt.pix.pixelformat);
break;
@@ -707,13 +703,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
}
case VIDIOCSTUNER: /* select a tuner input */
{
-#if 0 /* FIXME */
- err = drv(inode, file, VIDIOC_S_INPUT, &i);
- if (err < 0)
- dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
-#else
err = 0;
-#endif
break;
}
case VIDIOCGFREQ: /* get frequency */
@@ -852,12 +842,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
err = 0;
break;
}
-#if 0
- case VIDIOCGMBUF:
- /* v4l2 drivers must implement that themself. The
- mmap() differences can't be translated fully
- transparent, thus there is no point to try that */
-#endif
case VIDIOCMCAPTURE: /* capture a frame */
{
struct video_mmap *mm = arg;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b5e0cf3448f4..597b8db35a13 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -84,20 +84,6 @@ MODULE_LICENSE("GPL");
* Video Standard Operations (contributed by Michael Schimek)
*/
-#if 0 /* seems to have no users */
-/* This is the recommended method to deal with the framerate fields. More
- sophisticated drivers will access the fields directly. */
-unsigned int
-v4l2_video_std_fps(struct v4l2_standard *vs)
-{
- if (vs->frameperiod.numerator > 0)
- return (((vs->frameperiod.denominator << 8) /
- vs->frameperiod.numerator) +
- (1 << 7)) / (1 << 8);
- return 0;
-}
-EXPORT_SYMBOL(v4l2_video_std_fps);
-#endif
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
@@ -213,10 +199,6 @@ char *v4l2_ioctl_names[256] = {
[_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
[_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
[_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
-#if 0
- [_IOC_NR(VIDIOC_G_COMP)] = "VIDIOC_G_COMP",
- [_IOC_NR(VIDIOC_S_COMP)] = "VIDIOC_S_COMP",
-#endif
[_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
[_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
[_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index 15f5bb486963..55f129e964eb 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: video-buf-dvb.c,v 1.7 2004/12/09 12:51:35 kraxel Exp $
*
* some helper function for simple DVB cards which simply DMA the
* complete transport stream and let the computer sort everything else
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 5afdc7852610..574b8e36f3c6 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -1,5 +1,4 @@
/*
- * $Id: video-buf.c,v 1.18 2005/02/24 13:32:30 kraxel Exp $
*
* generic helper functions for video4linux capture buffers, to handle
* memory management and PCI DMA. Right now bttv + saa7134 use it.
@@ -268,10 +267,10 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
kfree(dma->pages);
dma->pages = NULL;
}
- if (dma->vmalloc) {
- vfree(dma->vmalloc);
- dma->vmalloc = NULL;
- }
+
+ vfree(dma->vmalloc);
+ dma->vmalloc = NULL;
+
if (dma->bus_addr) {
dma->bus_addr = 0;
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 76e8681d65c6..d8a0f763ca10 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -1,80 +1,606 @@
/*
- * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys.
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
*
* This file is subject to the terms and conditions of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * Based on the previous version of the driver for 2.4 kernels by:
* Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
*/
-#include <linux/module.h>
+/*
+ * TODO:
+ * - remove "hacks" from memory allocation code and implement nopage()
+ * - check decimation, calculating and reporting image size when
+ * using decimation
+ * - check vino_acquire_input(), vino_set_input() and channel
+ * ownership handling
+ * - report VINO error-interrupts via ioctls ?
+ * - implement picture controls (all implemented?)
+ * - use macros for boolean values (?)
+ * - implement user mode buffers and overlay (?)
+ */
+
#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/wrapper.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
+#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/time.h>
+#include <linux/moduleparam.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
#include <linux/i2c.h>
#include <linux/i2c-algo-sgi.h>
-#include <asm/addrspace.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/pgtable.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+
#include <asm/paccess.h>
#include <asm/io.h>
#include <asm/sgi/ip22.h>
-#include <asm/sgi/hpc3.h>
#include <asm/sgi/mc.h>
#include "vino.h"
+#include "saa7191.h"
+#include "indycam.h"
+
+/* Uncomment the following line to get lots and lots of (mostly useless)
+ * debug info.
+ * Note that the debug output also slows down the driver significantly */
+// #define VINO_DEBUG
+
+#define VINO_MODULE_VERSION "0.0.3"
+#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3)
+
+MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
+MODULE_VERSION(VINO_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
-/* debugging? */
-#if 1
-#define DEBUG(x...) printk(x);
+#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags))
+#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags))
+
+#ifdef VINO_DEBUG
+#define dprintk(x...) printk("VINO: " x);
#else
-#define DEBUG(x...)
+#define dprintk(x...)
#endif
+#define VINO_NO_CHANNEL 0
+#define VINO_CHANNEL_A 1
+#define VINO_CHANNEL_B 2
+
+#define VINO_PAL_WIDTH 768
+#define VINO_PAL_HEIGHT 576
+#define VINO_NTSC_WIDTH 640
+#define VINO_NTSC_HEIGHT 480
+
+#define VINO_MIN_WIDTH 32
+#define VINO_MIN_HEIGHT 32
+
+#define VINO_CLIPPING_START_ODD_D1 1
+#define VINO_CLIPPING_START_ODD_PAL 1
+#define VINO_CLIPPING_START_ODD_NTSC 1
+
+#define VINO_CLIPPING_START_EVEN_D1 2
+#define VINO_CLIPPING_START_EVEN_PAL 2
+#define VINO_CLIPPING_START_EVEN_NTSC 2
+
+#define VINO_INPUT_CHANNEL_COUNT 3
+
+#define VINO_INPUT_NONE -1
+#define VINO_INPUT_COMPOSITE 0
+#define VINO_INPUT_SVIDEO 1
+#define VINO_INPUT_D1 2
+
+#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
+
+#define VINO_FIFO_THRESHOLD_DEFAULT 512
+
+/*#define VINO_FRAMEBUFFER_SIZE (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \
+ + 2 * PAGE_SIZE)*/
+#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
+ * VINO_PAL_HEIGHT * 4 \
+ + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
+
+#define VINO_FRAMEBUFFER_MAX_COUNT 8
+
+#define VINO_FRAMEBUFFER_UNUSED 0
+#define VINO_FRAMEBUFFER_IN_USE 1
+#define VINO_FRAMEBUFFER_READY 2
+
+#define VINO_QUEUE_ERROR -1
+#define VINO_QUEUE_MAGIC 0x20050125
+
+#define VINO_MEMORY_NONE 0
+#define VINO_MEMORY_MMAP 1
+#define VINO_MEMORY_USERPTR 2
+
+#define VINO_DUMMY_DESC_COUNT 4
+#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
+
+/* the number is the index for vino_data_formats */
+#define VINO_DATA_FMT_NONE -1
+#define VINO_DATA_FMT_GREY 0
+#define VINO_DATA_FMT_RGB332 1
+#define VINO_DATA_FMT_RGB32 2
+#define VINO_DATA_FMT_YUV 3
+//#define VINO_DATA_FMT_RGB24 4
+
+#define VINO_DATA_FMT_COUNT 4
+
+#define VINO_DATA_NORM_NONE -1
+#define VINO_DATA_NORM_NTSC 0
+#define VINO_DATA_NORM_PAL 1
+#define VINO_DATA_NORM_SECAM 2
+#define VINO_DATA_NORM_D1 3
+/* The following is a special entry that can be used to
+ * autodetect the norm. */
+#define VINO_DATA_NORM_AUTO 0xff
+
+#define VINO_DATA_NORM_COUNT 4
-/* VINO ASIC registers */
-struct sgi_vino *vino;
+/* Internal data structure definitions */
-static const char *vinostr = "VINO IndyCam/TV";
-static int threshold_a = 512;
-static int threshold_b = 512;
+struct vino_input {
+ char *name;
+ v4l2_std_id std;
+};
+
+struct vino_clipping {
+ unsigned int left, right, top, bottom;
+};
+
+struct vino_data_format {
+ /* the description */
+ char *description;
+ /* bytes per pixel */
+ unsigned int bpp;
+ /* V4L2 fourcc code */
+ __u32 pixelformat;
+ /* V4L2 colorspace (duh!) */
+ enum v4l2_colorspace colorspace;
+};
+
+struct vino_data_norm {
+ char *description;
+ unsigned int width, height;
+ struct vino_clipping odd;
+ struct vino_clipping even;
+
+ v4l2_std_id std;
+ unsigned int fps_min, fps_max;
+ __u32 framelines;
+};
+
+struct vino_descriptor_table {
+ /* the number of PAGE_SIZE sized pages in the buffer */
+ unsigned int page_count;
+ /* virtual (kmalloc'd) pointers to the actual data
+ * (in PAGE_SIZE chunks, used with mmap streaming) */
+ unsigned long *virtual;
+
+ /* cpu address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ unsigned long *dma_cpu;
+ /* dma address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ dma_addr_t dma;
+};
+
+struct vino_framebuffer {
+ /* identifier nubmer */
+ unsigned int id;
+ /* the length of the whole buffer */
+ unsigned int size;
+ /* the length of actual data in buffer */
+ unsigned int data_size;
+ /* the data format */
+ unsigned int data_format;
+ /* the state of buffer data */
+ unsigned int state;
+ /* is the buffer mapped in user space? */
+ unsigned int map_count;
+ /* memory offset for mmap() */
+ unsigned int offset;
+ /* frame counter */
+ unsigned int frame_counter;
+ /* timestamp (written when image capture finishes) */
+ struct timeval timestamp;
+
+ struct vino_descriptor_table desc_table;
+
+ spinlock_t state_lock;
+};
-struct vino_device {
- struct video_device vdev;
-#define VINO_CHAN_A 1
-#define VINO_CHAN_B 2
- int chan;
+struct vino_framebuffer_fifo {
+ unsigned int length;
+
+ unsigned int used;
+ unsigned int head;
+ unsigned int tail;
+
+ unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT];
+};
+
+struct vino_framebuffer_queue {
+ unsigned int magic;
+
+ /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
+ unsigned int type;
+ unsigned int length;
+
+ /* data field of in and out contain index numbers for buffer */
+ struct vino_framebuffer_fifo in;
+ struct vino_framebuffer_fifo out;
+
+ struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT];
+
+ spinlock_t queue_lock;
+ struct semaphore queue_sem;
+ wait_queue_head_t frame_wait_queue;
+};
+
+struct vino_channel_settings {
+ unsigned int channel;
+
+ int input;
+ unsigned int data_format;
+ unsigned int data_norm;
+ struct vino_clipping clipping;
+ unsigned int decimation;
+ unsigned int line_size;
+ unsigned int alpha;
+ unsigned int fps;
+ unsigned int framert_reg;
+
+ unsigned int fifo_threshold;
+
+ struct vino_framebuffer_queue fb_queue;
+
+ /* number of the current field */
+ unsigned int field;
+
+ /* read in progress */
+ int reading;
+ /* streaming is active */
+ int streaming;
+ /* the driver is currently processing the queue */
+ int capturing;
+
+ struct semaphore sem;
+ spinlock_t capture_lock;
+
+ unsigned int users;
+
+ /* V4L support */
+ struct video_device *v4l_device;
};
struct vino_client {
+ /* the channel which owns this client:
+ * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+ unsigned int owner;
struct i2c_client *driver;
- int owner;
};
-struct vino_video {
- struct vino_device chA;
- struct vino_device chB;
+struct vino_settings {
+ struct vino_channel_settings a;
+ struct vino_channel_settings b;
struct vino_client decoder;
struct vino_client camera;
- struct semaphore input_lock;
+ /* a lock for vino register access */
+ spinlock_t vino_lock;
+ /* a lock for channel input changes */
+ spinlock_t input_lock;
- /* Loaded into VINO descriptors to clear End Of Descriptors table
- * interupt condition */
unsigned long dummy_page;
- unsigned int dummy_buf[4] __attribute__((aligned(8)));
+ struct vino_descriptor_table dummy_desc_table;
};
-static struct vino_video *Vino;
+/* Module parameters */
+
+/*
+ * Using vino_pixel_conversion the ARGB32-format pixels supplied
+ * by the VINO chip can be converted to more common formats
+ * like RGBA32 (or probably RGB24 in the future). This way we
+ * can give out data that can be specified correctly with
+ * the V4L2-definitions.
+ *
+ * The pixel format is specified as RGBA32 when no conversion
+ * is used.
+ *
+ * Note that this only affects the 32-bit bit depth.
+ *
+ * Use non-zero value to enable conversion.
+ */
+static int vino_pixel_conversion = 0;
+module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+MODULE_PARM_DESC(pixelconv,
+ "enable pixel conversion (non-zero value enables)");
+
+/* Internal data structures */
+
+static struct sgi_vino *vino;
+
+static struct vino_settings *vino_drvdata;
+
+static const char *vino_driver_name = "vino";
+static const char *vino_driver_description = "SGI VINO";
+static const char *vino_bus_name = "GIO64 bus";
+static const char *vino_v4l_device_name_a = "SGI VINO Channel A";
+static const char *vino_v4l_device_name_b = "SGI VINO Channel B";
+
+static const struct vino_input vino_inputs[] = {
+ {
+ .name = "Composite",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ },{
+ .name = "S-Video",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ },{
+ .name = "D1 (IndyCam)",
+ .std = V4L2_STD_NTSC,
+ }
+};
+
+static const struct vino_data_format vino_data_formats[] = {
+ {
+ .description = "8-bit greyscale",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_GREY,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ },{
+ .description = "8-bit dithered RGB 3-3-2",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_RGB332,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },{
+ .description = "32-bit RGB",
+ .bpp = 4,
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },{
+ .description = "YUV 4:2:2",
+ .bpp = 4,
+ .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ }/*,{
+ .description = "24-bit RGB",
+ .bpp = 3,
+ .pixelformat = V4L2_PIX_FMT_RGB24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }*/
+};
+
+static const struct vino_data_norm vino_data_norms[] = {
+ {
+ .description = "NTSC",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ },{
+ .description = "PAL",
+ .std = V4L2_STD_PAL,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ },{
+ .description = "SECAM",
+ .std = V4L2_STD_SECAM,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ },{
+ .description = "NTSC (D1 input)",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ }
+};
+
+#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
+
+struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic Gain Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AGC_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic White Balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AWB_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = INDYCAM_GAIN_MIN,
+ .maximum = INDYCAM_GAIN_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAIN_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Saturation",
+ .minimum = INDYCAM_RED_SATURATION_MIN,
+ .maximum = INDYCAM_RED_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_SATURATION_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE + 1,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Saturation",
+ .minimum = INDYCAM_BLUE_SATURATION_MIN,
+ .maximum = INDYCAM_BLUE_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = INDYCAM_RED_BALANCE_MIN,
+ .maximum = INDYCAM_RED_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_BALANCE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = INDYCAM_BLUE_BALANCE_MIN,
+ .maximum = INDYCAM_BLUE_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Shutter Control",
+ .minimum = INDYCAM_SHUTTER_MIN,
+ .maximum = INDYCAM_SHUTTER_MAX,
+ .step = 1,
+ .default_value = INDYCAM_SHUTTER_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_GAMMA,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gamma",
+ .minimum = INDYCAM_GAMMA_MIN,
+ .maximum = INDYCAM_GAMMA_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAMMA_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ }
+};
+
+#define VINO_SAA7191_V4L2_CONTROL_COUNT 2
+
+struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = SAA7191_HUE_MIN,
+ .maximum = SAA7191_HUE_MAX,
+ .step = 1,
+ .default_value = SAA7191_HUE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "VTR Time Constant",
+ .minimum = SAA7191_VTRC_MIN,
+ .maximum = SAA7191_VTRC_MAX,
+ .step = 1,
+ .default_value = SAA7191_VTRC_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ }
+};
+
+/* VINO I2C bus functions */
unsigned i2c_vino_getctrl(void *data)
{
@@ -112,49 +638,49 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data =
*/
static int i2c_vino_client_reg(struct i2c_client *client)
{
- int res = 0;
+ int ret = 0;
- down(&Vino->input_lock);
+ spin_lock(&vino_drvdata->input_lock);
switch (client->driver->id) {
case I2C_DRIVERID_SAA7191:
- if (Vino->decoder.driver)
- res = -EBUSY;
+ if (vino_drvdata->decoder.driver)
+ ret = -EBUSY;
else
- Vino->decoder.driver = client;
+ vino_drvdata->decoder.driver = client;
break;
case I2C_DRIVERID_INDYCAM:
- if (Vino->camera.driver)
- res = -EBUSY;
+ if (vino_drvdata->camera.driver)
+ ret = -EBUSY;
else
- Vino->camera.driver = client;
+ vino_drvdata->camera.driver = client;
break;
default:
- res = -ENODEV;
+ ret = -ENODEV;
}
- up(&Vino->input_lock);
+ spin_unlock(&vino_drvdata->input_lock);
- return res;
+ return ret;
}
static int i2c_vino_client_unreg(struct i2c_client *client)
{
- int res = 0;
+ int ret = 0;
- down(&Vino->input_lock);
- if (client == Vino->decoder.driver) {
- if (Vino->decoder.owner)
- res = -EBUSY;
+ spin_lock(&vino_drvdata->input_lock);
+ if (client == vino_drvdata->decoder.driver) {
+ if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
+ ret = -EBUSY;
else
- Vino->decoder.driver = NULL;
- } else if (client == Vino->camera.driver) {
- if (Vino->camera.owner)
- res = -EBUSY;
+ vino_drvdata->decoder.driver = NULL;
+ } else if (client == vino_drvdata->camera.driver) {
+ if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
+ ret = -EBUSY;
else
- Vino->camera.driver = NULL;
+ vino_drvdata->camera.driver = NULL;
}
- up(&Vino->input_lock);
+ spin_unlock(&vino_drvdata->input_lock);
- return res;
+ return ret;
}
static struct i2c_adapter vino_i2c_adapter =
@@ -176,172 +702,3591 @@ static int vino_i2c_del_bus(void)
return i2c_sgi_del_bus(&vino_i2c_adapter);
}
+static int i2c_camera_command(unsigned int cmd, void *arg)
+{
+ return vino_drvdata->camera.driver->
+ driver->command(vino_drvdata->camera.driver,
+ cmd, arg);
+}
+
+static int i2c_decoder_command(unsigned int cmd, void *arg)
+{
+ return vino_drvdata->decoder.driver->
+ driver->command(vino_drvdata->decoder.driver,
+ cmd, arg);
+}
+
+/* VINO framebuffer/DMA descriptor management */
+
+static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
+ unsigned int count)
+{
+ unsigned int i;
+
+ dprintk("vino_free_buffer_with_count(): count = %d\n", count);
+
+ for (i = 0; i < count; i++) {
+ mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i]));
+ dma_unmap_single(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ free_page(fb->desc_table.virtual[i]);
+ }
+
+ dma_free_coherent(NULL,
+ VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
+ sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
+ fb->desc_table.dma);
+ kfree(fb->desc_table.virtual);
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+}
+
+static void vino_free_buffer(struct vino_framebuffer *fb)
+{
+ vino_free_buffer_with_count(fb, fb->desc_table.page_count);
+}
+
+static int vino_allocate_buffer(struct vino_framebuffer *fb,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_allocate_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE) + 4) & ~3;
+
+ dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual = (unsigned long *)
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+ fb->data_format = VINO_DATA_FMT_NONE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+
+#if 0
+/* user buffers not fully implemented yet */
+static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
+ void *user,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_prepare_user_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE)) & ~3;
+
+ dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual = (unsigned long *)
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+#endif
+
+static void vino_sync_buffer(struct vino_framebuffer *fb)
+{
+ int i;
+
+ dprintk("vino_sync_buffer():\n");
+
+ for (i = 0; i < fb->desc_table.page_count; i++)
+ dma_sync_single(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+}
+
+/* Framebuffer fifo functions (need to be locked externally) */
+
+static void vino_fifo_init(struct vino_framebuffer_fifo *f,
+ unsigned int length)
+{
+ f->length = 0;
+ f->used = 0;
+ f->head = 0;
+ f->tail = 0;
+
+ if (length > VINO_FRAMEBUFFER_MAX_COUNT)
+ length = VINO_FRAMEBUFFER_MAX_COUNT;
+
+ f->length = length;
+}
+
+/* returns true/false */
+static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+ unsigned int i;
+ for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
+ if (f->data[i] == id)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* returns true/false */
+static int vino_fifo_full(struct vino_framebuffer_fifo *f)
+{
+ return (f->used == f->length);
+}
+
+static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
+{
+ return f->used;
+}
-static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
{
+ if (id >= f->length) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (vino_fifo_has_id(f, id)) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (f->used < f->length) {
+ f->data[f->tail] = id;
+ f->tail = (f->tail + 1) % f->length;
+ f->used++;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
}
-static int vino_open(struct video_device *dev, int flags)
+static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
return 0;
}
-static void vino_close(struct video_device *dev)
+static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ f->head = (f->head + 1) % f->length;
+ f->used--;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
}
-static int vino_mmap(struct video_device *dev, const char *adr,
- unsigned long size)
+/* Framebuffer queue functions */
+
+/* execute with queue_lock locked */
+static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
+ unsigned int length)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ unsigned int i;
- return -EINVAL;
+ q->length = 0;
+ memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
+ memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
+ for (i = 0; i < length; i++) {
+ dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
+ i);
+ vino_free_buffer(q->buffer[i]);
+ kfree(q->buffer[i]);
+ }
+
+ q->type = VINO_MEMORY_NONE;
+ q->magic = 0;
}
-static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static void vino_queue_free(struct vino_framebuffer_queue *q)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ dprintk("vino_queue_free():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC)
+ return;
+ if (q->type != VINO_MEMORY_MMAP)
+ return;
+
+ down(&q->queue_sem);
+
+ vino_queue_free_with_count(q, q->length);
+
+ up(&q->queue_sem);
+}
+
+static int vino_queue_init(struct vino_framebuffer_queue *q,
+ unsigned int *length)
+{
+ unsigned int i;
+ int ret = 0;
+
+ dprintk("vino_queue_init(): length = %d\n", *length);
+
+ if (q->magic == VINO_QUEUE_MAGIC) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (q->type != VINO_MEMORY_NONE) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (*length < 1)
+ return -EINVAL;
+
+ down(&q->queue_sem);
+
+ if (*length > VINO_FRAMEBUFFER_MAX_COUNT)
+ *length = VINO_FRAMEBUFFER_MAX_COUNT;
+
+ q->length = 0;
+
+ for (i = 0; i < *length; i++) {
+ dprintk("vino_queue_init(): allocating buffer %d\n", i);
+ q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
+ GFP_KERNEL);
+ if (!q->buffer[i]) {
+ dprintk("vino_queue_init(): kmalloc() failed\n");
+ ret = -ENOMEM;
+ break;
+ }
+
+ ret = vino_allocate_buffer(q->buffer[i],
+ VINO_FRAMEBUFFER_SIZE);
+ if (ret) {
+ kfree(q->buffer[i]);
+ dprintk("vino_queue_init(): "
+ "vino_allocate_buffer() failed\n");
+ break;
+ }
+
+ q->buffer[i]->id = i;
+ if (i > 0) {
+ q->buffer[i]->offset = q->buffer[i - 1]->offset +
+ q->buffer[i - 1]->size;
+ } else {
+ q->buffer[i]->offset = 0;
+ }
+
+ spin_lock_init(&q->buffer[i]->state_lock);
+
+ dprintk("vino_queue_init(): buffer = %d, offset = %d, "
+ "size = %d\n", i, q->buffer[i]->offset,
+ q->buffer[i]->size);
+ }
+
+ if (ret) {
+ vino_queue_free_with_count(q, i);
+ *length = 0;
+ } else {
+ q->length = *length;
+ vino_fifo_init(&q->in, q->length);
+ vino_fifo_init(&q->out, q->length);
+ q->type = VINO_MEMORY_MMAP;
+ q->magic = VINO_QUEUE_MAGIC;
+ }
+
+ up(&q->queue_sem);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_add(struct
+ vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned int total;
+ unsigned long flags;
+
+ dprintk("vino_queue_add(): id = %d\n", id);
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ /* not needed?: if (vino_fifo_full(&q->out)) {
+ goto out;
+ }*/
+ /* check that outgoing queue isn't already full
+ * (or that it won't become full) */
+ total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+ if (total >= q->length)
+ goto out;
+
+ if (vino_fifo_enqueue(&q->in, id))
+ goto out;
+
+ ret = q->buffer[id];
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_transfer(struct
+ vino_framebuffer_queue *q)
+{
+ struct vino_framebuffer *ret = NULL;
+ struct vino_framebuffer *fb;
+ int id;
+ unsigned long flags;
+
+ dprintk("vino_queue_transfer():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ // now this actually removes an entry from the incoming queue
+ if (vino_fifo_dequeue(&q->in, &id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_transfer(): id = %d\n", id);
+ fb = q->buffer[id];
+
+ // we have already checked that the outgoing queue is not full, but...
+ if (vino_fifo_enqueue(&q->out, id)) {
+ printk(KERN_ERR "vino_queue_transfer(): "
+ "outgoing queue is full, this shouldn't happen!\n");
+ goto out;
+ }
+
+ ret = fb;
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->in, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->out, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->in);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_total(struct vino_framebuffer_queue *q,
+ unsigned int *total)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_peek(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_peek(&q->in, id)) {
+ goto out;
+ }
+
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_remove(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+ dprintk("vino_queue_remove():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_dequeue(&q->out, id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_remove(): id = %d\n", *id);
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct
+vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ ret = q->buffer[id];
+ out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
+{
+ unsigned int length = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return length;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ length = q->length;
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return length;
+}
+
+static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
+{
+ unsigned int i;
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ for (i = 0; i < q->length; i++) {
+ if (q->buffer[i]->map_count > 0) {
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* VINO functions */
+
+/* execute with input_lock locked */
+static void vino_update_line_size(struct vino_channel_settings *vcs)
+{
+ unsigned int w = vcs->clipping.right - vcs->clipping.left;
+ unsigned int d = vcs->decimation;
+ unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
+ unsigned int lsize;
+
+ dprintk("update_line_size(): before: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+ /* line size must be multiple of 8 bytes */
+ lsize = (bpp * (w / d)) & ~7;
+ w = (lsize / bpp) * d;
+
+ vcs->clipping.right = vcs->clipping.left + w;
+ vcs->line_size = lsize;
+ dprintk("update_line_size(): after: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_clipping(struct vino_channel_settings *vcs,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ unsigned int maxwidth, maxheight;
+ unsigned int d;
+
+ maxwidth = vino_data_norms[vcs->data_norm].width;
+ maxheight = vino_data_norms[vcs->data_norm].height;
+ d = vcs->decimation;
+
+ y &= ~1; /* odd/even fields */
+
+ if (x > maxwidth) {
+ x = 0;
+ }
+ if (y > maxheight) {
+ y = 0;
+ }
+
+ if (((w / d) < VINO_MIN_WIDTH)
+ || ((h / d) < VINO_MIN_HEIGHT)) {
+ w = VINO_MIN_WIDTH * d;
+ h = VINO_MIN_HEIGHT * d;
+ }
+
+ if ((x + w) > maxwidth) {
+ w = maxwidth - x;
+ if ((w / d) < VINO_MIN_WIDTH)
+ x = maxwidth - VINO_MIN_WIDTH * d;
+ }
+ if ((y + h) > maxheight) {
+ h = maxheight - y;
+ if ((h / d) < VINO_MIN_HEIGHT)
+ y = maxheight - VINO_MIN_HEIGHT * d;
+ }
+
+ vcs->clipping.left = x;
+ vcs->clipping.top = y;
+ vcs->clipping.right = x + w;
+ vcs->clipping.bottom = y + h;
+
+ vino_update_line_size(vcs);
+
+ dprintk("clipping %d, %d, %d, %d / %d - %d\n",
+ vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
+ vcs->clipping.bottom, vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_clipping(struct vino_channel_settings *vcs)
+{
+ vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
+ vino_data_norms[vcs->data_norm].height);
+}
+
+/* execute with input_lock locked */
+static void vino_set_scaling(struct vino_channel_settings *vcs,
+ unsigned int w, unsigned int h)
+{
+ unsigned int x, y, curw, curh, d;
+
+ x = vcs->clipping.left;
+ y = vcs->clipping.top;
+ curw = vcs->clipping.right - vcs->clipping.left;
+ curh = vcs->clipping.bottom - vcs->clipping.top;
+
+ d = max(curw / w, curh / h);
+
+ dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
+ w, h, curw, curh, d);
+
+ if (d < 1) {
+ d = 1;
+ }
+ if (d > 8) {
+ d = 8;
+ }
+
+ vcs->decimation = d;
+ vino_set_clipping(vcs, x, y, w * d, h * d);
+
+ dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
+ vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
+ vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_reset_scaling(struct vino_channel_settings *vcs)
+{
+ vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
+ vcs->clipping.bottom - vcs->clipping.top);
+}
+
+/* execute with input_lock locked */
+static void vino_set_framerate(struct vino_channel_settings *vcs,
+ unsigned int fps)
+{
+ unsigned int mask;
+
+ switch (vcs->data_norm) {
+ case VINO_DATA_NORM_NTSC:
+ case VINO_DATA_NORM_D1:
+ fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 6:
+ mask = 0x003;
+ break;
+ case 12:
+ mask = 0x0c3;
+ break;
+ case 18:
+ mask = 0x333;
+ break;
+ case 24:
+ mask = 0x3ff;
+ break;
+ case 30:
+ mask = 0xfff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask);
+ break;
+ case VINO_DATA_NORM_PAL:
+ case VINO_DATA_NORM_SECAM:
+ fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 5:
+ mask = 0x003;
+ break;
+ case 10:
+ mask = 0x0c3;
+ break;
+ case 15:
+ mask = 0x333;
+ break;
+ case 20:
+ mask = 0x0ff;
+ break;
+ case 25:
+ mask = 0x3ff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
+ break;
+ }
+
+ vcs->fps = fps;
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_framerate(struct vino_channel_settings *vcs)
+{
+ vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
+}
+
+/*
+ * Prepare VINO for DMA transfer...
+ * (execute only with vino_lock and input_lock locked)
+ */
+static int vino_dma_setup(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ u32 ctrl, intr;
+ struct sgi_vino_channel *ch;
+ const struct vino_data_norm *norm;
+
+ dprintk("vino_dma_setup():\n");
+
+ vcs->field = 0;
+ fb->frame_counter = 0;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+ norm = &vino_data_norms[vcs->data_norm];
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ /* VINO line size register is set 8 bytes less than actual */
+ ch->line_size = vcs->line_size - 8;
+
+ /* let VINO know where to transfer data */
+ ch->start_desc_tbl = fb->desc_table.dma;
+ ch->next_4_desc = fb->desc_table.dma;
+
+ /* give vino time to fetch the first four descriptors, 5 usec
+ * should be more than enough time */
+ udelay(VINO_DESC_FETCH_DELAY);
+
+ /* set the alpha register */
+ ch->alpha = vcs->alpha;
+
+ /* set clipping registers */
+ ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.top / 2) |
+ VINO_CLIP_X(vcs->clipping.left);
+ ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_X(vcs->clipping.right);
+ /* FIXME: end-of-field bug workaround
+ VINO_CLIP_X(VINO_PAL_WIDTH);
+ */
+
+ /* set the size of actual content in the buffer (DECIMATION !) */
+ fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation) *
+ ((vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation) *
+ vino_data_formats[vcs->data_format].bpp;
+
+ ch->frame_rate = vcs->framert_reg;
+
+ ctrl = vino->control;
+ intr = vino->intr_status;
+
+ if (vcs->channel == VINO_CHANNEL_A) {
+ /* All interrupt conditions for this channel was cleared
+ * so clear the interrupt status register and enable
+ * interrupts */
+ intr &= ~VINO_INTSTAT_A;
+ ctrl |= VINO_CTRL_A_INT;
+
+ /* enable synchronization */
+ ctrl |= VINO_CTRL_A_SYNC_ENBL;
+
+ /* enable frame assembly */
+ ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
+
+ /* set decimation used */
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_A_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_A_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_A_DEC_SCALE_SHIFT;
+ }
+
+ /* select input interface */
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_A_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_A_SELECT;
+
+ /* palette */
+ ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
+ VINO_CTRL_A_DITHER);
+ } else {
+ intr &= ~VINO_INTSTAT_B;
+ ctrl |= VINO_CTRL_B_INT;
+
+ ctrl |= VINO_CTRL_B_SYNC_ENBL;
+ ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
+
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_B_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_B_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_B_DEC_SCALE_SHIFT;
+
+ }
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_B_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_B_SELECT;
+
+ ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
+ VINO_CTRL_B_DITHER);
+ }
+
+ /* set palette */
+ fb->data_format = vcs->data_format;
+
+ switch (vcs->data_format) {
+ case VINO_DATA_FMT_GREY:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
+ break;
+ case VINO_DATA_FMT_RGB32:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
+ break;
+ case VINO_DATA_FMT_YUV:
+ /* nothing needs to be done */
+ break;
+ case VINO_DATA_FMT_RGB332:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
+ VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
+ break;
+ }
+
+ vino->intr_status = intr;
+ vino->control = ctrl;
+
+ return 0;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_start(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ dprintk("vino_dma_start():\n");
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
+ vino->control = ctrl;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_stop(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+ ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
+ vino->control = ctrl;
+ dprintk("vino_dma_stop():\n");
+}
+
+/*
+ * Load dummy page to descriptor registers. This prevents generating of
+ * spurious interrupts. (execute only with vino_lock locked)
+ */
+static void vino_clear_interrupt(struct vino_channel_settings *vcs)
+{
+ struct sgi_vino_channel *ch;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
+ ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
+
+ udelay(VINO_DESC_FETCH_DELAY);
+ dprintk("channel %c clear interrupt condition\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
+}
+
+static int vino_capture(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags, flags2;
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ err = -EBUSY;
+ fb->state = VINO_FRAMEBUFFER_IN_USE;
+
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
+
+ vino_dma_setup(vcs, fb);
+ vino_dma_start(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ return err;
+}
+
+static
+struct vino_framebuffer *vino_capture_enqueue(struct
+ vino_channel_settings *vcs,
+ unsigned int index)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ dprintk("vino_capture_enqueue():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ fb = vino_queue_add(&vcs->fb_queue, index);
+ if (fb == NULL) {
+ dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
+ "queue full?\n");
+ goto out;
+ }
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return fb;
+}
+
+static int vino_capture_next(struct vino_channel_settings *vcs, int start)
+{
+ struct vino_framebuffer *fb;
+ unsigned int incoming, id;
+ int err = 0;
+ unsigned long flags, flags2;
+
+ dprintk("vino_capture_next():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ if (start) {
+ /* start capture only if capture isn't in progress already */
+ if (vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+
+ } else {
+ /* capture next frame:
+ * stop capture if capturing is not set */
+ if (!vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+ }
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_capture_next(): vino_queue_get_incoming() "
+ "failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+ if (incoming == 0) {
+ dprintk("vino_capture_next(): no buffers available\n");
+ goto out;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &id);
+ if (fb == NULL) {
+ dprintk("vino_capture_next(): vino_queue_peek() failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ spin_lock_irqsave(&fb->state_lock, flags2);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ spin_unlock_irqrestore(&fb->state_lock, flags2);
+
+ if (start) {
+ vcs->capturing = 1;
+ }
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ err = vino_capture(vcs, fb);
+
+ return err;
+
+out:
+ vcs->capturing = 0;
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return err;
+}
+
+static int vino_is_capturing(struct vino_channel_settings *vcs)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ ret = vcs->capturing;
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return ret;
+}
+
+/* waits until a frame is captured */
+static int vino_wait_for_frame(struct vino_channel_settings *vcs)
+{
+ wait_queue_t wait;
+ int err = 0;
+
+ dprintk("vino_wait_for_frame():\n");
+
+ init_waitqueue_entry(&wait, current);
+ /* add ourselves into wait queue */
+ add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+ /* and set current state */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* to ensure that schedule_timeout will return immediately
+ * if VINO interrupt was triggred meanwhile */
+ schedule_timeout(HZ / 10);
+
+ if (signal_pending(current))
+ err = -EINTR;
+
+ remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+ dprintk("vino_wait_for_frame(): waiting for frame %s\n",
+ err ? "failed" : "ok");
+
+ return err;
+}
+
+/* the function assumes that PAGE_SIZE % 4 == 0 */
+static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
+ unsigned char *pageptr;
+ unsigned int page, i;
+ unsigned char a;
+
+ for (page = 0; page < fb->desc_table.page_count; page++) {
+ pageptr = (unsigned char *)fb->desc_table.virtual[page];
+
+ for (i = 0; i < PAGE_SIZE; i += 4) {
+ a = pageptr[0];
+ pageptr[0] = pageptr[3];
+ pageptr[1] = pageptr[2];
+ pageptr[2] = pageptr[1];
+ pageptr[3] = a;
+ pageptr += 4;
+ }
+ }
+}
+
+/* checks if the buffer is in correct state and syncs data */
+static int vino_check_buffer(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags;
+
+ dprintk("vino_check_buffer():\n");
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ switch (fb->state) {
+ case VINO_FRAMEBUFFER_IN_USE:
+ err = -EIO;
+ break;
+ case VINO_FRAMEBUFFER_READY:
+ vino_sync_buffer(fb);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (!err) {
+ if (vino_pixel_conversion
+ && (fb->data_format == VINO_DATA_FMT_RGB32)) {
+ vino_convert_to_rgba(fb);
+ }
+ } else if (err && (err != -EINVAL)) {
+ dprintk("vino_check_buffer(): buffer not ready\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+ }
+
+ return err;
+}
+
+/* forcefully terminates capture */
+static void vino_capture_stop(struct vino_channel_settings *vcs)
+{
+ unsigned int incoming = 0, outgoing = 0, id;
+ unsigned long flags, flags2;
+
+ dprintk("vino_capture_stop():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ /* unset capturing to stop queue processing */
+ vcs->capturing = 0;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
+
+ /* remove all items from the queue */
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ while (incoming > 0) {
+ vino_queue_transfer(&vcs->fb_queue);
+
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ }
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ while (outgoing > 0) {
+ vino_queue_remove(&vcs->fb_queue, &id);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+}
+
+static int vino_capture_failed(struct vino_channel_settings *vcs)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+ unsigned int i;
+ int ret;
+
+ dprintk("vino_capture_failed():\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
+ if (ret == VINO_QUEUE_ERROR) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+ if (i == 0) {
+ /* no buffers to process */
+ return 0;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &i);
+ if (fb == NULL) {
+ dprintk("vino_queue_peek() failed\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ vino_queue_transfer(&vcs->fb_queue);
+ vino_queue_remove(&vcs->fb_queue, &i);
+ /* we should actually discard the newest frame,
+ * but who cares ... */
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ return 0;
+}
+
+static void vino_frame_done(struct vino_channel_settings *vcs,
+ unsigned int fc)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ fb = vino_queue_transfer(&vcs->fb_queue);
+ if (!fb) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ fb->frame_counter = fc;
+ do_gettimeofday(&fb->timestamp);
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ fb->state = VINO_FRAMEBUFFER_READY;
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ wake_up(&vcs->fb_queue.frame_wait_queue);
+
+ vino_capture_next(vcs, 0);
+}
+
+static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 intr;
+ unsigned int fc_a, fc_b;
+ int done_a = 0;
+ int done_b = 0;
+
+ spin_lock(&vino_drvdata->vino_lock);
+
+ intr = vino->intr_status;
+ fc_a = vino->a.field_counter / 2;
+ fc_b = vino->b.field_counter / 2;
+
+ // TODO: handle error-interrupts in some special way ?
+
+ if (intr & VINO_INTSTAT_A) {
+ if (intr & VINO_INTSTAT_A_EOF) {
+ vino_drvdata->a.field++;
+ if (vino_drvdata->a.field > 1) {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ vino_drvdata->a.field = 0;
+ done_a = 1;
+ }
+ dprintk("intr: channel A end-of-field interrupt: "
+ "%04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ done_a = 1;
+ dprintk("channel A error interrupt: %04x\n", intr);
+ }
+ }
+ if (intr & VINO_INTSTAT_B) {
+ if (intr & VINO_INTSTAT_B_EOF) {
+ vino_drvdata->b.field++;
+ if (vino_drvdata->b.field > 1) {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ vino_drvdata->b.field = 0;
+ done_b = 1;
+ }
+ dprintk("intr: channel B end-of-field interrupt: "
+ "%04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ done_b = 1;
+ dprintk("channel B error interrupt: %04x\n", intr);
+ }
+ }
+
+ /* always remember to clear interrupt status */
+ vino->intr_status = ~intr;
+
+ spin_unlock(&vino_drvdata->vino_lock);
+
+ if (done_a) {
+ vino_frame_done(&vino_drvdata->a, fc_a);
+ dprintk("channel A frame done, interrupt: %d\n", intr);
+ }
+ if (done_b) {
+ vino_frame_done(&vino_drvdata->b, fc_b);
+ dprintk("channel B frame done, interrupt: %d\n", intr);
+ }
- return -EINVAL;
+ return IRQ_HANDLED;
}
-static const struct video_device vino_device = {
+/* VINO video input management */
+
+static int vino_get_saa7191_input(int input)
+{
+ switch (input) {
+ case VINO_INPUT_COMPOSITE:
+ return SAA7191_INPUT_COMPOSITE;
+ case VINO_INPUT_SVIDEO:
+ return SAA7191_INPUT_SVIDEO;
+ default:
+ printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
+ "invalid input!\n");
+ return -1;
+ }
+}
+
+static int vino_get_saa7191_norm(int norm)
+{
+ switch (norm) {
+ case VINO_DATA_NORM_AUTO:
+ return SAA7191_NORM_AUTO;
+ case VINO_DATA_NORM_PAL:
+ return SAA7191_NORM_PAL;
+ case VINO_DATA_NORM_NTSC:
+ return SAA7191_NORM_NTSC;
+ case VINO_DATA_NORM_SECAM:
+ return SAA7191_NORM_SECAM;
+ default:
+ printk(KERN_ERR "VINO: vino_get_saa7191_norm(): "
+ "invalid norm!\n");
+ return -1;
+ }
+}
+
+/* execute with input_lock locked */
+static int vino_is_input_owner(struct vino_channel_settings *vcs)
+{
+ switch(vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ return (vino_drvdata->decoder.owner == vcs->channel);
+ case VINO_INPUT_D1:
+ return (vino_drvdata->camera.owner == vcs->channel);
+ default:
+ return 0;
+ }
+}
+
+static int vino_acquire_input(struct vino_channel_settings *vcs)
+{
+ int ret = 0;
+
+ dprintk("vino_acquire_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* First try D1 and then SAA7191 */
+ if (vino_drvdata->camera.driver
+ && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
+ if (i2c_use_client(vino_drvdata->camera.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vino_drvdata->camera.owner = vcs->channel;
+ vcs->input = VINO_INPUT_D1;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ } else if (vino_drvdata->decoder.driver
+ && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
+ int saa7191_input;
+ int saa7191_norm;
+
+ if (i2c_use_client(vino_drvdata->decoder.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vino_drvdata->decoder.owner = vcs->channel;
+ vcs->input = VINO_INPUT_COMPOSITE;
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+
+ saa7191_input = vino_get_saa7191_input(vcs->input);
+ i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+
+ saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+ } else {
+ vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.input : vino_drvdata->a.input;
+ vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
+ }
+
+ if (vcs->input == VINO_INPUT_NONE) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (vino_is_input_owner(vcs)) {
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+ }
+
+ dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static int vino_set_input(struct vino_channel_settings *vcs, int input)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+ int ret = 0;
+
+ dprintk("vino_set_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (vcs->input == input)
+ goto out;
+
+ switch(input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ if (!vino_drvdata->decoder.driver) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
+ if (i2c_use_client(vino_drvdata->decoder.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ vino_drvdata->decoder.owner = vcs->channel;
+ }
+
+ if (vino_drvdata->decoder.owner == vcs->channel) {
+ int saa7191_input;
+ int saa7191_norm;
+
+ vcs->input = input;
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+
+ saa7191_input = vino_get_saa7191_input(vcs->input);
+ i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+ saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM,
+ &saa7191_norm);
+ } else {
+ if (vcs2->input != input) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ vcs->input = input;
+ vcs->data_norm = vcs2->data_norm;
+ }
+
+ if (vino_drvdata->camera.owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->
+ camera.driver);
+ vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ }
+ }
+ break;
+ case VINO_INPUT_D1:
+ if (!vino_drvdata->camera.driver) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
+ if (i2c_use_client(vino_drvdata->camera.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ vino_drvdata->camera.owner = vcs->channel;
+ }
+
+ if (vino_drvdata->decoder.owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->
+ decoder.driver);
+ vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ }
+ }
+
+ vcs->input = input;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+
+ dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static void vino_release_input(struct vino_channel_settings *vcs)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+
+ dprintk("vino_release_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* Release ownership of the channel
+ * and if the other channel takes input from
+ * the same source, transfer the ownership */
+ if (vino_drvdata->camera.owner == vcs->channel) {
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->camera.driver);
+ vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ }
+ } else if (vino_drvdata->decoder.owner == vcs->channel) {
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->decoder.driver);
+ vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ }
+ }
+ vcs->input = VINO_INPUT_NONE;
+
+ spin_unlock(&vino_drvdata->input_lock);
+}
+
+/* execute with input_lock locked */
+static int vino_set_data_norm(struct vino_channel_settings *vcs,
+ unsigned int data_norm)
+{
+ int saa7191_norm;
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ /* only one "norm" supported */
+ if (data_norm != VINO_DATA_NORM_D1)
+ return -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+
+ saa7191_norm = vino_get_saa7191_norm(data_norm);
+
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+ vcs->data_norm = data_norm;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* V4L2 helper functions */
+
+static int vino_find_data_format(__u32 pixelformat)
+{
+ int i;
+
+ for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
+ if (vino_data_formats[i].pixelformat == pixelformat)
+ return i;
+ }
+
+ return VINO_DATA_FMT_NONE;
+}
+
+static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index)
+{
+ int data_norm = VINO_DATA_NORM_NONE;
+
+ spin_lock(&vino_drvdata->input_lock);
+ switch(vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ if (index == 0) {
+ data_norm = VINO_DATA_NORM_PAL;
+ } else if (index == 1) {
+ data_norm = VINO_DATA_NORM_NTSC;
+ } else if (index == 2) {
+ data_norm = VINO_DATA_NORM_SECAM;
+ }
+ break;
+ case VINO_INPUT_D1:
+ if (index == 0) {
+ data_norm = VINO_DATA_NORM_D1;
+ }
+ break;
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return data_norm;
+}
+
+static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
+{
+ int input = VINO_INPUT_NONE;
+
+ spin_lock(&vino_drvdata->input_lock);
+ if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ case 2:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ } else if (vino_drvdata->decoder.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ }
+ } else if (vino_drvdata->camera.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return input;
+}
+
+/* execute with input_lock locked */
+static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
+{
+ __u32 index = 0;
+ // FIXME: detect when no inputs available
+
+ if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ case VINO_INPUT_D1:
+ index = 2;
+ break;
+ }
+ } else if (vino_drvdata->decoder.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ }
+ } else if (vino_drvdata->camera.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ index = 0;
+ break;
+ }
+ }
+
+ return index;
+}
+
+/* V4L2 ioctls */
+
+static void vino_v4l2_querycap(struct v4l2_capability *cap)
+{
+ memset(cap, 0, sizeof(struct v4l2_capability));
+
+ strcpy(cap->driver, vino_driver_name);
+ strcpy(cap->card, vino_driver_description);
+ strcpy(cap->bus_info, vino_bus_name);
+ cap->version = VINO_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING;
+ // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+}
+
+static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ __u32 index = i->index;
+ int input;
+ dprintk("requested index = %d\n", index);
+
+ input = vino_enum_input(vcs, index);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ memset(i, 0, sizeof(struct v4l2_input));
+
+ i->index = index;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = vino_inputs[input].std;
+ strcpy(i->name, vino_inputs[input].name);
+
+ if ((input == VINO_INPUT_COMPOSITE)
+ || (input == VINO_INPUT_SVIDEO)) {
+ struct saa7191_status status;
+ i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
+ i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL;
+ i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ __u32 index;
+ int input;
+
+ spin_lock(&vino_drvdata->input_lock);
+ input = vcs->input;
+ index = vino_find_input_index(vcs);
+ spin_unlock(&vino_drvdata->input_lock);
+
+ dprintk("input = %d\n", input);
+
+ if (input == VINO_INPUT_NONE) {
+ return -EINVAL;
+ }
+
+ memset(i, 0, sizeof(struct v4l2_input));
+
+ i->index = index;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = vino_inputs[input].std;
+ strcpy(i->name, vino_inputs[input].name);
+
+ return 0;
+}
+
+static int vino_v4l2_s_input(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ int input;
+ dprintk("requested input = %d\n", i->index);
+
+ input = vino_enum_input(vcs, i->index);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ return vino_set_input(vcs, input);
+}
+
+static int vino_v4l2_enumstd(struct vino_channel_settings *vcs,
+ struct v4l2_standard *s)
+{
+ int index = s->index;
+ int data_norm = vino_enum_data_norm(vcs, index);
+ dprintk("standard index = %d\n", index);
+
+ if (data_norm == VINO_DATA_NORM_NONE)
+ return -EINVAL;
+
+ dprintk("standard name = %s\n",
+ vino_data_norms[data_norm].description);
+
+ memset(s, 0, sizeof(struct v4l2_standard));
+ s->index = index;
+
+ s->id = vino_data_norms[data_norm].std;
+ s->frameperiod.numerator = 1;
+ s->frameperiod.denominator =
+ vino_data_norms[data_norm].fps_max;
+ s->framelines =
+ vino_data_norms[data_norm].framelines;
+ strcpy(s->name,
+ vino_data_norms[data_norm].description);
+
+ return 0;
+}
+
+static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
+ v4l2_std_id *std)
+{
+ spin_lock(&vino_drvdata->input_lock);
+ dprintk("current standard = %d\n", vcs->data_norm);
+ *std = vino_data_norms[vcs->data_norm].std;
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return 0;
+}
+
+static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
+ v4l2_std_id *std)
+{
+ int ret = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* check if the standard is valid for the current input */
+ if (vino_is_input_owner(vcs)
+ && (vino_inputs[vcs->input].std & (*std))) {
+ dprintk("standard accepted\n");
+
+ /* change the video norm for SAA7191
+ * and accept NTSC for D1 (do nothing) */
+
+ if (vcs->input == VINO_INPUT_D1)
+ goto out;
+
+ if ((*std) & V4L2_STD_PAL) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_PAL);
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+ } else if ((*std) & V4L2_STD_NTSC) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC);
+ vcs->data_norm = VINO_DATA_NORM_NTSC;
+ } else if ((*std) & V4L2_STD_SECAM) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM);
+ vcs->data_norm = VINO_DATA_NORM_SECAM;
+ } else {
+ ret = -EINVAL;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_fmtdesc *fd)
+{
+ enum v4l2_buf_type type = fd->type;
+ int index = fd->index;
+ dprintk("format index = %d\n", index);
+
+ switch (fd->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if ((fd->index < 0) ||
+ (fd->index >= VINO_DATA_FMT_COUNT))
+ return -EINVAL;
+ dprintk("format name = %s\n",
+ vino_data_formats[index].description);
+
+ memset(fd, 0, sizeof(struct v4l2_fmtdesc));
+ fd->index = index;
+ fd->type = type;
+ fd->pixelformat = vino_data_formats[index].pixelformat;
+ strcpy(fd->description, vino_data_formats[index].description);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ struct vino_channel_settings tempvcs;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+
+ dprintk("requested: w = %d, h = %d\n",
+ pf->width, pf->height);
+
+ spin_lock(&vino_drvdata->input_lock);
+ memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+ spin_unlock(&vino_drvdata->input_lock);
+
+ tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+ if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+ tempvcs.data_format = VINO_DATA_FMT_RGB32;
+ pf->pixelformat =
+ vino_data_formats[tempvcs.data_format].
+ pixelformat;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[tempvcs.data_format].description);
+
+ pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+ tempvcs.decimation;
+ pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = tempvcs.line_size;
+ pf->sizeimage = tempvcs.line_size *
+ (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+ pf->colorspace =
+ vino_data_formats[tempvcs.data_format].colorspace;
+
+ pf->priv = 0;
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ spin_lock(&vino_drvdata->input_lock);
+
+ pf->width = (vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation;
+ pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].pixelformat;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ pf->priv = 0;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ int data_format;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+
+ data_format = vino_find_data_format(pf->pixelformat);
+ if (data_format == VINO_DATA_FMT_NONE) {
+ vcs->data_format = VINO_DATA_FMT_RGB32;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].
+ pixelformat;
+ } else {
+ vcs->data_format = data_format;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(vcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[vcs->data_format].description);
+
+ pf->width = vcs->clipping.right - vcs->clipping.left;
+ pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ pf->priv = 0;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
+ struct v4l2_cropcap *ccap)
+{
+ const struct vino_data_norm *norm;
+
+ switch (ccap->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+ norm = &vino_data_norms[vcs->data_norm];
+ spin_unlock(&vino_drvdata->input_lock);
+
+ ccap->bounds.left = 0;
+ ccap->bounds.top = 0;
+ ccap->bounds.width = norm->width;
+ ccap->bounds.height = norm->height;
+ memcpy(&ccap->defrect, &ccap->bounds,
+ sizeof(struct v4l2_rect));
+
+ ccap->pixelaspect.numerator = 1;
+ ccap->pixelaspect.denominator = 1;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
+ struct v4l2_crop *c)
+{
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+
+ c->c.left = vcs->clipping.left;
+ c->c.top = vcs->clipping.top;
+ c->c.width = vcs->clipping.right - vcs->clipping.left;
+ c->c.height = vcs->clipping.bottom - vcs->clipping.top;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
+ struct v4l2_crop *c)
+{
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+ vino_set_clipping(vcs, c->c.left, c->c.top,
+ c->c.width, c->c.height);
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
+ struct v4l2_streamparm *sp)
+{
+ switch (sp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+ memset(cp, 0, sizeof(struct v4l2_captureparm));
+
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+
+ spin_lock(&vino_drvdata->input_lock);
+ cp->timeperframe.denominator = vcs->fps;
+ spin_unlock(&vino_drvdata->input_lock);
+
+ // TODO: cp->readbuffers = xxx;
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
+ struct v4l2_streamparm *sp)
+{
+ switch (sp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+
+ spin_lock(&vino_drvdata->input_lock);
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+
+ if ((cp->timeperframe.numerator == 0) ||
+ (cp->timeperframe.denominator == 0)) {
+ /* reset framerate */
+ vino_set_default_framerate(vcs);
+ } else {
+ vino_set_framerate(vcs, cp->timeperframe.denominator /
+ cp->timeperframe.numerator);
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ // TODO: set buffers according to cp->readbuffers
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs,
+ struct v4l2_requestbuffers *rb)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (rb->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ // TODO: check queue type
+ if (rb->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ if (vino_is_capturing(vcs)) {
+ dprintk("busy, capturing\n");
+ return -EBUSY;
+ }
+
+ dprintk("count = %d\n", rb->count);
+ if (rb->count > 0) {
+ if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+ dprintk("busy, buffers still mapped\n");
+ return -EBUSY;
+ } else {
+ vino_queue_free(&vcs->fb_queue);
+ vino_queue_init(&vcs->fb_queue, &rb->count);
+ }
+ } else {
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb,
+ struct v4l2_buffer *b)
+{
+ if (vino_queue_outgoing_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_QUEUED;
+ b->flags |= V4L2_BUF_FLAG_DONE;
+ } else if (vino_queue_incoming_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_DONE;
+ b->flags |= V4L2_BUF_FLAG_QUEUED;
+ } else {
+ b->flags &= ~(V4L2_BUF_FLAG_DONE |
+ V4L2_BUF_FLAG_QUEUED);
+ }
+
+ b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
+
+ if (fb->map_count > 0)
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+ b->index = fb->id;
+ b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
+ V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
+ b->m.offset = fb->offset;
+ b->bytesused = fb->data_size;
+ b->length = fb->size;
+ b->field = V4L2_FIELD_INTERLACED;
+ b->sequence = fb->frame_counter;
+ memcpy(&b->timestamp, &fb->timestamp,
+ sizeof(struct timeval));
+ // b->input ?
+
+ dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
+ fb->id, fb->size, fb->data_size, fb->offset);
+}
+
+static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+
+ // TODO: check queue type
+ if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+ dprintk("invalid index = %d\n",
+ b->index);
+ return -EINVAL;
+ }
+
+ fb = vino_queue_get_buffer(&vcs->fb_queue,
+ b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_get_buffer() failed");
+ return -EINVAL;
+ }
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+ int ret;
+
+ // TODO: check queue type
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ fb = vino_capture_enqueue(vcs, b->index);
+ if (fb == NULL)
+ return -EINVAL;
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+
+ if (vcs->streaming) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret)
+ return ret;
+ }
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b,
+ unsigned int nonblocking)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+ unsigned int incoming, outgoing;
+ int err;
+
+ // TODO: check queue type
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EIO;
+ }
+ err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+ if (err) {
+ dprintk("vino_queue_get_outgoing() failed\n");
+ return -EIO;
+ }
+
+ dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+ if (outgoing == 0) {
+ if (incoming == 0) {
+ dprintk("no incoming or outgoing buffers\n");
+ return -EINVAL;
+ }
+ if (nonblocking) {
+ dprintk("non-blocking I/O was selected and "
+ "there are no buffers to dequeue\n");
+ return -EAGAIN;
+ }
+
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ /* interrupted */
+ vino_capture_failed(vcs);
+ return -EIO;
+ }
+ }
+ }
+
+ fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_remove() failed\n");
+ return -EINVAL;
+ }
+
+ err = vino_check_buffer(vcs, fb);
+ if (err)
+ return -EIO;
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
+{
+ unsigned int incoming;
+ int ret;
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (vcs->streaming)
+ return 0;
+
+ // TODO: check queue type
+
+ if (vino_queue_get_length(&vcs->fb_queue) < 1) {
+ dprintk("no buffers allocated\n");
+ return -EINVAL;
+ }
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (ret) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+
+ vcs->streaming = 1;
+
+ if (incoming > 0) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret) {
+ vcs->streaming = 0;
+
+ dprintk("couldn't start capture\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (!vcs->streaming)
+ return 0;
+
+ vino_capture_stop(vcs);
+ vcs->streaming = 0;
+
+ return 0;
+}
+
+static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
+ struct v4l2_queryctrl *queryctrl)
+{
+ int i;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_indycam_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_saa7191_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ found:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
+ struct v4l2_control *control)
+{
+ struct indycam_control indycam_ctrl;
+ struct saa7191_control saa7191_ctrl;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS,
+ &indycam_ctrl);
+
+ switch(control->id) {
+ case V4L2_CID_AUTOGAIN:
+ control->value = indycam_ctrl.agc;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ control->value = indycam_ctrl.awb;
+ break;
+ case V4L2_CID_GAIN:
+ control->value = indycam_ctrl.gain;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ control->value = indycam_ctrl.red_saturation;
+ break;
+ case V4L2_CID_PRIVATE_BASE + 1:
+ control->value = indycam_ctrl.blue_saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ control->value = indycam_ctrl.red_balance;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ control->value = indycam_ctrl.blue_balance;
+ break;
+ case V4L2_CID_EXPOSURE:
+ control->value = indycam_ctrl.shutter;
+ break;
+ case V4L2_CID_GAMMA:
+ control->value = indycam_ctrl.gamma;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS,
+ &saa7191_ctrl);
+
+ switch(control->id) {
+ case V4L2_CID_HUE:
+ control->value = saa7191_ctrl.hue;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ control->value = saa7191_ctrl.vtrc;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
+ struct v4l2_control *control)
+{
+ struct indycam_control indycam_ctrl;
+ struct saa7191_control saa7191_ctrl;
+ int i;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id ==
+ control->id) {
+ if ((control->value >=
+ vino_indycam_v4l2_controls[i].minimum)
+ && (control->value <=
+ vino_indycam_v4l2_controls[i].
+ maximum)) {
+ goto ok1;
+ } else {
+ err = -ERANGE;
+ goto error;
+ }
+ }
+ }
+ err = -EINVAL;
+ goto error;
+
+ok1:
+ indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED;
+
+ switch(control->id) {
+ case V4L2_CID_AUTOGAIN:
+ indycam_ctrl.agc = control->value;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ indycam_ctrl.awb = control->value;
+ break;
+ case V4L2_CID_GAIN:
+ indycam_ctrl.gain = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ indycam_ctrl.red_saturation = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE + 1:
+ indycam_ctrl.blue_saturation = control->value;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ indycam_ctrl.red_balance = control->value;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ indycam_ctrl.blue_balance = control->value;
+ break;
+ case V4L2_CID_EXPOSURE:
+ indycam_ctrl.shutter = control->value;
+ break;
+ case V4L2_CID_GAMMA:
+ indycam_ctrl.gamma = control->value;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err)
+ i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS,
+ &indycam_ctrl);
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id ==
+ control->id) {
+ if ((control->value >=
+ vino_saa7191_v4l2_controls[i].minimum)
+ && (control->value <=
+ vino_saa7191_v4l2_controls[i].
+ maximum)) {
+ goto ok2;
+ } else {
+ err = -ERANGE;
+ goto error;
+ }
+ }
+ }
+ err = -EINVAL;
+ goto error;
+
+ok2:
+ saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED;
+ saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED;
+
+ switch(control->id) {
+ case V4L2_CID_HUE:
+ saa7191_ctrl.hue = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ saa7191_ctrl.vtrc = control->value;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err)
+ i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS,
+ &saa7191_ctrl);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+error:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+/* File operations */
+
+static int vino_open(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ int ret = 0;
+ dprintk("open(): channel = %c\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
+
+ down(&vcs->sem);
+
+ if (vcs->users) {
+ dprintk("open(): driver busy\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = vino_acquire_input(vcs);
+ if (ret) {
+ dprintk("open(): vino_acquire_input() failed\n");
+ goto out;
+ }
+
+ vcs->users++;
+
+ out:
+ up(&vcs->sem);
+
+ dprintk("open(): %s!\n", ret ? "failed" : "complete");
+
+ return ret;
+}
+
+static int vino_close(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ dprintk("close():\n");
+
+ down(&vcs->sem);
+
+ vcs->users--;
+
+ if (!vcs->users) {
+ vino_release_input(vcs);
+
+ /* stop DMA and free buffers */
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+
+ up(&vcs->sem);
+
+ return 0;
+}
+
+static void vino_vm_open(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count++;
+ dprintk("vino_vm_open(): count = %d\n", fb->map_count);
+}
+
+static void vino_vm_close(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count--;
+ dprintk("vino_vm_close(): count = %d\n", fb->map_count);
+}
+
+static struct vm_operations_struct vino_vm_ops = {
+ .open = vino_vm_open,
+ .close = vino_vm_close,
+};
+
+static int vino_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ struct vino_framebuffer *fb = NULL;
+ unsigned int i, length;
+ int ret = 0;
+
+ dprintk("mmap():\n");
+
+ // TODO: reject mmap if already mapped
+
+ if (down_interruptible(&vcs->sem))
+ return -EINTR;
+
+ if (vcs->reading) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ // TODO: check queue type
+
+ if (!(vma->vm_flags & VM_WRITE)) {
+ dprintk("mmap(): app bug: PROT_WRITE please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!(vma->vm_flags & VM_SHARED)) {
+ dprintk("mmap(): app bug: MAP_SHARED please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* find the correct buffer using offset */
+ length = vino_queue_get_length(&vcs->fb_queue);
+ if (length == 0) {
+ dprintk("mmap(): queue not initialized\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < length; i++) {
+ fb = vino_queue_get_buffer(&vcs->fb_queue, i);
+ if (fb == NULL) {
+ dprintk("mmap(): vino_queue_get_buffer() failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fb->offset == offset)
+ goto found;
+ }
+
+ dprintk("mmap(): invalid offset = %lu\n", offset);
+ ret = -EINVAL;
+ goto out;
+
+found:
+ dprintk("mmap(): buffer = %d\n", i);
+
+ if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
+ dprintk("mmap(): failed: size = %lu > %lu\n",
+ size, fb->desc_table.page_count * PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < fb->desc_table.page_count; i++) {
+ unsigned long pfn =
+ virt_to_phys((void *)fb->desc_table.virtual[i]) >>
+ PAGE_SHIFT;
+
+ if (size < PAGE_SIZE)
+ break;
+
+ // protection was: PAGE_READONLY
+ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+ vma->vm_page_prot)) {
+ dprintk("mmap(): remap_pfn_range() failed\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ start += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ fb->map_count = 1;
+
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_flags &= ~VM_IO;
+ vma->vm_private_data = fb;
+ vma->vm_file = file;
+ vma->vm_ops = &vino_vm_ops;
+
+out:
+ up(&vcs->sem);
+
+ return ret;
+}
+
+static unsigned int vino_poll(struct file *file, poll_table *pt)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ unsigned int outgoing;
+ unsigned int ret = 0;
+
+ // lock mutex (?)
+ // TODO: this has to be corrected for different read modes
+
+ dprintk("poll():\n");
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+ if (outgoing > 0)
+ goto over;
+
+ poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+
+over:
+ dprintk("poll(): data %savailable\n",
+ (outgoing > 0) ? "" : "not ");
+ if (outgoing > 0) {
+ ret = POLLIN | POLLRDNORM;
+ }
+
+error:
+
+ return ret;
+}
+
+static int vino_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+
+ switch (_IOC_TYPE(cmd)) {
+ case 'v':
+ dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd);
+ break;
+ case 'V':
+ dprintk("ioctl(): V4L2 %s (0x%08x)\n",
+ v4l2_ioctl_names[_IOC_NR(cmd)], cmd);
+ break;
+ default:
+ dprintk("ioctl(): unsupported command 0x%08x\n", cmd);
+ }
+
+ switch (cmd) {
+ /* TODO: V4L1 interface (use compatibility layer?) */
+ /* V4L2 interface */
+ case VIDIOC_QUERYCAP: {
+ vino_v4l2_querycap(arg);
+ break;
+ }
+ case VIDIOC_ENUMINPUT: {
+ return vino_v4l2_enuminput(vcs, arg);
+ }
+ case VIDIOC_G_INPUT: {
+ return vino_v4l2_g_input(vcs, arg);
+ }
+ case VIDIOC_S_INPUT: {
+ return vino_v4l2_s_input(vcs, arg);
+ }
+ case VIDIOC_ENUMSTD: {
+ return vino_v4l2_enumstd(vcs, arg);
+ }
+ case VIDIOC_G_STD: {
+ return vino_v4l2_g_std(vcs, arg);
+ }
+ case VIDIOC_S_STD: {
+ return vino_v4l2_s_std(vcs, arg);
+ }
+ case VIDIOC_ENUM_FMT: {
+ return vino_v4l2_enum_fmt(vcs, arg);
+ }
+ case VIDIOC_TRY_FMT: {
+ return vino_v4l2_try_fmt(vcs, arg);
+ }
+ case VIDIOC_G_FMT: {
+ return vino_v4l2_g_fmt(vcs, arg);
+ }
+ case VIDIOC_S_FMT: {
+ return vino_v4l2_s_fmt(vcs, arg);
+ }
+ case VIDIOC_CROPCAP: {
+ return vino_v4l2_cropcap(vcs, arg);
+ }
+ case VIDIOC_G_CROP: {
+ return vino_v4l2_g_crop(vcs, arg);
+ }
+ case VIDIOC_S_CROP: {
+ return vino_v4l2_s_crop(vcs, arg);
+ }
+ case VIDIOC_G_PARM: {
+ return vino_v4l2_g_parm(vcs, arg);
+ }
+ case VIDIOC_S_PARM: {
+ return vino_v4l2_s_parm(vcs, arg);
+ }
+ case VIDIOC_REQBUFS: {
+ return vino_v4l2_reqbufs(vcs, arg);
+ }
+ case VIDIOC_QUERYBUF: {
+ return vino_v4l2_querybuf(vcs, arg);
+ }
+ case VIDIOC_QBUF: {
+ return vino_v4l2_qbuf(vcs, arg);
+ }
+ case VIDIOC_DQBUF: {
+ return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK);
+ }
+ case VIDIOC_STREAMON: {
+ return vino_v4l2_streamon(vcs);
+ }
+ case VIDIOC_STREAMOFF: {
+ return vino_v4l2_streamoff(vcs);
+ }
+ case VIDIOC_QUERYCTRL: {
+ return vino_v4l2_queryctrl(vcs, arg);
+ }
+ case VIDIOC_G_CTRL: {
+ return vino_v4l2_g_ctrl(vcs, arg);
+ }
+ case VIDIOC_S_CTRL: {
+ return vino_v4l2_s_ctrl(vcs, arg);
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static int vino_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct video_device *dev = video_devdata(file);
+ struct vino_channel_settings *vcs = video_get_drvdata(dev);
+ int ret;
+
+ if (down_interruptible(&vcs->sem))
+ return -EINTR;
+
+ ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl);
+
+ up(&vcs->sem);
+
+ return ret;
+}
+
+/* Initialization and cleanup */
+
+// __initdata
+static int vino_init_stage = 0;
+
+static struct file_operations vino_fops = {
.owner = THIS_MODULE,
- .type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE,
- .hardware = VID_HARDWARE_VINO,
- .name = "VINO",
.open = vino_open,
- .close = vino_close,
+ .release = vino_close,
.ioctl = vino_ioctl,
.mmap = vino_mmap,
+ .poll = vino_poll,
+ .llseek = no_llseek,
};
-static int __init vino_init(void)
+static struct video_device v4l_device_template = {
+ .name = "NOT SET",
+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
+ .hardware = VID_HARDWARE_VINO,
+ .fops = &vino_fops,
+ .minor = -1,
+};
+
+static void vino_module_cleanup(int stage)
+{
+ switch(stage) {
+ case 10:
+ video_unregister_device(vino_drvdata->b.v4l_device);
+ vino_drvdata->b.v4l_device = NULL;
+ case 9:
+ video_unregister_device(vino_drvdata->a.v4l_device);
+ vino_drvdata->a.v4l_device = NULL;
+ case 8:
+ vino_i2c_del_bus();
+ case 7:
+ free_irq(SGI_VINO_IRQ, NULL);
+ case 6:
+ if (vino_drvdata->b.v4l_device) {
+ video_device_release(vino_drvdata->b.v4l_device);
+ vino_drvdata->b.v4l_device = NULL;
+ }
+ case 5:
+ if (vino_drvdata->a.v4l_device) {
+ video_device_release(vino_drvdata->a.v4l_device);
+ vino_drvdata->a.v4l_device = NULL;
+ }
+ case 4:
+ /* all entries in dma_cpu dummy table have the same address */
+ dma_unmap_single(NULL,
+ vino_drvdata->dummy_desc_table.dma_cpu[0],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
+ * sizeof(dma_addr_t),
+ (void *)vino_drvdata->
+ dummy_desc_table.dma_cpu,
+ vino_drvdata->dummy_desc_table.dma);
+ case 3:
+ free_page(vino_drvdata->dummy_page);
+ case 2:
+ kfree(vino_drvdata);
+ case 1:
+ iounmap(vino);
+ case 0:
+ break;
+ default:
+ dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
+ stage);
+ }
+}
+
+static int vino_probe(void)
{
- unsigned long rev;
- int i, ret = 0;
+ unsigned long rev_id;
- /* VINO is Indy specific beast */
- if (ip22_is_fullhouse())
+ if (ip22_is_fullhouse()) {
+ printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
return -ENODEV;
+ }
- /*
- * VINO is in the EISA address space, so the sysid register will tell
- * us if the EISA_PRESENT pin on MC has been pulled low.
- *
- * If EISA_PRESENT is not set we definitely don't have a VINO equiped
- * system.
- */
if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
- printk(KERN_ERR "VINO not found\n");
+ printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
return -ENODEV;
}
vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
- if (!vino)
+ if (!vino) {
+ printk(KERN_ERR "VINO: ioremap() failed\n");
return -EIO;
+ }
+ vino_init_stage++;
- /* Okay, once we know that VINO is present we'll read its revision
- * safe way. One never knows... */
- if (get_dbe(rev, &(vino->rev_id))) {
- printk(KERN_ERR "VINO: failed to read revision register\n");
- ret = -ENODEV;
- goto out_unmap;
+ if (get_dbe(rev_id, &(vino->rev_id))) {
+ printk(KERN_ERR "Failed to read VINO revision register\n");
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
}
- if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) {
- printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev);
- ret = -ENODEV;
- goto out_unmap;
+
+ if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
+ printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
+ rev_id);
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
}
- printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev));
- Vino = (struct vino_video *)
- kmalloc(sizeof(struct vino_video), GFP_KERNEL);
- if (!Vino) {
- ret = -ENOMEM;
- goto out_unmap;
+ printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n",
+ VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id));
+
+ return 0;
+}
+
+static int vino_init(void)
+{
+ dma_addr_t dma_dummy_address;
+ int i;
+
+ vino_drvdata = (struct vino_settings *)
+ kmalloc(sizeof(struct vino_settings), GFP_KERNEL);
+ if (!vino_drvdata) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
}
+ memset(vino_drvdata, 0, sizeof(struct vino_settings));
+ vino_init_stage++;
- Vino->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!Vino->dummy_page) {
- ret = -ENOMEM;
- goto out_free_vino;
+ /* create a dummy dma descriptor */
+ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_page) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
}
- for (i = 0; i < 4; i++)
- Vino->dummy_buf[i] = PHYSADDR(Vino->dummy_page);
+ vino_init_stage++;
+
+ // TODO: use page_count in dummy_desc_table
+
+ vino_drvdata->dummy_desc_table.dma_cpu =
+ dma_alloc_coherent(NULL,
+ VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
+ &vino_drvdata->dummy_desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_desc_table.dma_cpu) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ dma_dummy_address = dma_map_single(NULL,
+ (void *)vino_drvdata->dummy_page,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
+ vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
+ }
+
+ /* initialize VINO */
vino->control = 0;
- /* prevent VINO from throwing spurious interrupts */
- vino->a.next_4_desc = PHYSADDR(Vino->dummy_buf);
- vino->b.next_4_desc = PHYSADDR(Vino->dummy_buf);
- udelay(5);
+ vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ udelay(VINO_DESC_FETCH_DELAY);
+
vino->intr_status = 0;
- /* set threshold level */
- vino->a.fifo_thres = threshold_a;
- vino->b.fifo_thres = threshold_b;
- init_MUTEX(&Vino->input_lock);
+ vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+ vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+
+ return 0;
+}
+
+static int vino_init_channel_settings(struct vino_channel_settings *vcs,
+ unsigned int channel, const char *name)
+{
+ vcs->channel = channel;
+ vcs->input = VINO_INPUT_NONE;
+ vcs->alpha = 0;
+ vcs->users = 0;
+ vcs->data_format = VINO_DATA_FMT_GREY;
+ vcs->data_norm = VINO_DATA_NORM_NTSC;
+ vcs->decimation = 1;
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+
+ vcs->capturing = 0;
+
+ init_MUTEX(&vcs->sem);
+ spin_lock_init(&vcs->capture_lock);
+
+ init_MUTEX(&vcs->fb_queue.queue_sem);
+ spin_lock_init(&vcs->fb_queue.queue_lock);
+ init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
+
+ vcs->v4l_device = video_device_alloc();
+ if (!vcs->v4l_device) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ memcpy(vcs->v4l_device, &v4l_device_template,
+ sizeof(struct video_device));
+ strcpy(vcs->v4l_device->name, name);
+ vcs->v4l_device->release = video_device_release;
+
+ video_set_drvdata(vcs->v4l_device, vcs);
+
+ return 0;
+}
+
+static int __init vino_module_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "SGI VINO driver version %s\n",
+ VINO_MODULE_VERSION);
+
+ ret = vino_probe();
+ if (ret)
+ return ret;
+
+ ret = vino_init();
+ if (ret)
+ return ret;
+
+ /* initialize data structures */
- if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) {
- printk(KERN_ERR "VINO: irq%02d registration failed\n",
+ spin_lock_init(&vino_drvdata->vino_lock);
+ spin_lock_init(&vino_drvdata->input_lock);
+
+ ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
+ vino_v4l_device_name_a);
+ if (ret)
+ return ret;
+
+ ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
+ vino_v4l_device_name_b);
+ if (ret)
+ return ret;
+
+ /* initialize hardware and register V4L devices */
+
+ ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
+ vino_driver_description, NULL);
+ if (ret) {
+ printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
SGI_VINO_IRQ);
- ret = -EAGAIN;
- goto out_free_page;
+ vino_module_cleanup(vino_init_stage);
+ return -EAGAIN;
}
+ vino_init_stage++;
ret = vino_i2c_add_bus();
if (ret) {
- printk(KERN_ERR "VINO: I2C bus registration failed\n");
- goto out_free_irq;
+ printk(KERN_ERR "VINO I2C bus registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return ret;
}
+ vino_init_stage++;
- if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) {
- printk("%s, chnl %d: device registration failed.\n",
- Vino->chA.vdev.name, Vino->chA.chan);
- ret = -EINVAL;
- goto out_i2c_del_bus;
+ ret = video_register_device(vino_drvdata->a.v4l_device,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel A Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
}
- if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) {
- printk("%s, chnl %d: device registration failed.\n",
- Vino->chB.vdev.name, Vino->chB.chan);
- ret = -EINVAL;
- goto out_unregister_vdev;
+ vino_init_stage++;
+
+ ret = video_register_device(vino_drvdata->b.v4l_device,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel B Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
}
+ vino_init_stage++;
- return 0;
+#if defined(CONFIG_KMOD) && defined(MODULE)
+ request_module("saa7191");
+ request_module("indycam");
+#endif
-out_unregister_vdev:
- video_unregister_device(&Vino->chA.vdev);
-out_i2c_del_bus:
- vino_i2c_del_bus();
-out_free_irq:
- free_irq(SGI_VINO_IRQ, NULL);
-out_free_page:
- free_page(Vino->dummy_page);
-out_free_vino:
- kfree(Vino);
-out_unmap:
- iounmap(vino);
+ dprintk("init complete!\n");
- return ret;
+ return 0;
}
-static void __exit vino_exit(void)
+static void __exit vino_module_exit(void)
{
- video_unregister_device(&Vino->chA.vdev);
- video_unregister_device(&Vino->chB.vdev);
- vino_i2c_del_bus();
- free_irq(SGI_VINO_IRQ, NULL);
- free_page(Vino->dummy_page);
- kfree(Vino);
- iounmap(vino);
+ dprintk("exiting, stage = %d ...\n", vino_init_stage);
+ vino_module_cleanup(vino_init_stage);
+ dprintk("cleanup complete, exit!\n");
}
-module_init(vino_init);
-module_exit(vino_exit);
-
-MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)");
-MODULE_LICENSE("GPL");
+module_init(vino_module_init);
+module_exit(vino_module_exit);
diff --git a/drivers/media/video/vino.h b/drivers/media/video/vino.h
index d2fce472f35a..de2d615ae7c9 100644
--- a/drivers/media/video/vino.h
+++ b/drivers/media/video/vino.h
@@ -1,13 +1,19 @@
/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
* Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
* Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
*/
-#ifndef VINO_H
-#define VINO_H
+#ifndef _VINO_H_
+#define _VINO_H_
#define VINO_BASE 0x00080000 /* Vino is in the EISA address space,
* but it is not an EISA bus card */
+#define VINO_PAGE_SIZE 4096
struct sgi_vino_channel {
u32 _pad_alpha;
@@ -21,8 +27,9 @@ struct sgi_vino_channel {
u32 _pad_clip_end;
volatile u32 clip_end;
+#define VINO_FRAMERT_FULL 0xfff
#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */
-#define VINO_FRAMERT_RT(x) (((x) & 0x1fff) << 1) /* bits 1:12 */
+#define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */
u32 _pad_frame_rate;
volatile u32 frame_rate;
@@ -67,18 +74,18 @@ struct sgi_vino {
volatile u32 rev_id;
#define VINO_CTRL_LITTLE_ENDIAN (1<<0)
-#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */
-#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */
-#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */
-#define VINO_CTRL_A_INT (VINO_CTRL_A_FIELD_TRANS_INT | \
- VINO_CTRL_A_FIFO_OF_INT | \
- VINO_CTRL_A_END_DESC_TBL_INT)
-#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */
-#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */
-#define VINO_CTRL_B_END_DESC_TBL_INT (1<<6) /* End of desc table int */
-#define VINO_CTRL_B_INT (VINO_CTRL_B_FIELD_TRANS_INT | \
- VINO_CTRL_B_FIFO_OF_INT | \
- VINO_CTRL_B_END_DESC_TBL_INT)
+#define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */
+#define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */
+#define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */
+#define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \
+ VINO_CTRL_A_FIFO_INT | \
+ VINO_CTRL_A_EOD_INT)
+#define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */
+#define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */
+#define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */
+#define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \
+ VINO_CTRL_B_FIFO_INT | \
+ VINO_CTRL_B_EOD_INT)
#define VINO_CTRL_A_DMA_ENBL (1<<7)
#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8)
#define VINO_CTRL_A_SYNC_ENBL (1<<9)
@@ -104,18 +111,18 @@ struct sgi_vino {
u32 _pad_control;
volatile u32 control;
-#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */
-#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */
-#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */
-#define VINO_INTSTAT_A (VINO_INTSTAT_A_FIELD_TRANS | \
- VINO_INTSTAT_A_FIFO_OF | \
- VINO_INTSTAT_A_END_DESC_TBL)
-#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */
-#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */
-#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */
-#define VINO_INTSTAT_B (VINO_INTSTAT_B_FIELD_TRANS | \
- VINO_INTSTAT_B_FIFO_OF | \
- VINO_INTSTAT_B_END_DESC_TBL)
+#define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */
+#define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */
+#define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */
+#define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \
+ VINO_INTSTAT_A_FIFO | \
+ VINO_INTSTAT_A_EOD)
+#define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */
+#define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */
+#define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */
+#define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \
+ VINO_INTSTAT_B_FIFO | \
+ VINO_INTSTAT_B_EOD)
u32 _pad_intr_status;
volatile u32 intr_status;
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 5dbd9f6bf353..4437bdebe24f 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -576,7 +576,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver vpx3220_i2c_driver;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 25743085b2d5..eed2acea1779 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -737,7 +737,7 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
};
static struct i2c_adapter zoran_i2c_adapter_template = {
- I2C_DEVNAME("zr36057"),
+ .name = "zr36057",
.id = I2C_HW_B_ZR36067,
.algo = NULL,
.client_register = zoran_i2c_client_register,
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index ba838a42ec80..53adeb70f2ca 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -650,7 +650,7 @@ jpg_fbuffer_free (struct file *file)
off += PAGE_SIZE)
ClearPageReserved(MAP_NR
(mem + off));
- kfree((void *) mem);
+ kfree(mem);
fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
}
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index c33533155cc7..07286816d7df 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -820,11 +820,9 @@ void zoran_close(struct video_device* dev)
msleep(100); /* Wait 1/10th of a second */
/* free the allocated framebuffer */
- if (ztv->fbuffer)
- bfree( ztv->fbuffer, ZORAN_MAX_FBUFSIZE );
+ bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
ztv->fbuffer = 0;
- if (ztv->overinfo.overlay)
- kfree( ztv->overinfo.overlay );
+ kfree(ztv->overinfo.overlay);
ztv->overinfo.overlay = 0;
}
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 9f98334e5076..b61e3d175070 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.07
+ * mpi.h Version: 01.05.08
*
* Version History
* ---------------
@@ -71,6 +71,9 @@
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
+ * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Added EEDP IOCStatus codes.
* --------------------------------------------------------------------------
*/
@@ -101,7 +104,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x09)
+#define MPI_HEADER_VERSION_UNIT (0x0A)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -292,10 +295,13 @@
#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D)
#define MPI_FUNCTION_DIAG_RELEASE (0x1E)
+#define MPI_FUNCTION_SCSI_IO_32 (0x1F)
+
#define MPI_FUNCTION_LAN_SEND (0x20)
#define MPI_FUNCTION_LAN_RECEIVE (0x21)
#define MPI_FUNCTION_LAN_RESET (0x22)
+#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED (0x23)
#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24)
#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25)
@@ -681,6 +687,15 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
/****************************************************************************/
+/* For use by SCSI Initiator and SCSI Target end-to-end data protection */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
+#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
+#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
+
+
+/****************************************************************************/
/* SCSI Target values */
/****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 15b12b06799d..d8339896f734 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.08
+ * mpi_cnfg.h Version: 01.05.09
*
* Version History
* ---------------
@@ -232,6 +232,23 @@
* New physical mapping mode in SAS IO Unit Page 2.
* Added CONFIG_PAGE_SAS_ENCLOSURE_0.
* Added Slot and Enclosure fields to SAS Device Page 0.
+ * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1.
+ * Added more RAID type defines to IOC Page 2.
+ * Added Port Enable Delay settings to BIOS Page 1.
+ * Added Bad Block Table Full define to RAID Volume Page 0.
+ * Added Previous State defines to RAID Physical Disk
+ * Page 0.
+ * Added Max Sata Targets define for DiscoveryStatus field
+ * of SAS IO Unit Page 0.
+ * Added Device Self Test to Control Flags of SAS IO Unit
+ * Page 1.
+ * Added Direct Attach Starting Slot Number define for SAS
+ * IO Unit Page 2.
+ * Added new fields in SAS Device Page 2 for enclosure
+ * mapping.
+ * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ * Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
* --------------------------------------------------------------------------
*/
@@ -477,6 +494,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626)
#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642)
#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -769,9 +787,13 @@ typedef struct _CONFIG_PAGE_IOC_1
} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
IOCPage1_t, MPI_POINTER pIOCPage1_t;
-#define MPI_IOCPAGE1_PAGEVERSION (0x02)
+#define MPI_IOCPAGE1_PAGEVERSION (0x03)
/* defines for the Flags field */
+#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000)
+#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000)
+#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000)
+#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000)
#define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010)
#define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001)
@@ -795,6 +817,11 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL
#define MPI_RAID_VOL_TYPE_IS (0x00)
#define MPI_RAID_VOL_TYPE_IME (0x01)
#define MPI_RAID_VOL_TYPE_IM (0x02)
+#define MPI_RAID_VOL_TYPE_RAID_5 (0x03)
+#define MPI_RAID_VOL_TYPE_RAID_6 (0x04)
+#define MPI_RAID_VOL_TYPE_RAID_10 (0x05)
+#define MPI_RAID_VOL_TYPE_RAID_50 (0x06)
+#define MPI_RAID_VOL_TYPE_UNKNOWN (0xFF)
/* IOC Page 2 Volume Flags values */
@@ -820,13 +847,17 @@ typedef struct _CONFIG_PAGE_IOC_2
} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
IOCPage2_t, MPI_POINTER pIOCPage2_t;
-#define MPI_IOCPAGE2_PAGEVERSION (0x02)
+#define MPI_IOCPAGE2_PAGEVERSION (0x03)
/* IOC Page 2 Capabilities flags */
#define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT (0x00000001)
#define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT (0x00000002)
#define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT (0x00000004)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT (0x00000008)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT (0x00000010)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT (0x00000020)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT (0x00000040)
#define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000)
#define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000)
#define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000)
@@ -945,7 +976,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
-#define MPI_BIOSPAGE1_PAGEVERSION (0x01)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x02)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -954,6 +985,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1167,6 +1200,7 @@ typedef struct _CONFIG_PAGE_BIOS_2
#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03)
#define MPI_BIOSPAGE2_FORM_FC_WWN (0x04)
#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05)
+#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
/****************************************************************************
@@ -1957,11 +1991,11 @@ typedef struct _RAID_VOL0_STATUS
RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t;
/* RAID Volume Page 0 VolumeStatus defines */
-
#define MPI_RAIDVOL0_STATUS_FLAG_ENABLED (0x01)
#define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED (0x02)
#define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x04)
#define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x08)
+#define MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x10)
#define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00)
#define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01)
@@ -2025,7 +2059,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
-#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x04)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x05)
/* values for RAID Volume Page 0 InactiveStatus field */
#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
@@ -2104,6 +2138,8 @@ typedef struct _RAID_PHYS_DISK0_STATUS
#define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01)
#define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02)
#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04)
+#define MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00)
+#define MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x08)
#define MPI_PHYSDISK0_STATUS_ONLINE (0x00)
#define MPI_PHYSDISK0_STATUS_MISSING (0x01)
@@ -2132,7 +2168,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0
} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t;
-#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x01)
+#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x02)
typedef struct _RAID_PHYS_DISK1_PATH
@@ -2263,7 +2299,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
-#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x02)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x03)
/* values for SAS IO Unit Page 0 PortFlags */
#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08)
@@ -2299,6 +2335,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
#define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400)
#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
+#define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS (0x00001000)
typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
@@ -2336,6 +2373,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04)
/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
@@ -2345,9 +2383,8 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x10)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02)
-#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
@@ -2390,7 +2427,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
-#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x03)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2406,6 +2443,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
+#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
@@ -2584,11 +2622,19 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U64 PhysicalIdentifier; /* 08h */
- U32 Reserved1; /* 10h */
+ U32 EnclosureMapping; /* 10h */
} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2,
SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t;
-#define MPI_SASDEVICE2_PAGEVERSION (0x00)
+#define MPI_SASDEVICE2_PAGEVERSION (0x01)
+
+/* defines for SAS Device Page 2 EnclosureMapping field */
+#define MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT (0x0000000F)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_MISSING_COUNT (0)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS (0x000007F0)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS (4)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_START_INDEX (0x001FF800)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX (11)
/****************************************************************************
@@ -2598,7 +2644,8 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
typedef struct _CONFIG_PAGE_SAS_PHY_0
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U16 OwnerDevHandle; /* 08h */
+ U16 Reserved1; /* 0Ah */
U64 SASAddress; /* 0Ch */
U16 AttachedDevHandle; /* 14h */
U8 AttachedPhyIdentifier; /* 16h */
@@ -2607,12 +2654,12 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
U8 ProgrammedLinkRate; /* 20h */
U8 HwLinkRate; /* 21h */
U8 ChangeCount; /* 22h */
- U8 Reserved3; /* 23h */
+ U8 Flags; /* 23h */
U32 PhyInfo; /* 24h */
} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
-#define MPI_SASPHY0_PAGEVERSION (0x00)
+#define MPI_SASPHY0_PAGEVERSION (0x01)
/* values for SAS PHY Page 0 ProgrammedLinkRate field */
#define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK (0xF0)
@@ -2632,6 +2679,9 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
#define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5 (0x08)
#define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0 (0x09)
+/* values for SAS PHY Page 0 Flags field */
+#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
+
/* values for SAS PHY Page 0 PhyInfo field */
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000)
@@ -2690,7 +2740,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0,
SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t;
-#define MPI_SASENCLOSURE0_PAGEVERSION (0x00)
+#define MPI_SASENCLOSURE0_PAGEVERSION (0x01)
/* values for SAS Enclosure Page 0 Flags field */
#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020)
@@ -2702,6 +2752,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
/****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index c9edbee41edf..1a30ef16adb4 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,17 +6,17 @@
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.09
+ Header Set Release Version: 01.05.10
Header Set Release Date: 03-11-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.07 01.05.06
- mpi_ioc.h 01.05.08 01.05.07
- mpi_cnfg.h 01.05.08 01.05.07
- mpi_init.h 01.05.04 01.05.03
- mpi_targ.h 01.05.04 01.05.03
+ mpi.h 01.05.08 01.05.07
+ mpi_ioc.h 01.05.09 01.05.08
+ mpi_cnfg.h 01.05.09 01.05.08
+ mpi_init.h 01.05.05 01.05.04
+ mpi_targ.h 01.05.05 01.05.04
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02
@@ -24,7 +24,7 @@
mpi_inb.h 01.05.01 01.05.01
mpi_sas.h 01.05.01 01.05.01
mpi_type.h 01.05.01 01.05.01
- mpi_history.txt 01.05.09 01.05.08
+ mpi_history.txt 01.05.09 01.05.09
* Date Version Description
@@ -88,6 +88,9 @@ mpi.h
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
+ * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Added EEDP IOCStatus codes.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -159,6 +162,8 @@ mpi_ioc.h
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
+ * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
+ * Added Max SATA Targets to SAS Discovery Error event.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -380,6 +385,23 @@ mpi_cnfg.h
* New physical mapping mode in SAS IO Unit Page 2.
* Added CONFIG_PAGE_SAS_ENCLOSURE_0.
* Added Slot and Enclosure fields to SAS Device Page 0.
+ * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1.
+ * Added more RAID type defines to IOC Page 2.
+ * Added Port Enable Delay settings to BIOS Page 1.
+ * Added Bad Block Table Full define to RAID Volume Page 0.
+ * Added Previous State defines to RAID Physical Disk
+ * Page 0.
+ * Added Max Sata Targets define for DiscoveryStatus field
+ * of SAS IO Unit Page 0.
+ * Added Device Self Test to Control Flags of SAS IO Unit
+ * Page 1.
+ * Added Direct Attach Starting Slot Number define for SAS
+ * IO Unit Page 2.
+ * Added new fields in SAS Device Page 2 for enclosure
+ * mapping.
+ * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ * Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
* --------------------------------------------------------------------------
mpi_init.h
@@ -418,6 +440,8 @@ mpi_init.h
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
+ * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
+ * Added four new defines for SEP SlotStatus.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -461,6 +485,7 @@ mpi_targ.h
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
+ * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
* --------------------------------------------------------------------------
mpi_fc.h
@@ -571,20 +596,20 @@ mpi_type.h
mpi_history.txt Parts list history
-Filename 01.05.09
----------- --------
-mpi.h 01.05.07
-mpi_ioc.h 01.05.08
-mpi_cnfg.h 01.05.08
-mpi_init.h 01.05.04
-mpi_targ.h 01.05.04
-mpi_fc.h 01.05.01
-mpi_lan.h 01.05.01
-mpi_raid.h 01.05.02
-mpi_tool.h 01.05.03
-mpi_inb.h 01.05.01
-mpi_sas.h 01.05.01
-mpi_type.h 01.05.01
+Filename 01.05.10 01.05.09
+---------- -------- --------
+mpi.h 01.05.08 01.05.07
+mpi_ioc.h 01.05.09 01.05.08
+mpi_cnfg.h 01.05.09 01.05.08
+mpi_init.h 01.05.05 01.05.04
+mpi_targ.h 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01
+mpi_sas.h 01.05.01 01.05.01
+mpi_type.h 01.05.01 01.05.01
Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index aca035801a86..d5af75afbd94 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.04
+ * mpi_init.h Version: 01.05.05
*
* Version History
* ---------------
@@ -48,6 +48,8 @@
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
+ * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
+ * Added four new defines for SEP SlotStatus.
* --------------------------------------------------------------------------
*/
@@ -203,6 +205,197 @@ typedef struct _MSG_SCSI_IO_REPLY
/****************************************************************************/
+/* SCSI IO 32 messages and associated structures */
+/****************************************************************************/
+
+typedef struct
+{
+ U8 CDB[20]; /* 00h */
+ U32 PrimaryReferenceTag; /* 14h */
+ U16 PrimaryApplicationTag; /* 18h */
+ U16 PrimaryApplicationTagMask; /* 1Ah */
+ U32 TransferLength; /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP32, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP32,
+ MpiScsiIo32CdbEedp32_t, MPI_POINTER pMpiScsiIo32CdbEedp32_t;
+
+typedef struct
+{
+ U8 CDB[16]; /* 00h */
+ U32 DataLength; /* 10h */
+ U32 PrimaryReferenceTag; /* 14h */
+ U16 PrimaryApplicationTag; /* 18h */
+ U16 PrimaryApplicationTagMask; /* 1Ah */
+ U32 TransferLength; /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP16, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP16,
+ MpiScsiIo32CdbEedp16_t, MPI_POINTER pMpiScsiIo32CdbEedp16_t;
+
+typedef union
+{
+ U8 CDB32[32];
+ MPI_SCSI_IO32_CDB_EEDP32 EEDP32;
+ MPI_SCSI_IO32_CDB_EEDP16 EEDP16;
+ SGE_SIMPLE_UNION SGE;
+} MPI_SCSI_IO32_CDB_UNION, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_UNION,
+ MpiScsiIo32Cdb_t, MPI_POINTER pMpiScsiIo32Cdb_t;
+
+typedef struct
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U16 Reserved1; /* 02h */
+ U32 Reserved2; /* 04h */
+} MPI_SCSI_IO32_BUS_TARGET_ID_FORM, MPI_POINTER PTR_MPI_SCSI_IO32_BUS_TARGET_ID_FORM,
+ MpiScsiIo32BusTargetIdForm_t, MPI_POINTER pMpiScsiIo32BusTargetIdForm_t;
+
+typedef union
+{
+ MPI_SCSI_IO32_BUS_TARGET_ID_FORM SCSIID;
+ U64 WWID;
+} MPI_SCSI_IO32_ADDRESS, MPI_POINTER PTR_MPI_SCSI_IO32_ADDRESS,
+ MpiScsiIo32Address_t, MPI_POINTER pMpiScsiIo32Address_t;
+
+typedef struct _MSG_SCSI_IO32_REQUEST
+{
+ U8 Port; /* 00h */
+ U8 Reserved1; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U8 CDBLength; /* 04h */
+ U8 SenseBufferLength; /* 05h */
+ U8 Flags; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 LUN[8]; /* 0Ch */
+ U32 Control; /* 14h */
+ MPI_SCSI_IO32_CDB_UNION CDB; /* 18h */
+ U32 DataLength; /* 38h */
+ U32 BidirectionalDataLength; /* 3Ch */
+ U32 SecondaryReferenceTag; /* 40h */
+ U16 SecondaryApplicationTag; /* 44h */
+ U16 Reserved2; /* 46h */
+ U16 EEDPFlags; /* 48h */
+ U16 ApplicationTagTranslationMask; /* 4Ah */
+ U32 EEDPBlockSize; /* 4Ch */
+ MPI_SCSI_IO32_ADDRESS DeviceAddress; /* 50h */
+ U8 SGLOffset0; /* 58h */
+ U8 SGLOffset1; /* 59h */
+ U8 SGLOffset2; /* 5Ah */
+ U8 SGLOffset3; /* 5Bh */
+ U32 Reserved3; /* 5Ch */
+ U32 Reserved4; /* 60h */
+ U32 SenseBufferLowAddr; /* 64h */
+ SGE_IO_UNION SGL; /* 68h */
+} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
+ SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
+
+/* SCSI IO 32 MsgFlags bits */
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01)
+
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_IOC (0x02)
+
+#define MPI_SCSIIO32_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
+#define MPI_SCSIIO32_MSGFLGS_SGL_OFFSETS_CHAINS (0x08)
+#define MPI_SCSIIO32_MSGFLGS_MULTICAST (0x10)
+#define MPI_SCSIIO32_MSGFLGS_BIDIRECTIONAL (0x20)
+#define MPI_SCSIIO32_MSGFLGS_LARGE_CDB (0x40)
+
+/* SCSI IO 32 Flags bits */
+#define MPI_SCSIIO32_FLAGS_FORM_MASK (0x03)
+#define MPI_SCSIIO32_FLAGS_FORM_SCSIID (0x00)
+#define MPI_SCSIIO32_FLAGS_FORM_WWID (0x01)
+
+/* SCSI IO 32 LUN fields */
+#define MPI_SCSIIO32_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_LEVEL_1_WORD (0xFF00)
+#define MPI_SCSIIO32_LUN_LEVEL_1_DWORD (0x0000FF00)
+
+/* SCSI IO 32 Control bits */
+#define MPI_SCSIIO32_CONTROL_DATADIRECTION_MASK (0x03000000)
+#define MPI_SCSIIO32_CONTROL_NODATATRANSFER (0x00000000)
+#define MPI_SCSIIO32_CONTROL_WRITE (0x01000000)
+#define MPI_SCSIIO32_CONTROL_READ (0x02000000)
+#define MPI_SCSIIO32_CONTROL_BIDIRECTIONAL (0x03000000)
+
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_MASK (0xFC000000)
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_SHIFT (26)
+
+#define MPI_SCSIIO32_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
+#define MPI_SCSIIO32_CONTROL_SIMPLEQ (0x00000000)
+#define MPI_SCSIIO32_CONTROL_HEADOFQ (0x00000100)
+#define MPI_SCSIIO32_CONTROL_ORDEREDQ (0x00000200)
+#define MPI_SCSIIO32_CONTROL_ACAQ (0x00000400)
+#define MPI_SCSIIO32_CONTROL_UNTAGGED (0x00000500)
+#define MPI_SCSIIO32_CONTROL_NO_DISCONNECT (0x00000700)
+
+#define MPI_SCSIIO32_CONTROL_TASKMANAGE_MASK (0x00FF0000)
+#define MPI_SCSIIO32_CONTROL_OBSOLETE (0x00800000)
+#define MPI_SCSIIO32_CONTROL_CLEAR_ACA_RSV (0x00400000)
+#define MPI_SCSIIO32_CONTROL_TARGET_RESET (0x00200000)
+#define MPI_SCSIIO32_CONTROL_LUN_RESET_RSV (0x00100000)
+#define MPI_SCSIIO32_CONTROL_RESERVED (0x00080000)
+#define MPI_SCSIIO32_CONTROL_CLR_TASK_SET_RSV (0x00040000)
+#define MPI_SCSIIO32_CONTROL_ABORT_TASK_SET (0x00020000)
+#define MPI_SCSIIO32_CONTROL_RESERVED2 (0x00010000)
+
+/* SCSI IO 32 EEDPFlags */
+#define MPI_SCSIIO32_EEDPFLAGS_MASK_OP (0x0007)
+#define MPI_SCSIIO32_EEDPFLAGS_NOOP_OP (0x0000)
+#define MPI_SCSIIO32_EEDPFLAGS_CHK_OP (0x0001)
+#define MPI_SCSIIO32_EEDPFLAGS_STRIP_OP (0x0002)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP (0x0003)
+#define MPI_SCSIIO32_EEDPFLAGS_INSERT_OP (0x0004)
+#define MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP (0x0006)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP (0x0007)
+
+#define MPI_SCSIIO32_EEDPFLAGS_PASS_REF_TAG (0x0008)
+#define MPI_SCSIIO32_EEDPFLAGS_8_9THS_MODE (0x0010)
+
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_MASK (0x0700)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD (0x0100)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG (0x0200)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG (0x0400)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_SHIFT (8)
+
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
+
+
+/* SCSIIO32 IO reply structure */
+typedef struct _MSG_SCSIIO32_IO_REPLY
+{
+ U8 Port; /* 00h */
+ U8 Reserved1; /* 01h */
+ U8 MsgLength; /* 02h */
+ U8 Function; /* 03h */
+ U8 CDBLength; /* 04h */
+ U8 SenseBufferLength; /* 05h */
+ U8 Flags; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 SCSIStatus; /* 0Ch */
+ U8 SCSIState; /* 0Dh */
+ U16 IOCStatus; /* 0Eh */
+ U32 IOCLogInfo; /* 10h */
+ U32 TransferCount; /* 14h */
+ U32 SenseCount; /* 18h */
+ U32 ResponseInfo; /* 1Ch */
+ U16 TaskTag; /* 20h */
+ U16 Reserved2; /* 22h */
+ U32 BidirectionalTransferCount; /* 24h */
+} MSG_SCSIIO32_IO_REPLY, MPI_POINTER PTR_MSG_SCSIIO32_IO_REPLY,
+ SCSIIO32Reply_t, MPI_POINTER pSCSIIO32Reply_t;
+
+
+/****************************************************************************/
/* SCSI Task Management messages */
/****************************************************************************/
@@ -310,10 +503,14 @@ typedef struct _MSG_SEP_REQUEST
#define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
#define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
#define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_CONSISTENCY_CHECK (0x00001000)
+#define MPI_SEP_REQ_SLOTSTATUS_DISABLE (0x00002000)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_RESERVED_DEVICE (0x00004000)
#define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT (0x00080000)
#define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE (0x00400000)
+#define MPI_SEP_REQ_SLOTSTATUS_ACTIVE (0x00800000)
#define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000)
#define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000)
#define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF (0x10000000)
@@ -352,11 +549,15 @@ typedef struct _MSG_SEP_REPLY
#define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
#define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
#define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI_SEP_REPLY_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000)
+#define MPI_SEP_REPLY_SLOTSTATUS_DISABLE (0x00002000)
+#define MPI_SEP_REPLY_SLOTSTATUS_RESERVED_DEVICE (0x00004000)
#define MPI_SEP_REPLY_SLOTSTATUS_REPORT (0x00010000)
#define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
#define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY (0x00080000)
#define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE (0x00400000)
+#define MPI_SEP_REPLY_SLOTSTATUS_ACTIVE (0x00800000)
#define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED (0x01000000)
#define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED (0x02000000)
#define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index f91eb4efe8cc..93b70e2b4266 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.08
+ * mpi_ioc.h Version: 01.05.09
*
* Version History
* ---------------
@@ -81,6 +81,8 @@
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
+ * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
+ * Added Max SATA Targets to SAS Discovery Error event.
* --------------------------------------------------------------------------
*/
@@ -261,7 +263,11 @@ typedef struct _MSG_IOC_FACTS_REPLY
#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
-
+#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040)
+#define MPI_IOCFACTS_CAPABILITY_BIDIRECTIONAL (0x00000080)
+#define MPI_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
+#define MPI_IOCFACTS_CAPABILITY_SCSIIO32 (0x00000200)
+#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16 (0x00000400)
/*****************************************************************************
@@ -677,6 +683,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200)
#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800)
+#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000)
/*****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
index 623901fd82be..3f462859ceea 100644
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -6,7 +6,7 @@
* Title: MPI Target mode messages and structures
* Creation Date: June 22, 2000
*
- * mpi_targ.h Version: 01.05.04
+ * mpi_targ.h Version: 01.05.05
*
* Version History
* ---------------
@@ -53,6 +53,7 @@
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
+ * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
* --------------------------------------------------------------------------
*/
@@ -371,6 +372,77 @@ typedef struct _MSG_TARGET_ERROR_REPLY
/****************************************************************************/
+/* Target Assist Extended Request */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_ASSIST_EXT_REQUEST
+{
+ U8 StatusCode; /* 00h */
+ U8 TargetAssistFlags; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 QueueTag; /* 04h */
+ U8 Reserved1; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U32 ReplyWord; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 RelativeOffset; /* 18h */
+ U32 Reserved2; /* 1Ch */
+ U32 Reserved3; /* 20h */
+ U32 PrimaryReferenceTag; /* 24h */
+ U16 PrimaryApplicationTag; /* 28h */
+ U16 PrimaryApplicationTagMask; /* 2Ah */
+ U32 Reserved4; /* 2Ch */
+ U32 DataLength; /* 30h */
+ U32 BidirectionalDataLength; /* 34h */
+ U32 SecondaryReferenceTag; /* 38h */
+ U16 SecondaryApplicationTag; /* 3Ch */
+ U16 Reserved5; /* 3Eh */
+ U16 EEDPFlags; /* 40h */
+ U16 ApplicationTagTranslationMask; /* 42h */
+ U32 EEDPBlockSize; /* 44h */
+ U8 SGLOffset0; /* 48h */
+ U8 SGLOffset1; /* 49h */
+ U8 SGLOffset2; /* 4Ah */
+ U8 SGLOffset3; /* 4Bh */
+ U32 Reserved6; /* 4Ch */
+ SGE_IO_UNION SGL[1]; /* 50h */
+} MSG_TARGET_ASSIST_EXT_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_EXT_REQUEST,
+ TargetAssistExtRequest_t, MPI_POINTER pTargetAssistExtRequest_t;
+
+/* see the defines after MSG_TARGET_ASSIST_REQUEST for TargetAssistFlags */
+
+/* defines for the MsgFlags field */
+#define TARGET_ASSIST_EXT_MSGFLAGS_BIDIRECTIONAL (0x20)
+#define TARGET_ASSIST_EXT_MSGFLAGS_MULTICAST (0x10)
+#define TARGET_ASSIST_EXT_MSGFLAGS_SGL_OFFSET_CHAINS (0x08)
+
+/* defines for the EEDPFlags field */
+#define TARGET_ASSIST_EXT_EEDP_MASK_OP (0x0007)
+#define TARGET_ASSIST_EXT_EEDP_NOOP_OP (0x0000)
+#define TARGET_ASSIST_EXT_EEDP_CHK_OP (0x0001)
+#define TARGET_ASSIST_EXT_EEDP_STRIP_OP (0x0002)
+#define TARGET_ASSIST_EXT_EEDP_CHKRM_OP (0x0003)
+#define TARGET_ASSIST_EXT_EEDP_INSERT_OP (0x0004)
+#define TARGET_ASSIST_EXT_EEDP_REPLACE_OP (0x0006)
+#define TARGET_ASSIST_EXT_EEDP_CHKREGEN_OP (0x0007)
+
+#define TARGET_ASSIST_EXT_EEDP_PASS_REF_TAG (0x0008)
+
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_MASK (0x0700)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_GUARD (0x0100)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_APPTAG (0x0200)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_REFTAG (0x0400)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_SHIFT (8)
+
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_APPTAG (0x1000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_APPTAG (0x2000)
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_REFTAG (0x4000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_REFTAG (0x8000)
+
+
+/****************************************************************************/
/* Target Status Send Request */
/****************************************************************************/
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ffbe6f4720e1..f517d0692d5f 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -218,8 +218,7 @@ pci_enable_io_access(struct pci_dev *pdev)
* (also referred to as a IO Controller or IOC).
* This routine must clear the interrupt from the adapter and does
* so by reading the reply FIFO. Multiple replies may be processed
- * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
- * which is currently set to 32 in mptbase.h.
+ * per single call to this routine.
*
* This routine handles register-level access of the adapter but
* dispatches (calls) a protocol-specific callback routine to handle
@@ -279,11 +278,11 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
- dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
- ioc->name, mr, req_idx));
+ dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+ ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
DBG_DUMP_REPLY_FRAME(mr)
- /* Check/log IOC log info
+ /* Check/log IOC log info
*/
ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
@@ -345,7 +344,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
|| (mf < ioc->req_frames)) ) {
printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
+ "mpt_interrupt: Invalid mf (%p)!\n", ioc->name, (void *)mf);
cb_idx = 0;
pa = 0;
freeme = 0;
@@ -399,7 +398,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
* @mf: Pointer to original MPT request frame
* @reply: Pointer to MPT reply frame (NULL if TurboReply)
*
- * Returns 1 indicating original alloc'd request frame ptr
+ * Returns 1 indicating original alloc'd request frame ptr
* should be freed, or 0 if it shouldn't.
*/
static int
@@ -408,28 +407,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
int freereq = 1;
u8 func;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
-
- if ((mf == NULL) ||
- (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
- printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
- ioc->name, (void *)mf);
- return 1;
- }
-
- if (reply == NULL) {
- dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
- ioc->name));
- return 1;
- }
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
+#if defined(MPT_DEBUG_MSG_FRAME)
if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
DBG_DUMP_REQUEST_FRAME_HDR(mf)
}
+#endif
func = reply->u.hdr.Function;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
ioc->name, func));
if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
@@ -448,8 +436,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
* Hmmm... It seems that EventNotificationReply is an exception
* to the rule of one reply per request.
*/
- if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
freereq = 0;
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+ ioc->name, pEvReply));
+ } else {
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+ ioc->name, pEvReply));
+ }
#ifdef CONFIG_PROC_FS
// LogEvent(ioc, pEvReply);
@@ -491,10 +485,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
pCfg->status = status;
if (status == MPI_IOCSTATUS_SUCCESS) {
- pCfg->hdr->PageVersion = pReply->Header.PageVersion;
- pCfg->hdr->PageLength = pReply->Header.PageLength;
- pCfg->hdr->PageNumber = pReply->Header.PageNumber;
- pCfg->hdr->PageType = pReply->Header.PageType;
+ if ((pReply->Header.PageType &
+ MPI_CONFIG_PAGETYPE_MASK) ==
+ MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pCfg->cfghdr.ehdr->ExtPageLength =
+ le16_to_cpu(pReply->ExtPageLength);
+ pCfg->cfghdr.ehdr->ExtPageType =
+ pReply->ExtPageType;
+ }
+ pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+
+ /* If this is a regular header, save PageLength. */
+ /* LMP Do this better so not using a reserved field! */
+ pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+ pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+ pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
}
}
@@ -705,7 +710,7 @@ mpt_device_driver_deregister(int cb_idx)
if (dd_cbfunc->remove)
dd_cbfunc->remove(ioc->pcidev);
}
-
+
MptDeviceDriverHandlers[cb_idx] = NULL;
}
@@ -818,7 +823,7 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
}
#endif
- mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
+ mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
}
@@ -920,7 +925,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
/* Make sure there are no doorbells */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
+
CHIPREG_WRITE32(&ioc->chip->Doorbell,
((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
@@ -935,14 +940,14 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
return -5;
dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
- ioc->name, ii));
+ ioc->name, ii));
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
return -2;
}
-
+
/* Send request via doorbell handshake */
req_as_bytes = (u8 *) req;
for (ii = 0; ii < reqBytes/4; ii++) {
@@ -988,9 +993,9 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
if (ioc->id == iocid) {
*iocpp =ioc;
return iocid;
- }
+ }
}
-
+
*iocpp = NULL;
return -1;
}
@@ -1032,9 +1037,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_enable_device(pdev))
return r;
-
+
dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
-
+
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
@@ -1059,7 +1064,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
-
+
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
@@ -1088,7 +1093,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
ioc->id = mpt_ids++;
-
+
mem_phys = msize = 0;
port = psize = 0;
for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
@@ -1143,7 +1148,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->prod_name = "LSIFC909";
ioc->bus_type = FC;
}
- if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
ioc->prod_name = "LSIFC929";
ioc->bus_type = FC;
}
@@ -1322,7 +1327,7 @@ mpt_detach(struct pci_dev *pdev)
remove_proc_entry(pname, NULL);
sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
remove_proc_entry(pname, NULL);
-
+
/* call per device driver remove entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
@@ -1330,7 +1335,7 @@ mpt_detach(struct pci_dev *pdev)
MptDeviceDriverHandlers[ii]->remove(pdev);
}
}
-
+
/* Disable interrupts! */
CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
@@ -1403,7 +1408,7 @@ mpt_resume(struct pci_dev *pdev)
u32 device_state = pdev->current_state;
int recovery_state;
int ii;
-
+
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -1534,7 +1539,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
break;
}
-
+
if (ii == 5) {
dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1542,7 +1547,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
MptDisplayIocCapabilities(ioc);
}
-
+
if (alt_ioc_ready) {
if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1613,7 +1618,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (reset_alt_ioc_active && ioc->alt_ioc) {
/* (re)Enable alt-IOC! (reply interrupt) */
- dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
+ dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
ioc->alt_ioc->active = 1;
@@ -1670,7 +1675,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* Find IM volumes
*/
- if (ioc->facts.MsgVersion >= 0x0102)
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
mpt_findImVolumes(ioc);
/* Check, and possibly reset, the coalescing value
@@ -1700,7 +1705,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
}
if (alt_ioc_ready && MptResetHandlers[ii]) {
- dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+ 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);
handlers++;
@@ -1733,8 +1738,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
" searching for devfn match on %x or %x\n",
- ioc->name, pci_name(pdev), pdev->devfn,
- func-1, func+1));
+ ioc->name, pci_name(pdev), pdev->bus->number,
+ pdev->devfn, func-1, func+1));
peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
if (!peer) {
@@ -1861,36 +1866,39 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
static void
mpt_adapter_dispose(MPT_ADAPTER *ioc)
{
- if (ioc != NULL) {
- int sz_first, sz_last;
+ int sz_first, sz_last;
- sz_first = ioc->alloc_total;
+ if (ioc == NULL)
+ return;
- mpt_adapter_disable(ioc);
+ sz_first = ioc->alloc_total;
- if (ioc->pci_irq != -1) {
- free_irq(ioc->pci_irq, ioc);
- ioc->pci_irq = -1;
- }
+ mpt_adapter_disable(ioc);
- if (ioc->memmap != NULL)
- iounmap(ioc->memmap);
+ if (ioc->pci_irq != -1) {
+ free_irq(ioc->pci_irq, ioc);
+ ioc->pci_irq = -1;
+ }
+
+ if (ioc->memmap != NULL) {
+ iounmap(ioc->memmap);
+ ioc->memmap = NULL;
+ }
#if defined(CONFIG_MTRR) && 0
- if (ioc->mtrr_reg > 0) {
- mtrr_del(ioc->mtrr_reg, 0, 0);
- dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
- }
+ if (ioc->mtrr_reg > 0) {
+ mtrr_del(ioc->mtrr_reg, 0, 0);
+ dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+ }
#endif
- /* Zap the adapter lookup ptr! */
- list_del(&ioc->list);
+ /* Zap the adapter lookup ptr! */
+ list_del(&ioc->list);
- sz_last = ioc->alloc_total;
- dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
- ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
- kfree(ioc);
- }
+ sz_last = ioc->alloc_total;
+ dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+ ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+ kfree(ioc);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1977,7 +1985,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
}
/* Is it already READY? */
- if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
+ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
return 0;
/*
@@ -1995,7 +2003,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Hmmm... Did it get left operational?
*/
if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
- dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+ dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
ioc->name));
/* Check WhoInit.
@@ -2004,8 +2012,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Else, fall through to KickStart case
*/
whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
- dprintk((KERN_WARNING MYNAM
- ": whoinit 0x%x\n statefault %d force %d\n",
+ dinitprintk((KERN_INFO MYNAM
+ ": whoinit 0x%x statefault %d force %d\n",
whoinit, statefault, force));
if (whoinit == MPI_WHOINIT_PCI_PEER)
return -4;
@@ -2140,8 +2148,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
get_facts.Function = MPI_FUNCTION_IOC_FACTS;
/* Assert: All other get_facts fields are zero! */
- dinitprintk((MYIOC_s_INFO_FMT
- "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
+ dinitprintk((MYIOC_s_INFO_FMT
+ "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
ioc->name, req_sz, reply_sz));
/* No non-zero fields in the get_facts request are greater than
@@ -2174,7 +2182,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
- status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
+ status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
/* CHECKME! IOCStatus, IOCLogInfo */
facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
@@ -2221,7 +2229,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
if ( sz & 0x02 )
sz += 2;
facts->FWImageSize = sz;
-
+
if (!facts->RequestFrameSize) {
/* Something is wrong! */
printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2240,7 +2248,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
ioc->NBShiftFactor = shiftFactor;
dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
ioc->name, vv, shiftFactor, r));
-
+
if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
/*
* Set values for this IOC's request & reply frame sizes,
@@ -2261,7 +2269,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
return r;
}
} else {
- printk(MYIOC_s_ERR_FMT
+ printk(MYIOC_s_ERR_FMT
"Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
RequestFrameSize)/sizeof(u32)));
@@ -2413,9 +2421,11 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
ioc->name, &ioc_init));
-
- if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
+
+ if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
+ printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
return r;
+ }
/* YIKES! SUPER IMPORTANT!!!
* Poll IocState until _OPERATIONAL while IOC is doing
@@ -2440,7 +2450,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
state = mpt_GetIocState(ioc, 1);
count++;
}
- dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+ dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
ioc->name, count));
return r;
@@ -2529,7 +2539,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
int sz;
sz = ioc->facts.FWImageSize;
- dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
pci_free_consistent(ioc->pcidev, sz,
ioc->cached_fw, ioc->cached_fw_dma);
@@ -2573,9 +2583,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
mpt_alloc_fw_memory(ioc, sz);
- dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-
+
if (ioc->cached_fw == NULL) {
/* Major Failure.
*/
@@ -2605,14 +2615,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
- dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
+ dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
prequest, sgeoffset));
DBG_DUMP_FW_REQUEST_FRAME(prequest)
ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
- dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
+ dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
cmdStatus = -EFAULT;
if (ii == 0) {
@@ -2627,10 +2637,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
cmdStatus = 0;
}
}
- dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+ dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
ioc->name, cmdStatus));
-
+
if (cmdStatus) {
ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
@@ -2761,8 +2771,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
fwSize = (pExtImage->ImageSize + 3) >> 2;
ptrFw = (u32 *)pExtImage;
- ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
- ioc->name, fwSize*4, ptrFw, load_addr));
+ ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+ ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
while (fwSize--) {
@@ -2845,9 +2855,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
* 0 else
*
* Returns:
- * 1 - hard reset, READY
- * 0 - no reset due to History bit, READY
- * -1 - no reset due to History bit but not READY
+ * 1 - hard reset, READY
+ * 0 - no reset due to History bit, READY
+ * -1 - no reset due to History bit but not READY
* OR reset but failed to come READY
* -2 - no reset, could not enter DIAG mode
* -3 - reset but bad FW bit
@@ -2990,7 +3000,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
*
*/
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
- mdelay (1);
+ mdelay(1);
/*
* Now hit the reset bit in the Diagnostic register
@@ -3170,7 +3180,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
u32 state;
int cntdn, count;
- drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+ drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
ioc->name, reset_type));
CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
@@ -3374,6 +3384,9 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->reply_frames = (MPT_FRAME_HDR *) mem;
ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
+ dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
alloc_dma += reply_sz;
mem += reply_sz;
@@ -3382,7 +3395,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->req_frames = (MPT_FRAME_HDR *) mem;
ioc->req_frames_dma = alloc_dma;
- dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
+ dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
ioc->name, mem, (void *)(ulong)alloc_dma));
ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
@@ -3408,7 +3421,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->ChainBuffer = mem;
ioc->ChainBufferDMA = alloc_dma;
- dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
+ dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
/* Initialize the free chain Q.
@@ -3513,7 +3526,7 @@ out_fail:
*/
static int
mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
- int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+ int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
{
MPIDefaultReply_t *mptReply;
int failcnt = 0;
@@ -3588,7 +3601,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
*/
if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
failcnt++;
-
+
dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
@@ -3747,7 +3760,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
}
dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
- ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
+ ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
/*
@@ -3819,7 +3832,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -3863,7 +3876,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -3930,7 +3943,7 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -4012,7 +4025,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 2;
hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -4102,7 +4115,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 0;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4122,6 +4135,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
ioc->spi_data.minSyncFactor = MPT_ASYNC;
ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
rc = 1;
+ ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
/* Save the Port Page 0 data
*/
@@ -4131,7 +4146,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
- dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+ ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
ioc->name, pPP0->Capabilities));
}
ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
@@ -4140,6 +4155,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
ioc->spi_data.minSyncFactor = (u8) (data >> 8);
+ ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
ioc->spi_data.maxSyncOffset = 0;
ioc->spi_data.minSyncFactor = MPT_ASYNC;
@@ -4152,8 +4169,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
- if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+ if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
ioc->spi_data.minSyncFactor = MPT_ULTRA;
+ ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
+ }
}
}
if (pbuf) {
@@ -4168,7 +4188,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4236,7 +4256,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4245,8 +4265,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
header.PageVersion = 0;
header.PageLength = 0;
@@ -4255,8 +4275,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
@@ -4298,7 +4318,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4394,7 +4414,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 3;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4446,7 +4466,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 4;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4498,7 +4518,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4580,13 +4600,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
if (evnp == NULL) {
- dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+ devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
ioc->name));
return 0;
}
memset(evnp, 0, sizeof(*evnp));
- dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+ devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
evnp->ChainOffset = 0;
@@ -4610,8 +4630,10 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
EventAck_t *pAck;
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
- printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
- ioc->name);
+ printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
+ "request frame for Event=%x EventContext=%x EventData=%x!\n",
+ ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
+ le32_to_cpu(evnp->Data[0]));
return -1;
}
memset(pAck, 0, sizeof(*pAck));
@@ -4647,10 +4669,11 @@ int
mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
{
Config_t *pReq;
+ ConfigExtendedPageHeader_t *pExtHdr = NULL;
MPT_FRAME_HDR *mf;
unsigned long flags;
int ii, rc;
- u32 flagsLength;
+ int flagsLength;
int in_isr;
/* Prevent calling wait_event() (below), if caller happens
@@ -4675,16 +4698,30 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Reserved = 0;
pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_CONFIG;
+
+ /* Assume page type is not extended and clear "reserved" fields. */
pReq->ExtPageLength = 0;
pReq->ExtPageType = 0;
pReq->MsgFlags = 0;
+
for (ii=0; ii < 8; ii++)
pReq->Reserved2[ii] = 0;
- pReq->Header.PageVersion = pCfg->hdr->PageVersion;
- pReq->Header.PageLength = pCfg->hdr->PageLength;
- pReq->Header.PageNumber = pCfg->hdr->PageNumber;
- pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+ pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
+ pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
+ pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
+ pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
+ pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
+ pReq->ExtPageType = pExtHdr->ExtPageType;
+ pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+
+ /* Page Length must be treated as a reserved field for the extended header. */
+ pReq->Header.PageLength = 0;
+ }
+
pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
/* Add a SGE to the config request.
@@ -4694,12 +4731,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
else
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
- flagsLength |= pCfg->hdr->PageLength * 4;
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ flagsLength |= pExtHdr->ExtPageLength * 4;
- mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
+ }
+ else {
+ flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
+
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+ }
- dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
- ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+ mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
/* Append pCfg pointer to end of mf
*/
@@ -4789,8 +4834,8 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Reserved3 = 0;
pReq->NumAddressBytes = 0x01;
pReq->Reserved4 = 0;
- pReq->DataLength = 0x04;
- pdev = (struct pci_dev *) ioc->pcidev;
+ pReq->DataLength = cpu_to_le16(0x04);
+ pdev = ioc->pcidev;
if (pdev->devfn & 1)
pReq->DeviceAddr = 0xB2;
else
@@ -5504,6 +5549,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* If needed, send (a single) EventAck.
*/
if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+ devtprintk((MYIOC_s_WARN_FMT
+ "EventAck required\n",ioc->name));
if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
ioc->name, ii));
@@ -5584,7 +5631,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
case 0x00080000:
desc = "Outbound DMA Overrun";
break;
-
+
case 0x00090000:
desc = "Task Management";
break;
@@ -5600,7 +5647,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
case 0x000C0000:
desc = "Untagged Table Size";
break;
-
+
}
printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
@@ -5692,7 +5739,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
break;
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
- /* This error is checked in scsi_io_done(). Skip.
+ /* This error is checked in scsi_io_done(). Skip.
desc = "SCSI Data Underrun";
*/
break;
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 848fb236b175..f4827d923731 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -915,7 +915,10 @@ struct scsi_cmnd;
typedef struct _x_config_parms {
struct list_head linkage; /* linked list */
struct timer_list timer; /* timer function for this request */
- ConfigPageHeader_t *hdr;
+ union {
+ ConfigExtendedPageHeader_t *ehdr;
+ ConfigPageHeader_t *hdr;
+ } cfghdr;
dma_addr_t physAddr;
int wait_done; /* wait for this request */
u32 pageAddr; /* properly formatted */
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 05ea5944c487..7577c2417e2e 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -242,7 +242,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
/* Set the command status to GOOD if IOC Status is GOOD
* OR if SCSI I/O cmd and data underrun or recovered error.
*/
- iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+ iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocStatus == MPI_IOCSTATUS_SUCCESS)
ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
@@ -2324,7 +2324,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -2333,7 +2333,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
strncpy(karg.serial_number, " ", 24);
if (mpt_config(ioc, &cfg) == 0) {
- if (cfg.hdr->PageLength > 0) {
+ if (cfg.cfghdr.hdr->PageLength > 0) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -2479,7 +2479,7 @@ mptctl_hp_targetinfo(unsigned long arg)
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
cfg.timeout = 0;
@@ -2527,15 +2527,15 @@ mptctl_hp_targetinfo(unsigned long arg)
hdr.PageNumber = 3;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
cfg.timeout = 0;
cfg.physAddr = -1;
- if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+ if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
- data_sz = (int) cfg.hdr->PageLength * 4;
+ data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
ioc->pcidev, data_sz, &page_dma);
if (pg3_alloc) {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b9d4f78725b4..4a003dc5fde8 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -281,12 +281,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
chain_idx = offset / ioc->req_sz;
rc = SUCCESS;
- dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
- ioc->name, *retIndex, chainBuf));
+ dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
+ ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
} else {
rc = FAILED;
chain_idx = MPT_HOST_NO_CHAIN;
- dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+ dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
ioc->name));
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -432,7 +432,7 @@ nextSGEset:
*/
pReq->ChainOffset = 0;
RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
- dsgprintk((MYIOC_s_ERR_FMT
+ dsgprintk((MYIOC_s_INFO_FMT
"Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
ioc->RequestNB[req_idx] = RequestNB;
}
@@ -491,11 +491,12 @@ nextSGEset:
/* NOTE: psge points to the beginning of the chain element
* in current buffer. Get a chain buffer.
*/
- dsgprintk((MYIOC_s_INFO_FMT
- "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
- ioc->name, pReq->CDB[0], SCpnt));
- if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
+ if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
+ dfailprintk((MYIOC_s_INFO_FMT
+ "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
+ ioc->name, pReq->CDB[0], SCpnt));
return FAILED;
+ }
/* Update the tracking arrays.
* If chainSge == NULL, update ReqToChain, else ChainToChain
@@ -577,14 +578,20 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1;
}
- dmfprintk((MYIOC_s_INFO_FMT
- "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
- ioc->name, mf, mr, sc, req_idx));
-
sc->result = DID_OK << 16; /* Set default reply as OK */
pScsiReq = (SCSIIORequest_t *) mf;
pScsiReply = (SCSIIOReply_t *) mr;
+ if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
+ dmfprintk((MYIOC_s_INFO_FMT
+ "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
+ ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
+ }else{
+ dmfprintk((MYIOC_s_INFO_FMT
+ "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
+ ioc->name, mf, mr, sc, req_idx));
+ }
+
if (pScsiReply == NULL) {
/* special context reply handling */
;
@@ -658,8 +665,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
/* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status;
} else if ( xfer_cnt == 0 ) {
- /* A CRC Error causes this condition; retry */
- sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
+ /* A CRC Error causes this condition; retry */
+ sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
(CHECK_CONDITION << 1);
sc->sense_buffer[0] = 0x70;
sc->sense_buffer[2] = NO_SENSE;
@@ -668,7 +675,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
} else {
sc->result = DID_SOFT_ERROR << 16;
}
- dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+ dreplyprintk((KERN_NOTICE
+ "RESIDUAL_MISMATCH: result=%x on id=%d\n",
+ sc->result, sc->device->id));
break;
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
@@ -796,7 +805,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1;
}
-
/*
* mptscsih_flush_running_cmds - For each command found, search
* Scsi_Host instance taskQ and reply to OS.
@@ -1017,7 +1025,7 @@ mptscsih_remove(struct pci_dev *pdev)
scsi_host_put(host);
mpt_detach(pdev);
-
+
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1072,7 +1080,7 @@ mptscsih_resume(struct pci_dev *pdev)
MPT_SCSI_HOST *hd;
mpt_resume(pdev);
-
+
if(!host)
return 0;
@@ -1214,8 +1222,8 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off
int size = 0;
if (func) {
- /*
- * write is not supported
+ /*
+ * write is not supported
*/
} else {
if (start)
@@ -1535,17 +1543,17 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
*/
if (mptscsih_tm_pending_wait(hd) == FAILED) {
if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
@@ -1631,8 +1639,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
hd->ioc->name));
- //return FAILED;
- return -999;
+ return FAILED;
}
dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
hd->ioc->name, mf));
@@ -1661,9 +1668,8 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->TaskMsgContext = ctx2abort;
- dtmprintk((MYIOC_s_INFO_FMT
- "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
- hd->ioc->name, ctx2abort, type));
+ dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+ hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
@@ -1902,13 +1908,13 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
/* If we can't locate the host to reset, then we failed. */
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
- dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+ dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
"Can't locate host! (sc=%p)\n",
SCpnt ) );
return FAILED;
}
- printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
+ printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
/* If our attempts to reset the host failed, then return a failed
@@ -1924,7 +1930,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
hd->tmState = TM_STATE_NONE;
}
- dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+ dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
"Status = %s\n",
(status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
@@ -1951,8 +1957,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
if (hd->tmState == TM_STATE_NONE) {
hd->tmState = TM_STATE_IN_PROGRESS;
hd->tmPending = 1;
- status = SUCCESS;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ status = SUCCESS;
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -1980,7 +1986,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if(hd->tmPending == 0) {
status = SUCCESS;
- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -2318,10 +2324,10 @@ mptscsih_slave_configure(struct scsi_device *device)
if (pTarget == NULL) {
/* Driver doesn't know about this device.
* Kernel may generate a "Dummy Lun 0" which
- * may become a real Lun if a
+ * may become a real Lun if a
* "scsi add-single-device" command is executed
- * while the driver is active (hot-plug a
- * device). LSI Raid controllers need
+ * while the driver is active (hot-plug a
+ * device). LSI Raid controllers need
* queue_depth set to DEV_HIGH for this reason.
*/
scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
@@ -2691,7 +2697,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
* If the peripheral qualifier filter is enabled then if the target reports a 0x1
* (i.e. The targer is capable of supporting the specified peripheral device type
* on this logical unit; however, the physical device is not currently connected
- * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
+ * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
* capable of supporting a physical device on this logical unit). This is to work
* around a bug in th emid-layer in some distributions in which the mid-layer will
* continue to try to communicate to the LUN and evntually create a dummy LUN.
@@ -3194,8 +3200,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
/* Get a MF for this command.
*/
if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
- dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
- ioc->name));
+ dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
+ ioc->name));
return -EAGAIN;
}
@@ -3289,7 +3295,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
/* Get a MF for this command.
*/
if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
- dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+ dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
ioc->name));
return -EAGAIN;
}
@@ -3447,7 +3453,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
* some type of error occurred.
*/
MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
- if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
+ if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
completionCode = MPT_SCANDV_GOOD;
else
completionCode = MPT_SCANDV_SOME_ERROR;
@@ -3955,7 +3961,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
header1.PageLength = ioc->spi_data.sdp1length;
header1.PageNumber = 1;
header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -3996,9 +4002,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
"offset=0 negoFlags=%x request=%x config=%x\n",
id, flags, requested, configuration));
- pcfg1Data->RequestedParameters = le32_to_cpu(requested);
+ pcfg1Data->RequestedParameters = cpu_to_le32(requested);
pcfg1Data->Reserved = 0;
- pcfg1Data->Configuration = le32_to_cpu(configuration);
+ pcfg1Data->Configuration = cpu_to_le32(configuration);
cfg.pageAddr = (bus<<8) | id;
mpt_config(hd->ioc, &cfg);
}
@@ -4353,7 +4359,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
/* Prep cfg structure
*/
cfg.pageAddr = (bus<<8) | id;
- cfg.hdr = NULL;
+ cfg.cfghdr.hdr = NULL;
/* Prep SDP0 header
*/
@@ -4399,7 +4405,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
cfg1_dma_addr = dvbuf_dma + sz;
- /* Skip this ID? Set cfg.hdr to force config page write
+ /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
*/
{
ScsiCfgData *pspi_data = &hd->ioc->spi_data;
@@ -4417,7 +4423,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
dv.cmd = MPT_SET_MAX;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
/* Save the final negotiated settings to
* SCSI device page 1.
@@ -4483,7 +4489,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
dv.cmd = MPT_SET_MIN;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -4596,8 +4602,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
if ((pbuf1[56] & 0x02) == 0) {
pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
- "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
+ ddvprintk((MYIOC_s_NOTE_FMT
+ "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
ioc->name, id, pbuf1[56]));
}
}
@@ -4637,7 +4643,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
u32 sdp0_info;
u32 sdp0_nego;
- cfg.hdr = &header0;
+ cfg.cfghdr.hdr = &header0;
cfg.physAddr = cfg0_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
@@ -4673,7 +4679,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
if (!firstPass)
doFallback = 1;
} else {
- ddvprintk((MYIOC_s_NOTE_FMT
+ ddvprintk((MYIOC_s_NOTE_FMT
"DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
mptscsih_initTarget(hd,
@@ -4689,8 +4695,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
} else if (rc == MPT_SCANDV_ISSUE_SENSE)
doFallback = 1; /* set fallback flag */
- else if ((rc == MPT_SCANDV_DID_RESET) ||
- (rc == MPT_SCANDV_SENSE) ||
+ else if ((rc == MPT_SCANDV_DID_RESET) ||
+ (rc == MPT_SCANDV_SENSE) ||
(rc == MPT_SCANDV_FALLBACK))
doFallback = 1; /* set fallback flag */
else
@@ -4722,7 +4728,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
* 4) release
* 5) update nego parms to target struct
*/
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -5121,12 +5127,12 @@ target_done:
/* Set if cfg1_dma_addr contents is valid
*/
- if ((cfg.hdr != NULL) && (retcode == 0)){
+ if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
/* If disk, not U320, disable QAS
*/
if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
+ ddvprintk((MYIOC_s_NOTE_FMT
"noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
}
@@ -5137,7 +5143,7 @@ target_done:
* skip save of the final negotiated settings to
* SCSI device page 1.
*
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -5248,7 +5254,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
/* Update tmax values with those from Device Page 0.*/
pPage0 = (SCSIDevicePage0_t *) pPage;
if (pPage0) {
- val = cpu_to_le32(pPage0->NegotiatedParameters);
+ val = le32_to_cpu(pPage0->NegotiatedParameters);
dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
@@ -5276,12 +5282,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
dv->now.offset, &val, &configuration, dv->now.flags);
dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
- ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
+ ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
break;
@@ -5301,9 +5307,9 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
offset, &val, &configuration, negoFlags);
dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
id, width, factor, offset, negoFlags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
id, width, factor, offset, val, configuration, negoFlags));
@@ -5377,12 +5383,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
if (pPage1) {
mptscsih_setDevicePage1Flags (width, factor, offset, &val,
&configuration, dv->now.flags);
- dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
+ dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
id, width, offset, factor, dv->now.flags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index dfa8806b1e13..587d1274fd74 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -162,15 +162,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u8 *mem;
int error=0;
int r;
-
+
if ((r = mpt_attach(pdev,id)) != 0)
return r;
-
+
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptspiDoneCtx;
ioc->TaskCtx = mptspiTaskCtx;
ioc->InternalCtx = mptspiInternalCtx;
-
+
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
new file mode 100644
index 000000000000..550f29744812
--- /dev/null
+++ b/drivers/mfd/Kconfig
@@ -0,0 +1,25 @@
+#
+# Multifunction miscellaneous devices
+#
+
+menu "Multimedia Capabilities Port drivers"
+
+config MCP
+ tristate
+
+# Interface drivers
+config MCP_SA11X0
+ tristate "Support SA11x0 MCP interface"
+ depends on ARCH_SA1100
+ select MCP
+
+# Chip drivers
+config MCP_UCB1200
+ tristate "Support for UCB1200 / UCB1300"
+ depends on MCP
+
+config MCP_UCB1200_TS
+ tristate "Touchscreen interface support"
+ depends on MCP_UCB1200 && INPUT
+
+endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
new file mode 100644
index 000000000000..adb29b5368a8
--- /dev/null
+++ b/drivers/mfd/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for multifunction miscellaneous devices
+#
+
+obj-$(CONFIG_MCP) += mcp-core.o
+obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
+obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
+
+ifeq ($(CONFIG_SA1100_ASSABET),y)
+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
+endif
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
new file mode 100644
index 000000000000..c75d713c01e4
--- /dev/null
+++ b/drivers/mfd/mcp-core.c
@@ -0,0 +1,255 @@
+/*
+ * linux/drivers/mfd/mcp-core.c
+ *
+ * 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.
+ *
+ * Generic MCP (Multimedia Communications Port) layer. All MCP locking
+ * is solely held within this file.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/system.h>
+
+#include "mcp.h"
+
+#define to_mcp(d) container_of(d, struct mcp, attached_device)
+#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
+
+static int mcp_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int mcp_bus_probe(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ return drv->probe(mcp);
+}
+
+static int mcp_bus_remove(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ drv->remove(mcp);
+ return 0;
+}
+
+static int mcp_bus_suspend(struct device *dev, pm_message_t state)
+{
+ struct mcp *mcp = to_mcp(dev);
+ int ret = 0;
+
+ if (dev->driver) {
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ ret = drv->suspend(mcp, state);
+ }
+ return ret;
+}
+
+static int mcp_bus_resume(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ int ret = 0;
+
+ if (dev->driver) {
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ ret = drv->resume(mcp);
+ }
+ return ret;
+}
+
+static struct bus_type mcp_bus_type = {
+ .name = "mcp",
+ .match = mcp_bus_match,
+ .suspend = mcp_bus_suspend,
+ .resume = mcp_bus_resume,
+};
+
+/**
+ * mcp_set_telecom_divisor - set the telecom divisor
+ * @mcp: MCP interface structure
+ * @div: SIB clock divisor
+ *
+ * Set the telecom divisor on the MCP interface. The resulting
+ * sample rate is SIBCLOCK/div.
+ */
+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
+{
+ spin_lock_irq(&mcp->lock);
+ mcp->ops->set_telecom_divisor(mcp, div);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_telecom_divisor);
+
+/**
+ * mcp_set_audio_divisor - set the audio divisor
+ * @mcp: MCP interface structure
+ * @div: SIB clock divisor
+ *
+ * Set the audio divisor on the MCP interface.
+ */
+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
+{
+ spin_lock_irq(&mcp->lock);
+ mcp->ops->set_audio_divisor(mcp, div);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_audio_divisor);
+
+/**
+ * mcp_reg_write - write a device register
+ * @mcp: MCP interface structure
+ * @reg: 4-bit register index
+ * @val: 16-bit data value
+ *
+ * Write a device register. The MCP interface must be enabled
+ * to prevent this function hanging.
+ */
+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ mcp->ops->reg_write(mcp, reg, val);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_reg_write);
+
+/**
+ * mcp_reg_read - read a device register
+ * @mcp: MCP interface structure
+ * @reg: 4-bit register index
+ *
+ * Read a device register and return its value. The MCP interface
+ * must be enabled to prevent this function hanging.
+ */
+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ val = mcp->ops->reg_read(mcp, reg);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL(mcp_reg_read);
+
+/**
+ * mcp_enable - enable the MCP interface
+ * @mcp: MCP interface to enable
+ *
+ * Enable the MCP interface. Each call to mcp_enable will need
+ * a corresponding call to mcp_disable to disable the interface.
+ */
+void mcp_enable(struct mcp *mcp)
+{
+ spin_lock_irq(&mcp->lock);
+ if (mcp->use_count++ == 0)
+ mcp->ops->enable(mcp);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_enable);
+
+/**
+ * mcp_disable - disable the MCP interface
+ * @mcp: MCP interface to disable
+ *
+ * Disable the MCP interface. The MCP interface will only be
+ * disabled once the number of calls to mcp_enable matches the
+ * number of calls to mcp_disable.
+ */
+void mcp_disable(struct mcp *mcp)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ if (--mcp->use_count == 0)
+ mcp->ops->disable(mcp);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_disable);
+
+static void mcp_release(struct device *dev)
+{
+ struct mcp *mcp = container_of(dev, struct mcp, attached_device);
+
+ kfree(mcp);
+}
+
+struct mcp *mcp_host_alloc(struct device *parent, size_t size)
+{
+ struct mcp *mcp;
+
+ mcp = kmalloc(sizeof(struct mcp) + size, GFP_KERNEL);
+ if (mcp) {
+ memset(mcp, 0, sizeof(struct mcp) + size);
+ spin_lock_init(&mcp->lock);
+ mcp->attached_device.parent = parent;
+ mcp->attached_device.bus = &mcp_bus_type;
+ mcp->attached_device.dma_mask = parent->dma_mask;
+ mcp->attached_device.release = mcp_release;
+ }
+ return mcp;
+}
+EXPORT_SYMBOL(mcp_host_alloc);
+
+int mcp_host_register(struct mcp *mcp)
+{
+ strcpy(mcp->attached_device.bus_id, "mcp0");
+ return device_register(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_register);
+
+void mcp_host_unregister(struct mcp *mcp)
+{
+ device_unregister(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_unregister);
+
+int mcp_driver_register(struct mcp_driver *mcpdrv)
+{
+ mcpdrv->drv.bus = &mcp_bus_type;
+ mcpdrv->drv.probe = mcp_bus_probe;
+ mcpdrv->drv.remove = mcp_bus_remove;
+ return driver_register(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_register);
+
+void mcp_driver_unregister(struct mcp_driver *mcpdrv)
+{
+ driver_unregister(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_unregister);
+
+static int __init mcp_init(void)
+{
+ return bus_register(&mcp_bus_type);
+}
+
+static void __exit mcp_exit(void)
+{
+ bus_unregister(&mcp_bus_type);
+}
+
+module_init(mcp_init);
+module_exit(mcp_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Core multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
new file mode 100644
index 000000000000..e9806fbbe696
--- /dev/null
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -0,0 +1,275 @@
+/*
+ * linux/drivers/mfd/mcp-sa11x0.c
+ *
+ * Copyright (C) 2001-2005 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.
+ *
+ * SA11x0 MCP (Multimedia Communications Port) driver.
+ *
+ * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+#include <asm/arch/mcp.h>
+
+#include <asm/arch/assabet.h>
+
+#include "mcp.h"
+
+struct mcp_sa11x0 {
+ u32 mccr0;
+ u32 mccr1;
+};
+
+#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
+
+static void
+mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
+{
+ unsigned int mccr0;
+
+ divisor /= 32;
+
+ mccr0 = Ser4MCCR0 & ~0x00007f00;
+ mccr0 |= divisor << 8;
+ Ser4MCCR0 = mccr0;
+}
+
+static void
+mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
+{
+ unsigned int mccr0;
+
+ divisor /= 32;
+
+ mccr0 = Ser4MCCR0 & ~0x0000007f;
+ mccr0 |= divisor;
+ Ser4MCCR0 = mccr0;
+}
+
+/*
+ * Write data to the device. The bit should be set after 3 subframe
+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static void
+mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+ int ret = -ETIME;
+ int i;
+
+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+
+ for (i = 0; i < 2; i++) {
+ udelay(mcp->rw_timeout);
+ if (Ser4MCSR & MCSR_CWC) {
+ ret = 0;
+ break;
+ }
+ }
+
+ if (ret < 0)
+ printk(KERN_WARNING "mcp: write timed out\n");
+}
+
+/*
+ * Read data from the device. The bit should be set after 3 subframe
+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static unsigned int
+mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
+{
+ int ret = -ETIME;
+ int i;
+
+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
+
+ for (i = 0; i < 2; i++) {
+ udelay(mcp->rw_timeout);
+ if (Ser4MCSR & MCSR_CRC) {
+ ret = Ser4MCDR2 & 0xffff;
+ break;
+ }
+ }
+
+ if (ret < 0)
+ printk(KERN_WARNING "mcp: read timed out\n");
+
+ return ret;
+}
+
+static void mcp_sa11x0_enable(struct mcp *mcp)
+{
+ Ser4MCSR = -1;
+ Ser4MCCR0 |= MCCR0_MCE;
+}
+
+static void mcp_sa11x0_disable(struct mcp *mcp)
+{
+ Ser4MCCR0 &= ~MCCR0_MCE;
+}
+
+/*
+ * Our methods.
+ */
+static struct mcp_ops mcp_sa11x0 = {
+ .set_telecom_divisor = mcp_sa11x0_set_telecom_divisor,
+ .set_audio_divisor = mcp_sa11x0_set_audio_divisor,
+ .reg_write = mcp_sa11x0_write,
+ .reg_read = mcp_sa11x0_read,
+ .enable = mcp_sa11x0_enable,
+ .disable = mcp_sa11x0_disable,
+};
+
+static int mcp_sa11x0_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mcp_plat_data *data = pdev->dev.platform_data;
+ struct mcp *mcp;
+ int ret;
+
+ if (!data)
+ return -ENODEV;
+
+ if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
+ return -EBUSY;
+
+ mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
+ if (!mcp) {
+ ret = -ENOMEM;
+ goto release;
+ }
+
+ mcp->owner = THIS_MODULE;
+ mcp->ops = &mcp_sa11x0;
+ mcp->sclk_rate = data->sclk_rate;
+ mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
+ mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
+ mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
+ mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
+
+ dev_set_drvdata(dev, mcp);
+
+ if (machine_is_assabet()) {
+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+ }
+
+ /*
+ * Setup the PPC unit correctly.
+ */
+ PPDR &= ~PPC_RXD4;
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PSDR |= PPC_RXD4;
+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
+ /*
+ * Initialise device. Note that we initially
+ * set the sampling rate to minimum.
+ */
+ Ser4MCSR = -1;
+ Ser4MCCR1 = data->mccr1;
+ Ser4MCCR0 = data->mccr0 | 0x7f7f;
+
+ /*
+ * Calculate the read/write timeout (us) from the bit clock
+ * rate. This is the period for 3 64-bit frames. Always
+ * round this time up.
+ */
+ mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
+ mcp->sclk_rate;
+
+ ret = mcp_host_register(mcp);
+ if (ret == 0)
+ goto out;
+
+ release:
+ release_mem_region(0x80060000, 0x60);
+ dev_set_drvdata(dev, NULL);
+
+ out:
+ return ret;
+}
+
+static int mcp_sa11x0_remove(struct device *dev)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+ mcp_host_unregister(mcp);
+ release_mem_region(0x80060000, 0x60);
+
+ return 0;
+}
+
+static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ if (level == SUSPEND_DISABLE) {
+ priv(mcp)->mccr0 = Ser4MCCR0;
+ priv(mcp)->mccr1 = Ser4MCCR1;
+ Ser4MCCR0 &= ~MCCR0_MCE;
+ }
+ return 0;
+}
+
+static int mcp_sa11x0_resume(struct device *dev, u32 level)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ if (level == RESUME_RESTORE_STATE) {
+ Ser4MCCR1 = priv(mcp)->mccr1;
+ Ser4MCCR0 = priv(mcp)->mccr0;
+ }
+ return 0;
+}
+
+/*
+ * The driver for the SA11x0 MCP port.
+ */
+static struct device_driver mcp_sa11x0_driver = {
+ .name = "sa11x0-mcp",
+ .bus = &platform_bus_type,
+ .probe = mcp_sa11x0_probe,
+ .remove = mcp_sa11x0_remove,
+ .suspend = mcp_sa11x0_suspend,
+ .resume = mcp_sa11x0_resume,
+};
+
+/*
+ * This needs re-working
+ */
+static int __init mcp_sa11x0_init(void)
+{
+ return driver_register(&mcp_sa11x0_driver);
+}
+
+static void __exit mcp_sa11x0_exit(void)
+{
+ driver_unregister(&mcp_sa11x0_driver);
+}
+
+module_init(mcp_sa11x0_init);
+module_exit(mcp_sa11x0_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp.h b/drivers/mfd/mcp.h
new file mode 100644
index 000000000000..c093a93b8808
--- /dev/null
+++ b/drivers/mfd/mcp.h
@@ -0,0 +1,66 @@
+/*
+ * linux/drivers/mfd/mcp.h
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#ifndef MCP_H
+#define MCP_H
+
+struct mcp_ops;
+
+struct mcp {
+ struct module *owner;
+ struct mcp_ops *ops;
+ spinlock_t lock;
+ int use_count;
+ unsigned int sclk_rate;
+ unsigned int rw_timeout;
+ dma_device_t dma_audio_rd;
+ dma_device_t dma_audio_wr;
+ dma_device_t dma_telco_rd;
+ dma_device_t dma_telco_wr;
+ struct device attached_device;
+};
+
+struct mcp_ops {
+ void (*set_telecom_divisor)(struct mcp *, unsigned int);
+ void (*set_audio_divisor)(struct mcp *, unsigned int);
+ void (*reg_write)(struct mcp *, unsigned int, unsigned int);
+ unsigned int (*reg_read)(struct mcp *, unsigned int);
+ void (*enable)(struct mcp *);
+ void (*disable)(struct mcp *);
+};
+
+void mcp_set_telecom_divisor(struct mcp *, unsigned int);
+void mcp_set_audio_divisor(struct mcp *, unsigned int);
+void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
+unsigned int mcp_reg_read(struct mcp *, unsigned int);
+void mcp_enable(struct mcp *);
+void mcp_disable(struct mcp *);
+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
+
+struct mcp *mcp_host_alloc(struct device *, size_t);
+int mcp_host_register(struct mcp *);
+void mcp_host_unregister(struct mcp *);
+
+struct mcp_driver {
+ struct device_driver drv;
+ int (*probe)(struct mcp *);
+ void (*remove)(struct mcp *);
+ int (*suspend)(struct mcp *, pm_message_t);
+ int (*resume)(struct mcp *);
+};
+
+int mcp_driver_register(struct mcp_driver *);
+void mcp_driver_unregister(struct mcp_driver *);
+
+#define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device)
+#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
+
+#define mcp_priv(mcp) ((void *)((mcp)+1))
+
+#endif
diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c
new file mode 100644
index 000000000000..e325fa71f38b
--- /dev/null
+++ b/drivers/mfd/ucb1x00-assabet.c
@@ -0,0 +1,73 @@
+/*
+ * linux/drivers/mfd/ucb1x00-assabet.c
+ *
+ * Copyright (C) 2001-2003 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * We handle the machine-specific bits of the UCB1x00 driver here.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+
+#include "ucb1x00.h"
+
+#define UCB1X00_ATTR(name,input)\
+static ssize_t name##_show(struct class_device *dev, char *buf) \
+{ \
+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); \
+ int val; \
+ ucb1x00_adc_enable(ucb); \
+ val = ucb1x00_adc_read(ucb, input, UCB_NOSYNC); \
+ ucb1x00_adc_disable(ucb); \
+ return sprintf(buf, "%d\n", val); \
+} \
+static CLASS_DEVICE_ATTR(name,0444,name##_show,NULL)
+
+UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1);
+UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0);
+UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
+
+static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
+{
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+ return 0;
+}
+
+static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
+{
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+}
+
+static struct ucb1x00_driver ucb1x00_assabet_driver = {
+ .add = ucb1x00_assabet_add,
+ .remove = ucb1x00_assabet_remove,
+};
+
+static int __init ucb1x00_assabet_init(void)
+{
+ return ucb1x00_register_driver(&ucb1x00_assabet_driver);
+}
+
+static void __exit ucb1x00_assabet_exit(void)
+{
+ ucb1x00_unregister_driver(&ucb1x00_assabet_driver);
+}
+
+module_init(ucb1x00_assabet_init);
+module_exit(ucb1x00_assabet_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
new file mode 100644
index 000000000000..10f6ce1bc0ab
--- /dev/null
+++ b/drivers/mfd/ucb1x00-core.c
@@ -0,0 +1,665 @@
+/*
+ * linux/drivers/mfd/ucb1x00-core.c
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * The UCB1x00 core driver provides basic services for handling IO,
+ * the ADC, interrupts, and accessing registers. It is designed
+ * such that everything goes through this layer, thereby providing
+ * a consistent locking methodology, as well as allowing the drivers
+ * to be used on other non-MCP-enabled hardware platforms.
+ *
+ * Note that all locks are private to this file. Nothing else may
+ * touch them.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include "ucb1x00.h"
+
+static DECLARE_MUTEX(ucb1x00_sem);
+static LIST_HEAD(ucb1x00_drivers);
+static LIST_HEAD(ucb1x00_devices);
+
+/**
+ * ucb1x00_io_set_dir - set IO direction
+ * @ucb: UCB1x00 structure describing chip
+ * @in: bitfield of IO pins to be set as inputs
+ * @out: bitfield of IO pins to be set as outputs
+ *
+ * Set the IO direction of the ten general purpose IO pins on
+ * the UCB1x00 chip. The @in bitfield has priority over the
+ * @out bitfield, in that if you specify a pin as both input
+ * and output, it will end up as an input.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ucb->io_lock, flags);
+ ucb->io_dir |= out;
+ ucb->io_dir &= ~in;
+
+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+ spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ * ucb1x00_io_write - set or clear IO outputs
+ * @ucb: UCB1x00 structure describing chip
+ * @set: bitfield of IO pins to set to logic '1'
+ * @clear: bitfield of IO pins to set to logic '0'
+ *
+ * Set the IO output state of the specified IO pins. The value
+ * is retained if the pins are subsequently configured as inputs.
+ * The @clear bitfield has priority over the @set bitfield -
+ * outputs will be cleared.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ucb->io_lock, flags);
+ ucb->io_out |= set;
+ ucb->io_out &= ~clear;
+
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+ spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ * ucb1x00_io_read - read the current state of the IO pins
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Return a bitfield describing the logic state of the ten
+ * general purpose IO pins.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function does not take any semaphores or spinlocks.
+ */
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
+{
+ return ucb1x00_reg_read(ucb, UCB_IO_DATA);
+}
+
+/*
+ * UCB1300 data sheet says we must:
+ * 1. enable ADC => 5us (including reference startup time)
+ * 2. select input => 51*tsibclk => 4.3us
+ * 3. start conversion => 102*tsibclk => 8.5us
+ * (tsibclk = 1/11981000)
+ * Period between SIB 128-bit frames = 10.7us
+ */
+
+/**
+ * ucb1x00_adc_enable - enable the ADC converter
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
+ * Any code wishing to use the ADC converter must call this
+ * function prior to using it.
+ *
+ * This function takes the ADC semaphore to prevent two or more
+ * concurrent uses, and therefore may sleep. As a result, it
+ * can only be called from process context, not interrupt
+ * context.
+ *
+ * You should release the ADC as soon as possible using
+ * ucb1x00_adc_disable.
+ */
+void ucb1x00_adc_enable(struct ucb1x00 *ucb)
+{
+ down(&ucb->adc_sem);
+
+ ucb->adc_cr |= UCB_ADC_ENA;
+
+ ucb1x00_enable(ucb);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+}
+
+/**
+ * ucb1x00_adc_read - read the specified ADC channel
+ * @ucb: UCB1x00 structure describing chip
+ * @adc_channel: ADC channel mask
+ * @sync: wait for syncronisation pulse.
+ *
+ * Start an ADC conversion and wait for the result. Note that
+ * synchronised ADC conversions (via the ADCSYNC pin) must wait
+ * until the trigger is asserted and the conversion is finished.
+ *
+ * This function currently spins waiting for the conversion to
+ * complete (2 frames max without sync).
+ *
+ * If called for a synchronised ADC conversion, it may sleep
+ * with the ADC semaphore held.
+ */
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
+{
+ unsigned int val;
+
+ if (sync)
+ adc_channel |= UCB_ADC_SYNC_ENA;
+
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
+
+ for (;;) {
+ val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
+ if (val & UCB_ADC_DAT_VAL)
+ break;
+ /* yield to other processes */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ return UCB_ADC_DAT(val);
+}
+
+/**
+ * ucb1x00_adc_disable - disable the ADC converter
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Disable the ADC converter and release the ADC semaphore.
+ */
+void ucb1x00_adc_disable(struct ucb1x00 *ucb)
+{
+ ucb->adc_cr &= ~UCB_ADC_ENA;
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+ ucb1x00_disable(ucb);
+
+ up(&ucb->adc_sem);
+}
+
+/*
+ * UCB1x00 Interrupt handling.
+ *
+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
+ * Since we need to read an internal register, we must re-enable
+ * SIBCLK to talk to the chip. We leave the clock running until
+ * we have finished processing all interrupts from the chip.
+ */
+static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+ struct ucb1x00 *ucb = devid;
+ struct ucb1x00_irq *irq;
+ unsigned int isr, i;
+
+ ucb1x00_enable(ucb);
+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
+ if (isr & 1 && irq->fn)
+ irq->fn(i, irq->devid);
+ ucb1x00_disable(ucb);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ucb1x00_hook_irq - hook a UCB1x00 interrupt
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @fn: function to call when interrupt is triggered
+ * @devid: device id to pass to interrupt handler
+ *
+ * Hook the specified interrupt. You can only register one handler
+ * for each interrupt source. The interrupt source is not enabled
+ * by this function; use ucb1x00_enable_irq instead.
+ *
+ * Interrupt handlers will be called with other interrupts enabled.
+ *
+ * Returns zero on success, or one of the following errors:
+ * -EINVAL if the interrupt index is invalid
+ * -EBUSY if the interrupt has already been hooked
+ */
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
+{
+ struct ucb1x00_irq *irq;
+ int ret = -EINVAL;
+
+ if (idx < 16) {
+ irq = ucb->irq_handler + idx;
+ ret = -EBUSY;
+
+ spin_lock_irq(&ucb->lock);
+ if (irq->fn == NULL) {
+ irq->devid = devid;
+ irq->fn = fn;
+ ret = 0;
+ }
+ spin_unlock_irq(&ucb->lock);
+ }
+ return ret;
+}
+
+/**
+ * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @edges: interrupt edges to enable
+ *
+ * Enable the specified interrupt to trigger on %UCB_RISING,
+ * %UCB_FALLING or both edges. The interrupt should have been
+ * hooked by ucb1x00_hook_irq.
+ */
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+ unsigned long flags;
+
+ if (idx < 16) {
+ spin_lock_irqsave(&ucb->lock, flags);
+
+ ucb1x00_enable(ucb);
+ if (edges & UCB_RISING) {
+ ucb->irq_ris_enbl |= 1 << idx;
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ }
+ if (edges & UCB_FALLING) {
+ ucb->irq_fal_enbl |= 1 << idx;
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ }
+ ucb1x00_disable(ucb);
+ spin_unlock_irqrestore(&ucb->lock, flags);
+ }
+}
+
+/**
+ * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
+ * @ucb: UCB1x00 structure describing chip
+ * @edges: interrupt edges to disable
+ *
+ * Disable the specified interrupt triggering on the specified
+ * (%UCB_RISING, %UCB_FALLING or both) edges.
+ */
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+ unsigned long flags;
+
+ if (idx < 16) {
+ spin_lock_irqsave(&ucb->lock, flags);
+
+ ucb1x00_enable(ucb);
+ if (edges & UCB_RISING) {
+ ucb->irq_ris_enbl &= ~(1 << idx);
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ }
+ if (edges & UCB_FALLING) {
+ ucb->irq_fal_enbl &= ~(1 << idx);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ }
+ ucb1x00_disable(ucb);
+ spin_unlock_irqrestore(&ucb->lock, flags);
+ }
+}
+
+/**
+ * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @devid: device id.
+ *
+ * Disable the interrupt source and remove the handler. devid must
+ * match the devid passed when hooking the interrupt.
+ *
+ * Returns zero on success, or one of the following errors:
+ * -EINVAL if the interrupt index is invalid
+ * -ENOENT if devid does not match
+ */
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
+{
+ struct ucb1x00_irq *irq;
+ int ret;
+
+ if (idx >= 16)
+ goto bad;
+
+ irq = ucb->irq_handler + idx;
+ ret = -ENOENT;
+
+ spin_lock_irq(&ucb->lock);
+ if (irq->devid == devid) {
+ ucb->irq_ris_enbl &= ~(1 << idx);
+ ucb->irq_fal_enbl &= ~(1 << idx);
+
+ ucb1x00_enable(ucb);
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ ucb1x00_disable(ucb);
+
+ irq->fn = NULL;
+ irq->devid = NULL;
+ ret = 0;
+ }
+ spin_unlock_irq(&ucb->lock);
+ return ret;
+
+bad:
+ printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx);
+ return -EINVAL;
+}
+
+static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
+{
+ struct ucb1x00_dev *dev;
+ int ret = -ENOMEM;
+
+ dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL);
+ if (dev) {
+ dev->ucb = ucb;
+ dev->drv = drv;
+
+ ret = drv->add(dev);
+
+ if (ret == 0) {
+ list_add(&dev->dev_node, &ucb->devs);
+ list_add(&dev->drv_node, &drv->devs);
+ } else {
+ kfree(dev);
+ }
+ }
+ return ret;
+}
+
+static void ucb1x00_remove_dev(struct ucb1x00_dev *dev)
+{
+ dev->drv->remove(dev);
+ list_del(&dev->dev_node);
+ list_del(&dev->drv_node);
+ kfree(dev);
+}
+
+/*
+ * Try to probe our interrupt, rather than relying on lots of
+ * hard-coded machine dependencies. For reference, the expected
+ * IRQ mappings are:
+ *
+ * Machine Default IRQ
+ * adsbitsy IRQ_GPCIN4
+ * cerf IRQ_GPIO_UCB1200_IRQ
+ * flexanet IRQ_GPIO_GUI
+ * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
+ * graphicsclient ADS_EXT_IRQ(8)
+ * graphicsmaster ADS_EXT_IRQ(8)
+ * lart LART_IRQ_UCB1200
+ * omnimeter IRQ_GPIO23
+ * pfs168 IRQ_GPIO_UCB1300_IRQ
+ * simpad IRQ_GPIO_UCB1300_IRQ
+ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
+ * yopy IRQ_GPIO_UCB1200_IRQ
+ */
+static int ucb1x00_detect_irq(struct ucb1x00 *ucb)
+{
+ unsigned long mask;
+
+ mask = probe_irq_on();
+ if (!mask)
+ return NO_IRQ;
+
+ /*
+ * Enable the ADC interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /*
+ * Cause an ADC interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+
+ /*
+ * Wait for the conversion to complete.
+ */
+ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
+
+ /*
+ * Disable and clear interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /*
+ * Read triggered interrupt.
+ */
+ return probe_irq_off(mask);
+}
+
+static int ucb1x00_probe(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb;
+ struct ucb1x00_driver *drv;
+ unsigned int id;
+ int ret = -ENODEV;
+
+ mcp_enable(mcp);
+ id = mcp_reg_read(mcp, UCB_ID);
+
+ if (id != UCB_ID_1200 && id != UCB_ID_1300) {
+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
+ goto err_disable;
+ }
+
+ ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
+ ret = -ENOMEM;
+ if (!ucb)
+ goto err_disable;
+
+ memset(ucb, 0, sizeof(struct ucb1x00));
+
+ ucb->cdev.class = &ucb1x00_class;
+ ucb->cdev.dev = &mcp->attached_device;
+ strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id));
+
+ spin_lock_init(&ucb->lock);
+ spin_lock_init(&ucb->io_lock);
+ sema_init(&ucb->adc_sem, 1);
+
+ ucb->id = id;
+ ucb->mcp = mcp;
+ ucb->irq = ucb1x00_detect_irq(ucb);
+ if (ucb->irq == NO_IRQ) {
+ printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb);
+ if (ret) {
+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+ ucb->irq, ret);
+ goto err_free;
+ }
+
+ set_irq_type(ucb->irq, IRQT_RISING);
+ mcp_set_drvdata(mcp, ucb);
+
+ ret = class_device_register(&ucb->cdev);
+ if (ret)
+ goto err_irq;
+
+ INIT_LIST_HEAD(&ucb->devs);
+ down(&ucb1x00_sem);
+ list_add(&ucb->node, &ucb1x00_devices);
+ list_for_each_entry(drv, &ucb1x00_drivers, node) {
+ ucb1x00_add_dev(ucb, drv);
+ }
+ up(&ucb1x00_sem);
+ goto out;
+
+ err_irq:
+ free_irq(ucb->irq, ucb);
+ err_free:
+ kfree(ucb);
+ err_disable:
+ mcp_disable(mcp);
+ out:
+ return ret;
+}
+
+static void ucb1x00_remove(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct list_head *l, *n;
+
+ down(&ucb1x00_sem);
+ list_del(&ucb->node);
+ list_for_each_safe(l, n, &ucb->devs) {
+ struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node);
+ ucb1x00_remove_dev(dev);
+ }
+ up(&ucb1x00_sem);
+
+ free_irq(ucb->irq, ucb);
+ class_device_unregister(&ucb->cdev);
+}
+
+static void ucb1x00_release(struct class_device *dev)
+{
+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);
+ kfree(ucb);
+}
+
+static struct class ucb1x00_class = {
+ .name = "ucb1x00",
+ .release = ucb1x00_release,
+};
+
+int ucb1x00_register_driver(struct ucb1x00_driver *drv)
+{
+ struct ucb1x00 *ucb;
+
+ INIT_LIST_HEAD(&drv->devs);
+ down(&ucb1x00_sem);
+ list_add(&drv->node, &ucb1x00_drivers);
+ list_for_each_entry(ucb, &ucb1x00_devices, node) {
+ ucb1x00_add_dev(ucb, drv);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
+{
+ struct list_head *n, *l;
+
+ down(&ucb1x00_sem);
+ list_del(&drv->node);
+ list_for_each_safe(l, n, &drv->devs) {
+ struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node);
+ ucb1x00_remove_dev(dev);
+ }
+ up(&ucb1x00_sem);
+}
+
+static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct ucb1x00_dev *dev;
+
+ down(&ucb1x00_sem);
+ list_for_each_entry(dev, &ucb->devs, dev_node) {
+ if (dev->drv->suspend)
+ dev->drv->suspend(dev, state);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+static int ucb1x00_resume(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct ucb1x00_dev *dev;
+
+ down(&ucb1x00_sem);
+ list_for_each_entry(dev, &ucb->devs, dev_node) {
+ if (dev->drv->resume)
+ dev->drv->resume(dev);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+static struct mcp_driver ucb1x00_driver = {
+ .drv = {
+ .name = "ucb1x00",
+ },
+ .probe = ucb1x00_probe,
+ .remove = ucb1x00_remove,
+ .suspend = ucb1x00_suspend,
+ .resume = ucb1x00_resume,
+};
+
+static int __init ucb1x00_init(void)
+{
+ int ret = class_register(&ucb1x00_class);
+ if (ret == 0) {
+ ret = mcp_driver_register(&ucb1x00_driver);
+ if (ret)
+ class_unregister(&ucb1x00_class);
+ }
+ return ret;
+}
+
+static void __exit ucb1x00_exit(void)
+{
+ mcp_driver_unregister(&ucb1x00_driver);
+ class_unregister(&ucb1x00_class);
+}
+
+module_init(ucb1x00_init);
+module_exit(ucb1x00_exit);
+
+EXPORT_SYMBOL(ucb1x00_class);
+
+EXPORT_SYMBOL(ucb1x00_io_set_dir);
+EXPORT_SYMBOL(ucb1x00_io_write);
+EXPORT_SYMBOL(ucb1x00_io_read);
+
+EXPORT_SYMBOL(ucb1x00_adc_enable);
+EXPORT_SYMBOL(ucb1x00_adc_read);
+EXPORT_SYMBOL(ucb1x00_adc_disable);
+
+EXPORT_SYMBOL(ucb1x00_hook_irq);
+EXPORT_SYMBOL(ucb1x00_free_irq);
+EXPORT_SYMBOL(ucb1x00_enable_irq);
+EXPORT_SYMBOL(ucb1x00_disable_irq);
+
+EXPORT_SYMBOL(ucb1x00_register_driver);
+EXPORT_SYMBOL(ucb1x00_unregister_driver);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
new file mode 100644
index 000000000000..a851d65c7cfe
--- /dev/null
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -0,0 +1,399 @@
+/*
+ * Touchscreen driver for UCB1x00-based touchscreens
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ * Copyright (C) 2005 Pavel Machek
+ *
+ * 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.
+ *
+ * 21-Jan-2002 <jco@ict.es> :
+ *
+ * Added support for synchronous A/D mode. This mode is useful to
+ * avoid noise induced in the touchpanel by the LCD, provided that
+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
+ * It is important to note that the signal connected to the ADCSYNC
+ * pin should provide pulses even when the LCD is blanked, otherwise
+ * a pen touch needed to unblank the LCD will never be read.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+
+#include <asm/dma.h>
+#include <asm/semaphore.h>
+
+#include "ucb1x00.h"
+
+
+struct ucb1x00_ts {
+ struct input_dev idev;
+ struct ucb1x00 *ucb;
+
+ wait_queue_head_t irq_wait;
+ struct task_struct *rtask;
+ u16 x_res;
+ u16 y_res;
+
+ int restart:1;
+ int adcsync:1;
+};
+
+static int adcsync;
+
+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
+{
+ input_report_abs(&ts->idev, ABS_X, x);
+ input_report_abs(&ts->idev, ABS_Y, y);
+ input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
+ input_sync(&ts->idev);
+}
+
+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
+{
+ input_report_abs(&ts->idev, ABS_PRESSURE, 0);
+ input_sync(&ts->idev);
+}
+
+/*
+ * Switch to interrupt mode.
+ */
+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+ UCB_TS_CR_MODE_INT);
+}
+
+/*
+ * Switch to pressure mode, and read pressure. We don't need to wait
+ * here, since both plates are being driven.
+ */
+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+}
+
+/*
+ * Switch to X position mode and measure Y plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+}
+
+/*
+ * Switch to Y position mode and measure X plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
+}
+
+/*
+ * Switch to X plate resistance mode. Set MX to ground, PX to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+/*
+ * Switch to Y plate resistance mode. Set MY to ground, PY to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+/*
+ * This is a RT kernel thread that handles the ADC accesses
+ * (mainly so we can use semaphores in the UCB1200 core code
+ * to serialise accesses to the ADC).
+ */
+static int ucb1x00_thread(void *_ts)
+{
+ struct ucb1x00_ts *ts = _ts;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ int valid;
+
+ /*
+ * We could run as a real-time thread. However, thus far
+ * this doesn't seem to be necessary.
+ */
+// tsk->policy = SCHED_FIFO;
+// tsk->rt_priority = 1;
+
+ valid = 0;
+
+ add_wait_queue(&ts->irq_wait, &wait);
+ while (!kthread_should_stop()) {
+ unsigned int x, y, p, val;
+ signed long timeout;
+
+ ts->restart = 0;
+
+ ucb1x00_adc_enable(ts->ucb);
+
+ x = ucb1x00_ts_read_xpos(ts);
+ y = ucb1x00_ts_read_ypos(ts);
+ p = ucb1x00_ts_read_pressure(ts);
+
+ /*
+ * Switch back to interrupt mode.
+ */
+ ucb1x00_ts_mode_int(ts);
+ ucb1x00_adc_disable(ts->ucb);
+
+ msleep(10);
+
+ ucb1x00_enable(ts->ucb);
+ val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+
+ if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+ ucb1x00_disable(ts->ucb);
+
+ /*
+ * If we spat out a valid sample set last time,
+ * spit out a "pen off" sample here.
+ */
+ if (valid) {
+ ucb1x00_ts_event_release(ts);
+ valid = 0;
+ }
+
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ } else {
+ ucb1x00_disable(ts->ucb);
+
+ /*
+ * Filtering is policy. Policy belongs in user
+ * space. We therefore leave it to user space
+ * to do any filtering they please.
+ */
+ if (!ts->restart) {
+ ucb1x00_ts_evt_add(ts, p, x, y);
+ valid = 1;
+ }
+
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ timeout = HZ / 100;
+ }
+
+ try_to_freeze();
+
+ schedule_timeout(timeout);
+ }
+
+ remove_wait_queue(&ts->irq_wait, &wait);
+
+ ts->rtask = NULL;
+ return 0;
+}
+
+/*
+ * We only detect touch screen _touches_ with this interrupt
+ * handler, and even then we just schedule our task.
+ */
+static void ucb1x00_ts_irq(int idx, void *id)
+{
+ struct ucb1x00_ts *ts = id;
+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+ wake_up(&ts->irq_wait);
+}
+
+static int ucb1x00_ts_open(struct input_dev *idev)
+{
+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+ int ret = 0;
+
+ BUG_ON(ts->rtask);
+
+ init_waitqueue_head(&ts->irq_wait);
+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
+ if (ret < 0)
+ goto out;
+
+ /*
+ * If we do this at all, we should allow the user to
+ * measure and read the X and Y resistance at any time.
+ */
+ ucb1x00_adc_enable(ts->ucb);
+ ts->x_res = ucb1x00_ts_read_xres(ts);
+ ts->y_res = ucb1x00_ts_read_yres(ts);
+ ucb1x00_adc_disable(ts->ucb);
+
+ ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
+ if (!IS_ERR(ts->rtask)) {
+ ret = 0;
+ } else {
+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+ ts->rtask = NULL;
+ ret = -EFAULT;
+ }
+
+ out:
+ return ret;
+}
+
+/*
+ * Release touchscreen resources. Disable IRQs.
+ */
+static void ucb1x00_ts_close(struct input_dev *idev)
+{
+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+
+ if (ts->rtask)
+ kthread_stop(ts->rtask);
+
+ ucb1x00_enable(ts->ucb);
+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
+ ucb1x00_disable(ts->ucb);
+}
+
+#ifdef CONFIG_PM
+static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts = dev->priv;
+
+ if (ts->rtask != NULL) {
+ /*
+ * Restart the TS thread to ensure the
+ * TS interrupt mode is set up again
+ * after sleep.
+ */
+ ts->restart = 1;
+ wake_up(&ts->irq_wait);
+ }
+ return 0;
+}
+#else
+#define ucb1x00_ts_resume NULL
+#endif
+
+
+/*
+ * Initialisation.
+ */
+static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts;
+
+ ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ memset(ts, 0, sizeof(struct ucb1x00_ts));
+
+ ts->ucb = dev->ucb;
+ ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
+
+ ts->idev.name = "Touchscreen panel";
+ ts->idev.id.product = ts->ucb->id;
+ ts->idev.open = ucb1x00_ts_open;
+ ts->idev.close = ucb1x00_ts_close;
+
+ __set_bit(EV_ABS, ts->idev.evbit);
+ __set_bit(ABS_X, ts->idev.absbit);
+ __set_bit(ABS_Y, ts->idev.absbit);
+ __set_bit(ABS_PRESSURE, ts->idev.absbit);
+
+ input_register_device(&ts->idev);
+
+ dev->priv = ts;
+
+ return 0;
+}
+
+static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts = dev->priv;
+ input_unregister_device(&ts->idev);
+ kfree(ts);
+}
+
+static struct ucb1x00_driver ucb1x00_ts_driver = {
+ .add = ucb1x00_ts_add,
+ .remove = ucb1x00_ts_remove,
+ .resume = ucb1x00_ts_resume,
+};
+
+static int __init ucb1x00_ts_init(void)
+{
+ return ucb1x00_register_driver(&ucb1x00_ts_driver);
+}
+
+static void __exit ucb1x00_ts_exit(void)
+{
+ ucb1x00_unregister_driver(&ucb1x00_ts_driver);
+}
+
+module_param(adcsync, int, 0444);
+module_init(ucb1x00_ts_init);
+module_exit(ucb1x00_ts_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
new file mode 100644
index 000000000000..6b632644f59a
--- /dev/null
+++ b/drivers/mfd/ucb1x00.h
@@ -0,0 +1,256 @@
+/*
+ * linux/drivers/mfd/ucb1x00.h
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#ifndef UCB1200_H
+#define UCB1200_H
+
+#define UCB_IO_DATA 0x00
+#define UCB_IO_DIR 0x01
+
+#define UCB_IO_0 (1 << 0)
+#define UCB_IO_1 (1 << 1)
+#define UCB_IO_2 (1 << 2)
+#define UCB_IO_3 (1 << 3)
+#define UCB_IO_4 (1 << 4)
+#define UCB_IO_5 (1 << 5)
+#define UCB_IO_6 (1 << 6)
+#define UCB_IO_7 (1 << 7)
+#define UCB_IO_8 (1 << 8)
+#define UCB_IO_9 (1 << 9)
+
+#define UCB_IE_RIS 0x02
+#define UCB_IE_FAL 0x03
+#define UCB_IE_STATUS 0x04
+#define UCB_IE_CLEAR 0x04
+#define UCB_IE_ADC (1 << 11)
+#define UCB_IE_TSPX (1 << 12)
+#define UCB_IE_TSMX (1 << 13)
+#define UCB_IE_TCLIP (1 << 14)
+#define UCB_IE_ACLIP (1 << 15)
+
+#define UCB_IRQ_TSPX 12
+
+#define UCB_TC_A 0x05
+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
+
+#define UCB_TC_B 0x06
+#define UCB_TC_B_VOICE_ENA (1 << 3)
+#define UCB_TC_B_CLIP (1 << 4)
+#define UCB_TC_B_ATT (1 << 6)
+#define UCB_TC_B_SIDE_ENA (1 << 11)
+#define UCB_TC_B_MUTE (1 << 13)
+#define UCB_TC_B_IN_ENA (1 << 14)
+#define UCB_TC_B_OUT_ENA (1 << 15)
+
+#define UCB_AC_A 0x07
+#define UCB_AC_B 0x08
+#define UCB_AC_B_LOOP (1 << 8)
+#define UCB_AC_B_MUTE (1 << 13)
+#define UCB_AC_B_IN_ENA (1 << 14)
+#define UCB_AC_B_OUT_ENA (1 << 15)
+
+#define UCB_TS_CR 0x09
+#define UCB_TS_CR_TSMX_POW (1 << 0)
+#define UCB_TS_CR_TSPX_POW (1 << 1)
+#define UCB_TS_CR_TSMY_POW (1 << 2)
+#define UCB_TS_CR_TSPY_POW (1 << 3)
+#define UCB_TS_CR_TSMX_GND (1 << 4)
+#define UCB_TS_CR_TSPX_GND (1 << 5)
+#define UCB_TS_CR_TSMY_GND (1 << 6)
+#define UCB_TS_CR_TSPY_GND (1 << 7)
+#define UCB_TS_CR_MODE_INT (0 << 8)
+#define UCB_TS_CR_MODE_PRES (1 << 8)
+#define UCB_TS_CR_MODE_POS (2 << 8)
+#define UCB_TS_CR_BIAS_ENA (1 << 11)
+#define UCB_TS_CR_TSPX_LOW (1 << 12)
+#define UCB_TS_CR_TSMX_LOW (1 << 13)
+
+#define UCB_ADC_CR 0x0a
+#define UCB_ADC_SYNC_ENA (1 << 0)
+#define UCB_ADC_VREFBYP_CON (1 << 1)
+#define UCB_ADC_INP_TSPX (0 << 2)
+#define UCB_ADC_INP_TSMX (1 << 2)
+#define UCB_ADC_INP_TSPY (2 << 2)
+#define UCB_ADC_INP_TSMY (3 << 2)
+#define UCB_ADC_INP_AD0 (4 << 2)
+#define UCB_ADC_INP_AD1 (5 << 2)
+#define UCB_ADC_INP_AD2 (6 << 2)
+#define UCB_ADC_INP_AD3 (7 << 2)
+#define UCB_ADC_EXT_REF (1 << 5)
+#define UCB_ADC_START (1 << 7)
+#define UCB_ADC_ENA (1 << 15)
+
+#define UCB_ADC_DATA 0x0b
+#define UCB_ADC_DAT_VAL (1 << 15)
+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
+
+#define UCB_ID 0x0c
+#define UCB_ID_1200 0x1004
+#define UCB_ID_1300 0x1005
+
+#define UCB_MODE 0x0d
+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
+#define UCB_MODE_AUD_OFF_CAN (1 << 13)
+
+#include "mcp.h"
+
+struct ucb1x00_irq {
+ void *devid;
+ void (*fn)(int, void *);
+};
+
+extern struct class ucb1x00_class;
+
+struct ucb1x00 {
+ spinlock_t lock;
+ struct mcp *mcp;
+ unsigned int irq;
+ struct semaphore adc_sem;
+ spinlock_t io_lock;
+ u16 id;
+ u16 io_dir;
+ u16 io_out;
+ u16 adc_cr;
+ u16 irq_fal_enbl;
+ u16 irq_ris_enbl;
+ struct ucb1x00_irq irq_handler[16];
+ struct class_device cdev;
+ struct list_head node;
+ struct list_head devs;
+};
+
+struct ucb1x00_driver;
+
+struct ucb1x00_dev {
+ struct list_head dev_node;
+ struct list_head drv_node;
+ struct ucb1x00 *ucb;
+ struct ucb1x00_driver *drv;
+ void *priv;
+};
+
+struct ucb1x00_driver {
+ struct list_head node;
+ struct list_head devs;
+ int (*add)(struct ucb1x00_dev *dev);
+ void (*remove)(struct ucb1x00_dev *dev);
+ int (*suspend)(struct ucb1x00_dev *dev, pm_message_t state);
+ int (*resume)(struct ucb1x00_dev *dev);
+};
+
+#define classdev_to_ucb1x00(cd) container_of(cd, struct ucb1x00, cdev)
+
+int ucb1x00_register_driver(struct ucb1x00_driver *);
+void ucb1x00_unregister_driver(struct ucb1x00_driver *);
+
+/**
+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Return the SIB clock rate in Hz.
+ */
+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
+{
+ return mcp_get_sclk_rate(ucb->mcp);
+}
+
+/**
+ * ucb1x00_enable - enable the UCB1x00 SIB clock
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Enable the SIB clock. This can be called multiple times.
+ */
+static inline void ucb1x00_enable(struct ucb1x00 *ucb)
+{
+ mcp_enable(ucb->mcp);
+}
+
+/**
+ * ucb1x00_disable - disable the UCB1x00 SIB clock
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Disable the SIB clock. The SIB clock will only be disabled
+ * when the number of ucb1x00_enable calls match the number of
+ * ucb1x00_disable calls.
+ */
+static inline void ucb1x00_disable(struct ucb1x00 *ucb)
+{
+ mcp_disable(ucb->mcp);
+}
+
+/**
+ * ucb1x00_reg_write - write a UCB1x00 register
+ * @ucb: UCB1x00 structure describing chip
+ * @reg: UCB1x00 4-bit register index to write
+ * @val: UCB1x00 16-bit value to write
+ *
+ * Write the UCB1x00 register @reg with value @val. The SIB
+ * clock must be running for this function to return.
+ */
+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
+{
+ mcp_reg_write(ucb->mcp, reg, val);
+}
+
+/**
+ * ucb1x00_reg_read - read a UCB1x00 register
+ * @ucb: UCB1x00 structure describing chip
+ * @reg: UCB1x00 4-bit register index to write
+ *
+ * Read the UCB1x00 register @reg and return its value. The SIB
+ * clock must be running for this function to return.
+ */
+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
+{
+ return mcp_reg_read(ucb->mcp, reg);
+}
+/**
+ * ucb1x00_set_audio_divisor -
+ * @ucb: UCB1x00 structure describing chip
+ * @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+ mcp_set_audio_divisor(ucb->mcp, div);
+}
+
+/**
+ * ucb1x00_set_telecom_divisor -
+ * @ucb: UCB1x00 structure describing chip
+ * @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+ mcp_set_telecom_divisor(ucb->mcp, div);
+}
+
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
+
+#define UCB_NOSYNC (0)
+#define UCB_SYNC (1)
+
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
+void ucb1x00_adc_enable(struct ucb1x00 *ucb);
+void ucb1x00_adc_disable(struct ucb1x00 *ucb);
+
+/*
+ * Which edges of the IRQ do you want to control today?
+ */
+#define UCB_RISING (1 << 0)
+#define UCB_FALLING (1 << 1)
+
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
+
+#endif
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 7501fab349e4..46de5c940555 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -192,22 +192,37 @@ static int hdpu_cpustate_probe(struct device *ddev)
{
struct platform_device *pdev = to_platform_device(ddev);
struct resource *res;
+ struct proc_dir_entry *proc_de;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cpustate.set_addr = (unsigned long *)res->start;
cpustate.clr_addr = (unsigned long *)res->end - 1;
- misc_register(&cpustate_dev);
- create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc, NULL);
+ ret = misc_register(&cpustate_dev);
+ if (ret) {
+ printk(KERN_WARNING "sky_cpustate: Unable to register misc "
+ "device.\n");
+ cpustate.set_addr = NULL;
+ cpustate.clr_addr = NULL;
+ return ret;
+ }
+
+ proc_de = create_proc_read_entry("sky_cpustate", 0, 0,
+ cpustate_read_proc, NULL);
+ if (proc_de == NULL)
+ printk(KERN_WARNING "sky_cpustate: Unable to create proc "
+ "dir entry\n");
printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
return 0;
}
+
static int hdpu_cpustate_remove(struct device *ddev)
{
- cpustate.set_addr = 0;
- cpustate.clr_addr = 0;
+ cpustate.set_addr = NULL;
+ cpustate.clr_addr = NULL;
remove_proc_entry("sky_cpustate", NULL);
misc_deregister(&cpustate_dev);
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 914804512dba..7e98434cfa37 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -25,15 +25,15 @@
#include <linux/termios.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
-#include <linux/serial.h>
#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
#include "ibmasm.h"
#include "lowlevel.h"
void ibmasm_register_uart(struct service_processor *sp)
{
- struct serial_struct serial;
+ struct uart_port uport;
void __iomem *iomem_base;
iomem_base = sp->base_address + SCOUT_COM_B_BASE;
@@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp)
return;
}
- memset(&serial, 0, sizeof(serial));
- serial.irq = sp->irq;
- serial.baud_base = 3686400 / 16;
- serial.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
- serial.io_type = UPIO_MEM;
- serial.iomem_base = iomem_base;
+ memset(&uport, 0, sizeof(struct uart_port));
+ uport.irq = sp->irq;
+ uport.uartclk = 3686400;
+ uport.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
+ uport.iotype = UPIO_MEM;
+ uport.membase = iomem_base;
- sp->serial_line = register_serial(&serial);
+ sp->serial_line = serial8250_register_port(&uport);
if (sp->serial_line < 0) {
dev_err(sp->dev, "Failed to register serial port\n");
return;
@@ -68,5 +68,5 @@ void ibmasm_unregister_uart(struct service_processor *sp)
return;
disable_uart_interrupts(sp->base_address);
- unregister_serial(sp->serial_line);
+ serial8250_unregister_port(sp->serial_line);
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index eeb9f6668e69..ceae379a4d4c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2,6 +2,8 @@
* linux/drivers/mmc/mmc.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ * SD support Copyright (C) 2005 Pierre Ossman, 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
@@ -16,6 +18,8 @@
#include <linux/delay.h>
#include <linux/pagemap.h>
#include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -172,7 +176,81 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
EXPORT_SYMBOL(mmc_wait_for_cmd);
+/**
+ * mmc_wait_for_app_cmd - start an application command and wait for
+ completion
+ * @host: MMC host to start command
+ * @rca: RCA to send MMC_APP_CMD to
+ * @cmd: MMC command to start
+ * @retries: maximum number of retries
+ *
+ * Sends a MMC_APP_CMD, checks the card response, sends the command
+ * in the parameter and waits for it to complete. Return any error
+ * that occurred while the command was executing. Do not attempt to
+ * parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+ struct mmc_command *cmd, int retries)
+{
+ struct mmc_request mrq;
+ struct mmc_command appcmd;
+
+ int i, err;
+
+ BUG_ON(host->card_busy == NULL);
+ BUG_ON(retries < 0);
+
+ err = MMC_ERR_INVALID;
+
+ /*
+ * We have to resend MMC_APP_CMD for each attempt so
+ * we cannot use the retries field in mmc_command.
+ */
+ for (i = 0;i <= retries;i++) {
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ appcmd.opcode = MMC_APP_CMD;
+ appcmd.arg = rca << 16;
+ appcmd.flags = MMC_RSP_R1;
+ appcmd.retries = 0;
+ memset(appcmd.resp, 0, sizeof(appcmd.resp));
+ appcmd.data = NULL;
+
+ mrq.cmd = &appcmd;
+ appcmd.data = NULL;
+
+ mmc_wait_for_req(host, &mrq);
+
+ if (appcmd.error) {
+ err = appcmd.error;
+ continue;
+ }
+
+ /* Check that card supported application commands */
+ if (!(appcmd.resp[0] & R1_APP_CMD))
+ return MMC_ERR_FAILED;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ memset(cmd->resp, 0, sizeof(cmd->resp));
+ cmd->retries = 0;
+
+ mrq.cmd = cmd;
+ cmd->data = NULL;
+
+ mmc_wait_for_req(host, &mrq);
+
+ err = cmd->error;
+ if (cmd->error == MMC_ERR_NONE)
+ break;
+ }
+ return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
/**
* __mmc_claim_host - exclusively claim a host
@@ -206,16 +284,10 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);
- if (card != (void *)-1 && host->card_selected != card) {
- struct mmc_command cmd;
-
- host->card_selected = card;
-
- cmd.opcode = MMC_SELECT_CARD;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
-
- err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (card != (void *)-1) {
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE)
+ return err;
}
return err;
@@ -245,6 +317,63 @@ void mmc_release_host(struct mmc_host *host)
EXPORT_SYMBOL(mmc_release_host);
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+ struct mmc_command cmd;
+
+ BUG_ON(host->card_busy == NULL);
+
+ if (host->card_selected == card)
+ return MMC_ERR_NONE;
+
+ host->card_selected = card;
+
+ cmd.opcode = MMC_SELECT_CARD;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ /*
+ * Default bus width is 1 bit.
+ */
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+ /*
+ * We can only change the bus width of the selected
+ * card so therefore we have to put the handling
+ * here.
+ */
+ if (host->caps & MMC_CAP_4_BIT_DATA) {
+ /*
+ * The card is in 1 bit mode by default so
+ * we only need to change if it supports the
+ * wider version.
+ */
+ if (mmc_card_sd(card) &&
+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ struct mmc_command cmd;
+ cmd.opcode = SD_APP_SET_BUS_WIDTH;
+ cmd.arg = SD_BUS_WIDTH_4;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
+ CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ host->ios.bus_width = MMC_BUS_WIDTH_4;
+ }
+ }
+
+ host->ops->set_ios(host, &host->ios);
+
+ return MMC_ERR_NONE;
+}
+
/*
* Ensure that no card is selected.
*/
@@ -322,48 +451,69 @@ static void mmc_decode_cid(struct mmc_card *card)
memset(&card->cid, 0, sizeof(struct mmc_cid));
- /*
- * The selection of the format here is guesswork based upon
- * information people have sent to date.
- */
- switch (card->csd.mmca_vsn) {
- case 0: /* MMC v1.? */
- case 1: /* MMC v1.4 */
- card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
- card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
- card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
- card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
- card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
- card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
- card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
- card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
- card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
- card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
- card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
- card->cid.month = UNSTUFF_BITS(resp, 12, 4);
- card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
- break;
-
- case 2: /* MMC v2.x ? */
- case 3: /* MMC v3.x ? */
- card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
- card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
- card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
- card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
- card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
- card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
- card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
- card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
- card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
- card->cid.month = UNSTUFF_BITS(resp, 12, 4);
- card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
- break;
-
- default:
- printk("%s: card has unknown MMCA version %d\n",
- card->host->host_name, card->csd.mmca_vsn);
- mmc_card_set_bad(card);
- break;
+ if (mmc_card_sd(card)) {
+ /*
+ * SD doesn't currently have a version field so we will
+ * have to assume we can parse this.
+ */
+ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
+ card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4);
+ card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4);
+ card->cid.serial = UNSTUFF_BITS(resp, 24, 32);
+ card->cid.year = UNSTUFF_BITS(resp, 12, 8);
+ card->cid.month = UNSTUFF_BITS(resp, 8, 4);
+
+ card->cid.year += 2000; /* SD cards year offset */
+ } else {
+ /*
+ * The selection of the format here is based upon published
+ * specs from sandisk and from what people have reported.
+ */
+ switch (card->csd.mmca_vsn) {
+ case 0: /* MMC v1.0 - v1.2 */
+ case 1: /* MMC v1.4 */
+ card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
+ card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
+ card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
+ card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
+ card->cid.month = UNSTUFF_BITS(resp, 12, 4);
+ card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
+ break;
+
+ case 2: /* MMC v2.0 - v2.2 */
+ case 3: /* MMC v3.1 - v3.3 */
+ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
+ card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
+ card->cid.month = UNSTUFF_BITS(resp, 12, 4);
+ card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
+ break;
+
+ default:
+ printk("%s: card has unknown MMCA version %d\n",
+ mmc_hostname(card->host), card->csd.mmca_vsn);
+ mmc_card_set_bad(card);
+ break;
+ }
}
}
@@ -376,34 +526,86 @@ static void mmc_decode_csd(struct mmc_card *card)
unsigned int e, m, csd_struct;
u32 *resp = card->raw_csd;
- /*
- * We only understand CSD structure v1.1 and v2.
- * v2 has extra information in bits 15, 11 and 10.
- */
- csd_struct = UNSTUFF_BITS(resp, 126, 2);
- if (csd_struct != 1 && csd_struct != 2) {
- printk("%s: unrecognised CSD structure version %d\n",
- card->host->host_name, csd_struct);
- mmc_card_set_bad(card);
- return;
+ if (mmc_card_sd(card)) {
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+ if (csd_struct != 0) {
+ printk("%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
+
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+
+ e = UNSTUFF_BITS(resp, 47, 3);
+ m = UNSTUFF_BITS(resp, 62, 12);
+ csd->capacity = (1 + m) << (e + 2);
+
+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ } else {
+ /*
+ * We only understand CSD structure v1.1 and v1.2.
+ * v1.2 has extra information in bits 15, 11 and 10.
+ */
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+ if (csd_struct != 1 && csd_struct != 2) {
+ printk("%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
+
+ csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+
+ e = UNSTUFF_BITS(resp, 47, 3);
+ m = UNSTUFF_BITS(resp, 62, 12);
+ csd->capacity = (1 + m) << (e + 2);
+
+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
}
+}
- csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
- m = UNSTUFF_BITS(resp, 115, 4);
- e = UNSTUFF_BITS(resp, 112, 3);
- csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
- csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static void mmc_decode_scr(struct mmc_card *card)
+{
+ struct sd_scr *scr = &card->scr;
+ unsigned int scr_struct;
+ u32 resp[4];
+
+ BUG_ON(!mmc_card_sd(card));
- m = UNSTUFF_BITS(resp, 99, 4);
- e = UNSTUFF_BITS(resp, 96, 3);
- csd->max_dtr = tran_exp[e] * tran_mant[m];
- csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+ resp[3] = card->raw_scr[1];
+ resp[2] = card->raw_scr[0];
- e = UNSTUFF_BITS(resp, 47, 3);
- m = UNSTUFF_BITS(resp, 62, 12);
- csd->capacity = (1 + m) << (e + 2);
+ scr_struct = UNSTUFF_BITS(resp, 60, 4);
+ if (scr_struct != 0) {
+ printk("%s: unrecognised SCR structure version %d\n",
+ mmc_hostname(card->host), scr_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
- csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+ scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
}
/*
@@ -457,6 +659,11 @@ 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_delay(1);
+
cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0;
cmd.flags = MMC_RSP_NONE;
@@ -464,6 +671,11 @@ static void mmc_idle_cards(struct mmc_host *host)
mmc_wait_for_cmd(host, &cmd, 0);
mmc_delay(1);
+
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ops->set_ios(host, &host->ios);
+
+ mmc_delay(1);
}
/*
@@ -475,7 +687,9 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.vdd = bit;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ 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_delay(1);
@@ -492,7 +706,9 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.clock = 0;
host->ios.vdd = 0;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ 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);
}
@@ -524,6 +740,34 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err;
}
+static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+ struct mmc_command cmd;
+ int i, err = 0;
+
+ cmd.opcode = SD_APP_OP_COND;
+ cmd.arg = ocr;
+ cmd.flags = MMC_RSP_R3;
+
+ for (i = 100; i; i--) {
+ err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ break;
+
+ if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+ break;
+
+ err = MMC_ERR_TIMEOUT;
+
+ mmc_delay(10);
+ }
+
+ if (rocr)
+ *rocr = cmd.resp[0];
+
+ return err;
+}
+
/*
* Discover cards by requesting their CID. If this command
* times out, it is not an error; there are no further cards
@@ -551,7 +795,7 @@ static void mmc_discover_cards(struct mmc_host *host)
}
if (err != MMC_ERR_NONE) {
printk(KERN_ERR "%s: error requesting CID: %d\n",
- host->host_name, err);
+ mmc_hostname(host), err);
break;
}
@@ -567,13 +811,38 @@ static void mmc_discover_cards(struct mmc_host *host)
card->state &= ~MMC_STATE_DEAD;
- cmd.opcode = MMC_SET_RELATIVE_ADDR;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ if (host->mode == MMC_MODE_SD) {
+ mmc_card_set_sd(card);
- err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
- if (err != MMC_ERR_NONE)
- mmc_card_set_dead(card);
+ cmd.opcode = SD_SEND_RELATIVE_ADDR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ mmc_card_set_dead(card);
+ else {
+ card->rca = cmd.resp[0] >> 16;
+
+ if (!host->ops->get_ro) {
+ printk(KERN_WARNING "%s: host does not "
+ "support reading read-only "
+ "switch. assuming write-enable.\n",
+ mmc_hostname(host));
+ } else {
+ if (host->ops->get_ro(host))
+ mmc_card_set_readonly(card);
+ }
+ }
+ } else {
+ cmd.opcode = MMC_SET_RELATIVE_ADDR;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ mmc_card_set_dead(card);
+ }
}
}
@@ -605,6 +874,79 @@ static void mmc_read_csds(struct mmc_host *host)
}
}
+static void mmc_read_scrs(struct mmc_host *host)
+{
+ int err;
+ struct mmc_card *card;
+
+ struct mmc_request mrq;
+ struct mmc_command cmd;
+ struct mmc_data data;
+
+ struct scatterlist sg;
+
+ list_for_each_entry(card, &host->cards, node) {
+ if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+ continue;
+ if (!mmc_card_sd(card))
+ continue;
+
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = MMC_APP_CMD;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = SD_APP_SEND_SCR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ data.timeout_ns = card->csd.tacc_ns * 10;
+ data.timeout_clks = card->csd.tacc_clks * 10;
+ data.blksz_bits = 3;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ sg_init_one(&sg, (u8*)card->raw_scr, 8);
+
+ err = mmc_wait_for_req(host, &mrq);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ card->raw_scr[0] = ntohl(card->raw_scr[0]);
+ card->raw_scr[1] = ntohl(card->raw_scr[1]);
+
+ mmc_decode_scr(card);
+ }
+
+ mmc_deselect_cards(host);
+}
+
static unsigned int mmc_calculate_clock(struct mmc_host *host)
{
struct mmc_card *card;
@@ -657,12 +999,24 @@ static void mmc_setup(struct mmc_host *host)
int err;
u32 ocr;
+ host->mode = MMC_MODE_SD;
+
mmc_power_up(host);
mmc_idle_cards(host);
- err = mmc_send_op_cond(host, 0, &ocr);
- if (err != MMC_ERR_NONE)
- return;
+ err = mmc_send_app_op_cond(host, 0, &ocr);
+
+ /*
+ * If we fail to detect any SD cards then try
+ * searching for MMC cards.
+ */
+ if (err != MMC_ERR_NONE) {
+ host->mode = MMC_MODE_MMC;
+
+ err = mmc_send_op_cond(host, 0, &ocr);
+ if (err != MMC_ERR_NONE)
+ return;
+ }
host->ocr = mmc_select_voltage(host, ocr);
@@ -702,7 +1056,10 @@ static void mmc_setup(struct mmc_host *host)
* all get the idea that they should be ready for CMD2.
* (My SanDisk card seems to need this.)
*/
- mmc_send_op_cond(host, host->ocr, NULL);
+ if (host->mode == MMC_MODE_SD)
+ mmc_send_app_op_cond(host, host->ocr, NULL);
+ else
+ mmc_send_op_cond(host, host->ocr, NULL);
mmc_discover_cards(host);
@@ -713,19 +1070,26 @@ static void mmc_setup(struct mmc_host *host)
host->ops->set_ios(host, &host->ios);
mmc_read_csds(host);
+
+ if (host->mode == MMC_MODE_SD)
+ mmc_read_scrs(host);
}
/**
* mmc_detect_change - process change of state on a MMC socket
* @host: host which changed state.
+ * @delay: optional delay to wait before detection (jiffies)
*
* All we know is that card(s) have been inserted or removed
* from the socket(s). We don't know which socket or cards.
*/
-void mmc_detect_change(struct mmc_host *host)
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
- schedule_work(&host->detect);
+ if (delay)
+ schedule_delayed_work(&host->detect, delay);
+ else
+ schedule_work(&host->detect);
}
EXPORT_SYMBOL(mmc_detect_change);
@@ -796,17 +1160,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
struct mmc_host *host;
- host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ host = mmc_alloc_host_sysfs(extra, dev);
if (host) {
- memset(host, 0, sizeof(struct mmc_host) + extra);
-
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_LIST_HEAD(&host->cards);
INIT_WORK(&host->detect, mmc_rescan, host);
- host->dev = dev;
-
/*
* By default, hosts do not support SGIO or large requests.
* They have to set these according to their abilities.
@@ -828,15 +1188,15 @@ EXPORT_SYMBOL(mmc_alloc_host);
*/
int mmc_add_host(struct mmc_host *host)
{
- static unsigned int host_num;
-
- snprintf(host->host_name, sizeof(host->host_name),
- "mmc%d", host_num++);
+ int ret;
- mmc_power_off(host);
- mmc_detect_change(host);
+ ret = mmc_add_host_sysfs(host);
+ if (ret == 0) {
+ mmc_power_off(host);
+ mmc_detect_change(host, 0);
+ }
- return 0;
+ return ret;
}
EXPORT_SYMBOL(mmc_add_host);
@@ -859,6 +1219,7 @@ void mmc_remove_host(struct mmc_host *host)
}
mmc_power_off(host);
+ mmc_remove_host_sysfs(host);
}
EXPORT_SYMBOL(mmc_remove_host);
@@ -872,7 +1233,7 @@ EXPORT_SYMBOL(mmc_remove_host);
void mmc_free_host(struct mmc_host *host)
{
flush_scheduled_work();
- kfree(host);
+ mmc_free_host_sysfs(host);
}
EXPORT_SYMBOL(mmc_free_host);
@@ -902,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
*/
int mmc_resume_host(struct mmc_host *host)
{
- mmc_detect_change(host);
+ mmc_detect_change(host, 0);
return 0;
}
diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h
index b498dffe0b11..97bae00292fa 100644
--- a/drivers/mmc/mmc.h
+++ b/drivers/mmc/mmc.h
@@ -13,4 +13,9 @@
void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
int mmc_register_card(struct mmc_card *card);
void mmc_remove_card(struct mmc_card *card);
+
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
+int mmc_add_host_sysfs(struct mmc_host *host);
+void mmc_remove_host_sysfs(struct mmc_host *host);
+void mmc_free_host_sysfs(struct mmc_host *host);
#endif
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index d4eee99c2bf6..fa83f15fdf16 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
if (md->usage == 2)
check_disk_change(inode->i_bdev);
ret = 0;
+
+ if ((filp->f_mode & FMODE_WRITE) &&
+ mmc_card_readonly(md->queue.card))
+ ret = -EROFS;
}
return ret;
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- printk(KERN_INFO "%s: %s %s %dKiB\n",
+ printk(KERN_INFO "%s: %s %s %dKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- (card->csd.capacity << card->csd.read_blkbits) / 1024);
+ (card->csd.capacity << card->csd.read_blkbits) / 1024,
+ mmc_card_readonly(card)?"(ro)":"");
mmc_set_drvdata(card, md);
add_disk(md->disk);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 5556cd3b5559..3f4a66ca9555 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/idr.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -20,6 +21,7 @@
#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
#define MMC_ATTR(name, fmt, args...) \
static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
@@ -32,6 +34,7 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
card->raw_cid[2], card->raw_cid[3]);
MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
@@ -55,6 +58,8 @@ static struct device_attribute mmc_dev_attrs[] = {
__ATTR_NULL
};
+static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
+
static void mmc_release_card(struct device *dev)
{
@@ -205,10 +210,20 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
*/
int mmc_register_card(struct mmc_card *card)
{
- snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
- "%s:%04x", card->host->host_name, card->rca);
+ int ret;
- return device_add(&card->dev);
+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+ "%s:%04x", mmc_hostname(card->host), card->rca);
+
+ ret = device_add(&card->dev);
+ if (ret == 0) {
+ if (mmc_card_sd(card)) {
+ ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
+ if (ret)
+ device_del(&card->dev);
+ }
+ }
+ return ret;
}
/*
@@ -217,20 +232,108 @@ int mmc_register_card(struct mmc_card *card)
*/
void mmc_remove_card(struct mmc_card *card)
{
- if (mmc_card_present(card))
+ if (mmc_card_present(card)) {
+ if (mmc_card_sd(card))
+ device_remove_file(&card->dev, &mmc_dev_attr_scr);
+
device_del(&card->dev);
+ }
put_device(&card->dev);
}
+static void mmc_host_classdev_release(struct class_device *dev)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ kfree(host);
+}
+
+static struct class mmc_host_class = {
+ .name = "mmc_host",
+ .release = mmc_host_classdev_release,
+};
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/*
+ * Internal function. Allocate a new MMC host.
+ */
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
+{
+ struct mmc_host *host;
+
+ host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ if (host) {
+ memset(host, 0, sizeof(struct mmc_host) + extra);
+
+ host->dev = dev;
+ host->class_dev.dev = host->dev;
+ host->class_dev.class = &mmc_host_class;
+ class_device_initialize(&host->class_dev);
+ }
+
+ return host;
+}
+
+/*
+ * Internal function. Register a new MMC host with the MMC class.
+ */
+int mmc_add_host_sysfs(struct mmc_host *host)
+{
+ int err;
+
+ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&mmc_host_lock);
+ err = idr_get_new(&mmc_host_idr, host, &host->index);
+ spin_unlock(&mmc_host_lock);
+ if (err)
+ return err;
+
+ snprintf(host->class_dev.class_id, BUS_ID_SIZE,
+ "mmc%d", host->index);
+
+ return class_device_add(&host->class_dev);
+}
+
+/*
+ * Internal function. Unregister a MMC host with the MMC class.
+ */
+void mmc_remove_host_sysfs(struct mmc_host *host)
+{
+ class_device_del(&host->class_dev);
+
+ spin_lock(&mmc_host_lock);
+ idr_remove(&mmc_host_idr, host->index);
+ spin_unlock(&mmc_host_lock);
+}
+
+/*
+ * Internal function. Free a MMC host.
+ */
+void mmc_free_host_sysfs(struct mmc_host *host)
+{
+ class_device_put(&host->class_dev);
+}
+
+
static int __init mmc_init(void)
{
- return bus_register(&mmc_bus_type);
+ int ret = bus_register(&mmc_bus_type);
+ if (ret == 0) {
+ ret = class_register(&mmc_host_class);
+ if (ret)
+ bus_unregister(&mmc_bus_type);
+ }
+ return ret;
}
static void __exit mmc_exit(void)
{
+ class_unregister(&mmc_host_class);
bus_unregister(&mmc_bus_type);
}
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 7a42966d755b..91c74843dc0d 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_MMC_DEBUG
#define DBG(host,fmt,args...) \
- pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args)
+ pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
#else
#define DBG(host,fmt,args...) do { } while (0)
#endif
@@ -442,7 +442,7 @@ static void mmci_check_status(unsigned long data)
status = host->plat->status(mmc_dev(host->mmc));
if (status ^ host->oldstat)
- mmc_detect_change(host->mmc);
+ mmc_detect_change(host->mmc, 0);
host->oldstat = status;
mod_timer(&host->timer, jiffies + HZ);
@@ -541,7 +541,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
mmc_add_host(mmc);
printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n",
- mmc->host_name, amba_rev(dev), amba_config(dev),
+ mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
dev->res.start, dev->irq[0], dev->irq[1]);
init_timer(&host->timer);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index b78beb1b0159..b53af57074e3 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -362,6 +362,16 @@ static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
pxamci_start_cmd(host, mrq->cmd, cmdat);
}
+static int pxamci_get_ro(struct mmc_host *mmc)
+{
+ struct pxamci_host *host = mmc_priv(mmc);
+
+ if (host->pdata && host->pdata->get_ro)
+ return host->pdata->get_ro(mmc->dev);
+ /* Host doesn't support read only detection so assume writeable */
+ return 0;
+}
+
static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct pxamci_host *host = mmc_priv(mmc);
@@ -401,6 +411,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static struct mmc_host_ops pxamci_ops = {
.request = pxamci_request,
+ .get_ro = pxamci_get_ro,
.set_ios = pxamci_set_ios,
};
@@ -412,7 +423,9 @@ static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs)
static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs)
{
- mmc_detect_change(devid);
+ struct pxamci_host *host = mmc_priv(devid);
+
+ mmc_detect_change(devid, host->pdata->detect_delay);
return IRQ_HANDLED;
}
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 974f2f36bdbe..3cbca7cbea80 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -42,7 +42,7 @@
#include "wbsd.h"
#define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.3"
+#define DRIVER_VERSION "1.4"
#ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \
@@ -93,7 +93,7 @@ static int dma = 2;
static inline void wbsd_unlock_config(struct wbsd_host* host)
{
BUG_ON(host->config == 0);
-
+
outb(host->unlock_code, host->config);
outb(host->unlock_code, host->config);
}
@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
static inline void wbsd_lock_config(struct wbsd_host* host)
{
BUG_ON(host->config == 0);
-
+
outb(LOCK_CODE, host->config);
}
static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
{
BUG_ON(host->config == 0);
-
+
outb(reg, host->config);
outb(value, host->config + 1);
}
@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
{
BUG_ON(host->config == 0);
-
+
outb(reg, host->config);
return inb(host->config + 1);
}
@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
static void wbsd_init_device(struct wbsd_host* host)
{
u8 setup, ier;
-
+
/*
* Reset chip (SD/MMC part) and fifo.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
/*
* Set DAT3 to input
*/
setup &= ~WBSD_DAT3_H;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
host->flags &= ~WBSD_FIGNORE_DETECT;
-
+
/*
* Read back default clock.
*/
@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
* Power down port.
*/
outb(WBSD_POWER_N, host->base + WBSD_CSR);
-
+
/*
* Set maximum timeout.
*/
wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
-
+
/*
* Test for card presence
*/
@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
host->flags |= WBSD_FCARD_PRESENT;
else
host->flags &= ~WBSD_FCARD_PRESENT;
-
+
/*
* Enable interesting interrupts.
*/
@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
static void wbsd_reset(struct wbsd_host* host)
{
u8 setup;
-
+
printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
-
+
/*
* Soft reset of chip (SD/MMC part).
*/
@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
{
unsigned long dmaflags;
-
+
DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
+
if (host->dma >= 0)
{
/*
@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
}
-
+
host->mrq = NULL;
/*
@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
host->offset = 0;
host->remain = host->cur_sg->length;
}
-
+
return host->num_sg;
}
@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg;
char* dmabuf = host->dma_buffer;
char* sgbuf;
-
+
size = host->size;
-
+
sg = data->sg;
len = data->sg_len;
-
+
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
memcpy(dmabuf, sgbuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length;
-
+
if (size < sg[i].length)
size = 0;
else
size -= sg[i].length;
-
+
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);
-
+
host->size -= size;
}
@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg;
char* dmabuf = host->dma_buffer;
char* sgbuf;
-
+
size = host->size;
-
+
sg = data->sg;
len = data->sg_len;
-
+
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
memcpy(sgbuf, dmabuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length;
-
+
if (size < sg[i].length)
size = 0;
else
size -= sg[i].length;
-
+
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);
-
+
host->size -= size;
}
/*
* Command handling
*/
-
+
static inline void wbsd_get_short_reply(struct wbsd_host* host,
struct mmc_command* cmd)
{
@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID;
return;
}
-
+
cmd->resp[0] =
wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
cmd->resp[0] |=
@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
struct mmc_command* cmd)
{
int i;
-
+
/*
* Correct response type?
*/
@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID;
return;
}
-
+
for (i = 0;i < 4;i++)
{
cmd->resp[i] =
@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
{
int i;
u8 status, isr;
-
+
DBGF("Sending cmd (%x)\n", cmd->opcode);
/*
@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* transfer.
*/
host->isr = 0;
-
+
/*
* Send the command (CRC calculated by host).
*/
outb(cmd->opcode, host->base + WBSD_CMDR);
for (i = 3;i >= 0;i--)
outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
-
+
cmd->error = MMC_ERR_NONE;
-
+
/*
* Wait for the request to complete.
*/
@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Read back status.
*/
isr = host->isr;
-
+
/* Card removed? */
if (isr & WBSD_INT_CARD)
cmd->error = MMC_ERR_TIMEOUT;
@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data;
char* buffer;
int i, fsr, fifo;
-
+
/*
* Handle excessive data.
*/
if (data->bytes_xfered == host->size)
return;
-
+
buffer = wbsd_kmap_sg(host) + host->offset;
/*
@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
- */
+ */
if (fsr & WBSD_FIFO_FULL)
fifo = 16;
else if (fsr & WBSD_FIFO_FUTHRE)
fifo = 8;
else
fifo = 1;
-
+
for (i = 0;i < fifo;i++)
{
*buffer = inb(host->base + WBSD_DFR);
@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
host->remain--;
data->bytes_xfered++;
-
+
/*
* Transfer done?
*/
if (data->bytes_xfered == host->size)
{
- wbsd_kunmap_sg(host);
+ wbsd_kunmap_sg(host);
return;
}
-
+
/*
* End of scatter list entry?
*/
if (host->remain == 0)
{
wbsd_kunmap_sg(host);
-
+
/*
* Get next entry. Check if last.
*/
@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON(1);
-
+
host->size = data->bytes_xfered;
-
+
return;
}
-
+
buffer = wbsd_kmap_sg(host);
}
}
}
-
+
wbsd_kunmap_sg(host);
/*
@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data;
char* buffer;
int i, fsr, fifo;
-
+
/*
* Check that we aren't being called after the
* entire buffer has been transfered.
@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
- */
+ */
if (fsr & WBSD_FIFO_EMPTY)
fifo = 0;
else if (fsr & WBSD_FIFO_EMTHRE)
@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
buffer++;
host->offset++;
host->remain--;
-
+
data->bytes_xfered++;
-
+
/*
* Transfer done?
*/
@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
if (host->remain == 0)
{
wbsd_kunmap_sg(host);
-
+
/*
* Get next entry. Check if last.
*/
@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON(1);
-
+
host->size = data->bytes_xfered;
-
+
return;
}
-
+
buffer = wbsd_kmap_sg(host);
}
}
}
-
+
wbsd_kunmap_sg(host);
-
+
/*
* The controller stops sending interrupts for
* 'FIFO empty' under certain conditions. So we
@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
1 << data->blksz_bits, data->blocks, data->flags);
DBGF("tsac %d ms nsac %d clk\n",
data->timeout_ns / 1000000, data->timeout_clks);
-
+
/*
* Calculate size.
*/
@@ -708,23 +708,40 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
wbsd_write_index(host, WBSD_IDX_TAAC, 127);
else
wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
-
+
if (data->timeout_clks > 255)
wbsd_write_index(host, WBSD_IDX_NSAC, 255);
else
wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
-
+
/*
* Inform the chip of how large blocks will be
* sent. It needs this to determine when to
* calculate CRC.
*
* Space for CRC must be included in the size.
+ * Two bytes are needed for each data line.
*/
- blksize = (1 << data->blksz_bits) + 2;
-
- wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
- wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+ if (host->bus_width == MMC_BUS_WIDTH_1)
+ {
+ blksize = (1 << data->blksz_bits) + 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;
+
+ wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
+ | WBSD_DATA_WIDTH);
+ wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+ }
+ else
+ {
+ data->error = MMC_ERR_INVALID;
+ return;
+ }
/*
* Clear the FIFO. This is needed even for DMA
@@ -734,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
/*
* DMA transfer?
*/
if (host->dma >= 0)
- {
+ {
/*
* The buffer for DMA is only 64 kB.
*/
@@ -749,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data->error = MMC_ERR_INVALID;
return;
}
-
+
/*
* Transfer data from the SG list to
* the DMA buffer.
*/
if (data->flags & MMC_DATA_WRITE)
wbsd_sg_to_dma(host, data);
-
+
/*
* Initialise the ISA DMA controller.
- */
+ */
dmaflags = claim_dma_lock();
disable_dma(host->dma);
clear_dma_ff(host->dma);
@@ -785,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* output to a minimum.
*/
host->firsterr = 1;
-
+
/*
* Initialise the SG list.
*/
wbsd_init_sg(host, data);
-
+
/*
* Turn off DMA.
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
+
/*
* Set up FIFO threshold levels (and fill
* buffer if doing a write).
@@ -811,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
WBSD_FIFOEN_EMPTY | 8);
wbsd_fill_fifo(host);
}
- }
-
+ }
+
data->error = MMC_ERR_NONE;
}
@@ -821,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
unsigned long dmaflags;
int count;
u8 status;
-
+
WARN_ON(host->mrq == NULL);
/*
@@ -838,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
status = wbsd_read_index(host, WBSD_IDX_STATUS);
} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
-
+
/*
* DMA transfer?
*/
@@ -848,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Disable DMA on the host.
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
+
/*
* Turn of ISA DMA controller.
*/
@@ -857,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
clear_dma_ff(host->dma);
count = get_dma_residue(host->dma);
release_dma_lock(dmaflags);
-
+
/*
* Any leftover data?
*/
@@ -865,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
"transfer. %d bytes left.\n", count);
-
+
data->error = MMC_ERR_FAILED;
}
else
@@ -876,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
*/
if (data->flags & MMC_DATA_READ)
wbsd_dma_to_sg(host, data);
-
+
data->bytes_xfered = host->size;
}
}
-
+
DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
+
wbsd_request_end(host, host->mrq);
}
@@ -907,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
cmd = mrq->cmd;
host->mrq = mrq;
-
+
/*
* If there is no card in the slot then
* timeout immediatly.
@@ -924,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
if (cmd->data)
{
wbsd_prepare_data(host, cmd->data);
-
+
if (cmd->data->error != MMC_ERR_NONE)
goto done;
}
-
+
wbsd_send_command(host, cmd);
/*
* If this is a data transfer the request
* will be finished after the data has
* transfered.
- */
+ */
if (cmd->data && (cmd->error == MMC_ERR_NONE))
{
/*
@@ -948,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
return;
}
-
+
done:
wbsd_request_end(host, mrq);
@@ -959,9 +976,10 @@ 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 Vdd %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+ 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);
@@ -971,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
*/
if (ios->power_mode == MMC_POWER_OFF)
wbsd_init_device(host);
-
+
if (ios->clock >= 24000000)
clk = WBSD_CLK_24M;
else if (ios->clock >= 16000000)
@@ -1003,30 +1021,63 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
/*
* MMC cards need to have pin 1 high during init.
- * Init time corresponds rather nicely with the bus mode.
* It wreaks havoc with the card detection though so
- * that needs to be disabed.
+ * that needs to be disabled.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
- if ((ios->power_mode == MMC_POWER_ON) &&
- (ios->bus_mode == MMC_BUSMODE_OPENDRAIN))
+ if (ios->chip_select == MMC_CS_HIGH)
{
+ BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
setup |= WBSD_DAT3_H;
host->flags |= WBSD_FIGNORE_DETECT;
}
else
{
setup &= ~WBSD_DAT3_H;
- host->flags &= ~WBSD_FIGNORE_DETECT;
+
+ /*
+ * We cannot resume card detection immediatly
+ * because of capacitance and delays in the chip.
+ */
+ mod_timer(&host->ignore_timer, jiffies + HZ/100);
}
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
+ /*
+ * Store bus width for later. Will be used when
+ * setting up the data transfer.
+ */
+ host->bus_width = ios->bus_width;
+
+ spin_unlock_bh(&host->lock);
+}
+
+static int wbsd_get_ro(struct mmc_host* mmc)
+{
+ struct wbsd_host* host = mmc_priv(mmc);
+ u8 csr;
+
+ spin_lock_bh(&host->lock);
+
+ csr = inb(host->base + WBSD_CSR);
+ csr |= WBSD_MSLED;
+ outb(csr, host->base + WBSD_CSR);
+
+ mdelay(1);
+
+ csr = inb(host->base + WBSD_CSR);
+ csr &= ~WBSD_MSLED;
+ outb(csr, host->base + WBSD_CSR);
+
spin_unlock_bh(&host->lock);
+
+ return csr & WBSD_WRPT;
}
static struct mmc_host_ops wbsd_ops = {
.request = wbsd_request,
.set_ios = wbsd_set_ios,
+ .get_ro = wbsd_get_ro,
};
/*****************************************************************************\
@@ -1036,17 +1087,28 @@ static struct mmc_host_ops wbsd_ops = {
\*****************************************************************************/
/*
- * Helper function for card detection
+ * Helper function to reset detection ignore
*/
-static void wbsd_detect_card(unsigned long data)
+
+static void wbsd_reset_ignore(unsigned long data)
{
struct wbsd_host *host = (struct wbsd_host*)data;
-
+
BUG_ON(host == NULL);
-
- DBG("Executing card detection\n");
-
- mmc_detect_change(host->mmc);
+
+ DBG("Resetting card detection ignore\n");
+
+ spin_lock_bh(&host->lock);
+
+ host->flags &= ~WBSD_FIGNORE_DETECT;
+
+ /*
+ * Card status might have changed during the
+ * blackout.
+ */
+ tasklet_schedule(&host->card_tasklet);
+
+ spin_unlock_bh(&host->lock);
}
/*
@@ -1066,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
WARN_ON(!host->mrq->cmd->data);
if (!host->mrq->cmd->data)
return NULL;
-
+
return host->mrq->cmd->data;
}
@@ -1074,68 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr;
-
+ int delay = -1;
+
spin_lock(&host->lock);
-
+
if (host->flags & WBSD_FIGNORE_DETECT)
{
spin_unlock(&host->lock);
return;
}
-
+
csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff);
-
+
if (csr & WBSD_CARDPRESENT)
{
if (!(host->flags & WBSD_FCARD_PRESENT))
{
DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT;
-
- /*
- * Delay card detection to allow electrical connections
- * to stabilise.
- */
- mod_timer(&host->timer, jiffies + HZ/2);
+
+ delay = 500;
}
-
- spin_unlock(&host->lock);
}
else if (host->flags & WBSD_FCARD_PRESENT)
{
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
-
+
if (host->mrq)
{
printk(KERN_ERR DRIVER_NAME
": Card removed during transfer!\n");
wbsd_reset(host);
-
+
host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet);
}
-
- /*
- * Unlock first since we might get a call back.
- */
- spin_unlock(&host->lock);
- mmc_detect_change(host->mmc);
+ delay = 0;
}
+
+ /*
+ * Unlock first since we might get a call back.
+ */
+
+ spin_unlock(&host->lock);
+
+ if (delay != -1)
+ mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
}
static void wbsd_tasklet_fifo(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
@@ -1154,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
tasklet_schedule(&host->finish_tasklet);
}
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1162,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC;
-
+
tasklet_schedule(&host->finish_tasklet);
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1186,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("Timeout\n");
data->error = MMC_ERR_TIMEOUT;
-
+
tasklet_schedule(&host->finish_tasklet);
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1210,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
WARN_ON(!host->mrq);
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
wbsd_finish_data(host, data);
-
-end:
+
+end:
spin_unlock(&host->lock);
}
@@ -1231,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
@@ -1240,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param)
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC;
-
+
tasklet_schedule(&host->finish_tasklet);
}
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1260,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct wbsd_host* host = dev_id;
int isr;
-
+
isr = inb(host->base + WBSD_ISR);
/*
@@ -1268,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
*/
if (isr == 0xff || isr == 0x00)
return IRQ_NONE;
-
+
host->isr |= isr;
/*
@@ -1286,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
tasklet_hi_schedule(&host->block_tasklet);
if (isr & WBSD_INT_TC)
tasklet_schedule(&host->finish_tasklet);
-
+
return IRQ_HANDLED;
}
@@ -1304,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
{
struct mmc_host* mmc;
struct wbsd_host* host;
-
+
/*
* Allocate MMC structure.
*/
mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
if (!mmc)
return -ENOMEM;
-
+
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -1324,37 +1385,38 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc->f_min = 375000;
mmc->f_max = 24000000;
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
-
+ mmc->caps = MMC_CAP_4_BIT_DATA;
+
spin_lock_init(&host->lock);
-
+
/*
- * Set up detection timer
+ * Set up timers
*/
- init_timer(&host->timer);
- host->timer.data = (unsigned long)host;
- host->timer.function = wbsd_detect_card;
-
+ init_timer(&host->ignore_timer);
+ host->ignore_timer.data = (unsigned long)host;
+ host->ignore_timer.function = wbsd_reset_ignore;
+
/*
* Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512.
*/
mmc->max_hw_segs = 128;
mmc->max_phys_segs = 128;
-
+
/*
* Maximum number of sectors in one transfer. Also limited by 64kB
* buffer.
*/
mmc->max_sectors = 128;
-
+
/*
* Maximum segment size. Could be one segment with the maximum number
* of segments.
*/
mmc->max_seg_size = mmc->max_sectors * 512;
-
+
dev_set_drvdata(dev, mmc);
-
+
return 0;
}
@@ -1362,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
{
struct mmc_host* mmc;
struct wbsd_host* host;
-
+
mmc = dev_get_drvdata(dev);
if (!mmc)
return;
-
+
host = mmc_priv(mmc);
BUG_ON(host == NULL);
-
- del_timer_sync(&host->timer);
-
+
+ del_timer_sync(&host->ignore_timer);
+
mmc_free_host(mmc);
-
+
dev_set_drvdata(dev, NULL);
}
@@ -1385,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
int i, j, k;
int id;
-
+
/*
* Iterate through all ports, all codes to
* find hardware that is in our known list.
@@ -1394,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
if (!request_region(config_ports[i], 2, DRIVER_NAME))
continue;
-
+
for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
{
id = 0xFFFF;
-
+
outb(unlock_codes[j], config_ports[i]);
outb(unlock_codes[j], config_ports[i]);
-
+
outb(WBSD_CONF_ID_HI, config_ports[i]);
id = inb(config_ports[i] + 1) << 8;
outb(WBSD_CONF_ID_LO, config_ports[i]);
id |= inb(config_ports[i] + 1);
-
+
for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
{
if (id == valid_ids[k])
- {
+ {
host->chip_id = id;
host->config = config_ports[i];
host->unlock_code = unlock_codes[i];
-
+
return 0;
}
}
-
+
if (id != 0xFFFF)
{
DBG("Unknown hardware (id %x) found at %x\n",
@@ -1428,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
outb(LOCK_CODE, config_ports[i]);
}
-
+
release_region(config_ports[i], 2);
}
-
+
return -ENODEV;
}
@@ -1443,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
{
if (io & 0x7)
return -EINVAL;
-
+
if (!request_region(base, 8, DRIVER_NAME))
return -EIO;
-
+
host->base = io;
-
+
return 0;
}
@@ -1456,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
{
if (host->base)
release_region(host->base, 8);
-
+
host->base = 0;
if (host->config)
release_region(host->config, 2);
-
+
host->config = 0;
}
@@ -1473,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
{
if (dma < 0)
return;
-
+
if (request_dma(dma, DRIVER_NAME))
goto err;
-
+
/*
* We need to allocate a special buffer in
* order for ISA to be able to DMA to it.
@@ -1491,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
*/
host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-
+
/*
* ISA DMA must be aligned on a 64k basis.
*/
@@ -1504,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
goto kfree;
host->dma = dma;
-
+
return;
-
+
kfree:
/*
* If we've gotten here then there is some kind of alignment bug
*/
BUG_ON(1);
-
+
dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL;
-
+
kfree(host->dma_buffer);
host->dma_buffer = NULL;
@@ -1537,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
kfree(host->dma_buffer);
if (host->dma >= 0)
free_dma(host->dma);
-
+
host->dma = -1;
host->dma_buffer = NULL;
host->dma_addr = (dma_addr_t)NULL;
@@ -1550,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
{
int ret;
-
+
/*
* Allocate interrupt.
*/
@@ -1558,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
if (ret)
return ret;
-
+
host->irq = irq;
/*
@@ -1570,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
-
+
return 0;
}
@@ -1580,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
return;
free_irq(host->irq, host);
-
+
host->irq = 0;
-
+
tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->fifo_tasklet);
tasklet_kill(&host->crc_tasklet);
@@ -1599,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
int base, int irq, int dma)
{
int ret;
-
+
/*
* Allocate I/O ports.
*/
@@ -1618,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Allocate DMA.
*/
wbsd_request_dma(host, dma);
-
+
return 0;
}
@@ -1641,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
{
/*
* Reset the chip.
- */
+ */
wbsd_write_config(host, WBSD_CONF_SWRST, 1);
wbsd_write_config(host, WBSD_CONF_SWRST, 0);
@@ -1649,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
* Select SD/MMC function.
*/
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
+
/*
* Set up card detection.
*/
wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
-
+
/*
* Configure chip
*/
wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-
+
wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
-
+
if (host->dma >= 0)
wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
-
+
/*
* Enable and power up chip.
*/
@@ -1676,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
/*
* Check that configured resources are correct.
*/
-
+
static int __devinit wbsd_chip_validate(struct wbsd_host* host)
{
int base, irq, dma;
-
+
/*
* Select SD/MMC function.
*/
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
+
/*
* Read configuration.
*/
base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
-
+
irq = wbsd_read_config(host, WBSD_CONF_IRQ);
-
+
dma = wbsd_read_config(host, WBSD_CONF_DRQ);
-
+
/*
* Validate against given configuration.
*/
@@ -1705,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
return 0;
if ((dma != host->dma) && (host->dma != -1))
return 0;
-
+
return 1;
}
@@ -1721,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
struct wbsd_host* host = NULL;
struct mmc_host* mmc = NULL;
int ret;
-
+
ret = wbsd_alloc_mmc(dev);
if (ret)
return ret;
-
+
mmc = dev_get_drvdata(dev);
host = mmc_priv(mmc);
-
+
/*
* Scan for hardware.
*/
@@ -1747,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return ret;
}
}
-
+
/*
* Request resources.
*/
@@ -1758,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
wbsd_free_mmc(dev);
return ret;
}
-
+
/*
* See if chip needs to be configured.
*/
@@ -1775,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
}
else
wbsd_chip_config(host);
-
+
/*
* Power Management stuff. No idea how this works.
* Not tested.
@@ -1793,10 +1855,10 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Reset the chip into a known state.
*/
wbsd_init_device(host);
-
+
mmc_add_host(mmc);
- printk(KERN_INFO "%s: W83L51xD", mmc->host_name);
+ printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
if (host->chip_id != 0)
printk(" id %x", (int)host->chip_id);
printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
@@ -1815,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
{
struct mmc_host* mmc = dev_get_drvdata(dev);
struct wbsd_host* host;
-
+
if (!mmc)
return;
host = mmc_priv(mmc);
-
+
mmc_remove_host(mmc);
if (!pnp)
@@ -1833,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
wbsd_lock_config(host);
}
-
+
wbsd_release_resources(host);
-
+
wbsd_free_mmc(dev);
}
@@ -1865,7 +1927,7 @@ static int __devinit
wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
{
int io, irq, dma;
-
+
/*
* Get resources from PnP layer.
*/
@@ -1875,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
dma = pnp_dma(pnpdev, 0);
else
dma = -1;
-
+
DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
-
+
return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
}
@@ -1918,7 +1980,7 @@ static struct device_driver wbsd_driver = {
.bus = &platform_bus_type,
.probe = wbsd_probe,
.remove = wbsd_remove,
-
+
.suspend = wbsd_suspend,
.resume = wbsd_resume,
};
@@ -1941,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = {
static int __init wbsd_drv_init(void)
{
int result;
-
+
printk(KERN_INFO DRIVER_NAME
": Winbond W83L51xD SD/MMC card interface driver, "
DRIVER_VERSION "\n");
@@ -1956,8 +2018,8 @@ static int __init wbsd_drv_init(void)
return result;
}
-#endif /* CONFIG_PNP */
-
+#endif /* CONFIG_PNP */
+
if (nopnp)
{
result = driver_register(&wbsd_driver);
@@ -1979,13 +2041,13 @@ static void __exit wbsd_drv_exit(void)
if (!nopnp)
pnp_unregister_driver(&wbsd_pnp_driver);
-
-#endif /* CONFIG_PNP */
+
+#endif /* CONFIG_PNP */
if (nopnp)
{
platform_device_unregister(wbsd_device);
-
+
driver_unregister(&wbsd_driver);
}
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 661a9f6a6e6f..249baa701cb0 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -106,6 +106,8 @@
#define WBSD_CLK_16M 0x02
#define WBSD_CLK_24M 0x03
+#define WBSD_DATA_WIDTH 0x01
+
#define WBSD_DAT3_H 0x08
#define WBSD_FIFO_RESET 0x04
#define WBSD_SOFT_RESET 0x02
@@ -137,49 +139,50 @@
struct wbsd_host
{
struct mmc_host* mmc; /* MMC structure */
-
+
spinlock_t lock; /* Mutex */
int flags; /* Driver states */
#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */
#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */
-
+
struct mmc_request* mrq; /* Current request */
-
+
u8 isr; /* Accumulated ISR */
-
+
struct scatterlist* cur_sg; /* Current SG entry */
unsigned int num_sg; /* Number of entries left */
void* mapped_sg; /* vaddr of mapped sg */
-
+
unsigned int offset; /* Offset into current entry */
unsigned int remain; /* Data left in curren entry */
int size; /* Total size of transfer */
-
+
char* dma_buffer; /* ISA DMA buffer */
dma_addr_t dma_addr; /* Physical address for same */
int firsterr; /* See fifo functions */
-
+
u8 clk; /* Current clock speed */
-
+ unsigned char bus_width; /* Current bus width */
+
int config; /* Config port */
u8 unlock_code; /* Code to unlock config */
int chip_id; /* ID of controller */
-
+
int base; /* I/O port base */
int irq; /* Interrupt */
int dma; /* DMA channel */
-
+
struct tasklet_struct card_tasklet; /* Tasklet structures */
struct tasklet_struct fifo_tasklet;
struct tasklet_struct crc_tasklet;
struct tasklet_struct timeout_tasklet;
struct tasklet_struct finish_tasklet;
struct tasklet_struct block_tasklet;
-
- struct timer_list timer; /* Card detection timer */
+
+ struct timer_list ignore_timer; /* Ignore detection timer */
};
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index bb713fed2f37..1443117fd8f4 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -91,8 +91,7 @@ static void __exit cleanup_mtdram(void)
{
if (mtd_info) {
del_mtd_device(mtd_info);
- if (mtd_info->priv)
- vfree(mtd_info->priv);
+ vfree(mtd_info->priv);
kfree(mtd_info);
}
}
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index d9ab60b36fd4..d32c1b3a8ce3 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1017,27 +1017,16 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
void ftl_freepart(partition_t *part)
{
- if (part->VirtualBlockMap) {
vfree(part->VirtualBlockMap);
part->VirtualBlockMap = NULL;
- }
- if (part->VirtualPageMap) {
kfree(part->VirtualPageMap);
part->VirtualPageMap = NULL;
- }
- if (part->EUNInfo) {
kfree(part->EUNInfo);
part->EUNInfo = NULL;
- }
- if (part->XferInfo) {
kfree(part->XferInfo);
part->XferInfo = NULL;
- }
- if (part->bam_cache) {
kfree(part->bam_cache);
part->bam_cache = NULL;
- }
-
} /* ftl_freepart */
static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 811d92e5f5b1..cc372136e852 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -25,9 +25,6 @@
/****************************************************************************/
-
-/****************************************************************************/
-
struct map_info uclinux_ram_map = {
.name = "RAM",
};
@@ -60,14 +57,15 @@ int __init uclinux_mtd_init(void)
struct mtd_info *mtd;
struct map_info *mapp;
extern char _ebss;
+ unsigned long addr = (unsigned long) &_ebss;
mapp = &uclinux_ram_map;
- mapp->phys = (unsigned long) &_ebss;
- mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
+ mapp->phys = addr;
+ mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
mapp->bankwidth = 4;
printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
- (int) mapp->map_priv_2, (int) mapp->size);
+ (int) mapp->phys, (int) mapp->size);
mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
@@ -95,7 +93,6 @@ int __init uclinux_mtd_init(void)
printk("uclinux[mtd]: set %s to be root filesystem\n",
uclinux_romfs[0].name);
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
- put_mtd_device(mtd);
return(0);
}
@@ -109,7 +106,7 @@ void __exit uclinux_mtd_cleanup(void)
map_destroy(uclinux_ram_mtdinfo);
uclinux_ram_mtdinfo = NULL;
}
- if (uclinux_ram_map.map_priv_1) {
+ if (uclinux_ram_map.virt) {
iounmap((void *) uclinux_ram_map.virt);
uclinux_ram_map.virt = 0;
}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index eee5115658c8..04e54318bc6a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -526,6 +526,7 @@ static void nand_wait_ready(struct mtd_info *mtd)
do {
if (this->dev_ready(mtd))
return;
+ touch_softlockup_watchdog();
} while (time_before(jiffies, timeo));
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 07746b95fd83..455ba915ede7 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -973,6 +973,11 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
netif_device_detach(dev);
vortex_down(dev, 1);
}
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+ free_irq(dev->irq, dev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
return 0;
}
@@ -980,8 +985,19 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
static int vortex_resume (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ struct vortex_private *vp = netdev_priv(dev);
- if (dev && dev->priv) {
+ if (dev && vp) {
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ if (request_irq(dev->irq, vp->full_bus_master_rx ?
+ &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
+ printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+ pci_disable_device(pdev);
+ return -EBUSY;
+ }
if (netif_running(dev)) {
vortex_up(dev);
netif_device_attach(dev);
@@ -1873,6 +1889,7 @@ vortex_timer(unsigned long data)
{
spin_lock_bh(&vp->lock);
mii_status = mdio_read(dev, vp->phys[0], 1);
+ mii_status = mdio_read(dev, vp->phys[0], 1);
ok = 1;
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8edb6936fb9b..54fff9c2e802 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -131,6 +131,8 @@ config NET_SB1000
source "drivers/net/arcnet/Kconfig"
+source "drivers/net/phy/Kconfig"
+
#
# Ethernet
#
@@ -395,7 +397,7 @@ config SUN3LANCE
If you're not building a kernel for a Sun 3, say N.
config SUN3_82586
- tristate "Sun3 on-board Intel 82586 support"
+ bool "Sun3 on-board Intel 82586 support"
depends on NET_ETHERNET && SUN3
help
This driver enables support for the on-board Intel 82586 based
@@ -445,7 +447,7 @@ config NET_SB1250_MAC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && PCI && SGI_IP27
+ depends on NET_ETHERNET && PCI && SGI_IP27 && BROKEN
select CRC32
select MII
help
@@ -1736,11 +1738,18 @@ config 68360_ENET
the Motorola 68360 processor.
config FEC
- bool "FEC ethernet controller (of ColdFire 5272)"
- depends on M5272 || M5282
+ bool "FEC ethernet controller (of ColdFire CPUs)"
+ depends on M523x || M527x || M5272 || M528x
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
- controller on the Motorola ColdFire 5272 processor.
+ controller on some Motorola ColdFire processors.
+
+config FEC2
+ bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+ depends on FEC
+ help
+ Say Y here if you want to use the second built-in 10/100 Fast
+ ethernet controller on some Motorola ColdFire processors.
config NE_H8300
tristate "NE2000 compatible support for H8/300"
@@ -1921,6 +1930,20 @@ config R8169_VLAN
If in doubt, say Y.
+config SIS190
+ tristate "SiS190/SiS191 gigabit ethernet support"
+ depends on PCI
+ select CRC32
+ select MII
+ ---help---
+ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+ appear in lan on motherboard designs which are based on SiS 965
+ and SiS 966 south bridge.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sis190. This is recommended.
+
config SKGE
tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
@@ -2042,6 +2065,13 @@ config BNX2
To compile this driver as a module, choose M here: the module
will be called bnx2. This is recommended.
+config SPIDER_NET
+ tristate "Spider Gigabit Ethernet driver"
+ depends on PCI && PPC_BPA
+ help
+ This driver supports the Gigabit Ethernet chips present on the
+ Cell Processor-Based Blades from IBM.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
@@ -2091,6 +2121,25 @@ endmenu
menu "Ethernet (10000 Mbit)"
depends on !UML
+config CHELSIO_T1
+ tristate "Chelsio 10Gb Ethernet support"
+ depends on PCI
+ help
+ This driver supports Chelsio N110 and N210 models 10Gb Ethernet
+ cards. More information about adapter features and performance
+ tuning is in <file:Documentation/networking/cxgb.txt>.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.htm>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called cxgb.
+
config IXGB
tristate "Intel(R) PRO/10GbE support"
depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 63c6d1e6d4d9..8645c843cf4d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,6 +9,7 @@ endif
obj-$(CONFIG_E1000) += e1000/
obj-$(CONFIG_IBM_EMAC) += ibm_emac/
obj-$(CONFIG_IXGB) += ixgb/
+obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_E100) += e100.o
obj-$(CONFIG_TLAN) += tlan.o
obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SIS190) += sis190.o
obj-$(CONFIG_SIS900) += sis900.o
obj-$(CONFIG_YELLOWFIN) += yellowfin.o
obj-$(CONFIG_ACENIC) += acenic.o
@@ -52,6 +54,8 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BNX2) += bnx2.o
+spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SK98LIN) += sk98lin/
@@ -65,6 +69,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
#
obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_PHYLIB) += phy/
obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 3707df6b0cfa..60304f7e7e5b 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -87,7 +87,6 @@ extern struct net_device *mvme147lance_probe(int unit);
extern struct net_device *tc515_probe(int unit);
extern struct net_device *lance_probe(int unit);
extern struct net_device *mace_probe(int unit);
-extern struct net_device *macsonic_probe(int unit);
extern struct net_device *mac8390_probe(int unit);
extern struct net_device *mac89x0_probe(int unit);
extern struct net_device *mc32_probe(int unit);
@@ -284,9 +283,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
#ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */
{mace_probe, 0},
#endif
-#ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */
- {macsonic_probe, 0},
-#endif
#ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */
{mac8390_probe, 0},
#endif
@@ -318,17 +314,9 @@ static void __init ethif_probe2(int unit)
#ifdef CONFIG_TR
/* Token-ring device probe */
extern int ibmtr_probe_card(struct net_device *);
-extern struct net_device *sk_isa_probe(int unit);
-extern struct net_device *proteon_probe(int unit);
extern struct net_device *smctr_probe(int unit);
static struct devprobe2 tr_probes2[] __initdata = {
-#ifdef CONFIG_SKISA
- {sk_isa_probe, 0},
-#endif
-#ifdef CONFIG_PROTEON
- {proteon_probe, 0},
-#endif
#ifdef CONFIG_SMCTR
{smctr_probe, 0},
#endif
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 91791ba37769..8a0af5453e21 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -275,7 +275,7 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev)
return 0;
out2:
if (ei_status.reg0)
- iounmap((void *)dev->mem_start);
+ iounmap(ei_status.mem);
out1:
free_irq(dev->irq, dev);
out:
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 4f9f69e22c1b..12ef52c193a3 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -597,7 +597,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
struct ArcProto *proto;
int txbuf;
unsigned long flags;
- int freeskb = 0;
+ int freeskb, retval;
BUGMSG(D_DURING,
"transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
@@ -615,7 +615,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
dev_kfree_skb(skb);
- return 0; /* don't try again */
+ return NETDEV_TX_OK; /* don't try again */
}
/* We're busy transmitting a packet... */
@@ -623,8 +623,11 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
AINTMASK(0);
-
- txbuf = get_arcbuf(dev);
+ if(lp->next_tx == -1)
+ txbuf = get_arcbuf(dev);
+ else {
+ txbuf = -1;
+ }
if (txbuf != -1) {
if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
!proto->ack_tx) {
@@ -638,6 +641,8 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
lp->outgoing.skb = skb;
lp->outgoing.pkt = pkt;
+ freeskb = 0;
+
if (proto->continue_tx &&
proto->continue_tx(dev, txbuf)) {
BUGMSG(D_NORMAL,
@@ -645,10 +650,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
"(proto='%c')\n", proto->suffix);
}
}
-
+ retval = NETDEV_TX_OK;
+ dev->trans_start = jiffies;
lp->next_tx = txbuf;
} else {
- freeskb = 1;
+ retval = NETDEV_TX_BUSY;
+ freeskb = 0;
}
BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
@@ -664,7 +671,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (freeskb) {
dev_kfree_skb(skb);
}
- return 0; /* no need to try again */
+ return retval; /* no need to try again */
}
@@ -690,7 +697,6 @@ static int go_tx(struct net_device *dev)
/* start sending */
ACOMMAND(TXcmd | (lp->cur_tx << 3));
- dev->trans_start = jiffies;
lp->stats.tx_packets++;
lp->lasttrans_dest = lp->lastload_dest;
lp->lastload_dest = 0;
@@ -917,6 +923,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
status);
+ /* MYRECON bit is at bit 7 of diagstatus */
+ if(diagstatus & 0x80)
+ BUGMSG(D_RECON,"Put out that recon myself\n");
/* is the RECON info empty or old? */
if (!lp->first_recon || !lp->last_recon ||
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 52c77cbe8c62..1f0302735416 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -160,7 +160,7 @@ static int __init com90io_probe(struct net_device *dev)
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
- BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n",
+ BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
@@ -242,7 +242,7 @@ static int __init com90io_found(struct net_device *dev)
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
- /* Reserve the I/O region - guaranteed to work by check_region */
+ /* Reserve the I/O region */
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index 1798ce7262c9..0095384ff454 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -155,7 +155,7 @@ static int bionet_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
static void bionet_tick(unsigned long);
-static struct timer_list bionet_timer = TIMER_INITIALIZER(bionet_tick, 0, 0);
+static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 81c362c8cb97..8b997809f9de 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -165,7 +165,7 @@ static void pamsnet_tick(unsigned long);
static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
-static struct timer_list pamsnet_timer = TIMER_INITIALIZER(pamsnet_tick, 0, 0);
+static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index ad011214c7f2..e01b6a78ec63 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -235,7 +235,7 @@ struct lance_private {
#define MEM lp->mem
#define DREG IO->data
#define AREG IO->addr
-#define REGA(a) ( AREG = (a), DREG )
+#define REGA(a) (*( AREG = (a), &DREG ))
/* Definitions for packet buffer access: */
#define PKT_BUF_SZ 1544
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8acc655ec1e8..3a2ace01e444 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -14,8 +14,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.2.19"
-#define DRV_MODULE_RELDATE "May 23, 2005"
+#define DRV_MODULE_VERSION "1.2.21"
+#define DRV_MODULE_RELDATE "September 7, 2005"
#define RUN_AT(x) (jiffies + (x))
@@ -52,7 +52,6 @@ static struct {
{ "HP NC370i Multifunction Gigabit Server Adapter" },
{ "Broadcom NetXtreme II BCM5706 1000Base-SX" },
{ "HP NC370F Multifunction Gigabit Server Adapter" },
- { 0 },
};
static struct pci_device_id bnx2_pci_tbl[] = {
@@ -108,6 +107,15 @@ static struct flash_spec flash_table[] =
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
+static inline u32 bnx2_tx_avail(struct bnx2 *bp)
+{
+ u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+
+ if (diff > MAX_TX_DESC_CNT)
+ diff = (diff & MAX_TX_DESC_CNT) - 1;
+ return (bp->tx_ring_size - diff);
+}
+
static u32
bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
{
@@ -807,7 +815,19 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE);
- bp->serdes_an_pending = SERDES_AN_TIMEOUT / bp->timer_interval;
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ /* Speed up link-up time when the link partner
+ * does not autonegotiate which is very common
+ * in blade servers. Some blade servers use
+ * IPMI for kerboard input and it's important
+ * to minimize link disruptions. Autoneg. involves
+ * exchanging base pages plus 3 next pages and
+ * normally completes in about 120 msec.
+ */
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+ }
}
return 0;
@@ -1327,22 +1347,17 @@ bnx2_tx_int(struct bnx2 *bp)
}
}
- atomic_add(tx_free_bd, &bp->tx_avail_bd);
+ bp->tx_cons = sw_cons;
if (unlikely(netif_queue_stopped(bp->dev))) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->tx_lock, flags);
+ spin_lock(&bp->tx_lock);
if ((netif_queue_stopped(bp->dev)) &&
- (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)) {
+ (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
netif_wake_queue(bp->dev);
}
- spin_unlock_irqrestore(&bp->tx_lock, flags);
+ spin_unlock(&bp->tx_lock);
}
-
- bp->tx_cons = sw_cons;
-
}
static inline void
@@ -1518,20 +1533,18 @@ bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
struct net_device *dev = dev_instance;
struct bnx2 *bp = dev->priv;
+ prefetch(bp->status_blk);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
/* Return here if interrupt is disabled. */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- return IRQ_RETVAL(1);
- }
+ if (unlikely(atomic_read(&bp->intr_sem) != 0))
+ return IRQ_HANDLED;
- if (netif_rx_schedule_prep(dev)) {
- __netif_rx_schedule(dev);
- }
+ netif_rx_schedule(dev);
- return IRQ_RETVAL(1);
+ return IRQ_HANDLED;
}
static irqreturn_t
@@ -1546,25 +1559,22 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
* When using MSI, the MSI message will always complete after
* the status block write.
*/
- if ((bp->status_blk->status_idx == bp->last_status_idx) ||
+ if ((bp->status_blk->status_idx == bp->last_status_idx) &&
(REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
- return IRQ_RETVAL(0);
+ return IRQ_NONE;
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
/* Return here if interrupt is shared and is disabled. */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- return IRQ_RETVAL(1);
- }
+ if (unlikely(atomic_read(&bp->intr_sem) != 0))
+ return IRQ_HANDLED;
- if (netif_rx_schedule_prep(dev)) {
- __netif_rx_schedule(dev);
- }
+ netif_rx_schedule(dev);
- return IRQ_RETVAL(1);
+ return IRQ_HANDLED;
}
static int
@@ -1581,11 +1591,9 @@ bnx2_poll(struct net_device *dev, int *budget)
(bp->status_blk->status_attn_bits_ack &
STATUS_ATTN_BITS_LINK_STATE)) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock(&bp->phy_lock);
bnx2_phy_int(bp);
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock(&bp->phy_lock);
}
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) {
@@ -1628,9 +1636,8 @@ bnx2_set_rx_mode(struct net_device *dev)
struct bnx2 *bp = dev->priv;
u32 rx_mode, sort_mode;
int i;
- unsigned long flags;
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock_bh(&bp->phy_lock);
rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
@@ -1691,7 +1698,7 @@ bnx2_set_rx_mode(struct net_device *dev)
REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock_bh(&bp->phy_lock);
}
static void
@@ -1998,14 +2005,14 @@ bnx2_init_cpus(struct bnx2 *bp)
}
static int
-bnx2_set_power_state(struct bnx2 *bp, int state)
+bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
{
u16 pmcsr;
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
switch (state) {
- case 0: {
+ case PCI_D0: {
u32 val;
pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
@@ -2026,7 +2033,7 @@ bnx2_set_power_state(struct bnx2 *bp, int state)
REG_WR(bp, BNX2_RPM_CONFIG, val);
break;
}
- case 3: {
+ case PCI_D3hot: {
int i;
u32 val, wol_msg;
@@ -2960,7 +2967,6 @@ bnx2_init_tx_ring(struct bnx2 *bp)
bp->tx_prod = 0;
bp->tx_cons = 0;
bp->tx_prod_bseq = 0;
- atomic_set(&bp->tx_avail_bd, bp->tx_ring_size);
val = BNX2_L2CTX_TYPE_TYPE_L2;
val |= BNX2_L2CTX_TYPE_SIZE_L2;
@@ -3507,11 +3513,11 @@ bnx2_test_registers(struct bnx2 *bp)
rw_mask = reg_tbl[i].rw_mask;
ro_mask = reg_tbl[i].ro_mask;
- save_val = readl((u8 *) bp->regview + offset);
+ save_val = readl(bp->regview + offset);
- writel(0, (u8 *) bp->regview + offset);
+ writel(0, bp->regview + offset);
- val = readl((u8 *) bp->regview + offset);
+ val = readl(bp->regview + offset);
if ((val & rw_mask) != 0) {
goto reg_test_err;
}
@@ -3520,9 +3526,9 @@ bnx2_test_registers(struct bnx2 *bp)
goto reg_test_err;
}
- writel(0xffffffff, (u8 *) bp->regview + offset);
+ writel(0xffffffff, bp->regview + offset);
- val = readl((u8 *) bp->regview + offset);
+ val = readl(bp->regview + offset);
if ((val & rw_mask) != rw_mask) {
goto reg_test_err;
}
@@ -3531,11 +3537,11 @@ bnx2_test_registers(struct bnx2 *bp)
goto reg_test_err;
}
- writel(save_val, (u8 *) bp->regview + offset);
+ writel(save_val, bp->regview + offset);
continue;
reg_test_err:
- writel(save_val, (u8 *) bp->regview + offset);
+ writel(save_val, bp->regview + offset);
ret = -ENODEV;
break;
}
@@ -3752,10 +3758,10 @@ bnx2_test_link(struct bnx2 *bp)
{
u32 bmsr;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_read_phy(bp, MII_BMSR, &bmsr);
bnx2_read_phy(bp, MII_BMSR, &bmsr);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
if (bmsr & BMSR_LSTATUS) {
return 0;
@@ -3801,6 +3807,9 @@ bnx2_timer(unsigned long data)
struct bnx2 *bp = (struct bnx2 *) data;
u32 msg;
+ if (!netif_running(bp->dev))
+ return;
+
if (atomic_read(&bp->intr_sem) != 0)
goto bnx2_restart_timer;
@@ -3809,15 +3818,16 @@ bnx2_timer(unsigned long data)
if ((bp->phy_flags & PHY_SERDES_FLAG) &&
(CHIP_NUM(bp) == CHIP_NUM_5706)) {
- unsigned long flags;
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock(&bp->phy_lock);
if (bp->serdes_an_pending) {
bp->serdes_an_pending--;
}
else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
u32 bmcr;
+ bp->current_interval = bp->timer_interval;
+
bnx2_read_phy(bp, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) {
@@ -3860,14 +3870,14 @@ bnx2_timer(unsigned long data)
}
}
+ else
+ bp->current_interval = bp->timer_interval;
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock(&bp->phy_lock);
}
bnx2_restart_timer:
- bp->timer.expires = RUN_AT(bp->timer_interval);
-
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
/* Called with rtnl_lock */
@@ -3877,7 +3887,7 @@ bnx2_open(struct net_device *dev)
struct bnx2 *bp = dev->priv;
int rc;
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
bnx2_disable_int(bp);
rc = bnx2_alloc_mem(bp);
@@ -3920,12 +3930,7 @@ bnx2_open(struct net_device *dev)
return rc;
}
- init_timer(&bp->timer);
-
- bp->timer.expires = RUN_AT(bp->timer_interval);
- bp->timer.data = (unsigned long) bp;
- bp->timer.function = bnx2_timer;
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
atomic_set(&bp->intr_sem, 0);
@@ -3976,12 +3981,17 @@ bnx2_reset_task(void *data)
{
struct bnx2 *bp = data;
+ if (!netif_running(bp->dev))
+ return;
+
+ bp->in_reset_task = 1;
bnx2_netif_stop(bp);
bnx2_init_nic(bp);
atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp);
+ bp->in_reset_task = 0;
}
static void
@@ -4041,9 +4051,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
u16 prod, ring_prod;
int i;
- if (unlikely(atomic_read(&bp->tx_avail_bd) <
- (skb_shinfo(skb)->nr_frags + 1))) {
-
+ if (unlikely(bnx2_tx_avail(bp) < (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
dev->name);
@@ -4140,8 +4148,6 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
prod = NEXT_TX_BD(prod);
bp->tx_prod_bseq += skb->len;
- atomic_sub(last_frag + 1, &bp->tx_avail_bd);
-
REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
@@ -4150,17 +4156,13 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
bp->tx_prod = prod;
dev->trans_start = jiffies;
- if (unlikely(atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS)) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->tx_lock, flags);
- if (atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS) {
- netif_stop_queue(dev);
-
- if (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)
- netif_wake_queue(dev);
- }
- spin_unlock_irqrestore(&bp->tx_lock, flags);
+ if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
+ spin_lock(&bp->tx_lock);
+ netif_stop_queue(dev);
+
+ if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+ netif_wake_queue(dev);
+ spin_unlock(&bp->tx_lock);
}
return NETDEV_TX_OK;
@@ -4173,7 +4175,13 @@ bnx2_close(struct net_device *dev)
struct bnx2 *bp = dev->priv;
u32 reset_code;
- flush_scheduled_work();
+ /* Calling flush_scheduled_work() may deadlock because
+ * linkwatch_event() may be on the workqueue and it will try to get
+ * the rtnl_lock which we are holding.
+ */
+ while (bp->in_reset_task)
+ msleep(1);
+
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
if (bp->wol)
@@ -4190,7 +4198,7 @@ bnx2_close(struct net_device *dev)
bnx2_free_mem(bp);
bp->link_up = 0;
netif_carrier_off(bp->dev);
- bnx2_set_power_state(bp, 3);
+ bnx2_set_power_state(bp, PCI_D3hot);
return 0;
}
@@ -4390,11 +4398,11 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
bp->req_line_speed = req_line_speed;
bp->req_duplex = req_duplex;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_setup_phy(bp);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4464,19 +4472,20 @@ bnx2_nway_reset(struct net_device *dev)
return -EINVAL;
}
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
/* Force a link down visible on the other side */
if (bp->phy_flags & PHY_SERDES_FLAG) {
bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
msleep(20);
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
if (CHIP_NUM(bp) == CHIP_NUM_5706) {
- bp->serdes_an_pending = SERDES_AN_TIMEOUT /
- bp->timer_interval;
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
}
@@ -4484,7 +4493,7 @@ bnx2_nway_reset(struct net_device *dev)
bmcr &= ~BMCR_LOOPBACK;
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4670,11 +4679,11 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
bp->autoneg &= ~AUTONEG_FLOW_CTRL;
}
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_setup_phy(bp);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4698,7 +4707,7 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
#define BNX2_NUM_STATS 45
-struct {
+static struct {
char string[ETH_GSTRING_LEN];
} bnx2_stats_str_arr[BNX2_NUM_STATS] = {
{ "rx_bytes" },
@@ -4750,7 +4759,7 @@ struct {
#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
-unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
+static unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
STATS_OFFSET32(stat_IfHCInOctets_hi),
STATS_OFFSET32(stat_IfHCInBadOctets_hi),
STATS_OFFSET32(stat_IfHCOutOctets_hi),
@@ -4801,7 +4810,7 @@ unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
* skipped because of errata.
*/
-u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
+static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
8,0,8,8,8,8,8,8,8,8,
4,0,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
@@ -4811,7 +4820,7 @@ u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
#define BNX2_NUM_TESTS 6
-struct {
+static struct {
char string[ETH_GSTRING_LEN];
} bnx2_tests_str_arr[BNX2_NUM_TESTS] = {
{ "register_test (offline)" },
@@ -4910,7 +4919,7 @@ bnx2_get_ethtool_stats(struct net_device *dev,
struct bnx2 *bp = dev->priv;
int i;
u32 *hw_stats = (u32 *) bp->stats_blk;
- u8 *stats_len_arr = 0;
+ u8 *stats_len_arr = NULL;
if (hw_stats == NULL) {
memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS);
@@ -5006,13 +5015,14 @@ static struct ethtool_ops bnx2_ethtool_ops = {
.phys_id = bnx2_phys_id,
.get_stats_count = bnx2_get_stats_count,
.get_ethtool_stats = bnx2_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/* Called with rtnl_lock */
static int
bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
+ struct mii_ioctl_data *data = if_mii(ifr);
struct bnx2 *bp = dev->priv;
int err;
@@ -5024,9 +5034,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: {
u32 mii_regval;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
data->val_out = mii_regval;
@@ -5037,9 +5047,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return err;
@@ -5057,6 +5067,9 @@ bnx2_change_mac_addr(struct net_device *dev, void *p)
struct sockaddr *addr = p;
struct bnx2 *bp = dev->priv;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if (netif_running(dev))
bnx2_set_mac_addr(bp);
@@ -5192,7 +5205,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
@@ -5305,6 +5318,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->stats_ticks = 1000000 & 0xffff00;
bp->timer_interval = HZ;
+ bp->current_interval = HZ;
/* Disable WOL support if we are running on a SERDES chip. */
if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
@@ -5328,6 +5342,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->req_line_speed = 0;
if (bp->phy_flags & PHY_SERDES_FLAG) {
bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+ reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE +
+ BNX2_PORT_HW_CFG_CONFIG);
+ reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+ if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+ bp->autoneg = 0;
+ bp->req_line_speed = bp->line_speed = SPEED_1000;
+ bp->req_duplex = DUPLEX_FULL;
+ }
}
else {
bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
@@ -5335,11 +5358,17 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
+ init_timer(&bp->timer);
+ bp->timer.expires = RUN_AT(bp->timer_interval);
+ bp->timer.data = (unsigned long) bp;
+ bp->timer.function = bnx2_timer;
+
return 0;
err_out_unmap:
if (bp->regview) {
iounmap(bp->regview);
+ bp->regview = NULL;
}
err_out_release:
@@ -5414,6 +5443,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
memcpy(dev->dev_addr, bp->mac_addr, 6);
+ memcpy(dev->perm_addr, bp->mac_addr, 6);
bp->name = board_info[ent->driver_data].name,
printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
"IRQ %d, ",
@@ -5454,6 +5484,8 @@ bnx2_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = dev->priv;
+ flush_scheduled_work();
+
unregister_netdev(dev);
if (bp->regview)
@@ -5466,7 +5498,7 @@ bnx2_remove_one(struct pci_dev *pdev)
}
static int
-bnx2_suspend(struct pci_dev *pdev, u32 state)
+bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = dev->priv;
@@ -5484,7 +5516,7 @@ bnx2_suspend(struct pci_dev *pdev, u32 state)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
bnx2_reset_chip(bp, reset_code);
bnx2_free_skbs(bp);
- bnx2_set_power_state(bp, state);
+ bnx2_set_power_state(bp, pci_choose_state(pdev, state));
return 0;
}
@@ -5497,7 +5529,7 @@ bnx2_resume(struct pci_dev *pdev)
if (!netif_running(dev))
return 0;
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
bnx2_init_nic(bp);
bnx2_netif_start(bp);
@@ -5505,12 +5537,12 @@ bnx2_resume(struct pci_dev *pdev)
}
static struct pci_driver bnx2_pci_driver = {
- name: DRV_MODULE_NAME,
- id_table: bnx2_pci_tbl,
- probe: bnx2_init_one,
- remove: __devexit_p(bnx2_remove_one),
- suspend: bnx2_suspend,
- resume: bnx2_resume,
+ .name = DRV_MODULE_NAME,
+ .id_table = bnx2_pci_tbl,
+ .probe = bnx2_init_one,
+ .remove = __devexit_p(bnx2_remove_one),
+ .suspend = bnx2_suspend,
+ .resume = bnx2_resume,
};
static int __init bnx2_init(void)
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 8214a2853d0d..62857b6a6ee4 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -50,6 +50,7 @@
#endif
#include <linux/workqueue.h>
#include <linux/crc32.h>
+#include <linux/prefetch.h>
/* Hardware data structures and register definitions automatically
* generated from RTL code. Do not modify.
@@ -3841,12 +3842,12 @@ struct bnx2 {
struct status_block *status_blk;
u32 last_status_idx;
- atomic_t tx_avail_bd;
struct tx_bd *tx_desc_ring;
struct sw_bd *tx_buf_ring;
u32 tx_prod_bseq;
u16 tx_prod;
u16 tx_cons;
+ int tx_ring_size;
#ifdef BCM_VLAN
struct vlan_group *vlgrp;
@@ -3872,8 +3873,10 @@ struct bnx2 {
char *name;
int timer_interval;
+ int current_interval;
struct timer_list timer;
struct work_struct reset_task;
+ int in_reset_task;
/* Used to synchronize phy accesses. */
spinlock_t phy_lock;
@@ -3927,7 +3930,6 @@ struct bnx2 {
u16 fw_wr_seq;
u16 fw_drv_pulse_wr_seq;
- int tx_ring_size;
dma_addr_t tx_desc_mapping;
@@ -3985,7 +3987,7 @@ struct bnx2 {
#define PHY_LOOPBACK 2
u8 serdes_an_pending;
-#define SERDES_AN_TIMEOUT (2 * HZ)
+#define SERDES_AN_TIMEOUT (HZ / 3)
u8 mac_addr[8];
@@ -4171,6 +4173,9 @@ struct fw_info {
#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a2e8dda5afac..d2f34d5a8083 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2419,22 +2419,19 @@ out:
return 0;
}
-int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev)
{
struct bonding *bond = dev->priv;
struct slave *slave = NULL;
int ret = NET_RX_DROP;
- if (!(dev->flags & IFF_MASTER)) {
+ if (!(dev->flags & IFF_MASTER))
goto out;
- }
read_lock(&bond->lock);
- slave = bond_get_slave_by_dev((struct bonding *)dev->priv,
- skb->real_dev);
- if (slave == NULL) {
+ slave = bond_get_slave_by_dev((struct bonding *)dev->priv, orig_dev);
+ if (!slave)
goto out_unlock;
- }
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index f46823894187..673a30af5660 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -295,6 +295,6 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
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);
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 5ce606d9dc03..f8fce3961197 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -354,15 +354,14 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
_unlock_rx_hashtbl(bond);
}
-static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype)
+static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
{
struct bonding *bond = bond_dev->priv;
struct arp_pkt *arp = (struct arp_pkt *)skb->data;
int res = NET_RX_DROP;
- if (!(bond_dev->flags & IFF_MASTER)) {
+ if (!(bond_dev->flags & IFF_MASTER))
goto out;
- }
if (!arp) {
dprintk("Packet has no ARP data\n");
@@ -1106,18 +1105,13 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
}
}
- if (found) {
- /* a slave was found that is using the mac address
- * of the new slave
- */
- printk(KERN_ERR DRV_NAME
- ": Error: the hw address of slave %s is not "
- "unique - cannot enslave it!",
- slave->dev->name);
- return -EINVAL;
- }
+ if (!found)
+ return 0;
- return 0;
+ /* Try setting slave mac to bond address and fall-through
+ to code handling that situation below... */
+ alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
+ bond->alb_info.rlb_enabled);
}
/* The slave's address is equal to the address of the bond.
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2c930da90a85..94c9f68dd16b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_
return 0;
}
+#define BOND_INTERSECT_FEATURES \
+ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+
+/*
+ * Compute the features available to the bonding device by
+ * intersection of all of the slave devices' BOND_INTERSECT_FEATURES.
+ * Call this after attaching or detaching a slave to update the
+ * bond's features.
+ */
+static int bond_compute_features(struct bonding *bond)
+{
+ int i;
+ struct slave *slave;
+ struct net_device *bond_dev = bond->dev;
+ int features = bond->bond_features;
+
+ bond_for_each_slave(bond, slave, i) {
+ struct net_device * slave_dev = slave->dev;
+ if (i == 0) {
+ features |= BOND_INTERSECT_FEATURES;
+ }
+ features &=
+ ~(~slave_dev->features & BOND_INTERSECT_FEATURES);
+ }
+
+ /* turn off NETIF_F_SG if we need a csum and h/w can't do it */
+ if ((features & NETIF_F_SG) &&
+ !(features & (NETIF_F_IP_CSUM |
+ NETIF_F_NO_CSUM |
+ NETIF_F_HW_CSUM))) {
+ features &= ~NETIF_F_SG;
+ }
+
+ bond_dev->features = features;
+
+ return 0;
+}
+
/* enslave device <slave> to bond device <master> */
static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
@@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
new_slave->delay = 0;
new_slave->link_failure_count = 0;
+ bond_compute_features(bond);
+
if (bond->params.miimon && !bond->params.use_carrier) {
link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@@ -2015,7 +2055,7 @@ err_free:
err_undo_flags:
bond_dev->features = old_features;
-
+
return res;
}
@@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* release the slave from its bond */
bond_detach_slave(bond, slave);
+ bond_compute_features(bond);
+
if (bond->primary_slave == slave) {
bond->primary_slave = NULL;
}
@@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev)
bond_alb_deinit_slave(bond, slave);
}
+ bond_compute_features(bond);
+
/* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from
* within a lock.
@@ -3588,6 +3632,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
{
struct net_device *bond_dev = slave_dev->master;
+ struct bonding *bond = bond_dev->priv;
switch (event) {
case NETDEV_UNREGISTER:
@@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* TODO: handle changing the primary's name
*/
break;
+ case NETDEV_FEAT_CHANGE:
+ bond_compute_features(bond);
+ break;
default:
break;
}
@@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
}
}
+static struct ethtool_ops bond_ethtool_ops = {
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+};
+
/*
* Does not allocate but creates a /proc entry.
* Allowed to fail.
@@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
bond_dev->stop = bond_close;
bond_dev->get_stats = bond_get_stats;
bond_dev->do_ioctl = bond_do_ioctl;
+ bond_dev->ethtool_ops = &bond_ethtool_ops;
bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address;
@@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
+ bond->bond_features = bond_dev->features;
+
#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
#endif
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index d27f377b3eeb..388196980862 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -211,6 +211,9 @@ struct bonding {
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
+ /* the features the bonding device supports, independently
+ * of any slaves */
+ int bond_features;
};
/**
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 3d88ad622bdb..fb4098ed469e 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -323,33 +323,27 @@ static void bsd_reset (void *state)
*/
static void bsd_free (void *state)
- {
- struct bsd_db *db = (struct bsd_db *) state;
+{
+ struct bsd_db *db = state;
- if (db)
- {
+ if (!db)
+ return;
+
/*
* Release the dictionary
*/
- if (db->dict)
- {
- vfree (db->dict);
- db->dict = NULL;
- }
+ vfree(db->dict);
+ db->dict = NULL;
/*
* Release the string buffer
*/
- if (db->lens)
- {
- vfree (db->lens);
- db->lens = NULL;
- }
+ vfree(db->lens);
+ db->lens = NULL;
/*
* Finally release the structure itself.
*/
- kfree (db);
- }
- }
+ kfree(db);
+}
/*
* Allocate space for a (de) compressor.
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
new file mode 100644
index 000000000000..91e927827c43
--- /dev/null
+++ b/drivers/net/chelsio/Makefile
@@ -0,0 +1,11 @@
+#
+# Chelsio 10Gb NIC driver for Linux.
+#
+
+obj-$(CONFIG_CHELSIO_T1) += cxgb.o
+
+EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS)
+
+
+cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
+
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
new file mode 100644
index 000000000000..bf3e7b6a7a18
--- /dev/null
+++ b/drivers/net/chelsio/common.h
@@ -0,0 +1,314 @@
+/*****************************************************************************
+ * *
+ * File: common.h *
+ * $Revision: 1.21 $ *
+ * $Date: 2005/06/22 00:43:25 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_COMMON_H_
+#define _CXGB_COMMON_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/pci_ids.h>
+
+#define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver"
+#define DRV_NAME "cxgb"
+#define DRV_VERSION "2.1.1"
+#define PFX DRV_NAME ": "
+
+#define CH_ERR(fmt, ...) printk(KERN_ERR PFX fmt, ## __VA_ARGS__)
+#define CH_WARN(fmt, ...) printk(KERN_WARNING PFX fmt, ## __VA_ARGS__)
+#define CH_ALERT(fmt, ...) printk(KERN_ALERT PFX fmt, ## __VA_ARGS__)
+
+#define CH_DEVICE(devid, ssid, idx) \
+ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
+
+#define SUPPORTED_PAUSE (1 << 13)
+#define SUPPORTED_LOOPBACK (1 << 15)
+
+#define ADVERTISED_PAUSE (1 << 13)
+#define ADVERTISED_ASYM_PAUSE (1 << 14)
+
+typedef struct adapter adapter_t;
+
+void t1_elmer0_ext_intr(adapter_t *adapter);
+void t1_link_changed(adapter_t *adapter, int port_id, int link_status,
+ int speed, int duplex, int fc);
+
+struct t1_rx_mode {
+ struct net_device *dev;
+ u32 idx;
+ struct dev_mc_list *list;
+};
+
+#define t1_rx_mode_promisc(rm) (rm->dev->flags & IFF_PROMISC)
+#define t1_rx_mode_allmulti(rm) (rm->dev->flags & IFF_ALLMULTI)
+#define t1_rx_mode_mc_cnt(rm) (rm->dev->mc_count)
+
+static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm)
+{
+ u8 *addr = NULL;
+
+ if (rm->idx++ < rm->dev->mc_count) {
+ addr = rm->list->dmi_addr;
+ rm->list = rm->list->next;
+ }
+ return addr;
+}
+
+#define MAX_NPORTS 4
+
+#define SPEED_INVALID 0xffff
+#define DUPLEX_INVALID 0xff
+
+enum {
+ CHBT_BOARD_N110,
+ CHBT_BOARD_N210
+};
+
+enum {
+ CHBT_TERM_T1,
+ CHBT_TERM_T2
+};
+
+enum {
+ CHBT_MAC_PM3393,
+};
+
+enum {
+ CHBT_PHY_88X2010,
+};
+
+enum {
+ PAUSE_RX = 1 << 0,
+ PAUSE_TX = 1 << 1,
+ PAUSE_AUTONEG = 1 << 2
+};
+
+/* Revisions of T1 chip */
+enum {
+ TERM_T1A = 0,
+ TERM_T1B = 1,
+ TERM_T2 = 3
+};
+
+struct sge_params {
+ unsigned int cmdQ_size[2];
+ unsigned int freelQ_size[2];
+ unsigned int large_buf_capacity;
+ unsigned int rx_coalesce_usecs;
+ unsigned int last_rx_coalesce_raw;
+ unsigned int default_rx_coalesce_usecs;
+ unsigned int sample_interval_usecs;
+ unsigned int coalesce_enable;
+ unsigned int polling;
+};
+
+struct chelsio_pci_params {
+ unsigned short speed;
+ unsigned char width;
+ unsigned char is_pcix;
+};
+
+struct adapter_params {
+ struct sge_params sge;
+ struct chelsio_pci_params pci;
+
+ const struct board_info *brd_info;
+
+ unsigned int nports; /* # of ethernet ports */
+ unsigned int stats_update_period;
+ unsigned short chip_revision;
+ unsigned char chip_version;
+};
+
+struct link_config {
+ unsigned int supported; /* link capabilities */
+ unsigned int advertising; /* advertised capabilities */
+ unsigned short requested_speed; /* speed user has requested */
+ unsigned short speed; /* actual link speed */
+ unsigned char requested_duplex; /* duplex user has requested */
+ unsigned char duplex; /* actual link duplex */
+ unsigned char requested_fc; /* flow control user has requested */
+ unsigned char fc; /* actual link flow control */
+ unsigned char autoneg; /* autonegotiating? */
+};
+
+struct cmac;
+struct cphy;
+
+struct port_info {
+ struct net_device *dev;
+ struct cmac *mac;
+ struct cphy *phy;
+ struct link_config link_config;
+ struct net_device_stats netstats;
+};
+
+struct sge;
+struct peespi;
+
+struct adapter {
+ u8 __iomem *regs;
+ struct pci_dev *pdev;
+ unsigned long registered_device_map;
+ unsigned long open_device_map;
+ unsigned long flags;
+
+ const char *name;
+ int msg_enable;
+ u32 mmio_len;
+
+ struct work_struct ext_intr_handler_task;
+ struct adapter_params params;
+
+ struct vlan_group *vlan_grp;
+
+ /* Terminator modules. */
+ struct sge *sge;
+ struct peespi *espi;
+
+ struct port_info port[MAX_NPORTS];
+ struct work_struct stats_update_task;
+ struct timer_list stats_update_timer;
+
+ struct semaphore mib_mutex;
+ spinlock_t tpi_lock;
+ spinlock_t work_lock;
+ /* guards async operations */
+ spinlock_t async_lock ____cacheline_aligned;
+ u32 slow_intr_mask;
+};
+
+enum { /* adapter flags */
+ FULL_INIT_DONE = 1 << 0,
+ TSO_CAPABLE = 1 << 2,
+ TCP_CSUM_CAPABLE = 1 << 3,
+ UDP_CSUM_CAPABLE = 1 << 4,
+ VLAN_ACCEL_CAPABLE = 1 << 5,
+ RX_CSUM_ENABLED = 1 << 6,
+};
+
+struct mdio_ops;
+struct gmac;
+struct gphy;
+
+struct board_info {
+ unsigned char board;
+ unsigned char port_number;
+ unsigned long caps;
+ unsigned char chip_term;
+ unsigned char chip_mac;
+ unsigned char chip_phy;
+ unsigned int clock_core;
+ unsigned int clock_mc3;
+ unsigned int clock_mc4;
+ unsigned int espi_nports;
+ unsigned int clock_cspi;
+ unsigned int clock_elmer0;
+ unsigned char mdio_mdien;
+ unsigned char mdio_mdiinv;
+ unsigned char mdio_mdc;
+ unsigned char mdio_phybaseaddr;
+ struct gmac *gmac;
+ struct gphy *gphy;
+ struct mdio_ops *mdio_ops;
+ const char *desc;
+};
+
+extern struct pci_device_id t1_pci_tbl[];
+
+static inline int adapter_matches_type(const adapter_t *adapter,
+ int version, int revision)
+{
+ return adapter->params.chip_version == version &&
+ adapter->params.chip_revision == revision;
+}
+
+#define t1_is_T1B(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1B)
+#define is_T2(adap) adapter_matches_type(adap, CHBT_TERM_T2, TERM_T2)
+
+/* Returns true if an adapter supports VLAN acceleration and TSO */
+static inline int vlan_tso_capable(const adapter_t *adapter)
+{
+ return !t1_is_T1B(adapter);
+}
+
+#define for_each_port(adapter, iter) \
+ for (iter = 0; iter < (adapter)->params.nports; ++iter)
+
+#define board_info(adapter) ((adapter)->params.brd_info)
+#define is_10G(adapter) (board_info(adapter)->caps & SUPPORTED_10000baseT_Full)
+
+static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
+{
+ return board_info(adap)->clock_core / 1000000;
+}
+
+extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
+extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
+
+extern void t1_interrupts_enable(adapter_t *adapter);
+extern void t1_interrupts_disable(adapter_t *adapter);
+extern void t1_interrupts_clear(adapter_t *adapter);
+extern int elmer0_ext_intr_handler(adapter_t *adapter);
+extern int t1_slow_intr_handler(adapter_t *adapter);
+
+extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
+extern const struct board_info *t1_get_board_info(unsigned int board_id);
+extern const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
+ unsigned short ssid);
+extern int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data);
+extern int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ struct adapter_params *p);
+extern int t1_init_hw_modules(adapter_t *adapter);
+extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
+extern void t1_free_sw_modules(adapter_t *adapter);
+extern void t1_fatal_err(adapter_t *adapter);
+
+extern void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable);
+extern void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable);
+extern void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable);
+
+#endif /* _CXGB_COMMON_H_ */
diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h
new file mode 100644
index 000000000000..3412342f7345
--- /dev/null
+++ b/drivers/net/chelsio/cphy.h
@@ -0,0 +1,148 @@
+/*****************************************************************************
+ * *
+ * File: cphy.h *
+ * $Revision: 1.7 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_CPHY_H_
+#define _CXGB_CPHY_H_
+
+#include "common.h"
+
+struct mdio_ops {
+ void (*init)(adapter_t *adapter, const struct board_info *bi);
+ int (*read)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *val);
+ int (*write)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val);
+};
+
+/* PHY interrupt types */
+enum {
+ cphy_cause_link_change = 0x1,
+ cphy_cause_error = 0x2
+};
+
+struct cphy;
+
+/* PHY operations */
+struct cphy_ops {
+ void (*destroy)(struct cphy *);
+ int (*reset)(struct cphy *, int wait);
+
+ int (*interrupt_enable)(struct cphy *);
+ int (*interrupt_disable)(struct cphy *);
+ int (*interrupt_clear)(struct cphy *);
+ int (*interrupt_handler)(struct cphy *);
+
+ int (*autoneg_enable)(struct cphy *);
+ int (*autoneg_disable)(struct cphy *);
+ int (*autoneg_restart)(struct cphy *);
+
+ int (*advertise)(struct cphy *phy, unsigned int advertise_map);
+ int (*set_loopback)(struct cphy *, int on);
+ int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
+ int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
+ int *duplex, int *fc);
+};
+
+/* A PHY instance */
+struct cphy {
+ int addr; /* PHY address */
+ adapter_t *adapter; /* associated adapter */
+ struct cphy_ops *ops; /* PHY operations */
+ int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *val);
+ int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val);
+ struct cphy_instance *instance;
+};
+
+/* Convenience MDIO read/write wrappers */
+static inline int mdio_read(struct cphy *cphy, int mmd, int reg,
+ unsigned int *valp)
+{
+ return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp);
+}
+
+static inline int mdio_write(struct cphy *cphy, int mmd, int reg,
+ unsigned int val)
+{
+ return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val);
+}
+
+static inline int simple_mdio_read(struct cphy *cphy, int reg,
+ unsigned int *valp)
+{
+ return mdio_read(cphy, 0, reg, valp);
+}
+
+static inline int simple_mdio_write(struct cphy *cphy, int reg,
+ unsigned int val)
+{
+ return mdio_write(cphy, 0, reg, val);
+}
+
+/* Convenience initializer */
+static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
+ int phy_addr, struct cphy_ops *phy_ops,
+ struct mdio_ops *mdio_ops)
+{
+ phy->adapter = adapter;
+ phy->addr = phy_addr;
+ phy->ops = phy_ops;
+ if (mdio_ops) {
+ phy->mdio_read = mdio_ops->read;
+ phy->mdio_write = mdio_ops->write;
+ }
+}
+
+/* Operations of the PHY-instance factory */
+struct gphy {
+ /* Construct a PHY instance with the given PHY address */
+ struct cphy *(*create)(adapter_t *adapter, int phy_addr,
+ struct mdio_ops *mdio_ops);
+
+ /*
+ * Reset the PHY chip. This resets the whole PHY chip, not individual
+ * ports.
+ */
+ int (*reset)(adapter_t *adapter);
+};
+
+extern struct gphy t1_mv88x201x_ops;
+extern struct gphy t1_dummy_phy_ops;
+
+#endif /* _CXGB_CPHY_H_ */
diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/chelsio/cpl5_cmd.h
new file mode 100644
index 000000000000..27925e487bcf
--- /dev/null
+++ b/drivers/net/chelsio/cpl5_cmd.h
@@ -0,0 +1,145 @@
+/*****************************************************************************
+ * *
+ * File: cpl5_cmd.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_CPL5_CMD_H_
+#define _CXGB_CPL5_CMD_H_
+
+#include <asm/byteorder.h>
+
+#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD)
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+
+enum CPL_opcode {
+ CPL_RX_PKT = 0xAD,
+ CPL_TX_PKT = 0xB2,
+ CPL_TX_PKT_LSO = 0xB6,
+};
+
+enum { /* TX_PKT_LSO ethernet types */
+ CPL_ETH_II,
+ CPL_ETH_II_VLAN,
+ CPL_ETH_802_3,
+ CPL_ETH_802_3_VLAN
+};
+
+struct cpl_rx_data {
+ u32 rsvd0;
+ u32 len;
+ u32 seq;
+ u16 urg;
+ u8 rsvd1;
+ u8 status;
+};
+
+/*
+ * We want this header's alignment to be no more stringent than 2-byte aligned.
+ * All fields are u8 or u16 except for the length. However that field is not
+ * used so we break it into 2 16-bit parts to easily meet our alignment needs.
+ */
+struct cpl_tx_pkt {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 ip_csum_dis:1;
+ u8 l4_csum_dis:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 l4_csum_dis:1;
+ u8 ip_csum_dis:1;
+ u8 iff:4;
+#endif
+ u16 vlan;
+ u16 len_hi;
+ u16 len_lo;
+};
+
+struct cpl_tx_pkt_lso {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 ip_csum_dis:1;
+ u8 l4_csum_dis:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 l4_csum_dis:1;
+ u8 ip_csum_dis:1;
+ u8 iff:4;
+#endif
+ u16 vlan;
+ u32 len;
+
+ u32 rsvd2;
+ u8 rsvd3;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 tcp_hdr_words:4;
+ u8 ip_hdr_words:4;
+#else
+ u8 ip_hdr_words:4;
+ u8 tcp_hdr_words:4;
+#endif
+ u16 eth_type_mss;
+};
+
+struct cpl_rx_pkt {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 csum_valid:1;
+ u8 bad_pkt:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 bad_pkt:1;
+ u8 csum_valid:1;
+ u8 iff:4;
+#endif
+ u16 csum;
+ u16 vlan;
+ u16 len;
+};
+
+#endif /* _CXGB_CPL5_CMD_H_ */
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
new file mode 100644
index 000000000000..349ebe783ed6
--- /dev/null
+++ b/drivers/net/chelsio/cxgb2.c
@@ -0,0 +1,1256 @@
+/*****************************************************************************
+ * *
+ * File: cxgb2.c *
+ * $Revision: 1.25 $ *
+ * $Date: 2005/06/22 00:43:25 $ *
+ * Description: *
+ * Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/mii.h>
+#include <linux/sockios.h>
+#include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
+#include <asm/uaccess.h>
+
+#include "cpl5_cmd.h"
+#include "regs.h"
+#include "gmac.h"
+#include "cphy.h"
+#include "sge.h"
+#include "espi.h"
+
+#ifdef work_struct
+#include <linux/tqueue.h>
+#define INIT_WORK INIT_TQUEUE
+#define schedule_work schedule_task
+#define flush_scheduled_work flush_scheduled_tasks
+
+static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
+{
+ mod_timer(&ap->stats_update_timer, jiffies + secs * HZ);
+}
+
+static inline void cancel_mac_stats_update(struct adapter *ap)
+{
+ del_timer_sync(&ap->stats_update_timer);
+ flush_scheduled_tasks();
+}
+
+/*
+ * Stats update timer for 2.4. It schedules a task to do the actual update as
+ * we need to access MAC statistics in process context.
+ */
+static void mac_stats_timer(unsigned long data)
+{
+ struct adapter *ap = (struct adapter *)data;
+
+ schedule_task(&ap->stats_update_task);
+}
+#else
+#include <linux/workqueue.h>
+
+static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
+{
+ schedule_delayed_work(&ap->stats_update_task, secs * HZ);
+}
+
+static inline void cancel_mac_stats_update(struct adapter *ap)
+{
+ cancel_delayed_work(&ap->stats_update_task);
+}
+#endif
+
+#define MAX_CMDQ_ENTRIES 16384
+#define MAX_CMDQ1_ENTRIES 1024
+#define MAX_RX_BUFFERS 16384
+#define MAX_RX_JUMBO_BUFFERS 16384
+#define MAX_TX_BUFFERS_HIGH 16384U
+#define MAX_TX_BUFFERS_LOW 1536U
+#define MIN_FL_ENTRIES 32
+
+#define PORT_MASK ((1 << MAX_NPORTS) - 1)
+
+#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
+ NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
+ NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
+
+/*
+ * The EEPROM is actually bigger but only the first few bytes are used so we
+ * only report those.
+ */
+#define EEPROM_SIZE 32
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("Chelsio Communications");
+MODULE_LICENSE("GPL");
+
+static int dflt_msg_enable = DFLT_MSG_ENABLE;
+
+MODULE_PARM(dflt_msg_enable, "i");
+MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap");
+
+
+static const char pci_speed[][4] = {
+ "33", "66", "100", "133"
+};
+
+/*
+ * Setup MAC to receive the types of packets we want.
+ */
+static void t1_set_rxmode(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ struct t1_rx_mode rm;
+
+ rm.dev = dev;
+ rm.idx = 0;
+ rm.list = dev->mc_list;
+ mac->ops->set_rx_mode(mac, &rm);
+}
+
+static void link_report(struct port_info *p)
+{
+ if (!netif_carrier_ok(p->dev))
+ printk(KERN_INFO "%s: link down\n", p->dev->name);
+ else {
+ const char *s = "10Mbps";
+
+ switch (p->link_config.speed) {
+ case SPEED_10000: s = "10Gbps"; break;
+ case SPEED_1000: s = "1000Mbps"; break;
+ case SPEED_100: s = "100Mbps"; break;
+ }
+
+ printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
+ p->dev->name, s,
+ p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
+ }
+}
+
+void t1_link_changed(struct adapter *adapter, int port_id, int link_stat,
+ int speed, int duplex, int pause)
+{
+ struct port_info *p = &adapter->port[port_id];
+
+ if (link_stat != netif_carrier_ok(p->dev)) {
+ if (link_stat)
+ netif_carrier_on(p->dev);
+ else
+ netif_carrier_off(p->dev);
+ link_report(p);
+
+ }
+}
+
+static void link_start(struct port_info *p)
+{
+ struct cmac *mac = p->mac;
+
+ mac->ops->reset(mac);
+ if (mac->ops->macaddress_set)
+ mac->ops->macaddress_set(mac, p->dev->dev_addr);
+ t1_set_rxmode(p->dev);
+ t1_link_start(p->phy, mac, &p->link_config);
+ mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+}
+
+static void enable_hw_csum(struct adapter *adapter)
+{
+ if (adapter->flags & TSO_CAPABLE)
+ t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */
+ t1_tp_set_tcp_checksum_offload(adapter, 1);
+}
+
+/*
+ * Things to do upon first use of a card.
+ * This must run with the rtnl lock held.
+ */
+static int cxgb_up(struct adapter *adapter)
+{
+ int err = 0;
+
+ if (!(adapter->flags & FULL_INIT_DONE)) {
+ err = t1_init_hw_modules(adapter);
+ if (err)
+ goto out_err;
+
+ enable_hw_csum(adapter);
+ adapter->flags |= FULL_INIT_DONE;
+ }
+
+ t1_interrupts_clear(adapter);
+ if ((err = request_irq(adapter->pdev->irq,
+ t1_select_intr_handler(adapter), SA_SHIRQ,
+ adapter->name, adapter))) {
+ goto out_err;
+ }
+ t1_sge_start(adapter->sge);
+ t1_interrupts_enable(adapter);
+ out_err:
+ return err;
+}
+
+/*
+ * Release resources when all the ports have been stopped.
+ */
+static void cxgb_down(struct adapter *adapter)
+{
+ t1_sge_stop(adapter->sge);
+ t1_interrupts_disable(adapter);
+ free_irq(adapter->pdev->irq, adapter);
+}
+
+static int cxgb_open(struct net_device *dev)
+{
+ int err;
+ struct adapter *adapter = dev->priv;
+ int other_ports = adapter->open_device_map & PORT_MASK;
+
+ if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0)
+ return err;
+
+ __set_bit(dev->if_port, &adapter->open_device_map);
+ link_start(&adapter->port[dev->if_port]);
+ netif_start_queue(dev);
+ if (!other_ports && adapter->params.stats_update_period)
+ schedule_mac_stats_update(adapter,
+ adapter->params.stats_update_period);
+ return 0;
+}
+
+static int cxgb_close(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct cmac *mac = p->mac;
+
+ netif_stop_queue(dev);
+ mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
+ netif_carrier_off(dev);
+
+ clear_bit(dev->if_port, &adapter->open_device_map);
+ if (adapter->params.stats_update_period &&
+ !(adapter->open_device_map & PORT_MASK)) {
+ /* Stop statistics accumulation. */
+ smp_mb__after_clear_bit();
+ spin_lock(&adapter->work_lock); /* sync with update task */
+ spin_unlock(&adapter->work_lock);
+ cancel_mac_stats_update(adapter);
+ }
+
+ if (!adapter->open_device_map)
+ cxgb_down(adapter);
+ return 0;
+}
+
+static struct net_device_stats *t1_get_stats(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct net_device_stats *ns = &p->netstats;
+ const struct cmac_statistics *pstats;
+
+ /* Do a full update of the MAC stats */
+ pstats = p->mac->ops->statistics_update(p->mac,
+ MAC_STATS_UPDATE_FULL);
+
+ ns->tx_packets = pstats->TxUnicastFramesOK +
+ pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
+
+ ns->rx_packets = pstats->RxUnicastFramesOK +
+ pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
+
+ ns->tx_bytes = pstats->TxOctetsOK;
+ ns->rx_bytes = pstats->RxOctetsOK;
+
+ ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
+ pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
+ ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
+ pstats->RxFCSErrors + pstats->RxAlignErrors +
+ pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
+ pstats->RxSymbolErrors + pstats->RxRuntErrors;
+
+ ns->multicast = pstats->RxMulticastFramesOK;
+ ns->collisions = pstats->TxTotalCollisions;
+
+ /* detailed rx_errors */
+ ns->rx_length_errors = pstats->RxFrameTooLongErrors +
+ pstats->RxJabberErrors;
+ ns->rx_over_errors = 0;
+ ns->rx_crc_errors = pstats->RxFCSErrors;
+ ns->rx_frame_errors = pstats->RxAlignErrors;
+ ns->rx_fifo_errors = 0;
+ ns->rx_missed_errors = 0;
+
+ /* detailed tx_errors */
+ ns->tx_aborted_errors = pstats->TxFramesAbortedDueToXSCollisions;
+ ns->tx_carrier_errors = 0;
+ ns->tx_fifo_errors = pstats->TxUnderrun;
+ ns->tx_heartbeat_errors = 0;
+ ns->tx_window_errors = pstats->TxLateCollisions;
+ return ns;
+}
+
+static u32 get_msglevel(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+
+ return adapter->msg_enable;
+}
+
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+ struct adapter *adapter = dev->priv;
+
+ adapter->msg_enable = val;
+}
+
+static char stats_strings[][ETH_GSTRING_LEN] = {
+ "TxOctetsOK",
+ "TxOctetsBad",
+ "TxUnicastFramesOK",
+ "TxMulticastFramesOK",
+ "TxBroadcastFramesOK",
+ "TxPauseFrames",
+ "TxFramesWithDeferredXmissions",
+ "TxLateCollisions",
+ "TxTotalCollisions",
+ "TxFramesAbortedDueToXSCollisions",
+ "TxUnderrun",
+ "TxLengthErrors",
+ "TxInternalMACXmitError",
+ "TxFramesWithExcessiveDeferral",
+ "TxFCSErrors",
+
+ "RxOctetsOK",
+ "RxOctetsBad",
+ "RxUnicastFramesOK",
+ "RxMulticastFramesOK",
+ "RxBroadcastFramesOK",
+ "RxPauseFrames",
+ "RxFCSErrors",
+ "RxAlignErrors",
+ "RxSymbolErrors",
+ "RxDataErrors",
+ "RxSequenceErrors",
+ "RxRuntErrors",
+ "RxJabberErrors",
+ "RxInternalMACRcvError",
+ "RxInRangeLengthErrors",
+ "RxOutOfRangeLengthField",
+ "RxFrameTooLongErrors",
+
+ "TSO",
+ "VLANextractions",
+ "VLANinsertions",
+ "RxCsumGood",
+ "TxCsumOffload",
+ "RxDrops"
+
+ "respQ_empty",
+ "respQ_overflow",
+ "freelistQ_empty",
+ "pkt_too_big",
+ "pkt_mismatch",
+ "cmdQ_full0",
+ "cmdQ_full1",
+ "tx_ipfrags",
+ "tx_reg_pkts",
+ "tx_lso_pkts",
+ "tx_do_cksum",
+
+ "espi_DIP2ParityErr",
+ "espi_DIP4Err",
+ "espi_RxDrops",
+ "espi_TxDrops",
+ "espi_RxOvfl",
+ "espi_ParityErr"
+};
+
+#define T2_REGMAP_SIZE (3 * 1024)
+
+static int get_regs_len(struct net_device *dev)
+{
+ return T2_REGMAP_SIZE;
+}
+
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct adapter *adapter = dev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, pci_name(adapter->pdev));
+}
+
+static int get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(stats_strings);
+}
+
+static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ if (stringset == ETH_SS_STATS)
+ memcpy(data, stats_strings, sizeof(stats_strings));
+}
+
+static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ const struct cmac_statistics *s;
+ const struct sge_port_stats *ss;
+ const struct sge_intr_counts *t;
+
+ s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
+ ss = t1_sge_get_port_stats(adapter->sge, dev->if_port);
+ t = t1_sge_get_intr_counts(adapter->sge);
+
+ *data++ = s->TxOctetsOK;
+ *data++ = s->TxOctetsBad;
+ *data++ = s->TxUnicastFramesOK;
+ *data++ = s->TxMulticastFramesOK;
+ *data++ = s->TxBroadcastFramesOK;
+ *data++ = s->TxPauseFrames;
+ *data++ = s->TxFramesWithDeferredXmissions;
+ *data++ = s->TxLateCollisions;
+ *data++ = s->TxTotalCollisions;
+ *data++ = s->TxFramesAbortedDueToXSCollisions;
+ *data++ = s->TxUnderrun;
+ *data++ = s->TxLengthErrors;
+ *data++ = s->TxInternalMACXmitError;
+ *data++ = s->TxFramesWithExcessiveDeferral;
+ *data++ = s->TxFCSErrors;
+
+ *data++ = s->RxOctetsOK;
+ *data++ = s->RxOctetsBad;
+ *data++ = s->RxUnicastFramesOK;
+ *data++ = s->RxMulticastFramesOK;
+ *data++ = s->RxBroadcastFramesOK;
+ *data++ = s->RxPauseFrames;
+ *data++ = s->RxFCSErrors;
+ *data++ = s->RxAlignErrors;
+ *data++ = s->RxSymbolErrors;
+ *data++ = s->RxDataErrors;
+ *data++ = s->RxSequenceErrors;
+ *data++ = s->RxRuntErrors;
+ *data++ = s->RxJabberErrors;
+ *data++ = s->RxInternalMACRcvError;
+ *data++ = s->RxInRangeLengthErrors;
+ *data++ = s->RxOutOfRangeLengthField;
+ *data++ = s->RxFrameTooLongErrors;
+
+ *data++ = ss->tso;
+ *data++ = ss->vlan_xtract;
+ *data++ = ss->vlan_insert;
+ *data++ = ss->rx_cso_good;
+ *data++ = ss->tx_cso;
+ *data++ = ss->rx_drops;
+
+ *data++ = (u64)t->respQ_empty;
+ *data++ = (u64)t->respQ_overflow;
+ *data++ = (u64)t->freelistQ_empty;
+ *data++ = (u64)t->pkt_too_big;
+ *data++ = (u64)t->pkt_mismatch;
+ *data++ = (u64)t->cmdQ_full[0];
+ *data++ = (u64)t->cmdQ_full[1];
+ *data++ = (u64)t->tx_ipfrags;
+ *data++ = (u64)t->tx_reg_pkts;
+ *data++ = (u64)t->tx_lso_pkts;
+ *data++ = (u64)t->tx_do_cksum;
+}
+
+static inline void reg_block_dump(struct adapter *ap, void *buf,
+ unsigned int start, unsigned int end)
+{
+ u32 *p = buf + start;
+
+ for ( ; start <= end; start += sizeof(u32))
+ *p++ = readl(ap->regs + start);
+}
+
+static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *buf)
+{
+ struct adapter *ap = dev->priv;
+
+ /*
+ * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
+ */
+ regs->version = 2;
+
+ memset(buf, 0, T2_REGMAP_SIZE);
+ reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
+}
+
+static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+
+ cmd->supported = p->link_config.supported;
+ cmd->advertising = p->link_config.advertising;
+
+ if (netif_carrier_ok(dev)) {
+ cmd->speed = p->link_config.speed;
+ cmd->duplex = p->link_config.duplex;
+ } else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+
+ cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
+ cmd->phy_address = p->phy->addr;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = p->link_config.autoneg;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+ return 0;
+}
+
+static int speed_duplex_to_caps(int speed, int duplex)
+{
+ int cap = 0;
+
+ switch (speed) {
+ case SPEED_10:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_10baseT_Full;
+ else
+ cap = SUPPORTED_10baseT_Half;
+ break;
+ case SPEED_100:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_100baseT_Full;
+ else
+ cap = SUPPORTED_100baseT_Half;
+ break;
+ case SPEED_1000:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_1000baseT_Full;
+ else
+ cap = SUPPORTED_1000baseT_Half;
+ break;
+ case SPEED_10000:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_10000baseT_Full;
+ }
+ return cap;
+}
+
+#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
+ ADVERTISED_10000baseT_Full)
+
+static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct link_config *lc = &p->link_config;
+
+ if (!(lc->supported & SUPPORTED_Autoneg))
+ return -EOPNOTSUPP; /* can't change speed/duplex */
+
+ if (cmd->autoneg == AUTONEG_DISABLE) {
+ int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
+
+ if (!(lc->supported & cap) || cmd->speed == SPEED_1000)
+ return -EINVAL;
+ lc->requested_speed = cmd->speed;
+ lc->requested_duplex = cmd->duplex;
+ lc->advertising = 0;
+ } else {
+ cmd->advertising &= ADVERTISED_MASK;
+ if (cmd->advertising & (cmd->advertising - 1))
+ cmd->advertising = lc->supported;
+ cmd->advertising &= lc->supported;
+ if (!cmd->advertising)
+ return -EINVAL;
+ lc->requested_speed = SPEED_INVALID;
+ lc->requested_duplex = DUPLEX_INVALID;
+ lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
+ }
+ lc->autoneg = cmd->autoneg;
+ if (netif_running(dev))
+ t1_link_start(p->phy, p->mac, lc);
+ return 0;
+}
+
+static void get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+
+ epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
+ epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
+ epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
+}
+
+static int set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct link_config *lc = &p->link_config;
+
+ if (epause->autoneg == AUTONEG_DISABLE)
+ lc->requested_fc = 0;
+ else if (lc->supported & SUPPORTED_Autoneg)
+ lc->requested_fc = PAUSE_AUTONEG;
+ else
+ return -EINVAL;
+
+ if (epause->rx_pause)
+ lc->requested_fc |= PAUSE_RX;
+ if (epause->tx_pause)
+ lc->requested_fc |= PAUSE_TX;
+ if (lc->autoneg == AUTONEG_ENABLE) {
+ if (netif_running(dev))
+ t1_link_start(p->phy, p->mac, lc);
+ } else {
+ lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+ if (netif_running(dev))
+ p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
+ lc->fc);
+ }
+ return 0;
+}
+
+static u32 get_rx_csum(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+
+ return (adapter->flags & RX_CSUM_ENABLED) != 0;
+}
+
+static int set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct adapter *adapter = dev->priv;
+
+ if (data)
+ adapter->flags |= RX_CSUM_ENABLED;
+ else
+ adapter->flags &= ~RX_CSUM_ENABLED;
+ return 0;
+}
+
+static int set_tso(struct net_device *dev, u32 value)
+{
+ struct adapter *adapter = dev->priv;
+
+ if (!(adapter->flags & TSO_CAPABLE))
+ return value ? -EOPNOTSUPP : 0;
+ return ethtool_op_set_tso(dev, value);
+}
+
+static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
+{
+ struct adapter *adapter = dev->priv;
+ int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ e->rx_max_pending = MAX_RX_BUFFERS;
+ e->rx_mini_max_pending = 0;
+ e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
+ e->tx_max_pending = MAX_CMDQ_ENTRIES;
+
+ e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
+ e->rx_mini_pending = 0;
+ e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
+ e->tx_pending = adapter->params.sge.cmdQ_size[0];
+}
+
+static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
+{
+ struct adapter *adapter = dev->priv;
+ int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
+ e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
+ e->tx_pending > MAX_CMDQ_ENTRIES ||
+ e->rx_pending < MIN_FL_ENTRIES ||
+ e->rx_jumbo_pending < MIN_FL_ENTRIES ||
+ e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
+ return -EINVAL;
+
+ if (adapter->flags & FULL_INIT_DONE)
+ return -EBUSY;
+
+ adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
+ adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
+ adapter->params.sge.cmdQ_size[0] = e->tx_pending;
+ adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
+ MAX_CMDQ1_ENTRIES : e->tx_pending;
+ return 0;
+}
+
+static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+{
+ struct adapter *adapter = dev->priv;
+
+ /*
+ * If RX coalescing is requested we use NAPI, otherwise interrupts.
+ * This choice can be made only when all ports and the TOE are off.
+ */
+ if (adapter->open_device_map == 0)
+ adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
+
+ if (adapter->params.sge.polling) {
+ adapter->params.sge.rx_coalesce_usecs = 0;
+ } else {
+ adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
+ }
+ adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
+ adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
+ t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
+ return 0;
+}
+
+static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+{
+ struct adapter *adapter = dev->priv;
+
+ c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
+ c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
+ c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
+ return 0;
+}
+
+static int get_eeprom_len(struct net_device *dev)
+{
+ return EEPROM_SIZE;
+}
+
+#define EEPROM_MAGIC(ap) \
+ (PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
+
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
+ u8 *data)
+{
+ int i;
+ u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
+ struct adapter *adapter = dev->priv;
+
+ e->magic = EEPROM_MAGIC(adapter);
+ for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
+ t1_seeprom_read(adapter, i, (u32 *)&buf[i]);
+ memcpy(data, buf + e->offset, e->len);
+ return 0;
+}
+
+static struct ethtool_ops t1_ethtool_ops = {
+ .get_settings = get_settings,
+ .set_settings = set_settings,
+ .get_drvinfo = get_drvinfo,
+ .get_msglevel = get_msglevel,
+ .set_msglevel = set_msglevel,
+ .get_ringparam = get_sge_param,
+ .set_ringparam = set_sge_param,
+ .get_coalesce = get_coalesce,
+ .set_coalesce = set_coalesce,
+ .get_eeprom_len = get_eeprom_len,
+ .get_eeprom = get_eeprom,
+ .get_pauseparam = get_pauseparam,
+ .set_pauseparam = set_pauseparam,
+ .get_rx_csum = get_rx_csum,
+ .set_rx_csum = set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_link = ethtool_op_get_link,
+ .get_strings = get_strings,
+ .get_stats_count = get_stats_count,
+ .get_ethtool_stats = get_stats,
+ .get_regs_len = get_regs_len,
+ .get_regs = get_regs,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = set_tso,
+};
+
+static void cxgb_proc_cleanup(struct adapter *adapter,
+ struct proc_dir_entry *dir)
+{
+ const char *name;
+ name = adapter->name;
+ remove_proc_entry(name, dir);
+}
+//#define chtoe_setup_toedev(adapter) NULL
+#define update_mtu_tab(adapter)
+#define write_smt_entry(adapter, idx)
+
+static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct mii_ioctl_data *data = if_mii(req);
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = adapter->port[dev->if_port].phy->addr;
+ /* FALLTHRU */
+ case SIOCGMIIREG: {
+ struct cphy *phy = adapter->port[dev->if_port].phy;
+ u32 val;
+
+ if (!phy->mdio_read)
+ return -EOPNOTSUPP;
+ phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
+ &val);
+ data->val_out = val;
+ break;
+ }
+ case SIOCSMIIREG: {
+ struct cphy *phy = adapter->port[dev->if_port].phy;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (!phy->mdio_write)
+ return -EOPNOTSUPP;
+ phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
+ data->val_in);
+ break;
+ }
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int t1_change_mtu(struct net_device *dev, int new_mtu)
+{
+ int ret;
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+
+ if (!mac->ops->set_mtu)
+ return -EOPNOTSUPP;
+ if (new_mtu < 68)
+ return -EINVAL;
+ if ((ret = mac->ops->set_mtu(mac, new_mtu)))
+ return ret;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static int t1_set_mac_addr(struct net_device *dev, void *p)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ struct sockaddr *addr = p;
+
+ if (!mac->ops->macaddress_set)
+ return -EOPNOTSUPP;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ mac->ops->macaddress_set(mac, dev->dev_addr);
+ return 0;
+}
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+static void vlan_rx_register(struct net_device *dev,
+ struct vlan_group *grp)
+{
+ struct adapter *adapter = dev->priv;
+
+ spin_lock_irq(&adapter->async_lock);
+ adapter->vlan_grp = grp;
+ t1_set_vlan_accel(adapter, grp != NULL);
+ spin_unlock_irq(&adapter->async_lock);
+}
+
+static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct adapter *adapter = dev->priv;
+
+ spin_lock_irq(&adapter->async_lock);
+ if (adapter->vlan_grp)
+ adapter->vlan_grp->vlan_devices[vid] = NULL;
+ spin_unlock_irq(&adapter->async_lock);
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void t1_netpoll(struct net_device *dev)
+{
+ unsigned long flags;
+ struct adapter *adapter = dev->priv;
+
+ local_irq_save(flags);
+ t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter, NULL);
+ local_irq_restore(flags);
+}
+#endif
+
+/*
+ * Periodic accumulation of MAC statistics. This is used only if the MAC
+ * does not have any other way to prevent stats counter overflow.
+ */
+static void mac_stats_task(void *data)
+{
+ int i;
+ struct adapter *adapter = data;
+
+ for_each_port(adapter, i) {
+ struct port_info *p = &adapter->port[i];
+
+ if (netif_running(p->dev))
+ p->mac->ops->statistics_update(p->mac,
+ MAC_STATS_UPDATE_FAST);
+ }
+
+ /* Schedule the next statistics update if any port is active. */
+ spin_lock(&adapter->work_lock);
+ if (adapter->open_device_map & PORT_MASK)
+ schedule_mac_stats_update(adapter,
+ adapter->params.stats_update_period);
+ spin_unlock(&adapter->work_lock);
+}
+
+/*
+ * Processes elmer0 external interrupts in process context.
+ */
+static void ext_intr_task(void *data)
+{
+ struct adapter *adapter = data;
+
+ elmer0_ext_intr_handler(adapter);
+
+ /* Now reenable external interrupts */
+ spin_lock_irq(&adapter->async_lock);
+ adapter->slow_intr_mask |= F_PL_INTR_EXT;
+ writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
+ writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+ adapter->regs + A_PL_ENABLE);
+ spin_unlock_irq(&adapter->async_lock);
+}
+
+/*
+ * Interrupt-context handler for elmer0 external interrupts.
+ */
+void t1_elmer0_ext_intr(struct adapter *adapter)
+{
+ /*
+ * Schedule a task to handle external interrupts as we require
+ * a process context. We disable EXT interrupts in the interim
+ * and let the task reenable them when it's done.
+ */
+ adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
+ writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+ adapter->regs + A_PL_ENABLE);
+ schedule_work(&adapter->ext_intr_handler_task);
+}
+
+void t1_fatal_err(struct adapter *adapter)
+{
+ if (adapter->flags & FULL_INIT_DONE) {
+ t1_sge_stop(adapter->sge);
+ t1_interrupts_disable(adapter);
+ }
+ CH_ALERT("%s: encountered fatal error, operation suspended\n",
+ adapter->name);
+}
+
+static int __devinit init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int version_printed;
+
+ int i, err, pci_using_dac = 0;
+ unsigned long mmio_start, mmio_len;
+ const struct board_info *bi;
+ struct adapter *adapter = NULL;
+ struct port_info *pi;
+
+ if (!version_printed) {
+ printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
+ DRV_VERSION);
+ ++version_printed;
+ }
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ CH_ERR("%s: cannot find PCI device memory base address\n",
+ pci_name(pdev));
+ err = -ENODEV;
+ goto out_disable_pdev;
+ }
+
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ pci_using_dac = 1;
+
+ if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
+ CH_ERR("%s: unable to obtain 64-bit DMA for"
+ "consistent allocations\n", pci_name(pdev));
+ err = -ENODEV;
+ goto out_disable_pdev;
+ }
+
+ } else if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
+ CH_ERR("%s: no usable DMA configuration\n", pci_name(pdev));
+ goto out_disable_pdev;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ CH_ERR("%s: cannot obtain PCI resources\n", pci_name(pdev));
+ goto out_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ mmio_start = pci_resource_start(pdev, 0);
+ mmio_len = pci_resource_len(pdev, 0);
+ bi = t1_get_board_info(ent->driver_data);
+
+ for (i = 0; i < bi->port_number; ++i) {
+ struct net_device *netdev;
+
+ netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto out_free_dev;
+ }
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ if (!adapter) {
+ adapter = netdev->priv;
+ adapter->pdev = pdev;
+ adapter->port[0].dev = netdev; /* so we don't leak it */
+
+ adapter->regs = ioremap(mmio_start, mmio_len);
+ if (!adapter->regs) {
+ CH_ERR("%s: cannot map device registers\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto out_free_dev;
+ }
+
+ if (t1_get_board_rev(adapter, bi, &adapter->params)) {
+ err = -ENODEV; /* Can't handle this chip rev */
+ goto out_free_dev;
+ }
+
+ adapter->name = pci_name(pdev);
+ adapter->msg_enable = dflt_msg_enable;
+ adapter->mmio_len = mmio_len;
+
+ init_MUTEX(&adapter->mib_mutex);
+ spin_lock_init(&adapter->tpi_lock);
+ spin_lock_init(&adapter->work_lock);
+ spin_lock_init(&adapter->async_lock);
+
+ INIT_WORK(&adapter->ext_intr_handler_task,
+ ext_intr_task, adapter);
+ INIT_WORK(&adapter->stats_update_task, mac_stats_task,
+ adapter);
+#ifdef work_struct
+ init_timer(&adapter->stats_update_timer);
+ adapter->stats_update_timer.function = mac_stats_timer;
+ adapter->stats_update_timer.data =
+ (unsigned long)adapter;
+#endif
+
+ pci_set_drvdata(pdev, netdev);
+ }
+
+ pi = &adapter->port[i];
+ pi->dev = netdev;
+ netif_carrier_off(netdev);
+ netdev->irq = pdev->irq;
+ netdev->if_port = i;
+ netdev->mem_start = mmio_start;
+ netdev->mem_end = mmio_start + mmio_len - 1;
+ netdev->priv = adapter;
+ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_LLTX;
+
+ adapter->flags |= RX_CSUM_ENABLED | TCP_CSUM_CAPABLE;
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+ if (vlan_tso_capable(adapter)) {
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ adapter->flags |= VLAN_ACCEL_CAPABLE;
+ netdev->features |=
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->vlan_rx_register = vlan_rx_register;
+ netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
+#endif
+ adapter->flags |= TSO_CAPABLE;
+ netdev->features |= NETIF_F_TSO;
+ }
+
+ netdev->open = cxgb_open;
+ netdev->stop = cxgb_close;
+ netdev->hard_start_xmit = t1_start_xmit;
+ netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
+ sizeof(struct cpl_tx_pkt_lso) :
+ sizeof(struct cpl_tx_pkt);
+ netdev->get_stats = t1_get_stats;
+ netdev->set_multicast_list = t1_set_rxmode;
+ netdev->do_ioctl = t1_ioctl;
+ netdev->change_mtu = t1_change_mtu;
+ netdev->set_mac_address = t1_set_mac_addr;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = t1_netpoll;
+#endif
+ netdev->weight = 64;
+
+ SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
+ }
+
+ if (t1_init_sw_modules(adapter, bi) < 0) {
+ err = -ENODEV;
+ goto out_free_dev;
+ }
+
+ /*
+ * The card is now ready to go. If any errors occur during device
+ * registration we do not fail the whole card but rather proceed only
+ * with the ports we manage to register successfully. However we must
+ * register at least one net device.
+ */
+ for (i = 0; i < bi->port_number; ++i) {
+ err = register_netdev(adapter->port[i].dev);
+ if (err)
+ CH_WARN("%s: cannot register net device %s, skipping\n",
+ pci_name(pdev), adapter->port[i].dev->name);
+ else {
+ /*
+ * Change the name we use for messages to the name of
+ * the first successfully registered interface.
+ */
+ if (!adapter->registered_device_map)
+ adapter->name = adapter->port[i].dev->name;
+
+ __set_bit(i, &adapter->registered_device_map);
+ }
+ }
+ if (!adapter->registered_device_map) {
+ CH_ERR("%s: could not register any net devices\n",
+ pci_name(pdev));
+ goto out_release_adapter_res;
+ }
+
+ printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
+ bi->desc, adapter->params.chip_revision,
+ adapter->params.pci.is_pcix ? "PCIX" : "PCI",
+ adapter->params.pci.speed, adapter->params.pci.width);
+ return 0;
+
+ out_release_adapter_res:
+ t1_free_sw_modules(adapter);
+ out_free_dev:
+ if (adapter) {
+ if (adapter->regs) iounmap(adapter->regs);
+ for (i = bi->port_number - 1; i >= 0; --i)
+ if (adapter->port[i].dev) {
+ cxgb_proc_cleanup(adapter, proc_root_driver);
+ kfree(adapter->port[i].dev);
+ }
+ }
+ pci_release_regions(pdev);
+ out_disable_pdev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static inline void t1_sw_reset(struct pci_dev *pdev)
+{
+ pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
+ pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
+}
+
+static void __devexit remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (dev) {
+ int i;
+ struct adapter *adapter = dev->priv;
+
+ for_each_port(adapter, i)
+ if (test_bit(i, &adapter->registered_device_map))
+ unregister_netdev(adapter->port[i].dev);
+
+ t1_free_sw_modules(adapter);
+ iounmap(adapter->regs);
+ while (--i >= 0)
+ if (adapter->port[i].dev) {
+ cxgb_proc_cleanup(adapter, proc_root_driver);
+ kfree(adapter->port[i].dev);
+ }
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ t1_sw_reset(pdev);
+ }
+}
+
+static struct pci_driver driver = {
+ .name = DRV_NAME,
+ .id_table = t1_pci_tbl,
+ .probe = init_one,
+ .remove = __devexit_p(remove_one),
+};
+
+static int __init t1_init_module(void)
+{
+ return pci_module_init(&driver);
+}
+
+static void __exit t1_cleanup_module(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(t1_init_module);
+module_exit(t1_cleanup_module);
diff --git a/drivers/net/chelsio/elmer0.h b/drivers/net/chelsio/elmer0.h
new file mode 100644
index 000000000000..5590cb2dac19
--- /dev/null
+++ b/drivers/net/chelsio/elmer0.h
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ * *
+ * File: elmer0.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 22:49:43 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_ELMER0_H_
+#define _CXGB_ELMER0_H_
+
+/* ELMER0 registers */
+#define A_ELMER0_VERSION 0x100000
+#define A_ELMER0_PHY_CFG 0x100004
+#define A_ELMER0_INT_ENABLE 0x100008
+#define A_ELMER0_INT_CAUSE 0x10000c
+#define A_ELMER0_GPI_CFG 0x100010
+#define A_ELMER0_GPI_STAT 0x100014
+#define A_ELMER0_GPO 0x100018
+#define A_ELMER0_PORT0_MI1_CFG 0x400000
+
+#define S_MI1_MDI_ENABLE 0
+#define V_MI1_MDI_ENABLE(x) ((x) << S_MI1_MDI_ENABLE)
+#define F_MI1_MDI_ENABLE V_MI1_MDI_ENABLE(1U)
+
+#define S_MI1_MDI_INVERT 1
+#define V_MI1_MDI_INVERT(x) ((x) << S_MI1_MDI_INVERT)
+#define F_MI1_MDI_INVERT V_MI1_MDI_INVERT(1U)
+
+#define S_MI1_PREAMBLE_ENABLE 2
+#define V_MI1_PREAMBLE_ENABLE(x) ((x) << S_MI1_PREAMBLE_ENABLE)
+#define F_MI1_PREAMBLE_ENABLE V_MI1_PREAMBLE_ENABLE(1U)
+
+#define S_MI1_SOF 3
+#define M_MI1_SOF 0x3
+#define V_MI1_SOF(x) ((x) << S_MI1_SOF)
+#define G_MI1_SOF(x) (((x) >> S_MI1_SOF) & M_MI1_SOF)
+
+#define S_MI1_CLK_DIV 5
+#define M_MI1_CLK_DIV 0xff
+#define V_MI1_CLK_DIV(x) ((x) << S_MI1_CLK_DIV)
+#define G_MI1_CLK_DIV(x) (((x) >> S_MI1_CLK_DIV) & M_MI1_CLK_DIV)
+
+#define A_ELMER0_PORT0_MI1_ADDR 0x400004
+
+#define S_MI1_REG_ADDR 0
+#define M_MI1_REG_ADDR 0x1f
+#define V_MI1_REG_ADDR(x) ((x) << S_MI1_REG_ADDR)
+#define G_MI1_REG_ADDR(x) (((x) >> S_MI1_REG_ADDR) & M_MI1_REG_ADDR)
+
+#define S_MI1_PHY_ADDR 5
+#define M_MI1_PHY_ADDR 0x1f
+#define V_MI1_PHY_ADDR(x) ((x) << S_MI1_PHY_ADDR)
+#define G_MI1_PHY_ADDR(x) (((x) >> S_MI1_PHY_ADDR) & M_MI1_PHY_ADDR)
+
+#define A_ELMER0_PORT0_MI1_DATA 0x400008
+
+#define S_MI1_DATA 0
+#define M_MI1_DATA 0xffff
+#define V_MI1_DATA(x) ((x) << S_MI1_DATA)
+#define G_MI1_DATA(x) (((x) >> S_MI1_DATA) & M_MI1_DATA)
+
+#define A_ELMER0_PORT0_MI1_OP 0x40000c
+
+#define S_MI1_OP 0
+#define M_MI1_OP 0x3
+#define V_MI1_OP(x) ((x) << S_MI1_OP)
+#define G_MI1_OP(x) (((x) >> S_MI1_OP) & M_MI1_OP)
+
+#define S_MI1_ADDR_AUTOINC 2
+#define V_MI1_ADDR_AUTOINC(x) ((x) << S_MI1_ADDR_AUTOINC)
+#define F_MI1_ADDR_AUTOINC V_MI1_ADDR_AUTOINC(1U)
+
+#define S_MI1_OP_BUSY 31
+#define V_MI1_OP_BUSY(x) ((x) << S_MI1_OP_BUSY)
+#define F_MI1_OP_BUSY V_MI1_OP_BUSY(1U)
+
+#define A_ELMER0_PORT1_MI1_CFG 0x500000
+#define A_ELMER0_PORT1_MI1_ADDR 0x500004
+#define A_ELMER0_PORT1_MI1_DATA 0x500008
+#define A_ELMER0_PORT1_MI1_OP 0x50000c
+#define A_ELMER0_PORT2_MI1_CFG 0x600000
+#define A_ELMER0_PORT2_MI1_ADDR 0x600004
+#define A_ELMER0_PORT2_MI1_DATA 0x600008
+#define A_ELMER0_PORT2_MI1_OP 0x60000c
+#define A_ELMER0_PORT3_MI1_CFG 0x700000
+#define A_ELMER0_PORT3_MI1_ADDR 0x700004
+#define A_ELMER0_PORT3_MI1_DATA 0x700008
+#define A_ELMER0_PORT3_MI1_OP 0x70000c
+
+/* Simple bit definition for GPI and GP0 registers. */
+#define ELMER0_GP_BIT0 0x0001
+#define ELMER0_GP_BIT1 0x0002
+#define ELMER0_GP_BIT2 0x0004
+#define ELMER0_GP_BIT3 0x0008
+#define ELMER0_GP_BIT4 0x0010
+#define ELMER0_GP_BIT5 0x0020
+#define ELMER0_GP_BIT6 0x0040
+#define ELMER0_GP_BIT7 0x0080
+#define ELMER0_GP_BIT8 0x0100
+#define ELMER0_GP_BIT9 0x0200
+#define ELMER0_GP_BIT10 0x0400
+#define ELMER0_GP_BIT11 0x0800
+#define ELMER0_GP_BIT12 0x1000
+#define ELMER0_GP_BIT13 0x2000
+#define ELMER0_GP_BIT14 0x4000
+#define ELMER0_GP_BIT15 0x8000
+#define ELMER0_GP_BIT16 0x10000
+#define ELMER0_GP_BIT17 0x20000
+#define ELMER0_GP_BIT18 0x40000
+#define ELMER0_GP_BIT19 0x80000
+
+#define MI1_OP_DIRECT_WRITE 1
+#define MI1_OP_DIRECT_READ 2
+
+#define MI1_OP_INDIRECT_ADDRESS 0
+#define MI1_OP_INDIRECT_WRITE 1
+#define MI1_OP_INDIRECT_READ_INC 2
+#define MI1_OP_INDIRECT_READ 3
+
+#endif /* _CXGB_ELMER0_H_ */
diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c
new file mode 100644
index 000000000000..230642571c92
--- /dev/null
+++ b/drivers/net/chelsio/espi.c
@@ -0,0 +1,346 @@
+/*****************************************************************************
+ * *
+ * File: espi.c *
+ * $Revision: 1.14 $ *
+ * $Date: 2005/05/14 00:59:32 $ *
+ * Description: *
+ * Ethernet SPI functionality. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "regs.h"
+#include "espi.h"
+
+struct peespi {
+ adapter_t *adapter;
+ struct espi_intr_counts intr_cnt;
+ u32 misc_ctrl;
+ spinlock_t lock;
+};
+
+#define ESPI_INTR_MASK (F_DIP4ERR | F_RXDROP | F_TXDROP | F_RXOVERFLOW | \
+ F_RAMPARITYERR | F_DIP2PARITYERR)
+#define MON_MASK (V_MONITORED_PORT_NUM(3) | F_MONITORED_DIRECTION \
+ | F_MONITORED_INTERFACE)
+
+#define TRICN_CNFG 14
+#define TRICN_CMD_READ 0x11
+#define TRICN_CMD_WRITE 0x21
+#define TRICN_CMD_ATTEMPTS 10
+
+static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
+ int ch_addr, int reg_offset, u32 wr_data)
+{
+ int busy, attempts = TRICN_CMD_ATTEMPTS;
+
+ writel(V_WRITE_DATA(wr_data) |
+ V_REGISTER_OFFSET(reg_offset) |
+ V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
+ V_BUNDLE_ADDR(bundle_addr) |
+ V_SPI4_COMMAND(TRICN_CMD_WRITE),
+ adapter->regs + A_ESPI_CMD_ADDR);
+ writel(0, adapter->regs + A_ESPI_GOSTAT);
+
+ do {
+ busy = readl(adapter->regs + A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
+ } while (busy && --attempts);
+
+ if (busy)
+ CH_ERR("%s: TRICN write timed out\n", adapter->name);
+
+ return busy;
+}
+
+/* 1. Deassert rx_reset_core. */
+/* 2. Program TRICN_CNFG registers. */
+/* 3. Deassert rx_reset_link */
+static int tricn_init(adapter_t *adapter)
+{
+ int i = 0;
+ int sme = 1;
+ int stat = 0;
+ int timeout = 0;
+ int is_ready = 0;
+ int dynamic_deskew = 0;
+
+ if (dynamic_deskew)
+ sme = 0;
+
+
+ /* 1 */
+ timeout=1000;
+ do {
+ stat = readl(adapter->regs + A_ESPI_RX_RESET);
+ is_ready = (stat & 0x4);
+ timeout--;
+ udelay(5);
+ } while (!is_ready || (timeout==0));
+ writel(0x2, adapter->regs + A_ESPI_RX_RESET);
+ if (timeout==0)
+ {
+ CH_ERR("ESPI : ERROR : Timeout tricn_init() \n");
+ t1_fatal_err(adapter);
+ }
+
+ /* 2 */
+ if (sme) {
+ tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
+ }
+ for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
+ for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
+ for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ for (i=4; i<= 4; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+ for (i=5; i<= 5; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ for (i=6; i<= 6; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+ for (i=7; i<= 7; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0x80);
+ for (i=8; i<= 8; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+
+ /* 3 */
+ writel(0x3, adapter->regs + A_ESPI_RX_RESET);
+
+ return 0;
+}
+
+void t1_espi_intr_enable(struct peespi *espi)
+{
+ u32 enable, pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
+
+ /*
+ * Cannot enable ESPI interrupts on T1B because HW asserts the
+ * interrupt incorrectly, namely the driver gets ESPI interrupts
+ * but no data is actually dropped (can verify this reading the ESPI
+ * drop registers). Also, once the ESPI interrupt is asserted it
+ * cannot be cleared (HW bug).
+ */
+ enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
+ writel(enable, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr | F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
+}
+
+void t1_espi_intr_clear(struct peespi *espi)
+{
+ writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
+ writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
+}
+
+void t1_espi_intr_disable(struct peespi *espi)
+{
+ u32 pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
+
+ writel(0, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr & ~F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
+}
+
+int t1_espi_intr_handler(struct peespi *espi)
+{
+ u32 cnt;
+ u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
+
+ if (status & F_DIP4ERR)
+ espi->intr_cnt.DIP4_err++;
+ if (status & F_RXDROP)
+ espi->intr_cnt.rx_drops++;
+ if (status & F_TXDROP)
+ espi->intr_cnt.tx_drops++;
+ if (status & F_RXOVERFLOW)
+ espi->intr_cnt.rx_ovflw++;
+ if (status & F_RAMPARITYERR)
+ espi->intr_cnt.parity_err++;
+ if (status & F_DIP2PARITYERR) {
+ espi->intr_cnt.DIP2_parity_err++;
+
+ /*
+ * Must read the error count to clear the interrupt
+ * that it causes.
+ */
+ cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ }
+
+ /*
+ * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
+ * write the status as is.
+ */
+ if (status && t1_is_T1B(espi->adapter))
+ status = 1;
+ writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
+ return 0;
+}
+
+const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
+{
+ return &espi->intr_cnt;
+}
+
+static void espi_setup_for_pm3393(adapter_t *adapter)
+{
+ u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
+
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN1);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(0x100, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ writel(wmark, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(3, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
+ writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
+}
+
+/* T2 Init part -- */
+/* 1. Set T_ESPI_MISCCTRL_ADDR */
+/* 2. Init ESPI registers. */
+/* 3. Init TriCN Hard Macro */
+int t1_espi_init(struct peespi *espi, int mac_type, int nports)
+{
+ u32 cnt;
+
+ u32 status_enable_extra = 0;
+ adapter_t *adapter = espi->adapter;
+ u32 status, burstval = 0x800100;
+
+ /* Disable ESPI training. MACs that can handle it enable it below. */
+ writel(0, adapter->regs + A_ESPI_TRAIN);
+
+ if (is_T2(adapter)) {
+ writel(V_OUT_OF_SYNC_COUNT(4) |
+ V_DIP2_PARITY_ERR_THRES(3) |
+ V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
+ if (nports == 4) {
+ /* T204: maxburst1 = 0x40, maxburst2 = 0x20 */
+ burstval = 0x200040;
+ }
+ }
+ writel(burstval, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
+
+ switch (mac_type) {
+ case CHBT_MAC_PM3393:
+ espi_setup_for_pm3393(adapter);
+ break;
+ default:
+ return -1;
+ }
+
+ /*
+ * Make sure any pending interrupts from the SPI are
+ * Cleared before enabling the interrupt.
+ */
+ writel(ESPI_INTR_MASK, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
+ if (status & F_DIP2PARITYERR) {
+ cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ }
+
+ /*
+ * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
+ * write the status as is.
+ */
+ if (status && t1_is_T1B(espi->adapter))
+ status = 1;
+ writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
+
+ writel(status_enable_extra | F_RXSTATUSENABLE,
+ adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
+
+ if (is_T2(adapter)) {
+ tricn_init(adapter);
+ /*
+ * Always position the control at the 1st port egress IN
+ * (sop,eop) counter to reduce PIOs for T/N210 workaround.
+ */
+ espi->misc_ctrl = (readl(adapter->regs + A_ESPI_MISC_CONTROL)
+ & ~MON_MASK) | (F_MONITORED_DIRECTION
+ | F_MONITORED_INTERFACE);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_lock_init(&espi->lock);
+ }
+
+ return 0;
+}
+
+void t1_espi_destroy(struct peespi *espi)
+{
+ kfree(espi);
+}
+
+struct peespi *t1_espi_create(adapter_t *adapter)
+{
+ struct peespi *espi = kmalloc(sizeof(*espi), GFP_KERNEL);
+
+ memset(espi, 0, sizeof(*espi));
+
+ if (espi)
+ espi->adapter = adapter;
+ return espi;
+}
+
+void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
+{
+ struct peespi *espi = adapter->espi;
+
+ if (!is_T2(adapter))
+ return;
+ spin_lock(&espi->lock);
+ espi->misc_ctrl = (val & ~MON_MASK) |
+ (espi->misc_ctrl & MON_MASK);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_unlock(&espi->lock);
+}
+
+u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
+{
+ u32 sel;
+
+ struct peespi *espi = adapter->espi;
+
+ if (!is_T2(adapter))
+ return 0;
+ sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
+ if (!wait) {
+ if (!spin_trylock(&espi->lock))
+ return 0;
+ }
+ else
+ spin_lock(&espi->lock);
+ if ((sel != (espi->misc_ctrl & MON_MASK))) {
+ writel(((espi->misc_ctrl & ~MON_MASK) | sel),
+ adapter->regs + A_ESPI_MISC_CONTROL);
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ else
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ spin_unlock(&espi->lock);
+ return sel;
+}
diff --git a/drivers/net/chelsio/espi.h b/drivers/net/chelsio/espi.h
new file mode 100644
index 000000000000..c90e37f8457c
--- /dev/null
+++ b/drivers/net/chelsio/espi.h
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * *
+ * File: espi.h *
+ * $Revision: 1.7 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_ESPI_H_
+#define _CXGB_ESPI_H_
+
+#include "common.h"
+
+struct espi_intr_counts {
+ unsigned int DIP4_err;
+ unsigned int rx_drops;
+ unsigned int tx_drops;
+ unsigned int rx_ovflw;
+ unsigned int parity_err;
+ unsigned int DIP2_parity_err;
+};
+
+struct peespi;
+
+struct peespi *t1_espi_create(adapter_t *adapter);
+void t1_espi_destroy(struct peespi *espi);
+int t1_espi_init(struct peespi *espi, int mac_type, int nports);
+
+void t1_espi_intr_enable(struct peespi *);
+void t1_espi_intr_clear(struct peespi *);
+void t1_espi_intr_disable(struct peespi *);
+int t1_espi_intr_handler(struct peespi *);
+const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi);
+
+void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val);
+u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait);
+
+#endif /* _CXGB_ESPI_H_ */
diff --git a/drivers/net/chelsio/gmac.h b/drivers/net/chelsio/gmac.h
new file mode 100644
index 000000000000..746b0eeea964
--- /dev/null
+++ b/drivers/net/chelsio/gmac.h
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * *
+ * File: gmac.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * Generic MAC functionality. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_GMAC_H_
+#define _CXGB_GMAC_H_
+
+#include "common.h"
+
+enum { MAC_STATS_UPDATE_FAST, MAC_STATS_UPDATE_FULL };
+enum { MAC_DIRECTION_RX = 1, MAC_DIRECTION_TX = 2 };
+
+struct cmac_statistics {
+ /* Transmit */
+ u64 TxOctetsOK;
+ u64 TxOctetsBad;
+ u64 TxUnicastFramesOK;
+ u64 TxMulticastFramesOK;
+ u64 TxBroadcastFramesOK;
+ u64 TxPauseFrames;
+ u64 TxFramesWithDeferredXmissions;
+ u64 TxLateCollisions;
+ u64 TxTotalCollisions;
+ u64 TxFramesAbortedDueToXSCollisions;
+ u64 TxUnderrun;
+ u64 TxLengthErrors;
+ u64 TxInternalMACXmitError;
+ u64 TxFramesWithExcessiveDeferral;
+ u64 TxFCSErrors;
+
+ /* Receive */
+ u64 RxOctetsOK;
+ u64 RxOctetsBad;
+ u64 RxUnicastFramesOK;
+ u64 RxMulticastFramesOK;
+ u64 RxBroadcastFramesOK;
+ u64 RxPauseFrames;
+ u64 RxFCSErrors;
+ u64 RxAlignErrors;
+ u64 RxSymbolErrors;
+ u64 RxDataErrors;
+ u64 RxSequenceErrors;
+ u64 RxRuntErrors;
+ u64 RxJabberErrors;
+ u64 RxInternalMACRcvError;
+ u64 RxInRangeLengthErrors;
+ u64 RxOutOfRangeLengthField;
+ u64 RxFrameTooLongErrors;
+};
+
+struct cmac_ops {
+ void (*destroy)(struct cmac *);
+ int (*reset)(struct cmac *);
+ int (*interrupt_enable)(struct cmac *);
+ int (*interrupt_disable)(struct cmac *);
+ int (*interrupt_clear)(struct cmac *);
+ int (*interrupt_handler)(struct cmac *);
+
+ int (*enable)(struct cmac *, int);
+ int (*disable)(struct cmac *, int);
+
+ int (*loopback_enable)(struct cmac *);
+ int (*loopback_disable)(struct cmac *);
+
+ int (*set_mtu)(struct cmac *, int mtu);
+ int (*set_rx_mode)(struct cmac *, struct t1_rx_mode *rm);
+
+ int (*set_speed_duplex_fc)(struct cmac *, int speed, int duplex, int fc);
+ int (*get_speed_duplex_fc)(struct cmac *, int *speed, int *duplex,
+ int *fc);
+
+ const struct cmac_statistics *(*statistics_update)(struct cmac *, int);
+
+ int (*macaddress_get)(struct cmac *, u8 mac_addr[6]);
+ int (*macaddress_set)(struct cmac *, u8 mac_addr[6]);
+};
+
+typedef struct _cmac_instance cmac_instance;
+
+struct cmac {
+ struct cmac_statistics stats;
+ adapter_t *adapter;
+ struct cmac_ops *ops;
+ cmac_instance *instance;
+};
+
+struct gmac {
+ unsigned int stats_update_period;
+ struct cmac *(*create)(adapter_t *adapter, int index);
+ int (*reset)(adapter_t *);
+};
+
+extern struct gmac t1_pm3393_ops;
+extern struct gmac t1_chelsio_mac_ops;
+extern struct gmac t1_vsc7321_ops;
+extern struct gmac t1_ixf1010_ops;
+extern struct gmac t1_dummy_mac_ops;
+
+#endif /* _CXGB_GMAC_H_ */
diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c
new file mode 100644
index 000000000000..db5034282782
--- /dev/null
+++ b/drivers/net/chelsio/mv88x201x.c
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ * *
+ * File: mv88x201x.c *
+ * $Revision: 1.12 $ *
+ * $Date: 2005/04/15 19:27:14 $ *
+ * Description: *
+ * Marvell PHY (mv88x201x) functionality. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "cphy.h"
+#include "elmer0.h"
+
+/*
+ * The 88x2010 Rev C. requires some link status registers * to be read
+ * twice in order to get the right values. Future * revisions will fix
+ * this problem and then this macro * can disappear.
+ */
+#define MV88x2010_LINK_STATUS_BUGS 1
+
+static int led_init(struct cphy *cphy)
+{
+ /* Setup the LED registers so we can turn on/off.
+ * Writing these bits maps control to another
+ * register. mmd(0x1) addr(0x7)
+ */
+ mdio_write(cphy, 0x3, 0x8304, 0xdddd);
+ return 0;
+}
+
+static int led_link(struct cphy *cphy, u32 do_enable)
+{
+ u32 led = 0;
+#define LINK_ENABLE_BIT 0x1
+
+ mdio_read(cphy, 0x1, 0x7, &led);
+
+ if (do_enable & LINK_ENABLE_BIT) {
+ led |= LINK_ENABLE_BIT;
+ mdio_write(cphy, 0x1, 0x7, led);
+ } else {
+ led &= ~LINK_ENABLE_BIT;
+ mdio_write(cphy, 0x1, 0x7, led);
+ }
+ return 0;
+}
+
+/* Port Reset */
+static int mv88x201x_reset(struct cphy *cphy, int wait)
+{
+ /* This can be done through registers. It is not required since
+ * a full chip reset is used.
+ */
+ return 0;
+}
+
+static int mv88x201x_interrupt_enable(struct cphy *cphy)
+{
+ u32 elmer;
+
+ /* Enable PHY LASI interrupts. */
+ mdio_write(cphy, 0x1, 0x9002, 0x1);
+
+ /* Enable Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_disable(struct cphy *cphy)
+{
+ u32 elmer;
+
+ /* Disable PHY LASI interrupts. */
+ mdio_write(cphy, 0x1, 0x9002, 0x0);
+
+ /* Disable Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_clear(struct cphy *cphy)
+{
+ u32 elmer;
+ u32 val;
+
+#ifdef MV88x2010_LINK_STATUS_BUGS
+ /* Required to read twice before clear takes affect. */
+ mdio_read(cphy, 0x1, 0x9003, &val);
+ mdio_read(cphy, 0x1, 0x9004, &val);
+ mdio_read(cphy, 0x1, 0x9005, &val);
+
+ /* Read this register after the others above it else
+ * the register doesn't clear correctly.
+ */
+ mdio_read(cphy, 0x1, 0x1, &val);
+#endif
+
+ /* Clear link status. */
+ mdio_read(cphy, 0x1, 0x1, &val);
+ /* Clear PHY LASI interrupts. */
+ mdio_read(cphy, 0x1, 0x9005, &val);
+
+#ifdef MV88x2010_LINK_STATUS_BUGS
+ /* Do it again. */
+ mdio_read(cphy, 0x1, 0x9003, &val);
+ mdio_read(cphy, 0x1, 0x9004, &val);
+#endif
+
+ /* Clear Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_handler(struct cphy *cphy)
+{
+ /* Clear interrupts */
+ mv88x201x_interrupt_clear(cphy);
+
+ /* We have only enabled link change interrupts and so
+ * cphy_cause must be a link change interrupt.
+ */
+ return cphy_cause_link_change;
+}
+
+static int mv88x201x_set_loopback(struct cphy *cphy, int on)
+{
+ return 0;
+}
+
+static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
+ int *speed, int *duplex, int *fc)
+{
+ u32 val = 0;
+#define LINK_STATUS_BIT 0x4
+
+ if (link_ok) {
+ /* Read link status. */
+ mdio_read(cphy, 0x1, 0x1, &val);
+ val &= LINK_STATUS_BIT;
+ *link_ok = (val == LINK_STATUS_BIT);
+ /* Turn on/off Link LED */
+ led_link(cphy, *link_ok);
+ }
+ if (speed)
+ *speed = SPEED_10000;
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ if (fc)
+ *fc = PAUSE_RX | PAUSE_TX;
+ return 0;
+}
+
+static void mv88x201x_destroy(struct cphy *cphy)
+{
+ kfree(cphy);
+}
+
+static struct cphy_ops mv88x201x_ops = {
+ .destroy = mv88x201x_destroy,
+ .reset = mv88x201x_reset,
+ .interrupt_enable = mv88x201x_interrupt_enable,
+ .interrupt_disable = mv88x201x_interrupt_disable,
+ .interrupt_clear = mv88x201x_interrupt_clear,
+ .interrupt_handler = mv88x201x_interrupt_handler,
+ .get_link_status = mv88x201x_get_link_status,
+ .set_loopback = mv88x201x_set_loopback,
+};
+
+static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
+ struct mdio_ops *mdio_ops)
+{
+ u32 val;
+ struct cphy *cphy = kmalloc(sizeof(*cphy), GFP_KERNEL);
+
+ if (!cphy)
+ return NULL;
+ memset(cphy, 0, sizeof(*cphy));
+ cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
+
+ /* Commands the PHY to enable XFP's clock. */
+ mdio_read(cphy, 0x3, 0x8300, &val);
+ mdio_write(cphy, 0x3, 0x8300, val | 1);
+
+ /* Clear link status. Required because of a bug in the PHY. */
+ mdio_read(cphy, 0x1, 0x8, &val);
+ mdio_read(cphy, 0x3, 0x8, &val);
+
+ /* Allows for Link,Ack LED turn on/off */
+ led_init(cphy);
+ return cphy;
+}
+
+/* Chip Reset */
+static int mv88x201x_phy_reset(adapter_t *adapter)
+{
+ u32 val;
+
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~4;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ msleep(100);
+
+ t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
+ msleep(1000);
+
+ /* Now lets enable the Laser. Delay 100us */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= 0x8000;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(100);
+ return 0;
+}
+
+struct gphy t1_mv88x201x_ops = {
+ mv88x201x_phy_create,
+ mv88x201x_phy_reset
+};
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c
new file mode 100644
index 000000000000..04a1404fc65e
--- /dev/null
+++ b/drivers/net/chelsio/pm3393.c
@@ -0,0 +1,826 @@
+/*****************************************************************************
+ * *
+ * File: pm3393.c *
+ * $Revision: 1.16 $ *
+ * $Date: 2005/05/14 00:59:32 $ *
+ * Description: *
+ * PMC/SIERRA (pm3393) MAC-PHY functionality. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "regs.h"
+#include "gmac.h"
+#include "elmer0.h"
+#include "suni1x10gexp_regs.h"
+
+/* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
+ */
+enum {
+ MMD_RESERVED,
+ MMD_PMAPMD,
+ MMD_WIS,
+ MMD_PCS,
+ MMD_PHY_XGXS, /* XGMII Extender Sublayer */
+ MMD_DTE_XGXS,
+};
+
+enum {
+ PHY_XGXS_CTRL_1,
+ PHY_XGXS_STATUS_1
+};
+
+#define OFFSET(REG_ADDR) (REG_ADDR << 2)
+
+/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
+#define MAX_FRAME_SIZE 9600
+
+#define IPG 12
+#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
+ SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
+ SUNI1x10GEXP_BITMSK_TXXG_PADEN)
+#define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
+ SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
+
+/* Update statistics every 15 minutes */
+#define STATS_TICK_SECS (15 * 60)
+
+enum { /* RMON registers */
+ RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
+ RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
+ RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
+ RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
+ RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
+ RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
+ RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
+ RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
+ RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
+ RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
+ RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
+ RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
+ RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
+
+ TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
+ TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
+ TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
+ TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
+ TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
+ TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
+ TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW
+};
+
+struct _cmac_instance {
+ u8 enabled;
+ u8 fc;
+ u8 mac_addr[6];
+};
+
+static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
+{
+ t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
+ return 0;
+}
+
+static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
+{
+ t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
+ return 0;
+}
+
+/* Port reset. */
+static int pm3393_reset(struct cmac *cmac)
+{
+ return 0;
+}
+
+/*
+ * Enable interrupts for the PM3393
+
+ 1. Enable PM3393 BLOCK interrupts.
+ 2. Enable PM3393 Master Interrupt bit(INTE)
+ 3. Enable ELMER's PM3393 bit.
+ 4. Enable Terminator external interrupt.
+*/
+static int pm3393_interrupt_enable(struct cmac *cmac)
+{
+ u32 pl_intr;
+
+ /* PM3393 - Enabling all hardware block interrupts.
+ */
+ pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
+
+ /* Don't interrupt on statistics overflow, we are polling */
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
+
+ /* PM3393 - Global interrupt enable
+ */
+ /* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
+ 0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
+
+ /* TERMINATOR - PL_INTERUPTS_EXT */
+ pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
+ pl_intr |= F_PL_INTR_EXT;
+ writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
+ return 0;
+}
+
+static int pm3393_interrupt_disable(struct cmac *cmac)
+{
+ u32 elmer;
+
+ /* PM3393 - Enabling HW interrupt blocks. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
+
+ /* PM3393 - Global interrupt enable */
+ pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
+
+ /* ELMER - External chip interrupts. */
+ t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT1;
+ t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
+
+ /* TERMINATOR - PL_INTERUPTS_EXT */
+ /* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
+ * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
+ */
+
+ return 0;
+}
+
+static int pm3393_interrupt_clear(struct cmac *cmac)
+{
+ u32 elmer;
+ u32 pl_intr;
+ u32 val32;
+
+ /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
+ * bit WCIMODE=0 for a clear-on-read.
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
+ &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
+
+ /* PM3393 - Global interrupt status
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
+
+ /* ELMER - External chip interrupts.
+ */
+ t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
+
+ /* TERMINATOR - PL_INTERUPTS_EXT
+ */
+ pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
+ pl_intr |= F_PL_INTR_EXT;
+ writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
+
+ return 0;
+}
+
+/* Interrupt handler */
+static int pm3393_interrupt_handler(struct cmac *cmac)
+{
+ u32 master_intr_status;
+/*
+ 1. Read master interrupt register.
+ 2. Read BLOCK's interrupt status registers.
+ 3. Handle BLOCK interrupts.
+*/
+ /* Read the master interrupt status register. */
+ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
+ &master_intr_status);
+
+ /* TBD XXX Lets just clear everything for now */
+ pm3393_interrupt_clear(cmac);
+
+ return 0;
+}
+
+static int pm3393_enable(struct cmac *cmac, int which)
+{
+ if (which & MAC_DIRECTION_RX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
+ (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
+
+ if (which & MAC_DIRECTION_TX) {
+ u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
+
+ if (cmac->instance->fc & PAUSE_RX)
+ val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
+ if (cmac->instance->fc & PAUSE_TX)
+ val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
+ }
+
+ cmac->instance->enabled |= which;
+ return 0;
+}
+
+static int pm3393_enable_port(struct cmac *cmac, int which)
+{
+ /* Clear port statistics */
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
+ SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
+ udelay(2);
+ memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
+
+ pm3393_enable(cmac, which);
+
+ /*
+ * XXX This should be done by the PHY and preferrably not at all.
+ * The PHY doesn't give us link status indication on its own so have
+ * the link management code query it instead.
+ */
+ {
+ extern void link_changed(adapter_t *adapter, int port_id);
+
+ link_changed(cmac->adapter, 0);
+ }
+ return 0;
+}
+
+static int pm3393_disable(struct cmac *cmac, int which)
+{
+ if (which & MAC_DIRECTION_RX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
+ if (which & MAC_DIRECTION_TX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
+
+ /*
+ * The disable is graceful. Give the PM3393 time. Can't wait very
+ * long here, we may be holding locks.
+ */
+ udelay(20);
+
+ cmac->instance->enabled &= ~which;
+ return 0;
+}
+
+static int pm3393_loopback_enable(struct cmac *cmac)
+{
+ return 0;
+}
+
+static int pm3393_loopback_disable(struct cmac *cmac)
+{
+ return 0;
+}
+
+static int pm3393_set_mtu(struct cmac *cmac, int mtu)
+{
+ int enabled = cmac->instance->enabled;
+
+ /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
+ mtu += 14 + 4;
+ if (mtu > MAX_FRAME_SIZE)
+ return -EINVAL;
+
+ /* Disable Rx/Tx MAC before configuring it. */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
+
+ if (enabled)
+ pm3393_enable(cmac, enabled);
+ return 0;
+}
+
+static u32 calc_crc(u8 *b, int len)
+{
+ int i;
+ u32 crc = (u32)~0;
+
+ /* calculate crc one bit at a time */
+ while (len--) {
+ crc ^= *b++;
+ for (i = 0; i < 8; i++) {
+ if (crc & 0x1)
+ crc = (crc >> 1) ^ 0xedb88320;
+ else
+ crc = (crc >> 1);
+ }
+ }
+
+ /* reverse bits */
+ crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
+ crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
+ crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
+ /* swap bytes */
+ crc = (crc >> 16) | (crc << 16);
+ crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
+
+ return crc;
+}
+
+static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
+{
+ int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
+ u32 rx_mode;
+
+ /* Disable MAC RX before reconfiguring it */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX);
+
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
+ rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
+ SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
+ (u16)rx_mode);
+
+ if (t1_rx_mode_promisc(rm)) {
+ /* Promiscuous mode. */
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
+ }
+ if (t1_rx_mode_allmulti(rm)) {
+ /* Accept all multicast. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
+ } else if (t1_rx_mode_mc_cnt(rm)) {
+ /* Accept one or more multicast(s). */
+ u8 *addr;
+ int bit;
+ u16 mc_filter[4] = { 0, };
+
+ while ((addr = t1_get_next_mcaddr(rm))) {
+ bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */
+ mc_filter[bit >> 4] |= 1 << (bit & 0xf);
+ }
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
+ }
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
+
+ if (enabled)
+ pm3393_enable(cmac, MAC_DIRECTION_RX);
+
+ return 0;
+}
+
+static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
+ int *duplex, int *fc)
+{
+ if (speed)
+ *speed = SPEED_10000;
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ if (fc)
+ *fc = cmac->instance->fc;
+ return 0;
+}
+
+static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
+ int fc)
+{
+ if (speed >= 0 && speed != SPEED_10000)
+ return -1;
+ if (duplex >= 0 && duplex != DUPLEX_FULL)
+ return -1;
+ if (fc & ~(PAUSE_TX | PAUSE_RX))
+ return -1;
+
+ if (fc != cmac->instance->fc) {
+ cmac->instance->fc = (u8) fc;
+ if (cmac->instance->enabled & MAC_DIRECTION_TX)
+ pm3393_enable(cmac, MAC_DIRECTION_TX);
+ }
+ return 0;
+}
+
+#define RMON_UPDATE(mac, name, stat_name) \
+ { \
+ t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
+ t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
+ t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
+ (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
+ (((u64)val1 & 0xffff) << 16) | \
+ (((u64)val2 & 0xff) << 32) | \
+ ((mac)->stats.stat_name & \
+ (~(u64)0 << 40)); \
+ if (ro & \
+ ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
+ (mac)->stats.stat_name += ((u64)1 << 40); \
+ }
+
+static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
+ int flag)
+{
+ u64 ro;
+ u32 val0, val1, val2, val3;
+
+ /* Snap the counters */
+ pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
+ SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
+
+ /* Counter rollover, clear on read */
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
+ ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
+ (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
+
+ /* Rx stats */
+ RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
+ RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
+ RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
+ RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
+ RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
+ RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
+ RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
+ RxInternalMACRcvError);
+ RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
+ RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
+ RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
+ RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
+ RMON_UPDATE(mac, RxFragments, RxRuntErrors);
+ RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
+
+ /* Tx stats */
+ RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
+ RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
+ TxInternalMACXmitError);
+ RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
+ RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
+ RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
+ RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
+ RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
+
+ return &mac->stats;
+}
+
+static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
+{
+ memcpy(mac_addr, cmac->instance->mac_addr, 6);
+ return 0;
+}
+
+static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
+{
+ u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
+
+ /*
+ * MAC addr: 00:07:43:00:13:09
+ *
+ * ma[5] = 0x09
+ * ma[4] = 0x13
+ * ma[3] = 0x00
+ * ma[2] = 0x43
+ * ma[1] = 0x07
+ * ma[0] = 0x00
+ *
+ * The PM3393 requires byte swapping and reverse order entry
+ * when programming MAC addresses:
+ *
+ * low_bits[15:0] = ma[1]:ma[0]
+ * mid_bits[31:16] = ma[3]:ma[2]
+ * high_bits[47:32] = ma[5]:ma[4]
+ */
+
+ /* Store local copy */
+ memcpy(cmac->instance->mac_addr, ma, 6);
+
+ lo = ((u32) ma[1] << 8) | (u32) ma[0];
+ mid = ((u32) ma[3] << 8) | (u32) ma[2];
+ hi = ((u32) ma[5] << 8) | (u32) ma[4];
+
+ /* Disable Rx/Tx MAC before configuring it. */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+
+ /* Set RXXG Station Address */
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
+
+ /* Set TXXG Station Address */
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
+
+ /* Setup Exact Match Filter 1 with our MAC address
+ *
+ * Must disable exact match filter before configuring it.
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
+ val &= 0xff0f;
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
+
+ val |= 0x0090;
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
+
+ if (enabled)
+ pm3393_enable(cmac, enabled);
+ return 0;
+}
+
+static void pm3393_destroy(struct cmac *cmac)
+{
+ kfree(cmac);
+}
+
+static struct cmac_ops pm3393_ops = {
+ .destroy = pm3393_destroy,
+ .reset = pm3393_reset,
+ .interrupt_enable = pm3393_interrupt_enable,
+ .interrupt_disable = pm3393_interrupt_disable,
+ .interrupt_clear = pm3393_interrupt_clear,
+ .interrupt_handler = pm3393_interrupt_handler,
+ .enable = pm3393_enable_port,
+ .disable = pm3393_disable,
+ .loopback_enable = pm3393_loopback_enable,
+ .loopback_disable = pm3393_loopback_disable,
+ .set_mtu = pm3393_set_mtu,
+ .set_rx_mode = pm3393_set_rx_mode,
+ .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
+ .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
+ .statistics_update = pm3393_update_statistics,
+ .macaddress_get = pm3393_macaddress_get,
+ .macaddress_set = pm3393_macaddress_set
+};
+
+static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
+{
+ struct cmac *cmac;
+
+ cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
+ if (!cmac)
+ return NULL;
+ memset(cmac, 0, sizeof(*cmac));
+
+ cmac->ops = &pm3393_ops;
+ cmac->instance = (cmac_instance *) (cmac + 1);
+ cmac->adapter = adapter;
+ cmac->instance->fc = PAUSE_TX | PAUSE_RX;
+
+ t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
+ t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
+ t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
+ t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001); /* PL4IO Enable */
+ t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
+ t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202); /* PL4IO Calendar Repetitions */
+
+ t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080); /* EFLX Enable */
+ t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000); /* EFLX Channel Deprovision */
+ t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000); /* EFLX Low Limit */
+ t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040); /* EFLX High Limit */
+ t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc); /* EFLX Almost Full */
+ t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199); /* EFLX Almost Empty */
+ t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240); /* EFLX Cut Through Threshold */
+ t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000); /* EFLX Indirect Register Update */
+ t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001); /* EFLX Channel Provision */
+ t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff); /* EFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff); /* EFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff); /* EFLX enable overflow interrupt The other bit are undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff); /* EFLX Undocumented */
+
+ t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000); /* IFLX Configuration - enable */
+ t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000); /* IFLX Channel Deprovision */
+ t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000); /* IFLX Low Limit */
+ t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100); /* IFLX High Limit */
+ t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00); /* IFLX Almost Full Limit */
+ t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599); /* IFLX Almost Empty Limit */
+ t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000); /* IFLX Indirect Register Update */
+ t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001); /* IFLX Channel Provision */
+ t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff); /* IFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff); /* IFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff); /* IFLX Enable overflow interrupt. The other bit are undocumented */
+
+ t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe); /* PL4MOS Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff); /* PL4MOS Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008); /* PL4MOS Starving Burst Size */
+ t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008); /* PL4MOS Hungry Burst Size */
+ t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008); /* PL4MOS Transfer Size */
+ t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005); /* PL4MOS Disable */
+
+ t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103); /* PL4ODP Training Repeat and SOP rule */
+ t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000); /* PL4ODP MAX_T setting */
+
+ t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087); /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
+ t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f); /* PL4IDU Enable Dip4 check error interrupts */
+
+ t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32); /* # TXXG Config */
+ /* For T1 use timer based Mac flow control. */
+ t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
+ t1_tpi_write(adapter, OFFSET(0x2040), 0x059c); /* # RXXG Config */
+ t1_tpi_write(adapter, OFFSET(0x2049), 0x0001); /* # RXXG Cut Through */
+ t1_tpi_write(adapter, OFFSET(0x2070), 0x0000); /* # Disable promiscuous mode */
+
+ /* Setup Exact Match Filter 0 to allow broadcast packets.
+ */
+ t1_tpi_write(adapter, OFFSET(0x206e), 0x0000); /* # Disable Match Enable bit */
+ t1_tpi_write(adapter, OFFSET(0x204a), 0xffff); /* # low addr */
+ t1_tpi_write(adapter, OFFSET(0x204b), 0xffff); /* # mid addr */
+ t1_tpi_write(adapter, OFFSET(0x204c), 0xffff); /* # high addr */
+ t1_tpi_write(adapter, OFFSET(0x206e), 0x0009); /* # Enable Match Enable bit */
+
+ t1_tpi_write(adapter, OFFSET(0x0003), 0x0000); /* # NO SOP/ PAD_EN setup */
+ t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0); /* # RXEQB disabled */
+ t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f); /* # No Preemphasis */
+
+ return cmac;
+}
+
+static int pm3393_mac_reset(adapter_t * adapter)
+{
+ u32 val;
+ u32 x;
+ u32 is_pl4_reset_finished;
+ u32 is_pl4_outof_lock;
+ u32 is_xaui_mabc_pll_locked;
+ u32 successful_reset;
+ int i;
+
+ /* The following steps are required to properly reset
+ * the PM3393. This information is provided in the
+ * PM3393 datasheet (Issue 2: November 2002)
+ * section 13.1 -- Device Reset.
+ *
+ * The PM3393 has three types of components that are
+ * individually reset:
+ *
+ * DRESETB - Digital circuitry
+ * PL4_ARESETB - PL4 analog circuitry
+ * XAUI_ARESETB - XAUI bus analog circuitry
+ *
+ * Steps to reset PM3393 using RSTB pin:
+ *
+ * 1. Assert RSTB pin low ( write 0 )
+ * 2. Wait at least 1ms to initiate a complete initialization of device.
+ * 3. Wait until all external clocks and REFSEL are stable.
+ * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
+ * 5. De-assert RSTB ( write 1 )
+ * 6. Wait until internal timers to expires after ~14ms.
+ * - Allows analog clock synthesizer(PL4CSU) to stabilize to
+ * selected reference frequency before allowing the digital
+ * portion of the device to operate.
+ * 7. Wait at least 200us for XAUI interface to stabilize.
+ * 8. Verify the PM3393 came out of reset successfully.
+ * Set successful reset flag if everything worked else try again
+ * a few more times.
+ */
+
+ successful_reset = 0;
+ for (i = 0; i < 3 && !successful_reset; i++) {
+ /* 1 */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ /* 2 */
+ msleep(1);
+
+ /* 3 */
+ msleep(1);
+
+ /* 4 */
+ msleep(2 /*1 extra ms for safety */ );
+
+ /* 5 */
+ val |= 1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ /* 6 */
+ msleep(15 /*1 extra ms for safety */ );
+
+ /* 7 */
+ msleep(1);
+
+ /* 8 */
+
+ /* Has PL4 analog block come out of reset correctly? */
+ t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
+ is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
+
+ /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
+ * figure out why? */
+
+ /* Have all PL4 block clocks locked? */
+ x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
+ /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */ |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
+ is_pl4_outof_lock = (val & x);
+
+ /* ??? If this fails, might be able to software reset the XAUI part
+ * and try to recover... thus saving us from doing another HW reset */
+ /* Has the XAUI MABC PLL circuitry stablized? */
+ is_xaui_mabc_pll_locked =
+ (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
+
+ successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
+ && is_xaui_mabc_pll_locked);
+ }
+ return successful_reset ? 0 : 1;
+}
+
+struct gmac t1_pm3393_ops = {
+ STATS_TICK_SECS,
+ pm3393_mac_create,
+ pm3393_mac_reset
+};
diff --git a/drivers/net/chelsio/regs.h b/drivers/net/chelsio/regs.h
new file mode 100644
index 000000000000..b90e11f40d1f
--- /dev/null
+++ b/drivers/net/chelsio/regs.h
@@ -0,0 +1,468 @@
+/*****************************************************************************
+ * *
+ * File: regs.h *
+ * $Revision: 1.8 $ *
+ * $Date: 2005/06/21 18:29:48 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_REGS_H_
+#define _CXGB_REGS_H_
+
+/* SGE registers */
+#define A_SG_CONTROL 0x0
+
+#define S_CMDQ0_ENABLE 0
+#define V_CMDQ0_ENABLE(x) ((x) << S_CMDQ0_ENABLE)
+#define F_CMDQ0_ENABLE V_CMDQ0_ENABLE(1U)
+
+#define S_CMDQ1_ENABLE 1
+#define V_CMDQ1_ENABLE(x) ((x) << S_CMDQ1_ENABLE)
+#define F_CMDQ1_ENABLE V_CMDQ1_ENABLE(1U)
+
+#define S_FL0_ENABLE 2
+#define V_FL0_ENABLE(x) ((x) << S_FL0_ENABLE)
+#define F_FL0_ENABLE V_FL0_ENABLE(1U)
+
+#define S_FL1_ENABLE 3
+#define V_FL1_ENABLE(x) ((x) << S_FL1_ENABLE)
+#define F_FL1_ENABLE V_FL1_ENABLE(1U)
+
+#define S_CPL_ENABLE 4
+#define V_CPL_ENABLE(x) ((x) << S_CPL_ENABLE)
+#define F_CPL_ENABLE V_CPL_ENABLE(1U)
+
+#define S_RESPONSE_QUEUE_ENABLE 5
+#define V_RESPONSE_QUEUE_ENABLE(x) ((x) << S_RESPONSE_QUEUE_ENABLE)
+#define F_RESPONSE_QUEUE_ENABLE V_RESPONSE_QUEUE_ENABLE(1U)
+
+#define S_CMDQ_PRIORITY 6
+#define M_CMDQ_PRIORITY 0x3
+#define V_CMDQ_PRIORITY(x) ((x) << S_CMDQ_PRIORITY)
+#define G_CMDQ_PRIORITY(x) (((x) >> S_CMDQ_PRIORITY) & M_CMDQ_PRIORITY)
+
+#define S_DISABLE_CMDQ1_GTS 9
+#define V_DISABLE_CMDQ1_GTS(x) ((x) << S_DISABLE_CMDQ1_GTS)
+#define F_DISABLE_CMDQ1_GTS V_DISABLE_CMDQ1_GTS(1U)
+
+#define S_DISABLE_FL0_GTS 10
+#define V_DISABLE_FL0_GTS(x) ((x) << S_DISABLE_FL0_GTS)
+#define F_DISABLE_FL0_GTS V_DISABLE_FL0_GTS(1U)
+
+#define S_DISABLE_FL1_GTS 11
+#define V_DISABLE_FL1_GTS(x) ((x) << S_DISABLE_FL1_GTS)
+#define F_DISABLE_FL1_GTS V_DISABLE_FL1_GTS(1U)
+
+#define S_ENABLE_BIG_ENDIAN 12
+#define V_ENABLE_BIG_ENDIAN(x) ((x) << S_ENABLE_BIG_ENDIAN)
+#define F_ENABLE_BIG_ENDIAN V_ENABLE_BIG_ENDIAN(1U)
+
+#define S_ISCSI_COALESCE 14
+#define V_ISCSI_COALESCE(x) ((x) << S_ISCSI_COALESCE)
+#define F_ISCSI_COALESCE V_ISCSI_COALESCE(1U)
+
+#define S_RX_PKT_OFFSET 15
+#define V_RX_PKT_OFFSET(x) ((x) << S_RX_PKT_OFFSET)
+
+#define S_VLAN_XTRACT 18
+#define V_VLAN_XTRACT(x) ((x) << S_VLAN_XTRACT)
+#define F_VLAN_XTRACT V_VLAN_XTRACT(1U)
+
+#define A_SG_DOORBELL 0x4
+#define A_SG_CMD0BASELWR 0x8
+#define A_SG_CMD0BASEUPR 0xc
+#define A_SG_CMD1BASELWR 0x10
+#define A_SG_CMD1BASEUPR 0x14
+#define A_SG_FL0BASELWR 0x18
+#define A_SG_FL0BASEUPR 0x1c
+#define A_SG_FL1BASELWR 0x20
+#define A_SG_FL1BASEUPR 0x24
+#define A_SG_CMD0SIZE 0x28
+#define A_SG_FL0SIZE 0x2c
+#define A_SG_RSPSIZE 0x30
+#define A_SG_RSPBASELWR 0x34
+#define A_SG_RSPBASEUPR 0x38
+#define A_SG_FLTHRESHOLD 0x3c
+#define A_SG_RSPQUEUECREDIT 0x40
+#define A_SG_SLEEPING 0x48
+#define A_SG_INTRTIMER 0x4c
+#define A_SG_CMD1SIZE 0xb0
+#define A_SG_FL1SIZE 0xb4
+#define A_SG_INT_ENABLE 0xb8
+
+#define S_RESPQ_EXHAUSTED 0
+#define V_RESPQ_EXHAUSTED(x) ((x) << S_RESPQ_EXHAUSTED)
+#define F_RESPQ_EXHAUSTED V_RESPQ_EXHAUSTED(1U)
+
+#define S_RESPQ_OVERFLOW 1
+#define V_RESPQ_OVERFLOW(x) ((x) << S_RESPQ_OVERFLOW)
+#define F_RESPQ_OVERFLOW V_RESPQ_OVERFLOW(1U)
+
+#define S_FL_EXHAUSTED 2
+#define V_FL_EXHAUSTED(x) ((x) << S_FL_EXHAUSTED)
+#define F_FL_EXHAUSTED V_FL_EXHAUSTED(1U)
+
+#define S_PACKET_TOO_BIG 3
+#define V_PACKET_TOO_BIG(x) ((x) << S_PACKET_TOO_BIG)
+#define F_PACKET_TOO_BIG V_PACKET_TOO_BIG(1U)
+
+#define S_PACKET_MISMATCH 4
+#define V_PACKET_MISMATCH(x) ((x) << S_PACKET_MISMATCH)
+#define F_PACKET_MISMATCH V_PACKET_MISMATCH(1U)
+
+#define A_SG_INT_CAUSE 0xbc
+#define A_SG_RESPACCUTIMER 0xc0
+
+/* MC3 registers */
+
+#define S_READY 1
+#define V_READY(x) ((x) << S_READY)
+#define F_READY V_READY(1U)
+
+/* MC4 registers */
+
+#define A_MC4_CFG 0x180
+#define S_MC4_SLOW 25
+#define V_MC4_SLOW(x) ((x) << S_MC4_SLOW)
+#define F_MC4_SLOW V_MC4_SLOW(1U)
+
+/* TPI registers */
+
+#define A_TPI_ADDR 0x280
+#define A_TPI_WR_DATA 0x284
+#define A_TPI_RD_DATA 0x288
+#define A_TPI_CSR 0x28c
+
+#define S_TPIWR 0
+#define V_TPIWR(x) ((x) << S_TPIWR)
+#define F_TPIWR V_TPIWR(1U)
+
+#define S_TPIRDY 1
+#define V_TPIRDY(x) ((x) << S_TPIRDY)
+#define F_TPIRDY V_TPIRDY(1U)
+
+#define A_TPI_PAR 0x29c
+
+#define S_TPIPAR 0
+#define M_TPIPAR 0x7f
+#define V_TPIPAR(x) ((x) << S_TPIPAR)
+#define G_TPIPAR(x) (((x) >> S_TPIPAR) & M_TPIPAR)
+
+/* TP registers */
+
+#define A_TP_IN_CONFIG 0x300
+
+#define S_TP_IN_CSPI_CPL 3
+#define V_TP_IN_CSPI_CPL(x) ((x) << S_TP_IN_CSPI_CPL)
+#define F_TP_IN_CSPI_CPL V_TP_IN_CSPI_CPL(1U)
+
+#define S_TP_IN_CSPI_CHECK_IP_CSUM 5
+#define V_TP_IN_CSPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_IP_CSUM)
+#define F_TP_IN_CSPI_CHECK_IP_CSUM V_TP_IN_CSPI_CHECK_IP_CSUM(1U)
+
+#define S_TP_IN_CSPI_CHECK_TCP_CSUM 6
+#define V_TP_IN_CSPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_TCP_CSUM)
+#define F_TP_IN_CSPI_CHECK_TCP_CSUM V_TP_IN_CSPI_CHECK_TCP_CSUM(1U)
+
+#define S_TP_IN_ESPI_ETHERNET 8
+#define V_TP_IN_ESPI_ETHERNET(x) ((x) << S_TP_IN_ESPI_ETHERNET)
+#define F_TP_IN_ESPI_ETHERNET V_TP_IN_ESPI_ETHERNET(1U)
+
+#define S_TP_IN_ESPI_CHECK_IP_CSUM 12
+#define V_TP_IN_ESPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_IP_CSUM)
+#define F_TP_IN_ESPI_CHECK_IP_CSUM V_TP_IN_ESPI_CHECK_IP_CSUM(1U)
+
+#define S_TP_IN_ESPI_CHECK_TCP_CSUM 13
+#define V_TP_IN_ESPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_TCP_CSUM)
+#define F_TP_IN_ESPI_CHECK_TCP_CSUM V_TP_IN_ESPI_CHECK_TCP_CSUM(1U)
+
+#define S_OFFLOAD_DISABLE 14
+#define V_OFFLOAD_DISABLE(x) ((x) << S_OFFLOAD_DISABLE)
+#define F_OFFLOAD_DISABLE V_OFFLOAD_DISABLE(1U)
+
+#define A_TP_OUT_CONFIG 0x304
+
+#define S_TP_OUT_CSPI_CPL 2
+#define V_TP_OUT_CSPI_CPL(x) ((x) << S_TP_OUT_CSPI_CPL)
+#define F_TP_OUT_CSPI_CPL V_TP_OUT_CSPI_CPL(1U)
+
+#define S_TP_OUT_ESPI_ETHERNET 6
+#define V_TP_OUT_ESPI_ETHERNET(x) ((x) << S_TP_OUT_ESPI_ETHERNET)
+#define F_TP_OUT_ESPI_ETHERNET V_TP_OUT_ESPI_ETHERNET(1U)
+
+#define S_TP_OUT_ESPI_GENERATE_IP_CSUM 10
+#define V_TP_OUT_ESPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_IP_CSUM)
+#define F_TP_OUT_ESPI_GENERATE_IP_CSUM V_TP_OUT_ESPI_GENERATE_IP_CSUM(1U)
+
+#define S_TP_OUT_ESPI_GENERATE_TCP_CSUM 11
+#define V_TP_OUT_ESPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_TCP_CSUM)
+#define F_TP_OUT_ESPI_GENERATE_TCP_CSUM V_TP_OUT_ESPI_GENERATE_TCP_CSUM(1U)
+
+#define A_TP_GLOBAL_CONFIG 0x308
+
+#define S_IP_TTL 0
+#define M_IP_TTL 0xff
+#define V_IP_TTL(x) ((x) << S_IP_TTL)
+
+#define S_TCP_CSUM 11
+#define V_TCP_CSUM(x) ((x) << S_TCP_CSUM)
+#define F_TCP_CSUM V_TCP_CSUM(1U)
+
+#define S_UDP_CSUM 12
+#define V_UDP_CSUM(x) ((x) << S_UDP_CSUM)
+#define F_UDP_CSUM V_UDP_CSUM(1U)
+
+#define S_IP_CSUM 13
+#define V_IP_CSUM(x) ((x) << S_IP_CSUM)
+#define F_IP_CSUM V_IP_CSUM(1U)
+
+#define S_PATH_MTU 15
+#define V_PATH_MTU(x) ((x) << S_PATH_MTU)
+#define F_PATH_MTU V_PATH_MTU(1U)
+
+#define S_5TUPLE_LOOKUP 17
+#define V_5TUPLE_LOOKUP(x) ((x) << S_5TUPLE_LOOKUP)
+
+#define S_SYN_COOKIE_PARAMETER 26
+#define V_SYN_COOKIE_PARAMETER(x) ((x) << S_SYN_COOKIE_PARAMETER)
+
+#define A_TP_PC_CONFIG 0x348
+#define S_DIS_TX_FILL_WIN_PUSH 12
+#define V_DIS_TX_FILL_WIN_PUSH(x) ((x) << S_DIS_TX_FILL_WIN_PUSH)
+#define F_DIS_TX_FILL_WIN_PUSH V_DIS_TX_FILL_WIN_PUSH(1U)
+
+#define S_TP_PC_REV 30
+#define M_TP_PC_REV 0x3
+#define G_TP_PC_REV(x) (((x) >> S_TP_PC_REV) & M_TP_PC_REV)
+#define A_TP_RESET 0x44c
+#define S_TP_RESET 0
+#define V_TP_RESET(x) ((x) << S_TP_RESET)
+#define F_TP_RESET V_TP_RESET(1U)
+
+#define A_TP_INT_ENABLE 0x470
+#define A_TP_INT_CAUSE 0x474
+#define A_TP_TX_DROP_CONFIG 0x4b8
+
+#define S_ENABLE_TX_DROP 31
+#define V_ENABLE_TX_DROP(x) ((x) << S_ENABLE_TX_DROP)
+#define F_ENABLE_TX_DROP V_ENABLE_TX_DROP(1U)
+
+#define S_ENABLE_TX_ERROR 30
+#define V_ENABLE_TX_ERROR(x) ((x) << S_ENABLE_TX_ERROR)
+#define F_ENABLE_TX_ERROR V_ENABLE_TX_ERROR(1U)
+
+#define S_DROP_TICKS_CNT 4
+#define V_DROP_TICKS_CNT(x) ((x) << S_DROP_TICKS_CNT)
+
+#define S_NUM_PKTS_DROPPED 0
+#define V_NUM_PKTS_DROPPED(x) ((x) << S_NUM_PKTS_DROPPED)
+
+/* CSPI registers */
+
+#define S_DIP4ERR 0
+#define V_DIP4ERR(x) ((x) << S_DIP4ERR)
+#define F_DIP4ERR V_DIP4ERR(1U)
+
+#define S_RXDROP 1
+#define V_RXDROP(x) ((x) << S_RXDROP)
+#define F_RXDROP V_RXDROP(1U)
+
+#define S_TXDROP 2
+#define V_TXDROP(x) ((x) << S_TXDROP)
+#define F_TXDROP V_TXDROP(1U)
+
+#define S_RXOVERFLOW 3
+#define V_RXOVERFLOW(x) ((x) << S_RXOVERFLOW)
+#define F_RXOVERFLOW V_RXOVERFLOW(1U)
+
+#define S_RAMPARITYERR 4
+#define V_RAMPARITYERR(x) ((x) << S_RAMPARITYERR)
+#define F_RAMPARITYERR V_RAMPARITYERR(1U)
+
+/* ESPI registers */
+
+#define A_ESPI_SCH_TOKEN0 0x880
+#define A_ESPI_SCH_TOKEN1 0x884
+#define A_ESPI_SCH_TOKEN2 0x888
+#define A_ESPI_SCH_TOKEN3 0x88c
+#define A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK 0x890
+#define A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK 0x894
+#define A_ESPI_CALENDAR_LENGTH 0x898
+#define A_PORT_CONFIG 0x89c
+
+#define S_RX_NPORTS 0
+#define V_RX_NPORTS(x) ((x) << S_RX_NPORTS)
+
+#define S_TX_NPORTS 8
+#define V_TX_NPORTS(x) ((x) << S_TX_NPORTS)
+
+#define A_ESPI_FIFO_STATUS_ENABLE 0x8a0
+
+#define S_RXSTATUSENABLE 0
+#define V_RXSTATUSENABLE(x) ((x) << S_RXSTATUSENABLE)
+#define F_RXSTATUSENABLE V_RXSTATUSENABLE(1U)
+
+#define S_INTEL1010MODE 4
+#define V_INTEL1010MODE(x) ((x) << S_INTEL1010MODE)
+#define F_INTEL1010MODE V_INTEL1010MODE(1U)
+
+#define A_ESPI_MAXBURST1_MAXBURST2 0x8a8
+#define A_ESPI_TRAIN 0x8ac
+#define A_ESPI_INTR_STATUS 0x8c8
+
+#define S_DIP2PARITYERR 5
+#define V_DIP2PARITYERR(x) ((x) << S_DIP2PARITYERR)
+#define F_DIP2PARITYERR V_DIP2PARITYERR(1U)
+
+#define A_ESPI_INTR_ENABLE 0x8cc
+#define A_RX_DROP_THRESHOLD 0x8d0
+#define A_ESPI_RX_RESET 0x8ec
+#define A_ESPI_MISC_CONTROL 0x8f0
+
+#define S_OUT_OF_SYNC_COUNT 0
+#define V_OUT_OF_SYNC_COUNT(x) ((x) << S_OUT_OF_SYNC_COUNT)
+
+#define S_DIP2_PARITY_ERR_THRES 5
+#define V_DIP2_PARITY_ERR_THRES(x) ((x) << S_DIP2_PARITY_ERR_THRES)
+
+#define S_DIP4_THRES 9
+#define V_DIP4_THRES(x) ((x) << S_DIP4_THRES)
+
+#define S_MONITORED_PORT_NUM 25
+#define V_MONITORED_PORT_NUM(x) ((x) << S_MONITORED_PORT_NUM)
+
+#define S_MONITORED_DIRECTION 27
+#define V_MONITORED_DIRECTION(x) ((x) << S_MONITORED_DIRECTION)
+#define F_MONITORED_DIRECTION V_MONITORED_DIRECTION(1U)
+
+#define S_MONITORED_INTERFACE 28
+#define V_MONITORED_INTERFACE(x) ((x) << S_MONITORED_INTERFACE)
+#define F_MONITORED_INTERFACE V_MONITORED_INTERFACE(1U)
+
+#define A_ESPI_DIP2_ERR_COUNT 0x8f4
+#define A_ESPI_CMD_ADDR 0x8f8
+
+#define S_WRITE_DATA 0
+#define V_WRITE_DATA(x) ((x) << S_WRITE_DATA)
+
+#define S_REGISTER_OFFSET 8
+#define V_REGISTER_OFFSET(x) ((x) << S_REGISTER_OFFSET)
+
+#define S_CHANNEL_ADDR 12
+#define V_CHANNEL_ADDR(x) ((x) << S_CHANNEL_ADDR)
+
+#define S_MODULE_ADDR 16
+#define V_MODULE_ADDR(x) ((x) << S_MODULE_ADDR)
+
+#define S_BUNDLE_ADDR 20
+#define V_BUNDLE_ADDR(x) ((x) << S_BUNDLE_ADDR)
+
+#define S_SPI4_COMMAND 24
+#define V_SPI4_COMMAND(x) ((x) << S_SPI4_COMMAND)
+
+#define A_ESPI_GOSTAT 0x8fc
+#define S_ESPI_CMD_BUSY 8
+#define V_ESPI_CMD_BUSY(x) ((x) << S_ESPI_CMD_BUSY)
+#define F_ESPI_CMD_BUSY V_ESPI_CMD_BUSY(1U)
+
+/* PL registers */
+
+#define A_PL_ENABLE 0xa00
+
+#define S_PL_INTR_SGE_ERR 0
+#define V_PL_INTR_SGE_ERR(x) ((x) << S_PL_INTR_SGE_ERR)
+#define F_PL_INTR_SGE_ERR V_PL_INTR_SGE_ERR(1U)
+
+#define S_PL_INTR_SGE_DATA 1
+#define V_PL_INTR_SGE_DATA(x) ((x) << S_PL_INTR_SGE_DATA)
+#define F_PL_INTR_SGE_DATA V_PL_INTR_SGE_DATA(1U)
+
+#define S_PL_INTR_TP 6
+#define V_PL_INTR_TP(x) ((x) << S_PL_INTR_TP)
+#define F_PL_INTR_TP V_PL_INTR_TP(1U)
+
+#define S_PL_INTR_ESPI 8
+#define V_PL_INTR_ESPI(x) ((x) << S_PL_INTR_ESPI)
+#define F_PL_INTR_ESPI V_PL_INTR_ESPI(1U)
+
+#define S_PL_INTR_PCIX 10
+#define V_PL_INTR_PCIX(x) ((x) << S_PL_INTR_PCIX)
+#define F_PL_INTR_PCIX V_PL_INTR_PCIX(1U)
+
+#define S_PL_INTR_EXT 11
+#define V_PL_INTR_EXT(x) ((x) << S_PL_INTR_EXT)
+#define F_PL_INTR_EXT V_PL_INTR_EXT(1U)
+
+#define A_PL_CAUSE 0xa04
+
+/* MC5 registers */
+
+#define A_MC5_CONFIG 0xc04
+
+#define S_TCAM_RESET 1
+#define V_TCAM_RESET(x) ((x) << S_TCAM_RESET)
+#define F_TCAM_RESET V_TCAM_RESET(1U)
+
+#define S_M_BUS_ENABLE 5
+#define V_M_BUS_ENABLE(x) ((x) << S_M_BUS_ENABLE)
+#define F_M_BUS_ENABLE V_M_BUS_ENABLE(1U)
+
+/* PCICFG registers */
+
+#define A_PCICFG_PM_CSR 0x44
+#define A_PCICFG_VPD_ADDR 0x4a
+
+#define S_VPD_OP_FLAG 15
+#define V_VPD_OP_FLAG(x) ((x) << S_VPD_OP_FLAG)
+#define F_VPD_OP_FLAG V_VPD_OP_FLAG(1U)
+
+#define A_PCICFG_VPD_DATA 0x4c
+
+#define A_PCICFG_INTR_ENABLE 0xf4
+#define A_PCICFG_INTR_CAUSE 0xf8
+
+#define A_PCICFG_MODE 0xfc
+
+#define S_PCI_MODE_64BIT 0
+#define V_PCI_MODE_64BIT(x) ((x) << S_PCI_MODE_64BIT)
+#define F_PCI_MODE_64BIT V_PCI_MODE_64BIT(1U)
+
+#define S_PCI_MODE_PCIX 5
+#define V_PCI_MODE_PCIX(x) ((x) << S_PCI_MODE_PCIX)
+#define F_PCI_MODE_PCIX V_PCI_MODE_PCIX(1U)
+
+#define S_PCI_MODE_CLK 6
+#define M_PCI_MODE_CLK 0x3
+#define G_PCI_MODE_CLK(x) (((x) >> S_PCI_MODE_CLK) & M_PCI_MODE_CLK)
+
+#endif /* _CXGB_REGS_H_ */
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
new file mode 100644
index 000000000000..53b41d99b00b
--- /dev/null
+++ b/drivers/net/chelsio/sge.c
@@ -0,0 +1,1684 @@
+/*****************************************************************************
+ * *
+ * File: sge.c *
+ * $Revision: 1.26 $ *
+ * $Date: 2005/06/21 18:29:48 $ *
+ * Description: *
+ * DMA engine. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+
+#include "cpl5_cmd.h"
+#include "sge.h"
+#include "regs.h"
+#include "espi.h"
+
+
+#ifdef NETIF_F_TSO
+#include <linux/tcp.h>
+#endif
+
+#define SGE_CMDQ_N 2
+#define SGE_FREELQ_N 2
+#define SGE_CMDQ0_E_N 1024
+#define SGE_CMDQ1_E_N 128
+#define SGE_FREEL_SIZE 4096
+#define SGE_JUMBO_FREEL_SIZE 512
+#define SGE_FREEL_REFILL_THRESH 16
+#define SGE_RESPQ_E_N 1024
+#define SGE_INTRTIMER_NRES 1000
+#define SGE_RX_COPY_THRES 256
+#define SGE_RX_SM_BUF_SIZE 1536
+
+# define SGE_RX_DROP_THRES 2
+
+#define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4)
+
+/*
+ * Period of the TX buffer reclaim timer. This timer does not need to run
+ * frequently as TX buffers are usually reclaimed by new TX packets.
+ */
+#define TX_RECLAIM_PERIOD (HZ / 4)
+
+#ifndef NET_IP_ALIGN
+# define NET_IP_ALIGN 2
+#endif
+
+#define M_CMD_LEN 0x7fffffff
+#define V_CMD_LEN(v) (v)
+#define G_CMD_LEN(v) ((v) & M_CMD_LEN)
+#define V_CMD_GEN1(v) ((v) << 31)
+#define V_CMD_GEN2(v) (v)
+#define F_CMD_DATAVALID (1 << 1)
+#define F_CMD_SOP (1 << 2)
+#define V_CMD_EOP(v) ((v) << 3)
+
+/*
+ * Command queue, receive buffer list, and response queue descriptors.
+ */
+#if defined(__BIG_ENDIAN_BITFIELD)
+struct cmdQ_e {
+ u32 addr_lo;
+ u32 len_gen;
+ u32 flags;
+ u32 addr_hi;
+};
+
+struct freelQ_e {
+ u32 addr_lo;
+ u32 len_gen;
+ u32 gen2;
+ u32 addr_hi;
+};
+
+struct respQ_e {
+ u32 Qsleeping : 4;
+ u32 Cmdq1CreditReturn : 5;
+ u32 Cmdq1DmaComplete : 5;
+ u32 Cmdq0CreditReturn : 5;
+ u32 Cmdq0DmaComplete : 5;
+ u32 FreelistQid : 2;
+ u32 CreditValid : 1;
+ u32 DataValid : 1;
+ u32 Offload : 1;
+ u32 Eop : 1;
+ u32 Sop : 1;
+ u32 GenerationBit : 1;
+ u32 BufferLength;
+};
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+struct cmdQ_e {
+ u32 len_gen;
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 flags;
+};
+
+struct freelQ_e {
+ u32 len_gen;
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 gen2;
+};
+
+struct respQ_e {
+ u32 BufferLength;
+ u32 GenerationBit : 1;
+ u32 Sop : 1;
+ u32 Eop : 1;
+ u32 Offload : 1;
+ u32 DataValid : 1;
+ u32 CreditValid : 1;
+ u32 FreelistQid : 2;
+ u32 Cmdq0DmaComplete : 5;
+ u32 Cmdq0CreditReturn : 5;
+ u32 Cmdq1DmaComplete : 5;
+ u32 Cmdq1CreditReturn : 5;
+ u32 Qsleeping : 4;
+} ;
+#endif
+
+/*
+ * SW Context Command and Freelist Queue Descriptors
+ */
+struct cmdQ_ce {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ DECLARE_PCI_UNMAP_LEN(dma_len);
+};
+
+struct freelQ_ce {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ DECLARE_PCI_UNMAP_LEN(dma_len);
+};
+
+/*
+ * SW command, freelist and response rings
+ */
+struct cmdQ {
+ unsigned long status; /* HW DMA fetch status */
+ unsigned int in_use; /* # of in-use command descriptors */
+ unsigned int size; /* # of descriptors */
+ unsigned int processed; /* total # of descs HW has processed */
+ unsigned int cleaned; /* total # of descs SW has reclaimed */
+ unsigned int stop_thres; /* SW TX queue suspend threshold */
+ u16 pidx; /* producer index (SW) */
+ u16 cidx; /* consumer index (HW) */
+ u8 genbit; /* current generation (=valid) bit */
+ u8 sop; /* is next entry start of packet? */
+ struct cmdQ_e *entries; /* HW command descriptor Q */
+ struct cmdQ_ce *centries; /* SW command context descriptor Q */
+ spinlock_t lock; /* Lock to protect cmdQ enqueuing */
+ dma_addr_t dma_addr; /* DMA addr HW command descriptor Q */
+};
+
+struct freelQ {
+ unsigned int credits; /* # of available RX buffers */
+ unsigned int size; /* free list capacity */
+ u16 pidx; /* producer index (SW) */
+ u16 cidx; /* consumer index (HW) */
+ u16 rx_buffer_size; /* Buffer size on this free list */
+ u16 dma_offset; /* DMA offset to align IP headers */
+ u16 recycleq_idx; /* skb recycle q to use */
+ u8 genbit; /* current generation (=valid) bit */
+ struct freelQ_e *entries; /* HW freelist descriptor Q */
+ struct freelQ_ce *centries; /* SW freelist context descriptor Q */
+ dma_addr_t dma_addr; /* DMA addr HW freelist descriptor Q */
+};
+
+struct respQ {
+ unsigned int credits; /* credits to be returned to SGE */
+ unsigned int size; /* # of response Q descriptors */
+ u16 cidx; /* consumer index (SW) */
+ u8 genbit; /* current generation(=valid) bit */
+ struct respQ_e *entries; /* HW response descriptor Q */
+ dma_addr_t dma_addr; /* DMA addr HW response descriptor Q */
+};
+
+/* Bit flags for cmdQ.status */
+enum {
+ CMDQ_STAT_RUNNING = 1, /* fetch engine is running */
+ CMDQ_STAT_LAST_PKT_DB = 2 /* last packet rung the doorbell */
+};
+
+/*
+ * Main SGE data structure
+ *
+ * Interrupts are handled by a single CPU and it is likely that on a MP system
+ * the application is migrated to another CPU. In that scenario, we try to
+ * seperate the RX(in irq context) and TX state in order to decrease memory
+ * contention.
+ */
+struct sge {
+ struct adapter *adapter; /* adapter backpointer */
+ struct net_device *netdev; /* netdevice backpointer */
+ struct freelQ freelQ[SGE_FREELQ_N]; /* buffer free lists */
+ struct respQ respQ; /* response Q */
+ unsigned long stopped_tx_queues; /* bitmap of suspended Tx queues */
+ unsigned int rx_pkt_pad; /* RX padding for L2 packets */
+ unsigned int jumbo_fl; /* jumbo freelist Q index */
+ unsigned int intrtimer_nres; /* no-resource interrupt timer */
+ unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */
+ struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
+ struct timer_list espibug_timer;
+ unsigned int espibug_timeout;
+ struct sk_buff *espibug_skb;
+ u32 sge_control; /* shadow value of sge control reg */
+ struct sge_intr_counts stats;
+ struct sge_port_stats port_stats[MAX_NPORTS];
+ struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
+};
+
+/*
+ * PIO to indicate that memory mapped Q contains valid descriptor(s).
+ */
+static inline void doorbell_pio(struct adapter *adapter, u32 val)
+{
+ wmb();
+ writel(val, adapter->regs + A_SG_DOORBELL);
+}
+
+/*
+ * Frees all RX buffers on the freelist Q. The caller must make sure that
+ * the SGE is turned off before calling this function.
+ */
+static void free_freelQ_buffers(struct pci_dev *pdev, struct freelQ *q)
+{
+ unsigned int cidx = q->cidx;
+
+ while (q->credits--) {
+ struct freelQ_ce *ce = &q->centries[cidx];
+
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(ce->skb);
+ ce->skb = NULL;
+ if (++cidx == q->size)
+ cidx = 0;
+ }
+}
+
+/*
+ * Free RX free list and response queue resources.
+ */
+static void free_rx_resources(struct sge *sge)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ if (sge->respQ.entries) {
+ size = sizeof(struct respQ_e) * sge->respQ.size;
+ pci_free_consistent(pdev, size, sge->respQ.entries,
+ sge->respQ.dma_addr);
+ }
+
+ for (i = 0; i < SGE_FREELQ_N; i++) {
+ struct freelQ *q = &sge->freelQ[i];
+
+ if (q->centries) {
+ free_freelQ_buffers(pdev, q);
+ kfree(q->centries);
+ }
+ if (q->entries) {
+ size = sizeof(struct freelQ_e) * q->size;
+ pci_free_consistent(pdev, size, q->entries,
+ q->dma_addr);
+ }
+ }
+}
+
+/*
+ * Allocates basic RX resources, consisting of memory mapped freelist Qs and a
+ * response queue.
+ */
+static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_FREELQ_N; i++) {
+ struct freelQ *q = &sge->freelQ[i];
+
+ q->genbit = 1;
+ q->size = p->freelQ_size[i];
+ q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN;
+ size = sizeof(struct freelQ_e) * q->size;
+ q->entries = (struct freelQ_e *)
+ pci_alloc_consistent(pdev, size, &q->dma_addr);
+ if (!q->entries)
+ goto err_no_mem;
+ memset(q->entries, 0, size);
+ size = sizeof(struct freelQ_ce) * q->size;
+ q->centries = kmalloc(size, GFP_KERNEL);
+ if (!q->centries)
+ goto err_no_mem;
+ memset(q->centries, 0, size);
+ }
+
+ /*
+ * Calculate the buffer sizes for the two free lists. FL0 accommodates
+ * regular sized Ethernet frames, FL1 is sized not to exceed 16K,
+ * including all the sk_buff overhead.
+ *
+ * Note: For T2 FL0 and FL1 are reversed.
+ */
+ sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE +
+ sizeof(struct cpl_rx_data) +
+ sge->freelQ[!sge->jumbo_fl].dma_offset;
+ sge->freelQ[sge->jumbo_fl].rx_buffer_size = (16 * 1024) -
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ /*
+ * Setup which skb recycle Q should be used when recycling buffers from
+ * each free list.
+ */
+ sge->freelQ[!sge->jumbo_fl].recycleq_idx = 0;
+ sge->freelQ[sge->jumbo_fl].recycleq_idx = 1;
+
+ sge->respQ.genbit = 1;
+ sge->respQ.size = SGE_RESPQ_E_N;
+ sge->respQ.credits = 0;
+ size = sizeof(struct respQ_e) * sge->respQ.size;
+ sge->respQ.entries = (struct respQ_e *)
+ pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr);
+ if (!sge->respQ.entries)
+ goto err_no_mem;
+ memset(sge->respQ.entries, 0, size);
+ return 0;
+
+err_no_mem:
+ free_rx_resources(sge);
+ return -ENOMEM;
+}
+
+/*
+ * Reclaims n TX descriptors and frees the buffers associated with them.
+ */
+static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n)
+{
+ struct cmdQ_ce *ce;
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int cidx = q->cidx;
+
+ q->in_use -= n;
+ ce = &q->centries[cidx];
+ while (n--) {
+ if (q->sop)
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ q->sop = 0;
+ if (ce->skb) {
+ dev_kfree_skb(ce->skb);
+ q->sop = 1;
+ }
+ ce++;
+ if (++cidx == q->size) {
+ cidx = 0;
+ ce = q->centries;
+ }
+ }
+ q->cidx = cidx;
+}
+
+/*
+ * Free TX resources.
+ *
+ * Assumes that SGE is stopped and all interrupts are disabled.
+ */
+static void free_tx_resources(struct sge *sge)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_CMDQ_N; i++) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ if (q->centries) {
+ if (q->in_use)
+ free_cmdQ_buffers(sge, q, q->in_use);
+ kfree(q->centries);
+ }
+ if (q->entries) {
+ size = sizeof(struct cmdQ_e) * q->size;
+ pci_free_consistent(pdev, size, q->entries,
+ q->dma_addr);
+ }
+ }
+}
+
+/*
+ * Allocates basic TX resources, consisting of memory mapped command Qs.
+ */
+static int alloc_tx_resources(struct sge *sge, struct sge_params *p)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_CMDQ_N; i++) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ q->genbit = 1;
+ q->sop = 1;
+ q->size = p->cmdQ_size[i];
+ q->in_use = 0;
+ q->status = 0;
+ q->processed = q->cleaned = 0;
+ q->stop_thres = 0;
+ spin_lock_init(&q->lock);
+ size = sizeof(struct cmdQ_e) * q->size;
+ q->entries = (struct cmdQ_e *)
+ pci_alloc_consistent(pdev, size, &q->dma_addr);
+ if (!q->entries)
+ goto err_no_mem;
+ memset(q->entries, 0, size);
+ size = sizeof(struct cmdQ_ce) * q->size;
+ q->centries = kmalloc(size, GFP_KERNEL);
+ if (!q->centries)
+ goto err_no_mem;
+ memset(q->centries, 0, size);
+ }
+
+ /*
+ * CommandQ 0 handles Ethernet and TOE packets, while queue 1 is TOE
+ * only. For queue 0 set the stop threshold so we can handle one more
+ * packet from each port, plus reserve an additional 24 entries for
+ * Ethernet packets only. Queue 1 never suspends nor do we reserve
+ * space for Ethernet packets.
+ */
+ sge->cmdQ[0].stop_thres = sge->adapter->params.nports *
+ (MAX_SKB_FRAGS + 1);
+ return 0;
+
+err_no_mem:
+ free_tx_resources(sge);
+ return -ENOMEM;
+}
+
+static inline void setup_ring_params(struct adapter *adapter, u64 addr,
+ u32 size, int base_reg_lo,
+ int base_reg_hi, int size_reg)
+{
+ writel((u32)addr, adapter->regs + base_reg_lo);
+ writel(addr >> 32, adapter->regs + base_reg_hi);
+ writel(size, adapter->regs + size_reg);
+}
+
+/*
+ * Enable/disable VLAN acceleration.
+ */
+void t1_set_vlan_accel(struct adapter *adapter, int on_off)
+{
+ struct sge *sge = adapter->sge;
+
+ sge->sge_control &= ~F_VLAN_XTRACT;
+ if (on_off)
+ sge->sge_control |= F_VLAN_XTRACT;
+ if (adapter->open_device_map) {
+ writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
+ readl(adapter->regs + A_SG_CONTROL); /* flush */
+ }
+}
+
+/*
+ * Programs the various SGE registers. However, the engine is not yet enabled,
+ * but sge->sge_control is setup and ready to go.
+ */
+static void configure_sge(struct sge *sge, struct sge_params *p)
+{
+ struct adapter *ap = sge->adapter;
+
+ writel(0, ap->regs + A_SG_CONTROL);
+ setup_ring_params(ap, sge->cmdQ[0].dma_addr, sge->cmdQ[0].size,
+ A_SG_CMD0BASELWR, A_SG_CMD0BASEUPR, A_SG_CMD0SIZE);
+ setup_ring_params(ap, sge->cmdQ[1].dma_addr, sge->cmdQ[1].size,
+ A_SG_CMD1BASELWR, A_SG_CMD1BASEUPR, A_SG_CMD1SIZE);
+ setup_ring_params(ap, sge->freelQ[0].dma_addr,
+ sge->freelQ[0].size, A_SG_FL0BASELWR,
+ A_SG_FL0BASEUPR, A_SG_FL0SIZE);
+ setup_ring_params(ap, sge->freelQ[1].dma_addr,
+ sge->freelQ[1].size, A_SG_FL1BASELWR,
+ A_SG_FL1BASEUPR, A_SG_FL1SIZE);
+
+ /* The threshold comparison uses <. */
+ writel(SGE_RX_SM_BUF_SIZE + 1, ap->regs + A_SG_FLTHRESHOLD);
+
+ setup_ring_params(ap, sge->respQ.dma_addr, sge->respQ.size,
+ A_SG_RSPBASELWR, A_SG_RSPBASEUPR, A_SG_RSPSIZE);
+ writel((u32)sge->respQ.size - 1, ap->regs + A_SG_RSPQUEUECREDIT);
+
+ sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE |
+ F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE |
+ V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE |
+ F_DISABLE_FL0_GTS | F_DISABLE_FL1_GTS |
+ V_RX_PKT_OFFSET(sge->rx_pkt_pad);
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ sge->sge_control |= F_ENABLE_BIG_ENDIAN;
+#endif
+
+ /* Initialize no-resource timer */
+ sge->intrtimer_nres = SGE_INTRTIMER_NRES * core_ticks_per_usec(ap);
+
+ t1_sge_set_coalesce_params(sge, p);
+}
+
+/*
+ * Return the payload capacity of the jumbo free-list buffers.
+ */
+static inline unsigned int jumbo_payload_capacity(const struct sge *sge)
+{
+ return sge->freelQ[sge->jumbo_fl].rx_buffer_size -
+ sge->freelQ[sge->jumbo_fl].dma_offset -
+ sizeof(struct cpl_rx_data);
+}
+
+/*
+ * Frees all SGE related resources and the sge structure itself
+ */
+void t1_sge_destroy(struct sge *sge)
+{
+ if (sge->espibug_skb)
+ kfree_skb(sge->espibug_skb);
+
+ free_tx_resources(sge);
+ free_rx_resources(sge);
+ kfree(sge);
+}
+
+/*
+ * Allocates new RX buffers on the freelist Q (and tracks them on the freelist
+ * context Q) until the Q is full or alloc_skb fails.
+ *
+ * It is possible that the generation bits already match, indicating that the
+ * buffer is already valid and nothing needs to be done. This happens when we
+ * copied a received buffer into a new sk_buff during the interrupt processing.
+ *
+ * If the SGE doesn't automatically align packets properly (!sge->rx_pkt_pad),
+ * we specify a RX_OFFSET in order to make sure that the IP header is 4B
+ * aligned.
+ */
+static void refill_free_list(struct sge *sge, struct freelQ *q)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ struct freelQ_ce *ce = &q->centries[q->pidx];
+ struct freelQ_e *e = &q->entries[q->pidx];
+ unsigned int dma_len = q->rx_buffer_size - q->dma_offset;
+
+
+ while (q->credits < q->size) {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+
+ skb = alloc_skb(q->rx_buffer_size, GFP_ATOMIC);
+ if (!skb)
+ break;
+
+ skb_reserve(skb, q->dma_offset);
+ mapping = pci_map_single(pdev, skb->data, dma_len,
+ PCI_DMA_FROMDEVICE);
+ ce->skb = skb;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, dma_len);
+ e->addr_lo = (u32)mapping;
+ e->addr_hi = (u64)mapping >> 32;
+ e->len_gen = V_CMD_LEN(dma_len) | V_CMD_GEN1(q->genbit);
+ wmb();
+ e->gen2 = V_CMD_GEN2(q->genbit);
+
+ e++;
+ ce++;
+ if (++q->pidx == q->size) {
+ q->pidx = 0;
+ q->genbit ^= 1;
+ ce = q->centries;
+ e = q->entries;
+ }
+ q->credits++;
+ }
+
+}
+
+/*
+ * Calls refill_free_list for both free lists. If we cannot fill at least 1/4
+ * of both rings, we go into 'few interrupt mode' in order to give the system
+ * time to free up resources.
+ */
+static void freelQs_empty(struct sge *sge)
+{
+ struct adapter *adapter = sge->adapter;
+ u32 irq_reg = readl(adapter->regs + A_SG_INT_ENABLE);
+ u32 irqholdoff_reg;
+
+ refill_free_list(sge, &sge->freelQ[0]);
+ refill_free_list(sge, &sge->freelQ[1]);
+
+ if (sge->freelQ[0].credits > (sge->freelQ[0].size >> 2) &&
+ sge->freelQ[1].credits > (sge->freelQ[1].size >> 2)) {
+ irq_reg |= F_FL_EXHAUSTED;
+ irqholdoff_reg = sge->fixed_intrtimer;
+ } else {
+ /* Clear the F_FL_EXHAUSTED interrupts for now */
+ irq_reg &= ~F_FL_EXHAUSTED;
+ irqholdoff_reg = sge->intrtimer_nres;
+ }
+ writel(irqholdoff_reg, adapter->regs + A_SG_INTRTIMER);
+ writel(irq_reg, adapter->regs + A_SG_INT_ENABLE);
+
+ /* We reenable the Qs to force a freelist GTS interrupt later */
+ doorbell_pio(adapter, F_FL0_ENABLE | F_FL1_ENABLE);
+}
+
+#define SGE_PL_INTR_MASK (F_PL_INTR_SGE_ERR | F_PL_INTR_SGE_DATA)
+#define SGE_INT_FATAL (F_RESPQ_OVERFLOW | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
+#define SGE_INT_ENABLE (F_RESPQ_EXHAUSTED | F_RESPQ_OVERFLOW | \
+ F_FL_EXHAUSTED | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
+
+/*
+ * Disable SGE Interrupts
+ */
+void t1_sge_intr_disable(struct sge *sge)
+{
+ u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
+
+ writel(val & ~SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
+ writel(0, sge->adapter->regs + A_SG_INT_ENABLE);
+}
+
+/*
+ * Enable SGE interrupts.
+ */
+void t1_sge_intr_enable(struct sge *sge)
+{
+ u32 en = SGE_INT_ENABLE;
+ u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
+
+ if (sge->adapter->flags & TSO_CAPABLE)
+ en &= ~F_PACKET_TOO_BIG;
+ writel(en, sge->adapter->regs + A_SG_INT_ENABLE);
+ writel(val | SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
+}
+
+/*
+ * Clear SGE interrupts.
+ */
+void t1_sge_intr_clear(struct sge *sge)
+{
+ writel(SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_CAUSE);
+ writel(0xffffffff, sge->adapter->regs + A_SG_INT_CAUSE);
+}
+
+/*
+ * SGE 'Error' interrupt handler
+ */
+int t1_sge_intr_error_handler(struct sge *sge)
+{
+ struct adapter *adapter = sge->adapter;
+ u32 cause = readl(adapter->regs + A_SG_INT_CAUSE);
+
+ if (adapter->flags & TSO_CAPABLE)
+ cause &= ~F_PACKET_TOO_BIG;
+ if (cause & F_RESPQ_EXHAUSTED)
+ sge->stats.respQ_empty++;
+ if (cause & F_RESPQ_OVERFLOW) {
+ sge->stats.respQ_overflow++;
+ CH_ALERT("%s: SGE response queue overflow\n",
+ adapter->name);
+ }
+ if (cause & F_FL_EXHAUSTED) {
+ sge->stats.freelistQ_empty++;
+ freelQs_empty(sge);
+ }
+ if (cause & F_PACKET_TOO_BIG) {
+ sge->stats.pkt_too_big++;
+ CH_ALERT("%s: SGE max packet size exceeded\n",
+ adapter->name);
+ }
+ if (cause & F_PACKET_MISMATCH) {
+ sge->stats.pkt_mismatch++;
+ CH_ALERT("%s: SGE packet mismatch\n", adapter->name);
+ }
+ if (cause & SGE_INT_FATAL)
+ t1_fatal_err(adapter);
+
+ writel(cause, adapter->regs + A_SG_INT_CAUSE);
+ return 0;
+}
+
+const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge)
+{
+ return &sge->stats;
+}
+
+const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port)
+{
+ return &sge->port_stats[port];
+}
+
+/**
+ * recycle_fl_buf - recycle a free list buffer
+ * @fl: the free list
+ * @idx: index of buffer to recycle
+ *
+ * Recycles the specified buffer on the given free list by adding it at
+ * the next available slot on the list.
+ */
+static void recycle_fl_buf(struct freelQ *fl, int idx)
+{
+ struct freelQ_e *from = &fl->entries[idx];
+ struct freelQ_e *to = &fl->entries[fl->pidx];
+
+ fl->centries[fl->pidx] = fl->centries[idx];
+ to->addr_lo = from->addr_lo;
+ to->addr_hi = from->addr_hi;
+ to->len_gen = G_CMD_LEN(from->len_gen) | V_CMD_GEN1(fl->genbit);
+ wmb();
+ to->gen2 = V_CMD_GEN2(fl->genbit);
+ fl->credits++;
+
+ if (++fl->pidx == fl->size) {
+ fl->pidx = 0;
+ fl->genbit ^= 1;
+ }
+}
+
+/**
+ * get_packet - return the next ingress packet buffer
+ * @pdev: the PCI device that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the actual packet length, excluding any SGE padding
+ * @dma_pad: padding at beginning of buffer left by SGE DMA
+ * @skb_pad: padding to be used if the packet is copied
+ * @copy_thres: length threshold under which a packet should be copied
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list and complete setup of the
+ * sk_buff. If the packet is small we make a copy and recycle the
+ * original buffer, otherwise we use the original buffer itself. If a
+ * positive drop threshold is supplied packets are dropped and their
+ * buffers recycled if (a) the number of remaining buffers is under the
+ * threshold and the packet is too big to copy, or (b) the packet should
+ * be copied but there is no memory for the copy.
+ */
+static inline struct sk_buff *get_packet(struct pci_dev *pdev,
+ struct freelQ *fl, unsigned int len,
+ int dma_pad, int skb_pad,
+ unsigned int copy_thres,
+ unsigned int drop_thres)
+{
+ struct sk_buff *skb;
+ struct freelQ_ce *ce = &fl->centries[fl->cidx];
+
+ if (len < copy_thres) {
+ skb = alloc_skb(len + skb_pad, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ skb_reserve(skb, skb_pad);
+ skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, ce->skb->data + dma_pad, len);
+ pci_dma_sync_single_for_device(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ goto use_orig_buf;
+
+ recycle_fl_buf(fl, fl->cidx);
+ return skb;
+ }
+
+ if (fl->credits < drop_thres) {
+ recycle_fl_buf(fl, fl->cidx);
+ return NULL;
+ }
+
+use_orig_buf:
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
+ skb = ce->skb;
+ skb_reserve(skb, dma_pad);
+ skb_put(skb, len);
+ return skb;
+}
+
+/**
+ * unexpected_offload - handle an unexpected offload packet
+ * @adapter: the adapter
+ * @fl: the free list that received the packet
+ *
+ * Called when we receive an unexpected offload packet (e.g., the TOE
+ * function is disabled or the card is a NIC). Prints a message and
+ * recycles the buffer.
+ */
+static void unexpected_offload(struct adapter *adapter, struct freelQ *fl)
+{
+ struct freelQ_ce *ce = &fl->centries[fl->cidx];
+ struct sk_buff *skb = ce->skb;
+
+ pci_dma_sync_single_for_cpu(adapter->pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
+ CH_ERR("%s: unexpected offload packet, cmd %u\n",
+ adapter->name, *skb->data);
+ recycle_fl_buf(fl, fl->cidx);
+}
+
+/*
+ * Write the command descriptors to transmit the given skb starting at
+ * descriptor pidx with the given generation.
+ */
+static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
+ unsigned int pidx, unsigned int gen,
+ struct cmdQ *q)
+{
+ dma_addr_t mapping;
+ struct cmdQ_e *e, *e1;
+ struct cmdQ_ce *ce;
+ unsigned int i, flags, nfrags = skb_shinfo(skb)->nr_frags;
+
+ mapping = pci_map_single(adapter->pdev, skb->data,
+ skb->len - skb->data_len, PCI_DMA_TODEVICE);
+ ce = &q->centries[pidx];
+ ce->skb = NULL;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, skb->len - skb->data_len);
+
+ flags = F_CMD_DATAVALID | F_CMD_SOP | V_CMD_EOP(nfrags == 0) |
+ V_CMD_GEN2(gen);
+ e = &q->entries[pidx];
+ e->addr_lo = (u32)mapping;
+ e->addr_hi = (u64)mapping >> 32;
+ e->len_gen = V_CMD_LEN(skb->len - skb->data_len) | V_CMD_GEN1(gen);
+ for (e1 = e, i = 0; nfrags--; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ ce++;
+ e1++;
+ if (++pidx == q->size) {
+ pidx = 0;
+ gen ^= 1;
+ ce = q->centries;
+ e1 = q->entries;
+ }
+
+ mapping = pci_map_page(adapter->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+ ce->skb = NULL;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, frag->size);
+
+ e1->addr_lo = (u32)mapping;
+ e1->addr_hi = (u64)mapping >> 32;
+ e1->len_gen = V_CMD_LEN(frag->size) | V_CMD_GEN1(gen);
+ e1->flags = F_CMD_DATAVALID | V_CMD_EOP(nfrags == 0) |
+ V_CMD_GEN2(gen);
+ }
+
+ ce->skb = skb;
+ wmb();
+ e->flags = flags;
+}
+
+/*
+ * Clean up completed Tx buffers.
+ */
+static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q)
+{
+ unsigned int reclaim = q->processed - q->cleaned;
+
+ if (reclaim) {
+ free_cmdQ_buffers(sge, q, reclaim);
+ q->cleaned += reclaim;
+ }
+}
+
+#ifndef SET_ETHTOOL_OPS
+# define __netif_rx_complete(dev) netif_rx_complete(dev)
+#endif
+
+/*
+ * We cannot use the standard netif_rx_schedule_prep() because we have multiple
+ * ports plus the TOE all multiplexing onto a single response queue, therefore
+ * accepting new responses cannot depend on the state of any particular port.
+ * So define our own equivalent that omits the netif_running() test.
+ */
+static inline int napi_schedule_prep(struct net_device *dev)
+{
+ return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+
+/**
+ * sge_rx - process an ingress ethernet packet
+ * @sge: the sge structure
+ * @fl: the free list that contains the packet buffer
+ * @len: the packet length
+ *
+ * Process an ingress ethernet pakcet and deliver it to the stack.
+ */
+static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
+{
+ struct sk_buff *skb;
+ struct cpl_rx_pkt *p;
+ struct adapter *adapter = sge->adapter;
+
+ sge->stats.ethernet_pkts++;
+ skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad,
+ sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES,
+ SGE_RX_DROP_THRES);
+ if (!skb) {
+ sge->port_stats[0].rx_drops++; /* charge only port 0 for now */
+ return 0;
+ }
+
+ p = (struct cpl_rx_pkt *)skb->data;
+ skb_pull(skb, sizeof(*p));
+ skb->dev = adapter->port[p->iff].dev;
+ skb->dev->last_rx = jiffies;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
+ skb->protocol == htons(ETH_P_IP) &&
+ (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
+ sge->port_stats[p->iff].rx_cso_good++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
+ sge->port_stats[p->iff].vlan_xtract++;
+ if (adapter->params.sge.polling)
+ vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
+ ntohs(p->vlan));
+ else
+ vlan_hwaccel_rx(skb, adapter->vlan_grp,
+ ntohs(p->vlan));
+ } else if (adapter->params.sge.polling)
+ netif_receive_skb(skb);
+ else
+ netif_rx(skb);
+ return 0;
+}
+
+/*
+ * Returns true if a command queue has enough available descriptors that
+ * we can resume Tx operation after temporarily disabling its packet queue.
+ */
+static inline int enough_free_Tx_descs(const struct cmdQ *q)
+{
+ unsigned int r = q->processed - q->cleaned;
+
+ return q->in_use - r < (q->size >> 1);
+}
+
+/*
+ * Called when sufficient space has become available in the SGE command queues
+ * after the Tx packet schedulers have been suspended to restart the Tx path.
+ */
+static void restart_tx_queues(struct sge *sge)
+{
+ struct adapter *adap = sge->adapter;
+
+ if (enough_free_Tx_descs(&sge->cmdQ[0])) {
+ int i;
+
+ for_each_port(adap, i) {
+ struct net_device *nd = adap->port[i].dev;
+
+ if (test_and_clear_bit(nd->if_port,
+ &sge->stopped_tx_queues) &&
+ netif_running(nd)) {
+ sge->stats.cmdQ_restarted[3]++;
+ netif_wake_queue(nd);
+ }
+ }
+ }
+}
+
+/*
+ * update_tx_info is called from the interrupt handler/NAPI to return cmdQ0
+ * information.
+ */
+static unsigned int update_tx_info(struct adapter *adapter,
+ unsigned int flags,
+ unsigned int pr0)
+{
+ struct sge *sge = adapter->sge;
+ struct cmdQ *cmdq = &sge->cmdQ[0];
+
+ cmdq->processed += pr0;
+
+ if (flags & F_CMDQ0_ENABLE) {
+ clear_bit(CMDQ_STAT_RUNNING, &cmdq->status);
+
+ if (cmdq->cleaned + cmdq->in_use != cmdq->processed &&
+ !test_and_set_bit(CMDQ_STAT_LAST_PKT_DB, &cmdq->status)) {
+ set_bit(CMDQ_STAT_RUNNING, &cmdq->status);
+ writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
+ }
+ flags &= ~F_CMDQ0_ENABLE;
+ }
+
+ if (unlikely(sge->stopped_tx_queues != 0))
+ restart_tx_queues(sge);
+
+ return flags;
+}
+
+/*
+ * Process SGE responses, up to the supplied budget. Returns the number of
+ * responses processed. A negative budget is effectively unlimited.
+ */
+static int process_responses(struct adapter *adapter, int budget)
+{
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &sge->respQ;
+ struct respQ_e *e = &q->entries[q->cidx];
+ int budget_left = budget;
+ unsigned int flags = 0;
+ unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
+
+
+ while (likely(budget_left && e->GenerationBit == q->genbit)) {
+ flags |= e->Qsleeping;
+
+ cmdq_processed[0] += e->Cmdq0CreditReturn;
+ cmdq_processed[1] += e->Cmdq1CreditReturn;
+
+ /* We batch updates to the TX side to avoid cacheline
+ * ping-pong of TX state information on MP where the sender
+ * might run on a different CPU than this function...
+ */
+ if (unlikely(flags & F_CMDQ0_ENABLE || cmdq_processed[0] > 64)) {
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ cmdq_processed[0] = 0;
+ }
+ if (unlikely(cmdq_processed[1] > 16)) {
+ sge->cmdQ[1].processed += cmdq_processed[1];
+ cmdq_processed[1] = 0;
+ }
+ if (likely(e->DataValid)) {
+ struct freelQ *fl = &sge->freelQ[e->FreelistQid];
+
+ if (unlikely(!e->Sop || !e->Eop))
+ BUG();
+ if (unlikely(e->Offload))
+ unexpected_offload(adapter, fl);
+ else
+ sge_rx(sge, fl, e->BufferLength);
+
+ /*
+ * Note: this depends on each packet consuming a
+ * single free-list buffer; cf. the BUG above.
+ */
+ if (++fl->cidx == fl->size)
+ fl->cidx = 0;
+ if (unlikely(--fl->credits <
+ fl->size - SGE_FREEL_REFILL_THRESH))
+ refill_free_list(sge, fl);
+ } else
+ sge->stats.pure_rsps++;
+
+ e++;
+ if (unlikely(++q->cidx == q->size)) {
+ q->cidx = 0;
+ q->genbit ^= 1;
+ e = q->entries;
+ }
+ prefetch(e);
+
+ if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
+ writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
+ q->credits = 0;
+ }
+ --budget_left;
+ }
+
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ sge->cmdQ[1].processed += cmdq_processed[1];
+
+ budget -= budget_left;
+ return budget;
+}
+
+/*
+ * A simpler version of process_responses() that handles only pure (i.e.,
+ * non data-carrying) responses. Such respones are too light-weight to justify
+ * calling a softirq when using NAPI, so we handle them specially in hard
+ * interrupt context. The function is called with a pointer to a response,
+ * which the caller must ensure is a valid pure response. Returns 1 if it
+ * encounters a valid data-carrying response, 0 otherwise.
+ */
+static int process_pure_responses(struct adapter *adapter, struct respQ_e *e)
+{
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &sge->respQ;
+ unsigned int flags = 0;
+ unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
+
+ do {
+ flags |= e->Qsleeping;
+
+ cmdq_processed[0] += e->Cmdq0CreditReturn;
+ cmdq_processed[1] += e->Cmdq1CreditReturn;
+
+ e++;
+ if (unlikely(++q->cidx == q->size)) {
+ q->cidx = 0;
+ q->genbit ^= 1;
+ e = q->entries;
+ }
+ prefetch(e);
+
+ if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
+ writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
+ q->credits = 0;
+ }
+ sge->stats.pure_rsps++;
+ } while (e->GenerationBit == q->genbit && !e->DataValid);
+
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ sge->cmdQ[1].processed += cmdq_processed[1];
+
+ return e->GenerationBit == q->genbit;
+}
+
+/*
+ * Handler for new data events when using NAPI. This does not need any locking
+ * or protection from interrupts as data interrupts are off at this point and
+ * other adapter interrupts do not interfere.
+ */
+static int t1_poll(struct net_device *dev, int *budget)
+{
+ struct adapter *adapter = dev->priv;
+ int effective_budget = min(*budget, dev->quota);
+
+ int work_done = process_responses(adapter, effective_budget);
+ *budget -= work_done;
+ dev->quota -= work_done;
+
+ if (work_done >= effective_budget)
+ return 1;
+
+ __netif_rx_complete(dev);
+
+ /*
+ * Because we don't atomically flush the following write it is
+ * possible that in very rare cases it can reach the device in a way
+ * that races with a new response being written plus an error interrupt
+ * causing the NAPI interrupt handler below to return unhandled status
+ * to the OS. To protect against this would require flushing the write
+ * and doing both the write and the flush with interrupts off. Way too
+ * expensive and unjustifiable given the rarity of the race.
+ */
+ writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
+ return 0;
+}
+
+/*
+ * Returns true if the device is already scheduled for polling.
+ */
+static inline int napi_is_scheduled(struct net_device *dev)
+{
+ return test_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+/*
+ * NAPI version of the main interrupt handler.
+ */
+static irqreturn_t t1_interrupt_napi(int irq, void *data, struct pt_regs *regs)
+{
+ int handled;
+ struct adapter *adapter = data;
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &adapter->sge->respQ;
+
+ /*
+ * Clear the SGE_DATA interrupt first thing. Normally the NAPI
+ * handler has control of the response queue and the interrupt handler
+ * can look at the queue reliably only once it knows NAPI is off.
+ * We can't wait that long to clear the SGE_DATA interrupt because we
+ * could race with t1_poll rearming the SGE interrupt, so we need to
+ * clear the interrupt speculatively and really early on.
+ */
+ writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+ spin_lock(&adapter->async_lock);
+ if (!napi_is_scheduled(sge->netdev)) {
+ struct respQ_e *e = &q->entries[q->cidx];
+
+ if (e->GenerationBit == q->genbit) {
+ if (e->DataValid ||
+ process_pure_responses(adapter, e)) {
+ if (likely(napi_schedule_prep(sge->netdev)))
+ __netif_rx_schedule(sge->netdev);
+ else
+ printk(KERN_CRIT
+ "NAPI schedule failure!\n");
+ } else
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ handled = 1;
+ goto unlock;
+ } else
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ } else
+ if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA)
+ printk(KERN_ERR "data interrupt while NAPI running\n");
+
+ handled = t1_slow_intr_handler(adapter);
+ if (!handled)
+ sge->stats.unhandled_irqs++;
+ unlock:
+ spin_unlock(&adapter->async_lock);
+ return IRQ_RETVAL(handled != 0);
+}
+
+/*
+ * Main interrupt handler, optimized assuming that we took a 'DATA'
+ * interrupt.
+ *
+ * 1. Clear the interrupt
+ * 2. Loop while we find valid descriptors and process them; accumulate
+ * information that can be processed after the loop
+ * 3. Tell the SGE at which index we stopped processing descriptors
+ * 4. Bookkeeping; free TX buffers, ring doorbell if there are any
+ * outstanding TX buffers waiting, replenish RX buffers, potentially
+ * reenable upper layers if they were turned off due to lack of TX
+ * resources which are available again.
+ * 5. If we took an interrupt, but no valid respQ descriptors was found we
+ * let the slow_intr_handler run and do error handling.
+ */
+static irqreturn_t t1_interrupt(int irq, void *cookie, struct pt_regs *regs)
+{
+ int work_done;
+ struct respQ_e *e;
+ struct adapter *adapter = cookie;
+ struct respQ *Q = &adapter->sge->respQ;
+
+ spin_lock(&adapter->async_lock);
+ e = &Q->entries[Q->cidx];
+ prefetch(e);
+
+ writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+ if (likely(e->GenerationBit == Q->genbit))
+ work_done = process_responses(adapter, -1);
+ else
+ work_done = t1_slow_intr_handler(adapter);
+
+ /*
+ * The unconditional clearing of the PL_CAUSE above may have raced
+ * with DMA completion and the corresponding generation of a response
+ * to cause us to miss the resulting data interrupt. The next write
+ * is also unconditional to recover the missed interrupt and render
+ * this race harmless.
+ */
+ writel(Q->cidx, adapter->regs + A_SG_SLEEPING);
+
+ if (!work_done)
+ adapter->sge->stats.unhandled_irqs++;
+ spin_unlock(&adapter->async_lock);
+ return IRQ_RETVAL(work_done != 0);
+}
+
+intr_handler_t t1_select_intr_handler(adapter_t *adapter)
+{
+ return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
+}
+
+/*
+ * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
+ *
+ * The code figures out how many entries the sk_buff will require in the
+ * cmdQ and updates the cmdQ data structure with the state once the enqueue
+ * has complete. Then, it doesn't access the global structure anymore, but
+ * uses the corresponding fields on the stack. In conjuction with a spinlock
+ * around that code, we can make the function reentrant without holding the
+ * lock when we actually enqueue (which might be expensive, especially on
+ * architectures with IO MMUs).
+ *
+ * This runs with softirqs disabled.
+ */
+unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
+ unsigned int qid, struct net_device *dev)
+{
+ struct sge *sge = adapter->sge;
+ struct cmdQ *q = &sge->cmdQ[qid];
+ unsigned int credits, pidx, genbit, count;
+
+ spin_lock(&q->lock);
+ reclaim_completed_tx(sge, q);
+
+ pidx = q->pidx;
+ credits = q->size - q->in_use;
+ count = 1 + skb_shinfo(skb)->nr_frags;
+
+ { /* Ethernet packet */
+ if (unlikely(credits < count)) {
+ netif_stop_queue(dev);
+ set_bit(dev->if_port, &sge->stopped_tx_queues);
+ sge->stats.cmdQ_full[3]++;
+ spin_unlock(&q->lock);
+ CH_ERR("%s: Tx ring full while queue awake!\n",
+ adapter->name);
+ return 1;
+ }
+ if (unlikely(credits - count < q->stop_thres)) {
+ sge->stats.cmdQ_full[3]++;
+ netif_stop_queue(dev);
+ set_bit(dev->if_port, &sge->stopped_tx_queues);
+ }
+ }
+ q->in_use += count;
+ genbit = q->genbit;
+ q->pidx += count;
+ if (q->pidx >= q->size) {
+ q->pidx -= q->size;
+ q->genbit ^= 1;
+ }
+ spin_unlock(&q->lock);
+
+ write_tx_descs(adapter, skb, pidx, genbit, q);
+
+ /*
+ * We always ring the doorbell for cmdQ1. For cmdQ0, we only ring
+ * the doorbell if the Q is asleep. There is a natural race, where
+ * the hardware is going to sleep just after we checked, however,
+ * then the interrupt handler will detect the outstanding TX packet
+ * and ring the doorbell for us.
+ */
+ if (qid)
+ doorbell_pio(adapter, F_CMDQ1_ENABLE);
+ else {
+ clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
+ set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
+ }
+ }
+ return 0;
+}
+
+#define MK_ETH_TYPE_MSS(type, mss) (((mss) & 0x3FFF) | ((type) << 14))
+
+/*
+ * eth_hdr_len - return the length of an Ethernet header
+ * @data: pointer to the start of the Ethernet header
+ *
+ * Returns the length of an Ethernet header, including optional VLAN tag.
+ */
+static inline int eth_hdr_len(const void *data)
+{
+ const struct ethhdr *e = data;
+
+ return e->h_proto == htons(ETH_P_8021Q) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+/*
+ * Adds the CPL header to the sk_buff and passes it to t1_sge_tx.
+ */
+int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct sge_port_stats *st = &adapter->sge->port_stats[dev->if_port];
+ struct sge *sge = adapter->sge;
+ struct cpl_tx_pkt *cpl;
+
+#ifdef NETIF_F_TSO
+ if (skb_shinfo(skb)->tso_size) {
+ int eth_type;
+ struct cpl_tx_pkt_lso *hdr;
+
+ st->tso++;
+
+ eth_type = skb->nh.raw - skb->data == ETH_HLEN ?
+ CPL_ETH_II : CPL_ETH_II_VLAN;
+
+ hdr = (struct cpl_tx_pkt_lso *)skb_push(skb, sizeof(*hdr));
+ hdr->opcode = CPL_TX_PKT_LSO;
+ hdr->ip_csum_dis = hdr->l4_csum_dis = 0;
+ hdr->ip_hdr_words = skb->nh.iph->ihl;
+ hdr->tcp_hdr_words = skb->h.th->doff;
+ hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
+ skb_shinfo(skb)->tso_size));
+ hdr->len = htonl(skb->len - sizeof(*hdr));
+ cpl = (struct cpl_tx_pkt *)hdr;
+ sge->stats.tx_lso_pkts++;
+ } else
+#endif
+ {
+ /*
+ * Packets shorter than ETH_HLEN can break the MAC, drop them
+ * early. Also, we may get oversized packets because some
+ * parts of the kernel don't handle our unusual hard_header_len
+ * right, drop those too.
+ */
+ if (unlikely(skb->len < ETH_HLEN ||
+ skb->len > dev->mtu + eth_hdr_len(skb->data))) {
+ dev_kfree_skb_any(skb);
+ return NET_XMIT_SUCCESS;
+ }
+
+ /*
+ * We are using a non-standard hard_header_len and some kernel
+ * components, such as pktgen, do not handle it right.
+ * Complain when this happens but try to fix things up.
+ */
+ if (unlikely(skb_headroom(skb) <
+ dev->hard_header_len - ETH_HLEN)) {
+ struct sk_buff *orig_skb = skb;
+
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: inadequate headroom in "
+ "Tx packet\n", dev->name);
+ skb = skb_realloc_headroom(skb, sizeof(*cpl));
+ dev_kfree_skb_any(orig_skb);
+ if (!skb)
+ return -ENOMEM;
+ }
+
+ if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
+ skb->ip_summed == CHECKSUM_HW &&
+ skb->nh.iph->protocol == IPPROTO_UDP)
+ if (unlikely(skb_checksum_help(skb, 0))) {
+ dev_kfree_skb_any(skb);
+ return -ENOMEM;
+ }
+
+ /* Hmmm, assuming to catch the gratious arp... and we'll use
+ * it to flush out stuck espi packets...
+ */
+ if (unlikely(!adapter->sge->espibug_skb)) {
+ if (skb->protocol == htons(ETH_P_ARP) &&
+ skb->nh.arph->ar_op == htons(ARPOP_REQUEST)) {
+ adapter->sge->espibug_skb = skb;
+ /* We want to re-use this skb later. We
+ * simply bump the reference count and it
+ * will not be freed...
+ */
+ skb = skb_get(skb);
+ }
+ }
+
+ cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl));
+ cpl->opcode = CPL_TX_PKT;
+ cpl->ip_csum_dis = 1; /* SW calculates IP csum */
+ cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_HW ? 0 : 1;
+ /* the length field isn't used so don't bother setting it */
+
+ st->tx_cso += (skb->ip_summed == CHECKSUM_HW);
+ sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_HW);
+ sge->stats.tx_reg_pkts++;
+ }
+ cpl->iff = dev->if_port;
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+ cpl->vlan_valid = 1;
+ cpl->vlan = htons(vlan_tx_tag_get(skb));
+ st->vlan_insert++;
+ } else
+#endif
+ cpl->vlan_valid = 0;
+
+ dev->trans_start = jiffies;
+ return t1_sge_tx(skb, adapter, 0, dev);
+}
+
+/*
+ * Callback for the Tx buffer reclaim timer. Runs with softirqs disabled.
+ */
+static void sge_tx_reclaim_cb(unsigned long data)
+{
+ int i;
+ struct sge *sge = (struct sge *)data;
+
+ for (i = 0; i < SGE_CMDQ_N; ++i) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ if (!spin_trylock(&q->lock))
+ continue;
+
+ reclaim_completed_tx(sge, q);
+ if (i == 0 && q->in_use) /* flush pending credits */
+ writel(F_CMDQ0_ENABLE,
+ sge->adapter->regs + A_SG_DOORBELL);
+
+ spin_unlock(&q->lock);
+ }
+ mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+}
+
+/*
+ * Propagate changes of the SGE coalescing parameters to the HW.
+ */
+int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
+{
+ sge->netdev->poll = t1_poll;
+ sge->fixed_intrtimer = p->rx_coalesce_usecs *
+ core_ticks_per_usec(sge->adapter);
+ writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
+ return 0;
+}
+
+/*
+ * Allocates both RX and TX resources and configures the SGE. However,
+ * the hardware is not enabled yet.
+ */
+int t1_sge_configure(struct sge *sge, struct sge_params *p)
+{
+ if (alloc_rx_resources(sge, p))
+ return -ENOMEM;
+ if (alloc_tx_resources(sge, p)) {
+ free_rx_resources(sge);
+ return -ENOMEM;
+ }
+ configure_sge(sge, p);
+
+ /*
+ * Now that we have sized the free lists calculate the payload
+ * capacity of the large buffers. Other parts of the driver use
+ * this to set the max offload coalescing size so that RX packets
+ * do not overflow our large buffers.
+ */
+ p->large_buf_capacity = jumbo_payload_capacity(sge);
+ return 0;
+}
+
+/*
+ * Disables the DMA engine.
+ */
+void t1_sge_stop(struct sge *sge)
+{
+ writel(0, sge->adapter->regs + A_SG_CONTROL);
+ (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+ if (is_T2(sge->adapter))
+ del_timer_sync(&sge->espibug_timer);
+ del_timer_sync(&sge->tx_reclaim_timer);
+}
+
+/*
+ * Enables the DMA engine.
+ */
+void t1_sge_start(struct sge *sge)
+{
+ refill_free_list(sge, &sge->freelQ[0]);
+ refill_free_list(sge, &sge->freelQ[1]);
+
+ writel(sge->sge_control, sge->adapter->regs + A_SG_CONTROL);
+ doorbell_pio(sge->adapter, F_FL0_ENABLE | F_FL1_ENABLE);
+ (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+
+ mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+
+ if (is_T2(sge->adapter))
+ mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
+}
+
+/*
+ * Callback for the T2 ESPI 'stuck packet feature' workaorund
+ */
+static void espibug_workaround(void *data)
+{
+ struct adapter *adapter = (struct adapter *)data;
+ struct sge *sge = adapter->sge;
+
+ if (netif_running(adapter->port[0].dev)) {
+ struct sk_buff *skb = sge->espibug_skb;
+
+ u32 seop = t1_espi_get_mon(adapter, 0x930, 0);
+
+ if ((seop & 0xfff0fff) == 0xfff && skb) {
+ if (!skb->cb[0]) {
+ u8 ch_mac_addr[ETH_ALEN] =
+ {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
+ memcpy(skb->data + sizeof(struct cpl_tx_pkt),
+ ch_mac_addr, ETH_ALEN);
+ memcpy(skb->data + skb->len - 10, ch_mac_addr,
+ ETH_ALEN);
+ skb->cb[0] = 0xff;
+ }
+
+ /* bump the reference count to avoid freeing of the
+ * skb once the DMA has completed.
+ */
+ skb = skb_get(skb);
+ t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
+ }
+ }
+ mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
+}
+
+/*
+ * Creates a t1_sge structure and returns suggested resource parameters.
+ */
+struct sge * __devinit t1_sge_create(struct adapter *adapter,
+ struct sge_params *p)
+{
+ struct sge *sge = kmalloc(sizeof(*sge), GFP_KERNEL);
+
+ if (!sge)
+ return NULL;
+ memset(sge, 0, sizeof(*sge));
+
+ sge->adapter = adapter;
+ sge->netdev = adapter->port[0].dev;
+ sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2;
+ sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ init_timer(&sge->tx_reclaim_timer);
+ sge->tx_reclaim_timer.data = (unsigned long)sge;
+ sge->tx_reclaim_timer.function = sge_tx_reclaim_cb;
+
+ if (is_T2(sge->adapter)) {
+ init_timer(&sge->espibug_timer);
+ sge->espibug_timer.function = (void *)&espibug_workaround;
+ sge->espibug_timer.data = (unsigned long)sge->adapter;
+ sge->espibug_timeout = 1;
+ }
+
+
+ p->cmdQ_size[0] = SGE_CMDQ0_E_N;
+ p->cmdQ_size[1] = SGE_CMDQ1_E_N;
+ p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE;
+ p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE;
+ p->rx_coalesce_usecs = 50;
+ p->coalesce_enable = 0;
+ p->sample_interval_usecs = 0;
+ p->polling = 0;
+
+ return sge;
+}
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
new file mode 100644
index 000000000000..434b25586851
--- /dev/null
+++ b/drivers/net/chelsio/sge.h
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ * *
+ * File: sge.h *
+ * $Revision: 1.11 $ *
+ * $Date: 2005/06/21 22:10:55 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_SGE_H_
+#define _CXGB_SGE_H_
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <asm/byteorder.h>
+
+#ifndef IRQ_RETVAL
+#define IRQ_RETVAL(x)
+typedef void irqreturn_t;
+#endif
+
+typedef irqreturn_t (*intr_handler_t)(int, void *, struct pt_regs *);
+
+struct sge_intr_counts {
+ unsigned int respQ_empty; /* # times respQ empty */
+ unsigned int respQ_overflow; /* # respQ overflow (fatal) */
+ unsigned int freelistQ_empty; /* # times freelist empty */
+ unsigned int pkt_too_big; /* packet too large (fatal) */
+ unsigned int pkt_mismatch;
+ unsigned int cmdQ_full[3]; /* not HW IRQ, host cmdQ[] full */
+ unsigned int cmdQ_restarted[3];/* # of times cmdQ X was restarted */
+ unsigned int ethernet_pkts; /* # of Ethernet packets received */
+ unsigned int offload_pkts; /* # of offload packets received */
+ unsigned int offload_bundles; /* # of offload pkt bundles delivered */
+ unsigned int pure_rsps; /* # of non-payload responses */
+ unsigned int unhandled_irqs; /* # of unhandled interrupts */
+ unsigned int tx_ipfrags;
+ unsigned int tx_reg_pkts;
+ unsigned int tx_lso_pkts;
+ unsigned int tx_do_cksum;
+};
+
+struct sge_port_stats {
+ unsigned long rx_cso_good; /* # of successful RX csum offloads */
+ unsigned long tx_cso; /* # of TX checksum offloads */
+ unsigned long vlan_xtract; /* # of VLAN tag extractions */
+ unsigned long vlan_insert; /* # of VLAN tag extractions */
+ unsigned long tso; /* # of TSO requests */
+ unsigned long rx_drops; /* # of packets dropped due to no mem */
+};
+
+struct sk_buff;
+struct net_device;
+struct adapter;
+struct sge_params;
+struct sge;
+
+struct sge *t1_sge_create(struct adapter *, struct sge_params *);
+int t1_sge_configure(struct sge *, struct sge_params *);
+int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
+void t1_sge_destroy(struct sge *);
+intr_handler_t t1_select_intr_handler(adapter_t *adapter);
+unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
+ unsigned int qid, struct net_device *netdev);
+int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void t1_set_vlan_accel(struct adapter *adapter, int on_off);
+void t1_sge_start(struct sge *);
+void t1_sge_stop(struct sge *);
+int t1_sge_intr_error_handler(struct sge *);
+void t1_sge_intr_enable(struct sge *);
+void t1_sge_intr_disable(struct sge *);
+void t1_sge_intr_clear(struct sge *);
+const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge);
+const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port);
+
+#endif /* _CXGB_SGE_H_ */
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c
new file mode 100644
index 000000000000..1ebb5d149aef
--- /dev/null
+++ b/drivers/net/chelsio/subr.c
@@ -0,0 +1,812 @@
+/*****************************************************************************
+ * *
+ * File: subr.c *
+ * $Revision: 1.27 $ *
+ * $Date: 2005/06/22 01:08:36 $ *
+ * Description: *
+ * Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "elmer0.h"
+#include "regs.h"
+#include "gmac.h"
+#include "cphy.h"
+#include "sge.h"
+#include "espi.h"
+
+/**
+ * t1_wait_op_done - wait until an operation is completed
+ * @adapter: the adapter performing the operation
+ * @reg: the register to check for completion
+ * @mask: a single-bit field within @reg that indicates completion
+ * @polarity: the value of the field when the operation is completed
+ * @attempts: number of check iterations
+ * @delay: delay in usecs between iterations
+ *
+ * Wait until an operation is completed by checking a bit in a register
+ * up to @attempts times. Returns %0 if the operation completes and %1
+ * otherwise.
+ */
+static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
+ int attempts, int delay)
+{
+ while (1) {
+ u32 val = readl(adapter->regs + reg) & mask;
+
+ if (!!val == polarity)
+ return 0;
+ if (--attempts == 0)
+ return 1;
+ if (delay)
+ udelay(delay);
+ }
+}
+
+#define TPI_ATTEMPTS 50
+
+/*
+ * Write a register over the TPI interface (unlocked and locked versions).
+ */
+static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
+{
+ int tpi_busy;
+
+ writel(addr, adapter->regs + A_TPI_ADDR);
+ writel(value, adapter->regs + A_TPI_WR_DATA);
+ writel(F_TPIWR, adapter->regs + A_TPI_CSR);
+
+ tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
+ TPI_ATTEMPTS, 3);
+ if (tpi_busy)
+ CH_ALERT("%s: TPI write to 0x%x failed\n",
+ adapter->name, addr);
+ return tpi_busy;
+}
+
+int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
+{
+ int ret;
+
+ spin_lock(&(adapter)->tpi_lock);
+ ret = __t1_tpi_write(adapter, addr, value);
+ spin_unlock(&(adapter)->tpi_lock);
+ return ret;
+}
+
+/*
+ * Read a register over the TPI interface (unlocked and locked versions).
+ */
+static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
+{
+ int tpi_busy;
+
+ writel(addr, adapter->regs + A_TPI_ADDR);
+ writel(0, adapter->regs + A_TPI_CSR);
+
+ tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
+ TPI_ATTEMPTS, 3);
+ if (tpi_busy)
+ CH_ALERT("%s: TPI read from 0x%x failed\n",
+ adapter->name, addr);
+ else
+ *valp = readl(adapter->regs + A_TPI_RD_DATA);
+ return tpi_busy;
+}
+
+int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
+{
+ int ret;
+
+ spin_lock(&(adapter)->tpi_lock);
+ ret = __t1_tpi_read(adapter, addr, valp);
+ spin_unlock(&(adapter)->tpi_lock);
+ return ret;
+}
+
+/*
+ * Called when a port's link settings change to propagate the new values to the
+ * associated PHY and MAC. After performing the common tasks it invokes an
+ * OS-specific handler.
+ */
+/* static */ void link_changed(adapter_t *adapter, int port_id)
+{
+ int link_ok, speed, duplex, fc;
+ struct cphy *phy = adapter->port[port_id].phy;
+ struct link_config *lc = &adapter->port[port_id].link_config;
+
+ phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
+
+ lc->speed = speed < 0 ? SPEED_INVALID : speed;
+ lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
+ if (!(lc->requested_fc & PAUSE_AUTONEG))
+ fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+
+ if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
+ /* Set MAC speed, duplex, and flow control to match PHY. */
+ struct cmac *mac = adapter->port[port_id].mac;
+
+ mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
+ lc->fc = (unsigned char)fc;
+ }
+ t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
+}
+
+static int t1_pci_intr_handler(adapter_t *adapter)
+{
+ u32 pcix_cause;
+
+ pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
+
+ if (pcix_cause) {
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
+ pcix_cause);
+ t1_fatal_err(adapter); /* PCI errors are fatal */
+ }
+ return 0;
+}
+
+
+/*
+ * Wait until Elmer's MI1 interface is ready for new operations.
+ */
+static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
+{
+ int attempts = 100, busy;
+
+ do {
+ u32 val;
+
+ __t1_tpi_read(adapter, mi1_reg, &val);
+ busy = val & F_MI1_OP_BUSY;
+ if (busy)
+ udelay(10);
+ } while (busy && --attempts);
+ if (busy)
+ CH_ALERT("%s: MDIO operation timed out\n",
+ adapter->name);
+ return busy;
+}
+
+/*
+ * MI1 MDIO initialization.
+ */
+static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
+{
+ u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
+ u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
+ V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
+
+ if (!(bi->caps & SUPPORTED_10000baseT_Full))
+ val |= V_MI1_SOF(1);
+ t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
+}
+
+static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *valp)
+{
+ u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ spin_lock(&(adapter)->tpi_lock);
+
+ /* Write the address we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
+ MI1_OP_INDIRECT_ADDRESS);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Write the operation we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Read the data. */
+ __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+ spin_unlock(&(adapter)->tpi_lock);
+ return 0;
+}
+
+static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val)
+{
+ u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ spin_lock(&(adapter)->tpi_lock);
+
+ /* Write the address we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
+ MI1_OP_INDIRECT_ADDRESS);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Write the data. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+ spin_unlock(&(adapter)->tpi_lock);
+ return 0;
+}
+
+static struct mdio_ops mi1_mdio_ext_ops = {
+ mi1_mdio_init,
+ mi1_mdio_ext_read,
+ mi1_mdio_ext_write
+};
+
+enum {
+ CH_BRD_N110_1F,
+ CH_BRD_N210_1F,
+};
+
+static struct board_info t1_board[] = {
+
+{ CHBT_BOARD_N110, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
+ CHBT_MAC_PM3393, CHBT_PHY_88X2010,
+ 125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
+ "Chelsio N110 1x10GBaseX NIC" },
+
+{ CHBT_BOARD_N210, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T2,
+ CHBT_MAC_PM3393, CHBT_PHY_88X2010,
+ 125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
+ "Chelsio N210 1x10GBaseX NIC" },
+
+};
+
+struct pci_device_id t1_pci_tbl[] = {
+ CH_DEVICE(7, 0, CH_BRD_N110_1F),
+ CH_DEVICE(10, 1, CH_BRD_N210_1F),
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
+
+/*
+ * Return the board_info structure with a given index. Out-of-range indices
+ * return NULL.
+ */
+const struct board_info *t1_get_board_info(unsigned int board_id)
+{
+ return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
+}
+
+struct chelsio_vpd_t {
+ u32 format_version;
+ u8 serial_number[16];
+ u8 mac_base_address[6];
+ u8 pad[2]; /* make multiple-of-4 size requirement explicit */
+};
+
+#define EEPROMSIZE (8 * 1024)
+#define EEPROM_MAX_POLL 4
+
+/*
+ * Read SEEPROM. A zero is written to the flag register when the addres is
+ * written to the Control register. The hardware device will set the flag to a
+ * one when 4B have been transferred to the Data register.
+ */
+int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
+{
+ int i = EEPROM_MAX_POLL;
+ u16 val;
+
+ if (addr >= EEPROMSIZE || (addr & 3))
+ return -EINVAL;
+
+ pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
+ do {
+ udelay(50);
+ pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
+ } while (!(val & F_VPD_OP_FLAG) && --i);
+
+ if (!(val & F_VPD_OP_FLAG)) {
+ CH_ERR("%s: reading EEPROM address 0x%x failed\n",
+ adapter->name, addr);
+ return -EIO;
+ }
+ pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, data);
+ *data = le32_to_cpu(*data);
+ return 0;
+}
+
+static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
+{
+ int addr, ret = 0;
+
+ for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
+ ret = t1_seeprom_read(adapter, addr,
+ (u32 *)((u8 *)vpd + addr));
+
+ return ret;
+}
+
+/*
+ * Read a port's MAC address from the VPD ROM.
+ */
+static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
+{
+ struct chelsio_vpd_t vpd;
+
+ if (t1_eeprom_vpd_get(adapter, &vpd))
+ return 1;
+ memcpy(mac_addr, vpd.mac_base_address, 5);
+ mac_addr[5] = vpd.mac_base_address[5] + index;
+ return 0;
+}
+
+/*
+ * Set up the MAC/PHY according to the requested link settings.
+ *
+ * If the PHY can auto-negotiate first decide what to advertise, then
+ * enable/disable auto-negotiation as desired and reset.
+ *
+ * If the PHY does not auto-negotiate we just reset it.
+ *
+ * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
+ * otherwise do it later based on the outcome of auto-negotiation.
+ */
+int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
+{
+ unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+
+ if (lc->supported & SUPPORTED_Autoneg) {
+ lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
+ if (fc) {
+ lc->advertising |= ADVERTISED_ASYM_PAUSE;
+ if (fc == (PAUSE_RX | PAUSE_TX))
+ lc->advertising |= ADVERTISED_PAUSE;
+ }
+ phy->ops->advertise(phy, lc->advertising);
+
+ if (lc->autoneg == AUTONEG_DISABLE) {
+ lc->speed = lc->requested_speed;
+ lc->duplex = lc->requested_duplex;
+ lc->fc = (unsigned char)fc;
+ mac->ops->set_speed_duplex_fc(mac, lc->speed,
+ lc->duplex, fc);
+ /* Also disables autoneg */
+ phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
+ phy->ops->reset(phy, 0);
+ } else
+ phy->ops->autoneg_enable(phy); /* also resets PHY */
+ } else {
+ mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
+ lc->fc = (unsigned char)fc;
+ phy->ops->reset(phy, 0);
+ }
+ return 0;
+}
+
+/*
+ * External interrupt handler for boards using elmer0.
+ */
+int elmer0_ext_intr_handler(adapter_t *adapter)
+{
+ struct cphy *phy;
+ int phy_cause;
+ u32 cause;
+
+ t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
+
+ switch (board_info(adapter)->board) {
+ case CHBT_BOARD_N210:
+ case CHBT_BOARD_N110:
+ if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
+ phy = adapter->port[0].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ link_changed(adapter, 0);
+ }
+ break;
+ }
+ t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
+ return 0;
+}
+
+/* Enables all interrupts. */
+void t1_interrupts_enable(adapter_t *adapter)
+{
+ unsigned int i;
+ u32 pl_intr;
+
+ adapter->slow_intr_mask = F_PL_INTR_SGE_ERR;
+
+ t1_sge_intr_enable(adapter->sge);
+ if (adapter->espi) {
+ adapter->slow_intr_mask |= F_PL_INTR_ESPI;
+ t1_espi_intr_enable(adapter->espi);
+ }
+
+ /* Enable MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
+ }
+
+ /* Enable PCIX & external chip interrupts on ASIC boards. */
+ pl_intr = readl(adapter->regs + A_PL_ENABLE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
+ 0xffffffff);
+
+ adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ writel(pl_intr, adapter->regs + A_PL_ENABLE);
+}
+
+/* Disables all interrupts. */
+void t1_interrupts_disable(adapter_t* adapter)
+{
+ unsigned int i;
+
+ t1_sge_intr_disable(adapter->sge);
+ if (adapter->espi)
+ t1_espi_intr_disable(adapter->espi);
+
+ /* Disable MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
+ }
+
+ /* Disable PCIX & external chip interrupts. */
+ writel(0, adapter->regs + A_PL_ENABLE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
+
+ adapter->slow_intr_mask = 0;
+}
+
+/* Clears all interrupts */
+void t1_interrupts_clear(adapter_t* adapter)
+{
+ unsigned int i;
+ u32 pl_intr;
+
+
+ t1_sge_intr_clear(adapter->sge);
+ if (adapter->espi)
+ t1_espi_intr_clear(adapter->espi);
+
+ /* Clear MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
+ }
+
+ /* Enable interrupts for external devices. */
+ pl_intr = readl(adapter->regs + A_PL_CAUSE);
+
+ writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
+ adapter->regs + A_PL_CAUSE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
+}
+
+/*
+ * Slow path interrupt handler for ASICs.
+ */
+int t1_slow_intr_handler(adapter_t *adapter)
+{
+ u32 cause = readl(adapter->regs + A_PL_CAUSE);
+
+ cause &= adapter->slow_intr_mask;
+ if (!cause)
+ return 0;
+ if (cause & F_PL_INTR_SGE_ERR)
+ t1_sge_intr_error_handler(adapter->sge);
+ if (cause & F_PL_INTR_ESPI)
+ t1_espi_intr_handler(adapter->espi);
+ if (cause & F_PL_INTR_PCIX)
+ t1_pci_intr_handler(adapter);
+ if (cause & F_PL_INTR_EXT)
+ t1_elmer0_ext_intr(adapter);
+
+ /* Clear the interrupts just processed. */
+ writel(cause, adapter->regs + A_PL_CAUSE);
+ (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */
+ return 1;
+}
+
+/* Pause deadlock avoidance parameters */
+#define DROP_MSEC 16
+#define DROP_PKTS_CNT 1
+
+static void set_csum_offload(adapter_t *adapter, u32 csum_bit, int enable)
+{
+ u32 val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
+
+ if (enable)
+ val |= csum_bit;
+ else
+ val &= ~csum_bit;
+ writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
+}
+
+void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_IP_CSUM, enable);
+}
+
+void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_UDP_CSUM, enable);
+}
+
+void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_TCP_CSUM, enable);
+}
+
+static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk)
+{
+ u32 val;
+
+ val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
+ F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
+ val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
+ F_TP_IN_ESPI_CHECK_TCP_CSUM;
+ writel(val, adapter->regs + A_TP_IN_CONFIG);
+ writel(F_TP_OUT_CSPI_CPL |
+ F_TP_OUT_ESPI_ETHERNET |
+ F_TP_OUT_ESPI_GENERATE_IP_CSUM |
+ F_TP_OUT_ESPI_GENERATE_TCP_CSUM,
+ adapter->regs + A_TP_OUT_CONFIG);
+
+ val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
+ val &= ~(F_IP_CSUM | F_UDP_CSUM | F_TCP_CSUM);
+ writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
+
+ /*
+ * Enable pause frame deadlock prevention.
+ */
+ if (is_T2(adapter)) {
+ u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
+
+ writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
+ V_DROP_TICKS_CNT(drop_ticks) |
+ V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
+ adapter->regs + A_TP_TX_DROP_CONFIG);
+ }
+
+ writel(F_TP_RESET, adapter->regs + A_TP_RESET);
+}
+
+int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ struct adapter_params *p)
+{
+ p->chip_version = bi->chip_term;
+ if (p->chip_version == CHBT_TERM_T1 ||
+ p->chip_version == CHBT_TERM_T2) {
+ u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
+
+ val = G_TP_PC_REV(val);
+ if (val == 2)
+ p->chip_revision = TERM_T1B;
+ else if (val == 3)
+ p->chip_revision = TERM_T2;
+ else
+ return -1;
+ } else
+ return -1;
+ return 0;
+}
+
+/*
+ * Enable board components other than the Chelsio chip, such as external MAC
+ * and PHY.
+ */
+static int board_init(adapter_t *adapter, const struct board_info *bi)
+{
+ switch (bi->board) {
+ case CHBT_BOARD_N110:
+ case CHBT_BOARD_N210:
+ writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR);
+ t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Initialize and configure the Terminator HW modules. Note that external
+ * MAC and PHYs are initialized separately.
+ */
+int t1_init_hw_modules(adapter_t *adapter)
+{
+ int err = -EIO;
+ const struct board_info *bi = board_info(adapter);
+
+ if (!bi->clock_mc4) {
+ u32 val = readl(adapter->regs + A_MC4_CFG);
+
+ writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
+ writel(F_M_BUS_ENABLE | F_TCAM_RESET,
+ adapter->regs + A_MC5_CONFIG);
+ }
+
+ if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
+ bi->espi_nports))
+ goto out_err;
+
+ t1_tp_reset(adapter, bi->clock_core);
+
+ err = t1_sge_configure(adapter->sge, &adapter->params.sge);
+ if (err)
+ goto out_err;
+
+ err = 0;
+ out_err:
+ return err;
+}
+
+/*
+ * Determine a card's PCI mode.
+ */
+static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
+{
+ static unsigned short speed_map[] = { 33, 66, 100, 133 };
+ u32 pci_mode;
+
+ pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
+ p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
+ p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
+ p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
+}
+
+/*
+ * Release the structures holding the SW per-Terminator-HW-module state.
+ */
+void t1_free_sw_modules(adapter_t *adapter)
+{
+ unsigned int i;
+
+ for_each_port(adapter, i) {
+ struct cmac *mac = adapter->port[i].mac;
+ struct cphy *phy = adapter->port[i].phy;
+
+ if (mac)
+ mac->ops->destroy(mac);
+ if (phy)
+ phy->ops->destroy(phy);
+ }
+
+ if (adapter->sge)
+ t1_sge_destroy(adapter->sge);
+ if (adapter->espi)
+ t1_espi_destroy(adapter->espi);
+}
+
+static void __devinit init_link_config(struct link_config *lc,
+ const struct board_info *bi)
+{
+ lc->supported = bi->caps;
+ lc->requested_speed = lc->speed = SPEED_INVALID;
+ lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
+ lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
+ if (lc->supported & SUPPORTED_Autoneg) {
+ lc->advertising = lc->supported;
+ lc->autoneg = AUTONEG_ENABLE;
+ lc->requested_fc |= PAUSE_AUTONEG;
+ } else {
+ lc->advertising = 0;
+ lc->autoneg = AUTONEG_DISABLE;
+ }
+}
+
+
+/*
+ * Allocate and initialize the data structures that hold the SW state of
+ * the Terminator HW modules.
+ */
+int __devinit t1_init_sw_modules(adapter_t *adapter,
+ const struct board_info *bi)
+{
+ unsigned int i;
+
+ adapter->params.brd_info = bi;
+ adapter->params.nports = bi->port_number;
+ adapter->params.stats_update_period = bi->gmac->stats_update_period;
+
+ adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
+ if (!adapter->sge) {
+ CH_ERR("%s: SGE initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+
+ if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
+ CH_ERR("%s: ESPI initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+
+ board_init(adapter, bi);
+ bi->mdio_ops->init(adapter, bi);
+ if (bi->gphy->reset)
+ bi->gphy->reset(adapter);
+ if (bi->gmac->reset)
+ bi->gmac->reset(adapter);
+
+ for_each_port(adapter, i) {
+ u8 hw_addr[6];
+ struct cmac *mac;
+ int phy_addr = bi->mdio_phybaseaddr + i;
+
+ adapter->port[i].phy = bi->gphy->create(adapter, phy_addr,
+ bi->mdio_ops);
+ if (!adapter->port[i].phy) {
+ CH_ERR("%s: PHY %d initialization failed\n",
+ adapter->name, i);
+ goto error;
+ }
+
+ adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
+ if (!mac) {
+ CH_ERR("%s: MAC %d initialization failed\n",
+ adapter->name, i);
+ goto error;
+ }
+
+ /*
+ * Get the port's MAC addresses either from the EEPROM if one
+ * exists or the one hardcoded in the MAC.
+ */
+ if (vpd_macaddress_get(adapter, i, hw_addr)) {
+ CH_ERR("%s: could not read MAC address from VPD ROM\n",
+ adapter->port[i].dev->name);
+ goto error;
+ }
+ memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
+ init_link_config(&adapter->port[i].link_config, bi);
+ }
+
+ get_pci_mode(adapter, &adapter->params.pci);
+ t1_interrupts_clear(adapter);
+ return 0;
+
+ error:
+ t1_free_sw_modules(adapter);
+ return -1;
+}
diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/chelsio/suni1x10gexp_regs.h
new file mode 100644
index 000000000000..81816c2b708a
--- /dev/null
+++ b/drivers/net/chelsio/suni1x10gexp_regs.h
@@ -0,0 +1,213 @@
+/*****************************************************************************
+ * *
+ * File: suni1x10gexp_regs.h *
+ * $Revision: 1.9 $ *
+ * $Date: 2005/06/22 00:17:04 $ *
+ * Description: *
+ * PMC/SIERRA (pm3393) MAC-PHY functionality. *
+ * part of the Chelsio 10Gb Ethernet 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. *
+ * *
+ * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: PMC/SIERRA *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_SUNI1x10GEXP_REGS_H_
+#define _CXGB_SUNI1x10GEXP_REGS_H_
+
+/******************************************************************************/
+/** S/UNI-1x10GE-XP REGISTER ADDRESS MAP **/
+/******************************************************************************/
+/* Refer to the Register Bit Masks bellow for the naming of each register and */
+/* to the S/UNI-1x10GE-XP Data Sheet for the signification of each bit */
+/******************************************************************************/
+
+#define SUNI1x10GEXP_REG_DEVICE_STATUS 0x0004
+#define SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS 0x000D
+#define SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE 0x000E
+#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE 0x0102
+#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS 0x0104
+#define SUNI1x10GEXP_REG_RXXG_CONFIG_1 0x2040
+#define SUNI1x10GEXP_REG_RXXG_CONFIG_3 0x2042
+#define SUNI1x10GEXP_REG_RXXG_INTERRUPT 0x2043
+#define SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH 0x2045
+#define SUNI1x10GEXP_REG_RXXG_SA_15_0 0x2046
+#define SUNI1x10GEXP_REG_RXXG_SA_31_16 0x2047
+#define SUNI1x10GEXP_REG_RXXG_SA_47_32 0x2048
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW 0x204D
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID 0x204E
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH 0x204F
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW 0x206A
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW 0x206B
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH 0x206C
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH 0x206D
+#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0 0x206E
+#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2 0x2070
+#define SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE 0x2088
+#define SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS 0x2089
+#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE 0x208B
+#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS 0x208C
+#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE 0x20C7
+#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS 0x20C8
+#define SUNI1x10GEXP_REG_MSTAT_CONTROL 0x2100
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0 0x2101
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1 0x2102
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2 0x2103
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3 0x2104
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0 0x2105
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1 0x2106
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2 0x2107
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3 0x2108
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW 0x2110
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW 0x2114
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW 0x2120
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW 0x2124
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW 0x2128
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW 0x2130
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW 0x2138
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW 0x213C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW 0x2140
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW 0x2144
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW 0x214C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW 0x2150
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW 0x2154
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW 0x2158
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW 0x2194
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW 0x219C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW 0x21A0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW 0x21A8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW 0x21B0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW 0x21B8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW 0x21BC
+#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE 0x2209
+#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT 0x220A
+#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK 0x2282
+#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT 0x2283
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS 0x2300
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE 0x2301
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK 0x2302
+#define SUNI1x10GEXP_REG_TXXG_CONFIG_1 0x3040
+#define SUNI1x10GEXP_REG_TXXG_CONFIG_3 0x3042
+#define SUNI1x10GEXP_REG_TXXG_INTERRUPT 0x3043
+#define SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE 0x3045
+#define SUNI1x10GEXP_REG_TXXG_SA_15_0 0x3047
+#define SUNI1x10GEXP_REG_TXXG_SA_31_16 0x3048
+#define SUNI1x10GEXP_REG_TXXG_SA_47_32 0x3049
+#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS 0x3084
+#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE 0x3085
+#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE 0x30C6
+#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS 0x30C7
+#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE 0x320C
+#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION 0x320D
+#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK 0x3282
+#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT 0x3283
+
+/******************************************************************************/
+/* -- End register offset definitions -- */
+/******************************************************************************/
+
+/******************************************************************************/
+/** SUNI-1x10GE-XP REGISTER BIT MASKS **/
+/******************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * Register 0x0004: S/UNI-1x10GE-XP Device Status
+ * Bit 9 TOP_SXRA_EXPIRED
+ * Bit 8 TOP_MDIO_BUSY
+ * Bit 7 TOP_DTRB
+ * Bit 6 TOP_EXPIRED
+ * Bit 5 TOP_PAUSED
+ * Bit 4 TOP_PL4_ID_DOOL
+ * Bit 3 TOP_PL4_IS_DOOL
+ * Bit 2 TOP_PL4_ID_ROOL
+ * Bit 1 TOP_PL4_IS_ROOL
+ * Bit 0 TOP_PL4_OUT_ROOL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED 0x0200
+#define SUNI1x10GEXP_BITMSK_TOP_EXPIRED 0x0040
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL 0x0010
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL 0x0008
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL 0x0004
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL 0x0002
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x000E:PM3393 Global interrupt enable
+ * Bit 15 TOP_INTE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TOP_INTE 0x8000
+
+/*----------------------------------------------------------------------------
+ * Register 0x2040: RXXG Configuration 1
+ * Bit 15 RXXG_RXEN
+ * Bit 14 RXXG_ROCF
+ * Bit 13 RXXG_PAD_STRIP
+ * Bit 10 RXXG_PUREP
+ * Bit 9 RXXG_LONGP
+ * Bit 8 RXXG_PARF
+ * Bit 7 RXXG_FLCHK
+ * Bit 5 RXXG_PASS_CTRL
+ * Bit 3 RXXG_CRC_STRIP
+ * Bit 2-0 RXXG_MIFG
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_RXEN 0x8000
+#define SUNI1x10GEXP_BITMSK_RXXG_PUREP 0x0400
+#define SUNI1x10GEXP_BITMSK_RXXG_FLCHK 0x0080
+#define SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP 0x0008
+
+/*----------------------------------------------------------------------------
+ * Register 0x2070: RXXG Address Filter Control 2
+ * Bit 1 RXXG_PMODE
+ * Bit 0 RXXG_MHASH_EN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_PMODE 0x0002
+#define SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2100: MSTAT Control
+ * Bit 2 MSTAT_WRITE
+ * Bit 1 MSTAT_CLEAR
+ * Bit 0 MSTAT_SNAP
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MSTAT_CLEAR 0x0002
+#define SUNI1x10GEXP_BITMSK_MSTAT_SNAP 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3040: TXXG Configuration Register 1
+ * Bit 15 TXXG_TXEN0
+ * Bit 13 TXXG_HOSTPAUSE
+ * Bit 12-7 TXXG_IPGT
+ * Bit 5 TXXG_32BIT_ALIGN
+ * Bit 4 TXXG_CRCEN
+ * Bit 3 TXXG_FCTX
+ * Bit 2 TXXG_FCRX
+ * Bit 1 TXXG_PADEN
+ * Bit 0 TXXG_SPRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_TXEN0 0x8000
+#define SUNI1x10GEXP_BITOFF_TXXG_IPGT 7
+#define SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN 0x0020
+#define SUNI1x10GEXP_BITMSK_TXXG_CRCEN 0x0010
+#define SUNI1x10GEXP_BITMSK_TXXG_FCTX 0x0008
+#define SUNI1x10GEXP_BITMSK_TXXG_FCRX 0x0004
+#define SUNI1x10GEXP_BITMSK_TXXG_PADEN 0x0002
+
+#endif /* _CXGB_SUNI1x10GEXP_REGS_H_ */
+
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 442670860fca..b68b9cad76e9 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -384,8 +384,8 @@ static unsigned int mdio_phy_addr; /* Transciever address */
static unsigned int network_tr_ctrl_shadow = 0;
/* Network speed indication. */
-static struct timer_list speed_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list clear_led_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(speed_timer, NULL, 0, 0);
+static DEFINE_TIMER(clear_led_timer, NULL, 0, 0);
static int current_speed; /* Speed read from transceiver */
static int current_speed_selection; /* Speed selected by user */
static unsigned long led_next_time;
@@ -393,7 +393,7 @@ static int led_active;
static int rx_queue_len;
/* Duplex */
-static struct timer_list duplex_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(duplex_timer, NULL, 0, 0);
static int full_duplex;
static enum duplex current_duplex;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index b780307093eb..cdc07ccd7332 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -247,6 +247,9 @@ static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer
static int get_eeprom_cksum(int off, int len, int *buffer);
static int set_mac_address(struct net_device *dev, void *addr);
static void count_rx_errors(int status, struct net_local *lp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void net_poll_controller(struct net_device *dev);
+#endif
#if ALLOW_DMA
static void get_dma_channel(struct net_device *dev);
static void release_dma_buff(struct net_local *lp);
@@ -405,6 +408,19 @@ get_eeprom_cksum(int off, int len, int *buffer)
return -1;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ net_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions.
@@ -760,6 +776,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
dev->get_stats = net_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = set_mac_address;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = net_poll_controller;
+#endif
printk("\n");
if (net_debug)
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 6440a892bb81..e54fc10f6846 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1140,7 +1140,7 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
}
static int
-dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
+dm9000_drv_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct net_device *ndev = dev_get_drvdata(dev);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index d0fa2448761d..25cc20e415da 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -156,7 +156,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.4.8-k2"DRV_EXT
+#define DRV_VERSION "3.4.14-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -785,6 +785,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
}
#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
+#define E100_WAIT_SCB_FAST 20 /* delay like the old code */
static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
@@ -798,7 +799,7 @@ static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
if(likely(!readb(&nic->csr->scb.cmd_lo)))
break;
cpu_relax();
- if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1)))
+ if(unlikely(i > E100_WAIT_SCB_FAST))
udelay(5);
}
if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
@@ -902,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
static void e100_get_defaults(struct nic *nic)
{
- struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
- struct param_range cbs = { .min = 64, .max = 256, .count = 64 };
+ struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
+ struct param_range cbs = { .min = 64, .max = 256, .count = 128 };
pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
@@ -1006,25 +1007,213 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
}
+/********************************************************/
+/* Micro code for 8086:1229 Rev 8 */
+/********************************************************/
+
+/* Parameter values for the D101M B-step */
+#define D101M_CPUSAVER_TIMER_DWORD 78
+#define D101M_CPUSAVER_BUNDLE_DWORD 65
+#define D101M_CPUSAVER_MIN_SIZE_DWORD 126
+
+#define D101M_B_RCVBUNDLE_UCODE \
+{\
+0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
+0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
+0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
+0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
+0x00380438, 0x00000000, 0x00140000, 0x00380555, \
+0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
+0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
+0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
+0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
+0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
+0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
+0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
+0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
+0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
+0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
+0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
+0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
+0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
+0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
+0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
+0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
+0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
+0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
+0x00380559, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
+0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
+0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
+}
+
+/********************************************************/
+/* Micro code for 8086:1229 Rev 9 */
+/********************************************************/
+
+/* Parameter values for the D101S */
+#define D101S_CPUSAVER_TIMER_DWORD 78
+#define D101S_CPUSAVER_BUNDLE_DWORD 67
+#define D101S_CPUSAVER_MIN_SIZE_DWORD 128
+
+#define D101S_RCVBUNDLE_UCODE \
+{\
+0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
+0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
+0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
+0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
+0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
+0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
+0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
+0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
+0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
+0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
+0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
+0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
+0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
+0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
+0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
+0x00101313, 0x00380700, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
+0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
+0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
+0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
+0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
+0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
+0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
+0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
+0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
+0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00130831, \
+0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
+0x00041000, 0x00010004, 0x00380700 \
+}
+
+/********************************************************/
+/* Micro code for the 8086:1229 Rev F/10 */
+/********************************************************/
+
+/* Parameter values for the D102 E-step */
+#define D102_E_CPUSAVER_TIMER_DWORD 42
+#define D102_E_CPUSAVER_BUNDLE_DWORD 54
+#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46
+
+#define D102_E_RCVBUNDLE_UCODE \
+{\
+0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
+0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
+0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
+0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
+0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
+0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
+0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+}
+
static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
- int i;
- static const u32 ucode[UCODE_SIZE] = {
- /* NFS packets are misinterpreted as TCO packets and
- * incorrectly routed to the BMC over SMBus. This
- * microcode patch checks the fragmented IP bit in the
- * NFS/UDP header to distinguish between NFS and TCO. */
- 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
- 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
- 0x00906EFD, 0x00900EFD, 0x00E00EF8,
- };
+/* *INDENT-OFF* */
+ static struct {
+ u32 ucode[UCODE_SIZE + 1];
+ u8 mac;
+ u8 timer_dword;
+ u8 bundle_dword;
+ u8 min_size_dword;
+ } ucode_opts[] = {
+ { D101M_B_RCVBUNDLE_UCODE,
+ mac_82559_D101M,
+ D101M_CPUSAVER_TIMER_DWORD,
+ D101M_CPUSAVER_BUNDLE_DWORD,
+ D101M_CPUSAVER_MIN_SIZE_DWORD },
+ { D101S_RCVBUNDLE_UCODE,
+ mac_82559_D101S,
+ D101S_CPUSAVER_TIMER_DWORD,
+ D101S_CPUSAVER_BUNDLE_DWORD,
+ D101S_CPUSAVER_MIN_SIZE_DWORD },
+ { D102_E_RCVBUNDLE_UCODE,
+ mac_82551_F,
+ D102_E_CPUSAVER_TIMER_DWORD,
+ D102_E_CPUSAVER_BUNDLE_DWORD,
+ D102_E_CPUSAVER_MIN_SIZE_DWORD },
+ { D102_E_RCVBUNDLE_UCODE,
+ mac_82551_10,
+ D102_E_CPUSAVER_TIMER_DWORD,
+ D102_E_CPUSAVER_BUNDLE_DWORD,
+ D102_E_CPUSAVER_MIN_SIZE_DWORD },
+ { {0}, 0, 0, 0, 0}
+ }, *opts;
+/* *INDENT-ON* */
+
+#define BUNDLESMALL 1
+#define BUNDLEMAX 50
+#define INTDELAY 15000
+
+ opts = ucode_opts;
+
+ /* do not load u-code for ICH devices */
+ if (nic->flags & ich)
+ return;
+
+ /* Search for ucode match against h/w rev_id */
+ while (opts->mac) {
+ if (nic->mac == opts->mac) {
+ int i;
+ u32 *ucode = opts->ucode;
+
+ /* Insert user-tunable settings */
+ ucode[opts->timer_dword] &= 0xFFFF0000;
+ ucode[opts->timer_dword] |=
+ (u16) INTDELAY;
+ ucode[opts->bundle_dword] &= 0xFFFF0000;
+ ucode[opts->bundle_dword] |= (u16) BUNDLEMAX;
+ ucode[opts->min_size_dword] &= 0xFFFF0000;
+ ucode[opts->min_size_dword] |=
+ (BUNDLESMALL) ? 0xFFFF : 0xFF80;
+
+ for(i = 0; i < UCODE_SIZE; i++)
+ cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+ cb->command = cpu_to_le16(cb_ucode);
+ return;
+ }
+ opts++;
+ }
- if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
- for(i = 0; i < UCODE_SIZE; i++)
- cb->u.ucode[i] = cpu_to_le32(ucode[i]);
- cb->command = cpu_to_le16(cb_ucode);
- } else
- cb->command = cpu_to_le16(cb_nop);
+ cb->command = cpu_to_le16(cb_nop);
}
static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
@@ -1307,14 +1496,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
{
cb->command = nic->tx_command;
/* interrupt every 16 packets regardless of delay */
- if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i;
+ if((nic->cbs_avail & ~15) == nic->cbs_avail)
+ cb->command |= cpu_to_le16(cb_i);
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
- // check for mapping failure?
+ /* check for mapping failure? */
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}
@@ -1539,7 +1729,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* Don't indicate if hardware indicates errors */
nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
- } else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
+ } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
nic->net_stats.rx_dropped++;
@@ -1706,6 +1896,7 @@ static int e100_poll(struct net_device *netdev, int *budget)
static void e100_netpoll(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
+
e100_disable_irq(nic);
e100_intr(nic->pdev->irq, netdev, NULL);
e100_tx_clean(nic);
@@ -2108,6 +2299,8 @@ static void e100_diag_test(struct net_device *netdev,
}
for(i = 0; i < E100_TEST_LEN; i++)
test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
+
+ msleep_interruptible(4 * 1000);
}
static int e100_phys_id(struct net_device *netdev, u32 data)
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 93e9f8788751..51c2b3a18b6f 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1270,7 +1270,7 @@ struct e1000_hw_stats {
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t *hw_addr;
+ uint8_t __iomem *hw_addr;
uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index b82fd15d0891..7c8a0a22dcd5 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -162,7 +162,7 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);
-static int e1000_suspend(struct pci_dev *pdev, uint32_t state);
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
#ifdef CONFIG_PM
static int e1000_resume(struct pci_dev *pdev);
#endif
@@ -2767,7 +2767,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%zx>\n"
+ " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
@@ -2776,7 +2776,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
E1000_READ_REG(&adapter->hw, TDT),
tx_ring->next_to_use,
i,
- tx_ring->buffer_info[i].dma,
+ (unsigned long long)tx_ring->buffer_info[i].dma,
tx_ring->buffer_info[i].time_stamp,
eop,
jiffies,
@@ -3642,7 +3642,7 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
}
static int
-e1000_suspend(struct pci_dev *pdev, uint32_t state)
+e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3726,9 +3726,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
}
pci_disable_device(pdev);
-
- state = (state > 0) ? 3 : 0;
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
@@ -3741,13 +3739,13 @@ e1000_resume(struct pci_dev *pdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t manc, ret_val, swsm;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
- pci_enable_wake(pdev, 3, 0);
- pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 1795425f512e..8c62ced2c9b2 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1263,8 +1263,8 @@ speedo_init_rx_ring(struct net_device *dev)
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- /* XXX: do we really want to call this before the NULL check? --hch */
- rx_align(skb); /* Align IP on 16 byte boundary */
+ if (skb)
+ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* OK. Just initially short of Rx bufs. */
@@ -1654,8 +1654,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
struct sk_buff *skb;
/* Get a fresh skbuff to replace the consumed one. */
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- /* XXX: do we really want to call this before the NULL check? --hch */
- rx_align(skb); /* Align IP on 16 byte boundary */
+ if (skb)
+ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[entry] = skb;
if (skb == NULL) {
sp->rx_ringp[entry] = NULL;
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 2c7008491378..85504fb900da 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -8,7 +8,7 @@
* describes connections using the internal parallel port I/O, which
* is basically all of Port D.
*
- * Right now, I am very watseful with the buffers. I allocate memory
+ * Right now, I am very wasteful with the buffers. I allocate memory
* pages and then divide them into 2K frame buffers. This way I know I
* have buffers large enough to hold one frame within one buffer descriptor.
* Once I get this working, I will use 64 or 128 byte CPM buffers, which
@@ -19,7 +19,10 @@
* Copyright (c) 2000 Ericsson Radio Systems AB.
*
* Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2005 Macq Electronique SA.
*/
#include <linux/config.h>
@@ -46,7 +49,8 @@
#include <asm/io.h>
#include <asm/pgtable.h>
-#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+ defined(CONFIG_M5272) || defined(CONFIG_M528x)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include "fec.h"
@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
#elif defined(CONFIG_M527x)
(MCF_MBAR + 0x1000),
(MCF_MBAR + 0x1800),
-#elif defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
(MCF_MBAR + 0x1000),
#else
&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@ static unsigned char fec_mac_default[] = {
#define FEC_FLASHMAC 0xffe04000
#elif defined(CONFIG_CANCam)
#define FEC_FLASHMAC 0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define FEC_FLASHMAC (0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC 0xffc0406b
#else
#define FEC_FLASHMAC 0
#endif
-unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
-
/* Forward declarations of some structures to support different PHYs
*/
@@ -158,7 +164,7 @@ typedef struct {
* size bits. Other FEC hardware does not, so we need to take that into
* account when setting it.
*/
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
@@ -196,7 +202,7 @@ struct fec_enet_private {
uint phy_id_done;
uint phy_status;
uint phy_speed;
- phy_info_t *phy;
+ phy_info_t const *phy;
struct work_struct phy_task;
uint sequence_done;
@@ -209,7 +215,6 @@ struct fec_enet_private {
int link;
int old_link;
int full_duplex;
- unsigned char mac_addr[ETH_ALEN];
};
static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@ typedef struct mii_list {
} mii_list_t;
#define NMII 20
-mii_list_t mii_cmds[NMII];
-mii_list_t *mii_free;
-mii_list_t *mii_head;
-mii_list_t *mii_tail;
+static mii_list_t mii_cmds[NMII];
+static mii_list_t *mii_free;
+static mii_list_t *mii_head;
+static mii_list_t *mii_tail;
static int mii_queue(struct net_device *dev, int request,
void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
}
}
#endif
- fec_restart(dev, 0);
+ fec_restart(dev, fep->full_duplex);
netif_wake_queue(dev);
}
@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
if (mii_reg & 0x0004)
- *s |= PHY_STAT_LINK;
+ status |= PHY_STAT_LINK;
if (mii_reg & 0x0010)
- *s |= PHY_STAT_FAULT;
+ status |= PHY_STAT_FAULT;
if (mii_reg & 0x0020)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
+
+ *s = status;
}
static void mii_parse_cr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+ status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
if (mii_reg & 0x1000)
- *s |= PHY_CONF_ANE;
+ status |= PHY_CONF_ANE;
if (mii_reg & 0x4000)
- *s |= PHY_CONF_LOOP;
+ status |= PHY_CONF_LOOP;
+ *s = status;
}
static void mii_parse_anar(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_CONF_SPMASK);
+ status = *s & ~(PHY_CONF_SPMASK);
if (mii_reg & 0x0020)
- *s |= PHY_CONF_10HDX;
+ status |= PHY_CONF_10HDX;
if (mii_reg & 0x0040)
- *s |= PHY_CONF_10FDX;
+ status |= PHY_CONF_10FDX;
if (mii_reg & 0x0080)
- *s |= PHY_CONF_100HDX;
+ status |= PHY_CONF_100HDX;
if (mii_reg & 0x00100)
- *s |= PHY_CONF_100FDX;
+ status |= PHY_CONF_100FDX;
+ *s = status;
}
/* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK);
-
+ status = *s & ~(PHY_STAT_SPMASK);
if (mii_reg & 0x0800) {
if (mii_reg & 0x1000)
- *s |= PHY_STAT_100FDX;
+ status |= PHY_STAT_100FDX;
else
- *s |= PHY_STAT_100HDX;
+ status |= PHY_STAT_100HDX;
} else {
if (mii_reg & 0x1000)
- *s |= PHY_STAT_10FDX;
+ status |= PHY_STAT_10FDX;
else
- *s |= PHY_STAT_10HDX;
+ status |= PHY_STAT_10HDX;
}
+ *s = status;
}
-static phy_info_t phy_info_lxt970 = {
- 0x07810000,
- "LXT970",
-
- (const phy_cmd_t []) { /* config */
+static phy_cmd_t const phy_cmd_lxt970_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
/* read SR and ISR to acknowledge */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
/* find out the current status */
{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_lxt970 = {
+ .id = 0x07810000,
+ .name = "LXT970",
+ .config = phy_cmd_lxt970_config,
+ .startup = phy_cmd_lxt970_startup,
+ .ack_int = phy_cmd_lxt970_ack_int,
+ .shutdown = phy_cmd_lxt970_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
if (mii_reg & 0x0400) {
fep->link = 1;
- *s |= PHY_STAT_LINK;
+ status |= PHY_STAT_LINK;
} else {
fep->link = 0;
}
if (mii_reg & 0x0080)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
if (mii_reg & 0x4000) {
if (mii_reg & 0x0200)
- *s |= PHY_STAT_100FDX;
+ status |= PHY_STAT_100FDX;
else
- *s |= PHY_STAT_100HDX;
+ status |= PHY_STAT_100HDX;
} else {
if (mii_reg & 0x0200)
- *s |= PHY_STAT_10FDX;
+ status |= PHY_STAT_10FDX;
else
- *s |= PHY_STAT_10HDX;
+ status |= PHY_STAT_10HDX;
}
if (mii_reg & 0x0008)
- *s |= PHY_STAT_FAULT;
-}
+ status |= PHY_STAT_FAULT;
-static phy_info_t phy_info_lxt971 = {
- 0x0001378e,
- "LXT971",
+ *s = status;
+}
- (const phy_cmd_t []) { /* config */
- /* limit to 10MBit because my protorype board
+static phy_cmd_t const phy_cmd_lxt971_config[] = {
+ /* limit to 10MBit because my prototype board
* doesn't work with 100. */
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt971_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
* read here to get a valid value in ack_int */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
+ /* acknowledge the int before reading status ! */
+ { mk_mii_read(MII_LXT971_ISR), NULL },
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
- /* we only need to read ISR to acknowledge */
- { mk_mii_read(MII_LXT971_ISR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_lxt971 = {
+ .id = 0x0001378e,
+ .name = "LXT971",
+ .config = phy_cmd_lxt971_config,
+ .startup = phy_cmd_lxt971_startup,
+ .ack_int = phy_cmd_lxt971_ack_int,
+ .shutdown = phy_cmd_lxt971_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK);
+ status = *s & ~(PHY_STAT_SPMASK);
switch((mii_reg >> 2) & 7) {
- case 1: *s |= PHY_STAT_10HDX; break;
- case 2: *s |= PHY_STAT_100HDX; break;
- case 5: *s |= PHY_STAT_10FDX; break;
- case 6: *s |= PHY_STAT_100FDX; break;
- }
+ case 1: status |= PHY_STAT_10HDX; break;
+ case 2: status |= PHY_STAT_100HDX; break;
+ case 5: status |= PHY_STAT_10FDX; break;
+ case 6: status |= PHY_STAT_100FDX; break;
}
-static phy_info_t phy_info_qs6612 = {
- 0x00181440,
- "QS6612",
-
- (const phy_cmd_t []) { /* config */
+ *s = status;
+}
+
+static phy_cmd_t const phy_cmd_qs6612_config[] = {
/* The PHY powers up isolated on the RPX,
* so send a command to allow operation.
*/
@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_qs6612_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
/* we need to read ISR, SR and ANER to acknowledge */
{ mk_mii_read(MII_QS6612_ISR), NULL },
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
/* read pcr to get info */
{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_qs6612 = {
+ .id = 0x00181440,
+ .name = "QS6612",
+ .config = phy_cmd_qs6612_config,
+ .startup = phy_cmd_qs6612_startup,
+ .ack_int = phy_cmd_qs6612_ack_int,
+ .shutdown = phy_cmd_qs6612_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
if (mii_reg & 0x0080)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
if (mii_reg & 0x0400)
- *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
+ status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
else
- *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+ status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+
+ *s = status;
}
-static phy_info_t phy_info_am79c874 = {
- 0x00022561,
- "AM79C874",
-
- (const phy_cmd_t []) { /* config */
- /* limit to 10MBit because my protorype board
- * doesn't work with 100. */
+static phy_cmd_t const phy_cmd_am79c874_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_am79c874_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
/* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_AM79C874_ICSR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_am79c874 = {
+ .id = 0x00022561,
+ .name = "AM79C874",
+ .config = phy_cmd_am79c874_config,
+ .startup = phy_cmd_am79c874_startup,
+ .ack_int = phy_cmd_am79c874_ack_int,
+ .shutdown = phy_cmd_am79c874_shutdown
};
+
/* ------------------------------------------------------------------------- */
/* Kendin KS8721BL phy */
@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
#define MII_KS8721BL_ICSR 22
#define MII_KS8721BL_PHYCR 31
-static phy_info_t phy_info_ks8721bl = {
- 0x00022161,
- "KS8721BL",
-
- (const phy_cmd_t []) { /* config */
+static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
/* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_KS8721BL_ICSR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_ks8721bl = {
+ .id = 0x00022161,
+ .name = "KS8721BL",
+ .config = phy_cmd_ks8721bl_config,
+ .startup = phy_cmd_ks8721bl_startup,
+ .ack_int = phy_cmd_ks8721bl_ack_int,
+ .shutdown = phy_cmd_ks8721bl_shutdown
};
/* ------------------------------------------------------------------------- */
-static phy_info_t *phy_info[] = {
+static phy_info_t const * const phy_info[] = {
&phy_info_lxt970,
&phy_info_lxt971,
&phy_info_qs6612,
@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
static void __inline__ fec_request_intrs(struct net_device *dev)
{
volatile unsigned long *icrp;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ } *idp, id[] = {
+ { "fec(RX)", 86, fec_enet_interrupt },
+ { "fec(TX)", 87, fec_enet_interrupt },
+ { "fec(OTHER)", 88, fec_enet_interrupt },
+ { "fec(MII)", 66, mii_link_interrupt },
+ { NULL },
+ };
/* Setup interrupt handlers. */
- if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0)
- printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n");
- if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0)
- printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n");
- if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
- printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
- if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
- printk("FEC: Could not allocate MII IRQ(66)!\n");
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
+ printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
+ }
/* Unmask interrupt at ColdFire 5272 SIM */
icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp;
- unsigned char *iap, tmpaddr[6];
- int i;
+ unsigned char *iap, tmpaddr[ETH_ALEN];
fecp = fep->hwp;
- if (fec_flashmac) {
+ if (FEC_FLASHMAC) {
/*
* Get MAC address from FLASH.
* If it is all 1's or 0's, use the default.
*/
- iap = fec_flashmac;
+ iap = (unsigned char *)FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default;
@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0];
}
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
/* Adjust MAC if using default MAC address */
- if (iap == fec_mac_default) {
- dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
- iap[ETH_ALEN-1] + fep->index;
- }
+ if (iap == fec_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
}
static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
/* ------------------------------------------------------------------------- */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/*
- * Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups.
+ * Code specific to Coldfire 5230/5231/5232/5234/5235,
+ * the 5270/5271/5274/5275 and 5280/5282 setups.
*/
static void __inline__ fec_request_intrs(struct net_device *dev)
{
struct fec_enet_private *fep;
int b;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ } *idp, id[] = {
+ { "fec(TXF)", 23 },
+ { "fec(TXB)", 24 },
+ { "fec(TXFIFO)", 25 },
+ { "fec(TXCR)", 26 },
+ { "fec(RXF)", 27 },
+ { "fec(RXB)", 28 },
+ { "fec(MII)", 29 },
+ { "fec(LC)", 30 },
+ { "fec(HBERR)", 31 },
+ { "fec(GRA)", 32 },
+ { "fec(EBERR)", 33 },
+ { "fec(BABT)", 34 },
+ { "fec(BABR)", 35 },
+ { NULL },
+ };
fep = netdev_priv(dev);
b = (fep->index) ? 128 : 64;
/* Setup interrupt handlers. */
- if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b);
- if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b);
- if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
- if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
-
- if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
- printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
- if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
- printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
-
- if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
- printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
- if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
- printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
- if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
- printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
- if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
- printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
- if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
- printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
- if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
- printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
- if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
- printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
+ printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+ }
/* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
{
@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
#if defined(CONFIG_M528x)
/* Set up gpio outputs for MII lines */
{
- volatile unsigned short *gpio_paspar;
+ volatile u16 *gpio_paspar;
+ volatile u8 *gpio_pehlpar;
- gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR +
- 0x100056);
- *gpio_paspar = 0x0f00;
+ gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
+ gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+ *gpio_paspar |= 0x0f00;
+ *gpio_pehlpar = 0xc0;
}
#endif
}
@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp;
- unsigned char *iap, tmpaddr[6];
- int i;
+ unsigned char *iap, tmpaddr[ETH_ALEN];
fecp = fep->hwp;
- if (fec_flashmac) {
+ if (FEC_FLASHMAC) {
/*
* Get MAC address from FLASH.
* If it is all 1's or 0's, use the default.
*/
- iap = fec_flashmac;
+ iap = FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default;
@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0];
}
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
/* Adjust MAC if using default MAC address */
- if (iap == fec_mac_default) {
- dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
- iap[ETH_ALEN-1] + fep->index;
- }
+ if (iap == fec_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
}
static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
#else
/*
- * Code sepcific to the MPC860T setup.
+ * Code specific to the MPC860T setup.
*/
static void __inline__ fec_request_intrs(struct net_device *dev)
{
@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
static void __inline__ fec_get_mac(struct net_device *dev)
{
- struct fec_enet_private *fep = netdev_priv(dev);
- unsigned char *iap, tmpaddr[6];
bd_t *bd;
- int i;
- iap = bd->bi_enetaddr;
bd = (bd_t *)__res;
+ memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
#ifdef CONFIG_RPXCLASSIC
/* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
* the address bits above something that would have (up to
* now) been allocated.
*/
- for (i=0; i<6; i++)
- tmpaddr[i] = *iap++;
- tmpaddr[3] |= 0x80;
- iap = tmpaddr;
+ dev->dev_adrd[3] |= 0x80;
#endif
-
- for (i=0; i<6; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
}
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
static void mii_display_config(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
- volatile uint *s = &(fep->phy_status);
+ uint status = fep->phy_status;
/*
** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
fep->mii_phy_task_queued = 0;
printk("%s: config: auto-negotiation ", dev->name);
- if (*s & PHY_CONF_ANE)
+ if (status & PHY_CONF_ANE)
printk("on");
else
printk("off");
- if (*s & PHY_CONF_100FDX)
+ if (status & PHY_CONF_100FDX)
printk(", 100FDX");
- if (*s & PHY_CONF_100HDX)
+ if (status & PHY_CONF_100HDX)
printk(", 100HDX");
- if (*s & PHY_CONF_10FDX)
+ if (status & PHY_CONF_10FDX)
printk(", 10FDX");
- if (*s & PHY_CONF_10HDX)
+ if (status & PHY_CONF_10HDX)
printk(", 10HDX");
- if (!(*s & PHY_CONF_SPMASK))
+ if (!(status & PHY_CONF_SPMASK))
printk(", No speed/duplex selected?");
- if (*s & PHY_CONF_LOOP)
+ if (status & PHY_CONF_LOOP)
printk(", loopback enabled");
printk(".\n");
@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task);
}
-/* mii_queue_config is called in user context from fec_enet_open */
+/* mii_queue_config is called in interrupt context from fec_enet_mii */
static void mii_queue_config(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task);
}
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
- { mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
- { mk_mii_end, } };
-
-
+phy_cmd_t const phy_cmd_relink[] = {
+ { mk_mii_read(MII_REG_CR), mii_queue_relink },
+ { mk_mii_end, }
+ };
+phy_cmd_t const phy_cmd_config[] = {
+ { mk_mii_read(MII_REG_CR), mii_queue_config },
+ { mk_mii_end, }
+ };
/* Read remainder of PHY ID.
*/
@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
static void
fec_set_mac_address(struct net_device *dev)
{
- struct fec_enet_private *fep;
volatile fec_t *fecp;
- fep = netdev_priv(dev);
- fecp = fep->hwp;
+ fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
/* Set station address. */
- fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
- (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
- fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
- (fep->mac_addr[4] << 24);
+ fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+ (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
+ fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
+ (dev->dev_addr[4] << 24);
}
@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
udelay(10);
/* Clear and enable interrupts */
- fecp->fec_ievent = 0xffc0;
+ fecp->fec_ievent = 0xffc00000;
fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
/* setup MII interface */
fec_set_mii(dev, fep);
- printk("%s: FEC ENET Version 0.2, ", dev->name);
- for (i=0; i<5; i++)
- printk("%02x:", dev->dev_addr[i]);
- printk("%02x\n", dev->dev_addr[5]);
-
/* Queue up command to detect the PHY and initialize the
* remainder of the interface.
*/
@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
/* Clear any outstanding interrupt.
*/
- fecp->fec_ievent = 0xffc0;
+ fecp->fec_ievent = 0xffc00000;
fec_enable_phy_intr();
/* Set station address.
*/
- fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
- (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
- fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
- (fep->mac_addr[4] << 24);
-
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i];
+ fec_set_mac_address(dev);
/* Reset all multicast.
*/
@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */
- while(!(fecp->fec_ievent & 0x10000000));
+ while(!(fecp->fec_ievent & FEC_ENET_GRA));
/* Whack a reset. We should wait for this.
*/
@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
static int __init fec_enet_module_init(void)
{
struct net_device *dev;
- int i, err;
+ int i, j, err;
+
+ printk("FEC ENET Version 0.2\n");
for (i = 0; (i < FEC_MAX_PORTS); i++) {
dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
free_netdev(dev);
return -EIO;
}
+
+ printk("%s: ethernet ", dev->name);
+ for (j = 0; (j < 5); j++)
+ printk("%02x:", dev->dev_addr[j]);
+ printk("%02x\n", dev->dev_addr[5]);
}
return 0;
}
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index c6e4f979ff5d..045761b8a600 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -1,8 +1,9 @@
/****************************************************************************/
/*
- * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5270,
- 5271, 5272, 5274, 5275, 5280 and 5282.
+ * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5230,
+ * 5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
+ * 5280 and 5282.
*
* (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
* (C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
#define FEC_H
/****************************************************************************/
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 64f0f697c958..d6eefdb71c17 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -85,6 +85,16 @@
* 0.33: 16 May 2005: Support for MCP51 added.
* 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
* 0.35: 26 Jun 2005: Support for MCP55 added.
+ * 0.36: 28 Jun 2005: Add jumbo frame support.
+ * 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
+ * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
+ * per-packet flags.
+ * 0.39: 18 Jul 2005: Add 64bit descriptor support.
+ * 0.40: 19 Jul 2005: Add support for mac address change.
+ * 0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+ * of nv_remove
+ * 0.42: 06 Aug 2005: Fix lack of link speed initialization
+ * in the second (and later) nv_open call
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -96,7 +106,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.35"
+#define FORCEDETH_VERSION "0.41"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -131,11 +141,10 @@
* Hardware access:
*/
-#define DEV_NEED_LASTPACKET1 0x0001 /* set LASTPACKET1 in tx flags */
-#define DEV_IRQMASK_1 0x0002 /* use NVREG_IRQMASK_WANTED_1 for irq mask */
-#define DEV_IRQMASK_2 0x0004 /* use NVREG_IRQMASK_WANTED_2 for irq mask */
-#define DEV_NEED_TIMERIRQ 0x0008 /* set the timer irq flag in the irq mask */
-#define DEV_NEED_LINKTIMER 0x0010 /* poll link settings. Relies on the timer irq */
+#define DEV_NEED_TIMERIRQ 0x0001 /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
enum {
NvRegIrqStatus = 0x000,
@@ -146,13 +155,16 @@ enum {
#define NVREG_IRQ_RX 0x0002
#define NVREG_IRQ_RX_NOBUF 0x0004
#define NVREG_IRQ_TX_ERR 0x0008
-#define NVREG_IRQ_TX2 0x0010
+#define NVREG_IRQ_TX_OK 0x0010
#define NVREG_IRQ_TIMER 0x0020
#define NVREG_IRQ_LINK 0x0040
+#define NVREG_IRQ_TX_ERROR 0x0080
#define NVREG_IRQ_TX1 0x0100
-#define NVREG_IRQMASK_WANTED_1 0x005f
-#define NVREG_IRQMASK_WANTED_2 0x0147
-#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
+#define NVREG_IRQMASK_WANTED 0x00df
+
+#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
+ NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
+ NVREG_IRQ_TX1))
NvRegUnknownSetupReg6 = 0x008,
#define NVREG_UNKSETUP6_VAL 3
@@ -286,6 +298,18 @@ struct ring_desc {
u32 FlagLen;
};
+struct ring_desc_ex {
+ u32 PacketBufferHigh;
+ u32 PacketBufferLow;
+ u32 Reserved;
+ u32 FlagLen;
+};
+
+typedef union _ring_type {
+ struct ring_desc* orig;
+ struct ring_desc_ex* ex;
+} ring_type;
+
#define FLAG_MASK_V1 0xffff0000
#define FLAG_MASK_V2 0xffffc000
#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
@@ -293,7 +317,7 @@ struct ring_desc {
#define NV_TX_LASTPACKET (1<<16)
#define NV_TX_RETRYERROR (1<<19)
-#define NV_TX_LASTPACKET1 (1<<24)
+#define NV_TX_FORCED_INTERRUPT (1<<24)
#define NV_TX_DEFERRED (1<<26)
#define NV_TX_CARRIERLOST (1<<27)
#define NV_TX_LATECOLLISION (1<<28)
@@ -303,7 +327,7 @@ struct ring_desc {
#define NV_TX2_LASTPACKET (1<<29)
#define NV_TX2_RETRYERROR (1<<18)
-#define NV_TX2_LASTPACKET1 (1<<23)
+#define NV_TX2_FORCED_INTERRUPT (1<<30)
#define NV_TX2_DEFERRED (1<<25)
#define NV_TX2_CARRIERLOST (1<<26)
#define NV_TX2_LATECOLLISION (1<<27)
@@ -379,9 +403,13 @@ struct ring_desc {
#define TX_LIMIT_START 62
/* rx/tx mac addr + type + vlan + align + slack*/
-#define RX_NIC_BUFSIZE (ETH_DATA_LEN + 64)
-/* even more slack */
-#define RX_ALLOC_BUFSIZE (ETH_DATA_LEN + 128)
+#define NV_RX_HEADERS (64)
+/* even more slack. */
+#define NV_RX_ALLOC_PAD (64)
+
+/* maximum mtu size */
+#define NV_PKTLIMIT_1 ETH_DATA_LEN /* hard limit not known */
+#define NV_PKTLIMIT_2 9100 /* Actual limit according to NVidia: 9202 */
#define OOM_REFILL (1+HZ/20)
#define POLL_WAIT (1+HZ/100)
@@ -396,6 +424,7 @@ struct ring_desc {
*/
#define DESC_VER_1 0x0
#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_3 (0x02200|NVREG_TXRXCTL_RXCHECK)
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
@@ -468,11 +497,12 @@ struct fe_priv {
/* rx specific fields.
* Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
*/
- struct ring_desc *rx_ring;
+ ring_type rx_ring;
unsigned int cur_rx, refill_rx;
struct sk_buff *rx_skbuff[RX_RING];
dma_addr_t rx_dma[RX_RING];
unsigned int rx_buf_sz;
+ unsigned int pkt_limit;
struct timer_list oom_kick;
struct timer_list nic_poll;
@@ -484,7 +514,7 @@ struct fe_priv {
/*
* tx specific fields.
*/
- struct ring_desc *tx_ring;
+ ring_type tx_ring;
unsigned int next_tx, nic_tx;
struct sk_buff *tx_skbuff[TX_RING];
dma_addr_t tx_dma[TX_RING];
@@ -519,6 +549,11 @@ static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
& ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
}
+static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
+{
+ return le32_to_cpu(prd->FlagLen) & LEN_MASK_V2;
+}
+
static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
int delay, int delaymax, const char *msg)
{
@@ -792,7 +827,7 @@ static int nv_alloc_rx(struct net_device *dev)
nr = refill_rx % RX_RING;
if (np->rx_skbuff[nr] == NULL) {
- skb = dev_alloc_skb(RX_ALLOC_BUFSIZE);
+ skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
if (!skb)
break;
@@ -803,9 +838,16 @@ static int nv_alloc_rx(struct net_device *dev)
}
np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len,
PCI_DMA_FROMDEVICE);
- np->rx_ring[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
- wmb();
- np->rx_ring[nr].FlagLen = cpu_to_le32(RX_NIC_BUFSIZE | NV_RX_AVAIL);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->rx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
+ wmb();
+ np->rx_ring.orig[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
+ } else {
+ np->rx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
+ np->rx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF;
+ wmb();
+ np->rx_ring.ex[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
+ }
dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet %d marked as Available\n",
dev->name, refill_rx);
refill_rx++;
@@ -831,19 +873,37 @@ static void nv_do_rx_refill(unsigned long data)
enable_irq(dev->irq);
}
-static int nv_init_ring(struct net_device *dev)
+static void nv_init_rx(struct net_device *dev)
{
struct fe_priv *np = get_nvpriv(dev);
int i;
- np->next_tx = np->nic_tx = 0;
- for (i = 0; i < TX_RING; i++)
- np->tx_ring[i].FlagLen = 0;
-
np->cur_rx = RX_RING;
np->refill_rx = 0;
for (i = 0; i < RX_RING; i++)
- np->rx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->rx_ring.orig[i].FlagLen = 0;
+ else
+ np->rx_ring.ex[i].FlagLen = 0;
+}
+
+static void nv_init_tx(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ int i;
+
+ np->next_tx = np->nic_tx = 0;
+ for (i = 0; i < TX_RING; i++)
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[i].FlagLen = 0;
+ else
+ np->tx_ring.ex[i].FlagLen = 0;
+}
+
+static int nv_init_ring(struct net_device *dev)
+{
+ nv_init_tx(dev);
+ nv_init_rx(dev);
return nv_alloc_rx(dev);
}
@@ -852,7 +912,10 @@ static void nv_drain_tx(struct net_device *dev)
struct fe_priv *np = get_nvpriv(dev);
int i;
for (i = 0; i < TX_RING; i++) {
- np->tx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[i].FlagLen = 0;
+ else
+ np->tx_ring.ex[i].FlagLen = 0;
if (np->tx_skbuff[i]) {
pci_unmap_single(np->pci_dev, np->tx_dma[i],
np->tx_skbuff[i]->len,
@@ -869,7 +932,10 @@ static void nv_drain_rx(struct net_device *dev)
struct fe_priv *np = get_nvpriv(dev);
int i;
for (i = 0; i < RX_RING; i++) {
- np->rx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->rx_ring.orig[i].FlagLen = 0;
+ else
+ np->rx_ring.ex[i].FlagLen = 0;
wmb();
if (np->rx_skbuff[i]) {
pci_unmap_single(np->pci_dev, np->rx_dma[i],
@@ -900,11 +966,19 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
PCI_DMA_TODEVICE);
- np->tx_ring[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ else {
+ np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+ np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+ }
spin_lock_irq(&np->lock);
wmb();
- np->tx_ring[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+ else
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
dev->name, np->next_tx);
{
@@ -942,7 +1016,10 @@ static void nv_tx_done(struct net_device *dev)
while (np->nic_tx != np->next_tx) {
i = np->nic_tx % TX_RING;
- Flags = le32_to_cpu(np->tx_ring[i].FlagLen);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
+ else
+ Flags = le32_to_cpu(np->tx_ring.ex[i].FlagLen);
dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, Flags 0x%x.\n",
dev->name, np->nic_tx, Flags);
@@ -993,9 +1070,56 @@ static void nv_tx_timeout(struct net_device *dev)
struct fe_priv *np = get_nvpriv(dev);
u8 __iomem *base = get_hwbase(dev);
- dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name,
+ printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
+ {
+ int i;
+
+ printk(KERN_INFO "%s: Ring at %lx: next %d nic %d\n",
+ 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) {
+ printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ i,
+ readl(base + i + 0), readl(base + i + 4),
+ readl(base + i + 8), readl(base + i + 12),
+ readl(base + i + 16), readl(base + i + 20),
+ readl(base + i + 24), readl(base + i + 28));
+ }
+ printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+ for (i=0;i<TX_RING;i+= 4) {
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+1].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+2].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+2].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+3].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
+ } else {
+ printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+1].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+2].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+3].FlagLen));
+ }
+ }
+ }
+
spin_lock_irq(&np->lock);
/* 1) stop tx engine */
@@ -1009,7 +1133,10 @@ static void nv_tx_timeout(struct net_device *dev)
printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name);
nv_drain_tx(dev);
np->next_tx = np->nic_tx = 0;
- writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
netif_wake_queue(dev);
}
@@ -1084,8 +1211,13 @@ static void nv_rx_process(struct net_device *dev)
break; /* we scanned the whole ring - do not continue */
i = np->cur_rx % RX_RING;
- Flags = le32_to_cpu(np->rx_ring[i].FlagLen);
- len = nv_descr_getlength(&np->rx_ring[i], np->desc_ver);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
+ len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
+ } else {
+ Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen);
+ len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
+ }
dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
dev->name, np->cur_rx, Flags);
@@ -1207,15 +1339,133 @@ next_pkt:
}
}
+static void set_bufsize(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+
+ if (dev->mtu <= ETH_DATA_LEN)
+ np->rx_buf_sz = ETH_DATA_LEN + NV_RX_HEADERS;
+ else
+ np->rx_buf_sz = dev->mtu + NV_RX_HEADERS;
+}
+
/*
* nv_change_mtu: dev->change_mtu function
* Called with dev_base_lock held for read.
*/
static int nv_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu > ETH_DATA_LEN)
+ struct fe_priv *np = get_nvpriv(dev);
+ int old_mtu;
+
+ if (new_mtu < 64 || new_mtu > np->pkt_limit)
return -EINVAL;
+
+ old_mtu = dev->mtu;
dev->mtu = new_mtu;
+
+ /* return early if the buffer sizes will not change */
+ if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN)
+ return 0;
+ if (old_mtu == new_mtu)
+ return 0;
+
+ /* synchronized against open : rtnl_lock() held by caller */
+ if (netif_running(dev)) {
+ u8 __iomem *base = get_hwbase(dev);
+ /*
+ * It seems that the nic preloads valid ring entries into an
+ * internal buffer. The procedure for flushing everything is
+ * guessed, there is probably a simpler approach.
+ * Changing the MTU is a rare event, it shouldn't matter.
+ */
+ disable_irq(dev->irq);
+ spin_lock_bh(&dev->xmit_lock);
+ spin_lock(&np->lock);
+ /* stop engines */
+ nv_stop_rx(dev);
+ nv_stop_tx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+ nv_drain_rx(dev);
+ nv_drain_tx(dev);
+ /* reinit driver view of the rx queue */
+ nv_init_rx(dev);
+ nv_init_tx(dev);
+ /* alloc new rx buffers */
+ set_bufsize(dev);
+ if (nv_alloc_rx(dev)) {
+ if (!np->in_shutdown)
+ mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+ }
+ /* reinit nic view of the rx queue */
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+ writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+ writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+ base + NvRegRingSizes);
+ pci_push(base);
+ writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+ pci_push(base);
+
+ /* restart rx engine */
+ nv_start_rx(dev);
+ nv_start_tx(dev);
+ spin_unlock(&np->lock);
+ spin_unlock_bh(&dev->xmit_lock);
+ enable_irq(dev->irq);
+ }
+ return 0;
+}
+
+static void nv_copy_mac_to_hw(struct net_device *dev)
+{
+ u8 __iomem *base = get_hwbase(dev);
+ u32 mac[2];
+
+ mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
+ (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+ mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+
+ writel(mac[0], base + NvRegMacAddrA);
+ writel(mac[1], base + NvRegMacAddrB);
+}
+
+/*
+ * nv_set_mac_address: dev->set_mac_address function
+ * Called with rtnl_lock() held.
+ */
+static int nv_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ struct sockaddr *macaddr = (struct sockaddr*)addr;
+
+ if(!is_valid_ether_addr(macaddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ /* synchronized against open : rtnl_lock() held by caller */
+ memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
+
+ if (netif_running(dev)) {
+ spin_lock_bh(&dev->xmit_lock);
+ spin_lock_irq(&np->lock);
+
+ /* stop rx engine */
+ nv_stop_rx(dev);
+
+ /* set mac address */
+ nv_copy_mac_to_hw(dev);
+
+ /* restart rx engine */
+ nv_start_rx(dev);
+ spin_unlock_irq(&np->lock);
+ spin_unlock_bh(&dev->xmit_lock);
+ } else {
+ nv_copy_mac_to_hw(dev);
+ }
return 0;
}
@@ -1470,7 +1720,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask))
break;
- if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX2|NVREG_IRQ_TX_ERR)) {
+ if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
spin_lock(&np->lock);
nv_tx_done(dev);
spin_unlock(&np->lock);
@@ -1761,6 +2011,50 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return 0;
}
+#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;
+}
+
+static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ u32 *rbuf = buf;
+ int i;
+
+ regs->version = FORCEDETH_REGS_VER;
+ spin_lock_irq(&np->lock);
+ for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+ rbuf[i] = readl(base + i*sizeof(u32));
+ spin_unlock_irq(&np->lock);
+}
+
+static int nv_nway_reset(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ int ret;
+
+ spin_lock_irq(&np->lock);
+ if (np->autoneg) {
+ int bmcr;
+
+ bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+ spin_unlock_irq(&np->lock);
+
+ return ret;
+}
+
static struct ethtool_ops ops = {
.get_drvinfo = nv_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -1768,6 +2062,9 @@ static struct ethtool_ops ops = {
.set_wol = nv_set_wol,
.get_settings = nv_get_settings,
.set_settings = nv_set_settings,
+ .get_regs_len = nv_get_regs_len,
+ .get_regs = nv_get_regs,
+ .nway_reset = nv_nway_reset,
};
static int nv_open(struct net_device *dev)
@@ -1792,6 +2089,7 @@ static int nv_open(struct net_device *dev)
writel(0, base + NvRegAdapterControl);
/* 2) initialize descriptor rings */
+ set_bufsize(dev);
oom = nv_init_ring(dev);
writel(0, base + NvRegLinkSpeed);
@@ -1802,20 +2100,14 @@ static int nv_open(struct net_device *dev)
np->in_shutdown = 0;
/* 3) set mac address */
- {
- u32 mac[2];
-
- mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
- (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
- mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
-
- writel(mac[0], base + NvRegMacAddrA);
- writel(mac[1], base + NvRegMacAddrB);
- }
+ nv_copy_mac_to_hw(dev);
/* 4) give hw rings */
writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
- writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
base + NvRegRingSizes);
@@ -1837,7 +2129,7 @@ static int nv_open(struct net_device *dev)
writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
- writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
get_random_bytes(&i, sizeof(i));
@@ -1888,6 +2180,9 @@ static int nv_open(struct net_device *dev)
writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
}
+ /* set linkspeed to invalid value, thus force nv_update_linkspeed
+ * to init hw */
+ np->linkspeed = 0;
ret = nv_update_linkspeed(dev);
nv_start_rx(dev);
nv_start_tx(dev);
@@ -1942,6 +2237,12 @@ static int nv_close(struct net_device *dev)
if (np->wolenabled)
nv_start_rx(dev);
+ /* special op: write back the misordered MAC address - otherwise
+ * the next nv_probe would see a wrong address.
+ */
+ writel(np->orig_mac[0], base + NvRegMacAddrA);
+ writel(np->orig_mac[1], base + NvRegMacAddrB);
+
/* FIXME: power down nic */
return 0;
@@ -2006,32 +2307,55 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
}
/* handle different descriptor versions */
- if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13)
- np->desc_ver = DESC_VER_1;
- else
+ 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)) {
+ printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
+ pci_name(pci_dev));
+ }
+ } else if (id->driver_data & DEV_HAS_LARGEDESC) {
+ /* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
+ } else {
+ /* original packet format */
+ np->desc_ver = DESC_VER_1;
+ }
+
+ np->pkt_limit = NV_PKTLIMIT_1;
+ if (id->driver_data & DEV_HAS_LARGEDESC)
+ np->pkt_limit = NV_PKTLIMIT_2;
err = -ENOMEM;
np->base = ioremap(addr, NV_PCI_REGSZ);
if (!np->base)
goto out_relreg;
dev->base_addr = (unsigned long)np->base;
+
dev->irq = pci_dev->irq;
- np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
- &np->ring_addr);
- if (!np->rx_ring)
- goto out_unmap;
- np->tx_ring = &np->rx_ring[RX_RING];
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->rx_ring.orig = pci_alloc_consistent(pci_dev,
+ sizeof(struct ring_desc) * (RX_RING + TX_RING),
+ &np->ring_addr);
+ if (!np->rx_ring.orig)
+ goto out_unmap;
+ np->tx_ring.orig = &np->rx_ring.orig[RX_RING];
+ } else {
+ np->rx_ring.ex = pci_alloc_consistent(pci_dev,
+ sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+ &np->ring_addr);
+ if (!np->rx_ring.ex)
+ goto out_unmap;
+ np->tx_ring.ex = &np->rx_ring.ex[RX_RING];
+ }
dev->open = nv_open;
dev->stop = nv_close;
dev->hard_start_xmit = nv_start_xmit;
dev->get_stats = nv_get_stats;
dev->change_mtu = nv_change_mtu;
+ dev->set_mac_address = nv_set_mac_address;
dev->set_multicast_list = nv_set_multicast;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = nv_poll_controller;
@@ -2080,17 +2404,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (np->desc_ver == DESC_VER_1) {
np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
- if (id->driver_data & DEV_NEED_LASTPACKET1)
- np->tx_flags |= NV_TX_LASTPACKET1;
} else {
np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
- if (id->driver_data & DEV_NEED_LASTPACKET1)
- np->tx_flags |= NV_TX2_LASTPACKET1;
}
- if (id->driver_data & DEV_IRQMASK_1)
- np->irqmask = NVREG_IRQMASK_WANTED_1;
- if (id->driver_data & DEV_IRQMASK_2)
- np->irqmask = NVREG_IRQMASK_WANTED_2;
+ np->irqmask = NVREG_IRQMASK_WANTED;
if (id->driver_data & DEV_NEED_TIMERIRQ)
np->irqmask |= NVREG_IRQ_TIMER;
if (id->driver_data & DEV_NEED_LINKTIMER) {
@@ -2155,8 +2472,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
return 0;
out_freering:
- pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
- np->rx_ring, np->ring_addr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
+ np->rx_ring.orig, np->ring_addr);
+ else
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+ np->rx_ring.ex, np->ring_addr);
pci_set_drvdata(pci_dev, NULL);
out_unmap:
iounmap(get_hwbase(dev));
@@ -2174,18 +2495,14 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
struct fe_priv *np = get_nvpriv(dev);
- u8 __iomem *base = get_hwbase(dev);
unregister_netdev(dev);
- /* special op: write back the misordered MAC address - otherwise
- * the next nv_probe would see a wrong address.
- */
- writel(np->orig_mac[0], base + NvRegMacAddrA);
- writel(np->orig_mac[1], base + NvRegMacAddrB);
-
/* free all structures */
- pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring, np->ring_addr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr);
+ else
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr);
iounmap(get_hwbase(dev));
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
@@ -2195,109 +2512,64 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
static struct pci_device_id pci_tbl[] = {
{ /* nForce Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce2 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_5,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_6,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_7,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
},
{ /* CK804 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_8,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* CK804 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_9,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_10,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_11,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_12,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_13,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_14,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ 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_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_15,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ 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_HIGH_DMA,
},
{0,},
};
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index d9df1d9a5739..bc9a3bf8d560 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -204,6 +204,10 @@ KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu>
#define RUN_AT(x) (jiffies + (x))
+#ifndef ADDRLEN
+#define ADDRLEN 32
+#endif
+
/* Condensed bus+endian portability operations. */
#if ADDRLEN == 64
#define cpu_to_leXX(addr) cpu_to_le64(addr)
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index f9e3be96963c..90999867a32c 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -293,7 +293,7 @@ static int sp_header(struct sk_buff *skb, struct net_device *dev,
{
#ifdef CONFIG_INET
if (type != htons(ETH_P_AX25))
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+ return ax25_hard_header(skb, dev, type, daddr, saddr, len);
#endif
return 0;
}
@@ -308,12 +308,6 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr_ax25 *sa = addr;
- if (sa->sax25_family != AF_AX25)
- return -EINVAL;
-
- if (!sa->sax25_ndigis)
- return -EINVAL;
-
spin_lock_irq(&dev->xmit_lock);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
@@ -668,6 +662,9 @@ static int sixpack_open(struct tty_struct *tty)
netif_start_queue(dev);
init_timer(&sp->tx_t);
+ sp->tx_t.function = sp_xmit_on_air;
+ sp->tx_t.data = (unsigned long) sp;
+
init_timer(&sp->resync_t);
spin_unlock_bh(&sp->lock);
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 0cd54306e636..de087cd609d9 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -1,6 +1,6 @@
config MKISS
tristate "Serial port KISS driver"
- depends on AX25 && BROKEN_ON_SMP
+ depends on AX25
---help---
KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index a7f15d9f13e5..e4188d082f01 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -40,7 +40,7 @@
/*****************************************************************************/
-#include <linux/config.h>
+#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -48,17 +48,12 @@
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/parport.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
#include <linux/if_arp.h>
-#include <linux/kmod.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
+#include <linux/jiffies.h>
#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-#include <linux/crc-ccitt.h>
+#include <asm/uaccess.h>
/* --------------------------------------------------------------------- */
@@ -287,7 +282,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
@@ -1176,13 +1171,8 @@ static void baycom_probe(struct net_device *dev)
/* Fill in the fields of the device structure */
bc->skb = NULL;
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = baycom_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 612ad452bee0..3b1bef1ee215 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -84,6 +84,7 @@
#include <linux/baycom.h>
#include <linux/parport.h>
#include <linux/bitops.h>
+#include <linux/jiffies.h>
#include <asm/bug.h>
#include <asm/system.h>
@@ -165,7 +166,7 @@ static void __inline__ baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 25f270b05378..232793d2ce6b 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -79,6 +79,7 @@
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */
@@ -159,7 +160,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index eead85d00962..be596a3eb3fd 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -69,6 +69,7 @@
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */
@@ -150,7 +151,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index ba9f0580e1f9..1756f0ed54cc 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -98,7 +98,7 @@ static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char bpq_eth_addr[6];
-static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
+static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
static const char *bpq_print_ethaddr(const unsigned char *);
@@ -165,7 +165,7 @@ static inline int dev_is_ethdev(struct net_device *dev)
/*
* Receive an AX.25 frame via an ethernet interface.
*/
-static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
+static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)
{
int len;
char * ptr;
@@ -488,7 +488,7 @@ static void bpq_setup(struct net_device *dev)
dev->flags = 0;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
#endif
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index f515245a3fd0..3be3f916643a 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -449,12 +449,12 @@ module_exit(dmascc_exit);
static void dev_setup(struct net_device *dev)
{
dev->type = ARPHRD_AX25;
- dev->hard_header_len = 73;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
dev->mtu = 1500;
- dev->addr_len = 7;
+ dev->addr_len = AX25_ADDR_LEN;
dev->tx_queue_len = 64;
- memcpy(dev->broadcast, ax25_broadcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
+ memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
}
static int __init setup_adapter(int card_base, int type, int n)
@@ -600,7 +600,7 @@ static int __init setup_adapter(int card_base, int type, int n)
dev->do_ioctl = scc_ioctl;
dev->hard_start_xmit = scc_send_packet;
dev->get_stats = scc_get_stats;
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_set_mac_address;
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b4c836e4fe86..dacc7687b97f 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -42,7 +42,6 @@
/*****************************************************************************/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/net.h>
@@ -52,20 +51,14 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/bitops.h>
-#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/hdlcdrv.h>
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
+#include <asm/uaccess.h>
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
#include <linux/crc-ccitt.h>
/* --------------------------------------------------------------------- */
@@ -708,13 +701,8 @@ static void hdlcdrv_setup(struct net_device *dev)
s->skb = NULL;
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = hdlcdrv_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 3035422f5ad8..d9fe64b46f4b 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -1,30 +1,19 @@
/*
- * MKISS Driver
+ * 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 module:
- * This module is free software; you can redistribute it and/or
- * modify it under the terms of the 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * This module implements the AX.25 protocol for kernel-based
- * devices like TTYs. It interfaces between a raw TTY, and the
- * kernel's AX.25 protocol layers, just like slip.c.
- * AX.25 needs to be separated from slip.c while slip.c is no
- * longer a static kernel device since it is a module.
- * This method clears the way to implement other kiss protocols
- * like mkiss smack g8bpq ..... so far only mkiss is implemented.
+ * You 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.
*
- * Hans Alblas <hans@esrac.ele.tue.nl>
- *
- * History
- * Jonathan (G4KLX) Fixed to match Linux networking changes - 2.1.15.
- * Matthias (DG2FEF) Added support for FlexNet CRC (on special request)
- * Fixed bug in ax25_close(): dev_lock_wait() was
- * called twice, causing a deadlock.
- * Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
- * MOD_*_USE_COUNT
- * Remove cli() and fix rtnl lock usage.
+ * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
+ * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
*/
#include <linux/config.h>
@@ -46,177 +35,300 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
+#include <linux/jiffies.h>
#include <net/ax25.h>
-#include "mkiss.h"
-
#ifdef CONFIG_INET
#include <linux/ip.h>
#include <linux/tcp.h>
#endif
-static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
-
-typedef struct ax25_ctrl {
- struct ax_disp ctrl; /* */
- struct net_device dev; /* the device */
-} ax25_ctrl_t;
-
-static ax25_ctrl_t **ax25_ctrls;
-
-int ax25_maxdev = AX25_MAXDEV; /* Can be overridden with insmod! */
-
-static struct tty_ldisc ax_ldisc;
-
-static int ax25_init(struct net_device *);
-static int kiss_esc(unsigned char *, unsigned char *, int);
-static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);
-static void kiss_unesc(struct ax_disp *, unsigned char);
+#define AX_MTU 236
+
+/* SLIP/KISS protocol characters. */
+#define END 0300 /* indicates end of frame */
+#define ESC 0333 /* indicates byte stuffing */
+#define ESC_END 0334 /* ESC ESC_END means END 'data' */
+#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
+
+struct mkiss {
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct net_device *dev; /* easy for intr handling */
+
+ /* These are pointers to the malloc()ed frame buffers. */
+ spinlock_t buflock;/* lock for rbuf and xbuf */
+ unsigned char *rbuff; /* receiver buffer */
+ int rcount; /* received chars counter */
+ unsigned char *xbuff; /* transmitter buffer */
+ unsigned char *xhead; /* pointer to next byte to XMIT */
+ int xleft; /* bytes left in XMIT queue */
+
+ struct net_device_stats stats;
+
+ /* Detailed SLIP statistics. */
+ int mtu; /* Our mtu (to spot changes!) */
+ int buffsize; /* Max buffers sizes */
+
+ unsigned long flags; /* Flag values/ mode etc */
+ /* long req'd: used by set_bit --RR */
+#define AXF_INUSE 0 /* Channel in use */
+#define AXF_ESCAPE 1 /* ESC received */
+#define AXF_ERROR 2 /* Parity, etc. error */
+#define AXF_KEEPTEST 3 /* Keepalive test flag */
+#define AXF_OUTWAIT 4 /* is outpacket was flag */
+
+ int mode;
+ int crcmode; /* MW: for FlexNet, SMACK etc. */
+#define CRC_MODE_NONE 0
+#define CRC_MODE_FLEX 1
+#define CRC_MODE_SMACK 2
+
+ atomic_t refcnt;
+ struct semaphore dead_sem;
+};
/*---------------------------------------------------------------------------*/
-static const unsigned short Crc_flex_table[] = {
- 0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
- 0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
- 0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
- 0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
- 0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
- 0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
- 0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
- 0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
- 0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
- 0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
- 0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
- 0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
- 0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
- 0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
- 0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
- 0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
- 0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
- 0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
- 0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
- 0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
- 0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
- 0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
- 0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
- 0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
- 0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
- 0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
- 0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
- 0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
- 0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
- 0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
- 0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
- 0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
+static const unsigned short crc_flex_table[] = {
+ 0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
+ 0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
+ 0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
+ 0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
+ 0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
+ 0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
+ 0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
+ 0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
+ 0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
+ 0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
+ 0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
+ 0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
+ 0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
+ 0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
+ 0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
+ 0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
+ 0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
+ 0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
+ 0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
+ 0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
+ 0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
+ 0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
+ 0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
+ 0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
+ 0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
+ 0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
+ 0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
+ 0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
+ 0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
+ 0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
+ 0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
+ 0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
};
-/*---------------------------------------------------------------------------*/
-
static unsigned short calc_crc_flex(unsigned char *cp, int size)
{
- unsigned short crc = 0xffff;
-
- while (size--)
- crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+ unsigned short crc = 0xffff;
- return crc;
-}
+ while (size--)
+ crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
-/*---------------------------------------------------------------------------*/
+ return crc;
+}
static int check_crc_flex(unsigned char *cp, int size)
{
- unsigned short crc = 0xffff;
+ unsigned short crc = 0xffff;
- if (size < 3)
- return -1;
+ if (size < 3)
+ return -1;
- while (size--)
- crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+ while (size--)
+ crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
- if ((crc & 0xffff) != 0x7070)
- return -1;
+ if ((crc & 0xffff) != 0x7070)
+ return -1;
- return 0;
+ return 0;
}
-/*---------------------------------------------------------------------------*/
+/*
+ * Standard encapsulation
+ */
-/* Find a free channel, and link in this `tty' line. */
-static inline struct ax_disp *ax_alloc(void)
+static int kiss_esc(unsigned char *s, unsigned char *d, int len)
{
- ax25_ctrl_t *axp=NULL;
- int i;
+ unsigned char *ptr = d;
+ unsigned char c;
- for (i = 0; i < ax25_maxdev; i++) {
- axp = ax25_ctrls[i];
+ /*
+ * Send an initial END character to flush out any data that may have
+ * accumulated in the receiver due to line noise.
+ */
- /* Not allocated ? */
- if (axp == NULL)
- break;
+ *ptr++ = END;
- /* Not in use ? */
- if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))
+ while (len-- > 0) {
+ switch (c = *s++) {
+ case END:
+ *ptr++ = ESC;
+ *ptr++ = ESC_END;
break;
+ case ESC:
+ *ptr++ = ESC;
+ *ptr++ = ESC_ESC;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
}
- /* Sorry, too many, all slots in use */
- if (i >= ax25_maxdev)
- return NULL;
+ *ptr++ = END;
+
+ return ptr - d;
+}
+
+/*
+ * MW:
+ * OK its ugly, but tell me a better solution without copying the
+ * packet to a temporary buffer :-)
+ */
+static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
+ int len)
+{
+ unsigned char *ptr = d;
+ unsigned char c=0;
+
+ *ptr++ = END;
+ while (len > 0) {
+ if (len > 2)
+ c = *s++;
+ else if (len > 1)
+ c = crc >> 8;
+ else if (len > 0)
+ c = crc & 0xff;
+
+ len--;
- /* If no channels are available, allocate one */
- if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
- axp = ax25_ctrls[i];
+ switch (c) {
+ case END:
+ *ptr++ = ESC;
+ *ptr++ = ESC_END;
+ break;
+ case ESC:
+ *ptr++ = ESC;
+ *ptr++ = ESC_ESC;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
}
- memset(axp, 0, sizeof(ax25_ctrl_t));
-
- /* Initialize channel control data */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- sprintf(axp->dev.name, "ax%d", i++);
- axp->ctrl.tty = NULL;
- axp->dev.base_addr = i;
- axp->dev.priv = (void *)&axp->ctrl;
- axp->dev.next = NULL;
- axp->dev.init = ax25_init;
-
- if (axp != NULL) {
- /*
- * register device so that it can be ifconfig'ed
- * ax25_init() will be called as a side-effect
- * SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !
- */
- if (register_netdev(&axp->dev) == 0) {
- /* (Re-)Set the INUSE bit. Very Important! */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- axp->ctrl.dev = &axp->dev;
- axp->dev.priv = (void *) &axp->ctrl;
-
- return &axp->ctrl;
- } else {
- clear_bit(AXF_INUSE,&axp->ctrl.flags);
- printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");
+ *ptr++ = END;
+
+ return ptr - d;
+}
+
+/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
+static void ax_bump(struct mkiss *ax)
+{
+ struct sk_buff *skb;
+ int count;
+
+ spin_lock_bh(&ax->buflock);
+ if (ax->rbuff[0] > 0x0f) {
+ if (ax->rbuff[0] & 0x20) {
+ ax->crcmode = CRC_MODE_FLEX;
+ if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+ ax->stats.rx_errors++;
+ return;
+ }
+ ax->rcount -= 2;
+ /* dl9sau bugfix: the trailling two bytes flexnet crc
+ * will not be passed to the kernel. thus we have
+ * to correct the kissparm signature, because it
+ * indicates a crc but there's none
+ */
+ *ax->rbuff &= ~0x20;
}
+ }
+ spin_unlock_bh(&ax->buflock);
+
+ count = ax->rcount;
+
+ if ((skb = dev_alloc_skb(count)) == NULL) {
+ printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
+ ax->dev->name);
+ ax->stats.rx_dropped++;
+ return;
}
- return NULL;
+ spin_lock_bh(&ax->buflock);
+ memcpy(skb_put(skb,count), ax->rbuff, count);
+ spin_unlock_bh(&ax->buflock);
+ skb->protocol = ax25_type_trans(skb, ax->dev);
+ netif_rx(skb);
+ ax->dev->last_rx = jiffies;
+ ax->stats.rx_packets++;
+ ax->stats.rx_bytes += count;
}
-/* Free an AX25 channel. */
-static inline void ax_free(struct ax_disp *ax)
+static void kiss_unesc(struct mkiss *ax, unsigned char s)
{
- /* Free all AX25 frame buffers. */
- if (ax->rbuff)
- kfree(ax->rbuff);
- ax->rbuff = NULL;
- if (ax->xbuff)
- kfree(ax->xbuff);
- ax->xbuff = NULL;
- if (!test_and_clear_bit(AXF_INUSE, &ax->flags))
- printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);
+ switch (s) {
+ case END:
+ /* drop keeptest bit = VSV */
+ if (test_bit(AXF_KEEPTEST, &ax->flags))
+ clear_bit(AXF_KEEPTEST, &ax->flags);
+
+ if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
+ ax_bump(ax);
+
+ clear_bit(AXF_ESCAPE, &ax->flags);
+ ax->rcount = 0;
+ return;
+
+ case ESC:
+ set_bit(AXF_ESCAPE, &ax->flags);
+ return;
+ case ESC_ESC:
+ if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+ s = ESC;
+ break;
+ case ESC_END:
+ if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+ s = END;
+ break;
+ }
+
+ spin_lock_bh(&ax->buflock);
+ if (!test_bit(AXF_ERROR, &ax->flags)) {
+ if (ax->rcount < ax->buffsize) {
+ ax->rbuff[ax->rcount++] = s;
+ spin_unlock_bh(&ax->buflock);
+ return;
+ }
+
+ ax->stats.rx_over_errors++;
+ set_bit(AXF_ERROR, &ax->flags);
+ }
+ spin_unlock_bh(&ax->buflock);
+}
+
+static int ax_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr_ax25 *sa = addr;
+
+ spin_lock_irq(&dev->xmit_lock);
+ memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+ spin_unlock_irq(&dev->xmit_lock);
+
+ return 0;
}
-static void ax_changedmtu(struct ax_disp *ax)
+/*---------------------------------------------------------------------------*/
+
+static void ax_changedmtu(struct mkiss *ax)
{
struct net_device *dev = ax->dev;
unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
@@ -236,7 +348,8 @@ static void ax_changedmtu(struct ax_disp *ax)
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
+ printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
+ "MTU change cancelled.\n",
ax->dev->name);
dev->mtu = ax->mtu;
if (xbuff != NULL)
@@ -258,7 +371,7 @@ static void ax_changedmtu(struct ax_disp *ax)
memcpy(ax->xbuff, ax->xhead, ax->xleft);
} else {
ax->xleft = 0;
- ax->tx_dropped++;
+ ax->stats.tx_dropped++;
}
}
@@ -269,7 +382,7 @@ static void ax_changedmtu(struct ax_disp *ax)
memcpy(ax->rbuff, orbuff, ax->rcount);
} else {
ax->rcount = 0;
- ax->rx_over_errors++;
+ ax->stats.rx_over_errors++;
set_bit(AXF_ERROR, &ax->flags);
}
}
@@ -279,72 +392,14 @@ static void ax_changedmtu(struct ax_disp *ax)
spin_unlock_bh(&ax->buflock);
- if (oxbuff != NULL)
- kfree(oxbuff);
- if (orbuff != NULL)
- kfree(orbuff);
-}
-
-
-/* Set the "sending" flag. This must be atomic. */
-static inline void ax_lock(struct ax_disp *ax)
-{
- netif_stop_queue(ax->dev);
-}
-
-
-/* Clear the "sending" flag. This must be atomic. */
-static inline void ax_unlock(struct ax_disp *ax)
-{
- netif_start_queue(ax->dev);
-}
-
-/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
-static void ax_bump(struct ax_disp *ax)
-{
- struct sk_buff *skb;
- int count;
-
- spin_lock_bh(&ax->buflock);
- if (ax->rbuff[0] > 0x0f) {
- if (ax->rbuff[0] & 0x20) {
- ax->crcmode = CRC_MODE_FLEX;
- if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
- ax->rx_errors++;
- return;
- }
- ax->rcount -= 2;
- /* dl9sau bugfix: the trailling two bytes flexnet crc
- * will not be passed to the kernel. thus we have
- * to correct the kissparm signature, because it
- * indicates a crc but there's none
- */
- *ax->rbuff &= ~0x20;
- }
- }
- spin_unlock_bh(&ax->buflock);
-
- count = ax->rcount;
-
- if ((skb = dev_alloc_skb(count)) == NULL) {
- printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);
- ax->rx_dropped++;
- return;
- }
-
- spin_lock_bh(&ax->buflock);
- memcpy(skb_put(skb,count), ax->rbuff, count);
- spin_unlock_bh(&ax->buflock);
- skb->protocol = ax25_type_trans(skb, ax->dev);
- netif_rx(skb);
- ax->dev->last_rx = jiffies;
- ax->rx_packets++;
- ax->rx_bytes+=count;
+ kfree(oxbuff);
+ kfree(orbuff);
}
/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
-static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
+static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
{
+ struct mkiss *ax = netdev_priv(dev);
unsigned char *p;
int actual, count;
@@ -354,8 +409,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */
len = ax->mtu;
printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
- ax->tx_dropped++;
- ax_unlock(ax);
+ ax->stats.tx_dropped++;
+ netif_start_queue(dev);
return;
}
@@ -376,10 +431,11 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
break;
}
- ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
- ax->tx_packets++;
- ax->tx_bytes+=actual;
+ ax->stats.tx_packets++;
+ ax->stats.tx_bytes += actual;
+
ax->dev->trans_start = jiffies;
ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual;
@@ -387,37 +443,10 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
spin_unlock_bh(&ax->buflock);
}
-/*
- * Called by the driver when there's room for more data. If we have
- * more packets to send, we send them here.
- */
-static void ax25_write_wakeup(struct tty_struct *tty)
-{
- int actual;
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
- return;
- if (ax->xleft <= 0) {
- /* Now serial buffer is almost free & we can start
- * transmission of another packet
- */
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
- netif_wake_queue(ax->dev);
- return;
- }
-
- actual = tty->driver->write(tty, ax->xhead, ax->xleft);
- ax->xleft -= actual;
- ax->xhead += actual;
-}
-
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
if (!netif_running(dev)) {
printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -429,7 +458,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- if (jiffies - dev->trans_start < 20 * HZ) {
+ if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
/* 20 sec timeout not reached */
return 1;
}
@@ -439,20 +468,30 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
"bad line quality" : "driver error");
ax->xleft = 0;
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- ax_unlock(ax);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
+ netif_start_queue(dev);
}
/* We were not busy, so we are now... :-) */
if (skb != NULL) {
- ax_lock(ax);
- ax_encaps(ax, skb->data, skb->len);
+ netif_stop_queue(dev);
+ ax_encaps(dev, skb->data, skb->len);
kfree_skb(skb);
}
return 0;
}
+static int ax_open_dev(struct net_device *dev)
+{
+ struct mkiss *ax = netdev_priv(dev);
+
+ if (ax->tty == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/* Return the frame type ID */
@@ -461,7 +500,7 @@ static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short
{
#ifdef CONFIG_INET
if (type != htons(ETH_P_AX25))
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+ return ax25_hard_header(skb, dev, type, daddr, saddr, len);
#endif
return 0;
}
@@ -481,7 +520,7 @@ static int ax_rebuild_header(struct sk_buff *skb)
/* Open the low-level part of the AX25 channel. Easy! */
static int ax_open(struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
unsigned long len;
if (ax->tty == NULL)
@@ -518,7 +557,6 @@ static int ax_open(struct net_device *dev)
spin_lock_init(&ax->buflock);
- netif_start_queue(dev);
return 0;
noxbuff:
@@ -532,68 +570,100 @@ norbuff:
/* Close the low-level part of the AX25 channel. Easy! */
static int ax_close(struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
- if (ax->tty == NULL)
- return -EBUSY;
-
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ if (ax->tty)
+ clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
netif_stop_queue(dev);
return 0;
}
-static int ax25_receive_room(struct tty_struct *tty)
+static struct net_device_stats *ax_get_stats(struct net_device *dev)
{
- return 65536; /* We can handle an infinite amount of data. :-) */
+ struct mkiss *ax = netdev_priv(dev);
+
+ return &ax->stats;
+}
+
+static void ax_setup(struct net_device *dev)
+{
+ static char ax25_bcast[AX25_ADDR_LEN] =
+ {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+ static char ax25_test[AX25_ADDR_LEN] =
+ {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+ /* Finish setting up the DEVICE info. */
+ dev->mtu = AX_MTU;
+ dev->hard_start_xmit = ax_xmit;
+ dev->open = ax_open_dev;
+ dev->stop = ax_close;
+ dev->get_stats = ax_get_stats;
+ dev->set_mac_address = ax_set_mac_address;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_AX25;
+ dev->tx_queue_len = 10;
+ dev->hard_header = ax_header;
+ dev->rebuild_header = ax_rebuild_header;
+
+ memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+
+ dev->flags = IFF_BROADCAST | IFF_MULTICAST;
}
/*
- * Handle the 'receiver data ready' interrupt.
- * This function is called by the 'tty_io' module in the kernel when
- * a block of data has been received, which can now be decapsulated
- * and sent on to the AX.25 layer for further processing.
+ * We have a potential race on dereferencing tty->disc_data, because the tty
+ * layer provides no locking at all - thus one cpu could be running
+ * sixpack_receive_buf while another calls sixpack_close, which zeroes
+ * tty->disc_data and frees the memory that sixpack_receive_buf is using. The
+ * best way to fix this is to use a rwlock in the tty struct, but for now we
+ * use a single global rwlock for all ttys in ppp line discipline.
*/
-static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+
+static struct mkiss *mkiss_get(struct tty_struct *tty)
{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+ struct mkiss *ax;
- if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
- return;
+ read_lock(&disc_data_lock);
+ ax = tty->disc_data;
+ if (ax)
+ atomic_inc(&ax->refcnt);
+ read_unlock(&disc_data_lock);
- /*
- * Argh! mtu change time! - costs us the packet part received
- * at the change
- */
- if (ax->mtu != ax->dev->mtu + 73)
- ax_changedmtu(ax);
-
- /* Read the characters out of the buffer */
- while (count--) {
- if (fp != NULL && *fp++) {
- if (!test_and_set_bit(AXF_ERROR, &ax->flags))
- ax->rx_errors++;
- cp++;
- continue;
- }
+ return ax;
+}
- kiss_unesc(ax, *cp++);
- }
+static void mkiss_put(struct mkiss *ax)
+{
+ if (atomic_dec_and_test(&ax->refcnt))
+ up(&ax->dead_sem);
}
-static int ax25_open(struct tty_struct *tty)
+static int mkiss_open(struct tty_struct *tty)
{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+ struct net_device *dev;
+ struct mkiss *ax;
int err;
- /* First make sure we're not already connected. */
- if (ax && ax->magic == AX25_MAGIC)
- return -EEXIST;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
- /* OK. Find a free AX25 channel to use. */
- if ((ax = ax_alloc()) == NULL)
- return -ENFILE;
+ dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+ if (!dev) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ ax = netdev_priv(dev);
+ ax->dev = dev;
+
+ spin_lock_init(&ax->buflock);
+ atomic_set(&ax->refcnt, 1);
+ init_MUTEX_LOCKED(&ax->dead_sem);
ax->tty = tty;
tty->disc_data = ax;
@@ -602,283 +672,212 @@ static int ax25_open(struct tty_struct *tty)
tty->driver->flush_buffer(tty);
/* Restore default settings */
- ax->dev->type = ARPHRD_AX25;
+ dev->type = ARPHRD_AX25;
/* Perform the low-level AX25 initialization. */
- if ((err = ax_open(ax->dev)))
- return err;
+ if ((err = ax_open(ax->dev))) {
+ goto out_free_netdev;
+ }
- /* Done. We have linked the TTY line to a channel. */
- return ax->dev->base_addr;
-}
+ if (register_netdev(dev))
+ goto out_free_buffers;
-static void ax25_close(struct tty_struct *tty)
-{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+ netif_start_queue(dev);
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return;
+ /* Done. We have linked the TTY line to a channel. */
+ return 0;
- unregister_netdev(ax->dev);
+out_free_buffers:
+ kfree(ax->rbuff);
+ kfree(ax->xbuff);
- tty->disc_data = NULL;
- ax->tty = NULL;
+out_free_netdev:
+ free_netdev(dev);
- ax_free(ax);
+out:
+ return err;
}
-
-static struct net_device_stats *ax_get_stats(struct net_device *dev)
+static void mkiss_close(struct tty_struct *tty)
{
- static struct net_device_stats stats;
- struct ax_disp *ax = netdev_priv(dev);
-
- memset(&stats, 0, sizeof(struct net_device_stats));
-
- stats.rx_packets = ax->rx_packets;
- stats.tx_packets = ax->tx_packets;
- stats.rx_bytes = ax->rx_bytes;
- stats.tx_bytes = ax->tx_bytes;
- stats.rx_dropped = ax->rx_dropped;
- stats.tx_dropped = ax->tx_dropped;
- stats.tx_errors = ax->tx_errors;
- stats.rx_errors = ax->rx_errors;
- stats.rx_over_errors = ax->rx_over_errors;
-
- return &stats;
-}
+ struct mkiss *ax;
+ write_lock(&disc_data_lock);
+ ax = tty->disc_data;
+ tty->disc_data = NULL;
+ write_unlock(&disc_data_lock);
-/************************************************************************
- * STANDARD ENCAPSULATION *
- ************************************************************************/
-
-static int kiss_esc(unsigned char *s, unsigned char *d, int len)
-{
- unsigned char *ptr = d;
- unsigned char c;
+ if (ax == 0)
+ return;
/*
- * Send an initial END character to flush out any
- * data that may have accumulated in the receiver
- * due to line noise.
+ * We have now ensured that nobody can start using ap from now on, but
+ * we have to wait for all existing users to finish.
*/
+ if (!atomic_dec_and_test(&ax->refcnt))
+ down(&ax->dead_sem);
- *ptr++ = END;
-
- while (len-- > 0) {
- switch (c = *s++) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
- }
- }
+ unregister_netdev(ax->dev);
- *ptr++ = END;
+ /* Free all AX25 frame buffers. */
+ kfree(ax->rbuff);
+ kfree(ax->xbuff);
- return ptr - d;
+ ax->tty = NULL;
}
-/*
- * MW:
- * OK its ugly, but tell me a better solution without copying the
- * packet to a temporary buffer :-)
- */
-static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc, int len)
+/* Perform I/O control on an active ax25 channel. */
+static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- unsigned char *ptr = d;
- unsigned char c=0;
-
- *ptr++ = END;
- while (len > 0) {
- if (len > 2)
- c = *s++;
- else if (len > 1)
- c = crc >> 8;
- else if (len > 0)
- c = crc & 0xff;
+ struct mkiss *ax = mkiss_get(tty);
+ struct net_device *dev = ax->dev;
+ unsigned int tmp, err;
- len--;
+ /* First make sure we're connected. */
+ if (ax == NULL)
+ return -ENXIO;
- switch (c) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
+ switch (cmd) {
+ case SIOCGIFNAME:
+ err = copy_to_user((void __user *) arg, ax->dev->name,
+ strlen(ax->dev->name) + 1) ? -EFAULT : 0;
+ break;
+
+ case SIOCGIFENCAP:
+ err = put_user(4, (int __user *) arg);
+ break;
+
+ case SIOCSIFENCAP:
+ if (get_user(tmp, (int __user *) arg)) {
+ err = -EFAULT;
+ break;
}
- }
- *ptr++ = END;
- return ptr - d;
-}
-static void kiss_unesc(struct ax_disp *ax, unsigned char s)
-{
- switch (s) {
- case END:
- /* drop keeptest bit = VSV */
- if (test_bit(AXF_KEEPTEST, &ax->flags))
- clear_bit(AXF_KEEPTEST, &ax->flags);
+ ax->mode = tmp;
+ dev->addr_len = AX25_ADDR_LEN;
+ dev->hard_header_len = AX25_KISS_HEADER_LEN +
+ AX25_MAX_HEADER_LEN + 3;
+ dev->type = ARPHRD_AX25;
- if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
- ax_bump(ax);
+ err = 0;
+ break;
- clear_bit(AXF_ESCAPE, &ax->flags);
- ax->rcount = 0;
- return;
+ case SIOCSIFHWADDR: {
+ char addr[AX25_ADDR_LEN];
+printk(KERN_INFO "In SIOCSIFHWADDR");
- case ESC:
- set_bit(AXF_ESCAPE, &ax->flags);
- return;
- case ESC_ESC:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = ESC;
+ if (copy_from_user(&addr,
+ (void __user *) arg, AX25_ADDR_LEN)) {
+ err = -EFAULT;
break;
- case ESC_END:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = END;
- break;
- }
-
- spin_lock_bh(&ax->buflock);
- if (!test_bit(AXF_ERROR, &ax->flags)) {
- if (ax->rcount < ax->buffsize) {
- ax->rbuff[ax->rcount++] = s;
- spin_unlock_bh(&ax->buflock);
- return;
}
- ax->rx_over_errors++;
- set_bit(AXF_ERROR, &ax->flags);
+ spin_lock_irq(&dev->xmit_lock);
+ memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
+ spin_unlock_irq(&dev->xmit_lock);
+
+ err = 0;
+ break;
+ }
+ default:
+ err = -ENOIOCTLCMD;
}
- spin_unlock_bh(&ax->buflock);
-}
+ mkiss_put(ax);
-static int ax_set_mac_address(struct net_device *dev, void __user *addr)
-{
- if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
- return -EFAULT;
- return 0;
+ return err;
}
-static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of data has been received, which can now be decapsulated
+ * and sent on to the AX.25 layer for further processing.
+ */
+static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ char *fp, int count)
{
- struct sockaddr *sa = addr;
-
- memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
+ struct mkiss *ax = mkiss_get(tty);
- return 0;
-}
-
-
-/* Perform I/O control on an active ax25 channel. */
-static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void __user *arg)
-{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
- unsigned int tmp;
+ if (!ax)
+ return;
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return -EINVAL;
+ /*
+ * Argh! mtu change time! - costs us the packet part received
+ * at the change
+ */
+ if (ax->mtu != ax->dev->mtu + 73)
+ ax_changedmtu(ax);
- switch (cmd) {
- case SIOCGIFNAME:
- if (copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1))
- return -EFAULT;
- return 0;
-
- case SIOCGIFENCAP:
- return put_user(4, (int __user *)arg);
-
- case SIOCSIFENCAP:
- if (get_user(tmp, (int __user *)arg))
- return -EFAULT;
- ax->mode = tmp;
- ax->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
- ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
- ax->dev->type = ARPHRD_AX25;
- return 0;
-
- case SIOCSIFHWADDR:
- return ax_set_mac_address(ax->dev, arg);
+ /* Read the characters out of the buffer */
+ while (count--) {
+ if (fp != NULL && *fp++) {
+ if (!test_and_set_bit(AXF_ERROR, &ax->flags))
+ ax->stats.rx_errors++;
+ cp++;
+ continue;
+ }
- default:
- return -ENOIOCTLCMD;
+ kiss_unesc(ax, *cp++);
}
+
+ mkiss_put(ax);
+ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+ && tty->driver->unthrottle)
+ tty->driver->unthrottle(tty);
}
-static int ax_open_dev(struct net_device *dev)
+static int mkiss_receive_room(struct tty_struct *tty)
{
- struct ax_disp *ax = netdev_priv(dev);
-
- if (ax->tty == NULL)
- return -ENODEV;
-
- return 0;
+ return 65536; /* We can handle an infinite amount of data. :-) */
}
-
-/* Initialize the driver. Called by network startup. */
-static int ax25_init(struct net_device *dev)
+/*
+ * Called by the driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ */
+static void mkiss_write_wakeup(struct tty_struct *tty)
{
- struct ax_disp *ax = netdev_priv(dev);
-
- static char ax25_bcast[AX25_ADDR_LEN] =
- {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
- static char ax25_test[AX25_ADDR_LEN] =
- {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
- if (ax == NULL) /* Allocation failed ?? */
- return -ENODEV;
+ struct mkiss *ax = mkiss_get(tty);
+ int actual;
- /* Set up the "AX25 Control Block". (And clear statistics) */
- memset(ax, 0, sizeof (struct ax_disp));
- ax->magic = AX25_MAGIC;
- ax->dev = dev;
+ if (!ax)
+ return;
- /* Finish setting up the DEVICE info. */
- dev->mtu = AX_MTU;
- dev->hard_start_xmit = ax_xmit;
- dev->open = ax_open_dev;
- dev->stop = ax_close;
- dev->get_stats = ax_get_stats;
- dev->set_mac_address = ax_set_dev_mac_address;
- dev->hard_header_len = 0;
- dev->addr_len = 0;
- dev->type = ARPHRD_AX25;
- dev->tx_queue_len = 10;
- dev->hard_header = ax_header;
- dev->rebuild_header = ax_rebuild_header;
+ if (ax->xleft <= 0) {
+ /* Now serial buffer is almost free & we can start
+ * transmission of another packet
+ */
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ netif_wake_queue(ax->dev);
+ goto out;
+ }
- /* New-style flags. */
- dev->flags = IFF_BROADCAST | IFF_MULTICAST;
+ actual = tty->driver->write(tty, ax->xhead, ax->xleft);
+ ax->xleft -= actual;
+ ax->xhead += actual;
- return 0;
+out:
+ mkiss_put(ax);
}
+static struct tty_ldisc ax_ldisc = {
+ .magic = TTY_LDISC_MAGIC,
+ .name = "mkiss",
+ .open = mkiss_open,
+ .close = mkiss_close,
+ .ioctl = mkiss_ioctl,
+ .receive_buf = mkiss_receive_buf,
+ .receive_room = mkiss_receive_room,
+ .write_wakeup = mkiss_write_wakeup
+};
-/* ******************************************************************** */
-/* * Init MKISS driver * */
-/* ******************************************************************** */
+static char banner[] __initdata = KERN_INFO \
+ "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
+static char msg_regfail[] __initdata = KERN_ERR \
+ "mkiss: can't register line discipline (err = %d)\n";
static int __init mkiss_init_driver(void)
{
@@ -886,64 +885,27 @@ static int __init mkiss_init_driver(void)
printk(banner);
- if (ax25_maxdev < 4)
- ax25_maxdev = 4; /* Sanity */
+ if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
+ printk(msg_regfail);
- if ((ax25_ctrls = kmalloc(sizeof(void *) * ax25_maxdev, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array!\n");
- return -ENOMEM;
- }
-
- /* Clear the pointer array, we allocate devices when we need them */
- memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
-
- /* Fill in our line protocol discipline, and register it */
- ax_ldisc.magic = TTY_LDISC_MAGIC;
- ax_ldisc.name = "mkiss";
- ax_ldisc.open = ax25_open;
- ax_ldisc.close = ax25_close;
- ax_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
- unsigned int, unsigned long))ax25_disp_ioctl;
- ax_ldisc.receive_buf = ax25_receive_buf;
- ax_ldisc.receive_room = ax25_receive_room;
- ax_ldisc.write_wakeup = ax25_write_wakeup;
-
- if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) {
- printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
- kfree(ax25_ctrls);
- }
return status;
}
+static const char msg_unregfail[] __exitdata = KERN_ERR \
+ "mkiss: can't unregister line discipline (err = %d)\n";
+
static void __exit mkiss_exit_driver(void)
{
- int i;
-
- for (i = 0; i < ax25_maxdev; i++) {
- if (ax25_ctrls[i]) {
- /*
- * VSV = if dev->start==0, then device
- * unregistered while close proc.
- */
- if (netif_running(&ax25_ctrls[i]->dev))
- unregister_netdev(&ax25_ctrls[i]->dev);
- kfree(ax25_ctrls[i]);
- }
- }
+ int ret;
- kfree(ax25_ctrls);
- ax25_ctrls = NULL;
-
- if ((i = tty_unregister_ldisc(N_AX25)))
- printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
+ if ((ret = tty_unregister_ldisc(N_AX25)))
+ printk(msg_unregfail, ret);
}
-MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
+MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-MODULE_PARM(ax25_maxdev, "i");
-MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
+
module_init(mkiss_init_driver);
module_exit(mkiss_exit_driver);
-
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index c27e417f32bf..6ace0e914fd1 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1557,7 +1557,7 @@ static void scc_net_setup(struct net_device *dev)
dev->stop = scc_net_close;
dev->hard_start_xmit = scc_net_tx;
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_net_set_mac_address;
dev->get_stats = scc_net_get_stats;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 41213ef602dc..fe22479eb202 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -60,15 +60,7 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
@@ -170,7 +162,7 @@ static char ax25_bcast[7] =
static char ax25_test[7] =
{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-static struct timer_list yam_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(yam_timer, NULL, 0, 0);
/* --------------------------------------------------------------------- */
@@ -1116,23 +1108,17 @@ static void yam_setup(struct net_device *dev)
skb_queue_head_init(&yp->send_queue);
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = yam_set_mac_address;
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 256; /* AX25 is the default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
+ dev->type = ARPHRD_AX25;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
+ dev->mtu = AX25_MTU;
+ dev->addr_len = AX25_ADDR_LEN;
+ memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
}
static int __init yam_init_driver(void)
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index c39b0609742a..32d5fabd4b10 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1144,7 +1144,7 @@ static void ibmveth_proc_unregister_driver(void)
static struct vio_device_id ibmveth_device_table[] __devinitdata= {
{ "network", "IBM,l-lan"},
- { 0,}
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, ibmveth_device_table);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 46e0022d3258..6c766fdc51a6 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER;
- urb->transfer_flags = URB_ASYNC_UNLINK;
+ urb->transfer_flags = 0;
/* Irq disabled -> GFP_ATOMIC */
if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
@@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
skb->data, IRDA_SKB_MAX_MTU,
write_bulk_callback, skb);
urb->transfer_buffer_length = skb->len;
- /* Note : unlink *must* be Asynchronous because of the code in
- * irda_usb_net_timeout() -> call in irq - Jean II */
- urb->transfer_flags = URB_ASYNC_UNLINK;
/* This flag (URB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD)
* after each of our packets that is exact multiple of the frame size.
* This is how the dongle will detect the end of packet - Jean II */
- urb->transfer_flags |= URB_ZERO_PACKET;
+ urb->transfer_flags = URB_ZERO_PACKET;
/* Generate min turn time. FIXME: can we do better than this? */
/* Trying to a turnaround time at this level is trying to measure
@@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* in completion handler, because urb->status will
* be -ENOENT. We will fix that at the next watchdog,
* leaving more time to USB to recover...
- * Also, we are in interrupt, so we need to have
- * URB_ASYNC_UNLINK to work properly...
* Jean II */
done = 1;
break;
@@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev)
}
}
/* Cancel Tx and speed URB - need to be synchronous to avoid races */
- self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->tx_urb);
- self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->speed_urb);
/* Stop and remove instance of IrLAP */
@@ -1521,9 +1514,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Toggle flags to make sure it's synchronous. */
- self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->tx_urb);
- self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->speed_urb);
}
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 10125a1dba22..dd89bda1f131 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -4,10 +4,10 @@
* Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Daniele Peri (peri@csai.unipa.it)
- * Created at:
- * Modified at:
- * Modified by:
- *
+ * Created at:
+ * Modified at:
+ * Modified by:
+ *
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
@@ -17,26 +17,26 @@
*
* Copyright (c) 2001 Stefani Seibold
* Copyright (c) 1999-2001 Dag Brattli
- * Copyright (c) 1998-1999 Thomas Davis,
+ * Copyright (c) 1998-1999 Thomas Davis,
*
* and irport.c:
*
* Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
+ *
+ * You 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
*
********************************************************************/
@@ -68,24 +68,42 @@
#include "smsc-ircc2.h"
#include "smsc-sio.h"
+
+MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
+MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
+MODULE_LICENSE("GPL");
+
+static int ircc_dma = 255;
+module_param(ircc_dma, int, 0);
+MODULE_PARM_DESC(ircc_dma, "DMA channel");
+
+static int ircc_irq = 255;
+module_param(ircc_irq, int, 0);
+MODULE_PARM_DESC(ircc_irq, "IRQ line");
+
+static int ircc_fir;
+module_param(ircc_fir, int, 0);
+MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
+
+static int ircc_sir;
+module_param(ircc_sir, int, 0);
+MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
+
+static int ircc_cfg;
+module_param(ircc_cfg, int, 0);
+MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
+
+static int ircc_transceiver;
+module_param(ircc_transceiver, int, 0);
+MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
+
/* Types */
struct smsc_transceiver {
char *name;
- void (*set_for_speed)(int fir_base, u32 speed);
+ void (*set_for_speed)(int fir_base, u32 speed);
int (*probe)(int fir_base);
};
-typedef struct smsc_transceiver smsc_transceiver_t;
-
-#if 0
-struct smc_chip {
- char *name;
- u16 flags;
- u8 devid;
- u8 rev;
-};
-typedef struct smc_chip smc_chip_t;
-#endif
struct smsc_chip {
char *name;
@@ -96,20 +114,18 @@ struct smsc_chip {
u8 devid;
u8 rev;
};
-typedef struct smsc_chip smsc_chip_t;
struct smsc_chip_address {
unsigned int cfg_base;
unsigned int type;
};
-typedef struct smsc_chip_address smsc_chip_address_t;
/* Private data for each instance */
struct smsc_ircc_cb {
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
-
+
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
@@ -119,7 +135,7 @@ struct smsc_ircc_cb {
struct qos_info qos; /* QoS capabilities for this device */
spinlock_t lock; /* For serializing operations */
-
+
__u32 new_speed;
__u32 flags; /* Interface flags */
@@ -127,18 +143,20 @@ struct smsc_ircc_cb {
int tx_len; /* Number of frames in tx_buff */
int transceiver;
- struct pm_dev *pmdev;
+ struct platform_device *pldev;
};
/* Constants */
-static const char *driver_name = "smsc-ircc2";
-#define DIM(x) (sizeof(x)/(sizeof(*(x))))
+#define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2"
+
#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600
#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1
-#define SMSC_IRCC2_C_NET_TIMEOUT 0
+#define SMSC_IRCC2_C_NET_TIMEOUT 0
#define SMSC_IRCC2_C_SIR_STOP 0
+static const char *driver_name = SMSC_IRCC2_DRIVER_NAME;
+
/* Prototypes */
static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
@@ -147,15 +165,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base,
static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
-static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase);
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase);
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self);
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self);
static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self);
static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs);
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase);
-static void smsc_ircc_change_speed(void *priv, u32 speed);
-static void smsc_ircc_set_sir_speed(void *priv, u32 speed);
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs);
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self);
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed);
+static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed);
static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev);
static void smsc_ircc_sir_start(struct smsc_ircc_cb *self);
@@ -171,7 +189,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm
static void smsc_ircc_timeout(struct net_device *dev);
#endif
static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
@@ -179,9 +196,9 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self);
/* Probing */
static int __init smsc_ircc_look_for_chips(void);
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type);
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type);
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
+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);
@@ -196,21 +213,26 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
/* Power Management */
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self);
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self);
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
+static int smsc_ircc_resume(struct device *dev, u32 level);
+static struct device_driver smsc_ircc_driver = {
+ .name = SMSC_IRCC2_DRIVER_NAME,
+ .bus = &platform_bus_type,
+ .suspend = smsc_ircc_suspend,
+ .resume = smsc_ircc_resume,
+};
/* Transceivers for SMSC-ircc */
-static smsc_transceiver_t smsc_transceivers[]=
+static struct smsc_transceiver smsc_transceivers[] =
{
- { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
- { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
- { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc},
- { NULL, NULL}
+ { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800 },
+ { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select },
+ { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc },
+ { NULL, NULL }
};
-#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1)
+#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (ARRAY_SIZE(smsc_transceivers) - 1)
/* SMC SuperIO chipsets definitions */
@@ -221,7 +243,7 @@ static smsc_transceiver_t smsc_transceivers[]=
#define FIR 4 /* SuperIO Chip has fast IRDA */
#define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
-static smsc_chip_t __initdata fdc_chips_flat[]=
+static struct smsc_chip __initdata fdc_chips_flat[] =
{
/* Base address 0x3f0 or 0x370 */
{ "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip cannot be detected */
@@ -235,7 +257,7 @@ static smsc_chip_t __initdata fdc_chips_flat[]=
{ NULL }
};
-static smsc_chip_t __initdata fdc_chips_paged[]=
+static struct smsc_chip __initdata fdc_chips_paged[] =
{
/* Base address 0x3f0 or 0x370 */
{ "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 },
@@ -254,7 +276,7 @@ static smsc_chip_t __initdata fdc_chips_paged[]=
{ NULL }
};
-static smsc_chip_t __initdata lpc_chips_flat[]=
+static struct smsc_chip __initdata lpc_chips_flat[] =
{
/* Base address 0x2E or 0x4E */
{ "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 },
@@ -262,7 +284,7 @@ static smsc_chip_t __initdata lpc_chips_flat[]=
{ NULL }
};
-static smsc_chip_t __initdata lpc_chips_paged[]=
+static struct smsc_chip __initdata lpc_chips_paged[] =
{
/* Base address 0x2E or 0x4E */
{ "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 },
@@ -281,33 +303,25 @@ static smsc_chip_t __initdata lpc_chips_paged[]=
#define SMSCSIO_TYPE_FLAT 4
#define SMSCSIO_TYPE_PAGED 8
-static smsc_chip_address_t __initdata possible_addresses[]=
+static struct smsc_chip_address __initdata possible_addresses[] =
{
- {0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0,0}
+ { 0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0, 0 }
};
/* Globals */
-static struct smsc_ircc_cb *dev_self[] = { NULL, NULL};
-
-static int ircc_irq=255;
-static int ircc_dma=255;
-static int ircc_fir=0;
-static int ircc_sir=0;
-static int ircc_cfg=0;
-static int ircc_transceiver=0;
-
-static unsigned short dev_count=0;
+static struct smsc_ircc_cb *dev_self[] = { NULL, NULL };
+static unsigned short dev_count;
static inline void register_bank(int iobase, int bank)
{
- outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
- iobase+IRCC_MASTER);
+ outb(((inb(iobase + IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+ iobase + IRCC_MASTER);
}
@@ -327,34 +341,44 @@ static inline void register_bank(int iobase, int bank)
*/
static int __init smsc_ircc_init(void)
{
- int ret=-ENODEV;
+ int ret;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- dev_count=0;
-
- if ((ircc_fir>0)&&(ircc_sir>0)) {
+ ret = driver_register(&smsc_ircc_driver);
+ if (ret) {
+ IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+ return ret;
+ }
+
+ dev_count = 0;
+
+ if (ircc_fir > 0 && ircc_sir > 0) {
IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
- if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0)
- return 0;
-
- return -ENODEV;
- }
+ if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
+ ret = -ENODEV;
+ } else {
+ ret = -ENODEV;
+
+ /* try user provided configuration register base address */
+ if (ircc_cfg > 0) {
+ IRDA_MESSAGE(" Overriding configuration address "
+ "0x%04x\n", ircc_cfg);
+ if (!smsc_superio_fdc(ircc_cfg))
+ ret = 0;
+ if (!smsc_superio_lpc(ircc_cfg))
+ ret = 0;
+ }
- /* try user provided configuration register base address */
- if (ircc_cfg>0) {
- IRDA_MESSAGE(" Overriding configuration address 0x%04x\n",
- ircc_cfg);
- if (!smsc_superio_fdc(ircc_cfg))
- ret = 0;
- if (!smsc_superio_lpc(ircc_cfg))
+ if (smsc_ircc_look_for_chips() > 0)
ret = 0;
}
-
- if(smsc_ircc_look_for_chips()>0) ret = 0;
-
+
+ if (ret)
+ driver_unregister(&smsc_ircc_driver);
+
return ret;
}
@@ -369,15 +393,15 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
struct smsc_ircc_cb *self;
struct net_device *dev;
int err;
-
+
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
err = smsc_ircc_present(fir_base, sir_base);
- if(err)
+ if (err)
goto err_out;
-
+
err = -ENOMEM;
- if (dev_count > DIM(dev_self)) {
+ if (dev_count >= ARRAY_SIZE(dev_self)) {
IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__);
goto err_out1;
}
@@ -396,14 +420,14 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
#if SMSC_IRCC2_C_NET_TIMEOUT
dev->tx_timeout = smsc_ircc_timeout;
- dev->watchdog_timeo = HZ*2; /* Allow enough time for speed change */
+ dev->watchdog_timeo = HZ * 2; /* Allow enough time for speed change */
#endif
dev->open = smsc_ircc_net_open;
dev->stop = smsc_ircc_net_close;
dev->do_ioctl = smsc_ircc_net_ioctl;
dev->get_stats = smsc_ircc_net_get_stats;
-
- self = dev->priv;
+
+ self = netdev_priv(dev);
self->netdev = dev;
/* Make ifconfig display some details */
@@ -411,10 +435,10 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->irq = self->io.irq = irq;
/* Need to store self somewhere */
- dev_self[dev_count++] = self;
+ dev_self[dev_count] = self;
spin_lock_init(&self->lock);
- self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
+ self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
self->rx_buff.head =
@@ -442,33 +466,40 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
self->rx_buff.state = OUTSIDE_FRAME;
self->tx_buff.data = self->tx_buff.head;
self->rx_buff.data = self->rx_buff.head;
-
- smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
+ smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
smsc_ircc_setup_qos(self);
-
smsc_ircc_init_chip(self);
-
- if(ircc_transceiver > 0 &&
- ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
+
+ if (ircc_transceiver > 0 &&
+ ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
self->transceiver = ircc_transceiver;
else
smsc_ircc_probe_transceiver(self);
err = register_netdev(self->netdev);
- if(err) {
+ if (err) {
IRDA_ERROR("%s, Network device registration failed!\n",
driver_name);
goto err_out4;
}
- self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
- if (self->pmdev)
- self->pmdev->data = self;
+ self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME,
+ dev_count, NULL, 0);
+ if (IS_ERR(self->pldev)) {
+ err = PTR_ERR(self->pldev);
+ goto err_out5;
+ }
+ dev_set_drvdata(&self->pldev->dev, self);
IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
+ dev_count++;
return 0;
+
+ err_out5:
+ unregister_netdev(self->netdev);
+
err_out4:
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
@@ -477,7 +508,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
self->rx_buff.head, self->rx_buff_dma);
err_out2:
free_netdev(self->netdev);
- dev_self[--dev_count] = NULL;
+ dev_self[dev_count] = NULL;
err_out1:
release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
@@ -511,16 +542,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
register_bank(fir_base, 3);
- high = inb(fir_base+IRCC_ID_HIGH);
- low = inb(fir_base+IRCC_ID_LOW);
- chip = inb(fir_base+IRCC_CHIP_ID);
- version = inb(fir_base+IRCC_VERSION);
- config = inb(fir_base+IRCC_INTERFACE);
+ high = inb(fir_base + IRCC_ID_HIGH);
+ low = inb(fir_base + IRCC_ID_LOW);
+ chip = inb(fir_base + IRCC_CHIP_ID);
+ version = inb(fir_base + IRCC_VERSION);
+ config = inb(fir_base + IRCC_INTERFACE);
dma = config & IRCC_INTERFACE_DMA_MASK;
irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
- if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
- IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
+ if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
+ IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
__FUNCTION__, fir_base);
goto out3;
}
@@ -529,6 +560,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
chip & 0x0f, version, fir_base, sir_base, dma, irq);
return 0;
+
out3:
release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
out2:
@@ -543,16 +575,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
* Setup I/O
*
*/
-static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
- unsigned int fir_base, unsigned int sir_base,
+static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
+ unsigned int fir_base, unsigned int sir_base,
u8 dma, u8 irq)
{
unsigned char config, chip_dma, chip_irq;
register_bank(fir_base, 3);
- config = inb(fir_base+IRCC_INTERFACE);
- chip_dma = config & IRCC_INTERFACE_DMA_MASK;
- chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
+ config = inb(fir_base + IRCC_INTERFACE);
+ chip_dma = config & IRCC_INTERFACE_DMA_MASK;
+ chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
self->io.fir_base = fir_base;
self->io.sir_base = sir_base;
@@ -566,17 +598,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
driver_name, chip_irq, irq);
self->io.irq = irq;
- }
- else
+ } else
self->io.irq = chip_irq;
-
+
if (dma < 255) {
if (dma != chip_dma)
IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
driver_name, chip_dma, dma);
self->io.dma = dma;
- }
- else
+ } else
self->io.dma = chip_dma;
}
@@ -591,7 +621,7 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
{
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
-
+
self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
@@ -608,43 +638,43 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
*/
static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
{
- int iobase, ir_mode, ctrl, fast;
-
- IRDA_ASSERT( self != NULL, return; );
- iobase = self->io.fir_base;
+ int iobase, ir_mode, ctrl, fast;
+
+ IRDA_ASSERT(self != NULL, return;);
+ iobase = self->io.fir_base;
ir_mode = IRCC_CFGA_IRDA_SIR_A;
ctrl = 0;
fast = 0;
register_bank(iobase, 0);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
+ outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
register_bank(iobase, 1);
- outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode),
- iobase+IRCC_SCE_CFGA);
+ outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode),
+ iobase + IRCC_SCE_CFGA);
#ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
- iobase+IRCC_SCE_CFGB);
-#else
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
- iobase+IRCC_SCE_CFGB);
-#endif
- (void) inb(iobase+IRCC_FIFO_THRESHOLD);
- outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase+IRCC_FIFO_THRESHOLD);
-
+ outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ iobase + IRCC_SCE_CFGB);
+#else
+ outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ iobase + IRCC_SCE_CFGB);
+#endif
+ (void) inb(iobase + IRCC_FIFO_THRESHOLD);
+ outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD);
+
register_bank(iobase, 4);
- outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
-
+ outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL);
+
register_bank(iobase, 0);
- outb(fast, iobase+IRCC_LCR_A);
+ outb(fast, iobase + IRCC_LCR_A);
smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
-
+
/* Power on device */
- outb(0x00, iobase+IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
}
/*
@@ -662,12 +692,12 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
-
+
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
@@ -703,14 +733,14 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
default:
ret = -EOPNOTSUPP;
}
-
+
return ret;
}
static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) dev->priv;
-
+ struct smsc_ircc_cb *self = netdev_priv(dev);
+
return &self->stats;
}
@@ -724,11 +754,9 @@ static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
static void smsc_ircc_timeout(struct net_device *dev)
{
- struct smsc_ircc_cb *self;
+ struct smsc_ircc_cb *self = netdev_priv(dev);
unsigned long flags;
- self = (struct smsc_ircc_cb *) dev->priv;
-
IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n",
dev->name, self->io.speed);
spin_lock_irqsave(&self->lock, flags);
@@ -751,26 +779,23 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
{
struct smsc_ircc_cb *self;
unsigned long flags;
- int iobase;
s32 speed;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
IRDA_ASSERT(dev != NULL, return 0;);
-
- self = (struct smsc_ircc_cb *) dev->priv;
- IRDA_ASSERT(self != NULL, return 0;);
- iobase = self->io.sir_base;
+ self = netdev_priv(dev);
+ IRDA_ASSERT(self != NULL, return 0;);
netif_stop_queue(dev);
-
+
/* Make sure test of self->io.speed & speed change are atomic */
spin_lock_irqsave(&self->lock, flags);
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
+ if (speed != self->io.speed && speed != -1) {
/* Check for empty frame */
if (!skb->len) {
/*
@@ -787,27 +812,26 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
- } else {
- self->new_speed = speed;
}
+ self->new_speed = speed;
}
/* Init tx buffer */
self->tx_buff.data = self->tx_buff.head;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
- self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
-
+
self->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
- outb(UART_IER_THRI, iobase+UART_IER);
+ outb(UART_IER_THRI, self->io.sir_base + UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
-
+
return 0;
}
@@ -826,9 +850,9 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
self->io.speed = speed;
- switch(speed) {
+ switch (speed) {
default:
- case 576000:
+ case 576000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
ctrl = IRCC_CRC;
fast = 0;
@@ -853,14 +877,14 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
Now in tranceiver!
/* This causes an interrupt */
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast, fir_base + IRCC_LCR_A);
#endif
-
+
register_bank(fir_base, 1);
- outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base+IRCC_SCE_CFGA);
-
+ outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA);
+
register_bank(fir_base, 4);
- outb((inb(fir_base+IRCC_CONTROL) & 0x30) | ctrl, fir_base+IRCC_CONTROL);
+ outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL);
}
/*
@@ -885,31 +909,31 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self)
/* Reset everything */
/* Install FIR transmit handler */
- dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;
+ dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;
/* Clear FIFO */
- outb(inb(fir_base+IRCC_LCR_A)|IRCC_LCR_A_FIFO_RESET, fir_base+IRCC_LCR_A);
+ outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A);
/* Enable interrupt */
- /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/
+ /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/
register_bank(fir_base, 1);
- /* Select the TX/RX interface */
+ /* Select the TX/RX interface */
#ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */
- outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
- fir_base+IRCC_SCE_CFGB);
-#else
- outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
- fir_base+IRCC_SCE_CFGB);
-#endif
- (void) inb(fir_base+IRCC_FIFO_THRESHOLD);
+ outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ fir_base + IRCC_SCE_CFGB);
+#else
+ outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ fir_base + IRCC_SCE_CFGB);
+#endif
+ (void) inb(fir_base + IRCC_FIFO_THRESHOLD);
/* Enable SCE interrupts */
- outb(0, fir_base+IRCC_MASTER);
+ outb(0, fir_base + IRCC_MASTER);
register_bank(fir_base, 0);
- outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, fir_base+IRCC_MASTER);
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER);
}
/*
@@ -923,13 +947,13 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
int fir_base;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(self != NULL, return;);
fir_base = self->io.fir_base;
register_bank(fir_base, 0);
- /*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/
- outb(inb(fir_base+IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base+IRCC_LCR_B);
+ /*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/
+ outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B);
}
@@ -941,18 +965,15 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
* This function *must* be called with spinlock held, because it may
* be called from the irq handler. - Jean II
*/
-static void smsc_ircc_change_speed(void *priv, u32 speed)
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
struct net_device *dev;
- int iobase;
int last_speed_was_sir;
-
+
IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);
IRDA_ASSERT(self != NULL, return;);
dev = self->netdev;
- iobase = self->io.fir_base;
last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED;
@@ -961,30 +982,30 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
speed= 1152000;
self->io.speed = speed;
last_speed_was_sir = 0;
- smsc_ircc_fir_start(self);
+ smsc_ircc_fir_start(self);
#endif
-
- if(self->io.speed == 0)
+
+ if (self->io.speed == 0)
smsc_ircc_sir_start(self);
#if 0
- if(!last_speed_was_sir) speed = self->io.speed;
+ if (!last_speed_was_sir) speed = self->io.speed;
#endif
- if(self->io.speed != speed) smsc_ircc_set_transceiver_for_speed(self, speed);
+ if (self->io.speed != speed)
+ smsc_ircc_set_transceiver_for_speed(self, speed);
self->io.speed = speed;
-
- if(speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
- if(!last_speed_was_sir) {
+
+ if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+ if (!last_speed_was_sir) {
smsc_ircc_fir_stop(self);
smsc_ircc_sir_start(self);
}
- smsc_ircc_set_sir_speed(self, speed);
- }
- else {
- if(last_speed_was_sir) {
- #if SMSC_IRCC2_C_SIR_STOP
+ smsc_ircc_set_sir_speed(self, speed);
+ } else {
+ if (last_speed_was_sir) {
+ #if SMSC_IRCC2_C_SIR_STOP
smsc_ircc_sir_stop(self);
#endif
smsc_ircc_fir_start(self);
@@ -994,13 +1015,13 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
#if 0
self->tx_buff.len = 10;
self->tx_buff.data = self->tx_buff.head;
-
- smsc_ircc_dma_xmit(self, iobase, 4000);
+
+ smsc_ircc_dma_xmit(self, 4000);
#endif
/* Be ready for incoming frames */
- smsc_ircc_dma_receive(self, iobase);
+ smsc_ircc_dma_receive(self);
}
-
+
netif_wake_queue(dev);
}
@@ -1010,10 +1031,9 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
* Set speed of IrDA port to specified baudrate
*
*/
-void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
+void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
- int iobase;
+ int iobase;
int fcr; /* FIFO control reg */
int lcr; /* Line control reg */
int divisor;
@@ -1022,38 +1042,36 @@ void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
-
+
/* Update accounting for new speed */
self->io.speed = speed;
/* Turn off interrupts */
- outb(0, iobase+UART_IER);
+ outb(0, iobase + UART_IER);
+
+ divisor = SMSC_IRCC2_MAX_SIR_SPEED / speed;
- divisor = SMSC_IRCC2_MAX_SIR_SPEED/speed;
-
fcr = UART_FCR_ENABLE_FIFO;
- /*
+ /*
* Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
- * about this timeout since it will always be fast enough.
+ * about this timeout since it will always be fast enough.
*/
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
-
+ fcr |= self->io.speed < 38400 ?
+ UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
+
/* IrDA ports use 8N1 */
lcr = UART_LCR_WLEN8;
-
- outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
- outb(divisor & 0xff, iobase+UART_DLL); /* Set speed */
- outb(divisor >> 8, iobase+UART_DLM);
- outb(lcr, iobase+UART_LCR); /* Set 8N1 */
- outb(fcr, iobase+UART_FCR); /* Enable FIFO's */
+
+ outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */
+ outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */
+ outb(divisor >> 8, iobase + UART_DLM);
+ outb(lcr, iobase + UART_LCR); /* Set 8N1 */
+ outb(fcr, iobase + UART_FCR); /* Enable FIFO's */
/* Turn on interrups */
- outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed);
}
@@ -1070,15 +1088,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
struct smsc_ircc_cb *self;
unsigned long flags;
s32 speed;
- int iobase;
int mtt;
IRDA_ASSERT(dev != NULL, return 0;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
- iobase = self->io.fir_base;
-
netif_stop_queue(dev);
/* Make sure test of self->io.speed & speed change are atomic */
@@ -1086,30 +1101,31 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
/* Check if we need to change the speed after this frame */
speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
+ if (speed != self->io.speed && speed != -1) {
/* Check for empty frame */
if (!skb->len) {
/* Note : you should make sure that speed changes
* are not going to corrupt any outgoing frame.
* Look at nsc-ircc for the gory details - Jean II */
- smsc_ircc_change_speed(self, speed);
+ smsc_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
- } else
- self->new_speed = speed;
+ }
+
+ self->new_speed = speed;
}
-
+
memcpy(self->tx_buff.head, skb->data, skb->len);
self->tx_buff.len = skb->len;
self->tx_buff.data = self->tx_buff.head;
-
- mtt = irda_get_mtt(skb);
+
+ mtt = irda_get_mtt(skb);
if (mtt) {
int bofs;
- /*
+ /*
* Compute how many BOFs (STA or PA's) we need to waste the
* min turn time given the speed of the link.
*/
@@ -1117,11 +1133,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
if (bofs > 4095)
bofs = 4095;
- smsc_ircc_dma_xmit(self, iobase, bofs);
+ smsc_ircc_dma_xmit(self, bofs);
} else {
/* Transmit frame */
- smsc_ircc_dma_xmit(self, iobase, 0);
+ smsc_ircc_dma_xmit(self, 0);
}
+
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
@@ -1129,43 +1146,44 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
}
/*
- * Function smsc_ircc_dma_xmit (self, iobase)
+ * Function smsc_ircc_dma_xmit (self, bofs)
*
* Transmit data using DMA
*
*/
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs)
{
+ int iobase = self->io.fir_base;
u8 ctrl;
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 1
/* Disable Rx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
self->io.direction = IO_XMIT;
/* Set BOF additional count for generating the min turn time */
register_bank(iobase, 4);
- outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
- ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
- outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+ outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO);
+ ctrl = inb(iobase + IRCC_CONTROL) & 0xf0;
+ outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI);
/* Set max Tx frame size */
- outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
- outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
+ outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI);
+ outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO);
/*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/
-
+
/* Enable burst mode chip Tx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
/* Setup DMA controller (must be done after enabling chip DMA) */
irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
@@ -1174,50 +1192,52 @@ static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
/* Enable interrupt */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
+
/* Enable transmit */
- outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
+ outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase + IRCC_LCR_B);
}
/*
* Function smsc_ircc_dma_xmit_complete (self)
*
- * The transfer of a frame in finished. This function will only be called
+ * The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self)
{
+ int iobase = self->io.fir_base;
+
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 0
/* Disable Tx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
- register_bank(self->io.fir_base, 1);
- outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- self->io.fir_base+IRCC_SCE_CFGB);
+ register_bank(iobase, 1);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
/* Check for underrun! */
register_bank(iobase, 0);
- if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
+ if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) {
self->stats.tx_errors++;
self->stats.tx_fifo_errors++;
/* Reset error condition */
register_bank(iobase, 0);
- outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
+ outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
} else {
self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
+ self->stats.tx_bytes += self->tx_buff.len;
}
/* Check if it's time to change the speed */
if (self->new_speed) {
- smsc_ircc_change_speed(self, self->new_speed);
+ smsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -1231,31 +1251,32 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
* if it starts to receive a frame.
*
*/
-static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase)
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self)
{
+ int iobase = self->io.fir_base;
#if 0
/* Turn off chip DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
#endif
-
+
/* Disable Tx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
/* Turn off chip DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
/* Set max Rx frame size */
register_bank(iobase, 4);
- outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
- outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+ outb((2050 >> 8) & 0x0f, iobase + IRCC_RX_SIZE_HI);
+ outb(2050 & 0xff, iobase + IRCC_RX_SIZE_LO);
/* Setup DMA controller */
irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
@@ -1263,83 +1284,83 @@ static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase)
/* Enable burst mode chip Rx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
/* Enable interrupt */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
/* Enable receiver */
register_bank(iobase, 0);
- outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
- iobase+IRCC_LCR_B);
-
+ outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
+ iobase + IRCC_LCR_B);
+
return 0;
}
/*
- * Function smsc_ircc_dma_receive_complete(self, iobase)
+ * Function smsc_ircc_dma_receive_complete(self)
*
* Finished with receiving frames
*
*/
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
{
struct sk_buff *skb;
int len, msgcnt, lsr;
-
+ int iobase = self->io.fir_base;
+
register_bank(iobase, 0);
-
+
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 0
/* Disable Rx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
register_bank(iobase, 0);
- outb(inb(iobase+IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase+IRCC_LSAR);
- lsr= inb(iobase+IRCC_LSR);
- msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
+ outb(inb(iobase + IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase + IRCC_LSAR);
+ lsr= inb(iobase + IRCC_LSR);
+ msgcnt = inb(iobase + IRCC_LCR_B) & 0x08;
IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__,
get_dma_residue(self->io.dma));
len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
- /* Look for errors
- */
-
- if(lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
+ /* Look for errors */
+ if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
self->stats.rx_errors++;
- if(lsr & IRCC_LSR_FRAME_ERROR) self->stats.rx_frame_errors++;
- if(lsr & IRCC_LSR_CRC_ERROR) self->stats.rx_crc_errors++;
- if(lsr & IRCC_LSR_SIZE_ERROR) self->stats.rx_length_errors++;
- if(lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) self->stats.rx_length_errors++;
+ if (lsr & IRCC_LSR_FRAME_ERROR)
+ self->stats.rx_frame_errors++;
+ if (lsr & IRCC_LSR_CRC_ERROR)
+ self->stats.rx_crc_errors++;
+ if (lsr & IRCC_LSR_SIZE_ERROR)
+ self->stats.rx_length_errors++;
+ if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN))
+ self->stats.rx_length_errors++;
return;
}
+
/* Remove CRC */
- if (self->io.speed < 4000000)
- len -= 2;
- else
- len -= 4;
+ len -= self->io.speed < 4000000 ? 2 : 4;
- if ((len < 2) || (len > 2050)) {
+ if (len < 2 || len > 2050) {
IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
return;
}
IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len);
- skb = dev_alloc_skb(len+1);
- if (!skb) {
+ skb = dev_alloc_skb(len + 1);
+ if (!skb) {
IRDA_WARNING("%s(), memory squeeze, dropping frame.\n",
__FUNCTION__);
return;
- }
+ }
/* Make sure IP header gets aligned */
- skb_reserve(skb, 1);
+ skb_reserve(skb, 1);
memcpy(skb_put(skb, len), self->rx_buff.data, len);
self->stats.rx_packets++;
@@ -1357,7 +1378,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase
* Receive one frame from the infrared port
*
*/
-static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
+static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
{
int boguscount = 0;
int iobase;
@@ -1366,20 +1387,20 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
iobase = self->io.sir_base;
- /*
- * Receive all characters in Rx FIFO, unwrap and unstuff them.
- * async_unwrap_char will deliver all found frames
+ /*
+ * Receive all characters in Rx FIFO, unwrap and unstuff them.
+ * async_unwrap_char will deliver all found frames
*/
do {
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
- inb(iobase+UART_RX));
+ async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ inb(iobase + UART_RX));
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__);
break;
}
- } while (inb(iobase+UART_LSR) & UART_LSR_DR);
+ } while (inb(iobase + UART_LSR) & UART_LSR_DR);
}
@@ -1397,18 +1418,19 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
irqreturn_t ret = IRQ_NONE;
if (dev == NULL) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
goto irq_ret;
}
- self = (struct smsc_ircc_cb *) dev->priv;
+
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return IRQ_NONE;);
/* Serialise the interrupt handler in various CPUs, stop Tx path */
- spin_lock(&self->lock);
+ spin_lock(&self->lock);
/* Check if we should use the SIR interrupt handler */
- if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+ if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
ret = smsc_ircc_interrupt_sir(dev);
goto irq_ret_unlock;
}
@@ -1416,25 +1438,25 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
iobase = self->io.fir_base;
register_bank(iobase, 0);
- iir = inb(iobase+IRCC_IIR);
- if (iir == 0)
+ iir = inb(iobase + IRCC_IIR);
+ if (iir == 0)
goto irq_ret_unlock;
ret = IRQ_HANDLED;
/* Disable interrupts */
- outb(0, iobase+IRCC_IER);
- lcra = inb(iobase+IRCC_LCR_A);
- lsr = inb(iobase+IRCC_LSR);
-
+ outb(0, iobase + IRCC_IER);
+ lcra = inb(iobase + IRCC_LCR_A);
+ lsr = inb(iobase + IRCC_LSR);
+
IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir);
if (iir & IRCC_IIR_EOM) {
if (self->io.direction == IO_RECV)
- smsc_ircc_dma_receive_complete(self, iobase);
+ smsc_ircc_dma_receive_complete(self);
else
- smsc_ircc_dma_xmit_complete(self, iobase);
-
- smsc_ircc_dma_receive(self, iobase);
+ smsc_ircc_dma_xmit_complete(self);
+
+ smsc_ircc_dma_receive(self);
}
if (iir & IRCC_IIR_ACTIVE_FRAME) {
@@ -1444,7 +1466,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
/* Enable interrupts again */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
irq_ret_unlock:
spin_unlock(&self->lock);
@@ -1459,7 +1481,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
*/
static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
{
- struct smsc_ircc_cb *self = dev->priv;
+ struct smsc_ircc_cb *self = netdev_priv(dev);
int boguscount = 0;
int iobase;
int iir, lsr;
@@ -1469,14 +1491,14 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
iobase = self->io.sir_base;
- iir = inb(iobase+UART_IIR) & UART_IIR_ID;
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
if (iir == 0)
return IRQ_NONE;
while (iir) {
/* Clear interrupt */
- lsr = inb(iobase+UART_LSR);
+ lsr = inb(iobase + UART_LSR);
- IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
__FUNCTION__, iir, lsr, iobase);
switch (iir) {
@@ -1496,13 +1518,13 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n",
__FUNCTION__, iir);
break;
- }
-
+ }
+
/* Make sure we don't stay here to long */
if (boguscount++ > 100)
break;
- iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
}
/*spin_unlock(&self->lock);*/
return IRQ_HANDLED;
@@ -1529,7 +1551,7 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
get_dma_residue(self->io.dma));
status = (self->rx_buff.state != OUTSIDE_FRAME);
-
+
return status;
}
#endif /* unused */
@@ -1544,19 +1566,16 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
static int smsc_ircc_net_open(struct net_device *dev)
{
struct smsc_ircc_cb *self;
- int iobase;
char hwname[16];
unsigned long flags;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
-
- iobase = self->io.fir_base;
- if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
+ if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
(void *) dev)) {
IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
__FUNCTION__, self->io.irq);
@@ -1568,14 +1587,14 @@ static int smsc_ircc_net_open(struct net_device *dev)
self->io.speed = 0;
smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
spin_unlock_irqrestore(&self->lock, flags);
-
+
/* Give self a hardware name */
/* It would be cool to offer the chip revision here - Jean II */
sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base);
- /*
+ /*
* Open new IrLAP layer instance, now that everything should be
- * initialized properly
+ * initialized properly
*/
self->irlap = irlap_open(dev, &self->qos, hwname);
@@ -1590,7 +1609,7 @@ static int smsc_ircc_net_open(struct net_device *dev)
__FUNCTION__, self->io.dma);
return -EAGAIN;
}
-
+
netif_start_queue(dev);
return 0;
@@ -1605,73 +1624,53 @@ static int smsc_ircc_net_open(struct net_device *dev)
static int smsc_ircc_net_close(struct net_device *dev)
{
struct smsc_ircc_cb *self;
- int iobase;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
-
- iobase = self->io.fir_base;
/* Stop device */
netif_stop_queue(dev);
-
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
self->irlap = NULL;
free_irq(self->io.irq, dev);
-
disable_dma(self->io.dma);
-
free_dma(self->io.dma);
return 0;
}
-
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
{
- IRDA_MESSAGE("%s, Suspending\n", driver_name);
+ struct smsc_ircc_cb *self = dev_get_drvdata(dev);
- if (self->io.suspended)
- return;
+ IRDA_MESSAGE("%s, Suspending\n", driver_name);
- smsc_ircc_net_close(self->netdev);
+ if (level == SUSPEND_DISABLE && !self->io.suspended) {
+ smsc_ircc_net_close(self->netdev);
+ self->io.suspended = 1;
+ }
- self->io.suspended = 1;
+ return 0;
}
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self)
+static int smsc_ircc_resume(struct device *dev, u32 level)
{
- if (!self->io.suspended)
- return;
+ struct smsc_ircc_cb *self = dev_get_drvdata(dev);
- /* The code was doing a "cli()" here, but this can't be right.
- * If you need protection, do it in net_open with a spinlock
- * or give a good reason. - Jean II */
+ if (level == RESUME_ENABLE && self->io.suspended) {
- smsc_ircc_net_open(self->netdev);
-
- IRDA_MESSAGE("%s, Waking up\n", driver_name);
-}
+ smsc_ircc_net_open(self->netdev);
+ self->io.suspended = 0;
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data;
- if (self) {
- switch (rqst) {
- case PM_SUSPEND:
- smsc_ircc_suspend(self);
- break;
- case PM_RESUME:
- smsc_ircc_wakeup(self);
- break;
- }
- }
+ IRDA_MESSAGE("%s, Waking up\n", driver_name);
+ }
return 0;
}
@@ -1690,10 +1689,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
IRDA_ASSERT(self != NULL, return -1;);
- iobase = self->io.fir_base;
-
- if (self->pmdev)
- pm_unregister(self->pmdev);
+ platform_device_unregister(self->pldev);
/* Remove netdevice */
unregister_netdev(self->netdev);
@@ -1702,15 +1698,16 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
spin_lock_irqsave(&self->lock, flags);
/* Stop interrupts */
+ iobase = self->io.fir_base;
register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
+ outb(0, iobase + IRCC_IER);
+ outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
#if 0
/* Reset to SIR mode */
register_bank(iobase, 1);
- outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
- outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
+ outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA);
+ outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB);
#endif
spin_unlock_irqrestore(&self->lock, flags);
@@ -1720,7 +1717,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
release_region(self->io.fir_base, self->io.fir_ext);
- IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
+ IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
self->io.sir_base);
release_region(self->io.sir_base, self->io.sir_ext);
@@ -1728,7 +1725,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
if (self->tx_buff.head)
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
-
+
if (self->rx_buff.head)
dma_free_coherent(NULL, self->rx_buff.truesize,
self->rx_buff.head, self->rx_buff_dma);
@@ -1744,10 +1741,12 @@ static void __exit smsc_ircc_cleanup(void)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- for (i=0; i < 2; i++) {
+ for (i = 0; i < 2; i++) {
if (dev_self[i])
smsc_ircc_close(dev_self[i]);
}
+
+ driver_unregister(&smsc_ircc_driver);
}
/*
@@ -1763,34 +1762,34 @@ void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
- IRDA_ASSERT(self != NULL, return;);
- dev= self->netdev;
- IRDA_ASSERT(dev != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ dev = self->netdev;
+ IRDA_ASSERT(dev != NULL, return;);
dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir;
fir_base = self->io.fir_base;
sir_base = self->io.sir_base;
/* Reset everything */
- outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);
+ outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);
#if SMSC_IRCC2_C_SIR_STOP
/*smsc_ircc_sir_stop(self);*/
#endif
register_bank(fir_base, 1);
- outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base+IRCC_SCE_CFGA);
+ outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base + IRCC_SCE_CFGA);
/* Initialize UART */
- outb(UART_LCR_WLEN8, sir_base+UART_LCR); /* Reset DLAB */
- outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base+UART_MCR);
-
+ outb(UART_LCR_WLEN8, sir_base + UART_LCR); /* Reset DLAB */
+ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base + UART_MCR);
+
/* Turn on interrups */
- outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base+UART_IER);
+ outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER);
IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__);
- outb(0x00, fir_base+IRCC_MASTER);
+ outb(0x00, fir_base + IRCC_MASTER);
}
#if SMSC_IRCC2_C_SIR_STOP
@@ -1802,10 +1801,10 @@ void smsc_ircc_sir_stop(struct smsc_ircc_cb *self)
iobase = self->io.sir_base;
/* Reset UART */
- outb(0, iobase+UART_MCR);
-
+ outb(0, iobase + UART_MCR);
+
/* Turn off interrupts */
- outb(0, iobase+UART_IER);
+ outb(0, iobase + UART_IER);
}
#endif
@@ -1831,16 +1830,16 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
/* Finished with frame? */
if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */
- actual = smsc_ircc_sir_write(iobase, self->io.fifo_size,
+ actual = smsc_ircc_sir_write(iobase, self->io.fifo_size,
self->tx_buff.data, self->tx_buff.len);
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
} else {
-
+
/*if (self->tx_buff.len ==0) {*/
-
- /*
- * Now serial buffer is almost free & we can start
+
+ /*
+ * Now serial buffer is almost free & we can start
* transmission of another packet. But first we must check
* if we need to change the speed of the hardware
*/
@@ -1856,21 +1855,19 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
}
self->stats.tx_packets++;
- if(self->io.speed <= 115200) {
- /*
- * Reset Rx FIFO to make sure that all reflected transmit data
- * is discarded. This is needed for half duplex operation
- */
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
+ if (self->io.speed <= 115200) {
+ /*
+ * Reset Rx FIFO to make sure that all reflected transmit data
+ * is discarded. This is needed for half duplex operation
+ */
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
+ fcr |= self->io.speed < 38400 ?
+ UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
- outb(fcr, iobase+UART_FCR);
+ outb(fcr, iobase + UART_FCR);
- /* Turn on receive interrupts */
- outb(UART_IER_RDI, iobase+UART_IER);
+ /* Turn on receive interrupts */
+ outb(UART_IER_RDI, iobase + UART_IER);
}
}
}
@@ -1884,17 +1881,17 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
{
int actual = 0;
-
+
/* Tx FIFO should be empty! */
- if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+ if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) {
IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
return 0;
}
-
+
/* Fill FIFO with current frame */
- while ((fifo_size-- > 0) && (actual < len)) {
+ while (fifo_size-- > 0 && actual < len) {
/* Transmit next byte */
- outb(buf[actual], iobase+UART_TX);
+ outb(buf[actual], iobase + UART_TX);
actual++;
}
return actual;
@@ -1921,20 +1918,21 @@ static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
{
unsigned int i;
-
+
IRDA_ASSERT(self != NULL, return;);
-
- for(i=0; smsc_transceivers[i].name!=NULL; i++)
- if((*smsc_transceivers[i].probe)(self->io.fir_base)) {
+
+ for (i = 0; smsc_transceivers[i].name != NULL; i++)
+ if (smsc_transceivers[i].probe(self->io.fir_base)) {
IRDA_MESSAGE(" %s transceiver found\n",
smsc_transceivers[i].name);
- self->transceiver= i+1;
+ self->transceiver= i + 1;
return;
}
+
IRDA_MESSAGE("No transceiver found. Defaulting to %s\n",
smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
-
- self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
+
+ self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
}
@@ -1947,9 +1945,10 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed)
{
unsigned int trx;
-
+
trx = self->transceiver;
- if(trx>0) (*smsc_transceivers[trx-1].set_for_speed)(self->io.fir_base, speed);
+ if (trx > 0)
+ smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed);
}
/*
@@ -1977,16 +1976,14 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s
static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
{
- int iobase;
+ int iobase = self->io.sir_base;
int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US;
-
- iobase = self->io.sir_base;
-
+
/* Calibrated busy loop */
- while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+ while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT))
udelay(1);
- if(count == 0)
+ if (count == 0)
IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
}
@@ -1998,40 +1995,42 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
static int __init smsc_ircc_look_for_chips(void)
{
- smsc_chip_address_t *address;
- char *type;
+ struct smsc_chip_address *address;
+ char *type;
unsigned int cfg_base, found;
-
+
found = 0;
address = possible_addresses;
-
- while(address->cfg_base){
+
+ while (address->cfg_base) {
cfg_base = address->cfg_base;
-
+
/*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/
-
- if( address->type & SMSCSIO_TYPE_FDC){
+
+ if (address->type & SMSCSIO_TYPE_FDC) {
type = "FDC";
- if((address->type) & SMSCSIO_TYPE_FLAT) {
- if(!smsc_superio_flat(fdc_chips_flat,cfg_base, type)) found++;
- }
- if((address->type) & SMSCSIO_TYPE_PAGED) {
- if(!smsc_superio_paged(fdc_chips_paged,cfg_base, type)) found++;
- }
+ if (address->type & SMSCSIO_TYPE_FLAT)
+ if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type))
+ found++;
+
+ if (address->type & SMSCSIO_TYPE_PAGED)
+ if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type))
+ found++;
}
- if( address->type & SMSCSIO_TYPE_LPC){
+ if (address->type & SMSCSIO_TYPE_LPC) {
type = "LPC";
- if((address->type) & SMSCSIO_TYPE_FLAT) {
- if(!smsc_superio_flat(lpc_chips_flat,cfg_base,type)) found++;
- }
- if((address->type) & SMSCSIO_TYPE_PAGED) {
- if(!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) found++;
- }
+ if (address->type & SMSCSIO_TYPE_FLAT)
+ if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type))
+ found++;
+
+ if (address->type & SMSCSIO_TYPE_PAGED)
+ if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type))
+ found++;
}
address++;
}
return found;
-}
+}
/*
* Function smsc_superio_flat (chip, base, type)
@@ -2039,7 +2038,7 @@ static int __init smsc_ircc_look_for_chips(void)
* Try to get configuration of a smc SuperIO chip with flat register model
*
*/
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfgbase, char *type)
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type)
{
unsigned short firbase, sirbase;
u8 mode, dma, irq;
@@ -2047,39 +2046,37 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type)==NULL)
+ if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL)
return ret;
outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase);
- mode = inb(cfgbase+1);
-
+ mode = inb(cfgbase + 1);
+
/*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/
-
- if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
+
+ if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);
- sirbase = inb(cfgbase+1) << 2;
+ sirbase = inb(cfgbase + 1) << 2;
- /* FIR iobase */
+ /* FIR iobase */
outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase);
- firbase = inb(cfgbase+1) << 3;
+ firbase = inb(cfgbase + 1) << 3;
/* DMA */
outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase);
- dma = inb(cfgbase+1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
-
+ dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
+
/* IRQ */
outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);
- irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+ irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
- if (firbase) {
- if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
- ret=0;
- }
-
+ if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
+ ret = 0;
+
/* Exit configuration */
outb(SMSCSIO_CFGEXITKEY, cfgbase);
@@ -2092,26 +2089,26 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
* Try to get configuration of a smc SuperIO chip with paged register model
*
*/
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type)
+static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type)
{
unsigned short fir_io, sir_io;
int ret = -ENODEV;
-
+
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- if (smsc_ircc_probe(cfg_base,0x20,chips,type)==NULL)
+ if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL)
return ret;
-
+
/* Select logical device (UART2) */
outb(0x07, cfg_base);
outb(0x05, cfg_base + 1);
-
+
/* SIR iobase */
outb(0x60, cfg_base);
- sir_io = inb(cfg_base + 1) << 8;
+ sir_io = inb(cfg_base + 1) << 8;
outb(0x61, cfg_base);
sir_io |= inb(cfg_base + 1);
-
+
/* Read FIR base */
outb(0x62, cfg_base);
fir_io = inb(cfg_base + 1) << 8;
@@ -2119,11 +2116,9 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
fir_io |= inb(cfg_base + 1);
outb(0x2b, cfg_base); /* ??? */
- if (fir_io) {
- if (smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
- ret=0;
- }
-
+ if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
+ ret = 0;
+
/* Exit configuration */
outb(SMSCSIO_CFGEXITKEY, cfg_base);
@@ -2131,21 +2126,17 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
}
-static int __init smsc_access(unsigned short cfg_base,unsigned char reg)
+static int __init smsc_access(unsigned short cfg_base, unsigned char reg)
{
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
outb(reg, cfg_base);
-
- if (inb(cfg_base)!=reg)
- return -1;
-
- return 0;
+ return inb(cfg_base) != reg ? -1 : 0;
}
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type)
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type)
{
- u8 devid,xdevid,rev;
+ u8 devid, xdevid, rev;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
@@ -2158,7 +2149,7 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
outb(reg, cfg_base);
- xdevid=inb(cfg_base+1);
+ xdevid = inb(cfg_base + 1);
/* Enter configuration */
@@ -2168,51 +2159,49 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
if (smsc_access(cfg_base,0x55)) /* send second key and check */
return NULL;
#endif
-
+
/* probe device ID */
- if (smsc_access(cfg_base,reg))
+ if (smsc_access(cfg_base, reg))
return NULL;
- devid=inb(cfg_base+1);
-
- if (devid==0) /* typical value for unused port */
- return NULL;
+ devid = inb(cfg_base + 1);
- if (devid==0xff) /* typical value for unused port */
+ if (devid == 0 || devid == 0xff) /* typical values for unused port */
return NULL;
/* probe revision ID */
- if (smsc_access(cfg_base,reg+1))
+ if (smsc_access(cfg_base, reg + 1))
return NULL;
- rev=inb(cfg_base+1);
+ rev = inb(cfg_base + 1);
- if (rev>=128) /* i think this will make no sense */
+ if (rev >= 128) /* i think this will make no sense */
return NULL;
- if (devid==xdevid) /* protection against false positives */
+ if (devid == xdevid) /* protection against false positives */
return NULL;
/* Check for expected device ID; are there others? */
- while(chip->devid!=devid) {
+ while (chip->devid != devid) {
chip++;
- if (chip->name==NULL)
+ if (chip->name == NULL)
return NULL;
}
- IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+ IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",
+ devid, rev, cfg_base, type, chip->name);
- if (chip->rev>rev){
- IRDA_MESSAGE("Revision higher than expected\n");
+ if (chip->rev > rev) {
+ IRDA_MESSAGE("Revision higher than expected\n");
return NULL;
}
-
- if (chip->flags&NoIRDA)
+
+ if (chip->flags & NoIRDA)
IRDA_MESSAGE("chipset does not support IRDA\n");
return chip;
@@ -2226,8 +2215,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base)
IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
__FUNCTION__, cfg_base);
} else {
- if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")
- ||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+ if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") ||
+ !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC"))
ret = 0;
release_region(cfg_base, 2);
@@ -2244,9 +2233,10 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
__FUNCTION__, cfg_base);
} else {
- if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")
- ||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+ if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") ||
+ !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC"))
ret = 0;
+
release_region(cfg_base, 2);
}
return ret;
@@ -2269,18 +2259,23 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed)
{
unsigned long jiffies_now, jiffies_timeout;
- u8 val;
-
- jiffies_now= jiffies;
- jiffies_timeout= jiffies+SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
-
+ u8 val;
+
+ jiffies_now = jiffies;
+ jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
+
/* ATC */
register_bank(fir_base, 4);
- outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC);
- while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout));
- if(val)
+ outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE,
+ fir_base + IRCC_ATC);
+
+ while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) &&
+ !time_after(jiffies, jiffies_timeout))
+ /* empty */;
+
+ if (val)
IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
- inb(fir_base+IRCC_ATC));
+ inb(fir_base + IRCC_ATC));
}
/*
@@ -2298,34 +2293,32 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base)
/*
* Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed)
*
- * Set transceiver
+ * Set transceiver
*
*/
static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed)
{
- u8 fast_mode;
-
- switch(speed)
- {
- default:
- case 576000 :
- fast_mode = 0;
+ u8 fast_mode;
+
+ switch (speed) {
+ default:
+ case 576000 :
+ fast_mode = 0;
break;
- case 1152000 :
- case 4000000 :
+ case 1152000 :
+ case 4000000 :
fast_mode = IRCC_LCR_A_FAST;
break;
-
}
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);
}
/*
* Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base)
*
- * Probe transceiver
+ * Probe transceiver
*
*/
@@ -2337,35 +2330,34 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base)
/*
* Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed)
*
- * Set transceiver
+ * Set transceiver
*
*/
static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed)
{
- u8 fast_mode;
-
- switch(speed)
- {
- default:
- case 576000 :
- fast_mode = 0;
+ u8 fast_mode;
+
+ switch (speed) {
+ default:
+ case 576000 :
+ fast_mode = 0;
break;
- case 1152000 :
- case 4000000 :
+ case 1152000 :
+ case 4000000 :
fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA;
break;
-
+
}
/* This causes an interrupt */
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);
}
/*
* Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base)
*
- * Probe transceiver
+ * Probe transceiver
*
*/
@@ -2377,20 +2369,3 @@ static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base)
module_init(smsc_ircc_init);
module_exit(smsc_ircc_cleanup);
-
-MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
-MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
-MODULE_LICENSE("GPL");
-
-module_param(ircc_dma, int, 0);
-MODULE_PARM_DESC(ircc_dma, "DMA channel");
-module_param(ircc_irq, int, 0);
-MODULE_PARM_DESC(ircc_irq, "IRQ line");
-module_param(ircc_fir, int, 0);
-MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
-module_param(ircc_sir, int, 0);
-MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
-module_param(ircc_cfg, int, 0);
-MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
-module_param(ircc_transceiver, int, 0);
-MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
diff --git a/drivers/net/irda/smsc-ircc2.h b/drivers/net/irda/smsc-ircc2.h
index 458611cc0d40..0c36286d87f7 100644
--- a/drivers/net/irda/smsc-ircc2.h
+++ b/drivers/net/irda/smsc-ircc2.h
@@ -1,5 +1,5 @@
/*********************************************************************
- * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
+ * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
*
* Description: Definitions for the SMC IrCC chipset
* Status: Experimental.
@@ -9,25 +9,25 @@
* All Rights Reserved.
*
* Based on smc-ircc.h:
- *
+ *
* Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
* All Rights Reserved
*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
+ *
+ * You 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
*
********************************************************************/
@@ -112,10 +112,10 @@
#define IRCC_CFGA_COM 0x00
#define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87
-#define IRCC_CFGA_IRDA_SIR_A 0x08
-#define IRCC_CFGA_ASK_SIR 0x10
-#define IRCC_CFGA_IRDA_SIR_B 0x18
-#define IRCC_CFGA_IRDA_HDLC 0x20
+#define IRCC_CFGA_IRDA_SIR_A 0x08
+#define IRCC_CFGA_ASK_SIR 0x10
+#define IRCC_CFGA_IRDA_SIR_B 0x18
+#define IRCC_CFGA_IRDA_HDLC 0x20
#define IRCC_CFGA_IRDA_4PPM 0x28
#define IRCC_CFGA_CONSUMER 0x30
#define IRCC_CFGA_RAW_IR 0x38
@@ -130,7 +130,7 @@
#define IRCC_CFGB_LPBCK_TX_CRC 0x10
#define IRCC_CFGB_NOWAIT 0x08
#define IRCC_CFGB_STRING_MOVE 0x04
-#define IRCC_CFGB_DMA_BURST 0x02
+#define IRCC_CFGB_DMA_BURST 0x02
#define IRCC_CFGB_DMA_ENABLE 0x01
#define IRCC_CFGB_MUX_COM 0x00
@@ -141,11 +141,11 @@
/* Register block 3 - Identification Registers! */
#define IRCC_ID_HIGH 0x00 /* 0x10 */
#define IRCC_ID_LOW 0x01 /* 0xB8 */
-#define IRCC_CHIP_ID 0x02 /* 0xF1 */
+#define IRCC_CHIP_ID 0x02 /* 0xF1 */
#define IRCC_VERSION 0x03 /* 0x01 */
#define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
-#define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */
-#define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */
/* Register block 4 - IrDA */
#define IRCC_CONTROL 0x00
@@ -163,10 +163,10 @@
/* Register block 5 - IrDA */
#define IRCC_ATC 0x00
-#define IRCC_ATC_nPROGREADY 0x80
-#define IRCC_ATC_SPEED 0x40
-#define IRCC_ATC_ENABLE 0x20
-#define IRCC_ATC_MASK 0xE0
+#define IRCC_ATC_nPROGREADY 0x80
+#define IRCC_ATC_SPEED 0x40
+#define IRCC_ATC_ENABLE 0x20
+#define IRCC_ATC_MASK 0xE0
#define IRCC_IRHALFDUPLEX_TIMEOUT 0x01
@@ -178,8 +178,8 @@
*/
#define SMSC_IRCC2_MAX_SIR_SPEED 115200
-#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
-#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
+#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
+#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_FIFO_SIZE 16
#define SMSC_IRCC2_FIFO_THRESHOLD 64
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 006e4f575606..6d9de626c967 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -1749,11 +1749,6 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
struct net_device *ndev = pci_get_drvdata(pdev);
vlsi_irda_dev_t *idev;
- if (state < 1 || state > 3 ) {
- IRDA_ERROR("%s - %s: invalid pm state request: %u\n",
- __FUNCTION__, PCIDEV_NAME(pdev), state);
- return 0;
- }
if (!ndev) {
IRDA_ERROR("%s - %s: no netdevice \n",
__FUNCTION__, PCIDEV_NAME(pdev));
@@ -1762,12 +1757,12 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
idev = ndev->priv;
down(&idev->sem);
if (pdev->current_state != 0) { /* already suspended */
- if (state > pdev->current_state) { /* simply go deeper */
- pci_set_power_state(pdev,state);
- pdev->current_state = state;
+ if (state.event > pdev->current_state) { /* simply go deeper */
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ pdev->current_state = state.event;
}
else
- IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state);
+ IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state.event);
up(&idev->sem);
return 0;
}
@@ -1781,8 +1776,8 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
idev->new_baud = idev->baud;
}
- pci_set_power_state(pdev,state);
- pdev->current_state = state;
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ pdev->current_state = state.event;
idev->resume_ok = 1;
up(&idev->sem);
return 0;
@@ -1807,8 +1802,8 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
return 0;
}
- pci_set_power_state(pdev, 0);
- pdev->current_state = 0;
+ pci_set_power_state(pdev, PCI_D0);
+ pdev->current_state = PM_EVENT_ON;
if (!idev->resume_ok) {
/* should be obsolete now - but used to happen due to:
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 414694abf588..741aecc655df 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -69,14 +69,8 @@ typedef void irqreturn_t;
#else /* 2.5 or later */
-/* recent 2.5/2.6 stores pci device names at varying places ;-) */
-#ifdef CONFIG_PCI_NAMES
-/* human readable name */
-#define PCIDEV_NAME(pdev) ((pdev)->pretty_name)
-#else
/* whatever we get from the associated struct device - bus:slot:dev.fn id */
#define PCIDEV_NAME(pdev) (pci_name(pdev))
-#endif
#endif
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 55af32e9bf08..3d56cf5a4e23 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -4,6 +4,7 @@
* Copyright (C) 2001 Kyle A. Lucke (klucke@us.ibm.com), IBM Corp.
* Substantially cleaned up by:
* Copyright (C) 2003 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ * Copyright (C) 2004-2005 Michael Ellerman, 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
@@ -79,12 +80,55 @@
#include <asm/iommu.h>
#include <asm/vio.h>
-#include "iseries_veth.h"
+#undef DEBUG
MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>");
MODULE_DESCRIPTION("iSeries Virtual ethernet driver");
MODULE_LICENSE("GPL");
+#define VETH_EVENT_CAP (0)
+#define VETH_EVENT_FRAMES (1)
+#define VETH_EVENT_MONITOR (2)
+#define VETH_EVENT_FRAMES_ACK (3)
+
+#define VETH_MAX_ACKS_PER_MSG (20)
+#define VETH_MAX_FRAMES_PER_MSG (6)
+
+struct veth_frames_data {
+ u32 addr[VETH_MAX_FRAMES_PER_MSG];
+ u16 len[VETH_MAX_FRAMES_PER_MSG];
+ u32 eofmask;
+};
+#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG)
+
+struct veth_frames_ack_data {
+ u16 token[VETH_MAX_ACKS_PER_MSG];
+};
+
+struct veth_cap_data {
+ u8 caps_version;
+ u8 rsvd1;
+ u16 num_buffers;
+ u16 ack_threshold;
+ u16 rsvd2;
+ u32 ack_timeout;
+ u32 rsvd3;
+ u64 rsvd4[3];
+};
+
+struct veth_lpevent {
+ struct HvLpEvent base_event;
+ union {
+ struct veth_cap_data caps_data;
+ struct veth_frames_data frames_data;
+ struct veth_frames_ack_data frames_ack_data;
+ } u;
+
+};
+
+#define DRV_NAME "iseries_veth"
+#define DRV_VERSION "2.0"
+
#define VETH_NUMBUFFERS (120)
#define VETH_ACKTIMEOUT (1000000) /* microseconds */
#define VETH_MAX_MCAST (12)
@@ -113,9 +157,9 @@ MODULE_LICENSE("GPL");
struct veth_msg {
struct veth_msg *next;
- struct VethFramesData data;
+ struct veth_frames_data data;
int token;
- unsigned long in_use;
+ int in_use;
struct sk_buff *skb;
struct device *dev;
};
@@ -125,23 +169,28 @@ struct veth_lpar_connection {
struct work_struct statemachine_wq;
struct veth_msg *msgs;
int num_events;
- struct VethCapData local_caps;
+ struct veth_cap_data local_caps;
+ struct kobject kobject;
struct timer_list ack_timer;
+ struct timer_list reset_timer;
+ unsigned int reset_timeout;
+ unsigned long last_contact;
+ int outstanding_tx;
+
spinlock_t lock;
unsigned long state;
HvLpInstanceId src_inst;
HvLpInstanceId dst_inst;
- struct VethLpEvent cap_event, cap_ack_event;
+ struct veth_lpevent cap_event, cap_ack_event;
u16 pending_acks[VETH_MAX_ACKS_PER_MSG];
u32 num_pending_acks;
int num_ack_events;
- struct VethCapData remote_caps;
+ struct veth_cap_data remote_caps;
u32 ack_timeout;
- spinlock_t msg_stack_lock;
struct veth_msg *msg_stack_head;
};
@@ -151,15 +200,17 @@ struct veth_port {
u64 mac_addr;
HvLpIndexMap lpar_map;
- spinlock_t pending_gate;
- struct sk_buff *pending_skb;
- HvLpIndexMap pending_lpmask;
+ /* queue_lock protects the stopped_map and dev's queue. */
+ spinlock_t queue_lock;
+ HvLpIndexMap stopped_map;
+ /* mcast_gate protects promiscuous, num_mcast & mcast_addr. */
rwlock_t mcast_gate;
int promiscuous;
- int all_mcast;
int num_mcast;
u64 mcast_addr[VETH_MAX_MCAST];
+
+ struct kobject kobject;
};
static HvLpIndex this_lp;
@@ -168,44 +219,56 @@ static struct net_device *veth_dev[HVMAXARCHITECTEDVIRTUALLANS]; /* = 0 */
static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *);
-static void veth_flush_pending(struct veth_lpar_connection *cnx);
-static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *);
-static void veth_timed_ack(unsigned long connectionPtr);
+static void veth_wake_queues(struct veth_lpar_connection *cnx);
+static void veth_stop_queues(struct veth_lpar_connection *cnx);
+static void veth_receive(struct veth_lpar_connection *, struct veth_lpevent *);
+static void veth_release_connection(struct kobject *kobject);
+static void veth_timed_ack(unsigned long ptr);
+static void veth_timed_reset(unsigned long ptr);
/*
* Utility functions
*/
-#define veth_printk(prio, fmt, args...) \
- printk(prio "%s: " fmt, __FILE__, ## args)
+#define veth_info(fmt, args...) \
+ printk(KERN_INFO DRV_NAME ": " fmt, ## args)
#define veth_error(fmt, args...) \
- printk(KERN_ERR "(%s:%3.3d) ERROR: " fmt, __FILE__, __LINE__ , ## args)
+ printk(KERN_ERR DRV_NAME ": Error: " fmt, ## args)
+
+#ifdef DEBUG
+#define veth_debug(fmt, args...) \
+ printk(KERN_DEBUG DRV_NAME ": " fmt, ## args)
+#else
+#define veth_debug(fmt, args...) do {} while (0)
+#endif
+/* You must hold the connection's lock when you call this function. */
static inline void veth_stack_push(struct veth_lpar_connection *cnx,
struct veth_msg *msg)
{
- unsigned long flags;
-
- spin_lock_irqsave(&cnx->msg_stack_lock, flags);
msg->next = cnx->msg_stack_head;
cnx->msg_stack_head = msg;
- spin_unlock_irqrestore(&cnx->msg_stack_lock, flags);
}
+/* You must hold the connection's lock when you call this function. */
static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx)
{
- unsigned long flags;
struct veth_msg *msg;
- spin_lock_irqsave(&cnx->msg_stack_lock, flags);
msg = cnx->msg_stack_head;
if (msg)
cnx->msg_stack_head = cnx->msg_stack_head->next;
- spin_unlock_irqrestore(&cnx->msg_stack_lock, flags);
+
return msg;
}
+/* You must hold the connection's lock when you call this function. */
+static inline int veth_stack_is_empty(struct veth_lpar_connection *cnx)
+{
+ return cnx->msg_stack_head == NULL;
+}
+
static inline HvLpEvent_Rc
veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype,
HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype,
@@ -249,7 +312,7 @@ static int veth_allocate_events(HvLpIndex rlp, int number)
struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 };
mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan,
- sizeof(struct VethLpEvent), number,
+ sizeof(struct veth_lpevent), number,
&veth_complete_allocation, &vc);
wait_for_completion(&vc.c);
@@ -257,6 +320,137 @@ static int veth_allocate_events(HvLpIndex rlp, int number)
}
/*
+ * sysfs support
+ */
+
+struct veth_cnx_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct veth_lpar_connection *, char *buf);
+ ssize_t (*store)(struct veth_lpar_connection *, const char *buf);
+};
+
+static ssize_t veth_cnx_attribute_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct veth_cnx_attribute *cnx_attr;
+ struct veth_lpar_connection *cnx;
+
+ cnx_attr = container_of(attr, struct veth_cnx_attribute, attr);
+ cnx = container_of(kobj, struct veth_lpar_connection, kobject);
+
+ if (!cnx_attr->show)
+ return -EIO;
+
+ return cnx_attr->show(cnx, buf);
+}
+
+#define CUSTOM_CNX_ATTR(_name, _format, _expression) \
+static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\
+{ \
+ return sprintf(buf, _format, _expression); \
+} \
+struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name)
+
+#define SIMPLE_CNX_ATTR(_name) \
+ CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name)
+
+SIMPLE_CNX_ATTR(outstanding_tx);
+SIMPLE_CNX_ATTR(remote_lp);
+SIMPLE_CNX_ATTR(num_events);
+SIMPLE_CNX_ATTR(src_inst);
+SIMPLE_CNX_ATTR(dst_inst);
+SIMPLE_CNX_ATTR(num_pending_acks);
+SIMPLE_CNX_ATTR(num_ack_events);
+CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout));
+CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout));
+CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state);
+CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ?
+ jiffies_to_msecs(jiffies - cnx->last_contact) : 0);
+
+#define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr)
+
+static struct attribute *veth_cnx_default_attrs[] = {
+ GET_CNX_ATTR(outstanding_tx),
+ GET_CNX_ATTR(remote_lp),
+ GET_CNX_ATTR(num_events),
+ GET_CNX_ATTR(reset_timeout),
+ GET_CNX_ATTR(last_contact),
+ GET_CNX_ATTR(state),
+ GET_CNX_ATTR(src_inst),
+ GET_CNX_ATTR(dst_inst),
+ GET_CNX_ATTR(num_pending_acks),
+ GET_CNX_ATTR(num_ack_events),
+ GET_CNX_ATTR(ack_timeout),
+ NULL
+};
+
+static struct sysfs_ops veth_cnx_sysfs_ops = {
+ .show = veth_cnx_attribute_show
+};
+
+static struct kobj_type veth_lpar_connection_ktype = {
+ .release = veth_release_connection,
+ .sysfs_ops = &veth_cnx_sysfs_ops,
+ .default_attrs = veth_cnx_default_attrs
+};
+
+struct veth_port_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct veth_port *, char *buf);
+ ssize_t (*store)(struct veth_port *, const char *buf);
+};
+
+static ssize_t veth_port_attribute_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct veth_port_attribute *port_attr;
+ struct veth_port *port;
+
+ port_attr = container_of(attr, struct veth_port_attribute, attr);
+ port = container_of(kobj, struct veth_port, kobject);
+
+ if (!port_attr->show)
+ return -EIO;
+
+ return port_attr->show(port, buf);
+}
+
+#define CUSTOM_PORT_ATTR(_name, _format, _expression) \
+static ssize_t _name##_show(struct veth_port *port, char *buf) \
+{ \
+ return sprintf(buf, _format, _expression); \
+} \
+struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name)
+
+#define SIMPLE_PORT_ATTR(_name) \
+ CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name)
+
+SIMPLE_PORT_ATTR(promiscuous);
+SIMPLE_PORT_ATTR(num_mcast);
+CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map);
+CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map);
+CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr);
+
+#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr)
+static struct attribute *veth_port_default_attrs[] = {
+ GET_PORT_ATTR(mac_addr),
+ GET_PORT_ATTR(lpar_map),
+ GET_PORT_ATTR(stopped_map),
+ GET_PORT_ATTR(promiscuous),
+ GET_PORT_ATTR(num_mcast),
+ NULL
+};
+
+static struct sysfs_ops veth_port_sysfs_ops = {
+ .show = veth_port_attribute_show
+};
+
+static struct kobj_type veth_port_ktype = {
+ .sysfs_ops = &veth_port_sysfs_ops,
+ .default_attrs = veth_port_default_attrs
+};
+
+/*
* LPAR connection code
*/
@@ -266,7 +460,7 @@ static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx)
}
static void veth_take_cap(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
@@ -278,7 +472,7 @@ static void veth_take_cap(struct veth_lpar_connection *cnx,
HvLpEvent_Type_VirtualLan);
if (cnx->state & VETH_STATE_GOTCAPS) {
- veth_error("Received a second capabilities from lpar %d\n",
+ veth_error("Received a second capabilities from LPAR %d.\n",
cnx->remote_lp);
event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable;
HvCallEvent_ackLpEvent((struct HvLpEvent *) event);
@@ -291,13 +485,13 @@ static void veth_take_cap(struct veth_lpar_connection *cnx,
}
static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
spin_lock_irqsave(&cnx->lock, flags);
if (cnx->state & VETH_STATE_GOTCAPACK) {
- veth_error("Received a second capabilities ack from lpar %d\n",
+ veth_error("Received a second capabilities ack from LPAR %d.\n",
cnx->remote_lp);
} else {
memcpy(&cnx->cap_ack_event, event,
@@ -309,19 +503,24 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
}
static void veth_take_monitor_ack(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
spin_lock_irqsave(&cnx->lock, flags);
- veth_printk(KERN_DEBUG, "Monitor ack returned for lpar %d\n",
- cnx->remote_lp);
- cnx->state |= VETH_STATE_RESET;
- veth_kick_statemachine(cnx);
+ veth_debug("cnx %d: lost connection.\n", cnx->remote_lp);
+
+ /* Avoid kicking the statemachine once we're shutdown.
+ * It's unnecessary and it could break veth_stop_connection(). */
+
+ if (! (cnx->state & VETH_STATE_SHUTDOWN)) {
+ cnx->state |= VETH_STATE_RESET;
+ veth_kick_statemachine(cnx);
+ }
spin_unlock_irqrestore(&cnx->lock, flags);
}
-static void veth_handle_ack(struct VethLpEvent *event)
+static void veth_handle_ack(struct veth_lpevent *event)
{
HvLpIndex rlp = event->base_event.xTargetLp;
struct veth_lpar_connection *cnx = veth_cnx[rlp];
@@ -329,58 +528,67 @@ static void veth_handle_ack(struct VethLpEvent *event)
BUG_ON(! cnx);
switch (event->base_event.xSubtype) {
- case VethEventTypeCap:
+ case VETH_EVENT_CAP:
veth_take_cap_ack(cnx, event);
break;
- case VethEventTypeMonitor:
+ case VETH_EVENT_MONITOR:
veth_take_monitor_ack(cnx, event);
break;
default:
- veth_error("Unknown ack type %d from lpar %d\n",
- event->base_event.xSubtype, rlp);
+ veth_error("Unknown ack type %d from LPAR %d.\n",
+ event->base_event.xSubtype, rlp);
};
}
-static void veth_handle_int(struct VethLpEvent *event)
+static void veth_handle_int(struct veth_lpevent *event)
{
HvLpIndex rlp = event->base_event.xSourceLp;
struct veth_lpar_connection *cnx = veth_cnx[rlp];
unsigned long flags;
- int i;
+ int i, acked = 0;
BUG_ON(! cnx);
switch (event->base_event.xSubtype) {
- case VethEventTypeCap:
+ case VETH_EVENT_CAP:
veth_take_cap(cnx, event);
break;
- case VethEventTypeMonitor:
+ case VETH_EVENT_MONITOR:
/* do nothing... this'll hang out here til we're dead,
* and the hypervisor will return it for us. */
break;
- case VethEventTypeFramesAck:
+ case VETH_EVENT_FRAMES_ACK:
spin_lock_irqsave(&cnx->lock, flags);
+
for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) {
u16 msgnum = event->u.frames_ack_data.token[i];
- if (msgnum < VETH_NUMBUFFERS)
+ if (msgnum < VETH_NUMBUFFERS) {
veth_recycle_msg(cnx, cnx->msgs + msgnum);
+ cnx->outstanding_tx--;
+ acked++;
+ }
+ }
+
+ if (acked > 0) {
+ cnx->last_contact = jiffies;
+ veth_wake_queues(cnx);
}
+
spin_unlock_irqrestore(&cnx->lock, flags);
- veth_flush_pending(cnx);
break;
- case VethEventTypeFrames:
+ case VETH_EVENT_FRAMES:
veth_receive(cnx, event);
break;
default:
- veth_error("Unknown interrupt type %d from lpar %d\n",
- event->base_event.xSubtype, rlp);
+ veth_error("Unknown interrupt type %d from LPAR %d.\n",
+ event->base_event.xSubtype, rlp);
};
}
static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
{
- struct VethLpEvent *veth_event = (struct VethLpEvent *)event;
+ struct veth_lpevent *veth_event = (struct veth_lpevent *)event;
if (event->xFlags.xFunction == HvLpEvent_Function_Ack)
veth_handle_ack(veth_event);
@@ -390,7 +598,7 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
static int veth_process_caps(struct veth_lpar_connection *cnx)
{
- struct VethCapData *remote_caps = &cnx->remote_caps;
+ struct veth_cap_data *remote_caps = &cnx->remote_caps;
int num_acks_needed;
/* Convert timer to jiffies */
@@ -400,8 +608,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx)
|| (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG)
|| (remote_caps->ack_threshold == 0)
|| (cnx->ack_timeout == 0) ) {
- veth_error("Received incompatible capabilities from lpar %d\n",
- cnx->remote_lp);
+ veth_error("Received incompatible capabilities from LPAR %d.\n",
+ cnx->remote_lp);
return HvLpEvent_Rc_InvalidSubtypeData;
}
@@ -418,8 +626,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx)
cnx->num_ack_events += num;
if (cnx->num_ack_events < num_acks_needed) {
- veth_error("Couldn't allocate enough ack events for lpar %d\n",
- cnx->remote_lp);
+ veth_error("Couldn't allocate enough ack events "
+ "for LPAR %d.\n", cnx->remote_lp);
return HvLpEvent_Rc_BufferNotAvailable;
}
@@ -440,15 +648,15 @@ static void veth_statemachine(void *p)
restart:
if (cnx->state & VETH_STATE_RESET) {
- int i;
-
- del_timer(&cnx->ack_timer);
-
if (cnx->state & VETH_STATE_OPEN)
HvCallEvent_closeLpEventPath(cnx->remote_lp,
HvLpEvent_Type_VirtualLan);
- /* reset ack data */
+ /*
+ * Reset ack data. This prevents the ack_timer actually
+ * doing anything, even if it runs one more time when
+ * we drop the lock below.
+ */
memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks));
cnx->num_pending_acks = 0;
@@ -458,14 +666,32 @@ static void veth_statemachine(void *p)
| VETH_STATE_SENTCAPACK | VETH_STATE_READY);
/* Clean up any leftover messages */
- if (cnx->msgs)
+ if (cnx->msgs) {
+ int i;
for (i = 0; i < VETH_NUMBUFFERS; ++i)
veth_recycle_msg(cnx, cnx->msgs + i);
+ }
+
+ cnx->outstanding_tx = 0;
+ veth_wake_queues(cnx);
+
+ /* Drop the lock so we can do stuff that might sleep or
+ * take other locks. */
spin_unlock_irq(&cnx->lock);
- veth_flush_pending(cnx);
+
+ del_timer_sync(&cnx->ack_timer);
+ del_timer_sync(&cnx->reset_timer);
+
spin_lock_irq(&cnx->lock);
+
if (cnx->state & VETH_STATE_RESET)
goto restart;
+
+ /* Hack, wait for the other end to reset itself. */
+ if (! (cnx->state & VETH_STATE_SHUTDOWN)) {
+ schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ);
+ goto out;
+ }
}
if (cnx->state & VETH_STATE_SHUTDOWN)
@@ -488,7 +714,7 @@ static void veth_statemachine(void *p)
if ( (cnx->state & VETH_STATE_OPEN)
&& !(cnx->state & VETH_STATE_SENTMON) ) {
- rc = veth_signalevent(cnx, VethEventTypeMonitor,
+ rc = veth_signalevent(cnx, VETH_EVENT_MONITOR,
HvLpEvent_AckInd_DoAck,
HvLpEvent_AckType_DeferredAck,
0, 0, 0, 0, 0, 0);
@@ -498,9 +724,8 @@ static void veth_statemachine(void *p)
} else {
if ( (rc != HvLpEvent_Rc_PartitionDead)
&& (rc != HvLpEvent_Rc_PathClosed) )
- veth_error("Error sending monitor to "
- "lpar %d, rc=%x\n",
- rlp, (int) rc);
+ veth_error("Error sending monitor to LPAR %d, "
+ "rc = %d\n", rlp, rc);
/* Oh well, hope we get a cap from the other
* end and do better when that kicks us */
@@ -512,7 +737,7 @@ static void veth_statemachine(void *p)
&& !(cnx->state & VETH_STATE_SENTCAPS)) {
u64 *rawcap = (u64 *)&cnx->local_caps;
- rc = veth_signalevent(cnx, VethEventTypeCap,
+ rc = veth_signalevent(cnx, VETH_EVENT_CAP,
HvLpEvent_AckInd_DoAck,
HvLpEvent_AckType_ImmediateAck,
0, rawcap[0], rawcap[1], rawcap[2],
@@ -523,9 +748,9 @@ static void veth_statemachine(void *p)
} else {
if ( (rc != HvLpEvent_Rc_PartitionDead)
&& (rc != HvLpEvent_Rc_PathClosed) )
- veth_error("Error sending caps to "
- "lpar %d, rc=%x\n",
- rlp, (int) rc);
+ veth_error("Error sending caps to LPAR %d, "
+ "rc = %d\n", rlp, rc);
+
/* Oh well, hope we get a cap from the other
* end and do better when that kicks us */
goto out;
@@ -534,7 +759,7 @@ static void veth_statemachine(void *p)
if ((cnx->state & VETH_STATE_GOTCAPS)
&& !(cnx->state & VETH_STATE_SENTCAPACK)) {
- struct VethCapData *remote_caps = &cnx->remote_caps;
+ struct veth_cap_data *remote_caps = &cnx->remote_caps;
memcpy(remote_caps, &cnx->cap_event.u.caps_data,
sizeof(*remote_caps));
@@ -565,10 +790,8 @@ static void veth_statemachine(void *p)
add_timer(&cnx->ack_timer);
cnx->state |= VETH_STATE_READY;
} else {
- veth_printk(KERN_ERR, "Caps rejected (rc=%d) by "
- "lpar %d\n",
- cnx->cap_ack_event.base_event.xRc,
- rlp);
+ veth_error("Caps rejected by LPAR %d, rc = %d\n",
+ rlp, cnx->cap_ack_event.base_event.xRc);
goto cant_cope;
}
}
@@ -581,8 +804,8 @@ static void veth_statemachine(void *p)
/* FIXME: we get here if something happens we really can't
* cope with. The link will never work once we get here, and
* all we can do is not lock the rest of the system up */
- veth_error("Badness on connection to lpar %d (state=%04lx) "
- " - shutting down\n", rlp, cnx->state);
+ veth_error("Unrecoverable error on connection to LPAR %d, shutting down"
+ " (state = 0x%04lx)\n", rlp, cnx->state);
cnx->state |= VETH_STATE_SHUTDOWN;
spin_unlock_irq(&cnx->lock);
}
@@ -591,7 +814,7 @@ static int veth_init_connection(u8 rlp)
{
struct veth_lpar_connection *cnx;
struct veth_msg *msgs;
- int i;
+ int i, rc;
if ( (rlp == this_lp)
|| ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) )
@@ -605,22 +828,36 @@ static int veth_init_connection(u8 rlp)
cnx->remote_lp = rlp;
spin_lock_init(&cnx->lock);
INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx);
+
init_timer(&cnx->ack_timer);
cnx->ack_timer.function = veth_timed_ack;
cnx->ack_timer.data = (unsigned long) cnx;
+
+ init_timer(&cnx->reset_timer);
+ cnx->reset_timer.function = veth_timed_reset;
+ cnx->reset_timer.data = (unsigned long) cnx;
+ cnx->reset_timeout = 5 * HZ * (VETH_ACKTIMEOUT / 1000000);
+
memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks));
veth_cnx[rlp] = cnx;
+ /* This gets us 1 reference, which is held on behalf of the driver
+ * infrastructure. It's released at module unload. */
+ kobject_init(&cnx->kobject);
+ cnx->kobject.ktype = &veth_lpar_connection_ktype;
+ rc = kobject_set_name(&cnx->kobject, "cnx%.2d", rlp);
+ if (rc != 0)
+ return rc;
+
msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL);
if (! msgs) {
- veth_error("Can't allocate buffers for lpar %d\n", rlp);
+ veth_error("Can't allocate buffers for LPAR %d.\n", rlp);
return -ENOMEM;
}
cnx->msgs = msgs;
memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg));
- spin_lock_init(&cnx->msg_stack_lock);
for (i = 0; i < VETH_NUMBUFFERS; i++) {
msgs[i].token = i;
@@ -630,8 +867,7 @@ static int veth_init_connection(u8 rlp)
cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS);
if (cnx->num_events < (2 + VETH_NUMBUFFERS)) {
- veth_error("Can't allocate events for lpar %d, only got %d\n",
- rlp, cnx->num_events);
+ veth_error("Can't allocate enough events for LPAR %d.\n", rlp);
return -ENOMEM;
}
@@ -642,11 +878,9 @@ static int veth_init_connection(u8 rlp)
return 0;
}
-static void veth_stop_connection(u8 rlp)
+static void veth_stop_connection(struct veth_lpar_connection *cnx)
{
- struct veth_lpar_connection *cnx = veth_cnx[rlp];
-
- if (! cnx)
+ if (!cnx)
return;
spin_lock_irq(&cnx->lock);
@@ -654,12 +888,23 @@ static void veth_stop_connection(u8 rlp)
veth_kick_statemachine(cnx);
spin_unlock_irq(&cnx->lock);
+ /* There's a slim chance the reset code has just queued the
+ * statemachine to run in five seconds. If so we need to cancel
+ * that and requeue the work to run now. */
+ if (cancel_delayed_work(&cnx->statemachine_wq)) {
+ spin_lock_irq(&cnx->lock);
+ veth_kick_statemachine(cnx);
+ spin_unlock_irq(&cnx->lock);
+ }
+
+ /* Wait for the state machine to run. */
flush_scheduled_work();
+}
- /* FIXME: not sure if this is necessary - will already have
- * been deleted by the state machine, just want to make sure
- * its not running any more */
- del_timer_sync(&cnx->ack_timer);
+static void veth_destroy_connection(struct veth_lpar_connection *cnx)
+{
+ if (!cnx)
+ return;
if (cnx->num_events > 0)
mf_deallocate_lp_events(cnx->remote_lp,
@@ -671,18 +916,18 @@ static void veth_stop_connection(u8 rlp)
HvLpEvent_Type_VirtualLan,
cnx->num_ack_events,
NULL, NULL);
-}
-
-static void veth_destroy_connection(u8 rlp)
-{
- struct veth_lpar_connection *cnx = veth_cnx[rlp];
-
- if (! cnx)
- return;
kfree(cnx->msgs);
+ veth_cnx[cnx->remote_lp] = NULL;
kfree(cnx);
- veth_cnx[rlp] = NULL;
+}
+
+static void veth_release_connection(struct kobject *kobj)
+{
+ struct veth_lpar_connection *cnx;
+ cnx = container_of(kobj, struct veth_lpar_connection, kobject);
+ veth_stop_connection(cnx);
+ veth_destroy_connection(cnx);
}
/*
@@ -726,17 +971,15 @@ static void veth_set_multicast_list(struct net_device *dev)
write_lock_irqsave(&port->mcast_gate, flags);
- if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
- printk(KERN_INFO "%s: Promiscuous mode enabled.\n",
- dev->name);
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
+ (dev->mc_count > VETH_MAX_MCAST)) {
port->promiscuous = 1;
- } else if ( (dev->flags & IFF_ALLMULTI)
- || (dev->mc_count > VETH_MAX_MCAST) ) {
- port->all_mcast = 1;
} else {
struct dev_mc_list *dmi = dev->mc_list;
int i;
+ port->promiscuous = 0;
+
/* Update table */
port->num_mcast = 0;
@@ -758,9 +1001,10 @@ static void veth_set_multicast_list(struct net_device *dev)
static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- strncpy(info->driver, "veth", sizeof(info->driver) - 1);
+ strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
info->driver[sizeof(info->driver) - 1] = '\0';
- strncpy(info->version, "1.0", sizeof(info->version) - 1);
+ strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+ info->version[sizeof(info->version) - 1] = '\0';
}
static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -791,49 +1035,6 @@ static struct ethtool_ops ops = {
.get_link = veth_get_link,
};
-static void veth_tx_timeout(struct net_device *dev)
-{
- struct veth_port *port = (struct veth_port *)dev->priv;
- struct net_device_stats *stats = &port->stats;
- unsigned long flags;
- int i;
-
- stats->tx_errors++;
-
- spin_lock_irqsave(&port->pending_gate, flags);
-
- if (!port->pending_lpmask) {
- spin_unlock_irqrestore(&port->pending_gate, flags);
- return;
- }
-
- printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n",
- dev->name, port->pending_lpmask);
-
- for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
- struct veth_lpar_connection *cnx = veth_cnx[i];
-
- if (! (port->pending_lpmask & (1<<i)))
- continue;
-
- /* If we're pending on it, we must be connected to it,
- * so we should certainly have a structure for it. */
- BUG_ON(! cnx);
-
- /* Theoretically we could be kicking a connection
- * which doesn't deserve it, but in practice if we've
- * had a Tx timeout, the pending_lpmask will have
- * exactly one bit set - the connection causing the
- * problem. */
- spin_lock(&cnx->lock);
- cnx->state |= VETH_STATE_RESET;
- veth_kick_statemachine(cnx);
- spin_unlock(&cnx->lock);
- }
-
- spin_unlock_irqrestore(&port->pending_gate, flags);
-}
-
static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
{
struct net_device *dev;
@@ -848,8 +1049,9 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
port = (struct veth_port *) dev->priv;
- spin_lock_init(&port->pending_gate);
+ spin_lock_init(&port->queue_lock);
rwlock_init(&port->mcast_gate);
+ port->stopped_map = 0;
for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
HvLpVirtualLanIndexMap map;
@@ -882,22 +1084,24 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
dev->set_multicast_list = veth_set_multicast_list;
SET_ETHTOOL_OPS(dev, &ops);
- dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000);
- dev->tx_timeout = veth_tx_timeout;
-
SET_NETDEV_DEV(dev, vdev);
rc = register_netdev(dev);
if (rc != 0) {
- veth_printk(KERN_ERR,
- "Failed to register ethernet device for vlan %d\n",
- vlan);
+ veth_error("Failed registering net device for vlan%d.\n", vlan);
free_netdev(dev);
return NULL;
}
- veth_printk(KERN_DEBUG, "%s attached to iSeries vlan %d (lpar_map=0x%04x)\n",
- dev->name, vlan, port->lpar_map);
+ kobject_init(&port->kobject);
+ port->kobject.parent = &dev->class_dev.kobj;
+ port->kobject.ktype = &veth_port_ktype;
+ kobject_set_name(&port->kobject, "veth_port");
+ if (0 != kobject_add(&port->kobject))
+ veth_error("Failed adding port for %s to sysfs.\n", dev->name);
+
+ veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n",
+ dev->name, vlan, port->lpar_map);
return dev;
}
@@ -912,98 +1116,95 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
struct veth_lpar_connection *cnx = veth_cnx[rlp];
struct veth_port *port = (struct veth_port *) dev->priv;
HvLpEvent_Rc rc;
- u32 dma_address, dma_length;
struct veth_msg *msg = NULL;
- int err = 0;
unsigned long flags;
- if (! cnx) {
- port->stats.tx_errors++;
- dev_kfree_skb(skb);
+ if (! cnx)
return 0;
- }
spin_lock_irqsave(&cnx->lock, flags);
if (! (cnx->state & VETH_STATE_READY))
- goto drop;
+ goto no_error;
- if ((skb->len - 14) > VETH_MAX_MTU)
+ if ((skb->len - ETH_HLEN) > VETH_MAX_MTU)
goto drop;
msg = veth_stack_pop(cnx);
-
- if (! msg) {
- err = 1;
+ if (! msg)
goto drop;
- }
- dma_length = skb->len;
- dma_address = dma_map_single(port->dev, skb->data,
- dma_length, DMA_TO_DEVICE);
+ msg->in_use = 1;
+ msg->skb = skb_get(skb);
+
+ msg->data.addr[0] = dma_map_single(port->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(dma_address))
+ if (dma_mapping_error(msg->data.addr[0]))
goto recycle_and_drop;
- /* Is it really necessary to check the length and address
- * fields of the first entry here? */
- msg->skb = skb;
msg->dev = port->dev;
- msg->data.addr[0] = dma_address;
- msg->data.len[0] = dma_length;
+ msg->data.len[0] = skb->len;
msg->data.eofmask = 1 << VETH_EOF_SHIFT;
- set_bit(0, &(msg->in_use));
- rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data);
+
+ rc = veth_signaldata(cnx, VETH_EVENT_FRAMES, msg->token, &msg->data);
if (rc != HvLpEvent_Rc_Good)
goto recycle_and_drop;
+ /* If the timer's not already running, start it now. */
+ if (0 == cnx->outstanding_tx)
+ mod_timer(&cnx->reset_timer, jiffies + cnx->reset_timeout);
+
+ cnx->last_contact = jiffies;
+ cnx->outstanding_tx++;
+
+ if (veth_stack_is_empty(cnx))
+ veth_stop_queues(cnx);
+
+ no_error:
spin_unlock_irqrestore(&cnx->lock, flags);
return 0;
recycle_and_drop:
- msg->skb = NULL;
- /* need to set in use to make veth_recycle_msg in case this
- * was a mapping failure */
- set_bit(0, &msg->in_use);
veth_recycle_msg(cnx, msg);
drop:
- port->stats.tx_errors++;
- dev_kfree_skb(skb);
spin_unlock_irqrestore(&cnx->lock, flags);
- return err;
+ return 1;
}
-static HvLpIndexMap veth_transmit_to_many(struct sk_buff *skb,
+static void veth_transmit_to_many(struct sk_buff *skb,
HvLpIndexMap lpmask,
struct net_device *dev)
{
struct veth_port *port = (struct veth_port *) dev->priv;
- int i;
- int rc;
+ int i, success, error;
+
+ success = error = 0;
for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
if ((lpmask & (1 << i)) == 0)
continue;
- rc = veth_transmit_to_one(skb_get(skb), i, dev);
- if (! rc)
- lpmask &= ~(1<<i);
+ if (veth_transmit_to_one(skb, i, dev))
+ error = 1;
+ else
+ success = 1;
}
- if (! lpmask) {
+ if (error)
+ port->stats.tx_errors++;
+
+ if (success) {
port->stats.tx_packets++;
port->stats.tx_bytes += skb->len;
}
-
- return lpmask;
}
static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *frame = skb->data;
struct veth_port *port = (struct veth_port *) dev->priv;
- unsigned long flags;
HvLpIndexMap lpmask;
if (! (frame[0] & 0x01)) {
@@ -1020,44 +1221,27 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
lpmask = port->lpar_map;
}
- spin_lock_irqsave(&port->pending_gate, flags);
-
- lpmask = veth_transmit_to_many(skb, lpmask, dev);
-
- dev->trans_start = jiffies;
+ veth_transmit_to_many(skb, lpmask, dev);
- if (! lpmask) {
- dev_kfree_skb(skb);
- } else {
- if (port->pending_skb) {
- veth_error("%s: Tx while skb was pending!\n",
- dev->name);
- dev_kfree_skb(skb);
- spin_unlock_irqrestore(&port->pending_gate, flags);
- return 1;
- }
-
- port->pending_skb = skb;
- port->pending_lpmask = lpmask;
- netif_stop_queue(dev);
- }
-
- spin_unlock_irqrestore(&port->pending_gate, flags);
+ dev_kfree_skb(skb);
return 0;
}
+/* You must hold the connection's lock when you call this function. */
static void veth_recycle_msg(struct veth_lpar_connection *cnx,
struct veth_msg *msg)
{
u32 dma_address, dma_length;
- if (test_and_clear_bit(0, &msg->in_use)) {
+ if (msg->in_use) {
+ msg->in_use = 0;
dma_address = msg->data.addr[0];
dma_length = msg->data.len[0];
- dma_unmap_single(msg->dev, dma_address, dma_length,
- DMA_TO_DEVICE);
+ if (!dma_mapping_error(dma_address))
+ dma_unmap_single(msg->dev, dma_address, dma_length,
+ DMA_TO_DEVICE);
if (msg->skb) {
dev_kfree_skb_any(msg->skb);
@@ -1066,15 +1250,16 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx,
memset(&msg->data, 0, sizeof(msg->data));
veth_stack_push(cnx, msg);
- } else
- if (cnx->state & VETH_STATE_OPEN)
- veth_error("Bogus frames ack from lpar %d (#%d)\n",
- cnx->remote_lp, msg->token);
+ } else if (cnx->state & VETH_STATE_OPEN) {
+ veth_error("Non-pending frame (# %d) acked by LPAR %d.\n",
+ cnx->remote_lp, msg->token);
+ }
}
-static void veth_flush_pending(struct veth_lpar_connection *cnx)
+static void veth_wake_queues(struct veth_lpar_connection *cnx)
{
int i;
+
for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
struct net_device *dev = veth_dev[i];
struct veth_port *port;
@@ -1088,20 +1273,77 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx)
if (! (port->lpar_map & (1<<cnx->remote_lp)))
continue;
- spin_lock_irqsave(&port->pending_gate, flags);
- if (port->pending_skb) {
- port->pending_lpmask =
- veth_transmit_to_many(port->pending_skb,
- port->pending_lpmask,
- dev);
- if (! port->pending_lpmask) {
- dev_kfree_skb_any(port->pending_skb);
- port->pending_skb = NULL;
- netif_wake_queue(dev);
- }
+ spin_lock_irqsave(&port->queue_lock, flags);
+
+ port->stopped_map &= ~(1 << cnx->remote_lp);
+
+ if (0 == port->stopped_map && netif_queue_stopped(dev)) {
+ veth_debug("cnx %d: woke queue for %s.\n",
+ cnx->remote_lp, dev->name);
+ netif_wake_queue(dev);
+ }
+ spin_unlock_irqrestore(&port->queue_lock, flags);
+ }
+}
+
+static void veth_stop_queues(struct veth_lpar_connection *cnx)
+{
+ int i;
+
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+ struct net_device *dev = veth_dev[i];
+ struct veth_port *port;
+
+ if (! dev)
+ continue;
+
+ port = (struct veth_port *)dev->priv;
+
+ /* If this cnx is not on the vlan for this port, continue */
+ if (! (port->lpar_map & (1 << cnx->remote_lp)))
+ continue;
+
+ spin_lock(&port->queue_lock);
+
+ netif_stop_queue(dev);
+ port->stopped_map |= (1 << cnx->remote_lp);
+
+ veth_debug("cnx %d: stopped queue for %s, map = 0x%x.\n",
+ cnx->remote_lp, dev->name, port->stopped_map);
+
+ spin_unlock(&port->queue_lock);
+ }
+}
+
+static void veth_timed_reset(unsigned long ptr)
+{
+ struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)ptr;
+ unsigned long trigger_time, flags;
+
+ /* FIXME is it possible this fires after veth_stop_connection()?
+ * That would reschedule the statemachine for 5 seconds and probably
+ * execute it after the module's been unloaded. Hmm. */
+
+ spin_lock_irqsave(&cnx->lock, flags);
+
+ if (cnx->outstanding_tx > 0) {
+ trigger_time = cnx->last_contact + cnx->reset_timeout;
+
+ if (trigger_time < jiffies) {
+ cnx->state |= VETH_STATE_RESET;
+ veth_kick_statemachine(cnx);
+ veth_error("%d packets not acked by LPAR %d within %d "
+ "seconds, resetting.\n",
+ cnx->outstanding_tx, cnx->remote_lp,
+ cnx->reset_timeout / HZ);
+ } else {
+ /* Reschedule the timer */
+ trigger_time = jiffies + cnx->reset_timeout;
+ mod_timer(&cnx->reset_timer, trigger_time);
}
- spin_unlock_irqrestore(&port->pending_gate, flags);
}
+
+ spin_unlock_irqrestore(&cnx->lock, flags);
}
/*
@@ -1117,12 +1359,9 @@ static inline int veth_frame_wanted(struct veth_port *port, u64 mac_addr)
if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) )
return 1;
- if (! (((char *) &mac_addr)[0] & 0x01))
- return 0;
-
read_lock_irqsave(&port->mcast_gate, flags);
- if (port->promiscuous || port->all_mcast) {
+ if (port->promiscuous) {
wanted = 1;
goto out;
}
@@ -1175,21 +1414,21 @@ static void veth_flush_acks(struct veth_lpar_connection *cnx)
{
HvLpEvent_Rc rc;
- rc = veth_signaldata(cnx, VethEventTypeFramesAck,
+ rc = veth_signaldata(cnx, VETH_EVENT_FRAMES_ACK,
0, &cnx->pending_acks);
if (rc != HvLpEvent_Rc_Good)
- veth_error("Error 0x%x acking frames from lpar %d!\n",
- (unsigned)rc, cnx->remote_lp);
+ veth_error("Failed acking frames from LPAR %d, rc = %d\n",
+ cnx->remote_lp, (int)rc);
cnx->num_pending_acks = 0;
memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks));
}
static void veth_receive(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
- struct VethFramesData *senddata = &event->u.frames_data;
+ struct veth_frames_data *senddata = &event->u.frames_data;
int startchunk = 0;
int nchunks;
unsigned long flags;
@@ -1216,9 +1455,10 @@ static void veth_receive(struct veth_lpar_connection *cnx,
/* make sure that we have at least 1 EOF entry in the
* remaining entries */
if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) {
- veth_error("missing EOF frag in event "
- "eofmask=0x%x startchunk=%d\n",
- (unsigned) senddata->eofmask, startchunk);
+ veth_error("Missing EOF fragment in event "
+ "eofmask = 0x%x startchunk = %d\n",
+ (unsigned)senddata->eofmask,
+ startchunk);
break;
}
@@ -1237,8 +1477,9 @@ static void veth_receive(struct veth_lpar_connection *cnx,
/* nchunks == # of chunks in this frame */
if ((length - ETH_HLEN) > VETH_MAX_MTU) {
- veth_error("Received oversize frame from lpar %d "
- "(length=%d)\n", cnx->remote_lp, length);
+ veth_error("Received oversize frame from LPAR %d "
+ "(length = %d)\n",
+ cnx->remote_lp, length);
continue;
}
@@ -1331,15 +1572,33 @@ static void veth_timed_ack(unsigned long ptr)
static int veth_remove(struct vio_dev *vdev)
{
- int i = vdev->unit_address;
+ struct veth_lpar_connection *cnx;
struct net_device *dev;
+ struct veth_port *port;
+ int i;
- dev = veth_dev[i];
- if (dev != NULL) {
- veth_dev[i] = NULL;
- unregister_netdev(dev);
- free_netdev(dev);
+ dev = veth_dev[vdev->unit_address];
+
+ if (! dev)
+ return 0;
+
+ port = netdev_priv(dev);
+
+ for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
+ cnx = veth_cnx[i];
+
+ if (cnx && (port->lpar_map & (1 << i))) {
+ /* Drop our reference to connections on our VLAN */
+ kobject_put(&cnx->kobject);
+ }
}
+
+ veth_dev[vdev->unit_address] = NULL;
+ kobject_del(&port->kobject);
+ kobject_put(&port->kobject);
+ unregister_netdev(dev);
+ free_netdev(dev);
+
return 0;
}
@@ -1347,6 +1606,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
int i = vdev->unit_address;
struct net_device *dev;
+ struct veth_port *port;
dev = veth_probe_one(i, &vdev->dev);
if (dev == NULL) {
@@ -1355,11 +1615,23 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
veth_dev[i] = dev;
- /* Start the state machine on each connection, to commence
- * link negotiation */
- for (i = 0; i < HVMAXARCHITECTEDLPS; i++)
- if (veth_cnx[i])
- veth_kick_statemachine(veth_cnx[i]);
+ port = (struct veth_port*)netdev_priv(dev);
+
+ /* Start the state machine on each connection on this vlan. If we're
+ * the first dev to do so this will commence link negotiation */
+ for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
+ struct veth_lpar_connection *cnx;
+
+ if (! (port->lpar_map & (1 << i)))
+ continue;
+
+ cnx = veth_cnx[i];
+ if (!cnx)
+ continue;
+
+ kobject_get(&cnx->kobject);
+ veth_kick_statemachine(cnx);
+ }
return 0;
}
@@ -1370,12 +1642,12 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
*/
static struct vio_device_id veth_device_table[] __devinitdata = {
{ "vlan", "" },
- { NULL, NULL }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, veth_device_table);
static struct vio_driver veth_driver = {
- .name = "iseries_veth",
+ .name = DRV_NAME,
.id_table = veth_device_table,
.probe = veth_probe,
.remove = veth_remove
@@ -1388,29 +1660,29 @@ static struct vio_driver veth_driver = {
void __exit veth_module_cleanup(void)
{
int i;
+ struct veth_lpar_connection *cnx;
- /* Stop the queues first to stop any new packets being sent. */
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++)
- if (veth_dev[i])
- netif_stop_queue(veth_dev[i]);
-
- /* Stop the connections before we unregister the driver. This
- * ensures there's no skbs lying around holding the device open. */
- for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
- veth_stop_connection(i);
-
+ /* Disconnect our "irq" to stop events coming from the Hypervisor. */
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
- /* Hypervisor callbacks may have scheduled more work while we
- * were stoping connections. Now that we've disconnected from
- * the hypervisor make sure everything's finished. */
+ /* Make sure any work queued from Hypervisor callbacks is finished. */
flush_scheduled_work();
- vio_unregister_driver(&veth_driver);
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ cnx = veth_cnx[i];
+
+ if (!cnx)
+ continue;
- for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
- veth_destroy_connection(i);
+ /* Remove the connection from sysfs */
+ kobject_del(&cnx->kobject);
+ /* Drop the driver's reference to the connection */
+ kobject_put(&cnx->kobject);
+ }
+ /* Unregister the driver, which will close all the netdevs and stop
+ * the connections when they're no longer referenced. */
+ vio_unregister_driver(&veth_driver);
}
module_exit(veth_module_cleanup);
@@ -1423,15 +1695,37 @@ int __init veth_module_init(void)
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
rc = veth_init_connection(i);
- if (rc != 0) {
- veth_module_cleanup();
- return rc;
- }
+ if (rc != 0)
+ goto error;
}
HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan,
&veth_handle_event);
- return vio_register_driver(&veth_driver);
+ rc = vio_register_driver(&veth_driver);
+ if (rc != 0)
+ goto error;
+
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ struct kobject *kobj;
+
+ if (!veth_cnx[i])
+ continue;
+
+ kobj = &veth_cnx[i]->kobject;
+ kobj->parent = &veth_driver.driver.kobj;
+ /* If the add failes, complain but otherwise continue */
+ if (0 != kobject_add(kobj))
+ veth_error("cnx %d: Failed adding to sysfs.\n", i);
+ }
+
+ return 0;
+
+error:
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ veth_destroy_connection(veth_cnx[i]);
+ }
+
+ return rc;
}
module_init(veth_module_init);
diff --git a/drivers/net/iseries_veth.h b/drivers/net/iseries_veth.h
deleted file mode 100644
index d9370f79b83e..000000000000
--- a/drivers/net/iseries_veth.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* File veth.h created by Kyle A. Lucke on Mon Aug 7 2000. */
-
-#ifndef _ISERIES_VETH_H
-#define _ISERIES_VETH_H
-
-#define VethEventTypeCap (0)
-#define VethEventTypeFrames (1)
-#define VethEventTypeMonitor (2)
-#define VethEventTypeFramesAck (3)
-
-#define VETH_MAX_ACKS_PER_MSG (20)
-#define VETH_MAX_FRAMES_PER_MSG (6)
-
-struct VethFramesData {
- u32 addr[VETH_MAX_FRAMES_PER_MSG];
- u16 len[VETH_MAX_FRAMES_PER_MSG];
- u32 eofmask;
-};
-#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG)
-
-struct VethFramesAckData {
- u16 token[VETH_MAX_ACKS_PER_MSG];
-};
-
-struct VethCapData {
- u8 caps_version;
- u8 rsvd1;
- u16 num_buffers;
- u16 ack_threshold;
- u16 rsvd2;
- u32 ack_timeout;
- u32 rsvd3;
- u64 rsvd4[3];
-};
-
-struct VethLpEvent {
- struct HvLpEvent base_event;
- union {
- struct VethCapData caps_data;
- struct VethFramesData frames_data;
- struct VethFramesAckData frames_ack_data;
- } u;
-
-};
-
-#endif /* _ISERIES_VETH_H */
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index f8d3385c7842..c83271b38621 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -119,7 +119,7 @@ struct ixgb_adapter;
* so a DMA handle can be stored along with the buffer */
struct ixgb_buffer {
struct sk_buff *skb;
- uint64_t dma;
+ dma_addr_t dma;
unsigned long time_stamp;
uint16_t length;
uint16_t next_to_watch;
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 3aae110c5560..661a46b95a61 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -565,24 +565,6 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
}
}
-/******************************************************************************
- * return the compatibility flags from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * compatibility flags if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_compatibility(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->compatibility));
-
- return(0);
-}
/******************************************************************************
* return the Printed Board Assembly number from EEPROM
@@ -602,81 +584,6 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
return(0);
}
-/******************************************************************************
- * return the Initialization Control Word 1 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->init_ctrl_reg_1));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Initialization Control Word 2 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->init_ctrl_reg_2));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Subsystem Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Subsystem Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->subsystem_id));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Sub Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Sub Vendor Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->subvendor_id));
-
- return(0);
-}
/******************************************************************************
* return the Device Id from EEPROM
@@ -694,81 +601,6 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->device_id));
- return(0);
-}
-
-/******************************************************************************
- * return the Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Device Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->vendor_id));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Software Defined Pins Register from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * SDP Register if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->swdpins_reg));
-
- return(0);
+ return (0);
}
-/******************************************************************************
- * return the D3 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d3_power(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->d3_power));
-
- return(0);
-}
-
-/******************************************************************************
- * return the D0 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d0_power(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->d0_power));
-
- return(0);
-}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 3fa113854eeb..9d026ed77ddd 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -98,10 +98,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
static int
ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
- ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+ ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
@@ -120,7 +120,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
static int
ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
if(ecmd->autoneg == AUTONEG_ENABLE ||
ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
@@ -130,6 +130,12 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ixgb_down(adapter, TRUE);
ixgb_reset(adapter);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+
} else
ixgb_reset(adapter);
@@ -140,7 +146,7 @@ static void
ixgb_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
pause->autoneg = AUTONEG_DISABLE;
@@ -159,7 +165,7 @@ static int
ixgb_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
if(pause->autoneg == AUTONEG_ENABLE)
@@ -177,6 +183,11 @@ ixgb_set_pauseparam(struct net_device *netdev,
if(netif_running(adapter->netdev)) {
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
} else
ixgb_reset(adapter);
@@ -186,19 +197,26 @@ ixgb_set_pauseparam(struct net_device *netdev,
static uint32_t
ixgb_get_rx_csum(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
return adapter->rx_csum;
}
static int
ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
adapter->rx_csum = data;
if(netif_running(netdev)) {
ixgb_down(adapter,TRUE);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
} else
ixgb_reset(adapter);
return 0;
@@ -246,14 +264,15 @@ static void
ixgb_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint32_t *reg = p;
uint32_t *reg_start = reg;
uint8_t i;
/* the 1 (one) below indicates an attempt at versioning, if the
- * interface in ethtool or the driver this 1 should be incremented */
+ * interface in ethtool or the driver changes, this 1 should be
+ * incremented */
regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
/* General Registers */
@@ -283,7 +302,8 @@ ixgb_get_regs(struct net_device *netdev,
*reg++ = IXGB_READ_REG(hw, RAIDC); /* 19 */
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
- for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
+ /* there are 16 RAR entries in hardware, we only use 3 */
+ for(i = 0; i < 16; i++) {
*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
}
@@ -391,7 +411,7 @@ static int
ixgb_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
int i, max_len, first_word, last_word;
@@ -439,7 +459,7 @@ static int
ixgb_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
void *ptr;
@@ -497,7 +517,7 @@ static void
ixgb_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
strncpy(drvinfo->driver, ixgb_driver_name, 32);
strncpy(drvinfo->version, ixgb_driver_version, 32);
@@ -512,7 +532,7 @@ static void
ixgb_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
@@ -530,7 +550,7 @@ static int
ixgb_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
@@ -573,6 +593,11 @@ ixgb_set_ringparam(struct net_device *netdev,
adapter->tx_ring = tx_new;
if((err = ixgb_up(adapter)))
return err;
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
}
return 0;
@@ -607,7 +632,7 @@ ixgb_led_blink_callback(unsigned long data)
static int
ixgb_phys_id(struct net_device *netdev, uint32_t data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
@@ -643,7 +668,7 @@ static void
ixgb_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int i;
ixgb_update_stats(adapter);
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index 97898efe7cc8..8bcf31ed10c2 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -822,17 +822,8 @@ extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */
void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
-uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 097b90ccf575..5c555373adbe 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -29,6 +29,11 @@
#include "ixgb.h"
/* Change Log
+ * 1.0.96 04/19/05
+ * - Make needlessly global code static -- bunk@stusta.de
+ * - ethtool cleanup -- shemminger@osdl.org
+ * - Support for MODULE_VERSION -- linville@tuxdriver.com
+ * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
* 1.0.88 01/05/05
* - include fix to the condition that determines when to quit NAPI - Robert Olsson
* - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
@@ -47,10 +52,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-
-#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
+#define DRV_VERSION "1.0.100-k2"DRIVERNAPI
char ixgb_driver_version[] = DRV_VERSION;
-char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -145,10 +149,12 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
/* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */
-#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is
- pushed this many descriptors from head */
#define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0 /* chip considers prefech below
+ * this */
+#define RXDCTL_HTHRESH_DEFAULT 0 /* chip will only prefetch if tail
+ * is pushed this many descriptors
+ * from head */
/**
* ixgb_init_module - Driver Registration Routine
@@ -376,7 +382,7 @@ ixgb_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
@@ -512,7 +518,7 @@ static void __devexit
ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
@@ -583,7 +589,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
static int
ixgb_open(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int err;
/* allocate transmit descriptors */
@@ -626,7 +632,7 @@ err_setup_tx:
static int
ixgb_close(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE);
@@ -1017,7 +1023,7 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
static int
ixgb_set_mac(struct net_device *netdev, void *p)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
if(!is_valid_ether_addr(addr->sa_data))
@@ -1043,7 +1049,7 @@ ixgb_set_mac(struct net_device *netdev, void *p)
static void
ixgb_set_multi(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
uint32_t rctl;
@@ -1371,7 +1377,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
static int
ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
unsigned int first;
unsigned int tx_flags = 0;
unsigned long flags;
@@ -1425,7 +1431,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void
ixgb_tx_timeout(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
@@ -1434,7 +1440,7 @@ ixgb_tx_timeout(struct net_device *netdev)
static void
ixgb_tx_timeout_task(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
@@ -1451,7 +1457,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
static struct net_device_stats *
ixgb_get_stats(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
return &adapter->net_stats;
}
@@ -1467,7 +1473,7 @@ ixgb_get_stats(struct net_device *netdev)
static int
ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
@@ -1522,7 +1528,8 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
/* fix up multicast stats by removing broadcasts */
- multi -= bcast;
+ if(multi >= bcast)
+ multi -= bcast;
adapter->stats.mprcl += (multi & 0xFFFFFFFF);
adapter->stats.mprch += (multi >> 32);
@@ -1641,7 +1648,7 @@ static irqreturn_t
ixgb_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint32_t icr = IXGB_READ_REG(hw, ICR);
#ifndef CONFIG_IXGB_NAPI
@@ -1688,7 +1695,7 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
static int
ixgb_clean(struct net_device *netdev, int *budget)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
@@ -2017,7 +2024,7 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
static void
ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, rctl;
ixgb_irq_disable(adapter);
@@ -2055,7 +2062,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
static void
ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
/* add VID to filter table */
@@ -2069,7 +2076,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
static void
ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
ixgb_irq_disable(adapter);
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 7fec613e1675..8423cb6875f0 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -1,5 +1,10 @@
/*
- * sonic.c
+ * jazzsonic.c
+ *
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, and (from the mac68k project) introduced
+ * dhd's support for 16-bit cards.
*
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*
@@ -28,8 +33,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/bitops.h>
#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -44,22 +49,20 @@ static struct platform_device *jazz_sonic_device;
#define SONIC_MEM_SIZE 0x100
-#define SREGS_PAD(n) u16 n;
-
#include "sonic.h"
/*
* Macros to access SONIC registers
*/
-#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg))
+#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
#define SONIC_WRITE(reg,val) \
do { \
- *((volatile unsigned int *)base_addr+(reg)) = (val); \
+ *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \
} while (0)
-/* use 0 for production, 1 for verification, >2 for debug */
+/* use 0 for production, 1 for verification, >1 for debug */
#ifdef SONIC_DEBUG
static unsigned int sonic_debug = SONIC_DEBUG;
#else
@@ -85,18 +88,18 @@ static unsigned short known_revisions[] =
0xffff /* end of list */
};
-static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
- unsigned int irq)
+static int __init sonic_probe1(struct net_device *dev)
{
static unsigned version_printed;
unsigned int silicon_revision;
unsigned int val;
- struct sonic_local *lp;
+ struct sonic_local *lp = netdev_priv(dev);
int err = -ENODEV;
int i;
- if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
+ if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
return -EBUSY;
+
/*
* get the Silicon Revision ID. If this is one of the known
* one assume that we found a SONIC ethernet controller at
@@ -120,11 +123,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
if (sonic_debug && version_printed++ == 0)
printk(version);
- printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr);
-
- /* Fill in the 'dev' fields. */
- dev->base_addr = base_addr;
- dev->irq = irq;
+ printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
/*
* Put the sonic into software reset, then
@@ -138,84 +137,44 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
dev->dev_addr[i*2+1] = val >> 8;
}
- printk("HW Address ");
- for (i = 0; i < 6; i++) {
- printk("%2.2x", dev->dev_addr[i]);
- if (i<5)
- printk(":");
- }
-
- printk(" IRQ %d\n", irq);
-
err = -ENOMEM;
/* Initialize the device structure. */
- if (dev->priv == NULL) {
- /*
- * the memory be located in the same 64kb segment
- */
- lp = NULL;
- i = 0;
- do {
- lp = kmalloc(sizeof(*lp), GFP_KERNEL);
- if ((unsigned long) lp >> 16
- != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
- /* FIXME, free the memory later */
- kfree(lp);
- lp = NULL;
- }
- } while (lp == NULL && i++ < 20);
-
- if (lp == NULL) {
- printk("%s: couldn't allocate memory for descriptors\n",
- dev->name);
- goto out;
- }
- memset(lp, 0, sizeof(struct sonic_local));
-
- /* get the virtual dma address */
- lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
- if (lp->cda_laddr == ~0UL) {
- printk("%s: couldn't get DMA page entry for "
- "descriptors\n", dev->name);
- goto out1;
- }
-
- lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
- lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
- lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
-
- /* allocate receive buffer area */
- /* FIXME, maybe we should use skbs */
- lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL);
- if (!lp->rba) {
- printk("%s: couldn't allocate receive buffers\n",
- dev->name);
- goto out2;
- }
+ lp->dma_bitmode = SONIC_BITMODE32;
- /* get virtual dma address */
- lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba),
- SONIC_NUM_RRS * SONIC_RBSIZE);
- if (lp->rba_laddr == ~0UL) {
- printk("%s: couldn't get DMA page entry for receive "
- "buffers\n",dev->name);
- goto out3;
- }
-
- /* now convert pointer to KSEG1 pointer */
- lp->rba = (char *)KSEG1ADDR(lp->rba);
- flush_cache_all();
- dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+ /* Allocate the entire chunk of memory for the descriptors.
+ Note that this cannot cross a 64K boundary. */
+ if ((lp->descriptors = dma_alloc_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
+ goto out;
}
- lp = (struct sonic_local *)dev->priv;
+ /* Now set up the pointers to point to the appropriate places */
+ lp->cda = lp->descriptors;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ lp->cda_laddr = lp->descriptors_laddr;
+ lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
dev->open = sonic_open;
dev->stop = sonic_close;
dev->hard_start_xmit = sonic_send_packet;
- dev->get_stats = sonic_get_stats;
+ dev->get_stats = sonic_get_stats;
dev->set_multicast_list = &sonic_multicast_list;
+ dev->tx_timeout = sonic_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
/*
@@ -226,14 +185,8 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
SONIC_WRITE(SONIC_MPT,0xffff);
return 0;
-out3:
- kfree(lp->rba);
-out2:
- vdma_free(lp->cda_laddr);
-out1:
- kfree(lp);
out:
- release_region(base_addr, SONIC_MEM_SIZE);
+ release_region(dev->base_addr, SONIC_MEM_SIZE);
return err;
}
@@ -245,7 +198,6 @@ static int __init jazz_sonic_probe(struct device *device)
{
struct net_device *dev;
struct sonic_local *lp;
- unsigned long base_addr;
int err = 0;
int i;
@@ -255,21 +207,26 @@ static int __init jazz_sonic_probe(struct device *device)
if (mips_machgroup != MACH_GROUP_JAZZ)
return -ENODEV;
- dev = alloc_etherdev(0);
+ dev = alloc_etherdev(sizeof(struct sonic_local));
if (!dev)
return -ENOMEM;
+ lp = netdev_priv(dev);
+ lp->device = device;
+ SET_NETDEV_DEV(dev, device);
+ SET_MODULE_OWNER(dev);
+
netdev_boot_setup_check(dev);
- base_addr = dev->base_addr;
- if (base_addr >= KSEG0) { /* Check a single specified location. */
- err = sonic_probe1(dev, base_addr, dev->irq);
- } else if (base_addr != 0) { /* Don't probe at all. */
+ if (dev->base_addr >= KSEG0) { /* Check a single specified location. */
+ err = sonic_probe1(dev);
+ } else if (dev->base_addr != 0) { /* Don't probe at all. */
err = -ENXIO;
} else {
for (i = 0; sonic_portlist[i].port; i++) {
- int io = sonic_portlist[i].port;
- if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
+ dev->base_addr = sonic_portlist[i].port;
+ dev->irq = sonic_portlist[i].irq;
+ if (sonic_probe1(dev) == 0)
break;
}
if (!sonic_portlist[i].port)
@@ -281,14 +238,17 @@ static int __init jazz_sonic_probe(struct device *device)
if (err)
goto out1;
+ printk("%s: MAC ", dev->name);
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ printk(" IRQ %d\n", dev->irq);
+
return 0;
out1:
- lp = dev->priv;
- vdma_free(lp->rba_laddr);
- kfree(lp->rba);
- vdma_free(lp->cda_laddr);
- kfree(lp);
release_region(dev->base_addr, SONIC_MEM_SIZE);
out:
free_netdev(dev);
@@ -296,21 +256,22 @@ out:
return err;
}
-/*
- * SONIC uses a normal IRQ
- */
-#define sonic_request_irq request_irq
-#define sonic_free_irq free_irq
+MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
+MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
-#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x))
+#define SONIC_IRQ_FLAG SA_INTERRUPT
#include "sonic.c"
static int __devexit jazz_sonic_device_remove (struct device *device)
{
struct net_device *dev = device->driver_data;
+ struct sonic_local* lp = netdev_priv(dev);
unregister_netdev (dev);
+ dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ lp->descriptors, lp->descriptors_laddr);
release_region (dev->base_addr, SONIC_MEM_SIZE);
free_netdev (dev);
@@ -323,7 +284,7 @@ static struct device_driver jazz_sonic_driver = {
.probe = jazz_sonic_probe,
.remove = __devexit_p(jazz_sonic_device_remove),
};
-
+
static void jazz_sonic_platform_release (struct device *device)
{
struct platform_device *pldev;
@@ -336,10 +297,11 @@ static void jazz_sonic_platform_release (struct device *device)
static int __init jazz_sonic_init_module(void)
{
struct platform_device *pldev;
+ int err;
- if (driver_register(&jazz_sonic_driver)) {
+ if ((err = driver_register(&jazz_sonic_driver))) {
printk(KERN_ERR "Driver registration failed\n");
- return -ENOMEM;
+ return err;
}
jazz_sonic_device = NULL;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 1f61f0cc95d8..690a1aae0b34 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -68,6 +68,7 @@ static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
* of largesending device modulo TCP checksum, which is ignored for loopback.
*/
+#ifdef LOOPBACK_TSO
static void emulate_large_send_offload(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
@@ -119,6 +120,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
dev_kfree_skb(skb);
}
+#endif /* LOOPBACK_TSO */
/*
* The higher levels take care of making this non-reentrant (it's
@@ -130,12 +132,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
skb_orphan(skb);
- skb->protocol=eth_type_trans(skb,dev);
- skb->dev=dev;
+ skb->protocol = eth_type_trans(skb,dev);
+ skb->dev = dev;
#ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif
+#ifdef LOOPBACK_TSO
if (skb_shinfo(skb)->tso_size) {
BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
@@ -143,14 +146,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
emulate_large_send_offload(skb);
return 0;
}
-
+#endif
dev->last_rx = jiffies;
lb_stats = &per_cpu(loopback_stats, get_cpu());
lb_stats->rx_bytes += skb->len;
- lb_stats->tx_bytes += skb->len;
+ lb_stats->tx_bytes = lb_stats->rx_bytes;
lb_stats->rx_packets++;
- lb_stats->tx_packets++;
+ lb_stats->tx_packets = lb_stats->rx_packets;
put_cpu();
netif_rx(skb);
@@ -208,9 +211,12 @@ struct net_device loopback_dev = {
.type = ARPHRD_LOOPBACK, /* 0x0001*/
.rebuild_header = eth_rebuild_header,
.flags = IFF_LOOPBACK,
- .features = NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
- |NETIF_F_LLTX,
+ .features = NETIF_F_SG | NETIF_F_FRAGLIST
+#ifdef LOOPBACK_TSO
+ | NETIF_F_TSO
+#endif
+ | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
+ | NETIF_F_LLTX,
.ethtool_ops = &loopback_ethtool_ops,
};
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index be28c65de729..405e18365ede 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -1,6 +1,12 @@
/*
* macsonic.c
*
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, converted to unified driver model, made it work as
+ * a module again, and from the mac68k project, introduced more 32-bit cards
+ * and dhd's support for 16-bit cards.
+ *
* (C) 1998 Alan Cox
*
* Debugging Andreas Ehliar, Michael Schmitz
@@ -26,8 +32,8 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/types.h>
-#include <linux/ctype.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -41,8 +47,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -54,25 +60,28 @@
#include <asm/macints.h>
#include <asm/mac_via.h>
-#define SREGS_PAD(n) u16 n;
+static char mac_sonic_string[] = "macsonic";
+static struct platform_device *mac_sonic_device;
#include "sonic.h"
-#define SONIC_READ(reg) \
- nubus_readl(base_addr+(reg))
-#define SONIC_WRITE(reg,val) \
- nubus_writel((val), base_addr+(reg))
-#define sonic_read(dev, reg) \
- nubus_readl((dev)->base_addr+(reg))
-#define sonic_write(dev, reg, val) \
- nubus_writel((val), (dev)->base_addr+(reg))
-
+/* These should basically be bus-size and endian independent (since
+ the SONIC is at least smart enough that it uses the same endianness
+ as the host, unlike certain less enlightened Macintosh NICs) */
+#define SONIC_READ(reg) (nubus_readw(dev->base_addr + (reg * 4) \
+ + lp->reg_offset))
+#define SONIC_WRITE(reg,val) (nubus_writew(val, dev->base_addr + (reg * 4) \
+ + lp->reg_offset))
+
+/* use 0 for production, 1 for verification, >1 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else
+static unsigned int sonic_debug = 1;
+#endif
-static int sonic_debug;
static int sonic_version_printed;
-static int reg_offset;
-
extern int mac_onboard_sonic_probe(struct net_device* dev);
extern int mac_nubus_sonic_probe(struct net_device* dev);
@@ -108,40 +117,6 @@ enum macsonic_type {
#define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)
-struct net_device * __init macsonic_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(0);
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0)
- sprintf(dev->name, "eth%d", unit);
-
- SET_MODULE_OWNER(dev);
-
- /* This will catch fatal stuff like -ENOMEM as well as success */
- err = mac_onboard_sonic_probe(dev);
- if (err == 0)
- goto found;
- if (err != -ENODEV)
- goto out;
- err = mac_nubus_sonic_probe(dev);
- if (err)
- goto out;
-found:
- err = register_netdev(dev);
- if (err)
- goto out1;
- return dev;
-out1:
- kfree(dev->priv);
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* For reversing the PROM address
*/
@@ -160,103 +135,55 @@ static inline void bit_reverse_addr(unsigned char addr[6])
int __init macsonic_init(struct net_device* dev)
{
- struct sonic_local* lp = NULL;
- int i;
+ struct sonic_local* lp = netdev_priv(dev);
/* Allocate the entire chunk of memory for the descriptors.
Note that this cannot cross a 64K boundary. */
- for (i = 0; i < 20; i++) {
- unsigned long desc_base, desc_top;
- if((lp = kmalloc(sizeof(struct sonic_local), GFP_KERNEL | GFP_DMA)) == NULL) {
- printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
- return -ENOMEM;
- }
-
- desc_base = (unsigned long) lp;
- desc_top = desc_base + sizeof(struct sonic_local);
- if ((desc_top & 0xffff) >= (desc_base & 0xffff))
- break;
- /* Hmm. try again (FIXME: does this actually work?) */
- kfree(lp);
- printk(KERN_DEBUG
- "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
- dev->name, desc_base, desc_top);
- }
-
- if (lp == NULL) {
- printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
- dev->name);
+ if ((lp->descriptors = dma_alloc_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
return -ENOMEM;
- }
-
- dev->priv = lp;
-
-#if 0
- /* this code is only here as a curiousity... mainly, where the
- fuck did SONIC_BUS_SCALE come from, and what was it supposed
- to do? the normal allocation works great for 32 bit stuffs.. */
+ }
/* Now set up the pointers to point to the appropriate places */
- lp->cda = lp->sonic_desc;
- lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->cda = lp->descriptors;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
- * SONIC_BUS_SCALE(lp->dma_bitmode));
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
- * SONIC_BUS_SCALE(lp->dma_bitmode));
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
-#endif
-
- memset(lp, 0, sizeof(struct sonic_local));
-
- lp->cda_laddr = (unsigned int)&(lp->cda);
- lp->tda_laddr = (unsigned int)lp->tda;
- lp->rra_laddr = (unsigned int)lp->rra;
- lp->rda_laddr = (unsigned int)lp->rda;
-
- /* FIXME, maybe we should use skbs */
- if ((lp->rba = (char *)
- kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
- printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
- dev->priv = NULL;
- kfree(lp);
- return -ENOMEM;
- }
-
- lp->rba_laddr = (unsigned int)lp->rba;
-
- {
- int rs, ds;
-
- /* almost always 12*4096, but let's not take chances */
- rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
- /* almost always under a page, but let's not take chances */
- ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096;
- kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
- kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER);
- }
-
-#if 0
- flush_cache_all();
-#endif
+ lp->cda_laddr = lp->descriptors_laddr;
+ lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
dev->open = sonic_open;
dev->stop = sonic_close;
dev->hard_start_xmit = sonic_send_packet;
dev->get_stats = sonic_get_stats;
dev->set_multicast_list = &sonic_multicast_list;
+ dev->tx_timeout = sonic_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/*
* clear tally counter
*/
- sonic_write(dev, SONIC_CRCT, 0xffff);
- sonic_write(dev, SONIC_FAET, 0xffff);
- sonic_write(dev, SONIC_MPT, 0xffff);
+ SONIC_WRITE(SONIC_CRCT, 0xffff);
+ SONIC_WRITE(SONIC_FAET, 0xffff);
+ SONIC_WRITE(SONIC_MPT, 0xffff);
return 0;
}
int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
{
+ struct sonic_local *lp = netdev_priv(dev);
const int prom_addr = ONBOARD_SONIC_PROM_BASE;
int i;
@@ -270,6 +197,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
why this is so. */
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
bit_reverse_addr(dev->dev_addr);
else
@@ -281,22 +209,23 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
the card... */
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
{
unsigned short val;
printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_CEP, 15);
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ SONIC_WRITE(SONIC_CEP, 15);
- val = sonic_read(dev, SONIC_CAP2);
+ val = SONIC_READ(SONIC_CAP2);
dev->dev_addr[5] = val >> 8;
dev->dev_addr[4] = val & 0xff;
- val = sonic_read(dev, SONIC_CAP1);
+ val = SONIC_READ(SONIC_CAP1);
dev->dev_addr[3] = val >> 8;
dev->dev_addr[2] = val & 0xff;
- val = sonic_read(dev, SONIC_CAP0);
+ val = SONIC_READ(SONIC_CAP0);
dev->dev_addr[1] = val >> 8;
dev->dev_addr[0] = val & 0xff;
@@ -311,6 +240,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
{
/*
@@ -325,8 +255,9 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
{
/* Bwahahaha */
static int once_is_more_than_enough;
- int i;
- int dma_bitmode;
+ struct sonic_local* lp = netdev_priv(dev);
+ int sr;
+ int commslot = 0;
if (once_is_more_than_enough)
return -ENODEV;
@@ -335,20 +266,18 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
if (!MACH_IS_MAC)
return -ENODEV;
- printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
-
if (macintosh_config->ether_type != MAC_ETHER_SONIC)
- {
- printk("none.\n");
return -ENODEV;
- }
-
+
+ printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
+
/* Bogus probing, on the models which may or may not have
Ethernet (BTW, the Ethernet *is* always at the same
address, and nothing else lives there, at least if Apple's
documentation is to be believed) */
if (macintosh_config->ident == MAC_MODEL_Q630 ||
macintosh_config->ident == MAC_MODEL_P588 ||
+ macintosh_config->ident == MAC_MODEL_P575 ||
macintosh_config->ident == MAC_MODEL_C610) {
unsigned long flags;
int card_present;
@@ -361,13 +290,13 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
printk("none.\n");
return -ENODEV;
}
+ commslot = 1;
}
printk("yes\n");
- /* Danger! My arms are flailing wildly! You *must* set this
- before using sonic_read() */
-
+ /* Danger! My arms are flailing wildly! You *must* set lp->reg_offset
+ * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
dev->base_addr = ONBOARD_SONIC_REGISTERS;
if (via_alt_mapping)
dev->irq = IRQ_AUTO_3;
@@ -379,84 +308,66 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
sonic_version_printed = 1;
}
printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
- dev->name, dev->base_addr);
-
- /* Now do a song and dance routine in an attempt to determine
- the bus width */
+ lp->device->bus_id, dev->base_addr);
/* The PowerBook's SONIC is 16 bit always. */
if (macintosh_config->ident == MAC_MODEL_PB520) {
- reg_offset = 0;
- dma_bitmode = 0;
- } else if (macintosh_config->ident == MAC_MODEL_C610) {
- reg_offset = 0;
- dma_bitmode = 1;
- } else {
+ lp->reg_offset = 0;
+ lp->dma_bitmode = SONIC_BITMODE16;
+ sr = SONIC_READ(SONIC_SR);
+ } else if (commslot) {
/* Some of the comm-slot cards are 16 bit. But some
- of them are not. The 32-bit cards use offset 2 and
- pad with zeroes or sometimes ones (I think...)
- Therefore, if we try offset 0 and get a silicon
- revision of 0, we assume 16 bit. */
- int sr;
-
- /* Technically this is not necessary since we zeroed
- it above */
- reg_offset = 0;
- dma_bitmode = 0;
- sr = sonic_read(dev, SONIC_SR);
- if (sr == 0 || sr == 0xffff) {
- reg_offset = 2;
- /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
- sr = sonic_read(dev, SONIC_SR);
- dma_bitmode = 1;
-
+ of them are not. The 32-bit cards use offset 2 and
+ have known revisions, we try reading the revision
+ register at offset 2, if we don't get a known revision
+ we assume 16 bit at offset 0. */
+ lp->reg_offset = 2;
+ lp->dma_bitmode = SONIC_BITMODE16;
+
+ sr = SONIC_READ(SONIC_SR);
+ if (sr == 0x0004 || sr == 0x0006 || sr == 0x0100 || sr == 0x0101)
+ /* 83932 is 0x0004 or 0x0006, 83934 is 0x0100 or 0x0101 */
+ lp->dma_bitmode = SONIC_BITMODE32;
+ else {
+ lp->dma_bitmode = SONIC_BITMODE16;
+ lp->reg_offset = 0;
+ sr = SONIC_READ(SONIC_SR);
}
- printk(KERN_INFO
- "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
- dev->name, sr, dma_bitmode?32:16, reg_offset);
+ } else {
+ /* All onboard cards are at offset 2 with 32 bit DMA. */
+ lp->reg_offset = 2;
+ lp->dma_bitmode = SONIC_BITMODE32;
+ sr = SONIC_READ(SONIC_SR);
}
-
+ printk(KERN_INFO
+ "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset);
- /* this carries my sincere apologies -- by the time I got to updating
- the driver, support for "reg_offsets" appeares nowhere in the sonic
- code, going back for over a year. Fortunately, my Mac does't seem
- to use whatever this was.
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+ printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+ SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
- If you know how this is supposed to be implemented, either fix it,
- or contact me (sammy@oh.verio.com) to explain what it is. --Sam */
-
- if(reg_offset) {
- printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name);
- return -ENODEV;
- }
-
/* Software reset, then initialize control registers. */
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
- SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
- (dma_bitmode ? SONIC_DCR_DW : 0));
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+
+ SONIC_WRITE(SONIC_DCR, SONIC_DCR_EXBUS | SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ (lp->dma_bitmode ? SONIC_DCR_DW : 0));
/* This *must* be written back to in order to restore the
- extended programmable output bits */
- sonic_write(dev, SONIC_DCR2, 0);
+ * extended programmable output bits, as it may not have been
+ * initialised since the hardware reset. */
+ SONIC_WRITE(SONIC_DCR2, 0);
/* Clear *and* disable interrupts to be on the safe side */
- sonic_write(dev, SONIC_ISR,0x7fff);
- sonic_write(dev, SONIC_IMR,0);
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
/* Now look for the MAC address. */
if (mac_onboard_sonic_ethernet_addr(dev) != 0)
return -ENODEV;
- printk(KERN_INFO "MAC ");
- for (i = 0; i < 6; i++) {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
-
- printk(" IRQ %d\n", dev->irq);
-
/* Shared init code */
return macsonic_init(dev);
}
@@ -468,8 +379,10 @@ int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
int i;
for(i = 0; i < 6; i++)
dev->dev_addr[i] = SONIC_READ_PROM(i);
- /* For now we are going to assume that they're all bit-reversed */
- bit_reverse_addr(dev->dev_addr);
+
+ /* Some of the addresses are bit-reversed */
+ if (id != MACSONIC_DAYNA)
+ bit_reverse_addr(dev->dev_addr);
return 0;
}
@@ -487,6 +400,15 @@ int __init macsonic_ident(struct nubus_dev* ndev)
else
return MACSONIC_APPLE;
}
+
+ if (ndev->dr_hw == NUBUS_DRHW_SMC9194 &&
+ ndev->dr_sw == NUBUS_DRSW_DAYNA)
+ return MACSONIC_DAYNA;
+
+ if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
+ ndev->dr_sw == 0) { /* huh? */
+ return MACSONIC_APPLE16;
+ }
return -1;
}
@@ -494,12 +416,12 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
{
static int slots;
struct nubus_dev* ndev = NULL;
+ struct sonic_local* lp = netdev_priv(dev);
unsigned long base_addr, prom_addr;
u16 sonic_dcr;
- int id;
- int i;
- int dma_bitmode;
-
+ int id = -1;
+ int reg_offset, dma_bitmode;
+
/* Find the first SONIC that hasn't been initialized already */
while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
NUBUS_TYPE_ETHERNET, ndev)) != NULL)
@@ -521,51 +443,52 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
case MACSONIC_DUODOCK:
base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
- sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1
- | SONIC_DCR_TFT0;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1 |
+ SONIC_DCR_TFT0;
reg_offset = 2;
- dma_bitmode = 1;
+ dma_bitmode = SONIC_BITMODE32;
break;
case MACSONIC_APPLE:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
reg_offset = 0;
- dma_bitmode = 1;
+ dma_bitmode = SONIC_BITMODE32;
break;
case MACSONIC_APPLE16:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
- sonic_dcr = SONIC_DCR_EXBUS
- | SONIC_DCR_RFT1 | SONIC_DCR_TFT0
- | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ SONIC_DCR_PO1 | SONIC_DCR_BMS;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
case MACSONIC_DAYNALINK:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
- sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0
- | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ SONIC_DCR_PO1 | SONIC_DCR_BMS;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
case MACSONIC_DAYNA:
base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
- sonic_dcr = SONIC_DCR_BMS
- | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
+ sonic_dcr = SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
default:
printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
return -ENODEV;
}
- /* Danger! My arms are flailing wildly! You *must* set this
- before using sonic_read() */
+ /* Danger! My arms are flailing wildly! You *must* set lp->reg_offset
+ * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
dev->base_addr = base_addr;
+ lp->reg_offset = reg_offset;
+ lp->dma_bitmode = dma_bitmode;
dev->irq = SLOT2IRQ(ndev->board->slot);
if (!sonic_version_printed) {
@@ -573,29 +496,66 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
sonic_version_printed = 1;
}
printk(KERN_INFO "%s: %s in slot %X\n",
- dev->name, ndev->board->name, ndev->board->slot);
+ lp->device->bus_id, ndev->board->name, ndev->board->slot);
printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
- dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
+ lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
- if(reg_offset) {
- printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name);
- return -ENODEV;
- }
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+ printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+ SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
/* Software reset, then initialize control registers. */
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_DCR, sonic_dcr
- | (dma_bitmode ? SONIC_DCR_DW : 0));
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ SONIC_WRITE(SONIC_DCR, sonic_dcr | (dma_bitmode ? SONIC_DCR_DW : 0));
+ /* This *must* be written back to in order to restore the
+ * extended programmable output bits, since it may not have been
+ * initialised since the hardware reset. */
+ SONIC_WRITE(SONIC_DCR2, 0);
/* Clear *and* disable interrupts to be on the safe side */
- sonic_write(dev, SONIC_ISR,0x7fff);
- sonic_write(dev, SONIC_IMR,0);
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
/* Now look for the MAC address. */
if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
return -ENODEV;
- printk(KERN_INFO "MAC ");
+ /* Shared init code */
+ return macsonic_init(dev);
+}
+
+static int __init mac_sonic_probe(struct device *device)
+{
+ struct net_device *dev;
+ struct sonic_local *lp;
+ int err;
+ int i;
+
+ dev = alloc_etherdev(sizeof(struct sonic_local));
+ if (!dev)
+ return -ENOMEM;
+
+ lp = netdev_priv(dev);
+ lp->device = device;
+ SET_NETDEV_DEV(dev, device);
+ SET_MODULE_OWNER(dev);
+
+ /* This will catch fatal stuff like -ENOMEM as well as success */
+ err = mac_onboard_sonic_probe(dev);
+ if (err == 0)
+ goto found;
+ if (err != -ENODEV)
+ goto out;
+ err = mac_nubus_sonic_probe(dev);
+ if (err)
+ goto out;
+found:
+ err = register_netdev(dev);
+ if (err)
+ goto out;
+
+ printk("%s: MAC ", dev->name);
for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i < 5)
@@ -603,55 +563,95 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
}
printk(" IRQ %d\n", dev->irq);
- /* Shared init code */
- return macsonic_init(dev);
-}
+ return 0;
-#ifdef MODULE
-static struct net_device *dev_macsonic;
+out:
+ free_netdev(dev);
-MODULE_PARM(sonic_debug, "i");
+ return err;
+}
+
+MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
-int
-init_module(void)
+#define SONIC_IRQ_FLAG IRQ_FLG_FAST
+
+#include "sonic.c"
+
+static int __devexit mac_sonic_device_remove (struct device *device)
{
- dev_macsonic = macsonic_probe(-1);
- if (IS_ERR(dev_macsonic)) {
- printk(KERN_WARNING "macsonic.c: No card found\n");
- return PTR_ERR(dev_macsonic);
- }
+ struct net_device *dev = device->driver_data;
+ struct sonic_local* lp = netdev_priv(dev);
+
+ unregister_netdev (dev);
+ dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ lp->descriptors, lp->descriptors_laddr);
+ free_netdev (dev);
+
return 0;
}
-void
-cleanup_module(void)
+static struct device_driver mac_sonic_driver = {
+ .name = mac_sonic_string,
+ .bus = &platform_bus_type,
+ .probe = mac_sonic_probe,
+ .remove = __devexit_p(mac_sonic_device_remove),
+};
+
+static void mac_sonic_platform_release(struct device *device)
{
- unregister_netdev(dev_macsonic);
- kfree(dev_macsonic->priv);
- free_netdev(dev_macsonic);
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device (device);
+ kfree (pldev);
}
-#endif /* MODULE */
+static int __init mac_sonic_init_module(void)
+{
+ struct platform_device *pldev;
+ int err;
-#define vdma_alloc(foo, bar) ((u32)foo)
-#define vdma_free(baz)
-#define sonic_chiptomem(bat) (bat)
-#define PHYSADDR(quux) (quux)
-#define CPHYSADDR(quux) (quux)
+ if ((err = driver_register(&mac_sonic_driver))) {
+ printk(KERN_ERR "Driver registration failed\n");
+ return err;
+ }
-#define sonic_request_irq request_irq
-#define sonic_free_irq free_irq
+ mac_sonic_device = NULL;
-#include "sonic.c"
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+ goto out_unregister;
+ }
-/*
- * Local variables:
- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o macsonic.o macsonic.c"
- * version-control: t
- * kept-new-versions: 5
- * c-indent-level: 8
- * tab-width: 8
- * End:
- *
- */
+ memset(pldev, 0, sizeof (*pldev));
+ pldev->name = mac_sonic_string;
+ pldev->id = 0;
+ pldev->dev.release = mac_sonic_platform_release;
+ mac_sonic_device = pldev;
+
+ if (platform_device_register (pldev)) {
+ kfree(pldev);
+ mac_sonic_device = NULL;
+ }
+
+ return 0;
+
+out_unregister:
+ platform_device_unregister(pldev);
+
+ return -ENOMEM;
+}
+
+static void __exit mac_sonic_cleanup_module(void)
+{
+ driver_unregister(&mac_sonic_driver);
+
+ if (mac_sonic_device) {
+ platform_device_unregister(mac_sonic_device);
+ mac_sonic_device = NULL;
+ }
+}
+
+module_init(mac_sonic_init_module);
+module_exit(mac_sonic_cleanup_module);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 0405e1f0d3df..25c9a99c377b 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -58,11 +58,10 @@
#define INT_CAUSE_UNMASK_ALL 0x0007ffff
#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
#define INT_CAUSE_MASK_ALL 0x00000000
+#define INT_CAUSE_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
-#endif
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
@@ -95,7 +94,7 @@ static char mv643xx_driver_version[] = "1.0";
static void __iomem *mv643xx_eth_shared_base;
/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
-static spinlock_t mv643xx_eth_phy_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
static inline u32 mv_read(int offset)
{
@@ -259,14 +258,13 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev)
static void mv643xx_eth_set_rx_mode(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
- u32 config_reg;
- config_reg = ethernet_get_config_reg(mp->port_num);
if (dev->flags & IFF_PROMISC)
- config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
else
- config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
- ethernet_set_config_reg(mp->port_num, config_reg);
+ mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+
+ mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
}
/*
@@ -369,15 +367,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
-
- /*
- * Decrement the number of outstanding skbs counter on
- * the TX queue.
- */
- if (mp->tx_ring_skbs == 0)
- panic("ERROR - TX outstanding SKBs"
- " counter is corrupted");
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -412,15 +401,13 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
struct pkt_info pkt_info;
#ifdef MV643XX_NAPI
- while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+ while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
#else
while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
#endif
mp->rx_ring_skbs--;
received_packets++;
-#ifdef MV643XX_NAPI
- budget--;
-#endif
+
/* Update statistics. Note byte count includes 4 byte CRC count */
stats->rx_packets++;
stats->rx_bytes += pkt_info.byte_cnt;
@@ -1044,9 +1031,6 @@ static void mv643xx_tx(struct net_device *dev)
DMA_TO_DEVICE);
dev_kfree_skb_irq(pkt_info.return_info);
-
- if (mp->tx_ring_skbs)
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -1157,16 +1141,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_shinfo(skb)->nr_frags) {
linear:
if (skb->ip_summed != CHECKSUM_HW) {
+ /* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+ ETH_TX_FIRST_DESC |
+ ETH_TX_LAST_DESC |
+ 5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
- u32 ipheader = skb->nh.iph->ihl << 11;
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
- ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ ETH_TX_FIRST_DESC |
+ ETH_TX_LAST_DESC |
+ ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM |
+ skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1185,7 +1173,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1193,7 +1180,6 @@ linear:
stats->tx_bytes += pkt_info.byte_cnt;
} else {
unsigned int frag;
- u32 ipheader;
/* Since hardware can't handle unaligned fragments smaller
* than 9 bytes, if we find any, we linearize the skb
@@ -1222,12 +1208,16 @@ linear:
DMA_TO_DEVICE);
pkt_info.l4i_chk = 0;
pkt_info.return_info = 0;
- pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
- if (skb->ip_summed == CHECKSUM_HW) {
- ipheader = skb->nh.iph->ihl << 11;
- pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ if (skb->ip_summed != CHECKSUM_HW)
+ /* Errata BTS #50, IHL must be 5 if no HW checksum */
+ pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+ 5 << ETH_TX_IHL_SHIFT;
+ else {
+ pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+ ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM |
+ skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1267,7 +1257,6 @@ linear:
pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
ETH_TX_LAST_DESC;
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
} else {
pkt_info.return_info = 0;
}
@@ -1304,7 +1293,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1349,6 +1337,43 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
return &mp->stats;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void mv643xx_netpoll(struct net_device *netdev)
+{
+ struct mv643xx_private *mp = netdev_priv(netdev);
+
+ mv643xx_disable_irq(mp);
+ mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
+ mv643xx_enable_irq(mp);
+}
+#endif
+
/*/
* mv643xx_eth_probe
*
@@ -1399,6 +1424,10 @@ static int mv643xx_eth_probe(struct device *ddev)
dev->weight = 64;
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = mv643xx_netpoll;
+#endif
+
dev->watchdog_timeo = 2 * HZ;
dev->tx_queue_len = mp->tx_ring_size;
dev->base_addr = 0;
@@ -1876,6 +1905,9 @@ static void eth_port_start(struct mv643xx_private *mp)
/* Enable port Rx. */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
mp->port_rx_queue_command);
+
+ /* Disable port bandwidth limits by clearing MTU register */
+ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
}
/*
@@ -2285,34 +2317,6 @@ static void eth_port_reset(unsigned int port_num)
mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
-/*
- * ethernet_set_config_reg - Set specified bits in configuration register.
- *
- * DESCRIPTION:
- * This function sets specified bits in the given ethernet
- * configuration register.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int value 32 bit value.
- *
- * OUTPUT:
- * The set bits in the value parameter are set in the configuration
- * register.
- *
- * RETURN:
- * None.
- *
- */
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
- eth_config_reg |= value;
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
-}
static int eth_port_autoneg_supported(unsigned int eth_port_num)
{
@@ -2339,31 +2343,6 @@ static int eth_port_link_is_up(unsigned int eth_port_num)
}
/*
- * ethernet_get_config_reg - Get the port configuration register
- *
- * DESCRIPTION:
- * This function returns the configuration register value of the given
- * ethernet port.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- *
- * OUTPUT:
- * None.
- *
- * RETURN:
- * Port configuration register value.
- */
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
- (eth_port_num));
- return eth_config_reg;
-}
-
-/*
* eth_port_read_smi_reg - Read PHY registers
*
* DESCRIPTION:
@@ -2521,6 +2500,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
return ETH_ERROR;
}
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2587,6 +2569,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2687,6 +2672,9 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
/* Any Tx return cancels the Tx resource error status */
mp->tx_resource_err = 0;
+ BUG_ON(mp->tx_ring_skbs == 0);
+ mp->tx_ring_skbs--;
+
return ETH_OK;
}
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
index 57c4f8fbfdb6..bcfda5192da0 100644
--- a/drivers/net/mv643xx_eth.h
+++ b/drivers/net/mv643xx_eth.h
@@ -49,7 +49,7 @@
/* Checksum offload for Tx works for most packets, but
* fails if previous packet sent did not use hw csum
*/
-#undef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MV643XX_CHECKSUM_OFFLOAD_TX
#define MV643XX_NAPI
#define MV643XX_TX_FAST_REFILL
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
@@ -217,6 +217,8 @@
#define ETH_TX_ENABLE_INTERRUPT (BIT23)
#define ETH_AUTO_MODE (BIT30)
+#define ETH_TX_IHL_SHIFT 11
+
/* typedefs */
typedef enum _eth_func_ret_status {
@@ -406,10 +408,6 @@ static void eth_port_init(struct mv643xx_private *mp);
static void eth_port_reset(unsigned int eth_port_num);
static void eth_port_start(struct mv643xx_private *mp);
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value);
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
-
/* Port MAC address routines */
static void eth_port_uc_addr_set(unsigned int eth_port_num,
unsigned char *p_addr);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index 6c92f0969015..73501d846588 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -26,9 +26,6 @@
Updated to EISA probing API 5/2003 by Marc Zyngier.
*/
-static const char *version =
- "ne3210.c: Driver revision v0.03, 30/09/98\n";
-
#include <linux/module.h>
#include <linux/eisa.h>
#include <linux/kernel.h>
@@ -197,7 +194,7 @@ static int __init ne3210_eisa_probe (struct device *device)
ei_status.priv = phys_mem;
if (ei_debug > 0)
- printk(version);
+ printk("ne3210 loaded.\n");
ei_status.reset_8390 = &ne3210_reset_8390;
ei_status.block_input = &ne3210_block_input;
@@ -360,12 +357,12 @@ MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(eisa, ne3210_ids);
-int ne3210_init(void)
+static int ne3210_init(void)
{
return eisa_driver_register (&ne3210_eisa_driver);
}
-void ne3210_cleanup(void)
+static void ne3210_cleanup(void)
{
eisa_driver_unregister (&ne3210_eisa_driver);
}
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 4a391ea0f58a..a1ac4bd1696e 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -486,9 +486,9 @@ struct netdrv_private {
MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM (max_interrupt_work, "i");
-MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");
+module_param(multicast_filter_limit, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param_array(media, int, NULL, 0);
MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses");
MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt");
MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex");
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 9d8197bb293a..384a736a0d2f 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -134,7 +134,7 @@ typedef struct local_info_t {
u_char mc_filter[8];
} local_info_t;
-#define MC_FILTERBREAK 64
+#define MC_FILTERBREAK 8
/*====================================================================*/
/*
@@ -1012,7 +1012,7 @@ static void fjn_reset(struct net_device *dev)
outb(BANK_1U, ioaddr + CONFIG_1);
/* set the multicast table to accept none. */
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 8; i++)
outb(0x00, ioaddr + MAR_ADR + i);
/* Switch to bank 2 (runtime mode) */
@@ -1269,6 +1269,16 @@ static void set_rx_mode(struct net_device *dev)
u_long flags;
int i;
+ int saved_config_0 = inb(ioaddr + CONFIG_0);
+
+ local_irq_save(flags);
+
+ /* Disable Tx and Rx */
+ if (sram_config == 0)
+ outb(CONFIG0_RST, ioaddr + CONFIG_0);
+ else
+ outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name);
@@ -1290,20 +1300,23 @@ static void set_rx_mode(struct net_device *dev)
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
unsigned int bit =
- ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f;
- mc_filter[bit >> 3] |= (1 << bit);
+ ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
+ mc_filter[bit >> 3] |= (1 << (bit & 7));
}
+ outb(2, ioaddr + RX_MODE); /* Use normal mode. */
}
- local_irq_save(flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inb(ioaddr + CONFIG_1);
/* Switch to bank 1 and set the multicast table. */
outb(0xe4, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++)
- outb(mc_filter[i], ioaddr + 8 + i);
+ outb(mc_filter[i], ioaddr + MAR_ADR + i);
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outb(saved_bank, ioaddr + CONFIG_1);
}
+
+ outb(saved_config_0, ioaddr + CONFIG_0);
+
local_irq_restore(flags);
}
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
new file mode 100644
index 000000000000..14f4de1a8180
--- /dev/null
+++ b/drivers/net/phy/Kconfig
@@ -0,0 +1,57 @@
+#
+# PHY Layer Configuration
+#
+
+menu "PHY device support"
+
+config PHYLIB
+ tristate "PHY Device support and infrastructure"
+ depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
+ help
+ Ethernet controllers are usually attached to PHY
+ devices. This option provides infrastructure for
+ managing PHY devices.
+
+config PHYCONTROL
+ bool " Support for automatically handling PHY state changes"
+ depends on PHYLIB
+ help
+ Adds code to perform all the work for keeping PHY link
+ state (speed/duplex/etc) up-to-date. Also handles
+ interrupts.
+
+comment "MII PHY device drivers"
+ depends on PHYLIB
+
+config MARVELL_PHY
+ tristate "Drivers for Marvell PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently has a driver for the 88E1011S
+
+config DAVICOM_PHY
+ tristate "Drivers for Davicom PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports dm9161e and dm9131
+
+config QSEMI_PHY
+ tristate "Drivers for Quality Semiconductor PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the qs6612
+
+config LXT_PHY
+ tristate "Drivers for the Intel LXT PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the lxt970, lxt971
+
+config CICADA_PHY
+ tristate "Drivers for the Cicada PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the cis8204
+
+endmenu
+
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
new file mode 100644
index 000000000000..e4116a5fbb4c
--- /dev/null
+++ b/drivers/net/phy/Makefile
@@ -0,0 +1,10 @@
+# Makefile for Linux PHY drivers
+
+libphy-objs := phy.o phy_device.o mdio_bus.o
+
+obj-$(CONFIG_PHYLIB) += libphy.o
+obj-$(CONFIG_MARVELL_PHY) += marvell.o
+obj-$(CONFIG_DAVICOM_PHY) += davicom.o
+obj-$(CONFIG_CICADA_PHY) += cicada.o
+obj-$(CONFIG_LXT_PHY) += lxt.o
+obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
new file mode 100644
index 000000000000..c47fb2ecd147
--- /dev/null
+++ b/drivers/net/phy/cicada.c
@@ -0,0 +1,134 @@
+/*
+ * drivers/net/phy/cicada.c
+ *
+ * Driver for Cicada PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1 0x17
+#define MII_CIS8201_EXTCON1_INIT 0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK 0x19
+#define MII_CIS8201_IMASK_IEN 0x8000
+#define MII_CIS8201_IMASK_SPEED 0x4000
+#define MII_CIS8201_IMASK_LINK 0x2000
+#define MII_CIS8201_IMASK_DUPLEX 0x1000
+#define MII_CIS8201_IMASK_MASK 0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT 0x1a
+#define MII_CIS8201_ISTAT_STATUS 0x8000
+#define MII_CIS8201_ISTAT_SPEED 0x4000
+#define MII_CIS8201_ISTAT_LINK 0x2000
+#define MII_CIS8201_ISTAT_DUPLEX 0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT 0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
+#define MII_CIS8201_AUXCONSTAT_100 0x0008
+
+MODULE_DESCRIPTION("Cicadia PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int cis820x_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
+ MII_CIS8201_AUXCONSTAT_INIT);
+
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_CIS8201_EXT_CON1,
+ MII_CIS8201_EXTCON1_INIT);
+
+ return err;
+}
+
+static int cis820x_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_CIS8201_ISTAT);
+
+ return (err < 0) ? err : 0;
+}
+
+static int cis820x_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_CIS8201_IMASK,
+ MII_CIS8201_IMASK_MASK);
+ else
+ err = phy_write(phydev, MII_CIS8201_IMASK, 0);
+
+ return err;
+}
+
+/* Cicada 820x */
+static struct phy_driver cis8204_driver = {
+ .phy_id = 0x000fc440,
+ .name = "Cicada Cis8204",
+ .phy_id_mask = 0x000fffc0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &cis820x_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &cis820x_ack_interrupt,
+ .config_intr = &cis820x_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init cis8204_init(void)
+{
+ return phy_driver_register(&cis8204_driver);
+}
+
+static void __exit cis8204_exit(void)
+{
+ phy_driver_unregister(&cis8204_driver);
+}
+
+module_init(cis8204_init);
+module_exit(cis8204_exit);
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
new file mode 100644
index 000000000000..6caf499fae32
--- /dev/null
+++ b/drivers/net/phy/davicom.c
@@ -0,0 +1,195 @@
+/*
+ * drivers/net/phy/davicom.c
+ *
+ * Driver for Davicom PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_DM9161_SCR 0x10
+#define MII_DM9161_SCR_INIT 0x0610
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR 0x15
+#define MII_DM9161_INTR_PEND 0x8000
+#define MII_DM9161_INTR_DPLX_MASK 0x0800
+#define MII_DM9161_INTR_SPD_MASK 0x0400
+#define MII_DM9161_INTR_LINK_MASK 0x0200
+#define MII_DM9161_INTR_MASK 0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
+#define MII_DM9161_INTR_SPD_CHANGE 0x0008
+#define MII_DM9161_INTR_LINK_CHANGE 0x0004
+#define MII_DM9161_INTR_INIT 0x0000
+#define MII_DM9161_INTR_STOP \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR 0x12
+#define MII_DM9161_10BTCSR_INIT 0x7800
+
+MODULE_DESCRIPTION("Davicom PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+
+#define DM9161_DELAY 1
+static int dm9161_config_intr(struct phy_device *phydev)
+{
+ int temp;
+
+ temp = phy_read(phydev, MII_DM9161_INTR);
+
+ if (temp < 0)
+ return temp;
+
+ if(PHY_INTERRUPT_ENABLED == phydev->interrupts )
+ temp &= ~(MII_DM9161_INTR_STOP);
+ else
+ temp |= MII_DM9161_INTR_STOP;
+
+ temp = phy_write(phydev, MII_DM9161_INTR, temp);
+
+ return temp;
+}
+
+static int dm9161_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ /* Isolate the PHY */
+ err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+ if (err < 0)
+ return err;
+
+ /* Configure the new settings */
+ err = genphy_config_aneg(phydev);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int dm9161_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ /* Isolate the PHY */
+ err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+ if (err < 0)
+ return err;
+
+ /* Do not bypass the scrambler/descrambler */
+ err = phy_write(phydev, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+ if (err < 0)
+ return err;
+
+ /* Clear 10BTCSR to default */
+ err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+ if (err < 0)
+ return err;
+
+ /* Reconnect the PHY, and enable Autonegotiation */
+ err = phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int dm9161_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_DM9161_INTR);
+
+ return (err < 0) ? err : 0;
+}
+
+static struct phy_driver dm9161_driver = {
+ .phy_id = 0x0181b880,
+ .name = "Davicom DM9161E",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .config_init = dm9161_config_init,
+ .config_aneg = dm9161_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver dm9131_driver = {
+ .phy_id = 0x00181b80,
+ .name = "Davicom DM9131",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = dm9161_ack_interrupt,
+ .config_intr = dm9161_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init davicom_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&dm9161_driver);
+ if (ret)
+ goto err1;
+
+ ret = phy_driver_register(&dm9131_driver);
+ if (ret)
+ goto err2;
+ return 0;
+
+ err2:
+ phy_driver_unregister(&dm9161_driver);
+ err1:
+ return ret;
+}
+
+static void __exit davicom_exit(void)
+{
+ phy_driver_unregister(&dm9161_driver);
+ phy_driver_unregister(&dm9131_driver);
+}
+
+module_init(davicom_init);
+module_exit(davicom_exit);
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
new file mode 100644
index 000000000000..4c840448ec86
--- /dev/null
+++ b/drivers/net/phy/lxt.c
@@ -0,0 +1,179 @@
+/*
+ * drivers/net/phy/lxt.c
+ *
+ * Driver for Intel LXT PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* The Level one LXT970 is used by many boards */
+
+#define MII_LXT970_IER 17 /* Interrupt Enable Register */
+
+#define MII_LXT970_IER_IEN 0x0002
+
+#define MII_LXT970_ISR 18 /* Interrupt Status Register */
+
+#define MII_LXT970_CONFIG 19 /* Configuration Register */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards */
+
+/* register definitions for the 971 */
+#define MII_LXT971_IER 18 /* Interrupt Enable Register */
+#define MII_LXT971_IER_IEN 0x00f2
+
+#define MII_LXT971_ISR 19 /* Interrupt Status Register */
+
+
+MODULE_DESCRIPTION("Intel LXT PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int lxt970_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, MII_BMSR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_LXT970_ISR);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int lxt970_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN);
+ else
+ err = phy_write(phydev, MII_LXT970_IER, 0);
+
+ return err;
+}
+
+static int lxt970_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_LXT970_CONFIG, 0);
+
+ return err;
+}
+
+
+static int lxt971_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_LXT971_ISR);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int lxt971_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN);
+ else
+ err = phy_write(phydev, MII_LXT971_IER, 0);
+
+ return err;
+}
+
+static struct phy_driver lxt970_driver = {
+ .phy_id = 0x07810000,
+ .name = "LXT970",
+ .phy_id_mask = 0x0fffffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = lxt970_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = lxt970_ack_interrupt,
+ .config_intr = lxt970_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver lxt971_driver = {
+ .phy_id = 0x0001378e,
+ .name = "LXT971",
+ .phy_id_mask = 0x0fffffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = lxt971_ack_interrupt,
+ .config_intr = lxt971_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init lxt_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&lxt970_driver);
+ if (ret)
+ goto err1;
+
+ ret = phy_driver_register(&lxt971_driver);
+ if (ret)
+ goto err2;
+ return 0;
+
+ err2:
+ phy_driver_unregister(&lxt970_driver);
+ err1:
+ return ret;
+}
+
+static void __exit lxt_exit(void)
+{
+ phy_driver_unregister(&lxt970_driver);
+ phy_driver_unregister(&lxt971_driver);
+}
+
+module_init(lxt_init);
+module_exit(lxt_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
new file mode 100644
index 000000000000..4a72b025006b
--- /dev/null
+++ b/drivers/net/phy/marvell.c
@@ -0,0 +1,140 @@
+/*
+ * drivers/net/phy/marvell.c
+ *
+ * Driver for Marvell PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_M1011_IEVENT 0x13
+#define MII_M1011_IEVENT_CLEAR 0x0000
+
+#define MII_M1011_IMASK 0x12
+#define MII_M1011_IMASK_INIT 0x6400
+#define MII_M1011_IMASK_CLEAR 0x0000
+
+MODULE_DESCRIPTION("Marvell PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int marvell_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ /* Clear the interrupts by reading the reg */
+ err = phy_read(phydev, MII_M1011_IEVENT);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int marvell_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+ else
+ err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+ return err;
+}
+
+static int marvell_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ /* The Marvell PHY has an errata which requires
+ * that certain registers get written in order
+ * to restart autonegotiation */
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x1f);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x200c);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x5);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x100);
+ if (err < 0)
+ return err;
+
+
+ err = genphy_config_aneg(phydev);
+
+ return err;
+}
+
+
+static struct phy_driver m88e1101_driver = {
+ .phy_id = 0x01410c00,
+ .phy_id_mask = 0xffffff00,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init marvell_init(void)
+{
+ return phy_driver_register(&m88e1101_driver);
+}
+
+static void __exit marvell_exit(void)
+{
+ phy_driver_unregister(&m88e1101_driver);
+}
+
+module_init(marvell_init);
+module_exit(marvell_exit);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
new file mode 100644
index 000000000000..90630672703d
--- /dev/null
+++ b/drivers/net/phy/mdio_bus.c
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/mdio_bus.c
+ *
+ * MDIO Bus interface
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* mdiobus_register
+ *
+ * description: Called by a bus driver to bring up all the PHYs
+ * on a given bus, and attach them to the bus
+ */
+int mdiobus_register(struct mii_bus *bus)
+{
+ int i;
+ int err = 0;
+
+ spin_lock_init(&bus->mdio_lock);
+
+ if (NULL == bus || NULL == bus->name ||
+ NULL == bus->read ||
+ NULL == bus->write)
+ return -EINVAL;
+
+ if (bus->reset)
+ bus->reset(bus);
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *phydev;
+
+ phydev = get_phy_device(bus, i);
+
+ if (IS_ERR(phydev))
+ return PTR_ERR(phydev);
+
+ /* There's a PHY at this address
+ * We need to set:
+ * 1) IRQ
+ * 2) bus_id
+ * 3) parent
+ * 4) bus
+ * 5) mii_bus
+ * And, we need to register it */
+ if (phydev) {
+ phydev->irq = bus->irq[i];
+
+ phydev->dev.parent = bus->dev;
+ phydev->dev.bus = &mdio_bus_type;
+ sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+
+ phydev->bus = bus;
+
+ err = device_register(&phydev->dev);
+
+ if (err)
+ printk(KERN_ERR "phy %d failed to register\n",
+ i);
+ }
+
+ bus->phy_map[i] = phydev;
+ }
+
+ pr_info("%s: probed\n", bus->name);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_register);
+
+void mdiobus_unregister(struct mii_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if (bus->phy_map[i]) {
+ device_unregister(&bus->phy_map[i]->dev);
+ kfree(bus->phy_map[i]);
+ }
+ }
+}
+EXPORT_SYMBOL(mdiobus_unregister);
+
+/* mdio_bus_match
+ *
+ * description: Given a PHY device, and a PHY driver, return 1 if
+ * the driver supports the device. Otherwise, return 0
+ */
+static int mdio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct phy_device *phydev = to_phy_device(dev);
+ struct phy_driver *phydrv = to_phy_driver(drv);
+
+ return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask));
+}
+
+/* Suspend and resume. Copied from platform_suspend and
+ * platform_resume
+ */
+static int mdio_bus_suspend(struct device * dev, pm_message_t state)
+{
+ int ret = 0;
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->suspend) {
+ ret = drv->suspend(dev, state, SUSPEND_DISABLE);
+ if (ret == 0)
+ ret = drv->suspend(dev, state, SUSPEND_SAVE_STATE);
+ if (ret == 0)
+ ret = drv->suspend(dev, state, SUSPEND_POWER_DOWN);
+ }
+ return ret;
+}
+
+static int mdio_bus_resume(struct device * dev)
+{
+ int ret = 0;
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->resume) {
+ ret = drv->resume(dev, RESUME_POWER_ON);
+ if (ret == 0)
+ ret = drv->resume(dev, RESUME_RESTORE_STATE);
+ if (ret == 0)
+ ret = drv->resume(dev, RESUME_ENABLE);
+ }
+ return ret;
+}
+
+struct bus_type mdio_bus_type = {
+ .name = "mdio_bus",
+ .match = mdio_bus_match,
+ .suspend = mdio_bus_suspend,
+ .resume = mdio_bus_resume,
+};
+
+int __init mdio_bus_init(void)
+{
+ return bus_register(&mdio_bus_type);
+}
+
+void mdio_bus_exit(void)
+{
+ bus_unregister(&mdio_bus_type);
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
new file mode 100644
index 000000000000..d9e11f93bf3a
--- /dev/null
+++ b/drivers/net/phy/phy.c
@@ -0,0 +1,871 @@
+/*
+ * drivers/net/phy/phy.c
+ *
+ * Framework for configuring and reading PHY devices
+ * Based on code in sungem_phy.c and gianfar_phy.c
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Convenience function to print out the current phy status
+ */
+void phy_print_status(struct phy_device *phydev)
+{
+ pr_info("%s: Link is %s", phydev->dev.bus_id,
+ phydev->link ? "Up" : "Down");
+ if (phydev->link)
+ printk(" - %d/%s", phydev->speed,
+ DUPLEX_FULL == phydev->duplex ?
+ "Full" : "Half");
+
+ printk("\n");
+}
+EXPORT_SYMBOL(phy_print_status);
+
+
+/* Convenience functions for reading/writing a given PHY
+ * register. They MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation. */
+int phy_read(struct phy_device *phydev, u16 regnum)
+{
+ int retval;
+ struct mii_bus *bus = phydev->bus;
+
+ spin_lock_bh(&bus->mdio_lock);
+ retval = bus->read(bus, phydev->addr, regnum);
+ spin_unlock_bh(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(phy_read);
+
+int phy_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+ int err;
+ struct mii_bus *bus = phydev->bus;
+
+ spin_lock_bh(&bus->mdio_lock);
+ err = bus->write(bus, phydev->addr, regnum, val);
+ spin_unlock_bh(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_write);
+
+
+int phy_clear_interrupt(struct phy_device *phydev)
+{
+ int err = 0;
+
+ if (phydev->drv->ack_interrupt)
+ err = phydev->drv->ack_interrupt(phydev);
+
+ return err;
+}
+
+
+int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
+{
+ int err = 0;
+
+ phydev->interrupts = interrupts;
+ if (phydev->drv->config_intr)
+ err = phydev->drv->config_intr(phydev);
+
+ return err;
+}
+
+
+/* phy_aneg_done
+ *
+ * description: Reads the status register and returns 0 either if
+ * auto-negotiation is incomplete, or if there was an error.
+ * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ */
+static inline int phy_aneg_done(struct phy_device *phydev)
+{
+ int retval;
+
+ retval = phy_read(phydev, MII_BMSR);
+
+ return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+
+/* A structure for mapping a particular speed and duplex
+ * combination to a particular SUPPORTED and ADVERTISED value */
+struct phy_setting {
+ int speed;
+ int duplex;
+ u32 setting;
+};
+
+/* A mapping of all SUPPORTED settings to speed/duplex */
+static struct phy_setting settings[] = {
+ {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10000baseT_Full,
+ },
+ {
+ .speed = SPEED_1000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_1000baseT_Full,
+ },
+ {
+ .speed = SPEED_1000,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_1000baseT_Half,
+ },
+ {
+ .speed = SPEED_100,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_100baseT_Full,
+ },
+ {
+ .speed = SPEED_100,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_100baseT_Half,
+ },
+ {
+ .speed = SPEED_10,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10baseT_Full,
+ },
+ {
+ .speed = SPEED_10,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_10baseT_Half,
+ },
+};
+
+#define MAX_NUM_SETTINGS (sizeof(settings)/sizeof(struct phy_setting))
+
+/* phy_find_setting
+ *
+ * description: Searches the settings array for the setting which
+ * matches the desired speed and duplex, and returns the index
+ * of that setting. Returns the index of the last setting if
+ * none of the others match.
+ */
+static inline int phy_find_setting(int speed, int duplex)
+{
+ int idx = 0;
+
+ while (idx < ARRAY_SIZE(settings) &&
+ (settings[idx].speed != speed ||
+ settings[idx].duplex != duplex))
+ idx++;
+
+ return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_find_valid
+ * idx: The first index in settings[] to search
+ * features: A mask of the valid settings
+ *
+ * description: Returns the index of the first valid setting less
+ * than or equal to the one pointed to by idx, as determined by
+ * the mask in features. Returns the index of the last setting
+ * if nothing else matches.
+ */
+static inline int phy_find_valid(int idx, u32 features)
+{
+ while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
+ idx++;
+
+ return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_sanitize_settings
+ *
+ * description: Make sure the PHY is set to supported speeds and
+ * duplexes. Drop down by one in this order: 1000/FULL,
+ * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF
+ */
+void phy_sanitize_settings(struct phy_device *phydev)
+{
+ u32 features = phydev->supported;
+ int idx;
+
+ /* Sanitize settings based on PHY capabilities */
+ if ((features & SUPPORTED_Autoneg) == 0)
+ phydev->autoneg = 0;
+
+ idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
+ features);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+}
+EXPORT_SYMBOL(phy_sanitize_settings);
+
+/* phy_ethtool_sset:
+ * A generic ethtool sset function. Handles all the details
+ *
+ * A few notes about parameter checking:
+ * - We don't set port or transceiver, so we don't care what they
+ * were set to.
+ * - phy_start_aneg() will make sure forced settings are sane, and
+ * choose the next best ones from the ones selected, so we don't
+ * care if ethtool tries to give us bad values
+ *
+ * A note about the PHYCONTROL Layer. If you turn off
+ * CONFIG_PHYCONTROL, you will need to read the PHY status
+ * registers after this function completes, and update your
+ * controller manually.
+ */
+int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+ if (cmd->phy_address != phydev->addr)
+ return -EINVAL;
+
+ /* We make sure that we don't pass unsupported
+ * values in to the PHY */
+ cmd->advertising &= phydev->supported;
+
+ /* Verify the settings we care about. */
+ if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_DISABLE
+ && ((cmd->speed != SPEED_1000
+ && cmd->speed != SPEED_100
+ && cmd->speed != SPEED_10)
+ || (cmd->duplex != DUPLEX_HALF
+ && cmd->duplex != DUPLEX_FULL)))
+ return -EINVAL;
+
+ phydev->autoneg = cmd->autoneg;
+
+ phydev->speed = cmd->speed;
+
+ phydev->advertising = cmd->advertising;
+
+ if (AUTONEG_ENABLE == cmd->autoneg)
+ phydev->advertising |= ADVERTISED_Autoneg;
+ else
+ phydev->advertising &= ~ADVERTISED_Autoneg;
+
+ phydev->duplex = cmd->duplex;
+
+ /* Restart the PHY */
+ phy_start_aneg(phydev);
+
+ return 0;
+}
+
+int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = phydev->supported;
+
+ cmd->advertising = phydev->advertising;
+
+ cmd->speed = phydev->speed;
+ cmd->duplex = phydev->duplex;
+ cmd->port = PORT_MII;
+ cmd->phy_address = phydev->addr;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = phydev->autoneg;
+
+ return 0;
+}
+
+
+/* Note that this function is currently incompatible with the
+ * PHYCONTROL layer. It changes registers without regard to
+ * current state. Use at own risk
+ */
+int phy_mii_ioctl(struct phy_device *phydev,
+ struct mii_ioctl_data *mii_data, int cmd)
+{
+ u16 val = mii_data->val_in;
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ mii_data->phy_id = phydev->addr;
+ break;
+ case SIOCGMIIREG:
+ mii_data->val_out = phy_read(phydev, mii_data->reg_num);
+ break;
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (mii_data->phy_id == phydev->addr) {
+ switch(mii_data->reg_num) {
+ case MII_BMCR:
+ if (val & (BMCR_RESET|BMCR_ANENABLE))
+ phydev->autoneg = AUTONEG_DISABLE;
+ else
+ phydev->autoneg = AUTONEG_ENABLE;
+ if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+ break;
+ case MII_ADVERTISE:
+ phydev->advertising = val;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ phy_write(phydev, mii_data->reg_num, val);
+
+ if (mii_data->reg_num == MII_BMCR
+ && val & BMCR_RESET
+ && phydev->drv->config_init)
+ phydev->drv->config_init(phydev);
+ break;
+ }
+
+ return 0;
+}
+
+/* phy_start_aneg
+ *
+ * description: Sanitizes the settings (if we're not
+ * autonegotiating them), and then calls the driver's
+ * config_aneg function. If the PHYCONTROL Layer is operating,
+ * we change the state to reflect the beginning of
+ * Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ spin_lock(&phydev->lock);
+
+ if (AUTONEG_DISABLE == phydev->autoneg)
+ phy_sanitize_settings(phydev);
+
+ err = phydev->drv->config_aneg(phydev);
+
+#ifdef CONFIG_PHYCONTROL
+ if (err < 0)
+ goto out_unlock;
+
+ if (phydev->state != PHY_HALTED) {
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ phydev->state = PHY_AN;
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+ } else {
+ phydev->state = PHY_FORCING;
+ phydev->link_timeout = PHY_FORCE_TIMEOUT;
+ }
+ }
+
+out_unlock:
+#endif
+ spin_unlock(&phydev->lock);
+ return err;
+}
+EXPORT_SYMBOL(phy_start_aneg);
+
+
+#ifdef CONFIG_PHYCONTROL
+static void phy_change(void *data);
+static void phy_timer(unsigned long data);
+
+/* phy_start_machine:
+ *
+ * description: The PHY infrastructure can run a state machine
+ * which tracks whether the PHY is starting up, negotiating,
+ * etc. This function starts the timer which tracks the state
+ * of the PHY. If you want to be notified when the state
+ * changes, pass in the callback, otherwise, pass NULL. If you
+ * want to maintain your own state machine, do not call this
+ * function. */
+void phy_start_machine(struct phy_device *phydev,
+ void (*handler)(struct net_device *))
+{
+ phydev->adjust_state = handler;
+
+ init_timer(&phydev->phy_timer);
+ phydev->phy_timer.function = &phy_timer;
+ phydev->phy_timer.data = (unsigned long) phydev;
+ mod_timer(&phydev->phy_timer, jiffies + HZ);
+}
+
+/* phy_stop_machine
+ *
+ * description: Stops the state machine timer, sets the state to
+ * UP (unless it wasn't up yet), and then frees the interrupt,
+ * if it is in use. This function must be called BEFORE
+ * phy_detach.
+ */
+void phy_stop_machine(struct phy_device *phydev)
+{
+ del_timer_sync(&phydev->phy_timer);
+
+ spin_lock(&phydev->lock);
+ if (phydev->state > PHY_UP)
+ phydev->state = PHY_UP;
+ spin_unlock(&phydev->lock);
+
+ if (phydev->irq != PHY_POLL)
+ phy_stop_interrupts(phydev);
+
+ phydev->adjust_state = NULL;
+}
+
+/* phy_force_reduction
+ *
+ * description: Reduces the speed/duplex settings by
+ * one notch. The order is so:
+ * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF,
+ * 10/FULL, 10/HALF. The function bottoms out at 10/HALF.
+ */
+static void phy_force_reduction(struct phy_device *phydev)
+{
+ int idx;
+
+ idx = phy_find_setting(phydev->speed, phydev->duplex);
+
+ idx++;
+
+ idx = phy_find_valid(idx, phydev->supported);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+
+ pr_info("Trying %d/%s\n", phydev->speed,
+ DUPLEX_FULL == phydev->duplex ?
+ "FULL" : "HALF");
+}
+
+
+/* phy_error:
+ *
+ * Moves the PHY to the HALTED state in response to a read
+ * or write error, and tells the controller the link is down.
+ * Must not be called from interrupt context, or while the
+ * phydev->lock is held.
+ */
+void phy_error(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+ phydev->state = PHY_HALTED;
+ spin_unlock(&phydev->lock);
+}
+
+/* phy_interrupt
+ *
+ * description: When a PHY interrupt occurs, the handler disables
+ * interrupts, and schedules a work task to clear the interrupt.
+ */
+static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
+{
+ struct phy_device *phydev = phy_dat;
+
+ /* The MDIO bus is not allowed to be written in interrupt
+ * context, so we need to disable the irq here. A work
+ * queue will write the PHY to disable and clear the
+ * interrupt, and then reenable the irq line. */
+ disable_irq_nosync(irq);
+
+ schedule_work(&phydev->phy_queue);
+
+ return IRQ_HANDLED;
+}
+
+/* Enable the interrupts from the PHY side */
+int phy_enable_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_clear_interrupt(phydev);
+
+ if (err < 0)
+ return err;
+
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_enable_interrupts);
+
+/* Disable the PHY interrupts from the PHY side */
+int phy_disable_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ /* Disable PHY interrupts */
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+
+ if (err)
+ goto phy_err;
+
+ /* Clear the interrupt */
+ err = phy_clear_interrupt(phydev);
+
+ if (err)
+ goto phy_err;
+
+ return 0;
+
+phy_err:
+ phy_error(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_disable_interrupts);
+
+/* phy_start_interrupts
+ *
+ * description: Request the interrupt for the given PHY. If
+ * this fails, then we set irq to PHY_POLL.
+ * Otherwise, we enable the interrupts in the PHY.
+ * Returns 0 on success.
+ * This should only be called with a valid IRQ number.
+ */
+int phy_start_interrupts(struct phy_device *phydev)
+{
+ int err = 0;
+
+ INIT_WORK(&phydev->phy_queue, phy_change, phydev);
+
+ if (request_irq(phydev->irq, phy_interrupt,
+ SA_SHIRQ,
+ "phy_interrupt",
+ phydev) < 0) {
+ printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n",
+ phydev->bus->name,
+ phydev->irq);
+ phydev->irq = PHY_POLL;
+ return 0;
+ }
+
+ err = phy_enable_interrupts(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_start_interrupts);
+
+int phy_stop_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_disable_interrupts(phydev);
+
+ if (err)
+ phy_error(phydev);
+
+ free_irq(phydev->irq, phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_stop_interrupts);
+
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void phy_change(void *data)
+{
+ int err;
+ struct phy_device *phydev = data;
+
+ err = phy_disable_interrupts(phydev);
+
+ if (err)
+ goto phy_err;
+
+ spin_lock(&phydev->lock);
+ if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
+ phydev->state = PHY_CHANGELINK;
+ spin_unlock(&phydev->lock);
+
+ enable_irq(phydev->irq);
+
+ /* Reenable interrupts */
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+ if (err)
+ goto irq_enable_err;
+
+ return;
+
+irq_enable_err:
+ disable_irq(phydev->irq);
+phy_err:
+ phy_error(phydev);
+}
+
+/* Bring down the PHY link, and stop checking the status. */
+void phy_stop(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+
+ if (PHY_HALTED == phydev->state)
+ goto out_unlock;
+
+ if (phydev->irq != PHY_POLL) {
+ /* Clear any pending interrupts */
+ phy_clear_interrupt(phydev);
+
+ /* Disable PHY Interrupts */
+ phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+ }
+
+ phydev->state = PHY_HALTED;
+
+out_unlock:
+ spin_unlock(&phydev->lock);
+}
+
+
+/* phy_start
+ *
+ * description: Indicates the attached device's readiness to
+ * handle PHY-related work. Used during startup to start the
+ * PHY, and after a call to phy_stop() to resume operation.
+ * Also used to indicate the MDIO bus has cleared an error
+ * condition.
+ */
+void phy_start(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+
+ switch (phydev->state) {
+ case PHY_STARTING:
+ phydev->state = PHY_PENDING;
+ break;
+ case PHY_READY:
+ phydev->state = PHY_UP;
+ break;
+ case PHY_HALTED:
+ phydev->state = PHY_RESUMING;
+ default:
+ break;
+ }
+ spin_unlock(&phydev->lock);
+}
+EXPORT_SYMBOL(phy_stop);
+EXPORT_SYMBOL(phy_start);
+
+/* PHY timer which handles the state machine */
+static void phy_timer(unsigned long data)
+{
+ struct phy_device *phydev = (struct phy_device *)data;
+ int needs_aneg = 0;
+ int err = 0;
+
+ spin_lock(&phydev->lock);
+
+ if (phydev->adjust_state)
+ phydev->adjust_state(phydev->attached_dev);
+
+ switch(phydev->state) {
+ case PHY_DOWN:
+ case PHY_STARTING:
+ case PHY_READY:
+ case PHY_PENDING:
+ break;
+ case PHY_UP:
+ needs_aneg = 1;
+
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+
+ break;
+ case PHY_AN:
+ /* Check if negotiation is done. Break
+ * if there's an error */
+ err = phy_aneg_done(phydev);
+ if (err < 0)
+ break;
+
+ /* If auto-negotiation is done, we change to
+ * either RUNNING, or NOLINK */
+ if (err > 0) {
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ phydev->state = PHY_NOLINK;
+ netif_carrier_off(phydev->attached_dev);
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+
+ } else if (0 == phydev->link_timeout--) {
+ /* The counter expired, so either we
+ * switch to forced mode, or the
+ * magic_aneg bit exists, and we try aneg
+ * again */
+ if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) {
+ int idx;
+
+ /* We'll start from the
+ * fastest speed, and work
+ * our way down */
+ idx = phy_find_valid(0,
+ phydev->supported);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+
+ phydev->autoneg = AUTONEG_DISABLE;
+ phydev->state = PHY_FORCING;
+ phydev->link_timeout =
+ PHY_FORCE_TIMEOUT;
+
+ pr_info("Trying %d/%s\n",
+ phydev->speed,
+ DUPLEX_FULL ==
+ phydev->duplex ?
+ "FULL" : "HALF");
+ }
+
+ needs_aneg = 1;
+ }
+ break;
+ case PHY_NOLINK:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ }
+ break;
+ case PHY_FORCING:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ if (0 == phydev->link_timeout--) {
+ phy_force_reduction(phydev);
+ needs_aneg = 1;
+ }
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+ break;
+ case PHY_RUNNING:
+ /* Only register a CHANGE if we are
+ * polling */
+ if (PHY_POLL == phydev->irq)
+ phydev->state = PHY_CHANGELINK;
+ break;
+ case PHY_CHANGELINK:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ phydev->state = PHY_NOLINK;
+ netif_carrier_off(phydev->attached_dev);
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+
+ if (PHY_POLL != phydev->irq)
+ err = phy_config_interrupt(phydev,
+ PHY_INTERRUPT_ENABLED);
+ break;
+ case PHY_HALTED:
+ if (phydev->link) {
+ phydev->link = 0;
+ netif_carrier_off(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ }
+ break;
+ case PHY_RESUMING:
+
+ err = phy_clear_interrupt(phydev);
+
+ if (err)
+ break;
+
+ err = phy_config_interrupt(phydev,
+ PHY_INTERRUPT_ENABLED);
+
+ if (err)
+ break;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ err = phy_aneg_done(phydev);
+ if (err < 0)
+ break;
+
+ /* err > 0 if AN is done.
+ * Otherwise, it's 0, and we're
+ * still waiting for AN */
+ if (err > 0) {
+ phydev->state = PHY_RUNNING;
+ } else {
+ phydev->state = PHY_AN;
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+ }
+ } else
+ phydev->state = PHY_RUNNING;
+ break;
+ }
+
+ spin_unlock(&phydev->lock);
+
+ if (needs_aneg)
+ err = phy_start_aneg(phydev);
+
+ if (err < 0)
+ phy_error(phydev);
+
+ mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
+}
+
+#endif /* CONFIG_PHYCONTROL */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
new file mode 100644
index 000000000000..33f7bdb5857c
--- /dev/null
+++ b/drivers/net/phy/phy_device.c
@@ -0,0 +1,696 @@
+/*
+ * drivers/net/phy/phy_device.c
+ *
+ * Framework for finding and configuring PHYs.
+ * Also contains generic PHY driver
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+static struct phy_driver genphy_driver;
+extern int mdio_bus_init(void);
+extern void mdio_bus_exit(void);
+
+/* get_phy_device
+ *
+ * description: Reads the ID registers of the PHY at addr on the
+ * bus, then allocates and returns the phy_device to
+ * represent it.
+ */
+struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
+{
+ int phy_reg;
+ u32 phy_id;
+ struct phy_device *dev = NULL;
+
+ /* Grab the bits from PHYIR1, and put them
+ * in the upper half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID1);
+
+ if (phy_reg < 0)
+ return ERR_PTR(phy_reg);
+
+ phy_id = (phy_reg & 0xffff) << 16;
+
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID2);
+
+ if (phy_reg < 0)
+ return ERR_PTR(phy_reg);
+
+ phy_id |= (phy_reg & 0xffff);
+
+ /* If the phy_id is all Fs, there is no device there */
+ if (0xffffffff == phy_id)
+ return NULL;
+
+ /* Otherwise, we allocate the device, and initialize the
+ * default values */
+ dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+
+ if (NULL == dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->speed = 0;
+ dev->duplex = -1;
+ dev->pause = dev->asym_pause = 0;
+ dev->link = 1;
+
+ dev->autoneg = AUTONEG_ENABLE;
+
+ dev->addr = addr;
+ dev->phy_id = phy_id;
+ dev->bus = bus;
+
+ dev->state = PHY_DOWN;
+
+ spin_lock_init(&dev->lock);
+
+ return dev;
+}
+
+#ifdef CONFIG_PHYCONTROL
+/* phy_prepare_link:
+ *
+ * description: Tells the PHY infrastructure to handle the
+ * gory details on monitoring link status (whether through
+ * polling or an interrupt), and to call back to the
+ * connected device driver when the link status changes.
+ * If you want to monitor your own link state, don't call
+ * this function */
+void phy_prepare_link(struct phy_device *phydev,
+ void (*handler)(struct net_device *))
+{
+ phydev->adjust_link = handler;
+}
+
+/* phy_connect:
+ *
+ * description: Convenience function for connecting ethernet
+ * devices to PHY devices. The default behavior is for
+ * the PHY infrastructure to handle everything, and only notify
+ * the connected driver when the link status changes. If you
+ * don't want, or can't use the provided functionality, you may
+ * choose to call only the subset of functions which provide
+ * the desired functionality.
+ */
+struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+ void (*handler)(struct net_device *), u32 flags)
+{
+ struct phy_device *phydev;
+
+ phydev = phy_attach(dev, phy_id, flags);
+
+ if (IS_ERR(phydev))
+ return phydev;
+
+ phy_prepare_link(phydev, handler);
+
+ phy_start_machine(phydev, NULL);
+
+ if (phydev->irq > 0)
+ phy_start_interrupts(phydev);
+
+ return phydev;
+}
+EXPORT_SYMBOL(phy_connect);
+
+void phy_disconnect(struct phy_device *phydev)
+{
+ if (phydev->irq > 0)
+ phy_stop_interrupts(phydev);
+
+ phy_stop_machine(phydev);
+
+ phydev->adjust_link = NULL;
+
+ phy_detach(phydev);
+}
+EXPORT_SYMBOL(phy_disconnect);
+
+#endif /* CONFIG_PHYCONTROL */
+
+/* phy_attach:
+ *
+ * description: Called by drivers to attach to a particular PHY
+ * device. The phy_device is found, and properly hooked up
+ * to the phy_driver. If no driver is attached, then the
+ * genphy_driver is used. The phy_device is given a ptr to
+ * the attaching device, and given a callback for link status
+ * change. The phy_device is returned to the attaching
+ * driver.
+ */
+static int phy_compare_id(struct device *dev, void *data)
+{
+ return strcmp((char *)data, dev->bus_id) ? 0 : 1;
+}
+
+struct phy_device *phy_attach(struct net_device *dev,
+ const char *phy_id, u32 flags)
+{
+ struct bus_type *bus = &mdio_bus_type;
+ struct phy_device *phydev;
+ struct device *d;
+
+ /* Search the list of PHY devices on the mdio bus for the
+ * PHY with the requested name */
+ d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
+
+ if (d) {
+ phydev = to_phy_device(d);
+ } else {
+ printk(KERN_ERR "%s not found\n", phy_id);
+ return ERR_PTR(-ENODEV);
+ }
+
+ /* Assume that if there is no driver, that it doesn't
+ * exist, and we should use the genphy driver. */
+ if (NULL == d->driver) {
+ int err;
+ down_write(&d->bus->subsys.rwsem);
+ d->driver = &genphy_driver.driver;
+
+ err = d->driver->probe(d);
+
+ if (err < 0)
+ return ERR_PTR(err);
+
+ device_bind_driver(d);
+ up_write(&d->bus->subsys.rwsem);
+ }
+
+ if (phydev->attached_dev) {
+ printk(KERN_ERR "%s: %s already attached\n",
+ dev->name, phy_id);
+ return ERR_PTR(-EBUSY);
+ }
+
+ phydev->attached_dev = dev;
+
+ phydev->dev_flags = flags;
+
+ return phydev;
+}
+EXPORT_SYMBOL(phy_attach);
+
+void phy_detach(struct phy_device *phydev)
+{
+ phydev->attached_dev = NULL;
+
+ /* If the device had no specific driver before (i.e. - it
+ * was using the generic driver), we unbind the device
+ * from the generic driver so that there's a chance a
+ * real driver could be loaded */
+ if (phydev->dev.driver == &genphy_driver.driver) {
+ down_write(&phydev->dev.bus->subsys.rwsem);
+ device_release_driver(&phydev->dev);
+ up_write(&phydev->dev.bus->subsys.rwsem);
+ }
+}
+EXPORT_SYMBOL(phy_detach);
+
+
+/* Generic PHY support and helper functions */
+
+/* genphy_config_advert
+ *
+ * description: Writes MII_ADVERTISE with the appropriate values,
+ * after sanitizing the values to make sure we only advertise
+ * what is supported
+ */
+int genphy_config_advert(struct phy_device *phydev)
+{
+ u32 advertise;
+ int adv;
+ int err;
+
+ /* Only allow advertising what
+ * this PHY supports */
+ phydev->advertising &= phydev->supported;
+ advertise = phydev->advertising;
+
+ /* Setup standard advertisement */
+ adv = phy_read(phydev, MII_ADVERTISE);
+
+ if (adv < 0)
+ return adv;
+
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
+
+ err = phy_write(phydev, MII_ADVERTISE, adv);
+
+ if (err < 0)
+ return err;
+
+ /* Configure gigabit if it's supported */
+ if (phydev->supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full)) {
+ adv = phy_read(phydev, MII_CTRL1000);
+
+ if (adv < 0)
+ return adv;
+
+ adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ if (advertise & SUPPORTED_1000baseT_Half)
+ adv |= ADVERTISE_1000HALF;
+ if (advertise & SUPPORTED_1000baseT_Full)
+ adv |= ADVERTISE_1000FULL;
+ err = phy_write(phydev, MII_CTRL1000, adv);
+
+ if (err < 0)
+ return err;
+ }
+
+ return adv;
+}
+EXPORT_SYMBOL(genphy_config_advert);
+
+/* genphy_setup_forced
+ *
+ * description: Configures MII_BMCR to force speed/duplex
+ * to the values in phydev. Assumes that the values are valid.
+ * Please see phy_sanitize_settings() */
+int genphy_setup_forced(struct phy_device *phydev)
+{
+ int ctl = BMCR_RESET;
+
+ phydev->pause = phydev->asym_pause = 0;
+
+ if (SPEED_1000 == phydev->speed)
+ ctl |= BMCR_SPEED1000;
+ else if (SPEED_100 == phydev->speed)
+ ctl |= BMCR_SPEED100;
+
+ if (DUPLEX_FULL == phydev->duplex)
+ ctl |= BMCR_FULLDPLX;
+
+ ctl = phy_write(phydev, MII_BMCR, ctl);
+
+ if (ctl < 0)
+ return ctl;
+
+ /* We just reset the device, so we'd better configure any
+ * settings the PHY requires to operate */
+ if (phydev->drv->config_init)
+ ctl = phydev->drv->config_init(phydev);
+
+ return ctl;
+}
+
+
+/* Enable and Restart Autonegotiation */
+int genphy_restart_aneg(struct phy_device *phydev)
+{
+ int ctl;
+
+ ctl = phy_read(phydev, MII_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+
+ /* Don't isolate the PHY if we're negotiating */
+ ctl &= ~(BMCR_ISOLATE);
+
+ ctl = phy_write(phydev, MII_BMCR, ctl);
+
+ return ctl;
+}
+
+
+/* genphy_config_aneg
+ *
+ * description: If auto-negotiation is enabled, we configure the
+ * advertising, and then restart auto-negotiation. If it is not
+ * enabled, then we write the BMCR
+ */
+int genphy_config_aneg(struct phy_device *phydev)
+{
+ int err = 0;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ err = genphy_config_advert(phydev);
+
+ if (err < 0)
+ return err;
+
+ err = genphy_restart_aneg(phydev);
+ } else
+ err = genphy_setup_forced(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(genphy_config_aneg);
+
+/* genphy_update_link
+ *
+ * description: Update the value in phydev->link to reflect the
+ * current link value. In order to do this, we need to read
+ * the status register twice, keeping the second value
+ */
+int genphy_update_link(struct phy_device *phydev)
+{
+ int status;
+
+ /* Do a fake read */
+ status = phy_read(phydev, MII_BMSR);
+
+ if (status < 0)
+ return status;
+
+ /* Read link and autonegotiation status */
+ status = phy_read(phydev, MII_BMSR);
+
+ if (status < 0)
+ return status;
+
+ if ((status & BMSR_LSTATUS) == 0)
+ phydev->link = 0;
+ else
+ phydev->link = 1;
+
+ return 0;
+}
+
+/* genphy_read_status
+ *
+ * description: Check the link, then figure out the current state
+ * by comparing what we advertise with what the link partner
+ * advertises. Start by checking the gigabit possibilities,
+ * then move on to 10/100.
+ */
+int genphy_read_status(struct phy_device *phydev)
+{
+ int adv;
+ int err;
+ int lpa;
+ int lpagb = 0;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genphy_update_link(phydev);
+ if (err)
+ return err;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ if (phydev->supported & (SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full)) {
+ lpagb = phy_read(phydev, MII_STAT1000);
+
+ if (lpagb < 0)
+ return lpagb;
+
+ adv = phy_read(phydev, MII_CTRL1000);
+
+ if (adv < 0)
+ return adv;
+
+ lpagb &= adv << 2;
+ }
+
+ lpa = phy_read(phydev, MII_LPA);
+
+ if (lpa < 0)
+ return lpa;
+
+ adv = phy_read(phydev, MII_ADVERTISE);
+
+ if (adv < 0)
+ return adv;
+
+ lpa &= adv;
+
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+ phydev->pause = phydev->asym_pause = 0;
+
+ if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+ phydev->speed = SPEED_1000;
+
+ if (lpagb & LPA_1000FULL)
+ phydev->duplex = DUPLEX_FULL;
+ } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phydev->speed = SPEED_100;
+
+ if (lpa & LPA_100FULL)
+ phydev->duplex = DUPLEX_FULL;
+ } else
+ if (lpa & LPA_10FULL)
+ phydev->duplex = DUPLEX_FULL;
+
+ if (phydev->duplex == DUPLEX_FULL){
+ phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
+ phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
+ }
+ } else {
+ int bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
+ if (bmcr & BMCR_FULLDPLX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+ if (bmcr & BMCR_SPEED1000)
+ phydev->speed = SPEED_1000;
+ else if (bmcr & BMCR_SPEED100)
+ phydev->speed = SPEED_100;
+ else
+ phydev->speed = SPEED_10;
+
+ phydev->pause = phydev->asym_pause = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_read_status);
+
+static int genphy_config_init(struct phy_device *phydev)
+{
+ u32 val;
+ u32 features;
+
+ /* For now, I'll claim that the generic driver supports
+ * all possible port types */
+ features = (SUPPORTED_TP | SUPPORTED_MII
+ | SUPPORTED_AUI | SUPPORTED_FIBRE |
+ SUPPORTED_BNC);
+
+ /* Do we support autonegotiation? */
+ val = phy_read(phydev, MII_BMSR);
+
+ if (val < 0)
+ return val;
+
+ if (val & BMSR_ANEGCAPABLE)
+ features |= SUPPORTED_Autoneg;
+
+ if (val & BMSR_100FULL)
+ features |= SUPPORTED_100baseT_Full;
+ if (val & BMSR_100HALF)
+ features |= SUPPORTED_100baseT_Half;
+ if (val & BMSR_10FULL)
+ features |= SUPPORTED_10baseT_Full;
+ if (val & BMSR_10HALF)
+ features |= SUPPORTED_10baseT_Half;
+
+ if (val & BMSR_ESTATEN) {
+ val = phy_read(phydev, MII_ESTATUS);
+
+ if (val < 0)
+ return val;
+
+ if (val & ESTATUS_1000_TFULL)
+ features |= SUPPORTED_1000baseT_Full;
+ if (val & ESTATUS_1000_THALF)
+ features |= SUPPORTED_1000baseT_Half;
+ }
+
+ phydev->supported = features;
+ phydev->advertising = features;
+
+ return 0;
+}
+
+
+/* phy_probe
+ *
+ * description: Take care of setting up the phy_device structure,
+ * set the state to READY (the driver's init function should
+ * set it to STARTING if needed).
+ */
+static int phy_probe(struct device *dev)
+{
+ struct phy_device *phydev;
+ struct phy_driver *phydrv;
+ struct device_driver *drv;
+ int err = 0;
+
+ phydev = to_phy_device(dev);
+
+ /* Make sure the driver is held.
+ * XXX -- Is this correct? */
+ drv = get_driver(phydev->dev.driver);
+ phydrv = to_phy_driver(drv);
+ phydev->drv = phydrv;
+
+ /* Disable the interrupt if the PHY doesn't support it */
+ if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+ phydev->irq = PHY_POLL;
+
+ spin_lock(&phydev->lock);
+
+ /* Start out supporting everything. Eventually,
+ * a controller will attach, and may modify one
+ * or both of these values */
+ phydev->supported = phydrv->features;
+ phydev->advertising = phydrv->features;
+
+ /* Set the state to READY by default */
+ phydev->state = PHY_READY;
+
+ if (phydev->drv->probe)
+ err = phydev->drv->probe(phydev);
+
+ spin_unlock(&phydev->lock);
+
+ if (err < 0)
+ return err;
+
+ if (phydev->drv->config_init)
+ err = phydev->drv->config_init(phydev);
+
+ return err;
+}
+
+static int phy_remove(struct device *dev)
+{
+ struct phy_device *phydev;
+
+ phydev = to_phy_device(dev);
+
+ spin_lock(&phydev->lock);
+ phydev->state = PHY_DOWN;
+ spin_unlock(&phydev->lock);
+
+ if (phydev->drv->remove)
+ phydev->drv->remove(phydev);
+
+ put_driver(dev->driver);
+ phydev->drv = NULL;
+
+ return 0;
+}
+
+int phy_driver_register(struct phy_driver *new_driver)
+{
+ int retval;
+
+ memset(&new_driver->driver, 0, sizeof(new_driver->driver));
+ new_driver->driver.name = new_driver->name;
+ new_driver->driver.bus = &mdio_bus_type;
+ new_driver->driver.probe = phy_probe;
+ new_driver->driver.remove = phy_remove;
+
+ retval = driver_register(&new_driver->driver);
+
+ if (retval) {
+ printk(KERN_ERR "%s: Error %d in registering driver\n",
+ new_driver->name, retval);
+
+ return retval;
+ }
+
+ pr_info("%s: Registered new driver\n", new_driver->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_driver_register);
+
+void phy_driver_unregister(struct phy_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(phy_driver_unregister);
+
+static struct phy_driver genphy_driver = {
+ .phy_id = 0xffffffff,
+ .phy_id_mask = 0xffffffff,
+ .name = "Generic PHY",
+ .config_init = genphy_config_init,
+ .features = 0,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = {.owner= THIS_MODULE, },
+};
+
+static int __init phy_init(void)
+{
+ int rc;
+
+ rc = mdio_bus_init();
+ if (rc)
+ return rc;
+
+ rc = phy_driver_register(&genphy_driver);
+ if (rc)
+ mdio_bus_exit();
+
+ return rc;
+}
+
+static void __exit phy_exit(void)
+{
+ phy_driver_unregister(&genphy_driver);
+ mdio_bus_exit();
+}
+
+subsys_initcall(phy_init);
+module_exit(phy_exit);
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
new file mode 100644
index 000000000000..d461ba457631
--- /dev/null
+++ b/drivers/net/phy/qsemi.c
@@ -0,0 +1,143 @@
+/*
+ * drivers/net/phy/qsemi.c
+ *
+ * Driver for Quality Semiconductor PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF */
+
+/* register definitions */
+
+#define MII_QS6612_MCR 17 /* Mode Control Register */
+#define MII_QS6612_FTR 27 /* Factory Test Register */
+#define MII_QS6612_MCO 28 /* Misc. Control Register */
+#define MII_QS6612_ISR 29 /* Interrupt Source Register */
+#define MII_QS6612_IMR 30 /* Interrupt Mask Register */
+#define MII_QS6612_IMR_INIT 0x003a
+#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */
+
+#define QS6612_PCR_AN_COMPLETE 0x1000
+#define QS6612_PCR_RLBEN 0x0200
+#define QS6612_PCR_DCREN 0x0100
+#define QS6612_PCR_4B5BEN 0x0040
+#define QS6612_PCR_TX_ISOLATE 0x0020
+#define QS6612_PCR_MLT3_DIS 0x0002
+#define QS6612_PCR_SCRM_DESCRM 0x0001
+
+MODULE_DESCRIPTION("Quality Semiconductor PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+/* Returns 0, unless there's a write error */
+static int qs6612_config_init(struct phy_device *phydev)
+{
+ /* The PHY powers up isolated on the RPX,
+ * so send a command to allow operation.
+ * XXX - My docs indicate this should be 0x0940
+ * ...or something. The current value sets three
+ * reserved bits, bit 11, which specifies it should be
+ * set to one, bit 10, which specifies it should be set
+ * to 0, and bit 7, which doesn't specify. However, my
+ * docs are preliminary, and I will leave it like this
+ * until someone more knowledgable corrects me or it.
+ * -- Andy Fleming
+ */
+ return phy_write(phydev, MII_QS6612_PCR, 0x0dc0);
+}
+
+static int qs6612_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, MII_QS6612_ISR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_BMSR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_EXPANSION);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int qs6612_config_intr(struct phy_device *phydev)
+{
+ int err;
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_QS6612_IMR,
+ MII_QS6612_IMR_INIT);
+ else
+ err = phy_write(phydev, MII_QS6612_IMR, 0);
+
+ return err;
+
+}
+
+static struct phy_driver qs6612_driver = {
+ .phy_id = 0x00181440,
+ .name = "QS6612",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = qs6612_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = qs6612_ack_interrupt,
+ .config_intr = qs6612_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init qs6612_init(void)
+{
+ return phy_driver_register(&qs6612_driver);
+}
+
+static void __exit qs6612_exit(void)
+{
+ phy_driver_unregister(&qs6612_driver);
+}
+
+module_init(qs6612_init);
+module_exit(qs6612_exit);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index a32668e88e09..0df7e92b0bf8 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1232,9 +1232,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
navail = 0; /* total # of usable channels (not deregistered) */
hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
i = 0;
- list = &ppp->channels;
- while ((list = list->next) != &ppp->channels) {
- pch = list_entry(list, struct channel, clist);
+ list_for_each_entry(pch, &ppp->channels, clist) {
navail += pch->avail = (pch->chan != NULL);
if (pch->avail) {
if (skb_queue_empty(&pch->file.xq) ||
@@ -1280,6 +1278,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
/* skip to the channel after the one we last used
and start at that one */
+ list = &ppp->channels;
for (i = 0; i < ppp->nxchan; ++i) {
list = list->next;
if (list == &ppp->channels) {
@@ -1657,7 +1656,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
skb->dev = ppp->dev;
skb->protocol = htons(npindex_to_ethertype[npi]);
skb->mac.raw = skb->data;
- skb->input_dev = ppp->dev;
netif_rx(skb);
ppp->dev->last_rx = jiffies;
}
@@ -1731,7 +1729,7 @@ static void
ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
u32 mask, seq;
- struct list_head *l;
+ struct channel *ch;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
@@ -1785,8 +1783,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
* The list of channels can't change because we have the receive
* side of the ppp unit locked.
*/
- for (l = ppp->channels.next; l != &ppp->channels; l = l->next) {
- struct channel *ch = list_entry(l, struct channel, clist);
+ list_for_each_entry(ch, &ppp->channels, clist) {
if (seq_before(ch->lastseq, seq))
seq = ch->lastseq;
}
@@ -2272,10 +2269,8 @@ static struct compressor_entry *
find_comp_entry(int proto)
{
struct compressor_entry *ce;
- struct list_head *list = &compressor_list;
- while ((list = list->next) != &compressor_list) {
- ce = list_entry(list, struct compressor_entry, list);
+ list_for_each_entry(ce, &compressor_list, list) {
if (ce->comp->compress_proto == proto)
return ce;
}
@@ -2541,20 +2536,15 @@ static struct channel *
ppp_find_channel(int unit)
{
struct channel *pch;
- struct list_head *list;
- list = &new_channels;
- while ((list = list->next) != &new_channels) {
- pch = list_entry(list, struct channel, list);
+ list_for_each_entry(pch, &new_channels, list) {
if (pch->file.index == unit) {
list_del(&pch->list);
list_add(&pch->list, &all_channels);
return pch;
}
}
- list = &all_channels;
- while ((list = list->next) != &all_channels) {
- pch = list_entry(list, struct channel, list);
+ list_for_each_entry(pch, &all_channels, list) {
if (pch->file.index == unit)
return pch;
}
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index ce1a9bf7b9a7..82f236cc3b9b 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -377,7 +377,8 @@ abort_kfree:
***********************************************************************/
static int pppoe_rcv(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct pppoe_hdr *ph;
@@ -426,7 +427,8 @@ out:
***********************************************************************/
static int pppoe_disc_rcv(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct pppoe_hdr *ph;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index d5afe05cd826..f0471d102e3c 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -187,6 +187,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
{ PCI_DEVICE(0x16ec, 0x0116), },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, },
{0,},
};
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 12a86f96d973..ec1a18d189a1 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1429,6 +1429,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rr_private *rrpriv = netdev_priv(dev);
struct rr_regs __iomem *regs = rrpriv->regs;
+ struct hippi_cb *hcb = (struct hippi_cb *) skb->cb;
struct ring_ctrl *txctrl;
unsigned long flags;
u32 index, len = skb->len;
@@ -1460,7 +1461,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
ifield = (u32 *)skb_push(skb, 8);
ifield[0] = 0;
- ifield[1] = skb->private.ifield;
+ ifield[1] = hcb->ifield;
/*
* We don't need the lock before we are actually going to start
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 7092ca6b277e..7cefe5507b9e 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -1,5 +1,5 @@
/************************************************************************
- * regs.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * regs.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -62,6 +62,7 @@ typedef struct _XENA_dev_config {
#define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6)
#define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7)
#define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8)
+#define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE vBIT(0x0F,8,8)
#define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8)
#define ADAPTER_STATUS_MC_DRAM_READY BIT(24)
#define ADAPTER_STATUS_MC_QUEUES_READY BIT(25)
@@ -77,21 +78,34 @@ typedef struct _XENA_dev_config {
#define ADAPTER_ECC_EN BIT(55)
u64 serr_source;
-#define SERR_SOURCE_PIC BIT(0)
-#define SERR_SOURCE_TXDMA BIT(1)
-#define SERR_SOURCE_RXDMA BIT(2)
+#define SERR_SOURCE_PIC BIT(0)
+#define SERR_SOURCE_TXDMA BIT(1)
+#define SERR_SOURCE_RXDMA BIT(2)
#define SERR_SOURCE_MAC BIT(3)
#define SERR_SOURCE_MC BIT(4)
#define SERR_SOURCE_XGXS BIT(5)
-#define SERR_SOURCE_ANY (SERR_SOURCE_PIC | \
- SERR_SOURCE_TXDMA | \
- SERR_SOURCE_RXDMA | \
- SERR_SOURCE_MAC | \
- SERR_SOURCE_MC | \
- SERR_SOURCE_XGXS)
-
-
- u8 unused_0[0x800 - 0x120];
+#define SERR_SOURCE_ANY (SERR_SOURCE_PIC | \
+ SERR_SOURCE_TXDMA | \
+ SERR_SOURCE_RXDMA | \
+ SERR_SOURCE_MAC | \
+ SERR_SOURCE_MC | \
+ SERR_SOURCE_XGXS)
+
+ u64 pci_mode;
+#define GET_PCI_MODE(val) ((val & vBIT(0xF, 0, 4)) >> 60)
+#define PCI_MODE_PCI_33 0
+#define PCI_MODE_PCI_66 0x1
+#define PCI_MODE_PCIX_M1_66 0x2
+#define PCI_MODE_PCIX_M1_100 0x3
+#define PCI_MODE_PCIX_M1_133 0x4
+#define PCI_MODE_PCIX_M2_66 0x5
+#define PCI_MODE_PCIX_M2_100 0x6
+#define PCI_MODE_PCIX_M2_133 0x7
+#define PCI_MODE_UNSUPPORTED BIT(0)
+#define PCI_MODE_32_BITS BIT(8)
+#define PCI_MODE_UNKNOWN_MODE BIT(9)
+
+ u8 unused_0[0x800 - 0x128];
/* PCI-X Controller registers */
u64 pic_int_status;
@@ -153,7 +167,11 @@ typedef struct _XENA_dev_config {
u8 unused4[0x08];
u64 gpio_int_reg;
+#define GPIO_INT_REG_LINK_DOWN BIT(1)
+#define GPIO_INT_REG_LINK_UP BIT(2)
u64 gpio_int_mask;
+#define GPIO_INT_MASK_LINK_DOWN BIT(1)
+#define GPIO_INT_MASK_LINK_UP BIT(2)
u64 gpio_alarms;
u8 unused5[0x38];
@@ -223,19 +241,16 @@ typedef struct _XENA_dev_config {
u64 xmsi_data;
u64 rx_mat;
+#define RX_MAT_SET(ring, msi) vBIT(msi, (8 * ring), 8)
u8 unused6[0x8];
- u64 tx_mat0_7;
- u64 tx_mat8_15;
- u64 tx_mat16_23;
- u64 tx_mat24_31;
- u64 tx_mat32_39;
- u64 tx_mat40_47;
- u64 tx_mat48_55;
- u64 tx_mat56_63;
+ u64 tx_mat0_n[0x8];
+#define TX_MAT_SET(fifo, msi) vBIT(msi, (8 * fifo), 8)
- u8 unused_1[0x10];
+ u8 unused_1[0x8];
+ u64 stat_byte_cnt;
+#define STAT_BC(n) vBIT(n,4,12)
/* Automated statistics collection */
u64 stat_cfg;
@@ -246,6 +261,7 @@ typedef struct _XENA_dev_config {
#define STAT_TRSF_PER(n) TBD
#define PER_SEC 0x208d5
#define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32)
+#define SET_UPDT_CLICKS(val) vBIT(val, 32, 32)
u64 stat_addr;
@@ -267,8 +283,15 @@ typedef struct _XENA_dev_config {
u64 gpio_control;
#define GPIO_CTRL_GPIO_0 BIT(8)
+ u64 misc_control;
+#define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3)
+
+ u8 unused7_1[0x240 - 0x208];
+
+ u64 wreq_split_mask;
+#define WREQ_SPLIT_MASK_SET_MASK(val) vBIT(val, 52, 12)
- u8 unused7[0x600];
+ u8 unused7_2[0x800 - 0x248];
/* TxDMA registers */
u64 txdma_int_status;
@@ -290,6 +313,7 @@ typedef struct _XENA_dev_config {
u64 pcc_err_reg;
#define PCC_FB_ECC_DB_ERR vBIT(0xFF, 16, 8)
+#define PCC_ENABLE_FOUR vBIT(0x0F,0,8)
u64 pcc_err_mask;
u64 pcc_err_alarm;
@@ -468,6 +492,7 @@ typedef struct _XENA_dev_config {
#define PRC_CTRL_NO_SNOOP (BIT(22)|BIT(23))
#define PRC_CTRL_NO_SNOOP_DESC BIT(22)
#define PRC_CTRL_NO_SNOOP_BUFF BIT(23)
+#define PRC_CTRL_BIMODAL_INTERRUPT BIT(37)
#define PRC_CTRL_RXD_BACKOFF_INTERVAL(val) vBIT(val,40,24)
u64 prc_alarm_action;
@@ -688,9 +713,16 @@ typedef struct _XENA_dev_config {
u64 mc_err_reg;
#define MC_ERR_REG_ECC_DB_ERR_L BIT(14)
#define MC_ERR_REG_ECC_DB_ERR_U BIT(15)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_0 BIT(18)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_1 BIT(20)
#define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22)
#define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23)
#define MC_ERR_REG_SM_ERR BIT(31)
+#define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\
+ BIT(6) | BIT(7) | BIT(17) | BIT(19))
+#define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\
+ BIT(13) | BIT(14) | BIT(15) |\
+ BIT(18) | BIT(20))
u64 mc_err_mask;
u64 mc_err_alarm;
@@ -736,7 +768,19 @@ typedef struct _XENA_dev_config {
u64 mc_rldram_test_d1;
u8 unused24[0x300 - 0x288];
u64 mc_rldram_test_d2;
- u8 unused25[0x700 - 0x308];
+
+ u8 unused24_1[0x360 - 0x308];
+ u64 mc_rldram_ctrl;
+#define MC_RLDRAM_ENABLE_ODT BIT(7)
+
+ u8 unused24_2[0x640 - 0x368];
+ u64 mc_rldram_ref_per_herc;
+#define MC_RLDRAM_SET_REF_PERIOD(val) vBIT(val, 0, 16)
+
+ u8 unused24_3[0x660 - 0x648];
+ u64 mc_rldram_mrs_herc;
+
+ u8 unused25[0x700 - 0x668];
u64 mc_debug_ctrl;
u8 unused26[0x3000 - 0x2f08];
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index ea638b162d3f..c829e6a2e8a6 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,5 +1,5 @@
/************************************************************************
- * s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -11,29 +11,28 @@
* See the file COPYING in this distribution for more information.
*
* Credits:
- * Jeff Garzik : For pointing out the improper error condition
- * check in the s2io_xmit routine and also some
- * issues in the Tx watch dog function. Also for
- * patiently answering all those innumerable
+ * Jeff Garzik : For pointing out the improper error condition
+ * check in the s2io_xmit routine and also some
+ * issues in the Tx watch dog function. Also for
+ * patiently answering all those innumerable
* questions regaring the 2.6 porting issues.
* Stephen Hemminger : Providing proper 2.6 porting mechanism for some
* macros available only in 2.6 Kernel.
- * Francois Romieu : For pointing out all code part that were
+ * Francois Romieu : For pointing out all code part that were
* deprecated and also styling related comments.
- * Grant Grundler : For helping me get rid of some Architecture
+ * Grant Grundler : For helping me get rid of some Architecture
* dependent code.
* Christopher Hellwig : Some more 2.6 specific issues in the driver.
- *
+ *
* The module loadable parameters that are supported by the driver and a brief
* explaination of all the variables.
- * rx_ring_num : This can be used to program the number of receive rings used
- * in the driver.
- * rx_ring_len: This defines the number of descriptors each ring can have. This
+ * rx_ring_num : This can be used to program the number of receive rings used
+ * in the driver.
+ * rx_ring_sz: This defines the number of descriptors each ring can have. This
* is also an array of size 8.
* tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
- * tx_fifo_len: This too is an array of 8. Each element defines the number of
+ * tx_fifo_len: This too is an array of 8. Each element defines the number of
* Tx descriptors that can be associated with each corresponding FIFO.
- * in PCI Configuration space.
************************************************************************/
#include <linux/config.h>
@@ -56,27 +55,39 @@
#include <linux/ethtool.h>
#include <linux/version.h>
#include <linux/workqueue.h>
+#include <linux/if_vlan.h>
-#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
/* local include */
#include "s2io.h"
#include "s2io-regs.h"
/* S2io Driver name & version. */
-static char s2io_driver_name[] = "s2io";
-static char s2io_driver_version[] = "Version 1.7.7.1";
+static char s2io_driver_name[] = "Neterion";
+static char s2io_driver_version[] = "Version 2.0.8.1";
-/*
+static inline int RXD_IS_UP2DT(RxD_t *rxdp)
+{
+ int ret;
+
+ ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
+ (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
+
+ return ret;
+}
+
+/*
* Cards with following subsystem_id have a link state indication
* problem, 600B, 600C, 600D, 640B, 640C and 640D.
* macro below identifies these cards given the subsystem_id.
*/
-#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \
- (((subid >= 0x600B) && (subid <= 0x600D)) || \
- ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0
+#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
+ (dev_type == XFRAME_I_DEVICE) ? \
+ ((((subid >= 0x600B) && (subid <= 0x600D)) || \
+ ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
#define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
@@ -86,9 +97,12 @@ static char s2io_driver_version[] = "Version 1.7.7.1";
static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
{
int level = 0;
- if ((sp->pkt_cnt[ring] - rxb_size) > 16) {
+ mac_info_t *mac_control;
+
+ mac_control = &sp->mac_control;
+ if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
level = LOW;
- if ((sp->pkt_cnt[ring] - rxb_size) < MAX_RXDS_PER_BLOCK) {
+ if (rxb_size <= MAX_RXDS_PER_BLOCK) {
level = PANIC;
}
}
@@ -145,6 +159,9 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
{"rmac_pause_cnt"},
{"rmac_accepted_ip"},
{"rmac_err_tcp"},
+ {"\n DRIVER STATISTICS"},
+ {"single_bit_ecc_errs"},
+ {"double_bit_ecc_errs"},
};
#define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
@@ -153,8 +170,37 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
#define S2IO_TEST_LEN sizeof(s2io_gstrings) / ETH_GSTRING_LEN
#define S2IO_STRINGS_LEN S2IO_TEST_LEN * ETH_GSTRING_LEN
+#define S2IO_TIMER_CONF(timer, handle, arg, exp) \
+ init_timer(&timer); \
+ timer.function = handle; \
+ timer.data = (unsigned long) arg; \
+ mod_timer(&timer, (jiffies + exp)) \
-/*
+/* Add the vlan */
+static void s2io_vlan_rx_register(struct net_device *dev,
+ struct vlan_group *grp)
+{
+ nic_t *nic = dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nic->tx_lock, flags);
+ nic->vlgrp = grp;
+ spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
+/* Unregister the vlan */
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+{
+ nic_t *nic = dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nic->tx_lock, flags);
+ if (nic->vlgrp)
+ nic->vlgrp->vlan_devices[vid] = NULL;
+ spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
+/*
* Constants to be programmed into the Xena's registers, to configure
* the XAUI.
*/
@@ -162,7 +208,28 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL
#define END_SIGN 0x0
-static u64 default_mdio_cfg[] = {
+static u64 herc_act_dtx_cfg[] = {
+ /* Set address */
+ 0x8000051536750000ULL, 0x80000515367500E0ULL,
+ /* Write data */
+ 0x8000051536750004ULL, 0x80000515367500E4ULL,
+ /* Set address */
+ 0x80010515003F0000ULL, 0x80010515003F00E0ULL,
+ /* Write data */
+ 0x80010515003F0004ULL, 0x80010515003F00E4ULL,
+ /* Set address */
+ 0x801205150D440000ULL, 0x801205150D4400E0ULL,
+ /* Write data */
+ 0x801205150D440004ULL, 0x801205150D4400E4ULL,
+ /* Set address */
+ 0x80020515F2100000ULL, 0x80020515F21000E0ULL,
+ /* Write data */
+ 0x80020515F2100004ULL, 0x80020515F21000E4ULL,
+ /* Done */
+ END_SIGN
+};
+
+static u64 xena_mdio_cfg[] = {
/* Reset PMA PLL */
0xC001010000000000ULL, 0xC0010100000000E0ULL,
0xC0010100008000E4ULL,
@@ -172,7 +239,7 @@ static u64 default_mdio_cfg[] = {
END_SIGN
};
-static u64 default_dtx_cfg[] = {
+static u64 xena_dtx_cfg[] = {
0x8000051500000000ULL, 0x80000515000000E0ULL,
0x80000515D93500E4ULL, 0x8001051500000000ULL,
0x80010515000000E0ULL, 0x80010515001E00E4ULL,
@@ -196,8 +263,7 @@ static u64 default_dtx_cfg[] = {
END_SIGN
};
-
-/*
+/*
* Constants for Fixing the MacAddress problem seen mostly on
* Alpha machines.
*/
@@ -226,20 +292,25 @@ static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
static unsigned int rx_ring_num = 1;
static unsigned int rx_ring_sz[MAX_RX_RINGS] =
{[0 ...(MAX_RX_RINGS - 1)] = 0 };
-static unsigned int Stats_refresh_time = 4;
+static unsigned int rts_frm_len[MAX_RX_RINGS] =
+ {[0 ...(MAX_RX_RINGS - 1)] = 0 };
+static unsigned int use_continuous_tx_intrs = 1;
static unsigned int rmac_pause_time = 65535;
static unsigned int mc_pause_threshold_q0q3 = 187;
static unsigned int mc_pause_threshold_q4q7 = 187;
static unsigned int shared_splits;
static unsigned int tmac_util_period = 5;
static unsigned int rmac_util_period = 5;
+static unsigned int bimodal = 0;
#ifndef CONFIG_S2IO_NAPI
static unsigned int indicate_max_pkts;
#endif
+/* Frequency of Rx desc syncs expressed as power of 2 */
+static unsigned int rxsync_frequency = 3;
-/*
+/*
* S2IO device table.
- * This table lists all the devices that this driver supports.
+ * This table lists all the devices that this driver supports.
*/
static struct pci_device_id s2io_tbl[] __devinitdata = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
@@ -247,9 +318,9 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
- PCI_ANY_ID, PCI_ANY_ID},
- {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
- PCI_ANY_ID, PCI_ANY_ID},
+ PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+ PCI_ANY_ID, PCI_ANY_ID},
{0,}
};
@@ -268,8 +339,8 @@ static struct pci_driver s2io_driver = {
/**
* init_shared_mem - Allocation and Initialization of Memory
* @nic: Device private variable.
- * Description: The function allocates all the memory areas shared
- * between the NIC and the driver. This includes Tx descriptors,
+ * Description: The function allocates all the memory areas shared
+ * between the NIC and the driver. This includes Tx descriptors,
* Rx descriptors and the statistics block.
*/
@@ -279,7 +350,7 @@ static int init_shared_mem(struct s2io_nic *nic)
void *tmp_v_addr, *tmp_v_addr_next;
dma_addr_t tmp_p_addr, tmp_p_addr_next;
RxD_block_t *pre_rxd_blk = NULL;
- int i, j, blk_cnt;
+ int i, j, blk_cnt, rx_sz, tx_sz;
int lst_size, lst_per_page;
struct net_device *dev = nic->dev;
#ifdef CONFIG_2BUFF_MODE
@@ -300,36 +371,41 @@ static int init_shared_mem(struct s2io_nic *nic)
size += config->tx_cfg[i].fifo_len;
}
if (size > MAX_AVAILABLE_TXDS) {
- DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ",
- dev->name);
- DBG_PRINT(ERR_DBG, "exceeds the maximum value ");
- DBG_PRINT(ERR_DBG, "that can be used\n");
+ DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
+ __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
return FAILURE;
}
lst_size = (sizeof(TxD_t) * config->max_txds);
+ tx_sz = lst_size * size;
lst_per_page = PAGE_SIZE / lst_size;
for (i = 0; i < config->tx_fifo_num; i++) {
int fifo_len = config->tx_cfg[i].fifo_len;
int list_holder_size = fifo_len * sizeof(list_info_hold_t);
- nic->list_info[i] = kmalloc(list_holder_size, GFP_KERNEL);
- if (!nic->list_info[i]) {
+ mac_control->fifos[i].list_info = kmalloc(list_holder_size,
+ GFP_KERNEL);
+ if (!mac_control->fifos[i].list_info) {
DBG_PRINT(ERR_DBG,
"Malloc failed for list_info\n");
return -ENOMEM;
}
- memset(nic->list_info[i], 0, list_holder_size);
+ memset(mac_control->fifos[i].list_info, 0, list_holder_size);
}
for (i = 0; i < config->tx_fifo_num; i++) {
int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
lst_per_page);
- mac_control->tx_curr_put_info[i].offset = 0;
- mac_control->tx_curr_put_info[i].fifo_len =
+ mac_control->fifos[i].tx_curr_put_info.offset = 0;
+ mac_control->fifos[i].tx_curr_put_info.fifo_len =
config->tx_cfg[i].fifo_len - 1;
- mac_control->tx_curr_get_info[i].offset = 0;
- mac_control->tx_curr_get_info[i].fifo_len =
+ mac_control->fifos[i].tx_curr_get_info.offset = 0;
+ mac_control->fifos[i].tx_curr_get_info.fifo_len =
config->tx_cfg[i].fifo_len - 1;
+ mac_control->fifos[i].fifo_no = i;
+ mac_control->fifos[i].nic = nic;
+ mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
+
for (j = 0; j < page_num; j++) {
int k = 0;
dma_addr_t tmp_p;
@@ -342,19 +418,38 @@ static int init_shared_mem(struct s2io_nic *nic)
DBG_PRINT(ERR_DBG, "failed for TxDL\n");
return -ENOMEM;
}
+ /* If we got a zero DMA address(can happen on
+ * certain platforms like PPC), reallocate.
+ * Store virtual address of page we don't want,
+ * to be freed later.
+ */
+ if (!tmp_p) {
+ mac_control->zerodma_virt_addr = tmp_v;
+ DBG_PRINT(INIT_DBG,
+ "%s: Zero DMA address for TxDL. ", dev->name);
+ DBG_PRINT(INIT_DBG,
+ "Virtual address %llx\n", (u64)tmp_v);
+ tmp_v = pci_alloc_consistent(nic->pdev,
+ PAGE_SIZE, &tmp_p);
+ if (!tmp_v) {
+ DBG_PRINT(ERR_DBG,
+ "pci_alloc_consistent ");
+ DBG_PRINT(ERR_DBG, "failed for TxDL\n");
+ return -ENOMEM;
+ }
+ }
while (k < lst_per_page) {
int l = (j * lst_per_page) + k;
if (l == config->tx_cfg[i].fifo_len)
- goto end_txd_alloc;
- nic->list_info[i][l].list_virt_addr =
+ break;
+ mac_control->fifos[i].list_info[l].list_virt_addr =
tmp_v + (k * lst_size);
- nic->list_info[i][l].list_phy_addr =
+ mac_control->fifos[i].list_info[l].list_phy_addr =
tmp_p + (k * lst_size);
k++;
}
}
}
- end_txd_alloc:
/* Allocation and initialization of RXDs in Rings */
size = 0;
@@ -367,21 +462,26 @@ static int init_shared_mem(struct s2io_nic *nic)
return FAILURE;
}
size += config->rx_cfg[i].num_rxd;
- nic->block_count[i] =
+ mac_control->rings[i].block_count =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- nic->pkt_cnt[i] =
- config->rx_cfg[i].num_rxd - nic->block_count[i];
+ mac_control->rings[i].pkt_cnt =
+ config->rx_cfg[i].num_rxd - mac_control->rings[i].block_count;
}
+ size = (size * (sizeof(RxD_t)));
+ rx_sz = size;
for (i = 0; i < config->rx_ring_num; i++) {
- mac_control->rx_curr_get_info[i].block_index = 0;
- mac_control->rx_curr_get_info[i].offset = 0;
- mac_control->rx_curr_get_info[i].ring_len =
+ mac_control->rings[i].rx_curr_get_info.block_index = 0;
+ mac_control->rings[i].rx_curr_get_info.offset = 0;
+ mac_control->rings[i].rx_curr_get_info.ring_len =
config->rx_cfg[i].num_rxd - 1;
- mac_control->rx_curr_put_info[i].block_index = 0;
- mac_control->rx_curr_put_info[i].offset = 0;
- mac_control->rx_curr_put_info[i].ring_len =
+ mac_control->rings[i].rx_curr_put_info.block_index = 0;
+ mac_control->rings[i].rx_curr_put_info.offset = 0;
+ mac_control->rings[i].rx_curr_put_info.ring_len =
config->rx_cfg[i].num_rxd - 1;
+ mac_control->rings[i].nic = nic;
+ mac_control->rings[i].ring_no = i;
+
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
/* Allocating all the Rx blocks */
@@ -395,32 +495,36 @@ static int init_shared_mem(struct s2io_nic *nic)
&tmp_p_addr);
if (tmp_v_addr == NULL) {
/*
- * In case of failure, free_shared_mem()
- * is called, which should free any
- * memory that was alloced till the
+ * In case of failure, free_shared_mem()
+ * is called, which should free any
+ * memory that was alloced till the
* failure happened.
*/
- nic->rx_blocks[i][j].block_virt_addr =
+ mac_control->rings[i].rx_blocks[j].block_virt_addr =
tmp_v_addr;
return -ENOMEM;
}
memset(tmp_v_addr, 0, size);
- nic->rx_blocks[i][j].block_virt_addr = tmp_v_addr;
- nic->rx_blocks[i][j].block_dma_addr = tmp_p_addr;
+ mac_control->rings[i].rx_blocks[j].block_virt_addr =
+ tmp_v_addr;
+ mac_control->rings[i].rx_blocks[j].block_dma_addr =
+ tmp_p_addr;
}
/* Interlinking all Rx Blocks */
for (j = 0; j < blk_cnt; j++) {
- tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
+ tmp_v_addr =
+ mac_control->rings[i].rx_blocks[j].block_virt_addr;
tmp_v_addr_next =
- nic->rx_blocks[i][(j + 1) %
+ mac_control->rings[i].rx_blocks[(j + 1) %
blk_cnt].block_virt_addr;
- tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+ tmp_p_addr =
+ mac_control->rings[i].rx_blocks[j].block_dma_addr;
tmp_p_addr_next =
- nic->rx_blocks[i][(j + 1) %
+ mac_control->rings[i].rx_blocks[(j + 1) %
blk_cnt].block_dma_addr;
pre_rxd_blk = (RxD_block_t *) tmp_v_addr;
- pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
+ pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
* marker.
*/
#ifndef CONFIG_2BUFF_MODE
@@ -433,28 +537,28 @@ static int init_shared_mem(struct s2io_nic *nic)
}
#ifdef CONFIG_2BUFF_MODE
- /*
+ /*
* Allocation of Storages for buffer addresses in 2BUFF mode
* and the buffers as well.
*/
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
+ mac_control->rings[i].ba = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
GFP_KERNEL);
- if (!nic->ba[i])
+ if (!mac_control->rings[i].ba)
return -ENOMEM;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) *
+ mac_control->rings[i].ba[j] = kmalloc((sizeof(buffAdd_t) *
(MAX_RXDS_PER_BLOCK + 1)),
GFP_KERNEL);
- if (!nic->ba[i][j])
+ if (!mac_control->rings[i].ba[j])
return -ENOMEM;
while (k != MAX_RXDS_PER_BLOCK) {
- ba = &nic->ba[i][j][k];
+ ba = &mac_control->rings[i].ba[j][k];
- ba->ba_0_org = kmalloc
+ ba->ba_0_org = (void *) kmalloc
(BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
if (!ba->ba_0_org)
return -ENOMEM;
@@ -463,7 +567,7 @@ static int init_shared_mem(struct s2io_nic *nic)
tmp &= ~((unsigned long) ALIGN_SIZE);
ba->ba_0 = (void *) tmp;
- ba->ba_1_org = kmalloc
+ ba->ba_1_org = (void *) kmalloc
(BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
if (!ba->ba_1_org)
return -ENOMEM;
@@ -483,9 +587,9 @@ static int init_shared_mem(struct s2io_nic *nic)
(nic->pdev, size, &mac_control->stats_mem_phy);
if (!mac_control->stats_mem) {
- /*
- * In case of failure, free_shared_mem() is called, which
- * should free any memory that was alloced till the
+ /*
+ * In case of failure, free_shared_mem() is called, which
+ * should free any memory that was alloced till the
* failure happened.
*/
return -ENOMEM;
@@ -495,15 +599,14 @@ static int init_shared_mem(struct s2io_nic *nic)
tmp_v_addr = mac_control->stats_mem;
mac_control->stats_info = (StatInfo_t *) tmp_v_addr;
memset(tmp_v_addr, 0, size);
-
DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,
(unsigned long long) tmp_p_addr);
return SUCCESS;
}
-/**
- * free_shared_mem - Free the allocated Memory
+/**
+ * free_shared_mem - Free the allocated Memory
* @nic: Device private variable.
* Description: This function is to free all memory locations allocated by
* the init_shared_mem() function and return it to the kernel.
@@ -517,7 +620,7 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_info_t *mac_control;
struct config_param *config;
int lst_size, lst_per_page;
-
+ struct net_device *dev = nic->dev;
if (!nic)
return;
@@ -533,15 +636,32 @@ static void free_shared_mem(struct s2io_nic *nic)
lst_per_page);
for (j = 0; j < page_num; j++) {
int mem_blks = (j * lst_per_page);
- if (!nic->list_info[i][mem_blks].list_virt_addr)
+ if (!mac_control->fifos[i].list_info)
+ return;
+ if (!mac_control->fifos[i].list_info[mem_blks].
+ list_virt_addr)
break;
pci_free_consistent(nic->pdev, PAGE_SIZE,
- nic->list_info[i][mem_blks].
+ mac_control->fifos[i].
+ list_info[mem_blks].
list_virt_addr,
- nic->list_info[i][mem_blks].
+ mac_control->fifos[i].
+ list_info[mem_blks].
list_phy_addr);
}
- kfree(nic->list_info[i]);
+ /* If we got a zero DMA address during allocation,
+ * free the page now
+ */
+ if (mac_control->zerodma_virt_addr) {
+ pci_free_consistent(nic->pdev, PAGE_SIZE,
+ mac_control->zerodma_virt_addr,
+ (dma_addr_t)0);
+ DBG_PRINT(INIT_DBG,
+ "%s: Freeing TxDL with zero DMA addr. ", dev->name);
+ DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
+ (u64)(mac_control->zerodma_virt_addr));
+ }
+ kfree(mac_control->fifos[i].list_info);
}
#ifndef CONFIG_2BUFF_MODE
@@ -550,10 +670,12 @@ static void free_shared_mem(struct s2io_nic *nic)
size = SIZE_OF_BLOCK;
#endif
for (i = 0; i < config->rx_ring_num; i++) {
- blk_cnt = nic->block_count[i];
+ blk_cnt = mac_control->rings[i].block_count;
for (j = 0; j < blk_cnt; j++) {
- tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
- tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+ tmp_v_addr = mac_control->rings[i].rx_blocks[j].
+ block_virt_addr;
+ tmp_p_addr = mac_control->rings[i].rx_blocks[j].
+ block_dma_addr;
if (tmp_v_addr == NULL)
break;
pci_free_consistent(nic->pdev, size,
@@ -566,35 +688,21 @@ static void free_shared_mem(struct s2io_nic *nic)
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- if (!nic->ba[i])
- goto end_free;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- if (!nic->ba[i][j]) {
- kfree(nic->ba[i]);
- goto end_free;
- }
+ if (!mac_control->rings[i].ba[j])
+ continue;
while (k != MAX_RXDS_PER_BLOCK) {
- buffAdd_t *ba = &nic->ba[i][j][k];
- if (!ba || !ba->ba_0_org || !ba->ba_1_org)
- {
- kfree(nic->ba[i]);
- kfree(nic->ba[i][j]);
- if(ba->ba_0_org)
- kfree(ba->ba_0_org);
- if(ba->ba_1_org)
- kfree(ba->ba_1_org);
- goto end_free;
- }
+ buffAdd_t *ba = &mac_control->rings[i].ba[j][k];
kfree(ba->ba_0_org);
kfree(ba->ba_1_org);
k++;
}
- kfree(nic->ba[i][j]);
+ kfree(mac_control->rings[i].ba[j]);
}
- kfree(nic->ba[i]);
+ if (mac_control->rings[i].ba)
+ kfree(mac_control->rings[i].ba);
}
-end_free:
#endif
if (mac_control->stats_mem) {
@@ -605,12 +713,93 @@ end_free:
}
}
-/**
- * init_nic - Initialization of hardware
+/**
+ * s2io_verify_pci_mode -
+ */
+
+static int s2io_verify_pci_mode(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ register u64 val64 = 0;
+ int mode;
+
+ val64 = readq(&bar0->pci_mode);
+ mode = (u8)GET_PCI_MODE(val64);
+
+ if ( val64 & PCI_MODE_UNKNOWN_MODE)
+ return -1; /* Unknown PCI mode */
+ return mode;
+}
+
+
+/**
+ * s2io_print_pci_mode -
+ */
+static int s2io_print_pci_mode(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ register u64 val64 = 0;
+ int mode;
+ struct config_param *config = &nic->config;
+
+ val64 = readq(&bar0->pci_mode);
+ mode = (u8)GET_PCI_MODE(val64);
+
+ if ( val64 & PCI_MODE_UNKNOWN_MODE)
+ return -1; /* Unknown PCI mode */
+
+ if (val64 & PCI_MODE_32_BITS) {
+ DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
+ } else {
+ DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
+ }
+
+ switch(mode) {
+ case PCI_MODE_PCI_33:
+ DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
+ config->bus_speed = 33;
+ break;
+ case PCI_MODE_PCI_66:
+ DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
+ config->bus_speed = 133;
+ break;
+ case PCI_MODE_PCIX_M1_66:
+ DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
+ config->bus_speed = 133; /* Herc doubles the clock rate */
+ break;
+ case PCI_MODE_PCIX_M1_100:
+ DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
+ config->bus_speed = 200;
+ break;
+ case PCI_MODE_PCIX_M1_133:
+ DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
+ config->bus_speed = 266;
+ break;
+ case PCI_MODE_PCIX_M2_66:
+ DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
+ config->bus_speed = 133;
+ break;
+ case PCI_MODE_PCIX_M2_100:
+ DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
+ config->bus_speed = 200;
+ break;
+ case PCI_MODE_PCIX_M2_133:
+ DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
+ config->bus_speed = 266;
+ break;
+ default:
+ return -1; /* Unsupported bus speed */
+ }
+
+ return mode;
+}
+
+/**
+ * init_nic - Initialization of hardware
* @nic: device peivate variable
- * Description: The function sequentially configures every block
- * of the H/W from their reset values.
- * Return Value: SUCCESS on success and
+ * Description: The function sequentially configures every block
+ * of the H/W from their reset values.
+ * Return Value: SUCCESS on success and
* '-1' on failure (endian settings incorrect).
*/
@@ -626,21 +815,32 @@ static int init_nic(struct s2io_nic *nic)
struct config_param *config;
int mdio_cnt = 0, dtx_cnt = 0;
unsigned long long mem_share;
+ int mem_size;
mac_control = &nic->mac_control;
config = &nic->config;
- /* Initialize swapper control register */
- if (s2io_set_swapper(nic)) {
+ /* to set the swapper controle on the card */
+ if(s2io_set_swapper(nic)) {
DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
return -1;
}
+ /*
+ * Herc requires EOI to be removed from reset before XGXS, so..
+ */
+ if (nic->device_type & XFRAME_II_DEVICE) {
+ val64 = 0xA500000000ULL;
+ writeq(val64, &bar0->sw_reset);
+ msleep(500);
+ val64 = readq(&bar0->sw_reset);
+ }
+
/* Remove XGXS from reset state */
val64 = 0;
writeq(val64, &bar0->sw_reset);
- val64 = readq(&bar0->sw_reset);
msleep(500);
+ val64 = readq(&bar0->sw_reset);
/* Enable Receiving broadcasts */
add = &bar0->mac_cfg;
@@ -660,48 +860,58 @@ static int init_nic(struct s2io_nic *nic)
val64 = dev->mtu;
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
- /*
- * Configuring the XAUI Interface of Xena.
+ /*
+ * Configuring the XAUI Interface of Xena.
* ***************************************
- * To Configure the Xena's XAUI, one has to write a series
- * of 64 bit values into two registers in a particular
- * sequence. Hence a macro 'SWITCH_SIGN' has been defined
- * which will be defined in the array of configuration values
- * (default_dtx_cfg & default_mdio_cfg) at appropriate places
- * to switch writing from one regsiter to another. We continue
+ * To Configure the Xena's XAUI, one has to write a series
+ * of 64 bit values into two registers in a particular
+ * sequence. Hence a macro 'SWITCH_SIGN' has been defined
+ * which will be defined in the array of configuration values
+ * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
+ * to switch writing from one regsiter to another. We continue
* writing these values until we encounter the 'END_SIGN' macro.
- * For example, After making a series of 21 writes into
- * dtx_control register the 'SWITCH_SIGN' appears and hence we
+ * For example, After making a series of 21 writes into
+ * dtx_control register the 'SWITCH_SIGN' appears and hence we
* start writing into mdio_control until we encounter END_SIGN.
*/
- while (1) {
- dtx_cfg:
- while (default_dtx_cfg[dtx_cnt] != END_SIGN) {
- if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
- dtx_cnt++;
- goto mdio_cfg;
- }
- SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt],
+ if (nic->device_type & XFRAME_II_DEVICE) {
+ while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
+ SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
&bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
+ if (dtx_cnt & 0x1)
+ msleep(1); /* Necessary!! */
dtx_cnt++;
}
- mdio_cfg:
- while (default_mdio_cfg[mdio_cnt] != END_SIGN) {
- if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+ } else {
+ while (1) {
+ dtx_cfg:
+ while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+ if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
+ dtx_cnt++;
+ goto mdio_cfg;
+ }
+ SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+ &bar0->dtx_control, UF);
+ val64 = readq(&bar0->dtx_control);
+ dtx_cnt++;
+ }
+ mdio_cfg:
+ while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
+ if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+ mdio_cnt++;
+ goto dtx_cfg;
+ }
+ SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
+ &bar0->mdio_control, UF);
+ val64 = readq(&bar0->mdio_control);
mdio_cnt++;
+ }
+ if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
+ (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
+ break;
+ } else {
goto dtx_cfg;
}
- SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt],
- &bar0->mdio_control, UF);
- val64 = readq(&bar0->mdio_control);
- mdio_cnt++;
- }
- if ((default_dtx_cfg[dtx_cnt] == END_SIGN) &&
- (default_mdio_cfg[mdio_cnt] == END_SIGN)) {
- break;
- } else {
- goto dtx_cfg;
}
}
@@ -748,12 +958,20 @@ static int init_nic(struct s2io_nic *nic)
val64 |= BIT(0); /* To enable the FIFO partition. */
writeq(val64, &bar0->tx_fifo_partition_0);
+ /*
+ * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
+ * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
+ */
+ if ((nic->device_type == XFRAME_I_DEVICE) &&
+ (get_xena_rev_id(nic->pdev) < 4))
+ writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
+
val64 = readq(&bar0->tx_fifo_partition_0);
DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
&bar0->tx_fifo_partition_0, (unsigned long long) val64);
- /*
- * Initialization of Tx_PA_CONFIG register to ignore packet
+ /*
+ * Initialization of Tx_PA_CONFIG register to ignore packet
* integrity checking.
*/
val64 = readq(&bar0->tx_pa_cfg);
@@ -770,85 +988,304 @@ static int init_nic(struct s2io_nic *nic)
}
writeq(val64, &bar0->rx_queue_priority);
- /*
- * Allocating equal share of memory to all the
+ /*
+ * Allocating equal share of memory to all the
* configured Rings.
*/
val64 = 0;
+ if (nic->device_type & XFRAME_II_DEVICE)
+ mem_size = 32;
+ else
+ mem_size = 64;
+
for (i = 0; i < config->rx_ring_num; i++) {
switch (i) {
case 0:
- mem_share = (64 / config->rx_ring_num +
- 64 % config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num +
+ mem_size % config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);
continue;
case 1:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);
continue;
case 2:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);
continue;
case 3:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);
continue;
case 4:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);
continue;
case 5:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);
continue;
case 6:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);
continue;
case 7:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);
continue;
}
}
writeq(val64, &bar0->rx_queue_cfg);
- /*
- * Initializing the Tx round robin registers to 0.
- * Filling Tx and Rx round robin registers as per the
- * number of FIFOs and Rings is still TODO.
- */
- writeq(0, &bar0->tx_w_round_robin_0);
- writeq(0, &bar0->tx_w_round_robin_1);
- writeq(0, &bar0->tx_w_round_robin_2);
- writeq(0, &bar0->tx_w_round_robin_3);
- writeq(0, &bar0->tx_w_round_robin_4);
-
- /*
- * TODO
- * Disable Rx steering. Hard coding all packets be steered to
- * Queue 0 for now.
+ /*
+ * Filling Tx round robin registers
+ * as per the number of FIFOs
*/
- val64 = 0x8080808080808080ULL;
- writeq(val64, &bar0->rts_qos_steering);
+ switch (config->tx_fifo_num) {
+ case 1:
+ val64 = 0x0000000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 2:
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0100000100000100ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0001000001000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0100000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 3:
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0001020000010001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0200000100010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001020000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 4:
+ val64 = 0x0001020300010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0100000102030001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0200010000010203ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001020001000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0203000100000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 5:
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 6:
+ val64 = 0x0001020304000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0304050001020001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0203000100000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304000102030405ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001000200000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 7:
+ val64 = 0x0001020001020300ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0102030400010203ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0405060001020001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304050000010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0102030000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 8:
+ val64 = 0x0001020300040105ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0200030106000204ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0103000502010007ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304010002060500ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0103020400000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ }
+
+ /* Filling the Rx round robin registers as per the
+ * number of Rings and steering based on QoS.
+ */
+ switch (config->rx_ring_num) {
+ case 1:
+ val64 = 0x8080808080808080ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 2:
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0100000100000100ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0001000001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0100000000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080808040404040ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 3:
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0001020000010001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0200000100010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001020000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080804040402020ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 4:
+ val64 = 0x0001020300010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0100000102030001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0200010000010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001020001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0203000100000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020201010ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 5:
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001000000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020201008ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 6:
+ val64 = 0x0001020304000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0304050001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0203000100000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304000102030405ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001000200000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020100804ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 7:
+ val64 = 0x0001020001020300ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0102030400010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0405060001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304050000010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0102030000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080402010080402ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 8:
+ val64 = 0x0001020300040105ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0200030106000204ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0103000502010007ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304010002060500ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0103020400000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8040201008040201ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ }
/* UDP Fix */
val64 = 0;
- for (i = 1; i < 8; i++)
+ for (i = 0; i < 8; i++)
writeq(val64, &bar0->rts_frm_len_n[i]);
- /* Set rts_frm_len register for fifo 0 */
- writeq(MAC_RTS_FRM_LEN_SET(dev->mtu + 22),
- &bar0->rts_frm_len_n[0]);
+ /* Set the default rts frame length for the rings configured */
+ val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22);
+ for (i = 0 ; i < config->rx_ring_num ; i++)
+ writeq(val64, &bar0->rts_frm_len_n[i]);
+
+ /* Set the frame length for the configured rings
+ * desired by the user
+ */
+ for (i = 0; i < config->rx_ring_num; i++) {
+ /* If rts_frm_len[i] == 0 then it is assumed that user not
+ * specified frame length steering.
+ * If the user provides the frame length then program
+ * the rts_frm_len register for those values or else
+ * leave it as it is.
+ */
+ if (rts_frm_len[i] != 0) {
+ writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
+ &bar0->rts_frm_len_n[i]);
+ }
+ }
- /* Enable statistics */
+ /* Program statistics memory */
writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
- val64 = SET_UPDT_PERIOD(Stats_refresh_time) |
- STAT_CFG_STAT_RO | STAT_CFG_STAT_EN;
- writeq(val64, &bar0->stat_cfg);
- /*
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = STAT_BC(0x320);
+ writeq(val64, &bar0->stat_byte_cnt);
+ }
+
+ /*
* Initializing the sampling rate for the device to calculate the
* bandwidth utilization.
*/
@@ -857,30 +1294,38 @@ static int init_nic(struct s2io_nic *nic)
writeq(val64, &bar0->mac_link_util);
- /*
- * Initializing the Transmit and Receive Traffic Interrupt
+ /*
+ * Initializing the Transmit and Receive Traffic Interrupt
* Scheme.
*/
- /* TTI Initialization. Default Tx timer gets us about
+ /*
+ * TTI Initialization. Default Tx timer gets us about
* 250 interrupts per sec. Continuous interrupts are enabled
* by default.
*/
- val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
- TTI_DATA1_MEM_TX_URNG_A(0xA) |
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ int count = (nic->config.bus_speed * 125)/2;
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
+ } else {
+
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
+ }
+ val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
TTI_DATA1_MEM_TX_URNG_B(0x10) |
- TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
- TTI_DATA1_MEM_TX_TIMER_CI_EN;
+ TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
+ if (use_continuous_tx_intrs)
+ val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
TTI_DATA2_MEM_TX_UFC_B(0x20) |
- TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
+ TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80);
writeq(val64, &bar0->tti_data2_mem);
val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
writeq(val64, &bar0->tti_command_mem);
- /*
+ /*
* Once the operation completes, the Strobe bit of the command
* register will be reset. We poll for this particular condition
* We wait for a maximum of 500ms for the operation to complete,
@@ -901,45 +1346,90 @@ static int init_nic(struct s2io_nic *nic)
time++;
}
- /* RTI Initialization */
- val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) |
- RTI_DATA1_MEM_RX_URNG_A(0xA) |
- RTI_DATA1_MEM_RX_URNG_B(0x10) |
- RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+ if (nic->config.bimodal) {
+ int k = 0;
+ for (k = 0; k < config->rx_ring_num; k++) {
+ val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
+ val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
+ writeq(val64, &bar0->tti_command_mem);
+
+ /*
+ * Once the operation completes, the Strobe bit of the command
+ * register will be reset. We poll for this particular condition
+ * We wait for a maximum of 500ms for the operation to complete,
+ * if it's not complete by then we return error.
+ */
+ time = 0;
+ while (TRUE) {
+ val64 = readq(&bar0->tti_command_mem);
+ if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
+ break;
+ }
+ if (time > 10) {
+ DBG_PRINT(ERR_DBG,
+ "%s: TTI init Failed\n",
+ dev->name);
+ return -1;
+ }
+ time++;
+ msleep(50);
+ }
+ }
+ } else {
- writeq(val64, &bar0->rti_data1_mem);
+ /* RTI Initialization */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ /*
+ * Programmed to generate Apprx 500 Intrs per
+ * second
+ */
+ int count = (nic->config.bus_speed * 125)/4;
+ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+ } else {
+ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
+ }
+ val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+ RTI_DATA1_MEM_RX_URNG_B(0x10) |
+ RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
- val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
- RTI_DATA2_MEM_RX_UFC_B(0x2) |
- RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
- writeq(val64, &bar0->rti_data2_mem);
+ writeq(val64, &bar0->rti_data1_mem);
- val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD;
- writeq(val64, &bar0->rti_command_mem);
+ val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+ RTI_DATA2_MEM_RX_UFC_B(0x2) |
+ RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
+ writeq(val64, &bar0->rti_data2_mem);
- /*
- * Once the operation completes, the Strobe bit of the command
- * register will be reset. We poll for this particular condition
- * We wait for a maximum of 500ms for the operation to complete,
- * if it's not complete by then we return error.
- */
- time = 0;
- while (TRUE) {
- val64 = readq(&bar0->rti_command_mem);
- if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
- break;
- }
- if (time > 10) {
- DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
- dev->name);
- return -1;
+ for (i = 0; i < config->rx_ring_num; i++) {
+ val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
+ | RTI_CMD_MEM_OFFSET(i);
+ writeq(val64, &bar0->rti_command_mem);
+
+ /*
+ * Once the operation completes, the Strobe bit of the
+ * command register will be reset. We poll for this
+ * particular condition. We wait for a maximum of 500ms
+ * for the operation to complete, if it's not complete
+ * by then we return error.
+ */
+ time = 0;
+ while (TRUE) {
+ val64 = readq(&bar0->rti_command_mem);
+ if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
+ break;
+ }
+ if (time > 10) {
+ DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
+ dev->name);
+ return -1;
+ }
+ time++;
+ msleep(50);
+ }
}
- time++;
- msleep(50);
}
- /*
- * Initializing proper values as Pause threshold into all
+ /*
+ * Initializing proper values as Pause threshold into all
* the 8 Queues on Rx side.
*/
writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);
@@ -955,8 +1445,8 @@ static int init_nic(struct s2io_nic *nic)
writel((u32) (val64 >> 32), (add + 4));
val64 = readq(&bar0->mac_cfg);
- /*
- * Set the time value to be inserted in the pause frame
+ /*
+ * Set the time value to be inserted in the pause frame
* generated by xena.
*/
val64 = readq(&bar0->rmac_pause_cfg);
@@ -964,7 +1454,7 @@ static int init_nic(struct s2io_nic *nic)
val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);
writeq(val64, &bar0->rmac_pause_cfg);
- /*
+ /*
* Set the Threshold Limit for Generating the pause frame
* If the amount of data in any Queue exceeds ratio of
* (mac_control.mc_pause_threshold_q0q3 or q4q7)/256
@@ -988,25 +1478,54 @@ static int init_nic(struct s2io_nic *nic)
}
writeq(val64, &bar0->mc_pause_thresh_q4q7);
- /*
- * TxDMA will stop Read request if the number of read split has
+ /*
+ * TxDMA will stop Read request if the number of read split has
* exceeded the limit pointed by shared_splits
*/
val64 = readq(&bar0->pic_control);
val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
writeq(val64, &bar0->pic_control);
+ /*
+ * Programming the Herc to split every write transaction
+ * that does not start on an ADB to reduce disconnects.
+ */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = WREQ_SPLIT_MASK_SET_MASK(255);
+ writeq(val64, &bar0->wreq_split_mask);
+ }
+
+ /* Setting Link stability period to 64 ms */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = MISC_LINK_STABILITY_PRD(3);
+ writeq(val64, &bar0->misc_control);
+ }
+
return SUCCESS;
}
+#define LINK_UP_DOWN_INTERRUPT 1
+#define MAC_RMAC_ERR_TIMER 2
-/**
- * en_dis_able_nic_intrs - Enable or Disable the interrupts
+#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
+#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
+#else
+int s2io_link_fault_indication(nic_t *nic)
+{
+ if (nic->device_type == XFRAME_II_DEVICE)
+ return LINK_UP_DOWN_INTERRUPT;
+ else
+ return MAC_RMAC_ERR_TIMER;
+}
+#endif
+
+/**
+ * en_dis_able_nic_intrs - Enable or Disable the interrupts
* @nic: device private variable,
* @mask: A mask indicating which Intr block must be modified and,
* @flag: A flag indicating whether to enable or disable the Intrs.
* Description: This function will either disable or enable the interrupts
- * depending on the flag argument. The mask argument can be used to
- * enable/disable any Intr block.
+ * depending on the flag argument. The mask argument can be used to
+ * enable/disable any Intr block.
* Return Value: NONE.
*/
@@ -1024,20 +1543,31 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * Disabled all PCIX, Flash, MDIO, IIC and GPIO
- * interrupts for now.
- * TODO
+ /*
+ * If Hercules adapter enable GPIO otherwise
+ * disabled all PCIX, Flash, MDIO, IIC and GPIO
+ * interrupts for now.
+ * TODO
*/
- writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
- /*
+ if (s2io_link_fault_indication(nic) ==
+ LINK_UP_DOWN_INTERRUPT ) {
+ temp64 = readq(&bar0->pic_int_mask);
+ temp64 &= ~((u64) PIC_INT_GPIO);
+ writeq(temp64, &bar0->pic_int_mask);
+ temp64 = readq(&bar0->gpio_int_mask);
+ temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
+ writeq(temp64, &bar0->gpio_int_mask);
+ } else {
+ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
+ }
+ /*
* No MSI Support is available presently, so TTI and
* RTI interrupts are also disabled.
*/
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable PIC Intrs in the general
- * intr mask register
+ /*
+ * Disable PIC Intrs in the general
+ * intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1055,27 +1585,27 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * Keep all interrupts other than PFC interrupt
+ /*
+ * Keep all interrupts other than PFC interrupt
* and PCC interrupt disabled in DMA level.
*/
val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M |
TXDMA_PCC_INT_M);
writeq(val64, &bar0->txdma_int_mask);
- /*
- * Enable only the MISC error 1 interrupt in PFC block
+ /*
+ * Enable only the MISC error 1 interrupt in PFC block
*/
val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1);
writeq(val64, &bar0->pfc_err_mask);
- /*
- * Enable only the FB_ECC error interrupt in PCC block
+ /*
+ * Enable only the FB_ECC error interrupt in PCC block
*/
val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR);
writeq(val64, &bar0->pcc_err_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable TxDMA Intrs in the general intr mask
- * register
+ /*
+ * Disable TxDMA Intrs in the general intr mask
+ * register
*/
writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask);
writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask);
@@ -1093,15 +1623,15 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All RxDMA block interrupts are disabled for now
- * TODO
+ /*
+ * All RxDMA block interrupts are disabled for now
+ * TODO
*/
writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable RxDMA Intrs in the general intr mask
- * register
+ /*
+ * Disable RxDMA Intrs in the general intr mask
+ * register
*/
writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1118,22 +1648,13 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All MAC block error interrupts are disabled for now
- * except the link status change interrupt.
+ /*
+ * All MAC block error interrupts are disabled for now
* TODO
*/
- val64 = MAC_INT_STATUS_RMAC_INT;
- temp64 = readq(&bar0->mac_int_mask);
- temp64 &= ~((u64) val64);
- writeq(temp64, &bar0->mac_int_mask);
-
- val64 = readq(&bar0->mac_rmac_err_mask);
- val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT);
- writeq(val64, &bar0->mac_rmac_err_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable MAC Intrs in the general intr mask register
+ /*
+ * Disable MAC Intrs in the general intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
writeq(DISABLE_ALL_INTRS,
@@ -1152,14 +1673,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
+ /*
* All XGXS block error interrupts are disabled for now
- * TODO
+ * TODO
*/
writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable MC Intrs in the general intr mask register
+ /*
+ * Disable MC Intrs in the general intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1175,11 +1696,11 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All MC block error interrupts are disabled for now
- * TODO
+ /*
+ * Enable all MC Intrs.
*/
- writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask);
+ writeq(0x0, &bar0->mc_int_mask);
+ writeq(0x0, &bar0->mc_err_mask);
} else if (flag == DISABLE_INTRS) {
/*
* Disable MC Intrs in the general intr mask register
@@ -1199,14 +1720,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
+ /*
* Enable all the Tx side interrupts
- * writing 0 Enables all 64 TX interrupt levels
+ * writing 0 Enables all 64 TX interrupt levels
*/
writeq(0x0, &bar0->tx_traffic_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable Tx Traffic Intrs in the general intr mask
+ /*
+ * Disable Tx Traffic Intrs in the general intr mask
* register.
*/
writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
@@ -1226,8 +1747,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
/* writing 0 Enables all 8 RX interrupt levels */
writeq(0x0, &bar0->rx_traffic_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable Rx Traffic Intrs in the general intr mask
+ /*
+ * Disable Rx Traffic Intrs in the general intr mask
* register.
*/
writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
@@ -1238,24 +1759,66 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
}
}
-/**
- * verify_xena_quiescence - Checks whether the H/W is ready
+static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
+{
+ int ret = 0;
+
+ if (flag == FALSE) {
+ if ((!herc && (rev_id >= 4)) || herc) {
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+ ret = 1;
+ }
+ }else {
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+ ret = 1;
+ }
+ }
+ } else {
+ if ((!herc && (rev_id >= 4)) || herc) {
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
+ ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+ ret = 1;
+ }
+ } else {
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
+ ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+ ret = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+/**
+ * verify_xena_quiescence - Checks whether the H/W is ready
* @val64 : Value read from adapter status register.
* @flag : indicates if the adapter enable bit was ever written once
* before.
* Description: Returns whether the H/W is ready to go or not. Depending
- * on whether adapter enable bit was written or not the comparison
+ * on whether adapter enable bit was written or not the comparison
* differs and the calling function passes the input argument flag to
* indicate this.
- * Return: 1 If xena is quiescence
+ * Return: 1 If xena is quiescence
* 0 If Xena is not quiescence
*/
-static int verify_xena_quiescence(u64 val64, int flag)
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
{
- int ret = 0;
+ int ret = 0, herc;
u64 tmp64 = ~((u64) val64);
+ int rev_id = get_xena_rev_id(sp->pdev);
+ herc = (sp->device_type == XFRAME_II_DEVICE);
if (!
(tmp64 &
(ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY |
@@ -1263,25 +1826,7 @@ static int verify_xena_quiescence(u64 val64, int flag)
ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |
ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |
ADAPTER_STATUS_P_PLL_LOCK))) {
- if (flag == FALSE) {
- if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
- ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
-
- ret = 1;
-
- }
- } else {
- if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
- ADAPTER_STATUS_RMAC_PCC_IDLE) &&
- (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
- ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
-
- ret = 1;
-
- }
- }
+ ret = check_prc_pcc_state(val64, flag, rev_id, herc);
}
return ret;
@@ -1290,12 +1835,12 @@ static int verify_xena_quiescence(u64 val64, int flag)
/**
* fix_mac_address - Fix for Mac addr problem on Alpha platforms
* @sp: Pointer to device specifc structure
- * Description :
+ * Description :
* New procedure to clear mac address reading problems on Alpha platforms
*
*/
-static void fix_mac_address(nic_t * sp)
+void fix_mac_address(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
@@ -1303,20 +1848,21 @@ static void fix_mac_address(nic_t * sp)
while (fix_mac[i] != END_SIGN) {
writeq(fix_mac[i++], &bar0->gpio_control);
+ udelay(10);
val64 = readq(&bar0->gpio_control);
}
}
/**
- * start_nic - Turns the device on
+ * start_nic - Turns the device on
* @nic : device private variable.
- * Description:
- * This function actually turns the device on. Before this function is
- * called,all Registers are configured from their reset states
- * and shared memory is allocated but the NIC is still quiescent. On
+ * Description:
+ * This function actually turns the device on. Before this function is
+ * called,all Registers are configured from their reset states
+ * and shared memory is allocated but the NIC is still quiescent. On
* calling this function, the device interrupts are cleared and the NIC is
* literally switched on by writing into the adapter control register.
- * Return Value:
+ * Return Value:
* SUCCESS on success and -1 on failure.
*/
@@ -1325,8 +1871,8 @@ static int start_nic(struct s2io_nic *nic)
XENA_dev_config_t __iomem *bar0 = nic->bar0;
struct net_device *dev = nic->dev;
register u64 val64 = 0;
- u16 interruptible, i;
- u16 subid;
+ u16 interruptible;
+ u16 subid, i;
mac_info_t *mac_control;
struct config_param *config;
@@ -1335,10 +1881,12 @@ static int start_nic(struct s2io_nic *nic)
/* PRC Initialization and configuration */
for (i = 0; i < config->rx_ring_num; i++) {
- writeq((u64) nic->rx_blocks[i][0].block_dma_addr,
+ writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,
&bar0->prc_rxd0_n[i]);
val64 = readq(&bar0->prc_ctrl_n[i]);
+ if (nic->config.bimodal)
+ val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
#ifndef CONFIG_2BUFF_MODE
val64 |= PRC_CTRL_RC_ENABLED;
#else
@@ -1354,7 +1902,7 @@ static int start_nic(struct s2io_nic *nic)
writeq(val64, &bar0->rx_pa_cfg);
#endif
- /*
+ /*
* Enabling MC-RLDRAM. After enabling the device, we timeout
* for around 100ms, which is approximately the time required
* for the device to be ready for operation.
@@ -1364,27 +1912,27 @@ static int start_nic(struct s2io_nic *nic)
SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
val64 = readq(&bar0->mc_rldram_mrs);
- msleep(100); /* Delay by around 100 ms. */
+ msleep(100); /* Delay by around 100 ms. */
/* Enabling ECC Protection. */
val64 = readq(&bar0->adapter_control);
val64 &= ~ADAPTER_ECC_EN;
writeq(val64, &bar0->adapter_control);
- /*
- * Clearing any possible Link state change interrupts that
+ /*
+ * Clearing any possible Link state change interrupts that
* could have popped up just before Enabling the card.
*/
val64 = readq(&bar0->mac_rmac_err_reg);
if (val64)
writeq(val64, &bar0->mac_rmac_err_reg);
- /*
- * Verify if the device is ready to be enabled, if so enable
+ /*
+ * Verify if the device is ready to be enabled, if so enable
* it.
*/
val64 = readq(&bar0->adapter_status);
- if (!verify_xena_quiescence(val64, nic->device_enabled_once)) {
+ if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
(unsigned long long) val64);
@@ -1392,16 +1940,18 @@ static int start_nic(struct s2io_nic *nic)
}
/* Enable select interrupts */
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
- RX_MAC_INTR;
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+
en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
- /*
+ /*
* With some switches, link might be already up at this point.
- * Because of this weird behavior, when we enable laser,
- * we may not get link. We need to handle this. We cannot
- * figure out which switch is misbehaving. So we are forced to
- * make a global change.
+ * Because of this weird behavior, when we enable laser,
+ * we may not get link. We need to handle this. We cannot
+ * figure out which switch is misbehaving. So we are forced to
+ * make a global change.
*/
/* Enabling Laser. */
@@ -1411,44 +1961,30 @@ static int start_nic(struct s2io_nic *nic)
/* SXE-002: Initialize link and activity LED */
subid = nic->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if (((subid & 0xFF) >= 0x07) &&
+ (nic->device_type == XFRAME_I_DEVICE)) {
val64 = readq(&bar0->gpio_control);
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) bar0 + 0x2700);
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
}
- /*
- * Don't see link state interrupts on certain switches, so
+ /*
+ * Don't see link state interrupts on certain switches, so
* directly scheduling a link state task from here.
*/
schedule_work(&nic->set_link_task);
- /*
- * Here we are performing soft reset on XGXS to
- * force link down. Since link is already up, we will get
- * link state change interrupt after this reset
- */
- SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
- SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
- SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
-
return SUCCESS;
}
-/**
- * free_tx_buffers - Free all queued Tx buffers
+/**
+ * free_tx_buffers - Free all queued Tx buffers
* @nic : device private variable.
- * Description:
+ * Description:
* Free all queued Tx buffers.
- * Return Value: void
+ * Return Value: void
*/
static void free_tx_buffers(struct s2io_nic *nic)
@@ -1459,39 +1995,61 @@ static void free_tx_buffers(struct s2io_nic *nic)
int i, j;
mac_info_t *mac_control;
struct config_param *config;
- int cnt = 0;
+ int cnt = 0, frg_cnt;
mac_control = &nic->mac_control;
config = &nic->config;
for (i = 0; i < config->tx_fifo_num; i++) {
for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
- txdp = (TxD_t *) nic->list_info[i][j].
+ txdp = (TxD_t *) mac_control->fifos[i].list_info[j].
list_virt_addr;
skb =
(struct sk_buff *) ((unsigned long) txdp->
Host_Control);
if (skb == NULL) {
- memset(txdp, 0, sizeof(TxD_t));
+ memset(txdp, 0, sizeof(TxD_t) *
+ config->max_txds);
continue;
}
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txdp->Buffer_Pointer,
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ if (frg_cnt) {
+ TxD_t *temp;
+ temp = txdp;
+ txdp++;
+ for (j = 0; j < frg_cnt; j++, txdp++) {
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[j];
+ pci_unmap_page(nic->pdev,
+ (dma_addr_t)
+ txdp->
+ Buffer_Pointer,
+ frag->size,
+ PCI_DMA_TODEVICE);
+ }
+ txdp = temp;
+ }
dev_kfree_skb(skb);
- memset(txdp, 0, sizeof(TxD_t));
+ memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
cnt++;
}
DBG_PRINT(INTR_DBG,
"%s:forcibly freeing %d skbs on FIFO%d\n",
dev->name, cnt, i);
- mac_control->tx_curr_get_info[i].offset = 0;
- mac_control->tx_curr_put_info[i].offset = 0;
+ mac_control->fifos[i].tx_curr_get_info.offset = 0;
+ mac_control->fifos[i].tx_curr_put_info.offset = 0;
}
}
-/**
- * stop_nic - To stop the nic
+/**
+ * stop_nic - To stop the nic
* @nic ; device private variable.
- * Description:
- * This function does exactly the opposite of what the start_nic()
+ * Description:
+ * This function does exactly the opposite of what the start_nic()
* function does. This function is called to stop the device.
* Return Value:
* void.
@@ -1509,8 +2067,9 @@ static void stop_nic(struct s2io_nic *nic)
config = &nic->config;
/* Disable all interrupts */
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
- RX_MAC_INTR;
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
/* Disable PRCs */
@@ -1521,11 +2080,11 @@ static void stop_nic(struct s2io_nic *nic)
}
}
-/**
- * fill_rx_buffers - Allocates the Rx side skbs
+/**
+ * fill_rx_buffers - Allocates the Rx side skbs
* @nic: device private variable
- * @ring_no: ring number
- * Description:
+ * @ring_no: ring number
+ * Description:
* The function allocates Rx side skbs and puts the physical
* address of these buffers into the RxD buffer pointers, so that the NIC
* can DMA the received frame into these locations.
@@ -1533,8 +2092,8 @@ static void stop_nic(struct s2io_nic *nic)
* 1. single buffer,
* 2. three buffer and
* 3. Five buffer modes.
- * Each mode defines how many fragments the received frame will be split
- * up into by the NIC. The frame is split into L3 header, L4 Header,
+ * Each mode defines how many fragments the received frame will be split
+ * up into by the NIC. The frame is split into L3 header, L4 Header,
* L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself
* is split into 3 fragments. As of now only single buffer mode is
* supported.
@@ -1542,7 +2101,7 @@ static void stop_nic(struct s2io_nic *nic)
* SUCCESS on success or an appropriate -ve value on failure.
*/
-static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
{
struct net_device *dev = nic->dev;
struct sk_buff *skb;
@@ -1550,34 +2109,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
int off, off1, size, block_no, block_no1;
int offset, offset1;
u32 alloc_tab = 0;
- u32 alloc_cnt = nic->pkt_cnt[ring_no] -
- atomic_read(&nic->rx_bufs_left[ring_no]);
+ u32 alloc_cnt;
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
RxD_t *rxdpnext;
int nextblk;
- unsigned long tmp;
+ u64 tmp;
buffAdd_t *ba;
dma_addr_t rxdpphys;
#endif
#ifndef CONFIG_S2IO_NAPI
unsigned long flags;
#endif
+ RxD_t *first_rxdp = NULL;
mac_control = &nic->mac_control;
config = &nic->config;
-
+ alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
+ atomic_read(&nic->rx_bufs_left[ring_no]);
size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
while (alloc_tab < alloc_cnt) {
- block_no = mac_control->rx_curr_put_info[ring_no].
+ block_no = mac_control->rings[ring_no].rx_curr_put_info.
block_index;
- block_no1 = mac_control->rx_curr_get_info[ring_no].
+ block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
block_index;
- off = mac_control->rx_curr_put_info[ring_no].offset;
- off1 = mac_control->rx_curr_get_info[ring_no].offset;
+ off = mac_control->rings[ring_no].rx_curr_put_info.offset;
+ off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
#ifndef CONFIG_2BUFF_MODE
offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1;
@@ -1586,7 +2146,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;
#endif
- rxdp = nic->rx_blocks[ring_no][block_no].
+ rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr + off;
if ((offset == offset1) && (rxdp->Host_Control)) {
DBG_PRINT(INTR_DBG, "%s: Get and Put", dev->name);
@@ -1595,15 +2155,15 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
}
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
block_index++;
- mac_control->rx_curr_put_info[ring_no].
- block_index %= nic->block_count[ring_no];
- block_no = mac_control->rx_curr_put_info
- [ring_no].block_index;
+ mac_control->rings[ring_no].rx_curr_put_info.
+ block_index %= mac_control->rings[ring_no].block_count;
+ block_no = mac_control->rings[ring_no].rx_curr_put_info.
+ block_index;
off++;
off %= (MAX_RXDS_PER_BLOCK + 1);
- mac_control->rx_curr_put_info[ring_no].offset =
+ mac_control->rings[ring_no].rx_curr_put_info.offset =
off;
rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2);
DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
@@ -1611,30 +2171,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
- nic->put_pos[ring_no] =
+ mac_control->rings[ring_no].put_pos =
(block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
#else
if (rxdp->Host_Control == END_OF_BLOCK) {
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
block_index++;
- mac_control->rx_curr_put_info[ring_no].
- block_index %= nic->block_count[ring_no];
- block_no = mac_control->rx_curr_put_info
- [ring_no].block_index;
+ mac_control->rings[ring_no].rx_curr_put_info.block_index
+ %= mac_control->rings[ring_no].block_count;
+ block_no = mac_control->rings[ring_no].rx_curr_put_info
+ .block_index;
off = 0;
DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",
dev->name, block_no,
(unsigned long long) rxdp->Control_1);
- mac_control->rx_curr_put_info[ring_no].offset =
+ mac_control->rings[ring_no].rx_curr_put_info.offset =
off;
- rxdp = nic->rx_blocks[ring_no][block_no].
+ rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr;
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
- nic->put_pos[ring_no] = (block_no *
+ mac_control->rings[ring_no].put_pos = (block_no *
(MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
@@ -1646,27 +2206,27 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
if (rxdp->Control_2 & BIT(0))
#endif
{
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
offset = off;
goto end;
}
#ifdef CONFIG_2BUFF_MODE
- /*
- * RxDs Spanning cache lines will be replenished only
- * if the succeeding RxD is also owned by Host. It
- * will always be the ((8*i)+3) and ((8*i)+6)
- * descriptors for the 48 byte descriptor. The offending
+ /*
+ * RxDs Spanning cache lines will be replenished only
+ * if the succeeding RxD is also owned by Host. It
+ * will always be the ((8*i)+3) and ((8*i)+6)
+ * descriptors for the 48 byte descriptor. The offending
* decsriptor is of-course the 3rd descriptor.
*/
- rxdpphys = nic->rx_blocks[ring_no][block_no].
+ rxdpphys = mac_control->rings[ring_no].rx_blocks[block_no].
block_dma_addr + (off * sizeof(RxD_t));
if (((u64) (rxdpphys)) % 128 > 80) {
- rxdpnext = nic->rx_blocks[ring_no][block_no].
+ rxdpnext = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr + (off + 1);
if (rxdpnext->Host_Control == END_OF_BLOCK) {
nextblk = (block_no + 1) %
- (nic->block_count[ring_no]);
- rxdpnext = nic->rx_blocks[ring_no]
+ (mac_control->rings[ring_no].block_count);
+ rxdpnext = mac_control->rings[ring_no].rx_blocks
[nextblk].block_virt_addr;
}
if (rxdpnext->Control_2 & BIT(0))
@@ -1682,6 +2242,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
if (!skb) {
DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
return -ENOMEM;
}
#ifndef CONFIG_2BUFF_MODE
@@ -1692,12 +2256,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);
rxdp->Control_2 |= SET_BUFFER0_SIZE(size);
rxdp->Host_Control = (unsigned long) (skb);
- rxdp->Control_1 |= RXD_OWN_XENA;
+ if (alloc_tab & ((1 << rxsync_frequency) - 1))
+ rxdp->Control_1 |= RXD_OWN_XENA;
off++;
off %= (MAX_RXDS_PER_BLOCK + 1);
- mac_control->rx_curr_put_info[ring_no].offset = off;
+ mac_control->rings[ring_no].rx_curr_put_info.offset = off;
#else
- ba = &nic->ba[ring_no][block_no][off];
+ ba = &mac_control->rings[ring_no].ba[block_no][off];
skb_reserve(skb, BUF0_LEN);
tmp = ((unsigned long) skb->data & ALIGN_SIZE);
if (tmp)
@@ -1719,22 +2284,41 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */
rxdp->Host_Control = (u64) ((unsigned long) (skb));
- rxdp->Control_1 |= RXD_OWN_XENA;
+ if (alloc_tab & ((1 << rxsync_frequency) - 1))
+ rxdp->Control_1 |= RXD_OWN_XENA;
off++;
- mac_control->rx_curr_put_info[ring_no].offset = off;
+ mac_control->rings[ring_no].rx_curr_put_info.offset = off;
#endif
+ rxdp->Control_2 |= SET_RXD_MARKER;
+
+ if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
+ first_rxdp = rxdp;
+ }
atomic_inc(&nic->rx_bufs_left[ring_no]);
alloc_tab++;
}
end:
+ /* Transfer ownership of first descriptor to adapter just before
+ * exiting. Before that, use memory barrier so that ownership
+ * and other fields are seen by adapter correctly.
+ */
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
+
return SUCCESS;
}
/**
- * free_rx_buffers - Frees all Rx buffers
+ * free_rx_buffers - Frees all Rx buffers
* @sp: device private variable.
- * Description:
+ * Description:
* This function will free all Rx buffers allocated by host.
* Return Value:
* NONE.
@@ -1758,7 +2342,8 @@ static void free_rx_buffers(struct s2io_nic *sp)
for (i = 0; i < config->rx_ring_num; i++) {
for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) {
off = j % (MAX_RXDS_PER_BLOCK + 1);
- rxdp = sp->rx_blocks[i][blk].block_virt_addr + off;
+ rxdp = mac_control->rings[i].rx_blocks[blk].
+ block_virt_addr + off;
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
@@ -1793,7 +2378,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
HEADER_SNAP_SIZE,
PCI_DMA_FROMDEVICE);
#else
- ba = &sp->ba[i][blk][off];
+ ba = &mac_control->rings[i].ba[blk][off];
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
BUF0_LEN,
@@ -1813,10 +2398,10 @@ static void free_rx_buffers(struct s2io_nic *sp)
}
memset(rxdp, 0, sizeof(RxD_t));
}
- mac_control->rx_curr_put_info[i].block_index = 0;
- mac_control->rx_curr_get_info[i].block_index = 0;
- mac_control->rx_curr_put_info[i].offset = 0;
- mac_control->rx_curr_get_info[i].offset = 0;
+ mac_control->rings[i].rx_curr_put_info.block_index = 0;
+ mac_control->rings[i].rx_curr_get_info.block_index = 0;
+ mac_control->rings[i].rx_curr_put_info.offset = 0;
+ mac_control->rings[i].rx_curr_get_info.offset = 0;
atomic_set(&sp->rx_bufs_left[i], 0);
DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
dev->name, buf_cnt, i);
@@ -1826,7 +2411,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
/**
* s2io_poll - Rx interrupt handler for NAPI support
* @dev : pointer to the device structure.
- * @budget : The number of packets that were budgeted to be processed
+ * @budget : The number of packets that were budgeted to be processed
* during one pass through the 'Poll" function.
* Description:
* Comes into picture only if NAPI support has been incorporated. It does
@@ -1836,160 +2421,36 @@ static void free_rx_buffers(struct s2io_nic *sp)
* 0 on success and 1 if there are No Rx packets to be processed.
*/
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
static int s2io_poll(struct net_device *dev, int *budget)
{
nic_t *nic = dev->priv;
- XENA_dev_config_t __iomem *bar0 = nic->bar0;
- int pkts_to_process = *budget, pkt_cnt = 0;
- register u64 val64 = 0;
- rx_curr_get_info_t get_info, put_info;
- int i, get_block, put_block, get_offset, put_offset, ring_bufs;
-#ifndef CONFIG_2BUFF_MODE
- u16 val16, cksum;
-#endif
- struct sk_buff *skb;
- RxD_t *rxdp;
+ int pkt_cnt = 0, org_pkts_to_process;
mac_info_t *mac_control;
struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
- buffAdd_t *ba;
-#endif
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 val64;
+ int i;
+ atomic_inc(&nic->isr_cnt);
mac_control = &nic->mac_control;
config = &nic->config;
- if (pkts_to_process > dev->quota)
- pkts_to_process = dev->quota;
+ nic->pkts_to_process = *budget;
+ if (nic->pkts_to_process > dev->quota)
+ nic->pkts_to_process = dev->quota;
+ org_pkts_to_process = nic->pkts_to_process;
val64 = readq(&bar0->rx_traffic_int);
writeq(val64, &bar0->rx_traffic_int);
for (i = 0; i < config->rx_ring_num; i++) {
- get_info = mac_control->rx_curr_get_info[i];
- get_block = get_info.block_index;
- put_info = mac_control->rx_curr_put_info[i];
- put_block = put_info.block_index;
- ring_bufs = config->rx_cfg[i].num_rxd;
- rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
-#ifndef CONFIG_2BUFF_MODE
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
- put_info.offset;
- while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (--pkts_to_process < 0) {
- goto no_rx;
- }
- if (rxdp->Control_1 == END_OF_BLOCK) {
- rxdp =
- (RxD_t *) ((unsigned long) rxdp->
- Control_2);
- get_info.offset++;
- get_info.offset %=
- (MAX_RXDS_PER_BLOCK + 1);
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- continue;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- skb =
- (struct sk_buff *) ((unsigned long) rxdp->
- Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- goto no_rx;
- }
- val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- val16 = (u16) (val64 >> 48);
- cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- dev->mtu +
- HEADER_ETHERNET_II_802_3_SIZE +
- HEADER_802_2_SIZE +
- HEADER_SNAP_SIZE,
- PCI_DMA_FROMDEVICE);
- rx_osm_handler(nic, val16, rxdp, i);
- pkt_cnt++;
- get_info.offset++;
- get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- }
-#else
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
- put_info.offset;
- while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- !(rxdp->Control_2 & BIT(0))) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (--pkts_to_process < 0) {
- goto no_rx;
- }
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- goto no_rx;
- }
-
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- BUF0_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer1_ptr,
- BUF1_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer2_ptr,
- dev->mtu + BUF0_LEN + 4,
- PCI_DMA_FROMDEVICE);
- ba = &nic->ba[i][get_block][get_info.offset];
-
- rx_osm_handler(nic, rxdp, i, ba);
-
- get_info.offset++;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
-
- if (get_info.offset &&
- (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
- get_info.offset = 0;
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- rxdp =
- nic->rx_blocks[i][get_block].
- block_virt_addr;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- pkt_cnt++;
+ rx_intr_handler(&mac_control->rings[i]);
+ pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
+ if (!nic->pkts_to_process) {
+ /* Quota for the current iteration has been met */
+ goto no_rx;
}
-#endif
}
if (!pkt_cnt)
pkt_cnt = 1;
@@ -2007,9 +2468,10 @@ static int s2io_poll(struct net_device *dev, int *budget)
}
/* Re enable the Rx interrupts. */
en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
+ atomic_dec(&nic->isr_cnt);
return 0;
- no_rx:
+no_rx:
dev->quota -= pkt_cnt;
*budget -= pkt_cnt;
@@ -2020,279 +2482,211 @@ static int s2io_poll(struct net_device *dev, int *budget)
break;
}
}
+ atomic_dec(&nic->isr_cnt);
return 1;
}
-#else
-/**
+#endif
+
+/**
* rx_intr_handler - Rx interrupt handler
* @nic: device private variable.
- * Description:
- * If the interrupt is because of a received frame or if the
+ * Description:
+ * If the interrupt is because of a received frame or if the
* receive ring contains fresh as yet un-processed frames,this function is
- * called. It picks out the RxD at which place the last Rx processing had
- * stopped and sends the skb to the OSM's Rx handler and then increments
+ * called. It picks out the RxD at which place the last Rx processing had
+ * stopped and sends the skb to the OSM's Rx handler and then increments
* the offset.
* Return Value:
* NONE.
*/
-
-static void rx_intr_handler(struct s2io_nic *nic)
+static void rx_intr_handler(ring_info_t *ring_data)
{
+ nic_t *nic = ring_data->nic;
struct net_device *dev = (struct net_device *) nic->dev;
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ int get_block, get_offset, put_block, put_offset, ring_bufs;
rx_curr_get_info_t get_info, put_info;
RxD_t *rxdp;
struct sk_buff *skb;
-#ifndef CONFIG_2BUFF_MODE
- u16 val16, cksum;
-#endif
- register u64 val64 = 0;
- int get_block, get_offset, put_block, put_offset, ring_bufs;
- int i, pkt_cnt = 0;
- mac_info_t *mac_control;
- struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
- buffAdd_t *ba;
+#ifndef CONFIG_S2IO_NAPI
+ int pkt_cnt = 0;
#endif
+ spin_lock(&nic->rx_lock);
+ if (atomic_read(&nic->card_state) == CARD_DOWN) {
+ DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
+ __FUNCTION__, dev->name);
+ spin_unlock(&nic->rx_lock);
+ return;
+ }
- mac_control = &nic->mac_control;
- config = &nic->config;
-
- /*
- * rx_traffic_int reg is an R1 register, hence we read and write back
- * the samevalue in the register to clear it.
- */
- val64 = readq(&bar0->rx_traffic_int);
- writeq(val64, &bar0->rx_traffic_int);
-
- for (i = 0; i < config->rx_ring_num; i++) {
- get_info = mac_control->rx_curr_get_info[i];
- get_block = get_info.block_index;
- put_info = mac_control->rx_curr_put_info[i];
- put_block = put_info.block_index;
- ring_bufs = config->rx_cfg[i].num_rxd;
- rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
-#ifndef CONFIG_2BUFF_MODE
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ get_info = ring_data->rx_curr_get_info;
+ get_block = get_info.block_index;
+ put_info = ring_data->rx_curr_put_info;
+ put_block = put_info.block_index;
+ ring_bufs = get_info.ring_len+1;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
get_info.offset;
- spin_lock(&nic->put_lock);
- put_offset = nic->put_pos[i];
- spin_unlock(&nic->put_lock);
- while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (rxdp->Control_1 == END_OF_BLOCK) {
- rxdp = (RxD_t *) ((unsigned long)
- rxdp->Control_2);
- get_info.offset++;
- get_info.offset %=
- (MAX_RXDS_PER_BLOCK + 1);
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- continue;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- return;
- }
- val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- val16 = (u16) (val64 >> 48);
- cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- dev->mtu +
- HEADER_ETHERNET_II_802_3_SIZE +
- HEADER_802_2_SIZE +
- HEADER_SNAP_SIZE,
- PCI_DMA_FROMDEVICE);
- rx_osm_handler(nic, val16, rxdp, i);
- get_info.offset++;
- get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- pkt_cnt++;
- if ((indicate_max_pkts)
- && (pkt_cnt > indicate_max_pkts))
- break;
+ get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ get_info.offset;
+#ifndef CONFIG_S2IO_NAPI
+ spin_lock(&nic->put_lock);
+ put_offset = ring_data->put_pos;
+ spin_unlock(&nic->put_lock);
+#else
+ put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ put_info.offset;
+#endif
+ while (RXD_IS_UP2DT(rxdp) &&
+ (((get_offset + 1) % ring_bufs) != put_offset)) {
+ skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
+ if (skb == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: The skb is ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+ spin_unlock(&nic->rx_lock);
+ return;
}
+#ifndef CONFIG_2BUFF_MODE
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer0_ptr,
+ dev->mtu +
+ HEADER_ETHERNET_II_802_3_SIZE +
+ HEADER_802_2_SIZE +
+ HEADER_SNAP_SIZE,
+ PCI_DMA_FROMDEVICE);
#else
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer0_ptr,
+ BUF0_LEN, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer1_ptr,
+ BUF1_LEN, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer2_ptr,
+ dev->mtu + BUF0_LEN + 4,
+ PCI_DMA_FROMDEVICE);
+#endif
+ rx_osm_handler(ring_data, rxdp);
+ get_info.offset++;
+ ring_data->rx_curr_get_info.offset =
get_info.offset;
- spin_lock(&nic->put_lock);
- put_offset = nic->put_pos[i];
- spin_unlock(&nic->put_lock);
- while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- !(rxdp->Control_2 & BIT(0))) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- return;
- }
-
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- BUF0_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer1_ptr,
- BUF1_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer2_ptr,
- dev->mtu + BUF0_LEN + 4,
- PCI_DMA_FROMDEVICE);
- ba = &nic->ba[i][get_block][get_info.offset];
-
- rx_osm_handler(nic, rxdp, i, ba);
-
- get_info.offset++;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
+ get_info.offset;
+ if (get_info.offset &&
+ (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
+ get_info.offset = 0;
+ ring_data->rx_curr_get_info.offset
+ = get_info.offset;
+ get_block++;
+ get_block %= ring_data->block_count;
+ ring_data->rx_curr_get_info.block_index
+ = get_block;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
+ }
- if (get_info.offset &&
- (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
- get_info.offset = 0;
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- rxdp =
- nic->rx_blocks[i][get_block].
- block_virt_addr;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
- pkt_cnt++;
- if ((indicate_max_pkts)
- && (pkt_cnt > indicate_max_pkts))
- break;
- }
-#endif
+#ifdef CONFIG_S2IO_NAPI
+ nic->pkts_to_process -= 1;
+ if (!nic->pkts_to_process)
+ break;
+#else
+ pkt_cnt++;
if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
break;
+#endif
}
+ spin_unlock(&nic->rx_lock);
}
-#endif
-/**
+
+/**
* tx_intr_handler - Transmit interrupt handler
* @nic : device private variable
- * Description:
- * If an interrupt was raised to indicate DMA complete of the
- * Tx packet, this function is called. It identifies the last TxD
- * whose buffer was freed and frees all skbs whose data have already
+ * Description:
+ * If an interrupt was raised to indicate DMA complete of the
+ * Tx packet, this function is called. It identifies the last TxD
+ * whose buffer was freed and frees all skbs whose data have already
* DMA'ed into the NICs internal memory.
* Return Value:
* NONE
*/
-static void tx_intr_handler(struct s2io_nic *nic)
+static void tx_intr_handler(fifo_info_t *fifo_data)
{
- XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ nic_t *nic = fifo_data->nic;
struct net_device *dev = (struct net_device *) nic->dev;
tx_curr_get_info_t get_info, put_info;
struct sk_buff *skb;
TxD_t *txdlp;
- register u64 val64 = 0;
- int i;
u16 j, frg_cnt;
- mac_info_t *mac_control;
- struct config_param *config;
-
- mac_control = &nic->mac_control;
- config = &nic->config;
-
- /*
- * tx_traffic_int reg is an R1 register, hence we read and write
- * back the samevalue in the register to clear it.
- */
- val64 = readq(&bar0->tx_traffic_int);
- writeq(val64, &bar0->tx_traffic_int);
- for (i = 0; i < config->tx_fifo_num; i++) {
- get_info = mac_control->tx_curr_get_info[i];
- put_info = mac_control->tx_curr_put_info[i];
- txdlp = (TxD_t *) nic->list_info[i][get_info.offset].
- list_virt_addr;
- while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
- (get_info.offset != put_info.offset) &&
- (txdlp->Host_Control)) {
- /* Check for TxD errors */
- if (txdlp->Control_1 & TXD_T_CODE) {
- unsigned long long err;
- err = txdlp->Control_1 & TXD_T_CODE;
- DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
- err);
+ get_info = fifo_data->tx_curr_get_info;
+ put_info = fifo_data->tx_curr_put_info;
+ txdlp = (TxD_t *) fifo_data->list_info[get_info.offset].
+ list_virt_addr;
+ while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
+ (get_info.offset != put_info.offset) &&
+ (txdlp->Host_Control)) {
+ /* Check for TxD errors */
+ if (txdlp->Control_1 & TXD_T_CODE) {
+ unsigned long long err;
+ err = txdlp->Control_1 & TXD_T_CODE;
+ if ((err >> 48) == 0xA) {
+ DBG_PRINT(TX_DBG, "TxD returned due \
+ to loss of link\n");
}
-
- skb = (struct sk_buff *) ((unsigned long)
- txdlp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: Null skb ",
- dev->name);
- DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
- return;
+ else {
+ DBG_PRINT(ERR_DBG, "***TxD error \
+ %llx\n", err);
}
- nic->tx_pkt_count++;
+ }
- frg_cnt = skb_shinfo(skb)->nr_frags;
+ skb = (struct sk_buff *) ((unsigned long)
+ txdlp->Host_Control);
+ if (skb == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Null skb ",
+ __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+ return;
+ }
- /* For unfragmented skb */
- pci_unmap_single(nic->pdev, (dma_addr_t)
- txdlp->Buffer_Pointer,
- skb->len - skb->data_len,
- PCI_DMA_TODEVICE);
- if (frg_cnt) {
- TxD_t *temp = txdlp;
- txdlp++;
- for (j = 0; j < frg_cnt; j++, txdlp++) {
- skb_frag_t *frag =
- &skb_shinfo(skb)->frags[j];
- pci_unmap_page(nic->pdev,
- (dma_addr_t)
- txdlp->
- Buffer_Pointer,
- frag->size,
- PCI_DMA_TODEVICE);
- }
- txdlp = temp;
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ nic->tx_pkt_count++;
+
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txdlp->Buffer_Pointer,
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ if (frg_cnt) {
+ TxD_t *temp;
+ temp = txdlp;
+ txdlp++;
+ for (j = 0; j < frg_cnt; j++, txdlp++) {
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[j];
+ if (!txdlp->Buffer_Pointer)
+ break;
+ pci_unmap_page(nic->pdev,
+ (dma_addr_t)
+ txdlp->
+ Buffer_Pointer,
+ frag->size,
+ PCI_DMA_TODEVICE);
}
- memset(txdlp, 0,
- (sizeof(TxD_t) * config->max_txds));
-
- /* Updating the statistics block */
- nic->stats.tx_packets++;
- nic->stats.tx_bytes += skb->len;
- dev_kfree_skb_irq(skb);
-
- get_info.offset++;
- get_info.offset %= get_info.fifo_len + 1;
- txdlp = (TxD_t *) nic->list_info[i]
- [get_info.offset].list_virt_addr;
- mac_control->tx_curr_get_info[i].offset =
- get_info.offset;
+ txdlp = temp;
}
+ memset(txdlp, 0,
+ (sizeof(TxD_t) * fifo_data->max_txds));
+
+ /* Updating the statistics block */
+ nic->stats.tx_bytes += skb->len;
+ dev_kfree_skb_irq(skb);
+
+ get_info.offset++;
+ get_info.offset %= get_info.fifo_len + 1;
+ txdlp = (TxD_t *) fifo_data->list_info
+ [get_info.offset].list_virt_addr;
+ fifo_data->tx_curr_get_info.offset =
+ get_info.offset;
}
spin_lock(&nic->tx_lock);
@@ -2301,13 +2695,13 @@ static void tx_intr_handler(struct s2io_nic *nic)
spin_unlock(&nic->tx_lock);
}
-/**
+/**
* alarm_intr_handler - Alarm Interrrupt handler
* @nic: device private variable
- * Description: If the interrupt was neither because of Rx packet or Tx
+ * Description: If the interrupt was neither because of Rx packet or Tx
* complete, this function is called. If the interrupt was to indicate
- * a loss of link, the OSM link status handler is invoked for any other
- * alarm interrupt the block that raised the interrupt is displayed
+ * a loss of link, the OSM link status handler is invoked for any other
+ * alarm interrupt the block that raised the interrupt is displayed
* and a H/W reset is issued.
* Return Value:
* NONE
@@ -2320,17 +2714,44 @@ static void alarm_intr_handler(struct s2io_nic *nic)
register u64 val64 = 0, err_reg = 0;
/* Handling link status change error Intr */
- err_reg = readq(&bar0->mac_rmac_err_reg);
- writeq(err_reg, &bar0->mac_rmac_err_reg);
- if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
- schedule_work(&nic->set_link_task);
+ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+ err_reg = readq(&bar0->mac_rmac_err_reg);
+ writeq(err_reg, &bar0->mac_rmac_err_reg);
+ if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
+ schedule_work(&nic->set_link_task);
+ }
+ }
+
+ /* Handling Ecc errors */
+ val64 = readq(&bar0->mc_err_reg);
+ writeq(val64, &bar0->mc_err_reg);
+ if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
+ if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
+ nic->mac_control.stats_info->sw_stat.
+ double_ecc_errs++;
+ DBG_PRINT(INIT_DBG, "%s: Device indicates ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "double ECC error!!\n");
+ if (nic->device_type != XFRAME_II_DEVICE) {
+ /* Reset XframeI only if critical error */
+ if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+ MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
+ netif_stop_queue(dev);
+ schedule_work(&nic->rst_timer_task);
+ }
+ }
+ } else {
+ nic->mac_control.stats_info->sw_stat.
+ single_ecc_errs++;
+ }
}
/* In case of a serious error, the device will be Reset. */
val64 = readq(&bar0->serr_source);
if (val64 & SERR_SOURCE_ANY) {
DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
- DBG_PRINT(ERR_DBG, "serious error!!\n");
+ DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
+ (unsigned long long)val64);
netif_stop_queue(dev);
schedule_work(&nic->rst_timer_task);
}
@@ -2338,7 +2759,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
/*
* Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
* Error occurs, the adapter will be recycled by disabling the
- * adapter enable bit and enabling it again after the device
+ * adapter enable bit and enabling it again after the device
* becomes Quiescent.
*/
val64 = readq(&bar0->pcc_err_reg);
@@ -2354,18 +2775,18 @@ static void alarm_intr_handler(struct s2io_nic *nic)
/* Other type of interrupts are not being handled now, TODO */
}
-/**
+/**
* wait_for_cmd_complete - waits for a command to complete.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * Description: Function that waits for a command to Write into RMAC
- * ADDR DATA registers to be completed and returns either success or
- * error depending on whether the command was complete or not.
+ * Description: Function that waits for a command to Write into RMAC
+ * ADDR DATA registers to be completed and returns either success or
+ * error depending on whether the command was complete or not.
* Return value:
* SUCCESS on success and FAILURE on failure.
*/
-static int wait_for_cmd_complete(nic_t * sp)
+int wait_for_cmd_complete(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
int ret = FAILURE, cnt = 0;
@@ -2385,29 +2806,32 @@ static int wait_for_cmd_complete(nic_t * sp)
return ret;
}
-/**
- * s2io_reset - Resets the card.
+/**
+ * s2io_reset - Resets the card.
* @sp : private member of the device structure.
* Description: Function to Reset the card. This function then also
- * restores the previously saved PCI configuration space registers as
+ * restores the previously saved PCI configuration space registers as
* the card reset also resets the configuration space.
* Return value:
* void.
*/
-static void s2io_reset(nic_t * sp)
+void s2io_reset(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
- u16 subid;
+ u16 subid, pci_cmd;
+
+ /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
+ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
val64 = SW_RESET_ALL;
writeq(val64, &bar0->sw_reset);
- /*
- * At this stage, if the PCI write is indeed completed, the
- * card is reset and so is the PCI Config space of the device.
- * So a read cannot be issued at this stage on any of the
+ /*
+ * At this stage, if the PCI write is indeed completed, the
+ * card is reset and so is the PCI Config space of the device.
+ * So a read cannot be issued at this stage on any of the
* registers to ensure the write into "sw_reset" register
* has gone through.
* Question: Is there any system call that will explicitly force
@@ -2418,42 +2842,72 @@ static void s2io_reset(nic_t * sp)
*/
msleep(250);
- /* Restore the PCI state saved during initializarion. */
+ /* Restore the PCI state saved during initialization. */
pci_restore_state(sp->pdev);
+ pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+ pci_cmd);
s2io_init_pci(sp);
msleep(250);
+ /* Set swapper to enable I/O register access */
+ s2io_set_swapper(sp);
+
+ /* Clear certain PCI/PCI-X fields after reset */
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ /* Clear parity err detect bit */
+ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
+
+ /* Clearing PCIX Ecc status register */
+ pci_write_config_dword(sp->pdev, 0x68, 0x7C);
+
+ /* Clearing PCI_STATUS error reflected here */
+ writeq(BIT(62), &bar0->txpic_int_reg);
+ }
+
+ /* Reset device statistics maintained by OS */
+ memset(&sp->stats, 0, sizeof (struct net_device_stats));
+
/* SXE-002: Configure link and activity LED to turn it off */
subid = sp->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if (((subid & 0xFF) >= 0x07) &&
+ (sp->device_type == XFRAME_I_DEVICE)) {
val64 = readq(&bar0->gpio_control);
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) bar0 + 0x2700);
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
+ }
+
+ /*
+ * Clear spurious ECC interrupts that would have occured on
+ * XFRAME II cards after reset.
+ */
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ val64 = readq(&bar0->pcc_err_reg);
+ writeq(val64, &bar0->pcc_err_reg);
}
sp->device_enabled_once = FALSE;
}
/**
- * s2io_set_swapper - to set the swapper controle on the card
- * @sp : private member of the device structure,
+ * s2io_set_swapper - to set the swapper controle on the card
+ * @sp : private member of the device structure,
* pointer to the s2io_nic structure.
- * Description: Function to set the swapper control on the card
+ * Description: Function to set the swapper control on the card
* correctly depending on the 'endianness' of the system.
* Return value:
* SUCCESS on success and FAILURE on failure.
*/
-static int s2io_set_swapper(nic_t * sp)
+int s2io_set_swapper(nic_t * sp)
{
struct net_device *dev = sp->dev;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64, valt, valr;
- /*
+ /*
* Set proper endian settings and verify the same by reading
* the PIF Feed-back register.
*/
@@ -2505,8 +2959,9 @@ static int s2io_set_swapper(nic_t * sp)
i++;
}
if(i == 4) {
+ unsigned long long x = val64;
DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
- DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64);
+ DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);
return FAILURE;
}
}
@@ -2514,8 +2969,8 @@ static int s2io_set_swapper(nic_t * sp)
val64 &= 0xFFFF000000000000ULL;
#ifdef __BIG_ENDIAN
- /*
- * The device by default set to a big endian format, so a
+ /*
+ * The device by default set to a big endian format, so a
* big endian driver need not set anything.
*/
val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2531,9 +2986,9 @@ static int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
writeq(val64, &bar0->swapper_ctrl);
#else
- /*
+ /*
* Initially we enable all bits to make it accessible by the
- * driver, then we selectively enable only those bits that
+ * driver, then we selectively enable only those bits that
* we want to set.
*/
val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2555,8 +3010,8 @@ static int s2io_set_swapper(nic_t * sp)
#endif
val64 = readq(&bar0->swapper_ctrl);
- /*
- * Verifying if endian settings are accurate by reading a
+ /*
+ * Verifying if endian settings are accurate by reading a
* feedback register.
*/
val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -2576,55 +3031,63 @@ static int s2io_set_swapper(nic_t * sp)
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
-/**
+/**
* s2io_open - open entry point of the driver
* @dev : pointer to the device structure.
* Description:
* This function is the open entry point of the driver. It mainly calls a
* function to allocate Rx buffers and inserts them into the buffer
- * descriptors and then enables the Rx part of the NIC.
+ * descriptors and then enables the Rx part of the NIC.
* Return value:
* 0 on success and an appropriate (-)ve integer as defined in errno.h
* file on failure.
*/
-static int s2io_open(struct net_device *dev)
+int s2io_open(struct net_device *dev)
{
nic_t *sp = dev->priv;
int err = 0;
- /*
- * Make sure you have link off by default every time
+ /*
+ * Make sure you have link off by default every time
* Nic is initialized
*/
netif_carrier_off(dev);
- sp->last_link_state = LINK_DOWN;
+ sp->last_link_state = 0;
/* Initialize H/W and enable interrupts */
if (s2io_card_up(sp)) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name);
- return -ENODEV;
+ err = -ENODEV;
+ goto hw_init_failed;
}
/* After proper initialization of H/W, register ISR */
- err = request_irq((int) sp->irq, s2io_isr, SA_SHIRQ,
+ err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
sp->name, dev);
if (err) {
- s2io_reset(sp);
DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
dev->name);
- return err;
+ goto isr_registration_failed;
}
if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
- s2io_reset(sp);
- return -ENODEV;
+ err = -ENODEV;
+ goto setting_mac_address_failed;
}
netif_start_queue(dev);
return 0;
+
+setting_mac_address_failed:
+ free_irq(sp->pdev->irq, dev);
+isr_registration_failed:
+ del_timer_sync(&sp->alarm_timer);
+ s2io_reset(sp);
+hw_init_failed:
+ return err;
}
/**
@@ -2640,16 +3103,15 @@ static int s2io_open(struct net_device *dev)
* file on failure.
*/
-static int s2io_close(struct net_device *dev)
+int s2io_close(struct net_device *dev)
{
nic_t *sp = dev->priv;
-
flush_scheduled_work();
netif_stop_queue(dev);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- free_irq(dev->irq, dev);
+ free_irq(sp->pdev->irq, dev);
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -2667,7 +3129,7 @@ static int s2io_close(struct net_device *dev)
* 0 on success & 1 on failure.
*/
-static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
{
nic_t *sp = dev->priv;
u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -2678,37 +3140,56 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef NETIF_F_TSO
int mss;
#endif
+ u16 vlan_tag = 0;
+ int vlan_priority = 0;
mac_info_t *mac_control;
struct config_param *config;
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
mac_control = &sp->mac_control;
config = &sp->config;
- DBG_PRINT(TX_DBG, "%s: In S2IO Tx routine\n", dev->name);
+ DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name);
spin_lock_irqsave(&sp->tx_lock, flags);
-
if (atomic_read(&sp->card_state) == CARD_DOWN) {
- DBG_PRINT(ERR_DBG, "%s: Card going down for reset\n",
+ DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
dev->name);
spin_unlock_irqrestore(&sp->tx_lock, flags);
- return 1;
+ dev_kfree_skb(skb);
+ return 0;
}
queue = 0;
- put_off = (u16) mac_control->tx_curr_put_info[queue].offset;
- get_off = (u16) mac_control->tx_curr_get_info[queue].offset;
- txdp = (TxD_t *) sp->list_info[queue][put_off].list_virt_addr;
- queue_len = mac_control->tx_curr_put_info[queue].fifo_len + 1;
+ /* Get Fifo number to Transmit based on vlan priority */
+ if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+ vlan_tag = vlan_tx_tag_get(skb);
+ vlan_priority = vlan_tag >> 13;
+ queue = config->fifo_mapping[vlan_priority];
+ }
+
+ put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset;
+ get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset;
+ txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off].
+ list_virt_addr;
+
+ queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
/* Avoid "put" pointer going beyond "get" pointer */
if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
- DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n");
+ DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
netif_stop_queue(dev);
dev_kfree_skb(skb);
spin_unlock_irqrestore(&sp->tx_lock, flags);
return 0;
}
+
+ /* A buffer with no data will be dropped */
+ if (!skb->len) {
+ DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&sp->tx_lock, flags);
+ return 0;
+ }
+
#ifdef NETIF_F_TSO
mss = skb_shinfo(skb)->tso_size;
if (mss) {
@@ -2720,9 +3201,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
frg_cnt = skb_shinfo(skb)->nr_frags;
frg_len = skb->len - skb->data_len;
- txdp->Host_Control = (unsigned long) skb;
txdp->Buffer_Pointer = pci_map_single
(sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
+ txdp->Host_Control = (unsigned long) skb;
if (skb->ip_summed == CHECKSUM_HW) {
txdp->Control_2 |=
(TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
@@ -2731,6 +3212,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Control_2 |= config->tx_intr_type;
+ if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+ txdp->Control_2 |= TXD_VLAN_ENABLE;
+ txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+ }
+
txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
TXD_GATHER_CODE_FIRST);
txdp->Control_1 |= TXD_LIST_OWN_XENA;
@@ -2738,6 +3224,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
/* For fragmented SKB. */
for (i = 0; i < frg_cnt; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ /* A '0' length fragment will be ignored */
+ if (!frag->size)
+ continue;
txdp++;
txdp->Buffer_Pointer = (u64) pci_map_page
(sp->pdev, frag->page, frag->page_offset,
@@ -2747,23 +3236,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Control_1 |= TXD_GATHER_CODE_LAST;
tx_fifo = mac_control->tx_FIFO_start[queue];
- val64 = sp->list_info[queue][put_off].list_phy_addr;
+ val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
writeq(val64, &tx_fifo->TxDL_Pointer);
val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
TX_FIFO_LAST_LIST);
+
#ifdef NETIF_F_TSO
if (mss)
val64 |= TX_FIFO_SPECIAL_FUNC;
#endif
writeq(val64, &tx_fifo->List_Control);
- /* Perform a PCI read to flush previous writes */
- val64 = readq(&bar0->general_int_status);
+ mmiowb();
put_off++;
- put_off %= mac_control->tx_curr_put_info[queue].fifo_len + 1;
- mac_control->tx_curr_put_info[queue].offset = put_off;
+ put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+ mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
/* Avoid "put" pointer going beyond "get" pointer */
if (((put_off + 1) % queue_len) == get_off) {
@@ -2779,18 +3268,74 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
+static void
+s2io_alarm_handle(unsigned long data)
+{
+ nic_t *sp = (nic_t *)data;
+
+ alarm_intr_handler(sp);
+ mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
+}
+
+static void s2io_txpic_intr_handle(nic_t *sp)
+{
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64;
+
+ val64 = readq(&bar0->pic_int_status);
+ if (val64 & PIC_INT_GPIO) {
+ val64 = readq(&bar0->gpio_int_reg);
+ if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
+ (val64 & GPIO_INT_REG_LINK_UP)) {
+ val64 |= GPIO_INT_REG_LINK_DOWN;
+ val64 |= GPIO_INT_REG_LINK_UP;
+ writeq(val64, &bar0->gpio_int_reg);
+ goto masking;
+ }
+
+ if (((sp->last_link_state == LINK_UP) &&
+ (val64 & GPIO_INT_REG_LINK_DOWN)) ||
+ ((sp->last_link_state == LINK_DOWN) &&
+ (val64 & GPIO_INT_REG_LINK_UP))) {
+ val64 = readq(&bar0->gpio_int_mask);
+ val64 |= GPIO_INT_MASK_LINK_DOWN;
+ val64 |= GPIO_INT_MASK_LINK_UP;
+ writeq(val64, &bar0->gpio_int_mask);
+ s2io_set_link((unsigned long)sp);
+ }
+masking:
+ if (sp->last_link_state == LINK_UP) {
+ /*enable down interrupt */
+ val64 = readq(&bar0->gpio_int_mask);
+ /* unmasks link down intr */
+ val64 &= ~GPIO_INT_MASK_LINK_DOWN;
+ /* masks link up intr */
+ val64 |= GPIO_INT_MASK_LINK_UP;
+ writeq(val64, &bar0->gpio_int_mask);
+ } else {
+ /*enable UP Interrupt */
+ val64 = readq(&bar0->gpio_int_mask);
+ /* unmasks link up interrupt */
+ val64 &= ~GPIO_INT_MASK_LINK_UP;
+ /* masks link down interrupt */
+ val64 |= GPIO_INT_MASK_LINK_DOWN;
+ writeq(val64, &bar0->gpio_int_mask);
+ }
+ }
+}
+
/**
* s2io_isr - ISR handler of the device .
* @irq: the irq of the device.
* @dev_id: a void pointer to the dev structure of the NIC.
* @pt_regs: pointer to the registers pushed on the stack.
- * Description: This function is the ISR handler of the device. It
- * identifies the reason for the interrupt and calls the relevant
- * service routines. As a contongency measure, this ISR allocates the
+ * Description: This function is the ISR handler of the device. It
+ * identifies the reason for the interrupt and calls the relevant
+ * service routines. As a contongency measure, this ISR allocates the
* recv buffers, if their numbers are below the panic value which is
* presently set to 25% of the original number of rcv buffers allocated.
* Return value:
- * IRQ_HANDLED: will be returned if IRQ was handled by this routine
+ * IRQ_HANDLED: will be returned if IRQ was handled by this routine
* IRQ_NONE: will be returned if interrupt is not from our device
*/
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2798,40 +3343,31 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = (struct net_device *) dev_id;
nic_t *sp = dev->priv;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
-#ifndef CONFIG_S2IO_NAPI
- int i, ret;
-#endif
- u64 reason = 0;
+ int i;
+ u64 reason = 0, val64;
mac_info_t *mac_control;
struct config_param *config;
+ atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
- /*
+ /*
* Identify the cause for interrupt and call the appropriate
* interrupt handler. Causes for the interrupt could be;
* 1. Rx of packet.
* 2. Tx complete.
* 3. Link down.
- * 4. Error in any functional blocks of the NIC.
+ * 4. Error in any functional blocks of the NIC.
*/
reason = readq(&bar0->general_int_status);
if (!reason) {
/* The interrupt was not raised by Xena. */
+ atomic_dec(&sp->isr_cnt);
return IRQ_NONE;
}
- /* If Intr is because of Tx Traffic */
- if (reason & GEN_INTR_TXTRAFFIC) {
- tx_intr_handler(sp);
- }
-
- /* If Intr is because of an error */
- if (reason & (GEN_ERROR_INTR))
- alarm_intr_handler(sp);
-
#ifdef CONFIG_S2IO_NAPI
if (reason & GEN_INTR_RXTRAFFIC) {
if (netif_rx_schedule_prep(dev)) {
@@ -2843,17 +3379,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
#else
/* If Intr is because of Rx Traffic */
if (reason & GEN_INTR_RXTRAFFIC) {
- rx_intr_handler(sp);
+ /*
+ * rx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit get's
+ * cleared and hence a read can be avoided.
+ */
+ val64 = 0xFFFFFFFFFFFFFFFFULL;
+ writeq(val64, &bar0->rx_traffic_int);
+ for (i = 0; i < config->rx_ring_num; i++) {
+ rx_intr_handler(&mac_control->rings[i]);
+ }
}
#endif
- /*
- * If the Rx buffer count is below the panic threshold then
- * reallocate the buffers from the interrupt handler itself,
+ /* If Intr is because of Tx Traffic */
+ if (reason & GEN_INTR_TXTRAFFIC) {
+ /*
+ * tx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit get's
+ * cleared and hence a read can be avoided.
+ */
+ val64 = 0xFFFFFFFFFFFFFFFFULL;
+ writeq(val64, &bar0->tx_traffic_int);
+
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
+ }
+
+ if (reason & GEN_INTR_TXPIC)
+ s2io_txpic_intr_handle(sp);
+ /*
+ * If the Rx buffer count is below the panic threshold then
+ * reallocate the buffers from the interrupt handler itself,
* else schedule a tasklet to reallocate the buffers.
*/
#ifndef CONFIG_S2IO_NAPI
for (i = 0; i < config->rx_ring_num; i++) {
+ int ret;
int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
int level = rx_buffer_level(sp, rxb_size, i);
@@ -2865,6 +3427,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
dev->name);
DBG_PRINT(ERR_DBG, " in ISR!!\n");
clear_bit(0, (&sp->tasklet_status));
+ atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
clear_bit(0, (&sp->tasklet_status));
@@ -2874,33 +3437,69 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
}
#endif
+ atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
/**
- * s2io_get_stats - Updates the device statistics structure.
+ * s2io_updt_stats -
+ */
+static void s2io_updt_stats(nic_t *sp)
+{
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64;
+ int cnt = 0;
+
+ if (atomic_read(&sp->card_state) == CARD_UP) {
+ /* Apprx 30us on a 133 MHz bus */
+ val64 = SET_UPDT_CLICKS(10) |
+ STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN;
+ writeq(val64, &bar0->stat_cfg);
+ do {
+ udelay(100);
+ val64 = readq(&bar0->stat_cfg);
+ if (!(val64 & BIT(0)))
+ break;
+ cnt++;
+ if (cnt == 5)
+ break; /* Updt failed */
+ } while(1);
+ }
+}
+
+/**
+ * s2io_get_stats - Updates the device statistics structure.
* @dev : pointer to the device structure.
* Description:
- * This function updates the device statistics structure in the s2io_nic
+ * This function updates the device statistics structure in the s2io_nic
* structure and returns a pointer to the same.
* Return value:
* pointer to the updated net_device_stats structure.
*/
-static struct net_device_stats *s2io_get_stats(struct net_device *dev)
+struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
nic_t *sp = dev->priv;
mac_info_t *mac_control;
struct config_param *config;
+
mac_control = &sp->mac_control;
config = &sp->config;
- sp->stats.tx_errors = mac_control->stats_info->tmac_any_err_frms;
- sp->stats.rx_errors = mac_control->stats_info->rmac_drop_frms;
- sp->stats.multicast = mac_control->stats_info->rmac_vld_mcst_frms;
+ /* Configure Stats for immediate updt */
+ s2io_updt_stats(sp);
+
+ sp->stats.tx_packets =
+ le32_to_cpu(mac_control->stats_info->tmac_frms);
+ sp->stats.tx_errors =
+ le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
+ sp->stats.rx_errors =
+ le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+ sp->stats.multicast =
+ le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
sp->stats.rx_length_errors =
- mac_control->stats_info->rmac_long_frms;
+ le32_to_cpu(mac_control->stats_info->rmac_long_frms);
return (&sp->stats);
}
@@ -2909,8 +3508,8 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
* s2io_set_multicast - entry point for multicast address enable/disable.
* @dev : pointer to the device structure
* Description:
- * This function is a driver entry point which gets called by the kernel
- * whenever multicast addresses must be enabled/disabled. This also gets
+ * This function is a driver entry point which gets called by the kernel
+ * whenever multicast addresses must be enabled/disabled. This also gets
* called to set/reset promiscuous mode. Depending on the deivce flag, we
* determine, if multicast address must be enabled or if promiscuous mode
* is to be disabled etc.
@@ -2948,6 +3547,8 @@ static void s2io_set_multicast(struct net_device *dev)
/* Disable all Multicast addresses */
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
&bar0->rmac_addr_data0_mem);
+ writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0),
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
@@ -2972,7 +3573,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 1;
- DBG_PRINT(ERR_DBG, "%s: entered promiscuous mode\n",
+ DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
dev->name);
} else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) {
/* Remove the NIC from promiscuous mode */
@@ -2987,7 +3588,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 0;
- DBG_PRINT(ERR_DBG, "%s: left promiscuous mode\n",
+ DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
dev->name);
}
@@ -3010,7 +3611,7 @@ static void s2io_set_multicast(struct net_device *dev)
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
&bar0->rmac_addr_data0_mem);
writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
- &bar0->rmac_addr_data1_mem);
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
@@ -3039,8 +3640,7 @@ static void s2io_set_multicast(struct net_device *dev)
writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
&bar0->rmac_addr_data0_mem);
writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
- &bar0->rmac_addr_data1_mem);
-
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
@@ -3059,12 +3659,12 @@ static void s2io_set_multicast(struct net_device *dev)
}
/**
- * s2io_set_mac_addr - Programs the Xframe mac address
+ * s2io_set_mac_addr - Programs the Xframe mac address
* @dev : pointer to the device structure.
* @addr: a uchar pointer to the new mac address which is to be set.
- * Description : This procedure will program the Xframe to receive
+ * Description : This procedure will program the Xframe to receive
* frames with new Mac Address
- * Return value: SUCCESS on success and an appropriate (-)ve integer
+ * Return value: SUCCESS on success and an appropriate (-)ve integer
* as defined in errno.h file on failure.
*/
@@ -3075,10 +3675,10 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
register u64 val64, mac_addr = 0;
int i;
- /*
+ /*
* Set the new MAC address as the new unicast filter and reflect this
* change on the device address registered with the OS. It will be
- * at offset 0.
+ * at offset 0.
*/
for (i = 0; i < ETH_ALEN; i++) {
mac_addr <<= 8;
@@ -3102,12 +3702,12 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
}
/**
- * s2io_ethtool_sset - Sets different link parameters.
+ * s2io_ethtool_sset - Sets different link parameters.
* @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
* @info: pointer to the structure with parameters given by ethtool to set
* link information.
* Description:
- * The function sets different link parameters provided by the user onto
+ * The function sets different link parameters provided by the user onto
* the NIC.
* Return value:
* 0 on success.
@@ -3129,7 +3729,7 @@ static int s2io_ethtool_sset(struct net_device *dev,
}
/**
- * s2io_ethtol_gset - Return link specific information.
+ * s2io_ethtol_gset - Return link specific information.
* @sp : private member of the device structure, pointer to the
* s2io_nic structure.
* @info : pointer to the structure with parameters given by ethtool
@@ -3161,8 +3761,8 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
}
/**
- * s2io_ethtool_gdrvinfo - Returns driver specific information.
- * @sp : private member of the device structure, which is a pointer to the
+ * s2io_ethtool_gdrvinfo - Returns driver specific information.
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @info : pointer to the structure with parameters given by ethtool to
* return driver information.
@@ -3190,9 +3790,9 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
/**
* s2io_ethtool_gregs - dumps the entire space of Xfame into the buffer.
- * @sp: private member of the device structure, which is a pointer to the
+ * @sp: private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @regs : pointer to the structure with parameters given by ethtool for
+ * @regs : pointer to the structure with parameters given by ethtool for
* dumping the registers.
* @reg_space: The input argumnet into which all the registers are dumped.
* Description:
@@ -3221,11 +3821,11 @@ static void s2io_ethtool_gregs(struct net_device *dev,
/**
* s2io_phy_id - timer function that alternates adapter LED.
- * @data : address of the private member of the device structure, which
+ * @data : address of the private member of the device structure, which
* is a pointer to the s2io_nic structure, provided as an u32.
- * Description: This is actually the timer function that alternates the
- * adapter LED bit of the adapter control bit to set/reset every time on
- * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
+ * Description: This is actually the timer function that alternates the
+ * adapter LED bit of the adapter control bit to set/reset every time on
+ * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
* once every second.
*/
static void s2io_phy_id(unsigned long data)
@@ -3236,7 +3836,8 @@ static void s2io_phy_id(unsigned long data)
u16 subid;
subid = sp->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if ((sp->device_type == XFRAME_II_DEVICE) ||
+ ((subid & 0xFF) >= 0x07)) {
val64 = readq(&bar0->gpio_control);
val64 ^= GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -3253,12 +3854,12 @@ static void s2io_phy_id(unsigned long data)
* s2io_ethtool_idnic - To physically identify the nic on the system.
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @id : pointer to the structure with identification parameters given by
+ * @id : pointer to the structure with identification parameters given by
* ethtool.
* Description: Used to physically identify the NIC on the system.
- * The Link LED will blink for a time specified by the user for
+ * The Link LED will blink for a time specified by the user for
* identification.
- * NOTE: The Link has to be Up to be able to blink the LED. Hence
+ * NOTE: The Link has to be Up to be able to blink the LED. Hence
* identification is possible only if it's link is up.
* Return value:
* int , returns 0 on success
@@ -3273,7 +3874,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
subid = sp->pdev->subsystem_device;
last_gpio_ctrl_val = readq(&bar0->gpio_control);
- if ((subid & 0xFF) < 0x07) {
+ if ((sp->device_type == XFRAME_I_DEVICE) &&
+ ((subid & 0xFF) < 0x07)) {
val64 = readq(&bar0->adapter_control);
if (!(val64 & ADAPTER_CNTL_EN)) {
printk(KERN_ERR
@@ -3288,12 +3890,12 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
}
mod_timer(&sp->id_timer, jiffies);
if (data)
- msleep(data * 1000);
+ msleep_interruptible(data * HZ);
else
- msleep(0xFFFFFFFF);
+ msleep_interruptible(MAX_FLICKER_TIME);
del_timer_sync(&sp->id_timer);
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) {
writeq(last_gpio_ctrl_val, &bar0->gpio_control);
last_gpio_ctrl_val = readq(&bar0->gpio_control);
}
@@ -3303,7 +3905,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
/**
* s2io_ethtool_getpause_data -Pause frame frame generation and reception.
- * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
+ * @sp : private member of the device structure, which is a pointer to the
+ * s2io_nic structure.
* @ep : pointer to the structure with pause parameters given by ethtool.
* Description:
* Returns the Pause frame generation and reception capability of the NIC.
@@ -3327,7 +3930,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
/**
* s2io_ethtool_setpause_data - set/reset pause frame generation.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @ep : pointer to the structure with pause parameters given by ethtool.
* Description:
@@ -3338,7 +3941,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
*/
static int s2io_ethtool_setpause_data(struct net_device *dev,
- struct ethtool_pauseparam *ep)
+ struct ethtool_pauseparam *ep)
{
u64 val64;
nic_t *sp = dev->priv;
@@ -3359,13 +3962,13 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
/**
* read_eeprom - reads 4 bytes of data from user given offset.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @off : offset at which the data must be written
* @data : Its an output parameter where the data read at the given
- * offset is stored.
+ * offset is stored.
* Description:
- * Will read 4 bytes of data from the user given offset and return the
+ * Will read 4 bytes of data from the user given offset and return the
* read data.
* NOTE: Will allow to read only part of the EEPROM visible through the
* I2C bus.
@@ -3406,7 +4009,7 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
* s2io_nic structure.
* @off : offset at which the data must be written
* @data : The data that is to be written
- * @cnt : Number of bytes of the data that are actually to be written into
+ * @cnt : Number of bytes of the data that are actually to be written into
* the Eeprom. (max of 3)
* Description:
* Actually writes the relevant part of the data value into the Eeprom
@@ -3443,7 +4046,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
/**
* s2io_ethtool_geeprom - reads the value stored in the Eeprom.
* @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
- * @eeprom : pointer to the user level structure provided by ethtool,
+ * @eeprom : pointer to the user level structure provided by ethtool,
* containing all relevant information.
* @data_buf : user defined value to be written into Eeprom.
* Description: Reads the values stored in the Eeprom at given offset
@@ -3454,7 +4057,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
*/
static int s2io_ethtool_geeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 * data_buf)
+ struct ethtool_eeprom *eeprom, u8 * data_buf)
{
u32 data, i, valid;
nic_t *sp = dev->priv;
@@ -3479,7 +4082,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev,
* s2io_ethtool_seeprom - tries to write the user provided value in Eeprom
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @eeprom : pointer to the user level structure provided by ethtool,
+ * @eeprom : pointer to the user level structure provided by ethtool,
* containing all relevant information.
* @data_buf ; user defined value to be written into Eeprom.
* Description:
@@ -3527,8 +4130,8 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
}
/**
- * s2io_register_test - reads and writes into all clock domains.
- * @sp : private member of the device structure, which is a pointer to the
+ * s2io_register_test - reads and writes into all clock domains.
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data : variable that returns the result of each of the test conducted b
* by the driver.
@@ -3545,8 +4148,8 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
u64 val64 = 0;
int fail = 0;
- val64 = readq(&bar0->pcc_enable);
- if (val64 != 0xff00000000000000ULL) {
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 != 0x123456789abcdefULL) {
fail = 1;
DBG_PRINT(INFO_DBG, "Read Test level 1 fails\n");
}
@@ -3590,13 +4193,13 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
/**
- * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.
+ * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data:variable that returns the result of each of the test conducted by
* the driver.
* Description:
- * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
+ * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
* register.
* Return value:
* 0 on success.
@@ -3661,14 +4264,14 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
/**
* s2io_bist_test - invokes the MemBist test of the card .
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @data:variable that returns the result of each of the test conducted by
+ * @data:variable that returns the result of each of the test conducted by
* the driver.
* Description:
* This invokes the MemBist test of the card. We give around
* 2 secs time for the Test to complete. If it's still not complete
- * within this peiod, we consider that the test failed.
+ * within this peiod, we consider that the test failed.
* Return value:
* 0 on success and -1 on failure.
*/
@@ -3697,13 +4300,13 @@ static int s2io_bist_test(nic_t * sp, uint64_t * data)
}
/**
- * s2io-link_test - verifies the link state of the nic
- * @sp ; private member of the device structure, which is a pointer to the
+ * s2io-link_test - verifies the link state of the nic
+ * @sp ; private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data: variable that returns the result of each of the test conducted by
* the driver.
* Description:
- * The function verifies the link state of the NIC and updates the input
+ * The function verifies the link state of the NIC and updates the input
* argument 'data' appropriately.
* Return value:
* 0 on success.
@@ -3722,13 +4325,13 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
}
/**
- * s2io_rldram_test - offline test for access to the RldRam chip on the NIC
- * @sp - private member of the device structure, which is a pointer to the
+ * s2io_rldram_test - offline test for access to the RldRam chip on the NIC
+ * @sp - private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @data - variable that returns the result of each of the test
+ * @data - variable that returns the result of each of the test
* conducted by the driver.
* Description:
- * This is one of the offline test that tests the read and write
+ * This is one of the offline test that tests the read and write
* access to the RldRam chip on the NIC.
* Return value:
* 0 on success.
@@ -3833,7 +4436,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
* s2io_nic structure.
* @ethtest : pointer to a ethtool command specific structure that will be
* returned to the user.
- * @data : variable that returns the result of each of the test
+ * @data : variable that returns the result of each of the test
* conducted by the driver.
* Description:
* This function conducts 6 tests ( 4 offline and 2 online) to determine
@@ -3851,23 +4454,18 @@ static void s2io_ethtool_test(struct net_device *dev,
if (ethtest->flags == ETH_TEST_FL_OFFLINE) {
/* Offline Tests. */
- if (orig_state) {
+ if (orig_state)
s2io_close(sp->dev);
- s2io_set_swapper(sp);
- } else
- s2io_set_swapper(sp);
if (s2io_register_test(sp, &data[0]))
ethtest->flags |= ETH_TEST_FL_FAILED;
s2io_reset(sp);
- s2io_set_swapper(sp);
if (s2io_rldram_test(sp, &data[3]))
ethtest->flags |= ETH_TEST_FL_FAILED;
s2io_reset(sp);
- s2io_set_swapper(sp);
if (s2io_eeprom_test(sp, &data[1]))
ethtest->flags |= ETH_TEST_FL_FAILED;
@@ -3910,61 +4508,111 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
nic_t *sp = dev->priv;
StatInfo_t *stat_info = sp->mac_control.stats_info;
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+ s2io_updt_stats(sp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_data_octets);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_mcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_bcst_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_any_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_vld_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_drop_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_icmp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_rst_tcp);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_data_octets);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_bcst_frms);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_discarded_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_usized_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_osized_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_frag_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_jabber_frms);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_ip);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_drop_ip);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_icmp);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_err_drp_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_pause_cnt);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_accepted_ip);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
+ tmp_stats[i++] = 0;
+ tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
+ tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
}
-static int s2io_ethtool_get_regs_len(struct net_device *dev)
+int s2io_ethtool_get_regs_len(struct net_device *dev)
{
return (XENA_REG_SPACE);
}
-static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
{
nic_t *sp = dev->priv;
return (sp->rx_csum);
}
-
-static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
{
nic_t *sp = dev->priv;
@@ -3975,19 +4623,17 @@ static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
-
-static int s2io_get_eeprom_len(struct net_device *dev)
+int s2io_get_eeprom_len(struct net_device *dev)
{
return (XENA_EEPROM_SPACE);
}
-static int s2io_ethtool_self_test_count(struct net_device *dev)
+int s2io_ethtool_self_test_count(struct net_device *dev)
{
return (S2IO_TEST_LEN);
}
-
-static void s2io_ethtool_get_strings(struct net_device *dev,
- u32 stringset, u8 * data)
+void s2io_ethtool_get_strings(struct net_device *dev,
+ u32 stringset, u8 * data)
{
switch (stringset) {
case ETH_SS_TEST:
@@ -3998,13 +4644,12 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
sizeof(ethtool_stats_keys));
}
}
-
static int s2io_ethtool_get_stats_count(struct net_device *dev)
{
return (S2IO_STAT_LEN);
}
-static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
{
if (data)
dev->features |= NETIF_F_IP_CSUM;
@@ -4046,21 +4691,18 @@ static struct ethtool_ops netdev_ethtool_ops = {
};
/**
- * s2io_ioctl - Entry point for the Ioctl
+ * s2io_ioctl - Entry point for the Ioctl
* @dev : Device pointer.
* @ifr : An IOCTL specefic structure, that can contain a pointer to
* a proprietary structure used to pass information to the driver.
* @cmd : This is used to distinguish between the different commands that
* can be passed to the IOCTL functions.
* Description:
- * This function has support for ethtool, adding multiple MAC addresses on
- * the NIC and some DBG commands for the util tool.
- * Return value:
- * Currently the IOCTL supports no operations, hence by default this
- * function returns OP NOT SUPPORTED value.
+ * Currently there are no special functionality supported in IOCTL, hence
+ * function always return EOPNOTSUPPORTED
*/
-static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
return -EOPNOTSUPP;
}
@@ -4076,17 +4718,9 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* file on failure.
*/
-static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+int s2io_change_mtu(struct net_device *dev, int new_mtu)
{
nic_t *sp = dev->priv;
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
- register u64 val64;
-
- if (netif_running(dev)) {
- DBG_PRINT(ERR_DBG, "%s: Must be stopped to ", dev->name);
- DBG_PRINT(ERR_DBG, "change its MTU \n");
- return -EBUSY;
- }
if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -4094,11 +4728,22 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
return -EPERM;
}
- /* Set the new MTU into the PYLD register of the NIC */
- val64 = new_mtu;
- writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
-
dev->mtu = new_mtu;
+ if (netif_running(dev)) {
+ s2io_card_down(sp);
+ netif_stop_queue(dev);
+ if (s2io_card_up(sp)) {
+ DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ __FUNCTION__);
+ }
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ } else { /* Device is down */
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64 = new_mtu;
+
+ writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
+ }
return 0;
}
@@ -4108,9 +4753,9 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
* @dev_adr : address of the device structure in dma_addr_t format.
* Description:
* This is the tasklet or the bottom half of the ISR. This is
- * an extension of the ISR which is scheduled by the scheduler to be run
+ * an extension of the ISR which is scheduled by the scheduler to be run
* when the load on the CPU is low. All low priority tasks of the ISR can
- * be pushed into the tasklet. For now the tasklet is used only to
+ * be pushed into the tasklet. For now the tasklet is used only to
* replenish the Rx buffers in the Rx buffer descriptors.
* Return value:
* void.
@@ -4166,19 +4811,22 @@ static void s2io_set_link(unsigned long data)
}
subid = nic->pdev->subsystem_device;
- /*
- * Allow a small delay for the NICs self initiated
- * cleanup to complete.
- */
- msleep(100);
+ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+ /*
+ * Allow a small delay for the NICs self initiated
+ * cleanup to complete.
+ */
+ msleep(100);
+ }
val64 = readq(&bar0->adapter_status);
- if (verify_xena_quiescence(val64, nic->device_enabled_once)) {
+ if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
if (LINK_IS_UP(val64)) {
val64 = readq(&bar0->adapter_control);
val64 |= ADAPTER_CNTL_EN;
writeq(val64, &bar0->adapter_control);
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+ subid)) {
val64 = readq(&bar0->gpio_control);
val64 |= GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -4187,20 +4835,24 @@ static void s2io_set_link(unsigned long data)
val64 |= ADAPTER_LED_ON;
writeq(val64, &bar0->adapter_control);
}
- val64 = readq(&bar0->adapter_status);
- if (!LINK_IS_UP(val64)) {
- DBG_PRINT(ERR_DBG, "%s:", dev->name);
- DBG_PRINT(ERR_DBG, " Link down");
- DBG_PRINT(ERR_DBG, "after ");
- DBG_PRINT(ERR_DBG, "enabling ");
- DBG_PRINT(ERR_DBG, "device \n");
+ if (s2io_link_fault_indication(nic) ==
+ MAC_RMAC_ERR_TIMER) {
+ val64 = readq(&bar0->adapter_status);
+ if (!LINK_IS_UP(val64)) {
+ DBG_PRINT(ERR_DBG, "%s:", dev->name);
+ DBG_PRINT(ERR_DBG, " Link down");
+ DBG_PRINT(ERR_DBG, "after ");
+ DBG_PRINT(ERR_DBG, "enabling ");
+ DBG_PRINT(ERR_DBG, "device \n");
+ }
}
if (nic->device_enabled_once == FALSE) {
nic->device_enabled_once = TRUE;
}
s2io_link(nic, LINK_UP);
} else {
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+ subid)) {
val64 = readq(&bar0->gpio_control);
val64 &= ~GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -4223,9 +4875,11 @@ static void s2io_card_down(nic_t * sp)
unsigned long flags;
register u64 val64 = 0;
+ del_timer_sync(&sp->alarm_timer);
/* If s2io_set_link task is executing, wait till it completes. */
- while (test_and_set_bit(0, &(sp->link_state)))
+ while (test_and_set_bit(0, &(sp->link_state))) {
msleep(50);
+ }
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
@@ -4237,7 +4891,7 @@ static void s2io_card_down(nic_t * sp)
/* Check if the device is Quiescent and then Reset the NIC */
do {
val64 = readq(&bar0->adapter_status);
- if (verify_xena_quiescence(val64, sp->device_enabled_once)) {
+ if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
break;
}
@@ -4251,14 +4905,27 @@ static void s2io_card_down(nic_t * sp)
break;
}
} while (1);
- spin_lock_irqsave(&sp->tx_lock, flags);
s2io_reset(sp);
- /* Free all unused Tx and Rx buffers */
+ /* Waiting till all Interrupt handlers are complete */
+ cnt = 0;
+ do {
+ msleep(10);
+ if (!atomic_read(&sp->isr_cnt))
+ break;
+ cnt++;
+ } while(cnt < 5);
+
+ spin_lock_irqsave(&sp->tx_lock, flags);
+ /* Free all Tx buffers */
free_tx_buffers(sp);
+ spin_unlock_irqrestore(&sp->tx_lock, flags);
+
+ /* Free all Rx buffers */
+ spin_lock_irqsave(&sp->rx_lock, flags);
free_rx_buffers(sp);
+ spin_unlock_irqrestore(&sp->rx_lock, flags);
- spin_unlock_irqrestore(&sp->tx_lock, flags);
clear_bit(0, &(sp->link_state));
}
@@ -4276,8 +4943,8 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
- /*
- * Initializing the Rx buffers. For now we are considering only 1
+ /*
+ * Initializing the Rx buffers. For now we are considering only 1
* Rx ring and initializing buffers into 30 Rx blocks
*/
mac_control = &sp->mac_control;
@@ -4311,16 +4978,18 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
+ S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+
atomic_set(&sp->card_state, CARD_UP);
return 0;
}
-/**
+/**
* s2io_restart_nic - Resets the NIC.
* @data : long pointer to the device private structure
* Description:
* This function is scheduled to be run by the s2io_tx_watchdog
- * function after 0.5 secs to reset the NIC. The idea is to reduce
+ * function after 0.5 secs to reset the NIC. The idea is to reduce
* the run time of the watch dog routine which is run holding a
* spin lock.
*/
@@ -4338,10 +5007,11 @@ static void s2io_restart_nic(unsigned long data)
netif_wake_queue(dev);
DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
dev->name);
+
}
-/**
- * s2io_tx_watchdog - Watchdog for transmit side.
+/**
+ * s2io_tx_watchdog - Watchdog for transmit side.
* @dev : Pointer to net device structure
* Description:
* This function is triggered if the Tx Queue is stopped
@@ -4369,7 +5039,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
* @len : length of the packet
* @cksum : FCS checksum of the frame.
* @ring_no : the ring from which this RxD was extracted.
- * Description:
+ * Description:
* This function is called by the Tx interrupt serivce routine to perform
* some OS related operations on the SKB before passing it to the upper
* layers. It mainly checks if the checksum is OK, if so adds it to the
@@ -4379,35 +5049,68 @@ static void s2io_tx_watchdog(struct net_device *dev)
* Return value:
* SUCCESS on success and -1 on failure.
*/
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no)
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
- buffAdd_t * ba)
-#endif
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
{
+ nic_t *sp = ring_data->nic;
struct net_device *dev = (struct net_device *) sp->dev;
- struct sk_buff *skb =
- (struct sk_buff *) ((unsigned long) rxdp->Host_Control);
+ struct sk_buff *skb = (struct sk_buff *)
+ ((unsigned long) rxdp->Host_Control);
+ int ring_no = ring_data->ring_no;
u16 l3_csum, l4_csum;
#ifdef CONFIG_2BUFF_MODE
- int buf0_len, buf2_len;
+ int buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
+ int buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
+ int get_block = ring_data->rx_curr_get_info.block_index;
+ int get_off = ring_data->rx_curr_get_info.offset;
+ buffAdd_t *ba = &ring_data->ba[get_block][get_off];
unsigned char *buff;
+#else
+ u16 len = (u16) ((RXD_GET_BUFFER0_SIZE(rxdp->Control_2)) >> 48);;
+#endif
+ skb->dev = dev;
+ if (rxdp->Control_1 & RXD_T_CODE) {
+ unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
+ DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+ dev->name, err);
+ dev_kfree_skb(skb);
+ sp->stats.rx_crc_errors++;
+ atomic_dec(&sp->rx_bufs_left[ring_no]);
+ rxdp->Host_Control = 0;
+ return 0;
+ }
+
+ /* Updating statistics */
+ rxdp->Host_Control = 0;
+ sp->rx_pkt_count++;
+ sp->stats.rx_packets++;
+#ifndef CONFIG_2BUFF_MODE
+ sp->stats.rx_bytes += len;
+#else
+ sp->stats.rx_bytes += buf0_len + buf2_len;
#endif
- l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
- if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) {
+#ifndef CONFIG_2BUFF_MODE
+ skb_put(skb, len);
+#else
+ buff = skb_push(skb, buf0_len);
+ memcpy(buff, ba->ba_0, buf0_len);
+ skb_put(skb, buf2_len);
+#endif
+
+ if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
+ (sp->rx_csum)) {
+ l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) {
- /*
+ /*
* NIC verifies if the Checksum of the received
* frame is Ok or not and accordingly returns
* a flag in the RxD.
*/
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
- /*
- * Packet with erroneous checksum, let the
+ /*
+ * Packet with erroneous checksum, let the
* upper layers deal with it.
*/
skb->ip_summed = CHECKSUM_NONE;
@@ -4416,44 +5119,26 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
skb->ip_summed = CHECKSUM_NONE;
}
- if (rxdp->Control_1 & RXD_T_CODE) {
- unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
- DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
- dev->name, err);
- }
-#ifdef CONFIG_2BUFF_MODE
- buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
-#endif
-
- skb->dev = dev;
-#ifndef CONFIG_2BUFF_MODE
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, dev);
-#else
- buff = skb_push(skb, buf0_len);
- memcpy(buff, ba->ba_0, buf0_len);
- skb_put(skb, buf2_len);
skb->protocol = eth_type_trans(skb, dev);
-#endif
-
#ifdef CONFIG_S2IO_NAPI
- netif_receive_skb(skb);
+ if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+ /* Queueing the vlan frame to the upper layer */
+ vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+ RXD_GET_VLAN_TAG(rxdp->Control_2));
+ } else {
+ netif_receive_skb(skb);
+ }
#else
- netif_rx(skb);
+ if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+ /* Queueing the vlan frame to the upper layer */
+ vlan_hwaccel_rx(skb, sp->vlgrp,
+ RXD_GET_VLAN_TAG(rxdp->Control_2));
+ } else {
+ netif_rx(skb);
+ }
#endif
-
dev->last_rx = jiffies;
- sp->rx_pkt_count++;
- sp->stats.rx_packets++;
-#ifndef CONFIG_2BUFF_MODE
- sp->stats.rx_bytes += len;
-#else
- sp->stats.rx_bytes += buf0_len + buf2_len;
-#endif
-
atomic_dec(&sp->rx_bufs_left[ring_no]);
- rxdp->Host_Control = 0;
return SUCCESS;
}
@@ -4464,13 +5149,13 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
* @link : inidicates whether link is UP/DOWN.
* Description:
* This function stops/starts the Tx queue depending on whether the link
- * status of the NIC is is down or up. This is called by the Alarm
- * interrupt handler whenever a link change interrupt comes up.
+ * status of the NIC is is down or up. This is called by the Alarm
+ * interrupt handler whenever a link change interrupt comes up.
* Return value:
* void.
*/
-static void s2io_link(nic_t * sp, int link)
+void s2io_link(nic_t * sp, int link)
{
struct net_device *dev = (struct net_device *) sp->dev;
@@ -4487,8 +5172,25 @@ static void s2io_link(nic_t * sp, int link)
}
/**
- * s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
- * @sp : private member of the device structure, which is a pointer to the
+ * get_xena_rev_id - to identify revision ID of xena.
+ * @pdev : PCI Dev structure
+ * Description:
+ * Function to identify the Revision ID of xena.
+ * Return value:
+ * returns the revision ID of the device.
+ */
+
+int get_xena_rev_id(struct pci_dev *pdev)
+{
+ u8 id = 0;
+ int ret;
+ ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
+ return id;
+}
+
+/**
+ * s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* Description:
* This function initializes a few of the PCI and PCI-X configuration registers
@@ -4499,15 +5201,15 @@ static void s2io_link(nic_t * sp, int link)
static void s2io_init_pci(nic_t * sp)
{
- u16 pci_cmd = 0;
+ u16 pci_cmd = 0, pcix_cmd = 0;
/* Enable Data Parity Error Recovery in PCI-X command register. */
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- (sp->pcix_cmd | 1));
+ (pcix_cmd | 1));
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
/* Set the PErr Response bit in PCI command register. */
pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
@@ -4515,53 +5217,43 @@ static void s2io_init_pci(nic_t * sp)
(pci_cmd | PCI_COMMAND_PARITY));
pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
- /* Set MMRB count to 1024 in PCI-X Command register. */
- sp->pcix_cmd &= 0xFFF3;
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, (sp->pcix_cmd | (0x1 << 2))); /* MMRBC 1K */
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
-
- /* Setting Maximum outstanding splits based on system type. */
- sp->pcix_cmd &= 0xFF8F;
-
- sp->pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1); /* 2 splits. */
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- sp->pcix_cmd);
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
/* Forcibly disabling relaxed ordering capability of the card. */
- sp->pcix_cmd &= 0xfffd;
+ pcix_cmd &= 0xfffd;
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- sp->pcix_cmd);
+ pcix_cmd);
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
}
MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
module_param(tx_fifo_num, int, 0);
-module_param_array(tx_fifo_len, int, NULL, 0);
module_param(rx_ring_num, int, 0);
-module_param_array(rx_ring_sz, int, NULL, 0);
-module_param(Stats_refresh_time, int, 0);
+module_param_array(tx_fifo_len, uint, NULL, 0);
+module_param_array(rx_ring_sz, uint, NULL, 0);
+module_param_array(rts_frm_len, uint, NULL, 0);
+module_param(use_continuous_tx_intrs, int, 1);
module_param(rmac_pause_time, int, 0);
module_param(mc_pause_threshold_q0q3, int, 0);
module_param(mc_pause_threshold_q4q7, int, 0);
module_param(shared_splits, int, 0);
module_param(tmac_util_period, int, 0);
module_param(rmac_util_period, int, 0);
+module_param(bimodal, bool, 0);
#ifndef CONFIG_S2IO_NAPI
module_param(indicate_max_pkts, int, 0);
#endif
+module_param(rxsync_frequency, int, 0);
+
/**
- * s2io_init_nic - Initialization of the adapter .
+ * s2io_init_nic - Initialization of the adapter .
* @pdev : structure containing the PCI related information of the device.
* @pre: List of PCI devices supported by the driver listed in s2io_tbl.
* Description:
* The function initializes an adapter identified by the pci_dec structure.
- * All OS related initialization including memory and device structure and
- * initlaization of the device private variable is done. Also the swapper
- * control register is initialized to enable read and write into the I/O
+ * All OS related initialization including memory and device structure and
+ * initlaization of the device private variable is done. Also the swapper
+ * control register is initialized to enable read and write into the I/O
* registers of the device.
* Return value:
* returns 0 on success and negative on failure.
@@ -4572,7 +5264,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
{
nic_t *sp;
struct net_device *dev;
- char *dev_name = "S2IO 10GE NIC";
int i, j, ret;
int dma_flag = FALSE;
u32 mac_up, mac_down;
@@ -4581,10 +5272,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
u16 subid;
mac_info_t *mac_control;
struct config_param *config;
+ int mode;
-
- DBG_PRINT(ERR_DBG, "Loading S2IO driver with %s\n",
- s2io_driver_version);
+#ifdef CONFIG_S2IO_NAPI
+ DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+#endif
if ((ret = pci_enable_device(pdev))) {
DBG_PRINT(ERR_DBG,
@@ -4595,7 +5287,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
dma_flag = TRUE;
-
if (pci_set_consistent_dma_mask
(pdev, DMA_64BIT_MASK)) {
DBG_PRINT(ERR_DBG,
@@ -4635,34 +5326,41 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
memset(sp, 0, sizeof(nic_t));
sp->dev = dev;
sp->pdev = pdev;
- sp->vendor_id = pdev->vendor;
- sp->device_id = pdev->device;
sp->high_dma_flag = dma_flag;
- sp->irq = pdev->irq;
sp->device_enabled_once = FALSE;
- strcpy(sp->name, dev_name);
+
+ if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
+ (pdev->device == PCI_DEVICE_ID_HERC_UNI))
+ sp->device_type = XFRAME_II_DEVICE;
+ else
+ sp->device_type = XFRAME_I_DEVICE;
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
- /*
+ /*
* Setting the device configuration parameters.
- * Most of these parameters can be specified by the user during
- * module insertion as they are module loadable parameters. If
- * these parameters are not not specified during load time, they
+ * Most of these parameters can be specified by the user during
+ * module insertion as they are module loadable parameters. If
+ * these parameters are not not specified during load time, they
* are initialized with default values.
*/
mac_control = &sp->mac_control;
config = &sp->config;
/* Tx side parameters. */
- tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
+ if (tx_fifo_len[0] == 0)
+ tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
config->tx_fifo_num = tx_fifo_num;
for (i = 0; i < MAX_TX_FIFOS; i++) {
config->tx_cfg[i].fifo_len = tx_fifo_len[i];
config->tx_cfg[i].fifo_priority = i;
}
+ /* mapping the QoS priority to the configured fifos */
+ for (i = 0; i < MAX_TX_FIFOS; i++)
+ config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
+
config->tx_intr_type = TXD_INT_TYPE_UTILZ;
for (i = 0; i < config->tx_fifo_num; i++) {
config->tx_cfg[i].f_no_snoop =
@@ -4672,10 +5370,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
break;
}
}
- config->max_txds = MAX_SKB_FRAGS;
+ config->max_txds = MAX_SKB_FRAGS + 1;
/* Rx side parameters. */
- rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
+ if (rx_ring_sz[0] == 0)
+ rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
config->rx_ring_num = rx_ring_num;
for (i = 0; i < MAX_RX_RINGS; i++) {
config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -4699,10 +5398,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
for (i = 0; i < config->rx_ring_num; i++)
atomic_set(&sp->rx_bufs_left[i], 0);
+ /* Initialize the number of ISRs currently running */
+ atomic_set(&sp->isr_cnt, 0);
+
/* initialize the shared memory used by the NIC and the host */
if (init_shared_mem(sp)) {
DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
- dev->name);
+ __FUNCTION__);
ret = -ENOMEM;
goto mem_alloc_failed;
}
@@ -4743,13 +5445,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->do_ioctl = &s2io_ioctl;
dev->change_mtu = &s2io_change_mtu;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_rx_register = s2io_vlan_rx_register;
+ dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
+
/*
* will use eth_mac_addr() for dev->set_mac_address
* mac address will be set every time dev->open() is called
*/
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
dev->poll = s2io_poll;
- dev->weight = 90;
+ dev->weight = 32;
#endif
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
@@ -4776,22 +5482,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto set_swap_failed;
}
- /* Fix for all "FFs" MAC address problems observed on Alpha platforms */
- fix_mac_address(sp);
- s2io_reset(sp);
+ /* Verify if the Herc works on the slot its placed into */
+ if (sp->device_type & XFRAME_II_DEVICE) {
+ mode = s2io_verify_pci_mode(sp);
+ if (mode < 0) {
+ DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__);
+ DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
+ ret = -EBADSLT;
+ goto set_swap_failed;
+ }
+ }
- /*
- * Setting swapper control on the NIC, so the MAC address can be read.
- */
- if (s2io_set_swapper(sp)) {
- DBG_PRINT(ERR_DBG,
- "%s: S2IO: swapper settings are wrong\n",
- dev->name);
- ret = -EAGAIN;
- goto set_swap_failed;
+ /* Not needed for Herc */
+ if (sp->device_type & XFRAME_I_DEVICE) {
+ /*
+ * Fix for all "FFs" MAC address problems observed on
+ * Alpha platforms
+ */
+ fix_mac_address(sp);
+ s2io_reset(sp);
}
- /*
+ /*
* MAC address initialization.
* For now only one mac address will be read and used.
*/
@@ -4814,37 +5526,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);
sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24);
- DBG_PRINT(INIT_DBG,
- "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n",
- sp->def_mac_addr[0].mac_addr[0],
- sp->def_mac_addr[0].mac_addr[1],
- sp->def_mac_addr[0].mac_addr[2],
- sp->def_mac_addr[0].mac_addr[3],
- sp->def_mac_addr[0].mac_addr[4],
- sp->def_mac_addr[0].mac_addr[5]);
-
/* Set the factory defined MAC address initially */
dev->addr_len = ETH_ALEN;
memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
/*
- * Initialize the tasklet status and link state flags
- * and the card statte parameter
+ * Initialize the tasklet status and link state flags
+ * and the card state parameter
*/
atomic_set(&(sp->card_state), 0);
sp->tasklet_status = 0;
sp->link_state = 0;
-
/* Initialize spinlocks */
spin_lock_init(&sp->tx_lock);
#ifndef CONFIG_S2IO_NAPI
spin_lock_init(&sp->put_lock);
#endif
+ spin_lock_init(&sp->rx_lock);
- /*
- * SXE-002: Configure link and activity LED to init state
- * on driver load.
+ /*
+ * SXE-002: Configure link and activity LED to init state
+ * on driver load.
*/
subid = sp->pdev->subsystem_device;
if ((subid & 0xFF) >= 0x07) {
@@ -4864,13 +5567,70 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto register_failed;
}
- /*
- * Make Link state as off at this point, when the Link change
- * interrupt comes the state will be automatically changed to
+ if (sp->device_type & XFRAME_II_DEVICE) {
+ DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "(rev %d), %s",
+ get_xena_rev_id(sp->pdev),
+ s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+ DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+
+ DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+ DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ sp->def_mac_addr[0].mac_addr[0],
+ sp->def_mac_addr[0].mac_addr[1],
+ sp->def_mac_addr[0].mac_addr[2],
+ sp->def_mac_addr[0].mac_addr[3],
+ sp->def_mac_addr[0].mac_addr[4],
+ sp->def_mac_addr[0].mac_addr[5]);
+ mode = s2io_print_pci_mode(sp);
+ if (mode < 0) {
+ DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+ ret = -EBADSLT;
+ goto set_swap_failed;
+ }
+ } else {
+ DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "(rev %d), %s",
+ get_xena_rev_id(sp->pdev),
+ s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+ DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+ DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+ DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ sp->def_mac_addr[0].mac_addr[0],
+ sp->def_mac_addr[0].mac_addr[1],
+ sp->def_mac_addr[0].mac_addr[2],
+ sp->def_mac_addr[0].mac_addr[3],
+ sp->def_mac_addr[0].mac_addr[4],
+ sp->def_mac_addr[0].mac_addr[5]);
+ }
+
+ /* Initialize device name */
+ strcpy(sp->name, dev->name);
+ if (sp->device_type & XFRAME_II_DEVICE)
+ strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
+ else
+ strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+
+ /* Initialize bimodal Interrupts */
+ sp->config.bimodal = bimodal;
+ if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
+ sp->config.bimodal = 0;
+ DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
+ dev->name);
+ }
+
+ /*
+ * Make Link state as off at this point, when the Link change
+ * interrupt comes the state will be automatically changed to
* the right state.
*/
netif_carrier_off(dev);
- sp->last_link_state = LINK_DOWN;
return 0;
@@ -4891,11 +5651,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
}
/**
- * s2io_rem_nic - Free the PCI device
+ * s2io_rem_nic - Free the PCI device
* @pdev: structure containing the PCI related information of the device.
- * Description: This function is called by the Pci subsystem to release a
+ * Description: This function is called by the Pci subsystem to release a
* PCI device and free up all resource held up by the device. This could
- * be in response to a Hot plug event or when the driver is to be removed
+ * be in response to a Hot plug event or when the driver is to be removed
* from memory.
*/
@@ -4919,7 +5679,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
pci_disable_device(pdev);
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
-
free_netdev(dev);
}
@@ -4935,11 +5694,11 @@ int __init s2io_starter(void)
}
/**
- * s2io_closer - Cleanup routine for the driver
+ * s2io_closer - Cleanup routine for the driver
* Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
*/
-static void s2io_closer(void)
+void s2io_closer(void)
{
pci_unregister_driver(&s2io_driver);
DBG_PRINT(INIT_DBG, "cleanup done\n");
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 1711c8c3dc99..89151cb52181 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -1,5 +1,5 @@
/************************************************************************
- * s2io.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -31,6 +31,9 @@
#define SUCCESS 0
#define FAILURE -1
+/* Maximum time to flicker LED when asked to identify NIC using ethtool */
+#define MAX_FLICKER_TIME 60000 /* 60 Secs */
+
/* Maximum outstanding splits to be configured into xena. */
typedef enum xena_max_outstanding_splits {
XENA_ONE_SPLIT_TRANSACTION = 0,
@@ -45,10 +48,10 @@ typedef enum xena_max_outstanding_splits {
#define XENA_MAX_OUTSTANDING_SPLITS(n) (n << 4)
/* OS concerned variables and constants */
-#define WATCH_DOG_TIMEOUT 5*HZ
-#define EFILL 0x1234
-#define ALIGN_SIZE 127
-#define PCIX_COMMAND_REGISTER 0x62
+#define WATCH_DOG_TIMEOUT 15*HZ
+#define EFILL 0x1234
+#define ALIGN_SIZE 127
+#define PCIX_COMMAND_REGISTER 0x62
/*
* Debug related variables.
@@ -61,7 +64,7 @@ typedef enum xena_max_outstanding_splits {
#define INTR_DBG 4
/* Global variable that defines the present debug level of the driver. */
-static int debug_level = ERR_DBG; /* Default level. */
+int debug_level = ERR_DBG; /* Default level. */
/* DEBUG message print. */
#define DBG_PRINT(dbg_level, args...) if(!(debug_level<dbg_level)) printk(args)
@@ -71,6 +74,12 @@ static int debug_level = ERR_DBG; /* Default level. */
#define L4_CKSUM_OK 0xFFFF
#define S2IO_JUMBO_SIZE 9600
+/* Driver statistics maintained by driver */
+typedef struct {
+ unsigned long long single_ecc_errs;
+ unsigned long long double_ecc_errs;
+} swStat_t;
+
/* The statistics block of Xena */
typedef struct stat_block {
/* Tx MAC statistics counters. */
@@ -186,12 +195,90 @@ typedef struct stat_block {
u32 rxd_rd_cnt;
u32 rxf_wr_cnt;
u32 txf_rd_cnt;
+
+/* Tx MAC statistics overflow counters. */
+ u32 tmac_data_octets_oflow;
+ u32 tmac_frms_oflow;
+ u32 tmac_bcst_frms_oflow;
+ u32 tmac_mcst_frms_oflow;
+ u32 tmac_ucst_frms_oflow;
+ u32 tmac_ttl_octets_oflow;
+ u32 tmac_any_err_frms_oflow;
+ u32 tmac_nucst_frms_oflow;
+ u64 tmac_vlan_frms;
+ u32 tmac_drop_ip_oflow;
+ u32 tmac_vld_ip_oflow;
+ u32 tmac_rst_tcp_oflow;
+ u32 tmac_icmp_oflow;
+ u32 tpa_unknown_protocol;
+ u32 tmac_udp_oflow;
+ u32 reserved_10;
+ u32 tpa_parse_failure;
+
+/* Rx MAC Statistics overflow counters. */
+ u32 rmac_data_octets_oflow;
+ u32 rmac_vld_frms_oflow;
+ u32 rmac_vld_bcst_frms_oflow;
+ u32 rmac_vld_mcst_frms_oflow;
+ u32 rmac_accepted_ucst_frms_oflow;
+ u32 rmac_ttl_octets_oflow;
+ u32 rmac_discarded_frms_oflow;
+ u32 rmac_accepted_nucst_frms_oflow;
+ u32 rmac_usized_frms_oflow;
+ u32 rmac_drop_events_oflow;
+ u32 rmac_frag_frms_oflow;
+ u32 rmac_osized_frms_oflow;
+ u32 rmac_ip_oflow;
+ u32 rmac_jabber_frms_oflow;
+ u32 rmac_icmp_oflow;
+ u32 rmac_drop_ip_oflow;
+ u32 rmac_err_drp_udp_oflow;
+ u32 rmac_udp_oflow;
+ u32 reserved_11;
+ u32 rmac_pause_cnt_oflow;
+ u64 rmac_ttl_1519_4095_frms;
+ u64 rmac_ttl_4096_8191_frms;
+ u64 rmac_ttl_8192_max_frms;
+ u64 rmac_ttl_gt_max_frms;
+ u64 rmac_osized_alt_frms;
+ u64 rmac_jabber_alt_frms;
+ u64 rmac_gt_max_alt_frms;
+ u64 rmac_vlan_frms;
+ u32 rmac_len_discard;
+ u32 rmac_fcs_discard;
+ u32 rmac_pf_discard;
+ u32 rmac_da_discard;
+ u32 rmac_red_discard;
+ u32 rmac_rts_discard;
+ u32 reserved_12;
+ u32 rmac_ingm_full_discard;
+ u32 reserved_13;
+ u32 rmac_accepted_ip_oflow;
+ u32 reserved_14;
+ u32 link_fault_cnt;
+ swStat_t sw_stat;
} StatInfo_t;
-/* Structures representing different init time configuration
+/*
+ * Structures representing different init time configuration
* parameters of the NIC.
*/
+#define MAX_TX_FIFOS 8
+#define MAX_RX_RINGS 8
+
+/* FIFO mappings for all possible number of fifos configured */
+int fifo_map[][MAX_TX_FIFOS] = {
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 1},
+ {0, 0, 0, 1, 1, 1, 2, 2},
+ {0, 0, 1, 1, 2, 2, 3, 3},
+ {0, 0, 1, 1, 2, 2, 3, 4},
+ {0, 0, 1, 1, 2, 3, 4, 5},
+ {0, 0, 1, 2, 3, 4, 5, 6},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+};
+
/* Maintains Per FIFO related information. */
typedef struct tx_fifo_config {
#define MAX_AVAILABLE_TXDS 8192
@@ -237,14 +324,14 @@ typedef struct rx_ring_config {
#define NO_SNOOP_RXD_BUFFER 0x02
} rx_ring_config_t;
-/* This structure provides contains values of the tunable parameters
- * of the H/W
+/* This structure provides contains values of the tunable parameters
+ * of the H/W
*/
struct config_param {
/* Tx Side */
u32 tx_fifo_num; /*Number of Tx FIFOs */
-#define MAX_TX_FIFOS 8
+ u8 fifo_mapping[MAX_TX_FIFOS];
tx_fifo_config_t tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */
u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */
u64 tx_intr_type;
@@ -252,10 +339,10 @@ struct config_param {
/* Rx Side */
u32 rx_ring_num; /*Number of receive rings */
-#define MAX_RX_RINGS 8
#define MAX_RX_BLOCKS_PER_RING 150
rx_ring_config_t rx_cfg[MAX_RX_RINGS]; /*Per-Rx Ring config */
+ u8 bimodal; /*Flag for setting bimodal interrupts*/
#define HEADER_ETHERNET_II_802_3_SIZE 14
#define HEADER_802_2_SIZE 3
@@ -269,6 +356,7 @@ struct config_param {
#define MAX_PYLD_JUMBO 9600
#define MAX_MTU_JUMBO (MAX_PYLD_JUMBO+18)
#define MAX_MTU_JUMBO_VLAN (MAX_PYLD_JUMBO+22)
+ u16 bus_speed;
};
/* Structure representing MAC Addrs */
@@ -277,7 +365,7 @@ typedef struct mac_addr {
} macaddr_t;
/* Structure that represent every FIFO element in the BAR1
- * Address location.
+ * Address location.
*/
typedef struct _TxFIFO_element {
u64 TxDL_Pointer;
@@ -339,6 +427,7 @@ typedef struct _RxD_t {
#define RXD_FRAME_PROTO vBIT(0xFFFF,24,8)
#define RXD_FRAME_PROTO_IPV4 BIT(27)
#define RXD_FRAME_PROTO_IPV6 BIT(28)
+#define RXD_FRAME_IP_FRAG BIT(29)
#define RXD_FRAME_PROTO_TCP BIT(30)
#define RXD_FRAME_PROTO_UDP BIT(31)
#define TCP_OR_UDP_FRAME (RXD_FRAME_PROTO_TCP | RXD_FRAME_PROTO_UDP)
@@ -346,11 +435,15 @@ typedef struct _RxD_t {
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
u64 Control_2;
+#define THE_RXD_MARK 0x3
+#define SET_RXD_MARKER vBIT(THE_RXD_MARK, 0, 2)
+#define GET_RXD_MARKER(ctrl) ((ctrl & SET_RXD_MARKER) >> 62)
+
#ifndef CONFIG_2BUFF_MODE
-#define MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16)
-#define SET_BUFFER0_SIZE(val) vBIT(val,0,16)
+#define MASK_BUFFER0_SIZE vBIT(0x3FFF,2,14)
+#define SET_BUFFER0_SIZE(val) vBIT(val,2,14)
#else
-#define MASK_BUFFER0_SIZE vBIT(0xFF,0,16)
+#define MASK_BUFFER0_SIZE vBIT(0xFF,2,14)
#define MASK_BUFFER1_SIZE vBIT(0xFFFF,16,16)
#define MASK_BUFFER2_SIZE vBIT(0xFFFF,32,16)
#define SET_BUFFER0_SIZE(val) vBIT(val,8,8)
@@ -363,7 +456,7 @@ typedef struct _RxD_t {
#define SET_NUM_TAG(val) vBIT(val,16,32)
#ifndef CONFIG_2BUFF_MODE
-#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0xFFFF,0,16)))
+#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0x3FFF,2,14)))
#else
#define RXD_GET_BUFFER0_SIZE(Control_2) (u8)((Control_2 & MASK_BUFFER0_SIZE) \
>> 48)
@@ -382,7 +475,7 @@ typedef struct _RxD_t {
#endif
} RxD_t;
-/* Structure that represents the Rx descriptor block which contains
+/* Structure that represents the Rx descriptor block which contains
* 128 Rx descriptors.
*/
#ifndef CONFIG_2BUFF_MODE
@@ -392,11 +485,11 @@ typedef struct _RxD_block {
u64 reserved_0;
#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
- u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last
+ u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last
* Rxd in this blk */
u64 reserved_2_pNext_RxD_block; /* Logical ptr to next */
u64 pNext_RxD_Blk_physical; /* Buff0_ptr.In a 32 bit arch
- * the upper 32 bits should
+ * the upper 32 bits should
* be 0 */
} RxD_block_t;
#else
@@ -405,13 +498,13 @@ typedef struct _RxD_block {
RxD_t rxd[MAX_RXDS_PER_BLOCK];
#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
- u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
+ u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
* in this blk */
u64 pNext_RxD_Blk_physical; /* Phy ponter to next blk. */
} RxD_block_t;
#define SIZE_OF_BLOCK 4096
-/* Structure to hold virtual addresses of Buf0 and Buf1 in
+/* Structure to hold virtual addresses of Buf0 and Buf1 in
* 2buf mode. */
typedef struct bufAdd {
void *ba_0_org;
@@ -423,8 +516,8 @@ typedef struct bufAdd {
/* Structure which stores all the MAC control parameters */
-/* This structure stores the offset of the RxD in the ring
- * from which the Rx Interrupt processor can start picking
+/* This structure stores the offset of the RxD in the ring
+ * from which the Rx Interrupt processor can start picking
* up the RxDs for processing.
*/
typedef struct _rx_curr_get_info_t {
@@ -436,7 +529,7 @@ typedef struct _rx_curr_get_info_t {
typedef rx_curr_get_info_t rx_curr_put_info_t;
/* This structure stores the offset of the TxDl in the FIFO
- * from which the Tx Interrupt processor can start picking
+ * from which the Tx Interrupt processor can start picking
* up the TxDLs for send complete interrupt processing.
*/
typedef struct {
@@ -446,32 +539,99 @@ typedef struct {
typedef tx_curr_get_info_t tx_curr_put_info_t;
-/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
- * is maintained in this structure.
- */
-typedef struct mac_info {
-/* rx side stuff */
- /* Put pointer info which indictes which RxD has to be replenished
+/* Structure that holds the Phy and virt addresses of the Blocks */
+typedef struct rx_block_info {
+ RxD_t *block_virt_addr;
+ dma_addr_t block_dma_addr;
+} rx_block_info_t;
+
+/* pre declaration of the nic structure */
+typedef struct s2io_nic nic_t;
+
+/* Ring specific structure */
+typedef struct ring_info {
+ /* The ring number */
+ int ring_no;
+
+ /*
+ * Place holders for the virtual and physical addresses of
+ * all the Rx Blocks
+ */
+ rx_block_info_t rx_blocks[MAX_RX_BLOCKS_PER_RING];
+ int block_count;
+ int pkt_cnt;
+
+ /*
+ * Put pointer info which indictes which RxD has to be replenished
* with a new buffer.
*/
- rx_curr_put_info_t rx_curr_put_info[MAX_RX_RINGS];
+ rx_curr_put_info_t rx_curr_put_info;
- /* Get pointer info which indictes which is the last RxD that was
+ /*
+ * Get pointer info which indictes which is the last RxD that was
* processed by the driver.
*/
- rx_curr_get_info_t rx_curr_get_info[MAX_RX_RINGS];
+ rx_curr_get_info_t rx_curr_get_info;
- u16 rmac_pause_time;
- u16 mc_pause_threshold_q0q3;
- u16 mc_pause_threshold_q4q7;
+#ifndef CONFIG_S2IO_NAPI
+ /* Index to the absolute position of the put pointer of Rx ring */
+ int put_pos;
+#endif
+
+#ifdef CONFIG_2BUFF_MODE
+ /* Buffer Address store. */
+ buffAdd_t **ba;
+#endif
+ nic_t *nic;
+} ring_info_t;
+/* Fifo specific structure */
+typedef struct fifo_info {
+ /* FIFO number */
+ int fifo_no;
+
+ /* Maximum TxDs per TxDL */
+ int max_txds;
+
+ /* Place holder of all the TX List's Phy and Virt addresses. */
+ list_info_hold_t *list_info;
+
+ /*
+ * Current offset within the tx FIFO where driver would write
+ * new Tx frame
+ */
+ tx_curr_put_info_t tx_curr_put_info;
+
+ /*
+ * Current offset within tx FIFO from where the driver would start freeing
+ * the buffers
+ */
+ tx_curr_get_info_t tx_curr_get_info;
+
+ nic_t *nic;
+}fifo_info_t;
+
+/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
+ * is maintained in this structure.
+ */
+typedef struct mac_info {
/* tx side stuff */
/* logical pointer of start of each Tx FIFO */
TxFIFO_element_t __iomem *tx_FIFO_start[MAX_TX_FIFOS];
-/* Current offset within tx_FIFO_start, where driver would write new Tx frame*/
- tx_curr_put_info_t tx_curr_put_info[MAX_TX_FIFOS];
- tx_curr_get_info_t tx_curr_get_info[MAX_TX_FIFOS];
+ /* Fifo specific structure */
+ fifo_info_t fifos[MAX_TX_FIFOS];
+
+ /* Save virtual address of TxD page with zero DMA addr(if any) */
+ void *zerodma_virt_addr;
+
+/* rx side stuff */
+ /* Ring specific structure */
+ ring_info_t rings[MAX_RX_RINGS];
+
+ u16 rmac_pause_time;
+ u16 mc_pause_threshold_q0q3;
+ u16 mc_pause_threshold_q4q7;
void *stats_mem; /* orignal pointer to allocated mem */
dma_addr_t stats_mem_phy; /* Physical address of the stat block */
@@ -485,12 +645,6 @@ typedef struct {
int usage_cnt;
} usr_addr_t;
-/* Structure that holds the Phy and virt addresses of the Blocks */
-typedef struct rx_block_info {
- RxD_t *block_virt_addr;
- dma_addr_t block_dma_addr;
-} rx_block_info_t;
-
/* Default Tunable parameters of the NIC. */
#define DEFAULT_FIFO_LEN 4096
#define SMALL_RXD_CNT 30 * (MAX_RXDS_PER_BLOCK+1)
@@ -499,7 +653,20 @@ typedef struct rx_block_info {
#define LARGE_BLK_CNT 100
/* Structure representing one instance of the NIC */
-typedef struct s2io_nic {
+struct s2io_nic {
+#ifdef CONFIG_S2IO_NAPI
+ /*
+ * Count of packets to be processed in a given iteration, it will be indicated
+ * by the quota field of the device structure when NAPI is enabled.
+ */
+ int pkts_to_process;
+#endif
+ struct net_device *dev;
+ mac_info_t mac_control;
+ struct config_param config;
+ struct pci_dev *pdev;
+ void __iomem *bar0;
+ void __iomem *bar1;
#define MAX_MAC_SUPPORTED 16
#define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
@@ -507,33 +674,20 @@ typedef struct s2io_nic {
macaddr_t pre_mac_addr[MAX_MAC_SUPPORTED];
struct net_device_stats stats;
- void __iomem *bar0;
- void __iomem *bar1;
- struct config_param config;
- mac_info_t mac_control;
int high_dma_flag;
int device_close_flag;
int device_enabled_once;
- char name[32];
+ char name[50];
struct tasklet_struct task;
volatile unsigned long tasklet_status;
- struct timer_list timer;
- struct net_device *dev;
- struct pci_dev *pdev;
- u16 vendor_id;
- u16 device_id;
- u16 ccmd;
- u32 cbar0_1;
- u32 cbar0_2;
- u32 cbar1_1;
- u32 cbar1_2;
- u32 cirq;
- u8 cache_line;
- u32 rom_expansion;
- u16 pcix_cmd;
- u32 irq;
+ /* Timer that handles I/O errors/exceptions */
+ struct timer_list alarm_timer;
+
+ /* Space to back up the PCI config space */
+ u32 config_space[256 / sizeof(u32)];
+
atomic_t rx_bufs_left[MAX_RX_RINGS];
spinlock_t tx_lock;
@@ -558,27 +712,11 @@ typedef struct s2io_nic {
u16 tx_err_count;
u16 rx_err_count;
-#ifndef CONFIG_S2IO_NAPI
- /* Index to the absolute position of the put pointer of Rx ring. */
- int put_pos[MAX_RX_RINGS];
-#endif
-
- /*
- * Place holders for the virtual and physical addresses of
- * all the Rx Blocks
- */
- rx_block_info_t rx_blocks[MAX_RX_RINGS][MAX_RX_BLOCKS_PER_RING];
- int block_count[MAX_RX_RINGS];
- int pkt_cnt[MAX_RX_RINGS];
-
- /* Place holder of all the TX List's Phy and Virt addresses. */
- list_info_hold_t *list_info[MAX_TX_FIFOS];
-
/* Id timer, used to blink NIC to physically identify NIC. */
struct timer_list id_timer;
/* Restart timer, used to restart NIC if the device is stuck and
- * a schedule task that will set the correct Link state once the
+ * a schedule task that will set the correct Link state once the
* NIC's PHY has stabilized after a state change.
*/
#ifdef INIT_TQUEUE
@@ -589,12 +727,12 @@ typedef struct s2io_nic {
struct work_struct set_link_task;
#endif
- /* Flag that can be used to turn on or turn off the Rx checksum
+ /* Flag that can be used to turn on or turn off the Rx checksum
* offload feature.
*/
int rx_csum;
- /* after blink, the adapter must be restored with original
+ /* after blink, the adapter must be restored with original
* values.
*/
u64 adapt_ctrl_org;
@@ -604,16 +742,19 @@ typedef struct s2io_nic {
#define LINK_DOWN 1
#define LINK_UP 2
-#ifdef CONFIG_2BUFF_MODE
- /* Buffer Address store. */
- buffAdd_t **ba[MAX_RX_RINGS];
-#endif
int task_flag;
#define CARD_DOWN 1
#define CARD_UP 2
atomic_t card_state;
volatile unsigned long link_state;
-} nic_t;
+ struct vlan_group *vlgrp;
+#define XFRAME_I_DEVICE 1
+#define XFRAME_II_DEVICE 2
+ u8 device_type;
+
+ spinlock_t rx_lock;
+ atomic_t isr_cnt;
+};
#define RESET_ERROR 1;
#define CMD_ERROR 2;
@@ -622,7 +763,8 @@ typedef struct s2io_nic {
#ifndef readq
static inline u64 readq(void __iomem *addr)
{
- u64 ret = readl(addr + 4);
+ u64 ret = 0;
+ ret = readl(addr + 4);
ret <<= 32;
ret |= readl(addr);
@@ -637,10 +779,10 @@ static inline void writeq(u64 val, void __iomem *addr)
writel((u32) (val >> 32), (addr + 4));
}
-/* In 32 bit modes, some registers have to be written in a
+/* In 32 bit modes, some registers have to be written in a
* particular order to expect correct hardware operation. The
- * macro SPECIAL_REG_WRITE is used to perform such ordered
- * writes. Defines UF (Upper First) and LF (Lower First) will
+ * macro SPECIAL_REG_WRITE is used to perform such ordered
+ * writes. Defines UF (Upper First) and LF (Lower First) will
* be used to specify the required write order.
*/
#define UF 1
@@ -716,6 +858,7 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
#define PCC_FB_ECC_ERR vBIT(0xff, 16, 8) /* Interrupt to indicate
PCC_FB_ECC Error. */
+#define RXD_GET_VLAN_TAG(Control_2) (u16)(Control_2 & MASK_VLAN_TAG)
/*
* Prototype declaration.
*/
@@ -725,36 +868,30 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev);
static int init_shared_mem(struct s2io_nic *sp);
static void free_shared_mem(struct s2io_nic *sp);
static int init_nic(struct s2io_nic *nic);
-#ifndef CONFIG_S2IO_NAPI
-static void rx_intr_handler(struct s2io_nic *sp);
-#endif
-static void tx_intr_handler(struct s2io_nic *sp);
+static void rx_intr_handler(ring_info_t *ring_data);
+static void tx_intr_handler(fifo_info_t *fifo_data);
static void alarm_intr_handler(struct s2io_nic *sp);
static int s2io_starter(void);
-static void s2io_closer(void);
+void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr);
static void s2io_set_multicast(struct net_device *dev);
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no);
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
- buffAdd_t * ba);
-#endif
-static void s2io_link(nic_t * sp, int link);
-static void s2io_reset(nic_t * sp);
-#ifdef CONFIG_S2IO_NAPI
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp);
+void s2io_link(nic_t * sp, int link);
+void s2io_reset(nic_t * sp);
+#if defined(CONFIG_S2IO_NAPI)
static int s2io_poll(struct net_device *dev, int *budget);
#endif
static void s2io_init_pci(nic_t * sp);
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static void s2io_alarm_handle(unsigned long data);
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
-static int verify_xena_quiescence(u64 val64, int flag);
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(unsigned long data);
-static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t * nic);
-static int s2io_card_up(nic_t * nic);
-
+int s2io_set_swapper(nic_t * sp);
+static void s2io_card_down(nic_t *nic);
+static int s2io_card_up(nic_t *nic);
+int get_xena_rev_id(struct pci_dev *pdev);
#endif /* _S2IO_H */
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index 3ad0b6751f6f..221354eea21f 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -156,52 +156,6 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
SHAPERCB(skb)->shapelen= shaper_clocks(shaper,skb);
-#ifdef SHAPER_COMPLEX /* and broken.. */
-
- while(ptr && ptr!=(struct sk_buff *)&shaper->sendq)
- {
- if(ptr->pri<skb->pri
- && jiffies - SHAPERCB(ptr)->shapeclock < SHAPER_MAXSLIP)
- {
- struct sk_buff *tmp=ptr->prev;
-
- /*
- * It goes before us therefore we slip the length
- * of the new frame.
- */
-
- SHAPERCB(ptr)->shapeclock+=SHAPERCB(skb)->shapelen;
- SHAPERCB(ptr)->shapelatency+=SHAPERCB(skb)->shapelen;
-
- /*
- * The packet may have slipped so far back it
- * fell off.
- */
- if(SHAPERCB(ptr)->shapelatency > SHAPER_LATENCY)
- {
- skb_unlink(ptr);
- dev_kfree_skb(ptr);
- }
- ptr=tmp;
- }
- else
- break;
- }
- if(ptr==NULL || ptr==(struct sk_buff *)&shaper->sendq)
- skb_queue_head(&shaper->sendq,skb);
- else
- {
- struct sk_buff *tmp;
- /*
- * Set the packet clock out time according to the
- * frames ahead. Im sure a bit of thought could drop
- * this loop.
- */
- for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=ptr; tmp=tmp->next)
- SHAPERCB(skb)->shapeclock+=tmp->shapelen;
- skb_append(ptr,skb);
- }
-#else
{
struct sk_buff *tmp;
/*
@@ -220,7 +174,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
} else
skb_queue_tail(&shaper->sendq, skb);
}
-#endif
+
if(sh_debug)
printk("Frame queued.\n");
if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN)
@@ -302,7 +256,7 @@ static void shaper_kick(struct shaper *shaper)
* Pull the frame and get interrupts back on.
*/
- skb_unlink(skb);
+ skb_unlink(skb, &shaper->sendq);
if (shaper->recovery <
SHAPERCB(skb)->shapeclock + SHAPERCB(skb)->shapelen)
shaper->recovery = SHAPERCB(skb)->shapeclock + SHAPERCB(skb)->shapelen;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
new file mode 100644
index 000000000000..92f75529eff8
--- /dev/null
+++ b/drivers/net/sis190.c
@@ -0,0 +1,1884 @@
+/*
+ sis190.c: Silicon Integrated Systems SiS190 ethernet driver
+
+ Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
+ Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
+ Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
+
+ Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
+ genuine driver.
+
+ This software may be used and distributed according to the terms of
+ the GNU General Public License (GPL), incorporated herein by reference.
+ Drivers based on or derived from this code fall under the GPL and must
+ retain the authorship, copyright and license notice. This file is not
+ a complete program and may only be used when the entire operating
+ system is licensed under the GPL.
+
+ See the file COPYING in this distribution for more information.
+
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/mii.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <asm/irq.h>
+
+#define net_drv(p, arg...) if (netif_msg_drv(p)) \
+ printk(arg)
+#define net_probe(p, arg...) if (netif_msg_probe(p)) \
+ printk(arg)
+#define net_link(p, arg...) if (netif_msg_link(p)) \
+ printk(arg)
+#define net_intr(p, arg...) if (netif_msg_intr(p)) \
+ printk(arg)
+#define net_tx_err(p, arg...) if (netif_msg_tx_err(p)) \
+ printk(arg)
+
+#define PHY_MAX_ADDR 32
+#define PHY_ID_ANY 0x1f
+#define MII_REG_ANY 0x1f
+
+#ifdef CONFIG_SIS190_NAPI
+#define NAPI_SUFFIX "-NAPI"
+#else
+#define NAPI_SUFFIX ""
+#endif
+
+#define DRV_VERSION "1.2" NAPI_SUFFIX
+#define DRV_NAME "sis190"
+#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
+#define PFX DRV_NAME ": "
+
+#ifdef CONFIG_SIS190_NAPI
+#define sis190_rx_skb netif_receive_skb
+#define sis190_rx_quota(count, quota) min(count, quota)
+#else
+#define sis190_rx_skb netif_rx
+#define sis190_rx_quota(count, quota) count
+#endif
+
+#define MAC_ADDR_LEN 6
+
+#define NUM_TX_DESC 64 /* [8..1024] */
+#define NUM_RX_DESC 64 /* [8..8192] */
+#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
+#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
+#define RX_BUF_SIZE 1536
+#define RX_BUF_MASK 0xfff8
+
+#define SIS190_REGS_SIZE 0x80
+#define SIS190_TX_TIMEOUT (6*HZ)
+#define SIS190_PHY_TIMEOUT (10*HZ)
+#define SIS190_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+ NETIF_MSG_IFDOWN)
+
+/* Enhanced PHY access register bit definitions */
+#define EhnMIIread 0x0000
+#define EhnMIIwrite 0x0020
+#define EhnMIIdataShift 16
+#define EhnMIIpmdShift 6 /* 7016 only */
+#define EhnMIIregShift 11
+#define EhnMIIreq 0x0010
+#define EhnMIInotDone 0x0010
+
+/* Write/read MMIO register */
+#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
+#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
+#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
+#define SIS_R8(reg) readb (ioaddr + (reg))
+#define SIS_R16(reg) readw (ioaddr + (reg))
+#define SIS_R32(reg) readl (ioaddr + (reg))
+
+#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
+
+enum sis190_registers {
+ TxControl = 0x00,
+ TxDescStartAddr = 0x04,
+ rsv0 = 0x08, // reserved
+ TxSts = 0x0c, // unused (Control/Status)
+ RxControl = 0x10,
+ RxDescStartAddr = 0x14,
+ rsv1 = 0x18, // reserved
+ RxSts = 0x1c, // unused
+ IntrStatus = 0x20,
+ IntrMask = 0x24,
+ IntrControl = 0x28,
+ IntrTimer = 0x2c, // unused (Interupt Timer)
+ PMControl = 0x30, // unused (Power Mgmt Control/Status)
+ rsv2 = 0x34, // reserved
+ ROMControl = 0x38,
+ ROMInterface = 0x3c,
+ StationControl = 0x40,
+ GMIIControl = 0x44,
+ GIoCR = 0x48, // unused (GMAC IO Compensation)
+ GIoCtrl = 0x4c, // unused (GMAC IO Control)
+ TxMacControl = 0x50,
+ TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
+ RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
+ rsv3 = 0x5c, // reserved
+ RxMacControl = 0x60,
+ RxMacAddr = 0x62,
+ RxHashTable = 0x68,
+ // Undocumented = 0x6c,
+ RxWolCtrl = 0x70,
+ RxWolData = 0x74, // unused (Rx WOL Data Access)
+ RxMPSControl = 0x78, // unused (Rx MPS Control)
+ rsv4 = 0x7c, // reserved
+};
+
+enum sis190_register_content {
+ /* IntrStatus */
+ SoftInt = 0x40000000, // unused
+ Timeup = 0x20000000, // unused
+ PauseFrame = 0x00080000, // unused
+ MagicPacket = 0x00040000, // unused
+ WakeupFrame = 0x00020000, // unused
+ LinkChange = 0x00010000,
+ RxQEmpty = 0x00000080,
+ RxQInt = 0x00000040,
+ TxQ1Empty = 0x00000020, // unused
+ TxQ1Int = 0x00000010,
+ TxQ0Empty = 0x00000008, // unused
+ TxQ0Int = 0x00000004,
+ RxHalt = 0x00000002,
+ TxHalt = 0x00000001,
+
+ /* {Rx/Tx}CmdBits */
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08, // unused
+ CmdTxEnb = 0x01,
+ RxBufEmpty = 0x01, // unused
+
+ /* Cfg9346Bits */
+ Cfg9346_Lock = 0x00, // unused
+ Cfg9346_Unlock = 0xc0, // unused
+
+ /* RxMacControl */
+ AcceptErr = 0x20, // unused
+ AcceptRunt = 0x10, // unused
+ AcceptBroadcast = 0x0800,
+ AcceptMulticast = 0x0400,
+ AcceptMyPhys = 0x0200,
+ AcceptAllPhys = 0x0100,
+
+ /* RxConfigBits */
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8, // 0x1a in RxControl ?
+
+ /* TxConfigBits */
+ TxInterFrameGapShift = 24,
+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+
+ LinkStatus = 0x02, // unused
+ FullDup = 0x01, // unused
+
+ /* TBICSRBit */
+ TBILinkOK = 0x02000000, // unused
+};
+
+struct TxDesc {
+ __le32 PSize;
+ __le32 status;
+ __le32 addr;
+ __le32 size;
+};
+
+struct RxDesc {
+ __le32 PSize;
+ __le32 status;
+ __le32 addr;
+ __le32 size;
+};
+
+enum _DescStatusBit {
+ /* _Desc.status */
+ OWNbit = 0x80000000, // RXOWN/TXOWN
+ INTbit = 0x40000000, // RXINT/TXINT
+ CRCbit = 0x00020000, // CRCOFF/CRCEN
+ PADbit = 0x00010000, // PREADD/PADEN
+ /* _Desc.size */
+ RingEnd = 0x80000000,
+ /* TxDesc.status */
+ LSEN = 0x08000000, // TSO ? -- FR
+ IPCS = 0x04000000,
+ TCPCS = 0x02000000,
+ UDPCS = 0x01000000,
+ BSTEN = 0x00800000,
+ EXTEN = 0x00400000,
+ DEFEN = 0x00200000,
+ BKFEN = 0x00100000,
+ CRSEN = 0x00080000,
+ COLEN = 0x00040000,
+ THOL3 = 0x30000000,
+ THOL2 = 0x20000000,
+ THOL1 = 0x10000000,
+ THOL0 = 0x00000000,
+ /* RxDesc.status */
+ IPON = 0x20000000,
+ TCPON = 0x10000000,
+ UDPON = 0x08000000,
+ Wakup = 0x00400000,
+ Magic = 0x00200000,
+ Pause = 0x00100000,
+ DEFbit = 0x00200000,
+ BCAST = 0x000c0000,
+ MCAST = 0x00080000,
+ UCAST = 0x00040000,
+ /* RxDesc.PSize */
+ TAGON = 0x80000000,
+ RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
+ ABORT = 0x00800000,
+ SHORT = 0x00400000,
+ LIMIT = 0x00200000,
+ MIIER = 0x00100000,
+ OVRUN = 0x00080000,
+ NIBON = 0x00040000,
+ COLON = 0x00020000,
+ CRCOK = 0x00010000,
+ RxSizeMask = 0x0000ffff
+ /*
+ * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
+ * provide two (unused with Linux) Tx queues. No publically
+ * available documentation alas.
+ */
+};
+
+enum sis190_eeprom_access_register_bits {
+ EECS = 0x00000001, // unused
+ EECLK = 0x00000002, // unused
+ EEDO = 0x00000008, // unused
+ EEDI = 0x00000004, // unused
+ EEREQ = 0x00000080,
+ EEROP = 0x00000200,
+ EEWOP = 0x00000100 // unused
+};
+
+/* EEPROM Addresses */
+enum sis190_eeprom_address {
+ EEPROMSignature = 0x00,
+ EEPROMCLK = 0x01, // unused
+ EEPROMInfo = 0x02,
+ EEPROMMACAddr = 0x03
+};
+
+enum sis190_feature {
+ F_HAS_RGMII = 1,
+ F_PHY_88E1111 = 2,
+ F_PHY_BCM5461 = 4
+};
+
+struct sis190_private {
+ void __iomem *mmio_addr;
+ struct pci_dev *pci_dev;
+ struct net_device_stats stats;
+ spinlock_t lock;
+ u32 rx_buf_sz;
+ u32 cur_rx;
+ u32 cur_tx;
+ u32 dirty_rx;
+ u32 dirty_tx;
+ dma_addr_t rx_dma;
+ dma_addr_t tx_dma;
+ struct RxDesc *RxDescRing;
+ struct TxDesc *TxDescRing;
+ struct sk_buff *Rx_skbuff[NUM_RX_DESC];
+ struct sk_buff *Tx_skbuff[NUM_TX_DESC];
+ struct work_struct phy_task;
+ struct timer_list timer;
+ u32 msg_enable;
+ struct mii_if_info mii_if;
+ struct list_head first_phy;
+ u32 features;
+};
+
+struct sis190_phy {
+ struct list_head list;
+ int phy_id;
+ u16 id[2];
+ u16 status;
+ u8 type;
+};
+
+enum sis190_phy_type {
+ UNKNOWN = 0x00,
+ HOME = 0x01,
+ LAN = 0x02,
+ MIX = 0x03
+};
+
+static struct mii_chip_info {
+ const char *name;
+ u16 id[2];
+ unsigned int type;
+ u32 feature;
+} mii_chip_table[] = {
+ { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+ { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
+ { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
+ { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
+ { NULL, }
+};
+
+const static struct {
+ const char *name;
+} sis_chip_info[] = {
+ { "SiS 190 PCI Fast Ethernet adapter" },
+ { "SiS 191 PCI Gigabit Ethernet adapter" },
+};
+
+static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, sis190_pci_tbl);
+
+static int rx_copybreak = 200;
+
+static struct {
+ u32 msg_enable;
+} debug = { -1 };
+
+MODULE_DESCRIPTION("SiS sis190 Gigabit Ethernet driver");
+module_param(rx_copybreak, int, 0);
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+module_param_named(debug, debug.msg_enable, int, 0);
+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>, Ueimor <romieu@fr.zoreil.com>");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
+static const u32 sis190_intr_mask =
+ RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
+
+/*
+ * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+ * The chips use a 64 element hash table based on the Ethernet CRC.
+ */
+static int multicast_filter_limit = 32;
+
+static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
+{
+ unsigned int i;
+
+ SIS_W32(GMIIControl, ctl);
+
+ msleep(1);
+
+ for (i = 0; i < 100; i++) {
+ if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
+ break;
+ msleep(1);
+ }
+
+ if (i > 999)
+ printk(KERN_ERR PFX "PHY command failed !\n");
+}
+
+static void mdio_write(void __iomem *ioaddr, int phy_id, int reg, int val)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
+ (((u32) val) << EhnMIIdataShift));
+}
+
+static int mdio_read(void __iomem *ioaddr, int phy_id, int reg)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
+
+ return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
+}
+
+static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ mdio_write(tp->mmio_addr, phy_id, reg, val);
+}
+
+static int __mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mdio_read(tp->mmio_addr, phy_id, reg);
+}
+
+static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
+{
+ mdio_read(ioaddr, phy_id, reg);
+ return mdio_read(ioaddr, phy_id, reg);
+}
+
+static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
+{
+ u16 data = 0xffff;
+ unsigned int i;
+
+ if (!(SIS_R32(ROMControl) & 0x0002))
+ return 0;
+
+ SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
+
+ for (i = 0; i < 200; i++) {
+ if (!(SIS_R32(ROMInterface) & EEREQ)) {
+ data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
+ break;
+ }
+ msleep(1);
+ }
+
+ return data;
+}
+
+static void sis190_irq_mask_and_ack(void __iomem *ioaddr)
+{
+ SIS_W32(IntrMask, 0x00);
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_PCI_COMMIT();
+}
+
+static void sis190_asic_down(void __iomem *ioaddr)
+{
+ /* Stop the chip's Tx and Rx DMA processes. */
+
+ SIS_W32(TxControl, 0x1a00);
+ SIS_W32(RxControl, 0x1a00);
+
+ sis190_irq_mask_and_ack(ioaddr);
+}
+
+static void sis190_mark_as_last_descriptor(struct RxDesc *desc)
+{
+ desc->size |= cpu_to_le32(RingEnd);
+}
+
+static inline void sis190_give_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
+{
+ u32 eor = le32_to_cpu(desc->size) & RingEnd;
+
+ desc->PSize = 0x0;
+ desc->size = cpu_to_le32((rx_buf_sz & RX_BUF_MASK) | eor);
+ wmb();
+ desc->status = cpu_to_le32(OWNbit | INTbit);
+}
+
+static inline void sis190_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
+ u32 rx_buf_sz)
+{
+ desc->addr = cpu_to_le32(mapping);
+ sis190_give_to_asic(desc, rx_buf_sz);
+}
+
+static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
+{
+ desc->PSize = 0x0;
+ desc->addr = 0xdeadbeef;
+ desc->size &= cpu_to_le32(RingEnd);
+ wmb();
+ desc->status = 0x0;
+}
+
+static int sis190_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+ struct RxDesc *desc, u32 rx_buf_sz)
+{
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ int ret = 0;
+
+ skb = dev_alloc_skb(rx_buf_sz);
+ if (!skb)
+ goto err_out;
+
+ *sk_buff = skb;
+
+ mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+
+ sis190_map_to_asic(desc, mapping, rx_buf_sz);
+out:
+ return ret;
+
+err_out:
+ ret = -ENOMEM;
+ sis190_make_unusable_by_asic(desc);
+ goto out;
+}
+
+static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
+ u32 start, u32 end)
+{
+ u32 cur;
+
+ for (cur = start; cur < end; cur++) {
+ int ret, i = cur % NUM_RX_DESC;
+
+ if (tp->Rx_skbuff[i])
+ continue;
+
+ ret = sis190_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+ tp->RxDescRing + i, tp->rx_buf_sz);
+ if (ret < 0)
+ break;
+ }
+ return cur - start;
+}
+
+static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+ struct RxDesc *desc, int rx_buf_sz)
+{
+ int ret = -1;
+
+ if (pkt_size < rx_copybreak) {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
+ if (skb) {
+ skb_reserve(skb, NET_IP_ALIGN);
+ eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+ *sk_buff = skb;
+ sis190_give_to_asic(desc, rx_buf_sz);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
+{
+#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
+
+ if ((status & CRCOK) && !(status & ErrMask))
+ return 0;
+
+ if (!(status & CRCOK))
+ stats->rx_crc_errors++;
+ else if (status & OVRUN)
+ stats->rx_over_errors++;
+ else if (status & (SHORT | LIMIT))
+ stats->rx_length_errors++;
+ else if (status & (MIIER | NIBON | COLON))
+ stats->rx_frame_errors++;
+
+ stats->rx_errors++;
+ return -1;
+}
+
+static int sis190_rx_interrupt(struct net_device *dev,
+ struct sis190_private *tp, void __iomem *ioaddr)
+{
+ struct net_device_stats *stats = &tp->stats;
+ u32 rx_left, cur_rx = tp->cur_rx;
+ u32 delta, count;
+
+ rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+ rx_left = sis190_rx_quota(rx_left, (u32) dev->quota);
+
+ for (; rx_left > 0; rx_left--, cur_rx++) {
+ unsigned int entry = cur_rx % NUM_RX_DESC;
+ struct RxDesc *desc = tp->RxDescRing + entry;
+ u32 status;
+
+ if (desc->status & OWNbit)
+ break;
+
+ status = le32_to_cpu(desc->PSize);
+
+ // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name,
+ // status);
+
+ if (sis190_rx_pkt_err(status, stats) < 0)
+ sis190_give_to_asic(desc, tp->rx_buf_sz);
+ else {
+ struct sk_buff *skb = tp->Rx_skbuff[entry];
+ int pkt_size = (status & RxSizeMask) - 4;
+ void (*pci_action)(struct pci_dev *, dma_addr_t,
+ size_t, int) = pci_dma_sync_single_for_device;
+
+ if (unlikely(pkt_size > tp->rx_buf_sz)) {
+ net_intr(tp, KERN_INFO
+ "%s: (frag) status = %08x.\n",
+ dev->name, status);
+ stats->rx_dropped++;
+ stats->rx_length_errors++;
+ sis190_give_to_asic(desc, tp->rx_buf_sz);
+ continue;
+ }
+
+ pci_dma_sync_single_for_cpu(tp->pci_dev,
+ le32_to_cpu(desc->addr), tp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+
+ if (sis190_try_rx_copy(&skb, pkt_size, desc,
+ tp->rx_buf_sz)) {
+ pci_action = pci_unmap_single;
+ tp->Rx_skbuff[entry] = NULL;
+ sis190_make_unusable_by_asic(desc);
+ }
+
+ pci_action(tp->pci_dev, le32_to_cpu(desc->addr),
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+
+ skb->dev = dev;
+ skb_put(skb, pkt_size);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ sis190_rx_skb(skb);
+
+ dev->last_rx = jiffies;
+ stats->rx_packets++;
+ stats->rx_bytes += pkt_size;
+ if ((status & BCAST) == MCAST)
+ stats->multicast++;
+ }
+ }
+ count = cur_rx - tp->cur_rx;
+ tp->cur_rx = cur_rx;
+
+ delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+ if (!delta && count && netif_msg_intr(tp))
+ printk(KERN_INFO "%s: no Rx buffer allocated.\n", dev->name);
+ tp->dirty_rx += delta;
+
+ if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx) && netif_msg_intr(tp))
+ printk(KERN_EMERG "%s: Rx buffers exhausted.\n", dev->name);
+
+ return count;
+}
+
+static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+ struct TxDesc *desc)
+{
+ unsigned int len;
+
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+ pci_unmap_single(pdev, le32_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+
+ memset(desc, 0x00, sizeof(*desc));
+}
+
+static void sis190_tx_interrupt(struct net_device *dev,
+ struct sis190_private *tp, void __iomem *ioaddr)
+{
+ u32 pending, dirty_tx = tp->dirty_tx;
+ /*
+ * It would not be needed if queueing was allowed to be enabled
+ * again too early (hint: think preempt and unclocked smp systems).
+ */
+ unsigned int queue_stopped;
+
+ smp_rmb();
+ pending = tp->cur_tx - dirty_tx;
+ queue_stopped = (pending == NUM_TX_DESC);
+
+ for (; pending; pending--, dirty_tx++) {
+ unsigned int entry = dirty_tx % NUM_TX_DESC;
+ struct TxDesc *txd = tp->TxDescRing + entry;
+ struct sk_buff *skb;
+
+ if (le32_to_cpu(txd->status) & OWNbit)
+ break;
+
+ skb = tp->Tx_skbuff[entry];
+
+ tp->stats.tx_packets++;
+ tp->stats.tx_bytes += skb->len;
+
+ sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
+ tp->Tx_skbuff[entry] = NULL;
+ dev_kfree_skb_irq(skb);
+ }
+
+ if (tp->dirty_tx != dirty_tx) {
+ tp->dirty_tx = dirty_tx;
+ smp_wmb();
+ if (queue_stopped)
+ netif_wake_queue(dev);
+ }
+}
+
+/*
+ * The interrupt handler does all of the Rx thread work and cleans up after
+ * the Tx thread.
+ */
+static irqreturn_t sis190_interrupt(int irq, void *__dev, struct pt_regs *regs)
+{
+ struct net_device *dev = __dev;
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned int handled = 0;
+ u32 status;
+
+ status = SIS_R32(IntrStatus);
+
+ if ((status == 0xffffffff) || !status)
+ goto out;
+
+ handled = 1;
+
+ if (unlikely(!netif_running(dev))) {
+ sis190_asic_down(ioaddr);
+ goto out;
+ }
+
+ SIS_W32(IntrStatus, status);
+
+ // net_intr(tp, KERN_INFO "%s: status = %08x.\n", dev->name, status);
+
+ if (status & LinkChange) {
+ net_intr(tp, KERN_INFO "%s: link change.\n", dev->name);
+ schedule_work(&tp->phy_task);
+ }
+
+ if (status & RxQInt)
+ sis190_rx_interrupt(dev, tp, ioaddr);
+
+ if (status & TxQ0Int)
+ sis190_tx_interrupt(dev, tp, ioaddr);
+out:
+ return IRQ_RETVAL(handled);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void sis190_netpoll(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+
+ disable_irq(pdev->irq);
+ sis190_interrupt(pdev->irq, dev, NULL);
+ enable_irq(pdev->irq);
+}
+#endif
+
+static void sis190_free_rx_skb(struct sis190_private *tp,
+ struct sk_buff **sk_buff, struct RxDesc *desc)
+{
+ struct pci_dev *pdev = tp->pci_dev;
+
+ pci_unmap_single(pdev, le32_to_cpu(desc->addr), tp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(*sk_buff);
+ *sk_buff = NULL;
+ sis190_make_unusable_by_asic(desc);
+}
+
+static void sis190_rx_clear(struct sis190_private *tp)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ if (!tp->Rx_skbuff[i])
+ continue;
+ sis190_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescRing + i);
+ }
+}
+
+static void sis190_init_ring_indexes(struct sis190_private *tp)
+{
+ tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
+}
+
+static int sis190_init_ring(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_init_ring_indexes(tp);
+
+ memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+ memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
+
+ if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+ goto err_rx_clear;
+
+ sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
+
+ return 0;
+
+err_rx_clear:
+ sis190_rx_clear(tp);
+ return -ENOMEM;
+}
+
+static void sis190_set_rx_mode(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned long flags;
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u16 rx_mode;
+
+ if (dev->flags & IFF_PROMISC) {
+ /* Unconditionally log net taps. */
+ net_drv(tp, KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+ dev->name);
+ rx_mode =
+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+ AcceptAllPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else if ((dev->mc_count > multicast_filter_limit) ||
+ (dev->flags & IFF_ALLMULTI)) {
+ /* Too many to filter perfectly -- accept all multicasts. */
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else {
+ struct dev_mc_list *mclist;
+ unsigned int i;
+
+ rx_mode = AcceptBroadcast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0;
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next) {
+ int bit_nr =
+ ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+ rx_mode |= AcceptMulticast;
+ }
+ }
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ SIS_W16(RxMacControl, rx_mode | 0x2);
+ SIS_W32(RxHashTable, mc_filter[0]);
+ SIS_W32(RxHashTable + 4, mc_filter[1]);
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static void sis190_soft_reset(void __iomem *ioaddr)
+{
+ SIS_W32(IntrControl, 0x8000);
+ SIS_PCI_COMMIT();
+ msleep(1);
+ SIS_W32(IntrControl, 0x0);
+ sis190_asic_down(ioaddr);
+ msleep(1);
+}
+
+static void sis190_hw_start(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ sis190_soft_reset(ioaddr);
+
+ SIS_W32(TxDescStartAddr, tp->tx_dma);
+ SIS_W32(RxDescStartAddr, tp->rx_dma);
+
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_W32(IntrMask, 0x0);
+ SIS_W32(GMIIControl, 0x0);
+ SIS_W32(TxMacControl, 0x60);
+ SIS_W16(RxMacControl, 0x02);
+ SIS_W32(RxHashTable, 0x0);
+ SIS_W32(0x6c, 0x0);
+ SIS_W32(RxWolCtrl, 0x0);
+ SIS_W32(RxWolData, 0x0);
+
+ SIS_PCI_COMMIT();
+
+ sis190_set_rx_mode(dev);
+
+ /* Enable all known interrupts by setting the interrupt mask. */
+ SIS_W32(IntrMask, sis190_intr_mask);
+
+ SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
+ SIS_W32(RxControl, 0x1a1d);
+
+ netif_start_queue(dev);
+}
+
+static void sis190_phy_task(void * data)
+{
+ struct net_device *dev = data;
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 val;
+
+ rtnl_lock();
+
+ val = mdio_read(ioaddr, phy_id, MII_BMCR);
+ if (val & BMCR_RESET) {
+ // FIXME: needlessly high ? -- FR 02/07/2005
+ mod_timer(&tp->timer, jiffies + HZ/10);
+ } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
+ BMSR_ANEGCOMPLETE)) {
+ net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
+ dev->name);
+ netif_carrier_off(dev);
+ mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
+ mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
+ } else {
+ /* Rejoice ! */
+ struct {
+ int val;
+ u32 ctl;
+ const char *msg;
+ } reg31[] = {
+ { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
+ "1000 Mbps Full Duplex" },
+ { LPA_1000XHALF | LPA_SLCT, 0x07000c00,
+ "1000 Mbps Half Duplex" },
+ { LPA_100FULL, 0x04000800 | 0x00001000,
+ "100 Mbps Full Duplex" },
+ { LPA_100HALF, 0x04000800,
+ "100 Mbps Half Duplex" },
+ { LPA_10FULL, 0x04000400 | 0x00001000,
+ "10 Mbps Full Duplex" },
+ { LPA_10HALF, 0x04000400,
+ "10 Mbps Half Duplex" },
+ { 0, 0x04000400, "unknown" }
+ }, *p;
+ u16 adv;
+
+ val = mdio_read(ioaddr, phy_id, 0x1f);
+ net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val);
+
+ val = mdio_read(ioaddr, phy_id, MII_LPA);
+ adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+ net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n",
+ dev->name, val, adv);
+
+ val &= adv;
+
+ for (p = reg31; p->val; p++) {
+ if ((val & p->val) == p->val)
+ break;
+ }
+
+ p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
+
+ if ((tp->features & F_HAS_RGMII) &&
+ (tp->features & F_PHY_BCM5461)) {
+ // Set Tx Delay in RGMII mode.
+ mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+ p->ctl |= 0x03000000;
+ }
+
+ SIS_W32(StationControl, p->ctl);
+
+ if (tp->features & F_HAS_RGMII) {
+ SIS_W32(RGDelay, 0x0441);
+ SIS_W32(RGDelay, 0x0440);
+ }
+
+ net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
+ p->msg);
+ netif_carrier_on(dev);
+ }
+
+ rtnl_unlock();
+}
+
+static void sis190_phy_timer(unsigned long __opaque)
+{
+ struct net_device *dev = (struct net_device *)__opaque;
+ struct sis190_private *tp = netdev_priv(dev);
+
+ if (likely(netif_running(dev)))
+ schedule_work(&tp->phy_task);
+}
+
+static inline void sis190_delete_timer(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ del_timer_sync(&tp->timer);
+}
+
+static inline void sis190_request_timer(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct timer_list *timer = &tp->timer;
+
+ init_timer(timer);
+ timer->expires = jiffies + SIS190_PHY_TIMEOUT;
+ timer->data = (unsigned long)dev;
+ timer->function = sis190_phy_timer;
+ add_timer(timer);
+}
+
+static void sis190_set_rxbufsize(struct sis190_private *tp,
+ struct net_device *dev)
+{
+ unsigned int mtu = dev->mtu;
+
+ tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
+ /* RxDesc->size has a licence to kill the lower bits */
+ if (tp->rx_buf_sz & 0x07) {
+ tp->rx_buf_sz += 8;
+ tp->rx_buf_sz &= RX_BUF_MASK;
+ }
+}
+
+static int sis190_open(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+ int rc = -ENOMEM;
+
+ sis190_set_rxbufsize(tp, dev);
+
+ /*
+ * Rx and Tx descriptors need 256 bytes alignment.
+ * pci_alloc_consistent() guarantees a stronger alignment.
+ */
+ tp->TxDescRing = pci_alloc_consistent(pdev, TX_RING_BYTES, &tp->tx_dma);
+ if (!tp->TxDescRing)
+ goto out;
+
+ tp->RxDescRing = pci_alloc_consistent(pdev, RX_RING_BYTES, &tp->rx_dma);
+ if (!tp->RxDescRing)
+ goto err_free_tx_0;
+
+ rc = sis190_init_ring(dev);
+ if (rc < 0)
+ goto err_free_rx_1;
+
+ INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+
+ sis190_request_timer(dev);
+
+ rc = request_irq(dev->irq, sis190_interrupt, SA_SHIRQ, dev->name, dev);
+ if (rc < 0)
+ goto err_release_timer_2;
+
+ sis190_hw_start(dev);
+out:
+ return rc;
+
+err_release_timer_2:
+ sis190_delete_timer(dev);
+ sis190_rx_clear(tp);
+err_free_rx_1:
+ pci_free_consistent(tp->pci_dev, RX_RING_BYTES, tp->RxDescRing,
+ tp->rx_dma);
+err_free_tx_0:
+ pci_free_consistent(tp->pci_dev, TX_RING_BYTES, tp->TxDescRing,
+ tp->tx_dma);
+ goto out;
+}
+
+static void sis190_tx_clear(struct sis190_private *tp)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_TX_DESC; i++) {
+ struct sk_buff *skb = tp->Tx_skbuff[i];
+
+ if (!skb)
+ continue;
+
+ sis190_unmap_tx_skb(tp->pci_dev, skb, tp->TxDescRing + i);
+ tp->Tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+
+ tp->stats.tx_dropped++;
+ }
+ tp->cur_tx = tp->dirty_tx = 0;
+}
+
+static void sis190_down(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned int poll_locked = 0;
+
+ sis190_delete_timer(dev);
+
+ netif_stop_queue(dev);
+
+ flush_scheduled_work();
+
+ do {
+ spin_lock_irq(&tp->lock);
+
+ sis190_asic_down(ioaddr);
+
+ spin_unlock_irq(&tp->lock);
+
+ synchronize_irq(dev->irq);
+
+ if (!poll_locked) {
+ netif_poll_disable(dev);
+ poll_locked++;
+ }
+
+ synchronize_sched();
+
+ } while (SIS_R32(IntrMask));
+
+ sis190_tx_clear(tp);
+ sis190_rx_clear(tp);
+}
+
+static int sis190_close(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+
+ sis190_down(dev);
+
+ free_irq(dev->irq, dev);
+
+ netif_poll_enable(dev);
+
+ pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
+ pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
+
+ tp->TxDescRing = NULL;
+ tp->RxDescRing = NULL;
+
+ return 0;
+}
+
+static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u32 len, entry, dirty_tx;
+ struct TxDesc *desc;
+ dma_addr_t mapping;
+
+ if (unlikely(skb->len < ETH_ZLEN)) {
+ skb = skb_padto(skb, ETH_ZLEN);
+ if (!skb) {
+ tp->stats.tx_dropped++;
+ goto out;
+ }
+ len = ETH_ZLEN;
+ } else {
+ len = skb->len;
+ }
+
+ entry = tp->cur_tx % NUM_TX_DESC;
+ desc = tp->TxDescRing + entry;
+
+ if (unlikely(le32_to_cpu(desc->status) & OWNbit)) {
+ netif_stop_queue(dev);
+ net_tx_err(tp, KERN_ERR PFX
+ "%s: BUG! Tx Ring full when queue awake!\n",
+ dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
+
+ tp->Tx_skbuff[entry] = skb;
+
+ desc->PSize = cpu_to_le32(len);
+ desc->addr = cpu_to_le32(mapping);
+
+ desc->size = cpu_to_le32(len);
+ if (entry == (NUM_TX_DESC - 1))
+ desc->size |= cpu_to_le32(RingEnd);
+
+ wmb();
+
+ desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
+
+ tp->cur_tx++;
+
+ smp_wmb();
+
+ SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
+
+ dev->trans_start = jiffies;
+
+ dirty_tx = tp->dirty_tx;
+ if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
+ netif_stop_queue(dev);
+ smp_rmb();
+ if (dirty_tx != tp->dirty_tx)
+ netif_wake_queue(dev);
+ }
+out:
+ return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *sis190_get_stats(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return &tp->stats;
+}
+
+static void sis190_free_phy(struct list_head *first_phy)
+{
+ struct sis190_phy *cur, *next;
+
+ list_for_each_entry_safe(cur, next, first_phy, list) {
+ kfree(cur);
+ }
+}
+
+/**
+ * sis190_default_phy - Select default PHY for sis190 mac.
+ * @dev: the net device to probe for
+ *
+ * Select first detected PHY with link as default.
+ * If no one is link on, select PHY whose types is HOME as default.
+ * If HOME doesn't exist, select LAN.
+ */
+static u16 sis190_default_phy(struct net_device *dev)
+{
+ struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
+ struct sis190_private *tp = netdev_priv(dev);
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 status;
+
+ phy_home = phy_default = phy_lan = NULL;
+
+ list_for_each_entry(phy, &tp->first_phy, list) {
+ status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
+
+ // Link ON & Not select default PHY & not ghost PHY.
+ if ((status & BMSR_LSTATUS) &&
+ !phy_default &&
+ (phy->type != UNKNOWN)) {
+ phy_default = phy;
+ } else {
+ status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
+ mdio_write(ioaddr, phy->phy_id, MII_BMCR,
+ status | BMCR_ANENABLE | BMCR_ISOLATE);
+ if (phy->type == HOME)
+ phy_home = phy;
+ else if (phy->type == LAN)
+ phy_lan = phy;
+ }
+ }
+
+ if (!phy_default) {
+ if (phy_home)
+ phy_default = phy_home;
+ else if (phy_lan)
+ phy_default = phy_lan;
+ else
+ phy_default = list_entry(&tp->first_phy,
+ struct sis190_phy, list);
+ }
+
+ if (mii_if->phy_id != phy_default->phy_id) {
+ mii_if->phy_id = phy_default->phy_id;
+ net_probe(tp, KERN_INFO
+ "%s: Using transceiver at address %d as default.\n",
+ pci_name(tp->pci_dev), mii_if->phy_id);
+ }
+
+ status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
+ status &= (~BMCR_ISOLATE);
+
+ mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
+ status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
+
+ return status;
+}
+
+static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp,
+ struct sis190_phy *phy, unsigned int phy_id,
+ u16 mii_status)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct mii_chip_info *p;
+
+ INIT_LIST_HEAD(&phy->list);
+ phy->status = mii_status;
+ phy->phy_id = phy_id;
+
+ phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
+ phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
+
+ for (p = mii_chip_table; p->type; p++) {
+ if ((p->id[0] == phy->id[0]) &&
+ (p->id[1] == (phy->id[1] & 0xfff0))) {
+ break;
+ }
+ }
+
+ if (p->id[1]) {
+ phy->type = (p->type == MIX) ?
+ ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
+ LAN : HOME) : p->type;
+ tp->features |= p->feature;
+ } else
+ phy->type = UNKNOWN;
+
+ net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
+ pci_name(tp->pci_dev),
+ (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
+}
+
+static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+{
+ if (tp->features & F_PHY_88E1111) {
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 reg[2][2] = {
+ { 0x808b, 0x0ce1 },
+ { 0x808f, 0x0c60 }
+ }, *p;
+
+ p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
+
+ mdio_write(ioaddr, phy_id, 0x1b, p[0]);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x14, p[1]);
+ udelay(200);
+ }
+}
+
+/**
+ * sis190_mii_probe - Probe MII PHY for sis190
+ * @dev: the net device to probe for
+ *
+ * Search for total of 32 possible mii phy addresses.
+ * Identify and set current phy if found one,
+ * return error if it failed to found.
+ */
+static int __devinit sis190_mii_probe(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id;
+ int rc = 0;
+
+ INIT_LIST_HEAD(&tp->first_phy);
+
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ struct sis190_phy *phy;
+ u16 status;
+
+ status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
+
+ // Try next mii if the current one is not accessible.
+ if (status == 0xffff || status == 0x0000)
+ continue;
+
+ phy = kmalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy) {
+ sis190_free_phy(&tp->first_phy);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ sis190_init_phy(dev, tp, phy, phy_id, status);
+
+ list_add(&tp->first_phy, &phy->list);
+ }
+
+ if (list_empty(&tp->first_phy)) {
+ net_probe(tp, KERN_INFO "%s: No MII transceivers found!\n",
+ pci_name(tp->pci_dev));
+ rc = -EIO;
+ goto out;
+ }
+
+ /* Select default PHY for mac */
+ sis190_default_phy(dev);
+
+ sis190_mii_probe_88e1111_fixup(tp);
+
+ mii_if->dev = dev;
+ mii_if->mdio_read = __mdio_read;
+ mii_if->mdio_write = __mdio_write;
+ mii_if->phy_id_mask = PHY_ID_ANY;
+ mii_if->reg_num_mask = MII_REG_ANY;
+out:
+ return rc;
+}
+
+static void __devexit sis190_mii_remove(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_free_phy(&tp->first_phy);
+}
+
+static void sis190_release_board(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct sis190_private *tp = netdev_priv(dev);
+
+ iounmap(tp->mmio_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ free_netdev(dev);
+}
+
+static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
+{
+ struct sis190_private *tp;
+ struct net_device *dev;
+ void __iomem *ioaddr;
+ int rc;
+
+ dev = alloc_etherdev(sizeof(*tp));
+ if (!dev) {
+ net_drv(&debug, KERN_ERR PFX "unable to alloc new ethernet\n");
+ rc = -ENOMEM;
+ goto err_out_0;
+ }
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ tp = netdev_priv(dev);
+ tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
+
+ rc = pci_enable_device(pdev);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR "%s: enable failure\n", pci_name(pdev));
+ goto err_free_dev_1;
+ }
+
+ rc = -ENODEV;
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ net_probe(tp, KERN_ERR "%s: region #0 is no MMIO resource.\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+ if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) {
+ net_probe(tp, KERN_ERR "%s: invalid PCI region size(s).\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR PFX "%s: could not request regions.\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR "%s: DMA configuration failed.\n",
+ pci_name(pdev));
+ goto err_free_res_3;
+ }
+
+ pci_set_master(pdev);
+
+ ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE);
+ if (!ioaddr) {
+ net_probe(tp, KERN_ERR "%s: cannot remap MMIO, aborting\n",
+ pci_name(pdev));
+ rc = -EIO;
+ goto err_free_res_3;
+ }
+
+ tp->pci_dev = pdev;
+ tp->mmio_addr = ioaddr;
+
+ sis190_irq_mask_and_ack(ioaddr);
+
+ sis190_soft_reset(ioaddr);
+out:
+ return dev;
+
+err_free_res_3:
+ pci_release_regions(pdev);
+err_pci_disable_2:
+ pci_disable_device(pdev);
+err_free_dev_1:
+ free_netdev(dev);
+err_out_0:
+ dev = ERR_PTR(rc);
+ goto out;
+}
+
+static void sis190_tx_timeout(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u8 tmp8;
+
+ /* Disable Tx, if not already */
+ tmp8 = SIS_R8(TxControl);
+ if (tmp8 & CmdTxEnb)
+ SIS_W8(TxControl, tmp8 & ~CmdTxEnb);
+
+
+ net_tx_err(tp, KERN_INFO "%s: Transmit timeout, status %08x %08x.\n",
+ dev->name, SIS_R32(TxControl), SIS_R32(TxSts));
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ SIS_W32(IntrMask, 0x0000);
+
+ /* Stop a shared interrupt from scavenging while we are. */
+ spin_lock_irq(&tp->lock);
+ sis190_tx_clear(tp);
+ spin_unlock_irq(&tp->lock);
+
+ /* ...and finally, reset everything. */
+ sis190_hw_start(dev);
+
+ netif_wake_queue(dev);
+}
+
+static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+{
+ tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+}
+
+static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 sig;
+ int i;
+
+ net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n",
+ pci_name(pdev));
+
+ /* Check to see if there is a sane EEPROM */
+ sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
+
+ if ((sig == 0xffff) || (sig == 0x0000)) {
+ net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n",
+ pci_name(pdev), sig);
+ return -EIO;
+ }
+
+ /* Get MAC address from EEPROM */
+ for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
+ __le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
+
+ ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
+ }
+
+ sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
+
+ return 0;
+}
+
+/**
+ * sis190_get_mac_addr_from_apc - Get MAC address for SiS965 model
+ * @pdev: PCI device
+ * @dev: network device to get address for
+ *
+ * SiS965 model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *isa_bridge;
+ u8 reg, tmp8;
+ int i;
+
+ net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n",
+ pci_name(pdev));
+
+ isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0965, NULL);
+ if (!isa_bridge) {
+ net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
+ pci_name(pdev));
+ return -EIO;
+ }
+
+ /* Enable port 78h & 79h to access APC Registers. */
+ pci_read_config_byte(isa_bridge, 0x48, &tmp8);
+ reg = (tmp8 & ~0x02);
+ pci_write_config_byte(isa_bridge, 0x48, reg);
+ udelay(50);
+ pci_read_config_byte(isa_bridge, 0x48, &reg);
+
+ for (i = 0; i < MAC_ADDR_LEN; i++) {
+ outb(0x9 + i, 0x78);
+ dev->dev_addr[i] = inb(0x79);
+ }
+
+ outb(0x12, 0x78);
+ reg = inb(0x79);
+
+ sis190_set_rgmii(tp, reg);
+
+ /* Restore the value to ISA Bridge */
+ pci_write_config_byte(isa_bridge, 0x48, tmp8);
+ pci_dev_put(isa_bridge);
+
+ return 0;
+}
+
+/**
+ * sis190_init_rxfilter - Initialize the Rx filter
+ * @dev: network device to initialize
+ *
+ * Set receive filter address to our MAC address
+ * and enable packet filtering.
+ */
+static inline void sis190_init_rxfilter(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 ctl;
+ int i;
+
+ ctl = SIS_R16(RxMacControl);
+ /*
+ * Disable packet filtering before setting filter.
+ * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
+ * only and followed by RxMacAddr (6 bytes). Strange. -- FR
+ */
+ SIS_W16(RxMacControl, ctl & ~0x0f00);
+
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+ SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
+
+ SIS_W16(RxMacControl, ctl);
+ SIS_PCI_COMMIT();
+}
+
+static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
+{
+ u8 from;
+
+ pci_read_config_byte(pdev, 0x73, &from);
+
+ return (from & 0x00000001) ?
+ sis190_get_mac_addr_from_apc(pdev, dev) :
+ sis190_get_mac_addr_from_eeprom(pdev, dev);
+}
+
+static void sis190_set_speed_auto(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ int val;
+
+ net_link(tp, KERN_INFO "%s: Enabling Auto-negotiation.\n", dev->name);
+
+ val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+
+ // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
+ // unchanged.
+ mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
+ ADVERTISE_100FULL | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_10HALF);
+
+ // Enable 1000 Full Mode.
+ mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
+
+ // Enable auto-negotiation and restart auto-negotiation.
+ mdio_write(ioaddr, phy_id, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
+}
+
+static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_ethtool_gset(&tp->mii_if, cmd);
+}
+
+static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_ethtool_sset(&tp->mii_if, cmd);
+}
+
+static void sis190_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(tp->pci_dev));
+}
+
+static int sis190_get_regs_len(struct net_device *dev)
+{
+ return SIS190_REGS_SIZE;
+}
+
+static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ unsigned long flags;
+
+ if (regs->len > SIS190_REGS_SIZE)
+ regs->len = SIS190_REGS_SIZE;
+
+ spin_lock_irqsave(&tp->lock, flags);
+ memcpy_fromio(p, tp->mmio_addr, regs->len);
+ spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static int sis190_nway_reset(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_nway_restart(&tp->mii_if);
+}
+
+static u32 sis190_get_msglevel(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return tp->msg_enable;
+}
+
+static void sis190_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ tp->msg_enable = value;
+}
+
+static struct ethtool_ops sis190_ethtool_ops = {
+ .get_settings = sis190_get_settings,
+ .set_settings = sis190_set_settings,
+ .get_drvinfo = sis190_get_drvinfo,
+ .get_regs_len = sis190_get_regs_len,
+ .get_regs = sis190_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = sis190_get_msglevel,
+ .set_msglevel = sis190_set_msglevel,
+ .nway_reset = sis190_nway_reset,
+};
+
+static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return !netif_running(dev) ? -EINVAL :
+ generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
+}
+
+static int __devinit sis190_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ struct sis190_private *tp;
+ struct net_device *dev;
+ void __iomem *ioaddr;
+ int rc;
+
+ if (!printed_version) {
+ net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
+ printed_version = 1;
+ }
+
+ dev = sis190_init_board(pdev);
+ if (IS_ERR(dev)) {
+ rc = PTR_ERR(dev);
+ goto out;
+ }
+
+ tp = netdev_priv(dev);
+ ioaddr = tp->mmio_addr;
+
+ rc = sis190_get_mac_addr(pdev, dev);
+ if (rc < 0)
+ goto err_release_board;
+
+ sis190_init_rxfilter(dev);
+
+ INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+
+ dev->open = sis190_open;
+ dev->stop = sis190_close;
+ dev->do_ioctl = sis190_ioctl;
+ dev->get_stats = sis190_get_stats;
+ dev->tx_timeout = sis190_tx_timeout;
+ dev->watchdog_timeo = SIS190_TX_TIMEOUT;
+ dev->hard_start_xmit = sis190_start_xmit;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = sis190_netpoll;
+#endif
+ dev->set_multicast_list = sis190_set_rx_mode;
+ SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
+ dev->irq = pdev->irq;
+ dev->base_addr = (unsigned long) 0xdead;
+
+ spin_lock_init(&tp->lock);
+
+ rc = sis190_mii_probe(dev);
+ if (rc < 0)
+ goto err_release_board;
+
+ rc = register_netdev(dev);
+ if (rc < 0)
+ goto err_remove_mii;
+
+ pci_set_drvdata(pdev, dev);
+
+ net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+ pci_name(pdev), sis_chip_info[ent->driver_data].name,
+ ioaddr, dev->irq,
+ dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3],
+ dev->dev_addr[4], dev->dev_addr[5]);
+
+ net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
+ (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
+
+ netif_carrier_off(dev);
+
+ sis190_set_speed_auto(dev);
+out:
+ return rc;
+
+err_remove_mii:
+ sis190_mii_remove(dev);
+err_release_board:
+ sis190_release_board(pdev);
+ goto out;
+}
+
+static void __devexit sis190_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ sis190_mii_remove(dev);
+ unregister_netdev(dev);
+ sis190_release_board(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver sis190_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = sis190_pci_tbl,
+ .probe = sis190_init_one,
+ .remove = __devexit_p(sis190_remove_one),
+};
+
+static int __init sis190_init_module(void)
+{
+ return pci_module_init(&sis190_pci_driver);
+}
+
+static void __exit sis190_cleanup_module(void)
+{
+ pci_unregister_driver(&sis190_pci_driver);
+}
+
+module_init(sis190_init_module);
+module_exit(sis190_cleanup_module);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f15739481d62..d7c98515fdfd 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "0.9"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -79,8 +79,8 @@ static const struct pci_device_id skge_id_table[] = {
{ 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) },
- { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -189,7 +189,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
{
u32 supported;
- if (iscopper(hw)) {
+ if (hw->copper) {
supported = SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
@@ -222,7 +222,7 @@ static int skge_get_settings(struct net_device *dev,
ecmd->transceiver = XCVR_INTERNAL;
ecmd->supported = skge_supported_modes(hw);
- if (iscopper(hw)) {
+ if (hw->copper) {
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
} else
@@ -876,6 +876,9 @@ static int skge_rx_fill(struct skge_port *skge)
static void skge_link_up(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
netif_carrier_on(skge->netdev);
if (skge->tx_avail > MAX_SKB_FRAGS + 1)
netif_wake_queue(skge->netdev);
@@ -894,6 +897,7 @@ static void skge_link_up(struct skge_port *skge)
static void skge_link_down(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
netif_carrier_off(skge->netdev);
netif_stop_queue(skge->netdev);
@@ -1599,7 +1603,7 @@ static void yukon_init(struct skge_hw *hw, int port)
adv = PHY_AN_CSMA;
if (skge->autoneg == AUTONEG_ENABLE) {
- if (iscopper(hw)) {
+ if (hw->copper) {
if (skge->advertising & ADVERTISED_1000baseT_Full)
ct1000 |= PHY_M_1000C_AFD;
if (skge->advertising & ADVERTISED_1000baseT_Half)
@@ -1691,7 +1695,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
- reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+ reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
/* Clear GMC reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
@@ -1780,7 +1784,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
reg &= ~GMF_RX_F_FL_ON;
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
- skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+ /*
+ * because Pause Packet Truncation in GMAC is not working
+ * we have to increase the Flush Threshold to 64 bytes
+ * in order to flush pause packets in Rx FIFO on Yukon-1
+ */
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
/* Configure Tx MAC FIFO */
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -2670,18 +2679,6 @@ static void skge_error_irq(struct skge_hw *hw)
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
-
- if (hwstatus & IS_IRQ_SENSOR) {
- /* no sensors on 32-bit Yukon */
- if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
- printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
- skge_write32(hw, B0_HWE_IMSK,
- IS_ERR_MSK & ~IS_IRQ_SENSOR);
- } else
- printk(KERN_WARNING PFX "sensor interrupt\n");
- }
-
-
}
if (hwstatus & IS_RAM_RD_PAR) {
@@ -2712,9 +2709,10 @@ static void skge_error_irq(struct skge_hw *hw)
skge_pci_clear(hw);
+ /* if error still set then just ignore it */
hwstatus = skge_read32(hw, B0_HWE_ISRC);
if (hwstatus & IS_IRQ_STAT) {
- printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+ pr_debug("IRQ status %x: still set ignoring hardware errors\n",
hwstatus);
hw->intr_mask &= ~IS_HW_ERR;
}
@@ -2876,7 +2874,7 @@ static const char *skge_board_name(const struct skge_hw *hw)
static int skge_reset(struct skge_hw *hw)
{
u16 ctst;
- u8 t8, mac_cfg;
+ u8 t8, mac_cfg, pmd_type, phy_type;
int i;
ctst = skge_read16(hw, B0_CTST);
@@ -2895,18 +2893,19 @@ static int skge_reset(struct skge_hw *hw)
ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
hw->chip_id = skge_read8(hw, B2_CHIP_ID);
- hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
- hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+ phy_type = skge_read8(hw, B2_E_1) & 0xf;
+ pmd_type = skge_read8(hw, B2_PMD_TYP);
+ hw->copper = (pmd_type == 'T' || pmd_type == '1');
switch (hw->chip_id) {
case CHIP_ID_GENESIS:
- switch (hw->phy_type) {
+ switch (phy_type) {
case SK_PHY_BCOM:
hw->phy_addr = PHY_ADDR_BCOM;
break;
default:
printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
- pci_name(hw->pdev), hw->phy_type);
+ pci_name(hw->pdev), phy_type);
return -EOPNOTSUPP;
}
break;
@@ -2914,13 +2913,10 @@ static int skge_reset(struct skge_hw *hw)
case CHIP_ID_YUKON:
case CHIP_ID_YUKON_LITE:
case CHIP_ID_YUKON_LP:
- if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
- hw->phy_type = SK_PHY_MARV_COPPER;
+ if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+ hw->copper = 1;
hw->phy_addr = PHY_ADDR_MARV;
- if (!iscopper(hw))
- hw->phy_type = SK_PHY_MARV_FIBER;
-
break;
default:
@@ -2948,12 +2944,20 @@ static int skge_reset(struct skge_hw *hw)
else
hw->ram_size = t8 * 4096;
+ hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_init(hw);
else {
/* switch power to VCC (WA for VAUX problem) */
skge_write8(hw, B0_POWER_CTRL,
PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+ /* avoid boards with stuck Hardware error bits */
+ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+ (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+ printk(KERN_WARNING PFX "stuck hardware sensor bit\n");
+ hw->intr_mask &= ~IS_HW_ERR;
+ }
+
for (i = 0; i < hw->ports; i++) {
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
@@ -2994,7 +2998,6 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
skge_write32(hw, B2_IRQM_CTRL, TIM_START);
- hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask);
if (hw->chip_id != CHIP_ID_GENESIS)
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index b432f1bb8168..f1680beb8e68 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -214,8 +214,6 @@ enum {
/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
enum {
- IS_ERR_MSK = 0x00003fff,/* All Error bits */
-
IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
@@ -230,6 +228,12 @@ enum {
IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
+
+ IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT
+ | IS_NO_STAT_M1 | IS_NO_STAT_M2
+ | IS_RAM_RD_PAR | IS_RAM_WR_PAR
+ | IS_M1_PAR_ERR | IS_M2_PAR_ERR
+ | IS_R1_PAR_ERR | IS_R2_PAR_ERR,
};
/* B2_TST_CTRL1 8 bit Test Control Register 1 */
@@ -2456,24 +2460,17 @@ struct skge_hw {
u8 chip_id;
u8 chip_rev;
- u8 phy_type;
- u8 pmd_type;
- u16 phy_addr;
+ u8 copper;
u8 ports;
u32 ram_size;
u32 ram_offset;
+ u16 phy_addr;
struct tasklet_struct ext_tasklet;
spinlock_t phy_lock;
};
-
-static inline int iscopper(const struct skge_hw *hw)
-{
- return (hw->pmd_type == 'T');
-}
-
enum {
FLOW_MODE_NONE = 0, /* No Flow-Control */
FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 6d9dae60a697..ba8593ac3f8a 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -68,6 +68,7 @@ static const char version[] =
#include <linux/etherdevice.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/system.h>
#include "8390.h"
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index a9b06b8d8e3f..ac9ce6509eee 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -986,7 +986,7 @@ static const char * chip_ids[ 16 ] = {
})
#endif
-#if SMC_CAN_USE_DATACS
+#ifdef SMC_CAN_USE_DATACS
#define SMC_PUSH_DATA(p, l) \
if ( lp->datacs ) { \
unsigned char *__ptr = (p); \
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index cdc9cc873e06..90b818a8de6e 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -1,6 +1,11 @@
/*
* sonic.c
*
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, added zero-copy buffer handling, and
+ * (from the mac68k project) introduced dhd's support for 16-bit cards.
+ *
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*
* This driver is based on work from Andreas Busse, but most of
@@ -9,12 +14,23 @@
* (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
*
* Core code included by system sonic drivers
+ *
+ * And... partially rewritten again by David Huggins-Daines in order
+ * to cope with screwed up Macintosh NICs that may or may not use
+ * 16-bit DMA.
+ *
+ * (C) 1999 David Huggins-Daines <dhd@debian.org>
+ *
*/
/*
* Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
* National Semiconductors data sheet for the DP83932B Sonic Ethernet
* controller, and the files "8390.c" and "skeleton.c" in this directory.
+ *
+ * Additional sources: Nat Semi data sheet for the DP83932C and Nat Semi
+ * Application Note AN-746, the files "lance.c" and "ibmlana.c". See also
+ * the NetBSD file "sys/arch/mac68k/dev/if_sn.c".
*/
@@ -28,6 +44,9 @@
*/
static int sonic_open(struct net_device *dev)
{
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
+
if (sonic_debug > 2)
printk("sonic_open: initializing sonic driver.\n");
@@ -40,14 +59,59 @@ static int sonic_open(struct net_device *dev)
* This means that during execution of the handler interrupt are disabled
* covering another bug otherwise corrupting data. This doesn't mean
* this glue works ok under all situations.
+ *
+ * Note (dhd): this also appears to prevent lockups on the Macintrash
+ * when more than one Ethernet card is installed (knock on wood)
+ *
+ * Note (fthain): whether the above is still true is anyones guess. Certainly
+ * the buffer handling algorithms will not tolerate re-entrance without some
+ * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
+ * rx code to make this a faster "fast interrupt".
*/
-// if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
- if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT,
- "sonic", dev)) {
- printk("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+ if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
+ printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
return -EAGAIN;
}
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ if (skb == NULL) {
+ while(i > 0) { /* free any that were allocated successfully */
+ i--;
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ printk(KERN_ERR "%s: couldn't allocate receive buffers\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ skb->dev = dev;
+ /* align IP header unless DMA requires otherwise */
+ if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+ skb_reserve(skb, 2);
+ lp->rx_skb[i] = skb;
+ }
+
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE),
+ SONIC_RBSIZE, DMA_FROM_DEVICE);
+ if (!laddr) {
+ while(i > 0) { /* free any that were mapped successfully */
+ i--;
+ dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ lp->rx_laddr[i] = (dma_addr_t)0;
+ }
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ printk(KERN_ERR "%s: couldn't map rx DMA buffers\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ lp->rx_laddr[i] = laddr;
+ }
+
/*
* Initialize the SONIC
*/
@@ -67,7 +131,8 @@ static int sonic_open(struct net_device *dev)
*/
static int sonic_close(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
if (sonic_debug > 2)
printk("sonic_close\n");
@@ -77,20 +142,56 @@ static int sonic_close(struct net_device *dev)
/*
* stop the SONIC, disable interrupts
*/
- SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
- sonic_free_irq(dev->irq, dev); /* release the IRQ */
+ /* unmap and free skbs that haven't been transmitted */
+ for (i = 0; i < SONIC_NUM_TDS; i++) {
+ if(lp->tx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+ lp->tx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->tx_skb[i]) {
+ dev_kfree_skb(lp->tx_skb[i]);
+ lp->tx_skb[i] = NULL;
+ }
+ }
+
+ /* unmap and free the receive buffers */
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ if(lp->rx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ lp->rx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->rx_skb[i]) {
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ }
+
+ free_irq(dev->irq, dev); /* release the IRQ */
return 0;
}
static void sonic_tx_timeout(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- printk("%s: transmit timed out.\n", dev->name);
-
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
+ /* Stop the interrupts for this */
+ SONIC_WRITE(SONIC_IMR, 0);
+ /* We could resend the original skbs. Easier to re-initialise. */
+ for (i = 0; i < SONIC_NUM_TDS; i++) {
+ if(lp->tx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+ lp->tx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->tx_skb[i]) {
+ dev_kfree_skb(lp->tx_skb[i]);
+ lp->tx_skb[i] = NULL;
+ }
+ }
/* Try to restart the adaptor. */
sonic_init(dev);
lp->stats.tx_errors++;
@@ -100,60 +201,92 @@ static void sonic_tx_timeout(struct net_device *dev)
/*
* transmit packet
+ *
+ * Appends new TD during transmission thus avoiding any TX interrupts
+ * until we run out of TDs.
+ * This routine interacts closely with the ISR in that it may,
+ * set tx_skb[i]
+ * reset the status flags of the new TD
+ * set and reset EOL flags
+ * stop the tx queue
+ * The ISR interacts with this routine in various ways. It may,
+ * reset tx_skb[i]
+ * test the EOL and status flags of the TDs
+ * wake the tx queue
+ * Concurrently with all of this, the SONIC is potentially writing to
+ * the status flags of the TDs.
+ * Until some mutual exclusion is added, this code will not work with SMP. However,
+ * MIPS Jazz machines and m68k Macs were all uni-processor machines.
*/
+
static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
- unsigned int laddr;
- int entry, length;
-
- netif_stop_queue(dev);
+ struct sonic_local *lp = netdev_priv(dev);
+ dma_addr_t laddr;
+ int length;
+ int entry = lp->next_tx;
if (sonic_debug > 2)
printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);
+ length = skb->len;
+ if (length < ETH_ZLEN) {
+ skb = skb_padto(skb, ETH_ZLEN);
+ if (skb == NULL)
+ return 0;
+ length = ETH_ZLEN;
+ }
+
/*
* Map the packet data into the logical DMA address space
*/
- if ((laddr = vdma_alloc(CPHYSADDR(skb->data), skb->len)) == ~0UL) {
- printk("%s: no VDMA entry for transmit available.\n",
- dev->name);
+
+ laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
+ if (!laddr) {
+ printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
dev_kfree_skb(skb);
- netif_start_queue(dev);
return 1;
}
- entry = lp->cur_tx & SONIC_TDS_MASK;
+
+ sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */
+ sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_L, laddr & 0xffff);
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_H, laddr >> 16);
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_SIZE, length);
+ sonic_tda_put(dev, entry, SONIC_TD_LINK,
+ sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
+
+ /*
+ * Must set tx_skb[entry] only after clearing status, and
+ * before clearing EOL and before stopping queue
+ */
+ wmb();
+ lp->tx_len[entry] = length;
lp->tx_laddr[entry] = laddr;
lp->tx_skb[entry] = skb;
- length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- flush_cache_all();
+ wmb();
+ sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK,
+ sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL);
+ lp->eol_tx = entry;
- /*
- * Setup the transmit descriptor and issue the transmit command.
- */
- lp->tda[entry].tx_status = 0; /* clear status */
- lp->tda[entry].tx_frag_count = 1; /* single fragment */
- lp->tda[entry].tx_pktsize = length; /* length of packet */
- lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
- lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
- lp->tda[entry].tx_frag_size = length;
- lp->cur_tx++;
- lp->stats.tx_bytes += length;
+ lp->next_tx = (entry + 1) & SONIC_TDS_MASK;
+ if (lp->tx_skb[lp->next_tx] != NULL) {
+ /* The ring is full, the ISR has yet to process the next TD. */
+ if (sonic_debug > 3)
+ printk("%s: stopping queue\n", dev->name);
+ netif_stop_queue(dev);
+ /* after this packet, wait for ISR to free up some TDAs */
+ } else netif_start_queue(dev);
if (sonic_debug > 2)
- printk("sonic_send_packet: issueing Tx command\n");
+ printk("sonic_send_packet: issuing Tx command\n");
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
dev->trans_start = jiffies;
- if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS)
- netif_start_queue(dev);
- else
- lp->tx_full = 1;
-
return 0;
}
@@ -164,175 +297,199 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
- unsigned int base_addr = dev->base_addr;
- struct sonic_local *lp;
+ struct sonic_local *lp = netdev_priv(dev);
int status;
if (dev == NULL) {
- printk("sonic_interrupt: irq %d for unknown device.\n", irq);
+ printk(KERN_ERR "sonic_interrupt: irq %d for unknown device.\n", irq);
return IRQ_NONE;
}
- lp = (struct sonic_local *) dev->priv;
-
- status = SONIC_READ(SONIC_ISR);
- SONIC_WRITE(SONIC_ISR, 0x7fff); /* clear all bits */
-
- if (sonic_debug > 2)
- printk("sonic_interrupt: ISR=%x\n", status);
-
- if (status & SONIC_INT_PKTRX) {
- sonic_rx(dev); /* got packet(s) */
- }
-
- if (status & SONIC_INT_TXDN) {
- int dirty_tx = lp->dirty_tx;
-
- while (dirty_tx < lp->cur_tx) {
- int entry = dirty_tx & SONIC_TDS_MASK;
- int status = lp->tda[entry].tx_status;
+ if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
+ return IRQ_NONE;
- if (sonic_debug > 3)
- printk
- ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
- status, lp->cur_tx, lp->dirty_tx);
+ do {
+ if (status & SONIC_INT_PKTRX) {
+ if (sonic_debug > 2)
+ printk("%s: packet rx\n", dev->name);
+ sonic_rx(dev); /* got packet(s) */
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_PKTRX); /* clear the interrupt */
+ }
- if (status == 0) {
- /* It still hasn't been Txed, kick the sonic again */
- SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
- break;
- }
+ if (status & SONIC_INT_TXDN) {
+ int entry = lp->cur_tx;
+ int td_status;
+ int freed_some = 0;
- /* put back EOL and free descriptor */
- lp->tda[entry].tx_frag_count = 0;
- lp->tda[entry].tx_status = 0;
-
- if (status & 0x0001)
- lp->stats.tx_packets++;
- else {
- lp->stats.tx_errors++;
- if (status & 0x0642)
- lp->stats.tx_aborted_errors++;
- if (status & 0x0180)
- lp->stats.tx_carrier_errors++;
- if (status & 0x0020)
- lp->stats.tx_window_errors++;
- if (status & 0x0004)
- lp->stats.tx_fifo_errors++;
- }
+ /* At this point, cur_tx is the index of a TD that is one of:
+ * unallocated/freed (status set & tx_skb[entry] clear)
+ * allocated and sent (status set & tx_skb[entry] set )
+ * allocated and not yet sent (status clear & tx_skb[entry] set )
+ * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+ */
- /* We must free the original skb */
- if (lp->tx_skb[entry]) {
+ if (sonic_debug > 2)
+ printk("%s: tx done\n", dev->name);
+
+ while (lp->tx_skb[entry] != NULL) {
+ if ((td_status = sonic_tda_get(dev, entry, SONIC_TD_STATUS)) == 0)
+ break;
+
+ if (td_status & 0x0001) {
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE);
+ } else {
+ lp->stats.tx_errors++;
+ if (td_status & 0x0642)
+ lp->stats.tx_aborted_errors++;
+ if (td_status & 0x0180)
+ lp->stats.tx_carrier_errors++;
+ if (td_status & 0x0020)
+ lp->stats.tx_window_errors++;
+ if (td_status & 0x0004)
+ lp->stats.tx_fifo_errors++;
+ }
+
+ /* We must free the original skb */
dev_kfree_skb_irq(lp->tx_skb[entry]);
- lp->tx_skb[entry] = 0;
+ lp->tx_skb[entry] = NULL;
+ /* and unmap DMA buffer */
+ dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE);
+ lp->tx_laddr[entry] = (dma_addr_t)0;
+ freed_some = 1;
+
+ if (sonic_tda_get(dev, entry, SONIC_TD_LINK) & SONIC_EOL) {
+ entry = (entry + 1) & SONIC_TDS_MASK;
+ break;
+ }
+ entry = (entry + 1) & SONIC_TDS_MASK;
}
- /* and the VDMA address */
- vdma_free(lp->tx_laddr[entry]);
- dirty_tx++;
- }
- if (lp->tx_full
- && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) {
- /* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
- netif_wake_queue(dev);
+ if (freed_some || lp->tx_skb[entry] == NULL)
+ netif_wake_queue(dev); /* The ring is no longer full */
+ lp->cur_tx = entry;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_TXDN); /* clear the interrupt */
}
- lp->dirty_tx = dirty_tx;
- }
+ /*
+ * check error conditions
+ */
+ if (status & SONIC_INT_RFO) {
+ if (sonic_debug > 1)
+ printk("%s: rx fifo overrun\n", dev->name);
+ lp->stats.rx_fifo_errors++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RFO); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_RDE) {
+ if (sonic_debug > 1)
+ printk("%s: rx descriptors exhausted\n", dev->name);
+ lp->stats.rx_dropped++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RDE); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_RBAE) {
+ if (sonic_debug > 1)
+ printk("%s: rx buffer area exceeded\n", dev->name);
+ lp->stats.rx_dropped++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RBAE); /* clear the interrupt */
+ }
- /*
- * check error conditions
- */
- if (status & SONIC_INT_RFO) {
- printk("%s: receive fifo underrun\n", dev->name);
- lp->stats.rx_fifo_errors++;
- }
- if (status & SONIC_INT_RDE) {
- printk("%s: receive descriptors exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
- if (status & SONIC_INT_RBE) {
- printk("%s: receive buffer exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
- if (status & SONIC_INT_RBAE) {
- printk("%s: receive buffer area exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
+ /* counter overruns; all counters are 16bit wide */
+ if (status & SONIC_INT_FAE) {
+ lp->stats.rx_frame_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_FAE); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_CRC) {
+ lp->stats.rx_crc_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_CRC); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_MP) {
+ lp->stats.rx_missed_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_MP); /* clear the interrupt */
+ }
- /* counter overruns; all counters are 16bit wide */
- if (status & SONIC_INT_FAE)
- lp->stats.rx_frame_errors += 65536;
- if (status & SONIC_INT_CRC)
- lp->stats.rx_crc_errors += 65536;
- if (status & SONIC_INT_MP)
- lp->stats.rx_missed_errors += 65536;
+ /* transmit error */
+ if (status & SONIC_INT_TXER) {
+ if ((SONIC_READ(SONIC_TCR) & SONIC_TCR_FU) && (sonic_debug > 2))
+ printk(KERN_ERR "%s: tx fifo underrun\n", dev->name);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_TXER); /* clear the interrupt */
+ }
- /* transmit error */
- if (status & SONIC_INT_TXER)
- lp->stats.tx_errors++;
+ /* bus retry */
+ if (status & SONIC_INT_BR) {
+ printk(KERN_ERR "%s: Bus retry occurred! Device interrupt disabled.\n",
+ dev->name);
+ /* ... to help debug DMA problems causing endless interrupts. */
+ /* Bounce the eth interface to turn on the interrupt again. */
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_BR); /* clear the interrupt */
+ }
- /*
- * clear interrupt bits and return
- */
- SONIC_WRITE(SONIC_ISR, status);
+ /* load CAM done */
+ if (status & SONIC_INT_LCD)
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
+ } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
return IRQ_HANDLED;
}
/*
- * We have a good packet(s), get it/them out of the buffers.
+ * We have a good packet(s), pass it/them up the network stack.
*/
static void sonic_rx(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];
+ struct sonic_local *lp = netdev_priv(dev);
int status;
-
- while (rd->in_use == 0) {
- struct sk_buff *skb;
+ int entry = lp->cur_rx;
+
+ while (sonic_rda_get(dev, entry, SONIC_RD_IN_USE) == 0) {
+ struct sk_buff *used_skb;
+ struct sk_buff *new_skb;
+ dma_addr_t new_laddr;
+ u16 bufadr_l;
+ u16 bufadr_h;
int pkt_len;
- unsigned char *pkt_ptr;
- status = rd->rx_status;
- if (sonic_debug > 3)
- printk("status %x, cur_rx %d, cur_rra %x\n",
- status, lp->cur_rx, lp->cur_rra);
+ status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
if (status & SONIC_RCR_PRX) {
- pkt_len = rd->rx_pktlen;
- pkt_ptr =
- (char *)
- sonic_chiptomem((rd->rx_pktptr_h << 16) +
- rd->rx_pktptr_l);
-
- if (sonic_debug > 3)
- printk
- ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n",
- pkt_ptr, lp->rba, rd->rx_pktptr_h,
- rd->rx_pktptr_l,
- SONIC_READ(SONIC_RBWC1),
- SONIC_READ(SONIC_RBWC0));
-
/* Malloc up new buffer. */
- skb = dev_alloc_skb(pkt_len + 2);
- if (skb == NULL) {
- printk
- ("%s: Memory squeeze, dropping packet.\n",
- dev->name);
+ new_skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ if (new_skb == NULL) {
+ printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ break;
+ }
+ new_skb->dev = dev;
+ /* provide 16 byte IP header alignment unless DMA requires otherwise */
+ if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+ skb_reserve(new_skb, 2);
+
+ new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE),
+ SONIC_RBSIZE, DMA_FROM_DEVICE);
+ if (!new_laddr) {
+ dev_kfree_skb(new_skb);
+ printk(KERN_ERR "%s: Failed to map rx buffer, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->dev = dev;
- skb_reserve(skb, 2); /* 16 byte align */
- skb_put(skb, pkt_len); /* Make room */
- eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb); /* pass the packet to upper layers */
+
+ /* now we have a new skb to replace it, pass the used one up the stack */
+ dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ used_skb = lp->rx_skb[entry];
+ pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
+ skb_trim(used_skb, pkt_len);
+ used_skb->protocol = eth_type_trans(used_skb, dev);
+ netif_rx(used_skb);
dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
+ /* and insert the new skb */
+ lp->rx_laddr[entry] = new_laddr;
+ lp->rx_skb[entry] = new_skb;
+
+ bufadr_l = (unsigned long)new_laddr & 0xffff;
+ bufadr_h = (unsigned long)new_laddr >> 16;
+ sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
+ sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
} else {
/* This should only happen, if we enable accepting broken packets. */
lp->stats.rx_errors++;
@@ -341,29 +498,35 @@ static void sonic_rx(struct net_device *dev)
if (status & SONIC_RCR_CRCR)
lp->stats.rx_crc_errors++;
}
-
- rd->in_use = 1;
- rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK];
- /* now give back the buffer to the receive buffer area */
if (status & SONIC_RCR_LPKT) {
/*
- * this was the last packet out of the current receice buffer
+ * this was the last packet out of the current receive buffer
* give the buffer back to the SONIC
*/
- lp->cur_rra += sizeof(sonic_rr_t);
- if (lp->cur_rra >
- (lp->rra_laddr +
- (SONIC_NUM_RRS -
- 1) * sizeof(sonic_rr_t))) lp->cur_rra =
- lp->rra_laddr;
- SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff);
+ lp->cur_rwp += SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode);
+ if (lp->cur_rwp >= lp->rra_end) lp->cur_rwp = lp->rra_laddr & 0xffff;
+ SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
+ if (SONIC_READ(SONIC_ISR) & SONIC_INT_RBE) {
+ if (sonic_debug > 2)
+ printk("%s: rx buffer exhausted\n", dev->name);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
+ }
} else
- printk
- ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
+ printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
dev->name);
+ /*
+ * give back the descriptor
+ */
+ sonic_rda_put(dev, entry, SONIC_RD_LINK,
+ sonic_rda_get(dev, entry, SONIC_RD_LINK) | SONIC_EOL);
+ sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
+ sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK,
+ sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK) & ~SONIC_EOL);
+ lp->eol_rx = entry;
+ lp->cur_rx = entry = (entry + 1) & SONIC_RDS_MASK;
}
/*
- * If any worth-while packets have been received, dev_rint()
+ * If any worth-while packets have been received, netif_rx()
* has done a mark_bh(NET_BH) for us and will work on them
* when we get to the bottom-half routine.
*/
@@ -376,8 +539,7 @@ static void sonic_rx(struct net_device *dev)
*/
static struct net_device_stats *sonic_get_stats(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
/* read the tally counter from the SONIC and reset them */
lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT);
@@ -396,8 +558,7 @@ static struct net_device_stats *sonic_get_stats(struct net_device *dev)
*/
static void sonic_multicast_list(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
unsigned int rcr;
struct dev_mc_list *dmi = dev->mc_list;
unsigned char *addr;
@@ -413,20 +574,15 @@ static void sonic_multicast_list(struct net_device *dev)
rcr |= SONIC_RCR_AMC;
} else {
if (sonic_debug > 2)
- printk
- ("sonic_multicast_list: mc_count %d\n",
- dev->mc_count);
- lp->cda.cam_enable = 1; /* always enable our own address */
+ printk("sonic_multicast_list: mc_count %d\n", dev->mc_count);
+ sonic_set_cam_enable(dev, 1); /* always enable our own address */
for (i = 1; i <= dev->mc_count; i++) {
addr = dmi->dmi_addr;
dmi = dmi->next;
- lp->cda.cam_desc[i].cam_cap0 =
- addr[1] << 8 | addr[0];
- lp->cda.cam_desc[i].cam_cap1 =
- addr[3] << 8 | addr[2];
- lp->cda.cam_desc[i].cam_cap2 =
- addr[5] << 8 | addr[4];
- lp->cda.cam_enable |= (1 << i);
+ sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]);
+ sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]);
+ sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]);
+ sonic_set_cam_enable(dev, sonic_get_cam_enable(dev) | (1 << i));
}
SONIC_WRITE(SONIC_CDC, 16);
/* issue Load CAM command */
@@ -447,19 +603,16 @@ static void sonic_multicast_list(struct net_device *dev)
*/
static int sonic_init(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
unsigned int cmd;
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int rra_start;
- unsigned int rra_end;
+ struct sonic_local *lp = netdev_priv(dev);
int i;
/*
* put the Sonic into software-reset mode and
* disable all interrupts
*/
- SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
/*
@@ -475,34 +628,32 @@ static int sonic_init(struct net_device *dev)
if (sonic_debug > 2)
printk("sonic_init: initialize receive resource area\n");
- rra_start = lp->rra_laddr & 0xffff;
- rra_end =
- (rra_start + (SONIC_NUM_RRS * sizeof(sonic_rr_t))) & 0xffff;
-
for (i = 0; i < SONIC_NUM_RRS; i++) {
- lp->rra[i].rx_bufadr_l =
- (lp->rba_laddr + i * SONIC_RBSIZE) & 0xffff;
- lp->rra[i].rx_bufadr_h =
- (lp->rba_laddr + i * SONIC_RBSIZE) >> 16;
- lp->rra[i].rx_bufsize_l = SONIC_RBSIZE >> 1;
- lp->rra[i].rx_bufsize_h = 0;
+ u16 bufadr_l = (unsigned long)lp->rx_laddr[i] & 0xffff;
+ u16 bufadr_h = (unsigned long)lp->rx_laddr[i] >> 16;
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
+ sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_L, SONIC_RBSIZE >> 1);
+ sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_H, 0);
}
/* initialize all RRA registers */
- SONIC_WRITE(SONIC_RSA, rra_start);
- SONIC_WRITE(SONIC_REA, rra_end);
- SONIC_WRITE(SONIC_RRP, rra_start);
- SONIC_WRITE(SONIC_RWP, rra_end);
+ lp->rra_end = (lp->rra_laddr + SONIC_NUM_RRS * SIZEOF_SONIC_RR *
+ SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+ lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR *
+ SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+
+ SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff);
+ SONIC_WRITE(SONIC_REA, lp->rra_end);
+ SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff);
+ SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16);
- SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE - 2) >> 1);
-
- lp->cur_rra =
- lp->rra_laddr + (SONIC_NUM_RRS - 1) * sizeof(sonic_rr_t);
+ SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1));
/* load the resource pointers */
if (sonic_debug > 3)
- printk("sonic_init: issueing RRRA command\n");
-
+ printk("sonic_init: issuing RRRA command\n");
+
SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
i = 0;
while (i++ < 100) {
@@ -511,27 +662,30 @@ static int sonic_init(struct net_device *dev)
}
if (sonic_debug > 2)
- printk("sonic_init: status=%x\n", SONIC_READ(SONIC_CMD));
-
+ printk("sonic_init: status=%x i=%d\n", SONIC_READ(SONIC_CMD), i);
+
/*
* Initialize the receive descriptors so that they
* become a circular linked list, ie. let the last
* descriptor point to the first again.
*/
if (sonic_debug > 2)
- printk("sonic_init: initialize receive descriptors\n");
- for (i = 0; i < SONIC_NUM_RDS; i++) {
- lp->rda[i].rx_status = 0;
- lp->rda[i].rx_pktlen = 0;
- lp->rda[i].rx_pktptr_l = 0;
- lp->rda[i].rx_pktptr_h = 0;
- lp->rda[i].rx_seqno = 0;
- lp->rda[i].in_use = 1;
- lp->rda[i].link =
- lp->rda_laddr + (i + 1) * sizeof(sonic_rd_t);
+ printk("sonic_init: initialize receive descriptors\n");
+ for (i=0; i<SONIC_NUM_RDS; i++) {
+ sonic_rda_put(dev, i, SONIC_RD_STATUS, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTLEN, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTPTR_L, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTPTR_H, 0);
+ sonic_rda_put(dev, i, SONIC_RD_SEQNO, 0);
+ sonic_rda_put(dev, i, SONIC_RD_IN_USE, 1);
+ sonic_rda_put(dev, i, SONIC_RD_LINK,
+ lp->rda_laddr +
+ ((i+1) * SIZEOF_SONIC_RD * SONIC_BUS_SCALE(lp->dma_bitmode)));
}
/* fix last descriptor */
- lp->rda[SONIC_NUM_RDS - 1].link = lp->rda_laddr;
+ sonic_rda_put(dev, SONIC_NUM_RDS - 1, SONIC_RD_LINK,
+ (lp->rda_laddr & 0xffff) | SONIC_EOL);
+ lp->eol_rx = SONIC_NUM_RDS - 1;
lp->cur_rx = 0;
SONIC_WRITE(SONIC_URDA, lp->rda_laddr >> 16);
SONIC_WRITE(SONIC_CRDA, lp->rda_laddr & 0xffff);
@@ -542,34 +696,34 @@ static int sonic_init(struct net_device *dev)
if (sonic_debug > 2)
printk("sonic_init: initialize transmit descriptors\n");
for (i = 0; i < SONIC_NUM_TDS; i++) {
- lp->tda[i].tx_status = 0;
- lp->tda[i].tx_config = 0;
- lp->tda[i].tx_pktsize = 0;
- lp->tda[i].tx_frag_count = 0;
- lp->tda[i].link =
- (lp->tda_laddr +
- (i + 1) * sizeof(sonic_td_t)) | SONIC_END_OF_LINKS;
+ sonic_tda_put(dev, i, SONIC_TD_STATUS, 0);
+ sonic_tda_put(dev, i, SONIC_TD_CONFIG, 0);
+ sonic_tda_put(dev, i, SONIC_TD_PKTSIZE, 0);
+ sonic_tda_put(dev, i, SONIC_TD_FRAG_COUNT, 0);
+ sonic_tda_put(dev, i, SONIC_TD_LINK,
+ (lp->tda_laddr & 0xffff) +
+ (i + 1) * SIZEOF_SONIC_TD * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->tx_skb[i] = NULL;
}
- lp->tda[SONIC_NUM_TDS - 1].link =
- (lp->tda_laddr & 0xffff) | SONIC_END_OF_LINKS;
+ /* fix last descriptor */
+ sonic_tda_put(dev, SONIC_NUM_TDS - 1, SONIC_TD_LINK,
+ (lp->tda_laddr & 0xffff));
SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16);
SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff);
- lp->cur_tx = lp->dirty_tx = 0;
-
+ lp->cur_tx = lp->next_tx = 0;
+ lp->eol_tx = SONIC_NUM_TDS - 1;
+
/*
* put our own address to CAM desc[0]
*/
- lp->cda.cam_desc[0].cam_cap0 =
- dev->dev_addr[1] << 8 | dev->dev_addr[0];
- lp->cda.cam_desc[0].cam_cap1 =
- dev->dev_addr[3] << 8 | dev->dev_addr[2];
- lp->cda.cam_desc[0].cam_cap2 =
- dev->dev_addr[5] << 8 | dev->dev_addr[4];
- lp->cda.cam_enable = 1;
+ sonic_cda_put(dev, 0, SONIC_CD_CAP0, dev->dev_addr[1] << 8 | dev->dev_addr[0]);
+ sonic_cda_put(dev, 0, SONIC_CD_CAP1, dev->dev_addr[3] << 8 | dev->dev_addr[2]);
+ sonic_cda_put(dev, 0, SONIC_CD_CAP2, dev->dev_addr[5] << 8 | dev->dev_addr[4]);
+ sonic_set_cam_enable(dev, 1);
for (i = 0; i < 16; i++)
- lp->cda.cam_desc[i].cam_entry_pointer = i;
+ sonic_cda_put(dev, i, SONIC_CD_ENTRY_POINTER, i);
/*
* initialize CAM registers
@@ -588,8 +742,8 @@ static int sonic_init(struct net_device *dev)
break;
}
if (sonic_debug > 2) {
- printk("sonic_init: CMD=%x, ISR=%x\n",
- SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR));
+ printk("sonic_init: CMD=%x, ISR=%x\n, i=%d",
+ SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i);
}
/*
@@ -604,7 +758,7 @@ static int sonic_init(struct net_device *dev)
cmd = SONIC_READ(SONIC_CMD);
if ((cmd & SONIC_CR_RXEN) == 0 || (cmd & SONIC_CR_STP) == 0)
- printk("sonic_init: failed, status=%x\n", cmd);
+ printk(KERN_ERR "sonic_init: failed, status=%x\n", cmd);
if (sonic_debug > 2)
printk("sonic_init: new status=%x\n",
diff --git a/drivers/net/sonic.h b/drivers/net/sonic.h
index c4a6d58e4afb..cede969a8baa 100644
--- a/drivers/net/sonic.h
+++ b/drivers/net/sonic.h
@@ -1,5 +1,5 @@
/*
- * Helpfile for sonic.c
+ * Header file for sonic.c
*
* (C) Waldorf Electronics, Germany
* Written by Andreas Busse
@@ -9,10 +9,16 @@
* and pad structure members must be exchanged. Also, the structures
* need to be changed accordingly to the bus size.
*
- * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian),
- * see CONFIG_MACSONIC branch below.
+ * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian)
*
+ * 990611 David Huggins-Daines <dhd@debian.org>: This machine abstraction
+ * does not cope with 16-bit bus sizes very well. Therefore I have
+ * rewritten it with ugly macros and evil inlines.
+ *
+ * 050625 Finn Thain: introduced more 32-bit cards and dhd's support
+ * for 16-bit cards (from the mac68k project).
*/
+
#ifndef SONIC_H
#define SONIC_H
@@ -83,6 +89,7 @@
/*
* Error counters
*/
+
#define SONIC_CRCT 0x2c
#define SONIC_FAET 0x2d
#define SONIC_MPT 0x2e
@@ -182,14 +189,14 @@
#define SONIC_INT_BR 0x4000
#define SONIC_INT_HBL 0x2000
-#define SONIC_INT_LCD 0x1000
-#define SONIC_INT_PINT 0x0800
-#define SONIC_INT_PKTRX 0x0400
-#define SONIC_INT_TXDN 0x0200
-#define SONIC_INT_TXER 0x0100
-#define SONIC_INT_TC 0x0080
-#define SONIC_INT_RDE 0x0040
-#define SONIC_INT_RBE 0x0020
+#define SONIC_INT_LCD 0x1000
+#define SONIC_INT_PINT 0x0800
+#define SONIC_INT_PKTRX 0x0400
+#define SONIC_INT_TXDN 0x0200
+#define SONIC_INT_TXER 0x0100
+#define SONIC_INT_TC 0x0080
+#define SONIC_INT_RDE 0x0040
+#define SONIC_INT_RBE 0x0020
#define SONIC_INT_RBAE 0x0010
#define SONIC_INT_CRC 0x0008
#define SONIC_INT_FAE 0x0004
@@ -201,224 +208,61 @@
* The interrupts we allow.
*/
-#define SONIC_IMR_DEFAULT (SONIC_INT_BR | \
- SONIC_INT_LCD | \
- SONIC_INT_PINT | \
+#define SONIC_IMR_DEFAULT ( SONIC_INT_BR | \
+ SONIC_INT_LCD | \
+ SONIC_INT_RFO | \
SONIC_INT_PKTRX | \
SONIC_INT_TXDN | \
SONIC_INT_TXER | \
SONIC_INT_RDE | \
- SONIC_INT_RBE | \
SONIC_INT_RBAE | \
SONIC_INT_CRC | \
SONIC_INT_FAE | \
SONIC_INT_MP)
-#define SONIC_END_OF_LINKS 0x0001
-
-
-#ifdef CONFIG_MACSONIC
-/*
- * Big endian like structures on 680x0 Macs
- */
-
-typedef struct {
- u32 rx_bufadr_l; /* receive buffer ptr */
- u32 rx_bufadr_h;
-
- u32 rx_bufsize_l; /* no. of words in the receive buffer */
- u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
- SREGS_PAD(pad0);
- u16 rx_status; /* status after reception of a packet */
- SREGS_PAD(pad1);
- u16 rx_pktlen; /* length of the packet incl. CRC */
-
- /*
- * Pointers to the location in the receive buffer area (RBA)
- * where the packet resides. A packet is always received into
- * a contiguous piece of memory.
- */
- SREGS_PAD(pad2);
- u16 rx_pktptr_l;
- SREGS_PAD(pad3);
- u16 rx_pktptr_h;
-
- SREGS_PAD(pad4);
- u16 rx_seqno; /* sequence no. */
-
- SREGS_PAD(pad5);
- u16 link; /* link to next RDD (end if EOL bit set) */
-
- /*
- * Owner of this descriptor, 0= driver, 1=sonic
- */
-
- SREGS_PAD(pad6);
- u16 in_use;
-
- caddr_t rda_next; /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
- SREGS_PAD(pad0);
- u16 tx_status; /* status after transmission of a packet */
- SREGS_PAD(pad1);
- u16 tx_config; /* transmit configuration for this packet */
- SREGS_PAD(pad2);
- u16 tx_pktsize; /* size of the packet to be transmitted */
- SREGS_PAD(pad3);
- u16 tx_frag_count; /* no. of fragments */
-
- SREGS_PAD(pad4);
- u16 tx_frag_ptr_l;
- SREGS_PAD(pad5);
- u16 tx_frag_ptr_h;
- SREGS_PAD(pad6);
- u16 tx_frag_size;
-
- SREGS_PAD(pad7);
- u16 link; /* ptr to next descriptor */
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
- SREGS_PAD(pad0);
- u16 cam_entry_pointer;
- SREGS_PAD(pad1);
- u16 cam_cap0;
- SREGS_PAD(pad2);
- u16 cam_cap1;
- SREGS_PAD(pad3);
- u16 cam_cap2;
-} sonic_cd_t;
-
+#define SONIC_EOL 0x0001
#define CAM_DESCRIPTORS 16
-
-typedef struct {
- sonic_cd_t cam_desc[CAM_DESCRIPTORS];
- SREGS_PAD(pad);
- u16 cam_enable;
-} sonic_cda_t;
-
-#else /* original declarations, little endian 32 bit */
-
-/*
- * structure definitions
- */
-
-typedef struct {
- u32 rx_bufadr_l; /* receive buffer ptr */
- u32 rx_bufadr_h;
-
- u32 rx_bufsize_l; /* no. of words in the receive buffer */
- u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
- u16 rx_status; /* status after reception of a packet */
- SREGS_PAD(pad0);
- u16 rx_pktlen; /* length of the packet incl. CRC */
- SREGS_PAD(pad1);
-
- /*
- * Pointers to the location in the receive buffer area (RBA)
- * where the packet resides. A packet is always received into
- * a contiguous piece of memory.
- */
- u16 rx_pktptr_l;
- SREGS_PAD(pad2);
- u16 rx_pktptr_h;
- SREGS_PAD(pad3);
-
- u16 rx_seqno; /* sequence no. */
- SREGS_PAD(pad4);
-
- u16 link; /* link to next RDD (end if EOL bit set) */
- SREGS_PAD(pad5);
-
- /*
- * Owner of this descriptor, 0= driver, 1=sonic
- */
-
- u16 in_use;
- SREGS_PAD(pad6);
-
- caddr_t rda_next; /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
- u16 tx_status; /* status after transmission of a packet */
- SREGS_PAD(pad0);
- u16 tx_config; /* transmit configuration for this packet */
- SREGS_PAD(pad1);
- u16 tx_pktsize; /* size of the packet to be transmitted */
- SREGS_PAD(pad2);
- u16 tx_frag_count; /* no. of fragments */
- SREGS_PAD(pad3);
-
- u16 tx_frag_ptr_l;
- SREGS_PAD(pad4);
- u16 tx_frag_ptr_h;
- SREGS_PAD(pad5);
- u16 tx_frag_size;
- SREGS_PAD(pad6);
-
- u16 link; /* ptr to next descriptor */
- SREGS_PAD(pad7);
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
- u16 cam_entry_pointer;
- SREGS_PAD(pad0);
- u16 cam_cap0;
- SREGS_PAD(pad1);
- u16 cam_cap1;
- SREGS_PAD(pad2);
- u16 cam_cap2;
- SREGS_PAD(pad3);
-} sonic_cd_t;
-
-#define CAM_DESCRIPTORS 16
-
-
-typedef struct {
- sonic_cd_t cam_desc[CAM_DESCRIPTORS];
- u16 cam_enable;
- SREGS_PAD(pad);
-} sonic_cda_t;
-#endif /* endianness */
+/* Offsets in the various DMA buffers accessed by the SONIC */
+
+#define SONIC_BITMODE16 0
+#define SONIC_BITMODE32 1
+#define SONIC_BUS_SCALE(bitmode) ((bitmode) ? 4 : 2)
+/* Note! These are all measured in bus-size units, so use SONIC_BUS_SCALE */
+#define SIZEOF_SONIC_RR 4
+#define SONIC_RR_BUFADR_L 0
+#define SONIC_RR_BUFADR_H 1
+#define SONIC_RR_BUFSIZE_L 2
+#define SONIC_RR_BUFSIZE_H 3
+
+#define SIZEOF_SONIC_RD 7
+#define SONIC_RD_STATUS 0
+#define SONIC_RD_PKTLEN 1
+#define SONIC_RD_PKTPTR_L 2
+#define SONIC_RD_PKTPTR_H 3
+#define SONIC_RD_SEQNO 4
+#define SONIC_RD_LINK 5
+#define SONIC_RD_IN_USE 6
+
+#define SIZEOF_SONIC_TD 8
+#define SONIC_TD_STATUS 0
+#define SONIC_TD_CONFIG 1
+#define SONIC_TD_PKTSIZE 2
+#define SONIC_TD_FRAG_COUNT 3
+#define SONIC_TD_FRAG_PTR_L 4
+#define SONIC_TD_FRAG_PTR_H 5
+#define SONIC_TD_FRAG_SIZE 6
+#define SONIC_TD_LINK 7
+
+#define SIZEOF_SONIC_CD 4
+#define SONIC_CD_ENTRY_POINTER 0
+#define SONIC_CD_CAP0 1
+#define SONIC_CD_CAP1 2
+#define SONIC_CD_CAP2 3
+
+#define SIZEOF_SONIC_CDA ((CAM_DESCRIPTORS * SIZEOF_SONIC_CD) + 1)
+#define SONIC_CDA_CAM_ENABLE (CAM_DESCRIPTORS * SIZEOF_SONIC_CD)
/*
* Some tunables for the buffer areas. Power of 2 is required
@@ -426,44 +270,60 @@ typedef struct {
*
* MSch: use more buffer space for the slow m68k Macs!
*/
-#ifdef CONFIG_MACSONIC
-#define SONIC_NUM_RRS 32 /* number of receive resources */
-#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS 32 /* number of transmit descriptors */
-#else
-#define SONIC_NUM_RRS 16 /* number of receive resources */
-#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS 16 /* number of transmit descriptors */
-#endif
-#define SONIC_RBSIZE 1520 /* size of one resource buffer */
+#define SONIC_NUM_RRS 16 /* number of receive resources */
+#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
+#define SONIC_NUM_TDS 16 /* number of transmit descriptors */
-#define SONIC_RDS_MASK (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK (SONIC_NUM_TDS-1)
+#define SONIC_RDS_MASK (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK (SONIC_NUM_TDS-1)
+#define SONIC_RBSIZE 1520 /* size of one resource buffer */
+
+/* Again, measured in bus size units! */
+#define SIZEOF_SONIC_DESC (SIZEOF_SONIC_CDA \
+ + (SIZEOF_SONIC_TD * SONIC_NUM_TDS) \
+ + (SIZEOF_SONIC_RD * SONIC_NUM_RDS) \
+ + (SIZEOF_SONIC_RR * SONIC_NUM_RRS))
/* Information that need to be kept for each board. */
struct sonic_local {
- sonic_cda_t cda; /* virtual CPU address of CDA */
- sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */
- sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource area */
- sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */
- struct sk_buff *tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
- unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
- unsigned char *rba; /* start of receive buffer areas */
- unsigned int cda_laddr; /* logical DMA address of CDA */
- unsigned int tda_laddr; /* logical DMA address of TDA */
- unsigned int rra_laddr; /* logical DMA address of RRA */
- unsigned int rda_laddr; /* logical DMA address of RDA */
- unsigned int rba_laddr; /* logical DMA address of RBA */
- unsigned int cur_rra; /* current indexes to resource areas */
+ /* Bus size. 0 == 16 bits, 1 == 32 bits. */
+ int dma_bitmode;
+ /* Register offset within the longword (independent of endianness,
+ and varies from one type of Macintosh SONIC to another
+ (Aarrgh)) */
+ int reg_offset;
+ void *descriptors;
+ /* Crud. These areas have to be within the same 64K. Therefore
+ we allocate a desriptors page, and point these to places within it. */
+ void *cda; /* CAM descriptor area */
+ void *tda; /* Transmit descriptor area */
+ void *rra; /* Receive resource area */
+ void *rda; /* Receive descriptor area */
+ struct sk_buff* volatile rx_skb[SONIC_NUM_RRS]; /* packets to be received */
+ struct sk_buff* volatile tx_skb[SONIC_NUM_TDS]; /* packets to be transmitted */
+ unsigned int tx_len[SONIC_NUM_TDS]; /* lengths of tx DMA mappings */
+ /* Logical DMA addresses on MIPS, bus addresses on m68k
+ * (so "laddr" is a bit misleading) */
+ dma_addr_t descriptors_laddr;
+ u32 cda_laddr; /* logical DMA address of CDA */
+ u32 tda_laddr; /* logical DMA address of TDA */
+ u32 rra_laddr; /* logical DMA address of RRA */
+ u32 rda_laddr; /* logical DMA address of RDA */
+ dma_addr_t rx_laddr[SONIC_NUM_RRS]; /* logical DMA addresses of rx skbuffs */
+ dma_addr_t tx_laddr[SONIC_NUM_TDS]; /* logical DMA addresses of tx skbuffs */
+ unsigned int rra_end;
+ unsigned int cur_rwp;
unsigned int cur_rx;
- unsigned int cur_tx;
- unsigned int dirty_tx; /* last unacked transmit packet */
- char tx_full;
+ unsigned int cur_tx; /* first unacked transmit packet */
+ unsigned int eol_rx;
+ unsigned int eol_tx; /* last unacked transmit packet */
+ unsigned int next_tx; /* next free TD */
+ struct device *device; /* generic device */
struct net_device_stats stats;
};
-#define TX_TIMEOUT 6
+#define TX_TIMEOUT (3 * HZ)
/* Index to functions, as function prototypes. */
@@ -477,6 +337,114 @@ static void sonic_multicast_list(struct net_device *dev);
static int sonic_init(struct net_device *dev);
static void sonic_tx_timeout(struct net_device *dev);
+/* Internal inlines for reading/writing DMA buffers. Note that bus
+ size and endianness matter here, whereas they don't for registers,
+ as far as we can tell. */
+/* OpenBSD calls this "SWO". I'd like to think that sonic_buf_put()
+ is a much better name. */
+static inline void sonic_buf_put(void* base, int bitmode,
+ int offset, __u16 val)
+{
+ if (bitmode)
+#ifdef __BIG_ENDIAN
+ ((__u16 *) base + (offset*2))[1] = val;
+#else
+ ((__u16 *) base + (offset*2))[0] = val;
+#endif
+ else
+ ((__u16 *) base)[offset] = val;
+}
+
+static inline __u16 sonic_buf_get(void* base, int bitmode,
+ int offset)
+{
+ if (bitmode)
+#ifdef __BIG_ENDIAN
+ return ((volatile __u16 *) base + (offset*2))[1];
+#else
+ return ((volatile __u16 *) base + (offset*2))[0];
+#endif
+ else
+ return ((volatile __u16 *) base)[offset];
+}
+
+/* Inlines that you should actually use for reading/writing DMA buffers */
+static inline void sonic_cda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->cda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_CD) + offset, val);
+}
+
+static inline __u16 sonic_cda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->cda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_CD) + offset);
+}
+
+static inline void sonic_set_cam_enable(struct net_device* dev, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE, val);
+}
+
+static inline __u16 sonic_get_cam_enable(struct net_device* dev)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE);
+}
+
+static inline void sonic_tda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->tda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_TD) + offset, val);
+}
+
+static inline __u16 sonic_tda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->tda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_TD) + offset);
+}
+
+static inline void sonic_rda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->rda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RD) + offset, val);
+}
+
+static inline __u16 sonic_rda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->rda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RD) + offset);
+}
+
+static inline void sonic_rra_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->rra, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RR) + offset, val);
+}
+
+static inline __u16 sonic_rra_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->rra, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RR) + offset);
+}
+
static const char *version =
"sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
new file mode 100644
index 000000000000..4e19220473d0
--- /dev/null
+++ b/drivers/net/spider_net.c
@@ -0,0 +1,2334 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/if_vlan.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <asm/bitops.h>
+#include <asm/pci-bridge.h>
+#include <net/checksum.h>
+
+#include "spider_net.h"
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com> and Jens Osterkamp " \
+ "<Jens.Osterkamp@de.ibm.com>");
+MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
+static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
+
+module_param(rx_descriptors, int, 0644);
+module_param(tx_descriptors, int, 0644);
+
+MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \
+ "in rx chains");
+MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \
+ "in tx chain");
+
+char spider_net_driver_name[] = "spidernet";
+
+static struct pci_device_id spider_net_pci_tbl[] = {
+ { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);
+
+/**
+ * spider_net_read_reg - reads an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to read from
+ *
+ * returns the content of the specified SMMIO register.
+ */
+static u32
+spider_net_read_reg(struct spider_net_card *card, u32 reg)
+{
+ u32 value;
+
+ value = readl(card->regs + reg);
+ value = le32_to_cpu(value);
+
+ return value;
+}
+
+/**
+ * spider_net_write_reg - writes to an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to write to
+ * @value: value to write into the specified SMMIO register
+ */
+static void
+spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
+{
+ value = cpu_to_le32(value);
+ writel(value, card->regs + reg);
+}
+
+/**
+ * spider_net_write_reg_sync - writes to an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to write to
+ * @value: value to write into the specified SMMIO register
+ *
+ * Unlike spider_net_write_reg, this will also make sure the
+ * data arrives on the card by reading the reg again.
+ */
+static void
+spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
+{
+ value = cpu_to_le32(value);
+ writel(value, card->regs + reg);
+ (void)readl(card->regs + reg);
+}
+
+/**
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
+ * @card: device structure
+ *
+ * switches off rx irq by masking them out in the GHIINTnMSK register
+ */
+static void
+spider_net_rx_irq_off(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue &= ~SPIDER_NET_RXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/** spider_net_write_phy - write to phy register
+ * @netdev: adapter to be written to
+ * @mii_id: id of MII
+ * @reg: PHY register
+ * @val: value to be written to phy register
+ *
+ * spider_net_write_phy_register writes to an arbitrary PHY
+ * register via the spider GPCWOPCMD register. We assume the queue does
+ * not run full (not more than 15 commands outstanding).
+ **/
+static void
+spider_net_write_phy(struct net_device *netdev, int mii_id,
+ int reg, int val)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 writevalue;
+
+ writevalue = ((u32)mii_id << 21) |
+ ((u32)reg << 16) | ((u32)val);
+
+ spider_net_write_reg(card, SPIDER_NET_GPCWOPCMD, writevalue);
+}
+
+/** spider_net_read_phy - read from phy register
+ * @netdev: network device to be read from
+ * @mii_id: id of MII
+ * @reg: PHY register
+ *
+ * Returns value read from PHY register
+ *
+ * spider_net_write_phy reads from an arbitrary PHY
+ * register via the spider GPCROPCMD register
+ **/
+static int
+spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 readvalue;
+
+ readvalue = ((u32)mii_id << 21) | ((u32)reg << 16);
+ spider_net_write_reg(card, SPIDER_NET_GPCROPCMD, readvalue);
+
+ /* we don't use semaphores to wait for an SPIDER_NET_GPROPCMPINT
+ * interrupt, as we poll for the completion of the read operation
+ * in spider_net_read_phy. Should take about 50 us */
+ do {
+ readvalue = spider_net_read_reg(card, SPIDER_NET_GPCROPCMD);
+ } while (readvalue & SPIDER_NET_GPREXEC);
+
+ readvalue &= SPIDER_NET_GPRDAT_MASK;
+
+ return readvalue;
+}
+
+/**
+ * spider_net_rx_irq_on - switch on rx irq on this spider card
+ * @card: device structure
+ *
+ * switches on rx irq by enabling them in the GHIINTnMSK register
+ */
+static void
+spider_net_rx_irq_on(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue |= SPIDER_NET_RXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_tx_irq_off - switch off tx irq on this spider card
+ * @card: device structure
+ *
+ * switches off tx irq by masking them out in the GHIINTnMSK register
+ */
+static void
+spider_net_tx_irq_off(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue &= ~SPIDER_NET_TXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_tx_irq_on - switch on tx irq on this spider card
+ * @card: device structure
+ *
+ * switches on tx irq by enabling them in the GHIINTnMSK register
+ */
+static void
+spider_net_tx_irq_on(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue |= SPIDER_NET_TXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_set_promisc - sets the unicast address or the promiscuous mode
+ * @card: card structure
+ *
+ * spider_net_set_promisc sets the unicast destination address filter and
+ * thus either allows for non-promisc mode or promisc mode
+ */
+static void
+spider_net_set_promisc(struct spider_net_card *card)
+{
+ u32 macu, macl;
+ struct net_device *netdev = card->netdev;
+
+ if (netdev->flags & IFF_PROMISC) {
+ /* clear destination entry 0 */
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
+ SPIDER_NET_PROMISC_VALUE);
+ } else {
+ macu = netdev->dev_addr[0];
+ macu <<= 8;
+ macu |= netdev->dev_addr[1];
+ memcpy(&macl, &netdev->dev_addr[2], sizeof(macl));
+
+ macu |= SPIDER_NET_UA_DESCR_VALUE;
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, macu);
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, macl);
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
+ SPIDER_NET_NONPROMISC_VALUE);
+ }
+}
+
+/**
+ * spider_net_get_mac_address - read mac address from spider card
+ * @card: device structure
+ *
+ * reads MAC address from GMACUNIMACU and GMACUNIMACL registers
+ */
+static int
+spider_net_get_mac_address(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 macl, macu;
+
+ macl = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACL);
+ macu = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACU);
+
+ netdev->dev_addr[0] = (macu >> 24) & 0xff;
+ netdev->dev_addr[1] = (macu >> 16) & 0xff;
+ netdev->dev_addr[2] = (macu >> 8) & 0xff;
+ netdev->dev_addr[3] = macu & 0xff;
+ netdev->dev_addr[4] = (macl >> 8) & 0xff;
+ netdev->dev_addr[5] = macl & 0xff;
+
+ if (!is_valid_ether_addr(&netdev->dev_addr[0]))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * spider_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum spider_net_descr_status
+spider_net_get_descr_status(struct spider_net_descr *descr)
+{
+ u32 cmd_status;
+ rmb();
+ cmd_status = descr->dmac_cmd_status;
+ rmb();
+ cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
+ /* no need to mask out any bits, as cmd_status is 32 bits wide only
+ * (and unsigned) */
+ return cmd_status;
+}
+
+/**
+ * spider_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void
+spider_net_set_descr_status(struct spider_net_descr *descr,
+ enum spider_net_descr_status status)
+{
+ u32 cmd_status;
+ /* read the status */
+ mb();
+ cmd_status = descr->dmac_cmd_status;
+ /* clean the upper 4 bits */
+ cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
+ /* add the status to it */
+ cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
+ /* and write it back */
+ descr->dmac_cmd_status = cmd_status;
+ wmb();
+}
+
+/**
+ * spider_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ *
+ */
+static void
+spider_net_free_chain(struct spider_net_card *card,
+ struct spider_net_descr_chain *chain)
+{
+ struct spider_net_descr *descr;
+
+ for (descr = chain->tail; !descr->bus_addr; descr = descr->next) {
+ pci_unmap_single(card->pdev, descr->bus_addr,
+ SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+ descr->bus_addr = 0;
+ }
+}
+
+/**
+ * spider_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_init_chain(struct spider_net_card *card,
+ struct spider_net_descr_chain *chain,
+ struct spider_net_descr *start_descr, int no)
+{
+ int i;
+ struct spider_net_descr *descr;
+
+ spin_lock_init(&card->chain_lock);
+
+ descr = start_descr;
+ memset(descr, 0, sizeof(*descr) * no);
+
+ /* set up the hardware pointers in each descriptor */
+ for (i=0; i<no; i++, descr++) {
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+
+ descr->bus_addr =
+ pci_map_single(card->pdev, descr,
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+
+ if (descr->bus_addr == DMA_ERROR_CODE)
+ goto iommu_error;
+
+ descr->next = descr + 1;
+ descr->prev = descr - 1;
+
+ }
+ /* do actual circular list */
+ (descr-1)->next = start_descr;
+ start_descr->prev = descr-1;
+
+ descr = start_descr;
+ for (i=0; i < no; i++, descr++) {
+ descr->next_descr_addr = descr->next->bus_addr;
+ }
+
+ chain->head = start_descr;
+ chain->tail = start_descr;
+
+ return 0;
+
+iommu_error:
+ descr = start_descr;
+ for (i=0; i < no; i++, descr++)
+ if (descr->bus_addr)
+ pci_unmap_single(card->pdev, descr->bus_addr,
+ SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+ return -ENOMEM;
+}
+
+/**
+ * spider_net_free_rx_chain_contents - frees descr contents in rx chain
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static void
+spider_net_free_rx_chain_contents(struct spider_net_card *card)
+{
+ struct spider_net_descr *descr;
+
+ descr = card->rx_chain.head;
+ while (descr->next != card->rx_chain.head) {
+ if (descr->skb) {
+ dev_kfree_skb(descr->skb);
+ pci_unmap_single(card->pdev, descr->buf_addr,
+ SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+ }
+ descr = descr->next;
+ }
+}
+
+/**
+ * spider_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int
+spider_net_prepare_rx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ int error = 0;
+ int offset;
+ int bufsize;
+
+ /* we need to round up the buffer size to a multiple of 128 */
+ bufsize = (SPIDER_NET_MAX_MTU + SPIDER_NET_RXBUF_ALIGN - 1) &
+ (~(SPIDER_NET_RXBUF_ALIGN - 1));
+
+ /* and we need to have it 128 byte aligned, therefore we allocate a
+ * bit more */
+ /* allocate an skb */
+ descr->skb = dev_alloc_skb(bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
+ if (!descr->skb) {
+ if (net_ratelimit())
+ if (netif_msg_rx_err(card))
+ pr_err("Not enough memory to allocate "
+ "rx buffer\n");
+ return -ENOMEM;
+ }
+ descr->buf_size = bufsize;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_status = 0;
+ descr->data_error = 0;
+
+ offset = ((unsigned long)descr->skb->data) &
+ (SPIDER_NET_RXBUF_ALIGN - 1);
+ if (offset)
+ skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
+ /* io-mmu-map the skb */
+ descr->buf_addr = pci_map_single(card->pdev, descr->skb->data,
+ SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+ if (descr->buf_addr == DMA_ERROR_CODE) {
+ dev_kfree_skb_any(descr->skb);
+ if (netif_msg_rx_err(card))
+ pr_err("Could not iommu-map rx buffer\n");
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ } else {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_RX_CARDOWNED;
+ }
+
+ return error;
+}
+
+/**
+ * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * @card: card structure
+ *
+ * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * chip by writing to the appropriate register. DMA is enabled in
+ * spider_net_enable_rxdmac.
+ */
+static void
+spider_net_enable_rxchtails(struct spider_net_card *card)
+{
+ /* assume chain is aligned correctly */
+ spider_net_write_reg(card, SPIDER_NET_GDADCHA ,
+ card->rx_chain.tail->bus_addr);
+}
+
+/**
+ * spider_net_enable_rxdmac - enables a receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static void
+spider_net_enable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_VALUE);
+}
+
+/**
+ * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * refills descriptors in all chains (last used chain first): allocates skbs
+ * and iommu-maps them.
+ */
+static void
+spider_net_refill_rx_chain(struct spider_net_card *card)
+{
+ struct spider_net_descr_chain *chain;
+ int count = 0;
+ unsigned long flags;
+
+ chain = &card->rx_chain;
+
+ spin_lock_irqsave(&card->chain_lock, flags);
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ count++;
+ chain->head = chain->head->next;
+ }
+ spin_unlock_irqrestore(&card->chain_lock, flags);
+
+ /* could be optimized, only do that, if we know the DMA processing
+ * has terminated */
+ if (count)
+ spider_net_enable_rxdmac(card);
+}
+
+/**
+ * spider_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_alloc_rx_skbs(struct spider_net_card *card)
+{
+ int result;
+ struct spider_net_descr_chain *chain;
+
+ result = -ENOMEM;
+
+ chain = &card->rx_chain;
+ /* put at least one buffer into the chain. if this fails,
+ * we've got a problem. if not, spider_net_refill_rx_chain
+ * will do the rest at the end of this function */
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ goto error;
+ else
+ chain->head = chain->head->next;
+
+ /* this will allocate the rest of the rx buffers; if not, it's
+ * business as usual later on */
+ spider_net_refill_rx_chain(card);
+ return 0;
+
+error:
+ spider_net_free_rx_chain_contents(card);
+ return result;
+}
+
+/**
+ * spider_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void
+spider_net_release_tx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ struct sk_buff *skb;
+
+ /* unmap the skb */
+ skb = descr->skb;
+ pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
+ PCI_DMA_BIDIRECTIONAL);
+
+ dev_kfree_skb_any(skb);
+
+ /* set status to not used */
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+}
+
+/**
+ * spider_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @brutal: if set, don't care about whether descriptor seems to be in use
+ *
+ * releases the tx descriptors that spider has finished with (if non-brutal)
+ * or simply release tx descriptors (if brutal)
+ */
+static void
+spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
+{
+ struct spider_net_descr_chain *tx_chain = &card->tx_chain;
+ enum spider_net_descr_status status;
+
+ spider_net_tx_irq_off(card);
+
+ /* no lock for chain needed, if this is only executed once at a time */
+again:
+ for (;;) {
+ status = spider_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case SPIDER_NET_DESCR_CARDOWNED:
+ if (!brutal) goto out;
+ /* fallthrough, if we release the descriptors
+ * brutally (then we don't care about
+ * SPIDER_NET_DESCR_CARDOWNED) */
+ case SPIDER_NET_DESCR_RESPONSE_ERROR:
+ case SPIDER_NET_DESCR_PROTECTION_ERROR:
+ case SPIDER_NET_DESCR_FORCE_END:
+ if (netif_msg_tx_err(card))
+ pr_err("%s: forcing end of tx descriptor "
+ "with status x%02x\n",
+ card->netdev->name, status);
+ card->netdev_stats.tx_dropped++;
+ break;
+
+ case SPIDER_NET_DESCR_COMPLETE:
+ card->netdev_stats.tx_packets++;
+ card->netdev_stats.tx_bytes +=
+ tx_chain->tail->skb->len;
+ break;
+
+ default: /* any other value (== SPIDER_NET_DESCR_NOT_IN_USE) */
+ goto out;
+ }
+ spider_net_release_tx_descr(card, tx_chain->tail);
+ tx_chain->tail = tx_chain->tail->next;
+ }
+out:
+ netif_wake_queue(card->netdev);
+
+ if (!brutal) {
+ /* switch on tx irqs (while we are still in the interrupt
+ * handler, so we don't get an interrupt), check again
+ * for done descriptors. This results in fewer interrupts */
+ spider_net_tx_irq_on(card);
+ status = spider_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case SPIDER_NET_DESCR_RESPONSE_ERROR:
+ case SPIDER_NET_DESCR_PROTECTION_ERROR:
+ case SPIDER_NET_DESCR_FORCE_END:
+ case SPIDER_NET_DESCR_COMPLETE:
+ goto again;
+ default:
+ break;
+ }
+ }
+
+}
+
+/**
+ * spider_net_get_multicast_hash - generates hash for multicast filter table
+ * @addr: multicast address
+ *
+ * returns the hash value.
+ *
+ * spider_net_get_multicast_hash calculates a hash value for a given multicast
+ * address, that is used to set the multicast filter tables
+ */
+static u8
+spider_net_get_multicast_hash(struct net_device *netdev, __u8 *addr)
+{
+ /* FIXME: an addr of 01:00:5e:00:00:01 must result in 0xa9,
+ * ff:ff:ff:ff:ff:ff must result in 0xfd */
+ u32 crc;
+ u8 hash;
+
+ crc = crc32_be(~0, addr, netdev->addr_len);
+
+ hash = (crc >> 27);
+ hash <<= 3;
+ hash |= crc & 7;
+
+ return hash;
+}
+
+/**
+ * spider_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * spider_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void
+spider_net_set_multi(struct net_device *netdev)
+{
+ struct dev_mc_list *mc;
+ u8 hash;
+ int i;
+ u32 reg;
+ struct spider_net_card *card = netdev_priv(netdev);
+ unsigned long bitmask[SPIDER_NET_MULTICAST_HASHES / BITS_PER_LONG] =
+ {0, };
+
+ spider_net_set_promisc(card);
+
+ if (netdev->flags & IFF_ALLMULTI) {
+ for (i = 0; i < SPIDER_NET_MULTICAST_HASHES; i++) {
+ set_bit(i, bitmask);
+ }
+ goto write_hash;
+ }
+
+ /* well, we know, what the broadcast hash value is: it's xfd
+ hash = spider_net_get_multicast_hash(netdev, netdev->broadcast); */
+ set_bit(0xfd, bitmask);
+
+ for (mc = netdev->mc_list; mc; mc = mc->next) {
+ hash = spider_net_get_multicast_hash(netdev, mc->dmi_addr);
+ set_bit(hash, bitmask);
+ }
+
+write_hash:
+ for (i = 0; i < SPIDER_NET_MULTICAST_HASHES / 4; i++) {
+ reg = 0;
+ if (test_bit(i * 4, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 1, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 2, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 3, bitmask))
+ reg += 0x08;
+
+ spider_net_write_reg(card, SPIDER_NET_GMRMHFILnR + i * 4, reg);
+ }
+}
+
+/**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
+ * spider_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+int
+spider_net_stop(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+
+ netif_poll_disable(netdev);
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ /* disable/mask all interrupts */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+
+ /* free_irq(netdev->irq, netdev);*/
+ free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_FEND_VALUE);
+
+ /* turn off DMA, force end */
+ spider_net_disable_rxdmac(card);
+
+ /* release chains */
+ spider_net_release_tx_chain(card, 1);
+
+ spider_net_free_chain(card, &card->tx_chain);
+ spider_net_free_chain(card, &card->rx_chain);
+
+ return 0;
+}
+
+/**
+ * spider_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct spider_net_descr *
+spider_net_get_next_tx_descr(struct spider_net_card *card)
+{
+ /* check, if head points to not-in-use descr */
+ if ( spider_net_get_descr_status(card->tx_chain.head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE ) {
+ return card->tx_chain.head;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * spider_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void
+spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
+ struct sk_buff *skb)
+{
+ if (skb->ip_summed != CHECKSUM_HW) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
+ return;
+ }
+
+ /* is packet ip?
+ * if yes: tcp? udp? */
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
+ } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
+ } else { /* the stack should checksum non-tcp and non-udp
+ packets on his own: NETIF_F_IP_CSUM */
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
+ }
+ }
+}
+
+/**
+ * spider_net_prepare_tx_descr - fill tx descriptor with skb data
+ * @card: card structure
+ * @descr: descriptor structure to fill out
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ * fills out the descriptor structure with skb data and len. Copies data,
+ * if needed (32bit DMA!)
+ */
+static int
+spider_net_prepare_tx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr,
+ struct sk_buff *skb)
+{
+ descr->buf_addr = pci_map_single(card->pdev, skb->data,
+ skb->len, PCI_DMA_BIDIRECTIONAL);
+ if (descr->buf_addr == DMA_ERROR_CODE) {
+ if (netif_msg_tx_err(card))
+ pr_err("could not iommu-map packet (%p, %i). "
+ "Dropping packet\n", skb->data, skb->len);
+ return -ENOMEM;
+ }
+
+ descr->buf_size = skb->len;
+ descr->skb = skb;
+ descr->data_status = 0;
+
+ /* make sure the above values are in memory before we change the
+ * status */
+ wmb();
+
+ spider_net_set_txdescr_cmdstat(descr,skb);
+
+ return 0;
+}
+
+/**
+ * spider_net_kick_tx_dma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ * spider_net_kick_tx_dma writes the current tx chain head as start address
+ * of the tx descriptor chain and enables the transmission DMA engine
+ */
+static void
+spider_net_kick_tx_dma(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ /* this is the only descriptor in the output chain.
+ * Enable TX DMA */
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+ descr->bus_addr);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_VALUE);
+}
+
+/**
+ * spider_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ struct spider_net_descr *descr;
+ int result;
+
+ descr = spider_net_get_next_tx_descr(card);
+
+ if (!descr) {
+ netif_stop_queue(netdev);
+
+ descr = spider_net_get_next_tx_descr(card);
+ if (!descr)
+ goto error;
+ else
+ netif_start_queue(netdev);
+ }
+
+ result = spider_net_prepare_tx_descr(card, descr, skb);
+ if (result)
+ goto error;
+
+ card->tx_chain.head = card->tx_chain.head->next;
+
+ /* make sure the status from spider_net_prepare_tx_descr is in
+ * memory before we check out the previous descriptor */
+ wmb();
+
+ if (spider_net_get_descr_status(descr->prev) !=
+ SPIDER_NET_DESCR_CARDOWNED)
+ spider_net_kick_tx_dma(card, descr);
+
+ return NETDEV_TX_OK;
+
+error:
+ card->netdev_stats.tx_dropped++;
+ return NETDEV_TX_LOCKED;
+}
+
+/**
+ * spider_net_do_ioctl - called for device ioctls
+ * @netdev: interface device structure
+ * @ifr: request parameter structure for ioctl
+ * @cmd: command code for ioctl
+ *
+ * returns 0 on success, <0 on failure. Currently, we have no special ioctls.
+ * -EOPNOTSUPP is returned, if an unknown ioctl was requested
+ */
+static int
+spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * returns 1 on success, 0 if no packet was passed to the stack
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static int
+spider_net_pass_skb_up(struct spider_net_descr *descr,
+ struct spider_net_card *card)
+{
+ struct sk_buff *skb;
+ struct net_device *netdev;
+ u32 data_status, data_error;
+
+ data_status = descr->data_status;
+ data_error = descr->data_error;
+
+ netdev = card->netdev;
+
+ /* check for errors in the data_error flag */
+ if ((data_error & SPIDER_NET_DATA_ERROR_MASK) &&
+ netif_msg_rx_err(card))
+ pr_err("error in received descriptor found, "
+ "data_status=x%08x, data_error=x%08x\n",
+ data_status, data_error);
+
+ /* prepare skb, unmap descriptor */
+ skb = descr->skb;
+ pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+
+ /* the cases we'll throw away the packet immediately */
+ if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+ return 0;
+
+ skb->dev = netdev;
+ skb_put(skb, descr->valid_size);
+
+ /* the card seems to add 2 bytes of junk in front
+ * of the ethernet frame */
+#define SPIDER_MISALIGN 2
+ skb_pull(skb, SPIDER_MISALIGN);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ /* checksum offload */
+ if (card->options.rx_csum) {
+ if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
+ (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
+ if (data_status & SPIDER_NET_VLAN_PACKET) {
+ /* further enhancements: HW-accel VLAN
+ * vlan_hwaccel_receive_skb
+ */
+ }
+
+ /* pass skb up to stack */
+ netif_receive_skb(skb);
+
+ /* update netdevice statistics */
+ card->netdev_stats.rx_packets++;
+ card->netdev_stats.rx_bytes += skb->len;
+
+ return 1;
+}
+
+/**
+ * spider_net_decode_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int
+spider_net_decode_one_descr(struct spider_net_card *card)
+{
+ enum spider_net_descr_status status;
+ struct spider_net_descr *descr;
+ struct spider_net_descr_chain *chain;
+ int result;
+
+ chain = &card->rx_chain;
+ descr = chain->tail;
+
+ status = spider_net_get_descr_status(descr);
+
+ if (status == SPIDER_NET_DESCR_CARDOWNED) {
+ /* nothing in the descriptor yet */
+ return 0;
+ }
+
+ if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
+ /* not initialized yet, I bet chain->tail == chain->head
+ * and the ring is empty */
+ spider_net_refill_rx_chain(card);
+ return 0;
+ }
+
+ /* descriptor definitively used -- move on head */
+ chain->tail = descr->next;
+
+ result = 0;
+ if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
+ (status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
+ (status == SPIDER_NET_DESCR_FORCE_END) ) {
+ if (netif_msg_rx_err(card))
+ pr_err("%s: dropping RX descriptor with state %d\n",
+ card->netdev->name, status);
+ card->netdev_stats.rx_dropped++;
+ goto refill;
+ }
+
+ if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
+ (status != SPIDER_NET_DESCR_FRAME_END) ) {
+ if (netif_msg_rx_err(card))
+ pr_err("%s: RX descriptor with state %d\n",
+ card->netdev->name, status);
+ goto refill;
+ }
+
+ /* ok, we've got a packet in descr */
+ result = spider_net_pass_skb_up(descr, card);
+refill:
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ /* change the descriptor state: */
+ spider_net_refill_rx_chain(card);
+
+ return result;
+}
+
+/**
+ * spider_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ * spider_net_poll returns all packets from the rx descriptors to the stack
+ * (using netif_receive_skb). If all/enough packets are up, the driver
+ * reenables interrupts and returns 0. If not, 1 is returned.
+ */
+static int
+spider_net_poll(struct net_device *netdev, int *budget)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ int packets_to_do, packets_done = 0;
+ int no_more_packets = 0;
+
+ packets_to_do = min(*budget, netdev->quota);
+
+ while (packets_to_do) {
+ if (spider_net_decode_one_descr(card)) {
+ packets_done++;
+ packets_to_do--;
+ } else {
+ /* no more packets for the stack */
+ no_more_packets = 1;
+ break;
+ }
+ }
+
+ netdev->quota -= packets_done;
+ *budget -= packets_done;
+
+ /* if all packets are in the stack, enable interrupts and return 0 */
+ /* if not, return 1 */
+ if (no_more_packets) {
+ netif_rx_complete(netdev);
+ spider_net_rx_irq_on(card);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * spider_net_vlan_rx_reg - initializes VLAN structures in the driver and card
+ * @netdev: interface device structure
+ * @grp: vlan_group structure that is registered (NULL on destroying interface)
+ */
+static void
+spider_net_vlan_rx_reg(struct net_device *netdev, struct vlan_group *grp)
+{
+ /* further enhancement... yet to do */
+ return;
+}
+
+/**
+ * spider_net_vlan_rx_add - adds VLAN id to the card filter
+ * @netdev: interface device structure
+ * @vid: VLAN id to add
+ */
+static void
+spider_net_vlan_rx_add(struct net_device *netdev, uint16_t vid)
+{
+ /* further enhancement... yet to do */
+ /* add vid to card's VLAN filter table */
+ return;
+}
+
+/**
+ * spider_net_vlan_rx_kill - removes VLAN id to the card filter
+ * @netdev: interface device structure
+ * @vid: VLAN id to remove
+ */
+static void
+spider_net_vlan_rx_kill(struct net_device *netdev, uint16_t vid)
+{
+ /* further enhancement... yet to do */
+ /* remove vid from card's VLAN filter table */
+}
+
+/**
+ * spider_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the spider_net_card struct
+ */
+static struct net_device_stats *
+spider_net_get_stats(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ struct net_device_stats *stats = &card->netdev_stats;
+ return stats;
+}
+
+/**
+ * spider_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+ * and mtu is outbound only anyway */
+ if ( (new_mtu < SPIDER_NET_MIN_MTU ) ||
+ (new_mtu > SPIDER_NET_MAX_MTU) )
+ return -EINVAL;
+ netdev->mtu = new_mtu;
+ return 0;
+}
+
+/**
+ * spider_net_set_mac - sets the MAC of an interface
+ * @netdev: interface device structure
+ * @ptr: pointer to new MAC address
+ *
+ * Returns 0 on success, <0 on failure. Currently, we don't support this
+ * and will always return EOPNOTSUPP.
+ */
+static int
+spider_net_set_mac(struct net_device *netdev, void *p)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 macl, macu, regvalue;
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ /* switch off GMACTPE and GMACRPE */
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+ regvalue &= ~((1 << 5) | (1 << 6));
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
+ /* write mac */
+ macu = (addr->sa_data[0]<<24) + (addr->sa_data[1]<<16) +
+ (addr->sa_data[2]<<8) + (addr->sa_data[3]);
+ macl = (addr->sa_data[4]<<8) + (addr->sa_data[5]);
+ spider_net_write_reg(card, SPIDER_NET_GMACUNIMACU, macu);
+ spider_net_write_reg(card, SPIDER_NET_GMACUNIMACL, macl);
+
+ /* switch GMACTPE and GMACRPE back on */
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+ regvalue |= ((1 << 5) | (1 << 6));
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
+ spider_net_set_promisc(card);
+
+ /* look up, whether we have been successful */
+ if (spider_net_get_mac_address(netdev))
+ return -EADDRNOTAVAIL;
+ if (memcmp(netdev->dev_addr,addr->sa_data,netdev->addr_len))
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+
+/**
+ * spider_net_enable_txdmac - enables a TX DMA controller
+ * @card: card structure
+ *
+ * spider_net_enable_txdmac enables the TX DMA controller by setting the
+ * descriptor chain tail address
+ */
+static void
+spider_net_enable_txdmac(struct spider_net_card *card)
+{
+ /* assume chain is aligned correctly */
+ spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+ card->tx_chain.tail->bus_addr);
+}
+
+/**
+ * spider_net_handle_error_irq - handles errors raised by an interrupt
+ * @card: card structure
+ * @status_reg: interrupt status register 0 (GHIINT0STS)
+ *
+ * spider_net_handle_error_irq treats or ignores all error conditions
+ * found when an interrupt is presented
+ */
+static void
+spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
+{
+ u32 error_reg1, error_reg2;
+ u32 i;
+ int show_error = 1;
+
+ error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
+ error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+
+ /* check GHIINT0STS ************************************/
+ if (status_reg)
+ for (i = 0; i < 32; i++)
+ if (status_reg & (1<<i))
+ switch (i)
+ {
+ /* let error_reg1 and error_reg2 evaluation decide, what to do
+ case SPIDER_NET_PHYINT:
+ case SPIDER_NET_GMAC2INT:
+ case SPIDER_NET_GMAC1INT:
+ case SPIDER_NET_GIPSINT:
+ case SPIDER_NET_GFIFOINT:
+ case SPIDER_NET_DMACINT:
+ case SPIDER_NET_GSYSINT:
+ break; */
+
+ case SPIDER_NET_GPWOPCMPINT:
+ /* PHY write operation completed */
+ show_error = 0;
+ break;
+ case SPIDER_NET_GPROPCMPINT:
+ /* PHY read operation completed */
+ /* we don't use semaphores, as we poll for the completion
+ * of the read operation in spider_net_read_phy. Should take
+ * about 50 us */
+ show_error = 0;
+ break;
+ case SPIDER_NET_GPWFFINT:
+ /* PHY command queue full */
+ if (netif_msg_intr(card))
+ pr_err("PHY write queue full\n");
+ show_error = 0;
+ break;
+
+ /* case SPIDER_NET_GRMDADRINT: not used. print a message */
+ /* case SPIDER_NET_GRMARPINT: not used. print a message */
+ /* case SPIDER_NET_GRMMPINT: not used. print a message */
+
+ case SPIDER_NET_GDTDEN0INT:
+ /* someone has set TX_DMA_EN to 0 */
+ show_error = 0;
+ break;
+
+ case SPIDER_NET_GDDDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDCDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDBDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDADEN0INT:
+ /* someone has set RX_DMA_EN to 0 */
+ show_error = 0;
+ break;
+
+ /* RX interrupts */
+ case SPIDER_NET_GDDFDCINT:
+ case SPIDER_NET_GDCFDCINT:
+ case SPIDER_NET_GDBFDCINT:
+ case SPIDER_NET_GDAFDCINT:
+ /* case SPIDER_NET_GDNMINT: not used. print a message */
+ /* case SPIDER_NET_GCNMINT: not used. print a message */
+ /* case SPIDER_NET_GBNMINT: not used. print a message */
+ /* case SPIDER_NET_GANMINT: not used. print a message */
+ /* case SPIDER_NET_GRFNMINT: not used. print a message */
+ show_error = 0;
+ break;
+
+ /* TX interrupts */
+ case SPIDER_NET_GDTFDCINT:
+ show_error = 0;
+ break;
+ case SPIDER_NET_GTTEDINT:
+ show_error = 0;
+ break;
+ case SPIDER_NET_GDTDCEINT:
+ /* chain end. If a descriptor should be sent, kick off
+ * tx dma
+ if (card->tx_chain.tail == card->tx_chain.head)
+ spider_net_kick_tx_dma(card);
+ show_error = 0; */
+ break;
+
+ /* case SPIDER_NET_G1TMCNTINT: not used. print a message */
+ /* case SPIDER_NET_GFREECNTINT: not used. print a message */
+ }
+
+ /* check GHIINT1STS ************************************/
+ if (error_reg1)
+ for (i = 0; i < 32; i++)
+ if (error_reg1 & (1<<i))
+ switch (i)
+ {
+ case SPIDER_NET_GTMFLLINT:
+ if (netif_msg_intr(card))
+ pr_err("Spider TX RAM full\n");
+ show_error = 0;
+ break;
+ case SPIDER_NET_GRMFLLINT:
+ if (netif_msg_intr(card))
+ pr_err("Spider RX RAM full, incoming packets "
+ "might be discarded !\n");
+ netif_rx_schedule(card->netdev);
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+ break;
+
+ /* case SPIDER_NET_GTMSHTINT: problem, print a message */
+ case SPIDER_NET_GDTINVDINT:
+ /* allrighty. tx from previous descr ok */
+ show_error = 0;
+ break;
+ /* case SPIDER_NET_GRFDFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFCFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFBFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFAFLLINT: print a message down there */
+
+ /* chain end */
+ case SPIDER_NET_GDDDCEINT: /* fallthrough */
+ case SPIDER_NET_GDCDCEINT: /* fallthrough */
+ case SPIDER_NET_GDBDCEINT: /* fallthrough */
+ case SPIDER_NET_GDADCEINT:
+ if (netif_msg_intr(card))
+ pr_err("got descriptor chain end interrupt, "
+ "restarting DMAC %c.\n",
+ 'D'+i-SPIDER_NET_GDDDCEINT);
+ spider_net_refill_rx_chain(card);
+ show_error = 0;
+ break;
+
+ /* invalid descriptor */
+ case SPIDER_NET_GDDINVDINT: /* fallthrough */
+ case SPIDER_NET_GDCINVDINT: /* fallthrough */
+ case SPIDER_NET_GDBINVDINT: /* fallthrough */
+ case SPIDER_NET_GDAINVDINT:
+ /* could happen when rx chain is full */
+ spider_net_refill_rx_chain(card);
+ show_error = 0;
+ break;
+
+ /* case SPIDER_NET_GDTRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDDRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDCRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDBRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDARSERINT: problem, print a message */
+ /* case SPIDER_NET_GDSERINT: problem, print a message */
+ /* case SPIDER_NET_GDTPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDDPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDCPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDBPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDAPTERINT: problem, print a message */
+ default:
+ show_error = 1;
+ break;
+ }
+
+ /* check GHIINT2STS ************************************/
+ if (error_reg2)
+ for (i = 0; i < 32; i++)
+ if (error_reg2 & (1<<i))
+ switch (i)
+ {
+ /* there is nothing we can (want to) do at this time. Log a
+ * message, we can switch on and off the specific values later on
+ case SPIDER_NET_GPROPERINT:
+ case SPIDER_NET_GMCTCRSNGINT:
+ case SPIDER_NET_GMCTLCOLINT:
+ case SPIDER_NET_GMCTTMOTINT:
+ case SPIDER_NET_GMCRCAERINT:
+ case SPIDER_NET_GMCRCALERINT:
+ case SPIDER_NET_GMCRALNERINT:
+ case SPIDER_NET_GMCROVRINT:
+ case SPIDER_NET_GMCRRNTINT:
+ case SPIDER_NET_GMCRRXERINT:
+ case SPIDER_NET_GTITCSERINT:
+ case SPIDER_NET_GTIFMTERINT:
+ case SPIDER_NET_GTIPKTRVKINT:
+ case SPIDER_NET_GTISPINGINT:
+ case SPIDER_NET_GTISADNGINT:
+ case SPIDER_NET_GTISPDNGINT:
+ case SPIDER_NET_GRIFMTERINT:
+ case SPIDER_NET_GRIPKTRVKINT:
+ case SPIDER_NET_GRISPINGINT:
+ case SPIDER_NET_GRISADNGINT:
+ case SPIDER_NET_GRISPDNGINT:
+ break;
+ */
+ default:
+ break;
+ }
+
+ if ((show_error) && (netif_msg_intr(card)))
+ pr_err("Got error interrupt, GHIINT0STS = 0x%08x, "
+ "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
+ status_reg, error_reg1, error_reg2);
+
+ /* clear interrupt sources */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1STS, error_reg1);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2STS, error_reg2);
+}
+
+/**
+ * spider_net_interrupt - interrupt handler for spider_net
+ * @irq: interupt number
+ * @ptr: pointer to net_device
+ * @regs: PU registers
+ *
+ * returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no
+ * interrupt found raised by card.
+ *
+ * This is the interrupt handler, that turns off
+ * interrupts for this device and makes the stack poll the driver
+ */
+static irqreturn_t
+spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ struct net_device *netdev = ptr;
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 status_reg;
+
+ status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+
+ if (!status_reg)
+ return IRQ_NONE;
+
+ if (status_reg & SPIDER_NET_TXINT)
+ spider_net_release_tx_chain(card, 0);
+
+ if (status_reg & SPIDER_NET_RXINT ) {
+ spider_net_rx_irq_off(card);
+ netif_rx_schedule(netdev);
+ }
+
+ /* we do this after rx and tx processing, as we want the tx chain
+ * processed to see, whether we should restart tx dma processing */
+ spider_net_handle_error_irq(card, status_reg);
+
+ /* clear interrupt sources */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * spider_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void
+spider_net_poll_controller(struct net_device *netdev)
+{
+ disable_irq(netdev->irq);
+ spider_net_interrupt(netdev->irq, netdev, NULL);
+ enable_irq(netdev->irq);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * spider_net_init_card - initializes the card
+ * @card: card structure
+ *
+ * spider_net_init_card initializes the card so that other registers can
+ * be used
+ */
+static void
+spider_net_init_card(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+}
+
+/**
+ * spider_net_enable_card - enables the card by setting all kinds of regs
+ * @card: card structure
+ *
+ * spider_net_enable_card sets a lot of SMMIO registers to enable the device
+ */
+static void
+spider_net_enable_card(struct spider_net_card *card)
+{
+ int i;
+ /* the following array consists of (register),(value) pairs
+ * that are set in this function. A register of 0 ends the list */
+ u32 regs[][2] = {
+ { SPIDER_NET_GRESUMINTNUM, 0 },
+ { SPIDER_NET_GREINTNUM, 0 },
+
+ /* set interrupt frame number registers */
+ /* clear the single DMA engine registers first */
+ { SPIDER_NET_GFAFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFBFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFCFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFDFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ /* then set, what we really need */
+ { SPIDER_NET_GFFRMNUM, SPIDER_NET_FRAMENUM_VALUE },
+
+ /* timer counter registers and stuff */
+ { SPIDER_NET_GFREECNNUM, 0 },
+ { SPIDER_NET_GONETIMENUM, 0 },
+ { SPIDER_NET_GTOUTFRMNUM, 0 },
+
+ /* RX mode setting */
+ { SPIDER_NET_GRXMDSET, SPIDER_NET_RXMODE_VALUE },
+ /* TX mode setting */
+ { SPIDER_NET_GTXMDSET, SPIDER_NET_TXMODE_VALUE },
+ /* IPSEC mode setting */
+ { SPIDER_NET_GIPSECINIT, SPIDER_NET_IPSECINIT_VALUE },
+
+ { SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
+
+ { SPIDER_NET_GMRWOLCTRL, 0 },
+ { SPIDER_NET_GTESTMD, 0 },
+
+ { SPIDER_NET_GMACINTEN, 0 },
+
+ /* flow control stuff */
+ { SPIDER_NET_GMACAPAUSE, SPIDER_NET_MACAPAUSE_VALUE },
+ { SPIDER_NET_GMACTXPAUSE, SPIDER_NET_TXPAUSE_VALUE },
+
+ { SPIDER_NET_GMACBSTLMT, SPIDER_NET_BURSTLMT_VALUE },
+ { 0, 0}
+ };
+
+ i = 0;
+ while (regs[i][0]) {
+ spider_net_write_reg(card, regs[i][0], regs[i][1]);
+ i++;
+ }
+
+ /* clear unicast filter table entries 1 to 14 */
+ for (i = 1; i <= 14; i++) {
+ spider_net_write_reg(card,
+ SPIDER_NET_GMRUAFILnR + i * 8,
+ 0x00080000);
+ spider_net_write_reg(card,
+ SPIDER_NET_GMRUAFILnR + i * 8 + 4,
+ 0x00000000);
+ }
+
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R, 0x08080000);
+
+ spider_net_write_reg(card, SPIDER_NET_ECMODE, SPIDER_NET_ECMODE_VALUE);
+
+ /* set chain tail adress for RX chains and
+ * enable DMA */
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+
+ spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE);
+
+ /* set chain tail adress for TX chain */
+ spider_net_enable_txdmac(card);
+
+ spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
+ SPIDER_NET_LENLMT_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GMACMODE,
+ SPIDER_NET_MACMODE_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
+ SPIDER_NET_OPMODE_VALUE);
+
+ /* set interrupt mask registers */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+ SPIDER_NET_INT0_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+ SPIDER_NET_INT1_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+ SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+int
+spider_net_open(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ int result;
+
+ result = -ENOMEM;
+ if (spider_net_init_chain(card, &card->tx_chain,
+ card->descr, tx_descriptors))
+ goto alloc_tx_failed;
+ if (spider_net_init_chain(card, &card->rx_chain,
+ card->descr + tx_descriptors, rx_descriptors))
+ goto alloc_rx_failed;
+
+ /* allocate rx skbs */
+ if (spider_net_alloc_rx_skbs(card))
+ goto alloc_skbs_failed;
+
+ spider_net_set_multi(netdev);
+
+ /* further enhancement: setup hw vlan, if needed */
+
+ result = -EBUSY;
+ if (request_irq(netdev->irq, spider_net_interrupt,
+ SA_SHIRQ, netdev->name, netdev))
+ goto register_int_failed;
+
+ spider_net_enable_card(card);
+
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ netif_poll_enable(netdev);
+
+ return 0;
+
+register_int_failed:
+ spider_net_free_rx_chain_contents(card);
+alloc_skbs_failed:
+ spider_net_free_chain(card, &card->rx_chain);
+alloc_rx_failed:
+ spider_net_free_chain(card, &card->tx_chain);
+alloc_tx_failed:
+ return result;
+}
+
+/**
+ * spider_net_setup_phy - setup PHY
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_setup_phy is used as part of spider_net_probe. Sets
+ * the PHY to 1000 Mbps
+ **/
+static int
+spider_net_setup_phy(struct spider_net_card *card)
+{
+ struct mii_phy *phy = &card->phy;
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMASEL,
+ SPIDER_NET_DMASEL_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GPCCTRL,
+ SPIDER_NET_PHY_CTRL_VALUE);
+ phy->mii_id = 1;
+ phy->dev = card->netdev;
+ phy->mdio_read = spider_net_read_phy;
+ phy->mdio_write = spider_net_write_phy;
+
+ mii_phy_probe(phy, phy->mii_id);
+
+ 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);
+
+ phy->def->ops->read_link(phy);
+ pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
+ phy->speed, phy->duplex==1 ? "Full" : "Half");
+
+ return 0;
+}
+
+/**
+ * spider_net_download_firmware - loads firmware into the adapter
+ * @card: card structure
+ * @firmware: firmware pointer
+ *
+ * spider_net_download_firmware loads the firmware opened by
+ * spider_net_init_firmware into the adapter.
+ */
+static void
+spider_net_download_firmware(struct spider_net_card *card,
+ const struct firmware *firmware)
+{
+ int sequencer, i;
+ u32 *fw_ptr = (u32 *)firmware->data;
+
+ /* stop sequencers */
+ spider_net_write_reg(card, SPIDER_NET_GSINIT,
+ SPIDER_NET_STOP_SEQ_VALUE);
+
+ for (sequencer = 0; sequencer < 6; sequencer++) {
+ spider_net_write_reg(card,
+ SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
+ for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, *fw_ptr);
+ fw_ptr++;
+ }
+ }
+
+ spider_net_write_reg(card, SPIDER_NET_GSINIT,
+ SPIDER_NET_RUN_SEQ_VALUE);
+}
+
+/**
+ * spider_net_init_firmware - reads in firmware parts
+ * @card: card structure
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_init_firmware opens the sequencer firmware and does some basic
+ * checks. This function opens and releases the firmware structure. A call
+ * to download the firmware is performed before the release.
+ *
+ * Firmware format
+ * ===============
+ * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being
+ * the program for each sequencer. Use the command
+ * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \
+ * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \
+ * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin
+ *
+ * to generate spider_fw.bin, if you have sequencer programs with something
+ * like the following contents for each sequencer:
+ * <ONE LINE COMMENT>
+ * <FIRST 4-BYTES-WORD FOR SEQUENCER>
+ * <SECOND 4-BYTES-WORD FOR SEQUENCER>
+ * ...
+ * <1024th 4-BYTES-WORD FOR SEQUENCER>
+ */
+static int
+spider_net_init_firmware(struct spider_net_card *card)
+{
+ const struct firmware *firmware;
+ int err = -EIO;
+
+ if (request_firmware(&firmware,
+ SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) < 0) {
+ if (netif_msg_probe(card))
+ pr_err("Couldn't read in sequencer data file %s.\n",
+ SPIDER_NET_FIRMWARE_NAME);
+ firmware = NULL;
+ goto out;
+ }
+
+ if (firmware->size != 6 * SPIDER_NET_FIRMWARE_LEN * sizeof(u32)) {
+ if (netif_msg_probe(card))
+ pr_err("Invalid size of sequencer data file %s.\n",
+ SPIDER_NET_FIRMWARE_NAME);
+ goto out;
+ }
+
+ spider_net_download_firmware(card, firmware);
+
+ err = 0;
+out:
+ release_firmware(firmware);
+
+ return err;
+}
+
+/**
+ * spider_net_workaround_rxramfull - work around firmware bug
+ * @card: card structure
+ *
+ * no return value
+ **/
+static void
+spider_net_workaround_rxramfull(struct spider_net_card *card)
+{
+ int i, sequencer = 0;
+
+ /* cancel reset */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+
+ /* empty sequencer data */
+ for (sequencer = 0; sequencer < 6; sequencer++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, 0x0);
+ for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, 0x0);
+ }
+ }
+
+ /* set sequencer operation */
+ spider_net_write_reg(card, SPIDER_NET_GSINIT, 0x000000fe);
+
+ /* reset */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+}
+
+/**
+ * spider_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @data: data, is interface device structure
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void
+spider_net_tx_timeout_task(void *data)
+{
+ struct net_device *netdev = data;
+ struct spider_net_card *card = netdev_priv(netdev);
+
+ if (!(netdev->flags & IFF_UP))
+ goto out;
+
+ netif_device_detach(netdev);
+ spider_net_stop(netdev);
+
+ spider_net_workaround_rxramfull(card);
+ spider_net_init_card(card);
+
+ if (spider_net_setup_phy(card))
+ goto out;
+ if (spider_net_init_firmware(card))
+ goto out;
+
+ spider_net_open(netdev);
+ spider_net_kick_tx_dma(card, card->tx_chain.head);
+ netif_device_attach(netdev);
+
+out:
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * spider_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void
+spider_net_tx_timeout(struct net_device *netdev)
+{
+ struct spider_net_card *card;
+
+ card = netdev_priv(netdev);
+ atomic_inc(&card->tx_timeout_task_counter);
+ if (netdev->flags & IFF_UP)
+ schedule_work(&card->tx_timeout_task);
+ else
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * spider_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void
+spider_net_setup_netdev_ops(struct net_device *netdev)
+{
+ netdev->open = &spider_net_open;
+ netdev->stop = &spider_net_stop;
+ netdev->hard_start_xmit = &spider_net_xmit;
+ netdev->get_stats = &spider_net_get_stats;
+ netdev->set_multicast_list = &spider_net_set_multi;
+ netdev->set_mac_address = &spider_net_set_mac;
+ netdev->change_mtu = &spider_net_change_mtu;
+ netdev->do_ioctl = &spider_net_do_ioctl;
+ /* tx watchdog */
+ netdev->tx_timeout = &spider_net_tx_timeout;
+ netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT;
+ /* NAPI */
+ netdev->poll = &spider_net_poll;
+ netdev->weight = SPIDER_NET_NAPI_WEIGHT;
+ /* HW VLAN */
+ netdev->vlan_rx_register = &spider_net_vlan_rx_reg;
+ netdev->vlan_rx_add_vid = &spider_net_vlan_rx_add;
+ netdev->vlan_rx_kill_vid = &spider_net_vlan_rx_kill;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ /* poll controller */
+ netdev->poll_controller = &spider_net_poll_controller;
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+ /* ethtool ops */
+ netdev->ethtool_ops = &spider_net_ethtool_ops;
+}
+
+/**
+ * spider_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * spider_net_setup_netdev initializes the net_device structure
+ **/
+static int
+spider_net_setup_netdev(struct spider_net_card *card)
+{
+ int result;
+ struct net_device *netdev = card->netdev;
+ struct device_node *dn;
+ struct sockaddr addr;
+ u8 *mac;
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &card->pdev->dev);
+
+ pci_set_drvdata(card->pdev, netdev);
+ spin_lock_init(&card->intmask_lock);
+ netdev->irq = card->pdev->irq;
+
+ card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
+
+ spider_net_setup_netdev_ops(netdev);
+
+ netdev->features = 0;
+ /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+ * NETIF_F_HW_VLAN_FILTER */
+
+ netdev->irq = card->pdev->irq;
+
+ dn = pci_device_to_OF_node(card->pdev);
+ if (!dn)
+ return -EIO;
+
+ mac = (u8 *)get_property(dn, "local-mac-address", NULL);
+ if (!mac)
+ return -EIO;
+ memcpy(addr.sa_data, mac, ETH_ALEN);
+
+ result = spider_net_set_mac(netdev, &addr);
+ if ((result) && (netif_msg_probe(card)))
+ pr_err("Failed to set MAC address: %i\n", result);
+
+ result = register_netdev(netdev);
+ if (result) {
+ if (netif_msg_probe(card))
+ pr_err("Couldn't register net_device: %i\n",
+ result);
+ return result;
+ }
+
+ if (netif_msg_probe(card))
+ pr_info("Initialized device %s.\n", netdev->name);
+
+ return 0;
+}
+
+/**
+ * spider_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct spider_net_card *
+spider_net_alloc_card(void)
+{
+ struct net_device *netdev;
+ struct spider_net_card *card;
+ size_t alloc_size;
+
+ alloc_size = sizeof (*card) +
+ sizeof (struct spider_net_descr) * rx_descriptors +
+ sizeof (struct spider_net_descr) * tx_descriptors;
+ netdev = alloc_etherdev(alloc_size);
+ if (!netdev)
+ return NULL;
+
+ card = netdev_priv(netdev);
+ card->netdev = netdev;
+ card->msg_enable = SPIDER_NET_DEFAULT_MSG;
+ INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev);
+ init_waitqueue_head(&card->waitq);
+ atomic_set(&card->tx_timeout_task_counter, 0);
+
+ return card;
+}
+
+/**
+ * spider_net_undo_pci_setup - releases PCI ressources
+ * @card: card structure
+ *
+ * spider_net_undo_pci_setup releases the mapped regions
+ */
+static void
+spider_net_undo_pci_setup(struct spider_net_card *card)
+{
+ iounmap(card->regs);
+ pci_release_regions(card->pdev);
+}
+
+/**
+ * spider_net_setup_pci_dev - sets up the device in terms of PCI operations
+ * @card: card structure
+ * @pdev: PCI device
+ *
+ * Returns the card structure or NULL if any errors occur
+ *
+ * spider_net_setup_pci_dev initializes pdev and together with the
+ * functions called in spider_net_open configures the device so that
+ * data can be transferred over it
+ * The net_device structure is attached to the card structure, if the
+ * function returns without error.
+ **/
+static struct spider_net_card *
+spider_net_setup_pci_dev(struct pci_dev *pdev)
+{
+ struct spider_net_card *card;
+ unsigned long mmio_start, mmio_len;
+
+ if (pci_enable_device(pdev)) {
+ pr_err("Couldn't enable PCI device\n");
+ return NULL;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ pr_err("Couldn't find proper PCI device base address.\n");
+ goto out_disable_dev;
+ }
+
+ if (pci_request_regions(pdev, spider_net_driver_name)) {
+ pr_err("Couldn't obtain PCI resources, aborting.\n");
+ goto out_disable_dev;
+ }
+
+ pci_set_master(pdev);
+
+ card = spider_net_alloc_card();
+ if (!card) {
+ pr_err("Couldn't allocate net_device structure, "
+ "aborting.\n");
+ goto out_release_regions;
+ }
+ card->pdev = pdev;
+
+ /* fetch base address and length of first resource */
+ mmio_start = pci_resource_start(pdev, 0);
+ mmio_len = pci_resource_len(pdev, 0);
+
+ card->netdev->mem_start = mmio_start;
+ card->netdev->mem_end = mmio_start + mmio_len;
+ card->regs = ioremap(mmio_start, mmio_len);
+
+ if (!card->regs) {
+ pr_err("Couldn't obtain PCI resources, aborting.\n");
+ goto out_release_regions;
+ }
+
+ return card;
+
+out_release_regions:
+ pci_release_regions(pdev);
+out_disable_dev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return NULL;
+}
+
+/**
+ * spider_net_probe - initialization of a device
+ * @pdev: PCI device
+ * @ent: entry in the device id list
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_probe initializes pdev and registers a net_device
+ * structure for it. After that, the device can be ifconfig'ed up
+ **/
+static int __devinit
+spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -EIO;
+ struct spider_net_card *card;
+
+ card = spider_net_setup_pci_dev(pdev);
+ if (!card)
+ goto out;
+
+ spider_net_workaround_rxramfull(card);
+ spider_net_init_card(card);
+
+ err = spider_net_setup_phy(card);
+ if (err)
+ goto out_undo_pci;
+
+ err = spider_net_init_firmware(card);
+ if (err)
+ goto out_undo_pci;
+
+ err = spider_net_setup_netdev(card);
+ if (err)
+ goto out_undo_pci;
+
+ return 0;
+
+out_undo_pci:
+ spider_net_undo_pci_setup(card);
+ free_netdev(card->netdev);
+out:
+ return err;
+}
+
+/**
+ * spider_net_remove - removal of a device
+ * @pdev: PCI device
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_remove is called to remove the device and unregisters the
+ * net_device
+ **/
+static void __devexit
+spider_net_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev;
+ struct spider_net_card *card;
+
+ netdev = pci_get_drvdata(pdev);
+ card = netdev_priv(netdev);
+
+ wait_event(card->waitq,
+ atomic_read(&card->tx_timeout_task_counter) == 0);
+
+ unregister_netdev(netdev);
+
+ /* switch off card */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+
+ spider_net_undo_pci_setup(card);
+ free_netdev(netdev);
+}
+
+static struct pci_driver spider_net_driver = {
+ .owner = THIS_MODULE,
+ .name = spider_net_driver_name,
+ .id_table = spider_net_pci_tbl,
+ .probe = spider_net_probe,
+ .remove = __devexit_p(spider_net_remove)
+};
+
+/**
+ * spider_net_init - init function when the driver is loaded
+ *
+ * spider_net_init registers the device driver
+ */
+static int __init spider_net_init(void)
+{
+ if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) {
+ rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN;
+ pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
+ }
+ if (rx_descriptors > SPIDER_NET_RX_DESCRIPTORS_MAX) {
+ rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MAX;
+ pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
+ }
+ if (tx_descriptors < SPIDER_NET_TX_DESCRIPTORS_MIN) {
+ tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_MIN;
+ pr_info("adjusting tx descriptors to %i.\n", tx_descriptors);
+ }
+ if (tx_descriptors > SPIDER_NET_TX_DESCRIPTORS_MAX) {
+ tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_MAX;
+ pr_info("adjusting tx descriptors to %i.\n", tx_descriptors);
+ }
+
+ return pci_register_driver(&spider_net_driver);
+}
+
+/**
+ * spider_net_cleanup - exit function when driver is unloaded
+ *
+ * spider_net_cleanup unregisters the device driver
+ */
+static void __exit spider_net_cleanup(void)
+{
+ pci_unregister_driver(&spider_net_driver);
+}
+
+module_init(spider_net_init);
+module_exit(spider_net_cleanup);
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
new file mode 100644
index 000000000000..22b2f2347351
--- /dev/null
+++ b/drivers/net/spider_net.h
@@ -0,0 +1,469 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SPIDER_NET_H
+#define _SPIDER_NET_H
+
+#include "sungem_phy.h"
+
+extern int spider_net_stop(struct net_device *netdev);
+extern int spider_net_open(struct net_device *netdev);
+
+extern struct ethtool_ops spider_net_ethtool_ops;
+
+extern char spider_net_driver_name[];
+
+#define SPIDER_NET_MAX_MTU 2308
+#define SPIDER_NET_MIN_MTU 64
+
+#define SPIDER_NET_RXBUF_ALIGN 128
+
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_RX_DESCRIPTORS_MIN 16
+#define SPIDER_NET_RX_DESCRIPTORS_MAX 256
+
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
+#define SPIDER_NET_TX_DESCRIPTORS_MAX 256
+
+#define SPIDER_NET_RX_CSUM_DEFAULT 1
+
+#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
+#define SPIDER_NET_NAPI_WEIGHT 64
+
+#define SPIDER_NET_FIRMWARE_LEN 1024
+#define SPIDER_NET_FIRMWARE_NAME "spider_fw.bin"
+
+/** spider_net SMMIO registers */
+#define SPIDER_NET_GHIINT0STS 0x00000000
+#define SPIDER_NET_GHIINT1STS 0x00000004
+#define SPIDER_NET_GHIINT2STS 0x00000008
+#define SPIDER_NET_GHIINT0MSK 0x00000010
+#define SPIDER_NET_GHIINT1MSK 0x00000014
+#define SPIDER_NET_GHIINT2MSK 0x00000018
+
+#define SPIDER_NET_GRESUMINTNUM 0x00000020
+#define SPIDER_NET_GREINTNUM 0x00000024
+
+#define SPIDER_NET_GFFRMNUM 0x00000028
+#define SPIDER_NET_GFAFRMNUM 0x0000002c
+#define SPIDER_NET_GFBFRMNUM 0x00000030
+#define SPIDER_NET_GFCFRMNUM 0x00000034
+#define SPIDER_NET_GFDFRMNUM 0x00000038
+
+/* clear them (don't use it) */
+#define SPIDER_NET_GFREECNNUM 0x0000003c
+#define SPIDER_NET_GONETIMENUM 0x00000040
+
+#define SPIDER_NET_GTOUTFRMNUM 0x00000044
+
+#define SPIDER_NET_GTXMDSET 0x00000050
+#define SPIDER_NET_GPCCTRL 0x00000054
+#define SPIDER_NET_GRXMDSET 0x00000058
+#define SPIDER_NET_GIPSECINIT 0x0000005c
+#define SPIDER_NET_GFTRESTRT 0x00000060
+#define SPIDER_NET_GRXDMAEN 0x00000064
+#define SPIDER_NET_GMRWOLCTRL 0x00000068
+#define SPIDER_NET_GPCWOPCMD 0x0000006c
+#define SPIDER_NET_GPCROPCMD 0x00000070
+#define SPIDER_NET_GTTFRMCNT 0x00000078
+#define SPIDER_NET_GTESTMD 0x0000007c
+
+#define SPIDER_NET_GSINIT 0x00000080
+#define SPIDER_NET_GSnPRGADR 0x00000084
+#define SPIDER_NET_GSnPRGDAT 0x00000088
+
+#define SPIDER_NET_GMACOPEMD 0x00000100
+#define SPIDER_NET_GMACLENLMT 0x00000108
+#define SPIDER_NET_GMACINTEN 0x00000118
+#define SPIDER_NET_GMACPHYCTRL 0x00000120
+
+#define SPIDER_NET_GMACAPAUSE 0x00000154
+#define SPIDER_NET_GMACTXPAUSE 0x00000164
+
+#define SPIDER_NET_GMACMODE 0x000001b0
+#define SPIDER_NET_GMACBSTLMT 0x000001b4
+
+#define SPIDER_NET_GMACUNIMACU 0x000001c0
+#define SPIDER_NET_GMACUNIMACL 0x000001c8
+
+#define SPIDER_NET_GMRMHFILnR 0x00000400
+#define SPIDER_NET_MULTICAST_HASHES 256
+
+#define SPIDER_NET_GMRUAFILnR 0x00000500
+#define SPIDER_NET_GMRUA0FIL15R 0x00000578
+
+/* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
+ * 0x00000b.. for DMA controller B, etc. */
+#define SPIDER_NET_GDADCHA 0x00000a00
+#define SPIDER_NET_GDADMACCNTR 0x00000a04
+#define SPIDER_NET_GDACTDPA 0x00000a08
+#define SPIDER_NET_GDACTDCNT 0x00000a0c
+#define SPIDER_NET_GDACDBADDR 0x00000a20
+#define SPIDER_NET_GDACDBSIZE 0x00000a24
+#define SPIDER_NET_GDACNEXTDA 0x00000a28
+#define SPIDER_NET_GDACCOMST 0x00000a2c
+#define SPIDER_NET_GDAWBCOMST 0x00000a30
+#define SPIDER_NET_GDAWBRSIZE 0x00000a34
+#define SPIDER_NET_GDAWBVSIZE 0x00000a38
+#define SPIDER_NET_GDAWBTRST 0x00000a3c
+#define SPIDER_NET_GDAWBTRERR 0x00000a40
+
+/* TX DMA controller registers */
+#define SPIDER_NET_GDTDCHA 0x00000e00
+#define SPIDER_NET_GDTDMACCNTR 0x00000e04
+#define SPIDER_NET_GDTCDPA 0x00000e08
+#define SPIDER_NET_GDTDMASEL 0x00000e14
+
+#define SPIDER_NET_ECMODE 0x00000f00
+/* clock and reset control register */
+#define SPIDER_NET_CKRCTRL 0x00000ff0
+
+/** SCONFIG registers */
+#define SPIDER_NET_SCONFIG_IOACTE 0x00002810
+
+/** hardcoded register values */
+#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe3ff
+#define SPIDER_NET_INT1_MASK_VALUE 0xffffffff
+/* no MAC aborts -> auto retransmission */
+#define SPIDER_NET_INT2_MASK_VALUE 0xfffffff1
+
+/* clear counter when interrupt sources are cleared
+#define SPIDER_NET_FRAMENUM_VALUE 0x0001f001 */
+/* we rely on flagged descriptor interrupts */
+#define SPIDER_NET_FRAMENUM_VALUE 0x00000000
+/* set this first, then the FRAMENUM_VALUE */
+#define SPIDER_NET_GFXFRAMES_VALUE 0x00000000
+
+#define SPIDER_NET_STOP_SEQ_VALUE 0x00000000
+#define SPIDER_NET_RUN_SEQ_VALUE 0x0000007e
+
+#define SPIDER_NET_PHY_CTRL_VALUE 0x00040040
+/* #define SPIDER_NET_PHY_CTRL_VALUE 0x01070080*/
+#define SPIDER_NET_RXMODE_VALUE 0x00000011
+/* auto retransmission in case of MAC aborts */
+#define SPIDER_NET_TXMODE_VALUE 0x00010000
+#define SPIDER_NET_RESTART_VALUE 0x00000000
+#define SPIDER_NET_WOL_VALUE 0x00001111
+#if 0
+#define SPIDER_NET_WOL_VALUE 0x00000000
+#endif
+#define SPIDER_NET_IPSECINIT_VALUE 0x00f000f8
+
+/* pause frames: automatic, no upper retransmission count */
+/* outside loopback mode: ETOMOD signal dont matter, not connected */
+#define SPIDER_NET_OPMODE_VALUE 0x00000063
+/*#define SPIDER_NET_OPMODE_VALUE 0x001b0062*/
+#define SPIDER_NET_LENLMT_VALUE 0x00000908
+
+#define SPIDER_NET_MACAPAUSE_VALUE 0x00000800 /* about 1 ms */
+#define SPIDER_NET_TXPAUSE_VALUE 0x00000000
+
+#define SPIDER_NET_MACMODE_VALUE 0x00000001
+#define SPIDER_NET_BURSTLMT_VALUE 0x00000200 /* about 16 us */
+
+/* 1(0) enable r/tx dma
+ * 0000000 fixed to 0
+ *
+ * 000000 fixed to 0
+ * 0(1) en/disable descr writeback on force end
+ * 0(1) force end
+ *
+ * 000000 fixed to 0
+ * 00 burst alignment: 128 bytes
+ *
+ * 00000 fixed to 0
+ * 0 descr writeback size 32 bytes
+ * 0(1) descr chain end interrupt enable
+ * 0(1) descr status writeback enable */
+
+/* to set RX_DMA_EN */
+#define SPIDER_NET_DMA_RX_VALUE 0x80000000
+#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
+/* to set TX_DMA_EN */
+#define SPIDER_NET_DMA_TX_VALUE 0x80000000
+#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
+
+/* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */
+#define SPIDER_NET_UA_DESCR_VALUE 0x00080000
+#define SPIDER_NET_PROMISC_VALUE 0x00080000
+#define SPIDER_NET_NONPROMISC_VALUE 0x00000000
+
+#define SPIDER_NET_DMASEL_VALUE 0x00000001
+
+#define SPIDER_NET_ECMODE_VALUE 0x00000000
+
+#define SPIDER_NET_CKRCTRL_RUN_VALUE 0x1fff010f
+#define SPIDER_NET_CKRCTRL_STOP_VALUE 0x0000010f
+
+#define SPIDER_NET_SBIMSTATE_VALUE 0x00000000
+#define SPIDER_NET_SBTMSTATE_VALUE 0x00000000
+
+/* SPIDER_NET_GHIINT0STS bits, in reverse order so that they can be used
+ * with 1 << SPIDER_NET_... */
+enum spider_net_int0_status {
+ SPIDER_NET_GPHYINT = 0,
+ SPIDER_NET_GMAC2INT,
+ SPIDER_NET_GMAC1INT,
+ SPIDER_NET_GIPSINT,
+ SPIDER_NET_GFIFOINT,
+ SPIDER_NET_GDMACINT,
+ SPIDER_NET_GSYSINT,
+ SPIDER_NET_GPWOPCMPINT,
+ SPIDER_NET_GPROPCMPINT,
+ SPIDER_NET_GPWFFINT,
+ SPIDER_NET_GRMDADRINT,
+ SPIDER_NET_GRMARPINT,
+ SPIDER_NET_GRMMPINT,
+ SPIDER_NET_GDTDEN0INT,
+ SPIDER_NET_GDDDEN0INT,
+ SPIDER_NET_GDCDEN0INT,
+ SPIDER_NET_GDBDEN0INT,
+ SPIDER_NET_GDADEN0INT,
+ SPIDER_NET_GDTFDCINT,
+ SPIDER_NET_GDDFDCINT,
+ SPIDER_NET_GDCFDCINT,
+ SPIDER_NET_GDBFDCINT,
+ SPIDER_NET_GDAFDCINT,
+ SPIDER_NET_GTTEDINT,
+ SPIDER_NET_GDTDCEINT,
+ SPIDER_NET_GRFDNMINT,
+ SPIDER_NET_GRFCNMINT,
+ SPIDER_NET_GRFBNMINT,
+ SPIDER_NET_GRFANMINT,
+ SPIDER_NET_GRFNMINT,
+ SPIDER_NET_G1TMCNTINT,
+ SPIDER_NET_GFREECNTINT
+};
+/* GHIINT1STS bits */
+enum spider_net_int1_status {
+ SPIDER_NET_GTMFLLINT = 0,
+ SPIDER_NET_GRMFLLINT,
+ SPIDER_NET_GTMSHTINT,
+ SPIDER_NET_GDTINVDINT,
+ SPIDER_NET_GRFDFLLINT,
+ SPIDER_NET_GDDDCEINT,
+ SPIDER_NET_GDDINVDINT,
+ SPIDER_NET_GRFCFLLINT,
+ SPIDER_NET_GDCDCEINT,
+ SPIDER_NET_GDCINVDINT,
+ SPIDER_NET_GRFBFLLINT,
+ SPIDER_NET_GDBDCEINT,
+ SPIDER_NET_GDBINVDINT,
+ SPIDER_NET_GRFAFLLINT,
+ SPIDER_NET_GDADCEINT,
+ SPIDER_NET_GDAINVDINT,
+ SPIDER_NET_GDTRSERINT,
+ SPIDER_NET_GDDRSERINT,
+ SPIDER_NET_GDCRSERINT,
+ SPIDER_NET_GDBRSERINT,
+ SPIDER_NET_GDARSERINT,
+ SPIDER_NET_GDSERINT,
+ SPIDER_NET_GDTPTERINT,
+ SPIDER_NET_GDDPTERINT,
+ SPIDER_NET_GDCPTERINT,
+ SPIDER_NET_GDBPTERINT,
+ SPIDER_NET_GDAPTERINT
+};
+/* GHIINT2STS bits */
+enum spider_net_int2_status {
+ SPIDER_NET_GPROPERINT = 0,
+ SPIDER_NET_GMCTCRSNGINT,
+ SPIDER_NET_GMCTLCOLINT,
+ SPIDER_NET_GMCTTMOTINT,
+ SPIDER_NET_GMCRCAERINT,
+ SPIDER_NET_GMCRCALERINT,
+ SPIDER_NET_GMCRALNERINT,
+ SPIDER_NET_GMCROVRINT,
+ SPIDER_NET_GMCRRNTINT,
+ SPIDER_NET_GMCRRXERINT,
+ SPIDER_NET_GTITCSERINT,
+ SPIDER_NET_GTIFMTERINT,
+ SPIDER_NET_GTIPKTRVKINT,
+ SPIDER_NET_GTISPINGINT,
+ SPIDER_NET_GTISADNGINT,
+ SPIDER_NET_GTISPDNGINT,
+ SPIDER_NET_GRIFMTERINT,
+ SPIDER_NET_GRIPKTRVKINT,
+ SPIDER_NET_GRISPINGINT,
+ SPIDER_NET_GRISADNGINT,
+ SPIDER_NET_GRISPDNGINT
+};
+
+#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GTTEDINT) | \
+ (1 << SPIDER_NET_GDTDCEINT) | \
+ (1 << SPIDER_NET_GDTFDCINT) )
+
+/* we rely on flagged descriptor interrupts*/
+#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
+ (1 << SPIDER_NET_GRMFLLINT) )
+
+#define SPIDER_NET_GPREXEC 0x80000000
+#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
+
+/* descriptor bits
+ *
+ * 1010 descriptor ready
+ * 0 descr in middle of chain
+ * 000 fixed to 0
+ *
+ * 0 no interrupt on completion
+ * 000 fixed to 0
+ * 1 no ipsec processing
+ * 1 last descriptor for this frame
+ * 00 no checksum
+ * 10 tcp checksum
+ * 11 udp checksum
+ *
+ * 00 fixed to 0
+ * 0 fixed to 0
+ * 0 no interrupt on response errors
+ * 0 no interrupt on invalid descr
+ * 0 no interrupt on dma process termination
+ * 0 no interrupt on descr chain end
+ * 0 no interrupt on descr complete
+ *
+ * 000 fixed to 0
+ * 0 response error interrupt status
+ * 0 invalid descr status
+ * 0 dma termination status
+ * 0 descr chain end status
+ * 0 descr complete status */
+#define SPIDER_NET_DMAC_CMDSTAT_NOCS 0xa00c0000
+#define SPIDER_NET_DMAC_CMDSTAT_TCPCS 0xa00e0000
+#define SPIDER_NET_DMAC_CMDSTAT_UDPCS 0xa00f0000
+#define SPIDER_NET_DESCR_IND_PROC_SHIFT 28
+#define SPIDER_NET_DESCR_IND_PROC_MASKO 0x0fffffff
+
+/* descr ready, descr is in middle of chain, get interrupt on completion */
+#define SPIDER_NET_DMAC_RX_CARDOWNED 0xa0800000
+
+/* multicast is no problem */
+#define SPIDER_NET_DATA_ERROR_MASK 0xffffbfff
+
+enum spider_net_descr_status {
+ SPIDER_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
+ SPIDER_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
+ SPIDER_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
+ SPIDER_NET_DESCR_FRAME_END = 0x04, /* used in rx */
+ SPIDER_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
+ SPIDER_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
+ SPIDER_NET_DESCR_NOT_IN_USE /* any other value */
+};
+
+struct spider_net_descr {
+ /* as defined by the hardware */
+ dma_addr_t buf_addr;
+ u32 buf_size;
+ dma_addr_t next_descr_addr;
+ u32 dmac_cmd_status;
+ u32 result_size;
+ u32 valid_size; /* all zeroes for tx */
+ u32 data_status;
+ u32 data_error; /* all zeroes for tx */
+
+ /* used in the driver */
+ struct sk_buff *skb;
+ dma_addr_t bus_addr;
+ struct spider_net_descr *next;
+ struct spider_net_descr *prev;
+} __attribute__((aligned(32)));
+
+struct spider_net_descr_chain {
+ /* we walk from tail to head */
+ struct spider_net_descr *head;
+ struct spider_net_descr *tail;
+};
+
+/* descriptor data_status bits */
+#define SPIDER_NET_RXIPCHK 29
+#define SPIDER_NET_TCPUDPIPCHK 28
+#define SPIDER_NET_DATA_STATUS_CHK_MASK (1 << SPIDER_NET_RXIPCHK | \
+ 1 << SPIDER_NET_TCPUDPIPCHK)
+
+#define SPIDER_NET_VLAN_PACKET 21
+
+/* descriptor data_error bits */
+#define SPIDER_NET_RXIPCHKERR 27
+#define SPIDER_NET_RXTCPCHKERR 26
+#define SPIDER_NET_DATA_ERROR_CHK_MASK (1 << SPIDER_NET_RXIPCHKERR | \
+ 1 << SPIDER_NET_RXTCPCHKERR)
+
+/* the cases we don't pass the packet to the stack */
+#define SPIDER_NET_DESTROY_RX_FLAGS 0x70138000
+
+#define SPIDER_NET_DESCR_SIZE 32
+
+/* this will be bigger some time */
+struct spider_net_options {
+ int rx_csum; /* for rx: if 0 ip_summed=NONE,
+ if 1 and hw has verified, ip_summed=UNNECESSARY */
+};
+
+#define SPIDER_NET_DEFAULT_MSG ( NETIF_MSG_DRV | \
+ NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_TIMER | \
+ NETIF_MSG_IFDOWN | \
+ NETIF_MSG_IFUP | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR | \
+ NETIF_MSG_TX_QUEUED | \
+ NETIF_MSG_INTR | \
+ NETIF_MSG_TX_DONE | \
+ NETIF_MSG_RX_STATUS | \
+ NETIF_MSG_PKTDATA | \
+ NETIF_MSG_HW | \
+ NETIF_MSG_WOL )
+
+struct spider_net_card {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct mii_phy phy;
+
+ void __iomem *regs;
+
+ struct spider_net_descr_chain tx_chain;
+ struct spider_net_descr_chain rx_chain;
+ spinlock_t chain_lock;
+
+ struct net_device_stats netdev_stats;
+
+ struct spider_net_options options;
+
+ spinlock_t intmask_lock;
+
+ struct work_struct tx_timeout_task;
+ atomic_t tx_timeout_task_counter;
+ wait_queue_head_t waitq;
+
+ /* for ethtool */
+ int msg_enable;
+
+ struct spider_net_descr descr[0];
+};
+
+#define pr_err(fmt,arg...) \
+ printk(KERN_ERR fmt ,##arg)
+
+#endif
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
new file mode 100644
index 000000000000..d42e60ba74ce
--- /dev/null
+++ b/drivers/net/spider_net_ethtool.c
@@ -0,0 +1,126 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+
+#include "spider_net.h"
+
+static int
+spider_net_ethtool_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+
+ cmd->supported = (SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE);
+ cmd->advertising = (ADVERTISED_1000baseT_Full |
+ ADVERTISED_FIBRE);
+ cmd->port = PORT_FIBRE;
+ cmd->speed = card->phy.speed;
+ cmd->duplex = DUPLEX_FULL;
+
+ return 0;
+}
+
+static void
+spider_net_ethtool_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+
+ /* clear and fill out info */
+ memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+ strncpy(drvinfo->driver, spider_net_driver_name, 32);
+ strncpy(drvinfo->version, "0.1", 32);
+ strcpy(drvinfo->fw_version, "no information");
+ strncpy(drvinfo->bus_info, pci_name(card->pdev), 32);
+}
+
+static void
+spider_net_ethtool_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wolinfo)
+{
+ /* no support for wol */
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
+}
+
+static u32
+spider_net_ethtool_get_msglevel(struct net_device *netdev)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+ return card->msg_enable;
+}
+
+static void
+spider_net_ethtool_set_msglevel(struct net_device *netdev,
+ u32 level)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+ card->msg_enable = level;
+}
+
+static int
+spider_net_ethtool_nway_reset(struct net_device *netdev)
+{
+ if (netif_running(netdev)) {
+ spider_net_stop(netdev);
+ spider_net_open(netdev);
+ }
+ return 0;
+}
+
+static u32
+spider_net_ethtool_get_rx_csum(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev->priv;
+
+ return card->options.rx_csum;
+}
+
+static int
+spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
+{
+ struct spider_net_card *card = netdev->priv;
+
+ card->options.rx_csum = n;
+ return 0;
+}
+
+struct ethtool_ops spider_net_ethtool_ops = {
+ .get_settings = spider_net_ethtool_get_settings,
+ .get_drvinfo = spider_net_ethtool_get_drvinfo,
+ .get_wol = spider_net_ethtool_get_wol,
+ .get_msglevel = spider_net_ethtool_get_msglevel,
+ .set_msglevel = spider_net_ethtool_set_msglevel,
+ .nway_reset = spider_net_ethtool_nway_reset,
+ .get_rx_csum = spider_net_ethtool_get_rx_csum,
+ .set_rx_csum = spider_net_ethtool_set_rx_csum,
+};
+
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 1f43bbfbc1c7..5c8fcd40ef4d 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -162,7 +162,7 @@ struct lance_private {
#define MEM lp->mem
#define DREG lp->iobase[0]
#define AREG lp->iobase[1]
-#define REGA(a) ( AREG = (a), DREG )
+#define REGA(a) (*( AREG = (a), &DREG ))
/* Definitions for the Lance */
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 2608e7a3d214..de399563a9db 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -948,6 +948,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u32 gem_status = readl(gp->regs + GREG_STAT);
if (gem_status == 0) {
+ netif_poll_enable(dev);
spin_unlock_irqrestore(&gp->lock, flags);
return IRQ_NONE;
}
@@ -2816,7 +2817,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
#if (!defined(__sparc__) && !defined(CONFIG_PPC_PMAC))
/* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
{
int this_offset;
@@ -2837,35 +2838,27 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
- break;
+ return 1;
}
+ return 0;
}
static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
{
- u32 rom_reg_orig;
- void __iomem *p;
-
- if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
- if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
- goto use_random;
- }
+ size_t size;
+ void __iomem *p = pci_map_rom(pdev, &size);
- pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
- pci_write_config_dword(pdev, pdev->rom_base_reg,
- rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+ if (p) {
+ int found;
- p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
- if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
- find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
-
- if (p != NULL)
- iounmap(p);
-
- pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
- return;
+ found = readb(p) == 0x55 &&
+ readb(p + 1) == 0xaa &&
+ find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
+ pci_unmap_rom(pdev, p);
+ if (found)
+ return;
+ }
-use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr[0] = 0x08;
dev_addr[1] = 0x00;
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index 7143fd7cf3f8..ff8ae5f79970 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -1020,7 +1020,7 @@ struct gem {
struct gem_init_block *init_block;
struct sk_buff *rx_skbs[RX_RING_SIZE];
- struct sk_buff *tx_skbs[RX_RING_SIZE];
+ struct sk_buff *tx_skbs[TX_RING_SIZE];
dma_addr_t gblock_dvma;
struct pci_dev *pdev;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index f02fe4119b2c..9f046cae2f71 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2954,7 +2954,7 @@ static int is_quattro_p(struct pci_dev *pdev)
}
/* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
{
int this_offset;
@@ -2977,42 +2977,33 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, uns
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
- break;
+ return 1;
}
index--;
}
+ return 0;
}
static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
{
- u32 rom_reg_orig;
- void __iomem *p;
- int index;
+ size_t size;
+ void __iomem *p = pci_map_rom(pdev, &size);
- index = 0;
- if (is_quattro_p(pdev))
- index = PCI_SLOT(pdev->devfn);
-
- if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
- if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
- goto use_random;
- }
+ if (p) {
+ int index = 0;
+ int found;
- pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
- pci_write_config_dword(pdev, pdev->rom_base_reg,
- rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+ if (is_quattro_p(pdev))
+ index = PCI_SLOT(pdev->devfn);
- p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
- if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
- find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
-
- if (p != NULL)
- iounmap(p);
-
- pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
- return;
+ found = readb(p) == 0x55 &&
+ readb(p + 1) == 0xaa &&
+ find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
+ pci_unmap_rom(pdev, p);
+ if (found)
+ return;
+ }
-use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr[0] = 0x08;
dev_addr[1] = 0x00;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 6d4ab1e333b5..7599f52e15b3 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -36,6 +36,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/workqueue.h>
+#include <linux/prefetch.h>
#include <net/checksum.h>
@@ -66,8 +67,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.37"
-#define DRV_MODULE_RELDATE "August 25, 2005"
+#define DRV_MODULE_VERSION "3.39"
+#define DRV_MODULE_RELDATE "September 5, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -121,12 +122,9 @@
TG3_RX_RCB_RING_SIZE(tp))
#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \
TG3_TX_RING_SIZE)
-#define TX_RING_GAP(TP) \
- (TG3_TX_RING_SIZE - (TP)->tx_pending)
#define TX_BUFFS_AVAIL(TP) \
- (((TP)->tx_cons <= (TP)->tx_prod) ? \
- (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod : \
- (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP))
+ ((TP)->tx_pending - \
+ (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1)))
#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
#define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64)
@@ -340,41 +338,92 @@ static struct {
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{
- if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- spin_lock_bh(&tp->indirect_lock);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_bh(&tp->indirect_lock);
- } else {
- writel(val, tp->regs + off);
- if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0)
- readl(tp->regs + off);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+}
+
+static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val)
+{
+ writel(val, tp->regs + off);
+ readl(tp->regs + off);
+}
+
+static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ return val;
+}
+
+static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+ unsigned long flags;
+
+ if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+ if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+
+ /* In indirect mode when disabling interrupts, we also need
+ * to clear the interrupt bit in the GRC local ctrl register.
+ */
+ if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
+ (val == 0x1)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
+ tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
}
}
+static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ return val;
+}
+
static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
{
- if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- spin_lock_bh(&tp->indirect_lock);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_bh(&tp->indirect_lock);
- } else {
- void __iomem *dest = tp->regs + off;
- writel(val, dest);
- readl(dest); /* always flush PCI write */
- }
+ tp->write32(tp, off, val);
+ if (!(tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) &&
+ !(tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) &&
+ !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
+ tp->read32(tp, off); /* flush */
}
-static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
+static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
{
- void __iomem *mbox = tp->regs + off;
- writel(val, mbox);
- if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
- readl(mbox);
+ tp->write32_mbox(tp, off, val);
+ if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
+ !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
+ tp->read32_mbox(tp, off);
}
-static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
+static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
{
void __iomem *mbox = tp->regs + off;
writel(val, mbox);
@@ -384,51 +433,63 @@ static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
readl(mbox);
}
-#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tp->regs + (reg))
-#define tw32_rx_mbox(reg, val) _tw32_rx_mbox(tp, reg, val)
-#define tw32_tx_mbox(reg, val) _tw32_tx_mbox(tp, reg, val)
+static void tg3_write32(struct tg3 *tp, u32 off, u32 val)
+{
+ writel(val, tp->regs + off);
+}
+
+static u32 tg3_read32(struct tg3 *tp, u32 off)
+{
+ return (readl(tp->regs + off));
+}
+
+#define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val)
+#define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val))
+#define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
+#define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val)
+#define tr32_mailbox(reg) tp->read32_mbox(tp, reg)
-#define tw32(reg,val) tg3_write_indirect_reg32(tp,(reg),(val))
+#define tw32(reg,val) tp->write32(tp, reg, val)
#define tw32_f(reg,val) _tw32_flush(tp,(reg),(val))
-#define tw16(reg,val) writew(((val) & 0xffff), tp->regs + (reg))
-#define tw8(reg,val) writeb(((val) & 0xff), tp->regs + (reg))
-#define tr32(reg) readl(tp->regs + (reg))
-#define tr16(reg) readw(tp->regs + (reg))
-#define tr8(reg) readb(tp->regs + (reg))
+#define tr32(reg) tp->read32(tp, reg)
static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
{
- spin_lock_bh(&tp->indirect_lock);
+ 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);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_bh(&tp->indirect_lock);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
{
- spin_lock_bh(&tp->indirect_lock);
+ 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);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_bh(&tp->indirect_lock);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
static void tg3_disable_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
}
static inline void tg3_cond_int(struct tg3 *tp)
{
- if (tp->hw_status->status & SD_STATUS_UPDATED)
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+ (tp->hw_status->status & SD_STATUS_UPDATED))
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
}
@@ -439,9 +500,8 @@ static void tg3_enable_ints(struct tg3 *tp)
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- (tp->last_tag << 24));
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ (tp->last_tag << 24));
tg3_cond_int(tp);
}
@@ -472,8 +532,6 @@ static inline unsigned int tg3_has_work(struct tg3 *tp)
*/
static void tg3_restart_ints(struct tg3 *tp)
{
- tw32(TG3PCI_MISC_HOST_CTRL,
- (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
tp->last_tag << 24);
mmiowb();
@@ -2821,9 +2879,13 @@ static void tg3_tx(struct tg3 *tp)
tp->tx_cons = sw_idx;
- if (netif_queue_stopped(tp->dev) &&
- (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
- netif_wake_queue(tp->dev);
+ if (unlikely(netif_queue_stopped(tp->dev))) {
+ spin_lock(&tp->tx_lock);
+ if (netif_queue_stopped(tp->dev) &&
+ (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+ netif_wake_queue(tp->dev);
+ spin_unlock(&tp->tx_lock);
+ }
}
/* Returns size of skb allocated or < 0 on error.
@@ -3139,9 +3201,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
/* run TX completion thread */
if (sblk->idx[0].tx_consumer != tp->tx_cons) {
- spin_lock(&tp->tx_lock);
tg3_tx(tp);
- spin_unlock(&tp->tx_lock);
}
/* run RX thread, within the bounds set by NAPI.
@@ -3161,18 +3221,17 @@ static int tg3_poll(struct net_device *netdev, int *budget)
netdev->quota -= work_done;
}
- if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
tp->last_tag = sblk->status_tag;
- rmb();
- sblk->status &= ~SD_STATUS_UPDATED;
+ rmb();
+ } else
+ sblk->status &= ~SD_STATUS_UPDATED;
/* if no more work, tell net stack and NIC we're done */
done = !tg3_has_work(tp);
if (done) {
- spin_lock(&tp->lock);
netif_rx_complete(netdev);
tg3_restart_ints(tp);
- spin_unlock(&tp->lock);
}
return (done ? 0 : 1);
@@ -3220,8 +3279,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
- struct tg3_hw_status *sblk = tp->hw_status;
+ prefetch(tp->hw_status);
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
/*
* Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
@@ -3230,19 +3290,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
* event coalescing.
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
- tp->last_tag = sblk->status_tag;
- rmb();
- if (tg3_irq_sync(tp))
- goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
+ if (likely(!tg3_irq_sync(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
- /* No work, re-enable interrupts. */
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- tp->last_tag << 24);
- }
-out:
+
return IRQ_RETVAL(1);
}
@@ -3272,15 +3322,15 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (tg3_irq_sync(tp))
goto out;
sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
+ if (likely(tg3_has_work(tp))) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
+ } else {
/* No work, shared interrupt perhaps? re-enable
* interrupts, and flush that PCI write
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000000);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
} else { /* shared interrupt */
handled = 0;
@@ -3301,7 +3351,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
* Reading the PCI State register will confirm whether the
* interrupt is ours and will flush the status block.
*/
- if ((sblk->status & SD_STATUS_UPDATED) ||
+ if ((sblk->status_tag != tp->last_tag) ||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
/*
* writing any value to intr-mbox-0 clears PCI INTA# and
@@ -3312,20 +3362,17 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
- tp->last_tag = sblk->status_tag;
- rmb();
if (tg3_irq_sync(tp))
goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
- netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
- /* no work, shared interrupt perhaps? re-enable
- * interrupts, and flush that PCI write
+ if (netif_rx_schedule_prep(dev)) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ /* Update last_tag to mark that this status has been
+ * seen. Because interrupt may be shared, we may be
+ * racing with tg3_poll(), so only update last_tag
+ * if tg3_poll() is not scheduled.
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- tp->last_tag << 24);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tp->last_tag = sblk->status_tag;
+ __netif_rx_schedule(dev);
}
} else { /* shared interrupt */
handled = 0;
@@ -3659,8 +3706,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
tp->tx_prod = entry;
- if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
+ if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
netif_stop_queue(dev);
+ if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+ netif_wake_queue(tp->dev);
+ }
out_unlock:
mmiowb();
@@ -4216,7 +4266,7 @@ static void tg3_stop_fw(struct tg3 *);
static int tg3_chip_reset(struct tg3 *tp)
{
u32 val;
- u32 flags_save;
+ void (*write_op)(struct tg3 *, u32, u32);
int i;
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
@@ -4228,8 +4278,9 @@ static int tg3_chip_reset(struct tg3 *tp)
* fun things. So, temporarily disable the 5701
* hardware workaround, while we do the reset.
*/
- flags_save = tp->tg3_flags;
- tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG;
+ write_op = tp->write32;
+ if (write_op == tg3_write_flush_reg32)
+ tp->write32 = tg3_write32;
/* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET;
@@ -4248,8 +4299,8 @@ static int tg3_chip_reset(struct tg3 *tp)
val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
tw32(GRC_MISC_CFG, val);
- /* restore 5701 hardware bug workaround flag */
- tp->tg3_flags = flags_save;
+ /* restore 5701 hardware bug workaround write method */
+ tp->write32 = write_op;
/* Unfortunately, we have to delay before the PCI read back.
* Some 575X chips even will not respond to a PCI cfg access
@@ -4635,7 +4686,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
int cpu_scratch_size, struct fw_info *info)
{
int err, i;
- u32 orig_tg3_flags = tp->tg3_flags;
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
@@ -4651,11 +4701,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
else
write_op = tg3_write_indirect_reg32;
- /* Force use of PCI config space for indirect register
- * write calls.
- */
- tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
-
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
@@ -4691,7 +4736,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
err = 0;
out:
- tp->tg3_flags = orig_tg3_flags;
return err;
}
@@ -5808,8 +5852,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
udelay(100);
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
tp->last_tag = 0;
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
@@ -5910,7 +5953,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_LED_CTRL, tp->led_ctrl);
tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
- if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10);
}
@@ -6192,13 +6235,15 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (err)
return err;
+ tp->hw_status->status &= ~SD_STATUS_UPDATED;
tg3_enable_ints(tp);
tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
HOSTCC_MODE_NOW);
for (i = 0; i < 5; i++) {
- int_mbox = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
+ TG3_64BIT_REG_LOW);
if (int_mbox != 0)
break;
msleep(10);
@@ -6598,10 +6643,10 @@ static int tg3_open(struct net_device *dev)
/* Mailboxes */
printk("DEBUG: SNDHOST_PROD[%08x%08x] SNDNIC_PROD[%08x%08x]\n",
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0),
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4),
- tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0),
- tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4));
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0),
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4),
+ tr32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0),
+ tr32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4));
/* NIC side send descriptors. */
for (i = 0; i < 6; i++) {
@@ -6848,8 +6893,7 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
get_stat64(&hw_stats->tx_octets);
stats->rx_errors = old_stats->rx_errors +
- get_stat64(&hw_stats->rx_errors) +
- get_stat64(&hw_stats->rx_discards);
+ get_stat64(&hw_stats->rx_errors);
stats->tx_errors = old_stats->tx_errors +
get_stat64(&hw_stats->tx_errors) +
get_stat64(&hw_stats->tx_mac_errors) +
@@ -6877,6 +6921,9 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
stats->rx_crc_errors = old_stats->rx_crc_errors +
calc_crc_errors(tp);
+ stats->rx_missed_errors = old_stats->rx_missed_errors +
+ get_stat64(&hw_stats->rx_discards);
+
return stats;
}
@@ -7506,6 +7553,38 @@ static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
}
}
+static int tg3_phys_id(struct net_device *dev, u32 data)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ int i;
+
+ if (!netif_running(tp->dev))
+ return -EAGAIN;
+
+ if (data == 0)
+ data = 2;
+
+ for (i = 0; i < (data * 2); i++) {
+ if ((i % 2) == 0)
+ tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+ LED_CTRL_1000MBPS_ON |
+ LED_CTRL_100MBPS_ON |
+ LED_CTRL_10MBPS_ON |
+ LED_CTRL_TRAFFIC_OVERRIDE |
+ LED_CTRL_TRAFFIC_BLINK |
+ LED_CTRL_TRAFFIC_LED);
+
+ else
+ tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+ LED_CTRL_TRAFFIC_OVERRIDE);
+
+ if (msleep_interruptible(500))
+ break;
+ }
+ tw32(MAC_LED_CTRL, tp->led_ctrl);
+ return 0;
+}
+
static void tg3_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
@@ -7565,7 +7644,7 @@ static int tg3_test_link(struct tg3 *tp)
if (!netif_running(tp->dev))
return -ENODEV;
- if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
max = TG3_SERDES_TIMEOUT_SEC;
else
max = TG3_COPPER_TIMEOUT_SEC;
@@ -7850,9 +7929,12 @@ static int tg3_test_memory(struct tg3 *tp)
return err;
}
-static int tg3_test_loopback(struct tg3 *tp)
+#define TG3_MAC_LOOPBACK 0
+#define TG3_PHY_LOOPBACK 1
+
+static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
{
- u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
+ u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
u32 desc_idx;
struct sk_buff *skb, *rx_skb;
u8 *tx_data;
@@ -7860,18 +7942,26 @@ static int tg3_test_loopback(struct tg3 *tp)
int num_pkts, tx_len, rx_len, i, err;
struct tg3_rx_buffer_desc *desc;
- if (!netif_running(tp->dev))
- return -ENODEV;
+ if (loopback_mode == TG3_MAC_LOOPBACK) {
+ mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+ MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
+ MAC_MODE_PORT_MODE_GMII;
+ tw32(MAC_MODE, mac_mode);
+ } else if (loopback_mode == TG3_PHY_LOOPBACK) {
+ 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)
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ tw32(MAC_MODE, mac_mode);
+
+ tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+ BMCR_SPEED1000);
+ }
+ else
+ return -EINVAL;
err = -EIO;
- tg3_reset_hw(tp);
-
- mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
- MAC_MODE_PORT_MODE_GMII;
- tw32(MAC_MODE, mac_mode);
-
tx_len = 1514;
skb = dev_alloc_skb(tx_len);
tx_data = skb_put(skb, tx_len);
@@ -7892,16 +7982,16 @@ static int tg3_test_loopback(struct tg3 *tp)
rx_start_idx = tp->hw_status->idx[0].rx_producer;
- send_idx = 0;
num_pkts = 0;
- tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
+ tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
- send_idx++;
+ tp->tx_prod++;
num_pkts++;
- tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+ tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW,
+ tp->tx_prod);
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
udelay(10);
@@ -7913,7 +8003,7 @@ static int tg3_test_loopback(struct tg3 *tp)
tx_idx = tp->hw_status->idx[0].tx_consumer;
rx_idx = tp->hw_status->idx[0].rx_producer;
- if ((tx_idx == send_idx) &&
+ if ((tx_idx == tp->tx_prod) &&
(rx_idx == (rx_start_idx + num_pkts)))
break;
}
@@ -7921,7 +8011,7 @@ static int tg3_test_loopback(struct tg3 *tp)
pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
- if (tx_idx != send_idx)
+ if (tx_idx != tp->tx_prod)
goto out;
if (rx_idx != rx_start_idx + num_pkts)
@@ -7957,6 +8047,30 @@ out:
return err;
}
+#define TG3_MAC_LOOPBACK_FAILED 1
+#define TG3_PHY_LOOPBACK_FAILED 2
+#define TG3_LOOPBACK_FAILED (TG3_MAC_LOOPBACK_FAILED | \
+ TG3_PHY_LOOPBACK_FAILED)
+
+static int tg3_test_loopback(struct tg3 *tp)
+{
+ int err = 0;
+
+ if (!netif_running(tp->dev))
+ return TG3_LOOPBACK_FAILED;
+
+ tg3_reset_hw(tp);
+
+ if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
+ err |= TG3_MAC_LOOPBACK_FAILED;
+ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
+ err |= TG3_PHY_LOOPBACK_FAILED;
+ }
+
+ return err;
+}
+
static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
u64 *data)
{
@@ -7997,10 +8111,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
etest->flags |= ETH_TEST_FL_FAILED;
data[3] = 1;
}
- if (tg3_test_loopback(tp) != 0) {
+ if ((data[4] = tg3_test_loopback(tp)) != 0)
etest->flags |= ETH_TEST_FL_FAILED;
- data[4] = 1;
- }
tg3_full_unlock(tp);
@@ -8188,10 +8300,12 @@ static struct ethtool_ops tg3_ethtool_ops = {
.self_test_count = tg3_get_test_count,
.self_test = tg3_self_test,
.get_strings = tg3_get_strings,
+ .phys_id = tg3_phys_id,
.get_stats_count = tg3_get_stats_count,
.get_ethtool_stats = tg3_get_ethtool_stats,
.get_coalesce = tg3_get_coalesce,
.set_coalesce = tg3_set_coalesce,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -8252,7 +8366,8 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
tw32(NVRAM_CFG1, nvcfg1);
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)) {
switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -8666,8 +8781,9 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
if (i == (len - 4))
nvram_cmd |= NVRAM_CMD_LAST;
- if ((tp->nvram_jedecnum == JEDEC_ST) &&
- (nvram_cmd & NVRAM_CMD_FIRST)) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+ (tp->nvram_jedecnum == JEDEC_ST) &&
+ (nvram_cmd & NVRAM_CMD_FIRST)) {
if ((ret = tg3_nvram_exec_cmd(tp,
NVRAM_CMD_WREN | NVRAM_CMD_GO |
@@ -9153,14 +9269,6 @@ static int __devinit tg3_is_sun_570X(struct tg3 *tp)
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AA_8) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AB_8) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_11) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_6) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_FE_GATE_700C) },
{ },
@@ -9177,7 +9285,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
#endif
- /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
+ /* If we have an AMD 762 chipset, write
* reordering to the mailbox registers done by the host
* controller can cause major troubles. We read back from
* every mailbox register write to force the writes to be
@@ -9215,6 +9323,69 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+ /* If we have 5702/03 A1 or A2 on certain ICH chipsets,
+ * we need to disable memory and use config. cycles
+ * only to access all registers. The 5702/03 chips
+ * can mistakenly decode the special cycles from the
+ * ICH chipsets as memory write cycles, causing corruption
+ * of register and memory space. Only certain ICH bridges
+ * will drive special cycles with non-zero data during the
+ * address phase which can fall within the 5703's address
+ * range. This is not an ICH bug as the PCI spec allows
+ * non-zero address during special cycles. However, only
+ * these ICH bridges are known to drive non-zero addresses
+ * during special cycles.
+ *
+ * Since special cycles do not cross PCI bridges, we only
+ * enable this workaround if the 5703 is on the secondary
+ * bus of these ICH bridges.
+ */
+ if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) ||
+ (tp->pci_chip_rev_id == CHIPREV_ID_5703_A2)) {
+ static struct tg3_dev_id {
+ u32 vendor;
+ u32 device;
+ u32 rev;
+ } ich_chipsets[] = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_8,
+ PCI_ANY_ID },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_8,
+ PCI_ANY_ID },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_11,
+ 0xa },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_6,
+ PCI_ANY_ID },
+ { },
+ };
+ struct tg3_dev_id *pci_id = &ich_chipsets[0];
+ struct pci_dev *bridge = NULL;
+
+ while (pci_id->vendor != 0) {
+ bridge = pci_get_device(pci_id->vendor, pci_id->device,
+ bridge);
+ if (!bridge) {
+ pci_id++;
+ continue;
+ }
+ if (pci_id->rev != PCI_ANY_ID) {
+ u8 rev;
+
+ pci_read_config_byte(bridge, PCI_REVISION_ID,
+ &rev);
+ if (rev > pci_id->rev)
+ continue;
+ }
+ if (bridge->subordinate &&
+ (bridge->subordinate->number ==
+ tp->pdev->bus->number)) {
+
+ tp->tg3_flags2 |= TG3_FLG2_ICH_WORKAROUND;
+ pci_dev_put(bridge);
+ break;
+ }
+ }
+ }
+
/* Find msi capability. */
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
@@ -9302,6 +9473,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
}
+ /* 5700 BX chips need to have their TX producer index mailboxes
+ * written twice to workaround a bug.
+ */
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
+ tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
+
/* Back to back register writes can cause problems on this chip,
* the workaround is to read back all reg writes except those to
* mailbox regs. See tg3_write_indirect_reg32().
@@ -9325,6 +9502,43 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
}
+ /* Default fast path register access methods */
+ tp->read32 = tg3_read32;
+ tp->write32 = tg3_write32;
+ tp->read32_mbox = tg3_read32;
+ tp->write32_mbox = tg3_write32;
+ tp->write32_tx_mbox = tg3_write32;
+ tp->write32_rx_mbox = tg3_write32;
+
+ /* Various workaround register access methods */
+ if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
+ tp->write32 = tg3_write_indirect_reg32;
+ else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+ tp->write32 = tg3_write_flush_reg32;
+
+ if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
+ (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
+ tp->write32_tx_mbox = tg3_write32_tx_mbox;
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tp->write32_rx_mbox = tg3_write_flush_reg32;
+ }
+
+ if (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND) {
+ tp->read32 = tg3_read_indirect_reg32;
+ tp->write32 = tg3_write_indirect_reg32;
+ tp->read32_mbox = tg3_read_indirect_mbox;
+ tp->write32_mbox = tg3_write_indirect_mbox;
+ tp->write32_tx_mbox = tg3_write_indirect_mbox;
+ tp->write32_rx_mbox = tg3_write_indirect_mbox;
+
+ iounmap(tp->regs);
+ tp->regs = 0;
+
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_MEMORY;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ }
+
/* 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
@@ -9539,14 +9753,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
- /* 5700 BX chips need to have their TX producer index mailboxes
- * written twice to workaround a bug.
- */
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
- tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
- else
- tp->tg3_flags &= ~TG3_FLAG_TXD_MBOX_HWBUG;
-
/* It seems all chips can get confused if TX buffers
* straddle the 4GB address boundary in some cases.
*/
@@ -9578,6 +9784,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
if (prom_getproplen(node, "local-mac-address") == 6) {
prom_getproperty(node, "local-mac-address",
dev->dev_addr, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, 6);
return 0;
}
}
@@ -9589,6 +9796,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
struct net_device *dev = tp->dev;
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
+ memcpy(dev->perm_addr, idprom->id_ethaddr, 6);
return 0;
}
#endif
@@ -9658,6 +9866,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
#endif
return -EINVAL;
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0;
}
@@ -10469,7 +10678,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
return 0;
err_out_iounmap:
- iounmap(tp->regs);
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = 0;
+ }
err_out_free_dev:
free_netdev(dev);
@@ -10491,7 +10703,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
struct tg3 *tp = netdev_priv(dev);
unregister_netdev(dev);
- iounmap(tp->regs);
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = 0;
+ }
free_netdev(dev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5c4433c147fa..c184b773e585 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2049,6 +2049,11 @@ struct tg3 {
spinlock_t lock;
spinlock_t indirect_lock;
+ u32 (*read32) (struct tg3 *, u32);
+ void (*write32) (struct tg3 *, u32, u32);
+ u32 (*read32_mbox) (struct tg3 *, u32);
+ void (*write32_mbox) (struct tg3 *, u32,
+ u32);
void __iomem *regs;
struct net_device *dev;
struct pci_dev *pdev;
@@ -2060,6 +2065,8 @@ struct tg3 {
u32 msg_enable;
/* begin "tx thread" cacheline section */
+ void (*write32_tx_mbox) (struct tg3 *, u32,
+ u32);
u32 tx_prod;
u32 tx_cons;
u32 tx_pending;
@@ -2071,6 +2078,8 @@ struct tg3 {
dma_addr_t tx_desc_mapping;
/* begin "rx thread" cacheline section */
+ void (*write32_rx_mbox) (struct tg3 *, u32,
+ u32);
u32 rx_rcb_ptr;
u32 rx_std_ptr;
u32 rx_jumbo_ptr;
@@ -2165,6 +2174,7 @@ struct tg3 {
#define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \
TG3_FLG2_MII_SERDES)
#define TG3_FLG2_PARALLEL_DETECT 0x01000000
+#define TG3_FLG2_ICH_WORKAROUND 0x02000000
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 7e99e9f8045e..e4cfc80b283b 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -84,7 +84,7 @@ config 3C359
config TMS380TR
tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
- depends on TR && (PCI || ISA && ISA_DMA_API)
+ depends on TR && (PCI || ISA && ISA_DMA_API || MCA)
select FW_LOADER
---help---
This driver provides generic support for token ring adapters
@@ -158,7 +158,7 @@ config ABYSS
config MADGEMC
tristate "Madge Smart 16/4 Ringnode MicroChannel"
- depends on TR && TMS380TR && MCA_LEGACY
+ depends on TR && TMS380TR && MCA
help
This tms380 module supports the Madge Smart 16/4 MC16 and MC32
MicroChannel adapters.
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 87103c400999..9345e68c451e 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -139,7 +139,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
*/
dev->base_addr += 0x10;
- ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
printk("%s: unable to get memory for dev->priv.\n",
dev->name);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 659cbdbef7f3..3a25d191ea4a 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -20,7 +20,7 @@
static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
#include <linux/module.h>
-#include <linux/mca-legacy.h>
+#include <linux/mca.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -38,9 +38,7 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
#define MADGEMC_IO_EXTENT 32
#define MADGEMC_SIF_OFFSET 0x08
-struct madgemc_card {
- struct net_device *dev;
-
+struct card_info {
/*
* These are read from the BIA ROM.
*/
@@ -57,16 +55,12 @@ struct madgemc_card {
unsigned int arblevel:4;
unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */
unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */
-
- struct madgemc_card *next;
};
-static struct madgemc_card *madgemc_card_list;
-
static int madgemc_open(struct net_device *dev);
static int madgemc_close(struct net_device *dev);
static int madgemc_chipset_init(struct net_device *dev);
-static void madgemc_read_rom(struct madgemc_card *card);
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card);
static unsigned short madgemc_setnselout_pins(struct net_device *dev);
static void madgemc_setcabletype(struct net_device *dev, int type);
@@ -151,261 +145,237 @@ static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsign
-static int __init madgemc_probe(void)
+static int __devinit madgemc_probe(struct device *device)
{
static int versionprinted;
struct net_device *dev;
struct net_local *tp;
- struct madgemc_card *card;
- int i,slot = 0;
- __u8 posreg[4];
-
- if (!MCA_bus)
- return -1;
-
- while (slot != MCA_NOTFOUND) {
- /*
- * Currently we only support the MC16/32 (MCA ID 002d)
- */
- slot = mca_find_unused_adapter(0x002d, slot);
- if (slot == MCA_NOTFOUND)
- break;
-
- /*
- * If we get here, we have an adapter.
- */
- if (versionprinted++ == 0)
- printk("%s", version);
-
- dev = alloc_trdev(sizeof(struct net_local));
- if (dev == NULL) {
- printk("madgemc: unable to allocate dev space\n");
- if (madgemc_card_list)
- return 0;
- return -1;
- }
+ struct card_info *card;
+ struct mca_device *mdev = to_mca_device(device);
+ int ret = 0, i = 0;
+
+ if (versionprinted++ == 0)
+ printk("%s", version);
+
+ if(mca_device_claimed(mdev))
+ return -EBUSY;
+ mca_device_set_claim(mdev, 1);
+
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev) {
+ printk("madgemc: unable to allocate dev space\n");
+ mca_device_set_claim(mdev, 0);
+ ret = -ENOMEM;
+ goto getout;
+ }
- SET_MODULE_OWNER(dev);
- dev->dma = 0;
+ SET_MODULE_OWNER(dev);
+ dev->dma = 0;
- /*
- * Fetch MCA config registers
- */
- for(i=0;i<4;i++)
- posreg[i] = mca_read_stored_pos(slot, i+2);
-
- card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL);
- if (card==NULL) {
- printk("madgemc: unable to allocate card struct\n");
- free_netdev(dev);
- if (madgemc_card_list)
- return 0;
- return -1;
- }
- card->dev = dev;
-
- /*
- * Parse configuration information. This all comes
- * directly from the publicly available @002d.ADF.
- * Get it from Madge or your local ADF library.
- */
-
- /*
- * Base address
- */
- dev->base_addr = 0x0a20 +
- ((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) +
- ((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) +
- ((posreg[3] & MC16_POS3_ADDR3)?0x2000:0);
-
- /*
- * Interrupt line
- */
- switch(posreg[0] >> 6) { /* upper two bits */
+ card = kmalloc(sizeof(struct card_info), GFP_KERNEL);
+ if (card==NULL) {
+ printk("madgemc: unable to allocate card struct\n");
+ ret = -ENOMEM;
+ goto getout1;
+ }
+
+ /*
+ * Parse configuration information. This all comes
+ * directly from the publicly available @002d.ADF.
+ * Get it from Madge or your local ADF library.
+ */
+
+ /*
+ * Base address
+ */
+ dev->base_addr = 0x0a20 +
+ ((mdev->pos[2] & MC16_POS2_ADDR2)?0x0400:0) +
+ ((mdev->pos[0] & MC16_POS0_ADDR1)?0x1000:0) +
+ ((mdev->pos[3] & MC16_POS3_ADDR3)?0x2000:0);
+
+ /*
+ * Interrupt line
+ */
+ switch(mdev->pos[0] >> 6) { /* upper two bits */
case 0x1: dev->irq = 3; break;
case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */
case 0x3: dev->irq = 10; break;
default: dev->irq = 0; break;
- }
+ }
- if (dev->irq == 0) {
- printk("%s: invalid IRQ\n", dev->name);
- goto getout1;
- }
+ if (dev->irq == 0) {
+ printk("%s: invalid IRQ\n", dev->name);
+ ret = -EBUSY;
+ goto getout2;
+ }
- if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT,
- "madgemc")) {
- printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
- dev->base_addr += MADGEMC_SIF_OFFSET;
- goto getout1;
- }
+ if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT,
+ "madgemc")) {
+ printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", mdev->slot, dev->base_addr);
dev->base_addr += MADGEMC_SIF_OFFSET;
+ ret = -EBUSY;
+ goto getout2;
+ }
+ dev->base_addr += MADGEMC_SIF_OFFSET;
+
+ /*
+ * Arbitration Level
+ */
+ card->arblevel = ((mdev->pos[0] >> 1) & 0x7) + 8;
+
+ /*
+ * Burst mode and Fairness
+ */
+ card->burstmode = ((mdev->pos[2] >> 6) & 0x3);
+ card->fairness = ((mdev->pos[2] >> 4) & 0x1);
+
+ /*
+ * Ring Speed
+ */
+ if ((mdev->pos[1] >> 2)&0x1)
+ card->ringspeed = 2; /* not selected */
+ else if ((mdev->pos[2] >> 5) & 0x1)
+ card->ringspeed = 1; /* 16Mb */
+ else
+ card->ringspeed = 0; /* 4Mb */
+
+ /*
+ * Cable type
+ */
+ if ((mdev->pos[1] >> 6)&0x1)
+ card->cabletype = 1; /* STP/DB9 */
+ else
+ card->cabletype = 0; /* UTP/RJ-45 */
+
+
+ /*
+ * ROM Info. This requires us to actually twiddle
+ * bits on the card, so we must ensure above that
+ * the base address is free of conflict (request_region above).
+ */
+ madgemc_read_rom(dev, card);
- /*
- * Arbitration Level
- */
- card->arblevel = ((posreg[0] >> 1) & 0x7) + 8;
-
- /*
- * Burst mode and Fairness
- */
- card->burstmode = ((posreg[2] >> 6) & 0x3);
- card->fairness = ((posreg[2] >> 4) & 0x1);
-
- /*
- * Ring Speed
- */
- if ((posreg[1] >> 2)&0x1)
- card->ringspeed = 2; /* not selected */
- else if ((posreg[2] >> 5) & 0x1)
- card->ringspeed = 1; /* 16Mb */
- else
- card->ringspeed = 0; /* 4Mb */
-
- /*
- * Cable type
- */
- if ((posreg[1] >> 6)&0x1)
- card->cabletype = 1; /* STP/DB9 */
- else
- card->cabletype = 0; /* UTP/RJ-45 */
-
-
- /*
- * ROM Info. This requires us to actually twiddle
- * bits on the card, so we must ensure above that
- * the base address is free of conflict (request_region above).
- */
- madgemc_read_rom(card);
-
- if (card->manid != 0x4d) { /* something went wrong */
- printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
- goto getout;
- }
+ if (card->manid != 0x4d) { /* something went wrong */
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
+ goto getout3;
+ }
- if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
- printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
- goto getout;
- }
+ if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
+ ret = -EIO;
+ goto getout3;
+ }
- /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
- if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
- card->ramsize = 128;
- else
- card->ramsize = 256;
-
- printk("%s: %s Rev %d at 0x%04lx IRQ %d\n",
- dev->name,
- (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
- MADGEMC32_CARDNAME, card->cardrev,
- dev->base_addr, dev->irq);
-
- if (card->cardtype == 0x0d)
- printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name);
-
- if (card->ringspeed==2) { /* Unknown */
- printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
- card->ringspeed = 1; /* default to 16mb */
- }
+ /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
+ if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
+ card->ramsize = 128;
+ else
+ card->ramsize = 256;
+
+ printk("%s: %s Rev %d at 0x%04lx IRQ %d\n",
+ dev->name,
+ (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
+ MADGEMC32_CARDNAME, card->cardrev,
+ dev->base_addr, dev->irq);
+
+ if (card->cardtype == 0x0d)
+ printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name);
+
+ if (card->ringspeed==2) { /* Unknown */
+ printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
+ card->ringspeed = 1; /* default to 16mb */
+ }
- printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize);
+ printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize);
- printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name,
- (card->ringspeed)?16:4,
- card->cabletype?"STP/DB9":"UTP/RJ-45");
- printk("%s: Arbitration Level: %d\n", dev->name,
- card->arblevel);
+ printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name,
+ (card->ringspeed)?16:4,
+ card->cabletype?"STP/DB9":"UTP/RJ-45");
+ printk("%s: Arbitration Level: %d\n", dev->name,
+ card->arblevel);
- printk("%s: Burst Mode: ", dev->name);
- switch(card->burstmode) {
+ printk("%s: Burst Mode: ", dev->name);
+ switch(card->burstmode) {
case 0: printk("Cycle steal"); break;
case 1: printk("Limited burst"); break;
case 2: printk("Delayed release"); break;
case 3: printk("Immediate release"); break;
- }
- printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
-
-
- /*
- * Enable SIF before we assign the interrupt handler,
- * just in case we get spurious interrupts that need
- * handling.
- */
- outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
- madgemc_setsifsel(dev, 1);
- if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
- "madgemc", dev))
- goto getout;
-
- madgemc_chipset_init(dev); /* enables interrupts! */
- madgemc_setcabletype(dev, card->cabletype);
+ }
+ printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
- /* Setup MCA structures */
- mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
- mca_set_adapter_procfn(slot, madgemc_mcaproc, dev);
- mca_mark_as_used(slot);
- printk("%s: Ring Station Address: ", dev->name);
- printk("%2.2x", dev->dev_addr[0]);
- for (i = 1; i < 6; i++)
- printk(":%2.2x", dev->dev_addr[i]);
- printk("\n");
-
- /* XXX is ISA_MAX_ADDRESS correct here? */
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) {
- printk("%s: unable to get memory for dev->priv.\n",
- dev->name);
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
- MADGEMC_IO_EXTENT);
-
- kfree(card);
- tmsdev_term(dev);
- free_netdev(dev);
- if (madgemc_card_list)
- return 0;
- return -1;
- }
- tp = netdev_priv(dev);
-
- /*
- * The MC16 is physically a 32bit card. However, Madge
- * insists on calling it 16bit, so I'll assume here that
- * they know what they're talking about. Cut off DMA
- * at 16mb.
- */
- tp->setnselout = madgemc_setnselout_pins;
- tp->sifwriteb = madgemc_sifwriteb;
- tp->sifreadb = madgemc_sifreadb;
- tp->sifwritew = madgemc_sifwritew;
- tp->sifreadw = madgemc_sifreadw;
- tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
-
- memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1);
-
- dev->open = madgemc_open;
- dev->stop = madgemc_close;
-
- if (register_netdev(dev) == 0) {
- /* Enlist in the card list */
- card->next = madgemc_card_list;
- madgemc_card_list = card;
- slot++;
- continue; /* successful, try to find another */
- }
-
- free_irq(dev->irq, dev);
- getout:
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
- MADGEMC_IO_EXTENT);
- getout1:
- kfree(card);
- free_netdev(dev);
- slot++;
+ /*
+ * Enable SIF before we assign the interrupt handler,
+ * just in case we get spurious interrupts that need
+ * handling.
+ */
+ outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
+ madgemc_setsifsel(dev, 1);
+ if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
+ "madgemc", dev)) {
+ ret = -EBUSY;
+ goto getout3;
}
- if (madgemc_card_list)
+ madgemc_chipset_init(dev); /* enables interrupts! */
+ madgemc_setcabletype(dev, card->cabletype);
+
+ /* Setup MCA structures */
+ mca_device_set_name(mdev, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
+ mca_set_adapter_procfn(mdev->slot, madgemc_mcaproc, dev);
+
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ if (tmsdev_init(dev, device)) {
+ printk("%s: unable to get memory for dev->priv.\n",
+ dev->name);
+ ret = -ENOMEM;
+ goto getout4;
+ }
+ tp = netdev_priv(dev);
+
+ /*
+ * The MC16 is physically a 32bit card. However, Madge
+ * insists on calling it 16bit, so I'll assume here that
+ * they know what they're talking about. Cut off DMA
+ * at 16mb.
+ */
+ tp->setnselout = madgemc_setnselout_pins;
+ tp->sifwriteb = madgemc_sifwriteb;
+ tp->sifreadb = madgemc_sifreadb;
+ tp->sifwritew = madgemc_sifwritew;
+ tp->sifreadw = madgemc_sifreadw;
+ tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
+
+ memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1);
+
+ dev->open = madgemc_open;
+ dev->stop = madgemc_close;
+
+ tp->tmspriv = card;
+ dev_set_drvdata(device, dev);
+
+ if (register_netdev(dev) == 0)
return 0;
- return -1;
+
+ dev_set_drvdata(device, NULL);
+ ret = -ENOMEM;
+getout4:
+ free_irq(dev->irq, dev);
+getout3:
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
+ MADGEMC_IO_EXTENT);
+getout2:
+ kfree(card);
+getout1:
+ free_netdev(dev);
+getout:
+ mca_device_set_claim(mdev, 0);
+ return ret;
}
/*
@@ -664,12 +634,12 @@ static void madgemc_chipset_close(struct net_device *dev)
* is complete.
*
*/
-static void madgemc_read_rom(struct madgemc_card *card)
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card)
{
unsigned long ioaddr;
unsigned char reg0, reg1, tmpreg0, i;
- ioaddr = card->dev->base_addr;
+ ioaddr = dev->base_addr;
reg0 = inb(ioaddr + MC_CONTROL_REG0);
reg1 = inb(ioaddr + MC_CONTROL_REG1);
@@ -686,9 +656,9 @@ static void madgemc_read_rom(struct madgemc_card *card)
outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);
/* Read BIA */
- card->dev->addr_len = 6;
+ dev->addr_len = 6;
for (i = 0; i < 6; i++)
- card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
+ dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
/* Restore original register values */
outb(reg0, ioaddr + MC_CONTROL_REG0);
@@ -721,14 +691,10 @@ static int madgemc_close(struct net_device *dev)
static int madgemc_mcaproc(char *buf, int slot, void *d)
{
struct net_device *dev = (struct net_device *)d;
- struct madgemc_card *curcard = madgemc_card_list;
+ struct net_local *tp = dev->priv;
+ struct card_info *curcard = tp->tmspriv;
int len = 0;
- while (curcard) { /* search for card struct */
- if (curcard->dev == dev)
- break;
- curcard = curcard->next;
- }
len += sprintf(buf+len, "-------\n");
if (curcard) {
struct net_local *tp = netdev_priv(dev);
@@ -763,25 +729,56 @@ static int madgemc_mcaproc(char *buf, int slot, void *d)
return len;
}
-static void __exit madgemc_exit(void)
+static int __devexit madgemc_remove(struct device *device)
{
- struct net_device *dev;
- struct madgemc_card *this_card;
-
- while (madgemc_card_list) {
- dev = madgemc_card_list->dev;
- unregister_netdev(dev);
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
- free_irq(dev->irq, dev);
- tmsdev_term(dev);
- free_netdev(dev);
- this_card = madgemc_card_list;
- madgemc_card_list = this_card->next;
- kfree(this_card);
- }
+ struct net_device *dev = dev_get_drvdata(device);
+ struct net_local *tp;
+ struct card_info *card;
+
+ if (!dev)
+ BUG();
+
+ tp = dev->priv;
+ card = tp->tmspriv;
+ kfree(card);
+ tp->tmspriv = NULL;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ dev_set_drvdata(device, NULL);
+
+ return 0;
+}
+
+static short madgemc_adapter_ids[] __initdata = {
+ 0x002d,
+ 0x0000
+};
+
+static struct mca_driver madgemc_driver = {
+ .id_table = madgemc_adapter_ids,
+ .driver = {
+ .name = "madgemc",
+ .bus = &mca_bus_type,
+ .probe = madgemc_probe,
+ .remove = __devexit_p(madgemc_remove),
+ },
+};
+
+static int __init madgemc_init (void)
+{
+ return mca_register_driver (&madgemc_driver);
+}
+
+static void __exit madgemc_exit (void)
+{
+ mca_unregister_driver (&madgemc_driver);
}
-module_init(madgemc_probe);
+module_init(madgemc_init);
module_exit(madgemc_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 40ad0fde28af..eb1423ede75c 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -62,8 +62,7 @@ static int dmalist[] __initdata = {
};
static char cardname[] = "Proteon 1392\0";
-
-struct net_device *proteon_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
static int proteon_open(struct net_device *dev);
static void proteon_read_eeprom(struct net_device *dev);
static unsigned short proteon_setnselout_pins(struct net_device *dev);
@@ -116,7 +115,7 @@ nodev:
return -ENODEV;
}
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
{
struct net_local *tp;
static int versionprinted;
@@ -137,7 +136,7 @@ static int __init setup_card(struct net_device *dev)
}
}
if (err)
- goto out4;
+ goto out5;
/* At this point we have found a valid card. */
@@ -145,14 +144,15 @@ static int __init setup_card(struct net_device *dev)
printk(KERN_DEBUG "%s", version);
err = -EIO;
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ pdev->dma_mask = &dma_mask;
+ if (tmsdev_init(dev, pdev))
goto out4;
dev->base_addr &= ~3;
proteon_read_eeprom(dev);
- printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk(KERN_DEBUG "proteon.c: Ring Station Address: ");
printk("%2.2x", dev->dev_addr[0]);
for (j = 1; j < 6; j++)
printk(":%2.2x", dev->dev_addr[j]);
@@ -185,7 +185,7 @@ static int __init setup_card(struct net_device *dev)
if(irqlist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ printk(KERN_INFO "proteon.c: AutoSelect no IRQ available\n");
goto out3;
}
}
@@ -196,15 +196,15 @@ static int __init setup_card(struct net_device *dev)
break;
if (irqlist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "proteon.c: Illegal IRQ %d specified\n",
+ dev->irq);
goto out3;
}
if (request_irq(dev->irq, tms380tr_interrupt, 0,
cardname, dev))
{
- printk(KERN_INFO "%s: Selected IRQ %d not available\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "proteon.c: Selected IRQ %d not available\n",
+ dev->irq);
goto out3;
}
}
@@ -220,7 +220,7 @@ static int __init setup_card(struct net_device *dev)
if(dmalist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ printk(KERN_INFO "proteon.c: AutoSelect no DMA available\n");
goto out2;
}
}
@@ -231,25 +231,25 @@ static int __init setup_card(struct net_device *dev)
break;
if (dmalist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal DMA %d specified\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "proteon.c: Illegal DMA %d specified\n",
+ dev->dma);
goto out2;
}
if (request_dma(dev->dma, cardname))
{
- printk(KERN_INFO "%s: Selected DMA %d not available\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "proteon.c: Selected DMA %d not available\n",
+ dev->dma);
goto out2;
}
}
- printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
- dev->name, dev->base_addr, dev->irq, dev->dma);
-
err = register_netdev(dev);
if (err)
goto out;
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
return 0;
out:
free_dma(dev->dma);
@@ -258,34 +258,11 @@ out2:
out3:
tmsdev_term(dev);
out4:
- release_region(dev->base_addr, PROTEON_IO_EXTENT);
+ release_region(dev->base_addr, PROTEON_IO_EXTENT);
+out5:
return err;
}
-struct net_device * __init proteon_probe(int unit)
-{
- struct net_device *dev = alloc_trdev(sizeof(struct net_local));
- int err = 0;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0) {
- sprintf(dev->name, "tr%d", unit);
- netdev_boot_setup_check(dev);
- }
-
- err = setup_card(dev);
- if (err)
- goto out;
-
- return dev;
-
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* Reads MAC address from adapter RAM, which should've read it from
* the onboard ROM.
@@ -352,8 +329,6 @@ static int proteon_open(struct net_device *dev)
return tms380tr_open(dev);
}
-#ifdef MODULE
-
#define ISATR_MAX_ADAPTERS 3
static int io[ISATR_MAX_ADAPTERS];
@@ -366,13 +341,23 @@ module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param_array(dma, int, NULL, 0);
-static struct net_device *proteon_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];
+
+static struct device_driver proteon_driver = {
+ .name = "proteon",
+ .bus = &platform_bus_type,
+};
-int init_module(void)
+static int __init proteon_init(void)
{
struct net_device *dev;
+ struct platform_device *pdev;
int i, num = 0, err = 0;
+ err = driver_register(&proteon_driver);
+ if (err)
+ return err;
+
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
dev = alloc_trdev(sizeof(struct net_local));
if (!dev)
@@ -381,11 +366,15 @@ int init_module(void)
dev->base_addr = io[i];
dev->irq = irq[i];
dev->dma = dma[i];
- err = setup_card(dev);
+ pdev = platform_device_register_simple("proteon",
+ i, NULL, 0);
+ err = setup_card(dev, &pdev->dev);
if (!err) {
- proteon_dev[i] = dev;
+ proteon_dev[i] = pdev;
+ dev_set_drvdata(&pdev->dev, dev);
++num;
} else {
+ platform_device_unregister(pdev);
free_netdev(dev);
}
}
@@ -399,23 +388,28 @@ int init_module(void)
return (0);
}
-void cleanup_module(void)
+static void __exit proteon_cleanup(void)
{
+ struct net_device *dev;
int i;
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
- struct net_device *dev = proteon_dev[i];
+ struct platform_device *pdev = proteon_dev[i];
- if (!dev)
+ if (!pdev)
continue;
-
+ dev = dev_get_drvdata(&pdev->dev);
unregister_netdev(dev);
release_region(dev->base_addr, PROTEON_IO_EXTENT);
free_irq(dev->irq, dev);
free_dma(dev->dma);
tmsdev_term(dev);
free_netdev(dev);
+ dev_set_drvdata(&pdev->dev, NULL);
+ platform_device_unregister(pdev);
}
+ driver_unregister(&proteon_driver);
}
-#endif /* MODULE */
+module_init(proteon_init);
+module_exit(proteon_cleanup);
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index f26796e2d0e5..3c7c66204f74 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -68,8 +68,7 @@ static int dmalist[] __initdata = {
};
static char isa_cardname[] = "SK NET TR 4/16 ISA\0";
-
-struct net_device *sk_isa_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
static int sk_isa_open(struct net_device *dev);
static void sk_isa_read_eeprom(struct net_device *dev);
static unsigned short sk_isa_setnselout_pins(struct net_device *dev);
@@ -133,7 +132,7 @@ static int __init sk_isa_probe1(struct net_device *dev, int ioaddr)
return 0;
}
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
{
struct net_local *tp;
static int versionprinted;
@@ -154,7 +153,7 @@ static int __init setup_card(struct net_device *dev)
}
}
if (err)
- goto out4;
+ goto out5;
/* At this point we have found a valid card. */
@@ -162,14 +161,15 @@ static int __init setup_card(struct net_device *dev)
printk(KERN_DEBUG "%s", version);
err = -EIO;
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ pdev->dma_mask = &dma_mask;
+ if (tmsdev_init(dev, pdev))
goto out4;
dev->base_addr &= ~3;
sk_isa_read_eeprom(dev);
- printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk(KERN_DEBUG "skisa.c: Ring Station Address: ");
printk("%2.2x", dev->dev_addr[0]);
for (j = 1; j < 6; j++)
printk(":%2.2x", dev->dev_addr[j]);
@@ -202,7 +202,7 @@ static int __init setup_card(struct net_device *dev)
if(irqlist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ printk(KERN_INFO "skisa.c: AutoSelect no IRQ available\n");
goto out3;
}
}
@@ -213,15 +213,15 @@ static int __init setup_card(struct net_device *dev)
break;
if (irqlist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "skisa.c: Illegal IRQ %d specified\n",
+ dev->irq);
goto out3;
}
if (request_irq(dev->irq, tms380tr_interrupt, 0,
isa_cardname, dev))
{
- printk(KERN_INFO "%s: Selected IRQ %d not available\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "skisa.c: Selected IRQ %d not available\n",
+ dev->irq);
goto out3;
}
}
@@ -237,7 +237,7 @@ static int __init setup_card(struct net_device *dev)
if(dmalist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ printk(KERN_INFO "skisa.c: AutoSelect no DMA available\n");
goto out2;
}
}
@@ -248,25 +248,25 @@ static int __init setup_card(struct net_device *dev)
break;
if (dmalist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal DMA %d specified\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "skisa.c: Illegal DMA %d specified\n",
+ dev->dma);
goto out2;
}
if (request_dma(dev->dma, isa_cardname))
{
- printk(KERN_INFO "%s: Selected DMA %d not available\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "skisa.c: Selected DMA %d not available\n",
+ dev->dma);
goto out2;
}
}
- printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
- dev->name, dev->base_addr, dev->irq, dev->dma);
-
err = register_netdev(dev);
if (err)
goto out;
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
return 0;
out:
free_dma(dev->dma);
@@ -275,33 +275,11 @@ out2:
out3:
tmsdev_term(dev);
out4:
- release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+ release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+out5:
return err;
}
-struct net_device * __init sk_isa_probe(int unit)
-{
- struct net_device *dev = alloc_trdev(sizeof(struct net_local));
- int err = 0;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0) {
- sprintf(dev->name, "tr%d", unit);
- netdev_boot_setup_check(dev);
- }
-
- err = setup_card(dev);
- if (err)
- goto out;
-
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* Reads MAC address from adapter RAM, which should've read it from
* the onboard ROM.
@@ -361,8 +339,6 @@ static int sk_isa_open(struct net_device *dev)
return tms380tr_open(dev);
}
-#ifdef MODULE
-
#define ISATR_MAX_ADAPTERS 3
static int io[ISATR_MAX_ADAPTERS];
@@ -375,13 +351,23 @@ module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param_array(dma, int, NULL, 0);
-static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
-int init_module(void)
+static struct device_driver sk_isa_driver = {
+ .name = "skisa",
+ .bus = &platform_bus_type,
+};
+
+static int __init sk_isa_init(void)
{
struct net_device *dev;
+ struct platform_device *pdev;
int i, num = 0, err = 0;
+ err = driver_register(&sk_isa_driver);
+ if (err)
+ return err;
+
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
dev = alloc_trdev(sizeof(struct net_local));
if (!dev)
@@ -390,12 +376,15 @@ int init_module(void)
dev->base_addr = io[i];
dev->irq = irq[i];
dev->dma = dma[i];
- err = setup_card(dev);
-
+ pdev = platform_device_register_simple("skisa",
+ i, NULL, 0);
+ err = setup_card(dev, &pdev->dev);
if (!err) {
- sk_isa_dev[i] = dev;
+ sk_isa_dev[i] = pdev;
+ dev_set_drvdata(&sk_isa_dev[i]->dev, dev);
++num;
} else {
+ platform_device_unregister(pdev);
free_netdev(dev);
}
}
@@ -409,23 +398,28 @@ int init_module(void)
return (0);
}
-void cleanup_module(void)
+static void __exit sk_isa_cleanup(void)
{
+ struct net_device *dev;
int i;
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
- struct net_device *dev = sk_isa_dev[i];
+ struct platform_device *pdev = sk_isa_dev[i];
- if (!dev)
+ if (!pdev)
continue;
-
+ dev = dev_get_drvdata(&pdev->dev);
unregister_netdev(dev);
release_region(dev->base_addr, SK_ISA_IO_EXTENT);
free_irq(dev->irq, dev);
free_dma(dev->dma);
tmsdev_term(dev);
free_netdev(dev);
+ dev_set_drvdata(&pdev->dev, NULL);
+ platform_device_unregister(pdev);
}
+ driver_unregister(&sk_isa_driver);
}
-#endif /* MODULE */
+module_init(sk_isa_init);
+module_exit(sk_isa_cleanup);
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 5e0b0ce98ed7..2e39bf1f7462 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -62,6 +62,7 @@
* normal operation.
* 30-Dec-02 JF Removed incorrect __init from
* tms380tr_init_card.
+ * 22-Jul-05 JF Converted to dma-mapping.
*
* To do:
* 1. Multi/Broadcast packet handling (this may have fixed itself)
@@ -89,7 +90,7 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -114,8 +115,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
#endif
static unsigned int tms380tr_debug = TMS380TR_DEBUG;
-static struct device tms_device;
-
/* Index to functions, as function prototypes.
* Alphabetical by function name.
*/
@@ -434,7 +433,7 @@ static void tms380tr_init_net_local(struct net_device *dev)
skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
/* data unreachable for DMA ? then use local buffer */
- dmabuf = pci_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
{
tp->Rpl[i].SkbStat = SKB_DATA_COPY;
@@ -638,10 +637,10 @@ static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device
/* Is buffer reachable for Busmaster-DMA? */
length = skb->len;
- dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
+ dmabuf = dma_map_single(tp->pdev, skb->data, length, DMA_TO_DEVICE);
if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) {
/* Copy frame to local buffer */
- pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, dmabuf, length, DMA_TO_DEVICE);
dmabuf = 0;
i = tp->TplFree->TPLIndex;
buf = tp->LocalTxBuffers[i];
@@ -1284,9 +1283,7 @@ static int tms380tr_reset_adapter(struct net_device *dev)
unsigned short count, c, count2;
const struct firmware *fw_entry = NULL;
- strncpy(tms_device.bus_id,dev->name, BUS_ID_SIZE);
-
- if (request_firmware(&fw_entry, "tms380tr.bin", &tms_device) != 0) {
+ if (request_firmware(&fw_entry, "tms380tr.bin", tp->pdev) != 0) {
printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
dev->name, "tms380tr.bin");
return (-1);
@@ -2021,7 +2018,7 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp)
printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
if (tpl->DMABuff)
- pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(tpl->Skb);
}
@@ -2090,7 +2087,7 @@ static void tms380tr_tx_status_irq(struct net_device *dev)
tp->MacStat.tx_packets++;
if (tpl->DMABuff)
- pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
dev_kfree_skb_irq(tpl->Skb);
tpl->BusyFlag = 0; /* "free" TPL */
}
@@ -2209,7 +2206,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
tp->MacStat.rx_errors++;
}
if (rpl->DMABuff)
- pci_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, DMA_TO_DEVICE);
rpl->DMABuff = 0;
/* Allocate new skb for rpl */
@@ -2227,7 +2224,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
skb_put(rpl->Skb, tp->MaxPacketSize);
/* Data unreachable for DMA ? then use local buffer */
- dmabuf = pci_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
{
rpl->SkbStat = SKB_DATA_COPY;
@@ -2332,23 +2329,26 @@ void tmsdev_term(struct net_device *dev)
struct net_local *tp;
tp = netdev_priv(dev);
- pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
+ DMA_BIDIRECTIONAL);
}
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
- struct pci_dev *pdev)
+int tmsdev_init(struct net_device *dev, struct device *pdev)
{
struct net_local *tms_local;
memset(dev->priv, 0, sizeof(struct net_local));
tms_local = netdev_priv(dev);
init_waitqueue_head(&tms_local->wait_for_tok_int);
- tms_local->dmalimit = dmalimit;
+ if (pdev->dma_mask)
+ tms_local->dmalimit = *pdev->dma_mask;
+ else
+ return -ENOMEM;
tms_local->pdev = pdev;
- tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local,
- sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL);
- if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit)
+ tms_local->dmabuffer = dma_map_single(pdev, (void *)tms_local,
+ sizeof(struct net_local), DMA_BIDIRECTIONAL);
+ if (tms_local->dmabuffer + sizeof(struct net_local) >
+ tms_local->dmalimit)
{
printk(KERN_INFO "%s: Memory not accessible for DMA\n",
dev->name);
@@ -2370,8 +2370,6 @@ int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
return 0;
}
-#ifdef MODULE
-
EXPORT_SYMBOL(tms380tr_open);
EXPORT_SYMBOL(tms380tr_close);
EXPORT_SYMBOL(tms380tr_interrupt);
@@ -2379,6 +2377,8 @@ EXPORT_SYMBOL(tmsdev_init);
EXPORT_SYMBOL(tmsdev_term);
EXPORT_SYMBOL(tms380tr_wait);
+#ifdef MODULE
+
static struct module *TMS380_module = NULL;
int init_module(void)
diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h
index f2c5ba0f37a5..30452c67bb68 100644
--- a/drivers/net/tokenring/tms380tr.h
+++ b/drivers/net/tokenring/tms380tr.h
@@ -17,8 +17,7 @@
int tms380tr_open(struct net_device *dev);
int tms380tr_close(struct net_device *dev);
irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
- struct pci_dev *pdev);
+int tmsdev_init(struct net_device *dev, struct device *pdev);
void tmsdev_term(struct net_device *dev);
void tms380tr_wait(unsigned long time);
@@ -719,7 +718,7 @@ struct s_TPL { /* Transmit Parameter List (align on even word boundaries) */
struct sk_buff *Skb;
unsigned char TPLIndex;
volatile unsigned char BusyFlag;/* Flag: TPL busy? */
- dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
};
/* ---------------------Receive Functions-------------------------------*
@@ -1060,7 +1059,7 @@ struct s_RPL { /* Receive Parameter List */
struct sk_buff *Skb;
SKB_STAT SkbStat;
int RPLIndex;
- dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
};
/* Information that need to be kept for each board. */
@@ -1091,7 +1090,7 @@ typedef struct net_local {
RPL *RplTail;
unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
- struct pci_dev *pdev;
+ struct device *pdev;
int DataRate;
unsigned char ScbInUse;
unsigned short CMDqueue;
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 2e18c0a46482..ab47c0547a3b 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -100,7 +100,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
unsigned int pci_irq_line;
unsigned long pci_ioaddr;
struct card_info *cardinfo = &card_info_table[ent->driver_data];
-
+
if (versionprinted++ == 0)
printk("%s", version);
@@ -143,7 +143,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
printk(":%2.2x", dev->dev_addr[i]);
printk("\n");
- ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
printk("%s: unable to get memory for dev->priv.\n", dev->name);
goto err_out_irq;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index e2cdaf876201..8c9634a98c11 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -135,6 +135,18 @@ config DM9102
<file:Documentation/networking/net-modules.txt>. The module will
be called dmfe.
+config ULI526X
+ tristate "ULi M526x controller support"
+ depends on NET_TULIP && PCI
+ select CRC32
+ ---help---
+ This driver is for ULi M5261/M5263 10/100M Ethernet Controller
+ (<http://www.uli.com.tw/>).
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called uli526x.
+
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
depends on NET_TULIP && CARDBUS
diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile
index 8bb9b4683979..451090d6fcca 100644
--- a/drivers/net/tulip/Makefile
+++ b/drivers/net/tulip/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_WINBOND_840) += winbond-840.o
obj-$(CONFIG_DE2104X) += de2104x.o
obj-$(CONFIG_TULIP) += tulip.o
obj-$(CONFIG_DE4X5) += de4x5.o
+obj-$(CONFIG_ULI526X) += uli526x.o
# Declare multi-part drivers.
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index fc353e348f9a..a22d00198e4d 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1934,7 +1934,7 @@ static int __init de_init_one (struct pci_dev *pdev,
struct de_private *de;
int rc;
void __iomem *regs;
- long pciaddr;
+ unsigned long pciaddr;
static int board_idx = -1;
board_idx++;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 93800c126e86..ee48bfd67349 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -2144,9 +2144,9 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
int i, j, cfrv;
struct de4x5_private *lp = netdev_priv(dev);
- struct list_head *walk = &pdev->bus_list;
+ struct list_head *walk;
- for (walk = walk->next; walk != &pdev->bus_list; walk = walk->next) {
+ list_for_each(walk, &pdev->bus_list) {
struct pci_dev *this_dev = pci_dev_b(walk);
/* Skip the pci_bus list entry */
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index e26c31f944bf..f53396fe79c9 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -81,25 +81,6 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
return retval & 0xffff;
}
- if(tp->chip_id == ULI526X && tp->revision >= 0x40) {
- int value;
- int i = 1000;
-
- value = ioread32(ioaddr + CSR9);
- iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-
- value = (phy_id << 21) | (location << 16) | 0x08000000;
- iowrite32(value, ioaddr + CSR10);
-
- while(--i > 0) {
- mdio_delay();
- if(ioread32(ioaddr + CSR10) & 0x10000000)
- break;
- }
- retval = ioread32(ioaddr + CSR10);
- spin_unlock_irqrestore(&tp->mii_lock, flags);
- return retval & 0xFFFF;
- }
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -159,23 +140,6 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
spin_unlock_irqrestore(&tp->mii_lock, flags);
return;
}
- if (tp->chip_id == ULI526X && tp->revision >= 0x40) {
- int value;
- int i = 1000;
-
- value = ioread32(ioaddr + CSR9);
- iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-
- value = (phy_id << 21) | (location << 16) | 0x04000000 | (val & 0xFFFF);
- iowrite32(value, ioaddr + CSR10);
-
- while(--i > 0) {
- if (ioread32(ioaddr + CSR10) & 0x10000000)
- break;
- }
- spin_unlock_irqrestore(&tp->mii_lock, flags);
- return;
- }
/* Establish sync by sending 32 logic ones. */
for (i = 32; i >= 0; i--) {
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
index 691568283553..e058a9fbfe88 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/tulip/timer.c
@@ -39,7 +39,6 @@ void tulip_timer(unsigned long data)
case MX98713:
case COMPEX9881:
case DM910X:
- case ULI526X:
default: {
struct medialeaf *mleaf;
unsigned char *p;
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 20346d847d9e..05d2d96f7be2 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -88,7 +88,6 @@ enum chips {
I21145,
DM910X,
CONEXANT,
- ULI526X
};
@@ -482,11 +481,8 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
static inline void tulip_restart_rxtx(struct tulip_private *tp)
{
- if(!(tp->chip_id == ULI526X &&
- (tp->revision == 0x40 || tp->revision == 0x50))) {
- tulip_stop_rxtx(tp);
- udelay(5);
- }
+ tulip_stop_rxtx(tp);
+ udelay(5);
tulip_start_rxtx(tp);
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index d45d8f56e5b4..6266a9a7e6e3 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -199,9 +199,6 @@ struct tulip_chip_table tulip_tbl[] = {
{ "Conexant LANfinity", 256, 0x0001ebef,
HAS_MII | HAS_ACPI, tulip_timer },
- /* ULi526X */
- { "ULi M5261/M5263", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
};
@@ -239,10 +236,9 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
- { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
- { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
{ 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+ { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -522,7 +518,7 @@ static void tulip_tx_timeout(struct net_device *dev)
dev->name);
} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
|| tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
- || tp->chip_id == DM910X || tp->chip_id == ULI526X) {
+ || tp->chip_id == DM910X) {
printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
"SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
@@ -1103,18 +1099,16 @@ static void set_rx_mode(struct net_device *dev)
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
- /* Avoid a chip errata by prefixing a dummy entry. Don't do
- this on the ULI526X as it triggers a different problem */
- if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
- tp->tx_buffers[entry].skb = NULL;
- tp->tx_buffers[entry].mapping = 0;
- tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
- tp->tx_ring[entry].buffer1 = 0;
- /* Must set DescOwned later to avoid race with chip */
- dummy = entry;
- entry = tp->cur_tx++ % TX_RING_SIZE;
- }
+ /* Avoid a chip errata by prefixing a dummy entry. */
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ /* Must set DescOwned later to avoid race with chip */
+ dummy = entry;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+
}
tp->tx_buffers[entry].skb = NULL;
@@ -1235,10 +1229,6 @@ static int tulip_uli_dm_quirk(struct pci_dev *pdev)
{
if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
- return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
- return 1;
return 0;
}
@@ -1680,7 +1670,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
switch (chip_idx) {
case DC21140:
case DM910X:
- case ULI526X:
default:
if (tp->mtable)
iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
new file mode 100644
index 000000000000..1a4316336256
--- /dev/null
+++ b/drivers/net/tulip/uli526x.c
@@ -0,0 +1,1749 @@
+/*
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the 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.
+
+
+*/
+
+#define DRV_NAME "uli526x"
+#define DRV_VERSION "0.9.3"
+#define DRV_RELDATE "2005-7-29"
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+
+/* Board/System/Debug information/definition ---------------- */
+#define PCI_ULI5261_ID 0x526110B9 /* ULi M5261 ID*/
+#define PCI_ULI5263_ID 0x526310B9 /* ULi M5263 ID*/
+
+#define ULI526X_IO_SIZE 0x100
+#define TX_DESC_CNT 0x20 /* Allocated Tx descriptors */
+#define RX_DESC_CNT 0x30 /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x600
+#define RX_ALLOC_SIZE 0x620
+#define ULI526X_RESET 1
+#define CR0_DEFAULT 0
+#define CR6_DEFAULT 0x22200000
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define ULI5261_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+
+#define ULI526X_10MHF 0
+#define ULI526X_100MHF 1
+#define ULI526X_10MFD 4
+#define ULI526X_100MFD 5
+#define ULI526X_AUTO 8
+
+#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */
+#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */
+#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */
+#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */
+#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */
+#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+#define ULI526X_TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */
+#define ULI526X_TX_TIMEOUT ((16*HZ)/2) /* tx packet time-out time 8 s" */
+#define ULI526X_TX_KICK (4*HZ/2) /* tx packet Kick-out time 2 s" */
+
+#define ULI526X_DBUG(dbug_now, msg, value) if (uli526x_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) \
+ outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+ udelay(5);
+
+/* Structure/enum declaration ------------------------------- */
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ char *tx_buf_ptr; /* Data for us */
+ struct tx_desc *next_tx_desc;
+} __attribute__(( aligned(32) ));
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ struct sk_buff *rx_skb_ptr; /* Data for us */
+ struct rx_desc *next_rx_desc;
+} __attribute__(( aligned(32) ));
+
+struct uli526x_board_info {
+ u32 chip_id; /* Chip vendor/Device ID */
+ struct net_device *next_dev; /* next device */
+ struct pci_dev *pdev; /* PCI device */
+ spinlock_t lock;
+
+ long ioaddr; /* I/O base address */
+ u32 cr0_data;
+ u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ /* pointer for memory physical address */
+ dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */
+ dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */
+ dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */
+ dma_addr_t first_tx_desc_dma;
+ dma_addr_t first_rx_desc_dma;
+
+ /* descriptor pointer */
+ unsigned char *buf_pool_ptr; /* Tx buffer pool memory */
+ unsigned char *buf_pool_start; /* Tx buffer pool align dword */
+ unsigned char *desc_pool_ptr; /* descriptor pool memory */
+ struct tx_desc *first_tx_desc;
+ struct tx_desc *tx_insert_ptr;
+ struct tx_desc *tx_remove_ptr;
+ struct rx_desc *first_rx_desc;
+ struct rx_desc *rx_insert_ptr;
+ struct rx_desc *rx_ready_ptr; /* packet come pointer */
+ unsigned long tx_packet_cnt; /* transmitted packet count */
+ unsigned long rx_avail_cnt; /* available rx descriptor count */
+ unsigned long interval_rx_cnt; /* rx packet count a callback time */
+
+ u16 dbug_cnt;
+ u16 NIC_capability; /* NIC media capability */
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work media mode */
+ u8 phy_addr;
+ u8 link_failed; /* Ever link failed */
+ u8 wait_reset; /* Hardware failed, need to reset */
+ struct timer_list timer;
+
+ /* System defined statistic counter */
+ struct net_device_stats stats;
+
+ /* Driver defined statistic counter */
+ unsigned long tx_fifo_underrun;
+ unsigned long tx_loss_carrier;
+ unsigned long tx_no_carrier;
+ unsigned long tx_late_collision;
+ unsigned long tx_excessive_collision;
+ unsigned long tx_jabber_timeout;
+ unsigned long reset_count;
+ unsigned long reset_cr8;
+ unsigned long reset_fatal;
+ unsigned long reset_TXtimeout;
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+ u8 init;
+};
+
+enum uli526x_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+ DCR15 = 0x78
+};
+
+enum uli526x_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration ----------------------------- */
+static int __devinitdata printed_version;
+static char version[] __devinitdata =
+ KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version "
+ DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static int uli526x_debug;
+static unsigned char uli526x_media_mode = ULI526X_AUTO;
+static u32 uli526x_cr6_user_set;
+
+/* For module input parameter */
+static int debug;
+static u32 cr6set;
+static unsigned char mode = 8;
+
+/* function declaration ------------------------------------- */
+static int uli526x_open(struct net_device *);
+static int uli526x_start_xmit(struct sk_buff *, struct net_device *);
+static int uli526x_stop(struct net_device *);
+static struct net_device_stats * uli526x_get_stats(struct net_device *);
+static void uli526x_set_filter_mode(struct net_device *);
+static struct ethtool_ops netdev_ethtool_ops;
+static u16 read_srom_word(long, int);
+static irqreturn_t uli526x_interrupt(int, void *, struct pt_regs *);
+static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
+static void allocate_rx_buffer(struct uli526x_board_info *);
+static void update_cr6(u32, unsigned long);
+static void send_filter_frame(struct net_device *, int);
+static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 phy_readby_cr10(unsigned long, u8, u8);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_writeby_cr10(unsigned long, u8, u8, u16);
+static void phy_write_1bit(unsigned long, u32, u32);
+static u16 phy_read_1bit(unsigned long, u32);
+static u8 uli526x_sense_speed(struct uli526x_board_info *);
+static void uli526x_process_mode(struct uli526x_board_info *);
+static void uli526x_timer(unsigned long);
+static void uli526x_rx_packet(struct net_device *, struct uli526x_board_info *);
+static void uli526x_free_tx_pkt(struct net_device *, struct uli526x_board_info *);
+static void uli526x_reuse_skb(struct uli526x_board_info *, struct sk_buff *);
+static void uli526x_dynamic_reset(struct net_device *);
+static void uli526x_free_rxbuffer(struct uli526x_board_info *);
+static void uli526x_init(struct net_device *);
+static void uli526x_set_phyxcer(struct uli526x_board_info *);
+
+/* ULI526X network board routine ---------------------------- */
+
+/*
+ * Search ULI526X board, allocate space and register it
+ */
+
+static int __devinit uli526x_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct uli526x_board_info *db; /* board information structure */
+ struct net_device *dev;
+ int i, err;
+
+ ULI526X_DBUG(0, "uli526x_init_one()", 0);
+
+ if (!printed_version++)
+ printk(version);
+
+ /* Init network device */
+ dev = alloc_etherdev(sizeof(*db));
+ if (dev == NULL)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
+ err = -ENODEV;
+ goto err_out_free;
+ }
+
+ /* Enable Master/IO access, Disable memory access */
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_out_free;
+
+ if (!pci_resource_start(pdev, 0)) {
+ printk(KERN_ERR DRV_NAME ": I/O base is zero\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ if (pci_resource_len(pdev, 0) < (ULI526X_IO_SIZE) ) {
+ printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ if (pci_request_regions(pdev, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ /* Init system & device */
+ db = netdev_priv(dev);
+
+ /* Allocate Tx/Rx descriptor memory */
+ db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+ if(db->desc_pool_ptr == NULL)
+ {
+ err = -ENOMEM;
+ goto err_out_nomem;
+ }
+ db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+ if(db->buf_pool_ptr == NULL)
+ {
+ err = -ENOMEM;
+ goto err_out_nomem;
+ }
+
+ db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+ db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+ db->buf_pool_start = db->buf_pool_ptr;
+ db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+ db->chip_id = ent->driver_data;
+ db->ioaddr = pci_resource_start(pdev, 0);
+
+ db->pdev = pdev;
+ db->init = 1;
+
+ dev->base_addr = db->ioaddr;
+ dev->irq = pdev->irq;
+ pci_set_drvdata(pdev, dev);
+
+ /* Register some necessary functions */
+ dev->open = &uli526x_open;
+ dev->hard_start_xmit = &uli526x_start_xmit;
+ dev->stop = &uli526x_stop;
+ dev->get_stats = &uli526x_get_stats;
+ dev->set_multicast_list = &uli526x_set_filter_mode;
+ dev->ethtool_ops = &netdev_ethtool_ops;
+ spin_lock_init(&db->lock);
+
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+
+ /* Set Node address */
+ if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0) /* SROM absent, so read MAC address from ID Table */
+ {
+ outl(0x10000, db->ioaddr + DCR0); //Diagnosis mode
+ outl(0x1c0, db->ioaddr + DCR13); //Reset dianostic pointer port
+ outl(0, db->ioaddr + DCR14); //Clear reset port
+ outl(0x10, db->ioaddr + DCR14); //Reset ID Table pointer
+ outl(0, db->ioaddr + DCR14); //Clear reset port
+ outl(0, db->ioaddr + DCR13); //Clear CR13
+ outl(0x1b0, db->ioaddr + DCR13); //Select ID Table access port
+ //Read MAC address from CR14
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = inl(db->ioaddr + DCR14);
+ //Read end
+ outl(0, db->ioaddr + DCR13); //Clear CR13
+ outl(0, db->ioaddr + DCR0); //Clear CR0
+ udelay(10);
+ }
+ else /*Exist SROM*/
+ {
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = db->srom[20 + i];
+ }
+ err = register_netdev (dev);
+ if (err)
+ goto err_out_res;
+
+ printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev));
+
+ for (i = 0; i < 6; i++)
+ printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
+ printk(", irq %d.\n", dev->irq);
+
+ pci_set_master(pdev);
+
+ return 0;
+
+err_out_res:
+ pci_release_regions(pdev);
+err_out_nomem:
+ if(db->desc_pool_ptr)
+ pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
+ db->desc_pool_ptr, db->desc_pool_dma_ptr);
+
+ if(db->buf_pool_ptr != NULL)
+ pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ db->buf_pool_ptr, db->buf_pool_dma_ptr);
+err_out_disable:
+ pci_disable_device(pdev);
+err_out_free:
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(dev);
+
+ return err;
+}
+
+
+static void __devexit uli526x_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_remove_one()", 0);
+
+ pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
+ DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
+ db->desc_pool_dma_ptr);
+ pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ db->buf_pool_ptr, db->buf_pool_dma_ptr);
+ unregister_netdev(dev);
+ pci_release_regions(pdev);
+ free_netdev(dev); /* free board information */
+ pci_set_drvdata(pdev, NULL);
+ pci_disable_device(pdev);
+ ULI526X_DBUG(0, "uli526x_remove_one() exit", 0);
+}
+
+
+/*
+ * Open the interface.
+ * The interface is opened whenever "ifconfig" activates it.
+ */
+
+static int uli526x_open(struct net_device *dev)
+{
+ int ret;
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_open", 0);
+
+ ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
+ if (ret)
+ return ret;
+
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
+ db->tx_packet_cnt = 0;
+ db->rx_avail_cnt = 0;
+ db->link_failed = 1;
+ netif_carrier_off(dev);
+ db->wait_reset = 0;
+
+ db->NIC_capability = 0xf; /* All capability*/
+ db->PHY_reg4 = 0x1e0;
+
+ /* CR6 operation mode decision */
+ db->cr6_data |= ULI526X_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+
+ /* Initialize ULI526X board */
+ uli526x_init(dev);
+
+ /* Active System Interface */
+ netif_wake_queue(dev);
+
+ /* set and active a timer process */
+ init_timer(&db->timer);
+ db->timer.expires = ULI526X_TIMER_WUT + HZ * 2;
+ db->timer.data = (unsigned long)dev;
+ db->timer.function = &uli526x_timer;
+ add_timer(&db->timer);
+
+ return 0;
+}
+
+
+/* Initialize ULI526X board
+ * Reset ULI526X board
+ * Initialize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void uli526x_init(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = db->ioaddr;
+ u8 phy_tmp;
+ u16 phy_value;
+ u16 phy_reg_reset;
+
+ ULI526X_DBUG(0, "uli526x_init()", 0);
+
+ /* Reset M526x MAC controller */
+ outl(ULI526X_RESET, ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : In some boards,M5261/M5263 phy address != 1 */
+ db->phy_addr = 1;
+ for(phy_tmp=0;phy_tmp<32;phy_tmp++)
+ {
+ phy_value=phy_read(db->ioaddr,phy_tmp,3,db->chip_id);//peer add
+ if(phy_value != 0xffff&&phy_value!=0)
+ {
+ db->phy_addr = phy_tmp;
+ break;
+ }
+ }
+ if(phy_tmp == 32)
+ printk(KERN_WARNING "Can not find the phy address!!!");
+ /* Parser SROM and media mode */
+ db->media_mode = uli526x_media_mode;
+
+ /* Phyxcer capability setting */
+ phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
+ phy_reg_reset = (phy_reg_reset | 0x8000);
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+ udelay(500);
+
+ /* Process Phyxcer Media Mode */
+ uli526x_set_phyxcer(db);
+
+ /* Media Mode Process */
+ if ( !(db->media_mode & ULI526X_AUTO) )
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initialize Transmit/Receive decriptor and CR3/4 */
+ uli526x_descriptor_init(db, ioaddr);
+
+ /* Init CR6 to program M526X operation */
+ update_cr6(db->cr6_data, ioaddr);
+
+ /* Send setup frame */
+ send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, ioaddr + DCR7);
+
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, ioaddr + DCR15);
+
+ /* Enable ULI526X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC;
+ update_cr6(db->cr6_data, ioaddr);
+}
+
+
+/*
+ * Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+
+static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ struct tx_desc *txptr;
+ unsigned long flags;
+
+ ULI526X_DBUG(0, "uli526x_start_xmit", 0);
+
+ /* Resource flag check */
+ netif_stop_queue(dev);
+
+ /* Too large packet check */
+ if (skb->len > MAX_PACKET_SIZE) {
+ printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ /* No Tx resource check, it never happen nromally */
+ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
+ spin_unlock_irqrestore(&db->lock, flags);
+ printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt);
+ return 1;
+ }
+
+ /* Disable NIC interrupt */
+ outl(0, dev->base_addr + DCR7);
+
+ /* transmit this packet */
+ txptr = db->tx_insert_ptr;
+ memcpy(txptr->tx_buf_ptr, skb->data, skb->len);
+ txptr->tdes1 = cpu_to_le32(0xe1000000 | skb->len);
+
+ /* Point to next transmit free descriptor */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+
+ /* Transmit Packet Process */
+ if ( (db->tx_packet_cnt < TX_DESC_CNT) ) {
+ txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
+ db->tx_packet_cnt++; /* Ready to send */
+ outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ dev->trans_start = jiffies; /* saved time stamp */
+ }
+
+ /* Tx resource check */
+ if ( db->tx_packet_cnt < TX_FREE_DESC_CNT )
+ netif_wake_queue(dev);
+
+ /* Restore CR7 to enable interrupt */
+ spin_unlock_irqrestore(&db->lock, flags);
+ outl(db->cr7_data, dev->base_addr + DCR7);
+
+ /* free this SKB */
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+
+/*
+ * Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+
+static int uli526x_stop(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = dev->base_addr;
+
+ ULI526X_DBUG(0, "uli526x_stop", 0);
+
+ /* disable system */
+ netif_stop_queue(dev);
+
+ /* deleted timer */
+ del_timer_sync(&db->timer);
+
+ /* Reset & stop ULI526X board */
+ outl(ULI526X_RESET, ioaddr + DCR0);
+ udelay(5);
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+
+ /* free interrupt */
+ free_irq(dev->irq, dev);
+
+ /* free allocated rx buffer */
+ uli526x_free_rxbuffer(db);
+
+#if 0
+ /* show statistic counter */
+ printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+ db->tx_fifo_underrun, db->tx_excessive_collision,
+ db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
+ db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
+ db->reset_fatal, db->reset_TXtimeout);
+#endif
+
+ return 0;
+}
+
+
+/*
+ * M5261/M5263 insterrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+
+static irqreturn_t uli526x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ if (!dev) {
+ ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
+ return IRQ_NONE;
+ }
+
+ spin_lock_irqsave(&db->lock, flags);
+ outl(0, ioaddr + DCR7);
+
+ /* Got ULI526X status */
+ db->cr5_data = inl(ioaddr + DCR5);
+ outl(db->cr5_data, ioaddr + DCR5);
+ if ( !(db->cr5_data & 0x180c1) ) {
+ spin_unlock_irqrestore(&db->lock, flags);
+ outl(db->cr7_data, ioaddr + DCR7);
+ return IRQ_HANDLED;
+ }
+
+ /* Check system status */
+ if (db->cr5_data & 0x2000) {
+ /* system bus error happen */
+ ULI526X_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
+ db->reset_fatal++;
+ db->wait_reset = 1; /* Need to RESET */
+ spin_unlock_irqrestore(&db->lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ /* Received the coming packet */
+ if ( (db->cr5_data & 0x40) && db->rx_avail_cnt )
+ uli526x_rx_packet(dev, db);
+
+ /* reallocate rx descriptor buffer */
+ if (db->rx_avail_cnt<RX_DESC_CNT)
+ allocate_rx_buffer(db);
+
+ /* Free the transmitted descriptor */
+ if ( db->cr5_data & 0x01)
+ uli526x_free_tx_pkt(dev, db);
+
+ /* Restore CR7 to enable interrupt mask */
+ outl(db->cr7_data, ioaddr + DCR7);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * Free TX resource after TX complete
+ */
+
+static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_info * db)
+{
+ struct tx_desc *txptr;
+ u32 tdes0;
+
+ txptr = db->tx_remove_ptr;
+ while(db->tx_packet_cnt) {
+ tdes0 = le32_to_cpu(txptr->tdes0);
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ if (tdes0 & 0x80000000)
+ break;
+
+ /* A packet sent completed */
+ db->tx_packet_cnt--;
+ db->stats.tx_packets++;
+
+ /* Transmit statistic counter */
+ if ( tdes0 != 0x7fffffff ) {
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ db->stats.collisions += (tdes0 >> 3) & 0xf;
+ db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+ if (tdes0 & TDES0_ERR_MASK) {
+ db->stats.tx_errors++;
+ if (tdes0 & 0x0002) { /* UnderRun */
+ db->tx_fifo_underrun++;
+ if ( !(db->cr6_data & CR6_SFT) ) {
+ db->cr6_data = db->cr6_data | CR6_SFT;
+ update_cr6(db->cr6_data, db->ioaddr);
+ }
+ }
+ if (tdes0 & 0x0100)
+ db->tx_excessive_collision++;
+ if (tdes0 & 0x0200)
+ db->tx_late_collision++;
+ if (tdes0 & 0x0400)
+ db->tx_no_carrier++;
+ if (tdes0 & 0x0800)
+ db->tx_loss_carrier++;
+ if (tdes0 & 0x4000)
+ db->tx_jabber_timeout++;
+ }
+ }
+
+ txptr = txptr->next_tx_desc;
+ }/* End of while */
+
+ /* Update TX remove pointer to next */
+ db->tx_remove_ptr = txptr;
+
+ /* Resource available check */
+ if ( db->tx_packet_cnt < TX_WAKE_DESC_CNT )
+ netif_wake_queue(dev); /* Active upper layer, send again */
+}
+
+
+/*
+ * Receive the come packet and pass to upper layer
+ */
+
+static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info * db)
+{
+ struct rx_desc *rxptr;
+ struct sk_buff *skb;
+ int rxlen;
+ u32 rdes0;
+
+ rxptr = db->rx_ready_ptr;
+
+ while(db->rx_avail_cnt) {
+ rdes0 = le32_to_cpu(rxptr->rdes0);
+ if (rdes0 & 0x80000000) /* packet owner check */
+ {
+ break;
+ }
+
+ db->rx_avail_cnt--;
+ db->interval_rx_cnt++;
+
+ pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+ if ( (rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ /* reuse this SKB */
+ ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ( (rdes0 >> 16) & 0x3fff) - 4;
+
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ /* This is a error packet */
+ //printk(DRV_NAME ": rdes0: %lx\n", rdes0);
+ db->stats.rx_errors++;
+ if (rdes0 & 1)
+ db->stats.rx_fifo_errors++;
+ if (rdes0 & 2)
+ db->stats.rx_crc_errors++;
+ if (rdes0 & 0x80)
+ db->stats.rx_length_errors++;
+ }
+
+ if ( !(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
+ skb = rxptr->rx_skb_ptr;
+
+ /* Good packet, send to upper layer */
+ /* Shorst packet used new SKB */
+ if ( (rxlen < RX_COPY_SIZE) &&
+ ( (skb = dev_alloc_skb(rxlen + 2) )
+ != NULL) ) {
+ /* size less than COPY_SIZE, allocate a rxlen SKB */
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16byte align */
+ memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ } else {
+ skb->dev = dev;
+ skb_put(skb, rxlen);
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ db->stats.rx_packets++;
+ db->stats.rx_bytes += rxlen;
+
+ } else {
+ /* Reuse SKB buffer when the packet is error */
+ ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ }
+ }
+
+ rxptr = rxptr->next_rx_desc;
+ }
+
+ db->rx_ready_ptr = rxptr;
+}
+
+
+/*
+ * Get statistics from driver.
+ */
+
+static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_get_stats", 0);
+ return &db->stats;
+}
+
+
+/*
+ * Set ULI526X multicast address
+ */
+
+static void uli526x_set_filter_mode(struct net_device * dev)
+{
+ struct uli526x_board_info *db = dev->priv;
+ unsigned long flags;
+
+ ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
+ spin_lock_irqsave(&db->lock, flags);
+
+ if (dev->flags & IFF_PROMISC) {
+ ULI526X_DBUG(0, "Enable PROM Mode", 0);
+ db->cr6_data |= CR6_PM | CR6_PBF;
+ update_cr6(db->cr6_data, db->ioaddr);
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) {
+ ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);
+ db->cr6_data &= ~(CR6_PM | CR6_PBF);
+ db->cr6_data |= CR6_PAM;
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ ULI526X_DBUG(0, "Set multicast address", dev->mc_count);
+ send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */
+ spin_unlock_irqrestore(&db->lock, flags);
+}
+
+static void
+ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
+{
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_MII);
+
+ ecmd->advertising = (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_Autoneg |
+ ADVERTISED_MII);
+
+
+ ecmd->port = PORT_MII;
+ ecmd->phy_address = db->phy_addr;
+
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ ecmd->speed = 10;
+ ecmd->duplex = DUPLEX_HALF;
+
+ if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+ {
+ ecmd->speed = 100;
+ }
+ if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+ {
+ ecmd->duplex = DUPLEX_FULL;
+ }
+ if(db->link_failed)
+ {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ if (db->media_mode & ULI526X_AUTO)
+ {
+ ecmd->autoneg = AUTONEG_ENABLE;
+ }
+}
+
+static void netdev_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ if (np->pdev)
+ strcpy(info->bus_info, pci_name(np->pdev));
+ else
+ sprintf(info->bus_info, "EISA 0x%lx %d",
+ dev->base_addr, dev->irq);
+}
+
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ ULi_ethtool_gset(np, cmd);
+
+ return 0;
+}
+
+static u32 netdev_get_link(struct net_device *dev) {
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ if(np->link_failed)
+ return 0;
+ else
+ return 1;
+}
+
+static void uli526x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ wol->supported = WAKE_PHY | WAKE_MAGIC;
+ wol->wolopts = 0;
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+ .get_drvinfo = netdev_get_drvinfo,
+ .get_settings = netdev_get_settings,
+ .get_link = netdev_get_link,
+ .get_wol = uli526x_get_wol,
+};
+
+/*
+ * A periodic timer routine
+ * Dynamic media sense, allocate Rx buffer...
+ */
+
+static void uli526x_timer(unsigned long data)
+{
+ u32 tmp_cr8;
+ unsigned char tmp_cr12=0;
+ struct net_device *dev = (struct net_device *) data;
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long flags;
+ u8 TmpSpeed=10;
+
+ //ULI526X_DBUG(0, "uli526x_timer()", 0);
+ spin_lock_irqsave(&db->lock, flags);
+
+
+ /* Dynamic reset ULI526X : system error or transmit time-out */
+ tmp_cr8 = inl(db->ioaddr + DCR8);
+ if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
+ db->reset_cr8++;
+ db->wait_reset = 1;
+ }
+ db->interval_rx_cnt = 0;
+
+ /* TX polling kick monitor */
+ if ( db->tx_packet_cnt &&
+ time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
+ outl(0x1, dev->base_addr + DCR1); // Tx polling again
+
+ // TX Timeout
+ if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
+ db->reset_TXtimeout++;
+ db->wait_reset = 1;
+ printk( "%s: Tx timeout - resetting\n",
+ dev->name);
+ }
+ }
+
+ if (db->wait_reset) {
+ ULI526X_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);
+ db->reset_count++;
+ uli526x_dynamic_reset(dev);
+ db->timer.expires = ULI526X_TIMER_WUT;
+ add_timer(&db->timer);
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ /* Link status check, Dynamic media type change */
+ if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)
+ tmp_cr12 = 3;
+
+ if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
+ /* Link Failed */
+ ULI526X_DBUG(0, "Link Failed", tmp_cr12);
+ netif_carrier_off(dev);
+ printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+ db->link_failed = 1;
+
+ /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
+ /* AUTO don't need */
+ if ( !(db->media_mode & 0x8) )
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+
+ /* AUTO mode, if INT phyxcer link failed, select EXT device */
+ if (db->media_mode & ULI526X_AUTO) {
+ db->cr6_data&=~0x00000200; /* bit9=0, HD mode */
+ update_cr6(db->cr6_data, db->ioaddr);
+ }
+ } else
+ if ((tmp_cr12 & 0x3) && db->link_failed) {
+ ULI526X_DBUG(0, "Link link OK", tmp_cr12);
+ db->link_failed = 0;
+
+ /* Auto Sense Speed */
+ if ( (db->media_mode & ULI526X_AUTO) &&
+ uli526x_sense_speed(db) )
+ db->link_failed = 1;
+ uli526x_process_mode(db);
+
+ if(db->link_failed==0)
+ {
+ if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+ {
+ TmpSpeed = 100;
+ }
+ if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed);
+ }
+ else
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed);
+ }
+ netif_carrier_on(dev);
+ }
+ /* SHOW_MEDIA_TYPE(db->op_mode); */
+ }
+ else if(!(tmp_cr12 & 0x3) && db->link_failed)
+ {
+ if(db->init==1)
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+ netif_carrier_off(dev);
+ }
+ }
+ db->init=0;
+
+ /* Timer active again */
+ db->timer.expires = ULI526X_TIMER_WUT;
+ add_timer(&db->timer);
+ spin_unlock_irqrestore(&db->lock, flags);
+}
+
+
+/*
+ * Dynamic reset the ULI526X board
+ * Stop ULI526X board
+ * Free Tx/Rx allocated memory
+ * Reset ULI526X board
+ * Re-initialize ULI526X board
+ */
+
+static void uli526x_dynamic_reset(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0);
+
+ /* Sopt MAC controller */
+ db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
+ update_cr6(db->cr6_data, dev->base_addr);
+ outl(0, dev->base_addr + DCR7); /* Disable Interrupt */
+ outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
+
+ /* Disable upper layer interface */
+ netif_stop_queue(dev);
+
+ /* Free Rx Allocate buffer */
+ uli526x_free_rxbuffer(db);
+
+ /* system variable init */
+ db->tx_packet_cnt = 0;
+ db->rx_avail_cnt = 0;
+ db->link_failed = 1;
+ db->init=1;
+ db->wait_reset = 0;
+
+ /* Re-initialize ULI526X board */
+ uli526x_init(dev);
+
+ /* Restart upper layer interface */
+ netif_wake_queue(dev);
+}
+
+
+/*
+ * free all allocated rx buffer
+ */
+
+static void uli526x_free_rxbuffer(struct uli526x_board_info * db)
+{
+ ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);
+
+ /* free allocated rx buffer */
+ while (db->rx_avail_cnt) {
+ dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
+ db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;
+ db->rx_avail_cnt--;
+ }
+}
+
+
+/*
+ * Reuse the SK buffer
+ */
+
+static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * skb)
+{
+ struct rx_desc *rxptr = db->rx_insert_ptr;
+
+ if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
+ rxptr->rx_skb_ptr = skb;
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ db->rx_avail_cnt++;
+ db->rx_insert_ptr = rxptr->next_rx_desc;
+ } else
+ ULI526X_DBUG(0, "SK Buffer reuse method error", db->rx_avail_cnt);
+}
+
+
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr)
+{
+ struct tx_desc *tmp_tx;
+ struct rx_desc *tmp_rx;
+ unsigned char *tmp_buf;
+ dma_addr_t tmp_tx_dma, tmp_rx_dma;
+ dma_addr_t tmp_buf_dma;
+ int i;
+
+ ULI526X_DBUG(0, "uli526x_descriptor_init()", 0);
+
+ /* tx descriptor start pointer */
+ db->tx_insert_ptr = db->first_tx_desc;
+ db->tx_remove_ptr = db->first_tx_desc;
+ outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->first_rx_desc_dma = db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->rx_insert_ptr = db->first_rx_desc;
+ db->rx_ready_ptr = db->first_rx_desc;
+ outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+
+ /* Init Transmit chain */
+ tmp_buf = db->buf_pool_start;
+ tmp_buf_dma = db->buf_pool_dma_start;
+ tmp_tx_dma = db->first_tx_desc_dma;
+ for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
+ tmp_tx->tx_buf_ptr = tmp_buf;
+ tmp_tx->tdes0 = cpu_to_le32(0);
+ tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+ tmp_tx_dma += sizeof(struct tx_desc);
+ tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
+ tmp_tx->next_tx_desc = tmp_tx + 1;
+ tmp_buf = tmp_buf + TX_BUF_ALLOC;
+ tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
+ }
+ (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
+ tmp_tx->next_tx_desc = db->first_tx_desc;
+
+ /* Init Receive descriptor chain */
+ tmp_rx_dma=db->first_rx_desc_dma;
+ for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {
+ tmp_rx->rdes0 = cpu_to_le32(0);
+ tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+ tmp_rx_dma += sizeof(struct rx_desc);
+ tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
+ tmp_rx->next_rx_desc = tmp_rx + 1;
+ }
+ (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
+ tmp_rx->next_rx_desc = db->first_rx_desc;
+
+ /* pre-allocate Rx buffer */
+ allocate_rx_buffer(db);
+}
+
+
+/*
+ * Update CR6 value
+ * Firstly stop ULI526X, then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+
+/*
+ * Send a setup frame for M5261/M5263
+ * This setup frame initialize ULI526X address filter mode
+ */
+
+static void send_filter_frame(struct net_device *dev, int mc_cnt)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ struct dev_mc_list *mcptr;
+ struct tx_desc *txptr;
+ u16 * addrptr;
+ u32 * suptr;
+ int i;
+
+ ULI526X_DBUG(0, "send_filter_frame()", 0);
+
+ txptr = db->tx_insert_ptr;
+ suptr = (u32 *) txptr->tx_buf_ptr;
+
+ /* Node address */
+ addrptr = (u16 *) dev->dev_addr;
+ *suptr++ = addrptr[0];
+ *suptr++ = addrptr[1];
+ *suptr++ = addrptr[2];
+
+ /* broadcast address */
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+
+ /* fit the multicast address */
+ for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ addrptr = (u16 *) mcptr->dmi_addr;
+ *suptr++ = addrptr[0];
+ *suptr++ = addrptr[1];
+ *suptr++ = addrptr[2];
+ }
+
+ for (; i<14; i++) {
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ }
+
+ /* prepare the setup frame */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+ txptr->tdes1 = cpu_to_le32(0x890000c0);
+
+ /* Resource Check and Send the setup packet */
+ if (db->tx_packet_cnt < TX_DESC_CNT) {
+ /* Resource Empty */
+ db->tx_packet_cnt++;
+ txptr->tdes0 = cpu_to_le32(0x80000000);
+ update_cr6(db->cr6_data | 0x2000, dev->base_addr);
+ outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, dev->base_addr);
+ dev->trans_start = jiffies;
+ } else
+ printk(KERN_ERR DRV_NAME ": No Tx resource - Send_filter_frame!\n");
+}
+
+
+/*
+ * Allocate rx buffer,
+ * As possible as allocate maxiumn Rx buffer
+ */
+
+static void allocate_rx_buffer(struct uli526x_board_info *db)
+{
+ struct rx_desc *rxptr;
+ struct sk_buff *skb;
+
+ rxptr = db->rx_insert_ptr;
+
+ while(db->rx_avail_cnt < RX_DESC_CNT) {
+ if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
+ break;
+ rxptr->rx_skb_ptr = skb; /* FIXME (?) */
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ rxptr = rxptr->next_rx_desc;
+ db->rx_avail_cnt++;
+ }
+
+ db->rx_insert_ptr = rxptr;
+}
+
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+
+/*
+ * Auto sense the media mode
+ */
+
+static u8 uli526x_sense_speed(struct uli526x_board_info * db)
+{
+ u8 ErrFlag = 0;
+ u16 phy_mode;
+
+ phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+ phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+
+ if ( (phy_mode & 0x24) == 0x24 ) {
+
+ phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
+ if(phy_mode&0x8000)
+ phy_mode = 0x8000;
+ else if(phy_mode&0x4000)
+ phy_mode = 0x4000;
+ else if(phy_mode&0x2000)
+ phy_mode = 0x2000;
+ else
+ phy_mode = 0x1000;
+
+ /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
+ switch (phy_mode) {
+ case 0x1000: db->op_mode = ULI526X_10MHF; break;
+ case 0x2000: db->op_mode = ULI526X_10MFD; break;
+ case 0x4000: db->op_mode = ULI526X_100MHF; break;
+ case 0x8000: db->op_mode = ULI526X_100MFD; break;
+ default: db->op_mode = ULI526X_10MHF; ErrFlag = 1; break;
+ }
+ } else {
+ db->op_mode = ULI526X_10MHF;
+ ULI526X_DBUG(0, "Link Failed :", phy_mode);
+ ErrFlag = 1;
+ }
+
+ return ErrFlag;
+}
+
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void uli526x_set_phyxcer(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & ULI526X_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch(db->media_mode) {
+ case ULI526X_10MHF: phy_reg |= 0x20; break;
+ case ULI526X_10MFD: phy_reg |= 0x40; break;
+ case ULI526X_100MHF: phy_reg |= 0x80; break;
+ case ULI526X_100MFD: phy_reg |= 0x100; break;
+ }
+
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if ( !(phy_reg & 0x01e0)) {
+ phy_reg|=db->PHY_reg4;
+ db->media_mode|=ULI526X_AUTO;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+ udelay(50);
+}
+
+
+/*
+ * Process op-mode
+ AUTO mode : PHY controller in Auto-negotiation Mode
+ * Force mode: PHY controller in force mode with HUB
+ * N-way force capability with SWITCH
+ */
+
+static void uli526x_process_mode(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Full Duplex Mode Check */
+ if (db->op_mode & 0x4)
+ db->cr6_data |= CR6_FDM; /* Set Full Duplex Bit */
+ else
+ db->cr6_data &= ~CR6_FDM; /* Clear Full Duplex Bit */
+
+ update_cr6(db->cr6_data, db->ioaddr);
+
+ /* 10/100M phyxcer force mode need */
+ if ( !(db->media_mode & 0x8)) {
+ /* Forece Mode */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);
+ if ( !(phy_reg & 0x1) ) {
+ /* parter without N-Way capability */
+ phy_reg = 0x0;
+ switch(db->op_mode) {
+ case ULI526X_10MHF: phy_reg = 0x0; break;
+ case ULI526X_10MFD: phy_reg = 0x100; break;
+ case ULI526X_100MHF: phy_reg = 0x2000; break;
+ case ULI526X_100MFD: phy_reg = 0x2100; break;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+ }
+ }
+}
+
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if(chip_id == PCI_ULI5263_ID)
+ {
+ phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
+ return;
+ }
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Write a word data to PHY controller */
+ for ( i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+}
+
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if(chip_id == PCI_ULI5263_ID)
+ return phy_readby_cr10(iobase, phy_addr, offset);
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr, chip_id);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr, chip_id);
+ }
+
+ return phy_data;
+}
+
+static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+{
+ unsigned long ioaddr,cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x08000000;
+ outl(cr10_value,ioaddr);
+ udelay(1);
+ while(1)
+ {
+ cr10_value = inl(ioaddr);
+ if(cr10_value&0x10000000)
+ break;
+ }
+ return (cr10_value&0x0ffff);
+}
+
+static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
+{
+ unsigned long ioaddr,cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
+ outl(cr10_value,ioaddr);
+ udelay(1);
+}
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+{
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+{
+ u16 phy_data;
+
+ outl(0x50000 , ioaddr);
+ udelay(1);
+ phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
+ outl(0x40000 , ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+
+static struct pci_device_id uli526x_pci_tbl[] = {
+ { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
+ { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, uli526x_pci_tbl);
+
+
+static struct pci_driver uli526x_driver = {
+ .name = "uli526x",
+ .id_table = uli526x_pci_tbl,
+ .probe = uli526x_init_one,
+ .remove = __devexit_p(uli526x_remove_one),
+};
+
+MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw");
+MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM(mode, "i");
+MODULE_PARM(cr6set, "i");
+MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)");
+MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
+
+/* Description:
+ * when user used insmod to add module, system invoked init_module()
+ * to register the services.
+ */
+
+static int __init uli526x_init_module(void)
+{
+ int rc;
+
+ printk(version);
+ printed_version = 1;
+
+ ULI526X_DBUG(0, "init_module() ", debug);
+
+ if (debug)
+ uli526x_debug = debug; /* set debug flag */
+ if (cr6set)
+ uli526x_cr6_user_set = cr6set;
+
+ switch(mode) {
+ case ULI526X_10MHF:
+ case ULI526X_100MHF:
+ case ULI526X_10MFD:
+ case ULI526X_100MFD:
+ uli526x_media_mode = mode;
+ break;
+ default:uli526x_media_mode = ULI526X_AUTO;
+ break;
+ }
+
+ rc = pci_module_init(&uli526x_driver);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+
+/*
+ * Description:
+ * when user used rmmod to delete module, system invoked clean_module()
+ * to un-register all registered services.
+ */
+
+static void __exit uli526x_cleanup_module(void)
+{
+ ULI526X_DBUG(0, "uli526x_clean_module() ", debug);
+ pci_unregister_driver(&uli526x_driver);
+}
+
+module_init(uli526x_init_module);
+module_exit(uli526x_cleanup_module);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index effab0b9adca..50b8c6754b1e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -18,6 +18,9 @@
/*
* Changes:
*
+ * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
+ * Add TUNSETLINK ioctl to set the link encapsulation
+ *
* Mark Smith <markzzzsmith@yahoo.com.au>
* Use random_ether_addr() for tap MAC address.
*
@@ -612,6 +615,18 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
break;
+ case TUNSETLINK:
+ /* Only allow setting the type when the interface is down */
+ if (tun->dev->flags & IFF_UP) {
+ DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
+ tun->dev->name);
+ return -EBUSY;
+ } else {
+ tun->dev->type = (int) arg;
+ DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
+ }
+ break;
+
#ifdef TUN_DEBUG
case TUNSETDEBUG:
tun->debug = arg;
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 6e74af62ca08..9e56fc346ba4 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -56,7 +56,7 @@
#include <linux/sched.h> /* for jiffies, HZ, etc. */
#include <linux/cycx_drv.h> /* API definitions */
#include <linux/cycx_cfm.h> /* CYCX firmware module definitions */
-#include <linux/delay.h> /* udelay */
+#include <linux/delay.h> /* udelay, msleep_interruptible */
#include <asm/io.h> /* read[wl], write[wl], ioremap, iounmap */
#define MOD_VERSION 0
@@ -74,7 +74,6 @@ static int reset_cyc2x(void __iomem *addr);
static int detect_cyc2x(void __iomem *addr);
/* Miscellaneous functions */
-static void delay_cycx(int sec);
static int get_option_index(long *optlist, long optval);
static u16 checksum(u8 *buf, u32 len);
@@ -259,7 +258,7 @@ static int memory_exists(void __iomem *addr)
if (readw(addr + 0x10) == TEST_PATTERN)
return 1;
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
return 0;
@@ -316,7 +315,7 @@ static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len)
/* 80186 was in hold, go */
writeb(0, addr + START_CPU);
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
/* Load data.bin file through boot (reset) interface. */
@@ -462,13 +461,13 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size);
/* reset is waiting for boot */
writew(GEN_POWER_ON, pt_cycld);
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
for (j = 0 ; j < 3 ; j++)
if (!readw(pt_cycld))
goto reset_loaded;
else
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
printk(KERN_ERR "%s: reset not started.\n", modname);
@@ -495,7 +494,7 @@ reset_loaded:
/* Arthur Ganzert's tip: wait a while after the firmware loading...
seg abr 26 17:17:12 EST 1999 - acme */
- delay_cycx(7);
+ msleep_interruptible(7 * 1000);
printk(KERN_INFO "%s: firmware loaded!\n", modname);
/* enable interrupts */
@@ -547,20 +546,13 @@ static int get_option_index(long *optlist, long optval)
static int reset_cyc2x(void __iomem *addr)
{
writeb(0, addr + RST_ENABLE);
- delay_cycx(2);
+ msleep_interruptible(2 * 1000);
writeb(0, addr + RST_DISABLE);
- delay_cycx(2);
+ msleep_interruptible(2 * 1000);
return memory_exists(addr);
}
-/* Delay */
-static void delay_cycx(int sec)
-{
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(sec * HZ);
-}
-
/* Calculate 16-bit CRC using CCITT polynomial. */
static u16 checksum(u8 *buf, u32 len)
{
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index a63f6a2cc4f7..cdd4c09c2d90 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -61,7 +61,7 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *p)
+ struct packet_type *p, struct net_device *orig_dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.netif_rx)
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 7f2e3653c5e5..6c302e9dbca2 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -86,7 +86,7 @@ static __inline__ int dev_is_ethdev(struct net_device *dev)
/*
* Receive a LAPB frame via an ethernet interface.
*/
-static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
+static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)
{
int len, err;
struct lapbethdev *lapbeth;
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index c5f5e62aab8b..0497dbdb8631 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -445,7 +445,7 @@ 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,
+static int setup_fr_header(struct sk_buff *skb,
struct net_device* dev, char op_mode);
@@ -1372,7 +1372,7 @@ static int if_send(struct sk_buff* skb, struct net_device* dev)
/* 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);
+ 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;
@@ -1597,8 +1597,6 @@ static int setup_for_delayed_transmit(struct net_device* dev,
return 1;
}
- skb_unlink(skb);
-
chan->transmit_length = len;
chan->delay_skb = skb;
@@ -4871,18 +4869,15 @@ static void unconfig_fr (sdla_t *card)
}
}
-static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
+static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
char op_mode)
{
- struct sk_buff *skb = *skb_orig;
fr_channel_t *chan=dev->priv;
- if (op_mode == WANPIPE){
-
+ 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;
@@ -4894,16 +4889,14 @@ static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
}
/* If we are in bridging mode, we must apply
- * an Ethernet header */
- if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){
-
-
+ * 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;
@@ -4916,7 +4909,6 @@ static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
/* Yuck. */
skb->protocol = ETH_P_802_3;
return 8;
-
}
return 0;
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 84b65c60c799..b56a7b516d24 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -1440,6 +1440,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
* @skb: The buffer to process
* @dev: The device it arrived on
* @p: Unused
+ * @orig_dev: Unused
*
* Protocol glue. This drives the deferred processing mode the poorer
* cards use. This can be called directly by cards that do not have
@@ -1447,7 +1448,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
* after interrupt servicing to process frames queued via netif_rx.
*/
-static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p)
+static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
{
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ec3f75a030d2..00a07f32a81e 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -137,6 +137,110 @@ config PCMCIA_RAYCS
comment "Wireless 802.11b ISA/PCI cards support"
depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
+config IPW2100
+ tristate "Intel PRO/Wireless 2100 Network Connection"
+ depends on NET_RADIO && PCI && IEEE80211
+ select FW_LOADER
+ ---help---
+ A driver for the Intel PRO/Wireless 2100 Network
+ Connection 802.11b wireless network adapter.
+
+ See <file:Documentation/networking/README.ipw2100> for information on
+ the capabilities currently enabled in this driver and for tips
+ for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2100.sf.net/>. Once you have the firmware image, you
+ will need to place it in /etc/firmware.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and remvoed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ipw2100.ko.
+
+config IPW2100_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2100
+ ---help---
+ Enables promiscuous/monitor mode support for the ipw2100 driver.
+ With this feature compiled into the driver, you can switch to
+ promiscuous mode via the Wireless Tool's Monitor mode. While in this
+ mode, no packets can be sent.
+
+config IPW_DEBUG
+ bool "Enable full debugging output in IPW2100 module."
+ depends on IPW2100
+ ---help---
+ This option will enable debug tracing output for the IPW2100.
+
+ This will result in the kernel module being ~60k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/bus/pci/drivers/ipw2100/debug_level
+
+ This entry will only exist if this option is enabled.
+
+ If you are not trying to debug or develop the IPW2100 driver, you
+ most likely want to say N here.
+
+config IPW2200
+ tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
+ depends on IEEE80211 && PCI
+ select FW_LOADER
+ ---help---
+ A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
+ Connection adapters.
+
+ See <file:Documentation/networking/README.ipw2200> for
+ information on the capabilities currently enabled in this
+ driver and for tips for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2200.sf.net/>. See the above referenced README.ipw2200
+ for information on where to install the firmare images.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and remvoed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ipw2200.ko.
+
+config IPW_DEBUG
+ bool "Enable full debugging output in IPW2200 module."
+ depends on IPW2200
+ ---help---
+ This option will enable debug tracing output for the IPW2200.
+
+ This will result in the kernel module being ~100k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/bus/pci/drivers/ipw2200/debug_level
+
+ This entry will only exist if this option is enabled.
+
+ To set a value, simply echo an 8-byte hex value to the same file:
+
+ % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level
+
+ You can find the list of debug mask values in
+ drivers/net/wireless/ipw2200.h
+
+ If you are not trying to debug or develop the IPW2200 driver, you
+ most likely want to say N here.
+
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
depends on NET_RADIO && ISA && (PCI || BROKEN)
@@ -185,8 +289,8 @@ config APPLE_AIRPORT
a non-standard interface
config PLX_HERMES
- tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in PLX9052 based PCI adaptors. These
@@ -195,12 +299,9 @@ config PLX_HERMES
802.11b PCMCIA cards can be used in desktop machines. The Netgear
MA301 is such an adaptor.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
-
config TMD_HERMES
- tristate "Hermes in TMD7160 based PCI adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in TMD7160 based PCI adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in TMD7160 based PCI adaptors. These
@@ -208,12 +309,18 @@ config TMD_HERMES
PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
802.11b PCMCIA cards can be used in desktop machines.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
+config NORTEL_HERMES
+ tristate "Nortel emobility PCI adaptor support"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in Nortel emobility PCI adaptors. These
+ adaptors are not full PCMCIA controllers, but act as a more limited
+ PCI <-> PCMCIA bridge.
config PCI_HERMES
- tristate "Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Prism 2.5 PCI 802.11b adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
@@ -268,6 +375,19 @@ config PCMCIA_HERMES
configure your card and that /etc/pcmcia/wireless.opts works:
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+config PCMCIA_SPECTRUM
+ tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+ depends on NET_RADIO && PCMCIA && HERMES
+ ---help---
+
+ This is a driver for 802.11b cards using RAM-loadable Symbol
+ firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+ cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+ This driver requires firmware download on startup. Utilities
+ for downloading Symbol firmware are available at
+ <http://sourceforge.net/projects/orinoco/>
+
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
@@ -355,6 +475,8 @@ config PRISM54
say M here and read <file:Documentation/modules.txt>. The module
will be called prism54.ko.
+source "drivers/net/wireless/hostap/Kconfig"
+
# yes, this works even when no drivers are selected
config NET_WIRELESS
bool
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 2b87841322cc..3a6f7ba326ca 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -2,6 +2,10 @@
# Makefile for the Linux Wireless network device drivers.
#
+obj-$(CONFIG_IPW2100) += ipw2100.o
+
+obj-$(CONFIG_IPW2200) += ipw2200.o
+
obj-$(CONFIG_STRIP) += strip.o
obj-$(CONFIG_ARLAN) += arlan.o
@@ -18,6 +22,8 @@ obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
obj-$(CONFIG_AIRO) += airo.o
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
@@ -28,6 +34,8 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
obj-$(CONFIG_PRISM54) += prism54/
+obj-$(CONFIG_HOSTAP) += hostap/
+
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index df20adcd0730..2be65d308fbe 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1040,7 +1040,7 @@ typedef struct {
u16 status;
} WifiCtlHdr;
-WifiCtlHdr wifictlhdr8023 = {
+static WifiCtlHdr wifictlhdr8023 = {
.ctlhdr = {
.ctl = HOST_DONT_RLSE,
}
@@ -1111,13 +1111,13 @@ static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
#ifdef WIRELESS_EXT
-struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
+static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
static void airo_read_wireless_stats (struct airo_info *local);
#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
-int flashcard(struct net_device *dev, aironet_ioctl *comp);
+static int flashcard(struct net_device *dev, aironet_ioctl *comp);
#endif /* CISCO_EXT */
#ifdef MICSUPPORT
static void micinit(struct airo_info *ai);
@@ -1226,6 +1226,12 @@ static int setup_proc_entry( struct net_device *dev,
static int takedown_proc_entry( struct net_device *dev,
struct airo_info *apriv );
+static int cmdreset(struct airo_info *ai);
+static int setflashmode (struct airo_info *ai);
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
+static int flashputbuf(struct airo_info *ai);
+static int flashrestart(struct airo_info *ai,struct net_device *dev);
+
#ifdef MICSUPPORT
/***********************************************************************
* MIC ROUTINES *
@@ -1234,10 +1240,11 @@ static int takedown_proc_entry( struct net_device *dev,
static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
static void MoveWindow(miccntx *context, u32 micSeq);
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
-void emmh32_init(emmh32_context *context);
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
-void emmh32_final(emmh32_context *context, u8 digest[4]);
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
+static void emmh32_init(emmh32_context *context);
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
+static void emmh32_final(emmh32_context *context, u8 digest[4]);
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
/* micinit - Initialize mic seed */
@@ -1301,7 +1308,7 @@ static int micsetup(struct airo_info *ai) {
int i;
if (ai->tfm == NULL)
- ai->tfm = crypto_alloc_tfm("aes", 0);
+ ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
if (ai->tfm == NULL) {
printk(KERN_ERR "airo: failed to load transform for AES\n");
@@ -1315,7 +1322,7 @@ static int micsetup(struct airo_info *ai) {
return SUCCESS;
}
-char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
/*===========================================================================
* Description: Mic a packet
@@ -1570,7 +1577,7 @@ static void MoveWindow(miccntx *context, u32 micSeq)
static unsigned char aes_counter[16];
/* expand the key to fill the MMH coefficient array */
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
{
/* take the keying material, expand if necessary, truncate at 16-bytes */
/* run through AES counter mode to generate context->coeff[] */
@@ -1602,7 +1609,7 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
}
/* prepare for calculation of a new mic */
-void emmh32_init(emmh32_context *context)
+static void emmh32_init(emmh32_context *context)
{
/* prepare for new mic calculation */
context->accum = 0;
@@ -1610,7 +1617,7 @@ void emmh32_init(emmh32_context *context)
}
/* add some bytes to the mic calculation */
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
{
int coeff_position, byte_position;
@@ -1652,7 +1659,7 @@ void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
/* calculate the mic */
-void emmh32_final(emmh32_context *context, u8 digest[4])
+static void emmh32_final(emmh32_context *context, u8 digest[4])
{
int coeff_position, byte_position;
u32 val;
@@ -2232,7 +2239,7 @@ static void airo_read_stats(struct airo_info *ai) {
u32 *vals = stats_rid.vals;
clear_bit(JOB_STATS, &ai->flags);
- if (ai->power) {
+ if (ai->power.event) {
up(&ai->sem);
return;
}
@@ -2255,7 +2262,7 @@ static void airo_read_stats(struct airo_info *ai) {
ai->stats.rx_fifo_errors = vals[0];
}
-struct net_device_stats *airo_get_stats(struct net_device *dev)
+static struct net_device_stats *airo_get_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
@@ -2403,8 +2410,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
}
}
#ifdef MICSUPPORT
- if (ai->tfm)
- crypto_free_tfm(ai->tfm);
+ crypto_free_tfm(ai->tfm);
#endif
del_airo_dev( dev );
free_netdev( dev );
@@ -2414,7 +2420,7 @@ EXPORT_SYMBOL(stop_airo_card);
static int add_airo_dev( struct net_device *dev );
-int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
+static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
return ETH_ALEN;
@@ -2681,7 +2687,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
return dev;
}
-int reset_card( struct net_device *dev , int lock) {
+static int reset_card( struct net_device *dev , int lock) {
struct airo_info *ai = dev->priv;
if (lock && down_interruptible(&ai->sem))
@@ -2696,9 +2702,9 @@ int reset_card( struct net_device *dev , int lock) {
return 0;
}
-struct net_device *_init_airo_card( unsigned short irq, int port,
- int is_pcmcia, struct pci_dev *pci,
- struct device *dmdev )
+static struct net_device *_init_airo_card( unsigned short irq, int port,
+ int is_pcmcia, struct pci_dev *pci,
+ struct device *dmdev )
{
struct net_device *dev;
struct airo_info *ai;
@@ -2962,7 +2968,7 @@ static int airo_thread(void *data) {
break;
}
- if (ai->power || test_bit(FLAG_FLASHING, &ai->flags)) {
+ if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
up(&ai->sem);
continue;
}
@@ -3252,7 +3258,7 @@ badrx:
wstats.noise = apriv->wstats.qual.noise;
wstats.updated = IW_QUAL_LEVEL_UPDATED
| IW_QUAL_QUAL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(dev, sa, &wstats);
}
@@ -3598,7 +3604,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
wstats.noise = ai->wstats.qual.noise;
wstats.updated = IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(ai->dev, sa, &wstats);
}
@@ -5514,7 +5520,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
- if (ai->power > 1) {
+ if (ai->power.event > 1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
@@ -6483,22 +6489,20 @@ static int airo_get_range(struct net_device *dev,
range->max_qual.qual = 100; /* % */
else
range->max_qual.qual = airo_get_max_quality(&cap_rid);
- range->max_qual.level = 0; /* 0 means we use dBm */
- range->max_qual.noise = 0;
- range->max_qual.updated = 0;
+ range->max_qual.level = 0x100 - 120; /* -120 dBm */
+ range->max_qual.noise = 0x100 - 120; /* -120 dBm */
/* Experimental measurements - boundary 11/5.5 Mb/s */
/* Note : with or without the (local->rssi), results
* are somewhat different. - Jean II */
if (local->rssi) {
- range->avg_qual.qual = 50; /* % */
- range->avg_qual.level = 186; /* -70 dBm */
+ range->avg_qual.qual = 50; /* % */
+ range->avg_qual.level = 0x100 - 70; /* -70 dBm */
} else {
range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
- range->avg_qual.level = 176; /* -80 dBm */
+ range->avg_qual.level = 0x100 - 80; /* -80 dBm */
}
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 0;
+ range->avg_qual.noise = 0x100 - 85; /* -85 dBm */
for(i = 0 ; i < 8 ; i++) {
range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
@@ -6721,15 +6725,17 @@ static int airo_get_aplist(struct net_device *dev,
if (local->rssi) {
qual[i].level = 0x100 - BSSList.dBm;
qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
- qual[i].updated = IW_QUAL_QUAL_UPDATED;
+ qual[i].updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
qual[i].level = (BSSList.dBm + 321) / 2;
qual[i].qual = 0;
- qual[i].updated = IW_QUAL_QUAL_INVALID;
+ qual[i].updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
qual[i].noise = local->wstats.qual.noise;
- qual[i].updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
if (BSSList.index == 0xffff)
break;
}
@@ -6855,15 +6861,17 @@ static inline char *airo_translate_scan(struct net_device *dev,
if (ai->rssi) {
iwe.u.qual.level = 0x100 - bss->dBm;
iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
iwe.u.qual.level = (bss->dBm + 321) / 2;
iwe.u.qual.qual = 0;
- iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
+ iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
iwe.u.qual.noise = ai->wstats.qual.noise;
- iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
/* Add encryption capability */
@@ -7116,7 +7124,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int rc = 0;
struct airo_info *ai = (struct airo_info *)dev->priv;
- if (ai->power)
+ if (ai->power.event)
return 0;
switch (cmd) {
@@ -7195,7 +7203,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
/* Get stats out of the card */
clear_bit(JOB_WSTATS, &local->flags);
- if (local->power) {
+ if (local->power.event) {
up(&local->sem);
return;
}
@@ -7216,13 +7224,12 @@ static void airo_read_wireless_stats(struct airo_info *local)
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
}
- local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
if (status_rid.len >= 124) {
local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
- local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
+ local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
} else {
local->wstats.qual.noise = 0;
- local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+ local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
}
/* Packets discarded in the wireless adapter due to wireless
@@ -7235,7 +7242,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
local->wstats.miss.beacon = vals[34];
}
-struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
@@ -7450,14 +7457,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
* Flash command switch table
*/
-int flashcard(struct net_device *dev, aironet_ioctl *comp) {
+static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
int z;
- int cmdreset(struct airo_info *);
- int setflashmode(struct airo_info *);
- int flashgchar(struct airo_info *,int,int);
- int flashpchar(struct airo_info *,int,int);
- int flashputbuf(struct airo_info *);
- int flashrestart(struct airo_info *,struct net_device *);
/* Only super-user can modify flash */
if (!capable(CAP_NET_ADMIN))
@@ -7515,7 +7516,7 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
* card.
*/
-int cmdreset(struct airo_info *ai) {
+static int cmdreset(struct airo_info *ai) {
disable_MAC(ai, 1);
if(!waitbusy (ai)){
@@ -7539,7 +7540,7 @@ int cmdreset(struct airo_info *ai) {
* mode
*/
-int setflashmode (struct airo_info *ai) {
+static int setflashmode (struct airo_info *ai) {
set_bit (FLAG_FLASHING, &ai->flags);
OUT4500(ai, SWS0, FLASH_COMMAND);
@@ -7566,7 +7567,7 @@ int setflashmode (struct airo_info *ai) {
* x 50us for echo .
*/
-int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
int echo;
int waittime;
@@ -7606,7 +7607,7 @@ int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
* Get a character from the card matching matchbyte
* Step 3)
*/
-int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
int rchar;
unsigned char rbyte=0;
@@ -7637,7 +7638,7 @@ int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
* send to the card
*/
-int flashputbuf(struct airo_info *ai){
+static int flashputbuf(struct airo_info *ai){
int nwords;
/* Write stuff */
@@ -7659,7 +7660,7 @@ int flashputbuf(struct airo_info *ai){
/*
*
*/
-int flashrestart(struct airo_info *ai,struct net_device *dev){
+static int flashrestart(struct airo_info *ai,struct net_device *dev){
int i,status;
ssleep(1); /* Added 12/7/00 */
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 18a7d38d2a13..587869d86eee 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -68,7 +68,7 @@
#include <linux/device.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
-#include "ieee802_11.h"
+#include <net/ieee80211.h>
#include "atmel.h"
#define DRIVER_MAJOR 0
@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
static int start_tx (struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -863,17 +863,17 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
return 1;
}
- frame_ctl = IEEE802_11_FTYPE_DATA;
+ frame_ctl = IEEE80211_FTYPE_DATA;
header.duration_id = 0;
header.seq_ctl = 0;
if (priv->wep_is_on)
- frame_ctl |= IEEE802_11_FCTL_WEP;
+ frame_ctl |= IEEE80211_FCTL_PROTECTED;
if (priv->operating_mode == IW_MODE_ADHOC) {
memcpy(&header.addr1, skb->data, 6);
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, priv->BSSID, 6);
} else {
- frame_ctl |= IEEE802_11_FCTL_TODS;
+ frame_ctl |= IEEE80211_FCTL_TODS;
memcpy(&header.addr1, priv->CurrentBSSID, 6);
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, skb->data, 6);
@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee802_11_hdr *header,
+ struct ieee80211_hdr *header,
u8 *body, int body_len)
{
u16 buff;
@@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
-static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
@@ -955,7 +955,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
}
memcpy(skbp, header->addr1, 6); /* destination address */
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(&skbp[6], header->addr3, 6);
else
memcpy(&skbp[6], header->addr2, 6); /* source address */
@@ -990,14 +990,14 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return (crc ^ 0xffffffff) == netcrc;
}
-static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
{
u8 mac4[6];
u8 source[6];
struct sk_buff *skb;
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(source, header->addr3, 6);
else
memcpy(source, header->addr2, 6);
@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
static void rx_done_irq(struct atmel_private *priv)
{
int i;
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr header;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -1117,7 +1117,7 @@ static void rx_done_irq(struct atmel_private *priv)
/* probe for CRC use here if needed once five packets have arrived with
the same crc status, we assume we know what's happening and stop probing */
if (priv->probe_crc) {
- if (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
+ if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
} else {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
@@ -1132,16 +1132,16 @@ static void rx_done_irq(struct atmel_private *priv)
}
/* don't CRC header when WEP in use */
- if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
+ if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
}
msdu_size -= 24; /* header */
- if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) {
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
- int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;
- u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;
- u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;
+ int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
+ u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
+ u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
if (!more_fragments && packet_fragment_no == 0 ) {
fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
@@ -1151,7 +1151,7 @@ static void rx_done_irq(struct atmel_private *priv)
}
}
- if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
/* copy rest of packet into buffer */
atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
@@ -1593,7 +1593,6 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT
dev->set_mac_address = atmel_set_mac_address;
dev->hard_start_xmit = start_tx;
dev->get_stats = atmel_get_stats;
- dev->get_wireless_stats = atmel_get_wireless_stats;
dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
dev->do_ioctl = atmel_ioctl;
dev->irq = irq;
@@ -2411,7 +2410,8 @@ static const struct iw_handler_def atmel_handler_def =
.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
.standard = (iw_handler *) atmel_handler,
.private = (iw_handler *) atmel_private_handler,
- .private_args = (struct iw_priv_args *) atmel_private_args
+ .private_args = (struct iw_priv_args *) atmel_private_args,
+ .get_wireless_stats = atmel_get_wireless_stats
};
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2424,19 +2424,6 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
char domain[REGDOMAINSZ+1];
switch (cmd) {
- case SIOCGIWPRIV:
- if(wrq->u.data.pointer) {
- /* Set the number of ioctl available */
- wrq->u.data.length = sizeof(atmel_private_args) / sizeof(atmel_private_args[0]);
-
- /* Copy structure to the user buffer */
- if (copy_to_user(wrq->u.data.pointer,
- (u_char *) atmel_private_args,
- sizeof(atmel_private_args)))
- rc = -EFAULT;
- }
- break;
-
case ATMELIDIFC:
wrq->u.param.value = ATMELMAGIC;
break;
@@ -2663,10 +2650,10 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
{
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr header;
struct auth_body auth;
- header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH);
+ header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
@@ -2677,7 +2664,7 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng
auth.alg = cpu_to_le16(C80211_MGMT_AAN_SHAREDKEY);
/* no WEP for authentication frames with TrSeqNo 1 */
if (priv->CurrentAuthentTransactionSeqNum != 1)
- header.frame_ctl |= cpu_to_le16(IEEE802_11_FCTL_WEP);
+ header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
} else {
auth.alg = cpu_to_le16(C80211_MGMT_AAN_OPENSYSTEM);
}
@@ -2701,7 +2688,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
{
u8 *ssid_el_p;
int bodysize;
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr header;
struct ass_req_format {
u16 capability;
u16 listen_interval;
@@ -2714,8 +2701,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
u8 rates[4];
} body;
- header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT |
- (is_reassoc ? IEEE802_11_STYPE_REASSOC_REQ : IEEE802_11_STYPE_ASSOC_REQ));
+ header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ (is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
@@ -2751,9 +2738,9 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
}
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee802_11_hdr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
{
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
else
return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
@@ -2801,7 +2788,7 @@ static int retrieve_bss(struct atmel_private *priv)
}
-static void store_bss_info(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
u8 ssid_len, u8 *ssid, int is_beacon)
{
@@ -3085,12 +3072,12 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
- switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_STYPE) {
+ switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
case C80211_SUBTYPE_MGMT_BEACON :
case C80211_SUBTYPE_MGMT_ProbeResponse:
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
new file mode 100644
index 000000000000..56f41c714d38
--- /dev/null
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -0,0 +1,73 @@
+config HOSTAP
+ tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
+ depends on NET_RADIO
+ select IEEE80211
+ select IEEE80211_CRYPT_WEP
+ ---help---
+ Shared driver code for IEEE 802.11b wireless cards based on
+ Intersil Prism2/2.5/3 chipset. This driver supports so called
+ Host AP mode that allows the card to act as an IEEE 802.11
+ access point.
+
+ See <http://hostap.epitest.fi/> for more information about the
+ Host AP driver configuration and tools. This site includes
+ information and tools (hostapd and wpa_supplicant) for WPA/WPA2
+ support.
+
+ This option includes the base Host AP driver code that is shared by
+ different hardware models. You will also need to enable support for
+ PLX/PCI/CS version of the driver to actually use the driver.
+
+ The driver can be compiled as a module and it will be called
+ "hostap.ko".
+
+config HOSTAP_FIRMWARE
+ bool "Support downloading firmware images with Host AP driver"
+ depends on HOSTAP
+ ---help---
+ Configure Host AP driver to include support for firmware image
+ download. Current version supports only downloading to volatile, i.e.,
+ RAM memory. Flash upgrade is not yet supported.
+
+ Firmware image downloading needs user space tool, prism2_srec. It is
+ available from http://hostap.epitest.fi/.
+
+config HOSTAP_PLX
+ tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
+ depends on PCI && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based
+ PCI adaptors.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_plx.ko".
+
+config HOSTAP_PCI
+ tristate "Host AP driver for Prism2.5 PCI adaptors"
+ depends on PCI && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2.5 PCI adaptors.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_pci.ko".
+
+config HOSTAP_CS
+ tristate "Host AP driver for Prism2/2.5/3 PC Cards"
+ depends on PCMCIA!=n && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2/2.5/3 PC Cards.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_cs.ko".
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
new file mode 100644
index 000000000000..fc62235bfc24
--- /dev/null
+++ b/drivers/net/wireless/hostap/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HOSTAP) += hostap.o
+
+obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
+obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o
+obj-$(CONFIG_HOSTAP_PCI) += hostap_pci.o
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
new file mode 100644
index 000000000000..e7f5821b4942
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap.c
@@ -0,0 +1,1198 @@
+/*
+ * Host AP (software wireless LAN access point) driver for
+ * Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/workqueue.h>
+#include <linux/kmod.h>
+#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211_crypt.h>
+#include <asm/uaccess.h>
+
+#include "hostap_wlan.h"
+#include "hostap_80211.h"
+#include "hostap_ap.h"
+#include "hostap.h"
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP common routines");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+#define TX_TIMEOUT (2 * HZ)
+
+#define PRISM2_MAX_FRAME_SIZE 2304
+#define PRISM2_MIN_MTU 256
+/* FIX: */
+#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */))
+
+
+/* hostap.c */
+static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked);
+static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove);
+
+/* hostap_ap.c */
+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist);
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+static int prism2_hostapd(struct ap_data *ap,
+ struct prism2_hostapd_param *param);
+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt);
+static void ap_control_kickall(struct ap_data *ap);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac);
+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac);
+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
+ u8 *mac);
+#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
+
+/* FIX: these could be compiled separately and linked together to hostap.o */
+#include "hostap_ap.c"
+#include "hostap_info.c"
+#include "hostap_ioctl.c"
+#include "hostap_proc.c"
+#include "hostap_80211_rx.c"
+#include "hostap_80211_tx.c"
+
+
+struct net_device * hostap_add_interface(struct local_info *local,
+ int type, int rtnl_locked,
+ const char *prefix,
+ const char *name)
+{
+ struct net_device *dev, *mdev;
+ struct hostap_interface *iface;
+ int ret;
+
+ dev = alloc_etherdev(sizeof(struct hostap_interface));
+ if (dev == NULL)
+ return NULL;
+
+ iface = netdev_priv(dev);
+ iface->dev = dev;
+ iface->local = local;
+ iface->type = type;
+ list_add(&iface->list, &local->hostap_interfaces);
+
+ mdev = local->dev;
+ memcpy(dev->dev_addr, mdev->dev_addr, ETH_ALEN);
+ dev->base_addr = mdev->base_addr;
+ dev->irq = mdev->irq;
+ dev->mem_start = mdev->mem_start;
+ dev->mem_end = mdev->mem_end;
+
+ hostap_setup_dev(dev, local, 0);
+ dev->destructor = free_netdev;
+
+ sprintf(dev->name, "%s%s", prefix, name);
+ if (!rtnl_locked)
+ rtnl_lock();
+
+ ret = 0;
+ if (strchr(dev->name, '%'))
+ ret = dev_alloc_name(dev, dev->name);
+
+ SET_NETDEV_DEV(dev, mdev->class_dev.dev);
+ if (ret >= 0)
+ ret = register_netdevice(dev);
+
+ if (!rtnl_locked)
+ rtnl_unlock();
+
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: failed to add new netdevice!\n",
+ dev->name);
+ free_netdev(dev);
+ return NULL;
+ }
+
+ printk(KERN_DEBUG "%s: registered netdevice %s\n",
+ mdev->name, dev->name);
+
+ return dev;
+}
+
+
+void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
+ int remove_from_list)
+{
+ struct hostap_interface *iface;
+
+ if (!dev)
+ return;
+
+ iface = netdev_priv(dev);
+
+ if (remove_from_list) {
+ list_del(&iface->list);
+ }
+
+ if (dev == iface->local->ddev)
+ iface->local->ddev = NULL;
+ else if (dev == iface->local->apdev)
+ iface->local->apdev = NULL;
+ else if (dev == iface->local->stadev)
+ iface->local->stadev = NULL;
+
+ if (rtnl_locked)
+ unregister_netdevice(dev);
+ else
+ unregister_netdev(dev);
+
+ /* dev->destructor = free_netdev() will free the device data, including
+ * private data, when removing the device */
+}
+
+
+static inline int prism2_wds_special_addr(u8 *addr)
+{
+ if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5])
+ return 0;
+
+ return 1;
+}
+
+
+static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked)
+{
+ struct net_device *dev;
+ struct list_head *ptr;
+ struct hostap_interface *iface, *empty, *match;
+
+ empty = match = NULL;
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+
+ if (prism2_wds_special_addr(iface->u.wds.remote_addr))
+ empty = iface;
+ else if (memcmp(iface->u.wds.remote_addr, remote_addr,
+ ETH_ALEN) == 0) {
+ match = iface;
+ break;
+ }
+ }
+ if (!match && empty && !prism2_wds_special_addr(remote_addr)) {
+ /* take pre-allocated entry into use */
+ memcpy(empty->u.wds.remote_addr, remote_addr, ETH_ALEN);
+ read_unlock_bh(&local->iface_lock);
+ printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n",
+ local->dev->name, empty->dev->name);
+ return 0;
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ if (!prism2_wds_special_addr(remote_addr)) {
+ if (match)
+ return -EEXIST;
+ hostap_add_sta(local->ap, remote_addr);
+ }
+
+ if (local->wds_connections >= local->wds_max_connections)
+ return -ENOBUFS;
+
+ /* verify that there is room for wds# postfix in the interface name */
+ if (strlen(local->dev->name) > IFNAMSIZ - 5) {
+ printk(KERN_DEBUG "'%s' too long base device name\n",
+ local->dev->name);
+ return -EINVAL;
+ }
+
+ dev = hostap_add_interface(local, HOSTAP_INTERFACE_WDS, rtnl_locked,
+ local->ddev->name, "wds%d");
+ if (dev == NULL)
+ return -ENOMEM;
+
+ iface = netdev_priv(dev);
+ memcpy(iface->u.wds.remote_addr, remote_addr, ETH_ALEN);
+
+ local->wds_connections++;
+
+ return 0;
+}
+
+
+static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct hostap_interface *iface, *selected = NULL;
+
+ write_lock_irqsave(&local->iface_lock, flags);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+
+ if (memcmp(iface->u.wds.remote_addr, remote_addr,
+ ETH_ALEN) == 0) {
+ selected = iface;
+ break;
+ }
+ }
+ if (selected && !do_not_remove)
+ list_del(&selected->list);
+ write_unlock_irqrestore(&local->iface_lock, flags);
+
+ if (selected) {
+ if (do_not_remove)
+ memset(selected->u.wds.remote_addr, 0, ETH_ALEN);
+ else {
+ hostap_remove_interface(selected->dev, rtnl_locked, 0);
+ local->wds_connections--;
+ }
+ }
+
+ return selected ? 0 : -ENODEV;
+}
+
+
+u16 hostap_tx_callback_register(local_info_t *local,
+ void (*func)(struct sk_buff *, int ok, void *),
+ void *data)
+{
+ unsigned long flags;
+ struct hostap_tx_callback_info *entry;
+
+ entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
+ GFP_ATOMIC);
+ if (entry == NULL)
+ return 0;
+
+ entry->func = func;
+ entry->data = data;
+
+ spin_lock_irqsave(&local->lock, flags);
+ entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1;
+ entry->next = local->tx_callback;
+ local->tx_callback = entry;
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ return entry->idx;
+}
+
+
+int hostap_tx_callback_unregister(local_info_t *local, u16 idx)
+{
+ unsigned long flags;
+ struct hostap_tx_callback_info *cb, *prev = NULL;
+
+ spin_lock_irqsave(&local->lock, flags);
+ cb = local->tx_callback;
+ while (cb != NULL && cb->idx != idx) {
+ prev = cb;
+ cb = cb->next;
+ }
+ if (cb) {
+ if (prev == NULL)
+ local->tx_callback = cb->next;
+ else
+ prev->next = cb->next;
+ kfree(cb);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ return cb ? 0 : -1;
+}
+
+
+/* val is in host byte order */
+int hostap_set_word(struct net_device *dev, int rid, u16 val)
+{
+ struct hostap_interface *iface;
+ u16 tmp = cpu_to_le16(val);
+ iface = netdev_priv(dev);
+ return iface->local->func->set_rid(dev, rid, &tmp, 2);
+}
+
+
+int hostap_set_string(struct net_device *dev, int rid, const char *val)
+{
+ struct hostap_interface *iface;
+ char buf[MAX_SSID_LEN + 2];
+ int len;
+
+ iface = netdev_priv(dev);
+ len = strlen(val);
+ if (len > MAX_SSID_LEN)
+ return -1;
+ memset(buf, 0, sizeof(buf));
+ buf[0] = len; /* little endian 16 bit word */
+ memcpy(buf + 2, val, len);
+
+ return iface->local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2);
+}
+
+
+u16 hostap_get_porttype(local_info_t *local)
+{
+ if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc)
+ return HFA384X_PORTTYPE_PSEUDO_IBSS;
+ if (local->iw_mode == IW_MODE_ADHOC)
+ return HFA384X_PORTTYPE_IBSS;
+ if (local->iw_mode == IW_MODE_INFRA)
+ return HFA384X_PORTTYPE_BSS;
+ if (local->iw_mode == IW_MODE_REPEAT)
+ return HFA384X_PORTTYPE_WDS;
+ if (local->iw_mode == IW_MODE_MONITOR)
+ return HFA384X_PORTTYPE_PSEUDO_IBSS;
+ return HFA384X_PORTTYPE_HOSTAP;
+}
+
+
+int hostap_set_encryption(local_info_t *local)
+{
+ u16 val, old_val;
+ int i, keylen, len, idx;
+ char keybuf[WEP_KEY_LEN + 1];
+ enum { NONE, WEP, OTHER } encrypt_type;
+
+ idx = local->tx_keyidx;
+ if (local->crypt[idx] == NULL || local->crypt[idx]->ops == NULL)
+ encrypt_type = NONE;
+ else if (strcmp(local->crypt[idx]->ops->name, "WEP") == 0)
+ encrypt_type = WEP;
+ else
+ encrypt_type = OTHER;
+
+ if (local->func->get_rid(local->dev, HFA384X_RID_CNFWEPFLAGS, &val, 2,
+ 1) < 0) {
+ printk(KERN_DEBUG "Could not read current WEP flags.\n");
+ goto fail;
+ }
+ le16_to_cpus(&val);
+ old_val = val;
+
+ if (encrypt_type != NONE || local->privacy_invoked)
+ val |= HFA384X_WEPFLAGS_PRIVACYINVOKED;
+ else
+ val &= ~HFA384X_WEPFLAGS_PRIVACYINVOKED;
+
+ if (local->open_wep || encrypt_type == NONE ||
+ ((local->ieee_802_1x || local->wpa) && local->host_decrypt))
+ val &= ~HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
+ else
+ val |= HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
+
+ if ((encrypt_type != NONE || local->privacy_invoked) &&
+ (encrypt_type == OTHER || local->host_encrypt))
+ val |= HFA384X_WEPFLAGS_HOSTENCRYPT;
+ else
+ val &= ~HFA384X_WEPFLAGS_HOSTENCRYPT;
+ if ((encrypt_type != NONE || local->privacy_invoked) &&
+ (encrypt_type == OTHER || local->host_decrypt))
+ val |= HFA384X_WEPFLAGS_HOSTDECRYPT;
+ else
+ val &= ~HFA384X_WEPFLAGS_HOSTDECRYPT;
+
+ if (val != old_val &&
+ hostap_set_word(local->dev, HFA384X_RID_CNFWEPFLAGS, val)) {
+ printk(KERN_DEBUG "Could not write new WEP flags (0x%x)\n",
+ val);
+ goto fail;
+ }
+
+ if (encrypt_type != WEP)
+ return 0;
+
+ /* 104-bit support seems to require that all the keys are set to the
+ * same keylen */
+ keylen = 6; /* first 5 octets */
+ len = local->crypt[idx]->ops->get_key(keybuf, sizeof(keybuf),
+ NULL, local->crypt[idx]->priv);
+ if (idx >= 0 && idx < WEP_KEYS && len > 5)
+ keylen = WEP_KEY_LEN + 1; /* first 13 octets */
+
+ for (i = 0; i < WEP_KEYS; i++) {
+ memset(keybuf, 0, sizeof(keybuf));
+ if (local->crypt[i]) {
+ (void) local->crypt[i]->ops->get_key(
+ keybuf, sizeof(keybuf),
+ NULL, local->crypt[i]->priv);
+ }
+ if (local->func->set_rid(local->dev,
+ HFA384X_RID_CNFDEFAULTKEY0 + i,
+ keybuf, keylen)) {
+ printk(KERN_DEBUG "Could not set key %d (len=%d)\n",
+ i, keylen);
+ goto fail;
+ }
+ }
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPDEFAULTKEYID, idx)) {
+ printk(KERN_DEBUG "Could not set default keyid %d\n", idx);
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ printk(KERN_DEBUG "%s: encryption setup failed\n", local->dev->name);
+ return -1;
+}
+
+
+int hostap_set_antsel(local_info_t *local)
+{
+ u16 val;
+ int ret = 0;
+
+ if (local->antsel_tx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_TX_CONFIGURE,
+ NULL, &val) == 0) {
+ val &= ~(BIT(2) | BIT(1));
+ switch (local->antsel_tx) {
+ case HOSTAP_ANTSEL_DIVERSITY:
+ val |= BIT(1);
+ break;
+ case HOSTAP_ANTSEL_LOW:
+ break;
+ case HOSTAP_ANTSEL_HIGH:
+ val |= BIT(2);
+ break;
+ }
+
+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_TX_CONFIGURE, &val, NULL)) {
+ printk(KERN_INFO "%s: setting TX AntSel failed\n",
+ local->dev->name);
+ ret = -1;
+ }
+ }
+
+ if (local->antsel_rx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_RX_CONFIGURE,
+ NULL, &val) == 0) {
+ val &= ~(BIT(1) | BIT(0));
+ switch (local->antsel_rx) {
+ case HOSTAP_ANTSEL_DIVERSITY:
+ break;
+ case HOSTAP_ANTSEL_LOW:
+ val |= BIT(0);
+ break;
+ case HOSTAP_ANTSEL_HIGH:
+ val |= BIT(0) | BIT(1);
+ break;
+ }
+
+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_RX_CONFIGURE, &val, NULL)) {
+ printk(KERN_INFO "%s: setting RX AntSel failed\n",
+ local->dev->name);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+
+int hostap_set_roaming(local_info_t *local)
+{
+ u16 val;
+
+ switch (local->host_roaming) {
+ case 1:
+ val = HFA384X_ROAMING_HOST;
+ break;
+ case 2:
+ val = HFA384X_ROAMING_DISABLED;
+ break;
+ case 0:
+ default:
+ val = HFA384X_ROAMING_FIRMWARE;
+ break;
+ }
+
+ return hostap_set_word(local->dev, HFA384X_RID_CNFROAMINGMODE, val);
+}
+
+
+int hostap_set_auth_algs(local_info_t *local)
+{
+ int val = local->auth_algs;
+ /* At least STA f/w v0.6.2 seems to have issues with cnfAuthentication
+ * set to include both Open and Shared Key flags. It tries to use
+ * Shared Key authentication in that case even if WEP keys are not
+ * configured.. STA f/w v0.7.6 is able to handle such configuration,
+ * but it is unknown when this was fixed between 0.6.2 .. 0.7.6. */
+ if (local->sta_fw_ver < PRISM2_FW_VER(0,7,0) &&
+ val != PRISM2_AUTH_OPEN && val != PRISM2_AUTH_SHARED_KEY)
+ val = PRISM2_AUTH_OPEN;
+
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFAUTHENTICATION, val)) {
+ printk(KERN_INFO "%s: cnfAuthentication setting to 0x%x "
+ "failed\n", local->dev->name, local->auth_algs);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
+{
+ u16 status, fc;
+
+ status = __le16_to_cpu(rx->status);
+
+ printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, "
+ "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; "
+ "jiffies=%ld\n",
+ name, status, (status >> 8) & 0x07, status >> 13, status & 1,
+ rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies);
+
+ fc = __le16_to_cpu(rx->frame_control);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
+ "data_len=%d%s%s\n",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl),
+ __le16_to_cpu(rx->data_len),
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
+ MACSTR "\n",
+ MAC2STR(rx->addr1), MAC2STR(rx->addr2), MAC2STR(rx->addr3),
+ MAC2STR(rx->addr4));
+
+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
+ MAC2STR(rx->dst_addr), MAC2STR(rx->src_addr),
+ __be16_to_cpu(rx->len));
+}
+
+
+void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
+{
+ u16 fc;
+
+ printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d "
+ "tx_control=0x%04x; jiffies=%ld\n",
+ name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate,
+ __le16_to_cpu(tx->tx_control), jiffies);
+
+ fc = __le16_to_cpu(tx->frame_control);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
+ "data_len=%d%s%s\n",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl),
+ __le16_to_cpu(tx->data_len),
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
+ MACSTR "\n",
+ MAC2STR(tx->addr1), MAC2STR(tx->addr2), MAC2STR(tx->addr3),
+ MAC2STR(tx->addr4));
+
+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
+ MAC2STR(tx->dst_addr), MAC2STR(tx->src_addr),
+ __be16_to_cpu(tx->len));
+}
+
+
+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); /* addr2 */
+ return ETH_ALEN;
+}
+
+
+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ if (*(u32 *)skb->mac.raw == LWNG_CAP_DID_BASE) {
+ memcpy(haddr, skb->mac.raw +
+ sizeof(struct linux_wlan_ng_prism_hdr) + 10,
+ ETH_ALEN); /* addr2 */
+ } else { /* (*(u32 *)skb->mac.raw == htonl(LWNG_CAPHDR_VERSION)) */
+ memcpy(haddr, skb->mac.raw +
+ sizeof(struct linux_wlan_ng_cap_hdr) + 10,
+ ETH_ALEN); /* addr2 */
+ }
+ return ETH_ALEN;
+}
+
+
+int hostap_80211_get_hdrlen(u16 fc)
+{
+ int hdrlen = 24;
+
+ switch (WLAN_FC_GET_TYPE(fc)) {
+ case IEEE80211_FTYPE_DATA:
+ if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+ hdrlen = 30; /* Addr4 */
+ break;
+ case IEEE80211_FTYPE_CTL:
+ switch (WLAN_FC_GET_STYPE(fc)) {
+ case IEEE80211_STYPE_CTS:
+ case IEEE80211_STYPE_ACK:
+ hdrlen = 10;
+ break;
+ default:
+ hdrlen = 16;
+ break;
+ }
+ break;
+ }
+
+ return hdrlen;
+}
+
+
+struct net_device_stats *hostap_get_stats(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ iface = netdev_priv(dev);
+ return &iface->stats;
+}
+
+
+static int prism2_close(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ PDEBUG(DEBUG_FLOW, "%s: prism2_close\n", dev->name);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (dev == local->ddev) {
+ prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
+ }
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (!local->hostapd && dev == local->dev &&
+ (!local->func->card_present || local->func->card_present(local)) &&
+ local->hw_ready && local->ap && local->iw_mode == IW_MODE_MASTER)
+ hostap_deauth_all_stas(dev, local->ap, 1);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ if (local->func->dev_close && local->func->dev_close(local))
+ return 0;
+
+ if (dev == local->dev) {
+ local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
+ }
+
+ if (netif_running(dev)) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+
+ flush_scheduled_work();
+
+ module_put(local->hw_module);
+
+ local->num_dev_open--;
+
+ if (dev != local->dev && local->dev->flags & IFF_UP &&
+ local->master_dev_auto_open && local->num_dev_open == 1) {
+ /* Close master radio interface automatically if it was also
+ * opened automatically and we are now closing the last
+ * remaining non-master device. */
+ dev_close(local->dev);
+ }
+
+ return 0;
+}
+
+
+static int prism2_open(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ PDEBUG(DEBUG_FLOW, "%s: prism2_open\n", dev->name);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: could not set interface UP - no PRI "
+ "f/w\n", dev->name);
+ return 1;
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ if (local->func->dev_open && local->func->dev_open(local))
+ return 1;
+
+ if (!try_module_get(local->hw_module))
+ return -ENODEV;
+ local->num_dev_open++;
+
+ if (!local->dev_enabled && local->func->hw_enable(dev, 1)) {
+ printk(KERN_WARNING "%s: could not enable MAC port\n",
+ dev->name);
+ prism2_close(dev);
+ return 1;
+ }
+ if (!local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_ENABLE);
+ local->dev_enabled = 1;
+
+ if (dev != local->dev && !(local->dev->flags & IFF_UP)) {
+ /* Master radio interface is needed for all operation, so open
+ * it automatically when any virtual net_device is opened. */
+ local->master_dev_auto_open = 1;
+ dev_open(local->dev);
+ }
+
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+
+static int prism2_set_mac_address(struct net_device *dev, void *p)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct list_head *ptr;
+ struct sockaddr *addr = p;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->set_rid(dev, HFA384X_RID_CNFOWNMACADDR, addr->sa_data,
+ ETH_ALEN) < 0 || local->func->reset_port(dev))
+ return -EINVAL;
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ memcpy(iface->dev->dev_addr, addr->sa_data, ETH_ALEN);
+ }
+ memcpy(local->dev->dev_addr, addr->sa_data, ETH_ALEN);
+ read_unlock_bh(&local->iface_lock);
+
+ return 0;
+}
+
+
+/* TODO: to be further implemented as soon as Prism2 fully supports
+ * GroupAddresses and correct documentation is available */
+void hostap_set_multicast_list_queue(void *data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
+ local->is_promisc)) {
+ printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",
+ dev->name, local->is_promisc ? "en" : "dis");
+ }
+}
+
+
+static void hostap_set_multicast_list(struct net_device *dev)
+{
+#if 0
+ /* FIX: promiscuous mode seems to be causing a lot of problems with
+ * some station firmware versions (FCSErr frames, invalid MACPort, etc.
+ * corrupted incoming frames). This code is now commented out while the
+ * problems are investigated. */
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if ((dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) {
+ local->is_promisc = 1;
+ } else {
+ local->is_promisc = 0;
+ }
+
+ schedule_work(&local->set_multicast_list_queue);
+#endif
+}
+
+
+static int prism2_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+
+static void prism2_tx_timeout(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_regs regs;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_WARNING "%s Tx timed out! Resetting card\n", dev->name);
+ netif_stop_queue(local->dev);
+
+ local->func->read_regs(dev, &regs);
+ printk(KERN_DEBUG "%s: CMD=%04x EVSTAT=%04x "
+ "OFFSET0=%04x OFFSET1=%04x SWSUPPORT0=%04x\n",
+ dev->name, regs.cmd, regs.evstat, regs.offset0, regs.offset1,
+ regs.swsupport0);
+
+ local->func->schedule_reset(local);
+}
+
+
+void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+ int main_dev)
+{
+ struct hostap_interface *iface;
+
+ iface = netdev_priv(dev);
+ ether_setup(dev);
+
+ /* kernel callbacks */
+ dev->get_stats = hostap_get_stats;
+ if (iface) {
+ /* Currently, we point to the proper spy_data only on
+ * the main_dev. This could be fixed. Jean II */
+ iface->wireless_data.spy_data = &iface->spy_data;
+ dev->wireless_data = &iface->wireless_data;
+ }
+ dev->wireless_handlers =
+ (struct iw_handler_def *) &hostap_iw_handler_def;
+ dev->do_ioctl = hostap_ioctl;
+ dev->open = prism2_open;
+ dev->stop = prism2_close;
+ dev->hard_start_xmit = hostap_data_start_xmit;
+ dev->set_mac_address = prism2_set_mac_address;
+ dev->set_multicast_list = hostap_set_multicast_list;
+ dev->change_mtu = prism2_change_mtu;
+ dev->tx_timeout = prism2_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->mtu = local->mtu;
+ if (!main_dev) {
+ /* use main radio device queue */
+ dev->tx_queue_len = 0;
+ }
+
+ SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
+
+ netif_stop_queue(dev);
+}
+
+
+static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ if (local->apdev)
+ return -EEXIST;
+
+ printk(KERN_DEBUG "%s: enabling hostapd mode\n", dev->name);
+
+ local->apdev = hostap_add_interface(local, HOSTAP_INTERFACE_AP,
+ rtnl_locked, local->ddev->name,
+ "ap");
+ if (local->apdev == NULL)
+ return -ENOMEM;
+
+ local->apdev->hard_start_xmit = hostap_mgmt_start_xmit;
+ local->apdev->type = ARPHRD_IEEE80211;
+ local->apdev->hard_header_parse = hostap_80211_header_parse;
+
+ return 0;
+}
+
+
+static int hostap_disable_hostapd(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name);
+
+ hostap_remove_interface(local->apdev, rtnl_locked, 1);
+ local->apdev = NULL;
+
+ return 0;
+}
+
+
+static int hostap_enable_hostapd_sta(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ if (local->stadev)
+ return -EEXIST;
+
+ printk(KERN_DEBUG "%s: enabling hostapd STA mode\n", dev->name);
+
+ local->stadev = hostap_add_interface(local, HOSTAP_INTERFACE_STA,
+ rtnl_locked, local->ddev->name,
+ "sta");
+ if (local->stadev == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+
+static int hostap_disable_hostapd_sta(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name);
+
+ hostap_remove_interface(local->stadev, rtnl_locked, 1);
+ local->stadev = NULL;
+
+ return 0;
+}
+
+
+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked)
+{
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ if (local->hostapd == val)
+ return 0;
+
+ if (val) {
+ ret = hostap_enable_hostapd(local, rtnl_locked);
+ if (ret == 0)
+ local->hostapd = 1;
+ } else {
+ local->hostapd = 0;
+ ret = hostap_disable_hostapd(local, rtnl_locked);
+ if (ret != 0)
+ local->hostapd = 1;
+ }
+
+ return ret;
+}
+
+
+int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked)
+{
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ if (local->hostapd_sta == val)
+ return 0;
+
+ if (val) {
+ ret = hostap_enable_hostapd_sta(local, rtnl_locked);
+ if (ret == 0)
+ local->hostapd_sta = 1;
+ } else {
+ local->hostapd_sta = 0;
+ ret = hostap_disable_hostapd_sta(local, rtnl_locked);
+ if (ret != 0)
+ local->hostapd_sta = 1;
+ }
+
+
+ return ret;
+}
+
+
+int prism2_update_comms_qual(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+ struct hfa384x_comms_quality sq;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if (!local->sta_fw_ver)
+ ret = -1;
+ else if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) {
+ if (local->func->get_rid(local->dev,
+ HFA384X_RID_DBMCOMMSQUALITY,
+ &sq, sizeof(sq), 1) >= 0) {
+ local->comms_qual = (s16) le16_to_cpu(sq.comm_qual);
+ local->avg_signal = (s16) le16_to_cpu(sq.signal_level);
+ local->avg_noise = (s16) le16_to_cpu(sq.noise_level);
+ local->last_comms_qual_update = jiffies;
+ } else
+ ret = -1;
+ } else {
+ if (local->func->get_rid(local->dev, HFA384X_RID_COMMSQUALITY,
+ &sq, sizeof(sq), 1) >= 0) {
+ local->comms_qual = le16_to_cpu(sq.comm_qual);
+ local->avg_signal = HFA384X_LEVEL_TO_dBm(
+ le16_to_cpu(sq.signal_level));
+ local->avg_noise = HFA384X_LEVEL_TO_dBm(
+ le16_to_cpu(sq.noise_level));
+ local->last_comms_qual_update = jiffies;
+ } else
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
+ u8 *body, size_t bodylen)
+{
+ struct sk_buff *skb;
+ struct hostap_ieee80211_mgmt *mgmt;
+ struct hostap_skb_tx_data *meta;
+ struct net_device *dev = local->dev;
+
+ skb = dev_alloc_skb(IEEE80211_MGMT_HDR_LEN + bodylen);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ mgmt = (struct hostap_ieee80211_mgmt *)
+ skb_put(skb, IEEE80211_MGMT_HDR_LEN);
+ memset(mgmt, 0, IEEE80211_MGMT_HDR_LEN);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
+ memcpy(mgmt->da, dst, ETH_ALEN);
+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->bssid, dst, ETH_ALEN);
+ if (body)
+ memcpy(skb_put(skb, bodylen), body, bodylen);
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = netdev_priv(dev);
+
+ skb->dev = dev;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ dev_queue_xmit(skb);
+
+ return 0;
+}
+
+
+int prism2_sta_deauth(local_info_t *local, u16 reason)
+{
+ union iwreq_data wrqu;
+ int ret;
+
+ if (local->iw_mode != IW_MODE_INFRA ||
+ memcmp(local->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 ||
+ memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0)
+ return 0;
+
+ reason = cpu_to_le16(reason);
+ ret = prism2_sta_send_mgmt(local, local->bssid, IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+ return ret;
+}
+
+
+struct proc_dir_entry *hostap_proc;
+
+static int __init hostap_init(void)
+{
+ if (proc_net != NULL) {
+ hostap_proc = proc_mkdir("hostap", proc_net);
+ if (!hostap_proc)
+ printk(KERN_WARNING "Failed to mkdir "
+ "/proc/net/hostap\n");
+ } else
+ hostap_proc = NULL;
+
+ return 0;
+}
+
+
+static void __exit hostap_exit(void)
+{
+ if (hostap_proc != NULL) {
+ hostap_proc = NULL;
+ remove_proc_entry("hostap", proc_net);
+ }
+}
+
+
+EXPORT_SYMBOL(hostap_set_word);
+EXPORT_SYMBOL(hostap_set_string);
+EXPORT_SYMBOL(hostap_get_porttype);
+EXPORT_SYMBOL(hostap_set_encryption);
+EXPORT_SYMBOL(hostap_set_antsel);
+EXPORT_SYMBOL(hostap_set_roaming);
+EXPORT_SYMBOL(hostap_set_auth_algs);
+EXPORT_SYMBOL(hostap_dump_rx_header);
+EXPORT_SYMBOL(hostap_dump_tx_header);
+EXPORT_SYMBOL(hostap_80211_header_parse);
+EXPORT_SYMBOL(hostap_80211_prism_header_parse);
+EXPORT_SYMBOL(hostap_80211_get_hdrlen);
+EXPORT_SYMBOL(hostap_get_stats);
+EXPORT_SYMBOL(hostap_setup_dev);
+EXPORT_SYMBOL(hostap_proc);
+EXPORT_SYMBOL(hostap_set_multicast_list_queue);
+EXPORT_SYMBOL(hostap_set_hostapd);
+EXPORT_SYMBOL(hostap_set_hostapd_sta);
+EXPORT_SYMBOL(hostap_add_interface);
+EXPORT_SYMBOL(hostap_remove_interface);
+EXPORT_SYMBOL(prism2_update_comms_qual);
+
+module_init(hostap_init);
+module_exit(hostap_exit);
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
new file mode 100644
index 000000000000..5fac89b8ce3a
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -0,0 +1,57 @@
+#ifndef HOSTAP_H
+#define HOSTAP_H
+
+/* hostap.c */
+
+extern struct proc_dir_entry *hostap_proc;
+
+u16 hostap_tx_callback_register(local_info_t *local,
+ void (*func)(struct sk_buff *, int ok, void *),
+ void *data);
+int hostap_tx_callback_unregister(local_info_t *local, u16 idx);
+int hostap_set_word(struct net_device *dev, int rid, u16 val);
+int hostap_set_string(struct net_device *dev, int rid, const char *val);
+u16 hostap_get_porttype(local_info_t *local);
+int hostap_set_encryption(local_info_t *local);
+int hostap_set_antsel(local_info_t *local);
+int hostap_set_roaming(local_info_t *local);
+int hostap_set_auth_algs(local_info_t *local);
+void hostap_dump_rx_header(const char *name,
+ const struct hfa384x_rx_frame *rx);
+void hostap_dump_tx_header(const char *name,
+ const struct hfa384x_tx_frame *tx);
+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr);
+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr);
+int hostap_80211_get_hdrlen(u16 fc);
+struct net_device_stats *hostap_get_stats(struct net_device *dev);
+void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+ int main_dev);
+void hostap_set_multicast_list_queue(void *data);
+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked);
+int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked);
+void hostap_cleanup(local_info_t *local);
+void hostap_cleanup_handler(void *data);
+struct net_device * hostap_add_interface(struct local_info *local,
+ int type, int rtnl_locked,
+ const char *prefix, const char *name);
+void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
+ int remove_from_list);
+int prism2_update_comms_qual(struct net_device *dev);
+int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
+ u8 *body, size_t bodylen);
+int prism2_sta_deauth(local_info_t *local, u16 reason);
+
+
+/* hostap_proc.c */
+
+void hostap_init_proc(local_info_t *local);
+void hostap_remove_proc(local_info_t *local);
+
+
+/* hostap_info.c */
+
+void hostap_info_init(local_info_t *local);
+void hostap_info_process(local_info_t *local, struct sk_buff *skb);
+
+
+#endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
new file mode 100644
index 000000000000..bf506f50d722
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -0,0 +1,96 @@
+#ifndef HOSTAP_80211_H
+#define HOSTAP_80211_H
+
+struct hostap_ieee80211_mgmt {
+ u16 frame_control;
+ u16 duration;
+ u8 da[6];
+ u8 sa[6];
+ u8 bssid[6];
+ u16 seq_ctrl;
+ union {
+ struct {
+ u16 auth_alg;
+ u16 auth_transaction;
+ u16 status_code;
+ /* possibly followed by Challenge text */
+ u8 variable[0];
+ } __attribute__ ((packed)) auth;
+ struct {
+ u16 reason_code;
+ } __attribute__ ((packed)) deauth;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) assoc_req;
+ struct {
+ u16 capab_info;
+ u16 status_code;
+ u16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) assoc_resp, reassoc_resp;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[6];
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) reassoc_req;
+ struct {
+ u16 reason_code;
+ } __attribute__ ((packed)) disassoc;
+ struct {
+ } __attribute__ ((packed)) probe_req;
+ struct {
+ u8 timestamp[8];
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+ } __attribute__ ((packed)) beacon, probe_resp;
+ } u;
+} __attribute__ ((packed));
+
+
+#define IEEE80211_MGMT_HDR_LEN 24
+#define IEEE80211_DATA_HDR3_LEN 24
+#define IEEE80211_DATA_HDR4_LEN 30
+
+
+struct hostap_80211_rx_status {
+ u32 mac_time;
+ u8 signal;
+ u8 noise;
+ u16 rate; /* in 100 kbps */
+};
+
+
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+
+
+/* prism2_rx_80211 'type' argument */
+enum {
+ PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC,
+ PRISM2_RX_NULLFUNC_ACK
+};
+
+int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int type);
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+
+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_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
new file mode 100644
index 000000000000..b0501243b175
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -0,0 +1,1091 @@
+#include <linux/etherdevice.h>
+
+#include "hostap_80211.h"
+#include "hostap.h"
+
+void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct ieee80211_hdr *hdr;
+ u16 fc;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
+ "jiffies=%ld\n",
+ name, rx_stats->signal, rx_stats->noise, rx_stats->rate,
+ skb->len, jiffies);
+
+ if (skb->len < 2)
+ return;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ printk("\n");
+ return;
+ }
+
+ printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
+ le16_to_cpu(hdr->seq_ctl));
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
+ if (skb->len >= 30)
+ printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
+ printk("\n");
+}
+
+
+/* Send RX frame to netif with 802.11 (and possible prism) header.
+ * Called from hardware or software IRQ context. */
+int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int type)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int hdrlen, phdrlen, head_need, tail_need;
+ u16 fc;
+ int prism_header, ret;
+ struct ieee80211_hdr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ dev->last_rx = jiffies;
+
+ if (dev->type == ARPHRD_IEEE80211_PRISM) {
+ if (local->monitor_type == PRISM2_MONITOR_PRISM) {
+ prism_header = 1;
+ phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);
+ } else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */
+ prism_header = 2;
+ phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
+ }
+ } else {
+ prism_header = 0;
+ phdrlen = 0;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
+ printk(KERN_DEBUG "%s: dropped management frame with header "
+ "version %d\n", dev->name, fc & IEEE80211_FCTL_VERS);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ /* check if there is enough room for extra data; if not, expand skb
+ * buffer to be large enough for the changes */
+ head_need = phdrlen;
+ tail_need = 0;
+#ifdef PRISM2_ADD_BOGUS_CRC
+ tail_need += 4;
+#endif /* PRISM2_ADD_BOGUS_CRC */
+
+ head_need -= skb_headroom(skb);
+ tail_need -= skb_tailroom(skb);
+
+ if (head_need > 0 || tail_need > 0) {
+ if (pskb_expand_head(skb, head_need > 0 ? head_need : 0,
+ tail_need > 0 ? tail_need : 0,
+ GFP_ATOMIC)) {
+ printk(KERN_DEBUG "%s: prism2_rx_80211 failed to "
+ "reallocate skb buffer\n", dev->name);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ }
+
+ /* We now have an skb with enough head and tail room, so just insert
+ * the extra data */
+
+#ifdef PRISM2_ADD_BOGUS_CRC
+ memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */
+#endif /* PRISM2_ADD_BOGUS_CRC */
+
+ if (prism_header == 1) {
+ struct linux_wlan_ng_prism_hdr *hdr;
+ hdr = (struct linux_wlan_ng_prism_hdr *)
+ skb_push(skb, phdrlen);
+ memset(hdr, 0, phdrlen);
+ hdr->msgcode = LWNG_CAP_DID_BASE;
+ hdr->msglen = sizeof(*hdr);
+ memcpy(hdr->devname, dev->name, sizeof(hdr->devname));
+#define LWNG_SETVAL(f,i,s,l,d) \
+hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \
+hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
+ LWNG_SETVAL(hosttime, 1, 0, 4, jiffies);
+ LWNG_SETVAL(mactime, 2, 0, 4, rx_stats->mac_time);
+ LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal);
+ LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise);
+ LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5);
+ LWNG_SETVAL(istx, 9, 0, 4, 0);
+ LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen);
+#undef LWNG_SETVAL
+ } else if (prism_header == 2) {
+ struct linux_wlan_ng_cap_hdr *hdr;
+ hdr = (struct linux_wlan_ng_cap_hdr *)
+ skb_push(skb, phdrlen);
+ memset(hdr, 0, phdrlen);
+ hdr->version = htonl(LWNG_CAPHDR_VERSION);
+ hdr->length = htonl(phdrlen);
+ hdr->mactime = __cpu_to_be64(rx_stats->mac_time);
+ hdr->hosttime = __cpu_to_be64(jiffies);
+ hdr->phytype = htonl(4); /* dss_dot11_b */
+ hdr->channel = htonl(local->channel);
+ hdr->datarate = htonl(rx_stats->rate);
+ hdr->antenna = htonl(0); /* unknown */
+ hdr->priority = htonl(0); /* unknown */
+ hdr->ssi_type = htonl(3); /* raw */
+ hdr->ssi_signal = htonl(rx_stats->signal);
+ hdr->ssi_noise = htonl(rx_stats->noise);
+ hdr->preamble = htonl(0); /* unknown */
+ hdr->encoding = htonl(1); /* cck */
+ }
+
+ ret = skb->len - phdrlen;
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ skb_pull(skb, hdrlen);
+ if (prism_header)
+ skb_pull(skb, phdrlen);
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = __constant_htons(ETH_P_802_2);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void monitor_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device_stats *stats;
+ int len;
+
+ len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR);
+ stats = hostap_get_stats(dev);
+ stats->rx_packets++;
+ stats->rx_bytes += len;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static struct prism2_frag_entry *
+prism2_frag_cache_find(local_info_t *local, unsigned int seq,
+ unsigned int frag, u8 *src, u8 *dst)
+{
+ struct prism2_frag_entry *entry;
+ int i;
+
+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
+ entry = &local->frag_cache[i];
+ if (entry->skb != NULL &&
+ time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ printk(KERN_DEBUG "%s: expiring fragment cache entry "
+ "seq=%u last_frag=%u\n",
+ local->dev->name, entry->seq, entry->last_frag);
+ dev_kfree_skb(entry->skb);
+ entry->skb = NULL;
+ }
+
+ if (entry->skb != NULL && entry->seq == seq &&
+ (entry->last_frag + 1 == frag || frag == -1) &&
+ memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
+ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
+ return entry;
+ }
+
+ return NULL;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
+{
+ struct sk_buff *skb = NULL;
+ u16 sc;
+ unsigned int frag, seq;
+ struct prism2_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
+
+ if (frag == 0) {
+ /* Reserve enough space to fit maximum frame length */
+ skb = dev_alloc_skb(local->dev->mtu +
+ sizeof(struct ieee80211_hdr) +
+ 8 /* LLC */ +
+ 2 /* alignment */ +
+ 8 /* WEP */ + ETH_ALEN /* WDS */);
+ if (skb == NULL)
+ return NULL;
+
+ entry = &local->frag_cache[local->frag_next_idx];
+ local->frag_next_idx++;
+ if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN)
+ local->frag_next_idx = 0;
+
+ if (entry->skb != NULL)
+ dev_kfree_skb(entry->skb);
+
+ entry->first_frag_time = jiffies;
+ entry->seq = seq;
+ entry->last_frag = frag;
+ entry->skb = skb;
+ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+ } else {
+ /* received a fragment of a frame for which the head fragment
+ * should have already been received */
+ entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2,
+ hdr->addr1);
+ if (entry != NULL) {
+ entry->last_frag = frag;
+ skb = entry->skb;
+ }
+ }
+
+ return skb;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int prism2_frag_cache_invalidate(local_info_t *local,
+ struct ieee80211_hdr *hdr)
+{
+ u16 sc;
+ unsigned int seq;
+ struct prism2_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
+
+ entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);
+
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: could not invalidate fragment cache "
+ "entry (seq=%u)\n",
+ local->dev->name, seq);
+ return -1;
+ }
+
+ entry->skb = NULL;
+ return 0;
+}
+
+
+static struct hostap_bss_info *__hostap_get_bss(local_info_t *local, u8 *bssid,
+ u8 *ssid, size_t ssid_len)
+{
+ struct list_head *ptr;
+ struct hostap_bss_info *bss;
+
+ list_for_each(ptr, &local->bss_list) {
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
+ (ssid == NULL ||
+ (ssid_len == bss->ssid_len &&
+ memcmp(ssid, bss->ssid, ssid_len) == 0))) {
+ list_move(&bss->list, &local->bss_list);
+ return bss;
+ }
+ }
+
+ return NULL;
+}
+
+
+static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid,
+ u8 *ssid, size_t ssid_len)
+{
+ struct hostap_bss_info *bss;
+
+ if (local->num_bss_info >= HOSTAP_MAX_BSS_COUNT) {
+ bss = list_entry(local->bss_list.prev,
+ struct hostap_bss_info, list);
+ list_del(&bss->list);
+ local->num_bss_info--;
+ } else {
+ bss = (struct hostap_bss_info *)
+ kmalloc(sizeof(*bss), GFP_ATOMIC);
+ if (bss == NULL)
+ return NULL;
+ }
+
+ memset(bss, 0, sizeof(*bss));
+ memcpy(bss->bssid, bssid, ETH_ALEN);
+ memcpy(bss->ssid, ssid, ssid_len);
+ bss->ssid_len = ssid_len;
+ local->num_bss_info++;
+ list_add(&bss->list, &local->bss_list);
+ return bss;
+}
+
+
+static void __hostap_expire_bss(local_info_t *local)
+{
+ struct hostap_bss_info *bss;
+
+ while (local->num_bss_info > 0) {
+ bss = list_entry(local->bss_list.prev,
+ struct hostap_bss_info, list);
+ if (!time_after(jiffies, bss->last_update + 60 * HZ))
+ break;
+
+ list_del(&bss->list);
+ local->num_bss_info--;
+ kfree(bss);
+ }
+}
+
+
+/* Both IEEE 802.11 Beacon and Probe Response frames have similar structure, so
+ * the same routine can be used to parse both of them. */
+static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
+ int stype)
+{
+ struct hostap_ieee80211_mgmt *mgmt;
+ int left, chan = 0;
+ u8 *pos;
+ u8 *ssid = NULL, *wpa = NULL, *rsn = NULL;
+ size_t ssid_len = 0, wpa_len = 0, rsn_len = 0;
+ struct hostap_bss_info *bss;
+
+ if (skb->len < IEEE80211_MGMT_HDR_LEN + sizeof(mgmt->u.beacon))
+ return;
+
+ mgmt = (struct hostap_ieee80211_mgmt *) skb->data;
+ pos = mgmt->u.beacon.variable;
+ left = skb->len - (pos - skb->data);
+
+ while (left >= 2) {
+ if (2 + pos[1] > left)
+ return; /* parse failed */
+ switch (*pos) {
+ case WLAN_EID_SSID:
+ ssid = pos + 2;
+ ssid_len = pos[1];
+ break;
+ case WLAN_EID_GENERIC:
+ if (pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 1) {
+ wpa = pos;
+ wpa_len = pos[1] + 2;
+ }
+ break;
+ case WLAN_EID_RSN:
+ rsn = pos;
+ rsn_len = pos[1] + 2;
+ break;
+ case WLAN_EID_DS_PARAMS:
+ if (pos[1] >= 1)
+ chan = pos[2];
+ break;
+ }
+ left -= 2 + pos[1];
+ pos += 2 + pos[1];
+ }
+
+ if (wpa_len > MAX_WPA_IE_LEN)
+ wpa_len = MAX_WPA_IE_LEN;
+ if (rsn_len > MAX_WPA_IE_LEN)
+ rsn_len = MAX_WPA_IE_LEN;
+ if (ssid_len > sizeof(bss->ssid))
+ ssid_len = sizeof(bss->ssid);
+
+ spin_lock(&local->lock);
+ bss = __hostap_get_bss(local, mgmt->bssid, ssid, ssid_len);
+ if (bss == NULL)
+ bss = __hostap_add_bss(local, mgmt->bssid, ssid, ssid_len);
+ if (bss) {
+ bss->last_update = jiffies;
+ bss->count++;
+ bss->capab_info = le16_to_cpu(mgmt->u.beacon.capab_info);
+ if (wpa) {
+ memcpy(bss->wpa_ie, wpa, wpa_len);
+ bss->wpa_ie_len = wpa_len;
+ } else
+ bss->wpa_ie_len = 0;
+ if (rsn) {
+ memcpy(bss->rsn_ie, rsn, rsn_len);
+ bss->rsn_ie_len = rsn_len;
+ } else
+ bss->rsn_ie_len = 0;
+ bss->chan = chan;
+ }
+ __hostap_expire_bss(local);
+ spin_unlock(&local->lock);
+}
+
+
+static inline int
+hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, u16 type,
+ u16 stype)
+{
+ if (local->iw_mode == IW_MODE_MASTER) {
+ hostap_update_sta_ps(local, (struct ieee80211_hdr *)
+ skb->data);
+ }
+
+ if (local->hostapd && type == IEEE80211_FTYPE_MGMT) {
+ if (stype == IEEE80211_STYPE_BEACON &&
+ local->iw_mode == IW_MODE_MASTER) {
+ struct sk_buff *skb2;
+ /* Process beacon frames also in kernel driver to
+ * update STA(AP) table statistics */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2)
+ hostap_rx(skb2->dev, skb2, rx_stats);
+ }
+
+ /* send management frames to the user space daemon for
+ * processing */
+ local->apdevstats.rx_packets++;
+ local->apdevstats.rx_bytes += skb->len;
+ if (local->apdev == NULL)
+ return -1;
+ prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT);
+ return 0;
+ }
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ if (type != IEEE80211_FTYPE_MGMT &&
+ type != IEEE80211_FTYPE_CTL) {
+ printk(KERN_DEBUG "%s: unknown management frame "
+ "(type=0x%02x, stype=0x%02x) dropped\n",
+ skb->dev->name, type >> 2, stype >> 4);
+ return -1;
+ }
+
+ hostap_rx(skb->dev, skb, rx_stats);
+ return 0;
+ } else if (type == IEEE80211_FTYPE_MGMT &&
+ (stype == IEEE80211_STYPE_BEACON ||
+ stype == IEEE80211_STYPE_PROBE_RESP)) {
+ hostap_rx_sta_beacon(local, skb, stype);
+ return -1;
+ } else if (type == IEEE80211_FTYPE_MGMT &&
+ (stype == IEEE80211_STYPE_ASSOC_RESP ||
+ stype == IEEE80211_STYPE_REASSOC_RESP)) {
+ /* Ignore (Re)AssocResp silently since these are not currently
+ * needed but are still received when WPA/RSN mode is enabled.
+ */
+ return -1;
+ } else {
+ printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: dropped unhandled"
+ " management frame in non-Host AP mode (type=%d:%d)\n",
+ skb->dev->name, type >> 2, stype >> 4);
+ return -1;
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
+ u8 *addr)
+{
+ struct hostap_interface *iface = NULL;
+ struct list_head *ptr;
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_WDS &&
+ memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0)
+ break;
+ iface = NULL;
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ return iface ? iface->dev : NULL;
+}
+
+
+static inline int
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
+ u16 fc, struct net_device **wds)
+{
+ /* FIX: is this really supposed to accept WDS frames only in Master
+ * mode? What about Repeater or Managed with WDS frames? */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=
+ (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS) &&
+ (local->iw_mode != IW_MODE_MASTER || !(fc & IEEE80211_FCTL_TODS)))
+ return 0; /* not a WDS frame */
+
+ /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS)
+ * or own non-standard frame with 4th address after payload */
+ if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 &&
+ (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||
+ hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
+ hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
+ /* RA (or BSSID) is not ours - drop */
+ PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with "
+ "not own or broadcast %s=" MACSTR "\n",
+ local->dev->name,
+ fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
+ MAC2STR(hdr->addr1));
+ return -1;
+ }
+
+ /* check if the frame came from a registered WDS connection */
+ *wds = prism2_rx_get_wds(local, hdr->addr2);
+ if (*wds == NULL && fc & IEEE80211_FCTL_FROMDS &&
+ (local->iw_mode != IW_MODE_INFRA ||
+ !(local->wds_type & HOSTAP_WDS_AP_CLIENT) ||
+ memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) {
+ /* require that WDS link has been registered with TA or the
+ * frame is from current AP when using 'AP client mode' */
+ PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
+ "from unknown TA=" MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ if (local->ap && local->ap->autom_ap_wds)
+ hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
+ return -1;
+ }
+
+ if (*wds && !(fc & IEEE80211_FCTL_FROMDS) && local->ap &&
+ hostap_is_sta_assoc(local->ap, hdr->addr2)) {
+ /* STA is actually associated with us even though it has a
+ * registered WDS link. Assume it is in 'AP client' mode.
+ * Since this is a 3-addr frame, assume it is not (bogus) WDS
+ * frame and process it like any normal ToDS frame from
+ * associated STA. */
+ *wds = NULL;
+ }
+
+ return 0;
+}
+
+
+static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
+{
+ struct net_device *dev = local->dev;
+ u16 fc, ethertype;
+ struct ieee80211_hdr *hdr;
+ u8 *pos;
+
+ if (skb->len < 24)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* check that the frame is unicast frame to us */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
+ memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ /* ToDS frame with own addr BSSID and DA */
+ } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ /* FromDS frame with own addr as DA */
+ } else
+ return 0;
+
+ if (skb->len < 24 + 8)
+ return 0;
+
+ /* check for port access entity Ethernet type */
+ pos = skb->data + 24;
+ ethertype = (pos[6] << 8) | pos[7];
+ if (ethertype == ETH_P_PAE)
+ return 1;
+
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline int
+hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ if (local->tkip_countermeasures &&
+ strcmp(crypt->ops->name, "TKIP") == 0) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "received packet from " MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ }
+ return -1;
+ }
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: decryption failed (SA=" MACSTR
+ ") res=%d\n",
+ local->dev->name, MAC2STR(hdr->addr2), res);
+ local->comm_tallies.rx_discards_wep_undecryptable++;
+ return -1;
+ }
+
+ return res;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline int
+hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
+ int keyidx, struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
+ " (SA=" MACSTR " keyidx=%d)\n",
+ local->dev->name, MAC2STR(hdr->addr2), keyidx);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ). */
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr *hdr;
+ size_t hdrlen;
+ u16 fc, type, stype, sc;
+ struct net_device *wds = NULL;
+ struct net_device_stats *stats;
+ unsigned int frag;
+ u8 *payload;
+ struct sk_buff *skb2 = NULL;
+ u16 ethertype;
+ int frame_authorized = 0;
+ int from_assoc_ap = 0;
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ struct ieee80211_crypt_data *crypt = NULL;
+ void *sta = NULL;
+ int keyidx = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ iface->stats.rx_packets++;
+ iface->stats.rx_bytes += skb->len;
+
+ /* dev is the master radio device; change this to be the default
+ * virtual interface (this may be changed to WDS device below) */
+ dev = local->ddev;
+ iface = netdev_priv(dev);
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ stats = hostap_get_stats(dev);
+
+ if (skb->len < 10)
+ goto rx_dropped;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ /* Put this code here so that we avoid duplicating it in all
+ * Rx paths. - Jean II */
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ /* If spy monitoring on */
+ if (iface->spy_data.spy_number > 0) {
+ struct iw_quality wstats;
+ wstats.level = rx_stats->signal;
+ wstats.noise = rx_stats->noise;
+ wstats.updated = 6; /* No qual value */
+ /* Update spy records */
+ wireless_spy_update(dev, hdr->addr2, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+ hostap_update_rx_stats(local->ap, hdr, rx_stats);
+
+ if (local->iw_mode == IW_MODE_MONITOR) {
+ monitor_rx(dev, skb, rx_stats);
+ return;
+ }
+
+ if (local->host_decrypt) {
+ int idx = 0;
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+ crypt = local->crypt[idx];
+ sta = NULL;
+
+ /* Use station specific key to override default keys if the
+ * receiver address is a unicast address ("individual RA"). If
+ * bcrx_sta_key parameter is set, station specific key is used
+ * even with broad/multicast targets (this is against IEEE
+ * 802.11, but makes it easier to use different keys with
+ * stations that do not support WEP key mapping). */
+
+ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ (void) hostap_handle_sta_crypto(local, hdr, &crypt,
+ &sta);
+
+ /* allow NULL decrypt to indicate an station specific override
+ * for default encryption */
+ if (crypt && (crypt->ops == NULL ||
+ crypt->ops->decrypt_mpdu == NULL))
+ crypt = NULL;
+
+ if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
+#if 0
+ /* This seems to be triggered by some (multicast?)
+ * frames from other than current BSS, so just drop the
+ * frames silently instead of filling system log with
+ * these reports. */
+ printk(KERN_DEBUG "%s: WEP decryption failed (not set)"
+ " (SA=" MACSTR ")\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+#endif
+ local->comm_tallies.rx_discards_wep_undecryptable++;
+ goto rx_dropped;
+ }
+ }
+
+ if (type != IEEE80211_FTYPE_DATA) {
+ if (type == IEEE80211_FTYPE_MGMT &&
+ stype == IEEE80211_STYPE_AUTH &&
+ fc & IEEE80211_FCTL_PROTECTED && local->host_decrypt &&
+ (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
+ {
+ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
+ "from " MACSTR "\n", dev->name,
+ MAC2STR(hdr->addr2));
+ /* TODO: could inform hostapd about this so that it
+ * could send auth failure report */
+ goto rx_dropped;
+ }
+
+ if (hostap_rx_frame_mgmt(local, skb, rx_stats, type, stype))
+ goto rx_dropped;
+ else
+ goto rx_exit;
+ }
+
+ /* Data frame - extract src/dst addresses */
+ if (skb->len < IEEE80211_DATA_HDR3_LEN)
+ goto rx_dropped;
+
+ switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr3, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ if (skb->len < IEEE80211_DATA_HDR4_LEN)
+ goto rx_dropped;
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+ break;
+ case 0:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ }
+
+ if (hostap_rx_frame_wds(local, hdr, fc, &wds))
+ goto rx_dropped;
+ if (wds) {
+ skb->dev = dev = wds;
+ stats = hostap_get_stats(dev);
+ }
+
+ if (local->iw_mode == IW_MODE_MASTER && !wds &&
+ (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ local->stadev &&
+ memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) {
+ /* Frame from BSSID of the AP for which we are a client */
+ skb->dev = dev = local->stadev;
+ stats = hostap_get_stats(dev);
+ from_assoc_ap = 1;
+ }
+
+ dev->last_rx = jiffies;
+
+ if ((local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT) &&
+ !from_assoc_ap) {
+ switch (hostap_handle_sta_rx(local, dev, skb, rx_stats,
+ wds != NULL)) {
+ case AP_RX_CONTINUE_NOT_AUTHORIZED:
+ frame_authorized = 0;
+ break;
+ case AP_RX_CONTINUE:
+ frame_authorized = 1;
+ break;
+ case AP_RX_DROP:
+ goto rx_dropped;
+ case AP_RX_EXIT:
+ goto rx_exit;
+ }
+ }
+
+ /* Nullfunc frames may have PS-bit set, so they must be passed to
+ * hostap_handle_sta_rx() before being dropped here. */
+ if (stype != IEEE80211_STYPE_DATA &&
+ stype != IEEE80211_STYPE_DATA_CFACK &&
+ stype != IEEE80211_STYPE_DATA_CFPOLL &&
+ stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
+ if (stype != IEEE80211_STYPE_NULLFUNC)
+ printk(KERN_DEBUG "%s: RX: dropped data frame "
+ "with no data (type=0x%02x, subtype=0x%02x)\n",
+ dev->name, type >> 2, stype >> 4);
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
+ goto rx_dropped;
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ /* skb: hdr + (possibly fragmented) plaintext payload */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ (frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
+ int flen;
+ struct sk_buff *frag_skb =
+ prism2_frag_cache_get(local, hdr);
+ if (!frag_skb) {
+ printk(KERN_DEBUG "%s: Rx cannot get skb from "
+ "fragment cache (morefrag=%d seq=%u frag=%u)\n",
+ dev->name, (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
+ WLAN_GET_SEQ_SEQ(sc) >> 4, frag);
+ goto rx_dropped;
+ }
+
+ flen = skb->len;
+ if (frag != 0)
+ flen -= hdrlen;
+
+ if (frag_skb->tail + flen > frag_skb->end) {
+ printk(KERN_WARNING "%s: host decrypted and "
+ "reassembled frame did not fit skb\n",
+ dev->name);
+ prism2_frag_cache_invalidate(local, hdr);
+ goto rx_dropped;
+ }
+
+ if (frag == 0) {
+ /* copy first fragment (including full headers) into
+ * beginning of the fragment cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data, flen);
+ } else {
+ /* append frame payload to the end of the fragment
+ * cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+ flen);
+ }
+ dev_kfree_skb(skb);
+ skb = NULL;
+
+ if (fc & IEEE80211_FCTL_MOREFRAGS) {
+ /* more fragments expected - leave the skb in fragment
+ * cache for now; it will be delivered to upper layers
+ * after all fragments have been received */
+ goto rx_exit;
+ }
+
+ /* this was the last fragment and the frame will be
+ * delivered, so remove skb from fragment cache */
+ skb = frag_skb;
+ hdr = (struct ieee80211_hdr *) skb->data;
+ prism2_frag_cache_invalidate(local, hdr);
+ }
+
+ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+ * encrypted/authenticated */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
+ if (local->ieee_802_1x &&
+ hostap_is_eapol_frame(local, skb)) {
+ /* pass unencrypted EAPOL frames even if encryption is
+ * configured */
+ PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X - passing "
+ "unencrypted EAPOL frame\n", local->dev->name);
+ } else {
+ printk(KERN_DEBUG "%s: encryption configured, but RX "
+ "frame not encrypted (SA=" MACSTR ")\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ goto rx_dropped;
+ }
+ }
+
+ if (local->drop_unencrypted && !(fc & IEEE80211_FCTL_PROTECTED) &&
+ !hostap_is_eapol_frame(local, skb)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: dropped unencrypted RX data "
+ "frame from " MACSTR " (drop_unencrypted=1)\n",
+ dev->name, MAC2STR(hdr->addr2));
+ }
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possible reassembled) full plaintext payload */
+
+ payload = skb->data + hdrlen;
+ ethertype = (payload[6] << 8) | payload[7];
+
+ /* If IEEE 802.1X is used, check whether the port is authorized to send
+ * the received frame. */
+ if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) {
+ if (ethertype == ETH_P_PAE) {
+ PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X frame\n",
+ dev->name);
+ if (local->hostapd && local->apdev) {
+ /* Send IEEE 802.1X frames to the user
+ * space daemon for processing */
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_MGMT);
+ local->apdevstats.rx_packets++;
+ local->apdevstats.rx_bytes += skb->len;
+ goto rx_exit;
+ }
+ } else if (!frame_authorized) {
+ printk(KERN_DEBUG "%s: dropped frame from "
+ "unauthorized port (IEEE 802.1X): "
+ "ethertype=0x%04x\n",
+ dev->name, ethertype);
+ goto rx_dropped;
+ }
+ }
+
+ /* convert hdr + possible LLC headers into Ethernet header */
+ if (skb->len - hdrlen >= 8 &&
+ ((memcmp(payload, rfc1042_header, 6) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(payload, bridge_tunnel_header, 6) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+ * replace EtherType */
+ skb_pull(skb, hdrlen + 6);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ u16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ skb_pull(skb, hdrlen);
+ len = htons(skb->len);
+ memcpy(skb_push(skb, 2), &len, 2);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ }
+
+ if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS) &&
+ skb->len >= ETH_HLEN + ETH_ALEN) {
+ /* Non-standard frame: get addr4 from its bogus location after
+ * the payload */
+ memcpy(skb->data + ETH_ALEN,
+ skb->data + skb->len - ETH_ALEN, ETH_ALEN);
+ skb_trim(skb, skb->len - ETH_ALEN);
+ }
+
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+
+ if (local->iw_mode == IW_MODE_MASTER && !wds &&
+ local->ap->bridge_packets) {
+ if (dst[0] & 0x01) {
+ /* copy multicast frame both to the higher layers and
+ * to the wireless media */
+ local->ap->bridged_multicast++;
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ printk(KERN_DEBUG "%s: skb_clone failed for "
+ "multicast frame\n", dev->name);
+ } else if (hostap_is_sta_authorized(local->ap, dst)) {
+ /* send frame directly to the associated STA using
+ * wireless media and not passing to higher layers */
+ local->ap->bridged_unicast++;
+ skb2 = skb;
+ skb = NULL;
+ }
+ }
+
+ if (skb2 != NULL) {
+ /* send to wireless media */
+ skb2->protocol = __constant_htons(ETH_P_802_3);
+ skb2->mac.raw = skb2->nh.raw = skb2->data;
+ /* skb2->nh.raw = skb2->data + ETH_HLEN; */
+ skb2->dev = dev;
+ dev_queue_xmit(skb2);
+ }
+
+ if (skb) {
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->dev = dev;
+ netif_rx(skb);
+ }
+
+ rx_exit:
+ if (sta)
+ hostap_handle_sta_release(sta);
+ return;
+
+ rx_dropped:
+ dev_kfree_skb(skb);
+
+ stats->rx_dropped++;
+ goto rx_exit;
+}
+
+
+EXPORT_SYMBOL(hostap_80211_rx);
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
new file mode 100644
index 000000000000..6358015f6526
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -0,0 +1,524 @@
+void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+ u16 fc;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
+ name, skb->len, jiffies);
+
+ if (skb->len < 2)
+ return;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ printk("\n");
+ return;
+ }
+
+ printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
+ le16_to_cpu(hdr->seq_ctl));
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
+ if (skb->len >= 30)
+ printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
+ printk("\n");
+}
+
+
+/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta)
+ * Convert Ethernet header into a suitable IEEE 802.11 header depending on
+ * device configuration. */
+int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int need_headroom, need_tailroom = 0;
+ struct ieee80211_hdr hdr;
+ u16 fc, ethertype = 0;
+ enum {
+ WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
+ } use_wds = WDS_NO;
+ u8 *encaps_data;
+ int hdr_len, encaps_len, skip_header_bytes;
+ int to_assoc_ap = 0;
+ struct hostap_skb_tx_data *meta;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < ETH_HLEN) {
+ printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ kfree_skb(skb);
+ return 0;
+ }
+
+ if (local->ddev != dev) {
+ use_wds = (local->iw_mode == IW_MODE_MASTER &&
+ !(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ?
+ WDS_OWN_FRAME : WDS_COMPLIANT_FRAME;
+ if (dev == local->stadev) {
+ to_assoc_ap = 1;
+ use_wds = WDS_NO;
+ } else if (dev == local->apdev) {
+ printk(KERN_DEBUG "%s: prism2_tx: trying to use "
+ "AP device with Ethernet net dev\n", dev->name);
+ kfree_skb(skb);
+ return 0;
+ }
+ } else {
+ if (local->iw_mode == IW_MODE_REPEAT) {
+ printk(KERN_DEBUG "%s: prism2_tx: trying to use "
+ "non-WDS link in Repeater mode\n", dev->name);
+ kfree_skb(skb);
+ return 0;
+ } else if (local->iw_mode == IW_MODE_INFRA &&
+ (local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
+ memcmp(skb->data + ETH_ALEN, dev->dev_addr,
+ ETH_ALEN) != 0) {
+ /* AP client mode: send frames with foreign src addr
+ * using 4-addr WDS frames */
+ use_wds = WDS_COMPLIANT_FRAME;
+ }
+ }
+
+ /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload
+ * ==>
+ * Prism2 TX frame with 802.11 header:
+ * txdesc (address order depending on used mode; includes dst_addr and
+ * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel;
+ * proto[2], payload {, possible addr4[6]} */
+
+ ethertype = (skb->data[12] << 8) | skb->data[13];
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ /* Length of data after IEEE 802.11 header */
+ encaps_data = NULL;
+ encaps_len = 0;
+ skip_header_bytes = ETH_HLEN;
+ if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
+ encaps_data = bridge_tunnel_header;
+ encaps_len = sizeof(bridge_tunnel_header);
+ skip_header_bytes -= 2;
+ } else if (ethertype >= 0x600) {
+ encaps_data = rfc1042_header;
+ encaps_len = sizeof(rfc1042_header);
+ skip_header_bytes -= 2;
+ }
+
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+ hdr_len = IEEE80211_DATA_HDR3_LEN;
+
+ if (use_wds != WDS_NO) {
+ /* Note! Prism2 station firmware has problems with sending real
+ * 802.11 frames with four addresses; until these problems can
+ * be fixed or worked around, 4-addr frames needed for WDS are
+ * using incompatible format: FromDS flag is not set and the
+ * fourth address is added after the frame payload; it is
+ * assumed, that the receiving station knows how to handle this
+ * frame format */
+
+ if (use_wds == WDS_COMPLIANT_FRAME) {
+ fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
+ /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA,
+ * Addr4 = SA */
+ memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ hdr_len += ETH_ALEN;
+ } else {
+ /* bogus 4-addr format to workaround Prism2 station
+ * f/w bug */
+ fc |= IEEE80211_FCTL_TODS;
+ /* From DS: Addr1 = DA (used as RA),
+ * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA),
+ */
+
+ /* SA from skb->data + ETH_ALEN will be added after
+ * frame payload; use hdr.addr4 as a temporary buffer
+ */
+ memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ need_tailroom += ETH_ALEN;
+ }
+
+ /* send broadcast and multicast frames to broadcast RA, if
+ * configured; otherwise, use unicast RA of the WDS link */
+ if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) &&
+ skb->data[0] & 0x01)
+ memset(&hdr.addr1, 0xff, ETH_ALEN);
+ else if (iface->type == HOSTAP_INTERFACE_WDS)
+ memcpy(&hdr.addr1, iface->u.wds.remote_addr,
+ ETH_ALEN);
+ else
+ memcpy(&hdr.addr1, local->bssid, ETH_ALEN);
+ memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) {
+ fc |= IEEE80211_FCTL_FROMDS;
+ /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */
+ memcpy(&hdr.addr1, skb->data, ETH_ALEN);
+ memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) {
+ fc |= IEEE80211_FCTL_TODS;
+ /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
+ memcpy(&hdr.addr1, to_assoc_ap ?
+ local->assoc_ap_addr : local->bssid, ETH_ALEN);
+ memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
+ memcpy(&hdr.addr1, skb->data, ETH_ALEN);
+ memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+ memcpy(&hdr.addr3, local->bssid, ETH_ALEN);
+ }
+
+ hdr.frame_ctl = cpu_to_le16(fc);
+
+ skb_pull(skb, skip_header_bytes);
+ need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len;
+ if (skb_tailroom(skb) < need_tailroom) {
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ if (pskb_expand_head(skb, need_headroom, need_tailroom,
+ GFP_ATOMIC)) {
+ kfree_skb(skb);
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ } else if (skb_headroom(skb) < need_headroom) {
+ struct sk_buff *tmp = skb;
+ skb = skb_realloc_headroom(skb, need_headroom);
+ kfree_skb(tmp);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ } else {
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ }
+
+ if (encaps_data)
+ memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
+ memcpy(skb_push(skb, hdr_len), &hdr, hdr_len);
+ if (use_wds == WDS_OWN_FRAME) {
+ memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN);
+ }
+
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+
+ skb->mac.raw = skb->data;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ if (use_wds)
+ meta->flags |= HOSTAP_TX_FLAGS_WDS;
+ meta->ethertype = ethertype;
+ meta->iface = iface;
+
+ /* Send IEEE 802.11 encapsulated frame using the master radio device */
+ skb->dev = local->dev;
+ dev_queue_xmit(skb);
+ return 0;
+}
+
+
+/* hard_start_xmit function for hostapd wlan#ap interfaces */
+int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hostap_skb_tx_data *meta;
+ struct ieee80211_hdr *hdr;
+ u16 fc;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < 10) {
+ printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ kfree_skb(skb);
+ return 0;
+ }
+
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = iface;
+
+ if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
+ u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +
+ sizeof(rfc1042_header)];
+ meta->ethertype = (pos[0] << 8) | pos[1];
+ }
+ }
+
+ /* Send IEEE 802.11 encapsulated frame using the master radio device */
+ skb->dev = local->dev;
+ dev_queue_xmit(skb);
+ return 0;
+}
+
+
+/* Called only from software IRQ */
+struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr *hdr;
+ u16 fc;
+ int hdr_len, res;
+
+ iface = netdev_priv(skb->dev);
+ local = iface->local;
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ if (local->tkip_countermeasures &&
+ crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "TX packet to " MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr1));
+ }
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
+ skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
+ pskb_expand_head(skb, crypt->ops->extra_prefix_len,
+ crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hdr_len = hostap_80211_get_hdrlen(fc);
+
+ /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+ * call both MSDU and MPDU encryption functions from here. */
+ atomic_inc(&crypt->refcnt);
+ res = 0;
+ if (crypt->ops->encrypt_msdu)
+ res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv);
+ if (res == 0 && crypt->ops->encrypt_mpdu)
+ res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ return skb;
+}
+
+
+/* hard_start_xmit function for master radio interface wifi#.
+ * AP processing (TX rate control, power save buffering, etc.).
+ * Use hardware TX function to send the frame. */
+int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 1;
+ u16 fc;
+ struct hostap_tx_data tx;
+ ap_tx_ret tx_ret;
+ struct hostap_skb_tx_data *meta;
+ int no_encrypt = 0;
+ struct ieee80211_hdr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ tx.skb = skb;
+ tx.sta_ptr = NULL;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
+ printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
+ "expected 0x%08x)\n",
+ dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+
+ if (local->host_encrypt) {
+ /* Set crypt to default algorithm and key; will be replaced in
+ * AP code if STA has own alg/key */
+ tx.crypt = local->crypt[local->tx_keyidx];
+ tx.host_encrypt = 1;
+ } else {
+ tx.crypt = NULL;
+ tx.host_encrypt = 0;
+ }
+
+ if (skb->len < 24) {
+ printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+
+ /* FIX (?):
+ * Wi-Fi 802.11b test plan suggests that AP should ignore power save
+ * bit in authentication and (re)association frames and assume tha
+ * STA remains awake for the response. */
+ tx_ret = hostap_handle_sta_tx(local, &tx);
+ skb = tx.skb;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ switch (tx_ret) {
+ case AP_TX_CONTINUE:
+ break;
+ case AP_TX_CONTINUE_NOT_AUTHORIZED:
+ if (local->ieee_802_1x &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ meta->ethertype != ETH_P_PAE &&
+ !(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
+ printk(KERN_DEBUG "%s: dropped frame to unauthorized "
+ "port (IEEE 802.1X): ethertype=0x%04x\n",
+ dev->name, meta->ethertype);
+ hostap_dump_tx_80211(dev->name, skb);
+
+ ret = 0; /* drop packet */
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+ break;
+ case AP_TX_DROP:
+ ret = 0; /* drop packet */
+ iface->stats.tx_dropped++;
+ goto fail;
+ case AP_TX_RETRY:
+ goto fail;
+ case AP_TX_BUFFERED:
+ /* do not free skb here, it will be freed when the
+ * buffered frame is sent/timed out */
+ ret = 0;
+ goto tx_exit;
+ }
+
+ /* Request TX callback if protocol version is 2 in 802.11 header;
+ * this version 2 is a special case used between hostapd and kernel
+ * driver */
+ if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) &&
+ local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) {
+ meta->tx_cb_idx = local->ap->tx_callback_idx;
+
+ /* remove special version from the frame header */
+ fc &= ~IEEE80211_FCTL_VERS;
+ hdr->frame_ctl = cpu_to_le16(fc);
+ }
+
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) {
+ no_encrypt = 1;
+ tx.crypt = NULL;
+ }
+
+ if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
+ !(fc & IEEE80211_FCTL_VERS)) {
+ no_encrypt = 1;
+ PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
+ "unencrypted EAPOL frame\n", dev->name);
+ tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */
+ }
+
+ if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
+ tx.crypt = NULL;
+ else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {
+ /* Add ISWEP flag both for firmware and host based encryption
+ */
+ fc |= IEEE80211_FCTL_PROTECTED;
+ hdr->frame_ctl = cpu_to_le16(fc);
+ } else if (local->drop_unencrypted &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ meta->ethertype != ETH_P_PAE) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: dropped unencrypted TX data "
+ "frame (drop_unencrypted=1)\n", dev->name);
+ }
+ iface->stats.tx_dropped++;
+ ret = 0;
+ goto fail;
+ }
+
+ if (tx.crypt) {
+ skb = hostap_tx_encrypt(skb, tx.crypt);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: TX - encryption failed\n",
+ dev->name);
+ ret = 0;
+ goto fail;
+ }
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
+ printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
+ "expected 0x%08x) after hostap_tx_encrypt\n",
+ dev->name, meta->magic,
+ HOSTAP_SKB_TX_DATA_MAGIC);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+ }
+
+ if (local->func->tx == NULL || local->func->tx(skb, dev)) {
+ ret = 0;
+ iface->stats.tx_dropped++;
+ } else {
+ ret = 0;
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+ }
+
+ fail:
+ if (!ret && skb)
+ dev_kfree_skb(skb);
+ tx_exit:
+ if (tx.sta_ptr)
+ hostap_handle_sta_release(tx.sta_ptr);
+ return ret;
+}
+
+
+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_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
new file mode 100644
index 000000000000..930cef8367f2
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -0,0 +1,3288 @@
+/*
+ * Intersil Prism2 driver with Host AP (software access point) support
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This file is to be included into hostap.c when S/W AP functionality is
+ * compiled.
+ *
+ * AP: FIX:
+ * - if unicast Class 2 (assoc,reassoc,disassoc) frame received from
+ * unauthenticated STA, send deauth. frame (8802.11: 5.5)
+ * - if unicast Class 3 (data with to/from DS,deauth,pspoll) frame received
+ * from authenticated, but unassoc STA, send disassoc frame (8802.11: 5.5)
+ * - if unicast Class 3 received from unauthenticated STA, send deauth. frame
+ * (8802.11: 5.5)
+ */
+
+static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
+ DEF_INTS };
+module_param_array(other_ap_policy, int, NULL, 0444);
+MODULE_PARM_DESC(other_ap_policy, "Other AP beacon monitoring policy (0-3)");
+
+static int ap_max_inactivity[MAX_PARM_DEVICES] = { AP_MAX_INACTIVITY_SEC,
+ DEF_INTS };
+module_param_array(ap_max_inactivity, int, NULL, 0444);
+MODULE_PARM_DESC(ap_max_inactivity, "AP timeout (in seconds) for station "
+ "inactivity");
+
+static int ap_bridge_packets[MAX_PARM_DEVICES] = { 1, DEF_INTS };
+module_param_array(ap_bridge_packets, int, NULL, 0444);
+MODULE_PARM_DESC(ap_bridge_packets, "Bridge packets directly between "
+ "stations");
+
+static int autom_ap_wds[MAX_PARM_DEVICES] = { 0, DEF_INTS };
+module_param_array(autom_ap_wds, int, NULL, 0444);
+MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs "
+ "automatically");
+
+
+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta);
+static void hostap_event_expired_sta(struct net_device *dev,
+ struct sta_info *sta);
+static void handle_add_proc_queue(void *data);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static void handle_wds_oper_queue(void *data);
+static void prism2_send_mgmt(struct net_device *dev,
+ u16 type_subtype, char *body,
+ int body_len, u8 *addr, u16 tx_cb_idx);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int ap_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast);
+ p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast);
+ p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ);
+ p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets);
+ p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack);
+ p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds);
+ p += sprintf(p, "auth_algs=%u\n", ap->local->auth_algs);
+ p += sprintf(p, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc);
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta)
+{
+ sta->hnext = ap->sta_hash[STA_HASH(sta->addr)];
+ ap->sta_hash[STA_HASH(sta->addr)] = sta;
+}
+
+static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
+{
+ struct sta_info *s;
+
+ s = ap->sta_hash[STA_HASH(sta->addr)];
+ if (s == NULL) return;
+ if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+ ap->sta_hash[STA_HASH(sta->addr)] = s->hnext;
+ return;
+ }
+
+ while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, ETH_ALEN)
+ != 0)
+ s = s->hnext;
+ if (s->hnext != NULL)
+ s->hnext = s->hnext->hnext;
+ else
+ printk("AP: could not remove STA " MACSTR " from hash table\n",
+ MAC2STR(sta->addr));
+}
+
+static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
+{
+ if (sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+
+ if (ap->proc != NULL) {
+ char name[20];
+ sprintf(name, MACSTR, MAC2STR(sta->addr));
+ remove_proc_entry(name, ap->proc);
+ }
+
+ if (sta->crypt) {
+ sta->crypt->ops->deinit(sta->crypt->priv);
+ kfree(sta->crypt);
+ sta->crypt = NULL;
+ }
+
+ skb_queue_purge(&sta->tx_buf);
+
+ ap->num_sta--;
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->aid > 0)
+ ap->sta_aid[sta->aid - 1] = NULL;
+
+ if (!sta->ap && sta->u.sta.challenge)
+ kfree(sta->u.sta.challenge);
+ del_timer(&sta->timer);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ kfree(sta);
+}
+
+
+static void hostap_set_tim(local_info_t *local, int aid, int set)
+{
+ if (local->func->set_tim)
+ local->func->set_tim(local->dev, aid, set);
+}
+
+
+static void hostap_event_new_sta(struct net_device *dev, struct sta_info *sta)
+{
+ union iwreq_data wrqu;
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVREGISTERED, &wrqu, NULL);
+}
+
+
+static void hostap_event_expired_sta(struct net_device *dev,
+ struct sta_info *sta)
+{
+ union iwreq_data wrqu;
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVEXPIRED, &wrqu, NULL);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void ap_handle_timer(unsigned long data)
+{
+ struct sta_info *sta = (struct sta_info *) data;
+ local_info_t *local;
+ struct ap_data *ap;
+ unsigned long next_time = 0;
+ int was_assoc;
+
+ if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) {
+ PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n");
+ return;
+ }
+
+ local = sta->local;
+ ap = local->ap;
+ was_assoc = sta->flags & WLAN_STA_ASSOC;
+
+ if (atomic_read(&sta->users) != 0)
+ next_time = jiffies + HZ;
+ else if ((sta->flags & WLAN_STA_PERM) && !(sta->flags & WLAN_STA_AUTH))
+ next_time = jiffies + ap->max_inactivity;
+
+ if (time_before(jiffies, sta->last_rx + ap->max_inactivity)) {
+ /* station activity detected; reset timeout state */
+ sta->timeout_next = STA_NULLFUNC;
+ next_time = sta->last_rx + ap->max_inactivity;
+ } else if (sta->timeout_next == STA_DISASSOC &&
+ !(sta->flags & WLAN_STA_PENDING_POLL)) {
+ /* STA ACKed data nullfunc frame poll */
+ sta->timeout_next = STA_NULLFUNC;
+ next_time = jiffies + ap->max_inactivity;
+ }
+
+ if (next_time) {
+ sta->timer.expires = next_time;
+ add_timer(&sta->timer);
+ return;
+ }
+
+ if (sta->ap)
+ sta->timeout_next = STA_DEAUTH;
+
+ if (sta->timeout_next == STA_DEAUTH && !(sta->flags & WLAN_STA_PERM)) {
+ spin_lock(&ap->sta_table_lock);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ spin_unlock(&ap->sta_table_lock);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ } else if (sta->timeout_next == STA_DISASSOC)
+ sta->flags &= ~WLAN_STA_ASSOC;
+
+ if (was_assoc && !(sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+
+ if (sta->timeout_next == STA_DEAUTH && sta->aid > 0 &&
+ !skb_queue_empty(&sta->tx_buf)) {
+ hostap_set_tim(local, sta->aid, 0);
+ sta->flags &= ~WLAN_STA_TIM;
+ }
+
+ if (sta->ap) {
+ if (ap->autom_ap_wds) {
+ PDEBUG(DEBUG_AP, "%s: removing automatic WDS "
+ "connection to AP " MACSTR "\n",
+ local->dev->name, MAC2STR(sta->addr));
+ hostap_wds_link_oper(local, sta->addr, WDS_DEL);
+ }
+ } else if (sta->timeout_next == STA_NULLFUNC) {
+ /* send data frame to poll STA and check whether this frame
+ * is ACKed */
+ /* FIX: IEEE80211_STYPE_NULLFUNC would be more appropriate, but
+ * it is apparently not retried so TX Exc events are not
+ * received for it */
+ sta->flags |= WLAN_STA_PENDING_POLL;
+ prism2_send_mgmt(local->dev, IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_DATA, NULL, 0,
+ sta->addr, ap->tx_callback_poll);
+ } else {
+ int deauth = sta->timeout_next == STA_DEAUTH;
+ u16 resp;
+ PDEBUG(DEBUG_AP, "%s: sending %s info to STA " MACSTR
+ "(last=%lu, jiffies=%lu)\n",
+ local->dev->name,
+ deauth ? "deauthentication" : "disassociation",
+ MAC2STR(sta->addr), sta->last_rx, jiffies);
+
+ resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID :
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
+ prism2_send_mgmt(local->dev, IEEE80211_FTYPE_MGMT |
+ (deauth ? IEEE80211_STYPE_DEAUTH :
+ IEEE80211_STYPE_DISASSOC),
+ (char *) &resp, 2, sta->addr, 0);
+ }
+
+ if (sta->timeout_next == STA_DEAUTH) {
+ if (sta->flags & WLAN_STA_PERM) {
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " would have been "
+ "removed, but it has 'perm' flag\n",
+ local->dev->name, MAC2STR(sta->addr));
+ } else
+ ap_free_sta(ap, sta);
+ return;
+ }
+
+ if (sta->timeout_next == STA_NULLFUNC) {
+ sta->timeout_next = STA_DISASSOC;
+ sta->timer.expires = jiffies + AP_DISASSOC_DELAY;
+ } else {
+ sta->timeout_next = STA_DEAUTH;
+ sta->timer.expires = jiffies + AP_DEAUTH_DELAY;
+ }
+
+ add_timer(&sta->timer);
+}
+
+
+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
+ int resend)
+{
+ u8 addr[ETH_ALEN];
+ u16 resp;
+ int i;
+
+ PDEBUG(DEBUG_AP, "%s: Deauthenticate all stations\n", dev->name);
+ memset(addr, 0xff, ETH_ALEN);
+
+ resp = __constant_cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+ /* deauth message sent; try to resend it few times; the message is
+ * broadcast, so it may be delayed until next DTIM; there is not much
+ * else we can do at this point since the driver is going to be shut
+ * down */
+ for (i = 0; i < 5; i++) {
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_DEAUTH,
+ (char *) &resp, 2, addr, 0);
+
+ if (!resend || ap->num_sta <= 0)
+ return;
+
+ mdelay(50);
+ }
+}
+
+
+static int ap_control_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+ char *policy_txt;
+ struct list_head *ptr;
+ struct mac_entry *entry;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ switch (ap->mac_restrictions.policy) {
+ case MAC_POLICY_OPEN:
+ policy_txt = "open";
+ break;
+ case MAC_POLICY_ALLOW:
+ policy_txt = "allow";
+ break;
+ case MAC_POLICY_DENY:
+ policy_txt = "deny";
+ break;
+ default:
+ policy_txt = "unknown";
+ break;
+ };
+ p += sprintf(p, "MAC policy: %s\n", policy_txt);
+ p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
+ p += sprintf(p, "MAC list:\n");
+ spin_lock_bh(&ap->mac_restrictions.lock);
+ for (ptr = ap->mac_restrictions.mac_list.next;
+ ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+ if (p - page > PAGE_SIZE - 80) {
+ p += sprintf(p, "All entries did not fit one page.\n");
+ break;
+ }
+
+ entry = list_entry(ptr, struct mac_entry, list);
+ p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
+ }
+ spin_unlock_bh(&ap->mac_restrictions.lock);
+
+ return (p - page);
+}
+
+
+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct mac_entry *entry;
+
+ entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL);
+ if (entry == NULL)
+ return -1;
+
+ memcpy(entry->addr, mac, ETH_ALEN);
+
+ spin_lock_bh(&mac_restrictions->lock);
+ list_add_tail(&entry->list, &mac_restrictions->mac_list);
+ mac_restrictions->entries++;
+ spin_unlock_bh(&mac_restrictions->lock);
+
+ return 0;
+}
+
+
+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct list_head *ptr;
+ struct mac_entry *entry;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next;
+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+
+ if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+ list_del(ptr);
+ kfree(entry);
+ mac_restrictions->entries--;
+ spin_unlock_bh(&mac_restrictions->lock);
+ return 0;
+ }
+ }
+ spin_unlock_bh(&mac_restrictions->lock);
+ return -1;
+}
+
+
+static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct list_head *ptr;
+ struct mac_entry *entry;
+ int found = 0;
+
+ if (mac_restrictions->policy == MAC_POLICY_OPEN)
+ return 0;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next;
+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+
+ if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_bh(&mac_restrictions->lock);
+
+ if (mac_restrictions->policy == MAC_POLICY_ALLOW)
+ return !found;
+ else
+ return found;
+}
+
+
+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+{
+ struct list_head *ptr, *n;
+ struct mac_entry *entry;
+
+ if (mac_restrictions->entries == 0)
+ return;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next, n = ptr->next;
+ ptr != &mac_restrictions->mac_list;
+ ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+ list_del(ptr);
+ kfree(entry);
+ }
+ mac_restrictions->entries = 0;
+ spin_unlock_bh(&mac_restrictions->lock);
+}
+
+
+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
+ u8 *mac)
+{
+ struct sta_info *sta;
+ u16 resp;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, mac);
+ if (sta) {
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -EINVAL;
+
+ resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH,
+ (char *) &resp, 2, sta->addr, 0);
+
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(dev, sta);
+
+ ap_free_sta(ap, sta);
+
+ return 0;
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static void ap_control_kickall(struct ap_data *ap)
+{
+ struct list_head *ptr, *n;
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list;
+ ptr = n, n = ptr->next) {
+ sta = list_entry(ptr, struct sta_info, list);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+#define PROC_LIMIT (PAGE_SIZE - 80)
+
+static int prism2_ap_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+ struct list_head *ptr;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ if (!sta->ap)
+ continue;
+
+ p += sprintf(p, MACSTR " %d %d %d %d '", MAC2STR(sta->addr),
+ sta->u.ap.channel, sta->last_rx_signal,
+ sta->last_rx_silence, sta->last_rx_rate);
+ for (i = 0; i < sta->u.ap.ssid_len; i++)
+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
+ sta->u.ap.ssid[i] < 127) ?
+ "%c" : "<%02x>"),
+ sta->u.ap.ssid[i]);
+ p += sprintf(p, "'");
+ if (sta->capability & WLAN_CAPABILITY_ESS)
+ p += sprintf(p, " [ESS]");
+ if (sta->capability & WLAN_CAPABILITY_IBSS)
+ p += sprintf(p, " [IBSS]");
+ if (sta->capability & WLAN_CAPABILITY_PRIVACY)
+ p += sprintf(p, " [WEP]");
+ p += sprintf(p, "\n");
+
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "hostap: ap proc did not fit\n");
+ break;
+ }
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver)
+{
+ if (!ap)
+ return;
+
+ if (sta_fw_ver == PRISM2_FW_VER(0,8,0)) {
+ PDEBUG(DEBUG_AP, "Using data::nullfunc ACK workaround - "
+ "firmware upgrade recommended\n");
+ ap->nullfunc_ack = 1;
+ } else
+ ap->nullfunc_ack = 0;
+
+ if (sta_fw_ver == PRISM2_FW_VER(1,4,2)) {
+ printk(KERN_WARNING "%s: Warning: secondary station firmware "
+ "version 1.4.2 does not seem to work in Host AP mode\n",
+ ap->local->dev->name);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ u16 fc;
+ struct ieee80211_hdr *hdr;
+
+ if (!ap->local->hostapd || !ap->local->apdev) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* Pass the TX callback frame to the hostapd; use 802.11 header version
+ * 1 to indicate failure (no ACK) and 2 success (frame ACKed) */
+
+ fc &= ~IEEE80211_FCTL_VERS;
+ fc |= ok ? BIT(1) : BIT(0);
+ hdr->frame_ctl = cpu_to_le16(fc);
+
+ skb->dev = ap->local->apdev;
+ skb_pull(skb, hostap_80211_get_hdrlen(fc));
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = __constant_htons(ETH_P_802_2);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct net_device *dev = ap->local->dev;
+ struct ieee80211_hdr *hdr;
+ u16 fc, *pos, auth_alg, auth_transaction, status;
+ struct sta_info *sta = NULL;
+ char *txt = NULL;
+
+ if (ap->local->hostapd) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
+ skb->len < IEEE80211_MGMT_HDR_LEN + 6) {
+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid "
+ "frame\n", dev->name);
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ auth_alg = le16_to_cpu(*pos++);
+ auth_transaction = le16_to_cpu(*pos++);
+ status = le16_to_cpu(*pos++);
+
+ if (!ok) {
+ txt = "frame was not ACKed";
+ goto done;
+ }
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&ap->sta_table_lock);
+
+ if (!sta) {
+ txt = "STA not found";
+ goto done;
+ }
+
+ if (status == WLAN_STATUS_SUCCESS &&
+ ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
+ (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
+ txt = "STA authenticated";
+ sta->flags |= WLAN_STA_AUTH;
+ sta->last_auth = jiffies;
+ } else if (status != WLAN_STATUS_SUCCESS)
+ txt = "authentication failed";
+
+ done:
+ if (sta)
+ atomic_dec(&sta->users);
+ if (txt) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth_cb - alg=%d trans#=%d "
+ "status=%d - %s\n",
+ dev->name, MAC2STR(hdr->addr1), auth_alg,
+ auth_transaction, status, txt);
+ }
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct net_device *dev = ap->local->dev;
+ struct ieee80211_hdr *hdr;
+ u16 fc, *pos, status;
+ struct sta_info *sta = NULL;
+ char *txt = NULL;
+
+ if (ap->local->hostapd) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
+ WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_REASSOC_RESP) ||
+ skb->len < IEEE80211_MGMT_HDR_LEN + 4) {
+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid "
+ "frame\n", dev->name);
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (!ok) {
+ txt = "frame was not ACKed";
+ goto done;
+ }
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&ap->sta_table_lock);
+
+ if (!sta) {
+ txt = "STA not found";
+ goto done;
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos++;
+ status = le16_to_cpu(*pos++);
+ if (status == WLAN_STATUS_SUCCESS) {
+ if (!(sta->flags & WLAN_STA_ASSOC))
+ hostap_event_new_sta(dev, sta);
+ txt = "STA associated";
+ sta->flags |= WLAN_STA_ASSOC;
+ sta->last_assoc = jiffies;
+ } else
+ txt = "association failed";
+
+ done:
+ if (sta)
+ atomic_dec(&sta->users);
+ if (txt) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " assoc_cb - %s\n",
+ dev->name, MAC2STR(hdr->addr1), txt);
+ }
+ dev_kfree_skb(skb);
+}
+
+/* Called only as a tasklet (software IRQ); TX callback for poll frames used
+ * in verifying whether the STA is still present. */
+static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct ieee80211_hdr *hdr;
+ struct sta_info *sta;
+
+ if (skb->len < 24)
+ goto fail;
+ hdr = (struct ieee80211_hdr *) skb->data;
+ if (ok) {
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+ spin_unlock(&ap->sta_table_lock);
+ } else {
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " did not ACK activity "
+ "poll frame\n", ap->local->dev->name,
+ MAC2STR(hdr->addr1));
+ }
+
+ fail:
+ dev_kfree_skb(skb);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+void hostap_init_data(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+
+ if (ap == NULL) {
+ printk(KERN_WARNING "hostap_init_data: ap == NULL\n");
+ return;
+ }
+ memset(ap, 0, sizeof(struct ap_data));
+ ap->local = local;
+
+ ap->ap_policy = GET_INT_PARM(other_ap_policy, local->card_idx);
+ ap->bridge_packets = GET_INT_PARM(ap_bridge_packets, local->card_idx);
+ ap->max_inactivity =
+ GET_INT_PARM(ap_max_inactivity, local->card_idx) * HZ;
+ ap->autom_ap_wds = GET_INT_PARM(autom_ap_wds, local->card_idx);
+
+ spin_lock_init(&ap->sta_table_lock);
+ INIT_LIST_HEAD(&ap->sta_list);
+
+ /* Initialize task queue structure for AP management */
+ INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap);
+
+ ap->tx_callback_idx =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb, ap);
+ if (ap->tx_callback_idx == 0)
+ printk(KERN_WARNING "%s: failed to register TX callback for "
+ "AP\n", local->dev->name);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local);
+
+ ap->tx_callback_auth =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap);
+ ap->tx_callback_assoc =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap);
+ ap->tx_callback_poll =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_poll, ap);
+ if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0 ||
+ ap->tx_callback_poll == 0)
+ printk(KERN_WARNING "%s: failed to register TX callback for "
+ "AP\n", local->dev->name);
+
+ spin_lock_init(&ap->mac_restrictions.lock);
+ INIT_LIST_HEAD(&ap->mac_restrictions.mac_list);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ ap->initialized = 1;
+}
+
+
+void hostap_init_ap_proc(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+
+ ap->proc = local->proc;
+ if (ap->proc == NULL)
+ return;
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("ap_debug", 0, ap->proc,
+ ap_debug_proc_read, ap);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ create_proc_read_entry("ap_control", 0, ap->proc,
+ ap_control_proc_read, ap);
+ create_proc_read_entry("ap", 0, ap->proc,
+ prism2_ap_proc_read, ap);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+}
+
+
+void hostap_free_data(struct ap_data *ap)
+{
+ struct list_head *n, *ptr;
+
+ if (ap == NULL || !ap->initialized) {
+ printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
+ "initialized - skip resource freeing\n");
+ return;
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (ap->crypt)
+ ap->crypt->deinit(ap->crypt_priv);
+ ap->crypt = ap->crypt_priv = NULL;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ list_for_each_safe(ptr, n, &ap->sta_list) {
+ struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+ }
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ if (ap->proc != NULL) {
+ remove_proc_entry("ap_debug", ap->proc);
+ }
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (ap->proc != NULL) {
+ remove_proc_entry("ap", ap->proc);
+ remove_proc_entry("ap_control", ap->proc);
+ }
+ ap_control_flush_macs(&ap->mac_restrictions);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ ap->initialized = 0;
+}
+
+
+/* caller should have mutex for AP STA list handling */
+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta)
+{
+ struct sta_info *s;
+
+ s = ap->sta_hash[STA_HASH(sta)];
+ while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0)
+ s = s->hnext;
+ return s;
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+/* Called from timer handler and from scheduled AP queue handlers */
+static void prism2_send_mgmt(struct net_device *dev,
+ u16 type_subtype, char *body,
+ int body_len, u8 *addr, u16 tx_cb_idx)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr *hdr;
+ u16 fc;
+ struct sk_buff *skb;
+ struct hostap_skb_tx_data *meta;
+ int hdrlen;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ dev = local->dev; /* always use master radio device */
+ iface = netdev_priv(dev);
+
+ if (!(dev->flags & IFF_UP)) {
+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt - device is not UP - "
+ "cannot send frame\n", dev->name);
+ return;
+ }
+
+ skb = dev_alloc_skb(sizeof(*hdr) + body_len);
+ if (skb == NULL) {
+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt failed to allocate "
+ "skb\n", dev->name);
+ return;
+ }
+
+ fc = type_subtype;
+ hdrlen = hostap_80211_get_hdrlen(fc);
+ hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
+ if (body)
+ memcpy(skb_put(skb, body_len), body, body_len);
+
+ memset(hdr, 0, hdrlen);
+
+ /* FIX: ctrl::ack sending used special HFA384X_TX_CTRL_802_11
+ * tx_control instead of using local->tx_control */
+
+
+ memcpy(hdr->addr1, addr, ETH_ALEN); /* DA / RA */
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) {
+ fc |= IEEE80211_FCTL_FROMDS;
+ memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */
+ memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* SA */
+ } else if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL) {
+ /* control:ACK does not have addr2 or addr3 */
+ memset(hdr->addr2, 0, ETH_ALEN);
+ memset(hdr->addr3, 0, ETH_ALEN);
+ } else {
+ memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* SA */
+ memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */
+ }
+
+ hdr->frame_ctl = cpu_to_le16(fc);
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = iface;
+ meta->tx_cb_idx = tx_cb_idx;
+
+ skb->dev = dev;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ dev_queue_xmit(skb);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static int prism2_sta_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct sta_info *sta = (struct sta_info *) data;
+ int i;
+
+ /* FIX: possible race condition.. the STA data could have just expired,
+ * but proc entry was still here so that the read could have started;
+ * some locking should be done here.. */
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "%s=" MACSTR "\nusers=%d\naid=%d\n"
+ "flags=0x%04x%s%s%s%s%s%s%s\n"
+ "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
+ sta->ap ? "AP" : "STA",
+ MAC2STR(sta->addr), atomic_read(&sta->users), sta->aid,
+ sta->flags,
+ sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
+ sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
+ sta->flags & WLAN_STA_PS ? " PS" : "",
+ sta->flags & WLAN_STA_TIM ? " TIM" : "",
+ sta->flags & WLAN_STA_PERM ? " PERM" : "",
+ sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",
+ sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",
+ sta->capability, sta->listen_interval);
+ /* supported_rates: 500 kbit/s units with msb ignored */
+ for (i = 0; i < sizeof(sta->supported_rates); i++)
+ if (sta->supported_rates[i] != 0)
+ p += sprintf(p, "%d%sMbps ",
+ (sta->supported_rates[i] & 0x7f) / 2,
+ sta->supported_rates[i] & 1 ? ".5" : "");
+ p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n"
+ "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n"
+ "tx_packets=%lu\n"
+ "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n"
+ "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n"
+ "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"
+ "tx[11M]=%d\n"
+ "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",
+ jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,
+ sta->last_tx,
+ sta->rx_packets, sta->tx_packets, sta->rx_bytes,
+ sta->tx_bytes, skb_queue_len(&sta->tx_buf),
+ sta->last_rx_silence,
+ sta->last_rx_signal, sta->last_rx_rate / 10,
+ sta->last_rx_rate % 10 ? ".5" : "",
+ sta->tx_rate, sta->tx_count[0], sta->tx_count[1],
+ sta->tx_count[2], sta->tx_count[3], sta->rx_count[0],
+ sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);
+ if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats)
+ p = sta->crypt->ops->print_stats(p, sta->crypt->priv);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->ap) {
+ if (sta->u.ap.channel >= 0)
+ p += sprintf(p, "channel=%d\n", sta->u.ap.channel);
+ p += sprintf(p, "ssid=");
+ for (i = 0; i < sta->u.ap.ssid_len; i++)
+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
+ sta->u.ap.ssid[i] < 127) ?
+ "%c" : "<%02x>"),
+ sta->u.ap.ssid[i]);
+ p += sprintf(p, "\n");
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ return (p - page);
+}
+
+
+static void handle_add_proc_queue(void *data)
+{
+ struct ap_data *ap = (struct ap_data *) data;
+ struct sta_info *sta;
+ char name[20];
+ struct add_sta_proc_data *entry, *prev;
+
+ entry = ap->add_sta_proc_entries;
+ ap->add_sta_proc_entries = NULL;
+
+ while (entry) {
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, entry->addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (sta) {
+ sprintf(name, MACSTR, MAC2STR(sta->addr));
+ sta->proc = create_proc_read_entry(
+ name, 0, ap->proc,
+ prism2_sta_proc_read, sta);
+
+ atomic_dec(&sta->users);
+ }
+
+ prev = entry;
+ entry = entry->next;
+ kfree(prev);
+ }
+}
+
+
+static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr)
+{
+ struct sta_info *sta;
+
+ sta = (struct sta_info *)
+ kmalloc(sizeof(struct sta_info), GFP_ATOMIC);
+ if (sta == NULL) {
+ PDEBUG(DEBUG_AP, "AP: kmalloc failed\n");
+ return NULL;
+ }
+
+ /* initialize STA info data */
+ memset(sta, 0, sizeof(struct sta_info));
+ sta->local = ap->local;
+ skb_queue_head_init(&sta->tx_buf);
+ memcpy(sta->addr, addr, ETH_ALEN);
+
+ atomic_inc(&sta->users);
+ spin_lock_bh(&ap->sta_table_lock);
+ list_add(&sta->list, &ap->sta_list);
+ ap->num_sta++;
+ ap_sta_hash_add(ap, sta);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (ap->proc) {
+ struct add_sta_proc_data *entry;
+ /* schedule a non-interrupt context process to add a procfs
+ * entry for the STA since procfs code use GFP_KERNEL */
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry) {
+ memcpy(entry->addr, sta->addr, ETH_ALEN);
+ entry->next = ap->add_sta_proc_entries;
+ ap->add_sta_proc_entries = entry;
+ schedule_work(&ap->add_sta_proc_queue);
+ } else
+ printk(KERN_DEBUG "Failed to add STA proc data\n");
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ init_timer(&sta->timer);
+ sta->timer.expires = jiffies + ap->max_inactivity;
+ sta->timer.data = (unsigned long) sta;
+ sta->timer.function = ap_handle_timer;
+ if (!ap->local->hostapd)
+ add_timer(&sta->timer);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ return sta;
+}
+
+
+static int ap_tx_rate_ok(int rateidx, struct sta_info *sta,
+ local_info_t *local)
+{
+ if (rateidx > sta->tx_max_rate ||
+ !(sta->tx_supp_rates & (1 << rateidx)))
+ return 0;
+
+ if (local->tx_rate_control != 0 &&
+ !(local->tx_rate_control & (1 << rateidx)))
+ return 0;
+
+ return 1;
+}
+
+
+static void prism2_check_tx_rates(struct sta_info *sta)
+{
+ int i;
+
+ sta->tx_supp_rates = 0;
+ for (i = 0; i < sizeof(sta->supported_rates); i++) {
+ if ((sta->supported_rates[i] & 0x7f) == 2)
+ sta->tx_supp_rates |= WLAN_RATE_1M;
+ if ((sta->supported_rates[i] & 0x7f) == 4)
+ sta->tx_supp_rates |= WLAN_RATE_2M;
+ if ((sta->supported_rates[i] & 0x7f) == 11)
+ sta->tx_supp_rates |= WLAN_RATE_5M5;
+ if ((sta->supported_rates[i] & 0x7f) == 22)
+ sta->tx_supp_rates |= WLAN_RATE_11M;
+ }
+ sta->tx_max_rate = sta->tx_rate = sta->tx_rate_idx = 0;
+ if (sta->tx_supp_rates & WLAN_RATE_1M) {
+ sta->tx_max_rate = 0;
+ if (ap_tx_rate_ok(0, sta, sta->local)) {
+ sta->tx_rate = 10;
+ sta->tx_rate_idx = 0;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_2M) {
+ sta->tx_max_rate = 1;
+ if (ap_tx_rate_ok(1, sta, sta->local)) {
+ sta->tx_rate = 20;
+ sta->tx_rate_idx = 1;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_5M5) {
+ sta->tx_max_rate = 2;
+ if (ap_tx_rate_ok(2, sta, sta->local)) {
+ sta->tx_rate = 55;
+ sta->tx_rate_idx = 2;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_11M) {
+ sta->tx_max_rate = 3;
+ if (ap_tx_rate_ok(3, sta, sta->local)) {
+ sta->tx_rate = 110;
+ sta->tx_rate_idx = 3;
+ }
+ }
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void ap_crypt_init(struct ap_data *ap)
+{
+ ap->crypt = ieee80211_get_crypto_ops("WEP");
+
+ if (ap->crypt) {
+ if (ap->crypt->init) {
+ ap->crypt_priv = ap->crypt->init(0);
+ if (ap->crypt_priv == NULL)
+ ap->crypt = NULL;
+ else {
+ u8 key[WEP_KEY_LEN];
+ get_random_bytes(key, WEP_KEY_LEN);
+ ap->crypt->set_key(key, WEP_KEY_LEN, NULL,
+ ap->crypt_priv);
+ }
+ }
+ }
+
+ if (ap->crypt == NULL) {
+ printk(KERN_WARNING "AP could not initialize WEP: load module "
+ "ieee80211_crypt_wep.ko\n");
+ }
+}
+
+
+/* Generate challenge data for shared key authentication. IEEE 802.11 specifies
+ * that WEP algorithm is used for generating challange. This should be unique,
+ * but otherwise there is not really need for randomness etc. Initialize WEP
+ * with pseudo random key and then use increasing IV to get unique challenge
+ * streams.
+ *
+ * Called only as a scheduled task for pending AP frames.
+ */
+static char * ap_auth_make_challenge(struct ap_data *ap)
+{
+ char *tmpbuf;
+ struct sk_buff *skb;
+
+ if (ap->crypt == NULL) {
+ ap_crypt_init(ap);
+ if (ap->crypt == NULL)
+ return NULL;
+ }
+
+ tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
+ if (tmpbuf == NULL) {
+ PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");
+ return NULL;
+ }
+
+ skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
+ ap->crypt->extra_prefix_len +
+ ap->crypt->extra_postfix_len);
+ if (skb == NULL) {
+ kfree(tmpbuf);
+ return NULL;
+ }
+
+ skb_reserve(skb, ap->crypt->extra_prefix_len);
+ memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
+ WLAN_AUTH_CHALLENGE_LEN);
+ if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
+ dev_kfree_skb(skb);
+ kfree(tmpbuf);
+ return NULL;
+ }
+
+ memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
+ WLAN_AUTH_CHALLENGE_LEN);
+ dev_kfree_skb(skb);
+
+ return tmpbuf;
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_authen(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ size_t hdrlen;
+ struct ap_data *ap = local->ap;
+ char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
+ int len, olen;
+ u16 auth_alg, auth_transaction, status_code, *pos;
+ u16 resp = WLAN_STATUS_SUCCESS, fc;
+ struct sta_info *sta = NULL;
+ struct ieee80211_crypt_data *crypt;
+ char *txt = "";
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ if (len < 6) {
+ PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "
+ "(len=%d) from " MACSTR "\n", dev->name, len,
+ MAC2STR(hdr->addr2));
+ return;
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta && sta->crypt)
+ crypt = sta->crypt;
+ else {
+ int idx = 0;
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+ crypt = local->crypt[idx];
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ auth_alg = __le16_to_cpu(*pos);
+ pos++;
+ auth_transaction = __le16_to_cpu(*pos);
+ pos++;
+ status_code = __le16_to_cpu(*pos);
+ pos++;
+
+ if (memcmp(dev->dev_addr, hdr->addr2, ETH_ALEN) == 0 ||
+ ap_control_mac_deny(&ap->mac_restrictions, hdr->addr2)) {
+ txt = "authentication denied";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ if (((local->auth_algs & PRISM2_AUTH_OPEN) &&
+ auth_alg == WLAN_AUTH_OPEN) ||
+ ((local->auth_algs & PRISM2_AUTH_SHARED_KEY) &&
+ crypt && auth_alg == WLAN_AUTH_SHARED_KEY)) {
+ } else {
+ txt = "unsupported algorithm";
+ resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
+ goto fail;
+ }
+
+ if (len >= 8) {
+ u8 *u = (u8 *) pos;
+ if (*u == WLAN_EID_CHALLENGE) {
+ if (*(u + 1) != WLAN_AUTH_CHALLENGE_LEN) {
+ txt = "invalid challenge len";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+ if (len - 8 < WLAN_AUTH_CHALLENGE_LEN) {
+ txt = "challenge underflow";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+ challenge = (char *) (u + 2);
+ }
+ }
+
+ if (sta && sta->ap) {
+ if (time_after(jiffies, sta->u.ap.last_beacon +
+ (10 * sta->listen_interval * HZ) / 1024)) {
+ PDEBUG(DEBUG_AP, "%s: no beacons received for a while,"
+ " assuming AP " MACSTR " is now STA\n",
+ dev->name, MAC2STR(sta->addr));
+ sta->ap = 0;
+ sta->flags = 0;
+ sta->u.sta.challenge = NULL;
+ } else {
+ txt = "AP trying to authenticate?";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+
+ if ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) ||
+ (auth_alg == WLAN_AUTH_SHARED_KEY &&
+ (auth_transaction == 1 ||
+ (auth_transaction == 3 && sta != NULL &&
+ sta->u.sta.challenge != NULL)))) {
+ } else {
+ txt = "unknown authentication transaction number";
+ resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
+ goto fail;
+ }
+
+ if (sta == NULL) {
+ txt = "new STA";
+
+ if (local->ap->num_sta >= MAX_STA_COUNT) {
+ /* FIX: might try to remove some old STAs first? */
+ txt = "no more room for new STAs";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ sta = ap_add_sta(local->ap, hdr->addr2);
+ if (sta == NULL) {
+ txt = "ap_add_sta failed";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+
+ switch (auth_alg) {
+ case WLAN_AUTH_OPEN:
+ txt = "authOK";
+ /* IEEE 802.11 standard is not completely clear about
+ * whether STA is considered authenticated after
+ * authentication OK frame has been send or after it
+ * has been ACKed. In order to reduce interoperability
+ * issues, mark the STA authenticated before ACK. */
+ sta->flags |= WLAN_STA_AUTH;
+ break;
+
+ case WLAN_AUTH_SHARED_KEY:
+ if (auth_transaction == 1) {
+ if (sta->u.sta.challenge == NULL) {
+ sta->u.sta.challenge =
+ ap_auth_make_challenge(local->ap);
+ if (sta->u.sta.challenge == NULL) {
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+ } else {
+ if (sta->u.sta.challenge == NULL ||
+ challenge == NULL ||
+ memcmp(sta->u.sta.challenge, challenge,
+ WLAN_AUTH_CHALLENGE_LEN) != 0 ||
+ !(fc & IEEE80211_FCTL_PROTECTED)) {
+ txt = "challenge response incorrect";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+
+ txt = "challenge OK - authOK";
+ /* IEEE 802.11 standard is not completely clear about
+ * whether STA is considered authenticated after
+ * authentication OK frame has been send or after it
+ * has been ACKed. In order to reduce interoperability
+ * issues, mark the STA authenticated before ACK. */
+ sta->flags |= WLAN_STA_AUTH;
+ kfree(sta->u.sta.challenge);
+ sta->u.sta.challenge = NULL;
+ }
+ break;
+ }
+
+ fail:
+ pos = (u16 *) body;
+ *pos = cpu_to_le16(auth_alg);
+ pos++;
+ *pos = cpu_to_le16(auth_transaction + 1);
+ pos++;
+ *pos = cpu_to_le16(resp); /* status_code */
+ pos++;
+ olen = 6;
+
+ if (resp == WLAN_STATUS_SUCCESS && sta != NULL &&
+ sta->u.sta.challenge != NULL &&
+ auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 1) {
+ u8 *tmp = (u8 *) pos;
+ *tmp++ = WLAN_EID_CHALLENGE;
+ *tmp++ = WLAN_AUTH_CHALLENGE_LEN;
+ pos++;
+ memcpy(pos, sta->u.sta.challenge, WLAN_AUTH_CHALLENGE_LEN);
+ olen += 2 + WLAN_AUTH_CHALLENGE_LEN;
+ }
+
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH,
+ body, olen, hdr->addr2, ap->tx_callback_auth);
+
+ if (sta) {
+ sta->last_rx = jiffies;
+ atomic_dec(&sta->users);
+ }
+
+ if (resp) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth (alg=%d trans#=%d "
+ "stat=%d len=%d fc=%04x) ==> %d (%s)\n",
+ dev->name, MAC2STR(hdr->addr2), auth_alg,
+ auth_transaction, status_code, len, fc, resp, txt);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_assoc(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int reassoc)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ char body[12], *p, *lpos;
+ int len, left;
+ u16 *pos;
+ u16 resp = WLAN_STATUS_SUCCESS;
+ struct sta_info *sta = NULL;
+ int send_deauth = 0;
+ char *txt = "";
+ u8 prev_ap[ETH_ALEN];
+
+ left = len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < (reassoc ? 10 : 4)) {
+ PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload "
+ "(len=%d, reassoc=%d) from " MACSTR "\n",
+ dev->name, len, reassoc, MAC2STR(hdr->addr2));
+ return;
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ txt = "trying to associate before authentication";
+ send_deauth = 1;
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ sta = NULL; /* do not decrement sta->users */
+ goto fail;
+ }
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ sta->capability = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+ sta->listen_interval = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+
+ if (reassoc) {
+ memcpy(prev_ap, pos, ETH_ALEN);
+ pos++; pos++; pos++; left -= 6;
+ } else
+ memset(prev_ap, 0, ETH_ALEN);
+
+ if (left >= 2) {
+ unsigned int ileft;
+ unsigned char *u = (unsigned char *) pos;
+
+ if (*u == WLAN_EID_SSID) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft > MAX_SSID_LEN) {
+ txt = "SSID overflow";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ if (ileft != strlen(local->essid) ||
+ memcmp(local->essid, u, ileft) != 0) {
+ txt = "not our SSID";
+ resp = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+ goto fail;
+ }
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (left >= 2 && *u == WLAN_EID_SUPP_RATES) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft == 0 ||
+ ileft > WLAN_SUPP_RATES_MAX) {
+ txt = "SUPP_RATES len error";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ memset(sta->supported_rates, 0,
+ sizeof(sta->supported_rates));
+ memcpy(sta->supported_rates, u, ileft);
+ prism2_check_tx_rates(sta);
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (left > 0) {
+ PDEBUG(DEBUG_AP, "%s: assoc from " MACSTR " with extra"
+ " data (%d bytes) [",
+ dev->name, MAC2STR(hdr->addr2), left);
+ while (left > 0) {
+ PDEBUG2(DEBUG_AP, "<%02x>", *u);
+ u++; left--;
+ }
+ PDEBUG2(DEBUG_AP, "]\n");
+ }
+ } else {
+ txt = "frame underflow";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ /* get a unique AID */
+ if (sta->aid > 0)
+ txt = "OK, old AID";
+ else {
+ spin_lock_bh(&local->ap->sta_table_lock);
+ for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
+ if (local->ap->sta_aid[sta->aid - 1] == NULL)
+ break;
+ if (sta->aid > MAX_AID_TABLE_SIZE) {
+ sta->aid = 0;
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ txt = "no room for more AIDs";
+ } else {
+ local->ap->sta_aid[sta->aid - 1] = sta;
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ txt = "OK, new AID";
+ }
+ }
+
+ fail:
+ pos = (u16 *) body;
+
+ if (send_deauth) {
+ *pos = __constant_cpu_to_le16(
+ WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
+ pos++;
+ } else {
+ /* FIX: CF-Pollable and CF-PollReq should be set to match the
+ * values in beacons/probe responses */
+ /* FIX: how about privacy and WEP? */
+ /* capability */
+ *pos = __constant_cpu_to_le16(WLAN_CAPABILITY_ESS);
+ pos++;
+
+ /* status_code */
+ *pos = __cpu_to_le16(resp);
+ pos++;
+
+ *pos = __cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) |
+ BIT(14) | BIT(15)); /* AID */
+ pos++;
+
+ /* Supported rates (Information element) */
+ p = (char *) pos;
+ *p++ = WLAN_EID_SUPP_RATES;
+ lpos = p;
+ *p++ = 0; /* len */
+ if (local->tx_rate_control & WLAN_RATE_1M) {
+ *p++ = local->basic_rates & WLAN_RATE_1M ? 0x82 : 0x02;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_2M) {
+ *p++ = local->basic_rates & WLAN_RATE_2M ? 0x84 : 0x04;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_5M5) {
+ *p++ = local->basic_rates & WLAN_RATE_5M5 ?
+ 0x8b : 0x0b;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_11M) {
+ *p++ = local->basic_rates & WLAN_RATE_11M ?
+ 0x96 : 0x16;
+ (*lpos)++;
+ }
+ pos = (u16 *) p;
+ }
+
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ (send_deauth ? IEEE80211_STYPE_DEAUTH :
+ (reassoc ? IEEE80211_STYPE_REASSOC_RESP :
+ IEEE80211_STYPE_ASSOC_RESP)),
+ body, (u8 *) pos - (u8 *) body,
+ hdr->addr2,
+ send_deauth ? 0 : local->ap->tx_callback_assoc);
+
+ if (sta) {
+ if (resp == WLAN_STATUS_SUCCESS) {
+ sta->last_rx = jiffies;
+ /* STA will be marked associated from TX callback, if
+ * AssocResp is ACKed */
+ }
+ atomic_dec(&sta->users);
+ }
+
+#if 0
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " %sassoc (len=%d prev_ap=" MACSTR
+ ") => %d(%d) (%s)\n",
+ dev->name, MAC2STR(hdr->addr2), reassoc ? "re" : "", len,
+ MAC2STR(prev_ap), resp, send_deauth, txt);
+#endif
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_deauth(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ int len;
+ u16 reason_code, *pos;
+ struct sta_info *sta = NULL;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 2) {
+ printk("handle_deauth - too short payload (len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ reason_code = __le16_to_cpu(*pos);
+
+ PDEBUG(DEBUG_AP, "%s: deauthentication: " MACSTR " len=%d, "
+ "reason_code=%d\n", dev->name, MAC2STR(hdr->addr2), len,
+ reason_code);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL) {
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ }
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ if (sta == NULL) {
+ printk("%s: deauthentication from " MACSTR ", "
+ "reason_code=%d, but STA not authenticated\n", dev->name,
+ MAC2STR(hdr->addr2), reason_code);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ int len;
+ u16 reason_code, *pos;
+ struct sta_info *sta = NULL;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 2) {
+ printk("handle_disassoc - too short payload (len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ reason_code = __le16_to_cpu(*pos);
+
+ PDEBUG(DEBUG_AP, "%s: disassociation: " MACSTR " len=%d, "
+ "reason_code=%d\n", dev->name, MAC2STR(hdr->addr2), len,
+ reason_code);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL) {
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+ sta->flags &= ~WLAN_STA_ASSOC;
+ }
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ if (sta == NULL) {
+ printk("%s: disassociation from " MACSTR ", "
+ "reason_code=%d, but STA not authenticated\n",
+ dev->name, MAC2STR(hdr->addr2), reason_code);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void ap_handle_data_nullfunc(local_info_t *local,
+ struct ieee80211_hdr *hdr)
+{
+ struct net_device *dev = local->dev;
+
+ /* some STA f/w's seem to require control::ACK frame for
+ * data::nullfunc, but at least Prism2 station f/w version 0.8.0 does
+ * not send this..
+ * send control::ACK for the data::nullfunc */
+
+ printk(KERN_DEBUG "Sending control::ACK for data::nullfunc\n");
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK,
+ NULL, 0, hdr->addr2, 0);
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void ap_handle_dropped_data(local_info_t *local,
+ struct ieee80211_hdr *hdr)
+{
+ struct net_device *dev = local->dev;
+ struct sta_info *sta;
+ u16 reason;
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC)) {
+ PDEBUG(DEBUG_AP, "ap_handle_dropped_data: STA is now okay?\n");
+ atomic_dec(&sta->users);
+ return;
+ }
+
+ reason = __constant_cpu_to_le16(
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ ((sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) ?
+ IEEE80211_STYPE_DEAUTH : IEEE80211_STYPE_DISASSOC),
+ (char *) &reason, sizeof(reason), hdr->addr2, 0);
+
+ if (sta)
+ atomic_dec(&sta->users);
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
+ struct sk_buff *skb)
+{
+ struct hostap_skb_tx_data *meta;
+
+ if (!(sta->flags & WLAN_STA_PS)) {
+ /* Station has moved to non-PS mode, so send all buffered
+ * frames using normal device queue. */
+ dev_queue_xmit(skb);
+ return;
+ }
+
+ /* add a flag for hostap_handle_sta_tx() to know that this skb should
+ * be passed through even though STA is using PS */
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ meta->flags |= HOSTAP_TX_FLAGS_BUFFERED_FRAME;
+ if (!skb_queue_empty(&sta->tx_buf)) {
+ /* indicate to STA that more frames follow */
+ meta->flags |= HOSTAP_TX_FLAGS_ADD_MOREDATA;
+ }
+ dev_queue_xmit(skb);
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_pspoll(local_info_t *local,
+ struct ieee80211_hdr *hdr,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct sta_info *sta;
+ u16 aid;
+ struct sk_buff *skb;
+
+ PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MACSTR ", TA=" MACSTR
+ " PWRMGT=%d\n",
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
+ !!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM));
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr1));
+ return;
+ }
+
+ aid = __le16_to_cpu(hdr->duration_id);
+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) {
+ PDEBUG(DEBUG_PS, " PSPOLL and AID[15:14] not set\n");
+ return;
+ }
+ aid &= ~BIT(15) & ~BIT(14);
+ if (aid == 0 || aid > MAX_AID_TABLE_SIZE) {
+ PDEBUG(DEBUG_PS, " invalid aid=%d\n", aid);
+ return;
+ }
+ PDEBUG(DEBUG_PS2, " aid=%d\n", aid);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta == NULL) {
+ PDEBUG(DEBUG_PS, " STA not found\n");
+ return;
+ }
+ if (sta->aid != aid) {
+ PDEBUG(DEBUG_PS, " received aid=%i does not match with "
+ "assoc.aid=%d\n", aid, sta->aid);
+ return;
+ }
+
+ /* FIX: todo:
+ * - add timeout for buffering (clear aid in TIM vector if buffer timed
+ * out (expiry time must be longer than ListenInterval for
+ * the corresponding STA; "8802-11: 11.2.1.9 AP aging function"
+ * - what to do, if buffered, pspolled, and sent frame is not ACKed by
+ * sta; store buffer for later use and leave TIM aid bit set? use
+ * TX event to check whether frame was ACKed?
+ */
+
+ while ((skb = skb_dequeue(&sta->tx_buf)) != NULL) {
+ /* send buffered frame .. */
+ PDEBUG(DEBUG_PS2, "Sending buffered frame to STA after PS POLL"
+ " (buffer_count=%d)\n", skb_queue_len(&sta->tx_buf));
+
+ pspoll_send_buffered(local, sta, skb);
+
+ if (sta->flags & WLAN_STA_PS) {
+ /* send only one buffered packet per PS Poll */
+ /* FIX: should ignore further PS Polls until the
+ * buffered packet that was just sent is acknowledged
+ * (Tx or TxExc event) */
+ break;
+ }
+ }
+
+ if (skb_queue_empty(&sta->tx_buf)) {
+ /* try to clear aid from TIM */
+ if (!(sta->flags & WLAN_STA_TIM))
+ PDEBUG(DEBUG_PS2, "Re-unsetting TIM for aid %d\n",
+ aid);
+ hostap_set_tim(local, aid, 0);
+ sta->flags &= ~WLAN_STA_TIM;
+ }
+
+ atomic_dec(&sta->users);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void handle_wds_oper_queue(void *data)
+{
+ local_info_t *local = data;
+ struct wds_oper_data *entry, *prev;
+
+ spin_lock_bh(&local->lock);
+ entry = local->ap->wds_oper_entries;
+ local->ap->wds_oper_entries = NULL;
+ spin_unlock_bh(&local->lock);
+
+ while (entry) {
+ PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection "
+ "to AP " MACSTR "\n",
+ local->dev->name,
+ entry->type == WDS_ADD ? "adding" : "removing",
+ MAC2STR(entry->addr));
+ if (entry->type == WDS_ADD)
+ prism2_wds_add(local, entry->addr, 0);
+ else if (entry->type == WDS_DEL)
+ prism2_wds_del(local, entry->addr, 0, 1);
+
+ prev = entry;
+ entry = entry->next;
+ kfree(prev);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_beacon(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ int len, left;
+ u16 *pos, beacon_int, capability;
+ char *ssid = NULL;
+ unsigned char *supp_rates = NULL;
+ int ssid_len = 0, supp_rates_len = 0;
+ struct sta_info *sta = NULL;
+ int new_sta = 0, channel = -1;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 8 + 2 + 2) {
+ printk(KERN_DEBUG "handle_beacon - too short payload "
+ "(len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ left = len;
+
+ /* Timestamp (8 octets) */
+ pos += 4; left -= 8;
+ /* Beacon interval (2 octets) */
+ beacon_int = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+ /* Capability information (2 octets) */
+ capability = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+
+ if (local->ap->ap_policy != AP_OTHER_AP_EVEN_IBSS &&
+ capability & WLAN_CAPABILITY_IBSS)
+ return;
+
+ if (left >= 2) {
+ unsigned int ileft;
+ unsigned char *u = (unsigned char *) pos;
+
+ if (*u == WLAN_EID_SSID) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft > MAX_SSID_LEN) {
+ PDEBUG(DEBUG_AP, "SSID: overflow\n");
+ return;
+ }
+
+ if (local->ap->ap_policy == AP_OTHER_AP_SAME_SSID &&
+ (ileft != strlen(local->essid) ||
+ memcmp(local->essid, u, ileft) != 0)) {
+ /* not our SSID */
+ return;
+ }
+
+ ssid = u;
+ ssid_len = ileft;
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (*u == WLAN_EID_SUPP_RATES) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft == 0 || ileft > 8) {
+ PDEBUG(DEBUG_AP, " - SUPP_RATES len error\n");
+ return;
+ }
+
+ supp_rates = u;
+ supp_rates_len = ileft;
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (*u == WLAN_EID_DS_PARAMS) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft != 1) {
+ PDEBUG(DEBUG_AP, " - DS_PARAMS len error\n");
+ return;
+ }
+
+ channel = *u;
+
+ u += ileft;
+ left -= ileft;
+ }
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta == NULL) {
+ /* add new AP */
+ new_sta = 1;
+ sta = ap_add_sta(local->ap, hdr->addr2);
+ if (sta == NULL) {
+ printk(KERN_INFO "prism2: kmalloc failed for AP "
+ "data structure\n");
+ return;
+ }
+ hostap_event_new_sta(local->dev, sta);
+
+ /* mark APs authentication and associated for pseudo ad-hoc
+ * style communication */
+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+
+ if (local->ap->autom_ap_wds) {
+ hostap_wds_link_oper(local, sta->addr, WDS_ADD);
+ }
+ }
+
+ sta->ap = 1;
+ if (ssid) {
+ sta->u.ap.ssid_len = ssid_len;
+ memcpy(sta->u.ap.ssid, ssid, ssid_len);
+ sta->u.ap.ssid[ssid_len] = '\0';
+ } else {
+ sta->u.ap.ssid_len = 0;
+ sta->u.ap.ssid[0] = '\0';
+ }
+ sta->u.ap.channel = channel;
+ sta->rx_packets++;
+ sta->rx_bytes += len;
+ sta->u.ap.last_beacon = sta->last_rx = jiffies;
+ sta->capability = capability;
+ sta->listen_interval = beacon_int;
+
+ atomic_dec(&sta->users);
+
+ if (new_sta) {
+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
+ memcpy(sta->supported_rates, supp_rates, supp_rates_len);
+ prism2_check_tx_rates(sta);
+ }
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+/* Called only as a tasklet. */
+static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ struct net_device *dev = local->dev;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ u16 fc, type, stype;
+ struct ieee80211_hdr *hdr;
+
+ /* FIX: should give skb->len to handler functions and check that the
+ * buffer is long enough */
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (!local->hostapd && type == IEEE80211_FTYPE_DATA) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - data frame\n");
+
+ if (!(fc & IEEE80211_FCTL_TODS) ||
+ (fc & IEEE80211_FCTL_FROMDS)) {
+ if (stype == IEEE80211_STYPE_NULLFUNC) {
+ /* no ToDS nullfunc seems to be used to check
+ * AP association; so send reject message to
+ * speed up re-association */
+ ap_handle_dropped_data(local, hdr);
+ goto done;
+ }
+ PDEBUG(DEBUG_AP, " not ToDS frame (fc=0x%04x)\n",
+ fc);
+ goto done;
+ }
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)="
+ MACSTR " not own MAC\n",
+ MAC2STR(hdr->addr1));
+ goto done;
+ }
+
+ if (local->ap->nullfunc_ack &&
+ stype == IEEE80211_STYPE_NULLFUNC)
+ ap_handle_data_nullfunc(local, hdr);
+ else
+ ap_handle_dropped_data(local, hdr);
+ goto done;
+ }
+
+ if (type == IEEE80211_FTYPE_MGMT && stype == IEEE80211_STYPE_BEACON) {
+ handle_beacon(local, skb, rx_stats);
+ goto done;
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ if (type == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL) {
+ handle_pspoll(local, hdr, rx_stats);
+ goto done;
+ }
+
+ if (local->hostapd) {
+ PDEBUG(DEBUG_AP, "Unknown frame in AP queue: type=0x%02x "
+ "subtype=0x%02x\n", type, stype);
+ goto done;
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (type != IEEE80211_FTYPE_MGMT) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - not a management frame?\n");
+ goto done;
+ }
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr1));
+ goto done;
+ }
+
+ if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr3));
+ goto done;
+ }
+
+ switch (stype) {
+ case IEEE80211_STYPE_ASSOC_REQ:
+ handle_assoc(local, skb, rx_stats, 0);
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ PDEBUG(DEBUG_AP, "==> ASSOC RESP (ignored)\n");
+ break;
+ case IEEE80211_STYPE_REASSOC_REQ:
+ handle_assoc(local, skb, rx_stats, 1);
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ PDEBUG(DEBUG_AP, "==> REASSOC RESP (ignored)\n");
+ break;
+ case IEEE80211_STYPE_ATIM:
+ PDEBUG(DEBUG_AP, "==> ATIM (ignored)\n");
+ break;
+ case IEEE80211_STYPE_DISASSOC:
+ handle_disassoc(local, skb, rx_stats);
+ break;
+ case IEEE80211_STYPE_AUTH:
+ handle_authen(local, skb, rx_stats);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ handle_deauth(local, skb, rx_stats);
+ break;
+ default:
+ PDEBUG(DEBUG_AP, "Unknown mgmt frame subtype 0x%02x\n",
+ stype >> 4);
+ break;
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ done:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 fc;
+ struct ieee80211_hdr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < 16)
+ goto drop;
+
+ local->stats.rx_packets++;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT &&
+ WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_BEACON)
+ goto drop;
+
+ skb->protocol = __constant_htons(ETH_P_HOSTAP);
+ handle_ap_item(local, skb, rx_stats);
+ return;
+
+ drop:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
+{
+ struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
+ struct hostap_80211_rx_status rx_stats;
+
+ if (skb_queue_empty(&sta->tx_buf))
+ return;
+
+ skb = dev_alloc_skb(16);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: schedule_packet_send: skb alloc "
+ "failed\n", local->dev->name);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
+
+ /* Generate a fake pspoll frame to start packet delivery */
+ hdr->frame_ctl = __constant_cpu_to_le16(
+ IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
+ memcpy(hdr->addr1, local->dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->addr2, sta->addr, ETH_ALEN);
+ hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14));
+
+ PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for "
+ "STA " MACSTR "\n", local->dev->name, MAC2STR(sta->addr));
+
+ skb->dev = local->dev;
+
+ memset(&rx_stats, 0, sizeof(rx_stats));
+ hostap_rx(local->dev, skb, &rx_stats);
+}
+
+
+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist)
+{
+ struct ap_data *ap = local->ap;
+ struct list_head *ptr;
+ int count = 0;
+
+ spin_lock_bh(&ap->sta_table_lock);
+
+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list;
+ ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ if (aplist && !sta->ap)
+ continue;
+ addr[count].sa_family = ARPHRD_ETHER;
+ memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
+ if (sta->last_rx_silence == 0)
+ qual[count].qual = sta->last_rx_signal < 27 ?
+ 0 : (sta->last_rx_signal - 27) * 92 / 127;
+ else
+ qual[count].qual = sta->last_rx_signal -
+ sta->last_rx_silence - 35;
+ qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+ qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+ qual[count].updated = sta->last_rx_updated;
+
+ sta->last_rx_updated = 0;
+
+ count++;
+ if (count >= buf_size)
+ break;
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ return count;
+}
+
+
+/* Translate our list of Access Points & Stations to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ap_data *ap;
+ struct list_head *ptr;
+ struct iw_event iwe;
+ char *current_ev = buffer;
+ char *end_buf = buffer + IW_SCAN_MAX_DATA;
+#if !defined(PRISM2_NO_KERNEL_IEEE80211_MGMT)
+ char buf[64];
+#endif
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ ap = local->ap;
+
+ spin_lock_bh(&ap->sta_table_lock);
+
+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list;
+ ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ /* First entry *MUST* be the AP MAC address */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN);
+ iwe.len = IW_EV_ADDR_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_ADDR_LEN);
+
+ /* Use the mode to indicate if it's a station or
+ * an Access Point */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWMODE;
+ if (sta->ap)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_INFRA;
+ iwe.len = IW_EV_UINT_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_UINT_LEN);
+
+ /* Some quality */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVQUAL;
+ if (sta->last_rx_silence == 0)
+ iwe.u.qual.qual = sta->last_rx_signal < 27 ?
+ 0 : (sta->last_rx_signal - 27) * 92 / 127;
+ else
+ iwe.u.qual.qual = sta->last_rx_signal -
+ sta->last_rx_silence - 35;
+ iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+ iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+ iwe.u.qual.updated = sta->last_rx_updated;
+ iwe.len = IW_EV_QUAL_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_QUAL_LEN);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->ap) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = sta->u.ap.ssid_len;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe,
+ sta->u.ap.ssid);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWENCODE;
+ if (sta->capability & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags =
+ IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe,
+ sta->u.ap.ssid
+ /* 0 byte memcpy */);
+
+ if (sta->u.ap.channel > 0 &&
+ sta->u.ap.channel <= FREQ_COUNT) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = freq_list[sta->u.ap.channel - 1]
+ * 100000;
+ iwe.u.freq.e = 1;
+ current_ev = iwe_stream_add_event(
+ current_ev, end_buf, &iwe,
+ IW_EV_FREQ_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "beacon_interval=%d",
+ sta->listen_interval);
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe, buf);
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ sta->last_rx_updated = 0;
+
+ /* To be continued, we should make good use of IWEVCUSTOM */
+ }
+
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ return current_ev - buffer;
+}
+
+
+static int prism2_hostapd_add_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (sta == NULL) {
+ sta = ap_add_sta(ap, param->sta_addr);
+ if (sta == NULL)
+ return -1;
+ }
+
+ if (!(sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_new_sta(sta->local->dev, sta);
+
+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ sta->last_rx = jiffies;
+ sta->aid = param->u.add_sta.aid;
+ sta->capability = param->u.add_sta.capability;
+ sta->tx_supp_rates = param->u.add_sta.tx_supp_rates;
+ if (sta->tx_supp_rates & WLAN_RATE_1M)
+ sta->supported_rates[0] = 2;
+ if (sta->tx_supp_rates & WLAN_RATE_2M)
+ sta->supported_rates[1] = 4;
+ if (sta->tx_supp_rates & WLAN_RATE_5M5)
+ sta->supported_rates[2] = 11;
+ if (sta->tx_supp_rates & WLAN_RATE_11M)
+ sta->supported_rates[3] = 22;
+ prism2_check_tx_rates(sta);
+ atomic_dec(&sta->users);
+ return 0;
+}
+
+
+static int prism2_hostapd_remove_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+
+ return 0;
+}
+
+
+static int prism2_hostapd_get_info_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ param->u.get_info_sta.inactive_sec = (jiffies - sta->last_rx) / HZ;
+
+ atomic_dec(&sta->users);
+
+ return 1;
+}
+
+
+static int prism2_hostapd_set_flags_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ sta->flags |= param->u.set_flags_sta.flags_or;
+ sta->flags &= param->u.set_flags_sta.flags_and;
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ return 0;
+}
+
+
+static int prism2_hostapd_sta_clear_stats(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+ int rate;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ sta->rx_packets = sta->tx_packets = 0;
+ sta->rx_bytes = sta->tx_bytes = 0;
+ for (rate = 0; rate < WLAN_RATE_COUNT; rate++) {
+ sta->tx_count[rate] = 0;
+ sta->rx_count[rate] = 0;
+ }
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ return 0;
+}
+
+
+static int prism2_hostapd(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ switch (param->cmd) {
+ case PRISM2_HOSTAPD_FLUSH:
+ ap_control_kickall(ap);
+ return 0;
+ case PRISM2_HOSTAPD_ADD_STA:
+ return prism2_hostapd_add_sta(ap, param);
+ case PRISM2_HOSTAPD_REMOVE_STA:
+ return prism2_hostapd_remove_sta(ap, param);
+ case PRISM2_HOSTAPD_GET_INFO_STA:
+ return prism2_hostapd_get_info_sta(ap, param);
+ case PRISM2_HOSTAPD_SET_FLAGS_STA:
+ return prism2_hostapd_set_flags_sta(ap, param);
+ case PRISM2_HOSTAPD_STA_CLEAR_STATS:
+ return prism2_hostapd_sta_clear_stats(ap, param);
+ default:
+ printk(KERN_WARNING "prism2_hostapd: unknown cmd=%d\n",
+ param->cmd);
+ return -EOPNOTSUPP;
+ }
+}
+
+
+/* Update station info for host-based TX rate control and return current
+ * TX rate */
+static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev)
+{
+ int ret = sta->tx_rate;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ sta->tx_count[sta->tx_rate_idx]++;
+ sta->tx_since_last_failure++;
+ sta->tx_consecutive_exc = 0;
+ if (sta->tx_since_last_failure >= WLAN_RATE_UPDATE_COUNT &&
+ sta->tx_rate_idx < sta->tx_max_rate) {
+ /* use next higher rate */
+ int old_rate, new_rate;
+ old_rate = new_rate = sta->tx_rate_idx;
+ while (new_rate < sta->tx_max_rate) {
+ new_rate++;
+ if (ap_tx_rate_ok(new_rate, sta, local)) {
+ sta->tx_rate_idx = new_rate;
+ break;
+ }
+ }
+ if (old_rate != sta->tx_rate_idx) {
+ switch (sta->tx_rate_idx) {
+ case 0: sta->tx_rate = 10; break;
+ case 1: sta->tx_rate = 20; break;
+ case 2: sta->tx_rate = 55; break;
+ case 3: sta->tx_rate = 110; break;
+ default: sta->tx_rate = 0; break;
+ }
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate raised to"
+ " %d\n", dev->name, MAC2STR(sta->addr),
+ sta->tx_rate);
+ }
+ sta->tx_since_last_failure = 0;
+ }
+
+ return ret;
+}
+
+
+/* Called only from software IRQ. Called for each TX frame prior possible
+ * encryption and transmit. */
+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
+{
+ struct sta_info *sta = NULL;
+ struct sk_buff *skb = tx->skb;
+ int set_tim, ret;
+ struct ieee80211_hdr *hdr;
+ struct hostap_skb_tx_data *meta;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ ret = AP_TX_CONTINUE;
+ if (local->ap == NULL || skb->len < 10 ||
+ meta->iface->type == HOSTAP_INTERFACE_STA)
+ goto out;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ if (hdr->addr1[0] & 0x01) {
+ /* broadcast/multicast frame - no AP related processing */
+ goto out;
+ }
+
+ /* unicast packet - check whether destination STA is associated */
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (local->iw_mode == IW_MODE_MASTER && sta == NULL &&
+ !(meta->flags & HOSTAP_TX_FLAGS_WDS) &&
+ meta->iface->type != HOSTAP_INTERFACE_MASTER &&
+ meta->iface->type != HOSTAP_INTERFACE_AP) {
+#if 0
+ /* This can happen, e.g., when wlan0 is added to a bridge and
+ * bridging code does not know which port is the correct target
+ * for a unicast frame. In this case, the packet is send to all
+ * ports of the bridge. Since this is a valid scenario, do not
+ * print out any errors here. */
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "AP: drop packet to non-associated "
+ "STA " MACSTR "\n", MAC2STR(hdr->addr1));
+ }
+#endif
+ local->ap->tx_drop_nonassoc++;
+ ret = AP_TX_DROP;
+ goto out;
+ }
+
+ if (sta == NULL)
+ goto out;
+
+ if (!(sta->flags & WLAN_STA_AUTHORIZED))
+ ret = AP_TX_CONTINUE_NOT_AUTHORIZED;
+
+ /* Set tx_rate if using host-based TX rate control */
+ if (!local->fw_tx_rate_control)
+ local->ap->last_tx_rate = meta->rate =
+ ap_update_sta_tx_rate(sta, local->dev);
+
+ if (local->iw_mode != IW_MODE_MASTER)
+ goto out;
+
+ if (!(sta->flags & WLAN_STA_PS))
+ goto out;
+
+ if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) {
+ /* indicate to STA that more frames follow */
+ hdr->frame_ctl |=
+ __constant_cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ }
+
+ if (meta->flags & HOSTAP_TX_FLAGS_BUFFERED_FRAME) {
+ /* packet was already buffered and now send due to
+ * PS poll, so do not rebuffer it */
+ goto out;
+ }
+
+ if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) {
+ PDEBUG(DEBUG_PS, "%s: No more space in STA (" MACSTR ")'s PS "
+ "mode buffer\n", local->dev->name, MAC2STR(sta->addr));
+ /* Make sure that TIM is set for the station (it might not be
+ * after AP wlan hw reset). */
+ /* FIX: should fix hw reset to restore bits based on STA
+ * buffer state.. */
+ hostap_set_tim(local, sta->aid, 1);
+ sta->flags |= WLAN_STA_TIM;
+ ret = AP_TX_DROP;
+ goto out;
+ }
+
+ /* STA in PS mode, buffer frame for later delivery */
+ set_tim = skb_queue_empty(&sta->tx_buf);
+ skb_queue_tail(&sta->tx_buf, skb);
+ /* FIX: could save RX time to skb and expire buffered frames after
+ * some time if STA does not poll for them */
+
+ if (set_tim) {
+ if (sta->flags & WLAN_STA_TIM)
+ PDEBUG(DEBUG_PS2, "Re-setting TIM for aid %d\n",
+ sta->aid);
+ hostap_set_tim(local, sta->aid, 1);
+ sta->flags |= WLAN_STA_TIM;
+ }
+
+ ret = AP_TX_BUFFERED;
+
+ out:
+ if (sta != NULL) {
+ if (ret == AP_TX_CONTINUE ||
+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) {
+ sta->tx_packets++;
+ sta->tx_bytes += skb->len;
+ sta->last_tx = jiffies;
+ }
+
+ if ((ret == AP_TX_CONTINUE ||
+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) &&
+ sta->crypt && tx->host_encrypt) {
+ tx->crypt = sta->crypt;
+ tx->sta_ptr = sta; /* hostap_handle_sta_release() will
+ * be called to release sta info
+ * later */
+ } else
+ atomic_dec(&sta->users);
+ }
+
+ return ret;
+}
+
+
+void hostap_handle_sta_release(void *ptr)
+{
+ struct sta_info *sta = ptr;
+ atomic_dec(&sta->users);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
+{
+ struct sta_info *sta;
+ struct ieee80211_hdr *hdr;
+ struct hostap_skb_tx_data *meta;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr1);
+ if (!sta) {
+ spin_unlock(&local->ap->sta_table_lock);
+ PDEBUG(DEBUG_AP, "%s: Could not find STA " MACSTR " for this "
+ "TX error (@%lu)\n",
+ local->dev->name, MAC2STR(hdr->addr1), jiffies);
+ return;
+ }
+
+ sta->tx_since_last_failure = 0;
+ sta->tx_consecutive_exc++;
+
+ if (sta->tx_consecutive_exc >= WLAN_RATE_DECREASE_THRESHOLD &&
+ sta->tx_rate_idx > 0 && meta->rate <= sta->tx_rate) {
+ /* use next lower rate */
+ int old, rate;
+ old = rate = sta->tx_rate_idx;
+ while (rate > 0) {
+ rate--;
+ if (ap_tx_rate_ok(rate, sta, local)) {
+ sta->tx_rate_idx = rate;
+ break;
+ }
+ }
+ if (old != sta->tx_rate_idx) {
+ switch (sta->tx_rate_idx) {
+ case 0: sta->tx_rate = 10; break;
+ case 1: sta->tx_rate = 20; break;
+ case 2: sta->tx_rate = 55; break;
+ case 3: sta->tx_rate = 110; break;
+ default: sta->tx_rate = 0; break;
+ }
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate lowered "
+ "to %d\n", local->dev->name, MAC2STR(sta->addr),
+ sta->tx_rate);
+ }
+ sta->tx_consecutive_exc = 0;
+ }
+ spin_unlock(&local->ap->sta_table_lock);
+}
+
+
+static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
+ int pwrmgt, int type, int stype)
+{
+ if (pwrmgt && !(sta->flags & WLAN_STA_PS)) {
+ sta->flags |= WLAN_STA_PS;
+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to use PS "
+ "mode (type=0x%02X, stype=0x%02X)\n",
+ MAC2STR(sta->addr), type >> 2, stype >> 4);
+ } else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) {
+ sta->flags &= ~WLAN_STA_PS;
+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to not use "
+ "PS mode (type=0x%02X, stype=0x%02X)\n",
+ MAC2STR(sta->addr), type >> 2, stype >> 4);
+ if (type != IEEE80211_FTYPE_CTL ||
+ stype != IEEE80211_STYPE_PSPOLL)
+ schedule_packet_send(local, sta);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ). Called for each RX frame to update
+ * STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
+{
+ struct sta_info *sta;
+ u16 fc;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (!sta)
+ return -1;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM,
+ WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc));
+
+ atomic_dec(&sta->users);
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ). Called for each RX frame after
+ * getting RX header and payload from hardware. */
+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
+ struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats,
+ int wds)
+{
+ int ret;
+ struct sta_info *sta;
+ u16 fc, type, stype;
+ struct ieee80211_hdr *hdr;
+
+ if (local->ap == NULL)
+ return AP_RX_CONTINUE;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (sta && !(sta->flags & WLAN_STA_AUTHORIZED))
+ ret = AP_RX_CONTINUE_NOT_AUTHORIZED;
+ else
+ ret = AP_RX_CONTINUE;
+
+
+ if (fc & IEEE80211_FCTL_TODS) {
+ if (!wds && (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NON_ASSOC);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ printk(KERN_DEBUG "%s: dropped received packet"
+ " from non-associated STA " MACSTR
+ " (type=0x%02x, subtype=0x%02x)\n",
+ dev->name, MAC2STR(hdr->addr2),
+ type >> 2, stype >> 4);
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ }
+ } else if (fc & IEEE80211_FCTL_FROMDS) {
+ if (!wds) {
+ /* FromDS frame - not for us; probably
+ * broadcast/multicast in another BSS - drop */
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ printk(KERN_DEBUG "Odd.. FromDS packet "
+ "received with own BSSID\n");
+ hostap_dump_rx_80211(dev->name, skb, rx_stats);
+ }
+ ret = AP_RX_DROP;
+ goto out;
+ }
+ } else if (stype == IEEE80211_STYPE_NULLFUNC && sta == NULL &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NON_ASSOC);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ /* At least Lucent f/w seems to send data::nullfunc
+ * frames with no ToDS flag when the current AP returns
+ * after being unavailable for some time. Speed up
+ * re-association by informing the station about it not
+ * being associated. */
+ printk(KERN_DEBUG "%s: rejected received nullfunc "
+ "frame without ToDS from not associated STA "
+ MACSTR "\n",
+ dev->name, MAC2STR(hdr->addr2));
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ } else if (stype == IEEE80211_STYPE_NULLFUNC) {
+ /* At least Lucent cards seem to send periodic nullfunc
+ * frames with ToDS. Let these through to update SQ
+ * stats and PS state. Nullfunc frames do not contain
+ * any data and they will be dropped below. */
+ } else {
+ /* If BSSID (Addr3) is foreign, this frame is a normal
+ * broadcast frame from an IBSS network. Drop it silently.
+ * If BSSID is own, report the dropping of this frame. */
+ if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ printk(KERN_DEBUG "%s: dropped received packet from "
+ MACSTR " with no ToDS flag (type=0x%02x, "
+ "subtype=0x%02x)\n", dev->name,
+ MAC2STR(hdr->addr2), type >> 2, stype >> 4);
+ hostap_dump_rx_80211(dev->name, skb, rx_stats);
+ }
+ ret = AP_RX_DROP;
+ goto out;
+ }
+
+ if (sta) {
+ hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM,
+ type, stype);
+
+ sta->rx_packets++;
+ sta->rx_bytes += skb->len;
+ sta->last_rx = jiffies;
+ }
+
+ if (local->ap->nullfunc_ack && stype == IEEE80211_STYPE_NULLFUNC &&
+ fc & IEEE80211_FCTL_TODS) {
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NULLFUNC_ACK);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ /* some STA f/w's seem to require control::ACK frame
+ * for data::nullfunc, but Prism2 f/w 0.8.0 (at least
+ * from Compaq) does not send this.. Try to generate
+ * ACK for these frames from the host driver to make
+ * power saving work with, e.g., Lucent WaveLAN f/w */
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ }
+
+ out:
+ if (sta)
+ atomic_dec(&sta->users);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_handle_sta_crypto(local_info_t *local,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_crypt_data **crypt,
+ void **sta_ptr)
+{
+ struct sta_info *sta;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (!sta)
+ return -1;
+
+ if (sta->crypt) {
+ *crypt = sta->crypt;
+ *sta_ptr = sta;
+ /* hostap_handle_sta_release() will be called to release STA
+ * info */
+ } else
+ atomic_dec(&sta->users);
+
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 0;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ ret = 1;
+ spin_unlock(&ap->sta_table_lock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 0;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap &&
+ ((sta->flags & WLAN_STA_AUTHORIZED) ||
+ ap->local->ieee_802_1x == 0))
+ ret = 1;
+ spin_unlock(&ap->sta_table_lock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 1;
+
+ if (!ap)
+ return -1;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta)
+ ret = 0;
+ spin_unlock(&ap->sta_table_lock);
+
+ if (ret == 1) {
+ sta = ap_add_sta(ap, sta_addr);
+ if (!sta)
+ ret = -1;
+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ sta->ap = 1;
+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
+ /* No way of knowing which rates are supported since we did not
+ * get supported rates element from beacon/assoc req. Assume
+ * that remote end supports all 802.11b rates. */
+ sta->supported_rates[0] = 0x82;
+ sta->supported_rates[1] = 0x84;
+ sta->supported_rates[2] = 0x0b;
+ sta->supported_rates[3] = 0x16;
+ sta->tx_supp_rates = WLAN_RATE_1M | WLAN_RATE_2M |
+ WLAN_RATE_5M5 | WLAN_RATE_11M;
+ sta->tx_rate = 110;
+ sta->tx_max_rate = sta->tx_rate_idx = 3;
+ }
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_update_rx_stats(struct ap_data *ap,
+ struct ieee80211_hdr *hdr,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct sta_info *sta;
+
+ if (!ap)
+ return -1;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr2);
+ if (sta) {
+ sta->last_rx_silence = rx_stats->noise;
+ sta->last_rx_signal = rx_stats->signal;
+ sta->last_rx_rate = rx_stats->rate;
+ sta->last_rx_updated = 7;
+ if (rx_stats->rate == 10)
+ sta->rx_count[0]++;
+ else if (rx_stats->rate == 20)
+ sta->rx_count[1]++;
+ else if (rx_stats->rate == 55)
+ sta->rx_count[2]++;
+ else if (rx_stats->rate == 110)
+ sta->rx_count[3]++;
+ }
+ spin_unlock(&ap->sta_table_lock);
+
+ return sta ? 0 : -1;
+}
+
+
+void hostap_update_rates(local_info_t *local)
+{
+ struct list_head *ptr;
+ struct ap_data *ap = local->ap;
+
+ if (!ap)
+ return;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+ prism2_check_tx_rates(sta);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+}
+
+
+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta && permanent)
+ sta = ap_add_sta(ap, addr);
+
+ if (!sta)
+ return NULL;
+
+ if (permanent)
+ sta->flags |= WLAN_STA_PERM;
+
+ *crypt = &sta->crypt;
+
+ return sta;
+}
+
+
+void hostap_add_wds_links(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+ struct list_head *ptr;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ list_for_each(ptr, &ap->sta_list) {
+ struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ if (sta->ap)
+ hostap_wds_link_oper(local, sta->addr, WDS_ADD);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ schedule_work(&local->ap->wds_oper_queue);
+}
+
+
+void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type)
+{
+ struct wds_oper_data *entry;
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return;
+ memcpy(entry->addr, addr, ETH_ALEN);
+ entry->type = type;
+ spin_lock_bh(&local->lock);
+ entry->next = local->ap->wds_oper_entries;
+ local->ap->wds_oper_entries = entry;
+ spin_unlock_bh(&local->lock);
+
+ schedule_work(&local->ap->wds_oper_queue);
+}
+
+
+EXPORT_SYMBOL(hostap_init_data);
+EXPORT_SYMBOL(hostap_init_ap_proc);
+EXPORT_SYMBOL(hostap_free_data);
+EXPORT_SYMBOL(hostap_check_sta_fw_version);
+EXPORT_SYMBOL(hostap_handle_sta_tx);
+EXPORT_SYMBOL(hostap_handle_sta_release);
+EXPORT_SYMBOL(hostap_handle_sta_tx_exc);
+EXPORT_SYMBOL(hostap_update_sta_ps);
+EXPORT_SYMBOL(hostap_handle_sta_rx);
+EXPORT_SYMBOL(hostap_is_sta_assoc);
+EXPORT_SYMBOL(hostap_is_sta_authorized);
+EXPORT_SYMBOL(hostap_add_sta);
+EXPORT_SYMBOL(hostap_update_rates);
+EXPORT_SYMBOL(hostap_add_wds_links);
+EXPORT_SYMBOL(hostap_wds_link_oper);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+EXPORT_SYMBOL(hostap_deauth_all_stas);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
new file mode 100644
index 000000000000..816a52bcea8f
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -0,0 +1,261 @@
+#ifndef HOSTAP_AP_H
+#define HOSTAP_AP_H
+
+/* AP data structures for STAs */
+
+/* maximum number of frames to buffer per STA */
+#define STA_MAX_TX_BUFFER 32
+
+/* STA flags */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+ * controlling whether STA is authorized to
+ * send and receive non-IEEE 802.1X frames
+ */
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
+
+#define WLAN_RATE_1M BIT(0)
+#define WLAN_RATE_2M BIT(1)
+#define WLAN_RATE_5M5 BIT(2)
+#define WLAN_RATE_11M BIT(3)
+#define WLAN_RATE_COUNT 4
+
+/* Maximum size of Supported Rates info element. IEEE 802.11 has a limit of 8,
+ * but some pre-standard IEEE 802.11g products use longer elements. */
+#define WLAN_SUPP_RATES_MAX 32
+
+/* Try to increase TX rate after # successfully sent consecutive packets */
+#define WLAN_RATE_UPDATE_COUNT 50
+
+/* Decrease TX rate after # consecutive dropped packets */
+#define WLAN_RATE_DECREASE_THRESHOLD 2
+
+struct sta_info {
+ struct list_head list;
+ struct sta_info *hnext; /* next entry in hash table list */
+ atomic_t users; /* number of users (do not remove if > 0) */
+ struct proc_dir_entry *proc;
+
+ u8 addr[6];
+ u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
+ u32 flags;
+ u16 capability;
+ u16 listen_interval; /* or beacon_int for APs */
+ u8 supported_rates[WLAN_SUPP_RATES_MAX];
+
+ unsigned long last_auth;
+ unsigned long last_assoc;
+ unsigned long last_rx;
+ unsigned long last_tx;
+ unsigned long rx_packets, tx_packets;
+ unsigned long rx_bytes, tx_bytes;
+ struct sk_buff_head tx_buf;
+ /* FIX: timeout buffers with an expiry time somehow derived from
+ * listen_interval */
+
+ s8 last_rx_silence; /* Noise in dBm */
+ s8 last_rx_signal; /* Signal strength in dBm */
+ u8 last_rx_rate; /* TX rate in 0.1 Mbps */
+ u8 last_rx_updated; /* IWSPY's struct iw_quality::updated */
+
+ u8 tx_supp_rates; /* bit field of supported TX rates */
+ u8 tx_rate; /* current TX rate (in 0.1 Mbps) */
+ u8 tx_rate_idx; /* current TX rate (WLAN_RATE_*) */
+ u8 tx_max_rate; /* max TX rate (WLAN_RATE_*) */
+ u32 tx_count[WLAN_RATE_COUNT]; /* number of frames sent (per rate) */
+ u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate)
+ */
+ u32 tx_since_last_failure;
+ u32 tx_consecutive_exc;
+
+ struct ieee80211_crypt_data *crypt;
+
+ int ap; /* whether this station is an AP */
+
+ local_info_t *local;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ union {
+ struct {
+ char *challenge; /* shared key authentication
+ * challenge */
+ } sta;
+ struct {
+ int ssid_len;
+ unsigned char ssid[MAX_SSID_LEN + 1]; /* AP's ssid */
+ int channel;
+ unsigned long last_beacon; /* last RX beacon time */
+ } ap;
+ } u;
+
+ struct timer_list timer;
+ enum { STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH } timeout_next;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+};
+
+
+#define MAX_STA_COUNT 1024
+
+/* Maximum number of AIDs to use for STAs; must be 2007 or lower
+ * (8802.11 limitation) */
+#define MAX_AID_TABLE_SIZE 128
+
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+
+
+/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY_SEC
+ * has passed since last received frame from the station, a nullfunc data
+ * frame is sent to the station. If this frame is not acknowledged and no other
+ * frames have been received, the station will be disassociated after
+ * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after
+ * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with
+ * max inactivity timer. */
+#define AP_MAX_INACTIVITY_SEC (5 * 60)
+#define AP_DISASSOC_DELAY (HZ)
+#define AP_DEAUTH_DELAY (HZ)
+
+/* ap_policy: whether to accept frames to/from other APs/IBSS */
+typedef enum {
+ AP_OTHER_AP_SKIP_ALL = 0,
+ AP_OTHER_AP_SAME_SSID = 1,
+ AP_OTHER_AP_ALL = 2,
+ AP_OTHER_AP_EVEN_IBSS = 3
+} ap_policy_enum;
+
+#define PRISM2_AUTH_OPEN BIT(0)
+#define PRISM2_AUTH_SHARED_KEY BIT(1)
+
+
+/* MAC address-based restrictions */
+struct mac_entry {
+ struct list_head list;
+ u8 addr[6];
+};
+
+struct mac_restrictions {
+ enum { MAC_POLICY_OPEN = 0, MAC_POLICY_ALLOW, MAC_POLICY_DENY } policy;
+ unsigned int entries;
+ struct list_head mac_list;
+ spinlock_t lock;
+};
+
+
+struct add_sta_proc_data {
+ u8 addr[ETH_ALEN];
+ struct add_sta_proc_data *next;
+};
+
+
+typedef enum { WDS_ADD, WDS_DEL } wds_oper_type;
+struct wds_oper_data {
+ wds_oper_type type;
+ u8 addr[ETH_ALEN];
+ struct wds_oper_data *next;
+};
+
+
+struct ap_data {
+ int initialized; /* whether ap_data has been initialized */
+ local_info_t *local;
+ int bridge_packets; /* send packet to associated STAs directly to the
+ * wireless media instead of higher layers in the
+ * kernel */
+ unsigned int bridged_unicast; /* number of unicast frames bridged on
+ * wireless media */
+ unsigned int bridged_multicast; /* number of non-unicast frames
+ * bridged on wireless media */
+ unsigned int tx_drop_nonassoc; /* number of unicast TX packets dropped
+ * because they were to an address that
+ * was not associated */
+ int nullfunc_ack; /* use workaround for nullfunc frame ACKs */
+
+ spinlock_t sta_table_lock;
+ int num_sta; /* number of entries in sta_list */
+ struct list_head sta_list; /* STA info list head */
+ struct sta_info *sta_hash[STA_HASH_SIZE];
+
+ struct proc_dir_entry *proc;
+
+ ap_policy_enum ap_policy;
+ unsigned int max_inactivity;
+ int autom_ap_wds;
+
+ struct mac_restrictions mac_restrictions; /* MAC-based auth */
+ int last_tx_rate;
+
+ struct work_struct add_sta_proc_queue;
+ struct add_sta_proc_data *add_sta_proc_entries;
+
+ struct work_struct wds_oper_queue;
+ struct wds_oper_data *wds_oper_entries;
+
+ u16 tx_callback_idx;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ /* pointers to STA info; based on allocated AID or NULL if AID free
+ * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
+ * and so on
+ */
+ struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
+
+ u16 tx_callback_auth, tx_callback_assoc, tx_callback_poll;
+
+ /* WEP operations for generating challenges to be used with shared key
+ * authentication */
+ struct ieee80211_crypto_ops *crypt;
+ void *crypt_priv;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+};
+
+
+void hostap_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_init_data(local_info_t *local);
+void hostap_init_ap_proc(local_info_t *local);
+void hostap_free_data(struct ap_data *ap);
+void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver);
+
+typedef enum {
+ AP_TX_CONTINUE, AP_TX_DROP, AP_TX_RETRY, AP_TX_BUFFERED,
+ AP_TX_CONTINUE_NOT_AUTHORIZED
+} ap_tx_ret;
+struct hostap_tx_data {
+ struct sk_buff *skb;
+ int host_encrypt;
+ struct ieee80211_crypt_data *crypt;
+ void *sta_ptr;
+};
+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
+void hostap_handle_sta_release(void *ptr);
+void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
+typedef enum {
+ AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
+} ap_rx_ret;
+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
+ struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats,
+ int wds);
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
+ struct ieee80211_crypt_data **crypt,
+ void **sta_ptr);
+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
+int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_update_rates(local_info_t *local);
+void hostap_add_wds_links(local_info_t *local);
+void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
+ int resend);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+#endif /* HOSTAP_AP_H */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
new file mode 100644
index 000000000000..6f4fa9dc308f
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -0,0 +1,435 @@
+#ifndef HOSTAP_COMMON_H
+#define HOSTAP_COMMON_H
+
+#define BIT(x) (1 << (x))
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+
+/* IEEE 802.11 defines */
+
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_CHALLENGE 16
+#define WLAN_EID_RSN 48
+#define WLAN_EID_GENERIC 221
+
+
+/* HFA384X Configuration RIDs */
+#define HFA384X_RID_CNFPORTTYPE 0xFC00
+#define HFA384X_RID_CNFOWNMACADDR 0xFC01
+#define HFA384X_RID_CNFDESIREDSSID 0xFC02
+#define HFA384X_RID_CNFOWNCHANNEL 0xFC03
+#define HFA384X_RID_CNFOWNSSID 0xFC04
+#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05
+#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06
+#define HFA384X_RID_CNFMAXDATALEN 0xFC07
+#define HFA384X_RID_CNFWDSADDRESS 0xFC08
+#define HFA384X_RID_CNFPMENABLED 0xFC09
+#define HFA384X_RID_CNFPMEPS 0xFC0A
+#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B
+#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C
+#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D
+#define HFA384X_RID_CNFOWNNAME 0xFC0E
+#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10
+#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */
+#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */
+#define HFA384X_RID_UNKNOWN1 0xFC20
+#define HFA384X_RID_UNKNOWN2 0xFC21
+#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23
+#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24
+#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25
+#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26
+#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27
+#define HFA384X_RID_CNFWEPFLAGS 0xFC28
+#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
+#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A
+#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */
+#define HFA384X_RID_CNFTXCONTROL 0xFC2C
+#define HFA384X_RID_CNFROAMINGMODE 0xFC2D
+#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */
+#define HFA384X_RID_CNFRCVCRCERROR 0xFC30
+#define HFA384X_RID_CNFMMLIFE 0xFC31
+#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32
+#define HFA384X_RID_CNFBEACONINT 0xFC33
+#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */
+#define HFA384X_RID_CNFSTAPCFINFO 0xFC35
+#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37
+#define HFA384X_RID_CNFTIMCTRL 0xFC40
+#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */
+#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */
+#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */
+#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0;
+ * write only */
+#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_GROUPADDRESSES 0xFC80
+#define HFA384X_RID_CREATEIBSS 0xFC81
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82
+#define HFA384X_RID_RTSTHRESHOLD 0xFC83
+#define HFA384X_RID_TXRATECONTROL 0xFC84
+#define HFA384X_RID_PROMISCUOUSMODE 0xFC85
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */
+#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0
+#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
+#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
+#define HFA384X_RID_CNFBASICRATES 0xFCB3
+#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4
+#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */
+#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */
+#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */
+#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */
+#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */
+#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */
+#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */
+#define HFA384X_RID_TICKTIME 0xFCE0
+#define HFA384X_RID_SCANREQUEST 0xFCE1
+#define HFA384X_RID_JOINREQUEST 0xFCE2
+#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */
+#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */
+#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */
+
+/* HFA384X Information RIDs */
+#define HFA384X_RID_MAXLOADTIME 0xFD00
+#define HFA384X_RID_DOWNLOADBUFFER 0xFD01
+#define HFA384X_RID_PRIID 0xFD02
+#define HFA384X_RID_PRISUPRANGE 0xFD03
+#define HFA384X_RID_CFIACTRANGES 0xFD04
+#define HFA384X_RID_NICSERNUM 0xFD0A
+#define HFA384X_RID_NICID 0xFD0B
+#define HFA384X_RID_MFISUPRANGE 0xFD0C
+#define HFA384X_RID_CFISUPRANGE 0xFD0D
+#define HFA384X_RID_CHANNELLIST 0xFD10
+#define HFA384X_RID_REGULATORYDOMAINS 0xFD11
+#define HFA384X_RID_TEMPTYPE 0xFD12
+#define HFA384X_RID_CIS 0xFD13
+#define HFA384X_RID_STAID 0xFD20
+#define HFA384X_RID_STASUPRANGE 0xFD21
+#define HFA384X_RID_MFIACTRANGES 0xFD22
+#define HFA384X_RID_CFIACTRANGES2 0xFD23
+#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1;
+ * only Prism2.5(?) */
+#define HFA384X_RID_PORTSTATUS 0xFD40
+#define HFA384X_RID_CURRENTSSID 0xFD41
+#define HFA384X_RID_CURRENTBSSID 0xFD42
+#define HFA384X_RID_COMMSQUALITY 0xFD43
+#define HFA384X_RID_CURRENTTXRATE 0xFD44
+#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45
+#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46
+#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47
+#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48
+#define HFA384X_RID_LONGRETRYLIMIT 0xFD49
+#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A
+#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B
+#define HFA384X_RID_CFPOLLABLE 0xFD4C
+#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D
+#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
+#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */
+#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */
+#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */
+#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */
+#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */
+#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */
+#define HFA384X_RID_PHYTYPE 0xFDC0
+#define HFA384X_RID_CURRENTCHANNEL 0xFDC1
+#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2
+#define HFA384X_RID_CCAMODE 0xFDC3
+#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6
+#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */
+#define HFA384X_RID_BUILDSEQ 0xFFFE
+#define HFA384X_RID_FWID 0xFFFF
+
+
+struct hfa384x_comp_ident
+{
+ u16 id;
+ u16 variant;
+ u16 major;
+ u16 minor;
+} __attribute__ ((packed));
+
+#define HFA384X_COMP_ID_PRI 0x15
+#define HFA384X_COMP_ID_STA 0x1f
+#define HFA384X_COMP_ID_FW_AP 0x14b
+
+struct hfa384x_sup_range
+{
+ u16 role;
+ u16 id;
+ u16 variant;
+ u16 bottom;
+ u16 top;
+} __attribute__ ((packed));
+
+
+struct hfa384x_build_id
+{
+ u16 pri_seq;
+ u16 sec_seq;
+} __attribute__ ((packed));
+
+/* FD01 - Download Buffer */
+struct hfa384x_rid_download_buffer
+{
+ u16 page;
+ u16 offset;
+ u16 length;
+} __attribute__ ((packed));
+
+/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */
+struct hfa384x_comms_quality {
+ u16 comm_qual; /* 0 .. 92 */
+ u16 signal_level; /* 27 .. 154 */
+ u16 noise_level; /* 27 .. 154 */
+} __attribute__ ((packed));
+
+
+/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
+
+/* New wireless extensions API - SET/GET convention (even ioctl numbers are
+ * root only)
+ */
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
+#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
+#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
+#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
+#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
+#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
+#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
+#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
+#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
+#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
+#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
+#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
+#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
+
+/* following are not in SIOCGIWPRIV list; check permission in the driver code
+ */
+#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
+#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
+
+
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
+enum {
+ /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_TXRATECTRL = 2,
+ PRISM2_PARAM_BEACON_INT = 3,
+ PRISM2_PARAM_PSEUDO_IBSS = 4,
+ PRISM2_PARAM_ALC = 5,
+ /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_DUMP = 7,
+ PRISM2_PARAM_OTHER_AP_POLICY = 8,
+ PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
+ PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
+ PRISM2_PARAM_DTIM_PERIOD = 11,
+ PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
+ PRISM2_PARAM_MAX_WDS = 13,
+ PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
+ PRISM2_PARAM_AP_AUTH_ALGS = 15,
+ PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
+ PRISM2_PARAM_HOST_ENCRYPT = 17,
+ PRISM2_PARAM_HOST_DECRYPT = 18,
+ /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, REMOVED 2005-08-14 */
+ /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, REMOVED 2005-08-14 */
+ PRISM2_PARAM_HOST_ROAMING = 21,
+ PRISM2_PARAM_BCRX_STA_KEY = 22,
+ PRISM2_PARAM_IEEE_802_1X = 23,
+ PRISM2_PARAM_ANTSEL_TX = 24,
+ PRISM2_PARAM_ANTSEL_RX = 25,
+ PRISM2_PARAM_MONITOR_TYPE = 26,
+ PRISM2_PARAM_WDS_TYPE = 27,
+ PRISM2_PARAM_HOSTSCAN = 28,
+ PRISM2_PARAM_AP_SCAN = 29,
+ PRISM2_PARAM_ENH_SEC = 30,
+ PRISM2_PARAM_IO_DEBUG = 31,
+ PRISM2_PARAM_BASIC_RATES = 32,
+ PRISM2_PARAM_OPER_RATES = 33,
+ PRISM2_PARAM_HOSTAPD = 34,
+ PRISM2_PARAM_HOSTAPD_STA = 35,
+ PRISM2_PARAM_WPA = 36,
+ PRISM2_PARAM_PRIVACY_INVOKED = 37,
+ PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
+ PRISM2_PARAM_DROP_UNENCRYPTED = 39,
+ PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
+};
+
+enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
+ HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
+
+
+/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
+enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
+ AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
+ AP_MAC_CMD_KICKALL = 4 };
+
+
+/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
+enum {
+ PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
+ /* Note! Old versions of prism2_srec have a fatal error in CRC-16
+ * calculation, which will corrupt all non-volatile downloads.
+ * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
+ * prevent use of old versions of prism2_srec for non-volatile
+ * download. */
+ PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
+ PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
+ /* Persistent versions of volatile download commands (keep firmware
+ * data in memory and automatically re-download after hw_reset */
+ PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
+ PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
+};
+
+struct prism2_download_param {
+ u32 dl_cmd;
+ u32 start_addr;
+ u32 num_areas;
+ struct prism2_download_area {
+ u32 addr; /* wlan card address */
+ u32 len;
+ void __user *ptr; /* pointer to data in user space */
+ } data[0];
+};
+
+#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
+#define PRISM2_MAX_DOWNLOAD_LEN 262144
+
+
+/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
+enum {
+ PRISM2_HOSTAPD_FLUSH = 1,
+ PRISM2_HOSTAPD_ADD_STA = 2,
+ PRISM2_HOSTAPD_REMOVE_STA = 3,
+ PRISM2_HOSTAPD_GET_INFO_STA = 4,
+ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
+ PRISM2_SET_ENCRYPTION = 6,
+ PRISM2_GET_ENCRYPTION = 7,
+ PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
+ PRISM2_HOSTAPD_GET_RID = 9,
+ PRISM2_HOSTAPD_SET_RID = 10,
+ PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
+ PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+ PRISM2_HOSTAPD_MLME = 13,
+ PRISM2_HOSTAPD_SCAN_REQ = 14,
+ PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
+};
+
+#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
+#define PRISM2_HOSTAPD_RID_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+
+/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
+ */
+#define HOSTAP_CRYPT_ALG_NAME_LEN 16
+
+
+struct prism2_hostapd_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u16 aid;
+ u16 capability;
+ u8 tx_supp_rates;
+ } add_sta;
+ struct {
+ u32 inactive_sec;
+ } get_info_sta;
+ struct {
+ u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
+ u32 flags;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+ struct {
+ u32 flags_and;
+ u32 flags_or;
+ } set_flags_sta;
+ struct {
+ u16 rid;
+ u16 len;
+ u8 data[0];
+ } rid;
+ struct {
+ u8 len;
+ u8 data[0];
+ } generic_elem;
+ struct {
+#define MLME_STA_DEAUTH 0
+#define MLME_STA_DISASSOC 1
+ u16 cmd;
+ u16 reason_code;
+ } mlme;
+ struct {
+ u8 ssid_len;
+ u8 ssid[32];
+ } scan_req;
+ } u;
+};
+
+#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
+#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
+
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
+#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
+#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
+
+
+#endif /* HOSTAP_COMMON_H */
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
new file mode 100644
index 000000000000..7ed3425d08c1
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -0,0 +1,55 @@
+#ifndef HOSTAP_CONFIG_H
+#define HOSTAP_CONFIG_H
+
+#define PRISM2_VERSION "0.4.4-kernel"
+
+/* In the previous versions of Host AP driver, support for user space version
+ * of IEEE 802.11 management (hostapd) used to be disabled in the default
+ * configuration. From now on, support for hostapd is always included and it is
+ * possible to disable kernel driver version of IEEE 802.11 management with a
+ * separate define, PRISM2_NO_KERNEL_IEEE80211_MGMT. */
+/* #define PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+/* Maximum number of events handler per one interrupt */
+#define PRISM2_MAX_INTERRUPT_EVENTS 20
+
+/* Include code for downloading firmware images into volatile RAM. */
+#define PRISM2_DOWNLOAD_SUPPORT
+
+/* Allow kernel configuration to enable download support. */
+#if !defined(PRISM2_DOWNLOAD_SUPPORT) && defined(CONFIG_HOSTAP_FIRMWARE)
+#define PRISM2_DOWNLOAD_SUPPORT
+#endif
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+/* Allow writing firmware images into flash, i.e., to non-volatile storage.
+ * Before you enable this option, you should make absolutely sure that you are
+ * using prism2_srec utility that comes with THIS version of the driver!
+ * In addition, please note that it is possible to kill your card with
+ * non-volatile download if you are using incorrect image. This feature has not
+ * been fully tested, so please be careful with it. */
+/* #define PRISM2_NON_VOLATILE_DOWNLOAD */
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+/* Save low-level I/O for debugging. This should not be enabled in normal use.
+ */
+/* #define PRISM2_IO_DEBUG */
+
+/* Following defines can be used to remove unneeded parts of the driver, e.g.,
+ * to limit the size of the kernel module. Definitions can be added here in
+ * hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
+ * e.g.,
+ * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
+ */
+
+/* Do not include debug messages into the driver */
+/* #define PRISM2_NO_DEBUG */
+
+/* Do not include /proc/net/prism2/wlan#/{registers,debug} */
+/* #define PRISM2_NO_PROCFS_DEBUG */
+
+/* Do not include station functionality (i.e., allow only Master (Host AP) mode
+ */
+/* #define PRISM2_NO_STATION_MODES */
+
+#endif /* HOSTAP_CONFIG_H */
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
new file mode 100644
index 000000000000..faa83badf0a1
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -0,0 +1,1030 @@
+#define PRISM2_PCCARD
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static dev_info_t dev_info = "hostap_cs";
+static dev_link_t *dev_list = NULL;
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
+ "cards (PC Card).");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+static int ignore_cis_vcc;
+module_param(ignore_cis_vcc, int, 0444);
+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;
+ int sandisk_connectplus;
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ outb(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ v = inb(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ outw(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ v = inw(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
+ outsw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline void hfa384x_insw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
+ insw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
+
+#else /* PRISM2_IO_DEBUG */
+
+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
+#define HFA384X_INB(a) inb(dev->base_addr + (a))
+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
+#define HFA384X_INW(a) inw(dev->base_addr + (a))
+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_INSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_OUTSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+
+
+static void prism2_detach(dev_link_t *link);
+static void prism2_release(u_long arg);
+static int prism2_event(event_t event, int priority,
+ event_callback_args_t *args);
+
+
+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)))
+ return 1;
+ return 0;
+}
+
+
+/*
+ * SanDisk CompactFlash WLAN Flashcard - Product Manual v1.0
+ * Document No. 20-10-00058, January 2004
+ * http://www.sandisk.com/pdf/industrial/ProdManualCFWLANv1.0.pdf
+ */
+#define SANDISK_WLAN_ACTIVATION_OFF 0x40
+#define SANDISK_HCR_OFF 0x42
+
+
+static void sandisk_set_iobase(local_info_t *local)
+{
+ int res;
+ conf_reg_t reg;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ reg.Function = 0;
+ 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,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
+ " res=%d\n", res);
+ }
+ udelay(10);
+
+ reg.Function = 0;
+ 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,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
+ " res=%d\n", res);
+ }
+}
+
+
+static void sandisk_write_hcr(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+ int i;
+
+ HFA384X_OUTB(0x80, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(50);
+ for (i = 0; i < 10; i++) {
+ HFA384X_OUTB(hcr, SANDISK_HCR_OFF);
+ }
+ udelay(55);
+ HFA384X_OUTB(0x45, SANDISK_WLAN_ACTIVATION_OFF);
+}
+
+
+static int sandisk_enable_wireless(struct net_device *dev)
+{
+ int res, ret = 0;
+ conf_reg_t reg;
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ tuple_t tuple;
+ cisparse_t *parse = NULL;
+ u_char buf[64];
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (hw_priv->link->io.NumPorts1 < 0x42) {
+ /* Not enough ports to be SanDisk multi-function card */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
+ if (parse == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ tuple.DesiredTuple = CISTPL_MANFID;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ 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) ||
+ parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
+ /* No SanDisk manfid found */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ 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) ||
+ parse->longlink_mfc.nfn < 2) {
+ /* No multi-function links found */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ printk(KERN_DEBUG "%s: Multi-function SanDisk ConnectPlus detected"
+ " - using vendor-specific initialization\n", dev->name);
+ hw_priv->sandisk_connectplus = 1;
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
+ dev->name, res);
+ goto done;
+ }
+ mdelay(5);
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ /*
+ * Do not enable interrupts here to avoid some bogus events. Interrupts
+ * 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,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
+ dev->name, res);
+ goto done;
+ }
+ mdelay(5);
+
+ sandisk_set_iobase(local);
+
+ HFA384X_OUTB(0xc5, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(10);
+ HFA384X_OUTB(0x4b, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(10);
+
+done:
+ kfree(parse);
+ return ret;
+}
+
+
+static void prism2_pccard_cor_sreset(local_info_t *local)
+{
+ int res;
+ conf_reg_t reg;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (!prism2_pccard_card_present(local))
+ return;
+
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ reg.Value = 0;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
+ res);
+ return;
+ }
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n",
+ reg.Value);
+
+ reg.Action = CS_WRITE;
+ reg.Value |= COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
+ res);
+ return;
+ }
+
+ mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
+
+ reg.Value &= ~COR_SOFT_RESET;
+ if (hw_priv->sandisk_connectplus)
+ reg.Value |= COR_IREQ_ENA;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
+ res);
+ return;
+ }
+
+ mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
+
+ if (hw_priv->sandisk_connectplus)
+ sandisk_set_iobase(local);
+}
+
+
+static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
+{
+ int res;
+ conf_reg_t reg;
+ int old_cor;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (!prism2_pccard_card_present(local))
+ return;
+
+ if (hw_priv->sandisk_connectplus) {
+ sandisk_write_hcr(local, hcr);
+ return;
+ }
+
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ reg.Value = 0;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
+ "(%d)\n", res);
+ return;
+ }
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset: original COR %02x\n",
+ reg.Value);
+ old_cor = reg.Value;
+
+ reg.Action = CS_WRITE;
+ reg.Value |= COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
+ "(%d)\n", res);
+ return;
+ }
+
+ mdelay(10);
+
+ /* Setup Genesis mode */
+ reg.Action = CS_WRITE;
+ reg.Value = hcr;
+ reg.Offset = CISREG_CCSR;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
+ "(%d)\n", res);
+ return;
+ }
+ mdelay(10);
+
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = old_cor & ~COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
+ "(%d)\n", res);
+ return;
+ }
+
+ mdelay(10);
+}
+
+
+static int prism2_pccard_dev_open(local_info_t *local)
+{
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+ hw_priv->link->open++;
+ return 0;
+}
+
+
+static int prism2_pccard_dev_close(local_info_t *local)
+{
+ struct hostap_cs_priv *hw_priv;
+
+ if (local == NULL || local->hw_priv == NULL)
+ return 1;
+ hw_priv = local->hw_priv;
+ if (hw_priv->link == NULL)
+ return 1;
+
+ if (!hw_priv->link->open) {
+ printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
+ "link not open?!\n", local->dev->name);
+ return 1;
+ }
+
+ hw_priv->link->open--;
+
+ return 0;
+}
+
+
+static struct prism2_helper_functions prism2_pccard_funcs =
+{
+ .card_present = prism2_pccard_card_present,
+ .cor_sreset = prism2_pccard_cor_sreset,
+ .dev_open = prism2_pccard_dev_open,
+ .dev_close = prism2_pccard_dev_close,
+ .genesis_reset = prism2_pccard_genesis_reset,
+ .hw_type = HOSTAP_HW_PCCARD,
+};
+
+
+/* allocate local data and register with CardServices
+ * initialize dev_link structure, but do not configure the card yet */
+static dev_link_t *prism2_attach(void)
+{
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret;
+
+ link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
+ if (link == NULL)
+ return NULL;
+
+ memset(link, 0, sizeof(dev_link_t));
+
+ PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
+ link->conf.Vcc = 33;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* register with CardServices */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ prism2_detach(link);
+ return NULL;
+ }
+ return link;
+}
+
+
+static void prism2_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+
+ PDEBUG(DEBUG_FLOW, "prism2_detach\n");
+
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+ if (*linkp == NULL) {
+ printk(KERN_WARNING "%s: Attempt to detach non-existing "
+ "PCMCIA client\n", dev_info);
+ return;
+ }
+
+ if (link->state & DEV_CONFIG) {
+ prism2_release((u_long)link);
+ }
+
+ if (link->handle) {
+ int res = pcmcia_deregister_client(link->handle);
+ if (res) {
+ printk("CardService(DeregisterClient) => %d\n", res);
+ cs_error(link->handle, DeregisterClient, res);
+ }
+ }
+
+ *linkp = link->next;
+ /* release net devices */
+ if (link->priv) {
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ dev = link->priv;
+ iface = netdev_priv(dev);
+ kfree(iface->local->hw_priv);
+ iface->local->hw_priv = NULL;
+ prism2_free_local_data(dev);
+ }
+ kfree(link);
+}
+
+
+#define CS_CHECK(fn, ret) \
+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+#define CFG_CHECK2(fn, retf) \
+do { int ret = (retf); \
+if (ret != 0) { \
+ PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
+ cs_error(link->handle, fn, ret); \
+ goto next_entry; \
+} \
+} while (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)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 1;
+ 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 };
+ struct hostap_cs_priv *hw_priv;
+
+ PDEBUG(DEBUG_FLOW, "prism2_config()\n");
+
+ parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
+ hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (parse == NULL || hw_priv == NULL) {
+ kfree(parse);
+ kfree(hw_priv);
+ ret = -ENOMEM;
+ goto failed;
+ }
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ 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));
+ 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;
+
+ /* 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));
+ for (;;) {
+ cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
+ CFG_CHECK2(GetTupleData,
+ pcmcia_get_tuple_data(link->handle, &tuple));
+ CFG_CHECK2(ParseTuple,
+ pcmcia_parse_tuple(link->handle, &tuple, parse));
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ if (cfg->index == 0)
+ goto next_entry;
+ link->conf.ConfigIndex = cfg->index;
+ PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
+ "(default 0x%02X)\n", cfg->index, dflt.index);
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* 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)) {
+ if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !ignore_cis_vcc) {
+ PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
+ " this entry\n");
+ goto next_entry;
+ }
+ } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
+ 10000 && !ignore_cis_vcc) {
+ PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
+ "- skipping this entry\n");
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+ else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) {
+ /* At least Compaq WL200 does not have IRQInfo1 set,
+ * but it does not work without interrupts.. */
+ printk("Config has no IRQ info, but trying to enable "
+ "IRQ anyway..\n");
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+ }
+
+ /* IO window settings */
+ PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
+ "dflt.io.nwin=%d\n",
+ cfg->io.nwin, dflt.io.nwin);
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
+ "io.base=0x%04x, len=%d\n", io->flags,
+ io->win[0].base, io->win[0].len);
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.IOAddrLines = io->flags &
+ CISTPL_IO_LINES_MASK;
+ link->io.BasePort1 = io->win[0].base;
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 = link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ link->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ CFG_CHECK2(RequestIO,
+ pcmcia_request_io(link->handle, &link->io));
+
+ /* This configuration table entry is OK */
+ break;
+
+ next_entry:
+ CS_CHECK(GetNextTuple,
+ pcmcia_get_next_tuple(link->handle, &tuple));
+ }
+
+ /* Need to allocate net_device before requesting IRQ handler */
+ dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
+ &handle_to_dev(link->handle));
+ if (dev == NULL)
+ goto failed;
+ link->priv = dev;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ hw_priv->link = link;
+ strcpy(hw_priv->node.dev_name, dev->name);
+ link->dev = &hw_priv->node;
+
+ /*
+ * 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) {
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Handler = prism2_interrupt;
+ link->irq.Instance = dev;
+ CS_CHECK(RequestIRQ,
+ pcmcia_request_irq(link->handle, &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));
+
+ 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);
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ printk(", irq %d", link->irq.AssignedIRQ);
+ if (link->io.NumPorts1)
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+ link->io.BasePort1+link->io.NumPorts1-1);
+ if (link->io.NumPorts2)
+ printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+ 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);
+
+ ret = prism2_hw_config(dev, 1);
+ if (!ret) {
+ ret = hostap_hw_ready(dev);
+ if (ret == 0 && local->ddev)
+ strcpy(hw_priv->node.dev_name, local->ddev->name);
+ }
+ kfree(parse);
+ return ret;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+ kfree(parse);
+ kfree(hw_priv);
+ prism2_release((u_long)link);
+ return ret;
+}
+
+
+static void prism2_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+
+ PDEBUG(DEBUG_FLOW, "prism2_release\n");
+
+ if (link->priv) {
+ struct net_device *dev = link->priv;
+ struct hostap_interface *iface;
+
+ iface = netdev_priv(dev);
+ if (link->state & DEV_CONFIG)
+ 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;
+
+ PDEBUG(DEBUG_FLOW, "release - done\n");
+}
+
+
+static int prism2_event(event_t event, int priority,
+ event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ struct net_device *dev = (struct net_device *) link->priv;
+
+ switch (event) {
+ case CS_EVENT_CARD_INSERTION:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info);
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ if (prism2_config(link)) {
+ PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+ }
+ break;
+
+ case CS_EVENT_CARD_REMOVAL:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ prism2_release((u_long) link);
+ }
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+ link->state |= DEV_SUSPEND;
+ /* fall through */
+
+ case CS_EVENT_RESET_PHYSICAL:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
+ if (link->state & DEV_CONFIG) {
+ if (link->open) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+ prism2_suspend(dev);
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+ link->state &= ~DEV_SUSPEND;
+ /* fall through */
+
+ case CS_EVENT_CARD_RESET:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle,
+ &link->conf);
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, link->open ? 0 : 1);
+ if (link->open) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ }
+ }
+ break;
+
+ default:
+ PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
+ dev_info, event);
+ break;
+ }
+ return 0;
+}
+
+
+static struct pcmcia_device_id hostap_cs_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
+ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777),
+ PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000),
+ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b),
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612),
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001),
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001),
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
+ PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
+ 0x7a954bd9, 0x74be00c6),
+ PCMCIA_DEVICE_PROD_ID1234(
+ "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P",
+ "Eval-RevA",
+ 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e),
+ PCMCIA_DEVICE_PROD_ID123(
+ "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
+ 0xe6ec52ce, 0x08649af2, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02",
+ 0x71b18589, 0xb6f1b0ab, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "Instant Wireless ", " Network PC CARD", "Version 01.02",
+ 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "SMC", "SMC2632W", "Version 01.02",
+ 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G",
+ 0x2decece3, 0x82067c18),
+ PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card",
+ 0x54f7c49c, 0x15a75e5b),
+ PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE",
+ 0x74c5e40d, 0xdb472a18),
+ PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card",
+ 0x0733cc81, 0x0c52f395),
+ PCMCIA_DEVICE_PROD_ID12(
+ "ZoomAir 11Mbps High", "Rate wireless Networking",
+ 0x273fe3db, 0x32a1eaee),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
+
+
+static struct pcmcia_driver hostap_driver = {
+ .drv = {
+ .name = "hostap_cs",
+ },
+ .attach = prism2_attach,
+ .detach = prism2_detach,
+ .owner = THIS_MODULE,
+ .event = prism2_event,
+ .id_table = hostap_cs_ids,
+};
+
+static int __init init_prism2_pccard(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+ return pcmcia_register_driver(&hostap_driver);
+}
+
+static void __exit exit_prism2_pccard(void)
+{
+ pcmcia_unregister_driver(&hostap_driver);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_pccard);
+module_exit(exit_prism2_pccard);
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
new file mode 100644
index 000000000000..ab26b52b3e76
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -0,0 +1,766 @@
+static int prism2_enable_aux_port(struct net_device *dev, int enable)
+{
+ u16 val, reg;
+ int i, tries;
+ unsigned long flags;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ if (enable) {
+ PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
+ "port is already enabled\n", dev->name);
+ }
+ return 0;
+ }
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+
+ /* wait until busy bit is clear */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+ printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
+ dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ val = HFA384X_INW(HFA384X_CONTROL_OFF);
+
+ if (enable) {
+ HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
+
+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
+ printk("prism2_enable_aux_port: was not disabled!?\n");
+ val &= ~HFA384X_AUX_PORT_MASK;
+ val |= HFA384X_AUX_PORT_ENABLE;
+ } else {
+ HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+
+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
+ printk("prism2_enable_aux_port: was not enabled!?\n");
+ val &= ~HFA384X_AUX_PORT_MASK;
+ val |= HFA384X_AUX_PORT_DISABLE;
+ }
+ HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
+
+ udelay(5);
+
+ i = 10000;
+ while (i > 0) {
+ val = HFA384X_INW(HFA384X_CONTROL_OFF);
+ val &= HFA384X_AUX_PORT_MASK;
+
+ if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
+ (!enable && val == HFA384X_AUX_PORT_DISABLED))
+ break;
+
+ udelay(10);
+ i--;
+ }
+
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (i == 0) {
+ printk("prism2_enable_aux_port(%d) timed out\n",
+ enable);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+
+static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
+ void *buf)
+{
+ u16 page, offset;
+ if (addr & 1 || len & 1)
+ return -1;
+
+ page = addr >> 7;
+ offset = addr & 0x7f;
+
+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
+
+ udelay(5);
+
+#ifdef PRISM2_PCI
+ {
+ u16 *pos = (u16 *) buf;
+ while (len > 0) {
+ *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
+ len -= 2;
+ }
+ }
+#else /* PRISM2_PCI */
+ HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
+#endif /* PRISM2_PCI */
+
+ return 0;
+}
+
+
+static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
+ void *buf)
+{
+ u16 page, offset;
+ if (addr & 1 || len & 1)
+ return -1;
+
+ page = addr >> 7;
+ offset = addr & 0x7f;
+
+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
+
+ udelay(5);
+
+#ifdef PRISM2_PCI
+ {
+ u16 *pos = (u16 *) buf;
+ while (len > 0) {
+ HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
+ len -= 2;
+ }
+ }
+#else /* PRISM2_PCI */
+ HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
+#endif /* PRISM2_PCI */
+
+ return 0;
+}
+
+
+static int prism2_pda_ok(u8 *buf)
+{
+ u16 *pda = (u16 *) buf;
+ int pos;
+ u16 len, pdr;
+
+ if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
+ buf[3] == 0x00)
+ return 0;
+
+ pos = 0;
+ while (pos + 1 < PRISM2_PDA_SIZE / 2) {
+ len = le16_to_cpu(pda[pos]);
+ pdr = le16_to_cpu(pda[pos + 1]);
+ if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
+ return 0;
+
+ if (pdr == 0x0000 && len == 2) {
+ /* PDA end found */
+ return 1;
+ }
+
+ pos += len + 1;
+ }
+
+ return 0;
+}
+
+
+static int prism2_download_aux_dump(struct net_device *dev,
+ unsigned int addr, int len, u8 *buf)
+{
+ int res;
+
+ prism2_enable_aux_port(dev, 1);
+ res = hfa384x_from_aux(dev, addr, len, buf);
+ prism2_enable_aux_port(dev, 0);
+ if (res)
+ return -1;
+
+ return 0;
+}
+
+
+static u8 * prism2_read_pda(struct net_device *dev)
+{
+ u8 *buf;
+ int res, i, found = 0;
+#define NUM_PDA_ADDRS 4
+ unsigned int pda_addr[NUM_PDA_ADDRS] = {
+ 0x7f0000 /* others than HFA3841 */,
+ 0x3f0000 /* HFA3841 */,
+ 0x390000 /* apparently used in older cards */,
+ 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
+ };
+
+ buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
+ if (buf == NULL)
+ return NULL;
+
+ /* Note: wlan card should be in initial state (just after init cmd)
+ * and no other operations should be performed concurrently. */
+
+ prism2_enable_aux_port(dev, 1);
+
+ for (i = 0; i < NUM_PDA_ADDRS; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
+ dev->name, pda_addr[i]);
+ res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
+ if (res)
+ continue;
+ if (res == 0 && prism2_pda_ok(buf)) {
+ PDEBUG2(DEBUG_EXTRA2, ": OK\n");
+ found = 1;
+ break;
+ } else {
+ PDEBUG2(DEBUG_EXTRA2, ": failed\n");
+ }
+ }
+
+ prism2_enable_aux_port(dev, 0);
+
+ if (!found) {
+ printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
+ kfree(buf);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+
+static int prism2_download_volatile(local_info_t *local,
+ struct prism2_download_data *param)
+{
+ struct net_device *dev = local->dev;
+ int ret = 0, i;
+ u16 param0, param1;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -1;
+ }
+
+ local->hw_downloading = 1;
+ if (local->pri_only) {
+ hfa384x_disable_interrupts(dev);
+ } else {
+ prism2_hw_shutdown(dev, 0);
+
+ if (prism2_hw_init(dev, 0)) {
+ printk(KERN_WARNING "%s: Could not initialize card for"
+ " download\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_WARNING "%s: Could not enable AUX port\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ param0 = param->start_addr & 0xffff;
+ param1 = param->start_addr >> 16;
+
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
+ param0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
+ dev->name, param->data[i].len, param->data[i].addr);
+ if (hfa384x_to_aux(dev, param->data[i].addr,
+ param->data[i].len, param->data[i].data)) {
+ printk(KERN_WARNING "%s: RAM download at 0x%08x "
+ "(len=%d) failed\n", dev->name,
+ param->data[i].addr, param->data[i].len);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_DISABLE << 8), param0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+ /* ProgMode disable causes the hardware to restart itself from the
+ * given starting address. Give hw some time and ACK command just in
+ * case restart did not happen. */
+ mdelay(5);
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
+ dev->name);
+ /* continue anyway.. restart should have taken care of this */
+ }
+
+ mdelay(5);
+ local->hw_downloading = 0;
+ if (prism2_hw_config(dev, 2)) {
+ printk(KERN_WARNING "%s: Card configuration after RAM "
+ "download failed\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+
+
+static int prism2_enable_genesis(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+ u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
+ u8 readbuf[4];
+
+ printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
+ dev->name, hcr);
+ local->func->cor_sreset(local);
+ hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
+ local->func->genesis_reset(local, hcr);
+
+ /* Readback test */
+ hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
+ hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
+ hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
+
+ if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
+ printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
+ hcr);
+ return 0;
+ } else {
+ printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
+ "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
+ hcr, initseq[0], initseq[1], initseq[2], initseq[3],
+ readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
+ return 1;
+ }
+}
+
+
+static int prism2_get_ram_size(local_info_t *local)
+{
+ int ret;
+
+ /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
+ if (prism2_enable_genesis(local, 0x1f) == 0)
+ ret = 8;
+ else if (prism2_enable_genesis(local, 0x0f) == 0)
+ ret = 16;
+ else
+ ret = -1;
+
+ /* Disable genesis mode */
+ local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
+
+ return ret;
+}
+
+
+static int prism2_download_genesis(local_info_t *local,
+ struct prism2_download_data *param)
+{
+ struct net_device *dev = local->dev;
+ int ram16 = 0, i;
+ int ret = 0;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -EBUSY;
+ }
+
+ if (!local->func->genesis_reset || !local->func->cor_sreset) {
+ printk(KERN_INFO "%s: Genesis mode downloading not supported "
+ "with this hwmodel\n", dev->name);
+ return -EOPNOTSUPP;
+ }
+
+ local->hw_downloading = 1;
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_DEBUG "%s: failed to enable AUX port\n",
+ dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (local->sram_type == -1) {
+ /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
+ if (prism2_enable_genesis(local, 0x1f) == 0) {
+ ram16 = 0;
+ PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
+ "SRAM\n", dev->name);
+ } else if (prism2_enable_genesis(local, 0x0f) == 0) {
+ ram16 = 1;
+ PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
+ "SRAM\n", dev->name);
+ } else {
+ printk(KERN_DEBUG "%s: Could not initiate genesis "
+ "mode\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+ } else {
+ if (prism2_enable_genesis(local, local->sram_type == 8 ?
+ 0x1f : 0x0f)) {
+ printk(KERN_DEBUG "%s: Failed to set Genesis "
+ "mode (sram_type=%d)\n", dev->name,
+ local->sram_type);
+ ret = -EIO;
+ goto out;
+ }
+ ram16 = local->sram_type != 8;
+ }
+
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
+ dev->name, param->data[i].len, param->data[i].addr);
+ if (hfa384x_to_aux(dev, param->data[i].addr,
+ param->data[i].len, param->data[i].data)) {
+ printk(KERN_WARNING "%s: RAM download at 0x%08x "
+ "(len=%d) failed\n", dev->name,
+ param->data[i].addr, param->data[i].len);
+ ret = -EIO;
+ goto out;
+ }
+ }
+
+ PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
+ local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
+ dev->name);
+ }
+
+ mdelay(5);
+ local->hw_downloading = 0;
+
+ PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
+ /*
+ * Make sure the INIT command does not generate a command completion
+ * event by disabling interrupts.
+ */
+ hfa384x_disable_interrupts(dev);
+ if (prism2_hw_init(dev, 1)) {
+ printk(KERN_DEBUG "%s: Initialization after genesis mode "
+ "download failed\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
+ if (prism2_hw_init2(dev, 1)) {
+ printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
+ "download failed\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+
+
+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
+/* Note! Non-volatile downloading functionality has not yet been tested
+ * thoroughly and it may corrupt flash image and effectively kill the card that
+ * is being updated. You have been warned. */
+
+static inline int prism2_download_block(struct net_device *dev,
+ u32 addr, u8 *data,
+ u32 bufaddr, int rest_len)
+{
+ u16 param0, param1;
+ int block_len;
+
+ block_len = rest_len < 4096 ? rest_len : 4096;
+
+ param0 = addr & 0xffff;
+ param1 = addr >> 16;
+
+ HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
+ param0)) {
+ printk(KERN_WARNING "%s: Flash download command execution "
+ "failed\n", dev->name);
+ return -1;
+ }
+
+ if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
+ printk(KERN_WARNING "%s: flash download at 0x%08x "
+ "(len=%d) failed\n", dev->name, addr, block_len);
+ return -1;
+ }
+
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
+ 0)) {
+ printk(KERN_WARNING "%s: Flash write command execution "
+ "failed\n", dev->name);
+ return -1;
+ }
+
+ return block_len;
+}
+
+
+static int prism2_download_nonvolatile(local_info_t *local,
+ struct prism2_download_data *dl)
+{
+ struct net_device *dev = local->dev;
+ int ret = 0, i;
+ struct {
+ u16 page;
+ u16 offset;
+ u16 len;
+ } dlbuffer;
+ u32 bufaddr;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -1;
+ }
+
+ ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
+ &dlbuffer, 6, 0);
+
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: Could not read download buffer "
+ "parameters\n", dev->name);
+ goto out;
+ }
+
+ dlbuffer.page = le16_to_cpu(dlbuffer.page);
+ dlbuffer.offset = le16_to_cpu(dlbuffer.offset);
+ dlbuffer.len = le16_to_cpu(dlbuffer.len);
+
+ printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
+ dlbuffer.len, dlbuffer.page, dlbuffer.offset);
+
+ bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
+
+ local->hw_downloading = 1;
+
+ if (!local->pri_only) {
+ prism2_hw_shutdown(dev, 0);
+
+ if (prism2_hw_init(dev, 0)) {
+ printk(KERN_WARNING "%s: Could not initialize card for"
+ " download\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ hfa384x_disable_interrupts(dev);
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_WARNING "%s: Could not enable AUX port\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
+ for (i = 0; i < dl->num_areas; i++) {
+ int rest_len = dl->data[i].len;
+ int data_off = 0;
+
+ while (rest_len > 0) {
+ int block_len;
+
+ block_len = prism2_download_block(
+ dev, dl->data[i].addr + data_off,
+ dl->data[i].data + data_off, bufaddr,
+ rest_len);
+
+ if (block_len < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ rest_len -= block_len;
+ data_off += block_len;
+ }
+ }
+
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_DISABLE << 8), 0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
+ dev->name);
+ /* continue anyway.. restart should have taken care of this */
+ }
+
+ mdelay(5);
+
+ local->func->hw_reset(dev);
+ local->hw_downloading = 0;
+ if (prism2_hw_config(dev, 2)) {
+ printk(KERN_WARNING "%s: Card configuration after flash "
+ "download failed\n", dev->name);
+ ret = -1;
+ } else {
+ printk(KERN_INFO "%s: Card initialized successfully after "
+ "flash download\n", dev->name);
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
+
+
+static void prism2_download_free_data(struct prism2_download_data *dl)
+{
+ int i;
+
+ if (dl == NULL)
+ return;
+
+ for (i = 0; i < dl->num_areas; i++)
+ kfree(dl->data[i].data);
+ kfree(dl);
+}
+
+
+static int prism2_download(local_info_t *local,
+ struct prism2_download_param *param)
+{
+ int ret = 0;
+ int i;
+ u32 total_len = 0;
+ struct prism2_download_data *dl = NULL;
+
+ printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
+ "num_areas=%d\n",
+ param->dl_cmd, param->start_addr, param->num_areas);
+
+ if (param->num_areas > 100) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dl = kmalloc(sizeof(*dl) + param->num_areas *
+ sizeof(struct prism2_download_data_area), GFP_KERNEL);
+ if (dl == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memset(dl, 0, sizeof(*dl) + param->num_areas *
+ sizeof(struct prism2_download_data_area));
+ dl->dl_cmd = param->dl_cmd;
+ dl->start_addr = param->start_addr;
+ dl->num_areas = param->num_areas;
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2,
+ " area %d: addr=0x%08x len=%d ptr=0x%p\n",
+ i, param->data[i].addr, param->data[i].len,
+ param->data[i].ptr);
+
+ dl->data[i].addr = param->data[i].addr;
+ dl->data[i].len = param->data[i].len;
+
+ total_len += param->data[i].len;
+ if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
+ total_len > PRISM2_MAX_DOWNLOAD_LEN) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
+ if (dl->data[i].data == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(dl->data[i].data, param->data[i].ptr,
+ param->data[i].len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+
+ switch (param->dl_cmd) {
+ case PRISM2_DOWNLOAD_VOLATILE:
+ case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
+ ret = prism2_download_volatile(local, dl);
+ break;
+ case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
+ case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
+ ret = prism2_download_genesis(local, dl);
+ break;
+ case PRISM2_DOWNLOAD_NON_VOLATILE:
+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
+ ret = prism2_download_nonvolatile(local, dl);
+#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
+ printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
+ local->dev->name);
+ ret = -EOPNOTSUPP;
+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
+ break;
+ default:
+ printk(KERN_DEBUG "%s: unsupported download command %d\n",
+ local->dev->name, param->dl_cmd);
+ ret = -EINVAL;
+ break;
+ };
+
+ out:
+ if (ret == 0 && dl &&
+ param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
+ prism2_download_free_data(local->dl_pri);
+ local->dl_pri = dl;
+ } else if (ret == 0 && dl &&
+ param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
+ prism2_download_free_data(local->dl_sec);
+ local->dl_sec = dl;
+ } else
+ prism2_download_free_data(dl);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
new file mode 100644
index 000000000000..e533a663deda
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -0,0 +1,3445 @@
+/*
+ * Host AP (software wireless LAN access point) driver for
+ * Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ *
+ * FIX:
+ * - there is currently no way of associating TX packets to correct wds device
+ * when TX Exc/OK event occurs, so all tx_packets and some
+ * tx_errors/tx_dropped are added to the main netdevice; using sw_support
+ * field in txdesc might be used to fix this (using Alloc event to increment
+ * tx_packets would need some further info in txfid table)
+ *
+ * Buffer Access Path (BAP) usage:
+ * Prism2 cards have two separate BAPs for accessing the card memory. These
+ * should allow concurrent access to two different frames and the driver
+ * previously used BAP0 for sending data and BAP1 for receiving data.
+ * However, there seems to be number of issues with concurrent access and at
+ * least one know hardware bug in using BAP0 and BAP1 concurrently with PCI
+ * Prism2.5. Therefore, the driver now only uses BAP0 for moving data between
+ * host and card memories. BAP0 accesses are protected with local->baplock
+ * (spin_lock_bh) to prevent concurrent use.
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211_crypt.h>
+#include <asm/irq.h>
+
+#include "hostap_80211.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+
+/* #define final_version */
+
+static int mtu = 1500;
+module_param(mtu, int, 0444);
+MODULE_PARM_DESC(mtu, "Maximum transfer unit");
+
+static int channel[MAX_PARM_DEVICES] = { 3, DEF_INTS };
+module_param_array(channel, int, NULL, 0444);
+MODULE_PARM_DESC(channel, "Initial channel");
+
+static char essid[33] = "test";
+module_param_string(essid, essid, sizeof(essid), 0444);
+MODULE_PARM_DESC(essid, "Host AP's ESSID");
+
+static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS };
+module_param_array(iw_mode, int, NULL, 0444);
+MODULE_PARM_DESC(iw_mode, "Initial operation mode");
+
+static int beacon_int[MAX_PARM_DEVICES] = { 100, DEF_INTS };
+module_param_array(beacon_int, int, NULL, 0444);
+MODULE_PARM_DESC(beacon_int, "Beacon interval (1 = 1024 usec)");
+
+static int dtim_period[MAX_PARM_DEVICES] = { 1, DEF_INTS };
+module_param_array(dtim_period, int, NULL, 0444);
+MODULE_PARM_DESC(dtim_period, "DTIM period");
+
+static char dev_template[16] = "wlan%d";
+module_param_string(dev_template, dev_template, sizeof(dev_template), 0444);
+MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: "
+ "wlan%d)");
+
+#ifdef final_version
+#define EXTRA_EVENTS_WTERR 0
+#else
+/* check WTERR events (Wait Time-out) in development versions */
+#define EXTRA_EVENTS_WTERR HFA384X_EV_WTERR
+#endif
+
+/* Events that will be using BAP0 */
+#define HFA384X_BAP0_EVENTS \
+ (HFA384X_EV_TXEXC | HFA384X_EV_RX | HFA384X_EV_INFO | HFA384X_EV_TX)
+
+/* event mask, i.e., events that will result in an interrupt */
+#define HFA384X_EVENT_MASK \
+ (HFA384X_BAP0_EVENTS | HFA384X_EV_ALLOC | HFA384X_EV_INFDROP | \
+ HFA384X_EV_CMD | HFA384X_EV_TICK | \
+ EXTRA_EVENTS_WTERR)
+
+/* Default TX control flags: use 802.11 headers and request interrupt for
+ * failed transmits. Frames that request ACK callback, will add
+ * _TX_OK flag and _ALT_RTRY flag may be used to select different retry policy.
+ */
+#define HFA384X_TX_CTRL_FLAGS \
+ (HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX)
+
+
+/* ca. 1 usec */
+#define HFA384X_CMD_BUSY_TIMEOUT 5000
+#define HFA384X_BAP_BUSY_TIMEOUT 50000
+
+/* ca. 10 usec */
+#define HFA384X_CMD_COMPL_TIMEOUT 20000
+#define HFA384X_DL_COMPL_TIMEOUT 1000000
+
+/* Wait times for initialization; yield to other processes to avoid busy
+ * waiting for long time. */
+#define HFA384X_INIT_TIMEOUT (HZ / 2) /* 500 ms */
+#define HFA384X_ALLOC_COMPL_TIMEOUT (HZ / 20) /* 50 ms */
+
+
+static void prism2_hw_reset(struct net_device *dev);
+static void prism2_check_sta_fw_version(local_info_t *local);
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+/* hostap_download.c */
+static int prism2_download_aux_dump(struct net_device *dev,
+ unsigned int addr, int len, u8 *buf);
+static u8 * prism2_read_pda(struct net_device *dev);
+static int prism2_download(local_info_t *local,
+ struct prism2_download_param *param);
+static void prism2_download_free_data(struct prism2_download_data *dl);
+static int prism2_download_volatile(local_info_t *local,
+ struct prism2_download_data *param);
+static int prism2_download_genesis(local_info_t *local,
+ struct prism2_download_data *param);
+static int prism2_get_ram_size(local_info_t *local);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+
+
+
+#ifndef final_version
+/* magic value written to SWSUPPORT0 reg. for detecting whether card is still
+ * present */
+#define HFA384X_MAGIC 0x8A32
+#endif
+
+
+static u16 hfa384x_read_reg(struct net_device *dev, u16 reg)
+{
+ return HFA384X_INW(reg);
+}
+
+
+static void hfa384x_read_regs(struct net_device *dev,
+ struct hfa384x_regs *regs)
+{
+ regs->cmd = HFA384X_INW(HFA384X_CMD_OFF);
+ regs->evstat = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ regs->offset0 = HFA384X_INW(HFA384X_OFFSET0_OFF);
+ regs->offset1 = HFA384X_INW(HFA384X_OFFSET1_OFF);
+ regs->swsupport0 = HFA384X_INW(HFA384X_SWSUPPORT0_OFF);
+}
+
+
+/**
+ * __hostap_cmd_queue_free - Free Prism2 command queue entry (private)
+ * @local: pointer to private Host AP driver data
+ * @entry: Prism2 command queue entry to be freed
+ * @del_req: request the entry to be removed
+ *
+ * Internal helper function for freeing Prism2 command queue entries.
+ * Caller must have acquired local->cmdlock before calling this function.
+ */
+static inline void __hostap_cmd_queue_free(local_info_t *local,
+ struct hostap_cmd_queue *entry,
+ int del_req)
+{
+ if (del_req) {
+ entry->del_req = 1;
+ if (!list_empty(&entry->list)) {
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+ }
+ }
+
+ if (atomic_dec_and_test(&entry->usecnt) && entry->del_req)
+ kfree(entry);
+}
+
+
+/**
+ * hostap_cmd_queue_free - Free Prism2 command queue entry
+ * @local: pointer to private Host AP driver data
+ * @entry: Prism2 command queue entry to be freed
+ * @del_req: request the entry to be removed
+ *
+ * Free a Prism2 command queue entry.
+ */
+static inline void hostap_cmd_queue_free(local_info_t *local,
+ struct hostap_cmd_queue *entry,
+ int del_req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ __hostap_cmd_queue_free(local, entry, del_req);
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+}
+
+
+/**
+ * prism2_clear_cmd_queue - Free all pending Prism2 command queue entries
+ * @local: pointer to private Host AP driver data
+ */
+static void prism2_clear_cmd_queue(local_info_t *local)
+{
+ struct list_head *ptr, *n;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ list_for_each_safe(ptr, n, &local->cmd_queue) {
+ entry = list_entry(ptr, struct hostap_cmd_queue, list);
+ atomic_inc(&entry->usecnt);
+ printk(KERN_DEBUG "%s: removed pending cmd_queue entry "
+ "(type=%d, cmd=0x%04x, param0=0x%04x)\n",
+ local->dev->name, entry->type, entry->cmd,
+ entry->param0);
+ __hostap_cmd_queue_free(local, entry, 1);
+ }
+ if (local->cmd_queue_len) {
+ /* This should not happen; print debug message and clear
+ * queue length. */
+ printk(KERN_DEBUG "%s: cmd_queue_len (%d) not zero after "
+ "flush\n", local->dev->name, local->cmd_queue_len);
+ local->cmd_queue_len = 0;
+ }
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+}
+
+
+/**
+ * hfa384x_cmd_issue - Issue a Prism2 command to the hardware
+ * @dev: pointer to net_device
+ * @entry: Prism2 command queue entry to be issued
+ */
+static inline int hfa384x_cmd_issue(struct net_device *dev,
+ struct hostap_cmd_queue *entry)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int tries;
+ u16 reg;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->card_present && !local->func->card_present(local))
+ return -ENODEV;
+
+ if (entry->issued) {
+ printk(KERN_DEBUG "%s: driver bug - re-issuing command @%p\n",
+ dev->name, entry);
+ }
+
+ /* wait until busy bit is clear; this should always be clear since the
+ * commands are serialized */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+#ifndef final_version
+ if (tries != HFA384X_CMD_BUSY_TIMEOUT) {
+ prism2_io_debug_error(dev, 1);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue: cmd reg was busy "
+ "for %d usec\n", dev->name,
+ HFA384X_CMD_BUSY_TIMEOUT - tries);
+ }
+#endif
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ prism2_io_debug_error(dev, 2);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue - timeout - "
+ "reg=0x%04x\n", dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ /* write command */
+ spin_lock_irqsave(&local->cmdlock, flags);
+ HFA384X_OUTW(entry->param0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(entry->param1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(entry->cmd, HFA384X_CMD_OFF);
+ entry->issued = 1;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ return 0;
+}
+
+
+/**
+ * hfa384x_cmd - Issue a Prism2 command and wait (sleep) for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @param1: value for Param1 register (pointer; %NULL if not used)
+ * @resp0: pointer for Resp0 data or %NULL if Resp0 is not needed
+ *
+ * Issue given command (possibly after waiting in command queue) and sleep
+ * until the command is completed (or timed out or interrupted). This can be
+ * called only from user process context.
+ */
+static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
+ u16 *param1, u16 *resp0)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int err, res, issue, issued = 0;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+ DECLARE_WAITQUEUE(wait, current);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (in_interrupt()) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd called from interrupt "
+ "context\n", dev->name);
+ return -1;
+ }
+
+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",
+ dev->name);
+ return -1;
+ }
+
+ if (signal_pending(current))
+ return -EINTR;
+
+ entry = (struct hostap_cmd_queue *)
+ kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ memset(entry, 0, sizeof(*entry));
+ atomic_set(&entry->usecnt, 1);
+ entry->type = CMD_SLEEP;
+ entry->cmd = cmd;
+ entry->param0 = param0;
+ if (param1)
+ entry->param1 = *param1;
+ init_waitqueue_head(&entry->compl);
+
+ /* prepare to wait for command completion event, but do not sleep yet
+ */
+ add_wait_queue(&entry->compl, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ issue = list_empty(&local->cmd_queue);
+ if (issue)
+ entry->issuing = 1;
+ list_add_tail(&entry->list, &local->cmd_queue);
+ local->cmd_queue_len++;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ err = 0;
+ if (!issue)
+ goto wait_completion;
+
+ if (signal_pending(current))
+ err = -EINTR;
+
+ if (!err) {
+ if (hfa384x_cmd_issue(dev, entry))
+ err = -ETIMEDOUT;
+ else
+ issued = 1;
+ }
+
+ wait_completion:
+ if (!err && entry->type != CMD_COMPLETED) {
+ /* sleep until command is completed or timed out */
+ res = schedule_timeout(2 * HZ);
+ } else
+ res = -1;
+
+ if (!err && signal_pending(current))
+ err = -EINTR;
+
+ if (err && issued) {
+ /* the command was issued, so a CmdCompl event should occur
+ * soon; however, there's a pending signal and
+ * schedule_timeout() would be interrupted; wait a short period
+ * of time to avoid removing entry from the list before
+ * CmdCompl event */
+ udelay(300);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&entry->compl, &wait);
+
+ /* If entry->list is still in the list, it must be removed
+ * first and in this case prism2_cmd_ev() does not yet have
+ * local reference to it, and the data can be kfree()'d
+ * here. If the command completion event is still generated,
+ * it will be assigned to next (possibly) pending command, but
+ * the driver will reset the card anyway due to timeout
+ *
+ * If the entry is not in the list prism2_cmd_ev() has a local
+ * reference to it, but keeps cmdlock as long as the data is
+ * needed, so the data can be kfree()'d here. */
+
+ /* FIX: if the entry->list is in the list, it has not been completed
+ * yet, so removing it here is somewhat wrong.. this could cause
+ * references to freed memory and next list_del() causing NULL pointer
+ * dereference.. it would probably be better to leave the entry in the
+ * list and the list should be emptied during hw reset */
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ if (!list_empty(&entry->list)) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: entry still in list? "
+ "(entry=%p, type=%d, res=%d)\n", dev->name, entry,
+ entry->type, res);
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+ }
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (err) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: interrupted; err=%d\n",
+ dev->name, err);
+ res = err;
+ goto done;
+ }
+
+ if (entry->type != CMD_COMPLETED) {
+ u16 reg = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ printk(KERN_DEBUG "%s: hfa384x_cmd: command was not "
+ "completed (res=%d, entry=%p, type=%d, cmd=0x%04x, "
+ "param0=0x%04x, EVSTAT=%04x INTEN=%04x)\n", dev->name,
+ res, entry, entry->type, entry->cmd, entry->param0, reg,
+ HFA384X_INW(HFA384X_INTEN_OFF));
+ if (reg & HFA384X_EV_CMD) {
+ /* Command completion event is pending, but the
+ * interrupt was not delivered - probably an issue
+ * with pcmcia-cs configuration. */
+ printk(KERN_WARNING "%s: interrupt delivery does not "
+ "seem to work\n", dev->name);
+ }
+ prism2_io_debug_error(dev, 3);
+ res = -ETIMEDOUT;
+ goto done;
+ }
+
+ if (resp0 != NULL)
+ *resp0 = entry->resp0;
+#ifndef final_version
+ if (entry->res) {
+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x, "
+ "resp0=0x%04x\n",
+ dev->name, cmd, entry->res, entry->resp0);
+ }
+#endif /* final_version */
+
+ res = entry->res;
+ done:
+ hostap_cmd_queue_free(local, entry, 1);
+ return res;
+}
+
+
+/**
+ * hfa384x_cmd_callback - Issue a Prism2 command; callback when completed
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @callback: command completion callback function (%NULL = no callback)
+ * @context: context data to be given to the callback function
+ *
+ * Issue given command (possibly after waiting in command queue) and use
+ * callback function to indicate command completion. This can be called both
+ * from user and interrupt context. The callback function will be called in
+ * hardware IRQ context. It can be %NULL, when no function is called when
+ * command is completed.
+ */
+static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
+ void (*callback)(struct net_device *dev,
+ long context, u16 resp0,
+ u16 status),
+ long context)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int issue, ret;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN + 2) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",
+ dev->name);
+ return -1;
+ }
+
+ entry = (struct hostap_cmd_queue *)
+ kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc "
+ "failed\n", dev->name);
+ return -ENOMEM;
+ }
+ memset(entry, 0, sizeof(*entry));
+ atomic_set(&entry->usecnt, 1);
+ entry->type = CMD_CALLBACK;
+ entry->cmd = cmd;
+ entry->param0 = param0;
+ entry->callback = callback;
+ entry->context = context;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ issue = list_empty(&local->cmd_queue);
+ if (issue)
+ entry->issuing = 1;
+ list_add_tail(&entry->list, &local->cmd_queue);
+ local->cmd_queue_len++;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (issue && hfa384x_cmd_issue(dev, entry))
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+
+ hostap_cmd_queue_free(local, entry, ret);
+
+ return ret;
+}
+
+
+/**
+ * __hfa384x_cmd_no_wait - Issue a Prism2 command (private)
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @io_debug_num: I/O debug error number
+ *
+ * Shared helper function for hfa384x_cmd_wait() and hfa384x_cmd_no_wait().
+ */
+static int __hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, u16 param0,
+ int io_debug_num)
+{
+ int tries;
+ u16 reg;
+
+ /* wait until busy bit is clear; this should always be clear since the
+ * commands are serialized */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ prism2_io_debug_error(dev, io_debug_num);
+ printk(KERN_DEBUG "%s: __hfa384x_cmd_no_wait(%d) - timeout - "
+ "reg=0x%04x\n", dev->name, io_debug_num, reg);
+ return -ETIMEDOUT;
+ }
+
+ /* write command */
+ HFA384X_OUTW(param0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(cmd, HFA384X_CMD_OFF);
+
+ return 0;
+}
+
+
+/**
+ * hfa384x_cmd_wait - Issue a Prism2 command and busy wait for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ */
+static int hfa384x_cmd_wait(struct net_device *dev, u16 cmd, u16 param0)
+{
+ int res, tries;
+ u16 reg;
+
+ res = __hfa384x_cmd_no_wait(dev, cmd, param0, 4);
+ if (res)
+ return res;
+
+ /* wait for command completion */
+ if ((cmd & HFA384X_CMDCODE_MASK) == HFA384X_CMDCODE_DOWNLOAD)
+ tries = HFA384X_DL_COMPL_TIMEOUT;
+ else
+ tries = HFA384X_CMD_COMPL_TIMEOUT;
+
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&
+ tries > 0) {
+ tries--;
+ udelay(10);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ prism2_io_debug_error(dev, 5);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout2 - "
+ "reg=0x%04x\n", dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ res = (HFA384X_INW(HFA384X_STATUS_OFF) &
+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) |
+ BIT(8))) >> 8;
+#ifndef final_version
+ if (res) {
+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x\n",
+ dev->name, cmd, res);
+ }
+#endif
+
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ return res;
+}
+
+
+/**
+ * hfa384x_cmd_no_wait - Issue a Prism2 command; do not wait for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ */
+static inline int hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd,
+ u16 param0)
+{
+ return __hfa384x_cmd_no_wait(dev, cmd, param0, 6);
+}
+
+
+/**
+ * prism2_cmd_ev - Prism2 command completion event handler
+ * @dev: pointer to net_device
+ *
+ * Interrupt handler for command completion events. Called by the main
+ * interrupt handler in hardware IRQ context. Read Resp0 and status registers
+ * from the hardware and ACK the event. Depending on the issued command type
+ * either wake up the sleeping process that is waiting for command completion
+ * or call the callback function. Issue the next command, if one is pending.
+ */
+static void prism2_cmd_ev(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hostap_cmd_queue *entry = NULL;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock(&local->cmdlock);
+ if (!list_empty(&local->cmd_queue)) {
+ entry = list_entry(local->cmd_queue.next,
+ struct hostap_cmd_queue, list);
+ atomic_inc(&entry->usecnt);
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+
+ if (!entry->issued) {
+ printk(KERN_DEBUG "%s: Command completion event, but "
+ "cmd not issued\n", dev->name);
+ __hostap_cmd_queue_free(local, entry, 1);
+ entry = NULL;
+ }
+ }
+ spin_unlock(&local->cmdlock);
+
+ if (!entry) {
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: Command completion event, but no "
+ "pending commands\n", dev->name);
+ return;
+ }
+
+ entry->resp0 = HFA384X_INW(HFA384X_RESP0_OFF);
+ entry->res = (HFA384X_INW(HFA384X_STATUS_OFF) &
+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) |
+ BIT(9) | BIT(8))) >> 8;
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ /* TODO: rest of the CmdEv handling could be moved to tasklet */
+ if (entry->type == CMD_SLEEP) {
+ entry->type = CMD_COMPLETED;
+ wake_up_interruptible(&entry->compl);
+ } else if (entry->type == CMD_CALLBACK) {
+ if (entry->callback)
+ entry->callback(dev, entry->context, entry->resp0,
+ entry->res);
+ } else {
+ printk(KERN_DEBUG "%s: Invalid command completion type %d\n",
+ dev->name, entry->type);
+ }
+ hostap_cmd_queue_free(local, entry, 1);
+
+ /* issue next command, if pending */
+ entry = NULL;
+ spin_lock(&local->cmdlock);
+ if (!list_empty(&local->cmd_queue)) {
+ entry = list_entry(local->cmd_queue.next,
+ struct hostap_cmd_queue, list);
+ if (entry->issuing) {
+ /* hfa384x_cmd() has already started issuing this
+ * command, so do not start here */
+ entry = NULL;
+ }
+ if (entry)
+ atomic_inc(&entry->usecnt);
+ }
+ spin_unlock(&local->cmdlock);
+
+ if (entry) {
+ /* issue next command; if command issuing fails, remove the
+ * entry from cmd_queue */
+ int res = hfa384x_cmd_issue(dev, entry);
+ spin_lock(&local->cmdlock);
+ __hostap_cmd_queue_free(local, entry, res);
+ spin_unlock(&local->cmdlock);
+ }
+}
+
+
+static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off)
+{
+ int tries = HFA384X_BAP_BUSY_TIMEOUT;
+ int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;
+
+ while (res && tries > 0) {
+ tries--;
+ udelay(1);
+ res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;
+ }
+ return res;
+}
+
+
+/* Offset must be even */
+static int hfa384x_setup_bap(struct net_device *dev, u16 bap, u16 id,
+ int offset)
+{
+ u16 o_off, s_off;
+ int ret = 0;
+
+ if (offset % 2 || bap > 1)
+ return -EINVAL;
+
+ if (bap == BAP1) {
+ o_off = HFA384X_OFFSET1_OFF;
+ s_off = HFA384X_SELECT1_OFF;
+ } else {
+ o_off = HFA384X_OFFSET0_OFF;
+ s_off = HFA384X_SELECT0_OFF;
+ }
+
+ if (hfa384x_wait_offset(dev, o_off)) {
+ prism2_io_debug_error(dev, 7);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout before\n",
+ dev->name);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ HFA384X_OUTW(id, s_off);
+ HFA384X_OUTW(offset, o_off);
+
+ if (hfa384x_wait_offset(dev, o_off)) {
+ prism2_io_debug_error(dev, 8);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout after\n",
+ dev->name);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+#ifndef final_version
+ if (HFA384X_INW(o_off) & HFA384X_OFFSET_ERR) {
+ prism2_io_debug_error(dev, 9);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - offset error "
+ "(%d,0x04%x,%d); reg=0x%04x\n",
+ dev->name, bap, id, offset, HFA384X_INW(o_off));
+ ret = -EINVAL;
+ }
+#endif
+
+ out:
+ return ret;
+}
+
+
+static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len,
+ int exact_len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res, rlen = 0;
+ struct hfa384x_rid_hdr rec;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: cannot get RID %04x (len=%d) - no PRI "
+ "f/w\n", dev->name, rid, len);
+ return -ENOTTY; /* Well.. not really correct, but return
+ * something unique enough.. */
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ res = down_interruptible(&local->rid_bap_sem);
+ if (res)
+ return res;
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS, rid, NULL, NULL);
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_get_rid: CMDCODE_ACCESS failed "
+ "(res=%d, rid=%04x, len=%d)\n",
+ dev->name, res, rid, len);
+ up(&local->rid_bap_sem);
+ return res;
+ }
+
+ spin_lock_bh(&local->baplock);
+
+ res = hfa384x_setup_bap(dev, BAP0, rid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
+
+ if (le16_to_cpu(rec.len) == 0) {
+ /* RID not available */
+ res = -ENODATA;
+ }
+
+ rlen = (le16_to_cpu(rec.len) - 1) * 2;
+ if (!res && exact_len && rlen != len) {
+ printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: "
+ "rid=0x%04x, len=%d (expected %d)\n",
+ dev->name, rid, rlen, len);
+ res = -ENODATA;
+ }
+
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, buf, len);
+
+ spin_unlock_bh(&local->baplock);
+ up(&local->rid_bap_sem);
+
+ if (res) {
+ if (res != -ENODATA)
+ printk(KERN_DEBUG "%s: hfa384x_get_rid (rid=%04x, "
+ "len=%d) - failed - res=%d\n", dev->name, rid,
+ len, res);
+ if (res == -ETIMEDOUT)
+ prism2_hw_reset(dev);
+ return res;
+ }
+
+ return rlen;
+}
+
+
+static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_rid_hdr rec;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: cannot set RID %04x (len=%d) - no PRI "
+ "f/w\n", dev->name, rid, len);
+ return -ENOTTY; /* Well.. not really correct, but return
+ * something unique enough.. */
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ rec.rid = cpu_to_le16(rid);
+ /* RID len in words and +1 for rec.rid */
+ rec.len = cpu_to_le16(len / 2 + len % 2 + 1);
+
+ res = down_interruptible(&local->rid_bap_sem);
+ if (res)
+ return res;
+
+ spin_lock_bh(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, rid, 0);
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, &rec, sizeof(rec));
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, buf, len);
+ spin_unlock_bh(&local->baplock);
+
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_set_rid (rid=%04x, len=%d) - "
+ "failed - res=%d\n", dev->name, rid, len, res);
+ up(&local->rid_bap_sem);
+ return res;
+ }
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL);
+ up(&local->rid_bap_sem);
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
+ "failed (res=%d, rid=%04x, len=%d)\n",
+ dev->name, res, rid, len);
+ return res;
+ }
+
+ if (res == -ETIMEDOUT)
+ prism2_hw_reset(dev);
+
+ return res;
+}
+
+
+static void hfa384x_disable_interrupts(struct net_device *dev)
+{
+ /* disable interrupts and clear event status */
+ HFA384X_OUTW(0, HFA384X_INTEN_OFF);
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+}
+
+
+static void hfa384x_enable_interrupts(struct net_device *dev)
+{
+ /* ack pending events and enable interrupts from selected events */
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_no_bap0(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EVENT_MASK & ~HFA384X_BAP0_EVENTS,
+ HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_all(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_only_cmd(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_INTEN_OFF);
+}
+
+
+static u16 hfa384x_allocate_fid(struct net_device *dev, int len)
+{
+ u16 fid;
+ unsigned long delay;
+
+ /* FIX: this could be replace with hfa384x_cmd() if the Alloc event
+ * below would be handled like CmdCompl event (sleep here, wake up from
+ * interrupt handler */
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_ALLOC, len)) {
+ printk(KERN_DEBUG "%s: cannot allocate fid, len=%d\n",
+ dev->name, len);
+ return 0xffff;
+ }
+
+ delay = jiffies + HFA384X_ALLOC_COMPL_TIMEOUT;
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC) &&
+ time_before(jiffies, delay))
+ yield();
+ if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC)) {
+ printk("%s: fid allocate, len=%d - timeout\n", dev->name, len);
+ return 0xffff;
+ }
+
+ fid = HFA384X_INW(HFA384X_ALLOCFID_OFF);
+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF);
+
+ return fid;
+}
+
+
+static int prism2_reset_port(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (!local->dev_enabled)
+ return 0;
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0,
+ NULL, NULL);
+ if (res)
+ printk(KERN_DEBUG "%s: reset port failed to disable port\n",
+ dev->name);
+ else {
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0,
+ NULL, NULL);
+ if (res)
+ printk(KERN_DEBUG "%s: reset port failed to enable "
+ "port\n", dev->name);
+ }
+
+ /* It looks like at least some STA firmware versions reset
+ * fragmentation threshold back to 2346 after enable command. Restore
+ * the configured value, if it differs from this default. */
+ if (local->fragm_threshold != 2346 &&
+ hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ local->fragm_threshold)) {
+ printk(KERN_DEBUG "%s: failed to restore fragmentation "
+ "threshold (%d) after Port0 enable\n",
+ dev->name, local->fragm_threshold);
+ }
+
+ return res;
+}
+
+
+static int prism2_get_version_info(struct net_device *dev, u16 rid,
+ const char *txt)
+{
+ struct hfa384x_comp_ident comp;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ /* PRI f/w not yet available - cannot read RIDs */
+ return -1;
+ }
+ if (hfa384x_get_rid(dev, rid, &comp, sizeof(comp), 1) < 0) {
+ printk(KERN_DEBUG "Could not get RID for component %s\n", txt);
+ return -1;
+ }
+
+ printk(KERN_INFO "%s: %s: id=0x%02x v%d.%d.%d\n", dev->name, txt,
+ __le16_to_cpu(comp.id), __le16_to_cpu(comp.major),
+ __le16_to_cpu(comp.minor), __le16_to_cpu(comp.variant));
+ return 0;
+}
+
+
+static int prism2_setup_rids(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 tmp;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ hostap_set_word(dev, HFA384X_RID_TICKTIME, 2000);
+
+ if (!local->fw_ap) {
+ tmp = hostap_get_porttype(local);
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp);
+ if (ret) {
+ printk("%s: Port type setting to %d failed\n",
+ dev->name, tmp);
+ goto fail;
+ }
+ }
+
+ /* Setting SSID to empty string seems to kill the card in Host AP mode
+ */
+ if (local->iw_mode != IW_MODE_MASTER || local->essid[0] != '\0') {
+ ret = hostap_set_string(dev, HFA384X_RID_CNFOWNSSID,
+ local->essid);
+ if (ret) {
+ printk("%s: AP own SSID setting failed\n", dev->name);
+ goto fail;
+ }
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXDATALEN,
+ PRISM2_DATA_MAXLEN);
+ if (ret) {
+ printk("%s: MAC data length setting to %d failed\n",
+ dev->name, PRISM2_DATA_MAXLEN);
+ goto fail;
+ }
+
+ if (hfa384x_get_rid(dev, HFA384X_RID_CHANNELLIST, &tmp, 2, 1) < 0) {
+ printk("%s: Channel list read failed\n", dev->name);
+ ret = -EINVAL;
+ goto fail;
+ }
+ local->channel_mask = __le16_to_cpu(tmp);
+
+ if (local->channel < 1 || local->channel > 14 ||
+ !(local->channel_mask & (1 << (local->channel - 1)))) {
+ printk(KERN_WARNING "%s: Channel setting out of range "
+ "(%d)!\n", dev->name, local->channel);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel);
+ if (ret) {
+ printk("%s: Channel setting to %d failed\n",
+ dev->name, local->channel);
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFBEACONINT,
+ local->beacon_int);
+ if (ret) {
+ printk("%s: Beacon interval setting to %d failed\n",
+ dev->name, local->beacon_int);
+ /* this may fail with Symbol/Lucent firmware */
+ if (ret == -ETIMEDOUT)
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD,
+ local->dtim_period);
+ if (ret) {
+ printk("%s: DTIM period setting to %d failed\n",
+ dev->name, local->dtim_period);
+ /* this may fail with Symbol/Lucent firmware */
+ if (ret == -ETIMEDOUT)
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
+ local->is_promisc);
+ if (ret)
+ printk(KERN_INFO "%s: Setting promiscuous mode (%d) failed\n",
+ dev->name, local->is_promisc);
+
+ if (!local->fw_ap) {
+ ret = hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID,
+ local->essid);
+ if (ret) {
+ printk("%s: Desired SSID setting failed\n", dev->name);
+ goto fail;
+ }
+ }
+
+ /* Setup TXRateControl, defaults to allow use of 1, 2, 5.5, and
+ * 11 Mbps in automatic TX rate fallback and 1 and 2 Mbps as basic
+ * rates */
+ if (local->tx_rate_control == 0) {
+ local->tx_rate_control =
+ HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS |
+ HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ }
+ if (local->basic_rates == 0)
+ local->basic_rates = HFA384X_RATES_1MBPS | HFA384X_RATES_2MBPS;
+
+ if (!local->fw_ap) {
+ ret = hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
+ local->tx_rate_control);
+ if (ret) {
+ printk("%s: TXRateControl setting to %d failed\n",
+ dev->name, local->tx_rate_control);
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
+ local->tx_rate_control);
+ if (ret) {
+ printk("%s: cnfSupportedRates setting to %d failed\n",
+ dev->name, local->tx_rate_control);
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ local->basic_rates);
+ if (ret) {
+ printk("%s: cnfBasicRates setting to %d failed\n",
+ dev->name, local->basic_rates);
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CREATEIBSS, 1);
+ if (ret) {
+ printk("%s: Create IBSS setting to 1 failed\n",
+ dev->name);
+ }
+ }
+
+ if (local->name_set)
+ (void) hostap_set_string(dev, HFA384X_RID_CNFOWNNAME,
+ local->name);
+
+ if (hostap_set_encryption(local)) {
+ printk(KERN_INFO "%s: could not configure encryption\n",
+ dev->name);
+ }
+
+ (void) hostap_set_antsel(local);
+
+ if (hostap_set_roaming(local)) {
+ printk(KERN_INFO "%s: could not set host roaming\n",
+ dev->name);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,6,3) &&
+ hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, local->enh_sec))
+ printk(KERN_INFO "%s: cnfEnhSecurity setting to 0x%x failed\n",
+ dev->name, local->enh_sec);
+
+ /* 32-bit tallies were added in STA f/w 0.8.0, but they were apparently
+ * not working correctly (last seven counters report bogus values).
+ * This has been fixed in 0.8.2, so enable 32-bit tallies only
+ * beginning with that firmware version. Another bug fix for 32-bit
+ * tallies in 1.4.0; should 16-bit tallies be used for some other
+ * versions, too? */
+ if (local->sta_fw_ver >= PRISM2_FW_VER(0,8,2)) {
+ if (hostap_set_word(dev, HFA384X_RID_CNFTHIRTY2TALLY, 1)) {
+ printk(KERN_INFO "%s: cnfThirty2Tally setting "
+ "failed\n", dev->name);
+ local->tallies32 = 0;
+ } else
+ local->tallies32 = 1;
+ } else
+ local->tallies32 = 0;
+
+ hostap_set_auth_algs(local);
+
+ if (hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ local->fragm_threshold)) {
+ printk(KERN_INFO "%s: setting FragmentationThreshold to %d "
+ "failed\n", dev->name, local->fragm_threshold);
+ }
+
+ if (hostap_set_word(dev, HFA384X_RID_RTSTHRESHOLD,
+ local->rts_threshold)) {
+ printk(KERN_INFO "%s: setting RTSThreshold to %d failed\n",
+ dev->name, local->rts_threshold);
+ }
+
+ if (local->manual_retry_count >= 0 &&
+ hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
+ local->manual_retry_count)) {
+ printk(KERN_INFO "%s: setting cnfAltRetryCount to %d failed\n",
+ dev->name, local->manual_retry_count);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1) &&
+ hfa384x_get_rid(dev, HFA384X_RID_CNFDBMADJUST, &tmp, 2, 1) == 2) {
+ local->rssi_to_dBm = le16_to_cpu(tmp);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->wpa &&
+ hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1)) {
+ printk(KERN_INFO "%s: setting ssnHandlingMode to 1 failed\n",
+ dev->name);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->generic_elem &&
+ hfa384x_set_rid(dev, HFA384X_RID_GENERICELEMENT,
+ local->generic_elem, local->generic_elem_len)) {
+ printk(KERN_INFO "%s: setting genericElement failed\n",
+ dev->name);
+ }
+
+ fail:
+ return ret;
+}
+
+
+static int prism2_hw_init(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret, first = 1;
+ unsigned long start, delay;
+
+ PDEBUG(DEBUG_FLOW, "prism2_hw_init()\n");
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits);
+
+ init:
+ /* initialize HFA 384x */
+ ret = hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_INIT, 0);
+ if (ret) {
+ printk(KERN_INFO "%s: first command failed - assuming card "
+ "does not have primary firmware\n", dev_info);
+ }
+
+ if (first && (HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) {
+ /* EvStat has Cmd bit set in some cases, so retry once if no
+ * wait was needed */
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: init command completed too quickly - "
+ "retrying\n", dev->name);
+ first = 0;
+ goto init;
+ }
+
+ start = jiffies;
+ delay = jiffies + HFA384X_INIT_TIMEOUT;
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&
+ time_before(jiffies, delay))
+ yield();
+ if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) {
+ printk(KERN_DEBUG "%s: assuming no Primary image in "
+ "flash - card initialization not completed\n",
+ dev_info);
+ local->no_pri = 1;
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ if (local->sram_type == -1)
+ local->sram_type = prism2_get_ram_size(local);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+ return 1;
+ }
+ local->no_pri = 0;
+ printk(KERN_DEBUG "prism2_hw_init: initialized in %lu ms\n",
+ (jiffies - start) * 1000 / HZ);
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ return 0;
+}
+
+
+static int prism2_hw_init2(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ kfree(local->pda);
+ if (local->no_pri)
+ local->pda = NULL;
+ else
+ local->pda = prism2_read_pda(dev);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ hfa384x_disable_interrupts(dev);
+
+#ifndef final_version
+ HFA384X_OUTW(HFA384X_MAGIC, HFA384X_SWSUPPORT0_OFF);
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) {
+ printk("SWSUPPORT0 write/read failed: %04X != %04X\n",
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF), HFA384X_MAGIC);
+ goto failed;
+ }
+#endif
+
+ if (initial || local->pri_only) {
+ hfa384x_events_only_cmd(dev);
+ /* get card version information */
+ if (prism2_get_version_info(dev, HFA384X_RID_NICID, "NIC") ||
+ prism2_get_version_info(dev, HFA384X_RID_PRIID, "PRI")) {
+ hfa384x_disable_interrupts(dev);
+ goto failed;
+ }
+
+ if (prism2_get_version_info(dev, HFA384X_RID_STAID, "STA")) {
+ printk(KERN_DEBUG "%s: Failed to read STA f/w version "
+ "- only Primary f/w present\n", dev->name);
+ local->pri_only = 1;
+ return 0;
+ }
+ local->pri_only = 0;
+ hfa384x_disable_interrupts(dev);
+ }
+
+ /* FIX: could convert allocate_fid to use sleeping CmdCompl wait and
+ * enable interrupts before this. This would also require some sort of
+ * sleeping AllocEv waiting */
+
+ /* allocate TX FIDs */
+ local->txfid_len = PRISM2_TXFID_LEN;
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++) {
+ local->txfid[i] = hfa384x_allocate_fid(dev, local->txfid_len);
+ if (local->txfid[i] == 0xffff && local->txfid_len > 1600) {
+ local->txfid[i] = hfa384x_allocate_fid(dev, 1600);
+ if (local->txfid[i] != 0xffff) {
+ printk(KERN_DEBUG "%s: Using shorter TX FID "
+ "(1600 bytes)\n", dev->name);
+ local->txfid_len = 1600;
+ }
+ }
+ if (local->txfid[i] == 0xffff)
+ goto failed;
+ local->intransmitfid[i] = PRISM2_TXFID_EMPTY;
+ }
+
+ hfa384x_events_only_cmd(dev);
+
+ if (initial) {
+ struct list_head *ptr;
+ prism2_check_sta_fw_version(local);
+
+ if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR,
+ &dev->dev_addr, 6, 1) < 0) {
+ printk("%s: could not get own MAC address\n",
+ dev->name);
+ }
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ memcpy(iface->dev->dev_addr, dev->dev_addr, ETH_ALEN);
+ }
+ } else if (local->fw_ap)
+ prism2_check_sta_fw_version(local);
+
+ prism2_setup_rids(dev);
+
+ /* MAC is now configured, but port 0 is not yet enabled */
+ return 0;
+
+ failed:
+ if (!local->no_pri)
+ printk(KERN_WARNING "%s: Initialization failed\n", dev_info);
+ return 1;
+}
+
+
+static int prism2_hw_enable(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int was_resetting;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ was_resetting = local->hw_resetting;
+
+ if (hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, NULL)) {
+ printk("%s: MAC port 0 enabling failed\n", dev->name);
+ return 1;
+ }
+
+ local->hw_ready = 1;
+ local->hw_reset_tries = 0;
+ local->hw_resetting = 0;
+ hfa384x_enable_interrupts(dev);
+
+ /* at least D-Link DWL-650 seems to require additional port reset
+ * before it starts acting as an AP, so reset port automatically
+ * here just in case */
+ if (initial && prism2_reset_port(dev)) {
+ printk("%s: MAC port 0 reseting failed\n", dev->name);
+ return 1;
+ }
+
+ if (was_resetting && netif_queue_stopped(dev)) {
+ /* If hw_reset() was called during pending transmit, netif
+ * queue was stopped. Wake it up now since the wlan card has
+ * been resetted. */
+ netif_wake_queue(dev);
+ }
+
+ return 0;
+}
+
+
+static int prism2_hw_config(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->hw_downloading)
+ return 1;
+
+ if (prism2_hw_init(dev, initial)) {
+ return local->no_pri ? 0 : 1;
+ }
+
+ if (prism2_hw_init2(dev, initial))
+ return 1;
+
+ /* Enable firmware if secondary image is loaded and at least one of the
+ * netdevices is up. */
+ if (!local->pri_only &&
+ (initial == 0 || (initial == 2 && local->num_dev_open > 0))) {
+ if (!local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_ENABLE);
+ local->dev_enabled = 1;
+ return prism2_hw_enable(dev, initial);
+ }
+
+ return 0;
+}
+
+
+static void prism2_hw_shutdown(struct net_device *dev, int no_disable)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Allow only command completion events during disable */
+ hfa384x_events_only_cmd(dev);
+
+ local->hw_ready = 0;
+ if (local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_DISABLE);
+ local->dev_enabled = 0;
+
+ if (local->func->card_present && !local->func->card_present(local)) {
+ printk(KERN_DEBUG "%s: card already removed or not configured "
+ "during shutdown\n", dev->name);
+ return;
+ }
+
+ if ((no_disable & HOSTAP_HW_NO_DISABLE) == 0 &&
+ hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, NULL))
+ printk(KERN_WARNING "%s: Shutdown failed\n", dev_info);
+
+ hfa384x_disable_interrupts(dev);
+
+ if (no_disable & HOSTAP_HW_ENABLE_CMDCOMPL)
+ hfa384x_events_only_cmd(dev);
+ else
+ prism2_clear_cmd_queue(local);
+}
+
+
+static void prism2_hw_reset(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+#if 0
+ static long last_reset = 0;
+
+ /* do not reset card more than once per second to avoid ending up in a
+ * busy loop reseting the card */
+ if (time_before_eq(jiffies, last_reset + HZ))
+ return;
+ last_reset = jiffies;
+#endif
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (in_interrupt()) {
+ printk(KERN_DEBUG "%s: driver bug - prism2_hw_reset() called "
+ "in interrupt context\n", dev->name);
+ return;
+ }
+
+ if (local->hw_downloading)
+ return;
+
+ if (local->hw_resetting) {
+ printk(KERN_WARNING "%s: %s: already resetting card - "
+ "ignoring reset request\n", dev_info, dev->name);
+ return;
+ }
+
+ local->hw_reset_tries++;
+ if (local->hw_reset_tries > 10) {
+ printk(KERN_WARNING "%s: too many reset tries, skipping\n",
+ dev->name);
+ return;
+ }
+
+ printk(KERN_WARNING "%s: %s: resetting card\n", dev_info, dev->name);
+ hfa384x_disable_interrupts(dev);
+ local->hw_resetting = 1;
+ if (local->func->cor_sreset) {
+ /* Host system seems to hang in some cases with high traffic
+ * load or shared interrupts during COR sreset. Disable shared
+ * interrupts during reset to avoid these crashes. COS sreset
+ * takes quite a long time, so it is unfortunate that this
+ * seems to be needed. Anyway, I do not know of any better way
+ * of avoiding the crash. */
+ disable_irq(dev->irq);
+ local->func->cor_sreset(local);
+ enable_irq(dev->irq);
+ }
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, 0);
+ local->hw_resetting = 0;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ if (local->dl_pri) {
+ printk(KERN_DEBUG "%s: persistent download of primary "
+ "firmware\n", dev->name);
+ if (prism2_download_genesis(local, local->dl_pri) < 0)
+ printk(KERN_WARNING "%s: download (PRI) failed\n",
+ dev->name);
+ }
+
+ if (local->dl_sec) {
+ printk(KERN_DEBUG "%s: persistent download of secondary "
+ "firmware\n", dev->name);
+ if (prism2_download_volatile(local, local->dl_sec) < 0)
+ printk(KERN_WARNING "%s: download (SEC) failed\n",
+ dev->name);
+ }
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ /* TODO: restore beacon TIM bits for STAs that have buffered frames */
+}
+
+
+static void prism2_schedule_reset(local_info_t *local)
+{
+ schedule_work(&local->reset_queue);
+}
+
+
+/* Called only as scheduled task after noticing card timeout in interrupt
+ * context */
+static void handle_reset_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name);
+ prism2_hw_reset(local->dev);
+
+ if (netif_queue_stopped(local->dev)) {
+ int i;
+
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++)
+ if (local->intransmitfid[i] == PRISM2_TXFID_EMPTY) {
+ PDEBUG(DEBUG_EXTRA, "prism2_tx_timeout: "
+ "wake up queue\n");
+ netif_wake_queue(local->dev);
+ break;
+ }
+ }
+}
+
+
+static int prism2_get_txfid_idx(local_info_t *local)
+{
+ int idx, end;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->txfidlock, flags);
+ end = idx = local->next_txfid;
+ do {
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) {
+ local->intransmitfid[idx] = PRISM2_TXFID_RESERVED;
+ spin_unlock_irqrestore(&local->txfidlock, flags);
+ return idx;
+ }
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != end);
+ spin_unlock_irqrestore(&local->txfidlock, flags);
+
+ PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: "
+ "packet dropped\n");
+ local->stats.tx_dropped++;
+
+ return -1;
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_transmit_cb(struct net_device *dev, long context,
+ u16 resp0, u16 res)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int idx = (int) context;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (res) {
+ printk(KERN_DEBUG "%s: prism2_transmit_cb - res=0x%02x\n",
+ dev->name, res);
+ return;
+ }
+
+ if (idx < 0 || idx >= PRISM2_TXFID_COUNT) {
+ printk(KERN_DEBUG "%s: prism2_transmit_cb called with invalid "
+ "idx=%d\n", dev->name, idx);
+ return;
+ }
+
+ if (!test_and_clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: driver bug: prism2_transmit_cb called "
+ "with no pending transmit\n", dev->name);
+ }
+
+ if (netif_queue_stopped(dev)) {
+ /* ready for next TX, so wake up queue that was stopped in
+ * prism2_transmit() */
+ netif_wake_queue(dev);
+ }
+
+ spin_lock(&local->txfidlock);
+
+ /* With reclaim, Resp0 contains new txfid for transmit; the old txfid
+ * will be automatically allocated for the next TX frame */
+ local->intransmitfid[idx] = resp0;
+
+ PDEBUG(DEBUG_FID, "%s: prism2_transmit_cb: txfid[%d]=0x%04x, "
+ "resp0=0x%04x, transmit_txfid=0x%04x\n",
+ dev->name, idx, local->txfid[idx],
+ resp0, local->intransmitfid[local->next_txfid]);
+
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ local->next_txfid = idx;
+
+ /* check if all TX buffers are occupied */
+ do {
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) {
+ spin_unlock(&local->txfidlock);
+ return;
+ }
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != local->next_txfid);
+ spin_unlock(&local->txfidlock);
+
+ /* no empty TX buffers, stop queue */
+ netif_stop_queue(dev);
+}
+
+
+/* Called only from software IRQ if PCI bus master is not used (with bus master
+ * this can be called both from software and hardware IRQ) */
+static int prism2_transmit(struct net_device *dev, int idx)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* The driver tries to stop netif queue so that there would not be
+ * more than one attempt to transmit frames going on; check that this
+ * is really the case */
+
+ if (test_and_set_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: driver bug - prism2_transmit() called "
+ "when previous TX was pending\n", dev->name);
+ return -1;
+ }
+
+ /* stop the queue for the time that transmit is pending */
+ netif_stop_queue(dev);
+
+ /* transmit packet */
+ res = hfa384x_cmd_callback(
+ dev,
+ HFA384X_CMDCODE_TRANSMIT | HFA384X_CMD_TX_RECLAIM,
+ local->txfid[idx],
+ prism2_transmit_cb, (long) idx);
+
+ if (res) {
+ struct net_device_stats *stats;
+ printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT "
+ "failed (res=%d)\n", dev->name, res);
+ stats = hostap_get_stats(dev);
+ stats->tx_dropped++;
+ netif_wake_queue(dev);
+ return -1;
+ }
+ dev->trans_start = jiffies;
+
+ /* Since we did not wait for command completion, the card continues
+ * to process on the background and we will finish handling when
+ * command completion event is handled (prism2_cmd_ev() function) */
+
+ return 0;
+}
+
+
+/* Send IEEE 802.11 frame (convert the header into Prism2 TX descriptor and
+ * send the payload with this descriptor) */
+/* Called only from software IRQ */
+static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_tx_frame txdesc;
+ struct hostap_skb_tx_data *meta;
+ int hdr_len, data_len, idx, res, ret = -1;
+ u16 tx_control, fc;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+
+ prism2_callback(local, PRISM2_CALLBACK_TX_START);
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ !local->hw_ready || local->hw_downloading || local->pri_only) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: prism2_tx_80211: hw not ready -"
+ " skipping\n", dev->name);
+ }
+ goto fail;
+ }
+
+ memset(&txdesc, 0, sizeof(txdesc));
+
+ /* skb->data starts with txdesc->frame_control */
+ hdr_len = 24;
+ memcpy(&txdesc.frame_control, skb->data, hdr_len);
+ fc = le16_to_cpu(txdesc.frame_control);
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ (fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS) &&
+ skb->len >= 30) {
+ /* Addr4 */
+ memcpy(txdesc.addr4, skb->data + hdr_len, ETH_ALEN);
+ hdr_len += ETH_ALEN;
+ }
+
+ tx_control = local->tx_control;
+ if (meta->tx_cb_idx) {
+ tx_control |= HFA384X_TX_CTRL_TX_OK;
+ txdesc.sw_support = cpu_to_le16(meta->tx_cb_idx);
+ }
+ txdesc.tx_control = cpu_to_le16(tx_control);
+ txdesc.tx_rate = meta->rate;
+
+ data_len = skb->len - hdr_len;
+ txdesc.data_len = cpu_to_le16(data_len);
+ txdesc.len = cpu_to_be16(data_len);
+
+ idx = prism2_get_txfid_idx(local);
+ if (idx < 0)
+ goto fail;
+
+ if (local->frame_dump & PRISM2_DUMP_TX_HDR)
+ hostap_dump_tx_header(dev->name, &txdesc);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0);
+
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc));
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, skb->data + hdr_len,
+ skb->len - hdr_len);
+ spin_unlock(&local->baplock);
+
+ if (!res)
+ res = prism2_transmit(dev, idx);
+ if (res) {
+ printk(KERN_DEBUG "%s: prism2_tx_80211 - to BAP0 failed\n",
+ dev->name);
+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY;
+ schedule_work(&local->reset_queue);
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ prism2_callback(local, PRISM2_CALLBACK_TX_END);
+ return ret;
+}
+
+
+/* Some SMP systems have reported number of odd errors with hostap_pci. fid
+ * register has changed values between consecutive reads for an unknown reason.
+ * This should really not happen, so more debugging is needed. This test
+ * version is a big slower, but it will detect most of such register changes
+ * and will try to get the correct fid eventually. */
+#define EXTRA_FID_READ_TESTS
+
+static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg)
+{
+#ifdef EXTRA_FID_READ_TESTS
+ u16 val, val2, val3;
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ val = HFA384X_INW(reg);
+ val2 = HFA384X_INW(reg);
+ val3 = HFA384X_INW(reg);
+
+ if (val == val2 && val == val3)
+ return val;
+
+ printk(KERN_DEBUG "%s: detected fid change (try=%d, reg=%04x):"
+ " %04x %04x %04x\n",
+ dev->name, i, reg, val, val2, val3);
+ if ((val == val2 || val == val3) && val != 0)
+ return val;
+ if (val2 == val3 && val2 != 0)
+ return val2;
+ }
+ printk(KERN_WARNING "%s: Uhhuh.. could not read good fid from reg "
+ "%04x (%04x %04x %04x)\n", dev->name, reg, val, val2, val3);
+ return val;
+#else /* EXTRA_FID_READ_TESTS */
+ return HFA384X_INW(reg);
+#endif /* EXTRA_FID_READ_TESTS */
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_rx(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ int res, rx_pending = 0;
+ u16 len, hdr_len, rxfid, status, macport;
+ struct net_device_stats *stats;
+ struct hfa384x_rx_frame rxdesc;
+ struct sk_buff *skb = NULL;
+
+ prism2_callback(local, PRISM2_CALLBACK_RX_START);
+ stats = hostap_get_stats(dev);
+
+ rxfid = prism2_read_fid_reg(dev, HFA384X_RXFID_OFF);
+#ifndef final_version
+ if (rxfid == 0) {
+ rxfid = HFA384X_INW(HFA384X_RXFID_OFF);
+ printk(KERN_DEBUG "prism2_rx: rxfid=0 (next 0x%04x)\n",
+ rxfid);
+ if (rxfid == 0) {
+ schedule_work(&local->reset_queue);
+ goto rx_dropped;
+ }
+ /* try to continue with the new rxfid value */
+ }
+#endif
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, rxfid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &rxdesc, sizeof(rxdesc));
+
+ if (res) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: copy from BAP0 failed %d\n", dev->name,
+ res);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ goto rx_dropped;
+ }
+
+ len = le16_to_cpu(rxdesc.data_len);
+ hdr_len = sizeof(rxdesc);
+ status = le16_to_cpu(rxdesc.status);
+ macport = (status >> 8) & 0x07;
+
+ /* Drop frames with too large reported payload length. Monitor mode
+ * seems to sometimes pass frames (e.g., ctrl::ack) with signed and
+ * negative value, so allow also values 65522 .. 65534 (-14 .. -2) for
+ * macport 7 */
+ if (len > PRISM2_DATA_MAXLEN + 8 /* WEP */) {
+ if (macport == 7 && local->iw_mode == IW_MODE_MONITOR) {
+ if (len >= (u16) -14) {
+ hdr_len -= 65535 - len;
+ hdr_len--;
+ }
+ len = 0;
+ } else {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Received frame with invalid "
+ "length 0x%04x\n", dev->name, len);
+ hostap_dump_rx_header(dev->name, &rxdesc);
+ goto rx_dropped;
+ }
+ }
+
+ skb = dev_alloc_skb(len + hdr_len);
+ if (!skb) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: RX failed to allocate skb\n",
+ dev->name);
+ goto rx_dropped;
+ }
+ skb->dev = dev;
+ memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len);
+
+ if (len > 0)
+ res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len);
+ spin_unlock(&local->baplock);
+ if (res) {
+ printk(KERN_DEBUG "%s: RX failed to read "
+ "frame data\n", dev->name);
+ goto rx_dropped;
+ }
+
+ skb_queue_tail(&local->rx_list, skb);
+ tasklet_schedule(&local->rx_tasklet);
+
+ rx_exit:
+ prism2_callback(local, PRISM2_CALLBACK_RX_END);
+ if (!rx_pending) {
+ HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF);
+ }
+
+ return;
+
+ rx_dropped:
+ stats->rx_dropped++;
+ if (skb)
+ dev_kfree_skb(skb);
+ goto rx_exit;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb)
+{
+ struct hfa384x_rx_frame *rxdesc;
+ struct net_device *dev = skb->dev;
+ struct hostap_80211_rx_status stats;
+ int hdrlen, rx_hdrlen;
+
+ rx_hdrlen = sizeof(*rxdesc);
+ if (skb->len < sizeof(*rxdesc)) {
+ /* Allow monitor mode to receive shorter frames */
+ if (local->iw_mode == IW_MODE_MONITOR &&
+ skb->len >= sizeof(*rxdesc) - 30) {
+ rx_hdrlen = skb->len;
+ } else {
+ dev_kfree_skb(skb);
+ return;
+ }
+ }
+
+ rxdesc = (struct hfa384x_rx_frame *) skb->data;
+
+ if (local->frame_dump & PRISM2_DUMP_RX_HDR &&
+ skb->len >= sizeof(*rxdesc))
+ hostap_dump_rx_header(dev->name, rxdesc);
+
+ if (le16_to_cpu(rxdesc->status) & HFA384X_RX_STATUS_FCSERR &&
+ (!local->monitor_allow_fcserr ||
+ local->iw_mode != IW_MODE_MONITOR))
+ goto drop;
+
+ if (skb->len > PRISM2_DATA_MAXLEN) {
+ printk(KERN_DEBUG "%s: RX: len(%d) > MAX(%d)\n",
+ dev->name, skb->len, PRISM2_DATA_MAXLEN);
+ goto drop;
+ }
+
+ stats.mac_time = le32_to_cpu(rxdesc->time);
+ stats.signal = rxdesc->signal - local->rssi_to_dBm;
+ stats.noise = rxdesc->silence - local->rssi_to_dBm;
+ stats.rate = rxdesc->rate;
+
+ /* Convert Prism2 RX structure into IEEE 802.11 header */
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(rxdesc->frame_control));
+ if (hdrlen > rx_hdrlen)
+ hdrlen = rx_hdrlen;
+
+ memmove(skb_pull(skb, rx_hdrlen - hdrlen),
+ &rxdesc->frame_control, hdrlen);
+
+ hostap_80211_rx(dev, skb, &stats);
+ return;
+
+ drop:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_rx_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->rx_list)) != NULL)
+ hostap_rx_skb(local, skb);
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_alloc_ev(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int idx;
+ u16 fid;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ fid = prism2_read_fid_reg(dev, HFA384X_ALLOCFID_OFF);
+
+ PDEBUG(DEBUG_FID, "FID: interrupt: ALLOC - fid=0x%04x\n", fid);
+
+ spin_lock(&local->txfidlock);
+ idx = local->next_alloc;
+
+ do {
+ if (local->txfid[idx] == fid) {
+ PDEBUG(DEBUG_FID, "FID: found matching txfid[%d]\n",
+ idx);
+
+#ifndef final_version
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY)
+ printk("Already released txfid found at idx "
+ "%d\n", idx);
+ if (local->intransmitfid[idx] == PRISM2_TXFID_RESERVED)
+ printk("Already reserved txfid found at idx "
+ "%d\n", idx);
+#endif
+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY;
+ idx++;
+ local->next_alloc = idx >= PRISM2_TXFID_COUNT ? 0 :
+ idx;
+
+ if (!test_bit(HOSTAP_BITS_TRANSMIT, &local->bits) &&
+ netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+
+ spin_unlock(&local->txfidlock);
+ return;
+ }
+
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != local->next_alloc);
+
+ printk(KERN_WARNING "%s: could not find matching txfid (0x%04x, new "
+ "read 0x%04x) for alloc event\n", dev->name, fid,
+ HFA384X_INW(HFA384X_ALLOCFID_OFF));
+ printk(KERN_DEBUG "TXFIDs:");
+ for (idx = 0; idx < PRISM2_TXFID_COUNT; idx++)
+ printk(" %04x[%04x]", local->txfid[idx],
+ local->intransmitfid[idx]);
+ printk("\n");
+ spin_unlock(&local->txfidlock);
+
+ /* FIX: should probably schedule reset; reference to one txfid was lost
+ * completely.. Bad things will happen if we run out of txfids
+ * Actually, this will cause netdev watchdog to notice TX timeout and
+ * then card reset after all txfids have been leaked. */
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_tx_callback(local_info_t *local,
+ struct hfa384x_tx_frame *txdesc, int ok,
+ char *payload)
+{
+ u16 sw_support, hdrlen, len;
+ struct sk_buff *skb;
+ struct hostap_tx_callback_info *cb;
+
+ /* Make sure that frame was from us. */
+ if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) {
+ printk(KERN_DEBUG "%s: TX callback - foreign frame\n",
+ local->dev->name);
+ return;
+ }
+
+ sw_support = le16_to_cpu(txdesc->sw_support);
+
+ spin_lock(&local->lock);
+ cb = local->tx_callback;
+ while (cb != NULL && cb->idx != sw_support)
+ cb = cb->next;
+ spin_unlock(&local->lock);
+
+ if (cb == NULL) {
+ printk(KERN_DEBUG "%s: could not find TX callback (idx %d)\n",
+ local->dev->name, sw_support);
+ return;
+ }
+
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(txdesc->frame_control));
+ len = le16_to_cpu(txdesc->data_len);
+ skb = dev_alloc_skb(hdrlen + len);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: hostap_tx_callback failed to allocate "
+ "skb\n", local->dev->name);
+ return;
+ }
+
+ memcpy(skb_put(skb, hdrlen), (void *) &txdesc->frame_control, hdrlen);
+ if (payload)
+ memcpy(skb_put(skb, len), payload, len);
+
+ skb->dev = local->dev;
+ skb->mac.raw = skb->data;
+
+ cb->func(skb, ok, cb->data);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int hostap_tx_compl_read(local_info_t *local, int error,
+ struct hfa384x_tx_frame *txdesc,
+ char **payload)
+{
+ u16 fid, len;
+ int res, ret = 0;
+ struct net_device *dev = local->dev;
+
+ fid = prism2_read_fid_reg(dev, HFA384X_TXCOMPLFID_OFF);
+
+ PDEBUG(DEBUG_FID, "interrupt: TX (err=%d) - fid=0x%04x\n", fid, error);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, fid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, txdesc, sizeof(*txdesc));
+ if (res) {
+ PDEBUG(DEBUG_EXTRA, "%s: TX (err=%d) - fid=0x%04x - could not "
+ "read txdesc\n", dev->name, error, fid);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ ret = -1;
+ goto fail;
+ }
+ if (txdesc->sw_support) {
+ len = le16_to_cpu(txdesc->data_len);
+ if (len < PRISM2_DATA_MAXLEN) {
+ *payload = (char *) kmalloc(len, GFP_ATOMIC);
+ if (*payload == NULL ||
+ hfa384x_from_bap(dev, BAP0, *payload, len)) {
+ PDEBUG(DEBUG_EXTRA, "%s: could not read TX "
+ "frame payload\n", dev->name);
+ kfree(*payload);
+ *payload = NULL;
+ ret = -1;
+ goto fail;
+ }
+ }
+ }
+
+ fail:
+ spin_unlock(&local->baplock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_tx_ev(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ char *payload = NULL;
+ struct hfa384x_tx_frame txdesc;
+
+ if (hostap_tx_compl_read(local, 0, &txdesc, &payload))
+ goto fail;
+
+ if (local->frame_dump & PRISM2_DUMP_TX_HDR) {
+ PDEBUG(DEBUG_EXTRA, "%s: TX - status=0x%04x "
+ "retry_count=%d tx_rate=%d seq_ctrl=%d "
+ "duration_id=%d\n",
+ dev->name, le16_to_cpu(txdesc.status),
+ txdesc.retry_count, txdesc.tx_rate,
+ le16_to_cpu(txdesc.seq_ctrl),
+ le16_to_cpu(txdesc.duration_id));
+ }
+
+ if (txdesc.sw_support)
+ hostap_tx_callback(local, &txdesc, 1, payload);
+ kfree(payload);
+
+ fail:
+ HFA384X_OUTW(HFA384X_EV_TX, HFA384X_EVACK_OFF);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_sta_tx_exc_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->sta_tx_exc_list)) != NULL) {
+ struct hfa384x_tx_frame *txdesc =
+ (struct hfa384x_tx_frame *) skb->data;
+
+ if (skb->len >= sizeof(*txdesc)) {
+ /* Convert Prism2 RX structure into IEEE 802.11 header
+ */
+ u16 fc = le16_to_cpu(txdesc->frame_control);
+ int hdrlen = hostap_80211_get_hdrlen(fc);
+ memmove(skb_pull(skb, sizeof(*txdesc) - hdrlen),
+ &txdesc->frame_control, hdrlen);
+
+ hostap_handle_sta_tx_exc(local, skb);
+ }
+ dev_kfree_skb(skb);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_txexc(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 status, fc;
+ int show_dump, res;
+ char *payload = NULL;
+ struct hfa384x_tx_frame txdesc;
+
+ show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR;
+ local->stats.tx_errors++;
+
+ res = hostap_tx_compl_read(local, 1, &txdesc, &payload);
+ HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF);
+ if (res)
+ return;
+
+ status = le16_to_cpu(txdesc.status);
+
+ /* We produce a TXDROP event only for retry or lifetime
+ * exceeded, because that's the only status that really mean
+ * that this particular node went away.
+ * Other errors means that *we* screwed up. - Jean II */
+ if (status & (HFA384X_TX_STATUS_RETRYERR | HFA384X_TX_STATUS_AGEDERR))
+ {
+ union iwreq_data wrqu;
+
+ /* Copy 802.11 dest address. */
+ memcpy(wrqu.addr.sa_data, txdesc.addr1, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
+ } else
+ show_dump = 1;
+
+ if (local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT ||
+ local->wds_type & HOSTAP_WDS_AP_CLIENT) {
+ struct sk_buff *skb;
+ skb = dev_alloc_skb(sizeof(txdesc));
+ if (skb) {
+ memcpy(skb_put(skb, sizeof(txdesc)), &txdesc,
+ sizeof(txdesc));
+ skb_queue_tail(&local->sta_tx_exc_list, skb);
+ tasklet_schedule(&local->sta_tx_exc_tasklet);
+ }
+ }
+
+ if (txdesc.sw_support)
+ hostap_tx_callback(local, &txdesc, 0, payload);
+ kfree(payload);
+
+ if (!show_dump)
+ return;
+
+ PDEBUG(DEBUG_EXTRA, "%s: TXEXC - status=0x%04x (%s%s%s%s)"
+ " tx_control=%04x\n",
+ dev->name, status,
+ status & HFA384X_TX_STATUS_RETRYERR ? "[RetryErr]" : "",
+ status & HFA384X_TX_STATUS_AGEDERR ? "[AgedErr]" : "",
+ status & HFA384X_TX_STATUS_DISCON ? "[Discon]" : "",
+ status & HFA384X_TX_STATUS_FORMERR ? "[FormErr]" : "",
+ le16_to_cpu(txdesc.tx_control));
+
+ fc = le16_to_cpu(txdesc.frame_control);
+ PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x "
+ "(%s%s%s::%d%s%s)\n",
+ txdesc.retry_count, txdesc.tx_rate, fc,
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT ? "Mgmt" : "",
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL ? "Ctrl" : "",
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA ? "Data" : "",
+ WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " ToDS" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " FromDS" : "");
+ PDEBUG(DEBUG_EXTRA, " A1=" MACSTR " A2=" MACSTR " A3="
+ MACSTR " A4=" MACSTR "\n",
+ MAC2STR(txdesc.addr1), MAC2STR(txdesc.addr2),
+ MAC2STR(txdesc.addr3), MAC2STR(txdesc.addr4));
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_info_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->info_list)) != NULL) {
+ hostap_info_process(local, skb);
+ dev_kfree_skb(skb);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 fid;
+ int res, left;
+ struct hfa384x_info_frame info;
+ struct sk_buff *skb;
+
+ fid = HFA384X_INW(HFA384X_INFOFID_OFF);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, fid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &info, sizeof(info));
+ if (res) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "Could not get info frame (fid=0x%04x)\n",
+ fid);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ goto out;
+ }
+
+ le16_to_cpus(&info.len);
+ le16_to_cpus(&info.type);
+ left = (info.len - 1) * 2;
+
+ if (info.len & 0x8000 || info.len == 0 || left > 2060) {
+ /* data register seems to give 0x8000 in some error cases even
+ * though busy bit is not set in offset register;
+ * in addition, length must be at least 1 due to type field */
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Received info frame with invalid "
+ "length 0x%04x (type 0x%04x)\n", dev->name, info.len,
+ info.type);
+ goto out;
+ }
+
+ skb = dev_alloc_skb(sizeof(info) + left);
+ if (skb == NULL) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Could not allocate skb for info "
+ "frame\n", dev->name);
+ goto out;
+ }
+
+ memcpy(skb_put(skb, sizeof(info)), &info, sizeof(info));
+ if (left > 0 && hfa384x_from_bap(dev, BAP0, skb_put(skb, left), left))
+ {
+ spin_unlock(&local->baplock);
+ printk(KERN_WARNING "%s: Info frame read failed (fid=0x%04x, "
+ "len=0x%04x, type=0x%04x\n",
+ dev->name, fid, info.len, info.type);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+ spin_unlock(&local->baplock);
+
+ skb_queue_tail(&local->info_list, skb);
+ tasklet_schedule(&local->info_tasklet);
+
+ out:
+ HFA384X_OUTW(HFA384X_EV_INFO, HFA384X_EVACK_OFF);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_bap_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct net_device *dev = local->dev;
+ u16 ev;
+ int frames = 30;
+
+ if (local->func->card_present && !local->func->card_present(local))
+ return;
+
+ set_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits);
+
+ /* Process all pending BAP events without generating new interrupts
+ * for them */
+ while (frames-- > 0) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev == 0xffff || !(ev & HFA384X_BAP0_EVENTS))
+ break;
+ if (ev & HFA384X_EV_RX)
+ prism2_rx(local);
+ if (ev & HFA384X_EV_INFO)
+ prism2_info(local);
+ if (ev & HFA384X_EV_TX)
+ prism2_tx_ev(local);
+ if (ev & HFA384X_EV_TXEXC)
+ prism2_txexc(local);
+ }
+
+ set_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits);
+ clear_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits);
+
+ /* Enable interrupts for new BAP events */
+ hfa384x_events_all(dev);
+ clear_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits);
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_infdrop(struct net_device *dev)
+{
+ static unsigned long last_inquire = 0;
+
+ PDEBUG(DEBUG_EXTRA, "%s: INFDROP event\n", dev->name);
+
+ /* some firmware versions seem to get stuck with
+ * full CommTallies in high traffic load cases; every
+ * packet will then cause INFDROP event and CommTallies
+ * info frame will not be sent automatically. Try to
+ * get out of this state by inquiring CommTallies. */
+ if (!last_inquire || time_after(jiffies, last_inquire + HZ)) {
+ hfa384x_cmd_callback(dev, HFA384X_CMDCODE_INQUIRE,
+ HFA384X_INFO_COMMTALLIES, NULL, 0);
+ last_inquire = jiffies;
+ }
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_ev_tick(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 evstat, inten;
+ static int prev_stuck = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (time_after(jiffies, local->last_tick_timer + 5 * HZ) &&
+ local->last_tick_timer) {
+ evstat = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ inten = HFA384X_INW(HFA384X_INTEN_OFF);
+ if (!prev_stuck) {
+ printk(KERN_INFO "%s: SW TICK stuck? "
+ "bits=0x%lx EvStat=%04x IntEn=%04x\n",
+ dev->name, local->bits, evstat, inten);
+ }
+ local->sw_tick_stuck++;
+ if ((evstat & HFA384X_BAP0_EVENTS) &&
+ (inten & HFA384X_BAP0_EVENTS)) {
+ printk(KERN_INFO "%s: trying to recover from IRQ "
+ "hang\n", dev->name);
+ hfa384x_events_no_bap0(dev);
+ }
+ prev_stuck = 1;
+ } else
+ prev_stuck = 0;
+}
+
+
+/* Called only from hardware IRQ */
+static inline void prism2_check_magic(local_info_t *local)
+{
+ /* at least PCI Prism2.5 with bus mastering seems to sometimes
+ * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the
+ * register once or twice seems to get the correct value.. PCI cards
+ * cannot anyway be removed during normal operation, so there is not
+ * really any need for this verification with them. */
+
+#ifndef PRISM2_PCI
+#ifndef final_version
+ static unsigned long last_magic_err = 0;
+ struct net_device *dev = local->dev;
+
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) {
+ if (!local->hw_ready)
+ return;
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ if (time_after(jiffies, last_magic_err + 10 * HZ)) {
+ printk("%s: Interrupt, but SWSUPPORT0 does not match: "
+ "%04X != %04X - card removed?\n", dev->name,
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF),
+ HFA384X_MAGIC);
+ last_magic_err = jiffies;
+ } else if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: interrupt - SWSUPPORT0=%04x "
+ "MAGIC=%04x\n", dev->name,
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF),
+ HFA384X_MAGIC);
+ }
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != 0xffff)
+ schedule_work(&local->reset_queue);
+ return;
+ }
+#endif /* final_version */
+#endif /* !PRISM2_PCI */
+}
+
+
+/* Called only from hardware IRQ */
+static irqreturn_t prism2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int events = 0;
+ u16 ev;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
+
+ if (local->func->card_present && !local->func->card_present(local)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: Interrupt, but dev not OK\n",
+ dev->name);
+ }
+ return IRQ_HANDLED;
+ }
+
+ prism2_check_magic(local);
+
+ for (;;) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev == 0xffff) {
+ if (local->shutdown)
+ return IRQ_HANDLED;
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: prism2_interrupt: ev=0xffff\n",
+ dev->name);
+ return IRQ_HANDLED;
+ }
+
+ ev &= HFA384X_INW(HFA384X_INTEN_OFF);
+ if (ev == 0)
+ break;
+
+ if (ev & HFA384X_EV_CMD) {
+ prism2_cmd_ev(dev);
+ }
+
+ /* Above events are needed even before hw is ready, but other
+ * events should be skipped during initialization. This may
+ * change for AllocEv if allocate_fid is implemented without
+ * busy waiting. */
+ if (!local->hw_ready || local->hw_resetting ||
+ !local->dev_enabled) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev & HFA384X_EV_CMD)
+ goto next_event;
+ if ((ev & HFA384X_EVENT_MASK) == 0)
+ return IRQ_HANDLED;
+ if (local->dev_enabled && (ev & ~HFA384X_EV_TICK) &&
+ net_ratelimit()) {
+ printk(KERN_DEBUG "%s: prism2_interrupt: hw "
+ "not ready; skipping events 0x%04x "
+ "(IntEn=0x%04x)%s%s%s\n",
+ dev->name, ev,
+ HFA384X_INW(HFA384X_INTEN_OFF),
+ !local->hw_ready ? " (!hw_ready)" : "",
+ local->hw_resetting ?
+ " (hw_resetting)" : "",
+ !local->dev_enabled ?
+ " (!dev_enabled)" : "");
+ }
+ HFA384X_OUTW(ev, HFA384X_EVACK_OFF);
+ return IRQ_HANDLED;
+ }
+
+ if (ev & HFA384X_EV_TICK) {
+ prism2_ev_tick(dev);
+ HFA384X_OUTW(HFA384X_EV_TICK, HFA384X_EVACK_OFF);
+ }
+
+ if (ev & HFA384X_EV_ALLOC) {
+ prism2_alloc_ev(dev);
+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF);
+ }
+
+ /* Reading data from the card is quite time consuming, so do it
+ * in tasklets. TX, TXEXC, RX, and INFO events will be ACKed
+ * and unmasked after needed data has been read completely. */
+ if (ev & HFA384X_BAP0_EVENTS) {
+ hfa384x_events_no_bap0(dev);
+ tasklet_schedule(&local->bap_tasklet);
+ }
+
+#ifndef final_version
+ if (ev & HFA384X_EV_WTERR) {
+ PDEBUG(DEBUG_EXTRA, "%s: WTERR event\n", dev->name);
+ HFA384X_OUTW(HFA384X_EV_WTERR, HFA384X_EVACK_OFF);
+ }
+#endif /* final_version */
+
+ if (ev & HFA384X_EV_INFDROP) {
+ prism2_infdrop(dev);
+ HFA384X_OUTW(HFA384X_EV_INFDROP, HFA384X_EVACK_OFF);
+ }
+
+ next_event:
+ events++;
+ if (events >= PRISM2_MAX_INTERRUPT_EVENTS) {
+ PDEBUG(DEBUG_EXTRA, "prism2_interrupt: >%d events "
+ "(EvStat=0x%04x)\n",
+ PRISM2_MAX_INTERRUPT_EVENTS,
+ HFA384X_INW(HFA384X_EVSTAT_OFF));
+ break;
+ }
+ }
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 1);
+ return IRQ_RETVAL(events);
+}
+
+
+static void prism2_check_sta_fw_version(local_info_t *local)
+{
+ struct hfa384x_comp_ident comp;
+ int id, variant, major, minor;
+
+ if (hfa384x_get_rid(local->dev, HFA384X_RID_STAID,
+ &comp, sizeof(comp), 1) < 0)
+ return;
+
+ local->fw_ap = 0;
+ id = le16_to_cpu(comp.id);
+ if (id != HFA384X_COMP_ID_STA) {
+ if (id == HFA384X_COMP_ID_FW_AP)
+ local->fw_ap = 1;
+ return;
+ }
+
+ major = __le16_to_cpu(comp.major);
+ minor = __le16_to_cpu(comp.minor);
+ variant = __le16_to_cpu(comp.variant);
+ local->sta_fw_ver = PRISM2_FW_VER(major, minor, variant);
+
+ /* Station firmware versions before 1.4.x seem to have a bug in
+ * firmware-based WEP encryption when using Host AP mode, so use
+ * host_encrypt as a default for them. Firmware version 1.4.9 is the
+ * first one that has been seen to produce correct encryption, but the
+ * bug might be fixed before that (although, at least 1.4.2 is broken).
+ */
+ local->fw_encrypt_ok = local->sta_fw_ver >= PRISM2_FW_VER(1,4,9);
+
+ if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
+ !local->fw_encrypt_ok) {
+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
+ "a workaround for firmware bug in Host AP mode WEP\n",
+ local->dev->name);
+ local->host_encrypt = 1;
+ }
+
+ /* IEEE 802.11 standard compliant WDS frames (4 addresses) were broken
+ * in station firmware versions before 1.5.x. With these versions, the
+ * driver uses a workaround with bogus frame format (4th address after
+ * the payload). This is not compatible with other AP devices. Since
+ * the firmware bug is fixed in the latest station firmware versions,
+ * automatically enable standard compliant mode for cards using station
+ * firmware version 1.5.0 or newer. */
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,5,0))
+ local->wds_type |= HOSTAP_WDS_STANDARD_FRAME;
+ else {
+ printk(KERN_DEBUG "%s: defaulting to bogus WDS frame as a "
+ "workaround for firmware bug in Host AP mode WDS\n",
+ local->dev->name);
+ }
+
+ hostap_check_sta_fw_version(local->ap, local->sta_fw_ver);
+}
+
+
+static void prism2_crypt_deinit_entries(local_info_t *local, int force)
+{
+ struct list_head *ptr, *n;
+ struct ieee80211_crypt_data *entry;
+
+ for (ptr = local->crypt_deinit_list.next, n = ptr->next;
+ ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct ieee80211_crypt_data, list);
+
+ if (atomic_read(&entry->refcnt) != 0 && !force)
+ continue;
+
+ list_del(ptr);
+
+ if (entry->ops)
+ entry->ops->deinit(entry->priv);
+ kfree(entry);
+ }
+}
+
+
+static void prism2_crypt_deinit_handler(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_crypt_deinit_entries(local, 0);
+ if (!list_empty(&local->crypt_deinit_list)) {
+ printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
+ "deletion list\n", local->dev->name);
+ local->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&local->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+}
+
+
+static void hostap_passive_scan(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct net_device *dev = local->dev;
+ u16 channel;
+
+ if (local->passive_scan_interval <= 0)
+ return;
+
+ if (local->passive_scan_state == PASSIVE_SCAN_LISTEN) {
+ int max_tries = 16;
+
+ /* Even though host system does not really know when the WLAN
+ * MAC is sending frames, try to avoid changing channels for
+ * passive scanning when a host-generated frame is being
+ * transmitted */
+ if (test_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: passive scan detected pending "
+ "TX - delaying\n", dev->name);
+ local->passive_scan_timer.expires = jiffies + HZ / 10;
+ add_timer(&local->passive_scan_timer);
+ return;
+ }
+
+ do {
+ local->passive_scan_channel++;
+ if (local->passive_scan_channel > 14)
+ local->passive_scan_channel = 1;
+ max_tries--;
+ } while (!(local->channel_mask &
+ (1 << (local->passive_scan_channel - 1))) &&
+ max_tries > 0);
+
+ if (max_tries == 0) {
+ printk(KERN_INFO "%s: no allowed passive scan channels"
+ " found\n", dev->name);
+ return;
+ }
+
+ printk(KERN_DEBUG "%s: passive scan channel %d\n",
+ dev->name, local->passive_scan_channel);
+ channel = local->passive_scan_channel;
+ local->passive_scan_state = PASSIVE_SCAN_WAIT;
+ local->passive_scan_timer.expires = jiffies + HZ / 10;
+ } else {
+ channel = local->channel;
+ local->passive_scan_state = PASSIVE_SCAN_LISTEN;
+ local->passive_scan_timer.expires = jiffies +
+ local->passive_scan_interval * HZ;
+ }
+
+ if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CHANGE_CHANNEL << 8),
+ channel, NULL, 0))
+ printk(KERN_ERR "%s: passive scan channel set %d "
+ "failed\n", dev->name, channel);
+
+ add_timer(&local->passive_scan_timer);
+}
+
+
+/* Called only as a scheduled task when communications quality values should
+ * be updated. */
+static void handle_comms_qual_update(void *data)
+{
+ local_info_t *local = data;
+ prism2_update_comms_qual(local->dev);
+}
+
+
+/* Software watchdog - called as a timer. Hardware interrupt (Tick event) is
+ * used to monitor that local->last_tick_timer is being updated. If not,
+ * interrupt busy-loop is assumed and driver tries to recover by masking out
+ * some events. */
+static void hostap_tick_timer(unsigned long data)
+{
+ static unsigned long last_inquire = 0;
+ local_info_t *local = (local_info_t *) data;
+ local->last_tick_timer = jiffies;
+
+ /* Inquire CommTallies every 10 seconds to keep the statistics updated
+ * more often during low load and when using 32-bit tallies. */
+ if ((!last_inquire || time_after(jiffies, last_inquire + 10 * HZ)) &&
+ !local->hw_downloading && local->hw_ready &&
+ !local->hw_resetting && local->dev_enabled) {
+ hfa384x_cmd_callback(local->dev, HFA384X_CMDCODE_INQUIRE,
+ HFA384X_INFO_COMMTALLIES, NULL, 0);
+ last_inquire = jiffies;
+ }
+
+ if ((local->last_comms_qual_update == 0 ||
+ time_after(jiffies, local->last_comms_qual_update + 10 * HZ)) &&
+ (local->iw_mode == IW_MODE_INFRA ||
+ local->iw_mode == IW_MODE_ADHOC)) {
+ schedule_work(&local->comms_qual_update);
+ }
+
+ local->tick_timer.expires = jiffies + 2 * HZ;
+ add_timer(&local->tick_timer);
+}
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int prism2_registers_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+#define SHOW_REG(n) \
+p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF))
+
+ SHOW_REG(CMD);
+ SHOW_REG(PARAM0);
+ SHOW_REG(PARAM1);
+ SHOW_REG(PARAM2);
+ SHOW_REG(STATUS);
+ SHOW_REG(RESP0);
+ SHOW_REG(RESP1);
+ SHOW_REG(RESP2);
+ SHOW_REG(INFOFID);
+ SHOW_REG(CONTROL);
+ SHOW_REG(SELECT0);
+ SHOW_REG(SELECT1);
+ SHOW_REG(OFFSET0);
+ SHOW_REG(OFFSET1);
+ SHOW_REG(RXFID);
+ SHOW_REG(ALLOCFID);
+ SHOW_REG(TXCOMPLFID);
+ SHOW_REG(SWSUPPORT0);
+ SHOW_REG(SWSUPPORT1);
+ SHOW_REG(SWSUPPORT2);
+ SHOW_REG(EVSTAT);
+ SHOW_REG(INTEN);
+ SHOW_REG(EVACK);
+ /* Do not read data registers, because they change the state of the
+ * MAC (offset += 2) */
+ /* SHOW_REG(DATA0); */
+ /* SHOW_REG(DATA1); */
+ SHOW_REG(AUXPAGE);
+ SHOW_REG(AUXOFFSET);
+ /* SHOW_REG(AUXDATA); */
+#ifdef PRISM2_PCI
+ SHOW_REG(PCICOR);
+ SHOW_REG(PCIHCR);
+ SHOW_REG(PCI_M0_ADDRH);
+ SHOW_REG(PCI_M0_ADDRL);
+ SHOW_REG(PCI_M0_LEN);
+ SHOW_REG(PCI_M0_CTL);
+ SHOW_REG(PCI_STATUS);
+ SHOW_REG(PCI_M1_ADDRH);
+ SHOW_REG(PCI_M1_ADDRL);
+ SHOW_REG(PCI_M1_LEN);
+ SHOW_REG(PCI_M1_CTL);
+#endif /* PRISM2_PCI */
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+struct set_tim_data {
+ struct list_head list;
+ int aid;
+ int set;
+};
+
+static int prism2_set_tim(struct net_device *dev, int aid, int set)
+{
+ struct list_head *ptr;
+ struct set_tim_data *new_entry;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ new_entry = (struct set_tim_data *)
+ kmalloc(sizeof(*new_entry), GFP_ATOMIC);
+ if (new_entry == NULL) {
+ printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n",
+ local->dev->name);
+ return -ENOMEM;
+ }
+ memset(new_entry, 0, sizeof(*new_entry));
+ new_entry->aid = aid;
+ new_entry->set = set;
+
+ spin_lock_bh(&local->set_tim_lock);
+ list_for_each(ptr, &local->set_tim_list) {
+ struct set_tim_data *entry =
+ list_entry(ptr, struct set_tim_data, list);
+ if (entry->aid == aid) {
+ PDEBUG(DEBUG_PS2, "%s: prism2_set_tim: aid=%d "
+ "set=%d ==> %d\n",
+ local->dev->name, aid, entry->set, set);
+ entry->set = set;
+ kfree(new_entry);
+ new_entry = NULL;
+ break;
+ }
+ }
+ if (new_entry)
+ list_add_tail(&new_entry->list, &local->set_tim_list);
+ spin_unlock_bh(&local->set_tim_lock);
+
+ schedule_work(&local->set_tim_queue);
+
+ return 0;
+}
+
+
+static void handle_set_tim_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct set_tim_data *entry;
+ u16 val;
+
+ for (;;) {
+ entry = NULL;
+ spin_lock_bh(&local->set_tim_lock);
+ if (!list_empty(&local->set_tim_list)) {
+ entry = list_entry(local->set_tim_list.next,
+ struct set_tim_data, list);
+ list_del(&entry->list);
+ }
+ spin_unlock_bh(&local->set_tim_lock);
+ if (!entry)
+ break;
+
+ PDEBUG(DEBUG_PS2, "%s: handle_set_tim_queue: aid=%d set=%d\n",
+ local->dev->name, entry->aid, entry->set);
+
+ val = entry->aid;
+ if (entry->set)
+ val |= 0x8000;
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFTIMCTRL, val)) {
+ printk(KERN_DEBUG "%s: set_tim failed (aid=%d "
+ "set=%d)\n",
+ local->dev->name, entry->aid, entry->set);
+ }
+
+ kfree(entry);
+ }
+}
+
+
+static void prism2_clear_set_tim_queue(local_info_t *local)
+{
+ struct list_head *ptr, *n;
+
+ list_for_each_safe(ptr, n, &local->set_tim_list) {
+ struct set_tim_data *entry;
+ entry = list_entry(ptr, struct set_tim_data, list);
+ list_del(&entry->list);
+ kfree(entry);
+ }
+}
+
+
+static struct net_device *
+prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
+ struct device *sdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ struct local_info *local;
+ int len, i, ret;
+
+ if (funcs == NULL)
+ return NULL;
+
+ len = strlen(dev_template);
+ if (len >= IFNAMSIZ || strstr(dev_template, "%d") == NULL) {
+ printk(KERN_WARNING "hostap: Invalid dev_template='%s'\n",
+ dev_template);
+ return NULL;
+ }
+
+ len = sizeof(struct hostap_interface) +
+ 3 + sizeof(struct local_info) +
+ 3 + sizeof(struct ap_data);
+
+ dev = alloc_etherdev(len);
+ if (dev == NULL)
+ return NULL;
+
+ iface = netdev_priv(dev);
+ local = (struct local_info *) ((((long) (iface + 1)) + 3) & ~3);
+ local->ap = (struct ap_data *) ((((long) (local + 1)) + 3) & ~3);
+ local->dev = iface->dev = dev;
+ iface->local = local;
+ iface->type = HOSTAP_INTERFACE_MASTER;
+ INIT_LIST_HEAD(&local->hostap_interfaces);
+
+ local->hw_module = THIS_MODULE;
+
+#ifdef PRISM2_IO_DEBUG
+ local->io_debug_enabled = 1;
+#endif /* PRISM2_IO_DEBUG */
+
+ local->func = funcs;
+ local->func->cmd = hfa384x_cmd;
+ local->func->read_regs = hfa384x_read_regs;
+ local->func->get_rid = hfa384x_get_rid;
+ local->func->set_rid = hfa384x_set_rid;
+ local->func->hw_enable = prism2_hw_enable;
+ local->func->hw_config = prism2_hw_config;
+ local->func->hw_reset = prism2_hw_reset;
+ local->func->hw_shutdown = prism2_hw_shutdown;
+ local->func->reset_port = prism2_reset_port;
+ local->func->schedule_reset = prism2_schedule_reset;
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ local->func->read_aux = prism2_download_aux_dump;
+ local->func->download = prism2_download;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+ local->func->tx = prism2_tx_80211;
+ local->func->set_tim = prism2_set_tim;
+ local->func->need_tx_headroom = 0; /* no need to add txdesc in
+ * skb->data (FIX: maybe for DMA bus
+ * mastering? */
+
+ local->mtu = mtu;
+
+ rwlock_init(&local->iface_lock);
+ spin_lock_init(&local->txfidlock);
+ spin_lock_init(&local->cmdlock);
+ spin_lock_init(&local->baplock);
+ spin_lock_init(&local->lock);
+ init_MUTEX(&local->rid_bap_sem);
+
+ if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
+ card_idx = 0;
+ local->card_idx = card_idx;
+
+ len = strlen(essid);
+ memcpy(local->essid, essid,
+ len > MAX_SSID_LEN ? MAX_SSID_LEN : len);
+ local->essid[MAX_SSID_LEN] = '\0';
+ i = GET_INT_PARM(iw_mode, card_idx);
+ if ((i >= IW_MODE_ADHOC && i <= IW_MODE_REPEAT) ||
+ i == IW_MODE_MONITOR) {
+ local->iw_mode = i;
+ } else {
+ printk(KERN_WARNING "prism2: Unknown iw_mode %d; using "
+ "IW_MODE_MASTER\n", i);
+ local->iw_mode = IW_MODE_MASTER;
+ }
+ local->channel = GET_INT_PARM(channel, card_idx);
+ local->beacon_int = GET_INT_PARM(beacon_int, card_idx);
+ local->dtim_period = GET_INT_PARM(dtim_period, card_idx);
+ local->wds_max_connections = 16;
+ local->tx_control = HFA384X_TX_CTRL_FLAGS;
+ local->manual_retry_count = -1;
+ local->rts_threshold = 2347;
+ local->fragm_threshold = 2346;
+ local->rssi_to_dBm = 100; /* default; to be overriden by
+ * cnfDbmAdjust, if available */
+ local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY;
+ local->sram_type = -1;
+ local->scan_channel_mask = 0xffff;
+
+ /* Initialize task queue structures */
+ INIT_WORK(&local->reset_queue, handle_reset_queue, local);
+ INIT_WORK(&local->set_multicast_list_queue,
+ hostap_set_multicast_list_queue, local->dev);
+
+ INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local);
+ INIT_LIST_HEAD(&local->set_tim_list);
+ spin_lock_init(&local->set_tim_lock);
+
+ INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local);
+
+ /* Initialize tasklets for handling hardware IRQ related operations
+ * outside hw IRQ handler */
+#define HOSTAP_TASKLET_INIT(q, f, d) \
+do { memset((q), 0, sizeof(*(q))); (q)->func = (f); (q)->data = (d); } \
+while (0)
+ HOSTAP_TASKLET_INIT(&local->bap_tasklet, hostap_bap_tasklet,
+ (unsigned long) local);
+
+ HOSTAP_TASKLET_INIT(&local->info_tasklet, hostap_info_tasklet,
+ (unsigned long) local);
+ hostap_info_init(local);
+
+ HOSTAP_TASKLET_INIT(&local->rx_tasklet,
+ hostap_rx_tasklet, (unsigned long) local);
+ skb_queue_head_init(&local->rx_list);
+
+ HOSTAP_TASKLET_INIT(&local->sta_tx_exc_tasklet,
+ hostap_sta_tx_exc_tasklet, (unsigned long) local);
+ skb_queue_head_init(&local->sta_tx_exc_list);
+
+ INIT_LIST_HEAD(&local->cmd_queue);
+ init_waitqueue_head(&local->hostscan_wq);
+ INIT_LIST_HEAD(&local->crypt_deinit_list);
+ init_timer(&local->crypt_deinit_timer);
+ local->crypt_deinit_timer.data = (unsigned long) local;
+ local->crypt_deinit_timer.function = prism2_crypt_deinit_handler;
+
+ init_timer(&local->passive_scan_timer);
+ local->passive_scan_timer.data = (unsigned long) local;
+ local->passive_scan_timer.function = hostap_passive_scan;
+
+ init_timer(&local->tick_timer);
+ local->tick_timer.data = (unsigned long) local;
+ local->tick_timer.function = hostap_tick_timer;
+ local->tick_timer.expires = jiffies + 2 * HZ;
+ add_timer(&local->tick_timer);
+
+ INIT_LIST_HEAD(&local->bss_list);
+
+ hostap_setup_dev(dev, local, 1);
+ local->saved_eth_header_parse = dev->hard_header_parse;
+
+ dev->hard_start_xmit = hostap_master_start_xmit;
+ dev->type = ARPHRD_IEEE80211;
+ dev->hard_header_parse = hostap_80211_header_parse;
+
+ rtnl_lock();
+ ret = dev_alloc_name(dev, "wifi%d");
+ SET_NETDEV_DEV(dev, sdev);
+ if (ret >= 0)
+ ret = register_netdevice(dev);
+ rtnl_unlock();
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: register netdevice failed!\n",
+ dev_info);
+ goto fail;
+ }
+ printk(KERN_INFO "%s: Registered netdevice %s\n", dev_info, dev->name);
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("registers", 0, local->proc,
+ prism2_registers_proc_read, local);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+ hostap_init_data(local);
+ return dev;
+
+ fail:
+ free_netdev(dev);
+ return NULL;
+}
+
+
+static int hostap_hw_ready(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ struct local_info *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->ddev = hostap_add_interface(local, HOSTAP_INTERFACE_MAIN, 0,
+ "", dev_template);
+
+ if (local->ddev) {
+ if (local->iw_mode == IW_MODE_INFRA ||
+ local->iw_mode == IW_MODE_ADHOC) {
+ netif_carrier_off(local->dev);
+ netif_carrier_off(local->ddev);
+ }
+ hostap_init_proc(local);
+ hostap_init_ap_proc(local);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static void prism2_free_local_data(struct net_device *dev)
+{
+ struct hostap_tx_callback_info *tx_cb, *tx_cb_prev;
+ int i;
+ struct hostap_interface *iface;
+ struct local_info *local;
+ struct list_head *ptr, *n;
+
+ if (dev == NULL)
+ return;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ flush_scheduled_work();
+
+ if (timer_pending(&local->crypt_deinit_timer))
+ del_timer(&local->crypt_deinit_timer);
+ prism2_crypt_deinit_entries(local, 1);
+
+ if (timer_pending(&local->passive_scan_timer))
+ del_timer(&local->passive_scan_timer);
+
+ if (timer_pending(&local->tick_timer))
+ del_timer(&local->tick_timer);
+
+ prism2_clear_cmd_queue(local);
+
+ skb_queue_purge(&local->info_list);
+ skb_queue_purge(&local->rx_list);
+ skb_queue_purge(&local->sta_tx_exc_list);
+
+ if (local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_DISABLE);
+
+ for (i = 0; i < WEP_KEYS; i++) {
+ struct ieee80211_crypt_data *crypt = local->crypt[i];
+ if (crypt) {
+ if (crypt->ops)
+ crypt->ops->deinit(crypt->priv);
+ kfree(crypt);
+ local->crypt[i] = NULL;
+ }
+ }
+
+ if (local->ap != NULL)
+ hostap_free_data(local->ap);
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ if (local->proc != NULL)
+ remove_proc_entry("registers", local->proc);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ hostap_remove_proc(local);
+
+ tx_cb = local->tx_callback;
+ while (tx_cb != NULL) {
+ tx_cb_prev = tx_cb;
+ tx_cb = tx_cb->next;
+ kfree(tx_cb_prev);
+ }
+
+ hostap_set_hostapd(local, 0, 0);
+ hostap_set_hostapd_sta(local, 0, 0);
+
+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
+ if (local->frag_cache[i].skb != NULL)
+ dev_kfree_skb(local->frag_cache[i].skb);
+ }
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ prism2_download_free_data(local->dl_pri);
+ prism2_download_free_data(local->dl_sec);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_MASTER) {
+ /* special handling for this interface below */
+ continue;
+ }
+ hostap_remove_interface(iface->dev, 0, 1);
+ }
+
+ prism2_clear_set_tim_queue(local);
+
+ list_for_each_safe(ptr, n, &local->bss_list) {
+ struct hostap_bss_info *bss =
+ list_entry(ptr, struct hostap_bss_info, list);
+ kfree(bss);
+ }
+
+ kfree(local->pda);
+ kfree(local->last_scan_results);
+ kfree(local->generic_elem);
+
+ unregister_netdev(local->dev);
+ free_netdev(local->dev);
+}
+
+
+#ifndef PRISM2_PLX
+static void prism2_suspend(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ struct local_info *local;
+ union iwreq_data wrqu;
+
+ iface = dev->priv;
+ local = iface->local;
+
+ /* Send disconnect event, e.g., to trigger reassociation after resume
+ * if wpa_supplicant is used. */
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+
+ /* Disable hardware and firmware */
+ prism2_hw_shutdown(dev, 0);
+}
+#endif /* PRISM2_PLX */
+
+
+/* These might at some point be compiled separately and used as separate
+ * kernel modules or linked into one */
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+#include "hostap_download.c"
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+#ifdef PRISM2_CALLBACK
+/* External hostap_callback.c file can be used to, e.g., blink activity led.
+ * This can use platform specific code and must define prism2_callback()
+ * function (if PRISM2_CALLBACK is not defined, these function calls are not
+ * used. */
+#include "hostap_callback.c"
+#endif /* PRISM2_CALLBACK */
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
new file mode 100644
index 000000000000..5aa998fdf1c4
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -0,0 +1,499 @@
+/* Host AP driver Info Frame processing (part of hostap.o module) */
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ struct hfa384x_comm_tallies *tallies;
+
+ if (left < sizeof(struct hfa384x_comm_tallies)) {
+ printk(KERN_DEBUG "%s: too short (len=%d) commtallies "
+ "info frame\n", local->dev->name, left);
+ return;
+ }
+
+ tallies = (struct hfa384x_comm_tallies *) buf;
+#define ADD_COMM_TALLIES(name) \
+local->comm_tallies.name += le16_to_cpu(tallies->name)
+ ADD_COMM_TALLIES(tx_unicast_frames);
+ ADD_COMM_TALLIES(tx_multicast_frames);
+ ADD_COMM_TALLIES(tx_fragments);
+ ADD_COMM_TALLIES(tx_unicast_octets);
+ ADD_COMM_TALLIES(tx_multicast_octets);
+ ADD_COMM_TALLIES(tx_deferred_transmissions);
+ ADD_COMM_TALLIES(tx_single_retry_frames);
+ ADD_COMM_TALLIES(tx_multiple_retry_frames);
+ ADD_COMM_TALLIES(tx_retry_limit_exceeded);
+ ADD_COMM_TALLIES(tx_discards);
+ ADD_COMM_TALLIES(rx_unicast_frames);
+ ADD_COMM_TALLIES(rx_multicast_frames);
+ ADD_COMM_TALLIES(rx_fragments);
+ ADD_COMM_TALLIES(rx_unicast_octets);
+ ADD_COMM_TALLIES(rx_multicast_octets);
+ ADD_COMM_TALLIES(rx_fcs_errors);
+ ADD_COMM_TALLIES(rx_discards_no_buffer);
+ ADD_COMM_TALLIES(tx_discards_wrong_sa);
+ ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
+ ADD_COMM_TALLIES(rx_message_in_msg_fragments);
+ ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
+#undef ADD_COMM_TALLIES
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies32(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ struct hfa384x_comm_tallies32 *tallies;
+
+ if (left < sizeof(struct hfa384x_comm_tallies32)) {
+ printk(KERN_DEBUG "%s: too short (len=%d) commtallies32 "
+ "info frame\n", local->dev->name, left);
+ return;
+ }
+
+ tallies = (struct hfa384x_comm_tallies32 *) buf;
+#define ADD_COMM_TALLIES(name) \
+local->comm_tallies.name += le32_to_cpu(tallies->name)
+ ADD_COMM_TALLIES(tx_unicast_frames);
+ ADD_COMM_TALLIES(tx_multicast_frames);
+ ADD_COMM_TALLIES(tx_fragments);
+ ADD_COMM_TALLIES(tx_unicast_octets);
+ ADD_COMM_TALLIES(tx_multicast_octets);
+ ADD_COMM_TALLIES(tx_deferred_transmissions);
+ ADD_COMM_TALLIES(tx_single_retry_frames);
+ ADD_COMM_TALLIES(tx_multiple_retry_frames);
+ ADD_COMM_TALLIES(tx_retry_limit_exceeded);
+ ADD_COMM_TALLIES(tx_discards);
+ ADD_COMM_TALLIES(rx_unicast_frames);
+ ADD_COMM_TALLIES(rx_multicast_frames);
+ ADD_COMM_TALLIES(rx_fragments);
+ ADD_COMM_TALLIES(rx_unicast_octets);
+ ADD_COMM_TALLIES(rx_multicast_octets);
+ ADD_COMM_TALLIES(rx_fcs_errors);
+ ADD_COMM_TALLIES(rx_discards_no_buffer);
+ ADD_COMM_TALLIES(tx_discards_wrong_sa);
+ ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
+ ADD_COMM_TALLIES(rx_message_in_msg_fragments);
+ ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
+#undef ADD_COMM_TALLIES
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ if (local->tallies32)
+ prism2_info_commtallies32(local, buf, left);
+ else
+ prism2_info_commtallies16(local, buf, left);
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+#ifndef PRISM2_NO_DEBUG
+static const char* hfa384x_linkstatus_str(u16 linkstatus)
+{
+ switch (linkstatus) {
+ case HFA384X_LINKSTATUS_CONNECTED:
+ return "Connected";
+ case HFA384X_LINKSTATUS_DISCONNECTED:
+ return "Disconnected";
+ case HFA384X_LINKSTATUS_AP_CHANGE:
+ return "Access point change";
+ case HFA384X_LINKSTATUS_AP_OUT_OF_RANGE:
+ return "Access point out of range";
+ case HFA384X_LINKSTATUS_AP_IN_RANGE:
+ return "Access point in range";
+ case HFA384X_LINKSTATUS_ASSOC_FAILED:
+ return "Association failed";
+ default:
+ return "Unknown";
+ }
+}
+#endif /* PRISM2_NO_DEBUG */
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_linkstatus(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ u16 val;
+ int non_sta_mode;
+
+ /* Alloc new JoinRequests to occur since LinkStatus for the previous
+ * has been received */
+ local->last_join_time = 0;
+
+ if (left != 2) {
+ printk(KERN_DEBUG "%s: invalid linkstatus info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ non_sta_mode = local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT ||
+ local->iw_mode == IW_MODE_MONITOR;
+
+ val = buf[0] | (buf[1] << 8);
+ if (!non_sta_mode || val != HFA384X_LINKSTATUS_DISCONNECTED) {
+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus=%d (%s)\n",
+ local->dev->name, val, hfa384x_linkstatus_str(val));
+ }
+
+ if (non_sta_mode) {
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ return;
+ }
+
+ /* Get current BSSID later in scheduled task */
+ set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info);
+ local->prev_link_status = val;
+ schedule_work(&local->info_queue);
+}
+
+
+static void prism2_host_roaming(local_info_t *local)
+{
+ struct hfa384x_join_request req;
+ struct net_device *dev = local->dev;
+ struct hfa384x_hostscan_result *selected, *entry;
+ int i;
+ unsigned long flags;
+
+ if (local->last_join_time &&
+ time_before(jiffies, local->last_join_time + 10 * HZ)) {
+ PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been "
+ "completed - waiting for it before issuing new one\n",
+ dev->name);
+ return;
+ }
+
+ /* ScanResults are sorted: first ESS results in decreasing signal
+ * quality then IBSS results in similar order.
+ * Trivial roaming policy: just select the first entry.
+ * This could probably be improved by adding hysteresis to limit
+ * number of handoffs, etc.
+ *
+ * Could do periodic RID_SCANREQUEST or Inquire F101 to get new
+ * ScanResults */
+ spin_lock_irqsave(&local->lock, flags);
+ if (local->last_scan_results == NULL ||
+ local->last_scan_results_count == 0) {
+ spin_unlock_irqrestore(&local->lock, flags);
+ PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n",
+ dev->name);
+ return;
+ }
+
+ selected = &local->last_scan_results[0];
+
+ if (local->preferred_ap[0] || local->preferred_ap[1] ||
+ local->preferred_ap[2] || local->preferred_ap[3] ||
+ local->preferred_ap[4] || local->preferred_ap[5]) {
+ /* Try to find preferred AP */
+ PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n",
+ dev->name, MAC2STR(local->preferred_ap));
+ for (i = 0; i < local->last_scan_results_count; i++) {
+ entry = &local->last_scan_results[i];
+ if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
+ {
+ PDEBUG(DEBUG_EXTRA, "%s: using preferred AP "
+ "selection\n", dev->name);
+ selected = entry;
+ break;
+ }
+ }
+ }
+
+ memcpy(req.bssid, selected->bssid, 6);
+ req.channel = selected->chid;
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n",
+ dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel));
+ if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
+ sizeof(req))) {
+ printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
+ }
+ local->last_join_time = jiffies;
+}
+
+
+static void hostap_report_scan_complete(local_info_t *local)
+{
+ union iwreq_data wrqu;
+
+ /* Inform user space about new scan results (just empty event,
+ * SIOCGIWSCAN can be used to fetch data */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL);
+
+ /* Allow SIOCGIWSCAN handling to occur since we have received
+ * scanning result */
+ local->scan_timestamp = 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ u16 *pos;
+ int new_count, i;
+ unsigned long flags;
+ struct hfa384x_scan_result *res;
+ struct hfa384x_hostscan_result *results, *prev;
+
+ if (left < 4) {
+ printk(KERN_DEBUG "%s: invalid scanresult info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ pos = (u16 *) buf;
+ pos++;
+ pos++;
+ left -= 4;
+
+ new_count = left / sizeof(struct hfa384x_scan_result);
+ results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+ GFP_ATOMIC);
+ if (results == NULL)
+ return;
+
+ /* Convert to hostscan result format. */
+ res = (struct hfa384x_scan_result *) pos;
+ for (i = 0; i < new_count; i++) {
+ memcpy(&results[i], &res[i],
+ sizeof(struct hfa384x_scan_result));
+ results[i].atim = 0;
+ }
+
+ spin_lock_irqsave(&local->lock, flags);
+ local->last_scan_type = PRISM2_SCAN;
+ prev = local->last_scan_results;
+ local->last_scan_results = results;
+ local->last_scan_results_count = new_count;
+ spin_unlock_irqrestore(&local->lock, flags);
+ kfree(prev);
+
+ hostap_report_scan_complete(local);
+
+ /* Perform rest of ScanResults handling later in scheduled task */
+ set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info);
+ schedule_work(&local->info_queue);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_hostscanresults(local_info_t *local,
+ unsigned char *buf, int left)
+{
+ int i, result_size, copy_len, new_count;
+ struct hfa384x_hostscan_result *results, *prev;
+ unsigned long flags;
+ u16 *pos;
+ u8 *ptr;
+
+ wake_up_interruptible(&local->hostscan_wq);
+
+ if (left < 4) {
+ printk(KERN_DEBUG "%s: invalid hostscanresult info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ pos = (u16 *) buf;
+ copy_len = result_size = le16_to_cpu(*pos);
+ if (result_size == 0) {
+ printk(KERN_DEBUG "%s: invalid result_size (0) in "
+ "hostscanresults\n", local->dev->name);
+ return;
+ }
+ if (copy_len > sizeof(struct hfa384x_hostscan_result))
+ copy_len = sizeof(struct hfa384x_hostscan_result);
+
+ pos++;
+ pos++;
+ left -= 4;
+ ptr = (u8 *) pos;
+
+ new_count = left / result_size;
+ results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+ GFP_ATOMIC);
+ if (results == NULL)
+ return;
+ memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result));
+
+ for (i = 0; i < new_count; i++) {
+ memcpy(&results[i], ptr, copy_len);
+ ptr += result_size;
+ left -= result_size;
+ }
+
+ if (left) {
+ printk(KERN_DEBUG "%s: short HostScan result entry (%d/%d)\n",
+ local->dev->name, left, result_size);
+ }
+
+ spin_lock_irqsave(&local->lock, flags);
+ local->last_scan_type = PRISM2_HOSTSCAN;
+ prev = local->last_scan_results;
+ local->last_scan_results = results;
+ local->last_scan_results_count = new_count;
+ spin_unlock_irqrestore(&local->lock, flags);
+ kfree(prev);
+
+ hostap_report_scan_complete(local);
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_info_process(local_info_t *local, struct sk_buff *skb)
+{
+ struct hfa384x_info_frame *info;
+ unsigned char *buf;
+ int left;
+#ifndef PRISM2_NO_DEBUG
+ int i;
+#endif /* PRISM2_NO_DEBUG */
+
+ info = (struct hfa384x_info_frame *) skb->data;
+ buf = skb->data + sizeof(*info);
+ left = skb->len - sizeof(*info);
+
+ switch (info->type) {
+ case HFA384X_INFO_COMMTALLIES:
+ prism2_info_commtallies(local, buf, left);
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case HFA384X_INFO_LINKSTATUS:
+ prism2_info_linkstatus(local, buf, left);
+ break;
+
+ case HFA384X_INFO_SCANRESULTS:
+ prism2_info_scanresults(local, buf, left);
+ break;
+
+ case HFA384X_INFO_HOSTSCANRESULTS:
+ prism2_info_hostscanresults(local, buf, left);
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+#ifndef PRISM2_NO_DEBUG
+ default:
+ PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n",
+ local->dev->name, info->len, info->type);
+ PDEBUG(DEBUG_EXTRA, "Unknown info frame:");
+ for (i = 0; i < (left < 100 ? left : 100); i++)
+ PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]);
+ PDEBUG2(DEBUG_EXTRA, "\n");
+ break;
+#endif /* PRISM2_NO_DEBUG */
+ }
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static void handle_info_queue_linkstatus(local_info_t *local)
+{
+ int val = local->prev_link_status;
+ int connected;
+ union iwreq_data wrqu;
+
+ connected =
+ val == HFA384X_LINKSTATUS_CONNECTED ||
+ val == HFA384X_LINKSTATUS_AP_CHANGE ||
+ val == HFA384X_LINKSTATUS_AP_IN_RANGE;
+
+ if (local->func->get_rid(local->dev, HFA384X_RID_CURRENTBSSID,
+ local->bssid, ETH_ALEN, 1) < 0) {
+ printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
+ "LinkStatus event\n", local->dev->name);
+ } else {
+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=" MACSTR "\n",
+ local->dev->name,
+ MAC2STR((unsigned char *) local->bssid));
+ if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
+ hostap_add_sta(local->ap, local->bssid);
+ }
+
+ /* Get BSSID if we have a valid AP address */
+ if (connected) {
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ memcpy(wrqu.ap_addr.sa_data, local->bssid, ETH_ALEN);
+ } else {
+ netif_carrier_off(local->dev);
+ netif_carrier_off(local->ddev);
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ }
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ /*
+ * Filter out sequential disconnect events in order not to cause a
+ * flood of SIOCGIWAP events that have a race condition with EAPOL
+ * frames and can confuse wpa_supplicant about the current association
+ * status.
+ */
+ if (connected || local->prev_linkstatus_connected)
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+ local->prev_linkstatus_connected = connected;
+}
+
+
+static void handle_info_queue_scanresults(local_info_t *local)
+{
+ if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA)
+ prism2_host_roaming(local);
+
+ if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA &&
+ memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00",
+ ETH_ALEN) != 0) {
+ /*
+ * Firmware seems to be getting into odd state in host_roaming
+ * mode 2 when hostscan is used without join command, so try
+ * to fix this by re-joining the current AP. This does not
+ * actually trigger a new association if the current AP is
+ * still in the scan results.
+ */
+ prism2_host_roaming(local);
+ }
+}
+
+
+/* Called only as scheduled task after receiving info frames (used to avoid
+ * pending too much time in HW IRQ handler). */
+static void handle_info_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS,
+ &local->pending_info))
+ handle_info_queue_linkstatus(local);
+
+ if (test_and_clear_bit(PRISM2_INFO_PENDING_SCANRESULTS,
+ &local->pending_info))
+ handle_info_queue_scanresults(local);
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+void hostap_info_init(local_info_t *local)
+{
+ skb_queue_head_init(&local->info_list);
+#ifndef PRISM2_NO_STATION_MODES
+ INIT_WORK(&local->info_queue, handle_info_queue, local);
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+EXPORT_SYMBOL(hostap_info_init);
+EXPORT_SYMBOL(hostap_info_process);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
new file mode 100644
index 000000000000..e720369a3515
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -0,0 +1,4102 @@
+/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
+
+#ifdef in_atomic
+/* Get kernel_locked() for in_atomic() */
+#include <linux/smp_lock.h>
+#endif
+#include <linux/ethtool.h>
+
+
+static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct iw_statistics *wstats;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Why are we doing that ? Jean II */
+ if (iface->type != HOSTAP_INTERFACE_MAIN)
+ return NULL;
+
+ wstats = &local->wstats;
+
+ wstats->status = 0;
+ wstats->discard.code =
+ local->comm_tallies.rx_discards_wep_undecryptable;
+ wstats->discard.misc =
+ local->comm_tallies.rx_fcs_errors +
+ local->comm_tallies.rx_discards_no_buffer +
+ local->comm_tallies.tx_discards_wrong_sa;
+
+ wstats->discard.retries =
+ local->comm_tallies.tx_retry_limit_exceeded;
+ wstats->discard.fragment =
+ local->comm_tallies.rx_message_in_bad_msg_fragments;
+
+ if (local->iw_mode != IW_MODE_MASTER &&
+ local->iw_mode != IW_MODE_REPEAT) {
+ int update = 1;
+#ifdef in_atomic
+ /* RID reading might sleep and it must not be called in
+ * interrupt context or while atomic. However, this
+ * function seems to be called while atomic (at least in Linux
+ * 2.5.59). Update signal quality values only if in suitable
+ * context. Otherwise, previous values read from tick timer
+ * will be used. */
+ if (in_atomic())
+ update = 0;
+#endif /* in_atomic */
+
+ if (update && prism2_update_comms_qual(dev) == 0)
+ wstats->qual.updated = 7;
+
+ wstats->qual.qual = local->comms_qual;
+ wstats->qual.level = local->avg_signal;
+ wstats->qual.noise = local->avg_noise;
+ } else {
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 0;
+ }
+
+ return wstats;
+}
+
+
+static int prism2_get_datarates(struct net_device *dev, u8 *rates)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u8 buf[12];
+ int len;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf,
+ sizeof(buf), 0);
+ if (len < 2)
+ return 0;
+
+ val = le16_to_cpu(*(u16 *) buf); /* string length */
+
+ if (len - 2 < val || val > 10)
+ return 0;
+
+ memcpy(rates, buf + 2, val);
+ return val;
+}
+
+
+static int prism2_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *name, char *extra)
+{
+ u8 rates[10];
+ int len, i, over2 = 0;
+
+ len = prism2_get_datarates(dev, rates);
+
+ for (i = 0; i < len; i++) {
+ if (rates[i] == 0x0b || rates[i] == 0x16) {
+ over2 = 1;
+ break;
+ }
+ }
+
+ strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS");
+
+ return 0;
+}
+
+
+static void prism2_crypt_delayed_deinit(local_info_t *local,
+ struct ieee80211_crypt_data **crypt)
+{
+ struct ieee80211_crypt_data *tmp;
+ unsigned long flags;
+
+ tmp = *crypt;
+ *crypt = NULL;
+
+ if (tmp == NULL)
+ return;
+
+ /* must not run ops->deinit() while there may be pending encrypt or
+ * decrypt operations. Use a list of delayed deinits to avoid needing
+ * locking. */
+
+ spin_lock_irqsave(&local->lock, flags);
+ list_add(&tmp->list, &local->crypt_deinit_list);
+ if (!timer_pending(&local->crypt_deinit_timer)) {
+ local->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&local->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+
+static int prism2_ioctl_siwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i;
+ struct ieee80211_crypt_data **crypt;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > 4)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ crypt = &local->crypt[i];
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ if (*crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ if (*crypt != NULL && (*crypt)->ops != NULL &&
+ strcmp((*crypt)->ops->name, "WEP") != 0) {
+ /* changing to use WEP; deinit previously used algorithm */
+ prism2_crypt_delayed_deinit(local, crypt);
+ }
+
+ if (*crypt == NULL) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ /* take WEP into use */
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL)
+ return -ENOMEM;
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ if (!new_crypt->ops) {
+ request_module("ieee80211_crypt_wep");
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ }
+ if (new_crypt->ops)
+ new_crypt->priv = new_crypt->ops->init(i);
+ if (!new_crypt->ops || !new_crypt->priv) {
+ kfree(new_crypt);
+ new_crypt = NULL;
+
+ printk(KERN_WARNING "%s: could not initialize WEP: "
+ "load module hostap_crypt_wep.o\n",
+ dev->name);
+ return -EOPNOTSUPP;
+ }
+ *crypt = new_crypt;
+ }
+
+ if (erq->length > 0) {
+ int len = erq->length <= 5 ? 5 : 13;
+ int first = 1, j;
+ if (len > erq->length)
+ memset(keybuf + erq->length, 0, len - erq->length);
+ (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
+ for (j = 0; j < WEP_KEYS; j++) {
+ if (j != i && local->crypt[j]) {
+ first = 0;
+ break;
+ }
+ }
+ if (first)
+ local->tx_keyidx = i;
+ } else {
+ /* No key data - just set the default TX key index */
+ local->tx_keyidx = i;
+ }
+
+ done:
+ local->open_wep = erq->flags & IW_ENCODE_OPEN;
+
+ if (hostap_set_encryption(local)) {
+ printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name);
+ return -EINVAL;
+ }
+
+ /* Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode. */
+ if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) {
+ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_giwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i, len;
+ u16 val;
+ struct ieee80211_crypt_data *crypt;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > 4)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ crypt = local->crypt[i];
+ erq->flags = i + 1;
+
+ if (crypt == NULL || crypt->ops == NULL) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+
+ if (strcmp(crypt->ops->name, "WEP") != 0) {
+ /* only WEP is supported with wireless extensions, so just
+ * report that encryption is used */
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_ENABLED;
+ return 0;
+ }
+
+ /* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show
+ * the keys from driver buffer */
+ len = crypt->ops->get_key(key, WEP_KEY_LEN, NULL, crypt->priv);
+ erq->length = (len >= 0 ? len : 0);
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0)
+ {
+ printk("CNFWEPFLAGS reading failed\n");
+ return -EOPNOTSUPP;
+ }
+ le16_to_cpus(&val);
+ if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED)
+ erq->flags |= IW_ENCODE_ENABLED;
+ else
+ erq->flags |= IW_ENCODE_DISABLED;
+ if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
+
+ return 0;
+}
+
+
+static int hostap_set_rate(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret, basic_rates;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ basic_rates = local->basic_rates & local->tx_rate_control;
+ if (!basic_rates || basic_rates != local->basic_rates) {
+ printk(KERN_INFO "%s: updating basic rate set automatically "
+ "to match with the new supported rate set\n",
+ dev->name);
+ if (!basic_rates)
+ basic_rates = local->tx_rate_control;
+
+ local->basic_rates = basic_rates;
+ if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ basic_rates))
+ printk(KERN_WARNING "%s: failed to set "
+ "cnfBasicRates\n", dev->name);
+ }
+
+ ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
+ local->tx_rate_control) ||
+ hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
+ local->tx_rate_control) ||
+ local->func->reset_port(dev));
+
+ if (ret) {
+ printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates "
+ "setting to 0x%x failed\n",
+ dev->name, local->tx_rate_control);
+ }
+
+ /* Update TX rate configuration for all STAs based on new operational
+ * rate set. */
+ hostap_update_rates(local);
+
+ return ret;
+}
+
+
+static int prism2_ioctl_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->fixed) {
+ switch (rrq->value) {
+ case 11000000:
+ local->tx_rate_control = HFA384X_RATES_11MBPS;
+ break;
+ case 5500000:
+ local->tx_rate_control = HFA384X_RATES_5MBPS;
+ break;
+ case 2000000:
+ local->tx_rate_control = HFA384X_RATES_2MBPS;
+ break;
+ case 1000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS;
+ break;
+ default:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ }
+ } else {
+ switch (rrq->value) {
+ case 11000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ case 5500000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS;
+ break;
+ case 2000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS;
+ break;
+ case 1000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS;
+ break;
+ default:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ }
+ }
+
+ return hostap_set_rate(dev);
+}
+
+
+static int prism2_ioctl_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ u16 val;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ if ((val & 0x1) && (val > 1))
+ rrq->fixed = 0;
+ else
+ rrq->fixed = 1;
+
+ if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL &&
+ !local->fw_tx_rate_control) {
+ /* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in
+ * Host AP mode, so use the recorded TX rate of the last sent
+ * frame */
+ rrq->value = local->ap->last_tx_rate > 0 ?
+ local->ap->last_tx_rate * 100000 : 11000000;
+ return 0;
+ }
+
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ switch (val) {
+ case HFA384X_RATES_1MBPS:
+ rrq->value = 1000000;
+ break;
+ case HFA384X_RATES_2MBPS:
+ rrq->value = 2000000;
+ break;
+ case HFA384X_RATES_5MBPS:
+ rrq->value = 5500000;
+ break;
+ case HFA384X_RATES_11MBPS:
+ rrq->value = 11000000;
+ break;
+ default:
+ /* should not happen */
+ rrq->value = 11000000;
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_siwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Set the desired AP density */
+ if (sens->value < 1 || sens->value > 3)
+ return -EINVAL;
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Get the current AP density */
+ if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ sens->value = __le16_to_cpu(val);
+ sens->fixed = 1;
+
+ return 0;
+}
+
+
+/* Deprecated in new wireless extension API */
+static int prism2_ioctl_giwaplist(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct sockaddr *addr;
+ struct iw_quality *qual;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->iw_mode != IW_MODE_MASTER) {
+ printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported "
+ "in Host AP mode\n");
+ data->length = 0;
+ return -EOPNOTSUPP;
+ }
+
+ addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL);
+ qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL);
+ if (addr == NULL || qual == NULL) {
+ kfree(addr);
+ kfree(qual);
+ data->length = 0;
+ return -ENOMEM;
+ }
+
+ data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
+
+ memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+ data->flags = 1; /* has quality information */
+ memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+ sizeof(struct iw_quality) * data->length);
+
+ kfree(addr);
+ kfree(qual);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rts->disabled)
+ val = __constant_cpu_to_le16(2347);
+ else if (rts->value < 0 || rts->value > 2347)
+ return -EINVAL;
+ else
+ val = __cpu_to_le16(rts->value);
+
+ if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ local->rts_threshold = rts->value;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ rts->value = __le16_to_cpu(val);
+ rts->disabled = (rts->value == 2347);
+ rts->fixed = 1;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rts->disabled)
+ val = __constant_cpu_to_le16(2346);
+ else if (rts->value < 256 || rts->value > 2346)
+ return -EINVAL;
+ else
+ val = __cpu_to_le16(rts->value & ~0x1); /* even numbers only */
+
+ local->fragm_threshold = rts->value & ~0x1;
+ if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val,
+ 2)
+ || local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ &val, 2, 1) < 0)
+ return -EINVAL;
+
+ rts->value = __le16_to_cpu(val);
+ rts->disabled = (rts->value == 2346);
+ rts->fixed = 1;
+
+ return 0;
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static int hostap_join_ap(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_join_request req;
+ unsigned long flags;
+ int i;
+ struct hfa384x_hostscan_result *entry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memcpy(req.bssid, local->preferred_ap, ETH_ALEN);
+ req.channel = 0;
+
+ spin_lock_irqsave(&local->lock, flags);
+ for (i = 0; i < local->last_scan_results_count; i++) {
+ if (!local->last_scan_results)
+ break;
+ entry = &local->last_scan_results[i];
+ if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) {
+ req.channel = entry->chid;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
+ sizeof(req))) {
+ printk(KERN_DEBUG "%s: JoinRequest " MACSTR
+ " failed\n",
+ dev->name, MAC2STR(local->preferred_ap));
+ return -1;
+ }
+
+ printk(KERN_DEBUG "%s: Trying to join BSSID " MACSTR "\n",
+ dev->name, MAC2STR(local->preferred_ap));
+
+ return 0;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+static int prism2_ioctl_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN);
+
+ if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) {
+ struct hfa384x_scan_request scan_req;
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST,
+ &scan_req, sizeof(scan_req))) {
+ printk(KERN_DEBUG "%s: ScanResults request failed - "
+ "preferred AP delayed to next unsolicited "
+ "scan\n", dev->name);
+ }
+ } else if (local->host_roaming == 2 &&
+ local->iw_mode == IW_MODE_INFRA) {
+ if (hostap_join_ap(dev))
+ return -EINVAL;
+ } else {
+ printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only "
+ "in Managed mode when host_roaming is enabled\n",
+ dev->name);
+ }
+
+ return 0;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+static int prism2_ioctl_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ ap_addr->sa_family = ARPHRD_ETHER;
+ switch (iface->type) {
+ case HOSTAP_INTERFACE_AP:
+ memcpy(&ap_addr->sa_data, dev->dev_addr, ETH_ALEN);
+ break;
+ case HOSTAP_INTERFACE_STA:
+ memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN);
+ break;
+ case HOSTAP_INTERFACE_WDS:
+ memcpy(&ap_addr->sa_data, iface->u.wds.remote_addr, ETH_ALEN);
+ break;
+ default:
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID,
+ &ap_addr->sa_data, ETH_ALEN, 1) < 0)
+ return -EOPNOTSUPP;
+
+ /* local->bssid is also updated in LinkStatus handler when in
+ * station mode */
+ memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN);
+ break;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(local->name, 0, sizeof(local->name));
+ memcpy(local->name, nickname, data->length);
+ local->name_set = 1;
+
+ if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int len;
+ char name[MAX_NAME_LEN + 3];
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME,
+ &name, MAX_NAME_LEN + 2, 0);
+ val = __le16_to_cpu(*(u16 *) name);
+ if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN)
+ return -EOPNOTSUPP;
+
+ name[val + 2] = '\0';
+ data->length = val + 1;
+ memcpy(nickname, name + 2, val + 1);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* freq => chan. */
+ if (freq->e == 1 &&
+ freq->m / 100000 >= freq_list[0] &&
+ freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) {
+ int ch;
+ int fr = freq->m / 100000;
+ for (ch = 0; ch < FREQ_COUNT; ch++) {
+ if (fr == freq_list[ch]) {
+ freq->e = 0;
+ freq->m = ch + 1;
+ break;
+ }
+ }
+ }
+
+ if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT ||
+ !(local->channel_mask & (1 << (freq->m - 1))))
+ return -EINVAL;
+
+ local->channel = freq->m; /* channel is used in prism2_setup_rids() */
+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ le16_to_cpus(&val);
+ if (val < 1 || val > FREQ_COUNT)
+ return -EINVAL;
+
+ freq->m = freq_list[val - 1] * 100000;
+ freq->e = 1;
+
+ return 0;
+}
+
+
+static void hostap_monitor_set_type(local_info_t *local)
+{
+ struct net_device *dev = local->ddev;
+
+ if (dev == NULL)
+ return;
+
+ if (local->monitor_type == PRISM2_MONITOR_PRISM ||
+ local->monitor_type == PRISM2_MONITOR_CAPHDR) {
+ dev->type = ARPHRD_IEEE80211_PRISM;
+ dev->hard_header_parse =
+ hostap_80211_prism_header_parse;
+ } else {
+ dev->type = ARPHRD_IEEE80211;
+ dev->hard_header_parse = hostap_80211_header_parse;
+ }
+}
+
+
+static int prism2_ioctl_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (iface->type == HOSTAP_INTERFACE_WDS)
+ return -EOPNOTSUPP;
+
+ if (data->flags == 0)
+ ssid[0] = '\0'; /* ANY */
+
+ if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') {
+ /* Setting SSID to empty string seems to kill the card in
+ * Host AP mode */
+ printk(KERN_DEBUG "%s: Host AP mode does not support "
+ "'Any' essid\n", dev->name);
+ return -EINVAL;
+ }
+
+ memcpy(local->essid, ssid, data->length);
+ local->essid[data->length] = '\0';
+
+ if ((!local->fw_ap &&
+ hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid))
+ || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (iface->type == HOSTAP_INTERFACE_WDS)
+ return -EOPNOTSUPP;
+
+ data->flags = 1; /* active */
+ if (local->iw_mode == IW_MODE_MASTER) {
+ data->length = strlen(local->essid);
+ memcpy(essid, local->essid, IW_ESSID_MAX_SIZE);
+ } else {
+ int len;
+ char ssid[MAX_SSID_LEN + 2];
+ memset(ssid, 0, sizeof(ssid));
+ len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID,
+ &ssid, MAX_SSID_LEN + 2, 0);
+ val = __le16_to_cpu(*(u16 *) ssid);
+ if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) {
+ return -EOPNOTSUPP;
+ }
+ data->length = val;
+ memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE);
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_giwrange(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct iw_range *range = (struct iw_range *) extra;
+ u8 rates[10];
+ u16 val;
+ int i, len, over2;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ data->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
+ /* TODO: could fill num_txpower and txpower array with
+ * something; however, there are 128 different values.. */
+
+ range->txpower_capa = IW_TXPOW_DBM;
+
+ if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC)
+ {
+ range->min_pmp = 1 * 1024;
+ range->max_pmp = 65535 * 1024;
+ range->min_pmt = 1 * 1024;
+ range->max_pmt = 1000 * 1024;
+ range->pmp_flags = IW_POWER_PERIOD;
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
+ IW_POWER_UNICAST_R | IW_POWER_ALL_R;
+ }
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 18;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->min_retry = 0;
+ range->max_retry = 255;
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ if (local->channel_mask & (1 << i)) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = freq_list[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) {
+ range->max_qual.qual = 70; /* what is correct max? This was not
+ * documented exactly. At least
+ * 69 has been observed. */
+ range->max_qual.level = 0; /* dB */
+ range->max_qual.noise = 0; /* dB */
+
+ /* What would be suitable values for "average/typical" qual? */
+ range->avg_qual.qual = 20;
+ range->avg_qual.level = -60;
+ range->avg_qual.noise = -95;
+ } else {
+ range->max_qual.qual = 92; /* 0 .. 92 */
+ range->max_qual.level = 154; /* 27 .. 154 */
+ range->max_qual.noise = 154; /* 27 .. 154 */
+ }
+ range->sensitivity = 3;
+
+ range->max_encoding_tokens = WEP_KEYS;
+ range->num_encoding_sizes = 2;
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+
+ over2 = 0;
+ len = prism2_get_datarates(dev, rates);
+ range->num_bitrates = 0;
+ for (i = 0; i < len; i++) {
+ if (range->num_bitrates < IW_MAX_BITRATES) {
+ range->bitrate[range->num_bitrates] =
+ rates[i] * 500000;
+ range->num_bitrates++;
+ }
+ if (rates[i] == 0x0b || rates[i] == 0x16)
+ over2 = 1;
+ }
+ /* estimated maximum TCP throughput values (bps) */
+ range->throughput = over2 ? 5500000 : 1500000;
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ /* Event capability (kernel + driver) */
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
+ IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
+ IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
+ IW_EVENT_CAPA_MASK(IWEVEXPIRED));
+
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+ return 0;
+}
+
+
+static int hostap_monitor_mode_enable(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "Enabling monitor mode\n");
+ hostap_monitor_set_type(local);
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_PSEUDO_IBSS)) {
+ printk(KERN_DEBUG "Port type setting for monitor mode "
+ "failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Host decrypt is needed to get the IV and ICV fields;
+ * however, monitor mode seems to remove WEP flag from frame
+ * control field */
+ if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
+ HFA384X_WEPFLAGS_HOSTENCRYPT |
+ HFA384X_WEPFLAGS_HOSTDECRYPT)) {
+ printk(KERN_DEBUG "WEP flags setting failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (local->func->reset_port(dev) ||
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_MONITOR << 8),
+ 0, NULL, NULL)) {
+ printk(KERN_DEBUG "Setting monitor mode failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+
+static int hostap_monitor_mode_disable(local_info_t *local)
+{
+ struct net_device *dev = local->ddev;
+
+ if (dev == NULL)
+ return -1;
+
+ printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name);
+ dev->type = ARPHRD_ETHER;
+ dev->hard_header_parse = local->saved_eth_header_parse;
+ if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_STOP << 8),
+ 0, NULL, NULL))
+ return -1;
+ return hostap_set_encryption(local);
+}
+
+
+static int prism2_ioctl_siwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int double_reset = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
+ *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT &&
+ *mode != IW_MODE_MONITOR)
+ return -EOPNOTSUPP;
+
+#ifdef PRISM2_NO_STATION_MODES
+ if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA)
+ return -EOPNOTSUPP;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ if (*mode == local->iw_mode)
+ return 0;
+
+ if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') {
+ printk(KERN_WARNING "%s: empty SSID not allowed in Master "
+ "mode\n", dev->name);
+ return -EINVAL;
+ }
+
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_mode_disable(local);
+
+ if ((local->iw_mode == IW_MODE_ADHOC ||
+ local->iw_mode == IW_MODE_MONITOR) && *mode == IW_MODE_MASTER) {
+ /* There seems to be a firmware bug in at least STA f/w v1.5.6
+ * that leaves beacon frames to use IBSS type when moving from
+ * IBSS to Host AP mode. Doing double Port0 reset seems to be
+ * enough to workaround this. */
+ double_reset = 1;
+ }
+
+ printk(KERN_DEBUG "prism2: %s: operating mode changed "
+ "%d -> %d\n", dev->name, local->iw_mode, *mode);
+ local->iw_mode = *mode;
+
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_mode_enable(local);
+ else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
+ !local->fw_encrypt_ok) {
+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
+ "a workaround for firmware bug in Host AP mode WEP\n",
+ dev->name);
+ local->host_encrypt = 1;
+ }
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ hostap_get_porttype(local)))
+ return -EOPNOTSUPP;
+
+ if (local->func->reset_port(dev))
+ return -EINVAL;
+ if (double_reset && local->func->reset_port(dev))
+ return -EINVAL;
+
+ if (local->iw_mode != IW_MODE_INFRA && local->iw_mode != IW_MODE_ADHOC)
+ {
+ /* netif_carrier is used only in client modes for now, so make
+ * sure carrier is on when moving to non-client modes. */
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_giwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (iface->type) {
+ case HOSTAP_INTERFACE_STA:
+ *mode = IW_MODE_INFRA;
+ break;
+ case HOSTAP_INTERFACE_WDS:
+ *mode = IW_MODE_REPEAT;
+ break;
+ default:
+ *mode = local->iw_mode;
+ break;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ int ret = 0;
+
+ if (wrq->disabled)
+ return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0);
+
+ switch (wrq->flags & IW_POWER_MODE) {
+ case IW_POWER_UNICAST_R:
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ break;
+ case IW_POWER_ALL_R:
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ break;
+ case IW_POWER_ON:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (wrq->flags & IW_POWER_TIMEOUT) {
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION,
+ wrq->value / 1024);
+ if (ret)
+ return ret;
+ }
+ if (wrq->flags & IW_POWER_PERIOD) {
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
+ wrq->value / 1024);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 enable, mcast;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1)
+ < 0)
+ return -EINVAL;
+
+ if (!__le16_to_cpu(enable)) {
+ rrq->disabled = 1;
+ return 0;
+ }
+
+ rrq->disabled = 0;
+
+ if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+ u16 timeout;
+ if (local->func->get_rid(dev,
+ HFA384X_RID_CNFPMHOLDOVERDURATION,
+ &timeout, 2, 1) < 0)
+ return -EINVAL;
+
+ rrq->flags = IW_POWER_TIMEOUT;
+ rrq->value = __le16_to_cpu(timeout) * 1024;
+ } else {
+ u16 period;
+ if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
+ &period, 2, 1) < 0)
+ return -EINVAL;
+
+ rrq->flags = IW_POWER_PERIOD;
+ rrq->value = __le16_to_cpu(period) * 1024;
+ }
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast,
+ 2, 1) < 0)
+ return -EINVAL;
+
+ if (__le16_to_cpu(mcast))
+ rrq->flags |= IW_POWER_ALL_R;
+ else
+ rrq->flags |= IW_POWER_UNICAST_R;
+
+ return 0;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_siwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->disabled)
+ return -EINVAL;
+
+ /* setting retry limits is not supported with the current station
+ * firmware code; simulate this with alternative retry count for now */
+ if (rrq->flags == IW_RETRY_LIMIT) {
+ if (rrq->value < 0) {
+ /* disable manual retry count setting and use firmware
+ * defaults */
+ local->manual_retry_count = -1;
+ local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY;
+ } else {
+ if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
+ rrq->value)) {
+ printk(KERN_DEBUG "%s: Alternate retry count "
+ "setting to %d failed\n",
+ dev->name, rrq->value);
+ return -EOPNOTSUPP;
+ }
+
+ local->manual_retry_count = rrq->value;
+ local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY;
+ }
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+
+#if 0
+ /* what could be done, if firmware would support this.. */
+
+ if (rrq->flags & IW_RETRY_LIMIT) {
+ if (rrq->flags & IW_RETRY_MAX)
+ HFA384X_RID_LONGRETRYLIMIT = rrq->value;
+ else if (rrq->flags & IW_RETRY_MIN)
+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
+ else {
+ HFA384X_RID_LONGRETRYLIMIT = rrq->value;
+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
+ }
+
+ }
+
+ if (rrq->flags & IW_RETRY_LIFETIME) {
+ HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024;
+ }
+
+ return 0;
+#endif /* 0 */
+}
+
+static int prism2_ioctl_giwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 shortretry, longretry, lifetime, altretry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry,
+ 2, 1) < 0 ||
+ local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry,
+ 2, 1) < 0 ||
+ local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME,
+ &lifetime, 2, 1) < 0)
+ return -EINVAL;
+
+ le16_to_cpus(&shortretry);
+ le16_to_cpus(&longretry);
+ le16_to_cpus(&lifetime);
+
+ rrq->disabled = 0;
+
+ if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+ rrq->flags = IW_RETRY_LIFETIME;
+ rrq->value = lifetime * 1024;
+ } else {
+ if (local->manual_retry_count >= 0) {
+ rrq->flags = IW_RETRY_LIMIT;
+ if (local->func->get_rid(dev,
+ HFA384X_RID_CNFALTRETRYCOUNT,
+ &altretry, 2, 1) >= 0)
+ rrq->value = le16_to_cpu(altretry);
+ else
+ rrq->value = local->manual_retry_count;
+ } else if ((rrq->flags & IW_RETRY_MAX)) {
+ rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ rrq->value = longretry;
+ } else {
+ rrq->flags = IW_RETRY_LIMIT;
+ rrq->value = shortretry;
+ if (shortretry != longretry)
+ rrq->flags |= IW_RETRY_MIN;
+ }
+ }
+ return 0;
+}
+
+
+/* Note! This TX power controlling is experimental and should not be used in
+ * production use. It just sets raw power register and does not use any kind of
+ * feedback information from the measured TX power (CR58). This is now
+ * commented out to make sure that it is not used by accident. TX power
+ * configuration will be enabled again after proper algorithm using feedback
+ * has been implemented. */
+
+#ifdef RAW_TXPOWER_SETTING
+/* Map HFA386x's CR31 to and from dBm with some sort of ad hoc mapping..
+ * This version assumes following mapping:
+ * CR31 is 7-bit value with -64 to +63 range.
+ * -64 is mapped into +20dBm and +63 into -43dBm.
+ * This is certainly not an exact mapping for every card, but at least
+ * increasing dBm value should correspond to increasing TX power.
+ */
+
+static int prism2_txpower_hfa386x_to_dBm(u16 val)
+{
+ signed char tmp;
+
+ if (val > 255)
+ val = 255;
+
+ tmp = val;
+ tmp >>= 2;
+
+ return -12 - tmp;
+}
+
+static u16 prism2_txpower_dBm_to_hfa386x(int val)
+{
+ signed char tmp;
+
+ if (val > 20)
+ return 128;
+ else if (val < -43)
+ return 127;
+
+ tmp = val;
+ tmp = -12 - tmp;
+ tmp <<= 2;
+
+ return (unsigned char) tmp;
+}
+#endif /* RAW_TXPOWER_SETTING */
+
+
+static int prism2_ioctl_siwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+#ifdef RAW_TXPOWER_SETTING
+ char *tmp;
+#endif
+ u16 val;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->disabled) {
+ if (local->txpower_type != PRISM2_TXPOWER_OFF) {
+ val = 0xff; /* use all standby and sleep modes */
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_A_D_TEST_MODES2,
+ &val, NULL);
+ printk(KERN_DEBUG "%s: Turning radio off: %s\n",
+ dev->name, ret ? "failed" : "OK");
+ local->txpower_type = PRISM2_TXPOWER_OFF;
+ }
+ return (ret ? -EOPNOTSUPP : 0);
+ }
+
+ if (local->txpower_type == PRISM2_TXPOWER_OFF) {
+ val = 0; /* disable all standby and sleep modes */
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_A_D_TEST_MODES2, &val, NULL);
+ printk(KERN_DEBUG "%s: Turning radio on: %s\n",
+ dev->name, ret ? "failed" : "OK");
+ local->txpower_type = PRISM2_TXPOWER_UNKNOWN;
+ }
+
+#ifdef RAW_TXPOWER_SETTING
+ if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) {
+ printk(KERN_DEBUG "Setting ALC on\n");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL);
+ local->txpower_type = PRISM2_TXPOWER_AUTO;
+ return 0;
+ }
+
+ if (local->txpower_type != PRISM2_TXPOWER_FIXED) {
+ printk(KERN_DEBUG "Setting ALC off\n");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
+ local->txpower_type = PRISM2_TXPOWER_FIXED;
+ }
+
+ if (rrq->flags == IW_TXPOW_DBM)
+ tmp = "dBm";
+ else if (rrq->flags == IW_TXPOW_MWATT)
+ tmp = "mW";
+ else
+ tmp = "UNKNOWN";
+ printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp);
+
+ if (rrq->flags != IW_TXPOW_DBM) {
+ printk("SIOCSIWTXPOW with mW is not supported; use dBm\n");
+ return -EOPNOTSUPP;
+ }
+
+ local->txpower = rrq->value;
+ val = prism2_txpower_dBm_to_hfa386x(local->txpower);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL))
+ ret = -EOPNOTSUPP;
+#else /* RAW_TXPOWER_SETTING */
+ if (rrq->fixed)
+ ret = -EOPNOTSUPP;
+#endif /* RAW_TXPOWER_SETTING */
+
+ return ret;
+}
+
+static int prism2_ioctl_giwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+#ifdef RAW_TXPOWER_SETTING
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 resp0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ rrq->flags = IW_TXPOW_DBM;
+ rrq->disabled = 0;
+ rrq->fixed = 0;
+
+ if (local->txpower_type == PRISM2_TXPOWER_AUTO) {
+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_MANUAL_TX_POWER,
+ NULL, &resp0) == 0) {
+ rrq->value = prism2_txpower_hfa386x_to_dBm(resp0);
+ } else {
+ /* Could not get real txpower; guess 15 dBm */
+ rrq->value = 15;
+ }
+ } else if (local->txpower_type == PRISM2_TXPOWER_OFF) {
+ rrq->value = 0;
+ rrq->disabled = 1;
+ } else if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
+ rrq->value = local->txpower;
+ rrq->fixed = 1;
+ } else {
+ printk("SIOCGIWTXPOW - unknown txpower_type=%d\n",
+ local->txpower_type);
+ }
+ return 0;
+#else /* RAW_TXPOWER_SETTING */
+ return -EOPNOTSUPP;
+#endif /* RAW_TXPOWER_SETTING */
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+
+/* HostScan request works with and without host_roaming mode. In addition, it
+ * does not break current association. However, it requires newer station
+ * firmware version (>= 1.3.1) than scan request. */
+static int prism2_request_hostscan(struct net_device *dev,
+ u8 *ssid, u8 ssid_len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_hostscan_request scan_req;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = cpu_to_le16(local->channel_mask &
+ local->scan_channel_mask);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+ if (ssid) {
+ if (ssid_len > 32)
+ return -EINVAL;
+ scan_req.target_ssid_len = cpu_to_le16(ssid_len);
+ memcpy(scan_req.target_ssid, ssid, ssid_len);
+ }
+
+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "%s: HOSTSCAN failed\n", dev->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int prism2_request_scan(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_scan_request scan_req;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = cpu_to_le16(local->channel_mask &
+ local->scan_channel_mask);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+
+ /* FIX:
+ * It seems to be enough to set roaming mode for a short moment to
+ * host-based and then setup scanrequest data and return the mode to
+ * firmware-based.
+ *
+ * Master mode would need to drop to Managed mode for a short while
+ * to make scanning work.. Or sweep through the different channels and
+ * use passive scan based on beacons. */
+
+ if (!local->host_roaming)
+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
+ HFA384X_ROAMING_HOST);
+
+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "SCANREQUEST failed\n");
+ ret = -EINVAL;
+ }
+
+ if (!local->host_roaming)
+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
+ HFA384X_ROAMING_FIRMWARE);
+
+ return 0;
+}
+
+#else /* !PRISM2_NO_STATION_MODES */
+
+static inline int prism2_request_hostscan(struct net_device *dev,
+ u8 *ssid, u8 ssid_len)
+{
+ return -EOPNOTSUPP;
+}
+
+
+static inline int prism2_request_scan(struct net_device *dev)
+{
+ return -EOPNOTSUPP;
+}
+
+#endif /* !PRISM2_NO_STATION_MODES */
+
+
+static int prism2_ioctl_siwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret;
+ u8 *ssid = NULL, ssid_len = 0;
+ struct iw_scan_req *req = (struct iw_scan_req *) extra;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (data->length < sizeof(struct iw_scan_req))
+ req = NULL;
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ /* In master mode, we just return the results of our local
+ * tables, so we don't need to start anything...
+ * Jean II */
+ data->length = 0;
+ return 0;
+ }
+
+ if (!local->dev_enabled)
+ return -ENETDOWN;
+
+ if (req && data->flags & IW_SCAN_THIS_ESSID) {
+ ssid = req->essid;
+ ssid_len = req->essid_len;
+
+ if (ssid_len &&
+ ((local->iw_mode != IW_MODE_INFRA &&
+ local->iw_mode != IW_MODE_ADHOC) ||
+ (local->sta_fw_ver < PRISM2_FW_VER(1,3,1))))
+ return -EOPNOTSUPP;
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
+ ret = prism2_request_hostscan(dev, ssid, ssid_len);
+ else
+ ret = prism2_request_scan(dev);
+
+ if (ret == 0)
+ local->scan_timestamp = jiffies;
+
+ /* Could inquire F101, F103 or wait for SIOCGIWSCAN and read RID */
+
+ return ret;
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static char * __prism2_translate_scan(local_info_t *local,
+ struct hfa384x_hostscan_result *scan,
+ struct hostap_bss_info *bss,
+ char *current_ev, char *end_buf)
+{
+ int i, chan;
+ struct iw_event iwe;
+ char *current_val;
+ u16 capabilities;
+ u8 *pos;
+ u8 *ssid, *bssid;
+ size_t ssid_len;
+ char *buf;
+
+ if (bss) {
+ ssid = bss->ssid;
+ ssid_len = bss->ssid_len;
+ bssid = bss->bssid;
+ } else {
+ ssid = scan->ssid;
+ ssid_len = le16_to_cpu(scan->ssid_len);
+ bssid = scan->bssid;
+ }
+ if (ssid_len > 32)
+ ssid_len = 32;
+
+ /* First entry *MUST* be the AP MAC address */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
+ /* FIX:
+ * I do not know how this is possible, but iwe_stream_add_event
+ * seems to re-order memcpy execution so that len is set only
+ * after copying.. Pre-setting len here "fixes" this, but real
+ * problems should be solved (after which these iwe.len
+ * settings could be removed from this function). */
+ iwe.len = IW_EV_ADDR_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_ADDR_LEN);
+
+ /* Other entries will be displayed in the order we give them */
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = ssid_len;
+ iwe.u.data.flags = 1;
+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWMODE;
+ if (bss) {
+ capabilities = bss->capab_info;
+ } else {
+ capabilities = le16_to_cpu(scan->capability);
+ }
+ if (capabilities & (WLAN_CAPABILITY_ESS |
+ WLAN_CAPABILITY_IBSS)) {
+ if (capabilities & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ iwe.len = IW_EV_UINT_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_UINT_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWFREQ;
+ if (scan) {
+ chan = scan->chid;
+ } else if (bss) {
+ chan = bss->chan;
+ } else {
+ chan = 0;
+ }
+
+ if (chan > 0) {
+ iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+ iwe.u.freq.e = 1;
+ iwe.len = IW_EV_FREQ_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_FREQ_LEN);
+ }
+
+ if (scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVQUAL;
+ if (local->last_scan_type == PRISM2_HOSTSCAN) {
+ iwe.u.qual.level = le16_to_cpu(scan->sl);
+ iwe.u.qual.noise = le16_to_cpu(scan->anl);
+ } else {
+ iwe.u.qual.level =
+ HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->sl));
+ iwe.u.qual.noise =
+ HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
+ }
+ iwe.len = IW_EV_QUAL_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_QUAL_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWENCODE;
+ if (capabilities & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+
+ /* TODO: add SuppRates into BSS table */
+ if (scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWRATE;
+ current_val = current_ev + IW_EV_LCP_LEN;
+ pos = scan->sup_rates;
+ for (i = 0; i < sizeof(scan->sup_rates); i++) {
+ if (pos[i] == 0)
+ break;
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000);
+ current_val = iwe_stream_add_value(
+ current_ev, current_val, end_buf, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any event */
+ if ((current_val - current_ev) > IW_EV_LCP_LEN)
+ current_ev = current_val;
+ }
+
+ /* TODO: add BeaconInt,resp_rate,atim into BSS table */
+ buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
+ if (buf && scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+ buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+ buf);
+
+ if (local->last_scan_type == PRISM2_HOSTSCAN &&
+ (capabilities & WLAN_CAPABILITY_IBSS)) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "atim=%d", le16_to_cpu(scan->atim));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe, buf);
+ }
+ }
+ kfree(buf);
+
+ if (bss && bss->wpa_ie_len > 0 && bss->wpa_ie_len <= MAX_WPA_IE_LEN) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->wpa_ie_len;
+ current_ev = iwe_stream_add_point(
+ current_ev, end_buf, &iwe, bss->wpa_ie);
+ }
+
+ if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->rsn_ie_len;
+ current_ev = iwe_stream_add_point(
+ current_ev, end_buf, &iwe, bss->rsn_ie);
+ }
+
+ return current_ev;
+}
+
+
+/* Translate scan data returned from the card to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static inline int prism2_translate_scan(local_info_t *local,
+ char *buffer, int buflen)
+{
+ struct hfa384x_hostscan_result *scan;
+ int entry, hostscan;
+ char *current_ev = buffer;
+ char *end_buf = buffer + buflen;
+ struct list_head *ptr;
+
+ spin_lock_bh(&local->lock);
+
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ bss->included = 0;
+ }
+
+ hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
+ for (entry = 0; entry < local->last_scan_results_count; entry++) {
+ int found = 0;
+ scan = &local->last_scan_results[entry];
+
+ /* Report every SSID if the AP is using multiple SSIDs. If no
+ * BSS record is found (e.g., when WPA mode is disabled),
+ * report the AP once. */
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) {
+ bss->included = 1;
+ current_ev = __prism2_translate_scan(
+ local, scan, bss, current_ev, end_buf);
+ found++;
+ }
+ }
+ if (!found) {
+ current_ev = __prism2_translate_scan(
+ local, scan, NULL, current_ev, end_buf);
+ }
+ /* Check if there is space for one more entry */
+ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a bigger buffer */
+ spin_unlock_bh(&local->lock);
+ return -E2BIG;
+ }
+ }
+
+ /* Prism2 firmware has limits (32 at least in some versions) for number
+ * of BSSes in scan results. Extend this limit by using local BSS list.
+ */
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (bss->included)
+ continue;
+ current_ev = __prism2_translate_scan(local, NULL, bss,
+ current_ev, end_buf);
+ /* Check if there is space for one more entry */
+ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a bigger buffer */
+ spin_unlock_bh(&local->lock);
+ return -E2BIG;
+ }
+ }
+
+ spin_unlock_bh(&local->lock);
+
+ return current_ev - buffer;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+static inline int prism2_ioctl_giwscan_sta(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Wait until the scan is finished. We can probably do better
+ * than that - Jean II */
+ if (local->scan_timestamp &&
+ time_before(jiffies, local->scan_timestamp + 3 * HZ)) {
+ /* Important note : we don't want to block the caller
+ * until results are ready for various reasons.
+ * First, managing wait queues is complex and racy
+ * (there may be multiple simultaneous callers).
+ * Second, we grab some rtnetlink lock before comming
+ * here (in dev_ioctl()).
+ * Third, the caller can wait on the Wireless Event
+ * - Jean II */
+ return -EAGAIN;
+ }
+ local->scan_timestamp = 0;
+
+ res = prism2_translate_scan(local, extra, data->length);
+
+ if (res >= 0) {
+ data->length = res;
+ return 0;
+ } else {
+ data->length = 0;
+ return res;
+ }
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_giwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ /* In MASTER mode, it doesn't make sense to go around
+ * scanning the frequencies and make the stations we serve
+ * wait when what the user is really interested about is the
+ * list of stations and access points we are talking to.
+ * So, just extract results from our cache...
+ * Jean II */
+
+ /* Translate to WE format */
+ res = prism2_ap_translate_scan(dev, extra);
+ if (res >= 0) {
+ printk(KERN_DEBUG "Scan result translation succeeded "
+ "(length=%d)\n", res);
+ data->length = res;
+ return 0;
+ } else {
+ printk(KERN_DEBUG
+ "Scan result translation failed (res=%d)\n",
+ res);
+ data->length = 0;
+ return res;
+ }
+ } else {
+ /* Station mode */
+ return prism2_ioctl_giwscan_sta(dev, info, data, extra);
+ }
+}
+
+
+static const struct iw_priv_args prism2_priv[] = {
+ { PRISM2_IOCTL_MONITOR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" },
+ { PRISM2_IOCTL_READMIF,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" },
+ { PRISM2_IOCTL_WRITEMIF,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" },
+ { PRISM2_IOCTL_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" },
+ { PRISM2_IOCTL_INQUIRE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" },
+ { PRISM2_IOCTL_SET_RID_WORD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" },
+ { PRISM2_IOCTL_MACCMD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" },
+ { PRISM2_IOCTL_WDS_ADD,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" },
+ { PRISM2_IOCTL_WDS_DEL,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" },
+ { PRISM2_IOCTL_ADDMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" },
+ { PRISM2_IOCTL_DELMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" },
+ { PRISM2_IOCTL_KICKMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" },
+ /* --- raw access to sub-ioctls --- */
+ { PRISM2_IOCTL_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" },
+ { PRISM2_IOCTL_GET_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" },
+ /* --- sub-ioctls handlers --- */
+ { PRISM2_IOCTL_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
+ { PRISM2_IOCTL_GET_PRISM2_PARAM,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
+ /* --- sub-ioctls definitions --- */
+ { PRISM2_PARAM_TXRATECTRL,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" },
+ { PRISM2_PARAM_TXRATECTRL,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" },
+ { PRISM2_PARAM_BEACON_INT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" },
+ { PRISM2_PARAM_BEACON_INT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" },
+#ifndef PRISM2_NO_STATION_MODES
+ { PRISM2_PARAM_PSEUDO_IBSS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" },
+ { PRISM2_PARAM_PSEUDO_IBSS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" },
+#endif /* PRISM2_NO_STATION_MODES */
+ { PRISM2_PARAM_ALC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" },
+ { PRISM2_PARAM_ALC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" },
+ { PRISM2_PARAM_DUMP,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" },
+ { PRISM2_PARAM_DUMP,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" },
+ { PRISM2_PARAM_OTHER_AP_POLICY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" },
+ { PRISM2_PARAM_OTHER_AP_POLICY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" },
+ { PRISM2_PARAM_AP_MAX_INACTIVITY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" },
+ { PRISM2_PARAM_AP_MAX_INACTIVITY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" },
+ { PRISM2_PARAM_AP_BRIDGE_PACKETS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" },
+ { PRISM2_PARAM_AP_BRIDGE_PACKETS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" },
+ { PRISM2_PARAM_DTIM_PERIOD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" },
+ { PRISM2_PARAM_DTIM_PERIOD,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" },
+ { PRISM2_PARAM_AP_NULLFUNC_ACK,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" },
+ { PRISM2_PARAM_AP_NULLFUNC_ACK,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" },
+ { PRISM2_PARAM_MAX_WDS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" },
+ { PRISM2_PARAM_MAX_WDS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" },
+ { PRISM2_PARAM_AP_AUTOM_AP_WDS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" },
+ { PRISM2_PARAM_AP_AUTOM_AP_WDS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" },
+ { PRISM2_PARAM_AP_AUTH_ALGS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" },
+ { PRISM2_PARAM_AP_AUTH_ALGS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" },
+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" },
+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" },
+ { PRISM2_PARAM_HOST_ENCRYPT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" },
+ { PRISM2_PARAM_HOST_ENCRYPT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" },
+ { PRISM2_PARAM_HOST_DECRYPT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" },
+ { PRISM2_PARAM_HOST_DECRYPT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },
+#ifndef PRISM2_NO_STATION_MODES
+ { PRISM2_PARAM_HOST_ROAMING,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" },
+ { PRISM2_PARAM_HOST_ROAMING,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" },
+#endif /* PRISM2_NO_STATION_MODES */
+ { PRISM2_PARAM_BCRX_STA_KEY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" },
+ { PRISM2_PARAM_BCRX_STA_KEY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" },
+ { PRISM2_PARAM_IEEE_802_1X,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" },
+ { PRISM2_PARAM_IEEE_802_1X,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" },
+ { PRISM2_PARAM_ANTSEL_TX,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" },
+ { PRISM2_PARAM_ANTSEL_TX,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" },
+ { PRISM2_PARAM_ANTSEL_RX,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" },
+ { PRISM2_PARAM_ANTSEL_RX,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" },
+ { PRISM2_PARAM_MONITOR_TYPE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" },
+ { PRISM2_PARAM_MONITOR_TYPE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" },
+ { PRISM2_PARAM_WDS_TYPE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" },
+ { PRISM2_PARAM_WDS_TYPE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" },
+ { PRISM2_PARAM_HOSTSCAN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" },
+ { PRISM2_PARAM_HOSTSCAN,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" },
+ { PRISM2_PARAM_AP_SCAN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" },
+ { PRISM2_PARAM_AP_SCAN,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" },
+ { PRISM2_PARAM_ENH_SEC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" },
+ { PRISM2_PARAM_ENH_SEC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" },
+#ifdef PRISM2_IO_DEBUG
+ { PRISM2_PARAM_IO_DEBUG,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" },
+ { PRISM2_PARAM_IO_DEBUG,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" },
+#endif /* PRISM2_IO_DEBUG */
+ { PRISM2_PARAM_BASIC_RATES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" },
+ { PRISM2_PARAM_BASIC_RATES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" },
+ { PRISM2_PARAM_OPER_RATES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" },
+ { PRISM2_PARAM_OPER_RATES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" },
+ { PRISM2_PARAM_HOSTAPD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" },
+ { PRISM2_PARAM_HOSTAPD,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" },
+ { PRISM2_PARAM_HOSTAPD_STA,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd_sta" },
+ { PRISM2_PARAM_HOSTAPD_STA,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd_sta" },
+ { PRISM2_PARAM_WPA,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wpa" },
+ { PRISM2_PARAM_WPA,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwpa" },
+ { PRISM2_PARAM_PRIVACY_INVOKED,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "privacy_invoked" },
+ { PRISM2_PARAM_PRIVACY_INVOKED,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprivacy_invo" },
+ { PRISM2_PARAM_TKIP_COUNTERMEASURES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tkip_countermea" },
+ { PRISM2_PARAM_TKIP_COUNTERMEASURES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettkip_counter" },
+ { PRISM2_PARAM_DROP_UNENCRYPTED,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "drop_unencrypte" },
+ { PRISM2_PARAM_DROP_UNENCRYPTED,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdrop_unencry" },
+ { PRISM2_PARAM_SCAN_CHANNEL_MASK,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "scan_channels" },
+ { PRISM2_PARAM_SCAN_CHANNEL_MASK,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getscan_channel" },
+};
+
+
+static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int *i = (int *) extra;
+ int param = *i;
+ int value = *(i + 1);
+ int ret = 0;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (param) {
+ case PRISM2_PARAM_TXRATECTRL:
+ local->fw_tx_rate_control = value;
+ break;
+
+ case PRISM2_PARAM_BEACON_INT:
+ if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ else
+ local->beacon_int = value;
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case PRISM2_PARAM_PSEUDO_IBSS:
+ if (value == local->pseudo_adhoc)
+ break;
+
+ if (value != 0 && value != 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n",
+ dev->name, local->pseudo_adhoc, value);
+ local->pseudo_adhoc = value;
+ if (local->iw_mode != IW_MODE_ADHOC)
+ break;
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ hostap_get_porttype(local))) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ case PRISM2_PARAM_ALC:
+ printk(KERN_DEBUG "%s: %s ALC\n", dev->name,
+ value == 0 ? "Disabling" : "Enabling");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8),
+ value == 0 ? 0 : 1, &val, NULL);
+ break;
+
+ case PRISM2_PARAM_DUMP:
+ local->frame_dump = value;
+ break;
+
+ case PRISM2_PARAM_OTHER_AP_POLICY:
+ if (value < 0 || value > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ if (local->ap != NULL)
+ local->ap->ap_policy = value;
+ break;
+
+ case PRISM2_PARAM_AP_MAX_INACTIVITY:
+ if (value < 0 || value > 7 * 24 * 60 * 60) {
+ ret = -EINVAL;
+ break;
+ }
+ if (local->ap != NULL)
+ local->ap->max_inactivity = value * HZ;
+ break;
+
+ case PRISM2_PARAM_AP_BRIDGE_PACKETS:
+ if (local->ap != NULL)
+ local->ap->bridge_packets = value;
+ break;
+
+ case PRISM2_PARAM_DTIM_PERIOD:
+ if (value < 0 || value > 65535) {
+ ret = -EINVAL;
+ break;
+ }
+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value)
+ || local->func->reset_port(dev))
+ ret = -EINVAL;
+ else
+ local->dtim_period = value;
+ break;
+
+ case PRISM2_PARAM_AP_NULLFUNC_ACK:
+ if (local->ap != NULL)
+ local->ap->nullfunc_ack = value;
+ break;
+
+ case PRISM2_PARAM_MAX_WDS:
+ local->wds_max_connections = value;
+ break;
+
+ case PRISM2_PARAM_AP_AUTOM_AP_WDS:
+ if (local->ap != NULL) {
+ if (!local->ap->autom_ap_wds && value) {
+ /* add WDS link to all APs in STA table */
+ hostap_add_wds_links(local);
+ }
+ local->ap->autom_ap_wds = value;
+ }
+ break;
+
+ case PRISM2_PARAM_AP_AUTH_ALGS:
+ local->auth_algs = value;
+ if (hostap_set_auth_algs(local))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
+ local->monitor_allow_fcserr = value;
+ break;
+
+ case PRISM2_PARAM_HOST_ENCRYPT:
+ local->host_encrypt = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_HOST_DECRYPT:
+ local->host_decrypt = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case PRISM2_PARAM_HOST_ROAMING:
+ if (value < 0 || value > 2) {
+ ret = -EINVAL;
+ break;
+ }
+ local->host_roaming = value;
+ if (hostap_set_roaming(local) || local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ case PRISM2_PARAM_BCRX_STA_KEY:
+ local->bcrx_sta_key = value;
+ break;
+
+ case PRISM2_PARAM_IEEE_802_1X:
+ local->ieee_802_1x = value;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_TX:
+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
+ ret = -EINVAL;
+ break;
+ }
+ local->antsel_tx = value;
+ hostap_set_antsel(local);
+ break;
+
+ case PRISM2_PARAM_ANTSEL_RX:
+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
+ ret = -EINVAL;
+ break;
+ }
+ local->antsel_rx = value;
+ hostap_set_antsel(local);
+ break;
+
+ case PRISM2_PARAM_MONITOR_TYPE:
+ if (value != PRISM2_MONITOR_80211 &&
+ value != PRISM2_MONITOR_CAPHDR &&
+ value != PRISM2_MONITOR_PRISM) {
+ ret = -EINVAL;
+ break;
+ }
+ local->monitor_type = value;
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_set_type(local);
+ break;
+
+ case PRISM2_PARAM_WDS_TYPE:
+ local->wds_type = value;
+ break;
+
+ case PRISM2_PARAM_HOSTSCAN:
+ {
+ struct hfa384x_hostscan_request scan_req;
+ u16 rate;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
+ switch (value) {
+ case 1: rate = HFA384X_RATES_1MBPS; break;
+ case 2: rate = HFA384X_RATES_2MBPS; break;
+ case 3: rate = HFA384X_RATES_5MBPS; break;
+ case 4: rate = HFA384X_RATES_11MBPS; break;
+ default: rate = HFA384X_RATES_1MBPS; break;
+ }
+ scan_req.txrate = cpu_to_le16(rate);
+ /* leave SSID empty to accept all SSIDs */
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_BSS) ||
+ local->func->reset_port(dev))
+ printk(KERN_DEBUG "Leaving Host AP mode "
+ "for HostScan failed\n");
+ }
+
+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "HOSTSCAN failed\n");
+ ret = -EINVAL;
+ }
+ if (local->iw_mode == IW_MODE_MASTER) {
+ wait_queue_t __wait;
+ init_waitqueue_entry(&__wait, current);
+ add_wait_queue(&local->hostscan_wq, &__wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ if (signal_pending(current))
+ ret = -EINTR;
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&local->hostscan_wq, &__wait);
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_HOSTAP) ||
+ local->func->reset_port(dev))
+ printk(KERN_DEBUG "Returning to Host AP mode "
+ "after HostScan failed\n");
+ }
+ break;
+ }
+
+ case PRISM2_PARAM_AP_SCAN:
+ local->passive_scan_interval = value;
+ if (timer_pending(&local->passive_scan_timer))
+ del_timer(&local->passive_scan_timer);
+ if (value > 0) {
+ local->passive_scan_timer.expires = jiffies +
+ local->passive_scan_interval * HZ;
+ add_timer(&local->passive_scan_timer);
+ }
+ break;
+
+ case PRISM2_PARAM_ENH_SEC:
+ if (value < 0 || value > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ local->enh_sec = value;
+ if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY,
+ local->enh_sec) ||
+ local->func->reset_port(dev)) {
+ printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w "
+ "1.6.3 or newer\n", dev->name);
+ ret = -EOPNOTSUPP;
+ }
+ break;
+
+#ifdef PRISM2_IO_DEBUG
+ case PRISM2_PARAM_IO_DEBUG:
+ local->io_debug_enabled = value;
+ break;
+#endif /* PRISM2_IO_DEBUG */
+
+ case PRISM2_PARAM_BASIC_RATES:
+ if ((value & local->tx_rate_control) != value || value == 0) {
+ printk(KERN_INFO "%s: invalid basic rate set - basic "
+ "rates must be in supported rate set\n",
+ dev->name);
+ ret = -EINVAL;
+ break;
+ }
+ local->basic_rates = value;
+ if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ local->basic_rates) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_OPER_RATES:
+ local->tx_rate_control = value;
+ if (hostap_set_rate(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD:
+ ret = hostap_set_hostapd(local, value, 1);
+ break;
+
+ case PRISM2_PARAM_HOSTAPD_STA:
+ ret = hostap_set_hostapd_sta(local, value, 1);
+ break;
+
+ case PRISM2_PARAM_WPA:
+ local->wpa = value;
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ ret = -EOPNOTSUPP;
+ else if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
+ value ? 1 : 0))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_PRIVACY_INVOKED:
+ local->privacy_invoked = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_TKIP_COUNTERMEASURES:
+ local->tkip_countermeasures = value;
+ break;
+
+ case PRISM2_PARAM_DROP_UNENCRYPTED:
+ local->drop_unencrypted = value;
+ break;
+
+ case PRISM2_PARAM_SCAN_CHANNEL_MASK:
+ local->scan_channel_mask = value;
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n",
+ dev->name, param);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int *param = (int *) extra;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (*param) {
+ case PRISM2_PARAM_TXRATECTRL:
+ *param = local->fw_tx_rate_control;
+ break;
+
+ case PRISM2_PARAM_BEACON_INT:
+ *param = local->beacon_int;
+ break;
+
+ case PRISM2_PARAM_PSEUDO_IBSS:
+ *param = local->pseudo_adhoc;
+ break;
+
+ case PRISM2_PARAM_ALC:
+ ret = -EOPNOTSUPP; /* FIX */
+ break;
+
+ case PRISM2_PARAM_DUMP:
+ *param = local->frame_dump;
+ break;
+
+ case PRISM2_PARAM_OTHER_AP_POLICY:
+ if (local->ap != NULL)
+ *param = local->ap->ap_policy;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_MAX_INACTIVITY:
+ if (local->ap != NULL)
+ *param = local->ap->max_inactivity / HZ;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_BRIDGE_PACKETS:
+ if (local->ap != NULL)
+ *param = local->ap->bridge_packets;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_DTIM_PERIOD:
+ *param = local->dtim_period;
+ break;
+
+ case PRISM2_PARAM_AP_NULLFUNC_ACK:
+ if (local->ap != NULL)
+ *param = local->ap->nullfunc_ack;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_MAX_WDS:
+ *param = local->wds_max_connections;
+ break;
+
+ case PRISM2_PARAM_AP_AUTOM_AP_WDS:
+ if (local->ap != NULL)
+ *param = local->ap->autom_ap_wds;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_AUTH_ALGS:
+ *param = local->auth_algs;
+ break;
+
+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
+ *param = local->monitor_allow_fcserr;
+ break;
+
+ case PRISM2_PARAM_HOST_ENCRYPT:
+ *param = local->host_encrypt;
+ break;
+
+ case PRISM2_PARAM_HOST_DECRYPT:
+ *param = local->host_decrypt;
+ break;
+
+ case PRISM2_PARAM_HOST_ROAMING:
+ *param = local->host_roaming;
+ break;
+
+ case PRISM2_PARAM_BCRX_STA_KEY:
+ *param = local->bcrx_sta_key;
+ break;
+
+ case PRISM2_PARAM_IEEE_802_1X:
+ *param = local->ieee_802_1x;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_TX:
+ *param = local->antsel_tx;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_RX:
+ *param = local->antsel_rx;
+ break;
+
+ case PRISM2_PARAM_MONITOR_TYPE:
+ *param = local->monitor_type;
+ break;
+
+ case PRISM2_PARAM_WDS_TYPE:
+ *param = local->wds_type;
+ break;
+
+ case PRISM2_PARAM_HOSTSCAN:
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_SCAN:
+ *param = local->passive_scan_interval;
+ break;
+
+ case PRISM2_PARAM_ENH_SEC:
+ *param = local->enh_sec;
+ break;
+
+#ifdef PRISM2_IO_DEBUG
+ case PRISM2_PARAM_IO_DEBUG:
+ *param = local->io_debug_enabled;
+ break;
+#endif /* PRISM2_IO_DEBUG */
+
+ case PRISM2_PARAM_BASIC_RATES:
+ *param = local->basic_rates;
+ break;
+
+ case PRISM2_PARAM_OPER_RATES:
+ *param = local->tx_rate_control;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD:
+ *param = local->hostapd;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD_STA:
+ *param = local->hostapd_sta;
+ break;
+
+ case PRISM2_PARAM_WPA:
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ ret = -EOPNOTSUPP;
+ *param = local->wpa;
+ break;
+
+ case PRISM2_PARAM_PRIVACY_INVOKED:
+ *param = local->privacy_invoked;
+ break;
+
+ case PRISM2_PARAM_TKIP_COUNTERMEASURES:
+ *param = local->tkip_countermeasures;
+ break;
+
+ case PRISM2_PARAM_DROP_UNENCRYPTED:
+ *param = local->drop_unencrypted;
+ break;
+
+ case PRISM2_PARAM_SCAN_CHANNEL_MASK:
+ *param = local->scan_channel_mask;
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n",
+ dev->name, *param);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_readmif(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 resp0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL,
+ &resp0))
+ return -EOPNOTSUPP;
+ else
+ *extra = resp0;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_writemif(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 cr, val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ cr = *extra;
+ val = *(extra + 1);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+ u32 mode;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
+ "- update software to use iwconfig mode monitor\n",
+ dev->name, current->pid, current->comm);
+
+ /* Backward compatibility code - this can be removed at some point */
+
+ if (*i == 0) {
+ /* Disable monitor mode - old mode was not saved, so go to
+ * Master mode */
+ mode = IW_MODE_MASTER;
+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
+ } else if (*i == 1) {
+ /* netlink socket mode is not supported anymore since it did
+ * not separate different devices from each other and was not
+ * best method for delivering large amount of packets to
+ * user space */
+ ret = -EOPNOTSUPP;
+ } else if (*i == 2 || *i == 3) {
+ switch (*i) {
+ case 2:
+ local->monitor_type = PRISM2_MONITOR_80211;
+ break;
+ case 3:
+ local->monitor_type = PRISM2_MONITOR_PRISM;
+ break;
+ }
+ mode = IW_MODE_MONITOR;
+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
+ hostap_monitor_mode_enable(local);
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_reset(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i);
+ switch (*i) {
+ case 0:
+ /* Disable and enable card */
+ local->func->hw_shutdown(dev, 1);
+ local->func->hw_config(dev, 0);
+ break;
+
+ case 1:
+ /* COR sreset */
+ local->func->hw_reset(dev);
+ break;
+
+ case 2:
+ /* Disable and enable port 0 */
+ local->func->reset_port(dev);
+ break;
+
+ case 3:
+ prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL,
+ NULL))
+ return -EINVAL;
+ break;
+
+ case 4:
+ if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL,
+ NULL))
+ return -EINVAL;
+ break;
+
+ default:
+ printk(KERN_DEBUG "Unknown reset request %d\n", *i);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i)
+{
+ int rid = *i;
+ int value = *(i + 1);
+
+ printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value);
+
+ if (hostap_set_word(dev, rid, value))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd)
+{
+ int ret = 0;
+
+ switch (*cmd) {
+ case AP_MAC_CMD_POLICY_OPEN:
+ local->ap->mac_restrictions.policy = MAC_POLICY_OPEN;
+ break;
+ case AP_MAC_CMD_POLICY_ALLOW:
+ local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW;
+ break;
+ case AP_MAC_CMD_POLICY_DENY:
+ local->ap->mac_restrictions.policy = MAC_POLICY_DENY;
+ break;
+ case AP_MAC_CMD_FLUSH:
+ ap_control_flush_macs(&local->ap->mac_restrictions);
+ break;
+ case AP_MAC_CMD_KICKALL:
+ ap_control_kickall(local->ap);
+ hostap_deauth_all_stas(local->dev, local->ap, 0);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
+{
+ struct prism2_download_param *param;
+ int ret = 0;
+
+ if (p->length < sizeof(struct prism2_download_param) ||
+ p->length > 1024 || !p->pointer)
+ return -EINVAL;
+
+ param = (struct prism2_download_param *)
+ kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (p->length < sizeof(struct prism2_download_param) +
+ param->num_areas * sizeof(struct prism2_download_area)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = local->func->download(local, param);
+
+ out:
+ if (param != NULL)
+ kfree(param);
+
+ return ret;
+}
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+
+static int prism2_set_genericelement(struct net_device *dev, u8 *elem,
+ size_t len)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ u8 *buf;
+
+ /*
+ * Add 16-bit length in the beginning of the buffer because Prism2 RID
+ * includes it.
+ */
+ buf = kmalloc(len + 2, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ *((u16 *) buf) = cpu_to_le16(len);
+ memcpy(buf + 2, elem, len);
+
+ kfree(local->generic_elem);
+ local->generic_elem = buf;
+ local->generic_elem_len = len + 2;
+
+ return local->func->set_rid(local->dev, HFA384X_RID_GENERICELEMENT,
+ buf, len + 2);
+}
+
+
+static int prism2_ioctl_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * Host AP driver does not use these parameters and allows
+ * wpa_supplicant to control them internally.
+ */
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ local->tkip_countermeasures = data->value;
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ local->drop_unencrypted = data->value;
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ local->auth_algs = data->value;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ if (data->value == 0) {
+ local->wpa = 0;
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ break;
+ prism2_set_genericelement(dev, "", 0);
+ local->host_roaming = 0;
+ local->privacy_invoked = 0;
+ if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
+ 0) ||
+ hostap_set_roaming(local) ||
+ hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+ break;
+ }
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ return -EOPNOTSUPP;
+ local->host_roaming = 2;
+ local->privacy_invoked = 1;
+ local->wpa = 1;
+ if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1) ||
+ hostap_set_roaming(local) ||
+ hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ local->ieee_802_1x = data->value;
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
+ local->privacy_invoked = data->value;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * Host AP driver does not use these parameters and allows
+ * wpa_supplicant to control them internally.
+ */
+ return -EOPNOTSUPP;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ data->value = local->tkip_countermeasures;
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ data->value = local->drop_unencrypted;
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ data->value = local->auth_algs;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ data->value = local->wpa;
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ data->value = local->ieee_802_1x;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+ int i, ret = 0;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ u8 *addr;
+ const char *alg, *module;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i > WEP_KEYS)
+ return -EINVAL;
+ if (i < 1 || i > WEP_KEYS)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ addr = ext->addr.sa_data;
+ if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
+ addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
+ sta_ptr = NULL;
+ crypt = &local->crypt[i];
+ } else {
+ if (i != 0)
+ return -EINVAL;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
+ if (sta_ptr == NULL) {
+ if (local->iw_mode == IW_MODE_INFRA) {
+ /*
+ * TODO: add STA entry for the current AP so
+ * that unicast key can be used. For now, this
+ * is emulated by using default key idx 0.
+ */
+ i = 0;
+ crypt = &local->crypt[i];
+ } else
+ return -EINVAL;
+ }
+ }
+
+ if ((erq->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ if (*crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_WEP:
+ alg = "WEP";
+ module = "ieee80211_crypt_wep";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg = "TKIP";
+ module = "ieee80211_crypt_tkip";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg = "CCMP";
+ module = "ieee80211_crypt_ccmp";
+ break;
+ default:
+ printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
+ local->dev->name, ext->alg);
+ ret = -EOPNOTSUPP;
+ goto done;
+ }
+
+ ops = ieee80211_get_crypto_ops(alg);
+ if (ops == NULL) {
+ request_module(module);
+ ops = ieee80211_get_crypto_ops(alg);
+ }
+ if (ops == NULL) {
+ printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
+ local->dev->name, alg);
+ ret = -EOPNOTSUPP;
+ goto done;
+ }
+
+ if (sta_ptr || ext->alg != IW_ENCODE_ALG_WEP) {
+ /*
+ * Per station encryption and other than WEP algorithms
+ * require host-based encryption, so force them on
+ * automatically.
+ */
+ local->host_decrypt = local->host_encrypt = 1;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ prism2_crypt_delayed_deinit(local, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ new_crypt->priv = new_crypt->ops->init(i);
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ /*
+ * TODO: if ext_flags does not have IW_ENCODE_EXT_RX_SEQ_VALID, the
+ * existing seq# should not be changed.
+ * TODO: if ext_flags has IW_ENCODE_EXT_TX_SEQ_VALID, next TX seq#
+ * should be changed to something else than zero.
+ */
+ if ((!(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) || ext->key_len > 0)
+ && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+ (*crypt)->priv) < 0) {
+ printk(KERN_DEBUG "%s: key setting failed\n",
+ local->dev->name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ if (!sta_ptr)
+ local->tx_keyidx = i;
+ else if (i) {
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+
+
+ if (sta_ptr == NULL && ext->key_len > 0) {
+ int first = 1, j;
+ for (j = 0; j < WEP_KEYS; j++) {
+ if (j != i && local->crypt[j]) {
+ first = 0;
+ break;
+ }
+ }
+ if (first)
+ local->tx_keyidx = i;
+ }
+
+ done:
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ local->open_wep = erq->flags & IW_ENCODE_OPEN;
+
+ /*
+ * Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode.
+ */
+ if (ret == 0 &&
+ (hostap_set_encryption(local) ||
+ (local->iw_mode != IW_MODE_INFRA &&
+ local->func->reset_port(local->dev))))
+ ret = -EINVAL;
+
+ return ret;
+}
+
+
+static int prism2_ioctl_giwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ int max_key_len, i;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+ u8 *addr;
+
+ max_key_len = erq->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > WEP_KEYS)
+ i = local->tx_keyidx;
+ else
+ i--;
+
+ addr = ext->addr.sa_data;
+ if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
+ addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
+ sta_ptr = NULL;
+ crypt = &local->crypt[i];
+ } else {
+ i = 0;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
+ if (sta_ptr == NULL)
+ return -EINVAL;
+ }
+ erq->flags = i + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (*crypt == NULL || (*crypt)->ops == NULL) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (strcmp((*crypt)->ops->name, "WEP") == 0)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else if (strcmp((*crypt)->ops->name, "TKIP") == 0)
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ else if (strcmp((*crypt)->ops->name, "CCMP") == 0)
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ else
+ return -EINVAL;
+
+ if ((*crypt)->ops->get_key) {
+ ext->key_len =
+ (*crypt)->ops->get_key(ext->key,
+ max_key_len,
+ ext->tx_seq,
+ (*crypt)->priv);
+ if (ext->key_len &&
+ (ext->alg == IW_ENCODE_ALG_TKIP ||
+ ext->alg == IW_ENCODE_ALG_CCMP))
+ ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+ }
+ }
+
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_set_encryption(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int ret = 0;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len !=
+ (int) ((char *) param->u.crypt.key - (char *) param) +
+ param->u.crypt.key_len)
+ return -EINVAL;
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS)
+ return -EINVAL;
+ sta_ptr = NULL;
+ crypt = &local->crypt[param->u.crypt.idx];
+ } else {
+ if (param->u.crypt.idx)
+ return -EINVAL;
+ sta_ptr = ap_crypt_get_ptrs(
+ local->ap, param->sta_addr,
+ (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT),
+ &crypt);
+
+ if (sta_ptr == NULL) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+ return -EINVAL;
+ }
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0) {
+ if (crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+ request_module("ieee80211_crypt_wep");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ request_module("ieee80211_crypt_tkip");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ request_module("ieee80211_crypt_ccmp");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ }
+ if (ops == NULL) {
+ printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
+ local->dev->name, param->u.crypt.alg);
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* station based encryption and other than WEP algorithms require
+ * host-based encryption, so force them on automatically */
+ local->host_decrypt = local->host_encrypt = 1;
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ prism2_crypt_delayed_deinit(local, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ param->u.crypt.err =
+ HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) ||
+ param->u.crypt.key_len > 0) && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(param->u.crypt.key,
+ param->u.crypt.key_len, param->u.crypt.seq,
+ (*crypt)->priv) < 0) {
+ printk(KERN_DEBUG "%s: key setting failed\n",
+ local->dev->name);
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
+ if (!sta_ptr)
+ local->tx_keyidx = param->u.crypt.idx;
+ else if (param->u.crypt.idx) {
+ printk(KERN_DEBUG "%s: TX key idx setting failed\n",
+ local->dev->name);
+ param->u.crypt.err =
+ HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+
+ done:
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ /* Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode. */
+ if (ret == 0 &&
+ (hostap_set_encryption(local) ||
+ (local->iw_mode != IW_MODE_INFRA &&
+ local->func->reset_port(local->dev)))) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED;
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_get_encryption(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ int max_key_len;
+
+ param->u.crypt.err = 0;
+
+ max_key_len = param_len -
+ (int) ((char *) param->u.crypt.key - (char *) param);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ sta_ptr = NULL;
+ if (param->u.crypt.idx >= WEP_KEYS)
+ param->u.crypt.idx = local->tx_keyidx;
+ crypt = &local->crypt[param->u.crypt.idx];
+ } else {
+ param->u.crypt.idx = 0;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
+ &crypt);
+
+ if (sta_ptr == NULL) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+ return -EINVAL;
+ }
+ }
+
+ if (*crypt == NULL || (*crypt)->ops == NULL) {
+ memcpy(param->u.crypt.alg, "none", 5);
+ param->u.crypt.key_len = 0;
+ param->u.crypt.idx = 0xff;
+ } else {
+ strncpy(param->u.crypt.alg, (*crypt)->ops->name,
+ HOSTAP_CRYPT_ALG_NAME_LEN);
+ param->u.crypt.key_len = 0;
+
+ memset(param->u.crypt.seq, 0, 8);
+ if ((*crypt)->ops->get_key) {
+ param->u.crypt.key_len =
+ (*crypt)->ops->get_key(param->u.crypt.key,
+ max_key_len,
+ param->u.crypt.seq,
+ (*crypt)->priv);
+ }
+ }
+
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_get_rid(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len, res;
+
+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
+ if (max_len < 0)
+ return -EINVAL;
+
+ res = local->func->get_rid(local->dev, param->u.rid.rid,
+ param->u.rid.data, param->u.rid.len, 0);
+ if (res >= 0) {
+ param->u.rid.len = res;
+ return 0;
+ }
+
+ return res;
+}
+
+
+static int prism2_ioctl_set_rid(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len;
+
+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
+ if (max_len < 0 || max_len < param->u.rid.len)
+ return -EINVAL;
+
+ return local->func->set_rid(local->dev, param->u.rid.rid,
+ param->u.rid.data, param->u.rid.len);
+}
+
+
+static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ printk(KERN_DEBUG "%ssta: associated as client with AP " MACSTR "\n",
+ local->dev->name, MAC2STR(param->sta_addr));
+ memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
+ return 0;
+}
+
+
+static int prism2_ioctl_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ return prism2_set_genericelement(dev, extra, data->length);
+}
+
+
+static int prism2_ioctl_giwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ int len = local->generic_elem_len - 2;
+
+ if (len <= 0 || local->generic_elem == NULL) {
+ data->length = 0;
+ return 0;
+ }
+
+ if (data->length < len)
+ return -E2BIG;
+
+ data->length = len;
+ memcpy(extra, local->generic_elem + 2, len);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_set_generic_element(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len, len;
+
+ len = param->u.generic_elem.len;
+ max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
+ if (max_len < 0 || max_len < len)
+ return -EINVAL;
+
+ return prism2_set_genericelement(local->dev,
+ param->u.generic_elem.data, len);
+}
+
+
+static int prism2_ioctl_siwmlme(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct iw_mlme *mlme = (struct iw_mlme *) extra;
+ u16 reason;
+
+ reason = cpu_to_le16(mlme->reason_code);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
+ IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ case IW_MLME_DISASSOC:
+ return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
+ IEEE80211_STYPE_DISASSOC,
+ (u8 *) &reason, 2);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+
+static int prism2_ioctl_mlme(local_info_t *local,
+ struct prism2_hostapd_param *param)
+{
+ u16 reason;
+
+ reason = cpu_to_le16(param->u.mlme.reason_code);
+ switch (param->u.mlme.cmd) {
+ case MLME_STA_DEAUTH:
+ return prism2_sta_send_mgmt(local, param->sta_addr,
+ IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ case MLME_STA_DISASSOC:
+ return prism2_sta_send_mgmt(local, param->sta_addr,
+ IEEE80211_STYPE_DISASSOC,
+ (u8 *) &reason, 2);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+
+static int prism2_ioctl_scan_req(local_info_t *local,
+ struct prism2_hostapd_param *param)
+{
+#ifndef PRISM2_NO_STATION_MODES
+ if ((local->iw_mode != IW_MODE_INFRA &&
+ local->iw_mode != IW_MODE_ADHOC) ||
+ (local->sta_fw_ver < PRISM2_FW_VER(1,3,1)))
+ return -EOPNOTSUPP;
+
+ if (!local->dev_enabled)
+ return -ENETDOWN;
+
+ return prism2_request_hostscan(local->dev, param->u.scan_req.ssid,
+ param->u.scan_req.ssid_len);
+#else /* PRISM2_NO_STATION_MODES */
+ return -EOPNOTSUPP;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p)
+{
+ struct prism2_hostapd_param *param;
+ int ret = 0;
+ int ap_ioctl = 0;
+
+ if (p->length < sizeof(struct prism2_hostapd_param) ||
+ p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
+ return -EINVAL;
+
+ param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ switch (param->cmd) {
+ case PRISM2_SET_ENCRYPTION:
+ ret = prism2_ioctl_set_encryption(local, param, p->length);
+ break;
+ case PRISM2_GET_ENCRYPTION:
+ ret = prism2_ioctl_get_encryption(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_GET_RID:
+ ret = prism2_ioctl_get_rid(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_RID:
+ ret = prism2_ioctl_set_rid(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR:
+ ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT:
+ ret = prism2_ioctl_set_generic_element(local, param,
+ p->length);
+ break;
+ case PRISM2_HOSTAPD_MLME:
+ ret = prism2_ioctl_mlme(local, param);
+ break;
+ case PRISM2_HOSTAPD_SCAN_REQ:
+ ret = prism2_ioctl_scan_req(local, param);
+ break;
+ default:
+ ret = prism2_hostapd(local->ap, param);
+ ap_ioctl = 1;
+ break;
+ }
+
+ if (ret == 1 || !ap_ioctl) {
+ if (copy_to_user(p->pointer, param, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ } else if (ap_ioctl)
+ ret = 0;
+ }
+
+ out:
+ if (param != NULL)
+ kfree(param);
+
+ return ret;
+}
+
+
+static void prism2_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
+ strncpy(info->version, PRISM2_VERSION,
+ sizeof(info->version) - 1);
+ snprintf(info->fw_version, sizeof(info->fw_version) - 1,
+ "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
+ (local->sta_fw_ver >> 8) & 0xff,
+ local->sta_fw_ver & 0xff);
+}
+
+static struct ethtool_ops prism2_ethtool_ops = {
+ .get_drvinfo = prism2_get_drvinfo
+};
+
+
+/* Structures to export the Wireless Handlers */
+
+static const iw_handler prism2_handler[] =
+{
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) prism2_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) prism2_ioctl_siwfreq, /* SIOCSIWFREQ */
+ (iw_handler) prism2_ioctl_giwfreq, /* SIOCGIWFREQ */
+ (iw_handler) prism2_ioctl_siwmode, /* SIOCSIWMODE */
+ (iw_handler) prism2_ioctl_giwmode, /* SIOCGIWMODE */
+ (iw_handler) prism2_ioctl_siwsens, /* SIOCSIWSENS */
+ (iw_handler) prism2_ioctl_giwsens, /* SIOCGIWSENS */
+ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
+ (iw_handler) prism2_ioctl_giwrange, /* SIOCGIWRANGE */
+ (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
+ (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
+ (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
+ (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
+ iw_handler_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+ (iw_handler) prism2_ioctl_siwap, /* SIOCSIWAP */
+ (iw_handler) prism2_ioctl_giwap, /* SIOCGIWAP */
+ (iw_handler) prism2_ioctl_siwmlme, /* SIOCSIWMLME */
+ (iw_handler) prism2_ioctl_giwaplist, /* SIOCGIWAPLIST */
+ (iw_handler) prism2_ioctl_siwscan, /* SIOCSIWSCAN */
+ (iw_handler) prism2_ioctl_giwscan, /* SIOCGIWSCAN */
+ (iw_handler) prism2_ioctl_siwessid, /* SIOCSIWESSID */
+ (iw_handler) prism2_ioctl_giwessid, /* SIOCGIWESSID */
+ (iw_handler) prism2_ioctl_siwnickn, /* SIOCSIWNICKN */
+ (iw_handler) prism2_ioctl_giwnickn, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) prism2_ioctl_siwrate, /* SIOCSIWRATE */
+ (iw_handler) prism2_ioctl_giwrate, /* SIOCGIWRATE */
+ (iw_handler) prism2_ioctl_siwrts, /* SIOCSIWRTS */
+ (iw_handler) prism2_ioctl_giwrts, /* SIOCGIWRTS */
+ (iw_handler) prism2_ioctl_siwfrag, /* SIOCSIWFRAG */
+ (iw_handler) prism2_ioctl_giwfrag, /* SIOCGIWFRAG */
+ (iw_handler) prism2_ioctl_siwtxpow, /* SIOCSIWTXPOW */
+ (iw_handler) prism2_ioctl_giwtxpow, /* SIOCGIWTXPOW */
+ (iw_handler) prism2_ioctl_siwretry, /* SIOCSIWRETRY */
+ (iw_handler) prism2_ioctl_giwretry, /* SIOCGIWRETRY */
+ (iw_handler) prism2_ioctl_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) prism2_ioctl_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) prism2_ioctl_siwpower, /* SIOCSIWPOWER */
+ (iw_handler) prism2_ioctl_giwpower, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) prism2_ioctl_siwgenie, /* SIOCSIWGENIE */
+ (iw_handler) prism2_ioctl_giwgenie, /* SIOCGIWGENIE */
+ (iw_handler) prism2_ioctl_siwauth, /* SIOCSIWAUTH */
+ (iw_handler) prism2_ioctl_giwauth, /* SIOCGIWAUTH */
+ (iw_handler) prism2_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) prism2_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
+ (iw_handler) NULL, /* -- hole -- */
+};
+
+static const iw_handler prism2_private_handler[] =
+{ /* SIOCIWFIRSTPRIV + */
+ (iw_handler) prism2_ioctl_priv_prism2_param, /* 0 */
+ (iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */
+ (iw_handler) prism2_ioctl_priv_writemif, /* 2 */
+ (iw_handler) prism2_ioctl_priv_readmif, /* 3 */
+};
+
+static const struct iw_handler_def hostap_iw_handler_def =
+{
+ .num_standard = sizeof(prism2_handler) / sizeof(iw_handler),
+ .num_private = sizeof(prism2_private_handler) / sizeof(iw_handler),
+ .num_private_args = sizeof(prism2_priv) / sizeof(struct iw_priv_args),
+ .standard = (iw_handler *) prism2_handler,
+ .private = (iw_handler *) prism2_private_handler,
+ .private_args = (struct iw_priv_args *) prism2_priv,
+ .get_wireless_stats = hostap_get_wireless_stats,
+};
+
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct iwreq *wrq = (struct iwreq *) ifr;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (cmd) {
+ /* Private ioctls (iwpriv) that have not yet been converted
+ * into new wireless extensions API */
+
+ case PRISM2_IOCTL_INQUIRE:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_MONITOR:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_RESET:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_WDS_ADD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1);
+ break;
+
+ case PRISM2_IOCTL_WDS_DEL:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0);
+ break;
+
+ case PRISM2_IOCTL_SET_RID_WORD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_set_rid_word(dev,
+ (int *) wrq->u.name);
+ break;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ case PRISM2_IOCTL_MACCMD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_ADDMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_add_mac(&local->ap->mac_restrictions,
+ wrq->u.ap_addr.sa_data);
+ break;
+ case PRISM2_IOCTL_DELMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_del_mac(&local->ap->mac_restrictions,
+ wrq->u.ap_addr.sa_data);
+ break;
+ case PRISM2_IOCTL_KICKMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_kick_mac(local->ap, local->dev,
+ wrq->u.ap_addr.sa_data);
+ break;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+ /* Private ioctls that are not used with iwpriv;
+ * in SIOCDEVPRIVATE range */
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ case PRISM2_IOCTL_DOWNLOAD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_download(local, &wrq->u.data);
+ break;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ case PRISM2_IOCTL_HOSTAPD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
new file mode 100644
index 000000000000..025f8cdb5566
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -0,0 +1,473 @@
+#define PRISM2_PCI
+
+/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
+ * driver patches from Reyk Floeter <reyk@vantronix.net> and
+ * Andy Warner <andyw@pobox.com> */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *dev_info = "hostap_pci";
+
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
+ "PCI cards.");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+/* struct local_info::hw_priv */
+struct hostap_pci_priv {
+ void __iomem *mem_start;
+};
+
+
+/* FIX: do we need mb/wmb/rmb with memory operations? */
+
+
+static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
+ /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
+ { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
+ /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
+ { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
+ /* Samsung MagicLAN SWL-2210P */
+ { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ writeb(v, hw_priv->mem_start + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = readb(hw_priv->mem_start + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ writew(v, hw_priv->mem_start + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = readw(hw_priv->mem_start + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v)))
+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a)))
+
+#else /* PRISM2_IO_DEBUG */
+
+static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ writeb(v, hw_priv->mem_start + a);
+}
+
+static inline u8 hfa384x_inb(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ return readb(hw_priv->mem_start + a);
+}
+
+static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ writew(v, hw_priv->mem_start + a);
+}
+
+static inline u16 hfa384x_inw(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ return readw(hw_priv->mem_start + a);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw(dev, (a))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), cpu_to_le16((v)))
+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw(dev, (a)))
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ for ( ; len > 1; len -= 2)
+ *pos++ = HFA384X_INW_DATA(d_off);
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ for ( ; len > 1; len -= 2)
+ HFA384X_OUTW_DATA(*pos++, d_off);
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+static void prism2_pci_cor_sreset(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 reg;
+
+ reg = HFA384X_INB(HFA384X_PCICOR_OFF);
+ printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
+
+ /* linux-wlan-ng uses extremely long hold and settle times for
+ * COR sreset. A comment in the driver code mentions that the long
+ * delays appear to be necessary. However, at least IBM 22P6901 seems
+ * to work fine with shorter delays.
+ *
+ * Longer delays can be configured by uncommenting following line: */
+/* #define PRISM2_PCI_USE_LONG_DELAYS */
+
+#ifdef PRISM2_PCI_USE_LONG_DELAYS
+ int i;
+
+ HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
+ mdelay(250);
+
+ HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
+ mdelay(500);
+
+ /* Wait for f/w to complete initialization (CMD:BUSY == 0) */
+ i = 2000000 / 10;
+ while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
+ udelay(10);
+
+#else /* PRISM2_PCI_USE_LONG_DELAYS */
+
+ HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
+ mdelay(2);
+ HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
+ mdelay(2);
+
+#endif /* PRISM2_PCI_USE_LONG_DELAYS */
+
+ if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
+ printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
+ }
+}
+
+
+static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+
+ HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
+ mdelay(10);
+ HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
+ mdelay(10);
+ HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
+ mdelay(10);
+}
+
+
+static struct prism2_helper_functions prism2_pci_funcs =
+{
+ .card_present = NULL,
+ .cor_sreset = prism2_pci_cor_sreset,
+ .dev_open = NULL,
+ .dev_close = NULL,
+ .genesis_reset = prism2_pci_genesis_reset,
+ .hw_type = HOSTAP_HW_PCI,
+};
+
+
+static int prism2_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ unsigned long phymem;
+ void __iomem *mem = NULL;
+ local_info_t *local = NULL;
+ struct net_device *dev = NULL;
+ static int cards_found /* = 0 */;
+ int irq_registered = 0;
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+
+ hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (hw_priv == NULL)
+ return -ENOMEM;
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ phymem = pci_resource_start(pdev, 0);
+
+ if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
+ printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
+ goto err_out_disable;
+ }
+
+ mem = ioremap(phymem, pci_resource_len(pdev, 0));
+ if (mem == NULL) {
+ printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
+ goto fail;
+ }
+
+ dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
+ &pdev->dev);
+ if (dev == NULL)
+ goto fail;
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ cards_found++;
+
+ dev->irq = pdev->irq;
+ hw_priv->mem_start = mem;
+
+ prism2_pci_cor_sreset(local);
+
+ pci_set_drvdata(pdev, dev);
+
+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
+ dev)) {
+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
+ goto fail;
+ } else
+ irq_registered = 1;
+
+ if (!local->pri_only && prism2_hw_config(dev, 1)) {
+ printk(KERN_DEBUG "%s: hardware initialization failed\n",
+ dev_info);
+ goto fail;
+ }
+
+ printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
+ "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
+
+ return hostap_hw_ready(dev);
+
+ fail:
+ kfree(hw_priv);
+
+ if (irq_registered && dev)
+ free_irq(dev->irq, dev);
+
+ if (mem)
+ iounmap(mem);
+
+ release_mem_region(phymem, pci_resource_len(pdev, 0));
+
+ err_out_disable:
+ pci_disable_device(pdev);
+ kfree(hw_priv);
+ if (local)
+ local->hw_priv = NULL;
+ prism2_free_local_data(dev);
+
+ return -ENODEV;
+}
+
+
+static void prism2_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ void __iomem *mem_start;
+ struct hostap_pci_priv *hw_priv;
+
+ dev = pci_get_drvdata(pdev);
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+
+ /* Reset the hardware, and ensure interrupts are disabled. */
+ prism2_pci_cor_sreset(iface->local);
+ hfa384x_disable_interrupts(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ mem_start = hw_priv->mem_start;
+ kfree(hw_priv);
+ iface->local->hw_priv = NULL;
+ prism2_free_local_data(dev);
+
+ iounmap(mem_start);
+
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
+}
+
+
+#ifdef CONFIG_PM
+static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (netif_running(dev)) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+ prism2_suspend(dev);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
+}
+
+static int prism2_pci_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ pci_enable_device(pdev);
+ pci_restore_state(pdev);
+ prism2_hw_config(dev, 0);
+ if (netif_running(dev)) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
+
+static struct pci_driver prism2_pci_drv_id = {
+ .name = "prism2_pci",
+ .id_table = prism2_pci_id_table,
+ .probe = prism2_pci_probe,
+ .remove = prism2_pci_remove,
+#ifdef CONFIG_PM
+ .suspend = prism2_pci_suspend,
+ .resume = prism2_pci_resume,
+#endif /* CONFIG_PM */
+ /* Linux 2.4.6 added save_state and enable_wake that are not used here
+ */
+};
+
+
+static int __init init_prism2_pci(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
+ return pci_register_driver(&prism2_pci_drv_id);
+}
+
+
+static void __exit exit_prism2_pci(void)
+{
+ pci_unregister_driver(&prism2_pci_drv_id);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_pci);
+module_exit(exit_prism2_pci);
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
new file mode 100644
index 000000000000..474ef83d813e
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -0,0 +1,645 @@
+#define PRISM2_PLX
+
+/* Host AP driver's support for PC Cards on PCI adapters using PLX9052 is
+ * based on:
+ * - Host AP driver patch from james@madingley.org
+ * - linux-wlan-ng driver, Copyright (C) AbsoluteValue Systems, Inc.
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *dev_info = "hostap_plx";
+
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
+ "cards (PLX).");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+static int ignore_cis;
+module_param(ignore_cis, int, 0444);
+MODULE_PARM_DESC(ignore_cis, "Do not verify manfid information in CIS");
+
+
+/* struct local_info::hw_priv */
+struct hostap_plx_priv {
+ void __iomem *attr_mem;
+ unsigned int cor_offset;
+};
+
+
+#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */
+#define COR_SRESET 0x80
+#define COR_LEVLREQ 0x40
+#define COR_ENABLE_FUNC 0x01
+/* PCI Configuration Registers */
+#define PLX_PCIIPR 0x3d /* PCI Interrupt Pin */
+/* Local Configuration Registers */
+#define PLX_INTCSR 0x4c /* Interrupt Control/Status Register */
+#define PLX_INTCSR_PCI_INTEN BIT(6) /* PCI Interrupt Enable */
+#define PLX_CNTRL 0x50
+#define PLX_CNTRL_SERIAL_EEPROM_PRESENT BIT(28)
+
+
+#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID }
+
+static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
+ PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
+ PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
+ PLXDEV(0x126c, 0x8030, "Nortel emobility"),
+ PLXDEV(0x1385, 0x4100, "Netgear MA301"),
+ PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
+ PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
+ PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
+ PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
+ PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
+ PLXDEV(0x16ab, 0x1103, "Longshine 8031"),
+ PLXDEV(0x16ec, 0x3685, "US Robotics USR2415"),
+ PLXDEV(0xec80, 0xec00, "Belkin F5D6000"),
+ { 0 }
+};
+
+
+/* Array of known Prism2/2.5 PC Card manufactured ids. If your card's manfid
+ * is not listed here, you will need to add it here to get the driver
+ * initialized. */
+static struct prism2_plx_manfid {
+ u16 manfid1, manfid2;
+} prism2_plx_known_manfids[] = {
+ { 0x000b, 0x7110 } /* D-Link DWL-650 Rev. P1 */,
+ { 0x000b, 0x7300 } /* Philips 802.11b WLAN PCMCIA */,
+ { 0x0101, 0x0777 } /* 3Com AirConnect PCI 777A */,
+ { 0x0126, 0x8000 } /* Proxim RangeLAN */,
+ { 0x0138, 0x0002 } /* Compaq WL100 */,
+ { 0x0156, 0x0002 } /* Intersil Prism II Ref. Design (and others) */,
+ { 0x026f, 0x030b } /* Buffalo WLI-CF-S11G */,
+ { 0x0274, 0x1612 } /* Linksys WPC11 Ver 2.5 */,
+ { 0x0274, 0x1613 } /* Linksys WPC11 Ver 3 */,
+ { 0x028a, 0x0002 } /* D-Link DRC-650 */,
+ { 0x0250, 0x0002 } /* Samsung SWL2000-N */,
+ { 0xc250, 0x0002 } /* EMTAC A2424i */,
+ { 0xd601, 0x0002 } /* Z-Com XI300 */,
+ { 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */,
+ { 0, 0}
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ outb(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = inb(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ outw(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = inw(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
+ outsw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline void hfa384x_insw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
+ insw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
+
+#else /* PRISM2_IO_DEBUG */
+
+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
+#define HFA384X_INB(a) inb(dev->base_addr + (a))
+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
+#define HFA384X_INW(a) inw(dev->base_addr + (a))
+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_INSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_OUTSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+
+static void prism2_plx_cor_sreset(local_info_t *local)
+{
+ unsigned char corsave;
+ struct hostap_plx_priv *hw_priv = local->hw_priv;
+
+ printk(KERN_DEBUG "%s: Doing reset via direct COR access.\n",
+ dev_info);
+
+ /* Set sreset bit of COR and clear it after hold time */
+
+ if (hw_priv->attr_mem == NULL) {
+ /* TMD7160 - COR at card's first I/O addr */
+ corsave = inb(hw_priv->cor_offset);
+ outb(corsave | COR_SRESET, hw_priv->cor_offset);
+ mdelay(2);
+ outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
+ mdelay(2);
+ } else {
+ /* PLX9052 */
+ corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
+ writeb(corsave | COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(2);
+ writeb(corsave & ~COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(2);
+ }
+}
+
+
+static void prism2_plx_genesis_reset(local_info_t *local, int hcr)
+{
+ unsigned char corsave;
+ struct hostap_plx_priv *hw_priv = local->hw_priv;
+
+ if (hw_priv->attr_mem == NULL) {
+ /* TMD7160 - COR at card's first I/O addr */
+ corsave = inb(hw_priv->cor_offset);
+ outb(corsave | COR_SRESET, hw_priv->cor_offset);
+ mdelay(10);
+ outb(hcr, hw_priv->cor_offset + 2);
+ mdelay(10);
+ outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
+ mdelay(10);
+ } else {
+ /* PLX9052 */
+ corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
+ writeb(corsave | COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(10);
+ writeb(hcr, hw_priv->attr_mem + hw_priv->cor_offset + 2);
+ mdelay(10);
+ writeb(corsave & ~COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(10);
+ }
+}
+
+
+static struct prism2_helper_functions prism2_plx_funcs =
+{
+ .card_present = NULL,
+ .cor_sreset = prism2_plx_cor_sreset,
+ .dev_open = NULL,
+ .dev_close = NULL,
+ .genesis_reset = prism2_plx_genesis_reset,
+ .hw_type = HOSTAP_HW_PLX,
+};
+
+
+static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
+ unsigned int *cor_offset,
+ unsigned int *cor_index)
+{
+#define CISTPL_CONFIG 0x1A
+#define CISTPL_MANFID 0x20
+#define CISTPL_END 0xFF
+#define CIS_MAX_LEN 256
+ u8 *cis;
+ int i, pos;
+ unsigned int rmsz, rasz, manfid1, manfid2;
+ struct prism2_plx_manfid *manfid;
+
+ cis = kmalloc(CIS_MAX_LEN, GFP_KERNEL);
+ if (cis == NULL)
+ return -ENOMEM;
+
+ /* read CIS; it is in even offsets in the beginning of attr_mem */
+ for (i = 0; i < CIS_MAX_LEN; i++)
+ cis[i] = readb(attr_mem + 2 * i);
+ printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n",
+ dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]);
+
+ /* set reasonable defaults for Prism2 cards just in case CIS parsing
+ * fails */
+ *cor_offset = 0x3e0;
+ *cor_index = 0x01;
+ manfid1 = manfid2 = 0;
+
+ pos = 0;
+ while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) {
+ if (pos + cis[pos + 1] >= CIS_MAX_LEN)
+ goto cis_error;
+
+ switch (cis[pos]) {
+ case CISTPL_CONFIG:
+ if (cis[pos + 1] < 1)
+ goto cis_error;
+ rmsz = (cis[pos + 2] & 0x3c) >> 2;
+ rasz = cis[pos + 2] & 0x03;
+ if (4 + rasz + rmsz > cis[pos + 1])
+ goto cis_error;
+ *cor_index = cis[pos + 3] & 0x3F;
+ *cor_offset = 0;
+ for (i = 0; i <= rasz; i++)
+ *cor_offset += cis[pos + 4 + i] << (8 * i);
+ printk(KERN_DEBUG "%s: cor_index=0x%x "
+ "cor_offset=0x%x\n", dev_info,
+ *cor_index, *cor_offset);
+ if (*cor_offset > attr_len) {
+ printk(KERN_ERR "%s: COR offset not within "
+ "attr_mem\n", dev_info);
+ kfree(cis);
+ return -1;
+ }
+ break;
+
+ case CISTPL_MANFID:
+ if (cis[pos + 1] < 4)
+ goto cis_error;
+ manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
+ manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
+ printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n",
+ dev_info, manfid1, manfid2);
+ break;
+ }
+
+ pos += cis[pos + 1] + 2;
+ }
+
+ if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END)
+ goto cis_error;
+
+ for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++)
+ if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) {
+ kfree(cis);
+ return 0;
+ }
+
+ printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is"
+ " not supported card\n", dev_info, manfid1, manfid2);
+ goto fail;
+
+ cis_error:
+ printk(KERN_WARNING "%s: invalid CIS data\n", dev_info);
+
+ fail:
+ kfree(cis);
+ if (ignore_cis) {
+ printk(KERN_INFO "%s: ignore_cis parameter set - ignoring "
+ "errors during CIS verification\n", dev_info);
+ return 0;
+ }
+ return -1;
+}
+
+
+static int prism2_plx_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ unsigned int pccard_ioaddr, plx_ioaddr;
+ unsigned long pccard_attr_mem;
+ unsigned int pccard_attr_len;
+ void __iomem *attr_mem = NULL;
+ unsigned int cor_offset, cor_index;
+ u32 reg;
+ local_info_t *local = NULL;
+ struct net_device *dev = NULL;
+ struct hostap_interface *iface;
+ static int cards_found /* = 0 */;
+ int irq_registered = 0;
+ int tmd7160;
+ struct hostap_plx_priv *hw_priv;
+
+ hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (hw_priv == NULL)
+ return -ENOMEM;
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ /* National Datacomm NCP130 based on TMD7160, not PLX9052. */
+ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131);
+
+ plx_ioaddr = pci_resource_start(pdev, 1);
+ pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3);
+
+ if (tmd7160) {
+ /* TMD7160 */
+ attr_mem = NULL; /* no access to PC Card attribute memory */
+
+ printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, "
+ "irq=%d, pccard_io=0x%x\n",
+ plx_ioaddr, pdev->irq, pccard_ioaddr);
+
+ cor_offset = plx_ioaddr;
+ cor_index = 0x04;
+
+ outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr);
+ mdelay(1);
+ reg = inb(plx_ioaddr);
+ if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) {
+ printk(KERN_ERR "%s: Error setting COR (expected="
+ "0x%02x, was=0x%02x)\n", dev_info,
+ cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg);
+ goto fail;
+ }
+ } else {
+ /* PLX9052 */
+ pccard_attr_mem = pci_resource_start(pdev, 2);
+ pccard_attr_len = pci_resource_len(pdev, 2);
+ if (pccard_attr_len < PLX_MIN_ATTR_LEN)
+ goto fail;
+
+
+ attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);
+ if (attr_mem == NULL) {
+ printk(KERN_ERR "%s: cannot remap attr_mem\n",
+ dev_info);
+ goto fail;
+ }
+
+ printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: "
+ "mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n",
+ pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr);
+
+ if (prism2_plx_check_cis(attr_mem, pccard_attr_len,
+ &cor_offset, &cor_index)) {
+ printk(KERN_INFO "Unknown PC Card CIS - not a "
+ "Prism2/2.5 card?\n");
+ goto fail;
+ }
+
+ printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 "
+ "adapter\n");
+
+ /* Write COR to enable PC Card */
+ writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC,
+ attr_mem + cor_offset);
+
+ /* Enable PCI interrupts if they are not already enabled */
+ reg = inl(plx_ioaddr + PLX_INTCSR);
+ printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg);
+ if (!(reg & PLX_INTCSR_PCI_INTEN)) {
+ outl(reg | PLX_INTCSR_PCI_INTEN,
+ plx_ioaddr + PLX_INTCSR);
+ if (!(inl(plx_ioaddr + PLX_INTCSR) &
+ PLX_INTCSR_PCI_INTEN)) {
+ printk(KERN_WARNING "%s: Could not enable "
+ "Local Interrupts\n", dev_info);
+ goto fail;
+ }
+ }
+
+ reg = inl(plx_ioaddr + PLX_CNTRL);
+ printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM "
+ "present=%d)\n",
+ reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0);
+ /* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is
+ * not present; but are there really such cards in use(?) */
+ }
+
+ dev = prism2_init_local_data(&prism2_plx_funcs, cards_found,
+ &pdev->dev);
+ if (dev == NULL)
+ goto fail;
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ cards_found++;
+
+ dev->irq = pdev->irq;
+ dev->base_addr = pccard_ioaddr;
+ hw_priv->attr_mem = attr_mem;
+ hw_priv->cor_offset = cor_offset;
+
+ pci_set_drvdata(pdev, dev);
+
+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
+ dev)) {
+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
+ goto fail;
+ } else
+ irq_registered = 1;
+
+ if (prism2_hw_config(dev, 1)) {
+ printk(KERN_DEBUG "%s: hardware initialization failed\n",
+ dev_info);
+ goto fail;
+ }
+
+ return hostap_hw_ready(dev);
+
+ fail:
+ kfree(hw_priv);
+ if (local)
+ local->hw_priv = NULL;
+ prism2_free_local_data(dev);
+
+ if (irq_registered && dev)
+ free_irq(dev->irq, dev);
+
+ if (attr_mem)
+ iounmap(attr_mem);
+
+ pci_disable_device(pdev);
+
+ return -ENODEV;
+}
+
+
+static void prism2_plx_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ struct hostap_plx_priv *hw_priv;
+
+ dev = pci_get_drvdata(pdev);
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+
+ /* Reset the hardware, and ensure interrupts are disabled. */
+ prism2_plx_cor_sreset(iface->local);
+ hfa384x_disable_interrupts(dev);
+
+ if (hw_priv->attr_mem)
+ iounmap(hw_priv->attr_mem);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ kfree(iface->local->hw_priv);
+ iface->local->hw_priv = NULL;
+ prism2_free_local_data(dev);
+ pci_disable_device(pdev);
+}
+
+
+MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
+
+static struct pci_driver prism2_plx_drv_id = {
+ .name = "prism2_plx",
+ .id_table = prism2_plx_id_table,
+ .probe = prism2_plx_probe,
+ .remove = prism2_plx_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .enable_wake = NULL
+};
+
+
+static int __init init_prism2_plx(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
+ return pci_register_driver(&prism2_plx_drv_id);
+}
+
+
+static void __exit exit_prism2_plx(void)
+{
+ pci_unregister_driver(&prism2_plx_drv_id);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_plx);
+module_exit(exit_prism2_plx);
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
new file mode 100644
index 000000000000..a0a4cbd4937a
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -0,0 +1,448 @@
+/* /proc routines for Host AP driver */
+
+#define PROC_LIMIT (PAGE_SIZE - 80)
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int prism2_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int i;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
+ local->next_txfid, local->next_alloc);
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++)
+ p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
+ local->txfid[i], local->intransmitfid[i]);
+ p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
+ p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
+ p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
+ p += sprintf(p, "wds_max_connections=%d\n",
+ local->wds_max_connections);
+ p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
+ p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (local->crypt[i] && local->crypt[i]->ops) {
+ p += sprintf(p, "crypt[%d]=%s\n",
+ i, local->crypt[i]->ops->name);
+ }
+ }
+ p += sprintf(p, "pri_only=%d\n", local->pri_only);
+ p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
+ p += sprintf(p, "sram_type=%d\n", local->sram_type);
+ p += sprintf(p, "no_pri=%d\n", local->no_pri);
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+static int prism2_stats_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
+ &local->comm_tallies;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
+ p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
+ p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
+ p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
+ p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
+ p += sprintf(p, "TxDeferredTransmissions=%u\n",
+ sums->tx_deferred_transmissions);
+ p += sprintf(p, "TxSingleRetryFrames=%u\n",
+ sums->tx_single_retry_frames);
+ p += sprintf(p, "TxMultipleRetryFrames=%u\n",
+ sums->tx_multiple_retry_frames);
+ p += sprintf(p, "TxRetryLimitExceeded=%u\n",
+ sums->tx_retry_limit_exceeded);
+ p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
+ p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
+ p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
+ p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
+ p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
+ p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
+ p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
+ p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
+ sums->rx_discards_no_buffer);
+ p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
+ p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
+ sums->rx_discards_wep_undecryptable);
+ p += sprintf(p, "RxMessageInMsgFragments=%u\n",
+ sums->rx_message_in_msg_fragments);
+ p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
+ sums->rx_message_in_bad_msg_fragments);
+ /* FIX: this may grow too long for one page(?) */
+
+ return (p - page);
+}
+
+
+static int prism2_wds_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct list_head *ptr;
+ struct hostap_interface *iface;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+ p += sprintf(p, "%s\t" MACSTR "\n",
+ iface->dev->name,
+ MAC2STR(iface->u.wds.remote_addr));
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "%s: wds proc did not fit\n",
+ local->dev->name);
+ break;
+ }
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct list_head *ptr;
+ struct hostap_bss_info *bss;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
+ "SSID(hex)\tWPA IE\n");
+ spin_lock_bh(&local->lock);
+ list_for_each(ptr, &local->bss_list) {
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ p += sprintf(p, MACSTR "\t%lu\t%u\t0x%x\t",
+ MAC2STR(bss->bssid), bss->last_update,
+ bss->count, bss->capab_info);
+ for (i = 0; i < bss->ssid_len; i++) {
+ p += sprintf(p, "%c",
+ bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
+ bss->ssid[i] : '_');
+ }
+ p += sprintf(p, "\t");
+ for (i = 0; i < bss->ssid_len; i++) {
+ p += sprintf(p, "%02x", bss->ssid[i]);
+ }
+ p += sprintf(p, "\t");
+ for (i = 0; i < bss->wpa_ie_len; i++) {
+ p += sprintf(p, "%02x", bss->wpa_ie[i]);
+ }
+ p += sprintf(p, "\n");
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "%s: BSS proc did not fit\n",
+ local->dev->name);
+ break;
+ }
+ }
+ spin_unlock_bh(&local->lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_crypt_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (local->crypt[i] && local->crypt[i]->ops &&
+ local->crypt[i]->ops->print_stats) {
+ p = local->crypt[i]->ops->print_stats(
+ p, local->crypt[i]->priv);
+ }
+ }
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_pda_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
+ *eof = 1;
+ return 0;
+ }
+
+ if (off + count > PRISM2_PDA_SIZE)
+ count = PRISM2_PDA_SIZE - off;
+
+ memcpy(page, local->pda + off, count);
+ return count;
+}
+
+
+static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (local->func->read_aux == NULL) {
+ *eof = 1;
+ return 0;
+ }
+
+ if (local->func->read_aux(local->dev, off, count, page)) {
+ *eof = 1;
+ return 0;
+ }
+ *start = page;
+
+ return count;
+}
+
+
+#ifdef PRISM2_IO_DEBUG
+static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+ int head = local->io_debug_head;
+ int start_bytes, left, copy, copied;
+
+ if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
+ *eof = 1;
+ if (off >= PRISM2_IO_DEBUG_SIZE * 4)
+ return 0;
+ count = PRISM2_IO_DEBUG_SIZE * 4 - off;
+ }
+
+ copied = 0;
+ start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
+ left = count;
+
+ if (off < start_bytes) {
+ copy = start_bytes - off;
+ if (copy > count)
+ copy = count;
+ memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
+ left -= copy;
+ if (left > 0)
+ memcpy(&page[copy], local->io_debug, left);
+ } else {
+ memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
+ left);
+ }
+
+ *start = page;
+
+ return count;
+}
+#endif /* PRISM2_IO_DEBUG */
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int entry, i, len, total = 0;
+ struct hfa384x_hostscan_result *scanres;
+ u8 *pos;
+
+ p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
+ "SSID\n");
+
+ spin_lock_bh(&local->lock);
+ for (entry = 0; entry < local->last_scan_results_count; entry++) {
+ scanres = &local->last_scan_results[entry];
+
+ if (total + (p - page) <= off) {
+ total += p - page;
+ p = page;
+ }
+ if (total + (p - page) > off + count)
+ break;
+ if ((p - page) > (PAGE_SIZE - 200))
+ break;
+
+ p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR " %d ",
+ le16_to_cpu(scanres->chid),
+ (s16) le16_to_cpu(scanres->anl),
+ (s16) le16_to_cpu(scanres->sl),
+ le16_to_cpu(scanres->beacon_interval),
+ le16_to_cpu(scanres->capability),
+ le16_to_cpu(scanres->rate),
+ MAC2STR(scanres->bssid),
+ le16_to_cpu(scanres->atim));
+
+ pos = scanres->sup_rates;
+ for (i = 0; i < sizeof(scanres->sup_rates); i++) {
+ if (pos[i] == 0)
+ break;
+ p += sprintf(p, "<%02x>", pos[i]);
+ }
+ p += sprintf(p, " ");
+
+ pos = scanres->ssid;
+ len = le16_to_cpu(scanres->ssid_len);
+ if (len > 32)
+ len = 32;
+ for (i = 0; i < len; i++) {
+ unsigned char c = pos[i];
+ if (c >= 32 && c < 127)
+ p += sprintf(p, "%c", c);
+ else
+ p += sprintf(p, "<%02x>", c);
+ }
+ p += sprintf(p, "\n");
+ }
+ spin_unlock_bh(&local->lock);
+
+ total += (p - page);
+ if (total >= off + count)
+ *eof = 1;
+
+ if (total < off) {
+ *eof = 1;
+ return 0;
+ }
+
+ len = total - off;
+ if (len > (p - page))
+ len = p - page;
+ *start = p - len;
+ if (len > count)
+ len = count;
+
+ return len;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+void hostap_init_proc(local_info_t *local)
+{
+ local->proc = NULL;
+
+ if (hostap_proc == NULL) {
+ printk(KERN_WARNING "%s: hostap proc directory not created\n",
+ local->dev->name);
+ return;
+ }
+
+ local->proc = proc_mkdir(local->ddev->name, hostap_proc);
+ if (local->proc == NULL) {
+ printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
+ local->ddev->name);
+ return;
+ }
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("debug", 0, local->proc,
+ prism2_debug_proc_read, local);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ create_proc_read_entry("stats", 0, local->proc,
+ prism2_stats_proc_read, local);
+ create_proc_read_entry("wds", 0, local->proc,
+ prism2_wds_proc_read, local);
+ create_proc_read_entry("pda", 0, local->proc,
+ prism2_pda_proc_read, local);
+ create_proc_read_entry("aux_dump", 0, local->proc,
+ prism2_aux_dump_proc_read, local);
+ create_proc_read_entry("bss_list", 0, local->proc,
+ prism2_bss_list_proc_read, local);
+ create_proc_read_entry("crypt", 0, local->proc,
+ prism2_crypt_proc_read, local);
+#ifdef PRISM2_IO_DEBUG
+ create_proc_read_entry("io_debug", 0, local->proc,
+ prism2_io_debug_proc_read, local);
+#endif /* PRISM2_IO_DEBUG */
+#ifndef PRISM2_NO_STATION_MODES
+ create_proc_read_entry("scan_results", 0, local->proc,
+ prism2_scan_results_proc_read, local);
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+void hostap_remove_proc(local_info_t *local)
+{
+ if (local->proc != NULL) {
+#ifndef PRISM2_NO_STATION_MODES
+ remove_proc_entry("scan_results", local->proc);
+#endif /* PRISM2_NO_STATION_MODES */
+#ifdef PRISM2_IO_DEBUG
+ remove_proc_entry("io_debug", local->proc);
+#endif /* PRISM2_IO_DEBUG */
+ remove_proc_entry("pda", local->proc);
+ remove_proc_entry("aux_dump", local->proc);
+ remove_proc_entry("wds", local->proc);
+ remove_proc_entry("stats", local->proc);
+ remove_proc_entry("bss_list", local->proc);
+ remove_proc_entry("crypt", local->proc);
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ remove_proc_entry("debug", local->proc);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ if (hostap_proc != NULL)
+ remove_proc_entry(local->proc->name, hostap_proc);
+ }
+}
+
+
+EXPORT_SYMBOL(hostap_init_proc);
+EXPORT_SYMBOL(hostap_remove_proc);
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
new file mode 100644
index 000000000000..cc061e1560d3
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -0,0 +1,1033 @@
+#ifndef HOSTAP_WLAN_H
+#define HOSTAP_WLAN_H
+
+#include "hostap_config.h"
+#include "hostap_common.h"
+
+#define MAX_PARM_DEVICES 8
+#define PARM_MIN_MAX "1-" __MODULE_STRING(MAX_PARM_DEVICES)
+#define DEF_INTS -1, -1, -1, -1, -1, -1, -1
+#define GET_INT_PARM(var,idx) var[var[idx] < 0 ? 0 : idx]
+
+
+/* Specific skb->protocol value that indicates that the packet already contains
+ * txdesc header.
+ * FIX: This might need own value that would be allocated especially for Prism2
+ * txdesc; ETH_P_CONTROL is commented as "Card specific control frames".
+ * However, these skb's should have only minimal path in the kernel side since
+ * prism2_send_mgmt() sends these with dev_queue_xmit() to prism2_tx(). */
+#define ETH_P_HOSTAP ETH_P_CONTROL
+
+/* ARPHRD_IEEE80211_PRISM uses a bloated version of Prism2 RX frame header
+ * (from linux-wlan-ng) */
+struct linux_wlan_ng_val {
+ u32 did;
+ u16 status, len;
+ u32 data;
+} __attribute__ ((packed));
+
+struct linux_wlan_ng_prism_hdr {
+ u32 msgcode, msglen;
+ char devname[16];
+ struct linux_wlan_ng_val hosttime, mactime, channel, rssi, sq, signal,
+ noise, rate, istx, frmlen;
+} __attribute__ ((packed));
+
+struct linux_wlan_ng_cap_hdr {
+ u32 version;
+ u32 length;
+ u64 mactime;
+ u64 hosttime;
+ u32 phytype;
+ u32 channel;
+ u32 datarate;
+ u32 antenna;
+ u32 priority;
+ u32 ssi_type;
+ s32 ssi_signal;
+ s32 ssi_noise;
+ u32 preamble;
+ u32 encoding;
+} __attribute__ ((packed));
+
+#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */
+#define LWNG_CAPHDR_VERSION 0x80211001
+
+struct hfa384x_rx_frame {
+ /* HFA384X RX frame descriptor */
+ u16 status; /* HFA384X_RX_STATUS_ flags */
+ u32 time; /* timestamp, 1 microsecond resolution */
+ u8 silence; /* 27 .. 154; seems to be 0 */
+ u8 signal; /* 27 .. 154 */
+ u8 rate; /* 10, 20, 55, or 110 */
+ u8 rxflow;
+ u32 reserved;
+
+ /* 802.11 */
+ u16 frame_control;
+ u16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6];
+ u8 addr3[6];
+ u16 seq_ctrl;
+ u8 addr4[6];
+ u16 data_len;
+
+ /* 802.3 */
+ u8 dst_addr[6];
+ u8 src_addr[6];
+ u16 len;
+
+ /* followed by frame data; max 2304 bytes */
+} __attribute__ ((packed));
+
+
+struct hfa384x_tx_frame {
+ /* HFA384X TX frame descriptor */
+ u16 status; /* HFA384X_TX_STATUS_ flags */
+ u16 reserved1;
+ u16 reserved2;
+ u32 sw_support;
+ u8 retry_count; /* not yet implemented */
+ u8 tx_rate; /* Host AP only; 0 = firmware, or 10, 20, 55, 110 */
+ u16 tx_control; /* HFA384X_TX_CTRL_ flags */
+
+ /* 802.11 */
+ u16 frame_control; /* parts not used */
+ u16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6]; /* filled by firmware */
+ u8 addr3[6];
+ u16 seq_ctrl; /* filled by firmware */
+ u8 addr4[6];
+ u16 data_len;
+
+ /* 802.3 */
+ u8 dst_addr[6];
+ u8 src_addr[6];
+ u16 len;
+
+ /* followed by frame data; max 2304 bytes */
+} __attribute__ ((packed));
+
+
+struct hfa384x_rid_hdr
+{
+ u16 len;
+ u16 rid;
+} __attribute__ ((packed));
+
+
+/* Macro for converting signal levels (range 27 .. 154) to wireless ext
+ * dBm value with some accuracy */
+#define HFA384X_LEVEL_TO_dBm(v) 0x100 + (v) * 100 / 255 - 100
+
+#define HFA384X_LEVEL_TO_dBm_sign(v) (v) * 100 / 255 - 100
+
+struct hfa384x_scan_request {
+ u16 channel_list;
+ u16 txrate; /* HFA384X_RATES_* */
+} __attribute__ ((packed));
+
+struct hfa384x_hostscan_request {
+ u16 channel_list;
+ u16 txrate;
+ u16 target_ssid_len;
+ u8 target_ssid[32];
+} __attribute__ ((packed));
+
+struct hfa384x_join_request {
+ u8 bssid[6];
+ u16 channel;
+} __attribute__ ((packed));
+
+struct hfa384x_info_frame {
+ u16 len;
+ u16 type;
+} __attribute__ ((packed));
+
+struct hfa384x_comm_tallies {
+ u16 tx_unicast_frames;
+ u16 tx_multicast_frames;
+ u16 tx_fragments;
+ u16 tx_unicast_octets;
+ u16 tx_multicast_octets;
+ u16 tx_deferred_transmissions;
+ u16 tx_single_retry_frames;
+ u16 tx_multiple_retry_frames;
+ u16 tx_retry_limit_exceeded;
+ u16 tx_discards;
+ u16 rx_unicast_frames;
+ u16 rx_multicast_frames;
+ u16 rx_fragments;
+ u16 rx_unicast_octets;
+ u16 rx_multicast_octets;
+ u16 rx_fcs_errors;
+ u16 rx_discards_no_buffer;
+ u16 tx_discards_wrong_sa;
+ u16 rx_discards_wep_undecryptable;
+ u16 rx_message_in_msg_fragments;
+ u16 rx_message_in_bad_msg_fragments;
+} __attribute__ ((packed));
+
+struct hfa384x_comm_tallies32 {
+ u32 tx_unicast_frames;
+ u32 tx_multicast_frames;
+ u32 tx_fragments;
+ u32 tx_unicast_octets;
+ u32 tx_multicast_octets;
+ u32 tx_deferred_transmissions;
+ u32 tx_single_retry_frames;
+ u32 tx_multiple_retry_frames;
+ u32 tx_retry_limit_exceeded;
+ u32 tx_discards;
+ u32 rx_unicast_frames;
+ u32 rx_multicast_frames;
+ u32 rx_fragments;
+ u32 rx_unicast_octets;
+ u32 rx_multicast_octets;
+ u32 rx_fcs_errors;
+ u32 rx_discards_no_buffer;
+ u32 tx_discards_wrong_sa;
+ u32 rx_discards_wep_undecryptable;
+ u32 rx_message_in_msg_fragments;
+ u32 rx_message_in_bad_msg_fragments;
+} __attribute__ ((packed));
+
+struct hfa384x_scan_result_hdr {
+ u16 reserved;
+ u16 scan_reason;
+#define HFA384X_SCAN_IN_PROGRESS 0 /* no results available yet */
+#define HFA384X_SCAN_HOST_INITIATED 1
+#define HFA384X_SCAN_FIRMWARE_INITIATED 2
+#define HFA384X_SCAN_INQUIRY_FROM_HOST 3
+} __attribute__ ((packed));
+
+#define HFA384X_SCAN_MAX_RESULTS 32
+
+struct hfa384x_scan_result {
+ u16 chid;
+ u16 anl;
+ u16 sl;
+ u8 bssid[6];
+ u16 beacon_interval;
+ u16 capability;
+ u16 ssid_len;
+ u8 ssid[32];
+ u8 sup_rates[10];
+ u16 rate;
+} __attribute__ ((packed));
+
+struct hfa384x_hostscan_result {
+ u16 chid;
+ u16 anl;
+ u16 sl;
+ u8 bssid[6];
+ u16 beacon_interval;
+ u16 capability;
+ u16 ssid_len;
+ u8 ssid[32];
+ u8 sup_rates[10];
+ u16 rate;
+ u16 atim;
+} __attribute__ ((packed));
+
+struct comm_tallies_sums {
+ unsigned int tx_unicast_frames;
+ unsigned int tx_multicast_frames;
+ unsigned int tx_fragments;
+ unsigned int tx_unicast_octets;
+ unsigned int tx_multicast_octets;
+ unsigned int tx_deferred_transmissions;
+ unsigned int tx_single_retry_frames;
+ unsigned int tx_multiple_retry_frames;
+ unsigned int tx_retry_limit_exceeded;
+ unsigned int tx_discards;
+ unsigned int rx_unicast_frames;
+ unsigned int rx_multicast_frames;
+ unsigned int rx_fragments;
+ unsigned int rx_unicast_octets;
+ unsigned int rx_multicast_octets;
+ unsigned int rx_fcs_errors;
+ unsigned int rx_discards_no_buffer;
+ unsigned int tx_discards_wrong_sa;
+ unsigned int rx_discards_wep_undecryptable;
+ unsigned int rx_message_in_msg_fragments;
+ unsigned int rx_message_in_bad_msg_fragments;
+};
+
+
+struct hfa384x_regs {
+ u16 cmd;
+ u16 evstat;
+ u16 offset0;
+ u16 offset1;
+ u16 swsupport0;
+};
+
+
+#if defined(PRISM2_PCCARD) || defined(PRISM2_PLX)
+/* I/O ports for HFA384X Controller access */
+#define HFA384X_CMD_OFF 0x00
+#define HFA384X_PARAM0_OFF 0x02
+#define HFA384X_PARAM1_OFF 0x04
+#define HFA384X_PARAM2_OFF 0x06
+#define HFA384X_STATUS_OFF 0x08
+#define HFA384X_RESP0_OFF 0x0A
+#define HFA384X_RESP1_OFF 0x0C
+#define HFA384X_RESP2_OFF 0x0E
+#define HFA384X_INFOFID_OFF 0x10
+#define HFA384X_CONTROL_OFF 0x14
+#define HFA384X_SELECT0_OFF 0x18
+#define HFA384X_SELECT1_OFF 0x1A
+#define HFA384X_OFFSET0_OFF 0x1C
+#define HFA384X_OFFSET1_OFF 0x1E
+#define HFA384X_RXFID_OFF 0x20
+#define HFA384X_ALLOCFID_OFF 0x22
+#define HFA384X_TXCOMPLFID_OFF 0x24
+#define HFA384X_SWSUPPORT0_OFF 0x28
+#define HFA384X_SWSUPPORT1_OFF 0x2A
+#define HFA384X_SWSUPPORT2_OFF 0x2C
+#define HFA384X_EVSTAT_OFF 0x30
+#define HFA384X_INTEN_OFF 0x32
+#define HFA384X_EVACK_OFF 0x34
+#define HFA384X_DATA0_OFF 0x36
+#define HFA384X_DATA1_OFF 0x38
+#define HFA384X_AUXPAGE_OFF 0x3A
+#define HFA384X_AUXOFFSET_OFF 0x3C
+#define HFA384X_AUXDATA_OFF 0x3E
+#endif /* PRISM2_PCCARD || PRISM2_PLX */
+
+#ifdef PRISM2_PCI
+/* Memory addresses for ISL3874 controller access */
+#define HFA384X_CMD_OFF 0x00
+#define HFA384X_PARAM0_OFF 0x04
+#define HFA384X_PARAM1_OFF 0x08
+#define HFA384X_PARAM2_OFF 0x0C
+#define HFA384X_STATUS_OFF 0x10
+#define HFA384X_RESP0_OFF 0x14
+#define HFA384X_RESP1_OFF 0x18
+#define HFA384X_RESP2_OFF 0x1C
+#define HFA384X_INFOFID_OFF 0x20
+#define HFA384X_CONTROL_OFF 0x28
+#define HFA384X_SELECT0_OFF 0x30
+#define HFA384X_SELECT1_OFF 0x34
+#define HFA384X_OFFSET0_OFF 0x38
+#define HFA384X_OFFSET1_OFF 0x3C
+#define HFA384X_RXFID_OFF 0x40
+#define HFA384X_ALLOCFID_OFF 0x44
+#define HFA384X_TXCOMPLFID_OFF 0x48
+#define HFA384X_PCICOR_OFF 0x4C
+#define HFA384X_SWSUPPORT0_OFF 0x50
+#define HFA384X_SWSUPPORT1_OFF 0x54
+#define HFA384X_SWSUPPORT2_OFF 0x58
+#define HFA384X_PCIHCR_OFF 0x5C
+#define HFA384X_EVSTAT_OFF 0x60
+#define HFA384X_INTEN_OFF 0x64
+#define HFA384X_EVACK_OFF 0x68
+#define HFA384X_DATA0_OFF 0x6C
+#define HFA384X_DATA1_OFF 0x70
+#define HFA384X_AUXPAGE_OFF 0x74
+#define HFA384X_AUXOFFSET_OFF 0x78
+#define HFA384X_AUXDATA_OFF 0x7C
+#define HFA384X_PCI_M0_ADDRH_OFF 0x80
+#define HFA384X_PCI_M0_ADDRL_OFF 0x84
+#define HFA384X_PCI_M0_LEN_OFF 0x88
+#define HFA384X_PCI_M0_CTL_OFF 0x8C
+#define HFA384X_PCI_STATUS_OFF 0x98
+#define HFA384X_PCI_M1_ADDRH_OFF 0xA0
+#define HFA384X_PCI_M1_ADDRL_OFF 0xA4
+#define HFA384X_PCI_M1_LEN_OFF 0xA8
+#define HFA384X_PCI_M1_CTL_OFF 0xAC
+
+/* PCI bus master control bits (these are undocumented; based on guessing and
+ * experimenting..) */
+#define HFA384X_PCI_CTL_FROM_BAP (BIT(5) | BIT(1) | BIT(0))
+#define HFA384X_PCI_CTL_TO_BAP (BIT(5) | BIT(0))
+
+#endif /* PRISM2_PCI */
+
+
+/* Command codes for CMD reg. */
+#define HFA384X_CMDCODE_INIT 0x00
+#define HFA384X_CMDCODE_ENABLE 0x01
+#define HFA384X_CMDCODE_DISABLE 0x02
+#define HFA384X_CMDCODE_ALLOC 0x0A
+#define HFA384X_CMDCODE_TRANSMIT 0x0B
+#define HFA384X_CMDCODE_INQUIRE 0x11
+#define HFA384X_CMDCODE_ACCESS 0x21
+#define HFA384X_CMDCODE_ACCESS_WRITE (0x21 | BIT(8))
+#define HFA384X_CMDCODE_DOWNLOAD 0x22
+#define HFA384X_CMDCODE_READMIF 0x30
+#define HFA384X_CMDCODE_WRITEMIF 0x31
+#define HFA384X_CMDCODE_TEST 0x38
+
+#define HFA384X_CMDCODE_MASK 0x3F
+
+/* Test mode operations */
+#define HFA384X_TEST_CHANGE_CHANNEL 0x08
+#define HFA384X_TEST_MONITOR 0x0B
+#define HFA384X_TEST_STOP 0x0F
+#define HFA384X_TEST_CFG_BITS 0x15
+#define HFA384X_TEST_CFG_BIT_ALC BIT(3)
+
+#define HFA384X_CMD_BUSY BIT(15)
+
+#define HFA384X_CMD_TX_RECLAIM BIT(8)
+
+#define HFA384X_OFFSET_ERR BIT(14)
+#define HFA384X_OFFSET_BUSY BIT(15)
+
+
+/* ProgMode for download command */
+#define HFA384X_PROGMODE_DISABLE 0
+#define HFA384X_PROGMODE_ENABLE_VOLATILE 1
+#define HFA384X_PROGMODE_ENABLE_NON_VOLATILE 2
+#define HFA384X_PROGMODE_PROGRAM_NON_VOLATILE 3
+
+#define HFA384X_AUX_MAGIC0 0xfe01
+#define HFA384X_AUX_MAGIC1 0xdc23
+#define HFA384X_AUX_MAGIC2 0xba45
+
+#define HFA384X_AUX_PORT_DISABLED 0
+#define HFA384X_AUX_PORT_DISABLE BIT(14)
+#define HFA384X_AUX_PORT_ENABLE BIT(15)
+#define HFA384X_AUX_PORT_ENABLED (BIT(14) | BIT(15))
+#define HFA384X_AUX_PORT_MASK (BIT(14) | BIT(15))
+
+#define PRISM2_PDA_SIZE 1024
+
+
+/* Events; EvStat, Interrupt mask (IntEn), and acknowledge bits (EvAck) */
+#define HFA384X_EV_TICK BIT(15)
+#define HFA384X_EV_WTERR BIT(14)
+#define HFA384X_EV_INFDROP BIT(13)
+#ifdef PRISM2_PCI
+#define HFA384X_EV_PCI_M1 BIT(9)
+#define HFA384X_EV_PCI_M0 BIT(8)
+#endif /* PRISM2_PCI */
+#define HFA384X_EV_INFO BIT(7)
+#define HFA384X_EV_DTIM BIT(5)
+#define HFA384X_EV_CMD BIT(4)
+#define HFA384X_EV_ALLOC BIT(3)
+#define HFA384X_EV_TXEXC BIT(2)
+#define HFA384X_EV_TX BIT(1)
+#define HFA384X_EV_RX BIT(0)
+
+
+/* HFA384X Information frames */
+#define HFA384X_INFO_HANDOVERADDR 0xF000 /* AP f/w ? */
+#define HFA384X_INFO_HANDOVERDEAUTHADDR 0xF001 /* AP f/w 1.3.7 */
+#define HFA384X_INFO_COMMTALLIES 0xF100
+#define HFA384X_INFO_SCANRESULTS 0xF101
+#define HFA384X_INFO_CHANNELINFORESULTS 0xF102 /* AP f/w only */
+#define HFA384X_INFO_HOSTSCANRESULTS 0xF103
+#define HFA384X_INFO_LINKSTATUS 0xF200
+#define HFA384X_INFO_ASSOCSTATUS 0xF201 /* ? */
+#define HFA384X_INFO_AUTHREQ 0xF202 /* ? */
+#define HFA384X_INFO_PSUSERCNT 0xF203 /* ? */
+#define HFA384X_INFO_KEYIDCHANGED 0xF204 /* ? */
+
+enum { HFA384X_LINKSTATUS_CONNECTED = 1,
+ HFA384X_LINKSTATUS_DISCONNECTED = 2,
+ HFA384X_LINKSTATUS_AP_CHANGE = 3,
+ HFA384X_LINKSTATUS_AP_OUT_OF_RANGE = 4,
+ HFA384X_LINKSTATUS_AP_IN_RANGE = 5,
+ HFA384X_LINKSTATUS_ASSOC_FAILED = 6 };
+
+enum { HFA384X_PORTTYPE_BSS = 1, HFA384X_PORTTYPE_WDS = 2,
+ HFA384X_PORTTYPE_PSEUDO_IBSS = 3, HFA384X_PORTTYPE_IBSS = 0,
+ HFA384X_PORTTYPE_HOSTAP = 6 };
+
+#define HFA384X_RATES_1MBPS BIT(0)
+#define HFA384X_RATES_2MBPS BIT(1)
+#define HFA384X_RATES_5MBPS BIT(2)
+#define HFA384X_RATES_11MBPS BIT(3)
+
+#define HFA384X_ROAMING_FIRMWARE 1
+#define HFA384X_ROAMING_HOST 2
+#define HFA384X_ROAMING_DISABLED 3
+
+#define HFA384X_WEPFLAGS_PRIVACYINVOKED BIT(0)
+#define HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED BIT(1)
+#define HFA384X_WEPFLAGS_HOSTENCRYPT BIT(4)
+#define HFA384X_WEPFLAGS_HOSTDECRYPT BIT(7)
+
+#define HFA384X_RX_STATUS_MSGTYPE (BIT(15) | BIT(14) | BIT(13))
+#define HFA384X_RX_STATUS_PCF BIT(12)
+#define HFA384X_RX_STATUS_MACPORT (BIT(10) | BIT(9) | BIT(8))
+#define HFA384X_RX_STATUS_UNDECR BIT(1)
+#define HFA384X_RX_STATUS_FCSERR BIT(0)
+
+#define HFA384X_RX_STATUS_GET_MSGTYPE(s) \
+(((s) & HFA384X_RX_STATUS_MSGTYPE) >> 13)
+#define HFA384X_RX_STATUS_GET_MACPORT(s) \
+(((s) & HFA384X_RX_STATUS_MACPORT) >> 8)
+
+enum { HFA384X_RX_MSGTYPE_NORMAL = 0, HFA384X_RX_MSGTYPE_RFC1042 = 1,
+ HFA384X_RX_MSGTYPE_BRIDGETUNNEL = 2, HFA384X_RX_MSGTYPE_MGMT = 4 };
+
+
+#define HFA384X_TX_CTRL_ALT_RTRY BIT(5)
+#define HFA384X_TX_CTRL_802_11 BIT(3)
+#define HFA384X_TX_CTRL_802_3 0
+#define HFA384X_TX_CTRL_TX_EX BIT(2)
+#define HFA384X_TX_CTRL_TX_OK BIT(1)
+
+#define HFA384X_TX_STATUS_RETRYERR BIT(0)
+#define HFA384X_TX_STATUS_AGEDERR BIT(1)
+#define HFA384X_TX_STATUS_DISCON BIT(2)
+#define HFA384X_TX_STATUS_FORMERR BIT(3)
+
+/* HFA3861/3863 (BBP) Control Registers */
+#define HFA386X_CR_TX_CONFIGURE 0x12 /* CR9 */
+#define HFA386X_CR_RX_CONFIGURE 0x14 /* CR10 */
+#define HFA386X_CR_A_D_TEST_MODES2 0x1A /* CR13 */
+#define HFA386X_CR_MANUAL_TX_POWER 0x3E /* CR31 */
+#define HFA386X_CR_MEASURED_TX_POWER 0x74 /* CR58 */
+
+
+#ifdef __KERNEL__
+
+#define PRISM2_TXFID_COUNT 8
+#define PRISM2_DATA_MAXLEN 2304
+#define PRISM2_TXFID_LEN (PRISM2_DATA_MAXLEN + sizeof(struct hfa384x_tx_frame))
+#define PRISM2_TXFID_EMPTY 0xffff
+#define PRISM2_TXFID_RESERVED 0xfffe
+#define PRISM2_DUMMY_FID 0xffff
+#define MAX_SSID_LEN 32
+#define MAX_NAME_LEN 32 /* this is assumed to be equal to MAX_SSID_LEN */
+
+#define PRISM2_DUMP_RX_HDR BIT(0)
+#define PRISM2_DUMP_TX_HDR BIT(1)
+#define PRISM2_DUMP_TXEXC_HDR BIT(2)
+
+struct hostap_tx_callback_info {
+ u16 idx;
+ void (*func)(struct sk_buff *, int ok, void *);
+ void *data;
+ struct hostap_tx_callback_info *next;
+};
+
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+#define PRISM2_FRAG_CACHE_LEN 4
+
+struct prism2_frag_entry {
+ unsigned long first_frag_time;
+ unsigned int seq;
+ unsigned int last_frag;
+ struct sk_buff *skb;
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+};
+
+
+struct hostap_cmd_queue {
+ struct list_head list;
+ wait_queue_head_t compl;
+ volatile enum { CMD_SLEEP, CMD_CALLBACK, CMD_COMPLETED } type;
+ void (*callback)(struct net_device *dev, long context, u16 resp0,
+ u16 res);
+ long context;
+ u16 cmd, param0, param1;
+ u16 resp0, res;
+ volatile int issued, issuing;
+
+ atomic_t usecnt;
+ int del_req;
+};
+
+/* options for hw_shutdown */
+#define HOSTAP_HW_NO_DISABLE BIT(0)
+#define HOSTAP_HW_ENABLE_CMDCOMPL BIT(1)
+
+typedef struct local_info local_info_t;
+
+struct prism2_helper_functions {
+ /* these functions are defined in hardware model specific files
+ * (hostap_{cs,plx,pci}.c */
+ int (*card_present)(local_info_t *local);
+ void (*cor_sreset)(local_info_t *local);
+ int (*dev_open)(local_info_t *local);
+ int (*dev_close)(local_info_t *local);
+ void (*genesis_reset)(local_info_t *local, int hcr);
+
+ /* the following functions are from hostap_hw.c, but they may have some
+ * hardware model specific code */
+
+ /* FIX: low-level commands like cmd might disappear at some point to
+ * make it easier to change them if needed (e.g., cmd would be replaced
+ * with write_mif/read_mif/testcmd/inquire); at least get_rid and
+ * set_rid might move to hostap_{cs,plx,pci}.c */
+ int (*cmd)(struct net_device *dev, u16 cmd, u16 param0, u16 *param1,
+ u16 *resp0);
+ void (*read_regs)(struct net_device *dev, struct hfa384x_regs *regs);
+ int (*get_rid)(struct net_device *dev, u16 rid, void *buf, int len,
+ int exact_len);
+ int (*set_rid)(struct net_device *dev, u16 rid, void *buf, int len);
+ int (*hw_enable)(struct net_device *dev, int initial);
+ int (*hw_config)(struct net_device *dev, int initial);
+ void (*hw_reset)(struct net_device *dev);
+ void (*hw_shutdown)(struct net_device *dev, int no_disable);
+ int (*reset_port)(struct net_device *dev);
+ void (*schedule_reset)(local_info_t *local);
+ int (*download)(local_info_t *local,
+ struct prism2_download_param *param);
+ int (*tx)(struct sk_buff *skb, struct net_device *dev);
+ int (*set_tim)(struct net_device *dev, int aid, int set);
+ int (*read_aux)(struct net_device *dev, unsigned addr, int len,
+ u8 *buf);
+
+ int need_tx_headroom; /* number of bytes of headroom needed before
+ * IEEE 802.11 header */
+ enum { HOSTAP_HW_PCCARD, HOSTAP_HW_PLX, HOSTAP_HW_PCI } hw_type;
+};
+
+
+struct prism2_download_data {
+ u32 dl_cmd;
+ u32 start_addr;
+ u32 num_areas;
+ struct prism2_download_data_area {
+ u32 addr; /* wlan card address */
+ u32 len;
+ u8 *data; /* allocated data */
+ } data[0];
+};
+
+
+#define HOSTAP_MAX_BSS_COUNT 64
+#define MAX_WPA_IE_LEN 64
+
+struct hostap_bss_info {
+ struct list_head list;
+ unsigned long last_update;
+ unsigned int count;
+ u8 bssid[ETH_ALEN];
+ u16 capab_info;
+ u8 ssid[32];
+ size_t ssid_len;
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ size_t wpa_ie_len;
+ u8 rsn_ie[MAX_WPA_IE_LEN];
+ size_t rsn_ie_len;
+ int chan;
+ int included;
+};
+
+
+/* Per radio private Host AP data - shared by all net devices interfaces used
+ * by each radio (wlan#, wlan#ap, wlan#sta, WDS).
+ * ((struct hostap_interface *) netdev_priv(dev))->local points to this
+ * structure. */
+struct local_info {
+ struct module *hw_module;
+ int card_idx;
+ int dev_enabled;
+ int master_dev_auto_open; /* was master device opened automatically */
+ int num_dev_open; /* number of open devices */
+ struct net_device *dev; /* master radio device */
+ struct net_device *ddev; /* main data device */
+ struct list_head hostap_interfaces; /* Host AP interface list (contains
+ * struct hostap_interface entries)
+ */
+ rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
+ * when removing entries from the list.
+ * TX and RX paths can use read lock. */
+ spinlock_t cmdlock, baplock, lock;
+ struct semaphore rid_bap_sem;
+ u16 infofid; /* MAC buffer id for info frame */
+ /* txfid, intransmitfid, next_txtid, and next_alloc are protected by
+ * txfidlock */
+ spinlock_t txfidlock;
+ int txfid_len; /* length of allocated TX buffers */
+ u16 txfid[PRISM2_TXFID_COUNT]; /* buffer IDs for TX frames */
+ /* buffer IDs for intransmit frames or PRISM2_TXFID_EMPTY if
+ * corresponding txfid is free for next TX frame */
+ u16 intransmitfid[PRISM2_TXFID_COUNT];
+ int next_txfid; /* index to the next txfid to be checked for
+ * availability */
+ int next_alloc; /* index to the next intransmitfid to be checked for
+ * allocation events */
+
+ /* bitfield for atomic bitops */
+#define HOSTAP_BITS_TRANSMIT 0
+#define HOSTAP_BITS_BAP_TASKLET 1
+#define HOSTAP_BITS_BAP_TASKLET2 2
+ long bits;
+
+ struct ap_data *ap;
+
+ char essid[MAX_SSID_LEN + 1];
+ char name[MAX_NAME_LEN + 1];
+ int name_set;
+ u16 channel_mask; /* mask of allowed channels */
+ u16 scan_channel_mask; /* mask of channels to be scanned */
+ struct comm_tallies_sums comm_tallies;
+ struct net_device_stats stats;
+ struct proc_dir_entry *proc;
+ int iw_mode; /* operating mode (IW_MODE_*) */
+ int pseudo_adhoc; /* 0: IW_MODE_ADHOC is real 802.11 compliant IBSS
+ * 1: IW_MODE_ADHOC is "pseudo IBSS" */
+ char bssid[ETH_ALEN];
+ int channel;
+ int beacon_int;
+ int dtim_period;
+ int mtu;
+ int frame_dump; /* dump RX/TX frame headers, PRISM2_DUMP_ flags */
+ int fw_tx_rate_control;
+ u16 tx_rate_control;
+ u16 basic_rates;
+ int hw_resetting;
+ int hw_ready;
+ int hw_reset_tries; /* how many times reset has been tried */
+ int hw_downloading;
+ int shutdown;
+ int pri_only;
+ int no_pri; /* no PRI f/w present */
+ int sram_type; /* 8 = x8 SRAM, 16 = x16 SRAM, -1 = unknown */
+
+ enum {
+ PRISM2_TXPOWER_AUTO = 0, PRISM2_TXPOWER_OFF,
+ PRISM2_TXPOWER_FIXED, PRISM2_TXPOWER_UNKNOWN
+ } txpower_type;
+ int txpower; /* if txpower_type == PRISM2_TXPOWER_FIXED */
+
+ /* command queue for hfa384x_cmd(); protected with cmdlock */
+ struct list_head cmd_queue;
+ /* max_len for cmd_queue; in addition, cmd_callback can use two
+ * additional entries to prevent sleeping commands from stopping
+ * transmits */
+#define HOSTAP_CMD_QUEUE_MAX_LEN 16
+ int cmd_queue_len; /* number of entries in cmd_queue */
+
+ /* if card timeout is detected in interrupt context, reset_queue is
+ * used to schedule card reseting to be done in user context */
+ struct work_struct reset_queue;
+
+ /* For scheduling a change of the promiscuous mode RID */
+ int is_promisc;
+ struct work_struct set_multicast_list_queue;
+
+ struct work_struct set_tim_queue;
+ struct list_head set_tim_list;
+ spinlock_t set_tim_lock;
+
+ int wds_max_connections;
+ int wds_connections;
+#define HOSTAP_WDS_BROADCAST_RA BIT(0)
+#define HOSTAP_WDS_AP_CLIENT BIT(1)
+#define HOSTAP_WDS_STANDARD_FRAME BIT(2)
+ u32 wds_type;
+ u16 tx_control; /* flags to be used in TX description */
+ int manual_retry_count; /* -1 = use f/w default; otherwise retry count
+ * to be used with all frames */
+
+ struct iw_statistics wstats;
+ unsigned long scan_timestamp; /* Time started to scan */
+ enum {
+ PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1,
+ PRISM2_MONITOR_CAPHDR = 2
+ } monitor_type;
+ int (*saved_eth_header_parse)(struct sk_buff *skb,
+ unsigned char *haddr);
+ int monitor_allow_fcserr;
+
+ int hostapd; /* whether user space daemon, hostapd, is used for AP
+ * management */
+ int hostapd_sta; /* whether hostapd is used with an extra STA interface
+ */
+ struct net_device *apdev;
+ struct net_device_stats apdevstats;
+
+ char assoc_ap_addr[ETH_ALEN];
+ struct net_device *stadev;
+ struct net_device_stats stadevstats;
+
+#define WEP_KEYS 4
+#define WEP_KEY_LEN 13
+ struct ieee80211_crypt_data *crypt[WEP_KEYS];
+ int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+ struct timer_list crypt_deinit_timer;
+ struct list_head crypt_deinit_list;
+
+ int open_wep; /* allow unencrypted frames */
+ int host_encrypt;
+ int host_decrypt;
+ int privacy_invoked; /* force privacy invoked flag even if no keys are
+ * configured */
+ int fw_encrypt_ok; /* whether firmware-based WEP encrypt is working
+ * in Host AP mode (STA f/w 1.4.9 or newer) */
+ int bcrx_sta_key; /* use individual keys to override default keys even
+ * with RX of broad/multicast frames */
+
+ struct prism2_frag_entry frag_cache[PRISM2_FRAG_CACHE_LEN];
+ unsigned int frag_next_idx;
+
+ int ieee_802_1x; /* is IEEE 802.1X used */
+
+ int antsel_tx, antsel_rx;
+ int rts_threshold; /* dot11RTSThreshold */
+ int fragm_threshold; /* dot11FragmentationThreshold */
+ int auth_algs; /* PRISM2_AUTH_ flags */
+
+ int enh_sec; /* cnfEnhSecurity options (broadcast SSID hide/ignore) */
+ int tallies32; /* 32-bit tallies in use */
+
+ struct prism2_helper_functions *func;
+
+ u8 *pda;
+ int fw_ap;
+#define PRISM2_FW_VER(major, minor, variant) \
+(((major) << 16) | ((minor) << 8) | variant)
+ u32 sta_fw_ver;
+
+ /* Tasklets for handling hardware IRQ related operations outside hw IRQ
+ * handler */
+ struct tasklet_struct bap_tasklet;
+
+ struct tasklet_struct info_tasklet;
+ struct sk_buff_head info_list; /* info frames as skb's for
+ * info_tasklet */
+
+ struct hostap_tx_callback_info *tx_callback; /* registered TX callbacks
+ */
+
+ struct tasklet_struct rx_tasklet;
+ struct sk_buff_head rx_list;
+
+ struct tasklet_struct sta_tx_exc_tasklet;
+ struct sk_buff_head sta_tx_exc_list;
+
+ int host_roaming;
+ unsigned long last_join_time; /* time of last JoinRequest */
+ struct hfa384x_hostscan_result *last_scan_results;
+ int last_scan_results_count;
+ enum { PRISM2_SCAN, PRISM2_HOSTSCAN } last_scan_type;
+ struct work_struct info_queue;
+ long pending_info; /* bit field of pending info_queue items */
+#define PRISM2_INFO_PENDING_LINKSTATUS 0
+#define PRISM2_INFO_PENDING_SCANRESULTS 1
+ int prev_link_status; /* previous received LinkStatus info */
+ int prev_linkstatus_connected;
+ u8 preferred_ap[6]; /* use this AP if possible */
+
+#ifdef PRISM2_CALLBACK
+ void *callback_data; /* Can be used in callbacks; e.g., allocate
+ * on enable event and free on disable event.
+ * Host AP driver code does not touch this. */
+#endif /* PRISM2_CALLBACK */
+
+ wait_queue_head_t hostscan_wq;
+
+ /* Passive scan in Host AP mode */
+ struct timer_list passive_scan_timer;
+ int passive_scan_interval; /* in seconds, 0 = disabled */
+ int passive_scan_channel;
+ enum { PASSIVE_SCAN_WAIT, PASSIVE_SCAN_LISTEN } passive_scan_state;
+
+ struct timer_list tick_timer;
+ unsigned long last_tick_timer;
+ unsigned int sw_tick_stuck;
+
+ /* commsQuality / dBmCommsQuality data from periodic polling; only
+ * valid for Managed and Ad-hoc modes */
+ unsigned long last_comms_qual_update;
+ int comms_qual; /* in some odd unit.. */
+ int avg_signal; /* in dB (note: negative) */
+ int avg_noise; /* in dB (note: negative) */
+ struct work_struct comms_qual_update;
+
+ /* RSSI to dBm adjustment (for RX descriptor fields) */
+ int rssi_to_dBm; /* substract from RSSI to get approximate dBm value */
+
+ /* BSS list / protected by local->lock */
+ struct list_head bss_list;
+ int num_bss_info;
+ int wpa; /* WPA support enabled */
+ int tkip_countermeasures;
+ int drop_unencrypted;
+ /* Generic IEEE 802.11 info element to be added to
+ * ProbeResp/Beacon/(Re)AssocReq */
+ u8 *generic_elem;
+ size_t generic_elem_len;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ /* Persistent volatile download data */
+ struct prism2_download_data *dl_pri;
+ struct prism2_download_data *dl_sec;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+#ifdef PRISM2_IO_DEBUG
+#define PRISM2_IO_DEBUG_SIZE 10000
+ u32 io_debug[PRISM2_IO_DEBUG_SIZE];
+ int io_debug_head;
+ int io_debug_enabled;
+#endif /* PRISM2_IO_DEBUG */
+
+ /* Pointer to hardware model specific (cs,pci,plx) private data. */
+ void *hw_priv;
+};
+
+
+/* Per interface private Host AP data
+ * Allocated for each net device that Host AP uses (wlan#, wlan#ap, wlan#sta,
+ * WDS) and netdev_priv(dev) points to this structure. */
+struct hostap_interface {
+ struct list_head list; /* list entry in Host AP interface list */
+ struct net_device *dev; /* pointer to this device */
+ struct local_info *local; /* pointer to shared private data */
+ struct net_device_stats stats;
+ struct iw_spy_data spy_data; /* iwspy support */
+ struct iw_public_data wireless_data;
+
+ enum {
+ HOSTAP_INTERFACE_MASTER,
+ HOSTAP_INTERFACE_MAIN,
+ HOSTAP_INTERFACE_AP,
+ HOSTAP_INTERFACE_STA,
+ HOSTAP_INTERFACE_WDS,
+ } type;
+
+ union {
+ struct hostap_interface_wds {
+ u8 remote_addr[ETH_ALEN];
+ } wds;
+ } u;
+};
+
+
+#define HOSTAP_SKB_TX_DATA_MAGIC 0xf08a36a2
+
+/*
+ * TX meta data - stored in skb->cb buffer, so this must not be increased over
+ * the 40-byte limit
+ */
+struct hostap_skb_tx_data {
+ u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */
+ u8 rate; /* transmit rate */
+#define HOSTAP_TX_FLAGS_WDS BIT(0)
+#define HOSTAP_TX_FLAGS_BUFFERED_FRAME BIT(1)
+#define HOSTAP_TX_FLAGS_ADD_MOREDATA BIT(2)
+ u8 flags; /* HOSTAP_TX_FLAGS_* */
+ u16 tx_cb_idx;
+ struct hostap_interface *iface;
+ unsigned long jiffies; /* queueing timestamp */
+ unsigned short ethertype;
+};
+
+
+#ifndef PRISM2_NO_DEBUG
+
+#define DEBUG_FID BIT(0)
+#define DEBUG_PS BIT(1)
+#define DEBUG_FLOW BIT(2)
+#define DEBUG_AP BIT(3)
+#define DEBUG_HW BIT(4)
+#define DEBUG_EXTRA BIT(5)
+#define DEBUG_EXTRA2 BIT(6)
+#define DEBUG_PS2 BIT(7)
+#define DEBUG_MASK (DEBUG_PS | DEBUG_AP | DEBUG_HW | DEBUG_EXTRA)
+#define PDEBUG(n, args...) \
+do { if ((n) & DEBUG_MASK) printk(KERN_DEBUG args); } while (0)
+#define PDEBUG2(n, args...) \
+do { if ((n) & DEBUG_MASK) printk(args); } while (0)
+
+#else /* PRISM2_NO_DEBUG */
+
+#define PDEBUG(n, args...)
+#define PDEBUG2(n, args...)
+
+#endif /* PRISM2_NO_DEBUG */
+
+enum { BAP0 = 0, BAP1 = 1 };
+
+#define PRISM2_IO_DEBUG_CMD_INB 0
+#define PRISM2_IO_DEBUG_CMD_INW 1
+#define PRISM2_IO_DEBUG_CMD_INSW 2
+#define PRISM2_IO_DEBUG_CMD_OUTB 3
+#define PRISM2_IO_DEBUG_CMD_OUTW 4
+#define PRISM2_IO_DEBUG_CMD_OUTSW 5
+#define PRISM2_IO_DEBUG_CMD_ERROR 6
+#define PRISM2_IO_DEBUG_CMD_INTERRUPT 7
+
+#ifdef PRISM2_IO_DEBUG
+
+#define PRISM2_IO_DEBUG_ENTRY(cmd, reg, value) \
+(((cmd) << 24) | ((reg) << 16) | value)
+
+static inline void prism2_io_debug_add(struct net_device *dev, int cmd,
+ int reg, int value)
+{
+ struct hostap_interface *iface = netdev_priv(dev);
+ local_info_t *local = iface->local;
+
+ if (!local->io_debug_enabled)
+ return;
+
+ local->io_debug[local->io_debug_head] = jiffies & 0xffffffff;
+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE)
+ local->io_debug_head = 0;
+ local->io_debug[local->io_debug_head] =
+ PRISM2_IO_DEBUG_ENTRY(cmd, reg, value);
+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE)
+ local->io_debug_head = 0;
+}
+
+
+static inline void prism2_io_debug_error(struct net_device *dev, int err)
+{
+ struct hostap_interface *iface = netdev_priv(dev);
+ local_info_t *local = iface->local;
+ unsigned long flags;
+
+ if (!local->io_debug_enabled)
+ return;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_ERROR, 0, err);
+ if (local->io_debug_enabled == 1) {
+ local->io_debug_enabled = 0;
+ printk(KERN_DEBUG "%s: I/O debug stopped\n", dev->name);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#else /* PRISM2_IO_DEBUG */
+
+static inline void prism2_io_debug_add(struct net_device *dev, int cmd,
+ int reg, int value)
+{
+}
+
+static inline void prism2_io_debug_error(struct net_device *dev, int err)
+{
+}
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+#ifdef PRISM2_CALLBACK
+enum {
+ /* Called when card is enabled */
+ PRISM2_CALLBACK_ENABLE,
+
+ /* Called when card is disabled */
+ PRISM2_CALLBACK_DISABLE,
+
+ /* Called when RX/TX starts/ends */
+ PRISM2_CALLBACK_RX_START, PRISM2_CALLBACK_RX_END,
+ PRISM2_CALLBACK_TX_START, PRISM2_CALLBACK_TX_END
+};
+void prism2_callback(local_info_t *local, int event);
+#else /* PRISM2_CALLBACK */
+#define prism2_callback(d, e) do { } while (0)
+#endif /* PRISM2_CALLBACK */
+
+#endif /* __KERNEL__ */
+
+#endif /* HOSTAP_WLAN_H */
diff --git a/drivers/net/wireless/ieee802_11.h b/drivers/net/wireless/ieee802_11.h
deleted file mode 100644
index 53dd5248f9f1..000000000000
--- a/drivers/net/wireless/ieee802_11.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _IEEE802_11_H
-#define _IEEE802_11_H
-
-#define IEEE802_11_DATA_LEN 2304
-/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
- 6.2.1.1.2.
-
- The figure in section 7.1.2 suggests a body size of up to 2312
- bytes is allowed, which is a bit confusing, I suspect this
- represents the 2304 bytes of real data, plus a possible 8 bytes of
- WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
-
-
-#define IEEE802_11_HLEN 30
-#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
-
-struct ieee802_11_hdr {
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-/* Frame control field constants */
-#define IEEE802_11_FCTL_VERS 0x0002
-#define IEEE802_11_FCTL_FTYPE 0x000c
-#define IEEE802_11_FCTL_STYPE 0x00f0
-#define IEEE802_11_FCTL_TODS 0x0100
-#define IEEE802_11_FCTL_FROMDS 0x0200
-#define IEEE802_11_FCTL_MOREFRAGS 0x0400
-#define IEEE802_11_FCTL_RETRY 0x0800
-#define IEEE802_11_FCTL_PM 0x1000
-#define IEEE802_11_FCTL_MOREDATA 0x2000
-#define IEEE802_11_FCTL_WEP 0x4000
-#define IEEE802_11_FCTL_ORDER 0x8000
-
-#define IEEE802_11_FTYPE_MGMT 0x0000
-#define IEEE802_11_FTYPE_CTL 0x0004
-#define IEEE802_11_FTYPE_DATA 0x0008
-
-/* management */
-#define IEEE802_11_STYPE_ASSOC_REQ 0x0000
-#define IEEE802_11_STYPE_ASSOC_RESP 0x0010
-#define IEEE802_11_STYPE_REASSOC_REQ 0x0020
-#define IEEE802_11_STYPE_REASSOC_RESP 0x0030
-#define IEEE802_11_STYPE_PROBE_REQ 0x0040
-#define IEEE802_11_STYPE_PROBE_RESP 0x0050
-#define IEEE802_11_STYPE_BEACON 0x0080
-#define IEEE802_11_STYPE_ATIM 0x0090
-#define IEEE802_11_STYPE_DISASSOC 0x00A0
-#define IEEE802_11_STYPE_AUTH 0x00B0
-#define IEEE802_11_STYPE_DEAUTH 0x00C0
-
-/* control */
-#define IEEE802_11_STYPE_PSPOLL 0x00A0
-#define IEEE802_11_STYPE_RTS 0x00B0
-#define IEEE802_11_STYPE_CTS 0x00C0
-#define IEEE802_11_STYPE_ACK 0x00D0
-#define IEEE802_11_STYPE_CFEND 0x00E0
-#define IEEE802_11_STYPE_CFENDACK 0x00F0
-
-/* data */
-#define IEEE802_11_STYPE_DATA 0x0000
-#define IEEE802_11_STYPE_DATA_CFACK 0x0010
-#define IEEE802_11_STYPE_DATA_CFPOLL 0x0020
-#define IEEE802_11_STYPE_DATA_CFACKPOLL 0x0030
-#define IEEE802_11_STYPE_NULLFUNC 0x0040
-#define IEEE802_11_STYPE_CFACK 0x0050
-#define IEEE802_11_STYPE_CFPOLL 0x0060
-#define IEEE802_11_STYPE_CFACKPOLL 0x0070
-
-#define IEEE802_11_SCTL_FRAG 0x000F
-#define IEEE802_11_SCTL_SEQ 0xFFF0
-
-#endif /* _IEEE802_11_H */
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
new file mode 100644
index 000000000000..2414e6493aa5
--- /dev/null
+++ b/drivers/net/wireless/ipw2100.c
@@ -0,0 +1,8680 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ Portions of this file are based on the sample_* files provided by Wireless
+ Extensions 0.26 package and copyright (c) 1997-2003 Jean Tourrilhes
+ <jt@hpl.hp.com>
+
+ Portions of this file are based on the Host AP project,
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and
+ ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c
+ available in the 2.4.25 kernel sources, and are copyright (c) Alan Cox
+
+******************************************************************************/
+/*
+
+ Initial driver on which this is based was developed by Janusz Gorycki,
+ Maciej Urbaniak, and Maciej Sosnowski.
+
+ Promiscuous mode support added by Jacek Wysoczynski and Maciej Urbaniak.
+
+Theory of Operation
+
+Tx - Commands and Data
+
+Firmware and host share a circular queue of Transmit Buffer Descriptors (TBDs)
+Each TBD contains a pointer to the physical (dma_addr_t) address of data being
+sent to the firmware as well as the length of the data.
+
+The host writes to the TBD queue at the WRITE index. The WRITE index points
+to the _next_ packet to be written and is advanced when after the TBD has been
+filled.
+
+The firmware pulls from the TBD queue at the READ index. The READ index points
+to the currently being read entry, and is advanced once the firmware is
+done with a packet.
+
+When data is sent to the firmware, the first TBD is used to indicate to the
+firmware if a Command or Data is being sent. If it is Command, all of the
+command information is contained within the physical address referred to by the
+TBD. If it is Data, the first TBD indicates the type of data packet, number
+of fragments, etc. The next TBD then referrs to the actual packet location.
+
+The Tx flow cycle is as follows:
+
+1) ipw2100_tx() is called by kernel with SKB to transmit
+2) Packet is move from the tx_free_list and appended to the transmit pending
+ list (tx_pend_list)
+3) work is scheduled to move pending packets into the shared circular queue.
+4) when placing packet in the circular queue, the incoming SKB is DMA mapped
+ to a physical address. That address is entered into a TBD. Two TBDs are
+ filled out. The first indicating a data packet, the second referring to the
+ actual payload data.
+5) the packet is removed from tx_pend_list and placed on the end of the
+ firmware pending list (fw_pend_list)
+6) firmware is notified that the WRITE index has
+7) Once the firmware has processed the TBD, INTA is triggered.
+8) For each Tx interrupt received from the firmware, the READ index is checked
+ to see which TBDs are done being processed.
+9) For each TBD that has been processed, the ISR pulls the oldest packet
+ from the fw_pend_list.
+10)The packet structure contained in the fw_pend_list is then used
+ to unmap the DMA address and to free the SKB originally passed to the driver
+ from the kernel.
+11)The packet structure is placed onto the tx_free_list
+
+The above steps are the same for commands, only the msg_free_list/msg_pend_list
+are used instead of tx_free_list/tx_pend_list
+
+...
+
+Critical Sections / Locking :
+
+There are two locks utilized. The first is the low level lock (priv->low_lock)
+that protects the following:
+
+- Access to the Tx/Rx queue lists via priv->low_lock. The lists are as follows:
+
+ tx_free_list : Holds pre-allocated Tx buffers.
+ TAIL modified in __ipw2100_tx_process()
+ HEAD modified in ipw2100_tx()
+
+ tx_pend_list : Holds used Tx buffers waiting to go into the TBD ring
+ TAIL modified ipw2100_tx()
+ HEAD modified by ipw2100_tx_send_data()
+
+ msg_free_list : Holds pre-allocated Msg (Command) buffers
+ TAIL modified in __ipw2100_tx_process()
+ HEAD modified in ipw2100_hw_send_command()
+
+ msg_pend_list : Holds used Msg buffers waiting to go into the TBD ring
+ TAIL modified in ipw2100_hw_send_command()
+ HEAD modified in ipw2100_tx_send_commands()
+
+ The flow of data on the TX side is as follows:
+
+ MSG_FREE_LIST + COMMAND => MSG_PEND_LIST => TBD => MSG_FREE_LIST
+ TX_FREE_LIST + DATA => TX_PEND_LIST => TBD => TX_FREE_LIST
+
+ The methods that work on the TBD ring are protected via priv->low_lock.
+
+- The internal data state of the device itself
+- Access to the firmware read/write indexes for the BD queues
+ and associated logic
+
+All external entry functions are locked with the priv->action_lock to ensure
+that only one external action is invoked at a time.
+
+
+*/
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#define __KERNEL_SYSCALLS__
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/unistd.h>
+#include <linux/stringify.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/time.h>
+#include <linux/firmware.h>
+#include <linux/acpi.h>
+#include <linux/ctype.h>
+
+#include "ipw2100.h"
+
+#define IPW2100_VERSION "1.1.0"
+
+#define DRV_NAME "ipw2100"
+#define DRV_VERSION IPW2100_VERSION
+#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
+
+
+/* Debugging stuff */
+#ifdef CONFIG_IPW_DEBUG
+#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */
+#endif
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static int mode = 0;
+static int channel = 0;
+static int associate = 1;
+static int disable = 0;
+#ifdef CONFIG_PM
+static struct ipw2100_fw ipw2100_firmware;
+#endif
+
+#include <linux/moduleparam.h>
+module_param(debug, int, 0444);
+module_param(mode, int, 0444);
+module_param(channel, int, 0444);
+module_param(associate, int, 0444);
+module_param(disable, int, 0444);
+
+MODULE_PARM_DESC(debug, "debug level");
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
+MODULE_PARM_DESC(channel, "channel");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+
+static u32 ipw2100_debug_level = IPW_DL_NONE;
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_DEBUG(level, message...) \
+do { \
+ if (ipw2100_debug_level & (level)) { \
+ printk(KERN_DEBUG "ipw2100: %c %s ", \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__); \
+ printk(message); \
+ } \
+} while (0)
+#else
+#define IPW_DEBUG(level, message...) do {} while (0)
+#endif /* CONFIG_IPW_DEBUG */
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *command_types[] = {
+ "undefined",
+ "unused", /* HOST_ATTENTION */
+ "HOST_COMPLETE",
+ "unused", /* SLEEP */
+ "unused", /* HOST_POWER_DOWN */
+ "unused",
+ "SYSTEM_CONFIG",
+ "unused", /* SET_IMR */
+ "SSID",
+ "MANDATORY_BSSID",
+ "AUTHENTICATION_TYPE",
+ "ADAPTER_ADDRESS",
+ "PORT_TYPE",
+ "INTERNATIONAL_MODE",
+ "CHANNEL",
+ "RTS_THRESHOLD",
+ "FRAG_THRESHOLD",
+ "POWER_MODE",
+ "TX_RATES",
+ "BASIC_TX_RATES",
+ "WEP_KEY_INFO",
+ "unused",
+ "unused",
+ "unused",
+ "unused",
+ "WEP_KEY_INDEX",
+ "WEP_FLAGS",
+ "ADD_MULTICAST",
+ "CLEAR_ALL_MULTICAST",
+ "BEACON_INTERVAL",
+ "ATIM_WINDOW",
+ "CLEAR_STATISTICS",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "TX_POWER_INDEX",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "BROADCAST_SCAN",
+ "CARD_DISABLE",
+ "PREFERRED_BSSID",
+ "SET_SCAN_OPTIONS",
+ "SCAN_DWELL_TIME",
+ "SWEEP_TABLE",
+ "AP_OR_STATION_TABLE",
+ "GROUP_ORDINALS",
+ "SHORT_RETRY_LIMIT",
+ "LONG_RETRY_LIMIT",
+ "unused", /* SAVE_CALIBRATION */
+ "unused", /* RESTORE_CALIBRATION */
+ "undefined",
+ "undefined",
+ "undefined",
+ "HOST_PRE_POWER_DOWN",
+ "unused", /* HOST_INTERRUPT_COALESCING */
+ "undefined",
+ "CARD_DISABLE_PHY_OFF",
+ "MSDU_TX_RATES"
+ "undefined",
+ "undefined",
+ "SET_STATION_STAT_BITS",
+ "CLEAR_STATIONS_STAT_BITS",
+ "LEAP_ROGUE_MODE",
+ "SET_SECURITY_INFORMATION",
+ "DISASSOCIATION_BSSID",
+ "SET_WPA_ASS_IE"
+};
+#endif
+
+
+/* Pre-decl until we get the code solid and then we can clean it up */
+static void ipw2100_tx_send_commands(struct ipw2100_priv *priv);
+static void ipw2100_tx_send_data(struct ipw2100_priv *priv);
+static int ipw2100_adapter_setup(struct ipw2100_priv *priv);
+
+static void ipw2100_queues_initialize(struct ipw2100_priv *priv);
+static void ipw2100_queues_free(struct ipw2100_priv *priv);
+static int ipw2100_queues_allocate(struct ipw2100_priv *priv);
+
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv);
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev);
+static struct iw_handler_def ipw2100_wx_handler_def;
+
+
+static inline void read_register(struct net_device *dev, u32 reg, u32 *val)
+{
+ *val = readl((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val);
+}
+
+static inline void write_register(struct net_device *dev, u32 reg, u32 val)
+{
+ writel(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val);
+}
+
+static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val)
+{
+ *val = readw((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val);
+}
+
+static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val)
+{
+ *val = readb((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val);
+}
+
+static inline void write_register_word(struct net_device *dev, u32 reg, u16 val)
+{
+ writew(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val);
+}
+
+
+static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val)
+{
+ writeb(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val);
+}
+
+static inline void read_nic_dword(struct net_device *dev, u32 addr, u32 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_dword(struct net_device *dev, u32 addr, u32 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void read_nic_word(struct net_device *dev, u32 addr, u16 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_word(struct net_device *dev, u32 addr, u16 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void read_nic_byte(struct net_device *dev, u32 addr, u8 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_byte(struct net_device *dev, u32 addr, u8 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_auto_inc_address(struct net_device *dev, u32 addr)
+{
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+}
+
+static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val)
+{
+ write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val);
+}
+
+static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
+ const u8 *buf)
+{
+ u32 aligned_addr;
+ u32 aligned_len;
+ u32 dif_len;
+ u32 i;
+
+ /* read first nibble byte by byte */
+ aligned_addr = addr & (~0x3);
+ dif_len = addr - aligned_addr;
+ if (dif_len) {
+ /* Start reading at aligned_addr + dif_len */
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ write_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i,
+ *buf);
+
+ len -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* read DWs through autoincrement registers */
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ aligned_addr);
+ aligned_len = len & (~0x3);
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ write_register(
+ dev, IPW_REG_AUTOINCREMENT_DATA, *(u32 *)buf);
+
+ /* copy the last nibble */
+ dif_len = len - aligned_len;
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ write_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i, *buf);
+}
+
+static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
+ u8 *buf)
+{
+ u32 aligned_addr;
+ u32 aligned_len;
+ u32 dif_len;
+ u32 i;
+
+ /* read first nibble byte by byte */
+ aligned_addr = addr & (~0x3);
+ dif_len = addr - aligned_addr;
+ if (dif_len) {
+ /* Start reading at aligned_addr + dif_len */
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ read_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i, buf);
+
+ len -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* read DWs through autoincrement registers */
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ aligned_addr);
+ aligned_len = len & (~0x3);
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ read_register(dev, IPW_REG_AUTOINCREMENT_DATA,
+ (u32 *)buf);
+
+ /* copy the last nibble */
+ dif_len = len - aligned_len;
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA +
+ i, buf);
+}
+
+static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev)
+{
+ return (dev->base_addr &&
+ (readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
+ == IPW_DATA_DOA_DEBUG_VALUE));
+}
+
+static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord,
+ void *val, u32 *len)
+{
+ struct ipw2100_ordinals *ordinals = &priv->ordinals;
+ u32 addr;
+ u32 field_info;
+ u16 field_len;
+ u16 field_count;
+ u32 total_length;
+
+ if (ordinals->table1_addr == 0) {
+ printk(KERN_WARNING DRV_NAME ": attempt to use fw ordinals "
+ "before they have been loaded.\n");
+ return -EINVAL;
+ }
+
+ if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) {
+ if (*len < IPW_ORD_TAB_1_ENTRY_SIZE) {
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ printk(KERN_WARNING DRV_NAME
+ ": ordinal buffer length too small, need %zd\n",
+ IPW_ORD_TAB_1_ENTRY_SIZE);
+
+ return -EINVAL;
+ }
+
+ read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2),
+ &addr);
+ read_nic_dword(priv->net_dev, addr, val);
+
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ return 0;
+ }
+
+ if (IS_ORDINAL_TABLE_TWO(ordinals, ord)) {
+
+ ord -= IPW_START_ORD_TAB_2;
+
+ /* get the address of statistic */
+ read_nic_dword(priv->net_dev, ordinals->table2_addr + (ord << 3),
+ &addr);
+
+ /* get the second DW of statistics ;
+ * two 16-bit words - first is length, second is count */
+ read_nic_dword(priv->net_dev,
+ ordinals->table2_addr + (ord << 3) + sizeof(u32),
+ &field_info);
+
+ /* get each entry length */
+ field_len = *((u16 *)&field_info);
+
+ /* get number of entries */
+ field_count = *(((u16 *)&field_info) + 1);
+
+ /* abort if no enought memory */
+ total_length = field_len * field_count;
+ if (total_length > *len) {
+ *len = total_length;
+ return -EINVAL;
+ }
+
+ *len = total_length;
+ if (!total_length)
+ return 0;
+
+ /* read the ordinal data from the SRAM */
+ read_nic_memory(priv->net_dev, addr, total_length, val);
+
+ return 0;
+ }
+
+ printk(KERN_WARNING DRV_NAME ": ordinal %d neither in table 1 nor "
+ "in table 2\n", ord);
+
+ return -EINVAL;
+}
+
+static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 *val,
+ u32 *len)
+{
+ struct ipw2100_ordinals *ordinals = &priv->ordinals;
+ u32 addr;
+
+ if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) {
+ if (*len != IPW_ORD_TAB_1_ENTRY_SIZE) {
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+ IPW_DEBUG_INFO("wrong size\n");
+ return -EINVAL;
+ }
+
+ read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2),
+ &addr);
+
+ write_nic_dword(priv->net_dev, addr, *val);
+
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("wrong table\n");
+ if (IS_ORDINAL_TABLE_TWO(ordinals, ord))
+ return -EINVAL;
+
+ return -EINVAL;
+}
+
+static char *snprint_line(char *buf, size_t count,
+ const u8 *data, u32 len, u32 ofs)
+{
+ int out, i, j, l;
+ char c;
+
+ out = snprintf(buf, count, "%08X", ofs);
+
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++)
+ out += snprintf(buf + out, count - out, "%02X ",
+ data[(i * 8 + j)]);
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ out += snprintf(buf + out, count - out, " ");
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++) {
+ c = data[(i * 8 + j)];
+ if (!isascii(c) || !isprint(c))
+ c = '.';
+
+ out += snprintf(buf + out, count - out, "%c", c);
+ }
+
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ return buf;
+}
+
+static void printk_buf(int level, const u8 *data, u32 len)
+{
+ char line[81];
+ u32 ofs = 0;
+ if (!(ipw2100_debug_level & level))
+ return;
+
+ while (len) {
+ printk(KERN_DEBUG "%s\n",
+ snprint_line(line, sizeof(line), &data[ofs],
+ min(len, 16U), ofs));
+ ofs += 16;
+ len -= min(len, 16U);
+ }
+}
+
+
+
+#define MAX_RESET_BACKOFF 10
+
+static inline void schedule_reset(struct ipw2100_priv *priv)
+{
+ unsigned long now = get_seconds();
+
+ /* If we haven't received a reset request within the backoff period,
+ * then we can reset the backoff interval so this reset occurs
+ * immediately */
+ if (priv->reset_backoff &&
+ (now - priv->last_reset > priv->reset_backoff))
+ priv->reset_backoff = 0;
+
+ priv->last_reset = get_seconds();
+
+ if (!(priv->status & STATUS_RESET_PENDING)) {
+ IPW_DEBUG_INFO("%s: Scheduling firmware restart (%ds).\n",
+ priv->net_dev->name, priv->reset_backoff);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ priv->status |= STATUS_RESET_PENDING;
+ if (priv->reset_backoff)
+ queue_delayed_work(priv->workqueue, &priv->reset_work,
+ priv->reset_backoff * HZ);
+ else
+ queue_work(priv->workqueue, &priv->reset_work);
+
+ if (priv->reset_backoff < MAX_RESET_BACKOFF)
+ priv->reset_backoff++;
+
+ wake_up_interruptible(&priv->wait_command_queue);
+ } else
+ IPW_DEBUG_INFO("%s: Firmware restart already in progress.\n",
+ priv->net_dev->name);
+
+}
+
+#define HOST_COMPLETE_TIMEOUT (2 * HZ)
+static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
+ struct host_command * cmd)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ unsigned long flags;
+ int err = 0;
+
+ IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n",
+ command_types[cmd->host_command], cmd->host_command,
+ cmd->host_command_length);
+ printk_buf(IPW_DL_HC, (u8*)cmd->host_command_parameters,
+ cmd->host_command_length);
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->fatal_error) {
+ IPW_DEBUG_INFO("Attempt to send command while hardware in fatal error condition.\n");
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ if (!(priv->status & STATUS_RUNNING)) {
+ IPW_DEBUG_INFO("Attempt to send command while hardware is not running.\n");
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ if (priv->status & STATUS_CMD_ACTIVE) {
+ IPW_DEBUG_INFO("Attempt to send command while another command is pending.\n");
+ err = -EBUSY;
+ goto fail_unlock;
+ }
+
+ if (list_empty(&priv->msg_free_list)) {
+ IPW_DEBUG_INFO("no available msg buffers\n");
+ goto fail_unlock;
+ }
+
+ priv->status |= STATUS_CMD_ACTIVE;
+ priv->messages_sent++;
+
+ element = priv->msg_free_list.next;
+
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+ packet->jiffy_start = jiffies;
+
+ /* initialize the firmware command packet */
+ packet->info.c_struct.cmd->host_command_reg = cmd->host_command;
+ packet->info.c_struct.cmd->host_command_reg1 = cmd->host_command1;
+ packet->info.c_struct.cmd->host_command_len_reg = cmd->host_command_length;
+ packet->info.c_struct.cmd->sequence = cmd->host_command_sequence;
+
+ memcpy(packet->info.c_struct.cmd->host_command_params_reg,
+ cmd->host_command_parameters,
+ sizeof(packet->info.c_struct.cmd->host_command_params_reg));
+
+ list_del(element);
+ DEC_STAT(&priv->msg_free_stat);
+
+ list_add_tail(element, &priv->msg_pend_list);
+ INC_STAT(&priv->msg_pend_stat);
+
+ ipw2100_tx_send_commands(priv);
+ ipw2100_tx_send_data(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ /*
+ * We must wait for this command to complete before another
+ * command can be sent... but if we wait more than 3 seconds
+ * then there is a problem.
+ */
+
+ err = wait_event_interruptible_timeout(
+ priv->wait_command_queue, !(priv->status & STATUS_CMD_ACTIVE),
+ HOST_COMPLETE_TIMEOUT);
+
+ if (err == 0) {
+ IPW_DEBUG_INFO("Command completion failed out after %dms.\n",
+ HOST_COMPLETE_TIMEOUT / (HZ / 100));
+ priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT;
+ priv->status &= ~STATUS_CMD_ACTIVE;
+ schedule_reset(priv);
+ return -EIO;
+ }
+
+ if (priv->fatal_error) {
+ printk(KERN_WARNING DRV_NAME ": %s: firmware fatal error\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* !!!!! HACK TEST !!!!!
+ * When lots of debug trace statements are enabled, the driver
+ * doesn't seem to have as many firmware restart cycles...
+ *
+ * As a test, we're sticking in a 1/100s delay here */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ / 100);
+
+ return 0;
+
+ fail_unlock:
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ return err;
+}
+
+
+/*
+ * Verify the values and data access of the hardware
+ * No locks needed or used. No functions called.
+ */
+static int ipw2100_verify(struct ipw2100_priv *priv)
+{
+ u32 data1, data2;
+ u32 address;
+
+ u32 val1 = 0x76543210;
+ u32 val2 = 0xFEDCBA98;
+
+ /* Domain 0 check - all values should be DOA_DEBUG */
+ for (address = IPW_REG_DOA_DEBUG_AREA_START;
+ address < IPW_REG_DOA_DEBUG_AREA_END;
+ address += sizeof(u32)) {
+ read_register(priv->net_dev, address, &data1);
+ if (data1 != IPW_DATA_DOA_DEBUG_VALUE)
+ return -EIO;
+ }
+
+ /* Domain 1 check - use arbitrary read/write compare */
+ for (address = 0; address < 5; address++) {
+ /* The memory area is not used now */
+ write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32,
+ val1);
+ write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36,
+ val2);
+ read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32,
+ &data1);
+ read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36,
+ &data2);
+ if (val1 == data1 && val2 == data2)
+ return 0;
+ }
+
+ return -EIO;
+}
+
+/*
+ *
+ * Loop until the CARD_DISABLED bit is the same value as the
+ * supplied parameter
+ *
+ * TODO: See if it would be more efficient to do a wait/wake
+ * cycle and have the completion event trigger the wakeup
+ *
+ */
+#define IPW_CARD_DISABLE_COMPLETE_WAIT 100 // 100 milli
+static int ipw2100_wait_for_card_state(struct ipw2100_priv *priv, int state)
+{
+ int i;
+ u32 card_state;
+ u32 len = sizeof(card_state);
+ int err;
+
+ for (i = 0; i <= IPW_CARD_DISABLE_COMPLETE_WAIT * 1000; i += 50) {
+ err = ipw2100_get_ordinal(priv, IPW_ORD_CARD_DISABLED,
+ &card_state, &len);
+ if (err) {
+ IPW_DEBUG_INFO("Query of CARD_DISABLED ordinal "
+ "failed.\n");
+ return 0;
+ }
+
+ /* We'll break out if either the HW state says it is
+ * in the state we want, or if HOST_COMPLETE command
+ * finishes */
+ if ((card_state == state) ||
+ ((priv->status & STATUS_ENABLED) ?
+ IPW_HW_STATE_ENABLED : IPW_HW_STATE_DISABLED) == state) {
+ if (state == IPW_HW_STATE_ENABLED)
+ priv->status |= STATUS_ENABLED;
+ else
+ priv->status &= ~STATUS_ENABLED;
+
+ return 0;
+ }
+
+ udelay(50);
+ }
+
+ IPW_DEBUG_INFO("ipw2100_wait_for_card_state to %s state timed out\n",
+ state ? "DISABLED" : "ENABLED");
+ return -EIO;
+}
+
+
+/*********************************************************************
+ Procedure : sw_reset_and_clock
+ Purpose : Asserts s/w reset, asserts clock initialization
+ and waits for clock stabilization
+ ********************************************************************/
+static int sw_reset_and_clock(struct ipw2100_priv *priv)
+{
+ int i;
+ u32 r;
+
+ // assert s/w reset
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+ // wait for clock stabilization
+ for (i = 0; i < 1000; i++) {
+ udelay(IPW_WAIT_RESET_ARC_COMPLETE_DELAY);
+
+ // check clock ready bit
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &r);
+ if (r & IPW_AUX_HOST_RESET_REG_PRINCETON_RESET)
+ break;
+ }
+
+ if (i == 1000)
+ return -EIO; // TODO: better error value
+
+ /* set "initialization complete" bit to move adapter to
+ * D0 state */
+ write_register(priv->net_dev, IPW_REG_GP_CNTRL,
+ IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE);
+
+ /* wait for clock stabilization */
+ for (i = 0; i < 10000; i++) {
+ udelay(IPW_WAIT_CLOCK_STABILIZATION_DELAY * 4);
+
+ /* check clock ready bit */
+ read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r);
+ if (r & IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY)
+ break;
+ }
+
+ if (i == 10000)
+ return -EIO; /* TODO: better error value */
+
+ /* set D0 standby bit */
+ read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r);
+ write_register(priv->net_dev, IPW_REG_GP_CNTRL,
+ r | IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY);
+
+ return 0;
+}
+
+/*********************************************************************
+ Procedure : ipw2100_download_firmware
+ Purpose : Initiaze adapter after power on.
+ The sequence is:
+ 1. assert s/w reset first!
+ 2. awake clocks & wait for clock stabilization
+ 3. hold ARC (don't ask me why...)
+ 4. load Dino ucode and reset/clock init again
+ 5. zero-out shared mem
+ 6. download f/w
+ *******************************************************************/
+static int ipw2100_download_firmware(struct ipw2100_priv *priv)
+{
+ u32 address;
+ int err;
+
+#ifndef CONFIG_PM
+ /* Fetch the firmware and microcode */
+ struct ipw2100_fw ipw2100_firmware;
+#endif
+
+ if (priv->fatal_error) {
+ IPW_DEBUG_ERROR("%s: ipw2100_download_firmware called after "
+ "fatal error %d. Interface must be brought down.\n",
+ priv->net_dev->name, priv->fatal_error);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_PM
+ if (!ipw2100_firmware.version) {
+ err = ipw2100_get_firmware(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",
+ priv->net_dev->name, err);
+ priv->fatal_error = IPW2100_ERR_FW_LOAD;
+ goto fail;
+ }
+ }
+#else
+ err = ipw2100_get_firmware(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",
+ priv->net_dev->name, err);
+ priv->fatal_error = IPW2100_ERR_FW_LOAD;
+ goto fail;
+ }
+#endif
+ priv->firmware_version = ipw2100_firmware.version;
+
+ /* s/w reset and clock stabilization */
+ err = sw_reset_and_clock(priv);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: sw_reset_and_clock failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ err = ipw2100_verify(priv);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_verify failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* Hold ARC */
+ write_nic_dword(priv->net_dev,
+ IPW_INTERNAL_REGISTER_HALT_AND_RESET,
+ 0x80000000);
+
+ /* allow ARC to run */
+ write_register(priv->net_dev, IPW_REG_RESET_REG, 0);
+
+ /* load microcode */
+ err = ipw2100_ucode_download(priv, &ipw2100_firmware);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Error loading microcode: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* release ARC */
+ write_nic_dword(priv->net_dev,
+ IPW_INTERNAL_REGISTER_HALT_AND_RESET,
+ 0x00000000);
+
+ /* s/w reset and clock stabilization (again!!!) */
+ err = sw_reset_and_clock(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: sw_reset_and_clock failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* load f/w */
+ err = ipw2100_fw_download(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: Error loading firmware: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+#ifndef CONFIG_PM
+ /*
+ * When the .resume method of the driver is called, the other
+ * part of the system, i.e. the ide driver could still stay in
+ * the suspend stage. This prevents us from loading the firmware
+ * from the disk. --YZ
+ */
+
+ /* free any storage allocated for firmware image */
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+#endif
+
+ /* zero out Domain 1 area indirectly (Si requirement) */
+ for (address = IPW_HOST_FW_SHARED_AREA0;
+ address < IPW_HOST_FW_SHARED_AREA0_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA1;
+ address < IPW_HOST_FW_SHARED_AREA1_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA2;
+ address < IPW_HOST_FW_SHARED_AREA2_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA3;
+ address < IPW_HOST_FW_SHARED_AREA3_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_INTERRUPT_AREA;
+ address < IPW_HOST_FW_INTERRUPT_AREA_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+
+ return 0;
+
+ fail:
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+ return err;
+}
+
+static inline void ipw2100_enable_interrupts(struct ipw2100_priv *priv)
+{
+ if (priv->status & STATUS_INT_ENABLED)
+ return;
+ priv->status |= STATUS_INT_ENABLED;
+ write_register(priv->net_dev, IPW_REG_INTA_MASK, IPW_INTERRUPT_MASK);
+}
+
+static inline void ipw2100_disable_interrupts(struct ipw2100_priv *priv)
+{
+ if (!(priv->status & STATUS_INT_ENABLED))
+ return;
+ priv->status &= ~STATUS_INT_ENABLED;
+ write_register(priv->net_dev, IPW_REG_INTA_MASK, 0x0);
+}
+
+
+static void ipw2100_initialize_ordinals(struct ipw2100_priv *priv)
+{
+ struct ipw2100_ordinals *ord = &priv->ordinals;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1,
+ &ord->table1_addr);
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2,
+ &ord->table2_addr);
+
+ read_nic_dword(priv->net_dev, ord->table1_addr, &ord->table1_size);
+ read_nic_dword(priv->net_dev, ord->table2_addr, &ord->table2_size);
+
+ ord->table2_size &= 0x0000FFFF;
+
+ IPW_DEBUG_INFO("table 1 size: %d\n", ord->table1_size);
+ IPW_DEBUG_INFO("table 2 size: %d\n", ord->table2_size);
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv)
+{
+ u32 reg = 0;
+ /*
+ * Set GPIO 3 writable by FW; GPIO 1 writable
+ * by driver and enable clock
+ */
+ reg = (IPW_BIT_GPIO_GPIO3_MASK | IPW_BIT_GPIO_GPIO1_ENABLE |
+ IPW_BIT_GPIO_LED_OFF);
+ write_register(priv->net_dev, IPW_REG_GPIO, reg);
+}
+
+static inline int rf_kill_active(struct ipw2100_priv *priv)
+{
+#define MAX_RF_KILL_CHECKS 5
+#define RF_KILL_CHECK_DELAY 40
+
+ unsigned short value = 0;
+ u32 reg = 0;
+ int i;
+
+ if (!(priv->hw_features & HW_FEATURE_RFKILL)) {
+ priv->status &= ~STATUS_RF_KILL_HW;
+ return 0;
+ }
+
+ for (i = 0; i < MAX_RF_KILL_CHECKS; i++) {
+ udelay(RF_KILL_CHECK_DELAY);
+ read_register(priv->net_dev, IPW_REG_GPIO, &reg);
+ value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);
+ }
+
+ if (value == 0)
+ priv->status |= STATUS_RF_KILL_HW;
+ else
+ priv->status &= ~STATUS_RF_KILL_HW;
+
+ return (value == 0);
+}
+
+static int ipw2100_get_hw_features(struct ipw2100_priv *priv)
+{
+ u32 addr, len;
+ u32 val;
+
+ /*
+ * EEPROM_SRAM_DB_START_ADDRESS using ordinal in ordinal table 1
+ */
+ len = sizeof(addr);
+ if (ipw2100_get_ordinal(
+ priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS,
+ &addr, &len)) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return -EIO;
+ }
+
+ IPW_DEBUG_INFO("EEPROM address: %08X\n", addr);
+
+ /*
+ * EEPROM version is the byte at offset 0xfd in firmware
+ * We read 4 bytes, then shift out the byte we actually want */
+ read_nic_dword(priv->net_dev, addr + 0xFC, &val);
+ priv->eeprom_version = (val >> 24) & 0xFF;
+ IPW_DEBUG_INFO("EEPROM version: %d\n", priv->eeprom_version);
+
+ /*
+ * HW RF Kill enable is bit 0 in byte at offset 0x21 in firmware
+ *
+ * notice that the EEPROM bit is reverse polarity, i.e.
+ * bit = 0 signifies HW RF kill switch is supported
+ * bit = 1 signifies HW RF kill switch is NOT supported
+ */
+ read_nic_dword(priv->net_dev, addr + 0x20, &val);
+ if (!((val >> 24) & 0x01))
+ priv->hw_features |= HW_FEATURE_RFKILL;
+
+ IPW_DEBUG_INFO("HW RF Kill: %ssupported.\n",
+ (priv->hw_features & HW_FEATURE_RFKILL) ?
+ "" : "not ");
+
+ return 0;
+}
+
+/*
+ * Start firmware execution after power on and intialization
+ * The sequence is:
+ * 1. Release ARC
+ * 2. Wait for f/w initialization completes;
+ */
+static int ipw2100_start_adapter(struct ipw2100_priv *priv)
+{
+ int i;
+ u32 inta, inta_mask, gpio;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->status & STATUS_RUNNING)
+ return 0;
+
+ /*
+ * Initialize the hw - drive adapter to DO state by setting
+ * init_done bit. Wait for clk_ready bit and Download
+ * fw & dino ucode
+ */
+ if (ipw2100_download_firmware(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to power on the adapter.\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* Clear the Tx, Rx and Msg queues and the r/w indexes
+ * in the firmware RBD and TBD ring queue */
+ ipw2100_queues_initialize(priv);
+
+ ipw2100_hw_set_gpio(priv);
+
+ /* TODO -- Look at disabling interrupts here to make sure none
+ * get fired during FW initialization */
+
+ /* Release ARC - clear reset bit */
+ write_register(priv->net_dev, IPW_REG_RESET_REG, 0);
+
+ /* wait for f/w intialization complete */
+ IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
+ i = 5000;
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(40 * HZ / 1000);
+ /* Todo... wait for sync command ... */
+
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+
+ /* check "init done" bit */
+ if (inta & IPW2100_INTA_FW_INIT_DONE) {
+ /* reset "init done" bit */
+ write_register(priv->net_dev, IPW_REG_INTA,
+ IPW2100_INTA_FW_INIT_DONE);
+ break;
+ }
+
+ /* check error conditions : we check these after the firmware
+ * check so that if there is an error, the interrupt handler
+ * will see it and the adapter will be reset */
+ if (inta &
+ (IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR)) {
+ /* clear error conditions */
+ write_register(priv->net_dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR);
+ }
+ } while (i--);
+
+ /* Clear out any pending INTAs since we aren't supposed to have
+ * interrupts enabled at this point... */
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+ read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask);
+ inta &= IPW_INTERRUPT_MASK;
+ /* Clear out any pending interrupts */
+ if (inta & inta_mask)
+ write_register(priv->net_dev, IPW_REG_INTA, inta);
+
+ IPW_DEBUG_FW("f/w initialization complete: %s\n",
+ i ? "SUCCESS" : "FAILED");
+
+ if (!i) {
+ printk(KERN_WARNING DRV_NAME ": %s: Firmware did not initialize.\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* allow firmware to write to GPIO1 & GPIO3 */
+ read_register(priv->net_dev, IPW_REG_GPIO, &gpio);
+
+ gpio |= (IPW_BIT_GPIO_GPIO1_MASK | IPW_BIT_GPIO_GPIO3_MASK);
+
+ write_register(priv->net_dev, IPW_REG_GPIO, gpio);
+
+ /* Ready to receive commands */
+ priv->status |= STATUS_RUNNING;
+
+ /* The adapter has been reset; we are not associated */
+ priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static inline void ipw2100_reset_fatalerror(struct ipw2100_priv *priv)
+{
+ if (!priv->fatal_error)
+ return;
+
+ priv->fatal_errors[priv->fatal_index++] = priv->fatal_error;
+ priv->fatal_index %= IPW2100_ERROR_QUEUE;
+ priv->fatal_error = 0;
+}
+
+
+/* NOTE: Our interrupt is disabled when this method is called */
+static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
+{
+ u32 reg;
+ int i;
+
+ IPW_DEBUG_INFO("Power cycling the hardware.\n");
+
+ ipw2100_hw_set_gpio(priv);
+
+ /* Step 1. Stop Master Assert */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+
+ /* Step 2. Wait for stop Master Assert
+ * (not more then 50us, otherwise ret error */
+ i = 5;
+ do {
+ udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ } while(i--);
+
+ priv->status &= ~STATUS_RESET_PENDING;
+
+ if (!i) {
+ IPW_DEBUG_INFO("exit - waited too long for master assert stop\n");
+ return -EIO;
+ }
+
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+
+ /* Reset any fatal_error conditions */
+ ipw2100_reset_fatalerror(priv);
+
+ /* At this point, the adapter is now stopped and disabled */
+ priv->status &= ~(STATUS_RUNNING | STATUS_ASSOCIATING |
+ STATUS_ASSOCIATED | STATUS_ENABLED);
+
+ return 0;
+}
+
+/*
+ * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it
+ *
+ * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent.
+ *
+ * STATUS_CARD_DISABLE_NOTIFICATION will be sent regardless of
+ * if STATUS_ASSN_LOST is sent.
+ */
+static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
+{
+
+#define HW_PHY_OFF_LOOP_DELAY (HZ / 5000)
+
+ struct host_command cmd = {
+ .host_command = CARD_DISABLE_PHY_OFF,
+ .host_command_sequence = 0,
+ .host_command_length = 0,
+ };
+ int err, i;
+ u32 val1, val2;
+
+ IPW_DEBUG_HC("CARD_DISABLE_PHY_OFF\n");
+
+ /* Turn off the radio */
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ for (i = 0; i < 2500; i++) {
+ read_nic_dword(priv->net_dev, IPW2100_CONTROL_REG, &val1);
+ read_nic_dword(priv->net_dev, IPW2100_COMMAND, &val2);
+
+ if ((val1 & IPW2100_CONTROL_PHY_OFF) &&
+ (val2 & IPW2100_COMMAND_PHY_OFF))
+ return 0;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
+ }
+
+ return -EIO;
+}
+
+
+static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = HOST_COMPLETE,
+ .host_command_sequence = 0,
+ .host_command_length = 0
+ };
+ int err = 0;
+
+ IPW_DEBUG_HC("HOST_COMPLETE\n");
+
+ if (priv->status & STATUS_ENABLED)
+ return 0;
+
+ down(&priv->adapter_sem);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_HC("Command aborted due to RF kill active.\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ IPW_DEBUG_INFO("Failed to send HOST_COMPLETE command\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_ENABLED);
+ if (err) {
+ IPW_DEBUG_INFO(
+ "%s: card not responding to init command.\n",
+ priv->net_dev->name);
+ goto fail_up;
+ }
+
+ if (priv->stop_hang_check) {
+ priv->stop_hang_check = 0;
+ queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+ }
+
+fail_up:
+ up(&priv->adapter_sem);
+ return err;
+}
+
+static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
+{
+#define HW_POWER_DOWN_DELAY (HZ / 10)
+
+ struct host_command cmd = {
+ .host_command = HOST_PRE_POWER_DOWN,
+ .host_command_sequence = 0,
+ .host_command_length = 0,
+ };
+ int err, i;
+ u32 reg;
+
+ if (!(priv->status & STATUS_RUNNING))
+ return 0;
+
+ priv->status |= STATUS_STOPPING;
+
+ /* We can only shut down the card if the firmware is operational. So,
+ * if we haven't reset since a fatal_error, then we can not send the
+ * shutdown commands. */
+ if (!priv->fatal_error) {
+ /* First, make sure the adapter is enabled so that the PHY_OFF
+ * command can shut it down */
+ ipw2100_enable_adapter(priv);
+
+ err = ipw2100_hw_phy_off(priv);
+ if (err)
+ printk(KERN_WARNING DRV_NAME ": Error disabling radio %d\n", err);
+
+ /*
+ * If in D0-standby mode going directly to D3 may cause a
+ * PCI bus violation. Therefore we must change out of the D0
+ * state.
+ *
+ * Sending the PREPARE_FOR_POWER_DOWN will restrict the
+ * hardware from going into standby mode and will transition
+ * out of D0-standy if it is already in that state.
+ *
+ * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the
+ * driver upon completion. Once received, the driver can
+ * proceed to the D3 state.
+ *
+ * Prepare for power down command to fw. This command would
+ * take HW out of D0-standby and prepare it for D3 state.
+ *
+ * Currently FW does not support event notification for this
+ * event. Therefore, skip waiting for it. Just wait a fixed
+ * 100ms
+ */
+ IPW_DEBUG_HC("HOST_PRE_POWER_DOWN\n");
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Power down command failed: Error %d\n",
+ priv->net_dev->name, err);
+ else {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HW_POWER_DOWN_DELAY);
+ }
+ }
+
+ priv->status &= ~STATUS_ENABLED;
+
+ /*
+ * Set GPIO 3 writable by FW; GPIO 1 writable
+ * by driver and enable clock
+ */
+ ipw2100_hw_set_gpio(priv);
+
+ /*
+ * Power down adapter. Sequence:
+ * 1. Stop master assert (RESET_REG[9]=1)
+ * 2. Wait for stop master (RESET_REG[8]==1)
+ * 3. S/w reset assert (RESET_REG[7] = 1)
+ */
+
+ /* Stop master assert */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+
+ /* wait stop master not more than 50 usec.
+ * Otherwise return error. */
+ for (i = 5; i > 0; i--) {
+ udelay(10);
+
+ /* Check master stop bit */
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ }
+
+ if (i == 0)
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Could now power down adapter.\n",
+ priv->net_dev->name);
+
+ /* assert s/w reset */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+ priv->status &= ~(STATUS_RUNNING | STATUS_STOPPING);
+
+ return 0;
+}
+
+
+static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = CARD_DISABLE,
+ .host_command_sequence = 0,
+ .host_command_length = 0
+ };
+ int err = 0;
+
+ IPW_DEBUG_HC("CARD_DISABLE\n");
+
+ if (!(priv->status & STATUS_ENABLED))
+ return 0;
+
+ /* Make sure we clear the associated state */
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+
+ if (!priv->stop_hang_check) {
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+ }
+
+ down(&priv->adapter_sem);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": exit - failed to send CARD_DISABLE command\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_DISABLED);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": exit - card failed to change to DISABLED\n");
+ goto fail_up;
+ }
+
+ IPW_DEBUG_INFO("TODO: implement scan state machine\n");
+
+fail_up:
+ up(&priv->adapter_sem);
+ return err;
+}
+
+static int ipw2100_set_scan_options(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = SET_SCAN_OPTIONS,
+ .host_command_sequence = 0,
+ .host_command_length = 8
+ };
+ int err;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ IPW_DEBUG_SCAN("setting scan options\n");
+
+ cmd.host_command_parameters[0] = 0;
+
+ if (!(priv->config & CFG_ASSOCIATE))
+ cmd.host_command_parameters[0] |= IPW_SCAN_NOASSOCIATE;
+ if ((priv->sec.flags & SEC_ENABLED) && priv->sec.enabled)
+ cmd.host_command_parameters[0] |= IPW_SCAN_MIXED_CELL;
+ if (priv->config & CFG_PASSIVE_SCAN)
+ cmd.host_command_parameters[0] |= IPW_SCAN_PASSIVE;
+
+ cmd.host_command_parameters[1] = priv->channel_mask;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ IPW_DEBUG_HC("SET_SCAN_OPTIONS 0x%04X\n",
+ cmd.host_command_parameters[0]);
+
+ return err;
+}
+
+static int ipw2100_start_scan(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = BROADCAST_SCAN,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ IPW_DEBUG_HC("START_SCAN\n");
+
+ cmd.host_command_parameters[0] = 0;
+
+ /* No scanning if in monitor mode */
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ return 1;
+
+ if (priv->status & STATUS_SCANNING) {
+ IPW_DEBUG_SCAN("Scan requested while already in scan...\n");
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("enter\n");
+
+ /* Not clearing here; doing so makes iwlist always return nothing...
+ *
+ * We should modify the table logic to use aging tables vs. clearing
+ * the table on each scan start.
+ */
+ IPW_DEBUG_SCAN("starting scan\n");
+
+ priv->status |= STATUS_SCANNING;
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ priv->status &= ~STATUS_SCANNING;
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return err;
+}
+
+static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
+{
+ unsigned long flags;
+ int rc = 0;
+ u32 lock;
+ u32 ord_len = sizeof(lock);
+
+ /* Quite if manually disabled. */
+ if (priv->status & STATUS_RF_KILL_SW) {
+ IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable "
+ "switch\n", priv->net_dev->name);
+ return 0;
+ }
+
+ /* If the interrupt is enabled, turn it off... */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+
+ /* Reset any fatal_error conditions */
+ ipw2100_reset_fatalerror(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ if (priv->status & STATUS_POWERED ||
+ (priv->status & STATUS_RESET_PENDING)) {
+ /* Power cycle the card ... */
+ if (ipw2100_power_cycle_adapter(priv)) {
+ printk(KERN_WARNING DRV_NAME ": %s: Could not cycle adapter.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+ } else
+ priv->status |= STATUS_POWERED;
+
+ /* Load the firmware, start the clocks, etc. */
+ if (ipw2100_start_adapter(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to start the firmware.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ ipw2100_initialize_ordinals(priv);
+
+ /* Determine capabilities of this particular HW configuration */
+ if (ipw2100_get_hw_features(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to determine HW features.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ lock = LOCK_NONE;
+ if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to clear ordinal lock.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ priv->status &= ~STATUS_SCANNING;
+
+ if (rf_kill_active(priv)) {
+ printk(KERN_INFO "%s: Radio is disabled by RF switch.\n",
+ priv->net_dev->name);
+
+ if (priv->stop_rf_kill) {
+ priv->stop_rf_kill = 0;
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ }
+
+ deferred = 1;
+ }
+
+ /* Turn on the interrupt so that commands can be processed */
+ ipw2100_enable_interrupts(priv);
+
+ /* Send all of the commands that must be sent prior to
+ * HOST_COMPLETE */
+ if (ipw2100_adapter_setup(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to start the card.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ if (!deferred) {
+ /* Enable the adapter - sends HOST_COMPLETE */
+ if (ipw2100_enable_adapter(priv)) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: failed in call to enable adapter.\n",
+ priv->net_dev->name);
+ ipw2100_hw_stop_adapter(priv);
+ rc = 1;
+ goto exit;
+ }
+
+
+ /* Start a scan . . . */
+ ipw2100_set_scan_options(priv);
+ ipw2100_start_scan(priv);
+ }
+
+ exit:
+ return rc;
+}
+
+/* Called by register_netdev() */
+static int ipw2100_net_init(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ipw2100_up(priv, 1);
+}
+
+static void ipw2100_down(struct ipw2100_priv *priv)
+{
+ unsigned long flags;
+ union iwreq_data wrqu = {
+ .ap_addr = {
+ .sa_family = ARPHRD_ETHER
+ }
+ };
+ int associated = priv->status & STATUS_ASSOCIATED;
+
+ /* Kill the RF switch timer */
+ if (!priv->stop_rf_kill) {
+ priv->stop_rf_kill = 1;
+ cancel_delayed_work(&priv->rf_kill);
+ }
+
+ /* Kill the firmare hang check timer */
+ if (!priv->stop_hang_check) {
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+ }
+
+ /* Kill any pending resets */
+ if (priv->status & STATUS_RESET_PENDING)
+ cancel_delayed_work(&priv->reset_work);
+
+ /* Make sure the interrupt is on so that FW commands will be
+ * processed correctly */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_enable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ if (ipw2100_hw_stop_adapter(priv))
+ printk(KERN_ERR DRV_NAME ": %s: Error stopping adapter.\n",
+ priv->net_dev->name);
+
+ /* Do not disable the interrupt until _after_ we disable
+ * the adaptor. Otherwise the CARD_DISABLE command will never
+ * be ack'd by the firmware */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ if (priv->config & CFG_C3_DISABLED) {
+ IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n");
+ acpi_set_cstate_limit(priv->cstate_limit);
+ priv->config &= ~CFG_C3_DISABLED;
+ }
+#endif
+
+ /* We have to signal any supplicant if we are disassociating */
+ if (associated)
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+}
+
+static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
+{
+ unsigned long flags;
+ union iwreq_data wrqu = {
+ .ap_addr = {
+ .sa_family = ARPHRD_ETHER
+ }
+ };
+ int associated = priv->status & STATUS_ASSOCIATED;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ IPW_DEBUG_INFO(DRV_NAME ": %s: Restarting adapter.\n",
+ priv->net_dev->name);
+ priv->resets++;
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+ priv->status |= STATUS_SECURITY_UPDATED;
+
+ /* Force a power cycle even if interface hasn't been opened
+ * yet */
+ cancel_delayed_work(&priv->reset_work);
+ priv->status |= STATUS_RESET_PENDING;
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ down(&priv->action_sem);
+ /* stop timed checks so that they don't interfere with reset */
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+
+ /* We have to signal any supplicant if we are disassociating */
+ if (associated)
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ ipw2100_up(priv, 0);
+ up(&priv->action_sem);
+
+}
+
+
+static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
+{
+
+#define MAC_ASSOCIATION_READ_DELAY (HZ)
+ int ret, len, essid_len;
+ char essid[IW_ESSID_MAX_SIZE];
+ u32 txrate;
+ u32 chan;
+ char *txratename;
+ u8 bssid[ETH_ALEN];
+
+ /*
+ * TBD: BSSID is usually 00:00:00:00:00:00 here and not
+ * an actual MAC of the AP. Seems like FW sets this
+ * address too late. Read it later and expose through
+ * /proc or schedule a later task to query and update
+ */
+
+ essid_len = IW_ESSID_MAX_SIZE;
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID,
+ essid, &essid_len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+
+ len = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE,
+ &txrate, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+
+ len = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+ len = ETH_ALEN;
+ ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+ memcpy(priv->ieee->bssid, bssid, ETH_ALEN);
+
+
+ switch (txrate) {
+ case TX_RATE_1_MBIT:
+ txratename = "1Mbps";
+ break;
+ case TX_RATE_2_MBIT:
+ txratename = "2Mbsp";
+ break;
+ case TX_RATE_5_5_MBIT:
+ txratename = "5.5Mbps";
+ break;
+ case TX_RATE_11_MBIT:
+ txratename = "11Mbps";
+ break;
+ default:
+ IPW_DEBUG_INFO("Unknown rate: %d\n", txrate);
+ txratename = "unknown rate";
+ break;
+ }
+
+ IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="
+ MAC_FMT ")\n",
+ priv->net_dev->name, escape_essid(essid, essid_len),
+ txratename, chan, MAC_ARG(bssid));
+
+ /* now we copy read ssid into dev */
+ if (!(priv->config & CFG_STATIC_ESSID)) {
+ priv->essid_len = min((u8)essid_len, (u8)IW_ESSID_MAX_SIZE);
+ memcpy(priv->essid, essid, priv->essid_len);
+ }
+ priv->channel = chan;
+ memcpy(priv->bssid, bssid, ETH_ALEN);
+
+ priv->status |= STATUS_ASSOCIATING;
+ priv->connect_start = get_seconds();
+
+ queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10);
+}
+
+
+static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
+ int length, int batch_mode)
+{
+ int ssid_len = min(length, IW_ESSID_MAX_SIZE);
+ struct host_command cmd = {
+ .host_command = SSID,
+ .host_command_sequence = 0,
+ .host_command_length = ssid_len
+ };
+ int err;
+
+ IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len));
+
+ if (ssid_len)
+ memcpy((char*)cmd.host_command_parameters,
+ essid, ssid_len);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ /* Bug in FW currently doesn't honor bit 0 in SET_SCAN_OPTIONS to
+ * disable auto association -- so we cheat by setting a bogus SSID */
+ if (!ssid_len && !(priv->config & CFG_ASSOCIATE)) {
+ int i;
+ u8 *bogus = (u8*)cmd.host_command_parameters;
+ for (i = 0; i < IW_ESSID_MAX_SIZE; i++)
+ bogus[i] = 0x18 + i;
+ cmd.host_command_length = IW_ESSID_MAX_SIZE;
+ }
+
+ /* NOTE: We always send the SSID command even if the provided ESSID is
+ * the same as what we currently think is set. */
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (!err) {
+ memset(priv->essid + ssid_len, 0,
+ IW_ESSID_MAX_SIZE - ssid_len);
+ memcpy(priv->essid, essid, ssid_len);
+ priv->essid_len = ssid_len;
+ }
+
+ if (!batch_mode) {
+ if (ipw2100_enable_adapter(priv))
+ err = -EIO;
+ }
+
+ return err;
+}
+
+static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
+ "disassociated: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid, priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+
+ if (priv->status & STATUS_STOPPING) {
+ IPW_DEBUG_INFO("Card is stopping itself, discard ASSN_LOST.\n");
+ return;
+ }
+
+ memset(priv->bssid, 0, ETH_ALEN);
+ memset(priv->ieee->bssid, 0, ETH_ALEN);
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+
+ if (!(priv->status & STATUS_RUNNING))
+ return;
+
+ if (priv->status & STATUS_SECURITY_UPDATED)
+ queue_work(priv->workqueue, &priv->security_work);
+
+ queue_work(priv->workqueue, &priv->wx_event_work);
+}
+
+static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_INFO("%s: RF Kill state changed to radio OFF.\n",
+ priv->net_dev->name);
+
+ /* RF_KILL is now enabled (else we wouldn't be here) */
+ priv->status |= STATUS_RF_KILL_HW;
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ if (priv->config & CFG_C3_DISABLED) {
+ IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n");
+ acpi_set_cstate_limit(priv->cstate_limit);
+ priv->config &= ~CFG_C3_DISABLED;
+ }
+#endif
+
+ /* Make sure the RF Kill check timer is running */
+ priv->stop_rf_kill = 0;
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+}
+
+static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_SCAN("scan complete\n");
+ /* Age the scan results... */
+ priv->ieee->scans++;
+ priv->status &= ~STATUS_SCANNING;
+}
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW2100_HANDLER(v, f) { v, f, # v }
+struct ipw2100_status_indicator {
+ int status;
+ void (*cb)(struct ipw2100_priv *priv, u32 status);
+ char *name;
+};
+#else
+#define IPW2100_HANDLER(v, f) { v, f }
+struct ipw2100_status_indicator {
+ int status;
+ void (*cb)(struct ipw2100_priv *priv, u32 status);
+};
+#endif /* CONFIG_IPW_DEBUG */
+
+static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_SCAN("Scanning...\n");
+ priv->status |= STATUS_SCANNING;
+}
+
+static const struct ipw2100_status_indicator status_handlers[] = {
+ IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL),
+ IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL),
+ IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),
+ IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost),
+ IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL),
+ IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete),
+ IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL),
+ IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL),
+ IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill),
+ IPW2100_HANDLER(IPW_STATE_DISABLED, NULL),
+ IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL),
+ IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning),
+ IPW2100_HANDLER(-1, NULL)
+};
+
+
+static void isr_status_change(struct ipw2100_priv *priv, int status)
+{
+ int i;
+
+ if (status == IPW_STATE_SCANNING &&
+ priv->status & STATUS_ASSOCIATED &&
+ !(priv->status & STATUS_SCANNING)) {
+ IPW_DEBUG_INFO("Scan detected while associated, with "
+ "no scan request. Restarting firmware.\n");
+
+ /* Wake up any sleeping jobs */
+ schedule_reset(priv);
+ }
+
+ for (i = 0; status_handlers[i].status != -1; i++) {
+ if (status == status_handlers[i].status) {
+ IPW_DEBUG_NOTIF("Status change: %s\n",
+ status_handlers[i].name);
+ if (status_handlers[i].cb)
+ status_handlers[i].cb(priv, status);
+ priv->wstats.status = status;
+ return;
+ }
+ }
+
+ IPW_DEBUG_NOTIF("unknown status received: %04x\n", status);
+}
+
+static void isr_rx_complete_command(
+ struct ipw2100_priv *priv,
+ struct ipw2100_cmd_header *cmd)
+{
+#ifdef CONFIG_IPW_DEBUG
+ if (cmd->host_command_reg < ARRAY_SIZE(command_types)) {
+ IPW_DEBUG_HC("Command completed '%s (%d)'\n",
+ command_types[cmd->host_command_reg],
+ cmd->host_command_reg);
+ }
+#endif
+ if (cmd->host_command_reg == HOST_COMPLETE)
+ priv->status |= STATUS_ENABLED;
+
+ if (cmd->host_command_reg == CARD_DISABLE)
+ priv->status &= ~STATUS_ENABLED;
+
+ priv->status &= ~STATUS_CMD_ACTIVE;
+
+ wake_up_interruptible(&priv->wait_command_queue);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *frame_types[] = {
+ "COMMAND_STATUS_VAL",
+ "STATUS_CHANGE_VAL",
+ "P80211_DATA_VAL",
+ "P8023_DATA_VAL",
+ "HOST_NOTIFICATION_VAL"
+};
+#endif
+
+
+static inline int ipw2100_alloc_skb(
+ struct ipw2100_priv *priv,
+ struct ipw2100_rx_packet *packet)
+{
+ packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));
+ if (!packet->skb)
+ return -ENOMEM;
+
+ packet->rxp = (struct ipw2100_rx *)packet->skb->data;
+ packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+ /* NOTE: pci_map_single does not return an error code, and 0 is a valid
+ * dma_addr */
+
+ return 0;
+}
+
+
+#define SEARCH_ERROR 0xffffffff
+#define SEARCH_FAIL 0xfffffffe
+#define SEARCH_SUCCESS 0xfffffff0
+#define SEARCH_DISCARD 0
+#define SEARCH_SNAPSHOT 1
+
+#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))
+static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
+{
+ int i;
+ if (priv->snapshot[0])
+ return 1;
+ for (i = 0; i < 0x30; i++) {
+ priv->snapshot[i] = (u8*)kmalloc(0x1000, GFP_ATOMIC);
+ if (!priv->snapshot[i]) {
+ IPW_DEBUG_INFO("%s: Error allocating snapshot "
+ "buffer %d\n", priv->net_dev->name, i);
+ while (i > 0)
+ kfree(priv->snapshot[--i]);
+ priv->snapshot[0] = NULL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+{
+ int i;
+ if (!priv->snapshot[0])
+ return;
+ for (i = 0; i < 0x30; i++)
+ kfree(priv->snapshot[i]);
+ priv->snapshot[0] = NULL;
+}
+
+static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 *in_buf,
+ size_t len, int mode)
+{
+ u32 i, j;
+ u32 tmp;
+ u8 *s, *d;
+ u32 ret;
+
+ s = in_buf;
+ if (mode == SEARCH_SNAPSHOT) {
+ if (!ipw2100_snapshot_alloc(priv))
+ mode = SEARCH_DISCARD;
+ }
+
+ for (ret = SEARCH_FAIL, i = 0; i < 0x30000; i += 4) {
+ read_nic_dword(priv->net_dev, i, &tmp);
+ if (mode == SEARCH_SNAPSHOT)
+ *(u32 *)SNAPSHOT_ADDR(i) = tmp;
+ if (ret == SEARCH_FAIL) {
+ d = (u8*)&tmp;
+ for (j = 0; j < 4; j++) {
+ if (*s != *d) {
+ s = in_buf;
+ continue;
+ }
+
+ s++;
+ d++;
+
+ if ((s - in_buf) == len)
+ ret = (i + j) - len + 1;
+ }
+ } else if (mode == SEARCH_DISCARD)
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * 0) Disconnect the SKB from the firmware (just unmap)
+ * 1) Pack the ETH header into the SKB
+ * 2) Pass the SKB to the network stack
+ *
+ * When packet is provided by the firmware, it contains the following:
+ *
+ * . ieee80211_hdr
+ * . ieee80211_snap_hdr
+ *
+ * The size of the constructed ethernet
+ *
+ */
+#ifdef CONFIG_IPW2100_RX_DEBUG
+static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
+#endif
+
+static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv,
+ int i)
+{
+#ifdef CONFIG_IPW_DEBUG_C3
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ u32 match, reg;
+ int j;
+#endif
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ int limit;
+#endif
+
+ IPW_DEBUG_INFO(DRV_NAME ": PCI latency error detected at "
+ "0x%04zX.\n", i * sizeof(struct ipw2100_status));
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ IPW_DEBUG_INFO(DRV_NAME ": Disabling C3 transitions.\n");
+ limit = acpi_get_cstate_limit();
+ if (limit > 2) {
+ priv->cstate_limit = limit;
+ acpi_set_cstate_limit(2);
+ priv->config |= CFG_C3_DISABLED;
+ }
+#endif
+
+#ifdef CONFIG_IPW_DEBUG_C3
+ /* Halt the fimrware so we can get a good image */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+ j = 5;
+ do {
+ udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ } while (j--);
+
+ match = ipw2100_match_buf(priv, (u8*)status,
+ sizeof(struct ipw2100_status),
+ SEARCH_SNAPSHOT);
+ if (match < SEARCH_SUCCESS)
+ IPW_DEBUG_INFO("%s: DMA status match in Firmware at "
+ "offset 0x%06X, length %d:\n",
+ priv->net_dev->name, match,
+ sizeof(struct ipw2100_status));
+ else
+ IPW_DEBUG_INFO("%s: No DMA status match in "
+ "Firmware.\n", priv->net_dev->name);
+
+ printk_buf((u8*)priv->status_queue.drv,
+ sizeof(struct ipw2100_status) * RX_QUEUE_LENGTH);
+#endif
+
+ priv->fatal_error = IPW2100_ERR_C3_CORRUPTION;
+ priv->ieee->stats.rx_errors++;
+ schedule_reset(priv);
+}
+
+static inline void isr_rx(struct ipw2100_priv *priv, int i,
+ struct ieee80211_rx_stats *stats)
+{
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+ IPW_DEBUG_RX("Handler...\n");
+
+ if (unlikely(status->frame_size > skb_tailroom(packet->skb))) {
+ IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"
+ " Dropping.\n",
+ priv->net_dev->name,
+ status->frame_size, skb_tailroom(packet->skb));
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ if (unlikely(!netif_running(priv->net_dev))) {
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+ return;
+ }
+
+ if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&
+ status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
+ IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR &&
+ !(priv->status & STATUS_ASSOCIATED))) {
+ IPW_DEBUG_DROP("Dropping packet while not associated.\n");
+ priv->wstats.discard.misc++;
+ return;
+ }
+
+
+ pci_unmap_single(priv->pci_dev,
+ packet->dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+
+ skb_put(packet->skb, status->frame_size);
+
+#ifdef CONFIG_IPW2100_RX_DEBUG
+ /* Make a copy of the frame so we can dump it to the logs if
+ * ieee80211_rx fails */
+ memcpy(packet_data, packet->skb->data,
+ min_t(u32, status->frame_size, IPW_RX_NIC_BUFFER_LENGTH));
+#endif
+
+ if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
+#ifdef CONFIG_IPW2100_RX_DEBUG
+ IPW_DEBUG_DROP("%s: Non consumed packet:\n",
+ priv->net_dev->name);
+ printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
+#endif
+ priv->ieee->stats.rx_errors++;
+
+ /* ieee80211_rx failed, so it didn't free the SKB */
+ dev_kfree_skb_any(packet->skb);
+ packet->skb = NULL;
+ }
+
+ /* We need to allocate a new SKB and attach it to the RDB. */
+ if (unlikely(ipw2100_alloc_skb(priv, packet))) {
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Unable to allocate SKB onto RBD ring - disabling "
+ "adapter.\n", priv->net_dev->name);
+ /* TODO: schedule adapter shutdown */
+ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n");
+ }
+
+ /* Update the RDB entry */
+ priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+}
+
+static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
+{
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ struct ipw2100_rx *u = priv->rx_buffers[i].rxp;
+ u16 frame_type = status->status_fields & STATUS_TYPE_MASK;
+
+ switch (frame_type) {
+ case COMMAND_STATUS_VAL:
+ return (status->frame_size != sizeof(u->rx_data.command));
+ case STATUS_CHANGE_VAL:
+ return (status->frame_size != sizeof(u->rx_data.status));
+ case HOST_NOTIFICATION_VAL:
+ return (status->frame_size < sizeof(u->rx_data.notification));
+ case P80211_DATA_VAL:
+ case P8023_DATA_VAL:
+#ifdef CONFIG_IPW2100_MONITOR
+ return 0;
+#else
+ switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ case IEEE80211_FTYPE_CTL:
+ return 0;
+ case IEEE80211_FTYPE_DATA:
+ return (status->frame_size >
+ IPW_MAX_802_11_PAYLOAD_LENGTH);
+ }
+#endif
+ }
+
+ return 1;
+}
+
+/*
+ * ipw2100 interrupts are disabled at this point, and the ISR
+ * is the only code that calls this method. So, we do not need
+ * to play with any locks.
+ *
+ * RX Queue works as follows:
+ *
+ * Read index - firmware places packet in entry identified by the
+ * Read index and advances Read index. In this manner,
+ * Read index will always point to the next packet to
+ * be filled--but not yet valid.
+ *
+ * Write index - driver fills this entry with an unused RBD entry.
+ * This entry has not filled by the firmware yet.
+ *
+ * In between the W and R indexes are the RBDs that have been received
+ * but not yet processed.
+ *
+ * The process of handling packets will start at WRITE + 1 and advance
+ * until it reaches the READ index.
+ *
+ * The WRITE index is cached in the variable 'priv->rx_queue.next'.
+ *
+ */
+static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
+{
+ struct ipw2100_bd_queue *rxq = &priv->rx_queue;
+ struct ipw2100_status_queue *sq = &priv->status_queue;
+ struct ipw2100_rx_packet *packet;
+ u16 frame_type;
+ u32 r, w, i, s;
+ struct ipw2100_rx *u;
+ struct ieee80211_rx_stats stats = {
+ .mac_time = jiffies,
+ };
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_READ_INDEX, &r);
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, &w);
+
+ if (r >= rxq->entries) {
+ IPW_DEBUG_RX("exit - bad read index\n");
+ return;
+ }
+
+ i = (rxq->next + 1) % rxq->entries;
+ s = i;
+ while (i != r) {
+ /* IPW_DEBUG_RX("r = %d : w = %d : processing = %d\n",
+ r, rxq->next, i); */
+
+ packet = &priv->rx_buffers[i];
+
+ /* Sync the DMA for the STATUS buffer so CPU is sure to get
+ * the correct values */
+ pci_dma_sync_single_for_cpu(
+ priv->pci_dev,
+ sq->nic + sizeof(struct ipw2100_status) * i,
+ sizeof(struct ipw2100_status),
+ PCI_DMA_FROMDEVICE);
+
+ /* Sync the DMA for the RX buffer so CPU is sure to get
+ * the correct values */
+ pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+
+ if (unlikely(ipw2100_corruption_check(priv, i))) {
+ ipw2100_corruption_detected(priv, i);
+ goto increment;
+ }
+
+ u = packet->rxp;
+ frame_type = sq->drv[i].status_fields &
+ STATUS_TYPE_MASK;
+ stats.rssi = sq->drv[i].rssi + IPW2100_RSSI_TO_DBM;
+ stats.len = sq->drv[i].frame_size;
+
+ stats.mask = 0;
+ if (stats.rssi != 0)
+ stats.mask |= IEEE80211_STATMASK_RSSI;
+ stats.freq = IEEE80211_24GHZ_BAND;
+
+ IPW_DEBUG_RX(
+ "%s: '%s' frame type received (%d).\n",
+ priv->net_dev->name, frame_types[frame_type],
+ stats.len);
+
+ switch (frame_type) {
+ case COMMAND_STATUS_VAL:
+ /* Reset Rx watchdog */
+ isr_rx_complete_command(
+ priv, &u->rx_data.command);
+ break;
+
+ case STATUS_CHANGE_VAL:
+ isr_status_change(priv, u->rx_data.status);
+ break;
+
+ case P80211_DATA_VAL:
+ case P8023_DATA_VAL:
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ isr_rx(priv, i, &stats);
+ break;
+ }
+#endif
+ if (stats.len < sizeof(u->rx_data.header))
+ break;
+ switch (WLAN_FC_GET_TYPE(u->rx_data.header.
+ frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ ieee80211_rx_mgt(priv->ieee,
+ &u->rx_data.header,
+ &stats);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+ break;
+
+ case IEEE80211_FTYPE_DATA:
+ isr_rx(priv, i, &stats);
+ break;
+
+ }
+ break;
+ }
+
+ increment:
+ /* clear status field associated with this RBD */
+ rxq->drv[i].status.info.field = 0;
+
+ i = (i + 1) % rxq->entries;
+ }
+
+ if (i != s) {
+ /* backtrack one entry, wrapping to end if at 0 */
+ rxq->next = (i ? i : rxq->entries) - 1;
+
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_RX_WRITE_INDEX,
+ rxq->next);
+ }
+}
+
+
+/*
+ * __ipw2100_tx_process
+ *
+ * This routine will determine whether the next packet on
+ * the fw_pend_list has been processed by the firmware yet.
+ *
+ * If not, then it does nothing and returns.
+ *
+ * If so, then it removes the item from the fw_pend_list, frees
+ * any associated storage, and places the item back on the
+ * free list of its source (either msg_free_list or tx_free_list)
+ *
+ * TX Queue works as follows:
+ *
+ * Read index - points to the next TBD that the firmware will
+ * process. The firmware will read the data, and once
+ * done processing, it will advance the Read index.
+ *
+ * Write index - driver fills this entry with an constructed TBD
+ * entry. The Write index is not advanced until the
+ * packet has been configured.
+ *
+ * In between the W and R indexes are the TBDs that have NOT been
+ * processed. Lagging behind the R index are packets that have
+ * been processed but have not been freed by the driver.
+ *
+ * In order to free old storage, an internal index will be maintained
+ * that points to the next packet to be freed. When all used
+ * packets have been freed, the oldest index will be the same as the
+ * firmware's read index.
+ *
+ * The OLDEST index is cached in the variable 'priv->tx_queue.oldest'
+ *
+ * Because the TBD structure can not contain arbitrary data, the
+ * driver must keep an internal queue of cached allocations such that
+ * it can put that data back into the tx_free_list and msg_free_list
+ * for use by future command and data packets.
+ *
+ */
+static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
+{
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ int descriptors_used;
+ int e, i;
+ u32 r, w, frag_num = 0;
+
+ if (list_empty(&priv->fw_pend_list))
+ return 0;
+
+ element = priv->fw_pend_list.next;
+
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+ tbd = &txq->drv[packet->index];
+
+ /* Determine how many TBD entries must be finished... */
+ switch (packet->type) {
+ case COMMAND:
+ /* COMMAND uses only one slot; don't advance */
+ descriptors_used = 1;
+ e = txq->oldest;
+ break;
+
+ case DATA:
+ /* DATA uses two slots; advance and loop position. */
+ descriptors_used = tbd->num_fragments;
+ frag_num = tbd->num_fragments - 1;
+ e = txq->oldest + frag_num;
+ e %= txq->entries;
+ break;
+
+ default:
+ printk(KERN_WARNING DRV_NAME ": %s: Bad fw_pend_list entry!\n",
+ priv->net_dev->name);
+ return 0;
+ }
+
+ /* if the last TBD is not done by NIC yet, then packet is
+ * not ready to be released.
+ *
+ */
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX,
+ &r);
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ &w);
+ if (w != txq->next)
+ printk(KERN_WARNING DRV_NAME ": %s: write index mismatch\n",
+ priv->net_dev->name);
+
+ /*
+ * txq->next is the index of the last packet written txq->oldest is
+ * the index of the r is the index of the next packet to be read by
+ * firmware
+ */
+
+
+ /*
+ * Quick graphic to help you visualize the following
+ * if / else statement
+ *
+ * ===>| s---->|===============
+ * e>|
+ * | a | b | c | d | e | f | g | h | i | j | k | l
+ * r---->|
+ * w
+ *
+ * w - updated by driver
+ * r - updated by firmware
+ * s - start of oldest BD entry (txq->oldest)
+ * e - end of oldest BD entry
+ *
+ */
+ if (!((r <= w && (e < r || e >= w)) || (e < r && e >= w))) {
+ IPW_DEBUG_TX("exit - no processed packets ready to release.\n");
+ return 0;
+ }
+
+ list_del(element);
+ DEC_STAT(&priv->fw_pend_stat);
+
+#ifdef CONFIG_IPW_DEBUG
+ {
+ int i = txq->oldest;
+ IPW_DEBUG_TX(
+ "TX%d V=%p P=%04X T=%04X L=%d\n", i,
+ &txq->drv[i],
+ (u32)(txq->nic + i * sizeof(struct ipw2100_bd)),
+ txq->drv[i].host_addr,
+ txq->drv[i].buf_length);
+
+ if (packet->type == DATA) {
+ i = (i + 1) % txq->entries;
+
+ IPW_DEBUG_TX(
+ "TX%d V=%p P=%04X T=%04X L=%d\n", i,
+ &txq->drv[i],
+ (u32)(txq->nic + i *
+ sizeof(struct ipw2100_bd)),
+ (u32)txq->drv[i].host_addr,
+ txq->drv[i].buf_length);
+ }
+ }
+#endif
+
+ switch (packet->type) {
+ case DATA:
+ if (txq->drv[txq->oldest].status.info.fields.txType != 0)
+ printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. "
+ "Expecting DATA TBD but pulled "
+ "something else: ids %d=%d.\n",
+ priv->net_dev->name, txq->oldest, packet->index);
+
+ /* DATA packet; we have to unmap and free the SKB */
+ priv->ieee->stats.tx_packets++;
+ for (i = 0; i < frag_num; i++) {
+ tbd = &txq->drv[(packet->index + 1 + i) %
+ txq->entries];
+
+ IPW_DEBUG_TX(
+ "TX%d P=%08x L=%d\n",
+ (packet->index + 1 + i) % txq->entries,
+ tbd->host_addr, tbd->buf_length);
+
+ pci_unmap_single(priv->pci_dev,
+ tbd->host_addr,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+ }
+
+ priv->ieee->stats.tx_bytes += packet->info.d_struct.txb->payload_size;
+ ieee80211_txb_free(packet->info.d_struct.txb);
+ packet->info.d_struct.txb = NULL;
+
+ list_add_tail(element, &priv->tx_free_list);
+ INC_STAT(&priv->tx_free_stat);
+
+ /* We have a free slot in the Tx queue, so wake up the
+ * transmit layer if it is stopped. */
+ if (priv->status & STATUS_ASSOCIATED &&
+ netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_INFO(KERN_INFO
+ "%s: Waking net queue.\n",
+ priv->net_dev->name);
+ netif_wake_queue(priv->net_dev);
+ }
+
+ /* A packet was processed by the hardware, so update the
+ * watchdog */
+ priv->net_dev->trans_start = jiffies;
+
+ break;
+
+ case COMMAND:
+ if (txq->drv[txq->oldest].status.info.fields.txType != 1)
+ printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. "
+ "Expecting COMMAND TBD but pulled "
+ "something else: ids %d=%d.\n",
+ priv->net_dev->name, txq->oldest, packet->index);
+
+#ifdef CONFIG_IPW_DEBUG
+ if (packet->info.c_struct.cmd->host_command_reg <
+ sizeof(command_types) / sizeof(*command_types))
+ IPW_DEBUG_TX(
+ "Command '%s (%d)' processed: %d.\n",
+ command_types[packet->info.c_struct.cmd->host_command_reg],
+ packet->info.c_struct.cmd->host_command_reg,
+ packet->info.c_struct.cmd->cmd_status_reg);
+#endif
+
+ list_add_tail(element, &priv->msg_free_list);
+ INC_STAT(&priv->msg_free_stat);
+ break;
+ }
+
+ /* advance oldest used TBD pointer to start of next entry */
+ txq->oldest = (e + 1) % txq->entries;
+ /* increase available TBDs number */
+ txq->available += descriptors_used;
+ SET_STAT(&priv->txq_stat, txq->available);
+
+ IPW_DEBUG_TX("packet latency (send to process) %ld jiffies\n",
+ jiffies - packet->jiffy_start);
+
+ return (!list_empty(&priv->fw_pend_list));
+}
+
+
+static inline void __ipw2100_tx_complete(struct ipw2100_priv *priv)
+{
+ int i = 0;
+
+ while (__ipw2100_tx_process(priv) && i < 200) i++;
+
+ if (i == 200) {
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Driver is running slow (%d iters).\n",
+ priv->net_dev->name, i);
+ }
+}
+
+
+static void ipw2100_tx_send_commands(struct ipw2100_priv *priv)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ int next = txq->next;
+
+ while (!list_empty(&priv->msg_pend_list)) {
+ /* if there isn't enough space in TBD queue, then
+ * don't stuff a new one in.
+ * NOTE: 3 are needed as a command will take one,
+ * and there is a minimum of 2 that must be
+ * maintained between the r and w indexes
+ */
+ if (txq->available <= 3) {
+ IPW_DEBUG_TX("no room in tx_queue\n");
+ break;
+ }
+
+ element = priv->msg_pend_list.next;
+ list_del(element);
+ DEC_STAT(&priv->msg_pend_stat);
+
+ packet = list_entry(element,
+ struct ipw2100_tx_packet, list);
+
+ IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n",
+ &txq->drv[txq->next],
+ (void*)(txq->nic + txq->next *
+ sizeof(struct ipw2100_bd)));
+
+ packet->index = txq->next;
+
+ tbd = &txq->drv[txq->next];
+
+ /* initialize TBD */
+ tbd->host_addr = packet->info.c_struct.cmd_phys;
+ tbd->buf_length = sizeof(struct ipw2100_cmd_header);
+ /* not marking number of fragments causes problems
+ * with f/w debug version */
+ tbd->num_fragments = 1;
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_COMMAND |
+ IPW_BD_STATUS_TX_INTERRUPT_ENABLE;
+
+ /* update TBD queue counters */
+ txq->next++;
+ txq->next %= txq->entries;
+ txq->available--;
+ DEC_STAT(&priv->txq_stat);
+
+ list_add_tail(element, &priv->fw_pend_list);
+ INC_STAT(&priv->fw_pend_stat);
+ }
+
+ if (txq->next != next) {
+ /* kick off the DMA by notifying firmware the
+ * write index has moved; make sure TBD stores are sync'd */
+ wmb();
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ txq->next);
+ }
+}
+
+
+/*
+ * ipw2100_tx_send_data
+ *
+ */
+static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ int next = txq->next;
+ int i = 0;
+ struct ipw2100_data_header *ipw_hdr;
+ struct ieee80211_hdr *hdr;
+
+ while (!list_empty(&priv->tx_pend_list)) {
+ /* if there isn't enough space in TBD queue, then
+ * don't stuff a new one in.
+ * NOTE: 4 are needed as a data will take two,
+ * and there is a minimum of 2 that must be
+ * maintained between the r and w indexes
+ */
+ element = priv->tx_pend_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ if (unlikely(1 + packet->info.d_struct.txb->nr_frags >
+ IPW_MAX_BDS)) {
+ /* TODO: Support merging buffers if more than
+ * IPW_MAX_BDS are used */
+ IPW_DEBUG_INFO(
+ "%s: Maximum BD theshold exceeded. "
+ "Increase fragmentation level.\n",
+ priv->net_dev->name);
+ }
+
+ if (txq->available <= 3 +
+ packet->info.d_struct.txb->nr_frags) {
+ IPW_DEBUG_TX("no room in tx_queue\n");
+ break;
+ }
+
+ list_del(element);
+ DEC_STAT(&priv->tx_pend_stat);
+
+ tbd = &txq->drv[txq->next];
+
+ packet->index = txq->next;
+
+ ipw_hdr = packet->info.d_struct.data;
+ hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
+ fragments[0]->data;
+
+ if (priv->ieee->iw_mode == IW_MODE_INFRA) {
+ /* To DS: Addr1 = BSSID, Addr2 = SA,
+ Addr3 = DA */
+ memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(ipw_hdr->dst_addr, hdr->addr3, ETH_ALEN);
+ } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA,
+ Addr3 = BSSID */
+ memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(ipw_hdr->dst_addr, hdr->addr1, ETH_ALEN);
+ }
+
+ ipw_hdr->host_command_reg = SEND;
+ ipw_hdr->host_command_reg1 = 0;
+
+ /* For now we only support host based encryption */
+ ipw_hdr->needs_encryption = 0;
+ ipw_hdr->encrypted = packet->info.d_struct.txb->encrypted;
+ if (packet->info.d_struct.txb->nr_frags > 1)
+ ipw_hdr->fragment_size =
+ packet->info.d_struct.txb->frag_size - IEEE80211_3ADDR_LEN;
+ else
+ ipw_hdr->fragment_size = 0;
+
+ tbd->host_addr = packet->info.d_struct.data_phys;
+ tbd->buf_length = sizeof(struct ipw2100_data_header);
+ tbd->num_fragments = 1 + packet->info.d_struct.txb->nr_frags;
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT;
+ txq->next++;
+ txq->next %= txq->entries;
+
+ IPW_DEBUG_TX(
+ "data header tbd TX%d P=%08x L=%d\n",
+ packet->index, tbd->host_addr,
+ tbd->buf_length);
+#ifdef CONFIG_IPW_DEBUG
+ if (packet->info.d_struct.txb->nr_frags > 1)
+ IPW_DEBUG_FRAG("fragment Tx: %d frames\n",
+ packet->info.d_struct.txb->nr_frags);
+#endif
+
+ for (i = 0; i < packet->info.d_struct.txb->nr_frags; i++) {
+ tbd = &txq->drv[txq->next];
+ if (i == packet->info.d_struct.txb->nr_frags - 1)
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_INTERRUPT_ENABLE;
+ else
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT;
+
+ tbd->buf_length = packet->info.d_struct.txb->
+ fragments[i]->len - IEEE80211_3ADDR_LEN;
+
+ tbd->host_addr = pci_map_single(
+ priv->pci_dev,
+ packet->info.d_struct.txb->fragments[i]->data +
+ IEEE80211_3ADDR_LEN,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+
+ IPW_DEBUG_TX(
+ "data frag tbd TX%d P=%08x L=%d\n",
+ txq->next, tbd->host_addr, tbd->buf_length);
+
+ pci_dma_sync_single_for_device(
+ priv->pci_dev, tbd->host_addr,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+
+ txq->next++;
+ txq->next %= txq->entries;
+ }
+
+ txq->available -= 1 + packet->info.d_struct.txb->nr_frags;
+ SET_STAT(&priv->txq_stat, txq->available);
+
+ list_add_tail(element, &priv->fw_pend_list);
+ INC_STAT(&priv->fw_pend_stat);
+ }
+
+ if (txq->next != next) {
+ /* kick off the DMA by notifying firmware the
+ * write index has moved; make sure TBD stores are sync'd */
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ txq->next);
+ }
+ return;
+}
+
+static void ipw2100_irq_tasklet(struct ipw2100_priv *priv)
+{
+ struct net_device *dev = priv->net_dev;
+ unsigned long flags;
+ u32 inta, tmp;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+
+ read_register(dev, IPW_REG_INTA, &inta);
+
+ IPW_DEBUG_ISR("enter - INTA: 0x%08lX\n",
+ (unsigned long)inta & IPW_INTERRUPT_MASK);
+
+ priv->in_isr++;
+ priv->interrupts++;
+
+ /* We do not loop and keep polling for more interrupts as this
+ * is frowned upon and doesn't play nicely with other potentially
+ * chained IRQs */
+ IPW_DEBUG_ISR("INTA: 0x%08lX\n",
+ (unsigned long)inta & IPW_INTERRUPT_MASK);
+
+ if (inta & IPW2100_INTA_FATAL_ERROR) {
+ printk(KERN_WARNING DRV_NAME
+ ": Fatal interrupt. Scheduling firmware restart.\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR);
+
+ read_nic_dword(dev, IPW_NIC_FATAL_ERROR, &priv->fatal_error);
+ IPW_DEBUG_INFO("%s: Fatal error value: 0x%08X\n",
+ priv->net_dev->name, priv->fatal_error);
+
+ read_nic_dword(dev, IPW_ERROR_ADDR(priv->fatal_error), &tmp);
+ IPW_DEBUG_INFO("%s: Fatal error address value: 0x%08X\n",
+ priv->net_dev->name, tmp);
+
+ /* Wake up any sleeping jobs */
+ schedule_reset(priv);
+ }
+
+ if (inta & IPW2100_INTA_PARITY_ERROR) {
+ printk(KERN_ERR DRV_NAME ": ***** PARITY ERROR INTERRUPT !!!! \n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_PARITY_ERROR);
+ }
+
+ if (inta & IPW2100_INTA_RX_TRANSFER) {
+ IPW_DEBUG_ISR("RX interrupt\n");
+
+ priv->rx_interrupts++;
+
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_RX_TRANSFER);
+
+ __ipw2100_rx_process(priv);
+ __ipw2100_tx_complete(priv);
+ }
+
+ if (inta & IPW2100_INTA_TX_TRANSFER) {
+ IPW_DEBUG_ISR("TX interrupt\n");
+
+ priv->tx_interrupts++;
+
+ write_register(dev, IPW_REG_INTA,
+ IPW2100_INTA_TX_TRANSFER);
+
+ __ipw2100_tx_complete(priv);
+ ipw2100_tx_send_commands(priv);
+ ipw2100_tx_send_data(priv);
+ }
+
+ if (inta & IPW2100_INTA_TX_COMPLETE) {
+ IPW_DEBUG_ISR("TX complete\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_TX_COMPLETE);
+
+ __ipw2100_tx_complete(priv);
+ }
+
+ if (inta & IPW2100_INTA_EVENT_INTERRUPT) {
+ /* ipw2100_handle_event(dev); */
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_EVENT_INTERRUPT);
+ }
+
+ if (inta & IPW2100_INTA_FW_INIT_DONE) {
+ IPW_DEBUG_ISR("FW init done interrupt\n");
+ priv->inta_other++;
+
+ read_register(dev, IPW_REG_INTA, &tmp);
+ if (tmp & (IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR)) {
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR);
+ }
+
+ write_register(dev, IPW_REG_INTA,
+ IPW2100_INTA_FW_INIT_DONE);
+ }
+
+ if (inta & IPW2100_INTA_STATUS_CHANGE) {
+ IPW_DEBUG_ISR("Status change interrupt\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_STATUS_CHANGE);
+ }
+
+ if (inta & IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE) {
+ IPW_DEBUG_ISR("slave host mode interrupt\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE);
+ }
+
+ priv->in_isr--;
+ ipw2100_enable_interrupts(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ IPW_DEBUG_ISR("exit\n");
+}
+
+
+static irqreturn_t ipw2100_interrupt(int irq, void *data,
+ struct pt_regs *regs)
+{
+ struct ipw2100_priv *priv = data;
+ u32 inta, inta_mask;
+
+ if (!data)
+ return IRQ_NONE;
+
+ spin_lock(&priv->low_lock);
+
+ /* We check to see if we should be ignoring interrupts before
+ * we touch the hardware. During ucode load if we try and handle
+ * an interrupt we can cause keyboard problems as well as cause
+ * the ucode to fail to initialize */
+ if (!(priv->status & STATUS_INT_ENABLED)) {
+ /* Shared IRQ */
+ goto none;
+ }
+
+ read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask);
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+
+ if (inta == 0xFFFFFFFF) {
+ /* Hardware disappeared */
+ printk(KERN_WARNING DRV_NAME ": IRQ INTA == 0xFFFFFFFF\n");
+ goto none;
+ }
+
+ inta &= IPW_INTERRUPT_MASK;
+
+ if (!(inta & inta_mask)) {
+ /* Shared interrupt */
+ goto none;
+ }
+
+ /* We disable the hardware interrupt here just to prevent unneeded
+ * calls to be made. We disable this again within the actual
+ * work tasklet, so if another part of the code re-enables the
+ * interrupt, that is fine */
+ ipw2100_disable_interrupts(priv);
+
+ tasklet_schedule(&priv->irq_tasklet);
+ spin_unlock(&priv->low_lock);
+
+ return IRQ_HANDLED;
+ none:
+ spin_unlock(&priv->low_lock);
+ return IRQ_NONE;
+}
+
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_INFO("Can not transmit when not connected.\n");
+ priv->ieee->stats.tx_carrier_errors++;
+ netif_stop_queue(dev);
+ goto fail_unlock;
+ }
+
+ if (list_empty(&priv->tx_free_list))
+ goto fail_unlock;
+
+ element = priv->tx_free_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ packet->info.d_struct.txb = txb;
+
+ IPW_DEBUG_TX("Sending fragment (%d bytes):\n",
+ txb->fragments[0]->len);
+ printk_buf(IPW_DL_TX, txb->fragments[0]->data,
+ txb->fragments[0]->len);
+
+ packet->jiffy_start = jiffies;
+
+ list_del(element);
+ DEC_STAT(&priv->tx_free_stat);
+
+ list_add_tail(element, &priv->tx_pend_list);
+ INC_STAT(&priv->tx_pend_stat);
+
+ ipw2100_tx_send_data(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+ return 0;
+
+ fail_unlock:
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+ return 1;
+}
+
+
+static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+ void *v;
+ dma_addr_t p;
+
+ priv->msg_buffers = (struct ipw2100_tx_packet *)kmalloc(
+ IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet),
+ GFP_KERNEL);
+ if (!priv->msg_buffers) {
+ printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg "
+ "buffers.\n", priv->net_dev->name);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
+ v = pci_alloc_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ &p);
+ if (!v) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: PCI alloc failed for msg "
+ "buffers.\n",
+ priv->net_dev->name);
+ err = -ENOMEM;
+ break;
+ }
+
+ memset(v, 0, sizeof(struct ipw2100_cmd_header));
+
+ priv->msg_buffers[i].type = COMMAND;
+ priv->msg_buffers[i].info.c_struct.cmd =
+ (struct ipw2100_cmd_header*)v;
+ priv->msg_buffers[i].info.c_struct.cmd_phys = p;
+ }
+
+ if (i == IPW_COMMAND_POOL_SIZE)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ priv->msg_buffers[j].info.c_struct.cmd,
+ priv->msg_buffers[j].info.c_struct.cmd_phys);
+ }
+
+ kfree(priv->msg_buffers);
+ priv->msg_buffers = NULL;
+
+ return err;
+}
+
+static int ipw2100_msg_initialize(struct ipw2100_priv *priv)
+{
+ int i;
+
+ INIT_LIST_HEAD(&priv->msg_free_list);
+ INIT_LIST_HEAD(&priv->msg_pend_list);
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++)
+ list_add_tail(&priv->msg_buffers[i].list, &priv->msg_free_list);
+ SET_STAT(&priv->msg_free_stat, i);
+
+ return 0;
+}
+
+static void ipw2100_msg_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ if (!priv->msg_buffers)
+ return;
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
+ pci_free_consistent(priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ priv->msg_buffers[i].info.c_struct.cmd,
+ priv->msg_buffers[i].info.c_struct.cmd_phys);
+ }
+
+ kfree(priv->msg_buffers);
+ priv->msg_buffers = NULL;
+}
+
+static ssize_t show_pci(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_dev = container_of(d, struct pci_dev, dev);
+ char *out = buf;
+ int i, j;
+ u32 val;
+
+ for (i = 0; i < 16; i++) {
+ out += sprintf(out, "[%08X] ", i * 16);
+ for (j = 0; j < 16; j += 4) {
+ pci_read_config_dword(pci_dev, i * 16 + j, &val);
+ out += sprintf(out, "%08X ", val);
+ }
+ out += sprintf(out, "\n");
+ }
+
+ return out - buf;
+}
+static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL);
+
+static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->config);
+}
+static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL);
+
+static ssize_t show_status(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->status);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+static ssize_t show_capability(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->capability);
+}
+static DEVICE_ATTR(capability, S_IRUGO, show_capability, NULL);
+
+
+#define IPW2100_REG(x) { IPW_ ##x, #x }
+static const struct {
+ u32 addr;
+ const char *name;
+} hw_data[] = {
+ IPW2100_REG(REG_GP_CNTRL),
+ IPW2100_REG(REG_GPIO),
+ IPW2100_REG(REG_INTA),
+ IPW2100_REG(REG_INTA_MASK),
+ IPW2100_REG(REG_RESET_REG),
+};
+#define IPW2100_NIC(x, s) { x, #x, s }
+static const struct {
+ u32 addr;
+ const char *name;
+ size_t size;
+} nic_data[] = {
+ IPW2100_NIC(IPW2100_CONTROL_REG, 2),
+ IPW2100_NIC(0x210014, 1),
+ IPW2100_NIC(0x210000, 1),
+};
+#define IPW2100_ORD(x, d) { IPW_ORD_ ##x, #x, d }
+static const struct {
+ u8 index;
+ const char *name;
+ const char *desc;
+} ord_data[] = {
+ IPW2100_ORD(STAT_TX_HOST_REQUESTS, "requested Host Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_HOST_COMPLETE, "successful Host Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_DIR_DATA, "successful Directed Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_DIR_DATA1, "successful Directed Tx's (MSDU) @ 1MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA2, "successful Directed Tx's (MSDU) @ 2MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA5_5, "successful Directed Tx's (MSDU) @ 5_5MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA11, "successful Directed Tx's (MSDU) @ 11MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA1, "successful Non_Directed Tx's (MSDU) @ 1MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA2, "successful Non_Directed Tx's (MSDU) @ 2MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA5_5, "successful Non_Directed Tx's (MSDU) @ 5.5MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA11, "successful Non_Directed Tx's (MSDU) @ 11MB"),
+ IPW2100_ORD(STAT_NULL_DATA, "successful NULL data Tx's"),
+ IPW2100_ORD(STAT_TX_RTS, "successful Tx RTS"),
+ IPW2100_ORD(STAT_TX_CTS, "successful Tx CTS"),
+ IPW2100_ORD(STAT_TX_ACK, "successful Tx ACK"),
+ IPW2100_ORD(STAT_TX_ASSN, "successful Association Tx's"),
+ IPW2100_ORD(STAT_TX_ASSN_RESP, "successful Association response Tx's"),
+ IPW2100_ORD(STAT_TX_REASSN, "successful Reassociation Tx's"),
+ IPW2100_ORD(STAT_TX_REASSN_RESP, "successful Reassociation response Tx's"),
+ IPW2100_ORD(STAT_TX_PROBE, "probes successfully transmitted"),
+ IPW2100_ORD(STAT_TX_PROBE_RESP, "probe responses successfully transmitted"),
+ IPW2100_ORD(STAT_TX_BEACON, "tx beacon"),
+ IPW2100_ORD(STAT_TX_ATIM, "Tx ATIM"),
+ IPW2100_ORD(STAT_TX_DISASSN, "successful Disassociation TX"),
+ IPW2100_ORD(STAT_TX_AUTH, "successful Authentication Tx"),
+ IPW2100_ORD(STAT_TX_DEAUTH, "successful Deauthentication TX"),
+ IPW2100_ORD(STAT_TX_TOTAL_BYTES, "Total successful Tx data bytes"),
+ IPW2100_ORD(STAT_TX_RETRIES, "Tx retries"),
+ IPW2100_ORD(STAT_TX_RETRY1, "Tx retries at 1MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY2, "Tx retries at 2MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY5_5, "Tx retries at 5.5MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY11, "Tx retries at 11MBPS"),
+ IPW2100_ORD(STAT_TX_FAILURES, "Tx Failures"),
+ IPW2100_ORD(STAT_TX_MAX_TRIES_IN_HOP,"times max tries in a hop failed"),
+ IPW2100_ORD(STAT_TX_DISASSN_FAIL, "times disassociation failed"),
+ IPW2100_ORD(STAT_TX_ERR_CTS, "missed/bad CTS frames"),
+ IPW2100_ORD(STAT_TX_ERR_ACK, "tx err due to acks"),
+ IPW2100_ORD(STAT_RX_HOST, "packets passed to host"),
+ IPW2100_ORD(STAT_RX_DIR_DATA, "directed packets"),
+ IPW2100_ORD(STAT_RX_DIR_DATA1, "directed packets at 1MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA2, "directed packets at 2MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA5_5, "directed packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA11, "directed packets at 11MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA,"nondirected packets"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA1, "nondirected packets at 1MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA2, "nondirected packets at 2MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA5_5, "nondirected packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA11, "nondirected packets at 11MB"),
+ IPW2100_ORD(STAT_RX_NULL_DATA, "null data rx's"),
+ IPW2100_ORD(STAT_RX_RTS, "Rx RTS"),
+ IPW2100_ORD(STAT_RX_CTS, "Rx CTS"),
+ IPW2100_ORD(STAT_RX_ACK, "Rx ACK"),
+ IPW2100_ORD(STAT_RX_CFEND, "Rx CF End"),
+ IPW2100_ORD(STAT_RX_CFEND_ACK, "Rx CF End + CF Ack"),
+ IPW2100_ORD(STAT_RX_ASSN, "Association Rx's"),
+ IPW2100_ORD(STAT_RX_ASSN_RESP, "Association response Rx's"),
+ IPW2100_ORD(STAT_RX_REASSN, "Reassociation Rx's"),
+ IPW2100_ORD(STAT_RX_REASSN_RESP, "Reassociation response Rx's"),
+ IPW2100_ORD(STAT_RX_PROBE, "probe Rx's"),
+ IPW2100_ORD(STAT_RX_PROBE_RESP, "probe response Rx's"),
+ IPW2100_ORD(STAT_RX_BEACON, "Rx beacon"),
+ IPW2100_ORD(STAT_RX_ATIM, "Rx ATIM"),
+ IPW2100_ORD(STAT_RX_DISASSN, "disassociation Rx"),
+ IPW2100_ORD(STAT_RX_AUTH, "authentication Rx"),
+ IPW2100_ORD(STAT_RX_DEAUTH, "deauthentication Rx"),
+ IPW2100_ORD(STAT_RX_TOTAL_BYTES,"Total rx data bytes received"),
+ IPW2100_ORD(STAT_RX_ERR_CRC, "packets with Rx CRC error"),
+ IPW2100_ORD(STAT_RX_ERR_CRC1, "Rx CRC errors at 1MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC2, "Rx CRC errors at 2MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC5_5, "Rx CRC errors at 5.5MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC11, "Rx CRC errors at 11MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE1, "duplicate rx packets at 1MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE2, "duplicate rx packets at 2MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE5_5, "duplicate rx packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE11, "duplicate rx packets at 11MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE, "duplicate rx packets"),
+ IPW2100_ORD(PERS_DB_LOCK, "locking fw permanent db"),
+ IPW2100_ORD(PERS_DB_SIZE, "size of fw permanent db"),
+ IPW2100_ORD(PERS_DB_ADDR, "address of fw permanent db"),
+ IPW2100_ORD(STAT_RX_INVALID_PROTOCOL, "rx frames with invalid protocol"),
+ IPW2100_ORD(SYS_BOOT_TIME, "Boot time"),
+ IPW2100_ORD(STAT_RX_NO_BUFFER, "rx frames rejected due to no buffer"),
+ IPW2100_ORD(STAT_RX_MISSING_FRAG, "rx frames dropped due to missing fragment"),
+ IPW2100_ORD(STAT_RX_ORPHAN_FRAG, "rx frames dropped due to non-sequential fragment"),
+ IPW2100_ORD(STAT_RX_ORPHAN_FRAME, "rx frames dropped due to unmatched 1st frame"),
+ IPW2100_ORD(STAT_RX_FRAG_AGEOUT, "rx frames dropped due to uncompleted frame"),
+ IPW2100_ORD(STAT_RX_ICV_ERRORS, "ICV errors during decryption"),
+ IPW2100_ORD(STAT_PSP_SUSPENSION,"times adapter suspended"),
+ IPW2100_ORD(STAT_PSP_BCN_TIMEOUT, "beacon timeout"),
+ IPW2100_ORD(STAT_PSP_POLL_TIMEOUT, "poll response timeouts"),
+ IPW2100_ORD(STAT_PSP_NONDIR_TIMEOUT, "timeouts waiting for last {broad,multi}cast pkt"),
+ IPW2100_ORD(STAT_PSP_RX_DTIMS, "PSP DTIMs received"),
+ IPW2100_ORD(STAT_PSP_RX_TIMS, "PSP TIMs received"),
+ IPW2100_ORD(STAT_PSP_STATION_ID,"PSP Station ID"),
+ IPW2100_ORD(LAST_ASSN_TIME, "RTC time of last association"),
+ IPW2100_ORD(STAT_PERCENT_MISSED_BCNS,"current calculation of % missed beacons"),
+ IPW2100_ORD(STAT_PERCENT_RETRIES,"current calculation of % missed tx retries"),
+ IPW2100_ORD(ASSOCIATED_AP_PTR, "0 if not associated, else pointer to AP table entry"),
+ IPW2100_ORD(AVAILABLE_AP_CNT, "AP's decsribed in the AP table"),
+ IPW2100_ORD(AP_LIST_PTR, "Ptr to list of available APs"),
+ IPW2100_ORD(STAT_AP_ASSNS, "associations"),
+ IPW2100_ORD(STAT_ASSN_FAIL, "association failures"),
+ IPW2100_ORD(STAT_ASSN_RESP_FAIL,"failures due to response fail"),
+ IPW2100_ORD(STAT_FULL_SCANS, "full scans"),
+ IPW2100_ORD(CARD_DISABLED, "Card Disabled"),
+ IPW2100_ORD(STAT_ROAM_INHIBIT, "times roaming was inhibited due to activity"),
+ IPW2100_ORD(RSSI_AT_ASSN, "RSSI of associated AP at time of association"),
+ IPW2100_ORD(STAT_ASSN_CAUSE1, "reassociation: no probe response or TX on hop"),
+ IPW2100_ORD(STAT_ASSN_CAUSE2, "reassociation: poor tx/rx quality"),
+ IPW2100_ORD(STAT_ASSN_CAUSE3, "reassociation: tx/rx quality (excessive AP load"),
+ IPW2100_ORD(STAT_ASSN_CAUSE4, "reassociation: AP RSSI level"),
+ IPW2100_ORD(STAT_ASSN_CAUSE5, "reassociations due to load leveling"),
+ IPW2100_ORD(STAT_AUTH_FAIL, "times authentication failed"),
+ IPW2100_ORD(STAT_AUTH_RESP_FAIL,"times authentication response failed"),
+ IPW2100_ORD(STATION_TABLE_CNT, "entries in association table"),
+ IPW2100_ORD(RSSI_AVG_CURR, "Current avg RSSI"),
+ IPW2100_ORD(POWER_MGMT_MODE, "Power mode - 0=CAM, 1=PSP"),
+ IPW2100_ORD(COUNTRY_CODE, "IEEE country code as recv'd from beacon"),
+ IPW2100_ORD(COUNTRY_CHANNELS, "channels suported by country"),
+ IPW2100_ORD(RESET_CNT, "adapter resets (warm)"),
+ IPW2100_ORD(BEACON_INTERVAL, "Beacon interval"),
+ IPW2100_ORD(ANTENNA_DIVERSITY, "TRUE if antenna diversity is disabled"),
+ IPW2100_ORD(DTIM_PERIOD, "beacon intervals between DTIMs"),
+ IPW2100_ORD(OUR_FREQ, "current radio freq lower digits - channel ID"),
+ IPW2100_ORD(RTC_TIME, "current RTC time"),
+ IPW2100_ORD(PORT_TYPE, "operating mode"),
+ IPW2100_ORD(CURRENT_TX_RATE, "current tx rate"),
+ IPW2100_ORD(SUPPORTED_RATES, "supported tx rates"),
+ IPW2100_ORD(ATIM_WINDOW, "current ATIM Window"),
+ IPW2100_ORD(BASIC_RATES, "basic tx rates"),
+ IPW2100_ORD(NIC_HIGHEST_RATE, "NIC highest tx rate"),
+ IPW2100_ORD(AP_HIGHEST_RATE, "AP highest tx rate"),
+ IPW2100_ORD(CAPABILITIES, "Management frame capability field"),
+ IPW2100_ORD(AUTH_TYPE, "Type of authentication"),
+ IPW2100_ORD(RADIO_TYPE, "Adapter card platform type"),
+ IPW2100_ORD(RTS_THRESHOLD, "Min packet length for RTS handshaking"),
+ IPW2100_ORD(INT_MODE, "International mode"),
+ IPW2100_ORD(FRAGMENTATION_THRESHOLD, "protocol frag threshold"),
+ IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_START_ADDRESS, "EEPROM offset in SRAM"),
+ IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_SIZE, "EEPROM size in SRAM"),
+ IPW2100_ORD(EEPROM_SKU_CAPABILITY, "EEPROM SKU Capability"),
+ IPW2100_ORD(EEPROM_IBSS_11B_CHANNELS, "EEPROM IBSS 11b channel set"),
+ IPW2100_ORD(MAC_VERSION, "MAC Version"),
+ IPW2100_ORD(MAC_REVISION, "MAC Revision"),
+ IPW2100_ORD(RADIO_VERSION, "Radio Version"),
+ IPW2100_ORD(NIC_MANF_DATE_TIME, "MANF Date/Time STAMP"),
+ IPW2100_ORD(UCODE_VERSION, "Ucode Version"),
+};
+
+
+static ssize_t show_registers(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char * out = buf;
+ u32 val = 0;
+
+ out += sprintf(out, "%30s [Address ] : Hex\n", "Register");
+
+ for (i = 0; i < (sizeof(hw_data) / sizeof(*hw_data)); i++) {
+ read_register(dev, hw_data[i].addr, &val);
+ out += sprintf(out, "%30s [%08X] : %08X\n",
+ hw_data[i].name, hw_data[i].addr, val);
+ }
+
+ return out - buf;
+}
+static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
+
+
+static ssize_t show_hardware(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char * out = buf;
+ int i;
+
+ out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry");
+
+ for (i = 0; i < (sizeof(nic_data) / sizeof(*nic_data)); i++) {
+ u8 tmp8;
+ u16 tmp16;
+ u32 tmp32;
+
+ switch (nic_data[i].size) {
+ case 1:
+ read_nic_byte(dev, nic_data[i].addr, &tmp8);
+ out += sprintf(out, "%30s [%08X] : %02X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp8);
+ break;
+ case 2:
+ read_nic_word(dev, nic_data[i].addr, &tmp16);
+ out += sprintf(out, "%30s [%08X] : %04X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp16);
+ break;
+ case 4:
+ read_nic_dword(dev, nic_data[i].addr, &tmp32);
+ out += sprintf(out, "%30s [%08X] : %08X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp32);
+ break;
+ }
+ }
+ return out - buf;
+}
+static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL);
+
+
+static ssize_t show_memory(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ static unsigned long loop = 0;
+ int len = 0;
+ u32 buffer[4];
+ int i;
+ char line[81];
+
+ if (loop >= 0x30000)
+ loop = 0;
+
+ /* sysfs provides us PAGE_SIZE buffer */
+ while (len < PAGE_SIZE - 128 && loop < 0x30000) {
+
+ if (priv->snapshot[0]) for (i = 0; i < 4; i++)
+ buffer[i] = *(u32 *)SNAPSHOT_ADDR(loop + i * 4);
+ else for (i = 0; i < 4; i++)
+ read_nic_dword(dev, loop + i * 4, &buffer[i]);
+
+ if (priv->dump_raw)
+ len += sprintf(buf + len,
+ "%c%c%c%c"
+ "%c%c%c%c"
+ "%c%c%c%c"
+ "%c%c%c%c",
+ ((u8*)buffer)[0x0],
+ ((u8*)buffer)[0x1],
+ ((u8*)buffer)[0x2],
+ ((u8*)buffer)[0x3],
+ ((u8*)buffer)[0x4],
+ ((u8*)buffer)[0x5],
+ ((u8*)buffer)[0x6],
+ ((u8*)buffer)[0x7],
+ ((u8*)buffer)[0x8],
+ ((u8*)buffer)[0x9],
+ ((u8*)buffer)[0xa],
+ ((u8*)buffer)[0xb],
+ ((u8*)buffer)[0xc],
+ ((u8*)buffer)[0xd],
+ ((u8*)buffer)[0xe],
+ ((u8*)buffer)[0xf]);
+ else
+ len += sprintf(buf + len, "%s\n",
+ snprint_line(line, sizeof(line),
+ (u8*)buffer, 16, loop));
+ loop += 16;
+ }
+
+ return len;
+}
+
+static ssize_t store_memory(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ const char *p = buf;
+
+ if (count < 1)
+ return count;
+
+ if (p[0] == '1' ||
+ (count >= 2 && tolower(p[0]) == 'o' && tolower(p[1]) == 'n')) {
+ IPW_DEBUG_INFO("%s: Setting memory dump to RAW mode.\n",
+ dev->name);
+ priv->dump_raw = 1;
+
+ } else if (p[0] == '0' || (count >= 2 && tolower(p[0]) == 'o' &&
+ tolower(p[1]) == 'f')) {
+ IPW_DEBUG_INFO("%s: Setting memory dump to HEX mode.\n",
+ dev->name);
+ priv->dump_raw = 0;
+
+ } else if (tolower(p[0]) == 'r') {
+ IPW_DEBUG_INFO("%s: Resetting firmware snapshot.\n",
+ dev->name);
+ ipw2100_snapshot_free(priv);
+
+ } else
+ IPW_DEBUG_INFO("%s: Usage: 0|on = HEX, 1|off = RAW, "
+ "reset = clear memory snapshot\n",
+ dev->name);
+
+ return count;
+}
+static DEVICE_ATTR(memory, S_IWUSR|S_IRUGO, show_memory, store_memory);
+
+
+static ssize_t show_ordinals(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ u32 val = 0;
+ int len = 0;
+ u32 val_len;
+ static int loop = 0;
+
+ if (loop >= sizeof(ord_data) / sizeof(*ord_data))
+ loop = 0;
+
+ /* sysfs provides us PAGE_SIZE buffer */
+ while (len < PAGE_SIZE - 128 &&
+ loop < (sizeof(ord_data) / sizeof(*ord_data))) {
+
+ val_len = sizeof(u32);
+
+ if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val,
+ &val_len))
+ len += sprintf(buf + len, "[0x%02X] = ERROR %s\n",
+ ord_data[loop].index,
+ ord_data[loop].desc);
+ else
+ len += sprintf(buf + len, "[0x%02X] = 0x%08X %s\n",
+ ord_data[loop].index, val,
+ ord_data[loop].desc);
+ loop++;
+ }
+
+ return len;
+}
+static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL);
+
+
+static ssize_t show_stats(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char * out = buf;
+
+ out += sprintf(out, "interrupts: %d {tx: %d, rx: %d, other: %d}\n",
+ priv->interrupts, priv->tx_interrupts,
+ priv->rx_interrupts, priv->inta_other);
+ out += sprintf(out, "firmware resets: %d\n", priv->resets);
+ out += sprintf(out, "firmware hangs: %d\n", priv->hangs);
+#ifdef CONFIG_IPW_DEBUG
+ out += sprintf(out, "packet mismatch image: %s\n",
+ priv->snapshot[0] ? "YES" : "NO");
+#endif
+
+ return out - buf;
+}
+static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+
+static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
+{
+ int err;
+
+ if (mode == priv->ieee->iw_mode)
+ return 0;
+
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+
+ switch (mode) {
+ case IW_MODE_INFRA:
+ priv->net_dev->type = ARPHRD_ETHER;
+ break;
+ case IW_MODE_ADHOC:
+ priv->net_dev->type = ARPHRD_ETHER;
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ priv->last_mode = priv->ieee->iw_mode;
+ priv->net_dev->type = ARPHRD_IEEE80211;
+ break;
+#endif /* CONFIG_IPW2100_MONITOR */
+ }
+
+ priv->ieee->iw_mode = mode;
+
+#ifdef CONFIG_PM
+ /* Indicate ipw2100_download_firmware download firmware
+ * from disk instead of memory. */
+ ipw2100_firmware.version = 0;
+#endif
+
+ printk(KERN_INFO "%s: Reseting on mode change.\n",
+ priv->net_dev->name);
+ priv->reset_backoff = 0;
+ schedule_reset(priv);
+
+ return 0;
+}
+
+static ssize_t show_internals(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ int len = 0;
+
+#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" # y "\n", priv-> x)
+
+ if (priv->status & STATUS_ASSOCIATED)
+ len += sprintf(buf + len, "connected: %lu\n",
+ get_seconds() - priv->connect_start);
+ else
+ len += sprintf(buf + len, "not connected\n");
+
+ DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], p);
+ DUMP_VAR(status, 08lx);
+ DUMP_VAR(config, 08lx);
+ DUMP_VAR(capability, 08lx);
+
+ len += sprintf(buf + len, "last_rtc: %lu\n", (unsigned long)priv->last_rtc);
+
+ DUMP_VAR(fatal_error, d);
+ DUMP_VAR(stop_hang_check, d);
+ DUMP_VAR(stop_rf_kill, d);
+ DUMP_VAR(messages_sent, d);
+
+ DUMP_VAR(tx_pend_stat.value, d);
+ DUMP_VAR(tx_pend_stat.hi, d);
+
+ DUMP_VAR(tx_free_stat.value, d);
+ DUMP_VAR(tx_free_stat.lo, d);
+
+ DUMP_VAR(msg_free_stat.value, d);
+ DUMP_VAR(msg_free_stat.lo, d);
+
+ DUMP_VAR(msg_pend_stat.value, d);
+ DUMP_VAR(msg_pend_stat.hi, d);
+
+ DUMP_VAR(fw_pend_stat.value, d);
+ DUMP_VAR(fw_pend_stat.hi, d);
+
+ DUMP_VAR(txq_stat.value, d);
+ DUMP_VAR(txq_stat.lo, d);
+
+ DUMP_VAR(ieee->scans, d);
+ DUMP_VAR(reset_backoff, d);
+
+ return len;
+}
+static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL);
+
+
+static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ u8 bssid[ETH_ALEN];
+ u32 chan = 0;
+ char * out = buf;
+ int length;
+ int ret;
+
+ memset(essid, 0, sizeof(essid));
+ memset(bssid, 0, sizeof(bssid));
+
+ length = IW_ESSID_MAX_SIZE;
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID, essid, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ length = sizeof(bssid);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID,
+ bssid, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ length = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ out += sprintf(out, "ESSID: %s\n", essid);
+ out += sprintf(out, "BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ bssid[0], bssid[1], bssid[2],
+ bssid[3], bssid[4], bssid[5]);
+ out += sprintf(out, "Channel: %d\n", chan);
+
+ return out - buf;
+}
+static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL);
+
+
+#ifdef CONFIG_IPW_DEBUG
+static ssize_t show_debug_level(struct device_driver *d, char *buf)
+{
+ return sprintf(buf, "0x%08X\n", ipw2100_debug_level);
+}
+
+static ssize_t store_debug_level(struct device_driver *d, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ u32 val;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buf)
+ IPW_DEBUG_INFO(DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ipw2100_debug_level = val;
+
+ return strnlen(buf, count);
+}
+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level,
+ store_debug_level);
+#endif /* CONFIG_IPW_DEBUG */
+
+
+static ssize_t show_fatal_error(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char *out = buf;
+ int i;
+
+ if (priv->fatal_error)
+ out += sprintf(out, "0x%08X\n",
+ priv->fatal_error);
+ else
+ out += sprintf(out, "0\n");
+
+ for (i = 1; i <= IPW2100_ERROR_QUEUE; i++) {
+ if (!priv->fatal_errors[(priv->fatal_index - i) %
+ IPW2100_ERROR_QUEUE])
+ continue;
+
+ out += sprintf(out, "%d. 0x%08X\n", i,
+ priv->fatal_errors[(priv->fatal_index - i) %
+ IPW2100_ERROR_QUEUE]);
+ }
+
+ return out - buf;
+}
+
+static ssize_t store_fatal_error(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ schedule_reset(priv);
+ return count;
+}
+static DEVICE_ATTR(fatal_error, S_IWUSR|S_IRUGO, show_fatal_error, store_fatal_error);
+
+
+static ssize_t show_scan_age(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ return sprintf(buf, "%d\n", priv->ieee->scan_age);
+}
+
+static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char buffer[] = "00000000";
+ unsigned long len =
+ (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
+ unsigned long val;
+ char *p = buffer;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ strncpy(buffer, buf, len);
+ buffer[len] = 0;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buffer) {
+ IPW_DEBUG_INFO("%s: user supplied invalid value.\n",
+ dev->name);
+ } else {
+ priv->ieee->scan_age = val;
+ IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age);
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+ return len;
+}
+static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
+
+
+static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ /* 0 - RF kill not enabled
+ 1 - SW based RF kill active (sysfs)
+ 2 - HW based RF kill active
+ 3 - Both HW and SW baed RF kill active */
+ struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data;
+ int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
+ (rf_kill_active(priv) ? 0x2 : 0x0);
+ return sprintf(buf, "%i\n", val);
+}
+
+static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
+{
+ if ((disable_radio ? 1 : 0) ==
+ (priv->status & STATUS_RF_KILL_SW ? 1 : 0))
+ return 0 ;
+
+ IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n",
+ disable_radio ? "OFF" : "ON");
+
+ down(&priv->action_sem);
+
+ if (disable_radio) {
+ priv->status |= STATUS_RF_KILL_SW;
+ ipw2100_down(priv);
+ } else {
+ priv->status &= ~STATUS_RF_KILL_SW;
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by HW switch\n");
+ /* Make sure the RF_KILL check timer is running */
+ priv->stop_rf_kill = 0;
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ HZ);
+ } else
+ schedule_reset(priv);
+ }
+
+ up(&priv->action_sem);
+ return 1;
+}
+
+static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ ipw_radio_kill_sw(priv, buf[0] == '1');
+ return count;
+}
+static DEVICE_ATTR(rf_kill, S_IWUSR|S_IRUGO, show_rf_kill, store_rf_kill);
+
+
+static struct attribute *ipw2100_sysfs_entries[] = {
+ &dev_attr_hardware.attr,
+ &dev_attr_registers.attr,
+ &dev_attr_ordinals.attr,
+ &dev_attr_pci.attr,
+ &dev_attr_stats.attr,
+ &dev_attr_internals.attr,
+ &dev_attr_bssinfo.attr,
+ &dev_attr_memory.attr,
+ &dev_attr_scan_age.attr,
+ &dev_attr_fatal_error.attr,
+ &dev_attr_rf_kill.attr,
+ &dev_attr_cfg.attr,
+ &dev_attr_status.attr,
+ &dev_attr_capability.attr,
+ NULL,
+};
+
+static struct attribute_group ipw2100_attribute_group = {
+ .attrs = ipw2100_sysfs_entries,
+};
+
+
+static int status_queue_allocate(struct ipw2100_priv *priv, int entries)
+{
+ struct ipw2100_status_queue *q = &priv->status_queue;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ q->size = entries * sizeof(struct ipw2100_status);
+ q->drv = (struct ipw2100_status *)pci_alloc_consistent(
+ priv->pci_dev, q->size, &q->nic);
+ if (!q->drv) {
+ IPW_DEBUG_WARNING(
+ "Can not allocate status queue.\n");
+ return -ENOMEM;
+ }
+
+ memset(q->drv, 0, q->size);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static void status_queue_free(struct ipw2100_priv *priv)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->status_queue.drv) {
+ pci_free_consistent(
+ priv->pci_dev, priv->status_queue.size,
+ priv->status_queue.drv, priv->status_queue.nic);
+ priv->status_queue.drv = NULL;
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static int bd_queue_allocate(struct ipw2100_priv *priv,
+ struct ipw2100_bd_queue *q, int entries)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ memset(q, 0, sizeof(struct ipw2100_bd_queue));
+
+ q->entries = entries;
+ q->size = entries * sizeof(struct ipw2100_bd);
+ q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic);
+ if (!q->drv) {
+ IPW_DEBUG_INFO("can't allocate shared memory for buffer descriptors\n");
+ return -ENOMEM;
+ }
+ memset(q->drv, 0, q->size);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static void bd_queue_free(struct ipw2100_priv *priv,
+ struct ipw2100_bd_queue *q)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ if (!q)
+ return;
+
+ if (q->drv) {
+ pci_free_consistent(priv->pci_dev,
+ q->size, q->drv, q->nic);
+ q->drv = NULL;
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void bd_queue_initialize(
+ struct ipw2100_priv *priv, struct ipw2100_bd_queue * q,
+ u32 base, u32 size, u32 r, u32 w)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ IPW_DEBUG_INFO("initializing bd queue at virt=%p, phys=%08x\n", q->drv, (u32)q->nic);
+
+ write_register(priv->net_dev, base, q->nic);
+ write_register(priv->net_dev, size, q->entries);
+ write_register(priv->net_dev, r, q->oldest);
+ write_register(priv->net_dev, w, q->next);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void ipw2100_kill_workqueue(struct ipw2100_priv *priv)
+{
+ if (priv->workqueue) {
+ priv->stop_rf_kill = 1;
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->reset_work);
+ cancel_delayed_work(&priv->security_work);
+ cancel_delayed_work(&priv->wx_event_work);
+ cancel_delayed_work(&priv->hang_check);
+ cancel_delayed_work(&priv->rf_kill);
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ }
+}
+
+static int ipw2100_tx_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+ void *v;
+ dma_addr_t p;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = bd_queue_allocate(priv, &priv->tx_queue, TX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: failed bd_queue_allocate\n",
+ priv->net_dev->name);
+ return err;
+ }
+
+ priv->tx_buffers = (struct ipw2100_tx_packet *)kmalloc(
+ TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet),
+ GFP_ATOMIC);
+ if (!priv->tx_buffers) {
+ printk(KERN_ERR DRV_NAME ": %s: alloc failed form tx buffers.\n",
+ priv->net_dev->name);
+ bd_queue_free(priv, &priv->tx_queue);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ v = pci_alloc_consistent(
+ priv->pci_dev, sizeof(struct ipw2100_data_header), &p);
+ if (!v) {
+ printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for tx "
+ "buffers.\n", priv->net_dev->name);
+ err = -ENOMEM;
+ break;
+ }
+
+ priv->tx_buffers[i].type = DATA;
+ priv->tx_buffers[i].info.d_struct.data = (struct ipw2100_data_header*)v;
+ priv->tx_buffers[i].info.d_struct.data_phys = p;
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+
+ if (i == TX_PENDED_QUEUE_LENGTH)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_data_header),
+ priv->tx_buffers[j].info.d_struct.data,
+ priv->tx_buffers[j].info.d_struct.data_phys);
+ }
+
+ kfree(priv->tx_buffers);
+ priv->tx_buffers = NULL;
+
+ return err;
+}
+
+static void ipw2100_tx_initialize(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ /*
+ * reinitialize packet info lists
+ */
+ INIT_LIST_HEAD(&priv->fw_pend_list);
+ INIT_STAT(&priv->fw_pend_stat);
+
+ /*
+ * reinitialize lists
+ */
+ INIT_LIST_HEAD(&priv->tx_pend_list);
+ INIT_LIST_HEAD(&priv->tx_free_list);
+ INIT_STAT(&priv->tx_pend_stat);
+ INIT_STAT(&priv->tx_free_stat);
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ /* We simply drop any SKBs that have been queued for
+ * transmit */
+ if (priv->tx_buffers[i].info.d_struct.txb) {
+ ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb);
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+
+ list_add_tail(&priv->tx_buffers[i].list, &priv->tx_free_list);
+ }
+
+ SET_STAT(&priv->tx_free_stat, i);
+
+ priv->tx_queue.oldest = 0;
+ priv->tx_queue.available = priv->tx_queue.entries;
+ priv->tx_queue.next = 0;
+ INIT_STAT(&priv->txq_stat);
+ SET_STAT(&priv->txq_stat, priv->tx_queue.available);
+
+ bd_queue_initialize(priv, &priv->tx_queue,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX);
+
+ IPW_DEBUG_INFO("exit\n");
+
+}
+
+static void ipw2100_tx_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ bd_queue_free(priv, &priv->tx_queue);
+
+ if (!priv->tx_buffers)
+ return;
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ if (priv->tx_buffers[i].info.d_struct.txb) {
+ ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb);
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+ if (priv->tx_buffers[i].info.d_struct.data)
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_data_header),
+ priv->tx_buffers[i].info.d_struct.data,
+ priv->tx_buffers[i].info.d_struct.data_phys);
+ }
+
+ kfree(priv->tx_buffers);
+ priv->tx_buffers = NULL;
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+
+
+static int ipw2100_rx_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = bd_queue_allocate(priv, &priv->rx_queue, RX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_INFO("failed bd_queue_allocate\n");
+ return err;
+ }
+
+ err = status_queue_allocate(priv, RX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_INFO("failed status_queue_allocate\n");
+ bd_queue_free(priv, &priv->rx_queue);
+ return err;
+ }
+
+ /*
+ * allocate packets
+ */
+ priv->rx_buffers = (struct ipw2100_rx_packet *)
+ kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet),
+ GFP_KERNEL);
+ if (!priv->rx_buffers) {
+ IPW_DEBUG_INFO("can't allocate rx packet buffer table\n");
+
+ bd_queue_free(priv, &priv->rx_queue);
+
+ status_queue_free(priv);
+
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < RX_QUEUE_LENGTH; i++) {
+ struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+ err = ipw2100_alloc_skb(priv, packet);
+ if (unlikely(err)) {
+ err = -ENOMEM;
+ break;
+ }
+
+ /* The BD holds the cache aligned address */
+ priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+ priv->rx_queue.drv[i].buf_length = IPW_RX_NIC_BUFFER_LENGTH;
+ priv->status_queue.drv[i].status_fields = 0;
+ }
+
+ if (i == RX_QUEUE_LENGTH)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_unmap_single(priv->pci_dev, priv->rx_buffers[j].dma_addr,
+ sizeof(struct ipw2100_rx_packet),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(priv->rx_buffers[j].skb);
+ }
+
+ kfree(priv->rx_buffers);
+ priv->rx_buffers = NULL;
+
+ bd_queue_free(priv, &priv->rx_queue);
+
+ status_queue_free(priv);
+
+ return err;
+}
+
+static void ipw2100_rx_initialize(struct ipw2100_priv *priv)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ priv->rx_queue.oldest = 0;
+ priv->rx_queue.available = priv->rx_queue.entries - 1;
+ priv->rx_queue.next = priv->rx_queue.entries - 1;
+
+ INIT_STAT(&priv->rxq_stat);
+ SET_STAT(&priv->rxq_stat, priv->rx_queue.available);
+
+ bd_queue_initialize(priv, &priv->rx_queue,
+ IPW_MEM_HOST_SHARED_RX_BD_BASE,
+ IPW_MEM_HOST_SHARED_RX_BD_SIZE,
+ IPW_MEM_HOST_SHARED_RX_READ_INDEX,
+ IPW_MEM_HOST_SHARED_RX_WRITE_INDEX);
+
+ /* set up the status queue */
+ write_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_STATUS_BASE,
+ priv->status_queue.nic);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void ipw2100_rx_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ bd_queue_free(priv, &priv->rx_queue);
+ status_queue_free(priv);
+
+ if (!priv->rx_buffers)
+ return;
+
+ for (i = 0; i < RX_QUEUE_LENGTH; i++) {
+ if (priv->rx_buffers[i].rxp) {
+ pci_unmap_single(priv->pci_dev,
+ priv->rx_buffers[i].dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(priv->rx_buffers[i].skb);
+ }
+ }
+
+ kfree(priv->rx_buffers);
+ priv->rx_buffers = NULL;
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
+{
+ u32 length = ETH_ALEN;
+ u8 mac[ETH_ALEN];
+
+ int err;
+
+ err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC,
+ mac, &length);
+ if (err) {
+ IPW_DEBUG_INFO("MAC address read failed\n");
+ return -EIO;
+ }
+ IPW_DEBUG_INFO("card MAC is %02X:%02X:%02X:%02X:%02X:%02X\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ memcpy(priv->net_dev->dev_addr, mac, ETH_ALEN);
+
+ return 0;
+}
+
+/********************************************************************
+ *
+ * Firmware Commands
+ *
+ ********************************************************************/
+
+static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = ADAPTER_ADDRESS,
+ .host_command_sequence = 0,
+ .host_command_length = ETH_ALEN
+ };
+ int err;
+
+ IPW_DEBUG_HC("SET_MAC_ADDRESS\n");
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->config & CFG_CUSTOM_MAC) {
+ memcpy(cmd.host_command_parameters, priv->mac_addr,
+ ETH_ALEN);
+ memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
+ } else
+ memcpy(cmd.host_command_parameters, priv->net_dev->dev_addr,
+ ETH_ALEN);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ IPW_DEBUG_INFO("exit\n");
+ return err;
+}
+
+static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = PORT_TYPE,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(u32)
+ };
+ int err;
+
+ switch (port_type) {
+ case IW_MODE_INFRA:
+ cmd.host_command_parameters[0] = IPW_BSS;
+ break;
+ case IW_MODE_ADHOC:
+ cmd.host_command_parameters[0] = IPW_IBSS;
+ break;
+ }
+
+ IPW_DEBUG_HC("PORT_TYPE: %s\n",
+ port_type == IPW_IBSS ? "Ad-Hoc" : "Managed");
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+
+static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = CHANNEL,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(u32)
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = channel;
+
+ IPW_DEBUG_HC("CHANNEL: %d\n", channel);
+
+ /* If BSS then we don't support channel selection */
+ if (priv->ieee->iw_mode == IW_MODE_INFRA)
+ return 0;
+
+ if ((channel != 0) &&
+ ((channel < REG_MIN_CHANNEL) || (channel > REG_MAX_CHANNEL)))
+ return -EINVAL;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ IPW_DEBUG_INFO("Failed to set channel to %d",
+ channel);
+ return err;
+ }
+
+ if (channel)
+ priv->config |= CFG_STATIC_CHANNEL;
+ else
+ priv->config &= ~CFG_STATIC_CHANNEL;
+
+ priv->channel = channel;
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SYSTEM_CONFIG,
+ .host_command_sequence = 0,
+ .host_command_length = 12,
+ };
+ u32 ibss_mask, len = sizeof(u32);
+ int err;
+
+ /* Set system configuration */
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC)
+ cmd.host_command_parameters[0] |= IPW_CFG_IBSS_AUTO_START;
+
+ cmd.host_command_parameters[0] |= IPW_CFG_IBSS_MASK |
+ IPW_CFG_BSS_MASK |
+ IPW_CFG_802_1x_ENABLE;
+
+ if (!(priv->config & CFG_LONG_PREAMBLE))
+ cmd.host_command_parameters[0] |= IPW_CFG_PREAMBLE_AUTO;
+
+ err = ipw2100_get_ordinal(priv,
+ IPW_ORD_EEPROM_IBSS_11B_CHANNELS,
+ &ibss_mask, &len);
+ if (err)
+ ibss_mask = IPW_IBSS_11B_DEFAULT_MASK;
+
+ cmd.host_command_parameters[1] = REG_CHANNEL_MASK;
+ cmd.host_command_parameters[2] = REG_CHANNEL_MASK & ibss_mask;
+
+ /* 11b only */
+ /*cmd.host_command_parameters[0] |= DIVERSITY_ANTENNA_A;*/
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+/* If IPv6 is configured in the kernel then we don't want to filter out all
+ * of the multicast packets as IPv6 needs some. */
+#if !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+ cmd.host_command = ADD_MULTICAST;
+ cmd.host_command_sequence = 0;
+ cmd.host_command_length = 0;
+
+ ipw2100_hw_send_command(priv, &cmd);
+#endif
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = BASIC_TX_RATES,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = rate & TX_RATE_MASK;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ /* Set BASIC TX Rate first */
+ ipw2100_hw_send_command(priv, &cmd);
+
+ /* Set TX Rate */
+ cmd.host_command = TX_RATES;
+ ipw2100_hw_send_command(priv, &cmd);
+
+ /* Set MSDU TX Rate */
+ cmd.host_command = MSDU_TX_RATES;
+ ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ priv->tx_rates = rate;
+
+ return 0;
+}
+
+static int ipw2100_set_power_mode(struct ipw2100_priv *priv,
+ int power_level)
+{
+ struct host_command cmd = {
+ .host_command = POWER_MODE,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = power_level;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ if (power_level == IPW_POWER_MODE_CAM)
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ else
+ priv->power_mode = IPW_POWER_ENABLED | power_level;
+
+#ifdef CONFIG_IPW2100_TX_POWER
+ if (priv->port_type == IBSS &&
+ priv->adhoc_power != DFTL_IBSS_TX_POWER) {
+ /* Set beacon interval */
+ cmd.host_command = TX_POWER_INDEX;
+ cmd.host_command_parameters[0] = (u32)priv->adhoc_power;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+ }
+#endif
+
+ return 0;
+}
+
+
+static int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold)
+{
+ struct host_command cmd = {
+ .host_command = RTS_THRESHOLD,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ if (threshold & RTS_DISABLED)
+ cmd.host_command_parameters[0] = MAX_RTS_THRESHOLD;
+ else
+ cmd.host_command_parameters[0] = threshold & ~RTS_DISABLED;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->rts_threshold = threshold;
+
+ return 0;
+}
+
+#if 0
+int ipw2100_set_fragmentation_threshold(struct ipw2100_priv *priv,
+ u32 threshold, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = FRAG_THRESHOLD,
+ .host_command_sequence = 0,
+ .host_command_length = 4,
+ .host_command_parameters[0] = 0,
+ };
+ int err;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (threshold == 0)
+ threshold = DEFAULT_FRAG_THRESHOLD;
+ else {
+ threshold = max(threshold, MIN_FRAG_THRESHOLD);
+ threshold = min(threshold, MAX_FRAG_THRESHOLD);
+ }
+
+ cmd.host_command_parameters[0] = threshold;
+
+ IPW_DEBUG_HC("FRAG_THRESHOLD: %u\n", threshold);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ if (!err)
+ priv->frag_threshold = threshold;
+
+ return err;
+}
+#endif
+
+static int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry)
+{
+ struct host_command cmd = {
+ .host_command = SHORT_RETRY_LIMIT,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = retry;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->short_retry_limit = retry;
+
+ return 0;
+}
+
+static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry)
+{
+ struct host_command cmd = {
+ .host_command = LONG_RETRY_LIMIT,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = retry;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->long_retry_limit = retry;
+
+ return 0;
+}
+
+
+static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = MANDATORY_BSSID,
+ .host_command_sequence = 0,
+ .host_command_length = (bssid == NULL) ? 0 : ETH_ALEN
+ };
+ int err;
+
+#ifdef CONFIG_IPW_DEBUG
+ if (bssid != NULL)
+ IPW_DEBUG_HC(
+ "MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4],
+ bssid[5]);
+ else
+ IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n");
+#endif
+ /* if BSSID is empty then we disable mandatory bssid mode */
+ if (bssid != NULL)
+ memcpy((u8 *)cmd.host_command_parameters, bssid, ETH_ALEN);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+#ifdef CONFIG_IEEE80211_WPA
+static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = DISASSOCIATION_BSSID,
+ .host_command_sequence = 0,
+ .host_command_length = ETH_ALEN
+ };
+ int err;
+ int len;
+
+ IPW_DEBUG_HC("DISASSOCIATION_BSSID\n");
+
+ len = ETH_ALEN;
+ /* The Firmware currently ignores the BSSID and just disassociates from
+ * the currently associated AP -- but in the off chance that a future
+ * firmware does use the BSSID provided here, we go ahead and try and
+ * set it to the currently associated AP's BSSID */
+ memcpy(cmd.host_command_parameters, priv->bssid, ETH_ALEN);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ return err;
+}
+#endif
+
+/*
+ * Pseudo code for setting up wpa_frame:
+ */
+#if 0
+void x(struct ieee80211_assoc_frame *wpa_assoc)
+{
+ struct ipw2100_wpa_assoc_frame frame;
+ frame->fixed_ie_mask = IPW_WPA_CAPABILTIES |
+ IPW_WPA_LISTENINTERVAL |
+ IPW_WPA_AP_ADDRESS;
+ frame->capab_info = wpa_assoc->capab_info;
+ frame->lisen_interval = wpa_assoc->listent_interval;
+ memcpy(frame->current_ap, wpa_assoc->current_ap, ETH_ALEN);
+
+ /* UNKNOWN -- I'm not postivive about this part; don't have any WPA
+ * setup here to test it with.
+ *
+ * Walk the IEs in the wpa_assoc and figure out the total size of all
+ * that data. Stick that into frame->var_ie_len. Then memcpy() all of
+ * the IEs from wpa_frame into frame.
+ */
+ frame->var_ie_len = calculate_ie_len(wpa_assoc);
+ memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len);
+
+ ipw2100_set_wpa_ie(priv, &frame, 0);
+}
+#endif
+
+
+
+
+static int ipw2100_set_wpa_ie(struct ipw2100_priv *,
+ struct ipw2100_wpa_assoc_frame *, int)
+__attribute__ ((unused));
+
+static int ipw2100_set_wpa_ie(struct ipw2100_priv *priv,
+ struct ipw2100_wpa_assoc_frame *wpa_frame,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SET_WPA_IE,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct ipw2100_wpa_assoc_frame),
+ };
+ int err;
+
+ IPW_DEBUG_HC("SET_WPA_IE\n");
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ memcpy(cmd.host_command_parameters, wpa_frame,
+ sizeof(struct ipw2100_wpa_assoc_frame));
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ if (ipw2100_enable_adapter(priv))
+ err = -EIO;
+ }
+
+ return err;
+}
+
+struct security_info_params {
+ u32 allowed_ciphers;
+ u16 version;
+ u8 auth_mode;
+ u8 replay_counters_number;
+ u8 unicast_using_group;
+} __attribute__ ((packed));
+
+static int ipw2100_set_security_information(struct ipw2100_priv *priv,
+ int auth_mode,
+ int security_level,
+ int unicast_using_group,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SET_SECURITY_INFORMATION,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct security_info_params)
+ };
+ struct security_info_params *security =
+ (struct security_info_params *)&cmd.host_command_parameters;
+ int err;
+ memset(security, 0, sizeof(*security));
+
+ /* If shared key AP authentication is turned on, then we need to
+ * configure the firmware to try and use it.
+ *
+ * Actual data encryption/decryption is handled by the host. */
+ security->auth_mode = auth_mode;
+ security->unicast_using_group = unicast_using_group;
+
+ switch (security_level) {
+ default:
+ case SEC_LEVEL_0:
+ security->allowed_ciphers = IPW_NONE_CIPHER;
+ break;
+ case SEC_LEVEL_1:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER;
+ break;
+ case SEC_LEVEL_2:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_TKIP_CIPHER;
+ break;
+ case SEC_LEVEL_2_CKIP:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_CKIP_CIPHER;
+ break;
+ case SEC_LEVEL_3:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_TKIP_CIPHER | IPW_CCMP_CIPHER;
+ break;
+ }
+
+ IPW_DEBUG_HC(
+ "SET_SECURITY_INFORMATION: auth:%d cipher:0x%02X (level %d)\n",
+ security->auth_mode, security->allowed_ciphers, security_level);
+
+ security->replay_counters_number = 0;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+static int ipw2100_set_tx_power(struct ipw2100_priv *priv,
+ u32 tx_power)
+{
+ struct host_command cmd = {
+ .host_command = TX_POWER_INDEX,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err = 0;
+
+ cmd.host_command_parameters[0] = tx_power;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC)
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (!err)
+ priv->tx_power = tx_power;
+
+ return 0;
+}
+
+static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv,
+ u32 interval, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = BEACON_INTERVAL,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = interval;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+void ipw2100_queues_initialize(struct ipw2100_priv *priv)
+{
+ ipw2100_tx_initialize(priv);
+ ipw2100_rx_initialize(priv);
+ ipw2100_msg_initialize(priv);
+}
+
+void ipw2100_queues_free(struct ipw2100_priv *priv)
+{
+ ipw2100_tx_free(priv);
+ ipw2100_rx_free(priv);
+ ipw2100_msg_free(priv);
+}
+
+int ipw2100_queues_allocate(struct ipw2100_priv *priv)
+{
+ if (ipw2100_tx_allocate(priv) ||
+ ipw2100_rx_allocate(priv) ||
+ ipw2100_msg_allocate(priv))
+ goto fail;
+
+ return 0;
+
+ fail:
+ ipw2100_tx_free(priv);
+ ipw2100_rx_free(priv);
+ ipw2100_msg_free(priv);
+ return -ENOMEM;
+}
+
+#define IPW_PRIVACY_CAPABLE 0x0008
+
+static int ipw2100_set_wep_flags(struct ipw2100_priv *priv, u32 flags,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = WEP_FLAGS,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = flags;
+
+ IPW_DEBUG_HC("WEP_FLAGS: flags = 0x%08X\n", flags);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+struct ipw2100_wep_key {
+ u8 idx;
+ u8 len;
+ u8 key[13];
+};
+
+/* Macros to ease up priting WEP keys */
+#define WEP_FMT_64 "%02X%02X%02X%02X-%02X"
+#define WEP_FMT_128 "%02X%02X%02X%02X-%02X%02X%02X%02X-%02X%02X%02X"
+#define WEP_STR_64(x) x[0],x[1],x[2],x[3],x[4]
+#define WEP_STR_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10]
+
+
+/**
+ * Set a the wep key
+ *
+ * @priv: struct to work on
+ * @idx: index of the key we want to set
+ * @key: ptr to the key data to set
+ * @len: length of the buffer at @key
+ * @batch_mode: FIXME perform the operation in batch mode, not
+ * disabling the device.
+ *
+ * @returns 0 if OK, < 0 errno code on error.
+ *
+ * Fill out a command structure with the new wep key, length an
+ * index and send it down the wire.
+ */
+static int ipw2100_set_key(struct ipw2100_priv *priv,
+ int idx, char *key, int len, int batch_mode)
+{
+ int keylen = len ? (len <= 5 ? 5 : 13) : 0;
+ struct host_command cmd = {
+ .host_command = WEP_KEY_INFO,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct ipw2100_wep_key),
+ };
+ struct ipw2100_wep_key *wep_key = (void*)cmd.host_command_parameters;
+ int err;
+
+ IPW_DEBUG_HC("WEP_KEY_INFO: index = %d, len = %d/%d\n",
+ idx, keylen, len);
+
+ /* NOTE: We don't check cached values in case the firmware was reset
+ * or some other problem is occuring. If the user is setting the key,
+ * then we push the change */
+
+ wep_key->idx = idx;
+ wep_key->len = keylen;
+
+ if (keylen) {
+ memcpy(wep_key->key, key, len);
+ memset(wep_key->key + len, 0, keylen - len);
+ }
+
+ /* Will be optimized out on debug not being configured in */
+ if (keylen == 0)
+ IPW_DEBUG_WEP("%s: Clearing key %d\n",
+ priv->net_dev->name, wep_key->idx);
+ else if (keylen == 5)
+ IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_64 "\n",
+ priv->net_dev->name, wep_key->idx, wep_key->len,
+ WEP_STR_64(wep_key->key));
+ else
+ IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_128
+ "\n",
+ priv->net_dev->name, wep_key->idx, wep_key->len,
+ WEP_STR_128(wep_key->key));
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ /* FIXME: IPG: shouldn't this prink be in _disable_adapter()? */
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ int err2 = ipw2100_enable_adapter(priv);
+ if (err == 0)
+ err = err2;
+ }
+ return err;
+}
+
+static int ipw2100_set_key_index(struct ipw2100_priv *priv,
+ int idx, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = WEP_KEY_INDEX,
+ .host_command_sequence = 0,
+ .host_command_length = 4,
+ .host_command_parameters = { idx },
+ };
+ int err;
+
+ IPW_DEBUG_HC("WEP_KEY_INDEX: index = %d\n", idx);
+
+ if (idx < 0 || idx > 3)
+ return -EINVAL;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+
+static int ipw2100_configure_security(struct ipw2100_priv *priv,
+ int batch_mode)
+{
+ int i, err, auth_mode, sec_level, use_group;
+
+ if (!(priv->status & STATUS_RUNNING))
+ return 0;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (!priv->sec.enabled) {
+ err = ipw2100_set_security_information(
+ priv, IPW_AUTH_OPEN, SEC_LEVEL_0, 0, 1);
+ } else {
+ auth_mode = IPW_AUTH_OPEN;
+ if ((priv->sec.flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode == WLAN_AUTH_SHARED_KEY))
+ auth_mode = IPW_AUTH_SHARED;
+
+ sec_level = SEC_LEVEL_0;
+ if (priv->sec.flags & SEC_LEVEL)
+ sec_level = priv->sec.level;
+
+ use_group = 0;
+ if (priv->sec.flags & SEC_UNICAST_GROUP)
+ use_group = priv->sec.unicast_uses_group;
+
+ err = ipw2100_set_security_information(
+ priv, auth_mode, sec_level, use_group, 1);
+ }
+
+ if (err)
+ goto exit;
+
+ if (priv->sec.enabled) {
+ for (i = 0; i < 4; i++) {
+ if (!(priv->sec.flags & (1 << i))) {
+ memset(priv->sec.keys[i], 0, WEP_KEY_LEN);
+ priv->sec.key_sizes[i] = 0;
+ } else {
+ err = ipw2100_set_key(priv, i,
+ priv->sec.keys[i],
+ priv->sec.key_sizes[i],
+ 1);
+ if (err)
+ goto exit;
+ }
+ }
+
+ ipw2100_set_key_index(priv, priv->ieee->tx_keyidx, 1);
+ }
+
+ /* Always enable privacy so the Host can filter WEP packets if
+ * encrypted data is sent up */
+ err = ipw2100_set_wep_flags(
+ priv, priv->sec.enabled ? IPW_PRIVACY_CAPABLE : 0, 1);
+ if (err)
+ goto exit;
+
+ priv->status &= ~STATUS_SECURITY_UPDATED;
+
+ exit:
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+static void ipw2100_security_work(struct ipw2100_priv *priv)
+{
+ /* If we happen to have reconnected before we get a chance to
+ * process this, then update the security settings--which causes
+ * a disassociation to occur */
+ if (!(priv->status & STATUS_ASSOCIATED) &&
+ priv->status & STATUS_SECURITY_UPDATED)
+ ipw2100_configure_security(priv, 0);
+}
+
+static void shim__set_security(struct net_device *dev,
+ struct ieee80211_security *sec)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int i, force_update = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED))
+ goto done;
+
+ for (i = 0; i < 4; i++) {
+ if (sec->flags & (1 << i)) {
+ priv->sec.key_sizes[i] = sec->key_sizes[i];
+ if (sec->key_sizes[i] == 0)
+ priv->sec.flags &= ~(1 << i);
+ else
+ memcpy(priv->sec.keys[i], sec->keys[i],
+ sec->key_sizes[i]);
+ priv->sec.flags |= (1 << i);
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+ }
+
+ if ((sec->flags & SEC_ACTIVE_KEY) &&
+ priv->sec.active_key != sec->active_key) {
+ if (sec->active_key <= 3) {
+ priv->sec.active_key = sec->active_key;
+ priv->sec.flags |= SEC_ACTIVE_KEY;
+ } else
+ priv->sec.flags &= ~SEC_ACTIVE_KEY;
+
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if ((sec->flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode != sec->auth_mode)) {
+ priv->sec.auth_mode = sec->auth_mode;
+ priv->sec.flags |= SEC_AUTH_MODE;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if (sec->flags & SEC_ENABLED &&
+ priv->sec.enabled != sec->enabled) {
+ priv->sec.flags |= SEC_ENABLED;
+ priv->sec.enabled = sec->enabled;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ force_update = 1;
+ }
+
+ if (sec->flags & SEC_LEVEL &&
+ priv->sec.level != sec->level) {
+ priv->sec.level = sec->level;
+ priv->sec.flags |= SEC_LEVEL;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ IPW_DEBUG_WEP("Security flags: %c %c%c%c%c %c%c%c%c\n",
+ priv->sec.flags & (1<<8) ? '1' : '0',
+ priv->sec.flags & (1<<7) ? '1' : '0',
+ priv->sec.flags & (1<<6) ? '1' : '0',
+ priv->sec.flags & (1<<5) ? '1' : '0',
+ priv->sec.flags & (1<<4) ? '1' : '0',
+ priv->sec.flags & (1<<3) ? '1' : '0',
+ priv->sec.flags & (1<<2) ? '1' : '0',
+ priv->sec.flags & (1<<1) ? '1' : '0',
+ priv->sec.flags & (1<<0) ? '1' : '0');
+
+/* As a temporary work around to enable WPA until we figure out why
+ * wpa_supplicant toggles the security capability of the driver, which
+ * forces a disassocation with force_update...
+ *
+ * if (force_update || !(priv->status & STATUS_ASSOCIATED))*/
+ if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
+ ipw2100_configure_security(priv, 0);
+done:
+ up(&priv->action_sem);
+}
+
+static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
+{
+ int err;
+ int batch_mode = 1;
+ u8 *bssid;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ err = ipw2100_set_channel(priv, priv->channel, batch_mode);
+ if (err)
+ return err;
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+ }
+#endif /* CONFIG_IPW2100_MONITOR */
+
+ err = ipw2100_read_mac_address(priv);
+ if (err)
+ return -EIO;
+
+ err = ipw2100_set_mac_address(priv, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_port_type(priv, priv->ieee->iw_mode, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ err = ipw2100_set_channel(priv, priv->channel, batch_mode);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_system_config(priv, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_tx_rates(priv, priv->tx_rates, batch_mode);
+ if (err)
+ return err;
+
+ /* Default to power mode OFF */
+ err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM);
+ if (err)
+ return err;
+
+ err = ipw2100_set_rts_threshold(priv, priv->rts_threshold);
+ if (err)
+ return err;
+
+ if (priv->config & CFG_STATIC_BSSID)
+ bssid = priv->bssid;
+ else
+ bssid = NULL;
+ err = ipw2100_set_mandatory_bssid(priv, bssid, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->config & CFG_STATIC_ESSID)
+ err = ipw2100_set_essid(priv, priv->essid, priv->essid_len,
+ batch_mode);
+ else
+ err = ipw2100_set_essid(priv, NULL, 0, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_configure_security(priv, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ err = ipw2100_set_ibss_beacon_interval(
+ priv, priv->beacon_interval, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_tx_power(priv, priv->tx_power);
+ if (err)
+ return err;
+ }
+
+ /*
+ err = ipw2100_set_fragmentation_threshold(
+ priv, priv->frag_threshold, batch_mode);
+ if (err)
+ return err;
+ */
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+/*************************************************************************
+ *
+ * EXTERNALLY CALLED METHODS
+ *
+ *************************************************************************/
+
+/* This method is called by the network layer -- not to be confused with
+ * ipw2100_set_mac_address() declared above called by this driver (and this
+ * method as well) to talk to the firmware */
+static int ipw2100_set_address(struct net_device *dev, void *p)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct sockaddr *addr = p;
+ int err = 0;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ down(&priv->action_sem);
+
+ priv->config |= CFG_CUSTOM_MAC;
+ memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
+
+ err = ipw2100_set_mac_address(priv, 0);
+ if (err)
+ goto done;
+
+ priv->reset_backoff = 0;
+ up(&priv->action_sem);
+ ipw2100_reset_adapter(priv);
+ return 0;
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_open(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+ IPW_DEBUG_INFO("dev->open\n");
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ if (priv->status & STATUS_ASSOCIATED) {
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+ }
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ return 0;
+}
+
+static int ipw2100_close(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->status & STATUS_ASSOCIATED)
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ /* Flush the TX queue ... */
+ while (!list_empty(&priv->tx_pend_list)) {
+ element = priv->tx_pend_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ list_del(element);
+ DEC_STAT(&priv->tx_pend_stat);
+
+ ieee80211_txb_free(packet->info.d_struct.txb);
+ packet->info.d_struct.txb = NULL;
+
+ list_add_tail(element, &priv->tx_free_list);
+ INC_STAT(&priv->tx_free_stat);
+ }
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+
+/*
+ * TODO: Fix this function... its just wrong
+ */
+static void ipw2100_tx_timeout(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ priv->ieee->stats.tx_errors++;
+
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ return;
+#endif
+
+ IPW_DEBUG_INFO("%s: TX timed out. Scheduling firmware restart.\n",
+ dev->name);
+ schedule_reset(priv);
+}
+
+
+/*
+ * TODO: reimplement it so that it reads statistics
+ * from the adapter using ordinal tables
+ * instead of/in addition to collecting them
+ * in the driver
+ */
+static struct net_device_stats *ipw2100_stats(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ return &priv->ieee->stats;
+}
+
+/* Support for wpa_supplicant. Will be replaced with WEXT once
+ * they get WPA support. */
+#ifdef CONFIG_IEEE80211_WPA
+
+/* following definitions must match definitions in driver_ipw2100.c */
+
+#define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
+
+#define IPW2100_CMD_SET_WPA_PARAM 1
+#define IPW2100_CMD_SET_WPA_IE 2
+#define IPW2100_CMD_SET_ENCRYPTION 3
+#define IPW2100_CMD_MLME 4
+
+#define IPW2100_PARAM_WPA_ENABLED 1
+#define IPW2100_PARAM_TKIP_COUNTERMEASURES 2
+#define IPW2100_PARAM_DROP_UNENCRYPTED 3
+#define IPW2100_PARAM_PRIVACY_INVOKED 4
+#define IPW2100_PARAM_AUTH_ALGS 5
+#define IPW2100_PARAM_IEEE_802_1X 6
+
+#define IPW2100_MLME_STA_DEAUTH 1
+#define IPW2100_MLME_STA_DISASSOC 2
+
+#define IPW2100_CRYPT_ERR_UNKNOWN_ALG 2
+#define IPW2100_CRYPT_ERR_UNKNOWN_ADDR 3
+#define IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define IPW2100_CRYPT_ERR_KEY_SET_FAILED 5
+#define IPW2100_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define IPW2100_CRYPT_ERR_CARD_CONF_FAILED 7
+
+#define IPW2100_CRYPT_ALG_NAME_LEN 16
+
+struct ipw2100_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u8 name;
+ u32 value;
+ } wpa_param;
+ struct {
+ u32 len;
+ u8 *data;
+ } wpa_ie;
+ struct{
+ int command;
+ int reason_code;
+ } mlme;
+ struct {
+ u8 alg[IPW2100_CRYPT_ALG_NAME_LEN];
+ u8 set_tx;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+
+ } u;
+};
+
+/* end of driver_ipw2100.c code */
+
+static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value){
+
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_security sec = {
+ .flags = SEC_LEVEL | SEC_ENABLED,
+ };
+ int ret = 0;
+
+ ieee->wpa_enabled = value;
+
+ if (value){
+ sec.level = SEC_LEVEL_3;
+ sec.enabled = 1;
+ } else {
+ sec.level = SEC_LEVEL_0;
+ sec.enabled = 0;
+ }
+
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+ else
+ ret = -EOPNOTSUPP;
+
+ return ret;
+}
+
+#define AUTH_ALG_OPEN_SYSTEM 0x1
+#define AUTH_ALG_SHARED_KEY 0x2
+
+static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value){
+
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_security sec = {
+ .flags = SEC_AUTH_MODE,
+ };
+ int ret = 0;
+
+ if (value & AUTH_ALG_SHARED_KEY){
+ sec.auth_mode = WLAN_AUTH_SHARED_KEY;
+ ieee->open_wep = 0;
+ } else {
+ sec.auth_mode = WLAN_AUTH_OPEN;
+ ieee->open_wep = 1;
+ }
+
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+ else
+ ret = -EOPNOTSUPP;
+
+ return ret;
+}
+
+
+static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int ret=0;
+
+ switch(name){
+ case IPW2100_PARAM_WPA_ENABLED:
+ ret = ipw2100_wpa_enable(priv, value);
+ break;
+
+ case IPW2100_PARAM_TKIP_COUNTERMEASURES:
+ priv->ieee->tkip_countermeasures=value;
+ break;
+
+ case IPW2100_PARAM_DROP_UNENCRYPTED:
+ priv->ieee->drop_unencrypted=value;
+ break;
+
+ case IPW2100_PARAM_PRIVACY_INVOKED:
+ priv->ieee->privacy_invoked=value;
+ break;
+
+ case IPW2100_PARAM_AUTH_ALGS:
+ ret = ipw2100_wpa_set_auth_algs(priv, value);
+ break;
+
+ case IPW2100_PARAM_IEEE_802_1X:
+ priv->ieee->ieee802_1x=value;
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n",
+ dev->name, name);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int ret=0;
+
+ switch(command){
+ case IPW2100_MLME_STA_DEAUTH:
+ // silently ignore
+ break;
+
+ case IPW2100_MLME_STA_DISASSOC:
+ ipw2100_disassociate_bssid(priv);
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n",
+ dev->name, command);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+
+void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
+ char *wpa_ie, int wpa_ie_len){
+
+ struct ipw2100_wpa_assoc_frame frame;
+
+ frame.fixed_ie_mask = 0;
+
+ /* copy WPA IE */
+ memcpy(frame.var_ie, wpa_ie, wpa_ie_len);
+ frame.var_ie_len = wpa_ie_len;
+
+ /* make sure WPA is enabled */
+ ipw2100_wpa_enable(priv, 1);
+ ipw2100_set_wpa_ie(priv, &frame, 0);
+}
+
+
+static int ipw2100_wpa_set_wpa_ie(struct net_device *dev,
+ struct ipw2100_param *param, int plen){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee;
+ u8 *buf;
+
+ if (! ieee->wpa_enabled)
+ return -EOPNOTSUPP;
+
+ if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
+ (param->u.wpa_ie.len &&
+ param->u.wpa_ie.data==NULL))
+ return -EINVAL;
+
+ if (param->u.wpa_ie.len){
+ buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
+
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = buf;
+ ieee->wpa_ie_len = param->u.wpa_ie.len;
+
+ } else {
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = NULL;
+ ieee->wpa_ie_len = 0;
+ }
+
+ ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
+
+ return 0;
+}
+
+/* implementation borrowed from hostap driver */
+
+static int ipw2100_wpa_set_encryption(struct net_device *dev,
+ struct ipw2100_param *param, int param_len){
+
+ int ret = 0;
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+
+ struct ieee80211_security sec = {
+ .flags = 0,
+ };
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IPW2100_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len !=
+ (int) ((char *) param->u.crypt.key - (char *) param) +
+ param->u.crypt.key_len){
+ IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, param->u.crypt.key_len);
+ return -EINVAL;
+ }
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS)
+ return -EINVAL;
+ crypt = &ieee->crypt[param->u.crypt.idx];
+ } else {
+ return -EINVAL;
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0) {
+ if (crypt){
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL;
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+ }
+ goto done;
+ }
+ sec.enabled = 1;
+ sec.flags |= SEC_ENABLED;
+
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+ request_module("ieee80211_crypt_wep");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ request_module("ieee80211_crypt_tkip");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ request_module("ieee80211_crypt_ccmp");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ }
+ if (ops == NULL) {
+ IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n",
+ dev->name, param->u.crypt.alg);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_UNKNOWN_ALG;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
+
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ param->u.crypt.err =
+ IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(param->u.crypt.key,
+ param->u.crypt.key_len, param->u.crypt.seq,
+ (*crypt)->priv) < 0) {
+ IPW_DEBUG_INFO("%s: key setting failed\n",
+ dev->name);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (param->u.crypt.set_tx){
+ ieee->tx_keyidx = param->u.crypt.idx;
+ sec.active_key = param->u.crypt.idx;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+
+ if (ops->name != NULL){
+
+ if (strcmp(ops->name, "WEP") == 0) {
+ memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, param->u.crypt.key_len);
+ sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
+ sec.flags |= (1 << param->u.crypt.idx);
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ } else if (strcmp(ops->name, "TKIP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_2;
+ } else if (strcmp(ops->name, "CCMP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_3;
+ }
+ }
+ done:
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack. */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port &&
+ ieee->reset_port(dev)) {
+ IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_CARD_CONF_FAILED;
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){
+
+ struct ipw2100_param *param;
+ int ret=0;
+
+ IPW_DEBUG_IOCTL("wpa_supplicant: len=%d\n", p->length);
+
+ if (p->length < sizeof(struct ipw2100_param) || !p->pointer)
+ return -EINVAL;
+
+ param = (struct ipw2100_param *)kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)){
+ kfree(param);
+ return -EFAULT;
+ }
+
+ switch (param->cmd){
+
+ case IPW2100_CMD_SET_WPA_PARAM:
+ ret = ipw2100_wpa_set_param(dev, param->u.wpa_param.name,
+ param->u.wpa_param.value);
+ break;
+
+ case IPW2100_CMD_SET_WPA_IE:
+ ret = ipw2100_wpa_set_wpa_ie(dev, param, p->length);
+ break;
+
+ case IPW2100_CMD_SET_ENCRYPTION:
+ ret = ipw2100_wpa_set_encryption(dev, param, p->length);
+ break;
+
+ case IPW2100_CMD_MLME:
+ ret = ipw2100_wpa_mlme(dev, param->u.mlme.command,
+ param->u.mlme.reason_code);
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown WPA supplicant request: %d\n",
+ dev->name, param->cmd);
+ ret = -EOPNOTSUPP;
+
+ }
+
+ if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+ ret = -EFAULT;
+
+ kfree(param);
+ return ret;
+}
+#endif /* CONFIG_IEEE80211_WPA */
+
+static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+#ifdef CONFIG_IEEE80211_WPA
+ struct iwreq *wrq = (struct iwreq *) rq;
+ int ret=-1;
+ switch (cmd){
+ case IPW2100_IOCTL_WPA_SUPPLICANT:
+ ret = ipw2100_wpa_supplicant(dev, &wrq->u.data);
+ return ret;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+#endif /* CONFIG_IEEE80211_WPA */
+
+ return -EOPNOTSUPP;
+}
+
+
+static void ipw_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ char fw_ver[64], ucode_ver[64];
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+
+ ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
+ ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
+
+ snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
+ fw_ver, priv->eeprom_version, ucode_ver);
+
+ strcpy(info->bus_info, pci_name(priv->pci_dev));
+}
+
+static u32 ipw2100_ethtool_get_link(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return (priv->status & STATUS_ASSOCIATED) ? 1 : 0;
+}
+
+
+static struct ethtool_ops ipw2100_ethtool_ops = {
+ .get_link = ipw2100_ethtool_get_link,
+ .get_drvinfo = ipw_ethtool_get_drvinfo,
+};
+
+static void ipw2100_hang_check(void *adapter)
+{
+ struct ipw2100_priv *priv = adapter;
+ unsigned long flags;
+ u32 rtc = 0xa5a5a5a5;
+ u32 len = sizeof(rtc);
+ int restart = 0;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->fatal_error != 0) {
+ /* If fatal_error is set then we need to restart */
+ IPW_DEBUG_INFO("%s: Hardware fatal error detected.\n",
+ priv->net_dev->name);
+
+ restart = 1;
+ } else if (ipw2100_get_ordinal(priv, IPW_ORD_RTC_TIME, &rtc, &len) ||
+ (rtc == priv->last_rtc)) {
+ /* Check if firmware is hung */
+ IPW_DEBUG_INFO("%s: Firmware RTC stalled.\n",
+ priv->net_dev->name);
+
+ restart = 1;
+ }
+
+ if (restart) {
+ /* Kill timer */
+ priv->stop_hang_check = 1;
+ priv->hangs++;
+
+ /* Restart the NIC */
+ schedule_reset(priv);
+ }
+
+ priv->last_rtc = rtc;
+
+ if (!priv->stop_hang_check)
+ queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+}
+
+
+static void ipw2100_rf_kill(void *adapter)
+{
+ struct ipw2100_priv *priv = adapter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
+ if (!priv->stop_rf_kill)
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ goto exit_unlock;
+ }
+
+ /* RF Kill is now disabled, so bring the device back up */
+
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting "
+ "device\n");
+ schedule_reset(priv);
+ } else
+ IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still "
+ "enabled\n");
+
+ exit_unlock:
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+}
+
+static void ipw2100_irq_tasklet(struct ipw2100_priv *priv);
+
+/* Look into using netdev destructor to shutdown ieee80211? */
+
+static struct net_device *ipw2100_alloc_device(
+ struct pci_dev *pci_dev,
+ void __iomem *base_addr,
+ unsigned long mem_start,
+ unsigned long mem_len)
+{
+ struct ipw2100_priv *priv;
+ struct net_device *dev;
+
+ dev = alloc_ieee80211(sizeof(struct ipw2100_priv));
+ if (!dev)
+ return NULL;
+ priv = ieee80211_priv(dev);
+ priv->ieee = netdev_priv(dev);
+ priv->pci_dev = pci_dev;
+ priv->net_dev = dev;
+
+ priv->ieee->hard_start_xmit = ipw2100_tx;
+ priv->ieee->set_security = shim__set_security;
+
+ dev->open = ipw2100_open;
+ dev->stop = ipw2100_close;
+ dev->init = ipw2100_net_init;
+ dev->do_ioctl = ipw2100_ioctl;
+ dev->get_stats = ipw2100_stats;
+ dev->ethtool_ops = &ipw2100_ethtool_ops;
+ dev->tx_timeout = ipw2100_tx_timeout;
+ dev->wireless_handlers = &ipw2100_wx_handler_def;
+ dev->get_wireless_stats = ipw2100_wx_wireless_stats;
+ dev->set_mac_address = ipw2100_set_address;
+ dev->watchdog_timeo = 3*HZ;
+ dev->irq = 0;
+
+ dev->base_addr = (unsigned long)base_addr;
+ dev->mem_start = mem_start;
+ dev->mem_end = dev->mem_start + mem_len - 1;
+
+ /* NOTE: We don't use the wireless_handlers hook
+ * in dev as the system will start throwing WX requests
+ * to us before we're actually initialized and it just
+ * ends up causing problems. So, we just handle
+ * the WX extensions through the ipw2100_ioctl interface */
+
+
+ /* memset() puts everything to 0, so we only have explicitely set
+ * those values that need to be something else */
+
+ /* If power management is turned on, default to AUTO mode */
+ priv->power_mode = IPW_POWER_AUTO;
+
+
+
+#ifdef CONFIG_IEEE80211_WPA
+ priv->ieee->wpa_enabled = 0;
+ priv->ieee->tkip_countermeasures = 0;
+ priv->ieee->drop_unencrypted = 0;
+ priv->ieee->privacy_invoked = 0;
+ priv->ieee->ieee802_1x = 1;
+#endif /* CONFIG_IEEE80211_WPA */
+
+ /* Set module parameters */
+ switch (mode) {
+ case 1:
+ priv->ieee->iw_mode = IW_MODE_ADHOC;
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case 2:
+ priv->ieee->iw_mode = IW_MODE_MONITOR;
+ break;
+#endif
+ default:
+ case 0:
+ priv->ieee->iw_mode = IW_MODE_INFRA;
+ break;
+ }
+
+ if (disable == 1)
+ priv->status |= STATUS_RF_KILL_SW;
+
+ if (channel != 0 &&
+ ((channel >= REG_MIN_CHANNEL) &&
+ (channel <= REG_MAX_CHANNEL))) {
+ priv->config |= CFG_STATIC_CHANNEL;
+ priv->channel = channel;
+ }
+
+ if (associate)
+ priv->config |= CFG_ASSOCIATE;
+
+ priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
+ priv->short_retry_limit = DEFAULT_SHORT_RETRY_LIMIT;
+ priv->long_retry_limit = DEFAULT_LONG_RETRY_LIMIT;
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD | RTS_DISABLED;
+ priv->frag_threshold = DEFAULT_FTS | FRAG_DISABLED;
+ priv->tx_power = IPW_TX_POWER_DEFAULT;
+ priv->tx_rates = DEFAULT_TX_RATES;
+
+ strcpy(priv->nick, "ipw2100");
+
+ spin_lock_init(&priv->low_lock);
+ sema_init(&priv->action_sem, 1);
+ sema_init(&priv->adapter_sem, 1);
+
+ init_waitqueue_head(&priv->wait_command_queue);
+
+ netif_carrier_off(dev);
+
+ INIT_LIST_HEAD(&priv->msg_free_list);
+ INIT_LIST_HEAD(&priv->msg_pend_list);
+ INIT_STAT(&priv->msg_free_stat);
+ INIT_STAT(&priv->msg_pend_stat);
+
+ INIT_LIST_HEAD(&priv->tx_free_list);
+ INIT_LIST_HEAD(&priv->tx_pend_list);
+ INIT_STAT(&priv->tx_free_stat);
+ INIT_STAT(&priv->tx_pend_stat);
+
+ INIT_LIST_HEAD(&priv->fw_pend_list);
+ INIT_STAT(&priv->fw_pend_stat);
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND2
+ priv->workqueue = create_workqueue(DRV_NAME, 0);
+#else
+ priv->workqueue = create_workqueue(DRV_NAME);
+#endif
+ INIT_WORK(&priv->reset_work,
+ (void (*)(void *))ipw2100_reset_adapter, priv);
+ INIT_WORK(&priv->security_work,
+ (void (*)(void *))ipw2100_security_work, priv);
+ INIT_WORK(&priv->wx_event_work,
+ (void (*)(void *))ipw2100_wx_event_work, priv);
+ INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv);
+ INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv);
+
+ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ ipw2100_irq_tasklet, (unsigned long)priv);
+
+ /* NOTE: We do not start the deferred work for status checks yet */
+ priv->stop_rf_kill = 1;
+ priv->stop_hang_check = 1;
+
+ return dev;
+}
+
+static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
+ const struct pci_device_id *ent)
+{
+ unsigned long mem_start, mem_len, mem_flags;
+ void __iomem *base_addr = NULL;
+ struct net_device *dev = NULL;
+ struct ipw2100_priv *priv = NULL;
+ int err = 0;
+ int registered = 0;
+ u32 val;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ mem_start = pci_resource_start(pci_dev, 0);
+ mem_len = pci_resource_len(pci_dev, 0);
+ mem_flags = pci_resource_flags(pci_dev, 0);
+
+ if ((mem_flags & IORESOURCE_MEM) != IORESOURCE_MEM) {
+ IPW_DEBUG_INFO("weird - resource type is not memory\n");
+ err = -ENODEV;
+ goto fail;
+ }
+
+ base_addr = ioremap_nocache(mem_start, mem_len);
+ if (!base_addr) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling ioremap_nocache.\n");
+ err = -EIO;
+ goto fail;
+ }
+
+ /* allocate and initialize our net_device */
+ dev = ipw2100_alloc_device(pci_dev, base_addr, mem_start, mem_len);
+ if (!dev) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling ipw2100_alloc_device.\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ /* set up PCI mappings for device */
+ err = pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_enable_device.\n");
+ return err;
+ }
+
+ priv = ieee80211_priv(dev);
+
+ pci_set_master(pci_dev);
+ pci_set_drvdata(pci_dev, priv);
+
+ err = pci_set_dma_mask(pci_dev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_set_dma_mask.\n");
+ pci_disable_device(pci_dev);
+ return err;
+ }
+
+ err = pci_request_regions(pci_dev, DRV_NAME);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_request_regions.\n");
+ pci_disable_device(pci_dev);
+ return err;
+ }
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_read_config_dword(pci_dev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff);
+
+ pci_set_power_state(pci_dev, PCI_D0);
+
+ if (!ipw2100_hw_is_adapter_in_system(dev)) {
+ printk(KERN_WARNING DRV_NAME
+ "Device not found via register read.\n");
+ err = -ENODEV;
+ goto fail;
+ }
+
+ SET_NETDEV_DEV(dev, &pci_dev->dev);
+
+ /* Force interrupts to be shut off on the device */
+ priv->status |= STATUS_INT_ENABLED;
+ ipw2100_disable_interrupts(priv);
+
+ /* Allocate and initialize the Tx/Rx queues and lists */
+ if (ipw2100_queues_allocate(priv)) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calilng ipw2100_queues_allocate.\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+ ipw2100_queues_initialize(priv);
+
+ err = request_irq(pci_dev->irq,
+ ipw2100_interrupt, SA_SHIRQ,
+ dev->name, priv);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling request_irq: %d.\n",
+ pci_dev->irq);
+ goto fail;
+ }
+ dev->irq = pci_dev->irq;
+
+ IPW_DEBUG_INFO("Attempting to register device...\n");
+
+ SET_MODULE_OWNER(dev);
+
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2100 Network Connection\n");
+
+ /* Bring up the interface. Pre 0.46, after we registered the
+ * network device we would call ipw2100_up. This introduced a race
+ * condition with newer hotplug configurations (network was coming
+ * up and making calls before the device was initialized).
+ *
+ * If we called ipw2100_up before we registered the device, then the
+ * device name wasn't registered. So, we instead use the net_dev->init
+ * member to call a function that then just turns and calls ipw2100_up.
+ * net_dev->init is called after name allocation but before the
+ * notifier chain is called */
+ down(&priv->action_sem);
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling register_netdev.\n");
+ goto fail_unlock;
+ }
+ registered = 1;
+
+ IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev));
+
+ /* perform this after register_netdev so that dev->name is set */
+ sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+ netif_carrier_off(dev);
+
+ /* If the RF Kill switch is disabled, go ahead and complete the
+ * startup sequence */
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ /* Enable the adapter - sends HOST_COMPLETE */
+ if (ipw2100_enable_adapter(priv)) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: failed in call to enable adapter.\n",
+ priv->net_dev->name);
+ ipw2100_hw_stop_adapter(priv);
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ /* Start a scan . . . */
+ ipw2100_set_scan_options(priv);
+ ipw2100_start_scan(priv);
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+
+ priv->status |= STATUS_INITIALIZED;
+
+ up(&priv->action_sem);
+
+ return 0;
+
+ fail_unlock:
+ up(&priv->action_sem);
+
+ fail:
+ if (dev) {
+ if (registered)
+ unregister_netdev(dev);
+
+ ipw2100_hw_stop_adapter(priv);
+
+ ipw2100_disable_interrupts(priv);
+
+ if (dev->irq)
+ free_irq(dev->irq, priv);
+
+ ipw2100_kill_workqueue(priv);
+
+ /* These are safe to call even if they weren't allocated */
+ ipw2100_queues_free(priv);
+ sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+
+ free_ieee80211(dev);
+ pci_set_drvdata(pci_dev, NULL);
+ }
+
+ if (base_addr)
+ iounmap(base_addr);
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
+
+ return err;
+}
+
+static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev;
+
+ if (priv) {
+ down(&priv->action_sem);
+
+ priv->status &= ~STATUS_INITIALIZED;
+
+ dev = priv->net_dev;
+ sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+
+#ifdef CONFIG_PM
+ if (ipw2100_firmware.version)
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+#endif
+ /* Take down the hardware */
+ ipw2100_down(priv);
+
+ /* Release the semaphore so that the network subsystem can
+ * complete any needed calls into the driver... */
+ up(&priv->action_sem);
+
+ /* Unregister the device first - this results in close()
+ * being called if the device is open. If we free storage
+ * first, then close() will crash. */
+ unregister_netdev(dev);
+
+ /* ipw2100_down will ensure that there is no more pending work
+ * in the workqueue's, so we can safely remove them now. */
+ ipw2100_kill_workqueue(priv);
+
+ ipw2100_queues_free(priv);
+
+ /* Free potential debugging firmware snapshot */
+ ipw2100_snapshot_free(priv);
+
+ if (dev->irq)
+ free_irq(dev->irq, priv);
+
+ if (dev->base_addr)
+ iounmap((void __iomem *)dev->base_addr);
+
+ free_ieee80211(dev);
+ }
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+static int ipw2100_suspend(struct pci_dev *pci_dev, u32 state)
+#else
+static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
+#endif
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev = priv->net_dev;
+
+ IPW_DEBUG_INFO("%s: Going into suspend...\n",
+ dev->name);
+
+ down(&priv->action_sem);
+ if (priv->status & STATUS_INITIALIZED) {
+ /* Take down the device; powers it off, etc. */
+ ipw2100_down(priv);
+ }
+
+ /* Remove the PRESENT state of the device */
+ netif_device_detach(dev);
+
+ pci_save_state(pci_dev);
+ pci_disable_device (pci_dev);
+ pci_set_power_state(pci_dev, PCI_D3hot);
+
+ up(&priv->action_sem);
+
+ return 0;
+}
+
+static int ipw2100_resume(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev = priv->net_dev;
+ u32 val;
+
+ if (IPW2100_PM_DISABLED)
+ return 0;
+
+ down(&priv->action_sem);
+
+ IPW_DEBUG_INFO("%s: Coming out of suspend...\n",
+ dev->name);
+
+ pci_set_power_state(pci_dev, PCI_D0);
+ pci_enable_device(pci_dev);
+ pci_restore_state(pci_dev);
+
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
+ * from interfering with C3 CPU state. pci_restore_state won't help
+ * here since it only restores the first 64 bytes pci config header.
+ */
+ pci_read_config_dword(pci_dev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff);
+
+ /* Set the device back into the PRESENT state; this will also wake
+ * the queue of needed */
+ netif_device_attach(dev);
+
+ /* Bring the device back up */
+ if (!(priv->status & STATUS_RF_KILL_SW))
+ ipw2100_up(priv, 0);
+
+ up(&priv->action_sem);
+
+ return 0;
+}
+#endif
+
+
+#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
+
+static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
+ IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */
+ IPW2100_DEV_ID(0x2522), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2523), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2527), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2528), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2529), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x252B), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x252C), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x252D), /* IN 2100 mPCI 3A */
+
+ IPW2100_DEV_ID(0x2550), /* IB 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2551), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2553), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2554), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2555), /* IB 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2560), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2562), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2563), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2561), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2565), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2566), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2567), /* DE 2100 mPCI 3A */
+
+ IPW2100_DEV_ID(0x2570), /* GA 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2580), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2582), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2583), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2581), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2585), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2586), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2587), /* TO 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2590), /* SO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2592), /* SO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2591), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2593), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2596), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2598), /* SO 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, ipw2100_pci_id_table);
+
+static struct pci_driver ipw2100_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ipw2100_pci_id_table,
+ .probe = ipw2100_pci_init_one,
+ .remove = __devexit_p(ipw2100_pci_remove_one),
+#ifdef CONFIG_PM
+ .suspend = ipw2100_suspend,
+ .resume = ipw2100_resume,
+#endif
+};
+
+
+/**
+ * Initialize the ipw2100 driver/module
+ *
+ * @returns 0 if ok, < 0 errno node con error.
+ *
+ * Note: we cannot init the /proc stuff until the PCI driver is there,
+ * or we risk an unlikely race condition on someone accessing
+ * uninitialized data in the PCI dev struct through /proc.
+ */
+static int __init ipw2100_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+ printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT);
+
+#ifdef CONFIG_IEEE80211_NOWEP
+ IPW_DEBUG_INFO(DRV_NAME ": Compiled with WEP disabled.\n");
+#endif
+
+ ret = pci_module_init(&ipw2100_pci_driver);
+
+#ifdef CONFIG_IPW_DEBUG
+ ipw2100_debug_level = debug;
+ driver_create_file(&ipw2100_pci_driver.driver,
+ &driver_attr_debug_level);
+#endif
+
+ return ret;
+}
+
+
+/**
+ * Cleanup ipw2100 driver registration
+ */
+static void __exit ipw2100_exit(void)
+{
+ /* FIXME: IPG: check that we have no instances of the devices open */
+#ifdef CONFIG_IPW_DEBUG
+ driver_remove_file(&ipw2100_pci_driver.driver,
+ &driver_attr_debug_level);
+#endif
+ pci_unregister_driver(&ipw2100_pci_driver);
+}
+
+module_init(ipw2100_init);
+module_exit(ipw2100_exit);
+
+#define WEXT_USECHANNELS 1
+
+static const long ipw2100_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT (sizeof(ipw2100_frequencies) / \
+ sizeof(ipw2100_frequencies[0]))
+
+static const long ipw2100_rates_11b[] = {
+ 1000000,
+ 2000000,
+ 5500000,
+ 11000000
+};
+
+#define RATE_COUNT (sizeof(ipw2100_rates_11b) / sizeof(ipw2100_rates_11b[0]))
+
+static int ipw2100_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ if (!(priv->status & STATUS_ASSOCIATED))
+ strcpy(wrqu->name, "unassociated");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
+
+ IPW_DEBUG_WX("Name: %s\n", wrqu->name);
+ return 0;
+}
+
+
+static int ipw2100_wx_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_freq *fwrq = &wrqu->freq;
+ int err = 0;
+
+ if (priv->ieee->iw_mode == IW_MODE_INFRA)
+ return -EOPNOTSUPP;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ /* if setting by freq convert to channel */
+ if (fwrq->e == 1) {
+ if ((fwrq->m >= (int) 2.412e8 &&
+ fwrq->m <= (int) 2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+
+ while ((c < REG_MAX_CHANNEL) &&
+ (f != ipw2100_frequencies[c]))
+ c++;
+
+ /* hack to fall through */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ }
+
+ if (fwrq->e > 0 || fwrq->m > 1000)
+ return -EOPNOTSUPP;
+ else { /* Set the channel */
+ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+ err = ipw2100_set_channel(priv, fwrq->m, 0);
+ }
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+
+static int ipw2100_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->freq.e = 0;
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured CHANNEL then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_CHANNEL ||
+ priv->status & STATUS_ASSOCIATED)
+ wrqu->freq.m = priv->channel;
+ else
+ wrqu->freq.m = 0;
+
+ IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+ return 0;
+
+}
+
+static int ipw2100_wx_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode);
+
+ if (wrqu->mode == priv->ieee->iw_mode)
+ return 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ switch (wrqu->mode) {
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ err = ipw2100_switch_mode(priv, IW_MODE_MONITOR);
+ break;
+#endif /* CONFIG_IPW2100_MONITOR */
+ case IW_MODE_ADHOC:
+ err = ipw2100_switch_mode(priv, IW_MODE_ADHOC);
+ break;
+ case IW_MODE_INFRA:
+ case IW_MODE_AUTO:
+ default:
+ err = ipw2100_switch_mode(priv, IW_MODE_INFRA);
+ break;
+ }
+
+done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->mode = priv->ieee->iw_mode;
+ IPW_DEBUG_WX("GET Mode -> %d\n", wrqu->mode);
+
+ return 0;
+}
+
+
+#define POWER_MODES 5
+
+/* Values are in microsecond */
+static const s32 timeout_duration[POWER_MODES] = {
+ 350000,
+ 250000,
+ 75000,
+ 37000,
+ 25000,
+};
+
+static const s32 period_duration[POWER_MODES] = {
+ 400000,
+ 700000,
+ 1000000,
+ 1000000,
+ 1000000
+};
+
+static int ipw2100_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_range *range = (struct iw_range *)extra;
+ u16 val;
+ int i, level;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* Let's try to keep this struct in the same order as in
+ * linux/include/wireless.h
+ */
+
+ /* TODO: See what values we can set, and remove the ones we can't
+ * set, or fill them with some default data.
+ */
+
+ /* ~5 Mb/s real (802.11b) */
+ range->throughput = 5 * 1000 * 1000;
+
+// range->sensitivity; /* signal level threshold range */
+
+ range->max_qual.qual = 100;
+ /* TODO: Find real max RSSI and stick here */
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 20 + IPW2100_RSSI_TO_DBM;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = RATE_COUNT;
+
+ for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
+ range->bitrate[i] = ipw2100_rates_11b[i];
+ }
+
+ range->min_rts = MIN_RTS_THRESHOLD;
+ range->max_rts = MAX_RTS_THRESHOLD;
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->min_pmp = period_duration[0]; /* Minimal PM period */
+ range->max_pmp = period_duration[POWER_MODES-1];/* Maximal PM period */
+ range->min_pmt = timeout_duration[POWER_MODES-1]; /* Minimal PM timeout */
+ range->max_pmt = timeout_duration[0];/* Maximal PM timeout */
+
+ /* How to decode max/min PM period */
+ range->pmp_flags = IW_POWER_PERIOD;
+ /* How to decode max/min PM period */
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ /* What PM options are supported */
+ range->pm_capa = IW_POWER_TIMEOUT | IW_POWER_PERIOD;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13; /* Different token sizes */
+ range->num_encoding_sizes = 2; /* Number of entry in the list */
+ range->max_encoding_tokens = WEP_KEYS; /* Max number of tokens */
+// range->encoding_login_index; /* token index for login token */
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ range->txpower_capa = IW_TXPOW_DBM;
+ range->num_txpower = IW_MAX_TXPOWER;
+ for (i = 0, level = (IPW_TX_POWER_MAX_DBM * 16); i < IW_MAX_TXPOWER;
+ i++, level -= ((IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM) * 16) /
+ (IW_MAX_TXPOWER - 1))
+ range->txpower[i] = level / 16;
+ } else {
+ range->txpower_capa = 0;
+ range->num_txpower = 0;
+ }
+
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+// range->retry_capa; /* What retry options are supported */
+// range->retry_flags; /* How to decode max/min retry limit */
+// range->r_time_flags; /* How to decode max/min retry life */
+// range->min_retry; /* Minimal number of retries */
+// range->max_retry; /* Maximal number of retries */
+// range->min_r_time; /* Minimal retry lifetime */
+// range->max_r_time; /* Maximal retry lifetime */
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ // TODO: Include only legal frequencies for some countries
+// if (local->channel_mask & (1 << i)) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = ipw2100_frequencies[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+// }
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ IPW_DEBUG_WX("GET Range\n");
+
+ return 0;
+}
+
+static int ipw2100_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ static const unsigned char any[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ static const unsigned char off[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // sanity checks
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
+ !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ /* we disable mandatory BSSID association */
+ IPW_DEBUG_WX("exit - disable mandatory BSSID\n");
+ priv->config &= ~CFG_STATIC_BSSID;
+ err = ipw2100_set_mandatory_bssid(priv, NULL, 0);
+ goto done;
+ }
+
+ priv->config |= CFG_STATIC_BSSID;
+ memcpy(priv->mandatory_bssid_mac, wrqu->ap_addr.sa_data, ETH_ALEN);
+
+ err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0);
+
+ IPW_DEBUG_WX("SET BSSID -> %02X:%02X:%02X:%02X:%02X:%02X\n",
+ wrqu->ap_addr.sa_data[0] & 0xff,
+ wrqu->ap_addr.sa_data[1] & 0xff,
+ wrqu->ap_addr.sa_data[2] & 0xff,
+ wrqu->ap_addr.sa_data[3] & 0xff,
+ wrqu->ap_addr.sa_data[4] & 0xff,
+ wrqu->ap_addr.sa_data[5] & 0xff);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured BSSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_BSSID ||
+ priv->status & STATUS_ASSOCIATED) {
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN);
+ } else
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+ IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+ return 0;
+}
+
+static int ipw2100_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ char *essid = ""; /* ANY */
+ int length = 0;
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ length = wrqu->essid.length - 1;
+ essid = extra;
+ }
+
+ if (length == 0) {
+ IPW_DEBUG_WX("Setting ESSID to ANY\n");
+ priv->config &= ~CFG_STATIC_ESSID;
+ err = ipw2100_set_essid(priv, NULL, 0, 0);
+ goto done;
+ }
+
+ length = min(length, IW_ESSID_MAX_SIZE);
+
+ priv->config |= CFG_STATIC_ESSID;
+
+ if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
+ IPW_DEBUG_WX("ESSID set to current ESSID.\n");
+ err = 0;
+ goto done;
+ }
+
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
+ length);
+
+ priv->essid_len = length;
+ memcpy(priv->essid, essid, priv->essid_len);
+
+ err = ipw2100_set_essid(priv, essid, length, 0);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured ESSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_ESSID ||
+ priv->status & STATUS_ASSOCIATED) {
+ IPW_DEBUG_WX("Getting essid: '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ memcpy(extra, priv->essid, priv->essid_len);
+ wrqu->essid.length = priv->essid_len;
+ wrqu->essid.flags = 1; /* active */
+ } else {
+ IPW_DEBUG_WX("Getting essid: ANY\n");
+ wrqu->essid.length = 0;
+ wrqu->essid.flags = 0; /* active */
+ }
+
+ return 0;
+}
+
+static int ipw2100_wx_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+ return -E2BIG;
+
+ wrqu->data.length = min((size_t)wrqu->data.length, sizeof(priv->nick));
+ memset(priv->nick, 0, sizeof(priv->nick));
+ memcpy(priv->nick, extra, wrqu->data.length);
+
+ IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick);
+
+ return 0;
+}
+
+static int ipw2100_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->data.length = strlen(priv->nick) + 1;
+ memcpy(extra, priv->nick, wrqu->data.length);
+ wrqu->data.flags = 1; /* active */
+
+ IPW_DEBUG_WX("GET Nickname -> %s \n", extra);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ u32 target_rate = wrqu->bitrate.value;
+ u32 rate;
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ rate = 0;
+
+ if (target_rate == 1000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 1000000))
+ rate |= TX_RATE_1_MBIT;
+ if (target_rate == 2000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 2000000))
+ rate |= TX_RATE_2_MBIT;
+ if (target_rate == 5500000 ||
+ (!wrqu->bitrate.fixed && target_rate > 5500000))
+ rate |= TX_RATE_5_5_MBIT;
+ if (target_rate == 11000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 11000000))
+ rate |= TX_RATE_11_MBIT;
+ if (rate == 0)
+ rate = DEFAULT_TX_RATES;
+
+ err = ipw2100_set_tx_rates(priv, rate, 0);
+
+ IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+
+static int ipw2100_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int val;
+ int len = sizeof(val);
+ int err = 0;
+
+ if (!(priv->status & STATUS_ENABLED) ||
+ priv->status & STATUS_RF_KILL_MASK ||
+ !(priv->status & STATUS_ASSOCIATED)) {
+ wrqu->bitrate.value = 0;
+ return 0;
+ }
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ err = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &val, &len);
+ if (err) {
+ IPW_DEBUG_WX("failed querying ordinals.\n");
+ return err;
+ }
+
+ switch (val & TX_RATE_MASK) {
+ case TX_RATE_1_MBIT:
+ wrqu->bitrate.value = 1000000;
+ break;
+ case TX_RATE_2_MBIT:
+ wrqu->bitrate.value = 2000000;
+ break;
+ case TX_RATE_5_5_MBIT:
+ wrqu->bitrate.value = 5500000;
+ break;
+ case TX_RATE_11_MBIT:
+ wrqu->bitrate.value = 11000000;
+ break;
+ default:
+ wrqu->bitrate.value = 0;
+ }
+
+ IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int value, err;
+
+ /* Auto RTS not yet supported */
+ if (wrqu->rts.fixed == 0)
+ return -EINVAL;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->rts.disabled)
+ value = priv->rts_threshold | RTS_DISABLED;
+ else {
+ if (wrqu->rts.value < 1 ||
+ wrqu->rts.value > 2304) {
+ err = -EINVAL;
+ goto done;
+ }
+ value = wrqu->rts.value;
+ }
+
+ err = ipw2100_set_rts_threshold(priv, value);
+
+ IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->rts.value = priv->rts_threshold & ~RTS_DISABLED;
+ wrqu->rts.fixed = 1; /* no auto select */
+
+ /* If RTS is set to the default value, then it is disabled */
+ wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0, value;
+
+ if (priv->ieee->iw_mode != IW_MODE_ADHOC)
+ return -EINVAL;
+
+ if (wrqu->txpower.disabled == 1 || wrqu->txpower.fixed == 0)
+ value = IPW_TX_POWER_DEFAULT;
+ else {
+ if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM ||
+ wrqu->txpower.value > IPW_TX_POWER_MAX_DBM)
+ return -EINVAL;
+
+ value = (wrqu->txpower.value - IPW_TX_POWER_MIN_DBM) * 16 /
+ (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
+ }
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ err = ipw2100_set_tx_power(priv, value);
+
+ IPW_DEBUG_WX("SET TX Power -> %d \n", value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (priv->ieee->iw_mode != IW_MODE_ADHOC) {
+ wrqu->power.disabled = 1;
+ return 0;
+ }
+
+ if (priv->tx_power == IPW_TX_POWER_DEFAULT) {
+ wrqu->power.fixed = 0;
+ wrqu->power.value = IPW_TX_POWER_MAX_DBM;
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ wrqu->power.fixed = 1;
+ wrqu->power.value =
+ (priv->tx_power *
+ (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM)) /
+ (IPW_TX_POWER_MAX - IPW_TX_POWER_MIN) +
+ IPW_TX_POWER_MIN_DBM;
+ }
+
+ wrqu->power.flags = IW_TXPOW_DBM;
+
+ IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->power.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (!wrqu->frag.fixed)
+ return -EINVAL;
+
+ if (wrqu->frag.disabled) {
+ priv->frag_threshold |= FRAG_DISABLED;
+ priv->ieee->fts = DEFAULT_FTS;
+ } else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ priv->ieee->fts = wrqu->frag.value & ~0x1;
+ priv->frag_threshold = priv->ieee->fts;
+ }
+
+ IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts);
+
+ return 0;
+}
+
+static int ipw2100_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ wrqu->frag.value = priv->frag_threshold & ~FRAG_DISABLED;
+ wrqu->frag.fixed = 0; /* no auto select */
+ wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
+ wrqu->retry.disabled)
+ return -EINVAL;
+
+ if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
+ return 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->retry.flags & IW_RETRY_MIN) {
+ err = ipw2100_set_short_retry(priv, wrqu->retry.value);
+ IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
+ wrqu->retry.value);
+ goto done;
+ }
+
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ err = ipw2100_set_long_retry(priv, wrqu->retry.value);
+ IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
+ wrqu->retry.value);
+ goto done;
+ }
+
+ err = ipw2100_set_short_retry(priv, wrqu->retry.value);
+ if (!err)
+ err = ipw2100_set_long_retry(priv, wrqu->retry.value);
+
+ IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->retry.disabled = 0; /* can't be disabled */
+
+ if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
+ IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
+ wrqu->retry.value = priv->long_retry_limit;
+ } else {
+ wrqu->retry.flags =
+ (priv->short_retry_limit !=
+ priv->long_retry_limit) ?
+ IW_RETRY_LIMIT & IW_RETRY_MIN : IW_RETRY_LIMIT;
+
+ wrqu->retry.value = priv->short_retry_limit;
+ }
+
+ IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ IPW_DEBUG_WX("Initiating scan...\n");
+ if (ipw2100_set_scan_options(priv) ||
+ ipw2100_start_scan(priv)) {
+ IPW_DEBUG_WX("Start scan failed.\n");
+
+ /* TODO: Mark a scan as pending so when hardware initialized
+ * a scan starts */
+ }
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra);
+}
+
+
+/*
+ * Implementation based on code in hostap-driver v0.1.3 hostap_ioctl.c
+ */
+static int ipw2100_wx_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ /*
+ * No check of STATUS_INITIALIZED required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw2100_wx_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw2100_wx_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->power.disabled) {
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM);
+ IPW_DEBUG_WX("SET Power Management Mode -> off\n");
+ goto done;
+ }
+
+ switch (wrqu->power.flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ break;
+ default: /* Otherwise we don't support it */
+ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
+ wrqu->power.flags);
+ err = -EOPNOTSUPP;
+ goto done;
+ }
+
+ /* If the user hasn't specified a power management mode yet, default
+ * to BATTERY */
+ priv->power_mode = IPW_POWER_ENABLED | priv->power_mode;
+ err = ipw2100_set_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
+
+ IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n",
+ priv->power_mode);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+
+}
+
+static int ipw2100_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ wrqu->power.flags = 0;
+ }
+
+ IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
+
+ return 0;
+}
+
+
+/*
+ *
+ * IWPRIV handlers
+ *
+ */
+#ifdef CONFIG_IPW2100_MONITOR
+static int ipw2100_wx_set_promisc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int *parms = (int *)extra;
+ int enable = (parms[0] > 0);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (enable) {
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ err = ipw2100_set_channel(priv, parms[1], 0);
+ goto done;
+ }
+ priv->channel = parms[1];
+ err = ipw2100_switch_mode(priv, IW_MODE_MONITOR);
+ } else {
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ err = ipw2100_switch_mode(priv, priv->last_mode);
+ }
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_reset(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ if (priv->status & STATUS_INITIALIZED)
+ schedule_reset(priv);
+ return 0;
+}
+
+#endif
+
+static int ipw2100_wx_set_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0, mode = *(int *)extra;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if ((mode < 1) || (mode > POWER_MODES))
+ mode = IPW_POWER_AUTO;
+
+ if (priv->power_mode != mode)
+ err = ipw2100_set_power_mode(priv, mode);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+#define MAX_POWER_STRING 80
+static int ipw2100_wx_get_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int level = IPW_POWER_LEVEL(priv->power_mode);
+ s32 timeout, period;
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (Off)", level);
+ } else {
+ switch (level) {
+ case IPW_POWER_MODE_CAM:
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (None)", level);
+ break;
+ case IPW_POWER_AUTO:
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (Auto)", 0);
+ break;
+ default:
+ timeout = timeout_duration[level - 1] / 1000;
+ period = period_duration[level - 1] / 1000;
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d "
+ "(Timeout %dms, Period %dms)",
+ level, timeout, period);
+ }
+ }
+
+ wrqu->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+
+static int ipw2100_wx_set_preamble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err, mode = *(int *)extra;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (mode == 1)
+ priv->config |= CFG_LONG_PREAMBLE;
+ else if (mode == 0)
+ priv->config &= ~CFG_LONG_PREAMBLE;
+ else {
+ err = -EINVAL;
+ goto done;
+ }
+
+ err = ipw2100_system_config(priv, 0);
+
+done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_preamble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (priv->config & CFG_LONG_PREAMBLE)
+ snprintf(wrqu->name, IFNAMSIZ, "long (1)");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "auto (0)");
+
+ return 0;
+}
+
+static iw_handler ipw2100_wx_handlers[] =
+{
+ NULL, /* SIOCSIWCOMMIT */
+ ipw2100_wx_get_name, /* SIOCGIWNAME */
+ NULL, /* SIOCSIWNWID */
+ NULL, /* SIOCGIWNWID */
+ ipw2100_wx_set_freq, /* SIOCSIWFREQ */
+ ipw2100_wx_get_freq, /* SIOCGIWFREQ */
+ ipw2100_wx_set_mode, /* SIOCSIWMODE */
+ ipw2100_wx_get_mode, /* SIOCGIWMODE */
+ NULL, /* SIOCSIWSENS */
+ NULL, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ ipw2100_wx_get_range, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+ NULL, /* SIOCSIWSPY */
+ NULL, /* SIOCGIWSPY */
+ NULL, /* SIOCGIWTHRSPY */
+ NULL, /* SIOCWIWTHRSPY */
+ ipw2100_wx_set_wap, /* SIOCSIWAP */
+ ipw2100_wx_get_wap, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST -- deprecated */
+ ipw2100_wx_set_scan, /* SIOCSIWSCAN */
+ ipw2100_wx_get_scan, /* SIOCGIWSCAN */
+ ipw2100_wx_set_essid, /* SIOCSIWESSID */
+ ipw2100_wx_get_essid, /* SIOCGIWESSID */
+ ipw2100_wx_set_nick, /* SIOCSIWNICKN */
+ ipw2100_wx_get_nick, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ ipw2100_wx_set_rate, /* SIOCSIWRATE */
+ ipw2100_wx_get_rate, /* SIOCGIWRATE */
+ ipw2100_wx_set_rts, /* SIOCSIWRTS */
+ ipw2100_wx_get_rts, /* SIOCGIWRTS */
+ ipw2100_wx_set_frag, /* SIOCSIWFRAG */
+ ipw2100_wx_get_frag, /* SIOCGIWFRAG */
+ ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */
+ ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */
+ ipw2100_wx_set_retry, /* SIOCSIWRETRY */
+ ipw2100_wx_get_retry, /* SIOCGIWRETRY */
+ ipw2100_wx_set_encode, /* SIOCSIWENCODE */
+ ipw2100_wx_get_encode, /* SIOCGIWENCODE */
+ ipw2100_wx_set_power, /* SIOCSIWPOWER */
+ ipw2100_wx_get_power, /* SIOCGIWPOWER */
+};
+
+#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV
+#define IPW2100_PRIV_RESET SIOCIWFIRSTPRIV+1
+#define IPW2100_PRIV_SET_POWER SIOCIWFIRSTPRIV+2
+#define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3
+#define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4
+#define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5
+
+static const struct iw_priv_args ipw2100_private_args[] = {
+
+#ifdef CONFIG_IPW2100_MONITOR
+ {
+ IPW2100_PRIV_SET_MONITOR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"
+ },
+ {
+ IPW2100_PRIV_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"
+ },
+#endif /* CONFIG_IPW2100_MONITOR */
+
+ {
+ IPW2100_PRIV_SET_POWER,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power"
+ },
+ {
+ IPW2100_PRIV_GET_POWER,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_POWER_STRING, "get_power"
+ },
+ {
+ IPW2100_PRIV_SET_LONGPREAMBLE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"
+ },
+ {
+ IPW2100_PRIV_GET_LONGPREAMBLE,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"
+ },
+};
+
+static iw_handler ipw2100_private_handler[] = {
+#ifdef CONFIG_IPW2100_MONITOR
+ ipw2100_wx_set_promisc,
+ ipw2100_wx_reset,
+#else /* CONFIG_IPW2100_MONITOR */
+ NULL,
+ NULL,
+#endif /* CONFIG_IPW2100_MONITOR */
+ ipw2100_wx_set_powermode,
+ ipw2100_wx_get_powermode,
+ ipw2100_wx_set_preamble,
+ ipw2100_wx_get_preamble,
+};
+
+static struct iw_handler_def ipw2100_wx_handler_def =
+{
+ .standard = ipw2100_wx_handlers,
+ .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler),
+ .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler),
+ .num_private_args = sizeof(ipw2100_private_args) /
+ sizeof(struct iw_priv_args),
+ .private = (iw_handler *)ipw2100_private_handler,
+ .private_args = (struct iw_priv_args *)ipw2100_private_args,
+};
+
+/*
+ * Get wireless statistics.
+ * Called by /proc/net/wireless
+ * Also called by SIOCGIWSTATS
+ */
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev)
+{
+ enum {
+ POOR = 30,
+ FAIR = 60,
+ GOOD = 80,
+ VERY_GOOD = 90,
+ EXCELLENT = 95,
+ PERFECT = 100
+ };
+ int rssi_qual;
+ int tx_qual;
+ int beacon_qual;
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_statistics *wstats;
+ u32 rssi, quality, tx_retries, missed_beacons, tx_failures;
+ u32 ord_len = sizeof(u32);
+
+ if (!priv)
+ return (struct iw_statistics *) NULL;
+
+ wstats = &priv->wstats;
+
+ /* if hw is disabled, then ipw2100_get_ordinal() can't be called.
+ * ipw2100_wx_wireless_stats seems to be called before fw is
+ * initialized. STATUS_ASSOCIATED will only be set if the hw is up
+ * and associated; if not associcated, the values are all meaningless
+ * anyway, so set them all to NULL and INVALID */
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 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;
+ }
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_MISSED_BCNS,
+ &missed_beacons, &ord_len))
+ goto fail_get_ordinal;
+
+ /* If we don't have a connection the quality and level is 0*/
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ } else {
+ if (ipw2100_get_ordinal(priv, IPW_ORD_RSSI_AVG_CURR,
+ &rssi, &ord_len))
+ goto fail_get_ordinal;
+ wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM;
+ if (rssi < 10)
+ rssi_qual = rssi * POOR / 10;
+ else if (rssi < 15)
+ rssi_qual = (rssi - 10) * (FAIR - POOR) / 5 + POOR;
+ else if (rssi < 20)
+ rssi_qual = (rssi - 15) * (GOOD - FAIR) / 5 + FAIR;
+ else if (rssi < 30)
+ rssi_qual = (rssi - 20) * (VERY_GOOD - GOOD) /
+ 10 + GOOD;
+ else
+ rssi_qual = (rssi - 30) * (PERFECT - VERY_GOOD) /
+ 10 + VERY_GOOD;
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_RETRIES,
+ &tx_retries, &ord_len))
+ goto fail_get_ordinal;
+
+ if (tx_retries > 75)
+ tx_qual = (90 - tx_retries) * POOR / 15;
+ else if (tx_retries > 70)
+ tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
+ else if (tx_retries > 65)
+ tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
+ else if (tx_retries > 50)
+ tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
+ 15 + GOOD;
+ else
+ tx_qual = (50 - tx_retries) *
+ (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+
+ if (missed_beacons > 50)
+ beacon_qual = (60 - missed_beacons) * POOR / 10;
+ else if (missed_beacons > 40)
+ beacon_qual = (50 - missed_beacons) * (FAIR - POOR) /
+ 10 + POOR;
+ else if (missed_beacons > 32)
+ beacon_qual = (40 - missed_beacons) * (GOOD - FAIR) /
+ 18 + FAIR;
+ else if (missed_beacons > 20)
+ beacon_qual = (32 - missed_beacons) *
+ (VERY_GOOD - GOOD) / 20 + GOOD;
+ else
+ beacon_qual = (20 - missed_beacons) *
+ (PERFECT - VERY_GOOD) / 20 + VERY_GOOD;
+
+ quality = min(beacon_qual, min(tx_qual, rssi_qual));
+
+#ifdef CONFIG_IPW_DEBUG
+ if (beacon_qual == quality)
+ IPW_DEBUG_WX("Quality clamped by Missed Beacons\n");
+ else if (tx_qual == quality)
+ IPW_DEBUG_WX("Quality clamped by Tx Retries\n");
+ else if (quality != 100)
+ IPW_DEBUG_WX("Quality clamped by Signal Strength\n");
+ else
+ IPW_DEBUG_WX("Quality not clamped.\n");
+#endif
+
+ wstats->qual.qual = quality;
+ wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM;
+ }
+
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 7;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
+
+ /* FIXME: this is percent and not a # */
+ wstats->miss.beacon = missed_beacons;
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURES,
+ &tx_failures, &ord_len))
+ goto fail_get_ordinal;
+ wstats->discard.retries = tx_failures;
+
+ return wstats;
+
+ fail_get_ordinal:
+ IPW_DEBUG_WX("failed querying ordinals.\n");
+
+ return (struct iw_statistics *) NULL;
+}
+
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
+{
+ union iwreq_data wrqu;
+ int len = ETH_ALEN;
+
+ if (priv->status & STATUS_STOPPING)
+ return;
+
+ down(&priv->action_sem);
+
+ IPW_DEBUG_WX("enter\n");
+
+ up(&priv->action_sem);
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ /* Fetch BSSID from the hardware */
+ if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) ||
+ priv->status & STATUS_RF_KILL_MASK ||
+ ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID,
+ &priv->bssid, &len)) {
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ } else {
+ /* We now have the BSSID, so can finish setting to the full
+ * associated state */
+ memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN);
+ memcpy(&priv->ieee->bssid, priv->bssid, ETH_ALEN);
+ priv->status &= ~STATUS_ASSOCIATING;
+ priv->status |= STATUS_ASSOCIATED;
+ netif_carrier_on(priv->net_dev);
+ if (netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_INFO("Waking net queue.\n");
+ netif_wake_queue(priv->net_dev);
+ } else {
+ IPW_DEBUG_INFO("Starting net queue.\n");
+ netif_start_queue(priv->net_dev);
+ }
+ }
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_WX("Configuring ESSID\n");
+ down(&priv->action_sem);
+ /* This is a disassociation event, so kick the firmware to
+ * look for another AP */
+ if (priv->config & CFG_STATIC_ESSID)
+ ipw2100_set_essid(priv, priv->essid, priv->essid_len, 0);
+ else
+ ipw2100_set_essid(priv, NULL, 0, 0);
+ up(&priv->action_sem);
+ }
+
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+#define IPW2100_FW_MAJOR_VERSION 1
+#define IPW2100_FW_MINOR_VERSION 3
+
+#define IPW2100_FW_MINOR(x) ((x & 0xff) >> 8)
+#define IPW2100_FW_MAJOR(x) (x & 0xff)
+
+#define IPW2100_FW_VERSION ((IPW2100_FW_MINOR_VERSION << 8) | \
+ IPW2100_FW_MAJOR_VERSION)
+
+#define IPW2100_FW_PREFIX "ipw2100-" __stringify(IPW2100_FW_MAJOR_VERSION) \
+"." __stringify(IPW2100_FW_MINOR_VERSION)
+
+#define IPW2100_FW_NAME(x) IPW2100_FW_PREFIX "" x ".fw"
+
+
+/*
+
+BINARY FIRMWARE HEADER FORMAT
+
+offset length desc
+0 2 version
+2 2 mode == 0:BSS,1:IBSS,2:MONITOR
+4 4 fw_len
+8 4 uc_len
+C fw_len firmware data
+12 + fw_len uc_len microcode data
+
+*/
+
+struct ipw2100_fw_header {
+ short version;
+ short mode;
+ unsigned int fw_size;
+ unsigned int uc_size;
+} __attribute__ ((packed));
+
+
+
+static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw)
+{
+ struct ipw2100_fw_header *h =
+ (struct ipw2100_fw_header *)fw->fw_entry->data;
+
+ if (IPW2100_FW_MAJOR(h->version) != IPW2100_FW_MAJOR_VERSION) {
+ printk(KERN_WARNING DRV_NAME ": Firmware image not compatible "
+ "(detected version id of %u). "
+ "See Documentation/networking/README.ipw2100\n",
+ h->version);
+ return 1;
+ }
+
+ fw->version = h->version;
+ fw->fw.data = fw->fw_entry->data + sizeof(struct ipw2100_fw_header);
+ fw->fw.size = h->fw_size;
+ fw->uc.data = fw->fw.data + h->fw_size;
+ fw->uc.size = h->uc_size;
+
+ return 0;
+}
+
+
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ char *fw_name;
+ int rc;
+
+ IPW_DEBUG_INFO("%s: Using hotplug firmware load.\n",
+ priv->net_dev->name);
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ fw_name = IPW2100_FW_NAME("-i");
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ fw_name = IPW2100_FW_NAME("-p");
+ break;
+#endif
+ case IW_MODE_INFRA:
+ default:
+ fw_name = IPW2100_FW_NAME("");
+ break;
+ }
+
+ rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
+
+ if (rc < 0) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: Firmware '%s' not available or load failed.\n",
+ priv->net_dev->name, fw_name);
+ return rc;
+ }
+ IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data,
+ fw->fw_entry->size);
+
+ ipw2100_mod_firmware_load(fw);
+
+ return 0;
+}
+
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ fw->version = 0;
+ if (fw->fw_entry)
+ release_firmware(fw->fw_entry);
+ fw->fw_entry = NULL;
+}
+
+
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
+{
+ char ver[MAX_FW_VERSION_LEN];
+ u32 len = MAX_FW_VERSION_LEN;
+ u32 tmp;
+ int i;
+ /* firmware version is an ascii string (max len of 14) */
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_FW_VER_NUM,
+ ver, &len))
+ return -EIO;
+ tmp = max;
+ if (len >= max)
+ len = max - 1;
+ for (i = 0; i < len; i++)
+ buf[i] = ver[i];
+ buf[i] = '\0';
+ return tmp;
+}
+
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
+{
+ u32 ver;
+ u32 len = sizeof(ver);
+ /* microcode version is a 32 bit integer */
+ if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION,
+ &ver, &len))
+ return -EIO;
+ return snprintf(buf, max, "%08X", ver);
+}
+
+/*
+ * On exit, the firmware will have been freed from the fw list
+ */
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ /* firmware is constructed of N contiguous entries, each entry is
+ * structured as:
+ *
+ * offset sie desc
+ * 0 4 address to write to
+ * 4 2 length of data run
+ * 6 length data
+ */
+ unsigned int addr;
+ unsigned short len;
+
+ const unsigned char *firmware_data = fw->fw.data;
+ unsigned int firmware_data_left = fw->fw.size;
+
+ while (firmware_data_left > 0) {
+ addr = *(u32 *)(firmware_data);
+ firmware_data += 4;
+ firmware_data_left -= 4;
+
+ len = *(u16 *)(firmware_data);
+ firmware_data += 2;
+ firmware_data_left -= 2;
+
+ if (len > 32) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Invalid firmware run-length of %d bytes\n",
+ len);
+ return -EINVAL;
+ }
+
+ write_nic_memory(priv->net_dev, addr, len, firmware_data);
+ firmware_data += len;
+ firmware_data_left -= len;
+ }
+
+ return 0;
+}
+
+struct symbol_alive_response {
+ u8 cmd_id;
+ u8 seq_num;
+ u8 ucode_rev;
+ u8 eeprom_valid;
+ u16 valid_flags;
+ u8 IEEE_addr[6];
+ u16 flags;
+ u16 pcb_rev;
+ u16 clock_settle_time; // 1us LSB
+ u16 powerup_settle_time; // 1us LSB
+ u16 hop_settle_time; // 1us LSB
+ u8 date[3]; // month, day, year
+ u8 time[2]; // hours, minutes
+ u8 ucode_valid;
+};
+
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ struct net_device *dev = priv->net_dev;
+ const unsigned char *microcode_data = fw->uc.data;
+ unsigned int microcode_data_left = fw->uc.size;
+ void __iomem *reg = (void __iomem *)dev->base_addr;
+
+ struct symbol_alive_response response;
+ int i, j;
+ u8 data;
+
+ /* Symbol control */
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
+ readl(reg);
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
+ readl(reg);
+
+ /* HW config */
+ write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
+ readl(reg);
+ write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
+ readl(reg);
+
+ /* EN_CS_ACCESS bit to reset control store pointer */
+ write_nic_byte(dev, 0x210000, 0x40);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x40);
+ readl(reg);
+
+ /* copy microcode from buffer into Symbol */
+
+ while (microcode_data_left > 0) {
+ write_nic_byte(dev, 0x210010, *microcode_data++);
+ write_nic_byte(dev, 0x210010, *microcode_data++);
+ microcode_data_left -= 2;
+ }
+
+ /* EN_CS_ACCESS bit to reset the control store pointer */
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+
+ /* Enable System (Reg 0)
+ * first enable causes garbage in RX FIFO */
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x80);
+ readl(reg);
+
+ /* Reset External Baseband Reg */
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
+ readl(reg);
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
+ readl(reg);
+
+ /* HW Config (Reg 5) */
+ write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
+ readl(reg);
+ write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
+ readl(reg);
+
+ /* Enable System (Reg 0)
+ * second enable should be OK */
+ write_nic_byte(dev, 0x210000, 0x00); // clear enable system
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x80); // set enable system
+
+ /* check Symbol is enabled - upped this from 5 as it wasn't always
+ * catching the update */
+ for (i = 0; i < 10; i++) {
+ udelay(10);
+
+ /* check Dino is enabled bit */
+ read_nic_byte(dev, 0x210000, &data);
+ if (data & 0x1)
+ break;
+ }
+
+ if (i == 10) {
+ printk(KERN_ERR DRV_NAME ": %s: Error initializing Symbol\n",
+ dev->name);
+ return -EIO;
+ }
+
+ /* Get Symbol alive response */
+ for (i = 0; i < 30; i++) {
+ /* Read alive response structure */
+ for (j = 0;
+ j < (sizeof(struct symbol_alive_response) >> 1);
+ j++)
+ read_nic_word(dev, 0x210004,
+ ((u16 *)&response) + j);
+
+ if ((response.cmd_id == 1) &&
+ (response.ucode_valid == 0x1))
+ break;
+ udelay(10);
+ }
+
+ if (i == 30) {
+ printk(KERN_ERR DRV_NAME ": %s: No response from Symbol - hw not alive\n",
+ dev->name);
+ printk_buf(IPW_DL_ERROR, (u8*)&response, sizeof(response));
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
new file mode 100644
index 000000000000..2a3cdbd50168
--- /dev/null
+++ b/drivers/net/wireless/ipw2100.h
@@ -0,0 +1,1167 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#ifndef _IPW2100_H
+#define _IPW2100_H
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+#include <linux/socket.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/version.h>
+#include <net/iw_handler.h> // new driver API
+
+#include <net/ieee80211.h>
+
+#include <linux/workqueue.h>
+
+struct ipw2100_priv;
+struct ipw2100_tx_packet;
+struct ipw2100_rx_packet;
+
+#define IPW_DL_UNINIT 0x80000000
+#define IPW_DL_NONE 0x00000000
+#define IPW_DL_ALL 0x7FFFFFFF
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IPW_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IPW2100_xxxx_DEBUG() macro definition for your
+ * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw2100/debug_level
+ *
+ * you simply need to add your entry to the ipw2100_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw2100 then you do not have
+ * CONFIG_IPW_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IPW_DL_ERROR (1<<0)
+#define IPW_DL_WARNING (1<<1)
+#define IPW_DL_INFO (1<<2)
+#define IPW_DL_WX (1<<3)
+#define IPW_DL_HC (1<<5)
+#define IPW_DL_STATE (1<<6)
+
+#define IPW_DL_NOTIF (1<<10)
+#define IPW_DL_SCAN (1<<11)
+#define IPW_DL_ASSOC (1<<12)
+#define IPW_DL_DROP (1<<13)
+
+#define IPW_DL_IOCTL (1<<14)
+#define IPW_DL_RF_KILL (1<<17)
+
+
+#define IPW_DL_MANAGE (1<<15)
+#define IPW_DL_FW (1<<16)
+
+#define IPW_DL_FRAG (1<<21)
+#define IPW_DL_WEP (1<<22)
+#define IPW_DL_TX (1<<23)
+#define IPW_DL_RX (1<<24)
+#define IPW_DL_ISR (1<<25)
+#define IPW_DL_IO (1<<26)
+#define IPW_DL_TRACE (1<<28)
+
+#define IPW_DEBUG_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_INFO(f...) IPW_DEBUG(IPW_DL_INFO, ## f)
+#define IPW_DEBUG_WX(f...) IPW_DEBUG(IPW_DL_WX, ## f)
+#define IPW_DEBUG_SCAN(f...) IPW_DEBUG(IPW_DL_SCAN, ## f)
+#define IPW_DEBUG_NOTIF(f...) IPW_DEBUG(IPW_DL_NOTIF, ## f)
+#define IPW_DEBUG_TRACE(f...) IPW_DEBUG(IPW_DL_TRACE, ## f)
+#define IPW_DEBUG_RX(f...) IPW_DEBUG(IPW_DL_RX, ## f)
+#define IPW_DEBUG_TX(f...) IPW_DEBUG(IPW_DL_TX, ## f)
+#define IPW_DEBUG_ISR(f...) IPW_DEBUG(IPW_DL_ISR, ## f)
+#define IPW_DEBUG_MANAGEMENT(f...) IPW_DEBUG(IPW_DL_MANAGE, ## f)
+#define IPW_DEBUG_WEP(f...) IPW_DEBUG(IPW_DL_WEP, ## f)
+#define IPW_DEBUG_HC(f...) IPW_DEBUG(IPW_DL_HC, ## f)
+#define IPW_DEBUG_FRAG(f...) IPW_DEBUG(IPW_DL_FRAG, ## f)
+#define IPW_DEBUG_FW(f...) IPW_DEBUG(IPW_DL_FW, ## f)
+#define IPW_DEBUG_RF_KILL(f...) IPW_DEBUG(IPW_DL_RF_KILL, ## f)
+#define IPW_DEBUG_DROP(f...) IPW_DEBUG(IPW_DL_DROP, ## f)
+#define IPW_DEBUG_IO(f...) IPW_DEBUG(IPW_DL_IO, ## f)
+#define IPW_DEBUG_IOCTL(f...) IPW_DEBUG(IPW_DL_IOCTL, ## f)
+#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+
+enum {
+ IPW_HW_STATE_DISABLED = 1,
+ IPW_HW_STATE_ENABLED = 0
+};
+
+struct ssid_context {
+ char ssid[IW_ESSID_MAX_SIZE + 1];
+ int ssid_len;
+ unsigned char bssid[ETH_ALEN];
+ int port_type;
+ int channel;
+
+};
+
+extern const char *port_type_str[];
+extern const char *band_str[];
+
+#define NUMBER_OF_BD_PER_COMMAND_PACKET 1
+#define NUMBER_OF_BD_PER_DATA_PACKET 2
+
+#define IPW_MAX_BDS 6
+#define NUMBER_OF_OVERHEAD_BDS_PER_PACKETR 2
+#define NUMBER_OF_BDS_TO_LEAVE_FOR_COMMANDS 1
+
+#define REQUIRED_SPACE_IN_RING_FOR_COMMAND_PACKET \
+ (IPW_BD_QUEUE_W_R_MIN_SPARE + NUMBER_OF_BD_PER_COMMAND_PACKET)
+
+struct bd_status {
+ union {
+ struct { u8 nlf:1, txType:2, intEnabled:1, reserved:4;} fields;
+ u8 field;
+ } info;
+} __attribute__ ((packed));
+
+struct ipw2100_bd {
+ u32 host_addr;
+ u32 buf_length;
+ struct bd_status status;
+ /* number of fragments for frame (should be set only for
+ * 1st TBD) */
+ u8 num_fragments;
+ u8 reserved[6];
+} __attribute__ ((packed));
+
+#define IPW_BD_QUEUE_LENGTH(n) (1<<n)
+#define IPW_BD_ALIGNMENT(L) (L*sizeof(struct ipw2100_bd))
+
+#define IPW_BD_STATUS_TX_FRAME_802_3 0x00
+#define IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT 0x01
+#define IPW_BD_STATUS_TX_FRAME_COMMAND 0x02
+#define IPW_BD_STATUS_TX_FRAME_802_11 0x04
+#define IPW_BD_STATUS_TX_INTERRUPT_ENABLE 0x08
+
+struct ipw2100_bd_queue {
+ /* driver (virtual) pointer to queue */
+ struct ipw2100_bd *drv;
+
+ /* firmware (physical) pointer to queue */
+ dma_addr_t nic;
+
+ /* Length of phy memory allocated for BDs */
+ u32 size;
+
+ /* Number of BDs in queue (and in array) */
+ u32 entries;
+
+ /* Number of available BDs (invalid for NIC BDs) */
+ u32 available;
+
+ /* Offset of oldest used BD in array (next one to
+ * check for completion) */
+ u32 oldest;
+
+ /* Offset of next available (unused) BD */
+ u32 next;
+};
+
+#define RX_QUEUE_LENGTH 256
+#define TX_QUEUE_LENGTH 256
+#define HW_QUEUE_LENGTH 256
+
+#define TX_PENDED_QUEUE_LENGTH (TX_QUEUE_LENGTH / NUMBER_OF_BD_PER_DATA_PACKET)
+
+#define STATUS_TYPE_MASK 0x0000000f
+#define COMMAND_STATUS_VAL 0
+#define STATUS_CHANGE_VAL 1
+#define P80211_DATA_VAL 2
+#define P8023_DATA_VAL 3
+#define HOST_NOTIFICATION_VAL 4
+
+#define IPW2100_RSSI_TO_DBM (-98)
+
+struct ipw2100_status {
+ u32 frame_size;
+ u16 status_fields;
+ u8 flags;
+#define IPW_STATUS_FLAG_DECRYPTED (1<<0)
+#define IPW_STATUS_FLAG_WEP_ENCRYPTED (1<<1)
+#define IPW_STATUS_FLAG_CRC_ERROR (1<<2)
+ u8 rssi;
+} __attribute__ ((packed));
+
+struct ipw2100_status_queue {
+ /* driver (virtual) pointer to queue */
+ struct ipw2100_status *drv;
+
+ /* firmware (physical) pointer to queue */
+ dma_addr_t nic;
+
+ /* Length of phy memory allocated for BDs */
+ u32 size;
+};
+
+#define HOST_COMMAND_PARAMS_REG_LEN 100
+#define CMD_STATUS_PARAMS_REG_LEN 3
+
+#define IPW_WPA_CAPABILITIES 0x1
+#define IPW_WPA_LISTENINTERVAL 0x2
+#define IPW_WPA_AP_ADDRESS 0x4
+
+#define IPW_MAX_VAR_IE_LEN ((HOST_COMMAND_PARAMS_REG_LEN - 4) * sizeof(u32))
+
+struct ipw2100_wpa_assoc_frame {
+ u16 fixed_ie_mask;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[ETH_ALEN];
+ } fixed_ies;
+ u32 var_ie_len;
+ u8 var_ie[IPW_MAX_VAR_IE_LEN];
+};
+
+#define IPW_BSS 1
+#define IPW_MONITOR 2
+#define IPW_IBSS 3
+
+/**
+ * @struct _tx_cmd - HWCommand
+ * @brief H/W command structure.
+ */
+struct ipw2100_cmd_header {
+ u32 host_command_reg;
+ u32 host_command_reg1;
+ u32 sequence;
+ u32 host_command_len_reg;
+ u32 host_command_params_reg[HOST_COMMAND_PARAMS_REG_LEN];
+ u32 cmd_status_reg;
+ u32 cmd_status_params_reg[CMD_STATUS_PARAMS_REG_LEN];
+ u32 rxq_base_ptr;
+ u32 rxq_next_ptr;
+ u32 rxq_host_ptr;
+ u32 txq_base_ptr;
+ u32 txq_next_ptr;
+ u32 txq_host_ptr;
+ u32 tx_status_reg;
+ u32 reserved;
+ u32 status_change_reg;
+ u32 reserved1[3];
+ u32 *ordinal1_ptr;
+ u32 *ordinal2_ptr;
+} __attribute__ ((packed));
+
+struct ipw2100_data_header {
+ u32 host_command_reg;
+ u32 host_command_reg1;
+ u8 encrypted; // BOOLEAN in win! TRUE if frame is enc by driver
+ u8 needs_encryption; // BOOLEAN in win! TRUE if frma need to be enc in NIC
+ u8 wep_index; // 0 no key, 1-4 key index, 0xff immediate key
+ u8 key_size; // 0 no imm key, 0x5 64bit encr, 0xd 128bit encr, 0x10 128bit encr and 128bit IV
+ u8 key[16];
+ u8 reserved[10]; // f/w reserved
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+ u16 fragment_size;
+} __attribute__ ((packed));
+
+/* Host command data structure */
+struct host_command {
+ u32 host_command; // COMMAND ID
+ u32 host_command1; // COMMAND ID
+ u32 host_command_sequence; // UNIQUE COMMAND NUMBER (ID)
+ u32 host_command_length; // LENGTH
+ u32 host_command_parameters[HOST_COMMAND_PARAMS_REG_LEN]; // COMMAND PARAMETERS
+} __attribute__ ((packed));
+
+
+typedef enum {
+ POWER_ON_RESET,
+ EXIT_POWER_DOWN_RESET,
+ SW_RESET,
+ EEPROM_RW,
+ SW_RE_INIT
+} ipw2100_reset_event;
+
+enum {
+ COMMAND = 0xCAFE,
+ DATA,
+ RX
+};
+
+
+struct ipw2100_tx_packet {
+ int type;
+ int index;
+ union {
+ struct { /* COMMAND */
+ struct ipw2100_cmd_header* cmd;
+ dma_addr_t cmd_phys;
+ } c_struct;
+ struct { /* DATA */
+ struct ipw2100_data_header* data;
+ dma_addr_t data_phys;
+ struct ieee80211_txb *txb;
+ } d_struct;
+ } info;
+ int jiffy_start;
+
+ struct list_head list;
+};
+
+
+struct ipw2100_rx_packet {
+ struct ipw2100_rx *rxp;
+ dma_addr_t dma_addr;
+ int jiffy_start;
+ struct sk_buff *skb;
+ struct list_head list;
+};
+
+#define FRAG_DISABLED (1<<31)
+#define RTS_DISABLED (1<<31)
+#define MAX_RTS_THRESHOLD 2304U
+#define MIN_RTS_THRESHOLD 1U
+#define DEFAULT_RTS_THRESHOLD 1000U
+
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+struct ipw2100_ordinals {
+ u32 table1_addr;
+ u32 table2_addr;
+ u32 table1_size;
+ u32 table2_size;
+};
+
+/* Host Notification header */
+struct ipw2100_notification {
+ u32 hnhdr_subtype; /* type of host notification */
+ u32 hnhdr_size; /* size in bytes of data
+ or number of entries, if table.
+ Does NOT include header */
+} __attribute__ ((packed));
+
+#define MAX_KEY_SIZE 16
+#define MAX_KEYS 8
+
+#define IPW2100_WEP_ENABLE (1<<1)
+#define IPW2100_WEP_DROP_CLEAR (1<<2)
+
+#define IPW_NONE_CIPHER (1<<0)
+#define IPW_WEP40_CIPHER (1<<1)
+#define IPW_TKIP_CIPHER (1<<2)
+#define IPW_CCMP_CIPHER (1<<4)
+#define IPW_WEP104_CIPHER (1<<5)
+#define IPW_CKIP_CIPHER (1<<6)
+
+#define IPW_AUTH_OPEN 0
+#define IPW_AUTH_SHARED 1
+
+struct statistic {
+ int value;
+ int hi;
+ int lo;
+};
+
+#define INIT_STAT(x) do { \
+ (x)->value = (x)->hi = 0; \
+ (x)->lo = 0x7fffffff; \
+} while (0)
+#define SET_STAT(x,y) do { \
+ (x)->value = y; \
+ if ((x)->value > (x)->hi) (x)->hi = (x)->value; \
+ if ((x)->value < (x)->lo) (x)->lo = (x)->value; \
+} while (0)
+#define INC_STAT(x) do { if (++(x)->value > (x)->hi) (x)->hi = (x)->value; } \
+while (0)
+#define DEC_STAT(x) do { if (--(x)->value < (x)->lo) (x)->lo = (x)->value; } \
+while (0)
+
+#define IPW2100_ERROR_QUEUE 5
+
+/* Power management code: enable or disable? */
+enum {
+#ifdef CONFIG_PM
+ IPW2100_PM_DISABLED = 0,
+ PM_STATE_SIZE = 16,
+#else
+ IPW2100_PM_DISABLED = 1,
+ PM_STATE_SIZE = 0,
+#endif
+};
+
+#define STATUS_POWERED (1<<0)
+#define STATUS_CMD_ACTIVE (1<<1) /**< host command in progress */
+#define STATUS_RUNNING (1<<2) /* Card initialized, but not enabled */
+#define STATUS_ENABLED (1<<3) /* Card enabled -- can scan,Tx,Rx */
+#define STATUS_STOPPING (1<<4) /* Card is in shutdown phase */
+#define STATUS_INITIALIZED (1<<5) /* Card is ready for external calls */
+#define STATUS_ASSOCIATING (1<<9) /* Associated, but no BSSID yet */
+#define STATUS_ASSOCIATED (1<<10) /* Associated and BSSID valid */
+#define STATUS_INT_ENABLED (1<<11)
+#define STATUS_RF_KILL_HW (1<<12)
+#define STATUS_RF_KILL_SW (1<<13)
+#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW)
+#define STATUS_EXIT_PENDING (1<<14)
+
+#define STATUS_SCAN_PENDING (1<<23)
+#define STATUS_SCANNING (1<<24)
+#define STATUS_SCAN_ABORTING (1<<25)
+#define STATUS_SCAN_COMPLETE (1<<26)
+#define STATUS_WX_EVENT_PENDING (1<<27)
+#define STATUS_RESET_PENDING (1<<29)
+#define STATUS_SECURITY_UPDATED (1<<30) /* Security sync needed */
+
+
+
+/* Internal NIC states */
+#define IPW_STATE_INITIALIZED (1<<0)
+#define IPW_STATE_COUNTRY_FOUND (1<<1)
+#define IPW_STATE_ASSOCIATED (1<<2)
+#define IPW_STATE_ASSN_LOST (1<<3)
+#define IPW_STATE_ASSN_CHANGED (1<<4)
+#define IPW_STATE_SCAN_COMPLETE (1<<5)
+#define IPW_STATE_ENTERED_PSP (1<<6)
+#define IPW_STATE_LEFT_PSP (1<<7)
+#define IPW_STATE_RF_KILL (1<<8)
+#define IPW_STATE_DISABLED (1<<9)
+#define IPW_STATE_POWER_DOWN (1<<10)
+#define IPW_STATE_SCANNING (1<<11)
+
+
+
+#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */
+#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */
+#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */
+#define CFG_CUSTOM_MAC (1<<3)
+#define CFG_LONG_PREAMBLE (1<<4)
+#define CFG_ASSOCIATE (1<<6)
+#define CFG_FIXED_RATE (1<<7)
+#define CFG_ADHOC_CREATE (1<<8)
+#define CFG_C3_DISABLED (1<<9)
+#define CFG_PASSIVE_SCAN (1<<10)
+
+#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */
+#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */
+
+struct ipw2100_priv {
+
+ int stop_hang_check; /* Set 1 when shutting down to kill hang_check */
+ int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */
+
+ struct ieee80211_device *ieee;
+ unsigned long status;
+ unsigned long config;
+ unsigned long capability;
+
+ /* Statistics */
+ int resets;
+ int reset_backoff;
+
+ /* Context */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u8 bssid[ETH_ALEN];
+ u8 channel;
+ int last_mode;
+ int cstate_limit;
+
+ unsigned long connect_start;
+ unsigned long last_reset;
+
+ u32 channel_mask;
+ u32 fatal_error;
+ u32 fatal_errors[IPW2100_ERROR_QUEUE];
+ u32 fatal_index;
+ int eeprom_version;
+ int firmware_version;
+ unsigned long hw_features;
+ int hangs;
+ u32 last_rtc;
+ int dump_raw; /* 1 to dump raw bytes in /sys/.../memory */
+ u8* snapshot[0x30];
+
+ u8 mandatory_bssid_mac[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
+
+ int power_mode;
+
+ /* WEP data */
+ struct ieee80211_security sec;
+ int messages_sent;
+
+
+ int short_retry_limit;
+ int long_retry_limit;
+
+ u32 rts_threshold;
+ u32 frag_threshold;
+
+ int in_isr;
+
+ u32 tx_rates;
+ int tx_power;
+ u32 beacon_interval;
+
+ char nick[IW_ESSID_MAX_SIZE + 1];
+
+ struct ipw2100_status_queue status_queue;
+
+ struct statistic txq_stat;
+ struct statistic rxq_stat;
+ struct ipw2100_bd_queue rx_queue;
+ struct ipw2100_bd_queue tx_queue;
+ struct ipw2100_rx_packet *rx_buffers;
+
+ struct statistic fw_pend_stat;
+ struct list_head fw_pend_list;
+
+ struct statistic msg_free_stat;
+ struct statistic msg_pend_stat;
+ struct list_head msg_free_list;
+ struct list_head msg_pend_list;
+ struct ipw2100_tx_packet *msg_buffers;
+
+ struct statistic tx_free_stat;
+ struct statistic tx_pend_stat;
+ struct list_head tx_free_list;
+ struct list_head tx_pend_list;
+ struct ipw2100_tx_packet *tx_buffers;
+
+ struct ipw2100_ordinals ordinals;
+
+ struct pci_dev *pci_dev;
+
+ struct proc_dir_entry *dir_dev;
+
+ struct net_device *net_dev;
+ struct iw_statistics wstats;
+
+ struct tasklet_struct irq_tasklet;
+
+ struct workqueue_struct *workqueue;
+ struct work_struct reset_work;
+ struct work_struct security_work;
+ struct work_struct wx_event_work;
+ struct work_struct hang_check;
+ struct work_struct rf_kill;
+
+ u32 interrupts;
+ int tx_interrupts;
+ int rx_interrupts;
+ int inta_other;
+
+ spinlock_t low_lock;
+ struct semaphore action_sem;
+ struct semaphore adapter_sem;
+
+ wait_queue_head_t wait_command_queue;
+};
+
+
+/*********************************************************
+ * Host Command -> From Driver to FW
+ *********************************************************/
+
+/**
+ * Host command identifiers
+ */
+#define HOST_COMPLETE 2
+#define SYSTEM_CONFIG 6
+#define SSID 8
+#define MANDATORY_BSSID 9
+#define AUTHENTICATION_TYPE 10
+#define ADAPTER_ADDRESS 11
+#define PORT_TYPE 12
+#define INTERNATIONAL_MODE 13
+#define CHANNEL 14
+#define RTS_THRESHOLD 15
+#define FRAG_THRESHOLD 16
+#define POWER_MODE 17
+#define TX_RATES 18
+#define BASIC_TX_RATES 19
+#define WEP_KEY_INFO 20
+#define WEP_KEY_INDEX 25
+#define WEP_FLAGS 26
+#define ADD_MULTICAST 27
+#define CLEAR_ALL_MULTICAST 28
+#define BEACON_INTERVAL 29
+#define ATIM_WINDOW 30
+#define CLEAR_STATISTICS 31
+#define SEND 33
+#define TX_POWER_INDEX 36
+#define BROADCAST_SCAN 43
+#define CARD_DISABLE 44
+#define PREFERRED_BSSID 45
+#define SET_SCAN_OPTIONS 46
+#define SCAN_DWELL_TIME 47
+#define SWEEP_TABLE 48
+#define AP_OR_STATION_TABLE 49
+#define GROUP_ORDINALS 50
+#define SHORT_RETRY_LIMIT 51
+#define LONG_RETRY_LIMIT 52
+
+#define HOST_PRE_POWER_DOWN 58
+#define CARD_DISABLE_PHY_OFF 61
+#define MSDU_TX_RATES 62
+
+
+/* Rogue AP Detection */
+#define SET_STATION_STAT_BITS 64
+#define CLEAR_STATIONS_STAT_BITS 65
+#define LEAP_ROGUE_MODE 66 //TODO tbw replaced by CFG_LEAP_ROGUE_AP
+#define SET_SECURITY_INFORMATION 67
+#define DISASSOCIATION_BSSID 68
+#define SET_WPA_IE 69
+
+
+
+/* system configuration bit mask: */
+#define IPW_CFG_MONITOR 0x00004
+#define IPW_CFG_PREAMBLE_AUTO 0x00010
+#define IPW_CFG_IBSS_AUTO_START 0x00020
+#define IPW_CFG_LOOPBACK 0x00100
+#define IPW_CFG_ANSWER_BCSSID_PROBE 0x00800
+#define IPW_CFG_BT_SIDEBAND_SIGNAL 0x02000
+#define IPW_CFG_802_1x_ENABLE 0x04000
+#define IPW_CFG_BSS_MASK 0x08000
+#define IPW_CFG_IBSS_MASK 0x10000
+
+#define IPW_SCAN_NOASSOCIATE (1<<0)
+#define IPW_SCAN_MIXED_CELL (1<<1)
+/* RESERVED (1<<2) */
+#define IPW_SCAN_PASSIVE (1<<3)
+
+#define IPW_NIC_FATAL_ERROR 0x2A7F0
+#define IPW_ERROR_ADDR(x) (x & 0x3FFFF)
+#define IPW_ERROR_CODE(x) ((x & 0xFF000000) >> 24)
+#define IPW2100_ERR_C3_CORRUPTION (0x10 << 24)
+#define IPW2100_ERR_MSG_TIMEOUT (0x11 << 24)
+#define IPW2100_ERR_FW_LOAD (0x12 << 24)
+
+#define IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND 0x200
+#define IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x0D80
+
+#define IPW_MEM_HOST_SHARED_RX_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x40)
+#define IPW_MEM_HOST_SHARED_RX_STATUS_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x44)
+#define IPW_MEM_HOST_SHARED_RX_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x48)
+#define IPW_MEM_HOST_SHARED_RX_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0xa0)
+
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x00)
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x04)
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x80)
+
+#define IPW_MEM_HOST_SHARED_RX_WRITE_INDEX \
+ (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND + 0x20)
+
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX \
+ (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND)
+
+#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x180)
+#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x184)
+
+#define IPW2100_INTA_TX_TRANSFER (0x00000001) // Bit 0 (LSB)
+#define IPW2100_INTA_RX_TRANSFER (0x00000002) // Bit 1
+#define IPW2100_INTA_TX_COMPLETE (0x00000004) // Bit 2
+#define IPW2100_INTA_EVENT_INTERRUPT (0x00000008) // Bit 3
+#define IPW2100_INTA_STATUS_CHANGE (0x00000010) // Bit 4
+#define IPW2100_INTA_BEACON_PERIOD_EXPIRED (0x00000020) // Bit 5
+#define IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE (0x00010000) // Bit 16
+#define IPW2100_INTA_FW_INIT_DONE (0x01000000) // Bit 24
+#define IPW2100_INTA_FW_CALIBRATION_CALC (0x02000000) // Bit 25
+#define IPW2100_INTA_FATAL_ERROR (0x40000000) // Bit 30
+#define IPW2100_INTA_PARITY_ERROR (0x80000000) // Bit 31 (MSB)
+
+#define IPW_AUX_HOST_RESET_REG_PRINCETON_RESET (0x00000001)
+#define IPW_AUX_HOST_RESET_REG_FORCE_NMI (0x00000002)
+#define IPW_AUX_HOST_RESET_REG_PCI_HOST_CLUSTER_FATAL_NMI (0x00000004)
+#define IPW_AUX_HOST_RESET_REG_CORE_FATAL_NMI (0x00000008)
+#define IPW_AUX_HOST_RESET_REG_SW_RESET (0x00000080)
+#define IPW_AUX_HOST_RESET_REG_MASTER_DISABLED (0x00000100)
+#define IPW_AUX_HOST_RESET_REG_STOP_MASTER (0x00000200)
+
+#define IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY (0x00000001) // Bit 0 (LSB)
+#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY (0x00000002) // Bit 1
+#define IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE (0x00000004) // Bit 2
+#define IPW_AUX_HOST_GP_CNTRL_BITS_SYS_CONFIG (0x000007c0) // Bits 6-10
+#define IPW_AUX_HOST_GP_CNTRL_BIT_BUS_TYPE (0x00000200) // Bit 9
+#define IPW_AUX_HOST_GP_CNTRL_BIT_BAR0_BLOCK_SIZE (0x00000400) // Bit 10
+#define IPW_AUX_HOST_GP_CNTRL_BIT_USB_MODE (0x20000000) // Bit 29
+#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_FORCES_SYS_CLK (0x40000000) // Bit 30
+#define IPW_AUX_HOST_GP_CNTRL_BIT_FW_FORCES_SYS_CLK (0x80000000) // Bit 31 (MSB)
+
+#define IPW_BIT_GPIO_GPIO1_MASK 0x0000000C
+#define IPW_BIT_GPIO_GPIO3_MASK 0x000000C0
+#define IPW_BIT_GPIO_GPIO1_ENABLE 0x00000008
+#define IPW_BIT_GPIO_RF_KILL 0x00010000
+
+#define IPW_BIT_GPIO_LED_OFF 0x00002000 // Bit 13 = 1
+
+#define IPW_REG_DOMAIN_0_OFFSET 0x0000
+#define IPW_REG_DOMAIN_1_OFFSET IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND
+
+#define IPW_REG_INTA IPW_REG_DOMAIN_0_OFFSET + 0x0008
+#define IPW_REG_INTA_MASK IPW_REG_DOMAIN_0_OFFSET + 0x000C
+#define IPW_REG_INDIRECT_ACCESS_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0010
+#define IPW_REG_INDIRECT_ACCESS_DATA IPW_REG_DOMAIN_0_OFFSET + 0x0014
+#define IPW_REG_AUTOINCREMENT_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0018
+#define IPW_REG_AUTOINCREMENT_DATA IPW_REG_DOMAIN_0_OFFSET + 0x001C
+#define IPW_REG_RESET_REG IPW_REG_DOMAIN_0_OFFSET + 0x0020
+#define IPW_REG_GP_CNTRL IPW_REG_DOMAIN_0_OFFSET + 0x0024
+#define IPW_REG_GPIO IPW_REG_DOMAIN_0_OFFSET + 0x0030
+#define IPW_REG_FW_TYPE IPW_REG_DOMAIN_1_OFFSET + 0x0188
+#define IPW_REG_FW_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x018C
+#define IPW_REG_FW_COMPATABILITY_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x0190
+
+#define IPW_REG_INDIRECT_ADDR_MASK 0x00FFFFFC
+
+#define IPW_INTERRUPT_MASK 0xC1010013
+
+#define IPW2100_CONTROL_REG 0x220000
+#define IPW2100_CONTROL_PHY_OFF 0x8
+
+#define IPW2100_COMMAND 0x00300004
+#define IPW2100_COMMAND_PHY_ON 0x0
+#define IPW2100_COMMAND_PHY_OFF 0x1
+
+/* in DEBUG_AREA, values of memory always 0xd55555d5 */
+#define IPW_REG_DOA_DEBUG_AREA_START IPW_REG_DOMAIN_0_OFFSET + 0x0090
+#define IPW_REG_DOA_DEBUG_AREA_END IPW_REG_DOMAIN_0_OFFSET + 0x00FF
+#define IPW_DATA_DOA_DEBUG_VALUE 0xd55555d5
+
+#define IPW_INTERNAL_REGISTER_HALT_AND_RESET 0x003000e0
+
+#define IPW_WAIT_CLOCK_STABILIZATION_DELAY 50 // micro seconds
+#define IPW_WAIT_RESET_ARC_COMPLETE_DELAY 10 // micro seconds
+#define IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY 10 // micro seconds
+
+// BD ring queue read/write difference
+#define IPW_BD_QUEUE_W_R_MIN_SPARE 2
+
+#define IPW_CACHE_LINE_LENGTH_DEFAULT 0x80
+
+#define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli
+#define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli
+
+
+
+
+#define IPW_HEADER_802_11_SIZE sizeof(struct ieee80211_hdr_3addr)
+#define IPW_MAX_80211_PAYLOAD_SIZE 2304U
+#define IPW_MAX_802_11_PAYLOAD_LENGTH 2312
+#define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536
+#define IPW_MIN_ACCEPTABLE_RX_FRAME_LENGTH 60
+#define IPW_MAX_ACCEPTABLE_RX_FRAME_LENGTH \
+ (IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH + IPW_HEADER_802_11_SIZE - \
+ sizeof(struct ethhdr))
+
+#define IPW_802_11_FCS_LENGTH 4
+#define IPW_RX_NIC_BUFFER_LENGTH \
+ (IPW_MAX_802_11_PAYLOAD_LENGTH + IPW_HEADER_802_11_SIZE + \
+ IPW_802_11_FCS_LENGTH)
+
+#define IPW_802_11_PAYLOAD_OFFSET \
+ (sizeof(struct ieee80211_hdr_3addr) + \
+ sizeof(struct ieee80211_snap_hdr))
+
+struct ipw2100_rx {
+ union {
+ unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
+ struct ieee80211_hdr header;
+ u32 status;
+ struct ipw2100_notification notification;
+ struct ipw2100_cmd_header command;
+ } rx_data;
+} __attribute__ ((packed));
+
+/* Bit 0-7 are for 802.11b tx rates - . Bit 5-7 are reserved */
+#define TX_RATE_1_MBIT 0x0001
+#define TX_RATE_2_MBIT 0x0002
+#define TX_RATE_5_5_MBIT 0x0004
+#define TX_RATE_11_MBIT 0x0008
+#define TX_RATE_MASK 0x000F
+#define DEFAULT_TX_RATES 0x000F
+
+#define IPW_POWER_MODE_CAM 0x00 //(always on)
+#define IPW_POWER_INDEX_1 0x01
+#define IPW_POWER_INDEX_2 0x02
+#define IPW_POWER_INDEX_3 0x03
+#define IPW_POWER_INDEX_4 0x04
+#define IPW_POWER_INDEX_5 0x05
+#define IPW_POWER_AUTO 0x06
+#define IPW_POWER_MASK 0x0F
+#define IPW_POWER_ENABLED 0x10
+#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK)
+
+#define IPW_TX_POWER_AUTO 0
+#define IPW_TX_POWER_ENHANCED 1
+
+#define IPW_TX_POWER_DEFAULT 32
+#define IPW_TX_POWER_MIN 0
+#define IPW_TX_POWER_MAX 16
+#define IPW_TX_POWER_MIN_DBM (-12)
+#define IPW_TX_POWER_MAX_DBM 16
+
+#define FW_SCAN_DONOT_ASSOCIATE 0x0001 // Dont Attempt to Associate after Scan
+#define FW_SCAN_PASSIVE 0x0008 // Force PASSSIVE Scan
+
+#define REG_MIN_CHANNEL 0
+#define REG_MAX_CHANNEL 14
+
+#define REG_CHANNEL_MASK 0x00003FFF
+#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff
+
+#define DIVERSITY_EITHER 0 // Use both antennas
+#define DIVERSITY_ANTENNA_A 1 // Use antenna A
+#define DIVERSITY_ANTENNA_B 2 // Use antenna B
+
+
+#define HOST_COMMAND_WAIT 0
+#define HOST_COMMAND_NO_WAIT 1
+
+#define LOCK_NONE 0
+#define LOCK_DRIVER 1
+#define LOCK_FW 2
+
+#define TYPE_SWEEP_ORD 0x000D
+#define TYPE_IBSS_STTN_ORD 0x000E
+#define TYPE_BSS_AP_ORD 0x000F
+#define TYPE_RAW_BEACON_ENTRY 0x0010
+#define TYPE_CALIBRATION_DATA 0x0011
+#define TYPE_ROGUE_AP_DATA 0x0012
+#define TYPE_ASSOCIATION_REQUEST 0x0013
+#define TYPE_REASSOCIATION_REQUEST 0x0014
+
+
+#define HW_FEATURE_RFKILL (0x0001)
+#define RF_KILLSWITCH_OFF (1)
+#define RF_KILLSWITCH_ON (0)
+
+#define IPW_COMMAND_POOL_SIZE 40
+
+#define IPW_START_ORD_TAB_1 1
+#define IPW_START_ORD_TAB_2 1000
+
+#define IPW_ORD_TAB_1_ENTRY_SIZE sizeof(u32)
+
+#define IS_ORDINAL_TABLE_ONE(mgr,id) \
+ ((id >= IPW_START_ORD_TAB_1) && (id < mgr->table1_size))
+#define IS_ORDINAL_TABLE_TWO(mgr,id) \
+ ((id >= IPW_START_ORD_TAB_2) && (id < (mgr->table2_size + IPW_START_ORD_TAB_2)))
+
+#define BSS_ID_LENGTH 6
+
+// Fixed size data: Ordinal Table 1
+typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW
+// Transmit statistics
+ IPW_ORD_STAT_TX_HOST_REQUESTS = 1,// # of requested Host Tx's (MSDU)
+ IPW_ORD_STAT_TX_HOST_COMPLETE, // # of successful Host Tx's (MSDU)
+ IPW_ORD_STAT_TX_DIR_DATA, // # of successful Directed Tx's (MSDU)
+
+ IPW_ORD_STAT_TX_DIR_DATA1 = 4, // # of successful Directed Tx's (MSDU) @ 1MB
+ IPW_ORD_STAT_TX_DIR_DATA2, // # of successful Directed Tx's (MSDU) @ 2MB
+ IPW_ORD_STAT_TX_DIR_DATA5_5, // # of successful Directed Tx's (MSDU) @ 5_5MB
+ IPW_ORD_STAT_TX_DIR_DATA11, // # of successful Directed Tx's (MSDU) @ 11MB
+ IPW_ORD_STAT_TX_DIR_DATA22, // # of successful Directed Tx's (MSDU) @ 22MB
+
+ IPW_ORD_STAT_TX_NODIR_DATA1 = 13,// # of successful Non_Directed Tx's (MSDU) @ 1MB
+ IPW_ORD_STAT_TX_NODIR_DATA2, // # of successful Non_Directed Tx's (MSDU) @ 2MB
+ IPW_ORD_STAT_TX_NODIR_DATA5_5, // # of successful Non_Directed Tx's (MSDU) @ 5.5MB
+ IPW_ORD_STAT_TX_NODIR_DATA11, // # of successful Non_Directed Tx's (MSDU) @ 11MB
+
+ IPW_ORD_STAT_NULL_DATA = 21, // # of successful NULL data Tx's
+ IPW_ORD_STAT_TX_RTS, // # of successful Tx RTS
+ IPW_ORD_STAT_TX_CTS, // # of successful Tx CTS
+ IPW_ORD_STAT_TX_ACK, // # of successful Tx ACK
+ IPW_ORD_STAT_TX_ASSN, // # of successful Association Tx's
+ IPW_ORD_STAT_TX_ASSN_RESP, // # of successful Association response Tx's
+ IPW_ORD_STAT_TX_REASSN, // # of successful Reassociation Tx's
+ IPW_ORD_STAT_TX_REASSN_RESP, // # of successful Reassociation response Tx's
+ IPW_ORD_STAT_TX_PROBE, // # of probes successfully transmitted
+ IPW_ORD_STAT_TX_PROBE_RESP, // # of probe responses successfully transmitted
+ IPW_ORD_STAT_TX_BEACON, // # of tx beacon
+ IPW_ORD_STAT_TX_ATIM, // # of Tx ATIM
+ IPW_ORD_STAT_TX_DISASSN, // # of successful Disassociation TX
+ IPW_ORD_STAT_TX_AUTH, // # of successful Authentication Tx
+ IPW_ORD_STAT_TX_DEAUTH, // # of successful Deauthentication TX
+
+ IPW_ORD_STAT_TX_TOTAL_BYTES = 41,// Total successful Tx data bytes
+ IPW_ORD_STAT_TX_RETRIES, // # of Tx retries
+ IPW_ORD_STAT_TX_RETRY1, // # of Tx retries at 1MBPS
+ IPW_ORD_STAT_TX_RETRY2, // # of Tx retries at 2MBPS
+ IPW_ORD_STAT_TX_RETRY5_5, // # of Tx retries at 5.5MBPS
+ IPW_ORD_STAT_TX_RETRY11, // # of Tx retries at 11MBPS
+
+ IPW_ORD_STAT_TX_FAILURES = 51, // # of Tx Failures
+ IPW_ORD_STAT_TX_ABORT_AT_HOP, //NS // # of Tx's aborted at hop time
+ IPW_ORD_STAT_TX_MAX_TRIES_IN_HOP,// # of times max tries in a hop failed
+ IPW_ORD_STAT_TX_ABORT_LATE_DMA, //NS // # of times tx aborted due to late dma setup
+ IPW_ORD_STAT_TX_ABORT_STX, //NS // # of times backoff aborted
+ IPW_ORD_STAT_TX_DISASSN_FAIL, // # of times disassociation failed
+ IPW_ORD_STAT_TX_ERR_CTS, // # of missed/bad CTS frames
+ IPW_ORD_STAT_TX_BPDU, //NS // # of spanning tree BPDUs sent
+ IPW_ORD_STAT_TX_ERR_ACK, // # of tx err due to acks
+
+ // Receive statistics
+ IPW_ORD_STAT_RX_HOST = 61, // # of packets passed to host
+ IPW_ORD_STAT_RX_DIR_DATA, // # of directed packets
+ IPW_ORD_STAT_RX_DIR_DATA1, // # of directed packets at 1MB
+ IPW_ORD_STAT_RX_DIR_DATA2, // # of directed packets at 2MB
+ IPW_ORD_STAT_RX_DIR_DATA5_5, // # of directed packets at 5.5MB
+ IPW_ORD_STAT_RX_DIR_DATA11, // # of directed packets at 11MB
+ IPW_ORD_STAT_RX_DIR_DATA22, // # of directed packets at 22MB
+
+ IPW_ORD_STAT_RX_NODIR_DATA = 71,// # of nondirected packets
+ IPW_ORD_STAT_RX_NODIR_DATA1, // # of nondirected packets at 1MB
+ IPW_ORD_STAT_RX_NODIR_DATA2, // # of nondirected packets at 2MB
+ IPW_ORD_STAT_RX_NODIR_DATA5_5, // # of nondirected packets at 5.5MB
+ IPW_ORD_STAT_RX_NODIR_DATA11, // # of nondirected packets at 11MB
+
+ IPW_ORD_STAT_RX_NULL_DATA = 80, // # of null data rx's
+ IPW_ORD_STAT_RX_POLL, //NS // # of poll rx
+ IPW_ORD_STAT_RX_RTS, // # of Rx RTS
+ IPW_ORD_STAT_RX_CTS, // # of Rx CTS
+ IPW_ORD_STAT_RX_ACK, // # of Rx ACK
+ IPW_ORD_STAT_RX_CFEND, // # of Rx CF End
+ IPW_ORD_STAT_RX_CFEND_ACK, // # of Rx CF End + CF Ack
+ IPW_ORD_STAT_RX_ASSN, // # of Association Rx's
+ IPW_ORD_STAT_RX_ASSN_RESP, // # of Association response Rx's
+ IPW_ORD_STAT_RX_REASSN, // # of Reassociation Rx's
+ IPW_ORD_STAT_RX_REASSN_RESP, // # of Reassociation response Rx's
+ IPW_ORD_STAT_RX_PROBE, // # of probe Rx's
+ IPW_ORD_STAT_RX_PROBE_RESP, // # of probe response Rx's
+ IPW_ORD_STAT_RX_BEACON, // # of Rx beacon
+ IPW_ORD_STAT_RX_ATIM, // # of Rx ATIM
+ IPW_ORD_STAT_RX_DISASSN, // # of disassociation Rx
+ IPW_ORD_STAT_RX_AUTH, // # of authentication Rx
+ IPW_ORD_STAT_RX_DEAUTH, // # of deauthentication Rx
+
+ IPW_ORD_STAT_RX_TOTAL_BYTES = 101,// Total rx data bytes received
+ IPW_ORD_STAT_RX_ERR_CRC, // # of packets with Rx CRC error
+ IPW_ORD_STAT_RX_ERR_CRC1, // # of Rx CRC errors at 1MB
+ IPW_ORD_STAT_RX_ERR_CRC2, // # of Rx CRC errors at 2MB
+ IPW_ORD_STAT_RX_ERR_CRC5_5, // # of Rx CRC errors at 5.5MB
+ IPW_ORD_STAT_RX_ERR_CRC11, // # of Rx CRC errors at 11MB
+
+ IPW_ORD_STAT_RX_DUPLICATE1 = 112, // # of duplicate rx packets at 1MB
+ IPW_ORD_STAT_RX_DUPLICATE2, // # of duplicate rx packets at 2MB
+ IPW_ORD_STAT_RX_DUPLICATE5_5, // # of duplicate rx packets at 5.5MB
+ IPW_ORD_STAT_RX_DUPLICATE11, // # of duplicate rx packets at 11MB
+ IPW_ORD_STAT_RX_DUPLICATE = 119, // # of duplicate rx packets
+
+ IPW_ORD_PERS_DB_LOCK = 120, // # locking fw permanent db
+ IPW_ORD_PERS_DB_SIZE, // # size of fw permanent db
+ IPW_ORD_PERS_DB_ADDR, // # address of fw permanent db
+ IPW_ORD_STAT_RX_INVALID_PROTOCOL, // # of rx frames with invalid protocol
+ IPW_ORD_SYS_BOOT_TIME, // # Boot time
+ IPW_ORD_STAT_RX_NO_BUFFER, // # of rx frames rejected due to no buffer
+ IPW_ORD_STAT_RX_ABORT_LATE_DMA, //NS // # of rx frames rejected due to dma setup too late
+ IPW_ORD_STAT_RX_ABORT_AT_HOP, //NS // # of rx frames aborted due to hop
+ IPW_ORD_STAT_RX_MISSING_FRAG, // # of rx frames dropped due to missing fragment
+ IPW_ORD_STAT_RX_ORPHAN_FRAG, // # of rx frames dropped due to non-sequential fragment
+ IPW_ORD_STAT_RX_ORPHAN_FRAME, // # of rx frames dropped due to unmatched 1st frame
+ IPW_ORD_STAT_RX_FRAG_AGEOUT, // # of rx frames dropped due to uncompleted frame
+ IPW_ORD_STAT_RX_BAD_SSID, //NS // Bad SSID (unused)
+ IPW_ORD_STAT_RX_ICV_ERRORS, // # of ICV errors during decryption
+
+// PSP Statistics
+ IPW_ORD_STAT_PSP_SUSPENSION = 137,// # of times adapter suspended
+ IPW_ORD_STAT_PSP_BCN_TIMEOUT, // # of beacon timeout
+ IPW_ORD_STAT_PSP_POLL_TIMEOUT, // # of poll response timeouts
+ IPW_ORD_STAT_PSP_NONDIR_TIMEOUT,// # of timeouts waiting for last broadcast/muticast pkt
+ IPW_ORD_STAT_PSP_RX_DTIMS, // # of PSP DTIMs received
+ IPW_ORD_STAT_PSP_RX_TIMS, // # of PSP TIMs received
+ IPW_ORD_STAT_PSP_STATION_ID, // PSP Station ID
+
+// Association and roaming
+ IPW_ORD_LAST_ASSN_TIME = 147, // RTC time of last association
+ IPW_ORD_STAT_PERCENT_MISSED_BCNS,// current calculation of % missed beacons
+ IPW_ORD_STAT_PERCENT_RETRIES, // current calculation of % missed tx retries
+ IPW_ORD_ASSOCIATED_AP_PTR, // If associated, this is ptr to the associated
+ // AP table entry. set to 0 if not associated
+ IPW_ORD_AVAILABLE_AP_CNT, // # of AP's decsribed in the AP table
+ IPW_ORD_AP_LIST_PTR, // Ptr to list of available APs
+ IPW_ORD_STAT_AP_ASSNS, // # of associations
+ IPW_ORD_STAT_ASSN_FAIL, // # of association failures
+ IPW_ORD_STAT_ASSN_RESP_FAIL, // # of failuresdue to response fail
+ IPW_ORD_STAT_FULL_SCANS, // # of full scans
+
+ IPW_ORD_CARD_DISABLED, // # Card Disabled
+ IPW_ORD_STAT_ROAM_INHIBIT, // # of times roaming was inhibited due to ongoing activity
+ IPW_FILLER_40,
+ IPW_ORD_RSSI_AT_ASSN = 160, // RSSI of associated AP at time of association
+ IPW_ORD_STAT_ASSN_CAUSE1, // # of reassociations due to no tx from AP in last N
+ // hops or no prob_ responses in last 3 minutes
+ IPW_ORD_STAT_ASSN_CAUSE2, // # of reassociations due to poor tx/rx quality
+ IPW_ORD_STAT_ASSN_CAUSE3, // # of reassociations due to tx/rx quality with excessive
+ // load at the AP
+ IPW_ORD_STAT_ASSN_CAUSE4, // # of reassociations due to AP RSSI level fell below
+ // eligible group
+ IPW_ORD_STAT_ASSN_CAUSE5, // # of reassociations due to load leveling
+ IPW_ORD_STAT_ASSN_CAUSE6, //NS // # of reassociations due to dropped by Ap
+ IPW_FILLER_41,
+ IPW_FILLER_42,
+ IPW_FILLER_43,
+ IPW_ORD_STAT_AUTH_FAIL, // # of times authentication failed
+ IPW_ORD_STAT_AUTH_RESP_FAIL, // # of times authentication response failed
+ IPW_ORD_STATION_TABLE_CNT, // # of entries in association table
+
+// Other statistics
+ IPW_ORD_RSSI_AVG_CURR = 173, // Current avg RSSI
+ IPW_ORD_STEST_RESULTS_CURR, //NS // Current self test results word
+ IPW_ORD_STEST_RESULTS_CUM, //NS // Cummulative self test results word
+ IPW_ORD_SELF_TEST_STATUS, //NS //
+ IPW_ORD_POWER_MGMT_MODE, // Power mode - 0=CAM, 1=PSP
+ IPW_ORD_POWER_MGMT_INDEX, //NS //
+ IPW_ORD_COUNTRY_CODE, // IEEE country code as recv'd from beacon
+ IPW_ORD_COUNTRY_CHANNELS, // channels suported by country
+// IPW_ORD_COUNTRY_CHANNELS:
+// For 11b the lower 2-byte are used for channels from 1-14
+// and the higher 2-byte are not used.
+ IPW_ORD_RESET_CNT, // # of adapter resets (warm)
+ IPW_ORD_BEACON_INTERVAL, // Beacon interval
+
+ IPW_ORD_PRINCETON_VERSION = 184, //NS // Princeton Version
+ IPW_ORD_ANTENNA_DIVERSITY, // TRUE if antenna diversity is disabled
+ IPW_ORD_CCA_RSSI, //NS // CCA RSSI value (factory programmed)
+ IPW_ORD_STAT_EEPROM_UPDATE, //NS // # of times config EEPROM updated
+ IPW_ORD_DTIM_PERIOD, // # of beacon intervals between DTIMs
+ IPW_ORD_OUR_FREQ, // current radio freq lower digits - channel ID
+
+ IPW_ORD_RTC_TIME = 190, // current RTC time
+ IPW_ORD_PORT_TYPE, // operating mode
+ IPW_ORD_CURRENT_TX_RATE, // current tx rate
+ IPW_ORD_SUPPORTED_RATES, // Bitmap of supported tx rates
+ IPW_ORD_ATIM_WINDOW, // current ATIM Window
+ IPW_ORD_BASIC_RATES, // bitmap of basic tx rates
+ IPW_ORD_NIC_HIGHEST_RATE, // bitmap of basic tx rates
+ IPW_ORD_AP_HIGHEST_RATE, // bitmap of basic tx rates
+ IPW_ORD_CAPABILITIES, // Management frame capability field
+ IPW_ORD_AUTH_TYPE, // Type of authentication
+ IPW_ORD_RADIO_TYPE, // Adapter card platform type
+ IPW_ORD_RTS_THRESHOLD = 201, // Min length of packet after which RTS handshaking is used
+ IPW_ORD_INT_MODE, // International mode
+ IPW_ORD_FRAGMENTATION_THRESHOLD, // protocol frag threshold
+ IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, // EEPROM offset in SRAM
+ IPW_ORD_EEPROM_SRAM_DB_BLOCK_SIZE, // EEPROM size in SRAM
+ IPW_ORD_EEPROM_SKU_CAPABILITY, // EEPROM SKU Capability 206 =
+ IPW_ORD_EEPROM_IBSS_11B_CHANNELS, // EEPROM IBSS 11b channel set
+
+ IPW_ORD_MAC_VERSION = 209, // MAC Version
+ IPW_ORD_MAC_REVISION, // MAC Revision
+ IPW_ORD_RADIO_VERSION, // Radio Version
+ IPW_ORD_NIC_MANF_DATE_TIME, // MANF Date/Time STAMP
+ IPW_ORD_UCODE_VERSION, // Ucode Version
+ IPW_ORD_HW_RF_SWITCH_STATE = 214, // HW RF Kill Switch State
+} ORDINALTABLE1;
+
+// ordinal table 2
+// Variable length data:
+#define IPW_FIRST_VARIABLE_LENGTH_ORDINAL 1001
+
+typedef enum _ORDINAL_TABLE_2 { // NS - means Not Supported by FW
+ IPW_ORD_STAT_BASE = 1000, // contains number of variable ORDs
+ IPW_ORD_STAT_ADAPTER_MAC = 1001, // 6 bytes: our adapter MAC address
+ IPW_ORD_STAT_PREFERRED_BSSID = 1002, // 6 bytes: BSSID of the preferred AP
+ IPW_ORD_STAT_MANDATORY_BSSID = 1003, // 6 bytes: BSSID of the mandatory AP
+ IPW_FILL_1, //NS //
+ IPW_ORD_STAT_COUNTRY_TEXT = 1005, // 36 bytes: Country name text, First two bytes are Country code
+ IPW_ORD_STAT_ASSN_SSID = 1006, // 32 bytes: ESSID String
+ IPW_ORD_STATION_TABLE = 1007, // ? bytes: Station/AP table (via Direct SSID Scans)
+ IPW_ORD_STAT_SWEEP_TABLE = 1008, // ? bytes: Sweep/Host Table table (via Broadcast Scans)
+ IPW_ORD_STAT_ROAM_LOG = 1009, // ? bytes: Roaming log
+ IPW_ORD_STAT_RATE_LOG = 1010, //NS // 0 bytes: Rate log
+ IPW_ORD_STAT_FIFO = 1011, //NS // 0 bytes: Fifo buffer data structures
+ IPW_ORD_STAT_FW_VER_NUM = 1012, // 14 bytes: fw version ID string as in (a.bb.ccc; "0.08.011")
+ IPW_ORD_STAT_FW_DATE = 1013, // 14 bytes: fw date string (mmm dd yyyy; "Mar 13 2002")
+ IPW_ORD_STAT_ASSN_AP_BSSID = 1014, // 6 bytes: MAC address of associated AP
+ IPW_ORD_STAT_DEBUG = 1015, //NS // ? bytes:
+ IPW_ORD_STAT_NIC_BPA_NUM = 1016, // 11 bytes: NIC BPA number in ASCII
+ IPW_ORD_STAT_UCODE_DATE = 1017, // 5 bytes: uCode date
+ IPW_ORD_SECURITY_NGOTIATION_RESULT = 1018,
+} ORDINALTABLE2; // NS - means Not Supported by FW
+
+#define IPW_LAST_VARIABLE_LENGTH_ORDINAL 1018
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY // enable iwspy support
+#endif
+
+#define IPW_HOST_FW_SHARED_AREA0 0x0002f200
+#define IPW_HOST_FW_SHARED_AREA0_END 0x0002f510 // 0x310 bytes
+
+#define IPW_HOST_FW_SHARED_AREA1 0x0002f610
+#define IPW_HOST_FW_SHARED_AREA1_END 0x0002f630 // 0x20 bytes
+
+#define IPW_HOST_FW_SHARED_AREA2 0x0002fa00
+#define IPW_HOST_FW_SHARED_AREA2_END 0x0002fa20 // 0x20 bytes
+
+#define IPW_HOST_FW_SHARED_AREA3 0x0002fc00
+#define IPW_HOST_FW_SHARED_AREA3_END 0x0002fc10 // 0x10 bytes
+
+#define IPW_HOST_FW_INTERRUPT_AREA 0x0002ff80
+#define IPW_HOST_FW_INTERRUPT_AREA_END 0x00030000 // 0x80 bytes
+
+struct ipw2100_fw_chunk {
+ unsigned char *buf;
+ long len;
+ long pos;
+ struct list_head list;
+};
+
+struct ipw2100_fw_chunk_set {
+ const void *data;
+ unsigned long size;
+};
+
+struct ipw2100_fw {
+ int version;
+ struct ipw2100_fw_chunk_set fw;
+ struct ipw2100_fw_chunk_set uc;
+ const struct firmware *fw_entry;
+};
+
+#define MAX_FW_VERSION_LEN 14
+
+#endif /* _IPW2100_H */
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
new file mode 100644
index 000000000000..b7f275c00de3
--- /dev/null
+++ b/drivers/net/wireless/ipw2200.c
@@ -0,0 +1,7383 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ 802.11 status code portion of this file from ethereal-0.10.6:
+ Copyright 2000, Axis Communications AB
+ Ethereal - Network traffic analyzer
+ By Gerald Combs <gerald@ethereal.com>
+ Copyright 1998 Gerald Combs
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#include "ipw2200.h"
+
+#define IPW2200_VERSION "1.0.0"
+#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
+#define DRV_VERSION IPW2200_VERSION
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static int channel = 0;
+static char *ifname;
+static int mode = 0;
+
+static u32 ipw_debug_level;
+static int associate = 1;
+static int auto_create = 1;
+static int disable = 0;
+static const char ipw_modes[] = {
+ 'a', 'b', 'g', '?'
+};
+
+static void ipw_rx(struct ipw_priv *priv);
+static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq, int qindex);
+static int ipw_queue_reset(struct ipw_priv *priv);
+
+static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
+ int len, int sync);
+
+static void ipw_tx_queue_free(struct ipw_priv *);
+
+static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *);
+static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *);
+static void ipw_rx_queue_replenish(void *);
+
+static int ipw_up(struct ipw_priv *);
+static void ipw_down(struct ipw_priv *);
+static int ipw_config(struct ipw_priv *);
+static int init_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *prates);
+
+static u8 band_b_active_channel[MAX_B_CHANNELS] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0
+};
+static u8 band_a_active_channel[MAX_A_CHANNELS] = {
+ 36, 40, 44, 48, 149, 153, 157, 161, 165, 52, 56, 60, 64, 0
+};
+
+static int is_valid_channel(int mode_mask, int channel)
+{
+ int i;
+
+ if (!channel)
+ return 0;
+
+ if (mode_mask & IEEE_A)
+ for (i = 0; i < MAX_A_CHANNELS; i++)
+ if (band_a_active_channel[i] == channel)
+ return IEEE_A;
+
+ if (mode_mask & (IEEE_B | IEEE_G))
+ for (i = 0; i < MAX_B_CHANNELS; i++)
+ if (band_b_active_channel[i] == channel)
+ return mode_mask & (IEEE_B | IEEE_G);
+
+ return 0;
+}
+
+static char *snprint_line(char *buf, size_t count,
+ const u8 * data, u32 len, u32 ofs)
+{
+ int out, i, j, l;
+ char c;
+
+ out = snprintf(buf, count, "%08X", ofs);
+
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++)
+ out += snprintf(buf + out, count - out, "%02X ",
+ data[(i * 8 + j)]);
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ out += snprintf(buf + out, count - out, " ");
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++) {
+ c = data[(i * 8 + j)];
+ if (!isascii(c) || !isprint(c))
+ c = '.';
+
+ out += snprintf(buf + out, count - out, "%c", c);
+ }
+
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ return buf;
+}
+
+static void printk_buf(int level, const u8 * data, u32 len)
+{
+ char line[81];
+ u32 ofs = 0;
+ if (!(ipw_debug_level & level))
+ return;
+
+ while (len) {
+ printk(KERN_DEBUG "%s\n",
+ snprint_line(line, sizeof(line), &data[ofs],
+ min(len, 16U), ofs));
+ ofs += 16;
+ len -= min(len, 16U);
+ }
+}
+
+static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg);
+#define ipw_read_reg32(a, b) _ipw_read_reg32(a, b)
+
+static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg);
+#define ipw_read_reg8(a, b) _ipw_read_reg8(a, b)
+
+static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value);
+static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect8(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg8(a, b, c);
+}
+
+static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value);
+static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect16(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg16(a, b, c);
+}
+
+static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value);
+static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect32(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg32(a, b, c);
+}
+
+#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
+#define ipw_write8(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write8(ipw, ofs, val)
+
+#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
+#define ipw_write16(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write16(ipw, ofs, val)
+
+#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
+#define ipw_write32(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write32(ipw, ofs, val)
+
+#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
+static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read8(ipw, ofs);
+}
+
+#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
+
+#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
+static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read16(ipw, ofs);
+}
+
+#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
+
+#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
+static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read32(ipw, ofs);
+}
+
+#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
+
+static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
+#define ipw_read_indirect(a, b, c, d) \
+ IPW_DEBUG_IO("%s %d: read_inddirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
+ _ipw_read_indirect(a, b, c, d)
+
+static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
+ int num);
+#define ipw_write_indirect(a, b, c, d) \
+ IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
+ _ipw_write_indirect(a, b, c, d)
+
+/* indirect write s */
+static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
+{
+ IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg);
+ _ipw_write32(priv, CX2_INDIRECT_DATA, value);
+}
+
+static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value)
+{
+ IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ _ipw_write8(priv, CX2_INDIRECT_DATA, value);
+ IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n",
+ (unsigned long)(priv->hw_base + CX2_INDIRECT_DATA), value);
+}
+
+static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value)
+{
+ IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ _ipw_write16(priv, CX2_INDIRECT_DATA, value);
+}
+
+/* indirect read s */
+
+static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
+{
+ u32 word;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ IPW_DEBUG_IO(" reg = 0x%8X : \n", reg);
+ word = _ipw_read32(priv, CX2_INDIRECT_DATA);
+ return (word >> ((reg & 0x3) * 8)) & 0xff;
+}
+
+static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
+{
+ u32 value;
+
+ IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg);
+
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg);
+ value = _ipw_read32(priv, CX2_INDIRECT_DATA);
+ IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value);
+ return value;
+}
+
+/* iterative/auto-increment 32 bit reads and writes */
+static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
+ int num)
+{
+ u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK;
+ u32 dif_len = addr - aligned_addr;
+ u32 aligned_len;
+ u32 i;
+
+ IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);
+
+ /* Read the first nibble byte by byte */
+ if (unlikely(dif_len)) {
+ /* Start reading at aligned_addr + dif_len */
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ *buf = _ipw_read8(priv, CX2_INDIRECT_DATA + i);
+ num -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* Read DWs through autoinc register */
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr);
+ aligned_len = num & CX2_INDIRECT_ADDR_MASK;
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ *(u32 *) buf = ipw_read32(priv, CX2_AUTOINC_DATA);
+
+ /* Copy the last nibble */
+ dif_len = num - aligned_len;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ *buf = ipw_read8(priv, CX2_INDIRECT_DATA + i);
+}
+
+static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
+ int num)
+{
+ u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK;
+ u32 dif_len = addr - aligned_addr;
+ u32 aligned_len;
+ u32 i;
+
+ IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);
+
+ /* Write the first nibble byte by byte */
+ if (unlikely(dif_len)) {
+ /* Start writing at aligned_addr + dif_len */
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf);
+ num -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* Write DWs through autoinc register */
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr);
+ aligned_len = num & CX2_INDIRECT_ADDR_MASK;
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ _ipw_write32(priv, CX2_AUTOINC_DATA, *(u32 *) buf);
+
+ /* Copy the last nibble */
+ dif_len = num - aligned_len;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf);
+}
+
+static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf,
+ int num)
+{
+ memcpy_toio((priv->hw_base + addr), buf, num);
+}
+
+static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask)
+{
+ ipw_write32(priv, reg, ipw_read32(priv, reg) | mask);
+}
+
+static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask)
+{
+ ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
+}
+
+static inline void ipw_enable_interrupts(struct ipw_priv *priv)
+{
+ if (priv->status & STATUS_INT_ENABLED)
+ return;
+ priv->status |= STATUS_INT_ENABLED;
+ ipw_write32(priv, CX2_INTA_MASK_R, CX2_INTA_MASK_ALL);
+}
+
+static inline void ipw_disable_interrupts(struct ipw_priv *priv)
+{
+ if (!(priv->status & STATUS_INT_ENABLED))
+ return;
+ priv->status &= ~STATUS_INT_ENABLED;
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+}
+
+static char *ipw_error_desc(u32 val)
+{
+ switch (val) {
+ case IPW_FW_ERROR_OK:
+ return "ERROR_OK";
+ case IPW_FW_ERROR_FAIL:
+ return "ERROR_FAIL";
+ case IPW_FW_ERROR_MEMORY_UNDERFLOW:
+ return "MEMORY_UNDERFLOW";
+ case IPW_FW_ERROR_MEMORY_OVERFLOW:
+ return "MEMORY_OVERFLOW";
+ case IPW_FW_ERROR_BAD_PARAM:
+ return "ERROR_BAD_PARAM";
+ case IPW_FW_ERROR_BAD_CHECKSUM:
+ return "ERROR_BAD_CHECKSUM";
+ case IPW_FW_ERROR_NMI_INTERRUPT:
+ return "ERROR_NMI_INTERRUPT";
+ case IPW_FW_ERROR_BAD_DATABASE:
+ return "ERROR_BAD_DATABASE";
+ case IPW_FW_ERROR_ALLOC_FAIL:
+ return "ERROR_ALLOC_FAIL";
+ case IPW_FW_ERROR_DMA_UNDERRUN:
+ return "ERROR_DMA_UNDERRUN";
+ case IPW_FW_ERROR_DMA_STATUS:
+ return "ERROR_DMA_STATUS";
+ case IPW_FW_ERROR_DINOSTATUS_ERROR:
+ return "ERROR_DINOSTATUS_ERROR";
+ case IPW_FW_ERROR_EEPROMSTATUS_ERROR:
+ return "ERROR_EEPROMSTATUS_ERROR";
+ case IPW_FW_ERROR_SYSASSERT:
+ return "ERROR_SYSASSERT";
+ case IPW_FW_ERROR_FATAL_ERROR:
+ return "ERROR_FATALSTATUS_ERROR";
+ default:
+ return "UNKNOWNSTATUS_ERROR";
+ }
+}
+
+static void ipw_dump_nic_error_log(struct ipw_priv *priv)
+{
+ u32 desc, time, blink1, blink2, ilink1, ilink2, idata, i, count, base;
+
+ base = ipw_read32(priv, IPWSTATUS_ERROR_LOG);
+ count = ipw_read_reg32(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IPW_ERROR("Start IPW Error Log Dump:\n");
+ IPW_ERROR("Status: 0x%08X, Config: %08X\n",
+ priv->status, priv->config);
+ }
+
+ for (i = ERROR_START_OFFSET;
+ i <= count * ERROR_ELEM_SIZE; i += ERROR_ELEM_SIZE) {
+ desc = ipw_read_reg32(priv, base + i);
+ time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32));
+ blink1 = ipw_read_reg32(priv, base + i + 2 * sizeof(u32));
+ blink2 = ipw_read_reg32(priv, base + i + 3 * sizeof(u32));
+ ilink1 = ipw_read_reg32(priv, base + i + 4 * sizeof(u32));
+ ilink2 = ipw_read_reg32(priv, base + i + 5 * sizeof(u32));
+ idata = ipw_read_reg32(priv, base + i + 6 * sizeof(u32));
+
+ IPW_ERROR("%s %i 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ipw_error_desc(desc), time, blink1, blink2,
+ ilink1, ilink2, idata);
+ }
+}
+
+static void ipw_dump_nic_event_log(struct ipw_priv *priv)
+{
+ u32 ev, time, data, i, count, base;
+
+ base = ipw_read32(priv, IPW_EVENT_LOG);
+ count = ipw_read_reg32(priv, base);
+
+ if (EVENT_START_OFFSET <= count * EVENT_ELEM_SIZE)
+ IPW_ERROR("Start IPW Event Log Dump:\n");
+
+ for (i = EVENT_START_OFFSET;
+ i <= count * EVENT_ELEM_SIZE; i += EVENT_ELEM_SIZE) {
+ ev = ipw_read_reg32(priv, base + i);
+ time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32));
+ data = ipw_read_reg32(priv, base + i + 2 * sizeof(u32));
+
+#ifdef CONFIG_IPW_DEBUG
+ IPW_ERROR("%i\t0x%08x\t%i\n", time, data, ev);
+#endif
+ }
+}
+
+static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len)
+{
+ u32 addr, field_info, field_len, field_count, total_len;
+
+ IPW_DEBUG_ORD("ordinal = %i\n", ord);
+
+ if (!priv || !val || !len) {
+ IPW_DEBUG_ORD("Invalid argument\n");
+ return -EINVAL;
+ }
+
+ /* verify device ordinal tables have been initialized */
+ if (!priv->table0_addr || !priv->table1_addr || !priv->table2_addr) {
+ IPW_DEBUG_ORD("Access ordinals before initialization\n");
+ return -EINVAL;
+ }
+
+ switch (IPW_ORD_TABLE_ID_MASK & ord) {
+ case IPW_ORD_TABLE_0_MASK:
+ /*
+ * TABLE 0: Direct access to a table of 32 bit values
+ *
+ * This is a very simple table with the data directly
+ * read from the table
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table0_len) {
+ IPW_DEBUG_ORD("ordinal value (%i) longer then "
+ "max (%i)\n", ord, priv->table0_len);
+ return -EINVAL;
+ }
+
+ /* verify we have enough room to store the value */
+ if (*len < sizeof(u32)) {
+ IPW_DEBUG_ORD("ordinal buffer length too small, "
+ "need %zd\n", sizeof(u32));
+ return -EINVAL;
+ }
+
+ IPW_DEBUG_ORD("Reading TABLE0[%i] from offset 0x%08x\n",
+ ord, priv->table0_addr + (ord << 2));
+
+ *len = sizeof(u32);
+ ord <<= 2;
+ *((u32 *) val) = ipw_read32(priv, priv->table0_addr + ord);
+ break;
+
+ case IPW_ORD_TABLE_1_MASK:
+ /*
+ * TABLE 1: Indirect access to a table of 32 bit values
+ *
+ * This is a fairly large table of u32 values each
+ * representing starting addr for the data (which is
+ * also a u32)
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table1_len) {
+ IPW_DEBUG_ORD("ordinal value too long\n");
+ return -EINVAL;
+ }
+
+ /* verify we have enough room to store the value */
+ if (*len < sizeof(u32)) {
+ IPW_DEBUG_ORD("ordinal buffer length too small, "
+ "need %zd\n", sizeof(u32));
+ return -EINVAL;
+ }
+
+ *((u32 *) val) =
+ ipw_read_reg32(priv, (priv->table1_addr + (ord << 2)));
+ *len = sizeof(u32);
+ break;
+
+ case IPW_ORD_TABLE_2_MASK:
+ /*
+ * TABLE 2: Indirect access to a table of variable sized values
+ *
+ * This table consist of six values, each containing
+ * - dword containing the starting offset of the data
+ * - dword containing the lengh in the first 16bits
+ * and the count in the second 16bits
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table2_len) {
+ IPW_DEBUG_ORD("ordinal value too long\n");
+ return -EINVAL;
+ }
+
+ /* get the address of statistic */
+ addr = ipw_read_reg32(priv, priv->table2_addr + (ord << 3));
+
+ /* get the second DW of statistics ;
+ * two 16-bit words - first is length, second is count */
+ field_info =
+ ipw_read_reg32(priv,
+ priv->table2_addr + (ord << 3) +
+ sizeof(u32));
+
+ /* get each entry length */
+ field_len = *((u16 *) & field_info);
+
+ /* get number of entries */
+ field_count = *(((u16 *) & field_info) + 1);
+
+ /* abort if not enought memory */
+ total_len = field_len * field_count;
+ if (total_len > *len) {
+ *len = total_len;
+ return -EINVAL;
+ }
+
+ *len = total_len;
+ if (!total_len)
+ return 0;
+
+ IPW_DEBUG_ORD("addr = 0x%08x, total_len = %i, "
+ "field_info = 0x%08x\n",
+ addr, total_len, field_info);
+ ipw_read_indirect(priv, addr, val, total_len);
+ break;
+
+ default:
+ IPW_DEBUG_ORD("Invalid ordinal!\n");
+ return -EINVAL;
+
+ }
+
+ return 0;
+}
+
+static void ipw_init_ordinals(struct ipw_priv *priv)
+{
+ priv->table0_addr = IPW_ORDINALS_TABLE_LOWER;
+ priv->table0_len = ipw_read32(priv, priv->table0_addr);
+
+ IPW_DEBUG_ORD("table 0 offset at 0x%08x, len = %i\n",
+ priv->table0_addr, priv->table0_len);
+
+ priv->table1_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_1);
+ priv->table1_len = ipw_read_reg32(priv, priv->table1_addr);
+
+ IPW_DEBUG_ORD("table 1 offset at 0x%08x, len = %i\n",
+ priv->table1_addr, priv->table1_len);
+
+ priv->table2_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_2);
+ priv->table2_len = ipw_read_reg32(priv, priv->table2_addr);
+ priv->table2_len &= 0x0000ffff; /* use first two bytes */
+
+ IPW_DEBUG_ORD("table 2 offset at 0x%08x, len = %i\n",
+ priv->table2_addr, priv->table2_len);
+
+}
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
+ * used for controling the debug level.
+ *
+ * See the level definitions in ipw for details.
+ */
+static ssize_t show_debug_level(struct device_driver *d, char *buf)
+{
+ return sprintf(buf, "0x%08X\n", ipw_debug_level);
+}
+static ssize_t store_debug_level(struct device_driver *d,
+ const char *buf, size_t count)
+{
+ char *p = (char *)buf;
+ u32 val;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buf)
+ printk(KERN_INFO DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ipw_debug_level = val;
+
+ return strnlen(buf, count);
+}
+
+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ show_debug_level, store_debug_level);
+
+static ssize_t show_status(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->status);
+}
+
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->config);
+}
+
+static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL);
+
+static ssize_t show_nic_type(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ u8 type = p->eeprom[EEPROM_NIC_TYPE];
+
+ switch (type) {
+ case EEPROM_NIC_TYPE_STANDARD:
+ return sprintf(buf, "STANDARD\n");
+ case EEPROM_NIC_TYPE_DELL:
+ return sprintf(buf, "DELL\n");
+ case EEPROM_NIC_TYPE_FUJITSU:
+ return sprintf(buf, "FUJITSU\n");
+ case EEPROM_NIC_TYPE_IBM:
+ return sprintf(buf, "IBM\n");
+ case EEPROM_NIC_TYPE_HP:
+ return sprintf(buf, "HP\n");
+ }
+
+ return sprintf(buf, "UNKNOWN\n");
+}
+
+static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL);
+
+static ssize_t dump_error_log(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+ ipw_dump_nic_error_log((struct ipw_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
+
+static ssize_t dump_event_log(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+ ipw_dump_nic_event_log((struct ipw_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
+
+static ssize_t show_ucode_version(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 len = sizeof(u32), tmp = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len))
+ return 0;
+
+ return sprintf(buf, "0x%08x\n", tmp);
+}
+
+static DEVICE_ATTR(ucode_version, S_IWUSR | S_IRUGO, show_ucode_version, NULL);
+
+static ssize_t show_rtc(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ u32 len = sizeof(u32), tmp = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len))
+ return 0;
+
+ return sprintf(buf, "0x%08x\n", tmp);
+}
+
+static DEVICE_ATTR(rtc, S_IWUSR | S_IRUGO, show_rtc, NULL);
+
+/*
+ * Add a device attribute to view/control the delay between eeprom
+ * operations.
+ */
+static ssize_t show_eeprom_delay(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ int n = ((struct ipw_priv *)d->driver_data)->eeprom_delay;
+ return sprintf(buf, "%i\n", n);
+}
+static ssize_t store_eeprom_delay(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *p = d->driver_data;
+ sscanf(buf, "%i", &p->eeprom_delay);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(eeprom_delay, S_IWUSR | S_IRUGO,
+ show_eeprom_delay, store_eeprom_delay);
+
+static ssize_t show_command_event_reg(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ reg = ipw_read_reg32(p, CX2_INTERNAL_CMD_EVENT);
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_command_event_reg(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 reg;
+ struct ipw_priv *p = d->driver_data;
+
+ sscanf(buf, "%x", &reg);
+ ipw_write_reg32(p, CX2_INTERNAL_CMD_EVENT, reg);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(command_event_reg, S_IWUSR | S_IRUGO,
+ show_command_event_reg, store_command_event_reg);
+
+static ssize_t show_mem_gpio_reg(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ reg = ipw_read_reg32(p, 0x301100);
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_mem_gpio_reg(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 reg;
+ struct ipw_priv *p = d->driver_data;
+
+ sscanf(buf, "%x", &reg);
+ ipw_write_reg32(p, 0x301100, reg);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(mem_gpio_reg, S_IWUSR | S_IRUGO,
+ show_mem_gpio_reg, store_mem_gpio_reg);
+
+static ssize_t show_indirect_dword(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+ if (priv->status & STATUS_INDIRECT_DWORD)
+ reg = ipw_read_reg32(priv, priv->indirect_dword);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_indirect_dword(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->indirect_dword);
+ priv->status |= STATUS_INDIRECT_DWORD;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(indirect_dword, S_IWUSR | S_IRUGO,
+ show_indirect_dword, store_indirect_dword);
+
+static ssize_t show_indirect_byte(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u8 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+ if (priv->status & STATUS_INDIRECT_BYTE)
+ reg = ipw_read_reg8(priv, priv->indirect_byte);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%02x\n", reg);
+}
+static ssize_t store_indirect_byte(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->indirect_byte);
+ priv->status |= STATUS_INDIRECT_BYTE;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(indirect_byte, S_IWUSR | S_IRUGO,
+ show_indirect_byte, store_indirect_byte);
+
+static ssize_t show_direct_dword(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+
+ if (priv->status & STATUS_DIRECT_DWORD)
+ reg = ipw_read32(priv, priv->direct_dword);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_direct_dword(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->direct_dword);
+ priv->status |= STATUS_DIRECT_DWORD;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,
+ show_direct_dword, store_direct_dword);
+
+static inline int rf_kill_active(struct ipw_priv *priv)
+{
+ if (0 == (ipw_read32(priv, 0x30) & 0x10000))
+ priv->status |= STATUS_RF_KILL_HW;
+ else
+ priv->status &= ~STATUS_RF_KILL_HW;
+
+ return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;
+}
+
+static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ /* 0 - RF kill not enabled
+ 1 - SW based RF kill active (sysfs)
+ 2 - HW based RF kill active
+ 3 - Both HW and SW baed RF kill active */
+ struct ipw_priv *priv = d->driver_data;
+ int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
+ (rf_kill_active(priv) ? 0x2 : 0x0);
+ return sprintf(buf, "%i\n", val);
+}
+
+static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
+{
+ if ((disable_radio ? 1 : 0) ==
+ (priv->status & STATUS_RF_KILL_SW ? 1 : 0))
+ return 0;
+
+ IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n",
+ disable_radio ? "OFF" : "ON");
+
+ if (disable_radio) {
+ priv->status |= STATUS_RF_KILL_SW;
+
+ if (priv->workqueue) {
+ cancel_delayed_work(&priv->request_scan);
+ }
+ wake_up_interruptible(&priv->wait_command_queue);
+ queue_work(priv->workqueue, &priv->down);
+ } else {
+ priv->status &= ~STATUS_RF_KILL_SW;
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by HW switch\n");
+ /* Make sure the RF_KILL check timer is running */
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ 2 * HZ);
+ } else
+ queue_work(priv->workqueue, &priv->up);
+ }
+
+ return 1;
+}
+
+static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ ipw_radio_kill_sw(priv, buf[0] == '1');
+
+ return count;
+}
+
+static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
+
+static void ipw_irq_tasklet(struct ipw_priv *priv)
+{
+ u32 inta, inta_mask, handled = 0;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ inta = ipw_read32(priv, CX2_INTA_RW);
+ inta_mask = ipw_read32(priv, CX2_INTA_MASK_R);
+ inta &= (CX2_INTA_MASK_ALL & inta_mask);
+
+ /* Add any cached INTA values that need to be handled */
+ inta |= priv->isr_inta;
+
+ /* handle all the justifications for the interrupt */
+ if (inta & CX2_INTA_BIT_RX_TRANSFER) {
+ ipw_rx(priv);
+ handled |= CX2_INTA_BIT_RX_TRANSFER;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_CMD_QUEUE) {
+ IPW_DEBUG_HC("Command completed.\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1);
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ wake_up_interruptible(&priv->wait_command_queue);
+ handled |= CX2_INTA_BIT_TX_CMD_QUEUE;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_1) {
+ IPW_DEBUG_TX("TX_QUEUE_1\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0);
+ handled |= CX2_INTA_BIT_TX_QUEUE_1;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_2) {
+ IPW_DEBUG_TX("TX_QUEUE_2\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1);
+ handled |= CX2_INTA_BIT_TX_QUEUE_2;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_3) {
+ IPW_DEBUG_TX("TX_QUEUE_3\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2);
+ handled |= CX2_INTA_BIT_TX_QUEUE_3;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_4) {
+ IPW_DEBUG_TX("TX_QUEUE_4\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3);
+ handled |= CX2_INTA_BIT_TX_QUEUE_4;
+ }
+
+ if (inta & CX2_INTA_BIT_STATUS_CHANGE) {
+ IPW_WARNING("STATUS_CHANGE\n");
+ handled |= CX2_INTA_BIT_STATUS_CHANGE;
+ }
+
+ if (inta & CX2_INTA_BIT_BEACON_PERIOD_EXPIRED) {
+ IPW_WARNING("TX_PERIOD_EXPIRED\n");
+ handled |= CX2_INTA_BIT_BEACON_PERIOD_EXPIRED;
+ }
+
+ if (inta & CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) {
+ IPW_WARNING("HOST_CMD_DONE\n");
+ handled |= CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FW_INITIALIZATION_DONE) {
+ IPW_WARNING("FW_INITIALIZATION_DONE\n");
+ handled |= CX2_INTA_BIT_FW_INITIALIZATION_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) {
+ IPW_WARNING("PHY_OFF_DONE\n");
+ handled |= CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_RF_KILL_DONE) {
+ IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
+ priv->status |= STATUS_RF_KILL_HW;
+ wake_up_interruptible(&priv->wait_command_queue);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ cancel_delayed_work(&priv->request_scan);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+ handled |= CX2_INTA_BIT_RF_KILL_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FATAL_ERROR) {
+ IPW_ERROR("Firmware error detected. Restarting.\n");
+#ifdef CONFIG_IPW_DEBUG
+ if (ipw_debug_level & IPW_DL_FW_ERRORS) {
+ ipw_dump_nic_error_log(priv);
+ ipw_dump_nic_event_log(priv);
+ }
+#endif
+ queue_work(priv->workqueue, &priv->adapter_restart);
+ handled |= CX2_INTA_BIT_FATAL_ERROR;
+ }
+
+ if (inta & CX2_INTA_BIT_PARITY_ERROR) {
+ IPW_ERROR("Parity error\n");
+ handled |= CX2_INTA_BIT_PARITY_ERROR;
+ }
+
+ if (handled != inta) {
+ IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
+ }
+
+ /* enable all interrupts */
+ ipw_enable_interrupts(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_CMD(x) case IPW_CMD_ ## x : return #x
+static char *get_cmd_string(u8 cmd)
+{
+ switch (cmd) {
+ IPW_CMD(HOST_COMPLETE);
+ IPW_CMD(POWER_DOWN);
+ IPW_CMD(SYSTEM_CONFIG);
+ IPW_CMD(MULTICAST_ADDRESS);
+ IPW_CMD(SSID);
+ IPW_CMD(ADAPTER_ADDRESS);
+ IPW_CMD(PORT_TYPE);
+ IPW_CMD(RTS_THRESHOLD);
+ IPW_CMD(FRAG_THRESHOLD);
+ IPW_CMD(POWER_MODE);
+ IPW_CMD(WEP_KEY);
+ IPW_CMD(TGI_TX_KEY);
+ IPW_CMD(SCAN_REQUEST);
+ IPW_CMD(SCAN_REQUEST_EXT);
+ IPW_CMD(ASSOCIATE);
+ IPW_CMD(SUPPORTED_RATES);
+ IPW_CMD(SCAN_ABORT);
+ IPW_CMD(TX_FLUSH);
+ IPW_CMD(QOS_PARAMETERS);
+ IPW_CMD(DINO_CONFIG);
+ IPW_CMD(RSN_CAPABILITIES);
+ IPW_CMD(RX_KEY);
+ IPW_CMD(CARD_DISABLE);
+ IPW_CMD(SEED_NUMBER);
+ IPW_CMD(TX_POWER);
+ IPW_CMD(COUNTRY_INFO);
+ IPW_CMD(AIRONET_INFO);
+ IPW_CMD(AP_TX_POWER);
+ IPW_CMD(CCKM_INFO);
+ IPW_CMD(CCX_VER_INFO);
+ IPW_CMD(SET_CALIBRATION);
+ IPW_CMD(SENSITIVITY_CALIB);
+ IPW_CMD(RETRY_LIMIT);
+ IPW_CMD(IPW_PRE_POWER_DOWN);
+ IPW_CMD(VAP_BEACON_TEMPLATE);
+ IPW_CMD(VAP_DTIM_PERIOD);
+ IPW_CMD(EXT_SUPPORTED_RATES);
+ IPW_CMD(VAP_LOCAL_TX_PWR_CONSTRAINT);
+ IPW_CMD(VAP_QUIET_INTERVALS);
+ IPW_CMD(VAP_CHANNEL_SWITCH);
+ IPW_CMD(VAP_MANDATORY_CHANNELS);
+ IPW_CMD(VAP_CELL_PWR_LIMIT);
+ IPW_CMD(VAP_CF_PARAM_SET);
+ IPW_CMD(VAP_SET_BEACONING_STATE);
+ IPW_CMD(MEASUREMENT);
+ IPW_CMD(POWER_CAPABILITY);
+ IPW_CMD(SUPPORTED_CHANNELS);
+ IPW_CMD(TPC_REPORT);
+ IPW_CMD(WME_INFO);
+ IPW_CMD(PRODUCTION_COMMAND);
+ default:
+ return "UNKNOWN";
+ }
+}
+#endif /* CONFIG_IPW_DEBUG */
+
+#define HOST_COMPLETE_TIMEOUT HZ
+static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
+{
+ int rc = 0;
+
+ if (priv->status & STATUS_HCMD_ACTIVE) {
+ IPW_ERROR("Already sending a command\n");
+ return -1;
+ }
+
+ priv->status |= STATUS_HCMD_ACTIVE;
+
+ IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n",
+ get_cmd_string(cmd->cmd), cmd->cmd, cmd->len);
+ printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
+
+ rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);
+ if (rc)
+ return rc;
+
+ rc = wait_event_interruptible_timeout(priv->wait_command_queue,
+ !(priv->
+ status & STATUS_HCMD_ACTIVE),
+ HOST_COMPLETE_TIMEOUT);
+ if (rc == 0) {
+ IPW_DEBUG_INFO("Command completion failed out after %dms.\n",
+ jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ return -EIO;
+ }
+ if (priv->status & STATUS_RF_KILL_MASK) {
+ IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ipw_send_host_complete(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_HOST_COMPLETE,
+ .len = 0
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send HOST_COMPLETE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_system_config(struct ipw_priv *priv,
+ struct ipw_sys_config *config)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SYSTEM_CONFIG,
+ .len = sizeof(*config)
+ };
+
+ if (!priv || !config) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, config, sizeof(*config));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SYSTEM_CONFIG command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SSID,
+ .len = min(len, IW_ESSID_MAX_SIZE)
+ };
+
+ if (!priv || !ssid) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, ssid, cmd.len);
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SSID command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_ADAPTER_ADDRESS,
+ .len = ETH_ALEN
+ };
+
+ if (!priv || !mac) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n",
+ priv->net_dev->name, MAC_ARG(mac));
+
+ memcpy(&cmd.param, mac, ETH_ALEN);
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send ADAPTER_ADDRESS command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void ipw_adapter_restart(void *adapter)
+{
+ struct ipw_priv *priv = adapter;
+
+ if (priv->status & STATUS_RF_KILL_MASK)
+ return;
+
+ ipw_down(priv);
+ if (ipw_up(priv)) {
+ IPW_ERROR("Failed to up device\n");
+ return;
+ }
+}
+
+#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
+
+static void ipw_scan_check(void *data)
+{
+ struct ipw_priv *priv = data;
+ if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
+ IPW_DEBUG_SCAN("Scan completion watchdog resetting "
+ "adapter (%dms).\n",
+ IPW_SCAN_CHECK_WATCHDOG / 100);
+ ipw_adapter_restart(priv);
+ }
+}
+
+static int ipw_send_scan_request_ext(struct ipw_priv *priv,
+ struct ipw_scan_request_ext *request)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SCAN_REQUEST_EXT,
+ .len = sizeof(*request)
+ };
+
+ if (!priv || !request) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, request, sizeof(*request));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n");
+ return -1;
+ }
+
+ queue_delayed_work(priv->workqueue, &priv->scan_check,
+ IPW_SCAN_CHECK_WATCHDOG);
+ return 0;
+}
+
+static int ipw_send_scan_abort(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SCAN_ABORT,
+ .len = 0
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SCAN_ABORT command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SENSITIVITY_CALIB,
+ .len = sizeof(struct ipw_sensitivity_calib)
+ };
+ struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *)
+ &cmd.param;
+ calib->beacon_rssi_raw = sens;
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SENSITIVITY CALIB command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_associate(struct ipw_priv *priv,
+ struct ipw_associate *associate)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_ASSOCIATE,
+ .len = sizeof(*associate)
+ };
+
+ if (!priv || !associate) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, associate, sizeof(*associate));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send ASSOCIATE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *rates)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SUPPORTED_RATES,
+ .len = sizeof(*rates)
+ };
+
+ if (!priv || !rates) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, rates, sizeof(*rates));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SUPPORTED_RATES command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_set_random_seed(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SEED_NUMBER,
+ .len = sizeof(u32)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ get_random_bytes(&cmd.param, sizeof(u32));
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SEED_NUMBER command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+#if 0
+static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_CARD_DISABLE,
+ .len = sizeof(u32)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ *((u32 *) & cmd.param) = phy_off;
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send CARD_DISABLE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_TX_POWER,
+ .len = sizeof(*power)
+ };
+
+ if (!priv || !power) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, power, sizeof(*power));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send TX_POWER command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts)
+{
+ struct ipw_rts_threshold rts_threshold = {
+ .rts_threshold = rts,
+ };
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_RTS_THRESHOLD,
+ .len = sizeof(rts_threshold)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, &rts_threshold, sizeof(rts_threshold));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send RTS_THRESHOLD command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
+{
+ struct ipw_frag_threshold frag_threshold = {
+ .frag_threshold = frag,
+ };
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_FRAG_THRESHOLD,
+ .len = sizeof(frag_threshold)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, &frag_threshold, sizeof(frag_threshold));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send FRAG_THRESHOLD command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_POWER_MODE,
+ .len = sizeof(u32)
+ };
+ u32 *param = (u32 *) (&cmd.param);
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ /* If on battery, set to 3, if AC set to CAM, else user
+ * level */
+ switch (mode) {
+ case IPW_POWER_BATTERY:
+ *param = IPW_POWER_INDEX_3;
+ break;
+ case IPW_POWER_AC:
+ *param = IPW_POWER_MODE_CAM;
+ break;
+ default:
+ *param = mode;
+ break;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send POWER_MODE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * The IPW device contains a Microwire compatible EEPROM that stores
+ * various data like the MAC address. Usually the firmware has exclusive
+ * access to the eeprom, but during device initialization (before the
+ * device driver has sent the HostComplete command to the firmware) the
+ * device driver has read access to the EEPROM by way of indirect addressing
+ * through a couple of memory mapped registers.
+ *
+ * The following is a simplified implementation for pulling data out of the
+ * the eeprom, along with some helper functions to find information in
+ * the per device private data's copy of the eeprom.
+ *
+ * NOTE: To better understand how these functions work (i.e what is a chip
+ * select and why do have to keep driving the eeprom clock?), read
+ * just about any data sheet for a Microwire compatible EEPROM.
+ */
+
+/* write a 32 bit value into the indirect accessor register */
+static inline void eeprom_write_reg(struct ipw_priv *p, u32 data)
+{
+ ipw_write_reg32(p, FW_MEM_REG_EEPROM_ACCESS, data);
+
+ /* the eeprom requires some time to complete the operation */
+ udelay(p->eeprom_delay);
+
+ return;
+}
+
+/* perform a chip select operation */
+static inline void eeprom_cs(struct ipw_priv *priv)
+{
+ eeprom_write_reg(priv, 0);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+}
+
+/* perform a chip select operation */
+static inline void eeprom_disable_cs(struct ipw_priv *priv)
+{
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ eeprom_write_reg(priv, 0);
+ eeprom_write_reg(priv, EEPROM_BIT_SK);
+}
+
+/* push a single bit down to the eeprom */
+static inline void eeprom_write_bit(struct ipw_priv *p, u8 bit)
+{
+ int d = (bit ? EEPROM_BIT_DI : 0);
+ eeprom_write_reg(p, EEPROM_BIT_CS | d);
+ eeprom_write_reg(p, EEPROM_BIT_CS | d | EEPROM_BIT_SK);
+}
+
+/* push an opcode followed by an address down to the eeprom */
+static void eeprom_op(struct ipw_priv *priv, u8 op, u8 addr)
+{
+ int i;
+
+ eeprom_cs(priv);
+ eeprom_write_bit(priv, 1);
+ eeprom_write_bit(priv, op & 2);
+ eeprom_write_bit(priv, op & 1);
+ for (i = 7; i >= 0; i--) {
+ eeprom_write_bit(priv, addr & (1 << i));
+ }
+}
+
+/* pull 16 bits off the eeprom, one bit at a time */
+static u16 eeprom_read_u16(struct ipw_priv *priv, u8 addr)
+{
+ int i;
+ u16 r = 0;
+
+ /* Send READ Opcode */
+ eeprom_op(priv, EEPROM_CMD_READ, addr);
+
+ /* Send dummy bit */
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+
+ /* Read the byte off the eeprom one bit at a time */
+ for (i = 0; i < 16; i++) {
+ u32 data = 0;
+ eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ data = ipw_read_reg32(priv, FW_MEM_REG_EEPROM_ACCESS);
+ r = (r << 1) | ((data & EEPROM_BIT_DO) ? 1 : 0);
+ }
+
+ /* Send another dummy bit */
+ eeprom_write_reg(priv, 0);
+ eeprom_disable_cs(priv);
+
+ return r;
+}
+
+/* helper function for pulling the mac address out of the private */
+/* data's copy of the eeprom data */
+static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac)
+{
+ u8 *ee = (u8 *) priv->eeprom;
+ memcpy(mac, &ee[EEPROM_MAC_ADDRESS], 6);
+}
+
+/*
+ * Either the device driver (i.e. the host) or the firmware can
+ * load eeprom data into the designated region in SRAM. If neither
+ * happens then the FW will shutdown with a fatal error.
+ *
+ * In order to signal the FW to load the EEPROM, the EEPROM_LOAD_DISABLE
+ * bit needs region of shared SRAM needs to be non-zero.
+ */
+static void ipw_eeprom_init_sram(struct ipw_priv *priv)
+{
+ int i;
+ u16 *eeprom = (u16 *) priv->eeprom;
+
+ IPW_DEBUG_TRACE(">>\n");
+
+ /* read entire contents of eeprom into private buffer */
+ for (i = 0; i < 128; i++)
+ eeprom[i] = eeprom_read_u16(priv, (u8) i);
+
+ /*
+ If the data looks correct, then copy it to our private
+ copy. Otherwise let the firmware know to perform the operation
+ on it's own
+ */
+ if ((priv->eeprom + EEPROM_VERSION) != 0) {
+ IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
+
+ /* write the eeprom data to sram */
+ for (i = 0; i < CX2_EEPROM_IMAGE_SIZE; i++)
+ ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]);
+
+ /* Do not load eeprom data on fatal error or suspend */
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
+ } else {
+ IPW_DEBUG_INFO("Enabling FW initializationg of SRAM\n");
+
+ /* Load eeprom data on fatal error or suspend */
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 1);
+ }
+
+ IPW_DEBUG_TRACE("<<\n");
+}
+
+static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
+{
+ count >>= 2;
+ if (!count)
+ return;
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, start);
+ while (count--)
+ _ipw_write32(priv, CX2_AUTOINC_DATA, 0);
+}
+
+static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv)
+{
+ ipw_zero_memory(priv, CX2_SHARED_SRAM_DMA_CONTROL,
+ CB_NUMBER_OF_ELEMENTS_SMALL *
+ sizeof(struct command_block));
+}
+
+static int ipw_fw_dma_enable(struct ipw_priv *priv)
+{ /* start dma engine but no transfers yet */
+
+ IPW_DEBUG_FW(">> : \n");
+
+ /* Start the dma */
+ ipw_fw_dma_reset_command_blocks(priv);
+
+ /* Write CB base address */
+ ipw_write_reg32(priv, CX2_DMA_I_CB_BASE, CX2_SHARED_SRAM_DMA_CONTROL);
+
+ IPW_DEBUG_FW("<< : \n");
+ return 0;
+}
+
+static void ipw_fw_dma_abort(struct ipw_priv *priv)
+{
+ u32 control = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+
+ //set the Stop and Abort bit
+ control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT;
+ ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control);
+ priv->sram_desc.last_cb_index = 0;
+
+ IPW_DEBUG_FW("<< \n");
+}
+
+static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index,
+ struct command_block *cb)
+{
+ u32 address =
+ CX2_SHARED_SRAM_DMA_CONTROL +
+ (sizeof(struct command_block) * index);
+ IPW_DEBUG_FW(">> :\n");
+
+ ipw_write_indirect(priv, address, (u8 *) cb,
+ (int)sizeof(struct command_block));
+
+ IPW_DEBUG_FW("<< :\n");
+ return 0;
+
+}
+
+static int ipw_fw_dma_kick(struct ipw_priv *priv)
+{
+ u32 control = 0;
+ u32 index = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+
+ for (index = 0; index < priv->sram_desc.last_cb_index; index++)
+ ipw_fw_dma_write_command_block(priv, index,
+ &priv->sram_desc.cb_list[index]);
+
+ /* Enable the DMA in the CSR register */
+ ipw_clear_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED |
+ CX2_RESET_REG_STOP_MASTER);
+
+ /* Set the Start bit. */
+ control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START;
+ ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control);
+
+ IPW_DEBUG_FW("<< :\n");
+ return 0;
+}
+
+static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv)
+{
+ u32 address;
+ u32 register_value = 0;
+ u32 cb_fields_address = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+ address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB);
+ IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address);
+
+ /* Read the DMA Controlor register */
+ register_value = ipw_read_reg32(priv, CX2_DMA_I_DMA_CONTROL);
+ IPW_DEBUG_FW_INFO("CX2_DMA_I_DMA_CONTROL is 0x%x \n", register_value);
+
+ /* Print the CB values */
+ cb_fields_address = address;
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n",
+ register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value);
+
+ IPW_DEBUG_FW(">> :\n");
+}
+
+static int ipw_fw_dma_command_block_index(struct ipw_priv *priv)
+{
+ u32 current_cb_address = 0;
+ u32 current_cb_index = 0;
+
+ IPW_DEBUG_FW("<< :\n");
+ current_cb_address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB);
+
+ current_cb_index = (current_cb_address - CX2_SHARED_SRAM_DMA_CONTROL) /
+ sizeof(struct command_block);
+
+ IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n",
+ current_cb_index, current_cb_address);
+
+ IPW_DEBUG_FW(">> :\n");
+ return current_cb_index;
+
+}
+
+static int ipw_fw_dma_add_command_block(struct ipw_priv *priv,
+ u32 src_address,
+ u32 dest_address,
+ u32 length,
+ int interrupt_enabled, int is_last)
+{
+
+ u32 control = CB_VALID | CB_SRC_LE | CB_DEST_LE | CB_SRC_AUTOINC |
+ CB_SRC_IO_GATED | CB_DEST_AUTOINC | CB_SRC_SIZE_LONG |
+ CB_DEST_SIZE_LONG;
+ struct command_block *cb;
+ u32 last_cb_element = 0;
+
+ IPW_DEBUG_FW_INFO("src_address=0x%x dest_address=0x%x length=0x%x\n",
+ src_address, dest_address, length);
+
+ if (priv->sram_desc.last_cb_index >= CB_NUMBER_OF_ELEMENTS_SMALL)
+ return -1;
+
+ last_cb_element = priv->sram_desc.last_cb_index;
+ cb = &priv->sram_desc.cb_list[last_cb_element];
+ priv->sram_desc.last_cb_index++;
+
+ /* Calculate the new CB control word */
+ if (interrupt_enabled)
+ control |= CB_INT_ENABLED;
+
+ if (is_last)
+ control |= CB_LAST_VALID;
+
+ control |= length;
+
+ /* Calculate the CB Element's checksum value */
+ cb->status = control ^ src_address ^ dest_address;
+
+ /* Copy the Source and Destination addresses */
+ cb->dest_addr = dest_address;
+ cb->source_addr = src_address;
+
+ /* Copy the Control Word last */
+ cb->control = control;
+
+ return 0;
+}
+
+static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
+ u32 src_phys, u32 dest_address, u32 length)
+{
+ u32 bytes_left = length;
+ u32 src_offset = 0;
+ u32 dest_offset = 0;
+ int status = 0;
+ IPW_DEBUG_FW(">> \n");
+ IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n",
+ src_phys, dest_address, length);
+ while (bytes_left > CB_MAX_LENGTH) {
+ status = ipw_fw_dma_add_command_block(priv,
+ src_phys + src_offset,
+ dest_address +
+ dest_offset,
+ CB_MAX_LENGTH, 0, 0);
+ if (status) {
+ IPW_DEBUG_FW_INFO(": Failed\n");
+ return -1;
+ } else
+ IPW_DEBUG_FW_INFO(": Added new cb\n");
+
+ src_offset += CB_MAX_LENGTH;
+ dest_offset += CB_MAX_LENGTH;
+ bytes_left -= CB_MAX_LENGTH;
+ }
+
+ /* add the buffer tail */
+ if (bytes_left > 0) {
+ status =
+ ipw_fw_dma_add_command_block(priv, src_phys + src_offset,
+ dest_address + dest_offset,
+ bytes_left, 0, 0);
+ if (status) {
+ IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n");
+ return -1;
+ } else
+ IPW_DEBUG_FW_INFO
+ (": Adding new cb - the buffer tail\n");
+ }
+
+ IPW_DEBUG_FW("<< \n");
+ return 0;
+}
+
+static int ipw_fw_dma_wait(struct ipw_priv *priv)
+{
+ u32 current_index = 0;
+ u32 watchdog = 0;
+
+ IPW_DEBUG_FW(">> : \n");
+
+ current_index = ipw_fw_dma_command_block_index(priv);
+ IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n",
+ (int)priv->sram_desc.last_cb_index);
+
+ while (current_index < priv->sram_desc.last_cb_index) {
+ udelay(50);
+ current_index = ipw_fw_dma_command_block_index(priv);
+
+ watchdog++;
+
+ if (watchdog > 400) {
+ IPW_DEBUG_FW_INFO("Timeout\n");
+ ipw_fw_dma_dump_command_block(priv);
+ ipw_fw_dma_abort(priv);
+ return -1;
+ }
+ }
+
+ ipw_fw_dma_abort(priv);
+
+ /*Disable the DMA in the CSR register */
+ ipw_set_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED | CX2_RESET_REG_STOP_MASTER);
+
+ IPW_DEBUG_FW("<< dmaWaitSync \n");
+ return 0;
+}
+
+static void ipw_remove_current_network(struct ipw_priv *priv)
+{
+ struct list_head *element, *safe;
+ struct ieee80211_network *network = NULL;
+ list_for_each_safe(element, safe, &priv->ieee->network_list) {
+ network = list_entry(element, struct ieee80211_network, list);
+ if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+ list_del(element);
+ list_add_tail(&network->list,
+ &priv->ieee->network_free_list);
+ }
+ }
+}
+
+/**
+ * Check that card is still alive.
+ * Reads debug register from domain0.
+ * If card is present, pre-defined value should
+ * be found there.
+ *
+ * @param priv
+ * @return 1 if card is present, 0 otherwise
+ */
+static inline int ipw_alive(struct ipw_priv *priv)
+{
+ return ipw_read32(priv, 0x90) == 0xd55555d5;
+}
+
+static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
+ int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((ipw_read32(priv, addr) & mask) == mask)
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIME;
+}
+
+/* These functions load the firmware and micro code for the operation of
+ * the ipw hardware. It assumes the buffer has all the bits for the
+ * image and the caller is handling the memory allocation and clean up.
+ */
+
+static int ipw_stop_master(struct ipw_priv *priv)
+{
+ int rc;
+
+ IPW_DEBUG_TRACE(">> \n");
+ /* stop master. typical delay - 0 */
+ ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER);
+
+ rc = ipw_poll_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED, 100);
+ if (rc < 0) {
+ IPW_ERROR("stop master failed in 10ms\n");
+ return -1;
+ }
+
+ IPW_DEBUG_INFO("stop master %dms\n", rc);
+
+ return rc;
+}
+
+static void ipw_arc_release(struct ipw_priv *priv)
+{
+ IPW_DEBUG_TRACE(">> \n");
+ mdelay(5);
+
+ ipw_clear_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET);
+
+ /* no one knows timing, for safety add some delay */
+ mdelay(5);
+}
+
+struct fw_header {
+ u32 version;
+ u32 mode;
+};
+
+struct fw_chunk {
+ u32 address;
+ u32 length;
+};
+
+#define IPW_FW_MAJOR_VERSION 2
+#define IPW_FW_MINOR_VERSION 2
+
+#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
+#define IPW_FW_MAJOR(x) (x & 0xff)
+
+#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | \
+ IPW_FW_MAJOR_VERSION)
+
+#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \
+"." __stringify(IPW_FW_MINOR_VERSION) "-"
+
+#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0
+#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw"
+#else
+#define IPW_FW_NAME(x) "ipw2200_" x ".fw"
+#endif
+
+static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
+{
+ int rc = 0, i, addr;
+ u8 cr = 0;
+ u16 *image;
+
+ image = (u16 *) data;
+
+ IPW_DEBUG_TRACE(">> \n");
+
+ rc = ipw_stop_master(priv);
+
+ if (rc < 0)
+ return rc;
+
+// spin_lock_irqsave(&priv->lock, flags);
+
+ for (addr = CX2_SHARED_LOWER_BOUND;
+ addr < CX2_REGISTER_DOMAIN1_END; addr += 4) {
+ ipw_write32(priv, addr, 0);
+ }
+
+ /* no ucode (yet) */
+ memset(&priv->dino_alive, 0, sizeof(priv->dino_alive));
+ /* destroy DMA queues */
+ /* reset sequence */
+
+ ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_ON);
+ ipw_arc_release(priv);
+ ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_OFF);
+ mdelay(1);
+
+ /* reset PHY */
+ ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, CX2_BASEBAND_POWER_DOWN);
+ mdelay(1);
+
+ ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, 0);
+ mdelay(1);
+
+ /* enable ucode store */
+ ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0);
+ ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS);
+ mdelay(1);
+
+ /* write ucode */
+ /**
+ * @bug
+ * Do NOT set indirect address register once and then
+ * store data to indirect data register in the loop.
+ * It seems very reasonable, but in this case DINO do not
+ * accept ucode. It is essential to set address each time.
+ */
+ /* load new ipw uCode */
+ for (i = 0; i < len / 2; i++)
+ ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, image[i]);
+
+ /* enable DINO */
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0);
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM);
+
+ /* this is where the igx / win driver deveates from the VAP driver. */
+
+ /* wait for alive response */
+ for (i = 0; i < 100; i++) {
+ /* poll for incoming data */
+ cr = ipw_read_reg8(priv, CX2_BASEBAND_CONTROL_STATUS);
+ if (cr & DINO_RXFIFO_DATA)
+ break;
+ mdelay(1);
+ }
+
+ if (cr & DINO_RXFIFO_DATA) {
+ /* alive_command_responce size is NOT multiple of 4 */
+ u32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4];
+
+ for (i = 0; i < ARRAY_SIZE(response_buffer); i++)
+ response_buffer[i] =
+ ipw_read_reg32(priv, CX2_BASEBAND_RX_FIFO_READ);
+ memcpy(&priv->dino_alive, response_buffer,
+ sizeof(priv->dino_alive));
+ if (priv->dino_alive.alive_command == 1
+ && priv->dino_alive.ucode_valid == 1) {
+ rc = 0;
+ IPW_DEBUG_INFO
+ ("Microcode OK, rev. %d (0x%x) dev. %d (0x%x) "
+ "of %02d/%02d/%02d %02d:%02d\n",
+ priv->dino_alive.software_revision,
+ priv->dino_alive.software_revision,
+ priv->dino_alive.device_identifier,
+ priv->dino_alive.device_identifier,
+ priv->dino_alive.time_stamp[0],
+ priv->dino_alive.time_stamp[1],
+ priv->dino_alive.time_stamp[2],
+ priv->dino_alive.time_stamp[3],
+ priv->dino_alive.time_stamp[4]);
+ } else {
+ IPW_DEBUG_INFO("Microcode is not alive\n");
+ rc = -EINVAL;
+ }
+ } else {
+ IPW_DEBUG_INFO("No alive response from DINO\n");
+ rc = -ETIME;
+ }
+
+ /* disable DINO, otherwise for some reason
+ firmware have problem getting alive resp. */
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0);
+
+// spin_unlock_irqrestore(&priv->lock, flags);
+
+ return rc;
+}
+
+static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
+{
+ int rc = -1;
+ int offset = 0;
+ struct fw_chunk *chunk;
+ dma_addr_t shared_phys;
+ u8 *shared_virt;
+
+ IPW_DEBUG_TRACE("<< : \n");
+ shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys);
+
+ if (!shared_virt)
+ return -ENOMEM;
+
+ memmove(shared_virt, data, len);
+
+ /* Start the Dma */
+ rc = ipw_fw_dma_enable(priv);
+
+ if (priv->sram_desc.last_cb_index > 0) {
+ /* the DMA is already ready this would be a bug. */
+ BUG();
+ goto out;
+ }
+
+ do {
+ chunk = (struct fw_chunk *)(data + offset);
+ offset += sizeof(struct fw_chunk);
+ /* build DMA packet and queue up for sending */
+ /* dma to chunk->address, the chunk->length bytes from data +
+ * offeset*/
+ /* Dma loading */
+ rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
+ chunk->address, chunk->length);
+ if (rc) {
+ IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
+ goto out;
+ }
+
+ offset += chunk->length;
+ } while (offset < len);
+
+ /* Run the DMA and wait for the answer */
+ rc = ipw_fw_dma_kick(priv);
+ if (rc) {
+ IPW_ERROR("dmaKick Failed\n");
+ goto out;
+ }
+
+ rc = ipw_fw_dma_wait(priv);
+ if (rc) {
+ IPW_ERROR("dmaWaitSync Failed\n");
+ goto out;
+ }
+ out:
+ pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys);
+ return rc;
+}
+
+/* stop nic */
+static int ipw_stop_nic(struct ipw_priv *priv)
+{
+ int rc = 0;
+
+ /* stop */
+ ipw_write32(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER);
+
+ rc = ipw_poll_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED, 500);
+ if (rc < 0) {
+ IPW_ERROR("wait for reg master disabled failed\n");
+ return rc;
+ }
+
+ ipw_set_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET);
+
+ return rc;
+}
+
+static void ipw_start_nic(struct ipw_priv *priv)
+{
+ IPW_DEBUG_TRACE(">>\n");
+
+ /* prvHwStartNic release ARC */
+ ipw_clear_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED |
+ CX2_RESET_REG_STOP_MASTER |
+ CBD_RESET_REG_PRINCETON_RESET);
+
+ /* enable power management */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW,
+ CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY);
+
+ IPW_DEBUG_TRACE("<<\n");
+}
+
+static int ipw_init_nic(struct ipw_priv *priv)
+{
+ int rc;
+
+ IPW_DEBUG_TRACE(">>\n");
+ /* reset */
+ /*prvHwInitNic */
+ /* set "initialization complete" bit to move adapter to D0 state */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE);
+
+ /* low-level PLL activation */
+ ipw_write32(priv, CX2_READ_INT_REGISTER,
+ CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER);
+
+ /* wait for clock stabilization */
+ rc = ipw_poll_bit(priv, CX2_GP_CNTRL_RW,
+ CX2_GP_CNTRL_BIT_CLOCK_READY, 250);
+ if (rc < 0)
+ IPW_DEBUG_INFO("FAILED wait for clock stablization\n");
+
+ /* assert SW reset */
+ ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_SW_RESET);
+
+ udelay(10);
+
+ /* set "initialization complete" bit to move adapter to D0 state */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE);
+
+ IPW_DEBUG_TRACE(">>\n");
+ return 0;
+}
+
+/* Call this function from process context, it will sleep in request_firmware.
+ * Probe is an ok place to call this from.
+ */
+static int ipw_reset_nic(struct ipw_priv *priv)
+{
+ int rc = 0;
+
+ IPW_DEBUG_TRACE(">>\n");
+
+ rc = ipw_init_nic(priv);
+
+ /* Clear the 'host command active' bit... */
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ wake_up_interruptible(&priv->wait_command_queue);
+
+ IPW_DEBUG_TRACE("<<\n");
+ return rc;
+}
+
+static int ipw_get_fw(struct ipw_priv *priv,
+ const struct firmware **fw, const char *name)
+{
+ struct fw_header *header;
+ int rc;
+
+ /* ask firmware_class module to get the boot firmware off disk */
+ rc = request_firmware(fw, name, &priv->pci_dev->dev);
+ if (rc < 0) {
+ IPW_ERROR("%s load failed: Reason %d\n", name, rc);
+ return rc;
+ }
+
+ header = (struct fw_header *)(*fw)->data;
+ if (IPW_FW_MAJOR(header->version) != IPW_FW_MAJOR_VERSION) {
+ IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n",
+ name,
+ IPW_FW_MAJOR(header->version), IPW_FW_MAJOR_VERSION);
+ return -EINVAL;
+ }
+
+ IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n",
+ name,
+ IPW_FW_MAJOR(header->version),
+ IPW_FW_MINOR(header->version),
+ (*fw)->size - sizeof(struct fw_header));
+ return 0;
+}
+
+#define CX2_RX_BUF_SIZE (3000)
+
+static inline void ipw_rx_queue_reset(struct ipw_priv *priv,
+ struct ipw_rx_queue *rxq)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+ /* In the reset function, these buffers may have been allocated
+ * to an SKB, so we need to unmap and free potential storage */
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+ }
+
+ /* Set us so that we have processed and used all buffers, but have
+ * not restocked the Rx queue with fresh buffers */
+ rxq->read = rxq->write = 0;
+ rxq->processed = RX_QUEUE_SIZE - 1;
+ rxq->free_count = 0;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+#ifdef CONFIG_PM
+static int fw_loaded = 0;
+static const struct firmware *bootfw = NULL;
+static const struct firmware *firmware = NULL;
+static const struct firmware *ucode = NULL;
+#endif
+
+static int ipw_load(struct ipw_priv *priv)
+{
+#ifndef CONFIG_PM
+ const struct firmware *bootfw = NULL;
+ const struct firmware *firmware = NULL;
+ const struct firmware *ucode = NULL;
+#endif
+ int rc = 0, retries = 3;
+
+#ifdef CONFIG_PM
+ if (!fw_loaded) {
+#endif
+ rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
+ if (rc)
+ goto error;
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ rc = ipw_get_fw(priv, &ucode,
+ IPW_FW_NAME("ibss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss"));
+ break;
+
+#ifdef CONFIG_IPW_PROMISC
+ case IW_MODE_MONITOR:
+ rc = ipw_get_fw(priv, &ucode,
+ IPW_FW_NAME("ibss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware,
+ IPW_FW_NAME("sniffer"));
+ break;
+#endif
+ case IW_MODE_INFRA:
+ rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss"));
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+
+ if (rc)
+ goto error;
+
+#ifdef CONFIG_PM
+ fw_loaded = 1;
+ }
+#endif
+
+ if (!priv->rxq)
+ priv->rxq = ipw_rx_queue_alloc(priv);
+ else
+ ipw_rx_queue_reset(priv, priv->rxq);
+ if (!priv->rxq) {
+ IPW_ERROR("Unable to initialize Rx queue\n");
+ goto error;
+ }
+
+ retry:
+ /* Ensure interrupts are disabled */
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+ priv->status &= ~STATUS_INT_ENABLED;
+
+ /* ack pending interrupts */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
+
+ ipw_stop_nic(priv);
+
+ rc = ipw_reset_nic(priv);
+ if (rc) {
+ IPW_ERROR("Unable to reset NIC\n");
+ goto error;
+ }
+
+ ipw_zero_memory(priv, CX2_NIC_SRAM_LOWER_BOUND,
+ CX2_NIC_SRAM_UPPER_BOUND - CX2_NIC_SRAM_LOWER_BOUND);
+
+ /* DMA the initial boot firmware into the device */
+ rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header),
+ bootfw->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load boot firmware\n");
+ goto error;
+ }
+
+ /* kick start the device */
+ ipw_start_nic(priv);
+
+ /* wait for the device to finish it's initial startup sequence */
+ rc = ipw_poll_bit(priv, CX2_INTA_RW,
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500);
+ if (rc < 0) {
+ IPW_ERROR("device failed to boot initial fw image\n");
+ goto error;
+ }
+ IPW_DEBUG_INFO("initial device response after %dms\n", rc);
+
+ /* ack fw init done interrupt */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE);
+
+ /* DMA the ucode into the device */
+ rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header),
+ ucode->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load ucode\n");
+ goto error;
+ }
+
+ /* stop nic */
+ ipw_stop_nic(priv);
+
+ /* DMA bss firmware into the device */
+ rc = ipw_load_firmware(priv, firmware->data +
+ sizeof(struct fw_header),
+ firmware->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load firmware\n");
+ goto error;
+ }
+
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
+
+ rc = ipw_queue_reset(priv);
+ if (rc) {
+ IPW_ERROR("Unable to initialize queues\n");
+ goto error;
+ }
+
+ /* Ensure interrupts are disabled */
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+
+ /* kick start the device */
+ ipw_start_nic(priv);
+
+ if (ipw_read32(priv, CX2_INTA_RW) & CX2_INTA_BIT_PARITY_ERROR) {
+ if (retries > 0) {
+ IPW_WARNING("Parity error. Retrying init.\n");
+ retries--;
+ goto retry;
+ }
+
+ IPW_ERROR("TODO: Handle parity error -- schedule restart?\n");
+ rc = -EIO;
+ goto error;
+ }
+
+ /* wait for the device */
+ rc = ipw_poll_bit(priv, CX2_INTA_RW,
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500);
+ if (rc < 0) {
+ IPW_ERROR("device failed to start after 500ms\n");
+ goto error;
+ }
+ IPW_DEBUG_INFO("device response after %dms\n", rc);
+
+ /* ack fw init done interrupt */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE);
+
+ /* read eeprom data and initialize the eeprom region of sram */
+ priv->eeprom_delay = 1;
+ ipw_eeprom_init_sram(priv);
+
+ /* enable interrupts */
+ ipw_enable_interrupts(priv);
+
+ /* Ensure our queue has valid packets */
+ ipw_rx_queue_replenish(priv);
+
+ ipw_write32(priv, CX2_RX_READ_INDEX, priv->rxq->read);
+
+ /* ack pending interrupts */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
+
+#ifndef CONFIG_PM
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+#endif
+ return 0;
+
+ error:
+ if (priv->rxq) {
+ ipw_rx_queue_free(priv, priv->rxq);
+ priv->rxq = NULL;
+ }
+ ipw_tx_queue_free(priv);
+ if (bootfw)
+ release_firmware(bootfw);
+ if (ucode)
+ release_firmware(ucode);
+ if (firmware)
+ release_firmware(firmware);
+#ifdef CONFIG_PM
+ fw_loaded = 0;
+ bootfw = ucode = firmware = NULL;
+#endif
+
+ return rc;
+}
+
+/**
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A queue is a circular buffers with 'Read' and 'Write' pointers.
+ * 2 empty entries always kept in the buffer to protect from overflow.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ * The IPW operates with six queues, one receive queue in the device's
+ * sram, one transmit queue for sending commands to the device firmware,
+ * and four transmit queues for data.
+ *
+ * The four transmit queues allow for performing quality of service (qos)
+ * transmissions as per the 802.11 protocol. Currently Linux does not
+ * provide a mechanism to the user for utilizing prioritized queues, so
+ * we only utilize the first data transmit queue (queue1).
+ */
+
+/**
+ * Driver allocates buffers of this size for Rx
+ */
+
+static inline int ipw_queue_space(const struct clx2_queue *q)
+{
+ int s = q->last_used - q->first_empty;
+ if (s <= 0)
+ s += q->n_bd;
+ s -= 2; /* keep some reserve to not confuse empty and full situations */
+ if (s < 0)
+ s = 0;
+ return s;
+}
+
+static inline int ipw_queue_inc_wrap(int index, int n_bd)
+{
+ return (++index == n_bd) ? 0 : index;
+}
+
+/**
+ * Initialize common DMA queue structure
+ *
+ * @param q queue to init
+ * @param count Number of BD's to allocate. Should be power of 2
+ * @param read_register Address for 'read' register
+ * (not offset within BAR, full address)
+ * @param write_register Address for 'write' register
+ * (not offset within BAR, full address)
+ * @param base_register Address for 'base' register
+ * (not offset within BAR, full address)
+ * @param size Address for 'size' register
+ * (not offset within BAR, full address)
+ */
+static void ipw_queue_init(struct ipw_priv *priv, struct clx2_queue *q,
+ int count, u32 read, u32 write, u32 base, u32 size)
+{
+ q->n_bd = count;
+
+ q->low_mark = q->n_bd / 4;
+ if (q->low_mark < 4)
+ q->low_mark = 4;
+
+ q->high_mark = q->n_bd / 8;
+ if (q->high_mark < 2)
+ q->high_mark = 2;
+
+ q->first_empty = q->last_used = 0;
+ q->reg_r = read;
+ q->reg_w = write;
+
+ ipw_write32(priv, base, q->dma_addr);
+ ipw_write32(priv, size, count);
+ ipw_write32(priv, read, 0);
+ ipw_write32(priv, write, 0);
+
+ _ipw_read32(priv, 0x90);
+}
+
+static int ipw_queue_tx_init(struct ipw_priv *priv,
+ struct clx2_tx_queue *q,
+ int count, u32 read, u32 write, u32 base, u32 size)
+{
+ struct pci_dev *dev = priv->pci_dev;
+
+ q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL);
+ if (!q->txb) {
+ IPW_ERROR("vmalloc for auxilary BD structures failed\n");
+ return -ENOMEM;
+ }
+
+ q->bd =
+ pci_alloc_consistent(dev, sizeof(q->bd[0]) * count, &q->q.dma_addr);
+ if (!q->bd) {
+ IPW_ERROR("pci_alloc_consistent(%zd) failed\n",
+ sizeof(q->bd[0]) * count);
+ kfree(q->txb);
+ q->txb = NULL;
+ return -ENOMEM;
+ }
+
+ ipw_queue_init(priv, &q->q, count, read, write, base, size);
+ return 0;
+}
+
+/**
+ * Free one TFD, those at index [txq->q.last_used].
+ * Do NOT advance any indexes
+ *
+ * @param dev
+ * @param txq
+ */
+static void ipw_queue_tx_free_tfd(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq)
+{
+ struct tfd_frame *bd = &txq->bd[txq->q.last_used];
+ struct pci_dev *dev = priv->pci_dev;
+ int i;
+
+ /* classify bd */
+ if (bd->control_flags.message_type == TX_HOST_COMMAND_TYPE)
+ /* nothing to cleanup after for host commands */
+ return;
+
+ /* sanity check */
+ if (bd->u.data.num_chunks > NUM_TFD_CHUNKS) {
+ IPW_ERROR("Too many chunks: %i\n", bd->u.data.num_chunks);
+ /** @todo issue fatal error, it is quite serious situation */
+ return;
+ }
+
+ /* unmap chunks if any */
+ for (i = 0; i < bd->u.data.num_chunks; i++) {
+ pci_unmap_single(dev, bd->u.data.chunk_ptr[i],
+ bd->u.data.chunk_len[i], PCI_DMA_TODEVICE);
+ if (txq->txb[txq->q.last_used]) {
+ ieee80211_txb_free(txq->txb[txq->q.last_used]);
+ txq->txb[txq->q.last_used] = NULL;
+ }
+ }
+}
+
+/**
+ * Deallocate DMA queue.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ *
+ * @param dev
+ * @param q
+ */
+static void ipw_queue_tx_free(struct ipw_priv *priv, struct clx2_tx_queue *txq)
+{
+ struct clx2_queue *q = &txq->q;
+ struct pci_dev *dev = priv->pci_dev;
+
+ if (q->n_bd == 0)
+ return;
+
+ /* first, empty all BD's */
+ for (; q->first_empty != q->last_used;
+ q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) {
+ ipw_queue_tx_free_tfd(priv, txq);
+ }
+
+ /* free buffers belonging to queue itself */
+ pci_free_consistent(dev, sizeof(txq->bd[0]) * q->n_bd, txq->bd,
+ q->dma_addr);
+ kfree(txq->txb);
+
+ /* 0 fill whole structure */
+ memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * Destroy all DMA queues and structures
+ *
+ * @param priv
+ */
+static void ipw_tx_queue_free(struct ipw_priv *priv)
+{
+ /* Tx CMD queue */
+ ipw_queue_tx_free(priv, &priv->txq_cmd);
+
+ /* Tx queues */
+ ipw_queue_tx_free(priv, &priv->txq[0]);
+ ipw_queue_tx_free(priv, &priv->txq[1]);
+ ipw_queue_tx_free(priv, &priv->txq[2]);
+ ipw_queue_tx_free(priv, &priv->txq[3]);
+}
+
+static void inline __maybe_wake_tx(struct ipw_priv *priv)
+{
+ if (netif_running(priv->net_dev)) {
+ switch (priv->port_type) {
+ case DCR_TYPE_MU_BSS:
+ case DCR_TYPE_MU_IBSS:
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ return;
+ }
+ }
+ netif_wake_queue(priv->net_dev);
+ }
+
+}
+
+static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
+{
+ /* First 3 bytes are manufacturer */
+ bssid[0] = priv->mac_addr[0];
+ bssid[1] = priv->mac_addr[1];
+ bssid[2] = priv->mac_addr[2];
+
+ /* Last bytes are random */
+ get_random_bytes(&bssid[3], ETH_ALEN - 3);
+
+ bssid[0] &= 0xfe; /* clear multicast bit */
+ bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */
+}
+
+static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
+{
+ struct ipw_station_entry entry;
+ int i;
+
+ for (i = 0; i < priv->num_stations; i++) {
+ if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) {
+ /* Another node is active in network */
+ priv->missed_adhoc_beacons = 0;
+ if (!(priv->config & CFG_STATIC_CHANNEL))
+ /* when other nodes drop out, we drop out */
+ priv->config &= ~CFG_ADHOC_PERSIST;
+
+ return i;
+ }
+ }
+
+ if (i == MAX_STATIONS)
+ return IPW_INVALID_STATION;
+
+ IPW_DEBUG_SCAN("Adding AdHoc station: " MAC_FMT "\n", MAC_ARG(bssid));
+
+ entry.reserved = 0;
+ entry.support_mode = 0;
+ memcpy(entry.mac_addr, bssid, ETH_ALEN);
+ memcpy(priv->stations[i], bssid, ETH_ALEN);
+ ipw_write_direct(priv, IPW_STATION_TABLE_LOWER + i * sizeof(entry),
+ &entry, sizeof(entry));
+ priv->num_stations++;
+
+ return i;
+}
+
+static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
+{
+ int i;
+
+ for (i = 0; i < priv->num_stations; i++)
+ if (!memcmp(priv->stations[i], bssid, ETH_ALEN))
+ return i;
+
+ return IPW_INVALID_STATION;
+}
+
+static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
+{
+ int err;
+
+ if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))) {
+ IPW_DEBUG_ASSOC("Disassociating while not associated.\n");
+ return;
+ }
+
+ IPW_DEBUG_ASSOC("Disassocation attempt from " MAC_FMT " "
+ "on channel %d.\n",
+ MAC_ARG(priv->assoc_request.bssid),
+ priv->assoc_request.channel);
+
+ priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
+ priv->status |= STATUS_DISASSOCIATING;
+
+ if (quiet)
+ priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
+ else
+ priv->assoc_request.assoc_type = HC_DISASSOCIATE;
+ err = ipw_send_associate(priv, &priv->assoc_request);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send [dis]associate command "
+ "failed.\n");
+ return;
+ }
+
+}
+
+static void ipw_disassociate(void *data)
+{
+ ipw_send_disassociate(data, 0);
+}
+
+static void notify_wx_assoc_event(struct ipw_priv *priv)
+{
+ union iwreq_data wrqu;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (priv->status & STATUS_ASSOCIATED)
+ memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN);
+ else
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+struct ipw_status_code {
+ u16 status;
+ const char *reason;
+};
+
+static const struct ipw_status_code ipw_status_codes[] = {
+ {0x00, "Successful"},
+ {0x01, "Unspecified failure"},
+ {0x0A, "Cannot support all requested capabilities in the "
+ "Capability information field"},
+ {0x0B, "Reassociation denied due to inability to confirm that "
+ "association exists"},
+ {0x0C, "Association denied due to reason outside the scope of this "
+ "standard"},
+ {0x0D,
+ "Responding station does not support the specified authentication "
+ "algorithm"},
+ {0x0E,
+ "Received an Authentication frame with authentication sequence "
+ "transaction sequence number out of expected sequence"},
+ {0x0F, "Authentication rejected because of challenge failure"},
+ {0x10, "Authentication rejected due to timeout waiting for next "
+ "frame in sequence"},
+ {0x11, "Association denied because AP is unable to handle additional "
+ "associated stations"},
+ {0x12,
+ "Association denied due to requesting station not supporting all "
+ "of the datarates in the BSSBasicServiceSet Parameter"},
+ {0x13,
+ "Association denied due to requesting station not supporting "
+ "short preamble operation"},
+ {0x14,
+ "Association denied due to requesting station not supporting "
+ "PBCC encoding"},
+ {0x15,
+ "Association denied due to requesting station not supporting "
+ "channel agility"},
+ {0x19,
+ "Association denied due to requesting station not supporting "
+ "short slot operation"},
+ {0x1A,
+ "Association denied due to requesting station not supporting "
+ "DSSS-OFDM operation"},
+ {0x28, "Invalid Information Element"},
+ {0x29, "Group Cipher is not valid"},
+ {0x2A, "Pairwise Cipher is not valid"},
+ {0x2B, "AKMP is not valid"},
+ {0x2C, "Unsupported RSN IE version"},
+ {0x2D, "Invalid RSN IE Capabilities"},
+ {0x2E, "Cipher suite is rejected per security policy"},
+};
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *ipw_get_status_code(u16 status)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ipw_status_codes); i++)
+ if (ipw_status_codes[i].status == status)
+ return ipw_status_codes[i].reason;
+ return "Unknown status value.";
+}
+#endif
+
+static void inline average_init(struct average *avg)
+{
+ memset(avg, 0, sizeof(*avg));
+}
+
+static void inline average_add(struct average *avg, s16 val)
+{
+ avg->sum -= avg->entries[avg->pos];
+ avg->sum += val;
+ avg->entries[avg->pos++] = val;
+ if (unlikely(avg->pos == AVG_ENTRIES)) {
+ avg->init = 1;
+ avg->pos = 0;
+ }
+}
+
+static s16 inline average_value(struct average *avg)
+{
+ if (!unlikely(avg->init)) {
+ if (avg->pos)
+ return avg->sum / avg->pos;
+ return 0;
+ }
+
+ return avg->sum / AVG_ENTRIES;
+}
+
+static void ipw_reset_stats(struct ipw_priv *priv)
+{
+ u32 len = sizeof(u32);
+
+ priv->quality = 0;
+
+ average_init(&priv->average_missed_beacons);
+ average_init(&priv->average_rssi);
+ average_init(&priv->average_noise);
+
+ priv->last_rate = 0;
+ priv->last_missed_beacons = 0;
+ priv->last_rx_packets = 0;
+ priv->last_tx_packets = 0;
+ priv->last_tx_failures = 0;
+
+ /* Firmware managed, reset only when NIC is restarted, so we have to
+ * normalize on the current value */
+ ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC,
+ &priv->last_rx_err, &len);
+ ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE,
+ &priv->last_tx_failures, &len);
+
+ /* Driver managed, reset with each association */
+ priv->missed_adhoc_beacons = 0;
+ priv->missed_beacons = 0;
+ priv->tx_packets = 0;
+ priv->rx_packets = 0;
+
+}
+
+static inline u32 ipw_get_max_rate(struct ipw_priv *priv)
+{
+ u32 i = 0x80000000;
+ u32 mask = priv->rates_mask;
+ /* If currently associated in B mode, restrict the maximum
+ * rate match to B rates */
+ if (priv->assoc_request.ieee_mode == IPW_B_MODE)
+ mask &= IEEE80211_CCK_RATES_MASK;
+
+ /* TODO: Verify that the rate is supported by the current rates
+ * list. */
+
+ while (i && !(mask & i))
+ i >>= 1;
+ switch (i) {
+ case IEEE80211_CCK_RATE_1MB_MASK: return 1000000;
+ case IEEE80211_CCK_RATE_2MB_MASK: return 2000000;
+ case IEEE80211_CCK_RATE_5MB_MASK: return 5500000;
+ case IEEE80211_OFDM_RATE_6MB_MASK: return 6000000;
+ case IEEE80211_OFDM_RATE_9MB_MASK: return 9000000;
+ case IEEE80211_CCK_RATE_11MB_MASK: return 11000000;
+ case IEEE80211_OFDM_RATE_12MB_MASK: return 12000000;
+ case IEEE80211_OFDM_RATE_18MB_MASK: return 18000000;
+ case IEEE80211_OFDM_RATE_24MB_MASK: return 24000000;
+ case IEEE80211_OFDM_RATE_36MB_MASK: return 36000000;
+ case IEEE80211_OFDM_RATE_48MB_MASK: return 48000000;
+ case IEEE80211_OFDM_RATE_54MB_MASK: return 54000000;
+ }
+
+ if (priv->ieee->mode == IEEE_B)
+ return 11000000;
+ else
+ return 54000000;
+}
+
+static u32 ipw_get_current_rate(struct ipw_priv *priv)
+{
+ u32 rate, len = sizeof(rate);
+ int err;
+
+ if (!(priv->status & STATUS_ASSOCIATED))
+ return 0;
+
+ if (priv->tx_packets > IPW_REAL_RATE_RX_PACKET_THRESHOLD) {
+ err = ipw_get_ordinal(priv, IPW_ORD_STAT_TX_CURR_RATE, &rate,
+ &len);
+ if (err) {
+ IPW_DEBUG_INFO("failed querying ordinals.\n");
+ return 0;
+ }
+ } else
+ return ipw_get_max_rate(priv);
+
+ switch (rate) {
+ case IPW_TX_RATE_1MB: return 1000000;
+ case IPW_TX_RATE_2MB: return 2000000;
+ case IPW_TX_RATE_5MB: return 5500000;
+ case IPW_TX_RATE_6MB: return 6000000;
+ case IPW_TX_RATE_9MB: return 9000000;
+ case IPW_TX_RATE_11MB: return 11000000;
+ case IPW_TX_RATE_12MB: return 12000000;
+ case IPW_TX_RATE_18MB: return 18000000;
+ case IPW_TX_RATE_24MB: return 24000000;
+ case IPW_TX_RATE_36MB: return 36000000;
+ case IPW_TX_RATE_48MB: return 48000000;
+ case IPW_TX_RATE_54MB: return 54000000;
+ }
+
+ return 0;
+}
+
+#define PERFECT_RSSI (-50)
+#define WORST_RSSI (-85)
+#define IPW_STATS_INTERVAL (2 * HZ)
+static void ipw_gather_stats(struct ipw_priv *priv)
+{
+ u32 rx_err, rx_err_delta, rx_packets_delta;
+ u32 tx_failures, tx_failures_delta, tx_packets_delta;
+ u32 missed_beacons_percent, missed_beacons_delta;
+ u32 quality = 0;
+ u32 len = sizeof(u32);
+ s16 rssi;
+ u32 beacon_quality, signal_quality, tx_quality, rx_quality,
+ rate_quality;
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ priv->quality = 0;
+ return;
+ }
+
+ /* Update the statistics */
+ ipw_get_ordinal(priv, IPW_ORD_STAT_MISSED_BEACONS,
+ &priv->missed_beacons, &len);
+ missed_beacons_delta = priv->missed_beacons - priv->last_missed_beacons;
+ priv->last_missed_beacons = priv->missed_beacons;
+ if (priv->assoc_request.beacon_interval) {
+ missed_beacons_percent = missed_beacons_delta *
+ (HZ * priv->assoc_request.beacon_interval) /
+ (IPW_STATS_INTERVAL * 10);
+ } else {
+ missed_beacons_percent = 0;
+ }
+ average_add(&priv->average_missed_beacons, missed_beacons_percent);
+
+ ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC, &rx_err, &len);
+ rx_err_delta = rx_err - priv->last_rx_err;
+ priv->last_rx_err = rx_err;
+
+ ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE, &tx_failures, &len);
+ tx_failures_delta = tx_failures - priv->last_tx_failures;
+ priv->last_tx_failures = tx_failures;
+
+ rx_packets_delta = priv->rx_packets - priv->last_rx_packets;
+ priv->last_rx_packets = priv->rx_packets;
+
+ tx_packets_delta = priv->tx_packets - priv->last_tx_packets;
+ priv->last_tx_packets = priv->tx_packets;
+
+ /* Calculate quality based on the following:
+ *
+ * Missed beacon: 100% = 0, 0% = 70% missed
+ * Rate: 60% = 1Mbs, 100% = Max
+ * Rx and Tx errors represent a straight % of total Rx/Tx
+ * RSSI: 100% = > -50, 0% = < -80
+ * Rx errors: 100% = 0, 0% = 50% missed
+ *
+ * The lowest computed quality is used.
+ *
+ */
+#define BEACON_THRESHOLD 5
+ beacon_quality = 100 - missed_beacons_percent;
+ if (beacon_quality < BEACON_THRESHOLD)
+ beacon_quality = 0;
+ else
+ beacon_quality = (beacon_quality - BEACON_THRESHOLD) * 100 /
+ (100 - BEACON_THRESHOLD);
+ IPW_DEBUG_STATS("Missed beacon: %3d%% (%d%%)\n",
+ beacon_quality, missed_beacons_percent);
+
+ priv->last_rate = ipw_get_current_rate(priv);
+ rate_quality = priv->last_rate * 40 / priv->last_rate + 60;
+ IPW_DEBUG_STATS("Rate quality : %3d%% (%dMbs)\n",
+ rate_quality, priv->last_rate / 1000000);
+
+ if (rx_packets_delta > 100 && rx_packets_delta + rx_err_delta)
+ rx_quality = 100 - (rx_err_delta * 100) /
+ (rx_packets_delta + rx_err_delta);
+ else
+ rx_quality = 100;
+ IPW_DEBUG_STATS("Rx quality : %3d%% (%u errors, %u packets)\n",
+ rx_quality, rx_err_delta, rx_packets_delta);
+
+ if (tx_packets_delta > 100 && tx_packets_delta + tx_failures_delta)
+ tx_quality = 100 - (tx_failures_delta * 100) /
+ (tx_packets_delta + tx_failures_delta);
+ else
+ tx_quality = 100;
+ IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n",
+ tx_quality, tx_failures_delta, tx_packets_delta);
+
+ rssi = average_value(&priv->average_rssi);
+ if (rssi > PERFECT_RSSI)
+ signal_quality = 100;
+ else if (rssi < WORST_RSSI)
+ signal_quality = 0;
+ else
+ signal_quality = (rssi - WORST_RSSI) * 100 /
+ (PERFECT_RSSI - WORST_RSSI);
+ IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
+ signal_quality, rssi);
+
+ quality = min(beacon_quality,
+ min(rate_quality,
+ min(tx_quality, min(rx_quality, signal_quality))));
+ if (quality == beacon_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n",
+ quality);
+ if (quality == rate_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to rate quality.\n",
+ quality);
+ if (quality == tx_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to Tx quality.\n",
+ quality);
+ if (quality == rx_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to Rx quality.\n",
+ quality);
+ if (quality == signal_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to signal quality.\n",
+ quality);
+
+ priv->quality = quality;
+
+ queue_delayed_work(priv->workqueue, &priv->gather_stats,
+ IPW_STATS_INTERVAL);
+}
+
+/**
+ * Handle host notification packet.
+ * Called from interrupt routine
+ */
+static inline void ipw_rx_notification(struct ipw_priv *priv,
+ struct ipw_rx_notification *notif)
+{
+ IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size);
+
+ switch (notif->subtype) {
+ case HOST_NOTIFICATION_STATUS_ASSOCIATED:{
+ struct notif_association *assoc = &notif->u.assoc;
+
+ switch (assoc->state) {
+ case CMAS_ASSOCIATED:{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "associated: '%s' " MAC_FMT
+ " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_INFRA:
+ memcpy(priv->ieee->bssid,
+ priv->bssid, ETH_ALEN);
+ break;
+
+ case IW_MODE_ADHOC:
+ memcpy(priv->ieee->bssid,
+ priv->bssid, ETH_ALEN);
+
+ /* clear out the station table */
+ priv->num_stations = 0;
+
+ IPW_DEBUG_ASSOC
+ ("queueing adhoc check\n");
+ queue_delayed_work(priv->
+ workqueue,
+ &priv->
+ adhoc_check,
+ priv->
+ assoc_request.
+ beacon_interval);
+ break;
+ }
+
+ priv->status &= ~STATUS_ASSOCIATING;
+ priv->status |= STATUS_ASSOCIATED;
+
+ netif_carrier_on(priv->net_dev);
+ if (netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_NOTIF
+ ("waking queue\n");
+ netif_wake_queue(priv->net_dev);
+ } else {
+ IPW_DEBUG_NOTIF
+ ("starting queue\n");
+ netif_start_queue(priv->
+ net_dev);
+ }
+
+ ipw_reset_stats(priv);
+ /* Ensure the rate is updated immediately */
+ priv->last_rate =
+ ipw_get_current_rate(priv);
+ schedule_work(&priv->gather_stats);
+ notify_wx_assoc_event(priv);
+
+/* queue_delayed_work(priv->workqueue,
+ &priv->request_scan,
+ SCAN_ASSOCIATED_INTERVAL);
+*/
+ break;
+ }
+
+ case CMAS_AUTHENTICATED:{
+ if (priv->
+ status & (STATUS_ASSOCIATED |
+ STATUS_AUTH)) {
+#ifdef CONFIG_IPW_DEBUG
+ struct notif_authenticate *auth
+ = &notif->u.auth;
+ IPW_DEBUG(IPW_DL_NOTIF |
+ IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "deauthenticated: '%s' "
+ MAC_FMT
+ ": (0x%04X) - %s \n",
+ escape_essid(priv->
+ essid,
+ priv->
+ essid_len),
+ MAC_ARG(priv->bssid),
+ ntohs(auth->status),
+ ipw_get_status_code
+ (ntohs
+ (auth->status)));
+#endif
+
+ priv->status &=
+ ~(STATUS_ASSOCIATING |
+ STATUS_AUTH |
+ STATUS_ASSOCIATED);
+
+ netif_carrier_off(priv->
+ net_dev);
+ netif_stop_queue(priv->net_dev);
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ notify_wx_assoc_event(priv);
+ break;
+ }
+
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "authenticated: '%s' " MAC_FMT
+ "\n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ break;
+ }
+
+ case CMAS_INIT:{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "disassociated: '%s' " MAC_FMT
+ " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &=
+ ~(STATUS_DISASSOCIATING |
+ STATUS_ASSOCIATING |
+ STATUS_ASSOCIATED | STATUS_AUTH);
+
+ netif_stop_queue(priv->net_dev);
+ if (!(priv->status & STATUS_ROAMING)) {
+ netif_carrier_off(priv->
+ net_dev);
+ notify_wx_assoc_event(priv);
+
+ /* Cancel any queued work ... */
+ cancel_delayed_work(&priv->
+ request_scan);
+ cancel_delayed_work(&priv->
+ adhoc_check);
+
+ /* Queue up another scan... */
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+
+ cancel_delayed_work(&priv->
+ gather_stats);
+ } else {
+ priv->status |= STATUS_ROAMING;
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ }
+
+ ipw_reset_stats(priv);
+ break;
+ }
+
+ default:
+ IPW_ERROR("assoc: unknown (%d)\n",
+ assoc->state);
+ break;
+ }
+
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_AUTHENTICATE:{
+ struct notif_authenticate *auth = &notif->u.auth;
+ switch (auth->state) {
+ case CMAS_AUTHENTICATED:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "authenticated: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ priv->status |= STATUS_AUTH;
+ break;
+
+ case CMAS_INIT:
+ if (priv->status & STATUS_AUTH) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "authentication failed (0x%04X): %s\n",
+ ntohs(auth->status),
+ ipw_get_status_code(ntohs
+ (auth->
+ status)));
+ }
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "deauthenticated: '%s' " MAC_FMT "\n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &= ~(STATUS_ASSOCIATING |
+ STATUS_AUTH |
+ STATUS_ASSOCIATED);
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ notify_wx_assoc_event(priv);
+ break;
+
+ case CMAS_TX_AUTH_SEQ_1:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1\n");
+ break;
+ case CMAS_RX_AUTH_SEQ_2:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_2\n");
+ break;
+ case CMAS_AUTH_SEQ_1_PASS:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1_PASS\n");
+ break;
+ case CMAS_AUTH_SEQ_1_FAIL:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1_FAIL\n");
+ break;
+ case CMAS_TX_AUTH_SEQ_3:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_3\n");
+ break;
+ case CMAS_RX_AUTH_SEQ_4:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "RX_AUTH_SEQ_4\n");
+ break;
+ case CMAS_AUTH_SEQ_2_PASS:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_2_PASS\n");
+ break;
+ case CMAS_AUTH_SEQ_2_FAIL:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUT_SEQ_2_FAIL\n");
+ break;
+ case CMAS_TX_ASSOC:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "TX_ASSOC\n");
+ break;
+ case CMAS_RX_ASSOC_RESP:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "RX_ASSOC_RESP\n");
+ break;
+ case CMAS_ASSOCIATED:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "ASSOCIATED\n");
+ break;
+ default:
+ IPW_DEBUG_NOTIF("auth: failure - %d\n",
+ auth->state);
+ break;
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT:{
+ struct notif_channel_result *x =
+ &notif->u.channel_result;
+
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG_SCAN("Scan result for channel %d\n",
+ x->channel_num);
+ } else {
+ IPW_DEBUG_SCAN("Scan result of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_SCAN_COMPLETED:{
+ struct notif_scan_complete *x = &notif->u.scan_complete;
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG_SCAN
+ ("Scan completed: type %d, %d channels, "
+ "%d status\n", x->scan_type,
+ x->num_channels, x->status);
+ } else {
+ IPW_ERROR("Scan completed of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+
+ priv->status &=
+ ~(STATUS_SCANNING | STATUS_SCAN_ABORTING);
+
+ cancel_delayed_work(&priv->scan_check);
+
+ if (!(priv->status & (STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING |
+ STATUS_ROAMING |
+ STATUS_DISASSOCIATING)))
+ queue_work(priv->workqueue, &priv->associate);
+ else if (priv->status & STATUS_ROAMING) {
+ /* If a scan completed and we are in roam mode, then
+ * the scan that completed was the one requested as a
+ * result of entering roam... so, schedule the
+ * roam work */
+ queue_work(priv->workqueue, &priv->roam);
+ } else if (priv->status & STATUS_SCAN_PENDING)
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+
+ priv->ieee->scans++;
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{
+ struct notif_frag_length *x = &notif->u.frag_len;
+
+ if (notif->size == sizeof(*x)) {
+ IPW_ERROR("Frag length: %d\n", x->frag_length);
+ } else {
+ IPW_ERROR("Frag length of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_LINK_DETERIORATION:{
+ struct notif_link_deterioration *x =
+ &notif->u.link_deterioration;
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "link deterioration: '%s' " MAC_FMT
+ " \n", escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ memcpy(&priv->last_link_deterioration, x,
+ sizeof(*x));
+ } else {
+ IPW_ERROR("Link Deterioration of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_DINO_CONFIG_RESPONSE:{
+ IPW_ERROR("Dino config\n");
+ if (priv->hcmd
+ && priv->hcmd->cmd == HOST_CMD_DINO_CONFIG) {
+ /* TODO: Do anything special? */
+ } else {
+ IPW_ERROR("Unexpected DINO_CONFIG_RESPONSE\n");
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_BEACON_STATE:{
+ struct notif_beacon_state *x = &notif->u.beacon_state;
+ if (notif->size != sizeof(*x)) {
+ IPW_ERROR
+ ("Beacon state of wrong size %d (should "
+ "be %zd)\n", notif->size, sizeof(*x));
+ break;
+ }
+
+ if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING) {
+ if (priv->status & STATUS_SCANNING) {
+ /* Stop scan to keep fw from getting
+ * stuck... */
+ queue_work(priv->workqueue,
+ &priv->abort_scan);
+ }
+
+ if (x->number > priv->missed_beacon_threshold &&
+ priv->status & STATUS_ASSOCIATED) {
+ IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
+ IPW_DL_STATE,
+ "Missed beacon: %d - disassociate\n",
+ x->number);
+ queue_work(priv->workqueue,
+ &priv->disassociate);
+ } else if (x->number > priv->roaming_threshold) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "Missed beacon: %d - initiate "
+ "roaming\n", x->number);
+ queue_work(priv->workqueue,
+ &priv->roam);
+ } else {
+ IPW_DEBUG_NOTIF("Missed beacon: %d\n",
+ x->number);
+ }
+
+ priv->notif_missed_beacons = x->number;
+
+ }
+
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_TGI_TX_KEY:{
+ struct notif_tgi_tx_key *x = &notif->u.tgi_tx_key;
+ if (notif->size == sizeof(*x)) {
+ IPW_ERROR("TGi Tx Key: state 0x%02x sec type "
+ "0x%02x station %d\n",
+ x->key_state, x->security_type,
+ x->station_index);
+ break;
+ }
+
+ IPW_ERROR
+ ("TGi Tx Key of wrong size %d (should be %zd)\n",
+ notif->size, sizeof(*x));
+ break;
+ }
+
+ case HOST_NOTIFICATION_CALIB_KEEP_RESULTS:{
+ struct notif_calibration *x = &notif->u.calibration;
+
+ if (notif->size == sizeof(*x)) {
+ memcpy(&priv->calib, x, sizeof(*x));
+ IPW_DEBUG_INFO("TODO: Calibration\n");
+ break;
+ }
+
+ IPW_ERROR
+ ("Calibration of wrong size %d (should be %zd)\n",
+ notif->size, sizeof(*x));
+ break;
+ }
+
+ case HOST_NOTIFICATION_NOISE_STATS:{
+ if (notif->size == sizeof(u32)) {
+ priv->last_noise =
+ (u8) (notif->u.noise.value & 0xff);
+ average_add(&priv->average_noise,
+ priv->last_noise);
+ break;
+ }
+
+ IPW_ERROR
+ ("Noise stat is wrong size %d (should be %zd)\n",
+ notif->size, sizeof(u32));
+ break;
+ }
+
+ default:
+ IPW_ERROR("Unknown notification: "
+ "subtype=%d,flags=0x%2x,size=%d\n",
+ notif->subtype, notif->flags, notif->size);
+ }
+}
+
+/**
+ * Destroys all DMA structures and initialise them again
+ *
+ * @param priv
+ * @return error code
+ */
+static int ipw_queue_reset(struct ipw_priv *priv)
+{
+ int rc = 0;
+ /** @todo customize queue sizes */
+ int nTx = 64, nTxCmd = 8;
+ ipw_tx_queue_free(priv);
+ /* Tx CMD queue */
+ rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd,
+ CX2_TX_CMD_QUEUE_READ_INDEX,
+ CX2_TX_CMD_QUEUE_WRITE_INDEX,
+ CX2_TX_CMD_QUEUE_BD_BASE,
+ CX2_TX_CMD_QUEUE_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx Cmd queue init failed\n");
+ goto error;
+ }
+ /* Tx queue(s) */
+ rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx,
+ CX2_TX_QUEUE_0_READ_INDEX,
+ CX2_TX_QUEUE_0_WRITE_INDEX,
+ CX2_TX_QUEUE_0_BD_BASE, CX2_TX_QUEUE_0_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 0 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx,
+ CX2_TX_QUEUE_1_READ_INDEX,
+ CX2_TX_QUEUE_1_WRITE_INDEX,
+ CX2_TX_QUEUE_1_BD_BASE, CX2_TX_QUEUE_1_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 1 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx,
+ CX2_TX_QUEUE_2_READ_INDEX,
+ CX2_TX_QUEUE_2_WRITE_INDEX,
+ CX2_TX_QUEUE_2_BD_BASE, CX2_TX_QUEUE_2_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 2 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx,
+ CX2_TX_QUEUE_3_READ_INDEX,
+ CX2_TX_QUEUE_3_WRITE_INDEX,
+ CX2_TX_QUEUE_3_BD_BASE, CX2_TX_QUEUE_3_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 3 queue init failed\n");
+ goto error;
+ }
+ /* statistics */
+ priv->rx_bufs_min = 0;
+ priv->rx_pend_max = 0;
+ return rc;
+
+ error:
+ ipw_tx_queue_free(priv);
+ return rc;
+}
+
+/**
+ * Reclaim Tx queue entries no more used by NIC.
+ *
+ * When FW adwances 'R' index, all entries between old and
+ * new 'R' index need to be reclaimed. As result, some free space
+ * forms. If there is enough free space (> low mark), wake Tx queue.
+ *
+ * @note Need to protect against garbage in 'R' index
+ * @param priv
+ * @param txq
+ * @param qindex
+ * @return Number of used entries remains in the queue
+ */
+static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq, int qindex)
+{
+ u32 hw_tail;
+ int used;
+ struct clx2_queue *q = &txq->q;
+
+ hw_tail = ipw_read32(priv, q->reg_r);
+ if (hw_tail >= q->n_bd) {
+ IPW_ERROR
+ ("Read index for DMA queue (%d) is out of range [0-%d)\n",
+ hw_tail, q->n_bd);
+ goto done;
+ }
+ for (; q->last_used != hw_tail;
+ q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) {
+ ipw_queue_tx_free_tfd(priv, txq);
+ priv->tx_packets++;
+ }
+ done:
+ if (ipw_queue_space(q) > q->low_mark && qindex >= 0) {
+ __maybe_wake_tx(priv);
+ }
+ used = q->first_empty - q->last_used;
+ if (used < 0)
+ used += q->n_bd;
+
+ return used;
+}
+
+static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
+ int len, int sync)
+{
+ struct clx2_tx_queue *txq = &priv->txq_cmd;
+ struct clx2_queue *q = &txq->q;
+ struct tfd_frame *tfd;
+
+ if (ipw_queue_space(q) < (sync ? 1 : 2)) {
+ IPW_ERROR("No space for Tx\n");
+ return -EBUSY;
+ }
+
+ tfd = &txq->bd[q->first_empty];
+ txq->txb[q->first_empty] = NULL;
+
+ memset(tfd, 0, sizeof(*tfd));
+ tfd->control_flags.message_type = TX_HOST_COMMAND_TYPE;
+ tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK;
+ priv->hcmd_seq++;
+ tfd->u.cmd.index = hcmd;
+ tfd->u.cmd.length = len;
+ memcpy(tfd->u.cmd.payload, buf, len);
+ q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
+ ipw_write32(priv, q->reg_w, q->first_empty);
+ _ipw_read32(priv, 0x90);
+
+ return 0;
+}
+
+/*
+ * Rx theory of operation
+ *
+ * The host allocates 32 DMA target addresses and passes the host address
+ * to the firmware at register CX2_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
+ * 0 to 31
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer it will advance the READ index
+ * and fire the RX interrupt. The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free. When
+ * ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ * to replensish the ipw->rxq->rx_free.
+ * + In ipw_rx_queue_replenish (scheduled) if 'processed' != 'read' then the
+ * ipw->rxq is replenished and the READ INDEX is updated (updating the
+ * 'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ * detached from the ipw->rxq. The driver 'processed' index is updated.
+ * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free
+ * list. If there are no allocated buffers in ipw->rxq->rx_free, the READ
+ * INDEX is not incremented and ipw->status(RX_STALLED) is set. If there
+ * were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * ipw_rx_queue_alloc() Allocates rx_free
+ * ipw_rx_queue_replenish() Replenishes rx_free list from rx_used, and calls
+ * ipw_rx_queue_restock
+ * ipw_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * queue, updates firmware pointers, and updates
+ * the WRITE index. If insufficient rx_free buffers
+ * are available, schedules ipw_rx_queue_replenish
+ *
+ * -- enable interrupts --
+ * ISR - ipw_rx() Detach ipw_rx_mem_buffers from pool up to the
+ * READ INDEX, detaching the SKB from the pool.
+ * Moves the packet buffer from queue to rx_used.
+ * Calls ipw_rx_queue_restock to refill any empty
+ * slots.
+ * ...
+ *
+ */
+
+/*
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void ipw_rx_queue_restock(struct ipw_priv *priv)
+{
+ struct ipw_rx_queue *rxq = priv->rxq;
+ struct list_head *element;
+ struct ipw_rx_mem_buffer *rxb;
+ unsigned long flags;
+ int write;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ write = rxq->write;
+ while ((rxq->write != rxq->processed) && (rxq->free_count)) {
+ element = rxq->rx_free.next;
+ rxb = list_entry(element, struct ipw_rx_mem_buffer, list);
+ list_del(element);
+
+ ipw_write32(priv, CX2_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE,
+ rxb->dma_addr);
+ rxq->queue[rxq->write] = rxb;
+ rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE;
+ rxq->free_count--;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ /* If the pre-allocated buffer pool is dropping low, schedule to
+ * refill it */
+ if (rxq->free_count <= RX_LOW_WATERMARK)
+ queue_work(priv->workqueue, &priv->rx_replenish);
+
+ /* If we've added more space for the firmware to place data, tell it */
+ if (write != rxq->write)
+ ipw_write32(priv, CX2_RX_WRITE_INDEX, rxq->write);
+}
+
+/*
+ * Move all used packet from rx_used to rx_free, allocating a new SKB for each.
+ * Also restock the Rx queue via ipw_rx_queue_restock.
+ *
+ * This is called as a scheduled work item (except for during intialization)
+ */
+static void ipw_rx_queue_replenish(void *data)
+{
+ struct ipw_priv *priv = data;
+ struct ipw_rx_queue *rxq = priv->rxq;
+ struct list_head *element;
+ struct ipw_rx_mem_buffer *rxb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ while (!list_empty(&rxq->rx_used)) {
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct ipw_rx_mem_buffer, list);
+ rxb->skb = alloc_skb(CX2_RX_BUF_SIZE, GFP_ATOMIC);
+ if (!rxb->skb) {
+ printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n",
+ priv->net_dev->name);
+ /* We don't reschedule replenish work here -- we will
+ * call the restock method and if it still needs
+ * more buffers it will schedule replenish */
+ break;
+ }
+ list_del(element);
+
+ rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data;
+ rxb->dma_addr =
+ pci_map_single(priv->pci_dev, rxb->skb->data,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ ipw_rx_queue_restock(priv);
+}
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+static void ipw_rx_queue_free(struct ipw_priv *priv, struct ipw_rx_queue *rxq)
+{
+ int i;
+
+ if (!rxq)
+ return;
+
+ for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+ }
+
+ kfree(rxq);
+}
+
+static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv)
+{
+ struct ipw_rx_queue *rxq;
+ int i;
+
+ rxq = (struct ipw_rx_queue *)kmalloc(sizeof(*rxq), GFP_KERNEL);
+ memset(rxq, 0, sizeof(*rxq));
+ spin_lock_init(&rxq->lock);
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
+ /* Set us so that we have processed and used all buffers, but have
+ * not restocked the Rx queue with fresh buffers */
+ rxq->read = rxq->write = 0;
+ rxq->processed = RX_QUEUE_SIZE - 1;
+ rxq->free_count = 0;
+
+ return rxq;
+}
+
+static int ipw_is_rate_in_mask(struct ipw_priv *priv, int ieee_mode, u8 rate)
+{
+ rate &= ~IEEE80211_BASIC_RATE_MASK;
+ if (ieee_mode == IEEE_A) {
+ switch (rate) {
+ case IEEE80211_OFDM_RATE_6MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ?
+ 1 : 0;
+ case IEEE80211_OFDM_RATE_9MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ?
+ 1 : 0;
+ case IEEE80211_OFDM_RATE_12MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_18MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_24MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_36MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_48MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_54MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
+ default:
+ return 0;
+ }
+ }
+
+ /* B and G mixed */
+ switch (rate) {
+ case IEEE80211_CCK_RATE_1MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_1MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_2MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_2MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_5MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_5MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_11MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_11MB_MASK ? 1 : 0;
+ }
+
+ /* If we are limited to B modulations, bail at this point */
+ if (ieee_mode == IEEE_B)
+ return 0;
+
+ /* G */
+ switch (rate) {
+ case IEEE80211_OFDM_RATE_6MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_9MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_12MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_18MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_24MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_36MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_48MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_54MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
+ }
+
+ return 0;
+}
+
+static int ipw_compatible_rates(struct ipw_priv *priv,
+ const struct ieee80211_network *network,
+ struct ipw_supported_rates *rates)
+{
+ int num_rates, i;
+
+ memset(rates, 0, sizeof(*rates));
+ num_rates = min(network->rates_len, (u8) IPW_MAX_RATES);
+ rates->num_rates = 0;
+ for (i = 0; i < num_rates; i++) {
+ if (!ipw_is_rate_in_mask
+ (priv, network->mode, network->rates[i])) {
+ IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
+ network->rates[i], priv->rates_mask);
+ continue;
+ }
+
+ rates->supported_rates[rates->num_rates++] = network->rates[i];
+ }
+
+ num_rates =
+ min(network->rates_ex_len, (u8) (IPW_MAX_RATES - num_rates));
+ for (i = 0; i < num_rates; i++) {
+ if (!ipw_is_rate_in_mask
+ (priv, network->mode, network->rates_ex[i])) {
+ IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
+ network->rates_ex[i], priv->rates_mask);
+ continue;
+ }
+
+ rates->supported_rates[rates->num_rates++] =
+ network->rates_ex[i];
+ }
+
+ return rates->num_rates;
+}
+
+static inline void ipw_copy_rates(struct ipw_supported_rates *dest,
+ const struct ipw_supported_rates *src)
+{
+ u8 i;
+ for (i = 0; i < src->num_rates; i++)
+ dest->supported_rates[i] = src->supported_rates[i];
+ dest->num_rates = src->num_rates;
+}
+
+/* TODO: Look at sniffed packets in the air to determine if the basic rate
+ * mask should ever be used -- right now all callers to add the scan rates are
+ * set with the modulation = CCK, so BASIC_RATE_MASK is never set... */
+static void ipw_add_cck_scan_rates(struct ipw_supported_rates *rates,
+ u8 modulation, u32 rate_mask)
+{
+ u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ?
+ IEEE80211_BASIC_RATE_MASK : 0;
+
+ if (rate_mask & IEEE80211_CCK_RATE_1MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_2MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_5MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_CCK_RATE_5MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_11MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_CCK_RATE_11MB;
+}
+
+static void ipw_add_ofdm_scan_rates(struct ipw_supported_rates *rates,
+ u8 modulation, u32 rate_mask)
+{
+ u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ?
+ IEEE80211_BASIC_RATE_MASK : 0;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_6MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_6MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_9MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_9MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_12MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_12MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_18MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_18MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_24MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_24MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_36MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_36MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_48MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_48MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_54MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_54MB;
+}
+
+struct ipw_network_match {
+ struct ieee80211_network *network;
+ struct ipw_supported_rates rates;
+};
+
+static int ipw_best_network(struct ipw_priv *priv,
+ struct ipw_network_match *match,
+ struct ieee80211_network *network, int roaming)
+{
+ struct ipw_supported_rates rates;
+
+ /* Verify that this network's capability is compatible with the
+ * current mode (AdHoc or Infrastructure) */
+ if ((priv->ieee->iw_mode == IW_MODE_INFRA &&
+ !(network->capability & WLAN_CAPABILITY_ESS)) ||
+ (priv->ieee->iw_mode == IW_MODE_ADHOC &&
+ !(network->capability & WLAN_CAPABILITY_IBSS))) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded due to "
+ "capability mismatch.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ /* If we do not have an ESSID for this AP, we can not associate with
+ * it */
+ if (network->flags & NETWORK_EMPTY_ESSID) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of hidden ESSID.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ if (unlikely(roaming)) {
+ /* If we are roaming, then ensure check if this is a valid
+ * network to try and roam to */
+ if ((network->ssid_len != match->network->ssid_len) ||
+ memcmp(network->ssid, match->network->ssid,
+ network->ssid_len)) {
+ IPW_DEBUG_ASSOC("Netowrk '%s (" MAC_FMT ")' excluded "
+ "because of non-network ESSID.\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+ } else {
+ /* If an ESSID has been configured then compare the broadcast
+ * ESSID to ours */
+ if ((priv->config & CFG_STATIC_ESSID) &&
+ ((network->ssid_len != priv->essid_len) ||
+ memcmp(network->ssid, priv->essid,
+ min(network->ssid_len, priv->essid_len)))) {
+ char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+ strncpy(escaped,
+ escape_essid(network->ssid, network->ssid_len),
+ sizeof(escaped));
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of ESSID mismatch: '%s'.\n",
+ escaped, MAC_ARG(network->bssid),
+ escape_essid(priv->essid,
+ priv->essid_len));
+ return 0;
+ }
+ }
+
+ /* If the old network rate is better than this one, don't bother
+ * testing everything else. */
+ if (match->network && match->network->stats.rssi > network->stats.rssi) {
+ char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+ strncpy(escaped,
+ escape_essid(network->ssid, network->ssid_len),
+ sizeof(escaped));
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded because "
+ "'%s (" MAC_FMT ")' has a stronger signal.\n",
+ escaped, MAC_ARG(network->bssid),
+ escape_essid(match->network->ssid,
+ match->network->ssid_len),
+ MAC_ARG(match->network->bssid));
+ return 0;
+ }
+
+ /* If this network has already had an association attempt within the
+ * last 3 seconds, do not try and associate again... */
+ if (network->last_associate &&
+ time_after(network->last_associate + (HZ * 5UL), jiffies)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of storming (%lu since last "
+ "assoc attempt).\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ (jiffies - network->last_associate) / HZ);
+ return 0;
+ }
+
+ /* Now go through and see if the requested network is valid... */
+ if (priv->ieee->scan_age != 0 &&
+ jiffies - network->last_scanned > priv->ieee->scan_age) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of age: %lums.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ (jiffies - network->last_scanned) / (HZ / 100));
+ return 0;
+ }
+
+ if ((priv->config & CFG_STATIC_CHANNEL) &&
+ (network->channel != priv->channel)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of channel mismatch: %d != %d.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ network->channel, priv->channel);
+ return 0;
+ }
+
+ /* Verify privacy compatability */
+ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
+ ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of privacy mismatch: %s != %s.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ priv->capability & CAP_PRIVACY_ON ? "on" :
+ "off",
+ network->capability &
+ WLAN_CAPABILITY_PRIVACY ? "on" : "off");
+ return 0;
+ }
+
+ if ((priv->config & CFG_STATIC_BSSID) &&
+ memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of BSSID mismatch: " MAC_FMT ".\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid), MAC_ARG(priv->bssid));
+ return 0;
+ }
+
+ /* Filter out any incompatible freq / mode combinations */
+ if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of invalid frequency/mode "
+ "combination.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ ipw_compatible_rates(priv, network, &rates);
+ if (rates.num_rates == 0) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of no compatible rates.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ /* TODO: Perform any further minimal comparititive tests. We do not
+ * want to put too much policy logic here; intelligent scan selection
+ * should occur within a generic IEEE 802.11 user space tool. */
+
+ /* Set up 'new' AP to this network */
+ ipw_copy_rates(&match->rates, &rates);
+ match->network = network;
+
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' is a viable match.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+
+ return 1;
+}
+
+static void ipw_adhoc_create(struct ipw_priv *priv,
+ struct ieee80211_network *network)
+{
+ /*
+ * For the purposes of scanning, we can set our wireless mode
+ * to trigger scans across combinations of bands, but when it
+ * comes to creating a new ad-hoc network, we have tell the FW
+ * exactly which band to use.
+ *
+ * We also have the possibility of an invalid channel for the
+ * chossen band. Attempting to create a new ad-hoc network
+ * with an invalid channel for wireless mode will trigger a
+ * FW fatal error.
+ */
+ network->mode = is_valid_channel(priv->ieee->mode, priv->channel);
+ if (network->mode) {
+ network->channel = priv->channel;
+ } else {
+ IPW_WARNING("Overriding invalid channel\n");
+ if (priv->ieee->mode & IEEE_A) {
+ network->mode = IEEE_A;
+ priv->channel = band_a_active_channel[0];
+ } else if (priv->ieee->mode & IEEE_G) {
+ network->mode = IEEE_G;
+ priv->channel = band_b_active_channel[0];
+ } else {
+ network->mode = IEEE_B;
+ priv->channel = band_b_active_channel[0];
+ }
+ }
+
+ network->channel = priv->channel;
+ priv->config |= CFG_ADHOC_PERSIST;
+ ipw_create_bssid(priv, network->bssid);
+ network->ssid_len = priv->essid_len;
+ memcpy(network->ssid, priv->essid, priv->essid_len);
+ memset(&network->stats, 0, sizeof(network->stats));
+ network->capability = WLAN_CAPABILITY_IBSS;
+ if (priv->capability & CAP_PRIVACY_ON)
+ network->capability |= WLAN_CAPABILITY_PRIVACY;
+ network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH);
+ memcpy(network->rates, priv->rates.supported_rates, network->rates_len);
+ network->rates_ex_len = priv->rates.num_rates - network->rates_len;
+ memcpy(network->rates_ex,
+ &priv->rates.supported_rates[network->rates_len],
+ network->rates_ex_len);
+ network->last_scanned = 0;
+ network->flags = 0;
+ network->last_associate = 0;
+ network->time_stamp[0] = 0;
+ network->time_stamp[1] = 0;
+ network->beacon_interval = 100; /* Default */
+ network->listen_interval = 10; /* Default */
+ network->atim_window = 0; /* Default */
+#ifdef CONFIG_IEEE80211_WPA
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+#endif /* CONFIG_IEEE80211_WPA */
+}
+
+static void ipw_send_wep_keys(struct ipw_priv *priv)
+{
+ struct ipw_wep_key *key;
+ int i;
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_WEP_KEY,
+ .len = sizeof(*key)
+ };
+
+ key = (struct ipw_wep_key *)&cmd.param;
+ key->cmd_id = DINO_CMD_WEP_KEY;
+ key->seq_num = 0;
+
+ for (i = 0; i < 4; i++) {
+ key->key_index = i;
+ if (!(priv->sec.flags & (1 << i))) {
+ key->key_size = 0;
+ } else {
+ key->key_size = priv->sec.key_sizes[i];
+ memcpy(key->key, priv->sec.keys[i], key->key_size);
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send WEP_KEY command\n");
+ return;
+ }
+ }
+}
+
+static void ipw_adhoc_check(void *data)
+{
+ struct ipw_priv *priv = data;
+
+ if (priv->missed_adhoc_beacons++ > priv->missed_beacon_threshold &&
+ !(priv->config & CFG_ADHOC_PERSIST)) {
+ IPW_DEBUG_SCAN("Disassociating due to missed beacons\n");
+ ipw_remove_current_network(priv);
+ ipw_disassociate(priv);
+ return;
+ }
+
+ queue_delayed_work(priv->workqueue, &priv->adhoc_check,
+ priv->assoc_request.beacon_interval);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+static void ipw_debug_config(struct ipw_priv *priv)
+{
+ IPW_DEBUG_INFO("Scan completed, no valid APs matched "
+ "[CFG 0x%08X]\n", priv->config);
+ if (priv->config & CFG_STATIC_CHANNEL)
+ IPW_DEBUG_INFO("Channel locked to %d\n", priv->channel);
+ else
+ IPW_DEBUG_INFO("Channel unlocked.\n");
+ if (priv->config & CFG_STATIC_ESSID)
+ IPW_DEBUG_INFO("ESSID locked to '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ else
+ IPW_DEBUG_INFO("ESSID unlocked.\n");
+ if (priv->config & CFG_STATIC_BSSID)
+ IPW_DEBUG_INFO("BSSID locked to %d\n", priv->channel);
+ else
+ IPW_DEBUG_INFO("BSSID unlocked.\n");
+ if (priv->capability & CAP_PRIVACY_ON)
+ IPW_DEBUG_INFO("PRIVACY on\n");
+ else
+ IPW_DEBUG_INFO("PRIVACY off\n");
+ IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask);
+}
+#else
+#define ipw_debug_config(x) do {} while (0)
+#endif
+
+static inline void ipw_set_fixed_rate(struct ipw_priv *priv,
+ struct ieee80211_network *network)
+{
+ /* TODO: Verify that this works... */
+ struct ipw_fixed_rate fr = {
+ .tx_rates = priv->rates_mask
+ };
+ u32 reg;
+ u16 mask = 0;
+
+ /* Identify 'current FW band' and match it with the fixed
+ * Tx rates */
+
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_52GHZ_BAND: /* A only */
+ /* IEEE_A */
+ if (priv->rates_mask & ~IEEE80211_OFDM_RATES_MASK) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ break;
+ }
+
+ fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A;
+ break;
+
+ default: /* 2.4Ghz or Mixed */
+ /* IEEE_B */
+ if (network->mode == IEEE_B) {
+ if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ }
+ break;
+ }
+
+ /* IEEE_G */
+ if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK |
+ IEEE80211_OFDM_RATES_MASK)) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ break;
+ }
+
+ if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK;
+ }
+
+ if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK;
+ }
+
+ if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK;
+ }
+
+ fr.tx_rates |= mask;
+ break;
+ }
+
+ reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE);
+ ipw_write_reg32(priv, reg, *(u32 *) & fr);
+}
+
+static int ipw_associate_network(struct ipw_priv *priv,
+ struct ieee80211_network *network,
+ struct ipw_supported_rates *rates, int roaming)
+{
+ int err;
+
+ if (priv->config & CFG_FIXED_RATE)
+ ipw_set_fixed_rate(priv, network);
+
+ if (!(priv->config & CFG_STATIC_ESSID)) {
+ priv->essid_len = min(network->ssid_len,
+ (u8) IW_ESSID_MAX_SIZE);
+ memcpy(priv->essid, network->ssid, priv->essid_len);
+ }
+
+ network->last_associate = jiffies;
+
+ memset(&priv->assoc_request, 0, sizeof(priv->assoc_request));
+ priv->assoc_request.channel = network->channel;
+ if ((priv->capability & CAP_PRIVACY_ON) &&
+ (priv->capability & CAP_SHARED_KEY)) {
+ priv->assoc_request.auth_type = AUTH_SHARED_KEY;
+ priv->assoc_request.auth_key = priv->sec.active_key;
+ } else {
+ priv->assoc_request.auth_type = AUTH_OPEN;
+ priv->assoc_request.auth_key = 0;
+ }
+
+ if (priv->capability & CAP_PRIVACY_ON)
+ ipw_send_wep_keys(priv);
+
+ /*
+ * It is valid for our ieee device to support multiple modes, but
+ * when it comes to associating to a given network we have to choose
+ * just one mode.
+ */
+ if (network->mode & priv->ieee->mode & IEEE_A)
+ priv->assoc_request.ieee_mode = IPW_A_MODE;
+ else if (network->mode & priv->ieee->mode & IEEE_G)
+ priv->assoc_request.ieee_mode = IPW_G_MODE;
+ else if (network->mode & priv->ieee->mode & IEEE_B)
+ priv->assoc_request.ieee_mode = IPW_B_MODE;
+
+ IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, "
+ "802.11%c [%d], enc=%s%s%s%c%c\n",
+ roaming ? "Rea" : "A",
+ escape_essid(priv->essid, priv->essid_len),
+ network->channel,
+ ipw_modes[priv->assoc_request.ieee_mode],
+ rates->num_rates,
+ priv->capability & CAP_PRIVACY_ON ? "on " : "off",
+ priv->capability & CAP_PRIVACY_ON ?
+ (priv->capability & CAP_SHARED_KEY ? "(shared)" :
+ "(open)") : "",
+ priv->capability & CAP_PRIVACY_ON ? " key=" : "",
+ priv->capability & CAP_PRIVACY_ON ?
+ '1' + priv->sec.active_key : '.',
+ priv->capability & CAP_PRIVACY_ON ? '.' : ' ');
+
+ priv->assoc_request.beacon_interval = network->beacon_interval;
+ if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+ (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) {
+ priv->assoc_request.assoc_type = HC_IBSS_START;
+ priv->assoc_request.assoc_tsf_msw = 0;
+ priv->assoc_request.assoc_tsf_lsw = 0;
+ } else {
+ if (unlikely(roaming))
+ priv->assoc_request.assoc_type = HC_REASSOCIATE;
+ else
+ priv->assoc_request.assoc_type = HC_ASSOCIATE;
+ priv->assoc_request.assoc_tsf_msw = network->time_stamp[1];
+ priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0];
+ }
+
+ memcpy(&priv->assoc_request.bssid, network->bssid, ETH_ALEN);
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN);
+ priv->assoc_request.atim_window = network->atim_window;
+ } else {
+ memcpy(&priv->assoc_request.dest, network->bssid, ETH_ALEN);
+ priv->assoc_request.atim_window = 0;
+ }
+
+ priv->assoc_request.capability = network->capability;
+ priv->assoc_request.listen_interval = network->listen_interval;
+
+ err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send SSID command failed.\n");
+ return err;
+ }
+
+ rates->ieee_mode = priv->assoc_request.ieee_mode;
+ rates->purpose = IPW_RATE_CONNECT;
+ ipw_send_supported_rates(priv, rates);
+
+ if (priv->assoc_request.ieee_mode == IPW_G_MODE)
+ priv->sys_config.dot11g_auto_detection = 1;
+ else
+ priv->sys_config.dot11g_auto_detection = 0;
+ err = ipw_send_system_config(priv, &priv->sys_config);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send sys config command failed.\n");
+ return err;
+ }
+
+ IPW_DEBUG_ASSOC("Association sensitivity: %d\n", network->stats.rssi);
+ err = ipw_set_sensitivity(priv, network->stats.rssi);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send associate command failed.\n");
+ return err;
+ }
+
+ /*
+ * If preemption is enabled, it is possible for the association
+ * to complete before we return from ipw_send_associate. Therefore
+ * we have to be sure and update our priviate data first.
+ */
+ priv->channel = network->channel;
+ memcpy(priv->bssid, network->bssid, ETH_ALEN);
+ priv->status |= STATUS_ASSOCIATING;
+ priv->status &= ~STATUS_SECURITY_UPDATED;
+
+ priv->assoc_network = network;
+
+ err = ipw_send_associate(priv, &priv->assoc_request);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send associate command failed.\n");
+ return err;
+ }
+
+ IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid, priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ return 0;
+}
+
+static void ipw_roam(void *data)
+{
+ struct ipw_priv *priv = data;
+ struct ieee80211_network *network = NULL;
+ struct ipw_network_match match = {
+ .network = priv->assoc_network
+ };
+
+ /* The roaming process is as follows:
+ *
+ * 1. Missed beacon threshold triggers the roaming process by
+ * setting the status ROAM bit and requesting a scan.
+ * 2. When the scan completes, it schedules the ROAM work
+ * 3. The ROAM work looks at all of the known networks for one that
+ * is a better network than the currently associated. If none
+ * found, the ROAM process is over (ROAM bit cleared)
+ * 4. If a better network is found, a disassociation request is
+ * sent.
+ * 5. When the disassociation completes, the roam work is again
+ * scheduled. The second time through, the driver is no longer
+ * associated, and the newly selected network is sent an
+ * association request.
+ * 6. At this point ,the roaming process is complete and the ROAM
+ * status bit is cleared.
+ */
+
+ /* If we are no longer associated, and the roaming bit is no longer
+ * set, then we are not actively roaming, so just return */
+ if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ROAMING)))
+ return;
+
+ if (priv->status & STATUS_ASSOCIATED) {
+ /* First pass through ROAM process -- look for a better
+ * network */
+ u8 rssi = priv->assoc_network->stats.rssi;
+ priv->assoc_network->stats.rssi = -128;
+ list_for_each_entry(network, &priv->ieee->network_list, list) {
+ if (network != priv->assoc_network)
+ ipw_best_network(priv, &match, network, 1);
+ }
+ priv->assoc_network->stats.rssi = rssi;
+
+ if (match.network == priv->assoc_network) {
+ IPW_DEBUG_ASSOC("No better APs in this network to "
+ "roam to.\n");
+ priv->status &= ~STATUS_ROAMING;
+ ipw_debug_config(priv);
+ return;
+ }
+
+ ipw_send_disassociate(priv, 1);
+ priv->assoc_network = match.network;
+
+ return;
+ }
+
+ /* Second pass through ROAM process -- request association */
+ ipw_compatible_rates(priv, priv->assoc_network, &match.rates);
+ ipw_associate_network(priv, priv->assoc_network, &match.rates, 1);
+ priv->status &= ~STATUS_ROAMING;
+}
+
+static void ipw_associate(void *data)
+{
+ struct ipw_priv *priv = data;
+
+ struct ieee80211_network *network = NULL;
+ struct ipw_network_match match = {
+ .network = NULL
+ };
+ struct ipw_supported_rates *rates;
+ struct list_head *element;
+
+ if (!(priv->config & CFG_ASSOCIATE) &&
+ !(priv->config & (CFG_STATIC_ESSID |
+ CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) {
+ IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n");
+ return;
+ }
+
+ list_for_each_entry(network, &priv->ieee->network_list, list)
+ ipw_best_network(priv, &match, network, 0);
+
+ network = match.network;
+ rates = &match.rates;
+
+ if (network == NULL &&
+ priv->ieee->iw_mode == IW_MODE_ADHOC &&
+ priv->config & CFG_ADHOC_CREATE &&
+ priv->config & CFG_STATIC_ESSID &&
+ !list_empty(&priv->ieee->network_free_list)) {
+ element = priv->ieee->network_free_list.next;
+ network = list_entry(element, struct ieee80211_network, list);
+ ipw_adhoc_create(priv, network);
+ rates = &priv->rates;
+ list_del(element);
+ list_add_tail(&network->list, &priv->ieee->network_list);
+ }
+
+ /* If we reached the end of the list, then we don't have any valid
+ * matching APs */
+ if (!network) {
+ ipw_debug_config(priv);
+
+ queue_delayed_work(priv->workqueue, &priv->request_scan,
+ SCAN_INTERVAL);
+
+ return;
+ }
+
+ ipw_associate_network(priv, network, rates, 0);
+}
+
+static inline void ipw_handle_data_packet(struct ipw_priv *priv,
+ struct ipw_rx_mem_buffer *rxb,
+ struct ieee80211_rx_stats *stats)
+{
+ struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
+
+ /* We received data from the HW, so stop the watchdog */
+ priv->net_dev->trans_start = jiffies;
+
+ /* We only process data packets if the
+ * interface is open */
+ if (unlikely((pkt->u.frame.length + IPW_RX_FRAME_SIZE) >
+ skb_tailroom(rxb->skb))) {
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
+ return;
+ } else if (unlikely(!netif_running(priv->net_dev))) {
+ priv->ieee->stats.rx_dropped++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+ return;
+ }
+
+ /* Advance skb->data to the start of the actual payload */
+ skb_reserve(rxb->skb, offsetof(struct ipw_rx_packet, u.frame.data));
+
+ /* Set the size of the skb to the size of the frame */
+ skb_put(rxb->skb, pkt->u.frame.length);
+
+ IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
+
+ if (!ieee80211_rx(priv->ieee, rxb->skb, stats))
+ priv->ieee->stats.rx_errors++;
+ else /* ieee80211_rx succeeded, so it now owns the SKB */
+ rxb->skb = NULL;
+}
+
+/*
+ * Main entry function for recieving a packet with 80211 headers. This
+ * should be called when ever the FW has notified us that there is a new
+ * skb in the recieve queue.
+ */
+static void ipw_rx(struct ipw_priv *priv)
+{
+ struct ipw_rx_mem_buffer *rxb;
+ struct ipw_rx_packet *pkt;
+ struct ieee80211_hdr *header;
+ u32 r, w, i;
+ u8 network_packet;
+
+ r = ipw_read32(priv, CX2_RX_READ_INDEX);
+ w = ipw_read32(priv, CX2_RX_WRITE_INDEX);
+ i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE;
+
+ while (i != r) {
+ rxb = priv->rxq->queue[i];
+#ifdef CONFIG_IPW_DEBUG
+ if (unlikely(rxb == NULL)) {
+ printk(KERN_CRIT "Queue not allocated!\n");
+ break;
+ }
+#endif
+ priv->rxq->queue[i] = NULL;
+
+ pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
+ CX2_RX_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ pkt = (struct ipw_rx_packet *)rxb->skb->data;
+ IPW_DEBUG_RX("Packet: type=%02X seq=%02X bits=%02X\n",
+ pkt->header.message_type,
+ pkt->header.rx_seq_num, pkt->header.control_bits);
+
+ switch (pkt->header.message_type) {
+ case RX_FRAME_TYPE: /* 802.11 frame */ {
+ struct ieee80211_rx_stats stats = {
+ .rssi = pkt->u.frame.rssi_dbm -
+ IPW_RSSI_TO_DBM,
+ .signal = pkt->u.frame.signal,
+ .rate = pkt->u.frame.rate,
+ .mac_time = jiffies,
+ .received_channel =
+ pkt->u.frame.received_channel,
+ .freq =
+ (pkt->u.frame.
+ control & (1 << 0)) ?
+ IEEE80211_24GHZ_BAND :
+ IEEE80211_52GHZ_BAND,
+ .len = pkt->u.frame.length,
+ };
+
+ if (stats.rssi != 0)
+ stats.mask |= IEEE80211_STATMASK_RSSI;
+ if (stats.signal != 0)
+ stats.mask |= IEEE80211_STATMASK_SIGNAL;
+ if (stats.rate != 0)
+ stats.mask |= IEEE80211_STATMASK_RATE;
+
+ priv->rx_packets++;
+
+#ifdef CONFIG_IPW_PROMISC
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ ipw_handle_data_packet(priv, rxb,
+ &stats);
+ break;
+ }
+#endif
+
+ header =
+ (struct ieee80211_hdr *)(rxb->skb->data +
+ IPW_RX_FRAME_SIZE);
+ /* TODO: Check Ad-Hoc dest/source and make sure
+ * that we are actually parsing these packets
+ * correctly -- we should probably use the
+ * frame control of the packet and disregard
+ * the current iw_mode */
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ network_packet =
+ !memcmp(header->addr1,
+ priv->net_dev->dev_addr,
+ ETH_ALEN) ||
+ !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN) ||
+ is_broadcast_ether_addr(header->
+ addr1)
+ || is_multicast_ether_addr(header->
+ addr1);
+ break;
+
+ case IW_MODE_INFRA:
+ default:
+ network_packet =
+ !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN) ||
+ !memcmp(header->addr1,
+ priv->net_dev->dev_addr,
+ ETH_ALEN) ||
+ is_broadcast_ether_addr(header->
+ addr1)
+ || is_multicast_ether_addr(header->
+ addr1);
+ break;
+ }
+
+ if (network_packet && priv->assoc_network) {
+ priv->assoc_network->stats.rssi =
+ stats.rssi;
+ average_add(&priv->average_rssi,
+ stats.rssi);
+ priv->last_rx_rssi = stats.rssi;
+ }
+
+ IPW_DEBUG_RX("Frame: len=%u\n",
+ pkt->u.frame.length);
+
+ if (pkt->u.frame.length < frame_hdr_len(header)) {
+ IPW_DEBUG_DROP
+ ("Received packet is too small. "
+ "Dropping.\n");
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ break;
+ }
+
+ switch (WLAN_FC_GET_TYPE(header->frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ ieee80211_rx_mgt(priv->ieee, header,
+ &stats);
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC
+ &&
+ ((WLAN_FC_GET_STYPE
+ (header->frame_ctl) ==
+ IEEE80211_STYPE_PROBE_RESP)
+ ||
+ (WLAN_FC_GET_STYPE
+ (header->frame_ctl) ==
+ IEEE80211_STYPE_BEACON))
+ && !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN))
+ ipw_add_station(priv,
+ header->addr2);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+ break;
+
+ case IEEE80211_FTYPE_DATA:
+ if (network_packet)
+ ipw_handle_data_packet(priv,
+ rxb,
+ &stats);
+ else
+ IPW_DEBUG_DROP("Dropping: "
+ MAC_FMT ", "
+ MAC_FMT ", "
+ MAC_FMT "\n",
+ MAC_ARG(header->
+ addr1),
+ MAC_ARG(header->
+ addr2),
+ MAC_ARG(header->
+ addr3));
+ break;
+ }
+ break;
+ }
+
+ case RX_HOST_NOTIFICATION_TYPE:{
+ IPW_DEBUG_RX
+ ("Notification: subtype=%02X flags=%02X size=%d\n",
+ pkt->u.notification.subtype,
+ pkt->u.notification.flags,
+ pkt->u.notification.size);
+ ipw_rx_notification(priv, &pkt->u.notification);
+ break;
+ }
+
+ default:
+ IPW_DEBUG_RX("Bad Rx packet of type %d\n",
+ pkt->header.message_type);
+ break;
+ }
+
+ /* For now we just don't re-use anything. We can tweak this
+ * later to try and re-use notification packets and SKBs that
+ * fail to Rx correctly */
+ if (rxb->skb != NULL) {
+ dev_kfree_skb_any(rxb->skb);
+ rxb->skb = NULL;
+ }
+
+ pci_unmap_single(priv->pci_dev, rxb->dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ list_add_tail(&rxb->list, &priv->rxq->rx_used);
+
+ i = (i + 1) % RX_QUEUE_SIZE;
+ }
+
+ /* Backtrack one entry */
+ priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1;
+
+ ipw_rx_queue_restock(priv);
+}
+
+static void ipw_abort_scan(struct ipw_priv *priv)
+{
+ int err;
+
+ if (priv->status & STATUS_SCAN_ABORTING) {
+ IPW_DEBUG_HC("Ignoring concurrent scan abort request.\n");
+ return;
+ }
+ priv->status |= STATUS_SCAN_ABORTING;
+
+ err = ipw_send_scan_abort(priv);
+ if (err)
+ IPW_DEBUG_HC("Request to abort scan failed.\n");
+}
+
+static int ipw_request_scan(struct ipw_priv *priv)
+{
+ struct ipw_scan_request_ext scan;
+ int channel_index = 0;
+ int i, err, scan_type;
+
+ if (priv->status & STATUS_EXIT_PENDING) {
+ IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ if (priv->status & STATUS_SCANNING) {
+ IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ ipw_abort_scan(priv);
+ return 0;
+ }
+
+ if (priv->status & STATUS_SCAN_ABORTING) {
+ IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ if (priv->status & STATUS_RF_KILL_MASK) {
+ IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ memset(&scan, 0, sizeof(scan));
+
+ scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20;
+ scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20;
+ scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20;
+
+ scan.full_scan_index = ieee80211_get_scans(priv->ieee);
+ /* If we are roaming, then make this a directed scan for the current
+ * network. Otherwise, ensure that every other scan is a fast
+ * channel hop scan */
+ if ((priv->status & STATUS_ROAMING)
+ || (!(priv->status & STATUS_ASSOCIATED)
+ && (priv->config & CFG_STATIC_ESSID)
+ && (scan.full_scan_index % 2))) {
+ err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send SSID command failed.\n");
+ return err;
+ }
+
+ scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN;
+ } else {
+ scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN;
+ }
+
+ if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) {
+ int start = channel_index;
+ for (i = 0; i < MAX_A_CHANNELS; i++) {
+ if (band_a_active_channel[i] == 0)
+ break;
+ if ((priv->status & STATUS_ASSOCIATED) &&
+ band_a_active_channel[i] == priv->channel)
+ continue;
+ channel_index++;
+ scan.channels_list[channel_index] =
+ band_a_active_channel[i];
+ ipw_set_scan_type(&scan, channel_index, scan_type);
+ }
+
+ if (start != channel_index) {
+ scan.channels_list[start] = (u8) (IPW_A_MODE << 6) |
+ (channel_index - start);
+ channel_index++;
+ }
+ }
+
+ if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) {
+ int start = channel_index;
+ for (i = 0; i < MAX_B_CHANNELS; i++) {
+ if (band_b_active_channel[i] == 0)
+ break;
+ if ((priv->status & STATUS_ASSOCIATED) &&
+ band_b_active_channel[i] == priv->channel)
+ continue;
+ channel_index++;
+ scan.channels_list[channel_index] =
+ band_b_active_channel[i];
+ ipw_set_scan_type(&scan, channel_index, scan_type);
+ }
+
+ if (start != channel_index) {
+ scan.channels_list[start] = (u8) (IPW_B_MODE << 6) |
+ (channel_index - start);
+ }
+ }
+
+ err = ipw_send_scan_request_ext(priv, &scan);
+ if (err) {
+ IPW_DEBUG_HC("Sending scan command failed: %08X\n", err);
+ return -EIO;
+ }
+
+ priv->status |= STATUS_SCANNING;
+ priv->status &= ~STATUS_SCAN_PENDING;
+
+ return 0;
+}
+
+/*
+ * This file defines the Wireless Extension handlers. It does not
+ * define any methods of hardware manipulation and relies on the
+ * functions defined in ipw_main to provide the HW interaction.
+ *
+ * The exception to this is the use of the ipw_get_ordinal()
+ * function used to poll the hardware vs. making unecessary calls.
+ *
+ */
+
+static int ipw_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ if (!(priv->status & STATUS_ASSOCIATED))
+ strcpy(wrqu->name, "unassociated");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
+ ipw_modes[priv->assoc_request.ieee_mode]);
+ IPW_DEBUG_WX("Name: %s\n", wrqu->name);
+ return 0;
+}
+
+static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
+{
+ if (channel == 0) {
+ IPW_DEBUG_INFO("Setting channel to ANY (0)\n");
+ priv->config &= ~CFG_STATIC_CHANNEL;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ priv->config |= CFG_STATIC_CHANNEL;
+
+ if (priv->channel == channel) {
+ IPW_DEBUG_INFO("Request to set channel to current value (%d)\n",
+ channel);
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel);
+ priv->channel = channel;
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new channel (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to channel change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_freq *fwrq = &wrqu->freq;
+
+ /* if setting by freq convert to channel */
+ if (fwrq->e == 1) {
+ if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+
+ while ((c < REG_MAX_CHANNEL) &&
+ (f != ipw_frequencies[c]))
+ c++;
+
+ /* hack to fall through */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ }
+
+ if (fwrq->e > 0 || fwrq->m > 1000)
+ return -EOPNOTSUPP;
+
+ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+ return ipw_set_channel(priv, (u8) fwrq->m);
+
+ return 0;
+}
+
+static int ipw_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->freq.e = 0;
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured CHANNEL then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_CHANNEL ||
+ priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
+ wrqu->freq.m = priv->channel;
+ else
+ wrqu->freq.m = 0;
+
+ IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+ return 0;
+}
+
+static int ipw_wx_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode);
+
+ if (wrqu->mode == priv->ieee->iw_mode)
+ return 0;
+
+ switch (wrqu->mode) {
+#ifdef CONFIG_IPW_PROMISC
+ case IW_MODE_MONITOR:
+#endif
+ case IW_MODE_ADHOC:
+ case IW_MODE_INFRA:
+ break;
+ case IW_MODE_AUTO:
+ wrqu->mode = IW_MODE_INFRA;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_IPW_PROMISC
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ priv->net_dev->type = ARPHRD_ETHER;
+
+ if (wrqu->mode == IW_MODE_MONITOR)
+ priv->net_dev->type = ARPHRD_IEEE80211;
+#endif /* CONFIG_IPW_PROMISC */
+
+#ifdef CONFIG_PM
+ /* Free the existing firmware and reset the fw_loaded
+ * flag so ipw_load() will bring in the new firmawre */
+ if (fw_loaded) {
+ fw_loaded = 0;
+ }
+
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+ bootfw = ucode = firmware = NULL;
+#endif
+
+ priv->ieee->iw_mode = wrqu->mode;
+ ipw_adapter_restart(priv);
+
+ return err;
+}
+
+static int ipw_wx_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->mode = priv->ieee->iw_mode;
+ IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode);
+
+ return 0;
+}
+
+#define DEFAULT_RTS_THRESHOLD 2304U
+#define MIN_RTS_THRESHOLD 1U
+#define MAX_RTS_THRESHOLD 2304U
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+/* Values are in microsecond */
+static const s32 timeout_duration[] = {
+ 350000,
+ 250000,
+ 75000,
+ 37000,
+ 25000,
+};
+
+static const s32 period_duration[] = {
+ 400000,
+ 700000,
+ 1000000,
+ 1000000,
+ 1000000
+};
+
+static int ipw_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_range *range = (struct iw_range *)extra;
+ u16 val;
+ int i;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* 54Mbs == ~27 Mb/s real (802.11g) */
+ range->throughput = 27 * 1000 * 1000;
+
+ range->max_qual.qual = 100;
+ /* TODO: Find real max RSSI and stick here */
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 70;
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 0; /* FIXME to real average level */
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
+
+ for (i = 0; i < range->num_bitrates; i++)
+ range->bitrate[i] = (priv->rates.supported_rates[i] & 0x7F) *
+ 500000;
+
+ range->max_rts = DEFAULT_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;
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = ipw_frequencies[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ IPW_DEBUG_WX("GET Range\n");
+ return 0;
+}
+
+static int ipw_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ static const unsigned char any[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ static const unsigned char off[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
+ !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ /* we disable mandatory BSSID association */
+ IPW_DEBUG_WX("Setting AP BSSID to ANY\n");
+ priv->config &= ~CFG_STATIC_BSSID;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ priv->config |= CFG_STATIC_BSSID;
+ if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ IPW_DEBUG_WX("BSSID set to current BSSID.\n");
+ return 0;
+ }
+
+ IPW_DEBUG_WX("Setting mandatory BSSID to " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+
+ memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new BSSID (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ /* If we are associated, trying to associate, or have a statically
+ * configured BSSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_BSSID ||
+ priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN);
+ } else
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+ IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+ return 0;
+}
+
+static int ipw_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ char *essid = ""; /* ANY */
+ int length = 0;
+
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ length = wrqu->essid.length - 1;
+ essid = extra;
+ }
+ if (length == 0) {
+ IPW_DEBUG_WX("Setting ESSID to ANY\n");
+ priv->config &= ~CFG_STATIC_ESSID;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ length = min(length, IW_ESSID_MAX_SIZE);
+
+ priv->config |= CFG_STATIC_ESSID;
+
+ if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
+ IPW_DEBUG_WX("ESSID set to current ESSID.\n");
+ return 0;
+ }
+
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
+ length);
+
+ priv->essid_len = length;
+ memcpy(priv->essid, essid, priv->essid_len);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new ESSID (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured ESSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_ESSID ||
+ priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_WX("Getting essid: '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ memcpy(extra, priv->essid, priv->essid_len);
+ wrqu->essid.length = priv->essid_len;
+ wrqu->essid.flags = 1; /* active */
+ } else {
+ IPW_DEBUG_WX("Getting essid: ANY\n");
+ wrqu->essid.length = 0;
+ wrqu->essid.flags = 0; /* active */
+ }
+
+ return 0;
+}
+
+static int ipw_wx_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ IPW_DEBUG_WX("Setting nick to '%s'\n", extra);
+ if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+ return -E2BIG;
+
+ wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+ memset(priv->nick, 0, sizeof(priv->nick));
+ memcpy(priv->nick, extra, wrqu->data.length);
+ IPW_DEBUG_TRACE("<<\n");
+ return 0;
+
+}
+
+static int ipw_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("Getting nick\n");
+ wrqu->data.length = strlen(priv->nick) + 1;
+ memcpy(extra, priv->nick, wrqu->data.length);
+ wrqu->data.flags = 1; /* active */
+ return 0;
+}
+
+static int ipw_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->bitrate.value = priv->last_rate;
+
+ IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+ return 0;
+}
+
+static int ipw_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->rts.disabled)
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
+ else {
+ if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
+ wrqu->rts.value > MAX_RTS_THRESHOLD)
+ return -EINVAL;
+
+ priv->rts_threshold = wrqu->rts.value;
+ }
+
+ ipw_send_rts_threshold(priv, priv->rts_threshold);
+ IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
+ return 0;
+}
+
+static int ipw_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->rts.value = priv->rts_threshold;
+ wrqu->rts.fixed = 0; /* no auto select */
+ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
+
+ IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
+ return 0;
+}
+
+static int ipw_wx_set_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct ipw_tx_power tx_power;
+ int i;
+
+ if (ipw_radio_kill_sw(priv, wrqu->power.disabled))
+ return -EINPROGRESS;
+
+ if (wrqu->power.flags != IW_TXPOW_DBM)
+ return -EINVAL;
+
+ if ((wrqu->power.value > 20) || (wrqu->power.value < -12))
+ return -EINVAL;
+
+ priv->tx_power = wrqu->power.value;
+
+ memset(&tx_power, 0, sizeof(tx_power));
+
+ /* configure device for 'G' band */
+ tx_power.ieee_mode = IPW_G_MODE;
+ tx_power.num_channels = 11;
+ for (i = 0; i < 11; i++) {
+ tx_power.channels_tx_power[i].channel_number = i + 1;
+ tx_power.channels_tx_power[i].tx_power = priv->tx_power;
+ }
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* configure device to also handle 'B' band */
+ tx_power.ieee_mode = IPW_B_MODE;
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ return 0;
+
+ error:
+ return -EIO;
+}
+
+static int ipw_wx_get_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->power.value = priv->tx_power;
+ wrqu->power.fixed = 1;
+ wrqu->power.flags = IW_TXPOW_DBM;
+ wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET TX Power -> %s %d \n",
+ wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value);
+
+ return 0;
+}
+
+static int ipw_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->frag.disabled)
+ priv->ieee->fts = DEFAULT_FTS;
+ else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ priv->ieee->fts = wrqu->frag.value & ~0x1;
+ }
+
+ ipw_send_frag_threshold(priv, wrqu->frag.value);
+ IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
+ return 0;
+}
+
+static int ipw_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->frag.value = priv->ieee->fts;
+ wrqu->frag.fixed = 0; /* no auto select */
+ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
+
+ IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+
+ return 0;
+}
+
+static int ipw_wx_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("Start scan\n");
+ if (ipw_request_scan(priv))
+ return -EIO;
+ return 0;
+}
+
+static int ipw_wx_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra);
+}
+
+static int ipw_wx_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw_wx_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw_wx_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int err;
+
+ if (wrqu->power.disabled) {
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM);
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+
+ IPW_DEBUG_WX("SET Power Management Mode -> off\n");
+
+ return 0;
+ }
+
+ switch (wrqu->power.flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ break;
+ default: /* Otherwise we don't support it */
+ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
+ wrqu->power.flags);
+ return -EOPNOTSUPP;
+ }
+
+ /* If the user hasn't specified a power management mode yet, default
+ * to BATTERY */
+ if (IPW_POWER_LEVEL(priv->power_mode) == IPW_POWER_AC)
+ priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY;
+ else
+ priv->power_mode = IPW_POWER_ENABLED | priv->power_mode;
+ err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+
+ IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
+
+ return 0;
+}
+
+static int ipw_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ }
+
+ IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
+
+ return 0;
+}
+
+static int ipw_wx_set_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int mode = *(int *)extra;
+ int err;
+
+ if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
+ mode = IPW_POWER_AC;
+ priv->power_mode = mode;
+ } else {
+ priv->power_mode = IPW_POWER_ENABLED | mode;
+ }
+
+ if (priv->power_mode != mode) {
+ err = ipw_send_power_mode(priv, mode);
+
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+#define MAX_WX_STRING 80
+static int ipw_wx_get_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int level = IPW_POWER_LEVEL(priv->power_mode);
+ char *p = extra;
+
+ p += snprintf(p, MAX_WX_STRING, "Power save level: %d ", level);
+
+ switch (level) {
+ case IPW_POWER_AC:
+ p += snprintf(p, MAX_WX_STRING - (p - extra), "(AC)");
+ break;
+ case IPW_POWER_BATTERY:
+ p += snprintf(p, MAX_WX_STRING - (p - extra), "(BATTERY)");
+ break;
+ default:
+ p += snprintf(p, MAX_WX_STRING - (p - extra),
+ "(Timeout %dms, Period %dms)",
+ timeout_duration[level - 1] / 1000,
+ period_duration[level - 1] / 1000);
+ }
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED))
+ p += snprintf(p, MAX_WX_STRING - (p - extra), " OFF");
+
+ wrqu->data.length = p - extra + 1;
+
+ return 0;
+}
+
+static int ipw_wx_set_wireless_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int mode = *(int *)extra;
+ u8 band = 0, modulation = 0;
+
+ if (mode == 0 || mode & ~IEEE_MODE_MASK) {
+ IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ if (priv->adapter == IPW_2915ABG) {
+ priv->ieee->abg_ture = 1;
+ if (mode & IEEE_A) {
+ band |= IEEE80211_52GHZ_BAND;
+ modulation |= IEEE80211_OFDM_MODULATION;
+ } else
+ priv->ieee->abg_ture = 0;
+ } else {
+ if (mode & IEEE_A) {
+ IPW_WARNING("Attempt to set 2200BG into "
+ "802.11a mode\n");
+ return -EINVAL;
+ }
+
+ priv->ieee->abg_ture = 0;
+ }
+
+ if (mode & IEEE_B) {
+ band |= IEEE80211_24GHZ_BAND;
+ modulation |= IEEE80211_CCK_MODULATION;
+ } else
+ priv->ieee->abg_ture = 0;
+
+ if (mode & IEEE_G) {
+ band |= IEEE80211_24GHZ_BAND;
+ modulation |= IEEE80211_OFDM_MODULATION;
+ } else
+ priv->ieee->abg_ture = 0;
+
+ priv->ieee->mode = mode;
+ priv->ieee->freq_band = band;
+ priv->ieee->modulation = modulation;
+ init_supported_rates(priv, &priv->rates);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new configuration (causing us to
+ * disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ /* The resulting association will trigger
+ * the new rates to be sent to the device */
+ IPW_DEBUG_ASSOC("Disassociating due to mode change.\n");
+ ipw_disassociate(priv);
+ } else
+ ipw_send_supported_rates(priv, &priv->rates);
+
+ IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
+ mode & IEEE_A ? 'a' : '.',
+ mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
+ return 0;
+}
+
+static int ipw_wx_get_wireless_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_24GHZ_BAND:
+ switch (priv->ieee->modulation) {
+ case IEEE80211_CCK_MODULATION:
+ strncpy(extra, "802.11b (2)", MAX_WX_STRING);
+ break;
+ case IEEE80211_OFDM_MODULATION:
+ strncpy(extra, "802.11g (4)", MAX_WX_STRING);
+ break;
+ default:
+ strncpy(extra, "802.11bg (6)", MAX_WX_STRING);
+ break;
+ }
+ break;
+
+ case IEEE80211_52GHZ_BAND:
+ strncpy(extra, "802.11a (1)", MAX_WX_STRING);
+ break;
+
+ default: /* Mixed Band */
+ switch (priv->ieee->modulation) {
+ case IEEE80211_CCK_MODULATION:
+ strncpy(extra, "802.11ab (3)", MAX_WX_STRING);
+ break;
+ case IEEE80211_OFDM_MODULATION:
+ strncpy(extra, "802.11ag (5)", MAX_WX_STRING);
+ break;
+ default:
+ strncpy(extra, "802.11abg (7)", MAX_WX_STRING);
+ break;
+ }
+ break;
+ }
+
+ IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
+
+ wrqu->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+#ifdef CONFIG_IPW_PROMISC
+static int ipw_wx_set_promisc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int *parms = (int *)extra;
+ int enable = (parms[0] > 0);
+
+ IPW_DEBUG_WX("SET PROMISC: %d %d\n", enable, parms[1]);
+ if (enable) {
+ if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+ priv->net_dev->type = ARPHRD_IEEE80211;
+ ipw_adapter_restart(priv);
+ }
+
+ ipw_set_channel(priv, parms[1]);
+ } else {
+ if (priv->ieee->iw_mode != IW_MODE_MONITOR)
+ return 0;
+ priv->net_dev->type = ARPHRD_ETHER;
+ ipw_adapter_restart(priv);
+ }
+ return 0;
+}
+
+static int ipw_wx_reset(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("RESET\n");
+ ipw_adapter_restart(priv);
+ return 0;
+}
+#endif // CONFIG_IPW_PROMISC
+
+/* Rebase the WE IOCTLs to zero for the handler array */
+#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+static iw_handler ipw_wx_handlers[] = {
+ IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name,
+ IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
+ IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
+ IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
+ IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode,
+ IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range,
+ IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap,
+ IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap,
+ IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan,
+ IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan,
+ IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid,
+ IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid,
+ IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick,
+ IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick,
+ IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate,
+ IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate,
+ IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts,
+ IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts,
+ IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag,
+ IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag,
+ IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow,
+ IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow,
+ IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry,
+ IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry,
+ IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode,
+ IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode,
+ IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power,
+ IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power,
+};
+
+#define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV
+#define IPW_PRIV_GET_POWER SIOCIWFIRSTPRIV+1
+#define IPW_PRIV_SET_MODE SIOCIWFIRSTPRIV+2
+#define IPW_PRIV_GET_MODE SIOCIWFIRSTPRIV+3
+#define IPW_PRIV_SET_PROMISC SIOCIWFIRSTPRIV+4
+#define IPW_PRIV_RESET SIOCIWFIRSTPRIV+5
+
+static struct iw_priv_args ipw_priv_args[] = {
+ {
+ .cmd = IPW_PRIV_SET_POWER,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_power"},
+ {
+ .cmd = IPW_PRIV_GET_POWER,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_power"},
+ {
+ .cmd = IPW_PRIV_SET_MODE,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_mode"},
+ {
+ .cmd = IPW_PRIV_GET_MODE,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_mode"},
+#ifdef CONFIG_IPW_PROMISC
+ {
+ IPW_PRIV_SET_PROMISC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"},
+ {
+ IPW_PRIV_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"},
+#endif /* CONFIG_IPW_PROMISC */
+};
+
+static iw_handler ipw_priv_handler[] = {
+ ipw_wx_set_powermode,
+ ipw_wx_get_powermode,
+ ipw_wx_set_wireless_mode,
+ ipw_wx_get_wireless_mode,
+#ifdef CONFIG_IPW_PROMISC
+ ipw_wx_set_promisc,
+ ipw_wx_reset,
+#endif
+};
+
+static struct iw_handler_def ipw_wx_handler_def = {
+ .standard = ipw_wx_handlers,
+ .num_standard = ARRAY_SIZE(ipw_wx_handlers),
+ .num_private = ARRAY_SIZE(ipw_priv_handler),
+ .num_private_args = ARRAY_SIZE(ipw_priv_args),
+ .private = ipw_priv_handler,
+ .private_args = ipw_priv_args,
+};
+
+/*
+ * Get wireless statistics.
+ * Called by /proc/net/wireless
+ * Also called by SIOCGIWSTATS
+ */
+static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_statistics *wstats;
+
+ wstats = &priv->wstats;
+
+ /* if hw is disabled, then ipw2100_get_ordinal() can't be called.
+ * ipw2100_wx_wireless_stats seems to be called before fw is
+ * initialized. STATUS_ASSOCIATED will only be set if the hw is up
+ * and associated; if not associcated, the values are all meaningless
+ * anyway, so set them all to NULL and INVALID */
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 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;
+ }
+
+ wstats->qual.qual = priv->quality;
+ wstats->qual.level = average_value(&priv->average_rssi);
+ wstats->qual.noise = average_value(&priv->average_noise);
+ wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+ IW_QUAL_NOISE_UPDATED;
+
+ wstats->miss.beacon = average_value(&priv->average_missed_beacons);
+ wstats->discard.retries = priv->last_tx_failures;
+ wstats->discard.code = priv->ieee->ieee_stats.rx_discards_undecryptable;
+
+/* if (ipw_get_ordinal(priv, IPW_ORD_STAT_TX_RETRY, &tx_retry, &len))
+ goto fail_get_ordinal;
+ wstats->discard.retries += tx_retry; */
+
+ return wstats;
+}
+
+/* net device stuff */
+
+static inline void init_sys_config(struct ipw_sys_config *sys_config)
+{
+ memset(sys_config, 0, sizeof(struct ipw_sys_config));
+ sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */
+ sys_config->answer_broadcast_ssid_probe = 0;
+ sys_config->accept_all_data_frames = 0;
+ sys_config->accept_non_directed_frames = 1;
+ sys_config->exclude_unicast_unencrypted = 0;
+ sys_config->disable_unicast_decryption = 1;
+ sys_config->exclude_multicast_unencrypted = 0;
+ sys_config->disable_multicast_decryption = 1;
+ sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH;
+ sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */
+ sys_config->dot11g_auto_detection = 0;
+ sys_config->enable_cts_to_self = 0;
+ sys_config->bt_coexist_collision_thr = 0;
+ sys_config->pass_noise_stats_to_host = 1;
+}
+
+static int ipw_net_open(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_INFO("dev->open\n");
+ /* we should be verifying the device is ready to be opened */
+ if (!(priv->status & STATUS_RF_KILL_MASK) &&
+ (priv->status & STATUS_ASSOCIATED))
+ netif_start_queue(dev);
+ return 0;
+}
+
+static int ipw_net_stop(struct net_device *dev)
+{
+ IPW_DEBUG_INFO("dev->close\n");
+ netif_stop_queue(dev);
+ return 0;
+}
+
+/*
+todo:
+
+modify to send one tfd per fragment instead of using chunking. otherwise
+we need to heavily modify the ieee80211_skb_to_txb.
+*/
+
+static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
+ txb->fragments[0]->data;
+ int i = 0;
+ struct tfd_frame *tfd;
+ struct clx2_tx_queue *txq = &priv->txq[0];
+ struct clx2_queue *q = &txq->q;
+ u8 id, hdr_len, unicast;
+ u16 remaining_bytes;
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ hdr_len = IEEE80211_3ADDR_LEN;
+ unicast = !is_broadcast_ether_addr(hdr->addr1) &&
+ !is_multicast_ether_addr(hdr->addr1);
+ id = ipw_find_station(priv, hdr->addr1);
+ if (id == IPW_INVALID_STATION) {
+ id = ipw_add_station(priv, hdr->addr1);
+ if (id == IPW_INVALID_STATION) {
+ IPW_WARNING("Attempt to send data to "
+ "invalid cell: " MAC_FMT "\n",
+ MAC_ARG(hdr->addr1));
+ goto drop;
+ }
+ }
+ break;
+
+ case IW_MODE_INFRA:
+ default:
+ unicast = !is_broadcast_ether_addr(hdr->addr3) &&
+ !is_multicast_ether_addr(hdr->addr3);
+ hdr_len = IEEE80211_3ADDR_LEN;
+ id = 0;
+ break;
+ }
+
+ tfd = &txq->bd[q->first_empty];
+ txq->txb[q->first_empty] = txb;
+ memset(tfd, 0, sizeof(*tfd));
+ tfd->u.data.station_number = id;
+
+ tfd->control_flags.message_type = TX_FRAME_TYPE;
+ tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK;
+
+ tfd->u.data.cmd_id = DINO_CMD_TX;
+ tfd->u.data.len = txb->payload_size;
+ remaining_bytes = txb->payload_size;
+ if (unlikely(!unicast))
+ tfd->u.data.tx_flags = DCT_FLAG_NO_WEP;
+ else
+ tfd->u.data.tx_flags = DCT_FLAG_NO_WEP | DCT_FLAG_ACK_REQD;
+
+ if (priv->assoc_request.ieee_mode == IPW_B_MODE)
+ tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_CCK;
+ else
+ tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_OFDM;
+
+ if (priv->config & CFG_PREAMBLE)
+ tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREMBL;
+
+ memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len);
+
+ /* payload */
+ tfd->u.data.num_chunks = min((u8) (NUM_TFD_CHUNKS - 2), txb->nr_frags);
+ for (i = 0; i < tfd->u.data.num_chunks; i++) {
+ IPW_DEBUG_TX("Dumping TX packet frag %i of %i (%d bytes):\n",
+ i, tfd->u.data.num_chunks,
+ txb->fragments[i]->len - hdr_len);
+ printk_buf(IPW_DL_TX, txb->fragments[i]->data + hdr_len,
+ txb->fragments[i]->len - hdr_len);
+
+ tfd->u.data.chunk_ptr[i] =
+ pci_map_single(priv->pci_dev,
+ txb->fragments[i]->data + hdr_len,
+ txb->fragments[i]->len - hdr_len,
+ PCI_DMA_TODEVICE);
+ tfd->u.data.chunk_len[i] = txb->fragments[i]->len - hdr_len;
+ }
+
+ if (i != txb->nr_frags) {
+ struct sk_buff *skb;
+ u16 remaining_bytes = 0;
+ int j;
+
+ for (j = i; j < txb->nr_frags; j++)
+ remaining_bytes += txb->fragments[j]->len - hdr_len;
+
+ printk(KERN_INFO "Trying to reallocate for %d bytes\n",
+ remaining_bytes);
+ skb = alloc_skb(remaining_bytes, GFP_ATOMIC);
+ if (skb != NULL) {
+ tfd->u.data.chunk_len[i] = remaining_bytes;
+ for (j = i; j < txb->nr_frags; j++) {
+ int size = txb->fragments[j]->len - hdr_len;
+ printk(KERN_INFO "Adding frag %d %d...\n",
+ j, size);
+ memcpy(skb_put(skb, size),
+ txb->fragments[j]->data + hdr_len, size);
+ }
+ dev_kfree_skb_any(txb->fragments[i]);
+ txb->fragments[i] = skb;
+ tfd->u.data.chunk_ptr[i] =
+ pci_map_single(priv->pci_dev, skb->data,
+ tfd->u.data.chunk_len[i],
+ PCI_DMA_TODEVICE);
+ tfd->u.data.num_chunks++;
+ }
+ }
+
+ /* kick DMA */
+ q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
+ ipw_write32(priv, q->reg_w, q->first_empty);
+
+ if (ipw_queue_space(q) < q->high_mark)
+ netif_stop_queue(priv->net_dev);
+
+ return;
+
+ drop:
+ IPW_DEBUG_DROP("Silently dropping Tx packet.\n");
+ ieee80211_txb_free(txb);
+}
+
+static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
+ struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+
+ IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_INFO("Tx attempt while not associated.\n");
+ priv->ieee->stats.tx_carrier_errors++;
+ netif_stop_queue(dev);
+ goto fail_unlock;
+ }
+
+ ipw_tx_skb(priv, txb);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+
+ fail_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 1;
+}
+
+static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ priv->ieee->stats.tx_packets = priv->tx_packets;
+ priv->ieee->stats.rx_packets = priv->rx_packets;
+ return &priv->ieee->stats;
+}
+
+static void ipw_net_set_multicast_list(struct net_device *dev)
+{
+
+}
+
+static int ipw_net_set_mac_address(struct net_device *dev, void *p)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct sockaddr *addr = p;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+ priv->config |= CFG_CUSTOM_MAC;
+ memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
+ printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
+ priv->net_dev->name, MAC_ARG(priv->mac_addr));
+ ipw_adapter_restart(priv);
+ return 0;
+}
+
+static void ipw_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+ char vers[64];
+ char date[32];
+ u32 len;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+
+ len = sizeof(vers);
+ ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
+ len = sizeof(date);
+ ipw_get_ordinal(p, IPW_ORD_STAT_FW_DATE, date, &len);
+
+ snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
+ vers, date);
+ strcpy(info->bus_info, pci_name(p->pci_dev));
+ info->eedump_len = CX2_EEPROM_IMAGE_SIZE;
+}
+
+static u32 ipw_ethtool_get_link(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return (priv->status & STATUS_ASSOCIATED) != 0;
+}
+
+static int ipw_ethtool_get_eeprom_len(struct net_device *dev)
+{
+ return CX2_EEPROM_IMAGE_SIZE;
+}
+
+static int ipw_ethtool_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * bytes)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+
+ if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
+ return -EINVAL;
+
+ memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len);
+ return 0;
+}
+
+static int ipw_ethtool_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * bytes)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+ int i;
+
+ if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
+ return -EINVAL;
+
+ memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len);
+ for (i = IPW_EEPROM_DATA;
+ i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++)
+ ipw_write8(p, i, p->eeprom[i]);
+
+ return 0;
+}
+
+static struct ethtool_ops ipw_ethtool_ops = {
+ .get_link = ipw_ethtool_get_link,
+ .get_drvinfo = ipw_ethtool_get_drvinfo,
+ .get_eeprom_len = ipw_ethtool_get_eeprom_len,
+ .get_eeprom = ipw_ethtool_get_eeprom,
+ .set_eeprom = ipw_ethtool_set_eeprom,
+};
+
+static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
+{
+ struct ipw_priv *priv = data;
+ u32 inta, inta_mask;
+
+ if (!priv)
+ return IRQ_NONE;
+
+ spin_lock(&priv->lock);
+
+ if (!(priv->status & STATUS_INT_ENABLED)) {
+ /* Shared IRQ */
+ goto none;
+ }
+
+ inta = ipw_read32(priv, CX2_INTA_RW);
+ inta_mask = ipw_read32(priv, CX2_INTA_MASK_R);
+
+ if (inta == 0xFFFFFFFF) {
+ /* Hardware disappeared */
+ IPW_WARNING("IRQ INTA == 0xFFFFFFFF\n");
+ goto none;
+ }
+
+ if (!(inta & (CX2_INTA_MASK_ALL & inta_mask))) {
+ /* Shared interrupt */
+ goto none;
+ }
+
+ /* tell the device to stop sending interrupts */
+ ipw_disable_interrupts(priv);
+
+ /* ack current interrupts */
+ inta &= (CX2_INTA_MASK_ALL & inta_mask);
+ ipw_write32(priv, CX2_INTA_RW, inta);
+
+ /* Cache INTA value for our tasklet */
+ priv->isr_inta = inta;
+
+ tasklet_schedule(&priv->irq_tasklet);
+
+ spin_unlock(&priv->lock);
+
+ return IRQ_HANDLED;
+ none:
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+}
+
+static void ipw_rf_kill(void *adapter)
+{
+ struct ipw_priv *priv = adapter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
+ if (priv->workqueue)
+ queue_delayed_work(priv->workqueue,
+ &priv->rf_kill, 2 * HZ);
+ goto exit_unlock;
+ }
+
+ /* RF Kill is now disabled, so bring the device back up */
+
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting "
+ "device\n");
+
+ /* we can not do an adapter restart while inside an irq lock */
+ queue_work(priv->workqueue, &priv->adapter_restart);
+ } else
+ IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still "
+ "enabled\n");
+
+ exit_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int ipw_setup_deferred_work(struct ipw_priv *priv)
+{
+ int ret = 0;
+
+ priv->workqueue = create_workqueue(DRV_NAME);
+ init_waitqueue_head(&priv->wait_command_queue);
+
+ INIT_WORK(&priv->adhoc_check, ipw_adhoc_check, priv);
+ INIT_WORK(&priv->associate, ipw_associate, priv);
+ INIT_WORK(&priv->disassociate, ipw_disassociate, priv);
+ INIT_WORK(&priv->rx_replenish, ipw_rx_queue_replenish, priv);
+ INIT_WORK(&priv->adapter_restart, ipw_adapter_restart, priv);
+ INIT_WORK(&priv->rf_kill, ipw_rf_kill, priv);
+ INIT_WORK(&priv->up, (void (*)(void *))ipw_up, priv);
+ INIT_WORK(&priv->down, (void (*)(void *))ipw_down, priv);
+ INIT_WORK(&priv->request_scan,
+ (void (*)(void *))ipw_request_scan, priv);
+ INIT_WORK(&priv->gather_stats,
+ (void (*)(void *))ipw_gather_stats, priv);
+ INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv);
+ INIT_WORK(&priv->roam, ipw_roam, priv);
+ INIT_WORK(&priv->scan_check, ipw_scan_check, priv);
+
+ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ ipw_irq_tasklet, (unsigned long)priv);
+
+ return ret;
+}
+
+static void shim__set_security(struct net_device *dev,
+ struct ieee80211_security *sec)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (sec->flags & (1 << i)) {
+ priv->sec.key_sizes[i] = sec->key_sizes[i];
+ if (sec->key_sizes[i] == 0)
+ priv->sec.flags &= ~(1 << i);
+ else
+ memcpy(priv->sec.keys[i], sec->keys[i],
+ sec->key_sizes[i]);
+ priv->sec.flags |= (1 << i);
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+ }
+
+ if ((sec->flags & SEC_ACTIVE_KEY) &&
+ priv->sec.active_key != sec->active_key) {
+ if (sec->active_key <= 3) {
+ priv->sec.active_key = sec->active_key;
+ priv->sec.flags |= SEC_ACTIVE_KEY;
+ } else
+ priv->sec.flags &= ~SEC_ACTIVE_KEY;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if ((sec->flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode != sec->auth_mode)) {
+ priv->sec.auth_mode = sec->auth_mode;
+ priv->sec.flags |= SEC_AUTH_MODE;
+ if (sec->auth_mode == WLAN_AUTH_SHARED_KEY)
+ priv->capability |= CAP_SHARED_KEY;
+ else
+ priv->capability &= ~CAP_SHARED_KEY;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) {
+ priv->sec.flags |= SEC_ENABLED;
+ priv->sec.enabled = sec->enabled;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ if (sec->enabled)
+ priv->capability |= CAP_PRIVACY_ON;
+ else
+ priv->capability &= ~CAP_PRIVACY_ON;
+ }
+
+ if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) {
+ priv->sec.level = sec->level;
+ priv->sec.flags |= SEC_LEVEL;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ /* To match current functionality of ipw2100 (which works well w/
+ * various supplicants, we don't force a disassociate if the
+ * privacy capability changes ... */
+#if 0
+ if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) &&
+ (((priv->assoc_request.capability &
+ WLAN_CAPABILITY_PRIVACY) && !sec->enabled) ||
+ (!(priv->assoc_request.capability &
+ WLAN_CAPABILITY_PRIVACY) && sec->enabled))) {
+ IPW_DEBUG_ASSOC("Disassociating due to capability "
+ "change.\n");
+ ipw_disassociate(priv);
+ }
+#endif
+}
+
+static int init_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *rates)
+{
+ /* TODO: Mask out rates based on priv->rates_mask */
+
+ memset(rates, 0, sizeof(*rates));
+ /* configure supported rates */
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_52GHZ_BAND:
+ rates->ieee_mode = IPW_A_MODE;
+ rates->purpose = IPW_RATE_CAPABILITIES;
+ ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_OFDM_DEFAULT_RATES_MASK);
+ break;
+
+ default: /* Mixed or 2.4Ghz */
+ rates->ieee_mode = IPW_G_MODE;
+ rates->purpose = IPW_RATE_CAPABILITIES;
+ ipw_add_cck_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_CCK_DEFAULT_RATES_MASK);
+ if (priv->ieee->modulation & IEEE80211_OFDM_MODULATION) {
+ ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_OFDM_DEFAULT_RATES_MASK);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int ipw_config(struct ipw_priv *priv)
+{
+ int i;
+ struct ipw_tx_power tx_power;
+
+ memset(&priv->sys_config, 0, sizeof(priv->sys_config));
+ memset(&tx_power, 0, sizeof(tx_power));
+
+ /* This is only called from ipw_up, which resets/reloads the firmware
+ so, we don't need to first disable the card before we configure
+ it */
+
+ /* configure device for 'G' band */
+ tx_power.ieee_mode = IPW_G_MODE;
+ tx_power.num_channels = 11;
+ for (i = 0; i < 11; i++) {
+ tx_power.channels_tx_power[i].channel_number = i + 1;
+ tx_power.channels_tx_power[i].tx_power = priv->tx_power;
+ }
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* configure device to also handle 'B' band */
+ tx_power.ieee_mode = IPW_B_MODE;
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* initialize adapter address */
+ if (ipw_send_adapter_address(priv, priv->net_dev->dev_addr))
+ goto error;
+
+ /* set basic system config settings */
+ init_sys_config(&priv->sys_config);
+ if (ipw_send_system_config(priv, &priv->sys_config))
+ goto error;
+
+ init_supported_rates(priv, &priv->rates);
+ if (ipw_send_supported_rates(priv, &priv->rates))
+ goto error;
+
+ /* Set request-to-send threshold */
+ if (priv->rts_threshold) {
+ if (ipw_send_rts_threshold(priv, priv->rts_threshold))
+ goto error;
+ }
+
+ if (ipw_set_random_seed(priv))
+ goto error;
+
+ /* final state transition to the RUN state */
+ if (ipw_send_host_complete(priv))
+ goto error;
+
+ /* If configured to try and auto-associate, kick off a scan */
+ if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv))
+ goto error;
+
+ return 0;
+
+ error:
+ return -EIO;
+}
+
+#define MAX_HW_RESTARTS 5
+static int ipw_up(struct ipw_priv *priv)
+{
+ int rc, i;
+
+ if (priv->status & STATUS_EXIT_PENDING)
+ return -EIO;
+
+ for (i = 0; i < MAX_HW_RESTARTS; i++) {
+ /* Load the microcode, firmware, and eeprom.
+ * Also start the clocks. */
+ rc = ipw_load(priv);
+ if (rc) {
+ IPW_ERROR("Unable to load firmware: 0x%08X\n", rc);
+ return rc;
+ }
+
+ ipw_init_ordinals(priv);
+ if (!(priv->config & CFG_CUSTOM_MAC))
+ eeprom_parse_mac(priv, priv->mac_addr);
+ memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
+
+ if (priv->status & STATUS_RF_KILL_MASK)
+ return 0;
+
+ rc = ipw_config(priv);
+ if (!rc) {
+ IPW_DEBUG_INFO("Configured device on count %i\n", i);
+ priv->notif_missed_beacons = 0;
+ netif_start_queue(priv->net_dev);
+ return 0;
+ } else {
+ IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n",
+ rc);
+ }
+
+ IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n",
+ i, MAX_HW_RESTARTS);
+
+ /* We had an error bringing up the hardware, so take it
+ * all the way back down so we can try again */
+ ipw_down(priv);
+ }
+
+ /* tried to restart and config the device for as long as our
+ * patience could withstand */
+ IPW_ERROR("Unable to initialize device after %d attempts.\n", i);
+ return -EIO;
+}
+
+static void ipw_down(struct ipw_priv *priv)
+{
+ /* Attempt to disable the card */
+#if 0
+ ipw_send_card_disable(priv, 0);
+#endif
+
+ /* tell the device to stop sending interrupts */
+ ipw_disable_interrupts(priv);
+
+ /* Clear all bits but the RF Kill */
+ priv->status &= STATUS_RF_KILL_MASK;
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+
+ ipw_stop_nic(priv);
+}
+
+/* Called by register_netdev() */
+static int ipw_net_init(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (priv->status & STATUS_RF_KILL_SW) {
+ IPW_WARNING("Radio disabled by module parameter.\n");
+ return 0;
+ } else if (rf_kill_active(priv)) {
+ IPW_WARNING("Radio Frequency Kill Switch is On:\n"
+ "Kill switch must be turned off for "
+ "wireless networking to work.\n");
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+ return 0;
+ }
+
+ if (ipw_up(priv))
+ return -EIO;
+
+ return 0;
+}
+
+/* PCI driver stuff */
+static struct pci_device_id card_ids[] = {
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2712, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2721, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2722, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2731, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2732, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2741, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x103c, 0x2741, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2742, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2751, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2752, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2753, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
+ {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 2225BG */
+ {PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+ {PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+
+ /* required last entry */
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, card_ids);
+
+static struct attribute *ipw_sysfs_entries[] = {
+ &dev_attr_rf_kill.attr,
+ &dev_attr_direct_dword.attr,
+ &dev_attr_indirect_byte.attr,
+ &dev_attr_indirect_dword.attr,
+ &dev_attr_mem_gpio_reg.attr,
+ &dev_attr_command_event_reg.attr,
+ &dev_attr_nic_type.attr,
+ &dev_attr_status.attr,
+ &dev_attr_cfg.attr,
+ &dev_attr_dump_errors.attr,
+ &dev_attr_dump_events.attr,
+ &dev_attr_eeprom_delay.attr,
+ &dev_attr_ucode_version.attr,
+ &dev_attr_rtc.attr,
+ NULL
+};
+
+static struct attribute_group ipw_attribute_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = ipw_sysfs_entries,
+};
+
+static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = 0;
+ struct net_device *net_dev;
+ void __iomem *base;
+ u32 length, val;
+ struct ipw_priv *priv;
+ int band, modulation;
+
+ net_dev = alloc_ieee80211(sizeof(struct ipw_priv));
+ if (net_dev == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ priv = ieee80211_priv(net_dev);
+ priv->ieee = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ priv->pci_dev = pdev;
+#ifdef CONFIG_IPW_DEBUG
+ ipw_debug_level = debug;
+#endif
+ spin_lock_init(&priv->lock);
+
+ if (pci_enable_device(pdev)) {
+ err = -ENODEV;
+ goto out_free_ieee80211;
+ }
+
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
+ goto out_pci_disable_device;
+ }
+
+ pci_set_drvdata(pdev, priv);
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err)
+ goto out_pci_disable_device;
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ length = pci_resource_len(pdev, 0);
+ priv->hw_len = length;
+
+ base = ioremap_nocache(pci_resource_start(pdev, 0), length);
+ if (!base) {
+ err = -ENODEV;
+ goto out_pci_release_regions;
+ }
+
+ priv->hw_base = base;
+ IPW_DEBUG_INFO("pci_resource_len = 0x%08x\n", length);
+ IPW_DEBUG_INFO("pci_resource_base = %p\n", base);
+
+ err = ipw_setup_deferred_work(priv);
+ if (err) {
+ IPW_ERROR("Unable to setup deferred work\n");
+ goto out_iounmap;
+ }
+
+ /* Initialize module parameter values here */
+ if (ifname)
+ strncpy(net_dev->name, ifname, IFNAMSIZ);
+
+ if (associate)
+ priv->config |= CFG_ASSOCIATE;
+ else
+ IPW_DEBUG_INFO("Auto associate disabled.\n");
+
+ if (auto_create)
+ priv->config |= CFG_ADHOC_CREATE;
+ else
+ IPW_DEBUG_INFO("Auto adhoc creation disabled.\n");
+
+ if (disable) {
+ priv->status |= STATUS_RF_KILL_SW;
+ IPW_DEBUG_INFO("Radio disabled.\n");
+ }
+
+ if (channel != 0) {
+ priv->config |= CFG_STATIC_CHANNEL;
+ priv->channel = channel;
+ IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
+ IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
+ /* TODO: Validate that provided channel is in range */
+ }
+
+ switch (mode) {
+ case 1:
+ priv->ieee->iw_mode = IW_MODE_ADHOC;
+ break;
+#ifdef CONFIG_IPW_PROMISC
+ case 2:
+ priv->ieee->iw_mode = IW_MODE_MONITOR;
+ break;
+#endif
+ default:
+ case 0:
+ priv->ieee->iw_mode = IW_MODE_INFRA;
+ break;
+ }
+
+ if ((priv->pci_dev->device == 0x4223) ||
+ (priv->pci_dev->device == 0x4224)) {
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2915ABG Network "
+ "Connection\n");
+ priv->ieee->abg_ture = 1;
+ band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
+ modulation = IEEE80211_OFDM_MODULATION |
+ IEEE80211_CCK_MODULATION;
+ priv->adapter = IPW_2915ABG;
+ priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B;
+ } else {
+ if (priv->pci_dev->device == 0x4221)
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2225BG Network "
+ "Connection\n");
+ else
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2200BG Network "
+ "Connection\n");
+
+ priv->ieee->abg_ture = 0;
+ band = IEEE80211_24GHZ_BAND;
+ modulation = IEEE80211_OFDM_MODULATION |
+ IEEE80211_CCK_MODULATION;
+ priv->adapter = IPW_2200BG;
+ priv->ieee->mode = IEEE_G | IEEE_B;
+ }
+
+ priv->ieee->freq_band = band;
+ priv->ieee->modulation = modulation;
+
+ priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK;
+
+ priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT;
+ priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;
+
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
+
+ /* If power management is turned on, default to AC mode */
+ priv->power_mode = IPW_POWER_AC;
+ priv->tx_power = IPW_DEFAULT_TX_POWER;
+
+ err = request_irq(pdev->irq, ipw_isr, SA_SHIRQ, DRV_NAME, priv);
+ if (err) {
+ IPW_ERROR("Error allocating IRQ %d\n", pdev->irq);
+ goto out_destroy_workqueue;
+ }
+
+ SET_MODULE_OWNER(net_dev);
+ SET_NETDEV_DEV(net_dev, &pdev->dev);
+
+ priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
+ priv->ieee->set_security = shim__set_security;
+
+ net_dev->open = ipw_net_open;
+ net_dev->stop = ipw_net_stop;
+ net_dev->init = ipw_net_init;
+ net_dev->get_stats = ipw_net_get_stats;
+ net_dev->set_multicast_list = ipw_net_set_multicast_list;
+ net_dev->set_mac_address = ipw_net_set_mac_address;
+ net_dev->get_wireless_stats = ipw_get_wireless_stats;
+ net_dev->wireless_handlers = &ipw_wx_handler_def;
+ net_dev->ethtool_ops = &ipw_ethtool_ops;
+ net_dev->irq = pdev->irq;
+ net_dev->base_addr = (unsigned long)priv->hw_base;
+ net_dev->mem_start = pci_resource_start(pdev, 0);
+ net_dev->mem_end = net_dev->mem_start + pci_resource_len(pdev, 0) - 1;
+
+ err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
+ if (err) {
+ IPW_ERROR("failed to create sysfs device attributes\n");
+ goto out_release_irq;
+ }
+
+ err = register_netdev(net_dev);
+ if (err) {
+ IPW_ERROR("failed to register network device\n");
+ goto out_remove_group;
+ }
+
+ return 0;
+
+ out_remove_group:
+ sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
+ out_release_irq:
+ free_irq(pdev->irq, priv);
+ out_destroy_workqueue:
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ out_iounmap:
+ iounmap(priv->hw_base);
+ out_pci_release_regions:
+ pci_release_regions(pdev);
+ out_pci_disable_device:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ out_free_ieee80211:
+ free_ieee80211(priv->net_dev);
+ out:
+ return err;
+}
+
+static void ipw_pci_remove(struct pci_dev *pdev)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ if (!priv)
+ return;
+
+ priv->status |= STATUS_EXIT_PENDING;
+
+ sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
+
+ ipw_down(priv);
+
+ unregister_netdev(priv->net_dev);
+
+ if (priv->rxq) {
+ ipw_rx_queue_free(priv, priv->rxq);
+ priv->rxq = NULL;
+ }
+ ipw_tx_queue_free(priv);
+
+ /* ipw_down will ensure that there is no more pending work
+ * in the workqueue's, so we can safely remove them now. */
+ if (priv->workqueue) {
+ cancel_delayed_work(&priv->adhoc_check);
+ cancel_delayed_work(&priv->gather_stats);
+ cancel_delayed_work(&priv->request_scan);
+ cancel_delayed_work(&priv->rf_kill);
+ cancel_delayed_work(&priv->scan_check);
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ }
+
+ free_irq(pdev->irq, priv);
+ iounmap(priv->hw_base);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ free_ieee80211(priv->net_dev);
+
+#ifdef CONFIG_PM
+ if (fw_loaded) {
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+ fw_loaded = 0;
+ }
+#endif
+}
+
+#ifdef CONFIG_PM
+static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ struct net_device *dev = priv->net_dev;
+
+ printk(KERN_INFO "%s: Going into suspend...\n", dev->name);
+
+ /* Take down the device; powers it off, etc. */
+ ipw_down(priv);
+
+ /* Remove the PRESENT state of the device */
+ netif_device_detach(dev);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int ipw_pci_resume(struct pci_dev *pdev)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ struct net_device *dev = priv->net_dev;
+ u32 val;
+
+ printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name);
+
+ pci_set_power_state(pdev, 0);
+ pci_enable_device(pdev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+ pci_restore_state(pdev, priv->pm_state);
+#else
+ pci_restore_state(pdev);
+#endif
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
+ * from interfering with C3 CPU state. pci_restore_state won't help
+ * here since it only restores the first 64 bytes pci config header.
+ */
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ /* Set the device back into the PRESENT state; this will also wake
+ * the queue of needed */
+ netif_device_attach(dev);
+
+ /* Bring the device back up */
+ queue_work(priv->workqueue, &priv->up);
+
+ return 0;
+}
+#endif
+
+/* driver initialization stuff */
+static struct pci_driver ipw_driver = {
+ .name = DRV_NAME,
+ .id_table = card_ids,
+ .probe = ipw_pci_probe,
+ .remove = __devexit_p(ipw_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = ipw_pci_suspend,
+ .resume = ipw_pci_resume,
+#endif
+};
+
+static int __init ipw_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+
+ ret = pci_module_init(&ipw_driver);
+ if (ret) {
+ IPW_ERROR("Unable to initialize PCI module\n");
+ return ret;
+ }
+
+ ret = driver_create_file(&ipw_driver.driver, &driver_attr_debug_level);
+ if (ret) {
+ IPW_ERROR("Unable to create driver sysfs file\n");
+ pci_unregister_driver(&ipw_driver);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void __exit ipw_exit(void)
+{
+ driver_remove_file(&ipw_driver.driver, &driver_attr_debug_level);
+ pci_unregister_driver(&ipw_driver);
+}
+
+module_param(disable, int, 0444);
+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+
+module_param(associate, int, 0444);
+MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+
+module_param(auto_create, int, 0444);
+MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
+
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "debug output mask");
+
+module_param(channel, int, 0444);
+MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
+
+module_param(ifname, charp, 0444);
+MODULE_PARM_DESC(ifname, "network device name (default eth%d)");
+
+#ifdef CONFIG_IPW_PROMISC
+module_param(mode, int, 0444);
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
+#else
+module_param(mode, int, 0444);
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
+#endif
+
+module_exit(ipw_exit);
+module_init(ipw_init);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
new file mode 100644
index 000000000000..5b00882133f9
--- /dev/null
+++ b/drivers/net/wireless/ipw2200.h
@@ -0,0 +1,1680 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#ifndef __ipw2200_h__
+#define __ipw2200_h__
+
+#define WEXT_USECHANNELS 1
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/firmware.h>
+#include <linux/wireless.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+
+#include <net/ieee80211.h>
+
+#define DRV_NAME "ipw2200"
+
+#include <linux/workqueue.h>
+
+/* Authentication and Association States */
+enum connection_manager_assoc_states {
+ CMAS_INIT = 0,
+ CMAS_TX_AUTH_SEQ_1,
+ CMAS_RX_AUTH_SEQ_2,
+ CMAS_AUTH_SEQ_1_PASS,
+ CMAS_AUTH_SEQ_1_FAIL,
+ CMAS_TX_AUTH_SEQ_3,
+ CMAS_RX_AUTH_SEQ_4,
+ CMAS_AUTH_SEQ_2_PASS,
+ CMAS_AUTH_SEQ_2_FAIL,
+ CMAS_AUTHENTICATED,
+ CMAS_TX_ASSOC,
+ CMAS_RX_ASSOC_RESP,
+ CMAS_ASSOCIATED,
+ CMAS_LAST
+};
+
+#define IPW_WAIT (1<<0)
+#define IPW_QUIET (1<<1)
+#define IPW_ROAMING (1<<2)
+
+#define IPW_POWER_MODE_CAM 0x00 //(always on)
+#define IPW_POWER_INDEX_1 0x01
+#define IPW_POWER_INDEX_2 0x02
+#define IPW_POWER_INDEX_3 0x03
+#define IPW_POWER_INDEX_4 0x04
+#define IPW_POWER_INDEX_5 0x05
+#define IPW_POWER_AC 0x06
+#define IPW_POWER_BATTERY 0x07
+#define IPW_POWER_LIMIT 0x07
+#define IPW_POWER_MASK 0x0F
+#define IPW_POWER_ENABLED 0x10
+#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK)
+
+#define IPW_CMD_HOST_COMPLETE 2
+#define IPW_CMD_POWER_DOWN 4
+#define IPW_CMD_SYSTEM_CONFIG 6
+#define IPW_CMD_MULTICAST_ADDRESS 7
+#define IPW_CMD_SSID 8
+#define IPW_CMD_ADAPTER_ADDRESS 11
+#define IPW_CMD_PORT_TYPE 12
+#define IPW_CMD_RTS_THRESHOLD 15
+#define IPW_CMD_FRAG_THRESHOLD 16
+#define IPW_CMD_POWER_MODE 17
+#define IPW_CMD_WEP_KEY 18
+#define IPW_CMD_TGI_TX_KEY 19
+#define IPW_CMD_SCAN_REQUEST 20
+#define IPW_CMD_ASSOCIATE 21
+#define IPW_CMD_SUPPORTED_RATES 22
+#define IPW_CMD_SCAN_ABORT 23
+#define IPW_CMD_TX_FLUSH 24
+#define IPW_CMD_QOS_PARAMETERS 25
+#define IPW_CMD_SCAN_REQUEST_EXT 26
+#define IPW_CMD_DINO_CONFIG 30
+#define IPW_CMD_RSN_CAPABILITIES 31
+#define IPW_CMD_RX_KEY 32
+#define IPW_CMD_CARD_DISABLE 33
+#define IPW_CMD_SEED_NUMBER 34
+#define IPW_CMD_TX_POWER 35
+#define IPW_CMD_COUNTRY_INFO 36
+#define IPW_CMD_AIRONET_INFO 37
+#define IPW_CMD_AP_TX_POWER 38
+#define IPW_CMD_CCKM_INFO 39
+#define IPW_CMD_CCX_VER_INFO 40
+#define IPW_CMD_SET_CALIBRATION 41
+#define IPW_CMD_SENSITIVITY_CALIB 42
+#define IPW_CMD_RETRY_LIMIT 51
+#define IPW_CMD_IPW_PRE_POWER_DOWN 58
+#define IPW_CMD_VAP_BEACON_TEMPLATE 60
+#define IPW_CMD_VAP_DTIM_PERIOD 61
+#define IPW_CMD_EXT_SUPPORTED_RATES 62
+#define IPW_CMD_VAP_LOCAL_TX_PWR_CONSTRAINT 63
+#define IPW_CMD_VAP_QUIET_INTERVALS 64
+#define IPW_CMD_VAP_CHANNEL_SWITCH 65
+#define IPW_CMD_VAP_MANDATORY_CHANNELS 66
+#define IPW_CMD_VAP_CELL_PWR_LIMIT 67
+#define IPW_CMD_VAP_CF_PARAM_SET 68
+#define IPW_CMD_VAP_SET_BEACONING_STATE 69
+#define IPW_CMD_MEASUREMENT 80
+#define IPW_CMD_POWER_CAPABILITY 81
+#define IPW_CMD_SUPPORTED_CHANNELS 82
+#define IPW_CMD_TPC_REPORT 83
+#define IPW_CMD_WME_INFO 84
+#define IPW_CMD_PRODUCTION_COMMAND 85
+#define IPW_CMD_LINKSYS_EOU_INFO 90
+
+#define RFD_SIZE 4
+#define NUM_TFD_CHUNKS 6
+
+#define TX_QUEUE_SIZE 32
+#define RX_QUEUE_SIZE 32
+
+#define DINO_CMD_WEP_KEY 0x08
+#define DINO_CMD_TX 0x0B
+#define DCT_ANTENNA_A 0x01
+#define DCT_ANTENNA_B 0x02
+
+#define IPW_A_MODE 0
+#define IPW_B_MODE 1
+#define IPW_G_MODE 2
+
+/*
+ * TX Queue Flag Definitions
+ */
+
+/* abort attempt if mgmt frame is rx'd */
+#define DCT_FLAG_ABORT_MGMT 0x01
+
+/* require CTS */
+#define DCT_FLAG_CTS_REQUIRED 0x02
+
+/* use short preamble */
+#define DCT_FLAG_SHORT_PREMBL 0x04
+
+/* RTS/CTS first */
+#define DCT_FLAG_RTS_REQD 0x08
+
+/* dont calculate duration field */
+#define DCT_FLAG_DUR_SET 0x10
+
+/* even if MAC WEP set (allows pre-encrypt) */
+#define DCT_FLAG_NO_WEP 0x20
+
+/* overwrite TSF field */
+#define DCT_FLAG_TSF_REQD 0x40
+
+/* ACK rx is expected to follow */
+#define DCT_FLAG_ACK_REQD 0x80
+
+#define DCT_FLAG_EXT_MODE_CCK 0x01
+#define DCT_FLAG_EXT_MODE_OFDM 0x00
+
+#define TX_RX_TYPE_MASK 0xFF
+#define TX_FRAME_TYPE 0x00
+#define TX_HOST_COMMAND_TYPE 0x01
+#define RX_FRAME_TYPE 0x09
+#define RX_HOST_NOTIFICATION_TYPE 0x03
+#define RX_HOST_CMD_RESPONSE_TYPE 0x04
+#define RX_TX_FRAME_RESPONSE_TYPE 0x05
+#define TFD_NEED_IRQ_MASK 0x04
+
+#define HOST_CMD_DINO_CONFIG 30
+
+#define HOST_NOTIFICATION_STATUS_ASSOCIATED 10
+#define HOST_NOTIFICATION_STATUS_AUTHENTICATE 11
+#define HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT 12
+#define HOST_NOTIFICATION_STATUS_SCAN_COMPLETED 13
+#define HOST_NOTIFICATION_STATUS_FRAG_LENGTH 14
+#define HOST_NOTIFICATION_STATUS_LINK_DETERIORATION 15
+#define HOST_NOTIFICATION_DINO_CONFIG_RESPONSE 16
+#define HOST_NOTIFICATION_STATUS_BEACON_STATE 17
+#define HOST_NOTIFICATION_STATUS_TGI_TX_KEY 18
+#define HOST_NOTIFICATION_TX_STATUS 19
+#define HOST_NOTIFICATION_CALIB_KEEP_RESULTS 20
+#define HOST_NOTIFICATION_MEASUREMENT_STARTED 21
+#define HOST_NOTIFICATION_MEASUREMENT_ENDED 22
+#define HOST_NOTIFICATION_CHANNEL_SWITCHED 23
+#define HOST_NOTIFICATION_RX_DURING_QUIET_PERIOD 24
+#define HOST_NOTIFICATION_NOISE_STATS 25
+#define HOST_NOTIFICATION_S36_MEASUREMENT_ACCEPTED 30
+#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31
+
+#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1
+#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24
+#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8
+#define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300
+
+#define MACADRR_BYTE_LEN 6
+
+#define DCR_TYPE_AP 0x01
+#define DCR_TYPE_WLAP 0x02
+#define DCR_TYPE_MU_ESS 0x03
+#define DCR_TYPE_MU_IBSS 0x04
+#define DCR_TYPE_MU_PIBSS 0x05
+#define DCR_TYPE_SNIFFER 0x06
+#define DCR_TYPE_MU_BSS DCR_TYPE_MU_ESS
+
+/**
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct clx2_queue {
+ int n_bd; /**< number of BDs in this queue */
+ int first_empty; /**< 1-st empty entry (index) */
+ int last_used; /**< last used entry (index) */
+ u32 reg_w; /**< 'write' reg (queue head), addr in domain 1 */
+ u32 reg_r; /**< 'read' reg (queue tail), addr in domain 1 */
+ dma_addr_t dma_addr; /**< physical addr for BD's */
+ int low_mark; /**< low watermark, resume queue if free space more than this */
+ int high_mark; /**< high watermark, stop queue if free space less than this */
+} __attribute__ ((packed));
+
+struct machdr32 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+ u16 qos_ctrl;
+} __attribute__ ((packed));
+
+struct machdr30 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+} __attribute__ ((packed));
+
+struct machdr26 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u16 qos_ctrl;
+} __attribute__ ((packed));
+
+struct machdr24 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+} __attribute__ ((packed));
+
+// TX TFD with 32 byte MAC Header
+struct tx_tfd_32 {
+ struct machdr32 mchdr; // 32
+ u32 uivplaceholder[2]; // 8
+} __attribute__ ((packed));
+
+// TX TFD with 30 byte MAC Header
+struct tx_tfd_30 {
+ struct machdr30 mchdr; // 30
+ u8 reserved[2]; // 2
+ u32 uivplaceholder[2]; // 8
+} __attribute__ ((packed));
+
+// tx tfd with 26 byte mac header
+struct tx_tfd_26 {
+ struct machdr26 mchdr; // 26
+ u8 reserved1[2]; // 2
+ u32 uivplaceholder[2]; // 8
+ u8 reserved2[4]; // 4
+} __attribute__ ((packed));
+
+// tx tfd with 24 byte mac header
+struct tx_tfd_24 {
+ struct machdr24 mchdr; // 24
+ u32 uivplaceholder[2]; // 8
+ u8 reserved[8]; // 8
+} __attribute__ ((packed));
+
+#define DCT_WEP_KEY_FIELD_LENGTH 16
+
+struct tfd_command {
+ u8 index;
+ u8 length;
+ u16 reserved;
+ u8 payload[0];
+} __attribute__ ((packed));
+
+struct tfd_data {
+ /* Header */
+ u32 work_area_ptr;
+ u8 station_number; /* 0 for BSS */
+ u8 reserved1;
+ u16 reserved2;
+
+ /* Tx Parameters */
+ u8 cmd_id;
+ u8 seq_num;
+ u16 len;
+ u8 priority;
+ u8 tx_flags;
+ u8 tx_flags_ext;
+ u8 key_index;
+ u8 wepkey[DCT_WEP_KEY_FIELD_LENGTH];
+ u8 rate;
+ u8 antenna;
+ u16 next_packet_duration;
+ u16 next_frag_len;
+ u16 back_off_counter; //////txop;
+ u8 retrylimit;
+ u16 cwcurrent;
+ u8 reserved3;
+
+ /* 802.11 MAC Header */
+ union {
+ struct tx_tfd_24 tfd_24;
+ struct tx_tfd_26 tfd_26;
+ struct tx_tfd_30 tfd_30;
+ struct tx_tfd_32 tfd_32;
+ } tfd;
+
+ /* Payload DMA info */
+ u32 num_chunks;
+ u32 chunk_ptr[NUM_TFD_CHUNKS];
+ u16 chunk_len[NUM_TFD_CHUNKS];
+} __attribute__ ((packed));
+
+struct txrx_control_flags {
+ u8 message_type;
+ u8 rx_seq_num;
+ u8 control_bits;
+ u8 reserved;
+} __attribute__ ((packed));
+
+#define TFD_SIZE 128
+#define TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH (TFD_SIZE - sizeof(struct txrx_control_flags))
+
+struct tfd_frame {
+ struct txrx_control_flags control_flags;
+ union {
+ struct tfd_data data;
+ struct tfd_command cmd;
+ u8 raw[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+ } u;
+} __attribute__ ((packed));
+
+typedef void destructor_func(const void *);
+
+/**
+ * Tx Queue for DMA. Queue consists of circular buffer of
+ * BD's and required locking structures.
+ */
+struct clx2_tx_queue {
+ struct clx2_queue q;
+ struct tfd_frame *bd;
+ struct ieee80211_txb **txb;
+};
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 32
+#define RX_LOW_WATERMARK 8
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS (8)
+#define SUP_RATE_11B_MAX_NUM_CHANNELS (4)
+#define SUP_RATE_11G_MAX_NUM_CHANNELS (12)
+
+// Used for passing to driver number of successes and failures per rate
+struct rate_histogram {
+ union {
+ u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } success;
+ union {
+ u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } failed;
+} __attribute__ ((packed));
+
+/* statistics command response */
+struct ipw_cmd_stats {
+ u8 cmd_id;
+ u8 seq_num;
+ u16 good_sfd;
+ u16 bad_plcp;
+ u16 wrong_bssid;
+ u16 valid_mpdu;
+ u16 bad_mac_header;
+ u16 reserved_frame_types;
+ u16 rx_ina;
+ u16 bad_crc32;
+ u16 invalid_cts;
+ u16 invalid_acks;
+ u16 long_distance_ina_fina;
+ u16 dsp_silence_unreachable;
+ u16 accumulated_rssi;
+ u16 rx_ovfl_frame_tossed;
+ u16 rssi_silence_threshold;
+ u16 rx_ovfl_frame_supplied;
+ u16 last_rx_frame_signal;
+ u16 last_rx_frame_noise;
+ u16 rx_autodetec_no_ofdm;
+ u16 rx_autodetec_no_barker;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct notif_channel_result {
+ u8 channel_num;
+ struct ipw_cmd_stats stats;
+ u8 uReserved;
+} __attribute__ ((packed));
+
+struct notif_scan_complete {
+ u8 scan_type;
+ u8 num_channels;
+ u8 status;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct notif_frag_length {
+ u16 frag_length;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct notif_beacon_state {
+ u32 state;
+ u32 number;
+} __attribute__ ((packed));
+
+struct notif_tgi_tx_key {
+ u8 key_state;
+ u8 security_type;
+ u8 station_index;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct notif_link_deterioration {
+ struct ipw_cmd_stats stats;
+ u8 rate;
+ u8 modulation;
+ struct rate_histogram histogram;
+ u8 reserved1;
+ u16 reserved2;
+} __attribute__ ((packed));
+
+struct notif_association {
+ u8 state;
+} __attribute__ ((packed));
+
+struct notif_authenticate {
+ u8 state;
+ struct machdr24 addr;
+ u16 status;
+} __attribute__ ((packed));
+
+struct notif_calibration {
+ u8 data[104];
+} __attribute__ ((packed));
+
+struct notif_noise {
+ u32 value;
+} __attribute__ ((packed));
+
+struct ipw_rx_notification {
+ u8 reserved[8];
+ u8 subtype;
+ u8 flags;
+ u16 size;
+ union {
+ struct notif_association assoc;
+ struct notif_authenticate auth;
+ struct notif_channel_result channel_result;
+ struct notif_scan_complete scan_complete;
+ struct notif_frag_length frag_len;
+ struct notif_beacon_state beacon_state;
+ struct notif_tgi_tx_key tgi_tx_key;
+ struct notif_link_deterioration link_deterioration;
+ struct notif_calibration calibration;
+ struct notif_noise noise;
+ u8 raw[0];
+ } u;
+} __attribute__ ((packed));
+
+struct ipw_rx_frame {
+ u32 reserved1;
+ u8 parent_tsf[4]; // fw_use[0] is boolean for OUR_TSF_IS_GREATER
+ u8 received_channel; // The channel that this frame was received on.
+ // Note that for .11b this does not have to be
+ // the same as the channel that it was sent.
+ // Filled by LMAC
+ u8 frameStatus;
+ u8 rate;
+ u8 rssi;
+ u8 agc;
+ u8 rssi_dbm;
+ u16 signal;
+ u16 noise;
+ u8 antennaAndPhy;
+ u8 control; // control bit should be on in bg
+ u8 rtscts_rate; // rate of rts or cts (in rts cts sequence rate
+ // is identical)
+ u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen
+ u16 length;
+ u8 data[0];
+} __attribute__ ((packed));
+
+struct ipw_rx_header {
+ u8 message_type;
+ u8 rx_seq_num;
+ u8 control_bits;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_rx_packet {
+ struct ipw_rx_header header;
+ union {
+ struct ipw_rx_frame frame;
+ struct ipw_rx_notification notification;
+ } u;
+} __attribute__ ((packed));
+
+#define IPW_RX_NOTIFICATION_SIZE sizeof(struct ipw_rx_header) + 12
+#define IPW_RX_FRAME_SIZE sizeof(struct ipw_rx_header) + \
+ sizeof(struct ipw_rx_frame)
+
+struct ipw_rx_mem_buffer {
+ dma_addr_t dma_addr;
+ struct ipw_rx_buffer *rxb;
+ struct sk_buff *skb;
+ struct list_head list;
+}; /* Not transferred over network, so not __attribute__ ((packed)) */
+
+struct ipw_rx_queue {
+ struct ipw_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct ipw_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ u32 processed; /* Internal index to last handled Rx packet */
+ u32 read; /* Shared index to newest available Rx buffer */
+ u32 write; /* Shared index to oldest written Rx packet */
+ u32 free_count; /* Number of pre-allocated buffers in rx_free */
+ /* Each of these lists is used as a FIFO for ipw_rx_mem_buffers */
+ struct list_head rx_free; /* Own an SKBs */
+ struct list_head rx_used; /* No SKB allocated */
+ spinlock_t lock;
+}; /* Not transferred over network, so not __attribute__ ((packed)) */
+
+struct alive_command_responce {
+ u8 alive_command;
+ u8 sequence_number;
+ u16 software_revision;
+ u8 device_identifier;
+ u8 reserved1[5];
+ u16 reserved2;
+ u16 reserved3;
+ u16 clock_settle_time;
+ u16 powerup_settle_time;
+ u16 reserved4;
+ u8 time_stamp[5]; /* month, day, year, hours, minutes */
+ u8 ucode_valid;
+} __attribute__ ((packed));
+
+#define IPW_MAX_RATES 12
+
+struct ipw_rates {
+ u8 num_rates;
+ u8 rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct command_block {
+ unsigned int control;
+ u32 source_addr;
+ u32 dest_addr;
+ unsigned int status;
+} __attribute__ ((packed));
+
+#define CB_NUMBER_OF_ELEMENTS_SMALL 64
+struct fw_image_desc {
+ unsigned long last_cb_index;
+ unsigned long current_cb_index;
+ struct command_block cb_list[CB_NUMBER_OF_ELEMENTS_SMALL];
+ void *v_addr;
+ unsigned long p_addr;
+ unsigned long len;
+};
+
+struct ipw_sys_config {
+ u8 bt_coexistence;
+ u8 reserved1;
+ u8 answer_broadcast_ssid_probe;
+ u8 accept_all_data_frames;
+ u8 accept_non_directed_frames;
+ u8 exclude_unicast_unencrypted;
+ u8 disable_unicast_decryption;
+ u8 exclude_multicast_unencrypted;
+ u8 disable_multicast_decryption;
+ u8 antenna_diversity;
+ u8 pass_crc_to_host;
+ u8 dot11g_auto_detection;
+ u8 enable_cts_to_self;
+ u8 enable_multicast_filtering;
+ u8 bt_coexist_collision_thr;
+ u8 reserved2;
+ u8 accept_all_mgmt_bcpr;
+ u8 accept_all_mgtm_frames;
+ u8 pass_noise_stats_to_host;
+ u8 reserved3;
+} __attribute__ ((packed));
+
+struct ipw_multicast_addr {
+ u8 num_of_multicast_addresses;
+ u8 reserved[3];
+ u8 mac1[6];
+ u8 mac2[6];
+ u8 mac3[6];
+ u8 mac4[6];
+} __attribute__ ((packed));
+
+struct ipw_wep_key {
+ u8 cmd_id;
+ u8 seq_num;
+ u8 key_index;
+ u8 key_size;
+ u8 key[16];
+} __attribute__ ((packed));
+
+struct ipw_tgi_tx_key {
+ u8 key_id;
+ u8 security_type;
+ u8 station_index;
+ u8 flags;
+ u8 key[16];
+ u32 tx_counter[2];
+} __attribute__ ((packed));
+
+#define IPW_SCAN_CHANNELS 54
+
+struct ipw_scan_request {
+ u8 scan_type;
+ u16 dwell_time;
+ u8 channels_list[IPW_SCAN_CHANNELS];
+ u8 channels_reserved[3];
+} __attribute__ ((packed));
+
+enum {
+ IPW_SCAN_PASSIVE_TILL_FIRST_BEACON_SCAN = 0,
+ IPW_SCAN_PASSIVE_FULL_DWELL_SCAN,
+ IPW_SCAN_ACTIVE_DIRECT_SCAN,
+ IPW_SCAN_ACTIVE_BROADCAST_SCAN,
+ IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN,
+ IPW_SCAN_TYPES
+};
+
+struct ipw_scan_request_ext {
+ u32 full_scan_index;
+ u8 channels_list[IPW_SCAN_CHANNELS];
+ u8 scan_type[IPW_SCAN_CHANNELS / 2];
+ u8 reserved;
+ u16 dwell_time[IPW_SCAN_TYPES];
+} __attribute__ ((packed));
+
+extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
+{
+ if (index % 2)
+ return scan->scan_type[index / 2] & 0x0F;
+ else
+ return (scan->scan_type[index / 2] & 0xF0) >> 4;
+}
+
+extern inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+ u8 index, u8 scan_type)
+{
+ if (index % 2)
+ scan->scan_type[index / 2] =
+ (scan->scan_type[index / 2] & 0xF0) | (scan_type & 0x0F);
+ else
+ scan->scan_type[index / 2] =
+ (scan->scan_type[index / 2] & 0x0F) |
+ ((scan_type & 0x0F) << 4);
+}
+
+struct ipw_associate {
+ u8 channel;
+ u8 auth_type:4, auth_key:4;
+ u8 assoc_type;
+ u8 reserved;
+ u16 policy_support;
+ u8 preamble_length;
+ u8 ieee_mode;
+ u8 bssid[ETH_ALEN];
+ u32 assoc_tsf_msw;
+ u32 assoc_tsf_lsw;
+ u16 capability;
+ u16 listen_interval;
+ u16 beacon_interval;
+ u8 dest[ETH_ALEN];
+ u16 atim_window;
+ u8 smr;
+ u8 reserved1;
+ u16 reserved2;
+} __attribute__ ((packed));
+
+struct ipw_supported_rates {
+ u8 ieee_mode;
+ u8 num_rates;
+ u8 purpose;
+ u8 reserved;
+ u8 supported_rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct ipw_rts_threshold {
+ u16 rts_threshold;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_frag_threshold {
+ u16 frag_threshold;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_retry_limit {
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_dino_config {
+ u32 dino_config_addr;
+ u16 dino_config_size;
+ u8 dino_response;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_aironet_info {
+ u8 id;
+ u8 length;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_rx_key {
+ u8 station_index;
+ u8 key_type;
+ u8 key_id;
+ u8 key_flag;
+ u8 key[16];
+ u8 station_address[6];
+ u8 key_index;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_country_channel_info {
+ u8 first_channel;
+ u8 no_channels;
+ s8 max_tx_power;
+} __attribute__ ((packed));
+
+struct ipw_country_info {
+ u8 id;
+ u8 length;
+ u8 country_str[3];
+ struct ipw_country_channel_info groups[7];
+} __attribute__ ((packed));
+
+struct ipw_channel_tx_power {
+ u8 channel_number;
+ s8 tx_power;
+} __attribute__ ((packed));
+
+#define SCAN_ASSOCIATED_INTERVAL (HZ)
+#define SCAN_INTERVAL (HZ / 10)
+#define MAX_A_CHANNELS 37
+#define MAX_B_CHANNELS 14
+
+struct ipw_tx_power {
+ u8 num_channels;
+ u8 ieee_mode;
+ struct ipw_channel_tx_power channels_tx_power[MAX_A_CHANNELS];
+} __attribute__ ((packed));
+
+struct ipw_qos_parameters {
+ u16 cw_min[4];
+ u16 cw_max[4];
+ u8 aifs[4];
+ u8 flag[4];
+ u16 tx_op_limit[4];
+} __attribute__ ((packed));
+
+struct ipw_rsn_capabilities {
+ u8 id;
+ u8 length;
+ u16 version;
+} __attribute__ ((packed));
+
+struct ipw_sensitivity_calib {
+ u16 beacon_rssi_raw;
+ u16 reserved;
+} __attribute__ ((packed));
+
+/**
+ * Host command structure.
+ *
+ * On input, the following fields should be filled:
+ * - cmd
+ * - len
+ * - status_len
+ * - param (if needed)
+ *
+ * On output,
+ * - \a status contains status;
+ * - \a param filled with status parameters.
+ */
+struct ipw_cmd {
+ u32 cmd; /**< Host command */
+ u32 status;/**< Status */
+ u32 status_len;
+ /**< How many 32 bit parameters in the status */
+ u32 len; /**< incoming parameters length, bytes */
+ /**
+ * command parameters.
+ * There should be enough space for incoming and
+ * outcoming parameters.
+ * Incoming parameters listed 1-st, followed by outcoming params.
+ * nParams=(len+3)/4+status_len
+ */
+ u32 param[0];
+} __attribute__ ((packed));
+
+#define STATUS_HCMD_ACTIVE (1<<0) /**< host command in progress */
+
+#define STATUS_INT_ENABLED (1<<1)
+#define STATUS_RF_KILL_HW (1<<2)
+#define STATUS_RF_KILL_SW (1<<3)
+#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW)
+
+#define STATUS_INIT (1<<5)
+#define STATUS_AUTH (1<<6)
+#define STATUS_ASSOCIATED (1<<7)
+#define STATUS_STATE_MASK (STATUS_INIT | STATUS_AUTH | STATUS_ASSOCIATED)
+
+#define STATUS_ASSOCIATING (1<<8)
+#define STATUS_DISASSOCIATING (1<<9)
+#define STATUS_ROAMING (1<<10)
+#define STATUS_EXIT_PENDING (1<<11)
+#define STATUS_DISASSOC_PENDING (1<<12)
+#define STATUS_STATE_PENDING (1<<13)
+
+#define STATUS_SCAN_PENDING (1<<20)
+#define STATUS_SCANNING (1<<21)
+#define STATUS_SCAN_ABORTING (1<<22)
+
+#define STATUS_INDIRECT_BYTE (1<<28) /* sysfs entry configured for access */
+#define STATUS_INDIRECT_DWORD (1<<29) /* sysfs entry configured for access */
+#define STATUS_DIRECT_DWORD (1<<30) /* sysfs entry configured for access */
+
+#define STATUS_SECURITY_UPDATED (1<<31) /* Security sync needed */
+
+#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */
+#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */
+#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */
+#define CFG_CUSTOM_MAC (1<<3)
+#define CFG_PREAMBLE (1<<4)
+#define CFG_ADHOC_PERSIST (1<<5)
+#define CFG_ASSOCIATE (1<<6)
+#define CFG_FIXED_RATE (1<<7)
+#define CFG_ADHOC_CREATE (1<<8)
+
+#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */
+#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */
+
+#define MAX_STATIONS 32
+#define IPW_INVALID_STATION (0xff)
+
+struct ipw_station_entry {
+ u8 mac_addr[ETH_ALEN];
+ u8 reserved;
+ u8 support_mode;
+};
+
+#define AVG_ENTRIES 8
+struct average {
+ s16 entries[AVG_ENTRIES];
+ u8 pos;
+ u8 init;
+ s32 sum;
+};
+
+struct ipw_priv {
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_device *ieee;
+ struct ieee80211_security sec;
+
+ /* spinlock */
+ spinlock_t lock;
+
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+ struct net_device *net_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+ unsigned long hw_len;
+
+ struct fw_image_desc sram_desc;
+
+ /* result of ucode download */
+ struct alive_command_responce dino_alive;
+
+ wait_queue_head_t wait_command_queue;
+ wait_queue_head_t wait_state;
+
+ /* Rx and Tx DMA processing queues */
+ struct ipw_rx_queue *rxq;
+ struct clx2_tx_queue txq_cmd;
+ struct clx2_tx_queue txq[4];
+ u32 status;
+ u32 config;
+ u32 capability;
+
+ u8 last_rx_rssi;
+ u8 last_noise;
+ struct average average_missed_beacons;
+ struct average average_rssi;
+ struct average average_noise;
+ u32 port_type;
+ int rx_bufs_min; /**< minimum number of bufs in Rx queue */
+ int rx_pend_max; /**< maximum pending buffers for one IRQ */
+ u32 hcmd_seq; /**< sequence number for hcmd */
+ u32 missed_beacon_threshold;
+ u32 roaming_threshold;
+
+ struct ipw_associate assoc_request;
+ struct ieee80211_network *assoc_network;
+
+ unsigned long ts_scan_abort;
+ struct ipw_supported_rates rates;
+ struct ipw_rates phy[3]; /**< PHY restrictions, per band */
+ struct ipw_rates supp; /**< software defined */
+ struct ipw_rates extended; /**< use for corresp. IE, AP only */
+
+ struct notif_link_deterioration last_link_deterioration; /** for statistics */
+ struct ipw_cmd *hcmd; /**< host command currently executed */
+
+ wait_queue_head_t hcmd_wq; /**< host command waits for execution */
+ u32 tsf_bcn[2]; /**< TSF from latest beacon */
+
+ struct notif_calibration calib; /**< last calibration */
+
+ /* ordinal interface with firmware */
+ u32 table0_addr;
+ u32 table0_len;
+ u32 table1_addr;
+ u32 table1_len;
+ u32 table2_addr;
+ u32 table2_len;
+
+ /* context information */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u8 nick[IW_ESSID_MAX_SIZE];
+ u16 rates_mask;
+ u8 channel;
+ struct ipw_sys_config sys_config;
+ u32 power_mode;
+ u8 bssid[ETH_ALEN];
+ u16 rts_threshold;
+ u8 mac_addr[ETH_ALEN];
+ u8 num_stations;
+ u8 stations[MAX_STATIONS][ETH_ALEN];
+
+ u32 notif_missed_beacons;
+
+ /* Statistics and counters normalized with each association */
+ u32 last_missed_beacons;
+ u32 last_tx_packets;
+ u32 last_rx_packets;
+ u32 last_tx_failures;
+ u32 last_rx_err;
+ u32 last_rate;
+
+ u32 missed_adhoc_beacons;
+ u32 missed_beacons;
+ u32 rx_packets;
+ u32 tx_packets;
+ u32 quality;
+
+ /* eeprom */
+ u8 eeprom[0x100]; /* 256 bytes of eeprom */
+ int eeprom_delay;
+
+ struct iw_statistics wstats;
+
+ struct workqueue_struct *workqueue;
+
+ struct work_struct adhoc_check;
+ struct work_struct associate;
+ struct work_struct disassociate;
+ struct work_struct rx_replenish;
+ struct work_struct request_scan;
+ struct work_struct adapter_restart;
+ struct work_struct rf_kill;
+ struct work_struct up;
+ struct work_struct down;
+ struct work_struct gather_stats;
+ struct work_struct abort_scan;
+ struct work_struct roam;
+ struct work_struct scan_check;
+
+ struct tasklet_struct irq_tasklet;
+
+#define IPW_2200BG 1
+#define IPW_2915ABG 2
+ u8 adapter;
+
+#define IPW_DEFAULT_TX_POWER 0x14
+ u8 tx_power;
+
+#ifdef CONFIG_PM
+ u32 pm_state[16];
+#endif
+
+ /* network state */
+
+ /* Used to pass the current INTA value from ISR to Tasklet */
+ u32 isr_inta;
+
+ /* debugging info */
+ u32 indirect_dword;
+ u32 direct_dword;
+ u32 indirect_byte;
+}; /*ipw_priv */
+
+/* debug macros */
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_DEBUG(level, fmt, args...) \
+do { if (ipw_debug_level & (level)) \
+ printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+#else
+#define IPW_DEBUG(level, fmt, args...) do {} while (0)
+#endif /* CONFIG_IPW_DEBUG */
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IPW_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IPW_xxxx_DEBUG() macro definition for your
+ * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw then you do not have
+ * CONFIG_IPW_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IPW_DL_ERROR (1<<0)
+#define IPW_DL_WARNING (1<<1)
+#define IPW_DL_INFO (1<<2)
+#define IPW_DL_WX (1<<3)
+#define IPW_DL_HOST_COMMAND (1<<5)
+#define IPW_DL_STATE (1<<6)
+
+#define IPW_DL_NOTIF (1<<10)
+#define IPW_DL_SCAN (1<<11)
+#define IPW_DL_ASSOC (1<<12)
+#define IPW_DL_DROP (1<<13)
+#define IPW_DL_IOCTL (1<<14)
+
+#define IPW_DL_MANAGE (1<<15)
+#define IPW_DL_FW (1<<16)
+#define IPW_DL_RF_KILL (1<<17)
+#define IPW_DL_FW_ERRORS (1<<18)
+
+#define IPW_DL_ORD (1<<20)
+
+#define IPW_DL_FRAG (1<<21)
+#define IPW_DL_WEP (1<<22)
+#define IPW_DL_TX (1<<23)
+#define IPW_DL_RX (1<<24)
+#define IPW_DL_ISR (1<<25)
+#define IPW_DL_FW_INFO (1<<26)
+#define IPW_DL_IO (1<<27)
+#define IPW_DL_TRACE (1<<28)
+
+#define IPW_DL_STATS (1<<29)
+
+#define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+#define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_INFO(f, a...) IPW_DEBUG(IPW_DL_INFO, f, ## a)
+
+#define IPW_DEBUG_WX(f, a...) IPW_DEBUG(IPW_DL_WX, f, ## a)
+#define IPW_DEBUG_SCAN(f, a...) IPW_DEBUG(IPW_DL_SCAN, f, ## a)
+#define IPW_DEBUG_STATUS(f, a...) IPW_DEBUG(IPW_DL_STATUS, f, ## a)
+#define IPW_DEBUG_TRACE(f, a...) IPW_DEBUG(IPW_DL_TRACE, f, ## a)
+#define IPW_DEBUG_RX(f, a...) IPW_DEBUG(IPW_DL_RX, f, ## a)
+#define IPW_DEBUG_TX(f, a...) IPW_DEBUG(IPW_DL_TX, f, ## a)
+#define IPW_DEBUG_ISR(f, a...) IPW_DEBUG(IPW_DL_ISR, f, ## a)
+#define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a)
+#define IPW_DEBUG_WEP(f, a...) IPW_DEBUG(IPW_DL_WEP, f, ## a)
+#define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a)
+#define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a)
+#define IPW_DEBUG_FW(f, a...) IPW_DEBUG(IPW_DL_FW, f, ## a)
+#define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a)
+#define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a)
+#define IPW_DEBUG_IO(f, a...) IPW_DEBUG(IPW_DL_IO, f, ## a)
+#define IPW_DEBUG_ORD(f, a...) IPW_DEBUG(IPW_DL_ORD, f, ## a)
+#define IPW_DEBUG_FW_INFO(f, a...) IPW_DEBUG(IPW_DL_FW_INFO, f, ## a)
+#define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a)
+#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a)
+
+#include <linux/ctype.h>
+
+/*
+* Register bit definitions
+*/
+
+/* Dino control registers bits */
+
+#define DINO_ENABLE_SYSTEM 0x80
+#define DINO_ENABLE_CS 0x40
+#define DINO_RXFIFO_DATA 0x01
+#define DINO_CONTROL_REG 0x00200000
+
+#define CX2_INTA_RW 0x00000008
+#define CX2_INTA_MASK_R 0x0000000C
+#define CX2_INDIRECT_ADDR 0x00000010
+#define CX2_INDIRECT_DATA 0x00000014
+#define CX2_AUTOINC_ADDR 0x00000018
+#define CX2_AUTOINC_DATA 0x0000001C
+#define CX2_RESET_REG 0x00000020
+#define CX2_GP_CNTRL_RW 0x00000024
+
+#define CX2_READ_INT_REGISTER 0xFF4
+
+#define CX2_GP_CNTRL_BIT_INIT_DONE 0x00000004
+
+#define CX2_REGISTER_DOMAIN1_END 0x00001000
+#define CX2_SRAM_READ_INT_REGISTER 0x00000ff4
+
+#define CX2_SHARED_LOWER_BOUND 0x00000200
+#define CX2_INTERRUPT_AREA_LOWER_BOUND 0x00000f80
+
+#define CX2_NIC_SRAM_LOWER_BOUND 0x00000000
+#define CX2_NIC_SRAM_UPPER_BOUND 0x00030000
+
+#define CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER (1 << 29)
+#define CX2_GP_CNTRL_BIT_CLOCK_READY 0x00000001
+#define CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY 0x00000002
+
+/*
+ * RESET Register Bit Indexes
+ */
+#define CBD_RESET_REG_PRINCETON_RESET 0x00000001 /* Bit 0 (LSB) */
+#define CX2_RESET_REG_SW_RESET 0x00000080 /* Bit 7 */
+#define CX2_RESET_REG_MASTER_DISABLED 0x00000100 /* Bit 8 */
+#define CX2_RESET_REG_STOP_MASTER 0x00000200 /* Bit 9 */
+#define CX2_ARC_KESHET_CONFIG 0x08000000 /* Bit 27 */
+#define CX2_START_STANDBY 0x00000004 /* Bit 2 */
+
+#define CX2_CSR_CIS_UPPER_BOUND 0x00000200
+#define CX2_DOMAIN_0_END 0x1000
+#define CLX_MEM_BAR_SIZE 0x1000
+
+#define CX2_BASEBAND_CONTROL_STATUS 0X00200000
+#define CX2_BASEBAND_TX_FIFO_WRITE 0X00200004
+#define CX2_BASEBAND_RX_FIFO_READ 0X00200004
+#define CX2_BASEBAND_CONTROL_STORE 0X00200010
+
+#define CX2_INTERNAL_CMD_EVENT 0X00300004
+#define CX2_BASEBAND_POWER_DOWN 0x00000001
+
+#define CX2_MEM_HALT_AND_RESET 0x003000e0
+
+/* defgroup bits_halt_reset MEM_HALT_AND_RESET register bits */
+#define CX2_BIT_HALT_RESET_ON 0x80000000
+#define CX2_BIT_HALT_RESET_OFF 0x00000000
+
+#define CB_LAST_VALID 0x20000000
+#define CB_INT_ENABLED 0x40000000
+#define CB_VALID 0x80000000
+#define CB_SRC_LE 0x08000000
+#define CB_DEST_LE 0x04000000
+#define CB_SRC_AUTOINC 0x00800000
+#define CB_SRC_IO_GATED 0x00400000
+#define CB_DEST_AUTOINC 0x00080000
+#define CB_SRC_SIZE_LONG 0x00200000
+#define CB_DEST_SIZE_LONG 0x00020000
+
+/* DMA DEFINES */
+
+#define DMA_CONTROL_SMALL_CB_CONST_VALUE 0x00540000
+#define DMA_CB_STOP_AND_ABORT 0x00000C00
+#define DMA_CB_START 0x00000100
+
+#define CX2_SHARED_SRAM_SIZE 0x00030000
+#define CX2_SHARED_SRAM_DMA_CONTROL 0x00027000
+#define CB_MAX_LENGTH 0x1FFF
+
+#define CX2_HOST_EEPROM_DATA_SRAM_SIZE 0xA18
+#define CX2_EEPROM_IMAGE_SIZE 0x100
+
+/* DMA defs */
+#define CX2_DMA_I_CURRENT_CB 0x003000D0
+#define CX2_DMA_O_CURRENT_CB 0x003000D4
+#define CX2_DMA_I_DMA_CONTROL 0x003000A4
+#define CX2_DMA_I_CB_BASE 0x003000A0
+
+#define CX2_TX_CMD_QUEUE_BD_BASE (0x00000200)
+#define CX2_TX_CMD_QUEUE_BD_SIZE (0x00000204)
+#define CX2_TX_QUEUE_0_BD_BASE (0x00000208)
+#define CX2_TX_QUEUE_0_BD_SIZE (0x0000020C)
+#define CX2_TX_QUEUE_1_BD_BASE (0x00000210)
+#define CX2_TX_QUEUE_1_BD_SIZE (0x00000214)
+#define CX2_TX_QUEUE_2_BD_BASE (0x00000218)
+#define CX2_TX_QUEUE_2_BD_SIZE (0x0000021C)
+#define CX2_TX_QUEUE_3_BD_BASE (0x00000220)
+#define CX2_TX_QUEUE_3_BD_SIZE (0x00000224)
+#define CX2_RX_BD_BASE (0x00000240)
+#define CX2_RX_BD_SIZE (0x00000244)
+#define CX2_RFDS_TABLE_LOWER (0x00000500)
+
+#define CX2_TX_CMD_QUEUE_READ_INDEX (0x00000280)
+#define CX2_TX_QUEUE_0_READ_INDEX (0x00000284)
+#define CX2_TX_QUEUE_1_READ_INDEX (0x00000288)
+#define CX2_TX_QUEUE_2_READ_INDEX (0x0000028C)
+#define CX2_TX_QUEUE_3_READ_INDEX (0x00000290)
+#define CX2_RX_READ_INDEX (0x000002A0)
+
+#define CX2_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80)
+#define CX2_TX_QUEUE_0_WRITE_INDEX (0x00000F84)
+#define CX2_TX_QUEUE_1_WRITE_INDEX (0x00000F88)
+#define CX2_TX_QUEUE_2_WRITE_INDEX (0x00000F8C)
+#define CX2_TX_QUEUE_3_WRITE_INDEX (0x00000F90)
+#define CX2_RX_WRITE_INDEX (0x00000FA0)
+
+/*
+ * EEPROM Related Definitions
+ */
+
+#define IPW_EEPROM_DATA_SRAM_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x814)
+#define IPW_EEPROM_DATA_SRAM_SIZE (CX2_SHARED_LOWER_BOUND + 0x818)
+#define IPW_EEPROM_LOAD_DISABLE (CX2_SHARED_LOWER_BOUND + 0x81C)
+#define IPW_EEPROM_DATA (CX2_SHARED_LOWER_BOUND + 0x820)
+#define IPW_EEPROM_UPPER_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x9E0)
+
+#define IPW_STATION_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0xA0C)
+#define IPW_STATION_TABLE_UPPER (CX2_SHARED_LOWER_BOUND + 0xB0C)
+#define IPW_REQUEST_ATIM (CX2_SHARED_LOWER_BOUND + 0xB0C)
+#define IPW_ATIM_SENT (CX2_SHARED_LOWER_BOUND + 0xB10)
+#define IPW_WHO_IS_AWAKE (CX2_SHARED_LOWER_BOUND + 0xB14)
+#define IPW_DURING_ATIM_WINDOW (CX2_SHARED_LOWER_BOUND + 0xB18)
+
+#define MSB 1
+#define LSB 0
+#define WORD_TO_BYTE(_word) ((_word) * sizeof(u16))
+
+#define GET_EEPROM_ADDR(_wordoffset,_byteoffset) \
+ ( WORD_TO_BYTE(_wordoffset) + (_byteoffset) )
+
+/* EEPROM access by BYTE */
+#define EEPROM_PME_CAPABILITY (GET_EEPROM_ADDR(0x09,MSB)) /* 1 byte */
+#define EEPROM_MAC_ADDRESS (GET_EEPROM_ADDR(0x21,LSB)) /* 6 byte */
+#define EEPROM_VERSION (GET_EEPROM_ADDR(0x24,MSB)) /* 1 byte */
+#define EEPROM_NIC_TYPE (GET_EEPROM_ADDR(0x25,LSB)) /* 1 byte */
+#define EEPROM_SKU_CAPABILITY (GET_EEPROM_ADDR(0x25,MSB)) /* 1 byte */
+#define EEPROM_COUNTRY_CODE (GET_EEPROM_ADDR(0x26,LSB)) /* 3 bytes */
+#define EEPROM_IBSS_CHANNELS_BG (GET_EEPROM_ADDR(0x28,LSB)) /* 2 bytes */
+#define EEPROM_IBSS_CHANNELS_A (GET_EEPROM_ADDR(0x29,MSB)) /* 5 bytes */
+#define EEPROM_BSS_CHANNELS_BG (GET_EEPROM_ADDR(0x2c,LSB)) /* 2 bytes */
+#define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */
+
+/* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/
+#define EEPROM_NIC_TYPE_STANDARD 0
+#define EEPROM_NIC_TYPE_DELL 1
+#define EEPROM_NIC_TYPE_FUJITSU 2
+#define EEPROM_NIC_TYPE_IBM 3
+#define EEPROM_NIC_TYPE_HP 4
+
+#define FW_MEM_REG_LOWER_BOUND 0x00300000
+#define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40)
+
+#define EEPROM_BIT_SK (1<<0)
+#define EEPROM_BIT_CS (1<<1)
+#define EEPROM_BIT_DI (1<<2)
+#define EEPROM_BIT_DO (1<<4)
+
+#define EEPROM_CMD_READ 0x2
+
+/* Interrupts masks */
+#define CX2_INTA_NONE 0x00000000
+
+#define CX2_INTA_BIT_RX_TRANSFER 0x00000002
+#define CX2_INTA_BIT_STATUS_CHANGE 0x00000010
+#define CX2_INTA_BIT_BEACON_PERIOD_EXPIRED 0x00000020
+
+//Inta Bits for CF
+#define CX2_INTA_BIT_TX_CMD_QUEUE 0x00000800
+#define CX2_INTA_BIT_TX_QUEUE_1 0x00001000
+#define CX2_INTA_BIT_TX_QUEUE_2 0x00002000
+#define CX2_INTA_BIT_TX_QUEUE_3 0x00004000
+#define CX2_INTA_BIT_TX_QUEUE_4 0x00008000
+
+#define CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE 0x00010000
+
+#define CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN 0x00100000
+#define CX2_INTA_BIT_POWER_DOWN 0x00200000
+
+#define CX2_INTA_BIT_FW_INITIALIZATION_DONE 0x01000000
+#define CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE 0x02000000
+#define CX2_INTA_BIT_RF_KILL_DONE 0x04000000
+#define CX2_INTA_BIT_FATAL_ERROR 0x40000000
+#define CX2_INTA_BIT_PARITY_ERROR 0x80000000
+
+/* Interrupts enabled at init time. */
+#define CX2_INTA_MASK_ALL \
+ (CX2_INTA_BIT_TX_QUEUE_1 | \
+ CX2_INTA_BIT_TX_QUEUE_2 | \
+ CX2_INTA_BIT_TX_QUEUE_3 | \
+ CX2_INTA_BIT_TX_QUEUE_4 | \
+ CX2_INTA_BIT_TX_CMD_QUEUE | \
+ CX2_INTA_BIT_RX_TRANSFER | \
+ CX2_INTA_BIT_FATAL_ERROR | \
+ CX2_INTA_BIT_PARITY_ERROR | \
+ CX2_INTA_BIT_STATUS_CHANGE | \
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE | \
+ CX2_INTA_BIT_BEACON_PERIOD_EXPIRED | \
+ CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE | \
+ CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN | \
+ CX2_INTA_BIT_POWER_DOWN | \
+ CX2_INTA_BIT_RF_KILL_DONE )
+
+#define IPWSTATUS_ERROR_LOG (CX2_SHARED_LOWER_BOUND + 0x410)
+#define IPW_EVENT_LOG (CX2_SHARED_LOWER_BOUND + 0x414)
+
+/* FW event log definitions */
+#define EVENT_ELEM_SIZE (3 * sizeof(u32))
+#define EVENT_START_OFFSET (1 * sizeof(u32) + 2 * sizeof(u16))
+
+/* FW error log definitions */
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+
+enum {
+ IPW_FW_ERROR_OK = 0,
+ IPW_FW_ERROR_FAIL,
+ IPW_FW_ERROR_MEMORY_UNDERFLOW,
+ IPW_FW_ERROR_MEMORY_OVERFLOW,
+ IPW_FW_ERROR_BAD_PARAM,
+ IPW_FW_ERROR_BAD_CHECKSUM,
+ IPW_FW_ERROR_NMI_INTERRUPT,
+ IPW_FW_ERROR_BAD_DATABASE,
+ IPW_FW_ERROR_ALLOC_FAIL,
+ IPW_FW_ERROR_DMA_UNDERRUN,
+ IPW_FW_ERROR_DMA_STATUS,
+ IPW_FW_ERROR_DINOSTATUS_ERROR,
+ IPW_FW_ERROR_EEPROMSTATUS_ERROR,
+ IPW_FW_ERROR_SYSASSERT,
+ IPW_FW_ERROR_FATAL_ERROR
+};
+
+#define AUTH_OPEN 0
+#define AUTH_SHARED_KEY 1
+#define AUTH_IGNORE 3
+
+#define HC_ASSOCIATE 0
+#define HC_REASSOCIATE 1
+#define HC_DISASSOCIATE 2
+#define HC_IBSS_START 3
+#define HC_IBSS_RECONF 4
+#define HC_DISASSOC_QUIET 5
+
+#define IPW_RATE_CAPABILITIES 1
+#define IPW_RATE_CONNECT 0
+
+/*
+ * Rate values and masks
+ */
+#define IPW_TX_RATE_1MB 0x0A
+#define IPW_TX_RATE_2MB 0x14
+#define IPW_TX_RATE_5MB 0x37
+#define IPW_TX_RATE_6MB 0x0D
+#define IPW_TX_RATE_9MB 0x0F
+#define IPW_TX_RATE_11MB 0x6E
+#define IPW_TX_RATE_12MB 0x05
+#define IPW_TX_RATE_18MB 0x07
+#define IPW_TX_RATE_24MB 0x09
+#define IPW_TX_RATE_36MB 0x0B
+#define IPW_TX_RATE_48MB 0x01
+#define IPW_TX_RATE_54MB 0x03
+
+#define IPW_ORD_TABLE_ID_MASK 0x0000FF00
+#define IPW_ORD_TABLE_VALUE_MASK 0x000000FF
+
+#define IPW_ORD_TABLE_0_MASK 0x0000F000
+#define IPW_ORD_TABLE_1_MASK 0x0000F100
+#define IPW_ORD_TABLE_2_MASK 0x0000F200
+#define IPW_ORD_TABLE_3_MASK 0x0000F300
+#define IPW_ORD_TABLE_4_MASK 0x0000F400
+#define IPW_ORD_TABLE_5_MASK 0x0000F500
+#define IPW_ORD_TABLE_6_MASK 0x0000F600
+#define IPW_ORD_TABLE_7_MASK 0x0000F700
+
+/*
+ * Table 0 Entries (all entries are 32 bits)
+ */
+enum {
+ IPW_ORD_STAT_TX_CURR_RATE = IPW_ORD_TABLE_0_MASK + 1,
+ IPW_ORD_STAT_FRAG_TRESHOLD,
+ IPW_ORD_STAT_RTS_THRESHOLD,
+ IPW_ORD_STAT_TX_HOST_REQUESTS,
+ IPW_ORD_STAT_TX_HOST_COMPLETE,
+ IPW_ORD_STAT_TX_DIR_DATA,
+ IPW_ORD_STAT_TX_DIR_DATA_B_1,
+ IPW_ORD_STAT_TX_DIR_DATA_B_2,
+ IPW_ORD_STAT_TX_DIR_DATA_B_5_5,
+ IPW_ORD_STAT_TX_DIR_DATA_B_11,
+ /* Hole */
+
+ IPW_ORD_STAT_TX_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 19,
+ IPW_ORD_STAT_TX_DIR_DATA_G_2,
+ IPW_ORD_STAT_TX_DIR_DATA_G_5_5,
+ IPW_ORD_STAT_TX_DIR_DATA_G_6,
+ IPW_ORD_STAT_TX_DIR_DATA_G_9,
+ IPW_ORD_STAT_TX_DIR_DATA_G_11,
+ IPW_ORD_STAT_TX_DIR_DATA_G_12,
+ IPW_ORD_STAT_TX_DIR_DATA_G_18,
+ IPW_ORD_STAT_TX_DIR_DATA_G_24,
+ IPW_ORD_STAT_TX_DIR_DATA_G_36,
+ IPW_ORD_STAT_TX_DIR_DATA_G_48,
+ IPW_ORD_STAT_TX_DIR_DATA_G_54,
+ IPW_ORD_STAT_TX_NON_DIR_DATA,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_1,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_2,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_5_5,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_11,
+ /* Hole */
+
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 44,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_2,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_5_5,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_6,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_9,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_11,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_12,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_18,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_24,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_36,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_48,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_54,
+ IPW_ORD_STAT_TX_RETRY,
+ IPW_ORD_STAT_TX_FAILURE,
+ IPW_ORD_STAT_RX_ERR_CRC,
+ IPW_ORD_STAT_RX_ERR_ICV,
+ IPW_ORD_STAT_RX_NO_BUFFER,
+ IPW_ORD_STAT_FULL_SCANS,
+ IPW_ORD_STAT_PARTIAL_SCANS,
+ IPW_ORD_STAT_TGH_ABORTED_SCANS,
+ IPW_ORD_STAT_TX_TOTAL_BYTES,
+ IPW_ORD_STAT_CURR_RSSI_RAW,
+ IPW_ORD_STAT_RX_BEACON,
+ IPW_ORD_STAT_MISSED_BEACONS,
+ IPW_ORD_TABLE_0_LAST
+};
+
+#define IPW_RSSI_TO_DBM 112
+
+/* Table 1 Entries
+ */
+enum {
+ IPW_ORD_TABLE_1_LAST = IPW_ORD_TABLE_1_MASK | 1,
+};
+
+/*
+ * Table 2 Entries
+ *
+ * FW_VERSION: 16 byte string
+ * FW_DATE: 16 byte string (only 14 bytes used)
+ * UCODE_VERSION: 4 byte version code
+ * UCODE_DATE: 5 bytes code code
+ * ADDAPTER_MAC: 6 byte MAC address
+ * RTC: 4 byte clock
+ */
+enum {
+ IPW_ORD_STAT_FW_VERSION = IPW_ORD_TABLE_2_MASK | 1,
+ IPW_ORD_STAT_FW_DATE,
+ IPW_ORD_STAT_UCODE_VERSION,
+ IPW_ORD_STAT_UCODE_DATE,
+ IPW_ORD_STAT_ADAPTER_MAC,
+ IPW_ORD_STAT_RTC,
+ IPW_ORD_TABLE_2_LAST
+};
+
+/* Table 3 */
+enum {
+ IPW_ORD_STAT_TX_PACKET = IPW_ORD_TABLE_3_MASK | 0,
+ IPW_ORD_STAT_TX_PACKET_FAILURE,
+ IPW_ORD_STAT_TX_PACKET_SUCCESS,
+ IPW_ORD_STAT_TX_PACKET_ABORTED,
+ IPW_ORD_TABLE_3_LAST
+};
+
+/* Table 4 */
+enum {
+ IPW_ORD_TABLE_4_LAST = IPW_ORD_TABLE_4_MASK
+};
+
+/* Table 5 */
+enum {
+ IPW_ORD_STAT_AVAILABLE_AP_COUNT = IPW_ORD_TABLE_5_MASK,
+ IPW_ORD_STAT_AP_ASSNS,
+ IPW_ORD_STAT_ROAM,
+ IPW_ORD_STAT_ROAM_CAUSE_MISSED_BEACONS,
+ IPW_ORD_STAT_ROAM_CAUSE_UNASSOC,
+ IPW_ORD_STAT_ROAM_CAUSE_RSSI,
+ IPW_ORD_STAT_ROAM_CAUSE_LINK_QUALITY,
+ IPW_ORD_STAT_ROAM_CAUSE_AP_LOAD_BALANCE,
+ IPW_ORD_STAT_ROAM_CAUSE_AP_NO_TX,
+ IPW_ORD_STAT_LINK_UP,
+ IPW_ORD_STAT_LINK_DOWN,
+ IPW_ORD_ANTENNA_DIVERSITY,
+ IPW_ORD_CURR_FREQ,
+ IPW_ORD_TABLE_5_LAST
+};
+
+/* Table 6 */
+enum {
+ IPW_ORD_COUNTRY_CODE = IPW_ORD_TABLE_6_MASK,
+ IPW_ORD_CURR_BSSID,
+ IPW_ORD_CURR_SSID,
+ IPW_ORD_TABLE_6_LAST
+};
+
+/* Table 7 */
+enum {
+ IPW_ORD_STAT_PERCENT_MISSED_BEACONS = IPW_ORD_TABLE_7_MASK,
+ IPW_ORD_STAT_PERCENT_TX_RETRIES,
+ IPW_ORD_STAT_PERCENT_LINK_QUALITY,
+ IPW_ORD_STAT_CURR_RSSI_DBM,
+ IPW_ORD_TABLE_7_LAST
+};
+
+#define IPW_ORDINALS_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0x500)
+#define IPW_ORDINALS_TABLE_0 (CX2_SHARED_LOWER_BOUND + 0x180)
+#define IPW_ORDINALS_TABLE_1 (CX2_SHARED_LOWER_BOUND + 0x184)
+#define IPW_ORDINALS_TABLE_2 (CX2_SHARED_LOWER_BOUND + 0x188)
+#define IPW_MEM_FIXED_OVERRIDE (CX2_SHARED_LOWER_BOUND + 0x41C)
+
+struct ipw_fixed_rate {
+ u16 tx_rates;
+ u16 reserved;
+} __attribute__ ((packed));
+
+#define CX2_INDIRECT_ADDR_MASK (~0x3ul)
+
+struct host_cmd {
+ u8 cmd;
+ u8 len;
+ u16 reserved;
+ u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+} __attribute__ ((packed));
+
+#define CFG_BT_COEXISTENCE_MIN 0x00
+#define CFG_BT_COEXISTENCE_DEFER 0x02
+#define CFG_BT_COEXISTENCE_KILL 0x04
+#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08
+#define CFG_BT_COEXISTENCE_OOB 0x10
+#define CFG_BT_COEXISTENCE_MAX 0xFF
+#define CFG_BT_COEXISTENCE_DEF 0x80 /* read Bt from EEPROM */
+
+#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x0
+#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x1
+#define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN
+
+#define CFG_SYS_ANTENNA_BOTH 0x000
+#define CFG_SYS_ANTENNA_A 0x001
+#define CFG_SYS_ANTENNA_B 0x003
+
+/*
+ * The definitions below were lifted off the ipw2100 driver, which only
+ * supports 'b' mode, so I'm sure these are not exactly correct.
+ *
+ * Somebody fix these!!
+ */
+#define REG_MIN_CHANNEL 0
+#define REG_MAX_CHANNEL 14
+
+#define REG_CHANNEL_MASK 0x00003FFF
+#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff
+
+static const long ipw_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT ARRAY_SIZE(ipw_frequencies)
+
+#define IPW_MAX_CONFIG_RETRIES 10
+
+static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
+{
+ u32 retval;
+ u16 fc;
+
+ retval = sizeof(struct ieee80211_hdr);
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /*
+ * Function ToDS FromDS
+ * IBSS 0 0
+ * To AP 1 0
+ * From AP 0 1
+ * WDS (bridge) 1 1
+ *
+ * Only WDS frames use Address4 among them. --YZ
+ */
+ if (!(fc & IEEE80211_FCTL_TODS) || !(fc & IEEE80211_FCTL_FROMDS))
+ retval -= ETH_ALEN;
+
+ return retval;
+}
+
+#endif /* __ipw2200_h__ */
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 5f507c49907b..ca6c03c89926 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -471,12 +471,12 @@ static dev_link_t *netwave_attach(void)
dev->get_stats = &netwave_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* wireless extensions */
-#ifdef WIRELESS_EXT
+#if WIRELESS_EXT <= 16
dev->get_wireless_stats = &netwave_get_wireless_stats;
+#endif /* WIRELESS_EXT <= 16 */
#if WIRELESS_EXT > 12
dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
#endif /* WIRELESS_EXT > 12 */
-#endif /* WIRELESS_EXT */
dev->do_ioctl = &netwave_ioctl;
dev->tx_timeout = &netwave_watchdog;
@@ -839,6 +839,9 @@ static const struct iw_handler_def netwave_handler_def =
.standard = (iw_handler *) netwave_handler,
.private = (iw_handler *) netwave_private_handler,
.private_args = (struct iw_priv_args *) netwave_private_args,
+#if WIRELESS_EXT > 16
+ .get_wireless_stats = netwave_get_wireless_stats,
+#endif /* WIRELESS_EXT > 16 */
};
#endif /* WIRELESS_EXT > 12 */
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index aabcdc2be05e..8de49fe57233 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -94,6 +94,8 @@
#include <net/iw_handler.h>
#include <net/ieee80211.h>
+#include <net/ieee80211.h>
+
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -101,7 +103,6 @@
#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
-#include "ieee802_11.h"
/********************************************************************/
/* Module information */
@@ -150,7 +151,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
#define ORINOCO_MIN_MTU 256
-#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
+#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
#define SYMBOL_MAX_VER_LEN (14)
#define USER_BAP 0
@@ -442,7 +443,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
return -EINVAL;
- if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
+ if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
(priv->nicbuf_size - ETH_HLEN) )
return -EINVAL;
@@ -918,7 +919,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
data. */
return;
}
- if (length > IEEE802_11_DATA_LEN) {
+ if (length > IEEE80211_DATA_LEN) {
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
dev->name, length);
stats->rx_length_errors++;
@@ -1052,8 +1053,9 @@ static void orinoco_join_ap(struct net_device *dev)
u16 channel;
} __attribute__ ((packed)) req;
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
- struct prism2_scan_apinfo *atom;
+ struct prism2_scan_apinfo *atom = NULL;
int offset = 4;
+ int found = 0;
u8 *buf;
u16 len;
@@ -1088,15 +1090,18 @@ static void orinoco_join_ap(struct net_device *dev)
* we were requested to join */
for (; offset + atom_len <= len; offset += atom_len) {
atom = (struct prism2_scan_apinfo *) (buf + offset);
- if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
- goto found;
+ if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
+ found = 1;
+ break;
+ }
}
- DEBUG(1, "%s: Requested AP not found in scan results\n",
- dev->name);
- goto out;
+ if (! found) {
+ DEBUG(1, "%s: Requested AP not found in scan results\n",
+ dev->name);
+ goto out;
+ }
- found:
memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
req.channel = atom->channel; /* both are little-endian */
err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
@@ -1283,8 +1288,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
/* Read scan data */
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
infofid, sizeof(info));
- if (err)
+ if (err) {
+ kfree(buf);
break;
+ }
#ifdef ORINOCO_DEBUG
{
@@ -2272,7 +2279,7 @@ static int orinoco_init(struct net_device *dev)
/* No need to lock, the hw_unavailable flag is already set in
* alloc_orinocodev() */
- priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
+ priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
/* Initialize the firmware */
err = orinoco_reinit_firmware(dev);
@@ -4020,7 +4027,8 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
}
/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
+ * format that the Wireless Tools will understand - Jean II
+ * Return message length or -errno for fatal errors */
static inline int orinoco_translate_scan(struct net_device *dev,
char *buffer,
char *scan,
@@ -4060,13 +4068,19 @@ static inline int orinoco_translate_scan(struct net_device *dev,
break;
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
- if (priv->has_hostscan)
- atom_len = scan[0] + (scan[1] << 8);
- else
+ if (priv->has_hostscan) {
+ atom_len = le16_to_cpup((u16 *)scan);
+ /* Sanity check for atom_len */
+ if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+ printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
+ dev->name, atom_len);
+ return -EIO;
+ }
+ } else
atom_len = offsetof(struct prism2_scan_apinfo, atim);
break;
default:
- return 0;
+ return -EOPNOTSUPP;
}
/* Check that we got an whole number of atoms */
@@ -4074,7 +4088,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
printk(KERN_ERR "%s: Unexpected scan data length %d, "
"atom_len %d, offset %d\n", dev->name, scan_len,
atom_len, offset);
- return 0;
+ return -EIO;
}
/* Read the entries one by one */
@@ -4209,33 +4223,41 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
/* We have some results to push back to user space */
/* Translate to WE format */
- srq->length = orinoco_translate_scan(dev, extra,
- priv->scan_result,
- priv->scan_len);
-
- /* Return flags */
- srq->flags = (__u16) priv->scan_mode;
+ int ret = orinoco_translate_scan(dev, extra,
+ priv->scan_result,
+ priv->scan_len);
+
+ if (ret < 0) {
+ err = ret;
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
+ } else {
+ srq->length = ret;
- /* Results are here, so scan no longer in progress */
- priv->scan_inprogress = 0;
+ /* Return flags */
+ srq->flags = (__u16) priv->scan_mode;
- /* In any case, Scan results will be cleaned up in the
- * reset function and when exiting the driver.
- * The person triggering the scanning may never come to
- * pick the results, so we need to do it in those places.
- * Jean II */
+ /* In any case, Scan results will be cleaned up in the
+ * reset function and when exiting the driver.
+ * The person triggering the scanning may never come to
+ * pick the results, so we need to do it in those places.
+ * Jean II */
#ifdef SCAN_SINGLE_READ
- /* If you enable this option, only one client (the first
- * one) will be able to read the result (and only one
- * time). If there is multiple concurent clients that
- * want to read scan results, this behavior is not
- * advisable - Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
+ /* If you enable this option, only one client (the first
+ * one) will be able to read the result (and only one
+ * time). If there is multiple concurent clients that
+ * want to read scan results, this behavior is not
+ * advisable - Jean II */
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
#endif /* SCAN_SINGLE_READ */
- /* Here, if too much time has elapsed since last scan,
- * we may want to clean up scan results... - Jean II */
+ /* Here, if too much time has elapsed since last scan,
+ * we may want to clean up scan results... - Jean II */
+ }
+
+ /* Scan is no longer in progress */
+ priv->scan_inprogress = 0;
}
orinoco_unlock(priv, &flags);
@@ -4322,36 +4344,36 @@ static const struct iw_priv_args orinoco_privtab[] = {
*/
static const iw_handler orinoco_handler[] = {
- [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
- [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
- [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
- [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
- [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
- [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
- [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
- [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
- [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
- [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
- [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
- [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap,
- [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
- [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan,
- [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan,
- [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
- [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
- [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
- [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
- [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
- [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
- [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
- [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
- [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
- [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
- [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
- [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
- [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
- [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
- [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
+ [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_commit,
+ [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getname,
+ [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfreq,
+ [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfreq,
+ [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setmode,
+ [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getmode,
+ [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
+ [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
+ [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
+ [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
+ [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
+ [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
+ [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
+ [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
+ [SIOCGIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getscan,
+ [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setessid,
+ [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getessid,
+ [SIOCSIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setnick,
+ [SIOCGIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getnick,
+ [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrate,
+ [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrate,
+ [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrts,
+ [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrts,
+ [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfrag,
+ [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfrag,
+ [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getretry,
+ [SIOCSIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setiwencode,
+ [SIOCGIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwencode,
+ [SIOCSIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setpower,
+ [SIOCGIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getpower,
};
@@ -4359,15 +4381,15 @@ static const iw_handler orinoco_handler[] = {
Added typecasting since we no longer use iwreq_data -- Moustafa
*/
static const iw_handler orinoco_private_handler[] = {
- [0] (iw_handler) orinoco_ioctl_reset,
- [1] (iw_handler) orinoco_ioctl_reset,
- [2] (iw_handler) orinoco_ioctl_setport3,
- [3] (iw_handler) orinoco_ioctl_getport3,
- [4] (iw_handler) orinoco_ioctl_setpreamble,
- [5] (iw_handler) orinoco_ioctl_getpreamble,
- [6] (iw_handler) orinoco_ioctl_setibssport,
- [7] (iw_handler) orinoco_ioctl_getibssport,
- [9] (iw_handler) orinoco_ioctl_getrid,
+ [0] = (iw_handler) orinoco_ioctl_reset,
+ [1] = (iw_handler) orinoco_ioctl_reset,
+ [2] = (iw_handler) orinoco_ioctl_setport3,
+ [3] = (iw_handler) orinoco_ioctl_getport3,
+ [4] = (iw_handler) orinoco_ioctl_setpreamble,
+ [5] = (iw_handler) orinoco_ioctl_getpreamble,
+ [6] = (iw_handler) orinoco_ioctl_setibssport,
+ [7] = (iw_handler) orinoco_ioctl_getibssport,
+ [9] = (iw_handler) orinoco_ioctl_getrid,
};
static const struct iw_handler_def orinoco_handler_def = {
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1cc1492083c9..bedd7f9f23e4 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -604,7 +604,6 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
@@ -630,6 +629,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
new file mode 100644
index 000000000000..86fa58e5cfac
--- /dev/null
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -0,0 +1,324 @@
+/* orinoco_nortel.c
+ *
+ * Driver for Prism II devices which would usually be driven by orinoco_cs,
+ * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter.
+ *
+ * Copyright (C) 2002 Tobias Hoffmann
+ * (C) 2003 Christoph Jungegger <disdos@traum404.de>
+ *
+ * Some of this code is borrowed from orinoco_plx.c
+ * Copyright (C) 2001 Daniel Barlow
+ * Some of this code is borrowed from orinoco_pci.c
+ * Copyright (C) 2001 Jean Tourrilhes
+ * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
+ * has been copied from it. linux-wlan-ng-0.1.10 is originally :
+ * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#define DRIVER_NAME "orinoco_nortel"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/fcntl.h>
+
+#include <pcmcia/cisreg.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+
+
+/* Nortel specific data */
+struct nortel_pci_card {
+ unsigned long iobase1;
+ unsigned long iobase2;
+};
+
+/*
+ * Do a soft reset of the PCI card using the Configuration Option Register
+ * We need this to get going...
+ * This is the part of the code that is strongly inspired from wlan-ng
+ *
+ * Note bis : Don't try to access HERMES_CMD during the reset phase.
+ * It just won't work !
+ */
+static int nortel_pci_cor_reset(struct orinoco_private *priv)
+{
+ struct nortel_pci_card *card = priv->card;
+
+ /* Assert the reset until the card notice */
+ outw_p(8, card->iobase1 + 2);
+ inw(card->iobase2 + COR_OFFSET);
+ outw_p(0x80, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* Give time for the card to recover from this hard effort */
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* set COR as usual */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ outw_p(0x228, card->iobase1 + 2);
+
+ return 0;
+}
+
+int nortel_pci_hw_init(struct nortel_pci_card *card)
+{
+ int i;
+ u32 reg;
+
+ /* setup bridge */
+ if (inw(card->iobase1) & 1) {
+ printk(KERN_ERR PFX "brg1 answer1 wrong\n");
+ return -EBUSY;
+ }
+ outw_p(0x118, card->iobase1 + 2);
+ outw_p(0x108, card->iobase1 + 2);
+ mdelay(30);
+ outw_p(0x8, card->iobase1 + 2);
+ for (i = 0; i < 30; i++) {
+ mdelay(30);
+ if (inw(card->iobase1) & 0x10) {
+ break;
+ }
+ }
+ if (i == 30) {
+ printk(KERN_ERR PFX "brg1 timed out\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe0) & 1) {
+ printk(KERN_ERR PFX "brg2 answer1 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe2) & 1) {
+ printk(KERN_ERR PFX "brg2 answer2 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe4) & 1) {
+ printk(KERN_ERR PFX "brg2 answer3 wrong\n");
+ return -EBUSY;
+ }
+
+ /* set the PCMCIA COR-Register */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+ reg = inw(card->iobase2 + COR_OFFSET);
+ if (reg != COR_VALUE) {
+ printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
+ reg);
+ return -EBUSY;
+ }
+
+ /* set leds */
+ outw_p(1, card->iobase1 + 10);
+ return 0;
+}
+
+static int nortel_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int err;
+ struct orinoco_private *priv;
+ struct nortel_pci_card *card;
+ struct net_device *dev;
+ void __iomem *iomem;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
+ }
+
+ iomem = pci_iomap(pdev, 3, 0);
+ if (!iomem) {
+ err = -ENOMEM;
+ goto fail_map_io;
+ }
+
+ /* Allocate network device */
+ dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+ if (!dev) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
+ err = -ENOMEM;
+ goto fail_alloc;
+ }
+
+ priv = netdev_priv(dev);
+ card = priv->card;
+ card->iobase1 = pci_resource_start(pdev, 0);
+ card->iobase2 = pci_resource_start(pdev, 1);
+ dev->base_addr = pci_resource_start(pdev, 2);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
+
+ printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
+ "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+
+ err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
+ err = -EBUSY;
+ goto fail_irq;
+ }
+ dev->irq = pdev->irq;
+
+ err = nortel_pci_hw_init(card);
+ if (err) {
+ printk(KERN_ERR PFX "Hardware initialization failed\n");
+ goto fail;
+ }
+
+ err = nortel_pci_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
+ goto fail;
+ }
+
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register network device\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ return 0;
+
+ fail:
+ free_irq(pdev->irq, dev);
+
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+
+ fail_alloc:
+ pci_iounmap(pdev, iomem);
+
+ fail_map_io:
+ pci_release_regions(pdev);
+
+ fail_resources:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct nortel_pci_card *card = priv->card;
+
+ /* clear leds */
+ outw_p(0, card->iobase1 + 10);
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+ pci_iounmap(pdev, priv->hw.iobase);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+
+static struct pci_device_id nortel_pci_id_table[] = {
+ /* Nortel emobility PCI */
+ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+
+static struct pci_driver nortel_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = nortel_pci_id_table,
+ .probe = nortel_pci_init_one,
+ .remove = __devexit_p(nortel_pci_remove_one),
+};
+
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
+MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
+MODULE_DESCRIPTION
+ ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_LICENSE("Dual MPL/GPL");
+
+static int __init nortel_pci_init(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+ return pci_module_init(&nortel_pci_driver);
+}
+
+static void __exit nortel_pci_exit(void)
+{
+ pci_unregister_driver(&nortel_pci_driver);
+ ssleep(1);
+}
+
+module_init(nortel_pci_init);
+module_exit(nortel_pci_exit);
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 7a6f52ea7faa..42e03438291b 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -301,8 +301,6 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
unsigned long flags;
int err;
- printk(KERN_DEBUG "%s: Orinoco-PCI entering sleep mode (state=%d)\n",
- dev->name, state);
err = orinoco_lock(priv, &flags);
if (err) {
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 0f29a9c7bc2c..9a8790e3580c 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -2727,6 +2727,9 @@ const struct iw_handler_def prism54_handler_def = {
.standard = (iw_handler *) prism54_handler,
.private = (iw_handler *) prism54_private_handler,
.private_args = (struct iw_priv_args *) prism54_private_args,
+#if WIRELESS_EXT > 16
+ .get_wireless_stats = prism54_get_wireless_stats,
+#endif /* WIRELESS_EXT > 16 */
#if WIRELESS_EXT == 16
.spy_offset = offsetof(islpci_private, spy_data),
#endif /* WIRELESS_EXT == 16 */
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index efab07e9e24e..6f13d4a8e2d3 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -815,7 +815,6 @@ islpci_setup(struct pci_dev *pdev)
ndev->open = &islpci_open;
ndev->stop = &islpci_close;
ndev->get_stats = &islpci_statistics;
- ndev->get_wireless_stats = &prism54_get_wireless_stats;
ndev->do_ioctl = &prism54_ioctl;
ndev->wireless_handlers =
(struct iw_handler_def *) &prism54_handler_def;
@@ -844,6 +843,8 @@ islpci_setup(struct pci_dev *pdev)
/* Add pointers to enable iwspy support. */
priv->wireless_data.spy_data = &priv->spy_data;
ndev->wireless_data = &priv->wireless_data;
+#else /* WIRELESS_EXT > 16 */
+ ndev->get_wireless_stats = &prism54_get_wireless_stats;
#endif /* WIRELESS_EXT > 16 */
/* save the start and end address of the PCI memory area */
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index c17391d947f3..dc040caab7d7 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -267,8 +267,6 @@ prism54_suspend(struct pci_dev *pdev, pm_message_t state)
islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
BUG_ON(!priv);
- printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
- ndev->name, state);
pci_save_state(pdev);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 0e0ba614259a..e9c5ea0f5535 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -53,6 +53,7 @@
#include <pcmcia/ds.h>
#include <pcmcia/mem_op.h>
+#include <net/ieee80211.h>
#include <linux/wireless.h>
#include <asm/io.h>
@@ -64,7 +65,6 @@
#define WIRELESS_SPY /* Enable spying addresses */
/* Definitions we need for spy */
typedef struct iw_statistics iw_stats;
-typedef struct iw_quality iw_qual;
typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */
#include "rayctl.h"
@@ -101,7 +101,6 @@ static int ray_dev_close(struct net_device *dev);
static int ray_dev_config(struct net_device *dev, struct ifmap *map);
static struct net_device_stats *ray_get_stats(struct net_device *dev);
static int ray_dev_init(struct net_device *dev);
-static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static struct ethtool_ops netdev_ethtool_ops;
@@ -114,9 +113,8 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
unsigned char *data);
static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
static iw_stats * ray_get_wireless_stats(struct net_device * dev);
-#endif /* WIRELESS_EXT > 7 */
+static const struct iw_handler_def ray_handler_def;
/***** Prototypes for raylink functions **************************************/
static int asc_to_int(char a);
@@ -373,11 +371,12 @@ static dev_link_t *ray_attach(void)
dev->hard_start_xmit = &ray_dev_start_xmit;
dev->set_config = &ray_dev_config;
dev->get_stats = &ray_get_stats;
- dev->do_ioctl = &ray_dev_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
- dev->get_wireless_stats = ray_get_wireless_stats;
-#endif
+ dev->wireless_handlers = &ray_handler_def;
+#ifdef WIRELESS_SPY
+ local->wireless_data.spy_data = &local->spy_data;
+ dev->wireless_data = &local->wireless_data;
+#endif /* WIRELESS_SPY */
dev->set_multicast_list = &set_multicast_list;
@@ -1201,436 +1200,420 @@ static struct ethtool_ops netdev_ethtool_ops = {
/*====================================================================*/
-static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get protocol name
+ */
+static int ray_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *cwrq,
+ char *extra)
{
- ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
- int err = 0;
-#if WIRELESS_EXT > 7
- struct iwreq *wrq = (struct iwreq *) ifr;
-#endif /* WIRELESS_EXT > 7 */
-#ifdef WIRELESS_SPY
- struct sockaddr address[IW_MAX_SPY];
-#endif /* WIRELESS_SPY */
+ strcpy(cwrq, "IEEE 802.11-FH");
+ return 0;
+}
- if (!(link->state & DEV_PRESENT)) {
- DEBUG(2,"ray_dev_ioctl - device not present\n");
- return -1;
- }
- DEBUG(2,"ray_cs IOCTL dev=%p, ifr=%p, cmd = 0x%x\n",dev,ifr,cmd);
- /* Validate the command */
- switch (cmd)
- {
-#if WIRELESS_EXT > 7
- /* --------------- WIRELESS EXTENSIONS --------------- */
- /* Get name */
- case SIOCGIWNAME:
- strcpy(wrq->u.name, "IEEE 802.11-FH");
- break;
-
- /* Get frequency/channel */
- case SIOCGIWFREQ:
- wrq->u.freq.m = local->sparm.b5.a_hop_pattern;
- wrq->u.freq.e = 0;
- break;
-
- /* Set frequency/channel */
- case SIOCSIWFREQ:
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int ray_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int err = -EINPROGRESS; /* Call commit handler */
- /* Setting by channel number */
- if ((wrq->u.freq.m > USA_HOP_MOD) || (wrq->u.freq.e > 0))
- err = -EOPNOTSUPP;
- else
- local->sparm.b5.a_hop_pattern = wrq->u.freq.m;
- break;
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
- /* Get current network name (ESSID) */
- case SIOCGIWESSID:
- if (wrq->u.data.pointer)
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
- /* Get the essid that was set */
- memcpy(essid, local->sparm.b5.a_current_ess_id,
- IW_ESSID_MAX_SIZE);
- essid[IW_ESSID_MAX_SIZE] = '\0';
-
- /* Push it out ! */
- wrq->u.data.length = strlen(essid) + 1;
- wrq->u.data.flags = 1; /* active */
- if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)))
- err = -EFAULT;
- }
- break;
+ /* Setting by channel number */
+ if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0))
+ err = -EOPNOTSUPP;
+ else
+ local->sparm.b5.a_hop_pattern = fwrq->m;
- /* Set desired network name (ESSID) */
- case SIOCSIWESSID:
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+ return err;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int ray_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- if (wrq->u.data.pointer)
- {
- char card_essid[IW_ESSID_MAX_SIZE + 1];
-
- /* Check if we asked for `any' */
- if(wrq->u.data.flags == 0)
- {
+ fwrq->m = local->sparm.b5.a_hop_pattern;
+ fwrq->e = 0;
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set ESSID
+ */
+static int ray_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* Check if we asked for `any' */
+ if(dwrq->flags == 0) {
/* Corey : can you do that ? */
- err = -EOPNOTSUPP;
- }
- else
- {
+ return -EOPNOTSUPP;
+ } else {
/* Check the size of the string */
- if(wrq->u.data.length >
- IW_ESSID_MAX_SIZE + 1)
- {
- err = -E2BIG;
- break;
- }
- if (copy_from_user(card_essid,
- wrq->u.data.pointer,
- wrq->u.data.length)) {
- err = -EFAULT;
- break;
+ if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+ return -E2BIG;
}
- card_essid[IW_ESSID_MAX_SIZE] = '\0';
/* Set the ESSID in the card */
- memcpy(local->sparm.b5.a_current_ess_id, card_essid,
- IW_ESSID_MAX_SIZE);
- }
+ memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE);
+ memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length);
}
- break;
-
- /* Get current Access Point (BSSID in our case) */
- case SIOCGIWAP:
- memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN);
- wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
- break;
-
- /* Get the current bit-rate */
- case SIOCGIWRATE:
- if(local->net_default_tx_rate == 3)
- wrq->u.bitrate.value = 2000000; /* Hum... */
- else
- wrq->u.bitrate.value = local->net_default_tx_rate * 500000;
- wrq->u.bitrate.fixed = 0; /* We are in auto mode */
- break;
-
- /* Set the desired bit-rate */
- case SIOCSIWRATE:
- /* Check if rate is in range */
- if((wrq->u.bitrate.value != 1000000) &&
- (wrq->u.bitrate.value != 2000000))
- {
- err = -EINVAL;
- break;
- }
- /* Hack for 1.5 Mb/s instead of 2 Mb/s */
- if((local->fw_ver == 0x55) && /* Please check */
- (wrq->u.bitrate.value == 2000000))
- local->net_default_tx_rate = 3;
- else
- local->net_default_tx_rate = wrq->u.bitrate.value/500000;
- break;
-
- /* Get the current RTS threshold */
- case SIOCGIWRTS:
- wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8)
- + local->sparm.b5.a_rts_threshold[1];
-#if WIRELESS_EXT > 8
- wrq->u.rts.disabled = (wrq->u.rts.value == 32767);
-#endif /* WIRELESS_EXT > 8 */
- wrq->u.rts.fixed = 1;
- break;
-
- /* Set the desired RTS threshold */
- case SIOCSIWRTS:
- {
- int rthr = wrq->u.rts.value;
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* if(wrq->u.rts.fixed == 0) we should complain */
-#if WIRELESS_EXT > 8
- if(wrq->u.rts.disabled)
- rthr = 32767;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get ESSID
+ */
+static int ray_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Get the essid that was set */
+ memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
+ extra[IW_ESSID_MAX_SIZE] = '\0';
+
+ /* Push it out ! */
+ dwrq->length = strlen(extra) + 1;
+ dwrq->flags = 1; /* active */
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get AP address
+ */
+static int ray_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ memcpy(awrq->sa_data, local->bss_id, ETH_ALEN);
+ awrq->sa_family = ARPHRD_ETHER;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Bit-Rate
+ */
+static int ray_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* Check if rate is in range */
+ if((vwrq->value != 1000000) && (vwrq->value != 2000000))
+ return -EINVAL;
+
+ /* Hack for 1.5 Mb/s instead of 2 Mb/s */
+ if((local->fw_ver == 0x55) && /* Please check */
+ (vwrq->value == 2000000))
+ local->net_default_tx_rate = 3;
else
-#endif /* WIRELESS_EXT > 8 */
- if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */
- {
- err = -EINVAL;
- break;
- }
+ local->net_default_tx_rate = vwrq->value/500000;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Bit-Rate
+ */
+static int ray_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ if(local->net_default_tx_rate == 3)
+ vwrq->value = 2000000; /* Hum... */
+ else
+ vwrq->value = local->net_default_tx_rate * 500000;
+ vwrq->fixed = 0; /* We are in auto mode */
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set RTS threshold
+ */
+static int ray_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int rthr = vwrq->value;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* if(wrq->u.rts.fixed == 0) we should complain */
+ if(vwrq->disabled)
+ rthr = 32767;
+ else {
+ if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */
+ return -EINVAL;
+ }
local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF;
local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF;
- }
- break;
- /* Get the current fragmentation threshold */
- case SIOCGIWFRAG:
- wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8)
- + local->sparm.b5.a_frag_threshold[1];
-#if WIRELESS_EXT > 8
- wrq->u.frag.disabled = (wrq->u.frag.value == 32767);
-#endif /* WIRELESS_EXT > 8 */
- wrq->u.frag.fixed = 1;
- break;
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* Set the desired fragmentation threshold */
- case SIOCSIWFRAG:
- {
- int fthr = wrq->u.frag.value;
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get RTS threshold
+ */
+static int ray_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8)
+ + local->sparm.b5.a_rts_threshold[1];
+ vwrq->disabled = (vwrq->value == 32767);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Fragmentation threshold
+ */
+static int ray_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int fthr = vwrq->value;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
/* if(wrq->u.frag.fixed == 0) should complain */
-#if WIRELESS_EXT > 8
- if(wrq->u.frag.disabled)
- fthr = 32767;
- else
-#endif /* WIRELESS_EXT > 8 */
- if((fthr < 256) || (fthr > 2347)) /* To check out ! */
- {
- err = -EINVAL;
- break;
- }
+ if(vwrq->disabled)
+ fthr = 32767;
+ else {
+ if((fthr < 256) || (fthr > 2347)) /* To check out ! */
+ return -EINVAL;
+ }
local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF;
local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF;
- }
- break;
-#endif /* WIRELESS_EXT > 7 */
-#if WIRELESS_EXT > 8
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* Get the current mode of operation */
- case SIOCGIWMODE:
- if(local->sparm.b5.a_network_type)
- wrq->u.mode = IW_MODE_INFRA;
- else
- wrq->u.mode = IW_MODE_ADHOC;
- break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Fragmentation threshold
+ */
+static int ray_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- /* Set the current mode of operation */
- case SIOCSIWMODE:
- {
+ vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8)
+ + local->sparm.b5.a_frag_threshold[1];
+ vwrq->disabled = (vwrq->value == 32767);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Mode of Operation
+ */
+static int ray_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int err = -EINPROGRESS; /* Call commit handler */
char card_mode = 1;
-
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
- switch (wrq->u.mode)
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ switch (*uwrq)
{
case IW_MODE_ADHOC:
- card_mode = 0;
- // Fall through
+ card_mode = 0;
+ // Fall through
case IW_MODE_INFRA:
- local->sparm.b5.a_network_type = card_mode;
- break;
+ local->sparm.b5.a_network_type = card_mode;
+ break;
default:
- err = -EINVAL;
+ err = -EINVAL;
}
- }
- break;
-#endif /* WIRELESS_EXT > 8 */
-#if WIRELESS_EXT > 7
- /* ------------------ IWSPY SUPPORT ------------------ */
- /* Define the range (variations) of above parameters */
- case SIOCGIWRANGE:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_range range;
- memset((char *) &range, 0, sizeof(struct iw_range));
-
- /* Set the length (very important for backward compatibility) */
- wrq->u.data.length = sizeof(struct iw_range);
-
-#if WIRELESS_EXT > 10
- /* Set the Wireless Extension versions */
- range.we_version_compiled = WIRELESS_EXT;
- range.we_version_source = 9;
-#endif /* WIRELESS_EXT > 10 */
-
- /* Set information in the range struct */
- range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */
- range.num_channels = hop_pattern_length[(int)country];
- range.num_frequency = 0;
- range.max_qual.qual = 0;
- range.max_qual.level = 255; /* What's the correct value ? */
- range.max_qual.noise = 255; /* Idem */
- range.num_bitrates = 2;
- range.bitrate[0] = 1000000; /* 1 Mb/s */
- range.bitrate[1] = 2000000; /* 2 Mb/s */
-
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- err = -EFAULT;
- }
- break;
+ return err;
+}
-#ifdef WIRELESS_SPY
- /* Set addresses to spy */
- case SIOCSIWSPY:
- /* Check the number of addresses */
- if(wrq->u.data.length > IW_MAX_SPY)
- {
- err = -E2BIG;
- break;
- }
- local->spy_number = wrq->u.data.length;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Mode of Operation
+ */
+static int ray_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- /* If there is some addresses to copy */
- if(local->spy_number > 0)
- {
- int i;
-
- /* Copy addresses to the driver */
- if(copy_from_user(address, wrq->u.data.pointer,
- sizeof(struct sockaddr) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Copy addresses to the lp structure */
- for(i = 0; i < local->spy_number; i++)
- memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
-
- /* Reset structure... */
- memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
-
-#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
- for(i = 0; i < local->spy_number; i++)
- printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
- local->spy_address[i][0],
- local->spy_address[i][1],
- local->spy_address[i][2],
- local->spy_address[i][3],
- local->spy_address[i][4],
- local->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
- }
- break;
+ if(local->sparm.b5.a_network_type)
+ *uwrq = IW_MODE_INFRA;
+ else
+ *uwrq = IW_MODE_ADHOC;
- /* Get the spy list and spy stats */
- case SIOCGIWSPY:
- /* Set the number of addresses */
- wrq->u.data.length = local->spy_number;
+ return 0;
+}
- /* If the user want to have the addresses back... */
- if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
- {
- int i;
-
- /* Copy addresses from the lp structure */
- for(i = 0; i < local->spy_number; i++)
- {
- memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
- address[i].sa_family = ARPHRD_ETHER;
- }
-
- /* Copy addresses to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, address,
- sizeof(struct sockaddr) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Copy stats to the user buffer (just after) */
- if(copy_to_user(wrq->u.data.pointer +
- (sizeof(struct sockaddr) * local->spy_number),
- local->spy_stat, sizeof(iw_qual) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Reset updated flags */
- for(i = 0; i < local->spy_number; i++)
- local->spy_stat[i].updated = 0x0;
- } /* if(pointer != NULL) */
-
- break;
-#endif /* WIRELESS_SPY */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int ray_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+
+ memset((char *) range, 0, sizeof(struct iw_range));
+
+ /* Set the length (very important for backward compatibility) */
+ dwrq->length = sizeof(struct iw_range);
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 9;
+
+ /* Set information in the range struct */
+ range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */
+ range->num_channels = hop_pattern_length[(int)country];
+ range->num_frequency = 0;
+ range->max_qual.qual = 0;
+ range->max_qual.level = 255; /* What's the correct value ? */
+ range->max_qual.noise = 255; /* Idem */
+ range->num_bitrates = 2;
+ range->bitrate[0] = 1000000; /* 1 Mb/s */
+ range->bitrate[1] = 2000000; /* 2 Mb/s */
+ return 0;
+}
- /* ------------------ PRIVATE IOCTL ------------------ */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
-#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */
-#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
- case SIOCSIPFRAMING:
- if(!capable(CAP_NET_ADMIN)) /* For private IOCTLs, we need to check permissions */
- {
- err = -EPERM;
- break;
- }
- translate = *(wrq->u.name); /* Set framing mode */
- break;
- case SIOCGIPFRAMING:
- *(wrq->u.name) = translate;
- break;
- case SIOCGIPCOUNTRY:
- *(wrq->u.name) = country;
- break;
- case SIOCGIWPRIV:
- /* Export our "private" intercace */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_priv_args priv[] =
- { /* cmd, set_args, get_args, name */
- { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
- { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
- { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
- };
- /* Set the number of ioctl available */
- wrq->u.data.length = 3;
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
- sizeof(priv)))
- err = -EFAULT;
- }
- break;
-#endif /* WIRELESS_EXT > 7 */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set framing mode
+ */
+static int ray_set_framing(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ translate = *(extra); /* Set framing mode */
+ return 0;
+}
- default:
- DEBUG(0,"ray_dev_ioctl cmd = 0x%x\n", cmd);
- err = -EOPNOTSUPP;
- }
- return err;
-} /* end ray_dev_ioctl */
-/*===========================================================================*/
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get framing mode
+ */
+static int ray_get_framing(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ *(extra) = translate;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get country
+ */
+static int ray_get_country(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ *(extra) = country;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Commit handler : called after a bunch of SET operations
+ */
+static int ray_commit(struct net_device *dev,
+ struct iw_request_info *info, /* NULL */
+ void *zwrq, /* NULL */
+ char *extra) /* NULL */
+{
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Stats handler : return Wireless Stats
+ */
static iw_stats * ray_get_wireless_stats(struct net_device * dev)
{
ray_dev_t * local = (ray_dev_t *) dev->priv;
@@ -1642,13 +1625,13 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
local->wstats.status = local->card_status;
#ifdef WIRELESS_SPY
- if((local->spy_number > 0) && (local->sparm.b5.a_network_type == 0))
+ if((local->spy_data.spy_number > 0) && (local->sparm.b5.a_network_type == 0))
{
/* Get it from the first node in spy list */
- local->wstats.qual.qual = local->spy_stat[0].qual;
- local->wstats.qual.level = local->spy_stat[0].level;
- local->wstats.qual.noise = local->spy_stat[0].noise;
- local->wstats.qual.updated = local->spy_stat[0].updated;
+ local->wstats.qual.qual = local->spy_data.spy_stat[0].qual;
+ local->wstats.qual.level = local->spy_data.spy_stat[0].level;
+ local->wstats.qual.noise = local->spy_data.spy_stat[0].noise;
+ local->wstats.qual.updated = local->spy_data.spy_stat[0].updated;
}
#endif /* WIRELESS_SPY */
@@ -1659,7 +1642,65 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
return &local->wstats;
} /* end ray_get_wireless_stats */
-#endif /* WIRELESS_EXT > 7 */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const iw_handler ray_handler[] = {
+ [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
+ [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) ray_get_name,
+ [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) ray_set_freq,
+ [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) ray_get_freq,
+ [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) ray_set_mode,
+ [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) ray_get_mode,
+ [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
+#ifdef WIRELESS_SPY
+ [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
+ [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
+ [SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
+ [SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
+#endif /* WIRELESS_SPY */
+ [SIOCGIWAP -SIOCIWFIRST] (iw_handler) ray_get_wap,
+ [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
+ [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
+ [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) ray_set_rate,
+ [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) ray_get_rate,
+ [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) ray_set_rts,
+ [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) ray_get_rts,
+ [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) ray_set_frag,
+ [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) ray_get_frag,
+};
+
+#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
+#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */
+#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
+
+static const iw_handler ray_private_handler[] = {
+ [0] (iw_handler) ray_set_framing,
+ [1] (iw_handler) ray_get_framing,
+ [3] (iw_handler) ray_get_country,
+};
+
+static const struct iw_priv_args ray_private_args[] = {
+/* cmd, set_args, get_args, name */
+{ SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
+{ SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
+{ SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
+};
+
+static const struct iw_handler_def ray_handler_def =
+{
+ .num_standard = sizeof(ray_handler)/sizeof(iw_handler),
+ .num_private = sizeof(ray_private_handler)/sizeof(iw_handler),
+ .num_private_args = sizeof(ray_private_args)/sizeof(struct iw_priv_args),
+ .standard = ray_handler,
+ .private = ray_private_handler,
+ .private_args = ray_private_args,
+ .get_wireless_stats = ray_get_wireless_stats,
+};
+
/*===========================================================================*/
static int ray_open(struct net_device *dev)
{
@@ -2392,20 +2433,15 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned i
/*local->wstats.qual.noise = none ? */
local->wstats.qual.updated = 0x2;
}
- /* Now, for the addresses in the spy list */
+ /* Now, update the spy stuff */
{
- int i;
- /* Look all addresses */
- for(i = 0; i < local->spy_number; i++)
- /* If match */
- if(!memcmp(linksrcaddr, local->spy_address[i], ETH_ALEN))
- {
- /* Update statistics */
- /*local->spy_stat[i].qual = none ? */
- local->spy_stat[i].level = siglev;
- /*local->spy_stat[i].noise = none ? */
- local->spy_stat[i].updated = 0x2;
- }
+ struct iw_quality wstats;
+ wstats.level = siglev;
+ /* wstats.noise = none ? */
+ /* wstats.qual = none ? */
+ wstats.updated = 0x2;
+ /* Update spy records */
+ wireless_spy_update(dev, linksrcaddr, &wstats);
}
#endif /* WIRELESS_SPY */
} /* end rx_data */
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index c77afa14fa86..42660fe64bfd 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -63,13 +63,10 @@ typedef struct ray_dev_t {
UCHAR last_rsl;
int beacon_rxed;
struct beacon_rx last_bcn;
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless specific stats */
-#endif
#ifdef WIRELESS_SPY
- int spy_number; /* Number of addresses to spy */
- mac_addr spy_address[IW_MAX_SPY + 1]; /* The addresses to spy */
- iw_qual spy_stat[IW_MAX_SPY + 1]; /* Statistics gathered */
+ struct iw_spy_data spy_data;
+ struct iw_public_data wireless_data;
#endif /* WIRELESS_SPY */
} ray_dev_t;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
new file mode 100644
index 000000000000..39c6cdf7f3f7
--- /dev/null
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -0,0 +1,1120 @@
+/*
+ * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
+ * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Communications and Intel PRO/Wireless 2011B.
+ *
+ * The driver implements Symbol firmware download. The rest is handled
+ * in hermes.c and orinoco.c.
+ *
+ * Utilities for downloading the Symbol firmware are available at
+ * http://sourceforge.net/projects/orinoco/
+ *
+ * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
+ * Portions based on orinoco_cs.c:
+ * Copyright (C) David Gibson, Linuxcare Australia
+ * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
+ * Copyright (C) Symbol Technologies.
+ *
+ * See copyright notice in file orinoco.c.
+ */
+
+#define DRIVER_NAME "spectrum_cs"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+#ifdef __IN_PCMCIA_PACKAGE__
+#include <pcmcia/k_compat.h>
+#endif /* __IN_PCMCIA_PACKAGE__ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "orinoco.h"
+
+/*
+ * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
+ * the driver. Use get_symbol_fw script to generate spectrum_fw.h and
+ * copy it to the same directory as spectrum_cs.c.
+ *
+ * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
+ * runtime using hotplug. Use the same get_symbol_fw script to generate
+ * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
+ * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
+ * make sure that you have hotplug installed and enabled in the kernel.
+ */
+/* #define SPECTRUM_FW_INCLUDED 1 */
+
+#ifdef SPECTRUM_FW_INCLUDED
+/* Header with the firmware */
+#include "spectrum_fw.h"
+#else /* !SPECTRUM_FW_INCLUDED */
+#include <linux/firmware.h>
+static unsigned char *primsym;
+static unsigned char *secsym;
+static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
+static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
+#endif /* !SPECTRUM_FW_INCLUDED */
+
+/********************************************************************/
+/* Module stuff */
+/********************************************************************/
+
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
+MODULE_LICENSE("Dual MPL/GPL");
+
+/* Module parameters */
+
+/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+ * don't have any CIS entry for it. This workaround it... */
+static int ignore_cis_vcc; /* = 0 */
+module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
+
+/********************************************************************/
+/* Magic constants */
+/********************************************************************/
+
+/*
+ * The dev_info variable is the "key" that is used to match up this
+ * device driver with appropriate cards, through the card
+ * configuration database.
+ */
+static dev_info_t dev_info = DRIVER_NAME;
+
+/********************************************************************/
+/* Data structures */
+/********************************************************************/
+
+/* PCMCIA specific device information (goes in the card field of
+ * struct orinoco_private */
+struct orinoco_pccard {
+ dev_link_t link;
+ dev_node_t node;
+};
+
+/*
+ * 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).
+ */
+static dev_link_t *dev_list; /* = NULL */
+
+/********************************************************************/
+/* Function prototypes */
+/********************************************************************/
+
+/* device methods */
+static int spectrum_cs_hard_reset(struct orinoco_private *priv);
+
+/* PCMCIA gumpf */
+static void spectrum_cs_config(dev_link_t * link);
+static void spectrum_cs_release(dev_link_t * link);
+static int spectrum_cs_event(event_t event, int priority,
+ event_callback_args_t * args);
+
+static dev_link_t *spectrum_cs_attach(void);
+static void spectrum_cs_detach(dev_link_t *);
+
+/********************************************************************/
+/* Firmware downloader */
+/********************************************************************/
+
+/* Position of PDA in the adapter memory */
+#define EEPROM_ADDR 0x3000
+#define EEPROM_LEN 0x200
+#define PDA_OFFSET 0x100
+
+#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
+#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
+
+/* Constants for the CISREG_CCSR register */
+#define HCR_RUN 0x07 /* run firmware after reset */
+#define HCR_IDLE 0x0E /* don't run firmware after reset */
+#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
+
+/*
+ * AUX port access. To unlock the AUX port write the access keys to the
+ * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
+ * register. Then read it and make sure it's HERMES_AUX_ENABLED.
+ */
+#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
+#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
+#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
+
+#define HERMES_AUX_PW0 0xFE01
+#define HERMES_AUX_PW1 0xDC23
+#define HERMES_AUX_PW2 0xBA45
+
+/* End markers */
+#define PDI_END 0x00000000 /* End of PDA */
+#define BLOCK_END 0xFFFFFFFF /* Last image block */
+#define TEXT_END 0x1A /* End of text header */
+
+/*
+ * The following structures have little-endian fields denoted by
+ * the leading underscore. Don't access them directly - use inline
+ * functions defined below.
+ */
+
+/*
+ * The binary image to be downloaded consists of series of data blocks.
+ * Each block has the following structure.
+ */
+struct dblock {
+ u32 _addr; /* adapter address where to write the block */
+ u16 _len; /* length of the data only, in bytes */
+ char data[0]; /* data to be written */
+} __attribute__ ((packed));
+
+/*
+ * Plug Data References are located in in the image after the last data
+ * block. They refer to areas in the adapter memory where the plug data
+ * items with matching ID should be written.
+ */
+struct pdr {
+ u32 _id; /* record ID */
+ u32 _addr; /* adapter address where to write the data */
+ u32 _len; /* expected length of the data, in bytes */
+ char next[0]; /* next PDR starts here */
+} __attribute__ ((packed));
+
+
+/*
+ * Plug Data Items are located in the EEPROM read from the adapter by
+ * primary firmware. They refer to the device-specific data that should
+ * be plugged into the secondary firmware.
+ */
+struct pdi {
+ u16 _len; /* length of ID and data, in words */
+ u16 _id; /* record ID */
+ char data[0]; /* plug data */
+} __attribute__ ((packed));;
+
+
+/* Functions for access to little-endian data */
+static inline u32
+dblock_addr(const struct dblock *blk)
+{
+ return le32_to_cpu(blk->_addr);
+}
+
+static inline u32
+dblock_len(const struct dblock *blk)
+{
+ return le16_to_cpu(blk->_len);
+}
+
+static inline u32
+pdr_id(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_id);
+}
+
+static inline u32
+pdr_addr(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_addr);
+}
+
+static inline u32
+pdr_len(const struct pdr *pdr)
+{
+ return le32_to_cpu(pdr->_len);
+}
+
+static inline u32
+pdi_id(const struct pdi *pdi)
+{
+ return le16_to_cpu(pdi->_id);
+}
+
+/* Return length of the data only, in bytes */
+static inline u32
+pdi_len(const struct pdi *pdi)
+{
+ return 2 * (le16_to_cpu(pdi->_len) - 1);
+}
+
+
+/* Set address of the auxiliary port */
+static inline void
+spectrum_aux_setaddr(hermes_t *hw, u32 addr)
+{
+ hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
+ hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
+}
+
+
+/* Open access to the auxiliary port */
+static int
+spectrum_aux_open(hermes_t *hw)
+{
+ int i;
+
+ /* Already open? */
+ if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED)
+ return 0;
+
+ hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
+ hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
+ hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
+ hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE);
+
+ for (i = 0; i < 20; i++) {
+ udelay(10);
+ if (hermes_read_reg(hw, HERMES_CONTROL) ==
+ HERMES_AUX_ENABLED)
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+
+#define CS_CHECK(fn, ret) \
+ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+/*
+ * Reset the card using configuration registers COR and CCSR.
+ * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
+ */
+static int
+spectrum_reset(dev_link_t *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))
+ return -ENODEV;
+
+ /* Save original COR value */
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ save_cor = reg.Value;
+
+ /* Soft-Reset card */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor | COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ udelay(1000);
+
+ /* Read CCSR */
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_CCSR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+
+ /*
+ * Start or stop the firmware. Memory width bit should be
+ * preserved from the value we've just read.
+ */
+ reg.Action = CS_WRITE;
+ 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));
+ udelay(1000);
+
+ /* Restore original COR configuration index */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor & ~COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ udelay(1000);
+ return 0;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+ return -ENODEV;
+}
+
+
+/*
+ * Scan PDR for the record with the specified RECORD_ID.
+ * If it's not found, return NULL.
+ */
+static struct pdr *
+spectrum_find_pdr(struct pdr *first_pdr, u32 record_id)
+{
+ struct pdr *pdr = first_pdr;
+
+ while (pdr_id(pdr) != PDI_END) {
+ /*
+ * PDR area is currently not terminated by PDI_END.
+ * It's followed by CRC records, which have the type
+ * field where PDR has length. The type can be 0 or 1.
+ */
+ if (pdr_len(pdr) < 2)
+ return NULL;
+
+ /* If the record ID matches, we are done */
+ if (pdr_id(pdr) == record_id)
+ return pdr;
+
+ pdr = (struct pdr *) pdr->next;
+ }
+ return NULL;
+}
+
+
+/* Process one Plug Data Item - find corresponding PDR and plug it */
+static int
+spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
+{
+ struct pdr *pdr;
+
+ /* Find the PDI corresponding to this PDR */
+ pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));
+
+ /* No match is found, safe to ignore */
+ if (!pdr)
+ return 0;
+
+ /* Lengths of the data in PDI and PDR must match */
+ if (pdi_len(pdi) != pdr_len(pdr))
+ return -EINVAL;
+
+ /* do the actual plugging */
+ spectrum_aux_setaddr(hw, pdr_addr(pdr));
+ hermes_write_words(hw, HERMES_AUXDATA, pdi->data,
+ pdi_len(pdi) / 2);
+
+ return 0;
+}
+
+
+/* Read PDA from the adapter */
+static int
+spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+{
+ int ret;
+ int pda_size;
+
+ /* Issue command to read EEPROM */
+ ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
+ if (ret)
+ return ret;
+
+ /* Open auxiliary port */
+ ret = spectrum_aux_open(hw);
+ if (ret)
+ return ret;
+
+ /* read PDA from EEPROM */
+ spectrum_aux_setaddr(hw, PDA_ADDR);
+ hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);
+
+ /* Check PDA length */
+ pda_size = le16_to_cpu(pda[0]);
+ if (pda_size > pda_len)
+ return -EINVAL;
+
+ return 0;
+}
+
+
+/* Parse PDA and write the records into the adapter */
+static int
+spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
+ u16 *pda)
+{
+ int ret;
+ struct pdi *pdi;
+ struct pdr *first_pdr;
+ const struct dblock *blk = first_block;
+
+ /* Skip all blocks to locate Plug Data References */
+ while (dblock_addr(blk) != BLOCK_END)
+ blk = (struct dblock *) &blk->data[dblock_len(blk)];
+
+ first_pdr = (struct pdr *) blk;
+
+ /* Go through every PDI and plug them into the adapter */
+ pdi = (struct pdi *) (pda + 2);
+ while (pdi_id(pdi) != PDI_END) {
+ ret = spectrum_plug_pdi(hw, first_pdr, pdi);
+ if (ret)
+ return ret;
+
+ /* Increment to the next PDI */
+ pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
+ }
+ return 0;
+}
+
+
+/* Load firmware blocks into the adapter */
+static int
+spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
+{
+ const struct dblock *blk;
+ u32 blkaddr;
+ u32 blklen;
+
+ blk = first_block;
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+
+ while (dblock_addr(blk) != BLOCK_END) {
+ spectrum_aux_setaddr(hw, blkaddr);
+ hermes_write_words(hw, HERMES_AUXDATA, blk->data,
+ blklen / 2);
+
+ blk = (struct dblock *) &blk->data[blklen];
+ blkaddr = dblock_addr(blk);
+ blklen = dblock_len(blk);
+ }
+ return 0;
+}
+
+
+/*
+ * Process a firmware image - stop the card, load the firmware, reset
+ * the card and make sure it responds. For the secondary firmware take
+ * 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,
+ const unsigned char *image)
+{
+ int ret;
+ const unsigned char *ptr;
+ const struct dblock *first_block;
+
+ /* Plug Data Area (PDA) */
+ u16 pda[PDA_WORDS];
+
+ /* Binary block begins after the 0x1A marker */
+ ptr = image;
+ while (*ptr++ != TEXT_END);
+ first_block = (const struct dblock *) ptr;
+
+ /* Read the PDA */
+ if (image != primsym) {
+ ret = spectrum_read_pda(hw, pda, sizeof(pda));
+ if (ret)
+ return ret;
+ }
+
+ /* Stop the firmware, so that it can be safely rewritten */
+ ret = spectrum_reset(link, 1);
+ if (ret)
+ return ret;
+
+ /* Program the adapter with new firmware */
+ ret = spectrum_load_blocks(hw, first_block);
+ if (ret)
+ return ret;
+
+ /* Write the PDA to the adapter */
+ if (image != primsym) {
+ ret = spectrum_apply_pda(hw, first_block, pda);
+ if (ret)
+ return ret;
+ }
+
+ /* Run the firmware */
+ ret = spectrum_reset(link, 0);
+ if (ret)
+ return ret;
+
+ /* Reset hermes chip and make sure it responds */
+ ret = hermes_init(hw);
+
+ /* hermes_reset() should return 0 with the secondary firmware */
+ if (image != primsym && ret != 0)
+ return -ENODEV;
+
+ /* And this should work with any firmware */
+ if (!hermes_present(hw))
+ return -ENODEV;
+
+ return 0;
+}
+
+
+/*
+ * Download the firmware into the card, this also does a PCMCIA soft
+ * 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)
+{
+ int ret;
+ client_handle_t handle = link->handle;
+
+#ifndef SPECTRUM_FW_INCLUDED
+ const struct firmware *fw_entry;
+
+ if (request_firmware(&fw_entry, primary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ primsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ primary_fw_name);
+ return -ENOENT;
+ }
+
+ if (request_firmware(&fw_entry, secondary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ secsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ secondary_fw_name);
+ return -ENOENT;
+ }
+#endif
+
+ /* Load primary firmware */
+ ret = spectrum_dl_image(hw, link, primsym);
+ if (ret) {
+ printk(KERN_ERR PFX "Primary firmware download failed\n");
+ return ret;
+ }
+
+ /* Load secondary firmware */
+ ret = spectrum_dl_image(hw, link, secsym);
+
+ if (ret) {
+ printk(KERN_ERR PFX "Secondary firmware download failed\n");
+ }
+
+ return ret;
+}
+
+/********************************************************************/
+/* Device methods */
+/********************************************************************/
+
+static int
+spectrum_cs_hard_reset(struct orinoco_private *priv)
+{
+ struct orinoco_pccard *card = priv->card;
+ dev_link_t *link = &card->link;
+ int err;
+
+ if (!hermes_present(&priv->hw)) {
+ /* The firmware needs to be reloaded */
+ if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+ printk(KERN_ERR PFX "Firmware download failed\n");
+ err = -ENODEV;
+ }
+ } else {
+ /* Soft reset using COR and HCR */
+ spectrum_reset(link, 0);
+ }
+
+ return 0;
+}
+
+/********************************************************************/
+/* PCMCIA stuff */
+/********************************************************************/
+
+/*
+ * This creates an "instance" of the driver, allocating local data
+ * structures for one device. The device is registered with Card
+ * Services.
+ *
+ * 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 dev_link_t *
+spectrum_cs_attach(void)
+{
+ struct net_device *dev;
+ struct orinoco_private *priv;
+ struct orinoco_pccard *card;
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret;
+
+ dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+ if (! dev)
+ return NULL;
+ priv = netdev_priv(dev);
+ card = priv->card;
+
+ /* Link both structures together */
+ link = &card->link;
+ link->priv = dev;
+
+ /* Interrupt setup */
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Handler = orinoco_interrupt;
+ link->irq.Instance = dev;
+
+ /* General socket configuration defaults can go here. In this
+ * client, we assume very little, and rely on the CIS for
+ * almost everything. In most clients, many details (i.e.,
+ * number, sizes, 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.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ /* FIXME: need a lock? */
+ link->next = dev_list;
+ dev_list = link;
+
+ client_reg.dev_info = &dev_info;
+ client_reg.Version = 0x0210; /* FIXME: what does this mean? */
+ client_reg.event_callback_args.client_data = link;
+
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ spectrum_cs_detach(link);
+ return NULL;
+ }
+
+ return link;
+} /* spectrum_cs_attach */
+
+/*
+ * This deletes a driver "instance". The device is de-registered with
+ * Card 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 spectrum_cs_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+ struct net_device *dev = link->priv;
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+
+ BUG_ON(*linkp == NULL);
+
+ if (link->state & DEV_CONFIG)
+ spectrum_cs_release(link);
+
+ /* Break the link with Card Services */
+ if (link->handle)
+ pcmcia_deregister_client(link->handle);
+
+ /* Unlink device structure, and free it */
+ *linkp = link->next;
+ DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
+ if (link->dev) {
+ DEBUG(0, PFX "About to unregister net device %p\n",
+ dev);
+ unregister_netdev(dev);
+ }
+ free_orinocodev(dev);
+} /* spectrum_cs_detach */
+
+/*
+ * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
+ * event is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+
+static void
+spectrum_cs_config(dev_link_t *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;
+ int last_fn, last_ret;
+ u_char buf[64];
+ config_info_t conf;
+ cisinfo_t info;
+ tuple_t tuple;
+ cisparse_t parse;
+ void __iomem *mem;
+
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+
+ /*
+ * This reads the card's CONFIG tuple to find its
+ * configuration registers.
+ */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ 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));
+ 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;
+
+ /*
+ * In this loop, we scan the CIS for configuration table
+ * entries, each of which describes a valid card
+ * configuration, including voltage, IO window, memory window,
+ * and interrupt settings.
+ *
+ * We make no assumptions about the card to be configured: we
+ * use just the information available in the CIS. In an ideal
+ * world, this would work for any PCMCIA card, but it requires
+ * a complete and accurate CIS. In practice, a driver usually
+ * "knows" most of these things without consulting the CIS,
+ * and most client drivers 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));
+ 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))
+ goto next_entry;
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+ dflt = *cfg;
+ if (cfg->index == 0)
+ goto next_entry;
+ link->conf.ConfigIndex = cfg->index;
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* 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)) {
+ if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if(!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ /* Do we need to allocate an interrupt? */
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io =
+ (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 =
+ IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 =
+ IO_DATA_PATH_WIDTH_8;
+ link->io.IOAddrLines =
+ io->flags & CISTPL_IO_LINES_MASK;
+ link->io.BasePort1 = io->win[0].base;
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 =
+ link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ 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)
+ goto next_entry;
+ }
+
+
+ /* If we got this far, we're cool! */
+
+ break;
+
+ next_entry:
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ if (last_ret == CS_NO_MORE_ITEMS) {
+ printk(KERN_ERR PFX "GetNextTuple(): No matching "
+ "CIS configuration. Maybe you need the "
+ "ignore_cis_vcc=1 parameter.\n");
+ goto cs_failed;
+ }
+ }
+
+ /*
+ * 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.
+ */
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+
+ /* We initialize the hermes structure before completing PCMCIA
+ * configuration just in case the interrupt handler gets
+ * called. */
+ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+ if (!mem)
+ goto cs_failed;
+
+ hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+
+ /*
+ * 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));
+
+ /* Ok, we have the configuration, prepare to register the netdev */
+ dev->base_addr = link->io.BasePort1;
+ dev->irq = link->irq.AssignedIRQ;
+ SET_MODULE_OWNER(dev);
+ card->node.major = card->node.minor = 0;
+
+ /* Reset card and download firmware */
+ if (spectrum_cs_hard_reset(priv) != 0) {
+ goto failed;
+ }
+
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ /* Tell the stack we exist */
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR PFX "register_netdev() failed\n");
+ goto failed;
+ }
+
+ /* At this point, the dev_node_t structure(s) needs to be
+ * initialized and arranged in a linked list at link->dev. */
+ strcpy(card->node.dev_name, dev->name);
+ link->dev = &card->node; /* link->dev 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(", irq %d", link->irq.AssignedIRQ);
+ if (link->io.NumPorts1)
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+ link->io.BasePort1 + link->io.NumPorts1 - 1);
+ if (link->io.NumPorts2)
+ printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+ link->io.BasePort2 + link->io.NumPorts2 - 1);
+ printk("\n");
+
+ return;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+ spectrum_cs_release(link);
+} /* spectrum_cs_config */
+
+/*
+ * After a card is removed, spectrum_cs_release() will unregister the
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void
+spectrum_cs_release(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ /* We're committed to taking the device away now, so mark the
+ * hardware as unavailable */
+ spin_lock_irqsave(&priv->lock, flags);
+ 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;
+ if (priv->hw.iobase)
+ ioport_unmap(priv->hw.iobase);
+} /* spectrum_cs_release */
+
+/*
+ * The card status event handler. Mostly, this schedules other stuff
+ * to run after an event is received.
+ */
+static int
+spectrum_cs_event(event_t event, int priority,
+ event_callback_args_t * args)
+{
+ dev_link_t *link = args->client_data;
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ int err = 0;
+ unsigned long flags;
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ spectrum_cs_config(link);
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ /* Mark the device as stopped, to block IO until later */
+ 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 :-( */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
+ dev->name,
+ event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
+ err);
+
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ 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);
+ }
+ break;
+ }
+
+ return err;
+} /* spectrum_cs_event */
+
+/********************************************************************/
+/* Module initialization */
+/********************************************************************/
+
+/* Can't be declared "const" or the whole __initdata section will
+ * become const */
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Pavel Roskin <proski@gnu.org>,"
+ " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
+
+static struct pcmcia_device_id spectrum_cs_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+ PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
+
+static struct pcmcia_driver orinoco_driver = {
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = DRIVER_NAME,
+ },
+ .attach = spectrum_cs_attach,
+ .event = spectrum_cs_event,
+ .detach = spectrum_cs_detach,
+ .id_table = spectrum_cs_ids,
+};
+
+static int __init
+init_spectrum_cs(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+
+ return pcmcia_register_driver(&orinoco_driver);
+}
+
+static void __exit
+exit_spectrum_cs(void)
+{
+ pcmcia_unregister_driver(&orinoco_driver);
+ BUG_ON(dev_list != NULL);
+}
+
+module_init(init_spectrum_cs);
+module_exit(exit_spectrum_cs);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 6c42b573a95a..4b0acae22b0d 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -209,7 +209,7 @@ enum {
NoStructure = 0, /* Really old firmware */
StructuredMessages = 1, /* Parsable AT response msgs */
ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */
-} FirmwareLevel;
+};
struct strip {
int magic;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index f6130a53b796..183c4732ef65 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -59,6 +59,12 @@
/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */
#include "wavelan_cs.p.h" /* Private header */
+#ifdef WAVELAN_ROAMING
+static void wl_cell_expiry(unsigned long data);
+static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp);
+static void wv_nwid_filter(unsigned char mode, net_local *lp);
+#endif /* WAVELAN_ROAMING */
+
/************************* MISC SUBROUTINES **************************/
/*
* Subroutines which won't fit in one of the following category
@@ -500,9 +506,9 @@ fee_write(u_long base, /* i/o port of the card */
#ifdef WAVELAN_ROAMING /* Conditional compile, see wavelan_cs.h */
-unsigned char WAVELAN_BEACON_ADDRESS[]= {0x09,0x00,0x0e,0x20,0x03,0x00};
+static unsigned char WAVELAN_BEACON_ADDRESS[] = {0x09,0x00,0x0e,0x20,0x03,0x00};
-void wv_roam_init(struct net_device *dev)
+static void wv_roam_init(struct net_device *dev)
{
net_local *lp= netdev_priv(dev);
@@ -531,7 +537,7 @@ void wv_roam_init(struct net_device *dev)
printk(KERN_DEBUG "WaveLAN: Roaming enabled on device %s\n",dev->name);
}
-void wv_roam_cleanup(struct net_device *dev)
+static void wv_roam_cleanup(struct net_device *dev)
{
wavepoint_history *ptr,*old_ptr;
net_local *lp= netdev_priv(dev);
@@ -550,7 +556,7 @@ void wv_roam_cleanup(struct net_device *dev)
}
/* Enable/Disable NWID promiscuous mode on a given device */
-void wv_nwid_filter(unsigned char mode, net_local *lp)
+static void wv_nwid_filter(unsigned char mode, net_local *lp)
{
mm_t m;
unsigned long flags;
@@ -575,7 +581,7 @@ void wv_nwid_filter(unsigned char mode, net_local *lp)
}
/* Find a record in the WavePoint table matching a given NWID */
-wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
+static wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
{
wavepoint_history *ptr=lp->wavepoint_table.head;
@@ -588,7 +594,7 @@ wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
}
/* Create a new wavepoint table entry */
-wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
+static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
{
wavepoint_history *new_wavepoint;
@@ -624,7 +630,7 @@ wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_
}
/* Remove a wavepoint entry from WavePoint table */
-void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
+static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
{
if(wavepoint==NULL)
return;
@@ -646,7 +652,7 @@ void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
}
/* Timer callback function - checks WavePoint table for stale entries */
-void wl_cell_expiry(unsigned long data)
+static void wl_cell_expiry(unsigned long data)
{
net_local *lp=(net_local *)data;
wavepoint_history *wavepoint=lp->wavepoint_table.head,*old_point;
@@ -686,7 +692,7 @@ void wl_cell_expiry(unsigned long data)
}
/* Update SNR history of a wavepoint */
-void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
+static void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
{
int i=0,num_missed=0,ptr=0;
int average_fast=0,average_slow=0;
@@ -723,7 +729,7 @@ void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsi
}
/* Perform a handover to a new WavePoint */
-void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
+static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
{
kio_addr_t base = lp->dev->base_addr;
mm_t m;
diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/net/wireless/wavelan_cs.h
index 29cff6daf860..fabc63ee153c 100644
--- a/drivers/net/wireless/wavelan_cs.h
+++ b/drivers/net/wireless/wavelan_cs.h
@@ -62,7 +62,7 @@
* like DEC RoamAbout, or Digital Ocean, Epson, ...), you must modify this
* part to accommodate your hardware...
*/
-const unsigned char MAC_ADDRESSES[][3] =
+static const unsigned char MAC_ADDRESSES[][3] =
{
{ 0x08, 0x00, 0x0E }, /* AT&T Wavelan (standard) & DEC RoamAbout */
{ 0x08, 0x00, 0x6A }, /* AT&T Wavelan (alternate) */
@@ -79,14 +79,14 @@ const unsigned char MAC_ADDRESSES[][3] =
* (as read in the offset register of the dac area).
* Used to map channel numbers used by `wfreqsel' to frequencies
*/
-const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
+static const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
0xD0, 0xF0, 0xF8, 0x150 };
/* Frequencies of the 1.0 modem (fixed frequencies).
* Use to map the PSA `subband' to a frequency
* Note : all frequencies apart from the first one need to be multiplied by 10
*/
-const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
+static const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
/*************************** PC INTERFACE ****************************/
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 677ff71883cb..01d882be8790 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -647,23 +647,6 @@ struct net_local
void __iomem *mem;
};
-/**************************** PROTOTYPES ****************************/
-
-#ifdef WAVELAN_ROAMING
-/* ---------------------- ROAMING SUBROUTINES -----------------------*/
-
-wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp);
-wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local *lp);
-void wl_del_wavepoint(wavepoint_history *wavepoint, net_local *lp);
-void wl_cell_expiry(unsigned long data);
-wavepoint_history *wl_best_sigqual(int fast_search, net_local *lp);
-void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq);
-void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp);
-void wv_nwid_filter(unsigned char mode, net_local *lp);
-void wv_roam_init(struct net_device *dev);
-void wv_roam_cleanup(struct net_device *dev);
-#endif /* WAVELAN_ROAMING */
-
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
static inline u_char /* data */
hasr_read(u_long); /* Read the host interface : base address */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 8636d9306785..7fcbe589c3f2 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -2,7 +2,7 @@
#define __WL3501_H__
#include <linux/spinlock.h>
-#include "ieee802_11.h"
+#include <net/ieee80211.h>
/* define for WLA 2.0 */
#define WL3501_BLKSZ 256
@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
struct wl3501_80211_tx_hdr {
struct wl3501_80211_tx_plcp_hdr pclp_hdr;
- struct ieee802_11_hdr mac_hdr;
+ struct ieee80211_hdr mac_hdr;
} __attribute__ ((packed));
/*
@@ -609,6 +609,7 @@ struct wl3501_card {
struct net_device_stats stats;
struct iw_statistics wstats;
struct iw_spy_data spy_data;
+ struct iw_public_data wireless_data;
struct dev_node_t node;
};
#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index dd902126d018..3f8c27f0871b 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -296,7 +296,8 @@ static int wl3501_get_flash_mac_addr(struct wl3501_card *this)
*
* Move 'size' bytes from PC to card. (Shouldn't be interrupted)
*/
-void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
+static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src,
+ int size)
{
/* switch to SRAM Page 0 */
wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 :
@@ -317,8 +318,8 @@ void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
*
* Move 'size' bytes from card to PC. (Shouldn't be interrupted)
*/
-void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
- int size)
+static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
+ int size)
{
/* switch to SRAM Page 0 */
wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 :
@@ -1438,14 +1439,14 @@ fail:
goto out;
}
-struct net_device_stats *wl3501_get_stats(struct net_device *dev)
+static struct net_device_stats *wl3501_get_stats(struct net_device *dev)
{
struct wl3501_card *this = dev->priv;
return &this->stats;
}
-struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
{
struct wl3501_card *this = dev->priv;
struct iw_statistics *wstats = &this->wstats;
@@ -1943,7 +1944,7 @@ static const iw_handler wl3501_handler[] = {
static const struct iw_handler_def wl3501_handler_def = {
.num_standard = sizeof(wl3501_handler) / sizeof(iw_handler),
.standard = (iw_handler *)wl3501_handler,
- .spy_offset = offsetof(struct wl3501_card, spy_data),
+ .get_wireless_stats = wl3501_get_wireless_stats,
};
/**
@@ -1960,6 +1961,7 @@ static dev_link_t *wl3501_attach(void)
client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
+ struct wl3501_card *this;
int ret;
/* Initialize the dev_link_t structure */
@@ -1994,7 +1996,9 @@ static dev_link_t *wl3501_attach(void)
dev->tx_timeout = wl3501_tx_timeout;
dev->watchdog_timeo = 5 * HZ;
dev->get_stats = wl3501_get_stats;
- dev->get_wireless_stats = wl3501_get_wireless_stats;
+ this = dev->priv;
+ this->wireless_data.spy_data = &this->spy_data;
+ 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);
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 91df0bf181dd..7a57c1b8373f 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -215,7 +215,7 @@ static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 va
#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
-static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(iosapic_lock);
static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
{
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 731855053392..cb84a4e84a2f 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm.h>
-#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 694bae162fed..5b887ba5aaf9 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -196,7 +196,7 @@ int parport_wait_peripheral(struct parport *port,
return 1;
/* 40ms of slow polling. */
- deadline = jiffies + (HZ + 24) / 25;
+ deadline = jiffies + msecs_to_jiffies(40);
while (time_before (jiffies, deadline)) {
int ret;
@@ -205,7 +205,7 @@ int parport_wait_peripheral(struct parport *port,
/* Wait for 10ms (or until an interrupt occurs if
* the handler is set) */
- if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)
+ if ((ret = parport_wait_event (port, msecs_to_jiffies(10))) < 0)
return ret;
status = parport_read_status (port);
@@ -216,8 +216,7 @@ int parport_wait_peripheral(struct parport *port,
/* parport_wait_event didn't time out, but the
* peripheral wasn't actually ready either.
* Wait for another 10ms. */
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ+ 99) / 100);
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
}
}
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index 6624278c6ed8..ce1e2aad8b10 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -60,7 +60,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
parport_data_forward (port);
while (count < len) {
unsigned long expire = jiffies + dev->timeout;
- long wait = (HZ + 99) / 100;
+ long wait = msecs_to_jiffies(10);
unsigned char mask = (PARPORT_STATUS_ERROR
| PARPORT_STATUS_BUSY);
unsigned char val = (PARPORT_STATUS_ERROR
@@ -97,8 +97,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
our interrupt handler called. */
if (count && no_irq) {
parport_release (dev);
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout (wait);
+ schedule_timeout_interruptible(wait);
parport_claim_or_block (dev);
}
else
@@ -542,13 +541,12 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
/* Yield the port for a while. */
if (count && dev->port->irq != PARPORT_IRQ_NONE) {
parport_release (dev);
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ + 24) / 25);
+ schedule_timeout_interruptible(msecs_to_jiffies(40));
parport_claim_or_block (dev);
}
else
/* We must have the device claimed here. */
- parport_wait_event (port, (HZ + 24) / 25);
+ parport_wait_event (port, msecs_to_jiffies(40));
/* Is there a signal pending? */
if (signal_pending (current))
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 4598c6a9212d..c6493ad7c0c8 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -173,8 +173,7 @@ static int change_mode(struct parport *p, int m)
if (time_after_eq (jiffies, expire))
/* The FIFO is stuck. */
return -EBUSY;
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ + 99) / 100);
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
if (signal_pending (current))
break;
}
@@ -2739,6 +2738,7 @@ enum parport_pc_pci_cards {
syba_2p_epp,
syba_1p_ecp,
titan_010l,
+ titan_1284p1,
titan_1284p2,
avlab_1p,
avlab_2p,
@@ -2811,6 +2811,7 @@ static struct parport_pc_pci {
/* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } },
/* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } },
/* titan_010l */ { 1, { { 3, -1 }, } },
+ /* titan_1284p1 */ { 1, { { 0, 1 }, } },
/* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } },
/* avlab_1p */ { 1, { { 0, 1}, } },
/* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} },
@@ -2884,6 +2885,7 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+ { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 },
{ 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */
@@ -3007,7 +3009,7 @@ static int __init parport_pc_init_superio (int autoirq, int autodma)
struct pci_dev *pdev = NULL;
int ret = 0;
- while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+ for_each_pci_dev(pdev) {
id = pci_match_id(parport_pc_pci_tbl, pdev);
if (id == NULL || id->driver_data >= last_sio)
continue;
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 00498e2f1205..d3dad0aac7cb 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -23,13 +23,8 @@
#include <linux/pci.h>
#include <linux/parport.h>
#include <linux/parport_pc.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/list.h>
#include <linux/8250_pci.h>
-#include <asm/serial.h>
-
enum parport_pc_pci_cards {
titan_110l = 0,
titan_210l,
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
-struct pci_board_no_ids {
- int flags;
- int num_ports;
- int base_baud;
- int uart_offset;
- int reg_shift;
- int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
- int enable);
- int first_uart_offset;
-};
-
-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- return pci_siig10x_fn(dev, enable);
-}
-
-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- return pci_siig20x_fn(dev, enable);
-}
-
-static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- board->num_ports = dev->subsystem_device & 0xf;
- return 0;
-}
-
-static struct pci_board_no_ids pci_boards[] __devinitdata = {
- /*
- * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
- * Offset to get to next UART's registers,
- * Register shift to use for memory-mapped I/O,
- * Initialization function, first UART offset
- */
-
-// Cards not tested are marked n/t
-// If you have one of these cards and it works for you, please tell me..
-
-/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
-/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* siig_1s1p_10x */ { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
-/* siig_2s1p_10x */ { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
-/* siig_2p1s_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_1s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_2s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/*
+ * This table describes the serial "geometry" of these boards. Any
+ * quirks for these can be found in drivers/serial/8250_pci.c
+ *
+ * Cards not tested are marked n/t
+ * If you have one of these cards and it works for you, please tell me..
+ */
+static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
+ [titan_110l] = {
+ .flags = FL_BASE1 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [titan_210l] = {
+ .flags = FL_BASE1 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [netmos_9xx5_combo] = {
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_9855] = {
+ .flags = FL_BASE2 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [siig_1s1p_10x] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [siig_2s1p_10x] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_2p1s_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_1s1p_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_2s1p_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
};
struct parport_serial_private {
- int num_ser;
- int line[20];
- struct pci_board_no_ids ser;
+ struct serial_private *serial;
int num_par;
struct parport *port[PARPORT_MAX];
struct parport_pc_pci par;
};
-static int __devinit get_pci_port (struct pci_dev *dev,
- struct pci_board_no_ids *board,
- struct serial_struct *req,
- int idx)
-{
- unsigned long port;
- int base_idx;
- int max_port;
- int offset;
-
- base_idx = SPCI_FL_GET_BASE(board->flags);
- if (board->flags & SPCI_FL_BASE_TABLE)
- base_idx += idx;
-
- if (board->flags & SPCI_FL_REGION_SZ_CAP) {
- max_port = pci_resource_len(dev, base_idx) / 8;
- if (idx >= max_port)
- return 1;
- }
-
- offset = board->first_uart_offset;
-
- /* Timedia/SUNIX uses a mixture of BARs and offsets */
- /* Ugh, this is ugly as all hell --- TYT */
- if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
- switch(idx) {
- case 0: base_idx=0;
- break;
- case 1: base_idx=0; offset=8;
- break;
- case 2: base_idx=1;
- break;
- case 3: base_idx=1; offset=8;
- break;
- case 4: /* BAR 2*/
- case 5: /* BAR 3 */
- case 6: /* BAR 4*/
- case 7: base_idx=idx-2; /* BAR 5*/
- }
-
- port = pci_resource_start(dev, base_idx) + offset;
-
- if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
- port += idx * (board->uart_offset ? board->uart_offset : 8);
-
- if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
- int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
- req->port = port;
- if (high_bits_offset)
- req->port_high = port >> high_bits_offset;
- else
- req->port_high = 0;
- return 0;
- }
- req->io_type = SERIAL_IO_MEM;
- req->iomem_base = ioremap(port, board->uart_offset);
- req->iomem_reg_shift = board->reg_shift;
- req->port = 0;
- return req->iomem_base ? 0 : 1;
-}
-
/* Register the serial port(s) of a PCI card. */
static int __devinit serial_register (struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct pci_board_no_ids *board;
struct parport_serial_private *priv = pci_get_drvdata (dev);
- struct serial_struct serial_req;
- int base_baud;
- int k;
- int success = 0;
-
- priv->ser = pci_boards[id->driver_data];
- board = &priv->ser;
- if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
- return 1;
-
- base_baud = board->base_baud;
- if (!base_baud)
- base_baud = BASE_BAUD;
- memset (&serial_req, 0, sizeof (serial_req));
-
- for (k = 0; k < board->num_ports; k++) {
- int line;
+ struct pciserial_board *board;
+ struct serial_private *serial;
- if (priv->num_ser == ARRAY_SIZE (priv->line)) {
- printk (KERN_WARNING
- "parport_serial: %s: only %u serial lines "
- "supported (%d reported)\n", pci_name (dev),
- ARRAY_SIZE (priv->line), board->num_ports);
- break;
- }
+ board = &pci_parport_serial_boards[id->driver_data];
+ serial = pciserial_init_ports(dev, board);
- serial_req.irq = dev->irq;
- if (get_pci_port (dev, board, &serial_req, k))
- break;
- serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
- serial_req.baud_base = base_baud;
- line = register_serial (&serial_req);
- if (line < 0) {
- printk (KERN_DEBUG
- "parport_serial: register_serial failed\n");
- continue;
- }
- priv->line[priv->num_ser++] = line;
- success = 1;
- }
+ if (IS_ERR(serial))
+ return PTR_ERR(serial);
- return success ? 0 : 1;
+ priv->serial = serial;
+ return 0;
}
/* Register the parallel port(s) of a PCI card. */
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
priv = kmalloc (sizeof *priv, GFP_KERNEL);
if (!priv)
return -ENOMEM;
- priv->num_ser = priv->num_par = 0;
+ memset(priv, 0, sizeof(struct parport_serial_private));
pci_set_drvdata (dev, priv);
err = pci_enable_device (dev);
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
struct parport_serial_private *priv = pci_get_drvdata (dev);
int i;
+ pci_set_drvdata(dev, NULL);
+
// Serial ports
- for (i = 0; i < priv->num_ser; i++) {
- unregister_serial (priv->line[i]);
+ if (priv->serial)
+ pciserial_remove_ports(priv->serial);
- if (priv->ser.init_fn)
- (priv->ser.init_fn) (dev, &priv->ser, 0);
- }
- pci_set_drvdata (dev, NULL);
-
// Parallel ports
for (i = 0; i < priv->num_par; i++)
parport_pc_unregister_port (priv->port[i]);
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
return;
}
+static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+ if (priv->serial)
+ pciserial_suspend_ports(priv->serial);
+
+ /* FIXME: What about parport? */
+
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ return 0;
+}
+
+static int parport_serial_pci_resume(struct pci_dev *dev)
+{
+ struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ /*
+ * The device may have been disabled. Re-enable it.
+ */
+ pci_enable_device(dev);
+
+ if (priv->serial)
+ pciserial_resume_ports(priv->serial);
+
+ /* FIXME: What about parport? */
+
+ return 0;
+}
+
static struct pci_driver parport_serial_pci_driver = {
.name = "parport_serial",
.id_table = parport_serial_pci_tbl,
.probe = parport_serial_pci_probe,
.remove = __devexit_p(parport_serial_pci_remove),
+ .suspend = parport_serial_pci_suspend,
+ .resume = parport_serial_pci_resume,
};
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7f31991772ea..f187fd8aeed6 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -30,23 +30,6 @@ config PCI_LEGACY_PROC
When in doubt, say N.
-config PCI_NAMES
- bool "PCI device name database"
- depends on PCI
- ---help---
- By default, the kernel contains a database of all known PCI device
- names to make the information in /proc/pci, /proc/ioports and
- similar files comprehensible to the user.
-
- This database increases size of the kernel image by about 80KB. This
- memory is freed after the system boots up if CONFIG_HOTPLUG is not set.
-
- Anyway, if you are building an installation floppy or kernel for an
- embedded system where kernel image size really matters, you can disable
- this feature and you'll get device ID numbers instead of names.
-
- When in doubt, say Y.
-
config PCI_DEBUG
bool "PCI Debugging"
depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 3657f6199c48..716df015f8d0 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -3,14 +3,9 @@
#
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
- names.o pci-driver.o search.o pci-sysfs.o \
- rom.o
+ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
obj-$(CONFIG_PROC_FS) += proc.o
-ifndef CONFIG_SPARC64
-obj-y += setup-res.o
-endif
-
obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to
@@ -46,21 +41,6 @@ ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-hostprogs-y := gen-devlist
-
-# Dependencies on generated files need to be listed explicitly
-$(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h
-$(obj)/classlist.h: $(obj)/devlist.h
-
-# And that's how to generate them
-quiet_cmd_devlist = DEVLIST $@
- cmd_devlist = ( cd $(obj); ./gen-devlist ) < $<
-$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
- $(call cmd,devlist)
-
-# Files generated that shall be removed upon make clean
-clean-files := devlist.h classlist.h
-
# Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index fb9a11243d2a..eed67d9e73bc 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -140,16 +140,65 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
void pci_enable_bridges(struct pci_bus *bus)
{
struct pci_dev *dev;
+ int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->subordinate) {
- pci_enable_device(dev);
+ retval = pci_enable_device(dev);
pci_set_master(dev);
pci_enable_bridges(dev->subordinate);
}
}
}
+/** pci_walk_bus - walk devices on/under bus, calling callback.
+ * @top bus whose devices should be walked
+ * @cb callback to be called for each device found
+ * @userdata arbitrary pointer to be passed to callback.
+ *
+ * Walk the given bus, including any bridged devices
+ * on buses under this bus. Call the provided callback
+ * on each device found.
+ */
+void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+ void *userdata)
+{
+ struct pci_dev *dev;
+ struct pci_bus *bus;
+ struct list_head *next;
+
+ bus = top;
+ spin_lock(&pci_bus_lock);
+ next = top->devices.next;
+ for (;;) {
+ if (next == &bus->devices) {
+ /* end of this bus, go up or finish */
+ if (bus == top)
+ break;
+ next = bus->self->bus_list.next;
+ bus = bus->self->bus;
+ continue;
+ }
+ dev = list_entry(next, struct pci_dev, bus_list);
+ pci_dev_get(dev);
+ if (dev->subordinate) {
+ /* this is a pci-pci bridge, do its devices next */
+ next = dev->subordinate->devices.next;
+ bus = dev->subordinate;
+ } else
+ next = dev->bus_list.next;
+ spin_unlock(&pci_bus_lock);
+
+ /* Run device routines with the bus unlocked */
+ cb(dev, userdata);
+
+ spin_lock(&pci_bus_lock);
+ pci_dev_put(dev);
+ }
+ spin_unlock(&pci_bus_lock);
+}
+EXPORT_SYMBOL_GPL(pci_walk_bus);
+
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices);
diff --git a/drivers/pci/gen-devlist.c b/drivers/pci/gen-devlist.c
deleted file mode 100644
index 8abfc499fdef..000000000000
--- a/drivers/pci/gen-devlist.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Generate devlist.h and classlist.h from the PCI ID file.
- *
- * (c) 1999--2002 Martin Mares <mj@ucw.cz>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define MAX_NAME_SIZE 200
-
-static void
-pq(FILE *f, const char *c, int len)
-{
- int i = 1;
- while (*c && i != len) {
- if (*c == '"')
- fprintf(f, "\\\"");
- else {
- fputc(*c, f);
- if (*c == '?' && c[1] == '?') {
- /* Avoid trigraphs */
- fprintf(f, "\" \"");
- }
- }
- c++;
- i++;
- }
-}
-
-int
-main(void)
-{
- char line[1024], *c, *bra, vend[8];
- int vendors = 0;
- int mode = 0;
- int lino = 0;
- int vendor_len = 0;
- FILE *devf, *clsf;
-
- devf = fopen("devlist.h", "w");
- clsf = fopen("classlist.h", "w");
- if (!devf || !clsf) {
- fprintf(stderr, "Cannot create output file!\n");
- return 1;
- }
-
- while (fgets(line, sizeof(line)-1, stdin)) {
- lino++;
- if ((c = strchr(line, '\n')))
- *c = 0;
- if (!line[0] || line[0] == '#')
- continue;
- if (line[1] == ' ') {
- if (line[0] == 'C' && strlen(line) > 4 && line[4] == ' ') {
- vend[0] = line[2];
- vend[1] = line[3];
- vend[2] = 0;
- mode = 2;
- } else goto err;
- }
- else if (line[0] == '\t') {
- if (line[1] == '\t')
- continue;
- switch (mode) {
- case 1:
- if (strlen(line) > 5 && line[5] == ' ') {
- c = line + 5;
- while (*c == ' ')
- *c++ = 0;
- if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
- /* Too long, try cutting off long description */
- bra = strchr(c, '[');
- if (bra && bra > c && bra[-1] == ' ')
- bra[-1] = 0;
- if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
- fprintf(stderr, "Line %d: Device name too long. Name truncated.\n", lino);
- fprintf(stderr, "%s\n", c);
- /*return 1;*/
- }
- }
- fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1);
- pq(devf, c, MAX_NAME_SIZE - vendor_len - 1);
- fputs("\")\n", devf);
- } else goto err;
- break;
- case 2:
- if (strlen(line) > 3 && line[3] == ' ') {
- c = line + 3;
- while (*c == ' ')
- *c++ = 0;
- fprintf(clsf, "CLASS(%s%s, \"%s\")\n", vend, line+1, c);
- } else goto err;
- break;
- default:
- goto err;
- }
- } else if (strlen(line) > 4 && line[4] == ' ') {
- c = line + 4;
- while (*c == ' ')
- *c++ = 0;
- if (vendors)
- fputs("ENDVENDOR()\n\n", devf);
- vendors++;
- strcpy(vend, line);
- vendor_len = strlen(c);
- if (vendor_len + 24 > MAX_NAME_SIZE) {
- fprintf(stderr, "Line %d: Vendor name too long\n", lino);
- return 1;
- }
- fprintf(devf, "VENDOR(%s,\"", vend);
- pq(devf, c, 0);
- fputs("\")\n", devf);
- mode = 1;
- } else {
- err:
- fprintf(stderr, "Line %d: Syntax error in mode %d: %s\n", lino, mode, line);
- return 1;
- }
- }
- fputs("ENDVENDOR()\n\
-\n\
-#undef VENDOR\n\
-#undef DEVICE\n\
-#undef ENDVENDOR\n", devf);
- fputs("\n#undef CLASS\n", clsf);
-
- fclose(devf);
- fclose(clsf);
-
- return 0;
-}
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index b844bc972324..10444988a10b 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -20,46 +20,35 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
scratch = buffer;
- /* stuff we want to pass to /sbin/hotplug */
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
- pdev->class);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_CLASS=%04X", pdev->class))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
- pdev->vendor, pdev->device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+ pdev->subsystem_device))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
- pci_name(pdev));
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device,
- (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
- (u8)(pdev->class));
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class)))
return -ENOMEM;
envp[i] = NULL;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 9c4a39ee89b5..2f1289eebb3c 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -78,7 +78,7 @@ config HOTPLUG_PCI_IBM
config HOTPLUG_PCI_ACPI
tristate "ACPI PCI Hotplug driver"
- depends on ACPI_BUS && HOTPLUG_PCI
+ depends on ACPI && HOTPLUG_PCI
help
Say Y here if you have a system that supports PCI Hotplug using
ACPI.
@@ -157,7 +157,7 @@ config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
config HOTPLUG_PCI_SHPC_PHPRM_LEGACY
bool "For AMD SHPC only: Use $HRT for resource/configuration"
- depends on HOTPLUG_PCI_SHPC && !ACPI_BUS
+ depends on HOTPLUG_PCI_SHPC && !ACPI
help
Say Y here for AMD SHPC. You have to select this option if you are
using this driver on platform with AMD SHPC.
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 31a307004b94..3c71e3077ff1 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -41,8 +41,7 @@ acpiphp-objs := acpiphp_core.o \
rpaphp-objs := rpaphp_core.o \
rpaphp_pci.o \
- rpaphp_slot.o \
- rpaphp_vio.o
+ rpaphp_slot.o
rpadlpar_io-objs := rpadlpar_core.o \
rpadlpar_sysfs.o
@@ -51,7 +50,7 @@ pciehp-objs := pciehp_core.o \
pciehp_ctrl.o \
pciehp_pci.o \
pciehp_hpc.o
-ifdef CONFIG_ACPI_BUS
+ifdef CONFIG_ACPI
pciehp-objs += pciehprm_acpi.o
else
pciehp-objs += pciehprm_nonacpi.o
@@ -62,7 +61,7 @@ shpchp-objs := shpchp_core.o \
shpchp_pci.o \
shpchp_sysfs.o \
shpchp_hpc.o
-ifdef CONFIG_ACPI_BUS
+ifdef CONFIG_ACPI
shpchp-objs += shpchprm_acpi.o
else
ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 2b92b9e8c910..061ead21ef14 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -302,7 +302,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
- snprintf(buffer, buffer_size, "%d", slot->number);
+ snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
}
enum php_ctlr_type {
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index 305b47ec2f2c..1406db35b089 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -1696,15 +1696,15 @@ void pciehprm_enable_card(
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+ rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+ rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
}
- cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+ command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+ bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA;
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
if (ab) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 86b384e42717..ad1017da8656 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -19,33 +19,36 @@
#include <asm/pci-bridge.h>
#include <asm/semaphore.h>
#include <asm/rtas.h>
+#include <asm/vio.h>
#include "../pci.h"
#include "rpaphp.h"
#include "rpadlpar.h"
static DECLARE_MUTEX(rpadlpar_sem);
+#define DLPAR_MODULE_NAME "rpadlpar_io"
+
#define NODE_TYPE_VIO 1
#define NODE_TYPE_SLOT 2
#define NODE_TYPE_PHB 3
-static struct device_node *find_php_slot_vio_node(char *drc_name)
+static struct device_node *find_vio_slot_node(char *drc_name)
{
- struct device_node *child;
struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
- char *loc_code;
+ struct device_node *dn = NULL;
+ char *name;
+ int rc;
if (!parent)
return NULL;
- for (child = of_get_next_child(parent, NULL);
- child; child = of_get_next_child(parent, child)) {
- loc_code = get_property(child, "ibm,loc-code", NULL);
- if (loc_code && !strncmp(loc_code, drc_name, strlen(drc_name)))
- return child;
+ while ((dn = of_get_next_child(parent, dn))) {
+ rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
+ if ((rc == 0) && (!strcmp(drc_name, name)))
+ break;
}
- return NULL;
+ return dn;
}
/* Find dlpar-capable pci node that contains the specified name and type */
@@ -67,7 +70,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
return np;
}
-static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
+static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
{
struct device_node *dn;
@@ -83,7 +86,7 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
return dn;
}
- dn = find_php_slot_vio_node(drc_name);
+ dn = find_vio_slot_node(drc_name);
if (dn) {
*node_type = NODE_TYPE_VIO;
return dn;
@@ -92,14 +95,14 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
return NULL;
}
-static struct slot *find_slot(char *drc_name)
+static struct slot *find_slot(struct device_node *dn)
{
struct list_head *tmp, *n;
struct slot *slot;
list_for_each_safe(tmp, n, &rpaphp_slot_head) {
slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (strcmp(slot->location, drc_name) == 0)
+ if (slot->dn == dn)
return slot;
}
@@ -131,7 +134,8 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b)
static int pci_add_secondary_bus(struct device_node *dn,
struct pci_dev *bridge_dev)
{
- struct pci_controller *hose = dn->phb;
+ struct pci_dn *pdn = dn->data;
+ struct pci_controller *hose = pdn->phb;
struct pci_bus *child;
u8 sec_busno;
@@ -156,7 +160,7 @@ static int pci_add_secondary_bus(struct device_node *dn,
if (hose->last_busno < child->number)
hose->last_busno = child->number;
- dn->bussubno = child->number;
+ pdn->bussubno = child->number;
/* ioremap() for child bus, which may or may not succeed */
remap_bus_range(child);
@@ -164,13 +168,28 @@ static int pci_add_secondary_bus(struct device_node *dn,
return 0;
}
+static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
+ struct device_node *dev_dn)
+{
+ struct pci_dev *tmp = NULL;
+ struct device_node *child_dn;
+
+ list_for_each_entry(tmp, &parent->devices, bus_list) {
+ child_dn = pci_device_to_OF_node(tmp);
+ if (child_dn == dev_dn)
+ return tmp;
+ }
+ return NULL;
+}
+
static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
{
- struct pci_controller *hose = dn->phb;
+ struct pci_dn *pdn = dn->data;
+ struct pci_controller *hose = pdn->phb;
struct pci_dev *dev = NULL;
/* Scan phb bus for EADS device, adding new one to bus->devices */
- if (!pci_scan_single_device(hose->bus, dn->devfn)) {
+ if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
return NULL;
}
@@ -179,49 +198,28 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
pci_bus_add_devices(hose->bus);
/* Confirm new bridge dev was created */
- dev = rpaphp_find_pci_dev(dn);
- if (!dev) {
- printk(KERN_ERR "%s: failed to add pci device\n", __FUNCTION__);
- return NULL;
- }
+ dev = dlpar_find_new_dev(hose->bus, dn);
+ if (dev) {
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ printk(KERN_ERR "%s: unexpected header type %d\n",
+ __FUNCTION__, dev->hdr_type);
+ return NULL;
+ }
- if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
- printk(KERN_ERR "%s: unexpected header type %d\n",
- __FUNCTION__, dev->hdr_type);
- return NULL;
+ if (pci_add_secondary_bus(dn, dev))
+ return NULL;
}
- if (pci_add_secondary_bus(dn, dev))
- return NULL;
-
return dev;
}
-static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
+static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
{
- struct pci_bus *secondary_bus;
+ struct pci_dev *dev;
+ int rc;
- if (!bridge_dev) {
- printk(KERN_ERR "%s: unexpected null device\n",
- __FUNCTION__);
+ if (rpaphp_find_pci_bus(dn))
return -EINVAL;
- }
-
- secondary_bus = bridge_dev->subordinate;
-
- if (unmap_bus_range(secondary_bus)) {
- printk(KERN_ERR "%s: failed to unmap bus range\n",
- __FUNCTION__);
- return -ERANGE;
- }
-
- pci_remove_bus_device(bridge_dev);
- return 0;
-}
-
-static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
-{
- struct pci_dev *dev;
/* Add pci bus */
dev = dlpar_pci_add_bus(dn);
@@ -231,6 +229,21 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
return -EIO;
}
+ if (dn->child) {
+ rc = rpaphp_config_pci_adapter(dev->subordinate);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: unable to enable slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
+ }
+
+ /* Add hotplug slot */
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
return 0;
}
@@ -255,47 +268,69 @@ static int dlpar_remove_root_bus(struct pci_controller *phb)
return 0;
}
-static int dlpar_remove_phb(struct slot *slot)
+static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
{
- struct pci_controller *phb;
- struct device_node *dn;
+ struct slot *slot;
+ struct pci_dn *pdn;
int rc = 0;
- dn = slot->dn;
- if (!dn) {
- printk(KERN_ERR "%s: unexpected NULL slot device node\n",
- __FUNCTION__);
- return -EIO;
- }
-
- phb = dn->phb;
- if (!phb) {
- printk(KERN_ERR "%s: unexpected NULL phb pointer\n",
- __FUNCTION__);
- return -EIO;
- }
+ if (!rpaphp_find_pci_bus(dn))
+ return -EINVAL;
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, slot->location);
- return -EIO;
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
- rc = dlpar_remove_root_bus(phb);
+ pdn = dn->data;
+ BUG_ON(!pdn || !pdn->phb);
+ rc = dlpar_remove_root_bus(pdn->phb);
if (rc < 0)
return rc;
+ pdn->phb = NULL;
+
return 0;
}
-static int dlpar_add_phb(struct device_node *dn)
+static int dlpar_add_phb(char *drc_name, struct device_node *dn)
{
struct pci_controller *phb;
+ if (PCI_DN(dn)->phb) {
+ /* PHB already exists */
+ return -EINVAL;
+ }
+
phb = init_phb_dynamic(dn);
if (!phb)
+ return -EIO;
+
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
+{
+ if (vio_find_node(dn))
return -EINVAL;
+ if (!vio_register_device_node(dn)) {
+ printk(KERN_ERR
+ "%s: failed to register vio node %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
return 0;
}
@@ -316,18 +351,13 @@ int dlpar_add_slot(char *drc_name)
{
struct device_node *dn = NULL;
int node_type;
- int rc = 0;
+ int rc = -EIO;
if (down_interruptible(&rpadlpar_sem))
return -ERESTARTSYS;
- /* Check for existing hotplug slot */
- if (find_slot(drc_name)) {
- rc = -EINVAL;
- goto exit;
- }
-
- dn = find_newly_added_node(drc_name, &node_type);
+ /* Find newly added node */
+ dn = find_dlpar_node(drc_name, &node_type);
if (!dn) {
rc = -ENODEV;
goto exit;
@@ -335,24 +365,17 @@ int dlpar_add_slot(char *drc_name)
switch (node_type) {
case NODE_TYPE_VIO:
- /* Just add hotplug slot */
+ rc = dlpar_add_vio_slot(drc_name, dn);
break;
case NODE_TYPE_SLOT:
rc = dlpar_add_pci_slot(drc_name, dn);
break;
case NODE_TYPE_PHB:
- rc = dlpar_add_phb(dn);
+ rc = dlpar_add_phb(drc_name, dn);
break;
- default:
- printk("%s: unexpected node type\n", __FUNCTION__);
- return -EIO;
}
- if (!rc && rpaphp_add_slot(dn)) {
- printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
- __FUNCTION__, drc_name);
- rc = -EIO;
- }
+ printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;
@@ -366,17 +389,17 @@ exit:
* of an I/O Slot.
* Return Codes:
* 0 Success
- * -EIO Internal Error
+ * -EINVAL Vio dev doesn't exist
*/
-int dlpar_remove_vio_slot(struct slot *slot, char *drc_name)
+static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
{
- /* Remove hotplug slot */
+ struct vio_dev *vio_dev;
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
- }
+ vio_dev = vio_find_node(dn);
+ if (!vio_dev)
+ return -EINVAL;
+
+ vio_unregister_device(vio_dev);
return 0;
}
@@ -391,31 +414,34 @@ int dlpar_remove_vio_slot(struct slot *slot, char *drc_name)
* -ENODEV Not a valid drc_name
* -EIO Internal PCI Error
*/
-int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
+int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
{
- struct pci_dev *bridge_dev;
+ struct pci_bus *bus;
+ struct slot *slot;
- bridge_dev = slot->bridge;
- if (!bridge_dev) {
- printk(KERN_ERR "%s: unexpected null bridge device\n",
- __FUNCTION__);
- return -EIO;
- }
+ bus = rpaphp_find_pci_bus(dn);
+ if (!bus)
+ return -EINVAL;
- /* Remove hotplug slot */
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
- /* Remove pci bus */
-
- if (dlpar_pci_remove_bus(bridge_dev)) {
- printk(KERN_ERR "%s: unable to remove pci bus %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
+ if (unmap_bus_range(bus)) {
+ printk(KERN_ERR "%s: failed to unmap bus range\n",
+ __FUNCTION__);
+ return -ERANGE;
}
+
+ BUG_ON(!bus->self);
+ pci_remove_bus_device(bus->self);
return 0;
}
@@ -434,38 +460,31 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
*/
int dlpar_remove_slot(char *drc_name)
{
- struct slot *slot;
+ struct device_node *dn;
+ int node_type;
int rc = 0;
if (down_interruptible(&rpadlpar_sem))
return -ERESTARTSYS;
- if (!find_php_slot_vio_node(drc_name) &&
- !find_php_slot_pci_node(drc_name, "SLOT") &&
- !find_php_slot_pci_node(drc_name, "PHB")) {
+ dn = find_dlpar_node(drc_name, &node_type);
+ if (!dn) {
rc = -ENODEV;
goto exit;
}
- slot = find_slot(drc_name);
- if (!slot) {
- rc = -EINVAL;
- goto exit;
- }
-
- if (slot->type == PHB) {
- rc = dlpar_remove_phb(slot);
- } else {
- switch (slot->dev_type) {
- case PCI_DEV:
- rc = dlpar_remove_pci_slot(slot, drc_name);
- break;
-
- case VIO_DEV:
- rc = dlpar_remove_vio_slot(slot, drc_name);
- break;
- }
+ switch (node_type) {
+ case NODE_TYPE_VIO:
+ rc = dlpar_remove_vio_slot(drc_name, dn);
+ break;
+ case NODE_TYPE_PHB:
+ rc = dlpar_remove_phb(drc_name, dn);
+ break;
+ case NODE_TYPE_SLOT:
+ rc = dlpar_remove_pci_slot(drc_name, dn);
+ break;
}
+ printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 81746e6e0e0f..61d94d1e29cb 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -30,10 +30,6 @@
#include <linux/pci.h>
#include "pci_hotplug.h"
-#define PHB 2
-#define HOTPLUG 1
-#define EMBEDDED 0
-
#define DR_INDICATOR 9002
#define DR_ENTITY_SENSE 9003
@@ -61,10 +57,6 @@ extern int debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-/* slot types */
-#define VIO_DEV 1
-#define PCI_DEV 2
-
/* slot states */
#define NOT_VALID 3
@@ -72,11 +64,6 @@ extern int debug;
#define CONFIGURED 1
#define EMPTY 0
-struct rpaphp_pci_func {
- struct pci_dev *pci_dev;
- struct list_head sibling;
-};
-
/*
* struct slot - slot information for each *physical* slot
*/
@@ -88,15 +75,9 @@ struct slot {
u32 power_domain;
char *name;
char *location;
- u8 removable;
- u8 dev_type; /* VIO or PCI */
- struct device_node *dn; /* slot's device_node in OFDT */
- /* dn has phb info */
- struct pci_dev *bridge; /* slot's pci_dev in pci_devices */
- union {
- struct list_head *pci_devs; /* pci_devs in PCI slot */
- struct vio_dev *vio_dev; /* vio_dev in VIO slot */
- } dev;
+ struct device_node *dn;
+ struct pci_bus *bus;
+ struct list_head *pci_devs;
struct hotplug_slot *hotplug_slot;
};
@@ -107,13 +88,13 @@ extern int num_slots;
/* function prototypes */
/* rpaphp_pci.c */
-extern struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn);
+extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
extern int register_pci_slot(struct slot *slot);
extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev);
+extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
/* rpaphp_core.c */
extern int rpaphp_add_slot(struct device_node *dn);
@@ -121,12 +102,6 @@ extern int rpaphp_remove_slot(struct slot *slot);
extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
char **drc_name, char **drc_type, int *drc_power_domain);
-/* rpaphp_vio.c */
-extern int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern int rpaphp_unconfig_vio_adapter(struct slot *slot);
-extern int register_vio_slot(struct device_node *dn);
-extern int rpaphp_enable_vio_slot(struct slot *slot);
-
/* rpaphp_slot.c */
extern void dealloc_slot_struct(struct slot *slot);
extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 29117a3a3287..c830ff0acdc3 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -152,17 +152,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
int retval = 0;
down(&rpaphp_sem);
- /* have to go through this */
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_get_pci_adapter_status(slot, 0, value);
- break;
- case VIO_DEV:
- retval = rpaphp_get_vio_adapter_status(slot, 0, value);
- break;
- default:
- retval = -EINVAL;
- }
+ retval = rpaphp_get_pci_adapter_status(slot, 0, value);
up(&rpaphp_sem);
return retval;
}
@@ -317,34 +307,6 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names,
return 0;
}
-static int is_dr_dn(struct device_node *dn, int **indexes, int **names,
- int **types, int **power_domains, int **my_drc_index)
-{
- int rc;
-
- *my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL);
- if(!*my_drc_index)
- return (0);
-
- if (!dn->parent)
- return (0);
-
- rc = get_children_props(dn->parent, indexes, names, types,
- power_domains);
- return (rc >= 0);
-}
-
-static inline int is_vdevice_root(struct device_node *dn)
-{
- return !strcmp(dn->name, "vdevice");
-}
-
-int is_dlpar_type(const char *type_str)
-{
- /* Only register DLPAR-capable nodes of drc-type PHB or SLOT */
- return (!strcmp(type_str, "PHB") || !strcmp(type_str, "SLOT"));
-}
-
/****************************************************************
* rpaphp not only registers PCI hotplug slots(HOTPLUG),
* but also logical DR slots(EMBEDDED).
@@ -356,54 +318,33 @@ int rpaphp_add_slot(struct device_node *dn)
{
struct slot *slot;
int retval = 0;
- int i, *my_drc_index, slot_type;
+ int i;
int *indexes, *names, *types, *power_domains;
char *name, *type;
dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
- if (dn->parent && is_vdevice_root(dn->parent)) {
- /* register a VIO device */
- retval = register_vio_slot(dn);
- goto exit;
- }
-
/* register PCI devices */
if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
- if (is_php_dn(dn, &indexes, &names, &types, &power_domains))
- slot_type = HOTPLUG;
- else if (is_dr_dn(dn, &indexes, &names, &types, &power_domains, &my_drc_index))
- slot_type = EMBEDDED;
- else goto exit;
+ if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+ goto exit;
name = (char *) &names[1];
type = (char *) &types[1];
for (i = 0; i < indexes[0]; i++,
- name += (strlen(name) + 1), type += (strlen(type) + 1)) {
-
- if (slot_type == HOTPLUG ||
- (slot_type == EMBEDDED &&
- indexes[i + 1] == my_drc_index[0] &&
- is_dlpar_type(type))) {
- if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
- power_domains[i + 1]))) {
- retval = -ENOMEM;
- goto exit;
- }
- if (!strcmp(type, "PHB"))
- slot->type = PHB;
- else if (slot_type == EMBEDDED)
- slot->type = EMBEDDED;
- else
- slot->type = simple_strtoul(type, NULL, 10);
+ name += (strlen(name) + 1), type += (strlen(type) + 1)) {
+
+ if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
+ power_domains[i + 1]))) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ slot->type = simple_strtoul(type, NULL, 10);
- dbg(" Found drc-index:0x%x drc-name:%s drc-type:%s\n",
+ dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
indexes[i + 1], name, type);
- retval = register_pci_slot(slot);
- if (slot_type == EMBEDDED)
- goto exit;
- }
+ retval = register_pci_slot(slot);
}
}
exit:
@@ -412,31 +353,6 @@ exit:
return retval;
}
-/*
- * init_slots - initialize 'struct slot' structures for each slot
- *
- */
-static void init_slots(void)
-{
- struct device_node *dn;
-
- for (dn = find_all_nodes(); dn; dn = dn->next)
- rpaphp_add_slot(dn);
-}
-
-static int __init init_rpa(void)
-{
-
- init_MUTEX(&rpaphp_sem);
-
- /* initialize internal data structure etc. */
- init_slots();
- if (!num_slots)
- return -ENODEV;
-
- return 0;
-}
-
static void __exit cleanup_slots(void)
{
struct list_head *tmp, *n;
@@ -458,10 +374,18 @@ static void __exit cleanup_slots(void)
static int __init rpaphp_init(void)
{
+ struct device_node *dn = NULL;
+
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ init_MUTEX(&rpaphp_sem);
- /* read all the PRA info from the system */
- return init_rpa();
+ while ((dn = of_find_node_by_type(dn, "pci")))
+ rpaphp_add_slot(dn);
+
+ if (!num_slots)
+ return -ENODEV;
+
+ return 0;
}
static void __exit rpaphp_exit(void)
@@ -481,16 +405,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
dbg("ENABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_enable_pci_slot(slot);
- break;
- case VIO_DEV:
- retval = rpaphp_enable_vio_slot(slot);
- break;
- default:
- retval = -EINVAL;
- }
+ retval = rpaphp_enable_pci_slot(slot);
up(&rpaphp_sem);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
@@ -511,16 +426,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
dbg("DISABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_unconfig_pci_adapter(slot);
- break;
- case VIO_DEV:
- retval = rpaphp_unconfig_vio_adapter(slot);
- break;
- default:
- retval = -ENODEV;
- }
+ retval = rpaphp_unconfig_pci_adapter(slot);
up(&rpaphp_sem);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index d8305a935aab..49e4d10a6488 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -30,22 +30,35 @@
#include "rpaphp.h"
-struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
+static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
+ struct device_node *dn)
{
- struct pci_dev *dev = NULL;
- char bus_id[BUS_ID_SIZE];
+ struct pci_bus *child = NULL;
+ struct list_head *tmp;
+ struct device_node *busdn;
+
+ busdn = pci_bus_to_OF_node(bus);
+ if (busdn == dn)
+ return bus;
- sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number,
- dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn));
- for_each_pci_dev(dev) {
- if (!strcmp(pci_name(dev), bus_id)) {
+ list_for_each(tmp, &bus->children) {
+ child = find_bus_among_children(pci_bus_b(tmp), dn);
+ if (child)
break;
- }
}
- return dev;
+ return child;
}
-EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev);
+struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
+{
+ struct pci_dn *pdn = dn->data;
+
+ if (!pdn || !pdn->phb || !pdn->phb->bus)
+ return NULL;
+
+ return find_bus_among_children(pdn->phb->bus, dn);
+}
+EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
int rpaphp_claim_resource(struct pci_dev *dev, int resource)
{
@@ -69,11 +82,6 @@ int rpaphp_claim_resource(struct pci_dev *dev, int resource)
EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
-static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
-{
- return rpaphp_find_pci_dev(slot->dn);
-}
-
static int rpaphp_get_sensor_state(struct slot *slot, int *state)
{
int rc;
@@ -116,39 +124,27 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state)
*/
int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
{
+ struct pci_bus *bus;
int state, rc;
- struct device_node *child_dn;
- struct pci_dev *child_dev = NULL;
*value = NOT_VALID;
rc = rpaphp_get_sensor_state(slot, &state);
if (rc)
goto exit;
- if ((state == EMPTY) || (slot->type == PHB)) {
- dbg("slot is empty\n");
+ if (state == EMPTY)
*value = EMPTY;
- }
else if (state == PRESENT) {
if (!is_init) {
/* at run-time slot->state can be changed by */
/* config/unconfig adapter */
*value = slot->state;
} else {
- child_dn = slot->dn->child;
- if (child_dn)
- child_dev = rpaphp_find_pci_dev(child_dn);
-
- if (child_dev)
- *value = CONFIGURED;
- else if (!child_dn)
- dbg("%s: %s is not valid OFDT node\n",
- __FUNCTION__, slot->dn->full_name);
- else {
- err("%s: can't find pdev of adapter in slot[%s]\n",
- __FUNCTION__, slot->dn->full_name);
+ bus = rpaphp_find_pci_bus(slot->dn);
+ if (bus && !list_empty(&bus->devices))
+ *value = CONFIGURED;
+ else
*value = NOT_CONFIGURED;
- }
}
}
exit:
@@ -186,39 +182,6 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
}
}
-static int rpaphp_pci_config_bridge(struct pci_dev *dev);
-
-/*****************************************************************************
- rpaphp_pci_config_slot() will configure all devices under the
- given slot->dn and return the the first pci_dev.
- *****************************************************************************/
-static struct pci_dev *
-rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus)
-{
- struct device_node *eads_first_child = dn->child;
- struct pci_dev *dev = NULL;
- int num;
-
- dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
-
- if (eads_first_child) {
- /* pci_scan_slot should find all children of EADs */
- num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0));
- if (num) {
- rpaphp_fixup_new_pci_devices(bus, 1);
- pci_bus_add_devices(bus);
- }
- dev = rpaphp_find_pci_dev(eads_first_child);
- if (!dev) {
- err("No new device found\n");
- return NULL;
- }
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- rpaphp_pci_config_bridge(dev);
- }
- return dev;
-}
-
static int rpaphp_pci_config_bridge(struct pci_dev *dev)
{
u8 sec_busno;
@@ -252,6 +215,42 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev)
return 0;
}
+/*****************************************************************************
+ rpaphp_pci_config_slot() will configure all devices under the
+ given slot->dn and return the the first pci_dev.
+ *****************************************************************************/
+static struct pci_dev *
+rpaphp_pci_config_slot(struct pci_bus *bus)
+{
+ struct device_node *dn = pci_bus_to_OF_node(bus);
+ struct pci_dev *dev = NULL;
+ int slotno;
+ int num;
+
+ dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
+ if (!dn || !dn->child)
+ return NULL;
+
+ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+
+ /* pci_scan_slot should find all children */
+ num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+ if (num) {
+ rpaphp_fixup_new_pci_devices(bus, 1);
+ pci_bus_add_devices(bus);
+ }
+ if (list_empty(&bus->devices)) {
+ err("%s: No new device found\n", __FUNCTION__);
+ return NULL;
+ }
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ rpaphp_pci_config_bridge(dev);
+ }
+
+ return dev;
+}
+
static void enable_eeh(struct device_node *dn)
{
struct device_node *sib;
@@ -263,49 +262,44 @@ static void enable_eeh(struct device_node *dn)
}
-static void print_slot_pci_funcs(struct slot *slot)
+static void print_slot_pci_funcs(struct pci_bus *bus)
{
+ struct device_node *dn;
struct pci_dev *dev;
- if (slot->dev_type == PCI_DEV) {
- dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
- list_for_each_entry (dev, slot->dev.pci_devs, bus_list)
- dbg("\t%s\n", pci_name(dev));
- }
+ dn = pci_bus_to_OF_node(bus);
+ if (!dn)
+ return;
+
+ dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
+ list_for_each_entry (dev, &bus->devices, bus_list)
+ dbg("\t%s\n", pci_name(dev));
return;
}
-static int rpaphp_config_pci_adapter(struct slot *slot)
+int rpaphp_config_pci_adapter(struct pci_bus *bus)
{
- struct pci_bus *pci_bus;
+ struct device_node *dn = pci_bus_to_OF_node(bus);
struct pci_dev *dev;
int rc = -ENODEV;
- dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
-
- if (slot->bridge) {
+ dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
+ if (!dn)
+ goto exit;
- pci_bus = slot->bridge->subordinate;
- if (!pci_bus) {
- err("%s: can't find bus structure\n", __FUNCTION__);
- goto exit;
- }
- enable_eeh(slot->dn);
- dev = rpaphp_pci_config_slot(slot->dn, pci_bus);
- if (!dev) {
- err("%s: can't find any devices.\n", __FUNCTION__);
- goto exit;
- }
- print_slot_pci_funcs(slot);
- rc = 0;
- } else {
- /* slot is not enabled */
- err("slot doesn't have pci_dev structure\n");
+ enable_eeh(dn);
+ dev = rpaphp_pci_config_slot(bus);
+ if (!dev) {
+ err("%s: can't find any devices.\n", __FUNCTION__);
+ goto exit;
}
+ print_slot_pci_funcs(bus);
+ rc = 0;
exit:
dbg("Exit %s: rc=%d\n", __FUNCTION__, rc);
return rc;
}
+EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
{
@@ -327,13 +321,14 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
int rpaphp_unconfig_pci_adapter(struct slot *slot)
{
- struct pci_dev *dev;
+ struct pci_dev *dev, *tmp;
int retval = 0;
- list_for_each_entry(dev, slot->dev.pci_devs, bus_list)
+ list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
rpaphp_eeh_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
+ }
- pci_remove_behind_bridge(slot->bridge);
slot->state = NOT_CONFIGURED;
info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
slot->name);
@@ -356,66 +351,41 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
return 0;
}
-static int set_phb_slot_name(struct slot *slot)
+static void set_slot_name(struct slot *slot)
{
- struct device_node *dn;
- struct pci_controller *phb;
- struct pci_bus *bus;
-
- dn = slot->dn;
- if (!dn) {
- return -EINVAL;
- }
- phb = dn->phb;
- if (!phb) {
- return -EINVAL;
- }
- bus = phb->bus;
- if (!bus) {
- return -EINVAL;
- }
+ struct pci_bus *bus = slot->bus;
+ struct pci_dev *bridge;
- sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus),
- bus->number, 0, 0);
- return 0;
+ bridge = bus->self;
+ if (bridge)
+ strcpy(slot->name, pci_name(bridge));
+ else
+ sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
+ bus->number);
}
static int setup_pci_slot(struct slot *slot)
{
+ struct device_node *dn = slot->dn;
struct pci_bus *bus;
- int rc;
- if (slot->type == PHB) {
- rc = set_phb_slot_name(slot);
- if (rc < 0) {
- err("%s: failed to set phb slot name\n", __FUNCTION__);
- goto exit_rc;
- }
- } else {
- slot->bridge = rpaphp_find_bridge_pdev(slot);
- if (!slot->bridge) {
- /* slot being added doesn't have pci_dev yet */
- err("%s: no pci_dev for bridge dn %s\n",
- __FUNCTION__, slot->name);
- goto exit_rc;
- }
-
- bus = slot->bridge->subordinate;
- if (!bus)
- goto exit_rc;
- slot->dev.pci_devs = &bus->devices;
-
- dbg("%s set slot->name to %s\n", __FUNCTION__,
- pci_name(slot->bridge));
- strcpy(slot->name, pci_name(slot->bridge));
+ BUG_ON(!dn);
+ bus = rpaphp_find_pci_bus(dn);
+ if (!bus) {
+ err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
+ goto exit_rc;
}
+ slot->bus = bus;
+ slot->pci_devs = &bus->devices;
+ set_slot_name(slot);
+
/* find slot's pci_dev if it's not empty */
if (slot->hotplug_slot->info->adapter_status == EMPTY) {
slot->state = EMPTY; /* slot is empty */
} else {
/* slot is occupied */
- if (!(slot->dn->child)) {
+ if (!dn->child) {
/* non-empty slot has to have child */
err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
__FUNCTION__, slot->name);
@@ -425,7 +395,7 @@ static int setup_pci_slot(struct slot *slot)
if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
dbg("%s CONFIGURING pci adapter in slot[%s]\n",
__FUNCTION__, slot->name);
- if (rpaphp_config_pci_adapter(slot)) {
+ if (rpaphp_config_pci_adapter(slot->bus)) {
err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
goto exit_rc;
}
@@ -435,8 +405,8 @@ static int setup_pci_slot(struct slot *slot)
__FUNCTION__, slot->name);
goto exit_rc;
}
- print_slot_pci_funcs(slot);
- if (!list_empty(slot->dev.pci_devs)) {
+ print_slot_pci_funcs(slot->bus);
+ if (!list_empty(slot->pci_devs)) {
slot->state = CONFIGURED;
} else {
/* DLPAR add as opposed to
@@ -454,11 +424,6 @@ int register_pci_slot(struct slot *slot)
{
int rc = -EINVAL;
- slot->dev_type = PCI_DEV;
- if ((slot->type == EMBEDDED) || (slot->type == PHB))
- slot->removable = 0;
- else
- slot->removable = 1;
if (setup_pci_hotplug_slot_info(slot))
goto exit_rc;
if (setup_pci_slot(slot))
@@ -479,7 +444,7 @@ int rpaphp_enable_pci_slot(struct slot *slot)
/* if slot is not empty, enable the adapter */
if (state == PRESENT) {
dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
- retval = rpaphp_config_pci_adapter(slot);
+ retval = rpaphp_config_pci_adapter(slot->bus);
if (!retval) {
slot->state = CONFIGURED;
dbg("%s: PCI devices in slot[%s] has been configured\n",
@@ -502,37 +467,3 @@ exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
}
-
-struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev)
-{
- struct list_head *tmp, *n;
- struct slot *slot;
-
- list_for_each_safe(tmp, n, &rpaphp_slot_head) {
- struct pci_bus *bus;
- struct list_head *ln;
-
- slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (slot->bridge == NULL) {
- if (slot->dev_type == PCI_DEV) {
- printk(KERN_WARNING "PCI slot missing bridge %s %s \n",
- slot->name, slot->location);
- }
- continue;
- }
-
- bus = slot->bridge->subordinate;
- if (!bus) {
- continue; /* should never happen? */
- }
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev == dev)
- return slot->hotplug_slot;
- }
- }
-
- return NULL;
-}
-
-EXPORT_SYMBOL_GPL(rpaphp_find_hotplug_slot);
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index ff2cbf0652d8..0e8815495083 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -30,35 +30,6 @@
#include <asm/rtas.h>
#include "rpaphp.h"
-static ssize_t removable_read_file (struct hotplug_slot *php_slot, char *buf)
-{
- u8 value;
- int retval = -ENOENT;
- struct slot *slot = (struct slot *)php_slot->private;
-
- if (!slot)
- return retval;
-
- value = slot->removable;
- retval = sprintf (buf, "%d\n", value);
- return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_removable = {
- .attr = {.name = "phy_removable", .mode = S_IFREG | S_IRUGO},
- .show = removable_read_file,
-};
-
-static void rpaphp_sysfs_add_attr_removable (struct hotplug_slot *slot)
-{
- sysfs_create_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
-}
-
-static void rpaphp_sysfs_remove_attr_removable (struct hotplug_slot *slot)
-{
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
-}
-
static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
{
char *value;
@@ -176,9 +147,6 @@ int deregister_slot(struct slot *slot)
/* remove "phy_location" file */
rpaphp_sysfs_remove_attr_location(php_slot);
- /* remove "phy_removable" file */
- rpaphp_sysfs_remove_attr_removable(php_slot);
-
retval = pci_hp_deregister(php_slot);
if (retval)
err("Problem unregistering a slot %s\n", slot->name);
@@ -212,21 +180,13 @@ int register_slot(struct slot *slot)
/* create "phy_locatoin" file */
rpaphp_sysfs_add_attr_location(slot->hotplug_slot);
- /* create "phy_removable" file */
- rpaphp_sysfs_add_attr_removable(slot->hotplug_slot);
-
/* add slot to our internal list */
dbg("%s adding slot[%s] to rpaphp_slot_list\n",
__FUNCTION__, slot->name);
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-
- if (slot->dev_type == VIO_DEV)
- info("Slot [%s](VIO location=%s) registered\n",
- slot->name, slot->location);
- else
- info("Slot [%s](PCI location=%s) registered\n",
- slot->name, slot->location);
+ info("Slot [%s](PCI location=%s) registered\n", slot->name,
+ slot->location);
num_slots++;
return 0;
}
@@ -235,21 +195,17 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value)
{
int rc = 0, level;
- if (slot->type == HOTPLUG) {
- rc = rtas_get_power_level(slot->power_domain, &level);
- if (!rc) {
- dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
- __FUNCTION__, slot->name, slot->power_domain, level);
- *value = level;
- } else
- err("failed to get power-level for slot(%s), rc=0x%x\n",
- slot->location, rc);
- } else {
- dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n",
- __FUNCTION__, slot->location);
- *value = (u8) POWER_ON;
+ rc = rtas_get_power_level(slot->power_domain, &level);
+ if (rc < 0) {
+ err("failed to get power-level for slot(%s), rc=0x%x\n",
+ slot->location, rc);
+ return rc;
}
+ dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
+ __FUNCTION__, slot->name, slot->power_domain, level);
+ *value = level;
+
return rc;
}
diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
deleted file mode 100644
index 74df6a305e64..000000000000
--- a/drivers/pci/hotplug/rpaphp_vio.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * RPA Hot Plug Virtual I/O device functions
- * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <lxie@us.ibm.com>
- *
- */
-#include <asm/vio.h>
-#include "rpaphp.h"
-
-/*
- * get_vio_adapter_status - get the status of a slot
- *
- * status:
- *
- * 1-- adapter is configured
- * 2-- adapter is not configured
- * 3-- not valid
- */
-inline int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 *value)
-{
- *value = slot->state;
- return 0;
-}
-
-int rpaphp_unconfig_vio_adapter(struct slot *slot)
-{
- int retval = 0;
-
- dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
- if (!slot->dev.vio_dev) {
- info("%s: no VIOA in slot[%s]\n", __FUNCTION__, slot->name);
- retval = -EINVAL;
- goto exit;
- }
- /* remove the device from the vio core */
- vio_unregister_device(slot->dev.vio_dev);
- slot->state = NOT_CONFIGURED;
- info("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, slot->name);
-exit:
- dbg("Exit %s, rc=0x%x\n", __FUNCTION__, retval);
- return retval;
-}
-
-static int setup_vio_hotplug_slot_info(struct slot *slot)
-{
- slot->hotplug_slot->info->power_status = 1;
- rpaphp_get_vio_adapter_status(slot, 1,
- &slot->hotplug_slot->info->adapter_status);
- return 0;
-}
-
-int register_vio_slot(struct device_node *dn)
-{
- u32 *index;
- char *name;
- int rc = -EINVAL;
- struct slot *slot = NULL;
-
- rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
- if (rc < 0)
- goto exit_rc;
- index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL);
- if (!index)
- goto exit_rc;
- if (!(slot = alloc_slot_struct(dn, *index, name, 0))) {
- rc = -ENOMEM;
- goto exit_rc;
- }
- slot->dev_type = VIO_DEV;
- slot->dev.vio_dev = vio_find_node(dn);
- if (slot->dev.vio_dev) {
- /*
- * rpaphp is the only owner of vio devices and
- * does not need extra reference taken by
- * vio_find_node
- */
- put_device(&slot->dev.vio_dev->dev);
- } else
- slot->dev.vio_dev = vio_register_device_node(dn);
- if (slot->dev.vio_dev)
- slot->state = CONFIGURED;
- else
- slot->state = NOT_CONFIGURED;
- if (setup_vio_hotplug_slot_info(slot))
- goto exit_rc;
- strcpy(slot->name, slot->dev.vio_dev->dev.bus_id);
- info("%s: registered VIO device[name=%s vio_dev=%p]\n",
- __FUNCTION__, slot->name, slot->dev.vio_dev);
- rc = register_slot(slot);
-exit_rc:
- if (rc && slot)
- dealloc_slot_struct(slot);
- return (rc);
-}
-
-int rpaphp_enable_vio_slot(struct slot *slot)
-{
- int retval = 0;
-
- if ((slot->dev.vio_dev = vio_register_device_node(slot->dn))) {
- info("%s: VIO adapter %s in slot[%s] has been configured\n",
- __FUNCTION__, slot->dn->name, slot->name);
- slot->state = CONFIGURED;
- } else {
- info("%s: no vio_dev struct for adapter in slot[%s]\n",
- __FUNCTION__, slot->name);
- slot->state = NOT_CONFIGURED;
- }
-
- return retval;
-}
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 323041fd41dc..b1409441c1cd 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -32,14 +32,15 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
-#define PCIIO_ASIC_TYPE_TIOCA 4
-#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
-#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
-#define PCI_L1_ERR 7 /* L1 console command error */
-#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
-#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
-#define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */
-#define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */
+#define PCIIO_ASIC_TYPE_TIOCA 4
+#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
+#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
+#define PCI_L1_ERR 7 /* L1 console command error */
+#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
+#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
+#define SN_MAX_HP_SLOTS 32 /* max hotplug slots */
+#define SGI_HOTPLUG_PROM_REV 0x0430 /* Min. required PROM version */
+#define SN_SLOT_NAME_SIZE 33 /* size of name string */
/* internal list head */
static struct list_head sn_hp_list;
@@ -51,6 +52,7 @@ struct slot {
/* this struct for glue internal only */
struct hotplug_slot *hotplug_slot;
struct list_head hp_list;
+ char physical_path[SN_SLOT_NAME_SIZE];
};
struct pcibr_slot_enable_resp {
@@ -70,7 +72,7 @@ enum sn_pci_req_e {
static int enable_slot(struct hotplug_slot *slot);
static int disable_slot(struct hotplug_slot *slot);
-static int get_power_status(struct hotplug_slot *slot, u8 *value);
+static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
static struct hotplug_slot_ops sn_hotplug_slot_ops = {
.owner = THIS_MODULE,
@@ -81,6 +83,21 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
static DECLARE_MUTEX(sn_hotplug_sem);
+static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
+ char *buf)
+{
+ int retval = -ENOENT;
+ struct slot *slot = bss_hotplug_slot->private;
+
+ if (!slot)
+ return retval;
+
+ retval = sprintf (buf, "%s\n", slot->physical_path);
+ return retval;
+}
+
+static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
+
static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
{
struct pcibus_info *pcibus_info;
@@ -120,15 +137,15 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus)
/* Only register slots in I/O Bricks that support hotplug */
bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
switch (bricktype) {
- case L1_BRICKTYPE_IX:
- case L1_BRICKTYPE_PX:
- case L1_BRICKTYPE_IA:
- case L1_BRICKTYPE_PA:
- return 1;
- break;
- default:
- return -EPERM;
- break;
+ case L1_BRICKTYPE_IX:
+ case L1_BRICKTYPE_PX:
+ case L1_BRICKTYPE_IA:
+ case L1_BRICKTYPE_PA:
+ return 1;
+ break;
+ default:
+ return -EPERM;
+ break;
}
return -EIO;
@@ -142,13 +159,12 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
- bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
- GFP_KERNEL);
- if (!bss_hotplug_slot->private)
+ slot = kcalloc(1, sizeof(*slot), GFP_KERNEL);
+ if (!slot)
return -ENOMEM;
- slot = (struct slot *)bss_hotplug_slot->private;
+ bss_hotplug_slot->private = slot;
- bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
+ bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL);
if (!bss_hotplug_slot->name) {
kfree(bss_hotplug_slot->private);
return -ENOMEM;
@@ -156,16 +172,16 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
slot->device_num = device;
slot->pci_bus = pci_bus;
-
- sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
+ sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
+ pci_domain_nr(pci_bus),
+ ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
+ device + 1);
+ sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
'0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
'0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
'0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
- MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
- ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
- device + 1);
-
+ MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
slot->hotplug_slot = bss_hotplug_slot;
list_add(&slot->hp_list, &sn_hp_list);
@@ -175,14 +191,14 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
static struct hotplug_slot * sn_hp_destroy(void)
{
struct slot *slot;
- struct list_head *list;
struct hotplug_slot *bss_hotplug_slot = NULL;
- list_for_each(list, &sn_hp_list) {
- slot = list_entry(list, struct slot, hp_list);
+ list_for_each_entry(slot, &sn_hp_list, hp_list) {
bss_hotplug_slot = slot->hotplug_slot;
list_del(&((struct slot *)bss_hotplug_slot->private)->
hp_list);
+ sysfs_remove_file(&bss_hotplug_slot->kobj,
+ &sn_slot_path_attr.attr);
break;
}
return bss_hotplug_slot;
@@ -190,7 +206,6 @@ static struct hotplug_slot * sn_hp_destroy(void)
static void sn_bus_alloc_data(struct pci_dev *dev)
{
- struct list_head *node;
struct pci_bus *subordinate_bus;
struct pci_dev *child;
@@ -199,66 +214,29 @@ static void sn_bus_alloc_data(struct pci_dev *dev)
/* Recursively sets up the sn_irq_info structs */
if (dev->subordinate) {
subordinate_bus = dev->subordinate;
- list_for_each(node, &subordinate_bus->devices) {
- child = list_entry(node, struct pci_dev, bus_list);
+ list_for_each_entry(child, &subordinate_bus->devices, bus_list)
sn_bus_alloc_data(child);
- }
}
}
static void sn_bus_free_data(struct pci_dev *dev)
{
- struct list_head *node;
struct pci_bus *subordinate_bus;
struct pci_dev *child;
/* Recursively clean up sn_irq_info structs */
if (dev->subordinate) {
subordinate_bus = dev->subordinate;
- list_for_each(node, &subordinate_bus->devices) {
- child = list_entry(node, struct pci_dev, bus_list);
+ list_for_each_entry(child, &subordinate_bus->devices, bus_list)
sn_bus_free_data(child);
- }
}
sn_pci_unfixup_slot(dev);
}
-static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
- u8 retval;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
-
- return retval ? 1 : 0;
-}
-
-static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
- int device_num)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices |= (1 << device_num);
-}
-
-static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
- int device_num)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
-}
-
static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
int device_num)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pcibus_info *pcibus_info;
struct pcibr_slot_enable_resp resp;
int rc;
@@ -273,7 +251,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
if (rc == PCI_SLOT_ALREADY_UP) {
dev_dbg(slot->pci_bus->self, "is already active\n");
- return -EPERM;
+ return 1; /* return 1 to user */
}
if (rc == PCI_L1_ERR) {
@@ -290,7 +268,8 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
return -EIO;
}
- sn_slot_mark_enable(bss_hotplug_slot, device_num);
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+ pcibus_info->pbi_enabled_devices |= (1 << device_num);
return 0;
}
@@ -298,7 +277,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
int device_num, int action)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pcibus_info *pcibus_info;
struct pcibr_slot_disable_resp resp;
int rc;
@@ -307,43 +286,44 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) &&
+ (rc == PCI_SLOT_ALREADY_DOWN)) {
dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
- return -ENODEV;
+ return 1; /* return 1 to user */
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) {
dev_dbg(slot->pci_bus->self,
"Cannot remove last 33MHz card\n");
return -EPERM;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) {
dev_dbg(slot->pci_bus->self,
"L1 failure %d with message \n%s\n",
resp.resp_sub_errno, resp.resp_l1_msg);
return -EPERM;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) {
dev_dbg(slot->pci_bus->self,
"remove failed with error %d sub-error %d\n",
rc, resp.resp_sub_errno);
return -EIO;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc)
return 0;
- if (action == PCI_REQ_SLOT_DISABLE && !rc) {
- sn_slot_mark_disable(bss_hotplug_slot, device_num);
+ if ((action == PCI_REQ_SLOT_DISABLE) && !rc) {
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+ pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
dev_dbg(slot->pci_bus->self, "remove successful\n");
return 0;
}
- if (action == PCI_REQ_SLOT_DISABLE && rc) {
+ if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
- return rc;
}
return rc;
@@ -351,7 +331,7 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pci_bus *new_bus = NULL;
struct pci_dev *dev;
int func, num_funcs;
@@ -371,8 +351,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
return rc;
}
- num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
- PCI_FUNC(0)));
+ num_funcs = pci_scan_slot(slot->pci_bus,
+ PCI_DEVFN(slot->device_num + 1, 0));
if (!num_funcs) {
dev_dbg(slot->pci_bus->self, "no device in slot\n");
up(&sn_hotplug_sem);
@@ -391,8 +371,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
-
-
if (dev) {
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
unsigned char sec_bus;
@@ -431,7 +409,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pci_dev *dev;
int func;
int rc;
@@ -448,7 +426,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
/* Free the SN resources assigned to the Linux device.*/
for (func = 0; func < 8; func++) {
dev = pci_get_slot(slot->pci_bus,
- PCI_DEVFN(slot->device_num+1,
+ PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
/*
@@ -477,10 +455,15 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
return rc;
}
-static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
+static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
+ u8 *value)
{
+ struct slot *slot = bss_hotplug_slot->private;
+ struct pcibus_info *pcibus_info;
+
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
down(&sn_hotplug_sem);
- *value = sn_power_status_get(bss_hotplug_slot);
+ *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
up(&sn_hotplug_sem);
return 0;
}
@@ -508,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
if (sn_pci_slot_valid(pci_bus, device) != 1)
continue;
- bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
+ bss_hotplug_slot = kcalloc(1, sizeof(*bss_hotplug_slot),
GFP_KERNEL);
if (!bss_hotplug_slot) {
rc = -ENOMEM;
@@ -516,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
}
bss_hotplug_slot->info =
- kcalloc(1,sizeof(struct hotplug_slot_info),
+ kcalloc(1, sizeof(struct hotplug_slot_info),
GFP_KERNEL);
if (!bss_hotplug_slot->info) {
rc = -ENOMEM;
@@ -535,6 +518,11 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
rc = pci_hp_register(bss_hotplug_slot);
if (rc)
goto register_err;
+
+ rc = sysfs_create_file(&bss_hotplug_slot->kobj,
+ &sn_slot_path_attr.attr);
+ if (rc)
+ goto register_err;
}
dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
return rc;
@@ -564,14 +552,14 @@ static int sn_pci_hotplug_init(void)
int rc;
int registered = 0;
- INIT_LIST_HEAD(&sn_hp_list);
-
if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
- printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
+ printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
__FUNCTION__);
return -EPERM;
}
+ INIT_LIST_HEAD(&sn_hp_list);
+
while ((pci_bus = pci_find_next_bus(pci_bus))) {
if (!pci_bus->sysdata)
continue;
@@ -584,9 +572,9 @@ static int sn_pci_hotplug_init(void)
dev_dbg(pci_bus->self, "valid hotplug bus\n");
rc = sn_hotplug_slot_register(pci_bus);
- if (!rc)
+ if (!rc) {
registered = 1;
- else {
+ } else {
registered = 0;
break;
}
@@ -599,9 +587,8 @@ static void sn_pci_hotplug_exit(void)
{
struct hotplug_slot *bss_hotplug_slot;
- while ((bss_hotplug_slot = sn_hp_destroy())) {
+ while ((bss_hotplug_slot = sn_hp_destroy()))
pci_hp_deregister(bss_hotplug_slot);
- }
if (!list_empty(&sn_hp_list))
printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index fe4d653da188..b7d1c61d6bbb 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -411,7 +411,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
- snprintf(buffer, buffer_size, "%d", slot->number);
+ snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
}
enum php_ctlr_type {
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2b85aa39f954..ee8677bda950 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -91,6 +91,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
struct msi_desc *entry;
struct msg_address address;
+ unsigned int irq = vector;
entry = (struct msi_desc *)msi_desc[vector];
if (!entry || !entry->dev)
@@ -112,6 +113,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
address.lo_address.value);
+ set_native_irq_info(irq, cpu_mask);
break;
}
case PCI_CAP_ID_MSIX:
@@ -125,22 +127,13 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
MSI_TARGET_CPU_SHIFT);
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
writel(address.lo_address.value, entry->mask_base + offset);
+ set_native_irq_info(irq, cpu_mask);
break;
}
default:
break;
}
}
-
-#ifdef CONFIG_IRQBALANCE
-static inline void move_msi(int vector)
-{
- if (!cpus_empty(pending_irq_balance_cpumask[vector])) {
- set_msi_affinity(vector, pending_irq_balance_cpumask[vector]);
- cpus_clear(pending_irq_balance_cpumask[vector]);
- }
-}
-#endif /* CONFIG_IRQBALANCE */
#endif /* CONFIG_SMP */
static void mask_MSI_irq(unsigned int vector)
@@ -191,13 +184,13 @@ static void shutdown_msi_irq(unsigned int vector)
static void end_msi_irq_wo_maskbit(unsigned int vector)
{
- move_msi(vector);
+ move_native_irq(vector);
ack_APIC_irq();
}
static void end_msi_irq_w_maskbit(unsigned int vector)
{
- move_msi(vector);
+ move_native_irq(vector);
unmask_MSI_irq(vector);
ack_APIC_irq();
}
@@ -446,10 +439,7 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u16 cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_intx(dev, 0); /* disable intx */
}
}
@@ -468,10 +458,7 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type)
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u16 cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_intx(dev, 1); /* enable intx */
}
}
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 390f1851c0f1..402136a5c9e4 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -19,7 +19,6 @@
#define NR_HP_RESERVED_VECTORS 20
extern int vector_irq[NR_VECTORS];
-extern cpumask_t pending_irq_balance_cpumask[NR_IRQS];
extern void (*interrupt[NR_IRQS])(void);
extern int pci_vector_resources(int last, int nr_released);
@@ -29,10 +28,6 @@ extern int pci_vector_resources(int last, int nr_released);
#define set_msi_irq_affinity NULL
#endif
-#ifndef CONFIG_IRQBALANCE
-static inline void move_msi(int vector) {}
-#endif
-
/*
* MSI-X Address Register
*/
diff --git a/drivers/pci/names.c b/drivers/pci/names.c
deleted file mode 100644
index ad224aada7c9..000000000000
--- a/drivers/pci/names.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * PCI Class and Device Name Tables
- *
- * Copyright 1993--1999 Drew Eckhardt, Frederic Potter,
- * David Mosberger-Tang, Martin Mares
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#ifdef CONFIG_PCI_NAMES
-
-struct pci_device_info {
- unsigned short device;
- unsigned short seen;
- const char *name;
-};
-
-struct pci_vendor_info {
- unsigned short vendor;
- unsigned short nr;
- const char *name;
- struct pci_device_info *devices;
-};
-
-/*
- * This is ridiculous, but we want the strings in
- * the .init section so that they don't take up
- * real memory.. Parse the same file multiple times
- * to get all the info.
- */
-#define VENDOR( vendor, name ) static char __vendorstr_##vendor[] __devinitdata = name;
-#define ENDVENDOR()
-#define DEVICE( vendor, device, name ) static char __devicestr_##vendor##device[] __devinitdata = name;
-#include "devlist.h"
-
-
-#define VENDOR( vendor, name ) static struct pci_device_info __devices_##vendor[] __devinitdata = {
-#define ENDVENDOR() };
-#define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device },
-#include "devlist.h"
-
-static struct pci_vendor_info __devinitdata pci_vendor_list[] = {
-#define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor },
-#define ENDVENDOR()
-#define DEVICE( vendor, device, name )
-#include "devlist.h"
-};
-
-#define VENDORS (sizeof(pci_vendor_list)/sizeof(struct pci_vendor_info))
-
-void __devinit pci_name_device(struct pci_dev *dev)
-{
- const struct pci_vendor_info *vendor_p = pci_vendor_list;
- int i = VENDORS;
- char *name = dev->pretty_name;
-
- do {
- if (vendor_p->vendor == dev->vendor)
- goto match_vendor;
- vendor_p++;
- } while (--i);
-
- /* Couldn't find either the vendor nor the device */
- sprintf(name, "PCI device %04x:%04x", dev->vendor, dev->device);
- return;
-
- match_vendor: {
- struct pci_device_info *device_p = vendor_p->devices;
- int i = vendor_p->nr;
-
- while (i > 0) {
- if (device_p->device == dev->device)
- goto match_device;
- device_p++;
- i--;
- }
-
- /* Ok, found the vendor, but unknown device */
- sprintf(name, "PCI device %04x:%04x (%." PCI_NAME_HALF "s)",
- dev->vendor, dev->device, vendor_p->name);
- return;
-
- /* Full match */
- match_device: {
- char *n = name + sprintf(name, "%s %s",
- vendor_p->name, device_p->name);
- int nr = device_p->seen + 1;
- device_p->seen = nr;
- if (nr > 1)
- sprintf(n, " (#%d)", nr);
- }
- }
-}
-
-/*
- * Class names. Not in .init section as they are needed in runtime.
- */
-
-static u16 pci_class_numbers[] = {
-#define CLASS(x,y) 0x##x,
-#include "classlist.h"
-};
-
-static char *pci_class_names[] = {
-#define CLASS(x,y) y,
-#include "classlist.h"
-};
-
-char *
-pci_class_name(u32 class)
-{
- int i;
-
- for(i=0; i<sizeof(pci_class_numbers)/sizeof(pci_class_numbers[0]); i++)
- if (pci_class_numbers[i] == class)
- return pci_class_names[i];
- return NULL;
-}
-
-#else
-
-void __devinit pci_name_device(struct pci_dev *dev)
-{
-}
-
-char *
-pci_class_name(u32 class)
-{
- return NULL;
-}
-
-#endif /* CONFIG_PCI_NAMES */
-
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e4115a0d5ba6..0d0d533894e0 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/mempolicy.h>
#include "pci.h"
/*
@@ -163,6 +164,34 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv,
return NULL;
}
+static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ int error;
+#ifdef CONFIG_NUMA
+ /* Execute driver initialization on node where the
+ device's bus is attached to. This way the driver likely
+ allocates its local memory on the right node without
+ any need to change it. */
+ struct mempolicy *oldpol;
+ cpumask_t oldmask = current->cpus_allowed;
+ int node = pcibus_to_node(dev->bus);
+ if (node >= 0 && node_online(node))
+ set_cpus_allowed(current, node_to_cpumask(node));
+ /* And set default memory allocation policy */
+ oldpol = current->mempolicy;
+ current->mempolicy = &default_policy;
+ mpol_get(current->mempolicy);
+#endif
+ error = drv->probe(dev, id);
+#ifdef CONFIG_NUMA
+ set_cpus_allowed(current, oldmask);
+ mpol_free(current->mempolicy);
+ current->mempolicy = oldpol;
+#endif
+ return error;
+}
+
/**
* __pci_device_probe()
*
@@ -180,7 +209,7 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
id = pci_match_device(drv, pci_dev);
if (id)
- error = drv->probe(pci_dev, id);
+ error = pci_call_probe(drv, pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
error = 0;
@@ -243,17 +272,19 @@ 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)
{
+ int retval;
+
/* restore the PCI config space */
pci_restore_state(pci_dev);
/* if the device was enabled before suspend, reenable */
if (pci_dev->is_enabled)
- pci_enable_device(pci_dev);
+ retval = pci_enable_device(pci_dev);
/* if the device was busmaster before the suspend, make it busmaster again */
if (pci_dev->is_busmaster)
pci_set_master(pci_dev);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index cc9d65388e62..56a3b397efee 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -44,10 +44,14 @@ pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");
-static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t local_cpus_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
- int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
+ cpumask_t mask;
+ int len;
+
+ mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
strcat(buf,"\n");
return 1+len;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1b34fc56067e..992db89adce7 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -222,6 +222,37 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
}
/**
+ * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
+ * @dev: PCI device to have its BARs restored
+ *
+ * Restore the BAR values for a given device, so as to make it
+ * accessible by its driver.
+ */
+void
+pci_restore_bars(struct pci_dev *dev)
+{
+ int i, numres;
+
+ switch (dev->hdr_type) {
+ case PCI_HEADER_TYPE_NORMAL:
+ numres = 6;
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ numres = 2;
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+ numres = 1;
+ break;
+ default:
+ /* Should never get here, but just in case... */
+ return;
+ }
+
+ for (i = 0; i < numres; i ++)
+ pci_update_resource(dev, &dev->resource[i], i);
+}
+
+/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
* @state: PCI power state (D0, D1, D2, D3hot, D3cold) we're entering
@@ -239,7 +270,7 @@ int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
int
pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
- int pm;
+ int pm, need_restore = 0;
u16 pmcsr, pmc;
/* bound the state we're entering */
@@ -263,7 +294,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
return -EIO;
pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
- if ((pmc & PCI_PM_CAP_VER_MASK) > 2) {
+ if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
printk(KERN_DEBUG
"PCI: %s has unsupported PM cap regs version (%u)\n",
pci_name(dev), pmc & PCI_PM_CAP_VER_MASK);
@@ -271,21 +302,22 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
}
/* check if this device supports the desired state */
- if (state == PCI_D1 || state == PCI_D2) {
- if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
- return -EIO;
- else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
- return -EIO;
- }
+ if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
+ return -EIO;
+ else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
+ return -EIO;
+
+ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
/* If we're in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= PCI_D3hot)
+ if (dev->current_state >= PCI_D3hot) {
+ if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ need_restore = 1;
pmcsr = 0;
- else {
- pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+ } else {
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= state;
}
@@ -308,6 +340,22 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
platform_pci_set_power_state(dev, state);
dev->current_state = state;
+
+ /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
+ * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
+ * from D3hot to D0 _may_ perform an internal reset, thereby
+ * going to "D0 Uninitialized" rather than "D0 Initialized".
+ * For example, at least some versions of the 3c905B and the
+ * 3c556B exhibit this behaviour.
+ *
+ * At least some laptop BIOSen (e.g. the Thinkpad T21) leave
+ * devices in a D3hot state at boot. Consequently, we need to
+ * restore at least the BARs so that the device will be
+ * accessible to its driver.
+ */
+ if (need_restore)
+ pci_restore_bars(dev);
+
return 0;
}
@@ -333,13 +381,17 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
if (platform_pci_choose_state) {
ret = platform_pci_choose_state(dev, state);
if (ret >= 0)
- state = ret;
+ state.event = ret;
}
- switch (state) {
- case 0: return PCI_D0;
- case 3: return PCI_D3hot;
+
+ switch (state.event) {
+ case PM_EVENT_ON:
+ return PCI_D0;
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_SUSPEND:
+ return PCI_D3hot;
default:
- printk("They asked me for state %d\n", state);
+ printk("They asked me for state %d\n", state.event);
BUG();
}
return PCI_D0;
@@ -390,8 +442,11 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
{
int err;
- pci_set_power_state(dev, PCI_D0);
- if ((err = pcibios_enable_device(dev, bars)) < 0)
+ err = pci_set_power_state(dev, PCI_D0);
+ if (err < 0 && err != -EIO)
+ return err;
+ err = pcibios_enable_device(dev, bars);
+ if (err < 0)
return err;
return 0;
}
@@ -743,6 +798,31 @@ pci_clear_mwi(struct pci_dev *dev)
}
}
+/**
+ * pci_intx - enables/disables PCI INTx for device dev
+ * @dev: the PCI device to operate on
+ * @enable: boolean
+ *
+ * Enables/disables PCI INTx for device dev
+ */
+void
+pci_intx(struct pci_dev *pdev, int enable)
+{
+ u16 pci_command, new;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
+ if (enable) {
+ new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+ } else {
+ new = pci_command | PCI_COMMAND_INTX_DISABLE;
+ }
+
+ if (new != pci_command) {
+ pci_write_config_word(pdev, PCI_COMMAND, new);
+ }
+}
+
#ifndef HAVE_ARCH_PCI_SET_DMA_MASK
/*
* These can be overridden by arch-specific implementations
@@ -805,6 +885,7 @@ struct pci_dev *isa_bridge;
EXPORT_SYMBOL(isa_bridge);
#endif
+EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_enable_device_bars);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_device);
@@ -819,6 +900,7 @@ EXPORT_SYMBOL(pci_request_region);
EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
+EXPORT_SYMBOL_GPL(pci_intx);
EXPORT_SYMBOL(pci_set_dma_mask);
EXPORT_SYMBOL(pci_set_consistent_dma_mask);
EXPORT_SYMBOL(pci_assign_resource);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d00168b1f662..d3f3dd42240d 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -29,7 +29,6 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif
/* Functions for PCI Hotplug drivers to use */
-extern struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
extern int pci_remove_device_safe(struct pci_dev *dev);
extern unsigned char pci_max_busnr(void);
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
deleted file mode 100644
index 1d2ef1e2ffc6..000000000000
--- a/drivers/pci/pci.ids
+++ /dev/null
@@ -1,10180 +0,0 @@
-#
-# List of PCI ID's
-#
-# Maintained by Martin Mares <mj@ucw.cz> and other volunteers from the
-# Linux PCI ID's Project at http://pciids.sf.net/. New data are always
-# welcome (if they are accurate), we're eagerly expecting new entries,
-# so if you have anything to contribute, please visit the home page or
-# send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
-#
-# Daily snapshot on Tue 2005-03-08 10:11:48
-#
-
-# Vendors, devices and subsystems. Please keep sorted.
-
-# Syntax:
-# vendor vendor_name
-# device device_name <-- single tab
-# subvendor subdevice subsystem_name <-- two tabs
-
-0000 Gammagraphx, Inc.
-001a Ascend Communications, Inc.
-0033 Paradyne corp.
-003d Lockheed Martin-Marietta Corp
-# Real TJN ID is e159, but they got it wrong several times --mj
-0059 Tiger Jet Network Inc. (Wrong ID)
-0070 Hauppauge computer works Inc.
- 4000 WinTV PVR-350
- 4001 WinTV PVR-250 (v1)
- 4009 WinTV PVR-250
- 4801 WinTV PVR-250 MCE
-0071 Nebula Electronics Ltd.
-0095 Silicon Image, Inc. (Wrong ID)
- 0680 Ultra ATA/133 IDE RAID CONTROLLER CARD
-0100 Ncipher Corp Ltd
-# 018a is not LevelOne but there is a board misprogrammed
-018a LevelOne
- 0106 FPC-0106TX misprogrammed [RTL81xx]
-# 021b is not Compaq but there is a board misprogrammed
-021b Compaq Computer Corporation
- 8139 HNE-300 (RealTek RTL8139c) [iPaq Networking]
-# http://www.davicom.com.tw/
-0291 Davicom Semiconductor, Inc.
- 8212 DM9102A(DM9102AE, SM9102AF) Ethernet 100/10 MBit(Rev 40)
-# SpeedStream is Efficient Networks, Inc, a Siemens Company
-02ac SpeedStream
- 1012 1012 PCMCIA 10/100 Ethernet Card [RTL81xx]
-0357 TTTech AG
- 000a TTP-Monitoring Card V2.0
-0432 SCM Microsystems, Inc.
- 0001 Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet]
-05e3 CyberDoor
- 0701 CBD516
-0675 Dynalink
- 1700 IS64PH ISDN Adapter
- 1702 IS64PH ISDN Adapter
-# Wrong ID used in subsystem ID of VIA USB controllers.
-0925 VIA Technologies, Inc. (Wrong ID)
-09c1 Arris
- 0704 CM 200E Cable Modem
-0a89 BREA Technologies Inc
-0b49 ASCII Corporation
-# see http://homepage1.nifty.com/mcn/lab/machines/trance_vibrator/usbview.vib.txt
- 064f Trance Vibrator
-0e11 Compaq Computer Corporation
- 0001 PCI to EISA Bridge
- 0002 PCI to ISA Bridge
- 0046 Smart Array 64xx
- 0e11 409a Smart Array 641
- 0e11 409b Smart Array 642
- 0e11 409c Smart Array 6400
- 0e11 409d Smart Array 6400 EM
- 0049 NC7132 Gigabit Upgrade Module
- 004a NC6136 Gigabit Server Adapter
- 007c NC7770 1000BaseTX
- 007d NC6770 1000BaseTX
- 0085 NC7780 1000BaseTX
- 00bb NC7760
- 00ca NC7771
- 00cb NC7781
- 00cf NC7772
- 00d0 NC7782
- 00d1 NC7783
- 00e3 NC7761
- 0508 Netelligent 4/16 Token Ring
- 1000 Triflex/Pentium Bridge, Model 1000
- 2000 Triflex/Pentium Bridge, Model 2000
- 3032 QVision 1280/p
- 3033 QVision 1280/p
- 3034 QVision 1280/p
- 4000 4000 [Triflex]
- 4030 SMART-2/P
- 4031 SMART-2SL
- 4032 Smart Array 3200
- 4033 Smart Array 3100ES
- 4034 Smart Array 221
- 4040 Integrated Array
- 4048 Compaq Raid LC2
- 4050 Smart Array 4200
- 4051 Smart Array 4250ES
- 4058 Smart Array 431
- 4070 Smart Array 5300
- 4080 Smart Array 5i
- 4082 Smart Array 532
- 4083 Smart Array 5312
- 4091 Smart Array 6i
- 409a Smart Array 641
- 409b Smart Array 642
- 409c Smart Array 6400
- 409d Smart Array 6400 EM
- 6010 HotPlug PCI Bridge 6010
- 7020 USB Controller
- a0ec Fibre Channel Host Controller
- a0f0 Advanced System Management Controller
- a0f3 Triflex PCI to ISA Bridge
- a0f7 PCI Hotplug Controller
- 8086 002a PCI Hotplug Controller A
- 8086 002b PCI Hotplug Controller B
- a0f8 ZFMicro Chipset USB
- a0fc FibreChannel HBA Tachyon
- ae10 Smart-2/P RAID Controller
- 0e11 4030 Smart-2/P Array Controller
- 0e11 4031 Smart-2SL Array Controller
- 0e11 4032 Smart Array Controller
- 0e11 4033 Smart 3100ES Array Controller
- ae29 MIS-L
- ae2a MPC
- ae2b MIS-E
- ae31 System Management Controller
- ae32 Netelligent 10/100 TX PCI UTP
- ae33 Triflex Dual EIDE Controller
- ae34 Netelligent 10 T PCI UTP
- ae35 Integrated NetFlex-3/P
- ae40 Netelligent Dual 10/100 TX PCI UTP
- ae43 Netelligent Integrated 10/100 TX UTP
- ae69 CETUS-L
- ae6c Northstar
- ae6d NorthStar CPU to PCI Bridge
- b011 Netelligent 10/100 TX Embedded UTP
- b012 Netelligent 10 T/2 PCI UTP/Coax
- b01e NC3120 Fast Ethernet NIC
- b01f NC3122 Fast Ethernet NIC
- b02f NC1120 Ethernet NIC
- b030 Netelligent 10/100 TX UTP
- b04a 10/100 TX PCI Intel WOL UTP Controller
- b060 Smart Array 5300 Controller
- b0c6 NC3161 Fast Ethernet NIC
- b0c7 NC3160 Fast Ethernet NIC
- b0d7 NC3121 Fast Ethernet NIC
- b0dd NC3131 Fast Ethernet NIC
- b0de NC3132 Fast Ethernet Module
- b0df NC6132 Gigabit Module
- b0e0 NC6133 Gigabit Module
- b0e1 NC3133 Fast Ethernet Module
- b123 NC6134 Gigabit NIC
- b134 NC3163 Fast Ethernet NIC
- b13c NC3162 Fast Ethernet NIC
- b144 NC3123 Fast Ethernet NIC
- b163 NC3134 Fast Ethernet NIC
- b164 NC3165 Fast Ethernet Upgrade Module
- b178 Smart Array 5i/532
- 0e11 4080 Smart Array 5i
- 0e11 4082 Smart Array 532
- 0e11 4083 Smart Array 5312
- b1a4 NC7131 Gigabit Server Adapter
-# HP Memory Hot-Plug Controller
- b200 Memory Hot-Plug Controller
- b203 Integrated Lights Out Controller
- b204 Integrated Lights Out Processor
- f130 NetFlex-3/P ThunderLAN 1.0
- f150 NetFlex-3/P ThunderLAN 2.3
-0e55 HaSoTec GmbH
-# Formerly NCR
-1000 LSI Logic / Symbios Logic
- 0001 53c810
- 1000 1000 LSI53C810AE PCI to SCSI I/O Processor
- 0002 53c820
- 0003 53c825
- 1000 1000 LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)
- 0004 53c815
- 0005 53c810AP
- 0006 53c860
- 1000 1000 LSI53C860E PCI to Ultra SCSI I/O Processor
- 000a 53c1510
- 1000 1000 LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
- 000b 53C896/897
- 0e11 6004 EOB003 Series SCSI host adapter
- 1000 1000 LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
- 1000 1010 LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
- 1000 1020 LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
-# multifunction PCI card: Dual U2W SCSI, dual 10/100TX, graphics
- 13e9 1000 6221L-4U
- 000c 53c895
- 1000 1010 LSI8951U PCI to Ultra2 SCSI host adapter
- 1000 1020 LSI8952U PCI to Ultra2 SCSI host adapter
- 1de1 3906 DC-390U2B SCSI adapter
- 1de1 3907 DC-390U2W
- 000d 53c885
- 000f 53c875
- 0e11 7004 Embedded Ultra Wide SCSI Controller
- 1000 1000 LSI53C876/E PCI to Dual Channel SCSI Controller
- 1000 1010 LSI22801 PCI to Dual Channel Ultra SCSI host adapter
- 1000 1020 LSI22802 PCI to Dual Channel Ultra SCSI host adapter
- 1092 8760 FirePort 40 Dual SCSI Controller
- 1de1 3904 DC390F/U Ultra Wide SCSI Adapter
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1050 CT7 mainboard
- 0010 53C1510
- 0e11 4040 Integrated Array Controller
- 0e11 4048 RAID LC2 Controller
- 1000 1000 53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
- 0012 53c895a
- 1000 1000 LSI53C895A PCI to Ultra2 SCSI Controller
- 0013 53c875a
- 1000 1000 LSI53C875A PCI to Ultra SCSI Controller
- 0020 53c1010 Ultra3 SCSI Adapter
- 1000 1000 LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller
- 1de1 1020 DC-390U3W
- 0021 53c1010 66MHz Ultra3 SCSI Adapter
- 1000 1000 LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
- 1000 1010 Asus TR-DLS onboard 53C1010-66
- 124b 1070 PMC-USCSI3
- 4c53 1080 CT8 mainboard
- 4c53 1300 P017 mezzanine (32-bit PMC)
- 4c53 1310 P017 mezzanine (64-bit PMC)
- 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1028 0123 PowerEdge 2600
- 1028 014a PowerEdge 1750
- 1028 016c PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)
- 1028 0183 PowerEdge 1800
- 1028 1010 LSI U320 SCSI Controller
- 0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
- 0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1000 1000 LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller
- 0033 1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 0040 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1000 0033 MegaRAID SCSI 320-2XR
- 1000 0066 MegaRAID SCSI 320-2XRWS
- 0041 53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
- 008f 53c875J
- 1092 8000 FirePort 40 SCSI Controller
- 1092 8760 FirePort 40 Dual SCSI Host Adapter
- 0407 MegaRAID
- 1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller
- 1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller
- 1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller
- 1028 0531 PowerEdge Expandable RAID Controller 4/QC
- 1028 0533 PowerEdge Expandable RAID Controller 4/QC
- 8086 0530 MegaRAID Intel RAID Controller SRCZCRX
- 8086 0532 MegaRAID Intel RAID Controller SRCU42X
- 0408 MegaRAID
- 1000 0001 MegaRAID SCSI 320-1E RAID Controller
- 1000 0002 MegaRAID SCSI 320-2E RAID Controller
- 1025 004d MegaRAID ACER ROMB-2E RAID Controller
- 1028 0001 PowerEdge RAID Controller PERC4e/SC
- 1028 0002 PowerEdge RAID Controller PERC4e/DC
- 1734 1065 FSC MegaRAID PCI Express ROMB
- 8086 0002 MegaRAID Intel RAID Controller SRCU42E
- 0409 MegaRAID
- 1000 3004 MegaRAID SATA 300-4X RAID Controller
- 1000 3008 MegaRAID SATA 300-8X RAID Controller
- 8086 3008 MegaRAID RAID Controller SRCS28X
- 8086 3431 MegaRAID RAID Controller Alief SROMBU42E
- 8086 3499 MegaRAID RAID Controller Harwich SROMBU42E
- 0621 FC909 Fibre Channel Adapter
- 0622 FC929 Fibre Channel Adapter
- 1000 1020 44929 O Dual Fibre Channel card
- 0623 FC929 LAN
- 0624 FC919 Fibre Channel Adapter
- 0625 FC919 LAN
- 0626 FC929X Fibre Channel Adapter
- 1000 1010 7202-XP-LC Dual Fibre Channel card
- 0627 FC929X LAN
- 0628 FC919X Fibre Channel Adapter
- 0629 FC919X LAN
- 0701 83C885 NT50 DigitalScape Fast Ethernet
- 0702 Yellowfin G-NIC gigabit ethernet
- 1318 0000 PEI100X
- 0804 SA2010
- 0805 SA2010ZC
- 0806 SA2020
- 0807 SA2020ZC
- 0901 61C102
- 1000 63C815
- 1960 MegaRAID
- 1000 0518 MegaRAID 518 SCSI 320-2 Controller
- 1000 0520 MegaRAID 520 SCSI 320-1 Controller
- 1000 0522 MegaRAID 522 i4 133 RAID Controller
- 1000 0523 MegaRAID SATA 150-6 RAID Controller
- 1000 4523 MegaRAID SATA 150-4 RAID Controller
- 1000 a520 MegaRAID ZCR SCSI 320-0 Controller
- 1028 0518 MegaRAID 518 DELL PERC 4/DC RAID Controller
- 1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller
- 1028 0531 PowerEdge Expandable RAID Controller 4/QC
- 1028 0533 PowerEdge Expandable RAID Controller 4/QC
- 8086 0520 MegaRAIDRAID Controller SRCU41L
- 8086 0523 MegaRAID RAID Controller SRCS16
-1001 Kolter Electronic
- 0010 PCI 1616 Measurement card with 32 digital I/O lines
- 0011 OPTO-PCI Opto-Isolated digital I/O board
- 0012 PCI-AD/DA Analogue I/O board
- 0013 PCI-OPTO-RELAIS Digital I/O board with relay outputs
- 0014 PCI-Counter/Timer Counter Timer board
- 0015 PCI-DAC416 Analogue output board
- 0016 PCI-MFB Analogue I/O board
- 0017 PROTO-3 PCI Prototyping board
- 9100 INI-9100/9100W SCSI Host
-1002 ATI Technologies Inc
- 3150 M24 1P [Radeon Mobility X600]
- 3154 M24 1T [FireGL M24 GL]
- 3e50 RV380 0x3e50 [Radeon X600]
- 3e54 RV380 0x3e54 [FireGL V3200]
- 3e70 RV380 [Radeon X600] Secondary
- 4136 Radeon IGP 320 M
- 4137 Radeon IGP330/340/350
- 4144 R300 AD [Radeon 9500 Pro]
-# New PCI ID provided by ATI developer relations (correction to above)
- 4145 R300 AE [Radeon 9700 Pro]
-# New PCI ID provided by ATI developer relations (oops, correction to above)
- 4146 R300 AF [Radeon 9700 Pro]
- 4147 R300 AG [FireGL Z1/X1]
- 4148 R350 AH [Radeon 9800]
- 4149 R350 AI [Radeon 9800]
- 414a R350 AJ [Radeon 9800]
- 414b R350 AK [Fire GL X2]
-# New PCI ID provided by ATI developer relations
- 4150 RV350 AP [Radeon 9600]
- 1002 0002 R9600 Pro primary (Asus OEM for HP)
- 1002 0003 R9600 Pro secondary (Asus OEM for HP)
- 1458 4024 Giga-Byte GV-R96128D Primary
- 148c 2064 PowerColor R96A-C3N
- 148c 2066 PowerColor R96A-C3N
- 174b 7c19 Sapphire Atlantis Radeon 9600 Pro
- 174b 7c29 GC-R9600PRO Primary [Sapphire]
- 17ee 2002 Radeon 9600 256Mb Primary
- 18bc 0101 GC-R9600PRO Primary
-# New PCI ID provided by ATI developer relations
- 4151 RV350 AQ [Radeon 9600]
- 1043 c004 A9600SE
-# New PCI ID provided by ATI developer relations
- 4152 RV350 AR [Radeon 9600]
- 1002 0002 Radeon 9600XT
- 1043 c002 Radeon 9600 XT TVD
- 174b 7c29 Sapphire Radeon 9600XT
- 1787 4002 Radeon 9600 XT
- 4153 RV350 AS [Radeon 9600 AS]
- 4154 RV350 AT [Fire GL T2]
- 4155 RV350 AU [Fire GL T2]
- 4156 RV350 AV [Fire GL T2]
- 4157 RV350 AW [Fire GL T2]
- 4158 68800AX [Mach32]
-# The PCI ID is unrelated to any DVI output.
- 4164 R300 AD [Radeon 9500 Pro] (Secondary)
-# New PCI ID info provided by ATI developer relations
- 4165 R300 AE [Radeon 9700 Pro] (Secondary)
-# New PCI ID info provided by ATI developer relations
- 4166 R300 AF [Radeon 9700 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations
- 4168 Radeon R350 [Radeon 9800] (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4170 RV350 AP [Radeon 9600] (Secondary)
- 1458 4025 Giga-Byte GV-R96128D Secondary
- 148c 2067 PowerColor R96A-C3N (Secondary)
- 174b 7c28 GC-R9600PRO Secondary [Sapphire]
- 17ee 2003 Radeon 9600 256Mb Secondary
- 18bc 0100 GC-R9600PRO Secondary
-# New PCI ID provided by ATI developer relations (correction to above)
- 4171 RV350 AQ [Radeon 9600] (Secondary)
- 1043 c005 A9600SE (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4172 RV350 AR [Radeon 9600] (Secondary)
- 1002 0003 Radeon 9600XT (Secondary)
- 1043 c003 A9600XT (Secondary)
- 174b 7c28 Sapphire Radeon 9600XT (Secondary)
- 1787 4003 Radeon 9600 XT (Secondary)
- 4173 RV350 ?? [Radeon 9550] (Secondary)
- 4237 Radeon 7000 IGP
- 4242 R200 BB [Radeon All in Wonder 8500DV]
- 1002 02aa Radeon 8500 AIW DV Edition
- 4243 R200 BC [Radeon All in Wonder 8500]
- 4336 Radeon Mobility U1
- 103c 0024 Pavilion ze4400 builtin Video
- 4337 Radeon IGP 330M/340M/350M
- 1014 053a ThinkPad R40e (2684-HVG) builtin VGA controller
- 103c 0850 Radeon IGP 345M
- 4341 IXP150 AC'97 Audio Controller
- 4345 EHCI USB Controller
- 4347 OHCI USB Controller #1
- 4348 OHCI USB Controller #2
- 4349 ATI Dual Channel Bus Master PCI IDE Controller
- 434d IXP AC'97 Modem
- 4353 ATI SMBus
- 4354 215CT [Mach64 CT]
- 4358 210888CX [Mach64 CX]
- 4363 ATI SMBus
- 436e ATI 436E Serial ATA Controller
- 4372 ATI SMBus
- 4376 Standard Dual Channel PCI IDE Controller ATI
- 4379 ATI 4379 Serial ATA Controller
- 437a ATI 437A Serial ATA Controller
- 4437 Radeon Mobility 7000 IGP
- 4554 210888ET [Mach64 ET]
- 4654 Mach64 VT
- 4742 3D Rage Pro AGP 1X/2X
- 1002 0040 Rage Pro Turbo AGP 2X
- 1002 0044 Rage Pro Turbo AGP 2X
- 1002 0061 Rage Pro AIW AGP 2X
- 1002 0062 Rage Pro AIW AGP 2X
- 1002 0063 Rage Pro AIW AGP 2X
- 1002 0080 Rage Pro Turbo AGP 2X
- 1002 0084 Rage Pro Turbo AGP 2X
- 1002 4742 Rage Pro Turbo AGP 2X
- 1002 8001 Rage Pro Turbo AGP 2X
- 1028 0082 Rage Pro Turbo AGP 2X
- 1028 4082 Optiplex GX1 Onboard Display Adapter
- 1028 8082 Rage Pro Turbo AGP 2X
- 1028 c082 Rage Pro Turbo AGP 2X
- 8086 4152 Xpert 98D AGP 2X
- 8086 464a Rage Pro Turbo AGP 2X
- 4744 3D Rage Pro AGP 1X
- 1002 4744 Rage Pro Turbo AGP
- 4747 3D Rage Pro
- 4749 3D Rage Pro
- 1002 0061 Rage Pro AIW
- 1002 0062 Rage Pro AIW
- 474c Rage XC
- 474d Rage XL AGP 2X
- 1002 0004 Xpert 98 RXL AGP 2X
- 1002 0008 Xpert 98 RXL AGP 2X
- 1002 0080 Rage XL AGP 2X
- 1002 0084 Xpert 98 AGP 2X
- 1002 474d Rage XL AGP
- 1033 806a Rage XL AGP
- 474e Rage XC AGP
- 1002 474e Rage XC AGP
- 474f Rage XL
- 1002 0008 Rage XL
- 1002 474f Rage XL
- 4750 3D Rage Pro 215GP
- 1002 0040 Rage Pro Turbo
- 1002 0044 Rage Pro Turbo
- 1002 0080 Rage Pro Turbo
- 1002 0084 Rage Pro Turbo
- 1002 4750 Rage Pro Turbo
- 4751 3D Rage Pro 215GQ
- 4752 Rage XL
- 1002 0008 Rage XL
- 1002 4752 Rage XL
- 1002 8008 Rage XL
- 1028 00ce PowerEdge 1400
- 1028 00d1 PowerEdge 2550
- 1028 00d9 PowerEdge 2500
- 8086 3411 SDS2 Mainboard
- 8086 3427 S875WP1-E mainboard
- 4753 Rage XC
- 1002 4753 Rage XC
- 4754 3D Rage I/II 215GT [Mach64 GT]
- 4755 3D Rage II+ 215GTB [Mach64 GTB]
- 4756 3D Rage IIC 215IIC [Mach64 GT IIC]
- 1002 4756 Rage IIC
- 4757 3D Rage IIC AGP
- 1002 4757 Rage IIC AGP
- 1028 0089 Rage 3D IIC
- 1028 4082 Rage 3D IIC
- 1028 8082 Rage 3D IIC
- 1028 c082 Rage 3D IIC
- 4758 210888GX [Mach64 GX]
- 4759 3D Rage IIC
- 475a 3D Rage IIC AGP
- 1002 0084 Rage 3D Pro AGP 2x XPERT 98
- 1002 0087 Rage 3D IIC
- 1002 475a Rage IIC AGP
- 4964 Radeon RV250 Id [Radeon 9000]
- 4965 Radeon RV250 Ie [Radeon 9000]
- 4966 Radeon RV250 If [Radeon 9000]
- 10f1 0002 RV250 If [Tachyon G9000 PRO]
- 148c 2039 RV250 If [Radeon 9000 Pro "Evil Commando"]
- 1509 9a00 RV250 If [Radeon 9000 "AT009"]
-# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified.
- 1681 0040 RV250 If [3D prophet 9000]
- 174b 7176 RV250 If [Sapphire Radeon 9000 Pro]
- 174b 7192 RV250 If [Radeon 9000 "Atlantis"]
- 17af 2005 RV250 If [Excalibur Radeon 9000 Pro]
- 17af 2006 RV250 If [Excalibur Radeon 9000]
- 4967 Radeon RV250 Ig [Radeon 9000]
- 496e Radeon RV250 [Radeon 9000] (Secondary)
- 4a48 R420 JH [Radeon X800]
- 4a49 R420 JI [Radeon X800PRO]
- 4a4a R420 JJ [Radeon X800SE]
- 4a4b R420 JK [Radeon X800]
- 4a4c R420 JL [Radeon X800]
- 4a4d R420 JM [FireGL X3]
- 4a4e M18 JN [Radeon Mobility 9800]
- 4a50 R420 JP [Radeon X800XT]
- 4a70 R420 [X800XT-PE] (Secondary)
- 4c42 3D Rage LT Pro AGP-133
- 0e11 b0e7 Rage LT Pro (Compaq Presario 5240)
- 0e11 b0e8 Rage 3D LT Pro
- 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750)
- 1002 0040 Rage LT Pro AGP 2X
- 1002 0044 Rage LT Pro AGP 2X
- 1002 4c42 Rage LT Pro AGP 2X
- 1002 8001 Rage LT Pro AGP 2X
- 1028 0085 Rage 3D LT Pro
- 4c44 3D Rage LT Pro AGP-66
- 4c45 Rage Mobility M3 AGP
- 4c46 Rage Mobility M3 AGP 2x
- 1028 00b1 Latitude C600
- 4c47 3D Rage LT-G 215LG
- 4c49 3D Rage LT Pro
- 1002 0004 Rage LT Pro
- 1002 0040 Rage LT Pro
- 1002 0044 Rage LT Pro
- 1002 4c49 Rage LT Pro
- 4c4d Rage Mobility P/M AGP 2x
- 0e11 b111 Armada M700
- 0e11 b160 Armada E500
- 1002 0084 Xpert 98 AGP 2X (Mobility)
- 1014 0154 ThinkPad A20m
- 1028 00aa Latitude CPt
- 1028 00bb Latitude CPx
- 4c4e Rage Mobility L AGP 2x
- 4c50 3D Rage LT Pro
- 1002 4c50 Rage LT Pro
- 4c51 3D Rage LT Pro
- 4c52 Rage Mobility P/M
- 1033 8112 Versa Note VXi
- 4c53 Rage Mobility L
- 4c54 264LT [Mach64 LT]
- 4c57 Radeon Mobility M7 LW [Radeon Mobility 7500]
- 1014 0517 ThinkPad T30
- 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100)
- 1028 012a Latitude C640
- 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4
- 4c58 Radeon RV200 LX [Mobility FireGL 7800 M7]
- 4c59 Radeon Mobility M6 LY
- 1014 0235 ThinkPad A30/A30p (2652/2653)
- 1014 0239 ThinkPad X22/X23/X24
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 4c5a Radeon Mobility M6 LZ
- 4c64 Radeon R250 Ld [Radeon Mobility 9000 M9]
- 4c65 Radeon R250 Le [Radeon Mobility 9000 M9]
- 4c66 Radeon R250 Lf [FireGL 9000]
- 4c67 Radeon R250 Lg [Radeon Mobility 9000 M9]
-# Secondary chip to the Lf
- 4c6e Radeon R250 Ln [Radeon Mobility 9000 M9] [Secondary]
- 4d46 Rage Mobility M4 AGP
- 4d4c Rage Mobility M4 AGP
- 4e44 Radeon R300 ND [Radeon 9700 Pro]
- 4e45 Radeon R300 NE [Radeon 9500 Pro]
- 1002 0002 Radeon R300 NE [Radeon 9500 Pro]
- 1681 0002 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]
-# New PCI ID provided by ATI developer relations (correction to above)
- 4e46 RV350 NF [Radeon 9600]
- 4e47 Radeon R300 NG [FireGL X1]
-# (added pro)
- 4e48 Radeon R350 [Radeon 9800 Pro]
-# New PCI ID provided by ATI developer relations
- 4e49 Radeon R350 [Radeon 9800]
- 4e4a RV350 NJ [Radeon 9800 XT]
- 4e4b R350 NK [Fire GL X2]
-# New PCI ID provided by ATI developer relations
- 4e50 RV350 [Mobility Radeon 9600 M10]
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1734 1055 Amilo M1420W
- 4e51 M10 NQ [Radeon Mobility 9600]
- 4e52 RV350 [Mobility Radeon 9600 M10]
- 4e53 M10 NS [Radeon Mobility 9600]
- 4e54 M10 NT [FireGL Mobility T2]
- 4e56 M11 NV [FireGL Mobility T2e]
- 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary)
- 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary)
- 1002 0003 Radeon R300 NE [Radeon 9500 Pro]
- 1681 0003 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4e66 RV350 NF [Radeon 9600] (Secondary)
- 4e67 Radeon R300 [FireGL X1] (Secondary)
-# (added pro)
- 4e68 Radeon R350 [Radeon 9800 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations
- 4e69 Radeon R350 [Radeon 9800] (Secondary)
- 4e6a RV350 NJ [Radeon 9800 XT] (Secondary)
- 1002 4e71 ATI Technologies Inc M10 NQ [Radeon Mobility 9600]
- 5041 Rage 128 PA/PRO
- 5042 Rage 128 PB/PRO AGP 2x
- 5043 Rage 128 PC/PRO AGP 4x
- 5044 Rage 128 PD/PRO TMDS
- 1002 0028 Rage 128 AIW
- 1002 0029 Rage 128 AIW
- 5045 Rage 128 PE/PRO AGP 2x TMDS
- 5046 Rage 128 PF/PRO AGP 4x TMDS
- 1002 0004 Rage Fury Pro
- 1002 0008 Rage Fury Pro/Xpert 2000 Pro
- 1002 0014 Rage Fury Pro
- 1002 0018 Rage Fury Pro/Xpert 2000 Pro
- 1002 0028 Rage 128 Pro AIW AGP
- 1002 002a Rage 128 Pro AIW AGP
- 1002 0048 Rage Fury Pro
- 1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device)
- 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)
- 5047 Rage 128 PG/PRO
- 5048 Rage 128 PH/PRO AGP 2x
- 5049 Rage 128 PI/PRO AGP 4x
- 504a Rage 128 PJ/PRO TMDS
- 504b Rage 128 PK/PRO AGP 2x TMDS
- 504c Rage 128 PL/PRO AGP 4x TMDS
- 504d Rage 128 PM/PRO
- 504e Rage 128 PN/PRO AGP 2x
- 504f Rage 128 PO/PRO AGP 4x
- 5050 Rage 128 PP/PRO TMDS [Xpert 128]
- 1002 0008 Xpert 128
- 5051 Rage 128 PQ/PRO AGP 2x TMDS
- 5052 Rage 128 PR/PRO AGP 4x TMDS
- 5053 Rage 128 PS/PRO
- 5054 Rage 128 PT/PRO AGP 2x
- 5055 Rage 128 PU/PRO AGP 4x
- 5056 Rage 128 PV/PRO TMDS
- 5057 Rage 128 PW/PRO AGP 2x TMDS
- 5058 Rage 128 PX/PRO AGP 4x TMDS
- 5144 Radeon R100 QD [Radeon 7200]
- 1002 0008 Radeon 7000/Radeon VE
- 1002 0009 Radeon 7000/Radeon
- 1002 000a Radeon 7000/Radeon
- 1002 001a Radeon 7000/Radeon
- 1002 0029 Radeon AIW
- 1002 0038 Radeon 7000/Radeon
- 1002 0039 Radeon 7000/Radeon
- 1002 008a Radeon 7000/Radeon
- 1002 00ba Radeon 7000/Radeon
- 1002 0139 Radeon 7000/Radeon
- 1002 028a Radeon 7000/Radeon
- 1002 02aa Radeon AIW
- 1002 053a Radeon 7000/Radeon
- 5145 Radeon R100 QE
- 5146 Radeon R100 QF
- 5147 Radeon R100 QG
- 5148 Radeon R200 QH [Radeon 8500]
- 1002 010a FireGL 8800 64Mb
- 1002 0152 FireGL 8800 128Mb
- 1002 0162 FireGL 8700 32Mb
- 1002 0172 FireGL 8700 64Mb
- 5149 Radeon R200 QI
- 514a Radeon R200 QJ
- 514b Radeon R200 QK
- 514c Radeon R200 QL [Radeon 8500 LE]
- 1002 003a Radeon R200 QL [Radeon 8500 LE]
- 1002 013a Radeon 8500
- 148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition]
- 1681 0010 Radeon 8500 [3D Prophet 8500 128Mb]
- 174b 7149 Radeon R200 QL [Sapphire Radeon 8500 LE]
- 514d Radeon R200 QM [Radeon 9100]
- 514e Radeon R200 QN [Radeon 8500LE]
- 514f Radeon R200 QO [Radeon 8500LE]
- 5154 R200 QT [Radeon 8500]
- 5155 R200 QU [Radeon 9100]
- 5157 Radeon RV200 QW [Radeon 7500]
- 1002 013a Radeon 7500
- 1002 103a Dell Optiplex GX260
- 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR]
- 148c 2024 RV200 QW [Radeon 7500LE Dual Display]
- 148c 2025 RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
- 148c 2036 RV200 QW [Radeon 7500 PCI Dual Display]
- 174b 7146 RV200 QW [Radeon 7500 LE]
- 174b 7147 RV200 QW [Sapphire Radeon 7500LE]
- 174b 7161 Radeon RV200 QW [Radeon 7500 LE]
- 17af 0202 RV200 QW [Excalibur Radeon 7500LE]
- 5158 Radeon RV200 QX [Radeon 7500]
- 5159 Radeon RV100 QY [Radeon 7000/VE]
- 1002 000a Radeon 7000/Radeon VE
- 1002 000b Radeon 7000
- 1002 0038 Radeon 7000/Radeon VE
- 1002 003a Radeon 7000/Radeon VE
- 1002 00ba Radeon 7000/Radeon VE
- 1002 013a Radeon 7000/Radeon VE
- 1458 4002 RV100 QY [RADEON 7000 PRO MAYA AV Series]
- 148c 2003 RV100 QY [Radeon 7000 Multi-Display Edition]
- 148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display]
- 174b 7112 RV100 QY [Sapphire Radeon VE 7000]
- 174b 7c28 Sapphire Radeon VE 7000 DDR
- 1787 0202 RV100 QY [Excalibur Radeon 7000]
- 515a Radeon RV100 QZ [Radeon 7000/VE]
- 5168 Radeon R200 Qh
- 5169 Radeon R200 Qi
- 516a Radeon R200 Qj
- 516b Radeon R200 Qk
-# This one is not in ATI documentation, but is in XFree86 source code
- 516c Radeon R200 Ql
- 5245 Rage 128 RE/SG
- 1002 0008 Xpert 128
- 1002 0028 Rage 128 AIW
- 1002 0029 Rage 128 AIW
- 1002 0068 Rage 128 AIW
- 5246 Rage 128 RF/SG AGP
- 1002 0004 Magnum/Xpert 128/Xpert 99
- 1002 0008 Magnum/Xpert128/X99/Xpert2000
- 1002 0028 Rage 128 AIW AGP
- 1002 0044 Rage Fury/Xpert 128/Xpert 2000
- 1002 0068 Rage 128 AIW AGP
- 1002 0448 Rage Fury
- 5247 Rage 128 RG
- 524b Rage 128 RK/VR
- 524c Rage 128 RL/VR AGP
- 1002 0008 Xpert 99/Xpert 2000
- 1002 0088 Xpert 99
- 5345 Rage 128 SE/4x
- 5346 Rage 128 SF/4x AGP 2x
- 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL
- 5347 Rage 128 SG/4x AGP 4x
- 5348 Rage 128 SH
- 534b Rage 128 SK/4x
- 534c Rage 128 SL/4x AGP 2x
- 534d Rage 128 SM/4x AGP 4x
- 1002 0008 Xpert 99/Xpert 2000
- 1002 0018 Xpert 2000
- 534e Rage 128 4x
- 5354 Mach 64 VT
- 1002 5654 Mach 64 reference
- 5446 Rage 128 Pro Ultra TF
- 1002 0004 Rage Fury Pro
- 1002 0008 Rage Fury Pro/Xpert 2000 Pro
- 1002 0018 Rage Fury Pro/Xpert 2000 Pro
- 1002 0028 Rage 128 AIW Pro AGP
- 1002 0029 Rage 128 AIW
- 1002 002a Rage 128 AIW Pro AGP
- 1002 002b Rage 128 AIW
- 1002 0048 Xpert 2000 Pro
- 544c Rage 128 Pro Ultra TL
- 5452 Rage 128 Pro Ultra TR
- 1002 001c Rage 128 Pro 4XL
- 103c 1279 Rage 128 Pro 4XL
- 5453 Rage 128 Pro Ultra TS
- 5454 Rage 128 Pro Ultra TT
- 5455 Rage 128 Pro Ultra TU
- 5460 M22 [Radeon Mobility M300]
- 5464 M22 [FireGL GL]
- 5548 R423 UH [Radeon X800 (PCIE)]
- 5549 R423 UI [Radeon X800PRO (PCIE)]
- 554a R423 UJ [Radeon X800LE (PCIE)]
- 554b R423 UK [Radeon X800SE (PCIE)]
- 5551 R423 UQ [FireGL V7200 (PCIE)]
- 5552 R423 UR [FireGL V5100 (PCIE)]
- 5554 R423 UT [FireGL V7100 (PCIE)]
- 556b Radeon R423 UK (PCIE) [X800 SE] (Secondary)
- 5654 264VT [Mach64 VT]
- 1002 5654 Mach64VT Reference
- 5655 264VT3 [Mach64 VT3]
- 5656 264VT4 [Mach64 VT4]
- 5830 RS300 Host Bridge
- 5831 RS300 Host Bridge
- 5832 RS300 Host Bridge
- 5833 Radeon 9100 IGP Host Bridge
- 5834 Radeon 9100 IGP
- 5835 RS300M AGP [Radeon Mobility 9100IGP]
- 5838 Radeon 9100 IGP AGP Bridge
- 5941 RV280 [Radeon 9200] (Secondary)
- 1458 4019 Gigabyte Radeon 9200
- 174b 7c12 Sapphire Radeon 9200
-# http://www.hightech.com.hk/html/9200.htm
- 17af 200d Excalibur Radeon 9200
- 18bc 0050 GeXcube GC-R9200-C3 (Secondary)
- 5944 RV280 [Radeon 9200 SE (PCI)]
- 5960 RV280 [Radeon 9200 PRO]
- 5961 RV280 [Radeon 9200]
- 1002 2f72 All-in-Wonder 9200 Series
- 1019 4c30 Radeon 9200 VIVO
- 12ab 5961 YUAN SMARTVGA Radeon 9200
- 1458 4018 Gigabyte Radeon 9200
- 174b 7c13 Sapphire Radeon 9200
-# http://www.hightech.com.hk/html/9200.htm
- 17af 200c Excalibur Radeon 9200
- 18bc 0050 Radeon 9200 Game Buster
- 18bc 0051 GeXcube GC-R9200-C3
- 18bc 0053 Radeon 9200 Game Buster VIVO
- 5962 RV280 [Radeon 9200]
- 5964 RV280 [Radeon 9200 SE]
- 1043 c006 ASUS Radeon 9200 SE / TD / 128M
- 1458 4018 Radeon 9200 SE
- 148c 2073 CN-AG92E
- 174b 7c13 Sapphire Radeon 9200 SE
- 1787 5964 Excalibur 9200SE VIVO 128M
- 17af 2012 Radeon 9200 SE Excalibur
- 18bc 0170 Sapphire Radeon 9200 SE 128MB Game Buster
-# 128MB DDR, DVI/VGA/TV out
- 18bc 0173 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
- 5b60 RV370 5B60 [Radeon X300 (PCIE)]
- 1043 002a Extreme AX300SE-X
- 1043 032e Extreme AX300/TD
- 5b62 RV370 5B62 [Radeon X600 (PCIE)]
- 5b64 RV370 5B64 [FireGL V3100 (PCIE)]
- 5b65 RV370 5B65 [FireGL D1100 (PCIE)]
- 5c61 M9+ 5C61 [Radeon Mobility 9200 (AGP)]
- 5c63 M9+ 5C63 [Radeon Mobility 9200 (AGP)]
- 5d44 RV280 [Radeon 9200 SE] (Secondary)
- 1458 4019 Radeon 9200 SE (Secondary)
- 174b 7c12 Sapphire Radeon 9200 SE (Secondary)
- 1787 5965 Excalibur 9200SE VIVO 128M (Secondary)
- 17af 2013 Radeon 9200 SE Excalibur (Secondary)
- 18bc 0171 Radeon 9200 SE 128MB Game Buster (Secondary)
- 18bc 0172 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
- 5d4d R480 [Radeon X850XT Platinum]
- 5d57 R423 5F57 [Radeon X800XT (PCIE)]
- 700f PCI Bridge [IGP 320M]
- 7010 PCI Bridge [IGP 340M]
- 7834 Radeon 9100 PRO IGP
- 7835 Radeon Mobility 9200 IGP
- 7c37 RV350 AQ [Radeon 9600 SE]
- cab0 AGP Bridge [IGP 320M]
- cab2 RS200/RS200M AGP Bridge [IGP 340M]
- cbb2 RS200/RS200M AGP Bridge [IGP 340M]
-1003 ULSI Systems
- 0201 US201
-1004 VLSI Technology Inc
- 0005 82C592-FC1
- 0006 82C593-FC1
- 0007 82C594-AFC2
- 0008 82C596/7 [Wildcat]
- 0009 82C597-AFC2
- 000c 82C541 [Lynx]
- 000d 82C543 [Lynx]
- 0101 82C532
- 0102 82C534 [Eagle]
- 0103 82C538
- 0104 82C535
- 0105 82C147
- 0200 82C975
- 0280 82C925
- 0304 QSound ThunderBird PCI Audio
- 1004 0304 QSound ThunderBird PCI Audio
- 122d 1206 DSP368 Audio
- 1483 5020 XWave Thunder 3D Audio
- 0305 QSound ThunderBird PCI Audio Gameport
- 1004 0305 QSound ThunderBird PCI Audio Gameport
- 122d 1207 DSP368 Audio Gameport
- 1483 5021 XWave Thunder 3D Audio Gameport
- 0306 QSound ThunderBird PCI Audio Support Registers
- 1004 0306 QSound ThunderBird PCI Audio Support Registers
- 122d 1208 DSP368 Audio Support Registers
- 1483 5022 XWave Thunder 3D Audio Support Registers
- 0307 Thunderbird
- 0308 Thunderbird
- 0702 VAS96011 [Golden Gate II]
- 0703 Tollgate
-1005 Avance Logic Inc. [ALI]
- 2064 ALG2032/2064
- 2128 ALG2364A
- 2301 ALG2301
- 2302 ALG2302
- 2364 ALG2364
- 2464 ALG2364A
- 2501 ALG2564A/25128A
-1006 Reply Group
-1007 NetFrame Systems Inc
-1008 Epson
-100a Phoenix Technologies
-100b National Semiconductor Corporation
- 0001 DP83810
- 0002 87415/87560 IDE
- 000e 87560 Legacy I/O
- 000f FireWire Controller
- 0011 NS87560 National PCI System I/O
- 0012 USB Controller
- 0020 DP83815 (MacPhyter) Ethernet Controller
- 103c 0024 Pavilion ze4400 builtin Network
- 1385 f311 FA311 / FA312 (FA311 with WoL HW)
- 0022 DP83820 10/100/1000 Ethernet Controller
- 0028 Geode GX2 Host Bridge
- 002a CS5535 South Bridge
- 002b CS5535 ISA bridge
- 002d CS5535 IDE
- 002e CS5535 Audio
- 002f CS5535 USB
- 0030 Geode GX2 Graphics Processor
- 0035 DP83065 [Saturn] 10/100/1000 Ethernet Controller
- 0500 SCx200 Bridge
- 0501 SCx200 SMI
- 0502 SCx200 IDE
- 0503 SCx200 Audio
- 0504 SCx200 Video
- 0505 SCx200 XBus
- 0510 SC1100 Bridge
- 0511 SC1100 SMI
- 0515 SC1100 XBus
- d001 87410 IDE
-100c Tseng Labs Inc
- 3202 ET4000/W32p rev A
- 3205 ET4000/W32p rev B
- 3206 ET4000/W32p rev C
- 3207 ET4000/W32p rev D
- 3208 ET6000
- 4702 ET6300
-100d AST Research Inc
-100e Weitek
- 9000 P9000 Viper
- 9001 P9000 Viper
- 9002 P9000 Viper
- 9100 P9100 Viper Pro/SE
-1010 Video Logic, Ltd.
-1011 Digital Equipment Corporation
- 0001 DECchip 21050
- 0002 DECchip 21040 [Tulip]
- 0004 DECchip 21030 [TGA]
- 0007 NVRAM [Zephyr NVRAM]
- 0008 KZPSA [KZPSA]
- 0009 DECchip 21140 [FasterNet]
- 1025 0310 21140 Fast Ethernet
- 10b8 2001 SMC9332BDT EtherPower 10/100
- 10b8 2002 SMC9332BVT EtherPower T4 10/100
- 10b8 2003 SMC9334BDT EtherPower 10/100 (1-port)
- 1109 2400 ANA-6944A/TX Fast Ethernet
- 1112 2300 RNS2300 Fast Ethernet
- 1112 2320 RNS2320 Fast Ethernet
- 1112 2340 RNS2340 Fast Ethernet
- 1113 1207 EN-1207-TX Fast Ethernet
- 1186 1100 DFE-500TX Fast Ethernet
- 1186 1112 DFE-570TX Fast Ethernet
- 1186 1140 DFE-660 Cardbus Ethernet 10/100
- 1186 1142 DFE-660 Cardbus Ethernet 10/100
- 11f6 0503 Freedomline Fast Ethernet
- 1282 9100 AEF-380TXD Fast Ethernet
- 1385 1100 FA310TX Fast Ethernet
- 2646 0001 KNE100TX Fast Ethernet
- 000a 21230 Video Codec
- 000d PBXGB [TGA2]
- 000f DEFPA
- 0014 DECchip 21041 [Tulip Pass 3]
- 1186 0100 DE-530+
- 0016 DGLPB [OPPO]
- 0017 PV-PCI Graphics Controller (ZLXp-L)
- 0019 DECchip 21142/43
- 1011 500a DE500A Fast Ethernet
- 1011 500b DE500B Fast Ethernet
- 1014 0001 10/100 EtherJet Cardbus
- 1025 0315 ALN315 Fast Ethernet
- 1033 800c PC-9821-CS01 100BASE-TX Interface Card
- 1033 800d PC-9821NR-B06 100BASE-TX Interface Card
- 108d 0016 Rapidfire 2327 10/100 Ethernet
- 108d 0017 GoCard 2250 Ethernet 10/100 Cardbus
- 10b8 2005 SMC8032DT Extreme Ethernet 10/100
- 10b8 8034 SMC8034 Extreme Ethernet 10/100
- 10ef 8169 Cardbus Fast Ethernet
- 1109 2a00 ANA-6911A/TX Fast Ethernet
- 1109 2b00 ANA-6911A/TXC Fast Ethernet
- 1109 3000 ANA-6922/TX Fast Ethernet
- 1113 1207 Cheetah Fast Ethernet
- 1113 2220 Cardbus Fast Ethernet
- 115d 0002 Cardbus Ethernet 10/100
- 1179 0203 Fast Ethernet
- 1179 0204 Cardbus Fast Ethernet
- 1186 1100 DFE-500TX Fast Ethernet
- 1186 1101 DFE-500TX Fast Ethernet
- 1186 1102 DFE-500TX Fast Ethernet
- 1186 1112 DFE-570TX Quad Fast Ethernet
- 1259 2800 AT-2800Tx Fast Ethernet
- 1266 0004 Eagle Fast EtherMAX
- 12af 0019 NetFlyer Cardbus Fast Ethernet
- 1374 0001 Cardbus Ethernet Card 10/100
- 1374 0002 Cardbus Ethernet Card 10/100
- 1374 0007 Cardbus Ethernet Card 10/100
- 1374 0008 Cardbus Ethernet Card 10/100
- 1385 2100 FA510
- 1395 0001 10/100 Ethernet CardBus PC Card
- 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200)
- 14cb 0100 LNDL-100N 100Base-TX Ethernet PC Card
- 8086 0001 EtherExpress PRO/100 Mobile CardBus 32
- 001a Farallon PN9000SX Gigabit Ethernet
- 0021 DECchip 21052
- 0022 DECchip 21150
- 0023 DECchip 21150
- 0024 DECchip 21152
- 0025 DECchip 21153
- 0026 DECchip 21154
- 0034 56k Modem Cardbus
- 1374 0003 56k Modem Cardbus
- 0045 DECchip 21553
- 0046 DECchip 21554
- 0e11 4050 Integrated Smart Array
- 0e11 4051 Integrated Smart Array
- 0e11 4058 Integrated Smart Array
- 103c 10c2 Hewlett-Packard NetRAID-4M
- 12d9 000a IP Telephony card
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 9005 0364 5400S (Mustang)
- 9005 0365 5400S (Mustang)
- 9005 1364 Dell PowerEdge RAID Controller 2
- 9005 1365 Dell PowerEdge RAID Controller 2
- e4bf 1000 CC8-1-BLUES
- 1065 StrongARM DC21285
- 1069 0020 DAC960P / DAC1164P
-1012 Micronics Computers Inc
-1013 Cirrus Logic
- 0038 GD 7548
- 0040 GD 7555 Flat Panel GUI Accelerator
- 004c GD 7556 Video/Graphics LCD/CRT Ctrlr
- 00a0 GD 5430/40 [Alpine]
- 00a2 GD 5432 [Alpine]
- 00a4 GD 5434-4 [Alpine]
- 00a8 GD 5434-8 [Alpine]
- 00ac GD 5436 [Alpine]
- 00b0 GD 5440
- 00b8 GD 5446
- 00bc GD 5480
- 1013 00bc CL-GD5480
- 00d0 GD 5462
- 00d2 GD 5462 [Laguna I]
- 00d4 GD 5464 [Laguna]
- 00d5 GD 5464 BD [Laguna]
- 00d6 GD 5465 [Laguna]
- 13ce 8031 Barco Metheus 2 Megapixel, Dual Head
- 13cf 8031 Barco Metheus 2 Megapixel, Dual Head
- 00e8 GD 5436U
- 1100 CL 6729
- 1110 PD 6832 PCMCIA/CardBus Ctrlr
- 1112 PD 6834 PCMCIA/CardBus Ctrlr
- 1113 PD 6833 PCMCIA/CardBus Ctrlr
- 1200 GD 7542 [Nordic]
- 1202 GD 7543 [Viking]
- 1204 GD 7541 [Nordic Light]
- 4000 MD 5620 [CLM Data Fax Voice]
- 4400 CD 4400
- 6001 CS 4610/11 [CrystalClear SoundFusion Audio Accelerator]
- 1014 1010 CS4610 SoundFusion Audio Accelerator
- 6003 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator]
- 1013 4280 Crystal SoundFusion PCI Audio Accelerator
- 153b 1136 SiXPack 5.1+
- 1681 0050 Game Theater XP
- 1681 a011 Fortissimo III 7.1
- 6004 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator]
- 6005 Crystal CS4281 PCI Audio
- 1013 4281 Crystal CS4281 PCI Audio
- 10cf 10a8 Crystal CS4281 PCI Audio
- 10cf 10a9 Crystal CS4281 PCI Audio
- 10cf 10aa Crystal CS4281 PCI Audio
- 10cf 10ab Crystal CS4281 PCI Audio
- 10cf 10ac Crystal CS4281 PCI Audio
- 10cf 10ad Crystal CS4281 PCI Audio
- 10cf 10b4 Crystal CS4281 PCI Audio
- 1179 0001 Crystal CS4281 PCI Audio
- 14c0 000c Crystal CS4281 PCI Audio
-1014 IBM
- 0002 PCI to MCA Bridge
- 0005 Alta Lite
- 0007 Alta MP
- 000a Fire Coral
- 0017 CPU to PCI Bridge
- 0018 TR Auto LANstreamer
- 001b GXT-150P
- 001c Carrera
- 001d 82G2675
- 0020 GXT1000 Graphics Adapter
- 0022 IBM27-82351
- 002d Python
-# [official name in AIX 5]
- 002e SCSI RAID Adapter [ServeRAID]
- 1014 002e ServeRAID-3x
- 1014 022e ServeRAID-4H
- 0031 2 Port Serial Adapter
-# AS400 iSeries PCI sync serial card
- 1014 0031 2721 WAN IOA - 2 Port Sync Serial Adapter
- 0036 Miami
- 0037 82660 CPU to PCI Bridge
- 003a CPU to PCI Bridge
- 003c GXT250P/GXT255P Graphics Adapter
- 003e 16/4 Token ring UTP/STP controller
- 1014 003e Token-Ring Adapter
- 1014 00cd Token-Ring Adapter + Wake-On-LAN
- 1014 00ce 16/4 Token-Ring Adapter 2
- 1014 00cf 16/4 Token-Ring Adapter Special
- 1014 00e4 High-Speed 100/16/4 Token-Ring Adapter
- 1014 00e5 16/4 Token-Ring Adapter 2 + Wake-On-LAN
- 1014 016d iSeries 2744 Card
- 0045 SSA Adapter
- 0046 MPIC interrupt controller
- 0047 PCI to PCI Bridge
- 0048 PCI to PCI Bridge
- 0049 Warhead SCSI Controller
- 004e ATM Controller (14104e00)
- 004f ATM Controller (14104f00)
- 0050 ATM Controller (14105000)
- 0053 25 MBit ATM Controller
- 0054 GXT500P/GXT550P Graphics Adapter
- 0057 MPEG PCI Bridge
- 005c i82557B 10/100
- 005e GXT800P Graphics Adapter
- 007c ATM Controller (14107c00)
- 007d 3780IDSP [MWave]
- 008b EADS PCI to PCI Bridge
- 008e GXT3000P Graphics Adapter
- 0090 GXT 3000P
- 1014 008e GXT-3000P
- 0091 SSA Adapter
- 0095 20H2999 PCI Docking Bridge
- 0096 Chukar chipset SCSI controller
- 1014 0097 iSeries 2778 DASD IOA
- 1014 0098 iSeries 2763 DASD IOA
- 1014 0099 iSeries 2748 DASD IOA
- 009f PCI 4758 Cryptographic Accelerator
- 00a5 ATM Controller (1410a500)
- 00a6 ATM 155MBPS MM Controller (1410a600)
- 00b7 256-bit Graphics Rasterizer [Fire GL1]
- 1092 00b8 FireGL1 AGP 32Mb
- 00b8 GXT2000P Graphics Adapter
- 00be ATM 622MBPS Controller (1410be00)
- 00dc Advanced Systems Management Adapter (ASMA)
- 00fc CPC710 Dual Bridge and Memory Controller (PCI-64)
- 0104 Gigabit Ethernet-SX Adapter
- 0105 CPC710 Dual Bridge and Memory Controller (PCI-32)
- 010f Remote Supervisor Adapter (RSA)
- 0142 Yotta Video Compositor Input
- 1014 0143 Yotta Input Controller (ytin)
- 0144 Yotta Video Compositor Output
- 1014 0145 Yotta Output Controller (ytout)
- 0156 405GP PLB to PCI Bridge
- 015e 622Mbps ATM PCI Adapter
- 0160 64bit/66MHz PCI ATM 155 MMF
- 016e GXT4000P Graphics Adapter
- 0170 GXT6000P Graphics Adapter
- 017d GXT300P Graphics Adapter
- 0180 Snipe chipset SCSI controller
- 1014 0241 iSeries 2757 DASD IOA
- 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
- 0188 EADS-X PCI-X to PCI-X Bridge
- 01a7 PCI-X to PCI-X Bridge
- 01bd ServeRAID Controller
- 1014 01be ServeRAID-4M
- 1014 01bf ServeRAID-4L
- 1014 0208 ServeRAID-4Mx
- 1014 020e ServeRAID-4Lx
- 1014 022e ServeRAID-4H
- 1014 0258 ServeRAID-5i
- 1014 0259 ServeRAID-5i
- 01c1 64bit/66MHz PCI ATM 155 UTP
- 01e6 Cryptographic Accelerator
- 01ff 10/100 Mbps Ethernet
- 0219 Multiport Serial Adapter
- 1014 021a Dual RVX
- 1014 0251 Internal Modem/RVX
- 1014 0252 Quad Internal Modem
- 021b GXT6500P Graphics Adapter
- 021c GXT4500P Graphics Adapter
- 0233 GXT135P Graphics Adapter
- 0266 PCI-X Dual Channel SCSI
- 0268 Gigabit Ethernet-SX Adapter (PCI-X)
- 0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X)
- 028c Citrine chipset SCSI controller
- 1014 028D Dual Channel PCI-X DDR SAS RAID Adapter (572E)
- 1014 02BE Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B)
- 1014 02C0 Dual Channel PCI-X DDR U320 SCSI Adapter (571A)
- 0302 X-Architecture Bridge [Summit]
- 0314 ZISC 036 Neural accelerator card
- ffff MPIC-2 interrupt controller
-1015 LSI Logic Corp of Canada
-1016 ICL Personal Systems
-1017 SPEA Software AG
- 5343 SPEA 3D Accelerator
-1018 Unisys Systems
-1019 Elitegroup Computer Systems
-101a AT&T GIS (NCR)
- 0005 100VG ethernet
-101b Vitesse Semiconductor
-101c Western Digital
- 0193 33C193A
- 0196 33C196A
- 0197 33C197A
- 0296 33C296A
- 3193 7193
- 3197 7197
- 3296 33C296A
- 4296 34C296
- 9710 Pipeline 9710
- 9712 Pipeline 9712
- c24a 90C
-101e American Megatrends Inc.
- 1960 MegaRAID
- 101e 0471 MegaRAID 471 Enterprise 1600 RAID Controller
- 101e 0475 MegaRAID 475 Express 500/500LC RAID Controller
- 101e 0477 MegaRAID 477 Elite 3100 RAID Controller
- 101e 0493 MegaRAID 493 Elite 1600 RAID Controller
- 101e 0494 MegaRAID 494 Elite 1650 RAID Controller
- 101e 0503 MegaRAID 503 Enterprise 1650 RAID Controller
- 101e 0511 MegaRAID 511 i4 IDE RAID Controller
- 101e 0522 MegaRAID 522 i4133 RAID Controller
- 1028 0471 PowerEdge RAID Controller 3/QC
- 1028 0475 PowerEdge RAID Controller 3/SC
- 1028 0493 PowerEdge RAID Controller 3/DC
- 1028 0511 PowerEdge Cost Effective RAID Controller ATA100/4Ch
- 9010 MegaRAID 428 Ultra RAID Controller
- 9030 EIDE Controller
- 9031 EIDE Controller
- 9032 EIDE & SCSI Controller
- 9033 SCSI Controller
- 9040 Multimedia card
- 9060 MegaRAID 434 Ultra GT RAID Controller
- 9063 MegaRAC
- 101e 0767 Dell Remote Assistant Card 2
-101f PictureTel
-1020 Hitachi Computer Products
-1021 OKI Electric Industry Co. Ltd.
-1022 Advanced Micro Devices [AMD]
- 1100 K8 [Athlon64/Opteron] HyperTransport Technology Configuration
- 1101 K8 [Athlon64/Opteron] Address Map
- 1102 K8 [Athlon64/Opteron] DRAM Controller
- 1103 K8 [Athlon64/Opteron] Miscellaneous Control
- 2000 79c970 [PCnet32 LANCE]
- 1014 2000 NetFinity 10/100 Fast Ethernet
- 1022 2000 PCnet - Fast 79C971
- 103c 104c Ethernet with LAN remote power Adapter
- 103c 1064 Ethernet with LAN remote power Adapter
- 103c 1065 Ethernet with LAN remote power Adapter
- 103c 106c Ethernet with LAN remote power Adapter
- 103c 106e Ethernet with LAN remote power Adapter
- 103c 10ea Ethernet with LAN remote power Adapter
- 1113 1220 EN1220 10/100 Fast Ethernet
- 1259 2450 AT-2450 10/100 Fast Ethernet
- 1259 2454 AT-2450v4 10Mb Ethernet Adapter
- 1259 2700 AT-2700TX 10/100 Fast Ethernet
- 1259 2701 AT-2700FX 100Mb Ethernet
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1010 CP5/CR6 mainboard
- 4c53 1020 VR6 mainboard
- 4c53 1030 PC5 mainboard
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 2001 79c978 [HomePNA]
- 1092 0a78 Multimedia Home Network Adapter
- 1668 0299 ActionLink Home Network Adapter
- 2003 Am 1771 MBW [Alchemy]
- 2020 53c974 [PCscsi]
- 2040 79c974
- 3000 ELanSC520 Microcontroller
- 7006 AMD-751 [Irongate] System Controller
- 7007 AMD-751 [Irongate] AGP Bridge
- 700a AMD-IGR4 AGP Host to PCI Bridge
- 700b AMD-IGR4 PCI to PCI Bridge
- 700c AMD-760 MP [IGD4-2P] System Controller
- 700d AMD-760 MP [IGD4-2P] AGP Bridge
- 700e AMD-760 [IGD4-1P] System Controller
- 700f AMD-760 [IGD4-1P] AGP Bridge
- 7400 AMD-755 [Cobra] ISA
- 7401 AMD-755 [Cobra] IDE
- 7403 AMD-755 [Cobra] ACPI
- 7404 AMD-755 [Cobra] USB
- 7408 AMD-756 [Viper] ISA
- 7409 AMD-756 [Viper] IDE
- 740b AMD-756 [Viper] ACPI
- 740c AMD-756 [Viper] USB
- 7410 AMD-766 [ViperPlus] ISA
- 7411 AMD-766 [ViperPlus] IDE
- 7413 AMD-766 [ViperPlus] ACPI
- 7414 AMD-766 [ViperPlus] USB
- 7440 AMD-768 [Opus] ISA
- 1043 8044 A7M-D Mainboard
- 7441 AMD-768 [Opus] IDE
- 7443 AMD-768 [Opus] ACPI
- 1043 8044 A7M-D Mainboard
- 7445 AMD-768 [Opus] Audio
- 7446 AMD-768 [Opus] MC97 Modem (Smart Link HAMR5600 compatible)
- 7448 AMD-768 [Opus] PCI
- 7449 AMD-768 [Opus] USB
- 7450 AMD-8131 PCI-X Bridge
- 7451 AMD-8131 PCI-X APIC
- 7454 AMD-8151 System Controller
- 7455 AMD-8151 AGP Bridge
- 7460 AMD-8111 PCI
- 161f 3017 HDAMB
- 7461 AMD-8111 USB
- 7462 AMD-8111 Ethernet
- 7464 AMD-8111 USB
- 161f 3017 HDAMB
- 7468 AMD-8111 LPC
- 161f 3017 HDAMB
- 7469 AMD-8111 IDE
- 161f 3017 HDAMB
- 746a AMD-8111 SMBus 2.0
- 746b AMD-8111 ACPI
- 161f 3017 HDAMB
- 746d AMD-8111 AC97 Audio
- 161f 3017 HDAMB
- 746e AMD-8111 MC97 Modem
- 756b AMD-8111 ACPI
-1023 Trident Microsystems
- 0194 82C194
- 2000 4DWave DX
- 2001 4DWave NX
- 122d 1400 Trident PCI288-Q3DII (NX)
- 2100 CyberBlade XP4m32
- 2200 XGI Volari XP5
- 8400 CyberBlade/i7
- 1023 8400 CyberBlade i7 AGP
- 8420 CyberBlade/i7d
- 0e11 b15a CyberBlade i7 AGP
- 8500 CyberBlade/i1
- 8520 CyberBlade i1
- 0e11 b16e CyberBlade i1 AGP
- 1023 8520 CyberBlade i1 AGP
- 8620 CyberBlade/i1
- 1014 0502 ThinkPad R30/T30
- 8820 CyberBlade XPAi1
- 9320 TGUI 9320
- 9350 GUI Accelerator
- 9360 Flat panel GUI Accelerator
- 9382 Cyber 9382 [Reference design]
- 9383 Cyber 9383 [Reference design]
- 9385 Cyber 9385 [Reference design]
- 9386 Cyber 9386
- 9388 Cyber 9388
- 9397 Cyber 9397
- 939a Cyber 9397DVD
- 9420 TGUI 9420
- 9430 TGUI 9430
- 9440 TGUI 9440
- 9460 TGUI 9460
- 9470 TGUI 9470
- 9520 Cyber 9520
- 9525 Cyber 9525
- 10cf 1094 Lifebook C6155
- 9540 Cyber 9540
- 9660 TGUI 9660/938x/968x
- 9680 TGUI 9680
- 9682 TGUI 9682
- 9683 TGUI 9683
- 9685 ProVIDIA 9685
- 9750 3DImage 9750
- 1014 9750 3DImage 9750
- 1023 9750 3DImage 9750
- 9753 TGUI 9753
- 9754 TGUI 9754
- 9759 TGUI 975
- 9783 TGUI 9783
- 9785 TGUI 9785
- 9850 3DImage 9850
- 9880 Blade 3D PCI/AGP
- 1023 9880 Blade 3D
- 9910 CyberBlade/XP
- 9930 CyberBlade/XPm
-1024 Zenith Data Systems
-1025 Acer Incorporated [ALI]
- 1435 M1435
- 1445 M1445
- 1449 M1449
- 1451 M1451
- 1461 M1461
- 1489 M1489
- 1511 M1511
- 1512 ALI M1512 Aladdin
- 1513 M1513
- 1521 ALI M1521 Aladdin III CPU Bridge
- 10b9 1521 ALI M1521 Aladdin III CPU Bridge
- 1523 ALI M1523 ISA Bridge
- 10b9 1523 ALI M1523 ISA Bridge
- 1531 M1531 Northbridge [Aladdin IV/IV+]
- 1533 M1533 PCI-to-ISA Bridge
- 10b9 1533 ALI M1533 Aladdin IV/V ISA South Bridge
- 1535 M1535 PCI Bridge + Super I/O + FIR
- 1541 M1541 Northbridge [Aladdin V]
- 10b9 1541 ALI M1541 Aladdin V/V+ AGP+PCI North Bridge
- 1542 M1542 Northbridge [Aladdin V]
- 1543 M1543 PCI-to-ISA Bridge + Super I/O + FIR
- 1561 M1561 Northbridge [Aladdin 7]
- 1621 M1621 Northbridge [Aladdin-Pro II]
- 1631 M1631 Northbridge+3D Graphics [Aladdin TNT2]
- 1641 M1641 Northbridge [Aladdin-Pro IV]
- 1647 M1647 [MaGiK1] PCI North Bridge
- 1671 M1671 Northbridge [ALADDiN-P4]
- 1672 Northbridge [CyberALADDiN-P4]
- 3141 M3141
- 3143 M3143
- 3145 M3145
- 3147 M3147
- 3149 M3149
- 3151 M3151
- 3307 M3307 MPEG-I Video Controller
- 3309 M3309 MPEG-II Video w/ Software Audio Decoder
- 3321 M3321 MPEG-II Audio/Video Decoder
- 5212 M4803
- 5215 ALI PCI EIDE Controller
- 5217 M5217H
- 5219 M5219
- 5225 M5225
- 5229 M5229
- 5235 M5235
- 5237 M5237 PCI USB Host Controller
- 5240 EIDE Controller
- 5241 PCMCIA Bridge
- 5242 General Purpose Controller
- 5243 PCI to PCI Bridge Controller
- 5244 Floppy Disk Controller
- 5247 M1541 PCI to PCI Bridge
- 5251 M5251 P1394 Controller
- 5427 PCI to AGP Bridge
- 5451 M5451 PCI AC-Link Controller Audio Device
- 5453 M5453 PCI AC-Link Controller Modem Device
- 7101 M7101 PCI PMU Power Management Controller
- 10b9 7101 M7101 PCI PMU Power Management Controller
-1028 Dell
- 0001 PowerEdge Expandable RAID Controller 2/Si
- 1028 0001 PowerEdge 2400
- 0002 PowerEdge Expandable RAID Controller 3/Di
- 1028 0002 PowerEdge 4400
- 0003 PowerEdge Expandable RAID Controller 3/Si
- 1028 0003 PowerEdge 2450
- 0006 PowerEdge Expandable RAID Controller 3/Di
- 0007 Remote Access Card III
- 0008 Remote Access Card III
- 0009 Remote Access Card III: BMC/SMIC device not present
- 000a PowerEdge Expandable RAID Controller 3/Di
- 000c Embedded Remote Access or ERA/O
- 000d Embedded Remote Access: BMC/SMIC device
- 000e PowerEdge Expandable RAID controller 4/Di
- 000f PowerEdge Expandable RAID controller 4/Di
- 0010 Remote Access Card 4
- 0011 Remote Access Card 4 Daughter Card
- 0012 Remote Access Card 4 Daughter Card Virtual UART
- 0013 PowerEdge Expandable RAID controller 4
- 1028 016c PowerEdge Expandable RAID Controller 4e/Si
- 1028 016d PowerEdge Expandable RAID Controller 4e/Di
- 1028 016e PowerEdge Expandable RAID Controller 4e/Di
- 1028 016f PowerEdge Expandable RAID Controller 4e/Di
- 1028 0170 PowerEdge Expandable RAID Controller 4e/Di
- 0014 Remote Access Card 4 Daughter Card SMIC interface
-1029 Siemens Nixdorf IS
-102a LSI Logic
- 0000 HYDRA
- 0010 ASPEN
- 001f AHA-2940U2/U2W /7890/7891 SCSI Controllers
- 9005 000f 2940U2W SCSI Controller
- 9005 0106 2940U2W SCSI Controller
- 9005 a180 2940U2W SCSI Controller
- 00c5 AIC-7899 U160/m SCSI Controller
- 1028 00c5 PowerEdge 2550/2650/4600
- 00cf AIC-7899P U160/m
- 1028 0106 PowerEdge 4600
- 1028 0121 PowerEdge 2650
-102b Matrox Graphics, Inc.
-# DJ: I've a suspicion that 0010 is a duplicate of 0d10.
- 0010 MGA-I [Impression?]
- 0100 MGA 1064SG [Mystique]
- 0518 MGA-II [Athena]
- 0519 MGA 2064W [Millennium]
- 051a MGA 1064SG [Mystique]
- 102b 0100 MGA-1064SG Mystique
- 102b 1100 MGA-1084SG Mystique
- 102b 1200 MGA-1084SG Mystique
- 1100 102b MGA-1084SG Mystique
- 110a 0018 Scenic Pro C5 (D1025)
- 051b MGA 2164W [Millennium II]
- 102b 051b MGA-2164W Millennium II
- 102b 1100 MGA-2164W Millennium II
- 102b 1200 MGA-2164W Millennium II
- 051e MGA 1064SG [Mystique] AGP
- 051f MGA 2164W [Millennium II] AGP
- 0520 MGA G200
- 102b dbc2 G200 Multi-Monitor
- 102b dbc8 G200 Multi-Monitor
- 102b dbe2 G200 Multi-Monitor
- 102b dbe8 G200 Multi-Monitor
- 102b ff03 Millennium G200 SD
- 102b ff04 Marvel G200
- 0521 MGA G200 AGP
- 1014 ff03 Millennium G200 AGP
- 102b 48e9 Mystique G200 AGP
- 102b 48f8 Millennium G200 SD AGP
- 102b 4a60 Millennium G200 LE AGP
- 102b 4a64 Millennium G200 AGP
- 102b c93c Millennium G200 AGP
- 102b c9b0 Millennium G200 AGP
- 102b c9bc Millennium G200 AGP
- 102b ca60 Millennium G250 LE AGP
- 102b ca6c Millennium G250 AGP
- 102b dbbc Millennium G200 AGP
- 102b dbc2 Millennium G200 MMS (Dual G200)
- 102b dbc3 G200 Multi-Monitor
- 102b dbc8 Millennium G200 MMS (Dual G200)
- 102b dbd2 G200 Multi-Monitor
- 102b dbd3 G200 Multi-Monitor
- 102b dbd4 G200 Multi-Monitor
- 102b dbd5 G200 Multi-Monitor
- 102b dbd8 G200 Multi-Monitor
- 102b dbd9 G200 Multi-Monitor
- 102b dbe2 Millennium G200 MMS (Quad G200)
- 102b dbe3 G200 Multi-Monitor
- 102b dbe8 Millennium G200 MMS (Quad G200)
- 102b dbf2 G200 Multi-Monitor
- 102b dbf3 G200 Multi-Monitor
- 102b dbf4 G200 Multi-Monitor
- 102b dbf5 G200 Multi-Monitor
- 102b dbf8 G200 Multi-Monitor
- 102b dbf9 G200 Multi-Monitor
- 102b f806 Mystique G200 Video AGP
- 102b ff00 MGA-G200 AGP
- 102b ff02 Mystique G200 AGP
- 102b ff03 Millennium G200 AGP
- 102b ff04 Marvel G200 AGP
- 110a 0032 MGA-G200 AGP
- 0525 MGA G400 AGP
- 0e11 b16f MGA-G400 AGP
- 102b 0328 Millennium G400 16Mb SDRAM
- 102b 0338 Millennium G400 16Mb SDRAM
- 102b 0378 Millennium G400 32Mb SDRAM
- 102b 0541 Millennium G450 Dual Head
- 102b 0542 Millennium G450 Dual Head LX
- 102b 0543 Millennium G450 Single Head LX
- 102b 0641 Millennium G450 32Mb SDRAM Dual Head
- 102b 0642 Millennium G450 32Mb SDRAM Dual Head LX
- 102b 0643 Millennium G450 32Mb SDRAM Single Head LX
- 102b 07c0 Millennium G450 Dual Head LE
- 102b 07c1 Millennium G450 SDR Dual Head LE
- 102b 0d41 Millennium G450 Dual Head PCI
- 102b 0d42 Millennium G450 Dual Head LX PCI
- 102b 0d43 Millennium G450 32Mb Dual Head PCI
- 102b 0e00 Marvel G450 eTV
- 102b 0e01 Marvel G450 eTV
- 102b 0e02 Marvel G450 eTV
- 102b 0e03 Marvel G450 eTV
- 102b 0f80 Millennium G450 Low Profile
- 102b 0f81 Millennium G450 Low Profile
- 102b 0f82 Millennium G450 Low Profile DVI
- 102b 0f83 Millennium G450 Low Profile DVI
- 102b 19d8 Millennium G400 16Mb SGRAM
- 102b 19f8 Millennium G400 32Mb SGRAM
- 102b 2159 Millennium G400 Dual Head 16Mb
- 102b 2179 Millennium G400 MAX/Dual Head 32Mb
- 102b 217d Millennium G400 Dual Head Max
- 102b 23c0 Millennium G450
- 102b 23c1 Millennium G450
- 102b 23c2 Millennium G450 DVI
- 102b 23c3 Millennium G450 DVI
- 102b 2f58 Millennium G400
- 102b 2f78 Millennium G400
- 102b 3693 Marvel G400 AGP
- 102b 5dd0 4Sight II
- 102b 5f50 4Sight II
- 102b 5f51 4Sight II
- 102b 5f52 4Sight II
- 102b 9010 Millennium G400 Dual Head
- 1458 0400 GA-G400
- 1705 0001 Millennium G450 32MB SGRAM
- 1705 0002 Millennium G450 16MB SGRAM
- 1705 0003 Millennium G450 32MB
- 1705 0004 Millennium G450 16MB
- 0527 MGA Parhelia AGP
- 102b 0840 Parhelia 128Mb
- 0d10 MGA Ultima/Impression
- 1000 MGA G100 [Productiva]
- 102b ff01 Productiva G100
- 102b ff05 Productiva G100 Multi-Monitor
- 1001 MGA G100 [Productiva] AGP
- 102b 1001 MGA-G100 AGP
- 102b ff00 MGA-G100 AGP
- 102b ff01 MGA-G100 Productiva AGP
- 102b ff03 Millennium G100 AGP
- 102b ff04 MGA-G100 AGP
- 102b ff05 MGA-G100 Productiva AGP Multi-Monitor
- 110a 001e MGA-G100 AGP
- 2007 MGA Mistral
- 2527 MGA G550 AGP
- 102b 0f83 Millennium G550
- 102b 0f84 Millennium G550 Dual Head DDR 32Mb
- 102b 1e41 Millennium G550
- 2537 MGA G650 AGP
- 4536 VIA Framegrabber
- 6573 Shark 10/100 Multiport SwitchNIC
-102c Chips and Technologies
- 00b8 F64310
- 00c0 F69000 HiQVideo
- 102c 00c0 F69000 HiQVideo
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1010 CP5/CR6 mainboard
- 4c53 1020 VR6 mainboard
- 4c53 1030 PC5 mainboard
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 00d0 F65545
- 00d8 F65545
- 00dc F65548
- 00e0 F65550
- 00e4 F65554
- 00e5 F65555 HiQVPro
- 0e11 b049 Armada 1700 Laptop Display Controller
- 00f0 F68554
- 00f4 F68554 HiQVision
- 00f5 F68555
- 0c30 F69030
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
-# C5C project cancelled
- 4c53 1080 CT8 mainboard
-102d Wyse Technology Inc.
- 50dc 3328 Audio
-102e Olivetti Advanced Technology
-102f Toshiba America
- 0009 r4x00
- 000a TX3927 MIPS RISC PCI Controller
- 0020 ATM Meteor 155
- 102f 00f8 ATM Meteor 155
- 0030 TC35815CF PCI 10/100 Mbit Ethernet Controller
- 0031 TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL
- 0105 TC86C001 [goku-s] IDE
- 0106 TC86C001 [goku-s] USB 1.1 Host
- 0107 TC86C001 [goku-s] USB Device Controller
- 0108 TC86C001 [goku-s] I2C/SIO/GPIO Controller
- 0180 TX4927/38 MIPS RISC PCI Controller
- 0181 TX4925 MIPS RISC PCI Controller
- 0182 TX4937 MIPS RISC PCI Controller
-1030 TMC Research
-1031 Miro Computer Products AG
- 5601 DC20 ASIC
- 5607 Video I/O & motion JPEG compressor
- 5631 Media 3D
- 6057 MiroVideo DC10/DC30+
-1032 Compaq
-1033 NEC Corporation
- 0000 Vr4181A USB Host or Function Control Unit
- 0001 PCI to 486-like bus Bridge
- 0002 PCI to VL98 Bridge
- 0003 ATM Controller
- 0004 R4000 PCI Bridge
- 0005 PCI to 486-like bus Bridge
- 0006 PC-9800 Graphic Accelerator
- 0007 PCI to UX-Bus Bridge
- 0008 PC-9800 Graphic Accelerator
- 0009 PCI to PC9800 Core-Graph Bridge
- 0016 PCI to VL Bridge
- 001a [Nile II]
- 0021 Vrc4373 [Nile I]
- 0029 PowerVR PCX1
- 002a PowerVR 3D
- 002c Star Alpha 2
- 002d PCI to C-bus Bridge
- 0035 USB
- 1179 0001 USB
- 12ee 7000 Root Hub
- 1799 0001 Root Hub
- 807d 0035 PCI-USB2 (OHCI subsystem)
- 003b PCI to C-bus Bridge
- 003e NAPCCARD Cardbus Controller
- 0046 PowerVR PCX2 [midas]
- 005a Vrc5074 [Nile 4]
- 0063 Firewarden
- 0067 PowerVR Neon 250 Chipset
- 1010 0020 PowerVR Neon 250 AGP 32Mb
- 1010 0080 PowerVR Neon 250 AGP 16Mb
- 1010 0088 PowerVR Neon 250 16Mb
- 1010 0090 PowerVR Neon 250 AGP 16Mb
- 1010 0098 PowerVR Neon 250 16Mb
- 1010 00a0 PowerVR Neon 250 AGP 32Mb
- 1010 00a8 PowerVR Neon 250 32Mb
- 1010 0120 PowerVR Neon 250 AGP 32Mb
- 0072 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr
- 0074 56k Voice Modem
- 1033 8014 RCV56ACF 56k Voice Modem
- 009b Vrc5476
- 00a5 VRC4173
- 00a6 VRC5477 AC97
- 00cd IEEE 1394 [OrangeLink] Host Controller
- 12ee 8011 Root hub
- 00ce IEEE 1394 Host Controller
- 00df Vr4131
- 00e0 USB 2.0
- 0ee4 3383 Sitecom IEEE 1394 / USB2.0 Combo Card
- 12ee 7001 Root hub
- 1799 0002 Root Hub
- 807d 1043 PCI-USB2 (EHCI subsystem)
- 00e7 IEEE 1394 Host Controller
- 00f2 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr
- 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2]
- 010c VR7701
-1034 Framatome Connectors USA Inc.
-1035 Comp. & Comm. Research Lab
-1036 Future Domain Corp.
- 0000 TMC-18C30 [36C70]
-1037 Hitachi Micro Systems
-1038 AMP, Inc
-1039 Silicon Integrated Systems [SiS]
- 0001 Virtual PCI-to-PCI bridge (AGP)
- 0002 SG86C202
- 0006 85C501/2/3
- 0008 SiS85C503/5513 (LPC Bridge)
- 0009 ACPI
-# source: http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
- 0016 SiS961/2 SMBus Controller
- 0018 SiS85C503/5513 (LPC Bridge)
-# Controller for 2 PATA and 2 SATA channels
- 0180 RAID bus controller 180 SATA/PATA [SiS]
- 0181 SiS SATA
- 0200 5597/5598/6326 VGA
- 1039 0000 SiS5597 SVGA (Shared RAM)
- 0204 82C204
- 0205 SG86C205
- 0300 300/305 PCI/AGP VGA Display Adapter
- 107d 2720 Leadtek WinFast VR300
- 0310 315H PCI/AGP VGA Display Adapter
- 0315 315 PCI/AGP VGA Display Adapter
- 0325 315PRO PCI/AGP VGA Display Adapter
- 0330 330 [Xabre] PCI/AGP VGA Display Adapter
- 0406 85C501/2
- 0496 85C496
- 0530 530 Host
- 0540 540 Host
- 0550 550 Host
- 0597 5513C
- 0601 85C601
- 0620 620 Host
- 0630 630 Host
- 0633 633 Host
- 0635 635 Host
- 0645 SiS645 Host & Memory & AGP Controller
- 0646 SiS645DX Host & Memory & AGP Controller
- 0648 SiS 645xx
- 0650 650/M650 Host
- 0651 651 Host
- 0655 655 Host
- 0660 660 Host
- 0661 661FX/M661FX/M661MX Host
- 0730 730 Host
- 0733 733 Host
- 0735 735 Host
- 0740 740 Host
- 0741 741/741GX/M741 Host
- 0745 745 Host
- 0746 746 Host
- 0755 755 Host
- 0760 760/M760 Host
- 0900 SiS900 PCI Fast Ethernet
- 1019 0a14 K7S5A motherboard
- 1039 0900 SiS900 10/100 Ethernet Adapter
- 1043 8035 CUSI-FX motherboard
- 0961 SiS961 [MuTIOL Media IO]
- 0962 SiS962 [MuTIOL Media IO]
- 0963 SiS963 [MuTIOL Media IO]
- 0964 SiS964 [MuTIOL Media IO]
- 0965 SiS965 [MuTIOL Media IO]
- 3602 83C602
- 5107 5107
- 5300 SiS540 PCI Display Adapter
- 5315 550 PCI/AGP VGA Display Adapter
- 5401 486 PCI Chipset
- 5511 5511/5512
- 5513 5513 [IDE]
- 1019 0970 P6STP-FL motherboard
- 1039 5513 SiS5513 EIDE Controller (A,B step)
- 1043 8035 CUSI-FX motherboard
- 5517 5517
- 5571 5571
- 5581 5581 Pentium Chipset
- 5582 5582
- 5591 5591/5592 Host
- 5596 5596 Pentium Chipset
- 5597 5597 [SiS5582]
- 5600 5600 Host
- 6204 Video decoder & MPEG interface
- 6205 VGA Controller
- 6236 6236 3D-AGP
- 6300 630/730 PCI/AGP VGA Display Adapter
- 1019 0970 P6STP-FL motherboard
- 1043 8035 CUSI-FX motherboard
- 6306 530/620 PCI/AGP VGA Display Adapter
- 1039 6306 SiS530,620 GUI Accelerator+3D
- 6325 65x/M650/740 PCI/AGP VGA Display Adapter
- 6326 86C326 5598/6326
- 1039 6326 SiS6326 GUI Accelerator
- 1092 0a50 SpeedStar A50
- 1092 0a70 SpeedStar A70
- 1092 4910 SpeedStar A70
- 1092 4920 SpeedStar A70
- 1569 6326 SiS6326 GUI Accelerator
- 6330 661/741/760 PCI/AGP VGA Display Adapter
- 1039 6330 [M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter
- 7001 USB 1.0 Controller
- 1019 0a14 K7S5A motherboard
- 1039 7000 Onboard USB Controller
- 7002 USB 2.0 Controller
- 1509 7002 Onboard USB Controller
- 7007 FireWire Controller
- 7012 Sound Controller
-# There are may be different modem codecs here (Intel537 compatible and incompatible)
- 7013 AC'97 Modem Controller
- 7016 SiS7016 PCI Fast Ethernet Adapter
- 1039 7016 SiS7016 10/100 Ethernet Adapter
- 7018 SiS PCI Audio Accelerator
- 1014 01b6 SiS PCI Audio Accelerator
- 1014 01b7 SiS PCI Audio Accelerator
- 1019 7018 SiS PCI Audio Accelerator
- 1025 000e SiS PCI Audio Accelerator
- 1025 0018 SiS PCI Audio Accelerator
- 1039 7018 SiS PCI Audio Accelerator
- 1043 800b SiS PCI Audio Accelerator
- 1054 7018 SiS PCI Audio Accelerator
- 107d 5330 SiS PCI Audio Accelerator
- 107d 5350 SiS PCI Audio Accelerator
- 1170 3209 SiS PCI Audio Accelerator
- 1462 400a SiS PCI Audio Accelerator
- 14a4 2089 SiS PCI Audio Accelerator
- 14cd 2194 SiS PCI Audio Accelerator
- 14ff 1100 SiS PCI Audio Accelerator
- 152d 8808 SiS PCI Audio Accelerator
- 1558 1103 SiS PCI Audio Accelerator
- 1558 2200 SiS PCI Audio Accelerator
- 1563 7018 SiS PCI Audio Accelerator
- 15c5 0111 SiS PCI Audio Accelerator
- 270f a171 SiS PCI Audio Accelerator
- a0a0 0022 SiS PCI Audio Accelerator
- 7019 SiS7019 Audio Accelerator
-103a Seiko Epson Corporation
-103b Tatung Co. of America
-103c Hewlett-Packard Company
- 1005 A4977A Visualize EG
- 1006 Visualize FX6
- 1008 Visualize FX4
- 100a Visualize FX2
- 1028 Tach TL Fibre Channel Host Adapter
- 1029 Tach XL2 Fibre Channel Host Adapter
- 107e 000f Interphase 5560 Fibre Channel Adapter
- 9004 9210 1Gb/2Gb Family Fibre Channel Controller
- 9004 9211 1Gb/2Gb Family Fibre Channel Controller
- 102a Tach TS Fibre Channel Host Adapter
- 107e 000e Interphase 5540/5541 Fibre Channel Adapter
- 9004 9110 1Gb/2Gb Family Fibre Channel Controller
- 9004 9111 1Gb/2Gb Family Fibre Channel Controller
- 1030 J2585A DeskDirect 10/100VG NIC
- 1031 J2585B HP 10/100VG PCI LAN Adapter
- 103c 1040 J2973A DeskDirect 10BaseT NIC
- 103c 1041 J2585B DeskDirect 10/100VG NIC
- 103c 1042 J2970A DeskDirect 10BaseT/2 NIC
- 1040 J2973A DeskDirect 10BaseT NIC
- 1041 J2585B DeskDirect 10/100 NIC
- 1042 J2970A DeskDirect 10BaseT/2 NIC
- 1048 Diva Serial [GSP] Multiport UART
- 103c 1049 Tosca Console
- 103c 104a Tosca Secondary
- 103c 104b Maestro SP2
- 103c 1223 Superdome Console
- 103c 1226 Keystone SP2
- 103c 1227 Powerbar SP2
- 103c 1282 Everest SP2
- 103c 1301 Diva RMP3
- 1054 PCI Local Bus Adapter
- 1064 79C970 PCnet Ethernet Controller
- 108b Visualize FXe
- 10c1 NetServer Smart IRQ Router
- 10ed TopTools Remote Control
- 10f0 rio System Bus Adapter
- 10f1 rio I/O Controller
- 1200 82557B 10/100 NIC
- 1219 NetServer PCI Hot-Plug Controller
- 121a NetServer SMIC Controller
- 121b NetServer Legacy COM Port Decoder
- 121c NetServer PCI COM Port Decoder
- 1229 zx1 System Bus Adapter
- 122a zx1 I/O Controller
- 122e zx1 Local Bus Adapter
- 127c sx1000 I/O Controller
- 1290 Auxiliary Diva Serial Port
- 12b4 zx1 QuickSilver AGP8x Local Bus Adapter
- 2910 E2910A PCIBus Exerciser
- 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer
-103e Solliday Engineering
-103f Synopsys/Logic Modeling Group
-1040 Accelgraphics Inc.
-1041 Computrend
-1042 Micron
- 1000 PC Tech RZ1000
- 1001 PC Tech RZ1001
- 3000 Samurai_0
- 3010 Samurai_1
- 3020 Samurai_IDE
-1043 ASUSTeK Computer Inc.
- 0675 ISDNLink P-IN100-ST-D
- 4015 v7100 SDRAM [GeForce2 MX]
- 4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner]
- 4057 v8200 GeForce 3
- 8043 v8240 PAL 128M [P4T] Motherboard
- 807b v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
- 80bb v9180 Magic/T [GeForce4 MX440 AGP 8x 64MB TV-out]
- 80c5 nForce3 chipset motherboard [SK8N]
- 80df v9520 Magic/T
-1044 Adaptec (formerly DPT)
- 1012 Domino RAID Engine
- a400 SmartCache/Raid I-IV Controller
- a500 PCI Bridge
- a501 SmartRAID V Controller
- 1044 c001 PM1554U2 Ultra2 Single Channel
- 1044 c002 PM1654U2 Ultra2 Single Channel
- 1044 c003 PM1564U3 Ultra3 Single Channel
- 1044 c004 PM1564U3 Ultra3 Dual Channel
- 1044 c005 PM1554U2 Ultra2 Single Channel (NON ACPI)
- 1044 c00a PM2554U2 Ultra2 Single Channel
- 1044 c00b PM2654U2 Ultra2 Single Channel
- 1044 c00c PM2664U3 Ultra3 Single Channel
- 1044 c00d PM2664U3 Ultra3 Dual Channel
- 1044 c00e PM2554U2 Ultra2 Single Channel (NON ACPI)
- 1044 c00f PM2654U2 Ultra2 Single Channel (NON ACPI)
- 1044 c014 PM3754U2 Ultra2 Single Channel (NON ACPI)
- 1044 c015 PM3755U2B Ultra2 Single Channel (NON ACPI)
- 1044 c016 PM3755F Fibre Channel (NON ACPI)
- 1044 c01e PM3757U2 Ultra2 Single Channel
- 1044 c01f PM3757U2 Ultra2 Dual Channel
- 1044 c020 PM3767U3 Ultra3 Dual Channel
- 1044 c021 PM3767U3 Ultra3 Quad Channel
- 1044 c028 PM2865U3 Ultra3 Single Channel
- 1044 c029 PM2865U3 Ultra3 Dual Channel
- 1044 c02a PM2865F Fibre Channel
- 1044 c03c 2000S Ultra3 Single Channel
- 1044 c03d 2000S Ultra3 Dual Channel
- 1044 c03e 2000F Fibre Channel
- 1044 c046 3000S Ultra3 Single Channel
- 1044 c047 3000S Ultra3 Dual Channel
- 1044 c048 3000F Fibre Channel
- 1044 c050 5000S Ultra3 Single Channel
- 1044 c051 5000S Ultra3 Dual Channel
- 1044 c052 5000F Fibre Channel
- 1044 c05a 2400A UDMA Four Channel
- 1044 c05b 2400A UDMA Four Channel DAC
- 1044 c064 3010S Ultra3 Dual Channel
- 1044 c065 3410S Ultra160 Four Channel
- 1044 c066 3010S Fibre Channel
- a511 SmartRAID V Controller
- 1044 c032 ASR-2005S I2O Zero Channel
-1045 OPTi Inc.
- a0f8 82C750 [Vendetta] USB Controller
- c101 92C264
- c178 92C178
- c556 82X556 [Viper]
- c557 82C557 [Viper-M]
- c558 82C558 [Viper-M ISA+IDE]
- c567 82C750 [Vendetta], device 0
- c568 82C750 [Vendetta], device 1
- c569 82C579 [Viper XPress+ Chipset]
- c621 82C621 [Viper-M/N+]
- c700 82C700 [FireStar]
- c701 82C701 [FireStar Plus]
- c814 82C814 [Firebridge 1]
- c822 82C822
- c824 82C824
- c825 82C825 [Firebridge 2]
- c832 82C832
- c861 82C861
- c895 82C895
- c935 EV1935 ECTIVA MachOne PCIAudio
- d568 82C825 [Firebridge 2]
- d721 IDE [FireStar]
-1046 IPC Corporation, Ltd.
-1047 Genoa Systems Corp
-1048 Elsa AG
- 0c60 Gladiac MX
- 0d22 Quadro4 900XGL [ELSA GLoria4 900XGL]
- 1000 QuickStep 1000
- 3000 QuickStep 3000
- 8901 Gloria XL
-1049 Fountain Technologies, Inc.
-# # nee SGS Thomson Microelectronics
-104a STMicroelectronics
- 0008 STG 2000X
- 0009 STG 1764X
- 0010 STG4000 [3D Prophet Kyro Series]
- 0209 STPC Consumer/Industrial North- and Southbridge
- 020a STPC Atlas/ConsumerS/Consumer IIA Northbridge
-# From <http://gatekeeper.dec.com/pub/BSD/FreeBSD/FreeBSD-stable/src/share/misc/pci_vendors>
- 0210 STPC Atlas ISA Bridge
- 021a STPC Consumer S Southbridge
- 021b STPC Consumer IIA Southbridge
- 0500 ST70137 [Unicorn] ADSL DMT Transceiver
- 0564 STPC Client Northbridge
- 0981 21x4x DEC-Tulip compatible 10/100 Ethernet
- 1746 STG 1764X
- 2774 21x4x DEC-Tulip compatible 10/100 Ethernet
- 3520 MPEG-II decoder card
- 55cc STPC Client Southbridge
-104b BusLogic
- 0140 BT-946C (old) [multimaster 01]
- 1040 BT-946C (BA80C30) [MultiMaster 10]
- 8130 Flashpoint LT
-104c Texas Instruments
- 0500 100 MBit LAN Controller
- 0508 TMS380C2X Compressor Interface
- 1000 Eagle i/f AS
- 104c PCI1510 PC card Cardbus Controller
- 3d04 TVP4010 [Permedia]
- 3d07 TVP4020 [Permedia 2]
- 1011 4d10 Comet
- 1040 000f AccelStar II
- 1040 0011 AccelStar II
- 1048 0a31 WINNER 2000
- 1048 0a32 GLoria Synergy
- 1048 0a35 GLoria Synergy
- 107d 2633 WinFast 3D L2300
- 1092 0127 FIRE GL 1000 PRO
- 1092 0136 FIRE GL 1000 PRO
- 1092 0141 FIRE GL 1000 PRO
- 1092 0146 FIRE GL 1000 PRO
- 1092 0148 FIRE GL 1000 PRO
- 1092 0149 FIRE GL 1000 PRO
- 1092 0152 FIRE GL 1000 PRO
- 1092 0154 FIRE GL 1000 PRO
- 1092 0155 FIRE GL 1000 PRO
- 1092 0156 FIRE GL 1000 PRO
- 1092 0157 FIRE GL 1000 PRO
- 1097 3d01 Jeronimo Pro
- 1102 100f Graphics Blaster Extreme
- 3d3d 0100 Reference Permedia 2 3D
- 8000 PCILynx/PCILynx2 IEEE 1394 Link Layer Controller
- e4bf 1010 CF1-1-SNARE
- e4bf 1020 CF1-2-SNARE
- 8009 FireWire Controller
- 104d 8032 8032 OHCI i.LINK (IEEE 1394) Controller
- 8017 PCI4410 FireWire Controller
- 8019 TSB12LV23 IEEE-1394 Controller
- 11bd 000a Studio DV500-1394
- 11bd 000e Studio DV
- e4bf 1010 CF2-1-CYMBAL
- 8020 TSB12LV26 IEEE-1394 Controller (Link)
- 11bd 000f Studio DV500-1394
- 8021 TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated)
- 104d 80df Vaio PCG-FX403
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 8022 TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link)
- 8023 TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)
- 103c 088c nc8000 laptop
- 8024 TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link)
- 8025 TSB82AA2 IEEE-1394b Link Layer Controller
- 55aa 55aa FireWire 800 PCI Card
- 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link)
- 8027 PCI4451 IEEE-1394 Controller
- 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
- 8029 PCI4510 IEEE-1394 Controller
- 1028 0163 Latitude D505
- 1071 8160 MIM2900
- 802b PCI7410,7510,7610 OHCI-Lynx Controller
- 1028 014e PCI7410,7510,7610 OHCI-Lynx Controller (Dell Latitude D800)
- 802e PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
- 8031 Texas Instruments PCIxx21/x515 Cardbus Controller
- 8032 Texas Instruments OHCI Compliant IEEE 1394 Host Controller
- 8033 Texas Instruments PCIxx21 Integrated FlashMedia Controller
- 8034 Texas Instruments PCI6411, PCI6421, PCI6611, PCI6621, PCI7411, PCI7421, PCI7611, PCI7621 Secure Digital (SD) Controller
- 8035 Texas Instruments PCI6411, PCI6421, PCI6611, PCI6621, PCI7411, PCI7421, PCI7611, PCI7621 Smart Card Controller (SMC)
- 8201 PCI1620 Firmware Loading Function
- 8204 PCI7410,7510,7610 PCI Firmware Loading Function
- 1028 014e Latitude D800
- 8400 ACX 100 22Mbps Wireless Interface
- 00fc 16ec U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
- 00fd 16ec U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
- 1186 3b00 DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]
- 1186 3b01 DWL-520+ 22Mbps PCI Wireless Adapter
- 8401 ACX 100 22Mbps Wireless Interface
-# OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi
- 9000 Wireless Interface (of unknown type)
- 9066 ACX 111 54Mbps Wireless Interface
- a001 TDC1570
- a100 TDC1561
- a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f
- a106 TMS320C6205 Fixed Point DSP
- 175c 5000 ASI50xx Audio Adapter
- 175c 8700 ASI87xx Radio Tuner card
- ac10 PCI1050
- ac11 PCI1053
- ac12 PCI1130
- ac13 PCI1031
- ac15 PCI1131
- ac16 PCI1250
- 1014 0092 ThinkPad 600
- ac17 PCI1220
- ac18 PCI1260
- ac19 PCI1221
- ac1a PCI1210
- ac1b PCI1450
- 0e11 b113 Armada M700
- ac1c PCI1225
- 0e11 b121 Armada E500
- 1028 0088 Dell Computer Corporation Latitude CPi A400XT
- ac1d PCI1251A
- ac1e PCI1211
- ac1f PCI1251B
- ac20 TI 2030
- ac21 PCI2031
- ac22 PCI2032 PCI Docking Bridge
- ac23 PCI2250 PCI-to-PCI Bridge
- ac28 PCI2050 PCI-to-PCI Bridge
- ac30 PCI1260 PC card Cardbus Controller
- ac40 PCI4450 PC card Cardbus Controller
- ac41 PCI4410 PC card Cardbus Controller
- ac42 PCI4451 PC card Cardbus Controller
- 1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100)
- ac44 PCI4510 PC card Cardbus Controller
- 1028 0163 Latitude D505
- 1071 8160 MIM2000
- ac46 PCI4520 PC card Cardbus Controller
- ac47 PCI7510 PC card Cardbus Controller
- 1028 014e Latitude D800
- ac4a PCI7510,7610 PC card Cardbus Controller
- 1028 014e Latitude D800
- ac50 PCI1410 PC card Cardbus Controller
- ac51 PCI1420
- 1014 023b ThinkPad T23 (2647-4MG)
- 1028 00b1 Latitude C600
- 1028 012a Latitude C640
- 1033 80cd Versa Note VXi
- 10cf 1095 Lifebook C6155
- e4bf 1000 CP2-2-HIPHOP
- ac52 PCI1451 PC card Cardbus Controller
- ac53 PCI1421 PC card Cardbus Controller
- ac54 PCI1620 PC Card Controller
- ac55 PCI1520 PC card Cardbus Controller
- 1014 0512 ThinkPad T30/T40
- ac56 PCI1510 PC card Cardbus Controller
- 1014 0528 ThinkPad R40e (2684-HVG) Cardbus Controller
- ac60 PCI2040 PCI to DSP Bridge Controller
- 175c 5100 ASI51xx Audio Adapter
- 175c 6100 ASI61xx Audio Adapter
- 175c 6200 ASI62xx Audio Adapter
- ac8d PCI 7620
- ac8e PCI7420 CardBus Controller
- ac8f PCI7420/PCI7620 Dual Socket CardBus and Smart Card Cont. w/ 1394a-2000 OHCI Two-Port PHY/Link-Layer Cont. and SD/MS-Pro Sockets
- fe00 FireWire Host Controller
- fe03 12C01A FireWire Host Controller
-104d Sony Corporation
- 8004 DTL-H2500 [Playstation development board]
- 8009 CXD1947Q i.LINK Controller
- 8039 CXD3222 i.LINK Controller
- 8056 Rockwell HCF 56K modem
- 808a Memory Stick Controller
-104e Oak Technology, Inc
- 0017 OTI-64017
- 0107 OTI-107 [Spitfire]
- 0109 Video Adapter
- 0111 OTI-64111 [Spitfire]
- 0217 OTI-64217
- 0317 OTI-64317
-104f Co-time Computer Ltd
-1050 Winbond Electronics Corp
- 0000 NE2000
- 0001 W83769F
- 0105 W82C105
- 0840 W89C840
- 1050 0001 W89C840 Ethernet Adapter
- 1050 0840 W89C840 Ethernet Adapter
- 0940 W89C940
- 5a5a W89C940F
- 6692 W6692
- 9921 W99200F MPEG-1 Video Encoder
- 9922 W99200F/W9922PF MPEG-1/2 Video Encoder
- 9970 W9970CF
-1051 Anigma, Inc.
-1052 ?Young Micro Systems
-1053 Young Micro Systems
-1054 Hitachi, Ltd
-1055 Efar Microsystems
- 9130 SLC90E66 [Victory66] IDE
- 9460 SLC90E66 [Victory66] ISA
- 9462 SLC90E66 [Victory66] USB
- 9463 SLC90E66 [Victory66] ACPI
-1056 ICL
-# Motorola made a mistake and used 1507 instead of 1057 in some chips. Please look at the 1507 entry as well when updating this.
-1057 Motorola
- 0001 MPC105 [Eagle]
- 0002 MPC106 [Grackle]
- 0003 MPC8240 [Kahlua]
- 0004 MPC107
- 0006 MPC8245 [Unity]
- 0008 MPC8540
- 0009 MPC8560
- 0100 MC145575 [HFC-PCI]
- 0431 KTI829c 100VG
- 1801 DSP56301 Digital Signal Processor
- 14fb 0101 Transas Radar Imitator Board [RIM]
- 14fb 0102 Transas Radar Imitator Board [RIM-2]
- 14fb 0202 Transas Radar Integrator Board [RIB-2]
- 14fb 0611 1 channel CAN bus Controller [CanPci-1]
- 14fb 0612 2 channels CAN bus Controller [CanPci-2]
- 14fb 0613 3 channels CAN bus Controller [CanPci-3]
- 14fb 0614 4 channels CAN bus Controller [CanPci-4]
- 14fb 0621 1 channel CAN bus Controller [CanPci2-1]
- 14fb 0622 2 channels CAN bus Controller [CanPci2-2]
- 14fb 0810 Transas VTS Radar Integrator Board [RIB-4]
- 175c 4200 ASI4215 Audio Adapter
- 175c 4300 ASI43xx Audio Adapter
- 175c 4400 ASI4401 Audio Adapter
- ecc0 0010 Darla
- ecc0 0020 Gina
- ecc0 0030 Layla rev.0
- ecc0 0031 Layla rev.1
- ecc0 0040 Darla24 rev.0
- ecc0 0041 Darla24 rev.1
- ecc0 0050 Gina24 rev.0
- ecc0 0051 Gina24 rev.1
- ecc0 0070 Mona rev.0
- ecc0 0071 Mona rev.1
- ecc0 0072 Mona rev.2
- 18c0 MPC8265A/MPC8266
- 18c1 MPC8271/MPC8272
- 3410 DSP56361 Digital Signal Processor
- ecc0 0050 Gina24 rev.0
- ecc0 0051 Gina24 rev.1
- ecc0 0060 Layla24
- ecc0 0070 Mona rev.0
- ecc0 0071 Mona rev.1
- ecc0 0072 Mona rev.2
- ecc0 0080 Mia rev.0
- ecc0 0081 Mia rev.1
- ecc0 0090 Indigo
- ecc0 00a0 Indigo IO
- ecc0 00b0 Indigo DJ
- ecc0 0100 3G
- 4801 Raven
- 4802 Falcon
- 4803 Hawk
- 4806 CPX8216
- 4d68 20268
- 5600 SM56 PCI Modem
- 1057 0300 SM56 PCI Speakerphone Modem
- 1057 0301 SM56 PCI Voice Modem
- 1057 0302 SM56 PCI Fax Modem
- 1057 5600 SM56 PCI Voice modem
- 13d2 0300 SM56 PCI Speakerphone Modem
- 13d2 0301 SM56 PCI Voice modem
- 13d2 0302 SM56 PCI Fax Modem
- 1436 0300 SM56 PCI Speakerphone Modem
- 1436 0301 SM56 PCI Voice modem
- 1436 0302 SM56 PCI Fax Modem
- 144f 100c SM56 PCI Fax Modem
- 1494 0300 SM56 PCI Speakerphone Modem
- 1494 0301 SM56 PCI Voice modem
- 14c8 0300 SM56 PCI Speakerphone Modem
- 14c8 0302 SM56 PCI Fax Modem
- 1668 0300 SM56 PCI Speakerphone Modem
- 1668 0302 SM56 PCI Fax Modem
- 5803 MPC5200
- 6400 MPC190 Security Processor (S1 family, encryption)
- 6405 MPC184 Security Processor (S1 family)
-1058 Electronics & Telecommunications RSH
-1059 Teknor Industrial Computers Inc
-105a Promise Technology, Inc.
-# more correct description from promise linux sources
- 0d30 PDC20265 (FastTrak100 Lite/Ultra100)
- 105a 4d33 Ultra100
- 0d38 20263
- 105a 4d39 Fasttrak66
- 1275 20275
- 3318 PDC20318 (SATA150 TX4)
- 3319 PDC20319 (FastTrak S150 TX4)
- 8086 3427 S875WP1-E mainboard
- 3371 PDC20371 (FastTrak S150 TX2plus)
- 3373 PDC20378 (FastTrak 378/SATA 378)
- 1043 80f5 K8V Deluxe/PC-DL Deluxe motherboard
- 1462 702e K8T NEO FIS2R motherboard
- 3375 PDC20375 (SATA150 TX2plus)
- 3376 PDC20376 (FastTrak 376)
- 1043 809e A7V8X motherboard
- 3574 PDC20579 SATAII 150 IDE Controller
- 3d18 PDC20518/PDC40518 (SATAII 150 TX4)
- 3d75 PDC20575 (SATAII150 TX2plus)
- 4d30 PDC20267 (FastTrak100/Ultra100)
- 105a 4d33 Ultra100
- 105a 4d39 FastTrak100
- 4d33 20246
- 105a 4d33 20246 IDE Controller
- 4d38 PDC20262 (FastTrak66/Ultra66)
- 105a 4d30 Ultra Device on SuperTrak
- 105a 4d33 Ultra66
- 105a 4d39 FastTrak66
- 4d68 PDC20268 (Ultra100 TX2)
- 105a 4d68 Ultra100TX2
- 4d69 20269
- 105a 4d68 Ultra133TX2
- 5275 PDC20276 (MBFastTrak133 Lite)
- 105a 0275 SuperTrak SX6000 IDE
- 105a 1275 MBFastTrak133 Lite (tm) Controller (RAID mode)
- 1458 b001 MBUltra 133
- 5300 DC5300
- 6268 PDC20270 (FastTrak100 LP/TX2/TX4)
- 105a 4d68 FastTrak100 TX2
- 6269 PDC20271 (FastTrak TX2000)
- 105a 6269 FastTrak TX2/TX2000
- 6621 PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite)
- 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller
- 6626 PDC20618 (Ultra 618)
- 6629 PDC20619 (FastTrak TX4000)
- 7275 PDC20277 (SBFastTrak133 Lite)
-105b Foxconn International, Inc.
-105c Wipro Infotech Limited
-105d Number 9 Computer Company
- 2309 Imagine 128
- 2339 Imagine 128-II
- 105d 0000 Imagine 128 series 2 4Mb VRAM
- 105d 0001 Imagine 128 series 2 4Mb VRAM
- 105d 0002 Imagine 128 series 2 4Mb VRAM
- 105d 0003 Imagine 128 series 2 4Mb VRAM
- 105d 0004 Imagine 128 series 2 4Mb VRAM
- 105d 0005 Imagine 128 series 2 4Mb VRAM
- 105d 0006 Imagine 128 series 2 4Mb VRAM
- 105d 0007 Imagine 128 series 2 4Mb VRAM
- 105d 0008 Imagine 128 series 2e 4Mb DRAM
- 105d 0009 Imagine 128 series 2e 4Mb DRAM
- 105d 000a Imagine 128 series 2 8Mb VRAM
- 105d 000b Imagine 128 series 2 8Mb H-VRAM
- 11a4 000a Barco Metheus 5 Megapixel
- 13cc 0000 Barco Metheus 5 Megapixel
- 13cc 0004 Barco Metheus 5 Megapixel
- 13cc 0005 Barco Metheus 5 Megapixel
- 13cc 0006 Barco Metheus 5 Megapixel
- 13cc 0008 Barco Metheus 5 Megapixel
- 13cc 0009 Barco Metheus 5 Megapixel
- 13cc 000a Barco Metheus 5 Megapixel
- 13cc 000c Barco Metheus 5 Megapixel
- 493d Imagine 128 T2R [Ticket to Ride]
- 11a4 000a Barco Metheus 5 Megapixel, Dual Head
- 11a4 000b Barco Metheus 5 Megapixel, Dual Head
- 13cc 0002 Barco Metheus 4 Megapixel, Dual Head
- 13cc 0003 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0007 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0008 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0009 Barco Metheus 5 Megapixel, Dual Head
- 13cc 000a Barco Metheus 5 Megapixel, Dual Head
- 5348 Revolution 4
- 105d 0037 Revolution IV-FP AGP (For SGI 1600SW)
-105e Vtech Computers Ltd
-105f Infotronic America Inc
-1060 United Microelectronics [UMC]
- 0001 UM82C881
- 0002 UM82C886
- 0101 UM8673F
- 0881 UM8881
- 0886 UM8886F
- 0891 UM8891A
- 1001 UM886A
- 673a UM8886BF
- 673b EIDE Master/DMA
- 8710 UM8710
- 886a UM8886A
- 8881 UM8881F
- 8886 UM8886F
- 888a UM8886A
- 8891 UM8891A
- 9017 UM9017F
- 9018 UM9018
- 9026 UM9026
- e881 UM8881N
- e886 UM8886N
- e88a UM8886N
- e891 UM8891N
-1061 I.I.T.
- 0001 AGX016
- 0002 IIT3204/3501
-1062 Maspar Computer Corp
-1063 Ocean Office Automation
-1064 Alcatel
-1065 Texas Microsystems
-1066 PicoPower Technology
- 0000 PT80C826
- 0001 PT86C521 [Vesuvius v1] Host Bridge
- 0002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Master
- 0003 PT86C524 [Nile] PCI-to-PCI Bridge
- 0004 PT86C525 [Nile-II] PCI-to-PCI Bridge
- 0005 National PC87550 System Controller
- 8002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave
-1067 Mitsubishi Electric
- 0301 AccelGraphics AccelECLIPSE
- 0304 AccelGALAXY A2100 [OEM Evans & Sutherland]
- 0308 Tornado 3000 [OEM Evans & Sutherland]
- 1002 VG500 [VolumePro Volume Rendering Accelerator]
-1068 Diversified Technology
-1069 Mylex Corporation
- 0001 DAC960P
- 0002 DAC960PD
- 0010 DAC960PG
- 0020 DAC960LA
- 0050 AcceleRAID 352/170/160 support Device
- b166 Gemstone chipset SCSI controller
- 1014 0242 iSeries 2872 DASD IOA
- 1014 0266 Dual Channel PCI-X U320 SCSI Adapter
- 1014 0278 Dual Channel PCI-X U320 SCSI RAID Adapter
- 1014 02d3 Dual Channel PCI-X U320 SCSI Adapter
- 1014 02d4 Dual Channel PCI-X U320 SCSI RAID Adapter
- ba55 eXtremeRAID 1100 support Device
- ba56 eXtremeRAID 2000/3000 support Device
-106a Aten Research Inc
-106b Apple Computer Inc.
- 0001 Bandit PowerPC host bridge
- 0002 Grand Central I/O
- 0003 Control Video
- 0004 PlanB Video-In
- 0007 O'Hare I/O
- 000c DOS on Mac
- 000e Hydra Mac I/O
- 0010 Heathrow Mac I/O
- 0017 Paddington Mac I/O
- 0018 UniNorth FireWire
- 0019 KeyLargo USB
- 001e UniNorth Internal PCI
- 001f UniNorth PCI
- 0020 UniNorth AGP
- 0021 UniNorth GMAC (Sun GEM)
- 0022 KeyLargo Mac I/O
- 0024 UniNorth/Pangea GMAC (Sun GEM)
- 0025 KeyLargo/Pangea Mac I/O
- 0026 KeyLargo/Pangea USB
- 0027 UniNorth/Pangea AGP
- 0028 UniNorth/Pangea PCI
- 0029 UniNorth/Pangea Internal PCI
- 002d UniNorth 1.5 AGP
- 002e UniNorth 1.5 PCI
- 002f UniNorth 1.5 Internal PCI
- 0030 UniNorth/Pangea FireWire
- 0031 UniNorth 2 FireWire
- 0032 UniNorth 2 GMAC (Sun GEM)
- 0033 UniNorth 2 ATA/100
- 0034 UniNorth 2 AGP
- 0035 UniNorth 2 PCI
- 0036 UniNorth 2 Internal PCI
- 003b UniNorth/Intrepid ATA/100
- 003e KeyLargo/Intrepid Mac I/O
- 003f KeyLargo/Intrepid USB
- 0040 K2 KeyLargo USB
- 0041 K2 KeyLargo Mac/IO
- 0042 K2 FireWire
- 0043 K2 ATA/100
- 0045 K2 HT-PCI Bridge
- 0046 K2 HT-PCI Bridge
- 0047 K2 HT-PCI Bridge
- 0048 K2 HT-PCI Bridge
- 0049 K2 HT-PCI Bridge
- 004b U3 AGP
- 004c K2 GMAC (Sun GEM)
- 004f Shasta Mac I/O
- 0050 Shasta IDE
- 0051 Shasta (Sun GEM)
- 0052 Shasta Firewire
- 0053 Shasta PCI Bridge
- 0054 Shasta PCI Bridge
- 0055 Shasta PCI Bridge
- 0058 U3L AGP Bridge
- 1645 Tigon3 Gigabit Ethernet NIC (BCM5701)
-106c Hynix Semiconductor
- 8801 Dual Pentium ISA/PCI Motherboard
- 8802 PowerPC ISA/PCI Motherboard
- 8803 Dual Window Graphics Accelerator
- 8804 LAN Controller
- 8805 100-BaseT LAN
-106d Sequent Computer Systems
-106e DFI, Inc
-106f City Gate Development Ltd
-1070 Daewoo Telecom Ltd
-1071 Mitac
- 8160 Mitac 8060B Mobile Platform
-1072 GIT Co Ltd
-1073 Yamaha Corporation
- 0001 3D GUI Accelerator
- 0002 YGV615 [RPA3 3D-Graphics Controller]
- 0003 YMF-740
- 0004 YMF-724
- 1073 0004 YMF724-Based PCI Audio Adapter
- 0005 DS1 Audio
- 1073 0005 DS-XG PCI Audio CODEC
- 0006 DS1 Audio
- 0008 DS1 Audio
- 1073 0008 DS-XG PCI Audio CODEC
- 000a DS1L Audio
- 1073 0004 DS-XG PCI Audio CODEC
- 1073 000a DS-XG PCI Audio CODEC
- 000c YMF-740C [DS-1L Audio Controller]
- 107a 000c DS-XG PCI Audio CODEC
- 000d YMF-724F [DS-1 Audio Controller]
- 1073 000d DS-XG PCI Audio CODEC
- 0010 YMF-744B [DS-1S Audio Controller]
- 1073 0006 DS-XG PCI Audio CODEC
- 1073 0010 DS-XG PCI Audio CODEC
- 0012 YMF-754 [DS-1E Audio Controller]
- 1073 0012 DS-XG PCI Audio Codec
- 0020 DS-1 Audio
- 2000 DS2416 Digital Mixing Card
- 1073 2000 DS2416 Digital Mixing Card
-1074 NexGen Microsystems
- 4e78 82c500/1
-1075 Advanced Integrations Research
-1076 Chaintech Computer Co. Ltd
-1077 QLogic Corp.
- 1016 ISP10160 Single Channel Ultra3 SCSI Processor
- 1020 ISP1020 Fast-wide SCSI
- 1022 ISP1022 Fast-wide SCSI
- 1080 ISP1080 SCSI Host Adapter
- 1216 ISP12160 Dual Channel Ultra3 SCSI Processor
- 101e 8471 QLA12160 on AMI MegaRAID
- 101e 8493 QLA12160 on AMI MegaRAID
- 1240 ISP1240 SCSI Host Adapter
- 1280 ISP1280 SCSI Host Adapter
- 2020 ISP2020A Fast!SCSI Basic Adapter
- 2100 QLA2100 64-bit Fibre Channel Adapter
- 1077 0001 QLA2100 64-bit Fibre Channel Adapter
- 2200 QLA2200 64-bit Fibre Channel Adapter
- 1077 0002 QLA2200
- 2300 QLA2300 64-bit Fibre Channel Adapter
- 2312 QLA2312 Fibre Channel Adapter
-1078 Cyrix Corporation
- 0000 5510 [Grappa]
- 0001 PCI Master
- 0002 5520 [Cognac]
- 0100 5530 Legacy [Kahlua]
- 0101 5530 SMI [Kahlua]
- 0102 5530 IDE [Kahlua]
- 0103 5530 Audio [Kahlua]
- 0104 5530 Video [Kahlua]
- 0400 ZFMicro PCI Bridge
- 0401 ZFMicro Chipset SMI
- 0402 ZFMicro Chipset IDE
- 0403 ZFMicro Expansion Bus
-1079 I-Bus
-107a NetWorth
-107b Gateway 2000
-107c LG Electronics [Lucky Goldstar Co. Ltd]
-107d LeadTek Research Inc.
- 0000 P86C850
- 2134 WinFast 3D S320 II
- 2971 [GeForce FX 5900] WinFast A350 TDH MyViVo
-107e Interphase Corporation
- 0001 5515 ATM Adapter [Flipper]
- 0002 100 VG AnyLan Controller
- 0004 5526 Fibre Channel Host Adapter
- 0005 x526 Fibre Channel Host Adapter
- 0008 5525/5575 ATM Adapter (155 Mbit) [Atlantic]
- 9003 5535-4P-BRI-ST
- 9007 5535-4P-BRI-U
- 9008 5535-1P-SR
- 900c 5535-1P-SR-ST
- 900e 5535-1P-SR-U
- 9011 5535-1P-PRI
- 9013 5535-2P-PRI
- 9023 5536-4P-BRI-ST
- 9027 5536-4P-BRI-U
- 9031 5536-1P-PRI
- 9033 5536-2P-PRI
-107f Data Technology Corporation
- 0802 SL82C105
-1080 Contaq Microsystems
- 0600 82C599
- c691 Cypress CY82C691
- c693 82c693
-1081 Supermac Technology
- 0d47 Radius PCI to NuBUS Bridge
-1082 EFA Corporation of America
-1083 Forex Computer Corporation
- 0001 FR710
-1084 Parador
-1085 Tulip Computers Int.B.V.
-1086 J. Bond Computer Systems
-1087 Cache Computer
-1088 Microcomputer Systems (M) Son
-1089 Data General Corporation
-# Formerly Bit3 Computer Corp.
-108a SBS Technologies
- 0001 VME Bridge Model 617
- 0010 VME Bridge Model 618
- 0040 dataBLIZZARD
- 3000 VME Bridge Model 2706
-108c Oakleigh Systems Inc.
-108d Olicom
- 0001 Token-Ring 16/4 PCI Adapter (3136/3137)
- 0002 16/4 Token Ring
- 0004 RapidFire 3139 Token-Ring 16/4 PCI Adapter
- 108d 0004 OC-3139/3140 RapidFire Token-Ring 16/4 Adapter
- 0005 GoCard 3250 Token-Ring 16/4 CardBus PC Card
- 0006 OC-3530 RapidFire Token-Ring 100
- 0007 RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter
- 108d 0007 OC-3141 RapidFire Token-Ring 16/4 Adapter
- 0008 RapidFire 3540 HSTR 100/16/4 PCI Adapter
- 108d 0008 OC-3540 RapidFire HSTR 100/16/4 Adapter
- 0011 OC-2315
- 0012 OC-2325
- 0013 OC-2183/2185
- 0014 OC-2326
- 0019 OC-2327/2250 10/100 Ethernet Adapter
- 108d 0016 OC-2327 Rapidfire 10/100 Ethernet Adapter
- 108d 0017 OC-2250 GoCard 10/100 Ethernet Adapter
- 0021 OC-6151/6152 [RapidFire ATM 155]
- 0022 ATM Adapter
-108e Sun Microsystems Computer Corp.
- 0001 EBUS
- 1000 EBUS
- 1001 Happy Meal
- 1100 RIO EBUS
- 1101 RIO GEM
- 1102 RIO 1394
- 1103 RIO USB
- 1648 [bge] Gigabit Ethernet
- 2bad GEM
- 5000 Simba Advanced PCI Bridge
- 5043 SunPCI Co-processor
- 8000 Psycho PCI Bus Module
- 8001 Schizo PCI Bus Module
- 8002 Schizo+ PCI Bus Module
- a000 Ultra IIi
- a001 Ultra IIe
- a801 Tomatillo PCI Bus Module
- abba Cassini 10/100/1000
-108f Systemsoft
-1090 Encore Computer Corporation
-1091 Intergraph Corporation
- 0020 3D graphics processor
- 0021 3D graphics processor w/Texturing
- 0040 3D graphics frame buffer
- 0041 3D graphics frame buffer
- 0060 Proprietary bus bridge
- 00e4 Powerstorm 4D50T
- 0720 Motion JPEG codec
- 07a0 Sun Expert3D-Lite Graphics Accelerator
- 1091 Sun Expert3D Graphics Accelerator
-1092 Diamond Multimedia Systems
- 00a0 Speedstar Pro SE
- 00a8 Speedstar 64
- 0550 Viper V550
- 08d4 Supra 2260 Modem
- 094c SupraExpress 56i Pro
- 1092 Viper V330
- 6120 Maximum DVD
- 8810 Stealth SE
- 8811 Stealth 64/SE
- 8880 Stealth
- 8881 Stealth
- 88b0 Stealth 64
- 88b1 Stealth 64
- 88c0 Stealth 64
- 88c1 Stealth 64
- 88d0 Stealth 64
- 88d1 Stealth 64
- 88f0 Stealth 64
- 88f1 Stealth 64
- 9999 DMD-I0928-1 "Monster sound" sound chip
-1093 National Instruments
- 0160 PCI-DIO-96
- 0162 PCI-MIO-16XE-50
- 1170 PCI-MIO-16XE-10
- 1180 PCI-MIO-16E-1
- 1190 PCI-MIO-16E-4
- 1310 PCI-6602
- 1330 PCI-6031E
- 1350 PCI-6071E
- 14e0 PCI-6110
- 14f0 PCI-6111
- 17d0 PCI-6503
- 1870 PCI-6713
- 1880 PCI-6711
- 18b0 PCI-6052E
- 2410 PCI-6733
- 2890 PCI-6036E
- 2a60 PCI-6023E
- 2a70 PCI-6024E
- 2a80 PCI-6025E
- 2c80 PCI-6035E
- 2ca0 PCI-6034E
- 70b8 PCI-6251 [M Series - High Speed Multifunction DAQ]
- b001 IMAQ-PCI-1408
- b011 IMAQ-PXI-1408
- b021 IMAQ-PCI-1424
- b031 IMAQ-PCI-1413
- b041 IMAQ-PCI-1407
- b051 IMAQ-PXI-1407
- b061 IMAQ-PCI-1411
- b071 IMAQ-PCI-1422
- b081 IMAQ-PXI-1422
- b091 IMAQ-PXI-1411
- c801 PCI-GPIB
- c831 PCI-GPIB bridge
-1094 First International Computers [FIC]
-1095 Silicon Image, Inc. (formerly CMD Technology Inc)
- 0240 Adaptec AAR-1210SA SATA HostRAID Controller
- 0640 PCI0640
- 0643 PCI0643
- 0646 PCI0646
- 0647 PCI0647
- 0648 PCI0648
- 0649 SiI 0649 Ultra ATA/100 PCI to ATA Host Controller
- 0e11 005d Integrated Ultra ATA-100 Dual Channel Controller
- 0e11 007e Integrated Ultra ATA-100 IDE RAID Controller
- 101e 0649 AMI MegaRAID IDE 100 Controller
- 0650 PBC0650A
- 0670 USB0670
- 1095 0670 USB0670
- 0673 USB0673
- 0680 PCI0680 Ultra ATA-133 Host Controller
- 1095 3680 Winic W-680 (Silicon Image 680 based)
- 3112 SiI 3112 [SATALink/SATARaid] Serial ATA Controller
- 1095 3112 SiI 3112 SATALink Controller
- 1095 6112 SiI 3112 SATARaid Controller
- 3114 SiI 3114 [SATALink/SATARaid] Serial ATA Controller
- 1095 3114 SiI 3114 SATALink Controller
- 1095 6114 SiI 3114 SATARaid Controller
- 3124 SiI 3124 PCI-X Serial ATA Controller
- 1095 3124 SiI 3124 PCI-X Serial ATA Controller
- 3512 SiI 3512 [SATALink/SATARaid] Serial ATA Controller
- 1095 3512 SiI 3512 SATALink Controller
- 1095 6512 SiI 3512 SATARaid Controller
-1096 Alacron
-1097 Appian Technology
-1098 Quantum Designs (H.K.) Ltd
- 0001 QD-8500
- 0002 QD-8580
-1099 Samsung Electronics Co., Ltd
-109a Packard Bell
-109b Gemlight Computer Ltd.
-109c Megachips Corporation
-109d Zida Technologies Ltd.
-109e Brooktree Corporation
- 0350 Bt848 Video Capture
- 0351 Bt849A Video capture
- 0369 Bt878 Video Capture
- 1002 0001 TV-Wonder
- 1002 0003 TV-Wonder/VE
- 036c Bt879(??) Video Capture
- 13e9 0070 Win/TV (Video Section)
- 036e Bt878 Video Capture
- 0070 13eb WinTV Series
- 0070 ff01 Viewcast Osprey 200
- 0071 0101 DigiTV PCI
- 107d 6606 WinFast TV 2000
- 11bd 0012 PCTV pro (TV + FM stereo receiver)
- 11bd 001c PCTV Sat (DBC receiver)
- 127a 0001 Bt878 Mediastream Controller NTSC
- 127a 0002 Bt878 Mediastream Controller PAL BG
- 127a 0003 Bt878a Mediastream Controller PAL BG
- 127a 0048 Bt878/832 Mediastream Controller
- 144f 3000 MagicTView CPH060 - Video
- 1461 0002 TV98 Series (TV/No FM/Remote)
- 1461 0003 AverMedia UltraTV PCI 350
- 1461 0004 AVerTV WDM Video Capture
- 1461 0761 AverTV DVB-T
- 14f1 0001 Bt878 Mediastream Controller NTSC
- 14f1 0002 Bt878 Mediastream Controller PAL BG
- 14f1 0003 Bt878a Mediastream Controller PAL BG
- 14f1 0048 Bt878/832 Mediastream Controller
- 1822 0001 VisionPlus DVB card
- 1851 1850 FlyVideo'98 - Video
- 1851 1851 FlyVideo II
- 1852 1852 FlyVideo'98 - Video (with FM Tuner)
- 270f fc00 Digitop DTT-1000
- bd11 1200 PCTV pro (TV + FM stereo receiver)
- 036f Bt879 Video Capture
- 127a 0044 Bt879 Video Capture NTSC
- 127a 0122 Bt879 Video Capture PAL I
- 127a 0144 Bt879 Video Capture NTSC
- 127a 0222 Bt879 Video Capture PAL BG
- 127a 0244 Bt879a Video Capture NTSC
- 127a 0322 Bt879 Video Capture NTSC
- 127a 0422 Bt879 Video Capture NTSC
- 127a 1122 Bt879 Video Capture PAL I
- 127a 1222 Bt879 Video Capture PAL BG
- 127a 1322 Bt879 Video Capture NTSC
- 127a 1522 Bt879a Video Capture PAL I
- 127a 1622 Bt879a Video Capture PAL BG
- 127a 1722 Bt879a Video Capture NTSC
- 14f1 0044 Bt879 Video Capture NTSC
- 14f1 0122 Bt879 Video Capture PAL I
- 14f1 0144 Bt879 Video Capture NTSC
- 14f1 0222 Bt879 Video Capture PAL BG
- 14f1 0244 Bt879a Video Capture NTSC
- 14f1 0322 Bt879 Video Capture NTSC
- 14f1 0422 Bt879 Video Capture NTSC
- 14f1 1122 Bt879 Video Capture PAL I
- 14f1 1222 Bt879 Video Capture PAL BG
- 14f1 1322 Bt879 Video Capture NTSC
- 14f1 1522 Bt879a Video Capture PAL I
- 14f1 1622 Bt879a Video Capture PAL BG
- 14f1 1722 Bt879a Video Capture NTSC
- 1851 1850 FlyVideo'98 - Video
- 1851 1851 FlyVideo II
- 1852 1852 FlyVideo'98 - Video (with FM Tuner)
- 0370 Bt880 Video Capture
- 1851 1850 FlyVideo'98
- 1851 1851 FlyVideo'98 EZ - video
- 1852 1852 FlyVideo'98 (with FM Tuner)
- 0878 Bt878 Audio Capture
- 0070 13eb WinTV Series
- 0070 ff01 Viewcast Osprey 200
- 0071 0101 DigiTV PCI
- 1002 0001 TV-Wonder
- 1002 0003 TV-Wonder/VE
- 11bd 0012 PCTV pro (TV + FM stereo receiver, audio section)
- 11bd 001c PCTV Sat (DBC receiver)
- 127a 0001 Bt878 Video Capture (Audio Section)
- 127a 0002 Bt878 Video Capture (Audio Section)
- 127a 0003 Bt878 Video Capture (Audio Section)
- 127a 0048 Bt878 Video Capture (Audio Section)
- 13e9 0070 Win/TV (Audio Section)
- 144f 3000 MagicTView CPH060 - Audio
- 1461 0004 AVerTV WDM Audio Capture
- 1461 0761 AVerTV DVB-T
- 14f1 0001 Bt878 Video Capture (Audio Section)
- 14f1 0002 Bt878 Video Capture (Audio Section)
- 14f1 0003 Bt878 Video Capture (Audio Section)
- 14f1 0048 Bt878 Video Capture (Audio Section)
- 1822 0001 VisionPlus DVB Card
- 270f fc00 Digitop DTT-1000
- bd11 1200 PCTV pro (TV + FM stereo receiver, audio section)
- 0879 Bt879 Audio Capture
- 127a 0044 Bt879 Video Capture (Audio Section)
- 127a 0122 Bt879 Video Capture (Audio Section)
- 127a 0144 Bt879 Video Capture (Audio Section)
- 127a 0222 Bt879 Video Capture (Audio Section)
- 127a 0244 Bt879 Video Capture (Audio Section)
- 127a 0322 Bt879 Video Capture (Audio Section)
- 127a 0422 Bt879 Video Capture (Audio Section)
- 127a 1122 Bt879 Video Capture (Audio Section)
- 127a 1222 Bt879 Video Capture (Audio Section)
- 127a 1322 Bt879 Video Capture (Audio Section)
- 127a 1522 Bt879 Video Capture (Audio Section)
- 127a 1622 Bt879 Video Capture (Audio Section)
- 127a 1722 Bt879 Video Capture (Audio Section)
- 14f1 0044 Bt879 Video Capture (Audio Section)
- 14f1 0122 Bt879 Video Capture (Audio Section)
- 14f1 0144 Bt879 Video Capture (Audio Section)
- 14f1 0222 Bt879 Video Capture (Audio Section)
- 14f1 0244 Bt879 Video Capture (Audio Section)
- 14f1 0322 Bt879 Video Capture (Audio Section)
- 14f1 0422 Bt879 Video Capture (Audio Section)
- 14f1 1122 Bt879 Video Capture (Audio Section)
- 14f1 1222 Bt879 Video Capture (Audio Section)
- 14f1 1322 Bt879 Video Capture (Audio Section)
- 14f1 1522 Bt879 Video Capture (Audio Section)
- 14f1 1622 Bt879 Video Capture (Audio Section)
- 14f1 1722 Bt879 Video Capture (Audio Section)
- 0880 Bt880 Audio Capture
- 2115 BtV 2115 Mediastream controller
- 2125 BtV 2125 Mediastream controller
- 2164 BtV 2164
- 2165 BtV 2165
- 8230 Bt8230 ATM Segment/Reassembly Ctrlr (SRC)
- 8472 Bt8472
- 8474 Bt8474
-109f Trigem Computer Inc.
-10a0 Meidensha Corporation
-10a1 Juko Electronics Ind. Co. Ltd
-10a2 Quantum Corporation
-10a3 Everex Systems Inc
-10a4 Globe Manufacturing Sales
-10a5 Smart Link Ltd.
- 3052 SmartPCI562 56K Modem
- 5449 SmartPCI561 modem
-10a6 Informtech Industrial Ltd.
-10a7 Benchmarq Microelectronics
-10a8 Sierra Semiconductor
- 0000 STB Horizon 64
-10a9 Silicon Graphics, Inc.
- 0001 Crosstalk to PCI Bridge
- 0002 Linc I/O controller
- 0003 IOC3 I/O controller
- 0004 O2 MACE
- 0005 RAD Audio
- 0006 HPCEX
- 0007 RPCEX
- 0008 DiVO VIP
- 0009 AceNIC Gigabit Ethernet
- 10a9 8002 AceNIC Gigabit Ethernet
- 0010 AMP Video I/O
- 0011 GRIP
- 0012 SGH PSHAC GSN
- 1001 Magic Carpet
- 1002 Lithium
- 1003 Dual JPEG 1
- 1004 Dual JPEG 2
- 1005 Dual JPEG 3
- 1006 Dual JPEG 4
- 1007 Dual JPEG 5
- 1008 Cesium
- 100a IOC4 I/O controller
- 2001 Fibre Channel
- 2002 ASDE
- 8001 O2 1394
- 8002 G-net NT
-10aa ACC Microelectronics
- 0000 ACCM 2188
-10ab Digicom
-10ac Honeywell IAC
-10ad Symphony Labs
- 0001 W83769F
- 0003 SL82C103
- 0005 SL82C105
- 0103 SL82c103
- 0105 SL82c105
- 0565 W83C553
-10ae Cornerstone Technology
-10af Micro Computer Systems Inc
-10b0 CardExpert Technology
-10b1 Cabletron Systems Inc
-10b2 Raytheon Company
-10b3 Databook Inc
- 3106 DB87144
- b106 DB87144
-10b4 STB Systems Inc
- 1b1d Velocity 128 3D
- 10b4 237e Velocity 4400
-10b5 PLX Technology, Inc.
- 0001 i960 PCI bus interface
- 1076 VScom 800 8 port serial adaptor
- 1077 VScom 400 4 port serial adaptor
- 1078 VScom 210 2 port serial and 1 port parallel adaptor
- 1103 VScom 200 2 port serial adaptor
- 1146 VScom 010 1 port parallel adaptor
- 1147 VScom 020 2 port parallel adaptor
- 2724 Thales PCSM Security Card
- 8516 PEX 8516 Versatile PCI Express Switch
- 8532 PEX 8532 Versatile PCI Express Switch
- 9030 PCI <-> IOBus Bridge Hot Swap
- 10b5 2862 Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board
- 10b5 2906 Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board
- 10b5 2940 Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board
- 10b5 3025 Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board
- 10b5 3068 Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board
- 15ed 1002 MCCS 8-port Serial Hot Swap
- 15ed 1003 MCCS 16-port Serial Hot Swap
- 9036 9036
- 9050 PCI <-> IOBus Bridge
- 10b5 1067 IXXAT CAN i165
- 10b5 1172 IK220 (Heidenhain)
- 10b5 2036 SatPak GPS
- 10b5 2221 Alpermann+Velte PCL PCI LV: Timecode Reader Board
- 10b5 2273 SH-ARC SoHard ARCnet card
- 10b5 2431 Alpermann+Velte PCL PCI D: Timecode Reader Board
- 10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board
- 10b5 9050 MP9050
- 1498 0362 TPMC866 8 Channel Serial Card
- 1522 0001 RockForce 4 Port V.90 Data/Fax/Voice Modem
- 1522 0002 RockForce 2 Port V.90 Data/Fax/Voice Modem
- 1522 0003 RockForce 6 Port V.90 Data/Fax/Voice Modem
- 1522 0004 RockForce 8 Port V.90 Data/Fax/Voice Modem
- 1522 0010 RockForce2000 4 Port V.90 Data/Fax/Voice Modem
- 1522 0020 RockForce2000 2 Port V.90 Data/Fax/Voice Modem
- 15ed 1000 Macrolink MCCS 8-port Serial
- 15ed 1001 Macrolink MCCS 16-port Serial
- 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap
- 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap
-# Sorry, there was a typo
- 5654 2036 OpenSwitch 6 Telephony card
-# Sorry, there was a typo
- 5654 3132 OpenSwitch 12 Telephony card
- 5654 5634 OpenLine4 Telephony Card
- d531 c002 PCIntelliCAN 2xSJA1000 CAN bus
- d84d 4006 EX-4006 1P
- d84d 4008 EX-4008 1P EPP/ECP
- d84d 4014 EX-4014 2P
- d84d 4018 EX-4018 3P EPP/ECP
- d84d 4025 EX-4025 1S(16C550) RS-232
- d84d 4027 EX-4027 1S(16C650) RS-232
- d84d 4028 EX-4028 1S(16C850) RS-232
- d84d 4036 EX-4036 2S(16C650) RS-232
- d84d 4037 EX-4037 2S(16C650) RS-232
- d84d 4038 EX-4038 2S(16C850) RS-232
- d84d 4052 EX-4052 1S(16C550) RS-422/485
- d84d 4053 EX-4053 2S(16C550) RS-422/485
- d84d 4055 EX-4055 4S(16C550) RS-232
- d84d 4058 EX-4055 4S(16C650) RS-232
- d84d 4065 EX-4065 8S(16C550) RS-232
- d84d 4068 EX-4068 8S(16C650) RS-232
- d84d 4078 EX-4078 2S(16C552) RS-232+1P
- 9054 PCI <-> IOBus Bridge
- 10b5 2455 Wessex Techology PHIL-PCI
- 10b5 2696 Innes Corp AM Radcap card
- 10b5 2717 Innes Corp Auricon card
- 10b5 2844 Innes Corp TVS Encoder card
- 12d9 0002 PCI Prosody Card rev 1.5
- 16df 0011 PIKA PrimeNet MM PCI
- 16df 0012 PIKA PrimeNet MM cPCI 8
- 16df 0013 PIKA PrimeNet MM cPCI 8 (without CAS Signaling Option)
- 16df 0014 PIKA PrimeNet MM cPCI 4
- 16df 0015 PIKA Daytona MM
- 16df 0016 PIKA InLine MM
- 9056 Francois
- 10b5 2979 CellinkBlade 11 - CPCI board VoATM AAL1
- 9060 9060
- 906d 9060SD
- 125c 0640 Aries 16000P
- 906e 9060ES
- 9080 9080
- 103c 10eb (Agilent) E2777B 83K Series PCI based Optical Communication Interface
- 103c 10ec (Agilent) E6978-66442 PCI CIC
- 10b5 9080 9080 [real subsystem ID not set]
- 129d 0002 Aculab PCI Prosidy card
- 12d9 0002 PCI Prosody Card
- 12df 4422 4422PCI ["Do-All" Telemetry Data Aquisition System]
- bb04 B&B 3PCIOSD1A Isolated PCI Serial
-10b6 Madge Networks
- 0001 Smart 16/4 PCI Ringnode
- 0002 Smart 16/4 PCI Ringnode Mk2
- 10b6 0002 Smart 16/4 PCI Ringnode Mk2
- 10b6 0006 16/4 CardBus Adapter
- 0003 Smart 16/4 PCI Ringnode Mk3
- 0e11 b0fd Compaq NC4621 PCI, 4/16, WOL
- 10b6 0003 Smart 16/4 PCI Ringnode Mk3
- 10b6 0007 Presto PCI Plus Adapter
- 0004 Smart 16/4 PCI Ringnode Mk1
- 0006 16/4 Cardbus Adapter
- 10b6 0006 16/4 CardBus Adapter
- 0007 Presto PCI Adapter
- 10b6 0007 Presto PCI
- 0009 Smart 100/16/4 PCI-HS Ringnode
- 10b6 0009 Smart 100/16/4 PCI-HS Ringnode
- 000a Smart 100/16/4 PCI Ringnode
- 10b6 000a Smart 100/16/4 PCI Ringnode
- 000b 16/4 CardBus Adapter Mk2
- 10b6 0008 16/4 CardBus Adapter Mk2
- 10b6 000b 16/4 Cardbus Adapter Mk2
- 000c RapidFire 3140V2 16/4 TR Adapter
- 10b6 000c RapidFire 3140V2 16/4 TR Adapter
- 1000 Collage 25/155 ATM Client Adapter
- 1001 Collage 155 ATM Server Adapter
-10b7 3Com Corporation
- 0001 3c985 1000BaseSX (SX/TX)
- 0013 AR5212 802.11abg NIC (3CRDAG675)
- 10b7 2031 3CRDAG675 11a/b/g Wireless PCI Adapter
- 0910 3C910-A01
- 1006 MINI PCI type 3B Data Fax Modem
- 1007 Mini PCI 56k Winmodem
- 10b7 615c Mini PCI 56K Modem
- 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra]
- 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra]
- 1700 3c940 10/100/1000Base-T [Marvell]
- 1043 80eb P4P800/K8V Deluxe motherboard
- 10b7 0010 3C940 Gigabit LOM Ethernet Adapter
- 10b7 0020 3C941 Gigabit LOM Ethernet Adapter
- 147b 1407 KV8-MAX3 motherboard
- 3390 3c339 TokenLink Velocity
- 3590 3c359 TokenLink Velocity XL
- 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B)
- 4500 3c450 HomePNA [Tornado]
- 5055 3c555 Laptop Hurricane
- 5057 3c575 Megahertz 10/100 LAN CardBus [Boomerang]
- 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5157 3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone]
- 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5257 3cCFE575CT CardBus [Cyclone]
- 10b7 5c57 FE575C-3Com 10/100 LAN CardBus-Fast Ethernet
- 5900 3c590 10BaseT [Vortex]
- 5920 3c592 EISA 10mbps Demon/Vortex
- 5950 3c595 100BaseTX [Vortex]
- 5951 3c595 100BaseT4 [Vortex]
- 5952 3c595 100Base-MII [Vortex]
- 5970 3c597 EISA Fast Demon/Vortex
- 5b57 3c595 Megahertz 10/100 LAN CardBus [Boomerang]
- 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 6000 3CRSHPW796 [OfficeConnect Wireless CardBus]
- 6001 3com 3CRWE154G72 [Office Connect Wireless LAN Adapter]
- 6055 3c556 Hurricane CardBus [Cyclone]
- 6056 3c556B CardBus [Tornado]
- 10b7 6556 10/100 Mini PCI Ethernet Adapter
- 6560 3cCFE656 CardBus [Cyclone]
- 10b7 656a 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6561 3cCFEM656 10/100 LAN+56K Modem CardBus
- 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6562 3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone]
- 10b7 656b 3CCFEM656B 10/100 LAN+56K Modem CardBus
- 6563 3cCFEM656B 10/100 LAN+56K Modem CardBus
- 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6564 3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado]
- 7646 3cSOHO100-TX Hurricane
- 7770 3CRWE777 PCI(PLX) Wireless Adaptor [Airconnect]
- 7940 3c803 FDDILink UTP Controller
- 7980 3c804 FDDILink SAS Controller
- 7990 3c805 FDDILink DAS Controller
- 80eb 3c940B 10/100/1000Base-T
- 8811 Token ring
- 9000 3c900 10BaseT [Boomerang]
- 9001 3c900 10Mbps Combo [Boomerang]
- 9004 3c900B-TPO Etherlink XL [Cyclone]
- 10b7 9004 3C900B-TPO Etherlink XL TPO 10Mb
- 9005 3c900B-Combo Etherlink XL [Cyclone]
- 10b7 9005 3C900B-Combo Etherlink XL Combo
- 9006 3c900B-TPC Etherlink XL [Cyclone]
- 900a 3c900B-FL 10base-FL [Cyclone]
- 9050 3c905 100BaseTX [Boomerang]
- 9051 3c905 100BaseT4 [Boomerang]
- 9055 3c905B 100BaseTX [Cyclone]
- 1028 0080 3C905B Fast Etherlink XL 10/100
- 1028 0081 3C905B Fast Etherlink XL 10/100
- 1028 0082 3C905B Fast Etherlink XL 10/100
- 1028 0083 3C905B Fast Etherlink XL 10/100
- 1028 0084 3C905B Fast Etherlink XL 10/100
- 1028 0085 3C905B Fast Etherlink XL 10/100
- 1028 0086 3C905B Fast Etherlink XL 10/100
- 1028 0087 3C905B Fast Etherlink XL 10/100
- 1028 0088 3C905B Fast Etherlink XL 10/100
- 1028 0089 3C905B Fast Etherlink XL 10/100
- 1028 0090 3C905B Fast Etherlink XL 10/100
- 1028 0091 3C905B Fast Etherlink XL 10/100
- 1028 0092 3C905B Fast Etherlink XL 10/100
- 1028 0093 3C905B Fast Etherlink XL 10/100
- 1028 0094 3C905B Fast Etherlink XL 10/100
- 1028 0095 3C905B Fast Etherlink XL 10/100
- 1028 0096 3C905B Fast Etherlink XL 10/100
- 1028 0097 3C905B Fast Etherlink XL 10/100
- 1028 0098 3C905B Fast Etherlink XL 10/100
- 1028 0099 3C905B Fast Etherlink XL 10/100
- 10b7 9055 3C905B Fast Etherlink XL 10/100
- 9056 3c905B-T4 Fast EtherLink XL [Cyclone]
- 9058 3c905B Deluxe Etherlink 10/100/BNC [Cyclone]
- 905a 3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone]
- 9200 3c905C-TX/TX-M [Tornado]
- 1028 0095 3C920 Integrated Fast Ethernet Controller
- 1028 0097 3C920 Integrated Fast Ethernet Controller
- 1028 00fe Optiplex GX240
- 1028 012a 3C920 Integrated Fast Ethernet Controller [Latitude C640]
- 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC
- 10b7 7000 10/100 Mini PCI Ethernet Adapter
- 10f1 2466 Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)
- 9201 3C920B-EMB Integrated Fast Ethernet Controller [Tornado]
- 1043 80ab A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller
- 9202 3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller
- 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller
- 9300 3CSOHO100B-TX 910-A01 [tulip]
- 9800 3c980-TX Fast Etherlink XL Server Adapter [Cyclone]
- 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter
- 9805 3c980-C 10/100baseTX NIC [Python-T]
- 10b7 1201 EtherLink Server 10/100 Dual Port A
- 10b7 1202 EtherLink Server 10/100 Dual Port B
- 10b7 9805 3c980 10/100baseTX NIC [Python-T]
- 10f1 2462 Thunder K7 S2462
- 9900 3C990-TX [Typhoon]
- 9902 3CR990-TX-95 [Typhoon 56-bit]
- 9903 3CR990-TX-97 [Typhoon 168-bit]
- 9904 3C990B-TX-M/3C990BSVR [Typhoon2]
- 10b7 1000 3CR990B-TX-M [Typhoon2]
- 10b7 2000 3CR990BSVR [Typhoon2 Server]
- 9905 3CR990-FX-95/97/95 [Typhon Fiber]
- 10b7 1101 3CR990-FX-95 [Typhoon Fiber 56-bit]
- 10b7 1102 3CR990-FX-97 [Typhoon Fiber 168-bit]
- 10b7 2101 3CR990-FX-95 Server [Typhoon Fiber 56-bit]
- 10b7 2102 3CR990-FX-97 Server [Typhoon Fiber 168-bit]
- 9908 3CR990SVR95 [Typhoon Server 56-bit]
- 9909 3CR990SVR97 [Typhoon Server 168-bit]
- 990a 3C990SVR [Typhoon Server]
- 990b 3C990SVR [Typhoon Server]
-10b8 Standard Microsystems Corp [SMC]
- 0005 83c170 EPIC/100 Fast Ethernet Adapter
- 1055 e000 LANEPIC 10/100 [EVB171Q-PCI]
- 1055 e002 LANEPIC 10/100 [EVB171G-PCI]
- 10b8 a011 EtherPower II 10/100
- 10b8 a014 EtherPower II 10/100
- 10b8 a015 EtherPower II 10/100
- 10b8 a016 EtherPower II 10/100
- 10b8 a017 EtherPower II 10/100
- 0006 83c175 EPIC/100 Fast Ethernet Adapter
- 1055 e100 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e102 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e300 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e302 LANEPIC Cardbus Fast Ethernet Adapter
- 10b8 a012 LANEPIC Cardbus Fast Ethernet Adapter
- 13a2 8002 LANEPIC Cardbus Fast Ethernet Adapter
- 13a2 8006 LANEPIC Cardbus Fast Ethernet Adapter
- 1000 FDC 37c665
- 1001 FDC 37C922
-# 802.11g card
- 2802 SMC2802W [EZ Connect g]
- a011 83C170QF
- b106 SMC34C90
-10b9 ALi Corporation
- 0101 CMI8338/C3DX PCI Audio Device
- 0111 C-Media CMI8738/C3DX Audio Device (OEM)
- 10b9 0111 C-Media CMI8738/C3DX Audio Device (OEM)
- 0780 Multi-IO Card
- 0782 Multi-IO Card
- 1435 M1435
- 1445 M1445
- 1449 M1449
- 1451 M1451
- 1461 M1461
- 1489 M1489
- 1511 M1511 [Aladdin]
- 1512 M1512 [Aladdin]
- 1513 M1513 [Aladdin]
- 1521 M1521 [Aladdin III]
- 10b9 1521 ALI M1521 Aladdin III CPU Bridge
- 1523 M1523
- 10b9 1523 ALI M1523 ISA Bridge
- 1531 M1531 [Aladdin IV]
- 1533 M1533 PCI to ISA Bridge [Aladdin IV]
- 1014 053b ThinkPad R40e (2684-HVG) PCI to ISA Bridge
- 10b9 1533 ALI M1533 Aladdin IV ISA Bridge
- 1541 M1541
- 10b9 1541 ALI M1541 Aladdin V/V+ AGP System Controller
- 1543 M1543
- 1563 M1563 HyperTransport South Bridge
- 1621 M1621
- 1631 ALI M1631 PCI North Bridge Aladdin Pro III
- 1632 M1632M Northbridge+Trident
- 1641 ALI M1641 PCI North Bridge Aladdin Pro IV
- 1644 M1644/M1644T Northbridge+Trident
- 1646 M1646 Northbridge+Trident
- 1647 M1647 Northbridge [MAGiK 1 / MobileMAGiK 1]
- 1651 M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM]
- 1671 M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR]
- 1672 M1672 Northbridge [CyberALADDiN-P4]
- 1681 M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR]
- 1687 M1687 K8 Northbridge [AGP8X and HyperTransport]
- 1689 M1689 K8 Northbridge [Super K8 Single Chip]
- 3141 M3141
- 3143 M3143
- 3145 M3145
- 3147 M3147
- 3149 M3149
- 3151 M3151
- 3307 M3307
- 3309 M3309
- 3323 M3325 Video/Audio Decoder
- 5212 M4803
- 5215 MS4803
- 5217 M5217H
- 5219 M5219
- 5225 M5225
- 5228 M5228 ALi ATA/RAID Controller
- 5229 M5229 IDE
- 1014 050f ThinkPad R30
- 1014 053d ThinkPad R40e (2684-HVG) builtin IDE
- 103c 0024 Pavilion ze4400 builtin IDE
- 1043 8053 A7A266 Motherboard IDE
- 5235 M5225
- 5237 USB 1.1 Controller
- 1014 0540 ThinkPad R40e (2684-HVG) builtin USB
- 103c 0024 Pavilion ze4400 builtin USB
- 5239 USB 2.0 Controller
- 5243 M1541 PCI to AGP Controller
- 5246 AGP8X Controller
- 5247 PCI to AGP Controller
- 5249 M5249 HTT to PCI Bridge
- 5251 M5251 P1394 OHCI 1.0 Controller
- 5253 M5253 P1394 OHCI 1.1 Controller
- 5261 M5261 Ethernet Controller
- 5263 M5263 Ethernet Controller
- 5281 ALi M5281 Serial ATA / RAID Host Controller
- 5287 ULi 5287 SATA
- 5289 ULi 5289 SATA
- 5450 Lucent Technologies Soft Modem AMR
- 5451 M5451 PCI AC-Link Controller Audio Device
- 1014 0506 ThinkPad R30
- 1014 053e ThinkPad R40e (2684-HVG) builtin Audio
- 103c 0024 Pavilion ze4400 builtin Audio
- 10b9 5451 HP Compaq nc4010 (DY885AA#ABN)
- 5453 M5453 PCI AC-Link Controller Modem Device
- 5455 M5455 PCI AC-Link Controller Audio Device
- 5457 M5457 AC'97 Modem Controller
- 1014 0535 ThinkPad R40e (2684-HVG) builtin modem
- 103c 0024 Pavilion ze4400 builtin Modem Device
-# Same but more usefull for driver's lookup
- 5459 SmartLink SmartPCI561 56K Modem
-# SmartLink PCI SoftModem
- 545a SmartLink SmartPCI563 56K Modem
- 5471 M5471 Memory Stick Controller
- 5473 M5473 SD-MMC Controller
- 7101 M7101 Power Management Controller [PMU]
- 1014 0510 ThinkPad R30
- 1014 053c ThinkPad R40e (2684-HVG) Power Management Controller
- 103c 0024 Pavilion ze4400
-10ba Mitsubishi Electric Corp.
- 0301 AccelGraphics AccelECLIPSE
- 0304 AccelGALAXY A2100 [OEM Evans & Sutherland]
- 0308 Tornado 3000 [OEM Evans & Sutherland]
- 1002 VG500 [VolumePro Volume Rendering Accelerator]
-10bb Dapha Electronics Corporation
-10bc Advanced Logic Research
-10bd Surecom Technology
- 0e34 NE-34
-10be Tseng Labs International Co.
-10bf Most Inc
-10c0 Boca Research Inc.
-10c1 ICM Co., Ltd.
-10c2 Auspex Systems Inc.
-10c3 Samsung Semiconductors, Inc.
- 1100 Smartether100 SC1100 LAN Adapter (i82557B)
-10c4 Award Software International Inc.
-10c5 Xerox Corporation
-10c6 Rambus Inc.
-10c7 Media Vision
-10c8 Neomagic Corporation
- 0001 NM2070 [MagicGraph 128]
- 0002 NM2090 [MagicGraph 128V]
- 0003 NM2093 [MagicGraph 128ZV]
- 0004 NM2160 [MagicGraph 128XD]
- 1014 00ba MagicGraph 128XD
- 1025 1007 MagicGraph 128XD
- 1028 0074 MagicGraph 128XD
- 1028 0075 MagicGraph 128XD
- 1028 007d MagicGraph 128XD
- 1028 007e MagicGraph 128XD
- 1033 802f MagicGraph 128XD
- 104d 801b MagicGraph 128XD
- 104d 802f MagicGraph 128XD
- 104d 830b MagicGraph 128XD
- 10ba 0e00 MagicGraph 128XD
- 10c8 0004 MagicGraph 128XD
- 10cf 1029 MagicGraph 128XD
- 10f7 8308 MagicGraph 128XD
- 10f7 8309 MagicGraph 128XD
- 10f7 830b MagicGraph 128XD
- 10f7 830d MagicGraph 128XD
- 10f7 8312 MagicGraph 128XD
- 0005 NM2200 [MagicGraph 256AV]
- 1014 00dd ThinkPad 570
- 1028 0088 Latitude CPi A
- 0006 NM2360 [MagicMedia 256ZX]
- 0016 NM2380 [MagicMedia 256XL+]
- 10c8 0016 MagicMedia 256XL+
- 0025 NM2230 [MagicGraph 256AV+]
- 0083 NM2093 [MagicGraph 128ZV+]
- 8005 NM2200 [MagicMedia 256AV Audio]
- 0e11 b0d1 MagicMedia 256AV Audio Device on Discovery
- 0e11 b126 MagicMedia 256AV Audio Device on Durango
- 1014 00dd MagicMedia 256AV Audio Device on BlackTip Thinkpad
- 1025 1003 MagicMedia 256AV Audio Device on TravelMate 720
- 1028 0088 Latitude CPi A
- 1028 008f MagicMedia 256AV Audio Device on Colorado Inspiron
- 103c 0007 MagicMedia 256AV Audio Device on Voyager II
- 103c 0008 MagicMedia 256AV Audio Device on Voyager III
- 103c 000d MagicMedia 256AV Audio Device on Omnibook 900
- 10c8 8005 MagicMedia 256AV Audio Device on FireAnt
- 110a 8005 MagicMedia 256AV Audio Device
- 14c0 0004 MagicMedia 256AV Audio Device
- 8006 NM2360 [MagicMedia 256ZX Audio]
- 8016 NM2380 [MagicMedia 256XL+ Audio]
-10c9 Dataexpert Corporation
-10ca Fujitsu Microelectr., Inc.
-10cb Omron Corporation
-# nee Mentor ARC Inc
-10cc Mai Logic Incorporated
- 0660 Articia S Host Bridge
- 0661 Articia S PCI Bridge
-10cd Advanced System Products, Inc
- 1100 ASC1100
- 1200 ASC1200 [(abp940) Fast SCSI-II]
- 1300 ABP940-U / ABP960-U
- 10cd 1310 ASC1300 SCSI Adapter
- 2300 ABP940-UW
- 2500 ABP940-U2W
-10ce Radius
-# nee Citicorp TTI
-10cf Fujitsu Limited.
- 2001 mb86605
-10d1 FuturePlus Systems Corp.
-10d2 Molex Incorporated
-10d3 Jabil Circuit Inc
-10d4 Hualon Microelectronics
-10d5 Autologic Inc.
-10d6 Cetia
-10d7 BCM Advanced Research
-10d8 Advanced Peripherals Labs
-10d9 Macronix, Inc. [MXIC]
- 0431 MX98715
- 0512 MX98713
- 0531 MX987x5
- 1186 1200 DFE-540TX ProFAST 10/100 Adapter
- 8625 MX86250
- 8888 MX86200
-10da Compaq IPG-Austin
- 0508 TC4048 Token Ring 4/16
- 3390 Tl3c3x9
-10db Rohm LSI Systems, Inc.
-10dc CERN/ECP/EDU
- 0001 STAR/RD24 SCI-PCI (PMC)
- 0002 TAR/RD24 SCI-PCI (PMC)
- 0021 HIPPI destination
- 0022 HIPPI source
- 10dc ATT2C15-3 FPGA
-10dd Evans & Sutherland
-10de nVidia Corporation
- 0008 NV1 [EDGE 3D]
- 0009 NV1 [EDGE 3D]
- 0010 NV2 [Mutara V08]
- 0020 NV4 [RIVA TNT]
- 1043 0200 V3400 TNT
- 1048 0c18 Erazor II SGRAM
- 1048 0c1b Erazor II
- 1092 0550 Viper V550
- 1092 0552 Viper V550
- 1092 4804 Viper V550
- 1092 4808 Viper V550
- 1092 4810 Viper V550
- 1092 4812 Viper V550
- 1092 4815 Viper V550
- 1092 4820 Viper V550 with TV out
- 1092 4822 Viper V550
- 1092 4904 Viper V550
- 1092 4914 Viper V550
- 1092 8225 Viper V550
- 10b4 273d Velocity 4400
- 10b4 273e Velocity 4400
- 10b4 2740 Velocity 4400
- 10de 0020 Riva TNT
- 1102 1015 Graphics Blaster CT6710
- 1102 1016 Graphics Blaster RIVA TNT
- 0028 NV5 [RIVA TNT2/TNT2 Pro]
- 1043 0200 AGP-V3800 SGRAM
- 1043 0201 AGP-V3800 SDRAM
- 1043 0205 PCI-V3800
- 1043 4000 AGP-V3800PRO
- 1048 0c21 Synergy II
- 1048 0c31 Erazor III
- 107d 2134 WinFast 3D S320 II + TV-Out
- 1092 4804 Viper V770
- 1092 4a00 Viper V770
- 1092 4a02 Viper V770 Ultra
- 1092 5a00 RIVA TNT2/TNT2 Pro
- 1092 6a02 Viper V770 Ultra
- 1092 7a02 Viper V770 Ultra
- 10de 0005 RIVA TNT2 Pro
- 10de 000f Compaq NVIDIA TNT2 Pro
- 1102 1020 3D Blaster RIVA TNT2
- 1102 1026 3D Blaster RIVA TNT2 Digital
- 14af 5810 Maxi Gamer Xentor
- 0029 NV5 [RIVA TNT2 Ultra]
- 1043 0200 AGP-V3800 Deluxe
- 1043 0201 AGP-V3800 Ultra SDRAM
- 1043 0205 PCI-V3800 Ultra
- 1102 1021 3D Blaster RIVA TNT2 Ultra
- 1102 1029 3D Blaster RIVA TNT2 Ultra
- 1102 102f 3D Blaster RIVA TNT2 Ultra
- 14af 5820 Maxi Gamer Xentor 32
- 002a NV5 [Riva TnT2]
- 002b NV5 [Riva TnT2]
- 002c NV6 [Vanta/Vanta LT]
- 1043 0200 AGP-V3800 Combat SDRAM
- 1043 0201 AGP-V3800 Combat
- 1092 6820 Viper V730
- 1102 1031 CT6938 VANTA 8MB
- 1102 1034 CT6894 VANTA 16MB
- 14af 5008 Maxi Gamer Phoenix 2
- 002d NV5M64 [RIVA TNT2 Model 64/Model 64 Pro]
- 1043 0200 AGP-V3800M
- 1043 0201 AGP-V3800M
- 1048 0c3a Erazor III LT
- 10de 001e M64 AGP4x
- 1102 1023 CT6892 RIVA TNT2 Value
- 1102 1024 CT6932 RIVA TNT2 Value 32Mb
- 1102 102c CT6931 RIVA TNT2 Value [Jumper]
- 1462 8808 MSI-8808
- 1554 1041 Pixelview RIVA TNT2 M64
- 1569 002d Palit Microsystems Daytona TNT2 M64
- 002e NV6 [Vanta]
- 002f NV6 [Vanta]
- 0034 MCP04 SMBus
- 0035 MCP04 IDE
- 0036 MCP04 Serial ATA Controller
- 0037 MCP04 Ethernet Controller
- 0038 MCP04 Ethernet Controller
- 003a MCP04 AC'97 Audio Controller
- 003b MCP04 USB Controller
- 003c MCP04 USB Controller
- 003d MCP04 PCI Bridge
- 003e MCP04 Serial ATA Controller
- 0040 nv40 [GeForce 6800 Ultra]
- 0041 NV40 [GeForce 6800]
- 0042 NV40.2
- 0043 NV40.3
- 0045 NV40 [GeForce 6800 GT]
- 0049 NV40GL
- 004e NV40GL [Quadro FX 4000]
- 0051 CK804 ISA Bridge
- 0052 CK804 SMBus
- 0053 CK804 IDE
- 0054 CK804 Serial ATA Controller
- 0055 CK804 Serial ATA Controller
- 0056 CK804 Ethernet Controller
- 0057 CK804 Ethernet Controller
- 0059 CK804 AC'97 Audio Controller
- 005a CK804 USB Controller
- 005b CK804 USB Controller
- 005c CK804 PCI Bridge
- 005d CK804 PCIE Bridge
- 005e CK804 Memory Controller
- 0060 nForce2 ISA Bridge
- 1043 80ad A7N8X Mainboard
- 0064 nForce2 SMBus (MCP)
- 0065 nForce2 IDE
- 0066 nForce2 Ethernet Controller
- 1043 80a7 A7N8X Mainboard onboard nForce2 Ethernet
- 0067 nForce2 USB Controller
- 1043 0c11 A7N8X Mainboard
- 0068 nForce2 USB Controller
- 1043 0c11 A7N8X Mainboard
- 006a nForce2 AC97 Audio Controler (MCP)
- 006b nForce Audio Processing Unit
- 10de 006b nForce2 MCP Audio Processing Unit
- 006c nForce2 External PCI Bridge
- 006d nForce2 PCI Bridge
- 006e nForce2 FireWire (IEEE 1394) Controller
- 0084 MCP2A SMBus
- 0085 MCP2A IDE
- 0086 MCP2A Ethernet Controller
- 0087 MCP2A USB Controller
- 0088 MCP2A USB Controller
- 008a MCP2S AC'97 Audio Controller
- 008b MCP2A PCI Bridge
- 008c MCP2A Ethernet Controller
- 008e nForce2 Serial ATA Controller
- 00a0 NV5 [Aladdin TNT2]
- 14af 5810 Maxi Gamer Xentor
- 00c0 NV41.0
- 00c1 NV41.1
- 00c2 NV41.2
- 00c8 NV41.8
- 00ce NV41GL
- 00d0 nForce3 LPC Bridge
- 00d1 nForce3 Host Bridge
- 00d2 nForce3 AGP Bridge
- 00d3 CK804 Memory Controller
- 00d4 nForce3 SMBus
- 00d5 nForce3 IDE
- 00d6 nForce3 Ethernet
- 00d7 nForce3 USB 1.1
- 00d8 nForce3 USB 2.0
- 00da nForce3 Audio
- 00dd nForce3 PCI Bridge
- 00df CK8S Ethernet Controller
- 00e0 nForce3 250Gb LPC Bridge
- 00e1 nForce3 250Gb Host Bridge
- 00e2 nForce3 250Gb AGP Host to PCI Bridge
- 00e3 CK8S Serial ATA Controller (v2.5)
- 00e4 nForce 250Gb PCI System Management
- 00e5 CK8S Parallel ATA Controller (v2.5)
- 00e6 CK8S Ethernet Controller
- 00e7 CK8S USB Controller
- 00e8 nForce3 EHCI USB 2.0 Controller
- 00ea nForce3 250Gb AC'97 Audio Controller
- 00ed nForce3 250Gb PCI-to-PCI Bridge
- 00ee CK8S Serial ATA Controller (v2.5)
- 00f0 NV40 [GeForce 6800/GeForce 6800 Ultra]
- 00f1 NV43 [GeForce 6600/GeForce 6600 GT]
- 00f2 NV43 [GeForce 6600 GT]
- 00f8 NV45GL [Quadro FX 3400]
- 00f9 NV40 [GeForce 6800 Ultra/GeForce 6800 GT]
- 1682 2120 GEFORCE 6800 GT PCI-E
- 00fa NV36 [GeForce PCX 5750]
- 00fb NV35 [GeForce PCX 5900]
- 00fc NV37GL [Quadro FX 330/GeForce PCX 5300]
- 00fd NV37GL [Quadro FX 330]
- 00fe NV38GL [Quadro FX 1300]
- 00ff NV18 [GeForce PCX 4300]
- 0100 NV10 [GeForce 256 SDR]
- 1043 0200 AGP-V6600 SGRAM
- 1043 0201 AGP-V6600 SDRAM
- 1043 4008 AGP-V6600 SGRAM
- 1043 4009 AGP-V6600 SDRAM
- 1102 102d CT6941 GeForce 256
- 14af 5022 3D Prophet SE
- 0101 NV10DDR [GeForce 256 DDR]
- 1043 0202 AGP-V6800 DDR
- 1043 400a AGP-V6800 DDR SGRAM
- 1043 400b AGP-V6800 DDR SDRAM
- 107d 2822 WinFast GeForce 256
- 1102 102e CT6971 GeForce 256 DDR
- 14af 5021 3D Prophet DDR-DVI
- 0103 NV10GL [Quadro]
- 0110 NV11 [GeForce2 MX/MX 400]
- 1043 4015 AGP-V7100 Pro
- 1043 4031 V7100 Pro with TV output
- 10de 0091 Dell OEM GeForce 2 MX 400
- 1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817]
- 14af 7102 3D Prophet II MX
- 14af 7103 3D Prophet II MX Dual-Display
- 0111 NV11DDR [GeForce2 MX 100 DDR/200 DDR]
- 0112 NV11 [GeForce2 Go]
- 0113 NV11GL [Quadro2 MXR/EX]
- 0140 NV43 [MSI NX6600GT-TD128E]
- 014f NV43 [GeForce 6200]
- 0150 NV15 [GeForce2 GTS/Pro]
- 1043 4016 V7700 AGP Video Card
- 107d 2840 WinFast GeForce2 GTS with TV output
- 107d 2842 WinFast GeForce 2 Pro
- 1462 8831 Creative GeForce2 Pro
- 0151 NV15DDR [GeForce2 Ti]
- 1043 405f V7700Ti
- 1462 5506 Creative 3D Blaster Geforce2 Titanium
- 0152 NV15BR [GeForce2 Ultra, Bladerunner]
- 1048 0c56 GLADIAC Ultra
- 0153 NV15GL [Quadro2 Pro]
- 0170 NV17 [GeForce4 MX 460]
- 0171 NV17 [GeForce4 MX 440]
- 10b0 0002 Gainward Pro/600 TV
- 1462 8661 G4MX440-VTP
- 1462 8730 MX440SES-T (MS-8873)
- 147b 8f00 Abit Siluro GeForce4MX440
- 0172 NV17 [GeForce4 MX 420]
- 0173 NV17 [GeForce4 MX 440-SE]
- 0174 NV17 [GeForce4 440 Go]
- 0175 NV17 [GeForce4 420 Go]
- 0176 NV17 [GeForce4 420 Go 32M]
- 4c53 1090 Cx9 / Vx9 mainboard
- 0177 NV17 [GeForce4 460 Go]
- 0178 NV17GL [Quadro4 550 XGL]
- 0179 NV17 [GeForce4 440 Go 64M]
- 10de 0179 GeForce4 MX (Mac)
- 017a NV17GL [Quadro4 200/400 NVS]
- 017b NV17GL [Quadro4 550 XGL]
- 017c NV17GL [Quadro4 550 GoGL]
- 017d NV17 [GeForce4 410 Go 16M]
- 0181 NV18 [GeForce4 MX 440 AGP 8x]
- 1043 806f V9180 Magic
- 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X
- 1462 8900 MS-8890 GeForce 4 MX440 AGP8X
- 1462 9350 MSI Geforce4 MX T8X with AGP8X
- 147b 8f0d Siluro GF4 MX-8X
- 0182 NV18 [GeForce4 MX 440SE AGP 8x]
- 0183 NV18 [GeForce4 MX 420 AGP 8x]
- 0185 NV18 [GeForce4 MX 4000 AGP 8x]
- 0186 NV18M [GeForce4 448 Go]
- 0187 NV18M [GeForce4 488 Go]
- 0188 NV18GL [Quadro4 580 XGL]
- 018a NV18GL [Quadro4 NVS AGP 8x]
- 018b NV18GL [Quadro4 380 XGL]
- 018d NV18M [GeForce4 448 Go]
- 01a0 NVCrush11 [GeForce2 MX Integrated Graphics]
- 01a4 nForce CPU bridge
- 01ab nForce 420 Memory Controller (DDR)
- 01ac nForce 220/420 Memory Controller
- 01ad nForce 220/420 Memory Controller
- 01b0 nForce Audio
- 01b1 nForce Audio
- 01b2 nForce ISA Bridge
- 01b4 nForce PCI System Management
- 01b7 nForce AGP to PCI Bridge
- 01b8 nForce PCI-to-PCI bridge
- 01bc nForce IDE
- 01c1 nForce AC'97 Modem Controller
- 01c2 nForce USB Controller
- 01c3 nForce Ethernet Controller
- 01e0 nForce2 AGP (different version?)
- 01e8 nForce2 AGP
- 01ea nForce2 Memory Controller 0
- 01eb nForce2 Memory Controller 1
- 01ec nForce2 Memory Controller 2
- 01ed nForce2 Memory Controller 3
- 01ee nForce2 Memory Controller 4
- 01ef nForce2 Memory Controller 5
- 01f0 NV18 [GeForce4 MX - nForce GPU]
- 0200 NV20 [GeForce3]
- 1043 402f AGP-V8200 DDR
- 0201 NV20 [GeForce3 Ti 200]
- 0202 NV20 [GeForce3 Ti 500]
- 1043 405b V8200 T5
- 1545 002f Xtasy 6964
- 0203 NV20DCC [Quadro DCC]
- 0240 C51 PCI Express Bridge
- 0241 C51 PCI Express Bridge
- 0242 C51 PCI Express Bridge
- 0243 C51 PCI Express Bridge
- 0244 C51 PCI Express Bridge
- 0245 C51 PCI Express Bridge
- 0246 C51 PCI Express Bridge
- 0247 C51 PCI Express Bridge
- 0248 C51 PCI Express Bridge
- 0249 C51 PCI Express Bridge
- 024a C51 PCI Express Bridge
- 024b C51 PCI Express Bridge
- 024c C51 PCI Express Bridge
- 024d C51 PCI Express Bridge
- 024e C51 PCI Express Bridge
- 024f C51 PCI Express Bridge
- 0250 NV25 [GeForce4 Ti 4600]
- 0251 NV25 [GeForce4 Ti 4400]
- 1043 8023 v8440 GeForce 4 Ti4400
- 0252 NV25 [GeForce4 Ti]
- 0253 NV25 [GeForce4 Ti 4200]
- 107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI)
- 147b 8f09 Siluro (Dual VGA/TV-out/DVI)
- 0258 NV25GL [Quadro4 900 XGL]
- 0259 NV25GL [Quadro4 750 XGL]
- 025b NV25GL [Quadro4 700 XGL]
- 0260 MCP51 LPC Bridge
- 0261 MCP51 LPC Bridge
- 0262 MCP51 LPC Bridge
- 0263 MCP51 LPC Bridge
- 0264 MCP51 SMBus
- 0265 MCP51 IDE
- 0266 MCP51 Serial ATA Controller
- 0267 MCP51 Serial ATA Controller
- 0268 MCP51 Ethernet Controller
- 0269 MCP51 Ethernet Controller
- 026a MCP51 MCI
- 026b MCP51 AC97 Audio Controller
- 026c MCP51 High Definition Audio
- 026d MCP51 USB Controller
- 026e MCP51 USB Controller
- 026f MCP51 PCI Bridge
- 0270 MCP51 Host Bridge
- 0271 MCP51 PMU
- 0272 MCP51 Memory Controller 0
- 027e C51 Memory Controller 2
- 027f C51 Memory Controller 3
- 0280 NV28 [GeForce4 Ti 4800]
- 0281 NV28 [GeForce4 Ti 4200 AGP 8x]
- 0282 NV28 [GeForce4 Ti 4800 SE]
- 0286 NV28 [GeForce4 Ti 4200 Go AGP 8x]
- 0288 NV28GL [Quadro4 980 XGL]
- 0289 NV28GL [Quadro4 780 XGL]
- 028c NV28GLM [Quadro4 700 GoGL]
- 02f0 C51 Host Bridge
- 02f1 C51 Host Bridge
- 02f2 C51 Host Bridge
- 02f3 C51 Host Bridge
- 02f4 C51 Host Bridge
- 02f5 C51 Host Bridge
- 02f6 C51 Host Bridge
- 02f7 C51 Host Bridge
- 02f8 C51 Memory Controller 5
- 02f9 C51 Memory Controller 4
- 02fa C51 Memory Controller 0
- 02fb C51 PCI Express Bridge
- 02fc C51 PCI Express Bridge
- 02fd C51 PCI Express Bridge
- 02fe C51 Memory Controller 1
- 02ff C51 Host Bridge
- 0300 NV30 [GeForce FX]
- 0301 NV30 [GeForce FX 5800 Ultra]
- 0302 NV30 [GeForce FX 5800]
- 0308 NV30GL [Quadro FX 2000]
- 0309 NV30GL [Quadro FX 1000]
- 0311 NV31 [GeForce FX 5600 Ultra]
- 0312 NV31 [GeForce FX 5600]
- 0313 NV31
- 0314 NV31 [GeForce FX 5600XT]
- 1043 814a V9560XT/TD
- 0316 NV31
- 0317 NV31
- 031a NV31M [GeForce FX Go 5600]
- 031b NV31M [GeForce FX Go5650]
- 031c NVIDIA Quadro FX 700 Go
- 031d NV31
- 031e NV31
- 031f NV31
- 0320 NV34 [GeForce FX 5200]
- 0321 NV34 [GeForce FX 5200 Ultra]
- 0322 NV34 [GeForce FX 5200]
- 1462 9171 MS-8917 (FX5200-T128)
- 0323 NV34 [GeForce FX 5200LE]
- 0324 NV34M [GeForce FX Go 5200]
- 1071 8160 MIM2000
- 0325 NV34M [GeForce FX Go5250]
- 0326 NV34 [GeForce FX 5500]
- 0327 NV34 [GeForce FX 5100]
- 0328 NV34M [GeForce FX Go 5200]
- 0329 NV34M [GeForce FX Go5200]
- 032a NV34GL [Quadro NVS 280 PCI]
- 032b NV34GL [Quadro FX 500/600 PCI]
- 032c NV34GLM [GeForce FX Go 5300]
- 032d NV34 [GeForce FX Go5100]
- 032f NV34
- 0330 NV35 [GeForce FX 5900 Ultra]
- 0331 NV35 [GeForce FX 5900]
- 1043 8145 V9950GE
- 0332 NV35 [GeForce FX 5900XT]
- 0333 NV38 [GeForce FX 5950 Ultra]
- 0334 NV35 [GeForce FX 5900ZT]
- 0338 NV35GL [Quadro FX 3000]
- 033f NV35GL [Quadro FX 700]
- 0341 NV36.1 [GeForce FX 5700 Ultra]
- 0342 NV36.2 [GeForce FX 5700]
- 0343 NV36 [GeForce FX 5700LE]
- 0344 NV36.4 [GeForce FX 5700VE]
- 0345 NV36.5
- 0347 NV36 [GeForce FX Go5700]
- 0348 NV36 [GeForce FX Go5700]
- 0349 NV36
- 034b NV36
- 034c NV36 [Quadro FX Go1000]
- 034e NV36GL [Quadro FX 1100]
- 034f NV36GL
-10df Emulex Corporation
- 1ae5 LP6000 Fibre Channel Host Adapter
- 1ae6 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- 1ae7 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:2-3)
- f005 LP1150e Fibre Channel Host Adapter
- f085 LP850 Fibre Channel Host Adapter
- f095 LP952 Fibre Channel Host Adapter
- f098 LP982 Fibre Channel Host Adapter
- f0a5 LP1050 Fibre Channel Host Adapter
- f0d5 LP1150 Fibre Channel Host Adapter
- f100 LP11000e Fibre Channel Host Adapter
- f700 LP7000 Fibre Channel Host Adapter
- f701 LP 7000EFibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f800 LP8000 Fibre Channel Host Adapter
- f801 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f900 LP9000 Fibre Channel Host Adapter
- f901 LP 9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f980 LP9802 Fibre Channel Host Adapter
- f981 LP 9802 Fibre Channel Host Adapter Alternate ID
- f982 LP 9802 Fibre Channel Host Adapter Alternate ID
- fa00 LP10000 Fibre Channel Host Adapter
- fa01 LP101 Fibre Channel Host Adapter
- fd00 LP11000 Fibre Channel Host Adapter
-10e0 Integrated Micro Solutions Inc.
- 5026 IMS5026/27/28
- 5027 IMS5027
- 5028 IMS5028
- 8849 IMS8849
- 8853 IMS8853
- 9128 IMS9128 [Twin turbo 128]
-10e1 Tekram Technology Co.,Ltd.
- 0391 TRM-S1040
- 10e1 0391 DC-315U SCSI-3 Host Adapter
- 690c DC-690c
- dc29 DC-290
-10e2 Aptix Corporation
-10e3 Tundra Semiconductor Corp.
- 0000 CA91C042 [Universe]
- 0860 CA91C860 [QSpan]
- 0862 CA91C862A [QSpan-II]
- 8260 CA91L8200B [Dual PCI PowerSpan II]
- 8261 CA91L8260B [Single PCI PowerSpan II]
-10e4 Tandem Computers
-10e5 Micro Industries Corporation
-10e6 Gainbery Computer Products Inc.
-10e7 Vadem
-10e8 Applied Micro Circuits Corp.
- 1072 INES GPIB-PCI (AMCC5920 based)
- 2011 Q-Motion Video Capture/Edit board
- 4750 S5930 [Matchmaker]
- 5920 S5920
- 8043 LANai4.x [Myrinet LANai interface chip]
- 8062 S5933_PARASTATION
- 807d S5933 [Matchmaker]
- 8088 Kongsberg Spacetec Format Synchronizer
- 8089 Kongsberg Spacetec Serial Output Board
- 809c S5933_HEPC3
- 80d7 PCI-9112
- 80d9 PCI-9118
- 80da PCI-9812
- 811a PCI-IEEE1355-DS-DE Interface
- 814c Fastcom ESCC-PCI (Commtech, Inc.)
- 8170 S5933 [Matchmaker] (Chipset Development Tool)
-# sold with Roper Scientifc(Photometrics) CoolSnap HQ camera
- 81e6 Multimedia video controller
- 8291 Fastcom 232/8-PCI (Commtech, Inc.)
- 82c4 Fastcom 422/4-PCI (Commtech, Inc.)
- 82c5 Fastcom 422/2-PCI (Commtech, Inc.)
- 82c6 Fastcom IG422/1-PCI (Commtech, Inc.)
- 82c7 Fastcom IG232/2-PCI (Commtech, Inc.)
- 82ca Fastcom 232/4-PCI (Commtech, Inc.)
- 82db AJA HDNTV HD SDI Framestore
- 82e2 Fastcom DIO24H-PCI (Commtech, Inc.)
- 8851 S5933 on Innes Corp FM Radio Capture card
-10e9 Alps Electric Co., Ltd.
-10ea Intergraphics Systems
- 1680 IGA-1680
- 1682 IGA-1682
- 1683 IGA-1683
- 2000 CyberPro 2000
- 2010 CyberPro 2000A
- 5000 CyberPro 5000
- 5050 CyberPro 5050
- 5202 CyberPro 5202
-# CyberPro5202 Audio Function
- 5252 CyberPro5252
-10eb Artists Graphics
- 0101 3GA
- 8111 Twist3 Frame Grabber
-10ec Realtek Semiconductor Co., Ltd.
- 8029 RTL-8029(AS)
- 10b8 2011 EZ-Card (SMC1208)
- 10ec 8029 RTL-8029(AS)
- 1113 1208 EN1208
- 1186 0300 DE-528
- 1259 2400 AT-2400
- 8129 RTL-8129
- 10ec 8129 RT8129 Fast Ethernet Adapter
- 8138 RT8139 (B/C) Cardbus Fast Ethernet Adapter
- 10ec 8138 RT8139 (B/C) Fast Ethernet Adapter
- 8139 RTL-8139/8139C/8139C+
- 0357 000a TTP-Monitoring Card V2.0
- 1025 005a TravelMate 290
- 1025 8920 ALN-325
- 1025 8921 ALN-325
- 1071 8160 MIM2000
- 10bd 0320 EP-320X-R
- 10ec 8139 RT8139
- 1113 ec01 FNC-0107TX
- 1186 1300 DFE-538TX
- 1186 1320 SN5200
- 1186 8139 DRN-32TX
- 11f6 8139 FN22-3(A) LinxPRO Ethernet Adapter
- 1259 2500 AT-2500TX
- 1259 2503 AT-2500TX/ACPI
- 1429 d010 ND010
- 1432 9130 EN-9130TX
- 1436 8139 RT8139
- 1458 e000 GA-7VM400M/7VT600 Motherboard
- 146c 1439 FE-1439TX
- 1489 6001 GF100TXRII
- 1489 6002 GF100TXRA
- 149c 139a LFE-8139ATX
- 149c 8139 LFE-8139TX
- 14cb 0200 LNR-100 Family 10/100 Base-TX Ethernet
- 1799 5000 F5D5000 PCI Card/Desktop Network PCI Card
- 2646 0001 EtheRx
- 8e2e 7000 KF-230TX
- 8e2e 7100 KF-230TX/2
- a0a0 0007 ALN-325C
- 8169 RTL-8169 Gigabit Ethernet
- 1259 c107 CG-LAPCIGT
- 1371 434e ProG-2000L
- 1458 e000 GA-K8VT800 Pro Motherboard
- 1462 702c K8T NEO 2 motherboard
- 8180 RTL8180L 802.11b MAC
- 8197 SmartLAN56 56K Modem
-10ed Ascii Corporation
- 7310 V7310
-10ee Xilinx Corporation
- 3fc0 RME Digi96
- 3fc1 RME Digi96/8
- 3fc2 RME Digi96/8 Pro
- 3fc3 RME Digi96/8 Pad
- 3fc4 RME Digi9652 (Hammerfall)
- 3fc5 RME Hammerfall DSP
- 3fc6 RME Hammerfall DSP MADI
- 8381 Ellips Santos Frame Grabber
-10ef Racore Computer Products, Inc.
- 8154 M815x Token Ring Adapter
-10f0 Peritek Corporation
-10f1 Tyan Computer
-10f2 Achme Computer, Inc.
-10f3 Alaris, Inc.
-10f4 S-MOS Systems, Inc.
-10f5 NKK Corporation
- a001 NDR4000 [NR4600 Bridge]
-10f6 Creative Electronic Systems SA
-10f7 Matsushita Electric Industrial Co., Ltd.
-10f8 Altos India Ltd
-10f9 PC Direct
-10fa Truevision
- 000c TARGA 1000
-10fb Thesys Gesellschaft für Mikroelektronik mbH
- 186f TH 6255
-10fc I-O Data Device, Inc.
-# What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives
- 0003 Cardbus IDE Controller
- 0005 Cardbus SCSI CBSC II
-10fd Soyo Computer, Inc
-10fe Fast Multimedia AG
-10ff NCube
-1100 Jazz Multimedia
-1101 Initio Corporation
- 1060 INI-A100U2W
- 9100 INI-9100/9100W
- 9400 INI-940
- 9401 INI-950
- 9500 360P
- 9502 Initio INI-9100UW Ultra Wide SCSI Controller INIC-950P chip
-1102 Creative Labs
- 0002 SB Live! EMU10k1
- 1102 0020 CT4850 SBLive! Value
- 1102 0021 CT4620 SBLive!
- 1102 002f SBLive! mainboard implementation
- 1102 4001 E-mu APS
- 1102 8022 CT4780 SBLive! Value
- 1102 8023 CT4790 SoundBlaster PCI512
- 1102 8024 CT4760 SBLive!
- 1102 8025 SBLive! Mainboard Implementation
- 1102 8026 CT4830 SBLive! Value
- 1102 8027 CT4832 SBLive! Value
- 1102 8028 CT4760 SBLive! OEM version
- 1102 8031 CT4831 SBLive! Value
- 1102 8040 CT4760 SBLive!
- 1102 8051 CT4850 SBLive! Value
- 1102 8061 SBLive! Player 5.1
- 1102 8064 SB Live! 5.1 Model SB0100
- 1102 8065 SBLive! 5.1 Digital Model SB0220
- 1102 8067 SBLive! 5.1 eMicro 28028
- 0004 SB Audigy
- 1102 0051 SB0090 Audigy Player
- 1102 0053 SB0090 Audigy Player/OEM
- 1102 0058 SB0090 Audigy Player/OEM
- 1102 1007 SB0240 Audigy 2 Platinum 6.1
- 1102 2002 SB Audigy 2 ZS (SB0350)
- 0006 [SB Live! Value] EMU10k1X
- 0007 SB Audigy LS
- 1102 1001 SB0310 Audigy LS
- 1102 1002 SB0312 Audigy LS
- 1102 1006 SB0410 SBLive! 24-bit
- 0008 SB0400 Audigy2 Value
- 4001 SB Audigy FireWire Port
- 1102 0010 SB Audigy FireWire Port
- 7002 SB Live! MIDI/Game Port
- 1102 0020 Gameport Joystick
- 7003 SB Audigy MIDI/Game port
- 1102 0040 SB Audigy MIDI/Game Port
- 7004 [SB Live! Value] Input device controller
- 7005 SB Audigy LS MIDI/Game port
- 1102 1001 SB0310 Audigy LS MIDI/Game port
- 1102 1002 SB0312 Audigy LS MIDI/Game port
- 8064 SB0100 [SBLive! 5.1 OEM]
- 8938 Ectiva EV1938
- 1033 80e5 SlimTower-Jim (NEC)
- 1071 7150 Mitac 7150
- 110a 5938 Siemens Scenic Mobile 510PIII
- 13bd 100c Ceres-C (Sharp, Intel BX)
- 13bd 100d Sharp, Intel Banister
- 13bd 100e TwinHead P09S/P09S3 (Sharp)
- 13bd f6f1 Marlin (Sharp)
- 14ff 0e70 P88TE (TWINHEAD INTERNATIONAL Corp)
- 14ff c401 Notebook 9100/9200/2000 (TWINHEAD INTERNATIONAL Corp)
- 156d b400 G400 - Geo (AlphaTop (Taiwan))
- 156d b550 G560 (AlphaTop (Taiwan))
- 156d b560 G560 (AlphaTop (Taiwan))
- 156d b700 G700/U700 (AlphaTop (Taiwan))
- 156d b795 G795 (AlphaTop (Taiwan))
- 156d b797 G797 (AlphaTop (Taiwan))
-1103 Triones Technologies, Inc.
- 0003 HPT343
- 0004 HPT366/368/370/370A/372/372N
- 1103 0001 HPT370A
- 1103 0003 HPT343 / HPT345 / HPT363 UDMA33
- 1103 0004 HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)
- 1103 0005 HPT370 UDMA100
- 1103 0006 HPT302
- 1103 0007 HPT371 UDMA133
- 1103 0008 HPT374 UDMA/ATA133 RAID Controller
- 0005 HPT372A/372N
- 0006 HPT302
- 0007 HPT371/371N
- 0008 HPT374
- 0009 HPT372N
-1104 RasterOps Corp.
-1105 Sigma Designs, Inc.
- 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder
- 8300 REALmagic Hollywood Plus DVD Decoder
- 8400 EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder
- 8401 EM8401 REALmagic DVD/MPEG-2 A/V Decoder
- 8470 EM8470 REALmagic DVD/MPEG-4 A/V Decoder
- 8471 EM8471 REALmagic DVD/MPEG-4 A/V Decoder
- 8475 EM8475 REALmagic DVD/MPEG-4 A/V Decoder
- 8476 EM8476 REALmagic DVD/MPEG-4 A/V Decoder
- 8485 EM8485 REALmagic DVD/MPEG-4 A/V Decoder
- 8486 EM8486 REALmagic DVD/MPEG-4 A/V Decoder
-1106 VIA Technologies, Inc.
- 0102 Embedded VIA Ethernet Controller
- 0130 VT6305 1394.A Controller
- 0305 VT8363/8365 [KT133/KM133]
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 147b a401 KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard
- 0391 VT8371 [KX133]
- 0501 VT8501 [Apollo MVP4]
- 0505 VT82C505
-# Shares chip with :0576. The VT82C576M has :1571 instead of :0561.
- 0561 VT82C576MV
- 0571 VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE
- 1019 0985 P6VXA Motherboard
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 8052 VT8233A Bus Master ATA100/66/33 IDE
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard rev. 1.01
- 1043 80ed A7V600 motherboard
- 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE
- 1179 0001 Magnia Z310
- 1297 f641 FX41 motherboard
- 1458 5002 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 1849 0571 K7VT2 motherboard
- 0576 VT82C576 3V [Apollo Master]
- 0585 VT82C585VP [Apollo VP1/VPX]
- 0586 VT82C586/A/B PCI-to-ISA [Apollo VP]
- 1106 0000 MVP3 ISA Bridge
- 0595 VT82C595 [Apollo VP2]
- 0596 VT82C596 ISA [Mobile South]
- 1106 0000 VT82C596/A/B PCI to ISA Bridge
- 1458 0596 VT82C596/A/B PCI to ISA Bridge
- 0597 VT82C597 [Apollo VP3]
- 0598 VT82C598 [Apollo MVP3]
- 0601 VT8601 [Apollo ProMedia]
- 0605 VT8605 [ProSavage PM133]
- 1043 802c CUV4X mainboard
- 0680 VT82C680 [Apollo P6]
- 0686 VT82C686 [Apollo Super South]
- 1019 0985 P6VXA Motherboard
- 1043 802c CUV4X mainboard
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8040 A7M266 Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 1106 0000 VT82C686/A PCI to ISA Bridge
- 1106 0686 VT82C686/A PCI to ISA Bridge
- 1179 0001 Magnia Z310
- 147b a702 KG7-Lite Mainboard
- 0691 VT82C693A/694x [Apollo PRO133x]
- 1019 0985 P6VXA Motherboard
- 1179 0001 Magnia Z310
- 1458 0691 VT82C691 Apollo Pro System Controller
- 0693 VT82C693 [Apollo Pro Plus]
- 0698 VT82C693A [Apollo Pro133 AGP]
- 0926 VT82C926 [Amazon]
- 1000 VT82C570MV
- 1106 VT82C570MV
- 1571 VT82C576M/VT82C586
- 1595 VT82C595/97 [Apollo VP2/97]
- 3022 CLE266
-# This is *not* USB 2.0 as the existing entry suggests
- 3038 VT82xxxxx UHCI USB 1.1 Controller
- 0925 1234 USB Controller
- 1019 0985 P6VXA Motherboard
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c VT6202 USB2.0 4 port controller
- 1043 80a1 A7V8X-X motherboard
- 1043 80ed A7V600 motherboard
- 1179 0001 Magnia Z310
- 1458 5004 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 182d 201d CN-029 USB2.0 4 port PCI Card
- 3040 VT82C586B ACPI
- 3043 VT86C100A [Rhine]
- 10bd 0000 VT86C100A Fast Ethernet Adapter
- 1106 0100 VT86C100A Fast Ethernet Adapter
- 1186 1400 DFE-530TX rev A
- 3044 IEEE 1394 Host Controller
- 1025 005a TravelMate 290
- 1458 1000 GA-7VT600-1394 Motherboard
- 1462 702d K8T NEO 2 motherboard
- 3050 VT82C596 Power Management
- 3051 VT82C596 Power Management
- 3053 VT6105M [Rhine-III]
- 3057 VT82C686 [Apollo Super ACPI]
- 1019 0985 P6VXA Motherboard
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8040 A7M266 Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 1179 0001 Magnia Z310
- 3058 VT82C686 AC97 Audio Controller
- 0e11 0097 SoundMax Digital Integrated Audio
- 0e11 b194 Soundmax integrated digital audio
- 1019 0985 P6VXA Motherboard
- 1043 1106 A7V133/A7V133-C Mainboard
- 1106 4511 Onboard Audio on EP7KXA
- 1458 7600 Onboard Audio
- 1462 3091 MS-6309 Onboard Audio
- 1462 3300 MS-6330 Onboard Audio
- 15dd 7609 Onboard Audio
- 3059 VT8233/A/8235/8237 AC97 Audio Controller
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 8095 A7V8X Motherboard (Realtek ALC650 codec)
- 1043 80a1 A7V8X-X Motherboard
- 1043 80b0 A7V600/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX])
- 1106 3059 L7VMM2 Motherboard
- 1106 4161 K7VT2 motherboard
- 1297 c160 FX41 motherboard (Realtek ALC650 codec)
- 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650)
- 1462 0080 K8T NEO 2 motherboard
- 1462 3800 KT266 onboard audio
- 147b 1407 KV8-MAX3 motherboard
- 3065 VT6102 [Rhine-II]
- 1043 80a1 A7V8X-X Motherboard
- 1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235
- 1186 1400 DFE-530TX rev A
- 1186 1401 DFE-530TX rev B
- 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
-# This hosts more than just the Intel 537 codec, it also hosts PCtel (SIL33) and SmartLink (SIL34) codecs
- 3068 AC'97 Modem Controller
- 1462 309e MS-6309 Saturn Motherboard
- 3074 VT8233 PCI to ISA Bridge
- 1043 8052 VT8233A
- 3091 VT8633 [Apollo Pro266]
- 3099 VT8366/A/7 [Apollo KT266/A/333]
- 1043 8064 A7V266-E Mainboard
- 1043 807f A7V333 Mainboard
- 1849 3099 K7VT2 motherboard
- 3101 VT8653 Host Bridge
- 3102 VT8662 Host Bridge
- 3103 VT8615 Host Bridge
- 3104 USB 2.0
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard rev 1.01
- 1043 80ed A7V600 motherboard
- 1297 f641 FX41 motherboard
- 1458 5004 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 182d 201d CN-029 USB 2.0 4 port PCI Card
- 3106 VT6105 [Rhine-III]
- 1186 1403 DFE-530TX rev C
- 3108 S3 Unichrome Pro VGA Adapter
- 3109 VT8233C PCI to ISA Bridge
- 3112 VT8361 [KLE133] Host Bridge
- 3116 VT8375 [KM266/KL266] Host Bridge
- 1297 f641 FX41 motherboard
- 3118 S3 Unichrome Pro VGA Adapter
- 3119 VT6120/VT6121/VT6122 Gigabit Ethernet Adapter
-# found on EPIA M6000/9000 mainboard
- 3122 VT8623 [Apollo CLE266] integrated CastleRock graphics
-# found on EPIA M6000/9000 mainboard
- 3123 VT8623 [Apollo CLE266]
- 3128 VT8753 [P4X266 AGP]
- 3133 VT3133 Host Bridge
- 3147 VT8233A ISA Bridge
- 3148 P4M266 Host Bridge
- 3149 VIA VT6420 SATA RAID Controller
- 1043 80ed A7V600/K8V Deluxe motherboard
- 1458 b003 GA-7VM400AM(F) Motherboard
- 1462 7020 K8T Neo 2 Motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3156 P/KN266 Host Bridge
-# on ASUS P4P800
- 3164 VT6410 ATA133 RAID controller
- 3168 VT8374 P4X400 Host Controller/AGP Bridge
- 3177 VT8235 ISA Bridge
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard
- 1297 f641 FX41 motherboard
- 1458 5001 GA-7VAX Mainboard
- 1849 3177 K7VT2 motherboard
- 3178 ProSavageDDR P4N333 Host Bridge
- 3188 VT8385 [K8T800 AGP] Host Bridge
- 1043 80a3 K8V Deluxe motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3189 VT8377 [KT400/KT600 AGP] Host Bridge
- 1043 807f A7V8X motherboard
- 1458 5000 GA-7VAX Mainboard
- 3204 K8M800
- 3205 VT8378 [KM400/A] Chipset Host Bridge
- 1458 5000 GA-7VM400M Motherboard
- 3218 K8T800M Host Bridge
- 3227 VT8237 ISA bridge [KT600/K8T800 South]
- 1043 80ed A7V600 motherboard
- 1106 3227 DFI KT600-AL Motherboard
- 1458 5001 GA-7VT600 Motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3249 VT6421 IDE RAID Controller
- 4149 VIA VT6420 (ATA133) Controller
- 5030 VT82C596 ACPI [Apollo PRO]
- 6100 VT85C100A [Rhine II]
- 7204 K8M800
-# S3 Graphics UniChromeâ„¢ 2D/3D Graphics with motion compensation
- 7205 VT8378 [S3 UniChrome] Integrated Video
- 1458 d000 Gigabyte GA-7VM400(A)M(F) Motherboard
- 8231 VT8231 [PCI-to-ISA Bridge]
- 8235 VT8235 ACPI
- 8305 VT8363/8365 [KT133/KM133 AGP]
- 8391 VT8371 [KX133 AGP]
- 8501 VT8501 [Apollo MVP4 AGP]
- 8596 VT82C596 [Apollo PRO AGP]
- 8597 VT82C597 [Apollo VP3 AGP]
- 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP]
- 1019 0985 P6VXA Motherboard
- 8601 VT8601 [Apollo ProMedia AGP]
- 8605 VT8605 [PM133 AGP]
- 8691 VT82C691 [Apollo Pro]
- 8693 VT82C693 [Apollo Pro Plus] PCI Bridge
- b091 VT8633 [Apollo Pro266 AGP]
- b099 VT8366/A/7 [Apollo KT266/A/333 AGP]
- b101 VT8653 AGP Bridge
- b102 VT8362 AGP Bridge
- b103 VT8615 AGP Bridge
- b112 VT8361 [KLE133] AGP Bridge
- b168 VT8235 PCI Bridge
- b188 VT8237 PCI bridge [K8T800 South]
- 147b 1407 KV8-MAX3 motherboard
- b198 VT8237 PCI Bridge
-# 32-Bit PCI bus master Ethernet MAC with standard MII interface
- d104 VT8237 Integrated Fast Ethernet Controller
-1107 Stratus Computers
- 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!)
-1108 Proteon, Inc.
- 0100 p1690plus_AA
- 0101 p1690plus_AB
- 0105 P1690Plus
- 0108 P1690Plus
- 0138 P1690Plus
- 0139 P1690Plus
- 013c P1690Plus
- 013d P1690Plus
-1109 Cogent Data Technologies, Inc.
- 1400 EM110TX [EX110TX]
-110a Siemens Nixdorf AG
- 0002 Pirahna 2-port
- 0005 Tulip controller, power management, switch extender
- 0006 FSC PINC (I/O-APIC)
- 0015 FSC Multiprocessor Interrupt Controller
- 001d FSC Copernicus Management Controller
- 007b FSC Remote Service Controller, mailbox device
- 007c FSC Remote Service Controller, shared memory device
- 007d FSC Remote Service Controller, SMIC device
-# Superfastcom-PCI (Commtech, Inc.) or DSCC4 WAN Adapter
- 2102 DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Controller with 4 Channels
- 2104 Eicon Diva 2.02 compatible passive ISDN card
- 3142 SIMATIC NET CP 5613A1 (Profibus Adapter)
- 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter)
- 4029 SIMATIC NET CP 5613A2 (Profibus Adapter)
- 4942 FPGA I-Bus Tracer for MBD
- 6120 SZB6120
-110b Chromatic Research Inc.
- 0001 Mpact Media Processor
- 0004 Mpact 2
-110c Mini-Max Technology, Inc.
-110d Znyx Advanced Systems
-110e CPU Technology
-110f Ross Technology
-1110 Powerhouse Systems
- 6037 Firepower Powerized SMP I/O ASIC
- 6073 Firepower Powerized SMP I/O ASIC
-1111 Santa Cruz Operation
-# Also claimed to be RNS or Rockwell International, current PCISIG records list Osicom
-1112 Osicom Technologies Inc
- 2200 FDDI Adapter
- 2300 Fast Ethernet Adapter
- 2340 4 Port Fast Ethernet Adapter
- 2400 ATM Adapter
-1113 Accton Technology Corporation
- 1211 SMC2-1211TX
- 103c 1207 EN-1207D Fast Ethernet Adapter
- 1113 1211 EN-1207D Fast Ethernet Adapter
- 1216 EN-1216 Ethernet Adapter
- 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card
- 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]
- 1217 EN-1217 Ethernet Adapter
- 5105 10Mbps Network card
- 9211 EN-1207D Fast Ethernet Adapter
- 1113 9211 EN-1207D Fast Ethernet Adapter
- 9511 21x4x DEC-Tulip compatible Fast Ethernet
- d301 CPWNA100 (Philips wireless PCMCIA)
- ec02 SMC 1244TX v3
-1114 Atmel Corporation
- 0506 802.11b Wireless Network Adaptor (at76c506)
-1115 3D Labs
-1116 Data Translation
- 0022 DT3001
- 0023 DT3002
- 0024 DT3003
- 0025 DT3004
- 0026 DT3005
- 0027 DT3001-PGL
- 0028 DT3003-PGL
-1117 Datacube, Inc
- 9500 Max-1C SVGA card
- 9501 Max-1C image processing
-1118 Berg Electronics
-1119 ICP Vortex Computersysteme GmbH
- 0000 GDT 6000/6020/6050
- 0001 GDT 6000B/6010
- 0002 GDT 6110/6510
- 0003 GDT 6120/6520
- 0004 GDT 6530
- 0005 GDT 6550
- 0006 GDT 6117/6517
- 0007 GDT 6127/6527
- 0008 GDT 6537
- 0009 GDT 6557/6557-ECC
- 000a GDT 6115/6515
- 000b GDT 6125/6525
- 000c GDT 6535
- 000d GDT 6555
- 0010 GDT 6115/6515
- 0011 GDT 6125/6525
- 0012 GDT 6535
- 0013 GDT 6555/6555-ECC
- 0100 GDT 6117RP/6517RP
- 0101 GDT 6127RP/6527RP
- 0102 GDT 6537RP
- 0103 GDT 6557RP
- 0104 GDT 6111RP/6511RP
- 0105 GDT 6121RP/6521RP
- 0110 GDT 6117RD/6517RD
- 0111 GDT 6127RD/6527RD
- 0112 GDT 6537RD
- 0113 GDT 6557RD
- 0114 GDT 6111RD/6511RD
- 0115 GDT 6121RD/6521RD
- 0118 GDT 6118RD/6518RD/6618RD
- 0119 GDT 6128RD/6528RD/6628RD
- 011a GDT 6538RD/6638RD
- 011b GDT 6558RD/6658RD
- 0120 GDT 6117RP2/6517RP2
- 0121 GDT 6127RP2/6527RP2
- 0122 GDT 6537RP2
- 0123 GDT 6557RP2
- 0124 GDT 6111RP2/6511RP2
- 0125 GDT 6121RP2/6521RP2
- 0136 GDT 6113RS/6513RS
- 0137 GDT 6123RS/6523RS
- 0138 GDT 6118RS/6518RS/6618RS
- 0139 GDT 6128RS/6528RS/6628RS
- 013a GDT 6538RS/6638RS
- 013b GDT 6558RS/6658RS
- 013c GDT 6533RS/6633RS
- 013d GDT 6543RS/6643RS
- 013e GDT 6553RS/6653RS
- 013f GDT 6563RS/6663RS
- 0166 GDT 7113RN/7513RN/7613RN
- 0167 GDT 7123RN/7523RN/7623RN
- 0168 GDT 7118RN/7518RN/7518RN
- 0169 GDT 7128RN/7528RN/7628RN
- 016a GDT 7538RN/7638RN
- 016b GDT 7558RN/7658RN
- 016c GDT 7533RN/7633RN
- 016d GDT 7543RN/7643RN
- 016e GDT 7553RN/7653RN
- 016f GDT 7563RN/7663RN
- 01d6 GDT 4x13RZ
- 01d7 GDT 4x23RZ
- 01f6 GDT 8x13RZ
- 01f7 GDT 8x23RZ
- 01fc GDT 8x33RZ
- 01fd GDT 8x43RZ
- 01fe GDT 8x53RZ
- 01ff GDT 8x63RZ
- 0210 GDT 6519RD/6619RD
- 0211 GDT 6529RD/6629RD
- 0260 GDT 7519RN/7619RN
- 0261 GDT 7529RN/7629RN
- 02ff GDT MAXRP
- 0300 GDT NEWRX
-111a Efficient Networks, Inc
- 0000 155P-MF1 (FPGA)
- 0002 155P-MF1 (ASIC)
- 0003 ENI-25P ATM
- 111a 0000 ENI-25p Miniport ATM Adapter
- 0005 SpeedStream (LANAI)
- 111a 0001 ENI-3010 ATM
- 111a 0009 ENI-3060 ADSL (VPI=0)
- 111a 0101 ENI-3010 ATM
- 111a 0109 ENI-3060CO ADSL (VPI=0)
- 111a 0809 ENI-3060 ADSL (VPI=0 or 8)
- 111a 0909 ENI-3060CO ADSL (VPI=0 or 8)
- 111a 0a09 ENI-3060 ADSL (VPI=<0..15>)
- 0007 SpeedStream ADSL
- 111a 1001 ENI-3061 ADSL [ASIC]
- 1203 SpeedStream 1023 Wireless PCI Adapter
-111b Teledyne Electronic Systems
-111c Tricord Systems Inc.
- 0001 Powerbis Bridge
-111d Integrated Device Technology, Inc.
- 0001 IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
- 0003 IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller
- 0004 IDT77V252 155Mbps ATM MICRO ABR SAR Controller
- 0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller
-111e Eldec
-111f Precision Digital Images
- 4a47 Precision MX Video engine interface
- 5243 Frame capture bus interface
-1120 EMC Corporation
-1121 Zilog
-1122 Multi-tech Systems, Inc.
-1123 Excellent Design, Inc.
-1124 Leutron Vision AG
-1125 Eurocore
-1126 Vigra
-1127 FORE Systems Inc
- 0200 ForeRunner PCA-200 ATM
- 0210 PCA-200PC
- 0250 ATM
- 0300 ForeRunner PCA-200EPC ATM
- 0310 ATM
- 0400 ForeRunnerHE ATM Adapter
- 1127 0400 ForeRunnerHE ATM
-1129 Firmworks
-112a Hermes Electronics Company, Ltd.
-112b Linotype - Hell AG
-112c Zenith Data Systems
-112d Ravicad
-112e Infomedia Microelectronics Inc.
-112f Imaging Technology Inc
- 0000 MVC IC-PCI
- 0001 MVC IM-PCI Video frame grabber/processor
-1130 Computervision
-1131 Philips Semiconductors
- 1561 USB 1.1 Host Controller
- 1562 USB 2.0 Host Controller
- 3400 SmartPCI56(UCB1500) 56K Modem
- 5400 TriMedia TM1000/1100
- 5402 TriMedia TM-1300
- 1244 0f00 Fritz!Card DSL
- 7130 SAA7130 Video Broadcast Decoder
- 5168 0138 LiveView FlyVideo 2000
- 7133 SAA713X Audio+video broadcast decoder
- 5168 0138 LifeView FlyVideo 3000
- 5168 0212 LifeView FlyTV Platinum mini
- 5168 0502 LifeView FlyDVB-T Duo CardBus
-# PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl)
- 7134 SAA7134
- 1043 4842 TV-FM Card 7134
- 7135 SAA7135 Audio+video broadcast decoder
- 7145 SAA7145
- 7146 SAA7146
- 110a 0000 Fujitsu/Siemens DVB-C card rev1.5
- 110a ffff Fujitsu/Siemens DVB-C card rev1.5
- 1131 4f56 KNC1 DVB-S Budget
- 1131 4f61 Fujitsu-Siemens Activy DVB-S Budget
- 114b 2003 DVRaptor Video Edit/Capture Card
- 11bd 0006 DV500 Overlay
- 11bd 000a DV500 Overlay
- 11bd 000f DV500 Overlay
- 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5
- 13c2 0001 Technotrend/Hauppauge DVB card rev1.3 or rev1.6
- 13c2 0002 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0003 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0004 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0006 Technotrend/Hauppauge DVB card rev1.3 or rev1.6
- 13c2 0008 Technotrend/Hauppauge DVB-T
- 13c2 000a Octal/Technotrend DVB-C for iTV
- 13c2 1003 Technotrend-Budget / Hauppauge WinTV-NOVA-S DVB card
- 13c2 1004 Technotrend-Budget / Hauppauge WinTV-NOVA-C DVB card
- 13c2 1005 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card
- 13c2 100c Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card
- 13c2 100f Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card
- 13c2 1011 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card
- 13c2 1013 SATELCO Multimedia DVB
- 13c2 1102 Technotrend/Hauppauge DVB card rev2.1
-1132 Mitel Corp.
-# This is the new official company name. See disclaimer on www.eicon.com for details!
-1133 Eicon Networks Corporation
- 7901 EiconCard S90
- 7902 EiconCard S90
- 7911 EiconCard S91
- 7912 EiconCard S91
- 7941 EiconCard S94
- 7942 EiconCard S94
- 7943 EiconCard S94
- 7944 EiconCard S94
- b921 EiconCard P92
- b922 EiconCard P92
- b923 EiconCard P92
- e001 Diva Pro 2.0 S/T
- e002 Diva 2.0 S/T PCI
- e003 Diva Pro 2.0 U
- e004 Diva 2.0 U PCI
- e005 Diva 2.01 S/T PCI
- e006 Diva CT S/T PCI
- e007 Diva CT U PCI
- e008 Diva CT Lite S/T PCI
- e009 Diva CT Lite U PCI
- e00a Diva ISDN+V.90 PCI
- e00b Diva 2.02 PCI S/T
- e00c Diva 2.02 PCI U
- e00d Diva ISDN Pro 3.0 PCI
- e00e Diva ISDN+CT S/T PCI Rev 2
- e010 Diva Server BRI-2M PCI
- 110a 0021 Fujitsu Siemens ISDN S0
- 8001 0014 Diva Server BRI-2M PCI Cornet NQ
- e011 Diva Server BRI S/T Rev 2
- e012 Diva Server 4BRI-8M PCI
- 8001 0014 Diva Server 4BRI-8M PCI Cornet NQ
- e013 Diva Server 4BRI Rev 2
- 1133 1300 Diva Server V-4BRI-8
- 1133 e013 Diva Server 4BRI-8M 2.0 PCI
- 8001 0014 Diva Server 4BRI-8M 2.0 PCI Cornet NQ
- e014 Diva Server PRI-30M PCI
- 0008 0100 Diva Server PRI-30M PCI
- 8001 0014 Diva Server PRI-30M PCI Cornet NQ
- e015 DIVA Server PRI Rev 2
- 1133 e015 Diva Server PRI 2.0 PCI
- 8001 0014 Diva Server PRI 2.0 PCI Cornet NQ
- e016 Diva Server Voice 4BRI PCI
- 8001 0014 Diva Server PRI Cornet NQ
- e017 Diva Server Voice 4BRI Rev 2
- 1133 e017 Diva Server Voice 4BRI-8M 2.0 PCI
- 8001 0014 Diva Server Voice 4BRI-8M 2.0 PCI Cornet NQ
- e018 Diva Server BRI-2M 2.0 PCI
- 1133 1800 Diva Server V-BRI-2
- 1133 e018 Diva Server BRI-2M 2.0 PCI
- 8001 0014 Diva Server BRI-2M 2.0 PCI Cornet NQ
- e019 Diva Server Voice PRI Rev 2
- 1133 e019 Diva Server Voice PRI 2.0 PCI
- 8001 0014 Diva Server Voice PRI 2.0 PCI Cornet NQ
- e01a Diva Server 2FX
- e01b Diva Server Voice BRI-2M 2.0 PCI
- 1133 e01b Diva Server Voice BRI-2M 2.0 PCI
- 8001 0014 Diva Server Voice BRI-2M 2.0 PCI Cornet NQ
- e01c Diva Server PRI Rev 3
- 1133 1c01 Diva Server PRI/E1/T1-8
- 1133 1c02 Diva Server PRI/T1-24
- 1133 1c03 Diva Server PRI/E1-30
- 1133 1c04 Diva Server PRI/E1/T1
- 1133 1c05 Diva Server V-PRI/T1-24
- 1133 1c06 Diva Server V-PRI/E1-30
- 1133 1c07 Diva Server PRI/E1/T1-8 Cornet NQ
- 1133 1c08 Diva Server PRI/T1-24 Cornet NQ
- 1133 1c09 Diva Server PRI/E1-30 Cornet NQ
- 1133 1c0a Diva Server PRI/E1/T1 Cornet NQ
- 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ
- 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ
- e01e Diva Server 2PRI
- 1133 1e00 Diva Server V-2PRI/E1-60
- 1133 1e01 Diva Server V-2PRI/T1-48
- 1133 1e02 Diva Server 2PRI/E1-60
- 1133 1e03 Diva Server 2PRI/T1-48
- e020 Diva Server 4PRI
- 1133 2000 Diva Server V-4PRI/E1-120
- 1133 2001 Diva Server V-4PRI/T1-96
- 1133 2002 Diva Server 4PRI/E1-120
- 1133 2003 Diva Server 4PRI/T1-96
- e024 Diva Server Analog-4P
- 1133 2400 Diva Server V-Analog-4P
- 1133 e024 Diva Server Analog-4P
- e028 Diva Server Analog-8P
- 1133 2800 Diva Server V-Analog-8P
- 1133 e028 Diva Server Analog-8P
-1134 Mercury Computer Systems
- 0001 Raceway Bridge
- 0002 Dual PCI to RapidIO Bridge
-1135 Fuji Xerox Co Ltd
- 0001 Printer controller
-1136 Momentum Data Systems
-1137 Cisco Systems Inc
-1138 Ziatech Corporation
- 8905 8905 [STD 32 Bridge]
-1139 Dynamic Pictures, Inc
- 0001 VGA Compatable 3D Graphics
-113a FWB Inc
-113b Network Computing Devices
-113c Cyclone Microsystems, Inc.
- 0000 PCI-9060 i960 Bridge
- 0001 PCI-SDK [PCI i960 Evaluation Platform]
- 0911 PCI-911 [i960Jx-based Intelligent I/O Controller]
- 0912 PCI-912 [i960CF-based Intelligent I/O Controller]
- 0913 PCI-913
- 0914 PCI-914 [I/O Controller w/ secondary PCI bus]
-113d Leading Edge Products Inc
-113e Sanyo Electric Co - Computer Engineering Dept
-113f Equinox Systems, Inc.
- 0808 SST-64P Adapter
- 1010 SST-128P Adapter
- 80c0 SST-16P DB Adapter
- 80c4 SST-16P RJ Adapter
- 80c8 SST-16P Adapter
- 8888 SST-4P Adapter
- 9090 SST-8P Adapter
-1140 Intervoice Inc
-1141 Crest Microsystem Inc
-1142 Alliance Semiconductor Corporation
- 3210 AP6410
- 6422 ProVideo 6422
- 6424 ProVideo 6424
- 6425 ProMotion AT25
- 643d ProMotion AT3D
-1143 NetPower, Inc
-1144 Cincinnati Milacron
- 0001 Noservo controller
-1145 Workbit Corporation
- 8007 NinjaSCSI-32 Workbit
- f007 NinjaSCSI-32 KME
- f010 NinjaSCSI-32 Workbit
- f012 NinjaSCSI-32 Logitec
- f013 NinjaSCSI-32 Logitec
- f015 NinjaSCSI-32 Melco
-1146 Force Computers
-1147 Interface Corp
-# Formerly (Schneider & Koch)
-1148 SysKonnect
- 4000 FDDI Adapter
- 0e11 b03b Netelligent 100 FDDI DAS Fibre SC
- 0e11 b03c Netelligent 100 FDDI SAS Fibre SC
- 0e11 b03d Netelligent 100 FDDI DAS UTP
- 0e11 b03e Netelligent 100 FDDI SAS UTP
- 0e11 b03f Netelligent 100 FDDI SAS Fibre MIC
- 1148 5521 FDDI SK-5521 (SK-NET FDDI-UP)
- 1148 5522 FDDI SK-5522 (SK-NET FDDI-UP DAS)
- 1148 5541 FDDI SK-5541 (SK-NET FDDI-FP)
- 1148 5543 FDDI SK-5543 (SK-NET FDDI-LP)
- 1148 5544 FDDI SK-5544 (SK-NET FDDI-LP DAS)
- 1148 5821 FDDI SK-5821 (SK-NET FDDI-UP64)
- 1148 5822 FDDI SK-5822 (SK-NET FDDI-UP64 DAS)
- 1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64)
- 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64)
- 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
- 4200 Token Ring adapter
- 4300 SK-98xx Gigabit Ethernet Server Adapter
- 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
- 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
- 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
- 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
- 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
- 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
- 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
- 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
- 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
- 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
- 1259 2970 AT-2970SX Gigabit Ethernet Adapter
- 1259 2971 AT-2970LX Gigabit Ethernet Adapter
- 1259 2972 AT-2970TX Gigabit Ethernet Adapter
- 1259 2973 AT-2971SX Gigabit Ethernet Adapter
- 1259 2974 AT-2971T Gigabit Ethernet Adapter
- 1259 2975 AT-2970SX/2SC Gigabit Ethernet Adapter
- 1259 2976 AT-2970LX/2SC Gigabit Ethernet Adapter
- 1259 2977 AT-2970TX/2TX Gigabit Ethernet Adapter
- 4320 SK-98xx V2.0 Gigabit Ethernet Adapter
- 1148 0121 Marvell RDK-8001 Adapter
- 1148 0221 Marvell RDK-8002 Adapter
- 1148 0321 Marvell RDK-8003 Adapter
- 1148 0421 Marvell RDK-8004 Adapter
- 1148 0621 Marvell RDK-8006 Adapter
- 1148 0721 Marvell RDK-8007 Adapter
- 1148 0821 Marvell RDK-8008 Adapter
- 1148 0921 Marvell RDK-8009 Adapter
- 1148 1121 Marvell RDK-8011 Adapter
- 1148 1221 Marvell RDK-8012 Adapter
- 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter
- 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
- 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
- 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5051 SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
- 1148 9521 SK-9521 10/100/1000Base-T Adapter
- 4400 SK-9Dxx Gigabit Ethernet Adapter
- 4500 SK-9Mxx Gigabit Ethernet Adapter
- 9000 SK-9Sxx Gigabit Ethernet Server Adapter PCI-X
- 9843 [Fujitsu] Gigabit Ethernet
- 9e00 SK-9Exx 10/100/1000Base-T Adapter
- 1148 2100 SK-9E21 Server Adapter
- 1148 21d0 SK-9E21D 10/100/1000Base-T Adapter
- 1148 2200 SK-9E22 Server Adapter
- 1148 8100 SK-9E81 Server Adapter
- 1148 8200 SK-9E82 Server Adapter
- 1148 9100 SK-9E91 Server Adapter
- 1148 9200 SK-9E92 Server Adapter
-1149 Win System Corporation
-114a VMIC
- 5579 VMIPCI-5579 (Reflective Memory Card)
- 5587 VMIPCI-5587 (Reflective Memory Card)
- 6504 VMIC PCI 7755 FPGA
- 7587 VMIVME-7587
-114b Canopus Co., Ltd
-114c Annabooks
-114d IC Corporation
-114e Nikon Systems Inc
-114f Digi International
- 0002 AccelePort EPC
- 0003 RightSwitch SE-6
- 0004 AccelePort Xem
- 0005 AccelePort Xr
- 0006 AccelePort Xr,C/X
- 0009 AccelePort Xr/J
- 000a AccelePort EPC/J
- 000c DataFirePRIme T1 (1-port)
- 000d SyncPort 2-Port (x.25/FR)
- 0011 AccelePort 8r EIA-232 (IBM)
- 0012 AccelePort 8r EIA-422
- 0013 AccelePort Xr
- 0014 AccelePort 8r EIA-422
- 0015 AccelePort Xem
- 0016 AccelePort EPC/X
- 0017 AccelePort C/X
- 001a DataFirePRIme E1 (1-port)
- 001b AccelePort C/X (IBM)
- 001d DataFire RAS T1/E1/PRI
- 114f 0050 DataFire RAS E1 Adapter
- 114f 0051 DataFire RAS Dual E1 Adapter
- 114f 0052 DataFire RAS T1 Adapter
- 114f 0053 DataFire RAS Dual T1 Adapter
- 0023 AccelePort RAS
- 0024 DataFire RAS B4 ST/U
- 114f 0030 DataFire RAS BRI U Adapter
- 114f 0031 DataFire RAS BRI S/T Adapter
- 0026 AccelePort 4r 920
- 0027 AccelePort Xr 920
- 0028 ClassicBoard 4
- 0029 ClassicBoard 8
- 0034 AccelePort 2r 920
- 0035 DataFire DSP T1/E1/PRI cPCI
- 0040 AccelePort Xp
- 0042 AccelePort 2p
- 0043 AccelePort 4p
- 0044 AccelePort 8p
- 0045 AccelePort 16p
- 004e AccelePort 32p
- 0070 Datafire Micro V IOM2 (Europe)
- 0071 Datafire Micro V (Europe)
- 0072 Datafire Micro V IOM2 (North America)
- 0073 Datafire Micro V (North America)
- 00b0 Digi Neo 4
- 00b1 Digi Neo 8
- 00c8 Digi Neo 2 DB9
- 00c9 Digi Neo 2 DB9 PRI
- 00ca Digi Neo 2 RJ45
- 00cb Digi Neo 2 RJ45 PRI
- 00d0 ClassicBoard 4 422
- 00d1 ClassicBoard 8 422
- 6001 Avanstar
-1150 Thinking Machines Corp
-1151 JAE Electronics Inc.
-1152 Megatek
-1153 Land Win Electronic Corp
-1154 Melco Inc
-1155 Pine Technology Ltd
-1156 Periscope Engineering
-1157 Avsys Corporation
-1158 Voarx R & D Inc
- 3011 Tokenet/vg 1001/10m anylan
- 9050 Lanfleet/Truevalue
- 9051 Lanfleet/Truevalue
-1159 Mutech Corp
- 0001 MV-1000
-115a Harlequin Ltd
-115b Parallax Graphics
-115c Photron Ltd.
-115d Xircom
- 0003 Cardbus Ethernet 10/100
- 1014 0181 10/100 EtherJet Cardbus Adapter
- 1014 1181 10/100 EtherJet Cardbus Adapter
- 1014 8181 10/100 EtherJet Cardbus Adapter
- 1014 9181 10/100 EtherJet Cardbus Adapter
- 115d 0181 Cardbus Ethernet 10/100
- 115d 1181 Cardbus Ethernet 10/100
- 1179 0181 Cardbus Ethernet 10/100
- 8086 8181 EtherExpress PRO/100 Mobile CardBus 32 Adapter
- 8086 9181 EtherExpress PRO/100 Mobile CardBus 32 Adapter
- 0005 Cardbus Ethernet 10/100
- 1014 0182 10/100 EtherJet Cardbus Adapter
- 1014 1182 10/100 EtherJet Cardbus Adapter
- 115d 0182 Cardbus Ethernet 10/100
- 115d 1182 Cardbus Ethernet 10/100
- 0007 Cardbus Ethernet 10/100
- 1014 0182 10/100 EtherJet Cardbus Adapter
- 1014 1182 10/100 EtherJet Cardbus Adapter
- 115d 0182 Cardbus Ethernet 10/100
- 115d 1182 Cardbus Ethernet 10/100
- 000b Cardbus Ethernet 10/100
- 1014 0183 10/100 EtherJet Cardbus Adapter
- 115d 0183 Cardbus Ethernet 10/100
- 000c Mini-PCI V.90 56k Modem
- 000f Cardbus Ethernet 10/100
- 1014 0183 10/100 EtherJet Cardbus Adapter
- 115d 0183 Cardbus Ethernet 10/100
- 00d4 Mini-PCI K56Flex Modem
- 0101 Cardbus 56k modem
- 115d 1081 Cardbus 56k Modem
- 0103 Cardbus Ethernet + 56k Modem
- 1014 9181 Cardbus 56k Modem
- 1115 1181 Cardbus Ethernet 100 + 56k Modem
- 115d 1181 CBEM56G-100 Ethernet + 56k Modem
- 8086 9181 PRO/100 LAN + Modem56 CardBus
-115e Peer Protocols Inc
-115f Maxtor Corporation
-1160 Megasoft Inc
-1161 PFU Limited
-1162 OA Laboratory Co Ltd
-1163 Rendition
- 0001 Verite 1000
- 2000 Verite V2000/V2100/V2200
- 1092 2000 Stealth II S220
-1164 Advanced Peripherals Technologies
-1165 Imagraph Corporation
- 0001 Motion TPEG Recorder/Player with audio
-1166 ServerWorks
- 0000 CMIC-LE
- 0005 CNB20-LE Host Bridge
- 0006 CNB20HE Host Bridge
- 0007 CNB20-LE Host Bridge
- 0008 CNB20HE Host Bridge
- 0009 CNB20LE Host Bridge
- 0010 CIOB30
- 0011 CMIC-HE
- 0012 CMIC-WS Host Bridge (GC-LE chipset)
- 0013 CNB20-HE Host Bridge
- 0014 CMIC-LE Host Bridge (GC-LE chipset)
- 0015 CMIC-GC Host Bridge
- 0016 CMIC-GC Host Bridge
- 0017 GCNB-LE Host Bridge
- 0101 CIOB-X2 PCI-X I/O Bridge
- 0110 CIOB-E I/O Bridge with Gigabit Ethernet
- 0200 OSB4 South Bridge
- 0201 CSB5 South Bridge
- 4c53 1080 CT8 mainboard
- 0203 CSB6 South Bridge
- 0211 OSB4 IDE Controller
- 0212 CSB5 IDE Controller
- 4c53 1080 CT8 mainboard
- 0213 CSB6 RAID/IDE Controller
- 0217 CSB6 IDE Controller
- 0220 OSB4/CSB5 OHCI USB Controller
- 4c53 1080 CT8 mainboard
- 0221 CSB6 OHCI USB Controller
- 0225 CSB5 LPC bridge
-# cancelled
- 4c53 1080 CT8 mainboard
- 0227 GCLE-2 Host Bridge
- 0230 CSB5 LPC bridge
- 4c53 1080 CT8 mainboard
- 0240 K2 SATA
- 0241 K2 SATA
- 0242 K2 SATA
-1167 Mutoh Industries Inc
-1168 Thine Electronics Inc
-1169 Centre for Development of Advanced Computing
-116a Polaris Communications
- 6100 Bus/Tag Channel
- 6800 Escon Channel
- 7100 Bus/Tag Channel
- 7800 Escon Channel
-116b Connectware Inc
-116c Intelligent Resources Integrated Systems
-116d Martin-Marietta
-116e Electronics for Imaging
-116f Workstation Technology
-1170 Inventec Corporation
-1171 Loughborough Sound Images Plc
-1172 Altera Corporation
-1173 Adobe Systems, Inc
-1174 Bridgeport Machines
-1175 Mitron Computer Inc.
-1176 SBE Incorporated
-1177 Silicon Engineering
-1178 Alfa, Inc.
- afa1 Fast Ethernet Adapter
-1179 Toshiba America Info Systems
- 0103 EX-IDE Type-B
- 0404 DVD Decoder card
- 0406 Tecra Video Capture device
- 0407 DVD Decoder card (Version 2)
- 0601 CPU to PCI bridge
- 0603 ToPIC95 PCI to CardBus Bridge for Notebooks
- 060a ToPIC95
- 060f ToPIC97
- 0617 ToPIC100 PCI to Cardbus Bridge with ZV Support
- 0618 CPU to PCI and PCI to ISA bridge
-# Claimed to be Lucent DSP1645 [Mars], but that's apparently incorrect. Does anyone know the correct ID?
- 0701 FIR Port
- 0804 TC6371AF SmartMedia Controller
- 0805 SD TypA Controller
- 0d01 FIR Port Type-DO
- 1179 0001 FIR Port Type-DO
-117a A-Trend Technology
-117b L G Electronics, Inc.
-117c Atto Technology
-117d Becton & Dickinson
-117e T/R Systems
-117f Integrated Circuit Systems
-1180 Ricoh Co Ltd
- 0465 RL5c465
- 0466 RL5c466
- 0475 RL5c475
- 144d c006 vpr Matrix 170B4 CardBus bridge
- 0476 RL5c476 II
- 1014 0185 ThinkPad A/T/X Series
- 104d 80df Vaio PCG-FX403
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 14ef 0220 PCD-RP-220S
- 0477 RL5c477
- 0478 RL5c478
- 1014 0184 ThinkPad A30p (2653-64G)
- 0522 R5C522 IEEE 1394 Controller
- 1014 01cf ThinkPad A30p (2653-64G)
- 0551 R5C551 IEEE 1394 Controller
- 144d c006 vpr Matrix 170B4
- 0552 R5C552 IEEE 1394 Controller
- 1014 0511 ThinkPad A/T/X Series
- 0576 R5C576 SD Bus Host Adapter
- 0592 R5C592 Memory Stick Bus Host Adapter
-1181 Telmatics International
-1183 Fujikura Ltd
-1184 Forks Inc
-1185 Dataworld International Ltd
-1186 D-Link System Inc
- 0100 DC21041
- 1002 DL10050 Sundance Ethernet
- 1186 1002 DFE-550TX
- 1186 1012 DFE-580TX
- 1025 AirPlus Xtreme G DWL-G650 Adapter
- 1026 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 1043 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 1300 RTL8139 Ethernet
- 1186 1300 DFE-538TX 10/100 Ethernet Adapter
- 1186 1301 DFE-530TX+ 10/100 Ethernet Adapter
- 1340 DFE-690TXD CardBus PC Card
- 1541 DFE-680TXD CardBus PC Card
- 1561 DRP-32TXD Cardbus PC Card
- 2027 AirPlus Xtreme G DWL-G520 Adapter
- 3203 AirPlus Xtreme G DWL-G520 Adapter
- 3300 DWL-510 2.4GHz Wireless PCI Adapter
- 3a03 AirPro DWL-A650 Wireless Cardbus Adapter(rev.B)
- 3a04 AirPro DWL-AB650 Multimode Wireless Cardbus Adapter
- 3a05 AirPro DWL-AB520 Multimode Wireless PCI Adapter
- 3a07 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 3a08 AirXpert DWL-AG520 Wireless PCI Adapter
- 3a10 AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B)
- 3a11 AirXpert DWL-AG520 Wireless PCI Adapter(rev.B)
- 3a12 AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)
- 3a13 AirPlus DWL-G520 Wireless PCI Adapter(rev.B)
- 3a14 AirPremier DWL-AG530 Wireless PCI Adapter
- 3a63 AirXpert DWL-AG660 Wireless Cardbus Adapter
- 3b05 DWL-G650+ CardBus PC Card
- 4000 DL2000-based Gigabit Ethernet
- 4300 DGE-528T Gigabit Ethernet Adapter
- 4c00 Gigabit Ethernet Adapter
- 1186 4c00 DGE-530T Gigabit Ethernet Adapter
- 8400 D-Link DWL-650+ CardBus PC Card
-1187 Advanced Technology Laboratories, Inc.
-1188 Shima Seiki Manufacturing Ltd.
-1189 Matsushita Electronics Co Ltd
-118a Hilevel Technology
-118b Hypertec Pty Limited
-118c Corollary, Inc
- 0014 PCIB [C-bus II to PCI bus host bridge chip]
- 1117 Intel 8-way XEON Profusion Chipset [Cache Coherency Filter]
-118d BitFlow Inc
- 0001 Raptor-PCI framegrabber
- 0012 Model 12 Road Runner Frame Grabber
- 0014 Model 14 Road Runner Frame Grabber
- 0024 Model 24 Road Runner Frame Grabber
- 0044 Model 44 Road Runner Frame Grabber
- 0112 Model 12 Road Runner Frame Grabber
- 0114 Model 14 Road Runner Frame Grabber
- 0124 Model 24 Road Runner Frame Grabber
- 0144 Model 44 Road Runner Frame Grabber
- 0212 Model 12 Road Runner Frame Grabber
- 0214 Model 14 Road Runner Frame Grabber
- 0224 Model 24 Road Runner Frame Grabber
- 0244 Model 44 Road Runner Frame Grabber
- 0312 Model 12 Road Runner Frame Grabber
- 0314 Model 14 Road Runner Frame Grabber
- 0324 Model 24 Road Runner Frame Grabber
- 0344 Model 44 Road Runner Frame Grabber
-118e Hermstedt GmbH
-118f Green Logic
-1190 Tripace
- c731 TP-910/920/940 PCI Ultra(Wide) SCSI Adapter
-1191 Artop Electronic Corp
- 0003 SCSI Cache Host Adapter
- 0004 ATP8400
- 0005 ATP850UF
- 0006 ATP860 NO-BIOS
- 0007 ATP860
- 0008 ATP865 NO-ROM
- 0009 ATP865
- 8002 AEC6710 SCSI-2 Host Adapter
- 8010 AEC6712UW SCSI
- 8020 AEC6712U SCSI
- 8030 AEC6712S SCSI
- 8040 AEC6712D SCSI
- 8050 AEC6712SUW SCSI
- 8060 AEC6712 SCSI
- 8080 AEC67160 SCSI
- 8081 AEC67160S SCSI
- 808a AEC67162 2-ch. LVD SCSI
-1192 Densan Company Ltd
-1193 Zeitnet Inc.
- 0001 1221
- 0002 1225
-1194 Toucan Technology
-1195 Ratoc System Inc
-1196 Hytec Electronics Ltd
-1197 Gage Applied Sciences, Inc.
- 010c CompuScope 82G 8bit 2GS/s Analog Input Card
-1198 Lambda Systems Inc
-1199 Attachmate Corporation
-119a Mind Share, Inc.
-119b Omega Micro Inc.
- 1221 82C092G
-119c Information Technology Inst.
-119d Bug, Inc. Sapporo Japan
-119e Fujitsu Microelectronics Ltd.
- 0001 FireStream 155
- 0003 FireStream 50
-119f Bull HN Information Systems
-11a0 Convex Computer Corporation
-11a1 Hamamatsu Photonics K.K.
-11a2 Sierra Research and Technology
-11a3 Deuretzbacher GmbH & Co. Eng. KG
-11a4 Barco Graphics NV
-11a5 Microunity Systems Eng. Inc
-11a6 Pure Data Ltd.
-11a7 Power Computing Corp.
-11a8 Systech Corp.
-11a9 InnoSys Inc.
- 4240 AMCC S933Q Intelligent Serial Card
-11aa Actel
-# Formerly Galileo Technology, Inc.
-11ab Marvell Technology Group Ltd.
- 0146 GT-64010/64010A System Controller
- 138f W8300 802.11 Adapter (rev 07)
- 1fa6 Marvell W8300 802.11 Adapter
- 1fa7 88W8310 and 88W8000G [Libertas] 802.11g client chipset
- 4320 Gigabit Ethernet Controller
- 1019 0f38 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
- 1019 8001 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
- 1043 173c Marvell 88E8001 Gigabit Ethernet Controller (Asus)
- 1043 811a Marvell 88E8001 Gigabit Ethernet Controller (Asus)
- 105b 0c19 Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)
- 10b8 b452 SMC EZ Card 1000 (SMC9452TXV.2)
- 11ab 0121 Marvell RDK-8001
- 11ab 0321 Marvell RDK-8003
- 11ab 1021 Marvell RDK-8010
- 11ab 5021 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)
- 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)
- 1458 e000 Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)
- 147b 1406 Marvell 88E8001 Gigabit Ethernet Controller (Abit)
- 15d4 0047 Marvell 88E8001 Gigabit Ethernet Controller (Iwill)
- 1695 9025 Marvell 88E8001 Gigabit Ethernet Controller (Epox)
- 17f2 1c03 Marvell 88E8001 Gigabit Ethernet Controller (Albatron)
- 270f 2803 Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)
- 4350 Fast Ethernet Controller
- 1179 0001 Marvell 88E8035 Fast Ethernet Controller (Toshiba)
- 11ab 3521 Marvell RDK-8035
- 1854 000d Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 000e Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 000f Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0011 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0012 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0016 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0017 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0018 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0019 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 001c Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 001e Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0020 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 4351 Fast Ethernet Controller
- 107b 4009 Marvell 88E8036 Fast Ethernet Controller (Wistron)
- 10f7 8338 Marvell 88E8036 Fast Ethernet Controller (Panasonic)
- 1179 0001 Marvell 88E8036 Fast Ethernet Controller (Toshiba)
- 1179 ff00 Marvell 88E8036 Fast Ethernet Controller (Compal)
- 1179 ff10 Marvell 88E8036 Fast Ethernet Controller (Inventec)
- 11ab 3621 Marvell RDK-8036
- 13d1 ac12 Abocom EFE3K - 10/100 Ethernet Expresscard
- 161f 203d Marvell 88E8036 Fast Ethernet Controller (Arima)
- 1854 000d Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 000e Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 000f Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0011 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0012 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0016 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0017 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0018 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0019 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 001c Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 001e Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0020 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 4360 Gigabit Ethernet Controller
- 1043 8134 Marvell 88E8052 Gigabit Ethernet Controller (Asus)
- 107b 4009 Marvell 88E8052 Gigabit Ethernet Controller (Wistron)
- 11ab 5221 Marvell RDK-8052
- 1458 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
- 1462 052c Marvell 88E8052 Gigabit Ethernet Controller (MSI)
- 1849 8052 Marvell 88E8052 Gigabit Ethernet Controller (ASRock)
- 1940 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
- a0a0 0509 Marvell 88E8052 Gigabit Ethernet Controller (Aopen)
- 4361 Gigabit Ethernet Controller
- 107b 3015 Marvell 88E8050 Gigabit Ethernet Controller (Gateway)
- 11ab 5021 Marvell 88E8050 Gigabit Ethernet Controller (Intel)
- 8086 3063 D925XCVLK mainboard
- 4362 Gigabit Ethernet Controller
- 103c 2a0d Marvell 88E8053 Gigabit Ethernet Controller (Asus)
- 1043 8142 Marvell 88E8053 Gigabit Ethernet Controller (Asus)
- 109f 3197 Marvell 88E8053 Gigabit Ethernet Controller (Trigem)
- 10f7 8338 Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)
- 10fd a430 Marvell 88E8053 Gigabit Ethernet Controller (SOYO)
- 1179 0001 Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)
- 1179 ff00 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
- 1179 ff10 Marvell 88E8053 Gigabit Ethernet Controller (Inventec)
- 11ab 5321 Marvell RDK-8053
- 1297 c240 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c241 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c242 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c243 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c244 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 13d1 ac11 Abocom EGE5K - Giga Ethernet Expresscard
- 1458 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
- 1462 058c Marvell 88E8053 Gigabit Ethernet Controller (MSI)
- 14c0 0012 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
- 1558 04a0 Marvell 88E8053 Gigabit Ethernet Controller (Clevo)
- 15bd 1003 Marvell 88E8053 Gigabit Ethernet Controller (DFI)
- 161f 203c Marvell 88E8053 Gigabit Ethernet Controller (Arima)
- 161f 203d Marvell 88E8053 Gigabit Ethernet Controller (Arima)
- 1695 9029 Marvell 88E8053 Gigabit Ethernet Controller (Epox)
- 17f2 2c08 Marvell 88E8053 Gigabit Ethernet Controller (Albatron)
- 17ff 0585 Marvell 88E8053 Gigabit Ethernet Controller (Quanta)
- 1849 8053 Marvell 88E8053 Gigabit Ethernet Controller (ASRock)
- 1854 000b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 000c Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0010 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0013 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0014 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0015 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001a Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001d Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001f Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0021 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0022 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1940 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
- 270f 2801 Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)
- a0a0 0506 Marvell 88E8053 Gigabit Ethernet Controller (Aopen)
- 4611 GT-64115 System Controller
- 4620 GT-64120/64120A/64121A System Controller
- 4801 GT-48001
- 5005 Belkin F5D5005 Gigabit Desktop Network PCI Card
- 5040 MV88SX5040 4-port SATA I PCI-X Controller
- 5041 MV88SX5041 4-port SATA I PCI-X Controller
- 5080 MV88SX5080 8-port SATA I PCI-X Controller
- 5081 MV88SX5081 8-port SATA I PCI-X Controller
- 6041 MV88SX6041 4-port SATA II PCI-X Controller
- 6081 MV88SX6081 8-port SATA II PCI-X Controller
- 6460 MV64360/64361/64362 System Controller
- f003 GT-64010 Primary Image Piranha Image Generator
-11ac Canon Information Systems Research Aust.
-11ad Lite-On Communications Inc
- 0002 LNE100TX
- 11ad 0002 LNE100TX
- 11ad 0003 LNE100TX
- 11ad f003 LNE100TX
- 11ad ffff LNE100TX
- 1385 f004 FA310TX
- c115 LNE100TX [Linksys EtherFast 10/100]
- 11ad c001 LNE100TX [ver 2.0]
-11ae Aztech System Ltd
-11af Avid Technology Inc.
- 0001 [Cinema]
-11b0 V3 Semiconductor Inc.
- 0002 V300PSC
- 0292 V292PBC [Am29030/40 Bridge]
- 0960 V96xPBC
- c960 V96DPC
-11b1 Apricot Computers
-11b2 Eastman Kodak
-11b3 Barr Systems Inc.
-11b4 Leitch Technology International
-11b5 Radstone Technology Plc
-11b6 United Video Corp
-11b7 Motorola
-11b8 XPoint Technologies, Inc
- 0001 Quad PeerMaster
-11b9 Pathlight Technology Inc.
- c0ed SSA Controller
-11ba Videotron Corp
-11bb Pyramid Technology
-11bc Network Peripherals Inc
- 0001 NP-PCI
-11bd Pinnacle Systems Inc.
-11be International Microcircuits Inc
-11bf Astrodesign, Inc.
-11c0 Hewlett Packard
-11c1 Agere Systems (former Lucent Microelectronics)
- 0440 56k WinModem
- 1033 8015 LT WinModem 56k Data+Fax+Voice+Dsvd
- 1033 8047 LT WinModem 56k Data+Fax+Voice+Dsvd
- 1033 804f LT WinModem 56k Data+Fax+Voice+Dsvd
- 10cf 102c LB LT Modem V.90 56k
- 10cf 104a BIBLO LT Modem 56k
- 10cf 105f LB2 LT Modem V.90 56k
- 1179 0001 Internal V.90 Modem
- 11c1 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 122d 4101 MDP7800-U Modem
- 122d 4102 MDP7800SP-U Modem
- 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0441 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0450 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 f100 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 f101 LT WinModem 56k Data+Fax+Voice+Dsvd
- 144d 2101 LT56PV Modem
- 149f 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 0441 56k WinModem
- 1033 804d LT WinModem 56k Data+Fax
- 1033 8065 LT WinModem 56k Data+Fax
- 1092 0440 Supra 56i
- 1179 0001 Internal V.90 Modem
- 11c1 0440 LT WinModem 56k Data+Fax
- 11c1 0441 LT WinModem 56k Data+Fax
- 122d 4100 MDP7800-U Modem
- 13e0 0040 LT WinModem 56k Data+Fax
- 13e0 0100 LT WinModem 56k Data+Fax
- 13e0 0410 LT WinModem 56k Data+Fax
- 13e0 0420 TelePath Internet 56k WinModem
- 13e0 0440 LT WinModem 56k Data+Fax
- 13e0 0443 LT WinModem 56k Data+Fax
- 13e0 f102 LT WinModem 56k Data+Fax
- 1416 9804 CommWave 56k Modem
- 141d 0440 LT WinModem 56k Data+Fax
- 144f 0441 Lucent 56k V.90 DF Modem
- 144f 0449 Lucent 56k V.90 DF Modem
- 144f 110d Lucent Win Modem
- 1468 0441 Presario 56k V.90 DF Modem
- 1668 0440 Lucent Win Modem
- 0442 56k WinModem
- 11c1 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 11c1 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0412 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13fc 2471 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 144d 2104 LT56PT Modem
- 144f 1104 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 149f 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 1668 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 0443 LT WinModem
- 0444 LT WinModem
- 0445 LT WinModem
- 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card)
- 8086 2204 PRO/100+ MiniPCI on Armada E500
- 0446 LT WinModem
- 0447 LT WinModem
- 0448 WinModem 56k
- 1014 0131 Lucent Win Modem
- 1033 8066 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0030 56k Voice Modem
- 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd
-# Actiontech eth+modem card as used by Dell &c.
- 1668 2400 LT WinModem 56k (MiniPCI Ethernet+Modem)
- 0449 WinModem 56k
- 0e11 b14d 56k V.90 Modem
- 13e0 0020 LT WinModem 56k Data+Fax
- 13e0 0041 TelePath Internet 56k WinModem
- 1436 0440 Lucent Win Modem
- 144f 0449 Lucent 56k V.90 DFi Modem
- 1468 0410 IBM ThinkPad T23 (2647-4MG)
- 1468 0440 Lucent Win Modem
- 1468 0449 Presario 56k V.90 DFi Modem
- 044a F-1156IV WinModem (V90, 56KFlex)
- 10cf 1072 LB Global LT Modem
- 13e0 0012 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0042 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 144f 1005 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 044b LT WinModem
- 044c LT WinModem
- 044d LT WinModem
- 044e LT WinModem
- 044f V90 WildWire Modem
- 0450 LT WinModem
- 1033 80a8 Versa Note Vxi
- 144f 4005 Magnia SG20
- 0451 LT WinModem
- 0452 LT WinModem
- 0453 LT WinModem
- 0454 LT WinModem
- 0455 LT WinModem
- 0456 LT WinModem
- 0457 LT WinModem
- 0458 LT WinModem
- 0459 LT WinModem
- 045a LT WinModem
- 045c LT WinModem
- 0461 V90 WildWire Modem
- 0462 V90 WildWire Modem
- 0480 Venus Modem (V90, 56KFlex)
- 048c V.92 56K WinModem
-# InPorte Home Internal 56k Modem/fax/answering machine/SMS Features
- 048f V.92 56k WinModem
- 5801 USB
- 5802 USS-312 USB Controller
-# 4 port PCI USB Controller made by Agere (formely Lucent)
- 5803 USS-344S USB Controller
- 5811 FW323
- 8086 524c D865PERL mainboard
- dead 0800 FireWire Host Bus Adapter
- ab10 WL60010 Wireless LAN MAC
- ab11 WL60040 Multimode Wireles LAN MAC
- 11c1 ab12 WaveLAN 11abg Cardbus card (Model 1102)
- 11c1 ab13 WaveLAN 11abg MiniPCI card (Model 0512)
- 11c1 ab15 WaveLAN 11abg Cardbus card (Model 1106)
- 11c1 ab16 WaveLAN 11abg MiniPCI card (Model 0516)
- ab20 ORiNOCO PCI Adapter
- ab21 Agere Wireless PCI Adapter
- ab30 Hermes2 Mini-PCI WaveLAN a/b/g
- 14cd 2012 Hermes2 Mini-PCI WaveLAN a/b/g
-11c2 Sand Microelectronics
-11c3 NEC Corporation
-11c4 Document Technologies, Inc
-11c5 Shiva Corporation
-11c6 Dainippon Screen Mfg. Co. Ltd
-11c7 D.C.M. Data Systems
-11c8 Dolphin Interconnect Solutions AS
- 0658 PSB32 SCI-Adapter D31x
- d665 PSB64 SCI-Adapter D32x
- d667 PSB66 SCI-Adapter D33x
-11c9 Magma
- 0010 16-line serial port w/- DMA
- 0011 4-line serial port w/- DMA
-11ca LSI Systems, Inc
-11cb Specialix Research Ltd.
- 2000 PCI_9050
- 11cb 0200 SX
- 11cb b008 I/O8+
- 4000 SUPI_1
- 8000 T225
-11cc Michels & Kleberhoff Computer GmbH
-11cd HAL Computer Systems, Inc.
-11ce Netaccess
-11cf Pioneer Electronic Corporation
-11d0 Lockheed Martin Federal Systems-Manassas
-11d1 Auravision
- 01f7 VxP524
-11d2 Intercom Inc.
-11d3 Trancell Systems Inc
-11d4 Analog Devices
- 1535 Blackfin BF535 processor
- 1805 SM56 PCI modem
- 1889 AD1889 sound chip
-11d5 Ikon Corporation
- 0115 10115
- 0117 10117
-11d6 Tekelec Telecom
-11d7 Trenton Technology, Inc.
-11d8 Image Technologies Development
-11d9 TEC Corporation
-11da Novell
-11db Sega Enterprises Ltd
-11dc Questra Corporation
-11dd Crosfield Electronics Limited
-11de Zoran Corporation
- 6057 ZR36057PQC Video cutting chipset
- 1031 7efe DC10 Plus
- 1031 fc00 MiroVIDEO DC50, Motion JPEG Capture/CODEC Board
- 13ca 4231 JPEG/TV Card
- 6120 ZR36120
- 1328 f001 Cinemaster C DVD Decoder
-11df New Wave PDG
-11e0 Cray Communications A/S
-11e1 GEC Plessey Semi Inc.
-11e2 Samsung Information Systems America
-11e3 Quicklogic Corporation
- 5030 PC Watchdog
-11e4 Second Wave Inc
-11e5 IIX Consulting
-11e6 Mitsui-Zosen System Research
-11e7 Toshiba America, Elec. Company
-11e8 Digital Processing Systems Inc.
-11e9 Highwater Designs Ltd.
-11ea Elsag Bailey
-11eb Formation Inc.
-11ec Coreco Inc
-11ed Mediamatics
-11ee Dome Imaging Systems Inc
-11ef Nicolet Technologies B.V.
-11f0 Compu-Shack
- 4231 FDDI
- 4232 FASTline UTP Quattro
- 4233 FASTline FO
- 4234 FASTline UTP
- 4235 FASTline-II UTP
- 4236 FASTline-II FO
- 4731 GIGAline
-11f1 Symbios Logic Inc
-11f2 Picture Tel Japan K.K.
-11f3 Keithley Metrabyte
-11f4 Kinetic Systems Corporation
- 2915 CAMAC controller
-11f5 Computing Devices International
-11f6 Compex
- 0112 ENet100VG4
- 0113 FreedomLine 100
- 1401 ReadyLink 2000
- 2011 RL100-ATX 10/100
- 11f6 2011 RL100-ATX
- 2201 ReadyLink 100TX (Winbond W89C840)
- 11f6 2011 ReadyLink 100TX
- 9881 RL100TX Fast Ethernet
-11f7 Scientific Atlanta
-11f8 PMC-Sierra Inc.
- 7375 PM7375 [LASAR-155 ATM SAR]
-11f9 I-Cube Inc
-11fa Kasan Electronics Company, Ltd.
-11fb Datel Inc
-11fc Silicon Magic
-11fd High Street Consultants
-11fe Comtrol Corporation
- 0001 RocketPort 32 port w/external I/F
- 0002 RocketPort 8 port w/external I/F
- 0003 RocketPort 16 port w/external I/F
- 0004 RocketPort 4 port w/quad cable
- 0005 RocketPort 8 port w/octa cable
- 0006 RocketPort 8 port w/RJ11 connectors
- 0007 RocketPort 4 port w/RJ11 connectors
- 0008 RocketPort 8 port w/ DB78 SNI (Siemens) connector
- 0009 RocketPort 16 port w/ DB78 SNI (Siemens) connector
- 000a RocketPort Plus 4 port
- 000b RocketPort Plus 8 port
- 000c RocketModem 6 port
- 000d RocketModem 4-port
- 000e RocketPort Plus 2 port RS232
- 000f RocketPort Plus 2 port RS422
- 0801 RocketPort UPCI 32 port w/external I/F
- 0802 RocketPort UPCI 8 port w/external I/F
- 0803 RocketPort UPCI 16 port w/external I/F
- 0805 RocketPort UPCI 8 port w/octa cable
- 080c RocketModem III 8 port
- 080d RocketModem III 4 port
- 0903 RocketPort Compact PCI 16 port w/external I/F
- 8015 RocketPort 4-port UART 16954
-11ff Scion Corporation
- 0003 AG-5
-1200 CSS Corporation
-1201 Vista Controls Corp
-1202 Network General Corp.
- 4300 Gigabit Ethernet Adapter
- 1202 9841 SK-9841 LX
- 1202 9842 SK-9841 LX dual link
- 1202 9843 SK-9843 SX
- 1202 9844 SK-9843 SX dual link
-1203 Bayer Corporation, Agfa Division
-1204 Lattice Semiconductor Corporation
-1205 Array Corporation
-1206 Amdahl Corporation
-1208 Parsytec GmbH
- 4853 HS-Link Device
-1209 SCI Systems Inc
-120a Synaptel
-120b Adaptive Solutions
-120c Technical Corp.
-120d Compression Labs, Inc.
-120e Cyclades Corporation
- 0100 Cyclom-Y below first megabyte
- 0101 Cyclom-Y above first megabyte
- 0102 Cyclom-4Y below first megabyte
- 0103 Cyclom-4Y above first megabyte
- 0104 Cyclom-8Y below first megabyte
- 0105 Cyclom-8Y above first megabyte
- 0200 Cyclades-Z below first megabyte
- 0201 Cyclades-Z above first megabyte
- 0300 PC300/RSV or /X21 (2 ports)
- 0301 PC300/RSV or /X21 (1 port)
- 0310 PC300/TE (2 ports)
- 0311 PC300/TE (1 port)
- 0320 PC300/TE-M (2 ports)
- 0321 PC300/TE-M (1 port)
- 0400 PC400
-120f Essential Communications
- 0001 Roadrunner serial HIPPI
-1210 Hyperparallel Technologies
-1211 Braintech Inc
-1212 Kingston Technology Corp.
-1213 Applied Intelligent Systems, Inc.
-1214 Performance Technologies, Inc.
-1215 Interware Co., Ltd
-1216 Purup Prepress A/S
-1217 O2 Micro, Inc.
- 6729 OZ6729
- 673a OZ6730
- 6832 OZ6832/6833 CardBus Controller
- 6836 OZ6836/6860 CardBus Controller
- 6872 OZ6812 CardBus Controller
- 6925 OZ6922 CardBus Controller
- 6933 OZ6933/711E1 CardBus/SmartCardBus Controller
- 1025 1016 Travelmate 612 TX
- 6972 OZ601/6912/711E0 CardBus/SmartCardBus Controller
- 1014 020c ThinkPad R30
- 1179 0001 Magnia Z310
- 7110 OZ711Mx 4-in-1 MemoryCardBus Accelerator
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 7112 OZ711EC1/M1 SmartCardBus/MemoryCardBus Controller
- 7113 OZ711EC1 SmartCardBus Controller
- 7114 OZ711M1/MC1 4-in-1 MemoryCardBus Controller
- 7134 OZ711MP1/MS1 MemoryCardBus Controller
- 71e2 OZ711E2 SmartCardBus Controller
- 7212 OZ711M2 4-in-1 MemoryCardBus Controller
- 7213 OZ6933E CardBus Controller
- 7223 OZ711M3/MC3 4-in-1 MemoryCardBus Controller
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 7233 OZ711MP3/MS3 4-in-1 MemoryCardBus Controller
-1218 Hybricon Corp.
-1219 First Virtual Corporation
-121a 3Dfx Interactive, Inc.
- 0001 Voodoo
- 0002 Voodoo 2
- 0003 Voodoo Banshee
- 1092 0003 Monster Fusion
- 1092 4000 Monster Fusion
- 1092 4002 Monster Fusion
- 1092 4801 Monster Fusion AGP
- 1092 4803 Monster Fusion AGP
- 1092 8030 Monster Fusion
- 1092 8035 Monster Fusion AGP
- 10b0 0001 Dragon 4000
- 1102 1018 3D Blaster Banshee VE
- 121a 0001 Voodoo Banshee AGP
- 121a 0003 Voodoo Banshee AGP SGRAM
- 121a 0004 Voodoo Banshee
- 139c 0016 Raven
- 139c 0017 Raven
- 14af 0002 Maxi Gamer Phoenix
- 0004 Voodoo Banshee [Velocity 100]
- 0005 Voodoo 3
- 121a 0004 Voodoo3 AGP
- 121a 0030 Voodoo3 AGP
- 121a 0031 Voodoo3 AGP
- 121a 0034 Voodoo3 AGP
- 121a 0036 Voodoo3 2000 PCI
- 121a 0037 Voodoo3 AGP
- 121a 0038 Voodoo3 AGP
- 121a 003a Voodoo3 AGP
- 121a 0044 Voodoo3
- 121a 004b Velocity 100
- 121a 004c Velocity 200
- 121a 004d Voodoo3 AGP
- 121a 004e Voodoo3 AGP
- 121a 0051 Voodoo3 AGP
- 121a 0052 Voodoo3 AGP
- 121a 0060 Voodoo3 3500 TV (NTSC)
- 121a 0061 Voodoo3 3500 TV (PAL)
- 121a 0062 Voodoo3 3500 TV (SECAM)
- 0009 Voodoo 4 / Voodoo 5
- 121a 0003 Voodoo5 PCI 5500
- 121a 0009 Voodoo5 AGP 5500/6000
- 0057 Voodoo 3/3000 [Avenger]
-121b Advanced Telecommunications Modules
-121c Nippon Texaco., Ltd
-121d Lippert Automationstechnik GmbH
-121e CSPI
-121f Arcus Technology, Inc.
-1220 Ariel Corporation
- 1220 AMCC 5933 TMS320C80 DSP/Imaging board
-1221 Contec Co., Ltd
-1222 Ancor Communications, Inc.
-1223 Artesyn Communication Products
- 0003 PM/Link
- 0004 PM/T1
- 0005 PM/E1
- 0008 PM/SLS
- 0009 BajaSpan Resource Target
- 000a BajaSpan Section 0
- 000b BajaSpan Section 1
- 000c BajaSpan Section 2
- 000d BajaSpan Section 3
- 000e PM/PPC
-1224 Interactive Images
-1225 Power I/O, Inc.
-1227 Tech-Source
- 0006 Raptor GFX 8P
-1228 Norsk Elektro Optikk A/S
-1229 Data Kinesis Inc.
-122a Integrated Telecom
-122b LG Industrial Systems Co., Ltd
-122c Sican GmbH
-122d Aztech System Ltd
- 1206 368DSP
- 1400 Trident PCI288-Q3DII (NX)
- 50dc 3328 Audio
- 122d 0001 3328 Audio
- 80da 3328 Audio
- 122d 0001 3328 Audio
-122e Xyratex
-122f Andrew Corporation
-1230 Fishcamp Engineering
-1231 Woodward McCoach, Inc.
-1232 GPT Limited
-1233 Bus-Tech, Inc.
-1234 Technical Corp.
-1235 Risq Modular Systems, Inc.
-1236 Sigma Designs Corporation
- 0000 RealMagic64/GX
- 6401 REALmagic 64/GX (SD 6425)
-1237 Alta Technology Corporation
-1238 Adtran
-1239 3DO Company
-123a Visicom Laboratories, Inc.
-123b Seeq Technology, Inc.
-123c Century Systems, Inc.
-123d Engineering Design Team, Inc.
- 0000 EasyConnect 8/32
- 0002 EasyConnect 8/64
- 0003 EasyIO
-123e Simutech, Inc.
-123f C-Cube Microsystems
- 00e4 MPEG
- 8120 E4?
- 11bd 0006 DV500 E4
- 11bd 000a DV500 E4
- 11bd 000f DV500 E4
- 8888 Cinemaster C 3.0 DVD Decoder
- 1002 0001 Cinemaster C 3.0 DVD Decoder
- 1002 0002 Cinemaster C 3.0 DVD Decoder
- 1328 0001 Cinemaster C 3.0 DVD Decoder
-1240 Marathon Technologies Corp.
-1241 DSC Communications
-# Formerly Jaycor Networks, Inc.
-1242 JNI Corporation
- 1560 JNIC-1560 PCI-X Fibre Channel Controller
- 1242 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter
- 1242 656a FCX-6562 PCI-X Fibre Channel Adapter
- 4643 FCI-1063 Fibre Channel Adapter
- 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter
- 656a FCX-6562 PCI-X Fibre Channel Adapter
-1243 Delphax
-1244 AVM Audiovisuelles MKTG & Computer System GmbH
- 0700 B1 ISDN
- 0800 C4 ISDN
- 0a00 A1 ISDN [Fritz]
- 1244 0a00 FRITZ!Card ISDN Controller
- 0e00 Fritz!PCI v2.0 ISDN
- 1100 C2 ISDN
- 1200 T1 ISDN
- 2700 Fritz!Card DSL SL
- 2900 Fritz!Card DSL v2.0
-1245 A.P.D., S.A.
-1246 Dipix Technologies, Inc.
-1247 Xylon Research, Inc.
-1248 Central Data Corporation
-1249 Samsung Electronics Co., Ltd.
-124a AEG Electrocom GmbH
-124b SBS/Greenspring Modular I/O
- 0040 PCI-40A or cPCI-200 Quad IndustryPack carrier
- 124b 9080 PCI9080 Bridge
-124c Solitron Technologies, Inc.
-124d Stallion Technologies, Inc.
- 0000 EasyConnection 8/32
- 0002 EasyConnection 8/64
- 0003 EasyIO
- 0004 EasyConnection/RA
-124e Cylink
-124f Infortrend Technology, Inc.
- 0041 IFT-2000 Series RAID Controller
-1250 Hitachi Microcomputer System Ltd
-1251 VLSI Solutions Oy
-1253 Guzik Technical Enterprises
-1254 Linear Systems Ltd.
-1255 Optibase Ltd
- 1110 MPEG Forge
- 1210 MPEG Fusion
- 2110 VideoPlex
- 2120 VideoPlex CC
- 2130 VideoQuest
-1256 Perceptive Solutions, Inc.
- 4201 PCI-2220I
- 4401 PCI-2240I
- 5201 PCI-2000
-1257 Vertex Networks, Inc.
-1258 Gilbarco, Inc.
-1259 Allied Telesyn International
- 2560 AT-2560 Fast Ethernet Adapter (i82557B)
- a117 RTL81xx Fast Ethernet
- a120 21x4x DEC-Tulip compatible 10/100 Ethernet
-125a ABB Power Systems
-125b Asix Electronics Corporation
- 1400 ALFA GFC2204 Fast Ethernet
-125c Aurora Technologies, Inc.
- 0101 Saturn 4520P
- 0640 Aries 16000P
-125d ESS Technology
- 0000 ES336H Fax Modem (Early Model)
- 1948 Solo?
- 1968 ES1968 Maestro 2
- 1028 0085 ES1968 Maestro-2 PCI
- 1033 8051 ES1968 Maestro-2 Audiodrive
- 1969 ES1969 Solo-1 Audiodrive
- 1014 0166 ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard
- 125d 8888 Solo-1 Audio Adapter
- 153b 111b Terratec 128i PCI
- 1978 ES1978 Maestro 2E
- 0e11 b112 Armada M700/E500
- 1033 803c ES1978 Maestro-2E Audiodrive
- 1033 8058 ES1978 Maestro-2E Audiodrive
- 1092 4000 Monster Sound MX400
- 1179 0001 ES1978 Maestro-2E Audiodrive
- 1988 ES1988 Allegro-1
- 1092 4100 Sonic Impact S100
- 125d 1988 ESS Allegro-1 Audiodrive
- 1989 ESS Modem
- 125d 1989 ESS Modem
- 1998 ES1983S Maestro-3i PCI Audio Accelerator
- 1028 00b1 Latitude C600
- 1028 00e6 ES1983S Maestro-3i (Dell Inspiron 8100)
- 1999 ES1983S Maestro-3i PCI Modem Accelerator
- 199a ES1983S Maestro-3i PCI Audio Accelerator
- 199b ES1983S Maestro-3i PCI Modem Accelerator
- 2808 ES336H Fax Modem (Later Model)
- 2838 ES2838/2839 SuperLink Modem
- 2898 ES2898 Modem
- 125d 0424 ES56-PI Data Fax Modem
- 125d 0425 ES56T-PI Data Fax Modem
- 125d 0426 ES56V-PI Data Fax Modem
- 125d 0427 VW-PI Data Fax Modem
- 125d 0428 ES56ST-PI Data Fax Modem
- 125d 0429 ES56SV-PI Data Fax Modem
- 147a c001 ES56-PI Data Fax Modem
- 14fe 0428 ES56-PI Data Fax Modem
- 14fe 0429 ES56-PI Data Fax Modem
-125e Specialvideo Engineering SRL
-125f Concurrent Technologies, Inc.
-1260 Intersil Corporation
- 3872 Prism 2.5 Wavelan chipset
- 1468 0202 LAN-Express IEEE 802.11b Wireless LAN
- 3873 Prism 2.5 Wavelan chipset
- 1186 3501 DWL-520 Wireless PCI Adapter
- 1186 3700 DWL-520 Wireless PCI Adapter, Rev E1
- 1385 4105 MA311 802.11b wireless adapter
- 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter
- 16a5 1601 AIR.mate PC-400 PCI Wireless LAN Adapter
- 1737 3874 WMP11 Wireless 802.11b PCI Adapter
- 8086 2513 Wireless 802.11b MiniPCI Adapter
- 3886 ISL3886 [Prism Javelin/Prism Xbow]
- 17cf 0037 Z-Com XG-901 and clones Wireless Adapter
- 3890 Intersil ISL3890 [Prism GT/Prism Duette]
- 10b8 2802 SMC2802W Wireless PCI Adapter
- 10b8 2835 SMC2835W Wireless Cardbus Adapter
- 10b8 a835 SMC2835W V2 Wireless Cardbus Adapter
- 1113 ee03 SMC2802W V2 Wireless PCI Adapter
- 1113 ee08 SMC2835W V3 EU Wireless Cardbus Adapter
- 1186 3202 DWL-G650 A1 Wireless Adapter
- 1259 c104 CG-WLCB54GT Wireless Adapter
- 1385 4800 WG511 Wireless Adapter
- 16a5 1605 ALLNET ALL0271 Wireless PCI Adapter
- 17cf 0014 Z-Com XG-600 and clones Wireless Adapter
- 17cf 0020 Z-Com XG-900 and clones Wireless Adapter
- 8130 HMP8130 NTSC/PAL Video Decoder
- 8131 HMP8131 NTSC/PAL Video Decoder
-1261 Matsushita-Kotobuki Electronics Industries, Ltd.
-1262 ES Computer Company, Ltd.
-1263 Sonic Solutions
-1264 Aval Nagasaki Corporation
-1265 Casio Computer Co., Ltd.
-1266 Microdyne Corporation
- 0001 NE10/100 Adapter (i82557B)
- 1910 NE2000Plus (RT8029) Ethernet Adapter
- 1266 1910 NE2000Plus Ethernet Adapter
-1267 S. A. Telecommunications
- 5352 PCR2101
- 5a4b Telsat Turbo
-1268 Tektronix
-1269 Thomson-CSF/TTM
-126a Lexmark International, Inc.
-126b Adax, Inc.
-126c Northern Telecom
- 1211 10/100BaseTX [RTL81xx]
- 126c 802.11b Wireless Ethernet Adapter
-126d Splash Technology, Inc.
-126e Sumitomo Metal Industries, Ltd.
-126f Silicon Motion, Inc.
- 0501 SM501 VoyagerGX
- 0710 SM710 LynxEM
- 0712 SM712 LynxEM+
- 0720 SM720 Lynx3DM
- 0730 SM731 Cougar3DR
- 0810 SM810 LynxE
- 0811 SM811 LynxE
- 0820 SM820 Lynx3D
- 0910 SM910
-1270 Olympus Optical Co., Ltd.
-1271 GW Instruments
-1272 Telematics International
-1273 Hughes Network Systems
- 0002 DirecPC
-1274 Ensoniq
- 1171 ES1373 [AudioPCI] (also Creative Labs CT5803)
- 1371 ES1371 [AudioPCI-97]
- 0e11 0024 AudioPCI on Motherboard Compaq Deskpro
- 0e11 b1a7 ES1371, ES1373 AudioPCI
- 1033 80ac ES1371, ES1373 AudioPCI
- 1042 1854 Tazer
- 107b 8054 Tabor2
- 1274 1371 Creative Sound Blaster AudioPCI64V, AudioPCI128
- 1462 6470 ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A
- 1462 6560 ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10
- 1462 6630 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 1.0A
- 1462 6631 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 1.0A
- 1462 6632 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 2.0A
- 1462 6633 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 2.0A
- 1462 6820 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00
- 1462 6822 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00A
- 1462 6830 ES1371, ES1373 AudioPCI On Motherboard MS-6183 1.00
- 1462 6880 ES1371, ES1373 AudioPCI On Motherboard MS-6188 1.00
- 1462 6900 ES1371, ES1373 AudioPCI On Motherboard MS-6190 1.00
- 1462 6910 ES1371, ES1373 AudioPCI On Motherboard MS-6191
- 1462 6930 ES1371, ES1373 AudioPCI On Motherboard MS-6193
- 1462 6990 ES1371, ES1373 AudioPCI On Motherboard MS-6199BX 2.0A
- 1462 6991 ES1371, ES1373 AudioPCI On Motherboard MS-6199VIA 2.0A
- 14a4 2077 ES1371, ES1373 AudioPCI On Motherboard KR639
- 14a4 2105 ES1371, ES1373 AudioPCI On Motherboard MR800
- 14a4 2107 ES1371, ES1373 AudioPCI On Motherboard MR801
- 14a4 2172 ES1371, ES1373 AudioPCI On Motherboard DR739
- 1509 9902 ES1371, ES1373 AudioPCI On Motherboard KW11
- 1509 9903 ES1371, ES1373 AudioPCI On Motherboard KW31
- 1509 9904 ES1371, ES1373 AudioPCI On Motherboard KA11
- 1509 9905 ES1371, ES1373 AudioPCI On Motherboard KC13
- 152d 8801 ES1371, ES1373 AudioPCI On Motherboard CP810E
- 152d 8802 ES1371, ES1373 AudioPCI On Motherboard CP810
- 152d 8803 ES1371, ES1373 AudioPCI On Motherboard P3810E
- 152d 8804 ES1371, ES1373 AudioPCI On Motherboard P3810-S
- 152d 8805 ES1371, ES1373 AudioPCI On Motherboard P3820-S
- 270f 2001 ES1371, ES1373 AudioPCI On Motherboard 6CTR
- 270f 2200 ES1371, ES1373 AudioPCI On Motherboard 6WTX
- 270f 3000 ES1371, ES1373 AudioPCI On Motherboard 6WSV
- 270f 3100 ES1371, ES1373 AudioPCI On Motherboard 6WIV2
- 270f 3102 ES1371, ES1373 AudioPCI On Motherboard 6WIV
- 270f 7060 ES1371, ES1373 AudioPCI On Motherboard 6ASA2
- 8086 4249 ES1371, ES1373 AudioPCI On Motherboard BI440ZX
- 8086 424c ES1371, ES1373 AudioPCI On Motherboard BL440ZX
- 8086 425a ES1371, ES1373 AudioPCI On Motherboard BZ440ZX
- 8086 4341 ES1371, ES1373 AudioPCI On Motherboard Cayman
- 8086 4343 ES1371, ES1373 AudioPCI On Motherboard Cape Cod
- 8086 4649 ES1371, ES1373 AudioPCI On Motherboard Fire Island
- 8086 464a ES1371, ES1373 AudioPCI On Motherboard FJ440ZX
- 8086 4d4f ES1371, ES1373 AudioPCI On Motherboard Montreal
- 8086 4f43 ES1371, ES1373 AudioPCI On Motherboard OC440LX
- 8086 5243 ES1371, ES1373 AudioPCI On Motherboard RC440BX
- 8086 5352 ES1371, ES1373 AudioPCI On Motherboard SunRiver
- 8086 5643 ES1371, ES1373 AudioPCI On Motherboard Vancouver
- 8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX
- 5000 ES1370 [AudioPCI]
- 5880 5880 AudioPCI
- 1274 2000 Creative Sound Blaster AudioPCI128
- 1274 2003 Creative SoundBlaster AudioPCI 128
- 1274 5880 Creative Sound Blaster AudioPCI128
- 1274 8001 Sound Blaster 16PCI 4.1ch
- 1458 a000 5880 AudioPCI On Motherboard 6OXET
- 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00
- 270f 2001 5880 AudioPCI On Motherboard 6CTR
- 270f 2200 5880 AudioPCI On Motherboard 6WTX
- 270f 7040 5880 AudioPCI On Motherboard 6ATA4
-1275 Network Appliance Corporation
-1276 Switched Network Technologies, Inc.
-1277 Comstream
-1278 Transtech Parallel Systems Ltd.
- 0701 TPE3/TM3 PowerPC Node
- 0710 TPE5 PowerPC PCI board
-1279 Transmeta Corporation
- 0295 Northbridge
- 0395 LongRun Northbridge
- 0396 SDRAM controller
- 0397 BIOS scratchpad
-127a Rockwell International
- 1002 HCF 56k Data/Fax Modem
- 1092 094c SupraExpress 56i PRO [Diamond SUP2380]
- 122d 4002 HPG / MDP3858-U
- 122d 4005 MDP3858-E
- 122d 4007 MDP3858-A/-NZ
- 122d 4012 MDP3858-SA
- 122d 4017 MDP3858-W
- 122d 4018 MDP3858-W
- 127a 1002 Rockwell 56K D/F HCF Modem
- 1003 HCF 56k Data/Fax Modem
- 0e11 b0bc 229-DF Zephyr
- 0e11 b114 229-DF Cheetah
- 1033 802b 229-DF
- 13df 1003 PCI56RX Modem
- 13e0 0117 IBM
- 13e0 0147 IBM F-1156IV+/R3 Spain V.90 Modem
- 13e0 0197 IBM
- 13e0 01c7 IBM F-1156IV+/R3 WW V.90 Modem
- 13e0 01f7 IBM
- 1436 1003 IBM
- 1436 1103 IBM 5614PM3G V.90 Modem
- 1436 1602 Compaq 229-DF Ducati
- 1004 HCF 56k Data/Fax/Voice Modem
- 1048 1500 MicroLink 56k Modem
- 10cf 1059 Fujitsu 229-DFRT
- 1005 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1005 127a AOpen FM56-P
- 1033 8029 229-DFSV
- 1033 8054 Modem
- 10cf 103c Fujitsu
- 10cf 1055 Fujitsu 229-DFSV
- 10cf 1056 Fujitsu 229-DFSV
- 122d 4003 MDP3858SP-U
- 122d 4006 Packard Bell MDP3858V-E
- 122d 4008 MDP3858SP-A/SP-NZ
- 122d 4009 MDP3858SP-E
- 122d 4010 MDP3858V-U
- 122d 4011 MDP3858SP-SA
- 122d 4013 MDP3858V-A/V-NZ
- 122d 4015 MDP3858SP-W
- 122d 4016 MDP3858V-W
- 122d 4019 MDP3858V-SA
- 13df 1005 PCI56RVP Modem
- 13e0 0187 IBM
- 13e0 01a7 IBM
- 13e0 01b7 IBM DF-1156IV+/R3 Spain V.90 Modem
- 13e0 01d7 IBM DF-1156IV+/R3 WW V.90 Modem
- 1436 1005 IBM
- 1436 1105 IBM
- 1437 1105 IBM 5614PS3G V.90 Modem
- 1022 HCF 56k Modem
- 1436 1303 M3-5614PM3G V.90 Modem
- 1023 HCF 56k Data/Fax Modem
- 122d 4020 Packard Bell MDP3858-WE
- 122d 4023 MDP3858-UE
- 13e0 0247 IBM F-1156IV+/R6 Spain V.90 Modem
- 13e0 0297 IBM
- 13e0 02c7 IBM F-1156IV+/R6 WW V.90 Modem
- 1436 1203 IBM
- 1436 1303 IBM
- 1024 HCF 56k Data/Fax/Voice Modem
- 1025 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 106a Fujitsu 235-DFSV
- 122d 4021 Packard Bell MDP3858V-WE
- 122d 4022 MDP3858SP-WE
- 122d 4024 MDP3858V-UE
- 122d 4025 MDP3858SP-UE
- 1026 HCF 56k PCI Speakerphone Modem
- 1032 HCF 56k Modem
- 1033 HCF 56k Modem
- 1034 HCF 56k Modem
- 1035 HCF 56k PCI Speakerphone Modem
- 1036 HCF 56k Modem
- 1085 HCF 56k Volcano PCI Modem
- 2005 HCF 56k Data/Fax Modem
- 104d 8044 229-DFSV
- 104d 8045 229-DFSV
- 104d 8055 PBE/Aztech 235W-DFSV
- 104d 8056 235-DFSV
- 104d 805a Modem
- 104d 805f Modem
- 104d 8074 Modem
- 2013 HSF 56k Data/Fax Modem
- 1179 0001 Modem
- 1179 ff00 Modem
- 2014 HSF 56k Data/Fax/Voice Modem
- 10cf 1057 Fujitsu Citicorp III
- 122d 4050 MSP3880-U
- 122d 4055 MSP3880-W
- 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 1063 Fujitsu
- 10cf 1064 Fujitsu
- 1468 2015 Fujitsu
- 2016 HSF 56k Data/Fax/Voice/Spkp Modem
- 122d 4051 MSP3880V-W
- 122d 4052 MSP3880SP-W
- 122d 4054 MSP3880V-U
- 122d 4056 MSP3880SP-U
- 122d 4057 MSP3880SP-A
- 4311 Riptide HSF 56k PCI Modem
- 127a 4311 Ring Modular? Riptide HSF RT HP Dom
- 13e0 0210 HP-GVC
- 4320 Riptide PCI Audio Controller
- 1235 4320 Riptide PCI Audio Controller
- 4321 Riptide HCF 56k PCI Modem
- 1235 4321 Hewlett Packard DF
- 1235 4324 Hewlett Packard DF
- 13e0 0210 Hewlett Packard DF
- 144d 2321 Riptide
- 4322 Riptide PCI Game Controller
- 1235 4322 Riptide PCI Game Controller
- 8234 RapidFire 616X ATM155 Adapter
- 108d 0022 RapidFire 616X ATM155 Adapter
- 108d 0027 RapidFire 616X ATM155 Adapter
-127b Pixera Corporation
-127c Crosspoint Solutions, Inc.
-127d Vela Research
-127e Winnov, L.P.
-127f Fujifilm
-1280 Photoscript Group Ltd.
-1281 Yokogawa Electric Corporation
-1282 Davicom Semiconductor, Inc.
- 9009 Ethernet 100/10 MBit
- 9100 21x4x DEC-Tulip compatible 10/100 Ethernet
- 9102 21x4x DEC-Tulip compatible 10/100 Ethernet
- 9132 Ethernet 100/10 MBit
-1283 Integrated Technology Express, Inc.
- 673a IT8330G
- 8212 IT/ITE8212 Dual channel ATA RAID controller (PCI version seems to be IT8212, embedded seems to be ITE8212)
- 1283 0001 IT/ITE8212 Dual channel ATA RAID controller
- 8330 IT8330G
- 8872 IT8874F PCI Dual Serial Port Controller
- 8888 IT8888F PCI to ISA Bridge with SMB
- 8889 IT8889F PCI to ISA Bridge
- e886 IT8330G
-1284 Sahara Networks, Inc.
-1285 Platform Technologies, Inc.
- 0100 AGOGO sound chip (aka ESS Maestro 1)
-1286 Mazet GmbH
-1287 M-Pact, Inc.
- 001e LS220D DVD Decoder
- 001f LS220C DVD Decoder
-1288 Timestep Corporation
-1289 AVC Technology, Inc.
-128a Asante Technologies, Inc.
-128b Transwitch Corporation
-128c Retix Corporation
-128d G2 Networks, Inc.
- 0021 ATM155 Adapter
-128e Hoontech Corporation/Samho Multi Tech Ltd.
- 0008 ST128 WSS/SB
- 0009 ST128 SAM9407
- 000a ST128 Game Port
- 000b ST128 MPU Port
- 000c ST128 Ctrl Port
-128f Tateno Dennou, Inc.
-1290 Sord Computer Corporation
-1291 NCS Computer Italia
-1292 Tritech Microelectronics Inc
-1293 Media Reality Technology
-1294 Rhetorex, Inc.
-1295 Imagenation Corporation
-1296 Kofax Image Products
-1297 Holco Enterprise Co, Ltd/Shuttle Computer
-1298 Spellcaster Telecommunications Inc.
-1299 Knowledge Technology Lab.
-129a VMetro, inc.
- 0615 PBT-615 PCI-X Bus Analyzer
-129b Image Access
-129c Jaycor
-129d Compcore Multimedia, Inc.
-129e Victor Company of Japan, Ltd.
-129f OEC Medical Systems, Inc.
-12a0 Allen-Bradley Company
-12a1 Simpact Associates, Inc.
-12a2 Newgen Systems Corporation
-12a3 Lucent Technologies
- 8105 T8105 H100 Digital Switch
-12a4 NTT Electronics Technology Company
-12a5 Vision Dynamics Ltd.
-12a6 Scalable Networks, Inc.
-12a7 AMO GmbH
-12a8 News Datacom
-12a9 Xiotech Corporation
-12aa SDL Communications, Inc.
-12ab Yuan Yuan Enterprise Co., Ltd.
- 0002 AU8830 [Vortex2] Based Sound Card With A3D Support
- 3000 MPG-200C PCI DVD Decoder Card
-12ac Measurex Corporation
-12ad Multidata GmbH
-12ae Alteon Networks Inc.
- 0001 AceNIC Gigabit Ethernet
- 1014 0104 Gigabit Ethernet-SX PCI Adapter
- 12ae 0001 Gigabit Ethernet-SX (Universal)
- 1410 0104 Gigabit Ethernet-SX PCI Adapter
- 0002 AceNIC Gigabit Ethernet (Copper)
- 10a9 8002 Acenic Gigabit Ethernet
- 12ae 0002 Gigabit Ethernet-T (3C986-T)
- 00fa Farallon PN9100-T Gigabit Ethernet
-12af TDK USA Corp
-12b0 Jorge Scientific Corp
-12b1 GammaLink
-12b2 General Signal Networks
-12b3 Inter-Face Co Ltd
-12b4 FutureTel Inc
-12b5 Granite Systems Inc.
-12b6 Natural Microsystems
-12b7 Cognex Modular Vision Systems Div. - Acumen Inc.
-12b8 Korg
-12b9 3Com Corp, Modem Division (formerly US Robotics)
- 1006 WinModem
- 12b9 005c USR 56k Internal Voice WinModem (Model 3472)
- 12b9 005e USR 56k Internal WinModem (Models 662975)
- 12b9 0062 USR 56k Internal Voice WinModem (Model 662978)
- 12b9 0068 USR 56k Internal Voice WinModem (Model 5690)
- 12b9 007a USR 56k Internal Voice WinModem (Model 662974)
- 12b9 007f USR 56k Internal WinModem (Models 5698, 5699)
- 12b9 0080 USR 56k Internal WinModem (Models 2975, 3528)
- 12b9 0081 USR 56k Internal Voice WinModem (Models 2974, 3529)
- 12b9 0091 USR 56k Internal Voice WinModem (Model 2978)
- 1007 USR 56k Internal WinModem
- 12b9 00a3 USR 56k Internal WinModem (Model 3595)
- 1008 56K FaxModem Model 5610
- 12b9 00a2 USR 56k Internal FAX Modem (Model 2977)
- 12b9 00aa USR 56k Internal Voice Modem (Model 2976)
- 12b9 00ab USR 56k Internal Voice Modem (Model 5609)
- 12b9 00ac USR 56k Internal Voice Modem (Model 3298)
- 12b9 00ad USR 56k Internal FAX Modem (Model 5610)
-12ba BittWare, Inc.
-12bb Nippon Unisoft Corporation
-12bc Array Microsystems
-12bd Computerm Corp.
-12be Anchor Chips Inc.
- 3041 AN3041Q CO-MEM
- 3042 AN3042Q CO-MEM Lite
- 12be 3042 Anchor Chips Lite Evaluation Board
-12bf Fujifilm Microdevices
-12c0 Infimed
-12c1 GMM Research Corp
-12c2 Mentec Limited
-12c3 Holtek Microelectronics Inc
- 0058 PCI NE2K Ethernet
- 5598 PCI NE2K Ethernet
-12c4 Connect Tech Inc
- 0001 Blue HEAT/PCI 8 (RS232/CL/RJ11)
- 0002 Blue HEAT/PCI 4 (RS232)
- 0003 Blue HEAT/PCI 2 (RS232)
- 0004 Blue HEAT/PCI 8 (UNIV, RS485)
- 0005 Blue HEAT/PCI 4+4/6+2 (UNIV, RS232/485)
- 0006 Blue HEAT/PCI 4 (OPTO, RS485)
- 0007 Blue HEAT/PCI 2+2 (RS232/485)
- 0008 Blue HEAT/PCI 2 (OPTO, Tx, RS485)
- 0009 Blue HEAT/PCI 2+6 (RS232/485)
- 000a Blue HEAT/PCI 8 (Tx, RS485)
- 000b Blue HEAT/PCI 4 (Tx, RS485)
- 000c Blue HEAT/PCI 2 (20 MHz, RS485)
- 000d Blue HEAT/PCI 2 PTM
- 0100 NT960/PCI
- 0201 cPCI Titan - 2 Port
- 0202 cPCI Titan - 4 Port
- 0300 CTI PCI UART 2 (RS232)
- 0301 CTI PCI UART 4 (RS232)
- 0302 CTI PCI UART 8 (RS232)
- 0310 CTI PCI UART 1+1 (RS232/485)
- 0311 CTI PCI UART 2+2 (RS232/485)
- 0312 CTI PCI UART 4+4 (RS232/485)
- 0320 CTI PCI UART 2
- 0321 CTI PCI UART 4
- 0322 CTI PCI UART 8
- 0330 CTI PCI UART 2 (RS485)
- 0331 CTI PCI UART 4 (RS485)
- 0332 CTI PCI UART 8 (RS485)
-12c5 Picture Elements Incorporated
- 007e Imaging/Scanning Subsystem Engine
- 007f Imaging/Scanning Subsystem Engine
- 0081 PCIVST [Grayscale Thresholding Engine]
- 0085 Video Simulator/Sender
- 0086 THR2 Multi-scale Thresholder
-12c6 Mitani Corporation
-12c7 Dialogic Corp
-12c8 G Force Co, Ltd
-12c9 Gigi Operations
-12ca Integrated Computing Engines
-12cb Antex Electronics Corporation
-12cc Pluto Technologies International
-12cd Aims Lab
-12ce Netspeed Inc.
-12cf Prophet Systems, Inc.
-12d0 GDE Systems, Inc.
-12d1 PSITech
-12d2 NVidia / SGS Thomson (Joint Venture)
- 0008 NV1
- 0009 DAC64
- 0018 Riva128
- 1048 0c10 VICTORY Erazor
- 107b 8030 STB Velocity 128
- 1092 0350 Viper V330
- 1092 1092 Viper V330
- 10b4 1b1b STB Velocity 128
- 10b4 1b1d STB Velocity 128
- 10b4 1b1e STB Velocity 128, PAL TV-Out
- 10b4 1b20 STB Velocity 128 Sapphire
- 10b4 1b21 STB Velocity 128
- 10b4 1b22 STB Velocity 128 AGP, NTSC TV-Out
- 10b4 1b23 STB Velocity 128 AGP, PAL TV-Out
- 10b4 1b27 STB Velocity 128 DVD
- 10b4 1b88 MVP Pro 128
- 10b4 222a STB Velocity 128 AGP
- 10b4 2230 STB Velocity 128
- 10b4 2232 STB Velocity 128
- 10b4 2235 STB Velocity 128 AGP
- 2a15 54a3 3DVision-SAGP / 3DexPlorer 3000
- 0019 Riva128ZX
- 0020 TNT
- 0028 TNT2
- 0029 UTNT2
- 002c VTNT2
- 00a0 ITNT2
-12d3 Vingmed Sound A/S
-12d4 Ulticom (Formerly DGM&S)
- 0200 T1 Card
-12d5 Equator Technologies Inc
- 0003 BSP16
- 1000 BSP15
-12d6 Analogic Corp
-12d7 Biotronic SRL
-12d8 Pericom Semiconductor
-12d9 Aculab PLC
- 0002 PCI Prosody
- 0004 cPCI Prosody
- 0005 Aculab E1/T1 PCI card
-12da True Time Inc.
-12db Annapolis Micro Systems, Inc
-12dc Symicron Computer Communication Ltd.
-12dd Management Graphics
-12de Rainbow Technologies
- 0200 CryptoSwift CS200
-12df SBS Technologies Inc
-12e0 Chase Research
- 0010 ST16C654 Quad UART
- 0020 ST16C654 Quad UART
- 0030 ST16C654 Quad UART
-12e1 Nintendo Co, Ltd
-12e2 Datum Inc. Bancomm-Timing Division
-12e3 Imation Corp - Medical Imaging Systems
-12e4 Brooktrout Technology Inc
-12e5 Apex Semiconductor Inc
-12e6 Cirel Systems
-12e7 Sunsgroup Corporation
-12e8 Crisc Corp
-12e9 GE Spacenet
-12ea Zuken
-12eb Aureal Semiconductor
- 0001 Vortex 1
- 104d 8036 AU8820 Vortex Digital Audio Processor
- 1092 2000 Sonic Impact A3D
- 1092 2100 Sonic Impact A3D
- 1092 2110 Sonic Impact A3D
- 1092 2200 Sonic Impact A3D
- 122d 1002 AU8820 Vortex Digital Audio Processor
- 12eb 0001 AU8820 Vortex Digital Audio Processor
- 5053 3355 Montego
- 0002 Vortex 2
- 104d 8049 AU8830 Vortex 3D Digital Audio Processor
- 104d 807b AU8830 Vortex 3D Digital Audio Processor
- 1092 3000 Monster Sound II
- 1092 3001 Monster Sound II
- 1092 3002 Monster Sound II
- 1092 3003 Monster Sound II
- 1092 3004 Monster Sound II
- 12eb 0001 AU8830 Vortex 3D Digital Audio Processor
- 12eb 0002 AU8830 Vortex 3D Digital Audio Processor
- 12eb 0088 AU8830 Vortex 3D Digital Audio Processor
- 144d 3510 AU8830 Vortex 3D Digital Audio Processor
- 5053 3356 Montego II
- 0003 AU8810 Vortex Digital Audio Processor
- 104d 8049 AU8810 Vortex Digital Audio Processor
- 104d 8077 AU8810 Vortex Digital Audio Processor
- 109f 1000 AU8810 Vortex Digital Audio Processor
- 12eb 0003 AU8810 Vortex Digital Audio Processor
- 1462 6780 AU8810 Vortex Digital Audio Processor
- 14a4 2073 AU8810 Vortex Digital Audio Processor
- 14a4 2091 AU8810 Vortex Digital Audio Processor
- 14a4 2104 AU8810 Vortex Digital Audio Processor
- 14a4 2106 AU8810 Vortex Digital Audio Processor
- 8803 Vortex 56k Software Modem
- 12eb 8803 Vortex 56k Software Modem
-12ec 3A International, Inc.
-12ed Optivision Inc.
-12ee Orange Micro
-12ef Vienna Systems
-12f0 Pentek
-12f1 Sorenson Vision Inc
-12f2 Gammagraphx, Inc.
-12f3 Radstone Technology
-12f4 Megatel
-12f5 Forks
-12f6 Dawson France
-12f7 Cognex
-12f8 Electronic Design GmbH
- 0002 VideoMaker
-12f9 Four Fold Ltd
-12fb Spectrum Signal Processing
-12fc Capital Equipment Corp
-12fd I2S
-12fe ESD Electronic System Design GmbH
-12ff Lexicon
-1300 Harman International Industries Inc
-1302 Computer Sciences Corp
-1303 Innovative Integration
-1304 Juniper Networks
-1305 Netphone, Inc
-1306 Duet Technologies
-# Formerly ComputerBoards
-1307 Measurement Computing
- 0001 PCI-DAS1602/16
- 000b PCI-DIO48H
- 000c PCI-PDISO8
- 000d PCI-PDISO16
- 000f PCI-DAS1200
- 0010 PCI-DAS1602/12
- 0014 PCI-DIO24H
- 0015 PCI-DIO24H/CTR3
- 0016 PCI-DIO48H/CTR15
- 0017 PCI-DIO96H
- 0018 PCI-CTR05
- 0019 PCI-DAS1200/JR
- 001a PCI-DAS1001
- 001b PCI-DAS1002
- 001c PCI-DAS1602JR/16
- 001d PCI-DAS6402/16
- 001e PCI-DAS6402/12
- 001f PCI-DAS16/M1
- 0020 PCI-DDA02/12
- 0021 PCI-DDA04/12
- 0022 PCI-DDA08/12
- 0023 PCI-DDA02/16
- 0024 PCI-DDA04/16
- 0025 PCI-DDA08/16
- 0026 PCI-DAC04/12-HS
- 0027 PCI-DAC04/16-HS
- 0028 PCI-DIO24
- 0029 PCI-DAS08
- 002c PCI-INT32
- 0033 PCI-DUAL-AC5
- 0034 PCI-DAS-TC
- 0035 PCI-DAS64/M1/16
- 0036 PCI-DAS64/M2/16
- 0037 PCI-DAS64/M3/16
- 004c PCI-DAS1000
- 004d PCI-QUAD04
- 0052 PCI-DAS4020/12
- 005e PCI-DAS6025
-1308 Jato Technologies Inc.
- 0001 NetCelerator Adapter
- 1308 0001 NetCelerator Adapter
-1309 AB Semiconductor Ltd
-130a Mitsubishi Electric Microcomputer
-130b Colorgraphic Communications Corp
-130c Ambex Technologies, Inc
-130d Accelerix Inc
-130e Yamatake-Honeywell Co. Ltd
-130f Advanet Inc
-1310 Gespac
-1311 Videoserver, Inc
-1312 Acuity Imaging, Inc
-1313 Yaskawa Electric Co.
-1316 Teradyne Inc
-1317 Linksys
- 0981 21x4x DEC-Tulip compatible 10/100 Ethernet
- 0985 NC100 Network Everywhere Fast Ethernet 10/100
- 1985 21x4x DEC-Tulip compatible 10/100 Ethernet
- 2850 HSP MicroModem 56
- 8201 ADMtek ADM8211 802.11b Wireless Interface
- 10b8 2635 SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
- 1317 8201 SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
- 8211 ADMtek ADM8211 802.11b Wireless Interface
- 9511 21x4x DEC-Tulip compatible 10/100 Ethernet
-1318 Packet Engines Inc.
- 0911 GNIC-II PCI Gigabit Ethernet [Hamachi]
-1319 Fortemedia, Inc
- 0801 Xwave QS3000A [FM801]
- 0802 Xwave QS3000A [FM801 game port]
- 1000 FM801 PCI Audio
- 1001 FM801 PCI Joystick
-131a Finisar Corp.
-131c Nippon Electro-Sensory Devices Corp
-131d Sysmic, Inc.
-131e Xinex Networks Inc
-131f Siig Inc
- 1000 CyberSerial (1-port) 16550
- 1001 CyberSerial (1-port) 16650
- 1002 CyberSerial (1-port) 16850
- 1010 Duet 1S(16550)+1P
- 1011 Duet 1S(16650)+1P
- 1012 Duet 1S(16850)+1P
- 1020 CyberParallel (1-port)
- 1021 CyberParallel (2-port)
- 1030 CyberSerial (2-port) 16550
- 1031 CyberSerial (2-port) 16650
- 1032 CyberSerial (2-port) 16850
- 1034 Trio 2S(16550)+1P
- 1035 Trio 2S(16650)+1P
- 1036 Trio 2S(16850)+1P
- 1050 CyberSerial (4-port) 16550
- 1051 CyberSerial (4-port) 16650
- 1052 CyberSerial (4-port) 16850
- 2000 CyberSerial (1-port) 16550
- 2001 CyberSerial (1-port) 16650
- 2002 CyberSerial (1-port) 16850
- 2010 Duet 1S(16550)+1P
- 2011 Duet 1S(16650)+1P
- 2012 Duet 1S(16850)+1P
- 2020 CyberParallel (1-port)
- 2021 CyberParallel (2-port)
- 2030 CyberSerial (2-port) 16550
- 131f 2030 PCI Serial Card
- 2031 CyberSerial (2-port) 16650
- 2032 CyberSerial (2-port) 16850
- 2040 Trio 1S(16550)+2P
- 2041 Trio 1S(16650)+2P
- 2042 Trio 1S(16850)+2P
- 2050 CyberSerial (4-port) 16550
- 2051 CyberSerial (4-port) 16650
- 2052 CyberSerial (4-port) 16850
- 2060 Trio 2S(16550)+1P
- 2061 Trio 2S(16650)+1P
- 2062 Trio 2S(16850)+1P
- 2081 CyberSerial (8-port) ST16654
-1320 Crypto AG
-1321 Arcobel Graphics BV
-1322 MTT Co., Ltd
-1323 Dome Inc
-1324 Sphere Communications
-1325 Salix Technologies, Inc
-1326 Seachange international
-1327 Voss scientific
-1328 quadrant international
-1329 Productivity Enhancement
-132a Microcom Inc.
-132b Broadband Technologies
-132c Micrel Inc
-132d Integrated Silicon Solution, Inc.
-1330 MMC Networks
-1331 Radisys Corp.
- 0030 ENP-2611
- 8200 82600 Host Bridge
- 8201 82600 IDE
- 8202 82600 USB
- 8210 82600 PCI Bridge
-1332 Micro Memory
- 5415 MM-5415CN PCI Memory Module with Battery Backup
- 5425 MM-5425CN PCI 64/66 Memory Module with Battery Backup
-1334 Redcreek Communications, Inc
-1335 Videomail, Inc
-1337 Third Planet Publishing
-1338 BT Electronics
-133a Vtel Corp
-133b Softcom Microsystems
-133c Holontech Corp
-133d SS Technologies
-133e Virtual Computer Corp
-133f SCM Microsystems
-1340 Atalla Corp
-1341 Kyoto Microcomputer Co
-1342 Promax Systems Inc
-1343 Phylon Communications Inc
-1344 Crucial Technology
-1345 Arescom Inc
-1347 Odetics
-1349 Sumitomo Electric Industries, Ltd.
-134a DTC Technology Corp.
- 0001 Domex 536
- 0002 Domex DMX3194UP SCSI Adapter
-134b ARK Research Corp.
-134c Chori Joho System Co. Ltd
-134d PCTel Inc
- 2189 HSP56 MicroModem
- 2486 2304WT V.92 MDC Modem
- 7890 HSP MicroModem 56
- 134d 0001 PCT789 adapter
- 7891 HSP MicroModem 56
- 134d 0001 HSP MicroModem 56
- 7892 HSP MicroModem 56
- 7893 HSP MicroModem 56
- 7894 HSP MicroModem 56
- 7895 HSP MicroModem 56
- 7896 HSP MicroModem 56
- 7897 HSP MicroModem 56
-134e CSTI
-134f Algo System Co Ltd
-1350 Systec Co. Ltd
-1351 Sonix Inc
-1353 Thales Idatys
- 0002 Proserver
- 0003 PCI-FUT
- 0004 PCI-S0
- 0005 PCI-FUT-S0
-1354 Dwave System Inc
-1355 Kratos Analytical Ltd
-1356 The Logical Co
-1359 Prisa Networks
-135a Brain Boxes
-135b Giganet Inc
-135c Quatech Inc
- 0010 QSC-100
- 0020 DSC-100
- 0030 DSC-200/300
- 0040 QSC-200/300
- 0050 ESC-100D
- 0060 ESC-100M
- 00f0 MPAC-100 Syncronous Serial Card (Zilog 85230)
- 0170 QSCLP-100
- 0180 DSCLP-100
- 0190 SSCLP-100
- 01a0 QSCLP-200/300
- 01b0 DSCLP-200/300
- 01c0 SSCLP-200/300
-135d ABB Network Partner AB
-135e Sealevel Systems Inc
- 5101 Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32)
- 7101 Single Port RS-232/422/485/530
- 7201 Dual Port RS-232/422/485 Interface
- 7202 Dual Port RS-232 Interface
- 7401 Four Port RS-232 Interface
- 7402 Four Port RS-422/485 Interface
- 7801 Eight Port RS-232 Interface
- 7804 Eight Port RS-232/422/485 Interface
- 8001 8001 Digital I/O Adapter
-135f I-Data International A-S
-1360 Meinberg Funkuhren
- 0101 PCI32 DCF77 Radio Clock
- 0102 PCI509 DCF77 Radio Clock
- 0103 PCI510 DCF77 Radio Clock
- 0201 GPS167PCI GPS Receiver
- 0202 GPS168PCI GPS Receiver
- 0203 GPS169PCI GPS Receiver
- 0301 TCR510PCI IRIG Receiver
-1361 Soliton Systems K.K.
-1362 Fujifacom Corporation
-1363 Phoenix Technology Ltd
-1364 ATM Communications Inc
-1365 Hypercope GmbH
-1366 Teijin Seiki Co. Ltd
-1367 Hitachi Zosen Corporation
-1368 Skyware Corporation
-1369 Digigram
-136a High Soft Tech
-136b Kawasaki Steel Corporation
- ff01 KL5A72002 Motion JPEG
-136c Adtek System Science Co Ltd
-136d Gigalabs Inc
-136f Applied Magic Inc
-1370 ATL Products
-1371 CNet Technology Inc
- 434e GigaCard Network Adapter
- 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
-1373 Silicon Vision Inc
-1374 Silicom Ltd
-1375 Argosystems Inc
-1376 LMC
-1377 Electronic Equipment Production & Distribution GmbH
-1378 Telemann Co. Ltd
-1379 Asahi Kasei Microsystems Co Ltd
-137a Mark of the Unicorn Inc
- 0001 PCI-324 Audiowire Interface
-137b PPT Vision
-137c Iwatsu Electric Co Ltd
-137d Dynachip Corporation
-137e Patriot Scientific Corporation
-137f Japan Satellite Systems Inc
-1380 Sanritz Automation Co Ltd
-1381 Brains Co. Ltd
-1382 Marian - Electronic & Software
- 0001 ARC88 audio recording card
- 2008 Prodif 96 Pro sound system
- 2088 Marc 8 Midi sound system
- 20c8 Marc A sound system
- 4008 Marc 2 sound system
- 4010 Marc 2 Pro sound system
- 4048 Marc 4 MIDI sound system
- 4088 Marc 4 Digi sound system
- 4248 Marc X sound system
-1383 Controlnet Inc
-1384 Reality Simulation Systems Inc
-1385 Netgear
-# Note: This lists as Atheros Communications, Inc. AR5212 802.11abg NIC because of Madwifi
- 0013 WG311T
- 311a GA511 Gigabit Ethernet
- 4100 802.11b Wireless Adapter (MA301)
- 4105 MA311 802.11b wireless adapter
- 4400 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4600 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4601 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4610 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4a00 WAG311 802.11a/g Wireless PCI Adapter
- 4c00 WG311v2 54 Mbps Wireless PCI Adapter
- 620a GA620 Gigabit Ethernet
- 622a GA622
- 630a GA630 Gigabit Ethernet
- f004 FA310TX
-1386 Video Domain Technologies
-1387 Systran Corp
-1388 Hitachi Information Technology Co Ltd
-1389 Applicom International
- 0001 PCI1500PFB [Intelligent fieldbus adaptor]
-138a Fusion Micromedia Corp
-138b Tokimec Inc
-138c Silicon Reality
-138d Future Techno Designs pte Ltd
-138e Basler GmbH
-138f Patapsco Designs Inc
-1390 Concept Development Inc
-1391 Development Concepts Inc
-1392 Medialight Inc
-1393 Moxa Technologies Co Ltd
- 1040 Smartio C104H/PCI
- 1141 Industrio CP-114
- 1680 Smartio C168H/PCI
- 2040 Intellio CP-204J
- 2180 Intellio C218 Turbo PCI
- 3200 Intellio C320 Turbo PCI
-1394 Level One Communications
- 0001 LXT1001 Gigabit Ethernet
- 1394 0001 NetCelerator Adapter
-1395 Ambicom Inc
-1396 Cipher Systems Inc
-1397 Cologne Chip Designs GmbH
- 2bd0 ISDN network controller [HFC-PCI]
- 1397 2bd0 ISDN Board
- e4bf 1000 CI1-1-Harp
-1398 Clarion co. Ltd
-1399 Rios systems Co Ltd
-139a Alacritech Inc
- 0001 Quad Port 10/100 Server Accelerator
- 0003 Single Port 10/100 Server Accelerator
- 0005 Single Port Gigabit Server Accelerator
-139b Mediasonic Multimedia Systems Ltd
-139c Quantum 3d Inc
-139d EPL limited
-139e Media4
-139f Aethra s.r.l.
-13a0 Crystal Group Inc
-13a1 Kawasaki Heavy Industries Ltd
-13a2 Ositech Communications Inc
-13a3 Hifn Inc.
- 0005 7751 Security Processor
- 0006 6500 Public Key Processor
- 0007 7811 Security Processor
- 0012 7951 Security Processor
- 0014 78XX Security Processor
- 0016 8065 Security Processor
- 0017 8165 Security Processor
- 0018 8154 Security Processor
- 001d 7956 Security Processor
- 0020 7955 Security Processor
-13a4 Rascom Inc
-13a5 Audio Digital Imaging Inc
-13a6 Videonics Inc
-13a7 Teles AG
-13a8 Exar Corp.
- 0154 XR17C154 Quad UART
- 0158 XR17C158 Octal UART
-13a9 Siemens Medical Systems, Ultrasound Group
-13aa Broadband Networks Inc
-13ab Arcom Control Systems Ltd
-13ac Motion Media Technology Ltd
-13ad Nexus Inc
-13ae ALD Technology Ltd
-13af T.Sqware
-13b0 Maxspeed Corp
-13b1 Tamura corporation
-13b2 Techno Chips Co. Ltd
-13b3 Lanart Corporation
-13b4 Wellbean Co Inc
-13b5 ARM
-13b6 Dlog GmbH
-13b7 Logic Devices Inc
-13b8 Nokia Telecommunications oy
-13b9 Elecom Co Ltd
-13ba Oxford Instruments
-13bb Sanyo Technosound Co Ltd
-13bc Bitran Corporation
-13bd Sharp corporation
-13be Miroku Jyoho Service Co. Ltd
-13bf Sharewave Inc
-13c0 Microgate Corporation
- 0010 SyncLink Adapter v1
- 0020 SyncLink SCC Adapter
- 0030 SyncLink Multiport Adapter
- 0210 SyncLink Adapter v2
-13c1 3ware Inc
- 1000 3ware Inc 3ware 5xxx/6xxx-series PATA-RAID
- 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
- 13c1 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
- 1002 3ware Inc 3ware 9xxx-series SATA-RAID
-13c2 Technotrend Systemtechnik GmbH
-13c3 Janz Computer AG
-13c4 Phase Metrics
-13c5 Alphi Technology Corp
-13c6 Condor Engineering Inc
- 0520 CEI-520 A429 Card
- 0620 CEI-620 A429 Card
- 0820 CEI-820 A429 Card
-13c7 Blue Chip Technology Ltd
-13c8 Apptech Inc
-13c9 Eaton Corporation
-13ca Iomega Corporation
-13cb Yano Electric Co Ltd
-13cc Metheus Corporation
-13cd Compatible Systems Corporation
-13ce Cocom A/S
-13cf Studio Audio & Video Ltd
-13d0 Techsan Electronics Co Ltd
- 2103 B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card
- 2200 B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card
-13d1 Abocom Systems Inc
- ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter
- ab03 21x4x DEC-Tulip compatible 10/100 Ethernet
- ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter
- ab08 21x4x DEC-Tulip compatible 10/100 Ethernet
-13d2 Shark Multimedia Inc
-13d3 IMC Networks
-13d4 Graphics Microsystems Inc
-13d5 Media 100 Inc
-13d6 K.I. Technology Co Ltd
-13d7 Toshiba Engineering Corporation
-13d8 Phobos corporation
-13d9 Apex PC Solutions Inc
-13da Intresource Systems pte Ltd
-13db Janich & Klass Computertechnik GmbH
-13dc Netboost Corporation
-13dd Multimedia Bundle Inc
-13de ABB Robotics Products AB
-13df E-Tech Inc
- 0001 PCI56RVP Modem
- 13df 0001 PCI56RVP Modem
-13e0 GVC Corporation
-13e1 Silicom Multimedia Systems Inc
-13e2 Dynamics Research Corporation
-13e3 Nest Inc
-13e4 Calculex Inc
-13e5 Telesoft Design Ltd
-13e6 Argosy research Inc
-13e7 NAC Incorporated
-13e8 Chip Express Corporation
-13e9 Intraserver Technology Inc
-13ea Dallas Semiconductor
-13eb Hauppauge Computer Works Inc
-13ec Zydacron Inc
-13ed Raytheion E-Systems
-13ee Hayes Microcomputer Products Inc
-13ef Coppercom Inc
-13f0 Sundance Technology Inc
- 0201 ST201 Sundance Ethernet
-13f1 Oce' - Technologies B.V.
-13f2 Ford Microelectronics Inc
-13f3 Mcdata Corporation
-13f4 Troika Networks, Inc.
- 1401 Zentai Fibre Channel Adapter
-13f5 Kansai Electric Co. Ltd
-13f6 C-Media Electronics Inc
- 0011 CMI8738
- 0100 CM8338A
- 13f6 ffff CMI8338/C3DX PCI Audio Device
- 0101 CM8338B
- 13f6 0101 CMI8338-031 PCI Audio Device
- 0111 CM8738
- 1019 0970 P6STP-FL motherboard
- 1043 8035 CUSI-FX motherboard
- 1043 8077 CMI8738 6-channel audio controller
- 1043 80e2 CMI8738 6ch-MX
- 13f6 0111 CMI8738/C3DX PCI Audio Device
- 1681 a000 Gamesurround MUSE XL
- 0211 CM8738
-13f7 Wildfire Communications
-13f8 Ad Lib Multimedia Inc
-13f9 NTT Advanced Technology Corp.
-13fa Pentland Systems Ltd
-13fb Aydin Corp
-13fc Computer Peripherals International
-13fd Micro Science Inc
-13fe Advantech Co. Ltd
- 1240 PCI-1240 4-channel stepper motor controller card w. Nova Electronics MCX314
- 1600 PCI-1612 4-port RS-232/422/485 PCI Communication Card
- 1752 PCI-1752
- 1754 PCI-1754
- 1756 PCI-1756
-13ff Silicon Spice Inc
-1400 Artx Inc
- 1401 9432 TX
-1401 CR-Systems A/S
-1402 Meilhaus Electronic GmbH
-1403 Ascor Inc
-1404 Fundamental Software Inc
-1405 Excalibur Systems Inc
-1406 Oce' Printing Systems GmbH
-1407 Lava Computer mfg Inc
- 0100 Lava Dual Serial
- 0101 Lava Quatro A
- 0102 Lava Quatro B
- 0110 Lava DSerial-PCI Port A
- 0111 Lava DSerial-PCI Port B
- 0120 Quattro-PCI A
- 0121 Quattro-PCI B
- 0180 Lava Octo A
- 0181 Lava Octo B
- 0200 Lava Port Plus
- 0201 Lava Quad A
- 0202 Lava Quad B
- 0220 Lava Quattro PCI Ports A/B
- 0221 Lava Quattro PCI Ports C/D
- 0500 Lava Single Serial
- 0600 Lava Port 650
- 8000 Lava Parallel
- 8001 Dual parallel port controller A
- 8002 Lava Dual Parallel port A
- 8003 Lava Dual Parallel port B
- 8800 BOCA Research IOPPAR
-1408 Aloka Co. Ltd
-1409 Timedia Technology Co Ltd
- 7168 PCI2S550 (Dual 16550 UART)
-140a DSP Research Inc
-140b Ramix Inc
-140c Elmic Systems Inc
-140d Matsushita Electric Works Ltd
-140e Goepel Electronic GmbH
-140f Salient Systems Corp
-1410 Midas lab Inc
-1411 Ikos Systems Inc
-# formerly IC Ensemble Inc.
-1412 VIA Technologies Inc.
- 1712 ICE1712 [Envy24] PCI Multi-Channel I/O Controller
- 1412 1712 Hoontech ST Audio DSP 24
- 1412 d630 M-Audio Delta 1010
- 1412 d631 M-Audio Delta DiO
- 1412 d632 M-Audio Delta 66
- 1412 d633 M-Audio Delta 44
- 1412 d634 M-Audio Delta Audiophile
- 1412 d635 M-Audio Delta TDIF
- 1412 d637 M-Audio Delta RBUS
- 1412 d638 M-Audio Delta 410
- 1412 d63b M-Audio Delta 1010LT
- 1412 d63c Digigram VX442
- 1416 1712 Hoontech ST Audio DSP 24 Media 7.1
- 153b 1115 EWS88 MT
- 153b 1125 EWS88 MT (Master)
- 153b 112b EWS88 D
- 153b 112c EWS88 D (Master)
- 153b 1130 EWX 24/96
- 153b 1138 DMX 6fire 24/96
- 153b 1151 PHASE88
- 16ce 1040 Edirol DA-2496
- 1724 VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller
- 1412 1724 AMP Ltd AUDIO2000
- 1412 3630 M-Audio Revolution 7.1
- 153b 1145 Aureon 7.1 Space
- 153b 1147 Aureon 5.1 Sky
- 153b 1153 Aureon 7.1 Universe
- 270f f641 ZNF3-150
- 270f f645 ZNF3-250
-1413 Addonics
-1414 Microsoft Corporation
-1415 Oxford Semiconductor Ltd
- 8403 VScom 011H-EP1 1 port parallel adaptor
- 9501 OX16PCI954 (Quad 16950 UART) function 0
- 131f 2050 CyberPro (4-port)
-# Model IO1085, Part No: JJ-P46012
- 131f 2051 CyberSerial 4S Plus
- 15ed 2000 MCCR Serial p0-3 of 8
- 15ed 2001 MCCR Serial p0-3 of 16
- 950a EXSYS EX-41092 Dual 16950 Serial adapter
- 950b OXCB950 Cardbus 16950 UART
- 9510 OX16PCI954 (Quad 16950 UART) function 1 (Disabled)
- 9511 OX16PCI954 (Quad 16950 UART) function 1
- 15ed 2000 MCCR Serial p4-7 of 8
- 15ed 2001 MCCR Serial p4-15 of 16
- 9521 OX16PCI952 (Dual 16950 UART)
-1416 Multiwave Innovation pte Ltd
-1417 Convergenet Technologies Inc
-1418 Kyushu electronics systems Inc
-1419 Excel Switching Corp
-141a Apache Micro Peripherals Inc
-141b Zoom Telephonics Inc
-141d Digitan Systems Inc
-141e Fanuc Ltd
-141f Visiontech Ltd
-1420 Psion Dacom plc
- 8002 Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part)
- 8003 Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part)
-1421 Ads Technologies Inc
-1422 Ygrec Systems Co Ltd
-1423 Custom Technology Corp.
-1424 Videoserver Connections
-1425 Chelsio Communications Inc
-1426 Storage Technology Corp.
-1427 Better On-Line Solutions
-1428 Edec Co Ltd
-1429 Unex Technology Corp.
-142a Kingmax Technology Inc
-142b Radiolan
-142c Minton Optic Industry Co Ltd
-142d Pix stream Inc
-142e Vitec Multimedia
- 4020 VM2-2 [Video Maker 2] MPEG1/2 Encoder
-142f Radicom Research Inc
-1430 ITT Aerospace/Communications Division
-1431 Gilat Satellite Networks
-1432 Edimax Computer Co.
- 9130 RTL81xx Fast Ethernet
-1433 Eltec Elektronik GmbH
-1435 Real Time Devices US Inc.
-1436 CIS Technology Inc
-1437 Nissin Inc Co
-1438 Atmel-dream
-1439 Outsource Engineering & Mfg. Inc
-143a Stargate Solutions Inc
-143b Canon Research Center, America
-143c Amlogic Inc
-143d Tamarack Microelectronics Inc
-143e Jones Futurex Inc
-143f Lightwell Co Ltd - Zax Division
-1440 ALGOL Corp.
-1441 AGIE Ltd
-1442 Phoenix Contact GmbH & Co.
-1443 Unibrain S.A.
-1444 TRW
-1445 Logical DO Ltd
-1446 Graphin Co Ltd
-1447 AIM GmBH
-1448 Alesis Studio Electronics
-1449 TUT Systems Inc
-144a Adlink Technology
- 7296 PCI-7296
- 7432 PCI-7432
- 7433 PCI-7433
- 7434 PCI-7434
- 7841 PCI-7841
- 8133 PCI-8133
- 8164 PCI-8164
- 8554 PCI-8554
- 9111 PCI-9111
- 9113 PCI-9113
- 9114 PCI-9114
-144b Loronix Information Systems Inc
-144c Catalina Research Inc
-144d Samsung Electronics Co Ltd
-144e OLITEC
-144f Askey Computer Corp.
-1450 Octave Communications Ind.
-1451 SP3D Chip Design GmBH
-1453 MYCOM Inc
-1454 Altiga Networks
-1455 Logic Plus Plus Inc
-1456 Advanced Hardware Architectures
-1457 Nuera Communications Inc
-1458 Giga-byte Technology
- 0c11 K8NS Pro Mainboard
-1459 DOOIN Electronics
-145a Escalate Networks Inc
-145b PRAIM SRL
-145c Cryptek
-145d Gallant Computer Inc
-145e Aashima Technology B.V.
-145f Baldor Electric Company
- 0001 NextMove PCI
-1460 DYNARC INC
-1461 Avermedia Technologies Inc
-1462 Micro-Star International Co., Ltd.
-# MSI CB54G Wireless PC Card that seems to use the Broadcom 4306 Chipset
- 6819 Broadcom Corporation BCM4306 802.11b/g Wireless LAN Controller [MSI CB54G]
- 6825 PCI Card wireless 11g [PC54G]
- 8725 NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter
-# MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I
- 9000 NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter
- 9110 GeFORCE FX5200
- 9119 NVIDIA NV31 [GeForce FX 5600XT] VGA Adapter
- 9591 nVidia Corporation NV36 [GeForce FX 5700LE]
-1463 Fast Corporation
-1464 Interactive Circuits & Systems Ltd
-1465 GN NETTEST Telecom DIV.
-1466 Designpro Inc.
-1467 DIGICOM SPA
-1468 AMBIT Microsystem Corp.
-1469 Cleveland Motion Controls
-146a IFR
-146b Parascan Technologies Ltd
-146c Ruby Tech Corp.
- 1430 FE-1430TX Fast Ethernet PCI Adapter
-146d Tachyon, INC.
-146e Williams Electronics Games, Inc.
-146f Multi Dimensional Consulting Inc
-1470 Bay Networks
-1471 Integrated Telecom Express Inc
-1472 DAIKIN Industries, Ltd
-1473 ZAPEX Technologies Inc
-1474 Doug Carson & Associates
-1475 PICAZO Communications
-1476 MORTARA Instrument Inc
-1477 Net Insight
-1478 DIATREND Corporation
-1479 TORAY Industries Inc
-147a FORMOSA Industrial Computing
-147b ABIT Computer Corp.
-147c AWARE, Inc.
-147d Interworks Computer Products
-147e Matsushita Graphic Communication Systems, Inc.
-147f NIHON UNISYS, Ltd.
-1480 SCII Telecom
-1481 BIOPAC Systems Inc
-1482 ISYTEC - Integrierte Systemtechnik GmBH
-1483 LABWAY Corporation
-1484 Logic Corporation
-1485 ERMA - Electronic GmBH
-1486 L3 Communications Telemetry & Instrumentation
-1487 MARQUETTE Medical Systems
-1488 KONTRON Electronik GmBH
-1489 KYE Systems Corporation
-148a OPTO
-148b INNOMEDIALOGIC Inc.
-148c C.P. Technology Co. Ltd
-148d DIGICOM Systems, Inc.
- 1003 HCF 56k Data/Fax Modem
-148e OSI Plus Corporation
-148f Plant Equipment, Inc.
-1490 Stone Microsystems PTY Ltd.
-1491 ZEAL Corporation
-1492 Time Logic Corporation
-1493 MAKER Communications
-1494 WINTOP Technology, Inc.
-1495 TOKAI Communications Industry Co. Ltd
-1496 JOYTECH Computer Co., Ltd.
-1497 SMA Regelsysteme GmBH
-1498 TEWS Datentechnik GmBH
- 30c8 TPCI200
-1499 EMTEC CO., Ltd
-149a ANDOR Technology Ltd
-149b SEIKO Instruments Inc
-149c OVISLINK Corp.
-149d NEWTEK Inc
- 0001 Video Toaster for PC
-149e Mapletree Networks Inc.
-149f LECTRON Co Ltd
-14a0 SOFTING GmBH
-14a1 Systembase Co Ltd
-14a2 Millennium Engineering Inc
-14a3 Maverick Networks
-14a4 GVC/BCM Advanced Research
-14a5 XIONICS Document Technologies Inc
-14a6 INOVA Computers GmBH & Co KG
-14a7 MYTHOS Systems Inc
-14a8 FEATRON Technologies Corporation
-14a9 HIVERTEC Inc
-14aa Advanced MOS Technology Inc
-14ab Mentor Graphics Corp.
-14ac Novaweb Technologies Inc
-14ad Time Space Radio AB
-14ae CTI, Inc
-14af Guillemot Corporation
- 7102 3D Prophet II MX
-14b0 BST Communication Technology Ltd
-14b1 Nextcom K.K.
-14b2 ENNOVATE Networks Inc
-14b3 XPEED Inc
- 0000 DSL NIC
-14b4 PHILIPS Business Electronics B.V.
-14b5 Creamware GmBH
- 0200 Scope
- 0300 Pulsar
- 0400 PulsarSRB
- 0600 Pulsar2
- 0800 DSP-Board
- 0900 DSP-Board
- 0a00 DSP-Board
- 0b00 DSP-Board
-14b6 Quantum Data Corp.
-14b7 PROXIM Inc
- 0001 Symphony 4110
-14b8 Techsoft Technology Co Ltd
-14b9 AIRONET Wireless Communications
- 0001 PC4800
- 0340 PC4800
- 0350 PC4800
- 4500 PC4500
- 4800 Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800
- a504 Cisco Aironet Wireless 802.11b
- a505 Cisco Aironet CB20a 802.11a Wireless LAN Adapter
- a506 Cisco Aironet Mini PCI b/g
-14ba INTERNIX Inc.
-14bb SEMTECH Corporation
-14bc Globespan Semiconductor Inc.
-14bd CARDIO Control N.V.
-14be L3 Communications
-14bf SPIDER Communications Inc.
-14c0 COMPAL Electronics Inc
-14c1 MYRICOM Inc.
- 8043 Myrinet 2000 Scalable Cluster Interconnect
-14c2 DTK Computer
-14c3 MEDIATEK Corp.
-14c4 IWASAKI Information Systems Co Ltd
-14c5 Automation Products AB
-14c6 Data Race Inc
-14c7 Modular Technology Holdings Ltd
-14c8 Turbocomm Tech. Inc.
-14c9 ODIN Telesystems Inc
-14ca PE Logic Corp.
-14cb Billionton Systems Inc
-14cc NAKAYO Telecommunications Inc
-14cd Universal Scientific Ind.
-14ce Whistle Communications
-14cf TEK Microsystems Inc.
-14d0 Ericsson Axe R & D
-14d1 Computer Hi-Tech Co Ltd
-14d2 Titan Electronics Inc
- 8001 VScom 010L 1 port parallel adaptor
- 8002 VScom 020L 2 port parallel adaptor
- 8010 VScom 100L 1 port serial adaptor
- 8011 VScom 110L 1 port serial and 1 port parallel adaptor
- 8020 VScom 200L 1 port serial adaptor
- 8021 VScom 210L 2 port serial and 1 port parallel adaptor
- 8040 VScom 400L 4 port serial adaptor
- 8080 VScom 800L 8 port serial adaptor
- a000 VScom 010H 1 port parallel adaptor
- a001 VScom 100H 1 port serial adaptor
- a003 VScom 400H 4 port serial adaptor
- a004 VScom 400HF1 4 port serial adaptor
- a005 VScom 200H 2 port serial adaptor
- e001 VScom 010HV2 1 port parallel adaptor
- e010 VScom 100HV2 1 port serial adaptor
- e020 VScom 200HV2 2 port serial adaptor
-14d3 CIRTECH (UK) Ltd
-14d4 Panacom Technology Corp
-14d5 Nitsuko Corporation
-14d6 Accusys Inc
-14d7 Hirakawa Hewtech Corp
-14d8 HOPF Elektronik GmBH
-# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
-14d9 Alliance Semiconductor Corporation
- 0010 AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
- 9000 AS90L10204/10208 HyperTransport to PCI-X Bridge
-14da National Aerospace Laboratories
-14db AFAVLAB Technology Inc
- 2120 TK9902
-14dc Amplicon Liveline Ltd
- 0000 PCI230
- 0001 PCI242
- 0002 PCI244
- 0003 PCI247
- 0004 PCI248
- 0005 PCI249
- 0006 PCI260
- 0007 PCI224
- 0008 PCI234
- 0009 PCI236
- 000a PCI272
- 000b PCI215
-14dd Boulder Design Labs Inc
-14de Applied Integration Corporation
-14df ASIC Communications Corp
-14e1 INVERTEX
-14e2 INFOLIBRIA
-14e3 AMTELCO
-14e4 Broadcom Corporation
- 0800 Sentry5 Chipcommon I/O Controller
- 0804 Sentry5 PCI Bridge
- 0805 Sentry5 MIPS32 CPU
- 0806 Sentry5 Ethernet Controller
- 080b Sentry5 Crypto Accelerator
- 080f Sentry5 DDR/SDR RAM Controller
- 0811 Sentry5 External Interface Core
- 0816 BCM3302 Sentry5 MIPS32 CPU
- 1600 NetXtreme BCM5752 Gigabit Ethernet PCI Express
- 1644 NetXtreme BCM5700 Gigabit Ethernet
- 1014 0277 Broadcom Vigil B5700 1000Base-T
- 1028 00d1 Broadcom BCM5700
- 1028 0106 Broadcom BCM5700
- 1028 0109 Broadcom BCM5700 1000Base-T
- 1028 010a Broadcom BCM5700 1000BaseTX
- 10b7 1000 3C996-T 1000Base-T
- 10b7 1001 3C996B-T 1000Base-T
- 10b7 1002 3C996C-T 1000Base-T
- 10b7 1003 3C997-T 1000Base-T Dual Port
- 10b7 1004 3C996-SX 1000Base-SX
- 10b7 1005 3C997-SX 1000Base-SX Dual Port
- 10b7 1008 3C942 Gigabit LOM (31X31)
- 14e4 0002 NetXtreme 1000Base-SX
- 14e4 0003 NetXtreme 1000Base-SX
- 14e4 0004 NetXtreme 1000Base-T
- 14e4 1028 NetXtreme 1000BaseTX
- 14e4 1644 BCM5700 1000Base-T
- 1645 NetXtreme BCM5701 Gigabit Ethernet
- 0e11 007c NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 0e11 007d NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)
- 0e11 0085 NC7780 Gigabit Server Adapter (embedded, WOL)
- 0e11 0099 NC7780 Gigabit Server Adapter (embedded, WOL)
- 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)
- 1028 0121 Broadcom BCM5701 1000Base-T
- 103c 128a HP 1000Base-T (PCI) [A7061A]
- 103c 128b HP 1000Base-SX (PCI) [A7073A]
- 103c 12a4 HP Core Lan 1000Base-T
- 103c 12c1 HP IOX Core Lan 1000Base-T [A7109AX]
- 10a9 8010 SGI IO9 Gigabit Ethernet (Copper)
- 10a9 8011 SGI Gigabit Ethernet (Copper)
- 10a9 8012 SGI Gigabit Ethernet (Fiber)
- 10b7 1004 3C996-SX 1000Base-SX
- 10b7 1006 3C996B-T 1000Base-T
- 10b7 1007 3C1000-T 1000Base-T
- 10b7 1008 3C940-BR01 1000Base-T
- 14e4 0001 BCM5701 1000Base-T
- 14e4 0005 BCM5701 1000Base-T
- 14e4 0006 BCM5701 1000Base-T
- 14e4 0007 BCM5701 1000Base-SX
- 14e4 0008 BCM5701 1000Base-T
- 14e4 8008 BCM5701 1000Base-T
- 1646 NetXtreme BCM5702 Gigabit Ethernet
- 0e11 00bb NC7760 1000BaseTX
- 1028 0126 Broadcom BCM5702 1000BaseTX
- 14e4 8009 BCM5702 1000BaseTX
- 1647 NetXtreme BCM5703 Gigabit Ethernet
- 0e11 0099 NC7780 1000BaseTX
- 0e11 009a NC7770 1000BaseTX
- 10a9 8010 SGI IO9 Gigabit Ethernet (Copper)
- 14e4 0009 BCM5703 1000BaseTX
- 14e4 000a BCM5703 1000BaseSX
- 14e4 000b BCM5703 1000BaseTX
- 14e4 8009 BCM5703 1000BaseTX
- 14e4 800a BCM5703 1000BaseTX
- 1648 NetXtreme BCM5704 Gigabit Ethernet
- 0e11 00cf NC7772 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00d0 NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00d1 NC7783 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X
- 10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X
- 1166 1648 NetXtreme CIOB-E 1000Base-T
- 164a NetXtreme II BCM5706 Gigabit Ethernet
- 164d NetXtreme BCM5702FE Gigabit Ethernet
- 1653 NetXtreme BCM5705 Gigabit Ethernet
- 0e11 00e3 NC7761 Gigabit Server Adapter
- 1654 NetXtreme BCM5705_2 Gigabit Ethernet
- 0e11 00e3 NC7761 Gigabit Server Adapter
- 103c 3100 NC1020 HP ProLiant Gigabit Server Adapter 32 PCI
- 1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express
- 165d NetXtreme BCM5705M Gigabit Ethernet
- 165e NetXtreme BCM5705M_2 Gigabit Ethernet
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 166e 570x 10/100 Integrated Controller
- 1677 NetXtreme BCM5751 Gigabit Ethernet PCI Express
- 1028 0179 Optiplex GX280
- 167d NetXtreme BCM5751M Gigabit Ethernet PCI Express
- 167e NetXtreme BCM5751F Fast Ethernet PCI Express
- 1696 NetXtreme BCM5782 Gigabit Ethernet
- 103c 12bc HP d530 CMT (DG746A)
- 14e4 000d NetXtreme BCM5782 1000Base-T
- 169c NetXtreme BCM5788 Gigabit Ethernet
- 169d NetLink BCM5789 Gigabit Ethernet PCI Express
- 16a6 NetXtreme BCM5702X Gigabit Ethernet
- 0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 1028 0126 BCM5702 1000Base-T
- 14e4 000c BCM5702 1000Base-T
- 14e4 8009 BCM5702 1000Base-T
- 16a7 NetXtreme BCM5703X Gigabit Ethernet
- 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 14e4 0009 NetXtreme BCM5703 1000Base-T
- 14e4 000a NetXtreme BCM5703 1000Base-SX
- 14e4 000b NetXtreme BCM5703 1000Base-T
- 14e4 800a NetXtreme BCM5703 1000Base-T
- 16a8 NetXtreme BCM5704S Gigabit Ethernet
- 10b7 2001 3C998-SX Dual Port 1000-SX PCI-X
- 16aa NetXtreme II BCM5706S Gigabit Ethernet
- 16c6 NetXtreme BCM5702A3 Gigabit Ethernet
- 10b7 1100 3C1000B-T 10/100/1000 PCI
- 14e4 000c BCM5702 1000Base-T
- 14e4 8009 BCM5702 1000Base-T
- 16c7 NetXtreme BCM5703 Gigabit Ethernet
- 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 103c 12c3 HP Combo FC/GigE-SX [A9782A]
- 103c 12ca HP Combo FC/GigE-T [A9784A]
- 14e4 0009 NetXtreme BCM5703 1000Base-T
- 14e4 000a NetXtreme BCM5703 1000Base-SX
- 16dd NetLink BCM5781 Gigabit Ethernet PCI Express
- 16f7 NetXtreme BCM5753 Gigabit Ethernet PCI Express
- 16fd NetXtreme BCM5753M Gigabit Ethernet PCI Express
- 16fe NetXtreme BCM5753F Fast Ethernet PCI Express
- 170c BCM4401-B0 100Base-TX
- 170d NetXtreme BCM5901 100Base-TX
- 1014 0545 ThinkPad R40e (2684-HVG) builtin ethernet controller
- 170e NetXtreme BCM5901 100Base-TX
- 3352 BCM3352
- 3360 BCM3360
- 4210 BCM4210 iLine10 HomePNA 2.0
- 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
- 4212 BCM4212 v.90 56k modem
- 4301 BCM4303 802.11b Wireless LAN Controller
- 1028 0407 TrueMobile 1180 Onboard WLAN
- 1043 0120 WL-103b Wireless LAN PC Card
- 4305 BCM4307 V.90 56k Modem
- 4306 BCM4307 Ethernet Controller
- 4307 BCM4307 802.11b Wireless LAN Controller
- 4310 BCM4310 Chipcommon I/OController
- 4312 BCM4310 UART
- 4313 BCM4310 Ethernet Controller
- 4315 BCM4310 USB Controller
- 4320 BCM4306 802.11b/g Wireless LAN Controller
- 1028 0001 TrueMobile 1300 WLAN Mini-PCI Card
- 1028 0003 Wireless 1350 WLAN Mini-PCI Card
- 1043 100f WL-100G
- 14e4 4320 Linksys WMP54G PCI
- 1737 4320 WPC54G
- 1799 7010 Belkin F5D7010 54g Wireless Network card
- 4321 BCM4306 802.11a Wireless LAN Controller
- 4322 BCM4306 UART
- 4324 BCM4309 802.11a/b/g
- 1028 0001 Truemobile 1400
- 1028 0003 Truemobile 1450 MiniPCI
- 4325 BCM43xG 802.11b/g
- 1414 0003 Wireless Notebook Adapter MN-720
- 1414 0004 Wireless PCI Adapter MN-730
-# probably this is a correct ID...
- 4326 BCM4307 Chipcommon I/O Controller?
- 4401 BCM4401 100Base-T
- 1043 80a8 A7V8X motherboard
- 4402 BCM4402 Integrated 10/100BaseT
- 4403 BCM4402 V.90 56k Modem
- 4410 BCM4413 iLine32 HomePNA 2.0
- 4411 BCM4413 V.90 56k modem
- 4412 BCM4412 10/100BaseT
- 4430 BCM44xx CardBus iLine32 HomePNA 2.0
- 4432 BCM4432 CardBus 10/100BaseT
- 4610 BCM4610 Sentry5 PCI to SB Bridge
- 4611 BCM4610 Sentry5 iLine32 HomePNA 1.0
- 4612 BCM4610 Sentry5 V.90 56k Modem
- 4613 BCM4610 Sentry5 Ethernet Controller
- 4614 BCM4610 Sentry5 External Interface
- 4615 BCM4610 Sentry5 USB Controller
- 4704 BCM4704 PCI to SB Bridge
- 4705 BCM4704 Sentry5 802.11b Wireless LAN Controller
- 4706 BCM4704 Sentry5 Ethernet Controller
- 4707 BCM4704 Sentry5 USB Controller
- 4708 BCM4704 Crypto Accelerator
- 4710 BCM4710 Sentry5 PCI to SB Bridge
- 4711 BCM47xx Sentry5 iLine32 HomePNA 2.0
- 4712 BCM47xx V.92 56k modem
- 4713 Sentry5 Ethernet Controller
- 4714 BCM47xx Sentry5 External Interface
- 4715 Sentry5 USB Controller
- 4716 BCM47xx Sentry5 USB Host Controller
- 4717 BCM47xx Sentry5 USB Device Controller
- 4718 Sentry5 Crypto Accelerator
- 4720 BCM4712 MIPS CPU
- 5365 BCM5365P Sentry5 Host Bridge
- 5600 BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
- 5605 BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
- 5615 BCM5615 StrataSwitch 24+2 Ethernet Switch Controller
- 5625 BCM5625 StrataSwitch 24+2 Ethernet Switch Controller
- 5645 BCM5645 StrataSwitch 24+2 Ethernet Switch Controller
- 5670 BCM5670 8-Port 10GE Ethernet Switch Fabric
- 5680 BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller
- 5690 BCM5690 12-port Multi-Layer Gigabit Ethernet Switch
- 5691 BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller
- 5820 BCM5820 Crypto Accelerator
- 5821 BCM5821 Crypto Accelerator
- 5822 BCM5822 Crypto Accelerator
- 5823 BCM5823 Crypto Accelerator
- 5824 BCM5824 Crypto Accelerator
- 5840 BCM5840 Crypto Accelerator
- 5841 BCM5841 Crypto Accelerator
- 5850 BCM5850 Crypto Accelerator
-14e5 Pixelfusion Ltd
-14e6 SHINING Technology Inc
-14e7 3CX
-14e8 RAYCER Inc
-14e9 GARNETS System CO Ltd
-14ea Planex Communications, Inc
- ab06 FNW-3603-TX CardBus Fast Ethernet
- ab07 RTL81xx RealTek Ethernet
-14eb SEIKO EPSON Corp
-14ec ACQIRIS
-14ed DATAKINETICS Ltd
-14ee MASPRO KENKOH Corp
-14ef CARRY Computer ENG. CO Ltd
-14f0 CANON RESEACH CENTRE FRANCE
-14f1 Conexant
- 1002 HCF 56k Modem
- 1003 HCF 56k Modem
- 1004 HCF 56k Modem
- 1005 HCF 56k Modem
- 1006 HCF 56k Modem
- 1022 HCF 56k Modem
- 1023 HCF 56k Modem
- 1024 HCF 56k Modem
- 1025 HCF 56k Modem
- 1026 HCF 56k Modem
- 1032 HCF 56k Modem
- 1033 HCF 56k Data/Fax Modem
- 1033 8077 NEC
- 122d 4027 Dell Zeus - MDP3880-W(B) Data Fax Modem
- 122d 4030 Dell Mercury - MDP3880-U(B) Data Fax Modem
- 122d 4034 Dell Thor - MDP3880-W(U) Data Fax Modem
- 13e0 020d Dell Copper
- 13e0 020e Dell Silver
- 13e0 0261 IBM
- 13e0 0290 Compaq Goldwing
- 13e0 02a0 IBM
- 13e0 02b0 IBM
- 13e0 02c0 Compaq Scooter
- 13e0 02d0 IBM
- 144f 1500 IBM P85-DF (1)
- 144f 1501 IBM P85-DF (2)
- 144f 150a IBM P85-DF (3)
- 144f 150b IBM P85-DF Low Profile (1)
- 144f 1510 IBM P85-DF Low Profile (2)
- 1034 HCF 56k Data/Fax/Voice Modem
- 1035 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 1098 Fujitsu P85-DFSV
- 1036 HCF 56k Data/Fax/Voice/Spkp Modem
- 104d 8067 HCF 56k Modem
- 122d 4029 MDP3880SP-W
- 122d 4031 MDP3880SP-U
- 13e0 0209 Dell Titanium
- 13e0 020a Dell Graphite
- 13e0 0260 Gateway Red Owl
- 13e0 0270 Gateway White Horse
- 1052 HCF 56k Data/Fax Modem (Worldwide)
- 1053 HCF 56k Data/Fax Modem (Worldwide)
- 1054 HCF 56k Data/Fax/Voice Modem (Worldwide)
- 1055 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide)
- 1056 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
- 1057 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
- 1059 HCF 56k Data/Fax/Voice Modem (Worldwide)
- 1063 HCF 56k Data/Fax Modem
- 1064 HCF 56k Data/Fax/Voice Modem
- 1065 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1066 HCF 56k Data/Fax/Voice/Spkp Modem
- 122d 4033 Dell Athena - MDP3900V-U
- 1433 HCF 56k Data/Fax Modem
- 1434 HCF 56k Data/Fax/Voice Modem
- 1435 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1436 HCF 56k Data/Fax Modem
- 1453 HCF 56k Data/Fax Modem
- 13e0 0240 IBM
- 13e0 0250 IBM
- 144f 1502 IBM P95-DF (1)
- 144f 1503 IBM P95-DF (2)
- 1454 HCF 56k Data/Fax/Voice Modem
- 1455 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1456 HCF 56k Data/Fax/Voice/Spkp Modem
- 122d 4035 Dell Europa - MDP3900V-W
- 122d 4302 Dell MP3930V-W(C) MiniPCI
- 1610 ADSL AccessRunner PCI Arbitration Device
- 1611 AccessRunner PCI ADSL Interface Device
- 1620 ADSL AccessRunner V2 PCI Arbitration Device
- 1621 AccessRunner V2 PCI ADSL Interface Device
- 1622 AccessRunner V2 PCI ADSL Yukon WAN Adapter
- 1803 HCF 56k Modem
- 0e11 0023 623-LAN Grizzly
- 0e11 0043 623-LAN Yogi
- 1815 HCF 56k Modem
- 0e11 0022 Grizzly
- 0e11 0042 Yogi
- 2003 HSF 56k Data/Fax Modem
- 2004 HSF 56k Data/Fax/Voice Modem
- 2005 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 2006 HSF 56k Data/Fax/Voice/Spkp Modem
- 2013 HSF 56k Data/Fax Modem
- 0e11 b195 Bear
- 0e11 b196 Seminole 1
- 0e11 b1be Seminole 2
- 1025 8013 Acer
- 1033 809d NEC
- 1033 80bc NEC
- 155d 6793 HP
- 155d 8850 E Machines
- 2014 HSF 56k Data/Fax/Voice Modem
- 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 2016 HSF 56k Data/Fax/Voice/Spkp Modem
- 2043 HSF 56k Data/Fax Modem (WorldW SmartDAA)
- 2044 HSF 56k Data/Fax/Voice Modem (WorldW SmartDAA)
- 2045 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA)
- 2046 HSF 56k Data/Fax/Voice/Spkp Modem (WorldW SmartDAA)
- 2063 HSF 56k Data/Fax Modem (SmartDAA)
- 2064 HSF 56k Data/Fax/Voice Modem (SmartDAA)
- 2065 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA)
- 2066 HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA)
- 2093 HSF 56k Modem
- 155d 2f07 Legend
- 2143 HSF 56k Data/Fax/Cell Modem (Mob WorldW SmartDAA)
- 2144 HSF 56k Data/Fax/Voice/Cell Modem (Mob WorldW SmartDAA)
- 2145 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WorldW SmartDAA)
- 2146 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob WorldW SmartDAA)
- 2163 HSF 56k Data/Fax/Cell Modem (Mob SmartDAA)
- 2164 HSF 56k Data/Fax/Voice/Cell Modem (Mob SmartDAA)
- 2165 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob SmartDAA)
- 2166 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob SmartDAA)
- 2343 HSF 56k Data/Fax CardBus Modem (Mob WorldW SmartDAA)
- 2344 HSF 56k Data/Fax/Voice CardBus Modem (Mob WorldW SmartDAA)
- 2345 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WorldW SmartDAA)
- 2346 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob WorldW SmartDAA)
- 2363 HSF 56k Data/Fax CardBus Modem (Mob SmartDAA)
- 2364 HSF 56k Data/Fax/Voice CardBus Modem (Mob SmartDAA)
- 2365 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA)
- 2366 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob SmartDAA)
- 2443 HSF 56k Data/Fax Modem (Mob WorldW SmartDAA)
- 104d 8075 Modem
- 104d 8083 Modem
- 104d 8097 Modem
- 2444 HSF 56k Data/Fax/Voice Modem (Mob WorldW SmartDAA)
- 2445 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob WorldW SmartDAA)
- 2446 HSF 56k Data/Fax/Voice/Spkp Modem (Mob WorldW SmartDAA)
- 2463 HSF 56k Data/Fax Modem (Mob SmartDAA)
- 2464 HSF 56k Data/Fax/Voice Modem (Mob SmartDAA)
- 2465 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA)
- 2466 HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA)
- 2f00 HSF 56k HSFi Modem
- 13e0 8d84 IBM HSFi V.90
- 13e0 8d85 Compaq Stinger
- 14f1 2004 Dynalink 56PMi
- 2f02 HSF 56k HSFi Data/Fax
- 2f11 HSF 56k HSFi Modem
- 8234 RS8234 ATM SAR Controller [ServiceSAR Plus]
- 8800 CX22702 DVB-T 2k/8k
- 17de 08a1 XPert DVB-T PCI BDA DVBT 23880 Video Capture
- 8802 CX23883 Broadcast Decoder
- 17de 08a1 Xpert DVB-T PCI 2388x Transport Stream Capture
-14f2 MOBILITY Electronics
- 0120 EV1000 bridge
- 0121 EV1000 Parallel port
- 0122 EV1000 Serial port
- 0123 EV1000 Keyboard controller
- 0124 EV1000 Mouse controller
-14f3 BroadLogic
- 2030 2030 DVB-S Satellite Reciever
- 2050 2050 DVB-T Terrestrial (Cable) Reciever
- 2060 2060 ATSC Terrestrial (Cable) Reciever
-14f4 TOKYO Electronic Industry CO Ltd
-14f5 SOPAC Ltd
-14f6 COYOTE Technologies LLC
-14f7 WOLF Technology Inc
-14f8 AUDIOCODES Inc
- 2077 TP-240 dual span E1 VoIP PCI card
-14f9 AG COMMUNICATIONS
-14fa WANDEL & GOCHERMANN
-14fb TRANSAS MARINE (UK) Ltd
-14fc Quadrics Ltd
- 0000 QsNet Elan3 Network Adapter
- 0001 QsNetII Elan4 Network Adapter
-14fd JAPAN Computer Industry Inc
-14fe ARCHTEK TELECOM Corp
-14ff TWINHEAD INTERNATIONAL Corp
-1500 DELTA Electronics, Inc
- 1360 RTL81xx RealTek Ethernet
-1501 BANKSOFT CANADA Ltd
-1502 MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd
-1503 KAWASAKI LSI USA Inc
-1504 KAISER Electronics
-1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH
-1506 CHAMELEON Systems Inc
-# Should be HTEC Ltd, but there are no known HTEC chips and 1507 is already used by mistake by Motorola (see vendor ID 1057).
-1507 Motorola ?? / HTEC
- 0001 MPC105 [Eagle]
- 0002 MPC106 [Grackle]
- 0003 MPC8240 [Kahlua]
- 0100 MC145575 [HFC-PCI]
- 0431 KTI829c 100VG
- 4801 Raven
- 4802 Falcon
- 4803 Hawk
- 4806 CPX8216
-1508 HONDA CONNECTORS/MHOTRONICS Inc
-1509 FIRST INTERNATIONAL Computer Inc
-150a FORVUS RESEARCH Inc
-150b YAMASHITA Systems Corp
-150c KYOPAL CO Ltd
-150d WARPSPPED Inc
-150e C-PORT Corp
-150f INTEC GmbH
-1510 BEHAVIOR TECH Computer Corp
-1511 CENTILLIUM Technology Corp
-1512 ROSUN Technologies Inc
-1513 Raychem
-1514 TFL LAN Inc
-1515 Advent design
-1516 MYSON Technology Inc
- 0800 MTD-8xx 100/10M Ethernet PCI Adapter
- 0803 SURECOM EP-320X-S 100/10M Ethernet PCI Adapter
- 1320 10bd SURECOM EP-320X-S 100/10M Ethernet PCI Adapter
- 0891 MTD-8xx 100/10M Ethernet PCI Adapter
-1517 ECHOTEK Corp
-1518 PEP MODULAR Computers GmbH
-1519 TELEFON AKTIEBOLAGET LM Ericsson
-151a Globetek
- 1002 PCI-1002
- 1004 PCI-1004
- 1008 PCI-1008
-151b COMBOX Ltd
-151c DIGITAL AUDIO LABS Inc
- 0003 Prodif T 2496
- 4000 Prodif 88
-151d Fujitsu Computer Products Of America
-151e MATRIX Corp
-151f TOPIC SEMICONDUCTOR Corp
- 0000 TP560 Data/Fax/Voice 56k modem
-1520 CHAPLET System Inc
-1521 BELL Corp
-1522 MainPine Ltd
- 0100 PCI <-> IOBus Bridge
- 1522 0200 RockForceDUO 2 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0300 RockForceQUATRO 4 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0400 RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0500 RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem
- 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem
- 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0c00 RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
- 1522 0d00 RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
-# this is a correction to a recent entry. 1522:0E00 should be 1522:1D00
- 1522 1d00 RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
-1523 MUSIC Semiconductors
-1524 ENE Technology Inc
- 0510 CB710 Memory Card Reader Controller
- 0610 PCI Smart Card Reader Controller
- 1211 CB1211 Cardbus Controller
- 1225 CB1225 Cardbus Controller
- 1410 CB1410 Cardbus Controller
- 1025 005a TravelMate 290
- 1411 CB-710/2/4 Cardbus Controller
- 1412 CB-712/4 Cardbus Controller
- 1420 CB1420 Cardbus Controller
- 1421 CB-720/2/4 Cardbus Controller
- 1422 CB-722/4 Cardbus Controller
-1525 IMPACT Technologies
-1526 ISS, Inc
-1527 SOLECTRON
-1528 ACKSYS
-1529 AMERICAN MICROSystems Inc
-152a QUICKTURN DESIGN Systems
-152b FLYTECH Technology CO Ltd
-152c MACRAIGOR Systems LLC
-152d QUANTA Computer Inc
-152e MELEC Inc
-152f PHILIPS - CRYPTO
-1530 ACQIS Technology Inc
-1531 CHRYON Corp
-1532 ECHELON Corp
-1533 BALTIMORE
-1534 ROAD Corp
-1535 EVERGREEN Technologies Inc
-1537 DATALEX COMMUNCATIONS
-1538 ARALION Inc
- 0303 ARS106S Ultra ATA 133/100/66 Host Controller
-1539 ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A.
-153a ONO SOKKI
-153b TERRATEC Electronic GmbH
- 1144 Aureon 5.1
-# Terratec seems to use several IDs for the same card.
- 1147 Aureon 5.1 Sky
- 1158 Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV]
-153c ANTAL Electronic
-153d FILANET Corp
-153e TECHWELL Inc
-153f MIPS DENMARK
-1540 PROVIDEO MULTIMEDIA Co Ltd
-1541 MACHONE Communications
-1542 VIVID Technology Inc
-1543 SILICON Laboratories
- 3052 Intel 537 [Winmodem]
- 4c22 Si3036 MC'97 DAA
-1544 DCM DATA Systems
-1545 VISIONTEK
-1546 IOI Technology Corp
-1547 MITUTOYO Corp
-1548 JET PROPULSION Laboratory
-1549 INTERCONNECT Systems Solutions
-154a MAX Technologies Inc
-154b COMPUTEX Co Ltd
-154c VISUAL Technology Inc
-154d PAN INTERNATIONAL Industrial Corp
-154e SERVOTEST Ltd
-154f STRATABEAM Technology
-1550 OPEN NETWORK Co Ltd
-1551 SMART Electronic DEVELOPMENT GmBH
-1552 RACAL AIRTECH Ltd
-1553 CHICONY Electronics Co Ltd
-1554 PROLINK Microsystems Corp
-1555 GESYTEC GmBH
-1556 PLD APPLICATIONS
-1557 MEDIASTAR Co Ltd
-1558 CLEVO/KAPOK Computer
-1559 SI LOGIC Ltd
-155a INNOMEDIA Inc
-155b PROTAC INTERNATIONAL Corp
-155c Cemax-Icon Inc
-155d Mac System Co Ltd
-155e LP Elektronik GmbH
-155f Perle Systems Ltd
-1560 Terayon Communications Systems
-1561 Viewgraphics Inc
-1562 Symbol Technologies
-1563 A-Trend Technology Co Ltd
-1564 Yamakatsu Electronics Industry Co Ltd
-1565 Biostar Microtech Int'l Corp
-1566 Ardent Technologies Inc
-1567 Jungsoft
-1568 DDK Electronics Inc
-1569 Palit Microsystems Inc.
-156a Avtec Systems
-156b 2wire Inc
-156c Vidac Electronics GmbH
-156d Alpha-Top Corp
-156e Alfa Inc
-156f M-Systems Flash Disk Pioneers Ltd
-1570 Lecroy Corp
-1571 Contemporary Controls
- a001 CCSI PCI20-485 ARCnet
- a002 CCSI PCI20-485D ARCnet
- a003 CCSI PCI20-485X ARCnet
- a004 CCSI PCI20-CXB ARCnet
- a005 CCSI PCI20-CXS ARCnet
- a006 CCSI PCI20-FOG-SMA ARCnet
- a007 CCSI PCI20-FOG-ST ARCnet
- a008 CCSI PCI20-TB5 ARCnet
- a009 CCSI PCI20-5-485 5Mbit ARCnet
- a00a CCSI PCI20-5-485D 5Mbit ARCnet
- a00b CCSI PCI20-5-485X 5Mbit ARCnet
- a00c CCSI PCI20-5-FOG-ST 5Mbit ARCnet
- a00d CCSI PCI20-5-FOG-SMA 5Mbit ARCnet
- a201 CCSI PCI22-485 10Mbit ARCnet
- a202 CCSI PCI22-485D 10Mbit ARCnet
- a203 CCSI PCI22-485X 10Mbit ARCnet
- a204 CCSI PCI22-CHB 10Mbit ARCnet
- a205 CCSI PCI22-FOG_ST 10Mbit ARCnet
- a206 CCSI PCI22-THB 10Mbit ARCnet
-1572 Otis Elevator Company
-1573 Lattice - Vantis
-1574 Fairchild Semiconductor
-1575 Voltaire Advanced Data Security Ltd
-1576 Viewcast COM
-1578 HITT
- 5615 VPMK3 [Video Processor Mk III]
-1579 Dual Technology Corp
-157a Japan Elecronics Ind Inc
-157b Star Multimedia Corp
-157c Eurosoft (UK)
- 8001 Fix2000 PCI Y2K Compliance Card
-157d Gemflex Networks
-157e Transition Networks
-157f PX Instruments Technology Ltd
-1580 Primex Aerospace Co
-1581 SEH Computertechnik GmbH
-1582 Cytec Corp
-1583 Inet Technologies Inc
-1584 Uniwill Computer Corp
-1585 Logitron
-1586 Lancast Inc
-1587 Konica Corp
-1588 Solidum Systems Corp
-1589 Atlantek Microsystems Pty Ltd
-158a Digalog Systems Inc
-158b Allied Data Technologies
-158c Hitachi Semiconductor & Devices Sales Co Ltd
-158d Point Multimedia Systems
-158e Lara Technology Inc
-158f Ditect Coop
-1590 3pardata Inc
-1591 ARN
-1592 Syba Tech Ltd
- 0781 Multi-IO Card
- 0782 Parallel Port Card 2xEPP
- 0783 Multi-IO Card
- 0785 Multi-IO Card
- 0786 Multi-IO Card
- 0787 Multi-IO Card
- 0788 Multi-IO Card
- 078a Multi-IO Card
-1593 Bops Inc
-1594 Netgame Ltd
-1595 Diva Systems Corp
-1596 Folsom Research Inc
-1597 Memec Design Services
-1598 Granite Microsystems
-1599 Delta Electronics Inc
-159a General Instrument
-159b Faraday Technology Corp
-159c Stratus Computer Systems
-159d Ningbo Harrison Electronics Co Ltd
-159e A-Max Technology Co Ltd
-159f Galea Network Security
-15a0 Compumaster SRL
-15a1 Geocast Network Systems
-15a2 Catalyst Enterprises Inc
- 0001 TA700 PCI Bus Analyzer/Exerciser
-15a3 Italtel
-15a4 X-Net OY
-15a5 Toyota Macs Inc
-15a6 Sunlight Ultrasound Technologies Ltd
-15a7 SSE Telecom Inc
-15a8 Shanghai Communications Technologies Center
-15aa Moreton Bay
-15ab Bluesteel Networks Inc
-15ac North Atlantic Instruments
-15ad VMware Inc
- 0405 [VMware SVGA II] PCI Display Adapter
- 0710 Virtual SVGA
- 0720 VMware High-Speed Virtual NIC [vmxnet]
-15ae Amersham Pharmacia Biotech
-15b0 Zoltrix International Ltd
-15b1 Source Technology Inc
-15b2 Mosaid Technologies Inc
-15b3 Mellanox Technologies
- 5274 MT21108 InfiniBridge
- 5a44 MT23108 InfiniHost
- 5a45 MT23108 [Infinihost HCA Flash Recovery]
- 5a46 MT23108 PCI Bridge
- 5e8c MT24204 [InfiniHost III Lx HCA]
- 5e8d MT24204 [InfiniHost III Lx HCA Flash Recovery]
- 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
- 6279 MT25208 [InfiniHost III Ex HCA Flash Recovery]
- 6282 MT25208 InfiniHost III Ex
-15b4 CCI/TRIAD
-15b5 Cimetrics Inc
-15b6 Texas Memory Systems Inc
-15b7 Sandisk Corp
-15b8 ADDI-DATA GmbH
-15b9 Maestro Digital Communications
-15ba Impacct Technology Corp
-15bb Portwell Inc
-15bc Agilent Technologies
- 2922 64 Bit, 133MHz PCI-X Exerciser & Protocol Checker
- 2928 64 Bit, 66MHz PCI Exerciser & Analyzer
- 2929 64 Bit, 133MHz PCI-X Analyzer & Exerciser
-15bd DFI Inc
-15be Sola Electronics
-15bf High Tech Computer Corp (HTC)
-15c0 BVM Ltd
-15c1 Quantel
-15c2 Newer Technology Inc
-15c3 Taiwan Mycomp Co Ltd
-15c4 EVSX Inc
-15c5 Procomp Informatics Ltd
- 8010 1394b - 1394 Firewire 3-Port Host Adapter Card
-15c6 Technical University of Budapest
-15c7 Tateyama System Laboratory Co Ltd
- 0349 Tateyama C-PCI PLC/NC card Rev.01A
-15c8 Penta Media Co Ltd
-15c9 Serome Technology Inc
-15ca Bitboys OY
-15cb AG Electronics Ltd
-15cc Hotrail Inc
-15cd Dreamtech Co Ltd
-15ce Genrad Inc
-15cf Hilscher GmbH
-15d1 Infineon Technologies AG
-15d2 FIC (First International Computer Inc)
-15d3 NDS Technologies Israel Ltd
-15d4 Iwill Corp
-15d5 Tatung Co
-15d6 Entridia Corp
-15d7 Rockwell-Collins Inc
-15d8 Cybernetics Technology Co Ltd
-15d9 Super Micro Computer Inc
-15da Cyberfirm Inc
-15db Applied Computing Systems Inc
-15dc Litronic Inc
- 0001 Argus 300 PCI Cryptography Module
-15dd Sigmatel Inc
-15de Malleable Technologies Inc
-15df Infinilink Corp
-15e0 Cacheflow Inc
-15e1 Voice Technologies Group Inc
-15e2 Quicknet Technologies Inc
-15e3 Networth Technologies Inc
-15e4 VSN Systemen BV
-15e5 Valley technologies Inc
-15e6 Agere Inc
-15e7 Get Engineering Corp
-15e8 National Datacomm Corp
- 0130 Wireless PCI Card
-15e9 Pacific Digital Corp
- 1841 ADMA-100 DiscStaQ ATA Controller
-15ea Tokyo Denshi Sekei K.K.
-15eb Drsearch GmbH
-15ec Beckhoff GmbH
- 3101 FC3101 Profibus DP 1 Channel PCI
- 5102 FC5102
-15ed Macrolink Inc
-15ee In Win Development Inc
-15ef Intelligent Paradigm Inc
-15f0 B-Tree Systems Inc
-15f1 Times N Systems Inc
-15f2 Diagnostic Instruments Inc
-15f3 Digitmedia Corp
-15f4 Valuesoft
-15f5 Power Micro Research
-15f6 Extreme Packet Device Inc
-15f7 Banctec
-15f8 Koga Electronics Co
-15f9 Zenith Electronics Corp
-15fa J.P. Axzam Corp
-15fb Zilog Inc
-15fc Techsan Electronics Co Ltd
-15fd N-CUBED.NET
-15fe Kinpo Electronics Inc
-15ff Fastpoint Technologies Inc
-1600 Northrop Grumman - Canada Ltd
-1601 Tenta Technology
-1602 Prosys-tec Inc
-1603 Nokia Wireless Communications
-1604 Central System Research Co Ltd
-1605 Pairgain Technologies
-1606 Europop AG
-1607 Lava Semiconductor Manufacturing Inc
-1608 Automated Wagering International
-1609 Scimetric Instruments Inc
-1612 Telesynergy Research Inc.
-1619 FarSite Communications Ltd
- 0400 FarSync T2P (2 port X.21/V.35/V.24)
- 0440 FarSync T4P (4 port X.21/V.35/V.24)
-# www.rioworks.com
-161f Rioworks
-1626 TDK Semiconductor Corp.
- 8410 RTL81xx Fast Ethernet
-1629 Kongsberg Spacetec AS
- 1003 Format synchronizer v3.0
- 2002 Fast Universal Data Output
-# This seems to occur on their 802.11b Wireless card WMP-11
-1637 Linksys
- 3874 Linksys 802.11b WMP11 PCI Wireless card
-1638 Standard Microsystems Corp [SMC]
- 1100 SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000
-163c Smart Link Ltd.
- 3052 SmartLink SmartPCI562 56K Modem
- 5449 SmartPCI561 Modem
-1657 Brocade Communications Systems, Inc.
-165a Epix Inc
- c100 PIXCI(R) CL1 Camera Link Video Capture Board [custom QL5232]
- d200 PIXCI(R) D2X Digital Video Capture Board [custom QL5232]
- d300 PIXCI(R) D3X Digital Video Capture Board [custom QL5232]
-165d Hsing Tech. Enterprise Co., Ltd.
-1661 Worldspace Corp.
-1668 Actiontec Electronics Inc
- 0100 Mini-PCI bridge
-# Formerly SiByte, Inc.
-166d Broadcom Corporation
- 0001 SiByte BCM1125/1125H/1250 System-on-a-Chip PCI
- 0002 SiByte BCM1125H/1250 System-on-a-Chip HyperTransport
-1677 Bernecker + Rainer
- 104e 5LS172.6 B&R Dual CAN Interface Card
- 12d7 5LS172.61 B&R Dual CAN Interface Card
-167b ZyDAS Technology Corp.
- 2102 ZyDAS ZD1202
- 187e 3406 ZyAIR B-122 CardBus 11Mbs Wireless LAN Card
-1681 Hercules
-# More specs, more accurate desc.
- 0010 Hercules 3d Prophet II Ultra 64MB [ 350 MHz NV15BR core, 128-bit DDR @ 460 MHz, 1.5v AGP4x ]
-1682 XFX Pine Group Inc.
-1688 CastleNet Technology Inc.
- 1170 WLAN 802.11b card
-168c Atheros Communications, Inc.
- 0007 AR5000 802.11a Wireless Adapter
- 0011 AR5210 802.11a NIC
- 0012 AR5211 802.11ab NIC
- 0013 AR5212 802.11abg NIC
- 1113 d301 Philips CPWNA100 Wireless CardBus adapter
- 1186 3202 D-link DWL-G650 B3 Wireless cardbus adapter
- 1186 3203 DWL-G520 Wireless PCI Adapter
- 1186 3a13 DWL-G520 Wireless PCI Adapter rev. B
- 1186 3a94 C54C Wireless 801.11g cardbus
- 1385 4d00 Netgear WG311T Wireless PCI Adapter
- 14b7 0a60 8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter
- 168c 0013 WG511T Wireless CardBus Adapter
- 168c 1025 DWL-G650B2 Wireless CardBus Adapter
- 168c 1027 Netgate NL-3054CB ARIES b/g CardBus Adapter
- 168c 2026 Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter
- 168c 2041 Netgate 5354MP Plus ARIES2 b/g MiniPCI Adapter
- 168c 2042 Netgate 5354MP Plus ARIES2 a/b/g MiniPCI Adapter
- 1014 AR5212 802.11abg NIC
-169c Netcell Corporation
- 0044 SyncRAID SR3000/5000 Series SATA RAID Controllers
-16a5 Tekram Technology Co.,Ltd.
-16ab Global Sun Technology Inc
- 1100 GL24110P
- 1101 PLX9052 PCMCIA-to-PCI Wireless LAN
- 1102 PCMCIA-to-PCI Wireless Network Bridge
- 8501 WL-8305 Wireless LAN PCI Adapter
-16ae Safenet Inc
- 1141 SafeXcel-1141
-16b4 Aspex Semiconductor Ltd
-16be Creatix Polymedia GmbH
-16ca CENATEK Inc
- 0001 Rocket Drive DL
-16cd Densitron Technologies
-16ce Roland Corp.
-# www.pikatechnologies.com
-16df PIKA Technologies Inc.
-16e3 European Space Agency
- 1e0f LEON2FT Processor
-16ec U.S. Robotics
- 00ff USR997900 10/100 Mbps PCI Network Card
- 0116 USR997902 10/100/1000 Mbps PCI Network Card
- 3685 Wireless Access PCI Adapter Model 022415
-16ed Sycron N. V.
- 1001 UMIO communication card
-16f3 Jetway Information Co., Ltd.
-16f4 Vweb Corp
- 8000 VW2010
-16f6 VideoTele.com, Inc.
-# www.internetmachines.com
-1702 Internet Machines Corporation (IMC)
-1705 Digital First, Inc.
-170b NetOctave
- 0100 NSP2000-SSL crypto accelerator
-170c YottaYotta Inc.
-# Seems to be a 2nd ID for Vitesse Semiconductor
-1725 Vitesse Semiconductor
- 7174 VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
-172a Accelerated Encryption
-1734 Fujitsu Siemens Computer GmbH
-1737 Linksys
- 0013 WMP54G Wireless Pci Card
- 0015 WMP54GS Wireless Pci Card
- 1032 Gigabit Network Adapter
- 1737 0015 EG1032 v2 Instant Gigabit Network Adapter
- 1064 Gigabit Network Adapter
- 1737 0016 EG1064 v2 Instant Gigabit Network Adapter
- ab08 21x4x DEC-Tulip compatible 10/100 Ethernet
- ab09 21x4x DEC-Tulip compatible 10/100 Ethernet
-173b Altima (nee Broadcom)
- 03e8 AC1000 Gigabit Ethernet
- 03e9 AC1001 Gigabit Ethernet
- 03ea AC9100 Gigabit Ethernet
- 173b 0001 AC1002
- 03eb AC1003 Gigabit Ethernet
-1743 Peppercon AG
- 8139 ROL/F-100 Fast Ethernet Adapter with ROL
-1749 RLX Technologies
-174b PC Partner Limited
-174d WellX Telecom SA
-175c AudioScience Inc
-175e Sanera Systems, Inc.
-1787 Hightech Information System Ltd.
-# also used by Struck Innovative Systeme for joint developments
-1796 Research Centre Juelich
- 0001 SIS1100 [Gigabit link]
- 0002 HOTlink
- 0003 Counter Timer
- 0004 CAMAC Controller
- 0005 PROFIBUS
- 0006 AMCC HOTlink
-1797 JumpTec h, GMBH
-1799 Belkin
- 6001 Wireless PCI Card - F5D6001
- 6020 Wireless PCMCIA Card - F5D6020
- 6060 Wireless PDA Card - F5D6060
- 7000 Wireless PCI Card - F5D7000
-17a0 Genesys Logic, Inc
- 8033 GL880S USB 1.1 controller
- 8034 GL880S USB 2.0 controller
-17af Hightech Information System Ltd.
-17b3 Hawking Technologies
- ab08 PN672TX 10/100 Ethernet
-17b4 Indra Networks, Inc.
- 0011 WebEnhance 100 GZIP Compression Card
-17c0 Wistron Corp.
-17c2 Newisys, Inc.
-17cc NetChip Technology, Inc
- 2280 USB 2.0
-17d3 Areca Technology Corp.
- 1110 ARC-1110 4-Port PCI-X to SATA RAID Controller
- 1120 ARC-1120 8-Port PCI-X to SATA RAID Controller
- 1130 ARC-1130 12-Port PCI-X to SATA RAID Controller
- 1160 ARC-1160 16-Port PCI-X to SATA RAID Controller
- 1210 ARC-1210 4-Port PCI-Express to SATA RAID Controller
- 1220 ARC-1220 8-Port PCI-Express to SATA RAID Controller
- 1230 ARC-1230 12-Port PCI-Express to SATA RAID Controller
- 1260 ARC-1260 16-Port PCI-Express to SATA RAID Controller
-# S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
-17d5 S2io Inc.
- 5831 Xframe 10 Gigabit Ethernet PCI-X
- 103c 12d5 HP PCI-X 133MHz 10GbE SR Fiber [AB287A]
-17de KWorld Computer Co. Ltd.
-# http://www.connect3d.com
-17ee Connect Components Ltd
-17fe Linksys, A Division of Cisco Systems
- 2120 WMP11v4 802.11b PCI card
- 2220 [AirConn] INPROCOMM IPN 2220 Wireless LAN Adapter (rev 01)
-1813 Ambient Technologies Inc
- 4000 HaM controllerless modem
- 16be 0001 V9x HAM Data Fax Modem
- 4100 HaM plus Data Fax Modem
- 16be 0002 V9x HAM 1394
-1814 RaLink
- 0101 Wireless PCI Adpator RT2400 / RT2460
- 3306 1113 Quidway WL100M
- 0201 Ralink RT2500 802.11 Cardbus Reference Card
- 1371 001e CWC-854 Wireless-G CardBus Adapter
- 1371 001f CWM-854 Wireless-G Mini PCI Adapter
- 1371 0020 CWP-854 Wireless-G PCI Adapter
- 1458 e381 GN-WMKG 802.11b/g Wireless CardBus Adapter
-1820 InfiniCon Systems Inc.
-1822 Twinhan Technology Co. Ltd
-182d SiteCom Europe BV
-# HFC-based ISDN card
- 3069 ISDN PCI DC-105V2
- 9790 WL-121 Wireless Network Adapter 100g+ [Ver.3]
-1830 Credence Systems Corporation
-183b MikroM GmbH
- 08a7 MVC100 DVI
- 08a8 MVC101 SDI
- 08a9 MVC102 DVI+Audio
-1849 ASRock Incorporation
-1851 Microtune, Inc.
-1852 Anritsu Corp.
-185f Wistron NeWeb Corp.
-1867 Topspin Communications
- 5a44 MT23108 PCI-X HCA
- 5a45 MT23108 PCI-X HCA flash recovery
- 5a46 MT23108 PCI-X HCA bridge
- 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
- 6282 MT25208 InfiniHost III Ex
-187e ZyXEL Communication Corporation
-1888 Varisys Ltd
- 0301 VMFX1 FPGA PMC module
- 0601 VSM2 dual PMC carrier
- 0710 VS14x series PowerPC PCI board
- 0720 VS24x series PowerPC PCI board
-# found e.g. on KNC DVB-S card
-1894 KNC One
-1896 B&B Electronics Manufacturing Company, Inc.
-18a1 Astute Networks Inc.
-18ac DViCO Corporation
- d810 FusionHDTV 3 Gold
-18b8 Ammasso
- b001 AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor
-18bc Info-Tek Corp.
-# assigned to Octigabay System, which has been acquired by Cray
-18c8 Cray Inc
-18c9 ARVOO Engineering BV
-18ca XGI - Xabre Graphics Inc
- 0040 Volari V8
-18e6 MPL AG
- 0001 OSCI [Octal Serial Communication Interface]
-18f7 Commtech, Inc.
- 0001 Fastcom ESCC-PCI-335
- 0002 Fastcom 422/4-PCI-335
- 0004 Fastcom 422/2-PCI-335
- 0005 Fastcom IGESCC-PCI-ISO/1
- 000a Fastcom 232/4-PCI-335
-18fb Resilience Corporation
-1924 Level 5 Networks Inc.
-1966 Orad Hi-Tec Systems
- 1975 DVG64 family
-1993 Innominate Security Technologies AG
-# http://www.progeny.net
-19ae Progeny Systems Corporation
-1a08 Sierra semiconductor
- 0000 SC15064
-1b13 Jaton Corp
-1c1c Symphony
- 0001 82C101
-1d44 DPT
- a400 PM2x24/PM3224
-1de1 Tekram Technology Co.,Ltd.
- 0391 TRM-S1040
- 2020 DC-390
- 690c 690c
- dc29 DC290
-1fc0 Tumsan Oy
- 0300 E2200 Dual E1/Rawpipe Card
-2000 Smart Link Ltd.
-2001 Temporal Research Ltd
-2003 Smart Link Ltd.
-2004 Smart Link Ltd.
-21c3 21st Century Computer Corp.
-2348 Racore
- 2010 8142 100VG/AnyLAN
-2646 Kingston Technologies
-270b Xantel Corporation
-270f Chaintech Computer Co. Ltd
-2711 AVID Technology Inc.
-2a15 3D Vision(???)
-3000 Hansol Electronics Inc.
-3142 Post Impression Systems.
-3388 Hint Corp
- 0013 HiNT HC4 PCI to ISDN bridge, Multimedia audio controller
- 0014 HiNT HC4 PCI to ISDN bridge, Network controller
- 0020 HB6 Universal PCI-PCI bridge (transparent mode)
- 0021 HB6 Universal PCI-PCI bridge (non-transparent mode)
- 4c53 1050 CT7 mainboard
- 4c53 1080 CT8 mainboard
- 4c53 10a0 CA3/CR3 mainboard
- 4c53 3010 PPCI mezzanine (32-bit PMC)
- 4c53 3011 PPCI mezzanine (64-bit PMC)
- 0022 HiNT HB4 PCI-PCI Bridge (PCI6150)
- 0026 HB2 PCI-PCI Bridge
- 101a E.Band [AudioTrak Inca88]
- 101b E.Band [AudioTrak Inca88]
- 8011 VXPro II Chipset
- 3388 8011 VXPro II Chipset CPU to PCI Bridge
- 8012 VXPro II Chipset
- 3388 8012 VXPro II Chipset PCI to ISA Bridge
- 8013 VXPro II IDE
- 3388 8013 VXPro II Chipset EIDE Controller
-3411 Quantum Designs (H.K.) Inc
-3513 ARCOM Control Systems Ltd
-3842 eVga.com. Corp.
-38ef 4Links
-3d3d 3DLabs
- 0001 GLINT 300SX
- 0002 GLINT 500TX
- 0003 GLINT Delta
- 0004 Permedia
- 0005 Permedia
- 0006 GLINT MX
- 0007 3D Extreme
- 0008 GLINT Gamma G1
- 0009 Permedia II 2D+3D
- 1040 0011 AccelStar II
- 13e9 1000 6221L-4U
- 3d3d 0100 AccelStar II 3D Accelerator
- 3d3d 0111 Permedia 3:16
- 3d3d 0114 Santa Ana
- 3d3d 0116 Oxygen GVX1
- 3d3d 0119 Scirocco
- 3d3d 0120 Santa Ana PCL
- 3d3d 0125 Oxygen VX1
- 3d3d 0127 Permedia3 Create!
- 000a GLINT R3
- 3d3d 0121 Oxygen VX1
- 000c GLINT R3 [Oxygen VX1]
- 3d3d 0144 Oxygen VX1-4X AGP [Permedia 4]
- 000d GLint R4 rev A
- 0011 GLint R4 rev B
- 0012 GLint R5 rev A
- 0013 GLint R5 rev B
- 0020 VP10 visual processor
-# P10 generic II
- 0022 VP10 visual processor
- 0024 VP9 visual processor
- 0100 Permedia II 2D+3D
- 07a1 Wildcat III 6210
- 07a2 Sun XVR-500 Graphics Accelerator
- 07a3 Wildcat IV 7210
- 1004 Permedia
- 3d04 Permedia
- ffff Glint VGA
-4005 Avance Logic Inc.
- 0300 ALS300 PCI Audio Device
- 0308 ALS300+ PCI Audio Device
- 0309 PCI Input Controller
- 1064 ALG-2064
- 2064 ALG-2064i
- 2128 ALG-2364A GUI Accelerator
- 2301 ALG-2301
- 2302 ALG-2302
- 2303 AVG-2302 GUI Accelerator
- 2364 ALG-2364A
- 2464 ALG-2464
- 2501 ALG-2564A/25128A
- 4000 ALS4000 Audio Chipset
- 4005 4000 ALS4000 Audio Chipset
- 4710 ALC200/200P
-4033 Addtron Technology Co, Inc.
- 1360 RTL8139 Ethernet
-4143 Digital Equipment Corp
-4144 Alpha Data
- 0044 ADM-XRCIIPro
-416c Aladdin Knowledge Systems
- 0100 AladdinCARD
- 0200 CPC
-4444 Internext Compression Inc
- 0016 iTVC16 (CX23416) MPEG-2 Encoder
- 0070 4009 WinTV PVR 250
- 0070 8003 WinTV PVR 150
- 0803 iTVC15 MPEG-2 Encoder
- 0070 4000 WinTV PVR-350
- 0070 4001 WinTV PVR-250
-# video capture card
- 1461 a3cf M179
-4468 Bridgeport machines
-4594 Cogetec Informatique Inc
-45fb Baldor Electric Company
-4680 Umax Computer Corp
-4843 Hercules Computer Technology Inc
-4916 RedCreek Communications Inc
- 1960 RedCreek PCI adapter
-4943 Growth Networks
-494f ACCES I/O Products, Inc.
- 10e8 LPCI-COM-8SM
-4978 Axil Computer Inc
-4a14 NetVin
- 5000 NV5000SC
- 4a14 5000 RT8029-Based Ethernet Adapter
-4b10 Buslogic Inc.
-4c48 LUNG HWA Electronics
-4c53 SBS Technologies
- 0000 PLUSTEST device
- 4c53 3000 PLUSTEST card (PC104+)
- 4c53 3001 PLUSTEST card (PMC)
- 0001 PLUSTEST-MM device
- 4c53 3002 PLUSTEST-MM card (PMC)
-4ca1 Seanix Technology Inc
-4d51 MediaQ Inc.
- 0200 MQ-200
-4d54 Microtechnica Co Ltd
-4ddc ILC Data Device Corp
- 0100 DD-42924I5-300 (ARINC 429 Data Bus)
- 0801 BU-65570I1 MIL-STD-1553 Test and Simulation
- 0802 BU-65570I2 MIL-STD-1553 Test and Simulation
- 0811 BU-65572I1 MIL-STD-1553 Test and Simulation
- 0812 BU-65572I2 MIL-STD-1553 Test and Simulation
- 0881 BU-65570T1 MIL-STD-1553 Test and Simulation
- 0882 BU-65570T2 MIL-STD-1553 Test and Simulation
- 0891 BU-65572T1 MIL-STD-1553 Test and Simulation
- 0892 BU-65572T2 MIL-STD-1553 Test and Simulation
- 0901 BU-65565C1 MIL-STD-1553 Data Bus
- 0902 BU-65565C2 MIL-STD-1553 Data Bus
- 0903 BU-65565C3 MIL-STD-1553 Data Bus
- 0904 BU-65565C4 MIL-STD-1553 Data Bus
- 0b01 BU-65569I1 MIL-STD-1553 Data Bus
- 0b02 BU-65569I2 MIL-STD-1553 Data Bus
- 0b03 BU-65569I3 MIL-STD-1553 Data Bus
- 0b04 BU-65569I4 MIL-STD-1553 Data Bus
-5046 GemTek Technology Corporation
- 1001 PCI Radio
-5053 Voyetra Technologies
- 2010 Daytona Audio Adapter
-5136 S S Technologies
-5143 Qualcomm Inc
-5145 Ensoniq (Old)
- 3031 Concert AudioPCI
-5168 Animation Technologies Inc.
-5301 Alliance Semiconductor Corp.
- 0001 ProMotion aT3D
-5333 S3 Inc.
- 0551 Plato/PX (system)
- 5631 86c325 [ViRGE]
- 8800 86c866 [Vision 866]
- 8801 86c964 [Vision 964]
- 8810 86c764_0 [Trio 32 vers 0]
- 8811 86c764/765 [Trio32/64/64V+]
- 8812 86cM65 [Aurora64V+]
- 8813 86c764_3 [Trio 32/64 vers 3]
- 8814 86c767 [Trio 64UV+]
- 8815 86cM65 [Aurora 128]
- 883d 86c988 [ViRGE/VX]
- 8870 FireGL
- 8880 86c868 [Vision 868 VRAM] vers 0
- 8881 86c868 [Vision 868 VRAM] vers 1
- 8882 86c868 [Vision 868 VRAM] vers 2
- 8883 86c868 [Vision 868 VRAM] vers 3
- 88b0 86c928 [Vision 928 VRAM] vers 0
- 88b1 86c928 [Vision 928 VRAM] vers 1
- 88b2 86c928 [Vision 928 VRAM] vers 2
- 88b3 86c928 [Vision 928 VRAM] vers 3
- 88c0 86c864 [Vision 864 DRAM] vers 0
- 88c1 86c864 [Vision 864 DRAM] vers 1
- 88c2 86c864 [Vision 864-P DRAM] vers 2
- 88c3 86c864 [Vision 864-P DRAM] vers 3
- 88d0 86c964 [Vision 964 VRAM] vers 0
- 88d1 86c964 [Vision 964 VRAM] vers 1
- 88d2 86c964 [Vision 964-P VRAM] vers 2
- 88d3 86c964 [Vision 964-P VRAM] vers 3
- 88f0 86c968 [Vision 968 VRAM] rev 0
- 88f1 86c968 [Vision 968 VRAM] rev 1
- 88f2 86c968 [Vision 968 VRAM] rev 2
- 88f3 86c968 [Vision 968 VRAM] rev 3
- 8900 86c755 [Trio 64V2/DX]
- 5333 8900 86C775 Trio64V2/DX
- 8901 86c775/86c785 [Trio 64V2/DX or /GX]
- 5333 8901 86C775 Trio64V2/DX, 86C785 Trio64V2/GX
- 8902 Plato/PX
- 8903 Trio 3D business multimedia
- 8904 Trio 64 3D
- 1014 00db Integrated Trio3D
- 5333 8904 86C365 Trio3D AGP
- 8905 Trio 64V+ family
- 8906 Trio 64V+ family
- 8907 Trio 64V+ family
- 8908 Trio 64V+ family
- 8909 Trio 64V+ family
- 890a Trio 64V+ family
- 890b Trio 64V+ family
- 890c Trio 64V+ family
- 890d Trio 64V+ family
- 890e Trio 64V+ family
- 890f Trio 64V+ family
- 8a01 ViRGE/DX or /GX
- 0e11 b032 ViRGE/GX
- 10b4 1617 Nitro 3D
- 10b4 1717 Nitro 3D
- 5333 8a01 ViRGE/DX
- 8a10 ViRGE/GX2
- 1092 8a10 Stealth 3D 4000
- 8a13 86c368 [Trio 3D/2X]
- 5333 8a13 Trio3D/2X
- 8a20 86c794 [Savage 3D]
- 5333 8a20 86C391 Savage3D
- 8a21 86c390 [Savage 3D/MV]
- 5333 8a21 86C390 Savage3D/MV
- 8a22 Savage 4
- 1033 8068 Savage 4
- 1033 8069 Savage 4
- 1033 8110 Savage4 LT
- 105d 0018 SR9 8Mb SDRAM
- 105d 002a SR9 Pro 16Mb SDRAM
- 105d 003a SR9 Pro 32Mb SDRAM
- 105d 092f SR9 Pro+ 16Mb SGRAM
- 1092 4207 Stealth III S540
- 1092 4800 Stealth III S540
- 1092 4807 SpeedStar A90
- 1092 4808 Stealth III S540
- 1092 4809 Stealth III S540
- 1092 480e Stealth III S540
- 1092 4904 Stealth III S520
- 1092 4905 SpeedStar A200
- 1092 4a09 Stealth III S540
- 1092 4a0b Stealth III S540 Xtreme
- 1092 4a0f Stealth III S540
- 1092 4e01 Stealth III S540
- 1102 101d 3d Blaster Savage 4
- 1102 101e 3d Blaster Savage 4
- 5333 8100 86C394-397 Savage4 SDRAM 100
- 5333 8110 86C394-397 Savage4 SDRAM 110
- 5333 8125 86C394-397 Savage4 SDRAM 125
- 5333 8143 86C394-397 Savage4 SDRAM 143
- 5333 8a22 86C394-397 Savage4
- 5333 8a2e 86C394-397 Savage4 32bit
- 5333 9125 86C394-397 Savage4 SGRAM 125
- 5333 9143 86C394-397 Savage4 SGRAM 143
- 8a23 Savage 4
- 8a25 ProSavage PM133
- 8a26 ProSavage KM133
- 8c00 ViRGE/M3
- 8c01 ViRGE/MX
- 1179 0001 ViRGE/MX
- 8c02 ViRGE/MX+
- 8c03 ViRGE/MX+MV
- 8c10 86C270-294 Savage/MX-MV
- 8c11 82C270-294 Savage/MX
- 8c12 86C270-294 Savage/IX-MV
- 1014 017f ThinkPad T20
- 1179 0001 86C584 SuperSavage/IXC Toshiba
- 8c13 86C270-294 Savage/IX
- 1179 0001 Magnia Z310
- 8c22 SuperSavage MX/128
- 8c24 SuperSavage MX/64
- 8c26 SuperSavage MX/64C
- 8c2a SuperSavage IX/128 SDR
- 8c2b SuperSavage IX/128 DDR
- 8c2c SuperSavage IX/64 SDR
- 8c2d SuperSavage IX/64 DDR
- 8c2e SuperSavage IX/C SDR
- 1014 01fc ThinkPad T23 (2647-4MG)
- 8c2f SuperSavage IX/C DDR
- 8d01 86C380 [ProSavageDDR K4M266]
- 8d02 VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK)
- 8d03 VT8751 [ProSavageDDR P4M266]
- 8d04 VT8375 [ProSavage8 KM266/KL266]
- 9102 86C410 Savage 2000
- 1092 5932 Viper II Z200
- 1092 5934 Viper II Z200
- 1092 5952 Viper II Z200
- 1092 5954 Viper II Z200
- 1092 5a35 Viper II Z200
- 1092 5a37 Viper II Z200
- 1092 5a55 Viper II Z200
- 1092 5a57 Viper II Z200
- ca00 SonicVibes
-544c Teralogic Inc
- 0350 TL880-based HDTV/ATSC tuner
-5455 Technische University Berlin
- 4458 S5933
-5519 Cnet Technologies, Inc.
-5544 Dunord Technologies
- 0001 I-30xx Scanner Interface
-5555 Genroco, Inc
- 0003 TURBOstor HFP-832 [HiPPI NIC]
-5654 VoiceTronix Pty Ltd
- 3132 OpenSwitch12
-5700 Netpower
-5851 Exacq Technologies
-6356 UltraStor
-6374 c't Magazin für Computertechnik
- 6773 GPPCI
-6409 Logitec Corp.
-6666 Decision Computer International Co.
- 0001 PCCOM4
- 0002 PCCOM8
-7604 O.N. Electronic Co Ltd.
-7bde MIDAC Corporation
-7fed PowerTV
-8008 Quancom Electronic GmbH
- 0010 WDOG1 [PCI-Watchdog 1]
- 0011 PWDOG2 [PCI-Watchdog 2]
-# Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card.
-807d Asustek Computer, Inc.
-8086 Intel Corporation
- 0007 82379AB
- 0008 Extended Express System Support Controller
- 0008 1000 WorldMark 4300 INCA ASIC
- 0039 21145 Fast Ethernet
- 0122 82437FX
- 0309 80303 I/O Processor PCI-to-PCI Bridge
- 030d 80312 I/O Companion Chip PCI-to-PCI Bridge
- 0326 6700/6702PXH I/OxAPIC Interrupt Controller A
- 0327 6700PXH I/OxAPIC Interrupt Controller B
- 0329 6700PXH PCI Express-to-PCI Bridge A
- 032a 6700PXH PCI Express-to-PCI Bridge B
- 032c 6702PXH PCI Express-to-PCI Bridge A
-# A-segment bridge
- 0330 80332 [Dobson] I/O processor
-# A-segment IOAPIC
- 0331 80332 [Dobson] I/O processor
-# B-segment bridge
- 0332 80332 [Dobson] I/O processor
-# B-segment IOAPIC
- 0333 80332 [Dobson] I/O processor
-# Address Translation Unit (ATU)
- 0334 80332 [Dobson] I/O processor
-# PCI-X bridge
- 0335 80331 [Lindsay] I/O processor
-# Address Translation Unit (ATU)
- 0336 80331 [Lindsay] I/O processor
-# A-segment bridge
- 0340 41210 [Lanai] Serial to Parallel PCI Bridge
-# B-segment bridge
- 0341 41210 [Lanai] Serial to Parallel PCI Bridge
- 0482 82375EB/SB PCI to EISA Bridge
- 0483 82424TX/ZX [Saturn] CPU to PCI bridge
- 0484 82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge
- 0486 82425EX/ZX [Aries] PCIset with ISA bridge
- 04a3 82434LX/NX [Mercury/Neptune] Processor to PCI bridge
- 04d0 82437FX [Triton FX]
- 0500 E8870 Processor bus control
- 0501 E8870 Memory controller
-# and registers common to both SPs
- 0502 E8870 Scalability Port 0
-# and global performance monitoring
- 0503 E8870 Scalability Port 1
- 0510 E8870IO Hub Interface Port 0 registers (8-bit compatibility port)
- 0511 E8870IO Hub Interface Port 1 registers
- 0512 E8870IO Hub Interface Port 2 registers
- 0513 E8870IO Hub Interface Port 3 registers
- 0514 E8870IO Hub Interface Port 4 registers
- 0515 E8870IO General SIOH registers
- 0516 E8870IO RAS registers
- 0530 E8870SP Scalability Port 0 registers
- 0531 E8870SP Scalability Port 1 registers
- 0532 E8870SP Scalability Port 2 registers
- 0533 E8870SP Scalability Port 3 registers
- 0534 E8870SP Scalability Port 4 registers
- 0535 E8870SP Scalability Port 5 registers
-# (bi-interleave 0) and global registers that are neither per-port nor per-interleave
- 0536 E8870SP Interleave registers 0 and 1
-# (bi-interleave 1)
- 0537 E8870SP Interleave registers 2 and 3
- 0600 RAID Controller
- 8086 01c1 ICP Vortex GDT8546RZ
- 8086 01f7 SCRU32
-# uninitialized SRCU32 RAID Controller
- 061f 80303 I/O Processor
- 0960 80960RP [i960 RP Microprocessor/Bridge]
- 0962 80960RM [i960RM Bridge]
- 0964 80960RP [i960 RP Microprocessor/Bridge]
- 1000 82542 Gigabit Ethernet Controller
- 0e11 b0df NC1632 Gigabit Ethernet Adapter (1000-SX)
- 0e11 b0e0 NC1633 Gigabit Ethernet Adapter (1000-LX)
- 0e11 b123 NC1634 Gigabit Ethernet Adapter (1000-SX)
- 1014 0119 Netfinity Gigabit Ethernet SX Adapter
- 8086 1000 PRO/1000 Gigabit Server Adapter
- 1001 82543GC Gigabit Ethernet Controller (Fiber)
- 0e11 004a NC6136 Gigabit Server Adapter
- 1014 01ea Netfinity Gigabit Ethernet SX Adapter
- 8086 1002 PRO/1000 F Server Adapter
- 8086 1003 PRO/1000 F Server Adapter
- 1002 Pro 100 LAN+Modem 56 Cardbus II
- 8086 200e Pro 100 LAN+Modem 56 Cardbus II
- 8086 2013 Pro 100 SR Mobile Combo Adapter
- 8086 2017 Pro 100 S Combo Mobile Adapter
- 1004 82543GC Gigabit Ethernet Controller (Copper)
- 0e11 0049 NC7132 Gigabit Upgrade Module
- 0e11 b1a4 NC7131 Gigabit Server Adapter
- 1014 10f2 Gigabit Ethernet Server Adapter
- 8086 1004 PRO/1000 T Server Adapter
- 8086 2004 PRO/1000 T Server Adapter
- 1008 82544EI Gigabit Ethernet Controller (Copper)
- 1014 0269 iSeries 1000/100/10 Ethernet Adapter
- 1028 011c PRO/1000 XT Network Connection
- 8086 1107 PRO/1000 XT Server Adapter
- 8086 2107 PRO/1000 XT Server Adapter
- 8086 2110 PRO/1000 XT Server Adapter
- 8086 3108 PRO/1000 XT Network Connection
- 1009 82544EI Gigabit Ethernet Controller (Fiber)
- 1014 0268 iSeries Gigabit Ethernet Adapter
- 8086 1109 PRO/1000 XF Server Adapter
- 8086 2109 PRO/1000 XF Server Adapter
- 100c 82544GC Gigabit Ethernet Controller (Copper)
- 8086 1112 PRO/1000 T Desktop Adapter
- 8086 2112 PRO/1000 T Desktop Adapter
- 100d 82544GC Gigabit Ethernet Controller (LOM)
- 1028 0123 PRO/1000 XT Network Connection
- 1079 891f 82544GC Based Network Connection
- 4c53 1080 CT8 mainboard
- 8086 110d 82544GC Based Network Connection
- 100e 82540EM Gigabit Ethernet Controller
- 1014 0265 PRO/1000 MT Network Connection
- 1014 0267 PRO/1000 MT Network Connection
- 1014 026a PRO/1000 MT Network Connection
- 1028 002e Optiplex GX260
- 1028 0151 PRO/1000 MT Network Connection
- 107b 8920 PRO/1000 MT Desktop Adapter
- 8086 001e PRO/1000 MT Desktop Adapter
- 8086 002e PRO/1000 MT Desktop Adapter
- 100f 82545EM Gigabit Ethernet Controller (Copper)
- 1014 0269 iSeries 1000/100/10 Ethernet Adapter
- 1014 028e PRO/1000 MT Network Connection
- 8086 1000 PRO/1000 MT Network Connection
- 8086 1001 PRO/1000 MT Server Adapter
- 1010 82546EB Gigabit Ethernet Controller (Copper)
- 1014 027c PRO/1000 MT Dual Port Network Adapter
- 18fb 7872 RESlink-X
- 4c53 1080 CT8 mainboard
- 4c53 10a0 CA3/CR3 mainboard
- 8086 1011 PRO/1000 MT Dual Port Server Adapter
- 8086 101a PRO/1000 MT Dual Port Network Adapter
- 8086 3424 SE7501HG2 Mainboard
- 1011 82545EM Gigabit Ethernet Controller (Fiber)
- 1014 0268 iSeries Gigabit Ethernet Adapter
- 8086 1002 PRO/1000 MF Server Adapter
- 8086 1003 PRO/1000 MF Server Adapter (LX)
- 1012 82546EB Gigabit Ethernet Controller (Fiber)
- 8086 1012 PRO/1000 MF Dual Port Server Adapter
- 1013 82541EI Gigabit Ethernet Controller (Copper)
- 8086 0013 PRO/1000 MT Network Connection
- 8086 1013 IBM ThinkCentre Network Card
- 8086 1113 PRO/1000 MT Desktop Adapter
- 1014 82541ER Gigabit Ethernet Controller
- 1015 82540EM Gigabit Ethernet Controller (LOM)
- 1016 82540EP Gigabit Ethernet Controller (LOM)
- 1014 052c PRO/1000 MT Mobile Connection
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 1016 PRO/1000 MT Mobile Connection
- 1017 82540EP Gigabit Ethernet Controller (LOM)
- 8086 1017 PR0/1000 MT Desktop Connection
-# Update controller name from 82541EP to 82541EI
- 1018 82541EI Gigabit Ethernet Controller
- 8086 1018 PRO/1000 MT Desktop Adapter
- 1019 82547EI Gigabit Ethernet Controller (LOM)
- 1458 1019 GA-8IPE1000 Pro2 motherboard (865PE)
- 1458 e000 Intel Gigabit Ethernet (Kenai II)
- 8086 1019 PRO/1000 CT Desktop Connection
- 8086 301f D865PERL mainboard
- 8086 3427 S875WP1-E mainboard
- 101d 82546EB Gigabit Ethernet Controller
- 8086 1000 PRO/1000 MT Quad Port Server Adapter
- 101e 82540EP Gigabit Ethernet Controller (Mobile)
- 1014 0549 PRO/1000 MT Mobile Connection
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 101e PRO/1000 MT Mobile Connection
- 1026 82545GM Gigabit Ethernet Controller
- 8086 1000 PRO/1000 MT Server Connection
- 8086 1001 PRO/1000 MT Server Adapter
- 8086 1002 PRO/1000 MT Server Adapter
- 8086 1026 PRO/1000 MT Server Connection
- 1027 82545GM Gigabit Ethernet Controller
- 8086 1001 PRO/1000 MF Server Adapter(LX)
- 8086 1002 PRO/1000 MF Server Adapter(LX)
- 8086 1003 PRO/1000 MF Server Adapter(LX)
- 8086 1027 PRO/1000 MF Server Adapter
- 1028 82545GM Gigabit Ethernet Controller
- 8086 1028 PRO/1000 MB Server Adapter
- 1029 82559 Ethernet Controller
- 1030 82559 InBusiness 10/100
- 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller
- 1014 0209 ThinkPad A/T/X Series
- 104d 80e7 Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 107b 5350 EtherExpress PRO/100 VE
- 1179 0001 EtherExpress PRO/100 VE
- 144d c000 EtherExpress PRO/100 VE
- 144d c001 EtherExpress PRO/100 VE
- 144d c003 EtherExpress PRO/100 VE
- 144d c006 vpr Matrix 170B4
- 1032 82801CAM (ICH3) PRO/100 VE Ethernet Controller
- 1033 82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller
- 1034 82801CAM (ICH3) PRO/100 VM Ethernet Controller
- 1035 82801CAM (ICH3)/82562EH (LOM) Ethernet Controller
- 1036 82801CAM (ICH3) 82562EH Ethernet Controller
- 1037 82801CAM (ICH3) Chipset Ethernet Controller
- 1038 82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller
- 1039 82801DB PRO/100 VE (LOM) Ethernet Controller
- 1014 0267 NetVista A30p
- 103a 82801DB PRO/100 VE (CNR) Ethernet Controller
- 103b 82801DB PRO/100 VM (LOM) Ethernet Controller
- 103c 82801DB PRO/100 VM (CNR) Ethernet Controller
- 103d 82801DB PRO/100 VE (MOB) Ethernet Controller
- 103e 82801DB PRO/100 VM (MOB) Ethernet Controller
- 1040 536EP Data Fax Modem
- 16be 1040 V.9X DSP Data Fax Modem
- 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter
- 8086 2527 MIM2000/Centrino
- 1048 PRO/10GbE LR Server Adapter
- 8086 a01f PRO/10GbE LR Server Adapter
- 8086 a11f PRO/10GbE LR Server Adapter
- 1050 82562EZ 10/100 Ethernet Controller
- 1462 728c 865PE Neo2 (MS-6728)
- 1462 758c MS-6758 (875P Neo)
- 8086 3020 D865PERL mainboard
- 8086 3427 S875WP1-E mainboard
- 1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller
- 1059 82551QM Ethernet Controller
-# ICH-6 Component
- 1064 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
-# ICH-6 Component
- 1065 82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller
-# ICH-6 Component
- 1066 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller
-# ICH-6 Component
- 1067 82562 EM/EX/GX - PRO/100 VM Ethernet Controller
-# ICH-6 Component
- 1068 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile
-# ICH-6 Component
- 1069 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile
-# ICH-6 Component
- 106a 82562G \t- PRO/100 VE (LOM) Ethernet Controller
-# ICH-6 Component
- 106b 82562G \t- PRO/100 VE Ethernet Controller Mobile
- 1075 82547GI Gigabit Ethernet Controller
- 1028 0165 PowerEdge 750
- 8086 0075 PRO/1000 CT Network Connection
- 8086 1075 PRO/1000 CT Network Connection
- 1076 82541GI/PI Gigabit Ethernet Controller
- 1028 0165 PowerEdge 750
- 8086 0076 PRO/1000 MT Network Connection
- 8086 1076 PRO/1000 MT Network Connection
- 8086 1176 PRO/1000 MT Desktop Adapter
- 8086 1276 PRO/1000 MT Desktop Adapter
- 1077 82541GI Gigabit Ethernet Controller
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 0077 PRO/1000 MT Mobile Connection
- 8086 1077 PRO/1000 MT Mobile Connection
- 1078 82541EI Gigabit Ethernet Controller
- 8086 1078 PRO/1000 MT Network Connection
- 1079 82546GB Gigabit Ethernet Controller
- 103c 12a6 HP Dual Port 1000Base-T [A9900A]
- 103c 12cf HP Core Dual Port 1000Base-T [AB352A]
- 4c53 1090 Cx9 / Vx9 mainboard
- 4c53 10b0 CL9 mainboard
- 8086 0079 PRO/1000 MT Dual Port Network Connection
- 8086 1079 PRO/1000 MT Dual Port Network Connection
- 8086 1179 PRO/1000 MT Dual Port Network Connection
- 8086 117a PRO/1000 MT Dual Port Server Adapter
- 107a 82546GB Gigabit Ethernet Controller
- 103c 12a8 HP Dual Port 1000base-SX [A9899A]
- 8086 107a PRO/1000 MF Dual Port Server Adapter
- 8086 127a PRO/1000 MF Dual Port Server Adapter
- 107b 82546GB Gigabit Ethernet Controller
- 8086 007b PRO/1000 MB Dual Port Server Connection
- 8086 107b PRO/1000 MB Dual Port Server Connection
- 1107 PRO/1000 MF Server Adapter (LX)
- 1130 82815 815 Chipset Host Bridge and Memory Controller Hub
- 1025 1016 Travelmate 612 TX
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 1131 82815 815 Chipset AGP Bridge
- 1132 82815 CGC [Chipset Graphics Controller]
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 Mainboard
- 8086 4557 D815EGEW Mainboard
- 1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller
- 8086 1161 82806AA PCI64 Hub APIC
- 1162 Xscale 80200 Big Endian Companion Chip
- 1200 Intel IXP1200 Network Processor
- 172a 0000 AEP SSL Accelerator
- 1209 8255xER/82551IT Fast Ethernet Controller
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 4c53 1070 PC6 mainboard
- 1221 82092AA PCI to PCMCIA Bridge
- 1222 82092AA IDE Controller
- 1223 SAA7116
- 1225 82452KX/GX [Orion]
- 1226 82596 PRO/10 PCI
- 1227 82865 EtherExpress PRO/100A
- 1228 82556 EtherExpress PRO/100 Smart
-# the revision field differentiates between them (1-3 is 82557, 4-5 is 82558, 6-8 is 82559, 9 is 82559ER)
- 1229 82557/8/9 [Ethernet Pro 100]
- 0e11 3001 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3002 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3003 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3004 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3005 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3006 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3007 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 b01e NC3120 Fast Ethernet NIC
- 0e11 b01f NC3122 Fast Ethernet NIC (dual port)
- 0e11 b02f NC1120 Ethernet NIC
- 0e11 b04a Netelligent 10/100TX NIC with Wake on LAN
- 0e11 b0c6 NC3161 Fast Ethernet NIC (embedded, WOL)
- 0e11 b0c7 NC3160 Fast Ethernet NIC (embedded)
- 0e11 b0d7 NC3121 Fast Ethernet NIC (WOL)
- 0e11 b0dd NC3131 Fast Ethernet NIC (dual port)
- 0e11 b0de NC3132 Fast Ethernet Module (dual port)
- 0e11 b0e1 NC3133 Fast Ethernet Module (100-FX)
- 0e11 b134 NC3163 Fast Ethernet NIC (embedded, WOL)
- 0e11 b13c NC3162 Fast Ethernet NIC (embedded)
- 0e11 b144 NC3123 Fast Ethernet NIC (WOL)
- 0e11 b163 NC3134 Fast Ethernet NIC (dual port)
- 0e11 b164 NC3135 Fast Ethernet Upgrade Module (dual port)
- 0e11 b1a4 NC7131 Gigabit Server Adapter
- 1014 005c 82558B Ethernet Pro 10/100
- 1014 01bc 82559 Fast Ethernet LAN On Motherboard
- 1014 01f1 10/100 Ethernet Server Adapter
- 1014 01f2 10/100 Ethernet Server Adapter
- 1014 0207 Ethernet Pro/100 S
- 1014 0232 10/100 Dual Port Server Adapter
- 1014 023a ThinkPad R30
- 1014 105c Netfinity 10/100
- 1014 2205 ThinkPad A22p
- 1014 305c 10/100 EtherJet Management Adapter
- 1014 405c 10/100 EtherJet Adapter with Alert on LAN
- 1014 505c 10/100 EtherJet Secure Management Adapter
- 1014 605c 10/100 EtherJet Secure Management Adapter
- 1014 705c 10/100 Netfinity 10/100 Ethernet Security Adapter
- 1014 805c 10/100 Netfinity 10/100 Ethernet Security Adapter
- 1028 009b PowerEdge 2500/2550
- 1028 00ce PowerEdge 1400
- 1033 8000 PC-9821X-B06
- 1033 8016 PK-UG-X006
- 1033 801f PK-UG-X006
- 1033 8026 PK-UG-X006
- 1033 8063 82559-based Fast Ethernet Adapter
- 1033 8064 82559-based Fast Ethernet Adapter
- 103c 10c0 NetServer 10/100TX
- 103c 10c3 NetServer 10/100TX
- 103c 10ca NetServer 10/100TX
- 103c 10cb NetServer 10/100TX
- 103c 10e3 NetServer 10/100TX
- 103c 10e4 NetServer 10/100TX
- 103c 1200 NetServer 10/100TX
- 10c3 1100 SmartEther100 SC1100
- 10cf 1115 8255x-based Ethernet Adapter (10/100)
- 10cf 1143 8255x-based Ethernet Adapter (10/100)
- 1179 0001 8255x-based Ethernet Adapter (10/100)
- 1179 0002 PCI FastEther LAN on Docker
- 1179 0003 8255x-based Fast Ethernet
- 1259 2560 AT-2560 100
- 1259 2561 AT-2560 100 FX Ethernet Adapter
- 1266 0001 NE10/100 Adapter
- 13e9 1000 6221L-4U
- 144d 2501 SEM-2000 MiniPCI LAN Adapter
- 144d 2502 SEM-2100IL MiniPCI LAN Adapter
- 1668 1100 EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)
- 4c53 1080 CT8 mainboard
- 8086 0001 EtherExpress PRO/100B (TX)
- 8086 0002 EtherExpress PRO/100B (T4)
- 8086 0003 EtherExpress PRO/10+
- 8086 0004 EtherExpress PRO/100 WfM
- 8086 0005 82557 10/100
- 8086 0006 82557 10/100 with Wake on LAN
- 8086 0007 82558 10/100 Adapter
- 8086 0008 82558 10/100 with Wake on LAN
- 8086 0009 EtherExpress PRO/100+
- 8086 000a EtherExpress PRO/100+ Management Adapter
- 8086 000b EtherExpress PRO/100+
- 8086 000c EtherExpress PRO/100+ Management Adapter
- 8086 000d EtherExpress PRO/100+ Alert On LAN II* Adapter
- 8086 000e EtherExpress PRO/100+ Management Adapter with Alert On LAN*
- 8086 000f EtherExpress PRO/100 Desktop Adapter
- 8086 0010 EtherExpress PRO/100 S Management Adapter
- 8086 0011 EtherExpress PRO/100 S Management Adapter
- 8086 0012 EtherExpress PRO/100 S Advanced Management Adapter (D)
- 8086 0013 EtherExpress PRO/100 S Advanced Management Adapter (E)
- 8086 0030 EtherExpress PRO/100 Management Adapter with Alert On LAN* GC
- 8086 0031 EtherExpress PRO/100 Desktop Adapter
- 8086 0040 EtherExpress PRO/100 S Desktop Adapter
- 8086 0041 EtherExpress PRO/100 S Desktop Adapter
- 8086 0042 EtherExpress PRO/100 Desktop Adapter
- 8086 0050 EtherExpress PRO/100 S Desktop Adapter
- 8086 1009 EtherExpress PRO/100+ Server Adapter
- 8086 100c EtherExpress PRO/100+ Server Adapter (PILA8470B)
- 8086 1012 EtherExpress PRO/100 S Server Adapter (D)
- 8086 1013 EtherExpress PRO/100 S Server Adapter (E)
- 8086 1015 EtherExpress PRO/100 S Dual Port Server Adapter
- 8086 1017 EtherExpress PRO/100+ Dual Port Server Adapter
- 8086 1030 EtherExpress PRO/100+ Management Adapter with Alert On LAN* G Server
- 8086 1040 EtherExpress PRO/100 S Server Adapter
- 8086 1041 EtherExpress PRO/100 S Server Adapter
- 8086 1042 EtherExpress PRO/100 Server Adapter
- 8086 1050 EtherExpress PRO/100 S Server Adapter
- 8086 1051 EtherExpress PRO/100 Server Adapter
- 8086 1052 EtherExpress PRO/100 Server Adapter
- 8086 10f0 EtherExpress PRO/100+ Dual Port Adapter
- 8086 2009 EtherExpress PRO/100 S Mobile Adapter
- 8086 200d EtherExpress PRO/100 Cardbus
- 8086 200e EtherExpress PRO/100 LAN+V90 Cardbus Modem
- 8086 200f EtherExpress PRO/100 SR Mobile Adapter
- 8086 2010 EtherExpress PRO/100 S Mobile Combo Adapter
- 8086 2013 EtherExpress PRO/100 SR Mobile Combo Adapter
- 8086 2016 EtherExpress PRO/100 S Mobile Adapter
- 8086 2017 EtherExpress PRO/100 S Combo Mobile Adapter
- 8086 2018 EtherExpress PRO/100 SR Mobile Adapter
- 8086 2019 EtherExpress PRO/100 SR Combo Mobile Adapter
- 8086 2101 EtherExpress PRO/100 P Mobile Adapter
- 8086 2102 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2103 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2104 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2105 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2106 EtherExpress PRO/100 P Mobile Adapter
- 8086 2107 EtherExpress PRO/100 Network Connection
- 8086 2108 EtherExpress PRO/100 Network Connection
- 8086 2200 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2201 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2202 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2203 EtherExpress PRO/100+ MiniPCI
- 8086 2204 EtherExpress PRO/100+ MiniPCI
- 8086 2205 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2206 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2207 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2208 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2402 EtherExpress PRO/100+ MiniPCI
- 8086 2407 EtherExpress PRO/100+ MiniPCI
- 8086 2408 EtherExpress PRO/100+ MiniPCI
- 8086 2409 EtherExpress PRO/100+ MiniPCI
- 8086 240f EtherExpress PRO/100+ MiniPCI
- 8086 2410 EtherExpress PRO/100+ MiniPCI
- 8086 2411 EtherExpress PRO/100+ MiniPCI
- 8086 2412 EtherExpress PRO/100+ MiniPCI
- 8086 2413 EtherExpress PRO/100+ MiniPCI
- 8086 3000 82559 Fast Ethernet LAN on Motherboard
- 8086 3001 82559 Fast Ethernet LOM with Basic Alert on LAN*
- 8086 3002 82559 Fast Ethernet LOM with Alert on LAN II*
- 8086 3006 EtherExpress PRO/100 S Network Connection
- 8086 3007 EtherExpress PRO/100 S Network Connection
- 8086 3008 EtherExpress PRO/100 Network Connection
- 8086 3010 EtherExpress PRO/100 S Network Connection
- 8086 3011 EtherExpress PRO/100 S Network Connection
- 8086 3012 EtherExpress PRO/100 Network Connection
- 8086 3411 SDS2 Mainboard
- 122d 430FX - 82437FX TSC [Triton I]
- 122e 82371FB PIIX ISA [Triton I]
- 1230 82371FB PIIX IDE [Triton I]
- 1231 DSVD Modem
- 1234 430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)
- 1235 430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP)
- 1237 440FX - 82441FX PMC [Natoma]
- 1239 82371FB PIIX IDE Interface
- 123b 82380PB PCI to PCI Docking Bridge
- 123c 82380AB (MISA) Mobile PCI-to-ISA Bridge
- 123d 683053 Programmable Interrupt Device
-# in" hidden" mode
- 123e 82466GX (IHPC) Integrated Hot-Plug Controller
- 123f 82466GX Integrated Hot-Plug Controller (IHPC)
- 1240 82752 (752) AGP Graphics Accelerator
- 124b 82380FB (MPCI2) Mobile Docking Controller
- 1250 430HX - 82439HX TXC [Triton II]
- 1360 82806AA PCI64 Hub PCI Bridge
- 1361 82806AA PCI64 Hub Controller (HRes)
- 8086 1361 82806AA PCI64 Hub Controller (HRes)
- 8086 8000 82806AA PCI64 Hub Controller (HRes)
- 1460 82870P2 P64H2 Hub PCI Bridge
- 1461 82870P2 P64H2 I/OxAPIC
- 15d9 3480 P4DP6
- 4c53 1090 Cx9 / Vx9 mainboard
- 1462 82870P2 P64H2 Hot Plug Controller
- 1960 80960RP [i960RP Microprocessor]
- 101e 0431 MegaRAID 431 RAID Controller
- 101e 0438 MegaRAID 438 Ultra2 LVD RAID Controller
- 101e 0466 MegaRAID 466 Express Plus RAID Controller
- 101e 0467 MegaRAID 467 Enterprise 1500 RAID Controller
- 101e 0490 MegaRAID 490 Express 300 RAID Controller
- 101e 0762 MegaRAID 762 Express RAID Controller
- 101e 09a0 PowerEdge Expandable RAID Controller 2/SC
- 1028 0467 PowerEdge Expandable RAID Controller 2/DC
- 1028 1111 PowerEdge Expandable RAID Controller 2/SC
- 103c 03a2 MegaRAID
- 103c 10c6 MegaRAID 438, HP NetRAID-3Si
- 103c 10c7 MegaRAID T5, Integrated HP NetRAID
- 103c 10cc MegaRAID, Integrated HP NetRAID
- 103c 10cd HP NetRAID-1Si
- 105a 0000 SuperTrak
- 105a 2168 SuperTrak Pro
- 105a 5168 SuperTrak66/100
- 1111 1111 MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC
- 1111 1112 PowerEdge Expandable RAID Controller 2/SC
- 113c 03a2 MegaRAID
- e4bf 1010 CG1-RADIO
- e4bf 1020 CU2-QUARTET
- e4bf 1040 CU1-CHORUS
- e4bf 3100 CX1-BAND
- 1962 80960RM [i960RM Microprocessor]
- 105a 0000 SuperTrak SX6000 I2O CPU
- 1a21 82840 840 (Carmel) Chipset Host Bridge (Hub A)
- 1a23 82840 840 (Carmel) Chipset AGP Bridge
- 1a24 82840 840 (Carmel) Chipset PCI Bridge (Hub B)
- 1a30 82845 845 (Brookdale) Chipset Host Bridge
- 1028 010e Optiplex GX240
- 1a31 82845 845 (Brookdale) Chipset AGP Bridge
- 2410 82801AA ISA Bridge (LPC)
- 2411 82801AA IDE
- 2412 82801AA USB
- 2413 82801AA SMBus
- 2415 82801AA AC'97 Audio
- 1028 0095 Precision Workstation 220 Integrated Digital Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 11d4 5340 SoundMAX Integrated Digital Audio
- 2416 82801AA AC'97 Modem
- 2418 82801AA PCI Bridge
- 2420 82801AB ISA Bridge (LPC)
- 2421 82801AB IDE
- 2422 82801AB USB
- 2423 82801AB SMBus
- 2425 82801AB AC'97 Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 2426 82801AB AC'97 Modem
- 2428 82801AB PCI Bridge
- 2440 82801BA ISA Bridge (LPC)
- 2442 82801BA/BAM USB (Hub #1)
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 2443 82801BA/BAM SMBus
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 2444 82801BA/BAM USB (Hub #2)
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 2445 82801BA/BAM AC'97 Audio
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 1462 3370 STAC9721 AC
- 147b 0507 TH7II-RAID
- 8086 4557 D815EGEW Mainboard
- 2446 82801BA/BAM AC'97 Modem
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 2448 82801 Mobile PCI Bridge
- 2449 82801BA/BAM/CA/CAM Ethernet Controller
- 0e11 0012 EtherExpress PRO/100 VM
- 0e11 0091 EtherExpress PRO/100 VE
- 1014 01ce EtherExpress PRO/100 VE
- 1014 01dc EtherExpress PRO/100 VE
- 1014 01eb EtherExpress PRO/100 VE
- 1014 01ec EtherExpress PRO/100 VE
- 1014 0202 EtherExpress PRO/100 VE
- 1014 0205 EtherExpress PRO/100 VE
- 1014 0217 EtherExpress PRO/100 VE
- 1014 0234 EtherExpress PRO/100 VE
- 1014 023d EtherExpress PRO/100 VE
- 1014 0244 EtherExpress PRO/100 VE
- 1014 0245 EtherExpress PRO/100 VE
- 1014 0265 PRO/100 VE Desktop Connection
- 1014 0267 PRO/100 VE Desktop Connection
- 1014 026a PRO/100 VE Desktop Connection
- 109f 315d EtherExpress PRO/100 VE
- 109f 3181 EtherExpress PRO/100 VE
- 1179 ff01 PRO/100 VE Network Connection
- 1186 7801 EtherExpress PRO/100 VE
- 144d 2602 HomePNA 1M CNR
- 8086 3010 EtherExpress PRO/100 VE
- 8086 3011 EtherExpress PRO/100 VM
- 8086 3012 82562EH based Phoneline
- 8086 3013 EtherExpress PRO/100 VE
- 8086 3014 EtherExpress PRO/100 VM
- 8086 3015 82562EH based Phoneline
- 8086 3016 EtherExpress PRO/100 P Mobile Combo
- 8086 3017 EtherExpress PRO/100 P Mobile
- 8086 3018 EtherExpress PRO/100
- 244a 82801BAM IDE U100
- 1025 1016 Travelmate 612TX
- 104d 80df Vaio PCG-FX403
- 244b 82801BA IDE U100
- 1014 01c6 Netvista A40/A40p
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 244c 82801BAM ISA Bridge (LPC)
- 244e 82801 PCI Bridge
- 1014 0267 NetVista A30p
- 2450 82801E ISA Bridge (LPC)
- 2452 82801E USB
- 2453 82801E SMBus
- 2459 82801E Ethernet Controller 0
- 245b 82801E IDE U100
- 245d 82801E Ethernet Controller 1
- 245e 82801E PCI Bridge
- 2480 82801CA LPC Interface Controller
- 2482 82801CA/CAM USB (Hub #1)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 8086 3424 SE7501HG2 Mainboard
- 8086 4541 Latitude C640
- 2483 82801CA/CAM SMBus Controller
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 2484 82801CA/CAM USB (Hub #2)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 2485 82801CA/CAM AC'97 Audio Controller
- 1013 5959 Crystal WMD Audio Codec
- 1014 0222 ThinkPad T23 (2647-4MG) or A30/A30p (2652/2653)
- 1014 0508 ThinkPad T30
- 1014 051c ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 144d c006 vpr Matrix 170B4
- 2486 82801CA/CAM AC'97 Modem Controller
- 1014 0223 ThinkPad A/T/X Series
- 1014 0503 ThinkPad R31 2656BBG
- 1014 051a ThinkPad A/T/X Series
- 101f 1025 Acer 620 Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 1179 0001 Toshiba Satellite 1110 Z15 internal Modem
- 134d 4c21 Dell Inspiron 2100 internal modem
- 144d 2115 vpr Matrix 170B4 internal modem
- 14f1 5421 MD56ORD V.92 MDC Modem
- 2487 82801CA/CAM USB (Hub #3)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 248a 82801CAM IDE U100
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 8086 1958 vpr Matrix 170B4
- 8086 4541 Latitude C640
- 248b 82801CA Ultra ATA Storage Controller
- 15d9 3480 P4DP6
- 248c 82801CAM ISA Bridge (LPC)
- 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge
- 1014 0267 NetVista A30p
- 1462 5800 845PE Max (MS-6580)
- 24c1 82801DBL (ICH4-L) IDE Controller
- 24c2 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H laptop
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c3 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1458 24c2 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c4 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c5 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
- 0e11 00b8 Analog Devices Inc. codec [SoundMAX]
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1458 a002 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 24c7 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24ca 82801DBM (ICH4-M) IDE Controller
- 1025 005a TravelMate 290
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 24cb 82801DB (ICH4) IDE Controller
- 1014 0267 NetVista A30p
- 1028 0126 Optiplex GX260
- 1458 24c2 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 4c53 1090 Cx9 / Vx9 mainboard
- 24cc 82801DBM (ICH4-M) LPC Interface Bridge
- 24cd 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 3981 845PE Max (MS-6580)
- 1509 1968 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24d0 82801EB/ER (ICH5/ICH5R) LPC Interface Bridge
- 24d1 82801EB (ICH5) SATA Controller
- 103c 12bc d530 CMT (DG746A)
- 1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000/8KNXP motherboard
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
- 103c 12bc Analog Devices codec [SoundMAX Integrated Digital Audio]
- 1043 80f3 P4P800 Mainboard
-# Again, I suppose they use the same in different subsystems
- 1458 a002 GA-8IPE1000/8KNXP motherboard
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 a000 D865PERL mainboard
- 8086 e000 D865PERL mainboard
- 24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller
- 24d7 82801EB/ER (ICH5/ICH5R) USB UHCI #3
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24db 82801EB/ER (ICH5/ICH5R) IDE Controller
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 1462 7580 MSI 875P
- 8086 24db P4C800 Mainboard
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24dc 82801EB (ICH5) LPC Interface Bridge
- 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 5006 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24de 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24df 82801ER (ICH5R) SATA Controller
- 2500 82820 820 (Camino) Chipset Host Bridge (MCH)
- 1028 0095 Precision Workstation 220 Chipset
- 1043 801c P3C-2000 system chipset
- 2501 82820 820 (Camino) Chipset Host Bridge (MCH)
- 1043 801c P3C-2000 system chipset
- 250b 82820 820 (Camino) Chipset Host Bridge
- 250f 82820 820 (Camino) Chipset AGP Bridge
- 2520 82805AA MTH Memory Translator Hub
- 2521 82804AA MRH-S Memory Repeater Hub for SDRAM
- 2530 82850 850 (Tehama) Chipset Host Bridge (MCH)
- 147b 0507 TH7II-RAID
- 2531 82860 860 (Wombat) Chipset Host Bridge (MCH)
- 2532 82850 850 (Tehama) Chipset AGP Bridge
- 2533 82860 860 (Wombat) Chipset AGP Bridge
- 2534 82860 860 (Wombat) Chipset PCI Bridge
- 2540 E7500 Memory Controller Hub
- 15d9 3480 P4DP6
- 2541 E7500/E7501 Host RASUM Controller
- 15d9 3480 P4DP6
- 4c53 1090 Cx9 / Vx9 mainboard
- 8086 3424 SE7501HG2 Mainboard
- 2543 E7500/E7501 Hub Interface B PCI-to-PCI Bridge
- 2544 E7500/E7501 Hub Interface B RASUM Controller
- 4c53 1090 Cx9 / Vx9 mainboard
- 2545 E7500/E7501 Hub Interface C PCI-to-PCI Bridge
- 2546 E7500/E7501 Hub Interface C RASUM Controller
- 2547 E7500/E7501 Hub Interface D PCI-to-PCI Bridge
- 2548 E7500/E7501 Hub Interface D RASUM Controller
- 254c E7501 Memory Controller Hub
- 4c53 1090 Cx9 / Vx9 mainboard
- 8086 3424 SE7501HG2 Mainboard
- 2550 E7505 Memory Controller Hub
- 2551 E7505/E7205 Series RAS Controller
- 2552 E7505/E7205 PCI-to-AGP Bridge
- 2553 E7505 Hub Interface B PCI-to-PCI Bridge
- 2554 E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
- 255d E7205 Memory Controller Hub
- 2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
- 1028 0126 Optiplex GX260
- 1458 2560 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 2561 82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge
- 2562 82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device
- 1014 0267 NetVista A30p
- 2570 82865G/PE/P DRAM Controller/Host-Hub Interface
- 1043 80f2 P4P800 Mainboard
- 1458 2570 GA-8IPE1000 Pro2 motherboard (865PE)
- 2571 82865G/PE/P PCI to AGP Controller
- 2572 82865G Integrated Graphics Controller
- 2573 82865G/PE/P PCI to CSA Bridge
- 2576 82865G/PE/P Processor to I/O Memory Interface
- 2578 82875P/E7210 Memory Controller Hub
- 1458 2578 GA-8KNXP motherboard (875P)
- 1462 7580 MS-6758 (875P Neo)
-# Motherboard P4SCE
- 15d9 4580 Super Micro Computer Inc. P4SCE
- 2579 82875P Processor to AGP Controller
- 257b 82875P/E7210 Processor to PCI to CSA Bridge
- 257e 82875P/E7210 Processor to I/O Memory Interface
- 2580 915G/P/GV/GL/PL/910GL Processor to I/O Controller
- 2581 915G/P/GV/GL/PL/910GL PCI Express Root Port
- 2582 82915G/GV/910GL Express Chipset Family Graphics Controller
- 1028 1079 Optiplex GX280
- 2584 925X/XE Memory Controller Hub
- 2585 925X/XE PCI Express Root Port
- 2588 E7220/E7221 Memory Controller Hub
- 2589 E7220/E7221 PCI Express Root Port
- 258a E7221 Integrated Graphics Controller
- 2590 Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller
- 2591 Mobile 915GM/PM Express PCI Express Root Port
- 2592 Mobile 915GM/GMS/910GML Express Graphics Controller
- 25a1 6300ESB LPC Interface Controller
- 25a2 6300ESB PATA Storage Controller
- 4c53 10b0 CL9 mainboard
- 25a3 6300ESB SATA Storage Controller
- 4c53 10b0 CL9 mainboard
- 25a4 6300ESB SMBus Controller
- 4c53 10b0 CL9 mainboard
- 25a6 6300ESB AC'97 Audio Controller
- 4c53 10b0 CL9 mainboard
- 25a7 6300ESB AC'97 Modem Controller
- 25a9 6300ESB USB Universal Host Controller
- 4c53 10b0 CL9 mainboard
- 25aa 6300ESB USB Universal Host Controller
- 4c53 10b0 CL9 mainboard
- 25ab 6300ESB Watchdog Timer
- 4c53 10b0 CL9 mainboard
- 25ac 6300ESB I/O Advanced Programmable Interrupt Controller
- 4c53 10b0 CL9 mainboard
- 25ad 6300ESB USB2 Enhanced Host Controller
- 25ae 6300ESB 64-bit PCI-X Bridge
- 25b0 6300ESB SATA RAID Controller
- 2600 E8500 Hub Interface
- 2601 E8500 PCI Express x4 Port D
- 2602 E8500 PCI Express x4 Port C0
- 2603 E8500 PCI Express x4 Port C1
- 2604 E8500 PCI Express x4 Port B0
- 2605 E8500 PCI Express x4 Port B1
- 2606 E8500 PCI Express x4 Port A0
- 2607 E8500 PCI Express x4 Port A1
- 2608 E8500 PCI Express x8 Port C
- 2609 E8500 PCI Express x8 Port B
- 260a E8500 PCI Express x8 Port A
- 260c E8500 IMI Registers
- 2610 E8500 System Bus, Boot, and Interrupt Registers
- 2611 E8500 Address Mapping Registers
- 2612 E8500 RAS Registers
- 2613 E8500 Reserved Registers
- 2614 E8500 Reserved Registers
- 2615 E8500 Miscellaneous Registers
- 2617 E8500 Reserved Registers
- 2618 E8500 Reserved Registers
- 2619 E8500 Reserved Registers
- 261a E8500 Reserved Registers
- 261b E8500 Reserved Registers
- 261c E8500 Reserved Registers
- 261d E8500 Reserved Registers
- 261e E8500 Reserved Registers
- 2620 E8500 eXternal Memory Bridge
- 2621 E8500 XMB Miscellaneous Registers
- 2622 E8500 XMB Memory Interleaving Registers
- 2623 E8500 XMB DDR Initialization and Calibration
- 2624 E8500 XMB Reserved Registers
- 2625 E8500 XMB Reserved Registers
- 2626 E8500 XMB Reserved Registers
- 2627 E8500 XMB Reserved Registers
- 2640 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge
- 2641 82801FBM (ICH6M) LPC Interface Bridge
- 2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
- 2651 82801FB/FW (ICH6/ICH6W) SATA Controller
- 1028 0179 Optiplex GX280
- 2652 82801FR/FRW (ICH6R/ICH6RW) SATA Controller
- 2653 82801FBM (ICH6M) SATA Controller
- 2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
- 1028 0179 Optiplex GX280
- 2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
- 1028 0179 Optiplex GX280
- 265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
- 1028 0179 Optiplex GX280
- 265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
- 1028 0179 Optiplex GX280
- 265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
- 1028 0179 Optiplex GX280
- 2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
- 2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
- 2664 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
- 2666 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
- 2668 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
- 266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
- 1028 0179 Optiplex GX280
- 266c 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
- 266d 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
- 266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
- 1028 0179 Optiplex GX280
- 266f 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
- 2770 Memory Controller Hub
- 2771 PCI Express Graphics Port
- 2772 Integrated Graphics Controller
- 2774 Workstation Memory Controller Hub
- 2775 PCI Express Graphics Port
- 2776 Integrated Graphics Controller
- 2778 Server Memory Controller Hub
- 2779 PCI Express Root Port
- 2782 82915G Express Chipset Family Graphics Controller
- 2792 Mobile 915GM/GMS/910GML Express Graphics Controller
- 27b8 I/O Controller Hub LPC
- 27b9 Mobile I/O Controller Hub LPC
- 27c0 I/O Controller Hub SATA cc=IDE
- 27c1 I/O Controller Hub SATA cc=AHCI
- 27c3 I/O Controller Hub SATA cc=RAID
- 27c4 Mobile I/O Controller Hub SATA cc=IDE
- 27c5 Mobile I/O Controller Hub SATA cc=AHCI
- 27c8 I/O Controller Hub UHCI USB #1
- 27c9 I/O Controller Hub UHCI USB #2
- 27ca I/O Controller Hub UHCI USB #3
- 27cb I/O Controller Hub UHCI USB #4
- 27cc I/O Controller Hub EHCI USB
- 27d0 I/O Controller Hub PCI Express Port 1
- 27d2 I/O Controller Hub PCI Express Port 2
- 27d4 I/O Controller Hub PCI Express Port 3
- 27d6 I/O Controller Hub PCI Express Port 4
- 27d8 I/O Controller Hub High Definition Audio
- 27da I/O Controller Hub SMBus
- 27dc I/O Controller Hub LAN
- 27dd I/O Controller Hub AC'97 Modem
- 27de I/O Controller Hub AC'97 Audio
- 27df I/O Controller Hub PATA
- 27e0 I/O Controller Hub PCI Express Port 5
- 27e2 I/O Controller Hub PCI Express Port 6
- 3092 Integrated RAID
- 3200 GD31244 PCI-X SATA HBA
- 3340 82855PM Processor to I/O Controller
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 3341 82855PM Processor to AGP Controller
- 3575 82830 830 Chipset Host Bridge
- 1014 021d ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 3576 82830 830 Chipset AGP Bridge
- 3577 82830 CGC [Chipset Graphics Controller]
- 1014 0513 ThinkPad A/T/X Series
- 3578 82830 830 Chipset Host Bridge
- 3580 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3581 82852/82855 GM/GME/PM/GMV Processor to AGP Controller
- 3582 82852/855GM Integrated Graphics Device
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3584 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3585 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3590 E7520 Memory Controller Hub
- 3591 E7525/E7520 Error Reporting Registers
- 3592 E7320 Memory Controller Hub
- 3593 E7320 Error Reporting Registers
- 3594 E7520 DMA Controller
- 3595 E7525/E7520/E7320 PCI Express Port A
- 3596 E7525/E7520/E7320 PCI Express Port A1
- 3597 E7525/E7520 PCI Express Port B
- 3598 E7520 PCI Express Port B1
- 3599 E7520 PCI Express Port C
- 359a E7520 PCI Express Port C1
- 359b E7525/E7520/E7320 Extended Configuration Registers
- 359e E7525 Memory Controller Hub
- 4220 PRO/Wireless 2200BG
- 4223 PRO/Wireless 2915ABG MiniPCI Adapter
- 5200 EtherExpress PRO/100 Intelligent Server
- 5201 EtherExpress PRO/100 Intelligent Server
- 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter
- 530d 80310 IOP [IO Processor]
- 7000 82371SB PIIX3 ISA [Natoma/Triton II]
- 7010 82371SB PIIX3 IDE [Natoma/Triton II]
- 7020 82371SB PIIX3 USB [Natoma/Triton II]
- 7030 430VX - 82437VX TVX [Triton VX]
- 7050 Intel Intercast Video Capture Card
- 7100 430TX - 82439TX MTXC
- 7110 82371AB/EB/MB PIIX4 ISA
- 15ad 1976 virtualHW v3
- 7111 82371AB/EB/MB PIIX4 IDE
- 15ad 1976 virtualHW v3
- 7112 82371AB/EB/MB PIIX4 USB
- 15ad 1976 virtualHW v3
- 7113 82371AB/EB/MB PIIX4 ACPI
- 15ad 1976 virtualHW v3
- 7120 82810 GMCH [Graphics Memory Controller Hub]
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 7121 82810 CGC [Chipset Graphics Controller]
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 8086 4341 Cayman (CA810) Mainboard
- 7122 82810 DC-100 GMCH [Graphics Memory Controller Hub]
- 7123 82810 DC-100 CGC [Chipset Graphics Controller]
- 7124 82810E DC-133 GMCH [Graphics Memory Controller Hub]
- 7125 82810E DC-133 CGC [Chipset Graphics Controller]
- 7126 82810 DC-133 System and Graphics Controller
- 7128 82810-M DC-100 System and Graphics Controller
- 712a 82810-M DC-133 System and Graphics Controller
- 7180 440LX/EX - 82443LX/EX Host bridge
- 7181 440LX/EX - 82443LX/EX AGP bridge
- 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge
- 0e11 0500 Armada 1750 Laptop System Chipset
- 0e11 b110 Armada M700/E500
- 1179 0001 Toshiba Tecra 8100 Laptop System Chipset
- 15ad 1976 virtualHW v3
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge
- 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled)
- 0e11 0460 Armada 1700 Laptop System Chipset
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 7194 82440MX Host Bridge
- 1033 0000 Versa Note Vxi
- 4c53 10a0 CA3/CR3 mainboard
- 7195 82440MX AC'97 Audio Controller
- 1033 80cc Versa Note VXi
- 10cf 1099 QSound_SigmaTel Stac97 PCI Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 7196 82440MX AC'97 Modem Controller
- 7198 82440MX ISA Bridge
- 7199 82440MX EIDE Controller
- 719a 82440MX USB Universal Host Controller
- 719b 82440MX Power Management Controller
- 71a0 440GX - 82443GX Host bridge
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 71a1 440GX - 82443GX AGP bridge
- 71a2 440GX - 82443GX Host bridge (AGP disabled)
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 7600 82372FB PIIX5 ISA
- 7601 82372FB PIIX5 IDE
- 7602 82372FB PIIX5 USB
- 7603 82372FB PIIX5 SMBus
- 7800 82740 (i740) AGP Graphics Accelerator
- 003d 0008 Starfighter AGP
- 003d 000b Starfighter AGP
- 1092 0100 Stealth II G460
- 10b4 201a Lightspeed 740
- 10b4 202f Lightspeed 740
- 8086 0000 Terminator 2x/i
- 8086 0100 Intel740 Graphics Accelerator
- 84c4 450KX/GX [Orion] - 82454KX/GX PCI bridge
- 84c5 450KX/GX [Orion] - 82453KX/GX Memory controller
- 84ca 450NX - 82451NX Memory & I/O Controller
- 84cb 450NX - 82454NX/84460GX PCI Expander Bridge
- 84e0 460GX - 84460GX System Address Controller (SAC)
- 84e1 460GX - 84460GX System Data Controller (SDC)
- 84e2 460GX - 84460GX AGP Bridge (GXB function 2)
- 84e3 460GX - 84460GX Memory Address Controller (MAC)
- 84e4 460GX - 84460GX Memory Data Controller (MDC)
- 84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
- 84ea 460GX - 84460GX AGP Bridge (GXB function 1)
- 8500 IXP4XX - Intel Network Processor family. IXP420, IXP421, IXP422, IXP425 and IXC1100
- 1993 0dee mGuard-PCI AV#1
- 1993 0def mGuard-PCI AV#0
- 9000 IXP2000 Family Network Processor
- 9001 IXP2400 Network Processor
- 9004 IXP2800 Network Processor
- 9621 Integrated RAID
- 9622 Integrated RAID
- 9641 Integrated RAID
- 96a1 Integrated RAID
-# retail verson
- a01f PRO/10GbE LR Server Adapter
-# OEM version
- a11f PRO/10GbE LR Server Adapter
- b152 21152 PCI-to-PCI Bridge
-# observed, and documented in Intel revision note; new mask of 1011:0026
- b154 21154 PCI-to-PCI Bridge
- b555 21555 Non transparent PCI-to-PCI Bridge
- 12d9 000a PCI VoIP Gateway
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- e4bf 1000 CC8-1-BLUES
- ffff 450NX/GX [Orion] - 82453KX/GX Memory controller [BUG]
-8401 TRENDware International Inc.
-8800 Trigem Computer Inc.
- 2008 Video assistent component
-8866 T-Square Design Inc.
-8888 Silicon Magic
-# 8c4a is not Winbond but there is a board misprogrammed
-8c4a Winbond
- 1980 W89C940 misprogrammed [ne2k]
-8e0e Computone Corporation
-8e2e KTI
- 3000 ET32P2
-9004 Adaptec
- 0078 AHA-2940U_CN
- 1078 AIC-7810
- 1160 AIC-1160 [Family Fibre Channel Adapter]
- 2178 AIC-7821
- 3860 AHA-2930CU
- 3b78 AHA-4844W/4844UW
- 5075 AIC-755x
- 5078 AHA-7850
- 9004 7850 AHA-2904/Integrated AIC-7850
- 5175 AIC-755x
- 5178 AIC-7851
- 5275 AIC-755x
- 5278 AIC-7852
- 5375 AIC-755x
- 5378 AIC-7850
- 5475 AIC-755x
- 5478 AIC-7850
- 5575 AVA-2930
- 5578 AIC-7855
- 5647 ANA-7711 TCP Offload Engine
- 9004 7710 ANA-7711F TCP Offload Engine - Optical
- 9004 7711 ANA-7711LP TCP Offload Engine - Copper
- 5675 AIC-755x
- 5678 AIC-7856
- 5775 AIC-755x
- 5778 AIC-7850
- 5800 AIC-5800
- 5900 ANA-5910/5930/5940 ATM155 & 25 LAN Adapter
- 5905 ANA-5910A/5930A/5940A ATM Adapter
- 6038 AIC-3860
- 6075 AIC-1480 / APA-1480
- 9004 7560 AIC-1480 / APA-1480 Cardbus
- 6078 AIC-7860
- 6178 AIC-7861
- 9004 7861 AHA-2940AU Single
- 6278 AIC-7860
- 6378 AIC-7860
- 6478 AIC-786x
- 6578 AIC-786x
- 6678 AIC-786x
- 6778 AIC-786x
- 6915 ANA620xx/ANA69011A
- 9004 0008 ANA69011A/TX 10/100
- 9004 0009 ANA69011A/TX 10/100
- 9004 0010 ANA62022 2-port 10/100
- 9004 0018 ANA62044 4-port 10/100
- 9004 0019 ANA62044 4-port 10/100
- 9004 0020 ANA62022 2-port 10/100
- 9004 0028 ANA69011A/TX 10/100
- 9004 8008 ANA69011A/TX 64 bit 10/100
- 9004 8009 ANA69011A/TX 64 bit 10/100
- 9004 8010 ANA62022 2-port 64 bit 10/100
- 9004 8018 ANA62044 4-port 64 bit 10/100
- 9004 8019 ANA62044 4-port 64 bit 10/100
- 9004 8020 ANA62022 2-port 64 bit 10/100
- 9004 8028 ANA69011A/TX 64 bit 10/100
- 7078 AHA-294x / AIC-7870
- 7178 AHA-2940/2940W / AIC-7871
- 7278 AHA-3940/3940W / AIC-7872
- 7378 AHA-3985 / AIC-7873
- 7478 AHA-2944/2944W / AIC-7874
- 7578 AHA-3944/3944W / AIC-7875
- 7678 AHA-4944W/UW / AIC-7876
- 7710 ANA-7711F Network Accelerator Card (NAC) - Optical
- 7711 ANA-7711C Network Accelerator Card (NAC) - Copper
- 7778 AIC-787x
- 7810 AIC-7810
- 7815 AIC-7815 RAID+Memory Controller IC
- 9004 7815 ARO-1130U2 RAID Controller
- 9004 7840 AIC-7815 RAID+Memory Controller IC
- 7850 AIC-7850
- 7855 AHA-2930
- 7860 AIC-7860
- 7870 AIC-7870
- 7871 AHA-2940
- 7872 AHA-3940
- 7873 AHA-3980
- 7874 AHA-2944
- 7880 AIC-7880P
- 7890 AIC-7890
- 7891 AIC-789x
- 7892 AIC-789x
- 7893 AIC-789x
- 7894 AIC-789x
- 7895 AHA-2940U/UW / AHA-39xx / AIC-7895
- 9004 7890 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7891 AHA-2940U/2940UW Dual
- 9004 7892 AHA-3940AU/AUW/AUWD/UWD
- 9004 7894 AHA-3944AUWD
- 9004 7895 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7896 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7897 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 7896 AIC-789x
- 7897 AIC-789x
- 8078 AIC-7880U
- 9004 7880 AIC-7880P Ultra/Ultra Wide SCSI Chipset
- 8178 AHA-2940U/UW/D / AIC-7881U
- 9004 7881 AHA-2940UW SCSI Host Adapter
- 8278 AHA-3940U/UW/UWD / AIC-7882U
- 8378 AHA-3940U/UW / AIC-7883U
- 8478 AHA-2944UW / AIC-7884U
- 8578 AHA-3944U/UWD / AIC-7885
- 8678 AHA-4944UW / AIC-7886
- 8778 AHA-2940UW Pro / AIC-788x
- 9004 7887 2940UW Pro Ultra-Wide SCSI Controller
- 8878 AHA-2930UW / AIC-7888
- 9004 7888 AHA-2930UW SCSI Controller
- 8b78 ABA-1030
- ec78 AHA-4944W/UW
-9005 Adaptec
- 0010 AHA-2940U2/U2W
- 9005 2180 AHA-2940U2 SCSI Controller
- 9005 8100 AHA-2940U2B SCSI Controller
- 9005 a100 AHA-2940U2B SCSI Controller
- 9005 a180 AHA-2940U2W SCSI Controller
- 9005 e100 AHA-2950U2B SCSI Controller
- 0011 AHA-2930U2
- 0013 78902
- 9005 0003 AAA-131U2 Array1000 1 Channel RAID Controller
- 9005 000f AIC7890_ARO
- 001f AHA-2940U2/U2W / 7890/7891
- 9005 000f 2940U2W SCSI Controller
- 9005 a180 2940U2W SCSI Controller
- 0020 AIC-7890
- 002f AIC-7890
- 0030 AIC-7890
- 003f AIC-7890
- 0050 AHA-3940U2x/395U2x
- 9005 f500 AHA-3950U2B
- 9005 ffff AHA-3950U2B
- 0051 AHA-3950U2D
- 9005 b500 AHA-3950U2D
- 0053 AIC-7896 SCSI Controller
- 9005 ffff AIC-7896 SCSI Controller mainboard implementation
- 005f AIC-7896U2/7897U2
- 0080 AIC-7892A U160/m
- 0e11 e2a0 Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter
- 9005 6220 AHA-29160C
- 9005 62a0 29160N Ultra160 SCSI Controller
- 9005 e220 29160LP Low Profile Ultra160 SCSI Controller
- 9005 e2a0 29160 Ultra160 SCSI Controller
- 0081 AIC-7892B U160/m
- 9005 62a1 19160 Ultra160 SCSI Controller
- 0083 AIC-7892D U160/m
- 008f AIC-7892P U160/m
- 1179 0001 Magnia Z310
- 15d9 9005 Onboard SCSI Host Adapter
- 00c0 AHA-3960D / AIC-7899A U160/m
- 0e11 f620 Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter
- 9005 f620 AHA-3960D U160/m
- 00c1 AIC-7899B U160/m
- 00c3 AIC-7899D U160/m
- 00c5 RAID subsystem HBA
- 1028 00c5 PowerEdge 2400,2500,2550,4400
- 00cf AIC-7899P U160/m
- 1028 00ce PowerEdge 1400
- 1028 00d1 PowerEdge 2550
- 1028 00d9 PowerEdge 2500
- 10f1 2462 Thunder K7 S2462
- 15d9 9005 Onboard SCSI Host Adapter
- 8086 3411 SDS2 Mainboard
- 0250 ServeRAID Controller
- 1014 0279 ServeRAID-xx
- 1014 028c ServeRAID-xx
-# from kernel sources
- 0279 ServeRAID 6M
- 0283 AAC-RAID
- 9005 0283 Catapult
- 0284 AAC-RAID
- 9005 0284 Tomcat
- 0285 AAC-RAID
- 0e11 0295 SATA 6Ch (Bearcat)
- 1014 02f2 ServeRAID 8i
- 1028 0287 PowerEdge Expandable RAID Controller 320/DC
- 1028 0291 CERC SATA RAID 2 PCI SATA 6ch (DellCorsair)
- 103c 3227 AAR-2610SA
- 17aa 0286 Legend S220 (Legend Crusader)
- 17aa 0287 Legend S230 (Legend Vulcan)
- 9005 0285 2200S (Vulcan)
- 9005 0286 2120S (Crusader)
- 9005 0287 2200S (Vulcan-2m)
- 9005 0288 3230S (Harrier)
- 9005 0289 3240S (Tornado)
- 9005 028a ASR-2020S PCI-X ZCR (Skyhawk)
- 9005 028b ASR-2020S SO-DIMM PCI-X ZCR (Terminator)
- 9005 0290 AAR-2410SA PCI SATA 4ch (Jaguar II)
- 9005 0292 AAR-2810SA PCI SATA 8ch (Corsair-8)
- 9005 0293 AAR-21610SA PCI SATA 16ch (Corsair-16)
- 9005 0294 ESD SO-DIMM PCI-X SATA ZCR (Prowler)
- 0286 AAC-RAID (Rocket)
- 9005 028c ASR-2230S + ASR-2230SLP PCI-X (Lancer)
- 0503 Scamp chipset SCSI controller
- 1014 02BF Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E)
- 8000 ASC-29320A U320
- 800f AIC-7901 U320
- 8010 ASC-39320 U320
- 8011 ASC-32320D U320
- 0e11 00ac ASC-39320D U320
- 9005 0041 ASC-39320D U320
- 8012 ASC-29320 U320
- 8013 ASC-29320B U320
- 8014 ASC-29320LP U320
- 8015 ASC-39320B U320
- 8016 ASC-39320A U320
- 8017 ASC-29320ALP U320
- 801c ASC-39320D U320
- 801d AIC-7902B U320
- 801e AIC-7901A U320
- 801f AIC-7902 U320
- 8080 ASC-29320A U320 w/HostRAID
- 808f AIC-7901 U320 w/HostRAID
- 8090 ASC-39320 U320 w/HostRAID
- 8091 ASC-39320D U320 w/HostRAID
- 8092 ASC-29320 U320 w/HostRAID
- 8093 ASC-29320B U320 w/HostRAID
- 8094 ASC-29320LP U320 w/HostRAID
- 8095 ASC-39320(B) U320 w/HostRAID
- 8096 ASC-39320A U320 w/HostRAID
- 8097 ASC-29320ALP U320 w/HostRAID
- 809c ASC-39320D(B) U320 w/HostRAID
- 809d AIC-7902(B) U320 w/HostRAID
- 809e AIC-7901A U320 w/HostRAID
- 809f AIC-7902 U320 w/HostRAID
-907f Atronics
- 2015 IDE-2015PL
-919a Gigapixel Corp
-9412 Holtek
- 6565 6565
-9699 Omni Media Technology Inc
- 6565 6565
-9710 NetMos Technology
- 7780 USB IRDA-port
- 9705 PCI 9705 Parallel Port
- 9715 PCI 9715 Dual Parallel Port
- 9735 PCI 9735 Multi-I/O Controller
- 1000 0002 0P2S (2 serial)
- 1000 0012 1P2S (1 parallel + 2 serial)
- 9745 PCI 9745 Multi-I/O Controller
- 1000 0002 0P2S (2 serial)
- 1000 0012 1P2S (1 parallel + 2 serial)
- 9755 PCI 9755 Parallel Port and ISA Bridge
- 9805 PCI 9805 Parallel Port
- 9815 PCI 9815 Dual Parallel Port
- 1000 0020 2P0S (2 port parallel adaptor)
- 9835 PCI 9835 Multi-I/O Controller
- 1000 0002 0P2S (16C550 UART)
- 1000 0012 1P2S
- 9845 PCI 9845 Multi-I/O Controller
- 1000 0004 0P4S (4 port 16550A serial card)
- 1000 0006 0P6S (6 port 16550A serial card)
- 1000 0014 1P4S (4 port 16550A serial card + parallel)
- 9855 PCI 9855 Multi-I/O Controller
- 1000 0014 1P4S
-9902 Stargen Inc.
- 0001 SG2010 PCI over Starfabric Bridge
- 0002 SG2010 PCI to Starfabric Gateway
- 0003 SG1010 Starfabric Switch and PCI Bridge
-a0a0 AOPEN Inc.
-a0f1 UNISYS Corporation
-a200 NEC Corporation
-a259 Hewlett Packard
-a25b Hewlett Packard GmbH PL24-MKT
-a304 Sony
-a727 3Com Corporation
- 0013 3CRPAG175 Wireless PC Card
-aa42 Scitex Digital Video
-ac1e Digital Receiver Technology Inc
-ac3d Actuality Systems
-aecb Adrienne Electronics Corporation
-b1b3 Shiva Europe Limited
-# Pinnacle should be 11bd, but they got it wrong several times --mj
-bd11 Pinnacle Systems, Inc. (Wrong ID)
-c001 TSI Telsys
-c0a9 Micron/Crucial Technology
-c0de Motorola
-c0fe Motion Engineering, Inc.
-ca50 Varian Australia Pty Ltd
-cafe Chrysalis-ITS
-cccc Catapult Communications
-cddd Tyzx, Inc.
- 0101 DeepSea 1 High Speed Stereo Vision Frame Grabber
- 0200 DeepSea 2 High Speed Stereo Vision Frame Grabber
-d4d4 Dy4 Systems Inc
- 0601 PCI Mezzanine Card
-d531 I+ME ACTIA GmbH
-d84d Exsys
-dead Indigita Corporation
-deaf Middle Digital Inc.
- 9050 PC Weasel Virtual VGA
- 9051 PC Weasel Serial Port
- 9052 PC Weasel Watchdog Timer
-e000 Winbond
- e000 W89C940
-# see also : http://www.schoenfeld.de/inside/Inside_CWMK3.txt maybe a misuse of TJN id or it use the TJN 3XX chip for other applic
-e159 Tiger Jet Network Inc.
- 0001 Tiger3XX Modem/ISDN interface
- 0059 0001 128k ISDN-S/T Adapter
- 0059 0003 128k ISDN-U Adapter
- 0002 Tiger100APC ISDN chipset
-e4bf EKF Elektronik GmbH
-# Innovative and scalable network IC vendor
-e55e Essence Technology, Inc.
-ea01 Eagle Technology
-# The main chip of all these devices is by Xilinx -> It could also be a Xilinx ID.
-ea60 RME
- 9896 Digi32
- 9897 Digi32 Pro
- 9898 Digi32/8
-eabb Aashima Technology B.V.
-eace Endace Measurement Systems, Ltd
- 3100 DAG 3.10 OC-3/OC-12
- 3200 DAG 3.2x OC-3/OC-12
- 320e DAG 3.2E Fast Ethernet
- 340e DAG 3.4E Fast Ethernet
- 341e DAG 3.41E Fast Ethernet
- 3500 DAG 3.5 OC-3/OC-12
- 351c DAG 3.5ECM Fast Ethernet
- 4100 DAG 4.10 OC-48
- 4110 DAG 4.11 OC-48
- 4220 DAG 4.2 OC-48
- 422e DAG 4.2E Dual Gigabit Ethernet
-ec80 Belkin Corporation
- ec00 F5D6000
-ecc0 Echo Digital Audio Corporation
-edd8 ARK Logic Inc
- a091 1000PV [Stingray]
- a099 2000PV [Stingray]
- a0a1 2000MT
- a0a9 2000MI
-f1d0 AJA Video
-# All boards I have seen have this ID not efac, though all docs say efac...
- cafe KONA SD SMPTE 259M I/O
- efac KONA SD SMPTE 259M I/O
- facd KONA HD SMPTE 292M I/O
-fa57 Interagon AS
- 0001 PMC [Pattern Matching Chip]
-febd Ultraview Corp.
-feda Broadcom Inc (nee Epigram)
- a0fa BCM4210 iLine10 HomePNA 2.0
- a10e BCM4230 iLine10 HomePNA 2.0
-# IT & Telecom company, develops PCI Trunk cards <www.fedetec.es>
-fede Fedetec Inc.
- 0003 TABIC PCI v3
-fffe VMWare Inc
- 0405 Virtual SVGA 4.0
- 0710 Virtual SVGA
-ffff Illegal Vendor ID
-
-
-# List of known device classes, subclasses and programming interfaces
-
-# Syntax:
-# C class class_name
-# subclass subclass_name <-- single tab
-# prog-if prog-if_name <-- two tabs
-
-C 00 Unclassified device
- 00 Non-VGA unclassified device
- 01 VGA compatible unclassified device
-C 01 Mass storage controller
- 00 SCSI storage controller
- 01 IDE interface
- 02 Floppy disk controller
- 03 IPI bus controller
- 04 RAID bus controller
- 80 Unknown mass storage controller
-C 02 Network controller
- 00 Ethernet controller
- 01 Token ring network controller
- 02 FDDI network controller
- 03 ATM network controller
- 04 ISDN controller
- 80 Network controller
-C 03 Display controller
- 00 VGA compatible controller
- 00 VGA
- 01 8514
- 01 XGA compatible controller
- 02 3D controller
- 80 Display controller
-C 04 Multimedia controller
- 00 Multimedia video controller
- 01 Multimedia audio controller
- 02 Computer telephony device
- 80 Multimedia controller
-C 05 Memory controller
- 00 RAM memory
- 01 FLASH memory
- 80 Memory controller
-C 06 Bridge
- 00 Host bridge
- 01 ISA bridge
- 02 EISA bridge
- 03 MicroChannel bridge
- 04 PCI bridge
- 00 Normal decode
- 01 Subtractive decode
- 05 PCMCIA bridge
- 06 NuBus bridge
- 07 CardBus bridge
- 08 RACEway bridge
- 00 Transparent mode
- 01 Endpoint mode
- 09 Semi-transparent PCI-to-PCI bridge
- 40 Primary bus towards host CPU
- 80 Secondary bus towards host CPU
- 0a InfiniBand to PCI host bridge
- 80 Bridge
-C 07 Communication controller
- 00 Serial controller
- 00 8250
- 01 16450
- 02 16550
- 03 16650
- 04 16750
- 05 16850
- 06 16950
- 01 Parallel controller
- 00 SPP
- 01 BiDir
- 02 ECP
- 03 IEEE1284
- fe IEEE1284 Target
- 02 Multiport serial controller
- 03 Modem
- 00 Generic
- 01 Hayes/16450
- 02 Hayes/16550
- 03 Hayes/16650
- 04 Hayes/16750
- 80 Communication controller
-C 08 Generic system peripheral
- 00 PIC
- 00 8259
- 01 ISA PIC
- 02 EISA PIC
- 10 IO-APIC
- 20 IO(X)-APIC
- 01 DMA controller
- 00 8237
- 01 ISA DMA
- 02 EISA DMA
- 02 Timer
- 00 8254
- 01 ISA Timer
- 02 EISA Timers
- 03 RTC
- 00 Generic
- 01 ISA RTC
- 04 PCI Hot-plug controller
- 80 System peripheral
-C 09 Input device controller
- 00 Keyboard controller
- 01 Digitizer Pen
- 02 Mouse controller
- 03 Scanner controller
- 04 Gameport controller
- 00 Generic
- 10 Extended
- 80 Input device controller
-C 0a Docking station
- 00 Generic Docking Station
- 80 Docking Station
-C 0b Processor
- 00 386
- 01 486
- 02 Pentium
- 10 Alpha
- 20 Power PC
- 30 MIPS
- 40 Co-processor
-C 0c Serial bus controller
- 00 FireWire (IEEE 1394)
- 00 Generic
- 10 OHCI
- 01 ACCESS Bus
- 02 SSA
- 03 USB Controller
- 00 UHCI
- 10 OHCI
- 20 EHCI
- 80 Unspecified
- fe USB Device
- 04 Fibre Channel
- 05 SMBus
- 06 InfiniBand
-C 0d Wireless controller
- 00 IRDA controller
- 01 Consumer IR controller
- 10 RF controller
- 80 Wireless controller
-C 0e Intelligent controller
- 00 I2O
-C 0f Satellite communications controller
- 00 Satellite TV controller
- 01 Satellite audio communication controller
- 03 Satellite voice communication controller
- 04 Satellite data communication controller
-C 10 Encryption controller
- 00 Network and computing encryption device
- 10 Entertainment encryption device
- 80 Encryption controller
-C 11 Signal processing controller
- 00 DPIO module
- 01 Performance counters
- 10 Communication synchronizer
- 80 Signal processing controller
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 30bac7ed7c16..3c565ce7f77b 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -90,15 +90,19 @@ static void pcie_portdrv_save_config(struct pci_dev *dev)
pci_save_msi_state(dev);
}
-static void pcie_portdrv_restore_config(struct pci_dev *dev)
+static int pcie_portdrv_restore_config(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
+ int retval;
pci_restore_state(dev);
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
pci_restore_msi_state(dev);
- pci_enable_device(dev);
+ retval = pci_enable_device(dev);
+ if (retval)
+ return retval;
pci_set_master(dev);
+ return 0;
}
/*
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 93e8a878ea95..26a55d08b506 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -72,11 +72,13 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/*
* PCI Bus Class Devices
*/
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf)
+static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+ char *buf)
{
- cpumask_t cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
int ret;
+ cpumask_t cpumask;
+ cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
if (ret < PAGE_SIZE)
buf[ret++] = '\n';
@@ -584,7 +586,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */
- dev->current_state = 4;
+ dev->current_state = PCI_UNKNOWN;
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
@@ -753,29 +755,19 @@ pci_scan_device(struct pci_bus *bus, int devfn)
kfree(dev);
return NULL;
}
- device_initialize(&dev->dev);
- dev->dev.release = pci_release_dev;
- pci_dev_get(dev);
-
- pci_name_device(dev);
-
- dev->dev.dma_mask = &dev->dma_mask;
- dev->dev.coherent_dma_mask = 0xffffffffull;
return dev;
}
-struct pci_dev * __devinit
-pci_scan_single_device(struct pci_bus *bus, int devfn)
+void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
- struct pci_dev *dev;
+ device_initialize(&dev->dev);
+ dev->dev.release = pci_release_dev;
+ pci_dev_get(dev);
- dev = pci_scan_device(bus, devfn);
- pci_scan_msi_device(dev);
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.coherent_dma_mask = 0xffffffffull;
- if (!dev)
- return NULL;
-
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);
@@ -787,6 +779,19 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
spin_lock(&pci_bus_lock);
list_add_tail(&dev->bus_list, &bus->devices);
spin_unlock(&pci_bus_lock);
+}
+
+struct pci_dev * __devinit
+pci_scan_single_device(struct pci_bus *bus, int devfn)
+{
+ struct pci_dev *dev;
+
+ dev = pci_scan_device(bus, devfn);
+ if (!dev)
+ return NULL;
+
+ pci_device_add(dev, bus);
+ pci_scan_msi_device(dev);
return dev;
}
@@ -883,7 +888,8 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
return max;
}
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus * __devinit pci_create_bus(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata)
{
int error;
struct pci_bus *b;
@@ -940,8 +946,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
- b->subordinate = pci_scan_child_bus(b);
-
return b;
sys_create_link_err:
@@ -959,6 +963,18 @@ err_out:
kfree(b);
return NULL;
}
+EXPORT_SYMBOL_GPL(pci_create_bus);
+
+struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata)
+{
+ struct pci_bus *b;
+
+ b = pci_create_bus(parent, bus, ops, sysdata);
+ if (b)
+ b->subordinate = pci_scan_child_bus(b);
+ return b;
+}
EXPORT_SYMBOL(pci_scan_bus_parented);
#ifdef CONFIG_HOTPLUG
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 7988fc8df3fd..9613f666c110 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -474,7 +474,7 @@ static int show_dev_config(struct seq_file *m, void *v)
struct pci_dev *first_dev;
struct pci_driver *drv;
u32 class_rev;
- unsigned char latency, min_gnt, max_lat, *class;
+ unsigned char latency, min_gnt, max_lat;
int reg;
first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
@@ -490,16 +490,8 @@ static int show_dev_config(struct seq_file *m, void *v)
pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- class = pci_class_name(class_rev >> 16);
- if (class)
- seq_printf(m, " %s", class);
- else
- seq_printf(m, " Class %04x", class_rev >> 16);
-#ifdef CONFIG_PCI_NAMES
- seq_printf(m, ": %s", dev->pretty_name);
-#else
+ seq_printf(m, " Class %04x", class_rev >> 16);
seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device);
-#endif
seq_printf(m, " (rev %d).\n", class_rev & 0xff);
if (dev->irq)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index bb36bb69803f..11ca44387cb0 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -245,12 +245,19 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsi
{
region &= ~(size-1);
if (region) {
+ struct pci_bus_region bus_region;
struct resource *res = dev->resource + nr;
res->name = pci_name(dev);
res->start = region;
res->end = region + size - 1;
res->flags = IORESOURCE_IO;
+
+ /* Convert from PCI bus to resource space. */
+ bus_region.start = res->start;
+ bus_region.end = res->end;
+ pcibios_bus_to_resource(dev, res, &bus_region);
+
pci_claim_resource(dev, nr);
}
}
@@ -422,6 +429,25 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
/*
+ * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
+ * This leads to doubled level interrupt rates.
+ * Set this bit to get rid of cycle wastage.
+ * Otherwise uncritical.
+ */
+static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
+{
+ u8 misc_control2;
+#define BYPASS_APIC_DEASSERT 8
+
+ pci_read_config_byte(dev, 0x5B, &misc_control2);
+ if (!(misc_control2 & BYPASS_APIC_DEASSERT)) {
+ printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n");
+ pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT);
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
+
+/*
* The AMD io apic can hang the box when an apic irq is masked.
* We check all revs >= B0 (yet not in the pre production!) as the bug
* is currently marked NoFix
@@ -850,6 +876,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0xC00C: /* Samsung P35 notebook */
asus_hides_smbus = 1;
}
+ } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {
+ if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
+ switch(dev->subsystem_device) {
+ case 0x0058: /* Compaq Evo N620c */
+ asus_hides_smbus = 1;
+ }
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge );
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 713c78f3a65d..49bd21702314 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -21,13 +21,21 @@
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
-static void pci_enable_rom(struct pci_dev *pdev)
+static int pci_enable_rom(struct pci_dev *pdev)
{
+ struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
+ struct pci_bus_region region;
u32 rom_addr;
+ if (!res->flags)
+ return -1;
+
+ pcibios_resource_to_bus(pdev, &region, res);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
- rom_addr |= PCI_ROM_ADDRESS_ENABLE;
+ rom_addr &= ~PCI_ROM_ADDRESS_MASK;
+ rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
+ return 0;
}
/**
@@ -71,19 +79,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
} else {
if (res->flags & IORESOURCE_ROM_COPY) {
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE);
+ return (void __iomem *)pci_resource_start(pdev,
+ PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
- if (res->parent == NULL)
- pci_assign_resource(pdev, PCI_ROM_RESOURCE);
-
+ if (res->parent == NULL &&
+ pci_assign_resource(pdev,PCI_ROM_RESOURCE))
+ return NULL;
start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (*size == 0)
return NULL;
/* Enable ROM space decodes */
- pci_enable_rom(pdev);
+ if (pci_enable_rom(pdev))
+ return NULL;
}
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6d864c502a1f..657be948baf7 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -40,7 +40,7 @@
* FIXME: IO should be max 256 bytes. However, since we may
* have a P2P bridge below a cardbus bridge, we need 4K.
*/
-#define CARDBUS_IO_SIZE (256)
+#define CARDBUS_IO_SIZE (4*1024)
#define CARDBUS_MEM_SIZE (32*1024*1024)
static void __devinit
@@ -77,8 +77,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
}
}
-static void __devinit
-pci_setup_cardbus(struct pci_bus *bus)
+void pci_setup_cardbus(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
struct pci_bus_region region;
@@ -130,6 +129,7 @@ pci_setup_cardbus(struct pci_bus *bus)
region.end);
}
}
+EXPORT_SYMBOL(pci_setup_cardbus);
/* Initialize bridges with base/limit values we have collected.
PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 5598b4714f77..50d6685dcbcc 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -26,7 +26,7 @@
#include "pci.h"
-static void
+void
pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
{
struct pci_bus_region region;
@@ -97,10 +97,7 @@ pci_claim_resource(struct pci_dev *dev, int resource)
char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
int err;
- if (res->flags & IORESOURCE_IO)
- root = &ioport_resource;
- if (res->flags & IORESOURCE_MEM)
- root = &iomem_resource;
+ root = pcibios_select_root(dev, res);
err = -EINVAL;
if (root != NULL)
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6485f75d2fb3..ddc741e6ecbf 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -221,6 +221,13 @@ config PCMCIA_VRC4173
tristate "NEC VRC4173 CARDU support"
depends on CPU_VR41XX && PCI && PCMCIA
+config OMAP_CF
+ tristate "OMAP CompactFlash Controller"
+ depends on PCMCIA && ARCH_OMAP16XX
+ help
+ Say Y here to support the CompactFlash controller on OMAP.
+ Note that this doesn't support "True IDE" mode.
+
config PCCARD_NONSTATIC
tristate
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index ef694c74dfb7..a41fbb38fdcb 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
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
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index e39178fc59d0..fabd3529cebc 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -654,9 +654,10 @@ static int pccardd(void *__skt)
skt->thread = NULL;
complete_and_exit(&skt->thread_done, 0);
}
- complete(&skt->thread_done);
add_wait_queue(&skt->thread_wait, &wait);
+ complete(&skt->thread_done);
+
for (;;) {
unsigned long flags;
unsigned int events;
@@ -682,11 +683,11 @@ static int pccardd(void *__skt)
continue;
}
- schedule();
- try_to_freeze();
-
if (!skt->thread)
break;
+
+ schedule();
+ try_to_freeze();
}
remove_wait_queue(&skt->thread_wait, &wait);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 6bbfbd0e02a5..55867bc7f199 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -17,9 +17,6 @@
#include <linux/config.h>
-#define CLIENT_MAGIC 0x51E6
-typedef struct client_t client_t;
-
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
#define CLIENT_IRQ_REQ 0x0002
@@ -45,7 +42,6 @@ typedef struct region_t {
typedef struct config_t {
u_int state;
u_int Attributes;
- u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 43da2e92d50f..080608c7381a 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -354,6 +354,7 @@ 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);
kfree(p_dev);
}
@@ -424,9 +425,13 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
{
cistpl_manfid_t manf_id;
cistpl_funcid_t func_id;
- cistpl_vers_1_t vers1;
+ cistpl_vers_1_t *vers1;
unsigned int i;
+ vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
+ if (!vers1)
+ return -ENOMEM;
+
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
CISTPL_MANFID, &manf_id)) {
p_dev->manf_id = manf_id.manf;
@@ -443,23 +448,30 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
/* rule of thumb: cards with no FUNCID, but with
* common memory device geometry information, are
* probably memory cards (from pcmcia-cs) */
- cistpl_device_geo_t devgeo;
+ cistpl_device_geo_t *devgeo;
+
+ devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
+ if (!devgeo) {
+ kfree(vers1);
+ return -ENOMEM;
+ }
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
- CISTPL_DEVICE_GEO, &devgeo)) {
+ CISTPL_DEVICE_GEO, devgeo)) {
ds_dbg(0, "mem device geometry probably means "
"FUNCID_MEMORY\n");
p_dev->func_id = CISTPL_FUNCID_MEMORY;
p_dev->has_func_id = 1;
}
+ kfree(devgeo);
}
if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
- &vers1)) {
- for (i=0; i < vers1.ns; i++) {
+ vers1)) {
+ for (i=0; i < vers1->ns; i++) {
char *tmp;
unsigned int length;
- tmp = vers1.str + vers1.ofs[i];
+ tmp = vers1->str + vers1->ofs[i];
length = strlen(tmp) + 1;
if ((length < 3) || (length > 255))
@@ -475,6 +487,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
}
}
+ kfree(vers1);
return 0;
}
@@ -492,6 +505,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
{
struct pcmcia_device *p_dev;
unsigned long flags;
+ int bus_id_len;
s = pcmcia_get_socket(s);
if (!s)
@@ -515,7 +529,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.dev;
p_dev->dev.release = pcmcia_release_dev;
- sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+
+ p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+ if (!p_dev->devname)
+ goto err_free;
+ sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
/* compat */
p_dev->state = CLIENT_UNBOUND;
@@ -540,6 +559,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
return p_dev;
err_free:
+ kfree(p_dev->devname);
kfree(p_dev);
s->device_count--;
err_put:
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
new file mode 100644
index 000000000000..08d1c9288264
--- /dev/null
+++ b/drivers/pcmcia/omap_cf.c
@@ -0,0 +1,373 @@
+/*
+ * omap_cf.c -- OMAP 16xx 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/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
+
+
+/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
+ * hard-wired timings to support Compact Flash memory cards; they won't work
+ * with various other devices (like WLAN adapters) without some external
+ * logic to help out.
+ *
+ * NOTE: CF controller docs disagree with address space docs as to where
+ * CF_BASE really lives; this is a doc erratum.
+ */
+#define CF_BASE 0xfffe2800
+
+/* status; read after IRQ */
+#define CF_STATUS_REG __REG16(CF_BASE + 0x00)
+# define CF_STATUS_BAD_READ (1 << 2)
+# define CF_STATUS_BAD_WRITE (1 << 1)
+# define CF_STATUS_CARD_DETECT (1 << 0)
+
+/* which chipselect (CS0..CS3) is used for CF (active low) */
+#define CF_CFG_REG __REG16(CF_BASE + 0x02)
+
+/* card reset */
+#define CF_CONTROL_REG __REG16(CF_BASE + 0x04)
+# define CF_CONTROL_RESET (1 << 0)
+
+#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT))
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "omap_cf";
+
+struct omap_cf_socket {
+ struct pcmcia_socket socket;
+
+ struct timer_list timer;
+ unsigned present:1;
+ unsigned active:1;
+
+ struct platform_device *pdev;
+ unsigned long phys_cf;
+ u_int irq;
+};
+
+#define POLL_INTERVAL (2 * HZ)
+
+#define SZ_2K (2 * SZ_1K)
+
+/*--------------------------------------------------------------------------*/
+
+static int omap_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void omap_cf_timer(unsigned long _cf)
+{
+ struct omap_cf_socket *cf = (void *) _cf;
+ unsigned present = omap_cf_present();
+
+ 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);
+ }
+
+ if (cf->active)
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+/* This irq handler prevents "irqNNN: nobody cared" messages as drivers
+ * claim the card's IRQ. It may also detect some card insertions, but
+ * not removals; it can't always eliminate timer irqs.
+ */
+static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+ omap_cf_timer((unsigned long)_cf);
+ return IRQ_HANDLED;
+}
+
+static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ if (!sp)
+ return -EINVAL;
+
+ /* FIXME power management should probably be board-specific:
+ * - 3VCARD vs XVCARD (OSK only handles 3VCARD)
+ * - POWERON (switched on/off by set_socket)
+ */
+ if (omap_cf_present()) {
+ struct omap_cf_socket *cf;
+
+ *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+ cf = container_of(s, struct omap_cf_socket, socket);
+ s->irq.AssignedIRQ = cf->irq;
+ } else
+ *sp = 0;
+ return 0;
+}
+
+static int
+omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+ u16 control;
+
+ /* FIXME some non-OSK boards will support power switching */
+ switch (s->Vcc) {
+ case 0:
+ case 33:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ control = CF_CONTROL_REG;
+ if (s->flags & SS_RESET)
+ CF_CONTROL_REG = CF_CONTROL_RESET;
+ else
+ CF_CONTROL_REG = 0;
+
+ 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 omap_cf_ss_suspend(struct pcmcia_socket *s)
+{
+ pr_debug("%s: %s\n", driver_name, __FUNCTION__);
+ return omap_cf_set_socket(s, &dead_socket);
+}
+
+/* regions are 2K each: mem, attrib, io (and reserved-for-ide) */
+
+static int
+omap_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+ struct omap_cf_socket *cf;
+
+ cf = container_of(s, struct omap_cf_socket, socket);
+ io->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ io->start = cf->phys_cf + SZ_4K;
+ io->stop = io->start + SZ_2K - 1;
+ return 0;
+}
+
+static int
+omap_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+ struct omap_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+ cf = container_of(s, struct omap_cf_socket, socket);
+ map->static_start = cf->phys_cf;
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ if (map->flags & MAP_ATTRIB)
+ map->static_start += SZ_2K;
+ return 0;
+}
+
+static struct pccard_operations omap_cf_ops = {
+ .init = omap_cf_ss_init,
+ .suspend = omap_cf_ss_suspend,
+ .get_status = omap_cf_get_status,
+ .set_socket = omap_cf_set_socket,
+ .set_io_map = omap_cf_set_io_map,
+ .set_mem_map = omap_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * NOTE: right now the only board-specific platform_data is
+ * "what chipselect is used". Boards could want more.
+ */
+
+static int __init omap_cf_probe(struct device *dev)
+{
+ unsigned seg;
+ struct omap_cf_socket *cf;
+ struct platform_device *pdev = to_platform_device(dev);
+ int irq;
+ int status;
+
+ seg = (int) dev->platform_data;
+ if (seg == 0 || seg > 3)
+ return -ENODEV;
+
+ /* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
+ irq = platform_get_irq(pdev, 0);
+ if (!irq)
+ return -EINVAL;
+
+ cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+ init_timer(&cf->timer);
+ cf->timer.function = omap_cf_timer;
+ cf->timer.data = (unsigned long) cf;
+
+ cf->pdev = pdev;
+ dev_set_drvdata(dev, cf);
+
+ /* this primarily just shuts up irq handling noise */
+ status = request_irq(irq, omap_cf_irq, SA_SHIRQ,
+ driver_name, cf);
+ if (status < 0)
+ goto fail0;
+ cf->irq = irq;
+ cf->socket.pci_irq = irq;
+
+ switch (seg) {
+ /* NOTE: CS0 could be configured too ... */
+ case 1:
+ cf->phys_cf = OMAP_CS1_PHYS;
+ break;
+ case 2:
+ cf->phys_cf = OMAP_CS2_PHYS;
+ break;
+ case 3:
+ cf->phys_cf = omap_cs3_phys();
+ break;
+ default:
+ goto fail1;
+ }
+
+ /* pcmcia layer only remaps "real" memory */
+ cf->socket.io_offset = (unsigned long)
+ ioremap(cf->phys_cf + SZ_4K, SZ_2K);
+ if (!cf->socket.io_offset)
+ goto fail1;
+
+ if (!request_mem_region(cf->phys_cf, SZ_8K, driver_name))
+ goto fail1;
+
+ /* NOTE: CF conflicts with MMC1 */
+ omap_cfg_reg(W11_1610_CF_CD1);
+ omap_cfg_reg(P11_1610_CF_CD2);
+ omap_cfg_reg(R11_1610_CF_IOIS16);
+ omap_cfg_reg(V10_1610_CF_IREQ);
+ omap_cfg_reg(W10_1610_CF_RESET);
+
+ CF_CFG_REG = ~(1 << seg);
+
+ pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq);
+
+ /* NOTE: better EMIFS setup might support more cards; but the
+ * TRM only shows how to affect regular flash signals, not their
+ * CF/PCMCIA variants...
+ */
+ pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name,
+ seg, EMIFS_CCS(seg), EMIFS_ACS(seg));
+ EMIFS_CCS(seg) = 0x0004a1b3; /* synch mode 4 etc */
+ EMIFS_ACS(seg) = 0x00000000; /* OE hold/setup */
+
+ /* CF uses armxor_ck, which is "always" available */
+
+ pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name,
+ CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG,
+ omap_cf_present() ? "present" : "(not present)");
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.dev = dev;
+ cf->socket.ops = &omap_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;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0)
+ goto fail2;
+
+ cf->active = 1;
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+ return 0;
+
+fail2:
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(cf->phys_cf, SZ_8K);
+fail1:
+ free_irq(irq, cf);
+fail0:
+ kfree(cf);
+ return status;
+}
+
+static int __devexit omap_cf_remove(struct device *dev)
+{
+ struct omap_cf_socket *cf = dev_get_drvdata(dev);
+
+ cf->active = 0;
+ pcmcia_unregister_socket(&cf->socket);
+ del_timer_sync(&cf->timer);
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(cf->phys_cf, SZ_8K);
+ free_irq(cf->irq, cf);
+ kfree(cf);
+ return 0;
+}
+
+static int omap_cf_suspend(struct device *dev, pm_message_t mesg, u32 level)
+{
+ if (level != SUSPEND_SAVE_STATE)
+ return 0;
+ return pcmcia_socket_dev_suspend(dev, mesg);
+}
+
+static int omap_cf_resume(struct device *dev, u32 level)
+{
+ if (level != RESUME_RESTORE_STATE)
+ return 0;
+ return pcmcia_socket_dev_resume(dev);
+}
+
+static struct device_driver omap_cf_driver = {
+ .name = (char *) driver_name,
+ .bus = &platform_bus_type,
+ .probe = omap_cf_probe,
+ .remove = __devexit_p(omap_cf_remove),
+ .suspend = omap_cf_suspend,
+ .resume = omap_cf_resume,
+};
+
+static int __init omap_cf_init(void)
+{
+ if (cpu_is_omap16xx())
+ driver_register(&omap_cf_driver);
+ return 0;
+}
+
+static void __exit omap_cf_exit(void)
+{
+ if (cpu_is_omap16xx())
+ driver_unregister(&omap_cf_driver);
+}
+
+module_init(omap_cf_init);
+module_exit(omap_cf_exit);
+
+MODULE_DESCRIPTION("OMAP CF Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 39ba6406fd54..80969f7e7a0b 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -376,6 +376,7 @@ static int ds_open(struct inode *inode, struct file *file)
socket_t i = iminor(inode);
struct pcmcia_socket *s;
user_info_t *user;
+ static int warning_printed = 0;
ds_dbg(0, "ds_open(socket %d)\n", i);
@@ -407,6 +408,17 @@ static int ds_open(struct inode *inode, struct file *file)
s->user = user;
file->private_data = user;
+ if (!warning_printed) {
+ printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
+ "usage.\n");
+ printk(KERN_INFO "pcmcia: This interface will soon be removed from "
+ "the kernel; please expect breakage unless you upgrade "
+ "to new tools.\n");
+ printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
+ "utils/kernel/pcmcia/pcmcia.html for details.\n");
+ warning_printed = 1;
+ }
+
if (s->pcmcia_state.present)
queue_event(user, CS_EVENT_CARD_INSERTION);
return 0;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 599b116d9747..89022ad5b520 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -447,7 +447,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
if (mod->Vpp1 != mod->Vpp2)
return CS_BAD_VPP;
- c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
+ s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
@@ -623,8 +623,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
- c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
-
/* Pick memory or I/O card, DMA mode, interrupt */
c->IntType = req->IntType;
c->Attributes = req->Attributes;
@@ -822,7 +820,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- p_dev->dev.bus_id,
+ p_dev->devname,
(req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
if (!ret) {
if (!(req->Attributes & IRQ_HANDLE_PRESENT))
@@ -832,7 +830,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
}
}
#endif
- if (ret) {
+ /* only assign PCI irq if no IRQ already assigned */
+ if (ret && !s->irq.AssignedIRQ) {
if (!s->pci_irq)
return ret;
irq = s->pci_irq;
@@ -843,7 +842,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- p_dev->dev.bus_id, req->Instance))
+ p_dev->devname, req->Instance))
return CS_IN_USE;
}
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 3e23cd461fb1..325c992f7d8f 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -246,7 +246,7 @@ static void __exit pxa2xx_pcmcia_exit(void)
driver_unregister(&pxa2xx_pcmcia_driver);
}
-module_init(pxa2xx_pcmcia_init);
+fs_initcall(pxa2xx_pcmcia_init);
module_exit(pxa2xx_pcmcia_exit);
MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5309734e1687..bbe69b07ce50 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -196,7 +196,7 @@ static void __exit mst_pcmcia_exit(void)
platform_device_unregister(mst_pcmcia_device);
}
-module_init(mst_pcmcia_init);
+fs_initcall(mst_pcmcia_init);
module_exit(mst_pcmcia_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 42efe218867a..a1178a600e3c 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -20,27 +20,18 @@
#include <asm/hardware.h>
#include <asm/irq.h>
-
#include <asm/hardware/scoop.h>
-#include <asm/arch/corgi.h>
#include <asm/arch/pxa-regs.h>
#include "soc_common.h"
#define NO_KEEP_VS 0x0001
-static unsigned char keep_vs;
-static unsigned char keep_rd;
-
-static struct pcmcia_irqs irqs[] = {
- { 0, CORGI_IRQ_GPIO_CF_CD, "PCMCIA0 CD"},
-};
-
-static void sharpsl_pcmcia_init_reset(void)
+static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
{
- reset_scoop(&corgiscoop_device.dev);
- keep_vs = NO_KEEP_VS;
- keep_rd = 0;
+ reset_scoop(scoopdev->dev);
+ scoopdev->keep_vs = NO_KEEP_VS;
+ scoopdev->keep_rd = 0;
}
static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
@@ -71,29 +62,35 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
pxa_gpio_mode(GPIO57_nIOIS16_MD);
/* Register interrupts */
- ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
-
- if (ret) {
- printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
- return ret;
+ if (scoop_devs[skt->nr].cd_irq >= 0) {
+ struct pcmcia_irqs cd_irq;
+
+ cd_irq.sock = skt->nr;
+ cd_irq.irq = scoop_devs[skt->nr].cd_irq;
+ cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
+ ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1);
+
+ if (ret) {
+ printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
+ return ret;
+ }
}
- /* Enable interrupt */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
- keep_vs = NO_KEEP_VS;
-
- skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
+ skt->irq = scoop_devs[skt->nr].irq;
return 0;
}
static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ if (scoop_devs[skt->nr].cd_irq >= 0) {
+ struct pcmcia_irqs cd_irq;
- /* CF_BUS_OFF */
- sharpsl_pcmcia_init_reset();
+ cd_irq.sock = skt->nr;
+ cd_irq.irq = scoop_devs[skt->nr].cd_irq;
+ cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
+ soc_pcmcia_free_irqs(skt, &cd_irq, 1);
+ }
}
@@ -101,31 +98,32 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
unsigned short cpr, csr;
+ struct device *scoop = scoop_devs[skt->nr].dev;
- cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
+ cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
- csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
+ write_scoop_reg(scoop, SCOOP_IRM, 0x00FF);
+ write_scoop_reg(scoop, SCOOP_ISR, 0x0000);
+ write_scoop_reg(scoop, SCOOP_IRM, 0x0000);
+ csr = read_scoop_reg(scoop, SCOOP_CSR);
if (csr & 0x0004) {
/* card eject */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- keep_vs = NO_KEEP_VS;
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
}
- else if (!(keep_vs & NO_KEEP_VS)) {
+ else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) {
/* keep vs1,vs2 */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- csr |= keep_vs;
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ csr |= scoop_devs[skt->nr].keep_vs;
}
else if (cpr & 0x0003) {
/* power on */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- keep_vs = (csr & 0x00C0);
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ scoop_devs[skt->nr].keep_vs = (csr & 0x00C0);
}
else {
/* card detect */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0002);
}
state->detect = (csr & 0x0004) ? 0 : 1;
@@ -147,6 +145,7 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long flags;
+ struct device *scoop = scoop_devs[skt->nr].dev;
unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
@@ -166,10 +165,10 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
local_irq_save(flags);
- nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
- ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
- nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
- nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
+ nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010;
+ ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083;
+ nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080;
+ nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E;
ncpr |= (state->Vcc == 33) ? 0x0001 :
(state->Vcc == 50) ? 0x0002 : 0;
@@ -184,22 +183,22 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
((skt->status&SS_WRPROT) ? 0x0008 : 0);
if (!(ncpr & 0x0003)) {
- keep_rd = 0;
- } else if (!keep_rd) {
+ scoop_devs[skt->nr].keep_rd = 0;
+ } else if (!scoop_devs[skt->nr].keep_rd) {
if (nccr & 0x0080)
- keep_rd = 1;
+ scoop_devs[skt->nr].keep_rd = 1;
else
nccr |= 0x0080;
}
if (mcr != nmcr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
+ write_scoop_reg(scoop, SCOOP_MCR, nmcr);
if (cpr != ncpr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
+ write_scoop_reg(scoop, SCOOP_CPR, ncpr);
if (ccr != nccr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
+ write_scoop_reg(scoop, SCOOP_CCR, nccr);
if (imr != nimr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
+ write_scoop_reg(scoop, SCOOP_IMR, nimr);
local_irq_restore(flags);
@@ -208,10 +207,18 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
{
+ sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
+
+ /* Enable interrupt */
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0);
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101);
+ scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
}
static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
+ /* CF_BUS_OFF */
+ sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
}
static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -223,7 +230,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
.socket_init = sharpsl_pcmcia_socket_init,
.socket_suspend = sharpsl_pcmcia_socket_suspend,
.first = 0,
- .nr = 1,
+ .nr = 0,
};
static struct platform_device *sharpsl_pcmcia_device;
@@ -232,12 +239,15 @@ static int __init sharpsl_pcmcia_init(void)
{
int ret;
+ sharpsl_pcmcia_ops.nr=scoop_num;
sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
if (!sharpsl_pcmcia_device)
return -ENOMEM;
+
memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
+ sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev;
ret = platform_device_register(sharpsl_pcmcia_device);
if (ret)
@@ -257,7 +267,7 @@ static void __exit sharpsl_pcmcia_exit(void)
platform_device_unregister(sharpsl_pcmcia_device);
}
-module_init(sharpsl_pcmcia_init);
+fs_initcall(sharpsl_pcmcia_init);
module_exit(sharpsl_pcmcia_exit);
MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index e98bb3d80e7c..d4ed508b38be 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -126,5 +126,5 @@ MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller");
MODULE_LICENSE("Dual MPL/GPL");
-module_init(sa11x0_pcmcia_init);
+fs_initcall(sa11x0_pcmcia_init);
module_exit(sa11x0_pcmcia_exit);
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index b441f43a6a55..bb90a1448a53 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -189,7 +189,7 @@ static void __exit sa1111_drv_pcmcia_exit(void)
sa1111_driver_unregister(&pcmcia_driver);
}
-module_init(sa1111_drv_pcmcia_init);
+fs_initcall(sa1111_drv_pcmcia_init);
module_exit(sa1111_drv_pcmcia_exit);
MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c
index db04ffb6f68c..59c5d968e9f6 100644
--- a/drivers/pcmcia/sa11xx_base.c
+++ b/drivers/pcmcia/sa11xx_base.c
@@ -189,7 +189,7 @@ static int __init sa11xx_pcmcia_init(void)
{
return 0;
}
-module_init(sa11xx_pcmcia_init);
+fs_initcall(sa11xx_pcmcia_init);
static void __exit sa11xx_pcmcia_exit(void) {}
diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h
index be420bb29113..edccfa5bb400 100644
--- a/drivers/pcmcia/topic.h
+++ b/drivers/pcmcia/topic.h
@@ -101,6 +101,8 @@
#define TOPIC97_AVS_AUDIO_CONTROL 0x02
#define TOPIC97_AVS_VIDEO_CONTROL 0x01
+#define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */
+#define TOPIC_EXCA_IFC_33V_ENA 0x01
static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
{
@@ -137,4 +139,19 @@ static int topic97_override(struct yenta_socket *socket)
return 0;
}
+
+static int topic95_override(struct yenta_socket *socket)
+{
+ u8 fctrl;
+
+ /* enable 3.3V support for 16bit cards */
+ fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
+ exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA);
+
+ /* tell yenta to use exca registers to power 16bit cards */
+ socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
+
+ return 0;
+}
+
#endif /* _LINUX_TOPIC_H */
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 62fd705203fb..f0997c36c9b7 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
{
debug("%p %04x %08x\n", socket, reg, val);
writel(val, socket->base + reg);
+ readl(socket->base + reg); /* avoid problems with PCI write posting */
}
static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
{
debug("%p %04x %02x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
+ readb(socket->base + 0x800 + reg); /* PCI write posting... */
}
static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
@@ -143,6 +145,10 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
debug("%p %04x %04x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
writeb(val >> 8, socket->base + 0x800 + reg + 1);
+
+ /* PCI write posting... */
+ readb(socket->base + 0x800 + reg);
+ readb(socket->base + 0x800 + reg + 1);
}
/*
@@ -184,22 +190,52 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0;
}
-static int yenta_Vcc_power(u32 control)
+static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
{
- switch (control & CB_SC_VCC_MASK) {
- case CB_SC_VCC_5V: return 50;
- case CB_SC_VCC_3V: return 33;
- default: return 0;
- }
-}
+ if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+ (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+ u8 reg, vcc, vpp;
+
+ reg = exca_readb(socket, I365_POWER);
+ vcc = reg & I365_VCC_MASK;
+ vpp = reg & I365_VPP1_MASK;
+ state->Vcc = state->Vpp = 0;
+
+ if (socket->flags & YENTA_16BIT_POWER_DF) {
+ if (vcc == I365_VCC_3V)
+ state->Vcc = 33;
+ if (vcc == I365_VCC_5V)
+ state->Vcc = 50;
+ if (vpp == I365_VPP1_5V)
+ state->Vpp = state->Vcc;
+ if (vpp == I365_VPP1_12V)
+ state->Vpp = 120;
+ } else {
+ if (reg & I365_VCC_5V) {
+ state->Vcc = 50;
+ if (vpp == I365_VPP1_5V)
+ state->Vpp = 50;
+ if (vpp == I365_VPP1_12V)
+ state->Vpp = 120;
+ }
+ }
+ } else {
+ u32 control;
-static int yenta_Vpp_power(u32 control)
-{
- switch (control & CB_SC_VPP_MASK) {
- case CB_SC_VPP_12V: return 120;
- case CB_SC_VPP_5V: return 50;
- case CB_SC_VPP_3V: return 33;
- default: return 0;
+ control = cb_readl(socket, CB_SOCKET_CONTROL);
+
+ switch (control & CB_SC_VCC_MASK) {
+ case CB_SC_VCC_5V: state->Vcc = 50; break;
+ case CB_SC_VCC_3V: state->Vcc = 33; break;
+ default: state->Vcc = 0;
+ }
+
+ switch (control & CB_SC_VPP_MASK) {
+ case CB_SC_VPP_12V: state->Vpp = 120; break;
+ case CB_SC_VPP_5V: state->Vpp = 50; break;
+ case CB_SC_VPP_3V: state->Vpp = 33; break;
+ default: state->Vpp = 0;
+ }
}
}
@@ -211,8 +247,7 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
control = cb_readl(socket, CB_SOCKET_CONTROL);
- state->Vcc = yenta_Vcc_power(control);
- state->Vpp = yenta_Vpp_power(control);
+ yenta_get_power(socket, state);
state->io_irq = socket->io_irq;
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
@@ -246,19 +281,54 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
{
- u32 reg = 0; /* CB_SC_STPCLK? */
- switch (state->Vcc) {
- case 33: reg = CB_SC_VCC_3V; break;
- case 50: reg = CB_SC_VCC_5V; break;
- default: reg = 0; break;
- }
- switch (state->Vpp) {
- case 33: reg |= CB_SC_VPP_3V; break;
- case 50: reg |= CB_SC_VPP_5V; break;
- case 120: reg |= CB_SC_VPP_12V; break;
+ /* some birdges require to use the ExCA registers to power 16bit cards */
+ if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+ (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+ u8 reg, old;
+ reg = old = exca_readb(socket, I365_POWER);
+ reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK);
+
+ /* i82365SL-DF style */
+ if (socket->flags & YENTA_16BIT_POWER_DF) {
+ switch (state->Vcc) {
+ case 33: reg |= I365_VCC_3V; break;
+ case 50: reg |= I365_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 33:
+ case 50: reg |= I365_VPP1_5V; break;
+ case 120: reg |= I365_VPP1_12V; break;
+ }
+ } else {
+ /* i82365SL-B style */
+ switch (state->Vcc) {
+ case 50: reg |= I365_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
+ case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
+ }
+ }
+
+ if (reg != old)
+ exca_writeb(socket, I365_POWER, reg);
+ } else {
+ u32 reg = 0; /* CB_SC_STPCLK? */
+ switch (state->Vcc) {
+ case 33: reg = CB_SC_VCC_3V; break;
+ case 50: reg = CB_SC_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 33: reg |= CB_SC_VPP_3V; break;
+ case 50: reg |= CB_SC_VPP_5V; break;
+ case 120: reg |= CB_SC_VPP_12V; break;
+ }
+ if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
+ cb_writel(socket, CB_SOCKET_CONTROL, reg);
}
- if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
- cb_writel(socket, CB_SOCKET_CONTROL, reg);
}
static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
@@ -603,7 +673,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
return 0;
}
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
+static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
{
struct resource *root, *res;
struct pci_bus_region region;
@@ -612,7 +682,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
/* Already allocated? */
if (res->parent)
- return;
+ return 0;
/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
mask = ~0xfff;
@@ -628,7 +698,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
pcibios_bus_to_resource(socket->dev, res, &region);
root = pci_find_parent_resource(socket->dev, res);
if (root && (request_resource(root, res) == 0))
- return;
+ return 0;
printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
pci_name(socket->dev), nr);
}
@@ -636,35 +706,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
if (type & IORESOURCE_IO) {
if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
+ return 1;
} else {
if (type & IORESOURCE_PREFETCH) {
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
/* Approximating prefetchable by non-prefetchable */
res->flags = IORESOURCE_MEM;
}
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
}
printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
pci_name(socket->dev), type);
res->start = res->end = res->flags = 0;
+ return 0;
}
/*
@@ -672,14 +734,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
*/
static void yenta_allocate_resources(struct yenta_socket *socket)
{
- yenta_allocate_res(socket, 0, IORESOURCE_IO,
+ int program = 0;
+ program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
- yenta_allocate_res(socket, 1, IORESOURCE_IO,
+ program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
- yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
+ program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
- yenta_allocate_res(socket, 3, IORESOURCE_MEM,
+ program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
+ if (program)
+ pci_setup_cardbus(socket->dev->subordinate);
}
@@ -694,7 +759,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
if (res->start != 0 && res->end != 0)
release_resource(res);
- res->start = res->end = 0;
+ res->start = res->end = res->flags = 0;
}
}
@@ -751,6 +816,7 @@ enum {
CARDBUS_TYPE_TI12XX,
CARDBUS_TYPE_TI1250,
CARDBUS_TYPE_RICOH,
+ CARDBUS_TYPE_TOPIC95,
CARDBUS_TYPE_TOPIC97,
CARDBUS_TYPE_O2MICRO,
};
@@ -789,6 +855,9 @@ static struct cardbus_type cardbus_type[] = {
.save_state = ricoh_save_state,
.restore_state = ricoh_restore_state,
},
+ [CARDBUS_TYPE_TOPIC95] = {
+ .override = topic95_override,
+ },
[CARDBUS_TYPE_TOPIC97] = {
.override = topic97_override,
},
@@ -1196,6 +1265,7 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
+ CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h
index 4e637eef2076..4e75e9e258cd 100644
--- a/drivers/pcmcia/yenta_socket.h
+++ b/drivers/pcmcia/yenta_socket.h
@@ -95,6 +95,12 @@
*/
#define CB_MEM_PAGE(map) (0x40 + (map))
+
+/* control how 16bit cards are powered */
+#define YENTA_16BIT_POWER_EXCA 0x00000001
+#define YENTA_16BIT_POWER_DF 0x00000002
+
+
struct yenta_socket;
struct cardbus_type {
@@ -113,6 +119,8 @@ struct yenta_socket {
struct pcmcia_socket socket;
struct cardbus_type *type;
+ u32 flags;
+
/* for PCI interrupt probing */
unsigned int probe_status;
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 6776308a1fe5..c5143201419a 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -6,7 +6,7 @@ menu "Plug and Play support"
config PNP
bool "Plug and Play support"
- depends on ISA || ACPI_BUS
+ depends on ISA || ACPI
---help---
Plug and Play (PnP) is a standard for peripherals which allows those
peripherals to be configured by software, e.g. assign IRQ's or other
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 6e5229e92fbc..e95ed67d4f05 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -8,13 +8,6 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 1d037c2a82ac..33da25f3213f 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -11,13 +11,6 @@
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 82c5edd5b9ee..beedd86800f4 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -142,17 +142,6 @@ static void isapnp_write_word(unsigned char idx, unsigned short val)
isapnp_write_byte(idx+1, val);
}
-static void *isapnp_alloc(long size)
-{
- void *result;
-
- result = kmalloc(size, GFP_KERNEL);
- if (!result)
- return NULL;
- memset(result, 0, size);
- return result;
-}
-
static void isapnp_key(void)
{
unsigned char code = 0x6a, msb;
@@ -406,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne
struct pnp_id * id;
if (!dev)
return;
- id = isapnp_alloc(sizeof(struct pnp_id));
+ id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -430,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
struct pnp_dev *dev;
isapnp_peek(tmp, size);
- dev = isapnp_alloc(sizeof(struct pnp_dev));
+ dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->number = number;
@@ -461,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
unsigned long bits;
isapnp_peek(tmp, size);
- irq = isapnp_alloc(sizeof(struct pnp_irq));
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (tmp[1] << 8) | tmp[0];
@@ -485,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
struct pnp_dma *dma;
isapnp_peek(tmp, size);
- dma = isapnp_alloc(sizeof(struct pnp_dma));
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = tmp[0];
@@ -505,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = isapnp_alloc(sizeof(struct pnp_port));
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (tmp[2] << 8) | tmp[1];
@@ -528,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = isapnp_alloc(sizeof(struct pnp_port));
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (tmp[1] << 8) | tmp[0];
@@ -550,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
@@ -573,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -595,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -838,7 +827,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
{
- struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
+ struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -874,7 +863,7 @@ static int __init isapnp_build_device_list(void)
header[4], header[5], header[6], header[7], header[8]);
printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
#endif
- if ((card = isapnp_alloc(sizeof(struct pnp_card))) == NULL)
+ if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
continue;
card->number = csn;
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 6c510c19ad7d..94442ffd4aed 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -11,13 +11,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig
index 0782cdc5009f..b1854171b963 100644
--- a/drivers/pnp/pnpacpi/Kconfig
+++ b/drivers/pnp/pnpacpi/Kconfig
@@ -3,7 +3,7 @@
#
config PNPACPI
bool "Plug and Play ACPI support (EXPERIMENTAL)"
- depends on PNP && ACPI_BUS && EXPERIMENTAL
+ depends on PNP && ACPI && EXPERIMENTAL
default y
---help---
Linux uses the PNPACPI to autodetect built-in
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 8655dd2e5b83..1a8915e74160 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/config.h>
#include <linux/acpi.h>
#include <linux/pnp.h>
#include <acpi/acpi_bus.h>
@@ -41,14 +42,6 @@ static inline int is_exclusive_device(struct acpi_device *dev)
return (!acpi_match_ids(dev, excluded_id_list));
}
-void *pnpacpi_kmalloc(size_t size, int f)
-{
- void *p = kmalloc(size, f);
- if (p)
- memset(p, 0, size);
- return p;
-}
-
/*
* Compatible Device IDs
*/
@@ -143,7 +136,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
return 0;
pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
- dev = pnpacpi_kmalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev) {
pnp_err("Out of memory");
return -ENOMEM;
@@ -173,7 +166,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
dev->number = num;
/* set the initial values for the PnP device */
- dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
goto err;
pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
@@ -205,8 +198,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
for (i = 0; i < cid_list->count; i++) {
if (!ispnpidacpi(cid_list->id[i].value))
continue;
- dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id),
- GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
continue;
diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h
index 76f907e09ee6..f28e2ed66fa3 100644
--- a/drivers/pnp/pnpacpi/pnpacpi.h
+++ b/drivers/pnp/pnpacpi/pnpacpi.h
@@ -5,7 +5,6 @@
#include <linux/acpi.h>
#include <linux/pnp.h>
-void *pnpacpi_kmalloc(size_t size, int f);
acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*);
acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*);
int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 75575f6c349c..416d30debe6c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -73,25 +73,35 @@ static void decode_irq_flags(int flag, int *edge_level, int *active_high_low)
}
static void
-pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
+ int edge_level, int active_high_low)
{
int i = 0;
+ int irq;
+
+ if (!valid_IRQ(gsi))
+ return;
+
while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
i < PNP_MAX_IRQ)
i++;
- if (i < PNP_MAX_IRQ) {
- res->irq_resource[i].flags = IORESOURCE_IRQ; //Also clears _UNSET flag
- if (irq == -1) {
- res->irq_resource[i].flags |= IORESOURCE_DISABLED;
- return;
- }
- res->irq_resource[i].start =(unsigned long) irq;
- res->irq_resource[i].end = (unsigned long) irq;
+ if (i >= PNP_MAX_IRQ)
+ return;
+
+ res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+ irq = acpi_register_gsi(gsi, edge_level, active_high_low);
+ if (irq < 0) {
+ res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
}
+
+ res->irq_resource[i].start = irq;
+ res->irq_resource[i].end = irq;
+ pcibios_penalize_isa_irq(irq, 1);
}
static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
{
int i = 0;
while (i < PNP_MAX_DMA &&
@@ -103,14 +113,14 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->dma_resource[i].start =(unsigned long) dma;
- res->dma_resource[i].end = (unsigned long) dma;
+ res->dma_resource[i].start = dma;
+ res->dma_resource[i].end = dma;
}
}
static void
pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
- int io, int len)
+ u32 io, u32 len)
{
int i = 0;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -122,14 +132,14 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->port_resource[i].start = (unsigned long) io;
- res->port_resource[i].end = (unsigned long)(io + len - 1);
+ res->port_resource[i].start = io;
+ res->port_resource[i].end = io + len - 1;
}
}
static void
pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
- int mem, int len)
+ u64 mem, u64 len)
{
int i = 0;
while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -141,8 +151,8 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->mem_resource[i].start = (unsigned long) mem;
- res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+ res->mem_resource[i].start = mem;
+ res->mem_resource[i].end = mem + len - 1;
}
}
@@ -151,27 +161,28 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data)
{
struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
+ int i;
switch (res->id) {
case ACPI_RSTYPE_IRQ:
- if ((res->data.irq.number_of_interrupts > 0) &&
- valid_IRQ(res->data.irq.interrupts[0])) {
- pnpacpi_parse_allocated_irqresource(res_table,
- acpi_register_gsi(res->data.irq.interrupts[0],
- res->data.irq.edge_level,
- res->data.irq.active_high_low));
- pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 1);
+ /*
+ * Per spec, only one interrupt per descriptor is allowed in
+ * _CRS, but some firmware violates this, so parse them all.
+ */
+ for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
+ pnpacpi_parse_allocated_irqresource(res_table,
+ res->data.irq.interrupts[i],
+ res->data.irq.edge_level,
+ res->data.irq.active_high_low);
}
break;
case ACPI_RSTYPE_EXT_IRQ:
- if ((res->data.extended_irq.number_of_interrupts > 0) &&
- valid_IRQ(res->data.extended_irq.interrupts[0])) {
- pnpacpi_parse_allocated_irqresource(res_table,
- acpi_register_gsi(res->data.extended_irq.interrupts[0],
- res->data.extended_irq.edge_level,
- res->data.extended_irq.active_high_low));
- pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1);
+ for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) {
+ pnpacpi_parse_allocated_irqresource(res_table,
+ res->data.extended_irq.interrupts[i],
+ res->data.extended_irq.edge_level,
+ res->data.extended_irq.active_high_low);
}
break;
case ACPI_RSTYPE_DMA:
@@ -244,7 +255,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
if (p->number_of_channels == 0)
return;
- dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
@@ -300,7 +311,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option,
if (p->number_of_interrupts == 0)
return;
- irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -321,7 +332,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
if (p->number_of_interrupts == 0)
return;
- irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -342,7 +353,7 @@ pnpacpi_parse_port_option(struct pnp_option *option,
if (io->range_length == 0)
return;
- port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = io->min_base_address;
@@ -363,7 +374,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
if (io->range_length == 0)
return;
- port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = io->base_address;
@@ -382,7 +393,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->min_base_address;
@@ -405,7 +416,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->min_base_address;
@@ -428,7 +439,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->range_base_address;
@@ -612,7 +623,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
if (!res_cnt)
return -EINVAL;
buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
- buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL);
+ buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
if (!buffer->pointer)
return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 778a324028f4..f49674f07949 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -86,16 +86,6 @@ int pnp_bios_present(void)
struct pnp_dev_node_info node_info;
-void *pnpbios_kmalloc(size_t size, int f)
-{
- void *p = kmalloc( size, f );
- if ( p == NULL )
- printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
- else
- memset(p, 0, size);
- return p;
-}
-
/*
*
* DOCKING FUNCTIONS
@@ -121,10 +111,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
if (!current->fs->root) {
return -EAGAIN;
}
- if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+ if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
return -ENOMEM;
}
- if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
+ if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
kfree (envp);
return -ENOMEM;
}
@@ -231,7 +221,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table
if(!pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -254,7 +244,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -305,7 +295,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev)
if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
@@ -347,7 +337,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
}
/* set the initial values for the PnP device */
- dev_id = pnpbios_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return -1;
pnpid32_to_pnpid(node->eisa_id,id);
@@ -385,7 +375,7 @@ static void __init build_devlist(void)
struct pnp_bios_node *node;
struct pnp_dev *dev;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return;
@@ -402,7 +392,7 @@ static void __init build_devlist(void)
break;
}
nodes_got++;
- dev = pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL);
+ dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
if (!dev)
break;
if(insert_device(dev,node)<0)
diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h
index 01896e705ed4..d8cb2fd1f127 100644
--- a/drivers/pnp/pnpbios/pnpbios.h
+++ b/drivers/pnp/pnpbios/pnpbios.h
@@ -26,7 +26,6 @@ union pnp_bios_install_struct {
extern int pnp_bios_present(void);
extern int pnpbios_dont_use_current_config;
-extern void *pnpbios_kmalloc(size_t size, int f);
extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 6bb8e1973fd4..5a3dfc97f5e9 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
return -EFBIG;
}
- tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
+ tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
if (!tmpbuf) return -ENOMEM;
if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
@@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos,
if (pos >= 0xff)
return 0;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
for (nodenum=pos; nodenum<0xff; ) {
@@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos,
u8 nodenum = (long)data;
int len;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
kfree(node);
@@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf,
u8 nodenum = (long)data;
int ret = count;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index e305bb132c24..b0ca65b68645 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -247,7 +247,7 @@ static void
pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((p[5] << 8) | p[4]) << 8;
@@ -263,7 +263,7 @@ static void
pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -279,7 +279,7 @@ static void
pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -296,7 +296,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option)
struct pnp_irq * irq;
unsigned long bits;
- irq = pnpbios_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (p[2] << 8) | p[1];
@@ -313,7 +313,7 @@ static void
pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_dma * dma;
- dma = pnpbios_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = p[1];
@@ -326,7 +326,7 @@ static void
pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (p[3] << 8) | p[2];
@@ -342,7 +342,7 @@ static void
pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (p[2] << 8) | p[1];
@@ -530,7 +530,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de
case SMALL_TAG_COMPATDEVID: /* compatible ID */
if (len != 4)
goto len_err;
- dev_id = pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
memset(dev_id, 0, sizeof(struct pnp_id));
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 596a02d7e03d..8936b0cb2ec3 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -16,13 +16,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index b952aec49189..61fe998944bd 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -8,13 +8,6 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ctype.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index dc1c89dbdb8f..6e7d7b06421d 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -49,7 +49,7 @@ config DASD_FBA
config DASD_DIAG
tristate "Support for DIAG access to Disks"
- depends on DASD && ARCH_S390X = 'n'
+ depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
help
Select this option if you want to use Diagnose250 command to access
Disks under VM. If you are not running under VM or unsure what it is,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d5f53980749b..8fc891a9d47f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.165 $
+ * $Revision: 1.167 $
*/
#include <linux/config.h>
@@ -1131,17 +1131,13 @@ __dasd_process_blk_queue(struct dasd_device * device)
request_queue_t *queue;
struct request *req;
struct dasd_ccw_req *cqr;
- int nr_queued, feature_ro;
+ int nr_queued;
queue = device->request_queue;
/* No queue ? Then there is nothing to do. */
if (queue == NULL)
return;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0) /* no devmap */
- return;
-
/*
* We requeue request from the block device queue to the ccw
* queue only in two states. In state DASD_STATE_READY the
@@ -1162,7 +1158,8 @@ __dasd_process_blk_queue(struct dasd_device * device)
nr_queued < DASD_CHANQ_MAX_SIZE) {
req = elv_next_request(queue);
- if (feature_ro && rq_data_dir(req) == WRITE) {
+ if (device->features & DASD_FEATURE_READONLY &&
+ rq_data_dir(req) == WRITE) {
DBF_DEV_EVENT(DBF_ERR, device,
"Rejecting write request %p",
req);
@@ -1814,17 +1811,13 @@ dasd_generic_set_online (struct ccw_device *cdev,
{
struct dasd_device *device;
- int feature_diag, rc;
+ int rc;
device = dasd_create_device(cdev);
if (IS_ERR(device))
return PTR_ERR(device);
- feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
- if (feature_diag < 0)
- return feature_diag;
-
- if (feature_diag) {
+ if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
"dasd_generic couldn't online device %s "
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d948566bb24a..bda896d9d788 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,7 @@
* functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context.
*
- * $Revision: 1.40 $
+ * $Revision: 1.43 $
*/
#include <linux/config.h>
@@ -513,6 +513,7 @@ dasd_create_device(struct ccw_device *cdev)
if (!devmap->device) {
devmap->device = device;
device->devindex = devmap->devindex;
+ device->features = devmap->features;
get_device(&cdev->dev);
device->cdev = cdev;
rc = 0;
@@ -643,6 +644,8 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
+ if (devmap->device)
+ devmap->device->features = devmap->features;
if (devmap->device && devmap->device->gdp)
set_disk_ro(devmap->device->gdp, ro_flag);
spin_unlock(&dasd_devmap_lock);
@@ -758,7 +761,8 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
devmap->features |= feature;
else
devmap->features &= ~feature;
-
+ if (devmap->device)
+ devmap->device->features = devmap->features;
spin_unlock(&dasd_devmap_lock);
return 0;
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 127699830fa1..7478423b53bb 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,17 +6,18 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.42 $
+ * $Revision: 1.49 $
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/hdreg.h> /* HDIO_GETGEO */
+#include <linux/hdreg.h>
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <asm/dasd.h>
#include <asm/debug.h>
@@ -28,58 +29,89 @@
#include "dasd_int.h"
#include "dasd_diag.h"
-#ifdef PRINTK_HEADER
-#undef PRINTK_HEADER
-#endif /* PRINTK_HEADER */
#define PRINTK_HEADER "dasd(diag):"
MODULE_LICENSE("GPL");
+/* The maximum number of blocks per request (max_blocks) is dependent on the
+ * amount of storage that is available in the static I/O buffer for each
+ * device. Currently each device gets 2 pages. We want to fit two requests
+ * into the available memory so that we can immediately start the next if one
+ * finishes. */
+#define DIAG_MAX_BLOCKS (((2 * PAGE_SIZE - sizeof(struct dasd_ccw_req) - \
+ sizeof(struct dasd_diag_req)) / \
+ sizeof(struct dasd_diag_bio)) / 2)
+#define DIAG_MAX_RETRIES 32
+#define DIAG_TIMEOUT 50 * HZ
+
struct dasd_discipline dasd_diag_discipline;
struct dasd_diag_private {
struct dasd_diag_characteristics rdc_data;
struct dasd_diag_rw_io iob;
struct dasd_diag_init_io iib;
- unsigned int pt_block;
+ blocknum_t pt_block;
};
struct dasd_diag_req {
- int block_count;
+ unsigned int block_count;
struct dasd_diag_bio bio[0];
};
+static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
+
+/* Perform DIAG250 call with block I/O parameter list iob (input and output)
+ * and function code cmd.
+ * In case of an exception return 3. Otherwise return result of bitwise OR of
+ * resulting condition code and DIAG return code. */
static __inline__ int
dia250(void *iob, int cmd)
{
+ typedef struct {
+ char _[max(sizeof (struct dasd_diag_init_io),
+ sizeof (struct dasd_diag_rw_io))];
+ } addr_type;
int rc;
- __asm__ __volatile__(" lhi %0,3\n"
- " lr 0,%2\n"
- " diag 0,%1,0x250\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- " or %0,1\n"
- "1:\n"
-#ifndef CONFIG_ARCH_S390X
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous\n"
+ __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ " lghi %0,3\n"
+ " lgr 0,%3\n"
+ " diag 0,%2,0x250\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ " or %0,1\n"
+ "1:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous\n"
#else
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous\n"
+ " lhi %0,3\n"
+ " lr 0,%3\n"
+ " diag 0,%2,0x250\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ " or %0,1\n"
+ "1:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous\n"
#endif
- : "=&d" (rc)
- : "d" (cmd), "d" ((void *) __pa(iob))
- : "0", "1", "cc");
+ : "=&d" (rc), "=m" (*(addr_type *) iob)
+ : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
+ : "0", "1", "cc");
return rc;
}
+/* Initialize block I/O to DIAG device using the specified blocksize and
+ * block offset. On success, return zero and set end_block to contain the
+ * number of blocks on the device minus the specified offset. Return non-zero
+ * otherwise. */
static __inline__ int
-mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size)
+mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
+ blocknum_t offset, blocknum_t *end_block)
{
struct dasd_diag_private *private;
struct dasd_diag_init_io *iib;
@@ -92,14 +124,18 @@ mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size)
iib->dev_nr = _ccw_device_get_device_number(device->cdev);
iib->block_size = blocksize;
iib->offset = offset;
- iib->start_block = 0;
- iib->end_block = size;
+ iib->flaga = DASD_DIAG_FLAGA_DEFAULT;
rc = dia250(iib, INIT_BIO);
- return rc & 3;
+ if ((rc & 3) == 0 && end_block)
+ *end_block = iib->end_block;
+
+ return rc;
}
+/* Remove block I/O environment for device. Return zero on success, non-zero
+ * otherwise. */
static __inline__ int
mdsk_term_io(struct dasd_device * device)
{
@@ -112,9 +148,25 @@ mdsk_term_io(struct dasd_device * device)
memset(iib, 0, sizeof (struct dasd_diag_init_io));
iib->dev_nr = _ccw_device_get_device_number(device->cdev);
rc = dia250(iib, TERM_BIO);
- return rc & 3;
+ return rc;
+}
+
+/* Error recovery for failed DIAG requests - try to reestablish the DIAG
+ * environment. */
+static void
+dasd_diag_erp(struct dasd_device *device)
+{
+ int rc;
+
+ mdsk_term_io(device);
+ rc = mdsk_init_io(device, device->bp_block, 0, NULL);
+ if (rc)
+ DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, "
+ "rc=%d", rc);
}
+/* Start a given request at the device. Return zero on success, non-zero
+ * otherwise. */
static int
dasd_start_diag(struct dasd_ccw_req * cqr)
{
@@ -124,32 +176,66 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
int rc;
device = cqr->device;
+ if (cqr->retries < 0) {
+ DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p "
+ "- no retry left)", cqr);
+ cqr->status = DASD_CQR_FAILED;
+ return -EIO;
+ }
private = (struct dasd_diag_private *) device->private;
dreq = (struct dasd_diag_req *) cqr->data;
private->iob.dev_nr = _ccw_device_get_device_number(device->cdev);
private->iob.key = 0;
- private->iob.flags = 2; /* do asynchronous io */
+ private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
private->iob.block_count = dreq->block_count;
- private->iob.interrupt_params = (u32)(addr_t) cqr;
+ private->iob.interrupt_params = (addr_t) cqr;
private->iob.bio_list = __pa(dreq->bio);
+ private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
cqr->startclk = get_clock();
+ cqr->starttime = jiffies;
+ cqr->retries--;
rc = dia250(&private->iob, RW_BIO);
- if (rc > 8) {
- DEV_MESSAGE(KERN_WARNING, device, "dia250 returned CC %d", rc);
- cqr->status = DASD_CQR_ERROR;
- } else if (rc == 0) {
+ switch (rc) {
+ case 0: /* Synchronous I/O finished successfully */
+ cqr->stopclk = get_clock();
cqr->status = DASD_CQR_DONE;
- dasd_schedule_bh(device);
- } else {
+ /* Indicate to calling function that only a dasd_schedule_bh()
+ and no timer is needed */
+ rc = -EACCES;
+ break;
+ case 8: /* Asynchronous I/O was started */
cqr->status = DASD_CQR_IN_IO;
rc = 0;
+ break;
+ default: /* Error condition */
+ cqr->status = DASD_CQR_QUEUED;
+ DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc);
+ dasd_diag_erp(device);
+ rc = -EIO;
+ break;
}
return rc;
}
+/* Terminate given request at the device. */
+static int
+dasd_diag_term_IO(struct dasd_ccw_req * cqr)
+{
+ struct dasd_device *device;
+
+ device = cqr->device;
+ mdsk_term_io(device);
+ mdsk_init_io(device, device->bp_block, 0, NULL);
+ cqr->status = DASD_CQR_CLEAR;
+ cqr->stopclk = get_clock();
+ dasd_schedule_bh(device);
+ return 0;
+}
+
+/* Handle external interruption. */
static void
dasd_ext_handler(struct pt_regs *regs, __u16 code)
{
@@ -157,25 +243,27 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
struct dasd_device *device;
unsigned long long expires;
unsigned long flags;
- char status;
- int ip;
-
- /*
- * Get the external interruption subcode. VM stores
- * this in the 'cpu address' field associated with
- * the external interrupt. For diag 250 the subcode
- * needs to be 3.
- */
- if ((S390_lowcore.cpu_addr & 0xff00) != 0x0300)
- return;
- status = *((char *) &S390_lowcore.ext_params + 5);
- ip = S390_lowcore.ext_params;
+ u8 int_code, status;
+ addr_t ip;
+ int rc;
+ int_code = *((u8 *) DASD_DIAG_LC_INT_CODE);
+ status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
+ switch (int_code) {
+ case DASD_DIAG_CODE_31BIT:
+ ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT);
+ break;
+ case DASD_DIAG_CODE_64BIT:
+ ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT);
+ break;
+ default:
+ return;
+ }
if (!ip) { /* no intparm: unsolicited interrupt */
MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
return;
}
- cqr = (struct dasd_ccw_req *)(addr_t) ip;
+ cqr = (struct dasd_ccw_req *) ip;
device = (struct dasd_device *) cqr->device;
if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
DEV_MESSAGE(KERN_WARNING, device,
@@ -188,6 +276,15 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
/* get irq lock to modify request queue */
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+ /* Check for a pending clear operation */
+ if (cqr->status == DASD_CQR_CLEAR) {
+ cqr->status = DASD_CQR_QUEUED;
+ dasd_clear_timer(device);
+ dasd_schedule_bh(device);
+ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+ return;
+ }
+
cqr->stopclk = get_clock();
expires = 0;
@@ -198,16 +295,22 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
next = list_entry(device->ccw_queue.next,
struct dasd_ccw_req, list);
if (next->status == DASD_CQR_QUEUED) {
- if (dasd_start_diag(next) == 0)
+ rc = dasd_start_diag(next);
+ if (rc == 0)
expires = next->expires;
- else
+ else if (rc != -EACCES)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"Interrupt fastpath "
"failed!");
}
}
- } else
- cqr->status = DASD_CQR_FAILED;
+ } else {
+ cqr->status = DASD_CQR_QUEUED;
+ DEV_MESSAGE(KERN_WARNING, device, "interrupt status for "
+ "request %p was %d (%d retries left)", cqr, status,
+ cqr->retries);
+ dasd_diag_erp(device);
+ }
if (expires != 0)
dasd_set_timer(device, expires);
@@ -218,14 +321,17 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
}
+/* Check whether device can be controlled by DIAG discipline. Return zero on
+ * success, non-zero otherwise. */
static int
dasd_diag_check_device(struct dasd_device *device)
{
struct dasd_diag_private *private;
struct dasd_diag_characteristics *rdc_data;
struct dasd_diag_bio bio;
- long *label;
- int sb, bsize;
+ struct dasd_diag_cms_label *label;
+ blocknum_t end_block;
+ unsigned int sb, bsize;
int rc;
private = (struct dasd_diag_private *) device->private;
@@ -244,8 +350,11 @@ dasd_diag_check_device(struct dasd_device *device)
rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);
rc = diag210((struct diag210 *) rdc_data);
- if (rc)
+ if (rc) {
+ DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "
+ "information (rc=%d)", rc);
return -ENOTSUPP;
+ }
/* Figure out position of label block */
switch (private->rdc_data.vdev_class) {
@@ -256,6 +365,8 @@ dasd_diag_check_device(struct dasd_device *device)
private->pt_block = 2;
break;
default:
+ DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "
+ "(class=%d)", private->rdc_data.vdev_class);
return -ENOTSUPP;
}
@@ -269,15 +380,17 @@ dasd_diag_check_device(struct dasd_device *device)
mdsk_term_io(device);
/* figure out blocksize of device */
- label = (long *) get_zeroed_page(GFP_KERNEL);
+ label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
}
+ rc = 0;
+ end_block = 0;
/* try all sizes - needed for ECKD devices */
for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
- mdsk_init_io(device, bsize, 0, 64);
+ mdsk_init_io(device, bsize, 0, &end_block);
memset(&bio, 0, sizeof (struct dasd_diag_bio));
bio.type = MDSK_READ_REQ;
bio.block_number = private->pt_block + 1;
@@ -289,37 +402,45 @@ dasd_diag_check_device(struct dasd_device *device)
private->iob.block_count = 1;
private->iob.interrupt_params = 0;
private->iob.bio_list = __pa(&bio);
- if (dia250(&private->iob, RW_BIO) == 0)
+ private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
+ rc = dia250(&private->iob, RW_BIO);
+ if (rc == 0 || rc == 3)
break;
mdsk_term_io(device);
}
- if (bsize <= PAGE_SIZE && label[0] == 0xc3d4e2f1) {
- /* get formatted blocksize from label block */
- bsize = (int) label[3];
- device->blocks = label[7];
+ if (rc == 3) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
+ rc = -EOPNOTSUPP;
+ } else if (rc != 0) {
+ DEV_MESSAGE(KERN_WARNING, device, "device access failed "
+ "(rc=%d)", rc);
+ rc = -EIO;
+ } else {
+ if (memcmp(label->label_id, DASD_DIAG_CMS1,
+ sizeof(DASD_DIAG_CMS1)) == 0) {
+ /* get formatted blocksize from label block */
+ bsize = (unsigned int) label->block_size;
+ device->blocks = (unsigned long) label->block_count;
+ } else
+ device->blocks = end_block;
device->bp_block = bsize;
device->s2b_shift = 0; /* bits to shift 512 to get a block */
for (sb = 512; sb < bsize; sb = sb << 1)
device->s2b_shift++;
DEV_MESSAGE(KERN_INFO, device,
- "capacity (%dkB blks): %ldkB",
- (device->bp_block >> 10),
- (device->blocks << device->s2b_shift) >> 1);
+ "(%ld B/blk): %ldkB",
+ (unsigned long) device->bp_block,
+ (unsigned long) (device->blocks <<
+ device->s2b_shift) >> 1);
rc = 0;
- } else {
- if (bsize > PAGE_SIZE)
- DEV_MESSAGE(KERN_WARNING, device, "%s",
- "DIAG access failed");
- else
- DEV_MESSAGE(KERN_WARNING, device, "%s",
- "volume is not CMS formatted");
- rc = -EMEDIUMTYPE;
}
free_page((long) label);
return rc;
}
+/* Fill in virtual disk geometry for device. Return zero on success, non-zero
+ * otherwise. */
static int
dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo)
{
@@ -349,6 +470,8 @@ dasd_diag_erp_postaction(struct dasd_ccw_req * cqr)
return dasd_default_erp_postaction;
}
+/* Create DASD request from block device request. Return pointer to new
+ * request on success, ERR_PTR otherwise. */
static struct dasd_ccw_req *
dasd_diag_build_cp(struct dasd_device * device, struct request *req)
{
@@ -358,9 +481,9 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
struct bio *bio;
struct bio_vec *bv;
char *dst;
- int count, datasize;
+ unsigned int count, datasize;
sector_t recid, first_rec, last_rec;
- unsigned blksize, off;
+ unsigned int blksize, off;
unsigned char rw_cmd;
int i;
@@ -413,13 +536,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
}
}
}
+ cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
cqr->device = device;
- cqr->expires = 50 * HZ; /* 50 seconds */
+ cqr->expires = DIAG_TIMEOUT;
cqr->status = DASD_CQR_FILLED;
return cqr;
}
+/* Release DASD request. Return non-zero if request was successful, zero
+ * otherwise. */
static int
dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
{
@@ -430,6 +556,7 @@ dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
return status;
}
+/* Fill in IOCTL data for device. */
static int
dasd_diag_fill_info(struct dasd_device * device,
struct dasd_information2_t * info)
@@ -437,7 +564,7 @@ dasd_diag_fill_info(struct dasd_device * device,
struct dasd_diag_private *private;
private = (struct dasd_diag_private *) device->private;
- info->label_block = private->pt_block;
+ info->label_block = (unsigned int) private->pt_block;
info->FBA_layout = 1;
info->format = DASD_FORMAT_LDL;
info->characteristics_size = sizeof (struct dasd_diag_characteristics);
@@ -456,26 +583,15 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
"dump sense not available for DIAG data");
}
-/*
- * max_blocks is dependent on the amount of storage that is available
- * in the static io buffer for each device. Currently each device has
- * 8192 bytes (=2 pages). dasd diag is only relevant for 31 bit.
- * The struct dasd_ccw_req has 96 bytes, the struct dasd_diag_req has
- * 8 bytes and the struct dasd_diag_bio for each block has 16 bytes.
- * That makes:
- * (8192 - 96 - 8) / 16 = 505.5 blocks at maximum.
- * We want to fit two into the available memory so that we can immediately
- * start the next request if one finishes off. That makes 252.75 blocks
- * for one request. Give a little safety and the result is 240.
- */
struct dasd_discipline dasd_diag_discipline = {
.owner = THIS_MODULE,
.name = "DIAG",
.ebcname = "DIAG",
- .max_blocks = 240,
+ .max_blocks = DIAG_MAX_BLOCKS,
.check_device = dasd_diag_check_device,
.fill_geometry = dasd_diag_fill_geometry,
.start_IO = dasd_start_diag,
+ .term_IO = dasd_diag_term_IO,
.examine_error = dasd_diag_examine_error,
.erp_action = dasd_diag_erp_action,
.erp_postaction = dasd_diag_erp_postaction,
@@ -493,7 +609,7 @@ dasd_diag_init(void)
"Machine is not VM: %s "
"discipline not initializing",
dasd_diag_discipline.name);
- return -EINVAL;
+ return -ENODEV;
}
ASCEBC(dasd_diag_discipline.ebcname, 4);
@@ -506,13 +622,6 @@ dasd_diag_init(void)
static void __exit
dasd_diag_cleanup(void)
{
- if (!MACHINE_IS_VM) {
- MESSAGE_LOG(KERN_INFO,
- "Machine is not VM: %s "
- "discipline not cleaned",
- dasd_diag_discipline.name);
- return;
- }
unregister_external_interrupt(0x2603, dasd_ext_handler);
ctl_clear_bit(0, 9);
dasd_diag_discipline_pointer = NULL;
@@ -520,22 +629,3 @@ dasd_diag_cleanup(void)
module_init(dasd_diag_init);
module_exit(dasd_diag_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
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index a0c38e303979..b26eb28df4bf 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
*/
#define MDSK_WRITE_REQ 0x01
@@ -19,6 +19,18 @@
#define DEV_CLASS_FBA 0x01
#define DEV_CLASS_ECKD 0x04
+#define DASD_DIAG_LC_INT_CODE 132
+#define DASD_DIAG_LC_INT_STATUS 133
+#define DASD_DIAG_LC_INT_PARM_31BIT 128
+#define DASD_DIAG_LC_INT_PARM_64BIT 4536
+#define DASD_DIAG_CODE_31BIT 0x03
+#define DASD_DIAG_CODE_64BIT 0x07
+
+#define DASD_DIAG_RWFLAG_ASYNC 0x02
+#define DASD_DIAG_RWFLAG_NOCACHE 0x01
+
+#define DASD_DIAG_FLAGA_FORMAT_64BIT 0x80
+
struct dasd_diag_characteristics {
u16 dev_nr;
u16 rdc_len;
@@ -32,35 +44,106 @@ struct dasd_diag_characteristics {
u8 rdev_features;
} __attribute__ ((packed, aligned(4)));
+struct dasd_diag_cms_label {
+ u8 label_id[4];
+ u8 vol_id[6];
+ u16 version_id;
+ u32 block_size;
+ u32 origin_ptr;
+ u32 usable_count;
+ u32 formatted_count;
+ u32 block_count;
+ u32 used_count;
+ u32 fst_size;
+ u32 fst_count;
+ u8 format_date[6];
+ u8 reserved1[2];
+ u32 disk_offset;
+ u32 map_block;
+ u32 hblk_disp;
+ u32 user_disp;
+ u8 reserved2[4];
+ u8 segment_name[8];
+} __attribute__ ((packed));
+
+#ifdef CONFIG_ARCH_S390X
+#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT
+
+typedef u64 blocknum_t;
+typedef s64 sblocknum_t;
+
+struct dasd_diag_bio {
+ u8 type;
+ u8 status;
+ u8 spare1[2];
+ u32 alet;
+ blocknum_t block_number;
+ u64 buffer;
+} __attribute__ ((packed, aligned(8)));
+
+struct dasd_diag_init_io {
+ u16 dev_nr;
+ u8 flaga;
+ u8 spare1[21];
+ u32 block_size;
+ u8 spare2[4];
+ blocknum_t offset;
+ sblocknum_t start_block;
+ blocknum_t end_block;
+ u8 spare3[8];
+} __attribute__ ((packed, aligned(8)));
+
+struct dasd_diag_rw_io {
+ u16 dev_nr;
+ u8 flaga;
+ u8 spare1[21];
+ u8 key;
+ u8 flags;
+ u8 spare2[2];
+ u32 block_count;
+ u32 alet;
+ u8 spare3[4];
+ u64 interrupt_params;
+ u64 bio_list;
+ u8 spare4[8];
+} __attribute__ ((packed, aligned(8)));
+#else /* CONFIG_ARCH_S390X */
+#define DASD_DIAG_FLAGA_DEFAULT 0x0
+
+typedef u32 blocknum_t;
+typedef s32 sblocknum_t;
+
struct dasd_diag_bio {
u8 type;
u8 status;
u16 spare1;
- u32 block_number;
+ blocknum_t block_number;
u32 alet;
u32 buffer;
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_init_io {
u16 dev_nr;
- u16 spare1[11];
+ u8 flaga;
+ u8 spare1[21];
u32 block_size;
- u32 offset;
- u32 start_block;
- u32 end_block;
- u32 spare2[6];
+ blocknum_t offset;
+ sblocknum_t start_block;
+ blocknum_t end_block;
+ u8 spare2[24];
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_rw_io {
u16 dev_nr;
- u16 spare1[11];
+ u8 flaga;
+ u8 spare1[21];
u8 key;
u8 flags;
- u16 spare2;
+ u8 spare2[2];
u32 block_count;
u32 alet;
u32 bio_list;
u32 interrupt_params;
- u32 spare3[5];
+ u8 spare3[20];
} __attribute__ ((packed, aligned(8)));
-
+#endif /* CONFIG_ARCH_S390X */
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 96c49349701f..a601c9a33541 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,7 @@
*
* gendisk related functions for the dasd driver.
*
- * $Revision: 1.50 $
+ * $Revision: 1.51 $
*/
#include <linux/config.h>
@@ -31,16 +31,12 @@ int
dasd_gendisk_alloc(struct dasd_device *device)
{
struct gendisk *gdp;
- int len, feature_ro;
+ int len;
/* Make sure the minor for this device exists. */
if (device->devindex >= DASD_PER_MAJOR)
return -EBUSY;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
-
gdp = alloc_disk(1 << DASD_PARTN_BITS);
if (!gdp)
return -ENOMEM;
@@ -75,7 +71,7 @@ dasd_gendisk_alloc(struct dasd_device *device)
sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
- if (feature_ro)
+ if (device->features & DASD_FEATURE_READONLY)
set_disk_ro(gdp, 1);
gdp->private_data = device;
gdp->queue = device->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a9f38b235981..9fab04f3056d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.64 $
+ * $Revision: 1.65 $
*/
#ifndef DASD_INT_H
@@ -286,6 +286,7 @@ struct dasd_device {
unsigned int bp_block; /* bytes per block */
unsigned int s2b_shift; /* log2 (bp_block/512) */
unsigned long flags; /* per device flags */
+ unsigned short features; /* copy of devmap-features (read-only!) */
/* Device discipline stuff. */
struct dasd_discipline *discipline;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 980c555aa538..789595b3fa09 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.45 $
+ * $Revision: 1.47 $
*
* i/o controls for the dasd driver.
*/
@@ -296,7 +296,6 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
{
struct dasd_device *device;
struct format_data_t fdata;
- int feature_ro;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -308,10 +307,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
if (device == NULL)
return -ENODEV;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
- if (feature_ro)
+ if (device->features & DASD_FEATURE_READONLY)
return -EROFS;
if (copy_from_user(&fdata, (void __user *) args,
sizeof (struct format_data_t)))
@@ -384,7 +380,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
struct dasd_device *device;
struct dasd_information2_t *dasd_info;
unsigned long flags;
- int rc, feature_ro;
+ int rc;
struct ccw_device *cdev;
device = bdev->bd_disk->private_data;
@@ -394,10 +390,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
if (!device->discipline->fill_info)
return -EINVAL;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
-
dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
if (dasd_info == NULL)
return -ENOMEM;
@@ -427,7 +419,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
(dasd_check_blocksize(device->bp_block)))
dasd_info->format = DASD_FORMAT_NONE;
- dasd_info->features |= feature_ro;
+ dasd_info->features |=
+ ((device->features & DASD_FEATURE_READONLY) != 0);
if (device->discipline)
memcpy(dasd_info->type, device->discipline->name, 4);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 43c34f8c5e68..fff9020d4886 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,7 @@
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.32 $
+ * $Revision: 1.33 $
*/
#include <linux/config.h>
@@ -55,7 +55,6 @@ dasd_devices_show(struct seq_file *m, void *v)
{
struct dasd_device *device;
char *substr;
- int feature;
device = dasd_device_from_devindex((unsigned long) v - 1);
if (IS_ERR(device))
@@ -79,10 +78,7 @@ dasd_devices_show(struct seq_file *m, void *v)
else
seq_printf(m, " is ????????");
/* Print devices features. */
- feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature < 0)
- return 0;
- substr = feature ? "(ro)" : " ";
+ substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
seq_printf(m, "%4s: ", substr);
/* Print device status information. */
switch ((device != NULL) ? device->state : -1) {
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index d5eefeaba50c..328d9cbc56a3 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -632,12 +632,9 @@ __raw3270_size_device(struct raw3270 *rp)
raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
- if (rc) {
+ if (rc)
/* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */
- if (rc == -EOPNOTSUPP && MACHINE_IS_VM)
- return __raw3270_size_device_vm(rp);
return rc;
- }
/* Wait for attention interrupt. */
#ifdef CONFIG_TN3270_CONSOLE
@@ -695,7 +692,10 @@ raw3270_size_device(struct raw3270 *rp)
down(&raw3270_init_sem);
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
- rc = __raw3270_size_device(rp);
+ if (MACHINE_IS_VM)
+ rc = __raw3270_size_device_vm(rp);
+ else
+ rc = __raw3270_size_device(rp);
raw3270_init_view.dev = 0;
rp->view = 0;
up(&raw3270_init_sem);
@@ -710,6 +710,12 @@ raw3270_size_device(struct raw3270 *rp)
rp->model = 4;
if (rp->rows == 27 && rp->cols == 132)
rp->model = 5;
+ } else {
+ /* Couldn't detect size. Use default model 2. */
+ rp->model = 2;
+ rp->rows = 24;
+ rp->cols = 80;
+ return 0;
}
return rc;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index ea813bdce1d6..185bc73c3ecd 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.134 $
+ * $Revision: 1.135 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -815,8 +815,9 @@ __clear_subchannel_easy(unsigned int schid)
struct tpi_info ti;
if (tpi(&ti)) {
- tsch(schid, (struct irb *)__LC_IRB);
- return 0;
+ tsch(ti.irq, (struct irb *)__LC_IRB);
+ if (ti.irq == schid)
+ return 0;
}
udelay(100);
}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index ee7a05e0c3ba..fbe4202a3f6f 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <asm/ccwdev.h>
-#include <asm/qdio.h>
+#include <asm/cio.h>
#include "cio.h"
#include "cio_debug.h"
@@ -21,7 +21,6 @@
#include "device.h"
#include "chsc.h"
#include "ioasm.h"
-#include "qdio.h"
int
device_is_online(struct subchannel *sch)
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 02d01a0de16c..ad3fe5aeb663 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.56 $
+ * $Revision: 1.57 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -19,14 +19,12 @@
#include <asm/ccwdev.h>
#include <asm/idals.h>
-#include <asm/qdio.h>
#include "cio.h"
#include "cio_debug.h"
#include "css.h"
#include "chsc.h"
#include "device.h"
-#include "qdio.h"
int
ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index c874607d9a80..45480a2bc4c0 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -21,7 +21,7 @@ struct tpi_info {
* Some S390 specific IO instructions as inline
*/
-extern __inline__ int stsch(int irq, volatile struct schib *addr)
+static inline int stsch(int irq, volatile struct schib *addr)
{
int ccode;
@@ -36,7 +36,7 @@ extern __inline__ int stsch(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int msch(int irq, volatile struct schib *addr)
+static inline int msch(int irq, volatile struct schib *addr)
{
int ccode;
@@ -51,7 +51,7 @@ extern __inline__ int msch(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int msch_err(int irq, volatile struct schib *addr)
+static inline int msch_err(int irq, volatile struct schib *addr)
{
int ccode;
@@ -79,7 +79,7 @@ extern __inline__ int msch_err(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int tsch(int irq, volatile struct irb *addr)
+static inline int tsch(int irq, volatile struct irb *addr)
{
int ccode;
@@ -94,7 +94,7 @@ extern __inline__ int tsch(int irq, volatile struct irb *addr)
return ccode;
}
-extern __inline__ int tpi( volatile struct tpi_info *addr)
+static inline int tpi( volatile struct tpi_info *addr)
{
int ccode;
@@ -108,7 +108,7 @@ extern __inline__ int tpi( volatile struct tpi_info *addr)
return ccode;
}
-extern __inline__ int ssch(int irq, volatile struct orb *addr)
+static inline int ssch(int irq, volatile struct orb *addr)
{
int ccode;
@@ -123,7 +123,7 @@ extern __inline__ int ssch(int irq, volatile struct orb *addr)
return ccode;
}
-extern __inline__ int rsch(int irq)
+static inline int rsch(int irq)
{
int ccode;
@@ -138,7 +138,7 @@ extern __inline__ int rsch(int irq)
return ccode;
}
-extern __inline__ int csch(int irq)
+static inline int csch(int irq)
{
int ccode;
@@ -153,7 +153,7 @@ extern __inline__ int csch(int irq)
return ccode;
}
-extern __inline__ int hsch(int irq)
+static inline int hsch(int irq)
{
int ccode;
@@ -168,7 +168,7 @@ extern __inline__ int hsch(int irq)
return ccode;
}
-extern __inline__ int xsch(int irq)
+static inline int xsch(int irq)
{
int ccode;
@@ -183,7 +183,7 @@ extern __inline__ int xsch(int irq)
return ccode;
}
-extern __inline__ int chsc(void *chsc_area)
+static inline int chsc(void *chsc_area)
{
int cc;
@@ -198,7 +198,7 @@ extern __inline__ int chsc(void *chsc_area)
return cc;
}
-extern __inline__ int iac( void)
+static inline int iac( void)
{
int ccode;
@@ -210,7 +210,7 @@ extern __inline__ int iac( void)
return ccode;
}
-extern __inline__ int rchp(int chpid)
+static inline int rchp(int chpid)
{
int ccode;
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index bcabac7a7c46..e319e78b5ea2 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -27,7 +27,7 @@
#ifndef _Z90COMMON_H_
#define _Z90COMMON_H_
-#define VERSION_Z90COMMON_H "$Revision: 1.16 $"
+#define VERSION_Z90COMMON_H "$Revision: 1.17 $"
#define RESPBUFFSIZE 256
@@ -164,5 +164,4 @@ struct CPRBX {
#define UMIN(a,b) ((a) < (b) ? (a) : (b))
#define IS_EVEN(x) ((x) == (2 * ((x) / 2)))
-
#endif
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index beb6a5e0da22..c215e0889736 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -32,7 +32,7 @@
#include "z90crypt.h"
#include "z90common.h"
-#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $"
+#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
char z90hardware_version[] __initdata =
"z90hardware.o (" VERSION_Z90HARDWARE_C "/"
@@ -283,48 +283,6 @@ struct type6_msg {
struct CPRB CPRB;
};
-union request_msg {
- union type4_msg t4msg;
- struct type6_msg t6msg;
-};
-
-struct request_msg_ext {
- int q_nr;
- unsigned char *psmid;
- union request_msg reqMsg;
-};
-
-struct type82_hdr {
- unsigned char reserved1;
- unsigned char type;
- unsigned char reserved2[2];
- unsigned char reply_code;
- unsigned char reserved3[3];
-};
-
-#define TYPE82_RSP_CODE 0x82
-
-#define REPLY_ERROR_MACHINE_FAILURE 0x10
-#define REPLY_ERROR_PREEMPT_FAILURE 0x12
-#define REPLY_ERROR_CHECKPT_FAILURE 0x14
-#define REPLY_ERROR_MESSAGE_TYPE 0x20
-#define REPLY_ERROR_INVALID_COMM_CD 0x21
-#define REPLY_ERROR_INVALID_MSG_LEN 0x23
-#define REPLY_ERROR_RESERVD_FIELD 0x24
-#define REPLY_ERROR_FORMAT_FIELD 0x29
-#define REPLY_ERROR_INVALID_COMMAND 0x30
-#define REPLY_ERROR_MALFORMED_MSG 0x40
-#define REPLY_ERROR_RESERVED_FIELDO 0x50
-#define REPLY_ERROR_WORD_ALIGNMENT 0x60
-#define REPLY_ERROR_MESSAGE_LENGTH 0x80
-#define REPLY_ERROR_OPERAND_INVALID 0x82
-#define REPLY_ERROR_OPERAND_SIZE 0x84
-#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85
-#define REPLY_ERROR_RESERVED_FIELD 0x88
-#define REPLY_ERROR_TRANSPORT_FAIL 0x90
-#define REPLY_ERROR_PACKET_TRUNCATED 0xA0
-#define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0
-
struct type86_hdr {
unsigned char reserved1;
unsigned char type;
@@ -338,7 +296,7 @@ struct type86_hdr {
#define TYPE86_FMT2 0x02
struct type86_fmt2_msg {
- struct type86_hdr hdr;
+ struct type86_hdr header;
unsigned char reserved[4];
unsigned char apfs[4];
unsigned int count1;
@@ -538,6 +496,8 @@ static struct function_and_rules_block static_pke_function_and_rulesX = {
{'M','R','P',' ',' ',' ',' ',' '}
};
+static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+
struct T6_keyBlock_hdrX {
unsigned short blen;
unsigned short ulen;
@@ -688,9 +648,38 @@ static struct cca_public_sec static_cca_pub_sec = {
#define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724
-#define CALLER_HEADER 12
+struct error_hdr {
+ unsigned char reserved1;
+ unsigned char type;
+ unsigned char reserved2[2];
+ unsigned char reply_code;
+ unsigned char reserved3[3];
+};
-static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+#define TYPE82_RSP_CODE 0x82
+
+#define REP82_ERROR_MACHINE_FAILURE 0x10
+#define REP82_ERROR_PREEMPT_FAILURE 0x12
+#define REP82_ERROR_CHECKPT_FAILURE 0x14
+#define REP82_ERROR_MESSAGE_TYPE 0x20
+#define REP82_ERROR_INVALID_COMM_CD 0x21
+#define REP82_ERROR_INVALID_MSG_LEN 0x23
+#define REP82_ERROR_RESERVD_FIELD 0x24
+#define REP82_ERROR_FORMAT_FIELD 0x29
+#define REP82_ERROR_INVALID_COMMAND 0x30
+#define REP82_ERROR_MALFORMED_MSG 0x40
+#define REP82_ERROR_RESERVED_FIELDO 0x50
+#define REP82_ERROR_WORD_ALIGNMENT 0x60
+#define REP82_ERROR_MESSAGE_LENGTH 0x80
+#define REP82_ERROR_OPERAND_INVALID 0x82
+#define REP82_ERROR_OPERAND_SIZE 0x84
+#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
+#define REP82_ERROR_RESERVED_FIELD 0x88
+#define REP82_ERROR_TRANSPORT_FAIL 0x90
+#define REP82_ERROR_PACKET_TRUNCATED 0xA0
+#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
+
+#define CALLER_HEADER 12
static inline int
testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
@@ -1212,9 +1201,9 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
struct ap_status_word stat_word;
enum devstat stat;
int ccode;
+ u32 *q_nr_p = (u32 *)msg_ext;
- ((struct request_msg_ext *) msg_ext)->q_nr =
- (dev_nr << SKIP_BITL) + cdx;
+ *q_nr_p = (dev_nr << SKIP_BITL) + cdx;
PDEBUG("msg_len passed to sen: %d\n", msg_len);
PDEBUG("q number passed to sen: %02x%02x%02x%02x\n",
msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]);
@@ -2104,7 +2093,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
int *respbufflen_p, unsigned char *resp_buff)
{
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
- struct type82_hdr *t82h_p = (struct type82_hdr *) response;
+ struct error_hdr *errh_p = (struct error_hdr *) response;
struct type84_hdr *t84h_p = (struct type84_hdr *) response;
struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
int reply_code, service_rc, service_rs, src_l;
@@ -2117,12 +2106,13 @@ convert_response(unsigned char *response, unsigned char *buffer,
service_rc = 0;
service_rs = 0;
src_l = 0;
- switch (t82h_p->type) {
+ switch (errh_p->type) {
case TYPE82_RSP_CODE:
- reply_code = t82h_p->reply_code;
- src_p = (unsigned char *)t82h_p;
- PRINTK("Hardware error: Type 82 Message Header: "
+ reply_code = errh_p->reply_code;
+ src_p = (unsigned char *)errh_p;
+ PRINTK("Hardware error: Type %02X Message Header: "
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ errh_p->type,
src_p[0], src_p[1], src_p[2], src_p[3],
src_p[4], src_p[5], src_p[6], src_p[7]);
break;
@@ -2131,7 +2121,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_p = response + (int)t84h_p->len - src_l;
break;
case TYPE86_RSP_CODE:
- reply_code = t86m_p->hdr.reply_code;
+ reply_code = t86m_p->header.reply_code;
if (reply_code != 0)
break;
cprb_p = (struct CPRB *)
@@ -2143,6 +2133,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
le2toI(cprb_p->ccp_rscode, &service_rs);
if ((service_rc == 8) && (service_rs == 66))
PDEBUG("Bad block format on PCICC\n");
+ else if ((service_rc == 8) && (service_rs == 65))
+ PDEBUG("Probably an even modulus on "
+ "PCICC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCICC\n");
unset_ext_bitlens();
@@ -2155,7 +2148,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
return REC_USE_PCICA;
}
else
- PRINTK("service rc/rs: %d/%d\n",
+ PRINTK("service rc/rs (PCICC): %d/%d\n",
service_rc, service_rs);
return REC_OPERAND_INV;
}
@@ -2169,7 +2162,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (service_rc != 0) {
service_rs = (int) cprbx_p->ccp_rscode;
if ((service_rc == 8) && (service_rs == 66))
- PDEBUG("Bad block format on PCXICC\n");
+ PDEBUG("Bad block format on PCIXCC\n");
+ else if ((service_rc == 8) && (service_rs == 65))
+ PDEBUG("Probably an even modulus on "
+ "PCIXCC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCIXCC\n");
unset_ext_bitlens();
@@ -2182,7 +2178,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
return REC_USE_PCICA;
}
else
- PRINTK("service rc/rs: %d/%d\n",
+ PRINTK("service rc/rs (PCIXCC): %d/%d\n",
service_rc, service_rs);
return REC_OPERAND_INV;
}
@@ -2195,20 +2191,25 @@ convert_response(unsigned char *response, unsigned char *buffer,
}
break;
default:
+ src_p = (unsigned char *)errh_p;
+ PRINTK("Unrecognized Message Header: "
+ "%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ src_p[0], src_p[1], src_p[2], src_p[3],
+ src_p[4], src_p[5], src_p[6], src_p[7]);
return REC_BAD_MESSAGE;
}
if (reply_code)
switch (reply_code) {
- case REPLY_ERROR_OPERAND_INVALID:
+ case REP82_ERROR_OPERAND_INVALID:
return REC_OPERAND_INV;
- case REPLY_ERROR_OPERAND_SIZE:
+ case REP82_ERROR_OPERAND_SIZE:
return REC_OPERAND_SIZE;
- case REPLY_ERROR_EVEN_MOD_IN_OPND:
+ case REP82_ERROR_EVEN_MOD_IN_OPND:
return REC_EVEN_MOD;
- case REPLY_ERROR_MESSAGE_TYPE:
+ case REP82_ERROR_MESSAGE_TYPE:
return WRONG_DEVICE_TYPE;
- case REPLY_ERROR_TRANSPORT_FAIL:
+ case REP82_ERROR_TRANSPORT_FAIL:
PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
t86m_p->apfs[0], t86m_p->apfs[1],
t86m_p->apfs[2], t86m_p->apfs[3]);
@@ -2229,7 +2230,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
PDEBUG("Length returned = %d\n", src_l);
tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l;
memcpy(tgt_p, src_p, src_l);
- if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
+ if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
return REC_INVALID_PAD;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 9ec29bb41b28..6aeef3bacc33 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/interrupt.h> // for tasklets
#include <linux/ioctl32.h>
+#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kobject_uevent.h>
@@ -39,19 +40,8 @@
#include <linux/version.h>
#include "z90crypt.h"
#include "z90common.h"
-#ifndef Z90CRYPT_USE_HOTPLUG
-#include <linux/miscdevice.h>
-#endif
-
-#define VERSION_CODE(vers, rel, seq) (((vers)<<16) | ((rel)<<8) | (seq))
-#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0) /* version < 2.4 */
-# error "This kernel is too old: not supported"
-#endif
-#if LINUX_VERSION_CODE > VERSION_CODE(2,7,0) /* version > 2.6 */
-# error "This kernel is too recent: not supported by this file"
-#endif
-#define VERSION_Z90MAIN_C "$Revision: 1.57 $"
+#define VERSION_Z90MAIN_C "$Revision: 1.62 $"
static char z90main_version[] __initdata =
"z90main.o (" VERSION_Z90MAIN_C "/"
@@ -63,21 +53,12 @@ extern char z90hardware_version[];
* Defaults that may be modified.
*/
-#ifndef Z90CRYPT_USE_HOTPLUG
/**
* You can specify a different minor at compile time.
*/
#ifndef Z90CRYPT_MINOR
#define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR
#endif
-#else
-/**
- * You can specify a different major at compile time.
- */
-#ifndef Z90CRYPT_MAJOR
-#define Z90CRYPT_MAJOR 0
-#endif
-#endif
/**
* You can specify a different domain at compile time or on the insmod
@@ -97,7 +78,7 @@ extern char z90hardware_version[];
* older than CLEANUPTIME seconds in the past.
*/
#ifndef CLEANUPTIME
-#define CLEANUPTIME 20
+#define CLEANUPTIME 15
#endif
/**
@@ -298,6 +279,10 @@ struct z90crypt {
* it contains the request; at READ, the response. The function
* send_to_crypto_device converts the request to device-dependent
* form and use the caller's OPEN-allocated buffer for the response.
+ *
+ * For the contents of caller_dev_dep_req and caller_dev_dep_req_p
+ * because that points to it, see the discussion in z90hardware.c.
+ * Search for "extended request message block".
*/
struct caller {
int caller_buf_l; // length of original request
@@ -398,24 +383,9 @@ static int z90crypt_status_write(struct file *, const char __user *,
unsigned long, void *);
/**
- * Hotplug support
- */
-
-#ifdef Z90CRYPT_USE_HOTPLUG
-#define Z90CRYPT_HOTPLUG_ADD 1
-#define Z90CRYPT_HOTPLUG_REMOVE 2
-
-static void z90crypt_hotplug_event(int, int, int);
-#endif
-
-/**
* Storage allocated at initialization and used throughout the life of
* this insmod
*/
-#ifdef Z90CRYPT_USE_HOTPLUG
-static int z90crypt_major = Z90CRYPT_MAJOR;
-#endif
-
static int domain = DOMAIN_INDEX;
static struct z90crypt z90crypt;
static int quiesce_z90crypt;
@@ -444,14 +414,12 @@ static struct file_operations z90crypt_fops = {
.release = z90crypt_release
};
-#ifndef Z90CRYPT_USE_HOTPLUG
static struct miscdevice z90crypt_misc_device = {
.minor = Z90CRYPT_MINOR,
.name = DEV_NAME,
.fops = &z90crypt_fops,
.devfs_name = DEV_NAME
};
-#endif
/**
* Documentation values.
@@ -603,7 +571,6 @@ z90crypt_init_module(void)
return -EINVAL;
}
-#ifndef Z90CRYPT_USE_HOTPLUG
/* Register as misc device with given minor (or get a dynamic one). */
result = misc_register(&z90crypt_misc_device);
if (result < 0) {
@@ -611,18 +578,6 @@ z90crypt_init_module(void)
z90crypt_misc_device.minor, result);
return result;
}
-#else
- /* Register the major (or get a dynamic one). */
- result = register_chrdev(z90crypt_major, REG_NAME, &z90crypt_fops);
- if (result < 0) {
- PRINTKW("register_chrdev (major %d) failed with %d.\n",
- z90crypt_major, result);
- return result;
- }
-
- if (z90crypt_major == 0)
- z90crypt_major = result;
-#endif
PDEBUG("Registered " DEV_NAME " with result %d\n", result);
@@ -645,11 +600,6 @@ z90crypt_init_module(void)
} else
PRINTK("No devices at startup\n");
-#ifdef Z90CRYPT_USE_HOTPLUG
- /* generate hotplug event for device node generation */
- z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_ADD);
-#endif
-
/* Initialize globals. */
spin_lock_init(&queuespinlock);
@@ -701,17 +651,10 @@ z90crypt_init_module(void)
return 0; // success
init_module_cleanup:
-#ifndef Z90CRYPT_USE_HOTPLUG
if ((nresult = misc_deregister(&z90crypt_misc_device)))
PRINTK("misc_deregister failed with %d.\n", nresult);
else
PDEBUG("misc_deregister successful.\n");
-#else
- if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
- PRINTK("unregister_chrdev failed with %d.\n", nresult);
- else
- PDEBUG("unregister_chrdev successful.\n");
-#endif
return result; // failure
}
@@ -728,19 +671,10 @@ z90crypt_cleanup_module(void)
remove_proc_entry("driver/z90crypt", 0);
-#ifndef Z90CRYPT_USE_HOTPLUG
if ((nresult = misc_deregister(&z90crypt_misc_device)))
PRINTK("misc_deregister failed with %d.\n", nresult);
else
PDEBUG("misc_deregister successful.\n");
-#else
- z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_REMOVE);
-
- if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
- PRINTK("unregister_chrdev failed with %d.\n", nresult);
- else
- PDEBUG("unregister_chrdev successful.\n");
-#endif
/* Remove the tasks */
tasklet_kill(&reader_tasklet);
@@ -748,6 +682,9 @@ z90crypt_cleanup_module(void)
del_timer(&config_timer);
del_timer(&cleanup_timer);
+ if (z90_device_work)
+ destroy_workqueue(z90_device_work);
+
destroy_z90crypt();
PRINTKN("Unloaded.\n");
@@ -766,8 +703,6 @@ z90crypt_cleanup_module(void)
* z90crypt_status_write
* disable_card
* enable_card
- * scan_char
- * scan_string
*
* Helper functions:
* z90crypt_rsa
@@ -1057,9 +992,10 @@ remove_device(struct device *device_p)
* The MCL must be applied and the newer bitlengths enabled for these to work.
*
* Card Type Old limit New limit
+ * PCICA ??-2048 same (the lower limit is less than 128 bit...)
* PCICC 512-1024 512-2048
- * PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+)
- * PCIXCC_MCL3 512-2048 128-2048
+ * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card)
+ * PCIXCC_MCL3 ----- 128-2048
* CEX2C 512-2048 128-2048
*
* ext_bitlens (extended bitlengths) is a global, since you should not apply an
@@ -1104,7 +1040,7 @@ select_device_type(int *dev_type_p, int bytelength)
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
/**
* bitlength is a factor, PCICA is the most capable, even with
- * the new MCL.
+ * the new MCL for PCIXCC.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
@@ -2144,73 +2080,15 @@ enable_card(int card_index)
z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--;
}
-static inline int
-scan_char(unsigned char *bf, unsigned int len,
- unsigned int *offs, unsigned int *p_eof, unsigned char c)
-{
- unsigned int i, found;
-
- found = 0;
- for (i = 0; i < len; i++) {
- if (bf[i] == c) {
- found = 1;
- break;
- }
- if (bf[i] == '\0') {
- *p_eof = 1;
- break;
- }
- if (bf[i] == '\n') {
- break;
- }
- }
- *offs = i+1;
- return found;
-}
-
-static inline int
-scan_string(unsigned char *bf, unsigned int len,
- unsigned int *offs, unsigned int *p_eof, unsigned char *s)
-{
- unsigned int temp_len, temp_offs, found, eof;
-
- temp_len = temp_offs = found = eof = 0;
- while (!eof && !found) {
- found = scan_char(bf+temp_len, len-temp_len,
- &temp_offs, &eof, *s);
-
- temp_len += temp_offs;
- if (eof) {
- found = 0;
- break;
- }
-
- if (found) {
- if (len >= temp_offs+strlen(s)) {
- found = !strncmp(bf+temp_len-1, s, strlen(s));
- if (found) {
- *offs = temp_len+strlen(s)-1;
- break;
- }
- } else {
- found = 0;
- *p_eof = 1;
- break;
- }
- }
- }
- return found;
-}
-
static int
z90crypt_status_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
- int i, j, len, offs, found, eof;
- unsigned char *lbuf;
+ int j, eol;
+ unsigned char *lbuf, *ptr;
unsigned int local_count;
-#define LBUFSIZE 600
+#define LBUFSIZE 1200
lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
if (!lbuf) {
PRINTK("kmalloc failed!\n");
@@ -2227,49 +2105,46 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
return -EFAULT;
}
- lbuf[local_count-1] = '\0';
+ lbuf[local_count] = '\0';
- len = 0;
- eof = 0;
- found = 0;
- while (!eof) {
- found = scan_string(lbuf+len, local_count-len, &offs, &eof,
- "Online devices");
- len += offs;
- if (found == 1)
- break;
+ ptr = strstr(lbuf, "Online devices");
+ if (ptr == 0) {
+ PRINTK("Unable to parse data (missing \"Online devices\")\n");
+ kfree(lbuf);
+ return count;
}
- if (eof) {
+ ptr = strstr(ptr, "\n");
+ if (ptr == 0) {
+ PRINTK("Unable to parse data (missing newline after \"Online devices\")\n");
kfree(lbuf);
return count;
}
+ ptr++;
- if (found)
- found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n');
-
- if (!found || eof) {
+ if (strstr(ptr, "Waiting work element counts") == NULL) {
+ PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n");
kfree(lbuf);
return count;
}
- len += offs;
j = 0;
- for (i = 0; i < 80; i++) {
- switch (*(lbuf+len+i)) {
+ eol = 0;
+ while ((j < 64) && (*ptr != '\0')) {
+ switch (*ptr) {
case '\t':
case ' ':
break;
case '\n':
default:
- eof = 1;
+ eol = 1;
break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
+ case '0': // no device
+ case '1': // PCICA
+ case '2': // PCICC
+ case '3': // PCIXCC_MCL2
+ case '4': // PCIXCC_MCL3
+ case '5': // CEX2C
j++;
break;
case 'd':
@@ -2283,8 +2158,9 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
j++;
break;
}
- if (eof)
+ if (eol)
break;
+ ptr++;
}
kfree(lbuf);
@@ -3479,45 +3355,5 @@ probe_PCIXCC_type(struct device *devPtr)
return rv;
}
-#ifdef Z90CRYPT_USE_HOTPLUG
-static void
-z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
-{
-#ifdef CONFIG_HOTPLUG
- char *argv[3];
- char *envp[6];
- char major[20];
- char minor[20];
-
- sprintf(major, "MAJOR=%d", dev_major);
- sprintf(minor, "MINOR=%d", dev_minor);
-
- argv[0] = hotplug_path;
- argv[1] = "z90crypt";
- argv[2] = 0;
-
- envp[0] = "HOME=/";
- envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
- switch (action) {
- case Z90CRYPT_HOTPLUG_ADD:
- envp[2] = "ACTION=add";
- break;
- case Z90CRYPT_HOTPLUG_REMOVE:
- envp[2] = "ACTION=remove";
- break;
- default:
- BUG();
- break;
- }
- envp[3] = major;
- envp[4] = minor;
- envp[5] = 0;
-
- call_usermodehelper(argv[0], argv, envp, 0);
-#endif
-}
-#endif
-
module_init(z90crypt_init_module);
module_exit(z90crypt_cleanup_module);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 24c0af49c25c..3092473991a7 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2,9 +2,9 @@
* drivers/s390/net/claw.c
* ESCON CLAW network driver
*
- * $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $
+ * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $
*
- * Linux fo zSeries version
+ * Linux for zSeries version
* Copyright (C) 2002,2005 IBM Corporation
* Author(s) Original code written by:
* Kazuo Iimura (iimura@jp.ibm.com)
@@ -431,12 +431,12 @@ claw_pack_skb(struct claw_privbk *privptr)
if (!skb_queue_empty(&p_ch->collect_queue)) {
/* some data */
held_skb = skb_dequeue(&p_ch->collect_queue);
- if (p_env->packing != DO_PACKED)
- return held_skb;
if (held_skb)
- atomic_dec(&held_skb->users);
+ dev_kfree_skb_any(held_skb);
else
return NULL;
+ if (p_env->packing != DO_PACKED)
+ return held_skb;
/* get a new SKB we will pack at least one */
new_skb = dev_alloc_skb(p_env->write_size);
if (new_skb == NULL) {
@@ -455,7 +455,7 @@ claw_pack_skb(struct claw_privbk *privptr)
privptr->stats.tx_packets++;
so_far += held_skb->len;
pkt_cnt++;
- dev_kfree_skb_irq(held_skb);
+ dev_kfree_skb_any(held_skb);
held_skb = skb_dequeue(&p_ch->collect_queue);
if (held_skb)
atomic_dec(&held_skb->users);
@@ -1092,7 +1092,7 @@ claw_release(struct net_device *dev)
}
}
if (privptr->pk_skb != NULL) {
- dev_kfree_skb(privptr->pk_skb);
+ dev_kfree_skb_any(privptr->pk_skb);
privptr->pk_skb = NULL;
}
if(privptr->buffs_alloc != 1) {
@@ -2016,7 +2016,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
p_buf=(struct ccwbk*)privptr->p_end_ccw;
dumpit((char *)p_buf, sizeof(struct endccw));
#endif
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
if (linkid==0) {
lock=LOCK_NO;
}
@@ -4061,7 +4061,7 @@ claw_purge_skb_queue(struct sk_buff_head *q)
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb_any(skb);
}
}
@@ -4410,7 +4410,7 @@ claw_init(void)
#else
"compiled into kernel "
#endif
- " $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ \n");
+ " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n");
#ifdef FUNCTRACE
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 5bb255e02acc..4191fd9d4d11 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -240,7 +240,7 @@ s390_revalidate_registers(struct mci *mci)
* Floating point control register can't be restored.
* Task will be terminated.
*/
- asm volatile ("lfpc 0(%0)" : : "a" (&zero));
+ asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
kill_task = 1;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index e17b4d58a9f6..bfe3ba73bc0f 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1299,13 +1299,10 @@ struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
u32 d_id)
{
- struct zfcp_port *port, *tmp_port;
+ struct zfcp_port *port;
int check_wwpn;
- scsi_id_t scsi_id;
- int found;
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
-
/*
* check that there is no port with this WWPN already in list
*/
@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
} else {
snprintf(port->sysfs_device.bus_id,
BUS_ID_SIZE, "0x%016llx", wwpn);
- port->sysfs_device.parent = &adapter->ccw_device->dev;
+ port->sysfs_device.parent = &adapter->ccw_device->dev;
}
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
zfcp_port_get(port);
- scsi_id = 1;
- found = 0;
write_lock_irq(&zfcp_data.config_lock);
- list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
- if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
- &tmp_port->status))
- continue;
- if (tmp_port->scsi_id != scsi_id) {
- found = 1;
- break;
- }
- scsi_id++;
- }
- port->scsi_id = scsi_id;
- if (found)
- list_add_tail(&port->list, &tmp_port->list);
- else
- list_add_tail(&port->list, &adapter->port_list_head);
+ list_add_tail(&port->list, &adapter->port_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
@@ -1427,6 +1408,9 @@ zfcp_port_dequeue(struct zfcp_port *port)
list_del(&port->list);
port->adapter->ports--;
write_unlock_irq(&zfcp_data.config_lock);
+ if (port->rport)
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
zfcp_adapter_put(port->adapter);
zfcp_sysfs_port_remove_files(&port->sysfs_device,
atomic_read(&port->status));
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 0fc46381fc22..b30abab77da3 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -202,9 +202,19 @@ static int
zfcp_ccw_set_offline(struct ccw_device *ccw_device)
{
struct zfcp_adapter *adapter;
+ struct zfcp_port *port;
+ struct fc_rport *rport;
down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(&ccw_device->dev);
+ /* might be racy, but we cannot take config_lock due to the fact that
+ fc_remote_port_delete might sleep */
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (port->rport) {
+ rport = port->rport;
+ port->rport = NULL;
+ fc_remote_port_delete(rport);
+ }
zfcp_erp_adapter_shutdown(adapter, 0);
zfcp_erp_wait(adapter);
zfcp_adapter_scsi_unregister(adapter);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 4103b5be7683..455e902533a9 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -906,6 +906,7 @@ struct zfcp_adapter {
*/
struct zfcp_port {
struct device sysfs_device; /* sysfs device */
+ struct fc_rport *rport; /* rport of fc transport class */
struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -916,7 +917,6 @@ struct zfcp_port {
list */
u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */
- scsi_id_t scsi_id; /* own SCSI ID */
wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */
fc_id_t d_id; /* D_ID */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 0cf31f7d1c0f..cb4f612550ba 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
if ((result == ZFCP_ERP_SUCCEEDED)
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status))
- && (!unit->device))
- scsi_add_device(unit->port->adapter->scsi_host, 0,
- unit->port->scsi_id, unit->scsi_lun);
+ && !unit->device
+ && port->rport)
+ scsi_add_device(port->adapter->scsi_host, 0,
+ port->rport->scsi_target_id,
+ unit->scsi_lun);
zfcp_unit_put(unit);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if ((result == ZFCP_ERP_SUCCEEDED)
+ && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+ &port->status)
+ && !port->rport) {
+ struct fc_rport_identifiers ids;
+ ids.node_name = port->wwnn;
+ ids.port_name = port->wwpn;
+ ids.port_id = port->d_id;
+ ids.roles = FC_RPORT_ROLE_FCP_TARGET;
+ port->rport =
+ fc_remote_port_add(adapter->scsi_host, 0, &ids);
+ if (!port->rport)
+ ZFCP_LOG_NORMAL("failed registration of rport"
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+ port->wwpn);
+ }
zfcp_port_put(port);
break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 42df7e57eeae..cd98a2de9f8f 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
struct timer_list *);
+extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
+extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0d9f20edc490..c007b6424e74 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
}
+ zfcp_set_fc_host_attrs(adapter);
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b61d309352c3..31a76065cf28 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
struct zfcp_unit *unit, *retval = NULL;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id != port->scsi_id)
+ if (!port->rport || (id != port->rport->scsi_target_id))
continue;
list_for_each_entry(unit, &port->unit_list_head, list) {
if (lun == unit->scsi_lun) {
@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id == port->scsi_id)
+ if (port->rport && (id == port->rport->scsi_target_id))
return port;
}
return (struct zfcp_port *) NULL;
@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
int retval;
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
- struct Scsi_Host *scsi_host = scpnt->device->host;
if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
@@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
{
int retval = 0;
struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
int retval = 0;
struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with "
@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
shost = adapter->scsi_host;
if (!shost)
return;
+ fc_remove_host(shost);
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
+void
+zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter)
+{
+ struct Scsi_Host *shost = adapter->scsi_host;
+
+ fc_host_node_name(shost) = adapter->wwnn;
+ fc_host_port_name(shost) = adapter->wwpn;
+ strncpy(fc_host_serial_number(shost), adapter->serial_number,
+ min(FC_SERIAL_NUMBER_SIZE, 32));
+ fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+}
+
struct fc_function_template zfcp_transport_functions = {
.get_starget_port_id = zfcp_get_port_id,
.get_starget_port_name = zfcp_get_port_name,
@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
.show_starget_node_name = 1,
+ .show_rport_supported_classes = 1,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_serial_number = 1,
};
/**
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 7a84c7d474d9..c55e82d91deb 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -67,7 +67,6 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
-ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -263,7 +262,6 @@ static struct attribute_group zfcp_port_common_attr_group = {
static struct attribute *zfcp_port_no_ns_attrs[] = {
&dev_attr_unit_add.attr,
&dev_attr_unit_remove.attr,
- &dev_attr_scsi_id.attr,
NULL
};
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig
index a41778a490d6..3a8152906bf6 100644
--- a/drivers/sbus/char/Kconfig
+++ b/drivers/sbus/char/Kconfig
@@ -69,11 +69,40 @@ config SUN_JSFLASH
If you say Y here, you will be able to boot from your JavaStation's
Flash memory.
-# XXX Why don't we do "source drivers/char/Config.in" somewhere?
-# no shit
-config RTC
- tristate "PC-style Real Time Clock Support"
- depends on PCI && EXPERIMENTAL && SPARC32
+config BBC_I2C
+ tristate "UltraSPARC-III bootbus i2c controller driver"
+ depends on PCI && SPARC64
+ help
+ The BBC devices on the UltraSPARC III have two I2C controllers. The
+ first I2C controller connects mainly to configuration PROMs (NVRAM,
+ CPU configuration, DIMM types, etc.). The second I2C controller
+ connects to environmental control devices such as fans and
+ temperature sensors. The second controller also connects to the
+ smartcard reader, if present. Say Y to enable support for these.
+
+config ENVCTRL
+ tristate "SUNW, envctrl support"
+ depends on PCI && SPARC64
+ help
+ Kernel support for temperature and fan monitoring on Sun SME
+ machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called envctrl.
+
+config DISPLAY7SEG
+ tristate "7-Segment Display support"
+ depends on PCI && SPARC64
+ ---help---
+ This is the driver for the 7-segment display and LED present on
+ Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+ To compile this driver as a module, choose M here: the
+ module will be called display7seg.
+
+ If you do not have a CompactPCI model CP1400 or CP1500, or
+ another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
+ you should say N to this option.
endmenu
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index d96cc47de566..672f9f2b2163 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -871,8 +871,7 @@ static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * reg
#ifdef AURORA_INT_DEBUG
static void aurora_timer (unsigned long ignored);
-static struct timer_list aurora_poll_timer =
- TIMER_INITIALIZER(aurora_timer, 0, 0);
+static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0);
static void
aurora_timer (unsigned long ignored)
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index d44205d52bf3..d89f83f769f5 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -5,6 +5,7 @@
*/
#define __KERNEL_SYSCALLS__
+static int errno;
#include <linux/kernel.h>
#include <linux/kthread.h>
@@ -13,8 +14,6 @@
#include <linux/delay.h>
#include <asm/oplib.h>
#include <asm/ebus.h>
-static int errno;
-#include <asm/unistd.h>
#include "bbc_i2c.h"
#include "max1617.h"
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index 87302fb14885..ccb20a6f5f36 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -295,8 +295,7 @@ static unsigned short get_pins(unsigned minor)
static void snooze(unsigned long snooze_time, unsigned minor)
{
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(snooze_time + 1);
+ schedule_timeout_uninterruptible(snooze_time + 1);
}
static int wait_for(unsigned short set, unsigned short clr,
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index dbad7f35eb0a..24ed5893b4f0 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -14,7 +14,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
-#include <linux/ioport.h> /* request_region, check_region */
+#include <linux/ioport.h> /* request_region */
#include <asm/atomic.h>
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index d765cc1bf060..b0cc3c2588fd 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -20,6 +20,7 @@
*/
#define __KERNEL_SYSCALLS__
+static int errno;
#include <linux/config.h>
#include <linux/module.h>
@@ -38,9 +39,6 @@
#include <asm/uaccess.h>
#include <asm/envctrl.h>
-static int errno;
-#include <asm/unistd.h>
-
#define ENVCTRL_MINOR 162
#define PCF8584_ADDRESS 0x55
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 739cad9b19a1..ceec30648f4f 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -81,8 +81,7 @@ int vfc_pcf8584_init(struct vfc_dev *dev)
void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs)
{
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(usecs_to_jiffies(usecs));
+ schedule_timeout_uninterruptible(usecs_to_jiffies(usecs));
}
void inline vfc_i2c_delay(struct vfc_dev *dev)
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index bc6e4627c7a1..a6ac61611f35 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -59,6 +59,7 @@
Fix 'handled=1' ISR usage, remove bogus IRQ check.
Remove un-needed eh_abort handler.
Add support for embedded firmware error strings.
+ 2.26.02.003 - Correctly handle single sgl's with use_sg=1.
*/
#include <linux/module.h>
@@ -81,7 +82,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.002"
+#define TW_DRIVER_VERSION "2.26.02.003"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -1805,6 +1806,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
+ memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
} else {
buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
if (buffaddr == 0)
@@ -1823,6 +1826,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (tw_dev->srb[request_id]->use_sg > 0) {
if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
+ struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+ char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
} else {
@@ -1888,11 +1897,20 @@ out:
/* This function completes an execute scsi operation */
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
{
- /* Copy the response if too small */
- if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
- memcpy(tw_dev->srb[request_id]->request_buffer,
- tw_dev->generic_buffer_virt[request_id],
- tw_dev->srb[request_id]->request_bufflen);
+ if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
+ (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
+ tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
+ if (tw_dev->srb[request_id]->use_sg == 0) {
+ memcpy(tw_dev->srb[request_id]->request_buffer,
+ tw_dev->generic_buffer_virt[request_id],
+ tw_dev->srb[request_id]->request_bufflen);
+ }
+ 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;
+ memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
}
} /* End twa_scsiop_execute_scsi_complete() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 973c51fb0fe2..ae9e0203e9de 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
return 0;
} /* End tw_scsiop_inquiry() */
+static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
+ void *data, unsigned int len)
+{
+ struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+ void *buf;
+ unsigned int transfer_len;
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg =
+ (struct scatterlist *)cmd->request_buffer;
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ transfer_len = min(sg->length, len);
+ } else {
+ buf = cmd->request_buffer;
+ transfer_len = min(cmd->request_bufflen, len);
+ }
+
+ memcpy(buf, data, transfer_len);
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *)cmd->request_buffer;
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
+}
+
/* This function is called by the isr to complete an inquiry command */
static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
{
unsigned char *is_unit_present;
- unsigned char *request_buffer;
+ unsigned char request_buffer[36];
TW_Param *param;
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
- /* Fill request buffer */
- if (tw_dev->srb[request_id]->request_buffer == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
- return 1;
- }
- request_buffer = tw_dev->srb[request_id]->request_buffer;
- memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(request_buffer, 0, sizeof(request_buffer));
request_buffer[0] = TYPE_DISK; /* Peripheral device type */
request_buffer[1] = 0; /* Device type modifier */
request_buffer[2] = 0; /* No ansi/iso compliance */
@@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_i
memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */
sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);
+ tw_transfer_internal(tw_dev, request_id, request_buffer,
+ sizeof(request_buffer));
param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
if (param == NULL) {
@@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
{
TW_Param *param;
unsigned char *flags;
- unsigned char *request_buffer;
+ unsigned char request_buffer[8];
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
@@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
return 1;
}
flags = (char *)&(param->data[0]);
- request_buffer = tw_dev->srb[request_id]->buffer;
- memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(request_buffer, 0, sizeof(request_buffer));
request_buffer[0] = 0xf; /* mode data length */
request_buffer[1] = 0; /* default medium type */
@@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
request_buffer[6] = 0x4; /* WCE on */
else
request_buffer[6] = 0x0; /* WCE off */
+ tw_transfer_internal(tw_dev, request_id, request_buffer,
+ sizeof(request_buffer));
return 0;
} /* End tw_scsiop_mode_sense_complete() */
@@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req
{
unsigned char *param_data;
u32 capacity;
- char *buff;
+ char buff[8];
TW_Param *param;
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
- buff = tw_dev->srb[request_id]->request_buffer;
- if (buff == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
- return 1;
- }
- memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(buff, 0, sizeof(buff));
param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
if (param == NULL) {
printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
@@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req
buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
buff[7] = TW_BLOCK_SIZE & 0xff;
+ tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));
+
return 0;
} /* End tw_scsiop_read_capacity_complete() */
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 2341d27ceed7..7a33c708f5b3 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -6090,8 +6090,8 @@ NCR53c7x0_release(struct Scsi_Host *host) {
if (hostdata->num_cmds)
printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
host->host_no, hostdata->num_cmds);
- if (hostdata->events)
- vfree ((void *)hostdata->events);
+
+ vfree(hostdata->events);
/* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
* XXX may be invalid (CONFIG_060_WRITETHROUGH)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 12c208fb18c5..20019b82b4a8 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1,5 +1,11 @@
menu "SCSI device support"
+config RAID_ATTRS
+ tristate "RAID Transport Class"
+ default n
+ ---help---
+ Provides RAID
+
config SCSI
tristate "SCSI device support"
---help---
@@ -229,6 +235,13 @@ config SCSI_ISCSI_ATTRS
each attached iSCSI device to sysfs, say Y.
Otherwise, say N.
+config SCSI_SAS_ATTRS
+ tristate "SAS Transport Attributes"
+ depends on SCSI
+ help
+ If you wish to export transport-specific information about
+ each attached SAS device to sysfs, say Y.
+
endmenu
menu "SCSI low-level drivers"
@@ -250,7 +263,7 @@ config SCSI_DECNCR
config SCSI_DECSII
tristate "DEC SII Scsi Driver"
- depends on MACH_DECSTATION && SCSI && MIPS32
+ depends on MACH_DECSTATION && SCSI && 32BIT
config BLK_DEV_3W_XXXX_RAID
tristate "3ware 5/6/7/8xxx ATA-RAID support"
@@ -459,6 +472,15 @@ config SCSI_ATA_PIIX
If unsure, say N.
+config SCSI_SATA_MV
+ tristate "Marvell SATA support"
+ depends on SCSI_SATA && PCI && EXPERIMENTAL
+ help
+ This option enables support for the Marvell Serial ATA family.
+ Currently supports 88SX[56]0[48][01] chips.
+
+ If unsure, say N.
+
config SCSI_SATA_NV
tristate "NVIDIA SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 3746fb9fa2f5..1e4edbdf2730 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -22,6 +22,8 @@ subdir-$(CONFIG_PCMCIA) += pcmcia
obj-$(CONFIG_SCSI) += scsi_mod.o
+obj-$(CONFIG_RAID_ATTRS) += raid_class.o
+
# --- NOTE ORDERING HERE ---
# For kernel non-modular link, transport attributes need to
# be initialised before drivers
@@ -29,6 +31,7 @@ obj-$(CONFIG_SCSI) += scsi_mod.o
obj-$(CONFIG_SCSI_SPI_ATTRS) += scsi_transport_spi.o
obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o
obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
+obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o
obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
@@ -132,6 +135,7 @@ obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o
obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o
obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o
obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o
+obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o
obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index f8ec6fe7d858..d40ba0bd68a3 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -88,6 +88,13 @@
*/
#include <scsi/scsi_dbg.h>
+#ifndef NDEBUG
+#define NDEBUG 0
+#endif
+#ifndef NDEBUG
+#define NDEBUG_ABORT 0
+#endif
+
#if (NDEBUG & NDEBUG_LISTS)
#define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }
#define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }
@@ -359,7 +366,7 @@ static struct {
{PHASE_UNKNOWN, "UNKNOWN"}
};
-#ifdef NDEBUG
+#if NDEBUG
static struct {
unsigned char mask;
const char *name;
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 79ae73b23680..e1f2246ee7cd 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -62,7 +62,7 @@
#define SYNC_MODE 0 /* Synchronous transfer mode */
-#if DEBUG
+#ifdef DEBUG
#undef NCR53C406A_DEBUG
#define NCR53C406A_DEBUG 1
#endif
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index ccdf440021fb..a8e3dfcd0dc7 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -133,6 +133,7 @@ struct inquiry_data {
static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
#ifdef AAC_DETAILED_STATUS_INFO
static char *aac_get_status_string(u32 status);
@@ -348,6 +349,27 @@ static void aac_io_done(struct scsi_cmnd * scsicmd)
spin_unlock_irqrestore(host->host_lock, cpu_flags);
}
+static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
+{
+ void *buf;
+ unsigned int transfer_len;
+ struct scatterlist *sg = scsicmd->request_buffer;
+
+ if (scsicmd->use_sg) {
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ transfer_len = min(sg->length, len + offset);
+ } else {
+ buf = scsicmd->request_buffer;
+ transfer_len = min(scsicmd->request_bufflen, len + offset);
+ }
+
+ memcpy(buf + offset, data, transfer_len - offset);
+
+ if (scsicmd->use_sg)
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+
+}
+
static void get_container_name_callback(void *context, struct fib * fibptr)
{
struct aac_get_name_resp * get_name_reply;
@@ -363,18 +385,22 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
/* Failure is irrelevant, using default value instead */
if ((le32_to_cpu(get_name_reply->status) == CT_OK)
&& (get_name_reply->data[0] != '\0')) {
- int count;
- char * dp;
- char * sp = get_name_reply->data;
+ char *sp = get_name_reply->data;
sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
while (*sp == ' ')
++sp;
- count = sizeof(((struct inquiry_data *)NULL)->inqd_pid);
- dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid;
- if (*sp) do {
- *dp++ = (*sp) ? *sp++ : ' ';
- } while (--count > 0);
+ if (*sp) {
+ char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+ int count = sizeof(d);
+ char *dp = d;
+ do {
+ *dp++ = (*sp) ? *sp++ : ' ';
+ } while (--count > 0);
+ aac_internal_transfer(scsicmd, d,
+ offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+ }
}
+
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
fib_complete(fibptr);
@@ -777,34 +803,36 @@ int aac_get_adapter_info(struct aac_dev* dev)
/*
* 57 scatter gather elements
*/
- dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
- sizeof(struct aac_fibhdr) -
- sizeof(struct aac_write) + sizeof(struct sgmap)) /
- sizeof(struct sgmap);
- if (dev->dac_support) {
- /*
- * 38 scatter gather elements
- */
- dev->scsi_host_ptr->sg_tablesize =
- (dev->max_fib_size -
+ if (!(dev->raw_io_interface)) {
+ dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
sizeof(struct aac_fibhdr) -
- sizeof(struct aac_write64) +
- sizeof(struct sgmap64)) /
- sizeof(struct sgmap64);
- }
- dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
- if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
- /*
- * Worst case size that could cause sg overflow when
- * we break up SG elements that are larger than 64KB.
- * Would be nice if we could tell the SCSI layer what
- * the maximum SG element size can be. Worst case is
- * (sg_tablesize-1) 4KB elements with one 64KB
- * element.
- * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
- */
- dev->scsi_host_ptr->max_sectors =
- (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ sizeof(struct aac_write) + sizeof(struct sgmap)) /
+ sizeof(struct sgmap);
+ if (dev->dac_support) {
+ /*
+ * 38 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize =
+ (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write64) +
+ sizeof(struct sgmap64)) /
+ sizeof(struct sgmap64);
+ }
+ dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+ /*
+ * Worst case size that could cause sg overflow when
+ * we break up SG elements that are larger than 64KB.
+ * Would be nice if we could tell the SCSI layer what
+ * the maximum SG element size can be. Worst case is
+ * (sg_tablesize-1) 4KB elements with one 64KB
+ * element.
+ * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
+ */
+ dev->scsi_host_ptr->max_sectors =
+ (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
}
fib_complete(fibptr);
@@ -814,12 +842,11 @@ int aac_get_adapter_info(struct aac_dev* dev)
}
-static void read_callback(void *context, struct fib * fibptr)
+static void io_callback(void *context, struct fib * fibptr)
{
struct aac_dev *dev;
struct aac_read_reply *readreply;
struct scsi_cmnd *scsicmd;
- u32 lba;
u32 cid;
scsicmd = (struct scsi_cmnd *) context;
@@ -827,8 +854,7 @@ static void read_callback(void *context, struct fib * fibptr)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
- lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
- dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], jiffies));
if (fibptr == NULL)
BUG();
@@ -847,7 +873,7 @@ static void read_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
#ifdef AAC_DETAILED_STATUS_INFO
- printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+ printk(KERN_WARNING "io_callback: io failed, status = %d\n",
le32_to_cpu(readreply->status));
#endif
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
@@ -867,53 +893,6 @@ static void read_callback(void *context, struct fib * fibptr)
aac_io_done(scsicmd);
}
-static void write_callback(void *context, struct fib * fibptr)
-{
- struct aac_dev *dev;
- struct aac_write_reply *writereply;
- struct scsi_cmnd *scsicmd;
- u32 lba;
- u32 cid;
-
- scsicmd = (struct scsi_cmnd *) context;
- dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
-
- lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
- dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
- if (fibptr == NULL)
- BUG();
-
- if(scsicmd->use_sg)
- pci_unmap_sg(dev->pdev,
- (struct scatterlist *)scsicmd->buffer,
- scsicmd->use_sg,
- scsicmd->sc_data_direction);
- else if(scsicmd->request_bufflen)
- pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
- scsicmd->request_bufflen,
- scsicmd->sc_data_direction);
-
- writereply = (struct aac_write_reply *) fib_data(fibptr);
- if (le32_to_cpu(writereply->status) == ST_OK)
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
- else {
- printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
- set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
- HARDWARE_ERROR,
- SENCODE_INTERNAL_TARGET_FAILURE,
- ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
- 0, 0);
- memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
- sizeof(struct sense_data));
- }
-
- fib_complete(fibptr);
- fib_free(fibptr);
- aac_io_done(scsicmd);
-}
-
static int aac_read(struct scsi_cmnd * scsicmd, int cid)
{
u32 lba;
@@ -954,7 +933,32 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fib_init(cmd_fibcontext);
- if (dev->dac_support == 1) {
+ if (dev->raw_io_interface) {
+ struct aac_raw_io *readcmd;
+ readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+ readcmd->block[0] = cpu_to_le32(lba);
+ readcmd->block[1] = 0;
+ readcmd->count = cpu_to_le32(count<<9);
+ readcmd->cid = cpu_to_le16(cid);
+ readcmd->flags = cpu_to_le16(1);
+ readcmd->bpTotal = 0;
+ readcmd->bpComplete = 0;
+
+ aac_build_sgraw(scsicmd, &readcmd->sg);
+ fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+ BUG();
+ /*
+ * Now send the Fib to the adapter
+ */
+ status = fib_send(ContainerRawIo,
+ cmd_fibcontext,
+ fibsize,
+ FsaNormal,
+ 0, 1,
+ (fib_callback) io_callback,
+ (void *) scsicmd);
+ } else if (dev->dac_support == 1) {
struct aac_read64 *readcmd;
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -968,7 +972,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize = sizeof(struct aac_read64) +
((le32_to_cpu(readcmd->sg.count) - 1) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -978,7 +982,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) read_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
} else {
struct aac_read *readcmd;
@@ -1002,7 +1006,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) read_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
}
@@ -1061,7 +1065,32 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
}
fib_init(cmd_fibcontext);
- if(dev->dac_support == 1) {
+ if (dev->raw_io_interface) {
+ struct aac_raw_io *writecmd;
+ writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+ writecmd->block[0] = cpu_to_le32(lba);
+ writecmd->block[1] = 0;
+ writecmd->count = cpu_to_le32(count<<9);
+ writecmd->cid = cpu_to_le16(cid);
+ writecmd->flags = 0;
+ writecmd->bpTotal = 0;
+ writecmd->bpComplete = 0;
+
+ aac_build_sgraw(scsicmd, &writecmd->sg);
+ fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+ BUG();
+ /*
+ * Now send the Fib to the adapter
+ */
+ status = fib_send(ContainerRawIo,
+ cmd_fibcontext,
+ fibsize,
+ FsaNormal,
+ 0, 1,
+ (fib_callback) io_callback,
+ (void *) scsicmd);
+ } else if (dev->dac_support == 1) {
struct aac_write64 *writecmd;
writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1085,7 +1114,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) write_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
} else {
struct aac_write *writecmd;
@@ -1111,7 +1140,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) write_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
}
@@ -1340,44 +1369,45 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
switch (scsicmd->cmnd[0]) {
case INQUIRY:
{
- struct inquiry_data *inq_data_ptr;
+ struct inquiry_data inq_data;
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
- inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
- memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
+ memset(&inq_data, 0, sizeof (struct inquiry_data));
- inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */
- inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */
- inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
- inq_data_ptr->inqd_len = 31;
+ inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
+ inq_data.inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */
+ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
+ inq_data.inqd_len = 31;
/*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
- inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
+ inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
/*
* Set the Vendor, Product, and Revision Level
* see: <vendor>.c i.e. aac.c
*/
if (scsicmd->device->id == host->this_id) {
- setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));
- inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */
+ setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+ inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
+ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
return 0;
}
- setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);
- inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+ setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+ inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
return aac_get_container_name(scsicmd, cid);
}
case READ_CAPACITY:
{
u32 capacity;
- char *cp;
+ char cp[8];
dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
if (fsa_dev_ptr[cid].size <= 0x100000000LL)
capacity = fsa_dev_ptr[cid].size - 1;
else
capacity = (u32)-1;
- cp = scsicmd->request_buffer;
+
cp[0] = (capacity >> 24) & 0xff;
cp[1] = (capacity >> 16) & 0xff;
cp[2] = (capacity >> 8) & 0xff;
@@ -1386,6 +1416,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
cp[5] = 0;
cp[6] = 2;
cp[7] = 0;
+ aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1395,15 +1426,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case MODE_SENSE:
{
- char *mode_buf;
+ char mode_buf[4];
dprintk((KERN_DEBUG "MODE SENSE command.\n"));
- mode_buf = scsicmd->request_buffer;
mode_buf[0] = 3; /* Mode data length */
mode_buf[1] = 0; /* Medium type - default */
mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */
mode_buf[3] = 0; /* Block descriptor length */
+ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1411,10 +1442,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
}
case MODE_SENSE_10:
{
- char *mode_buf;
+ char mode_buf[8];
dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
- mode_buf = scsicmd->request_buffer;
mode_buf[0] = 0; /* Mode data length (MSB) */
mode_buf[1] = 6; /* Mode data length (LSB) */
mode_buf[2] = 0; /* Medium type - default */
@@ -1423,6 +1453,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
mode_buf[5] = 0; /* reserved */
mode_buf[6] = 0; /* Block descriptor length (MSB) */
mode_buf[7] = 0; /* Block descriptor length (LSB) */
+ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1894,7 +1925,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
srbcmd->id = cpu_to_le32(scsicmd->device->id);
srbcmd->lun = cpu_to_le32(scsicmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
- timeout = (scsicmd->timeout-jiffies)/HZ;
+ timeout = scsicmd->timeout_per_command/HZ;
if(timeout == 0){
timeout = 1;
}
@@ -2077,6 +2108,76 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
return byte_count;
}
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+{
+ struct Scsi_Host *host = scsicmd->device->host;
+ struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+ unsigned long byte_count = 0;
+
+ // Get rid of old data
+ psg->count = 0;
+ psg->sg[0].next = 0;
+ psg->sg[0].prev = 0;
+ psg->sg[0].addr[0] = 0;
+ psg->sg[0].addr[1] = 0;
+ psg->sg[0].count = 0;
+ psg->sg[0].flags = 0;
+ if (scsicmd->use_sg) {
+ struct scatterlist *sg;
+ int i;
+ int sg_count;
+ sg = (struct scatterlist *) scsicmd->request_buffer;
+
+ sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
+ scsicmd->sc_data_direction);
+
+ for (i = 0; i < sg_count; i++) {
+ int count = sg_dma_len(sg);
+ u64 addr = sg_dma_address(sg);
+ psg->sg[i].next = 0;
+ psg->sg[i].prev = 0;
+ psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
+ psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+ psg->sg[i].count = cpu_to_le32(count);
+ psg->sg[i].flags = 0;
+ 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) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
+ byte_count = scsicmd->request_bufflen;
+ }
+ /* Check for command underflow */
+ if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
+ }
+ }
+ else if(scsicmd->request_bufflen) {
+ int count;
+ u64 addr;
+ scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
+ scsicmd->request_buffer,
+ scsicmd->request_bufflen,
+ scsicmd->sc_data_direction);
+ addr = scsicmd->SCp.dma_handle;
+ count = scsicmd->request_bufflen;
+ psg->count = cpu_to_le32(1);
+ psg->sg[0].next = 0;
+ psg->sg[0].prev = 0;
+ psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
+ psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+ psg->sg[0].count = cpu_to_le32(count);
+ psg->sg[0].flags = 0;
+ byte_count = scsicmd->request_bufflen;
+ }
+ return byte_count;
+}
+
#ifdef AAC_DETAILED_STATUS_INFO
struct aac_srb_status_info {
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 4ab07861b457..e40528185d48 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -110,6 +110,22 @@ struct user_sgentry64 {
u32 count; /* Length. */
};
+struct sgentryraw {
+ __le32 next; /* reserved for F/W use */
+ __le32 prev; /* reserved for F/W use */
+ __le32 addr[2];
+ __le32 count;
+ __le32 flags; /* reserved for F/W use */
+};
+
+struct user_sgentryraw {
+ u32 next; /* reserved for F/W use */
+ u32 prev; /* reserved for F/W use */
+ u32 addr[2];
+ u32 count;
+ u32 flags; /* reserved for F/W use */
+};
+
/*
* SGMAP
*
@@ -137,6 +153,16 @@ struct user_sgmap64 {
struct user_sgentry64 sg[1];
};
+struct sgmapraw {
+ __le32 count;
+ struct sgentryraw sg[1];
+};
+
+struct user_sgmapraw {
+ u32 count;
+ struct user_sgentryraw sg[1];
+};
+
struct creation_info
{
u8 buildnum; /* e.g., 588 */
@@ -351,6 +377,7 @@ struct hw_fib {
*/
#define ContainerCommand 500
#define ContainerCommand64 501
+#define ContainerRawIo 502
/*
* Cluster Commands
*/
@@ -456,6 +483,7 @@ struct adapter_ops
{
void (*adapter_interrupt)(struct aac_dev *dev);
void (*adapter_notify)(struct aac_dev *dev, u32 event);
+ void (*adapter_disable_int)(struct aac_dev *dev);
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
};
@@ -981,6 +1009,9 @@ struct aac_dev
u8 nondasd_support;
u8 dac_support;
u8 raid_scsi_mode;
+ /* macro side-effects BEWARE */
+# define raw_io_interface \
+ init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
u8 printf_enabled;
};
@@ -990,6 +1021,9 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \
(dev)->a_ops.adapter_notify(dev, event)
+#define aac_adapter_disable_int(dev) \
+ (dev)->a_ops.adapter_disable_int(dev)
+
#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
@@ -1156,6 +1190,17 @@ struct aac_write_reply
__le32 committed;
};
+struct aac_raw_io
+{
+ __le32 block[2];
+ __le32 count;
+ __le16 cid;
+ __le16 flags; /* 00 W, 01 R */
+ __le16 bpTotal; /* reserved for F/W use */
+ __le16 bpComplete; /* reserved for F/W use */
+ struct sgmapraw sg;
+};
+
#define CT_FLUSH_CACHE 129
struct aac_synchronize {
__le32 command; /* VM_ContainerConfig */
@@ -1196,7 +1241,7 @@ struct aac_srb
};
/*
- * This and assocated data structs are used by the
+ * This and associated data structs are used by the
* ioctl caller and are in cpu order.
*/
struct user_aac_srb
@@ -1508,11 +1553,12 @@ struct fib_ioctl
struct revision
{
- u32 compat;
- u32 version;
- u32 build;
+ __le32 compat;
+ __le32 version;
+ __le32 build;
};
+
/*
* Ugly - non Linux like ioctl coding for back compat.
*/
@@ -1733,3 +1779,4 @@ int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
extern int numacb;
extern int acbsize;
+extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 85387099aab2..71f1cad9b5f0 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -287,7 +287,6 @@ return_fib:
kfree(fib->hw_fib);
kfree(fib);
status = 0;
- fibctx->jiffies = jiffies/HZ;
} else {
spin_unlock_irqrestore(&dev->fib_lock, flags);
if (f.wait) {
@@ -302,6 +301,7 @@ return_fib:
status = -EAGAIN;
}
}
+ fibctx->jiffies = jiffies/HZ;
return status;
}
@@ -405,10 +405,20 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
static int check_revision(struct aac_dev *dev, void __user *arg)
{
struct revision response;
-
- response.compat = 1;
- response.version = le32_to_cpu(dev->adapter_info.kernelrev);
- response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
+ char *driver_version = aac_driver_version;
+ u32 version;
+
+ response.compat = cpu_to_le32(1);
+ version = (simple_strtol(driver_version,
+ &driver_version, 10) << 24) | 0x00000400;
+ version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
+ version += simple_strtol(driver_version + 1, NULL, 10);
+ response.version = cpu_to_le32(version);
+# if (defined(AAC_DRIVER_BUILD))
+ response.build = cpu_to_le32(AAC_DRIVER_BUILD);
+# else
+ response.build = cpu_to_le32(9999);
+# endif
if (copy_to_user(arg, &response, sizeof(response)))
return -EFAULT;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 43557bf661f6..75abd0453289 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -44,7 +44,9 @@
#include "aacraid.h"
-struct aac_common aac_config;
+struct aac_common aac_config = {
+ .irq_mod = 1
+};
static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
{
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 5322865942e2..a1d303f03480 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -254,6 +254,7 @@ static void fib_dealloc(struct fib * fibptr)
static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
{
struct aac_queue * q;
+ unsigned long idx;
/*
* All of the queues wrap when they reach the end, so we check
@@ -263,10 +264,23 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
*/
q = &dev->queues->queue[qid];
-
- *index = le32_to_cpu(*(q->headers.producer));
- if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
+
+ idx = *index = le32_to_cpu(*(q->headers.producer));
+ /* Interrupt Moderation, only interrupt for first two entries */
+ if (idx != le32_to_cpu(*(q->headers.consumer))) {
+ if (--idx == 0) {
+ if (qid == AdapHighCmdQueue)
+ idx = ADAP_HIGH_CMD_ENTRIES;
+ else if (qid == AdapNormCmdQueue)
+ idx = ADAP_NORM_CMD_ENTRIES;
+ else if (qid == AdapHighRespQueue)
+ idx = ADAP_HIGH_RESP_ENTRIES;
+ else if (qid == AdapNormRespQueue)
+ idx = ADAP_NORM_RESP_ENTRIES;
+ }
+ if (idx != le32_to_cpu(*(q->headers.consumer)))
*nonotify = 1;
+ }
if (qid == AdapHighCmdQueue) {
if (*index >= ADAP_HIGH_CMD_ENTRIES)
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 562da90480a1..4ff29d7f5825 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,8 +27,11 @@
* Abstract: Linux Driver entry module for Adaptec RAID Array Controller
*/
-#define AAC_DRIVER_VERSION "1.1.2-lk2"
-#define AAC_DRIVER_BUILD_DATE __DATE__
+#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>
@@ -58,16 +61,24 @@
#include "aacraid.h"
+#ifdef AAC_DRIVER_BUILD
+#define _str(x) #x
+#define str(x) _str(x)
+#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH
+#else
+#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE
+#endif
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");
MODULE_LICENSE("GPL");
-MODULE_VERSION(AAC_DRIVER_VERSION);
+MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
+char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
/*
* Because of the way Linux names scsi devices, the order in this table has
@@ -109,36 +120,39 @@ static struct pci_device_id aac_pci_tbl[] = {
{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
- { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */
- { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */
- { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */
- { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
- { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
- { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
- { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
- { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
- { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
- { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
- { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */
- { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */
- { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */
- { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */
- { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */
- { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */
- { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */
- { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */
- { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */
-
- { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/
- { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/
- { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/
- { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */
- { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */
-
- { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */
- { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */
- { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */
- { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */
+ { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
+ { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */
+ { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */
+ { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */
+ { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+ { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+ { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+ { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+ { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+ { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+ { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
+ { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
+ { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
+ { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
+ { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
+ { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
+ { 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
+ { 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
+ { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
+ { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
+ { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
+ { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
+
+ { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
+ { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
+ { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/
+ { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */
+ { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */
+
+ { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */
+ { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
+ { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
+ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
{ 0,}
};
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -180,8 +194,9 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
+ { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
+ { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
+ { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */
{ NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
@@ -195,10 +210,12 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */
{ aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
+ { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
+ { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
+ { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
{ aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
{ aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@@ -839,11 +856,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
return 0;
-out_deinit:
+ out_deinit:
kill_proc(aac->thread_pid, SIGKILL, 0);
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac);
+ aac_adapter_disable_int(aac);
fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
@@ -860,6 +878,13 @@ out_deinit:
return error;
}
+static void aac_shutdown(struct pci_dev *dev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(dev);
+ struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+ aac_send_shutdown(aac);
+}
+
static void __devexit aac_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -871,6 +896,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac);
+ aac_adapter_disable_int(aac);
fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
@@ -891,14 +917,15 @@ static struct pci_driver aac_pci_driver = {
.id_table = aac_pci_tbl,
.probe = aac_probe_one,
.remove = __devexit_p(aac_remove_one),
+ .shutdown = aac_shutdown,
};
static int __init aac_init(void)
{
int error;
- printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n",
- AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE);
+ printk(KERN_INFO "Adaptec %s driver (%s)\n",
+ AAC_DRIVERNAME, aac_driver_version);
error = pci_module_init(&aac_pci_driver);
if (error)
@@ -909,6 +936,7 @@ static int __init aac_init(void)
printk(KERN_WARNING
"aacraid: unable to register \"aac\" device.\n");
}
+
return 0;
}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 7d68b7825137..557287a0b80b 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_rkt_disable_interrupt - Disable interrupts
+ * @dev: Adapter
+ */
+
+static void aac_rkt_disable_interrupt(struct aac_dev *dev)
+{
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
* rkt_sync_cmd - send a command and wait
* @dev: Adapter
* @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
dev->a_ops.adapter_check_health = aac_rkt_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that we
+ * can handle.
+ */
+ rkt_writeb(dev, MUnit.OIMR, 0xff);
+ rkt_writel(dev, MUnit.ODR, 0xffffffff);
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
@@ -438,6 +457,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 1ff25f49fada..a8459faf87ca 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_rx_disable_interrupt - Disable interrupts
+ * @dev: Adapter
+ */
+
+static void aac_rx_disable_interrupt(struct aac_dev *dev)
+{
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
* rx_sync_cmd - send a command and wait
* @dev: Adapter
* @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
dev->a_ops.adapter_notify = aac_rx_notify_adapter;
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that we
+ * can handle.
+ */
+ rx_writeb(dev, MUnit.OIMR, 0xff);
+ rx_writel(dev, MUnit.ODR, 0xffffffff);
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
@@ -438,6 +457,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 0680249ab861..3900abc5850d 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_sa_disable_interrupt - disable interrupt
+ * @dev: Which adapter to enable.
+ */
+
+static void aac_sa_disable_interrupt (struct aac_dev *dev)
+{
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+}
+
+/**
* aac_sa_notify_adapter - handle adapter notification
* @dev: Adapter that notification is for
* @event: Event to notidy
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
static void aac_sa_interrupt_adapter (struct aac_dev *dev)
{
- u32 ret;
sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
- &ret, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
*/
dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that
+ * we can handle.
+ */
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+ sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
+ DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
if(aac_init_adapter(dev) == NULL)
goto error_irq;
@@ -381,6 +398,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0fb93363eb22..37ec5411e325 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
(unsigned) s->serial_number, s->retries, s->allowed);
printk(
-" timeout_per_command %d, timeout_total %d, timeout %d\n",
- s->timeout_per_command, s->timeout_total, s->timeout);
+" timeout_per_command %d\n",
+ s->timeout_per_command);
printk(
" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index e3b9692b9688..c2c8fa828e24 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -1,26 +1,34 @@
/*
* ahci.c - AHCI SATA support
*
- * Copyright 2004 Red Hat, Inc.
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
+ * Copyright 2004-2005 Red Hat, Inc.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
*
- * Version 1.0 of the AHCI specification:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * AHCI hardware documentation:
* http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
*
*/
@@ -181,7 +189,6 @@ static void ahci_irq_clear(struct ata_port *ap);
static void ahci_eng_timeout(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
-static void ahci_host_stop(struct ata_host_set *host_set);
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
@@ -234,7 +241,6 @@ static struct ata_port_operations ahci_ops = {
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
- .host_stop = ahci_host_stop,
};
static struct ata_port_info ahci_port_info[] = {
@@ -244,7 +250,7 @@ static struct ata_port_info ahci_port_info[] = {
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_PIO_DMA,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
},
@@ -269,6 +275,8 @@ static struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ESB2 */
{ PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ESB2 */
+ { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH7-M DH */
{ } /* terminate list */
};
@@ -286,17 +294,9 @@ static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int
return base + 0x100 + (port * 0x80);
}
-static inline void *ahci_port_base (void *base, unsigned int port)
-{
- return (void *) ahci_port_base_ul((unsigned long)base, port);
-}
-
-static void ahci_host_stop(struct ata_host_set *host_set)
+static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
{
- struct ahci_host_priv *hpriv = host_set->private_data;
- kfree(hpriv);
-
- ata_host_stop(host_set);
+ return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
}
static int ahci_port_start(struct ata_port *ap)
@@ -304,8 +304,9 @@ static int ahci_port_start(struct ata_port *ap)
struct device *dev = ap->host_set->dev;
struct ahci_host_priv *hpriv = ap->host_set->private_data;
struct ahci_port_priv *pp;
- void *mem, *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void *mem;
dma_addr_t mem_dma;
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
@@ -373,8 +374,8 @@ static void ahci_port_stop(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct ahci_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
tmp = readl(port_mmio + PORT_CMD);
@@ -536,8 +537,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
int work;
@@ -584,12 +585,16 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
static void ahci_eng_timeout(struct ata_port *ap)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ struct ata_host_set *host_set = ap->host_set;
+ void __iomem *mmio = host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -607,12 +612,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
ata_qc_complete(qc, ATA_ERR);
}
+ spin_unlock_irqrestore(&host_set->lock, flags);
}
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 status, serr, ci;
serr = readl(port_mmio + PORT_SCR_ERR);
@@ -648,7 +654,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
struct ata_host_set *host_set = dev_instance;
struct ahci_host_priv *hpriv;
unsigned int i, handled = 0;
- void *mmio;
+ void __iomem *mmio;
u32 irq_stat, irq_ack = 0;
VPRINTK("ENTER\n");
@@ -694,10 +700,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
static int ahci_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void *port_mmio = (void *) ap->ioaddr.cmd_addr;
-
- writel(1, port_mmio + PORT_SCR_ACT);
- readl(port_mmio + PORT_SCR_ACT); /* flush */
+ void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
writel(1, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */
@@ -862,27 +865,11 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
return 0;
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_intx(struct pci_dev *pdev, int enable)
-{
- u16 pci_command, new;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-
- if (enable)
- new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
- else
- new = pci_command | PCI_COMMAND_INTX_DISABLE;
-
- if (new != pci_command)
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
-}
-
static void ahci_print_info(struct ata_probe_ent *probe_ent)
{
struct ahci_host_priv *hpriv = probe_ent->private_data;
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- void *mmio = probe_ent->mmio_base;
+ void __iomem *mmio = probe_ent->mmio_base;
u32 vers, cap, impl, speed;
const char *speed_s;
u16 cc;
@@ -955,7 +942,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_probe_ent *probe_ent = NULL;
struct ahci_host_priv *hpriv;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int have_msi, pci_dev_busy = 0;
int rc;
@@ -992,8 +979,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, AHCI_PCI_BAR),
- pci_resource_len(pdev, AHCI_PCI_BAR));
+ mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -1037,7 +1023,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_hpriv:
kfree(hpriv);
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_free_ent:
kfree(probe_ent);
err_out_msi:
@@ -1077,7 +1063,8 @@ static void ahci_remove_one (struct pci_dev *pdev)
scsi_host_put(ap->host);
}
- host_set->ops->host_stop(host_set);
+ kfree(hpriv);
+ pci_iounmap(pdev, host_set->mmio_base);
kfree(host_set);
if (have_msi)
@@ -1094,7 +1081,6 @@ static int __init ahci_init(void)
return pci_module_init(&ahci_pci_driver);
}
-
static void __exit ahci_exit(void)
{
pci_unregister_driver(&ahci_pci_driver);
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index c2523a30a7f5..69ed77fcb71f 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,6 +5,7 @@
config SCSI_AIC79XX
tristate "Adaptec AIC79xx U320 support"
depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
help
This driver supports all of Adaptec's Ultra 320 PCI-X
based SCSI controllers.
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index 00f3bd1e181e..527efd36f5c1 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
int
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{
- u_long l;
int error;
int have_seeprom;
u_int hostconf;
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index fd4b2f3eb0c2..653fb0b42aea 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
uint16_t user_tagenable;/* Tagged Queuing allowed */
};
-TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
-extern struct ahd_softc_tailq ahd_tailq;
-
/*************************** IO Cell Configuration ****************************/
#define AHD_PRECOMP_SLEW_INDEX \
(AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
void ahd_pause_and_flushwork(struct ahd_softc *ahd);
int ahd_suspend(struct ahd_softc *ahd);
int ahd_resume(struct ahd_softc *ahd);
-void ahd_softc_insert(struct ahd_softc *);
-struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
void ahd_set_unit(struct ahd_softc *, int);
void ahd_set_name(struct ahd_softc *, char *);
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
void ahd_print_devinfo(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
void ahd_dump_sglist(struct scb *scb);
-void ahd_dump_all_cards_state(void);
void ahd_dump_card_state(struct ahd_softc *ahd);
int ahd_print_register(ahd_reg_parse_entry_t *table,
u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 137fb1a37dd1..4e8f00df978d 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
#endif
-/******************************** Globals *************************************/
-struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
/***************************** Lookup Tables **********************************/
char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
}
void
-ahd_softc_insert(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
-#if AHD_PCI_CONFIG > 0
- /*
- * Second Function PCI devices need to inherit some
- * settings from function 0.
- */
- if ((ahd->features & AHD_MULTI_FUNC) != 0) {
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dev_softc_t list_pci;
- ahd_dev_softc_t pci;
-
- list_pci = list_ahd->dev_softc;
- pci = ahd->dev_softc;
- if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
- && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
- struct ahd_softc *master;
- struct ahd_softc *slave;
-
- if (ahd_get_pci_function(list_pci) == 0) {
- master = list_ahd;
- slave = ahd;
- } else {
- master = ahd;
- slave = list_ahd;
- }
- slave->flags &= ~AHD_BIOS_ENABLED;
- slave->flags |=
- master->flags & AHD_BIOS_ENABLED;
- break;
- }
- }
- }
-#endif
-
- /*
- * Insertion sort into our list of softcs.
- */
- list_ahd = TAILQ_FIRST(&ahd_tailq);
- while (list_ahd != NULL
- && ahd_softc_comp(ahd, list_ahd) <= 0)
- list_ahd = TAILQ_NEXT(list_ahd, links);
- if (list_ahd != NULL)
- TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
- else
- TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
- ahd->init_level++;
-}
-
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahd_softc *
-ahd_find_softc(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- if (list_ahd == ahd)
- return (ahd);
- }
- return (NULL);
-}
-
-void
ahd_set_unit(struct ahd_softc *ahd, int unit)
{
ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
static void
ahd_reset_poll(void *arg)
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd = arg;
u_int scsiseq1;
- u_long l;
u_long s;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
ahd_pause(ahd);
ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
ahd_reset_poll, ahd);
ahd_unpause(ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
return;
}
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
ahd_unlock(ahd, &s);
ahd_release_simq(ahd);
- ahd_list_unlock(&l);
}
/**************************** Statistics Processing ***************************/
static void
ahd_stat_timer(void *arg)
{
- struct ahd_softc *ahd;
- u_long l;
+ struct ahd_softc *ahd = arg;
u_long s;
int enint_coal;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
ahd_stat_timer, ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
}
/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
return (last_probe);
}
-void
-ahd_dump_all_cards_state(void)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dump_card_state(list_ahd);
- }
-}
-
int
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
}
printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
- ahd_platform_dump_card_state(ahd);
ahd_restore_modes(ahd, saved_modes);
if (paused == 0)
ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 329cb2331339..6b6d4e287793 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -46,32 +46,14 @@
#include "aic79xx_inline.h"
#include <scsi/scsicam.h>
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
+static struct scsi_transport_template *ahd_linux_transport_template = NULL;
#include <linux/init.h> /* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h" /* For geometry detection */
-#endif
-
#include <linux/mm.h> /* For fetching system memory size */
+#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
/*
- * Lock protecting manipulation of the ahd softc list.
- */
-spinlock_t ahd_list_spinlock;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahd_linux_nseg;
-#endif
-
-/*
* Bucket size for counting good commands in between bad ones.
*/
#define AHD_LINUX_ERR_THRESH 1000
@@ -188,71 +170,6 @@ static adapter_tag_info_t aic79xx_tag_info[] =
};
/*
- * By default, read streaming is disabled. In theory,
- * read streaming should enhance performance, but early
- * U320 drive firmware actually performs slower with
- * read streaming enabled.
- */
-#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM
-#define AIC79XX_CONFIGED_RD_STRM 0xFFFF
-#else
-#define AIC79XX_CONFIGED_RD_STRM 0
-#endif
-
-static uint16_t aic79xx_rd_strm_info[] =
-{
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM
-};
-
-/*
- * DV option:
- *
- * positive value = DV Enabled
- * zero = DV Disabled
- * negative value = DV Default for adapter type/seeprom
- */
-#ifdef CONFIG_AIC79XX_DV_SETTING
-#define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING
-#else
-#define AIC79XX_CONFIGED_DV -1
-#endif
-
-static int8_t aic79xx_dv_settings[] =
-{
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV
-};
-
-/*
* The I/O cell on the chip is very configurable in respect to its analog
* characteristics. Set the defaults here; they can be overriden with
* the proper insmod parameters.
@@ -375,13 +292,6 @@ static uint32_t aic79xx_pci_parity = ~0;
uint32_t aic79xx_allow_memio = ~0;
/*
- * aic79xx_detect() has been run, so register all device arrivals
- * immediately with the system rather than deferring to the sorted
- * attachment performed by aic79xx_detect().
- */
-int aic79xx_detect_complete;
-
-/*
* So that we can set how long each device is given as a selection timeout.
* The table of values goes like this:
* 0 - 256ms
@@ -412,7 +322,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC79XX_DRIVER_VERSION);
-module_param(aic79xx, charp, 0);
+module_param(aic79xx, charp, 0444);
MODULE_PARM_DESC(aic79xx,
"period delimited, options string.\n"
" verbose Enable verbose/diagnostic logging\n"
@@ -427,8 +337,6 @@ MODULE_PARM_DESC(aic79xx,
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
-" rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n"
-" dv:<dv_settings> Set per-controller Domain Validation Setting.\n"
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
" precomp:<pcomp_list> Set the signal precompensation (0-7).\n"
" amplitude:<int> Set the signal amplitude (0-7).\n"
@@ -441,249 +349,35 @@ MODULE_PARM_DESC(aic79xx,
" Shorten the selection timeout to 128ms\n"
"\n"
" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
-"\n"
-" Sample /etc/modprobe.conf line:\n"
-" Change Read Streaming for Controller's 2 and 3\n"
-"\n"
-" options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
+"\n");
static void ahd_linux_handle_scsi_status(struct ahd_softc *,
- struct ahd_linux_device *,
+ struct scsi_device *,
struct scb *);
static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
- Scsi_Cmnd *cmd);
-static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dev_timed_unfreeze(u_long arg);
+ struct scsi_cmnd *cmd);
static void ahd_linux_sem_timeout(u_long arg);
+static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
-static void ahd_linux_size_nseg(void);
-static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
-static void ahd_linux_start_dv(struct ahd_softc *ahd);
-static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
-static int ahd_linux_dv_thread(void *data);
-static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
-static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
-static void ahd_linux_dv_transition(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_inq(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ,
- u_int request_length);
-static void ahd_linux_dv_tur(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_web(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_reb(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_su(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static int ahd_linux_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
-static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd);
-static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd);
-static void ahd_linux_device_queue_depth(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*,
- u_int, u_int);
-static void ahd_linux_free_target(struct ahd_softc*,
- struct ahd_linux_target*);
-static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*,
- struct ahd_linux_target*,
- u_int);
-static void ahd_linux_free_device(struct ahd_softc*,
- struct ahd_linux_device*);
-static void ahd_linux_run_device_queue(struct ahd_softc*,
- struct ahd_linux_device*);
+static void ahd_linux_device_queue_depth(struct scsi_device *);
+static int ahd_linux_run_command(struct ahd_softc*,
+ struct ahd_linux_device *,
+ struct scsi_cmnd *);
static void ahd_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahd_linux_setup_tag_info;
-static aic_option_callback_t ahd_linux_setup_rd_strm_info;
-static aic_option_callback_t ahd_linux_setup_dv;
-static aic_option_callback_t ahd_linux_setup_iocell_info;
-static int ahd_linux_next_unit(void);
-static void ahd_runq_tasklet(unsigned long data);
-static int aic79xx_setup(char *c);
-
-/****************************** Inlines ***************************************/
-static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
-static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
-static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
-static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
-static __inline struct ahd_linux_device*
- ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
- u_int target, u_int lun, int alloc);
-static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
-static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static __inline struct ahd_linux_device *
- ahd_linux_next_device_to_run(struct ahd_softc *ahd);
-static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
-
-static __inline void
-ahd_schedule_completeq(struct ahd_softc *ahd)
-{
- if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
- ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
- ahd->platform_data->completeq_timer.expires = jiffies;
- add_timer(&ahd->platform_data->completeq_timer);
- }
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahd_schedule_runq(struct ahd_softc *ahd)
-{
- tasklet_schedule(&ahd->platform_data->runq_tasklet);
-}
-
-static __inline
-void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
- (unsigned long)ahd);
-}
+static int aic79xx_setup(char *c);
-static __inline void
-ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_kill(&ahd->platform_data->runq_tasklet);
-}
+static int ahd_linux_unit;
-static __inline struct ahd_linux_device*
-ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
- u_int lun, int alloc)
-{
- struct ahd_linux_target *targ;
- struct ahd_linux_device *dev;
- u_int target_offset;
- target_offset = target;
- if (channel != 0)
- target_offset += 8;
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL) {
- if (alloc != 0) {
- targ = ahd_linux_alloc_target(ahd, channel, target);
- if (targ == NULL)
- return (NULL);
- } else
- return (NULL);
- }
- dev = targ->devices[lun];
- if (dev == NULL && alloc != 0)
- dev = ahd_linux_alloc_device(ahd, targ, lun);
- return (dev);
-}
-
-#define AHD_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahd_cmd *
-ahd_linux_run_complete_queue(struct ahd_softc *ahd)
-{
- struct ahd_cmd *acmd;
- u_long done_flags;
- int with_errors;
-
- with_errors = 0;
- ahd_done_lock(ahd, &done_flags);
- while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
- /*
- * Linux uses stack recursion to requeue
- * commands that need to be retried. Avoid
- * blowing out the stack by "spoon feeding"
- * commands that completed with error back
- * the operating system in case they are going
- * to be retried. "ick"
- */
- ahd_schedule_completeq(ahd);
- break;
- }
- TAILQ_REMOVE(&ahd->platform_data->completeq,
- acmd, acmd_links.tqe);
- cmd = &acmd_scsi_cmd(acmd);
- cmd->host_scribble = NULL;
- if (ahd_cmd_get_transaction_status(cmd) != DID_OK
- || (cmd->result & 0xFF) != SCSI_STATUS_OK)
- with_errors++;
-
- cmd->scsi_done(cmd);
- }
- ahd_done_unlock(ahd, &done_flags);
- return (acmd);
-}
-
-static __inline void
-ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev)
-{
- if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
- && dev->active == 0) {
- dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
- dev->qfrozen--;
- }
-
- if (TAILQ_FIRST(&dev->busyq) == NULL
- || dev->openings == 0 || dev->qfrozen != 0)
- return;
-
- ahd_linux_run_device_queue(ahd, dev);
-}
-
-static __inline struct ahd_linux_device *
-ahd_linux_next_device_to_run(struct ahd_softc *ahd)
-{
-
- if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
- || (ahd->platform_data->qfrozen != 0
- && AHD_DV_SIMQ_FROZEN(ahd) == 0))
- return (NULL);
- return (TAILQ_FIRST(&ahd->platform_data->device_runq));
-}
-
-static __inline void
-ahd_linux_run_device_queues(struct ahd_softc *ahd)
-{
- struct ahd_linux_device *dev;
-
- while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
- TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
- dev->flags &= ~AHD_DEV_ON_RUN_LIST;
- ahd_linux_check_device_queue(ahd, dev);
- }
-}
+/****************************** Inlines ***************************************/
+static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
static __inline void
ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
int direction;
cmd = scb->io_ctx;
@@ -705,197 +399,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
#define BUILD_SCSIID(ahd, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
-/************************ Host template entry points *************************/
-static int ahd_linux_detect(Scsi_Host_Template *);
-static const char *ahd_linux_info(struct Scsi_Host *);
-static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int ahd_linux_slave_alloc(Scsi_Device *);
-static int ahd_linux_slave_configure(Scsi_Device *);
-static void ahd_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int ahd_linux_biosparam(struct scsi_device*,
- struct block_device*, sector_t, int[]);
-#endif
-#else
-static int ahd_linux_release(struct Scsi_Host *);
-static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
- Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int ahd_linux_bus_reset(Scsi_Cmnd *);
-static int ahd_linux_dev_reset(Scsi_Cmnd *);
-static int ahd_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc. This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer. Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem. We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahd_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- u_int cur_size;
- u_int best_size;
-
- /*
- * The SCSI allocator rounds to the nearest 512 bytes
- * an cannot allocate across a page boundary. Our algorithm
- * is to start at 1K of scsi malloc space per-command and
- * loop through all factors of the PAGE_SIZE and pick the best.
- */
- best_size = 0;
- for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
- u_int nseg;
-
- nseg = cur_size / sizeof(struct scatterlist);
- if (nseg < AHD_LINUX_MIN_NSEG)
- continue;
-
- if (best_size == 0) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- } else {
- u_int best_rem;
- u_int cur_rem;
-
- /*
- * Compare the traits of the current "best_size"
- * with the current size to determine if the
- * current size is a better size.
- */
- best_rem = best_size % sizeof(struct scatterlist);
- cur_rem = cur_size % sizeof(struct scatterlist);
- if (cur_rem < best_rem) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- }
- }
- }
-#endif
-}
-
-/*
- * Try to detect an Adaptec 79XX controller.
- */
-static int
-ahd_linux_detect(Scsi_Host_Template *template)
-{
- struct ahd_softc *ahd;
- int found;
- int error = 0;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * It is a bug that the upper layer takes
- * this lock just prior to calling us.
- */
- spin_unlock_irq(&io_request_lock);
-#endif
-
- /*
- * Sanity checking of Linux SCSI data structures so
- * that some of our hacks^H^H^H^H^Hassumptions aren't
- * violated.
- */
- if (offsetof(struct ahd_cmd_internal, end)
- > offsetof(struct scsi_cmnd, host_scribble)) {
- printf("ahd_linux_detect: SCSI data structures changed.\n");
- printf("ahd_linux_detect: Unable to attach\n");
- return (0);
- }
- /*
- * Determine an appropriate size for our Scatter Gatther lists.
- */
- ahd_linux_size_nseg();
-#ifdef MODULE
- /*
- * If we've been passed any parameters, process them now.
- */
- if (aic79xx)
- aic79xx_setup(aic79xx);
-#endif
-
- template->proc_name = "aic79xx";
-
- /*
- * Initialize our softc list lock prior to
- * probing for any adapters.
- */
- ahd_list_lockinit();
-
-#ifdef CONFIG_PCI
- error = ahd_linux_pci_init();
- if (error)
- return error;
-#endif
-
- /*
- * Register with the SCSI layer all
- * controllers we've found.
- */
- found = 0;
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-
- if (ahd_linux_register_host(ahd, template) == 0)
- found++;
- }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- spin_lock_irq(&io_request_lock);
-#endif
- aic79xx_detect_complete++;
- return 0;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-static int
-ahd_linux_release(struct Scsi_Host * host)
-{
- struct ahd_softc *ahd;
- u_long l;
-
- ahd_list_lock(&l);
- if (host != NULL) {
-
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
- if (ahd != NULL) {
- u_long s;
-
- ahd_lock(ahd, &s);
- ahd_intr_enable(ahd, FALSE);
- ahd_unlock(ahd, &s);
- ahd_free(ahd);
- }
- }
- ahd_list_unlock(&l);
- return (0);
-}
-#endif
-
/*
* Return a string describing the driver.
*/
@@ -928,220 +431,177 @@ ahd_linux_info(struct Scsi_Host *host)
* Queue an SCB to the controller.
*/
static int
-ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
{
struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
+ struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
/*
- * Save the callback on completion function.
- */
- cmd->scsi_done = scsi_done;
-
- ahd_midlayer_entrypoint_lock(ahd, &flags);
-
- /*
* Close the race of a command that was in the process of
* being queued to us just as our simq was frozen. Let
* DV commands through so long as we are only frozen to
* perform DV.
*/
- if (ahd->platform_data->qfrozen != 0
- && AHD_DV_CMD(cmd) == 0) {
-
- ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- return (0);
- }
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id, cmd->device->lun,
- /*alloc*/TRUE);
- if (dev == NULL) {
- ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
- ahd_name(ahd));
- return (0);
+ if (ahd->platform_data->qfrozen != 0) {
+ printf("%s: queue frozen\n", ahd_name(ahd));
+
+ return SCSI_MLQUEUE_HOST_BUSY;
}
- if (cmd->cmd_len > MAX_CDB_LEN)
- return (-EINVAL);
+
+ /*
+ * Save the callback on completion function.
+ */
+ cmd->scsi_done = scsi_done;
+
cmd->result = CAM_REQ_INPROG << 16;
- TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);
- if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- ahd_linux_run_device_queues(ahd);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- return (0);
+
+ return ahd_linux_run_command(ahd, dev, cmd);
+}
+
+static inline struct scsi_target **
+ahd_linux_target_in_softc(struct scsi_target *starget)
+{
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+ unsigned int target_offset;
+
+ target_offset = starget->id;
+ if (starget->channel != 0)
+ target_offset += 8;
+
+ return &ahd->platform_data->starget[target_offset];
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static int
-ahd_linux_slave_alloc(Scsi_Device *device)
+ahd_linux_target_alloc(struct scsi_target *starget)
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+ unsigned long flags;
+ struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+ struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+ struct ahd_devinfo devinfo;
+ struct ahd_initiator_tinfo *tinfo;
+ struct ahd_tmode_tstate *tstate;
+ char channel = starget->channel + 'A';
- ahd = *((struct ahd_softc **)device->host->hostdata);
- if (bootverbose)
- printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id);
- return (0);
+ ahd_lock(ahd, &flags);
+
+ BUG_ON(*ahd_targp != NULL);
+
+ *ahd_targp = starget;
+ memset(targ, 0, sizeof(*targ));
+
+ tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
+ starget->id, &tstate);
+ ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
+ CAM_LUN_WILDCARD, channel,
+ ROLE_INITIATOR);
+ spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */
+ if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
+ spi_max_offset(starget) = MAX_OFFSET_PACED_BUG;
+ else
+ spi_max_offset(starget) = MAX_OFFSET_PACED;
+ spi_max_width(starget) = ahd->features & AHD_WIDE;
+
+ ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
+ AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+ AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_unlock(ahd, &flags);
+
+ return 0;
+}
+
+static void
+ahd_linux_target_destroy(struct scsi_target *starget)
+{
+ struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+
+ *ahd_targp = NULL;
}
static int
-ahd_linux_slave_configure(Scsi_Device *device)
+ahd_linux_slave_alloc(struct scsi_device *sdev)
{
- struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)sdev->host->hostdata);
+ struct scsi_target *starget = sdev->sdev_target;
+ struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+ struct ahd_linux_device *dev;
- ahd = *((struct ahd_softc **)device->host->hostdata);
if (bootverbose)
- printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id);
- ahd_midlayer_entrypoint_lock(ahd, &flags);
+ printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
+
+ BUG_ON(targ->sdev[sdev->lun] != NULL);
+
+ dev = scsi_transport_device_data(sdev);
+ memset(dev, 0, sizeof(*dev));
+
/*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
+ * We start out life using untagged
+ * transactions of which we allow one.
*/
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- dev->flags |= AHD_DEV_SLAVE_CONFIGURED;
- dev->scsi_device = device;
- ahd_linux_device_queue_depth(ahd, dev);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ dev->openings = 1;
+
+ /*
+ * Set maxtags to 0. This will be changed if we
+ * later determine that we are dealing with
+ * a tagged queuing capable device.
+ */
+ dev->maxtags = 0;
+
+ targ->sdev[sdev->lun] = sdev;
+
return (0);
}
-static void
-ahd_linux_slave_destroy(Scsi_Device *device)
+static int
+ahd_linux_slave_configure(struct scsi_device *sdev)
{
struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
- ahd = *((struct ahd_softc **)device->host->hostdata);
+ ahd = *((struct ahd_softc **)sdev->host->hostdata);
if (bootverbose)
- printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id);
- ahd_midlayer_entrypoint_lock(ahd, &flags);
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/FALSE);
+ printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id);
- /*
- * Filter out "silly" deletions of real devices by only
- * deleting devices that have had slave_configure()
- * called on them. All other devices that have not
- * been configured will automatically be deleted by
- * the refcounting process.
- */
- if (dev != NULL
- && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- if (TAILQ_EMPTY(&dev->busyq)
- && dev->active == 0
- && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
- ahd_linux_free_device(ahd, dev);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ ahd_linux_device_queue_depth(sdev);
+
+ /* Initial Domain Validation */
+ if (!spi_initial_dv(sdev->sdev_target))
+ spi_dv_device(sdev);
+
+ return 0;
}
-#else
-/*
- * Sets the queue depth for each SCSI device hanging
- * off the input host adapter.
- */
+
static void
-ahd_linux_select_queue_depth(struct Scsi_Host * host,
- Scsi_Device * scsi_devs)
+ahd_linux_slave_destroy(struct scsi_device *sdev)
{
- Scsi_Device *device;
- Scsi_Device *ldev;
struct ahd_softc *ahd;
- u_long flags;
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+ struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
- ahd = *((struct ahd_softc **)host->hostdata);
- ahd_lock(ahd, &flags);
- for (device = scsi_devs; device != NULL; device = device->next) {
+ ahd = *((struct ahd_softc **)sdev->host->hostdata);
+ if (bootverbose)
+ printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
- /*
- * Watch out for duplicate devices. This works around
- * some quirks in how the SCSI scanning code does its
- * device management.
- */
- for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
- if (ldev->host == device->host
- && ldev->channel == device->channel
- && ldev->id == device->id
- && ldev->lun == device->lun)
- break;
- }
- /* Skip duplicate. */
- if (ldev != device)
- continue;
+ BUG_ON(dev->active);
- if (device->host == host) {
- struct ahd_linux_device *dev;
+ targ->sdev[sdev->lun] = NULL;
- /*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
- */
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- dev->scsi_device = device;
- ahd_linux_device_queue_depth(ahd, dev);
- device->queue_depth = dev->openings
- + dev->active;
- if ((dev->flags & (AHD_DEV_Q_BASIC
- | AHD_DEV_Q_TAGGED)) == 0) {
- /*
- * We allow the OS to queue 2 untagged
- * transactions to us at any time even
- * though we can only execute them
- * serially on the controller/device.
- * This should remove some latency.
- */
- device->queue_depth = 2;
- }
- }
- }
- }
- ahd_unlock(ahd, &flags);
}
-#endif
#if defined(__i386__)
/*
* Return the disk geometry for the given SCSI device.
*/
static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
uint8_t *bh;
-#else
-ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
-{
- struct scsi_device *sdev = disk->device;
- u_long capacity = disk->capacity;
- struct buffer_head *bh;
-#endif
int heads;
int sectors;
int cylinders;
@@ -1151,22 +611,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
ahd = *((struct ahd_softc **)sdev->host->hostdata);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
bh = scsi_bios_ptable(bdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
-#else
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
-#endif
-
if (bh) {
ret = scsi_partsize(bh, capacity,
&geom[2], &geom[0], &geom[1]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
kfree(bh);
-#else
- brelse(bh);
-#endif
if (ret != -1)
return (ret);
}
@@ -1194,392 +643,35 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
* Abort the current SCSI command(s).
*/
static int
-ahd_linux_abort(Scsi_Cmnd *cmd)
+ahd_linux_abort(struct scsi_cmnd *cmd)
{
- struct ahd_softc *ahd;
- struct ahd_cmd *acmd;
- struct ahd_cmd *list_acmd;
- struct ahd_linux_device *dev;
- struct scb *pending_scb;
- u_long s;
- u_int saved_scbptr;
- u_int active_scbptr;
- u_int last_phase;
- u_int cdb_byte;
- int retval;
- int was_paused;
- int paused;
- int wait;
- int disconnected;
- ahd_mode_state saved_modes;
-
- pending_scb = NULL;
- paused = FALSE;
- wait = FALSE;
- ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
- acmd = (struct ahd_cmd *)cmd;
-
- printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun, cmd);
- for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
- printf(" 0x%x", cmd->cmnd[cdb_byte]);
- printf("\n");
-
- /*
- * In all versions of Linux, we have to work around
- * a major flaw in how the mid-layer is locked down
- * if we are to sleep successfully in our error handler
- * while allowing our interrupt handler to run. Since
- * the midlayer acquires either the io_request_lock or
- * our lock prior to calling us, we must use the
- * spin_unlock_irq() method for unlocking our lock.
- * This will force interrupts to be enabled on the
- * current CPU. Since the EH thread should not have
- * been running with CPU interrupts disabled other than
- * by acquiring either the io_request_lock or our own
- * lock, this *should* be safe.
- */
- ahd_midlayer_entrypoint_lock(ahd, &s);
-
- /*
- * First determine if we currently own this command.
- * Start by searching the device queue. If not found
- * there, check the pending_scb list. If not found
- * at all, and the system wanted us to just abort the
- * command, return success.
- */
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id, cmd->device->lun,
- /*alloc*/FALSE);
-
- if (dev == NULL) {
- /*
- * No target device for this command exists,
- * so we must not still own the command.
- */
- printf("%s:%d:%d:%d: Is not an active device\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- retval = SUCCESS;
- goto no_cmd;
- }
-
- TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
- if (list_acmd == acmd)
- break;
- }
-
- if (list_acmd != NULL) {
- printf("%s:%d:%d:%d: Command found on device queue\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
- cmd->result = DID_ABORT << 16;
- ahd_linux_queue_cmd_complete(ahd, cmd);
- retval = SUCCESS;
- goto done;
- }
+ int error;
- /*
- * See if we can find a matching cmd in the pending list.
- */
- LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
- if (pending_scb->io_ctx == cmd)
- break;
- }
-
- if (pending_scb == NULL) {
- printf("%s:%d:%d:%d: Command not found\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- goto no_cmd;
- }
-
- if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
- /*
- * We can't queue two recovery actions using the same SCB
- */
- retval = FAILED;
- goto done;
- }
-
- /*
- * Ensure that the card doesn't do anything
- * behind our back. Also make sure that we
- * didn't "just" miss an interrupt that would
- * affect this cmd.
- */
- was_paused = ahd_is_paused(ahd);
- ahd_pause_and_flushwork(ahd);
- paused = TRUE;
-
- if ((pending_scb->flags & SCB_ACTIVE) == 0) {
- printf("%s:%d:%d:%d: Command already completed\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- goto no_cmd;
- }
-
- printf("%s: At time of recovery, card was %spaused\n",
- ahd_name(ahd), was_paused ? "" : "not ");
- ahd_dump_card_state(ahd);
-
- disconnected = TRUE;
- if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
- cmd->device->lun, SCB_GET_TAG(pending_scb),
- ROLE_INITIATOR, CAM_REQ_ABORTED,
- SEARCH_COMPLETE) > 0) {
- printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- retval = SUCCESS;
- goto done;
- }
-
- saved_modes = ahd_save_modes(ahd);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- last_phase = ahd_inb(ahd, LASTPHASE);
- saved_scbptr = ahd_get_scbptr(ahd);
- active_scbptr = saved_scbptr;
- if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
- struct scb *bus_scb;
-
- bus_scb = ahd_lookup_scb(ahd, active_scbptr);
- if (bus_scb == pending_scb)
- disconnected = FALSE;
- }
-
- /*
- * At this point, pending_scb is the scb associated with the
- * passed in command. That command is currently active on the
- * bus or is in the disconnected state.
- */
- if (last_phase != P_BUSFREE
- && SCB_GET_TAG(pending_scb) == active_scbptr) {
-
- /*
- * We're active on the bus, so assert ATN
- * and hope that the target responds.
- */
- pending_scb = ahd_lookup_scb(ahd, active_scbptr);
- pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
- ahd_outb(ahd, MSG_OUT, HOST_MSG);
- ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
- printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
- ahd_name(ahd), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
- wait = TRUE;
- } else if (disconnected) {
-
- /*
- * Actually re-queue this SCB in an attempt
- * to select the device before it reconnects.
- */
- pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
- ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
- pending_scb->hscb->cdb_len = 0;
- pending_scb->hscb->task_attribute = 0;
- pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
-
- if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
- /*
- * Mark the SCB has having an outstanding
- * task management function. Should the command
- * complete normally before the task management
- * function can be sent, the host will be notified
- * to abort our requeued SCB.
- */
- ahd_outb(ahd, SCB_TASK_MANAGEMENT,
- pending_scb->hscb->task_management);
- } else {
- /*
- * If non-packetized, set the MK_MESSAGE control
- * bit indicating that we desire to send a message.
- * We also set the disconnected flag since there is
- * no guarantee that our SCB control byte matches
- * the version on the card. We don't want the
- * sequencer to abort the command thinking an
- * unsolicited reselection occurred.
- */
- pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
-
- /*
- * The sequencer will never re-reference the
- * in-core SCB. To make sure we are notified
- * during reslection, set the MK_MESSAGE flag in
- * the card's copy of the SCB.
- */
- ahd_outb(ahd, SCB_CONTROL,
- ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
- }
-
- /*
- * Clear out any entries in the QINFIFO first
- * so we are the next SCB for this target
- * to run.
- */
- ahd_search_qinfifo(ahd, cmd->device->id,
- cmd->device->channel + 'A', cmd->device->lun,
- SCB_LIST_NULL, ROLE_INITIATOR,
- CAM_REQUEUE_REQ, SEARCH_COMPLETE);
- ahd_qinfifo_requeue_tail(ahd, pending_scb);
- ahd_set_scbptr(ahd, saved_scbptr);
- ahd_print_path(ahd, pending_scb);
- printf("Device is disconnected, re-queuing SCB\n");
- wait = TRUE;
- } else {
- printf("%s:%d:%d:%d: Unable to deliver message\n",
- ahd_name(ahd), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
- retval = FAILED;
- goto done;
- }
-
-no_cmd:
- /*
- * Our assumption is that if we don't have the command, no
- * recovery action was required, so we return success. Again,
- * the semantics of the mid-layer recovery engine are not
- * well defined, so this may change in time.
- */
- retval = SUCCESS;
-done:
- if (paused)
- ahd_unpause(ahd);
- if (wait) {
- struct timer_list timer;
- int ret;
-
- pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
- spin_unlock_irq(&ahd->platform_data->spin_lock);
- init_timer(&timer);
- timer.data = (u_long)pending_scb;
- timer.expires = jiffies + (5 * HZ);
- timer.function = ahd_linux_sem_timeout;
- add_timer(&timer);
- printf("Recovery code sleeping\n");
- down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
- ret = del_timer_sync(&timer);
- if (ret == 0) {
- printf("Timer Expired\n");
- retval = FAILED;
- }
- spin_lock_irq(&ahd->platform_data->spin_lock);
- }
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &s);
- return (retval);
-}
-
-
-static void
-ahd_linux_dev_reset_complete(Scsi_Cmnd *cmd)
-{
- free(cmd, M_DEVBUF);
+ error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT);
+ if (error != 0)
+ printf("aic79xx_abort returns 0x%x\n", error);
+ return error;
}
/*
* Attempt to send a target reset message to the device that timed out.
*/
static int
-ahd_linux_dev_reset(Scsi_Cmnd *cmd)
+ahd_linux_dev_reset(struct scsi_cmnd *cmd)
{
- struct ahd_softc *ahd;
- struct scsi_cmnd *recovery_cmd;
- struct ahd_linux_device *dev;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
- struct scb *scb;
- struct hardware_scb *hscb;
- u_long s;
- struct timer_list timer;
- int retval;
-
- ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
- recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
- if (!recovery_cmd)
- return (FAILED);
- memset(recovery_cmd, 0, sizeof(struct scsi_cmnd));
- recovery_cmd->device = cmd->device;
- recovery_cmd->scsi_done = ahd_linux_dev_reset_complete;
-#ifdef AHD_DEBUG
- if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
- printf("%s:%d:%d:%d: Device reset called for cmd %p\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun, cmd);
-#endif
- ahd_lock(ahd, &s);
-
- dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
- cmd->device->lun, /*alloc*/FALSE);
- if (dev == NULL) {
- ahd_unlock(ahd, &s);
- kfree(recovery_cmd);
- return (FAILED);
- }
- if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
- ahd_unlock(ahd, &s);
- kfree(recovery_cmd);
- return (FAILED);
- }
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- cmd->device->id, &tstate);
- recovery_cmd->result = CAM_REQ_INPROG << 16;
- recovery_cmd->host_scribble = (char *)scb;
- scb->io_ctx = recovery_cmd;
- scb->platform_data->dev = dev;
- scb->sg_count = 0;
- ahd_set_residual(scb, 0);
- ahd_set_sense_residual(scb, 0);
- hscb = scb->hscb;
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahd, cmd);
- hscb->lun = cmd->device->lun;
- hscb->cdb_len = 0;
- hscb->task_management = SIU_TASKMGMT_LUN_RESET;
- scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
- if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- scb->flags |= SCB_PACKETIZED;
- } else {
- hscb->control |= MK_MESSAGE;
- }
- dev->openings--;
- dev->active++;
- dev->commands_issued++;
- LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
- ahd_queue_scb(ahd, scb);
+ int error;
- scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
- ahd_unlock(ahd, &s);
- init_timer(&timer);
- timer.data = (u_long)scb;
- timer.expires = jiffies + (5 * HZ);
- timer.function = ahd_linux_sem_timeout;
- add_timer(&timer);
- printf("Recovery code sleeping\n");
- down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
- retval = SUCCESS;
- if (del_timer_sync(&timer) == 0) {
- printf("Timer Expired\n");
- retval = FAILED;
- }
- ahd_lock(ahd, &s);
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &s);
- printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
- return (retval);
+ error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
+ if (error != 0)
+ printf("aic79xx_dev_reset returns 0x%x\n", error);
+ return error;
}
/*
* Reset the SCSI bus.
*/
static int
-ahd_linux_bus_reset(Scsi_Cmnd *cmd)
+ahd_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahd_softc *ahd;
u_long s;
@@ -1594,7 +686,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
- ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &s);
if (bootverbose)
@@ -1604,9 +695,10 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
return (SUCCESS);
}
-Scsi_Host_Template aic79xx_driver_template = {
+struct scsi_host_template aic79xx_driver_template = {
.module = THIS_MODULE,
.name = "aic79xx",
+ .proc_name = "aic79xx",
.proc_info = ahd_linux_proc_info,
.info = ahd_linux_info,
.queuecommand = ahd_linux_queue,
@@ -1623,37 +715,10 @@ Scsi_Host_Template aic79xx_driver_template = {
.slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure,
.slave_destroy = ahd_linux_slave_destroy,
+ .target_alloc = ahd_linux_target_alloc,
+ .target_destroy = ahd_linux_target_destroy,
};
-/**************************** Tasklet Handler *********************************/
-
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahd_schedule_runq() calls this routine
- * directly and ahd_schedule_runq() is called with our lock held.
- */
-static void
-ahd_runq_tasklet(unsigned long data)
-{
- struct ahd_softc* ahd;
- struct ahd_linux_device *dev;
- u_long flags;
-
- ahd = (struct ahd_softc *)data;
- ahd_lock(ahd, &flags);
- while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-
- TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
- dev->flags &= ~AHD_DEV_ON_RUN_LIST;
- ahd_linux_check_device_queue(ahd, dev);
- /* Yeild to our interrupt handler */
- ahd_unlock(ahd, &flags);
- ahd_lock(ahd, &flags);
- }
- ahd_unlock(ahd, &flags);
-}
-
/******************************** Bus DMA *************************************/
int
ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
@@ -1693,36 +758,10 @@ int
ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
int flags, bus_dmamap_t *mapp)
{
- bus_dmamap_t map;
-
- map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
- if (map == NULL)
- return (ENOMEM);
- /*
- * Although we can dma data above 4GB, our
- * "consistent" memory is below 4GB for
- * space efficiency reasons (only need a 4byte
- * address). For this reason, we have to reset
- * our dma mask when doing allocations.
- */
- if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
- printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
*vaddr = pci_alloc_consistent(ahd->dev_softc,
- dmat->maxsize, &map->bus_addr);
- if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc,
- ahd->platform_data->hw_dma_mask)) {
- printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
+ dmat->maxsize, mapp);
if (*vaddr == NULL)
return (ENOMEM);
- *mapp = map;
return(0);
}
@@ -1731,7 +770,7 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
void* vaddr, bus_dmamap_t map)
{
pci_free_consistent(ahd->dev_softc, dmat->maxsize,
- vaddr, map->bus_addr);
+ vaddr, map);
}
int
@@ -1745,7 +784,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
*/
bus_dma_segment_t stack_sg;
- stack_sg.ds_addr = map->bus_addr;
+ stack_sg.ds_addr = map;
stack_sg.ds_len = dmat->maxsize;
cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
return (0);
@@ -1754,11 +793,6 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
void
ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
{
- /*
- * The map may is NULL in our < 2.3.X implementation.
- */
- if (map != NULL)
- free(map, M_DEVBUF);
}
int
@@ -1823,41 +857,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
}
static void
-ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
-{
-
- if ((instance >= 0) && (targ >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_tag_info))
- && (targ < AHD_NUM_TARGETS)) {
- aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
- if (bootverbose)
- printf("tag_info[%d:%d] = %d\n", instance, targ, value);
- }
-}
-
-static void
-ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value)
-{
- if ((instance >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {
- aic79xx_rd_strm_info[instance] = value & 0xFFFF;
- if (bootverbose)
- printf("rd_strm[%d] = 0x%x\n", instance, value);
- }
-}
-
-static void
-ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
-{
- if ((instance >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {
- aic79xx_dv_settings[instance] = value;
- if (bootverbose)
- printf("dv[%d] = %d\n", instance, value);
- }
-}
-
-static void
ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
{
@@ -1887,6 +886,99 @@ ahd_linux_setup_tag_info_global(char *p)
}
}
+static void
+ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
+{
+
+ if ((instance >= 0) && (targ >= 0)
+ && (instance < NUM_ELEMENTS(aic79xx_tag_info))
+ && (targ < AHD_NUM_TARGETS)) {
+ aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
+ if (bootverbose)
+ printf("tag_info[%d:%d] = %d\n", instance, targ, value);
+ }
+}
+
+static char *
+ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+ void (*callback)(u_long, int, int, int32_t),
+ u_long callback_arg)
+{
+ char *tok_end;
+ char *tok_end2;
+ int i;
+ int instance;
+ int targ;
+ int done;
+ char tok_list[] = {'.', ',', '{', '}', '\0'};
+
+ /* All options use a ':' name/arg separator */
+ if (*opt_arg != ':')
+ return (opt_arg);
+ opt_arg++;
+ instance = -1;
+ targ = -1;
+ done = FALSE;
+ /*
+ * Restore separator that may be in
+ * the middle of our option argument.
+ */
+ tok_end = strchr(opt_arg, '\0');
+ if (tok_end < end)
+ *tok_end = ',';
+ while (!done) {
+ switch (*opt_arg) {
+ case '{':
+ if (instance == -1) {
+ instance = 0;
+ } else {
+ if (depth > 1) {
+ if (targ == -1)
+ targ = 0;
+ } else {
+ printf("Malformed Option %s\n",
+ opt_name);
+ done = TRUE;
+ }
+ }
+ opt_arg++;
+ break;
+ case '}':
+ if (targ != -1)
+ targ = -1;
+ else if (instance != -1)
+ instance = -1;
+ opt_arg++;
+ break;
+ case ',':
+ case '.':
+ if (instance == -1)
+ done = TRUE;
+ else if (targ >= 0)
+ targ++;
+ else if (instance >= 0)
+ instance++;
+ opt_arg++;
+ break;
+ case '\0':
+ done = TRUE;
+ break;
+ default:
+ tok_end = end;
+ for (i = 0; tok_list[i]; i++) {
+ tok_end2 = strchr(opt_arg, tok_list[i]);
+ if ((tok_end2) && (tok_end2 < tok_end))
+ tok_end = tok_end2;
+ }
+ callback(callback_arg, instance, targ,
+ simple_strtol(opt_arg, NULL, 0));
+ opt_arg = tok_end;
+ break;
+ }
+ }
+ return (opt_arg);
+}
+
/*
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
@@ -1916,8 +1008,6 @@ aic79xx_setup(char *s)
{ "seltime", &aic79xx_seltime },
{ "tag_info", NULL },
{ "global_tag_depth", NULL},
- { "rd_strm", NULL },
- { "dv", NULL },
{ "slewrate", NULL },
{ "precomp", NULL },
{ "amplitude", NULL },
@@ -1946,24 +1036,18 @@ aic79xx_setup(char *s)
if (strncmp(p, "global_tag_depth", n) == 0) {
ahd_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
- s = aic_parse_brace_option("tag_info", p + n, end,
+ s = ahd_parse_brace_option("tag_info", p + n, end,
2, ahd_linux_setup_tag_info, 0);
- } else if (strncmp(p, "rd_strm", n) == 0) {
- s = aic_parse_brace_option("rd_strm", p + n, end,
- 1, ahd_linux_setup_rd_strm_info, 0);
- } else if (strncmp(p, "dv", n) == 0) {
- s = aic_parse_brace_option("dv", p + n, end, 1,
- ahd_linux_setup_dv, 0);
} else if (strncmp(p, "slewrate", n) == 0) {
- s = aic_parse_brace_option("slewrate",
+ s = ahd_parse_brace_option("slewrate",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_SLEWRATE_INDEX);
} else if (strncmp(p, "precomp", n) == 0) {
- s = aic_parse_brace_option("precomp",
+ s = ahd_parse_brace_option("precomp",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_PRECOMP_INDEX);
} else if (strncmp(p, "amplitude", n) == 0) {
- s = aic_parse_brace_option("amplitude",
+ s = ahd_parse_brace_option("amplitude",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_AMPLITUDE_INDEX);
} else if (p[n] == ':') {
@@ -1982,13 +1066,12 @@ __setup("aic79xx=", aic79xx_setup);
uint32_t aic79xx_verbose;
int
-ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
+ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
{
char buf[80];
struct Scsi_Host *host;
char *new_name;
u_long s;
- u_long target;
template->name = ahd->description;
host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
@@ -1997,11 +1080,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
*((struct ahd_softc **)host->hostdata) = ahd;
ahd_lock(ahd, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_assign_lock(host, &ahd->platform_data->spin_lock);
-#elif AHD_SCSI_HAS_HOST_LOCK != 0
- host->lock = &ahd->platform_data->spin_lock;
-#endif
ahd->platform_data->host = host;
host->can_queue = AHD_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -2012,7 +1091,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
host->max_lun = AHD_NUM_LUNS;
host->max_channel = 0;
host->sg_tablesize = AHD_NSEG;
- ahd_set_unit(ahd, ahd_linux_next_unit());
+ ahd_set_unit(ahd, ahd_linux_unit++);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@@ -2020,54 +1099,14 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
ahd_set_name(ahd, new_name);
}
host->unique_id = ahd->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- scsi_set_pci_device(host, ahd->dev_softc);
-#endif
- ahd_linux_setup_user_rd_strm_settings(ahd);
ahd_linux_initialize_scsi_bus(ahd);
- ahd_unlock(ahd, &s);
- ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);
- ahd_lock(ahd, &s);
- if (ahd->platform_data->dv_pid < 0) {
- printf("%s: Failed to create DV thread, error= %d\n",
- ahd_name(ahd), ahd->platform_data->dv_pid);
- return (-ahd->platform_data->dv_pid);
- }
- /*
- * Initially allocate *all* of our linux target objects
- * so that the DV thread will scan them all in parallel
- * just after driver initialization. Any device that
- * does not exist will have its target object destroyed
- * by the selection timeout handler. In the case of a
- * device that appears after the initial DV scan, async
- * negotiation will occur for the first command, and DV
- * will comence should that first command be successful.
- */
- for (target = 0; target < host->max_id; target++) {
-
- /*
- * Skip our own ID. Some Compaq/HP storage devices
- * have enclosure management devices that respond to
- * single bit selection (i.e. selecting ourselves).
- * It is expected that either an external application
- * or a modified kernel will be used to probe this
- * ID if it is appropriate. To accommodate these
- * installations, ahc_linux_alloc_target() will allocate
- * for our ID if asked to do so.
- */
- if (target == ahd->our_id)
- continue;
-
- ahd_linux_alloc_target(ahd, 0, target);
- }
ahd_intr_enable(ahd, TRUE);
- ahd_linux_start_dv(ahd);
ahd_unlock(ahd, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ host->transportt = ahd_linux_transport_template;
+
scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
scsi_scan_host(host);
-#endif
return (0);
}
@@ -2081,29 +1120,6 @@ ahd_linux_get_memsize(void)
}
/*
- * Find the smallest available unit number to use
- * for a new device. We don't just use a static
- * count to handle the "repeated hot-(un)plug"
- * scenario.
- */
-static int
-ahd_linux_next_unit(void)
-{
- struct ahd_softc *ahd;
- int unit;
-
- unit = 0;
-retry:
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- if (ahd->unit == unit) {
- unit++;
- goto retry;
- }
- }
- return (unit);
-}
-
-/*
* Place the SCSI bus into a known state by either resetting it,
* or forcing transfer negotiations on the next command to any
* target.
@@ -2162,20 +1178,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
if (ahd->platform_data == NULL)
return (ENOMEM);
memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
- TAILQ_INIT(&ahd->platform_data->completeq);
- TAILQ_INIT(&ahd->platform_data->device_runq);
ahd->platform_data->irq = AHD_LINUX_NOIRQ;
- ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
ahd_lockinit(ahd);
- ahd_done_lockinit(ahd);
- init_timer(&ahd->platform_data->completeq_timer);
- ahd->platform_data->completeq_timer.data = (u_long)ahd;
- ahd->platform_data->completeq_timer.function =
- (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
- init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
- init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
- ahd_setup_runq_tasklet(ahd);
ahd->seltime = (aic79xx_seltime & 0x3) << 4;
return (0);
}
@@ -2183,39 +1188,27 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
void
ahd_platform_free(struct ahd_softc *ahd)
{
- struct ahd_linux_target *targ;
- struct ahd_linux_device *dev;
+ struct scsi_target *starget;
int i, j;
if (ahd->platform_data != NULL) {
- del_timer_sync(&ahd->platform_data->completeq_timer);
- ahd_linux_kill_dv_thread(ahd);
- ahd_teardown_runq_tasklet(ahd);
if (ahd->platform_data->host != NULL) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_remove_host(ahd->platform_data->host);
-#endif
scsi_host_put(ahd->platform_data->host);
}
/* destroy all of the device and target objects */
for (i = 0; i < AHD_NUM_TARGETS; i++) {
- targ = ahd->platform_data->targets[i];
- if (targ != NULL) {
- /* Keep target around through the loop. */
- targ->refcount++;
+ starget = ahd->platform_data->starget[i];
+ if (starget != NULL) {
for (j = 0; j < AHD_NUM_LUNS; j++) {
-
- if (targ->devices[j] == NULL)
+ struct ahd_linux_target *targ =
+ scsi_transport_target_data(starget);
+ if (targ->sdev[j] == NULL)
continue;
- dev = targ->devices[j];
- ahd_linux_free_device(ahd, dev);
+ targ->sdev[j] = NULL;
}
- /*
- * Forcibly free the target now that
- * all devices are gone.
- */
- ahd_linux_free_target(ahd, targ);
+ ahd->platform_data->starget[i] = NULL;
}
}
@@ -2233,16 +1226,6 @@ ahd_platform_free(struct ahd_softc *ahd)
release_mem_region(ahd->platform_data->mem_busaddr,
0x1000);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * In 2.4 we detach from the scsi midlayer before the PCI
- * layer invokes our remove callback. No per-instance
- * detach is provided, so we must reach inside the PCI
- * subsystem's internals and detach our driver manually.
- */
- if (ahd->dev_softc != NULL)
- ahd->dev_softc->driver = NULL;
-#endif
free(ahd->platform_data, M_DEVBUF);
}
}
@@ -2280,13 +1263,22 @@ void
ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_queue_alg alg)
{
+ struct scsi_target *starget;
+ struct ahd_linux_target *targ;
struct ahd_linux_device *dev;
+ struct scsi_device *sdev;
int was_queuing;
int now_queuing;
- dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
- devinfo->target,
- devinfo->lun, /*alloc*/FALSE);
+ starget = ahd->platform_data->starget[devinfo->target];
+ targ = scsi_transport_target_data(starget);
+ BUG_ON(targ == NULL);
+ sdev = targ->sdev[devinfo->lun];
+ if (sdev == NULL)
+ return;
+
+ dev = scsi_transport_device_data(sdev);
+
if (dev == NULL)
return;
was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
@@ -2339,1434 +1331,37 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
dev->maxtags = 0;
dev->openings = 1 - dev->active;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if (dev->scsi_device != NULL) {
- switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
- case AHD_DEV_Q_BASIC:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_SIMPLE_TASK,
- dev->openings + dev->active);
- break;
- case AHD_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_ORDERED_TASK,
- dev->openings + dev->active);
- break;
- default:
- /*
- * We allow the OS to queue 2 untagged transactions to
- * us at any time even though we can only execute them
- * serially on the controller/device. This should
- * remove some latency.
- */
- scsi_adjust_queue_depth(dev->scsi_device,
- /*NON-TAGGED*/0,
- /*queue depth*/2);
- break;
- }
- }
-#endif
-}
-
-int
-ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
- int lun, u_int tag, role_t role, uint32_t status)
-{
- int targ;
- int maxtarg;
- int maxlun;
- int clun;
- int count;
-
- if (tag != SCB_LIST_NULL)
- return (0);
-
- targ = 0;
- if (target != CAM_TARGET_WILDCARD) {
- targ = target;
- maxtarg = targ + 1;
- } else {
- maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
- }
- clun = 0;
- if (lun != CAM_LUN_WILDCARD) {
- clun = lun;
- maxlun = clun + 1;
- } else {
- maxlun = AHD_NUM_LUNS;
- }
-
- count = 0;
- for (; targ < maxtarg; targ++) {
-
- for (; clun < maxlun; clun++) {
- struct ahd_linux_device *dev;
- struct ahd_busyq *busyq;
- struct ahd_cmd *acmd;
-
- dev = ahd_linux_get_device(ahd, /*chan*/0, targ,
- clun, /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- busyq = &dev->busyq;
- while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- cmd = &acmd_scsi_cmd(acmd);
- TAILQ_REMOVE(busyq, acmd,
- acmd_links.tqe);
- count++;
- cmd->result = status << 16;
- ahd_linux_queue_cmd_complete(ahd, cmd);
- }
- }
- }
-
- return (count);
-}
-
-static void
-ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
-{
- u_long flags;
-
- ahd_lock(ahd, &flags);
- del_timer(&ahd->platform_data->completeq_timer);
- ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &flags);
-}
-
-static void
-ahd_linux_start_dv(struct ahd_softc *ahd)
-{
-
- /*
- * Freeze the simq and signal ahd_linux_queue to not let any
- * more commands through
- */
- if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s: Starting DV\n", ahd_name(ahd));
-#endif
-
- ahd->platform_data->flags |= AHD_DV_ACTIVE;
- ahd_freeze_simq(ahd);
-
- /* Wake up the DV kthread */
- up(&ahd->platform_data->dv_sem);
- }
-}
-
-static int
-ahd_linux_dv_thread(void *data)
-{
- struct ahd_softc *ahd;
- int target;
- u_long s;
-
- ahd = (struct ahd_softc *)data;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("In DV Thread\n");
-#endif
-
- /*
- * Complete thread creation.
- */
- lock_kernel();
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
- /*
- * Don't care about any signals.
- */
- siginitsetinv(&current->blocked, 0);
-
- daemonize();
- sprintf(current->comm, "ahd_dv_%d", ahd->unit);
-#else
- daemonize("ahd_dv_%d", ahd->unit);
- current->flags |= PF_NOFREEZE;
-#endif
- unlock_kernel();
-
- while (1) {
- /*
- * Use down_interruptible() rather than down() to
- * avoid inclusion in the load average.
- */
- down_interruptible(&ahd->platform_data->dv_sem);
-
- /* Check to see if we've been signaled to exit */
- ahd_lock(ahd, &s);
- if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) {
- ahd_unlock(ahd, &s);
- break;
- }
- ahd_unlock(ahd, &s);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s: Beginning Domain Validation\n",
- ahd_name(ahd));
-#endif
-
- /*
- * Wait for any pending commands to drain before proceeding.
- */
- ahd_lock(ahd, &s);
- while (LIST_FIRST(&ahd->pending_scbs) != NULL) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
-
- /*
- * Wait for the SIMQ to be released so that DV is the
- * only reason the queue is frozen.
- */
- while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
- ahd_unlock(ahd, &s);
-
- for (target = 0; target < AHD_NUM_TARGETS; target++)
- ahd_linux_dv_target(ahd, target);
-
- ahd_lock(ahd, &s);
- ahd->platform_data->flags &= ~AHD_DV_ACTIVE;
- ahd_unlock(ahd, &s);
-
- /*
- * Release the SIMQ so that normal commands are
- * allowed to continue on the bus.
- */
- ahd_release_simq(ahd);
- }
- up(&ahd->platform_data->eh_sem);
- return (0);
-}
-
-static void
-ahd_linux_kill_dv_thread(struct ahd_softc *ahd)
-{
- u_long s;
-
- ahd_lock(ahd, &s);
- if (ahd->platform_data->dv_pid != 0) {
- ahd->platform_data->flags |= AHD_DV_SHUTDOWN;
- ahd_unlock(ahd, &s);
- up(&ahd->platform_data->dv_sem);
-
- /*
- * Use the eh_sem as an indicator that the
- * dv thread is exiting. Note that the dv
- * thread must still return after performing
- * the up on our semaphore before it has
- * completely exited this module. Unfortunately,
- * there seems to be no easy way to wait for the
- * exit of a thread for which you are not the
- * parent (dv threads are parented by init).
- * Cross your fingers...
- */
- down(&ahd->platform_data->eh_sem);
-
- /*
- * Mark the dv thread as already dead. This
- * avoids attempting to kill it a second time.
- * This is necessary because we must kill the
- * DV thread before calling ahd_free() in the
- * module shutdown case to avoid bogus locking
- * in the SCSI mid-layer, but we ahd_free() is
- * called without killing the DV thread in the
- * instance detach case, so ahd_platform_free()
- * calls us again to verify that the DV thread
- * is dead.
- */
- ahd->platform_data->dv_pid = 0;
- } else {
- ahd_unlock(ahd, &s);
- }
-}
-
-#define AHD_LINUX_DV_INQ_SHORT_LEN 36
-#define AHD_LINUX_DV_INQ_LEN 256
-#define AHD_LINUX_DV_TIMEOUT (HZ / 4)
-
-#define AHD_SET_DV_STATE(ahd, targ, newstate) \
- ahd_set_dv_state(ahd, targ, newstate, __LINE__)
-
-static __inline void
-ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ,
- ahd_dv_state newstate, u_int line)
-{
- ahd_dv_state oldstate;
-
- oldstate = targ->dv_state;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s:%d: Going from state %d to state %d\n",
- ahd_name(ahd), line, oldstate, newstate);
-#endif
-
- if (oldstate == newstate)
- targ->dv_state_retry++;
- else
- targ->dv_state_retry = 0;
- targ->dv_state = newstate;
-}
-
-static void
-ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
-{
- struct ahd_devinfo devinfo;
- struct ahd_linux_target *targ;
- struct scsi_cmnd *cmd;
- struct scsi_device *scsi_dev;
- struct scsi_sense_data *sense;
- uint8_t *buffer;
- u_long s;
- u_int timeout;
- int echo_size;
-
- sense = NULL;
- buffer = NULL;
- echo_size = 0;
- ahd_lock(ahd, &s);
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) {
- ahd_unlock(ahd, &s);
- return;
- }
- ahd_compile_devinfo(&devinfo, ahd->our_id, targ->target, /*lun*/0,
- targ->channel + 'A', ROLE_INITIATOR);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, &devinfo);
- printf("Performing DV\n");
- }
-#endif
-
- ahd_unlock(ahd, &s);
-
- cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
- scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK);
- scsi_dev->host = ahd->platform_data->host;
- scsi_dev->id = devinfo.target;
- scsi_dev->lun = devinfo.lun;
- scsi_dev->channel = devinfo.channel - 'A';
- ahd->platform_data->dv_scsi_dev = scsi_dev;
-
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC);
-
- while (targ->dv_state != AHD_DV_STATE_EXIT) {
- timeout = AHD_LINUX_DV_TIMEOUT;
- switch (targ->dv_state) {
- case AHD_DV_STATE_INQ_SHORT_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC_VERIFY:
- /*
- * Set things to async narrow to reduce the
- * chance that the INQ will fail.
- */
- ahd_lock(ahd, &s);
- ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_unlock(ahd, &s);
- timeout = 10 * HZ;
- targ->flags &= ~AHD_INQ_VALID;
- /* FALLTHROUGH */
- case AHD_DV_STATE_INQ_VERIFY:
- {
- u_int inq_len;
-
- if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC)
- inq_len = AHD_LINUX_DV_INQ_SHORT_LEN;
- else
- inq_len = targ->inq_data->additional_length + 5;
- ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len);
- break;
- }
- case AHD_DV_STATE_TUR:
- case AHD_DV_STATE_BUSY:
- timeout = 5 * HZ;
- ahd_linux_dv_tur(ahd, cmd, &devinfo);
- break;
- case AHD_DV_STATE_REBD:
- ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ);
- break;
- case AHD_DV_STATE_WEB:
- ahd_linux_dv_web(ahd, cmd, &devinfo, targ);
- break;
-
- case AHD_DV_STATE_REB:
- ahd_linux_dv_reb(ahd, cmd, &devinfo, targ);
- break;
-
- case AHD_DV_STATE_SU:
- ahd_linux_dv_su(ahd, cmd, &devinfo, targ);
- timeout = 50 * HZ;
- break;
-
- default:
- ahd_print_devinfo(ahd, &devinfo);
- printf("Unknown DV state %d\n", targ->dv_state);
- goto out;
- }
-
- /* Queue the command and wait for it to complete */
- /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
- init_timer(&cmd->eh_timeout);
-#ifdef AHD_DEBUG
- if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
- /*
- * All of the printfs during negotiation
- * really slow down the negotiation.
- * Add a bit of time just to be safe.
- */
- timeout += HZ;
-#endif
- scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout);
- /*
- * In 2.5.X, it is assumed that all calls from the
- * "midlayer" (which we are emulating) will have the
- * ahd host lock held. For other kernels, the
- * io_request_lock must be held.
- */
-#if AHD_SCSI_HAS_HOST_LOCK != 0
- ahd_lock(ahd, &s);
-#else
- spin_lock_irqsave(&io_request_lock, s);
-#endif
- ahd_linux_queue(cmd, ahd_linux_dv_complete);
-#if AHD_SCSI_HAS_HOST_LOCK != 0
- ahd_unlock(ahd, &s);
-#else
- spin_unlock_irqrestore(&io_request_lock, s);
-#endif
- down_interruptible(&ahd->platform_data->dv_cmd_sem);
- /*
- * Wait for the SIMQ to be released so that DV is the
- * only reason the queue is frozen.
- */
- ahd_lock(ahd, &s);
- while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
- ahd_unlock(ahd, &s);
-
- ahd_linux_dv_transition(ahd, cmd, &devinfo, targ);
- }
-
-out:
- if ((targ->flags & AHD_INQ_VALID) != 0
- && ahd_linux_get_device(ahd, devinfo.channel - 'A',
- devinfo.target, devinfo.lun,
- /*alloc*/FALSE) == NULL) {
- /*
- * The DV state machine failed to configure this device.
- * This is normal if DV is disabled. Since we have inquiry
- * data, filter it and use the "optimistic" negotiation
- * parameters found in the inquiry string.
- */
- ahd_linux_filter_inquiry(ahd, &devinfo);
- if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
- ahd_print_devinfo(ahd, &devinfo);
- printf("DV failed to configure device. "
- "Please file a bug report against "
- "this driver.\n");
- }
- }
-
- if (cmd != NULL)
- free(cmd, M_DEVBUF);
-
- if (ahd->platform_data->dv_scsi_dev != NULL) {
- free(ahd->platform_data->dv_scsi_dev, M_DEVBUF);
- ahd->platform_data->dv_scsi_dev = NULL;
- }
-
- ahd_lock(ahd, &s);
- if (targ->dv_buffer != NULL) {
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = NULL;
- }
- if (targ->dv_buffer1 != NULL) {
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = NULL;
- }
- targ->flags &= ~AHD_DV_REQUIRED;
- if (targ->refcount == 0)
- ahd_linux_free_target(ahd, targ);
- ahd_unlock(ahd, &s);
-}
-
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
- u_long s;
- int retval;
-
- ahd_lock(ahd, &s);
- retval = ahd_linux_fallback(ahd, devinfo);
- ahd_unlock(ahd, &s);
-
- return (retval);
-}
-
-static void
-ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ)
-{
- u_int32_t status;
-
- status = aic_error_action(cmd, targ->inq_data,
- ahd_cmd_get_transaction_status(cmd),
- ahd_cmd_get_scsi_status(cmd));
-
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Entering ahd_linux_dv_transition, state= %d, "
- "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
- status, cmd->result);
- }
-#endif
- switch (targ->dv_state) {
- case AHD_DV_STATE_INQ_SHORT_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
- if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
+ switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
+ case AHD_DEV_Q_BASIC:
+ scsi_adjust_queue_depth(sdev,
+ MSG_SIMPLE_TASK,
+ dev->openings + dev->active);
break;
- case AHD_DV_STATE_INQ_ASYNC_VERIFY:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- u_int xportflags;
- u_int spi3data;
-
- if (memcmp(targ->inq_data, targ->dv_buffer,
- AHD_LINUX_DV_INQ_LEN) != 0) {
- /*
- * Inquiry data must have changed.
- * Try from the top again.
- */
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- }
-
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
- targ->flags |= AHD_INQ_VALID;
- if (ahd_linux_user_dv_setting(ahd) == 0)
- break;
-
- xportflags = targ->inq_data->flags;
- if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
- break;
-
- spi3data = targ->inq_data->spi3data;
- switch (spi3data & SID_SPI_CLOCK_DT_ST) {
- default:
- case SID_SPI_CLOCK_ST:
- /* Assume only basic DV is supported. */
- targ->flags |= AHD_BASIC_DV;
- break;
- case SID_SPI_CLOCK_DT:
- case SID_SPI_CLOCK_DT_ST:
- targ->flags |= AHD_ENHANCED_DV;
- break;
- }
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
-
- if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
+ case AHD_DEV_Q_TAGGED:
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TASK,
+ dev->openings + dev->active);
break;
- case AHD_DV_STATE_INQ_VERIFY:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
-
- if (memcmp(targ->inq_data, targ->dv_buffer,
- AHD_LINUX_DV_INQ_LEN) == 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- int i;
-
- ahd_print_devinfo(ahd, devinfo);
- printf("Inquiry buffer mismatch:");
- for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
- if ((i & 0xF) == 0)
- printf("\n ");
- printf("0x%x:0x0%x ",
- ((uint8_t *)targ->inq_data)[i],
- targ->dv_buffer[i]);
- }
- printf("\n");
- }
-#endif
-
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- } else if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
- break;
-
- case AHD_DV_STATE_TUR:
- switch (status & SS_MASK) {
- case SS_NOP:
- if ((targ->flags & AHD_BASIC_DV) != 0) {
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_VERIFY);
- } else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
- } else {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- }
- break;
- case SS_RETRY:
- case SS_TUR:
- if ((status & SS_ERRMASK) == EBUSY) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- break;
- }
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- }
- if (targ->dv_state_retry >= 10) {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV TUR reties exhausted\n");
- }
-#endif
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- if (status & SSQ_DELAY)
- ssleep(1);
-
- break;
- case SS_START:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_REBD:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- uint32_t echo_size;
-
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
- echo_size = scsi_3btoul(&targ->dv_buffer[1]);
- echo_size &= 0x1FFF;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Echo buffer size= %d\n", echo_size);
- }
-#endif
- if (echo_size == 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-
- /* Generate the buffer pattern */
- targ->dv_echo_size = echo_size;
- ahd_linux_generate_dv_pattern(targ);
- /*
- * Setup initial negotiation values.
- */
- ahd_linux_filter_inquiry(ahd, devinfo);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
- if (targ->dv_state_retry <= 10)
- break;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV REBD reties exhausted\n");
- }
-#endif
- /* FALLTHROUGH */
- case SS_FATAL:
- default:
- /*
- * Setup initial negotiation values
- * and try level 1 DV.
- */
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY);
- targ->dv_echo_size = 0;
- break;
- }
- break;
-
- case AHD_DV_STATE_WEB:
- switch (status & SS_MASK) {
- case SS_NOP:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- }
- if (targ->dv_state_retry <= 10)
- break;
- /* FALLTHROUGH */
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV WEB reties exhausted\n");
- }
-#endif
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_REB:
- switch (status & SS_MASK) {
- case SS_NOP:
- if (memcmp(targ->dv_buffer, targ->dv_buffer1,
- targ->dv_echo_size) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0)
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- else
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_WEB);
- break;
- }
-
- if (targ->dv_buffer != NULL) {
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = NULL;
- }
- if (targ->dv_buffer1 != NULL) {
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = NULL;
- }
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
- }
- if (targ->dv_state_retry <= 10) {
- if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
- msleep(ahd->our_id*1000/10);
- break;
- }
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV REB reties exhausted\n");
- }
-#endif
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_SU:
- switch (status & SS_MASK) {
- case SS_NOP:
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_BUSY:
- switch (status & SS_MASK) {
- case SS_NOP:
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if (targ->dv_state_retry < 60) {
- if ((status & SSQ_DELAY) != 0)
- ssleep(1);
- } else {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV BUSY reties exhausted\n");
- }
-#endif
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- }
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
default:
- printf("%s: Invalid DV completion state %d\n", ahd_name(ahd),
- targ->dv_state);
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-}
-
-static void
-ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo)
-{
- memset(cmd, 0, sizeof(struct scsi_cmnd));
- cmd->device = ahd->platform_data->dv_scsi_dev;
- cmd->scsi_done = ahd_linux_dv_complete;
-}
-
-/*
- * Synthesize an inquiry command. On the return trip, it'll be
- * sniffed and the device transfer settings set for us.
- */
-static void
-ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ,
- u_int request_length)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending INQ\n");
- }
-#endif
- if (targ->inq_data == NULL)
- targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN,
- M_DEVBUF, M_WAITOK);
- if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) {
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN,
- M_DEVBUF, M_WAITOK);
- }
-
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = INQUIRY;
- cmd->cmnd[4] = request_length;
- cmd->request_bufflen = request_length;
- if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC)
- cmd->request_buffer = targ->dv_buffer;
- else
- cmd->request_buffer = targ->inq_data;
- memset(cmd->request_buffer, 0, AHD_LINUX_DV_INQ_LEN);
-}
-
-static void
-ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending TUR\n");
- }
-#endif
- /* Do a TUR to clear out any non-fatal transitional state */
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_NONE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = TEST_UNIT_READY;
-}
-
-#define AHD_REBD_LEN 4
-
-static void
-ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending REBD\n");
- }
-#endif
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(AHD_REBD_LEN, M_DEVBUF, M_WAITOK);
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = READ_BUFFER;
- cmd->cmnd[1] = 0x0b;
- scsi_ulto3b(AHD_REBD_LEN, &cmd->cmnd[6]);
- cmd->request_bufflen = AHD_REBD_LEN;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer;
-}
-
-static void
-ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending WEB\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_TO_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = WRITE_BUFFER;
- cmd->cmnd[1] = 0x0a;
- scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
- cmd->request_bufflen = targ->dv_echo_size;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer;
-}
-
-static void
-ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending REB\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = READ_BUFFER;
- cmd->cmnd[1] = 0x0a;
- scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
- cmd->request_bufflen = targ->dv_echo_size;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer1;
-}
-
-static void
-ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ)
-{
- u_int le;
-
- le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending SU\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_NONE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = START_STOP_UNIT;
- cmd->cmnd[4] = le | SSS_START;
-}
-
-static int
-ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
- struct ahd_linux_target *targ;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_transinfo *goal;
- struct ahd_tmode_tstate *tstate;
- u_int width;
- u_int period;
- u_int offset;
- u_int ppr_options;
- u_int cur_speed;
- u_int wide_speed;
- u_int narrow_speed;
- u_int fallback_speed;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Trying to fallback\n");
- }
-#endif
- targ = ahd->platform_data->targets[devinfo->target_offset];
- tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
- devinfo->our_scsiid,
- devinfo->target, &tstate);
- goal = &tinfo->goal;
- width = goal->width;
- period = goal->period;
- offset = goal->offset;
- ppr_options = goal->ppr_options;
- if (offset == 0)
- period = AHD_ASYNC_XFER_PERIOD;
- if (targ->dv_next_narrow_period == 0)
- targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
- if (targ->dv_next_wide_period == 0)
- targ->dv_next_wide_period = period;
- if (targ->dv_max_width == 0)
- targ->dv_max_width = width;
- if (targ->dv_max_ppr_options == 0)
- targ->dv_max_ppr_options = ppr_options;
- if (targ->dv_last_ppr_options == 0)
- targ->dv_last_ppr_options = ppr_options;
-
- cur_speed = aic_calc_speed(width, period, offset, AHD_SYNCRATE_MIN);
- wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
- targ->dv_next_wide_period,
- MAX_OFFSET, AHD_SYNCRATE_MIN);
- narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
- targ->dv_next_narrow_period,
- MAX_OFFSET, AHD_SYNCRATE_MIN);
- fallback_speed = aic_calc_speed(width, period+1, offset,
- AHD_SYNCRATE_MIN);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
- "fallback_speed= %d\n", cur_speed, wide_speed,
- narrow_speed, fallback_speed);
- }
-#endif
-
- if (cur_speed > 160000) {
- /*
- * Paced/DT/IU_REQ only transfer speeds. All we
- * can do is fallback in terms of syncrate.
- */
- period++;
- } else if (cur_speed > 80000) {
- if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- /*
- * Try without IU_REQ as it may be confusing
- * an expander.
- */
- ppr_options &= ~MSG_EXT_PPR_IU_REQ;
- } else {
- /*
- * Paced/DT only transfer speeds. All we
- * can do is fallback in terms of syncrate.
- */
- period++;
- ppr_options = targ->dv_max_ppr_options;
- }
- } else if (cur_speed > 3300) {
-
/*
- * In this range we the following
- * options ordered from highest to
- * lowest desireability:
- *
- * o Wide/DT
- * o Wide/non-DT
- * o Narrow at a potentally higher sync rate.
- *
- * All modes are tested with and without IU_REQ
- * set since using IUs may confuse an expander.
+ * We allow the OS to queue 2 untagged transactions to
+ * us at any time even though we can only execute them
+ * serially on the controller/device. This should
+ * remove some latency.
*/
- if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-
- ppr_options &= ~MSG_EXT_PPR_IU_REQ;
- } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
- /*
- * Try going non-DT.
- */
- ppr_options = targ->dv_max_ppr_options;
- ppr_options &= ~MSG_EXT_PPR_DT_REQ;
- } else if (targ->dv_last_ppr_options != 0) {
- /*
- * Try without QAS or any other PPR options.
- * We may need a non-PPR message to work with
- * an expander. We look at the "last PPR options"
- * so we will perform this fallback even if the
- * target responded to our PPR negotiation with
- * no option bits set.
- */
- ppr_options = 0;
- } else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
- /*
- * If the next narrow speed is greater than
- * the next wide speed, fallback to narrow.
- * Otherwise fallback to the next DT/Wide setting.
- * The narrow async speed will always be smaller
- * than the wide async speed, so handle this case
- * specifically.
- */
- ppr_options = targ->dv_max_ppr_options;
- if (narrow_speed > fallback_speed
- || period >= AHD_ASYNC_XFER_PERIOD) {
- targ->dv_next_wide_period = period+1;
- width = MSG_EXT_WDTR_BUS_8_BIT;
- period = targ->dv_next_narrow_period;
- } else {
- period++;
- }
- } else if ((ahd->features & AHD_WIDE) != 0
- && targ->dv_max_width != 0
- && wide_speed >= fallback_speed
- && (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
- || period >= AHD_ASYNC_XFER_PERIOD)) {
-
- /*
- * We are narrow. Try falling back
- * to the next wide speed with
- * all supported ppr options set.
- */
- targ->dv_next_narrow_period = period+1;
- width = MSG_EXT_WDTR_BUS_16_BIT;
- period = targ->dv_next_wide_period;
- ppr_options = targ->dv_max_ppr_options;
- } else {
- /* Only narrow fallback is allowed. */
- period++;
- ppr_options = targ->dv_max_ppr_options;
- }
- } else {
- return (-1);
- }
- offset = MAX_OFFSET;
- ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_PACED);
- ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, FALSE);
- if (period == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
- if (width == MSG_EXT_WDTR_BUS_8_BIT)
- targ->dv_next_narrow_period = AHD_ASYNC_XFER_PERIOD;
- else
- targ->dv_next_wide_period = AHD_ASYNC_XFER_PERIOD;
- }
- ahd_set_syncrate(ahd, devinfo, period, offset,
- ppr_options, AHD_TRANS_GOAL, FALSE);
- targ->dv_last_ppr_options = ppr_options;
- return (0);
-}
-
-static void
-ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
-{
- struct ahd_softc *ahd;
- struct scb *scb;
- u_long flags;
-
- ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
- ahd_lock(ahd, &flags);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- printf("%s: Timeout while doing DV command %x.\n",
- ahd_name(ahd), cmd->cmnd[0]);
- ahd_dump_card_state(ahd);
- }
-#endif
-
- /*
- * Guard against "done race". No action is
- * required if we just completed.
- */
- if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
- ahd_unlock(ahd, &flags);
- return;
+ scsi_adjust_queue_depth(sdev,
+ /*NON-TAGGED*/0,
+ /*queue depth*/2);
+ break;
}
-
- /*
- * Command has not completed. Mark this
- * SCB as having failing status prior to
- * resetting the bus, so we get the correct
- * error code.
- */
- if ((scb->flags & SCB_SENSE) != 0)
- ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
- else
- ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);
-
- /*
- * Add a minimal bus settle delay for devices that are slow to
- * respond after bus resets.
- */
- ahd_freeze_simq(ahd);
- init_timer(&ahd->platform_data->reset_timer);
- ahd->platform_data->reset_timer.data = (u_long)ahd;
- ahd->platform_data->reset_timer.expires = jiffies + HZ / 2;
- ahd->platform_data->reset_timer.function =
- (ahd_linux_callback_t *)ahd_release_simq;
- add_timer(&ahd->platform_data->reset_timer);
- if (ahd_linux_next_device_to_run(ahd) != NULL)
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &flags);
-}
-
-static void
-ahd_linux_dv_complete(struct scsi_cmnd *cmd)
-{
- struct ahd_softc *ahd;
-
- ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
-
- /* Delete the DV timer before it goes off! */
- scsi_delete_timer(cmd);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s:%c:%d: Command completed, status= 0x%x\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->result);
-#endif
-
- /* Wake up the state machine */
- up(&ahd->platform_data->dv_cmd_sem);
}
-static void
-ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ)
+int
+ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
+ int lun, u_int tag, role_t role, uint32_t status)
{
- uint16_t b;
- u_int i;
- u_int j;
-
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
- if (targ->dv_buffer1 != NULL)
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
-
- i = 0;
-
- b = 0x0001;
- for (j = 0 ; i < targ->dv_echo_size; j++) {
- if (j < 32) {
- /*
- * 32bytes of sequential numbers.
- */
- targ->dv_buffer[i++] = j & 0xff;
- } else if (j < 48) {
- /*
- * 32bytes of repeating 0x0000, 0xffff.
- */
- targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00;
- } else if (j < 64) {
- /*
- * 32bytes of repeating 0x5555, 0xaaaa.
- */
- targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55;
- } else {
- /*
- * Remaining buffer is filled with a repeating
- * patter of:
- *
- * 0xffff
- * ~0x0001 << shifted once in each loop.
- */
- if (j & 0x02) {
- if (j & 0x01) {
- targ->dv_buffer[i++] = ~(b >> 8) & 0xff;
- b <<= 1;
- if (b == 0x0000)
- b = 0x0001;
- } else {
- targ->dv_buffer[i++] = (~b & 0xff);
- }
- } else {
- targ->dv_buffer[i++] = 0xff;
- }
- }
- }
+ return 0;
}
static u_int
@@ -3800,100 +1395,23 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
return (tags);
}
-static u_int
-ahd_linux_user_dv_setting(struct ahd_softc *ahd)
-{
- static int warned_user;
- int dv;
-
- if (ahd->unit >= NUM_ELEMENTS(aic79xx_dv_settings)) {
-
- if (warned_user == 0) {
- printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient dv settings instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_dv_settings array in"
-"aic79xx: the aic79xx_osm.c source file.\n");
- warned_user++;
- }
- dv = -1;
- } else {
-
- dv = aic79xx_dv_settings[ahd->unit];
- }
-
- if (dv < 0) {
- /*
- * Apply the default.
- */
- dv = 1;
- if (ahd->seep_config != 0)
- dv = (ahd->seep_config->bios_control & CFENABLEDV);
- }
- return (dv);
-}
-
-static void
-ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd)
-{
- static int warned_user;
- u_int rd_strm_mask;
- u_int target_id;
-
- /*
- * If we have specific read streaming info for this controller,
- * apply it. Otherwise use the defaults.
- */
- if (ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) {
-
- if (warned_user == 0) {
-
- printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient rd_strm instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_rd_strm_info array\n"
-"aic79xx: in the aic79xx_osm.c source file.\n");
- warned_user++;
- }
- rd_strm_mask = AIC79XX_CONFIGED_RD_STRM;
- } else {
-
- rd_strm_mask = aic79xx_rd_strm_info[ahd->unit];
- }
- for (target_id = 0; target_id < 16; target_id++) {
- struct ahd_devinfo devinfo;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
-
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- target_id, &tstate);
- ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
- CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
- tinfo->user.ppr_options &= ~MSG_EXT_PPR_RD_STRM;
- if ((rd_strm_mask & devinfo.target_mask) != 0)
- tinfo->user.ppr_options |= MSG_EXT_PPR_RD_STRM;
- }
-}
-
/*
* Determines the queue depth for a given device.
*/
static void
-ahd_linux_device_queue_depth(struct ahd_softc *ahd,
- struct ahd_linux_device *dev)
+ahd_linux_device_queue_depth(struct scsi_device *sdev)
{
struct ahd_devinfo devinfo;
u_int tags;
+ struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
ahd_compile_devinfo(&devinfo,
ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
tags = ahd_linux_user_tagdepth(ahd, &devinfo);
- if (tags != 0
- && dev->scsi_device != NULL
- && dev->scsi_device->tagged_supported != 0) {
+ if (tags != 0 && sdev->tagged_supported != 0) {
ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
ahd_print_devinfo(ahd, &devinfo);
@@ -3903,11 +1421,10 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd,
}
}
-static void
-ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
+static int
+ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ struct scsi_cmnd *cmd)
{
- struct ahd_cmd *acmd;
- struct scsi_cmnd *cmd;
struct scb *scb;
struct hardware_scb *hscb;
struct ahd_initiator_tinfo *tinfo;
@@ -3915,157 +1432,122 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
u_int col_idx;
uint16_t mask;
- if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0)
- panic("running device on run list");
-
- while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
- && dev->openings > 0 && dev->qfrozen == 0) {
-
- /*
- * Schedule us to run later. The only reason we are not
- * running is because the whole controller Q is frozen.
- */
- if (ahd->platform_data->qfrozen != 0
- && AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
- dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- return;
- }
-
- cmd = &acmd_scsi_cmd(acmd);
+ /*
+ * Get an scb to use.
+ */
+ tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
+ cmd->device->id, &tstate);
+ if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
+ || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
+ col_idx = AHD_NEVER_COL_IDX;
+ } else {
+ col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
+ cmd->device->lun);
+ }
+ if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
+ ahd->flags |= AHD_RESOURCE_SHORTAGE;
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
- /*
- * Get an scb to use.
- */
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- cmd->device->id, &tstate);
- if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
- || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- col_idx = AHD_NEVER_COL_IDX;
- } else {
- col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
- cmd->device->lun);
- }
- if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
- dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- ahd->flags |= AHD_RESOURCE_SHORTAGE;
- return;
- }
- TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
- scb->io_ctx = cmd;
- scb->platform_data->dev = dev;
- hscb = scb->hscb;
- cmd->host_scribble = (char *)scb;
+ scb->io_ctx = cmd;
+ scb->platform_data->dev = dev;
+ hscb = scb->hscb;
+ cmd->host_scribble = (char *)scb;
- /*
- * Fill out basics of the HSCB.
- */
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahd, cmd);
- hscb->lun = cmd->device->lun;
- scb->hscb->task_management = 0;
- mask = SCB_GET_TARGET_MASK(ahd, scb);
+ /*
+ * Fill out basics of the HSCB.
+ */
+ hscb->control = 0;
+ hscb->scsiid = BUILD_SCSIID(ahd, cmd);
+ hscb->lun = cmd->device->lun;
+ scb->hscb->task_management = 0;
+ mask = SCB_GET_TARGET_MASK(ahd, scb);
- if ((ahd->user_discenable & mask) != 0)
- hscb->control |= DISCENB;
+ if ((ahd->user_discenable & mask) != 0)
+ hscb->control |= DISCENB;
- if (AHD_DV_CMD(cmd) != 0)
- scb->flags |= SCB_SILENT;
+ if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
+ scb->flags |= SCB_PACKETIZED;
- if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
- scb->flags |= SCB_PACKETIZED;
+ if ((tstate->auto_negotiate & mask) != 0) {
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
+ }
- if ((tstate->auto_negotiate & mask) != 0) {
- scb->flags |= SCB_AUTO_NEGOTIATE;
- scb->hscb->control |= MK_MESSAGE;
- }
+ if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
+ int msg_bytes;
+ uint8_t tag_msgs[2];
- if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- int msg_bytes;
- uint8_t tag_msgs[2];
-
- msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
- if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
- hscb->control |= tag_msgs[0];
- if (tag_msgs[0] == MSG_ORDERED_TASK)
- dev->commands_since_idle_or_otag = 0;
- } else
-#endif
- if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
- && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
- hscb->control |= MSG_ORDERED_TASK;
+ msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
+ if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
+ hscb->control |= tag_msgs[0];
+ if (tag_msgs[0] == MSG_ORDERED_TASK)
dev->commands_since_idle_or_otag = 0;
- } else {
- hscb->control |= MSG_SIMPLE_TASK;
- }
+ } else
+ if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
+ && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
+ hscb->control |= MSG_ORDERED_TASK;
+ dev->commands_since_idle_or_otag = 0;
+ } else {
+ hscb->control |= MSG_SIMPLE_TASK;
}
+ }
- hscb->cdb_len = cmd->cmd_len;
- memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
-
- scb->sg_count = 0;
- ahd_set_residual(scb, 0);
- ahd_set_sense_residual(scb, 0);
- if (cmd->use_sg != 0) {
- void *sg;
- struct scatterlist *cur_seg;
- u_int nseg;
- int dir;
-
- cur_seg = (struct scatterlist *)cmd->request_buffer;
- dir = cmd->sc_data_direction;
- nseg = pci_map_sg(ahd->dev_softc, cur_seg,
- cmd->use_sg, dir);
- scb->platform_data->xfer_len = 0;
- for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
- dma_addr_t addr;
- bus_size_t len;
-
- addr = sg_dma_address(cur_seg);
- len = sg_dma_len(cur_seg);
- scb->platform_data->xfer_len += len;
- sg = ahd_sg_setup(ahd, scb, sg, addr, len,
- /*last*/nseg == 1);
- }
- } else if (cmd->request_bufflen != 0) {
- void *sg;
+ hscb->cdb_len = cmd->cmd_len;
+ memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
+
+ scb->platform_data->xfer_len = 0;
+ ahd_set_residual(scb, 0);
+ ahd_set_sense_residual(scb, 0);
+ scb->sg_count = 0;
+ if (cmd->use_sg != 0) {
+ void *sg;
+ struct scatterlist *cur_seg;
+ u_int nseg;
+ int dir;
+
+ cur_seg = (struct scatterlist *)cmd->request_buffer;
+ dir = cmd->sc_data_direction;
+ nseg = pci_map_sg(ahd->dev_softc, cur_seg,
+ cmd->use_sg, dir);
+ scb->platform_data->xfer_len = 0;
+ for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
dma_addr_t addr;
- int dir;
-
- sg = scb->sg_list;
- dir = cmd->sc_data_direction;
- addr = pci_map_single(ahd->dev_softc,
- cmd->request_buffer,
- cmd->request_bufflen, dir);
- scb->platform_data->xfer_len = cmd->request_bufflen;
- scb->platform_data->buf_busaddr = addr;
- sg = ahd_sg_setup(ahd, scb, sg, addr,
- cmd->request_bufflen, /*last*/TRUE);
- }
+ bus_size_t len;
- LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
- dev->openings--;
- dev->active++;
- dev->commands_issued++;
-
- /* Update the error counting bucket and dump if needed */
- if (dev->target->cmds_since_error) {
- dev->target->cmds_since_error++;
- if (dev->target->cmds_since_error >
- AHD_LINUX_ERR_THRESH)
- dev->target->cmds_since_error = 0;
+ addr = sg_dma_address(cur_seg);
+ len = sg_dma_len(cur_seg);
+ scb->platform_data->xfer_len += len;
+ sg = ahd_sg_setup(ahd, scb, sg, addr, len,
+ /*last*/nseg == 1);
}
+ } else if (cmd->request_bufflen != 0) {
+ void *sg;
+ dma_addr_t addr;
+ int dir;
- if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
- dev->commands_since_idle_or_otag++;
- scb->flags |= SCB_ACTIVE;
- ahd_queue_scb(ahd, scb);
+ sg = scb->sg_list;
+ dir = cmd->sc_data_direction;
+ addr = pci_map_single(ahd->dev_softc,
+ cmd->request_buffer,
+ cmd->request_bufflen, dir);
+ scb->platform_data->xfer_len = cmd->request_bufflen;
+ scb->platform_data->buf_busaddr = addr;
+ sg = ahd_sg_setup(ahd, scb, sg, addr,
+ cmd->request_bufflen, /*last*/TRUE);
}
+
+ LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
+ dev->openings--;
+ dev->active++;
+ dev->commands_issued++;
+
+ if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
+ dev->commands_since_idle_or_otag++;
+ scb->flags |= SCB_ACTIVE;
+ ahd_queue_scb(ahd, scb);
+
+ return 0;
}
/*
@@ -4081,9 +1563,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
ahd = (struct ahd_softc *) dev_id;
ahd_lock(ahd, &flags);
ours = ahd_intr(ahd);
- if (ahd_linux_next_device_to_run(ahd) != NULL)
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &flags);
return IRQ_RETVAL(ours);
}
@@ -4092,111 +1571,6 @@ void
ahd_platform_flushwork(struct ahd_softc *ahd)
{
- while (ahd_linux_run_complete_queue(ahd) != NULL)
- ;
-}
-
-static struct ahd_linux_target*
-ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
-{
- struct ahd_linux_target *targ;
-
- targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
- if (targ == NULL)
- return (NULL);
- memset(targ, 0, sizeof(*targ));
- targ->channel = channel;
- targ->target = target;
- targ->ahd = ahd;
- targ->flags = AHD_DV_REQUIRED;
- ahd->platform_data->targets[target] = targ;
- return (targ);
-}
-
-static void
-ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ)
-{
- struct ahd_devinfo devinfo;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
- u_int our_id;
- u_int target_offset;
- char channel;
-
- /*
- * Force a negotiation to async/narrow on any
- * future command to this device unless a bus
- * reset occurs between now and that command.
- */
- channel = 'A' + targ->channel;
- our_id = ahd->our_id;
- target_offset = targ->target;
- tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
- targ->target, &tstate);
- ahd_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
- channel, ROLE_INITIATOR);
- ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS);
- ahd->platform_data->targets[target_offset] = NULL;
- if (targ->inq_data != NULL)
- free(targ->inq_data, M_DEVBUF);
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- if (targ->dv_buffer1 != NULL)
- free(targ->dv_buffer1, M_DEVBUF);
- free(targ, M_DEVBUF);
-}
-
-static struct ahd_linux_device*
-ahd_linux_alloc_device(struct ahd_softc *ahd,
- struct ahd_linux_target *targ, u_int lun)
-{
- struct ahd_linux_device *dev;
-
- dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
- if (dev == NULL)
- return (NULL);
- memset(dev, 0, sizeof(*dev));
- init_timer(&dev->timer);
- TAILQ_INIT(&dev->busyq);
- dev->flags = AHD_DEV_UNCONFIGURED;
- dev->lun = lun;
- dev->target = targ;
-
- /*
- * We start out life using untagged
- * transactions of which we allow one.
- */
- dev->openings = 1;
-
- /*
- * Set maxtags to 0. This will be changed if we
- * later determine that we are dealing with
- * a tagged queuing capable device.
- */
- dev->maxtags = 0;
-
- targ->refcount++;
- targ->devices[lun] = dev;
- return (dev);
-}
-
-static void
-ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev)
-{
- struct ahd_linux_target *targ;
-
- del_timer(&dev->timer);
- targ = dev->target;
- targ->devices[dev->lun] = NULL;
- free(dev, M_DEVBUF);
- targ->refcount--;
- if (targ->refcount == 0
- && (targ->flags & AHD_DV_REQUIRED) == 0)
- ahd_linux_free_target(ahd, targ);
}
void
@@ -4207,10 +1581,14 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
case AC_TRANSFER_NEG:
{
char buf[80];
+ struct scsi_target *starget;
struct ahd_linux_target *targ;
struct info_str info;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
+ unsigned int target_ppr_options;
+
+ BUG_ON(target == CAM_TARGET_WILDCARD);
info.buffer = buf;
info.length = sizeof(buf);
@@ -4234,58 +1612,47 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
* Don't bother reporting results that
* are identical to those last reported.
*/
- targ = ahd->platform_data->targets[target];
- if (targ == NULL)
+ starget = ahd->platform_data->starget[target];
+ if (starget == NULL)
break;
- if (tinfo->curr.period == targ->last_tinfo.period
- && tinfo->curr.width == targ->last_tinfo.width
- && tinfo->curr.offset == targ->last_tinfo.offset
- && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
+ targ = scsi_transport_target_data(starget);
+
+ target_ppr_options =
+ (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
+ + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
+ + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0)
+ + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
+ + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
+ + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
+ + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
+ + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
+
+ if (tinfo->curr.period == spi_period(starget)
+ && tinfo->curr.width == spi_width(starget)
+ && tinfo->curr.offset == spi_offset(starget)
+ && tinfo->curr.ppr_options == target_ppr_options)
if (bootverbose == 0)
break;
- targ->last_tinfo.period = tinfo->curr.period;
- targ->last_tinfo.width = tinfo->curr.width;
- targ->last_tinfo.offset = tinfo->curr.offset;
- targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
-
- printf("(%s:%c:", ahd_name(ahd), channel);
- if (target == CAM_TARGET_WILDCARD)
- printf("*): ");
- else
- printf("%d): ", target);
- ahd_format_transinfo(&info, &tinfo->curr);
- if (info.pos < info.length)
- *info.buffer = '\0';
- else
- buf[info.length - 1] = '\0';
- printf("%s", buf);
+ spi_period(starget) = tinfo->curr.period;
+ spi_width(starget) = tinfo->curr.width;
+ spi_offset(starget) = tinfo->curr.offset;
+ spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+ spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+ spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
+ spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
+ spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
+ spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0;
+ spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
+ spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
+ spi_display_xfer_agreement(starget);
break;
}
case AC_SENT_BDR:
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahd->platform_data->host,
channel - 'A', target);
-#else
- Scsi_Device *scsi_dev;
-
- /*
- * Find the SCSI device associated with this
- * request and indicate that a UA is expected.
- */
- for (scsi_dev = ahd->platform_data->host->host_queue;
- scsi_dev != NULL; scsi_dev = scsi_dev->next) {
- if (channel - 'A' == scsi_dev->channel
- && target == scsi_dev->id
- && (lun == CAM_LUN_WILDCARD
- || lun == scsi_dev->lun)) {
- scsi_dev->was_reset = 1;
- scsi_dev->expecting_cc_ua = 1;
- }
- }
-#endif
break;
}
case AC_BUS_RESET:
@@ -4305,7 +1672,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
void
ahd_done(struct ahd_softc *ahd, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
struct ahd_linux_device *dev;
if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -4373,19 +1740,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
ahd_set_transaction_status(scb, CAM_REQ_CMP);
}
} else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
- ahd_linux_handle_scsi_status(ahd, dev, scb);
- } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- if (AHD_DV_CMD(cmd) == FALSE)
- dev->target->flags &= ~AHD_DV_REQUIRED;
+ ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
}
- /*
- * Start DV for devices that require it assuming the first command
- * sent does not result in a selection timeout.
- */
- if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT
- && (dev->target->flags & AHD_DV_REQUIRED) != 0)
- ahd_linux_start_dv(ahd);
if (dev->openings == 1
&& ahd_get_transaction_status(scb) == CAM_REQ_CMP
@@ -4406,47 +1762,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if (dev->active == 0)
dev->commands_since_idle_or_otag = 0;
- if (TAILQ_EMPTY(&dev->busyq)) {
- if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
- && dev->active == 0
- && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
- ahd_linux_free_device(ahd, dev);
- } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- }
-
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
printf("Recovery SCB completes\n");
if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
|| ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
- scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+ if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+ ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
up(&ahd->platform_data->eh_sem);
}
}
ahd_free_scb(ahd, scb);
ahd_linux_queue_cmd_complete(ahd, cmd);
-
- if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0
- && LIST_FIRST(&ahd->pending_scbs) == NULL) {
- ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY;
- up(&ahd->platform_data->dv_sem);
- }
}
static void
ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
- struct ahd_linux_device *dev, struct scb *scb)
+ struct scsi_device *sdev, struct scb *scb)
{
struct ahd_devinfo devinfo;
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
ahd_compile_devinfo(&devinfo,
ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
/*
@@ -4465,7 +1806,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
case SCSI_STATUS_CHECK_COND:
case SCSI_STATUS_CMD_TERMINATED:
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
/*
* Copy sense information to the OS's cmd
@@ -4518,7 +1859,6 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
break;
}
case SCSI_STATUS_QUEUE_FULL:
- {
/*
* By the time the core driver has returned this
* command, all other commands that were queued
@@ -4579,98 +1919,23 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
(dev->flags & AHD_DEV_Q_BASIC)
? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
- /* FALLTHROUGH */
- }
- case SCSI_STATUS_BUSY:
- /*
- * Set a short timer to defer sending commands for
- * a bit since Linux will not delay in this case.
- */
- if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) {
- printf("%s:%c:%d: Device Timer still active during "
- "busy processing\n", ahd_name(ahd),
- dev->target->channel, dev->target->target);
- break;
- }
- dev->flags |= AHD_DEV_TIMER_ACTIVE;
- dev->qfrozen++;
- init_timer(&dev->timer);
- dev->timer.data = (u_long)dev;
- dev->timer.expires = jiffies + (HZ/2);
- dev->timer.function = ahd_linux_dev_timed_unfreeze;
- add_timer(&dev->timer);
- break;
}
}
static void
-ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd)
+ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
{
/*
- * Typically, the complete queue has very few entries
- * queued to it before the queue is emptied by
- * ahd_linux_run_complete_queue, so sorting the entries
- * by generation number should be inexpensive.
- * We perform the sort so that commands that complete
- * with an error are retuned in the order origionally
- * queued to the controller so that any subsequent retries
- * are performed in order. The underlying ahd routines do
- * not guarantee the order that aborted commands will be
- * returned to us.
- */
- struct ahd_completeq *completeq;
- struct ahd_cmd *list_cmd;
- struct ahd_cmd *acmd;
-
- /*
* Map CAM error codes into Linux Error codes. We
* avoid the conversion so that the DV code has the
* full error information available when making
* state change decisions.
*/
- if (AHD_DV_CMD(cmd) == FALSE) {
+ {
uint32_t status;
u_int new_status;
status = ahd_cmd_get_transaction_status(cmd);
- if (status != CAM_REQ_CMP) {
- struct ahd_linux_device *dev;
- struct ahd_devinfo devinfo;
- cam_status cam_status;
- uint32_t action;
- u_int scsi_status;
-
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id,
- cmd->device->lun,
- /*alloc*/FALSE);
-
- if (dev == NULL)
- goto no_fallback;
-
- ahd_compile_devinfo(&devinfo,
- ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A':'B',
- ROLE_INITIATOR);
-
- scsi_status = ahd_cmd_get_scsi_status(cmd);
- cam_status = ahd_cmd_get_transaction_status(cmd);
- action = aic_error_action(cmd, dev->target->inq_data,
- cam_status, scsi_status);
- if ((action & SSQ_FALLBACK) != 0) {
-
- /* Update stats */
- dev->target->errors_detected++;
- if (dev->target->cmds_since_error == 0)
- dev->target->cmds_since_error++;
- else {
- dev->target->cmds_since_error = 0;
- ahd_linux_fallback(ahd, &devinfo);
- }
- }
- }
-no_fallback:
switch (status) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
@@ -4715,26 +1980,7 @@ no_fallback:
new_status = DID_ERROR;
break;
case CAM_REQUEUE_REQ:
- /*
- * If we want the request requeued, make sure there
- * are sufficent retries. In the old scsi error code,
- * we used to be able to specify a result code that
- * bypassed the retry count. Now we must use this
- * hack. We also "fake" a check condition with
- * a sense code of ABORTED COMMAND. This seems to
- * evoke a retry even if this command is being sent
- * via the eh thread. Ick! Ick! Ick!
- */
- if (cmd->retries > 0)
- cmd->retries--;
- new_status = DID_OK;
- ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
- cmd->result |= (DRIVER_SENSE << 24);
- memset(cmd->sense_buffer, 0,
- sizeof(cmd->sense_buffer));
- cmd->sense_buffer[0] = SSD_ERRCODE_VALID
- | SSD_CURRENT_ERROR;
- cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
+ new_status = DID_REQUEUE;
break;
default:
/* We should never get here */
@@ -4745,116 +1991,23 @@ no_fallback:
ahd_cmd_set_transaction_status(cmd, new_status);
}
- completeq = &ahd->platform_data->completeq;
- list_cmd = TAILQ_FIRST(completeq);
- acmd = (struct ahd_cmd *)cmd;
- while (list_cmd != NULL
- && acmd_scsi_cmd(list_cmd).serial_number
- < acmd_scsi_cmd(acmd).serial_number)
- list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
- if (list_cmd != NULL)
- TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
- else
- TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
+ cmd->scsi_done(cmd);
}
static void
-ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+ahd_linux_sem_timeout(u_long arg)
{
- struct scsi_inquiry_data *sid;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_transinfo *user;
- struct ahd_transinfo *goal;
- struct ahd_transinfo *curr;
- struct ahd_tmode_tstate *tstate;
- struct ahd_linux_device *dev;
- u_int width;
- u_int period;
- u_int offset;
- u_int ppr_options;
- u_int trans_version;
- u_int prot_version;
-
- /*
- * Determine if this lun actually exists. If so,
- * hold on to its corresponding device structure.
- * If not, make sure we release the device and
- * don't bother processing the rest of this inquiry
- * command.
- */
- dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
- devinfo->target, devinfo->lun,
- /*alloc*/TRUE);
-
- sid = (struct scsi_inquiry_data *)dev->target->inq_data;
- if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
-
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- } else {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- return;
- }
+ struct ahd_softc *ahd;
+ u_long s;
- /*
- * Update our notion of this device's transfer
- * negotiation capabilities.
- */
- tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
- devinfo->our_scsiid,
- devinfo->target, &tstate);
- user = &tinfo->user;
- goal = &tinfo->goal;
- curr = &tinfo->curr;
- width = user->width;
- period = user->period;
- offset = user->offset;
- ppr_options = user->ppr_options;
- trans_version = user->transport_version;
- prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid));
+ ahd = (struct ahd_softc *)arg;
- /*
- * Only attempt SPI3/4 once we've verified that
- * the device claims to support SPI3/4 features.
- */
- if (prot_version < SCSI_REV_2)
- trans_version = SID_ANSI_REV(sid);
- else
- trans_version = SCSI_REV_2;
-
- if ((sid->flags & SID_WBus16) == 0)
- width = MSG_EXT_WDTR_BUS_8_BIT;
- if ((sid->flags & SID_Sync) == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
- }
- if ((sid->spi3data & SID_SPI_QAS) == 0)
- ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
- if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
- ppr_options &= MSG_EXT_PPR_QAS_REQ;
- if ((sid->spi3data & SID_SPI_IUS) == 0)
- ppr_options &= (MSG_EXT_PPR_DT_REQ
- | MSG_EXT_PPR_QAS_REQ);
-
- if (prot_version > SCSI_REV_2
- && ppr_options != 0)
- trans_version = user->transport_version;
-
- ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN);
- ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
- ahd_validate_offset(ahd, /*tinfo limit*/NULL, period,
- &offset, width, ROLE_UNKNOWN);
- if (offset == 0 || period == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
+ ahd_lock(ahd, &s);
+ if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+ ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+ up(&ahd->platform_data->eh_sem);
}
- /* Apply our filtered user settings. */
- curr->transport_version = trans_version;
- curr->protocol_version = prot_version;
- ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_syncrate(ahd, devinfo, period, offset, ppr_options,
- AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_unlock(ahd, &s);
}
void
@@ -4882,12 +2035,6 @@ ahd_release_simq(struct ahd_softc *ahd)
if (ahd->platform_data->qfrozen == 0) {
unblock_reqs = 1;
}
- if (AHD_DV_SIMQ_FROZEN(ahd)
- && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) {
- ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE;
- up(&ahd->platform_data->dv_sem);
- }
- ahd_schedule_runq(ahd);
ahd_unlock(ahd, &s);
/*
* There is still a race here. The mid-layer
@@ -4899,118 +2046,743 @@ ahd_release_simq(struct ahd_softc *ahd)
scsi_unblock_requests(ahd->platform_data->host);
}
-static void
-ahd_linux_sem_timeout(u_long arg)
+static int
+ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
{
- struct scb *scb;
- struct ahd_softc *ahd;
- u_long s;
+ struct ahd_softc *ahd;
+ struct ahd_linux_device *dev;
+ struct scb *pending_scb;
+ u_int saved_scbptr;
+ u_int active_scbptr;
+ u_int last_phase;
+ u_int saved_scsiid;
+ u_int cdb_byte;
+ int retval;
+ int was_paused;
+ int paused;
+ int wait;
+ int disconnected;
+ ahd_mode_state saved_modes;
- scb = (struct scb *)arg;
- ahd = scb->ahd_softc;
- ahd_lock(ahd, &s);
- if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
- scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
- up(&ahd->platform_data->eh_sem);
+ pending_scb = NULL;
+ paused = FALSE;
+ wait = FALSE;
+ ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
+
+ printf("%s:%d:%d:%d: Attempting to queue a%s message:",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun,
+ flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
+
+ printf("CDB:");
+ for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
+ printf(" 0x%x", cmd->cmnd[cdb_byte]);
+ printf("\n");
+
+ spin_lock_irq(&ahd->platform_data->spin_lock);
+
+ /*
+ * First determine if we currently own this command.
+ * Start by searching the device queue. If not found
+ * there, check the pending_scb list. If not found
+ * at all, and the system wanted us to just abort the
+ * command, return success.
+ */
+ dev = scsi_transport_device_data(cmd->device);
+
+ if (dev == NULL) {
+ /*
+ * No target device for this command exists,
+ * so we must not still own the command.
+ */
+ printf("%s:%d:%d:%d: Is not an active device\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ retval = SUCCESS;
+ goto no_cmd;
}
- ahd_unlock(ahd, &s);
+
+ /*
+ * See if we can find a matching cmd in the pending list.
+ */
+ LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+ if (pending_scb->io_ctx == cmd)
+ break;
+ }
+
+ if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
+
+ /* Any SCB for this device will do for a target reset */
+ LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+ if (ahd_match_scb(ahd, pending_scb, cmd->device->id,
+ cmd->device->channel + 'A',
+ CAM_LUN_WILDCARD,
+ SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+ break;
+ }
+ }
+
+ if (pending_scb == NULL) {
+ printf("%s:%d:%d:%d: Command not found\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ goto no_cmd;
+ }
+
+ if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
+ /*
+ * We can't queue two recovery actions using the same SCB
+ */
+ retval = FAILED;
+ goto done;
+ }
+
+ /*
+ * Ensure that the card doesn't do anything
+ * behind our back. Also make sure that we
+ * didn't "just" miss an interrupt that would
+ * affect this cmd.
+ */
+ was_paused = ahd_is_paused(ahd);
+ ahd_pause_and_flushwork(ahd);
+ paused = TRUE;
+
+ if ((pending_scb->flags & SCB_ACTIVE) == 0) {
+ printf("%s:%d:%d:%d: Command already completed\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ goto no_cmd;
+ }
+
+ printf("%s: At time of recovery, card was %spaused\n",
+ ahd_name(ahd), was_paused ? "" : "not ");
+ ahd_dump_card_state(ahd);
+
+ disconnected = TRUE;
+ if (flag == SCB_ABORT) {
+ if (ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A',
+ cmd->device->lun,
+ pending_scb->hscb->tag,
+ ROLE_INITIATOR, CAM_REQ_ABORTED,
+ SEARCH_COMPLETE) > 0) {
+ printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ retval = SUCCESS;
+ goto done;
+ }
+ } else if (ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A',
+ cmd->device->lun, pending_scb->hscb->tag,
+ ROLE_INITIATOR, /*status*/0,
+ SEARCH_COUNT) > 0) {
+ disconnected = FALSE;
+ }
+
+ saved_modes = ahd_save_modes(ahd);
+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+ last_phase = ahd_inb(ahd, LASTPHASE);
+ saved_scbptr = ahd_get_scbptr(ahd);
+ active_scbptr = saved_scbptr;
+ if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
+ struct scb *bus_scb;
+
+ bus_scb = ahd_lookup_scb(ahd, active_scbptr);
+ if (bus_scb == pending_scb)
+ disconnected = FALSE;
+ else if (flag != SCB_ABORT
+ && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid
+ && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))
+ disconnected = FALSE;
+ }
+
+ /*
+ * At this point, pending_scb is the scb associated with the
+ * passed in command. That command is currently active on the
+ * bus or is in the disconnected state.
+ */
+ saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
+ if (last_phase != P_BUSFREE
+ && (SCB_GET_TAG(pending_scb) == active_scbptr
+ || (flag == SCB_DEVICE_RESET
+ && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) {
+
+ /*
+ * We're active on the bus, so assert ATN
+ * and hope that the target responds.
+ */
+ pending_scb = ahd_lookup_scb(ahd, active_scbptr);
+ pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+ ahd_outb(ahd, MSG_OUT, HOST_MSG);
+ ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
+ printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ wait = TRUE;
+ } else if (disconnected) {
+
+ /*
+ * Actually re-queue this SCB in an attempt
+ * to select the device before it reconnects.
+ */
+ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
+ ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
+ pending_scb->hscb->cdb_len = 0;
+ pending_scb->hscb->task_attribute = 0;
+ pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
+
+ if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
+ /*
+ * Mark the SCB has having an outstanding
+ * task management function. Should the command
+ * complete normally before the task management
+ * function can be sent, the host will be notified
+ * to abort our requeued SCB.
+ */
+ ahd_outb(ahd, SCB_TASK_MANAGEMENT,
+ pending_scb->hscb->task_management);
+ } else {
+ /*
+ * If non-packetized, set the MK_MESSAGE control
+ * bit indicating that we desire to send a message.
+ * We also set the disconnected flag since there is
+ * no guarantee that our SCB control byte matches
+ * the version on the card. We don't want the
+ * sequencer to abort the command thinking an
+ * unsolicited reselection occurred.
+ */
+ pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+
+ /*
+ * The sequencer will never re-reference the
+ * in-core SCB. To make sure we are notified
+ * during reslection, set the MK_MESSAGE flag in
+ * the card's copy of the SCB.
+ */
+ ahd_outb(ahd, SCB_CONTROL,
+ ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
+ }
+
+ /*
+ * Clear out any entries in the QINFIFO first
+ * so we are the next SCB for this target
+ * to run.
+ */
+ ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A', cmd->device->lun,
+ SCB_LIST_NULL, ROLE_INITIATOR,
+ CAM_REQUEUE_REQ, SEARCH_COMPLETE);
+ ahd_qinfifo_requeue_tail(ahd, pending_scb);
+ ahd_set_scbptr(ahd, saved_scbptr);
+ ahd_print_path(ahd, pending_scb);
+ printf("Device is disconnected, re-queuing SCB\n");
+ wait = TRUE;
+ } else {
+ printf("%s:%d:%d:%d: Unable to deliver message\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ retval = FAILED;
+ goto done;
+ }
+
+no_cmd:
+ /*
+ * Our assumption is that if we don't have the command, no
+ * recovery action was required, so we return success. Again,
+ * the semantics of the mid-layer recovery engine are not
+ * well defined, so this may change in time.
+ */
+ retval = SUCCESS;
+done:
+ if (paused)
+ ahd_unpause(ahd);
+ if (wait) {
+ struct timer_list timer;
+ int ret;
+
+ ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;
+ spin_unlock_irq(&ahd->platform_data->spin_lock);
+ init_timer(&timer);
+ timer.data = (u_long)ahd;
+ timer.expires = jiffies + (5 * HZ);
+ timer.function = ahd_linux_sem_timeout;
+ add_timer(&timer);
+ printf("Recovery code sleeping\n");
+ down(&ahd->platform_data->eh_sem);
+ printf("Recovery code awake\n");
+ ret = del_timer_sync(&timer);
+ if (ret == 0) {
+ printf("Timer Expired\n");
+ retval = FAILED;
+ }
+ spin_lock_irq(&ahd->platform_data->spin_lock);
+ }
+ spin_unlock_irq(&ahd->platform_data->spin_lock);
+ return (retval);
}
-static void
-ahd_linux_dev_timed_unfreeze(u_long arg)
+static void ahd_linux_set_width(struct scsi_target *starget, int width)
{
- struct ahd_linux_device *dev;
- struct ahd_softc *ahd;
- u_long s;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_devinfo devinfo;
+ unsigned long flags;
- dev = (struct ahd_linux_device *)arg;
- ahd = dev->target->ahd;
- ahd_lock(ahd, &s);
- dev->flags &= ~AHD_DEV_TIMER_ACTIVE;
- if (dev->qfrozen > 0)
- dev->qfrozen--;
- if (dev->qfrozen == 0
- && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
- ahd_linux_run_device_queue(ahd, dev);
- if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
- && dev->active == 0)
- ahd_linux_free_device(ahd, dev);
- ahd_unlock(ahd, &s);
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_lock(ahd, &flags);
+ ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-void
-ahd_platform_dump_card_state(struct ahd_softc *ahd)
+static void ahd_linux_set_period(struct scsi_target *starget, int period)
{
- struct ahd_linux_device *dev;
- int target;
- int maxtarget;
- int lun;
- int i;
-
- maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7;
- for (target = 0; target <=maxtarget; target++) {
-
- for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
- struct ahd_cmd *acmd;
-
- dev = ahd_linux_get_device(ahd, 0, target,
- lun, /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- printf("DevQ(%d:%d:%d): ", 0, target, lun);
- i = 0;
- TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) {
- if (i++ > AHD_SCB_MAX)
- break;
- }
- printf("%d waiting\n", i);
- }
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options;
+ unsigned int dt;
+ unsigned long flags;
+ unsigned long offset = tinfo->goal.offset;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: set period to %d\n", ahd_name(ahd), period);
+#endif
+ if (offset == 0)
+ offset = MAX_OFFSET;
+
+ if (period < 8)
+ period = 8;
+ if (period < 10) {
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (period == 8)
+ ppr_options |= MSG_EXT_PPR_IU_REQ;
}
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+
+ /* all PPR requests apart from QAS require wide transfers */
+ if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
+ if (spi_width(starget) == 0)
+ ppr_options &= MSG_EXT_PPR_QAS_REQ;
+ }
+
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-static int __init
-ahd_linux_init(void)
+static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- return ahd_linux_detect(&aic79xx_driver_template);
-#else
- scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template);
- if (aic79xx_driver_template.present == 0) {
- scsi_unregister_module(MODULE_SCSI_HA,
- &aic79xx_driver_template);
- return (-ENODEV);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = 0;
+ unsigned int period = 0;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: set offset to %d\n", ahd_name(ahd), offset);
+#endif
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ if (offset != 0) {
+ period = tinfo->goal.period;
+ ppr_options = tinfo->goal.ppr_options;
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
}
- return (0);
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
+ AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_DT_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int width = tinfo->goal.width;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s DT\n", ahd_name(ahd),
+ dt ? "enabling" : "disabling");
+#endif
+ if (dt) {
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (!width)
+ ahd_linux_set_width(starget, 1);
+ } else {
+ if (period <= 9)
+ period = 10; /* If resetting DT, period must be >= 25ns */
+ /* IU is invalid without DT set */
+ ppr_options &= ~MSG_EXT_PPR_IU_REQ;
+ }
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_QAS_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s QAS\n", ahd_name(ahd),
+ qas ? "enabling" : "disabling");
+#endif
+
+ if (qas) {
+ ppr_options |= MSG_EXT_PPR_QAS_REQ;
+ }
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_IU_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s IU\n", ahd_name(ahd),
+ iu ? "enabling" : "disabling");
#endif
+
+ if (iu) {
+ ppr_options |= MSG_EXT_PPR_IU_REQ;
+ ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */
+ }
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-static void __exit
-ahd_linux_exit(void)
+static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
{
- struct ahd_softc *ahd;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_RD_STRM;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
- /*
- * Shutdown DV threads before going into the SCSI mid-layer.
- * This avoids situations where the mid-layer locks the entire
- * kernel so that waiting for our DV threads to exit leads
- * to deadlock.
- */
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Read Streaming\n", ahd_name(ahd),
+ rdstrm ? "enabling" : "disabling");
+#endif
+
+ if (rdstrm)
+ ppr_options |= MSG_EXT_PPR_RD_STRM;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
- ahd_linux_kill_dv_thread(ahd);
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_WR_FLOW;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Write Flow Control\n", ahd_name(ahd),
+ wrflow ? "enabling" : "disabling");
+#endif
+
+ if (wrflow)
+ ppr_options |= MSG_EXT_PPR_WR_FLOW;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_RTI;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+ if ((ahd->features & AHD_RTI) == 0) {
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: RTI not available\n", ahd_name(ahd));
+#endif
+ return;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s RTI\n", ahd_name(ahd),
+ rti ? "enabling" : "disabling");
+#endif
+
+ if (rti)
+ ppr_options |= MSG_EXT_PPR_RTI;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_PCOMP_EN;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Precompensation\n", ahd_name(ahd),
+ pcomp ? "Enable" : "Disable");
+#endif
+
+ if (pcomp)
+ ppr_options |= MSG_EXT_PPR_PCOMP_EN;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_HOLD_MCS;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+ if (hold)
+ ppr_options |= MSG_EXT_PPR_HOLD_MCS;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+
+
+static struct spi_function_template ahd_linux_transport_functions = {
+ .set_offset = ahd_linux_set_offset,
+ .show_offset = 1,
+ .set_period = ahd_linux_set_period,
+ .show_period = 1,
+ .set_width = ahd_linux_set_width,
+ .show_width = 1,
+ .set_dt = ahd_linux_set_dt,
+ .show_dt = 1,
+ .set_iu = ahd_linux_set_iu,
+ .show_iu = 1,
+ .set_qas = ahd_linux_set_qas,
+ .show_qas = 1,
+ .set_rd_strm = ahd_linux_set_rd_strm,
+ .show_rd_strm = 1,
+ .set_wr_flow = ahd_linux_set_wr_flow,
+ .show_wr_flow = 1,
+ .set_rti = ahd_linux_set_rti,
+ .show_rti = 1,
+ .set_pcomp_en = ahd_linux_set_pcomp_en,
+ .show_pcomp_en = 1,
+ .set_hold_mcs = ahd_linux_set_hold_mcs,
+ .show_hold_mcs = 1,
+};
+
+static int __init
+ahd_linux_init(void)
+{
+ int error = 0;
+
/*
- * In 2.4 we have to unregister from the PCI core _after_
- * unregistering from the scsi midlayer to avoid dangling
- * references.
+ * If we've been passed any parameters, process them now.
*/
- scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
-#endif
+ if (aic79xx)
+ aic79xx_setup(aic79xx);
+
+ ahd_linux_transport_template =
+ spi_attach_transport(&ahd_linux_transport_functions);
+ if (!ahd_linux_transport_template)
+ return -ENODEV;
+
+ scsi_transport_reserve_target(ahd_linux_transport_template,
+ sizeof(struct ahd_linux_target));
+ scsi_transport_reserve_device(ahd_linux_transport_template,
+ sizeof(struct ahd_linux_device));
+
+ error = ahd_linux_pci_init();
+ if (error)
+ spi_release_transport(ahd_linux_transport_template);
+ return error;
+}
+
+static void __exit
+ahd_linux_exit(void)
+{
ahd_linux_pci_exit();
+ spi_release_transport(ahd_linux_transport_template);
}
module_init(ahd_linux_init);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 7823e52e99ab..052c6619accc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -42,6 +42,7 @@
#ifndef _AIC79XX_LINUX_H_
#define _AIC79XX_LINUX_H_
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -49,18 +50,23 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/io.h>
-#include <linux/interrupt.h> /* For tasklet support. */
-#include <linux/config.h>
-#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
/* Core SCSI definitions */
#define AIC_LIB_PREFIX ahd
-#include "scsi.h"
-#include <scsi/scsi_host.h>
/* Name space conflict with BSD queue macros */
#ifdef LIST_HEAD
@@ -95,7 +101,7 @@
/************************* Forward Declarations *******************************/
struct ahd_softc;
typedef struct pci_dev *ahd_dev_softc_t;
-typedef Scsi_Cmnd *ahd_io_ctx_t;
+typedef struct scsi_cmnd *ahd_io_ctx_t;
/******************************* Byte Order ***********************************/
#define ahd_htobe16(x) cpu_to_be16(x)
@@ -114,8 +120,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
/************************* Configuration Data *********************************/
extern uint32_t aic79xx_allow_memio;
-extern int aic79xx_detect_complete;
-extern Scsi_Host_Template aic79xx_driver_template;
+extern struct scsi_host_template aic79xx_driver_template;
/***************************** Bus Space/DMA **********************************/
@@ -145,11 +150,7 @@ struct ahd_linux_dma_tag
};
typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
-struct ahd_linux_dmamap
-{
- dma_addr_t bus_addr;
-};
-typedef struct ahd_linux_dmamap* bus_dmamap_t;
+typedef dma_addr_t bus_dmamap_t;
typedef int bus_dma_filter_t(void*, dma_addr_t);
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t;
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);
-static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
+static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
ahd_callback_t *func, void *arg);
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
static __inline void
-ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
+ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
{
struct ahd_softc *ahd;
@@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
-#define AHD_SCSI_HAS_HOST_LOCK 1
-#else
-#define AHD_SCSI_HAS_HOST_LOCK 0
-#endif
-
#define AIC79XX_DRIVER_VERSION "1.3.11"
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros. The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahd_cmd_internal {
- /* Area owned by the Linux scsi layer. */
- uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
- union {
- STAILQ_ENTRY(ahd_cmd) ste;
- LIST_ENTRY(ahd_cmd) le;
- TAILQ_ENTRY(ahd_cmd) tqe;
- } links;
- uint32_t end;
-};
-
-struct ahd_cmd {
- union {
- struct ahd_cmd_internal icmd;
- struct scsi_cmnd scsi_cmd;
- } un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
/*************************** Device Data Structures ***************************/
/*
* A per probed device structure used to deal with some error recovery
@@ -297,22 +263,17 @@ struct ahd_cmd {
* after a successfully completed inquiry command to the target when
* that inquiry data indicates a lun is present.
*/
-TAILQ_HEAD(ahd_busyq, ahd_cmd);
+
typedef enum {
- AHD_DEV_UNCONFIGURED = 0x01,
AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
- AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
- AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */
AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
- AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
} ahd_linux_dev_flags;
struct ahd_linux_target;
struct ahd_linux_device {
TAILQ_ENTRY(ahd_linux_device) links;
- struct ahd_busyq busyq;
/*
* The number of transactions currently
@@ -388,62 +349,12 @@ struct ahd_linux_device {
*/
u_int commands_since_idle_or_otag;
#define AHD_OTAG_THRESH 500
-
- int lun;
- Scsi_Device *scsi_device;
- struct ahd_linux_target *target;
};
-typedef enum {
- AHD_DV_REQUIRED = 0x01,
- AHD_INQ_VALID = 0x02,
- AHD_BASIC_DV = 0x04,
- AHD_ENHANCED_DV = 0x08
-} ahd_linux_targ_flags;
-
-/* DV States */
-typedef enum {
- AHD_DV_STATE_EXIT = 0,
- AHD_DV_STATE_INQ_SHORT_ASYNC,
- AHD_DV_STATE_INQ_ASYNC,
- AHD_DV_STATE_INQ_ASYNC_VERIFY,
- AHD_DV_STATE_TUR,
- AHD_DV_STATE_REBD,
- AHD_DV_STATE_INQ_VERIFY,
- AHD_DV_STATE_WEB,
- AHD_DV_STATE_REB,
- AHD_DV_STATE_SU,
- AHD_DV_STATE_BUSY
-} ahd_dv_state;
-
struct ahd_linux_target {
- struct ahd_linux_device *devices[AHD_NUM_LUNS];
- int channel;
- int target;
- int refcount;
+ struct scsi_device *sdev[AHD_NUM_LUNS];
struct ahd_transinfo last_tinfo;
struct ahd_softc *ahd;
- ahd_linux_targ_flags flags;
- struct scsi_inquiry_data *inq_data;
- /*
- * The next "fallback" period to use for narrow/wide transfers.
- */
- uint8_t dv_next_narrow_period;
- uint8_t dv_next_wide_period;
- uint8_t dv_max_width;
- uint8_t dv_max_ppr_options;
- uint8_t dv_last_ppr_options;
- u_int dv_echo_size;
- ahd_dv_state dv_state;
- u_int dv_state_retry;
- uint8_t *dv_buffer;
- uint8_t *dv_buffer1;
-
- /*
- * Cumulative counter of errors.
- */
- u_long errors_detected;
- u_long cmds_since_error;
};
/********************* Definitions Required by the Core ***********************/
@@ -453,32 +364,16 @@ struct ahd_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * We dynamically adjust the number of segments in pre-2.5 kernels to
- * avoid fragmentation issues in the SCSI mid-layer's private memory
- * allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
- */
-extern u_int ahd_linux_nseg;
-#define AHD_NSEG ahd_linux_nseg
-#define AHD_LINUX_MIN_NSEG 64
-#else
#define AHD_NSEG 128
-#endif
/*
* Per-SCB OSM storage.
*/
-typedef enum {
- AHD_SCB_UP_EH_SEM = 0x1
-} ahd_linux_scb_flags;
-
struct scb_platform_data {
struct ahd_linux_device *dev;
dma_addr_t buf_busaddr;
uint32_t xfer_len;
uint32_t sense_resid; /* Auto-Sense residual */
- ahd_linux_scb_flags flags;
};
/*
@@ -487,44 +382,23 @@ struct scb_platform_data {
* alignment restrictions of the various platforms supported by
* this driver.
*/
-typedef enum {
- AHD_DV_WAIT_SIMQ_EMPTY = 0x01,
- AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
- AHD_DV_ACTIVE = 0x04,
- AHD_DV_SHUTDOWN = 0x08,
- AHD_RUN_CMPLT_Q_TIMER = 0x10
-} ahd_linux_softc_flags;
-
-TAILQ_HEAD(ahd_completeq, ahd_cmd);
-
struct ahd_platform_data {
/*
* Fields accessed from interrupt context.
*/
- struct ahd_linux_target *targets[AHD_NUM_TARGETS];
- TAILQ_HEAD(, ahd_linux_device) device_runq;
- struct ahd_completeq completeq;
+ struct scsi_target *starget[AHD_NUM_TARGETS];
spinlock_t spin_lock;
- struct tasklet_struct runq_tasklet;
u_int qfrozen;
- pid_t dv_pid;
- struct timer_list completeq_timer;
struct timer_list reset_timer;
- struct timer_list stats_timer;
struct semaphore eh_sem;
- struct semaphore dv_sem;
- struct semaphore dv_cmd_sem; /* XXX This needs to be in
- * the target struct
- */
- struct scsi_device *dv_scsi_dev;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */
- uint64_t hw_dma_mask;
- ahd_linux_softc_flags flags;
+#define AHD_SCB_UP_EH_SEM 0x1
+ uint32_t flags;
};
/************************** OS Utility Wrappers *******************************/
@@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
/**************************** Initialization **********************************/
int ahd_linux_register_host(struct ahd_softc *,
- Scsi_Host_Template *);
+ struct scsi_host_template *);
uint64_t ahd_linux_get_memsize(void);
@@ -657,28 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
struct ahd_transinfo *tinfo);
/******************************** Locking *************************************/
-/* Lock protecting internal data structures */
-static __inline void ahd_lockinit(struct ahd_softc *);
-static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock acquisition and release of the above lock in midlayer entry points. */
-static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
- unsigned long *flags);
-static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
- unsigned long *flags);
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void ahd_done_lockinit(struct ahd_softc *);
-static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock held during ahd_list manipulation and ahd softc frees */
-extern spinlock_t ahd_list_spinlock;
-static __inline void ahd_list_lockinit(void);
-static __inline void ahd_list_lock(unsigned long *flags);
-static __inline void ahd_list_unlock(unsigned long *flags);
-
static __inline void
ahd_lockinit(struct ahd_softc *ahd)
{
@@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
}
-static __inline void
-ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
- /*
- * In 2.5.X and some 2.4.X versions, the midlayer takes our
- * lock just before calling us, so we avoid locking again.
- * For other kernel versions, the io_request_lock is taken
- * just before our entry point is called. In this case, we
- * trade the io_request_lock for our per-softc lock.
- */
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&io_request_lock);
- spin_lock(&ahd->platform_data->spin_lock);
-#endif
-}
-
-static __inline void
-ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&ahd->platform_data->spin_lock);
- spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_lockinit(struct ahd_softc *ahd)
-{
- /*
- * In 2.5.X, our own lock is held during completions.
- * In previous versions, the io_request_lock is used.
- * In either case, we can't initialize this lock again.
- */
-}
-
-static __inline void
-ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_list_lockinit(void)
-{
- spin_lock_init(&ahd_list_spinlock);
-}
-
-static __inline void
-ahd_list_lock(unsigned long *flags)
-{
- spin_lock_irqsave(&ahd_list_spinlock, *flags);
-}
-
-static __inline void
-ahd_list_unlock(unsigned long *flags)
-{
- spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
-}
-
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
@@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
}
/**************************** Proc FS Support *********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int ahd_linux_proc_info(char *, char **, off_t, int, int, int);
-#else
int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
off_t, int, int);
-#endif
-
-/*************************** Domain Validation ********************************/
-#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
-#define AHD_DV_SIMQ_FROZEN(ahd) \
- ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \
- && (ahd)->platform_data->qfrozen == 1)
/*********************** Transaction Access Wrappers **************************/
-static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_scsi_status(struct scb *);
static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahd_get_transfer_length(struct scb *);
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
static __inline void ahd_freeze_scb(struct scb *scb);
static __inline
-void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
@@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status)
}
static __inline
-void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
@@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status)
}
static __inline
-uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
@@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb)
}
static __inline
-uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
@@ -1117,7 +890,6 @@ void ahd_done(struct ahd_softc*, struct scb*);
void ahd_send_async(struct ahd_softc *, char channel,
u_int target, u_int lun, ac_code, void *);
void ahd_print_path(struct ahd_softc *, struct scb *);
-void ahd_platform_dump_card_state(struct ahd_softc *ahd);
#ifdef CONFIG_PCI
#define AHD_PCI_CONFIG 1
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 91daf0c7fb10..390b53852d4b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
- struct ahd_softc *ahd;
- u_long l;
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ u_long s;
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev));
- if (ahd != NULL) {
- u_long s;
-
- TAILQ_REMOVE(&ahd_tailq, ahd, links);
- ahd_list_unlock(&l);
- ahd_lock(ahd, &s);
- ahd_intr_enable(ahd, FALSE);
- ahd_unlock(ahd, &s);
- ahd_free(ahd);
- } else
- ahd_list_unlock(&l);
+ ahd_lock(ahd, &s);
+ ahd_intr_enable(ahd, FALSE);
+ ahd_unlock(ahd, &s);
+ ahd_free(ahd);
+}
+
+static void
+ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
+{
+ struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
+ unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+ master_pdev = pci_get_slot(pdev->bus, master_devfn);
+ if (master_pdev) {
+ struct ahd_softc *master = pci_get_drvdata(master_pdev);
+ if (master) {
+ ahd->flags &= ~AHD_BIOS_ENABLED;
+ ahd->flags |= master->flags & AHD_BIOS_ENABLED;
+ } else
+ printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
+ pci_dev_put(master_pdev);
+ }
}
static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
char *name;
int error;
- /*
- * Some BIOSen report the same device multiple times.
- */
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- struct pci_dev *probed_pdev;
-
- probed_pdev = ahd->dev_softc;
- if (probed_pdev->bus->number == pdev->bus->number
- && probed_pdev->devfn == pdev->devfn)
- break;
- }
- if (ahd != NULL) {
- /* Skip duplicate. */
- return (-ENODEV);
- }
-
pci = pdev;
entry = ahd_find_pci_device(pci);
if (entry == NULL)
@@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (memsize >= 0x8000000000ULL
&& pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
ahd->flags |= AHD_64BIT_ADDRESSING;
- ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK;
} else if (memsize > 0x80000000
&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
ahd->flags |= AHD_39BIT_ADDRESSING;
- ahd->platform_data->hw_dma_mask = mask_39bit;
}
} else {
pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
ahd->dev_softc = pci;
error = ahd_pci_config(ahd, entry);
@@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahd_free(ahd);
return (-error);
}
+
+ /*
+ * Second Function PCI devices need to inherit some
+ * * settings from function 0.
+ */
+ if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+ ahd_linux_pci_inherit_flags(ahd);
+
pci_set_drvdata(pdev, ahd);
- if (aic79xx_detect_complete) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- ahd_linux_register_host(ahd, &aic79xx_driver_template);
-#else
- printf("aic79xx: ignoring PCI device found after "
- "initialization\n");
- return (-ENODEV);
-#endif
- }
+
+ ahd_linux_register_host(ahd, &aic79xx_driver_template);
return (0);
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 703f6e44889d..2131db60018a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -283,7 +283,6 @@ int
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
{
struct scb_data *shared_scb_data;
- u_long l;
u_int command;
uint32_t devconfig;
uint16_t subvendor;
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
* Allow interrupts now that we are completely setup.
*/
error = ahd_pci_map_int(ahd);
- if (error != 0)
- return (error);
-
- ahd_list_lock(&l);
- /*
- * Link this softc in with all other ahd instances.
- */
- ahd_softc_insert(ahd);
- ahd_list_unlock(&l);
- return (0);
+ if (!error)
+ ahd->init_level++;
+ return error;
}
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index e01cd6175e34..39a27840fce6 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -49,10 +49,53 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
u_int our_id, char channel,
u_int target_id, u_int target_offset);
static void ahd_dump_device_state(struct info_str *info,
- struct ahd_linux_device *dev);
+ struct scsi_device *sdev);
static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
char *buffer, int length);
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+} scsi_syncrates[] = {
+ { 0x08, 625 }, /* FAST-160 */
+ { 0x09, 1250 }, /* FAST-80 */
+ { 0x0a, 2500 }, /* FAST-40 40MHz */
+ { 0x0b, 3030 }, /* FAST-40 33MHz */
+ { 0x0c, 5000 } /* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahd_calc_syncsrate(u_int period_factor)
+{
+ int i;
+ int num_syncrates;
+
+ num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+ /* See if the period is in the "exception" table */
+ for (i = 0; i < num_syncrates; i++) {
+
+ if (period_factor == scsi_syncrates[i].period_factor) {
+ /* Period in kHz */
+ return (100000000 / scsi_syncrates[i].period);
+ }
+ }
+
+ /*
+ * Wasn't in the table, so use the standard
+ * 4 times conversion.
+ */
+ return (10000000 / (period_factor * 4 * 10));
+}
+
+
static void
copy_mem_info(struct info_str *info, char *data, int len)
{
@@ -109,7 +152,7 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
speed = 3300;
freq = 0;
if (tinfo->offset != 0) {
- freq = aic_calc_syncsrate(tinfo->period);
+ freq = ahd_calc_syncsrate(tinfo->period);
speed = freq;
}
speed *= (0x01 << tinfo->width);
@@ -167,6 +210,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
u_int target_offset)
{
struct ahd_linux_target *targ;
+ struct scsi_target *starget;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
int lun;
@@ -176,20 +220,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahd_format_transinfo(info, &tinfo->user);
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL)
+ starget = ahd->platform_data->starget[target_offset];
+ if (starget == NULL)
return;
+ targ = scsi_transport_target_data(starget);
copy_info(info, "\tGoal: ");
ahd_format_transinfo(info, &tinfo->goal);
copy_info(info, "\tCurr: ");
ahd_format_transinfo(info, &tinfo->curr);
- copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
- struct ahd_linux_device *dev;
+ struct scsi_device *dev;
- dev = targ->devices[lun];
+ dev = targ->sdev[lun];
if (dev == NULL)
continue;
@@ -199,10 +243,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
}
static void
-ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
+ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
{
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+
copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
- dev->target->channel + 'A', dev->target->target, dev->lun);
+ sdev->sdev_target->channel + 'A',
+ sdev->sdev_target->id, sdev->lun);
copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -278,36 +325,16 @@ done:
* Return information to handle /proc support for the driver.
*/
int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ahd_linux_proc_info(char *buffer, char **start, off_t offset,
- int length, int hostno, int inout)
-#else
ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
off_t offset, int length, int inout)
-#endif
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
struct info_str info;
char ahd_info[256];
- u_long l;
u_int max_targ;
u_int i;
int retval;
- retval = -EINVAL;
- ahd_list_lock(&l);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- if (ahd->platform_data->host->host_no == hostno)
- break;
- }
-#else
- ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
-#endif
-
- if (ahd == NULL)
- goto done;
-
/* Has data been written to the file? */
if (inout == TRUE) {
retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -357,6 +384,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
}
retval = info.pos > info.offset ? info.pos - info.offset : 0;
done:
- ahd_list_unlock(&l);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 088cbc23743d..91d294c6334e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
*
* $FreeBSD$
*/
@@ -243,7 +243,7 @@ typedef enum {
*/
AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
AHC_AIC7860_FE = AHC_AIC7850_FE,
- AHC_AIC7870_FE = AHC_TARGETMODE,
+ AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE,
AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA,
/*
* Although we have space for both the initiator and
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 810ec700d9fc..e196d83b93c7 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1306,7 +1306,6 @@ scratch_ram {
*/
MWI_RESIDUAL {
size 1
- alias TARG_IMMEDIATE_SCB
}
/*
* SCBID of the next SCB to be started by the controller.
@@ -1461,6 +1460,7 @@ scratch_ram {
*/
LAST_MSG {
size 1
+ alias TARG_IMMEDIATE_SCB
}
/*
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
index d84b741fbab5..15196390e28d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
PATCH_ARG_LIST = "struct ahc_softc *ahc"
PREFIX = "ahc_"
@@ -679,6 +679,7 @@ await_busfree:
clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
}
and SXFRCTL0, ~SPIOEN;
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
test SSTAT1,REQINIT|BUSFREE jz .;
test SSTAT1, BUSFREE jnz poll_for_work;
mvi MISSED_BUSFREE call set_seqint;
@@ -1097,7 +1098,7 @@ ultra2_dmahalt:
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SSTAT0, TARGET jz dma_last_sg;
- if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+ if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
test DMAPARAMS, DIRECTION jz dma_mid_sg;
}
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
index 468d612a44f6..3cb07e114e89 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
@@ -28,9 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
*/
/*
@@ -64,7 +62,6 @@
* is preceded by an initial zero (leading 0, followed by 16-bits, MSB
* first). The clock cycling from low to high initiates the next data
* bit to be sent from the chip.
- *
*/
#ifdef __linux__
@@ -81,14 +78,22 @@
* Right now, we only have to read the SEEPROM. But we make it easier to
* add other 93Cx6 functions.
*/
-static struct seeprom_cmd {
+struct seeprom_cmd {
uint8_t len;
- uint8_t bits[9];
-} seeprom_read = {3, {1, 1, 0}};
+ uint8_t bits[11];
+};
+/* Short opcodes for the c46 */
static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Long opcodes for the C56/C66 */
+static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Common opcodes */
static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
/*
* Wait for the SEERDY to go high; about 800 ns.
@@ -222,12 +227,25 @@ int
ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
u_int start_addr, u_int count)
{
+ struct seeprom_cmd *ewen, *ewds;
uint16_t v;
uint8_t temp;
int i, k;
/* Place the chip into write-enable mode */
- send_seeprom_cmd(sd, &seeprom_ewen);
+ if (sd->sd_chip == C46) {
+ ewen = &seeprom_ewen;
+ ewds = &seeprom_ewds;
+ } else if (sd->sd_chip == C56_66) {
+ ewen = &seeprom_long_ewen;
+ ewds = &seeprom_long_ewds;
+ } else {
+ printf("ahc_write_seeprom: unsupported seeprom type %d\n",
+ sd->sd_chip);
+ return (0);
+ }
+
+ send_seeprom_cmd(sd, ewen);
reset_seeprom(sd);
/* Write all requested data out to the seeprom. */
@@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
}
/* Put the chip back into write-protect mode */
- send_seeprom_cmd(sd, &seeprom_ewds);
+ send_seeprom_cmd(sd, ewds);
reset_seeprom(sd);
return (1);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 7bc01e41bcce..58ac46103eb6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -37,9 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $
*/
#ifdef __linux__
@@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc)
ahc_outb(ahc, SEQ_FLAGS2,
ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
}
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahc_outb(ahc, CLRINT, CLRSEQINT);
+
ahc_outb(ahc, MWI_RESIDUAL, 0);
ahc_outb(ahc, SEQCTL, ahc->seqctl);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
+
ahc_unpause(ahc);
}
@@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb_index);
}
#endif
- /*
- * Force a renegotiation with this target just in
- * case the cable was pulled and will later be
- * re-attached. The target may forget its negotiation
- * settings with us should it attempt to reselect
- * during the interruption. The target will not issue
- * a unit attention in this case, so we must always
- * renegotiate.
- */
ahc_scb_devinfo(ahc, &devinfo, scb);
- ahc_force_renegotiation(ahc, &devinfo);
ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahc_freeze_devq(ahc, scb);
+
+ /*
+ * Cancel any pending transactions on the device
+ * now that it seems to be missing. This will
+ * also revert us to async/narrow transfers until
+ * we can renegotiate with the device.
+ */
+ ahc_handle_devreset(ahc, &devinfo,
+ CAM_SEL_TIMEOUT,
+ "Selection Timeout",
+ /*verbose_level*/1);
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_restart(ahc);
@@ -3763,8 +3771,9 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
/*period*/0, /*offset*/0, /*ppr_options*/0,
AHC_TRANS_CUR, /*paused*/TRUE);
- ahc_send_async(ahc, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+ if (status != CAM_SEL_TIMEOUT)
+ ahc_send_async(ahc, devinfo->channel, devinfo->target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
if (message != NULL
&& (verbose_level <= bootverbose))
@@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
* to disturb the integrity of the bus.
*/
ahc_pause(ahc);
- if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
- /*
- * The chip has not been initialized since
- * PCI/EISA/VLB bus reset. Don't trust
- * "left over BIOS data".
- */
- ahc->flags |= AHC_NO_BIOS_INIT;
- }
sxfrctl1_b = 0;
if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
u_int sblkctl;
@@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
ahc->flags |= AHC_ALL_INTERRUPTS;
paused = FALSE;
do {
- if (paused)
+ if (paused) {
ahc_unpause(ahc);
+ /*
+ * Give the sequencer some time to service
+ * any active selections.
+ */
+ ahc_delay(500);
+ }
ahc_intr(ahc);
ahc_pause(ahc);
paused = TRUE;
ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
- ahc_clear_critical_section(ahc);
intstat = ahc_inb(ahc, INTSTAT);
+ if ((intstat & INT_PEND) == 0) {
+ ahc_clear_critical_section(ahc);
+ intstat = ahc_inb(ahc, INTSTAT);
+ }
} while (--maxloops
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 687f19e9cf03..c932b3b94490 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -125,12 +125,6 @@
static struct scsi_transport_template *ahc_linux_transport_template = NULL;
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
-
#include <linux/init.h> /* __setup */
#include <linux/mm.h> /* For fetching system memory size */
#include <linux/blkdev.h> /* For block_size() */
@@ -391,7 +385,6 @@ static int ahc_linux_run_command(struct ahc_softc*,
struct ahc_linux_device *,
struct scsi_cmnd *);
static void ahc_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahc_linux_setup_tag_info;
static int aic7xxx_setup(char *s);
static int ahc_linux_unit;
@@ -635,6 +628,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev)
targ->sdev[sdev->lun] = sdev;
+ spi_period(starget) = 0;
+
return 0;
}
@@ -918,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
}
}
+static char *
+ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+ void (*callback)(u_long, int, int, int32_t),
+ u_long callback_arg)
+{
+ char *tok_end;
+ char *tok_end2;
+ int i;
+ int instance;
+ int targ;
+ int done;
+ char tok_list[] = {'.', ',', '{', '}', '\0'};
+
+ /* All options use a ':' name/arg separator */
+ if (*opt_arg != ':')
+ return (opt_arg);
+ opt_arg++;
+ instance = -1;
+ targ = -1;
+ done = FALSE;
+ /*
+ * Restore separator that may be in
+ * the middle of our option argument.
+ */
+ tok_end = strchr(opt_arg, '\0');
+ if (tok_end < end)
+ *tok_end = ',';
+ while (!done) {
+ switch (*opt_arg) {
+ case '{':
+ if (instance == -1) {
+ instance = 0;
+ } else {
+ if (depth > 1) {
+ if (targ == -1)
+ targ = 0;
+ } else {
+ printf("Malformed Option %s\n",
+ opt_name);
+ done = TRUE;
+ }
+ }
+ opt_arg++;
+ break;
+ case '}':
+ if (targ != -1)
+ targ = -1;
+ else if (instance != -1)
+ instance = -1;
+ opt_arg++;
+ break;
+ case ',':
+ case '.':
+ if (instance == -1)
+ done = TRUE;
+ else if (targ >= 0)
+ targ++;
+ else if (instance >= 0)
+ instance++;
+ opt_arg++;
+ break;
+ case '\0':
+ done = TRUE;
+ break;
+ default:
+ tok_end = end;
+ for (i = 0; tok_list[i]; i++) {
+ tok_end2 = strchr(opt_arg, tok_list[i]);
+ if ((tok_end2) && (tok_end2 < tok_end))
+ tok_end = tok_end2;
+ }
+ callback(callback_arg, instance, targ,
+ simple_strtol(opt_arg, NULL, 0));
+ opt_arg = tok_end;
+ break;
+ }
+ }
+ return (opt_arg);
+}
+
/*
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
@@ -972,7 +1047,7 @@ aic7xxx_setup(char *s)
if (strncmp(p, "global_tag_depth", n) == 0) {
ahc_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
- s = aic_parse_brace_option("tag_info", p + n, end,
+ s = ahc_parse_brace_option("tag_info", p + n, end,
2, ahc_linux_setup_tag_info, 0);
} else if (p[n] == ':') {
*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
@@ -1612,9 +1687,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
if (channel == 'B')
target_offset += 8;
starget = ahc->platform_data->starget[target_offset];
- targ = scsi_transport_target_data(starget);
- if (targ == NULL)
+ if (starget == NULL)
break;
+ targ = scsi_transport_target_data(starget);
target_ppr_options =
(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -2329,8 +2404,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
{
}
-static void ahc_linux_exit(void);
-
static void ahc_linux_set_width(struct scsi_target *starget, int width)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 0e47ac217549..c52996269240 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#define AIC7XXX_DRIVER_VERSION "6.2.36"
+#define AIC7XXX_DRIVER_VERSION "7.0"
/*************************** Device Data Structures ***************************/
/*
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 9d318ce2c993..0d44a6907dd2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
ahc_free(ahc);
}
+static void
+ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
+{
+ struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
+ unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+ master_pdev = pci_get_slot(pdev->bus, master_devfn);
+ if (master_pdev) {
+ struct ahc_softc *master = pci_get_drvdata(master_pdev);
+ if (master) {
+ ahc->flags &= ~AHC_BIOS_ENABLED;
+ ahc->flags |= master->flags & AHC_BIOS_ENABLED;
+
+ ahc->flags &= ~AHC_PRIMARY_CHANNEL;
+ ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
+ } else
+ printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
+ pci_dev_put(master_pdev);
+ }
+}
+
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc_free(ahc);
return (-error);
}
+
+ /*
+ * Second Function PCI devices need to inherit some
+ * settings from function 0.
+ */
+ if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+ ahc_linux_pci_inherit_flags(ahc);
+
pci_set_drvdata(pdev, ahc);
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 3802c91f0b07..04a3506cf340 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -54,6 +54,49 @@ static void ahc_dump_device_state(struct info_str *info,
static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
char *buffer, int length);
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+} scsi_syncrates[] = {
+ { 0x08, 625 }, /* FAST-160 */
+ { 0x09, 1250 }, /* FAST-80 */
+ { 0x0a, 2500 }, /* FAST-40 40MHz */
+ { 0x0b, 3030 }, /* FAST-40 33MHz */
+ { 0x0c, 5000 } /* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahc_calc_syncsrate(u_int period_factor)
+{
+ int i;
+ int num_syncrates;
+
+ num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+ /* See if the period is in the "exception" table */
+ for (i = 0; i < num_syncrates; i++) {
+
+ if (period_factor == scsi_syncrates[i].period_factor) {
+ /* Period in kHz */
+ return (100000000 / scsi_syncrates[i].period);
+ }
+ }
+
+ /*
+ * Wasn't in the table, so use the standard
+ * 4 times conversion.
+ */
+ return (10000000 / (period_factor * 4 * 10));
+}
+
+
static void
copy_mem_info(struct info_str *info, char *data, int len)
{
@@ -106,7 +149,7 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
speed = 3300;
freq = 0;
if (tinfo->offset != 0) {
- freq = aic_calc_syncsrate(tinfo->period);
+ freq = ahc_calc_syncsrate(tinfo->period);
speed = freq;
}
speed *= (0x01 << tinfo->width);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
index 7c1390ed1179..2ce1febca207 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahc_reg_parse_entry {
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
#define CMDSIZE_TABLE_TAIL 0x34
#define MWI_RESIDUAL 0x38
-#define TARG_IMMEDIATE_SCB 0x38
#define NEXT_QUEUED_SCB 0x39
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
#define RETURN_2 0x52
#define LAST_MSG 0x53
+#define TARG_IMMEDIATE_SCB 0x53
#define SCSISEQ_TEMPLATE 0x54
#define ENSELO 0x40
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
index 9c713775d44a..88bfd767c51c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
#include "aic7xxx_osm.h"
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
index cf411368a871..4cee08521e75 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
@@ -2,13 +2,13 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
static uint8_t seqprog[] = {
0xb2, 0x00, 0x00, 0x08,
0xf7, 0x11, 0x22, 0x08,
- 0x00, 0x65, 0xec, 0x59,
+ 0x00, 0x65, 0xee, 0x59,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x6a, 0x24, 0x08,
0x40, 0x00, 0x40, 0x68,
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = {
0x01, 0x4d, 0xc8, 0x30,
0x00, 0x4c, 0x12, 0x70,
0x01, 0x39, 0xa2, 0x30,
- 0x00, 0x6a, 0xc0, 0x5e,
+ 0x00, 0x6a, 0xc2, 0x5e,
0x01, 0x51, 0x20, 0x31,
0x01, 0x57, 0xae, 0x00,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x51, 0x12, 0x5e,
+ 0x00, 0x51, 0x14, 0x5e,
0x01, 0x51, 0xc8, 0x30,
0x00, 0x39, 0xc8, 0x60,
0x00, 0xbb, 0x30, 0x70,
- 0xc1, 0x6a, 0xd8, 0x5e,
+ 0xc1, 0x6a, 0xda, 0x5e,
0x01, 0xbf, 0x72, 0x30,
0x01, 0x40, 0x7e, 0x31,
0x01, 0x90, 0x80, 0x30,
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = {
0x08, 0x6a, 0x78, 0x00,
0x01, 0x50, 0xc8, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0xfc, 0x5d,
+ 0x48, 0x6a, 0xfe, 0x5d,
0x01, 0x6a, 0xdc, 0x01,
0x88, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0xfc, 0x5d,
+ 0x48, 0x6a, 0xfe, 0x5d,
0x01, 0x6a, 0x26, 0x01,
0xf0, 0x19, 0x7a, 0x08,
0x0f, 0x18, 0xc8, 0x08,
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = {
0x00, 0x65, 0x20, 0x41,
0x02, 0x57, 0xae, 0x00,
0x00, 0x65, 0x9e, 0x40,
- 0x61, 0x6a, 0xd8, 0x5e,
+ 0x61, 0x6a, 0xda, 0x5e,
0x08, 0x51, 0x20, 0x71,
0x02, 0x0b, 0xb2, 0x78,
0x00, 0x65, 0xae, 0x40,
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = {
0x80, 0x3d, 0x7a, 0x00,
0x20, 0x6a, 0x16, 0x00,
0x00, 0x65, 0xcc, 0x41,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0x65, 0xb4, 0x5e,
0x00, 0x65, 0x12, 0x40,
0x20, 0x11, 0xd2, 0x68,
0x20, 0x6a, 0x18, 0x00,
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = {
0x80, 0x0b, 0xc4, 0x79,
0x12, 0x01, 0x02, 0x00,
0x01, 0xab, 0xac, 0x30,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x40, 0x6a, 0x16, 0x00,
- 0x80, 0x3e, 0x84, 0x5d,
+ 0x80, 0x3e, 0x86, 0x5d,
0x20, 0xb8, 0x18, 0x79,
- 0x20, 0x6a, 0x84, 0x5d,
- 0x00, 0xab, 0x84, 0x5d,
+ 0x20, 0x6a, 0x86, 0x5d,
+ 0x00, 0xab, 0x86, 0x5d,
0x01, 0xa9, 0x78, 0x30,
0x10, 0xb8, 0x20, 0x79,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x00, 0x65, 0xae, 0x40,
0x10, 0x03, 0x3c, 0x69,
0x08, 0x3c, 0x5a, 0x69,
0x04, 0x3c, 0x92, 0x69,
0x02, 0x3c, 0x98, 0x69,
0x01, 0x3c, 0x44, 0x79,
- 0xff, 0x6a, 0x70, 0x00,
+ 0xff, 0x6a, 0xa6, 0x00,
0x00, 0x65, 0xa4, 0x59,
- 0x00, 0x6a, 0xc0, 0x5e,
- 0xff, 0x38, 0x30, 0x71,
+ 0x00, 0x6a, 0xc2, 0x5e,
+ 0xff, 0x53, 0x30, 0x71,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x38, 0x12, 0x5e,
+ 0x00, 0x53, 0x14, 0x5e,
0x00, 0x65, 0xea, 0x58,
0x12, 0x01, 0x02, 0x00,
0x00, 0x65, 0x18, 0x41,
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = {
0x00, 0x65, 0xf2, 0x58,
0xfd, 0x57, 0xae, 0x08,
0x00, 0x65, 0xae, 0x40,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x20, 0x3c, 0x4a, 0x79,
- 0x02, 0x6a, 0x84, 0x5d,
- 0x04, 0x6a, 0x84, 0x5d,
+ 0x02, 0x6a, 0x86, 0x5d,
+ 0x04, 0x6a, 0x86, 0x5d,
0x01, 0x03, 0x4c, 0x69,
0xf7, 0x11, 0x22, 0x08,
0xff, 0x6a, 0x24, 0x08,
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = {
0x80, 0x86, 0xc8, 0x08,
0x01, 0x4f, 0xc8, 0x30,
0x00, 0x50, 0x6c, 0x61,
- 0xc4, 0x6a, 0x6e, 0x5d,
+ 0xc4, 0x6a, 0x70, 0x5d,
0x40, 0x3c, 0x68, 0x79,
- 0x28, 0x6a, 0x84, 0x5d,
+ 0x28, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
- 0x08, 0x6a, 0x84, 0x5d,
+ 0x08, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
- 0x84, 0x6a, 0x6e, 0x5d,
+ 0x84, 0x6a, 0x70, 0x5d,
0x00, 0x65, 0xf2, 0x58,
0x01, 0x66, 0xc8, 0x30,
0x01, 0x64, 0xd8, 0x31,
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = {
0xf7, 0x3c, 0x78, 0x08,
0x00, 0x65, 0x20, 0x41,
0x40, 0xaa, 0x7e, 0x10,
- 0x04, 0xaa, 0x6e, 0x5d,
- 0x00, 0x65, 0x56, 0x42,
- 0xc4, 0x6a, 0x6e, 0x5d,
+ 0x04, 0xaa, 0x70, 0x5d,
+ 0x00, 0x65, 0x58, 0x42,
+ 0xc4, 0x6a, 0x70, 0x5d,
0xc0, 0x6a, 0x7e, 0x00,
- 0x00, 0xa8, 0x84, 0x5d,
+ 0x00, 0xa8, 0x86, 0x5d,
0xe4, 0x6a, 0x06, 0x00,
- 0x00, 0x6a, 0x84, 0x5d,
+ 0x00, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
0x10, 0x3c, 0xa8, 0x69,
- 0x00, 0xbb, 0x8a, 0x44,
+ 0x00, 0xbb, 0x8c, 0x44,
0x18, 0x6a, 0xda, 0x01,
0x01, 0x69, 0xd8, 0x31,
0x1c, 0x6a, 0xd0, 0x01,
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = {
0x01, 0x93, 0x26, 0x01,
0x03, 0x6a, 0x2a, 0x01,
0x01, 0x69, 0x32, 0x31,
- 0x1c, 0x6a, 0xe0, 0x5d,
+ 0x1c, 0x6a, 0xe2, 0x5d,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
0x01, 0x50, 0xa0, 0x18,
0x02, 0x6a, 0x22, 0x05,
0x1a, 0x01, 0x02, 0x00,
0x80, 0x6a, 0x74, 0x00,
0x40, 0x6a, 0x78, 0x00,
0x40, 0x6a, 0x16, 0x00,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x00, 0x65, 0xda, 0x5d,
0x01, 0x3f, 0xc8, 0x30,
- 0xbf, 0x64, 0x56, 0x7a,
- 0x80, 0x64, 0x9e, 0x73,
- 0xa0, 0x64, 0x00, 0x74,
- 0xc0, 0x64, 0xf4, 0x73,
- 0xe0, 0x64, 0x30, 0x74,
- 0x01, 0x6a, 0xd8, 0x5e,
+ 0xbf, 0x64, 0x58, 0x7a,
+ 0x80, 0x64, 0xa0, 0x73,
+ 0xa0, 0x64, 0x02, 0x74,
+ 0xc0, 0x64, 0xf6, 0x73,
+ 0xe0, 0x64, 0x32, 0x74,
+ 0x01, 0x6a, 0xda, 0x5e,
0x00, 0x65, 0xcc, 0x41,
0xf7, 0x11, 0x22, 0x08,
0x01, 0x06, 0xd4, 0x30,
0xff, 0x6a, 0x24, 0x08,
0xf7, 0x01, 0x02, 0x08,
- 0x09, 0x0c, 0xe6, 0x79,
+ 0xc0, 0x6a, 0x78, 0x00,
+ 0x09, 0x0c, 0xe8, 0x79,
0x08, 0x0c, 0x04, 0x68,
- 0xb1, 0x6a, 0xd8, 0x5e,
+ 0xb1, 0x6a, 0xda, 0x5e,
0xff, 0x6a, 0x26, 0x09,
0x12, 0x01, 0x02, 0x00,
0x02, 0x6a, 0x08, 0x30,
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = {
0x00, 0xa5, 0x4a, 0x21,
0x00, 0xa6, 0x4c, 0x21,
0x00, 0xa7, 0x4e, 0x25,
- 0x08, 0xeb, 0xdc, 0x7e,
- 0x80, 0xeb, 0x06, 0x7a,
+ 0x08, 0xeb, 0xde, 0x7e,
+ 0x80, 0xeb, 0x08, 0x7a,
0xff, 0x6a, 0xd6, 0x09,
- 0x08, 0xeb, 0x0a, 0x6a,
+ 0x08, 0xeb, 0x0c, 0x6a,
0xff, 0x6a, 0xd4, 0x0c,
- 0x80, 0xa3, 0xdc, 0x6e,
- 0x88, 0xeb, 0x20, 0x72,
- 0x08, 0xeb, 0xdc, 0x6e,
- 0x04, 0xea, 0x24, 0xe2,
- 0x08, 0xee, 0xdc, 0x6e,
+ 0x80, 0xa3, 0xde, 0x6e,
+ 0x88, 0xeb, 0x22, 0x72,
+ 0x08, 0xeb, 0xde, 0x6e,
+ 0x04, 0xea, 0x26, 0xe2,
+ 0x08, 0xee, 0xde, 0x6e,
0x04, 0x6a, 0xd0, 0x81,
0x05, 0xa4, 0xc0, 0x89,
0x03, 0xa5, 0xc2, 0x31,
0x09, 0x6a, 0xd6, 0x05,
- 0x00, 0x65, 0x08, 0x5a,
+ 0x00, 0x65, 0x0a, 0x5a,
0x06, 0xa4, 0xd4, 0x89,
- 0x80, 0x94, 0xdc, 0x7e,
+ 0x80, 0x94, 0xde, 0x7e,
0x07, 0xe9, 0x10, 0x31,
0x01, 0xe9, 0x46, 0x31,
- 0x00, 0xa3, 0xba, 0x5e,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x00, 0xa3, 0xbc, 0x5e,
+ 0x00, 0x65, 0xfc, 0x59,
0x01, 0xa4, 0xca, 0x30,
- 0x80, 0xa3, 0x34, 0x7a,
+ 0x80, 0xa3, 0x36, 0x7a,
0x02, 0x65, 0xca, 0x00,
0x01, 0x65, 0xf8, 0x31,
0x80, 0x93, 0x26, 0x01,
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = {
0x01, 0x8c, 0xc8, 0x30,
0x00, 0x88, 0xc8, 0x18,
0x02, 0x64, 0xc8, 0x88,
- 0xff, 0x64, 0xdc, 0x7e,
- 0xff, 0x8d, 0x4a, 0x6a,
- 0xff, 0x8e, 0x4a, 0x6a,
+ 0xff, 0x64, 0xde, 0x7e,
+ 0xff, 0x8d, 0x4c, 0x6a,
+ 0xff, 0x8e, 0x4c, 0x6a,
0x03, 0x8c, 0xd4, 0x98,
- 0x00, 0x65, 0xdc, 0x56,
+ 0x00, 0x65, 0xde, 0x56,
0x01, 0x64, 0x70, 0x30,
0xff, 0x64, 0xc8, 0x10,
0x01, 0x64, 0xc8, 0x18,
0x00, 0x8c, 0x18, 0x19,
0xff, 0x8d, 0x1a, 0x21,
0xff, 0x8e, 0x1c, 0x25,
- 0xc0, 0x3c, 0x5a, 0x7a,
- 0x21, 0x6a, 0xd8, 0x5e,
+ 0xc0, 0x3c, 0x5c, 0x7a,
+ 0x21, 0x6a, 0xda, 0x5e,
0xa8, 0x6a, 0x76, 0x00,
0x79, 0x6a, 0x76, 0x00,
- 0x40, 0x3f, 0x62, 0x6a,
+ 0x40, 0x3f, 0x64, 0x6a,
0x04, 0x3b, 0x76, 0x00,
0x04, 0x6a, 0xd4, 0x81,
- 0x20, 0x3c, 0x6a, 0x7a,
- 0x51, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x82, 0x42,
+ 0x20, 0x3c, 0x6c, 0x7a,
+ 0x51, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x84, 0x42,
0x20, 0x3c, 0x78, 0x00,
- 0x00, 0xb3, 0xba, 0x5e,
+ 0x00, 0xb3, 0xbc, 0x5e,
0x07, 0xac, 0x10, 0x31,
0x05, 0xb3, 0x46, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0xac, 0x6a, 0xee, 0x5d,
+ 0xac, 0x6a, 0xf0, 0x5d,
0xa3, 0x6a, 0xcc, 0x00,
- 0xb3, 0x6a, 0xf2, 0x5d,
- 0x00, 0x65, 0x3a, 0x5a,
+ 0xb3, 0x6a, 0xf4, 0x5d,
+ 0x00, 0x65, 0x3c, 0x5a,
0xfd, 0xa4, 0x48, 0x09,
0x03, 0x8c, 0x10, 0x30,
- 0x00, 0x65, 0xe6, 0x5d,
- 0x01, 0xa4, 0x94, 0x7a,
+ 0x00, 0x65, 0xe8, 0x5d,
+ 0x01, 0xa4, 0x96, 0x7a,
0x04, 0x3b, 0x76, 0x08,
0x01, 0x3b, 0x26, 0x31,
0x80, 0x02, 0x04, 0x00,
- 0x10, 0x0c, 0x8a, 0x7a,
- 0x03, 0x9e, 0x8c, 0x6a,
+ 0x10, 0x0c, 0x8c, 0x7a,
+ 0x03, 0x9e, 0x8e, 0x6a,
0x7f, 0x02, 0x04, 0x08,
- 0x91, 0x6a, 0xd8, 0x5e,
+ 0x91, 0x6a, 0xda, 0x5e,
0x00, 0x65, 0xcc, 0x41,
0x01, 0xa4, 0xca, 0x30,
- 0x80, 0xa3, 0x9a, 0x7a,
+ 0x80, 0xa3, 0x9c, 0x7a,
0x02, 0x65, 0xca, 0x00,
0x01, 0x65, 0xf8, 0x31,
0x01, 0x3b, 0x26, 0x31,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x01, 0xfc, 0xa8, 0x6a,
- 0x80, 0x0b, 0x9e, 0x6a,
- 0x10, 0x0c, 0x9e, 0x7a,
- 0x20, 0x93, 0x9e, 0x6a,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x01, 0xfc, 0xaa, 0x6a,
+ 0x80, 0x0b, 0xa0, 0x6a,
+ 0x10, 0x0c, 0xa0, 0x7a,
+ 0x20, 0x93, 0xa0, 0x6a,
0x02, 0x93, 0x26, 0x01,
- 0x02, 0xfc, 0xb2, 0x7a,
- 0x40, 0x0d, 0xc6, 0x6a,
+ 0x02, 0xfc, 0xb4, 0x7a,
+ 0x40, 0x0d, 0xc8, 0x6a,
0x01, 0xa4, 0x48, 0x01,
- 0x00, 0x65, 0xc6, 0x42,
- 0x40, 0x0d, 0xb8, 0x6a,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x00, 0x65, 0xaa, 0x42,
- 0x80, 0xfc, 0xc2, 0x7a,
- 0x80, 0xa4, 0xc2, 0x6a,
+ 0x00, 0x65, 0xc8, 0x42,
+ 0x40, 0x0d, 0xba, 0x6a,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x00, 0x65, 0xac, 0x42,
+ 0x80, 0xfc, 0xc4, 0x7a,
+ 0x80, 0xa4, 0xc4, 0x6a,
0xff, 0xa5, 0x4a, 0x19,
0xff, 0xa6, 0x4c, 0x21,
0xff, 0xa7, 0x4e, 0x21,
0xf8, 0xfc, 0x48, 0x09,
0x7f, 0xa3, 0x46, 0x09,
- 0x04, 0x3b, 0xe2, 0x6a,
+ 0x04, 0x3b, 0xe4, 0x6a,
0x02, 0x93, 0x26, 0x01,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0xa4, 0xe0, 0x7a,
- 0x01, 0xfc, 0xd6, 0x7a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x00, 0x65, 0x82, 0x42,
- 0x01, 0x94, 0xe0, 0x7a,
- 0x10, 0x94, 0xe2, 0x6a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0xa4, 0xe2, 0x7a,
+ 0x01, 0xfc, 0xd8, 0x7a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x00, 0x65, 0x84, 0x42,
+ 0x01, 0x94, 0xe2, 0x7a,
+ 0x10, 0x94, 0xe4, 0x6a,
0xd7, 0x93, 0x26, 0x09,
- 0x28, 0x93, 0xe6, 0x6a,
+ 0x28, 0x93, 0xe8, 0x6a,
0x01, 0x85, 0x0a, 0x01,
- 0x02, 0xfc, 0xee, 0x6a,
+ 0x02, 0xfc, 0xf0, 0x6a,
0x01, 0x14, 0x46, 0x31,
0xff, 0x6a, 0x10, 0x09,
0xfe, 0x85, 0x0a, 0x09,
- 0xff, 0x38, 0xfc, 0x6a,
- 0x80, 0xa3, 0xfc, 0x7a,
- 0x80, 0x0b, 0xfa, 0x7a,
- 0x04, 0x3b, 0xfc, 0x7a,
+ 0xff, 0x38, 0xfe, 0x6a,
+ 0x80, 0xa3, 0xfe, 0x7a,
+ 0x80, 0x0b, 0xfc, 0x7a,
+ 0x04, 0x3b, 0xfe, 0x7a,
0xbf, 0x3b, 0x76, 0x08,
0x01, 0x3b, 0x26, 0x31,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x01, 0x0b, 0x0a, 0x6b,
- 0x10, 0x0c, 0xfe, 0x7a,
- 0x04, 0x93, 0x08, 0x6b,
- 0x01, 0x94, 0x06, 0x7b,
- 0x10, 0x94, 0x08, 0x6b,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x01, 0x0b, 0x0c, 0x6b,
+ 0x10, 0x0c, 0x00, 0x7b,
+ 0x04, 0x93, 0x0a, 0x6b,
+ 0x01, 0x94, 0x08, 0x7b,
+ 0x10, 0x94, 0x0a, 0x6b,
0xc7, 0x93, 0x26, 0x09,
0x01, 0x99, 0xd4, 0x30,
- 0x38, 0x93, 0x0c, 0x6b,
- 0xff, 0x08, 0x5a, 0x6b,
- 0xff, 0x09, 0x5a, 0x6b,
- 0xff, 0x0a, 0x5a, 0x6b,
- 0xff, 0x38, 0x28, 0x7b,
+ 0x38, 0x93, 0x0e, 0x6b,
+ 0xff, 0x08, 0x5c, 0x6b,
+ 0xff, 0x09, 0x5c, 0x6b,
+ 0xff, 0x0a, 0x5c, 0x6b,
+ 0xff, 0x38, 0x2a, 0x7b,
0x04, 0x14, 0x10, 0x31,
0x01, 0x38, 0x18, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0xf4, 0x5d,
- 0x00, 0x38, 0xe0, 0x5d,
+ 0x14, 0x6a, 0xf6, 0x5d,
+ 0x00, 0x38, 0xe2, 0x5d,
0xff, 0x6a, 0x70, 0x08,
- 0x00, 0x65, 0x54, 0x43,
- 0x80, 0xa3, 0x2e, 0x7b,
+ 0x00, 0x65, 0x56, 0x43,
+ 0x80, 0xa3, 0x30, 0x7b,
0x01, 0xa4, 0x48, 0x01,
- 0x00, 0x65, 0x5a, 0x43,
- 0x08, 0xeb, 0x34, 0x7b,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x08, 0xeb, 0x30, 0x6b,
+ 0x00, 0x65, 0x5c, 0x43,
+ 0x08, 0xeb, 0x36, 0x7b,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x08, 0xeb, 0x32, 0x6b,
0x07, 0xe9, 0x10, 0x31,
0x01, 0xe9, 0xca, 0x30,
0x01, 0x65, 0x46, 0x31,
- 0x00, 0x6a, 0xba, 0x5e,
+ 0x00, 0x6a, 0xbc, 0x5e,
0x88, 0x6a, 0xcc, 0x00,
- 0xa4, 0x6a, 0xf4, 0x5d,
- 0x08, 0x6a, 0xe0, 0x5d,
+ 0xa4, 0x6a, 0xf6, 0x5d,
+ 0x08, 0x6a, 0xe2, 0x5d,
0x0d, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
0x88, 0x6a, 0xcc, 0x00,
- 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8c, 0x5e,
0x01, 0x99, 0x46, 0x31,
- 0x00, 0xa3, 0xba, 0x5e,
+ 0x00, 0xa3, 0xbc, 0x5e,
0x01, 0x88, 0x10, 0x31,
- 0x00, 0x65, 0x3a, 0x5a,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x00, 0x65, 0x3c, 0x5a,
+ 0x00, 0x65, 0xfc, 0x59,
0x03, 0x8c, 0x10, 0x30,
- 0x00, 0x65, 0xe6, 0x5d,
- 0x80, 0x0b, 0x82, 0x6a,
- 0x80, 0x0b, 0x62, 0x6b,
- 0x01, 0x0c, 0x5c, 0x7b,
- 0x10, 0x0c, 0x82, 0x7a,
- 0x03, 0x9e, 0x82, 0x6a,
- 0x00, 0x65, 0x04, 0x5a,
- 0x00, 0x6a, 0xba, 0x5e,
- 0x01, 0xa4, 0x82, 0x6b,
- 0xff, 0x38, 0x78, 0x7b,
+ 0x00, 0x65, 0xe8, 0x5d,
+ 0x80, 0x0b, 0x84, 0x6a,
+ 0x80, 0x0b, 0x64, 0x6b,
+ 0x01, 0x0c, 0x5e, 0x7b,
+ 0x10, 0x0c, 0x84, 0x7a,
+ 0x03, 0x9e, 0x84, 0x6a,
+ 0x00, 0x65, 0x06, 0x5a,
+ 0x00, 0x6a, 0xbc, 0x5e,
+ 0x01, 0xa4, 0x84, 0x6b,
+ 0xff, 0x38, 0x7a, 0x7b,
0x01, 0x38, 0xc8, 0x30,
0x00, 0x08, 0x40, 0x19,
0xff, 0x6a, 0xc8, 0x08,
0x00, 0x09, 0x42, 0x21,
0x00, 0x0a, 0x44, 0x21,
0xff, 0x6a, 0x70, 0x08,
- 0x00, 0x65, 0x7a, 0x43,
+ 0x00, 0x65, 0x7c, 0x43,
0x03, 0x08, 0x40, 0x31,
0x03, 0x08, 0x40, 0x31,
0x01, 0x08, 0x40, 0x31,
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = {
0x04, 0x3c, 0xcc, 0x79,
0xfb, 0x3c, 0x78, 0x08,
0x04, 0x93, 0x20, 0x79,
- 0x01, 0x0c, 0x8e, 0x6b,
+ 0x01, 0x0c, 0x90, 0x6b,
0x80, 0xba, 0x20, 0x79,
0x80, 0x04, 0x20, 0x79,
- 0xe4, 0x6a, 0x6e, 0x5d,
- 0x23, 0x6a, 0x84, 0x5d,
- 0x01, 0x6a, 0x84, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
+ 0x23, 0x6a, 0x86, 0x5d,
+ 0x01, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x20, 0x41,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0x3c, 0xa2, 0x7b,
- 0x21, 0x6a, 0xd8, 0x5e,
+ 0x80, 0x3c, 0xa4, 0x7b,
+ 0x21, 0x6a, 0xda, 0x5e,
0x01, 0xbc, 0x18, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x02, 0x6a, 0xf8, 0x01,
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = {
0xff, 0x6a, 0x12, 0x08,
0xff, 0x6a, 0x14, 0x08,
0xf3, 0xbc, 0xd4, 0x18,
- 0xa0, 0x6a, 0xc8, 0x53,
+ 0xa0, 0x6a, 0xca, 0x53,
0x04, 0xa0, 0x10, 0x31,
0xac, 0x6a, 0x26, 0x01,
0x04, 0xa0, 0x10, 0x31,
0x03, 0x08, 0x18, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0xa0, 0x6a, 0xf4, 0x5d,
- 0x00, 0xbc, 0xe0, 0x5d,
+ 0xa0, 0x6a, 0xf6, 0x5d,
+ 0x00, 0xbc, 0xe2, 0x5d,
0x3d, 0x6a, 0x26, 0x01,
- 0x00, 0x65, 0xe0, 0x43,
+ 0x00, 0x65, 0xe2, 0x43,
0xff, 0x6a, 0x10, 0x09,
0xa4, 0x6a, 0x26, 0x01,
0x0c, 0xa0, 0x32, 0x31,
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = {
0x36, 0x6a, 0x26, 0x01,
0x02, 0x93, 0x26, 0x01,
0x35, 0x6a, 0x26, 0x01,
- 0x00, 0x65, 0x9c, 0x5e,
- 0x00, 0x65, 0x9c, 0x5e,
+ 0x00, 0x65, 0x9e, 0x5e,
+ 0x00, 0x65, 0x9e, 0x5e,
0x02, 0x93, 0x26, 0x01,
0xbf, 0x3c, 0x78, 0x08,
- 0x04, 0x0b, 0xe6, 0x6b,
- 0x10, 0x0c, 0xe2, 0x7b,
- 0x01, 0x03, 0xe6, 0x6b,
- 0x20, 0x93, 0xe8, 0x6b,
- 0x04, 0x0b, 0xee, 0x6b,
+ 0x04, 0x0b, 0xe8, 0x6b,
+ 0x10, 0x0c, 0xe4, 0x7b,
+ 0x01, 0x03, 0xe8, 0x6b,
+ 0x20, 0x93, 0xea, 0x6b,
+ 0x04, 0x0b, 0xf0, 0x6b,
0x40, 0x3c, 0x78, 0x00,
0xc7, 0x93, 0x26, 0x09,
- 0x38, 0x93, 0xf0, 0x6b,
+ 0x38, 0x93, 0xf2, 0x6b,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0x3c, 0x56, 0x6c,
+ 0x80, 0x3c, 0x58, 0x6c,
0x01, 0x06, 0x50, 0x31,
0x80, 0xb8, 0x70, 0x01,
0x00, 0x65, 0xcc, 0x41,
0x10, 0x3f, 0x06, 0x00,
0x10, 0x6a, 0x06, 0x00,
0x01, 0x3a, 0xca, 0x30,
- 0x80, 0x65, 0x1c, 0x64,
- 0x10, 0xb8, 0x40, 0x6c,
+ 0x80, 0x65, 0x1e, 0x64,
+ 0x10, 0xb8, 0x42, 0x6c,
0xc0, 0x3e, 0xca, 0x00,
- 0x40, 0xb8, 0x0c, 0x6c,
+ 0x40, 0xb8, 0x0e, 0x6c,
0xbf, 0x65, 0xca, 0x08,
- 0x20, 0xb8, 0x20, 0x7c,
+ 0x20, 0xb8, 0x22, 0x7c,
0x01, 0x65, 0x0c, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0x28, 0x64,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0x2a, 0x64,
0x23, 0xb8, 0x0c, 0x08,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0x28, 0x64,
- 0x00, 0xbb, 0x20, 0x44,
- 0xff, 0x65, 0x20, 0x64,
- 0x00, 0x65, 0x40, 0x44,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0x2a, 0x64,
+ 0x00, 0xbb, 0x22, 0x44,
+ 0xff, 0x65, 0x22, 0x64,
+ 0x00, 0x65, 0x42, 0x44,
0x40, 0x6a, 0x18, 0x00,
0x01, 0x65, 0x0c, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0xfc, 0x73,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0xfe, 0x73,
0x40, 0x6a, 0x18, 0x00,
0x01, 0x3a, 0xa6, 0x30,
0x08, 0x6a, 0x74, 0x00,
0x00, 0x65, 0xcc, 0x41,
- 0x64, 0x6a, 0x68, 0x5d,
- 0x80, 0x64, 0xd8, 0x6c,
- 0x04, 0x64, 0x9a, 0x74,
- 0x02, 0x64, 0xaa, 0x74,
- 0x00, 0x6a, 0x60, 0x74,
- 0x03, 0x64, 0xc8, 0x74,
- 0x23, 0x64, 0x48, 0x74,
- 0x08, 0x64, 0x5c, 0x74,
- 0x61, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x64, 0x6a, 0x6a, 0x5d,
+ 0x80, 0x64, 0xda, 0x6c,
+ 0x04, 0x64, 0x9c, 0x74,
+ 0x02, 0x64, 0xac, 0x74,
+ 0x00, 0x6a, 0x62, 0x74,
+ 0x03, 0x64, 0xca, 0x74,
+ 0x23, 0x64, 0x4a, 0x74,
+ 0x08, 0x64, 0x5e, 0x74,
+ 0x61, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0xda, 0x5d,
0x08, 0x51, 0xce, 0x71,
- 0x00, 0x65, 0x40, 0x44,
- 0x80, 0x04, 0x5a, 0x7c,
- 0x51, 0x6a, 0x5e, 0x5d,
- 0x01, 0x51, 0x5a, 0x64,
- 0x01, 0xa4, 0x52, 0x7c,
- 0x80, 0xba, 0x5c, 0x6c,
- 0x41, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
- 0x21, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
- 0x07, 0x6a, 0x54, 0x5d,
+ 0x00, 0x65, 0x42, 0x44,
+ 0x80, 0x04, 0x5c, 0x7c,
+ 0x51, 0x6a, 0x60, 0x5d,
+ 0x01, 0x51, 0x5c, 0x64,
+ 0x01, 0xa4, 0x54, 0x7c,
+ 0x80, 0xba, 0x5e, 0x6c,
+ 0x41, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x21, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x07, 0x6a, 0x56, 0x5d,
0x01, 0x06, 0xd4, 0x30,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0xb8, 0x56, 0x7c,
- 0xc0, 0x3c, 0x6a, 0x7c,
- 0x80, 0x3c, 0x56, 0x6c,
- 0xff, 0xa8, 0x6a, 0x6c,
- 0x40, 0x3c, 0x56, 0x6c,
- 0x10, 0xb8, 0x6e, 0x7c,
- 0xa1, 0x6a, 0xd8, 0x5e,
- 0x01, 0xb4, 0x74, 0x6c,
- 0x02, 0xb4, 0x76, 0x6c,
- 0x01, 0xa4, 0x76, 0x7c,
- 0xff, 0xa8, 0x86, 0x7c,
+ 0x80, 0xb8, 0x58, 0x7c,
+ 0xc0, 0x3c, 0x6c, 0x7c,
+ 0x80, 0x3c, 0x58, 0x6c,
+ 0xff, 0xa8, 0x6c, 0x6c,
+ 0x40, 0x3c, 0x58, 0x6c,
+ 0x10, 0xb8, 0x70, 0x7c,
+ 0xa1, 0x6a, 0xda, 0x5e,
+ 0x01, 0xb4, 0x76, 0x6c,
+ 0x02, 0xb4, 0x78, 0x6c,
+ 0x01, 0xa4, 0x78, 0x7c,
+ 0xff, 0xa8, 0x88, 0x7c,
0x04, 0xb4, 0x68, 0x01,
0x01, 0x6a, 0x76, 0x00,
- 0x00, 0xbb, 0x12, 0x5e,
- 0xff, 0xa8, 0x86, 0x7c,
- 0x71, 0x6a, 0xd8, 0x5e,
- 0x40, 0x51, 0x86, 0x64,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0xbb, 0x14, 0x5e,
+ 0xff, 0xa8, 0x88, 0x7c,
+ 0x71, 0x6a, 0xda, 0x5e,
+ 0x40, 0x51, 0x88, 0x64,
+ 0x00, 0x65, 0xb4, 0x5e,
0x00, 0x65, 0xde, 0x41,
- 0x00, 0xbb, 0x8a, 0x5c,
+ 0x00, 0xbb, 0x8c, 0x5c,
0x00, 0x65, 0xde, 0x41,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0x65, 0xb4, 0x5e,
0x01, 0x65, 0xa2, 0x30,
0x01, 0xf8, 0xc8, 0x30,
0x01, 0x4e, 0xc8, 0x30,
- 0x00, 0x6a, 0xb6, 0xdd,
- 0x00, 0x51, 0xc8, 0x5d,
+ 0x00, 0x6a, 0xb8, 0xdd,
+ 0x00, 0x51, 0xca, 0x5d,
0x01, 0x4e, 0x9c, 0x18,
0x02, 0x6a, 0x22, 0x05,
- 0xc0, 0x3c, 0x56, 0x6c,
+ 0xc0, 0x3c, 0x58, 0x6c,
0x04, 0xb8, 0x70, 0x01,
- 0x00, 0x65, 0xd4, 0x5e,
+ 0x00, 0x65, 0xd6, 0x5e,
0x20, 0xb8, 0xde, 0x69,
0x01, 0xbb, 0xa2, 0x30,
0x3f, 0xba, 0x7c, 0x08,
- 0x00, 0xb9, 0xce, 0x5c,
+ 0x00, 0xb9, 0xd0, 0x5c,
0x00, 0x65, 0xde, 0x41,
0x01, 0x06, 0xd4, 0x30,
0x20, 0x3c, 0xcc, 0x79,
- 0x20, 0x3c, 0x5c, 0x7c,
- 0x01, 0xa4, 0xb8, 0x7c,
+ 0x20, 0x3c, 0x5e, 0x7c,
+ 0x01, 0xa4, 0xba, 0x7c,
0x01, 0xb4, 0x68, 0x01,
0x00, 0x65, 0xcc, 0x41,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x00, 0x65, 0x5e, 0x44,
0x04, 0x14, 0x58, 0x31,
0x01, 0x06, 0xd4, 0x30,
0x08, 0xa0, 0x60, 0x31,
0xac, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0xf4, 0x5d,
+ 0x14, 0x6a, 0xf6, 0x5d,
0x01, 0x06, 0xd4, 0x30,
- 0xa0, 0x6a, 0xec, 0x5d,
+ 0xa0, 0x6a, 0xee, 0x5d,
0x00, 0x65, 0xcc, 0x41,
0xdf, 0x3c, 0x78, 0x08,
0x12, 0x01, 0x02, 0x00,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x00, 0x65, 0x5e, 0x44,
0x4c, 0x65, 0xcc, 0x28,
0x01, 0x3e, 0x20, 0x31,
0xd0, 0x66, 0xcc, 0x18,
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = {
0xd0, 0x65, 0xca, 0x18,
0x01, 0x3e, 0x20, 0x31,
0x30, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xe6, 0x4c,
+ 0x00, 0x65, 0xe8, 0x4c,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x20, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xee, 0x54,
+ 0x00, 0x65, 0xf0, 0x54,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x20, 0x65, 0xca, 0x18,
0xe0, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xf8, 0x4c,
+ 0x00, 0x65, 0xfa, 0x4c,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0xd0, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0x00, 0x55,
+ 0x00, 0x65, 0x02, 0x55,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x01, 0x6c, 0xa2, 0x30,
- 0xff, 0x51, 0x12, 0x75,
- 0x00, 0x51, 0x8e, 0x5d,
+ 0xff, 0x51, 0x14, 0x75,
+ 0x00, 0x51, 0x90, 0x5d,
0x01, 0x51, 0x20, 0x31,
- 0x00, 0x65, 0x34, 0x45,
+ 0x00, 0x65, 0x36, 0x45,
0x3f, 0xba, 0xc8, 0x08,
- 0x00, 0x3e, 0x34, 0x75,
- 0x00, 0x65, 0xb0, 0x5e,
+ 0x00, 0x3e, 0x36, 0x75,
+ 0x00, 0x65, 0xb2, 0x5e,
0x80, 0x3c, 0x78, 0x00,
0x01, 0x06, 0xd4, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x00, 0x65, 0xda, 0x5d,
0x01, 0x3c, 0x78, 0x00,
- 0xe0, 0x3f, 0x50, 0x65,
+ 0xe0, 0x3f, 0x52, 0x65,
0x02, 0x3c, 0x78, 0x00,
- 0x20, 0x12, 0x50, 0x65,
- 0x51, 0x6a, 0x5e, 0x5d,
- 0x00, 0x51, 0x8e, 0x5d,
- 0x51, 0x6a, 0x5e, 0x5d,
+ 0x20, 0x12, 0x52, 0x65,
+ 0x51, 0x6a, 0x60, 0x5d,
+ 0x00, 0x51, 0x90, 0x5d,
+ 0x51, 0x6a, 0x60, 0x5d,
0x01, 0x51, 0x20, 0x31,
0x04, 0x3c, 0x78, 0x00,
0x01, 0xb9, 0xc8, 0x30,
- 0x00, 0x3d, 0x4e, 0x65,
+ 0x00, 0x3d, 0x50, 0x65,
0x08, 0x3c, 0x78, 0x00,
0x3f, 0xba, 0xc8, 0x08,
- 0x00, 0x3e, 0x4e, 0x65,
+ 0x00, 0x3e, 0x50, 0x65,
0x10, 0x3c, 0x78, 0x00,
- 0x04, 0xb8, 0x4e, 0x7d,
+ 0x04, 0xb8, 0x50, 0x7d,
0xfb, 0xb8, 0x70, 0x09,
- 0x20, 0xb8, 0x44, 0x6d,
+ 0x20, 0xb8, 0x46, 0x6d,
0x01, 0x90, 0xc8, 0x30,
0xff, 0x6a, 0xa2, 0x00,
- 0x00, 0x3d, 0xce, 0x5c,
+ 0x00, 0x3d, 0xd0, 0x5c,
0x01, 0x64, 0x20, 0x31,
0xff, 0x6a, 0x78, 0x08,
0x00, 0x65, 0xea, 0x58,
- 0x10, 0xb8, 0x5c, 0x7c,
- 0xff, 0x6a, 0x54, 0x5d,
- 0x00, 0x65, 0x5c, 0x44,
- 0x00, 0x65, 0xb0, 0x5e,
- 0x31, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x10, 0xb8, 0x5e, 0x7c,
+ 0xff, 0x6a, 0x56, 0x5d,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x00, 0x65, 0xb2, 0x5e,
+ 0x31, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
0x10, 0x3f, 0x06, 0x00,
0x10, 0x6a, 0x06, 0x00,
0x01, 0x65, 0x74, 0x34,
- 0x81, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x60, 0x45,
+ 0x81, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x62, 0x45,
0x01, 0x06, 0xd4, 0x30,
- 0x01, 0x0c, 0x60, 0x7d,
- 0x04, 0x0c, 0x5a, 0x6d,
+ 0x01, 0x0c, 0x62, 0x7d,
+ 0x04, 0x0c, 0x5c, 0x6d,
0xe0, 0x03, 0x7e, 0x08,
0xe0, 0x3f, 0xcc, 0x61,
0x01, 0x65, 0xcc, 0x30,
0x01, 0x12, 0xda, 0x34,
0x01, 0x06, 0xd4, 0x34,
- 0x01, 0x03, 0x6e, 0x6d,
+ 0x01, 0x03, 0x70, 0x6d,
0x40, 0x03, 0xcc, 0x08,
0x01, 0x65, 0x06, 0x30,
0x40, 0x65, 0xc8, 0x08,
- 0x00, 0x66, 0x7c, 0x75,
- 0x40, 0x65, 0x7c, 0x7d,
- 0x00, 0x65, 0x7c, 0x5d,
+ 0x00, 0x66, 0x7e, 0x75,
+ 0x40, 0x65, 0x7e, 0x7d,
+ 0x00, 0x65, 0x7e, 0x5d,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x0c,
0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0x86, 0x7d,
+ 0x02, 0x0b, 0x88, 0x7d,
0x01, 0x65, 0x0c, 0x30,
- 0x02, 0x0b, 0x8a, 0x7d,
+ 0x02, 0x0b, 0x8c, 0x7d,
0xf7, 0x01, 0x02, 0x0c,
0x01, 0x65, 0xc8, 0x30,
- 0xff, 0x41, 0xae, 0x75,
+ 0xff, 0x41, 0xb0, 0x75,
0x01, 0x41, 0x20, 0x31,
0xff, 0x6a, 0xa4, 0x00,
- 0x00, 0x65, 0x9e, 0x45,
- 0xff, 0xbf, 0xae, 0x75,
+ 0x00, 0x65, 0xa0, 0x45,
+ 0xff, 0xbf, 0xb0, 0x75,
0x01, 0x90, 0xa4, 0x30,
0x01, 0xbf, 0x20, 0x31,
- 0x00, 0xbb, 0x98, 0x65,
- 0xff, 0x52, 0xac, 0x75,
+ 0x00, 0xbb, 0x9a, 0x65,
+ 0xff, 0x52, 0xae, 0x75,
0x01, 0xbf, 0xcc, 0x30,
0x01, 0x90, 0xca, 0x30,
0x01, 0x52, 0x20, 0x31,
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = {
0x01, 0x65, 0x20, 0x35,
0x01, 0xbf, 0x82, 0x34,
0x01, 0x64, 0xa2, 0x30,
- 0x00, 0x6a, 0xc0, 0x5e,
+ 0x00, 0x6a, 0xc2, 0x5e,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x51, 0x12, 0x46,
+ 0x00, 0x51, 0x14, 0x46,
0x01, 0x65, 0xa4, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0x06, 0x5e,
+ 0x48, 0x6a, 0x08, 0x5e,
0x01, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x05,
0x88, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0x06, 0x5e,
- 0x01, 0x6a, 0xe0, 0x5d,
+ 0x48, 0x6a, 0x08, 0x5e,
+ 0x01, 0x6a, 0xe2, 0x5d,
0x01, 0x6a, 0x26, 0x05,
0x01, 0x65, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0xcc, 0x7d,
+ 0x80, 0xee, 0xce, 0x7d,
0xff, 0x6a, 0xdc, 0x0d,
0x01, 0x65, 0x32, 0x31,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x46,
- 0x81, 0x6a, 0xd8, 0x5e,
- 0x01, 0x0c, 0xd8, 0x7d,
- 0x04, 0x0c, 0xd6, 0x6d,
+ 0x00, 0x65, 0xaa, 0x46,
+ 0x81, 0x6a, 0xda, 0x5e,
+ 0x01, 0x0c, 0xda, 0x7d,
+ 0x04, 0x0c, 0xd8, 0x6d,
0xe0, 0x03, 0x06, 0x08,
0xe0, 0x03, 0x7e, 0x0c,
0x01, 0x65, 0x18, 0x31,
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = {
0x01, 0x6c, 0xda, 0x34,
0x3d, 0x64, 0xa4, 0x28,
0x55, 0x64, 0xc8, 0x28,
- 0x00, 0x65, 0x06, 0x46,
+ 0x00, 0x65, 0x08, 0x46,
0x2e, 0x64, 0xa4, 0x28,
0x66, 0x64, 0xc8, 0x28,
0x00, 0x6c, 0xda, 0x18,
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = {
0x00, 0x6c, 0xda, 0x24,
0x01, 0x65, 0xc8, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x44, 0x6a, 0x02, 0x5e,
+ 0x44, 0x6a, 0x04, 0x5e,
0x01, 0x90, 0xe2, 0x31,
- 0x04, 0x3b, 0x26, 0x7e,
+ 0x04, 0x3b, 0x28, 0x7e,
0x30, 0x6a, 0xd0, 0x01,
0x20, 0x6a, 0xd0, 0x01,
0x1d, 0x6a, 0xdc, 0x01,
- 0xdc, 0xee, 0x22, 0x66,
- 0x00, 0x65, 0x3e, 0x46,
+ 0xdc, 0xee, 0x24, 0x66,
+ 0x00, 0x65, 0x40, 0x46,
0x20, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x01,
0x20, 0xa0, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0x2e, 0x7e,
+ 0x80, 0xee, 0x30, 0x7e,
0x11, 0x6a, 0xdc, 0x01,
- 0x50, 0xee, 0x32, 0x66,
+ 0x50, 0xee, 0x34, 0x66,
0x20, 0x6a, 0xd0, 0x01,
0x09, 0x6a, 0xdc, 0x01,
- 0x88, 0xee, 0x38, 0x66,
+ 0x88, 0xee, 0x3a, 0x66,
0x19, 0x6a, 0xdc, 0x01,
- 0xd8, 0xee, 0x3c, 0x66,
+ 0xd8, 0xee, 0x3e, 0x66,
0xff, 0x6a, 0xdc, 0x09,
- 0x18, 0xee, 0x40, 0x6e,
+ 0x18, 0xee, 0x42, 0x6e,
0xff, 0x6a, 0xd4, 0x0c,
0x88, 0x6a, 0xcc, 0x00,
- 0x44, 0x6a, 0x02, 0x5e,
- 0x20, 0x6a, 0xe0, 0x5d,
+ 0x44, 0x6a, 0x04, 0x5e,
+ 0x20, 0x6a, 0xe2, 0x5d,
0x01, 0x3b, 0x26, 0x31,
- 0x04, 0x3b, 0x5a, 0x6e,
+ 0x04, 0x3b, 0x5c, 0x6e,
0xa0, 0x6a, 0xca, 0x00,
0x20, 0x65, 0xc8, 0x18,
- 0x00, 0x65, 0x98, 0x5e,
- 0x00, 0x65, 0x52, 0x66,
+ 0x00, 0x65, 0x9a, 0x5e,
+ 0x00, 0x65, 0x54, 0x66,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x46,
+ 0x00, 0x65, 0xaa, 0x46,
0xa0, 0x6a, 0xcc, 0x00,
0xff, 0x6a, 0xc8, 0x08,
- 0x20, 0x94, 0x5e, 0x6e,
- 0x10, 0x94, 0x60, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
+ 0x20, 0x94, 0x60, 0x6e,
+ 0x10, 0x94, 0x62, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
0xff, 0x8c, 0xc8, 0x10,
0xc1, 0x64, 0xc8, 0x18,
0xf8, 0x64, 0xc8, 0x08,
0x01, 0x99, 0xda, 0x30,
- 0x00, 0x66, 0x6e, 0x66,
- 0xc0, 0x66, 0xaa, 0x76,
+ 0x00, 0x66, 0x70, 0x66,
+ 0xc0, 0x66, 0xac, 0x76,
0x60, 0x66, 0xc8, 0x18,
0x3d, 0x64, 0xc8, 0x28,
- 0x00, 0x65, 0x5e, 0x46,
+ 0x00, 0x65, 0x60, 0x46,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0x7c, 0x6e,
+ 0x08, 0x93, 0x7e, 0x6e,
0x00, 0x62, 0xc4, 0x18,
- 0x00, 0x65, 0xa8, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
0x01, 0x99, 0xda, 0x30,
0x01, 0x99, 0xda, 0x30,
0x01, 0x99, 0xda, 0x30,
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = {
0x01, 0x6c, 0x32, 0x31,
0x01, 0x6c, 0x32, 0x31,
0x01, 0x6c, 0x32, 0x35,
- 0x08, 0x94, 0xa8, 0x7e,
+ 0x08, 0x94, 0xaa, 0x7e,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0xac, 0x6e,
+ 0x08, 0x93, 0xae, 0x6e,
0xff, 0x6a, 0xd4, 0x0c,
- 0x04, 0xb8, 0xd4, 0x6e,
+ 0x04, 0xb8, 0xd6, 0x6e,
0x01, 0x42, 0x7e, 0x31,
0xff, 0x6a, 0x76, 0x01,
0x01, 0x90, 0x84, 0x34,
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = {
0x01, 0x85, 0x0a, 0x01,
0x7f, 0x65, 0x10, 0x09,
0xfe, 0x85, 0x0a, 0x0d,
- 0xff, 0x42, 0xd0, 0x66,
- 0xff, 0x41, 0xc8, 0x66,
- 0xd1, 0x6a, 0xd8, 0x5e,
+ 0xff, 0x42, 0xd2, 0x66,
+ 0xff, 0x41, 0xca, 0x66,
+ 0xd1, 0x6a, 0xda, 0x5e,
0xff, 0x6a, 0xca, 0x04,
0x01, 0x41, 0x20, 0x31,
0x01, 0xbf, 0x82, 0x30,
0x01, 0x6a, 0x76, 0x00,
- 0x00, 0xbb, 0x12, 0x46,
+ 0x00, 0xbb, 0x14, 0x46,
0x01, 0x42, 0x20, 0x31,
0x01, 0xbf, 0x84, 0x34,
0x01, 0x41, 0x7e, 0x31,
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func;
static int
ahc_patch17_func(struct ahc_softc *ahc)
{
- return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0);
+ return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0);
}
static ahc_patch_func_t ahc_patch16_func;
@@ -1142,152 +1143,152 @@ static struct patch {
{ ahc_patch0_func, 196, 1, 1 },
{ ahc_patch9_func, 212, 6, 2 },
{ ahc_patch0_func, 218, 6, 1 },
- { ahc_patch8_func, 226, 20, 2 },
+ { ahc_patch8_func, 226, 21, 2 },
{ ahc_patch1_func, 241, 1, 1 },
- { ahc_patch1_func, 248, 1, 2 },
- { ahc_patch0_func, 249, 2, 2 },
- { ahc_patch11_func, 250, 1, 1 },
- { ahc_patch9_func, 258, 27, 3 },
- { ahc_patch1_func, 274, 10, 2 },
- { ahc_patch13_func, 277, 1, 1 },
- { ahc_patch14_func, 285, 14, 1 },
- { ahc_patch1_func, 301, 1, 2 },
- { ahc_patch0_func, 302, 1, 1 },
- { ahc_patch9_func, 305, 1, 1 },
- { ahc_patch13_func, 310, 1, 1 },
- { ahc_patch9_func, 311, 2, 2 },
- { ahc_patch0_func, 313, 4, 1 },
- { ahc_patch14_func, 317, 1, 1 },
- { ahc_patch15_func, 319, 2, 3 },
- { ahc_patch9_func, 319, 1, 2 },
- { ahc_patch0_func, 320, 1, 1 },
- { ahc_patch6_func, 325, 1, 2 },
- { ahc_patch0_func, 326, 1, 1 },
- { ahc_patch1_func, 330, 47, 11 },
- { ahc_patch6_func, 337, 2, 4 },
- { ahc_patch7_func, 337, 1, 1 },
- { ahc_patch8_func, 338, 1, 1 },
- { ahc_patch0_func, 339, 1, 1 },
- { ahc_patch16_func, 340, 1, 1 },
- { ahc_patch6_func, 356, 6, 3 },
- { ahc_patch16_func, 356, 5, 1 },
- { ahc_patch0_func, 362, 7, 1 },
- { ahc_patch13_func, 372, 5, 1 },
- { ahc_patch0_func, 377, 52, 17 },
- { ahc_patch14_func, 377, 1, 1 },
- { ahc_patch7_func, 379, 2, 2 },
- { ahc_patch17_func, 380, 1, 1 },
- { ahc_patch9_func, 383, 1, 1 },
- { ahc_patch18_func, 390, 1, 1 },
- { ahc_patch14_func, 395, 9, 3 },
- { ahc_patch9_func, 396, 3, 2 },
- { ahc_patch0_func, 399, 3, 1 },
- { ahc_patch9_func, 407, 6, 2 },
- { ahc_patch0_func, 413, 9, 2 },
- { ahc_patch13_func, 413, 1, 1 },
- { ahc_patch13_func, 422, 2, 1 },
- { ahc_patch14_func, 424, 1, 1 },
- { ahc_patch9_func, 426, 1, 2 },
- { ahc_patch0_func, 427, 1, 1 },
- { ahc_patch7_func, 428, 1, 1 },
+ { ahc_patch1_func, 249, 1, 2 },
+ { ahc_patch0_func, 250, 2, 2 },
+ { ahc_patch11_func, 251, 1, 1 },
+ { ahc_patch9_func, 259, 27, 3 },
+ { ahc_patch1_func, 275, 10, 2 },
+ { ahc_patch13_func, 278, 1, 1 },
+ { ahc_patch14_func, 286, 14, 1 },
+ { ahc_patch1_func, 302, 1, 2 },
+ { ahc_patch0_func, 303, 1, 1 },
+ { ahc_patch9_func, 306, 1, 1 },
+ { ahc_patch13_func, 311, 1, 1 },
+ { ahc_patch9_func, 312, 2, 2 },
+ { ahc_patch0_func, 314, 4, 1 },
+ { ahc_patch14_func, 318, 1, 1 },
+ { ahc_patch15_func, 320, 2, 3 },
+ { ahc_patch9_func, 320, 1, 2 },
+ { ahc_patch0_func, 321, 1, 1 },
+ { ahc_patch6_func, 326, 1, 2 },
+ { ahc_patch0_func, 327, 1, 1 },
+ { ahc_patch1_func, 331, 47, 11 },
+ { ahc_patch6_func, 338, 2, 4 },
+ { ahc_patch7_func, 338, 1, 1 },
+ { ahc_patch8_func, 339, 1, 1 },
+ { ahc_patch0_func, 340, 1, 1 },
+ { ahc_patch16_func, 341, 1, 1 },
+ { ahc_patch6_func, 357, 6, 3 },
+ { ahc_patch16_func, 357, 5, 1 },
+ { ahc_patch0_func, 363, 7, 1 },
+ { ahc_patch13_func, 373, 5, 1 },
+ { ahc_patch0_func, 378, 52, 17 },
+ { ahc_patch14_func, 378, 1, 1 },
+ { ahc_patch7_func, 380, 2, 2 },
+ { ahc_patch17_func, 381, 1, 1 },
+ { ahc_patch9_func, 384, 1, 1 },
+ { ahc_patch18_func, 391, 1, 1 },
+ { ahc_patch14_func, 396, 9, 3 },
+ { ahc_patch9_func, 397, 3, 2 },
+ { ahc_patch0_func, 400, 3, 1 },
+ { ahc_patch9_func, 408, 6, 2 },
+ { ahc_patch0_func, 414, 9, 2 },
+ { ahc_patch13_func, 414, 1, 1 },
+ { ahc_patch13_func, 423, 2, 1 },
+ { ahc_patch14_func, 425, 1, 1 },
+ { ahc_patch9_func, 427, 1, 2 },
+ { ahc_patch0_func, 428, 1, 1 },
{ ahc_patch7_func, 429, 1, 1 },
- { ahc_patch8_func, 430, 3, 3 },
- { ahc_patch6_func, 431, 1, 2 },
- { ahc_patch0_func, 432, 1, 1 },
- { ahc_patch9_func, 433, 1, 1 },
- { ahc_patch15_func, 434, 1, 2 },
- { ahc_patch13_func, 434, 1, 1 },
- { ahc_patch14_func, 436, 9, 4 },
- { ahc_patch9_func, 436, 1, 1 },
- { ahc_patch9_func, 443, 2, 1 },
- { ahc_patch0_func, 445, 4, 3 },
- { ahc_patch9_func, 445, 1, 2 },
- { ahc_patch0_func, 446, 3, 1 },
- { ahc_patch1_func, 450, 2, 1 },
- { ahc_patch7_func, 452, 10, 2 },
- { ahc_patch0_func, 462, 1, 1 },
- { ahc_patch8_func, 463, 118, 22 },
- { ahc_patch1_func, 465, 3, 2 },
- { ahc_patch0_func, 468, 5, 3 },
- { ahc_patch9_func, 468, 2, 2 },
- { ahc_patch0_func, 470, 3, 1 },
- { ahc_patch1_func, 475, 2, 2 },
- { ahc_patch0_func, 477, 6, 3 },
- { ahc_patch9_func, 477, 2, 2 },
- { ahc_patch0_func, 479, 3, 1 },
- { ahc_patch1_func, 485, 2, 2 },
- { ahc_patch0_func, 487, 9, 7 },
- { ahc_patch9_func, 487, 5, 6 },
- { ahc_patch19_func, 487, 1, 2 },
- { ahc_patch0_func, 488, 1, 1 },
- { ahc_patch19_func, 490, 1, 2 },
- { ahc_patch0_func, 491, 1, 1 },
- { ahc_patch0_func, 492, 4, 1 },
- { ahc_patch6_func, 497, 3, 2 },
- { ahc_patch0_func, 500, 1, 1 },
- { ahc_patch6_func, 510, 1, 2 },
- { ahc_patch0_func, 511, 1, 1 },
- { ahc_patch20_func, 548, 7, 1 },
- { ahc_patch3_func, 583, 1, 2 },
- { ahc_patch0_func, 584, 1, 1 },
- { ahc_patch21_func, 587, 1, 1 },
- { ahc_patch8_func, 589, 106, 33 },
- { ahc_patch4_func, 591, 1, 1 },
- { ahc_patch1_func, 597, 2, 2 },
- { ahc_patch0_func, 599, 1, 1 },
- { ahc_patch1_func, 602, 1, 2 },
- { ahc_patch0_func, 603, 1, 1 },
- { ahc_patch9_func, 604, 3, 3 },
- { ahc_patch15_func, 605, 1, 1 },
- { ahc_patch0_func, 607, 4, 1 },
- { ahc_patch19_func, 616, 2, 2 },
- { ahc_patch0_func, 618, 1, 1 },
- { ahc_patch19_func, 622, 10, 3 },
- { ahc_patch5_func, 624, 8, 1 },
- { ahc_patch0_func, 632, 9, 2 },
- { ahc_patch5_func, 633, 8, 1 },
- { ahc_patch4_func, 643, 1, 2 },
- { ahc_patch0_func, 644, 1, 1 },
- { ahc_patch19_func, 645, 1, 2 },
- { ahc_patch0_func, 646, 3, 2 },
- { ahc_patch4_func, 648, 1, 1 },
- { ahc_patch5_func, 649, 1, 1 },
- { ahc_patch5_func, 652, 1, 1 },
- { ahc_patch5_func, 654, 1, 1 },
- { ahc_patch4_func, 656, 2, 2 },
- { ahc_patch0_func, 658, 2, 1 },
- { ahc_patch5_func, 660, 1, 1 },
- { ahc_patch5_func, 663, 1, 1 },
- { ahc_patch5_func, 666, 1, 1 },
- { ahc_patch19_func, 670, 1, 1 },
- { ahc_patch19_func, 673, 1, 1 },
- { ahc_patch4_func, 679, 1, 1 },
- { ahc_patch6_func, 682, 1, 2 },
- { ahc_patch0_func, 683, 1, 1 },
- { ahc_patch7_func, 695, 16, 1 },
- { ahc_patch4_func, 711, 20, 1 },
- { ahc_patch9_func, 732, 4, 2 },
- { ahc_patch0_func, 736, 4, 1 },
- { ahc_patch9_func, 740, 4, 2 },
- { ahc_patch0_func, 744, 3, 1 },
- { ahc_patch6_func, 750, 1, 1 },
- { ahc_patch22_func, 752, 14, 1 },
- { ahc_patch7_func, 766, 3, 1 },
- { ahc_patch9_func, 778, 24, 8 },
- { ahc_patch19_func, 782, 1, 2 },
- { ahc_patch0_func, 783, 1, 1 },
- { ahc_patch15_func, 788, 4, 2 },
- { ahc_patch0_func, 792, 7, 3 },
- { ahc_patch23_func, 792, 5, 2 },
- { ahc_patch0_func, 797, 2, 1 },
- { ahc_patch0_func, 802, 42, 3 },
- { ahc_patch18_func, 814, 18, 2 },
- { ahc_patch0_func, 832, 1, 1 },
- { ahc_patch4_func, 856, 1, 1 },
- { ahc_patch4_func, 857, 3, 2 },
- { ahc_patch0_func, 860, 1, 1 },
- { ahc_patch13_func, 861, 3, 1 },
- { ahc_patch4_func, 864, 12, 1 }
+ { ahc_patch7_func, 430, 1, 1 },
+ { ahc_patch8_func, 431, 3, 3 },
+ { ahc_patch6_func, 432, 1, 2 },
+ { ahc_patch0_func, 433, 1, 1 },
+ { ahc_patch9_func, 434, 1, 1 },
+ { ahc_patch15_func, 435, 1, 2 },
+ { ahc_patch13_func, 435, 1, 1 },
+ { ahc_patch14_func, 437, 9, 4 },
+ { ahc_patch9_func, 437, 1, 1 },
+ { ahc_patch9_func, 444, 2, 1 },
+ { ahc_patch0_func, 446, 4, 3 },
+ { ahc_patch9_func, 446, 1, 2 },
+ { ahc_patch0_func, 447, 3, 1 },
+ { ahc_patch1_func, 451, 2, 1 },
+ { ahc_patch7_func, 453, 10, 2 },
+ { ahc_patch0_func, 463, 1, 1 },
+ { ahc_patch8_func, 464, 118, 22 },
+ { ahc_patch1_func, 466, 3, 2 },
+ { ahc_patch0_func, 469, 5, 3 },
+ { ahc_patch9_func, 469, 2, 2 },
+ { ahc_patch0_func, 471, 3, 1 },
+ { ahc_patch1_func, 476, 2, 2 },
+ { ahc_patch0_func, 478, 6, 3 },
+ { ahc_patch9_func, 478, 2, 2 },
+ { ahc_patch0_func, 480, 3, 1 },
+ { ahc_patch1_func, 486, 2, 2 },
+ { ahc_patch0_func, 488, 9, 7 },
+ { ahc_patch9_func, 488, 5, 6 },
+ { ahc_patch19_func, 488, 1, 2 },
+ { ahc_patch0_func, 489, 1, 1 },
+ { ahc_patch19_func, 491, 1, 2 },
+ { ahc_patch0_func, 492, 1, 1 },
+ { ahc_patch0_func, 493, 4, 1 },
+ { ahc_patch6_func, 498, 3, 2 },
+ { ahc_patch0_func, 501, 1, 1 },
+ { ahc_patch6_func, 511, 1, 2 },
+ { ahc_patch0_func, 512, 1, 1 },
+ { ahc_patch20_func, 549, 7, 1 },
+ { ahc_patch3_func, 584, 1, 2 },
+ { ahc_patch0_func, 585, 1, 1 },
+ { ahc_patch21_func, 588, 1, 1 },
+ { ahc_patch8_func, 590, 106, 33 },
+ { ahc_patch4_func, 592, 1, 1 },
+ { ahc_patch1_func, 598, 2, 2 },
+ { ahc_patch0_func, 600, 1, 1 },
+ { ahc_patch1_func, 603, 1, 2 },
+ { ahc_patch0_func, 604, 1, 1 },
+ { ahc_patch9_func, 605, 3, 3 },
+ { ahc_patch15_func, 606, 1, 1 },
+ { ahc_patch0_func, 608, 4, 1 },
+ { ahc_patch19_func, 617, 2, 2 },
+ { ahc_patch0_func, 619, 1, 1 },
+ { ahc_patch19_func, 623, 10, 3 },
+ { ahc_patch5_func, 625, 8, 1 },
+ { ahc_patch0_func, 633, 9, 2 },
+ { ahc_patch5_func, 634, 8, 1 },
+ { ahc_patch4_func, 644, 1, 2 },
+ { ahc_patch0_func, 645, 1, 1 },
+ { ahc_patch19_func, 646, 1, 2 },
+ { ahc_patch0_func, 647, 3, 2 },
+ { ahc_patch4_func, 649, 1, 1 },
+ { ahc_patch5_func, 650, 1, 1 },
+ { ahc_patch5_func, 653, 1, 1 },
+ { ahc_patch5_func, 655, 1, 1 },
+ { ahc_patch4_func, 657, 2, 2 },
+ { ahc_patch0_func, 659, 2, 1 },
+ { ahc_patch5_func, 661, 1, 1 },
+ { ahc_patch5_func, 664, 1, 1 },
+ { ahc_patch5_func, 667, 1, 1 },
+ { ahc_patch19_func, 671, 1, 1 },
+ { ahc_patch19_func, 674, 1, 1 },
+ { ahc_patch4_func, 680, 1, 1 },
+ { ahc_patch6_func, 683, 1, 2 },
+ { ahc_patch0_func, 684, 1, 1 },
+ { ahc_patch7_func, 696, 16, 1 },
+ { ahc_patch4_func, 712, 20, 1 },
+ { ahc_patch9_func, 733, 4, 2 },
+ { ahc_patch0_func, 737, 4, 1 },
+ { ahc_patch9_func, 741, 4, 2 },
+ { ahc_patch0_func, 745, 3, 1 },
+ { ahc_patch6_func, 751, 1, 1 },
+ { ahc_patch22_func, 753, 14, 1 },
+ { ahc_patch7_func, 767, 3, 1 },
+ { ahc_patch9_func, 779, 24, 8 },
+ { ahc_patch19_func, 783, 1, 2 },
+ { ahc_patch0_func, 784, 1, 1 },
+ { ahc_patch15_func, 789, 4, 2 },
+ { ahc_patch0_func, 793, 7, 3 },
+ { ahc_patch23_func, 793, 5, 2 },
+ { ahc_patch0_func, 798, 2, 1 },
+ { ahc_patch0_func, 803, 42, 3 },
+ { ahc_patch18_func, 815, 18, 2 },
+ { ahc_patch0_func, 833, 1, 1 },
+ { ahc_patch4_func, 857, 1, 1 },
+ { ahc_patch4_func, 858, 3, 2 },
+ { ahc_patch0_func, 861, 1, 1 },
+ { ahc_patch13_func, 862, 3, 1 },
+ { ahc_patch4_func, 865, 12, 1 }
};
static struct cs {
@@ -1296,11 +1297,11 @@ static struct cs {
} critical_sections[] = {
{ 11, 18 },
{ 21, 30 },
- { 711, 727 },
- { 857, 860 },
- { 864, 870 },
- { 872, 874 },
- { 874, 876 }
+ { 712, 728 },
+ { 858, 861 },
+ { 865, 871 },
+ { 873, 875 },
+ { 875, 877 }
};
static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
index 7c5a6db0e672..828ae3d9a510 100644
--- a/drivers/scsi/aic7xxx/aiclib.c
+++ b/drivers/scsi/aic7xxx/aiclib.c
@@ -30,1382 +30,5 @@
* $Id$
*/
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-
-/* Core SCSI definitions */
-#include <scsi/scsi_host.h>
#include "aiclib.h"
-#include "cam.h"
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* FALSE */
-#ifndef TRUE
-#define TRUE 1
-#endif /* TRUE */
-#ifndef ERESTART
-#define ERESTART -1 /* restart syscall */
-#endif
-#ifndef EJUSTRETURN
-#define EJUSTRETURN -2 /* don't modify regs, just return */
-#endif
-
-static int ascentrycomp(const void *key, const void *member);
-static int senseentrycomp(const void *key, const void *member);
-static void fetchtableentries(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *,
- const struct sense_key_table_entry **,
- const struct asc_table_entry **);
-static void * scsibsearch(const void *key, const void *base, size_t nmemb,
- size_t size,
- int (*compar)(const void *, const void *));
-typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
-static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern,
- int str_len);
-static caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table,
- int num_entries, int entry_size,
- cam_quirkmatch_t *comp_func);
-
-#define SCSI_NO_SENSE_STRINGS 1
-#if !defined(SCSI_NO_SENSE_STRINGS)
-#define SST(asc, ascq, action, desc) \
- asc, ascq, action, desc
-#else
-static const char empty_string[] = "";
-
-#define SST(asc, ascq, action, desc) \
- asc, ascq, action, empty_string
-#endif
-
-static const struct sense_key_table_entry sense_key_table[] =
-{
- { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
- { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
- {
- SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
- "NOT READY"
- },
- { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
- { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
- { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
- { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
- { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
- { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
- { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
- { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
- { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
- { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
- { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
- { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
- { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
-};
-
-static const int sense_key_table_size =
- sizeof(sense_key_table)/sizeof(sense_key_table[0]);
-
-static struct asc_table_entry quantum_fireball_entries[] = {
- {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, initializing cmd. required")}
-};
-
-static struct asc_table_entry sony_mo_entries[] = {
- {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, cause not reportable")}
-};
-
-static struct scsi_sense_quirk_entry sense_quirk_table[] = {
- {
- /*
- * The Quantum Fireball ST and SE like to return 0x04 0x0b when
- * they really should return 0x04 0x02. 0x04,0x0b isn't
- * defined in any SCSI spec, and it isn't mentioned in the
- * hardware manual for these drives.
- */
- {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
- /*num_sense_keys*/0,
- sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
- /*sense key entries*/NULL,
- quantum_fireball_entries
- },
- {
- /*
- * This Sony MO drive likes to return 0x04, 0x00 when it
- * isn't spun up.
- */
- {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
- /*num_sense_keys*/0,
- sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
- /*sense key entries*/NULL,
- sony_mo_entries
- }
-};
-
-static const int sense_quirk_table_size =
- sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
-
-static struct asc_table_entry asc_table[] = {
-/*
- * From File: ASC-NUM.TXT
- * SCSI ASC/ASCQ Assignments
- * Numeric Sorted Listing
- * as of 5/12/97
- *
- * D - DIRECT ACCESS DEVICE (SBC) device column key
- * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
- * . L - PRINTER DEVICE (SSC) blank = reserved
- * . P - PROCESSOR DEVICE (SPC) not blank = allowed
- * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
- * . . R - CD DEVICE (MMC)
- * . . S - SCANNER DEVICE (SGC)
- * . . .O - OPTICAL MEMORY DEVICE (SBC)
- * . . . M - MEDIA CHANGER DEVICE (SMC)
- * . . . C - COMMUNICATION DEVICE (SSC)
- * . . . .A - STORAGE ARRAY DEVICE (SCC)
- * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
- * DTLPWRSOMCAE ASC ASCQ Action Description
- * ------------ ---- ---- ------ -----------------------------------*/
-/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
- "No additional sense information") },
-/* T S */{SST(0x00, 0x01, SS_RDEF,
- "Filemark detected") },
-/* T S */{SST(0x00, 0x02, SS_RDEF,
- "End-of-partition/medium detected") },
-/* T */{SST(0x00, 0x03, SS_RDEF,
- "Setmark detected") },
-/* T S */{SST(0x00, 0x04, SS_RDEF,
- "Beginning-of-partition/medium detected") },
-/* T S */{SST(0x00, 0x05, SS_RDEF,
- "End-of-data detected") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
- "I/O process terminated") },
-/* R */{SST(0x00, 0x11, SS_FATAL|EBUSY,
- "Audio play operation in progress") },
-/* R */{SST(0x00, 0x12, SS_NOP,
- "Audio play operation paused") },
-/* R */{SST(0x00, 0x13, SS_NOP,
- "Audio play operation successfully completed") },
-/* R */{SST(0x00, 0x14, SS_RDEF,
- "Audio play operation stopped due to error") },
-/* R */{SST(0x00, 0x15, SS_NOP,
- "No current audio status to return") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
- "Operation in progress") },
-/* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
- "Cleaning requested") },
-/* D W O */{SST(0x01, 0x00, SS_RDEF,
- "No index/sector signal") },
-/* D WR OM */{SST(0x02, 0x00, SS_RDEF,
- "No seek complete") },
-/* DTL W SO */{SST(0x03, 0x00, SS_RDEF,
- "Peripheral device write fault") },
-/* T */{SST(0x03, 0x01, SS_RDEF,
- "No write current") },
-/* T */{SST(0x03, 0x02, SS_RDEF,
- "Excessive write errors") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x00,
- SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
- "Logical unit not ready, cause not reportable") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x01,
- SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
- "Logical unit is in process of becoming ready") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, initializing cmd. required") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
- "Logical unit not ready, manual intervention required")},
-/* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY,
- "Logical unit not ready, format in progress") },
-/* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY,
- "Logical unit not ready, rebuild in progress") },
-/* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY,
- "Logical unit not ready, recalculation in progress") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
- "Logical unit not ready, operation in progress") },
-/* R */{SST(0x04, 0x08, SS_FATAL|EBUSY,
- "Logical unit not ready, long write in progress") },
-/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
- "Logical unit does not respond to selection") },
-/* D WR OM */{SST(0x06, 0x00, SS_RDEF,
- "No reference position found") },
-/* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF,
- "Multiple peripheral devices selected") },
-/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
- "Logical unit communication failure") },
-/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
- "Logical unit communication time-out") },
-/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
- "Logical unit communication parity error") },
-/* DT R OM */{SST(0x08, 0x03, SS_RDEF,
- "Logical unit communication crc error (ultra-dma/32)")},
-/* DT WR O */{SST(0x09, 0x00, SS_RDEF,
- "Track following error") },
-/* WR O */{SST(0x09, 0x01, SS_RDEF,
- "Tracking servo failure") },
-/* WR O */{SST(0x09, 0x02, SS_RDEF,
- "Focus servo failure") },
-/* WR O */{SST(0x09, 0x03, SS_RDEF,
- "Spindle servo failure") },
-/* DT WR O */{SST(0x09, 0x04, SS_RDEF,
- "Head select fault") },
-/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
- "Error log overflow") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
- "Warning") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
- "Specified temperature exceeded") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
- "Enclosure degraded") },
-/* T RS */{SST(0x0C, 0x00, SS_RDEF,
- "Write error") },
-/* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Write error - recovered with auto reallocation") },
-/* D W O */{SST(0x0C, 0x02, SS_RDEF,
- "Write error - auto reallocation failed") },
-/* D W O */{SST(0x0C, 0x03, SS_RDEF,
- "Write error - recommend reassignment") },
-/* DT W O */{SST(0x0C, 0x04, SS_RDEF,
- "Compression check miscompare error") },
-/* DT W O */{SST(0x0C, 0x05, SS_RDEF,
- "Data expansion occurred during compression") },
-/* DT W O */{SST(0x0C, 0x06, SS_RDEF,
- "Block not compressible") },
-/* R */{SST(0x0C, 0x07, SS_RDEF,
- "Write error - recovery needed") },
-/* R */{SST(0x0C, 0x08, SS_RDEF,
- "Write error - recovery failed") },
-/* R */{SST(0x0C, 0x09, SS_RDEF,
- "Write error - loss of streaming") },
-/* R */{SST(0x0C, 0x0A, SS_RDEF,
- "Write error - padding blocks added") },
-/* D W O */{SST(0x10, 0x00, SS_RDEF,
- "ID CRC or ECC error") },
-/* DT WRSO */{SST(0x11, 0x00, SS_RDEF,
- "Unrecovered read error") },
-/* DT W SO */{SST(0x11, 0x01, SS_RDEF,
- "Read retries exhausted") },
-/* DT W SO */{SST(0x11, 0x02, SS_RDEF,
- "Error too long to correct") },
-/* DT W SO */{SST(0x11, 0x03, SS_RDEF,
- "Multiple read errors") },
-/* D W O */{SST(0x11, 0x04, SS_RDEF,
- "Unrecovered read error - auto reallocate failed") },
-/* WR O */{SST(0x11, 0x05, SS_RDEF,
- "L-EC uncorrectable error") },
-/* WR O */{SST(0x11, 0x06, SS_RDEF,
- "CIRC unrecovered error") },
-/* W O */{SST(0x11, 0x07, SS_RDEF,
- "Data re-synchronization error") },
-/* T */{SST(0x11, 0x08, SS_RDEF,
- "Incomplete block read") },
-/* T */{SST(0x11, 0x09, SS_RDEF,
- "No gap found") },
-/* DT O */{SST(0x11, 0x0A, SS_RDEF,
- "Miscorrected error") },
-/* D W O */{SST(0x11, 0x0B, SS_RDEF,
- "Unrecovered read error - recommend reassignment") },
-/* D W O */{SST(0x11, 0x0C, SS_RDEF,
- "Unrecovered read error - recommend rewrite the data")},
-/* DT WR O */{SST(0x11, 0x0D, SS_RDEF,
- "De-compression CRC error") },
-/* DT WR O */{SST(0x11, 0x0E, SS_RDEF,
- "Cannot decompress using declared algorithm") },
-/* R */{SST(0x11, 0x0F, SS_RDEF,
- "Error reading UPC/EAN number") },
-/* R */{SST(0x11, 0x10, SS_RDEF,
- "Error reading ISRC number") },
-/* R */{SST(0x11, 0x11, SS_RDEF,
- "Read error - loss of streaming") },
-/* D W O */{SST(0x12, 0x00, SS_RDEF,
- "Address mark not found for id field") },
-/* D W O */{SST(0x13, 0x00, SS_RDEF,
- "Address mark not found for data field") },
-/* DTL WRSO */{SST(0x14, 0x00, SS_RDEF,
- "Recorded entity not found") },
-/* DT WR O */{SST(0x14, 0x01, SS_RDEF,
- "Record not found") },
-/* T */{SST(0x14, 0x02, SS_RDEF,
- "Filemark or setmark not found") },
-/* T */{SST(0x14, 0x03, SS_RDEF,
- "End-of-data not found") },
-/* T */{SST(0x14, 0x04, SS_RDEF,
- "Block sequence error") },
-/* DT W O */{SST(0x14, 0x05, SS_RDEF,
- "Record not found - recommend reassignment") },
-/* DT W O */{SST(0x14, 0x06, SS_RDEF,
- "Record not found - data auto-reallocated") },
-/* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF,
- "Random positioning error") },
-/* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF,
- "Mechanical positioning error") },
-/* DT WR O */{SST(0x15, 0x02, SS_RDEF,
- "Positioning error detected by read of medium") },
-/* D W O */{SST(0x16, 0x00, SS_RDEF,
- "Data synchronization mark error") },
-/* D W O */{SST(0x16, 0x01, SS_RDEF,
- "Data sync error - data rewritten") },
-/* D W O */{SST(0x16, 0x02, SS_RDEF,
- "Data sync error - recommend rewrite") },
-/* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Data sync error - data auto-reallocated") },
-/* D W O */{SST(0x16, 0x04, SS_RDEF,
- "Data sync error - recommend reassignment") },
-/* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with no error correction applied") },
-/* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with retries") },
-/* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with positive head offset") },
-/* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with negative head offset") },
-/* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with retries and/or CIRC applied") },
-/* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data using previous sector id") },
-/* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - data auto-reallocated") },
-/* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - recommend reassignment")},
-/* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - recommend rewrite") },
-/* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - data rewritten") },
-/* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with error correction applied") },
-/* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with error corr. & retries applied") },
-/* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - data auto-reallocated") },
-/* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with CIRC") },
-/* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with L-EC") },
-/* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - recommend reassignment") },
-/* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - recommend rewrite") },
-/* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with ECC - data rewritten") },
-/* D O */{SST(0x19, 0x00, SS_RDEF,
- "Defect list error") },
-/* D O */{SST(0x19, 0x01, SS_RDEF,
- "Defect list not available") },
-/* D O */{SST(0x19, 0x02, SS_RDEF,
- "Defect list error in primary list") },
-/* D O */{SST(0x19, 0x03, SS_RDEF,
- "Defect list error in grown list") },
-/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
- "Parameter list length error") },
-/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
- "Synchronous data transfer error") },
-/* D O */{SST(0x1C, 0x00, SS_RDEF,
- "Defect list not found") },
-/* D O */{SST(0x1C, 0x01, SS_RDEF,
- "Primary defect list not found") },
-/* D O */{SST(0x1C, 0x02, SS_RDEF,
- "Grown defect list not found") },
-/* D W O */{SST(0x1D, 0x00, SS_FATAL,
- "Miscompare during verify operation" )},
-/* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered id with ecc correction") },
-/* D O */{SST(0x1F, 0x00, SS_RDEF,
- "Partial defect list transfer") },
-/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
- "Invalid command operation code") },
-/* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL,
- "Logical block address out of range" )},
-/* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL,
- "Invalid element address") },
-/* D */{SST(0x22, 0x00, SS_FATAL|EINVAL,
- "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
-/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
- "Invalid field in CDB") },
-/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
- "Logical unit not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
- "Invalid field in parameter list") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
- "Parameter not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
- "Parameter value invalid") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
- "Threshold parameters not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
- "Invalid release of active persistent reservation") },
-/* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES,
- "Write protected") },
-/* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES,
- "Hardware write protected") },
-/* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES,
- "Logical unit software write protected") },
-/* T */{SST(0x27, 0x03, SS_FATAL|EACCES,
- "Associated write protect") },
-/* T */{SST(0x27, 0x04, SS_FATAL|EACCES,
- "Persistent write protect") },
-/* T */{SST(0x27, 0x05, SS_FATAL|EACCES,
- "Permanent write protect") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF,
- "Not ready to ready change, medium may have changed") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
- "Import or export element accessed") },
-/*
- * XXX JGibbs - All of these should use the same errno, but I don't think
- * ENXIO is the correct choice. Should we borrow from the networking
- * errnos? ECONNRESET anyone?
- */
-/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF,
- "Power on, reset, or bus device reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
- "Power on occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
- "Scsi bus reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
- "Bus device reset function occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
- "Device internal reset") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
- "Transceiver mode changed to single-ended") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
- "Transceiver mode changed to LVD") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
- "Parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
- "Mode parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
- "Log parameters changed") },
-/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
- "Reservations preempted") },
-/* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF,
- "Copy cannot execute since host cannot disconnect") },
-/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
- "Command sequence error") },
-/* S */{SST(0x2C, 0x01, SS_RDEF,
- "Too many windows specified") },
-/* S */{SST(0x2C, 0x02, SS_RDEF,
- "Invalid combination of windows specified") },
-/* R */{SST(0x2C, 0x03, SS_RDEF,
- "Current program area is not empty") },
-/* R */{SST(0x2C, 0x04, SS_RDEF,
- "Current program area is empty") },
-/* T */{SST(0x2D, 0x00, SS_RDEF,
- "Overwrite error on update in place") },
-/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
- "Commands cleared by another initiator") },
-/* DT WR OM */{SST(0x30, 0x00, SS_RDEF,
- "Incompatible medium installed") },
-/* DT WR O */{SST(0x30, 0x01, SS_RDEF,
- "Cannot read medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x02, SS_RDEF,
- "Cannot read medium - incompatible format") },
-/* DT */{SST(0x30, 0x03, SS_RDEF,
- "Cleaning cartridge installed") },
-/* DT WR O */{SST(0x30, 0x04, SS_RDEF,
- "Cannot write medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x05, SS_RDEF,
- "Cannot write medium - incompatible format") },
-/* DT W O */{SST(0x30, 0x06, SS_RDEF,
- "Cannot format medium - incompatible medium") },
-/* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
- "Cleaning failure") },
-/* R */{SST(0x30, 0x08, SS_RDEF,
- "Cannot write - application code mismatch") },
-/* R */{SST(0x30, 0x09, SS_RDEF,
- "Current session not fixated for append") },
-/* DT WR O */{SST(0x31, 0x00, SS_RDEF,
- "Medium format corrupted") },
-/* D L R O */{SST(0x31, 0x01, SS_RDEF,
- "Format command failed") },
-/* D W O */{SST(0x32, 0x00, SS_RDEF,
- "No defect spare location available") },
-/* D W O */{SST(0x32, 0x01, SS_RDEF,
- "Defect list update failure") },
-/* T */{SST(0x33, 0x00, SS_RDEF,
- "Tape length error") },
-/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
- "Enclosure failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
- "Enclosure services failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
- "Unsupported enclosure function") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
- "Enclosure services unavailable") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
- "Enclosure services transfer failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
- "Enclosure services transfer refused") },
-/* L */{SST(0x36, 0x00, SS_RDEF,
- "Ribbon, ink, or toner failure") },
-/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
- "Rounded parameter") },
-/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
- "Saving parameters not supported") },
-/* DTL WRSOM */{SST(0x3A, 0x00, SS_NOP,
- "Medium not present") },
-/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
- "Medium not present - tray closed") },
-/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
- "Medium not present - tray open") },
-/* DT WR OM */{SST(0x3A, 0x03, SS_NOP,
- "Medium not present - Loadable") },
-/* DT WR OM */{SST(0x3A, 0x04, SS_NOP,
- "Medium not present - medium auxiliary "
- "memory accessible") },
-/* DT WR OM */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */
-/* TL */{SST(0x3B, 0x00, SS_RDEF,
- "Sequential positioning error") },
-/* T */{SST(0x3B, 0x01, SS_RDEF,
- "Tape position error at beginning-of-medium") },
-/* T */{SST(0x3B, 0x02, SS_RDEF,
- "Tape position error at end-of-medium") },
-/* L */{SST(0x3B, 0x03, SS_RDEF,
- "Tape or electronic vertical forms unit not ready") },
-/* L */{SST(0x3B, 0x04, SS_RDEF,
- "Slew failure") },
-/* L */{SST(0x3B, 0x05, SS_RDEF,
- "Paper jam") },
-/* L */{SST(0x3B, 0x06, SS_RDEF,
- "Failed to sense top-of-form") },
-/* L */{SST(0x3B, 0x07, SS_RDEF,
- "Failed to sense bottom-of-form") },
-/* T */{SST(0x3B, 0x08, SS_RDEF,
- "Reposition error") },
-/* S */{SST(0x3B, 0x09, SS_RDEF,
- "Read past end of medium") },
-/* S */{SST(0x3B, 0x0A, SS_RDEF,
- "Read past beginning of medium") },
-/* S */{SST(0x3B, 0x0B, SS_RDEF,
- "Position past end of medium") },
-/* T S */{SST(0x3B, 0x0C, SS_RDEF,
- "Position past beginning of medium") },
-/* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
- "Medium destination element full") },
-/* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF,
- "Medium source element empty") },
-/* R */{SST(0x3B, 0x0F, SS_RDEF,
- "End of medium reached") },
-/* DT WR OM */{SST(0x3B, 0x11, SS_RDEF,
- "Medium magazine not accessible") },
-/* DT WR OM */{SST(0x3B, 0x12, SS_RDEF,
- "Medium magazine removed") },
-/* DT WR OM */{SST(0x3B, 0x13, SS_RDEF,
- "Medium magazine inserted") },
-/* DT WR OM */{SST(0x3B, 0x14, SS_RDEF,
- "Medium magazine locked") },
-/* DT WR OM */{SST(0x3B, 0x15, SS_RDEF,
- "Medium magazine unlocked") },
-/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
- "Invalid bits in identify message") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
- "Logical unit has not self-configured yet") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
- "Logical unit failure") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
- "Timeout on logical unit") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
- "Target operating conditions have changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
- "Microcode has been changed") },
-/* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF,
- "Changed operating definition") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT,
- "Inquiry data has changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
- "Component device attached") },
-/* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
- "Device identifier changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
- "Redundancy group created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
- "Redundancy group deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
- "Spare created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
- "Spare deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
- "Volume set created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
- "Volume set deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
- "Volume set deassigned") },
-/* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
- "Volume set reassigned") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF,
- "Reported luns data has changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT
- | SSQ_DELAY_RANDOM|EBUSY,
- "Echo buffer overwritten") },
-/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") },
-/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF,
- "Medium auxiliary memory accessible") },
-/* D */{SST(0x40, 0x00, SS_RDEF,
- "Ram failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
- "Diagnostic failure: ASCQ = Component ID") },
-/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) },/* Range 0x80->0xFF */
-/* D */{SST(0x41, 0x00, SS_RDEF,
- "Data path failure") }, /* deprecated - use 40 NN instead */
-/* D */{SST(0x42, 0x00, SS_RDEF,
- "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
- "Message error") },
-/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
- "Internal target failure") },
-/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
- "Select or reselect failure") },
-/* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF,
- "Unsuccessful soft reset") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK,
- "SCSI parity error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK,
- "Data Phase CRC error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK,
- "SCSI parity error detected during ST data phase") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK,
- "Information Unit iuCRC error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK,
- "Asynchronous information protection error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK,
- "Protocol server CRC error") },
-/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK,
- "Initiator detected error message received") },
-/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
- "Invalid message error") },
-/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
- "Command phase error") },
-/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
- "Data phase error") },
-/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
- "Logical unit failed self-configuration") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
- "Tagged overlapped commands: ASCQ = Queue tag ID") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL)}, /* Range 0x00->0xFF */
-/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
- "Overlapped commands attempted") },
-/* T */{SST(0x50, 0x00, SS_RDEF,
- "Write append error") },
-/* T */{SST(0x50, 0x01, SS_RDEF,
- "Write append position error") },
-/* T */{SST(0x50, 0x02, SS_RDEF,
- "Position error related to timing") },
-/* T O */{SST(0x51, 0x00, SS_RDEF,
- "Erase failure") },
-/* T */{SST(0x52, 0x00, SS_RDEF,
- "Cartridge fault") },
-/* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF,
- "Media load or eject failed") },
-/* T */{SST(0x53, 0x01, SS_RDEF,
- "Unload tape failure") },
-/* DT WR OM */{SST(0x53, 0x02, SS_RDEF,
- "Medium removal prevented") },
-/* P */{SST(0x54, 0x00, SS_RDEF,
- "Scsi to host system interface failure") },
-/* P */{SST(0x55, 0x00, SS_RDEF,
- "System resource failure") },
-/* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
- "System buffer full") },
-/* R */{SST(0x57, 0x00, SS_RDEF,
- "Unable to recover table-of-contents") },
-/* O */{SST(0x58, 0x00, SS_RDEF,
- "Generation does not exist") },
-/* O */{SST(0x59, 0x00, SS_RDEF,
- "Updated block read") },
-/* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF,
- "Operator request or state change input") },
-/* DT WR OM */{SST(0x5A, 0x01, SS_RDEF,
- "Operator medium removal request") },
-/* DT W O */{SST(0x5A, 0x02, SS_RDEF,
- "Operator selected write protect") },
-/* DT W O */{SST(0x5A, 0x03, SS_RDEF,
- "Operator selected write permit") },
-/* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF,
- "Log exception") },
-/* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF,
- "Threshold condition met") },
-/* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF,
- "Log counter at maximum") },
-/* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF,
- "Log list codes exhausted") },
-/* D O */{SST(0x5C, 0x00, SS_RDEF,
- "RPL status change") },
-/* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Spindles synchronized") },
-/* D O */{SST(0x5C, 0x02, SS_RDEF,
- "Spindles not synchronized") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
- "Failure prediction threshold exceeded") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
- "Failure prediction threshold exceeded (false)") },
-/* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF,
- "Low power condition on") },
-/* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF,
- "Idle condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF,
- "Standby condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF,
- "Idle condition activated by command") },
-/* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF,
- "Standby condition activated by command") },
-/* S */{SST(0x60, 0x00, SS_RDEF,
- "Lamp failure") },
-/* S */{SST(0x61, 0x00, SS_RDEF,
- "Video acquisition error") },
-/* S */{SST(0x61, 0x01, SS_RDEF,
- "Unable to acquire video") },
-/* S */{SST(0x61, 0x02, SS_RDEF,
- "Out of focus") },
-/* S */{SST(0x62, 0x00, SS_RDEF,
- "Scan head positioning error") },
-/* R */{SST(0x63, 0x00, SS_RDEF,
- "End of user area encountered on this track") },
-/* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
- "Packet does not fit in available space") },
-/* R */{SST(0x64, 0x00, SS_RDEF,
- "Illegal mode for this track") },
-/* R */{SST(0x64, 0x01, SS_RDEF,
- "Invalid packet size") },
-/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
- "Voltage fault") },
-/* S */{SST(0x66, 0x00, SS_RDEF,
- "Automatic document feeder cover up") },
-/* S */{SST(0x66, 0x01, SS_RDEF,
- "Automatic document feeder lift up") },
-/* S */{SST(0x66, 0x02, SS_RDEF,
- "Document jam in automatic document feeder") },
-/* S */{SST(0x66, 0x03, SS_RDEF,
- "Document miss feed automatic in document feeder") },
-/* A */{SST(0x67, 0x00, SS_RDEF,
- "Configuration failure") },
-/* A */{SST(0x67, 0x01, SS_RDEF,
- "Configuration of incapable logical units failed") },
-/* A */{SST(0x67, 0x02, SS_RDEF,
- "Add logical unit failed") },
-/* A */{SST(0x67, 0x03, SS_RDEF,
- "Modification of logical unit failed") },
-/* A */{SST(0x67, 0x04, SS_RDEF,
- "Exchange of logical unit failed") },
-/* A */{SST(0x67, 0x05, SS_RDEF,
- "Remove of logical unit failed") },
-/* A */{SST(0x67, 0x06, SS_RDEF,
- "Attachment of logical unit failed") },
-/* A */{SST(0x67, 0x07, SS_RDEF,
- "Creation of logical unit failed") },
-/* A */{SST(0x68, 0x00, SS_RDEF,
- "Logical unit not configured") },
-/* A */{SST(0x69, 0x00, SS_RDEF,
- "Data loss on logical unit") },
-/* A */{SST(0x69, 0x01, SS_RDEF,
- "Multiple logical unit failures") },
-/* A */{SST(0x69, 0x02, SS_RDEF,
- "Parity/data mismatch") },
-/* A */{SST(0x6A, 0x00, SS_RDEF,
- "Informational, refer to log") },
-/* A */{SST(0x6B, 0x00, SS_RDEF,
- "State change has occurred") },
-/* A */{SST(0x6B, 0x01, SS_RDEF,
- "Redundancy level got better") },
-/* A */{SST(0x6B, 0x02, SS_RDEF,
- "Redundancy level got worse") },
-/* A */{SST(0x6C, 0x00, SS_RDEF,
- "Rebuild failure occurred") },
-/* A */{SST(0x6D, 0x00, SS_RDEF,
- "Recalculate failure occurred") },
-/* A */{SST(0x6E, 0x00, SS_RDEF,
- "Command to logical unit failed") },
-/* T */{SST(0x70, 0x00, SS_RDEF,
- "Decompression exception short: ASCQ = Algorithm ID") },
-/* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) }, /* Range 0x00 -> 0xFF */
-/* T */{SST(0x71, 0x00, SS_RDEF,
- "Decompression exception long: ASCQ = Algorithm ID") },
-/* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) }, /* Range 0x00 -> 0xFF */
-/* R */{SST(0x72, 0x00, SS_RDEF,
- "Session fixation error") },
-/* R */{SST(0x72, 0x01, SS_RDEF,
- "Session fixation error writing lead-in") },
-/* R */{SST(0x72, 0x02, SS_RDEF,
- "Session fixation error writing lead-out") },
-/* R */{SST(0x72, 0x03, SS_RDEF,
- "Session fixation error - incomplete track in session") },
-/* R */{SST(0x72, 0x04, SS_RDEF,
- "Empty or partially written reserved track") },
-/* R */{SST(0x73, 0x00, SS_RDEF,
- "CD control error") },
-/* R */{SST(0x73, 0x01, SS_RDEF,
- "Power calibration area almost full") },
-/* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
- "Power calibration area is full") },
-/* R */{SST(0x73, 0x03, SS_RDEF,
- "Power calibration area error") },
-/* R */{SST(0x73, 0x04, SS_RDEF,
- "Program memory area update failure") },
-/* R */{SST(0x73, 0x05, SS_RDEF,
- "program memory area is full") }
-};
-
-static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
-
-struct asc_key
-{
- int asc;
- int ascq;
-};
-
-static int
-ascentrycomp(const void *key, const void *member)
-{
- int asc;
- int ascq;
- const struct asc_table_entry *table_entry;
-
- asc = ((const struct asc_key *)key)->asc;
- ascq = ((const struct asc_key *)key)->ascq;
- table_entry = (const struct asc_table_entry *)member;
-
- if (asc >= table_entry->asc) {
-
- if (asc > table_entry->asc)
- return (1);
-
- if (ascq <= table_entry->ascq) {
- /* Check for ranges */
- if (ascq == table_entry->ascq
- || ((table_entry->action & SSQ_RANGE) != 0
- && ascq >= (table_entry - 1)->ascq))
- return (0);
- return (-1);
- }
- return (1);
- }
- return (-1);
-}
-
-static int
-senseentrycomp(const void *key, const void *member)
-{
- int sense_key;
- const struct sense_key_table_entry *table_entry;
-
- sense_key = *((const int *)key);
- table_entry = (const struct sense_key_table_entry *)member;
-
- if (sense_key >= table_entry->sense_key) {
- if (sense_key == table_entry->sense_key)
- return (0);
- return (1);
- }
- return (-1);
-}
-
-static void
-fetchtableentries(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *inq_data,
- const struct sense_key_table_entry **sense_entry,
- const struct asc_table_entry **asc_entry)
-{
- void *match;
- const struct asc_table_entry *asc_tables[2];
- const struct sense_key_table_entry *sense_tables[2];
- struct asc_key asc_ascq;
- size_t asc_tables_size[2];
- size_t sense_tables_size[2];
- int num_asc_tables;
- int num_sense_tables;
- int i;
-
- /* Default to failure */
- *sense_entry = NULL;
- *asc_entry = NULL;
- match = NULL;
- if (inq_data != NULL)
- match = cam_quirkmatch((void *)inq_data,
- (void *)sense_quirk_table,
- sense_quirk_table_size,
- sizeof(*sense_quirk_table),
- aic_inquiry_match);
-
- if (match != NULL) {
- struct scsi_sense_quirk_entry *quirk;
-
- quirk = (struct scsi_sense_quirk_entry *)match;
- asc_tables[0] = quirk->asc_info;
- asc_tables_size[0] = quirk->num_ascs;
- asc_tables[1] = asc_table;
- asc_tables_size[1] = asc_table_size;
- num_asc_tables = 2;
- sense_tables[0] = quirk->sense_key_info;
- sense_tables_size[0] = quirk->num_sense_keys;
- sense_tables[1] = sense_key_table;
- sense_tables_size[1] = sense_key_table_size;
- num_sense_tables = 2;
- } else {
- asc_tables[0] = asc_table;
- asc_tables_size[0] = asc_table_size;
- num_asc_tables = 1;
- sense_tables[0] = sense_key_table;
- sense_tables_size[0] = sense_key_table_size;
- num_sense_tables = 1;
- }
-
- asc_ascq.asc = asc;
- asc_ascq.ascq = ascq;
- for (i = 0; i < num_asc_tables; i++) {
- void *found_entry;
-
- found_entry = scsibsearch(&asc_ascq, asc_tables[i],
- asc_tables_size[i],
- sizeof(**asc_tables),
- ascentrycomp);
-
- if (found_entry) {
- *asc_entry = (struct asc_table_entry *)found_entry;
- break;
- }
- }
-
- for (i = 0; i < num_sense_tables; i++) {
- void *found_entry;
-
- found_entry = scsibsearch(&sense_key, sense_tables[i],
- sense_tables_size[i],
- sizeof(**sense_tables),
- senseentrycomp);
-
- if (found_entry) {
- *sense_entry =
- (struct sense_key_table_entry *)found_entry;
- break;
- }
- }
-}
-
-static void *
-scsibsearch(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *))
-{
- const void *entry;
- u_int l;
- u_int u;
- u_int m;
-
- l = -1;
- u = nmemb;
- while (l + 1 != u) {
- m = (l + u) / 2;
- entry = base + m * size;
- if (compar(key, entry) > 0)
- l = m;
- else
- u = m;
- }
-
- entry = base + u * size;
- if (u == nmemb
- || compar(key, entry) != 0)
- return (NULL);
-
- return ((void *)entry);
-}
-
-/*
- * Compare string with pattern, returning 0 on match.
- * Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name,
- * wildcard '?' matches a single non-space character.
- */
-static int
-cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
-{
-
- while (*pattern != '\0'&& str_len > 0) {
-
- if (*pattern == '*') {
- return (0);
- }
- if ((*pattern != *str)
- && (*pattern != '?' || *str == ' ')) {
- return (1);
- }
- pattern++;
- str++;
- str_len--;
- }
- while (str_len > 0 && *str++ == ' ')
- str_len--;
-
- return (str_len);
-}
-
-static caddr_t
-cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
- int entry_size, cam_quirkmatch_t *comp_func)
-{
- for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
- if ((*comp_func)(target, quirk_table) == 0)
- return (quirk_table);
- }
- return (NULL);
-}
-
-void
-aic_sense_desc(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *inq_data,
- const char **sense_key_desc, const char **asc_desc)
-{
- const struct asc_table_entry *asc_entry;
- const struct sense_key_table_entry *sense_entry;
-
- fetchtableentries(sense_key, asc, ascq,
- inq_data,
- &sense_entry,
- &asc_entry);
-
- *sense_key_desc = sense_entry->desc;
-
- if (asc_entry != NULL)
- *asc_desc = asc_entry->desc;
- else if (asc >= 0x80 && asc <= 0xff)
- *asc_desc = "Vendor Specific ASC";
- else if (ascq >= 0x80 && ascq <= 0xff)
- *asc_desc = "Vendor Specific ASCQ";
- else
- *asc_desc = "Reserved ASC/ASCQ pair";
-}
-
-/*
- * Given sense and device type information, return the appropriate action.
- * If we do not understand the specific error as identified by the ASC/ASCQ
- * pair, fall back on the more generic actions derived from the sense key.
- */
-aic_sense_action
-aic_sense_error_action(struct scsi_sense_data *sense_data,
- struct scsi_inquiry_data *inq_data, uint32_t sense_flags)
-{
- const struct asc_table_entry *asc_entry;
- const struct sense_key_table_entry *sense_entry;
- int error_code, sense_key, asc, ascq;
- aic_sense_action action;
-
- scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);
-
- if (error_code == SSD_DEFERRED_ERROR) {
- /*
- * XXX dufault@FreeBSD.org
- * This error doesn't relate to the command associated
- * with this request sense. A deferred error is an error
- * for a command that has already returned GOOD status
- * (see SCSI2 8.2.14.2).
- *
- * By my reading of that section, it looks like the current
- * command has been cancelled, we should now clean things up
- * (hopefully recovering any lost data) and then retry the
- * current command. There are two easy choices, both wrong:
- *
- * 1. Drop through (like we had been doing), thus treating
- * this as if the error were for the current command and
- * return and stop the current command.
- *
- * 2. Issue a retry (like I made it do) thus hopefully
- * recovering the current transfer, and ignoring the
- * fact that we've dropped a command.
- *
- * These should probably be handled in a device specific
- * sense handler or punted back up to a user mode daemon
- */
- action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
- } else {
- fetchtableentries(sense_key, asc, ascq,
- inq_data,
- &sense_entry,
- &asc_entry);
-
- /*
- * Override the 'No additional Sense' entry (0,0)
- * with the error action of the sense key.
- */
- if (asc_entry != NULL
- && (asc != 0 || ascq != 0))
- action = asc_entry->action;
- else
- action = sense_entry->action;
-
- if (sense_key == SSD_KEY_RECOVERED_ERROR) {
- /*
- * The action succeeded but the device wants
- * the user to know that some recovery action
- * was required.
- */
- action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
- action |= SS_NOP|SSQ_PRINT_SENSE;
- } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
- if ((sense_flags & SF_QUIET_IR) != 0)
- action &= ~SSQ_PRINT_SENSE;
- } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
- if ((sense_flags & SF_RETRY_UA) != 0
- && (action & SS_MASK) == SS_FAIL) {
- action &= ~(SS_MASK|SSQ_MASK);
- action |= SS_RETRY|SSQ_DECREMENT_COUNT|
- SSQ_PRINT_SENSE;
- }
- }
- }
-
- if ((sense_flags & SF_PRINT_ALWAYS) != 0)
- action |= SSQ_PRINT_SENSE;
- else if ((sense_flags & SF_NO_PRINT) != 0)
- action &= ~SSQ_PRINT_SENSE;
-
- return (action);
-}
-
-/*
- * Try make as good a match as possible with
- * available sub drivers
- */
-int
-aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
-{
- struct scsi_inquiry_pattern *entry;
- struct scsi_inquiry_data *inq;
-
- entry = (struct scsi_inquiry_pattern *)table_entry;
- inq = (struct scsi_inquiry_data *)inqbuffer;
-
- if (((SID_TYPE(inq) == entry->type)
- || (entry->type == T_ANY))
- && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
- : entry->media_type & SIP_MEDIA_FIXED)
- && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
- && (cam_strmatch(inq->product, entry->product,
- sizeof(inq->product)) == 0)
- && (cam_strmatch(inq->revision, entry->revision,
- sizeof(inq->revision)) == 0)) {
- return (0);
- }
- return (-1);
-}
-
-/*
- * Table of syncrates that don't follow the "divisible by 4"
- * rule. This table will be expanded in future SCSI specs.
- */
-static struct {
- u_int period_factor;
- u_int period; /* in 100ths of ns */
-} scsi_syncrates[] = {
- { 0x08, 625 }, /* FAST-160 */
- { 0x09, 1250 }, /* FAST-80 */
- { 0x0a, 2500 }, /* FAST-40 40MHz */
- { 0x0b, 3030 }, /* FAST-40 33MHz */
- { 0x0c, 5000 } /* FAST-20 */
-};
-
-/*
- * Return the frequency in kHz corresponding to the given
- * sync period factor.
- */
-u_int
-aic_calc_syncsrate(u_int period_factor)
-{
- int i;
- int num_syncrates;
-
- num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
- /* See if the period is in the "exception" table */
- for (i = 0; i < num_syncrates; i++) {
-
- if (period_factor == scsi_syncrates[i].period_factor) {
- /* Period in kHz */
- return (100000000 / scsi_syncrates[i].period);
- }
- }
-
- /*
- * Wasn't in the table, so use the standard
- * 4 times conversion.
- */
- return (10000000 / (period_factor * 4 * 10));
-}
-
-/*
- * Return speed in KB/s.
- */
-u_int
-aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate)
-{
- u_int freq;
-
- if (offset != 0 && period < min_rate)
- freq = aic_calc_syncsrate(period);
- else
- /* Roughly 3.3MB/s for async */
- freq = 3300;
- freq <<= width;
- return (freq);
-}
-
-uint32_t
-aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
- cam_status status, u_int scsi_status)
-{
- aic_sense_action err_action;
- int sense;
-
- sense = (cmd->result >> 24) == DRIVER_SENSE;
-
- switch (status) {
- case CAM_REQ_CMP:
- err_action = SS_NOP;
- break;
- case CAM_AUTOSENSE_FAIL:
- case CAM_SCSI_STATUS_ERROR:
-
- switch (scsi_status) {
- case SCSI_STATUS_OK:
- case SCSI_STATUS_COND_MET:
- case SCSI_STATUS_INTERMED:
- case SCSI_STATUS_INTERMED_COND_MET:
- err_action = SS_NOP;
- break;
- case SCSI_STATUS_CMD_TERMINATED:
- case SCSI_STATUS_CHECK_COND:
- if (sense != 0) {
- struct scsi_sense_data *sense;
-
- sense = (struct scsi_sense_data *)
- &cmd->sense_buffer;
- err_action =
- aic_sense_error_action(sense, inq_data, 0);
-
- } else {
- err_action = SS_RETRY|SSQ_FALLBACK
- | SSQ_DECREMENT_COUNT|EIO;
- }
- break;
- case SCSI_STATUS_QUEUE_FULL:
- case SCSI_STATUS_BUSY:
- err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY
- | SSQ_DECREMENT_COUNT|EBUSY;
- break;
- case SCSI_STATUS_RESERV_CONFLICT:
- default:
- err_action = SS_FAIL|EBUSY;
- break;
- }
- break;
- case CAM_CMD_TIMEOUT:
- case CAM_REQ_CMP_ERR:
- case CAM_UNEXP_BUSFREE:
- case CAM_UNCOR_PARITY:
- case CAM_DATA_RUN_ERR:
- err_action = SS_RETRY|SSQ_FALLBACK|EIO;
- break;
- case CAM_UA_ABORT:
- case CAM_UA_TERMIO:
- case CAM_MSG_REJECT_REC:
- case CAM_SEL_TIMEOUT:
- err_action = SS_FAIL|EIO;
- break;
- case CAM_REQ_INVALID:
- case CAM_PATH_INVALID:
- case CAM_DEV_NOT_THERE:
- case CAM_NO_HBA:
- case CAM_PROVIDE_FAIL:
- case CAM_REQ_TOO_BIG:
- case CAM_RESRC_UNAVAIL:
- case CAM_BUSY:
- default:
- /* panic?? These should never occur in our application. */
- err_action = SS_FAIL|EIO;
- break;
- case CAM_SCSI_BUS_RESET:
- case CAM_BDR_SENT:
- case CAM_REQUEUE_REQ:
- /* Unconditional requeue */
- err_action = SS_RETRY;
- break;
- }
-
- return (err_action);
-}
-
-char *
-aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
- aic_option_callback_t *callback, u_long callback_arg)
-{
- char *tok_end;
- char *tok_end2;
- int i;
- int instance;
- int targ;
- int done;
- char tok_list[] = {'.', ',', '{', '}', '\0'};
- /* All options use a ':' name/arg separator */
- if (*opt_arg != ':')
- return (opt_arg);
- opt_arg++;
- instance = -1;
- targ = -1;
- done = FALSE;
- /*
- * Restore separator that may be in
- * the middle of our option argument.
- */
- tok_end = strchr(opt_arg, '\0');
- if (tok_end < end)
- *tok_end = ',';
- while (!done) {
- switch (*opt_arg) {
- case '{':
- if (instance == -1) {
- instance = 0;
- } else {
- if (depth > 1) {
- if (targ == -1)
- targ = 0;
- } else {
- printf("Malformed Option %s\n",
- opt_name);
- done = TRUE;
- }
- }
- opt_arg++;
- break;
- case '}':
- if (targ != -1)
- targ = -1;
- else if (instance != -1)
- instance = -1;
- opt_arg++;
- break;
- case ',':
- case '.':
- if (instance == -1)
- done = TRUE;
- else if (targ >= 0)
- targ++;
- else if (instance >= 0)
- instance++;
- opt_arg++;
- break;
- case '\0':
- done = TRUE;
- break;
- default:
- tok_end = end;
- for (i = 0; tok_list[i]; i++) {
- tok_end2 = strchr(opt_arg, tok_list[i]);
- if ((tok_end2) && (tok_end2 < tok_end))
- tok_end = tok_end2;
- }
- callback(callback_arg, instance, targ,
- simple_strtol(opt_arg, NULL, 0));
- opt_arg = tok_end;
- break;
- }
- }
- return (opt_arg);
-}
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h
index bfe6f954d3c4..3bfbf0fe1ec2 100644
--- a/drivers/scsi/aic7xxx/aiclib.h
+++ b/drivers/scsi/aic7xxx/aiclib.h
@@ -57,121 +57,6 @@
#ifndef _AICLIB_H
#define _AICLIB_H
-/*
- * Linux Interrupt Support.
- */
-#ifndef IRQ_RETVAL
-typedef void irqreturn_t;
-#define IRQ_RETVAL(x)
-#endif
-
-/*
- * SCSI command format
- */
-
-/*
- * Define dome bits that are in ALL (or a lot of) scsi commands
- */
-#define SCSI_CTL_LINK 0x01
-#define SCSI_CTL_FLAG 0x02
-#define SCSI_CTL_VENDOR 0xC0
-#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
-#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
-
-#define SCSI_MAX_CDBLEN 16 /*
- * 16 byte commands are in the
- * SCSI-3 spec
- */
-/* 6byte CDBs special case 0 length to be 256 */
-#define SCSI_CDB6_LEN(len) ((len) == 0 ? 256 : len)
-
-/*
- * This type defines actions to be taken when a particular sense code is
- * received. Right now, these flags are only defined to take up 16 bits,
- * but can be expanded in the future if necessary.
- */
-typedef enum {
- SS_NOP = 0x000000, /* Do nothing */
- SS_RETRY = 0x010000, /* Retry the command */
- SS_FAIL = 0x020000, /* Bail out */
- SS_START = 0x030000, /* Send a Start Unit command to the device,
- * then retry the original command.
- */
- SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
- * device, then retry the original command.
- */
- SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
- * device, then retry the original command.
- */
- SS_INQ_REFRESH = 0x060000,
- SS_MASK = 0xff0000
-} aic_sense_action;
-
-typedef enum {
- SSQ_NONE = 0x0000,
- SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */
- SSQ_MANY = 0x0200, /* send lots of recovery commands */
- SSQ_RANGE = 0x0400, /*
- * This table entry represents the
- * end of a range of ASCQs that
- * have identical error actions
- * and text.
- */
- SSQ_PRINT_SENSE = 0x0800,
- SSQ_DELAY = 0x1000, /* Delay before retry. */
- SSQ_DELAY_RANDOM = 0x2000, /* Randomized delay before retry. */
- SSQ_FALLBACK = 0x4000, /* Do a speed fallback to recover */
- SSQ_MASK = 0xff00
-} aic_sense_action_qualifier;
-
-/* Mask for error status values */
-#define SS_ERRMASK 0xff
-
-/* The default, retyable, error action */
-#define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
-
-/* The retyable, error action, with table specified error code */
-#define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
-
-/* Fatal error action, with table specified error code */
-#define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE
-
-struct scsi_generic
-{
- uint8_t opcode;
- uint8_t bytes[11];
-};
-
-struct scsi_request_sense
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_test_unit_ready
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[3];
- uint8_t control;
-};
-
-struct scsi_send_diag
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SSD_UOL 0x01
-#define SSD_DOL 0x02
-#define SSD_SELFTEST 0x04
-#define SSD_PF 0x10
- uint8_t unused[1];
- uint8_t paramlen[2];
- uint8_t control;
-};
-
struct scsi_sense
{
uint8_t opcode;
@@ -181,537 +66,12 @@ struct scsi_sense
uint8_t control;
};
-struct scsi_inquiry
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SI_EVPD 0x01
- uint8_t page_code;
- uint8_t reserved;
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_sense_6
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SMS_DBD 0x08
- uint8_t page;
-#define SMS_PAGE_CODE 0x3F
-#define SMS_VENDOR_SPECIFIC_PAGE 0x00
-#define SMS_DISCONNECT_RECONNECT_PAGE 0x02
-#define SMS_PERIPHERAL_DEVICE_PAGE 0x09
-#define SMS_CONTROL_MODE_PAGE 0x0A
-#define SMS_ALL_PAGES_PAGE 0x3F
-#define SMS_PAGE_CTRL_MASK 0xC0
-#define SMS_PAGE_CTRL_CURRENT 0x00
-#define SMS_PAGE_CTRL_CHANGEABLE 0x40
-#define SMS_PAGE_CTRL_DEFAULT 0x80
-#define SMS_PAGE_CTRL_SAVED 0xC0
- uint8_t unused;
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_sense_10
-{
- uint8_t opcode;
- uint8_t byte2; /* same bits as small version */
- uint8_t page; /* same bits as small version */
- uint8_t unused[4];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_mode_select_6
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SMS_SP 0x01
-#define SMS_PF 0x10
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_select_10
-{
- uint8_t opcode;
- uint8_t byte2; /* same bits as small version */
- uint8_t unused[5];
- uint8_t length[2];
- uint8_t control;
-};
-
-/*
- * When sending a mode select to a tape drive, the medium type must be 0.
- */
-struct scsi_mode_hdr_6
-{
- uint8_t datalen;
- uint8_t medium_type;
- uint8_t dev_specific;
- uint8_t block_descr_len;
-};
-
-struct scsi_mode_hdr_10
-{
- uint8_t datalen[2];
- uint8_t medium_type;
- uint8_t dev_specific;
- uint8_t reserved[2];
- uint8_t block_descr_len[2];
-};
-
-struct scsi_mode_block_descr
-{
- uint8_t density_code;
- uint8_t num_blocks[3];
- uint8_t reserved;
- uint8_t block_len[3];
-};
-
-struct scsi_log_sense
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SLS_SP 0x01
-#define SLS_PPC 0x02
- uint8_t page;
-#define SLS_PAGE_CODE 0x3F
-#define SLS_ALL_PAGES_PAGE 0x00
-#define SLS_OVERRUN_PAGE 0x01
-#define SLS_ERROR_WRITE_PAGE 0x02
-#define SLS_ERROR_READ_PAGE 0x03
-#define SLS_ERROR_READREVERSE_PAGE 0x04
-#define SLS_ERROR_VERIFY_PAGE 0x05
-#define SLS_ERROR_NONMEDIUM_PAGE 0x06
-#define SLS_ERROR_LASTN_PAGE 0x07
-#define SLS_PAGE_CTRL_MASK 0xC0
-#define SLS_PAGE_CTRL_THRESHOLD 0x00
-#define SLS_PAGE_CTRL_CUMULATIVE 0x40
-#define SLS_PAGE_CTRL_THRESH_DEFAULT 0x80
-#define SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0
- uint8_t reserved[2];
- uint8_t paramptr[2];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_log_select
-{
- uint8_t opcode;
- uint8_t byte2;
-/* SLS_SP 0x01 */
-#define SLS_PCR 0x02
- uint8_t page;
-/* SLS_PAGE_CTRL_MASK 0xC0 */
-/* SLS_PAGE_CTRL_THRESHOLD 0x00 */
-/* SLS_PAGE_CTRL_CUMULATIVE 0x40 */
-/* SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 */
-/* SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 */
- uint8_t reserved[4];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_log_header
-{
- uint8_t page;
- uint8_t reserved;
- uint8_t datalen[2];
-};
-
-struct scsi_log_param_header {
- uint8_t param_code[2];
- uint8_t param_control;
-#define SLP_LP 0x01
-#define SLP_LBIN 0x02
-#define SLP_TMC_MASK 0x0C
-#define SLP_TMC_ALWAYS 0x00
-#define SLP_TMC_EQUAL 0x04
-#define SLP_TMC_NOTEQUAL 0x08
-#define SLP_TMC_GREATER 0x0C
-#define SLP_ETC 0x10
-#define SLP_TSD 0x20
-#define SLP_DS 0x40
-#define SLP_DU 0x80
- uint8_t param_len;
-};
-
-struct scsi_control_page {
- uint8_t page_code;
- uint8_t page_length;
- uint8_t rlec;
-#define SCB_RLEC 0x01 /*Report Log Exception Cond*/
- uint8_t queue_flags;
-#define SCP_QUEUE_ALG_MASK 0xF0
-#define SCP_QUEUE_ALG_RESTRICTED 0x00
-#define SCP_QUEUE_ALG_UNRESTRICTED 0x10
-#define SCP_QUEUE_ERR 0x02 /*Queued I/O aborted for CACs*/
-#define SCP_QUEUE_DQUE 0x01 /*Queued I/O disabled*/
- uint8_t eca_and_aen;
-#define SCP_EECA 0x80 /*Enable Extended CA*/
-#define SCP_RAENP 0x04 /*Ready AEN Permission*/
-#define SCP_UAAENP 0x02 /*UA AEN Permission*/
-#define SCP_EAENP 0x01 /*Error AEN Permission*/
- uint8_t reserved;
- uint8_t aen_holdoff_period[2];
-};
-
-struct scsi_reserve
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_release
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_prevent
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t how;
- uint8_t control;
-};
-#define PR_PREVENT 0x01
-#define PR_ALLOW 0x00
-
-struct scsi_sync_cache
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t begin_lba[4];
- uint8_t reserved;
- uint8_t lb_count[2];
- uint8_t control;
-};
-
-
-struct scsi_changedef
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused1;
- uint8_t how;
- uint8_t unused[4];
- uint8_t datalen;
- uint8_t control;
-};
-
-struct scsi_read_buffer
-{
- uint8_t opcode;
- uint8_t byte2;
-#define RWB_MODE 0x07
-#define RWB_MODE_HDR_DATA 0x00
-#define RWB_MODE_DATA 0x02
-#define RWB_MODE_DOWNLOAD 0x04
-#define RWB_MODE_DOWNLOAD_SAVE 0x05
- uint8_t buffer_id;
- uint8_t offset[3];
- uint8_t length[3];
- uint8_t control;
-};
-
-struct scsi_write_buffer
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t buffer_id;
- uint8_t offset[3];
- uint8_t length[3];
- uint8_t control;
-};
-
-struct scsi_rw_6
-{
- uint8_t opcode;
- uint8_t addr[3];
-/* only 5 bits are valid in the MSB address byte */
-#define SRW_TOPADDR 0x1F
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_rw_10
-{
- uint8_t opcode;
-#define SRW10_RELADDR 0x01
-#define SRW10_FUA 0x08
-#define SRW10_DPO 0x10
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t reserved;
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_rw_12
-{
- uint8_t opcode;
-#define SRW12_RELADDR 0x01
-#define SRW12_FUA 0x08
-#define SRW12_DPO 0x10
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t length[4];
- uint8_t reserved;
- uint8_t control;
-};
-
-struct scsi_start_stop_unit
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SSS_IMMED 0x01
- uint8_t reserved[2];
- uint8_t how;
-#define SSS_START 0x01
-#define SSS_LOEJ 0x02
- uint8_t control;
-};
-
-#define SC_SCSI_1 0x01
-#define SC_SCSI_2 0x03
-
-/*
- * Opcodes
- */
-
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define READ_6 0x08
-#define WRITE_6 0x0a
-#define INQUIRY 0x12
-#define MODE_SELECT_6 0x15
-#define MODE_SENSE_6 0x1a
-#define START_STOP_UNIT 0x1b
-#define START_STOP 0x1b
-#define RESERVE 0x16
-#define RELEASE 0x17
-#define RECEIVE_DIAGNOSTIC 0x1c
-#define SEND_DIAGNOSTIC 0x1d
-#define PREVENT_ALLOW 0x1e
-#define READ_CAPACITY 0x25
-#define READ_10 0x28
-#define WRITE_10 0x2a
-#define POSITION_TO_ELEMENT 0x2b
-#define SYNCHRONIZE_CACHE 0x35
-#define WRITE_BUFFER 0x3b
-#define READ_BUFFER 0x3c
-#define CHANGE_DEFINITION 0x40
-#define LOG_SELECT 0x4c
-#define LOG_SENSE 0x4d
-#ifdef XXXCAM
-#define MODE_SENSE_10 0x5A
-#endif
-#define MODE_SELECT_10 0x55
-#define MOVE_MEDIUM 0xa5
-#define READ_12 0xa8
-#define WRITE_12 0xaa
-#define READ_ELEMENT_STATUS 0xb8
-
-
-/*
- * Device Types
- */
-#define T_DIRECT 0x00
-#define T_SEQUENTIAL 0x01
-#define T_PRINTER 0x02
-#define T_PROCESSOR 0x03
-#define T_WORM 0x04
-#define T_CDROM 0x05
-#define T_SCANNER 0x06
-#define T_OPTICAL 0x07
-#define T_CHANGER 0x08
-#define T_COMM 0x09
-#define T_ASC0 0x0a
-#define T_ASC1 0x0b
-#define T_STORARRAY 0x0c
-#define T_ENCLOSURE 0x0d
-#define T_RBC 0x0e
-#define T_OCRW 0x0f
-#define T_NODEVICE 0x1F
-#define T_ANY 0xFF /* Used in Quirk table matches */
-
-#define T_REMOV 1
-#define T_FIXED 0
-
-/*
- * This length is the initial inquiry length used by the probe code, as
- * well as the legnth necessary for aic_print_inquiry() to function
- * correctly. If either use requires a different length in the future,
- * the two values should be de-coupled.
- */
-#define SHORT_INQUIRY_LENGTH 36
-
-struct scsi_inquiry_data
-{
- uint8_t device;
-#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
-#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
-#define SID_QUAL_LU_CONNECTED 0x00 /*
- * The specified peripheral device
- * type is currently connected to
- * logical unit. If the target cannot
- * determine whether or not a physical
- * device is currently connected, it
- * shall also use this peripheral
- * qualifier when returning the INQUIRY
- * data. This peripheral qualifier
- * does not mean that the device is
- * ready for access by the initiator.
- */
-#define SID_QUAL_LU_OFFLINE 0x01 /*
- * The target is capable of supporting
- * the specified peripheral device type
- * on this logical unit; however, the
- * physical device is not currently
- * connected to this logical unit.
- */
-#define SID_QUAL_RSVD 0x02
-#define SID_QUAL_BAD_LU 0x03 /*
- * The target is not capable of
- * supporting a physical device on
- * this logical unit. For this
- * peripheral qualifier the peripheral
- * device type shall be set to 1Fh to
- * provide compatibility with previous
- * versions of SCSI. All other
- * peripheral device type values are
- * reserved for this peripheral
- * qualifier.
- */
-#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0)
- uint8_t dev_qual2;
-#define SID_QUAL2 0x7F
-#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0)
- uint8_t version;
-#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07)
#define SCSI_REV_0 0
#define SCSI_REV_CCS 1
#define SCSI_REV_2 2
#define SCSI_REV_SPC 3
#define SCSI_REV_SPC2 4
-#define SID_ECMA 0x38
-#define SID_ISO 0xC0
- uint8_t response_format;
-#define SID_AENC 0x80
-#define SID_TrmIOP 0x40
- uint8_t additional_length;
- uint8_t reserved[2];
- uint8_t flags;
-#define SID_SftRe 0x01
-#define SID_CmdQue 0x02
-#define SID_Linked 0x08
-#define SID_Sync 0x10
-#define SID_WBus16 0x20
-#define SID_WBus32 0x40
-#define SID_RelAdr 0x80
-#define SID_VENDOR_SIZE 8
- char vendor[SID_VENDOR_SIZE];
-#define SID_PRODUCT_SIZE 16
- char product[SID_PRODUCT_SIZE];
-#define SID_REVISION_SIZE 4
- char revision[SID_REVISION_SIZE];
- /*
- * The following fields were taken from SCSI Primary Commands - 2
- * (SPC-2) Revision 14, Dated 11 November 1999
- */
-#define SID_VENDOR_SPECIFIC_0_SIZE 20
- uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE];
- /*
- * An extension of SCSI Parallel Specific Values
- */
-#define SID_SPI_IUS 0x01
-#define SID_SPI_QAS 0x02
-#define SID_SPI_CLOCK_ST 0x00
-#define SID_SPI_CLOCK_DT 0x04
-#define SID_SPI_CLOCK_DT_ST 0x0C
-#define SID_SPI_MASK 0x0F
- uint8_t spi3data;
- uint8_t reserved2;
- /*
- * Version Descriptors, stored 2 byte values.
- */
- uint8_t version1[2];
- uint8_t version2[2];
- uint8_t version3[2];
- uint8_t version4[2];
- uint8_t version5[2];
- uint8_t version6[2];
- uint8_t version7[2];
- uint8_t version8[2];
-
- uint8_t reserved3[22];
-
-#define SID_VENDOR_SPECIFIC_1_SIZE 160
- uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
-};
-
-struct scsi_vpd_unit_serial_number
-{
- uint8_t device;
- uint8_t page_code;
-#define SVPD_UNIT_SERIAL_NUMBER 0x80
- uint8_t reserved;
- uint8_t length; /* serial number length */
-#define SVPD_SERIAL_NUM_SIZE 251
- uint8_t serial_num[SVPD_SERIAL_NUM_SIZE];
-};
-
-struct scsi_read_capacity
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t unused[3];
- uint8_t control;
-};
-
-struct scsi_read_capacity_data
-{
- uint8_t addr[4];
- uint8_t length[4];
-};
-
-struct scsi_report_luns
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[3];
- uint8_t addr[4];
- uint8_t control;
-};
-
-struct scsi_report_luns_data {
- uint8_t length[4]; /* length of LUN inventory, in bytes */
- uint8_t reserved[4]; /* unused */
- /*
- * LUN inventory- we only support the type zero form for now.
- */
- struct {
- uint8_t lundata[8];
- } luns[1];
-};
-#define RPL_LUNDATA_ATYP_MASK 0xc0 /* MBZ for type 0 lun */
-#define RPL_LUNDATA_T0LUN 1 /* @ lundata[1] */
-
-
struct scsi_sense_data
{
uint8_t error_code;
@@ -757,41 +117,6 @@ struct scsi_sense_data
#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
};
-struct scsi_mode_header_6
-{
- uint8_t data_length; /* Sense data length */
- uint8_t medium_type;
- uint8_t dev_spec;
- uint8_t blk_desc_len;
-};
-
-struct scsi_mode_header_10
-{
- uint8_t data_length[2];/* Sense data length */
- uint8_t medium_type;
- uint8_t dev_spec;
- uint8_t unused[2];
- uint8_t blk_desc_len[2];
-};
-
-struct scsi_mode_page_header
-{
- uint8_t page_code;
- uint8_t page_length;
-};
-
-struct scsi_mode_blk_desc
-{
- uint8_t density;
- uint8_t nblocks[3];
- uint8_t reserved;
- uint8_t blklen[3];
-};
-
-#define SCSI_DEFAULT_DENSITY 0x00 /* use 'default' density */
-#define SCSI_SAME_DENSITY 0x7f /* use 'same' density- >= SCSI-2 only */
-
-
/*
* Status Byte
*/
@@ -807,76 +132,7 @@ struct scsi_mode_blk_desc
#define SCSI_STATUS_ACA_ACTIVE 0x30
#define SCSI_STATUS_TASK_ABORTED 0x40
-struct scsi_inquiry_pattern {
- uint8_t type;
- uint8_t media_type;
-#define SIP_MEDIA_REMOVABLE 0x01
-#define SIP_MEDIA_FIXED 0x02
- const char *vendor;
- const char *product;
- const char *revision;
-};
-
-struct scsi_static_inquiry_pattern {
- uint8_t type;
- uint8_t media_type;
- char vendor[SID_VENDOR_SIZE+1];
- char product[SID_PRODUCT_SIZE+1];
- char revision[SID_REVISION_SIZE+1];
-};
-
-struct scsi_sense_quirk_entry {
- struct scsi_inquiry_pattern inq_pat;
- int num_sense_keys;
- int num_ascs;
- struct sense_key_table_entry *sense_key_info;
- struct asc_table_entry *asc_info;
-};
-
-struct sense_key_table_entry {
- uint8_t sense_key;
- uint32_t action;
- const char *desc;
-};
-
-struct asc_table_entry {
- uint8_t asc;
- uint8_t ascq;
- uint32_t action;
- const char *desc;
-};
-
-struct op_table_entry {
- uint8_t opcode;
- uint16_t opmask;
- const char *desc;
-};
-
-struct scsi_op_quirk_entry {
- struct scsi_inquiry_pattern inq_pat;
- int num_ops;
- struct op_table_entry *op_table;
-};
-
-typedef enum {
- SSS_FLAG_NONE = 0x00,
- SSS_FLAG_PRINT_COMMAND = 0x01
-} scsi_sense_string_flags;
-
-extern const char *scsi_sense_key_text[];
-
/************************* Large Disk Handling ********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
-
-static __inline int
-aic_sector_div(u_long capacity, int heads, int sectors)
-{
- return (capacity / (heads * sectors));
-}
-#else
-static __inline int aic_sector_div(sector_t capacity, int heads, int sectors);
-
static __inline int
aic_sector_div(sector_t capacity, int heads, int sectors)
{
@@ -884,152 +140,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
sector_div(capacity, (heads * sectors));
return (int)capacity;
}
-#endif
-
-/**************************** Module Library Hack *****************************/
-/*
- * What we'd like to do is have a single "scsi library" module that both the
- * aic7xxx and aic79xx drivers could load and depend on. A cursory examination
- * of implementing module dependencies in Linux (handling the install and
- * initrd cases) does not look promissing. For now, we just duplicate this
- * code in both drivers using a simple symbol renaming scheme that hides this
- * hack from the drivers.
- */
-#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x
-#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
-#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
-
-#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc)
-#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action)
-#define aic_error_action AIC_LIB_ENTRY(_error_action)
-#define aic_op_desc AIC_LIB_ENTRY(_op_desc)
-#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string)
-#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry)
-#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate)
-#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam)
-#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed)
-#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match)
-#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match)
-#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option)
-
-/******************************************************************************/
-
-void aic_sense_desc(int /*sense_key*/, int /*asc*/,
- int /*ascq*/, struct scsi_inquiry_data*,
- const char** /*sense_key_desc*/,
- const char** /*asc_desc*/);
-aic_sense_action aic_sense_error_action(struct scsi_sense_data*,
- struct scsi_inquiry_data*,
- uint32_t /*sense_flags*/);
-uint32_t aic_error_action(struct scsi_cmnd *,
- struct scsi_inquiry_data *,
- cam_status, u_int);
-
-#define SF_RETRY_UA 0x01
-#define SF_NO_PRINT 0x02
-#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
-#define SF_PRINT_ALWAYS 0x08
-
-
-const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*);
-char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/,
- size_t /*len*/);
-void aic_print_inquiry(struct scsi_inquiry_data*);
-
-u_int aic_calc_syncsrate(u_int /*period_factor*/);
-u_int aic_calc_syncparam(u_int /*period*/);
-u_int aic_calc_speed(u_int width, u_int period, u_int offset,
- u_int min_rate);
-
-int aic_inquiry_match(caddr_t /*inqbuffer*/,
- caddr_t /*table_entry*/);
-int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
- caddr_t /*table_entry*/);
-
-typedef void aic_option_callback_t(u_long, int, int, int32_t);
-char * aic_parse_brace_option(char *opt_name, char *opt_arg,
- char *end, int depth,
- aic_option_callback_t *, u_long);
-
-static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
- int *error_code, int *sense_key,
- int *asc, int *ascq);
-static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
-static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
-static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
-static __inline uint32_t scsi_2btoul(uint8_t *bytes);
-static __inline uint32_t scsi_3btoul(uint8_t *bytes);
-static __inline int32_t scsi_3btol(uint8_t *bytes);
-static __inline uint32_t scsi_4btoul(uint8_t *bytes);
-
-static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
- int *error_code, int *sense_key,
- int *asc, int *ascq)
-{
- *error_code = sense->error_code & SSD_ERRCODE;
- *sense_key = sense->flags & SSD_KEY;
- *asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
- *ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
-}
-
-static __inline void
-scsi_ulto2b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 8) & 0xff;
- bytes[1] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto3b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 16) & 0xff;
- bytes[1] = (val >> 8) & 0xff;
- bytes[2] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto4b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 24) & 0xff;
- bytes[1] = (val >> 16) & 0xff;
- bytes[2] = (val >> 8) & 0xff;
- bytes[3] = val & 0xff;
-}
-
-static __inline uint32_t
-scsi_2btoul(uint8_t *bytes)
-{
- uint32_t rv;
-
- rv = (bytes[0] << 8) |
- bytes[1];
- return (rv);
-}
-
-static __inline uint32_t
-scsi_3btoul(uint8_t *bytes)
-{
- uint32_t rv;
-
- rv = (bytes[0] << 16) |
- (bytes[1] << 8) |
- bytes[2];
- return (rv);
-}
-
-static __inline int32_t
-scsi_3btol(uint8_t *bytes)
-{
- uint32_t rc = scsi_3btoul(bytes);
-
- if (rc & 0x00800000)
- rc |= 0xff000000;
-
- return (int32_t) rc;
-}
static __inline uint32_t
scsi_4btoul(uint8_t *bytes)
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index d96ebf9d2228..87e0c36f1554 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -1,24 +1,42 @@
/*
-
- ata_piix.c - Intel PATA/SATA controllers
-
- Maintained by: Jeff Garzik <jgarzik@pobox.com>
- Please ALWAYS copy linux-ide@vger.kernel.org
- on emails.
-
-
- Copyright 2003-2004 Red Hat Inc
- Copyright 2003-2004 Jeff Garzik
-
-
- Copyright header from piix.c:
-
- Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
-
- May be copied or modified under the terms of the GNU General Public License
-
+ * ata_piix.c - Intel PATA/SATA controllers
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ *
+ * Copyright 2003-2005 Red Hat Inc
+ * Copyright 2003-2005 Jeff Garzik
+ *
+ *
+ * Copyright header from piix.c:
+ *
+ * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available at http://developer.intel.com/
+ *
*/
#include <linux/kernel.h>
@@ -50,8 +68,8 @@ enum {
PIIX_COMB_PATA_P0 = (1 << 1),
PIIX_COMB = (1 << 2), /* combined mode enabled? */
- PIIX_PORT_PRESENT = (1 << 0),
- PIIX_PORT_ENABLED = (1 << 4),
+ PIIX_PORT_ENABLED = (1 << 0),
+ PIIX_PORT_PRESENT = (1 << 4),
PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6),
@@ -359,7 +377,9 @@ static void piix_pata_phy_reset(struct ata_port *ap)
* None (inherited from caller).
*
* RETURNS:
- * Non-zero if device detected, zero otherwise.
+ * Non-zero if port is enabled, it may or may not have a device
+ * attached in that case (PRESENT bit would only be set if BIOS probe
+ * was done). Zero is returned if port is disabled.
*/
static int piix_sata_probe (struct ata_port *ap)
{
@@ -383,7 +403,7 @@ static int piix_sata_probe (struct ata_port *ap)
*/
for (i = 0; i < 4; i++) {
- mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
+ mask = (PIIX_PORT_ENABLED << i);
if ((orig_mask & mask) == mask)
if (combined || (i == ap->hard_port_no))
@@ -548,25 +568,12 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
}
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
-}
-
#define AHCI_PCI_BAR 5
#define AHCI_GLOBAL_CTL 0x04
#define AHCI_ENABLE (1 << 31)
static int piix_disable_ahci(struct pci_dev *pdev)
{
- void *mmio;
- unsigned long addr;
+ void __iomem *mmio;
u32 tmp;
int rc = 0;
@@ -574,11 +581,11 @@ static int piix_disable_ahci(struct pci_dev *pdev)
* works because this device is usually set up by BIOS.
*/
- addr = pci_resource_start(pdev, AHCI_PCI_BAR);
- if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+ if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
+ !pci_resource_len(pdev, AHCI_PCI_BAR))
return 0;
- mmio = ioremap(addr, 64);
+ mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
if (!mmio)
return -ENOMEM;
@@ -592,7 +599,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
rc = -EIO;
}
- iounmap(mmio);
+ pci_iounmap(pdev, mmio);
return rc;
}
@@ -629,13 +636,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
port_info[1] = NULL;
if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
- u8 tmp;
- pci_read_config_byte(pdev, PIIX_SCC, &tmp);
- if (tmp == PIIX_AHCI_DEVICE) {
- int rc = piix_disable_ahci(pdev);
- if (rc)
- return rc;
- }
+ u8 tmp;
+ pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+ if (tmp == PIIX_AHCI_DEVICE) {
+ int rc = piix_disable_ahci(pdev);
+ if (rc)
+ return rc;
+ }
}
if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
@@ -658,7 +665,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
* message-signalled interrupts currently).
*/
if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
if (combined) {
port_info[sata_chan] = &piix_port_info[ent->driver_data];
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 3900e28ac7d6..da6e51c7fe69 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/chio.h> /* here are all the ioctls */
@@ -31,7 +30,7 @@
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_dbg.h>
#define CH_DT_MAX 16
@@ -117,7 +116,7 @@ typedef struct {
} scsi_changer;
static LIST_HEAD(ch_devlist);
-static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ch_devlist_lock);
static int ch_devcount;
static struct scsi_driver ch_template =
@@ -181,17 +180,17 @@ static struct {
/* ------------------------------------------------------------------- */
-static int ch_find_errno(unsigned char *sense_buffer)
+static int ch_find_errno(struct scsi_sense_hdr *sshdr)
{
int i,errno = 0;
/* Check to see if additional sense information is available */
- if (sense_buffer[7] > 5 &&
- sense_buffer[12] != 0) {
+ if (scsi_sense_valid(sshdr) &&
+ sshdr->asc != 0) {
for (i = 0; err[i].errno != 0; i++) {
- if (err[i].sense == sense_buffer[ 2] &&
- err[i].asc == sense_buffer[12] &&
- err[i].ascq == sense_buffer[13]) {
+ if (err[i].sense == sshdr->sense_key &&
+ err[i].asc == sshdr->asc &&
+ err[i].ascq == sshdr->ascq) {
errno = -err[i].errno;
break;
}
@@ -207,13 +206,9 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
void *buffer, unsigned buflength,
enum dma_data_direction direction)
{
- int errno, retries = 0, timeout;
- struct scsi_request *sr;
+ int errno, retries = 0, timeout, result;
+ struct scsi_sense_hdr sshdr;
- sr = scsi_allocate_request(ch->device, GFP_KERNEL);
- if (NULL == sr)
- return -ENOMEM;
-
timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
? timeout_init : timeout_move;
@@ -224,16 +219,17 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
__scsi_print_command(cmd);
}
- scsi_wait_req(sr, cmd, buffer, buflength,
- timeout * HZ, MAX_RETRIES);
+ result = scsi_execute_req(ch->device, cmd, direction, buffer,
+ buflength, &sshdr, timeout * HZ,
+ MAX_RETRIES);
- dprintk("result: 0x%x\n",sr->sr_result);
- if (driver_byte(sr->sr_result) & DRIVER_SENSE) {
+ dprintk("result: 0x%x\n",result);
+ if (driver_byte(result) & DRIVER_SENSE) {
if (debug)
- scsi_print_req_sense(ch->name, sr);
- errno = ch_find_errno(sr->sr_sense_buffer);
+ scsi_print_sense_hdr(ch->name, &sshdr);
+ errno = ch_find_errno(&sshdr);
- switch(sr->sr_sense_buffer[2] & 0xf) {
+ switch(sshdr.sense_key) {
case UNIT_ATTENTION:
ch->unit_attention = 1;
if (retries++ < 3)
@@ -241,7 +237,6 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
break;
}
}
- scsi_release_request(sr);
return errno;
}
@@ -565,7 +560,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
return result;
}
-static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
+static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
{
int retval = 0;
u_char data[16];
@@ -639,6 +634,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
scsi_changer *ch = file->private_data;
int retval;
+ void __user *argp = (void __user *)arg;
switch (cmd) {
case CHIOGPARAMS:
@@ -651,7 +647,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
params.cp_nportals = ch->counts[CHET_IE];
params.cp_ndrives = ch->counts[CHET_DT];
- if (copy_to_user((void *) arg, &params, sizeof(params)))
+ if (copy_to_user(argp, &params, sizeof(params)))
return -EFAULT;
return 0;
}
@@ -676,7 +672,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
vparams.cvp_n4 = ch->counts[CHET_V4];
strncpy(vparams.cvp_label4,vendor_labels[3],16);
}
- if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
+ if (copy_to_user(argp, &vparams, sizeof(vparams)))
return -EFAULT;
return 0;
}
@@ -685,7 +681,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_position pos;
- if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
+ if (copy_from_user(&pos, argp, sizeof (pos)))
return -EFAULT;
if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
@@ -704,7 +700,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_move mv;
- if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ if (copy_from_user(&mv, argp, sizeof (mv)))
return -EFAULT;
if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
@@ -726,7 +722,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_exchange mv;
- if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ if (copy_from_user(&mv, argp, sizeof (mv)))
return -EFAULT;
if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) ||
@@ -751,7 +747,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_element_status ces;
- if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
+ if (copy_from_user(&ces, argp, sizeof (ces)))
return -EFAULT;
if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
return -EINVAL;
@@ -767,7 +763,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
unsigned int elem;
int result,i;
- if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
+ if (copy_from_user(&cge, argp, sizeof (cge)))
return -EFAULT;
if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
@@ -830,7 +826,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
kfree(buffer);
up(&ch->lock);
- if (copy_to_user((void*)arg, &cge, sizeof (cge)))
+ if (copy_to_user(argp, &cge, sizeof (cge)))
return -EFAULT;
return result;
}
@@ -848,7 +844,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
struct changer_set_voltag csv;
int elem;
- if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
+ if (copy_from_user(&csv, argp, sizeof(csv)))
return -EFAULT;
if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
@@ -866,7 +862,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
}
default:
- return scsi_ioctl(ch->device, cmd, (void*)arg);
+ return scsi_ioctl(ch->device, cmd, argp);
}
}
@@ -899,9 +895,9 @@ static long ch_ioctl_compat(struct file * file,
case CHIOGSTATUS32:
{
struct changer_element_status32 ces32;
- unsigned char *data;
+ unsigned char __user *data;
- if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
+ if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
return -EFAULT;
if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
return -EINVAL;
@@ -940,8 +936,6 @@ static int ch_probe(struct device *dev)
if (init)
ch_init_elem(ch);
- devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
- S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
class_device_create(ch_sysfs_class,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
dev, "s%s", ch->name);
@@ -974,7 +968,6 @@ static int ch_remove(struct device *dev)
class_device_destroy(ch_sysfs_class,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
- devfs_remove(ch->name);
kfree(ch->dt);
kfree(ch);
ch_devcount--;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index ec161733a82b..f6be2c1c3942 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -17,6 +17,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_eh.h>
+#include <scsi/scsi_dbg.h>
@@ -1155,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
}
}
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+ const char *sense_txt;
+ /* An example of deferred is when an earlier write to disk cache
+ * succeeded, but now the disk discovers that it cannot write the
+ * data to the magnetic media.
+ */
+ const char *error = scsi_sense_is_deferred(sshdr) ?
+ "<<DEFERRED>>" : "Current";
+ printk(KERN_INFO "%s: %s", name, error);
+ if (sshdr->response_code >= 0x72)
+ printk(" [descriptor]");
+
+ sense_txt = scsi_sense_key_string(sshdr->sense_key);
+ if (sense_txt)
+ printk(": sense key: %s\n", sense_txt);
+ else
+ printk(": sense key=0x%x\n", sshdr->sense_key);
+ printk(KERN_INFO " ");
+ scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+ printk("\n");
+}
+EXPORT_SYMBOL(scsi_print_sense_hdr);
+
/* Print sense information */
void
__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
@@ -1162,8 +1188,6 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
{
int k, num, res;
unsigned int info;
- const char *error;
- const char *sense_txt;
struct scsi_sense_hdr ssh;
res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
@@ -1181,26 +1205,7 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
printk("\n");
return;
}
-
- /* An example of deferred is when an earlier write to disk cache
- * succeeded, but now the disk discovers that it cannot write the
- * data to the magnetic media.
- */
- error = scsi_sense_is_deferred(&ssh) ?
- "<<DEFERRED>>" : "Current";
- printk(KERN_INFO "%s: %s", name, error);
- if (ssh.response_code >= 0x72)
- printk(" [descriptor]");
-
- sense_txt = scsi_sense_key_string(ssh.sense_key);
- if (sense_txt)
- printk(": sense key: %s\n", sense_txt);
- else
- printk(": sense key=0x%x\n", ssh.sense_key);
- printk(KERN_INFO " ");
- scsi_show_extd_sense(ssh.asc, ssh.ascq);
- printk("\n");
-
+ scsi_print_sense_hdr(name, &ssh);
if (ssh.response_code < 0x72) {
/* only decode extras for "fixed" format now */
char buff[80];
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index d72be0ce89c8..3fda8d455c5b 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -691,8 +691,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg)
if( copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
result = -EFAULT;
- if( buf)
- kfree( buf);
+ kfree(buf);
return result;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5feb886c3392..85503fad789a 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/init.h>
@@ -52,21 +53,80 @@ static struct class shost_class = {
};
/**
- * scsi_host_cancel - cancel outstanding IO to this host
- * @shost: pointer to struct Scsi_Host
- * recovery: recovery requested to run.
+ * scsi_host_set_state - Take the given host through the host
+ * state model.
+ * @shost: scsi host to change the state of.
+ * @state: state to change to.
+ *
+ * Returns zero if unsuccessful or an error if the requested
+ * transition is illegal.
**/
-static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
+int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
{
- struct scsi_device *sdev;
+ enum scsi_host_state oldstate = shost->shost_state;
+
+ if (state == oldstate)
+ return 0;
+
+ switch (state) {
+ case SHOST_CREATED:
+ /* There are no legal states that come back to
+ * created. This is the manually initialised start
+ * state */
+ goto illegal;
+
+ case SHOST_RUNNING:
+ switch (oldstate) {
+ case SHOST_CREATED:
+ case SHOST_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_RECOVERY:
+ switch (oldstate) {
+ case SHOST_RUNNING:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_CANCEL:
+ switch (oldstate) {
+ case SHOST_CREATED:
+ case SHOST_RUNNING:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_DEL:
+ switch (oldstate) {
+ case SHOST_CANCEL:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
- set_bit(SHOST_CANCEL, &shost->shost_state);
- shost_for_each_device(sdev, shost) {
- scsi_device_cancel(sdev, recovery);
}
- wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY,
- &shost->shost_state)));
+ shost->shost_state = state;
+ return 0;
+
+ illegal:
+ SCSI_LOG_ERROR_RECOVERY(1,
+ dev_printk(KERN_ERR, &shost->shost_gendev,
+ "Illegal host state transition"
+ "%s->%s\n",
+ scsi_host_state_name(oldstate),
+ scsi_host_state_name(state)));
+ return -EINVAL;
}
+EXPORT_SYMBOL(scsi_host_set_state);
/**
* scsi_remove_host - remove a scsi host
@@ -74,11 +134,13 @@ static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/
void scsi_remove_host(struct Scsi_Host *shost)
{
+ down(&shost->scan_mutex);
+ scsi_host_set_state(shost, SHOST_CANCEL);
+ up(&shost->scan_mutex);
scsi_forget_host(shost);
- scsi_host_cancel(shost, 0);
scsi_proc_host_rm(shost);
- set_bit(SHOST_DEL, &shost->shost_state);
+ scsi_host_set_state(shost, SHOST_DEL);
transport_unregister_device(&shost->shost_gendev);
class_device_unregister(&shost->shost_classdev);
@@ -115,7 +177,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (error)
goto out;
- set_bit(SHOST_ADD, &shost->shost_state);
+ scsi_host_set_state(shost, SHOST_RUNNING);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
@@ -164,15 +226,8 @@ static void scsi_host_dev_release(struct device *dev)
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
- if (shost->ehandler) {
- DECLARE_COMPLETION(sem);
- shost->eh_notify = &sem;
- shost->eh_kill = 1;
- up(shost->eh_wait);
- wait_for_completion(&sem);
- shost->eh_notify = NULL;
- }
-
+ if (shost->ehandler)
+ kthread_stop(shost->ehandler);
if (shost->work_q)
destroy_workqueue(shost->work_q);
@@ -202,7 +257,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
{
struct Scsi_Host *shost;
int gfp_mask = GFP_KERNEL, rval;
- DECLARE_COMPLETION(complete);
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
@@ -226,6 +280,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock);
+ shost->shost_state = SHOST_CREATED;
INIT_LIST_HEAD(&shost->__devices);
INIT_LIST_HEAD(&shost->__targets);
INIT_LIST_HEAD(&shost->eh_cmd_q);
@@ -307,12 +362,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
- shost->eh_notify = &complete;
- rval = kernel_thread(scsi_error_handler, shost, 0);
- if (rval < 0)
+ shost->ehandler = kthread_run(scsi_error_handler, shost,
+ "scsi_eh_%d", shost->host_no);
+ if (IS_ERR(shost->ehandler)) {
+ rval = PTR_ERR(shost->ehandler);
goto fail_destroy_freelist;
- wait_for_completion(&complete);
- shost->eh_notify = NULL;
+ }
scsi_proc_hostdir_add(shost->hostt);
return shost;
@@ -382,7 +437,7 @@ EXPORT_SYMBOL(scsi_host_lookup);
**/
struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
{
- if (test_bit(SHOST_DEL, &shost->shost_state) ||
+ if ((shost->shost_state == SHOST_DEL) ||
!get_device(&shost->shost_gendev))
return NULL;
return shost;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index b5dc35355570..6e54c7d9b33c 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -36,7 +36,6 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/mca.h>
-#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/mca-legacy.h>
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fe09d145542a..5b14934ba861 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
-#define IBMVSCSI_VERSION "1.5.6"
+#define IBMVSCSI_VERSION "1.5.7"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@@ -145,6 +145,8 @@ static int initialize_event_pool(struct event_pool *pool,
sizeof(*evt->xfer_iu) * i;
evt->xfer_iu = pool->iu_storage + i;
evt->hostdata = hostdata;
+ evt->ext_list = NULL;
+ evt->ext_list_token = 0;
}
return 0;
@@ -161,9 +163,16 @@ static void release_event_pool(struct event_pool *pool,
struct ibmvscsi_host_data *hostdata)
{
int i, in_use = 0;
- for (i = 0; i < pool->size; ++i)
+ for (i = 0; i < pool->size; ++i) {
if (atomic_read(&pool->events[i].free) != 1)
++in_use;
+ if (pool->events[i].ext_list) {
+ dma_free_coherent(hostdata->dev,
+ SG_ALL * sizeof(struct memory_descriptor),
+ pool->events[i].ext_list,
+ pool->events[i].ext_list_token);
+ }
+ }
if (in_use)
printk(KERN_WARNING
"ibmvscsi: releasing event pool with %d "
@@ -286,24 +295,41 @@ static void set_srp_direction(struct scsi_cmnd *cmd,
} else {
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_out_count = numbuf;
+ 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;
+ srp_cmd->data_in_count =
+ numbuf < MAX_INDIRECT_BUFS ?
+ numbuf: MAX_INDIRECT_BUFS;
}
}
}
+static void unmap_sg_list(int num_entries,
+ struct device *dev,
+ struct memory_descriptor *md)
+{
+ int i;
+
+ for (i = 0; i < num_entries; ++i) {
+ dma_unmap_single(dev,
+ md[i].virtual_address,
+ md[i].length, DMA_BIDIRECTIONAL);
+ }
+}
+
/**
* unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
* @cmd: srp_cmd whose additional_data member will be unmapped
* @dev: device for which the memory is mapped
*
*/
-static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+static void unmap_cmd_data(struct srp_cmd *cmd,
+ struct srp_event_struct *evt_struct,
+ struct device *dev)
{
- int i;
-
if ((cmd->data_out_format == SRP_NO_BUFFER) &&
(cmd->data_in_format == SRP_NO_BUFFER))
return;
@@ -318,15 +344,34 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
(struct indirect_descriptor *)cmd->additional_data;
int num_mapped = indirect->head.length /
sizeof(indirect->list[0]);
- for (i = 0; i < num_mapped; ++i) {
- struct memory_descriptor *data = &indirect->list[i];
- dma_unmap_single(dev,
- data->virtual_address,
- data->length, DMA_BIDIRECTIONAL);
+
+ if (num_mapped <= MAX_INDIRECT_BUFS) {
+ unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+ return;
}
+
+ unmap_sg_list(num_mapped, dev, evt_struct->ext_list);
}
}
+static int map_sg_list(int num_entries,
+ struct scatterlist *sg,
+ struct memory_descriptor *md)
+{
+ int i;
+ u64 total_length = 0;
+
+ for (i = 0; i < num_entries; ++i) {
+ struct memory_descriptor *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;
+ total_length += sg_dma_len(sg_entry);
+ }
+ return total_length;
+}
+
/**
* map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
* @cmd: Scsi_Cmnd with the scatterlist
@@ -337,10 +382,11 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
* Returns 1 on success.
*/
static int map_sg_data(struct scsi_cmnd *cmd,
+ struct srp_event_struct *evt_struct,
struct srp_cmd *srp_cmd, struct device *dev)
{
- int i, sg_mapped;
+ int sg_mapped;
u64 total_length = 0;
struct scatterlist *sg = cmd->request_buffer;
struct memory_descriptor *data =
@@ -363,27 +409,46 @@ static int map_sg_data(struct scsi_cmnd *cmd,
return 1;
}
- if (sg_mapped > MAX_INDIRECT_BUFS) {
+ if (sg_mapped > SG_ALL) {
printk(KERN_ERR
"ibmvscsi: More than %d mapped sg entries, got %d\n",
- MAX_INDIRECT_BUFS, sg_mapped);
+ SG_ALL, sg_mapped);
return 0;
}
indirect->head.virtual_address = 0;
indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
indirect->head.memory_handle = 0;
- for (i = 0; i < sg_mapped; ++i) {
- struct memory_descriptor *descr = &indirect->list[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;
- total_length += sg_dma_len(sg_entry);
+
+ if (sg_mapped <= MAX_INDIRECT_BUFS) {
+ total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
+ indirect->total_length = total_length;
+ return 1;
}
- indirect->total_length = total_length;
- return 1;
+ /* get indirect table */
+ if (!evt_struct->ext_list) {
+ evt_struct->ext_list =(struct memory_descriptor*)
+ dma_alloc_coherent(dev,
+ SG_ALL * sizeof(struct memory_descriptor),
+ &evt_struct->ext_list_token, 0);
+ if (!evt_struct->ext_list) {
+ printk(KERN_ERR
+ "ibmvscsi: Can't allocate memory for indirect table\n");
+ return 0;
+
+ }
+ }
+
+ 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));
+
+ return 1;
}
/**
@@ -428,6 +493,7 @@ static int map_single_data(struct scsi_cmnd *cmd,
* Returns 1 on success.
*/
static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+ struct srp_event_struct *evt_struct,
struct srp_cmd *srp_cmd, struct device *dev)
{
switch (cmd->sc_data_direction) {
@@ -450,7 +516,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
if (!cmd->request_buffer)
return 1;
if (cmd->use_sg)
- return map_sg_data(cmd, srp_cmd, dev);
+ return map_sg_data(cmd, evt_struct, srp_cmd, dev);
return map_single_data(cmd, srp_cmd, dev);
}
@@ -486,6 +552,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
printk(KERN_WARNING
"ibmvscsi: Warning, request_limit exceeded\n");
unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ evt_struct,
hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -513,7 +580,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
return 0;
send_error:
- unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+ unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
if ((cmnd = evt_struct->cmnd) != NULL) {
cmnd->result = DID_ERROR << 16;
@@ -551,6 +618,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
rsp->sense_and_response_data,
rsp->sense_data_list_length);
unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ evt_struct,
evt_struct->hostdata->dev);
if (rsp->doover)
@@ -583,6 +651,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
{
struct srp_cmd *srp_cmd;
struct srp_event_struct *evt_struct;
+ struct indirect_descriptor *indirect;
struct ibmvscsi_host_data *hostdata =
(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
u16 lun = lun_from_dev(cmnd->device);
@@ -591,14 +660,6 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
if (!evt_struct)
return SCSI_MLQUEUE_HOST_BUSY;
- init_event_struct(evt_struct,
- handle_cmd_rsp,
- VIOSRP_SRP_FORMAT,
- cmnd->timeout);
-
- evt_struct->cmnd = cmnd;
- evt_struct->cmnd_done = done;
-
/* Set up the actual SRP IU */
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, sizeof(*srp_cmd));
@@ -606,17 +667,25 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
srp_cmd->lun = ((u64) lun) << 48;
- if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+ if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
}
+ init_event_struct(evt_struct,
+ handle_cmd_rsp,
+ VIOSRP_SRP_FORMAT,
+ cmnd->timeout_per_command/HZ);
+
+ evt_struct->cmnd = cmnd;
+ evt_struct->cmnd_done = done;
+
/* Fix up dma address of the buffer itself */
- if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
- (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)srp_cmd->additional_data;
+ 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);
@@ -826,11 +895,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *found_evt;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
* out the correct tag
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -839,11 +910,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
- if (!found_evt)
+ if (!found_evt) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return FAILED;
+ }
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
return FAILED;
}
@@ -867,7 +941,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
return FAILED;
}
@@ -901,6 +977,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -910,6 +987,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
if (found_evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
tsk_mgmt->managed_task_tag);
@@ -922,8 +1000,10 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
- unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+ unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt,
+ found_evt->hostdata->dev);
free_event_struct(&found_evt->hostdata->pool, found_evt);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
atomic_inc(&hostdata->request_limit);
return SUCCESS;
}
@@ -943,10 +1023,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *pos;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
return FAILED;
}
@@ -969,7 +1052,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
return FAILED;
}
@@ -1002,12 +1087,14 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
if (tmp_evt->cmnd)
tmp_evt->cmnd->result = (DID_RESET << 16);
list_del(&tmp_evt->list);
- unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+ unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt,
+ tmp_evt->hostdata->dev);
free_event_struct(&tmp_evt->hostdata->pool,
tmp_evt);
atomic_inc(&hostdata->request_limit);
@@ -1017,6 +1104,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
tmp_evt->done(tmp_evt);
}
}
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return SUCCESS;
}
@@ -1035,6 +1123,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata)
if (tmp_evt->cmnd) {
tmp_evt->cmnd->result = (DID_ERROR << 16);
unmap_cmd_data(&tmp_evt->iu.srp.cmd,
+ tmp_evt,
tmp_evt->hostdata->dev);
if (tmp_evt->cmnd_done)
tmp_evt->cmnd_done(tmp_evt->cmnd);
@@ -1339,7 +1428,7 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 16,
.can_queue = 1, /* Updated after SRP_LOGIN */
.this_id = -1,
- .sg_tablesize = MAX_INDIRECT_BUFS,
+ .sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = ibmvscsi_attrs,
};
@@ -1442,7 +1531,7 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
*/
static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
{"vscsi", "IBM,v-scsi"},
- {0,}
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 1030b703c30e..8bec0438dc8a 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,6 +68,8 @@ struct srp_event_struct {
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
union viosrp_iu *sync_srp;
+ struct memory_descriptor *ext_list;
+ dma_addr_t ext_list_token;
};
/* a pool of event structs for use */
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 035f615817d7..8bf5652f1060 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -28,6 +28,7 @@
*/
#include <asm/vio.h>
+#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/hvcall.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index f4e7dcb6492b..5cc53cd9323e 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1,25 +1,35 @@
/*
- libata-core.c - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
+ * libata-core.c - helper library for ATA
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from http://www.t13.org/ and
+ * http://www.sata-io.org/
+ *
*/
#include <linux/config.h>
@@ -65,6 +75,10 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
+int atapi_enabled = 0;
+module_param(atapi_enabled, int, 0444);
+MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
@@ -1304,12 +1318,12 @@ static inline u8 ata_dev_knobble(struct ata_port *ap)
/**
* ata_dev_config - Run device specific handlers and check for
* SATA->PATA bridges
- * @ap: Bus
+ * @ap: Bus
* @i: Device
*
* LOCKING:
*/
-
+
void ata_dev_config(struct ata_port *ap, unsigned int i)
{
/* limit bridge transfers to udma5, 200 sectors */
@@ -2377,6 +2391,27 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
}
/**
+ * ata_poll_qc_complete - turn irq back on and finish qc
+ * @qc: Command to complete
+ * @drv_stat: ATA status register content
+ *
+ * LOCKING:
+ * None. (grabs host lock)
+ */
+
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+ struct ata_port *ap = qc->ap;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_irq_on(ap);
+ ata_qc_complete(qc, drv_stat);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+}
+
+/**
* ata_pio_poll -
* @ap:
*
@@ -2438,11 +2473,10 @@ static void ata_pio_complete (struct ata_port *ap)
u8 drv_stat;
/*
- * This is purely hueristic. This is a fast path.
- * Sometimes when we enter, BSY will be cleared in
- * a chk-status or two. If not, the drive is probably seeking
- * or something. Snooze for a couple msecs, then
- * chk-status again. If still busy, fall back to
+ * This is purely heuristic. This is a fast path. Sometimes when
+ * we enter, BSY will be cleared in a chk-status or two. If not,
+ * the drive is probably seeking or something. Snooze for a couple
+ * msecs, then chk-status again. If still busy, fall back to
* PIO_ST_POLL state.
*/
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
@@ -2467,9 +2501,7 @@ static void ata_pio_complete (struct ata_port *ap)
ap->pio_task_state = PIO_ST_IDLE;
- ata_irq_on(ap);
-
- ata_qc_complete(qc, drv_stat);
+ ata_poll_qc_complete(qc, drv_stat);
}
@@ -2494,6 +2526,20 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
#endif /* __BIG_ENDIAN */
}
+/**
+ * ata_mmio_data_xfer - Transfer data by MMIO
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @write_data: read/write
+ *
+ * Transfer data from/to the device data register by MMIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int write_data)
{
@@ -2502,6 +2548,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
u16 *buf16 = (u16 *) buf;
void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+ /* Transfer multiple of 2 bytes */
if (write_data) {
for (i = 0; i < words; i++)
writew(le16_to_cpu(buf16[i]), mmio);
@@ -2509,19 +2556,76 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
for (i = 0; i < words; i++)
buf16[i] = cpu_to_le16(readw(mmio));
}
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ u16 align_buf[1] = { 0 };
+ unsigned char *trailing_buf = buf + buflen - 1;
+
+ if (write_data) {
+ memcpy(align_buf, trailing_buf, 1);
+ writew(le16_to_cpu(align_buf[0]), mmio);
+ } else {
+ align_buf[0] = cpu_to_le16(readw(mmio));
+ memcpy(trailing_buf, align_buf, 1);
+ }
+ }
}
+/**
+ * ata_pio_data_xfer - Transfer data by PIO
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @write_data: read/write
+ *
+ * Transfer data from/to the device data register by PIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int write_data)
{
- unsigned int dwords = buflen >> 1;
+ unsigned int words = buflen >> 1;
+ /* Transfer multiple of 2 bytes */
if (write_data)
- outsw(ap->ioaddr.data_addr, buf, dwords);
+ outsw(ap->ioaddr.data_addr, buf, words);
else
- insw(ap->ioaddr.data_addr, buf, dwords);
+ insw(ap->ioaddr.data_addr, buf, words);
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ u16 align_buf[1] = { 0 };
+ unsigned char *trailing_buf = buf + buflen - 1;
+
+ if (write_data) {
+ memcpy(align_buf, trailing_buf, 1);
+ outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+ } else {
+ align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+ memcpy(trailing_buf, align_buf, 1);
+ }
+ }
}
+/**
+ * ata_data_xfer - Transfer data from/to the data register.
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @do_write: read/write
+ *
+ * Transfer data from/to the device data register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int do_write)
{
@@ -2531,6 +2635,16 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
ata_pio_data_xfer(ap, buf, buflen, do_write);
}
+/**
+ * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ * @qc: Command on going
+ *
+ * Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void ata_pio_sector(struct ata_queued_cmd *qc)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2569,6 +2683,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
kunmap(page);
}
+/**
+ * __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ * @qc: Command on going
+ * @bytes: number of bytes
+ *
+ * Transfer Transfer data from/to the ATAPI device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2578,10 +2704,33 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
unsigned char *buf;
unsigned int offset, count;
- if (qc->curbytes == qc->nbytes - bytes)
+ if (qc->curbytes + bytes >= qc->nbytes)
ap->pio_task_state = PIO_ST_LAST;
next_sg:
+ if (unlikely(qc->cursg >= qc->n_elem)) {
+ /*
+ * The end of qc->sg is reached and the device expects
+ * more data to transfer. In order not to overrun qc->sg
+ * and fulfill length specified in the byte count register,
+ * - for read case, discard trailing data from the device
+ * - for write case, padding zero data to the device
+ */
+ u16 pad_buf[1] = { 0 };
+ unsigned int words = bytes >> 1;
+ unsigned int i;
+
+ if (words) /* warning if bytes > 1 */
+ printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
+ ap->id, bytes);
+
+ for (i = 0; i < words; i++)
+ ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+ ap->pio_task_state = PIO_ST_LAST;
+ return;
+ }
+
sg = &qc->sg[qc->cursg];
page = sg->page;
@@ -2615,11 +2764,21 @@ next_sg:
kunmap(page);
- if (bytes) {
+ if (bytes)
goto next_sg;
- }
}
+/**
+ * atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ * @qc: Command on going
+ *
+ * Transfer Transfer data from/to the ATAPI device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void atapi_pio_bytes(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -2692,9 +2851,7 @@ static void ata_pio_block(struct ata_port *ap)
if ((status & ATA_DRQ) == 0) {
ap->pio_task_state = PIO_ST_IDLE;
- ata_irq_on(ap);
-
- ata_qc_complete(qc, status);
+ ata_poll_qc_complete(qc, status);
return;
}
@@ -2724,9 +2881,7 @@ static void ata_pio_error(struct ata_port *ap)
ap->pio_task_state = PIO_ST_IDLE;
- ata_irq_on(ap);
-
- ata_qc_complete(qc, drv_stat | ATA_ERR);
+ ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
}
static void ata_pio_task(void *_data)
@@ -2832,8 +2987,10 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
static void ata_qc_timeout(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ struct ata_host_set *host_set = ap->host_set;
struct ata_device *dev = qc->dev;
u8 host_stat = 0, drv_stat;
+ unsigned long flags;
DPRINTK("ENTER\n");
@@ -2844,7 +3001,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
/* finish completing original command */
+ spin_lock_irqsave(&host_set->lock, flags);
__ata_qc_complete(qc);
+ spin_unlock_irqrestore(&host_set->lock, flags);
atapi_request_sense(ap, dev, cmd);
@@ -2855,6 +3014,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
}
}
+ spin_lock_irqsave(&host_set->lock, flags);
+
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
@@ -2870,7 +3031,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ap->ops->bmdma_stop(qc);
/* fall through */
@@ -2888,6 +3049,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
ata_qc_complete(qc, drv_stat);
break;
}
+
+ spin_unlock_irqrestore(&host_set->lock, flags);
+
out:
DPRINTK("EXIT\n");
}
@@ -3061,9 +3225,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
+ /* atapi: mark qc as inactive to prevent the interrupt handler
+ * from completing the command twice later, before the error handler
+ * is called. (when rc != 0 and atapi request sense is needed)
+ */
+ qc->flags &= ~ATA_QCFLAG_ACTIVE;
+
/* call completion callback */
rc = qc->complete_fn(qc, drv_stat);
- qc->flags &= ~ATA_QCFLAG_ACTIVE;
/* if callback indicates not to complete command (non-zero),
* return immediately
@@ -3193,11 +3362,13 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
break;
case ATA_PROT_ATAPI_NODATA:
+ ap->flags |= ATA_FLAG_NOINTR;
ata_tf_to_host_nolock(ap, &qc->tf);
queue_work(ata_wq, &ap->packet_task);
break;
case ATA_PROT_ATAPI_DMA:
+ ap->flags |= ATA_FLAG_NOINTR;
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
queue_work(ata_wq, &ap->packet_task);
@@ -3242,7 +3413,7 @@ static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
}
/**
- * ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
@@ -3413,7 +3584,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
/**
* ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- * @ap: Port associated with this ATA transaction.
+ * @qc: Command we are ending DMA for
*
* Clears the ATA_DMA_START flag in the dma control register
*
@@ -3423,8 +3594,9 @@ u8 ata_bmdma_status(struct ata_port *ap)
* spin_lock_irqsave(host_set lock)
*/
-void ata_bmdma_stop(struct ata_port *ap)
+void ata_bmdma_stop(struct ata_queued_cmd *qc)
{
+ struct ata_port *ap = qc->ap;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
@@ -3476,7 +3648,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ap->ops->bmdma_stop(qc);
/* fall through */
@@ -3551,7 +3723,8 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -3603,19 +3776,27 @@ static void atapi_packet_task(void *_data)
/* send SCSI cdb */
DPRINTK("send cdb\n");
assert(ap->cdb_len >= 12);
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
- /* if we are DMA'ing, irq handler takes over from here */
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
- ap->ops->bmdma_start(qc); /* initiate bmdma */
+ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+ unsigned long flags;
- /* non-data commands are also handled via irq */
- else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
- /* do nothing */
- }
+ /* Once we're done issuing command and kicking bmdma,
+ * irq handler takes over. To not lose irq, we need
+ * to clear NOINTR flag before sending cdb, but
+ * interrupt handler shouldn't be invoked before we're
+ * finished. Hence, the following locking.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+ 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, ap->cdb_len, 1);
- /* PIO commands are handled by polling */
- else {
+ /* PIO commands are handled by polling */
ap->pio_task_state = PIO_ST;
queue_work(ata_wq, &ap->pio_task);
}
@@ -3623,7 +3804,7 @@ static void atapi_packet_task(void *_data)
return;
err_out:
- ata_qc_complete(qc, ATA_ERR);
+ ata_poll_qc_complete(qc, ATA_ERR);
}
@@ -4023,6 +4204,15 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+#ifdef CONFIG_PCI
+
+void ata_pci_host_stop (struct ata_host_set *host_set)
+{
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+ pci_iounmap(pdev, host_set->mmio_base);
+}
+
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
@@ -4035,7 +4225,6 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
* ata_probe_ent structure should then be freed with kfree().
*/
-#ifdef CONFIG_PCI
struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
@@ -4418,6 +4607,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_simulate);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_host_stop);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 6a75ec2187fd..104fd9a63e73 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1,25 +1,36 @@
/*
- libata-scsi.c - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
+ * libata-scsi.c - helper library for ATA
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from
+ * - http://www.t10.org/
+ * - http://www.t13.org/
+ *
*/
#include <linux/kernel.h>
@@ -392,6 +403,60 @@ int ata_scsi_error(struct Scsi_Host *host)
}
/**
+ * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ * @qc: Storage for translated ATA taskfile
+ * @scsicmd: SCSI command to translate
+ *
+ * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ * (to start). Perhaps these commands should be preceded by
+ * CHECK POWER MODE to see what power mode the device is already in.
+ * [See SAT revision 5 at www.t10.org]
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+ u8 *scsicmd)
+{
+ struct ata_taskfile *tf = &qc->tf;
+
+ tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf->protocol = ATA_PROT_NODATA;
+ if (scsicmd[1] & 0x1) {
+ ; /* ignore IMMED bit, violates sat-r05 */
+ }
+ if (scsicmd[4] & 0x2)
+ return 1; /* LOEJ bit set not supported */
+ if (((scsicmd[4] >> 4) & 0xf) != 0)
+ return 1; /* power conditions not supported */
+ if (scsicmd[4] & 0x1) {
+ tf->nsect = 1; /* 1 sector, lba=0 */
+ tf->lbah = 0x0;
+ tf->lbam = 0x0;
+ tf->lbal = 0x0;
+ tf->device |= ATA_LBA;
+ tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
+ } else {
+ tf->nsect = 0; /* time period value (0 implies now) */
+ tf->command = ATA_CMD_STANDBY;
+ /* Consider: ATA STANDBY IMMEDIATE command */
+ }
+ /*
+ * Standby and Idle condition timers could be implemented but that
+ * would require libata to implement the Power condition mode page
+ * and allow the user to change it. Changing mode pages requires
+ * MODE SELECT to be implemented.
+ */
+
+ return 0;
+}
+
+
+/**
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
* @qc: Storage for translated ATA taskfile
* @scsicmd: SCSI command to translate (ignored)
@@ -576,11 +641,19 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
tf->lbah = scsicmd[3];
VPRINTK("ten-byte command\n");
+ if (qc->nsect == 0) /* we don't support length==0 cmds */
+ return 1;
return 0;
}
if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
qc->nsect = tf->nsect = scsicmd[4];
+ if (!qc->nsect) {
+ qc->nsect = 256;
+ if (lba48)
+ tf->hob_nsect = 1;
+ }
+
tf->lbal = scsicmd[3];
tf->lbam = scsicmd[2];
tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
@@ -620,6 +693,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
tf->lbah = scsicmd[7];
VPRINTK("sixteen-byte command\n");
+ if (qc->nsect == 0) /* we don't support length==0 cmds */
+ return 1;
return 0;
}
@@ -1395,10 +1470,10 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
if (unlikely(!ata_dev_present(dev)))
return NULL;
-#ifndef ATA_ENABLE_ATAPI
- if (unlikely(dev->class == ATA_DEV_ATAPI))
- return NULL;
-#endif
+ if (!atapi_enabled) {
+ if (unlikely(dev->class == ATA_DEV_ATAPI))
+ return NULL;
+ }
return dev;
}
@@ -1435,6 +1510,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case VERIFY:
case VERIFY_16:
return ata_scsi_verify_xlat;
+ case START_STOP:
+ return ata_scsi_start_stop_xlat;
}
return NULL;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 3e7f4843020f..d608b3a0f6fe 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -1,25 +1,28 @@
/*
- libata.h - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
+ * libata.h - helper library for ATA
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
*/
#ifndef __LIBATA_H__
@@ -35,6 +38,7 @@ struct ata_scsi_args {
};
/* libata-core.c */
+extern int atapi_enabled;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
extern void ata_qc_free(struct ata_queued_cmd *qc);
@@ -72,7 +76,7 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3bb82aae432e..adb95674823f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -342,9 +342,6 @@ struct lpfc_hba {
#define VPD_MASK 0xf /* mask for any vpd data */
struct timer_list els_tmofunc;
-
- void *link_stats;
-
/*
* stat counters
*/
@@ -370,6 +367,8 @@ struct lpfc_hba {
struct list_head freebufList;
struct list_head ctrspbuflist;
struct list_head rnidrspbuflist;
+
+ struct fc_host_statistics link_stats;
};
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3cea92883019..86eaf6d408d5 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
@@ -965,21 +966,21 @@ static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
- u64 nodename;
+ u64 node_name;
spin_lock_irq(shost->host_lock);
if ((phba->fc_flag & FC_FABRIC) ||
((phba->fc_topology == TOPOLOGY_LOOP) &&
(phba->fc_flag & FC_PUBLIC_LOOP)))
- memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64));
+ node_name = wwn_to_u64(phba->fc_fabparam.nodeName.wwn);
else
/* fabric is local port if there is no F/FL_Port */
- memcpy(&nodename, &phba->fc_nodename, sizeof(u64));
+ node_name = wwn_to_u64(phba->fc_nodename.wwn);
spin_unlock_irq(shost->host_lock);
- fc_host_fabric_name(shost) = be64_to_cpu(nodename);
+ fc_host_fabric_name(shost) = node_name;
}
@@ -988,8 +989,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
struct lpfc_sli *psli = &phba->sli;
- struct fc_host_statistics *hs =
- (struct fc_host_statistics *)phba->link_stats;
+ struct fc_host_statistics *hs = &phba->link_stats;
LPFC_MBOXQ_t *pmboxq;
MAILBOX_t *pmb;
int rc=0;
@@ -1020,6 +1020,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
return NULL;
}
+ memset(hs, 0, sizeof (struct fc_host_statistics));
+
hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
@@ -1101,21 +1103,20 @@ lpfc_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
- uint64_t node_name = 0;
+ u64 node_name = 0;
struct lpfc_nodelist *ndlp = NULL;
spin_lock_irq(shost->host_lock);
/* Search the mapped list for this target ID */
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
if (starget->id == ndlp->nlp_sid) {
- memcpy(&node_name, &ndlp->nlp_nodename,
- sizeof(struct lpfc_name));
+ node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);
break;
}
}
spin_unlock_irq(shost->host_lock);
- fc_starget_node_name(starget) = be64_to_cpu(node_name);
+ fc_starget_node_name(starget) = node_name;
}
static void
@@ -1123,21 +1124,20 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
- uint64_t port_name = 0;
+ u64 port_name = 0;
struct lpfc_nodelist *ndlp = NULL;
spin_lock_irq(shost->host_lock);
/* Search the mapped list for this target ID */
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
if (starget->id == ndlp->nlp_sid) {
- memcpy(&port_name, &ndlp->nlp_portname,
- sizeof(struct lpfc_name));
+ port_name = wwn_to_u64(ndlp->nlp_portname.wwn);
break;
}
}
spin_unlock_irq(shost->host_lock);
- fc_starget_port_name(starget) = be64_to_cpu(port_name);
+ fc_starget_port_name(starget) = port_name;
}
static void
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 78adee4699af..1280f0e54636 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -27,8 +27,10 @@
#include <linux/interrupt.h>
#include <linux/utsname.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
#include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 2b1c9572dae7..63caf7fe9725 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 233901e9dfde..4fb8eb0c84cf 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -24,6 +24,7 @@
#include <linux/kthread.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
@@ -1016,13 +1017,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
struct fc_rport *rport;
struct lpfc_rport_data *rdata;
struct fc_rport_identifiers rport_ids;
- uint64_t wwn;
/* Remote port has reappeared. Re-register w/ FC transport */
- memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t));
- rport_ids.node_name = be64_to_cpu(wwn);
- memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t));
- rport_ids.port_name = be64_to_cpu(wwn);
+ rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);
+ rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.wwn);
rport_ids.port_id = ndlp->nlp_DID;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
if (ndlp->nlp_type & NLP_FCP_TARGET)
@@ -1135,6 +1133,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
switch(list) {
case NLP_NO_LIST: /* No list, just remove it */
lpfc_nlp_remove(phba, nlp);
+ /* as node removed - stop further transport calls */
+ rport_del = none;
break;
case NLP_UNUSED_LIST:
spin_lock_irq(phba->host->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 21591cb9f551..047a87c26cc0 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -262,12 +262,14 @@ struct lpfc_sli_ct_request {
#define FF_FRAME_SIZE 2048
struct lpfc_name {
+ union {
+ struct {
#ifdef __BIG_ENDIAN_BITFIELD
- uint8_t nameType:4; /* FC Word 0, bit 28:31 */
- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */
+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
#else /* __LITTLE_ENDIAN_BITFIELD */
- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
- uint8_t nameType:4; /* FC Word 0, bit 28:31 */
+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */
#endif
#define NAME_IEEE 0x1 /* IEEE name - nameType */
@@ -276,8 +278,11 @@ struct lpfc_name {
#define NAME_IP_TYPE 0x4 /* IP address */
#define NAME_CCITT_TYPE 0xC
#define NAME_CCITT_GR_TYPE 0xE
- uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */
- uint8_t IEEE[6]; /* FC IEEE address */
+ uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */
+ uint8_t IEEE[6]; /* FC IEEE address */
+ };
+ uint8_t wwn[8];
+ };
};
struct csp {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 34d416d2b007..454058f655db 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
@@ -1332,21 +1333,18 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
unsigned long bar0map_len, bar2map_len;
int error = -ENODEV, retval;
int i;
- u64 wwname;
if (pci_enable_device(pdev))
goto out;
if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
goto out_disable_device;
- host = scsi_host_alloc(&lpfc_template,
- sizeof (struct lpfc_hba) + sizeof (unsigned long));
+ host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
if (!host)
goto out_release_regions;
phba = (struct lpfc_hba*)host->hostdata;
memset(phba, 0, sizeof (struct lpfc_hba));
- phba->link_stats = (void *)&phba[1];
phba->host = host;
phba->fc_flag |= FC_LOADING;
@@ -1525,10 +1523,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
* Must done after lpfc_sli_hba_setup()
*/
- memcpy(&wwname, &phba->fc_nodename, sizeof(u64));
- fc_host_node_name(host) = be64_to_cpu(wwname);
- memcpy(&wwname, &phba->fc_portname, sizeof(u64));
- fc_host_port_name(host) = be64_to_cpu(wwname);
+ fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.wwn);
+ fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.wwn);
fc_host_supported_classes(host) = FC_COS_CLASS3;
memset(fc_host_supported_fc4s(host), 0,
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index c27cf94795db..73eb89f91593 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -23,6 +23,11 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
#include "lpfc_hw.h"
#include "lpfc_sli.h"
#include "lpfc_disc.h"
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index a5cfb6421fa9..0aba13ceaacf 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -23,6 +23,11 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
#include "lpfc_hw.h"
#include "lpfc_sli.h"
#include "lpfc_disc.h"
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 45dc0210fc49..9b35eaac781d 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 17e4974d4445..b5ad1871d34b 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -40,11 +40,6 @@
#define LPFC_RESET_WAIT 2
#define LPFC_ABORT_WAIT 2
-static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
-{
- fcmd->fcpLunLsl = 0;
- fcmd->fcpLunMsl = swab16((uint16_t)lun);
-}
/*
* This routine allocates a scsi buffer, which contains all the necessary
@@ -238,6 +233,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
if (datadir == DMA_TO_DEVICE)
bpl->tus.f.bdeFlags = 0;
+ else
+ bpl->tus.f.bdeFlags = BUFF_USE_RCV;
bpl->tus.w = le32_to_cpu(bpl->tus.w);
num_bde = 1;
bpl++;
@@ -245,8 +242,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
/*
* Finish initializing those IOCB fields that are dependent on the
- * scsi_cmnd request_buffer
+ * scsi_cmnd request_buffer. Note that the bdeSize is explicitly
+ * reinitialized since all iocb memory resources are used many times
+ * for transmit, receive, and continuation bpl's.
*/
+ iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
iocb_cmd->un.fcpi64.bdl.bdeSize +=
(num_bde * sizeof (struct ulp_bde64));
iocb_cmd->ulpBdeCount = 1;
@@ -445,8 +445,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
int datadir = scsi_cmnd->sc_data_direction;
lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+ /* clear task management bits */
+ lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
- lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+ int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+ &lpfc_cmd->fcp_cmnd->fcp_lun);
memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
@@ -545,7 +548,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
piocb = &piocbq->iocb;
fcp_cmnd = lpfc_cmd->fcp_cmnd;
- lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+ int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+ &lpfc_cmd->fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
@@ -746,6 +750,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
goto out_fail_command;
}
+ else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+ cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ goto out_fail_command;
+ }
/*
* The device is most likely recovered and the driver
* needs a bit more time to finish. Ask the midlayer
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 0fd9ba14e1b5..acd64c49e849 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -78,18 +78,7 @@ struct fcp_rsp {
};
struct fcp_cmnd {
- uint32_t fcpLunMsl; /* most significant lun word (32 bits) */
- uint32_t fcpLunLsl; /* least significant lun word (32 bits) */
- /* # of bits to shift lun id to end up in right
- * payload word, little endian = 8, big = 16.
- */
-#ifdef __BIG_ENDIAN
-#define FC_LUN_SHIFT 16
-#define FC_ADDR_MODE_SHIFT 24
-#else /* __LITTLE_ENDIAN */
-#define FC_LUN_SHIFT 8
-#define FC_ADDR_MODE_SHIFT 0
-#endif
+ struct scsi_lun fcp_lun;
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1775508ed276..e74e224fd77c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -24,9 +24,11 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
#include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 47dea48ee0ec..7e6747b06f90 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.0.29"
+#define LPFC_DRIVER_VERSION "8.0.30"
#define LPFC_DRIVER_NAME "lpfc"
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index ff1933298da6..a4857db4f9b8 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1766,7 +1766,7 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t state)
struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
unsigned long flags;
- if (state == mdev->ofdev.dev.power.power_state || state < 2)
+ if (state.event == mdev->ofdev.dev.power.power_state.event || state.event < 2)
return 0;
scsi_block_requests(ms->host);
@@ -1791,7 +1791,7 @@ static int mesh_resume(struct macio_dev *mdev)
struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
unsigned long flags;
- if (mdev->ofdev.dev.power.power_state == 0)
+ if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
return 0;
set_mesh_power(ms, 1);
@@ -1802,7 +1802,7 @@ static int mesh_resume(struct macio_dev *mdev)
enable_irq(ms->meshintr);
scsi_unblock_requests(ms->host);
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
return 0;
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 89a4a0615c22..3f2f2464fa63 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -1377,7 +1377,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
*aSRpnt = SRpnt;
return (-EIO);
}
@@ -1419,7 +1419,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
if (new_frame > frame + 1000) {
printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO);
}
if ( i >= nframes + pending ) break;
@@ -1500,7 +1500,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
SRpnt->sr_sense_buffer[12] == 0 &&
SRpnt->sr_sense_buffer[13] == 2) {
printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO); /* hit end of tape = fail */
}
i = ((SRpnt->sr_sense_buffer[3] << 24) |
@@ -1525,7 +1525,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
}
if (!pending)
osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
- vfree((void *)buffer);
+ vfree(buffer);
return 0;
}
@@ -5852,7 +5852,7 @@ static int osst_remove(struct device *dev)
os_scsi_tapes[i] = NULL;
osst_nr_dev--;
write_unlock(&os_scsi_tapes_lock);
- if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
+ vfree(tpnt->header_cache);
if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
@@ -5896,8 +5896,7 @@ static void __exit exit_osst (void)
for (i=0; i < osst_max_dev; ++i) {
if (!(STp = os_scsi_tapes[i])) continue;
/* This is defensive, supposed to happen during detach */
- if (STp->header_cache)
- vfree(STp->header_cache);
+ vfree(STp->header_cache);
if (STp->buffer) {
normalize_buffer(STp->buffer);
kfree(STp->buffer);
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 623082d3a83f..c89da7d5b6df 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -95,8 +95,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
int i, retry, nplutos;
fc_channel *fc;
Scsi_Device dev;
- struct timer_list fc_timer =
- TIMER_INITIALIZER(pluto_detect_timeout, 0, 0);
+ DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
tpnt->proc_name = "pluto";
fcscount = 0;
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index b993652bfa25..637fb6565d28 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
break;
case ABORT_DEVICE:
- ha->flags.in_reset = 1;
if (qla1280_verbose)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing abort device "
@@ -1010,7 +1009,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing device reset "
"command.\n", ha->host_no, bus, target, lun);
- ha->flags.in_reset = 1;
if (qla1280_device_reset(ha, bus, target) == 0)
result = SUCCESS;
break;
@@ -1019,7 +1017,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
if (qla1280_verbose)
printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS "
"DEVICE RESET\n", ha->host_no, bus);
- ha->flags.in_reset = 1;
if (qla1280_bus_reset(ha, bus == 0))
result = SUCCESS;
@@ -1047,7 +1044,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
if (!list_empty(&ha->done_q))
qla1280_done(ha);
- ha->flags.in_reset = 0;
/* If we didn't manage to issue the action, or we have no
* command to wait for, exit here */
@@ -1269,6 +1265,22 @@ qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
}
#endif
+
+/* disable risc and host interrupts */
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+ WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
+}
+
+/* enable risc and host interrupts */
+static inline void
+qla1280_enable_intrs(struct scsi_qla_host *ha)
+{
+ WRT_REG_WORD(&ha->iobase->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+ RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
+}
/**************************************************************************
* qla1280_intr_handler
@@ -1290,7 +1302,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
ha->isr_count++;
reg = ha->iobase;
- WRT_REG_WORD(&reg->ictrl, 0); /* disable our interrupt. */
+ qla1280_disable_intrs(ha);
data = qla1280_debounce_register(&reg->istatus);
/* Check for pending interrupts. */
@@ -1303,8 +1315,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(HOST_LOCK);
- /* enable our interrupt. */
- WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+ qla1280_enable_intrs(ha);
LEAVE_INTR("qla1280_intr_handler");
return IRQ_RETVAL(handled);
@@ -1317,7 +1328,7 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
uint8_t mr;
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct nvram *nv;
- int status;
+ int status, lun;
nv = &ha->nvram;
@@ -1325,24 +1336,38 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
/* Set Target Parameters. */
mb[0] = MBC_SET_TARGET_PARAMETERS;
- mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
- mb[1] <<= 8;
-
- mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[2] = nv->bus[bus].target[target].parameter.renegotiate_on_error << 8;
+ mb[2] |= nv->bus[bus].target[target].parameter.stop_queue_on_check << 9;
+ mb[2] |= nv->bus[bus].target[target].parameter.auto_request_sense << 10;
+ mb[2] |= nv->bus[bus].target[target].parameter.tag_queuing << 11;
+ mb[2] |= nv->bus[bus].target[target].parameter.enable_sync << 12;
+ mb[2] |= nv->bus[bus].target[target].parameter.enable_wide << 13;
+ mb[2] |= nv->bus[bus].target[target].parameter.parity_checking << 14;
+ mb[2] |= nv->bus[bus].target[target].parameter.disconnect_allowed << 15;
if (IS_ISP1x160(ha)) {
mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
- mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
- nv->bus[bus].target[target].sync_period;
+ mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8);
mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
mr |= BIT_6;
} else {
- mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
- nv->bus[bus].target[target].sync_period;
+ mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8);
}
+ mb[3] |= nv->bus[bus].target[target].sync_period;
- status = qla1280_mailbox_command(ha, mr, &mb[0]);
+ status = qla1280_mailbox_command(ha, mr, mb);
+
+ /* Set Device Queue Parameters. */
+ for (lun = 0; lun < MAX_LUNS; lun++) {
+ mb[0] = MBC_SET_DEVICE_QUEUE;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[1] |= lun;
+ mb[2] = nv->bus[bus].max_queue_depth;
+ mb[3] = nv->bus[bus].target[target].execution_throttle;
+ status |= qla1280_mailbox_command(ha, 0x0f, mb);
+ }
if (status)
printk(KERN_WARNING "scsi(%ld:%i:%i): "
@@ -1389,19 +1414,19 @@ qla1280_slave_configure(struct scsi_device *device)
}
#if LINUX_VERSION_CODE > 0x020500
- nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr;
- nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr;
+ nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
+ nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
#endif
if (driver_setup.no_sync ||
(driver_setup.sync_mask &&
(~driver_setup.sync_mask & (1 << target))))
- nv->bus[bus].target[target].parameter.f.enable_sync = 0;
+ nv->bus[bus].target[target].parameter.enable_sync = 0;
if (driver_setup.no_wide ||
(driver_setup.wide_mask &&
(~driver_setup.wide_mask & (1 << target))))
- nv->bus[bus].target[target].parameter.f.enable_wide = 0;
+ nv->bus[bus].target[target].parameter.enable_wide = 0;
if (IS_ISP1x160(ha)) {
if (driver_setup.no_ppr ||
(driver_setup.ppr_mask &&
@@ -1410,7 +1435,7 @@ qla1280_slave_configure(struct scsi_device *device)
}
spin_lock_irqsave(HOST_LOCK, flags);
- if (nv->bus[bus].target[target].parameter.f.enable_sync)
+ if (nv->bus[bus].target[target].parameter.enable_sync)
status = qla1280_set_target_parameters(ha, bus, target);
qla1280_get_target_parameters(ha, device);
spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1448,7 +1473,6 @@ qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q)
*
* Input:
* ha = adapter block pointer.
- * done_q = done queue.
*/
static void
qla1280_done(struct scsi_qla_host *ha)
@@ -1522,7 +1546,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
int host_status = DID_ERROR;
uint16_t comp_status = le16_to_cpu(sts->comp_status);
uint16_t state_flags = le16_to_cpu(sts->state_flags);
- uint16_t residual_length = le16_to_cpu(sts->residual_length);
+ uint16_t residual_length = le32_to_cpu(sts->residual_length);
uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
#if DEBUG_QLA1280_INTR
static char *reason[] = {
@@ -1582,7 +1606,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
case CS_DATA_OVERRUN:
dprintk(2, "Data overrun 0x%x\n", residual_length);
- dprintk(2, "qla1280_isr: response packet data\n");
+ dprintk(2, "qla1280_return_status: response packet data\n");
qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
host_status = DID_ERROR;
break;
@@ -1617,40 +1641,6 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
/* QLogic ISP1280 Hardware Support Functions. */
/****************************************************************************/
- /*
- * qla2100_enable_intrs
- * qla2100_disable_intrs
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * None
- */
-static inline void
-qla1280_enable_intrs(struct scsi_qla_host *ha)
-{
- struct device_reg __iomem *reg;
-
- reg = ha->iobase;
- /* enable risc and host interrupts */
- WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
- RD_REG_WORD(&reg->ictrl); /* PCI Posted Write flush */
- ha->flags.ints_enabled = 1;
-}
-
-static inline void
-qla1280_disable_intrs(struct scsi_qla_host *ha)
-{
- struct device_reg __iomem *reg;
-
- reg = ha->iobase;
- /* disable risc and host interrupts */
- WRT_REG_WORD(&reg->ictrl, 0);
- RD_REG_WORD(&reg->ictrl); /* PCI Posted Write flush */
- ha->flags.ints_enabled = 0;
-}
-
/*
* qla1280_initialize_adapter
* Initialize board.
@@ -1679,7 +1669,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
ha->flags.reset_active = 0;
ha->flags.abort_isp_active = 0;
- ha->flags.ints_enabled = 0;
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ia64_platform_is("sn2")) {
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
@@ -1758,69 +1747,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
return status;
}
-
-/*
- * ISP Firmware Test
- * Checks if present version of RISC firmware is older than
- * driver firmware.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * 0 = firmware does not need to be loaded.
- */
-static int
-qla1280_isp_firmware(struct scsi_qla_host *ha)
-{
- struct nvram *nv = (struct nvram *) ha->response_ring;
- int status = 0; /* dg 2/27 always loads RISC */
- uint16_t mb[MAILBOX_REGISTER_COUNT];
-
- ENTER("qla1280_isp_firmware");
-
- dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no);
-
- /* Bad NVRAM data, load RISC code. */
- if (!ha->nvram_valid) {
- ha->flags.disable_risc_code_load = 0;
- } else
- ha->flags.disable_risc_code_load =
- nv->cntr_flags_1.disable_loading_risc_code;
-
- if (ha->flags.disable_risc_code_load) {
- dprintk(3, "qla1280_isp_firmware: Telling RISC to verify "
- "checksum of loaded BIOS code.\n");
-
- /* Verify checksum of loaded RISC code. */
- mb[0] = MBC_VERIFY_CHECKSUM;
- /* mb[1] = ql12_risc_code_addr01; */
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-
- if (!(status =
- qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
- /* Start firmware execution. */
- dprintk(3, "qla1280_isp_firmware: Startng F/W "
- "execution.\n");
-
- mb[0] = MBC_EXECUTE_FIRMWARE;
- /* mb[1] = ql12_risc_code_addr01; */
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
- qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
- } else
- printk(KERN_INFO "qla1280: RISC checksum failed.\n");
- } else {
- dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
- status = 1;
- }
-
- if (status)
- dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
-
- LEAVE("qla1280_isp_firmware");
- return status;
-}
-
/*
* Chip diagnostics
* Test chip for proper operation.
@@ -2006,7 +1932,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
"%d,%d(0x%x)\n",
risc_code_address, cnt, num, risc_address);
for(i = 0; i < cnt; i++)
- ((uint16_t *)ha->request_ring)[i] =
+ ((__le16 *)ha->request_ring)[i] =
cpu_to_le16(risc_code_address[i]);
mb[0] = MBC_LOAD_RAM;
@@ -2085,7 +2011,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
if (err) {
- printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+ printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
return err;
}
@@ -2105,14 +2031,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
static int
qla1280_load_firmware(struct scsi_qla_host *ha)
{
- int err = -ENODEV;
-
- /* If firmware needs to be loaded */
- if (!qla1280_isp_firmware(ha)) {
- printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
- ha->host_no);
- goto out;
- }
+ int err;
err = qla1280_chip_diag(ha);
if (err)
@@ -2246,17 +2165,17 @@ qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
{
struct nvram *nv = &ha->nvram;
- nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
- nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
- nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
- nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+ nv->bus[bus].target[target].parameter.renegotiate_on_error = 1;
+ nv->bus[bus].target[target].parameter.auto_request_sense = 1;
+ nv->bus[bus].target[target].parameter.tag_queuing = 1;
+ nv->bus[bus].target[target].parameter.enable_sync = 1;
#if 1 /* Some SCSI Processors do not seem to like this */
- nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+ nv->bus[bus].target[target].parameter.enable_wide = 1;
#endif
- nv->bus[bus].target[target].parameter.f.parity_checking = 1;
- nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
nv->bus[bus].target[target].execution_throttle =
nv->bus[bus].max_queue_depth - 1;
+ nv->bus[bus].target[target].parameter.parity_checking = 1;
+ nv->bus[bus].target[target].parameter.disconnect_allowed = 1;
if (IS_ISP1x160(ha)) {
nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
@@ -2284,9 +2203,9 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
nv->firmware_feature.f.enable_fast_posting = 1;
nv->firmware_feature.f.disable_synchronous_backoff = 1;
- nv->termination.f.scsi_bus_0_control = 3;
- nv->termination.f.scsi_bus_1_control = 3;
- nv->termination.f.auto_term_support = 1;
+ nv->termination.scsi_bus_0_control = 3;
+ nv->termination.scsi_bus_1_control = 3;
+ nv->termination.auto_term_support = 1;
/*
* Set default FIFO magic - What appropriate values would be here
@@ -2296,7 +2215,12 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
* header file provided by QLogic seems to be bogus or incomplete
* at best.
*/
- nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+ nv->isp_config.burst_enable = 1;
+ if (IS_ISP1040(ha))
+ nv->isp_config.fifo_threshold |= 3;
+ else
+ nv->isp_config.fifo_threshold |= 4;
+
if (IS_ISP1x160(ha))
nv->isp_parameter = 0x01; /* fast memory enable */
@@ -2327,66 +2251,53 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
struct nvram *nv = &ha->nvram;
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status, lun;
+ uint16_t flag;
/* Set Target Parameters. */
mb[0] = MBC_SET_TARGET_PARAMETERS;
- mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
- mb[1] <<= 8;
-
- /*
- * Do not enable wide, sync, and ppr for the initial
- * INQUIRY run. We enable this later if we determine
- * the target actually supports it.
- */
- nv->bus[bus].target[target].parameter.f.
- auto_request_sense = 1;
- nv->bus[bus].target[target].parameter.f.
- stop_queue_on_check = 0;
-
- if (IS_ISP1x160(ha))
- nv->bus[bus].target[target].ppr_1x160.
- flags.enable_ppr = 0;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
/*
- * No sync, wide, etc. while probing
+ * Do not enable sync and ppr for the initial INQUIRY run. We
+ * enable this later if we determine the target actually
+ * supports it.
*/
- mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
- ~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+ mb[2] = (TP_RENEGOTIATE | TP_AUTO_REQUEST_SENSE | TP_TAGGED_QUEUE
+ | TP_WIDE | TP_PARITY | TP_DISCONNECT);
if (IS_ISP1x160(ha))
mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
else
mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
mb[3] |= nv->bus[bus].target[target].sync_period;
-
- status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status = qla1280_mailbox_command(ha, 0x0f, mb);
/* Save Tag queuing enable flag. */
- mb[0] = BIT_0 << target;
- if (nv->bus[bus].target[target].parameter.f.tag_queuing)
- ha->bus_settings[bus].qtag_enables |= mb[0];
+ flag = (BIT_0 << target) & mb[0];
+ if (nv->bus[bus].target[target].parameter.tag_queuing)
+ ha->bus_settings[bus].qtag_enables |= flag;
/* Save Device enable flag. */
if (IS_ISP1x160(ha)) {
if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
- ha->bus_settings[bus].device_enables |= mb[0];
+ ha->bus_settings[bus].device_enables |= flag;
ha->bus_settings[bus].lun_disables |= 0;
} else {
if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
- ha->bus_settings[bus].device_enables |= mb[0];
+ ha->bus_settings[bus].device_enables |= flag;
/* Save LUN disable flag. */
if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
- ha->bus_settings[bus].lun_disables |= mb[0];
+ ha->bus_settings[bus].lun_disables |= flag;
}
/* Set Device Queue Parameters. */
for (lun = 0; lun < MAX_LUNS; lun++) {
mb[0] = MBC_SET_DEVICE_QUEUE;
- mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
- mb[1] = mb[1] << 8 | lun;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[1] |= lun;
mb[2] = nv->bus[bus].max_queue_depth;
mb[3] = nv->bus[bus].target[target].execution_throttle;
- status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+ status |= qla1280_mailbox_command(ha, 0x0f, mb);
}
return status;
@@ -2431,7 +2342,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
struct nvram *nv = &ha->nvram;
int bus, target, status = 0;
uint16_t mb[MAILBOX_REGISTER_COUNT];
- uint16_t mask;
ENTER("qla1280_nvram_config");
@@ -2439,7 +2349,7 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
/* Always force AUTO sense for LINUX SCSI */
for (bus = 0; bus < MAX_BUSES; bus++)
for (target = 0; target < MAX_TARGETS; target++) {
- nv->bus[bus].target[target].parameter.f.
+ nv->bus[bus].target[target].parameter.
auto_request_sense = 1;
}
} else {
@@ -2457,31 +2367,40 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
- cfg1 = RD_REG_WORD(&reg->cfg_1);
+ cfg1 = RD_REG_WORD(&reg->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6);
cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
/* Busted fifo, says mjacob. */
- if (hwrev == ISP_CFG0_1040A)
- WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
- else
- WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+ if (hwrev != ISP_CFG0_1040A)
+ cfg1 |= nv->isp_config.fifo_threshold << 4;
+
+ cfg1 |= nv->isp_config.burst_enable << 2;
+ WRT_REG_WORD(&reg->cfg_1, cfg1);
WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
} else {
+ uint16_t cfg1, term;
+
/* Set ISP hardware DMA burst */
- mb[0] = nv->isp_config.c;
+ cfg1 = nv->isp_config.fifo_threshold << 4;
+ cfg1 |= nv->isp_config.burst_enable << 2;
/* Enable DMA arbitration on dual channel controllers */
if (ha->ports > 1)
- mb[0] |= BIT_13;
- WRT_REG_WORD(&reg->cfg_1, mb[0]);
+ cfg1 |= BIT_13;
+ WRT_REG_WORD(&reg->cfg_1, cfg1);
/* Set SCSI termination. */
- WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
- mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
- WRT_REG_WORD(&reg->gpio_data, mb[0]);
+ WRT_REG_WORD(&reg->gpio_enable,
+ BIT_7 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
+ term = nv->termination.scsi_bus_1_control;
+ term |= nv->termination.scsi_bus_0_control << 2;
+ term |= nv->termination.auto_term_support << 7;
+ RD_REG_WORD(&reg->id_l); /* Flush PCI write */
+ WRT_REG_WORD(&reg->gpio_data, term);
}
+ RD_REG_WORD(&reg->id_l); /* Flush PCI write */
/* ISP parameter word. */
mb[0] = MBC_SET_SYSTEM_PARAMETER;
@@ -2497,16 +2416,17 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
/* Firmware feature word. */
mb[0] = MBC_SET_FIRMWARE_FEATURES;
- mask = BIT_5 | BIT_1 | BIT_0;
- mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask);
+ mb[1] = nv->firmware_feature.f.enable_fast_posting;
+ mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1;
+ mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5;
#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2)
if (ia64_platform_is("sn2")) {
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
"workaround\n", ha->host_no);
- mb[1] |= BIT_9;
+ mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */
}
#endif
- status |= qla1280_mailbox_command(ha, mask, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* Retry count and delay. */
mb[0] = MBC_SET_RETRY_COUNT;
@@ -2535,27 +2455,27 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
mb[2] |= BIT_5;
if (nv->bus[1].config_2.data_line_active_negation)
mb[2] |= BIT_4;
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY;
mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */
- status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* thingy */
mb[0] = MBC_SET_PCI_CONTROL;
- mb[1] = 2; /* Data DMA Channel Burst Enable */
- mb[2] = 2; /* Command DMA Channel Burst Enable */
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ mb[1] = BIT_1; /* Data DMA Channel Burst Enable */
+ mb[2] = BIT_1; /* Command DMA Channel Burst Enable */
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
mb[0] = MBC_SET_TAG_AGE_LIMIT;
mb[1] = 8;
- status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* Selection timeout. */
mb[0] = MBC_SET_SELECTION_TIMEOUT;
mb[1] = nv->bus[0].selection_timeout;
mb[2] = nv->bus[1].selection_timeout;
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
for (bus = 0; bus < ha->ports; bus++)
status |= qla1280_config_bus(ha, bus);
@@ -3066,7 +2986,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct scsi_cmnd *cmd = sp->cmd;
cmd_a64_entry_t *pkt;
struct scatterlist *sg = NULL;
- u32 *dword_ptr;
+ __le32 *dword_ptr;
dma_addr_t dma_handle;
int status = 0;
int cnt;
@@ -3104,10 +3024,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
}
+ dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n",
+ ha->req_q_cnt, seg_cnt);
+
/* If room for request in request ring. */
if ((req_cnt + 2) >= ha->req_q_cnt) {
status = 1;
- dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt="
+ dprintk(2, "qla1280_start_scsi: in-ptr=0x%x req_q_cnt="
"0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
req_cnt);
goto out;
@@ -3119,7 +3042,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
if (cnt >= MAX_OUTSTANDING_COMMANDS) {
status = 1;
- dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
+ dprintk(2, "qla1280_start_scsi: NO ROOM IN "
"OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt);
goto out;
}
@@ -3128,7 +3051,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
ha->req_q_cnt -= req_cnt;
CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1);
- dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
+ dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd));
dprintk(2, " bus %i, target %i, lun %i\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
@@ -3350,7 +3273,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct scsi_cmnd *cmd = sp->cmd;
struct cmd_entry *pkt;
struct scatterlist *sg = NULL;
- uint32_t *dword_ptr;
+ __le32 *dword_ptr;
int status = 0;
int cnt;
int req_cnt;
@@ -3993,21 +3916,21 @@ qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha)
result = cmd->request_buffer;
n = &ha->nvram;
- n->bus[bus].target[target].parameter.f.enable_wide = 0;
- n->bus[bus].target[target].parameter.f.enable_sync = 0;
+ n->bus[bus].target[target].parameter.enable_wide = 0;
+ n->bus[bus].target[target].parameter.enable_sync = 0;
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
if (result[7] & 0x60)
- n->bus[bus].target[target].parameter.f.enable_wide = 1;
+ n->bus[bus].target[target].parameter.enable_wide = 1;
if (result[7] & 0x10)
- n->bus[bus].target[target].parameter.f.enable_sync = 1;
+ n->bus[bus].target[target].parameter.enable_sync = 1;
if ((result[2] >= 3) && (result[4] + 5 > 56) &&
(result[56] & 0x4))
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
- n->bus[bus].target[target].parameter.f.enable_wide,
- n->bus[bus].target[target].parameter.f.enable_sync,
+ n->bus[bus].target[target].parameter.enable_wide,
+ n->bus[bus].target[target].parameter.enable_sync,
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
}
#endif
@@ -4071,7 +3994,7 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
/* Save ISP completion status */
CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
- if (scsi_status & SS_CHECK_CONDITION) {
+ if (scsi_status & SAM_STAT_CHECK_CONDITION) {
if (comp_status != CS_ARS_FAILED) {
uint16_t req_sense_length =
le16_to_cpu(pkt->req_sense_length);
@@ -4650,7 +4573,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
- " suitable DMA mask - aboring\n", ha->host_no);
+ "suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
goto error_free_irq;
}
@@ -4660,14 +4583,14 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#else
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
- " suitable DMA mask - aboring\n", ha->host_no);
+ "suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
goto error_free_irq;
}
#endif
ha->request_ring = pci_alloc_consistent(ha->pdev,
- ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+ ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
&ha->request_dma);
if (!ha->request_ring) {
printk(KERN_INFO "qla1280: Failed to get request memory\n");
@@ -4675,7 +4598,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
ha->response_ring = pci_alloc_consistent(ha->pdev,
- ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+ ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
&ha->response_dma);
if (!ha->response_ring) {
printk(KERN_INFO "qla1280: Failed to get response memory\n");
@@ -4758,7 +4681,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#if LINUX_VERSION_CODE >= 0x020600
error_disable_adapter:
- WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ qla1280_disable_intrs(ha);
#endif
error_free_irq:
free_irq(pdev->irq, ha);
@@ -4770,11 +4693,11 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#endif
error_free_response_ring:
pci_free_consistent(ha->pdev,
- ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+ ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
ha->response_ring, ha->response_dma);
error_free_request_ring:
pci_free_consistent(ha->pdev,
- ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+ ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
ha->request_ring, ha->request_dma);
error_put_host:
scsi_host_put(host);
@@ -4795,7 +4718,7 @@ qla1280_remove_one(struct pci_dev *pdev)
scsi_remove_host(host);
#endif
- WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ qla1280_disable_intrs(ha);
free_irq(pdev->irq, ha);
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index d245ae07518e..59915fb70301 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -94,9 +94,6 @@
#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */
-/* Number of segments 1 - 65535 */
-#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */
-
/*
* SCSI Request Block structure (sp) that is placed
* on cmd->SCp location of every I/O
@@ -378,29 +375,23 @@ struct nvram {
uint16_t unused_12; /* 12, 13 */
uint16_t unused_14; /* 14, 15 */
- union {
- uint8_t c;
- struct {
- uint8_t reserved:2;
- uint8_t burst_enable:1;
- uint8_t reserved_1:1;
- uint8_t fifo_threshold:4;
- } f;
+ struct {
+ uint8_t reserved:2;
+ uint8_t burst_enable:1;
+ uint8_t reserved_1:1;
+ uint8_t fifo_threshold:4;
} isp_config; /* 16 */
/* Termination
* 0 = Disable, 1 = high only, 3 = Auto term
*/
- union {
- uint8_t c;
- struct {
- uint8_t scsi_bus_1_control:2;
- uint8_t scsi_bus_0_control:2;
- uint8_t unused_0:1;
- uint8_t unused_1:1;
- uint8_t unused_2:1;
- uint8_t auto_term_support:1;
- } f;
+ struct {
+ uint8_t scsi_bus_1_control:2;
+ uint8_t scsi_bus_0_control:2;
+ uint8_t unused_0:1;
+ uint8_t unused_1:1;
+ uint8_t unused_2:1;
+ uint8_t auto_term_support:1;
} termination; /* 17 */
uint16_t isp_parameter; /* 18, 19 */
@@ -460,18 +451,15 @@ struct nvram {
uint16_t unused_38; /* 38, 39 */
struct {
- union {
- uint8_t c;
- struct {
- uint8_t renegotiate_on_error:1;
- uint8_t stop_queue_on_check:1;
- uint8_t auto_request_sense:1;
- uint8_t tag_queuing:1;
- uint8_t enable_sync:1;
- uint8_t enable_wide:1;
- uint8_t parity_checking:1;
- uint8_t disconnect_allowed:1;
- } f;
+ struct {
+ uint8_t renegotiate_on_error:1;
+ uint8_t stop_queue_on_check:1;
+ uint8_t auto_request_sense:1;
+ uint8_t tag_queuing:1;
+ uint8_t enable_sync:1;
+ uint8_t enable_wide:1;
+ uint8_t parity_checking:1;
+ uint8_t disconnect_allowed:1;
} parameter; /* 40 */
uint8_t execution_throttle; /* 41 */
@@ -528,23 +516,23 @@ struct cmd_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t handle; /* System handle. */
+ __le32 handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
};
/*
@@ -556,21 +544,21 @@ struct cont_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved; /* Reserved */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
- uint32_t dseg_5_address; /* Data segment 5 address. */
- uint32_t dseg_5_length; /* Data segment 5 length. */
- uint32_t dseg_6_address; /* Data segment 6 address. */
- uint32_t dseg_6_length; /* Data segment 6 length. */
+ __le32 reserved; /* Reserved */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_4_address; /* Data segment 4 address. */
+ __le32 dseg_4_length; /* Data segment 4 length. */
+ __le32 dseg_5_address; /* Data segment 5 address. */
+ __le32 dseg_5_length; /* Data segment 5 length. */
+ __le32 dseg_6_address; /* Data segment 6 address. */
+ __le32 dseg_6_length; /* Data segment 6 length. */
};
/*
@@ -586,22 +574,22 @@ struct response {
#define RF_FULL BIT_1 /* Full */
#define RF_BAD_HEADER BIT_2 /* Bad header. */
#define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */
- uint32_t handle; /* System handle. */
- uint16_t scsi_status; /* SCSI status. */
- uint16_t comp_status; /* Completion status. */
- uint16_t state_flags; /* State flags. */
-#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */
-#define SF_GOT_SENSE BIT_13 /* Got Sense */
-#define SF_GOT_STATUS BIT_12 /* Got Status */
-#define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */
-#define SF_SENT_CDB BIT_10 /* Send CDB */
-#define SF_GOT_TARGET BIT_9 /* */
-#define SF_GOT_BUS BIT_8 /* */
- uint16_t status_flags; /* Status flags. */
- uint16_t time; /* Time. */
- uint16_t req_sense_length; /* Request sense data length. */
- uint32_t residual_length; /* Residual transfer length. */
- uint16_t reserved[4];
+ __le32 handle; /* System handle. */
+ __le16 scsi_status; /* SCSI status. */
+ __le16 comp_status; /* Completion status. */
+ __le16 state_flags; /* State flags. */
+#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */
+#define SF_GOT_SENSE BIT_13 /* Got Sense */
+#define SF_GOT_STATUS BIT_12 /* Got Status */
+#define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */
+#define SF_SENT_CDB BIT_10 /* Send CDB */
+#define SF_GOT_TARGET BIT_9 /* */
+#define SF_GOT_BUS BIT_8 /* */
+ __le16 status_flags; /* Status flags. */
+ __le16 time; /* Time. */
+ __le16 req_sense_length;/* Request sense data length. */
+ __le32 residual_length; /* Residual transfer length. */
+ __le16 reserved[4];
uint8_t req_sense_data[32]; /* Request sense data. */
};
@@ -614,7 +602,7 @@ struct mrk_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved;
+ __le32 reserved;
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
uint8_t modifier; /* Modifier (7-0). */
@@ -638,11 +626,11 @@ struct ecmd_entry {
uint32_t handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[88]; /* SCSI command words. */
};
@@ -655,20 +643,20 @@ typedef struct {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t handle; /* System handle. */
+ __le32 handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t reserved_1[2]; /* unused */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
+ __le32 reserved_1[2]; /* unused */
+ __le32 dseg_0_address[2]; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2]; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
} cmd_a64_entry_t, request_t;
/*
@@ -680,16 +668,16 @@ struct cont_a64_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address[2]; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address[2]; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address[2]; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
+ __le32 dseg_0_address[2]; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2]; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address[2]; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address[2]; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_4_address[2]; /* Data segment 4 address. */
+ __le32 dseg_4_length; /* Data segment 4 length. */
};
/*
@@ -701,10 +689,10 @@ struct elun_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status not used. */
- uint32_t reserved_2;
- uint16_t lun; /* Bit 15 is bus number. */
- uint16_t reserved_4;
- uint32_t option_flags;
+ __le32 reserved_2;
+ __le16 lun; /* Bit 15 is bus number. */
+ __le16 reserved_4;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_5;
uint8_t command_count; /* Number of ATIOs allocated. */
@@ -714,8 +702,8 @@ struct elun_entry {
/* commands (2-26). */
uint8_t group_7_length; /* SCSI CDB length for group 7 */
/* commands (2-26). */
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t reserved_6[20];
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 reserved_6[20];
};
/*
@@ -729,20 +717,20 @@ struct modify_lun_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t reserved_3;
uint8_t operators;
uint8_t reserved_4;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_5;
uint8_t command_count; /* Number of ATIOs allocated. */
uint8_t immed_notify_count; /* Number of Immediate Notify */
/* entries allocated. */
- uint16_t reserved_6;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t reserved_7[20];
+ __le16 reserved_6;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 reserved_7[20];
};
/*
@@ -754,20 +742,20 @@ struct notify_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_4;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
/* entries allocated. */
- uint16_t seq_id;
+ __le16 seq_id;
uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */
- uint16_t reserved_5[8];
+ __le16 reserved_5[8];
uint8_t sense_data[18];
};
@@ -780,16 +768,16 @@ struct nack_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t event;
- uint16_t seq_id;
- uint16_t reserved_4[22];
+ __le16 seq_id;
+ __le16 reserved_4[22];
};
/*
@@ -801,12 +789,12 @@ struct atio_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t cdb_len;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
@@ -824,28 +812,28 @@ struct ctio_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
};
/*
@@ -857,24 +845,24 @@ struct ctio_ret_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint16_t dseg_1_length; /* Data segment 1 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le16 dseg_1_length; /* Data segment 1 length. */
uint8_t sense_data[18];
};
@@ -887,25 +875,25 @@ struct ctio_a64_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t reserved_4[2];
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 reserved_4[2];
+ __le32 dseg_0_address[2];/* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2];/* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
};
/*
@@ -917,21 +905,21 @@ struct ctio_a64_ret_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint16_t reserved_4[7];
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le16 reserved_4[7];
uint8_t sense_data[18];
};
@@ -979,14 +967,6 @@ struct ctio_a64_ret_entry {
#define CS_RETRY 0x82 /* Driver defined */
/*
- * ISP status entry - SCSI status byte bit definitions.
- */
-#define SS_CHECK_CONDITION BIT_1
-#define SS_CONDITION_MET BIT_2
-#define SS_BUSY_CONDITION BIT_3
-#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
-
-/*
* ISP target entries - Option flags bit definitions.
*/
#define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */
@@ -1082,10 +1062,6 @@ struct scsi_qla_host {
uint32_t reset_active:1; /* 3 */
uint32_t abort_isp_active:1; /* 4 */
uint32_t disable_risc_code_load:1; /* 5 */
- uint32_t enable_64bit_addressing:1; /* 6 */
- uint32_t in_reset:1; /* 7 */
- uint32_t ints_enabled:1;
- uint32_t ignore_nvram:1;
#ifdef __ia64__
uint32_t use_pci_vchannel:1;
#endif
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 659a5d63467d..fc25cd834668 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
}
+/* Scsi_Host attributes. */
+
+static ssize_t
+qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
+}
+
+static ssize_t
+qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ char fw_str[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->isp_ops.fw_version_str(ha, fw_str));
+}
+
+static ssize_t
+qla2x00_serial_num_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ uint32_t sn;
+
+ sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+ return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
+ sn % 100000);
+}
+
+static ssize_t
+qla2x00_isp_name_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name);
+}
+
+static ssize_t
+qla2x00_isp_id_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+ ha->product_id[0], ha->product_id[1], ha->product_id[2],
+ ha->product_id[3]);
+}
+
+static ssize_t
+qla2x00_model_name_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
+}
+
+static ssize_t
+qla2x00_model_desc_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->model_desc ? ha->model_desc: "");
+}
+
+static ssize_t
+qla2x00_pci_info_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ char pci_info[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->isp_ops.pci_info_str(ha, pci_info));
+}
+
+static ssize_t
+qla2x00_state_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int len = 0;
+
+ if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+ atomic_read(&ha->loop_state) == LOOP_DEAD)
+ len = snprintf(buf, PAGE_SIZE, "Link Down\n");
+ else if (atomic_read(&ha->loop_state) != LOOP_READY ||
+ test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+ test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))
+ len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
+ else {
+ len = snprintf(buf, PAGE_SIZE, "Link Up - ");
+
+ switch (ha->current_topology) {
+ case ISP_CFG_NL:
+ len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+ break;
+ case ISP_CFG_FL:
+ len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
+ break;
+ case ISP_CFG_N:
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "N_Port to N_Port\n");
+ break;
+ case ISP_CFG_F:
+ len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
+ break;
+ default:
+ len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+ break;
+ }
+ }
+ return len;
+}
+
+static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
+ NULL);
+static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
+static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
+static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
+static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
+static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
+static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
+static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
+static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+
+struct class_device_attribute *qla2x00_host_attrs[] = {
+ &class_device_attr_driver_version,
+ &class_device_attr_fw_version,
+ &class_device_attr_serial_num,
+ &class_device_attr_isp_name,
+ &class_device_attr_isp_id,
+ &class_device_attr_model_name,
+ &class_device_attr_model_desc,
+ &class_device_attr_pci_info,
+ &class_device_attr_state,
+ NULL,
+};
+
/* Host attributes. */
static void
@@ -228,16 +360,16 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
scsi_qla_host_t *ha = to_qla_host(host);
fc_port_t *fcport;
- uint64_t node_name = 0;
+ u64 node_name = 0;
list_for_each_entry(fcport, &ha->fcports, list) {
if (starget->id == fcport->os_target_id) {
- node_name = *(uint64_t *)fcport->node_name;
+ node_name = wwn_to_u64(fcport->node_name);
break;
}
}
- fc_starget_node_name(starget) = be64_to_cpu(node_name);
+ fc_starget_node_name(starget) = node_name;
}
static void
@@ -246,16 +378,16 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
scsi_qla_host_t *ha = to_qla_host(host);
fc_port_t *fcport;
- uint64_t port_name = 0;
+ u64 port_name = 0;
list_for_each_entry(fcport, &ha->fcports, list) {
if (starget->id == fcport->os_target_id) {
- port_name = *(uint64_t *)fcport->port_name;
+ port_name = wwn_to_u64(fcport->port_name);
break;
}
}
- fc_starget_port_name(starget) = be64_to_cpu(port_name);
+ fc_starget_port_name(starget) = port_name;
}
static void
@@ -304,10 +436,13 @@ struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
.dd_fcrport_size = sizeof(struct fc_port *),
+ .show_rport_supported_classes = 1,
.get_starget_node_name = qla2x00_get_starget_node_name,
.show_starget_node_name = 1,
@@ -325,8 +460,7 @@ struct fc_function_template qla2xxx_transport_functions = {
void
qla2x00_init_host_attr(scsi_qla_host_t *ha)
{
- fc_host_node_name(ha->host) =
- be64_to_cpu(*(uint64_t *)ha->init_cb->node_name);
- fc_host_port_name(ha->host) =
- be64_to_cpu(*(uint64_t *)ha->init_cb->port_name);
+ fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name);
+ fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name);
+ fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 72bbaa91dc77..9791496fa788 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1334,7 +1334,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
WRT_REG_DWORD(dmp_reg, 0xB0200000);
- dmp_reg = (uint32_t *)((uint8_t *)reg + 0xFC);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index b8d90e97e017..9684e7a91fa9 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -81,6 +81,7 @@
#define DEBUG2_3_11(x) do {x;} while (0);
#define DEBUG2_9_10(x) do {x;} while (0);
#define DEBUG2_11(x) do {x;} while (0);
+#define DEBUG2_13(x) do {x;} while (0);
#else
#define DEBUG2(x) do {} while (0);
#endif
@@ -169,8 +170,14 @@
#if defined(QL_DEBUG_LEVEL_13)
#define DEBUG13(x) do {x;} while (0)
+#if !defined(DEBUG2_13)
+#define DEBUG2_13(x) do {x;} while(0)
+#endif
#else
#define DEBUG13(x) do {} while (0)
+#if !defined(QL_DEBUG_LEVEL_2)
+#define DEBUG2_13(x) do {} while(0)
+#endif
#endif
#if defined(QL_DEBUG_LEVEL_14)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 1c6d366f4fad..b455c31405e4 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -214,6 +214,7 @@
* valid range of an N-PORT id is 0 through 0x7ef.
*/
#define NPH_LAST_HANDLE 0x7ef
+#define NPH_MGMT_SERVER 0x7fa /* FFFFFA */
#define NPH_SNS 0x7fc /* FFFFFC */
#define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */
#define NPH_F_PORT 0x7fe /* FFFFFE */
@@ -630,6 +631,7 @@ typedef struct {
#define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */
#define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */
#define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */
+#define MBC_STOP_FIRMWARE 0x14 /* Stop firmware. */
#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */
#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */
#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */
@@ -913,7 +915,7 @@ typedef struct {
* MSB BIT 1 =
* MSB BIT 2 =
* MSB BIT 3 =
- * MSB BIT 4 =
+ * MSB BIT 4 = LED mode
* MSB BIT 5 = enable 50 ohm termination
* MSB BIT 6 = Data Rate (2300 only)
* MSB BIT 7 = Data Rate (2300 only)
@@ -1035,7 +1037,7 @@ typedef struct {
* MSB BIT 1 =
* MSB BIT 2 =
* MSB BIT 3 =
- * MSB BIT 4 =
+ * MSB BIT 4 = LED mode
* MSB BIT 5 = enable 50 ohm termination
* MSB BIT 6 = Data Rate (2300 only)
* MSB BIT 7 = Data Rate (2300 only)
@@ -1131,10 +1133,7 @@ typedef struct {
uint8_t link_down_timeout;
- uint8_t adapter_id_0[4];
- uint8_t adapter_id_1[4];
- uint8_t adapter_id_2[4];
- uint8_t adapter_id_3[4];
+ uint8_t adapter_id[16];
uint8_t alt1_boot_node_name[WWN_SIZE];
uint16_t alt1_boot_lun_number;
@@ -1673,6 +1672,7 @@ typedef struct fc_port {
uint8_t cur_path; /* current path id */
struct fc_rport *rport;
+ u32 supported_classes;
} fc_port_t;
/*
@@ -1727,6 +1727,8 @@ typedef struct fc_port {
#define CT_REJECT_RESPONSE 0x8001
#define CT_ACCEPT_RESPONSE 0x8002
+#define CT_REASON_CANNOT_PERFORM 0x09
+#define CT_EXPL_ALREADY_REGISTERED 0x10
#define NS_N_PORT_TYPE 0x01
#define NS_NL_PORT_TYPE 0x02
@@ -1768,6 +1770,100 @@ typedef struct fc_port {
#define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255)
#define RSNN_NN_RSP_SIZE 16
+/*
+ * HBA attribute types.
+ */
+#define FDMI_HBA_ATTR_COUNT 9
+#define FDMI_HBA_NODE_NAME 1
+#define FDMI_HBA_MANUFACTURER 2
+#define FDMI_HBA_SERIAL_NUMBER 3
+#define FDMI_HBA_MODEL 4
+#define FDMI_HBA_MODEL_DESCRIPTION 5
+#define FDMI_HBA_HARDWARE_VERSION 6
+#define FDMI_HBA_DRIVER_VERSION 7
+#define FDMI_HBA_OPTION_ROM_VERSION 8
+#define FDMI_HBA_FIRMWARE_VERSION 9
+#define FDMI_HBA_OS_NAME_AND_VERSION 0xa
+#define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb
+
+struct ct_fdmi_hba_attr {
+ uint16_t type;
+ uint16_t len;
+ union {
+ uint8_t node_name[WWN_SIZE];
+ uint8_t manufacturer[32];
+ uint8_t serial_num[8];
+ uint8_t model[16];
+ uint8_t model_desc[80];
+ uint8_t hw_version[16];
+ uint8_t driver_version[32];
+ uint8_t orom_version[16];
+ uint8_t fw_version[16];
+ uint8_t os_version[128];
+ uint8_t max_ct_len[4];
+ } a;
+};
+
+struct ct_fdmi_hba_attributes {
+ uint32_t count;
+ struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT];
+};
+
+/*
+ * Port attribute types.
+ */
+#define FDMI_PORT_ATTR_COUNT 5
+#define FDMI_PORT_FC4_TYPES 1
+#define FDMI_PORT_SUPPORT_SPEED 2
+#define FDMI_PORT_CURRENT_SPEED 3
+#define FDMI_PORT_MAX_FRAME_SIZE 4
+#define FDMI_PORT_OS_DEVICE_NAME 5
+#define FDMI_PORT_HOST_NAME 6
+
+struct ct_fdmi_port_attr {
+ uint16_t type;
+ uint16_t len;
+ union {
+ uint8_t fc4_types[32];
+ uint32_t sup_speed;
+ uint32_t cur_speed;
+ uint32_t max_frame_size;
+ uint8_t os_dev_name[32];
+ uint8_t host_name[32];
+ } a;
+};
+
+/*
+ * Port Attribute Block.
+ */
+struct ct_fdmi_port_attributes {
+ uint32_t count;
+ struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT];
+};
+
+/* FDMI definitions. */
+#define GRHL_CMD 0x100
+#define GHAT_CMD 0x101
+#define GRPL_CMD 0x102
+#define GPAT_CMD 0x110
+
+#define RHBA_CMD 0x200
+#define RHBA_RSP_SIZE 16
+
+#define RHAT_CMD 0x201
+#define RPRT_CMD 0x210
+
+#define RPA_CMD 0x211
+#define RPA_RSP_SIZE 16
+
+#define DHBA_CMD 0x300
+#define DHBA_REQ_SIZE (16 + 8)
+#define DHBA_RSP_SIZE 16
+
+#define DHAT_CMD 0x301
+#define DPRT_CMD 0x310
+#define DPA_CMD 0x311
+
/* CT command header -- request/response common fields */
struct ct_cmd_hdr {
uint8_t revision;
@@ -1825,6 +1921,43 @@ struct ct_sns_req {
uint8_t name_len;
uint8_t sym_node_name[255];
} rsnn_nn;
+
+ struct {
+ uint8_t hba_indentifier[8];
+ } ghat;
+
+ struct {
+ uint8_t hba_identifier[8];
+ uint32_t entry_count;
+ uint8_t port_name[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } rhba;
+
+ struct {
+ uint8_t hba_identifier[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } rhat;
+
+ struct {
+ uint8_t port_name[8];
+ struct ct_fdmi_port_attributes attrs;
+ } rpa;
+
+ struct {
+ uint8_t port_name[8];
+ } dhba;
+
+ struct {
+ uint8_t port_name[8];
+ } dhat;
+
+ struct {
+ uint8_t port_name[8];
+ } dprt;
+
+ struct {
+ uint8_t port_name[8];
+ } dpa;
} req;
};
@@ -1882,6 +2015,12 @@ struct ct_sns_rsp {
struct {
uint8_t fc4_types[32];
} gft_id;
+
+ struct {
+ uint32_t entry_count;
+ uint8_t port_name[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } ghat;
} rsp;
};
@@ -2032,6 +2171,8 @@ struct isp_operations {
uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
+ void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
+ uint32_t);
uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
@@ -2111,6 +2252,7 @@ typedef struct scsi_qla_host {
#define IOCTL_ERROR_RECOVERY 23
#define LOOP_RESET_NEEDED 24
#define BEACON_BLINK_NEEDED 25
+#define REGISTER_FDMI_NEEDED 26
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@@ -2204,6 +2346,7 @@ typedef struct scsi_qla_host {
int port_down_retry_count;
uint8_t mbx_count;
uint16_t last_loop_id;
+ uint16_t mgmt_svr_loop_id;
uint32_t login_retry_count;
@@ -2318,6 +2461,7 @@ typedef struct scsi_qla_host {
uint8_t model_number[16+1];
#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
char *model_desc;
+ uint8_t adapter_id[16+1];
uint8_t *node_name;
uint8_t *port_name;
@@ -2377,6 +2521,7 @@ typedef struct scsi_qla_host {
#define QLA_SUSPENDED 0x106
#define QLA_BUSY 0x107
#define QLA_RSCNS_HANDLED 0x108
+#define QLA_ALREADY_REGISTERED 0x109
/*
* Stat info for all adpaters
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 665c203e0675..1ed32e7b5472 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -79,6 +79,7 @@ extern int ql2xplogiabsentdevice;
extern int ql2xenablezio;
extern int ql2xintrdelaytimer;
extern int ql2xloginretrycount;
+extern int ql2xfdmienable;
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
@@ -147,9 +148,6 @@ qla2x00_abort_target(fc_port_t *);
#endif
extern int
-qla2x00_target_reset(scsi_qla_host_t *, struct fc_port *);
-
-extern int
qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
uint8_t *, uint16_t *);
@@ -215,6 +213,9 @@ qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *,
extern int
qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+extern int
+qla2x00_stop_firmware(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
@@ -269,6 +270,9 @@ extern int qla2x00_rft_id(scsi_qla_host_t *);
extern int qla2x00_rff_id(scsi_qla_host_t *);
extern int qla2x00_rnn_id(scsi_qla_host_t *);
extern int qla2x00_rsnn_nn(scsi_qla_host_t *);
+extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern int qla2x00_fdmi_register(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_rscn.c source file.
@@ -289,6 +293,8 @@ extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_attr.c source file.
*/
+struct class_device_attribute;
+extern struct class_device_attribute *qla2x00_host_attrs[];
struct fc_function_template;
extern struct fc_function_template qla2xxx_transport_functions;
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 31ce4f62da13..e7b138c2e339 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1099,3 +1099,567 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
return (rval);
}
+
+/**
+ * qla2x00_mgmt_svr_login() - Login to fabric Managment Service.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_mgmt_svr_login(scsi_qla_host_t *ha)
+{
+ int ret;
+ uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+ ret = QLA_SUCCESS;
+ if (ha->flags.management_server_logged_in)
+ return ret;
+
+ ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
+ mb, BIT_1);
+ if (mb[0] != MBS_COMMAND_COMPLETE) {
+ DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
+ "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
+ __func__, ha->host_no, ha->mgmt_svr_loop_id, mb[0], mb[1],
+ mb[2], mb[6], mb[7]));
+ ret = QLA_FUNCTION_FAILED;
+ } else
+ ha->flags.management_server_logged_in = 1;
+
+ return ret;
+}
+
+/**
+ * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+ uint32_t rsp_size)
+{
+ ms_iocb_entry_t *ms_pkt;
+
+ ms_pkt = ha->ms_iocb;
+ memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
+
+ ms_pkt->entry_type = MS_IOCB_TYPE;
+ ms_pkt->entry_count = 1;
+ SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id);
+ ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
+ ms_pkt->timeout = __constant_cpu_to_le16(59);
+ ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+ ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
+ ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
+ ms_pkt->req_bytecount = cpu_to_le32(req_size);
+
+ ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+
+ ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
+
+ return ms_pkt;
+}
+
+/**
+ * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+ uint32_t rsp_size)
+{
+ struct ct_entry_24xx *ct_pkt;
+
+ ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+ memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
+
+ ct_pkt->entry_type = CT_IOCB_TYPE;
+ ct_pkt->entry_count = 1;
+ ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
+ ct_pkt->timeout = __constant_cpu_to_le16(59);
+ ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+ ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
+ ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
+ ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+
+ ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+
+ ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+
+ return ct_pkt;
+}
+
+static inline ms_iocb_entry_t *
+qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size)
+{
+ ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
+ struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+ ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+ } else {
+ ms_pkt->req_bytecount = cpu_to_le32(req_size);
+ ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+ }
+
+ return ms_pkt;
+}
+
+/**
+ * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
+ * @ct_req: CT request buffer
+ * @cmd: GS command
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the intitialized @ct_req.
+ */
+static inline struct ct_sns_req *
+qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
+ uint16_t rsp_size)
+{
+ memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+
+ ct_req->header.revision = 0x01;
+ ct_req->header.gs_type = 0xFA;
+ ct_req->header.gs_subtype = 0x10;
+ ct_req->command = cpu_to_be16(cmd);
+ ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+
+ return ct_req;
+}
+
+/**
+ * qla2x00_fdmi_rhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rhba(scsi_qla_host_t *ha)
+{
+ int rval, alen;
+ uint32_t size, sn;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ uint8_t *entries;
+ struct ct_fdmi_hba_attr *eiter;
+
+ /* Issue RHBA */
+ /* Prepare common MS IOCB */
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
+ RHBA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- attribute block, attributes. */
+ memcpy(ct_req->req.rhba.hba_identifier, ha->port_name, WWN_SIZE);
+ ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
+ memcpy(ct_req->req.rhba.port_name, ha->port_name, WWN_SIZE);
+ size = 2 * WWN_SIZE + 4 + 4;
+
+ /* Attributes */
+ ct_req->req.rhba.attrs.count =
+ __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
+ entries = ct_req->req.rhba.hba_identifier;
+
+ /* Nodename. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
+ eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
+ memcpy(eiter->a.node_name, ha->node_name, WWN_SIZE);
+ size += 4 + WWN_SIZE;
+
+ DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n",
+ __func__, ha->host_no,
+ eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2],
+ eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5],
+ eiter->a.node_name[6], eiter->a.node_name[7]));
+
+ /* Manufacturer. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
+ strcpy(eiter->a.manufacturer, "QLogic Corporation");
+ alen = strlen(eiter->a.manufacturer);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, ha->host_no,
+ eiter->a.manufacturer));
+
+ /* Serial number. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
+ sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+ sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
+ alen = strlen(eiter->a.serial_num);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, ha->host_no,
+ eiter->a.serial_num));
+
+ /* Model name. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
+ strcpy(eiter->a.model, ha->model_number);
+ alen = strlen(eiter->a.model);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, ha->host_no,
+ eiter->a.model));
+
+ /* Model description. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
+ if (ha->model_desc)
+ strncpy(eiter->a.model_desc, ha->model_desc, 80);
+ alen = strlen(eiter->a.model_desc);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, ha->host_no,
+ eiter->a.model_desc));
+
+ /* Hardware version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
+ strcpy(eiter->a.hw_version, ha->adapter_id);
+ alen = strlen(eiter->a.hw_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, ha->host_no,
+ eiter->a.hw_version));
+
+ /* Driver version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
+ strcpy(eiter->a.driver_version, qla2x00_version_str);
+ alen = strlen(eiter->a.driver_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, ha->host_no,
+ eiter->a.driver_version));
+
+ /* Option ROM version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
+ strcpy(eiter->a.orom_version, "0.00");
+ alen = strlen(eiter->a.orom_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, ha->host_no,
+ eiter->a.orom_version));
+
+ /* Firmware version */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
+ ha->isp_ops.fw_version_str(ha, eiter->a.fw_version);
+ alen = strlen(eiter->a.fw_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, ha->host_no,
+ eiter->a.fw_version));
+
+ /* Update MS request size. */
+ qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+ DEBUG13(printk("%s(%ld): RHBA identifier="
+ "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+ ha->host_no, ct_req->req.rhba.hba_identifier[0],
+ ct_req->req.rhba.hba_identifier[1],
+ ct_req->req.rhba.hba_identifier[2],
+ ct_req->req.rhba.hba_identifier[3],
+ ct_req->req.rhba.hba_identifier[4],
+ ct_req->req.rhba.hba_identifier[5],
+ ct_req->req.rhba.hba_identifier[6],
+ ct_req->req.rhba.hba_identifier[7], size));
+ DEBUG13(qla2x00_dump_buffer(entries, size));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RHBA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+ ct_rsp->header.explanation_code ==
+ CT_EXPL_ALREADY_REGISTERED) {
+ DEBUG2_13(printk("%s(%ld): HBA already registered.\n",
+ __func__, ha->host_no));
+ rval = QLA_ALREADY_REGISTERED;
+ }
+ } else {
+ DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_dhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_dhba(scsi_qla_host_t *ha)
+{
+ int rval;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+
+ /* Issue RPA */
+ /* Prepare common MS IOCB */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE,
+ DHBA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
+ DHBA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- portname. */
+ memcpy(ct_req->req.dhba.port_name, ha->port_name, WWN_SIZE);
+
+ DEBUG13(printk("%s(%ld): DHBA portname="
+ "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no,
+ ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
+ ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
+ ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
+ ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "DHBA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_rpa() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+{
+ int rval, alen;
+ uint32_t size, max_frame_size;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ uint8_t *entries;
+ struct ct_fdmi_port_attr *eiter;
+ struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+
+ /* Issue RPA */
+ /* Prepare common MS IOCB */
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
+ RPA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- attribute block, attributes. */
+ memcpy(ct_req->req.rpa.port_name, ha->port_name, WWN_SIZE);
+ size = WWN_SIZE + 4;
+
+ /* Attributes */
+ ct_req->req.rpa.attrs.count =
+ __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
+ entries = ct_req->req.rpa.port_name;
+
+ /* FC4 types. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
+ eiter->len = __constant_cpu_to_be16(4 + 32);
+ eiter->a.fc4_types[2] = 0x01;
+ size += 4 + 32;
+
+ DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__, ha->host_no,
+ eiter->a.fc4_types[2], eiter->a.fc4_types[1]));
+
+ /* Supported speed. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ if (IS_QLA25XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(4);
+ else if (IS_QLA24XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(8);
+ else if (IS_QLA23XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(2);
+ else
+ eiter->a.sup_speed = __constant_cpu_to_be32(1);
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no,
+ eiter->a.sup_speed));
+
+ /* Current speed. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ switch (ha->link_data_rate) {
+ case 0:
+ eiter->a.cur_speed = __constant_cpu_to_be32(1);
+ break;
+ case 1:
+ eiter->a.cur_speed = __constant_cpu_to_be32(2);
+ break;
+ case 3:
+ eiter->a.cur_speed = __constant_cpu_to_be32(8);
+ break;
+ case 4:
+ eiter->a.cur_speed = __constant_cpu_to_be32(4);
+ break;
+ }
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, ha->host_no,
+ eiter->a.cur_speed));
+
+ /* Max frame size. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ?
+ (uint32_t) icb24->frame_payload_size:
+ (uint32_t) ha->init_cb->frame_payload_size;
+ eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, ha->host_no,
+ eiter->a.max_frame_size));
+
+ /* OS device name. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+ sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no);
+ alen = strlen(eiter->a.os_dev_name);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no,
+ eiter->a.os_dev_name));
+
+ /* Update MS request size. */
+ qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+ DEBUG13(printk("%s(%ld): RPA portname="
+ "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+ ha->host_no, ct_req->req.rpa.port_name[0],
+ ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2],
+ ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4],
+ ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6],
+ ct_req->req.rpa.port_name[7], size));
+ DEBUG13(qla2x00_dump_buffer(entries, size));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RPA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ DEBUG2(printk("scsi(%ld): RPA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_register() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qla2x00_fdmi_register(scsi_qla_host_t *ha)
+{
+ int rval;
+
+ rval = qla2x00_mgmt_svr_login(ha);
+ if (rval)
+ return rval;
+
+ rval = qla2x00_fdmi_rhba(ha);
+ if (rval) {
+ if (rval != QLA_ALREADY_REGISTERED)
+ return rval;
+
+ rval = qla2x00_fdmi_dhba(ha);
+ if (rval)
+ return rval;
+
+ rval = qla2x00_fdmi_rhba(ha);
+ if (rval)
+ return rval;
+ }
+ rval = qla2x00_fdmi_rpa(ha);
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a6d2559217cd..3e9b64137873 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
ha->mbx_flags = 0;
ha->isp_abort_cnt = 0;
ha->beacon_blink_led = 0;
+ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
rval = ha->isp_ops.pci_config(ha);
@@ -1563,7 +1564,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
- ha->flags.enable_led_scheme = ((nv->efi_parameters & BIT_3) ? 1 : 0);
+ ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
ha->operating_mode =
(icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -1697,6 +1698,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
+ fcport->supported_classes = FC_COS_UNSPECIFIED;
return (fcport);
}
@@ -1898,7 +1900,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
continue;
/* Bypass if not same domain and area of adapter. */
- if (area != ha->d_id.b.area || domain != ha->d_id.b.domain)
+ if (area && domain &&
+ (area != ha->d_id.b.area || domain != ha->d_id.b.domain))
continue;
/* Bypass invalid local loop ID. */
@@ -2063,8 +2066,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
return;
}
- rport_ids.node_name = be64_to_cpu(*(uint64_t *)fcport->node_name);
- rport_ids.port_name = be64_to_cpu(*(uint64_t *)fcport->port_name);
+ rport_ids.node_name = wwn_to_u64(fcport->node_name);
+ rport_ids.port_name = wwn_to_u64(fcport->port_name);
rport_ids.port_id = fcport->d_id.b.domain << 16 |
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2075,6 +2078,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
return;
}
rport->dd_data = fcport;
+ rport->supported_classes = fcport->supported_classes;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
if (fcport->port_type == FCT_INITIATOR)
@@ -2130,6 +2134,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
return (QLA_SUCCESS);
}
do {
+ /* FDMI support. */
+ if (ql2xfdmienable &&
+ test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags))
+ qla2x00_fdmi_register(ha);
+
/* Ensure we are logged into the SNS. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
loop_id = NPH_SNS;
@@ -2392,6 +2401,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
if (new_fcport->d_id.b24 == ha->d_id.b24)
continue;
+ /* Bypass if same domain and area of adapter. */
+ if (((new_fcport->d_id.b24 & 0xffff00) ==
+ (ha->d_id.b24 & 0xffff00)) && ha->current_topology ==
+ ISP_CFG_FL)
+ continue;
+
/* Bypass reserved domain fields. */
if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
continue;
@@ -2794,6 +2809,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
}
}
+ if (mb[10] & BIT_0)
+ fcport->supported_classes |= FC_COS_CLASS2;
+ if (mb[10] & BIT_1)
+ fcport->supported_classes |= FC_COS_CLASS3;
+
rval = QLA_SUCCESS;
break;
} else if (mb[0] == MBS_LOOP_ID_USED) {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index ebdc3c54d155..37f82e2cd7fb 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -810,12 +810,8 @@ qla24xx_start_scsi(srb_t *sp)
ha->req_q_cnt = ha->request_q_length -
(ha->req_ring_index - cnt);
}
- if (ha->req_q_cnt < (req_cnt + 2)) {
- if (cmd->use_sg)
- pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
- cmd->sc_data_direction);
+ if (ha->req_q_cnt < (req_cnt + 2))
goto queuing_error;
- }
/* Build command packet. */
ha->current_outstanding_cmd = handle;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f910de6dd437..c255bb0268a9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->flags.management_server_logged_in = 0;
ha->link_data_rate = 0;
+ if (ql2xfdmienable)
+ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
/* Update AEN queue. */
qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 409ea0ac4032..13e1c9047079 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -19,6 +19,7 @@
#include "qla_def.h"
#include <linux/delay.h>
+#include <scsi/scsi_transport_fc.h>
static void
qla2x00_mbx_sem_timeout(unsigned long data)
@@ -251,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
} else {
- mb0 = RD_MAILBOX_REG(ha, reg->isp, 0);
+ mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
ictrl = RD_REG_WORD(&reg->isp.ictrl);
}
printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
@@ -983,58 +984,6 @@ qla2x00_abort_target(fc_port_t *fcport)
#endif
/*
- * qla2x00_target_reset
- * Issue target reset mailbox command.
- *
- * Input:
- * ha = adapter block pointer.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);)
-
- if (atomic_read(&fcport->state) != FCS_ONLINE)
- return 0;
-
- mcp->mb[0] = MBC_TARGET_RESET;
- if (HAS_EXTENDED_IDS(ha))
- mcp->mb[1] = fcport->loop_id;
- else
- mcp->mb[1] = fcport->loop_id << 8;
- mcp->mb[2] = ha->loop_reset_delay;
- mcp->out_mb = MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n",
- ha->host_no, rval);)
- } else {
- /*EMPTY*/
- DEBUG11(printk("qla2x00_target_reset(%ld): done.\n",
- ha->host_no);)
- }
-
- return rval;
-}
-
-/*
* qla2x00_get_adapter_id
* Get adapter ID and topology.
*
@@ -1326,6 +1275,10 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
fcport->port_type = FCT_INITIATOR;
else
fcport->port_type = FCT_TARGET;
+
+ /* Passback COS information. */
+ fcport->supported_classes = (pd->options & BIT_4) ?
+ FC_COS_CLASS2: FC_COS_CLASS3;
}
gpd_error_out:
@@ -1661,6 +1614,13 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
mb[1] |= BIT_1;
} else
mb[1] = BIT_0;
+
+ /* Passback COS information. */
+ mb[10] = 0;
+ if (lg->io_parameter[7] || lg->io_parameter[8])
+ mb[10] |= BIT_0; /* Class 2. */
+ if (lg->io_parameter[9] || lg->io_parameter[10])
+ mb[10] |= BIT_1; /* Class 3. */
}
dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1723,6 +1683,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
mb[2] = mcp->mb[2];
mb[6] = mcp->mb[6];
mb[7] = mcp->mb[7];
+ /* COS retrieved from Get-Port-Database mailbox command. */
+ mb[10] = 0;
}
if (rval != QLA_SUCCESS) {
@@ -2465,3 +2427,32 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
return rval;
}
+
+int
+qla2x00_stop_firmware(scsi_qla_host_t *ha)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+ mcp->mb[0] = MBC_STOP_FIRMWARE;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = 5;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 9000659bfbcf..8982978c42fd 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
-int ql2xfwloadbin;
+int ql2xfwloadbin=1;
module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
"Load ISP2xxx firmware image via hotplug.");
@@ -88,6 +88,12 @@ static void qla2x00_free_device(scsi_qla_host_t *);
static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
+int ql2xfdmienable;
+module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfdmienable,
+ "Enables FDMI registratons "
+ "Default is 0 - no FDMI. 1 - perfom FDMI.");
+
/*
* SCSI host template entry points
*/
@@ -105,6 +111,9 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
static int qla2x00_loop_reset(scsi_qla_host_t *ha);
static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
+static int qla2x00_change_queue_depth(struct scsi_device *, int);
+static int qla2x00_change_queue_type(struct scsi_device *, int);
+
static struct scsi_host_template qla2x00_driver_template = {
.module = THIS_MODULE,
.name = "qla2xxx",
@@ -119,6 +128,8 @@ static struct scsi_host_template qla2x00_driver_template = {
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .change_queue_depth = qla2x00_change_queue_depth,
+ .change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
@@ -129,6 +140,7 @@ static struct scsi_host_template qla2x00_driver_template = {
* which equates to 0x800000 sectors.
*/
.max_sectors = 0xFFFF,
+ .shost_attrs = qla2x00_host_attrs,
};
static struct scsi_host_template qla24xx_driver_template = {
@@ -145,12 +157,15 @@ static struct scsi_host_template qla24xx_driver_template = {
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .change_queue_depth = qla2x00_change_queue_depth,
+ .change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
+ .shost_attrs = qla2x00_host_attrs,
};
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@ -487,14 +502,13 @@ qc24_fail_command:
static int
qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
{
-#define ABORT_POLLING_PERIOD HZ
-#define ABORT_WAIT_ITER ((10 * HZ) / (ABORT_POLLING_PERIOD))
+#define ABORT_POLLING_PERIOD 1000
+#define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD))
unsigned long wait_iter = ABORT_WAIT_ITER;
int ret = QLA_SUCCESS;
while (CMD_SP(cmd)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(ABORT_POLLING_PERIOD);
+ msleep(ABORT_POLLING_PERIOD);
if (--wait_iter)
break;
@@ -1016,7 +1030,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
if (fcport->port_type != FCT_TARGET)
continue;
- status = qla2x00_target_reset(ha, fcport);
+ status = qla2x00_device_reset(ha, fcport);
if (status != QLA_SUCCESS)
break;
}
@@ -1103,6 +1117,28 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
sdev->hostdata = NULL;
}
+static int
+qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ return sdev->queue_depth;
+}
+
+static int
+qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+ if (sdev->tagged_supported) {
+ scsi_set_tag_type(sdev, tag_type);
+ if (tag_type)
+ scsi_activate_tcq(sdev, sdev->queue_depth);
+ else
+ scsi_deactivate_tcq(sdev, sdev->queue_depth);
+ } else
+ tag_type = 0;
+
+ return tag_type;
+}
+
/**
* qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
* @ha: HA context
@@ -1113,36 +1149,23 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
static void
qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
{
- /* Assume 32bit DMA address */
+ /* Assume a 32bit DMA mask. */
ha->flags.enable_64bit_addressing = 0;
- /*
- * Given the two variants pci_set_dma_mask(), allow the compiler to
- * assist in setting the proper dma mask.
- */
- if (sizeof(dma_addr_t) > 4) {
- if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
+ if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) {
+ /* Any upper-dword bits set? */
+ if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
+ !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
+ /* Ok, a 64bit DMA mask is applicable. */
ha->flags.enable_64bit_addressing = 1;
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64;
-
- if (pci_set_consistent_dma_mask(ha->pdev,
- DMA_64BIT_MASK)) {
- qla_printk(KERN_DEBUG, ha,
- "Failed to set 64 bit PCI consistent mask; "
- "using 32 bit.\n");
- pci_set_consistent_dma_mask(ha->pdev,
- DMA_32BIT_MASK);
- }
- } else {
- qla_printk(KERN_DEBUG, ha,
- "Failed to set 64 bit PCI DMA mask, falling back "
- "to 32 bit MASK.\n");
- pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
+ return;
}
- } else {
- pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
+
+ dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK);
+ pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
static int
@@ -1316,6 +1339,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->prev_topology = 0;
ha->ports = MAX_BUSES;
ha->init_cb_size = sizeof(init_cb_t);
+ ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
/* Assign ISP specific operations. */
ha->isp_ops.pci_config = qla2100_pci_config;
@@ -1338,6 +1362,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32;
ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb;
+ ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb;
ha->isp_ops.read_nvram = qla2x00_read_nvram_data;
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
ha->isp_ops.fw_dump = qla2100_fw_dump;
@@ -1375,6 +1400,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct init_cb_24xx);
+ ha->mgmt_svr_loop_id = 10;
ha->isp_ops.pci_config = qla24xx_pci_config;
ha->isp_ops.reset_chip = qla24xx_reset_chip;
ha->isp_ops.chip_diag = qla24xx_chip_diag;
@@ -1395,6 +1421,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.fabric_login = qla24xx_login_fabric;
ha->isp_ops.fabric_logout = qla24xx_fabric_logout;
ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb;
+ ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb;
ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
ha->isp_ops.fw_dump = qla24xx_fw_dump;
@@ -1558,8 +1585,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
return 0;
probe_failed:
- fc_remove_host(ha->host);
-
qla2x00_free_device(ha);
scsi_host_put(host);
@@ -1601,10 +1626,6 @@ qla2x00_free_device(scsi_qla_host_t *ha)
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
qla2x00_cancel_io_descriptors(ha);
- /* turn-off interrupts on the card */
- if (ha->interrupts_on)
- ha->isp_ops.disable_intrs(ha);
-
/* Disable timer */
if (ha->timer_active)
qla2x00_stop_timer(ha);
@@ -1624,8 +1645,14 @@ qla2x00_free_device(scsi_qla_host_t *ha)
}
}
- qla2x00_mem_free(ha);
+ /* Stop currently executing firmware. */
+ qla2x00_stop_firmware(ha);
+
+ /* turn-off interrupts on the card */
+ if (ha->interrupts_on)
+ ha->isp_ops.disable_intrs(ha);
+ qla2x00_mem_free(ha);
ha->flags.online = 0;
@@ -1934,7 +1961,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
{
struct list_head *fcpl, *fcptemp;
fc_port_t *fcport;
- unsigned long wtime;/* max wait time if mbx cmd is busy. */
+ unsigned int wtime;/* max wait time if mbx cmd is busy. */
if (ha == NULL) {
/* error */
@@ -1943,11 +1970,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
}
/* Make sure all other threads are stopped. */
- wtime = 60 * HZ;
- while (ha->dpc_wait && wtime) {
- set_current_state(TASK_INTERRUPTIBLE);
- wtime = schedule_timeout(wtime);
- }
+ wtime = 60 * 1000;
+ while (ha->dpc_wait && wtime)
+ wtime = msleep_interruptible(wtime);
/* free ioctl memory */
qla2x00_free_ioctl_mem(ha);
@@ -2478,15 +2503,15 @@ qla2x00_timer(scsi_qla_host_t *ha)
int
qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
{
- const unsigned int step = HZ/10;
+ const unsigned int step = 100; /* msecs */
+ unsigned int iterations = jiffies_to_msecs(timeout)/100;
do {
if (!down_trylock(sema))
return 0;
- set_current_state(TASK_INTERRUPTIBLE);
- if (schedule_timeout(step))
+ if (msleep_interruptible(step))
break;
- } while ((timeout -= step) > 0);
+ } while (--iterations >= 0);
return -ETIMEDOUT;
}
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d7f5c608009c..c14abf743b7c 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
uint32_t i;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
for (i = 0; i < dwords; i++, faddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
flash_data_to_access_addr(faddr)));
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return dwptr;
}
@@ -532,10 +523,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
ret = QLA_SUCCESS;
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
ha->host_no, man_id, flash_id));
@@ -599,10 +586,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return ret;
}
@@ -630,11 +613,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
{
uint32_t i;
uint32_t *dwptr;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
dwptr = (uint32_t *)buf;
@@ -642,10 +620,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
nvram_data_to_access_addr(naddr)));
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return buf;
}
@@ -690,10 +664,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
ret = QLA_SUCCESS;
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -728,9 +698,5 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index e3cd3618bc54..eae7d6edd531 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -19,9 +19,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.00b5-k"
+#define QLA2XXX_VERSION "8.01.00-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
#define QLA_DRIVER_PATCH_VER 0
-#define QLA_DRIVER_BETA_VER 5
+#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
new file mode 100644
index 000000000000..f1ea5027865f
--- /dev/null
+++ b/drivers/scsi/raid_class.c
@@ -0,0 +1,250 @@
+/*
+ * RAID Attributes
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/raid_class.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#define RAID_NUM_ATTRS 3
+
+struct raid_internal {
+ struct raid_template r;
+ struct raid_function_template *f;
+ /* The actual attributes */
+ struct class_device_attribute private_attrs[RAID_NUM_ATTRS];
+ /* The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c */
+ struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1];
+};
+
+struct raid_component {
+ struct list_head node;
+ struct device *dev;
+ int num;
+};
+
+#define to_raid_internal(tmpl) container_of(tmpl, struct raid_internal, r)
+
+#define tc_to_raid_internal(tcont) ({ \
+ struct raid_template *r = \
+ container_of(tcont, struct raid_template, raid_attrs); \
+ to_raid_internal(r); \
+})
+
+#define ac_to_raid_internal(acont) ({ \
+ struct transport_container *tc = \
+ container_of(acont, struct transport_container, ac); \
+ tc_to_raid_internal(tc); \
+})
+
+#define class_device_to_raid_internal(cdev) ({ \
+ struct attribute_container *ac = \
+ attribute_container_classdev_to_container(cdev); \
+ ac_to_raid_internal(ac); \
+})
+
+
+static int raid_match(struct attribute_container *cont, struct device *dev)
+{
+ /* We have to look for every subsystem that could house
+ * emulated RAID devices, so start with SCSI */
+ struct raid_internal *i = ac_to_raid_internal(cont);
+
+ if (scsi_is_sdev_device(dev)) {
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (i->f->cookie != sdev->host->hostt)
+ return 0;
+
+ return i->f->is_raid(dev);
+ }
+ /* FIXME: look at other subsystems too */
+ return 0;
+}
+
+static int raid_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct raid_data *rd;
+
+ BUG_ON(class_get_devdata(cdev));
+
+ rd = kmalloc(sizeof(*rd), GFP_KERNEL);
+ if (!rd)
+ return -ENOMEM;
+
+ memset(rd, 0, sizeof(*rd));
+ INIT_LIST_HEAD(&rd->component_list);
+ class_set_devdata(cdev, rd);
+
+ return 0;
+}
+
+static int raid_remove(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct raid_data *rd = class_get_devdata(cdev);
+ struct raid_component *rc, *next;
+ class_set_devdata(cdev, NULL);
+ list_for_each_entry_safe(rc, next, &rd->component_list, node) {
+ char buf[40];
+ snprintf(buf, sizeof(buf), "component-%d", rc->num);
+ list_del(&rc->node);
+ sysfs_remove_link(&cdev->kobj, buf);
+ kfree(rc);
+ }
+ kfree(class_get_devdata(cdev));
+ return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(raid_class,
+ "raid_devices",
+ raid_setup,
+ raid_remove,
+ NULL);
+
+static struct {
+ enum raid_state value;
+ char *name;
+} raid_states[] = {
+ { RAID_ACTIVE, "active" },
+ { RAID_DEGRADED, "degraded" },
+ { RAID_RESYNCING, "resyncing" },
+ { RAID_OFFLINE, "offline" },
+};
+
+static const char *raid_state_name(enum raid_state state)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) {
+ if (raid_states[i].value == state) {
+ name = raid_states[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
+
+#define raid_attr_show_internal(attr, fmt, var, code) \
+static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \
+{ \
+ struct raid_data *rd = class_get_devdata(cdev); \
+ code \
+ return snprintf(buf, 20, #fmt "\n", var); \
+}
+
+#define raid_attr_ro_states(attr, states, code) \
+raid_attr_show_internal(attr, %s, name, \
+ const char *name; \
+ code \
+ name = raid_##states##_name(rd->attr); \
+) \
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+
+#define raid_attr_ro_internal(attr, code) \
+raid_attr_show_internal(attr, %d, rd->attr, code) \
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+#define ATTR_CODE(attr) \
+ struct raid_internal *i = class_device_to_raid_internal(cdev); \
+ if (i->f->get_##attr) \
+ i->f->get_##attr(cdev->dev);
+
+#define raid_attr_ro(attr) raid_attr_ro_internal(attr, )
+#define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr))
+#define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
+
+raid_attr_ro(level);
+raid_attr_ro_fn(resync);
+raid_attr_ro_state(state);
+
+void raid_component_add(struct raid_template *r,struct device *raid_dev,
+ struct device *component_dev)
+{
+ struct class_device *cdev =
+ attribute_container_find_class_device(&r->raid_attrs.ac,
+ raid_dev);
+ struct raid_component *rc;
+ struct raid_data *rd = class_get_devdata(cdev);
+ char buf[40];
+
+ rc = kmalloc(sizeof(*rc), GFP_KERNEL);
+ if (!rc)
+ return;
+
+ INIT_LIST_HEAD(&rc->node);
+ rc->dev = component_dev;
+ rc->num = rd->component_count++;
+
+ snprintf(buf, sizeof(buf), "component-%d", rc->num);
+ list_add_tail(&rc->node, &rd->component_list);
+ sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf);
+}
+EXPORT_SYMBOL(raid_component_add);
+
+struct raid_template *
+raid_class_attach(struct raid_function_template *ft)
+{
+ struct raid_internal *i = kmalloc(sizeof(struct raid_internal),
+ GFP_KERNEL);
+ int count = 0;
+
+ if (unlikely(!i))
+ return NULL;
+
+ memset(i, 0, sizeof(*i));
+
+ i->f = ft;
+
+ i->r.raid_attrs.ac.class = &raid_class.class;
+ i->r.raid_attrs.ac.match = raid_match;
+ i->r.raid_attrs.ac.attrs = &i->attrs[0];
+
+ attribute_container_register(&i->r.raid_attrs.ac);
+
+ i->attrs[count++] = &class_device_attr_level;
+ i->attrs[count++] = &class_device_attr_resync;
+ i->attrs[count++] = &class_device_attr_state;
+
+ i->attrs[count] = NULL;
+ BUG_ON(count > RAID_NUM_ATTRS);
+
+ return &i->r;
+}
+EXPORT_SYMBOL(raid_class_attach);
+
+void
+raid_class_release(struct raid_template *r)
+{
+ struct raid_internal *i = to_raid_internal(r);
+
+ attribute_container_unregister(&i->r.raid_attrs.ac);
+
+ kfree(i);
+}
+EXPORT_SYMBOL(raid_class_release);
+
+static __init int raid_init(void)
+{
+ return transport_class_register(&raid_class);
+}
+
+static __exit void raid_exit(void)
+{
+ transport_class_unregister(&raid_class);
+}
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("RAID device class");
+MODULE_LICENSE("GPL");
+
+module_init(raid_init);
+module_exit(raid_exit);
+
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
new file mode 100644
index 000000000000..ea76fe44585e
--- /dev/null
+++ b/drivers/scsi/sata_mv.c
@@ -0,0 +1,827 @@
+/*
+ * sata_mv.c - Marvell SATA support
+ *
+ * Copyright 2005: EMC Corporation, all rights reserved.
+ *
+ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME "sata_mv"
+#define DRV_VERSION "0.12"
+
+enum {
+ /* BAR's are enumerated in terms of pci_resource_start() terms */
+ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */
+ MV_IO_BAR = 2, /* offset 0x18: IO space */
+ MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */
+
+ MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */
+ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */
+
+ MV_PCI_REG_BASE = 0,
+ MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
+ MV_SATAHC0_REG_BASE = 0x20000,
+
+ MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ,
+ MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ,
+ MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */
+ MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ,
+
+ MV_Q_CT = 32,
+ MV_CRQB_SZ = 32,
+ MV_CRPB_SZ = 8,
+
+ MV_DMA_BOUNDARY = 0xffffffffU,
+ SATAHC_MASK = (~(MV_SATAHC_REG_SZ - 1)),
+
+ MV_PORTS_PER_HC = 4,
+ /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
+ MV_PORT_HC_SHIFT = 2,
+ /* == (port % MV_PORTS_PER_HC) to determine port from 0-7 port */
+ MV_PORT_MASK = 3,
+
+ /* Host Flags */
+ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
+ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
+ MV_FLAG_BDMA = (1 << 28), /* Basic DMA */
+
+ chip_504x = 0,
+ chip_508x = 1,
+ chip_604x = 2,
+ chip_608x = 3,
+
+ /* PCI interface registers */
+
+ PCI_MAIN_CMD_STS_OFS = 0xd30,
+ STOP_PCI_MASTER = (1 << 2),
+ PCI_MASTER_EMPTY = (1 << 3),
+ GLOB_SFT_RST = (1 << 4),
+
+ PCI_IRQ_CAUSE_OFS = 0x1d58,
+ PCI_IRQ_MASK_OFS = 0x1d5c,
+ PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */
+
+ HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
+ HC_MAIN_IRQ_MASK_OFS = 0x1d64,
+ PORT0_ERR = (1 << 0), /* shift by port # */
+ PORT0_DONE = (1 << 1), /* shift by port # */
+ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
+ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */
+ PCI_ERR = (1 << 18),
+ TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */
+ TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */
+ PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */
+ GPIO_INT = (1 << 22),
+ SELF_INT = (1 << 23),
+ TWSI_INT = (1 << 24),
+ HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
+ HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
+ PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
+ HC_MAIN_RSVD),
+
+ /* SATAHC registers */
+ HC_CFG_OFS = 0,
+
+ HC_IRQ_CAUSE_OFS = 0x14,
+ CRBP_DMA_DONE = (1 << 0), /* shift by port # */
+ HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */
+ DEV_IRQ = (1 << 8), /* shift by port # */
+
+ /* Shadow block registers */
+ SHD_PIO_DATA_OFS = 0x100,
+ SHD_FEA_ERR_OFS = 0x104,
+ SHD_SECT_CNT_OFS = 0x108,
+ SHD_LBA_L_OFS = 0x10C,
+ SHD_LBA_M_OFS = 0x110,
+ SHD_LBA_H_OFS = 0x114,
+ SHD_DEV_HD_OFS = 0x118,
+ SHD_CMD_STA_OFS = 0x11C,
+ SHD_CTL_AST_OFS = 0x120,
+
+ /* SATA registers */
+ SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
+ SATA_ACTIVE_OFS = 0x350,
+
+ /* Port registers */
+ EDMA_CFG_OFS = 0,
+
+ EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
+ EDMA_ERR_IRQ_MASK_OFS = 0xc,
+ EDMA_ERR_D_PAR = (1 << 0),
+ EDMA_ERR_PRD_PAR = (1 << 1),
+ EDMA_ERR_DEV = (1 << 2),
+ EDMA_ERR_DEV_DCON = (1 << 3),
+ EDMA_ERR_DEV_CON = (1 << 4),
+ EDMA_ERR_SERR = (1 << 5),
+ EDMA_ERR_SELF_DIS = (1 << 7),
+ EDMA_ERR_BIST_ASYNC = (1 << 8),
+ EDMA_ERR_CRBQ_PAR = (1 << 9),
+ EDMA_ERR_CRPB_PAR = (1 << 10),
+ EDMA_ERR_INTRL_PAR = (1 << 11),
+ EDMA_ERR_IORDY = (1 << 12),
+ EDMA_ERR_LNK_CTRL_RX = (0xf << 13),
+ EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15),
+ EDMA_ERR_LNK_DATA_RX = (0xf << 17),
+ EDMA_ERR_LNK_CTRL_TX = (0x1f << 21),
+ EDMA_ERR_LNK_DATA_TX = (0x1f << 26),
+ EDMA_ERR_TRANS_PROTO = (1 << 31),
+ EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+ EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
+ EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
+ EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
+ EDMA_ERR_LNK_DATA_RX |
+ EDMA_ERR_LNK_DATA_TX |
+ EDMA_ERR_TRANS_PROTO),
+
+ EDMA_CMD_OFS = 0x28,
+ EDMA_EN = (1 << 0),
+ EDMA_DS = (1 << 1),
+ ATA_RST = (1 << 2),
+
+ /* BDMA is 6xxx part only */
+ BDMA_CMD_OFS = 0x224,
+ BDMA_START = (1 << 0),
+
+ MV_UNDEF = 0,
+};
+
+struct mv_port_priv {
+
+};
+
+struct mv_host_priv {
+
+};
+
+static void mv_irq_clear(struct ata_port *ap);
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static void mv_phy_reset(struct ata_port *ap);
+static int mv_master_reset(void __iomem *mmio_base);
+static irqreturn_t mv_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs);
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static Scsi_Host_Template mv_sht = {
+ .module = THIS_MODULE,
+ .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 = MV_UNDEF,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = MV_UNDEF,
+ .proc_name = DRV_NAME,
+ .dma_boundary = MV_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+ .ordered_flush = 1,
+};
+
+static struct ata_port_operations mv_ops = {
+ .port_disable = ata_port_disable,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+
+ .phy_reset = mv_phy_reset,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = mv_interrupt,
+ .irq_clear = mv_irq_clear,
+
+ .scr_read = mv_scr_read,
+ .scr_write = mv_scr_write,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+static struct ata_port_info mv_port_info[] = {
+ { /* chip_504x */
+ .sht = &mv_sht,
+ .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+ .pio_mask = 0x1f, /* pio4-0 */
+ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_508x */
+ .sht = &mv_sht,
+ .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ MV_FLAG_DUAL_HC),
+ .pio_mask = 0x1f, /* pio4-0 */
+ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_604x */
+ .sht = &mv_sht,
+ .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA),
+ .pio_mask = 0x1f, /* pio4-0 */
+ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_608x */
+ .sht = &mv_sht,
+ .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC |
+ MV_FLAG_BDMA),
+ .pio_mask = 0x1f, /* pio4-0 */
+ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+};
+
+static struct pci_device_id mv_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
+
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
+ {} /* terminate list */
+};
+
+static struct pci_driver mv_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = mv_pci_tbl,
+ .probe = mv_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+/*
+ * Functions
+ */
+
+static inline void writelfl(unsigned long data, void __iomem *addr)
+{
+ writel(data, addr);
+ (void) readl(addr); /* flush to avoid PCI posted write */
+}
+
+static inline void __iomem *mv_port_addr_to_hc_base(void __iomem *port_mmio)
+{
+ return ((void __iomem *)((unsigned long)port_mmio &
+ (unsigned long)SATAHC_MASK));
+}
+
+static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+{
+ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+}
+
+static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
+{
+ return (mv_hc_base(base, port >> MV_PORT_HC_SHIFT) +
+ MV_SATAHC_ARBTR_REG_SZ +
+ ((port & MV_PORT_MASK) * MV_PORT_REG_SZ));
+}
+
+static inline void __iomem *mv_ap_base(struct ata_port *ap)
+{
+ return mv_port_base(ap->host_set->mmio_base, ap->port_no);
+}
+
+static inline int mv_get_hc_count(unsigned long flags)
+{
+ return ((flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+}
+
+static inline int mv_is_edma_active(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ return (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+}
+
+static inline int mv_port_bdma_capable(struct ata_port *ap)
+{
+ return (ap->flags & MV_FLAG_BDMA);
+}
+
+static void mv_irq_clear(struct ata_port *ap)
+{
+}
+
+static unsigned int mv_scr_offset(unsigned int sc_reg_in)
+{
+ unsigned int ofs;
+
+ switch (sc_reg_in) {
+ case SCR_STATUS:
+ case SCR_CONTROL:
+ case SCR_ERROR:
+ ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
+ break;
+ case SCR_ACTIVE:
+ ofs = SATA_ACTIVE_OFS; /* active is not with the others */
+ break;
+ default:
+ ofs = 0xffffffffU;
+ break;
+ }
+ return ofs;
+}
+
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
+{
+ unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+ if (0xffffffffU != ofs) {
+ return readl(mv_ap_base(ap) + ofs);
+ } else {
+ return (u32) ofs;
+ }
+}
+
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+{
+ unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+ if (0xffffffffU != ofs) {
+ writelfl(val, mv_ap_base(ap) + ofs);
+ }
+}
+
+static int mv_master_reset(void __iomem *mmio_base)
+{
+ void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS;
+ int i, rc = 0;
+ u32 t;
+
+ VPRINTK("ENTER\n");
+
+ /* Following procedure defined in PCI "main command and status
+ * register" table.
+ */
+ t = readl(reg);
+ writel(t | STOP_PCI_MASTER, reg);
+
+ for (i = 0; i < 100; i++) {
+ msleep(10);
+ t = readl(reg);
+ if (PCI_MASTER_EMPTY & t) {
+ break;
+ }
+ }
+ if (!(PCI_MASTER_EMPTY & t)) {
+ printk(KERN_ERR DRV_NAME "PCI master won't flush\n");
+ rc = 1; /* broken HW? */
+ goto done;
+ }
+
+ /* set reset */
+ i = 5;
+ do {
+ writel(t | GLOB_SFT_RST, reg);
+ t = readl(reg);
+ udelay(1);
+ } while (!(GLOB_SFT_RST & t) && (i-- > 0));
+
+ if (!(GLOB_SFT_RST & t)) {
+ printk(KERN_ERR DRV_NAME "can't set global reset\n");
+ rc = 1; /* broken HW? */
+ goto done;
+ }
+
+ /* clear reset */
+ i = 5;
+ do {
+ writel(t & ~GLOB_SFT_RST, reg);
+ t = readl(reg);
+ udelay(1);
+ } while ((GLOB_SFT_RST & t) && (i-- > 0));
+
+ if (GLOB_SFT_RST & t) {
+ printk(KERN_ERR DRV_NAME "can't clear global reset\n");
+ rc = 1; /* broken HW? */
+ }
+
+ done:
+ VPRINTK("EXIT, rc = %i\n", rc);
+ return rc;
+}
+
+static void mv_err_intr(struct ata_port *ap)
+{
+ void __iomem *port_mmio;
+ u32 edma_err_cause, serr = 0;
+
+ /* bug here b/c we got an err int on a port we don't know about,
+ * so there's no way to clear it
+ */
+ BUG_ON(NULL == ap);
+ port_mmio = mv_ap_base(ap);
+
+ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ if (EDMA_ERR_SERR & edma_err_cause) {
+ serr = scr_read(ap, SCR_ERROR);
+ scr_write_flush(ap, SCR_ERROR, serr);
+ }
+ DPRINTK("port %u error; EDMA err cause: 0x%08x SERR: 0x%08x\n",
+ ap->port_no, edma_err_cause, serr);
+
+ /* Clear EDMA now that SERR cleanup done */
+ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* check for fatal here and recover if needed */
+ if (EDMA_ERR_FATAL & edma_err_cause) {
+ mv_phy_reset(ap);
+ }
+}
+
+/* Handle any outstanding interrupts in a single SATAHC
+ */
+static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
+ unsigned int hc)
+{
+ 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;
+ u8 ata_status;
+
+ if (hc == 0) {
+ port0 = 0;
+ } else {
+ port0 = MV_PORTS_PER_HC;
+ }
+
+ /* we'll need the HC success int register in most cases */
+ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+ if (hc_irq_cause) {
+ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+ }
+
+ VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
+ hc,relevant,hc_irq_cause);
+
+ for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
+ ap = host_set->ports[port];
+ hard_port = port & MV_PORT_MASK; /* range 0-3 */
+ ata_status = 0xffU;
+
+ if (((CRBP_DMA_DONE | DEV_IRQ) << hard_port) & hc_irq_cause) {
+ BUG_ON(NULL == ap);
+ /* rcv'd new resp, basic DMA complete, or ATA IRQ */
+ /* This is needed to clear the ATA INTRQ.
+ * FIXME: don't read the status reg in EDMA mode!
+ */
+ ata_status = readb((void __iomem *)
+ ap->ioaddr.status_addr);
+ }
+
+ shift = port * 2;
+ if (port >= MV_PORTS_PER_HC) {
+ shift++; /* skip bit 8 in the HC Main IRQ reg */
+ }
+ if ((PORT0_ERR << shift) & relevant) {
+ mv_err_intr(ap);
+ /* FIXME: smart to OR in ATA_ERR? */
+ ata_status = readb((void __iomem *)
+ ap->ioaddr.status_addr) | ATA_ERR;
+ }
+
+ if (ap) {
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (NULL != qc) {
+ VPRINTK("port %u IRQ found for qc, "
+ "ata_status 0x%x\n", port,ata_status);
+ BUG_ON(0xffU == ata_status);
+ /* mark qc status appropriately */
+ ata_qc_complete(qc, ata_status);
+ }
+ }
+ }
+ VPRINTK("EXIT\n");
+}
+
+static irqreturn_t mv_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ unsigned int hc, handled = 0, n_hcs;
+ void __iomem *mmio;
+ u32 irq_stat;
+
+ mmio = host_set->mmio_base;
+ irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
+ n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
+
+ /* check the cases where we either have nothing pending or have read
+ * a bogus register value which can indicate HW removal or PCI fault
+ */
+ if (!irq_stat || (0xffffffffU == irq_stat)) {
+ return IRQ_NONE;
+ }
+
+ spin_lock(&host_set->lock);
+
+ for (hc = 0; hc < n_hcs; hc++) {
+ u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
+ if (relevant) {
+ mv_host_intr(host_set, relevant, hc);
+ handled = 1;
+ }
+ }
+ if (PCI_ERR & irq_stat) {
+ /* FIXME: these are all masked by default, but still need
+ * to recover from them properly.
+ */
+ }
+
+ spin_unlock(&host_set->lock);
+
+ return IRQ_RETVAL(handled);
+}
+
+static void mv_phy_reset(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct ata_taskfile tf;
+ struct ata_device *dev = &ap->device[0];
+ u32 edma = 0, bdma;
+
+ VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
+
+ edma = readl(port_mmio + EDMA_CMD_OFS);
+ if (EDMA_EN & edma) {
+ /* disable EDMA if active */
+ edma &= ~EDMA_EN;
+ writelfl(edma | EDMA_DS, port_mmio + EDMA_CMD_OFS);
+ udelay(1);
+ } else if (mv_port_bdma_capable(ap) &&
+ (bdma = readl(port_mmio + BDMA_CMD_OFS)) & BDMA_START) {
+ /* disable BDMA if active */
+ writelfl(bdma & ~BDMA_START, port_mmio + BDMA_CMD_OFS);
+ }
+
+ writelfl(edma | ATA_RST, port_mmio + EDMA_CMD_OFS);
+ udelay(25); /* allow reset propagation */
+
+ /* Spec never mentions clearing the bit. Marvell's driver does
+ * clear the bit, however.
+ */
+ writelfl(edma & ~ATA_RST, port_mmio + EDMA_CMD_OFS);
+
+ VPRINTK("Done. Now calling __sata_phy_reset()\n");
+
+ /* proceed to init communications via the scr_control reg */
+ __sata_phy_reset(ap);
+
+ if (ap->flags & ATA_FLAG_PORT_DISABLED) {
+ VPRINTK("Port disabled pre-sig. Exiting.\n");
+ return;
+ }
+
+ tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
+ tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
+ tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
+ tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
+
+ dev->class = ata_dev_classify(&tf);
+ if (!ata_dev_present(dev)) {
+ VPRINTK("Port disabled post-sig: No device present.\n");
+ ata_port_disable(ap);
+ }
+ VPRINTK("EXIT\n");
+}
+
+static void mv_port_init(struct ata_ioports *port, unsigned long base)
+{
+ /* PIO related setup */
+ port->data_addr = base + SHD_PIO_DATA_OFS;
+ port->error_addr = port->feature_addr = base + SHD_FEA_ERR_OFS;
+ port->nsect_addr = base + SHD_SECT_CNT_OFS;
+ port->lbal_addr = base + SHD_LBA_L_OFS;
+ port->lbam_addr = base + SHD_LBA_M_OFS;
+ port->lbah_addr = base + SHD_LBA_H_OFS;
+ port->device_addr = base + SHD_DEV_HD_OFS;
+ port->status_addr = port->command_addr = base + SHD_CMD_STA_OFS;
+ port->altstatus_addr = port->ctl_addr = base + SHD_CTL_AST_OFS;
+ /* unused */
+ port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+
+ /* unmask all EDMA error interrupts */
+ writel(~0, (void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS);
+
+ VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
+ readl((void __iomem *)base + EDMA_CFG_OFS),
+ readl((void __iomem *)base + EDMA_ERR_IRQ_CAUSE_OFS),
+ readl((void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS));
+}
+
+static int mv_host_init(struct ata_probe_ent *probe_ent)
+{
+ int rc = 0, n_hc, port, hc;
+ void __iomem *mmio = probe_ent->mmio_base;
+ void __iomem *port_mmio;
+
+ if (mv_master_reset(probe_ent->mmio_base)) {
+ rc = 1;
+ goto done;
+ }
+
+ n_hc = mv_get_hc_count(probe_ent->host_flags);
+ probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
+
+ for (port = 0; port < probe_ent->n_ports; port++) {
+ port_mmio = mv_port_base(mmio, port);
+ mv_port_init(&probe_ent->port[port], (unsigned long)port_mmio);
+ }
+
+ for (hc = 0; hc < n_hc; hc++) {
+ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause=0x%08x\n", hc,
+ readl(mv_hc_base(mmio, hc) + HC_CFG_OFS),
+ readl(mv_hc_base(mmio, hc) + HC_IRQ_CAUSE_OFS));
+ }
+
+ writel(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
+ writel(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+
+ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
+ "PCI int cause/mask=0x%08x/0x%08x\n",
+ readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
+ readl(mmio + HC_MAIN_IRQ_MASK_OFS),
+ readl(mmio + PCI_IRQ_CAUSE_OFS),
+ readl(mmio + PCI_IRQ_MASK_OFS));
+
+ done:
+ return rc;
+}
+
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ struct ata_probe_ent *probe_ent = NULL;
+ struct mv_host_priv *hpriv;
+ unsigned int board_idx = (unsigned int)ent->driver_data;
+ void __iomem *mmio_base;
+ int pci_dev_busy = 0;
+ int rc;
+
+ if (!printed_version++) {
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ }
+
+ VPRINTK("ENTER for PCI Bus:Slot.Func=%u:%u.%u\n", pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc) {
+ pci_dev_busy = 1;
+ goto err_out;
+ }
+
+ pci_intx(pdev, 1);
+
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ mmio_base = ioremap_nocache(pci_resource_start(pdev, MV_PRIMARY_BAR),
+ pci_resource_len(pdev, MV_PRIMARY_BAR));
+ if (mmio_base == NULL) {
+ rc = -ENOMEM;
+ goto err_out_free_ent;
+ }
+
+ hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv) {
+ rc = -ENOMEM;
+ goto err_out_iounmap;
+ }
+ memset(hpriv, 0, sizeof(*hpriv));
+
+ probe_ent->sht = mv_port_info[board_idx].sht;
+ probe_ent->host_flags = mv_port_info[board_idx].host_flags;
+ probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
+ probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
+ probe_ent->port_ops = mv_port_info[board_idx].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = mmio_base;
+ probe_ent->private_data = hpriv;
+
+ /* initialize adapter */
+ rc = mv_host_init(probe_ent);
+ if (rc) {
+ goto err_out_hpriv;
+ }
+/* mv_print_info(probe_ent); */
+
+ {
+ int b, w;
+ u32 dw[4]; /* hold a line of 16b */
+ VPRINTK("PCI config space:\n");
+ for (b = 0; b < 0x40; ) {
+ for (w = 0; w < 4; w++) {
+ (void) pci_read_config_dword(pdev,b,&dw[w]);
+ b += sizeof(*dw);
+ }
+ VPRINTK("%08x %08x %08x %08x\n",
+ dw[0],dw[1],dw[2],dw[3]);
+ }
+ }
+
+ /* FIXME: check ata_device_add return value */
+ ata_device_add(probe_ent);
+ kfree(probe_ent);
+
+ return 0;
+
+ err_out_hpriv:
+ kfree(hpriv);
+ err_out_iounmap:
+ iounmap(mmio_base);
+ err_out_free_ent:
+ kfree(probe_ent);
+ err_out_regions:
+ pci_release_regions(pdev);
+ err_out:
+ if (!pci_dev_busy) {
+ pci_disable_device(pdev);
+ }
+
+ return rc;
+}
+
+static int __init mv_init(void)
+{
+ return pci_module_init(&mv_pci_driver);
+}
+
+static void __exit mv_exit(void)
+{
+ pci_unregister_driver(&mv_pci_driver);
+}
+
+MODULE_AUTHOR("Brett Russ");
+MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(mv_init);
+module_exit(mv_exit);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index b0403ccd8a25..a1d62dee3be6 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -4,21 +4,37 @@
* Copyright 2004 NVIDIA Corp. All rights reserved.
* Copyright 2004 Andrew Chew
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * No hardware documentation available outside of NVIDIA.
+ * This driver programs the NVIDIA SATA controller in a similar
+ * fashion as with other PCI IDE BMDMA controllers, with a few
+ * NV-specific details such as register offsets, SATA phy location,
+ * hotplug info, etc.
+ *
+ *
+ * 0.08
+ * - Added support for MCP51 and MCP55.
+ *
+ * 0.07
+ * - Added support for RAID class code.
*
* 0.06
* - Added generic SATA support by using a pci_device_id that filters on
@@ -48,7 +64,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_nv"
-#define DRV_VERSION "0.6"
+#define DRV_VERSION "0.8"
#define NV_PORTS 2
#define NV_PIO_MASK 0x1f
@@ -116,7 +132,9 @@ enum nv_host_type
GENERIC,
NFORCE2,
NFORCE3,
- CK804
+ CK804,
+ MCP51,
+ MCP55
};
static struct pci_device_id nv_pci_tbl[] = {
@@ -134,9 +152,18 @@ static struct pci_device_id nv_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
{ 0, } /* terminate list */
};
@@ -274,7 +301,8 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -323,6 +351,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static void nv_host_stop (struct ata_host_set *host_set)
{
struct nv_host *host = host_set->private_data;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
// Disable hotplug event interrupts.
if (host->host_desc->disable_hotplug)
@@ -330,7 +359,8 @@ static void nv_host_stop (struct ata_host_set *host_set)
kfree(host);
- ata_host_stop(host_set);
+ if (host_set->mmio_base)
+ pci_iounmap(pdev, host_set->mmio_base);
}
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -392,8 +422,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
unsigned long base;
- probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
if (probe_ent->mmio_base == NULL) {
rc = -EIO;
goto err_out_free_host;
@@ -429,7 +458,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_iounmap:
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- iounmap(probe_ent->mmio_base);
+ pci_iounmap(pdev, probe_ent->mmio_base);
err_out_free_host:
kfree(host);
err_out_free_ent:
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 919fb314ad10..538ad727bd2e 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -7,21 +7,26 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware information only available under NDA.
*
*/
@@ -79,13 +84,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
static void pdc_eng_timeout(struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
-static void pdc_phy_reset(struct ata_port *ap);
+static void pdc_pata_phy_reset(struct ata_port *ap);
+static void pdc_sata_phy_reset(struct ata_port *ap);
static void pdc_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_irq_clear(struct ata_port *ap);
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
+
static Scsi_Host_Template pdc_ata_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -106,24 +113,48 @@ static Scsi_Host_Template pdc_ata_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations pdc_ata_ops = {
+static struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
.dev_select = ata_std_dev_select,
- .phy_reset = pdc_phy_reset,
+
+ .phy_reset = pdc_sata_phy_reset,
+
.qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot,
.eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear,
+
.scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write,
.port_start = pdc_port_start,
.port_stop = pdc_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
+};
+
+static struct ata_port_operations pdc_pata_ops = {
+ .port_disable = ata_port_disable,
+ .tf_load = pdc_tf_load_mmio,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = pdc_exec_command_mmio,
+ .dev_select = ata_std_dev_select,
+
+ .phy_reset = pdc_pata_phy_reset,
+
+ .qc_prep = pdc_qc_prep,
+ .qc_issue = pdc_qc_issue_prot,
+ .eng_timeout = pdc_eng_timeout,
+ .irq_handler = pdc_interrupt,
+ .irq_clear = pdc_irq_clear,
+
+ .port_start = pdc_port_start,
+ .port_stop = pdc_port_stop,
+ .host_stop = ata_pci_host_stop,
};
static struct ata_port_info pdc_port_info[] = {
@@ -135,7 +166,7 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_sata_ops,
},
/* board_20319 */
@@ -146,7 +177,7 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_sata_ops,
},
/* board_20619 */
@@ -157,7 +188,7 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_pata_ops,
},
};
@@ -181,6 +212,10 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
@@ -248,7 +283,7 @@ static void pdc_port_stop(struct ata_port *ap)
static void pdc_reset_port(struct ata_port *ap)
{
- void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
unsigned int i;
u32 tmp;
@@ -268,12 +303,23 @@ static void pdc_reset_port(struct ata_port *ap)
readl(mmio); /* flush */
}
-static void pdc_phy_reset(struct ata_port *ap)
+static void pdc_sata_phy_reset(struct ata_port *ap)
{
pdc_reset_port(ap);
sata_phy_reset(ap);
}
+static void pdc_pata_phy_reset(struct ata_port *ap)
+{
+ /* FIXME: add cable detect. Don't assume 40-pin cable */
+ ap->cbl = ATA_CBL_PATA40;
+ ap->udma_mask &= ATA_UDMA_MASK_40C;
+
+ pdc_reset_port(ap);
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
+}
+
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
@@ -321,11 +367,15 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
static void pdc_eng_timeout(struct ata_port *ap)
{
+ struct ata_host_set *host_set = ap->host_set;
u8 drv_stat;
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -359,6 +409,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
}
out:
+ spin_unlock_irqrestore(&host_set->lock, flags);
DPRINTK("EXIT\n");
}
@@ -368,7 +419,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
u8 status;
unsigned int handled = 0, have_err = 0;
u32 tmp;
- void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
tmp = readl(mmio);
if (tmp & PDC_ERR_MASK) {
@@ -397,7 +448,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
static void pdc_irq_clear(struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
readl(mmio + PDC_INT_SEQMASK);
}
@@ -409,7 +460,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
u32 mask = 0;
unsigned int i, tmp;
unsigned int handled = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
VPRINTK("ENTER\n");
@@ -441,7 +492,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
VPRINTK("port %u\n", i);
ap = host_set->ports[i];
tmp = mask & (1 << (i + 1));
- if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (tmp && ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -530,7 +582,7 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
{
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
u32 tmp;
/*
@@ -573,7 +625,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc;
@@ -612,8 +664,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 3),
- pci_resource_len(pdev, 3));
+ mmio_base = pci_iomap(pdev, 3, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
diff --git a/drivers/scsi/sata_promise.h b/drivers/scsi/sata_promise.h
index 6e7e96b9ee13..6ee5e190262d 100644
--- a/drivers/scsi/sata_promise.h
+++ b/drivers/scsi/sata_promise.h
@@ -3,21 +3,24 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
*
*/
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 1383e8a28d72..ffcdeb68641c 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -6,21 +6,24 @@
* Copyright 2005 Pacific Digital Corporation.
* (OSL/GPL code release authorized by Jalil Fadavi).
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
*
*/
@@ -117,7 +120,7 @@ static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc);
static int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-static void qs_bmdma_stop(struct ata_port *ap);
+static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap);
static void qs_irq_clear(struct ata_port *ap);
static void qs_eng_timeout(struct ata_port *ap);
@@ -198,7 +201,7 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
return 1; /* ATAPI DMA not supported */
}
-static void qs_bmdma_stop(struct ata_port *ap)
+static void qs_bmdma_stop(struct ata_queued_cmd *qc)
{
/* nothing */
}
@@ -386,7 +389,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
sff1, sff0, port_no, sHST, sDST);
handled = 1;
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap && !(ap->flags &
+ (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_pkt)
@@ -417,7 +421,8 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
struct ata_port *ap;
ap = host_set->ports[port_no];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio)
@@ -431,7 +436,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
continue;
DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
ap->id, qc->tf.protocol, status);
-
+
/* complete taskfile transaction */
pp->state = qs_state_idle;
ata_qc_complete(qc, status);
@@ -489,7 +494,7 @@ static int qs_port_start(struct ata_port *ap)
if (rc)
return rc;
qs_enter_reg_mode(ap);
- pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) {
rc = -ENOMEM;
goto err_out;
@@ -533,11 +538,12 @@ static void qs_port_stop(struct ata_port *ap)
static void qs_host_stop(struct ata_host_set *host_set)
{
void __iomem *mmio_base = host_set->mmio_base;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
- ata_host_stop(host_set);
+ pci_iounmap(pdev, mmio_base);
}
static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
@@ -641,8 +647,7 @@ static int qs_ata_init_one(struct pci_dev *pdev,
goto err_out_regions;
}
- mmio_base = ioremap(pci_resource_start(pdev, 4),
- pci_resource_len(pdev, 4));
+ mmio_base = pci_iomap(pdev, 4, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_regions;
@@ -692,7 +697,7 @@ static int qs_ata_init_one(struct pci_dev *pdev,
return 0;
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_regions:
pci_release_regions(pdev);
err_out:
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 49ed557a4b66..ba98a175ee3a 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -5,24 +5,32 @@
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
- * Copyright 2003 Red Hat, Inc.
+ * Copyright 2003-2005 Red Hat, Inc.
* Copyright 2003 Benjamin Herrenschmidt
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Documentation for SiI 3112:
+ * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ * Other errata and documentation available under NDA.
*
*/
@@ -41,8 +49,11 @@
#define DRV_VERSION "0.9"
enum {
+ SIL_FLAG_MOD15WRITE = (1 << 30),
+
sil_3112 = 0,
- sil_3114 = 1,
+ sil_3112_m15w = 1,
+ sil_3114 = 2,
SIL_FIFO_R0 = 0x40,
SIL_FIFO_W0 = 0x41,
@@ -75,14 +86,15 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void sil_post_set_mode (struct ata_port *ap);
+
static struct pci_device_id sil_pci_tbl[] = {
- { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
- { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ } /* terminate list */
};
@@ -161,7 +173,7 @@ static struct ata_port_operations sil_ops = {
.scr_write = sil_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static struct ata_port_info sil_port_info[] = {
@@ -174,6 +186,16 @@ static struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
+ }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+ {
+ .sht = &sil_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_MOD15WRITE,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil_ops,
}, /* sil_3114 */
{
.sht = &sil_sht,
@@ -210,6 +232,7 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
u8 cache_line = 0;
@@ -221,7 +244,8 @@ static void sil_post_set_mode (struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
struct ata_device *dev;
- void *addr = host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+ void __iomem *addr =
+ host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
u32 tmp, dev_mode[2];
unsigned int i;
@@ -323,15 +347,15 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
while ((len > 0) && (s[len - 1] == ' '))
len--;
- for (n = 0; sil_blacklist[n].product; n++)
+ for (n = 0; sil_blacklist[n].product; n++)
if (!memcmp(sil_blacklist[n].product, s,
strlen(sil_blacklist[n].product))) {
quirks = sil_blacklist[n].quirk;
break;
}
-
+
/* limit requests to 15 sectors */
- if (quirks & SIL_QUIRK_MOD15WRITE) {
+ if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
ap->id, dev->devno);
ap->host->max_sectors = 15;
@@ -354,7 +378,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
int rc;
unsigned int i;
int pci_dev_busy = 0;
@@ -404,8 +428,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
- mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ mmio_base = pci_iomap(pdev, 5, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index e418b89c6b9d..a63f93186e41 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -7,21 +7,26 @@
*
* Copyright 2004 Uwe Koziolek
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -47,7 +52,10 @@ enum {
/* PCI configuration registers */
SIS_GENCTL = 0x54, /* IDE General Control register */
SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */
- SIS_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
+ SIS180_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
+ SIS182_SATA1_OFS = 0x20, /* offset from sata0->sata1 phy regs */
+ SIS_PMR = 0x90, /* port mapping register */
+ SIS_PMR_COMBINED = 0x30,
/* random bits */
SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */
@@ -62,6 +70,7 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static struct pci_device_id sis_pci_tbl[] = {
{ PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
{ PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+ { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
{ } /* terminate list */
};
@@ -134,67 +143,95 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg)
+static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
{
unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
- if (port_no)
- addr += SIS_SATA1_OFS;
+ if (port_no) {
+ if (device == 0x182)
+ addr += SIS182_SATA1_OFS;
+ else
+ addr += SIS180_SATA1_OFS;
+ }
+
return addr;
}
static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg);
- u32 val;
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
+ u32 val, val2;
+ u8 pmr;
if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
return 0xffffffff;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
pci_read_config_dword(pdev, cfg_addr, &val);
- return val;
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
+
+ return val|val2;
}
static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr);
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
+ u8 pmr;
if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
return;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
pci_write_config_dword(pdev, cfg_addr, val);
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ pci_write_config_dword(pdev, cfg_addr+0x10, val);
}
static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+ u32 val, val2 = 0;
+ u8 pmr;
+
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
if (ap->flags & SIS_FLAG_CFGSCR)
return sis_scr_cfg_read(ap, sc_reg);
- return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+ val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
+
+ return val | val2;
}
static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
{
+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+ u8 pmr;
+
if (sc_reg > SCR_CONTROL)
return;
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
if (ap->flags & SIS_FLAG_CFGSCR)
sis_scr_cfg_write(ap, sc_reg, val);
- else
+ else {
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
}
}
@@ -205,6 +242,8 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
u32 genctl;
struct ata_port_info *ppi;
int pci_dev_busy = 0;
+ u8 pmr;
+ u8 port2_start;
rc = pci_enable_device(pdev);
if (rc)
@@ -234,7 +273,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-
+
/* if hardware thinks SCRs are in IO space, but there are
* no IO resources assigned, change to PCI cfg space.
*/
@@ -246,15 +285,31 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
}
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ if (ent->device != 0x182) {
+ if ((pmr & SIS_PMR_COMBINED) == 0) {
+ printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
+ port2_start=0x64;
+ }
+ else {
+ printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n");
+ port2_start=0;
+ }
+ }
+ else {
+ printk(KERN_INFO "sata_sis: Detected SiS 182 chipset\n");
+ port2_start = 0x20;
+ }
+
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
probe_ent->port[0].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR);
probe_ent->port[1].scr_addr =
- pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
+ pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
}
pci_set_master(pdev);
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 858e07185dbd..d89d968bedac 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -13,21 +13,26 @@
* This driver probably works with non-Apple versions of the
* Broadcom chipset...
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -195,18 +200,18 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
/* start host DMA transaction */
dmactl = readb(mmio + ATA_DMA_CMD);
writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
- /* There is a race condition in certain SATA controllers that can
- be seen when the r/w command is given to the controller before the
+ /* There is a race condition in certain SATA controllers that can
+ be seen when the r/w command is given to the controller before the
host DMA is started. On a Read command, the controller would initiate
the command to the drive even before it sees the DMA start. When there
- are very fast drives connected to the controller, or when the data request
+ are very fast drives connected to the controller, or when the data request
hits in the drive cache, there is the possibility that the drive returns a part
or all of the requested data to the controller before the DMA start is issued.
In this case, the controller would become confused as to what to do with the data.
In the worst case when all the data is returned back to the controller, the
controller could hang. In other cases it could return partial data returning
in data corruption. This problem has been seen in PPC systems and can also appear
- on an system with very fast disks, where the SATA controller is sitting behind a
+ on an system with very fast disks, where the SATA controller is sitting behind a
number of bridges, and hence there is significant latency between the r/w command
and the start command. */
/* issue r/w command if the access is to ATA*/
@@ -214,7 +219,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
ap->ops->exec_command(ap, &qc->tf);
}
-
+
static u8 k2_stat_check_status(struct ata_port *ap)
{
return readl((void *) ap->ioaddr.status_addr);
@@ -313,7 +318,7 @@ static struct ata_port_operations k2_sata_ops = {
.scr_write = k2_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -341,7 +346,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
int pci_dev_busy = 0;
int rc;
int i;
@@ -387,8 +392,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ mmio_base = pci_iomap(pdev, 5, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index efd7d7a61135..540a85191172 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -7,21 +7,26 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -94,7 +99,7 @@ enum {
PDC_DIMM1_CONTROL_OFFSET = 0x84,
PDC_SDRAM_CONTROL_OFFSET = 0x88,
PDC_I2C_WRITE = 0x00000000,
- PDC_I2C_READ = 0x00000040,
+ PDC_I2C_READ = 0x00000040,
PDC_I2C_START = 0x00000080,
PDC_I2C_MASK_INT = 0x00000020,
PDC_I2C_COMPLETE = 0x00010000,
@@ -105,16 +110,16 @@ enum {
PDC_DIMM_SPD_COLUMN_NUM = 4,
PDC_DIMM_SPD_MODULE_ROW = 5,
PDC_DIMM_SPD_TYPE = 11,
- PDC_DIMM_SPD_FRESH_RATE = 12,
- PDC_DIMM_SPD_BANK_NUM = 17,
+ PDC_DIMM_SPD_FRESH_RATE = 12,
+ PDC_DIMM_SPD_BANK_NUM = 17,
PDC_DIMM_SPD_CAS_LATENCY = 18,
- PDC_DIMM_SPD_ATTRIBUTE = 21,
+ PDC_DIMM_SPD_ATTRIBUTE = 21,
PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
- PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
+ PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
PDC_DIMM_SPD_SYSTEM_FREQ = 126,
- PDC_CTL_STATUS = 0x08,
+ PDC_CTL_STATUS = 0x08,
PDC_DIMM_WINDOW_CTLR = 0x0C,
PDC_TIME_CONTROL = 0x3C,
PDC_TIME_PERIOD = 0x40,
@@ -157,15 +162,15 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set);
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
u32 device, u32 subaddr, u32 *pdata);
static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
static void pdc20621_irq_clear(struct ata_port *ap);
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -240,13 +245,14 @@ static struct pci_driver pdc_sata_pci_driver = {
static void pdc20621_host_stop(struct ata_host_set *host_set)
{
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
struct pdc_host_priv *hpriv = host_set->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
- iounmap(dimm_mmio);
+ pci_iounmap(pdev, dimm_mmio);
kfree(hpriv);
- ata_host_stop(host_set);
+ pci_iounmap(pdev, host_set->mmio_base);
}
static int pdc_port_start(struct ata_port *ap)
@@ -446,9 +452,9 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
struct scatterlist *sg = qc->sg;
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host_set->mmio_base;
struct pdc_host_priv *hpriv = ap->host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
unsigned int portno = ap->port_no;
unsigned int i, last, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
@@ -508,9 +514,9 @@ static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host_set->mmio_base;
struct pdc_host_priv *hpriv = ap->host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
unsigned int portno = ap->port_no;
unsigned int i;
@@ -560,7 +566,7 @@ static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
{
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -634,7 +640,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 seq = (u8) (port_no + 1);
unsigned int port_ofs;
@@ -694,7 +700,7 @@ static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
struct ata_queued_cmd *qc,
unsigned int doing_hdma,
- void *mmio)
+ void __iomem *mmio)
{
unsigned int port_no = ap->port_no;
unsigned int port_ofs =
@@ -773,7 +779,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
static void pdc20621_irq_clear(struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
mmio += PDC_CHIP0_OFS;
@@ -787,7 +793,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
u32 mask = 0;
unsigned int i, tmp, port_no;
unsigned int handled = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
VPRINTK("ENTER\n");
@@ -825,7 +831,8 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
ap = host_set->ports[port_no];
tmp = mask & (1 << i);
VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
- if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (tmp && ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -847,10 +854,14 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
static void pdc_eng_timeout(struct ata_port *ap)
{
u8 drv_stat;
+ struct ata_host_set *host_set = ap->host_set;
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -884,6 +895,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
}
out:
+ spin_unlock_irqrestore(&host_set->lock, flags);
DPRINTK("EXIT\n");
}
@@ -922,23 +934,23 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
- page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
- idx = (u16) (offset / window_size);
+ page_mask = 0x00;
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
+ idx = (u16) (offset / window_size);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
@@ -947,19 +959,19 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
offset -= (idx * window_size);
idx++;
- dist = ((long) (window_size - (offset + size))) >= 0 ? size :
+ dist = ((long) (window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
dist);
- psource += dist;
+ psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio),
window_size / 4);
psource += window_size;
size -= window_size;
@@ -971,34 +983,34 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio),
size / 4);
}
}
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
- /* hard-code chip #0 */
+ /* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
- page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
+ page_mask = 0x00;
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- offset -= (idx * window_size);
+ offset -= (idx * window_size);
idx++;
dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
@@ -1006,12 +1018,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
- psource += dist;
+ psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_toio((char *) (dimm_mmio), (char *) psource,
+ memcpy_toio((char *) (dimm_mmio), (char *) psource,
window_size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
@@ -1019,7 +1031,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
size -= window_size;
idx ++;
}
-
+
if (size) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
@@ -1030,12 +1042,12 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
}
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
u32 subaddr, u32 *pdata)
{
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
u32 i2creg = 0;
- u32 status;
+ u32 status;
u32 count =0;
/* hard-code chip #0 */
@@ -1049,7 +1061,7 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
/* Write Control to perform read operation, mask int */
- writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
+ writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
mmio + PDC_I2C_CONTROL_OFFSET);
for (count = 0; count <= 1000; count ++) {
@@ -1062,26 +1074,26 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
}
*pdata = (status >> 8) & 0x000000ff;
- return 1;
+ return 1;
}
static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
{
u32 data=0 ;
- if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
if (data == 100)
return 100;
} else
return 0;
-
+
if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
- if(data <= 0x75)
+ if(data <= 0x75)
return 133;
} else
return 0;
-
+
return 0;
}
@@ -1091,15 +1103,15 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
u32 spd0[50];
u32 data = 0;
int size, i;
- u8 bdimmsize;
- void *mmio = pe->mmio_base;
+ u8 bdimmsize;
+ void __iomem *mmio = pe->mmio_base;
static const struct {
unsigned int reg;
unsigned int ofs;
} pdc_i2c_read_data [] = {
- { PDC_DIMM_SPD_TYPE, 11 },
+ { PDC_DIMM_SPD_TYPE, 11 },
{ PDC_DIMM_SPD_FRESH_RATE, 12 },
- { PDC_DIMM_SPD_COLUMN_NUM, 4 },
+ { PDC_DIMM_SPD_COLUMN_NUM, 4 },
{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
{ PDC_DIMM_SPD_ROW_NUM, 3 },
{ PDC_DIMM_SPD_BANK_NUM, 17 },
@@ -1108,7 +1120,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
- { PDC_DIMM_SPD_CAS_LATENCY, 18 },
+ { PDC_DIMM_SPD_CAS_LATENCY, 18 },
};
/* hard-code chip #0 */
@@ -1116,17 +1128,17 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
- pdc_i2c_read_data[i].reg,
+ pdc_i2c_read_data[i].reg,
&spd0[pdc_i2c_read_data[i].ofs]);
-
+
data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
- data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
+ data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
((((spd0[27] + 9) / 10) - 1) << 8) ;
- data |= (((((spd0[29] > spd0[28])
- ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
+ data |= (((((spd0[29] > spd0[28])
+ ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
-
- if (spd0[18] & 0x08)
+
+ if (spd0[18] & 0x08)
data |= ((0x03) << 14);
else if (spd0[18] & 0x04)
data |= ((0x02) << 14);
@@ -1135,7 +1147,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
else
data |= (0 << 14);
- /*
+ /*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
@@ -1145,9 +1157,9 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
data |= (((size / 16) - 1) << 16);
data |= (0 << 23);
data |= 8;
- writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
+ writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
- return size;
+ return size;
}
@@ -1155,7 +1167,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
{
u32 data, spd0;
int error, i;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1167,12 +1179,12 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
Refresh Enable (bit 17)
*/
- data = 0x022259F1;
+ data = 0x022259F1;
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
/* Turn on for ECC */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
@@ -1186,22 +1198,22 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
data |= (1<<19);
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- error = 1;
+ error = 1;
for (i = 1; i <= 10; i++) { /* polling ~5 secs */
data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
if (!(data & (1<<19))) {
error = 0;
- break;
+ break;
}
msleep(i*100);
}
return error;
}
-
+
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
{
- int speed, size, length;
+ int speed, size, length;
u32 addr,spd0,pci_status;
u32 tmp=0;
u32 time_period=0;
@@ -1209,7 +1221,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
u32 ticks=0;
u32 clock=0;
u32 fparam=0;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1228,7 +1240,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
/* Wait 3 seconds */
msleep(3000);
- /*
+ /*
When timer is enabled, counter is decreased every internal
clock cycle.
*/
@@ -1236,24 +1248,24 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
tcount = readl(mmio + PDC_TIME_COUNTER);
VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
- /*
+ /*
If SX4 is on PCI-X bus, after 3 seconds, the timer counter
register should be >= (0xffffffff - 3x10^8).
*/
if(tcount >= PCI_X_TCOUNT) {
ticks = (time_period - tcount);
VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
-
+
clock = (ticks / 300000);
VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
-
+
clock = (clock * 33);
VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
/* PLL F Param (bit 22:16) */
fparam = (1400000 / clock) - 2;
VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
-
+
/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
pci_status = (0x8a001824 | (fparam << 16));
} else
@@ -1264,21 +1276,21 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
writel(pci_status, mmio + PDC_CTL_STATUS);
readl(mmio + PDC_CTL_STATUS);
- /*
+ /*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if (!(speed = pdc20621_detect_dimm(pe))) {
- printk(KERN_ERR "Detect Local DIMM Fail\n");
+ printk(KERN_ERR "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
}
VPRINTK("Local DIMM Speed = %d\n", speed);
- /* Programming DIMM0 Module Control Register (index_CID0:80h) */
+ /* Programming DIMM0 Module Control Register (index_CID0:80h) */
size = pdc20621_prog_dimm0(pe);
VPRINTK("Local DIMM Size = %dMB\n",size);
- /* Programming DIMM Module Global Control Register (index_CID0:88h) */
+ /* Programming DIMM Module Global Control Register (index_CID0:88h) */
if (pdc20621_prog_dimm_global(pe)) {
printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
return 1;
@@ -1297,30 +1309,30 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
+ pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
#endif
/* ECC initiliazation. */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
VPRINTK("Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
while (addr < length) {
- pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
+ pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
sizeof(u32));
addr += sizeof(u32);
}
@@ -1333,7 +1345,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
static void pdc_20621_init(struct ata_probe_ent *pe)
{
u32 tmp;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1366,7 +1378,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base, *dimm_mmio = NULL;
+ void __iomem *mmio_base;
+ void __iomem *dimm_mmio = NULL;
struct pdc_host_priv *hpriv = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
@@ -1406,8 +1419,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 3),
- pci_resource_len(pdev, 3));
+ mmio_base = pci_iomap(pdev, 3, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -1421,8 +1433,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
}
memset(hpriv, 0, sizeof(*hpriv));
- dimm_mmio = ioremap(pci_resource_start(pdev, 4),
- pci_resource_len(pdev, 4));
+ dimm_mmio = pci_iomap(pdev, 4, 0);
if (!dimm_mmio) {
kfree(hpriv);
rc = -ENOMEM;
@@ -1469,9 +1480,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
err_out_iounmap_dimm: /* only get to this label if 20621 */
kfree(hpriv);
- iounmap(dimm_mmio);
+ pci_iounmap(pdev, dimm_mmio);
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_free_ent:
kfree(probe_ent);
err_out_regions:
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index a71fb54eebd3..4c9fb8b71be1 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -1,21 +1,26 @@
/*
* sata_uli.c - ULi Electronics SATA
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, in which case the provisions of
- * the GPL are applicable instead of the above. If you wish to allow
- * the use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under
- * the OSL, indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by the GPL.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under either the OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -120,8 +125,8 @@ static struct ata_port_info uli_port_info = {
.sht = &uli_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x03, //support pio mode 4 (FIXME)
- .udma_mask = 0x7f, //support udma mode 6
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &uli_ops,
};
@@ -171,18 +176,6 @@ static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
uli_scr_cfg_write(ap, sc_reg, val);
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
-}
-
static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct ata_probe_ent *probe_ent;
@@ -214,7 +207,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = -ENOMEM;
goto err_out_regions;
}
-
+
switch (board_idx) {
case uli_5287:
probe_ent->port[0].scr_addr = ULI5287_BASE;
@@ -255,7 +248,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
}
pci_set_master(pdev);
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index f43183c19a12..128b996b07b7 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -1,34 +1,38 @@
/*
- sata_via.c - VIA Serial ATA controllers
-
- Maintained by: Jeff Garzik <jgarzik@pobox.com>
- Please ALWAYS copy linux-ide@vger.kernel.org
+ * sata_via.c - VIA Serial ATA controllers
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
on emails.
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
- ----------------------------------------------------------------------
-
- To-do list:
- * VT6421 PATA support
-
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
+ *
+ *
+ * To-do list:
+ * - VT6421 PATA support
+ *
*/
#include <linux/kernel.h>
@@ -347,7 +351,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent = vt6420_init_probe_ent(pdev);
else
probe_ent = vt6421_init_probe_ent(pdev);
-
+
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index c5e09dc6f3de..cf94e0158a8d 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -9,9 +9,29 @@
*
* Bits from Jeff Garzik, Copyright RedHat, Inc.
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Vitesse hardware documentation presumably available under NDA.
+ * Intel 31244 (same hardware interface) documentation presumably
+ * available from http://developer.intel.com/
+ *
*/
#include <linux/kernel.h>
@@ -173,7 +193,8 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap && !(ap->flags &
+ (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -231,7 +252,7 @@ static struct ata_port_operations vsc_sata_ops = {
.scr_write = vsc_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -305,8 +326,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ mmio_base = pci_iomap(pdev, 0, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -342,7 +362,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
pci_set_master(pdev);
- /*
+ /*
* Config offset 0x98 is "Extended Control and Status Register 0"
* Default value is (1 << 28). All bits except bit 28 are reserved in
* DPA mode. If bit 28 is set, LED 0 reflects all ports' activity.
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d14523d7e449..a780546eda9c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
} else
put_device(&dev->sdev_gendev);
+ cmd->jiffies_at_alloc = jiffies;
return cmd;
}
EXPORT_SYMBOL(scsi_get_command);
@@ -627,7 +628,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
spin_lock_irqsave(host->host_lock, flags);
scsi_cmd_get_serial(host, cmd);
- if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
+ if (unlikely(host->shost_state == SHOST_DEL)) {
cmd->result = (DID_NO_CONNECT << 16);
scsi_done(cmd);
} else {
@@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_action *h)
while (!list_empty(&local_q)) {
struct scsi_cmnd *cmd = list_entry(local_q.next,
struct scsi_cmnd, eh_entry);
+ /* The longest time any command should be outstanding is the
+ * per command timeout multiplied by the number of retries.
+ *
+ * For a typical command, this is 2.5 minutes */
+ unsigned long wait_for
+ = cmd->allowed * cmd->timeout_per_command;
list_del_init(&cmd->eh_entry);
disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ dev_printk(KERN_ERR, &cmd->device->sdev_gendev,
+ "timing out command, waited %lus\n",
+ wait_for/HZ);
+ disposition = SUCCESS;
+ }
+
scsi_log_completion(cmd, disposition);
switch (disposition) {
case SUCCESS:
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 6121dc1bfada..07b554affcf2 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -114,6 +114,7 @@ static struct {
{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */
+ {"", "Scanner", "1.80", BLIST_NOLUN}, /* responds to all lun */
/*
* Other types of devices that have special flags.
@@ -135,7 +136,7 @@ static struct {
{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
- {"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
+ {"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
{"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN},
{"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */
@@ -191,6 +192,7 @@ static struct {
{"SGI", "RAID5", "*", BLIST_SPARSELUN},
{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
{"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+ {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
{"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 0fc8b48f052b..895c9452be4c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -75,7 +76,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
- set_bit(SHOST_RECOVERY, &shost->shost_state);
+ scsi_host_set_state(shost, SHOST_RECOVERY);
shost->host_failed++;
scsi_eh_wakeup(shost);
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -115,7 +116,6 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
add_timer(&scmd->eh_timeout);
}
-EXPORT_SYMBOL(scsi_add_timer);
/**
* scsi_delete_timer - Delete/cancel timer for a given function.
@@ -143,7 +143,6 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
return rtn;
}
-EXPORT_SYMBOL(scsi_delete_timer);
/**
* scsi_times_out - Timeout function for normal scsi commands.
@@ -197,7 +196,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
{
int online;
- wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state)));
+ wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
+ SHOST_RECOVERY));
online = scsi_device_online(sdev);
@@ -775,9 +775,11 @@ retry_tur:
__FUNCTION__, scmd, rtn));
if (rtn == SUCCESS)
return 0;
- else if (rtn == NEEDS_RETRY)
+ else if (rtn == NEEDS_RETRY) {
if (retry_cnt--)
goto retry_tur;
+ return 0;
+ }
return 1;
}
@@ -1458,7 +1460,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
__FUNCTION__));
- clear_bit(SHOST_RECOVERY, &shost->shost_state);
+ scsi_host_set_state(shost, SHOST_RUNNING);
wake_up(&shost->host_wait);
@@ -1582,16 +1584,8 @@ int scsi_error_handler(void *data)
int rtn;
DECLARE_MUTEX_LOCKED(sem);
- /*
- * Flush resources
- */
-
- daemonize("scsi_eh_%d", shost->host_no);
-
current->flags |= PF_NOFREEZE;
-
shost->eh_wait = &sem;
- shost->ehandler = current;
/*
* Wake up the thread that created us.
@@ -1599,8 +1593,6 @@ int scsi_error_handler(void *data)
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
" scsi_eh_%d\n",shost->host_no));
- complete(shost->eh_notify);
-
while (1) {
/*
* If we get a signal, it means we are supposed to go
@@ -1621,7 +1613,7 @@ int scsi_error_handler(void *data)
* semaphores isn't unreasonable.
*/
down_interruptible(&sem);
- if (shost->eh_kill)
+ if (kthread_should_stop())
break;
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
@@ -1660,22 +1652,6 @@ int scsi_error_handler(void *data)
* Make sure that nobody tries to wake us up again.
*/
shost->eh_wait = NULL;
-
- /*
- * Knock this down too. From this point on, the host is flying
- * without a pilot. If this is because the module is being unloaded,
- * that's fine. If the user sent a signal to this thing, we are
- * potentially in real danger.
- */
- shost->eh_active = 0;
- shost->ehandler = NULL;
-
- /*
- * If anyone is waiting for us to exit (i.e. someone trying to unload
- * a driver), then wake up that process to let them know we are on
- * the way out the door.
- */
- complete_and_exit(shost->eh_notify, 0);
return 0;
}
@@ -1846,12 +1822,16 @@ EXPORT_SYMBOL(scsi_reset_provider);
int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
struct scsi_sense_hdr *sshdr)
{
- if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70)
+ if (!sense_buffer || !sb_len)
return 0;
memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
sshdr->response_code = (sense_buffer[0] & 0x7f);
+
+ if (!scsi_sense_valid(sshdr))
+ return 0;
+
if (sshdr->response_code >= 0x72) {
/*
* descriptor format
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 7a6b530115ac..b7fddac81347 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -30,20 +30,20 @@
#define MAX_BUF PAGE_SIZE
-/*
- * If we are told to probe a host, we will return 0 if the host is not
- * present, 1 if the host is present, and will return an identifying
- * string at *arg, if arg is non null, filling to the length stored at
- * (int *) arg
+/**
+ * ioctl_probe -- return host identification
+ * @host: host to identify
+ * @buffer: userspace buffer for identification
+ *
+ * Return an identifying string at @buffer, if @buffer is non-NULL, filling
+ * to the length stored at * (int *) @buffer.
*/
-
static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
{
unsigned int len, slen;
const char *string;
- int temp = host->hostt->present;
- if (temp && buffer) {
+ if (buffer) {
if (get_user(len, (unsigned int __user *) buffer))
return -EFAULT;
@@ -59,7 +59,7 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
return -EFAULT;
}
}
- return temp;
+ return 1;
}
/*
@@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
int timeout, int retries)
{
- struct scsi_request *sreq;
int result;
struct scsi_sense_hdr sshdr;
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n");
- return -ENOMEM;
- }
-
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0,
+ &sshdr, timeout, retries);
- SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result));
+ SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result));
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
- (scsi_request_normalize_sense(sreq, &sshdr))) {
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ (scsi_sense_valid(&sshdr))) {
switch (sshdr.sense_key) {
case ILLEGAL_REQUEST:
if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
@@ -125,7 +118,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
case UNIT_ATTENTION:
if (sdev->removable) {
sdev->changed = 1;
- sreq->sr_result = 0; /* This is no longer considered an error */
+ result = 0; /* This is no longer considered an error */
break;
}
default: /* Fall through for non-removable media */
@@ -135,15 +128,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
sdev->channel,
sdev->id,
sdev->lun,
- sreq->sr_result);
- scsi_print_req_sense(" ", sreq);
+ result);
+ scsi_print_sense_hdr(" ", &sshdr);
break;
}
}
- result = sreq->sr_result;
SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n"));
- scsi_release_request(sreq);
return result;
}
@@ -208,8 +199,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
{
char *buf;
unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
char __user *cmd_in;
- struct scsi_request *sreq;
unsigned char opcode;
unsigned int inlen, outlen, cmdlen;
unsigned int needed, buf_needed;
@@ -321,31 +312,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
break;
}
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- result = -EINTR;
- goto error;
- }
-
- sreq->sr_data_direction = data_direction;
- scsi_wait_req(sreq, cmd, buf, needed, timeout, retries);
+ 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.
*/
- result = sreq->sr_result;
if (result) {
- int sb_len = sizeof(sreq->sr_sense_buffer);
+ int sb_len = sizeof(*sense);
sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
- if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len))
+ if (copy_to_user(cmd_in, sense, sb_len))
result = -EFAULT;
} else {
if (copy_to_user(cmd_in, buf, outlen))
result = -EFAULT;
}
- scsi_release_request(sreq);
error:
kfree(buf);
return result;
@@ -475,8 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
* error processing, as long as the device was opened
* non-blocking */
if (filp && filp->f_flags & O_NONBLOCK) {
- if (test_bit(SHOST_RECOVERY,
- &sdev->host->shost_state))
+ if (sdev->host->shost_state == SHOST_RECOVERY)
return -ENODEV;
} else if (!scsi_block_when_processing_errors(sdev))
return -ENODEV;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7a91ca3d32a6..863bb6495daa 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -97,6 +97,30 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
}
static void scsi_run_queue(struct request_queue *q);
+static void scsi_release_buffers(struct scsi_cmnd *cmd);
+
+/*
+ * Function: scsi_unprep_request()
+ *
+ * Purpose: Remove all preparation done for a request, including its
+ * associated scsi_cmnd, so that it can be requeued.
+ *
+ * Arguments: req - request to unprepare
+ *
+ * Lock status: Assumed that no locks are held upon entry.
+ *
+ * Returns: Nothing.
+ */
+static void scsi_unprep_request(struct request *req)
+{
+ struct scsi_cmnd *cmd = req->special;
+
+ req->flags &= ~REQ_DONTPREP;
+ req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+
+ scsi_release_buffers(cmd);
+ scsi_put_command(cmd);
+}
/*
* Function: scsi_queue_insert()
@@ -116,12 +140,14 @@ static void scsi_run_queue(struct request_queue *q);
* commands.
* Notes: This could be called either from an interrupt context or a
* normal process context.
+ * Notes: Upon return, cmd is a stale pointer.
*/
int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
struct request_queue *q = device->request_queue;
+ struct request *req = cmd->request;
unsigned long flags;
SCSI_LOG_MLQUEUE(1,
@@ -162,8 +188,9 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
* function. The SCSI request function detects the blocked condition
* and plugs the queue appropriately.
*/
+ scsi_unprep_request(req);
spin_lock_irqsave(q->queue_lock, flags);
- blk_requeue_request(q, cmd->request);
+ blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
@@ -232,23 +259,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
}
EXPORT_SYMBOL(scsi_do_req);
-static void scsi_wait_done(struct scsi_cmnd *cmd)
-{
- struct request *req = cmd->request;
- struct request_queue *q = cmd->device->request_queue;
- unsigned long flags;
-
- req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
-
- spin_lock_irqsave(q->queue_lock, flags);
- if (blk_rq_tagged(req))
- blk_queue_end_tag(q, req);
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- if (req->waiting)
- complete(req->waiting);
-}
-
/* This is the end routine we get to if a command was never attached
* to the request. Simply complete the request without changing
* rq_status; this will cause a DRIVER_ERROR. */
@@ -263,21 +273,114 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
unsigned bufflen, int timeout, int retries)
{
DECLARE_COMPLETION(wait);
-
- sreq->sr_request->waiting = &wait;
- sreq->sr_request->rq_status = RQ_SCSI_BUSY;
- sreq->sr_request->end_io = scsi_wait_req_end_io;
- scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
- timeout, retries);
+ int write = (sreq->sr_data_direction == DMA_TO_DEVICE);
+ struct request *req;
+
+ req = blk_get_request(sreq->sr_device->request_queue, write,
+ __GFP_WAIT);
+ if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req,
+ buffer, bufflen, __GFP_WAIT)) {
+ sreq->sr_result = DRIVER_ERROR << 24;
+ blk_put_request(req);
+ return;
+ }
+
+ req->flags |= REQ_NOMERGE;
+ req->waiting = &wait;
+ req->end_io = scsi_wait_req_end_io;
+ req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]);
+ req->sense = sreq->sr_sense_buffer;
+ req->sense_len = 0;
+ memcpy(req->cmd, cmnd, req->cmd_len);
+ req->timeout = timeout;
+ req->flags |= REQ_BLOCK_PC;
+ req->rq_disk = NULL;
+ blk_insert_request(sreq->sr_device->request_queue, req,
+ sreq->sr_data_direction == DMA_TO_DEVICE, NULL);
wait_for_completion(&wait);
sreq->sr_request->waiting = NULL;
- if (sreq->sr_request->rq_status != RQ_SCSI_DONE)
+ sreq->sr_result = req->errors;
+ if (req->errors)
sreq->sr_result |= (DRIVER_ERROR << 24);
- __scsi_release_request(sreq);
+ blk_put_request(req);
}
+
EXPORT_SYMBOL(scsi_wait_req);
+/**
+ * scsi_execute - insert request and wait for the result
+ * @sdev: scsi device
+ * @cmd: scsi command
+ * @data_direction: data direction
+ * @buffer: data buffer
+ * @bufflen: len of buffer
+ * @sense: optional sense buffer
+ * @timeout: request timeout in seconds
+ * @retries: number of times to retry request
+ * @flags: or into request flags;
+ *
+ * returns the req->errors value which is the the scsi_cmnd result
+ * field.
+ **/
+int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ unsigned char *sense, int timeout, int retries, int flags)
+{
+ struct request *req;
+ int write = (data_direction == DMA_TO_DEVICE);
+ int ret = DRIVER_ERROR << 24;
+
+ req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+
+ if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
+ buffer, bufflen, __GFP_WAIT))
+ goto out;
+
+ req->cmd_len = COMMAND_SIZE(cmd[0]);
+ memcpy(req->cmd, cmd, req->cmd_len);
+ req->sense = sense;
+ req->sense_len = 0;
+ req->timeout = timeout;
+ req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+
+ /*
+ * head injection *required* here otherwise quiesce won't work
+ */
+ blk_execute_rq(req->q, NULL, req, 1);
+
+ ret = req->errors;
+ out:
+ blk_put_request(req);
+
+ return ret;
+}
+EXPORT_SYMBOL(scsi_execute);
+
+
+int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ struct scsi_sense_hdr *sshdr, int timeout, int retries)
+{
+ char *sense = NULL;
+ int result;
+
+ if (sshdr) {
+ sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+ if (!sense)
+ return DRIVER_ERROR << 24;
+ memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
+ }
+ result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
+ sense, timeout, retries, 0);
+ if (sshdr)
+ scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
+
+ kfree(sense);
+ return result;
+}
+EXPORT_SYMBOL(scsi_execute_req);
+
/*
* Function: scsi_init_cmd_errh()
*
@@ -348,7 +451,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
- if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) &&
+ if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
shost->host_failed))
scsi_eh_wakeup(shost);
spin_unlock(shost->host_lock);
@@ -476,15 +579,16 @@ static void scsi_run_queue(struct request_queue *q)
* I/O errors in the middle of the request, in which case
* we need to request the blocks that come after the bad
* sector.
+ * Notes: Upon return, cmd is a stale pointer.
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
+ struct request *req = cmd->request;
unsigned long flags;
- cmd->request->flags &= ~REQ_DONTPREP;
-
+ scsi_unprep_request(req);
spin_lock_irqsave(q->queue_lock, flags);
- blk_requeue_request(q, cmd->request);
+ blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
@@ -519,13 +623,14 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
*
* Lock status: Assumed that lock is not held upon entry.
*
- * Returns: cmd if requeue done or required, NULL otherwise
+ * Returns: cmd if requeue required, NULL otherwise.
*
* Notes: This is called for block device requests in order to
* mark some number of sectors as complete.
*
* We are guaranteeing that the request queue will be goosed
* at some point during this call.
+ * Notes: If cmd was requeued, upon return it will be a stale pointer.
*/
static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
int bytes, int requeue)
@@ -548,14 +653,15 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
if (!uptodate && blk_noretry_request(req))
end_that_request_chunk(req, 0, leftover);
else {
- if (requeue)
+ if (requeue) {
/*
* Bleah. Leftovers again. Stick the
* leftovers in the front of the
* queue, and goose the queue again.
*/
scsi_requeue_command(q, cmd);
-
+ cmd = NULL;
+ }
return cmd;
}
}
@@ -781,15 +887,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
* requeueing right here - we will requeue down below
* when we handle the bad sectors.
*/
- cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);
/*
- * If the command completed without error, then either finish off the
- * rest of the command, or start a new one.
+ * If the command completed without error, then either
+ * finish off the rest of the command, or start a new one.
*/
- if (result == 0 || cmd == NULL ) {
+ if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)
return;
- }
}
/*
* Now, if we were good little boys and girls, Santa left us a request
@@ -804,7 +908,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
* and quietly refuse further access.
*/
cmd->device->changed = 1;
- cmd = scsi_end_request(cmd, 0,
+ scsi_end_request(cmd, 0,
this_count, 1);
return;
} else {
@@ -838,7 +942,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
scsi_requeue_command(q, cmd);
result = 0;
} else {
- cmd = scsi_end_request(cmd, 0, this_count, 1);
+ scsi_end_request(cmd, 0, this_count, 1);
return;
}
break;
@@ -851,18 +955,21 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
scsi_requeue_command(q, cmd);
return;
}
- printk(KERN_INFO "Device %s not ready.\n",
- req->rq_disk ? req->rq_disk->disk_name : "");
- cmd = scsi_end_request(cmd, 0, this_count, 1);
+ if (!(req->flags & REQ_QUIET))
+ dev_printk(KERN_INFO,
+ &cmd->device->sdev_gendev,
+ "Device not ready.\n");
+ scsi_end_request(cmd, 0, this_count, 1);
return;
case VOLUME_OVERFLOW:
- printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ",
- cmd->device->host->host_no,
- (int)cmd->device->channel,
- (int)cmd->device->id, (int)cmd->device->lun);
- __scsi_print_command(cmd->data_cmnd);
- scsi_print_sense("", cmd);
- cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+ if (!(req->flags & REQ_QUIET)) {
+ dev_printk(KERN_INFO,
+ &cmd->device->sdev_gendev,
+ "Volume overflow, CDB: ");
+ __scsi_print_command(cmd->data_cmnd);
+ scsi_print_sense("", cmd);
+ }
+ scsi_end_request(cmd, 0, block_bytes, 1);
return;
default:
break;
@@ -878,14 +985,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
return;
}
if (result) {
- printk(KERN_INFO "SCSI error : <%d %d %d %d> return code "
- "= 0x%x\n", cmd->device->host->host_no,
- cmd->device->channel,
- cmd->device->id,
- cmd->device->lun, result);
-
- if (driver_byte(result) & DRIVER_SENSE)
- scsi_print_sense("", cmd);
+ if (!(req->flags & REQ_QUIET)) {
+ dev_printk(KERN_INFO, &cmd->device->sdev_gendev,
+ "SCSI error: return code = 0x%x\n", result);
+
+ if (driver_byte(result) & DRIVER_SENSE)
+ scsi_print_sense("", cmd);
+ }
/*
* Mark a single buffer as not uptodate. Queue the remainder.
* We sometimes get this cruft in the event that a medium error
@@ -894,7 +1000,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
block_bytes = req->hard_cur_sectors << 9;
if (!block_bytes)
block_bytes = req->data_len;
- cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+ scsi_end_request(cmd, 0, block_bytes, 1);
}
}
EXPORT_SYMBOL(scsi_io_completion);
@@ -1020,6 +1126,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
return -EOPNOTSUPP;
}
+static void scsi_generic_done(struct scsi_cmnd *cmd)
+{
+ BUG_ON(!blk_pc_request(cmd->request));
+ scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
+}
+
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
struct scsi_device *sdev = q->queuedata;
@@ -1034,7 +1146,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
if (unlikely(!scsi_device_online(sdev))) {
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
/* OK, we're not in a running state don't prep
@@ -1044,7 +1156,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* at all allowed down */
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
/* OK, we only allow special commands (i.e. not
* user initiated ones */
@@ -1061,7 +1173,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* these two cases differently. We differentiate by looking
* at request->cmd, as this tells us the real story.
*/
- if (req->flags & REQ_SPECIAL) {
+ if (req->flags & REQ_SPECIAL && req->special) {
struct scsi_request *sreq = req->special;
if (sreq->sr_magic == SCSI_REQ_MAGIC) {
@@ -1073,14 +1185,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
cmd = req->special;
} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
- if(unlikely(specials_only)) {
+ if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
if(specials_only == SDEV_QUIESCE ||
specials_only == SDEV_BLOCK)
- return BLKPREP_DEFER;
+ goto defer;
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
@@ -1098,7 +1210,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
cmd->tag = req->tag;
} else {
blk_dump_rq_flags(req, "SCSI bad req");
- return BLKPREP_KILL;
+ goto kill;
}
/* note the overloading of req->special. When the tag
@@ -1136,17 +1248,37 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* required).
*/
ret = scsi_init_io(cmd);
- if (ret) /* BLKPREP_KILL return also releases the command */
- return ret;
+ switch(ret) {
+ case BLKPREP_KILL:
+ /* BLKPREP_KILL return also releases the command */
+ goto kill;
+ case BLKPREP_DEFER:
+ goto defer;
+ }
/*
* Initialize the actual SCSI command for this request.
*/
- drv = *(struct scsi_driver **)req->rq_disk->private_data;
- if (unlikely(!drv->init_command(cmd))) {
- scsi_release_buffers(cmd);
- scsi_put_command(cmd);
- return BLKPREP_KILL;
+ if (req->rq_disk) {
+ drv = *(struct scsi_driver **)req->rq_disk->private_data;
+ if (unlikely(!drv->init_command(cmd))) {
+ scsi_release_buffers(cmd);
+ scsi_put_command(cmd);
+ goto kill;
+ }
+ } else {
+ memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+ if (rq_data_dir(req) == WRITE)
+ cmd->sc_data_direction = DMA_TO_DEVICE;
+ else if (req->data_len)
+ cmd->sc_data_direction = DMA_FROM_DEVICE;
+ else
+ cmd->sc_data_direction = DMA_NONE;
+
+ cmd->transfersize = req->data_len;
+ cmd->allowed = 3;
+ cmd->timeout_per_command = req->timeout;
+ cmd->done = scsi_generic_done;
}
}
@@ -1163,6 +1295,9 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
if (sdev->device_busy == 0)
blk_plug_device(q);
return BLKPREP_DEFER;
+ kill:
+ req->errors = DID_NO_CONNECT << 16;
+ return BLKPREP_KILL;
}
/*
@@ -1207,7 +1342,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
struct Scsi_Host *shost,
struct scsi_device *sdev)
{
- if (test_bit(SHOST_RECOVERY, &shost->shost_state))
+ if (shost->shost_state == SHOST_RECOVERY)
return 0;
if (shost->host_busy == 0 && shost->host_blocked) {
/*
@@ -1237,19 +1372,24 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
}
/*
- * Kill requests for a dead device
+ * Kill a request for a dead device
*/
-static void scsi_kill_requests(request_queue_t *q)
+static void scsi_kill_request(struct request *req, request_queue_t *q)
{
- struct request *req;
+ struct scsi_cmnd *cmd = req->special;
- while ((req = elv_next_request(q)) != NULL) {
- blkdev_dequeue_request(req);
- req->flags |= REQ_QUIET;
- while (end_that_request_first(req, 0, req->nr_sectors))
- ;
- end_that_request_last(req);
+ blkdev_dequeue_request(req);
+
+ if (unlikely(cmd == NULL)) {
+ printk(KERN_CRIT "impossible request in %s.\n",
+ __FUNCTION__);
+ BUG();
}
+
+ scsi_init_cmd_errh(cmd);
+ cmd->result = DID_NO_CONNECT << 16;
+ atomic_inc(&cmd->device->iorequest_cnt);
+ __scsi_done(cmd);
}
/*
@@ -1272,7 +1412,8 @@ static void scsi_request_fn(struct request_queue *q)
if (!sdev) {
printk("scsi: killing requests for dead queue\n");
- scsi_kill_requests(q);
+ while ((req = elv_next_request(q)) != NULL)
+ scsi_kill_request(req, q);
return;
}
@@ -1299,11 +1440,7 @@ static void scsi_request_fn(struct request_queue *q)
if (unlikely(!scsi_device_online(sdev))) {
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- blkdev_dequeue_request(req);
- req->flags |= REQ_QUIET;
- while (end_that_request_first(req, 0, req->nr_sectors))
- ;
- end_that_request_last(req);
+ scsi_kill_request(req, q);
continue;
}
@@ -1316,6 +1453,14 @@ static void scsi_request_fn(struct request_queue *q)
sdev->device_busy++;
spin_unlock(q->queue_lock);
+ cmd = req->special;
+ if (unlikely(cmd == NULL)) {
+ printk(KERN_CRIT "impossible request in %s.\n"
+ "please mail a stack trace to "
+ "linux-scsi@vger.kernel.org",
+ __FUNCTION__);
+ BUG();
+ }
spin_lock(shost->host_lock);
if (!scsi_host_queue_ready(q, shost, sdev))
@@ -1334,15 +1479,6 @@ static void scsi_request_fn(struct request_queue *q)
*/
spin_unlock_irq(shost->host_lock);
- cmd = req->special;
- if (unlikely(cmd == NULL)) {
- printk(KERN_CRIT "impossible request in %s.\n"
- "please mail a stack trace to "
- "linux-scsi@vger.kernel.org",
- __FUNCTION__);
- BUG();
- }
-
/*
* Finally, initialize any error handling parameters, and set up
* the timers for timeouts.
@@ -1378,6 +1514,7 @@ static void scsi_request_fn(struct request_queue *q)
* cases (host limits or settings) should run the queue at some
* later time.
*/
+ scsi_unprep_request(req);
spin_lock_irq(q->queue_lock);
blk_requeue_request(q, req);
sdev->device_busy--;
@@ -1539,9 +1676,9 @@ void scsi_exit_queue(void)
}
}
/**
- * __scsi_mode_sense - issue a mode sense, falling back from 10 to
+ * scsi_mode_sense - issue a mode sense, falling back from 10 to
* six bytes if necessary.
- * @sreq: SCSI request to fill in with the MODE_SENSE
+ * @sdev: SCSI device to be queried
* @dbd: set if mode sense will allow block descriptors to be returned
* @modepage: mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
@@ -1549,26 +1686,34 @@ void scsi_exit_queue(void)
* @timeout: command timeout
* @retries: number of retries before failing
* @data: returns a structure abstracting the mode header data
+ * @sense: place to put sense data (or NULL if no sense to be collected).
+ * must be SCSI_SENSE_BUFFERSIZE big.
*
* Returns zero if unsuccessful, or the header offset (either 4
* or 8 depending on whether a six or ten byte command was
* issued) if successful.
**/
int
-__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data) {
+ struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) {
unsigned char cmd[12];
int use_10_for_ms;
int header_length;
+ int result;
+ struct scsi_sense_hdr my_sshdr;
memset(data, 0, sizeof(*data));
memset(&cmd[0], 0, 12);
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
+ /* caller might not be interested in sense, but we need it */
+ if (!sshdr)
+ sshdr = &my_sshdr;
+
retry:
- use_10_for_ms = sreq->sr_device->use_10_for_ms;
+ use_10_for_ms = sdev->use_10_for_ms;
if (use_10_for_ms) {
if (len < 8)
@@ -1586,36 +1731,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
header_length = 4;
}
- sreq->sr_cmd_len = 0;
- memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
memset(buffer, 0, len);
- scsi_wait_req(sreq, cmd, buffer, len, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+ sshdr, timeout, retries);
/* This code looks awful: what it's doing is making sure an
* ILLEGAL REQUEST sense return identifies the actual command
* byte as the problem. MODE_SENSE commands can return
* ILLEGAL REQUEST if the code page isn't supported */
- if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) &&
- (driver_byte(sreq->sr_result) & DRIVER_SENSE)) {
- struct scsi_sense_hdr sshdr;
-
- if (scsi_request_normalize_sense(sreq, &sshdr)) {
- if ((sshdr.sense_key == ILLEGAL_REQUEST) &&
- (sshdr.asc == 0x20) && (sshdr.ascq == 0)) {
+ if (use_10_for_ms && !scsi_status_is_good(result) &&
+ (driver_byte(result) & DRIVER_SENSE)) {
+ if (scsi_sense_valid(sshdr)) {
+ if ((sshdr->sense_key == ILLEGAL_REQUEST) &&
+ (sshdr->asc == 0x20) && (sshdr->ascq == 0)) {
/*
* Invalid command operation code
*/
- sreq->sr_device->use_10_for_ms = 0;
+ sdev->use_10_for_ms = 0;
goto retry;
}
}
}
- if(scsi_status_is_good(sreq->sr_result)) {
+ if(scsi_status_is_good(result)) {
data->header_length = header_length;
if(use_10_for_ms) {
data->length = buffer[0]*256 + buffer[1] + 2;
@@ -1632,73 +1772,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
}
}
- return sreq->sr_result;
-}
-EXPORT_SYMBOL(__scsi_mode_sense);
-
-/**
- * scsi_mode_sense - issue a mode sense, falling back from 10 to
- * six bytes if necessary.
- * @sdev: scsi device to send command to.
- * @dbd: set if mode sense will disable block descriptors in the return
- * @modepage: mode page being requested
- * @buffer: request buffer (may not be smaller than eight bytes)
- * @len: length of request buffer.
- * @timeout: command timeout
- * @retries: number of retries before failing
- *
- * Returns zero if unsuccessful, or the header offset (either 4
- * or 8 depending on whether a six or ten byte command was
- * issued) if successful.
- **/
-int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
- unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data)
-{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- int ret;
-
- if (!sreq)
- return -1;
-
- ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len,
- timeout, retries, data);
-
- scsi_release_request(sreq);
-
- return ret;
+ return result;
}
EXPORT_SYMBOL(scsi_mode_sense);
int
scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
{
- struct scsi_request *sreq;
char cmd[] = {
TEST_UNIT_READY, 0, 0, 0, 0, 0,
};
+ struct scsi_sense_hdr sshdr;
int result;
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq)
- return -ENOMEM;
-
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr,
+ timeout, retries);
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) {
- struct scsi_sense_hdr sshdr;
+ if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
- if ((scsi_request_normalize_sense(sreq, &sshdr)) &&
+ if ((scsi_sense_valid(&sshdr)) &&
((sshdr.sense_key == UNIT_ATTENTION) ||
(sshdr.sense_key == NOT_READY))) {
sdev->changed = 1;
- sreq->sr_result = 0;
+ result = 0;
}
}
- result = sreq->sr_result;
- scsi_release_request(sreq);
return result;
}
EXPORT_SYMBOL(scsi_test_unit_ready);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index d30d7f4e63ec..d05f778d31a8 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -63,6 +63,9 @@ extern int __init scsi_init_devinfo(void);
extern void scsi_exit_devinfo(void);
/* scsi_error.c */
+extern void scsi_add_timer(struct scsi_cmnd *, int,
+ void (*)(struct scsi_cmnd *));
+extern int scsi_delete_timer(struct scsi_cmnd *);
extern void scsi_times_out(struct scsi_cmnd *cmd);
extern int scsi_error_handler(void *host);
extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
@@ -121,6 +124,7 @@ extern void scsi_sysfs_unregister(void);
extern void scsi_sysfs_device_initialize(struct scsi_device *);
extern int scsi_sysfs_target_initialize(struct scsi_device *);
extern struct scsi_transport_template blank_transport_template;
+extern void __scsi_remove_device(struct scsi_device *);
extern struct bus_type scsi_bus_type;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 48edd67982a5..b86f170fa8ed 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout,
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
- * @sreq: used to send the command
+ * @sdev: scsi device to send command to
* @result: area to store the result of the MODE SENSE
*
* Description:
- * Send a vendor specific MODE SENSE (not a MODE SELECT) command using
- * @sreq to unlock a device, storing the (unused) results into result.
+ * Send a vendor specific MODE SENSE (not a MODE SELECT) command.
* Called for BLIST_KEY devices.
**/
-static void scsi_unlock_floptical(struct scsi_request *sreq,
+static void scsi_unlock_floptical(struct scsi_device *sdev,
unsigned char *result)
{
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
@@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq,
scsi_cmd[1] = 0;
scsi_cmd[2] = 0x2e;
scsi_cmd[3] = 0;
- scsi_cmd[4] = 0x2a; /* size */
+ scsi_cmd[4] = 0x2a; /* size */
scsi_cmd[5] = 0;
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
- scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3);
+ scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL,
+ SCSI_TIMEOUT, 3);
}
/**
@@ -433,26 +431,25 @@ void scsi_target_reap(struct scsi_target *starget)
/**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
- * @sreq: used to send the INQUIRY
+ * @sdev: scsi_device to probe
* @inq_result: area to store the INQUIRY result
+ * @result_len: len of inq_result
* @bflags: store any bflags found here
*
* Description:
- * Probe the lun associated with @sreq using a standard SCSI INQUIRY;
+ * Probe the lun associated with @req using a standard SCSI INQUIRY;
*
- * If the INQUIRY is successful, sreq->sr_result is zero and: the
+ * If the INQUIRY is successful, zero is returned and the
* INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
- * are copied to the Scsi_Device at @sreq->sr_device (sdev);
- * any flags value is stored in *@bflags.
+ * are copied to the Scsi_Device any flags value is stored in *@bflags.
**/
-static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
- int *bflags)
+static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
+ int result_len, int *bflags)
{
- struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
int first_inquiry_len, try_inquiry_len, next_inquiry_len;
int response_len = 0;
- int pass, count;
+ int pass, count, result;
struct scsi_sense_hdr sshdr;
*bflags = 0;
@@ -475,28 +472,26 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
memset(scsi_cmd, 0, 6);
scsi_cmd[0] = INQUIRY;
scsi_cmd[4] = (unsigned char) try_inquiry_len;
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
memset(inq_result, 0, try_inquiry_len);
- scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result,
- try_inquiry_len,
- HZ/2 + HZ*scsi_inq_timeout, 3);
+
+ result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
+ inq_result, try_inquiry_len, &sshdr,
+ HZ / 2 + HZ * scsi_inq_timeout, 3);
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s "
"with code 0x%x\n",
- sreq->sr_result ? "failed" : "successful",
- sreq->sr_result));
+ result ? "failed" : "successful", result));
- if (sreq->sr_result) {
+ if (result) {
/*
* not-ready to ready transition [asc/ascq=0x28/0x0]
* or power-on, reset [asc/ascq=0x29/0x0], continue.
* INQUIRY should not yield UNIT_ATTENTION
* but many buggy devices do so anyway.
*/
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
- scsi_request_normalize_sense(sreq, &sshdr)) {
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ scsi_sense_valid(&sshdr)) {
if ((sshdr.sense_key == UNIT_ATTENTION) &&
((sshdr.asc == 0x28) ||
(sshdr.asc == 0x29)) &&
@@ -507,7 +502,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
break;
}
- if (sreq->sr_result == 0) {
+ if (result == 0) {
response_len = (unsigned char) inq_result[4] + 5;
if (response_len > 255)
response_len = first_inquiry_len; /* sanity */
@@ -556,8 +551,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
/* If the last transfer attempt got an error, assume the
* peripheral doesn't exist or is dead. */
- if (sreq->sr_result)
- return;
+ if (result)
+ return -EIO;
/* Don't report any more data than the device says is valid */
sdev->inquiry_len = min(try_inquiry_len, response_len);
@@ -593,7 +588,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
(sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1))
sdev->scsi_level++;
- return;
+ return 0;
}
/**
@@ -800,9 +795,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
void *hostdata)
{
struct scsi_device *sdev;
- struct scsi_request *sreq;
unsigned char *result;
- int bflags, res = SCSI_SCAN_NO_RESPONSE;
+ int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
/*
@@ -831,16 +825,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
sdev = scsi_alloc_sdev(starget, lun, hostdata);
if (!sdev)
goto out;
- sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
- if (!sreq)
- goto out_free_sdev;
- result = kmalloc(256, GFP_ATOMIC |
+
+ result = kmalloc(result_len, GFP_ATOMIC |
((shost->unchecked_isa_dma) ? __GFP_DMA : 0));
if (!result)
- goto out_free_sreq;
+ goto out_free_sdev;
- scsi_probe_lun(sreq, result, &bflags);
- if (sreq->sr_result)
+ if (scsi_probe_lun(sdev, result, result_len, &bflags))
goto out_free_result;
/*
@@ -868,7 +859,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
if (res == SCSI_SCAN_LUN_PRESENT) {
if (bflags & BLIST_KEY) {
sdev->lockable = 0;
- scsi_unlock_floptical(sreq, result);
+ scsi_unlock_floptical(sdev, result);
}
if (bflagsp)
*bflagsp = bflags;
@@ -876,13 +867,15 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
out_free_result:
kfree(result);
- out_free_sreq:
- scsi_release_request(sreq);
out_free_sdev:
if (res == SCSI_SCAN_LUN_PRESENT) {
if (sdevp) {
- scsi_device_get(sdev);
- *sdevp = sdev;
+ if (scsi_device_get(sdev) == 0) {
+ *sdevp = sdev;
+ } else {
+ __scsi_remove_device(sdev);
+ res = SCSI_SCAN_NO_RESPONSE;
+ }
}
} else {
if (sdev->host->hostt->slave_destroy)
@@ -1070,8 +1063,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
unsigned int lun;
unsigned int num_luns;
unsigned int retries;
+ int result;
struct scsi_lun *lunp, *lun_data;
- struct scsi_request *sreq;
u8 *data;
struct scsi_sense_hdr sshdr;
struct scsi_target *starget = scsi_target(sdev);
@@ -1089,10 +1082,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
if (bflags & BLIST_NOLUN)
return 0;
- sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
- if (!sreq)
- goto out;
-
sprintf(devname, "host %d channel %d id %d",
sdev->host->host_no, sdev->channel, sdev->id);
@@ -1110,7 +1099,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
lun_data = kmalloc(length, GFP_ATOMIC |
(sdev->host->unchecked_isa_dma ? __GFP_DMA : 0));
if (!lun_data)
- goto out_release_request;
+ goto out;
scsi_cmd[0] = REPORT_LUNS;
@@ -1129,8 +1118,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
scsi_cmd[10] = 0; /* reserved */
scsi_cmd[11] = 0; /* control */
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
/*
* We can get a UNIT ATTENTION, for example a power on/reset, so
@@ -1146,29 +1133,29 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending"
" REPORT LUNS to %s (try %d)\n", devname,
retries));
- scsi_wait_req(sreq, scsi_cmd, lun_data, length,
- SCSI_TIMEOUT + 4*HZ, 3);
+
+ result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
+ lun_data, length, &sshdr,
+ SCSI_TIMEOUT + 4 * HZ, 3);
+
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS"
- " %s (try %d) result 0x%x\n", sreq->sr_result
- ? "failed" : "successful", retries,
- sreq->sr_result));
- if (sreq->sr_result == 0)
+ " %s (try %d) result 0x%x\n", result
+ ? "failed" : "successful", retries, result));
+ if (result == 0)
break;
- else if (scsi_request_normalize_sense(sreq, &sshdr)) {
+ else if (scsi_sense_valid(&sshdr)) {
if (sshdr.sense_key != UNIT_ATTENTION)
break;
}
}
- if (sreq->sr_result) {
+ if (result) {
/*
* The device probably does not support a REPORT LUN command
*/
kfree(lun_data);
- scsi_release_request(sreq);
return 1;
}
- scsi_release_request(sreq);
/*
* Get the length from the first four bytes of lun_data.
@@ -1242,8 +1229,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
kfree(lun_data);
return 0;
- out_release_request:
- scsi_release_request(sreq);
out:
/*
* We are out of memory, don't try scanning any further.
@@ -1265,9 +1250,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
get_device(&starget->dev);
down(&shost->scan_mutex);
- res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
- if (res != SCSI_SCAN_LUN_PRESENT)
- sdev = ERR_PTR(-ENODEV);
+ if (scsi_host_scan_allowed(shost)) {
+ res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
+ hostdata);
+ if (res != SCSI_SCAN_LUN_PRESENT)
+ sdev = ERR_PTR(-ENODEV);
+ }
up(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
@@ -1276,6 +1264,19 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
}
EXPORT_SYMBOL(__scsi_add_device);
+int scsi_add_device(struct Scsi_Host *host, uint channel,
+ uint target, uint lun)
+{
+ struct scsi_device *sdev =
+ __scsi_add_device(host, channel, target, lun, NULL);
+ if (IS_ERR(sdev))
+ return PTR_ERR(sdev);
+
+ scsi_device_put(sdev);
+ return 0;
+}
+EXPORT_SYMBOL(scsi_add_device);
+
void scsi_rescan_device(struct device *dev)
{
struct scsi_driver *drv;
@@ -1292,27 +1293,8 @@ void scsi_rescan_device(struct device *dev)
}
EXPORT_SYMBOL(scsi_rescan_device);
-/**
- * scsi_scan_target - scan a target id, possibly including all LUNs on the
- * target.
- * @sdevsca: Scsi_Device handle for scanning
- * @shost: host to scan
- * @channel: channel to scan
- * @id: target id to scan
- *
- * Description:
- * Scan the target id on @shost, @channel, and @id. Scan at least LUN
- * 0, and possibly all LUNs on the target id.
- *
- * Use the pre-allocated @sdevscan as a handle for the scanning. This
- * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the
- * scanning functions modify sdevscan->lun.
- *
- * First try a REPORT LUN scan, if that does not scan the target, do a
- * sequential scan of LUNs on the target id.
- **/
-void scsi_scan_target(struct device *parent, unsigned int channel,
- unsigned int id, unsigned int lun, int rescan)
+static void __scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan)
{
struct Scsi_Host *shost = dev_to_shost(parent);
int bflags = 0;
@@ -1326,9 +1308,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
*/
return;
-
starget = scsi_alloc_target(parent, channel, id);
-
if (!starget)
return;
@@ -1374,6 +1354,33 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
put_device(&starget->dev);
}
+
+/**
+ * scsi_scan_target - scan a target id, possibly including all LUNs on the
+ * target.
+ * @parent: host to scan
+ * @channel: channel to scan
+ * @id: target id to scan
+ * @lun: Specific LUN to scan or SCAN_WILD_CARD
+ * @rescan: passed to LUN scanning routines
+ *
+ * Description:
+ * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0,
+ * and possibly all LUNs on the target id.
+ *
+ * First try a REPORT LUN scan, if that does not scan the target, do a
+ * sequential scan of LUNs on the target id.
+ **/
+void scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan)
+{
+ struct Scsi_Host *shost = dev_to_shost(parent);
+
+ down(&shost->scan_mutex);
+ if (scsi_host_scan_allowed(shost))
+ __scsi_scan_target(parent, channel, id, lun, rescan);
+ up(&shost->scan_mutex);
+}
EXPORT_SYMBOL(scsi_scan_target);
static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
@@ -1399,10 +1406,12 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
order_id = shost->max_id - id - 1;
else
order_id = id;
- scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
+ __scsi_scan_target(&shost->shost_gendev, channel,
+ order_id, lun, rescan);
}
else
- scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
+ __scsi_scan_target(&shost->shost_gendev, channel,
+ id, lun, rescan);
}
int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1417,11 +1426,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
return -EINVAL;
down(&shost->scan_mutex);
- if (channel == SCAN_WILD_CARD)
- for (channel = 0; channel <= shost->max_channel; channel++)
+ if (scsi_host_scan_allowed(shost)) {
+ if (channel == SCAN_WILD_CARD)
+ for (channel = 0; channel <= shost->max_channel;
+ channel++)
+ scsi_scan_channel(shost, channel, id, lun,
+ rescan);
+ else
scsi_scan_channel(shost, channel, id, lun, rescan);
- else
- scsi_scan_channel(shost, channel, id, lun, rescan);
+ }
up(&shost->scan_mutex);
return 0;
@@ -1496,12 +1509,15 @@ void scsi_forget_host(struct Scsi_Host *shost)
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
- struct scsi_device *sdev;
+ struct scsi_device *sdev = NULL;
struct scsi_target *starget;
+ down(&shost->scan_mutex);
+ if (!scsi_host_scan_allowed(shost))
+ goto out;
starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
if (!starget)
- return NULL;
+ goto out;
sdev = scsi_alloc_sdev(starget, 0, NULL);
if (sdev) {
@@ -1509,6 +1525,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
sdev->borken = 0;
}
put_device(&starget->dev);
+ out:
+ up(&shost->scan_mutex);
return sdev;
}
EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index beed7fbe1cbe..b8052d5206cc 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum scsi_device_state state)
return name;
}
+static struct {
+ enum scsi_host_state value;
+ char *name;
+} shost_states[] = {
+ { SHOST_CREATED, "created" },
+ { SHOST_RUNNING, "running" },
+ { SHOST_CANCEL, "cancel" },
+ { SHOST_DEL, "deleted" },
+ { SHOST_RECOVERY, "recovery" },
+};
+const char *scsi_host_state_name(enum scsi_host_state state)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+ if (shost_states[i].value == state) {
+ name = shost_states[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
static int check_set(unsigned int *val, char *src)
{
char *last;
@@ -124,6 +148,43 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf,
};
static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+static ssize_t
+store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+{
+ int i;
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ enum scsi_host_state state = 0;
+
+ for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+ const int len = strlen(shost_states[i].name);
+ if (strncmp(shost_states[i].name, buf, len) == 0 &&
+ buf[len] == '\n') {
+ state = shost_states[i].value;
+ break;
+ }
+ }
+ if (!state)
+ return -EINVAL;
+
+ if (scsi_host_set_state(shost, state))
+ return -EINVAL;
+ return count;
+}
+
+static ssize_t
+show_shost_state(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ const char *name = scsi_host_state_name(shost->shost_state);
+
+ if (!name)
+ return -EINVAL;
+
+ return snprintf(buf, 20, "%s\n", name);
+}
+
+static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+
shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -139,6 +200,7 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
&class_device_attr_unchecked_isa_dma,
&class_device_attr_proc_name,
&class_device_attr_scan,
+ &class_device_attr_state,
NULL
};
@@ -591,7 +653,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
error = attr_add(&sdev->sdev_gendev,
sdev->host->hostt->sdev_attrs[i]);
if (error) {
- scsi_remove_device(sdev);
+ __scsi_remove_device(sdev);
goto out;
}
}
@@ -605,7 +667,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
scsi_sysfs_sdev_attrs[i]);
error = device_create_file(&sdev->sdev_gendev, attr);
if (error) {
- scsi_remove_device(sdev);
+ __scsi_remove_device(sdev);
goto out;
}
}
@@ -625,17 +687,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
return error;
}
-/**
- * scsi_remove_device - unregister a device from the scsi bus
- * @sdev: scsi_device to unregister
- **/
-void scsi_remove_device(struct scsi_device *sdev)
+void __scsi_remove_device(struct scsi_device *sdev)
{
- struct Scsi_Host *shost = sdev->host;
-
- down(&shost->scan_mutex);
if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
- goto out;
+ return;
class_device_unregister(&sdev->sdev_classdev);
device_del(&sdev->sdev_gendev);
@@ -644,8 +699,17 @@ void scsi_remove_device(struct scsi_device *sdev)
sdev->host->hostt->slave_destroy(sdev);
transport_unregister_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev);
-out:
- up(&shost->scan_mutex);
+}
+
+/**
+ * scsi_remove_device - unregister a device from the scsi bus
+ * @sdev: scsi_device to unregister
+ **/
+void scsi_remove_device(struct scsi_device *sdev)
+{
+ down(&sdev->host->scan_mutex);
+ __scsi_remove_device(sdev);
+ up(&sdev->host->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index e6412fce423c..2cab556b6e82 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -252,7 +252,8 @@ struct fc_internal {
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
-static int fc_target_setup(struct device *dev)
+static int fc_target_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct scsi_target *starget = to_scsi_target(dev);
struct fc_rport *rport = starget_to_rport(starget);
@@ -281,7 +282,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
NULL,
NULL);
-static int fc_host_setup(struct device *dev)
+static int fc_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
new file mode 100644
index 000000000000..ff724bbe6611
--- /dev/null
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2005 Dell Inc.
+ * Released under GPL v2.
+ *
+ * Serial Attached SCSI (SAS) transport class.
+ *
+ * The SAS transport class contains common code to deal with SAS HBAs,
+ * an aproximated representation of SAS topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and managment
+ * interfaces to userspace.
+ *
+ * In addition to the basic SCSI core objects this transport class
+ * introduces two additional intermediate objects: The SAS PHY
+ * as represented by struct sas_phy defines an "outgoing" PHY on
+ * a SAS HBA or Expander, and the SAS remote PHY represented by
+ * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
+ * end device. Note that this is purely a software concept, the
+ * underlying hardware for a PHY and a remote PHY is the exactly
+ * the same.
+ *
+ * There is no concept of a SAS port in this code, users can see
+ * what PHYs form a wide port based on the port_identifier attribute,
+ * which is the same for all PHYs in a port.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_sas.h>
+
+
+#define SAS_HOST_ATTRS 0
+#define SAS_PORT_ATTRS 11
+#define SAS_RPORT_ATTRS 5
+
+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 transport_container phy_attr_cont;
+ struct transport_container rphy_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];
+};
+#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
+
+struct sas_host_attrs {
+ struct list_head rphy_list;
+ spinlock_t lock;
+ u32 next_target_id;
+};
+#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+ struct class_device_attribute class_device_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * Pretty printing helpers
+ */
+
+#define sas_bitfield_name_match(title, table) \
+static ssize_t \
+get_sas_##title##_names(u32 table_key, char *buf) \
+{ \
+ char *prefix = ""; \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \
+ if (table[i].value & table_key) { \
+ len += sprintf(buf + len, "%s%s", \
+ prefix, table[i].name); \
+ prefix = ", "; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+#define sas_bitfield_name_search(title, table) \
+static ssize_t \
+get_sas_##title##_names(u32 table_key, char *buf) \
+{ \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \
+ if (table[i].value == table_key) { \
+ len += sprintf(buf + len, "%s", \
+ table[i].name); \
+ break; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+static struct {
+ u32 value;
+ char *name;
+} sas_device_type_names[] = {
+ { SAS_PHY_UNUSED, "unused" },
+ { SAS_END_DEVICE, "end device" },
+ { SAS_EDGE_EXPANDER_DEVICE, "edge expander" },
+ { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" },
+};
+sas_bitfield_name_search(device_type, sas_device_type_names)
+
+
+static struct {
+ u32 value;
+ char *name;
+} sas_protocol_names[] = {
+ { SAS_PROTOCOL_SATA, "sata" },
+ { SAS_PROTOCOL_SMP, "smp" },
+ { SAS_PROTOCOL_STP, "stp" },
+ { SAS_PROTOCOL_SSP, "ssp" },
+};
+sas_bitfield_name_match(protocol, sas_protocol_names)
+
+static struct {
+ u32 value;
+ char *name;
+} sas_linkspeed_names[] = {
+ { SAS_LINK_RATE_UNKNOWN, "Unknown" },
+ { SAS_PHY_DISABLED, "Phy disabled" },
+ { SAS_LINK_RATE_FAILED, "Link Rate failed" },
+ { SAS_SATA_SPINUP_HOLD, "Spin-up hold" },
+ { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" },
+ { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" },
+};
+sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
+
+
+/*
+ * SAS host attributes
+ */
+
+static int sas_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ INIT_LIST_HEAD(&sas_host->rphy_list);
+ spin_lock_init(&sas_host->lock);
+ sas_host->next_target_id = 0;
+ return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(sas_host_class,
+ "sas_host", sas_host_setup, NULL, NULL);
+
+static int sas_host_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_host_device(dev))
+ return 0;
+ shost = dev_to_shost(dev);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->t.host_attrs.ac == cont;
+}
+
+static int do_sas_phy_delete(struct device *dev, void *data)
+{
+ if (scsi_is_sas_phy(dev))
+ sas_phy_delete(dev_to_phy(dev));
+ return 0;
+}
+
+/**
+ * sas_remove_host -- tear down a Scsi_Host's SAS data structures
+ * @shost: Scsi Host that is torn down
+ *
+ * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
+ * Must be called just before scsi_remove_host for SAS HBAs.
+ */
+void sas_remove_host(struct Scsi_Host *shost)
+{
+ device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete);
+}
+EXPORT_SYMBOL(sas_remove_host);
+
+
+/*
+ * SAS Port attributes
+ */
+
+#define sas_phy_show_simple(field, name, format_string, cast) \
+static ssize_t \
+show_sas_phy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ return snprintf(buf, 20, format_string, cast phy->field); \
+}
+
+#define sas_phy_simple_attr(field, name, format_string, type) \
+ sas_phy_show_simple(field, name, format_string, (type)) \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_protocol(field, name) \
+static ssize_t \
+show_sas_phy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ if (!phy->field) \
+ return snprintf(buf, 20, "none\n"); \
+ return get_sas_protocol_names(phy->field, buf); \
+}
+
+#define sas_phy_protocol_attr(field, name) \
+ sas_phy_show_protocol(field, name) \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_linkspeed(field) \
+static ssize_t \
+show_sas_phy_##field(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ return get_sas_linkspeed_names(phy->field, buf); \
+}
+
+#define sas_phy_linkspeed_attr(field) \
+ sas_phy_show_linkspeed(field) \
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+
+static ssize_t
+show_sas_device_type(struct class_device *cdev, char *buf)
+{
+ struct sas_phy *phy = transport_class_to_phy(cdev);
+
+ if (!phy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+ return get_sas_device_type_names(phy->identify.device_type, buf);
+}
+
+static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+
+sas_phy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+sas_phy_protocol_attr(identify.target_port_protocols,
+ target_port_protocols);
+sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+ unsigned long long);
+sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
+sas_phy_linkspeed_attr(negotiated_linkrate);
+sas_phy_linkspeed_attr(minimum_linkrate_hw);
+sas_phy_linkspeed_attr(minimum_linkrate);
+sas_phy_linkspeed_attr(maximum_linkrate_hw);
+sas_phy_linkspeed_attr(maximum_linkrate);
+
+
+static DECLARE_TRANSPORT_CLASS(sas_phy_class,
+ "sas_phy", NULL, NULL, NULL);
+
+static int sas_phy_match(struct attribute_container *cont, struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_sas_phy(dev))
+ return 0;
+ shost = dev_to_shost(dev->parent);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->phy_attr_cont.ac == cont;
+}
+
+static void sas_phy_release(struct device *dev)
+{
+ struct sas_phy *phy = dev_to_phy(dev);
+
+ put_device(dev->parent);
+ kfree(phy);
+}
+
+/**
+ * sas_phy_alloc -- allocates and initialize a SAS PHY structure
+ * @parent: Parent device
+ * @number: Port number
+ *
+ * Allocates an SAS PHY structure. It will be added in the device tree
+ * below the device specified by @parent, which has to be either a Scsi_Host
+ * or sas_rphy.
+ *
+ * Returns:
+ * SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_phy *sas_phy_alloc(struct device *parent, int number)
+{
+ struct Scsi_Host *shost = dev_to_shost(parent);
+ struct sas_phy *phy;
+
+ phy = kmalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return NULL;
+ memset(phy, 0, sizeof(*phy));
+
+ get_device(parent);
+
+ phy->number = number;
+
+ device_initialize(&phy->dev);
+ phy->dev.parent = get_device(parent);
+ phy->dev.release = sas_phy_release;
+ sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
+
+ transport_setup_device(&phy->dev);
+
+ return phy;
+}
+EXPORT_SYMBOL(sas_phy_alloc);
+
+/**
+ * sas_phy_add -- add a SAS PHY to the device hierachy
+ * @phy: The PHY to be added
+ *
+ * Publishes a SAS PHY to the rest of the system.
+ */
+int sas_phy_add(struct sas_phy *phy)
+{
+ int error;
+
+ error = device_add(&phy->dev);
+ if (!error) {
+ transport_add_device(&phy->dev);
+ transport_configure_device(&phy->dev);
+ }
+
+ return error;
+}
+EXPORT_SYMBOL(sas_phy_add);
+
+/**
+ * sas_phy_free -- free a SAS PHY
+ * @phy: SAS PHY to free
+ *
+ * Frees the specified SAS PHY.
+ *
+ * Note:
+ * This function must only be called on a PHY that has not
+ * sucessfully been added using 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);
+}
+EXPORT_SYMBOL(sas_phy_free);
+
+/**
+ * sas_phy_delete -- remove SAS PHY
+ * @phy: SAS PHY to remove
+ *
+ * Removes the specified SAS PHY. If the SAS PHY has an
+ * associated remote PHY it is removed before.
+ */
+void
+sas_phy_delete(struct sas_phy *phy)
+{
+ struct device *dev = &phy->dev;
+
+ if (phy->rphy)
+ sas_rphy_delete(phy->rphy);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(dev->parent);
+}
+EXPORT_SYMBOL(sas_phy_delete);
+
+/**
+ * scsi_is_sas_phy -- check if a struct device represents a SAS PHY
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a SAS PHY, %0 else
+ */
+int scsi_is_sas_phy(const struct device *dev)
+{
+ return dev->release == sas_phy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_phy);
+
+/*
+ * SAS remote PHY attributes.
+ */
+
+#define sas_rphy_show_simple(field, name, format_string, cast) \
+static ssize_t \
+show_sas_rphy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
+ \
+ return snprintf(buf, 20, format_string, cast rphy->field); \
+}
+
+#define sas_rphy_simple_attr(field, name, format_string, type) \
+ sas_rphy_show_simple(field, name, format_string, (type)) \
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+#define sas_rphy_show_protocol(field, name) \
+static ssize_t \
+show_sas_rphy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
+ \
+ if (!rphy->field) \
+ return snprintf(buf, 20, "none\n"); \
+ return get_sas_protocol_names(rphy->field, buf); \
+}
+
+#define sas_rphy_protocol_attr(field, name) \
+ sas_rphy_show_protocol(field, name) \
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+static ssize_t
+show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+{
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev);
+
+ if (!rphy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+ return get_sas_device_type_names(
+ rphy->identify.device_type, buf);
+}
+
+static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
+ show_sas_rphy_device_type, NULL);
+
+sas_rphy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
+sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+ unsigned long long);
+sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+
+static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
+ "sas_rphy", NULL, NULL, NULL);
+
+static int sas_rphy_match(struct attribute_container *cont, struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_sas_rphy(dev))
+ return 0;
+ shost = dev_to_shost(dev->parent->parent);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->rphy_attr_cont.ac == cont;
+}
+
+static void sas_rphy_release(struct device *dev)
+{
+ struct sas_rphy *rphy = dev_to_rphy(dev);
+
+ put_device(dev->parent);
+ kfree(rphy);
+}
+
+/**
+ * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure
+ * @parent: SAS PHY this remote PHY is conneted to
+ *
+ * Allocates an SAS remote PHY structure, connected to @parent.
+ *
+ * Returns:
+ * SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent)
+{
+ struct Scsi_Host *shost = dev_to_shost(&parent->dev);
+ struct sas_rphy *rphy;
+
+ rphy = kmalloc(sizeof(*rphy), GFP_KERNEL);
+ if (!rphy) {
+ put_device(&parent->dev);
+ return NULL;
+ }
+ memset(rphy, 0, sizeof(*rphy));
+
+ device_initialize(&rphy->dev);
+ rphy->dev.parent = get_device(&parent->dev);
+ rphy->dev.release = sas_rphy_release;
+ sprintf(rphy->dev.bus_id, "rphy-%d:%d",
+ shost->host_no, parent->number);
+ transport_setup_device(&rphy->dev);
+
+ return rphy;
+}
+EXPORT_SYMBOL(sas_rphy_alloc);
+
+/**
+ * sas_rphy_add -- add a SAS remote PHY to the device hierachy
+ * @rphy: The remote PHY to be added
+ *
+ * Publishes a SAS remote PHY to the rest of the system.
+ */
+int sas_rphy_add(struct sas_rphy *rphy)
+{
+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+ struct sas_identify *identify = &rphy->identify;
+ int error;
+
+ if (parent->rphy)
+ return -ENXIO;
+ parent->rphy = rphy;
+
+ error = device_add(&rphy->dev);
+ if (error)
+ return error;
+ transport_add_device(&rphy->dev);
+ transport_configure_device(&rphy->dev);
+
+ spin_lock(&sas_host->lock);
+ list_add_tail(&rphy->list, &sas_host->rphy_list);
+ if (identify->device_type == SAS_END_DEVICE &&
+ (identify->target_port_protocols &
+ (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
+ rphy->scsi_target_id = sas_host->next_target_id++;
+ else
+ rphy->scsi_target_id = -1;
+ spin_unlock(&sas_host->lock);
+
+ if (rphy->scsi_target_id != -1) {
+ scsi_scan_target(&rphy->dev, parent->number,
+ rphy->scsi_target_id, ~0, 0);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sas_rphy_add);
+
+/**
+ * sas_rphy_free -- free a SAS remote PHY
+ * @rphy SAS remote PHY to free
+ *
+ * Frees the specified SAS remote PHY.
+ *
+ * Note:
+ * This function must only be called on a remote
+ * PHY that has not sucessfully been added using
+ * sas_rphy_add().
+ */
+void sas_rphy_free(struct sas_rphy *rphy)
+{
+ struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ spin_lock(&sas_host->lock);
+ list_del(&rphy->list);
+ spin_unlock(&sas_host->lock);
+
+ transport_destroy_device(&rphy->dev);
+ put_device(rphy->dev.parent);
+ put_device(rphy->dev.parent);
+ put_device(rphy->dev.parent);
+ kfree(rphy);
+}
+EXPORT_SYMBOL(sas_rphy_free);
+
+/**
+ * sas_rphy_delete -- remove SAS remote PHY
+ * @rphy: SAS remote PHY to remove
+ *
+ * Removes the specified SAS remote PHY.
+ */
+void
+sas_rphy_delete(struct sas_rphy *rphy)
+{
+ struct device *dev = &rphy->dev;
+ struct sas_phy *parent = dev_to_phy(dev->parent);
+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ transport_destroy_device(&rphy->dev);
+
+ scsi_remove_target(&rphy->dev);
+
+ spin_lock(&sas_host->lock);
+ list_del(&rphy->list);
+ spin_unlock(&sas_host->lock);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(&parent->dev);
+}
+EXPORT_SYMBOL(sas_rphy_delete);
+
+/**
+ * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a SAS remote PHY, %0 else
+ */
+int scsi_is_sas_rphy(const struct device *dev)
+{
+ return dev->release == sas_rphy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_rphy);
+
+
+/*
+ * SCSI scan helper
+ */
+
+static struct device *sas_target_parent(struct Scsi_Host *shost,
+ int channel, uint id)
+{
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+ struct sas_rphy *rphy;
+ struct device *dev = NULL;
+
+ spin_lock(&sas_host->lock);
+ list_for_each_entry(rphy, &sas_host->rphy_list, list) {
+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+ if (parent->number == channel &&
+ rphy->scsi_target_id == id)
+ dev = &rphy->dev;
+ }
+ spin_unlock(&sas_host->lock);
+
+ return dev;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_RPORT_ATTRIBUTE(field) \
+ i->private_rphy_attrs[count] = class_device_attr_##field; \
+ i->private_rphy_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rphy_attrs[count].store = NULL; \
+ i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \
+ count++
+
+#define SETUP_PORT_ATTRIBUTE(field) \
+ i->private_phy_attrs[count] = class_device_attr_##field; \
+ i->private_phy_attrs[count].attr.mode = S_IRUGO; \
+ i->private_phy_attrs[count].store = NULL; \
+ i->phy_attrs[count] = &i->private_phy_attrs[count]; \
+ count++
+
+
+/**
+ * sas_attach_transport -- instantiate SAS transport template
+ * @ft: SAS transport class function template
+ */
+struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *ft)
+{
+ struct sas_internal *i;
+ int count;
+
+ i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL);
+ if (!i)
+ return NULL;
+ memset(i, 0, sizeof(struct sas_internal));
+
+ i->t.target_parent = sas_target_parent;
+
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &sas_host_class.class;
+ i->t.host_attrs.ac.match = sas_host_match;
+ transport_container_register(&i->t.host_attrs);
+ i->t.host_size = sizeof(struct sas_host_attrs);
+
+ i->phy_attr_cont.ac.class = &sas_phy_class.class;
+ i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
+ i->phy_attr_cont.ac.match = sas_phy_match;
+ transport_container_register(&i->phy_attr_cont);
+
+ i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
+ i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
+ i->rphy_attr_cont.ac.match = sas_rphy_match;
+ transport_container_register(&i->rphy_attr_cont);
+
+ i->f = ft;
+
+ count = 0;
+ i->host_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_PORT_ATTRIBUTE(initiator_port_protocols);
+ SETUP_PORT_ATTRIBUTE(target_port_protocols);
+ SETUP_PORT_ATTRIBUTE(device_type);
+ SETUP_PORT_ATTRIBUTE(sas_address);
+ SETUP_PORT_ATTRIBUTE(phy_identifier);
+ SETUP_PORT_ATTRIBUTE(port_identifier);
+ SETUP_PORT_ATTRIBUTE(negotiated_linkrate);
+ SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);
+ SETUP_PORT_ATTRIBUTE(minimum_linkrate);
+ SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);
+ SETUP_PORT_ATTRIBUTE(maximum_linkrate);
+ i->phy_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
+ SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
+ SETUP_RPORT_ATTRIBUTE(rphy_device_type);
+ SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
+ SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
+ i->rphy_attrs[count] = NULL;
+
+ return &i->t;
+}
+EXPORT_SYMBOL(sas_attach_transport);
+
+/**
+ * sas_release_transport -- release SAS transport template instance
+ * @t: transport template instance
+ */
+void sas_release_transport(struct scsi_transport_template *t)
+{
+ struct sas_internal *i = to_sas_internal(t);
+
+ transport_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->phy_attr_cont);
+ transport_container_unregister(&i->rphy_attr_cont);
+
+ kfree(i);
+}
+EXPORT_SYMBOL(sas_release_transport);
+
+static __init int sas_transport_init(void)
+{
+ int error;
+
+ error = transport_class_register(&sas_host_class);
+ if (error)
+ goto out;
+ error = transport_class_register(&sas_phy_class);
+ if (error)
+ goto out_unregister_transport;
+ error = transport_class_register(&sas_rphy_class);
+ if (error)
+ goto out_unregister_phy;
+
+ return 0;
+
+ out_unregister_phy:
+ transport_class_unregister(&sas_phy_class);
+ out_unregister_transport:
+ transport_class_unregister(&sas_host_class);
+ out:
+ return error;
+
+}
+
+static void __exit sas_transport_exit(void)
+{
+ transport_class_unregister(&sas_host_class);
+ transport_class_unregister(&sas_phy_class);
+ transport_class_unregister(&sas_rphy_class);
+}
+
+MODULE_AUTHOR("Christoph Hellwig");
+MODULE_DESCRIPTION("SAS Transphy Attributes");
+MODULE_LICENSE("GPL");
+
+module_init(sas_transport_init);
+module_exit(sas_transport_exit);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 7670919a087a..ef577c8c2182 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -28,14 +28,14 @@
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
-#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */
+#define SPI_NUM_ATTRS 14 /* increase this if you add attributes */
#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always
* on" attributes */
#define SPI_HOST_ATTRS 1
@@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int value, int denom)
return result;
}
-/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions
- * resulting from (likely) bus and device resets */
-static void spi_wait_req(struct scsi_request *sreq, const void *cmd,
- void *buffer, unsigned bufflen)
+static int spi_execute(struct scsi_device *sdev, const void *cmd,
+ enum dma_data_direction dir,
+ void *buffer, unsigned bufflen,
+ struct scsi_sense_hdr *sshdr)
{
- int i;
+ int i, result;
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
for(i = 0; i < DV_RETRIES; i++) {
- sreq->sr_request->flags |= REQ_FAILFAST;
-
- scsi_wait_req(sreq, cmd, buffer, bufflen,
- DV_TIMEOUT, /* retries */ 1);
- if (sreq->sr_result & DRIVER_SENSE) {
- struct scsi_sense_hdr sshdr;
-
- if (scsi_request_normalize_sense(sreq, &sshdr)
- && sshdr.sense_key == UNIT_ATTENTION)
+ result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
+ sense, DV_TIMEOUT, /* retries */ 1,
+ REQ_FAILFAST);
+ if (result & DRIVER_SENSE) {
+ struct scsi_sense_hdr sshdr_tmp;
+ if (!sshdr)
+ sshdr = &sshdr_tmp;
+
+ if (scsi_normalize_sense(sense, sizeof(*sense),
+ sshdr)
+ && sshdr->sense_key == UNIT_ATTENTION)
continue;
}
break;
}
+ return result;
}
static struct {
@@ -162,7 +166,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
return SPI_SIGNAL_UNKNOWN;
}
-static int spi_host_setup(struct device *dev)
+static int spi_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
@@ -196,7 +201,9 @@ static int spi_host_match(struct attribute_container *cont,
return &i->t.host_attrs.ac == cont;
}
-static int spi_device_configure(struct device *dev)
+static int spi_device_configure(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_target *starget = sdev->sdev_target;
@@ -214,7 +221,9 @@ static int spi_device_configure(struct device *dev)
return 0;
}
-static int spi_setup_transport_attrs(struct device *dev)
+static int spi_setup_transport_attrs(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
struct scsi_target *starget = to_scsi_target(dev);
@@ -231,6 +240,7 @@ static int spi_setup_transport_attrs(struct device *dev)
spi_rd_strm(starget) = 0;
spi_rti(starget) = 0;
spi_pcomp_en(starget) = 0;
+ spi_hold_mcs(starget) = 0;
spi_dv_pending(starget) = 0;
spi_initial_dv(starget) = 0;
init_MUTEX(&spi_dv_sem(starget));
@@ -347,6 +357,7 @@ spi_transport_rd_attr(wr_flow, "%d\n");
spi_transport_rd_attr(rd_strm, "%d\n");
spi_transport_rd_attr(rti, "%d\n");
spi_transport_rd_attr(pcomp_en, "%d\n");
+spi_transport_rd_attr(hold_mcs, "%d\n");
/* we only care about the first child device so we return 1 */
static int child_iter(struct device *dev, void *data)
@@ -539,13 +550,13 @@ enum spi_compare_returns {
/* This is for read/write Domain Validation: If the device supports
* an echo buffer, we do read/write tests to it */
static enum spi_compare_returns
-spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
u8 *ptr, const int retries)
{
- struct scsi_device *sdev = sreq->sr_device;
int len = ptr - buffer;
- int j, k, r;
+ int j, k, r, result;
unsigned int pattern = 0x0000ffff;
+ struct scsi_sense_hdr sshdr;
const char spi_write_buffer[] = {
WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0
@@ -590,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
}
for (r = 0; r < retries; r++) {
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_TO_DEVICE;
- spi_wait_req(sreq, spi_write_buffer, buffer, len);
- if(sreq->sr_result || !scsi_device_online(sdev)) {
- struct scsi_sense_hdr sshdr;
+ result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE,
+ buffer, len, &sshdr);
+ if(result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
- if (scsi_request_normalize_sense(sreq, &sshdr)
+ if (scsi_sense_valid(&sshdr)
&& sshdr.sense_key == ILLEGAL_REQUEST
/* INVALID FIELD IN CDB */
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00)
@@ -609,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
return SPI_COMPARE_SKIP_TEST;
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
+ SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result);
return SPI_COMPARE_FAILURE;
}
memset(ptr, 0, len);
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_FROM_DEVICE;
- spi_wait_req(sreq, spi_read_buffer, ptr, len);
+ spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE,
+ ptr, len, NULL);
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (memcmp(buffer, ptr, len) != 0)
@@ -628,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
/* This is for the simplest form of Domain Validation: a read test
* on the inquiry data from the device */
static enum spi_compare_returns
-spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer,
u8 *ptr, const int retries)
{
- int r;
- const int len = sreq->sr_device->inquiry_len;
- struct scsi_device *sdev = sreq->sr_device;
+ int r, result;
+ const int len = sdev->inquiry_len;
const char spi_inquiry[] = {
INQUIRY, 0, 0, 0, len, 0
};
for (r = 0; r < retries; r++) {
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
memset(ptr, 0, len);
- spi_wait_req(sreq, spi_inquiry, ptr, len);
+ result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE,
+ ptr, len, NULL);
- if(sreq->sr_result || !scsi_device_online(sdev)) {
+ if(result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
return SPI_COMPARE_FAILURE;
}
@@ -667,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
}
static enum spi_compare_returns
-spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
+spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr,
enum spi_compare_returns
- (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+ (*compare_fn)(struct scsi_device *, u8 *, u8 *, int))
{
- struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
- struct scsi_device *sdev = sreq->sr_device;
+ struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct scsi_target *starget = sdev->sdev_target;
int period = 0, prevperiod = 0;
enum spi_compare_returns retval;
@@ -680,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
for (;;) {
int newperiod;
- retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+ retval = compare_fn(sdev, buffer, ptr, DV_LOOPS);
if (retval == SPI_COMPARE_SUCCESS
|| retval == SPI_COMPARE_SKIP_TEST)
@@ -726,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
}
static int
-spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer)
{
- int l;
+ int l, result;
/* first off do a test unit ready. This can error out
* because of reservations or some other reason. If it
@@ -744,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
};
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_NONE;
-
/* We send a set of three TURs to clear any outstanding
* unit attention conditions if they exist (Otherwise the
* buffer tests won't be happy). If the TUR still fails
* (reservation conflict, device not ready, etc) just
* skip the write tests */
for (l = 0; ; l++) {
- spi_wait_req(sreq, spi_test_unit_ready, NULL, 0);
+ result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE,
+ NULL, 0, NULL);
- if(sreq->sr_result) {
+ if(result) {
if(l >= 3)
return 0;
} else {
@@ -764,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
}
}
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
- spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4);
+ result = spi_execute(sdev, spi_read_buffer_descriptor,
+ DMA_FROM_DEVICE, buffer, 4, NULL);
- if (sreq->sr_result)
+ if (result)
/* Device has no echo buffer */
return 0;
@@ -777,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
}
static void
-spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
{
- struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
- struct scsi_device *sdev = sreq->sr_device;
+ struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct scsi_target *starget = sdev->sdev_target;
int len = sdev->inquiry_len;
/* first set us up for narrow async */
DV_SET(offset, 0);
DV_SET(width, 0);
- if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+ if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
@@ -799,7 +798,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
scsi_device_wide(sdev)) {
i->f->set_width(starget, 1);
- if (spi_dv_device_compare_inquiry(sreq, buffer,
+ if (spi_dv_device_compare_inquiry(sdev, buffer,
buffer + len,
DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
@@ -820,7 +819,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
len = 0;
if (scsi_device_dt(sdev))
- len = spi_dv_device_get_echo_buffer(sreq, buffer);
+ len = spi_dv_device_get_echo_buffer(sdev, buffer);
retry:
@@ -846,7 +845,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (len == 0) {
SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
- spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_retrain(sdev, buffer, buffer + len,
spi_dv_device_compare_inquiry);
return;
}
@@ -856,7 +855,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
- if (spi_dv_retrain(sreq, buffer, buffer + len,
+ if (spi_dv_retrain(sdev, buffer, buffer + len,
spi_dv_device_echo_buffer)
== SPI_COMPARE_SKIP_TEST) {
/* OK, the stupid drive can't do a write echo buffer
@@ -879,16 +878,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
void
spi_dv_device(struct scsi_device *sdev)
{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
struct scsi_target *starget = sdev->sdev_target;
u8 *buffer;
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
- if (unlikely(!sreq))
- return;
-
if (unlikely(scsi_device_get(sdev)))
- goto out_free_req;
+ return;
buffer = kmalloc(len, GFP_KERNEL);
@@ -909,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev)
SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n");
- spi_dv_device_internal(sreq, buffer);
+ spi_dv_device_internal(sdev, buffer);
SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n");
@@ -924,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev)
kfree(buffer);
out_put:
scsi_device_put(sdev);
- out_free_req:
- scsi_release_request(sreq);
}
EXPORT_SYMBOL(spi_dv_device);
@@ -1028,10 +1021,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
sprint_frac(tmp, picosec, 1000);
dev_info(&starget->dev,
- "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
- scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
- tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
- tp->qas ? " QAS" : "", tmp, tp->offset);
+ "%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n",
+ scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
+ tp->dt ? "DT" : "ST",
+ tp->iu ? " IU" : "",
+ tp->qas ? " QAS" : "",
+ tp->rd_strm ? " RDSTRM" : "",
+ tp->rti ? " RTI" : "",
+ tp->wr_flow ? " WRFLOW" : "",
+ tp->pcomp_en ? " PCOMP" : "",
+ tp->hold_mcs ? " HMCS" : "",
+ tmp, tp->offset);
} else {
dev_info(&starget->dev, "%sasynchronous.\n",
tp->width ? "wide " : "");
@@ -1073,6 +1073,7 @@ static int spi_device_match(struct attribute_container *cont,
{
struct scsi_device *sdev;
struct Scsi_Host *shost;
+ struct spi_internal *i;
if (!scsi_is_sdev_device(dev))
return 0;
@@ -1085,6 +1086,9 @@ static int spi_device_match(struct attribute_container *cont,
/* Note: this class has no device attributes, so it has
* no per-HBA allocation and thus we don't need to distinguish
* the attribute containers for the device */
+ i = to_spi_internal(shost->transportt);
+ if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target))
+ return 0;
return 1;
}
@@ -1092,6 +1096,7 @@ static int spi_target_match(struct attribute_container *cont,
struct device *dev)
{
struct Scsi_Host *shost;
+ struct scsi_target *starget;
struct spi_internal *i;
if (!scsi_is_target_device(dev))
@@ -1103,7 +1108,11 @@ static int spi_target_match(struct attribute_container *cont,
return 0;
i = to_spi_internal(shost->transportt);
-
+ starget = to_scsi_target(dev);
+
+ if (i->f->deny_binding && i->f->deny_binding(starget))
+ return 0;
+
return &i->t.target_attrs.ac == cont;
}
@@ -1154,6 +1163,7 @@ spi_attach_transport(struct spi_function_template *ft)
SETUP_ATTRIBUTE(rd_strm);
SETUP_ATTRIBUTE(rti);
SETUP_ATTRIBUTE(pcomp_en);
+ SETUP_ATTRIBUTE(hold_mcs);
/* if you add an attribute but forget to increase SPI_NUM_ATTRS
* this bug will trigger */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0410e1bf109a..de564b386052 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -59,7 +59,6 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
#include <scsi/scsicam.h>
#include "scsi_logging.h"
@@ -125,7 +124,7 @@ static int sd_issue_flush(struct device *, sector_t *);
static void sd_end_flush(request_queue_t *, struct request *);
static int sd_prepare_flush(request_queue_t *, struct request *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer);
+ unsigned char *buffer);
static struct scsi_driver sd_template = {
.owner = THIS_MODULE,
@@ -682,19 +681,13 @@ not_present:
static int sd_sync_cache(struct scsi_device *sdp)
{
- struct scsi_request *sreq;
int retries, res;
+ struct scsi_sense_hdr sshdr;
if (!scsi_device_online(sdp))
return -ENODEV;
- sreq = scsi_allocate_request(sdp, GFP_KERNEL);
- if (!sreq) {
- printk("FAILED\n No memory for request\n");
- return -ENOMEM;
- }
- sreq->sr_data_direction = DMA_NONE;
for (retries = 3; retries > 0; --retries) {
unsigned char cmd[10] = { 0 };
@@ -703,22 +696,20 @@ static int sd_sync_cache(struct scsi_device *sdp)
* Leave the rest of the command zero to indicate
* flush everything.
*/
- scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
- if (sreq->sr_result == 0)
+ res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
+ if (res == 0)
break;
}
- res = sreq->sr_result;
- if (res) {
- printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
+ if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
"host = %d, driver = %02x\n ",
status_byte(res), msg_byte(res),
host_byte(res), driver_byte(res));
if (driver_byte(res) & DRIVER_SENSE)
- scsi_print_req_sense("sd", sreq);
+ scsi_print_sense_hdr("sd", &sshdr);
}
- scsi_release_request(sreq);
return res;
}
@@ -957,22 +948,19 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
}
-static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)
+static int media_not_present(struct scsi_disk *sdkp,
+ struct scsi_sense_hdr *sshdr)
{
- struct scsi_sense_hdr sshdr;
- if (!srp->sr_result)
- return 0;
- if (!(driver_byte(srp->sr_result) & DRIVER_SENSE))
+ if (!scsi_sense_valid(sshdr))
return 0;
/* not invoked for commands that could return deferred errors */
- if (scsi_request_normalize_sense(srp, &sshdr)) {
- if (sshdr.sense_key != NOT_READY &&
- sshdr.sense_key != UNIT_ATTENTION)
- return 0;
- if (sshdr.asc != 0x3A) /* medium not present */
- return 0;
- }
+ if (sshdr->sense_key != NOT_READY &&
+ sshdr->sense_key != UNIT_ATTENTION)
+ return 0;
+ if (sshdr->asc != 0x3A) /* medium not present */
+ return 0;
+
set_media_not_present(sdkp);
return 1;
}
@@ -981,10 +969,10 @@ static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)
* spinup disk - called only in sd_revalidate_disk()
*/
static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+{
unsigned char cmd[10];
- unsigned long spintime_value = 0;
+ unsigned long spintime_expire = 0;
int retries, spintime;
unsigned int the_result;
struct scsi_sense_hdr sshdr;
@@ -1001,18 +989,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
cmd[0] = TEST_UNIT_READY;
memset((void *) &cmd[1], 0, 9);
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0,
- SCSI_SENSE_BUFFERSIZE);
- SRpnt->sr_data_direction = DMA_NONE;
+ the_result = scsi_execute_req(sdkp->device, cmd,
+ DMA_NONE, NULL, 0,
+ &sshdr, SD_TIMEOUT,
+ SD_MAX_RETRIES);
- scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,
- 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES);
-
- the_result = SRpnt->sr_result;
if (the_result)
- sense_valid = scsi_request_normalize_sense(
- SRpnt, &sshdr);
+ sense_valid = scsi_sense_valid(&sshdr);
retries++;
} while (retries < 3 &&
(!scsi_status_is_good(the_result) ||
@@ -1024,7 +1007,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
* any media in it, don't bother with any of the rest of
* this crap.
*/
- if (media_not_present(sdkp, SRpnt))
+ if (media_not_present(sdkp, &sshdr))
return;
if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
@@ -1063,33 +1046,42 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
cmd[1] = 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0,
- SCSI_SENSE_BUFFERSIZE);
-
- SRpnt->sr_data_direction = DMA_NONE;
- scsi_wait_req(SRpnt, (void *)cmd,
- (void *) buffer, 0/*512*/,
- SD_TIMEOUT, SD_MAX_RETRIES);
- spintime_value = jiffies;
+ scsi_execute_req(sdkp->device, cmd, DMA_NONE,
+ NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
+ spintime_expire = jiffies + 100 * HZ;
+ spintime = 1;
}
- spintime = 1;
/* Wait 1 second for next try */
msleep(1000);
printk(".");
+
+ /*
+ * Wait for USB flash devices with slow firmware.
+ * Yes, this sense key/ASC combination shouldn't
+ * occur here. It's characteristic of these devices.
+ */
+ } else if (sense_valid &&
+ sshdr.sense_key == UNIT_ATTENTION &&
+ sshdr.asc == 0x28) {
+ if (!spintime) {
+ spintime_expire = jiffies + 5 * HZ;
+ spintime = 1;
+ }
+ /* Wait 1 second for next try */
+ msleep(1000);
} else {
/* we don't understand the sense code, so it's
* probably pointless to loop */
if(!spintime) {
printk(KERN_NOTICE "%s: Unit Not Ready, "
"sense:\n", diskname);
- scsi_print_req_sense("", SRpnt);
+ scsi_print_sense_hdr("", &sshdr);
}
break;
}
- } while (spintime &&
- time_after(spintime_value + 100 * HZ, jiffies));
+ } while (spintime && time_before_eq(jiffies, spintime_expire));
if (spintime) {
if (scsi_status_is_good(the_result))
@@ -1104,14 +1096,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
*/
static void
sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+ unsigned char *buffer)
+{
unsigned char cmd[16];
- struct scsi_device *sdp = sdkp->device;
int the_result, retries;
int sector_size = 0;
int longrc = 0;
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
+ struct scsi_device *sdp = sdkp->device;
repeat:
retries = 3;
@@ -1128,20 +1121,15 @@ repeat:
memset((void *) buffer, 0, 8);
}
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
- SRpnt->sr_data_direction = DMA_FROM_DEVICE;
-
- scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
- longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
+ the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ buffer, longrc ? 12 : 8, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
- if (media_not_present(sdkp, SRpnt))
+ if (media_not_present(sdkp, &sshdr))
return;
- the_result = SRpnt->sr_result;
if (the_result)
- sense_valid = scsi_request_normalize_sense(SRpnt,
- &sshdr);
+ sense_valid = scsi_sense_valid(&sshdr);
retries--;
} while (the_result && retries);
@@ -1156,7 +1144,7 @@ repeat:
driver_byte(the_result));
if (driver_byte(the_result) & DRIVER_SENSE)
- scsi_print_req_sense("sd", SRpnt);
+ scsi_print_sense_hdr("sd", &sshdr);
else
printk("%s : sense not available. \n", diskname);
@@ -1296,11 +1284,13 @@ got_data:
/* called with buffer of length 512 */
static inline int
-sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
- unsigned char *buffer, int len, struct scsi_mode_data *data)
+sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
+ unsigned char *buffer, int len, struct scsi_mode_data *data,
+ struct scsi_sense_hdr *sshdr)
{
- return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len,
- SD_TIMEOUT, SD_MAX_RETRIES, data);
+ return scsi_mode_sense(sdp, dbd, modepage, buffer, len,
+ SD_TIMEOUT, SD_MAX_RETRIES, data,
+ sshdr);
}
/*
@@ -1309,25 +1299,27 @@ sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
*/
static void
sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+ unsigned char *buffer)
+{
int res;
+ struct scsi_device *sdp = sdkp->device;
struct scsi_mode_data data;
set_disk_ro(sdkp->disk, 0);
- if (sdkp->device->skip_ms_page_3f) {
+ if (sdp->skip_ms_page_3f) {
printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
return;
}
- if (sdkp->device->use_192_bytes_for_3f) {
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data);
+ if (sdp->use_192_bytes_for_3f) {
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL);
} else {
/*
* First attempt: ask for all pages (0x3F), but only 4 bytes.
* We have to start carefully: some devices hang if we ask
* for more than is available.
*/
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL);
/*
* Second attempt: ask for page 0 When only page 0 is
@@ -1336,14 +1328,14 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
* CDB.
*/
if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL);
/*
* Third attempt: ask 255 bytes, as we did earlier.
*/
if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255,
- &data);
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255,
+ &data, NULL);
}
if (!scsi_status_is_good(res)) {
@@ -1365,19 +1357,20 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
*/
static void
sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer)
+ unsigned char *buffer)
{
int len = 0, res;
+ struct scsi_device *sdp = sdkp->device;
int dbd;
int modepage;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
- if (sdkp->device->skip_ms_page_8)
+ if (sdp->skip_ms_page_8)
goto defaults;
- if (sdkp->device->type == TYPE_RBC) {
+ if (sdp->type == TYPE_RBC) {
modepage = 6;
dbd = 8;
} else {
@@ -1386,7 +1379,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
}
/* cautiously ask */
- res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr);
if (!scsi_status_is_good(res))
goto bad_sense;
@@ -1407,7 +1400,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
len += data.header_length + data.block_descriptor_length;
/* Get the data */
- res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data);
+ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
if (scsi_status_is_good(res)) {
const char *types[] = {
@@ -1439,7 +1432,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
}
bad_sense:
- if (scsi_request_normalize_sense(SRpnt, &sshdr) &&
+ if (scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST &&
sshdr.asc == 0x24 && sshdr.ascq == 0x0)
printk(KERN_NOTICE "%s: cache data unavailable\n",
@@ -1464,7 +1457,6 @@ static int sd_revalidate_disk(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
- struct scsi_request *sreq;
unsigned char *buffer;
SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
@@ -1476,18 +1468,11 @@ static int sd_revalidate_disk(struct gendisk *disk)
if (!scsi_device_online(sdp))
goto out;
- sreq = scsi_allocate_request(sdp, GFP_KERNEL);
- if (!sreq) {
- printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation "
- "failure.\n");
- goto out;
- }
-
buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA);
if (!buffer) {
printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
"failure.\n");
- goto out_release_request;
+ goto out;
}
/* defaults, until the device tells us otherwise */
@@ -1498,25 +1483,23 @@ static int sd_revalidate_disk(struct gendisk *disk)
sdkp->WCE = 0;
sdkp->RCD = 0;
- sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer);
+ sd_spinup_disk(sdkp, disk->disk_name);
/*
* Without media there is no reason to ask; moreover, some devices
* react badly if we do.
*/
if (sdkp->media_present) {
- sd_read_capacity(sdkp, disk->disk_name, sreq, buffer);
+ sd_read_capacity(sdkp, disk->disk_name, buffer);
if (sdp->removable)
sd_read_write_protect_flag(sdkp, disk->disk_name,
- sreq, buffer);
- sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer);
+ buffer);
+ sd_read_cache_type(sdkp, disk->disk_name, buffer);
}
set_capacity(disk, sdkp->capacity);
kfree(buffer);
- out_release_request:
- scsi_release_request(sreq);
out:
return 0;
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 51292f269ce5..9ea4765d1d12 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -61,7 +61,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */
#ifdef CONFIG_SCSI_PROC_FS
#include <linux/proc_fs.h>
-static char *sg_version_date = "20050328";
+static char *sg_version_date = "20050908";
static int sg_proc_init(void);
static void sg_proc_cleanup(void);
@@ -1027,8 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (sdp->detached)
return -ENODEV;
if (filp->f_flags & O_NONBLOCK) {
- if (test_bit(SHOST_RECOVERY,
- &sdp->device->host->shost_state))
+ if (sdp->device->host->shost_state == SHOST_RECOVERY)
return -EBUSY;
} else if (!scsi_block_when_processing_errors(sdp->device))
return -EBUSY;
@@ -1300,7 +1299,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */
sfp->mmap_called = 1;
}
- vma->vm_flags |= (VM_RESERVED | VM_IO);
+ vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = sfp;
vma->vm_ops = &sg_mmap_vm_ops;
return 0;
@@ -1795,12 +1794,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unsigned long uaddr, size_t count, int rw,
unsigned long max_pfn)
{
+ unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = uaddr >> PAGE_SHIFT;
+ const int nr_pages = end - start;
int res, i, j;
- unsigned int nr_pages;
struct page **pages;
- nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
/* User attempted Overflow! */
if ((uaddr + count) < uaddr)
return -EINVAL;
@@ -2971,23 +2970,22 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos)
{
struct sg_proc_deviter * it = kmalloc(sizeof(*it), GFP_KERNEL);
+ s->private = it;
if (! it)
return NULL;
+
if (NULL == sg_dev_arr)
- goto err1;
+ return NULL;
it->index = *pos;
it->max = sg_last_dev();
if (it->index >= it->max)
- goto err1;
+ return NULL;
return it;
-err1:
- kfree(it);
- return NULL;
}
static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
+ struct sg_proc_deviter * it = s->private;
*pos = ++it->index;
return (it->index < it->max) ? it : NULL;
@@ -2995,7 +2993,7 @@ static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void dev_seq_stop(struct seq_file *s, void *v)
{
- kfree (v);
+ kfree(s->private);
}
static int sg_proc_open_dev(struct inode *inode, struct file *file)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2f259f249522..ce63fc8312dc 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -50,10 +50,10 @@
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */
-#include <scsi/scsi_request.h>
#include "scsi_logging.h"
#include "sr.h"
@@ -199,15 +199,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
/* check multisession offset etc */
sr_cd_check(cdi);
- /*
- * If the disk changed, the capacity will now be different,
- * so we force a re-read of this information
- * Force 2048 for the sector size so that filesystems won't
- * be trying to use something that is too small if the disc
- * has changed.
- */
- cd->needs_sector_size = 1;
- cd->device->sector_size = 2048;
+ get_sectorsize(cd);
}
return retval;
}
@@ -538,13 +530,6 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
- /*
- * If this device did not have media in the drive at boot time, then
- * we would have been unable to get the sector size. Check to see if
- * this is the case, and try again.
- */
- if (cd->needs_sector_size)
- get_sectorsize(cd);
return 0;
error_out:
@@ -604,7 +589,6 @@ static int sr_probe(struct device *dev)
cd->driver = &sr_template;
cd->disk = disk;
cd->capacity = 0x1fffff;
- cd->needs_sector_size = 1;
cd->device->changed = 1; /* force recheck CD type */
cd->use = 1;
cd->readcd_known = 0;
@@ -658,43 +642,30 @@ static void get_sectorsize(struct scsi_cd *cd)
unsigned char *buffer;
int the_result, retries = 3;
int sector_size;
- struct scsi_request *SRpnt = NULL;
request_queue_t *queue;
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
goto Enomem;
- SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
- if (!SRpnt)
- goto Enomem;
do {
cmd[0] = READ_CAPACITY;
memset((void *) &cmd[1], 0, 9);
- /* Mark as really busy */
- SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
- SRpnt->sr_cmd_len = 0;
-
memset(buffer, 0, 8);
/* Do the command and wait.. */
- SRpnt->sr_data_direction = DMA_FROM_DEVICE;
- scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
- 8, SR_TIMEOUT, MAX_RETRIES);
+ the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
+ buffer, 8, NULL, SR_TIMEOUT,
+ MAX_RETRIES);
- the_result = SRpnt->sr_result;
retries--;
} while (the_result && retries);
- scsi_release_request(SRpnt);
- SRpnt = NULL;
-
if (the_result) {
cd->capacity = 0x1fffff;
sector_size = 2048; /* A guess, just in case */
- cd->needs_sector_size = 1;
} else {
#if 0
if (cdrom_get_last_written(&cd->cdi,
@@ -727,7 +698,6 @@ static void get_sectorsize(struct scsi_cd *cd)
printk("%s: unsupported sector size %d.\n",
cd->cdi.name, sector_size);
cd->capacity = 0;
- cd->needs_sector_size = 1;
}
cd->device->sector_size = sector_size;
@@ -736,7 +706,6 @@ static void get_sectorsize(struct scsi_cd *cd)
* Add this so that we have the ability to correctly gauge
* what the device is capable of.
*/
- cd->needs_sector_size = 0;
set_capacity(cd->disk, cd->capacity);
}
@@ -748,10 +717,7 @@ out:
Enomem:
cd->capacity = 0x1fffff;
- sector_size = 2048; /* A guess, just in case */
- cd->needs_sector_size = 1;
- if (SRpnt)
- scsi_release_request(SRpnt);
+ cd->device->sector_size = 2048; /* A guess, just in case */
goto out;
}
@@ -759,8 +725,8 @@ static void get_capabilities(struct scsi_cd *cd)
{
unsigned char *buffer;
struct scsi_mode_data data;
- struct scsi_request *SRpnt;
unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_sense_hdr sshdr;
unsigned int the_result;
int retries, rc, n;
@@ -776,19 +742,11 @@ static void get_capabilities(struct scsi_cd *cd)
""
};
- /* allocate a request for the TEST_UNIT_READY */
- SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
- if (!SRpnt) {
- printk(KERN_WARNING "(get_capabilities:) Request allocation "
- "failure.\n");
- return;
- }
/* allocate transfer buffer */
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer) {
printk(KERN_ERR "sr: out of memory.\n");
- scsi_release_request(SRpnt);
return;
}
@@ -800,24 +758,19 @@ static void get_capabilities(struct scsi_cd *cd)
memset((void *)cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt->sr_cmd_len = 0;
- SRpnt->sr_sense_buffer[0] = 0;
- SRpnt->sr_sense_buffer[2] = 0;
- SRpnt->sr_data_direction = DMA_NONE;
-
- scsi_wait_req (SRpnt, (void *) cmd, buffer,
- 0, SR_TIMEOUT, MAX_RETRIES);
+ the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
+ 0, &sshdr, SR_TIMEOUT,
+ MAX_RETRIES);
- the_result = SRpnt->sr_result;
retries++;
} while (retries < 5 &&
(!scsi_status_is_good(the_result) ||
- ((driver_byte(the_result) & DRIVER_SENSE) &&
- SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
+ (scsi_sense_valid(&sshdr) &&
+ sshdr.sense_key == UNIT_ATTENTION)));
/* ask for mode page 0x2a */
rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
- SR_TIMEOUT, 3, &data);
+ SR_TIMEOUT, 3, &data, NULL);
if (!scsi_status_is_good(rc)) {
/* failed, drive doesn't have capabilities mode page */
@@ -825,7 +778,6 @@ static void get_capabilities(struct scsi_cd *cd)
cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
CDC_DVD | CDC_DVD_RAM |
CDC_SELECT_DISC | CDC_SELECT_SPEED);
- scsi_release_request(SRpnt);
kfree(buffer);
printk("%s: scsi-1 drive\n", cd->cdi.name);
return;
@@ -885,7 +837,6 @@ static void get_capabilities(struct scsi_cd *cd)
cd->device->writeable = 1;
}
- scsi_release_request(SRpnt);
kfree(buffer);
}
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index 0b3178007203..d2bcd99c272f 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -33,7 +33,6 @@ typedef struct scsi_cd {
struct scsi_device *device;
unsigned int vendor; /* vendor code, see sr_vendor.c */
unsigned long ms_offset; /* for reading multisession-CD's */
- unsigned needs_sector_size:1; /* needs to get sector size */
unsigned use:1; /* is this device still supportable */
unsigned xa_flag:1; /* CD has XA sectors ? */
unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 82d68fdb1548..6e45ac3c43c5 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -17,7 +17,7 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
#include "sr.h"
@@ -84,41 +84,37 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
{
- struct scsi_request *SRpnt;
struct scsi_device *SDev;
- struct request *req;
+ struct scsi_sense_hdr sshdr;
int result, err = 0, retries = 0;
+ struct request_sense *sense = cgc->sense;
SDev = cd->device;
- SRpnt = scsi_allocate_request(SDev, GFP_KERNEL);
- if (!SRpnt) {
- printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl");
- err = -ENOMEM;
- goto out;
- }
- SRpnt->sr_data_direction = cgc->data_direction;
+
+ if (!sense) {
+ sense = kmalloc(sizeof(*sense), GFP_KERNEL);
+ if (!sense) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
retry:
if (!scsi_block_when_processing_errors(SDev)) {
err = -ENODEV;
- goto out_free;
+ goto out;
}
- scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen,
- cgc->timeout, IOCTL_RETRIES);
-
- req = SRpnt->sr_request;
- if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) {
- memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen);
- kfree(SRpnt->sr_buffer);
- SRpnt->sr_buffer = req->buffer;
- }
+ memset(sense, 0, sizeof(*sense));
+ result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
+ cgc->buffer, cgc->buflen, (char *)sense,
+ cgc->timeout, IOCTL_RETRIES, 0);
- result = SRpnt->sr_result;
+ scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
/* Minimal error checking. Ignore cases we know about, and report the rest. */
if (driver_byte(result) != 0) {
- switch (SRpnt->sr_sense_buffer[2] & 0xf) {
+ switch (sshdr.sense_key) {
case UNIT_ATTENTION:
SDev->changed = 1;
if (!cgc->quiet)
@@ -128,8 +124,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
err = -ENOMEDIUM;
break;
case NOT_READY: /* This happens if there is no disc in drive */
- if (SRpnt->sr_sense_buffer[12] == 0x04 &&
- SRpnt->sr_sense_buffer[13] == 0x01) {
+ if (sshdr.asc == 0x04 &&
+ sshdr.ascq == 0x01) {
/* sense: Logical unit is in process of becoming ready */
if (!cgc->quiet)
printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
@@ -146,37 +142,33 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
if (!cgc->quiet)
printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name);
#ifdef DEBUG
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
#endif
err = -ENOMEDIUM;
break;
case ILLEGAL_REQUEST:
err = -EIO;
- if (SRpnt->sr_sense_buffer[12] == 0x20 &&
- SRpnt->sr_sense_buffer[13] == 0x00)
+ if (sshdr.asc == 0x20 &&
+ sshdr.ascq == 0x00)
/* sense: Invalid command operation code */
err = -EDRIVE_CANT_DO_THIS;
#ifdef DEBUG
__scsi_print_command(cgc->cmd);
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
#endif
break;
default:
printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
__scsi_print_command(cgc->cmd);
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
err = -EIO;
}
}
- if (cgc->sense)
- memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense));
-
/* Wake up a process waiting for device */
- out_free:
- scsi_release_request(SRpnt);
- SRpnt = NULL;
out:
+ if (!cgc->sense)
+ kfree(sense);
cgc->stat = err;
return err;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 0a7839db5752..a93308ae9736 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20050501";
+static char *verstr = "20050830";
#include <linux/module.h>
@@ -219,6 +219,12 @@ static int switch_partition(struct scsi_tape *);
static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
+static void scsi_tape_release(struct kref *);
+
+#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
+
+static DECLARE_MUTEX(st_ref_sem);
+
#include "osst_detect.h"
#ifndef SIGS_FROM_OSST
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
{"OnStream", "FW-", "", "osst"}
#endif
+static struct scsi_tape *scsi_tape_get(int dev)
+{
+ struct scsi_tape *STp = NULL;
+
+ down(&st_ref_sem);
+ write_lock(&st_dev_arr_lock);
+
+ if (dev < st_dev_max && scsi_tapes != NULL)
+ STp = scsi_tapes[dev];
+ if (!STp) goto out;
+
+ kref_get(&STp->kref);
+
+ if (!STp->device)
+ goto out_put;
+
+ if (scsi_device_get(STp->device))
+ goto out_put;
+
+ goto out;
+
+out_put:
+ kref_put(&STp->kref, scsi_tape_release);
+ STp = NULL;
+out:
+ write_unlock(&st_dev_arr_lock);
+ up(&st_ref_sem);
+ return STp;
+}
+
+static void scsi_tape_put(struct scsi_tape *STp)
+{
+ struct scsi_device *sdev = STp->device;
+
+ down(&st_ref_sem);
+ kref_put(&STp->kref, scsi_tape_release);
+ scsi_device_put(sdev);
+ up(&st_ref_sem);
+}
+
struct st_reject_data {
char *vendor;
char *model;
@@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
return 0;
cmdstatp = &STp->buffer->cmdstat;
- st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
+ st_analyze_sense(SRpnt, cmdstatp);
if (cmdstatp->have_sense)
scode = STp->buffer->cmdstat.sense_hdr.sense_key;
@@ -399,10 +445,10 @@ static void st_sleep_done(struct scsi_cmnd * SCpnt)
(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
SCpnt->request->rq_status = RQ_SCSI_DONE;
- (STp->buffer)->last_SRpnt = SCpnt->sc_request;
DEB( STp->write_pending = 0; )
- complete(SCpnt->request->waiting);
+ if (SCpnt->request->waiting)
+ complete(SCpnt->request->waiting);
}
/* Do the scsi command. Waits until command performed if do_wait is true.
@@ -412,8 +458,20 @@ static struct scsi_request *
st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
int bytes, int direction, int timeout, int retries, int do_wait)
{
+ struct completion *waiting;
unsigned char *bp;
+ /* if async, make sure there's no command outstanding */
+ if (!do_wait && ((STp->buffer)->last_SRpnt)) {
+ printk(KERN_ERR "%s: Async command already active.\n",
+ tape_name(STp));
+ if (signal_pending(current))
+ (STp->buffer)->syscall_result = (-EINTR);
+ else
+ (STp->buffer)->syscall_result = (-EBUSY);
+ return NULL;
+ }
+
if (SRpnt == NULL) {
SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
if (SRpnt == NULL) {
@@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
}
}
- init_completion(&STp->wait);
+ /* If async IO, set last_SRpnt. This ptr tells write_behind_check
+ which IO is outstanding. It's nulled out when the IO completes. */
+ if (!do_wait)
+ (STp->buffer)->last_SRpnt = SRpnt;
+
+ waiting = &STp->wait;
+ init_completion(waiting);
SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
if (SRpnt->sr_use_sg) {
if (!STp->buffer->do_dio)
@@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
bp = (STp->buffer)->b_data;
SRpnt->sr_data_direction = direction;
SRpnt->sr_cmd_len = 0;
- SRpnt->sr_request->waiting = &(STp->wait);
+ SRpnt->sr_request->waiting = waiting;
SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
SRpnt->sr_request->rq_disk = STp->disk;
+ SRpnt->sr_request->end_io = blk_end_sync_rq;
STp->buffer->cmdstat.have_sense = 0;
scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
st_sleep_done, timeout, retries);
if (do_wait) {
- wait_for_completion(SRpnt->sr_request->waiting);
+ wait_for_completion(waiting);
SRpnt->sr_request->waiting = NULL;
+ if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+ SRpnt->sr_result |= (DRIVER_ERROR << 24);
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
}
return SRpnt;
@@ -465,6 +532,7 @@ static int write_behind_check(struct scsi_tape * STp)
struct st_buffer *STbuffer;
struct st_partstat *STps;
struct st_cmdstatus *cmdstatp;
+ struct scsi_request *SRpnt;
STbuffer = STp->buffer;
if (!STbuffer->writing)
@@ -478,10 +546,14 @@ static int write_behind_check(struct scsi_tape * STp)
) /* end DEB */
wait_for_completion(&(STp->wait));
- (STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
+ SRpnt = STbuffer->last_SRpnt;
+ STbuffer->last_SRpnt = NULL;
+ SRpnt->sr_request->waiting = NULL;
+ if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+ SRpnt->sr_result |= (DRIVER_ERROR << 24);
- (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
- scsi_release_request((STp->buffer)->last_SRpnt);
+ (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+ scsi_release_request(SRpnt);
STbuffer->buffer_bytes -= STbuffer->writing;
STps = &(STp->ps[STp->partition]);
@@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, struct file *filp)
*/
filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+ if (!(STp = scsi_tape_get(dev)))
+ return -ENXIO;
+
write_lock(&st_dev_arr_lock);
- if (dev >= st_dev_max || scsi_tapes == NULL ||
- ((STp = scsi_tapes[dev]) == NULL)) {
- write_unlock(&st_dev_arr_lock);
- return (-ENXIO);
- }
filp->private_data = STp;
name = tape_name(STp);
if (STp->in_use) {
write_unlock(&st_dev_arr_lock);
+ scsi_tape_put(STp);
DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
return (-EBUSY);
}
- if(scsi_device_get(STp->device)) {
- write_unlock(&st_dev_arr_lock);
- return (-ENXIO);
- }
STp->in_use = 1;
write_unlock(&st_dev_arr_lock);
STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
@@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, struct file *filp)
err_out:
normalize_buffer(STp->buffer);
STp->in_use = 0;
- scsi_device_put(STp->device);
+ scsi_tape_put(STp);
return retval;
}
@@ -1250,7 +1317,7 @@ static int st_release(struct inode *inode, struct file *filp)
write_lock(&st_dev_arr_lock);
STp->in_use = 0;
write_unlock(&st_dev_arr_lock);
- scsi_device_put(STp->device);
+ scsi_tape_put(STp);
return result;
}
@@ -3887,6 +3954,7 @@ static int st_probe(struct device *dev)
goto out_put_disk;
}
memset(tpnt, 0, sizeof(struct scsi_tape));
+ kref_init(&tpnt->kref);
tpnt->disk = disk;
sprintf(disk->disk_name, "st%d", i);
disk->private_data = &tpnt->driver;
@@ -3902,6 +3970,7 @@ static int st_probe(struct device *dev)
tpnt->tape_type = MT_ISSCSI2;
tpnt->buffer = buffer;
+ tpnt->buffer->last_SRpnt = NULL;
tpnt->inited = 0;
tpnt->dirty = 0;
@@ -4076,15 +4145,10 @@ static int st_remove(struct device *dev)
tpnt->modes[mode].cdevs[j] = NULL;
}
}
- tpnt->device = NULL;
- if (tpnt->buffer) {
- tpnt->buffer->orig_frp_segs = 0;
- normalize_buffer(tpnt->buffer);
- kfree(tpnt->buffer);
- }
- put_disk(tpnt->disk);
- kfree(tpnt);
+ down(&st_ref_sem);
+ kref_put(&tpnt->kref, scsi_tape_release);
+ up(&st_ref_sem);
return 0;
}
}
@@ -4093,6 +4157,34 @@ static int st_remove(struct device *dev)
return 0;
}
+/**
+ * scsi_tape_release - Called to free the Scsi_Tape structure
+ * @kref: pointer to embedded kref
+ *
+ * st_ref_sem must be held entering this routine. Because it is
+ * called on last put, you should always use the scsi_tape_get()
+ * scsi_tape_put() helpers which manipulate the semaphore directly
+ * and never do a direct kref_put().
+ **/
+static void scsi_tape_release(struct kref *kref)
+{
+ struct scsi_tape *tpnt = to_scsi_tape(kref);
+ struct gendisk *disk = tpnt->disk;
+
+ tpnt->device = NULL;
+
+ if (tpnt->buffer) {
+ tpnt->buffer->orig_frp_segs = 0;
+ normalize_buffer(tpnt->buffer);
+ kfree(tpnt->buffer);
+ }
+
+ disk->private_data = NULL;
+ put_disk(disk);
+ kfree(tpnt);
+ return;
+}
+
static void st_intr(struct scsi_cmnd *SCpnt)
{
scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
@@ -4348,12 +4440,12 @@ static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pag
static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unsigned long uaddr, size_t count, int rw)
{
+ unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = uaddr >> PAGE_SHIFT;
+ const int nr_pages = end - start;
int res, i, j;
- unsigned int nr_pages;
struct page **pages;
- nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
/* User attempted Overflow! */
if ((uaddr + count) < uaddr)
return -EINVAL;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 061da111398e..790acac160bc 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -3,7 +3,7 @@
#define _ST_H
#include <linux/completion.h>
-
+#include <linux/kref.h>
/* Descriptor for analyzed sense data */
struct st_cmdstatus {
@@ -156,6 +156,7 @@ struct scsi_tape {
unsigned char last_sense[16];
#endif
struct gendisk *disk;
+ struct kref kref;
};
/* Bit masks for use_pf */
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 0b10169961eb..aec39fb261ca 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -58,8 +58,7 @@ static const char serial21285_name[] = "Footbridge UART";
* int((BAUD_BASE - (baud >> 1)) / baud)
*/
-static void
-serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial21285_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(IRQ_CONTX);
@@ -67,8 +66,7 @@ serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial21285_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(IRQ_CONTX);
@@ -148,7 +146,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- serial21285_stop_tx(port, 0);
+ serial21285_stop_tx(port);
goto out;
}
@@ -164,7 +162,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- serial21285_stop_tx(port, 0);
+ serial21285_stop_tx(port);
out:
return IRQ_HANDLED;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 9097f2f7b12a..2efb317153ce 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -40,7 +40,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index b116122e569a..170c9d2a749c 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -2474,8 +2474,7 @@ static struct tty_operations rs_360_ops = {
.tiocmset = rs_360_tiocmset,
};
-/* int __init rs_360_init(void) */
-int rs_360_init(void)
+static int __init rs_360_init(void)
{
struct serial_state * state;
ser_info_t *info;
@@ -2827,10 +2826,7 @@ int rs_360_init(void)
return 0;
}
-
-
-
-
+module_init(rs_360_init);
/* This must always be called before the rs_360_init() function, otherwise
* it blows away the port control information.
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 7e8fc7c1d4cc..4d75cdfa0a0a 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -864,7 +864,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
/*
* We're pretty sure there's a port here. Lets find out what
* type of port it is. The IIR top two bits allows us to find
- * out if its 8250 or 16450, 16550, 16550A or later. This
+ * out if it's 8250 or 16450, 16550, 16550A or later. This
* determines what we test for next.
*
* We also initialise the EFR (if any) to zero for later. The
@@ -1001,7 +1001,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
}
}
-static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1018,7 +1018,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void transmit_chars(struct uart_8250_port *up);
-static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1158,7 +1158,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
up->port.x_char = 0;
return;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ if (uart_tx_stopped(&up->port)) {
+ serial8250_stop_tx(&up->port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
__stop_tx(up);
return;
}
@@ -2532,7 +2536,7 @@ static int __init serial8250_init(void)
goto out;
serial8250_isa_devs = platform_device_register_simple("serial8250",
- -1, NULL, 0);
+ PLAT8250_DEV_LEGACY, NULL, 0);
if (IS_ERR(serial8250_isa_devs)) {
ret = PTR_ERR(serial8250_isa_devs);
goto unreg;
@@ -2586,82 +2590,3 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
#endif
MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
-
-/**
- * register_serial - configure a 16x50 serial port at runtime
- * @req: request structure
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use an error is returned. If the port
- * is not currently in the table it is added.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- *
- * Note: this function is deprecated - use serial8250_register_port
- * instead.
- */
-int register_serial(struct serial_struct *req)
-{
- struct uart_port port;
-
- port.iobase = req->port;
- port.membase = req->iomem_base;
- port.irq = req->irq;
- port.uartclk = req->baud_base * 16;
- port.fifosize = req->xmit_fifo_size;
- port.regshift = req->iomem_reg_shift;
- port.iotype = req->io_type;
- port.flags = req->flags | UPF_BOOT_AUTOCONF;
- port.mapbase = req->iomap_base;
- port.dev = NULL;
-
- if (share_irqs)
- port.flags |= UPF_SHARE_IRQ;
-
- if (HIGH_BITS_OFFSET)
- port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-
- /*
- * If a clock rate wasn't specified by the low level driver, then
- * default to the standard clock rate. This should be 115200 (*16)
- * and should not depend on the architecture's BASE_BAUD definition.
- * However, since this API will be deprecated, it's probably a
- * better idea to convert the drivers to use the new API
- * (serial8250_register_port and serial8250_unregister_port).
- */
- if (port.uartclk == 0) {
- printk(KERN_WARNING
- "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n",
- port.iobase, port.mapbase, port.membase, port.irq);
- printk(KERN_WARNING "Serial: see %s:%d for more information\n",
- __FILE__, __LINE__);
- dump_stack();
-
- /*
- * Fix it up for now, but this is only a temporary measure.
- */
- port.uartclk = BASE_BAUD * 16;
- }
-
- return serial8250_register_port(&port);
-}
-EXPORT_SYMBOL(register_serial);
-
-/**
- * unregister_serial - remove a 16x50 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may not be called from interrupt
- * context. We hand the port back to our local PM control.
- *
- * Note: this function is deprecated - use serial8250_unregister_port
- * instead.
- */
-void unregister_serial(int line)
-{
- serial8250_unregister_port(line);
-}
-EXPORT_SYMBOL(unregister_serial);
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 9225c82faeb8..b1b459efda52 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -16,11 +16,7 @@
*/
#include <linux/config.h>
-
-int serial8250_register_port(struct uart_port *);
-void serial8250_unregister_port(int line);
-void serial8250_suspend_port(int line);
-void serial8250_resume_port(int line);
+#include <linux/serial_8250.h>
struct old_serial_port {
unsigned int uart;
diff --git a/drivers/serial/8250_accent.c b/drivers/serial/8250_accent.c
index 1f2c276063ef..9c10262f2469 100644
--- a/drivers/serial/8250_accent.c
+++ b/drivers/serial/8250_accent.c
@@ -29,7 +29,7 @@ static struct plat_serial8250_port accent_data[] = {
static struct platform_device accent_device = {
.name = "serial8250",
- .id = 2,
+ .id = PLAT8250_DEV_ACCENT,
.dev = {
.platform_data = accent_data,
},
diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
index 6b9ead288517..a802bdce6e5d 100644
--- a/drivers/serial/8250_acpi.c
+++ b/drivers/serial/8250_acpi.c
@@ -47,18 +47,30 @@ static acpi_status acpi_serial_port(struct uart_port *port,
static acpi_status acpi_serial_ext_irq(struct uart_port *port,
struct acpi_resource_ext_irq *ext_irq)
{
- if (ext_irq->number_of_interrupts > 0)
- port->irq = acpi_register_gsi(ext_irq->interrupts[0],
+ int rc;
+
+ if (ext_irq->number_of_interrupts > 0) {
+ rc = acpi_register_gsi(ext_irq->interrupts[0],
ext_irq->edge_level, ext_irq->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ port->irq = rc;
+ }
return AE_OK;
}
static acpi_status acpi_serial_irq(struct uart_port *port,
struct acpi_resource_irq *irq)
{
- if (irq->number_of_interrupts > 0)
- port->irq = acpi_register_gsi(irq->interrupts[0],
+ int rc;
+
+ if (irq->number_of_interrupts > 0) {
+ rc = acpi_register_gsi(irq->interrupts[0],
irq->edge_level, irq->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ port->irq = rc;
+ }
return AE_OK;
}
diff --git a/drivers/serial/8250_boca.c b/drivers/serial/8250_boca.c
index 465c9ea1e7a3..3bfe0f7b26fb 100644
--- a/drivers/serial/8250_boca.c
+++ b/drivers/serial/8250_boca.c
@@ -43,7 +43,7 @@ static struct plat_serial8250_port boca_data[] = {
static struct platform_device boca_device = {
.name = "serial8250",
- .id = 3,
+ .id = PLAT8250_DEV_BOCA,
.dev = {
.platform_data = boca_data,
},
diff --git a/drivers/serial/8250_fourport.c b/drivers/serial/8250_fourport.c
index e9b4d908ef42..6375d68b7913 100644
--- a/drivers/serial/8250_fourport.c
+++ b/drivers/serial/8250_fourport.c
@@ -35,7 +35,7 @@ static struct plat_serial8250_port fourport_data[] = {
static struct platform_device fourport_device = {
.name = "serial8250",
- .id = 1,
+ .id = PLAT8250_DEV_FOURPORT,
.dev = {
.platform_data = fourport_data,
},
diff --git a/drivers/serial/8250_hub6.c b/drivers/serial/8250_hub6.c
index 77f396f84b4c..daf569cd3c8f 100644
--- a/drivers/serial/8250_hub6.c
+++ b/drivers/serial/8250_hub6.c
@@ -40,7 +40,7 @@ static struct plat_serial8250_port hub6_data[] = {
static struct platform_device hub6_device = {
.name = "serial8250",
- .id = 4,
+ .id = PLAT8250_DEV_HUB6,
.dev = {
.platform_data = hub6_data,
},
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c
index f0c40d68b8c1..ac205256d5f3 100644
--- a/drivers/serial/8250_mca.c
+++ b/drivers/serial/8250_mca.c
@@ -44,7 +44,7 @@ static struct plat_serial8250_port mca_data[] = {
static struct platform_device mca_device = {
.name = "serial8250",
- .id = 5,
+ .id = PLAT8250_DEV_MCA,
.dev = {
.platform_data = mca_data,
},
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 07f05e9d0955..0e21f583690e 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -34,36 +34,6 @@
#undef SERIAL_DEBUG_PCI
/*
- * Definitions for PCI support.
- */
-#define FL_BASE_MASK 0x0007
-#define FL_BASE0 0x0000
-#define FL_BASE1 0x0001
-#define FL_BASE2 0x0002
-#define FL_BASE3 0x0003
-#define FL_BASE4 0x0004
-#define FL_GET_BASE(x) (x & FL_BASE_MASK)
-
-/* Use successive BARs (PCI base address registers),
- else use offset into some specified BAR */
-#define FL_BASE_BARS 0x0008
-
-/* do not assign an irq */
-#define FL_NOIRQ 0x0080
-
-/* Use the Base address register size to cap number of ports */
-#define FL_REGION_SZ_CAP 0x0100
-
-struct pci_board {
- unsigned int flags;
- unsigned int num_ports;
- unsigned int base_baud;
- unsigned int uart_offset;
- unsigned int reg_shift;
- unsigned int first_offset;
-};
-
-/*
* init function returns:
* > 0 - number of ports
* = 0 - use board->num_ports
@@ -75,14 +45,15 @@ struct pci_serial_quirk {
u32 subvendor;
u32 subdevice;
int (*init)(struct pci_dev *dev);
- int (*setup)(struct pci_dev *dev, struct pci_board *board,
- struct uart_port *port, int idx);
+ int (*setup)(struct serial_private *, struct pciserial_board *,
+ struct uart_port *, int);
void (*exit)(struct pci_dev *dev);
};
#define PCI_NUM_BAR_RESOURCES 6
struct serial_private {
+ struct pci_dev *dev;
unsigned int nr;
void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];
struct pci_serial_quirk *quirk;
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev)
}
static int
-setup_port(struct pci_dev *dev, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_port *port,
int bar, int offset, int regshift)
{
- struct serial_private *priv = pci_get_drvdata(dev);
+ struct pci_dev *dev = priv->dev;
unsigned long base, len;
if (bar >= PCI_NUM_BAR_RESOURCES)
return -EINVAL;
+ base = pci_resource_start(dev, bar);
+
if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
- base = pci_resource_start(dev, bar);
len = pci_resource_len(dev, bar);
if (!priv->remapped_bar[bar])
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
return -ENOMEM;
port->iotype = UPIO_MEM;
+ port->iobase = 0;
port->mapbase = base + offset;
port->membase = priv->remapped_bar[bar] + offset;
port->regshift = regshift;
} else {
- base = pci_resource_start(dev, bar) + offset;
port->iotype = UPIO_PORT;
- port->iobase = base;
+ port->iobase = base + offset;
+ port->mapbase = 0;
+ port->membase = NULL;
+ port->regshift = 0;
}
return 0;
}
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
* Not that ugly ;) -- HW
*/
static int
-afavlab_setup(struct pci_dev *dev, struct pci_board *board,
+afavlab_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
offset += (idx - 4) * board->uart_offset;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -189,13 +164,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
* some serial ports are supposed to be hidden on certain models.
*/
static int
-pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
+pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
- switch (dev->subsystem_device) {
+ switch (priv->dev->subsystem_device) {
case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
if (idx == 3)
idx++;
@@ -212,7 +187,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
offset += idx * board->uart_offset;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -307,7 +282,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
-sbs_setup(struct pci_dev *dev, struct pci_board *board,
+sbs_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -323,7 +298,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
} else /* we have only 8 ports on PMC-OCTALPRO */
return 1;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -389,6 +364,9 @@ static void __devexit sbs_exit(struct pci_dev *dev)
* - 10x cards have control registers in IO and/or memory space;
* - 20x cards have control registers in standard PCI configuration space.
*
+ * Note: all 10x cards have PCI device ids 0x10..
+ * all 20x cards have PCI device ids 0x20..
+ *
* There are also Quartet Serial cards which use Oxford Semiconductor
* 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
*
@@ -445,24 +423,18 @@ static int pci_siig20x_init(struct pci_dev *dev)
return 0;
}
-int pci_siig10x_fn(struct pci_dev *dev, int enable)
+static int pci_siig_init(struct pci_dev *dev)
{
- int ret = 0;
- if (enable)
- ret = pci_siig10x_init(dev);
- return ret;
-}
+ unsigned int type = dev->device & 0xff00;
-int pci_siig20x_fn(struct pci_dev *dev, int enable)
-{
- int ret = 0;
- if (enable)
- ret = pci_siig20x_init(dev);
- return ret;
-}
+ if (type == 0x1000)
+ return pci_siig10x_init(dev);
+ else if (type == 0x2000)
+ return pci_siig20x_init(dev);
-EXPORT_SYMBOL(pci_siig10x_fn);
-EXPORT_SYMBOL(pci_siig20x_fn);
+ moan_device("Unknown SIIG card", dev);
+ return -ENODEV;
+}
/*
* Timedia has an explosion of boards, and to avoid the PCI table from
@@ -523,7 +495,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
* Ugh, this is ugly as all hell --- TYT
*/
static int
-pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
+pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -549,14 +521,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
bar = idx - 2;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
* Some Titan cards are also a little weird
*/
static int
-titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
+titan_400l_800l_setup(struct serial_private *priv,
+ struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -573,7 +546,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
offset = (idx - 2) * board->uart_offset;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
static int __devinit pci_xircom_init(struct pci_dev *dev)
@@ -593,7 +566,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev)
}
static int
-pci_default_setup(struct pci_dev *dev, struct pci_board *board,
+pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -604,13 +577,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
else
offset += idx * board->uart_offset;
- maxnr = (pci_resource_len(dev, bar) - board->first_offset) /
+ maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) /
(8 << board->reg_shift);
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
return 1;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* This should be in linux/pci_ids.h */
@@ -754,152 +727,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = sbs_setup,
.exit = __devexit_p(sbs_exit),
},
-
/*
* SIIG cards.
- * It is not clear whether these could be collapsed.
*/
{
.vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- { .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_850,
+ .device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
+ .init = pci_siig_init,
.setup = pci_default_setup,
},
/*
@@ -990,7 +826,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
}
static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
+get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
{
if (board->flags & FL_NOIRQ)
return 0;
@@ -1115,7 +951,7 @@ enum pci_board_num_t {
* see first lines of serial_in() and serial_out() in 8250.c
*/
-static struct pci_board pci_boards[] __devinitdata = {
+static struct pciserial_board pci_boards[] __devinitdata = {
[pbn_default] = {
.flags = FL_BASE0,
.num_ports = 1,
@@ -1575,7 +1411,7 @@ static struct pci_board pci_boards[] __devinitdata = {
* serial specs. Returns 0 on success, 1 on failure.
*/
static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
int num_iomem, num_port, first_port = -1, i;
@@ -1640,7 +1476,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
}
static inline int
-serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
+serial_pci_matches(struct pciserial_board *board,
+ struct pciserial_board *guessed)
{
return
board->num_ports == guessed->num_ports &&
@@ -1650,58 +1487,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
board->first_offset == guessed->first_offset;
}
-/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
{
+ struct uart_port serial_port;
struct serial_private *priv;
- struct pci_board *board, tmp;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
- if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
- printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
- ent->driver_data);
- return -EINVAL;
- }
-
- board = &pci_boards[ent->driver_data];
-
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
-
- if (ent->driver_data == pbn_default) {
- /*
- * Use a copy of the pci_board entry for this;
- * avoid changing entries in the table.
- */
- memcpy(&tmp, board, sizeof(struct pci_board));
- board = &tmp;
-
- /*
- * We matched one of our class entries. Try to
- * determine the parameters of this board.
- */
- rc = serial_pci_guess_board(dev, board);
- if (rc)
- goto disable;
- } else {
- /*
- * We matched an explicit entry. If we are able to
- * detect this boards settings with our heuristic,
- * then we no longer need this entry.
- */
- memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc == 0 && serial_pci_matches(board, &tmp))
- moan_device("Redundant entry in serial pci_table.",
- dev);
- }
-
nr_ports = board->num_ports;
/*
@@ -1718,8 +1511,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
*/
if (quirk->init) {
rc = quirk->init(dev);
- if (rc < 0)
- goto disable;
+ if (rc < 0) {
+ priv = ERR_PTR(rc);
+ goto err_out;
+ }
if (rc)
nr_ports = rc;
}
@@ -1728,27 +1523,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
sizeof(unsigned int) * nr_ports,
GFP_KERNEL);
if (!priv) {
- rc = -ENOMEM;
- goto deinit;
+ priv = ERR_PTR(-ENOMEM);
+ goto err_deinit;
}
memset(priv, 0, sizeof(struct serial_private) +
sizeof(unsigned int) * nr_ports);
+ priv->dev = dev;
priv->quirk = quirk;
- pci_set_drvdata(dev, priv);
+
+ memset(&serial_port, 0, sizeof(struct uart_port));
+ serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ serial_port.uartclk = board->base_baud * 16;
+ serial_port.irq = get_pci_irq(dev, board);
+ serial_port.dev = &dev->dev;
for (i = 0; i < nr_ports; i++) {
- struct uart_port serial_port;
- memset(&serial_port, 0, sizeof(struct uart_port));
-
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF |
- UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board, i);
- serial_port.dev = &dev->dev;
- if (quirk->setup(dev, board, &serial_port, i))
+ if (quirk->setup(priv, board, &serial_port, i))
break;
+
#ifdef SERIAL_DEBUG_PCI
printk("Setup PCI port: port %x, irq %d, type %d\n",
serial_port.iobase, serial_port.irq, serial_port.iotype);
@@ -1763,24 +1557,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
priv->nr = i;
- return 0;
+ return priv;
- deinit:
+ err_deinit:
if (quirk->exit)
quirk->exit(dev);
- disable:
- pci_disable_device(dev);
- return rc;
+ err_out:
+ return priv;
}
+EXPORT_SYMBOL_GPL(pciserial_init_ports);
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
+void pciserial_remove_ports(struct serial_private *priv)
{
- struct serial_private *priv = pci_get_drvdata(dev);
struct pci_serial_quirk *quirk;
int i;
- pci_set_drvdata(dev, NULL);
-
for (i = 0; i < priv->nr; i++)
serial8250_unregister_port(priv->line[i]);
@@ -1793,25 +1584,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
/*
* Find the exit quirks.
*/
- quirk = find_quirk(dev);
+ quirk = find_quirk(priv->dev);
if (quirk->exit)
- quirk->exit(dev);
+ quirk->exit(priv->dev);
+
+ kfree(priv);
+}
+EXPORT_SYMBOL_GPL(pciserial_remove_ports);
+
+void pciserial_suspend_ports(struct serial_private *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_suspend_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
+
+void pciserial_resume_ports(struct serial_private *priv)
+{
+ int i;
+
+ /*
+ * Ensure that the board is correctly configured.
+ */
+ if (priv->quirk->init)
+ priv->quirk->init(priv->dev);
+
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_resume_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+
+/*
+ * Probe one serial board. Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ struct serial_private *priv;
+ struct pciserial_board *board, tmp;
+ int rc;
+
+ if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+ printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+ ent->driver_data);
+ return -EINVAL;
+ }
+
+ board = &pci_boards[ent->driver_data];
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ if (ent->driver_data == pbn_default) {
+ /*
+ * Use a copy of the pci_board entry for this;
+ * avoid changing entries in the table.
+ */
+ memcpy(&tmp, board, sizeof(struct pciserial_board));
+ board = &tmp;
+
+ /*
+ * We matched one of our class entries. Try to
+ * determine the parameters of this board.
+ */
+ rc = serial_pci_guess_board(dev, board);
+ if (rc)
+ goto disable;
+ } else {
+ /*
+ * We matched an explicit entry. If we are able to
+ * detect this boards settings with our heuristic,
+ * then we no longer need this entry.
+ */
+ memcpy(&tmp, &pci_boards[pbn_default],
+ sizeof(struct pciserial_board));
+ rc = serial_pci_guess_board(dev, &tmp);
+ if (rc == 0 && serial_pci_matches(board, &tmp))
+ moan_device("Redundant entry in serial pci_table.",
+ dev);
+ }
+ priv = pciserial_init_ports(dev, board);
+ if (!IS_ERR(priv)) {
+ pci_set_drvdata(dev, priv);
+ return 0;
+ }
+
+ rc = PTR_ERR(priv);
+
+ disable:
pci_disable_device(dev);
+ return rc;
+}
- kfree(priv);
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_drvdata(dev, NULL);
+
+ pciserial_remove_ports(priv);
+
+ pci_disable_device(dev);
}
static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
{
struct serial_private *priv = pci_get_drvdata(dev);
- if (priv) {
- int i;
+ if (priv)
+ pciserial_suspend_ports(priv);
- for (i = 0; i < priv->nr; i++)
- serial8250_suspend_port(priv->line[i]);
- }
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
@@ -1825,21 +1714,12 @@ static int pciserial_resume_one(struct pci_dev *dev)
pci_restore_state(dev);
if (priv) {
- int i;
-
/*
* The device may have been disabled. Re-enable it.
*/
pci_enable_device(dev);
- /*
- * Ensure that the board is correctly configured.
- */
- if (priv->quirk->init)
- priv->quirk->init(dev);
-
- for (i = 0; i < priv->nr; i++)
- serial8250_resume_port(priv->line[i]);
+ pciserial_resume_ports(priv);
}
return 0;
}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d5797618a3b9..b745a1b9e835 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -80,7 +80,7 @@ config SERIAL_8250_CS
config SERIAL_8250_ACPI
bool "8250/16550 device discovery via ACPI namespace"
default y if IA64
- depends on ACPI_BUS && SERIAL_8250
+ depends on ACPI && SERIAL_8250
---help---
If you wish to enable serial port discovery via the ACPI
namespace, say Y here. If unsure, say N.
@@ -308,7 +308,7 @@ config SERIAL_S3C2410_CONSOLE
config SERIAL_DZ
bool "DECstation DZ serial driver"
- depends on MACH_DECSTATION && MIPS32
+ depends on MACH_DECSTATION && 32BIT
select SERIAL_CORE
help
DZ11-family serial controllers for VAXstations, including the
@@ -830,7 +830,7 @@ config SERIAL_M32R_PLDSIO
config SERIAL_TXX9
bool "TMPTX39XX/49XX SIO support"
- depends HAS_TXX9_SERIAL
+ depends HAS_TXX9_SERIAL && BROKEN
select SERIAL_CORE
default y
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 2884b310e54d..978e12437e61 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -105,7 +105,7 @@ struct uart_amba_port {
unsigned int old_status;
};
-static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pl010_stop_tx(struct uart_port *port)
{
unsigned int cr;
@@ -114,7 +114,7 @@ static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
UART_PUT_CR(port, cr);
}
-static void pl010_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pl010_start_tx(struct uart_port *port)
{
unsigned int cr;
@@ -219,7 +219,7 @@ static void pl010_tx_chars(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- pl010_stop_tx(port, 0);
+ pl010_stop_tx(port);
return;
}
@@ -236,7 +236,7 @@ static void pl010_tx_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- pl010_stop_tx(port, 0);
+ pl010_stop_tx(port);
}
static void pl010_modem_status(struct uart_port *port)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 7db88ee18f75..56071309744c 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -74,7 +74,7 @@ struct uart_amba_port {
unsigned int old_status;
};
-static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -82,7 +82,7 @@ static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
writew(uap->im, uap->port.membase + UART011_IMSC);
}
-static void pl011_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pl011_start_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -184,7 +184,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
- pl011_stop_tx(&uap->port, 0);
+ pl011_stop_tx(&uap->port);
return;
}
@@ -201,7 +201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
uart_write_wakeup(&uap->port);
if (uart_circ_empty(xmit))
- pl011_stop_tx(&uap->port, 0);
+ pl011_stop_tx(&uap->port);
}
static void pl011_modem_status(struct uart_amba_port *uap)
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index 6104aeef1243..a274ebf256a1 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -200,7 +200,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
}
-static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -210,7 +210,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -337,7 +337,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port, 0);
+ serial8250_stop_tx(&up->port);
return;
}
@@ -356,7 +356,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
DEBUG_INTR("THRE...");
if (uart_circ_empty(xmit))
- serial8250_stop_tx(&up->port, 0);
+ serial8250_stop_tx(&up->port);
}
static _INLINE_ void check_modem_status(struct uart_8250_port *up)
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index e92522b33c48..d822896b488c 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -69,8 +69,7 @@
#define tx_enabled(port) ((port)->unused[0])
-static void
-clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void clps711xuart_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
@@ -78,8 +77,7 @@ clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
+static void clps711xuart_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(TX_IRQ(port));
@@ -165,7 +163,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port, 0);
+ clps711xuart_stop_tx(port);
return IRQ_HANDLED;
}
@@ -182,7 +180,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port, 0);
+ clps711xuart_stop_tx(port);
return IRQ_HANDLED;
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index d639ac92a117..25825f2aba22 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -124,7 +124,7 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
/*
* Stop transmitter
*/
-static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void cpm_uart_stop_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
@@ -141,7 +141,7 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
/*
* Start transmitter
*/
-static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+static void cpm_uart_start_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
@@ -403,10 +403,8 @@ static int cpm_uart_startup(struct uart_port *port)
inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
{
- unsigned long target_jiffies = jiffies + pinfo->wait_closing;
-
- while (!time_after(jiffies, target_jiffies))
- schedule();
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(pinfo->wait_closing);
}
/*
@@ -425,9 +423,12 @@ static void cpm_uart_shutdown(struct uart_port *port)
/* If the port is not the console, disable Rx and Tx. */
if (!(pinfo->flags & FLAG_CONSOLE)) {
/* Wait for all the BDs marked sent */
- while(!cpm_uart_tx_empty(port))
+ while(!cpm_uart_tx_empty(port)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(2);
- if(pinfo->wait_closing)
+ }
+
+ if (pinfo->wait_closing)
cpm_uart_wait_until_send(pinfo);
/* Stop uarts */
@@ -623,7 +624,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- cpm_uart_stop_tx(port, 0);
+ cpm_uart_stop_tx(port);
return 0;
}
@@ -656,7 +657,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
- cpm_uart_stop_tx(port, 0);
+ cpm_uart_stop_tx(port);
return 0;
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index c4c8f4b44f53..15ad58d94889 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -142,6 +142,14 @@ 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;
@@ -149,6 +157,7 @@ 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;
@@ -257,6 +266,7 @@ int cpm_uart_init_portdesc(void)
cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
cpm_uart_ports[UART_SMC1].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
+ *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
cpm_uart_ports[UART_SMC1].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[0];
cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
@@ -269,6 +279,7 @@ int cpm_uart_init_portdesc(void)
cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
cpm_uart_ports[UART_SMC2].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
+ *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
cpm_uart_ports[UART_SMC2].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[1];
cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 23b8871e74cc..40d3e7139cfe 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -446,7 +446,6 @@ static char *serial_version = "$Revision: 1.25 $";
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <linux/delay.h>
@@ -5041,17 +5040,3 @@ rs_init(void)
/* this makes sure that rs_init is called during kernel boot */
module_init(rs_init);
-
-/*
- * register_serial and unregister_serial allows for serial ports to be
- * configured at run-time, to support PCMCIA modems.
- */
-int
-register_serial(struct serial_struct *req)
-{
- return -1;
-}
-
-void unregister_serial(int line)
-{
-}
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 97824eeeafae..e63b9dffc8d7 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -112,7 +112,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset,
* ------------------------------------------------------------
*/
-static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
+static void dz_stop_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
@@ -125,7 +125,7 @@ static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
spin_unlock_irqrestore(&dport->port.lock, flags);
}
-static void dz_start_tx(struct uart_port *uport, unsigned int tty_start)
+static void dz_start_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
@@ -290,7 +290,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)
}
/* if nothing to do or stopped or hardware stopped */
if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
- dz_stop_tx(&dport->port, 0);
+ dz_stop_tx(&dport->port);
return;
}
@@ -308,7 +308,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)
/* Are we done */
if (uart_circ_empty(xmit))
- dz_stop_tx(&dport->port, 0);
+ dz_stop_tx(&dport->port);
}
/*
@@ -440,7 +440,7 @@ static int dz_startup(struct uart_port *uport)
*/
static void dz_shutdown(struct uart_port *uport)
{
- dz_stop_tx(uport, 0);
+ dz_stop_tx(uport);
}
/*
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index c112b32764e8..eb31125c6a30 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -56,7 +56,6 @@
#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -989,18 +988,16 @@ static unsigned int icom_get_mctrl(struct uart_port *port)
return result;
}
-static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void icom_stop_tx(struct uart_port *port)
{
unsigned char cmdReg;
- if (tty_stop) {
- trace(ICOM_PORT, "STOP", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
- }
+ trace(ICOM_PORT, "STOP", 0);
+ cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+ writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
}
-static void icom_start_tx(struct uart_port *port, unsigned int tty_start)
+static void icom_start_tx(struct uart_port *port)
{
unsigned char cmdReg;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 01a8726a3f97..4c985e6b3784 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -124,7 +124,7 @@ static void imx_timeout(unsigned long data)
/*
* interrupts disabled on entry
*/
-static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void imx_stop_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
@@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
} while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
if (uart_circ_empty(xmit))
- imx_stop_tx(&sport->port, 0);
+ imx_stop_tx(&sport->port);
}
/*
* interrupts disabled on entry
*/
-static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
+static void imx_start_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
@@ -196,7 +196,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- imx_stop_tx(&sport->port, 0);
+ imx_stop_tx(&sport->port);
goto out;
}
@@ -291,13 +291,31 @@ static unsigned int imx_tx_empty(struct uart_port *port)
return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0;
}
+/*
+ * We have a modem side uart, so the meanings of RTS and CTS are inverted.
+ */
static unsigned int imx_get_mctrl(struct uart_port *port)
{
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+ struct imx_port *sport = (struct imx_port *)port;
+ unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
+
+ if (USR1((u32)sport->port.membase) & USR1_RTSS)
+ tmp |= TIOCM_CTS;
+
+ if (UCR2((u32)sport->port.membase) & UCR2_CTS)
+ tmp |= TIOCM_RTS;
+
+ return tmp;
}
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ struct imx_port *sport = (struct imx_port *)port;
+
+ if (mctrl & TIOCM_RTS)
+ UCR2((u32)sport->port.membase) |= UCR2_CTS;
+ else
+ UCR2((u32)sport->port.membase) &= ~UCR2_CTS;
}
/*
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 793c3a7cbe47..0c5c96a582b3 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2373,10 +2373,9 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port)
/**
* ic4_stop_tx - stop the transmitter
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_stop
*
*/
-static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop)
+static void ic4_stop_tx(struct uart_port *the_port)
{
}
@@ -2471,10 +2470,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port)
/**
* ic4_start_tx - Start transmitter, flush any output
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_start
*
*/
-static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop)
+static void ic4_start_tx(struct uart_port *the_port)
{
struct ioc4_port *port = get_ioc4_port(the_port);
unsigned long flags;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ea5bf4d4daa3..ef132349f310 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -592,7 +592,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
}
/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void ip22zilog_stop_tx(struct uart_port *port)
{
struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
@@ -600,7 +600,7 @@ static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start)
+static void ip22zilog_start_tx(struct uart_port *port)
{
struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 98de2258fd06..6fa0d62d6f68 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -113,7 +113,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
udelay(10);
}
-static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
+static void jsm_tty_start_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
@@ -125,7 +125,7 @@ static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
}
-static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void jsm_tty_stop_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 9b50560b9d16..b0ecc7537ce5 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -275,7 +275,7 @@ serial_out(struct uart_sio_port *up, int offset, int value)
__sio_out(value, offset);
}
-static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void m32r_sio_stop_tx(struct uart_port *port)
{
struct uart_sio_port *up = (struct uart_sio_port *)port;
@@ -285,7 +285,7 @@ static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void m32r_sio_start_tx(struct uart_port *port, unsigned int tty_start)
+static void m32r_sio_start_tx(struct uart_port *port)
{
#ifdef CONFIG_SERIAL_M32R_PLDSIO
struct uart_sio_port *up = (struct uart_sio_port *)port;
@@ -425,7 +425,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- m32r_sio_stop_tx(&up->port, 0);
+ m32r_sio_stop_tx(&up->port);
return;
}
@@ -446,7 +446,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up)
DEBUG_INTR("THRE...");
if (uart_circ_empty(xmit))
- m32r_sio_stop_tx(&up->port, 0);
+ m32r_sio_stop_tx(&up->port);
}
/*
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 8c40167778de..e2ebdcad553c 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -40,7 +40,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/semaphore.h>
#include <asm/delay.h>
#include <asm/coldfire.h>
@@ -64,8 +63,13 @@ struct timer_list mcfrs_timer_struct;
#endif
#if defined(CONFIG_HW_FEITH)
- #define CONSOLE_BAUD_RATE 38400
- #define DEFAULT_CBAUD B38400
+#define CONSOLE_BAUD_RATE 38400
+#define DEFAULT_CBAUD B38400
+#endif
+
+#if defined(CONFIG_MOD5272)
+#define CONSOLE_BAUD_RATE 115200
+#define DEFAULT_CBAUD B115200
#endif
#ifndef CONSOLE_BAUD_RATE
@@ -91,7 +95,7 @@ static struct tty_driver *mcfrs_serial_driver;
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
@@ -1511,7 +1515,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
*portp = (*portp & ~0x000000ff) | 0x00000055;
portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
*portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
volatile unsigned char *icrp, *uartp;
volatile unsigned long *imrp;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 2a5cf174ca30..a3cd0ee8486d 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -119,7 +119,7 @@ mpc52xx_uart_get_mctrl(struct uart_port *port)
}
static void
-mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+mpc52xx_uart_stop_tx(struct uart_port *port)
{
/* port->lock taken by caller */
port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
@@ -127,7 +127,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
static void
-mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+mpc52xx_uart_start_tx(struct uart_port *port)
{
/* port->lock taken by caller */
port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
@@ -485,7 +485,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
/* Nothing to do ? */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mpc52xx_uart_stop_tx(port,0);
+ mpc52xx_uart_stop_tx(port);
return 0;
}
@@ -504,7 +504,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
/* Maybe we're done after all */
if (uart_circ_empty(xmit)) {
- mpc52xx_uart_stop_tx(port,0);
+ mpc52xx_uart_stop_tx(port);
return 0;
}
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index e43276c6a954..efe79b1fd431 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -1072,18 +1072,18 @@ mpsc_get_mctrl(struct uart_port *port)
}
static void
-mpsc_stop_tx(struct uart_port *port, uint tty_start)
+mpsc_stop_tx(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- pr_debug("mpsc_stop_tx[%d]: tty_start: %d\n", port->line, tty_start);
+ pr_debug("mpsc_stop_tx[%d]\n", port->line);
mpsc_freeze(pi);
return;
}
static void
-mpsc_start_tx(struct uart_port *port, uint tty_start)
+mpsc_start_tx(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
@@ -1091,7 +1091,7 @@ mpsc_start_tx(struct uart_port *port, uint tty_start)
mpsc_copy_tx_data(pi);
mpsc_sdma_start_tx(pi);
- pr_debug("mpsc_start_tx[%d]: tty_start: %d\n", port->line, tty_start);
+ pr_debug("mpsc_start_tx[%d]\n", port->line);
return;
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index dadd7e19714e..189064607709 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -111,22 +111,20 @@ static unsigned int mux_get_mctrl(struct uart_port *port)
/**
* mux_stop_tx - Stop transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_stop: tty layer issue this command?
*
* The Serial MUX does not support this function.
*/
-static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void mux_stop_tx(struct uart_port *port)
{
}
/**
* mux_start_tx - Start transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_start: tty layer issue this command?
*
* The Serial Mux does not support this function.
*/
-static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
+static void mux_start_tx(struct uart_port *port)
{
}
@@ -181,7 +179,7 @@ static void mux_write(struct uart_port *port)
}
if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
return;
}
@@ -202,7 +200,7 @@ static void mux_write(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
}
/**
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 7db2f37532cf..5ddd8ab1f108 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -630,11 +630,10 @@ static unsigned int pmz_get_mctrl(struct uart_port *port)
/*
* Stop TX side. Dealt like sunzilog at next Tx interrupt,
- * though for DMA, we will have to do a bit more. What is
- * the meaning of the tty_stop bit ? XXX
+ * though for DMA, we will have to do a bit more.
* The port lock is held and interrupts are disabled.
*/
-static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pmz_stop_tx(struct uart_port *port)
{
to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED;
}
@@ -643,7 +642,7 @@ static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop)
* Kick the Tx side.
* The port lock is held and interrupts are disabled.
*/
-static void pmz_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pmz_start_tx(struct uart_port *port)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned char status;
@@ -1601,7 +1600,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
return 0;
}
- if (pm_state == mdev->ofdev.dev.power.power_state || pm_state < 2)
+ if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
return 0;
pmz_debug("suspend, switching to state %d\n", pm_state);
@@ -1661,7 +1660,7 @@ static int pmz_resume(struct macio_dev *mdev)
if (uap == NULL)
return 0;
- if (mdev->ofdev.dev.power.power_state == 0)
+ if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
return 0;
pmz_debug("resume, switching to state 0\n");
@@ -1714,7 +1713,7 @@ static int pmz_resume(struct macio_dev *mdev)
pmz_debug("resume, switching complete\n");
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
return 0;
}
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 461c81c93207..eaa0af835290 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -80,7 +80,7 @@ static void serial_pxa_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
-static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial_pxa_stop_tx(struct uart_port *port)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
@@ -185,7 +185,7 @@ static void transmit_chars(struct uart_pxa_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_pxa_stop_tx(&up->port, 0);
+ serial_pxa_stop_tx(&up->port);
return;
}
@@ -203,10 +203,10 @@ static void transmit_chars(struct uart_pxa_port *up)
if (uart_circ_empty(xmit))
- serial_pxa_stop_tx(&up->port, 0);
+ serial_pxa_stop_tx(&up->port);
}
-static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial_pxa_start_tx(struct uart_port *port)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 7365d4b50b95..c361c6fb0809 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -246,8 +246,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
}
-static void
-s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void s3c24xx_serial_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
@@ -257,8 +256,7 @@ s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-s3c24xx_serial_start_tx(struct uart_port *port, unsigned int tty_start)
+static void s3c24xx_serial_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
if (port->flags & UPF_CONS_FLOW)
@@ -424,7 +422,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re
*/
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- s3c24xx_serial_stop_tx(port, 0);
+ s3c24xx_serial_stop_tx(port);
goto out;
}
@@ -443,7 +441,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- s3c24xx_serial_stop_tx(port, 0);
+ s3c24xx_serial_stop_tx(port);
out:
return IRQ_HANDLED;
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 98641c3f5ab9..1225b14f6e9d 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -145,7 +145,7 @@ static void sa1100_timeout(unsigned long data)
/*
* interrupts disabled on entry
*/
-static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sa1100_stop_tx(struct uart_port *port)
{
struct sa1100_port *sport = (struct sa1100_port *)port;
u32 utcr3;
@@ -158,7 +158,7 @@ static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
/*
* interrupts may not be disabled on entry
*/
-static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sa1100_start_tx(struct uart_port *port)
{
struct sa1100_port *sport = (struct sa1100_port *)port;
unsigned long flags;
@@ -264,7 +264,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
sa1100_mctrl_check(sport);
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- sa1100_stop_tx(&sport->port, 0);
+ sa1100_stop_tx(&sport->port);
return;
}
@@ -284,7 +284,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit))
- sa1100_stop_tx(&sport->port, 0);
+ sa1100_stop_tx(&sport->port);
}
static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 54699c3a00ab..2d8622eef701 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -80,7 +80,7 @@ static void uart_stop(struct tty_struct *tty)
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- port->ops->stop_tx(port, 1);
+ port->ops->stop_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -91,7 +91,7 @@ static void __uart_start(struct tty_struct *tty)
if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
!tty->stopped && !tty->hw_stopped)
- port->ops->start_tx(port, 1);
+ port->ops->start_tx(port);
}
static void uart_start(struct tty_struct *tty)
@@ -542,7 +542,7 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
port->x_char = ch;
if (ch) {
spin_lock_irqsave(&port->lock, flags);
- port->ops->start_tx(port, 0);
+ port->ops->start_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
}
}
@@ -1146,7 +1146,7 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios
spin_lock_irqsave(&state->port->lock, flags);
if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
tty->hw_stopped = 1;
- state->port->ops->stop_tx(state->port, 0);
+ state->port->ops->stop_tx(state->port);
}
spin_unlock_irqrestore(&state->port->lock, flags);
}
@@ -1869,7 +1869,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
struct uart_ops *ops = port->ops;
spin_lock_irq(&port->lock);
- ops->stop_tx(port, 0);
+ ops->stop_tx(port);
ops->set_mctrl(port, 0);
ops->stop_rx(port);
spin_unlock_irq(&port->lock);
@@ -1935,7 +1935,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
uart_change_speed(state, NULL);
spin_lock_irq(&port->lock);
ops->set_mctrl(port, port->mctrl);
- ops->start_tx(port, 0);
+ ops->start_tx(port);
spin_unlock_irq(&port->lock);
}
@@ -1947,21 +1947,29 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
static inline void
uart_report_port(struct uart_driver *drv, struct uart_port *port)
{
- printk("%s%d", drv->dev_name, port->line);
- printk(" at ");
+ char address[64];
+
switch (port->iotype) {
case UPIO_PORT:
- printk("I/O 0x%x", port->iobase);
+ snprintf(address, sizeof(address),
+ "I/O 0x%x", port->iobase);
break;
case UPIO_HUB6:
- printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+ snprintf(address, sizeof(address),
+ "I/O 0x%x offset 0x%x", port->iobase, port->hub6);
break;
case UPIO_MEM:
case UPIO_MEM32:
- printk("MMIO 0x%lx", port->mapbase);
+ snprintf(address, sizeof(address),
+ "MMIO 0x%lx", port->mapbase);
+ break;
+ default:
+ strlcpy(address, "*unknown*", sizeof(address));
break;
}
- printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
+
+ printk(KERN_INFO "%s%d at %s (irq = %d) is a %s\n",
+ drv->dev_name, port->line, address, port->irq, uart_type(port));
}
static void
@@ -2289,143 +2297,11 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
}
EXPORT_SYMBOL(uart_match_port);
-/*
- * Try to find an unused uart_state slot for a port.
- */
-static struct uart_state *
-uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
-{
- int i;
-
- /*
- * First, find a port entry which matches. Note: if we do
- * find a matching entry, and it has a non-zero use count,
- * then we can't register the port.
- */
- for (i = 0; i < drv->nr; i++)
- if (uart_match_port(drv->state[i].port, port))
- return &drv->state[i];
-
- /*
- * We didn't find a matching entry, so look for the first
- * free entry. We look for one which hasn't been previously
- * used (indicated by zero iobase).
- */
- for (i = 0; i < drv->nr; i++)
- if (drv->state[i].port->type == PORT_UNKNOWN &&
- drv->state[i].port->iobase == 0 &&
- drv->state[i].count == 0)
- return &drv->state[i];
-
- /*
- * That also failed. Last resort is to find any currently
- * entry which doesn't have a real port associated with it.
- */
- for (i = 0; i < drv->nr; i++)
- if (drv->state[i].port->type == PORT_UNKNOWN &&
- drv->state[i].count == 0)
- return &drv->state[i];
-
- return NULL;
-}
-
-/**
- * uart_register_port: register uart settings with a port
- * @drv: pointer to the uart low level driver structure for this port
- * @port: uart port structure describing the port
- *
- * Register UART settings with the specified low level driver. Detect
- * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
- * IRQ if UPF_AUTO_IRQ is set.
- *
- * We try to pick the same port for the same IO base address, so that
- * when a modem is plugged in, unplugged and plugged back in, it gets
- * allocated the same port.
- *
- * Returns negative error, or positive line number.
- */
-int uart_register_port(struct uart_driver *drv, struct uart_port *port)
-{
- struct uart_state *state;
- int ret;
-
- down(&port_sem);
-
- state = uart_find_match_or_unused(drv, port);
-
- if (state) {
- /*
- * Ok, we've found a line that we can use.
- *
- * If we find a port that matches this one, and it appears
- * to be in-use (even if it doesn't have a type) we shouldn't
- * alter it underneath itself - the port may be open and
- * trying to do useful work.
- */
- if (uart_users(state) != 0) {
- ret = -EBUSY;
- goto out;
- }
-
- /*
- * If the port is already initialised, don't touch it.
- */
- if (state->port->type == PORT_UNKNOWN) {
- state->port->iobase = port->iobase;
- state->port->membase = port->membase;
- state->port->irq = port->irq;
- state->port->uartclk = port->uartclk;
- state->port->fifosize = port->fifosize;
- state->port->regshift = port->regshift;
- state->port->iotype = port->iotype;
- state->port->flags = port->flags;
- state->port->line = state - drv->state;
- state->port->mapbase = port->mapbase;
-
- uart_configure_port(drv, state, state->port);
- }
-
- ret = state->port->line;
- } else
- ret = -ENOSPC;
- out:
- up(&port_sem);
- return ret;
-}
-
-/**
- * uart_unregister_port - de-allocate a port
- * @drv: pointer to the uart low level driver structure for this port
- * @line: line index previously returned from uart_register_port()
- *
- * Hang up the specified line associated with the low level driver,
- * and mark the port as unused.
- */
-void uart_unregister_port(struct uart_driver *drv, int line)
-{
- struct uart_state *state;
-
- if (line < 0 || line >= drv->nr) {
- printk(KERN_ERR "Attempt to unregister ");
- printk("%s%d", drv->dev_name, line);
- printk("\n");
- return;
- }
-
- state = drv->state + line;
-
- down(&port_sem);
- uart_unconfigure_port(drv, state);
- up(&port_sem);
-}
-
EXPORT_SYMBOL(uart_write_wakeup);
EXPORT_SYMBOL(uart_register_driver);
EXPORT_SYMBOL(uart_unregister_driver);
EXPORT_SYMBOL(uart_suspend_port);
EXPORT_SYMBOL(uart_resume_port);
-EXPORT_SYMBOL(uart_register_port);
-EXPORT_SYMBOL(uart_unregister_port);
EXPORT_SYMBOL(uart_add_one_port);
EXPORT_SYMBOL(uart_remove_one_port);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 56f269b6bfb1..8302376800c0 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -112,13 +112,12 @@ struct uart_port_lh7a40x {
unsigned int statusPrev; /* Most recently read modem status */
};
-static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop)
+static void lh7a40xuart_stop_tx (struct uart_port* port)
{
BIT_CLR (port, UART_R_INTEN, TxInt);
}
-static void lh7a40xuart_start_tx (struct uart_port* port,
- unsigned int tty_start)
+static void lh7a40xuart_start_tx (struct uart_port* port)
{
BIT_SET (port, UART_R_INTEN, TxInt);
@@ -208,7 +207,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
return;
}
if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
- lh7a40xuart_stop_tx (port, 0);
+ lh7a40xuart_stop_tx (port);
return;
}
@@ -230,7 +229,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
uart_write_wakeup (port);
if (uart_circ_empty (xmit))
- lh7a40xuart_stop_tx (port, 0);
+ lh7a40xuart_stop_tx (port);
}
static void lh7a40xuart_modem_status (struct uart_port* port)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index d085030df70b..f10c86d60b64 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -31,6 +31,8 @@
* 1.01 Set fifosize to make tx_empry called properly.
* Use standard uart_get_divisor.
* 1.02 Cleanup. (import 8250.c changes)
+ * 1.03 Fix low-latency mode. (import 8250.c changes)
+ * 1.04 Remove usage of deprecated functions, cleanup.
*/
#include <linux/config.h>
@@ -54,7 +56,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-static char *serial_version = "1.02";
+static char *serial_version = "1.04";
static char *serial_name = "TX39/49 Serial driver";
#define PASS_LIMIT 256
@@ -86,9 +88,9 @@ static char *serial_name = "TX39/49 Serial driver";
*/
#ifdef ENABLE_SERIAL_TXX9_PCI
#define NR_PCI_BOARDS 4
-#define UART_NR (2 + NR_PCI_BOARDS)
+#define UART_NR (4 + NR_PCI_BOARDS)
#else
-#define UART_NR 2
+#define UART_NR 4
#endif
struct uart_txx9_port {
@@ -253,7 +255,7 @@ sio_quot_set(struct uart_txx9_port *up, int quot)
sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
}
-static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial_txx9_stop_tx(struct uart_port *port)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
unsigned long flags;
@@ -263,7 +265,7 @@ static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop)
spin_unlock_irqrestore(&up->port.lock, flags);
}
-static void serial_txx9_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial_txx9_start_tx(struct uart_port *port)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
unsigned long flags;
@@ -304,8 +306,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
/* The following is not allowed by the tty layer and
unsafe. It should be fixed ASAP */
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if(tty->low_latency)
+ if (tty->low_latency) {
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ }
/* If this failed then we will throw away the
bytes but must do so to clear interrupts */
}
@@ -356,7 +361,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
ignore_char:
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
*status = disr;
}
@@ -372,7 +379,7 @@ static inline void transmit_chars(struct uart_txx9_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_txx9_stop_tx(&up->port, 0);
+ serial_txx9_stop_tx(&up->port);
return;
}
@@ -389,7 +396,7 @@ static inline void transmit_chars(struct uart_txx9_port *up)
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- serial_txx9_stop_tx(&up->port, 0);
+ serial_txx9_stop_tx(&up->port);
}
static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -667,17 +674,8 @@ serial_txx9_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
- if (state) {
- /* sleep */
-
- if (up->pm)
- up->pm(port, state, oldstate);
- } else {
- /* wake */
-
- if (up->pm)
- up->pm(port, state, oldstate);
- }
+ if (up->pm)
+ up->pm(port, state, oldstate);
}
static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -979,14 +977,6 @@ static int __init serial_txx9_console_init(void)
}
console_initcall(serial_txx9_console_init);
-static int __init serial_txx9_late_console_init(void)
-{
- if (!(serial_txx9_console.flags & CON_ENABLED))
- register_console(&serial_txx9_console);
- return 0;
-}
-late_initcall(serial_txx9_late_console_init);
-
#define SERIAL_TXX9_CONSOLE &serial_txx9_console
#else
#define SERIAL_TXX9_CONSOLE NULL
@@ -1039,6 +1029,73 @@ static void serial_txx9_resume_port(int line)
uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
}
+static DECLARE_MUTEX(serial_txx9_sem);
+
+/**
+ * serial_txx9_register_port - register a serial port
+ * @port: serial port template
+ *
+ * Configure the serial port specified by the request.
+ *
+ * The port is then probed and if necessary the IRQ is autodetected
+ * If this fails an error is returned.
+ *
+ * On success the port is ready to use and the line number is returned.
+ */
+static int __devinit serial_txx9_register_port(struct uart_port *port)
+{
+ int i;
+ struct uart_txx9_port *uart;
+ int ret = -ENOSPC;
+
+ down(&serial_txx9_sem);
+ for (i = 0; i < UART_NR; i++) {
+ uart = &serial_txx9_ports[i];
+ if (uart->port.type == PORT_UNKNOWN)
+ break;
+ }
+ if (i < UART_NR) {
+ uart_remove_one_port(&serial_txx9_reg, &uart->port);
+ uart->port.iobase = port->iobase;
+ uart->port.membase = port->membase;
+ uart->port.irq = port->irq;
+ uart->port.uartclk = port->uartclk;
+ uart->port.iotype = port->iotype;
+ uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
+ uart->port.mapbase = port->mapbase;
+ if (port->dev)
+ uart->port.dev = port->dev;
+ ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
+ }
+ up(&serial_txx9_sem);
+ return ret;
+}
+
+/**
+ * serial_txx9_unregister_port - remove a txx9 serial port at runtime
+ * @line: serial line number
+ *
+ * Remove one serial port. This may not be called from interrupt
+ * context. We hand the port back to the our control.
+ */
+static void __devexit serial_txx9_unregister_port(int line)
+{
+ struct uart_txx9_port *uart = &serial_txx9_ports[line];
+
+ down(&serial_txx9_sem);
+ uart_remove_one_port(&serial_txx9_reg, &uart->port);
+ uart->port.flags = 0;
+ uart->port.type = PORT_UNKNOWN;
+ uart->port.iobase = 0;
+ uart->port.mapbase = 0;
+ uart->port.membase = 0;
+ uart->port.dev = NULL;
+ uart_add_one_port(&serial_txx9_reg, &uart->port);
+ up(&serial_txx9_sem);
+}
+
/*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
@@ -1056,13 +1113,13 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
memset(&port, 0, sizeof(port));
port.ops = &serial_txx9_pops;
- port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called */
port.flags |= UPF_TXX9_HAVE_CTS_LINE;
port.uartclk = 66670000;
port.irq = dev->irq;
port.iotype = UPIO_PORT;
port.iobase = pci_resource_start(dev, 1);
- line = uart_register_port(&serial_txx9_reg, &port);
+ port.dev = &dev->dev;
+ line = serial_txx9_register_port(&port);
if (line < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
}
@@ -1078,7 +1135,7 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
if (line) {
- uart_unregister_port(&serial_txx9_reg, line);
+ serial_txx9_unregister_port(line);
pci_disable_device(dev);
}
}
@@ -1089,6 +1146,8 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
if (line)
serial_txx9_suspend_port(line);
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@@ -1096,8 +1155,13 @@ static int pciserial_txx9_resume_one(struct pci_dev *dev)
{
int line = (int)(long)pci_get_drvdata(dev);
- if (line)
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ if (line) {
+ pci_enable_device(dev);
serial_txx9_resume_port(line);
+ }
return 0;
}
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index ad5b776d779b..512266307866 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -79,8 +79,8 @@ static struct sci_port *serial_console_port = 0;
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
/* Function prototypes */
-static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop);
-static void sci_start_tx(struct uart_port *port, unsigned int tty_start);
+static void sci_stop_tx(struct uart_port *port);
+static void sci_start_tx(struct uart_port *port);
static void sci_start_rx(struct uart_port *port, unsigned int tty_start);
static void sci_stop_rx(struct uart_port *port);
static int sci_request_irq(struct sci_port *port);
@@ -455,7 +455,7 @@ static void sci_transmit_chars(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
- sci_stop_tx(port, 0);
+ sci_stop_tx(port);
} else {
local_irq_save(flags);
ctrl = sci_in(port, SCSCR);
@@ -900,7 +900,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
}
-static void sci_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sci_start_tx(struct uart_port *port)
{
struct sci_port *s = &sci_ports[port->line];
@@ -909,7 +909,7 @@ static void sci_start_tx(struct uart_port *port, unsigned int tty_start)
enable_irq(s->irqs[SCIx_TXI_IRQ]);
}
-static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sci_stop_tx(struct uart_port *port)
{
unsigned long flags;
unsigned short ctrl;
@@ -978,7 +978,7 @@ static void sci_shutdown(struct uart_port *port)
struct sci_port *s = &sci_ports[port->line];
sci_stop_rx(port);
- sci_stop_tx(port, 1);
+ sci_stop_tx(port);
sci_free_irq(s);
#if defined(__H8300S__)
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 12d1f14e78ce..313f9df24a2d 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -259,10 +259,9 @@ static unsigned int snp_tx_empty(struct uart_port *port)
/**
* snp_stop_tx - stop the transmitter - no-op for us
* @port: Port to operat eon - we ignore - no-op function
- * @tty_stop: Set to 1 if called via uart_stop
*
*/
-static void snp_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void snp_stop_tx(struct uart_port *port)
{
}
@@ -325,10 +324,9 @@ static void snp_stop_rx(struct uart_port *port)
/**
* snp_start_tx - Start transmitter
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_start
*
*/
-static void snp_start_tx(struct uart_port *port, unsigned int tty_stop)
+static void snp_start_tx(struct uart_port *port)
{
if (sal_console_port.sc_ops->sal_wakeup_transmit)
sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port,
@@ -615,7 +613,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw)
uart_write_wakeup(&port->sc_port);
if (uart_circ_empty(xmit))
- snp_stop_tx(&port->sc_port, 0); /* no-op for us */
+ snp_stop_tx(&port->sc_port); /* no-op for us */
}
/**
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 8d198880756a..e971156daa60 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -245,7 +245,7 @@ receive_chars(struct uart_sunsab_port *up,
return tty;
}
-static void sunsab_stop_tx(struct uart_port *, unsigned int);
+static void sunsab_stop_tx(struct uart_port *);
static void sunsab_tx_idle(struct uart_sunsab_port *);
static void transmit_chars(struct uart_sunsab_port *up,
@@ -301,7 +301,7 @@ static void transmit_chars(struct uart_sunsab_port *up,
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- sunsab_stop_tx(&up->port, 0);
+ sunsab_stop_tx(&up->port);
}
static void check_status(struct uart_sunsab_port *up,
@@ -448,7 +448,7 @@ static unsigned int sunsab_get_mctrl(struct uart_port *port)
}
/* port->lock held by caller. */
-static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sunsab_stop_tx(struct uart_port *port)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
@@ -476,7 +476,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *up)
}
/* port->lock held by caller. */
-static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunsab_start_tx(struct uart_port *port)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
struct circ_buf *xmit = &up->port.info->xmit;
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index d57a3553aea3..5959e6755a81 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -255,21 +255,30 @@ static void disable_rsa(struct uart_sunsu_port *up)
}
#endif /* CONFIG_SERIAL_8250_RSA */
-static void sunsu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static inline void __stop_tx(struct uart_sunsu_port *p)
+{
+ if (p->ier & UART_IER_THRI) {
+ p->ier &= ~UART_IER_THRI;
+ serial_out(p, UART_IER, p->ier);
+ }
+}
+
+static void sunsu_stop_tx(struct uart_port *port)
{
struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
- if (up->port.type == PORT_16C950 && tty_stop) {
+ __stop_tx(up);
+
+ /*
+ * We really want to stop the transmitter from sending.
+ */
+ if (up->port.type == PORT_16C950) {
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
}
-static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunsu_start_tx(struct uart_port *port)
{
struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
@@ -277,10 +286,11 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
up->ier |= UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
+
/*
- * We only do this from uart_start
+ * Re-enable the transmitter if we disabled it.
*/
- if (tty_start && up->port.type == PORT_16C950) {
+ if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
up->acr &= ~UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
@@ -413,8 +423,12 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
up->port.x_char = 0;
return;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- sunsu_stop_tx(&up->port, 0);
+ if (uart_tx_stopped(&up->port)) {
+ sunsu_stop_tx(&up->port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
+ __stop_tx(up);
return;
}
@@ -431,7 +445,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- sunsu_stop_tx(&up->port, 0);
+ __stop_tx(up);
}
static _INLINE_ void check_modem_status(struct uart_sunsu_port *up)
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index bff42a7b89d0..d75445738c88 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -684,7 +684,7 @@ static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sunzilog_stop_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
@@ -692,7 +692,7 @@ static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunzilog_start_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
index 186f1300cead..47b504ff38b2 100644
--- a/drivers/serial/uart00.c
+++ b/drivers/serial/uart00.c
@@ -87,7 +87,7 @@
#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
-static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void uart00_stop_tx(struct uart_port *port)
{
UART_PUT_IEC(port, UART_IEC_TIE_MSK);
}
@@ -199,7 +199,7 @@ static void uart00_tx_chars(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- uart00_stop_tx(port, 0);
+ uart00_stop_tx(port);
return;
}
@@ -218,10 +218,10 @@ static void uart00_tx_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- uart00_stop_tx(port, 0);
+ uart00_stop_tx(port);
}
-static void uart00_start_tx(struct uart_port *port, unsigned int tty_start)
+static void uart00_start_tx(struct uart_port *port)
{
UART_PUT_IES(port, UART_IES_TIE_MSK);
uart00_tx_chars(port);
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index bb482780a41d..9378895a8d56 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -240,7 +240,7 @@ console_initcall(v850e_uart_console_init);
/* TX/RX interrupt handlers. */
-static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
+static void v850e_uart_stop_tx (struct uart_port *port);
void v850e_uart_tx (struct uart_port *port)
{
@@ -339,14 +339,14 @@ static unsigned v850e_uart_get_mctrl (struct uart_port *port)
return mctrl;
}
-static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start)
+static void v850e_uart_start_tx (struct uart_port *port)
{
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
v850e_uart_tx (port);
v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));
}
-static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
+static void v850e_uart_stop_tx (struct uart_port *port)
{
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
}
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 1f985327b0d4..0c5d65a08f6e 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -284,7 +284,7 @@ static unsigned int siu_get_mctrl(struct uart_port *port)
return mctrl;
}
-static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void siu_stop_tx(struct uart_port *port)
{
unsigned long flags;
uint8_t ier;
@@ -298,7 +298,7 @@ static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
spin_unlock_irqrestore(&port->lock, flags);
}
-static void siu_start_tx(struct uart_port *port, unsigned int tty_start)
+static void siu_start_tx(struct uart_port *port)
{
unsigned long flags;
uint8_t ier;
@@ -458,7 +458,7 @@ static inline void transmit_chars(struct uart_port *port)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- siu_stop_tx(port, 0);
+ siu_stop_tx(port);
return;
}
@@ -474,7 +474,7 @@ static inline void transmit_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- siu_stop_tx(port, 0);
+ siu_stop_tx(port);
}
static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 4382ee60b6a8..6bed8713897e 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1683,7 +1683,7 @@ static void __init probe_sccs(void)
#ifndef CONFIG_SERIAL_DEC_CONSOLE
/*
* We're called early and memory managment isn't up, yet.
- * Thus check_region would fail.
+ * Thus request_region would fail.
*/
if (!request_region((unsigned long)
zs_channels[n_channels].control,
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index f2c9fa423d40..f6704688ee8c 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -774,10 +774,7 @@ static int ixj_wink(IXJ *j)
j->pots_winkstart = jiffies;
SLIC_SetState(PLD_SLIC_STATE_OC, j);
- while (time_before(jiffies, j->pots_winkstart + j->winktime)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(jiffies_to_msecs(j->winktime));
SLIC_SetState(slicnow, j);
return 0;
@@ -1912,7 +1909,6 @@ static int ixj_pcmcia_cable_check(IXJ *j)
static int ixj_hookstate(IXJ *j)
{
- unsigned long det;
int fOffHook = 0;
switch (j->cardtype) {
@@ -1943,11 +1939,7 @@ static int ixj_hookstate(IXJ *j)
j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
if (j->flags.ringing || j->flags.cringing) {
if (!in_interrupt()) {
- det = jiffies + (hertz / 50);
- while (time_before(jiffies, det)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(20);
}
SLIC_GetState(j);
if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
@@ -2062,7 +2054,7 @@ static void ixj_ring_start(IXJ *j)
static int ixj_ring(IXJ *j)
{
char cntr;
- unsigned long jif, det;
+ unsigned long jif;
j->flags.ringing = 1;
if (ixj_hookstate(j) & 1) {
@@ -2070,7 +2062,6 @@ static int ixj_ring(IXJ *j)
j->flags.ringing = 0;
return 1;
}
- det = 0;
for (cntr = 0; cntr < j->maxrings; cntr++) {
jif = jiffies + (1 * hertz);
ixj_ring_on(j);
@@ -2080,8 +2071,7 @@ static int ixj_ring(IXJ *j)
j->flags.ringing = 0;
return 1;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (signal_pending(current))
break;
}
@@ -2089,20 +2079,13 @@ static int ixj_ring(IXJ *j)
ixj_ring_off(j);
while (time_before(jiffies, jif)) {
if (ixj_hookstate(j) & 1) {
- det = jiffies + (hertz / 100);
- while (time_before(jiffies, det)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- }
+ msleep(10);
if (ixj_hookstate(j) & 1) {
j->flags.ringing = 0;
return 1;
}
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (signal_pending(current))
break;
}
@@ -2168,10 +2151,8 @@ static int ixj_release(struct inode *inode, struct file *file_p)
* Set up locks to ensure that only one process is talking to the DSP at a time.
* This is necessary to keep the DSP from locking up.
*/
- while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if (ixjdebug & 0x0002)
printk(KERN_INFO "Closing board %d\n", NUM(inode));
@@ -3301,14 +3282,10 @@ static void ixj_write_cidcw(IXJ *j)
ixj_play_tone(j, 23);
clear_bit(j->board, &j->busyflags);
- while(j->tone_state) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(j->tone_state)
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if(ixjdebug & 0x0200) {
printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies);
}
@@ -3328,14 +3305,10 @@ static void ixj_write_cidcw(IXJ *j)
ixj_play_tone(j, 24);
clear_bit(j->board, &j->busyflags);
- while(j->tone_state) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(j->tone_state)
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if(ixjdebug & 0x0200) {
printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies);
}
@@ -3343,14 +3316,10 @@ static void ixj_write_cidcw(IXJ *j)
j->cidcw_wait = jiffies + ((50 * hertz) / 100);
clear_bit(j->board, &j->busyflags);
- while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait))
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
j->cidcw_wait = 0;
if(!j->flags.cidcw_ack) {
if(ixjdebug & 0x0200) {
@@ -6125,10 +6094,8 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
* Set up locks to ensure that only one process is talking to the DSP at a time.
* This is necessary to keep the DSP from locking up.
*/
- while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if (ixjdebug & 0x0040)
printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
if (minor >= IXJMAX) {
@@ -6694,8 +6661,6 @@ static struct file_operations ixj_fops =
static int ixj_linetest(IXJ *j)
{
- unsigned long jifwait;
-
j->flags.pstncheck = 1; /* Testing */
j->flags.pstn_present = 0; /* Assume the line is not there */
@@ -6726,11 +6691,7 @@ static int ixj_linetest(IXJ *j)
outb_p(j->pld_scrw.byte, j->XILINXbase);
daa_set_mode(j, SOP_PU_CONVERSATION);
- jifwait = jiffies + hertz;
- while (time_before(jiffies, jifwait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(1000);
daa_int_read(j);
daa_set_mode(j, SOP_PU_RESET);
if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6750,11 +6711,7 @@ static int ixj_linetest(IXJ *j)
j->pld_slicw.bits.rly3 = 0;
outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
daa_set_mode(j, SOP_PU_CONVERSATION);
- jifwait = jiffies + hertz;
- while (time_before(jiffies, jifwait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(1000);
daa_int_read(j);
daa_set_mode(j, SOP_PU_RESET);
if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6783,7 +6740,6 @@ static int ixj_linetest(IXJ *j)
static int ixj_selfprobe(IXJ *j)
{
unsigned short cmd;
- unsigned long jif;
int cnt;
BYTES bytes;
@@ -6933,29 +6889,13 @@ static int ixj_selfprobe(IXJ *j)
} else {
if (j->cardtype == QTI_LINEJACK) {
LED_SetState(0x1, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x2, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x4, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x8, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x0, j);
daa_get_version(j);
if (ixjdebug & 0x0002)
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 8e184e2641cb..79861ee12a29 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE,
cxacru_blocking_completion, &instance->rcv_done, 1);
- instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_fill_int_urb(instance->snd_urb,
usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
instance->snd_buf, PAGE_SIZE,
cxacru_blocking_completion, &instance->snd_done, 4);
- instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;
init_MUTEX(&instance->cm_serialize);
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index bb1db1959854..c466739428b2 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -960,7 +960,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
intf->altsetting->desc.bInterfaceNumber);
/* instance init */
- instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
+ instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
if (!instance) {
dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
return -ENOMEM;
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 0561d0234f23..333e39bb105f 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -4,9 +4,22 @@
comment "USB Device Class drivers"
depends on USB
+config OBSOLETE_OSS_USB_DRIVER
+ bool "Obsolete OSS USB drivers"
+ depends on USB && SOUND
+ help
+ This option enables support for the obsolete USB Audio and Midi
+ 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 of missing support in the ALSA drivers.
+
+ If unsure, say N.
+
config USB_AUDIO
tristate "USB Audio support"
- depends on USB && SOUND
+ depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
help
Say Y here if you want to connect USB audio equipment such as
speakers to your computer's USB port. You only need this if you use
@@ -40,10 +53,12 @@ config USB_BLUETOOTH_TTY
config USB_MIDI
tristate "USB MIDI support"
- depends on USB && SOUND
+ depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
---help---
Say Y here if you want to connect a USB MIDI device to your
- computer's USB port. This driver is for devices that comply with
+ computer's USB port. You only need this if you use the OSS
+ sound system; USB MIDI devices are supported by ALSA's USB
+ audio driver. This driver is for devices that comply with
'Universal Serial Bus Device Class Definition for MIDI Device'.
The following devices are known to work:
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index f8f21567cc22..50858273f8d3 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -631,8 +631,10 @@ static void usbin_stop(struct usb_audiodev *as)
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ if (notkilled)
+ schedule_timeout_interruptible(1);
+ else
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&as->lock, flags);
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
@@ -1102,8 +1104,10 @@ static void usbout_stop(struct usb_audiodev *as)
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ if (notkilled)
+ schedule_timeout_interruptible(1);
+ else
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&as->lock, flags);
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 7ce43fb8118a..e195709c9c7f 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -310,8 +310,9 @@ static int usblp_check_status(struct usblp *usblp, int err)
error = usblp_read_status (usblp, usblp->statusbuf);
if (error < 0) {
- err("usblp%d: error %d reading printer status",
- usblp->minor, error);
+ if (printk_ratelimit())
+ err("usblp%d: error %d reading printer status",
+ usblp->minor, error);
return 0;
}
@@ -604,7 +605,9 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case LPGETSTATUS:
if (usblp_read_status(usblp, usblp->statusbuf)) {
- err("usblp%d: failed reading printer status", usblp->minor);
+ if (printk_ratelimit())
+ err("usblp%d: failed reading printer status",
+ usblp->minor);
retval = -EIO;
goto done;
}
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 9e8c377b8161..d5503cf0bf74 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -3,14 +3,14 @@
#
usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
- config.o file.o buffer.o sysfs.o
+ config.o file.o buffer.o sysfs.o devio.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
endif
ifeq ($(CONFIG_USB_DEVICEFS),y)
- usbcore-objs += devio.o inode.o devices.o
+ usbcore-objs += inode.o devices.o
endif
obj-$(CONFIG_USB) += usbcore.o
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f86bf1454e21..b4265aa7d45e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -43,6 +43,7 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
+#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
@@ -50,6 +51,10 @@
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
+#define USB_MAXBUS 64
+#define USB_DEVICE_MAX USB_MAXBUS * 128
+static struct class *usb_device_class;
+
struct async {
struct list_head asynclist;
struct dev_state *ps;
@@ -71,6 +76,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
dev_info( dev , format , ## arg); \
} while (0)
+#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
+
#define MAX_USBFS_BUFFER_SIZE 16384
@@ -487,7 +494,7 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
*/
static int usbdev_open(struct inode *inode, struct file *file)
{
- struct usb_device *dev;
+ struct usb_device *dev = NULL;
struct dev_state *ps;
int ret;
@@ -501,11 +508,16 @@ static int usbdev_open(struct inode *inode, struct file *file)
lock_kernel();
ret = -ENOENT;
- dev = usb_get_dev(inode->u.generic_ip);
+ /* check if we are called from a real node or usbfs */
+ if (imajor(inode) == USB_DEVICE_MAJOR)
+ dev = usbdev_lookup_minor(iminor(inode));
+ if (!dev)
+ dev = inode->u.generic_ip;
if (!dev) {
kfree(ps);
goto out;
}
+ usb_get_dev(dev);
ret = 0;
ps->dev = dev;
ps->file = file;
@@ -1226,7 +1238,6 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
int retval = 0;
struct usb_interface *intf = NULL;
struct usb_driver *driver = NULL;
- int i;
/* get input parameters and alloc buffer */
if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
@@ -1258,15 +1269,6 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
/* disconnect kernel driver from interface */
case USBDEVFS_DISCONNECT:
- /* don't allow the user to unbind the hub driver from
- * a hub with children to manage */
- for (i = 0; i < ps->dev->maxchild; ++i) {
- if (ps->dev->children[i])
- retval = -EBUSY;
- }
- if (retval)
- break;
-
down_write(&usb_bus_type.subsys.rwsem);
if (intf->dev.driver) {
driver = to_usb_driver(intf->dev.driver);
@@ -1477,3 +1479,79 @@ struct file_operations usbfs_device_file_operations = {
.open = usbdev_open,
.release = usbdev_release,
};
+
+struct usb_device *usbdev_lookup_minor(int minor)
+{
+ struct class_device *class_dev;
+ struct usb_device *dev = NULL;
+
+ down(&usb_device_class->sem);
+ list_for_each_entry(class_dev, &usb_device_class->children, node) {
+ if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+ dev = class_dev->class_data;
+ break;
+ }
+ }
+ up(&usb_device_class->sem);
+
+ return dev;
+};
+
+void usbdev_add(struct usb_device *dev)
+{
+ int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
+
+ dev->class_dev = class_device_create(usb_device_class,
+ MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
+ "usbdev%d.%d", dev->bus->busnum, dev->devnum);
+
+ dev->class_dev->class_data = dev;
+}
+
+void usbdev_remove(struct usb_device *dev)
+{
+ class_device_unregister(dev->class_dev);
+}
+
+static struct cdev usb_device_cdev = {
+ .kobj = {.name = "usb_device", },
+ .owner = THIS_MODULE,
+};
+
+int __init usbdev_init(void)
+{
+ int retval;
+
+ retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
+ "usb_device");
+ if (retval) {
+ err("unable to register minors for usb_device");
+ goto out;
+ }
+ cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
+ retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
+ if (retval) {
+ err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
+ unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ goto out;
+ }
+ usb_device_class = class_create(THIS_MODULE, "usb_device");
+ if (IS_ERR(usb_device_class)) {
+ err("unable to register usb_device class");
+ retval = PTR_ERR(usb_device_class);
+ usb_device_class = NULL;
+ cdev_del(&usb_device_cdev);
+ unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ }
+
+out:
+ return retval;
+}
+
+void usbdev_cleanup(void)
+{
+ class_destroy(usb_device_class);
+ cdev_del(&usb_device_cdev);
+ unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+}
+
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index fc056062c960..cbb451d227d2 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -121,10 +121,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
}
}
-#ifdef CONFIG_PCI_NAMES
- hcd->product_desc = dev->pretty_name;
-#endif
-
pci_set_master (dev);
retval = usb_add_hcd (hcd, dev->irq, SA_SHIRQ);
@@ -264,8 +260,10 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
retval = pci_set_power_state (dev, PCI_D3hot);
if (retval == 0) {
dev_dbg (hcd->self.controller, "--> PCI D3\n");
- pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
- pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
+ retval = pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+ if (retval)
+ break;
+ retval = pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
} else if (retval < 0) {
dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
retval);
@@ -339,8 +337,20 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
dev->current_state);
}
#endif
- pci_enable_wake (dev, dev->current_state, 0);
- pci_enable_wake (dev, PCI_D3cold, 0);
+ retval = pci_enable_wake (dev, dev->current_state, 0);
+ if (retval) {
+ dev_err(hcd->self.controller,
+ "can't enable_wake to %d, %d!\n",
+ dev->current_state, retval);
+ return retval;
+ }
+ retval = pci_enable_wake (dev, PCI_D3cold, 0);
+ if (retval) {
+ dev_err(hcd->self.controller,
+ "can't enable_wake to %d, %d!\n",
+ PCI_D3cold, retval);
+ return retval;
+ }
} else {
/* Same basic cases: clean (powered/not), dirty */
dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -380,7 +390,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
usb_hc_died (hcd);
}
- pci_enable_device(dev);
+ retval = pci_enable_device(dev);
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_resume);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 79422a3b07bc..1017a97a418b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -782,7 +782,7 @@ static int usb_register_bus(struct usb_bus *bus)
return -E2BIG;
}
- bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
+ bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
if (IS_ERR(bus->class_dev)) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
@@ -1606,7 +1606,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
return IRQ_NONE;
hcd->saw_irq = 1;
- if (hcd->state != start && hcd->state == HC_STATE_HALT)
+ if (hcd->state == HC_STATE_HALT)
usb_hc_died (hcd);
return IRQ_HANDLED;
}
@@ -1630,7 +1630,6 @@ void usb_hc_died (struct usb_hcd *hcd)
spin_lock_irqsave (&hcd_root_hub_lock, flags);
if (hcd->rh_registered) {
hcd->poll_rh = 0;
- del_timer(&hcd->rh_timer);
/* make khubd clean up old urbs and devices */
usb_set_device_state (hcd->self.root_hub,
@@ -1669,7 +1668,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
{
struct usb_hcd *hcd;
- hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
+ hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
if (!hcd) {
dev_dbg (dev, "hcd alloc failed\n");
return NULL;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 28055f95645b..ac451fa7e4d2 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -339,11 +339,11 @@ extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
* to preallocate bandwidth)
*/
#define USB2_HOST_DELAY 5 /* nsec, guess */
-#define HS_NSECS(bytes) ( ((55 * 8 * 2083)/1000) \
- + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+#define HS_NSECS(bytes) ( ((55 * 8 * 2083) \
+ + (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
-#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083)/1000) \
- + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
+ + (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c3e46d24a37e..a12cab5314e9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -435,6 +435,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
static void hub_power_on(struct usb_hub *hub)
{
int port1;
+ unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
/* if hub supports power switching, enable power on each port */
if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
@@ -444,8 +445,8 @@ static void hub_power_on(struct usb_hub *hub)
USB_PORT_FEAT_POWER);
}
- /* Wait for power to be enabled */
- msleep(hub->descriptor->bPwrOn2PwrGood * 2);
+ /* Wait at least 100 msec for power to become stable */
+ msleep(max(pgood_delay, (unsigned) 100));
}
static void hub_quiesce(struct usb_hub *hub)
@@ -492,6 +493,23 @@ static int hub_hub_status(struct usb_hub *hub,
return ret;
}
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+{
+ struct usb_device *hdev = hub->hdev;
+ int ret;
+
+ if (hdev->children[port1-1] && set_state) {
+ usb_set_device_state(hdev->children[port1-1],
+ USB_STATE_NOTATTACHED);
+ }
+ ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+ if (ret)
+ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+ port1, ret);
+
+ return ret;
+}
+
static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
@@ -610,19 +628,33 @@ static int hub_configure(struct usb_hub *hub,
break;
}
+ /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
- case 0x00:
- if (hdev->descriptor.bDeviceProtocol != 0)
- dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n");
+ case HUB_TTTT_8_BITS:
+ if (hdev->descriptor.bDeviceProtocol != 0) {
+ hub->tt.think_time = 666;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 8, hub->tt.think_time);
+ }
break;
- case 0x20:
- dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n");
+ case HUB_TTTT_16_BITS:
+ hub->tt.think_time = 666 * 2;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 16, hub->tt.think_time);
break;
- case 0x40:
- dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n");
+ case HUB_TTTT_24_BITS:
+ hub->tt.think_time = 666 * 3;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 24, hub->tt.think_time);
break;
- case 0x60:
- dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n");
+ case HUB_TTTT_32_BITS:
+ hub->tt.think_time = 666 * 4;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 32, hub->tt.think_time);
break;
}
@@ -712,20 +744,36 @@ fail:
static unsigned highspeed_hubs;
+/* Called after the hub driver is unbound from a hub with children */
+static void hub_remove_children_work(void *__hub)
+{
+ struct usb_hub *hub = __hub;
+ struct usb_device *hdev = hub->hdev;
+ int i;
+
+ kfree(hub);
+
+ usb_lock_device(hdev);
+ for (i = 0; i < hdev->maxchild; ++i) {
+ if (hdev->children[i])
+ usb_disconnect(&hdev->children[i]);
+ }
+ usb_unlock_device(hdev);
+ usb_put_dev(hdev);
+}
+
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev;
+ int n, port1;
- if (!hub)
- return;
+ usb_set_intfdata (intf, NULL);
hdev = hub->hdev;
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
- usb_set_intfdata (intf, NULL);
-
hub_quiesce(hub);
usb_free_urb(hub->urb);
hub->urb = NULL;
@@ -746,8 +794,27 @@ static void hub_disconnect(struct usb_interface *intf)
hub->buffer = NULL;
}
- /* Free the memory */
- kfree(hub);
+ /* If there are any children then this is an unbind only, not a
+ * physical disconnection. The active ports must be disabled
+ * and later on we must call usb_disconnect(). We can't call
+ * it now because we may not hold the hub's device lock.
+ */
+ n = 0;
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ if (hdev->children[port1 - 1]) {
+ ++n;
+ hub_port_disable(hub, port1, 1);
+ }
+ }
+
+ if (n == 0)
+ kfree(hub);
+ else {
+ /* Reuse the hub->leds work_struct for our own purposes */
+ INIT_WORK(&hub->leds, hub_remove_children_work, hub);
+ schedule_work(&hub->leds);
+ usb_get_dev(hdev);
+ }
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1051,6 +1118,7 @@ void usb_disconnect(struct usb_device **pdev)
dev_dbg (&udev->dev, "unregistering device\n");
release_address(udev);
usbfs_remove_device(udev);
+ usbdev_remove(udev);
usb_remove_sysfs_dev_files(udev);
/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1290,6 +1358,7 @@ int usb_new_device(struct usb_device *udev)
/* USB device state == configured ... usable */
/* add a /proc/bus/usb entry */
+ usbdev_add(udev);
usbfs_add_device(udev);
return 0;
@@ -1392,7 +1461,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
port1, status);
else {
status = hub_port_wait_reset(hub, port1, udev, delay);
- if (status)
+ if (status && status != -ENOTCONN)
dev_dbg(hub->intfdev,
"port_wait_reset: err = %d\n",
status);
@@ -1401,8 +1470,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
/* return on disconnect or reset */
switch (status) {
case 0:
- /* TRSTRCY = 10 ms */
- msleep(10);
+ /* TRSTRCY = 10 ms; plus some extra */
+ msleep(10 + 40);
/* FALL THROUGH */
case -ENOTCONN:
case -ENODEV:
@@ -1428,23 +1497,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status;
}
-static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
-{
- struct usb_device *hdev = hub->hdev;
- int ret;
-
- if (hdev->children[port1-1] && set_state) {
- usb_set_device_state(hdev->children[port1-1],
- USB_STATE_NOTATTACHED);
- }
- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
- if (ret)
- dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
- port1, ret);
-
- return ret;
-}
-
/*
* Disable a port and mark a logical connnect-change event, so that some
* time later khubd will disconnect() any existing usb_device on the port
@@ -1570,7 +1622,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
struct usb_driver *driver;
intf = udev->actconfig->interface[i];
- if (state <= intf->dev.power.power_state)
+ if (state.event <= intf->dev.power.power_state.event)
continue;
if (!intf->dev.driver)
continue;
@@ -1578,11 +1630,11 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
if (driver->suspend) {
status = driver->suspend(intf, state);
- if (intf->dev.power.power_state != state
+ if (intf->dev.power.power_state.event != state.event
|| status)
dev_err(&intf->dev,
"suspend %d fail, code %d\n",
- state, status);
+ state.event, status);
}
/* only drivers with suspend() can ever resume();
@@ -1595,7 +1647,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
* since we know every driver's probe/disconnect works
* even for drivers that can't suspend.
*/
- if (!driver->suspend || state > PM_SUSPEND_MEM) {
+ if (!driver->suspend || state.event > PM_EVENT_FREEZE) {
#if 1
dev_warn(&intf->dev, "resume is unsafe!\n");
#else
@@ -1616,7 +1668,7 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
* policies (when HNP doesn't apply) once we have mechanisms to
* turn power back on! (Likely not before 2.7...)
*/
- if (state > PM_SUSPEND_MEM) {
+ if (state.event > PM_EVENT_FREEZE) {
dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
}
@@ -1733,7 +1785,7 @@ static int finish_port_resume(struct usb_device *udev)
struct usb_driver *driver;
intf = udev->actconfig->interface[i];
- if (intf->dev.power.power_state == PMSG_ON)
+ if (intf->dev.power.power_state.event == PM_EVENT_ON)
continue;
if (!intf->dev.driver) {
/* FIXME maybe force to alt 0 */
@@ -1747,11 +1799,11 @@ static int finish_port_resume(struct usb_device *udev)
/* can we do better than just logging errors? */
status = driver->resume(intf);
- if (intf->dev.power.power_state != PMSG_ON
+ if (intf->dev.power.power_state.event != PM_EVENT_ON
|| status)
dev_dbg(&intf->dev,
"resume fail, state %d code %d\n",
- intf->dev.power.power_state, status);
+ intf->dev.power.power_state.event, status);
}
status = 0;
@@ -1934,7 +1986,7 @@ static int hub_resume(struct usb_interface *intf)
unsigned port1;
int status;
- if (intf->dev.power.power_state == PM_SUSPEND_ON)
+ if (intf->dev.power.power_state.event == PM_EVENT_ON)
return 0;
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 53bf5649621e..e7fa9b5a521e 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -157,6 +157,12 @@ enum hub_led_mode {
struct usb_device;
+/* Transaction Translator Think Times, in bits */
+#define HUB_TTTT_8_BITS 0x00
+#define HUB_TTTT_16_BITS 0x20
+#define HUB_TTTT_24_BITS 0x40
+#define HUB_TTTT_32_BITS 0x60
+
/*
* As of USB 2.0, full/low speed devices are segregated into trees.
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
@@ -170,6 +176,7 @@ struct usb_device;
struct usb_tt {
struct usb_device *hub; /* upstream highspeed hub */
int multi; /* true means one TT per port */
+ unsigned think_time; /* think time in ns */
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
spinlock_t lock;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index c3e3a95d3804..640f41e47029 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -728,15 +728,9 @@ int __init usbfs_init(void)
{
int retval;
- retval = usb_register(&usbfs_driver);
- if (retval)
- return retval;
-
retval = register_filesystem(&usb_fs_type);
- if (retval) {
- usb_deregister(&usbfs_driver);
+ if (retval)
return retval;
- }
/* create mount point for usbfs */
usbdir = proc_mkdir("usb", proc_bus);
@@ -746,7 +740,6 @@ int __init usbfs_init(void)
void usbfs_cleanup(void)
{
- usb_deregister(&usbfs_driver);
unregister_filesystem(&usb_fs_type);
if (usbdir)
remove_proc_entry("usb", proc_bus);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 88d1b376f67c..c47c8052b486 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -48,7 +48,6 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
init_completion(&done);
urb->context = &done;
- urb->transfer_flags |= URB_ASYNC_UNLINK;
urb->actual_length = 0;
status = usb_submit_urb(urb, GFP_NOIO);
@@ -266,7 +265,9 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
continue;
if (found) {
status = usb_unlink_urb (io->urbs [i]);
- if (status != -EINPROGRESS && status != -EBUSY)
+ if (status != -EINPROGRESS
+ && status != -ENODEV
+ && status != -EBUSY)
dev_err (&io->dev->dev,
"%s, unlink --> %d\n",
__FUNCTION__, status);
@@ -357,8 +358,7 @@ int usb_sg_init (
if (!io->urbs)
goto nomem;
- urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
- | URB_NO_INTERRUPT;
+ urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
if (usb_pipein (pipe))
urb_flags |= URB_SHORT_NOT_OK;
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c0feee25ff0a..c846fefb7386 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -309,9 +309,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
unsigned int allowed;
/* enforce simple/standard policy */
- allowed = URB_ASYNC_UNLINK; // affects later unlinks
- allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- allowed |= URB_NO_INTERRUPT;
+ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+ URB_NO_INTERRUPT);
switch (temp) {
case PIPE_BULK:
if (is_out)
@@ -400,14 +399,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
* canceled (rather than any other code) and will quickly be removed
* from host controller data structures.
*
- * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the
- * URB indicated that the request was synchronous. This usage is now
- * deprecated; if the flag is clear the call will be forwarded to
- * usb_kill_urb() and the return value will be 0. In the future, drivers
- * should call usb_kill_urb() directly for synchronous unlinking.
- *
- * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
- * request is asynchronous. Success is indicated by returning -EINPROGRESS,
+ * This request is always asynchronous.
+ * Success is indicated by returning -EINPROGRESS,
* at which time the URB will normally have been unlinked but not yet
* given back to the device driver. When it is called, the completion
* function will see urb->status == -ECONNRESET. Failure is indicated
@@ -453,17 +446,6 @@ int usb_unlink_urb(struct urb *urb)
{
if (!urb)
return -EINVAL;
- if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
-#ifdef CONFIG_DEBUG_KERNEL
- if (printk_ratelimit()) {
- printk(KERN_NOTICE "usb_unlink_urb() is deprecated for "
- "synchronous unlinks. Use usb_kill_urb() instead.\n");
- WARN_ON(1);
- }
-#endif
- usb_kill_urb(urb);
- return 0;
- }
if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
return -ENODEV;
return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 99c85d2f92da..087af73a59dd 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -65,6 +65,16 @@ static int generic_probe (struct device *dev)
}
static int generic_remove (struct device *dev)
{
+ struct usb_device *udev = to_usb_device(dev);
+
+ /* if this is only an unbind, not a physical disconnect, then
+ * unconfigure the device */
+ if (udev->state == USB_STATE_CONFIGURED)
+ usb_set_configuration(udev, 0);
+
+ /* in case the call failed or the device was suspended */
+ if (udev->state >= USB_STATE_CONFIGURED)
+ usb_disable_device(udev, 0);
return 0;
}
@@ -912,7 +922,7 @@ int usb_trylock_device(struct usb_device *udev)
* is neither BINDING nor BOUND. Rather than sleeping to wait for the
* lock, the routine polls repeatedly. This is to prevent deadlock with
* disconnect; in some drivers (such as usb-storage) the disconnect()
- * callback will block waiting for a device reset to complete.
+ * or suspend() method will block waiting for a device reset to complete.
*
* Returns a negative error code for failure, otherwise 1 or 0 to indicate
* that the device will or will not have to be unlocked. (0 can be
@@ -922,6 +932,8 @@ int usb_trylock_device(struct usb_device *udev)
int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface)
{
+ unsigned long jiffies_expire = jiffies + HZ;
+
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
if (udev->state == USB_STATE_SUSPENDED)
@@ -938,6 +950,12 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
while (!usb_trylock_device(udev)) {
+
+ /* If we can't acquire the lock after waiting one second,
+ * we're probably deadlocked */
+ if (time_after(jiffies, jiffies_expire))
+ return -EBUSY;
+
msleep(15);
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
@@ -1400,7 +1418,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
driver = to_usb_driver(dev->driver);
/* there's only one USB suspend state */
- if (intf->dev.power.power_state)
+ if (intf->dev.power.power_state.event)
return 0;
if (driver->suspend)
@@ -1478,13 +1496,18 @@ static int __init usb_init(void)
retval = usb_major_init();
if (retval)
goto major_init_failed;
+ retval = usb_register(&usbfs_driver);
+ if (retval)
+ goto driver_register_failed;
+ retval = usbdev_init();
+ if (retval)
+ goto usbdevice_init_failed;
retval = usbfs_init();
if (retval)
goto fs_init_failed;
retval = usb_hub_init();
if (retval)
goto hub_init_failed;
-
retval = driver_register(&usb_generic_driver);
if (!retval)
goto out;
@@ -1493,7 +1516,11 @@ static int __init usb_init(void)
hub_init_failed:
usbfs_cleanup();
fs_init_failed:
- usb_major_cleanup();
+ usbdev_cleanup();
+usbdevice_init_failed:
+ usb_deregister(&usbfs_driver);
+driver_register_failed:
+ usb_major_cleanup();
major_init_failed:
usb_host_cleanup();
host_init_failed:
@@ -1514,6 +1541,8 @@ static void __exit usb_exit(void)
driver_unregister(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
+ usb_deregister(&usbfs_driver);
+ usbdev_cleanup();
usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 2c690f6d4c18..83d48c8133af 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -37,6 +37,11 @@ extern struct file_operations usbfs_devices_fops;
extern struct file_operations usbfs_device_file_operations;
extern void usbfs_conn_disc_event(void);
+extern int usbdev_init(void);
+extern void usbdev_cleanup(void);
+extern void usbdev_add(struct usb_device *dev);
+extern void usbdev_remove(struct usb_device *dev);
+extern struct usb_device *usbdev_lookup_minor(int minor);
struct dev_state {
struct list_head list; /* state list */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8509e955007d..49459e33e952 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2181,6 +2181,7 @@ eth_bind (struct usb_gadget *gadget)
u8 cdc = 1, zlp = 1, rndis = 1;
struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
int status = -ENOMEM;
+ int gcnum;
/* these flags are only ever cleared; compiler take note */
#ifndef DEV_CONFIG_CDC
@@ -2194,44 +2195,26 @@ eth_bind (struct usb_gadget *gadget)
* standard protocol is _strongly_ preferred for interop purposes.
* (By everyone except Microsoft.)
*/
- if (gadget_is_net2280 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
- } else if (gadget_is_dummy (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0202);
- } else if (gadget_is_pxa (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
+ if (gadget_is_pxa (gadget)) {
/* pxa doesn't support altsettings */
cdc = 0;
} else if (gadget_is_sh(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
/* sh doesn't support multiple interfaces or configs */
cdc = 0;
rndis = 0;
} else if (gadget_is_sa1100 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
/* hardware can't write zlps */
zlp = 0;
/* sa1100 CAN do CDC, without status endpoint ... we use
* non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
*/
cdc = 0;
- } else if (gadget_is_goku (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
- } else if (gadget_is_mq11xx (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
- } else if (gadget_is_omap (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
- } else if (gadget_is_lh7a40x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
- } else if (gadget_is_n9604(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
- } else if (gadget_is_pxa27x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
- } else if (gadget_is_s3c2410(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
- } else if (gadget_is_at91(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
- } else {
+ }
+
+ gcnum = usb_gadget_controller_number (gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+ else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
* so we fail in this case.
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 4f57085619b4..a41d9d4baee3 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3713,6 +3713,7 @@ static void fsg_unbind(struct usb_gadget *gadget)
static int __init check_parameters(struct fsg_dev *fsg)
{
int prot;
+ int gcnum;
/* Store the default values */
mod_data.transport_type = USB_PR_BULK;
@@ -3724,33 +3725,13 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.can_stall = 0;
if (mod_data.release == 0xffff) { // Parameter wasn't set
- if (gadget_is_net2280(fsg->gadget))
- mod_data.release = 0x0301;
- else if (gadget_is_dummy(fsg->gadget))
- mod_data.release = 0x0302;
- else if (gadget_is_pxa(fsg->gadget))
- mod_data.release = 0x0303;
- else if (gadget_is_sh(fsg->gadget))
- mod_data.release = 0x0304;
-
/* The sa1100 controller is not supported */
-
- else if (gadget_is_goku(fsg->gadget))
- mod_data.release = 0x0306;
- else if (gadget_is_mq11xx(fsg->gadget))
- mod_data.release = 0x0307;
- else if (gadget_is_omap(fsg->gadget))
- mod_data.release = 0x0308;
- else if (gadget_is_lh7a40x(fsg->gadget))
- mod_data.release = 0x0309;
- else if (gadget_is_n9604(fsg->gadget))
- mod_data.release = 0x0310;
- else if (gadget_is_pxa27x(fsg->gadget))
- mod_data.release = 0x0311;
- else if (gadget_is_s3c2410(gadget))
- mod_data.release = 0x0312;
- else if (gadget_is_at91(fsg->gadget))
- mod_data.release = 0x0313;
+ if (gadget_is_sa1100(fsg->gadget))
+ gcnum = -1;
+ else
+ gcnum = usb_gadget_controller_number(fsg->gadget);
+ if (gcnum >= 0)
+ mod_data.release = 0x0300 + gcnum;
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index ea2eb52c766d..8cbae21d84b9 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -5,6 +5,7 @@
*
* This could eventually work like the ARM mach_is_*() stuff, driven by
* some config file that gets updated as new hardware is supported.
+ * (And avoiding the runtime comparisons in typical one-choice cases.)
*
* NOTE: some of these controller drivers may not be available yet.
*/
@@ -86,7 +87,61 @@
#define gadget_is_at91(g) 0
#endif
+#ifdef CONFIG_USB_GADGET_IMX
+#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
+#else
+#define gadget_is_imx(g) 0
+#endif
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
+
+/**
+ * usb_gadget_controller_number - support bcdDevice id convention
+ * @gadget: the controller being driven
+ *
+ * Return a 2-digit BCD value associated with the peripheral controller,
+ * suitable for use as part of a bcdDevice value, or a negative error code.
+ *
+ * NOTE: this convention is purely optional, and has no meaning in terms of
+ * any USB specification. If you want to use a different convention in your
+ * gadget driver firmware -- maybe a more formal revision ID -- feel free.
+ *
+ * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
+ * to change their behavior accordingly. For example it might help avoiding
+ * some chip bug.
+ */
+static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
+{
+ if (gadget_is_net2280(gadget))
+ return 0x01;
+ else if (gadget_is_dummy(gadget))
+ return 0x02;
+ else if (gadget_is_pxa(gadget))
+ return 0x03;
+ else if (gadget_is_sh(gadget))
+ return 0x04;
+ else if (gadget_is_sa1100(gadget))
+ return 0x05;
+ else if (gadget_is_goku(gadget))
+ return 0x06;
+ else if (gadget_is_mq11xx(gadget))
+ return 0x07;
+ else if (gadget_is_omap(gadget))
+ return 0x08;
+ else if (gadget_is_lh7a40x(gadget))
+ return 0x09;
+ else if (gadget_is_n9604(gadget))
+ return 0x10;
+ else if (gadget_is_pxa27x(gadget))
+ return 0x11;
+ else if (gadget_is_s3c2410(gadget))
+ return 0x12;
+ else if (gadget_is_at91(gadget))
+ return 0x13;
+ else if (gadget_is_imx(gadget))
+ return 0x14;
+ return -ENOENT;
+}
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 020815397a49..5c40980a5bd9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -483,6 +483,7 @@ ep_release (struct inode *inode, struct file *fd)
data->state = STATE_EP_DISABLED;
data->desc.bDescriptorType = 0;
data->hs_desc.bDescriptorType = 0;
+ usb_ep_disable(data->ep);
}
put_ep (data);
return 0;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 9e4f1c6935a5..c925d9222f53 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1422,49 +1422,20 @@ static int gs_bind(struct usb_gadget *gadget)
int ret;
struct usb_ep *ep;
struct gs_dev *dev;
+ int gcnum;
- /* device specific */
- if (gadget_is_net2280(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
- } else if (gadget_is_pxa(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
- } else if (gadget_is_sh(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
- /* sh doesn't support multiple interfaces or configs */
+ /* Some controllers can't support CDC ACM:
+ * - sh doesn't support multiple interfaces or configs;
+ * - sa1100 doesn't have a third interrupt endpoint
+ */
+ if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
use_acm = 0;
- } else if (gadget_is_sa1100(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
- /* sa1100 doesn't support necessary endpoints */
- use_acm = 0;
- } else if (gadget_is_goku(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
- } else if (gadget_is_mq11xx(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
- } else if (gadget_is_omap(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
- } else if (gadget_is_lh7a40x(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
- } else if (gadget_is_n9604(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0009);
- } else if (gadget_is_pxa27x(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0011);
- } else if (gadget_is_s3c2410(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
- } else if (gadget_is_at91(gadget)) {
+
+ gcnum = usb_gadget_controller_number(gadget);
+ if (gcnum >= 0)
gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
- } else {
+ cpu_to_le16(GS_VERSION_NUM | gcnum);
+ else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name);
/* unrecognized, but safe unless bulk is REALLY quirky */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index bb9b2d94eed5..6890e773b2a2 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1139,6 +1139,13 @@ zero_bind (struct usb_gadget *gadget)
{
struct zero_dev *dev;
struct usb_ep *ep;
+ int gcnum;
+
+ /* FIXME this can't yet work right with SH ... it has only
+ * one configuration, numbered one.
+ */
+ if (gadget_is_sh(gadget))
+ return -ENODEV;
/* Bulk-only drivers like this one SHOULD be able to
* autoconfigure on any sane usb controller driver,
@@ -1161,43 +1168,10 @@ autoconf_fail:
EP_OUT_NAME = ep->name;
ep->driver_data = ep; /* claim */
-
- /*
- * DRIVER POLICY CHOICE: you may want to do this differently.
- * One thing to avoid is reusing a bcdDevice revision code
- * with different host-visible configurations or behavior
- * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
- */
- if (gadget_is_net2280 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
- } else if (gadget_is_pxa (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
-#if 0
- } else if (gadget_is_sh(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
- /* SH has only one configuration; see "loopdefault" */
- device_desc.bNumConfigurations = 1;
- /* FIXME make 1 == default.bConfigurationValue */
-#endif
- } else if (gadget_is_sa1100 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
- } else if (gadget_is_goku (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
- } else if (gadget_is_mq11xx (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
- } else if (gadget_is_omap (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
- } else if (gadget_is_lh7a40x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
- } else if (gadget_is_n9604(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
- } else if (gadget_is_pxa27x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
- } else if (gadget_is_s3c2410(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
- } else if (gadget_is_at91(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
- } else {
+ gcnum = usb_gadget_controller_number (gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+ else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
* so warn about unrcognized controllers, don't panic.
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index b01efb6b36f6..65ac9fef3a7c 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -641,7 +641,7 @@ show_registers (struct class_device *class_dev, char *buf)
spin_lock_irqsave (&ehci->lock, flags);
- if (bus->controller->power.power_state) {
+ if (bus->controller->power.power_state.event) {
size = scnprintf (next, size,
"bus %s, device %s (driver " DRIVER_VERSION ")\n"
"%s\n"
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 149b13fc0a71..b948ffd94f45 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -400,6 +400,23 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
return -EIO;
}
break;
+ case PCI_VENDOR_ID_NVIDIA:
+ /* NVidia reports that certain chips don't handle
+ * QH, ITD, or SITD addresses above 2GB. (But TD,
+ * data buffer, and periodic schedule are normal.)
+ */
+ switch (pdev->device) {
+ case 0x003c: /* MCP04 */
+ case 0x005b: /* CK804 */
+ case 0x00d8: /* CK8 */
+ case 0x00e8: /* CK8S */
+ if (pci_set_consistent_dma_mask(pdev,
+ DMA_31BIT_MASK) < 0)
+ ehci_warn (ehci, "can't enable NVidia "
+ "workaround for >2GB RAM\n");
+ break;
+ }
+ break;
}
/* optional debug port, normally in the first BAR */
@@ -549,7 +566,9 @@ static int ehci_start (struct usb_hcd *hcd)
hcd->can_wakeup = (port_wake & 1) != 0;
/* help hc dma work well with cachelines */
- pci_set_mwi (pdev);
+ retval = pci_set_mwi(pdev);
+ if (retval)
+ ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
}
#endif
@@ -757,12 +776,16 @@ static int ehci_resume (struct usb_hcd *hcd)
if (time_before (jiffies, ehci->next_statechange))
msleep (100);
- /* If any port is suspended, we know we can/must resume the HC. */
+ /* If any port is suspended (or owned by the companion),
+ * we know we can/must resume the HC (and mustn't reset it).
+ */
for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
u32 status;
port--;
status = readl (&ehci->regs->port_status [port]);
- if (status & PORT_SUSPEND) {
+ if (!(status & PORT_POWER))
+ continue;
+ if (status & (PORT_SUSPEND | PORT_OWNER)) {
down (&hcd->self.root_hub->serialize);
retval = ehci_hub_resume (hcd);
up (&hcd->self.root_hub->serialize);
@@ -1124,8 +1147,7 @@ rescan:
case QH_STATE_UNLINK: /* wait for hw to finish? */
idle_timeout:
spin_unlock_irqrestore (&ehci->lock, flags);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (1);
+ schedule_timeout_uninterruptible(1);
goto rescan;
case QH_STATE_IDLE: /* fully unlinked */
if (list_empty (&qh->qtd_list)) {
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 36cc1f2218d5..18d3f2270316 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* suspend any active/unsuspended ports, maybe allow wakeup */
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
- u32 t1 = readl (reg);
+ u32 t1 = readl (reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
- temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
+ temp &= ~(PORT_RWC_BITS
+ | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
if (temp & PORT_SUSPEND) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME;
@@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
temp = readl (&ehci->regs->port_status [i]);
if ((temp & PORT_SUSPEND) == 0)
continue;
- temp &= ~PORT_RESUME;
+ temp &= ~(PORT_RWC_BITS | PORT_RESUME);
writel (temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
@@ -191,6 +192,7 @@ static int check_reset_complete (
// what happens if HCS_N_CC(params) == 0 ?
port_status |= PORT_OWNER;
+ port_status &= ~PORT_RWC_BITS;
writel (port_status, &ehci->regs->port_status [index]);
} else
@@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (temp & PORT_OWNER) {
/* don't report this in GetPortStatus */
if (temp & PORT_CSC) {
- temp &= ~PORT_CSC;
+ temp &= ~PORT_RWC_BITS;
+ temp |= PORT_CSC;
writel (temp, &ehci->regs->port_status [i]);
}
continue;
@@ -343,7 +346,7 @@ static int ehci_hub_control (
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_ENABLE:
- writel (temp | PORT_PEC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_SUSPEND:
@@ -353,7 +356,8 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0)
goto error;
/* resume signaling for 20 msec */
- writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
+ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ writel (temp | PORT_RESUME,
&ehci->regs->port_status [wIndex]);
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (20);
@@ -364,15 +368,15 @@ static int ehci_hub_control (
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
- writel (temp & ~PORT_POWER,
+ writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_CONNECTION:
- writel (temp | PORT_CSC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- writel (temp | PORT_OCC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_RESET:
@@ -416,7 +420,7 @@ static int ehci_hub_control (
/* stop resume signaling */
temp = readl (&ehci->regs->port_status [wIndex]);
- writel (temp & ~PORT_RESUME,
+ writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
&ehci->regs->port_status [wIndex]);
retval = handshake (
&ehci->regs->port_status [wIndex],
@@ -437,7 +441,7 @@ static int ehci_hub_control (
ehci->reset_done [wIndex] = 0;
/* force reset to complete */
- writel (temp & ~PORT_RESET,
+ writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
&ehci->regs->port_status [wIndex]);
/* REVISIT: some hardware needs 550+ usec to clear
* this bit; seems too long to spin routinely...
@@ -500,6 +504,7 @@ static int ehci_hub_control (
if (temp & PORT_OWNER)
break;
+ temp &= ~PORT_RWC_BITS;
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
if ((temp & PORT_PE) == 0
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 20df01a79b2e..940d38ca7d91 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -677,6 +677,9 @@ qh_make (
goto done;
}
} else {
+ struct usb_tt *tt = urb->dev->tt;
+ int think_time;
+
/* gap is f(FS/LS transfer times) */
qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
is_input, 0, maxp) / (125 * 1000);
@@ -690,6 +693,10 @@ qh_make (
qh->c_usecs = HS_USECS (0);
}
+ think_time = tt ? tt->think_time : 0;
+ qh->tt_usecs = NS_TO_US (think_time +
+ usb_calc_bus_time (urb->dev->speed,
+ is_input, 0, max_packet (maxp)));
qh->period = urb->interval;
}
}
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index b56f25864ed6..ccc7300baa6d 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -638,7 +638,7 @@ iso_stream_alloc (unsigned mem_flags)
{
struct ehci_iso_stream *stream;
- stream = kcalloc(1, sizeof *stream, mem_flags);
+ stream = kzalloc(sizeof *stream, mem_flags);
if (likely (stream != NULL)) {
INIT_LIST_HEAD(&stream->td_list);
INIT_LIST_HEAD(&stream->free_list);
@@ -700,6 +700,7 @@ iso_stream_init (
} else {
u32 addr;
+ int think_time;
addr = dev->ttport << 24;
if (!ehci_is_TDI(ehci)
@@ -709,6 +710,9 @@ iso_stream_init (
addr |= epnum << 8;
addr |= dev->devnum;
stream->usecs = HS_USECS_ISO (maxp);
+ think_time = dev->tt ? dev->tt->think_time : 0;
+ stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
+ dev->speed, is_input, 1, maxp));
if (is_input) {
u32 tmp;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index a7542157534c..f34a0516d35f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -263,6 +263,7 @@ struct ehci_regs {
#define PORT_PE (1<<2) /* port enable */
#define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */
+#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
} __attribute__ ((packed));
/* Appendix C, Debug port ... intended for use with special "debug devices"
@@ -421,6 +422,7 @@ struct ehci_qh {
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */
u8 c_usecs; /* ... split completion bw */
+ u16 tt_usecs; /* tt downstream bandwidth */
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
@@ -479,6 +481,7 @@ struct ehci_iso_stream {
*/
u8 interval;
u8 usecs, c_usecs;
+ u16 tt_usecs;
u16 maxp;
u16 raw_mask;
unsigned bandwidth;
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 81f8f6b7fdce..a8267cf17db4 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -178,8 +178,8 @@ static __u8 root_hub_hub_des[] =
0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
};
-static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0);
+static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
/* We want the start timer to expire before the eot timer, because the former might start
traffic, thus making it unnecessary for the latter to time out. */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 76cb496c5836..41bbae83fc71 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -83,7 +83,7 @@
#include "../core/hcd.h"
#include "isp116x.h"
-#define DRIVER_VERSION "08 Apr 2005"
+#define DRIVER_VERSION "05 Aug 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -629,14 +629,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
ERR("Unrecoverable error\n");
/* What should we do here? Reset? */
}
- if (intstat & HCINT_RHSC) {
- isp116x->rhstatus =
- isp116x_read_reg32(isp116x, HCRHSTATUS);
- isp116x->rhport[0] =
- isp116x_read_reg32(isp116x, HCRHPORT1);
- isp116x->rhport[1] =
- isp116x_read_reg32(isp116x, HCRHPORT2);
- }
+ if (intstat & HCINT_RHSC)
+ /* When root hub or any of its ports is going
+ to come out of suspend, it may take more
+ than 10ms for status bits to stabilize. */
+ mod_timer(&hcd->rh_timer, jiffies
+ + msecs_to_jiffies(20) + 1);
if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n");
schedule_work(&isp116x->rh_resume);
@@ -717,7 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
}
/* avoid all allocations within spinlocks: request or endpoint */
if (!hep->hcpriv) {
- ep = kcalloc(1, sizeof *ep, mem_flags);
+ ep = kzalloc(sizeof *ep, mem_flags);
if (!ep)
return -ENOMEM;
}
@@ -925,20 +923,27 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
int ports, i, changed = 0;
+ unsigned long flags;
if (!HC_IS_RUNNING(hcd->state))
return -ESHUTDOWN;
- ports = isp116x->rhdesca & RH_A_NDP;
+ /* Report no status change now, if we are scheduled to be
+ called later */
+ if (timer_pending(&hcd->rh_timer))
+ return 0;
- /* init status */
+ ports = isp116x->rhdesca & RH_A_NDP;
+ spin_lock_irqsave(&isp116x->lock, flags);
+ isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))
buf[0] = changed = 1;
else
buf[0] = 0;
for (i = 0; i < ports; i++) {
- u32 status = isp116x->rhport[i];
+ u32 status = isp116x->rhport[i] =
+ isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
| RH_PS_OCIC | RH_PS_PRSC)) {
@@ -947,6 +952,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
continue;
}
}
+ spin_unlock_irqrestore(&isp116x->lock, flags);
return changed;
}
@@ -1463,10 +1469,6 @@ static int isp116x_sw_reset(struct isp116x *isp116x)
return ret;
}
-/*
- Reset. Tries to perform platform-specific hardware
- reset first; falls back to software reset.
-*/
static int isp116x_reset(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
@@ -1474,17 +1476,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
u16 clkrdy = 0;
int ret = 0, timeout = 15 /* ms */ ;
- if (isp116x->board && isp116x->board->reset) {
- /* Hardware reset */
- isp116x->board->reset(hcd->self.controller, 1);
- msleep(10);
- if (isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 1);
- msleep(1);
- isp116x->board->reset(hcd->self.controller, 0);
- } else
- ret = isp116x_sw_reset(isp116x);
-
+ ret = isp116x_sw_reset(isp116x);
if (ret)
return ret;
@@ -1501,10 +1493,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
ERR("Clock not ready after 20ms\n");
/* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */
- if (!isp116x->board || !isp116x->board->reset)
- ERR("The driver does not support hardware wakeup.\n");
- ERR("Please make sure that the H_WAKEUP pin "
- "is pulled low!\n");
+ ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
ret = -ENODEV;
}
return ret;
@@ -1527,15 +1516,7 @@ static void isp116x_stop(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
spin_unlock_irqrestore(&isp116x->lock, flags);
- /* Put the chip into reset state */
- if (isp116x->board && isp116x->board->reset)
- isp116x->board->reset(hcd->self.controller, 0);
- else
- isp116x_sw_reset(isp116x);
-
- /* Stop the clock */
- if (isp116x->board && isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 0);
+ isp116x_sw_reset(isp116x);
}
/*
@@ -1561,6 +1542,9 @@ static int isp116x_start(struct usb_hcd *hcd)
return -ENODEV;
}
+ /* To be removed in future */
+ hcd->uses_new_polling = 1;
+
isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
@@ -1569,7 +1553,7 @@ static int isp116x_start(struct usb_hcd *hcd)
if (board->sel15Kres)
val |= HCHWCFG_15KRSEL;
/* Remote wakeup won't work without working clock */
- if (board->clknotstop || board->remote_wakeup_enable)
+ if (board->remote_wakeup_enable)
val |= HCHWCFG_CLKNOTSTOP;
if (board->oc_enable)
val |= HCHWCFG_ANALOG_OC;
@@ -1580,16 +1564,13 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg16(isp116x, HCHWCFG, val);
/* ----- Root hub conf */
- val = 0;
- /* AN10003_1.pdf recommends NPS to be always 1 */
- if (board->no_power_switching)
- val |= RH_A_NPS;
- if (board->power_switching_mode)
- val |= RH_A_PSM;
- if (board->potpg)
- val |= (board->potpg << 24) & RH_A_POTPGT;
- else
- val |= (25 << 24) & RH_A_POTPGT;
+ val = (25 << 24) & RH_A_POTPGT;
+ /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+ be always set. Yet, instead, we request individual port
+ power switching. */
+ val |= RH_A_PSM;
+ /* Report overcurrent per port */
+ val |= RH_A_OCPM;
isp116x_write_reg32(isp116x, HCRHDESCA, val);
isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
@@ -1619,9 +1600,6 @@ static int isp116x_start(struct usb_hcd *hcd)
/* Go operational */
val = HCCONTROL_USB_OPER;
- /* Remote wakeup connected - NOT SUPPORTED */
- /* if (board->remote_wakeup_connected)
- val |= HCCONTROL_RWC; */
if (board->remote_wakeup_enable)
val |= HCCONTROL_RWE;
isp116x_write_reg32(isp116x, HCCONTROL, val);
@@ -1670,7 +1648,7 @@ static int __init_or_module isp116x_remove(struct device *dev)
struct platform_device *pdev;
struct resource *res;
- if(!hcd)
+ if (!hcd)
return 0;
isp116x = hcd_to_isp116x(hcd);
pdev = container_of(dev, struct platform_device, dev);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index c58408c95c3d..7924c74f958e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -228,23 +228,22 @@ ohci_dump_roothub (
char **next,
unsigned *size)
{
- u32 temp, ndp, i;
+ u32 temp, i;
temp = roothub_a (controller);
if (temp == ~(u32)0)
return;
- ndp = (temp & RH_A_NDP);
if (verbose) {
ohci_dbg_sw (controller, next, size,
- "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+ "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
((temp & RH_A_POTPGT) >> 24) & 0xff,
(temp & RH_A_NOCP) ? " NOCP" : "",
(temp & RH_A_OCPM) ? " OCPM" : "",
(temp & RH_A_DT) ? " DT" : "",
(temp & RH_A_NPS) ? " NPS" : "",
(temp & RH_A_PSM) ? " PSM" : "",
- ndp
+ (temp & RH_A_NDP), controller->num_ports
);
temp = roothub_b (controller);
ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@ ohci_dump_roothub (
);
}
- for (i = 0; i < ndp; i++) {
+ for (i = 0; i < controller->num_ports; i++) {
temp = roothub_portstatus (controller, i);
dbg_port_sw (controller, i, temp, next, size);
}
@@ -631,7 +630,7 @@ show_registers (struct class_device *class_dev, char *buf)
hcd->product_desc,
hcd_name);
- if (bus->controller->power.power_state) {
+ if (bus->controller->power.power_state.event) {
size -= scnprintf (next, size,
"SUSPENDED (no register access)\n");
goto done;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 56b43f2a0e52..67c1aa5eb1c1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -382,8 +382,7 @@ sanitize:
goto sanitize;
}
spin_unlock_irqrestore (&ohci->lock, flags);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (1);
+ schedule_timeout_uninterruptible(1);
goto rescan;
case ED_IDLE: /* fully unlinked */
if (list_empty (&ed->td_list)) {
@@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
// flush the writes
(void) ohci_readl (ohci, &ohci->regs->control);
+ /* Read the number of ports unless overridden */
+ if (ohci->num_ports == 0)
+ ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
if (ohci->hcca)
return 0;
@@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
msleep(temp);
temp = roothub_a (ohci);
if (!(temp & RH_A_NPS)) {
- unsigned ports = temp & RH_A_NDP;
-
/* power down each port */
- for (temp = 0; temp < ports; temp++)
+ for (temp = 0; temp < ohci->num_ports; temp++)
ohci_writel (ohci, RH_PS_LSDA,
&ohci->regs->roothub.portstatus [temp]);
}
@@ -720,6 +721,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_RD) {
ohci_vdbg (ohci, "resume detect\n");
+ ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
if (hcd->state != HC_STATE_QUIESCING)
schedule_work(&ohci->rh_resume);
}
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* and that if we try to turn them back on the root hub
* will respond to CSC processing.
*/
- i = roothub_a (ohci) & RH_A_NDP;
+ i = ohci->num_ports;
while (i--)
ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [temp]);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 83ca4549a50e..ce7b28da7a15 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (status != -EINPROGRESS)
return status;
- temp = roothub_a (ohci) & RH_A_NDP;
+ temp = ohci->num_ports;
enables = 0;
while (temp--) {
u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@ static int
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ports, i, changed = 0, length = 1;
+ int i, changed = 0, length = 1;
int can_suspend = hcd->can_wakeup;
unsigned long flags;
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
goto done;
}
- ports = roothub_a (ohci) & RH_A_NDP;
- if (ports > MAX_ROOT_PORTS) {
- ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+ /* undocumented erratum seen on at least rev D */
+ if ((ohci->flags & OHCI_QUIRK_AMD756)
+ && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+ ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
goto done;
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
buf [0] = changed = 1;
else
buf [0] = 0;
- if (ports > 7) {
+ if (ohci->num_ports > 7) {
buf [1] = 0;
length++;
}
/* look at each port */
- for (i = 0; i < ports; i++) {
+ for (i = 0; i < ohci->num_ports; i++) {
u32 status = roothub_portstatus (ohci, i);
if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
struct usb_hub_descriptor *desc
) {
u32 rh = roothub_a (ohci);
- int ports = rh & RH_A_NDP;
u16 temp;
desc->bDescriptorType = 0x29;
desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
desc->bHubContrCurrent = 0;
- desc->bNbrPorts = ports;
- temp = 1 + (ports / 8);
+ desc->bNbrPorts = ohci->num_ports;
+ temp = 1 + (ohci->num_ports / 8);
desc->bDescLength = 7 + 2 * temp;
temp = 0;
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
rh = roothub_b (ohci);
memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
desc->bitmap [0] = rh & RH_B_DR;
- if (ports > 7) {
+ if (ohci->num_ports > 7) {
desc->bitmap [1] = (rh & RH_B_DR) >> 8;
desc->bitmap [2] = 0xff;
} else
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 17964c39d06a..251533363028 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -14,8 +14,6 @@
* This file is licenced under the GPL.
*/
-#include <asm/usb.h>
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -23,9 +21,7 @@
* usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
* Context: !in_interrupt()
*
- * 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.
+ * Allocates basic resources for this USB host controller.
*
* Store this function in the HCD's struct pci_driver as probe().
*/
@@ -37,7 +33,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
struct ohci_hcd *ohci;
struct resource *res;
int irq;
- struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
pr_debug("initializing PPC-SOC USB Controller\n");
@@ -73,9 +68,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
goto err2;
}
- if (pd->start && (retval = pd->start(pdev)))
- goto err3;
-
ohci = hcd_to_ohci(hcd);
ohci->flags |= OHCI_BIG_ENDIAN;
ohci_hcd_init(ohci);
@@ -85,9 +77,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
return retval;
pr_debug("Removing PPC-SOC USB Controller\n");
- if (pd && pd->stop)
- pd->stop(pdev);
- err3:
+
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -105,25 +95,21 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
* @pdev: USB Host Controller being removed
* Context: !in_interrupt()
*
- * Reverses the effect of usb_hcd_ppc_soc_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
+ * Reverses the effect of usb_hcd_ppc_soc_probe().
+ * It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
- struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
-
usb_remove_hcd(hcd);
pr_debug("stopping PPC-SOC USB Controller\n");
- if (pd && pd->stop)
- pd->stop(pdev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_hcd_put(hcd);
+ usb_put_hcd(hcd);
}
static int __devinit
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e5bc1789d18a..2fdb262d4726 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -75,33 +75,6 @@ static int pxa27x_ohci_select_pmm( int mode )
return 0;
}
-/*
- If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_set_port_power( int port )
-{
- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
- UHCRHPS(port) |= 0x100;
- return 0;
- }
- return -1;
-}
-
-/*
- If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_clear_port_power( int port )
-{
- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
- UHCRHPS(port) |= 0x200;
- return 0;
- }
-
- return -1;
-}
-
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
@@ -130,11 +103,17 @@ static void pxa27x_start_hc(struct platform_device *dev)
Polarity Low to active low. Supply power to USB ports. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
}
UHCHR &= ~UHCHR_SSE;
UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
+
+ /* Clear any OTG Pin Hold */
+ if (PSSR & PSSR_OTGPH)
+ PSSR |= PSSR_OTGPH;
}
static void pxa27x_stop_hc(struct platform_device *dev)
@@ -198,17 +177,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
pxa27x_start_hc(dev);
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );
-
- /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
- if (pxa27x_ohci_set_port_power(1) < 0)
- printk(KERN_ERR "Setting port 1 power failed.\n");
-
- if (pxa27x_ohci_clear_port_power(2) < 0)
- printk(KERN_ERR "Setting port 2 power failed.\n");
-
- if (pxa27x_ohci_clear_port_power(3) < 0)
- printk(KERN_ERR "Setting port 3 power failed.\n");
+ pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
ohci_hcd_init(hcd_to_ohci(hcd));
@@ -258,6 +227,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
+ /* The value of NDP in roothub_a is incorrect on this hardware */
+ ohci->num_ports = 3;
+
if ((ret = ohci_init(ohci)) < 0)
return ret;
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index e9401662503c..3d9bcf78a9a4 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -129,7 +129,7 @@ static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info,
if (info->power_control != NULL) {
info->port[port-1].power = to;
- (info->power_control)(port, to);
+ (info->power_control)(port-1, to);
}
}
@@ -339,8 +339,8 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
struct usb_hcd *hcd = NULL;
int retval;
- s3c2410_usb_set_power(dev->dev.platform_data, 0, 1);
s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);
+ s3c2410_usb_set_power(dev->dev.platform_data, 2, 1);
hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");
if (hcd == NULL)
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 71cdd2262860..8a9b9d9209e9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -383,6 +383,7 @@ struct ohci_hcd {
/*
* driver state
*/
+ int num_ports;
int load [NUM_INTS];
u32 hc_control; /* copy of hc control reg */
unsigned long next_statechange; /* suspend/resume */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 7a890a65f55d..d2a1fd40dfcb 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -835,7 +835,7 @@ static int sl811h_urb_enqueue(
/* avoid all allocations within spinlocks */
if (!hep->hcpriv)
- ep = kcalloc(1, sizeof *ep, mem_flags);
+ ep = kzalloc(sizeof *ep, mem_flags);
spin_lock_irqsave(&sl811->lock, flags);
@@ -1781,9 +1781,9 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
if (phase != SUSPEND_POWER_DOWN)
return retval;
- if (state <= PM_SUSPEND_MEM)
+ if (state.event == PM_EVENT_FREEZE)
retval = sl811h_hub_suspend(hcd);
- else
+ else if (state.event == PM_EVENT_SUSPEND)
port_power(sl811, 0);
if (retval == 0)
dev->power.power_state = state;
@@ -1802,7 +1802,7 @@ sl811h_resume(struct device *dev, u32 phase)
/* with no "check to see if VBUS is still powered" board hook,
* let's assume it'd only be powered to enable remote wakeup.
*/
- if (dev->power.power_state > PM_SUSPEND_MEM
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND
|| !hcd->can_wakeup) {
sl811->port1 = 0;
port_power(sl811, 1);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 0d5d2545bf07..0c024898cbea 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
-static inline void restart_timer(struct uhci_hcd *uhci)
-{
- mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
-}
-
-#include "uhci-hub.c"
#include "uhci-debug.c"
#include "uhci-q.c"
+#include "uhci-hub.c"
/*
* Make sure the controller is completely inactive, unable to
@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
{
reset_hc(uhci);
uhci->hc_inaccessible = 1;
- del_timer(&uhci->stall_timer);
}
/*
@@ -287,8 +281,11 @@ __acquires(uhci->lock)
/* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode, still configured.
*/
- int_enable = (resume_detect_interrupts_are_broken(uhci) ?
- 0 : USBINTR_RESUME);
+ uhci->working_RD = 1;
+ int_enable = USBINTR_RESUME;
+ if (resume_detect_interrupts_are_broken(uhci)) {
+ uhci->working_RD = int_enable = 0;
+ }
outw(int_enable, uhci->io_addr + USBINTR);
outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
mb();
@@ -315,7 +312,6 @@ __acquires(uhci->lock)
uhci->rh_state = new_state;
uhci->is_stopped = UHCI_IS_STOPPED;
- del_timer(&uhci->stall_timer);
uhci_to_hcd(uhci)->poll_rh = !int_enable;
uhci_scan_schedule(uhci, NULL);
@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
mb();
uhci->rh_state = UHCI_RH_RUNNING;
uhci_to_hcd(uhci)->poll_rh = 1;
- restart_timer(uhci);
}
static void wakeup_rh(struct uhci_hcd *uhci)
@@ -374,20 +369,6 @@ __acquires(uhci->lock)
mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
}
-static void stall_callback(unsigned long _uhci)
-{
- struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
- unsigned long flags;
-
- spin_lock_irqsave(&uhci->lock, flags);
- uhci_scan_schedule(uhci, NULL);
- check_fsbr(uhci);
-
- if (!uhci->is_stopped)
- restart_timer(uhci);
- spin_unlock_irqrestore(&uhci->lock, flags);
-}
-
static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
"host controller halted, "
"very bad!\n");
hc_died(uhci);
- spin_unlock_irqrestore(&uhci->lock, flags);
- return IRQ_HANDLED;
+
+ /* Force a callback in case there are
+ * pending unlinks */
+ mod_timer(&hcd->rh_timer, jiffies);
}
spin_unlock_irqrestore(&uhci->lock, flags);
}
@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (status & USBSTS_RD)
usb_hcd_poll_rh_status(hcd);
-
- spin_lock_irqsave(&uhci->lock, flags);
- uhci_scan_schedule(uhci, regs);
- spin_unlock_irqrestore(&uhci->lock, flags);
+ else {
+ spin_lock_irqsave(&uhci->lock, flags);
+ uhci_scan_schedule(uhci, regs);
+ spin_unlock_irqrestore(&uhci->lock, flags);
+ }
return IRQ_HANDLED;
}
@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
init_waitqueue_head(&uhci->waitqh);
- init_timer(&uhci->stall_timer);
- uhci->stall_timer.function = stall_callback;
- uhci->stall_timer.data = (unsigned long) uhci;
-
uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
&dma_handle, 0);
if (!uhci->fl) {
@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
spin_lock_irq(&uhci->lock);
- reset_hc(uhci);
+ if (!uhci->hc_inaccessible)
+ reset_hc(uhci);
uhci_scan_schedule(uhci, NULL);
spin_unlock_irq(&uhci->lock);
- del_timer_sync(&uhci->stall_timer);
release_uhci(uhci);
}
@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
*/
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
uhci->hc_inaccessible = 1;
+ hcd->poll_rh = 0;
/* FIXME: Enable non-PME# remote wakeup? */
done:
spin_unlock_irq(&uhci->lock);
- if (rc == 0)
- del_timer_sync(&hcd->rh_timer);
return rc;
}
@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
spin_unlock_irq(&uhci->lock);
- if (hcd->poll_rh)
+ if (!uhci->working_RD) {
+ /* Suspended root hub needs to be polled */
+ hcd->poll_rh = 1;
usb_hcd_poll_rh_status(hcd);
+ }
return 0;
}
#endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index bf9c5f9b508b..282f40b75881 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -345,9 +345,6 @@ enum uhci_rh_state {
/*
* This describes the full uhci information.
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs.
*/
struct uhci_hcd {
@@ -360,8 +357,6 @@ struct uhci_hcd {
struct dma_pool *qh_pool;
struct dma_pool *td_pool;
- struct usb_bus *bus;
-
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
@@ -380,6 +375,8 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int hc_inaccessible:1; /* HC is suspended or dead */
+ unsigned int working_RD:1; /* Suspended root hub doesn't
+ need to be polled */
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
@@ -405,9 +402,7 @@ struct uhci_hcd {
/* List of URB's awaiting completion callback */
struct list_head complete_list; /* P: uhci->lock */
- int rh_numports;
-
- struct timer_list stall_timer;
+ int rh_numports; /* Number of root-hub ports */
wait_queue_head_t waitqh; /* endpoint_disable waiters */
};
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 4eace2b19ddb..a71e48a66805 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags;
- int status;
+ int status = 0;
spin_lock_irqsave(&uhci->lock, flags);
- if (uhci->hc_inaccessible) {
- status = 0;
- goto done;
- }
+ uhci_scan_schedule(uhci, NULL);
+ if (uhci->hc_inaccessible)
+ goto done;
+ check_fsbr(uhci);
uhci_check_ports(uhci);
+
status = get_hub_status_data(uhci, buf);
switch (uhci->rh_state) {
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index bbb36cd6ed61..ea0d168a8c67 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
{
if (uhci->is_stopped)
- mod_timer(&uhci->stall_timer, jiffies);
+ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
}
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 298e4a25e3d3..1e53934907c0 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -230,6 +230,20 @@ config USB_EGALAX
To compile this driver as a module, choose M here: the
module will be called touchkitusb.
+config USB_YEALINK
+ tristate "Yealink usb-p1k voip phone"
+ depends on USB && INPUT && EXPERIMENTAL
+ ---help---
+ Say Y here if you want to enable keyboard and LCD functions of the
+ Yealink usb-p1k usb phones. The audio part is enabled by the generic
+ usb sound driver, so you might want to enable that as well.
+
+ For information about how to use these additional functions, see
+ <file:Documentation/input/yealink.txt>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called yealink.
+
config USB_XPAD
tristate "X-Box gamepad support"
depends on USB && INPUT
@@ -272,3 +286,23 @@ config USB_KEYSPAN_REMOTE
To compile this driver as a module, choose M here: the module will
be called keyspan_remote.
+
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (prior models have a Synaptics touchpad connected
+ to the ADB bus).
+
+ This driver provides a basic mouse driver but can be interfaced
+ with the synaptics X11 driver to provide acceleration and
+ scrolling in X11.
+
+ For further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called appletouch.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index f1547be632d4..5e03b93f29f6 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -39,4 +39,6 @@ obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
+obj-$(CONFIG_USB_YEALINK) += yealink.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 13532f3e3efc..74f8760d7c07 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL);
+ acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
if (!acecad)
return -ENOMEM;
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644
index 000000000000..e03c1c567a14
--- /dev/null
+++ b/drivers/usb/input/appletouch.c
@@ -0,0 +1,469 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
+ * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ *
+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/usb_input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID 0x05AC
+
+#define ATP_DEVICE(prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = APPLE_VENDOR_ID, \
+ .idProduct = (prod), \
+ .bInterfaceClass = 0x03, \
+ .bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+ { ATP_DEVICE(0x020E) },
+ { ATP_DEVICE(0x020F) },
+ { ATP_DEVICE(0x030A) },
+ { ATP_DEVICE(0x030B) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/* size of a USB urb transfer */
+#define ATP_DATASIZE 81
+
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) sensors.
+ */
+#define ATP_XSENSORS 26
+#define ATP_YSENSORS 16
+
+/* amount of fuzz this touchpad generates */
+#define ATP_FUZZ 16
+
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE 300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 5
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+ struct usb_device * udev; /* usb device */
+ struct urb * urb; /* usb request block */
+ signed char * data; /* transferred data */
+ int open; /* non-zero if opened */
+ struct input_dev input; /* input dev */
+ int valid; /* are the sensors valid ? */
+ int x_old; /* last reported x/y, */
+ int y_old; /* used for smoothing */
+ /* current value of the sensors */
+ signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ /* last value of the sensors */
+ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ /* accumulated sensors */
+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+};
+
+#define dbg_dump(msg, tab) \
+ if (debug > 1) { \
+ int i; \
+ printk("appletouch: %s %lld", msg, (long long)jiffies); \
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
+ printk(" %02x", tab[i]); \
+ printk("\n"); \
+ }
+
+#define dprintk(format, a...) \
+ do { \
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+ int *z, int *fingers)
+{
+ int i;
+ /* values to calculate mean */
+ int pcum = 0, psum = 0;
+
+ *fingers = 0;
+
+ for (i = 0; i < nb_sensors; i++) {
+ if (xy_sensors[i] < ATP_THRESHOLD)
+ continue;
+ if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+ (*fingers)++;
+ pcum += xy_sensors[i] * i;
+ psum += xy_sensors[i];
+ }
+
+ if (psum > 0) {
+ *z = psum;
+ return pcum * fact / psum;
+ }
+
+ return 0;
+}
+
+static inline void atp_report_fingers(struct input_dev *input, int fingers)
+{
+ input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i;
+ struct atp *dev = urb->context;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ 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;
+ }
+
+ /* drop incomplete datasets */
+ if (dev->urb->actual_length != ATP_DATASIZE) {
+ dprintk("appletouch: incomplete data package.\n");
+ goto exit;
+ }
+
+ /* reorder the sensors values */
+ for (i = 0; i < 8; i++) {
+ /* X values */
+ dev->xy_cur[i ] = dev->data[5 * i + 2];
+ dev->xy_cur[i + 8] = dev->data[5 * i + 4];
+ dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+ if (i < 2)
+ dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+ /* Y values */
+ dev->xy_cur[i + 26] = dev->data[5 * i + 1];
+ dev->xy_cur[i + 34] = dev->data[5 * i + 3];
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ if (!dev->valid) {
+ /* first sample */
+ dev->valid = 1;
+ dev->x_old = dev->y_old = -1;
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ /* 17" Powerbooks have 10 extra X sensors */
+ for (i = 16; i < ATP_XSENSORS; i++)
+ if (dev->xy_cur[i]) {
+ printk("appletouch: 17\" model detected.\n");
+ input_set_abs_params(&dev->input, ABS_X, 0,
+ (ATP_XSENSORS - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ break;
+ }
+
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+ /* accumulate the change */
+ signed char change = dev->xy_old[i] - dev->xy_cur[i];
+ dev->xy_acc[i] -= change;
+
+ /* prevent down drifting */
+ if (dev->xy_acc[i] < 0)
+ dev->xy_acc[i] = 0;
+ }
+
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ dbg_dump("accumulator", dev->xy_acc);
+
+ x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+ ATP_XFACT, &x_z, &x_f);
+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+ ATP_YFACT, &y_z, &y_f);
+
+ if (x && y) {
+ if (dev->x_old != -1) {
+ x = (dev->x_old * 3 + x) >> 2;
+ y = (dev->y_old * 3 + y) >> 2;
+ dev->x_old = x;
+ dev->y_old = y;
+
+ if (debug > 1)
+ printk("appletouch: X: %3d Y: %3d "
+ "Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+
+ input_report_key(&dev->input, BTN_TOUCH, 1);
+ input_report_abs(&dev->input, ABS_X, x);
+ input_report_abs(&dev->input, ABS_Y, y);
+ input_report_abs(&dev->input, ABS_PRESSURE,
+ min(ATP_PRESSURE, x_z + y_z));
+ atp_report_fingers(&dev->input, max(x_f, y_f));
+ }
+ dev->x_old = x;
+ dev->y_old = y;
+ }
+ else if (!x && !y) {
+
+ dev->x_old = dev->y_old = -1;
+ input_report_key(&dev->input, BTN_TOUCH, 0);
+ input_report_abs(&dev->input, ABS_PRESSURE, 0);
+ atp_report_fingers(&dev->input, 0);
+
+ /* reset the accumulator on release */
+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+ }
+
+ input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+
+ input_sync(&dev->input);
+
+exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+ }
+}
+
+static int atp_open(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ if (usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
+
+ dev->open = 1;
+ return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ usb_kill_urb(dev->urb);
+ dev->open = 0;
+}
+
+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+ struct atp *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int int_in_endpointAddr = 0;
+ int i, retval = -ENOMEM;
+
+ /* allocate memory for our device state and initialize it */
+ dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
+ if (dev == NULL) {
+ err("Out of memory");
+ goto err_kmalloc;
+ }
+ memset(dev, 0, sizeof(struct atp));
+
+ dev->udev = interface_to_usbdev(iface);
+
+ /* set up the endpoint information */
+ /* use only the first interrupt-in endpoint */
+ iface_desc = iface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if (!int_in_endpointAddr &&
+ (endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT)) {
+ /* we found an interrupt in endpoint */
+ int_in_endpointAddr = endpoint->bEndpointAddress;
+ break;
+ }
+ }
+ if (!int_in_endpointAddr) {
+ retval = -EIO;
+ err("Could not find int-in endpoint");
+ goto err_endpoint;
+ }
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
+
+ dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb) {
+ retval = -ENOMEM;
+ goto err_usballoc;
+ }
+ dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+ &dev->urb->transfer_dma);
+ if (!dev->data) {
+ retval = -ENOMEM;
+ goto err_usbbufalloc;
+ }
+ usb_fill_int_urb(dev->urb, dev->udev,
+ usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+ dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+
+ init_input_dev(&dev->input);
+ dev->input.name = "appletouch";
+ dev->input.dev = &iface->dev;
+ dev->input.private = dev;
+ dev->input.open = atp_open;
+ dev->input.close = atp_close;
+
+ usb_to_input_id(dev->udev, &dev->input.id);
+
+ set_bit(EV_ABS, dev->input.evbit);
+
+ /*
+ * 12" and 15" Powerbooks only have 16 x sensors,
+ * 17" models are detected later.
+ */
+ input_set_abs_params(&dev->input, ABS_X, 0,
+ (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(&dev->input, ABS_Y, 0,
+ (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+
+ set_bit(EV_KEY, dev->input.evbit);
+ set_bit(BTN_TOUCH, dev->input.keybit);
+ set_bit(BTN_TOOL_FINGER, dev->input.keybit);
+ set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
+ set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
+ set_bit(BTN_LEFT, dev->input.keybit);
+
+ input_register_device(&dev->input);
+
+ printk(KERN_INFO "input: appletouch connected\n");
+
+ return 0;
+
+err_usbbufalloc:
+ usb_free_urb(dev->urb);
+err_usballoc:
+ usb_set_intfdata(iface, NULL);
+err_endpoint:
+ kfree(dev);
+err_kmalloc:
+ return retval;
+}
+
+static void atp_disconnect(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+
+ usb_set_intfdata(iface, NULL);
+ if (dev) {
+ usb_kill_urb(dev->urb);
+ input_unregister_device(&dev->input);
+ usb_free_urb(dev->urb);
+ usb_buffer_free(dev->udev, ATP_DATASIZE,
+ dev->data, dev->urb->transfer_dma);
+ kfree(dev);
+ }
+ printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+static int atp_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ usb_kill_urb(dev->urb);
+ dev->valid = 0;
+ return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
+
+ return 0;
+}
+
+static struct usb_driver atp_driver = {
+ .owner = THIS_MODULE,
+ .name = "appletouch",
+ .probe = atp_probe,
+ .disconnect = atp_disconnect,
+ .suspend = atp_suspend,
+ .resume = atp_resume,
+ .id_table = atp_table,
+};
+
+static int __init atp_init(void)
+{
+ return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+ usb_deregister(&atp_driver);
+}
+
+module_init(atp_init);
+module_exit(atp_exit);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index b2cb2b35892e..a99865c689c5 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -2,7 +2,8 @@
* USB HID support for Linux
*
* Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
*/
/*
@@ -38,7 +39,7 @@
* Version Information
*/
-#define DRIVER_VERSION "v2.01"
+#define DRIVER_VERSION "v2.6"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
if (maxpacket > 0) {
padlen = (len + maxpacket - 1) / maxpacket;
padlen *= maxpacket;
- if (padlen > HID_BUFFER_SIZE)
- padlen = HID_BUFFER_SIZE;
+ if (padlen > hid->bufsize)
+ padlen = hid->bufsize;
} else
padlen = 0;
hid->urbctrl->transfer_buffer_length = padlen;
@@ -1096,6 +1097,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
switch (urb->status) {
case 0: /* success */
+ break;
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timeout on uhci */
unplug = 1;
@@ -1143,6 +1145,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
case 0: /* success */
if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+ break;
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timectrl on uhci */
unplug = 1;
@@ -1284,13 +1287,8 @@ void hid_init_reports(struct hid_device *hid)
struct hid_report *report;
int err, ret;
- list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
- int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
- if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
- if (size > hid->urbin->transfer_buffer_length)
- hid->urbin->transfer_buffer_length = size;
+ list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
- }
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
@@ -1372,12 +1370,14 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_A4TECH 0x09da
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
-#define USB_VENDOR_ID_AASHIMA 0x06D6
+#define USB_VENDOR_ID_AASHIMA 0x06d6
#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
#define USB_VENDOR_ID_CYPRESS 0x04b4
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@@ -1432,7 +1432,7 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_VENDOR_ID_LD 0x0f11
-#define USB_DEVICE_ID_CASSY 0x1000
+#define USB_DEVICE_ID_CASSY 0x1000
#define USB_DEVICE_ID_POCKETCASSY 0x1010
#define USB_DEVICE_ID_MOBILECASSY 0x1020
#define USB_DEVICE_ID_JWM 0x1080
@@ -1444,6 +1444,8 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_NETWORKANALYSER 0x2020
#define USB_DEVICE_ID_POWERCONTROL 0x2030
+#define USB_VENDOR_ID_APPLE 0x05ac
+#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
/*
* Alphabetically sorted blacklist by quirk type.
@@ -1468,6 +1470,7 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
@@ -1548,10 +1551,12 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, 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 },
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -1564,15 +1569,32 @@ static struct hid_blacklist {
{ 0, 0 }
};
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
+{
+ struct hid_report *report;
+ int size;
+
+ list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+ size = ((report->size - 1) >> 3) + 1;
+ if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
+ size++;
+ if (*max < size)
+ *max = size;
+ }
+}
+
static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
+ if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
return -1;
- if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
+ if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
return -1;
if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
return -1;
- if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+ if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
return -1;
return 0;
@@ -1581,13 +1603,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
if (hid->inbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
if (hid->outbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
if (hid->cr)
usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
if (hid->ctrlbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
@@ -1598,7 +1620,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
struct hid_device *hid;
unsigned quirks = 0, rsize = 0;
char *buf, *rdesc;
- int n;
+ int n, insize = 0;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1652,6 +1674,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
kfree(rdesc);
hid->quirks = quirks;
+ hid->bufsize = HID_MIN_BUFFER_SIZE;
+ hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
+ hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
+ hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+
+ if (hid->bufsize > HID_MAX_BUFFER_SIZE)
+ hid->bufsize = HID_MAX_BUFFER_SIZE;
+
+ hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
+
+ if (insize > HID_MAX_BUFFER_SIZE)
+ insize = HID_MAX_BUFFER_SIZE;
+
if (hid_alloc_buffers(dev, hid)) {
hid_free_buffers(dev, hid);
goto fail;
@@ -1682,10 +1717,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
+ usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
hid_irq_in, hid, interval);
hid->urbin->transfer_dma = hid->inbuf_dma;
- hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
} else {
if (hid->urbout)
continue;
@@ -1695,7 +1730,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
hid_irq_out, hid, interval);
hid->urbout->transfer_dma = hid->outbuf_dma;
- hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
}
@@ -1747,7 +1782,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->ctrlbuf, 1, hid_ctrl, hid);
hid->urbctrl->setup_dma = hid->cr_dma;
hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
- hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
return hid;
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index 52437e5e2e78..ceebab99eff2 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -85,6 +85,23 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x91, "D-PadDown"},
{0, 0x92, "D-PadRight"},
{0, 0x93, "D-PadLeft"},
+ { 2, 0, "Simulation" },
+ {0, 0xb0, "Aileron"},
+ {0, 0xb1, "AileronTrim"},
+ {0, 0xb2, "Anti-Torque"},
+ {0, 0xb3, "Autopilot"},
+ {0, 0xb4, "Chaff"},
+ {0, 0xb5, "Collective"},
+ {0, 0xb6, "DiveBrake"},
+ {0, 0xb7, "ElectronicCountermeasures"},
+ {0, 0xb8, "Elevator"},
+ {0, 0xb9, "ElevatorTrim"},
+ {0, 0xba, "Rudder"},
+ {0, 0xbb, "Throttle"},
+ {0, 0xbc, "FlightCommunications"},
+ {0, 0xbd, "FlareRelease"},
+ {0, 0xbe, "LandingGear"},
+ {0, 0xbf, "ToeBrake"},
{ 7, 0, "Keyboard" },
{ 8, 0, "LED" },
{0, 0x01, "NumLock"},
@@ -92,6 +109,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x03, "ScrollLock"},
{0, 0x04, "Compose"},
{0, 0x05, "Kana"},
+ {0, 0x4b, "GenericIndicator"},
{ 9, 0, "Button" },
{ 10, 0, "Ordinal" },
{ 12, 0, "Consumer" },
@@ -574,7 +592,8 @@ static char *keys[KEY_MAX + 1] = {
[KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
[KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
[KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
- [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13",
+ [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
+ [KEY_REDO] = "Redo", [KEY_F13] = "F13",
[KEY_F14] = "F14", [KEY_F15] = "F15",
[KEY_F16] = "F16", [KEY_F17] = "F17",
[KEY_F18] = "F18", [KEY_F19] = "F19",
@@ -584,15 +603,15 @@ static char *keys[KEY_MAX + 1] = {
[KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
[KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
[KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
- [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost",
+ [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost",
[KEY_PRINT] = "Print", [KEY_HP] = "HP",
[KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
[KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
[KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
[KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
[KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
- [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel",
- [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up",
+ [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
+ [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
[KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
@@ -622,8 +641,8 @@ static char *keys[KEY_MAX + 1] = {
[BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
- [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
- [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
+ [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
+ [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
@@ -659,6 +678,9 @@ static char *keys[KEY_MAX + 1] = {
[KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL",
[KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine",
[KEY_DEL_LINE] = "DeleteLine",
+ [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
+ [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
+ [KEY_DOCUMENTS] = "Documents",
};
static char *relatives[REL_MAX + 1] = {
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 63a4db721f7e..0b6452248a39 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -78,8 +78,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
{
struct input_dev *input = &hidinput->input;
struct hid_device *device = hidinput->input.private;
- int max, code;
- unsigned long *bit;
+ int max = 0, code;
+ unsigned long *bit = NULL;
field->hidinput = hidinput;
@@ -131,6 +131,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_key(code);
break;
+
+ case HID_UP_SIMULATION:
+
+ switch (usage->hid & 0xffff) {
+ case 0xba: map_abs(ABS_RUDDER); break;
+ case 0xbb: map_abs(ABS_THROTTLE); break;
+ }
+ break;
+
case HID_UP_GENDESK:
if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
@@ -238,8 +247,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x000: goto ignore;
case 0x034: map_key_clear(KEY_SLEEP); break;
case 0x036: map_key_clear(BTN_MISC); break;
+ case 0x045: map_key_clear(KEY_RADIO); break;
case 0x08a: map_key_clear(KEY_WWW); break;
+ case 0x08d: map_key_clear(KEY_PROGRAM); break;
case 0x095: map_key_clear(KEY_HELP); break;
+ case 0x09c: map_key_clear(KEY_CHANNELUP); break;
+ case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
case 0x0b0: map_key_clear(KEY_PLAY); break;
case 0x0b1: map_key_clear(KEY_PAUSE); break;
case 0x0b2: map_key_clear(KEY_RECORD); break;
@@ -259,6 +272,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x18a: map_key_clear(KEY_MAIL); break;
case 0x192: map_key_clear(KEY_CALC); break;
case 0x194: map_key_clear(KEY_FILE); break;
+ case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
+ case 0x201: map_key_clear(KEY_NEW); break;
+ case 0x207: map_key_clear(KEY_SAVE); break;
+ case 0x208: map_key_clear(KEY_PRINT); break;
+ case 0x209: map_key_clear(KEY_PROPS); break;
case 0x21a: map_key_clear(KEY_UNDO); break;
case 0x21b: map_key_clear(KEY_COPY); break;
case 0x21c: map_key_clear(KEY_CUT); break;
@@ -271,7 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
case 0x238: map_rel(REL_HWHEEL); break;
- default: goto unknown;
+ case 0x279: map_key_clear(KEY_REDO); break;
+ case 0x289: map_key_clear(KEY_REPLY); break;
+ case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
+ case 0x28c: map_key_clear(KEY_SEND); break;
+ default: goto ignore;
}
break;
@@ -296,9 +318,42 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_MSVENDOR:
-
goto ignore;
+ case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0x003: map_key_clear(KEY_FN); break;
+ default: goto ignore;
+ }
+ break;
+
+ case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0x004: map_key_clear(KEY_AGAIN); break;
+ case 0x00d: map_key_clear(KEY_HOME); break;
+ case 0x024: map_key_clear(KEY_SHUFFLE); break;
+ 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 0x033: map_key_clear(KEY_LAST); break;
+ case 0x047: map_key_clear(KEY_MP3); break;
+ case 0x048: map_key_clear(KEY_DVD); break;
+ case 0x049: map_key_clear(KEY_MEDIA); break;
+ case 0x04a: map_key_clear(KEY_VIDEO); break;
+ case 0x04b: map_key_clear(KEY_ANGLE); break;
+ case 0x04c: map_key_clear(KEY_LANGUAGE); break;
+ case 0x04d: map_key_clear(KEY_SUBTITLE); break;
+ case 0x051: map_key_clear(KEY_RED); break;
+ case 0x052: map_key_clear(KEY_CLOSE); break;
+ default: goto ignore;
+ }
+ break;
+
case HID_UP_PID:
set_bit(EV_FF, input->evbit);
@@ -349,6 +404,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (usage->code > max)
goto ignore;
+ if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
+ map_rel(REL_HWHEEL);
+
if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
(usage->type == EV_REL) && (usage->code == REL_WHEEL))
set_bit(REL_HWHEEL, bit);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index c1b6b69bc4a4..ec2412c42f1e 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -173,6 +173,7 @@ struct hid_item {
#define HID_UP_UNDEFINED 0x00000000
#define HID_UP_GENDESK 0x00010000
+#define HID_UP_SIMULATION 0x00020000
#define HID_UP_KEYBOARD 0x00070000
#define HID_UP_LED 0x00080000
#define HID_UP_BUTTON 0x00090000
@@ -182,6 +183,8 @@ struct hid_item {
#define HID_UP_PID 0x000f0000
#define HID_UP_HPVENDOR 0xff7f0000
#define HID_UP_MSVENDOR 0xff000000
+#define HID_UP_CUSTOM 0x00ff0000
+#define HID_UP_LOGIVENDOR 0xffbc0000
#define HID_USAGE 0x0000ffff
@@ -242,6 +245,7 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200
+#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400
/*
* This is the global environment of the parser. This information is
@@ -348,7 +352,8 @@ struct hid_report_enum {
#define HID_REPORT_TYPES 3
-#define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */
+#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
+#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
#define HID_OUTPUT_FIFO_SIZE 64
@@ -386,6 +391,8 @@ struct hid_device { /* device report descriptor */
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ unsigned int bufsize; /* URB buffer size */
+
struct urb *urbin; /* Input URB */
char *inbuf; /* Input buffer */
dma_addr_t inbuf_dma; /* Input buffer dma */
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 4c13331b5f41..d32427818af7 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -507,6 +507,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL;
hid_submit_report(hid, report, USB_DIR_OUT);
+ hid_wait_io(hid);
return 0;
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 0dc439f10823..becb87efb869 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -166,7 +166,7 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) {
+ if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) {
err("%s - Out of memory.", __FUNCTION__);
return -ENOMEM;
}
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 67dc93685203..99de1b33c07d 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -431,11 +431,6 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
- /* See if the offered device matches what we can accept */
- if ((udev->descriptor.idVendor != USB_KEYSPAN_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_KEYSPAN_PRODUCT_UIA11) )
- return -ENODEV;
-
/* allocate memory for our device state and initialize it */
remote = kmalloc(sizeof(*remote), GFP_KERNEL);
if (remote == NULL) {
diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h
new file mode 100644
index 000000000000..52ff27f15127
--- /dev/null
+++ b/drivers/usb/input/map_to_7segment.h
@@ -0,0 +1,189 @@
+/*
+ * drivers/usb/input/map_to_7segment.h
+ *
+ * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MAP_TO_7SEGMENT_H
+#define MAP_TO_7SEGMENT_H
+
+/* This file provides translation primitives and tables for the conversion
+ * of (ASCII) characters to a 7-segments notation.
+ *
+ * The 7 segment's wikipedia notation below is used as standard.
+ * See: http://en.wikipedia.org/wiki/Seven_segment_display
+ *
+ * Notation: +-a-+
+ * f b
+ * +-g-+
+ * e c
+ * +-d-+
+ *
+ * Usage:
+ *
+ * Register a map variable, and fill it with a character set:
+ * static SEG7_DEFAULT_MAP(map_seg7);
+ *
+ *
+ * Then use for conversion:
+ * seg7 = map_to_seg7(&map_seg7, some_char);
+ * ...
+ *
+ * In device drivers it is recommended, if required, to make the char map
+ * accessible via the sysfs interface using the following scheme:
+ *
+ * static ssize_t show_map(struct device *dev, char *buf) {
+ * memcpy(buf, &map_seg7, sizeof(map_seg7));
+ * return sizeof(map_seg7);
+ * }
+ * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) {
+ * if(cnt != sizeof(map_seg7))
+ * return -EINVAL;
+ * memcpy(&map_seg7, buf, cnt);
+ * return cnt;
+ * }
+ * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map);
+ *
+ * History:
+ * 2005-05-31 RFC linux-kernel@vger.kernel.org
+ */
+#include <linux/errno.h>
+
+
+#define BIT_SEG7_A 0
+#define BIT_SEG7_B 1
+#define BIT_SEG7_C 2
+#define BIT_SEG7_D 3
+#define BIT_SEG7_E 4
+#define BIT_SEG7_F 5
+#define BIT_SEG7_G 6
+#define BIT_SEG7_RESERVED 7
+
+struct seg7_conversion_map {
+ unsigned char table[128];
+};
+
+static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
+{
+ return c & 0x7f ? map->table[c] : -EINVAL;
+}
+
+#define SEG7_CONVERSION_MAP(_name, _map) \
+ struct seg7_conversion_map _name = { .table = { _map } }
+
+/*
+ * It is recommended to use a facility that allows user space to redefine
+ * custom character sets for LCD devices. Please use a sysfs interface
+ * as described above.
+ */
+#define MAP_TO_SEG7_SYSFS_FILE "map_seg7"
+
+/*******************************************************************************
+ * ASCII conversion table
+ ******************************************************************************/
+
+#define _SEG7(l,a,b,c,d,e,f,g) \
+ ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \
+ e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G )
+
+#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+
+#define _MAP_33_47_ASCII_SEG7_SYMBOL \
+ _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\
+ _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\
+ _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\
+ _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\
+ _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1),
+
+#define _MAP_48_57_ASCII_SEG7_NUMERIC \
+ _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\
+ _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\
+ _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\
+ _SEG7('9',1,1,1,1,0,1,1),
+
+#define _MAP_58_64_ASCII_SEG7_SYMBOL \
+ _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\
+ _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\
+ _SEG7('@',1,1,0,1,1,1,1),
+
+#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \
+ _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\
+ _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
+ _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\
+ _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
+ _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\
+ _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\
+ _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\
+ _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
+ _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
+
+#define _MAP_91_96_ASCII_SEG7_SYMBOL \
+ _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\
+ _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0),
+
+#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
+ _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\
+ _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
+ _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\
+ _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
+ _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\
+ _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\
+ _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\
+ _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
+ _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
+
+#define _MAP_123_126_ASCII_SEG7_SYMBOL \
+ _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\
+ _SEG7('~',1,0,0,0,0,0,0),
+
+/* Maps */
+
+/* This set tries to map as close as possible to the visible characteristics
+ * of the ASCII symbol, lowercase and uppercase letters may differ in
+ * presentation on the display.
+ */
+#define MAP_ASCII7SEG_ALPHANUM \
+ _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
+ _MAP_33_47_ASCII_SEG7_SYMBOL \
+ _MAP_48_57_ASCII_SEG7_NUMERIC \
+ _MAP_58_64_ASCII_SEG7_SYMBOL \
+ _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \
+ _MAP_91_96_ASCII_SEG7_SYMBOL \
+ _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
+ _MAP_123_126_ASCII_SEG7_SYMBOL
+
+/* This set tries to map as close as possible to the symbolic characteristics
+ * of the ASCII character for maximum discrimination.
+ * For now this means all alpha chars are in lower case representations.
+ * (This for example facilitates the use of hex numbers with uppercase input.)
+ */
+#define MAP_ASCII7SEG_ALPHANUM_LC \
+ _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \
+ _MAP_33_47_ASCII_SEG7_SYMBOL \
+ _MAP_48_57_ASCII_SEG7_NUMERIC \
+ _MAP_58_64_ASCII_SEG7_SYMBOL \
+ _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
+ _MAP_91_96_ASCII_SEG7_SYMBOL \
+ _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \
+ _MAP_123_126_ASCII_SEG7_SYMBOL
+
+#define SEG7_DEFAULT_MAP(_name) \
+ SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM)
+
+#endif /* MAP_TO_7SEGMENT_H */
+
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index 256963863478..acc71ec560e9 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -263,7 +263,7 @@ int hid_pid_init(struct hid_device *hid)
struct hid_ff_pid *private;
struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
- private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+ private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
if (!private)
return -ENOMEM;
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
new file mode 100644
index 000000000000..58a176ef96a5
--- /dev/null
+++ b/drivers/usb/input/yealink.c
@@ -0,0 +1,1013 @@
+/*
+ * drivers/usb/input/yealink.c
+ *
+ * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Description:
+ * Driver for the USB-P1K voip usb phone.
+ * This device is produced by Yealink Network Technology Co Ltd
+ * but may be branded under several names:
+ * - Yealink usb-p1k
+ * - Tiptel 115
+ * - ...
+ *
+ * This driver is based on:
+ * - the usbb2k-api http://savannah.nongnu.org/projects/usbb2k-api/
+ * - information from http://memeteau.free.fr/usbb2k
+ * - the xpad-driver drivers/usb/input/xpad.c
+ *
+ * Thanks to:
+ * - Olivier Vandorpe, for providing the usbb2k-api.
+ * - Martin Diehl, for spotting my memory allocation bug.
+ *
+ * History:
+ * 20050527 henk First version, functional keyboard. Keyboard events
+ * will pop-up on the ../input/eventX bus.
+ * 20050531 henk Added led, LCD, dialtone and sysfs interface.
+ * 20050610 henk Cleanups, make it ready for public consumption.
+ * 20050630 henk Cleanups, fixes in response to comments.
+ * 20050701 henk sysfs write serialisation, fix potential unload races
+ * 20050801 henk Added ringtone, restructure USB
+ * 20050816 henk Merge 2.6.13-rc6
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/usb.h>
+
+#include "map_to_7segment.h"
+#include "yealink.h"
+
+#define DRIVER_VERSION "yld-20050816"
+#define DRIVER_AUTHOR "Henk Vergonet"
+#define DRIVER_DESC "Yealink phone driver"
+
+#define YEALINK_POLLING_FREQUENCY 10 /* in [Hz] */
+
+struct yld_status {
+ u8 lcd[24];
+ u8 led;
+ u8 dialtone;
+ u8 ringtone;
+ u8 keynum;
+} __attribute__ ((packed));
+
+/*
+ * Register the LCD segment and icon map
+ */
+#define _LOC(k,l) { .a = (k), .m = (l) }
+#define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm) \
+ { .type = (t), \
+ .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm), \
+ _LOC(d, dm), _LOC(e, em), _LOC(g, gm), \
+ _LOC(f, fm) } } }
+#define _PIC(t, h, hm, n) \
+ { .type = (t), \
+ .u = { .p = { .name = (n), .a = (h), .m = (hm) } } }
+
+static const struct lcd_segment_map {
+ char type;
+ union {
+ struct pictogram_map {
+ u8 a,m;
+ char name[10];
+ } p;
+ struct segment_map {
+ u8 a,m;
+ } s[7];
+ } u;
+} lcdMap[] = {
+#include "yealink.h"
+};
+
+struct yealink_dev {
+ struct input_dev idev; /* input device */
+ struct usb_device *udev; /* usb device */
+
+ /* irq input channel */
+ struct yld_ctl_packet *irq_data;
+ dma_addr_t irq_dma;
+ struct urb *urb_irq;
+
+ /* control output channel */
+ struct yld_ctl_packet *ctl_data;
+ dma_addr_t ctl_dma;
+ struct usb_ctrlrequest *ctl_req;
+ dma_addr_t ctl_req_dma;
+ struct urb *urb_ctl;
+
+ char phys[64]; /* physical device path */
+
+ u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
+ int key_code; /* last reported key */
+
+ int stat_ix;
+ union {
+ struct yld_status s;
+ u8 b[sizeof(struct yld_status)];
+ } master, copy;
+};
+
+
+/*******************************************************************************
+ * Yealink lcd interface
+ ******************************************************************************/
+
+/*
+ * Register a default 7 segment character set
+ */
+static SEG7_DEFAULT_MAP(map_seg7);
+
+ /* Display a char,
+ * char '\9' and '\n' are placeholders and do not overwrite the original text.
+ * A space will always hide an icon.
+ */
+static int setChar(struct yealink_dev *yld, int el, int chr)
+{
+ int i, a, m, val;
+
+ if (el >= ARRAY_SIZE(lcdMap))
+ return -EINVAL;
+
+ if (chr == '\t' || chr == '\n')
+ return 0;
+
+ yld->lcdMap[el] = chr;
+
+ if (lcdMap[el].type == '.') {
+ a = lcdMap[el].u.p.a;
+ m = lcdMap[el].u.p.m;
+ if (chr != ' ')
+ yld->master.b[a] |= m;
+ else
+ yld->master.b[a] &= ~m;
+ return 0;
+ }
+
+ val = map_to_seg7(&map_seg7, chr);
+ for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) {
+ m = lcdMap[el].u.s[i].m;
+
+ if (m == 0)
+ continue;
+
+ a = lcdMap[el].u.s[i].a;
+ if (val & 1)
+ yld->master.b[a] |= m;
+ else
+ yld->master.b[a] &= ~m;
+ val = val >> 1;
+ }
+ return 0;
+};
+
+/*******************************************************************************
+ * Yealink key interface
+ ******************************************************************************/
+
+/* Map device buttons to internal key events.
+ *
+ * USB-P1K button layout:
+ *
+ * up
+ * IN OUT
+ * down
+ *
+ * pickup C hangup
+ * 1 2 3
+ * 4 5 6
+ * 7 8 9
+ * * 0 #
+ *
+ * The "up" and "down" keys, are symbolised by arrows on the button.
+ * The "pickup" and "hangup" keys are symbolised by a green and red phone
+ * on the button.
+ */
+static int map_p1k_to_key(int scancode)
+{
+ switch(scancode) { /* phone key: */
+ case 0x23: return KEY_LEFT; /* IN */
+ case 0x33: return KEY_UP; /* up */
+ case 0x04: return KEY_RIGHT; /* OUT */
+ case 0x24: return KEY_DOWN; /* down */
+ case 0x03: return KEY_ENTER; /* pickup */
+ case 0x14: return KEY_BACKSPACE; /* C */
+ case 0x13: return KEY_ESC; /* hangup */
+ case 0x00: return KEY_1; /* 1 */
+ case 0x01: return KEY_2; /* 2 */
+ case 0x02: return KEY_3; /* 3 */
+ case 0x10: return KEY_4; /* 4 */
+ case 0x11: return KEY_5; /* 5 */
+ case 0x12: return KEY_6; /* 6 */
+ case 0x20: return KEY_7; /* 7 */
+ case 0x21: return KEY_8; /* 8 */
+ case 0x22: return KEY_9; /* 9 */
+ case 0x30: return KEY_KPASTERISK; /* * */
+ case 0x31: return KEY_0; /* 0 */
+ case 0x32: return KEY_LEFTSHIFT |
+ KEY_3 << 8; /* # */
+ }
+ return -EINVAL;
+}
+
+/* Completes a request by converting the data into events for the
+ * input subsystem.
+ *
+ * The key parameter can be cascaded: key2 << 8 | key1
+ */
+static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs)
+{
+ struct input_dev *idev = &yld->idev;
+
+ input_regs(idev, regs);
+ if (yld->key_code >= 0) {
+ /* old key up */
+ input_report_key(idev, yld->key_code & 0xff, 0);
+ if (yld->key_code >> 8)
+ input_report_key(idev, yld->key_code >> 8, 0);
+ }
+
+ yld->key_code = key;
+ if (key >= 0) {
+ /* new valid key */
+ input_report_key(idev, key & 0xff, 1);
+ if (key >> 8)
+ input_report_key(idev, key >> 8, 1);
+ }
+ input_sync(idev);
+}
+
+/*******************************************************************************
+ * Yealink usb communication interface
+ ******************************************************************************/
+
+static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p)
+{
+ u8 *buf = (u8 *)p;
+ int i;
+ u8 sum = 0;
+
+ for(i=0; i<USB_PKT_LEN-1; i++)
+ sum -= buf[i];
+ p->sum = sum;
+ return usb_control_msg(yld->udev,
+ usb_sndctrlpipe(yld->udev, 0),
+ USB_REQ_SET_CONFIGURATION,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x200, 3,
+ p, sizeof(*p),
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static u8 default_ringtone[] = {
+ 0xEF, /* volume [0-255] */
+ 0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */
+ 0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */
+ 0x00, 0x00 /* end of sequence */
+};
+
+static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size)
+{
+ struct yld_ctl_packet *p = yld->ctl_data;
+ int ix, len;
+
+ if (size <= 0)
+ return -EINVAL;
+
+ /* Set the ringtone volume */
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_RING_VOLUME;
+ yld->ctl_data->size = 1;
+ yld->ctl_data->data[0] = buf[0];
+ yealink_cmd(yld, p);
+
+ buf++;
+ size--;
+
+ p->cmd = CMD_RING_NOTE;
+ ix = 0;
+ while (size != ix) {
+ len = size - ix;
+ if (len > sizeof(p->data))
+ len = sizeof(p->data);
+ p->size = len;
+ p->offset = cpu_to_be16(ix);
+ memcpy(p->data, &buf[ix], len);
+ yealink_cmd(yld, p);
+ ix += len;
+ }
+ return 0;
+}
+
+/* keep stat_master & stat_copy in sync.
+ */
+static int yealink_do_idle_tasks(struct yealink_dev *yld)
+{
+ u8 val;
+ int i, ix, len;
+
+ ix = yld->stat_ix;
+
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_KEYPRESS;
+ yld->ctl_data->size = 1;
+ yld->ctl_data->sum = 0xff - CMD_KEYPRESS;
+
+ /* If state update pointer wraps do a KEYPRESS first. */
+ if (ix >= sizeof(yld->master)) {
+ yld->stat_ix = 0;
+ return 0;
+ }
+
+ /* find update candidates: copy != master */
+ do {
+ val = yld->master.b[ix];
+ if (val != yld->copy.b[ix])
+ goto send_update;
+ } while (++ix < sizeof(yld->master));
+
+ /* nothing todo, wait a bit and poll for a KEYPRESS */
+ yld->stat_ix = 0;
+ /* TODO how can we wait abit. ??
+ * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY);
+ */
+ return 0;
+
+send_update:
+
+ /* Setup an appropriate update request */
+ yld->copy.b[ix] = val;
+ yld->ctl_data->data[0] = val;
+
+ switch(ix) {
+ case offsetof(struct yld_status, led):
+ yld->ctl_data->cmd = CMD_LED;
+ yld->ctl_data->sum = -1 - CMD_LED - val;
+ break;
+ case offsetof(struct yld_status, dialtone):
+ yld->ctl_data->cmd = CMD_DIALTONE;
+ yld->ctl_data->sum = -1 - CMD_DIALTONE - val;
+ break;
+ case offsetof(struct yld_status, ringtone):
+ yld->ctl_data->cmd = CMD_RINGTONE;
+ yld->ctl_data->sum = -1 - CMD_RINGTONE - val;
+ break;
+ case offsetof(struct yld_status, keynum):
+ val--;
+ val &= 0x1f;
+ yld->ctl_data->cmd = CMD_SCANCODE;
+ yld->ctl_data->offset = cpu_to_be16(val);
+ yld->ctl_data->data[0] = 0;
+ yld->ctl_data->sum = -1 - CMD_SCANCODE - val;
+ break;
+ default:
+ len = sizeof(yld->master.s.lcd) - ix;
+ if (len > sizeof(yld->ctl_data->data))
+ len = sizeof(yld->ctl_data->data);
+
+ /* Combine up to <len> consecutive LCD bytes in a singe request
+ */
+ yld->ctl_data->cmd = CMD_LCD;
+ yld->ctl_data->offset = cpu_to_be16(ix);
+ yld->ctl_data->size = len;
+ yld->ctl_data->sum = -CMD_LCD - ix - val - len;
+ for(i=1; i<len; i++) {
+ ix++;
+ val = yld->master.b[ix];
+ yld->copy.b[ix] = val;
+ yld->ctl_data->data[i] = val;
+ yld->ctl_data->sum -= val;
+ }
+ }
+ yld->stat_ix = ix + 1;
+ return 1;
+}
+
+/* Decide on how to handle responses
+ *
+ * The state transition diagram is somethhing like:
+ *
+ * syncState<--+
+ * | |
+ * | idle
+ * \|/ |
+ * init --ok--> waitForKey --ok--> getKey
+ * ^ ^ |
+ * | +-------ok-------+
+ * error,start
+ *
+ */
+static void urb_irq_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct yealink_dev *yld = urb->context;
+ int ret;
+
+ if (urb->status)
+ err("%s - urb status %d", __FUNCTION__, urb->status);
+
+ switch (yld->irq_data->cmd) {
+ case CMD_KEYPRESS:
+
+ yld->master.s.keynum = yld->irq_data->data[0];
+ break;
+
+ case CMD_SCANCODE:
+ dbg("get scancode %x", yld->irq_data->data[0]);
+
+ report_key(yld, map_p1k_to_key(yld->irq_data->data[0]), regs);
+ break;
+
+ default:
+ err("unexpected response %x", yld->irq_data->cmd);
+ }
+
+ yealink_do_idle_tasks(yld);
+
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (ret)
+ err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+}
+
+static void urb_ctl_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct yealink_dev *yld = urb->context;
+ int ret;
+
+ if (urb->status)
+ err("%s - urb status %d", __FUNCTION__, urb->status);
+
+ switch (yld->ctl_data->cmd) {
+ case CMD_KEYPRESS:
+ case CMD_SCANCODE:
+ /* ask for a response */
+ ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+ break;
+ default:
+ /* send new command */
+ yealink_do_idle_tasks(yld);
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ }
+
+ if (ret)
+ err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+}
+
+/*******************************************************************************
+ * input event interface
+ ******************************************************************************/
+
+/* TODO should we issue a ringtone on a SND_BELL event?
+static int input_ev(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
+{
+
+ if (type != EV_SND)
+ return -EINVAL;
+
+ switch (code) {
+ case SND_BELL:
+ case SND_TONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+*/
+
+static int input_open(struct input_dev *dev)
+{
+ struct yealink_dev *yld = dev->private;
+ int i, ret;
+
+ dbg("%s", __FUNCTION__);
+
+ /* force updates to device */
+ for (i = 0; i<sizeof(yld->master); i++)
+ yld->copy.b[i] = ~yld->master.b[i];
+ yld->key_code = -1; /* no keys pressed */
+
+ yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone));
+
+ /* issue INIT */
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_INIT;
+ yld->ctl_data->size = 10;
+ yld->ctl_data->sum = 0x100-CMD_INIT-10;
+ if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
+ dbg("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static void input_close(struct input_dev *dev)
+{
+ struct yealink_dev *yld = dev->private;
+
+ usb_kill_urb(yld->urb_ctl);
+ usb_kill_urb(yld->urb_irq);
+}
+
+/*******************************************************************************
+ * sysfs interface
+ ******************************************************************************/
+
+static DECLARE_RWSEM(sysfs_rwsema);
+
+/* Interface to the 7-segments translation table aka. char set.
+ */
+static ssize_t show_map(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ memcpy(buf, &map_seg7, sizeof(map_seg7));
+ return sizeof(map_seg7);
+}
+
+static ssize_t store_map(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t cnt)
+{
+ if (cnt != sizeof(map_seg7))
+ return -EINVAL;
+ memcpy(&map_seg7, buf, sizeof(map_seg7));
+ return sizeof(map_seg7);
+}
+
+/* Interface to the LCD.
+ */
+
+/* Reading /sys/../lineX will return the format string with its settings:
+ *
+ * Example:
+ * cat ./line3
+ * 888888888888
+ * Linux Rocks!
+ */
+static ssize_t show_line(struct device *dev, char *buf, int a, int b)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_read(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_read(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = a; i < b; i++)
+ *buf++ = lcdMap[i].type;
+ *buf++ = '\n';
+ for (i = a; i < b; i++)
+ *buf++ = yld->lcdMap[i];
+ *buf++ = '\n';
+ *buf = 0;
+
+ up_read(&sysfs_rwsema);
+ return 3 + ((b - a) << 1);
+}
+
+static ssize_t show_line1(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET);
+}
+
+static ssize_t show_line2(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET);
+}
+
+static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET);
+}
+
+/* Writing to /sys/../lineX will set the coresponding LCD line.
+ * - Excess characters are ignored.
+ * - If less characters are written than allowed, the remaining digits are
+ * unchanged.
+ * - The '\n' or '\t' char is a placeholder, it does not overwrite the
+ * original content.
+ */
+static ssize_t store_line(struct device *dev, const char *buf, size_t count,
+ int el, size_t len)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ if (len > count)
+ len = count;
+ for (i = 0; i < len; i++)
+ setChar(yld, el++, buf[i]);
+
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+static ssize_t store_line1(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE);
+}
+
+static ssize_t store_line2(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE);
+}
+
+static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE);
+}
+
+/* Interface to visible and audible "icons", these include:
+ * pictures on the LCD, the LED, and the dialtone signal.
+ */
+
+/* Get a list of "switchable elements" with their current state. */
+static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct yealink_dev *yld;
+ int i, ret = 1;
+
+ down_read(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_read(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
+ if (lcdMap[i].type != '.')
+ continue;
+ ret += sprintf(&buf[ret], "%s %s\n",
+ yld->lcdMap[i] == ' ' ? " " : "on",
+ lcdMap[i].u.p.name);
+ }
+ up_read(&sysfs_rwsema);
+ return ret;
+}
+
+/* Change the visibility of a particular element. */
+static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
+ int chr)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
+ if (lcdMap[i].type != '.')
+ continue;
+ if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) {
+ setChar(yld, i, chr);
+ break;
+ }
+ }
+
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+static ssize_t show_icon(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return set_icon(dev, buf, count, buf[0]);
+}
+
+static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return set_icon(dev, buf, count, ' ');
+}
+
+/* Upload a ringtone to the device.
+ */
+
+/* Stores raw ringtone data in the phone */
+static ssize_t store_ringtone(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct yealink_dev *yld;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ /* TODO locking with async usb control interface??? */
+ yealink_set_ringtone(yld, (char *)buf, count);
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+#define _M444 S_IRUGO
+#define _M664 S_IRUGO|S_IWUSR|S_IWGRP
+#define _M220 S_IWUSR|S_IWGRP
+
+static DEVICE_ATTR(map_seg7 , _M664, show_map , store_map );
+static DEVICE_ATTR(line1 , _M664, show_line1 , store_line1 );
+static DEVICE_ATTR(line2 , _M664, show_line2 , store_line2 );
+static DEVICE_ATTR(line3 , _M664, show_line3 , store_line3 );
+static DEVICE_ATTR(get_icons , _M444, get_icons , NULL );
+static DEVICE_ATTR(show_icon , _M220, NULL , show_icon );
+static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon );
+static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone);
+
+static struct attribute *yld_attributes[] = {
+ &dev_attr_line1.attr,
+ &dev_attr_line2.attr,
+ &dev_attr_line3.attr,
+ &dev_attr_get_icons.attr,
+ &dev_attr_show_icon.attr,
+ &dev_attr_hide_icon.attr,
+ &dev_attr_map_seg7.attr,
+ &dev_attr_ringtone.attr,
+ NULL
+};
+
+static struct attribute_group yld_attr_group = {
+ .attrs = yld_attributes
+};
+
+/*******************************************************************************
+ * Linux interface and usb initialisation
+ ******************************************************************************/
+
+static const struct yld_device {
+ u16 idVendor;
+ u16 idProduct;
+ char *name;
+} yld_device[] = {
+ { 0x6993, 0xb001, "Yealink usb-p1k" },
+};
+
+static struct usb_device_id usb_table [] = {
+ { USB_INTERFACE_INFO(USB_CLASS_HID, 0, 0) },
+ { }
+};
+
+static int usb_cleanup(struct yealink_dev *yld, int err)
+{
+ if (yld == NULL)
+ return err;
+
+ if (yld->urb_irq) {
+ usb_kill_urb(yld->urb_irq);
+ usb_free_urb(yld->urb_irq);
+ }
+ if (yld->urb_ctl)
+ usb_free_urb(yld->urb_ctl);
+ if (yld->idev.dev)
+ input_unregister_device(&yld->idev);
+ if (yld->ctl_req)
+ usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
+ yld->ctl_req, yld->ctl_req_dma);
+ if (yld->ctl_data)
+ usb_buffer_free(yld->udev, USB_PKT_LEN,
+ yld->ctl_data, yld->ctl_dma);
+ if (yld->irq_data)
+ usb_buffer_free(yld->udev, USB_PKT_LEN,
+ yld->irq_data, yld->irq_dma);
+ kfree(yld);
+ return err;
+}
+
+static void usb_disconnect(struct usb_interface *intf)
+{
+ struct yealink_dev *yld;
+
+ down_write(&sysfs_rwsema);
+ yld = usb_get_intfdata(intf);
+ sysfs_remove_group(&intf->dev.kobj, &yld_attr_group);
+ usb_set_intfdata(intf, NULL);
+ up_write(&sysfs_rwsema);
+
+ usb_cleanup(yld, 0);
+}
+
+static int usb_match(struct usb_device *udev)
+{
+ int i;
+ u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
+ u16 idProduct = le16_to_cpu(udev->descriptor.idProduct);
+
+ for (i = 0; i < ARRAY_SIZE(yld_device); i++) {
+ if ((idVendor == yld_device[i].idVendor) &&
+ (idProduct == yld_device[i].idProduct))
+ return i;
+ }
+ return -ENODEV;
+}
+
+static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev (intf);
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct yealink_dev *yld;
+ char path[64];
+ int ret, pipe, i;
+
+ i = usb_match(udev);
+ if (i < 0)
+ return -ENODEV;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+ if (!(endpoint->bEndpointAddress & 0x80))
+ return -EIO;
+ if ((endpoint->bmAttributes & 3) != 3)
+ return -EIO;
+
+ if ((yld = kmalloc(sizeof(struct yealink_dev), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ memset(yld, 0, sizeof(*yld));
+ yld->udev = udev;
+
+ /* allocate usb buffers */
+ yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ SLAB_ATOMIC, &yld->irq_dma);
+ if (yld->irq_data == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ SLAB_ATOMIC, &yld->ctl_dma);
+ if (!yld->ctl_data)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
+ SLAB_ATOMIC, &yld->ctl_req_dma);
+ if (yld->ctl_req == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ /* allocate urb structures */
+ yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (yld->urb_irq == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
+ if (yld->urb_ctl == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ /* get a handle to the interrupt data pipe */
+ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+ ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ if (ret != USB_PKT_LEN)
+ err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+
+ /* initialise irq urb */
+ usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
+ USB_PKT_LEN,
+ urb_irq_callback,
+ yld, endpoint->bInterval);
+ yld->urb_irq->transfer_dma = yld->irq_dma;
+ yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ yld->urb_irq->dev = udev;
+
+ /* initialise ctl urb */
+ yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
+ USB_DIR_OUT;
+ yld->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION;
+ yld->ctl_req->wValue = cpu_to_le16(0x200);
+ yld->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
+ yld->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN);
+
+ usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+ (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
+ urb_ctl_callback, yld);
+ yld->urb_ctl->setup_dma = yld->ctl_req_dma;
+ yld->urb_ctl->transfer_dma = yld->ctl_dma;
+ yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
+ URB_NO_TRANSFER_DMA_MAP;
+ yld->urb_ctl->dev = udev;
+
+ /* find out the physical bus location */
+ if (usb_make_path(udev, path, sizeof(path)) > 0)
+ snprintf(yld->phys, sizeof(yld->phys)-1, "%s/input0", path);
+
+ /* register settings for the input device */
+ init_input_dev(&yld->idev);
+ yld->idev.private = yld;
+ yld->idev.id.bustype = BUS_USB;
+ yld->idev.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ yld->idev.id.product = le16_to_cpu(udev->descriptor.idProduct);
+ yld->idev.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
+ yld->idev.dev = &intf->dev;
+ yld->idev.name = yld_device[i].name;
+ yld->idev.phys = yld->phys;
+ /* yld->idev.event = input_ev; TODO */
+ yld->idev.open = input_open;
+ yld->idev.close = input_close;
+
+ /* register available key events */
+ yld->idev.evbit[0] = BIT(EV_KEY);
+ for (i = 0; i < 256; i++) {
+ int k = map_p1k_to_key(i);
+ if (k >= 0) {
+ set_bit(k & 0xff, yld->idev.keybit);
+ if (k >> 8)
+ set_bit(k >> 8, yld->idev.keybit);
+ }
+ }
+
+ printk(KERN_INFO "input: %s on %s\n", yld->idev.name, path);
+
+ input_register_device(&yld->idev);
+
+ usb_set_intfdata(intf, yld);
+
+ /* clear visible elements */
+ for (i=0; i<ARRAY_SIZE(lcdMap); i++)
+ setChar(yld, i, ' ');
+
+ /* display driver version on LCD line 3 */
+ store_line3(&intf->dev, NULL,
+ DRIVER_VERSION, sizeof(DRIVER_VERSION));
+
+ /* Register sysfs hooks (don't care about failure) */
+ sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
+ return 0;
+}
+
+static struct usb_driver yealink_driver = {
+ .owner = THIS_MODULE,
+ .name = "yealink",
+ .probe = usb_probe,
+ .disconnect = usb_disconnect,
+ .id_table = usb_table,
+};
+
+static int __init yealink_dev_init(void)
+{
+ int ret = usb_register(&yealink_driver);
+ if (ret == 0)
+ info(DRIVER_DESC ":" DRIVER_VERSION);
+ return ret;
+}
+
+static void __exit yealink_dev_exit(void)
+{
+ usb_deregister(&yealink_driver);
+}
+
+module_init(yealink_dev_init);
+module_exit(yealink_dev_exit);
+
+MODULE_DEVICE_TABLE (usb, usb_table);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/yealink.h b/drivers/usb/input/yealink.h
new file mode 100644
index 000000000000..48af0be9cbdf
--- /dev/null
+++ b/drivers/usb/input/yealink.h
@@ -0,0 +1,220 @@
+/*
+ * drivers/usb/input/yealink.h
+ *
+ * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef INPUT_YEALINK_H
+#define INPUT_YEALINK_H
+
+/* Using the control channel on interface 3 various aspects of the phone
+ * can be controlled like LCD, LED, dialtone and the ringtone.
+ */
+
+struct yld_ctl_packet {
+ u8 cmd; /* command code, see below */
+ u8 size; /* 1-11, size of used data bytes. */
+ u16 offset; /* internal packet offset */
+ u8 data[11];
+ s8 sum; /* negative sum of 15 preceding bytes */
+} __attribute__ ((packed));
+
+#define USB_PKT_LEN sizeof(struct yld_ctl_packet)
+
+/* The following yld_ctl_packet's are available: */
+
+/* Init registers
+ *
+ * cmd 0x8e
+ * size 10
+ * offset 0
+ * data 0,0,0,0....
+ */
+#define CMD_INIT 0x8e
+
+/* Request key scan
+ *
+ * cmd 0x80
+ * size 1
+ * offset 0
+ * data[0] on return returns the key number, if it changes there's a new
+ * key pressed.
+ */
+#define CMD_KEYPRESS 0x80
+
+/* Request scancode
+ *
+ * cmd 0x81
+ * size 1
+ * offset key number [0-1f]
+ * data[0] on return returns the scancode
+ */
+#define CMD_SCANCODE 0x81
+
+/* Set LCD
+ *
+ * cmd 0x04
+ * size 1-11
+ * offset 0-23
+ * data segment bits
+ */
+#define CMD_LCD 0x04
+
+/* Set led
+ *
+ * cmd 0x05
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 1 ON
+ */
+#define CMD_LED 0x05
+
+/* Set ringtone volume
+ *
+ * cmd 0x11
+ * size 1
+ * offset 0
+ * data[0] 0-0xff volume
+ */
+#define CMD_RING_VOLUME 0x11
+
+/* Set ringtone notes
+ *
+ * cmd 0x02
+ * size 1-11
+ * offset 0->
+ * data binary representation LE16(-freq), LE16(duration) ....
+ */
+#define CMD_RING_NOTE 0x02
+
+/* Sound ringtone via the speaker on the back
+ *
+ * cmd 0x03
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 0x24 ON
+ */
+#define CMD_RINGTONE 0x03
+
+/* Sound dial tone via the ear speaker
+ *
+ * cmd 0x09
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 1 ON
+ */
+#define CMD_DIALTONE 0x09
+
+#endif /* INPUT_YEALINK_H */
+
+
+#if defined(_SEG) && defined(_PIC)
+/* This table maps the LCD segments onto individual bit positions in the
+ * yld_status struct.
+ */
+
+/* LCD, each segment must be driven seperately.
+ *
+ * Layout:
+ *
+ * |[] [][] [][] [][] in |[][]
+ * |[] M [][] D [][] : [][] out |[][]
+ * store
+ *
+ * NEW REP SU MO TU WE TH FR SA
+ *
+ * [] [] [] [] [] [] [] [] [] [] [] []
+ * [] [] [] [] [] [] [] [] [] [] [] []
+ */
+
+/* Line 1
+ * Format : 18.e8.M8.88...188
+ * Icon names : M D : IN OUT STORE
+ */
+#define LCD_LINE1_OFFSET 0
+#define LCD_LINE1_SIZE 17
+
+/* Note: first g then f => ! ! */
+/* _SEG( type a b c d e g f ) */
+ _SEG('1', 0,0 , 22,2 , 22,2 , 0,0 , 0,0 , 0,0 , 0,0 ),
+ _SEG('8', 20,1 , 20,2 , 20,4 , 20,8 , 21,4 , 21,2 , 21,1 ),
+ _PIC('.', 22,1 , "M" ),
+ _SEG('e', 18,1 , 18,2 , 18,4 , 18,1 , 19,2 , 18,1 , 19,1 ),
+ _SEG('8', 16,1 , 16,2 , 16,4 , 16,8 , 17,4 , 17,2 , 17,1 ),
+ _PIC('.', 15,8 , "D" ),
+ _SEG('M', 14,1 , 14,2 , 14,4 , 14,1 , 15,4 , 15,2 , 15,1 ),
+ _SEG('8', 12,1 , 12,2 , 12,4 , 12,8 , 13,4 , 13,2 , 13,1 ),
+ _PIC('.', 11,8 , ":" ),
+ _SEG('8', 10,1 , 10,2 , 10,4 , 10,8 , 11,4 , 11,2 , 11,1 ),
+ _SEG('8', 8,1 , 8,2 , 8,4 , 8,8 , 9,4 , 9,2 , 9,1 ),
+ _PIC('.', 7,1 , "IN" ),
+ _PIC('.', 7,2 , "OUT" ),
+ _PIC('.', 7,4 , "STORE" ),
+ _SEG('1', 0,0 , 5,1 , 5,1 , 0,0 , 0,0 , 0,0 , 0,0 ),
+ _SEG('8', 4,1 , 4,2 , 4,4 , 4,8 , 5,8 , 5,4 , 5,2 ),
+ _SEG('8', 2,1 , 2,2 , 2,4 , 2,8 , 3,4 , 3,2 , 3,1 ),
+
+/* Line 2
+ * Format : .........
+ * Pict. name : NEW REP SU MO TU WE TH FR SA
+ */
+#define LCD_LINE2_OFFSET LCD_LINE1_OFFSET + LCD_LINE1_SIZE
+#define LCD_LINE2_SIZE 9
+
+ _PIC('.', 23,2 , "NEW" ),
+ _PIC('.', 23,4 , "REP" ),
+ _PIC('.', 1,8 , "SU" ),
+ _PIC('.', 1,4 , "MO" ),
+ _PIC('.', 1,2 , "TU" ),
+ _PIC('.', 1,1 , "WE" ),
+ _PIC('.', 0,1 , "TH" ),
+ _PIC('.', 0,2 , "FR" ),
+ _PIC('.', 0,4 , "SA" ),
+
+/* Line 3
+ * Format : 888888888888
+ */
+#define LCD_LINE3_OFFSET LCD_LINE2_OFFSET + LCD_LINE2_SIZE
+#define LCD_LINE3_SIZE 12
+
+ _SEG('8', 22,16, 22,32, 22,64, 22,128, 23,128, 23,64, 23,32 ),
+ _SEG('8', 20,16, 20,32, 20,64, 20,128, 21,128, 21,64, 21,32 ),
+ _SEG('8', 18,16, 18,32, 18,64, 18,128, 19,128, 19,64, 19,32 ),
+ _SEG('8', 16,16, 16,32, 16,64, 16,128, 17,128, 17,64, 17,32 ),
+ _SEG('8', 14,16, 14,32, 14,64, 14,128, 15,128, 15,64, 15,32 ),
+ _SEG('8', 12,16, 12,32, 12,64, 12,128, 13,128, 13,64, 13,32 ),
+ _SEG('8', 10,16, 10,32, 10,64, 10,128, 11,128, 11,64, 11,32 ),
+ _SEG('8', 8,16, 8,32, 8,64, 8,128, 9,128, 9,64, 9,32 ),
+ _SEG('8', 6,16, 6,32, 6,64, 6,128, 7,128, 7,64, 7,32 ),
+ _SEG('8', 4,16, 4,32, 4,64, 4,128, 5,128, 5,64, 5,32 ),
+ _SEG('8', 2,16, 2,32, 2,64, 2,128, 3,128, 3,64, 3,32 ),
+ _SEG('8', 0,16, 0,32, 0,64, 0,128, 1,128, 1,64, 1,32 ),
+
+/* Line 4
+ *
+ * The LED, DIALTONE and RINGTONE are implemented as icons and use the same
+ * sysfs interface.
+ */
+#define LCD_LINE4_OFFSET LCD_LINE3_OFFSET + LCD_LINE3_SIZE
+
+ _PIC('.', offsetof(struct yld_status, led) , 0x01, "LED" ),
+ _PIC('.', offsetof(struct yld_status, dialtone) , 0x01, "DIALTONE" ),
+ _PIC('.', offsetof(struct yld_status, ringtone) , 0x24, "RINGTONE" ),
+
+#undef _SEG
+#undef _PIC
+#endif /* _SEG && _PIC */
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 7398a7f19c1e..0fd0fa9fec21 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -260,7 +260,7 @@ static int stv_stop_video (struct usb_stv *dev)
PDEBUG (0, "STV(i): Camera set to original resolution");
}
/* origMode */
- kfree (buf);
+ kfree(buf);
return i;
}
@@ -276,7 +276,7 @@ static int stv_set_video_mode (struct usb_stv *dev)
}
if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
- kfree (buf);
+ kfree(buf);
return i;
}
@@ -301,13 +301,13 @@ static int stv_set_video_mode (struct usb_stv *dev)
goto exit;
error:
- kfree (buf);
+ kfree(buf);
if (stop_video == 1)
stv_stop_video (dev);
return -1;
exit:
- kfree (buf);
+ kfree(buf);
return 0;
}
@@ -327,7 +327,7 @@ static int stv_init (struct usb_stv *stv680)
/* set config 1, interface 0, alternate 0 */
if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
- kfree (buffer);
+ kfree(buffer);
PDEBUG (0, "STV(e): set config 1,0,0 failed");
return -1;
}
@@ -435,11 +435,11 @@ static int stv_init (struct usb_stv *stv680)
error:
i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */
PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]);
- kfree (buffer);
+ kfree(buffer);
return -1;
exit:
- kfree (buffer);
+ kfree(buffer);
/* video = 320x240, 352x288 */
if (stv680->CIF == 1) {
@@ -708,10 +708,10 @@ static int stv680_stop_stream (struct usb_stv *stv680)
usb_kill_urb (stv680->urb[i]);
usb_free_urb (stv680->urb[i]);
stv680->urb[i] = NULL;
- kfree (stv680->sbuf[i].data);
+ kfree(stv680->sbuf[i].data);
}
for (i = 0; i < STV680_NUMSCRATCH; i++) {
- kfree (stv680->scratch[i].data);
+ kfree(stv680->scratch[i].data);
stv680->scratch[i].data = NULL;
}
@@ -1068,7 +1068,7 @@ static int stv_close (struct inode *inode, struct file *file)
stv680->user = 0;
if (stv680->removed) {
- kfree (stv680);
+ kfree(stv680);
stv680 = NULL;
PDEBUG (0, "STV(i): device unregistered");
}
@@ -1445,14 +1445,14 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
usb_kill_urb (stv680->urb[i]);
usb_free_urb (stv680->urb[i]);
stv680->urb[i] = NULL;
- kfree (stv680->sbuf[i].data);
+ kfree(stv680->sbuf[i].data);
}
for (i = 0; i < STV680_NUMSCRATCH; i++)
- kfree (stv680->scratch[i].data);
+ kfree(stv680->scratch[i].data);
PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
/* Free the memory */
- kfree (stv680);
+ kfree(stv680);
}
static void stv680_disconnect (struct usb_interface *intf)
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index ca9f3a30634f..f36c0b6c6e36 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1523,7 +1523,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap)
static int w9968cf_i2c_attach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
int id = client->driver->id, err = 0;
if (id == I2C_DRIVERID_OVCAMCHIP) {
@@ -1535,12 +1534,12 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
}
} else {
DBG(4, "Rejected client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->name)
return -EINVAL;
}
DBG(5, "I2C attach client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->name)
return 0;
}
@@ -1549,12 +1548,11 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
static int w9968cf_i2c_detach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
if (cam->sensor_client == client)
cam->sensor_client = NULL;
- DBG(5, "I2C detach client [%s]", clientname)
+ DBG(5, "I2C detach client [%s]", client->name)
return 0;
}
@@ -1573,15 +1571,13 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
int err = 0;
static struct i2c_algorithm algo = {
- .name = "W996[87]CF algorithm",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = w9968cf_i2c_smbus_xfer,
.algo_control = w9968cf_i2c_control,
.functionality = w9968cf_i2c_func,
};
static struct i2c_adapter adap = {
- .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
+ .id = I2C_HW_SMBUS_W9968CF,
.class = I2C_CLASS_CAM_DIGITAL,
.owner = THIS_MODULE,
.client_register = w9968cf_i2c_attach_inform,
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 6f7994f5a714..ae4681f9f0ea 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -426,7 +426,7 @@ static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
/* cancel an urb which is submitted to the chain
the result is 0 if the urb is cancelled, or -EINPROGRESS if
- URB_ASYNC_UNLINK is set and the function is successfully started.
+ the function is successfully started.
*/
static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
{
@@ -515,7 +515,6 @@ static void auerchain_unlink_all (pauerchain_t acp)
acep = acp->active;
if (acep) {
urbp = acep->urbp;
- urbp->transfer_flags &= ~URB_ASYNC_UNLINK;
dbg ("unlink active urb");
usb_kill_urb (urbp);
}
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index ad17892aac9e..7e93ac96490f 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -464,7 +464,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
bytes_to_read = min(count, *actual_buffer);
if (bytes_to_read < *actual_buffer)
- dev_warn(&dev->intf->dev, "Read buffer overflow, %d bytes dropped\n",
+ dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
*actual_buffer-bytes_to_read);
/* copy one interrupt_in_buffer from ring_buffer into userspace */
@@ -528,8 +528,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
/* write the data into interrupt_out_buffer from userspace */
bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
if (bytes_to_write < count)
- dev_warn(&dev->intf->dev, "Write buffer overflow, %d bytes dropped\n",count-bytes_to_write);
- dbg_info(&dev->intf->dev, "%s: count = %d, bytes_to_write = %d\n", __FUNCTION__, count, bytes_to_write);
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
retval = -EFAULT;
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e144caf7..7603cbe0865d 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -4,11 +4,43 @@ config USB_SISUSBVGA
depends on USB && USB_EHCI_HCD
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
- Net2280 and a SiS315 chip.
-
- Note that this device requires a USB 2.0 host controller. It will not
+ Net2280 and a SiS315 chip.
+
+ Note that this device requires a USB 2.0 host controller. It will not
work with USB 1.x controllers.
- To compile this driver as a module, choose M here: the module will be
- called sisusb. If unsure, say N.
+ To compile this driver as a module, choose M here; the module will be
+ called sisusbvga. If unsure, say N.
+
+config USB_SISUSBVGA_CON
+ bool "Text console and mode switching support" if USB_SISUSBVGA
+ depends on VT
+ select FONT_8x16
+ ---help---
+ Say Y here if you want a VGA text console via the USB dongle or
+ want to support userland applications that utilize the driver's
+ display mode switching capabilities.
+
+ Note that this console supports VGA/EGA text mode only.
+
+ By default, the console part of the driver will not kick in when
+ the driver is initialized. If you want the driver to take over
+ one or more of the consoles, you need to specify the number of
+ the first and last consoles (starting at 1) as driver parameters.
+
+ For example, if the driver is compiled as a module:
+
+ modprobe sisusbvga first=1 last=5
+
+ If you use hotplug, add this to your modutils config files with
+ the "options" keyword, such as eg.
+
+ options sisusbvga first=1 last=5
+
+ If the driver is compiled into the kernel image, the parameters
+ must be given in the kernel command like, such as
+
+ sisusbvga.first=1 sisusbvga.last=5
+
+
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643ceaf8..7f934cfc906c 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,7 @@
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
+
+sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 2fd12264fd53..39db3155723a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
+ * Main part
+ *
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
#include <linux/kref.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
#include "sisusb.h"
+#ifdef INCL_SISUSB_CON
+#include <linux/font.h>
+#endif
+
#define SISUSB_DONTSYNC
/* Forward declarations / clean-up routines */
+#ifdef INCL_SISUSB_CON
+int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
+int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
+int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
+int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
+int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
+
+int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written);
+
+int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern void sisusb_init_concode(void);
+extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+
+extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+
+extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ u8 *arg, int cmapsz, int ch512, int dorecalc,
+ struct vc_data *c, int fh, int uplock);
+
+static int sisusb_first_vc = 0;
+static int sisusb_last_vc = 0;
+module_param_named(first, sisusb_first_vc, int, 0);
+module_param_named(last, sisusb_last_vc, int, 0);
+MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
+MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
+#endif
+
static struct usb_driver sisusb_driver;
-static DECLARE_MUTEX(disconnect_sem);
+DECLARE_MUTEX(disconnect_sem);
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -229,7 +275,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completeout, &sisusb->urbout_context[index]);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
if ((urb->transfer_dma = transfer_dma))
@@ -295,7 +341,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completein, sisusb);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
if ((urb->transfer_dma = transfer_dma))
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
/* The following routines assume being used to transfer byte, word,
* long etc.
- * This means that they assume "data" in machine endianness format.
+ * This means that
+ * - the write routines expect "data" in machine endianness format.
+ * The data will be converted to leXX in sisusb_xxx_packet.
+ * - the read routines can expect read data in machine-endianess.
*/
static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap16, (u16 __user *)userbuffer))
return -EFAULT;
} else
- swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+ swap16 = *((u16 *)kernbuffer);
ret = sisusb_write_memio_word(sisusb,
SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (userbuffer) {
if (copy_from_user(&buf, userbuffer, 3))
return -EFAULT;
-
+#ifdef __BIG_ENDIAN
swap32 = (buf[0] << 16) |
(buf[1] << 8) |
buf[2];
+#else
+ swap32 = (buf[2] << 16) |
+ (buf[1] << 8) |
+ buf[0];
+#endif
} else
+#ifdef __BIG_ENDIAN
swap32 = (kernbuffer[0] << 16) |
(kernbuffer[1] << 8) |
kernbuffer[2];
+#else
+ swap32 = (kernbuffer[2] << 16) |
+ (kernbuffer[1] << 8) |
+ kernbuffer[0];
+#endif
ret = sisusb_write_memio_24bit(sisusb,
SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap32, (u32 __user *)userbuffer))
return -EFAULT;
} else
- swap32 = (kernbuffer[0] << 24) |
- (kernbuffer[1] << 16) |
- (kernbuffer[2] << 8) |
- kernbuffer[3];
+ swap32 = *((u32 *)kernbuffer);
ret = sisusb_write_memio_long(sisusb,
SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
return ret ? -EIO : 0;
}
+/* Remember: Read data in packet is in machine-endianess! So for
+ * byte, word, 24bit, long no endian correction is necessary.
+ */
+
static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
u32 addr, u8 *data)
{
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
(u16 __user *)userbuffer))
return -EFAULT;
} else {
- kernbuffer[0] = swap16 >> 8;
- kernbuffer[1] = swap16 & 0xff;
+ *((u16 *)kernbuffer) = swap16;
}
}
return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
addr, &swap32);
if (!ret) {
(*bytes_read) += 3;
+#ifdef __BIG_ENDIAN
buf[0] = (swap32 >> 16) & 0xff;
buf[1] = (swap32 >> 8) & 0xff;
buf[2] = swap32 & 0xff;
+#else
+ buf[2] = (swap32 >> 16) & 0xff;
+ buf[1] = (swap32 >> 8) & 0xff;
+ buf[0] = swap32 & 0xff;
+#endif
if (userbuffer) {
if (copy_to_user(userbuffer, &buf[0], 3))
return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
userbuffer += 4;
} else {
- kernbuffer[0] = (swap32 >> 24) & 0xff;
- kernbuffer[1] = (swap32 >> 16) & 0xff;
- kernbuffer[2] = (swap32 >> 8) & 0xff;
- kernbuffer[3] = swap32 & 0xff;
+ *((u32 *)kernbuffer) = swap32;
kernbuffer += 4;
}
addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
/* High level: Gfx (indexed) register access */
-static int
+#ifdef INCL_SISUSB_CON
+int
+sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
+{
+ return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+
+int
+sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
+{
+ return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+#endif
+
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
{
int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
{
int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
u8 myand, u8 myor)
{
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
{
return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
{
return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
}
+/* Write/read video ram */
+
+#ifdef INCL_SISUSB_CON
+int
+sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
+{
+ return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
+{
+ return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
+{
+ return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
+{
+ return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written)
+{
+ return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
+}
+
+#ifdef SISUSBENDIANTEST
+int
+sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
+ u32 src, int length, size_t *bytes_written)
+{
+ return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
+}
+#endif
+#endif
+
+#ifdef SISUSBENDIANTEST
+static void
+sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
+{
+ static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+ char destbuffer[10];
+ size_t dummy;
+ int i,j;
+
+ sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
+
+ for(i = 1; i <= 7; i++) {
+ printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
+ sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
+ for(j = 0; j < i; j++) {
+ printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
+ }
+ }
+}
+#endif
+
/* access pci config registers (reg numbers 0, 4, 8, etc) */
static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
return ret;
}
+
+#ifdef INCL_SISUSB_CON
+
+/* Set up default text mode:
+ - Set text mode (0x03)
+ - Upload default font
+ - Upload user font (if available)
+*/
+
+int
+sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
+{
+ int ret = 0, slot = sisusb->font_slot, i;
+ struct font_desc *myfont;
+ u8 *tempbuf;
+ u16 *tempbufb;
+ size_t written;
+ static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+ static char bootlogo[] = "(o_ //\\ V_/_";
+
+ /* sisusb->lock is down */
+
+ if (!sisusb->SiS_Pr)
+ return 1;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ /* Set mode 0x03 */
+ SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
+
+ if (!(myfont = find_font("VGA8x16")))
+ return 1;
+
+ if (!(tempbuf = vmalloc(8192)))
+ return 1;
+
+ for (i = 0; i < 256; i++)
+ memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
+
+ /* Upload default font */
+ ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
+
+ vfree(tempbuf);
+
+ /* Upload user font (and reset current slot) */
+ if (sisusb->font_backup) {
+ ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
+ 8192, sisusb->font_backup_512, 1, NULL,
+ sisusb->font_backup_height, 0);
+ if (slot != 2)
+ sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
+ NULL, 16, 0);
+ }
+
+ if (init && !sisusb->scrbuf) {
+
+ if ((tempbuf = vmalloc(8192))) {
+
+ i = 4096;
+ tempbufb = (u16 *)tempbuf;
+ while (i--)
+ *(tempbufb++) = 0x0720;
+
+ i = 0;
+ tempbufb = (u16 *)tempbuf;
+ while (bootlogo[i]) {
+ *(tempbufb++) = 0x0700 | bootlogo[i++];
+ if (!(i % 4))
+ tempbufb += 76;
+ }
+
+ i = 0;
+ tempbufb = (u16 *)tempbuf + 6;
+ while (bootstring[i])
+ *(tempbufb++) = 0x0700 | bootstring[i++];
+
+ ret |= sisusb_copy_memory(sisusb, tempbuf,
+ sisusb->vrambase, 8192, &written);
+
+ vfree(tempbuf);
+
+ }
+
+ } else if (sisusb->scrbuf) {
+
+ ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
+ sisusb->vrambase, sisusb->scrbuf_size, &written);
+
+ }
+
+ if (sisusb->sisusb_cursor_size_from >= 0 &&
+ sisusb->sisusb_cursor_size_to >= 0) {
+ sisusb_setidxreg(sisusb, SISCR, 0x0a,
+ sisusb->sisusb_cursor_size_from);
+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
+ sisusb->sisusb_cursor_size_to);
+ } else {
+ sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
+ sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
+ sisusb->sisusb_cursor_size_to = -1;
+ }
+
+ slot = sisusb->sisusb_cursor_loc;
+ if(slot < 0) slot = 0;
+
+ sisusb->sisusb_cursor_loc = -1;
+ sisusb->bad_cursor_pos = 1;
+
+ sisusb_set_cursor(sisusb, slot);
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+
+ sisusb->textmodedestroyed = 0;
+
+ /* sisusb->lock is down */
+
+ return ret;
+}
+
+#endif
+
/* fops */
static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
}
}
- /* increment usage count for the device */
+ /* Increment usage count for our sisusb */
kref_get(&sisusb->kref);
sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
up(&disconnect_sem);
- printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
-
return 0;
}
-static void
+void
sisusb_delete(struct kref *kref)
{
struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
sisusb->sisusb_dev = NULL;
sisusb_free_buffers(sisusb);
sisusb_free_urbs(sisusb);
+#ifdef INCL_SISUSB_CON
+ kfree(sisusb->SiS_Pr);
+#endif
kfree(sisusb);
}
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
up(&disconnect_sem);
- printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
-
return 0;
}
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
int retval, port, length;
u32 address;
+ /* All our commands require the device
+ * to be initialized.
+ */
+ if (!sisusb->devinit)
+ return -ENODEV;
+
port = y->data3 -
SISUSB_PCI_PSEUDO_IOPORTBASE +
SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
break;
case SUCMD_CLRSCR:
+ /* Gfx core must be initialized */
+ if (!sisusb->gfxinit)
+ return -ENODEV;
+
length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
address = y->data3 -
SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
retval = sisusb_clear_vram(sisusb, address, length);
break;
+ case SUCMD_HANDLETEXTMODE:
+ retval = 0;
+#ifdef INCL_SISUSB_CON
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ switch (y->data0) {
+ case 0:
+ retval = sisusb_reset_text_mode(sisusb, 0);
+ break;
+ case 1:
+ sisusb->textmodedestroyed = 1;
+ break;
+ }
+#endif
+ break;
+
+#ifdef INCL_SISUSB_CON
+ case SUCMD_SETMODE:
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ retval = 0;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
+ retval = -EINVAL;
+
+ break;
+
+ case SUCMD_SETVESAMODE:
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ retval = 0;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
+ retval = -EINVAL;
+
+ break;
+#endif
+
default:
retval = -EINVAL;
}
- if(retval > 0)
+ if (retval > 0)
retval = -EIO;
return retval;
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
x.sisusb_vramsize = sisusb->vramsize;
x.sisusb_minor = sisusb->minor;
x.sisusb_fbdevactive= 0;
+#ifdef INCL_SISUSB_CON
+ x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
+#else
+ x.sisusb_conactive = 0;
+#endif
if (copy_to_user((void __user *)arg, &x, sizeof(x)))
retval = -EFAULT;
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
};
static struct usb_class_driver usb_sisusb_class = {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
.name = "usb/sisusbvga%d",
- .fops = &usb_sisusb_fops,
.mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+#else
+ .name = "sisusbvga%d",
+#endif
+ .fops = &usb_sisusb_fops,
.minor_base = SISUSB_MINOR
};
@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
sisusb->minor, sisusb->numobufs);
+#ifdef INCL_SISUSB_CON
+ /* Allocate our SiS_Pr */
+ if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
+ sisusb->minor);
+ }
+#endif
+
/* Do remaining init stuff */
init_waitqueue_head(&sisusb->wait_q);
usb_set_intfdata(intf, sisusb);
+ usb_get_dev(sisusb->sisusb_dev);
+
+ sisusb->present = 1;
+
#ifdef SISUSB_OLD_CONFIG_COMPAT
{
int ret;
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->minor);
else
sisusb->ioctl32registered = 1;
-
}
#endif
- sisusb->present = 1;
-
if (dev->speed == USB_SPEED_HIGH) {
- if (sisusb_init_gfxdevice(sisusb, 1))
+ int initscreen = 1;
+#ifdef INCL_SISUSB_CON
+ if (sisusb_first_vc > 0 &&
+ sisusb_last_vc > 0 &&
+ sisusb_first_vc <= sisusb_last_vc &&
+ sisusb_last_vc <= MAX_NR_CONSOLES)
+ initscreen = 0;
+#endif
+ if (sisusb_init_gfxdevice(sisusb, initscreen))
printk(KERN_ERR
"sisusbvga[%d]: Failed to early "
"initialize device\n",
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->ready = 1;
+#ifdef SISUSBENDIANTEST
+ printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
+ sisusb_testreadwrite(sisusb);
+ printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
+#endif
+
+#ifdef INCL_SISUSB_CON
+ sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
+#endif
+
return 0;
error_4:
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
struct sisusb_usb_data *sisusb;
int minor;
- down(&disconnect_sem);
-
/* This should *not* happen */
- if (!(sisusb = usb_get_intfdata(intf))) {
- up(&disconnect_sem);
+ if (!(sisusb = usb_get_intfdata(intf)))
return;
- }
+
+#ifdef INCL_SISUSB_CON
+ sisusb_console_exit(sisusb);
+#endif
+
+ /* The above code doesn't need the disconnect
+ * semaphore to be down; its meaning is to
+ * protect all other routines from the disconnect
+ * case, not the other way round.
+ */
+ down(&disconnect_sem);
down(&sisusb->lock);
@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
{
int retval;
+#ifdef INCL_SISUSB_CON
+ sisusb_init_concode();
+#endif
+
if (!(retval = usb_register(&sisusb_driver))) {
+
printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
printk(KERN_INFO
"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+
}
return retval;
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
module_exit(usb_sisusb_exit);
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
-MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d006a25a..401ff21d7881 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -46,15 +46,36 @@
#endif
#endif
+/* For older kernels, support for text consoles is by default
+ * off. To ensable text console support, change the following:
+ */
+#if 0
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+#define CONFIG_USB_SISUSBVGA_CON
+#endif
+#endif
+
/* Version Information */
#define SISUSB_VERSION 0
#define SISUSB_REVISION 0
-#define SISUSB_PATCHLEVEL 7
+#define SISUSB_PATCHLEVEL 8
+
+/* Include console and mode switching code? */
+
+#ifdef CONFIG_USB_SISUSBVGA_CON
+#define INCL_SISUSB_CON 1
+#endif
+
+#ifdef INCL_SISUSB_CON
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include "sisusb_struct.h"
+#endif
/* USB related */
-#define SISUSB_MINOR 133 /* FIXME */
+#define SISUSB_MINOR 133 /* official */
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE 0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
unsigned char gfxinit; /* graphics core initialized? */
unsigned short chipid, chipvendor;
unsigned short chiprevision;
+#ifdef INCL_SISUSB_CON
+ struct SiS_Private *SiS_Pr;
+ unsigned long scrbuf;
+ unsigned int scrbuf_size;
+ int haveconsole, con_first, con_last;
+ int havethisconsole[MAX_NR_CONSOLES];
+ int textmodedestroyed;
+ unsigned int sisusb_num_columns; /* real number, not vt's idea */
+ int cur_start_addr, con_rolled_over;
+ int sisusb_cursor_loc, bad_cursor_pos;
+ int sisusb_cursor_size_from;
+ int sisusb_cursor_size_to;
+ int current_font_height, current_font_512;
+ int font_backup_size, font_backup_height, font_backup_512;
+ char *font_backup;
+ int font_slot;
+ struct vc_data *sisusb_display_fg;
+ int is_gfx;
+ int con_blanked;
+#endif
};
#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {
__u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
- __u8 sisusb_reserved[32]; /* for future use */
+ __u32 sisusb_conactive; /* != 0 if console driver active */
+
+ __u8 sisusb_reserved[28]; /* for future use */
};
struct sisusb_command {
@@ -261,18 +304,24 @@ struct sisusb_command {
__u32 data4; /* for future use */
};
-#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
-#define SUCMD_SET 0x02 /* data1 = value */
-#define SUCMD_SETOR 0x03 /* data1 = or */
-#define SUCMD_SETAND 0x04 /* data1 = and */
-#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
-#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
+#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
+#define SUCMD_SET 0x02 /* data1 = value */
+#define SUCMD_SETOR 0x03 /* data1 = or */
+#define SUCMD_SETAND 0x04 /* data1 = and */
+#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
+#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
-#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
+#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
+
+#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
+
+#define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */
+#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */
#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
-#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
-#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+
#endif /* SISUSB_H */
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 000000000000..24584463553d
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1658 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * VGA text mode console part
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Portions based on vgacon.c which are
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * based on code Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ *
+ * A note on using in_atomic() in here: We can't handle console
+ * calls from non-schedulable context due to our USB-dependend
+ * nature. For now, this driver just ignores any calls if it
+ * detects this state.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/smp_lock.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
+extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
+extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
+extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
+
+extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written);
+
+extern void sisusb_delete(struct kref *kref);
+extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+
+#define sisusbcon_writew(val, addr) (*(addr) = (val))
+#define sisusbcon_readw(addr) (*(addr))
+#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
+#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
+
+/* vc_data -> sisusb conversion table */
+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
+
+/* Forward declaration */
+static const struct consw sisusb_con;
+
+extern struct semaphore disconnect_sem;
+
+static inline void
+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ sisusbcon_writew(c, s++);
+}
+
+static inline void
+sisusb_initialize(struct sisusb_usb_data *sisusb)
+{
+ /* Reset cursor and start address */
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
+}
+
+static inline void
+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
+{
+ sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+}
+
+void
+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
+{
+ if (sisusb->sisusb_cursor_loc == location)
+ return;
+
+ sisusb->sisusb_cursor_loc = location;
+
+ /* Hardware bug: Text cursor appears twice or not at all
+ * at some positions. Work around it with the cursor skew
+ * bits.
+ */
+
+ if ((location & 0x0007) == 0x0007) {
+ sisusb->bad_cursor_pos = 1;
+ location--;
+ if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
+ return;
+ } else if (sisusb->bad_cursor_pos) {
+ if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
+ return;
+ sisusb->bad_cursor_pos = 0;
+ }
+
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
+}
+
+static inline struct sisusb_usb_data *
+sisusb_get_sisusb(unsigned short console)
+{
+ return mysisusbs[console];
+}
+
+static inline int
+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
+{
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
+ return 0;
+
+ return 1;
+}
+
+static struct sisusb_usb_data *
+sisusb_get_sisusb_lock_and_check(unsigned short console)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* We can't handle console calls in non-schedulable
+ * context due to our locks and the USB transport.
+ * So we simply ignore them. This should only affect
+ * some calls to printk.
+ */
+ if (in_atomic())
+ return NULL;
+
+ if (!(sisusb = sisusb_get_sisusb(console)))
+ return NULL;
+
+ down(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb) ||
+ !sisusb->havethisconsole[console]) {
+ up(&sisusb->lock);
+ return NULL;
+ }
+
+ return sisusb;
+}
+
+static int
+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
+{
+ if (sisusb->is_gfx ||
+ sisusb->textmodedestroyed ||
+ c->vc_mode != KD_TEXT)
+ return 1;
+
+ return 0;
+}
+
+/* con_startup console interface routine */
+static const char *
+sisusbcon_startup(void)
+{
+ return "SISUSBCON";
+}
+
+/* con_init console interface routine */
+static void
+sisusbcon_init(struct vc_data *c, int init)
+{
+ struct sisusb_usb_data *sisusb;
+ int cols, rows;
+
+ /* This is called by take_over_console(),
+ * ie by us/under our control. It is
+ * only called after text mode and fonts
+ * are set up/restored.
+ */
+
+ down(&disconnect_sem);
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+ up(&disconnect_sem);
+ return;
+ }
+
+ down(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb)) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return;
+ }
+
+ c->vc_can_do_color = 1;
+
+ c->vc_complement_mask = 0x7700;
+
+ c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
+
+ sisusb->haveconsole = 1;
+
+ sisusb->havethisconsole[c->vc_num] = 1;
+
+ /* We only support 640x400 */
+ c->vc_scan_lines = 400;
+
+ c->vc_font.height = sisusb->current_font_height;
+
+ /* We only support width = 8 */
+ cols = 80;
+ rows = c->vc_scan_lines / c->vc_font.height;
+
+ /* Increment usage count for our sisusb.
+ * Doing so saves us from upping/downing
+ * the disconnect semaphore; we can't
+ * lose our sisusb until this is undone
+ * in con_deinit. For all other console
+ * interface functions, it suffices to
+ * use sisusb->lock and do a quick check
+ * of sisusb for device disconnection.
+ */
+ kref_get(&sisusb->kref);
+
+ if (!*c->vc_uni_pagedir_loc)
+ con_set_default_unimap(c);
+
+ up(&sisusb->lock);
+
+ up(&disconnect_sem);
+
+ if (init) {
+ c->vc_cols = cols;
+ c->vc_rows = rows;
+ } else
+ vc_resize(c, cols, rows);
+}
+
+/* con_deinit console interface routine */
+static void
+sisusbcon_deinit(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int i;
+
+ /* This is called by take_over_console()
+ * and others, ie not under our control.
+ */
+
+ down(&disconnect_sem);
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+ up(&disconnect_sem);
+ return;
+ }
+
+ down(&sisusb->lock);
+
+ /* Clear ourselves in mysisusbs */
+ mysisusbs[c->vc_num] = NULL;
+
+ sisusb->havethisconsole[c->vc_num] = 0;
+
+ /* Free our font buffer if all consoles are gone */
+ if (sisusb->font_backup) {
+ for(i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (sisusb->havethisconsole[c->vc_num])
+ break;
+ }
+ if (i == MAX_NR_CONSOLES) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ up(&sisusb->lock);
+
+ /* decrement the usage count on our sisusb */
+ kref_put(&sisusb->kref, sisusb_delete);
+
+ up(&disconnect_sem);
+}
+
+/* interface routine */
+static u8
+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+ u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = color;
+
+ if (underline)
+ attr = (attr & 0xf0) | c->vc_ulcolor;
+ else if (intensity == 0)
+ attr = (attr & 0xf0) | c->vc_halfcolor;
+
+ if (reverse)
+ attr = ((attr) & 0x88) |
+ ((((attr) >> 4) |
+ ((attr) << 4)) & 0x77);
+
+ if (blink)
+ attr ^= 0x80;
+
+ if (intensity == 2)
+ attr ^= 0x08;
+
+ return attr;
+}
+
+/* Interface routine */
+static void
+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
+{
+ /* Invert a region. This is called with a pointer
+ * to the console's internal screen buffer. So we
+ * simply do the inversion there and rely on
+ * a call to putc(s) to update the real screen.
+ */
+
+ while (count--) {
+ u16 a = sisusbcon_readw(p);
+
+ a = ((a) & 0x88ff) |
+ (((a) & 0x7000) >> 4) |
+ (((a) & 0x0700) << 4);
+
+ sisusbcon_writew(a, p++);
+ }
+}
+
+#define SISUSB_VADDR(x,y) \
+ ((u16 *)c->vc_origin + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+#define SISUSB_HADDR(x,y) \
+ ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+/* Interface routine */
+static void
+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Don't need to put the character into buffer ourselves,
+ * because the vt does this BEFORE calling us.
+ */
+#if 0
+ sisusbcon_writew(ch, SISUSB_VADDR(x, y));
+#endif
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), 2, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
+ int count, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ u16 *dest;
+ int i;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to put the characters into the buffer ourselves,
+ * because the vt does this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ for (i = count; i > 0; i--)
+ sisusbcon_writew(sisusbcon_readw(s++), dest++);
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), count * 2, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int i, length, cols;
+ u16 *dest;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to clear buffer ourselves, because the vt does
+ * this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ cols = sisusb->sisusb_num_columns;
+
+ if (width > cols)
+ width = cols;
+
+ if (x == 0 && width >= c->vc_cols) {
+
+ sisusbcon_memsetw(dest, eattr, height * cols * 2);
+
+ } else {
+
+ for (i = height; i > 0; i--, dest += cols)
+ sisusbcon_memsetw(dest, eattr, width * 2);
+
+ }
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - x - (cols - width - x)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), length, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_bmove(struct vc_data *c, int sy, int sx,
+ int dy, int dx, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int cols, length;
+#if 0
+ u16 *src, *dest;
+ int i;
+#endif
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ cols = sisusb->sisusb_num_columns;
+
+ /* Don't need to move data outselves, because
+ * vt does this BEFORE calling us.
+ * This is only used by vt's insert/deletechar.
+ */
+#if 0
+ if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
+
+ sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
+ height * width * 2);
+
+ } else if (dy < sy || (dy == sy && dx < sx)) {
+
+ src = SISUSB_VADDR(sx, sy);
+ dest = SISUSB_VADDR(dx, dy);
+
+ for (i = height; i > 0; i--) {
+ sisusbcon_memmovew(dest, src, width * 2);
+ src += cols;
+ dest += cols;
+ }
+
+ } else {
+
+ src = SISUSB_VADDR(sx, sy + height - 1);
+ dest = SISUSB_VADDR(dx, dy + height - 1);
+
+ for (i = height; i > 0; i--) {
+ sisusbcon_memmovew(dest, src, width * 2);
+ src -= cols;
+ dest -= cols;
+ }
+
+ }
+#endif
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - dx - (cols - width - dx)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
+ (u32)SISUSB_HADDR(dx, dy), length, &written);
+
+ up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_switch(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int length;
+
+ /* Returnvalue 0 means we have fully restored screen,
+ * and vt doesn't need to call do_update_region().
+ * Returnvalue != 0 naturally means the opposite.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ /* Don't write to screen if in gfx mode */
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ /* That really should not happen. It would mean we are
+ * being called while the vc is using its private buffer
+ * as origin.
+ */
+ if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
+ up(&sisusb->lock);
+ printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
+ return 0;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Restore the screen contents */
+ sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
+ length);
+
+ sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
+ (u32)SISUSB_HADDR(0, 0),
+ length, &written);
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static void
+sisusbcon_save_screen(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int length;
+
+ /* Save the current screen contents to vc's private
+ * buffer.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Save the screen contents to vc's private buffer */
+ sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
+ length);
+
+ up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ struct sisusb_usb_data *sisusb;
+ int i, j;
+
+ /* Return value not used by vt */
+
+ if (!CON_IS_VISIBLE(c))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -EINVAL;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ for (i = j = 0; i < 16; i++) {
+ if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ }
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static int
+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
+{
+ struct sisusb_usb_data *sisusb;
+ u8 sr1, cr17, pmreg, cr63;
+ ssize_t written;
+ int ret = 0;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (mode_switch)
+ sisusb->is_gfx = blank ? 1 : 0;
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ switch (blank) {
+
+ case 1: /* Normal blanking: Clear screen */
+ case -1:
+ sisusbcon_memsetw((u16 *)c->vc_origin,
+ c->vc_video_erase_char,
+ c->vc_screenbuf_size);
+ sisusb_copy_memory(sisusb,
+ (unsigned char *)c->vc_origin,
+ (u32)(sisusb->vrambase +
+ (c->vc_origin - sisusb->scrbuf)),
+ c->vc_screenbuf_size, &written);
+ sisusb->con_blanked = 1;
+ ret = 1;
+ break;
+
+ default: /* VESA blanking */
+ switch (blank) {
+ case 0: /* Unblank */
+ sr1 = 0x00;
+ cr17 = 0x80;
+ pmreg = 0x00;
+ cr63 = 0x00;
+ ret = 1;
+ sisusb->con_blanked = 0;
+ break;
+ case VESA_VSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x80;
+ cr63 = 0x40;
+ break;
+ case VESA_HSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x40;
+ cr63 = 0x40;
+ break;
+ case VESA_POWERDOWN + 1:
+ sr1 = 0x20;
+ cr17 = 0x00;
+ pmreg = 0xc0;
+ cr63 = 0x40;
+ break;
+ default:
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
+ sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
+ sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
+ sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
+
+ }
+
+ up(&sisusb->lock);
+
+ return ret;
+}
+
+/* interface routine */
+static int
+sisusbcon_scrolldelta(struct vc_data *c, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ /* The return value does not seem to be used */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+
+ if (sisusb->con_rolled_over >
+ (c->vc_scr_end - sisusb->scrbuf) + margin) {
+
+ ul = c->vc_scr_end - sisusb->scrbuf;
+ we = sisusb->con_rolled_over + c->vc_size_row;
+
+ } else {
+
+ ul = 0;
+ we = sisusb->scrbuf_size;
+
+ }
+
+ p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
+ lines * c->vc_size_row;
+
+ st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
+
+ if (st < 2 * margin)
+ margin = 0;
+
+ if (p < margin)
+ p = 0;
+
+ if (p > st - margin)
+ p = st;
+
+ c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
+ }
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static void
+sisusbcon_cursor(struct vc_data *c, int mode)
+{
+ struct sisusb_usb_data *sisusb;
+ int from, to, baseline;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ if (mode == CM_ERASE) {
+ sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
+ sisusb->sisusb_cursor_size_to = -1;
+ up(&sisusb->lock);
+ return;
+ }
+
+ sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
+
+ baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
+
+ switch (c->vc_cursor_type & 0x0f) {
+ case CUR_BLOCK: from = 1;
+ to = c->vc_font.height;
+ break;
+ case CUR_TWO_THIRDS: from = c->vc_font.height / 3;
+ to = baseline;
+ break;
+ case CUR_LOWER_HALF: from = c->vc_font.height / 2;
+ to = baseline;
+ break;
+ case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;
+ to = baseline;
+ break;
+ case CUR_NONE: from = 31;
+ to = 30;
+ break;
+ default:
+ case CUR_UNDERLINE: from = baseline - 1;
+ to = baseline;
+ break;
+ }
+
+ if (sisusb->sisusb_cursor_size_from != from ||
+ sisusb->sisusb_cursor_size_to != to) {
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
+
+ sisusb->sisusb_cursor_size_from = from;
+ sisusb->sisusb_cursor_size_to = to;
+ }
+
+ up(&sisusb->lock);
+}
+
+static int
+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
+ int t, int b, int dir, int lines)
+{
+ int cols = sisusb->sisusb_num_columns;
+ int length = ((b - t) * cols) * 2;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+
+ /* sisusb->lock is down */
+
+ /* Scroll an area which does not match the
+ * visible screen's dimensions. This needs
+ * to be done separately, as it does not
+ * use hardware panning.
+ */
+
+ switch (dir) {
+
+ case SM_UP:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t),
+ SISUSB_VADDR(0, t + lines),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
+ lines * cols * 2);
+ break;
+
+ case SM_DOWN:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
+ SISUSB_VADDR(0, t),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+ lines * cols * 2);
+ break;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
+ (u32)SISUSB_HADDR(0, t), length, &written);
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int copyall = 0;
+ unsigned long oldorigin;
+ unsigned int delta = lines * c->vc_size_row;
+ u32 originoffset;
+
+ /* Returning != 0 means we have done the scrolling successfully.
+ * Returning 0 makes vt do the scrolling on its own.
+ * Note that con_scroll is only called if the console is
+ * visible. In that case, the origin should be our buffer,
+ * not the vt's private one.
+ */
+
+ if (!lines)
+ return 1;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ /* Special case */
+ if (t || b != c->vc_rows)
+ return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ /* limit amount to maximum realistic size */
+ if (lines > c->vc_rows)
+ lines = c->vc_rows;
+
+ oldorigin = c->vc_origin;
+
+ switch (dir) {
+
+ case SM_UP:
+
+ if (c->vc_scr_end + delta >=
+ sisusb->scrbuf + sisusb->scrbuf_size) {
+ sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+ (u16 *)(oldorigin + delta),
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf;
+ sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
+ copyall = 1;
+ } else
+ c->vc_origin += delta;
+
+ sisusbcon_memsetw(
+ (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
+ eattr, delta);
+
+ break;
+
+ case SM_DOWN:
+
+ if (oldorigin - delta < sisusb->scrbuf) {
+ sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size +
+ delta),
+ (u16 *)oldorigin,
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size;
+ sisusb->con_rolled_over = 0;
+ copyall = 1;
+ } else
+ c->vc_origin -= delta;
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+
+ scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
+
+ break;
+ }
+
+ originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
+
+ if (copyall)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ c->vc_screenbuf_size, &written);
+ else if (dir == SM_UP)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin + c->vc_screenbuf_size - delta,
+ (u32)sisusb->vrambase + originoffset +
+ c->vc_screenbuf_size - delta,
+ delta, &written);
+ else
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ delta, &written);
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+ c->vc_visible_origin = c->vc_origin;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_set_origin(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* Returning != 0 means we were successful.
+ * Returning 0 will vt make to use its own
+ * screenbuffer as the origin.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ sisusb->con_rolled_over = 0;
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
+{
+ struct sisusb_usb_data *sisusb;
+ int fh;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ fh = sisusb->current_font_height;
+
+ up(&sisusb->lock);
+
+ /* We are quite unflexible as regards resizing. The vt code
+ * handles sizes where the line length isn't equal the pitch
+ * quite badly. As regards the rows, our panning tricks only
+ * work well if the number of rows equals the visible number
+ * of rows.
+ */
+
+ if (newcols != 80 || c->vc_scan_lines / fh != newrows)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ u8 *arg, int cmapsz, int ch512, int dorecalc,
+ struct vc_data *c, int fh, int uplock)
+{
+ int font_select = 0x00, i, err = 0;
+ u32 offset = 0;
+ u8 dummy;
+
+ /* sisusb->lock is down */
+
+ /*
+ * The default font is kept in slot 0.
+ * A user font is loaded in slot 2 (256 ch)
+ * or 2+3 (512 ch).
+ */
+
+ if ((slot != 0 && slot != 2) || !fh) {
+ if (uplock)
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ if (set)
+ sisusb->font_slot = slot;
+
+ /* Default font is always 256 */
+ if (slot == 0)
+ ch512 = 0;
+ else
+ offset = 4 * cmapsz;
+
+ font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if (arg) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset + i,
+ arg[i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset + i,
+ &arg[i]);
+ if (err)
+ break;
+ }
+
+ /*
+ * In 512-character mode, the character map is not contiguous if
+ * we want to remain EGA compatible -- which we do
+ */
+
+ if (ch512) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ &arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ }
+ }
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
+ if (set)
+ sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if ((set) && (ch512 != sisusb->current_font_512)) {
+
+ /* Font is shared among all our consoles.
+ * And so is the hi_font_mask.
+ */
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *c = vc_cons[i].d;
+ if (c && c->vc_sw == &sisusb_con)
+ c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ }
+
+ sisusb->current_font_512 = ch512;
+
+ /* color plane enable register:
+ 256-char: enable intensity bit
+ 512-char: disable intensity bit */
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x12);
+ sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
+
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x20);
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ }
+
+ if (dorecalc) {
+
+ /*
+ * Adjust the screen to fit a font of a certain height
+ */
+
+ unsigned char ovr, vde, fsr;
+ int rows = 0, maxscan = 0;
+
+ if (c) {
+
+ /* Number of video rows */
+ rows = c->vc_scan_lines / fh;
+ /* Scan lines to actually display-1 */
+ maxscan = rows * fh - 1;
+
+ /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
+ rows, maxscan, fh, c->vc_scan_lines);*/
+
+ sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
+ vde = maxscan & 0xff;
+ ovr = (ovr & 0xbd) |
+ ((maxscan & 0x100) >> 7) |
+ ((maxscan & 0x200) >> 3);
+ sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
+ sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
+
+ }
+
+ sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
+ fsr = (fsr & 0xe0) | (fh - 1);
+ sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
+ sisusb->current_font_height = fh;
+
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ }
+
+ if (uplock)
+ up(&sisusb->lock);
+
+ if (dorecalc && c) {
+ int i, rows = c->vc_scan_lines / fh;
+
+ /* Now adjust our consoles' size */
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *vc = vc_cons[i].d;
+
+ if (vc && vc->vc_sw == &sisusb_con) {
+ if (CON_IS_VISIBLE(vc)) {
+ vc->vc_sw->con_cursor(vc, CM_DRAW);
+ }
+ vc->vc_font.height = fh;
+ vc_resize(vc, 0, rows);
+ }
+ }
+ }
+
+ return 0;
+
+font_op_error:
+ if (uplock)
+ up(&sisusb->lock);
+
+ return -EIO;
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_set(struct vc_data *c, struct console_font *font,
+ unsigned flags)
+{
+ struct sisusb_usb_data *sisusb;
+ unsigned charcount = font->charcount;
+
+ if (font->width != 8 || (charcount != 256 && charcount != 512))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ /* Save the user-provided font into a buffer. This
+ * is used for restoring text mode after quitting
+ * from X and for the con_getfont routine.
+ */
+ if (sisusb->font_backup) {
+ if (sisusb->font_backup_size < charcount) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ if (!sisusb->font_backup)
+ sisusb->font_backup = vmalloc(charcount * 32);
+
+ if (sisusb->font_backup) {
+ memcpy(sisusb->font_backup, font->data, charcount * 32);
+ sisusb->font_backup_size = charcount;
+ sisusb->font_backup_height = font->height;
+ sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
+ }
+
+ /* do_font_op ups sisusb->lock */
+
+ return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
+ 8192, (charcount == 512),
+ (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
+ c, font->height, 1);
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_get(struct vc_data *c, struct console_font *font)
+{
+ struct sisusb_usb_data *sisusb;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ font->width = 8;
+ font->height = c->vc_font.height;
+ font->charcount = 256;
+
+ if (!font->data) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ if (!sisusb->font_backup) {
+ up(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ /* Copy 256 chars only, like vgacon */
+ memcpy(font->data, sisusb->font_backup, 256 * 32);
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/*
+ * The console `switch' structure for the sisusb console
+ */
+
+static const struct consw sisusb_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbcon_startup,
+ .con_init = sisusbcon_init,
+ .con_deinit = sisusbcon_deinit,
+ .con_clear = sisusbcon_clear,
+ .con_putc = sisusbcon_putc,
+ .con_putcs = sisusbcon_putcs,
+ .con_cursor = sisusbcon_cursor,
+ .con_scroll = sisusbcon_scroll,
+ .con_bmove = sisusbcon_bmove,
+ .con_switch = sisusbcon_switch,
+ .con_blank = sisusbcon_blank,
+ .con_font_set = sisusbcon_font_set,
+ .con_font_get = sisusbcon_font_get,
+ .con_set_palette = sisusbcon_set_palette,
+ .con_scrolldelta = sisusbcon_scrolldelta,
+ .con_build_attr = sisusbcon_build_attr,
+ .con_invert_region = sisusbcon_invert_region,
+ .con_set_origin = sisusbcon_set_origin,
+ .con_save_screen = sisusbcon_save_screen,
+ .con_resize = sisusbcon_resize,
+};
+
+/* Our very own dummy console driver */
+
+static const char *sisusbdummycon_startup(void)
+{
+ return "SISUSBVGADUMMY";
+}
+
+static void sisusbdummycon_init(struct vc_data *vc, int init)
+{
+ vc->vc_can_do_color = 1;
+ if (init) {
+ vc->vc_cols = 80;
+ vc->vc_rows = 25;
+ } else
+ vc_resize(vc, 80, 25);
+}
+
+static int sisusbdummycon_dummy(void)
+{
+ return 0;
+}
+
+#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
+
+const struct consw sisusb_dummy_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbdummycon_startup,
+ .con_init = sisusbdummycon_init,
+ .con_deinit = SISUSBCONDUMMY,
+ .con_clear = SISUSBCONDUMMY,
+ .con_putc = SISUSBCONDUMMY,
+ .con_putcs = SISUSBCONDUMMY,
+ .con_cursor = SISUSBCONDUMMY,
+ .con_scroll = SISUSBCONDUMMY,
+ .con_bmove = SISUSBCONDUMMY,
+ .con_switch = SISUSBCONDUMMY,
+ .con_blank = SISUSBCONDUMMY,
+ .con_font_set = SISUSBCONDUMMY,
+ .con_font_get = SISUSBCONDUMMY,
+ .con_font_default = SISUSBCONDUMMY,
+ .con_font_copy = SISUSBCONDUMMY,
+ .con_set_palette = SISUSBCONDUMMY,
+ .con_scrolldelta = SISUSBCONDUMMY,
+};
+
+int
+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+{
+ int i, ret, minor = sisusb->minor;
+
+ down(&disconnect_sem);
+
+ down(&sisusb->lock);
+
+ /* Erm.. that should not happen */
+ if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 1;
+ }
+
+ sisusb->con_first = first;
+ sisusb->con_last = last;
+
+ if (first > last ||
+ first > MAX_NR_CONSOLES ||
+ last > MAX_NR_CONSOLES) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 1;
+ }
+
+ /* If gfxcore not initialized or no consoles given, quit graciously */
+ if (!sisusb->gfxinit || first < 1 || last < 1) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 0;
+ }
+
+ sisusb->sisusb_cursor_loc = -1;
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ /* Set up text mode (and upload default font) */
+ if (sisusb_reset_text_mode(sisusb, 1)) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to set up text mode\n",
+ minor);
+ return 1;
+ }
+
+ /* Initialize some gfx registers */
+ sisusb_initialize(sisusb);
+
+ for (i = first - 1; i <= last - 1; i++) {
+ /* Save sisusb for our interface routines */
+ mysisusbs[i] = sisusb;
+ }
+
+ /* Initial console setup */
+ sisusb->sisusb_num_columns = 80;
+
+ /* Use a 32K buffer (matches b8000-bffff area) */
+ sisusb->scrbuf_size = 32 * 1024;
+
+ /* Allocate screen buffer */
+ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate screen buffer\n",
+ minor);
+ return 1;
+ }
+
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+
+ /* Now grab the desired console(s) */
+ ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
+
+ if (!ret)
+ sisusb->haveconsole = 1;
+ else {
+ for (i = first - 1; i <= last - 1; i++)
+ mysisusbs[i] = NULL;
+ }
+
+ return ret;
+}
+
+void
+sisusb_console_exit(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ /* This is called if the device is disconnected
+ * and while disconnect and lock semaphores
+ * are up. This should be save because we
+ * can't lose our sisusb any other way but by
+ * disconnection (and hence, the disconnect
+ * sema is for protecting all other access
+ * functions from disconnection, not the
+ * other way round).
+ */
+
+ /* Now what do we do in case of disconnection:
+ * One alternative would be to simply call
+ * give_up_console(). Nah, not a good idea.
+ * give_up_console() is obviously buggy as it
+ * only discards the consw pointer from the
+ * driver_map, but doesn't adapt vc->vc_sw
+ * of the affected consoles. Hence, the next
+ * call to any of the console functions will
+ * eventually take a trip to oops county.
+ * Also, give_up_console for some reason
+ * doesn't decrement our module refcount.
+ * Instead, we switch our consoles to a private
+ * dummy console. This, of course, keeps our
+ * refcount up as well, but it works perfectly.
+ */
+
+ if (sisusb->haveconsole) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ if (sisusb->havethisconsole[i])
+ take_over_console(&sisusb_dummy_con, i, i, 0);
+ /* At this point, con_deinit for all our
+ * consoles is executed by take_over_console().
+ */
+ sisusb->haveconsole = 0;
+ }
+
+ vfree((void *)sisusb->scrbuf);
+ sisusb->scrbuf = 0;
+
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+}
+
+void __init sisusb_init_concode(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ mysisusbs[i] = NULL;
+}
+
+#endif /* INCL_CON */
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 000000000000..f28bc240f9b6
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,1047 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Display mode initializing code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+
+#include "sisusb_init.h"
+
+/*********************************************/
+/* POINTER INITIALIZATION */
+/*********************************************/
+
+static void
+SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
+ SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
+
+ SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
+ SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
+ SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
+ SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
+
+ SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
+}
+
+/*********************************************/
+/* HELPER: Get ModeID */
+/*********************************************/
+
+unsigned short
+SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
+{
+ unsigned short ModeIndex = 0;
+
+ switch (HDisplay)
+ {
+ case 320:
+ if (VDisplay == 200)
+ ModeIndex = ModeIndex_320x200[Depth];
+ else if (VDisplay == 240)
+ ModeIndex = ModeIndex_320x240[Depth];
+ break;
+ case 400:
+ if (VDisplay == 300)
+ ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 512:
+ if (VDisplay == 384)
+ ModeIndex = ModeIndex_512x384[Depth];
+ break;
+ case 640:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_640x480[Depth];
+ else if (VDisplay == 400)
+ ModeIndex = ModeIndex_640x400[Depth];
+ break;
+ case 720:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_720x480[Depth];
+ else if (VDisplay == 576)
+ ModeIndex = ModeIndex_720x576[Depth];
+ break;
+ case 768:
+ if (VDisplay == 576)
+ ModeIndex = ModeIndex_768x576[Depth];
+ break;
+ case 800:
+ if (VDisplay == 600)
+ ModeIndex = ModeIndex_800x600[Depth];
+ else if (VDisplay == 480)
+ ModeIndex = ModeIndex_800x480[Depth];
+ break;
+ case 848:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_848x480[Depth];
+ break;
+ case 856:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_856x480[Depth];
+ break;
+ case 960:
+ if (VDisplay == 540)
+ ModeIndex = ModeIndex_960x540[Depth];
+ else if (VDisplay == 600)
+ ModeIndex = ModeIndex_960x600[Depth];
+ break;
+ case 1024:
+ if (VDisplay == 576)
+ ModeIndex = ModeIndex_1024x576[Depth];
+ else if (VDisplay == 768)
+ ModeIndex = ModeIndex_1024x768[Depth];
+ break;
+ case 1152:
+ if (VDisplay == 864)
+ ModeIndex = ModeIndex_1152x864[Depth];
+ break;
+ case 1280:
+ switch (VDisplay) {
+ case 720:
+ ModeIndex = ModeIndex_1280x720[Depth];
+ break;
+ case 768:
+ ModeIndex = ModeIndex_1280x768[Depth];
+ break;
+ case 1024:
+ ModeIndex = ModeIndex_1280x1024[Depth];
+ break;
+ }
+ }
+
+ return ModeIndex;
+}
+
+/*********************************************/
+/* HELPER: SetReg, GetReg */
+/*********************************************/
+
+static void
+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short data)
+{
+ sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
+}
+
+static void
+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short data)
+{
+ sisusb_setreg(SiS_Pr->sisusb, port, data);
+}
+
+static unsigned char
+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index)
+{
+ u8 data;
+
+ sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
+
+ return data;
+}
+
+static unsigned char
+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
+{
+ u8 data;
+
+ sisusb_getreg(SiS_Pr->sisusb, port, &data);
+
+ return data;
+}
+
+static void
+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND,
+ unsigned short DataOR)
+{
+ sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
+}
+
+static void
+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND)
+{
+ sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
+}
+
+static void
+SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
+ unsigned short index, unsigned short DataOR)
+{
+ sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
+}
+
+/*********************************************/
+/* HELPER: DisplayOn, DisplayOff */
+/*********************************************/
+
+static void
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
+}
+
+/*********************************************/
+/* HELPER: Init Port Addresses */
+/*********************************************/
+
+void
+SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
+{
+ SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+ SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+ SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+ SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+ SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+ SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+ SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+ SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+ SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+ SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+ SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+ SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+ SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+}
+
+/*********************************************/
+/* HELPER: GetSysFlags */
+/*********************************************/
+
+static void
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_MyCR63 = 0x63;
+}
+
+/*********************************************/
+/* HELPER: Init PCI & Engines */
+/*********************************************/
+
+static void
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
+ /* - Enable 2D (0x40)
+ * - Enable 3D (0x02)
+ * - Enable 3D vertex command fetch (0x10)
+ * - Enable 3D command parser (0x08)
+ * - Enable 3D G/L transformation engine (0x80)
+ */
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
+}
+
+/*********************************************/
+/* HELPER: SET SEGMENT REGISTERS */
+/*********************************************/
+
+static void
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
+ temp |= (value >> 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
+ temp |= (value & 0x0f);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
+ temp |= (value & 0xf0);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
+ temp |= (value << 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ SiS_SetSegRegLower(SiS_Pr, value);
+ SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp = value >> 8;
+
+ temp &= 0x07;
+ temp |= (temp << 4);
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
+ SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+ SiS_ResetSegmentReg(SiS_Pr);
+ SiS_ResetSegmentRegOver(SiS_Pr);
+}
+
+/*********************************************/
+/* HELPER: SearchModeID */
+/*********************************************/
+
+static int
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex)
+{
+ if ((*ModeNo) <= 0x13) {
+
+ if ((*ModeNo) != 0x03)
+ return 0;
+
+ (*ModeIdIndex) = 0;
+
+ } else {
+
+ for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
+ break;
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+ return 0;
+ }
+
+ }
+
+ return 1;
+}
+
+/*********************************************/
+/* HELPER: ENABLE CRT1 */
+/*********************************************/
+
+static void
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+ /* Enable CRT1 gating */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
+}
+
+/*********************************************/
+/* HELPER: GetColorDepth */
+/*********************************************/
+
+static unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
+ unsigned short modeflag;
+ short index;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ index = (modeflag & ModeTypeMask) - ModeEGA;
+ if (index < 0) index = 0;
+ return ColorDepth[index];
+}
+
+/*********************************************/
+/* HELPER: GetOffset */
+/*********************************************/
+
+static unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short xres, temp, colordepth, infoflag;
+
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
+
+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+ temp = xres / 16;
+
+ if (infoflag & InterlaceMode)
+ temp <<= 1;
+
+ temp *= colordepth;
+
+ if (xres % 16)
+ temp += (colordepth >> 1);
+
+ return temp;
+}
+
+/*********************************************/
+/* SEQ */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char SRdata;
+ int i;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
+
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
+
+ for(i = 2; i <= 4; i++) {
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
+ }
+}
+
+/*********************************************/
+/* MISC */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
+}
+
+/*********************************************/
+/* CRTC */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char CRTCdata;
+ unsigned short i;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+ for(i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
+ }
+}
+
+/*********************************************/
+/* ATT */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char ARdata;
+ unsigned short i;
+
+ for(i = 0; i <= 0x13; i++) {
+ ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
+ }
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
+
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/* GRC */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char GRdata;
+ unsigned short i;
+
+ for(i = 0; i <= 0x08; i++) {
+ GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
+ }
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA) {
+ /* 256 color disable */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
+ }
+}
+
+/*********************************************/
+/* CLEAR EXTENDED REGISTERS */
+/*********************************************/
+
+static void
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ int i;
+
+ for(i = 0x0A; i <= 0x0E; i++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
+ }
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
+}
+
+/*********************************************/
+/* Get rate index */
+/*********************************************/
+
+static unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short rrti, i, index, temp;
+
+ if (ModeNo <= 0x13)
+ return 0xFFFF;
+
+ index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
+ if (index > 0) index--;
+
+ rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
+
+ i = 0;
+ do {
+ if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
+ break;
+
+ temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
+ if (temp < SiS_Pr->SiS_ModeType)
+ break;
+
+ i++;
+ index--;
+ } while(index != 0xFFFF);
+
+ i--;
+
+ return (rrti + i);
+}
+
+/*********************************************/
+/* SYNC */
+/*********************************************/
+
+static void
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
+{
+ unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
+ sync &= 0xC0;
+ sync |= 0x2f;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
+}
+
+/*********************************************/
+/* CRTC/2 */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned char index;
+ unsigned short temp, i, j, modeflag;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
+
+ for(i = 0,j = 0; i <= 7; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x10; i <= 10; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x15; i <= 12; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x0A; i <= 15; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+
+ temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
+
+ temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+ if (modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
+}
+
+/*********************************************/
+/* OFFSET & PITCH */
+/*********************************************/
+/* (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ unsigned short temp;
+
+ temp = (du >> 8) & 0x0f;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
+
+ if (infoflag & InterlaceMode) du >>= 1;
+
+ du <<= 5;
+ temp = (du >> 8) & 0xff;
+ if (du & 0xff) temp++;
+ temp++;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
+}
+
+/*********************************************/
+/* VCLK */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+ unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
+}
+
+/*********************************************/
+/* FIFO */
+/*********************************************/
+
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short mi)
+{
+ unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ /* disable auto-threshold */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
+
+ if (ModeNo <= 0x13)
+ return;
+
+ if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
+ }
+}
+
+/*********************************************/
+/* MODE REGISTERS */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short data = 0, VCLK = 0, index = 0;
+
+ if (ModeNo > 0x13) {
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+
+ if (VCLK >= 166) data |= 0x0c;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
+
+ if (VCLK >= 166)
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
+
+ /* DAC speed */
+ data = 0x03;
+ if (VCLK >= 260)
+ data = 0x00;
+ else if (VCLK >= 160)
+ data = 0x01;
+ else if (VCLK >= 135)
+ data = 0x02;
+
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short data, infoflag = 0, modeflag;
+
+ if (ModeNo <= 0x13)
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ }
+
+ /* Disable DPMS */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
+
+ data = 0;
+ if (ModeNo > 0x13) {
+ if (SiS_Pr->SiS_ModeType > ModeEGA) {
+ data |= 0x02;
+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+ }
+ if (infoflag & InterlaceMode) data |= 0x20;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
+
+ data = 0;
+ if (infoflag & InterlaceMode) {
+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+ unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
+ unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
+ data = hrs - (hto >> 1) + 3;
+ }
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
+
+ if (modeflag & HalfDCLK)
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
+
+ data = 0;
+ if (modeflag & LineCompareOff)
+ data = 0x08;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
+
+ if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
+
+ data = 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeText) {
+ data ^= 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeEGA)
+ data ^= 0xA0;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
+
+ SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
+
+ if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
+ else
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
+}
+
+/*********************************************/
+/* LOAD DAC */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
+ unsigned short shiftflag, unsigned short dl, unsigned short ah,
+ unsigned short al, unsigned short dh)
+{
+ unsigned short d1, d2, d3;
+
+ switch (dl) {
+ case 0:
+ d1 = dh; d2 = ah; d3 = al;
+ break;
+ case 1:
+ d1 = ah; d2 = al; d3 = dh;
+ break;
+ default:
+ d1 = al; d2 = dh; d3 = ah;
+ }
+ SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
+}
+
+static void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
+{
+ unsigned short data, data2, time, i, j, k, m, n, o;
+ unsigned short si, di, bx, sf;
+ unsigned long DACAddr, DACData;
+ const unsigned char *table = NULL;
+
+ if (ModeNo < 0x13)
+ data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
+ else
+ data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ data &= DACInfoFlag;
+
+ j = time = 64;
+ if (data == 0x00)
+ table = SiS_MDA_DAC;
+ else if (data == 0x08)
+ table = SiS_CGA_DAC;
+ else if (data == 0x10)
+ table = SiS_EGA_DAC;
+ else {
+ j = 16;
+ time = 256;
+ table = SiS_VGA_DAC;
+ }
+
+ DACAddr = SiS_Pr->SiS_P3c8;
+ DACData = SiS_Pr->SiS_P3c9;
+ sf = 0;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
+
+ for(i = 0; i < j; i++) {
+ data = table[i];
+ for(k = 0; k < 3; k++) {
+ data2 = 0;
+ if (data & 0x01) data2 += 0x2A;
+ if (data & 0x02) data2 += 0x15;
+ SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
+ data >>= 2;
+ }
+ }
+
+ if (time == 256) {
+ for(i = 16; i < 32; i++) {
+ data = table[i] << sf;
+ for(k = 0; k < 3; k++)
+ SiS_SetRegByte(SiS_Pr, DACData, data);
+ }
+ si = 32;
+ for(m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 4;
+ for(n = 0; n < 3; n++) {
+ for(o = 0; o < 5; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[bx], table[si]);
+ si++;
+ }
+ si -= 2;
+ for(o = 0; o < 3; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[si], table[bx]);
+ si--;
+ }
+ }
+ si += 5;
+ }
+ }
+}
+
+/*********************************************/
+/* SET CRT1 REGISTER GROUP */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short StandTableIndex, rrti;
+
+ SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+ if (ModeNo <= 0x13)
+ StandTableIndex = 0;
+ else
+ StandTableIndex = 1;
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+
+ rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if (rrti != 0xFFFF) {
+ SiS_SetCRT1Sync(SiS_Pr, rrti);
+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
+ }
+
+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_DisplayOn(SiS_Pr);
+}
+
+/*********************************************/
+/* SiSSetMode() */
+/*********************************************/
+
+int
+SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ unsigned short ModeIdIndex;
+ unsigned long BaseAddr = SiS_Pr->IOAddress;
+
+ SiSUSB_InitPtr(SiS_Pr);
+ SiSUSBRegInit(SiS_Pr, BaseAddr);
+ SiS_GetSysFlags(SiS_Pr);
+
+ if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
+ return 0;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
+
+ SiSInitPCIetc(SiS_Pr);
+
+ ModeNo &= 0x7f;
+
+ SiS_Pr->SiS_ModeType =
+ SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
+
+ SiS_Pr->SiS_SetFlag = LowModeTests;
+
+ /* Set mode on CRT1 */
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_HandleCRT1(SiS_Pr);
+
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ /* Store mode number */
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
+
+ return 1;
+}
+
+int
+SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
+{
+ unsigned short ModeNo = 0;
+ int i;
+
+ SiSUSB_InitPtr(SiS_Pr);
+
+ if (VModeNo == 0x03) {
+
+ ModeNo = 0x03;
+
+ } else {
+
+ i = 0;
+ do {
+
+ if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
+ ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
+ break;
+ }
+
+ } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
+
+ }
+
+ if (!ModeNo)
+ return 0;
+
+ return SiSUSBSetMode(SiS_Pr, ModeNo);
+}
+
+#endif /* INCL_SISUSB_CON */
+
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 000000000000..5b11577835c8
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,830 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_INIT_H_
+#define _SISUSB_INIT_H_
+
+/* SiS_ModeType */
+#define ModeText 0x00
+#define ModeCGA 0x01
+#define ModeEGA 0x02
+#define ModeVGA 0x03
+#define Mode15Bpp 0x04
+#define Mode16Bpp 0x05
+#define Mode24Bpp 0x06
+#define Mode32Bpp 0x07
+
+#define ModeTypeMask 0x07
+#define IsTextMode 0x07
+
+#define DACInfoFlag 0x0018
+#define MemoryInfoFlag 0x01E0
+#define MemorySizeShift 5
+
+/* modeflag */
+#define Charx8Dot 0x0200
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode 0x8000
+
+/* Infoflag */
+#define SupportTV 0x0008
+#define SupportTV1024 0x0800
+#define SupportCHTV 0x0800
+#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */
+#define SupportHiVision 0x0010
+#define SupportYPbPr750p 0x1000
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */
+#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */
+#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+#define SyncNN 0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2 0x0001
+#define LowModeTests 0x0002
+#define LCDVESATiming 0x0008
+#define EnableLVDSDDA 0x0010
+#define SetDispDevSwitchFlag 0x0020
+#define CheckWinDos 0x0040
+#define SetDOSMode 0x0080
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200 0
+#define SIS_RI_320x240 1
+#define SIS_RI_320x400 2
+#define SIS_RI_400x300 3
+#define SIS_RI_512x384 4
+#define SIS_RI_640x400 5
+#define SIS_RI_640x480 6
+#define SIS_RI_800x600 7
+#define SIS_RI_1024x768 8
+#define SIS_RI_1280x1024 9
+#define SIS_RI_1600x1200 10
+#define SIS_RI_1920x1440 11
+#define SIS_RI_2048x1536 12
+#define SIS_RI_720x480 13
+#define SIS_RI_720x576 14
+#define SIS_RI_1280x960 15
+#define SIS_RI_800x480 16
+#define SIS_RI_1024x576 17
+#define SIS_RI_1280x720 18
+#define SIS_RI_856x480 19
+#define SIS_RI_1280x768 20
+#define SIS_RI_1400x1050 21
+#define SIS_RI_1152x864 22 /* Up to here SiS conforming */
+#define SIS_RI_848x480 23
+#define SIS_RI_1360x768 24
+#define SIS_RI_1024x600 25
+#define SIS_RI_1152x768 26
+#define SIS_RI_768x576 27
+#define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800 30
+#define SIS_RI_1920x1080 31
+#define SIS_RI_960x540 32
+#define SIS_RI_960x600 33
+
+#define SIS_VIDEO_CAPTURE 0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
+#define SIS_CRT2_PORT_04 0x04 - 0x30
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f};
+static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22};
+static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+
+static const unsigned char SiS_MDA_DAC[] =
+{
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+ 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+ 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+ 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+ 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+ 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+ 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+ 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+ 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+ 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+ 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+ 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+ 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x0B,0x0C,0x0D,0x0F,0x10
+};
+
+static const struct SiS_St SiSUSB_SModeIDTable[] =
+{
+ {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
+{
+ { 640,400},
+ { 640,350},
+ { 720,400},
+ { 720,350},
+ { 640,480}
+};
+
+static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
+{
+ { 320, 200, 8, 8}, /* 0x00 */
+ { 320, 240, 8, 8}, /* 0x01 */
+ { 320, 400, 8, 8}, /* 0x02 */
+ { 400, 300, 8, 8}, /* 0x03 */
+ { 512, 384, 8, 8}, /* 0x04 */
+ { 640, 400, 8,16}, /* 0x05 */
+ { 640, 480, 8,16}, /* 0x06 */
+ { 800, 600, 8,16}, /* 0x07 */
+ { 1024, 768, 8,16}, /* 0x08 */
+ { 1280,1024, 8,16}, /* 0x09 */
+ { 1600,1200, 8,16}, /* 0x0a */
+ { 1920,1440, 8,16}, /* 0x0b */
+ { 2048,1536, 8,16}, /* 0x0c */
+ { 720, 480, 8,16}, /* 0x0d */
+ { 720, 576, 8,16}, /* 0x0e */
+ { 1280, 960, 8,16}, /* 0x0f */
+ { 800, 480, 8,16}, /* 0x10 */
+ { 1024, 576, 8,16}, /* 0x11 */
+ { 1280, 720, 8,16}, /* 0x12 */
+ { 856, 480, 8,16}, /* 0x13 */
+ { 1280, 768, 8,16}, /* 0x14 */
+ { 1400,1050, 8,16}, /* 0x15 */
+ { 1152, 864, 8,16}, /* 0x16 */
+ { 848, 480, 8,16}, /* 0x17 */
+ { 1360, 768, 8,16}, /* 0x18 */
+ { 1024, 600, 8,16}, /* 0x19 */
+ { 1152, 768, 8,16}, /* 0x1a */
+ { 768, 576, 8,16}, /* 0x1b */
+ { 1360,1024, 8,16}, /* 0x1c */
+ { 1680,1050, 8,16}, /* 0x1d */
+ { 1280, 800, 8,16}, /* 0x1e */
+ { 1920,1080, 8,16}, /* 0x1f */
+ { 960, 540, 8,16}, /* 0x20 */
+ { 960, 600, 8,16} /* 0x21 */
+};
+
+static const struct SiS_StandTable SiSUSB_StandTable[] =
+{
+ /* MD_3_400 - mode 0x03 - 400 */
+ {
+ 0x50,0x18,0x10,0x1000,
+ { 0x00,0x03,0x00,0x02 },
+ 0x67,
+ { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+ 0xff },
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x0c,0x00,0x0f,0x08 },
+ { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
+ },
+ /* Generic for VGA and higher */
+ {
+ 0x00,0x00,0x00,0x0000,
+ { 0x01,0x0f,0x00,0x0e },
+ 0x23,
+ { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+ 0xff },
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x01,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
+ }
+};
+
+static const struct SiS_Ext SiSUSB_EModeIDTable[] =
+{
+ {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+ {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+ {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+ {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+ {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+ {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+ {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+ {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+ {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+ {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+ {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
+ {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
+ {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+ {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+ {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+ {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
+ {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */
+ {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */
+ {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */
+ {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
+ {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
+ {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
+ {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */
+ {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
+ {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
+ {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+ {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+ {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+ {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+ {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
+ {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
+ {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
+ {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
+ {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
+ {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
+ {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
+ {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
+ {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
+ {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
+ {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
+ {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
+ {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
+ {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
+ {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
+ {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
+ {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
+ {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
+ {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
+ {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
+ {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
+ {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
+ {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
+ {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
+ {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
+ {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
+ {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
+ {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
+ {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
+ {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
+ {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
+ {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
+ {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+ {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+ {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const struct SiS_Ext2 SiSUSB_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
+ {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
+ {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
+ {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
+ {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
+ {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
+ {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
+ {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
+ {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
+ {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
+ {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
+ {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
+ {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
+ {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
+ {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
+ {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
+ {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
+ {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
+ {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
+ {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
+ {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
+ {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
+ {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
+ {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
+ {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
+ {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
+ {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
+ {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
+ {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
+ {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
+ {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
+ {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
+ {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
+ {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */
+ {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */
+ {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */
+ {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */
+ {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */
+ {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
+ {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
+ {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
+ {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
+ {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
+ {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
+ {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */
+ {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */
+ {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */
+ {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
+ 0x00}}, /* 0x0 */
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}, /* 0x1 */
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
+ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+ 0x01}}, /* 0x2 */
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+ 0x01}}, /* 0x3 */
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+ 0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
+ 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+ 0x00}}, /* 0x6 */
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+ 0x00}}, /* 0x7 */
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+ 0x00}}, /* 0x8 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+ 0x61}}, /* 0x9 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
+ 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
+ 0x61}}, /* 0xa */
+ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
+ 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
+ 0x61}}, /* 0xb */
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+ 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
+ 0x00}}, /* 0xc */
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+ 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+ 0x01}}, /* 0xd */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+ 0x01}}, /* 0xe */
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+ 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+ 0x01}}, /* 0xf */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+ 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+ 0x01}}, /* 0x10 */
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+ 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+ 0x01}}, /* 0x11 */
+ {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
+ 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
+ 0x61}}, /* 0x12 */
+ {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
+ 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
+ 0x61}}, /* 0x13 */
+ {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
+ 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
+ 0x61}}, /* 0x14 */
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+ 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+ 0x00}}, /* 0x15 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x16 */
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x17 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+ 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+ 0x01}}, /* 0x18 */
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+ 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+ 0x01}}, /* 0x19 */
+ {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
+ 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
+ 0x62}}, /* 0x1a */
+ {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
+ 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
+ 0x62}}, /* 0x1b */
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+ 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+ 0x00}}, /* 0x1c */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+ 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+ 0x01}}, /* 0x1d */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
+ 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+ 0x01}}, /* 0x1e */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+ 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+ 0x01}}, /* 0x1f */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x20 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x21 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x22 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x23 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x24 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x25 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x26 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x27 */
+ {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
+ 0x63}}, /* 0x28 */
+ {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
+ 0x63}}, /* 0x29 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2a */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2b */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2c */
+ {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
+ 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2d */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
+ 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2e */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
+ 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2f */
+ {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
+ 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
+ 0x44}}, /* 0x30 */
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+ 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+ 0x00}}, /* 0x31 */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
+ 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+ 0x01}}, /* 0x32 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+ 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+ 0x01}}, /* 0x33 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+ 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+ 0x01}}, /* 0x34 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+ 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+ 0x01}}, /* 0x35 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+ 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+ 0x01}}, /* 0x36 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
+ 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+ 0x01}}, /* 0x37 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+ 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x38 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+ 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x39 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+ 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+ 0x01}}, /* 0x3a */
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
+ 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+ 0x01}}, /* 0x3b */
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+ 0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x3d */
+ {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
+ 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
+ 0x00}}, /* 0x3e */
+ {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
+ 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
+ 0x00}}, /* 0x3f */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+ 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+ 0x01}}, /* 0x40 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x41 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
+ 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+ 0x01}}, /* 0x42 */
+ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
+ 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
+ 0x00}}, /* 0x43 */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
+ 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+ 0x01}}, /* 0x44 */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x45 */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
+ 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+ 0x00}}, /* 0x46 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x47 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
+ 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+ 0x00}}, /* 0x48 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
+ 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+ 0x01}}, /* 0x49 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
+ 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+ 0x01}}, /* 0x4a */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
+ 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
+ 0x00}}, /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
+ 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+ 0x01}}, /* 0x4c */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}},
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}, /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
+ 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+ 0x21}}, /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
+ 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+ 0x20}}, /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
+ 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+ 0x61}}, /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
+ 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+ 0x41}}, /* 0x52 */
+ {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
+ 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
+ 0x01}}, /* 0x53 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
+ 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+ 0x41}} /* 0x54 */
+};
+
+static struct SiS_VCLKData SiSUSB_VCLKData[] =
+{
+ { 0x1b,0xe1, 25}, /* 0x00 */
+ { 0x4e,0xe4, 28}, /* 0x01 */
+ { 0x57,0xe4, 31}, /* 0x02 */
+ { 0xc3,0xc8, 36}, /* 0x03 */
+ { 0x42,0xe2, 40}, /* 0x04 */
+ { 0xfe,0xcd, 43}, /* 0x05 */
+ { 0x5d,0xc4, 44}, /* 0x06 */
+ { 0x52,0xe2, 49}, /* 0x07 */
+ { 0x53,0xe2, 50}, /* 0x08 */
+ { 0x74,0x67, 52}, /* 0x09 */
+ { 0x6d,0x66, 56}, /* 0x0a */
+ { 0x5a,0x64, 65}, /* 0x0b */
+ { 0x46,0x44, 67}, /* 0x0c */
+ { 0xb1,0x46, 68}, /* 0x0d */
+ { 0xd3,0x4a, 72}, /* 0x0e */
+ { 0x29,0x61, 75}, /* 0x0f */
+ { 0x6e,0x46, 76}, /* 0x10 */
+ { 0x2b,0x61, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x41,104}, /* 0x17 */
+ { 0x3a,0x23,105}, /* 0x18 */
+ { 0x70,0x44,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0x54,0x42,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x62,0x06,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a 301 TV */
+ { 0x52,0x6a, 27}, /* 0x3b 301 TV */
+ { 0x62,0x24, 70}, /* 0x3c 301 TV */
+ { 0x62,0x64, 70}, /* 0x3d 301 TV */
+ { 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+ { 0x20,0x26, 33}, /* 0x3f 301 TV */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x60,0x36, 30}, /* 0x41 Chrontel */
+ { 0x40,0x4a, 28}, /* 0x42 Chrontel */
+ { 0x9f,0x46, 44}, /* 0x43 Chrontel */
+ { 0x97,0x2c, 26}, /* 0x44 */
+ { 0x44,0xe4, 25}, /* 0x45 Chrontel */
+ { 0x7e,0x32, 47}, /* 0x46 Chrontel */
+ { 0x8a,0x24, 31}, /* 0x47 Chrontel */
+ { 0x97,0x2c, 26}, /* 0x48 Chrontel */
+ { 0xce,0x3c, 39}, /* 0x49 */
+ { 0x52,0x4a, 36}, /* 0x4a Chrontel */
+ { 0x34,0x61, 95}, /* 0x4b */
+ { 0x78,0x27,108}, /* 0x4c - was 102 */
+ { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+ { 0x41,0x4e, 21}, /* 0x4e */
+ { 0xa1,0x4a, 29}, /* 0x4f Chrontel */
+ { 0x19,0x42, 42}, /* 0x50 */
+ { 0x54,0x46, 58}, /* 0x51 Chrontel */
+ { 0x25,0x42, 61}, /* 0x52 */
+ { 0x44,0x44, 66}, /* 0x53 Chrontel */
+ { 0x3a,0x62, 70}, /* 0x54 Chrontel */
+ { 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+ { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+ { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+ { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+ { 0x52,0x07,149}, /* 0x59 1280x960-85 */
+ { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+ { 0x45,0x25, 83}, /* 0x5c 1280x800 */
+ { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+ { 0x70,0x24,162}, /* 0x5e 1600x1200 */
+ { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+ { 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+ { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+ { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */
+ { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+ { 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+ { 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+ { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+ { 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+ { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+ { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+ { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+ { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+ { 0x45,0x25, 83}, /* 0x6c 1280x800 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35} /* 0x71 768@576@60 */
+};
+
+void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
+unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
+int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 data);
+extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 *data);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand, u8 myor);
+extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 myor);
+extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand);
+
+#endif
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 000000000000..94edd4726c42
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,169 @@
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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) 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_STRUCT_H_
+#define _SISUSB_STRUCT_H_
+
+struct SiS_St {
+ unsigned char St_ModeID;
+ unsigned short St_ModeFlag;
+ unsigned char St_StTableIndex;
+ unsigned char St_CRT2CRTC;
+ unsigned char St_ResInfo;
+ unsigned char VB_StTVFlickerIndex;
+ unsigned char VB_StTVEdgeIndex;
+ unsigned char VB_StTVYFilterIndex;
+ unsigned char St_PDC;
+};
+
+struct SiS_StandTable
+{
+ unsigned char CRT_COLS;
+ unsigned char ROWS;
+ unsigned char CHAR_HEIGHT;
+ unsigned short CRT_LEN;
+ unsigned char SR[4];
+ unsigned char MISC;
+ unsigned char CRTC[0x19];
+ unsigned char ATTR[0x14];
+ unsigned char GRC[9];
+};
+
+struct SiS_StResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+};
+
+struct SiS_Ext
+{
+ unsigned char Ext_ModeID;
+ unsigned short Ext_ModeFlag;
+ unsigned short Ext_VESAID;
+ unsigned char Ext_RESINFO;
+ unsigned char VB_ExtTVFlickerIndex;
+ unsigned char VB_ExtTVEdgeIndex;
+ unsigned char VB_ExtTVYFilterIndex;
+ unsigned char VB_ExtTVYFilterIndexROM661;
+ unsigned char REFindex;
+ char ROMMODEIDX661;
+};
+
+struct SiS_Ext2
+{
+ unsigned short Ext_InfoFlag;
+ unsigned char Ext_CRT1CRTC;
+ unsigned char Ext_CRTVCLK;
+ unsigned char Ext_CRT2CRTC;
+ unsigned char Ext_CRT2CRTC_NS;
+ unsigned char ModeID;
+ unsigned short XRes;
+ unsigned short YRes;
+ unsigned char Ext_PDC;
+ unsigned char Ext_FakeCRT2CRTC;
+ unsigned char Ext_FakeCRT2Clk;
+};
+
+struct SiS_CRT1Table
+{
+ unsigned char CR[17];
+};
+
+struct SiS_VCLKData
+{
+ unsigned char SR2B,SR2C;
+ unsigned short CLOCK;
+};
+
+struct SiS_ModeResInfo
+{
+ unsigned short HTotal;
+ unsigned short VTotal;
+ unsigned char XChar;
+ unsigned char YChar;
+};
+
+struct SiS_Private
+{
+ void *sisusb;
+
+ unsigned long IOAddress;
+
+ unsigned long SiS_P3c4;
+ unsigned long SiS_P3d4;
+ unsigned long SiS_P3c0;
+ unsigned long SiS_P3ce;
+ unsigned long SiS_P3c2;
+ unsigned long SiS_P3ca;
+ unsigned long SiS_P3c6;
+ unsigned long SiS_P3c7;
+ unsigned long SiS_P3c8;
+ unsigned long SiS_P3c9;
+ unsigned long SiS_P3cb;
+ unsigned long SiS_P3cc;
+ unsigned long SiS_P3cd;
+ unsigned long SiS_P3da;
+ unsigned long SiS_Part1Port;
+
+ unsigned char SiS_MyCR63;
+ unsigned short SiS_CRT1Mode;
+ unsigned short SiS_ModeType;
+ unsigned short SiS_SetFlag;
+
+ const struct SiS_StandTable *SiS_StandTable;
+ const struct SiS_St *SiS_SModeIDTable;
+ const struct SiS_Ext *SiS_EModeIDTable;
+ const struct SiS_Ext2 *SiS_RefIndex;
+ const struct SiS_CRT1Table *SiS_CRT1Table;
+ struct SiS_VCLKData *SiS_VCLKData;
+ const struct SiS_ModeResInfo *SiS_ModeResInfo;
+};
+
+#endif
+
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index cda7249a90b2..54799eb0bc60 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -986,7 +986,6 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
u->context = &context;
u->complete = ctrl_complete;
- u->transfer_flags |= URB_ASYNC_UNLINK;
}
/* queue the urbs */
@@ -1052,7 +1051,6 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
if (!urb)
return -ENOMEM;
- urb->transfer_flags |= URB_ASYNC_UNLINK;
urb->context = &completion;
urb->complete = unlink1_callback;
@@ -1533,7 +1531,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (down_interruptible (&dev->sem))
return -ERESTARTSYS;
- if (intf->dev.power.power_state != PMSG_ON) {
+ if (intf->dev.power.power_state.event != PM_EVENT_ON) {
up (&dev->sem);
return -EHOSTUNREACH;
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index faa74436de52..03fb70ef2eb3 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -3,8 +3,8 @@
/*
* uss720.c -- USS720 USB Parport Cable.
*
- * Copyright (C) 1999
- * Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1999, 2005
+ * Thomas Sailer (t.sailer@alumni.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,103 +23,240 @@
* Based on parport_pc.c
*
* History:
- * 0.1 04.08.99 Created
- * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh
- * Interrupt handling currently disabled because
- * usb_request_irq crashes somewhere within ohci.c
- * for no apparent reason (that is for me, anyway)
- * ECP currently untested
- * 0.3 10.08.99 fixing merge errors
- * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable
- * 0.5 20.09.99 usb_control_msg wrapper used
- * Nov01.00 usb_device_table support by Adam J. Richter
- * 08.04.01 Identify version on module load. gb
+ * 0.1 04.08.1999 Created
+ * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh
+ * Interrupt handling currently disabled because
+ * usb_request_irq crashes somewhere within ohci.c
+ * for no apparent reason (that is for me, anyway)
+ * ECP currently untested
+ * 0.3 10.08.1999 fixing merge errors
+ * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable
+ * 0.5 20.09.1999 usb_control_msg wrapper used
+ * Nov01.2000 usb_device_table support by Adam J. Richter
+ * 08.04.2001 Identify version on module load. gb
+ * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore
+ * context asynchronous
*
*/
/*****************************************************************************/
+#define DEBUG
+
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/parport.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5"
-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_VERSION "v0.6"
+#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
/* --------------------------------------------------------------------- */
struct parport_uss720_private {
struct usb_device *usbdev;
- void *irqhandle;
- unsigned int irqpipe;
- unsigned char reg[7]; /* USB registers */
+ struct parport *pp;
+ struct kref ref_count;
+ __u8 reg[7]; /* USB registers */
+ struct list_head asynclist;
+ spinlock_t asynclock;
+};
+
+struct uss720_async_request {
+ struct parport_uss720_private *priv;
+ struct kref ref_count;
+ struct list_head asynclist;
+ struct completion compl;
+ struct urb *urb;
+ struct usb_ctrlrequest dr;
+ __u8 reg[7];
};
/* --------------------------------------------------------------------- */
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+static void destroy_priv(struct kref *kref)
{
- struct parport_uss720_private *priv = pp->private_data;
- struct usb_device *usbdev = priv->usbdev;
- static const unsigned char regindex[9] = {
- 4, 0, 1, 5, 5, 0, 2, 3, 6
- };
- int ret;
+ struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
- if (!usbdev)
- return -1;
- ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
- if (ret != 7) {
- printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
- (unsigned int)reg, ret);
- ret = -1;
- } else {
+ usb_put_dev(priv->usbdev);
+ kfree(priv);
+ dbg("destroying priv datastructure");
+}
+
+static void destroy_async(struct kref *kref)
+{
+ struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
+ struct parport_uss720_private *priv = rq->priv;
+ unsigned long flags;
+
+ if (likely(rq->urb))
+ usb_free_urb(rq->urb);
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_del_init(&rq->asynclist);
+ spin_unlock_irqrestore(&priv->asynclock, flags);
+ kfree(rq);
+ kref_put(&priv->ref_count, destroy_priv);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+ struct uss720_async_request *rq;
+ struct parport *pp;
+ struct parport_uss720_private *priv;
+
+ rq = urb->context;
+ priv = rq->priv;
+ pp = priv->pp;
+ if (urb->status) {
+ err("async_complete: urb error %d", urb->status);
+ } else if (rq->dr.bRequest == 3) {
+ memcpy(priv->reg, rq->reg, sizeof(priv->reg));
#if 0
- printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
- (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
- (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
- (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
+ dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
+ (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
+ (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
+ (unsigned int)priv->reg[6]);
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
- if (priv->reg[2] & priv->reg[1] & 0x10)
+ if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
parport_generic_irq(0, pp, NULL);
- ret = 0;
}
- if (val)
- *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
- return ret;
+ complete(&rq->compl);
+ kref_put(&rq->ref_count, destroy_async);
}
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
+ unsigned int mem_flags)
{
- struct parport_uss720_private *priv = pp->private_data;
- struct usb_device *usbdev = priv->usbdev;
+ struct usb_device *usbdev;
+ struct uss720_async_request *rq;
+ unsigned long flags;
int ret;
+ if (!priv)
+ return NULL;
+ usbdev = priv->usbdev;
if (!usbdev)
- return -1;
- ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
- if (ret) {
- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n",
- (unsigned int)reg, (unsigned int)val, ret);
- } else {
-#if 0
- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n",
- (unsigned int)reg, (unsigned int)val);
-#endif
+ return NULL;
+ rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
+ if (!rq) {
+ err("submit_async_request out of memory");
+ return NULL;
+ }
+ kref_init(&rq->ref_count);
+ INIT_LIST_HEAD(&rq->asynclist);
+ init_completion(&rq->compl);
+ kref_get(&priv->ref_count);
+ rq->priv = priv;
+ rq->urb = usb_alloc_urb(0, mem_flags);
+ if (!rq->urb) {
+ kref_put(&rq->ref_count, destroy_async);
+ err("submit_async_request out of memory");
+ return NULL;
+ }
+ rq->dr.bRequestType = requesttype;
+ rq->dr.bRequest = request;
+ rq->dr.wValue = cpu_to_le16(value);
+ rq->dr.wIndex = cpu_to_le16(index);
+ rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
+ usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
+ (unsigned char *)&rq->dr,
+ (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
+ /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_add_tail(&rq->asynclist, &priv->asynclist);
+ spin_unlock_irqrestore(&priv->asynclock, flags);
+ ret = usb_submit_urb(rq->urb, mem_flags);
+ if (!ret) {
+ kref_get(&rq->ref_count);
+ return rq;
}
+ kref_put(&rq->ref_count, destroy_async);
+ err("submit_async_request submit_urb failed with %d", ret);
+ return NULL;
+}
+
+static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
+{
+ struct uss720_async_request *rq;
+ unsigned long flags;
+ unsigned int ret = 0;
+
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_for_each_entry(rq, &priv->asynclist, asynclist) {
+ usb_unlink_urb(rq->urb);
+ ret++;
+ }
+ spin_unlock_irqrestore(&priv->asynclock, flags);
return ret;
}
/* --------------------------------------------------------------------- */
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+{
+ struct parport_uss720_private *priv;
+ struct uss720_async_request *rq;
+ static const unsigned char regindex[9] = {
+ 4, 0, 1, 5, 5, 0, 2, 3, 6
+ };
+ int ret;
+
+ if (!pp)
+ return -EIO;
+ priv = pp->private_data;
+ rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
+ if (!rq) {
+ err("get_1284_register(%u) failed", (unsigned int)reg);
+ return -EIO;
+ }
+ if (!val) {
+ kref_put(&rq->ref_count, destroy_async);
+ return 0;
+ }
+ if (wait_for_completion_timeout(&rq->compl, HZ)) {
+ ret = rq->urb->status;
+ *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
+ if (ret)
+ warn("get_1284_register: usb error %d", ret);
+ kref_put(&rq->ref_count, destroy_async);
+ return ret;
+ }
+ warn("get_1284_register timeout");
+ kill_all_async_requests_priv(priv);
+ return -EIO;
+}
+
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
+{
+ struct parport_uss720_private *priv;
+ struct uss720_async_request *rq;
+
+ if (!pp)
+ return -EIO;
+ priv = pp->private_data;
+ rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
+ if (!rq) {
+ err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
+ return -EIO;
+ }
+ kref_put(&rq->ref_count, destroy_async);
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
/* ECR modes */
#define ECR_SPP 00
#define ECR_PS2 01
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
{
struct parport_uss720_private *priv = pp->private_data;
int mode;
+ __u8 reg;
- if (get_1284_register(pp, 6, NULL))
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
/* Bits <7:5> contain the mode. */
mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
case ECR_ECP: /* ECP Parallel Port mode */
/* Poll slowly. */
for (;;) {
- if (get_1284_register(pp, 6, NULL))
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
if (priv->reg[2] & 0x01)
break;
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
}
}
/* Set the mode. */
- if (set_1284_register(pp, 6, m << 5))
+ if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
+ return -EIO;
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
return 0;
}
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
{
unsigned char stat;
- if (get_1284_register(pp, 1, &stat))
+ if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
return 1;
return stat & 1;
}
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
static void parport_uss720_write_data(struct parport *pp, unsigned char d)
{
- set_1284_register(pp, 0, d);
+ set_1284_register(pp, 0, d, GFP_KERNEL);
}
static unsigned char parport_uss720_read_data(struct parport *pp)
{
unsigned char ret;
- if (get_1284_register(pp, 0, &ret))
+ if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
return 0;
return ret;
}
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
struct parport_uss720_private *priv = pp->private_data;
d = (d & 0xf) | (priv->reg[1] & 0xf0);
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
mask &= 0x0f;
val &= 0x0f;
d = (priv->reg[1] & (~mask)) ^ val;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return 0;
priv->reg[1] = d;
return d & 0xf;
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
{
unsigned char ret;
- if (get_1284_register(pp, 1, &ret))
+ if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
return 0;
return ret & 0xf8;
}
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
unsigned char d;
d = priv->reg[1] & ~0x10;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
unsigned char d;
d = priv->reg[1] | 0x10;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
unsigned char d;
d = priv->reg[1] & ~0x20;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
unsigned char d;
d = priv->reg[1] | 0x20;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
{
struct parport_uss720_private *priv = pp->private_data;
- if (get_1284_register(pp, 2, NULL))
+#if 0
+ if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
return;
+#endif
s->u.pc.ctr = priv->reg[1];
s->u.pc.ecr = priv->reg[2];
}
static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
{
- set_1284_register(pp, 2, s->u.pc.ctr);
- set_1284_register(pp, 6, s->u.pc.ecr);
- get_1284_register(pp, 2, NULL);
+ struct parport_uss720_private *priv = pp->private_data;
+
+ set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
+ set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
+ get_1284_register(pp, 2, NULL, GFP_ATOMIC);
+ priv->reg[1] = s->u.pc.ctr;
+ priv->reg[2] = s->u.pc.ecr;
}
static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
- if (get_1284_register(pp, 4, (char *)buf))
+ if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
break;
buf++;
if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
- if (set_1284_register(pp, 4, (char *)buf))
+ if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
break;
((char*)buf)++;
- if (get_1284_register(pp, 1, NULL))
+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
- if (get_1284_register(pp, 3, (char *)buf))
+ if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
break;
buf++;
if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
- if (set_1284_register(pp, 3, *(char *)buf))
+ if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
break;
buf++;
- if (get_1284_register(pp, 1, NULL))
+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
if (change_mode(pp, ECR_ECP))
return 0;
for (; written < len; written++) {
- if (set_1284_register(pp, 5, *(char *)buffer))
+ if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
break;
buffer++;
}
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
static int uss720_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct usb_device *usbdev = interface_to_usbdev(intf);
+ struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
struct usb_host_interface *interface;
struct usb_host_endpoint *endpoint;
struct parport_uss720_private *priv;
struct parport *pp;
+ unsigned char reg;
int i;
- printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
- le16_to_cpu(usbdev->descriptor.idVendor),
- le16_to_cpu(usbdev->descriptor.idProduct));
+ dbg("probe: vendor id 0x%x, device id 0x%x\n",
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct));
/* our known interfaces have 3 alternate settings */
- if (intf->num_altsetting != 3)
+ if (intf->num_altsetting != 3) {
+ usb_put_dev(usbdev);
return -ENODEV;
-
+ }
i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
- printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+ dbg("set inteface result %d", i);
interface = intf->cur_altsetting;
/*
* Allocate parport interface
*/
- printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
-
- if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+ if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+ usb_put_dev(usbdev);
return -ENOMEM;
+ }
+ priv->pp = NULL;
+ priv->usbdev = usbdev;
+ kref_init(&priv->ref_count);
+ spin_lock_init(&priv->asynclock);
+ INIT_LIST_HEAD(&priv->asynclist);
if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
- printk(KERN_WARNING "usb-uss720: could not register parport\n");
+ warn("could not register parport");
goto probe_abort;
}
+ priv->pp = pp;
pp->private_data = priv;
- priv->usbdev = usbdev;
pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
- set_1284_register(pp, 7, 0x00);
- set_1284_register(pp, 6, 0x30); /* PS/2 mode */
- set_1284_register(pp, 2, 0x0c);
+ set_1284_register(pp, 7, 0x00, GFP_KERNEL);
+ set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */
+ set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
/* debugging */
- get_1284_register(pp, 0, NULL);
- printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
- priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+ get_1284_register(pp, 0, &reg, GFP_KERNEL);
+ dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
+ priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
endpoint = &interface->endpoint[2];
- printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
-#if 0
- priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
- i = usb_request_irq(usbdev, priv->irqpipe,
- uss720_irq, endpoint->bInterval,
- pp, &priv->irqhandle);
- if (i) {
- printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
- goto probe_abort_port;
- }
-#endif
+ dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
parport_announce_port(pp);
- usb_set_intfdata (intf, pp);
+ usb_set_intfdata(intf, pp);
return 0;
-#if 0
-probe_abort_port:
- parport_put_port(pp);
-#endif
probe_abort:
- kfree(priv);
+ kill_all_async_requests_priv(priv);
+ kref_put(&priv->ref_count, destroy_priv);
return -ENODEV;
}
static void uss720_disconnect(struct usb_interface *intf)
{
- struct parport *pp = usb_get_intfdata (intf);
+ struct parport *pp = usb_get_intfdata(intf);
struct parport_uss720_private *priv;
+ struct usb_device *usbdev;
- usb_set_intfdata (intf, NULL);
+ dbg("disconnect");
+ usb_set_intfdata(intf, NULL);
if (pp) {
priv = pp->private_data;
- parport_remove_port(pp);
-#if 0
- usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
+ usbdev = priv->usbdev;
priv->usbdev = NULL;
+ priv->pp = NULL;
+ dbg("parport_remove_port");
+ parport_remove_port(pp);
parport_put_port(pp);
- kfree(priv);
+ kill_all_async_requests_priv(priv);
+ kref_put(&priv->ref_count, destroy_priv);
}
+ dbg("disconnect done");
}
/* table of cables that work through this driver */
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
/* --------------------------------------------------------------------- */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static int __init uss720_init(void)
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
goto out;
info(DRIVER_VERSION ":" DRIVER_DESC);
+ info("NOTE: this is a special purpose driver to allow nonstandard");
+ info("protocols (eg. bitbang) over USS720 usb to parallel cables");
+ info("If you just want to connect to a printer, use usblp instead");
out:
return retval;
}
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index b0015b8a1d1f..3cf3ea3a88ed 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -2,7 +2,7 @@
# Makefile for USB Core files and filesystem
#
-usbmon-objs := mon_main.o mon_stat.o mon_text.o
+usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_dma.o
# This does not use CONFIG_USB_MON because we want this to use a tristate.
obj-$(CONFIG_USB) += usbmon.o
diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c
new file mode 100644
index 000000000000..0a1367b760a0
--- /dev/null
+++ b/drivers/usb/mon/mon_dma.c
@@ -0,0 +1,55 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * mon_dma.c: Library which snoops on DMA areas.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
+ */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+
+#include <linux/usb.h> /* Only needed for declarations in usb_mon.h */
+#include "usb_mon.h"
+
+#ifdef __i386__ /* CONFIG_ARCH_I386 does not exit */
+#define MON_HAS_UNMAP 1
+
+#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
+
+char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+{
+ struct page *pg;
+ unsigned long flags;
+ unsigned char *map;
+ unsigned char *ptr;
+
+ /*
+ * On i386, a DMA handle is the "physical" address of a page.
+ * In other words, the bus address is equal to physical address.
+ * There is no IOMMU.
+ */
+ pg = phys_to_page(dma_addr);
+
+ /*
+ * We are called from hardware IRQs in case of callbacks.
+ * But we can be called from softirq or process context in case
+ * of submissions. In such case, we need to protect KM_IRQ0.
+ */
+ local_irq_save(flags);
+ map = kmap_atomic(pg, KM_IRQ0);
+ ptr = map + (dma_addr & (PAGE_SIZE-1));
+ memcpy(dst, ptr, len);
+ kunmap_atomic(map, KM_IRQ0);
+ local_irq_restore(flags);
+ return 0;
+}
+#endif /* __i386__ */
+
+#ifndef MON_HAS_UNMAP
+char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+{
+ return 'D';
+}
+#endif
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 26266b30028e..17d0190ef64e 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -79,7 +79,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
return '-';
if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
- return 'D';
+ return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
if (urb->setup_packet == NULL)
return 'Z'; /* '0' would be not as pretty. */
@@ -91,25 +91,11 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
int len, char ev_type)
{
int pipe = urb->pipe;
- unsigned char *data;
-
- /*
- * The check to see if it's safe to poke at data has an enormous
- * number of corner cases, but it seems that the following is
- * more or less safe.
- *
- * We do not even try to look transfer_buffer, because it can
- * contain non-NULL garbage in case the upper level promised to
- * set DMA for the HCD.
- */
- if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
- return 'D';
if (len <= 0)
return 'L';
-
- if ((data = urb->transfer_buffer) == NULL)
- return 'Z'; /* '0' would be not as pretty. */
+ if (len >= DATA_MAX)
+ len = DATA_MAX;
/*
* Bulk is easy to shortcut reliably.
@@ -126,8 +112,21 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
}
}
- if (len >= DATA_MAX)
- len = DATA_MAX;
+ /*
+ * The check to see if it's safe to poke at data has an enormous
+ * number of corner cases, but it seems that the following is
+ * more or less safe.
+ *
+ * We do not even try to look transfer_buffer, because it can
+ * contain non-NULL garbage in case the upper level promised to
+ * set DMA for the HCD.
+ */
+ if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+ return mon_dmapeek(ep->data, urb->transfer_dma, len);
+
+ if (urb->transfer_buffer == NULL)
+ return 'Z'; /* '0' would be not as pretty. */
+
memcpy(ep->data, urb->transfer_buffer, len);
return 0;
}
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 9b06784d2c48..4be0f9346071 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -45,6 +45,10 @@ struct mon_reader {
void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r);
void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
+/*
+ */
+extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
+
extern struct semaphore mon_lock;
extern struct file_operations mon_fops_text;
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index b104430e2c6a..8c010bb44eb8 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -99,7 +99,7 @@ config USB_USBNET
with "minidrivers" built around a common network driver core
that supports deep queues for efficient transfers. (This gives
better performance with small packets and at high speeds).
-
+
The USB host runs "usbnet", and the other end of the link might be:
- Another USB host, when using USB "network" or "data transfer"
@@ -125,38 +125,63 @@ config USB_USBNET
To compile this driver as a module, choose M here: the
module will be called usbnet.
-comment "USB Host-to-Host Cables"
- depends on USB_USBNET
-
-config USB_ALI_M5632
- boolean "ALi M5632 based 'USB 2.0 Data Link' cables"
- depends on USB_USBNET
+config USB_NET_AX8817X
+ tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
+ depends on USB_USBNET && NET_ETHERNET
+ select CRC32
+ select MII
default y
help
- Choose this option if you're using a host-to-host cable
- based on this design, which supports USB 2.0 high speed.
+ This option adds support for ASIX AX88xxx based USB 2.0
+ 10/100 Ethernet adapters.
-config USB_AN2720
- boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
- depends on USB_USBNET
- default y
- help
- Choose this option if you're using a host-to-host cable
- based on this design. Note that AnchorChips is now a
- Cypress brand.
+ This driver should work with at least the following devices:
+ * Aten UC210T
+ * ASIX AX88172
+ * Billionton Systems, USB2AR
+ * Buffalo LUA-U2-KTX
+ * Corega FEther USB2-TX
+ * D-Link DUB-E100
+ * Hawking UF200
+ * Linksys USB200M
+ * Netgear FA120
+ * Sitecom LN-029
+ * Intellinet USB 2.0 Ethernet
+ * ST Lab USB 2.0 Ethernet
+ * TrendNet TU2-ET100
-config USB_BELKIN
- boolean "eTEK based host-to-host cables (Advance, Belkin, ...)"
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use.
+
+
+config USB_NET_CDCETHER
+ tristate "CDC Ethernet support (smart devices such as cable modems)"
depends on USB_USBNET
default y
help
- Choose this option if you're using a host-to-host cable
- based on this design: two NetChip 2890 chips and an Atmel
- microcontroller, with LEDs that indicate traffic.
+ This option supports devices conforming to the Communication Device
+ Class (CDC) Ethernet Control Model, a specification that's easy to
+ implement in device firmware. The CDC specifications are available
+ from <http://www.usb.org/>.
-config USB_GENESYS
- boolean "GeneSys GL620USB-A based cables"
- default y
+ CDC Ethernet is an implementation option for DOCSIS cable modems
+ that support USB connectivity, used for non-Microsoft USB hosts.
+ The Linux-USB CDC Ethernet Gadget driver is an open implementation.
+ This driver should work with at least the following devices:
+
+ * Ericsson PipeRider (all variants)
+ * Motorola (DM100 and SB4100)
+ * Broadcom Cable Modem (reference design)
+ * Toshiba PCX1100U
+ * ...
+
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use. However, if the
+ IEEE 802 "local assignment" bit is set in the address, a "usbX"
+ name is used instead.
+
+config USB_NET_GL620A
+ tristate "GeneSys GL620USB-A based cables"
depends on USB_USBNET
help
Choose this option if you're using a host-to-host cable,
@@ -164,38 +189,78 @@ config USB_GENESYS
Note that the half-duplex "GL620USB" is not supported.
-config USB_NET1080
- boolean "NetChip 1080 based cables (Laplink, ...)"
+config USB_NET_NET1080
+ tristate "NetChip 1080 based cables (Laplink, ...)"
default y
depends on USB_USBNET
help
Choose this option if you're using a host-to-host cable based
- on this design: one NetChip 1080 chips and supporting logic,
- supporting LEDs that indicate traffic
+ on this design: one NetChip 1080 chip and supporting logic,
+ optionally with LEDs that indicate traffic
-config USB_PL2301
- boolean "Prolific PL-2301/2302 based cables"
- default y
- # handshake/init/reset problems, from original 'plusb' driver
+config USB_NET_PLUSB
+ tristate "Prolific PL-2301/2302 based cables"
+ # if the handshake/init/reset problems, from original 'plusb',
+ # are ever resolved ... then remove "experimental"
depends on USB_USBNET && EXPERIMENTAL
help
Choose this option if you're using a host-to-host cable
with one of these chips.
-config USB_KC2190
- boolean "KT Technology KC2190 based cables (InstaNet)"
- default y
+config USB_NET_RNDIS_HOST
+ tristate "Host for RNDIS devices (EXPERIMENTAL)"
depends on USB_USBNET && EXPERIMENTAL
+ select USB_NET_CDCETHER
help
- Choose this option if you're using a host-to-host cable
- with one of these chips.
+ This option enables hosting "Remote NDIS" USB networking links,
+ as encouraged by Microsoft (instead of CDC Ethernet!) for use in
+ various devices that may only support this protocol.
-comment "Intelligent USB Devices/Gadgets"
+ Avoid using this protocol unless you have no better options.
+ The protocol specification is incomplete, and is controlled by
+ (and for) Microsoft; it isn't an "Open" ecosystem or market.
+
+config USB_NET_CDC_SUBSET
+ tristate "Simple USB Network Links (CDC Ethernet subset)"
depends on USB_USBNET
+ help
+ This driver module supports USB network devices that can work
+ without any device-specific information. Select it if you have
+ one of these drivers.
+
+ Note that while many USB host-to-host cables can work in this mode,
+ that may mean not being able to talk to Win32 systems or more
+ commonly not being able to handle certain events (like replugging
+ the host on the other end) very well. Also, these devices will
+ not generally have permanently assigned Ethernet addresses.
+
+config USB_ALI_M5632
+ boolean "ALi M5632 based 'USB 2.0 Data Link' cables"
+ depends on USB_NET_CDC_SUBSET
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design, which supports USB 2.0 high speed.
+
+config USB_AN2720
+ boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
+ depends on USB_NET_CDC_SUBSET
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design. Note that AnchorChips is now a
+ Cypress brand.
+
+config USB_BELKIN
+ boolean "eTEK based host-to-host cables (Advance, Belkin, ...)"
+ depends on USB_NET_CDC_SUBSET
+ default y
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design: two NetChip 2890 chips and an Atmel
+ microcontroller, with LEDs that indicate traffic.
config USB_ARMLINUX
boolean "Embedded ARM Linux links (iPaq, ...)"
- depends on USB_USBNET
+ depends on USB_NET_CDC_SUBSET
default y
help
Choose this option to support the "usb-eth" networking driver
@@ -212,15 +277,15 @@ config USB_ARMLINUX
config USB_EPSON2888
boolean "Epson 2888 based firmware (DEVELOPMENT)"
- depends on USB_USBNET
- default y
+ depends on USB_NET_CDC_SUBSET
help
Choose this option to support the usb networking links used
by some sample firmware from Epson.
-config USB_ZAURUS
- boolean "Sharp Zaurus (stock ROMs) and compatible"
+config USB_NET_ZAURUS
+ tristate "Sharp Zaurus (stock ROMs) and compatible"
depends on USB_USBNET
+ select USB_NET_CDCETHER
select CRC32
default y
help
@@ -235,61 +300,6 @@ config USB_ZAURUS
really need this non-conformant variant of CDC Ethernet (or in
some cases CDC MDLM) protocol, not "g_ether".
-config USB_CDCETHER
- boolean "CDC Ethernet support (smart devices such as cable modems)"
- depends on USB_USBNET
- default y
- help
- This option supports devices conforming to the Communication Device
- Class (CDC) Ethernet Control Model, a specification that's easy to
- implement in device firmware. The CDC specifications are available
- from <http://www.usb.org/>.
-
- CDC Ethernet is an implementation option for DOCSIS cable modems
- that support USB connectivity, used for non-Microsoft USB hosts.
- This driver should work with at least the following devices:
-
- * Ericsson PipeRider (all variants)
- * Motorola (DM100 and SB4100)
- * Broadcom Cable Modem (reference design)
- * Toshiba PCX1100U
- * ...
-
- This driver creates an interface named "ethX", where X depends on
- what other networking devices you have in use. However, if the
- IEEE 802 "local assignment" bit is set in the address, a "usbX"
- name is used instead.
-
-comment "USB Network Adapters"
- depends on USB_USBNET
-
-config USB_AX8817X
- boolean "ASIX AX88xxx Based USB 2.0 Ethernet Devices"
- depends on USB_USBNET && NET_ETHERNET
- select CRC32
- select MII
- default y
- help
- This option adds support for ASIX AX88xxx based USB 2.0
- 10/100 Ethernet devices.
-
- This driver should work with at least the following devices:
- * Aten UC210T
- * ASIX AX88172
- * Billionton Systems, USB2AR
- * Buffalo LUA-U2-KTX
- * Corega FEther USB2-TX
- * D-Link DUB-E100
- * Hawking UF200
- * Linksys USB200M
- * Netgear FA120
- * Sitecom LN-029
- * Intellinet USB 2.0 Ethernet
- * ST Lab USB 2.0 Ethernet
- * TrendNet TU2-ET100
-
- This driver creates an interface named "ethX", where X depends on
- what other networking devices you have in use.
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 16f352195512..222c0495f791 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -6,7 +6,13 @@ obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_RTL8150) += rtl8150.o
+obj-$(CONFIG_USB_NET_AX8817X) += asix.o
+obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
+obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
+obj-$(CONFIG_USB_NET_NET1080) += net1080.o
+obj-$(CONFIG_USB_NET_PLUSB) += plusb.o
+obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o
+obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o
+obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
-
-CFLAGS_zd1201.o = -Idrivers/net/wireless/
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
new file mode 100644
index 000000000000..861f00a43750
--- /dev/null
+++ b/drivers/usb/net/asix.c
@@ -0,0 +1,948 @@
+/*
+ * ASIX AX8817X based USB 2.0 Ethernet Devices
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (c) 2002-2003 TiVo Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+
+#include "usbnet.h"
+
+
+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
+
+#define AX_CMD_SET_SW_MII 0x06
+#define AX_CMD_READ_MII_REG 0x07
+#define AX_CMD_WRITE_MII_REG 0x08
+#define AX_CMD_SET_HW_MII 0x0a
+#define AX_CMD_READ_EEPROM 0x0b
+#define AX_CMD_WRITE_EEPROM 0x0c
+#define AX_CMD_WRITE_ENABLE 0x0d
+#define AX_CMD_WRITE_DISABLE 0x0e
+#define AX_CMD_WRITE_RX_CTL 0x10
+#define AX_CMD_READ_IPG012 0x11
+#define AX_CMD_WRITE_IPG0 0x12
+#define AX_CMD_WRITE_IPG1 0x13
+#define AX_CMD_WRITE_IPG2 0x14
+#define AX_CMD_WRITE_MULTI_FILTER 0x16
+#define AX_CMD_READ_NODE_ID 0x17
+#define AX_CMD_READ_PHY_ID 0x19
+#define AX_CMD_READ_MEDIUM_STATUS 0x1a
+#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
+#define AX_CMD_READ_MONITOR_MODE 0x1c
+#define AX_CMD_WRITE_MONITOR_MODE 0x1d
+#define AX_CMD_WRITE_GPIOS 0x1f
+#define AX_CMD_SW_RESET 0x20
+#define AX_CMD_SW_PHY_STATUS 0x21
+#define AX_CMD_SW_PHY_SELECT 0x22
+#define AX88772_CMD_READ_NODE_ID 0x13
+
+#define AX_MONITOR_MODE 0x01
+#define AX_MONITOR_LINK 0x02
+#define AX_MONITOR_MAGIC 0x04
+#define AX_MONITOR_HSFS 0x10
+
+/* AX88172 Medium Status Register values */
+#define AX_MEDIUM_FULL_DUPLEX 0x02
+#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
+#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
+
+#define AX_MCAST_FILTER_SIZE 8
+#define AX_MAX_MCAST 64
+
+#define AX_EEPROM_LEN 0x40
+
+#define AX_SWRESET_CLEAR 0x00
+#define AX_SWRESET_RR 0x01
+#define AX_SWRESET_RT 0x02
+#define AX_SWRESET_PRTE 0x04
+#define AX_SWRESET_PRL 0x08
+#define AX_SWRESET_BZ 0x10
+#define AX_SWRESET_IPRL 0x20
+#define AX_SWRESET_IPPD 0x40
+
+#define AX88772_IPG0_DEFAULT 0x15
+#define AX88772_IPG1_DEFAULT 0x0c
+#define AX88772_IPG2_DEFAULT 0x12
+
+#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
+#define AX88772_MEDIUM_RESERVED 0x0004
+#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
+#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
+#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
+#define AX88772_MEDIUM_RX_ENABLE 0x0100
+#define AX88772_MEDIUM_100MB 0x0200
+#define AX88772_MEDIUM_DEFAULT \
+ (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
+ AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
+ AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+
+#define AX_EEPROM_MAGIC 0xdeadbeef
+
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
+struct ax8817x_data {
+ u8 multi_filter[AX_MCAST_FILTER_SIZE];
+};
+
+struct ax88172_int_data {
+ u16 res1;
+ u8 link;
+ u16 res2;
+ u8 status;
+ u16 res3;
+} __attribute__ ((packed));
+
+static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ return usb_control_msg(
+ dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ cmd,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ index,
+ data,
+ size,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ return usb_control_msg(
+ dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ cmd,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ index,
+ data,
+ size,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static void ax8817x_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",
+ urb->status);
+
+ kfree(req);
+ usb_free_urb(urb);
+}
+
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+{
+ struct ax88172_int_data *event;
+ int link;
+
+ if (urb->actual_length < 8)
+ return;
+
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link) {
+ netif_carrier_on(dev->net);
+ usbnet_defer_kevent (dev, EVENT_LINK_RESET );
+ } else
+ netif_carrier_off(dev->net);
+ devdbg(dev, "ax8817x - Link Status is: %d", link);
+ }
+}
+
+static void
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ struct usb_ctrlrequest *req;
+ int status;
+ struct urb *urb;
+
+ if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+ devdbg(dev, "Error allocating URB in write_cmd_async!");
+ return;
+ }
+
+ if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+ deverr(dev, "Failed to allocate memory for control request");
+ usb_free_urb(urb);
+ return;
+ }
+
+ req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+ req->bRequest = cmd;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
+
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (void *)req, data, size,
+ ax8817x_async_cmd_callback, req);
+
+ if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ deverr(dev, "Error submitting the control message: status=%d",
+ status);
+ kfree(req);
+ usb_free_urb(urb);
+ }
+}
+
+static void ax8817x_set_multicast(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ u8 rx_ctl = 0x8c;
+
+ if (net->flags & IFF_PROMISC) {
+ rx_ctl |= 0x01;
+ } else if (net->flags & IFF_ALLMULTI
+ || net->mc_count > AX_MAX_MCAST) {
+ rx_ctl |= 0x02;
+ } else if (net->mc_count == 0) {
+ /* just broadcast and directed */
+ } else {
+ /* We use the 20 byte dev->data
+ * for our 8 byte filter buffer
+ * to avoid allocating memory that
+ * is tricky to free later */
+ struct dev_mc_list *mc_list = net->mc_list;
+ u32 crc_bits;
+ int i;
+
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+ /* Build the multicast hash filter. */
+ for (i = 0; i < net->mc_count; i++) {
+ crc_bits =
+ ether_crc(ETH_ALEN,
+ mc_list->dmi_addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ mc_list = mc_list->next;
+ }
+
+ ax8817x_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);
+}
+
+static int ax8817x_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,
+ (__u16)loc, 2, (u16 *)&res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+
+ 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)
+{
+ return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+}
+
+static void
+ax8817x_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,
+ (__u16)loc, 2, (u16 *)&res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+}
+
+/* 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)
+{
+ ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+ u16 lpa;
+ u16 adv;
+ u16 res;
+ 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);
+ 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);
+
+ return 0;
+}
+
+static void
+ax8817x_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) {
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
+ return;
+ }
+ wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
+ wolinfo->wolopts = 0;
+ if (opt & AX_MONITOR_MODE) {
+ if (opt & AX_MONITOR_LINK)
+ wolinfo->wolopts |= WAKE_PHY;
+ if (opt & AX_MONITOR_MAGIC)
+ wolinfo->wolopts |= WAKE_MAGIC;
+ }
+}
+
+static int
+ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ u8 opt = 0;
+ u8 buf[1];
+
+ if (wolinfo->wolopts & WAKE_PHY)
+ opt |= AX_MONITOR_LINK;
+ if (wolinfo->wolopts & WAKE_MAGIC)
+ opt |= AX_MONITOR_MAGIC;
+ if (opt != 0)
+ opt |= AX_MONITOR_MODE;
+
+ if (ax8817x_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)
+{
+ return AX_EEPROM_LEN;
+}
+
+static int ax8817x_get_eeprom(struct net_device *net,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct usbnet *dev = netdev_priv(net);
+ u16 *ebuf = (u16 *)data;
+ int i;
+
+ /* Crude hack to ensure that we don't overwrite memory
+ * if an odd length is supplied
+ */
+ if (eeprom->len % 2)
+ return -EINVAL;
+
+ eeprom->magic = AX_EEPROM_MAGIC;
+
+ /* 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,
+ eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void ax8817x_get_drvinfo (struct net_device *net,
+ struct ethtool_drvinfo *info)
+{
+ /* Inherit standard device info */
+ usbnet_get_drvinfo(net, info);
+ info->eedump_len = 0x3e;
+}
+
+static int ax8817x_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)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return mii_ethtool_sset(&dev->mii,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,
+ .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,
+};
+
+static int ax8817x_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)
+{
+ int ret = 0;
+ void *buf;
+ int i;
+ unsigned long gpio_bits = dev->driver_info->data;
+
+ usbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* 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,
+ (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);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_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.phy_id_mask = 0x3f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = *((u8 *)buf + 1);
+ dev->net->do_ioctl = ax8817x_ioctl;
+
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->ethtool_ops = &ax8817x_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,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ mii_nway_restart(&dev->mii);
+
+ return 0;
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static struct ethtool_ops ax88772_ethtool_ops = {
+ .get_drvinfo = ax8817x_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,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ void *buf;
+
+ usbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ dbg ("Cannot allocate memory for buffer");
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ if ((ret = ax8817x_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,
+ 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);
+ 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);
+ 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);
+ 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);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_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);
+ goto out2;
+ }
+
+ if (((ret = ax8817x_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);
+ 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.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+ dev->net->do_ioctl = ax8817x_ioctl;
+
+ /* 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);
+ 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);
+ goto out2;
+ }
+ msleep(150);
+
+
+ dev->net->set_multicast_list = ax8817x_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,
+ ADVERTISE_ALL | ADVERTISE_CSMA);
+ mii_nway_restart(&dev->mii);
+
+ if ((ret = ax8817x_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,
+ 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);
+ 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);
+ goto out2;
+ }
+
+ kfree(buf);
+
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+ /* hard_mtu is still the default - the device does not support
+ jumbo eth frames */
+ dev->rx_urb_size = 2048;
+ }
+
+ return 0;
+
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ u8 *head;
+ u32 header;
+ char *packet;
+ struct sk_buff *ax_skb;
+ u16 size;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
+
+ skb_pull(skb, 4);
+
+ while (skb->len > 0) {
+ if ((short)(header & 0x0000ffff) !=
+ ~((short)((header & 0xffff0000) >> 16))) {
+ devdbg(dev,"header length data is error");
+ }
+ /* get the packet length */
+ size = (u16) (header & 0x0000ffff);
+
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+ return 2;
+ if (size > ETH_FRAME_LEN) {
+ devdbg(dev,"invalid rx length %d", size);
+ return 0;
+ }
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (ax_skb) {
+ ax_skb->len = size;
+ ax_skb->data = packet;
+ ax_skb->tail = packet + size;
+ usbnet_skb_return(dev, ax_skb);
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, (size + 1) & 0xfffe);
+
+ if (skb->len == 0)
+ break;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
+ skb_pull(skb, 4);
+ }
+
+ if (skb->len < 0) {
+ devdbg(dev,"invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ unsigned flags)
+{
+ int padlen;
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+ u32 packet_len;
+ u32 padbytes = 0xffff0000;
+
+ padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (4 + padlen))) {
+ if ((headroom < 4) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ skb_push(skb, 4);
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
+
+ if ((skb->len % 512) == 0) {
+ memcpy( skb->tail, &padbytes, sizeof(padbytes));
+ skb_put(skb, sizeof(padbytes));
+ }
+ return skb;
+}
+
+static int ax88772_link_reset(struct usbnet *dev)
+{
+ u16 lpa;
+ u16 adv;
+ u16 res;
+ 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);
+ 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);
+
+ return 0;
+}
+
+static const struct driver_info ax8817x_info = {
+ .description = "ASIX AX8817x USB 2.0 Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x00130103,
+};
+
+static const struct driver_info dlink_dub_e100_info = {
+ .description = "DLink DUB-E100 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x009f9d9f,
+};
+
+static const struct driver_info netgear_fa120_info = {
+ .description = "Netgear FA-120 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x00130103,
+};
+
+static const struct driver_info hawking_uf200_info = {
+ .description = "Hawking UF200 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x001f1d1f,
+};
+
+static const struct driver_info ax88772_info = {
+ .description = "ASIX AX88772 USB 2.0 Ethernet",
+ .bind = ax88772_bind,
+ .status = ax8817x_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 [] = {
+{
+ // Linksys USB200M
+ USB_DEVICE (0x077b, 0x2226),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Netgear FA120
+ USB_DEVICE (0x0846, 0x1040),
+ .driver_info = (unsigned long) &netgear_fa120_info,
+}, {
+ // DLink DUB-E100
+ USB_DEVICE (0x2001, 0x1a00),
+ .driver_info = (unsigned long) &dlink_dub_e100_info,
+}, {
+ // Intellinet, ST Lab USB Ethernet
+ USB_DEVICE (0x0b95, 0x1720),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Hawking UF200, TrendNet TU2-ET100
+ USB_DEVICE (0x07b8, 0x420a),
+ .driver_info = (unsigned long) &hawking_uf200_info,
+}, {
+ // Billionton Systems, USB2AR
+ USB_DEVICE (0x08dd, 0x90ff),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // ATEN UC210T
+ USB_DEVICE (0x0557, 0x2009),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Buffalo LUA-U2-KTX
+ USB_DEVICE (0x0411, 0x003d),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
+ USB_DEVICE (0x6189, 0x182d),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // corega FEther USB2-TX
+ USB_DEVICE (0x07aa, 0x0017),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Surecom EP-1427X-2
+ USB_DEVICE (0x1189, 0x0893),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // goodway corp usb gwusb2e
+ USB_DEVICE (0x1631, 0x6200),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // ASIX AX88772 10/100
+ USB_DEVICE (0x0b95, 0x7720),
+ .driver_info = (unsigned long) &ax88772_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver asix_driver = {
+ .owner = THIS_MODULE,
+ .name = "asix",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disconnect = usbnet_disconnect,
+};
+
+static int __init asix_init(void)
+{
+ return usb_register(&asix_driver);
+}
+module_init(asix_init);
+
+static void __exit asix_exit(void)
+{
+ usb_deregister(&asix_driver);
+}
+module_exit(asix_exit);
+
+MODULE_AUTHOR("David Hollis");
+MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index c8be912f24e1..37ef365a2472 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -383,7 +383,6 @@ static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
if (urb->status == -ECONNRESET) {
dbg("Tx Reset.");
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
urb->status = 0;
catc->netdev->trans_start = jiffies;
catc->stats.tx_errors++;
@@ -445,7 +444,6 @@ static void catc_tx_timeout(struct net_device *netdev)
struct catc *catc = netdev_priv(netdev);
warn("Transmit timed out.");
- catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(catc->tx_urb);
}
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
new file mode 100644
index 000000000000..652b04bbf6af
--- /dev/null
+++ b/drivers/usb/net/cdc_ether.c
@@ -0,0 +1,509 @@
+/*
+ * CDC Ethernet based networking peripherals
+ * Copyright (C) 2003-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * probes control interface, claims data interface, collects the bulk
+ * endpoints, activates data interface (if needed), maybe sets MTU.
+ * all pure cdc, except for certain firmware workarounds, and knowing
+ * that rndis uses one different rule.
+ */
+int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ u8 *buf = intf->cur_altsetting->extra;
+ int len = intf->cur_altsetting->extralen;
+ struct usb_interface_descriptor *d;
+ struct cdc_state *info = (void *) &dev->data;
+ int status;
+ int rndis;
+ struct usb_driver *driver = driver_of(intf);
+
+ if (sizeof dev->data < sizeof *info)
+ return -EDOM;
+
+ /* expect strict spec conformance for the descriptors, but
+ * cope with firmware which stores them in the wrong place
+ */
+ if (len == 0 && dev->udev->actconfig->extralen) {
+ /* Motorola SB4100 (and others: Brad Hards says it's
+ * from a Broadcom design) put CDC descriptors here
+ */
+ buf = dev->udev->actconfig->extra;
+ len = dev->udev->actconfig->extralen;
+ if (len)
+ dev_dbg(&intf->dev,
+ "CDC descriptors on config\n");
+ }
+
+ /* this assumes that if there's a non-RNDIS vendor variant
+ * of cdc-acm, it'll fail RNDIS requests cleanly.
+ */
+ rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
+
+ memset(info, 0, sizeof *info);
+ info->control = intf;
+ while (len > 3) {
+ if (buf [1] != USB_DT_CS_INTERFACE)
+ goto next_desc;
+
+ /* use bDescriptorSubType to identify the CDC descriptors.
+ * We expect devices with CDC header and union descriptors.
+ * For CDC Ethernet we need the ethernet descriptor.
+ * For RNDIS, ignore two (pointless) CDC modem descriptors
+ * in favor of a complicated OID-based RPC scheme doing what
+ * CDC Ethernet achieves with a simple descriptor.
+ */
+ switch (buf [2]) {
+ case USB_CDC_HEADER_TYPE:
+ if (info->header) {
+ dev_dbg(&intf->dev, "extra CDC header\n");
+ goto bad_desc;
+ }
+ info->header = (void *) buf;
+ if (info->header->bLength != sizeof *info->header) {
+ dev_dbg(&intf->dev, "CDC header len %u\n",
+ info->header->bLength);
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_UNION_TYPE:
+ if (info->u) {
+ dev_dbg(&intf->dev, "extra CDC union\n");
+ goto bad_desc;
+ }
+ info->u = (void *) buf;
+ if (info->u->bLength != sizeof *info->u) {
+ dev_dbg(&intf->dev, "CDC union len %u\n",
+ info->u->bLength);
+ goto bad_desc;
+ }
+
+ /* we need a master/control interface (what we're
+ * probed with) and a slave/data interface; union
+ * descriptors sort this all out.
+ */
+ info->control = usb_ifnum_to_if(dev->udev,
+ info->u->bMasterInterface0);
+ info->data = usb_ifnum_to_if(dev->udev,
+ info->u->bSlaveInterface0);
+ if (!info->control || !info->data) {
+ dev_dbg(&intf->dev,
+ "master #%u/%p slave #%u/%p\n",
+ info->u->bMasterInterface0,
+ info->control,
+ info->u->bSlaveInterface0,
+ info->data);
+ goto bad_desc;
+ }
+ if (info->control != intf) {
+ dev_dbg(&intf->dev, "bogus CDC Union\n");
+ /* Ambit USB Cable Modem (and maybe others)
+ * interchanges master and slave interface.
+ */
+ if (info->data == intf) {
+ info->data = info->control;
+ info->control = intf;
+ } else
+ goto bad_desc;
+ }
+
+ /* a data interface altsetting does the real i/o */
+ d = &info->data->cur_altsetting->desc;
+ if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
+ dev_dbg(&intf->dev, "slave class %u\n",
+ d->bInterfaceClass);
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_ETHERNET_TYPE:
+ if (info->ether) {
+ dev_dbg(&intf->dev, "extra CDC ether\n");
+ goto bad_desc;
+ }
+ info->ether = (void *) buf;
+ if (info->ether->bLength != sizeof *info->ether) {
+ dev_dbg(&intf->dev, "CDC ether len %u\n",
+ info->ether->bLength);
+ goto bad_desc;
+ }
+ dev->hard_mtu = le16_to_cpu(
+ info->ether->wMaxSegmentSize);
+ /* because of Zaurus, we may be ignoring the host
+ * side link address we were given.
+ */
+ break;
+ }
+next_desc:
+ len -= buf [0]; /* bLength */
+ buf += buf [0];
+ }
+
+ if (!info->header || !info->u || (!rndis && !info->ether)) {
+ dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n",
+ info->header ? "" : "header ",
+ info->u ? "" : "union ",
+ info->ether ? "" : "ether ");
+ goto bad_desc;
+ }
+
+ /* claim data interface and set it up ... with side effects.
+ * network traffic can't flow until an altsetting is enabled.
+ */
+ status = usb_driver_claim_interface(driver, info->data, dev);
+ if (status < 0)
+ return status;
+ status = usbnet_get_endpoints(dev, info->data);
+ if (status < 0) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ return status;
+ }
+
+ /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+ dev->status = NULL;
+ if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+ struct usb_endpoint_descriptor *desc;
+
+ dev->status = &info->control->cur_altsetting->endpoint [0];
+ desc = &dev->status->desc;
+ if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
+ || !(desc->bEndpointAddress & USB_DIR_IN)
+ || (le16_to_cpu(desc->wMaxPacketSize)
+ < sizeof(struct usb_cdc_notification))
+ || !desc->bInterval) {
+ dev_dbg(&intf->dev, "bad notification endpoint\n");
+ dev->status = NULL;
+ }
+ }
+ if (rndis && !dev->status) {
+ dev_dbg(&intf->dev, "missing RNDIS status endpoint\n");
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ return -ENODEV;
+ }
+ return 0;
+
+bad_desc:
+ dev_info(&dev->udev->dev, "bad CDC descriptors\n");
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct cdc_state *info = (void *) &dev->data;
+ struct usb_driver *driver = driver_of(intf);
+
+ /* disconnect master --> disconnect slave */
+ if (intf == info->control && info->data) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ info->data = NULL;
+ }
+
+ /* and vice versa (just in case) */
+ else if (intf == info->data && info->control) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->control, NULL);
+ usb_driver_release_interface(driver, info->control);
+ info->control = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Communications Device Class, Ethernet Control model
+ *
+ * Takes two interfaces. The DATA interface is inactive till an altsetting
+ * is selected. Configuration data includes class descriptors. There's
+ * an optional status endpoint on the control interface.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with, with more functionality.
+ *
+ *-------------------------------------------------------------------------*/
+
+static void dumpspeed(struct usbnet *dev, __le32 *speeds)
+{
+ if (netif_msg_timer(dev))
+ devinfo(dev, "link speeds: %u kbps up, %u kbps down",
+ __le32_to_cpu(speeds[0]) / 1000,
+ __le32_to_cpu(speeds[1]) / 1000);
+}
+
+static void cdc_status(struct usbnet *dev, struct urb *urb)
+{
+ struct usb_cdc_notification *event;
+
+ if (urb->actual_length < sizeof *event)
+ return;
+
+ /* SPEED_CHANGE can get split into two 8-byte packets */
+ if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
+ dumpspeed(dev, (__le32 *) urb->transfer_buffer);
+ return;
+ }
+
+ event = urb->transfer_buffer;
+ switch (event->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ if (netif_msg_timer(dev))
+ devdbg(dev, "CDC: carrier %s",
+ event->wValue ? "on" : "off");
+ if (event->wValue)
+ netif_carrier_on(dev->net);
+ else
+ netif_carrier_off(dev->net);
+ break;
+ case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
+ if (netif_msg_timer(dev))
+ devdbg(dev, "CDC: speed change (len %d)",
+ urb->actual_length);
+ if (urb->actual_length != (sizeof *event + 8))
+ set_bit(EVENT_STS_SPLIT, &dev->flags);
+ else
+ dumpspeed(dev, (__le32 *) &event[1]);
+ break;
+ /* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS),
+ * but there are no standard formats for the response data.
+ */
+ default:
+ deverr(dev, "CDC: unexpected notification %02x!",
+ event->bNotificationType);
+ break;
+ }
+}
+
+static u8 nibble(unsigned char c)
+{
+ if (likely(isdigit(c)))
+ return c - '0';
+ c = toupper(c);
+ if (likely(isxdigit(c)))
+ return 10 + c - 'A';
+ return 0;
+}
+
+static inline int
+get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e)
+{
+ int tmp, i;
+ unsigned char buf [13];
+
+ tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf);
+ if (tmp != 12) {
+ dev_dbg(&dev->udev->dev,
+ "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp);
+ if (tmp >= 0)
+ tmp = -EINVAL;
+ return tmp;
+ }
+ for (i = tmp = 0; i < 6; i++, tmp += 2)
+ dev->net->dev_addr [i] =
+ (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]);
+ return 0;
+}
+
+static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int status;
+ struct cdc_state *info = (void *) &dev->data;
+
+ status = usbnet_generic_cdc_bind(dev, intf);
+ if (status < 0)
+ return status;
+
+ status = get_ethernet_addr(dev, info->ether);
+ if (status < 0) {
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver_of(intf), info->data);
+ return status;
+ }
+
+ /* FIXME cdc-ether has some multicast code too, though it complains
+ * in routine cases. info->ether describes the multicast support.
+ * Implement that here, manipulating the cdc filter as needed.
+ */
+ return 0;
+}
+
+static const struct driver_info cdc_info = {
+ .description = "CDC Ethernet Device",
+ .flags = FLAG_ETHER,
+ // .check_connect = cdc_check_connect,
+ .bind = cdc_bind,
+ .unbind = usbnet_cdc_unbind,
+ .status = cdc_status,
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+static const struct usb_device_id products [] = {
+/*
+ * BLACKLIST !!
+ *
+ * First blacklist any products that are egregiously nonconformant
+ * with the CDC Ethernet specs. Minor braindamage we cope with; when
+ * they're not even trying, needing a separate driver is only the first
+ * of the differences to show up.
+ */
+
+#define ZAURUS_MASTER_INTERFACE \
+ .bInterfaceClass = USB_CLASS_COMM, \
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+/* SA-1100 based Sharp Zaurus ("collie"), or compatible;
+ * wire-incompatible with true CDC Ethernet implementations.
+ * (And, it seems, needlessly so...)
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8004,
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+},
+
+/* PXA-25x based Sharp Zaurii. Note that it seems some of these
+ * (later models especially) may have shipped only with firmware
+ * advertising false "CDC MDLM" compatibility ... but we're not
+ * clear which models did that, so for now let's assume the worst.
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9031, /* C-750 C-760 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9032, /* SL-6000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9050, /* C-860 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+},
+
+/*
+ * WHITELIST!!!
+ *
+ * CDC Ether uses two interfaces, not necessarily consecutive.
+ * We match the main interface, ignoring the optional device
+ * class so we could handle devices that aren't exclusively
+ * CDC ether.
+ *
+ * NOTE: this match must come AFTER entries blacklisting devices
+ * because of bugs/quirks in a given product (like Zaurus, above).
+ */
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver cdc_driver = {
+ .owner = THIS_MODULE,
+ .name = "cdc_ether",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+
+static int __init cdc_init(void)
+{
+ BUG_ON((sizeof(((struct usbnet *)0)->data)
+ < sizeof(struct cdc_state)));
+
+ return usb_register(&cdc_driver);
+}
+module_init(cdc_init);
+
+static void __exit cdc_exit(void)
+{
+ usb_deregister(&cdc_driver);
+}
+module_exit(cdc_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB CDC Ethernet devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
new file mode 100644
index 000000000000..f1730b685fd2
--- /dev/null
+++ b/drivers/usb/net/cdc_subset.c
@@ -0,0 +1,335 @@
+/*
+ * Simple "CDC Subset" USB Networking Links
+ * Copyright (C) 2000-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * This supports simple USB network links that don't require any special
+ * framing or hardware control operations. The protocol used here is a
+ * strict subset of CDC Ethernet, with three basic differences reflecting
+ * the goal that almost any hardware should run it:
+ *
+ * - Minimal runtime control: one interface, no altsettings, and
+ * no vendor or class specific control requests. If a device is
+ * configured, it is allowed to exchange packets with the host.
+ * Fancier models would mean not working on some hardware.
+ *
+ * - Minimal manufacturing control: no IEEE "Organizationally
+ * Unique ID" required, or an EEPROMs to store one. Each host uses
+ * one random "locally assigned" Ethernet address instead, which can
+ * of course be overridden using standard tools like "ifconfig".
+ * (With 2^46 such addresses, same-net collisions are quite rare.)
+ *
+ * - There is no additional framing data for USB. Packets are written
+ * exactly as in CDC Ethernet, starting with an Ethernet header and
+ * terminated by a short packet. However, the host will never send a
+ * zero length packet; some systems can't handle those robustly.
+ *
+ * Anything that can transmit and receive USB bulk packets can implement
+ * this protocol. That includes both smart peripherals and quite a lot
+ * of "host-to-host" USB cables (which embed two devices back-to-back).
+ *
+ * Note that although Linux may use many of those host-to-host links
+ * with this "cdc_subset" framing, that doesn't mean there may not be a
+ * better approach. Handling the "other end unplugs/replugs" scenario
+ * well tends to require chip-specific vendor requests. Also, Windows
+ * peers at the other end of host-to-host cables may expect their own
+ * framing to be used rather than this "cdc_subset" model.
+ */
+
+#if defined(CONFIG_USB_EPSON2888) || defined(CONFIG_USB_ARMLINUX)
+/* PDA style devices are always connected if present */
+static int always_connected (struct usbnet *dev)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_USB_ALI_M5632
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * ALi M5632 driver ... does high speed
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info ali_m5632_info = {
+ .description = "ALi M5632",
+};
+
+
+#endif
+
+
+#ifdef CONFIG_USB_AN2720
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * AnchorChips 2720 driver ... http://www.cypress.com
+ *
+ * This doesn't seem to have a way to detect whether the peer is
+ * connected, or need any reset handshaking. It's got pretty big
+ * internal buffers (handles most of a frame's worth of data).
+ * Chip data sheets don't describe any vendor control messages.
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info an2720_info = {
+ .description = "AnchorChips/Cypress 2720",
+ // no reset available!
+ // no check_connect available!
+
+ .in = 2, .out = 2, // direction distinguishes these
+};
+
+#endif /* CONFIG_USB_AN2720 */
+
+
+#ifdef CONFIG_USB_BELKIN
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * Belkin F5U104 ... two NetChip 2280 devices + Atmel AVR microcontroller
+ *
+ * ... also two eTEK designs, including one sold as "Advance USBNET"
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info belkin_info = {
+ .description = "Belkin, eTEK, or compatible",
+};
+
+#endif /* CONFIG_USB_BELKIN */
+
+
+
+#ifdef CONFIG_USB_EPSON2888
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * EPSON USB clients
+ *
+ * This is the same idea as Linux PDAs (below) except the firmware in the
+ * device might not be Tux-powered. Epson provides reference firmware that
+ * implements this interface. Product developers can reuse or modify that
+ * code, such as by using their own product and vendor codes.
+ *
+ * Support was from Juro Bystricky <bystricky.juro@erd.epson.com>
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info epson2888_info = {
+ .description = "Epson USB Device",
+ .check_connect = always_connected,
+
+ .in = 4, .out = 3,
+};
+
+#endif /* CONFIG_USB_EPSON2888 */
+
+
+#ifdef CONFIG_USB_KC2190
+#define HAVE_HARDWARE
+static const struct driver_info kc2190_info = {
+ .description = "KC Technology KC-190",
+};
+#endif /* CONFIG_USB_KC2190 */
+
+
+#ifdef CONFIG_USB_ARMLINUX
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * Intel's SA-1100 chip integrates basic USB support, and is used
+ * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more.
+ * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to
+ * network using minimal USB framing data.
+ *
+ * This describes the driver currently in standard ARM Linux kernels.
+ * The Zaurus uses a different driver (see later).
+ *
+ * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support
+ * and different USB endpoint numbering than the SA1100 devices. The
+ * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100
+ * so we rely on the endpoint descriptors.
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info linuxdev_info = {
+ .description = "Linux Device",
+ .check_connect = always_connected,
+};
+
+static const struct driver_info yopy_info = {
+ .description = "Yopy",
+ .check_connect = always_connected,
+};
+
+static const struct driver_info blob_info = {
+ .description = "Boot Loader OBject",
+ .check_connect = always_connected,
+};
+
+#endif /* CONFIG_USB_ARMLINUX */
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef HAVE_HARDWARE
+#error You need to configure some hardware for this driver
+#endif
+
+/*
+ * chip vendor names won't normally be on the cables, and
+ * may not be on the device.
+ */
+
+static const struct usb_device_id products [] = {
+
+#ifdef CONFIG_USB_ALI_M5632
+{
+ USB_DEVICE (0x0402, 0x5632), // ALi defaults
+ .driver_info = (unsigned long) &ali_m5632_info,
+},
+#endif
+
+#ifdef CONFIG_USB_AN2720
+{
+ USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
+ .driver_info = (unsigned long) &an2720_info,
+}, {
+ USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
+ .driver_info = (unsigned long) &an2720_info,
+},
+#endif
+
+#ifdef CONFIG_USB_BELKIN
+{
+ USB_DEVICE (0x050d, 0x0004), // Belkin
+ .driver_info = (unsigned long) &belkin_info,
+}, {
+ USB_DEVICE (0x056c, 0x8100), // eTEK
+ .driver_info = (unsigned long) &belkin_info,
+}, {
+ USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK)
+ .driver_info = (unsigned long) &belkin_info,
+},
+#endif
+
+#ifdef CONFIG_USB_EPSON2888
+{
+ USB_DEVICE (0x0525, 0x2888), // EPSON USB client
+ .driver_info = (unsigned long) &epson2888_info,
+},
+#endif
+
+#ifdef CONFIG_USB_KC2190
+{
+ USB_DEVICE (0x050f, 0x0190), // KC-190
+ .driver_info = (unsigned long) &kc2190_info,
+},
+#endif
+
+#ifdef CONFIG_USB_ARMLINUX
+/*
+ * SA-1100 using standard ARM Linux kernels, or compatible.
+ * Often used when talking to Linux PDAs (iPaq, Yopy, etc).
+ * The sa-1100 "usb-eth" driver handles the basic framing.
+ *
+ * PXA25x or PXA210 ... these use a "usb-eth" driver much like
+ * the sa1100 one, but hardware uses different endpoint numbers.
+ *
+ * Or the Linux "Ethernet" gadget on hardware that can't talk
+ * CDC Ethernet (e.g., no altsettings), in either of two modes:
+ * - acting just like the old "usb-eth" firmware, though
+ * the implementation is different
+ * - supporting RNDIS as the first/default configuration for
+ * MS-Windows interop; Linux needs to use the other config
+ */
+{
+ // 1183 = 0x049F, both used as hex values?
+ // Compaq "Itsy" vendor/product id
+ USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible
+ .driver_info = (unsigned long) &linuxdev_info,
+}, {
+ USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy"
+ .driver_info = (unsigned long) &yopy_info,
+}, {
+ USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
+ .driver_info = (unsigned long) &blob_info,
+}, {
+ // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
+ // e.g. Gumstix, current OpenZaurus, ...
+ USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
+ .driver_info = (unsigned long) &linuxdev_info,
+},
+#endif
+
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_driver cdc_subset_driver = {
+ .owner = THIS_MODULE,
+ .name = "cdc_subset",
+ .probe = usbnet_probe,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disconnect = usbnet_disconnect,
+ .id_table = products,
+};
+
+static int __init cdc_subset_init(void)
+{
+ return usb_register(&cdc_subset_driver);
+}
+module_init(cdc_subset_init);
+
+static void __exit cdc_subset_exit(void)
+{
+ usb_deregister(&cdc_subset_driver);
+}
+module_exit(cdc_subset_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("Simple 'CDC Subset' USB networking links");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
new file mode 100644
index 000000000000..c8763ae33c73
--- /dev/null
+++ b/drivers/usb/net/gl620a.c
@@ -0,0 +1,407 @@
+/*
+ * GeneSys GL620USB-A based links
+ * Copyright (C) 2001 by Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
+ * Copyright (C) 2001 by Stanislav Brabec <utx@penguin.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ * ... should partially interop with the Win32 driver for this hardware.
+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
+ *
+ * Some info from GeneSys:
+ * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk.
+ * (Some cables, like the BAFO-100c, use the half duplex version.)
+ * - For the full duplex model, the low bit of the version code says
+ * which side is which ("left/right").
+ * - For the half duplex type, a control/interrupt handshake settles
+ * the transfer direction. (That's disabled here, partially coded.)
+ * A control URB would block until other side writes an interrupt.
+ *
+ * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
+ * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>.
+ */
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE 0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE 0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE 0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL 0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS 32
+// max packet length
+#define GL_MAX_PACKET_LEN 1514
+// max receive buffer size
+#define GL_RCV_BUF_SIZE \
+ (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_packet {
+ u32 packet_length;
+ char packet_data [1];
+};
+
+struct gl_header {
+ u32 packet_count;
+ struct gl_packet packets;
+};
+
+#ifdef GENELINK_ACK
+
+// FIXME: this code is incomplete, not debugged; it doesn't
+// handle interrupts correctly; it should use the generic
+// status IRQ code (which didn't exist back in 2001).
+
+struct gl_priv {
+ struct urb *irq_urb;
+ char irq_buf [INTERRUPT_BUFSIZE];
+};
+
+static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
+{
+ int retval;
+
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ value,
+ 0, // index
+ 0, // data buffer
+ 0, // size
+ USB_CTRL_SET_TIMEOUT);
+ return retval;
+}
+
+static void gl_interrupt_complete(struct urb *urb, struct pt_regs *regs)
+{
+ int status = urb->status;
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ }
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, status);
+}
+
+static int gl_interrupt_read(struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+ int retval;
+
+ // issue usb interrupt read
+ if (priv && priv->irq_urb) {
+ // submit urb
+ if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0)
+ dbg("gl_interrupt_read: submit fail - %X...", retval);
+ else
+ dbg("gl_interrupt_read: submit success...");
+ }
+
+ return 0;
+}
+
+// check whether another side is connected
+static int genelink_check_connect(struct usbnet *dev)
+{
+ int retval;
+
+ dbg("genelink_check_connect...");
+
+ // detect whether another side is connected
+ if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+ dbg("%s: genelink_check_connect write fail - %X",
+ dev->net->name, retval);
+ return retval;
+ }
+
+ // usb interrupt read to ack another side
+ if ((retval = gl_interrupt_read(dev)) != 0) {
+ dbg("%s: genelink_check_connect read fail - %X",
+ dev->net->name, retval);
+ return retval;
+ }
+
+ dbg("%s: genelink_check_connect read success", dev->net->name);
+ return 0;
+}
+
+// allocate and initialize the private data for genelink
+static int genelink_init(struct usbnet *dev)
+{
+ struct gl_priv *priv;
+
+ // allocate the private data structure
+ if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) {
+ dbg("%s: cannot allocate private data per device",
+ dev->net->name);
+ return -ENOMEM;
+ }
+
+ // allocate irq urb
+ if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) {
+ dbg("%s: cannot allocate private irq urb per device",
+ dev->net->name);
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ // fill irq urb
+ usb_fill_int_urb(priv->irq_urb, dev->udev,
+ usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE),
+ priv->irq_buf, INTERRUPT_BUFSIZE,
+ gl_interrupt_complete, 0,
+ GENELINK_INTERRUPT_INTERVAL);
+
+ // set private data pointer
+ dev->priv_data = priv;
+
+ return 0;
+}
+
+// release the private data
+static int genelink_free(struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+
+ if (!priv)
+ return 0;
+
+// FIXME: can't cancel here; it's synchronous, and
+// should have happened earlier in any case (interrupt
+// handling needs to be generic)
+
+ // cancel irq urb first
+ usb_kill_urb(priv->irq_urb);
+
+ // free irq urb
+ usb_free_urb(priv->irq_urb);
+
+ // free the private data structure
+ kfree(priv);
+
+ return 0;
+}
+
+#endif
+
+static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct gl_header *header;
+ struct gl_packet *packet;
+ struct sk_buff *gl_skb;
+ u32 size;
+
+ header = (struct gl_header *) skb->data;
+
+ // get the packet count of the received skb
+ le32_to_cpus(&header->packet_count);
+ if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
+ || (header->packet_count < 0)) {
+ dbg("genelink: invalid received packet count %d",
+ header->packet_count);
+ return 0;
+ }
+
+ // set the current packet pointer to the first packet
+ packet = &header->packets;
+
+ // decrement the length for the packet count size 4 bytes
+ skb_pull(skb, 4);
+
+ while (header->packet_count > 1) {
+ // get the packet length
+ size = le32_to_cpu(packet->packet_length);
+
+ // this may be a broken packet
+ if (size > GL_MAX_PACKET_LEN) {
+ dbg("genelink: invalid rx length %d", size);
+ return 0;
+ }
+
+ // allocate the skb for the individual packet
+ gl_skb = alloc_skb(size, GFP_ATOMIC);
+ if (gl_skb) {
+
+ // copy the packet data to the new skb
+ memcpy(skb_put(gl_skb, size),
+ packet->packet_data, size);
+ usbnet_skb_return(dev, gl_skb);
+ }
+
+ // advance to the next packet
+ packet = (struct gl_packet *)
+ &packet->packet_data [size];
+ header->packet_count--;
+
+ // shift the data pointer to the next gl_packet
+ skb_pull(skb, size + 4);
+ }
+
+ // skip the packet length field 4 bytes
+ skb_pull(skb, 4);
+
+ if (skb->len > GL_MAX_PACKET_LEN) {
+ dbg("genelink: invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *
+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+{
+ int padlen;
+ int length = skb->len;
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+ u32 *packet_count;
+ u32 *packet_len;
+
+ // FIXME: magic numbers, bleech
+ padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+ if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + (4 + 4*1),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ // attach the packet count to the header
+ packet_count = (u32 *) skb_push(skb, (4 + 4*1));
+ packet_len = packet_count + 1;
+
+ *packet_count = cpu_to_le32(1);
+ *packet_len = cpu_to_le32(length);
+
+ // add padding byte
+ if ((skb->len % dev->maxpacket) == 0)
+ skb_put(skb, 1);
+
+ return skb;
+}
+
+static int genelink_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ dev->hard_mtu = GL_RCV_BUF_SIZE;
+ dev->net->hard_header_len += 4;
+ dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
+ dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
+ return 0;
+}
+
+static const struct driver_info genelink_info = {
+ .description = "Genesys GeneLink",
+ .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT,
+ .bind = genelink_bind,
+ .rx_fixup = genelink_rx_fixup,
+ .tx_fixup = genelink_tx_fixup,
+
+ .in = 1, .out = 2,
+
+#ifdef GENELINK_ACK
+ .check_connect =genelink_check_connect,
+#endif
+};
+
+static const struct usb_device_id products [] = {
+
+{
+ USB_DEVICE(0x05e3, 0x0502), // GL620USB-A
+ .driver_info = (unsigned long) &genelink_info,
+},
+ /* NOT: USB_DEVICE(0x05e3, 0x0501), // GL620USB
+ * that's half duplex, not currently supported
+ */
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver gl620a_driver = {
+ .owner = THIS_MODULE,
+ .name = "gl620a",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init usbnet_init(void)
+{
+ return usb_register(&gl620a_driver);
+}
+module_init(usbnet_init);
+
+static void __exit usbnet_exit(void)
+{
+ usb_deregister(&gl620a_driver);
+}
+module_exit(usbnet_exit);
+
+MODULE_AUTHOR("Jiun-Jie Huang");
+MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 7ffa99b9760f..e04b0ce3611a 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -787,7 +787,6 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
kaweth_usb_transmit_complete,
kaweth);
kaweth->end = 0;
- kaweth->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
{
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
new file mode 100644
index 000000000000..a4309c4a491b
--- /dev/null
+++ b/drivers/usb/net/net1080.c
@@ -0,0 +1,622 @@
+/*
+ * Net1080 based USB host-to-host cables
+ * Copyright (C) 2000-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include <asm/unaligned.h>
+
+#include "usbnet.h"
+
+
+/*
+ * Netchip 1080 driver ... http://www.netchip.com
+ * (Sept 2004: End-of-life announcement has been sent.)
+ * Used in (some) LapLink cables
+ */
+
+#define frame_errors data[1]
+
+/*
+ * NetChip framing of ethernet packets, supporting additional error
+ * checks for links that may drop bulk packets from inside messages.
+ * Odd USB length == always short read for last usb packet.
+ * - nc_header
+ * - Ethernet header (14 bytes)
+ * - payload
+ * - (optional padding byte, if needed so length becomes odd)
+ * - nc_trailer
+ *
+ * This framing is to be avoided for non-NetChip devices.
+ */
+
+struct nc_header { // packed:
+ __le16 hdr_len; // sizeof nc_header (LE, all)
+ __le16 packet_len; // payload size (including ethhdr)
+ __le16 packet_id; // detects dropped packets
+#define MIN_HEADER 6
+
+ // all else is optional, and must start with:
+ // __le16 vendorId; // from usb-if
+ // __le16 productId;
+} __attribute__((__packed__));
+
+#define PAD_BYTE ((unsigned char)0xAC)
+
+struct nc_trailer {
+ __le16 packet_id;
+} __attribute__((__packed__));
+
+// packets may use FLAG_FRAMING_NC and optional pad
+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+ + sizeof (struct ethhdr) \
+ + (mtu) \
+ + 1 \
+ + sizeof (struct nc_trailer))
+
+#define MIN_FRAMED FRAMED_SIZE(0)
+
+/* packets _could_ be up to 64KB... */
+#define NC_MAX_PACKET 32767
+
+
+/*
+ * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
+ * before the hardware drops it. If that's done, the driver will need to
+ * frame network packets to guard against the dropped USB packets. The win32
+ * driver sets this for both sides of the link.
+ */
+#define NC_READ_TTL_MS ((u8)255) // ms
+
+/*
+ * We ignore most registers and EEPROM contents.
+ */
+#define REG_USBCTL ((u8)0x04)
+#define REG_TTL ((u8)0x10)
+#define REG_STATUS ((u8)0x11)
+
+/*
+ * Vendor specific requests to read/write data
+ */
+#define REQUEST_REGISTER ((u8)0x10)
+#define REQUEST_EEPROM ((u8)0x11)
+
+static int
+nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
+{
+ int status = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, regnum,
+ retval_ptr, sizeof *retval_ptr,
+ USB_CTRL_GET_TIMEOUT);
+ if (status > 0)
+ status = 0;
+ if (!status)
+ le16_to_cpus(retval_ptr);
+ return status;
+}
+
+static inline int
+nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
+{
+ return nc_vendor_read(dev, REQUEST_REGISTER, regnum, retval_ptr);
+}
+
+// no retval ... can become async, usable in_interrupt()
+static void
+nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
+{
+ usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, regnum,
+ NULL, 0, // data is in setup packet
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static inline void
+nc_register_write(struct usbnet *dev, u8 regnum, u16 value)
+{
+ nc_vendor_write(dev, REQUEST_REGISTER, regnum, value);
+}
+
+
+#if 0
+static void nc_dump_registers(struct usbnet *dev)
+{
+ u8 reg;
+ u16 *vp = kmalloc(sizeof (u16));
+
+ if (!vp) {
+ dbg("no memory?");
+ return;
+ }
+
+ dbg("%s registers:", dev->net->name);
+ for (reg = 0; reg < 0x20; reg++) {
+ int retval;
+
+ // reading some registers is trouble
+ if (reg >= 0x08 && reg <= 0xf)
+ continue;
+ if (reg >= 0x12 && reg <= 0x1e)
+ continue;
+
+ retval = nc_register_read(dev, reg, vp);
+ if (retval < 0)
+ dbg("%s reg [0x%x] ==> error %d",
+ dev->net->name, reg, retval);
+ else
+ dbg("%s reg [0x%x] = 0x%x",
+ dev->net->name, reg, *vp);
+ }
+ kfree(vp);
+}
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Control register
+ */
+
+#define USBCTL_WRITABLE_MASK 0x1f0f
+// bits 15-13 reserved, r/o
+#define USBCTL_ENABLE_LANG (1 << 12)
+#define USBCTL_ENABLE_MFGR (1 << 11)
+#define USBCTL_ENABLE_PROD (1 << 10)
+#define USBCTL_ENABLE_SERIAL (1 << 9)
+#define USBCTL_ENABLE_DEFAULTS (1 << 8)
+// bits 7-4 reserved, r/o
+#define USBCTL_FLUSH_OTHER (1 << 3)
+#define USBCTL_FLUSH_THIS (1 << 2)
+#define USBCTL_DISCONN_OTHER (1 << 1)
+#define USBCTL_DISCONN_THIS (1 << 0)
+
+static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
+{
+ if (!netif_msg_link(dev))
+ return;
+ devdbg(dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
+ " this%s%s;"
+ " other%s%s; r/o 0x%x",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ usbctl,
+ (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
+ (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
+ (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
+ (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
+ (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
+
+ (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
+ (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
+ (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
+ (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
+ usbctl & ~USBCTL_WRITABLE_MASK
+ );
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Status register
+ */
+
+#define STATUS_PORT_A (1 << 15)
+
+#define STATUS_CONN_OTHER (1 << 14)
+#define STATUS_SUSPEND_OTHER (1 << 13)
+#define STATUS_MAILBOX_OTHER (1 << 12)
+#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
+
+#define STATUS_CONN_THIS (1 << 6)
+#define STATUS_SUSPEND_THIS (1 << 5)
+#define STATUS_MAILBOX_THIS (1 << 4)
+#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
+
+#define STATUS_UNSPEC_MASK 0x0c8c
+#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
+
+
+static inline void nc_dump_status(struct usbnet *dev, u16 status)
+{
+ if (!netif_msg_link(dev))
+ return;
+ devdbg(dev, "net1080 %s-%s status 0x%x:"
+ " this (%c) PKT=%d%s%s%s;"
+ " other PKT=%d%s%s%s; unspec 0x%x",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ status,
+
+ // XXX the packet counts don't seem right
+ // (1 at reset, not 0); maybe UNSPEC too
+
+ (status & STATUS_PORT_A) ? 'A' : 'B',
+ STATUS_PACKETS_THIS(status),
+ (status & STATUS_CONN_THIS) ? " CON" : "",
+ (status & STATUS_SUSPEND_THIS) ? " SUS" : "",
+ (status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
+
+ STATUS_PACKETS_OTHER(status),
+ (status & STATUS_CONN_OTHER) ? " CON" : "",
+ (status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
+ (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
+
+ status & STATUS_UNSPEC_MASK
+ );
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * TTL register
+ */
+
+#define TTL_THIS(ttl) (0x00ff & ttl)
+#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8))
+#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this))))
+
+static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
+{
+ if (netif_msg_link(dev))
+ devdbg(dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ ttl, TTL_THIS(ttl), TTL_OTHER(ttl));
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int net1080_reset(struct usbnet *dev)
+{
+ u16 usbctl, status, ttl;
+ u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+ int retval;
+
+ if (!vp)
+ return -ENOMEM;
+
+ // nc_dump_registers(dev);
+
+ if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
+ dbg("can't read %s-%s status: %d",
+ dev->udev->bus->bus_name, dev->udev->devpath, retval);
+ goto done;
+ }
+ status = *vp;
+ nc_dump_status(dev, status);
+
+ if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
+ dbg("can't read USBCTL, %d", retval);
+ goto done;
+ }
+ usbctl = *vp;
+ nc_dump_usbctl(dev, usbctl);
+
+ nc_register_write(dev, REG_USBCTL,
+ USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
+
+ if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
+ dbg("can't read TTL, %d", retval);
+ goto done;
+ }
+ ttl = *vp;
+ // nc_dump_ttl(dev, ttl);
+
+ nc_register_write(dev, REG_TTL,
+ MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) );
+ dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
+
+ if (netif_msg_link(dev))
+ devinfo(dev, "port %c, peer %sconnected",
+ (status & STATUS_PORT_A) ? 'A' : 'B',
+ (status & STATUS_CONN_OTHER) ? "" : "dis"
+ );
+ retval = 0;
+
+done:
+ kfree(vp);
+ return retval;
+}
+
+static int net1080_check_connect(struct usbnet *dev)
+{
+ int retval;
+ u16 status;
+ u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+
+ if (!vp)
+ return -ENOMEM;
+ retval = nc_register_read(dev, REG_STATUS, vp);
+ status = *vp;
+ kfree(vp);
+ if (retval != 0) {
+ dbg("%s net1080_check_conn read - %d", dev->net->name, retval);
+ return retval;
+ }
+ if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
+ return -ENOLINK;
+ return 0;
+}
+
+static void nc_flush_complete(struct urb *urb, struct pt_regs *regs)
+{
+ kfree(urb->context);
+ usb_free_urb(urb);
+}
+
+static void nc_ensure_sync(struct usbnet *dev)
+{
+ dev->frame_errors++;
+ if (dev->frame_errors > 5) {
+ struct urb *urb;
+ struct usb_ctrlrequest *req;
+ int status;
+
+ /* Send a flush */
+ urb = usb_alloc_urb(0, SLAB_ATOMIC);
+ if (!urb)
+ return;
+
+ req = kmalloc(sizeof *req, GFP_ATOMIC);
+ if (!req) {
+ usb_free_urb(urb);
+ return;
+ }
+
+ req->bRequestType = USB_DIR_OUT
+ | USB_TYPE_VENDOR
+ | USB_RECIP_DEVICE;
+ req->bRequest = REQUEST_REGISTER;
+ req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS
+ | USBCTL_FLUSH_OTHER);
+ req->wIndex = cpu_to_le16(REG_USBCTL);
+ req->wLength = cpu_to_le16(0);
+
+ /* queue an async control request, we don't need
+ * to do anything when it finishes except clean up.
+ */
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (unsigned char *) req,
+ NULL, 0,
+ nc_flush_complete, req);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ kfree(req);
+ usb_free_urb(urb);
+ return;
+ }
+
+ if (netif_msg_rx_err(dev))
+ devdbg(dev, "flush net1080; too many framing errors");
+ dev->frame_errors = 0;
+ }
+}
+
+static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct nc_header *header;
+ struct nc_trailer *trailer;
+ u16 hdr_len, packet_len;
+
+ if (!(skb->len & 0x01)) {
+#ifdef DEBUG
+ struct net_device *net = dev->net;
+ dbg("rx framesize %d range %d..%d mtu %d", skb->len,
+ net->hard_header_len, dev->hard_mtu, net->mtu);
+#endif
+ dev->stats.rx_frame_errors++;
+ nc_ensure_sync(dev);
+ return 0;
+ }
+
+ header = (struct nc_header *) skb->data;
+ hdr_len = le16_to_cpup(&header->hdr_len);
+ packet_len = le16_to_cpup(&header->packet_len);
+ if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
+ dev->stats.rx_frame_errors++;
+ dbg("packet too big, %d", packet_len);
+ nc_ensure_sync(dev);
+ return 0;
+ } else if (hdr_len < MIN_HEADER) {
+ dev->stats.rx_frame_errors++;
+ dbg("header too short, %d", hdr_len);
+ nc_ensure_sync(dev);
+ return 0;
+ } else if (hdr_len > MIN_HEADER) {
+ // out of band data for us?
+ dbg("header OOB, %d bytes", hdr_len - MIN_HEADER);
+ nc_ensure_sync(dev);
+ // switch (vendor/product ids) { ... }
+ }
+ skb_pull(skb, hdr_len);
+
+ trailer = (struct nc_trailer *)
+ (skb->data + skb->len - sizeof *trailer);
+ skb_trim(skb, skb->len - sizeof *trailer);
+
+ if ((packet_len & 0x01) == 0) {
+ if (skb->data [packet_len] != PAD_BYTE) {
+ dev->stats.rx_frame_errors++;
+ dbg("bad pad");
+ return 0;
+ }
+ skb_trim(skb, skb->len - 1);
+ }
+ if (skb->len != packet_len) {
+ dev->stats.rx_frame_errors++;
+ dbg("bad packet len %d (expected %d)",
+ skb->len, packet_len);
+ nc_ensure_sync(dev);
+ return 0;
+ }
+ if (header->packet_id != get_unaligned(&trailer->packet_id)) {
+ dev->stats.rx_fifo_errors++;
+ dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
+ le16_to_cpu(header->packet_id),
+ le16_to_cpu(trailer->packet_id));
+ return 0;
+ }
+#if 0
+ devdbg(dev, "frame <rx h %d p %d id %d", header->hdr_len,
+ header->packet_len, header->packet_id);
+#endif
+ dev->frame_errors = 0;
+ return 1;
+}
+
+static struct sk_buff *
+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+ struct nc_header *header = NULL;
+ struct nc_trailer *trailer = NULL;
+ int len = skb->len;
+
+ padlen = ((len + sizeof (struct nc_header)
+ + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+ if (!skb_cloned(skb)) {
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+
+ if ((padlen + sizeof (struct nc_trailer)) <= tailroom
+ && sizeof (struct nc_header) <= headroom)
+ /* There's enough head and tail room */
+ goto encapsulate;
+
+ if ((sizeof (struct nc_header) + padlen
+ + sizeof (struct nc_trailer)) <
+ (headroom + tailroom)) {
+ /* There's enough total room, so just readjust */
+ skb->data = memmove(skb->head
+ + sizeof (struct nc_header),
+ skb->data, skb->len);
+ skb->tail = skb->data + len;
+ goto encapsulate;
+ }
+ }
+
+ /* Create a new skb to use with the correct size */
+ skb2 = skb_copy_expand(skb,
+ sizeof (struct nc_header),
+ sizeof (struct nc_trailer) + padlen,
+ flags);
+ dev_kfree_skb_any(skb);
+ if (!skb2)
+ return skb2;
+ skb = skb2;
+
+encapsulate:
+ /* header first */
+ header = (struct nc_header *) skb_push(skb, sizeof *header);
+ header->hdr_len = cpu_to_le16(sizeof (*header));
+ header->packet_len = cpu_to_le16(len);
+ header->packet_id = cpu_to_le16((u16)dev->xid++);
+
+ /* maybe pad; then trailer */
+ if (!((skb->len + sizeof *trailer) & 0x01))
+ *skb_put(skb, 1) = PAD_BYTE;
+ trailer = (struct nc_trailer *) skb_put(skb, sizeof *trailer);
+ put_unaligned(header->packet_id, &trailer->packet_id);
+#if 0
+ devdbg(dev, "frame >tx h %d p %d id %d",
+ header->hdr_len, header->packet_len,
+ header->packet_id);
+#endif
+ return skb;
+}
+
+static int net1080_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ unsigned extra = sizeof (struct nc_header)
+ + 1
+ + sizeof (struct nc_trailer);
+
+ dev->net->hard_header_len += extra;
+ dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
+ dev->hard_mtu = NC_MAX_PACKET;
+ return usbnet_get_endpoints (dev, intf);
+}
+
+static const struct driver_info net1080_info = {
+ .description = "NetChip TurboCONNECT",
+ .flags = FLAG_FRAMING_NC,
+ .bind = net1080_bind,
+ .reset = net1080_reset,
+ .check_connect = net1080_check_connect,
+ .rx_fixup = net1080_rx_fixup,
+ .tx_fixup = net1080_tx_fixup,
+};
+
+static const struct usb_device_id products [] = {
+{
+ USB_DEVICE(0x0525, 0x1080), // NetChip ref design
+ .driver_info = (unsigned long) &net1080_info,
+}, {
+ USB_DEVICE(0x06D0, 0x0622), // Laplink Gold
+ .driver_info = (unsigned long) &net1080_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver net1080_driver = {
+ .owner = THIS_MODULE,
+ .name = "net1080",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init net1080_init(void)
+{
+ return usb_register(&net1080_driver);
+}
+module_init(net1080_init);
+
+static void __exit net1080_exit(void)
+{
+ usb_deregister(&net1080_driver);
+}
+module_exit(net1080_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("NetChip 1080 based USB Host-to-Host Links");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index fcd6d3ccef44..7484d34780fc 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -825,7 +825,6 @@ static void pegasus_tx_timeout(struct net_device *net)
pegasus_t *pegasus = netdev_priv(net);
if (netif_msg_timer(pegasus))
printk(KERN_WARNING "%s: tx timeout\n", net->name);
- pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
}
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
new file mode 100644
index 000000000000..74c2b3581c76
--- /dev/null
+++ b/drivers/usb/net/plusb.c
@@ -0,0 +1,156 @@
+/*
+ * PL-2301/2302 USB host-to-host link cables
+ * Copyright (C) 2000-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
+ *
+ * The protocol and handshaking used here should be bug-compatible
+ * with the Linux 2.2 "plusb" driver, by Deti Fliegl.
+ *
+ * HEADS UP: this handshaking isn't all that robust. This driver
+ * gets confused easily if you unplug one end of the cable then
+ * try to connect it again; you'll need to restart both ends. The
+ * "naplink" software (used by some PlayStation/2 deveopers) does
+ * the handshaking much better! Also, sometimes this hardware
+ * seems to get wedged under load. Prolific docs are weak, and
+ * don't identify differences between PL2301 and PL2302, much less
+ * anything to explain the different PL2302 versions observed.
+ */
+
+/*
+ * Bits 0-4 can be used for software handshaking; they're set from
+ * one end, cleared from the other, "read" with the interrupt byte.
+ */
+#define PL_S_EN (1<<7) /* (feature only) suspend enable */
+/* reserved bit -- rx ready (6) ? */
+#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */
+#define PL_RESET_OUT (1<<4) /* reset output pipe */
+#define PL_RESET_IN (1<<3) /* reset input pipe */
+#define PL_TX_C (1<<2) /* transmission complete */
+#define PL_TX_REQ (1<<1) /* transmission received */
+#define PL_PEER_E (1<<0) /* peer exists */
+
+static inline int
+pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
+{
+ return usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ val, index,
+ NULL, 0,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static inline int
+pl_clear_QuickLink_features(struct usbnet *dev, int val)
+{
+ return pl_vendor_req(dev, 1, (u8) val, 0);
+}
+
+static inline int
+pl_set_QuickLink_features(struct usbnet *dev, int val)
+{
+ return pl_vendor_req(dev, 3, (u8) val, 0);
+}
+
+static int pl_reset(struct usbnet *dev)
+{
+ /* some units seem to need this reset, others reject it utterly.
+ * FIXME be more like "naplink" or windows drivers.
+ */
+ (void) pl_set_QuickLink_features(dev,
+ PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
+ return 0;
+}
+
+static const struct driver_info prolific_info = {
+ .description = "Prolific PL-2301/PL-2302",
+ .flags = FLAG_NO_SETINT,
+ /* some PL-2302 versions seem to fail usb_set_interface() */
+ .reset = pl_reset,
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Proilific's name won't normally be on the cables, and
+ * may not be on the device.
+ */
+
+static const struct usb_device_id products [] = {
+
+{
+ USB_DEVICE(0x067b, 0x0000), // PL-2301
+ .driver_info = (unsigned long) &prolific_info,
+}, {
+ USB_DEVICE(0x067b, 0x0001), // PL-2302
+ .driver_info = (unsigned long) &prolific_info,
+},
+
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver plusb_driver = {
+ .owner = THIS_MODULE,
+ .name = "plusb",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init plusb_init(void)
+{
+ return usb_register(&plusb_driver);
+}
+module_init(plusb_init);
+
+static void __exit plusb_exit(void)
+{
+ usb_deregister(&plusb_driver);
+}
+module_exit(plusb_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("Prolific PL-2301/2302 USB Host to Host Link Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
new file mode 100644
index 000000000000..2ed2e5fb7778
--- /dev/null
+++ b/drivers/usb/net/rndis_host.c
@@ -0,0 +1,615 @@
+/*
+ * Host Side support for RNDIS Networking Links
+ * Copyright (C) 2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * 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.
+ */
+
+/*
+ * CONTROL uses CDC "encapsulated commands" with funky notifications.
+ * - control-out: SEND_ENCAPSULATED
+ * - interrupt-in: RESPONSE_AVAILABLE
+ * - control-in: GET_ENCAPSULATED
+ *
+ * We'll try to ignore the RESPONSE_AVAILABLE notifications.
+ */
+struct rndis_msg_hdr {
+ __le32 msg_type; /* RNDIS_MSG_* */
+ __le32 msg_len;
+ // followed by data that varies between messages
+ __le32 request_id;
+ __le32 status;
+ // ... and more
+} __attribute__ ((packed));
+
+/* RNDIS defines this (absurdly huge) control timeout */
+#define RNDIS_CONTROL_TIMEOUT_MS (10 * 1000)
+
+
+#define ccpu2 __constant_cpu_to_le32
+
+#define RNDIS_MSG_COMPLETION ccpu2(0x80000000)
+
+/* codes for "msg_type" field of rndis messages;
+ * only the data channel uses packet messages (maybe batched);
+ * everything else goes on the control channel.
+ */
+#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_HALT ccpu2(0x00000003)
+#define RNDIS_MSG_QUERY ccpu2(0x00000004)
+#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_RESET ccpu2(0x00000006)
+#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)
+
+/* codes for "status" field of completion messages */
+#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
+#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001)
+#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015)
+#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb)
+#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b)
+#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c)
+
+
+struct rndis_data_hdr {
+ __le32 msg_type; /* RNDIS_MSG_PACKET */
+ __le32 msg_len; // rndis_data_hdr + data_len + pad
+ __le32 data_offset; // 36 -- right after header
+ __le32 data_len; // ... real packet size
+
+ __le32 oob_data_offset; // zero
+ __le32 oob_data_len; // zero
+ __le32 num_oob; // zero
+ __le32 packet_data_offset; // zero
+
+ __le32 packet_data_len; // zero
+ __le32 vc_handle; // zero
+ __le32 reserved; // zero
+} __attribute__ ((packed));
+
+struct rndis_init { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INIT */
+ __le32 msg_len; // 24
+ __le32 request_id;
+ __le32 major_version; // of rndis (1.0)
+ __le32 minor_version;
+ __le32 max_transfer_size;
+} __attribute__ ((packed));
+
+struct rndis_init_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INIT_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+ __le32 major_version; // of rndis (1.0)
+ __le32 minor_version;
+ __le32 device_flags;
+ __le32 medium; // zero == 802.3
+ __le32 max_packets_per_message;
+ __le32 max_transfer_size;
+ __le32 packet_alignment; // max 7; (1<<n) bytes
+ __le32 af_list_offset; // zero
+ __le32 af_list_size; // zero
+} __attribute__ ((packed));
+
+struct rndis_halt { /* OUT (no reply) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_HALT */
+ __le32 msg_len;
+ __le32 request_id;
+} __attribute__ ((packed));
+
+struct rndis_query { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_QUERY */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 oid;
+ __le32 len;
+ __le32 offset;
+/*?*/ __le32 handle; // zero
+} __attribute__ ((packed));
+
+struct rndis_query_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_QUERY_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+ __le32 len;
+ __le32 offset;
+} __attribute__ ((packed));
+
+struct rndis_set { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_SET */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 oid;
+ __le32 len;
+ __le32 offset;
+/*?*/ __le32 handle; // zero
+} __attribute__ ((packed));
+
+struct rndis_set_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_SET_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+} __attribute__ ((packed));
+
+struct rndis_reset { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_RESET */
+ __le32 msg_len;
+ __le32 reserved;
+} __attribute__ ((packed));
+
+struct rndis_reset_c { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_RESET_C */
+ __le32 msg_len;
+ __le32 status;
+ __le32 addressing_lost;
+} __attribute__ ((packed));
+
+struct rndis_indicate { /* IN (unrequested) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INDICATE */
+ __le32 msg_len;
+ __le32 status;
+ __le32 length;
+ __le32 offset;
+/**/ __le32 diag_status;
+ __le32 error_offset;
+/**/ __le32 message;
+} __attribute__ ((packed));
+
+struct rndis_keepalive { /* OUT (optionally IN) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */
+ __le32 msg_len;
+ __le32 request_id;
+} __attribute__ ((packed));
+
+struct rndis_keepalive_c { /* IN (optionally OUT) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+} __attribute__ ((packed));
+
+/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and
+ * there are gobs more that may optionally be supported. We'll avoid as much
+ * of that mess as possible.
+ */
+#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101)
+#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e)
+
+/*
+ * RNDIS notifications from device: command completion; "reverse"
+ * keepalives; etc
+ */
+static void rndis_status(struct usbnet *dev, struct urb *urb)
+{
+ devdbg(dev, "rndis status urb, len %d stat %d",
+ urb->actual_length, urb->status);
+ // FIXME for keepalives, respond immediately (asynchronously)
+ // if not an RNDIS status, do like cdc_status(dev,urb) does
+}
+
+/*
+ * RPC done RNDIS-style. Caller guarantees:
+ * - message is properly byteswapped
+ * - there's no other request pending
+ * - buf can hold up to 1KB response (required by RNDIS spec)
+ * On return, the first few entries are already byteswapped.
+ *
+ * Call context is likely probe(), before interface name is known,
+ * which is why we won't try to use it in the diagnostics.
+ */
+static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
+{
+ struct cdc_state *info = (void *) &dev->data;
+ int retval;
+ unsigned count;
+ __le32 rsp;
+ u32 xid = 0, msg_len, request_id;
+
+ /* REVISIT when this gets called from contexts other than probe() or
+ * disconnect(): either serialize, or dispatch responses on xid
+ */
+
+ /* Issue the request; don't bother byteswapping our xid */
+ if (likely(buf->msg_type != RNDIS_MSG_HALT
+ && buf->msg_type != RNDIS_MSG_RESET)) {
+ xid = dev->xid++;
+ if (!xid)
+ xid = dev->xid++;
+ buf->request_id = (__force __le32) xid;
+ }
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ buf, le32_to_cpu(buf->msg_len),
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (unlikely(retval < 0 || xid == 0))
+ return retval;
+
+ // FIXME Seems like some devices discard responses when
+ // we time out and cancel our "get response" requests...
+ // so, this is fragile. Probably need to poll for status.
+
+ /* ignore status endpoint, just poll the control channel;
+ * the request probably completed immediately
+ */
+ rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
+ for (count = 0; count < 10; count++) {
+ memset(buf, 0, 1024);
+ retval = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ USB_CDC_GET_ENCAPSULATED_RESPONSE,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ buf, 1024,
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (likely(retval >= 8)) {
+ msg_len = le32_to_cpu(buf->msg_len);
+ request_id = (__force u32) buf->request_id;
+ if (likely(buf->msg_type == rsp)) {
+ if (likely(request_id == xid)) {
+ if (unlikely(rsp == RNDIS_MSG_RESET_C))
+ return 0;
+ if (likely(RNDIS_STATUS_SUCCESS
+ == buf->status))
+ return 0;
+ dev_dbg(&info->control->dev,
+ "rndis reply status %08x\n",
+ le32_to_cpu(buf->status));
+ return -EL3RST;
+ }
+ dev_dbg(&info->control->dev,
+ "rndis reply id %d expected %d\n",
+ request_id, xid);
+ /* then likely retry */
+ } else switch (buf->msg_type) {
+ case RNDIS_MSG_INDICATE: { /* fault */
+ // struct rndis_indicate *msg = (void *)buf;
+ dev_info(&info->control->dev,
+ "rndis fault indication\n");
+ }
+ break;
+ case RNDIS_MSG_KEEPALIVE: { /* ping */
+ struct rndis_keepalive_c *msg = (void *)buf;
+
+ msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
+ msg->msg_len = ccpu2(sizeof *msg);
+ msg->status = RNDIS_STATUS_SUCCESS;
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ msg, sizeof *msg,
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (unlikely(retval < 0))
+ dev_dbg(&info->control->dev,
+ "rndis keepalive err %d\n",
+ retval);
+ }
+ break;
+ default:
+ dev_dbg(&info->control->dev,
+ "unexpected rndis msg %08x len %d\n",
+ le32_to_cpu(buf->msg_type), msg_len);
+ }
+ } else {
+ /* device probably issued a protocol stall; ignore */
+ dev_dbg(&info->control->dev,
+ "rndis response error, code %d\n", retval);
+ }
+ msleep(2);
+ }
+ dev_dbg(&info->control->dev, "rndis response timeout\n");
+ return -ETIMEDOUT;
+}
+
+static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int retval;
+ struct net_device *net = dev->net;
+ union {
+ void *buf;
+ struct rndis_msg_hdr *header;
+ struct rndis_init *init;
+ struct rndis_init_c *init_c;
+ struct rndis_query *get;
+ struct rndis_query_c *get_c;
+ struct rndis_set *set;
+ struct rndis_set_c *set_c;
+ } u;
+ u32 tmp;
+
+ /* we can't rely on i/o from stack working, or stack allocation */
+ u.buf = kmalloc(1024, GFP_KERNEL);
+ if (!u.buf)
+ return -ENOMEM;
+ retval = usbnet_generic_cdc_bind(dev, intf);
+ if (retval < 0)
+ goto done;
+
+ net->hard_header_len += sizeof (struct rndis_data_hdr);
+
+ /* initialize; max transfer is 16KB at full speed */
+ u.init->msg_type = RNDIS_MSG_INIT;
+ u.init->msg_len = ccpu2(sizeof *u.init);
+ u.init->major_version = ccpu2(1);
+ u.init->minor_version = ccpu2(0);
+ u.init->max_transfer_size = ccpu2(net->mtu + net->hard_header_len);
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ /* it might not even be an RNDIS device!! */
+ dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
+fail:
+ usb_driver_release_interface(driver_of(intf),
+ ((struct cdc_state *)&(dev->data))->data);
+ goto done;
+ }
+ dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size);
+ /* REVISIT: peripheral "alignment" request is ignored ... */
+ dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu,
+ 1 << le32_to_cpu(u.init_c->packet_alignment));
+
+ /* get designated host ethernet address */
+ memset(u.get, 0, sizeof *u.get);
+ u.get->msg_type = RNDIS_MSG_QUERY;
+ u.get->msg_len = ccpu2(sizeof *u.get);
+ u.get->oid = OID_802_3_PERMANENT_ADDRESS;
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
+ goto fail;
+ }
+ tmp = le32_to_cpu(u.get_c->offset);
+ if (unlikely((tmp + 8) > (1024 - ETH_ALEN)
+ || u.get_c->len != ccpu2(ETH_ALEN))) {
+ dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
+ tmp, le32_to_cpu(u.get_c->len));
+ retval = -EDOM;
+ goto fail;
+ }
+ memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
+
+ /* set a nonzero filter to enable data transfers */
+ memset(u.set, 0, sizeof *u.set);
+ u.set->msg_type = RNDIS_MSG_SET;
+ u.set->msg_len = ccpu2(4 + sizeof *u.set);
+ u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
+ u.set->len = ccpu2(4);
+ u.set->offset = ccpu2((sizeof *u.set) - 8);
+ *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER);
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
+ goto fail;
+ }
+
+ retval = 0;
+done:
+ kfree(u.buf);
+ return retval;
+}
+
+static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct rndis_halt *halt;
+
+ /* try to clear any rndis state/activity (no i/o from stack!) */
+ halt = kcalloc(1, sizeof *halt, SLAB_KERNEL);
+ if (halt) {
+ halt->msg_type = RNDIS_MSG_HALT;
+ halt->msg_len = ccpu2(sizeof *halt);
+ (void) rndis_command(dev, (void *)halt);
+ kfree(halt);
+ }
+
+ return usbnet_cdc_unbind(dev, intf);
+}
+
+/*
+ * DATA -- host must not write zlps
+ */
+static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ /* peripheral may have batched packets to us... */
+ while (likely(skb->len)) {
+ struct rndis_data_hdr *hdr = (void *)skb->data;
+ struct sk_buff *skb2;
+ u32 msg_len, data_offset, data_len;
+
+ msg_len = le32_to_cpu(hdr->msg_len);
+ data_offset = le32_to_cpu(hdr->data_offset);
+ data_len = le32_to_cpu(hdr->data_len);
+
+ /* don't choke if we see oob, per-packet data, etc */
+ if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
+ || skb->len < msg_len
+ || (data_offset + data_len + 8) > msg_len)) {
+ dev->stats.rx_frame_errors++;
+ devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
+ le32_to_cpu(hdr->msg_type),
+ msg_len, data_offset, data_len, skb->len);
+ return 0;
+ }
+ skb_pull(skb, 8 + data_offset);
+
+ /* at most one packet left? */
+ if (likely((data_len - skb->len) <= sizeof *hdr)) {
+ skb_trim(skb, data_len);
+ break;
+ }
+
+ /* try to return all the packets in the batch */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ break;
+ skb_pull(skb, msg_len - sizeof *hdr);
+ skb_trim(skb2, data_len);
+ usbnet_skb_return(dev, skb2);
+ }
+
+ /* caller will usbnet_skb_return the remaining packet */
+ return 1;
+}
+
+static struct sk_buff *
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+{
+ struct rndis_data_hdr *hdr;
+ struct sk_buff *skb2;
+ unsigned len = skb->len;
+
+ if (likely(!skb_cloned(skb))) {
+ int room = skb_headroom(skb);
+
+ /* enough head room as-is? */
+ if (unlikely((sizeof *hdr) <= room))
+ goto fill;
+
+ /* enough room, but needs to be readjusted? */
+ room += skb_tailroom(skb);
+ if (likely((sizeof *hdr) <= room)) {
+ skb->data = memmove(skb->head + sizeof *hdr,
+ skb->data, len);
+ skb->tail = skb->data + len;
+ goto fill;
+ }
+ }
+
+ /* create a new skb, with the correct size (and tailpad) */
+ skb2 = skb_copy_expand(skb, sizeof *hdr, 1, flags);
+ dev_kfree_skb_any(skb);
+ if (unlikely(!skb2))
+ return skb2;
+ skb = skb2;
+
+ /* fill out the RNDIS header. we won't bother trying to batch
+ * packets; Linux minimizes wasted bandwidth through tx queues.
+ */
+fill:
+ hdr = (void *) __skb_push(skb, sizeof *hdr);
+ memset(hdr, 0, sizeof *hdr);
+ hdr->msg_type = RNDIS_MSG_PACKET;
+ hdr->msg_len = cpu_to_le32(skb->len);
+ hdr->data_offset = ccpu2(sizeof(*hdr) - 8);
+ hdr->data_len = cpu_to_le32(len);
+
+ /* FIXME make the last packet always be short ... */
+ return skb;
+}
+
+
+static const struct driver_info rndis_info = {
+ .description = "RNDIS device",
+ .flags = FLAG_ETHER | FLAG_FRAMING_RN,
+ .bind = rndis_bind,
+ .unbind = rndis_unbind,
+ .status = rndis_status,
+ .rx_fixup = rndis_rx_fixup,
+ .tx_fixup = rndis_tx_fixup,
+};
+
+#undef ccpu2
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products [] = {
+{
+ /* RNDIS is MSFT's un-official variant of CDC ACM */
+ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+ .driver_info = (unsigned long) &rndis_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver rndis_driver = {
+ .owner = THIS_MODULE,
+ .name = "rndis_host",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init rndis_init(void)
+{
+ return usb_register(&rndis_driver);
+}
+module_init(rndis_init);
+
+static void __exit rndis_exit(void)
+{
+ usb_deregister(&rndis_driver);
+}
+module_exit(rndis_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB Host side RNDIS driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 59ab40ebb394..c3d4e3589e30 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -653,7 +653,6 @@ static void rtl8150_tx_timeout(struct net_device *netdev)
{
rtl8150_t *dev = netdev_priv(netdev);
warn("%s: Tx timeout.", netdev->name);
- dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(dev->tx_urb);
dev->stats.tx_errors++;
}
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 4528a00c45b0..6c460918d54f 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -1,10 +1,7 @@
/*
- * USB Networking Links
- * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
- * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
+ * USB Network driver infrastructure
+ * Copyright (C) 2000-2005 by David Brownell
* Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
- * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
- * Copyright (c) 2002-2003 TiVo 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
@@ -23,95 +20,15 @@
/*
* This is a generic "USB networking" framework that works with several
- * kinds of full and high speed networking devices:
- *
- * + USB host-to-host "network cables", used for IP-over-USB links.
- * These are often used for Laplink style connectivity products.
- * - AnchorChip 2720
- * - Belkin, eTEK (interops with Win32 drivers)
- * - GeneSys GL620USB-A
- * - NetChip 1080 (interoperates with NetChip Win32 drivers)
- * - Prolific PL-2301/2302 (replaces "plusb" driver)
- * - KC Technology KC2190
- *
- * + Smart USB devices can support such links directly, using Internet
- * standard protocols instead of proprietary host-to-device links.
- * - Linux PDAs like iPaq, Yopy, and Zaurus
- * - The BLOB boot loader (for diskless booting)
- * - Linux "gadgets", perhaps using PXA-2xx or Net2280 controllers
- * - Devices using EPSON's sample USB firmware
- * - CDC-Ethernet class devices, such as many cable modems
- *
- * + Adapters to networks such as Ethernet.
- * - AX8817X based USB 2.0 products
- *
- * Links to these devices can be bridged using Linux Ethernet bridging.
- * With minor exceptions, these all use similar USB framing for network
- * traffic, but need different protocols for control traffic.
- *
- * USB devices can implement their side of this protocol at the cost
- * of two bulk endpoints; it's not restricted to "cable" applications.
- * See the SA1110, Zaurus, or EPSON device/client support in this driver;
- * slave/target drivers such as "usb-eth" (on most SA-1100 PDAs) or
- * "g_ether" (in the Linux "gadget" framework) implement that behavior
- * within devices.
- *
- *
- * CHANGELOG:
- *
- * 13-sep-2000 experimental, new
- * 10-oct-2000 usb_device_id table created.
- * 28-oct-2000 misc fixes; mostly, discard more TTL-mangled rx packets.
- * 01-nov-2000 usb_device_id table and probing api update by
- * Adam J. Richter <adam@yggdrasil.com>.
- * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info
- * and prolific support, isolate net1080-specific bits, cleanup.
- * fix unlink_urbs oops in D3 PM resume code path.
- *
- * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ...
- * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it;
- * AnchorChips 2720 support (from spec) for testing;
- * fix bit-ordering problem with ethernet multicast addr
- * 19-feb-2001 Support for clearing halt conditions. SA1100 UDC support
- * updates. Oleg Drokin (green@iXcelerator.com)
- * 25-mar-2001 More SA-1100 updates, including workaround for ip problem
- * expecting cleared skb->cb and framing change to match latest
- * handhelds.org version (Oleg). Enable device IDs from the
- * Win32 Belkin driver; other cleanups (db).
- * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various
- * cleanups for problems not yet seen in the field. (db)
- * 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
- * from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
- * rx unlinks somehow weren't async; minor cleanup.
- * 03-nov-2001 Merged GeneSys driver; original code from Jiun-Jie Huang
- * <huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec
- * <utx@penguin.cz>. Made framing options (NetChip/GeneSys)
- * tie mostly to (sub)driver info. Workaround some PL-2302
- * chips that seem to reject SET_INTERFACE requests.
- *
- * 06-apr-2002 Added ethtool support, based on a patch from Brad Hards.
- * Level of diagnostics is more configurable; they use device
- * location (usb_device->devpath) instead of address (2.5).
- * For tx_fixup, memflags can't be NOIO.
- * 07-may-2002 Generalize/cleanup keventd support, handling rx stalls (mostly
- * for USB 2.0 TTs) and memory shortages (potential) too. (db)
- * Use "locally assigned" IEEE802 address space. (Brad Hards)
- * 18-oct-2002 Support for Zaurus (Pavel Machek), related cleanup (db).
- * 14-dec-2002 Remove Zaurus-private crc32 code (Pavel); 2.5 oops fix,
- * cleanups and stubbed PXA-250 support (db), fix for framing
- * issues on Z, net1080, and gl620a (Toby Milne)
- *
- * 31-mar-2003 Use endpoint descriptors: high speed support, simpler sa1100
- * vs pxa25x, and CDC Ethernet. Throttle down log floods on
- * disconnect; other cleanups. (db) Flush net1080 fifos
- * after several sequential framing errors. (Johannes Erdfelt)
- * 22-aug-2003 AX8817X support (Dave Hollis).
- * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan
- * (Neil Bortnak)
- * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
- *
- * 01-feb-2005 AX88772 support (Phil Chang & Dave Hollis)
- *-------------------------------------------------------------------------*/
+ * kinds of full and high speed networking devices: host-to-host cables,
+ * smart usb peripherals, and actual Ethernet adapters.
+ *
+ * These devices usually differ in terms of control protocols (if they
+ * even have one!) and sometimes they define new framing to wrap or batch
+ * Ethernet packets. Otherwise, they talk to USB pretty much the same,
+ * so interface (un)binding, endpoint I/O queues, fault handling, and other
+ * issues can usefully be addressed by this framework.
+ */
// #define DEBUG // error path messages, extra info
// #define VERBOSE // more; success messages
@@ -121,24 +38,18 @@
# define DEBUG
#endif
#include <linux/module.h>
-#include <linux/kmod.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/random.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
#include <linux/usb.h>
-#include <asm/io.h>
-#include <asm/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/dma-mapping.h>
-#define DRIVER_VERSION "03-Nov-2004"
+#include "usbnet.h"
+
+#define DRIVER_VERSION "22-Aug-2005"
/*-------------------------------------------------------------------------*/
@@ -149,15 +60,14 @@
* One maximum size Ethernet packet takes twenty four of them.
* For high speed, each frame comfortably fits almost 36 max size
* Ethernet packets (so queues should be bigger).
+ *
+ * REVISIT qlens should be members of 'struct usbnet'; the goal is to
+ * let the USB host controller be busy for 5msec or more before an irq
+ * is required, under load. Jumbograms change the equation.
*/
#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-// packets are always ethernet inside
-// ... except they can be bigger (limit of 64K with NetChip framing)
-#define MIN_PACKET sizeof(struct ethhdr)
-#define MAX_PACKET 32768
-
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
@@ -165,9 +75,6 @@
// us (it polls at HZ/4 usually) before we report too many false errors.
#define THROTTLE_JIFFIES (HZ/8)
-// for vendor-specific control operations
-#define CONTROL_TIMEOUT_MS 500
-
// between wakeups
#define UNLINK_TIMEOUT_MS 3
@@ -176,109 +83,6 @@
// randomly generated ethernet address
static u8 node_id [ETH_ALEN];
-// state we keep for each device we handle
-struct usbnet {
- // housekeeping
- struct usb_device *udev;
- struct driver_info *driver_info;
- wait_queue_head_t *wait;
-
- // i/o info: pipes etc
- unsigned in, out;
- struct usb_host_endpoint *status;
- unsigned maxpacket;
- struct timer_list delay;
-
- // protocol/interface state
- struct net_device *net;
- struct net_device_stats stats;
- int msg_enable;
- unsigned long data [5];
-
- struct mii_if_info mii;
-
- // various kinds of pending driver work
- struct sk_buff_head rxq;
- struct sk_buff_head txq;
- struct sk_buff_head done;
- struct urb *interrupt;
- struct tasklet_struct bh;
-
- struct work_struct kevent;
- unsigned long flags;
-# define EVENT_TX_HALT 0
-# define EVENT_RX_HALT 1
-# define EVENT_RX_MEMORY 2
-# define EVENT_STS_SPLIT 3
-# define EVENT_LINK_RESET 4
-};
-
-// device-specific info used by the driver
-struct driver_info {
- char *description;
-
- int flags;
-/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
-#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
-#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
-#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
-#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
-
-#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
-#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
-
-#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
-
- /* init device ... can sleep, or cause probe() failure */
- int (*bind)(struct usbnet *, struct usb_interface *);
-
- /* cleanup device ... can sleep, but can't fail */
- void (*unbind)(struct usbnet *, struct usb_interface *);
-
- /* reset device ... can sleep */
- int (*reset)(struct usbnet *);
-
- /* see if peer is connected ... can sleep */
- int (*check_connect)(struct usbnet *);
-
- /* for status polling */
- void (*status)(struct usbnet *, struct urb *);
-
- /* link reset handling, called from defer_kevent */
- int (*link_reset)(struct usbnet *);
-
- /* fixup rx packet (strip framing) */
- int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
-
- /* fixup tx packet (add framing) */
- struct sk_buff *(*tx_fixup)(struct usbnet *dev,
- struct sk_buff *skb, int flags);
-
- // FIXME -- also an interrupt mechanism
- // useful for at least PL2301/2302 and GL620USB-A
- // and CDC use them to report 'is it connected' changes
-
- /* for new devices, use the descriptor-reading code instead */
- int in; /* rx endpoint */
- int out; /* tx endpoint */
-
- unsigned long data; /* Misc driver specific data */
-};
-
-// we record the state for each of our queued skbs
-enum skb_state {
- illegal = 0,
- tx_start, tx_done,
- rx_start, rx_done, rx_cleanup
-};
-
-struct skb_data { // skb->cb is one of these
- struct urb *urb;
- struct usbnet *dev;
- enum skb_state state;
- size_t length;
-};
-
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
@@ -286,39 +90,10 @@ static int msg_level = -1;
module_param (msg_level, int, 0);
MODULE_PARM_DESC (msg_level, "Override default message level");
-
-#ifdef DEBUG
-#define devdbg(usbnet, fmt, arg...) \
- printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-#else
-#define devdbg(usbnet, fmt, arg...) do {} while(0)
-#endif
-
-#define deverr(usbnet, fmt, arg...) \
- printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-#define devwarn(usbnet, fmt, arg...) \
- printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-
-#define devinfo(usbnet, fmt, arg...) \
- printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
-
/*-------------------------------------------------------------------------*/
-static void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
-static u32 usbnet_get_link (struct net_device *);
-static u32 usbnet_get_msglevel (struct net_device *);
-static void usbnet_set_msglevel (struct net_device *, u32);
-static void defer_kevent (struct usbnet *, int);
-
-/* mostly for PDA style devices, which are always connected if present */
-static int always_connected (struct usbnet *dev)
-{
- return 0;
-}
-
/* handles CDC Ethernet and many other network "bulk data" interfaces */
-static int
-get_endpoints (struct usbnet *dev, struct usb_interface *intf)
+int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
{
int tmp;
struct usb_host_interface *alt = NULL;
@@ -382,6 +157,7 @@ get_endpoints (struct usbnet *dev, struct usb_interface *intf)
dev->status = status;
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_get_endpoints);
static void intr_complete (struct urb *urb, struct pt_regs *regs);
@@ -421,7 +197,11 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
return 0;
}
-static void skb_return (struct usbnet *dev, struct sk_buff *skb)
+/* Passes this packet up the stack, updating its accounting.
+ * Some link protocols batch packets, so their rx_fixup paths
+ * can return clones as well as just modify the original skb.
+ */
+void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
{
int status;
@@ -438,2425 +218,7 @@ static void skb_return (struct usbnet *dev, struct sk_buff *skb)
if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
devdbg (dev, "netif_rx status %d", status);
}
-
-
-#ifdef CONFIG_USB_ALI_M5632
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * ALi M5632 driver ... does high speed
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info ali_m5632_info = {
- .description = "ALi M5632",
-};
-
-
-#endif
-
-
-#ifdef CONFIG_USB_AN2720
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * AnchorChips 2720 driver ... http://www.cypress.com
- *
- * This doesn't seem to have a way to detect whether the peer is
- * connected, or need any reset handshaking. It's got pretty big
- * internal buffers (handles most of a frame's worth of data).
- * Chip data sheets don't describe any vendor control messages.
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info an2720_info = {
- .description = "AnchorChips/Cypress 2720",
- // no reset available!
- // no check_connect available!
-
- .in = 2, .out = 2, // direction distinguishes these
-};
-
-#endif /* CONFIG_USB_AN2720 */
-
-
-#ifdef CONFIG_USB_AX8817X
-/* ASIX AX8817X based USB 2.0 Ethernet Devices */
-
-#define HAVE_HARDWARE
-#define NEED_MII
-
-#include <linux/crc32.h>
-
-#define AX_CMD_SET_SW_MII 0x06
-#define AX_CMD_READ_MII_REG 0x07
-#define AX_CMD_WRITE_MII_REG 0x08
-#define AX_CMD_SET_HW_MII 0x0a
-#define AX_CMD_READ_EEPROM 0x0b
-#define AX_CMD_WRITE_EEPROM 0x0c
-#define AX_CMD_WRITE_ENABLE 0x0d
-#define AX_CMD_WRITE_DISABLE 0x0e
-#define AX_CMD_WRITE_RX_CTL 0x10
-#define AX_CMD_READ_IPG012 0x11
-#define AX_CMD_WRITE_IPG0 0x12
-#define AX_CMD_WRITE_IPG1 0x13
-#define AX_CMD_WRITE_IPG2 0x14
-#define AX_CMD_WRITE_MULTI_FILTER 0x16
-#define AX_CMD_READ_NODE_ID 0x17
-#define AX_CMD_READ_PHY_ID 0x19
-#define AX_CMD_READ_MEDIUM_STATUS 0x1a
-#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
-#define AX_CMD_READ_MONITOR_MODE 0x1c
-#define AX_CMD_WRITE_MONITOR_MODE 0x1d
-#define AX_CMD_WRITE_GPIOS 0x1f
-#define AX_CMD_SW_RESET 0x20
-#define AX_CMD_SW_PHY_STATUS 0x21
-#define AX_CMD_SW_PHY_SELECT 0x22
-#define AX88772_CMD_READ_NODE_ID 0x13
-
-#define AX_MONITOR_MODE 0x01
-#define AX_MONITOR_LINK 0x02
-#define AX_MONITOR_MAGIC 0x04
-#define AX_MONITOR_HSFS 0x10
-
-/* AX88172 Medium Status Register values */
-#define AX_MEDIUM_FULL_DUPLEX 0x02
-#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
-#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
-
-#define AX_MCAST_FILTER_SIZE 8
-#define AX_MAX_MCAST 64
-
-#define AX_EEPROM_LEN 0x40
-
-#define AX_SWRESET_CLEAR 0x00
-#define AX_SWRESET_RR 0x01
-#define AX_SWRESET_RT 0x02
-#define AX_SWRESET_PRTE 0x04
-#define AX_SWRESET_PRL 0x08
-#define AX_SWRESET_BZ 0x10
-#define AX_SWRESET_IPRL 0x20
-#define AX_SWRESET_IPPD 0x40
-
-#define AX88772_IPG0_DEFAULT 0x15
-#define AX88772_IPG1_DEFAULT 0x0c
-#define AX88772_IPG2_DEFAULT 0x12
-
-#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
-#define AX88772_MEDIUM_RESERVED 0x0004
-#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
-#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
-#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
-#define AX88772_MEDIUM_RX_ENABLE 0x0100
-#define AX88772_MEDIUM_100MB 0x0200
-#define AX88772_MEDIUM_DEFAULT \
- (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
- AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
- AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
-
-#define AX_EEPROM_MAGIC 0xdeadbeef
-
-/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct ax8817x_data {
- u8 multi_filter[AX_MCAST_FILTER_SIZE];
-};
-
-struct ax88172_int_data {
- u16 res1;
- u8 link;
- u16 res2;
- u8 status;
- u16 res3;
-} __attribute__ ((packed));
-
-static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- return usb_control_msg(
- dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- data,
- size,
- CONTROL_TIMEOUT_MS);
-}
-
-static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- return usb_control_msg(
- dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- data,
- size,
- CONTROL_TIMEOUT_MS);
-}
-
-static void ax8817x_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",
- urb->status);
-
- kfree(req);
- usb_free_urb(urb);
-}
-
-static void ax8817x_status(struct usbnet *dev, struct urb *urb)
-{
- struct ax88172_int_data *event;
- int link;
-
- if (urb->actual_length < 8)
- return;
-
- event = urb->transfer_buffer;
- link = event->link & 0x01;
- if (netif_carrier_ok(dev->net) != link) {
- if (link) {
- netif_carrier_on(dev->net);
- defer_kevent (dev, EVENT_LINK_RESET );
- } else
- netif_carrier_off(dev->net);
- devdbg(dev, "ax8817x - Link Status is: %d", link);
- }
-}
-
-static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- struct usb_ctrlrequest *req;
- int status;
- struct urb *urb;
-
- if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
- devdbg(dev, "Error allocating URB in write_cmd_async!");
- return;
- }
-
- if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
- deverr(dev, "Failed to allocate memory for control request");
- usb_free_urb(urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- req->bRequest = cmd;
- req->wValue = cpu_to_le16(value);
- req->wIndex = cpu_to_le16(index);
- req->wLength = cpu_to_le16(size);
-
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, size,
- ax8817x_async_cmd_callback, req);
-
- if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- deverr(dev, "Error submitting the control message: status=%d", status);
- kfree(req);
- usb_free_urb(urb);
- }
-}
-
-static void ax8817x_set_multicast(struct net_device *net)
-{
- struct usbnet *dev = netdev_priv(net);
- struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
- u8 rx_ctl = 0x8c;
-
- if (net->flags & IFF_PROMISC) {
- rx_ctl |= 0x01;
- } else if (net->flags & IFF_ALLMULTI
- || net->mc_count > AX_MAX_MCAST) {
- rx_ctl |= 0x02;
- } else if (net->mc_count == 0) {
- /* just broadcast and directed */
- } else {
- /* We use the 20 byte dev->data
- * for our 8 byte filter buffer
- * to avoid allocating memory that
- * is tricky to free later */
- struct dev_mc_list *mc_list = net->mc_list;
- u32 crc_bits;
- int i;
-
- memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
-
- /* Build the multicast hash filter. */
- for (i = 0; i < net->mc_count; i++) {
- crc_bits =
- ether_crc(ETH_ALEN,
- mc_list->dmi_addr) >> 26;
- data->multi_filter[crc_bits >> 3] |=
- 1 << (crc_bits & 7);
- mc_list = mc_list->next;
- }
-
- ax8817x_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);
-}
-
-static int ax8817x_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, (__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
-
- return res & 0xffff;
-}
-
-static void ax8817x_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, (__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
-}
-
-static int ax88172_link_reset(struct usbnet *dev)
-{
- u16 lpa;
- u8 mode;
-
- mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
- lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
- if (lpa & LPA_DUPLEX)
- mode |= AX_MEDIUM_FULL_DUPLEX;
- ax8817x_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)
-{
- struct usbnet *dev = netdev_priv(net);
- u8 opt;
-
- if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
- wolinfo->supported = 0;
- wolinfo->wolopts = 0;
- return;
- }
- wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
- wolinfo->wolopts = 0;
- if (opt & AX_MONITOR_MODE) {
- if (opt & AX_MONITOR_LINK)
- wolinfo->wolopts |= WAKE_PHY;
- if (opt & AX_MONITOR_MAGIC)
- wolinfo->wolopts |= WAKE_MAGIC;
- }
-}
-
-static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-{
- struct usbnet *dev = netdev_priv(net);
- u8 opt = 0;
- u8 buf[1];
-
- if (wolinfo->wolopts & WAKE_PHY)
- opt |= AX_MONITOR_LINK;
- if (wolinfo->wolopts & WAKE_MAGIC)
- opt |= AX_MONITOR_MAGIC;
- if (opt != 0)
- opt |= AX_MONITOR_MODE;
-
- if (ax8817x_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)
-{
- return AX_EEPROM_LEN;
-}
-
-static int ax8817x_get_eeprom(struct net_device *net,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct usbnet *dev = netdev_priv(net);
- u16 *ebuf = (u16 *)data;
- int i;
-
- /* Crude hack to ensure that we don't overwrite memory
- * if an odd length is supplied
- */
- if (eeprom->len % 2)
- return -EINVAL;
-
- eeprom->magic = AX_EEPROM_MAGIC;
-
- /* 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,
- eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
- return -EINVAL;
- }
- return 0;
-}
-
-static void ax8817x_get_drvinfo (struct net_device *net,
- struct ethtool_drvinfo *info)
-{
- /* Inherit standard device info */
- usbnet_get_drvinfo(net, info);
- info->eedump_len = 0x3e;
-}
-
-static int ax8817x_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)
-{
- struct usbnet *dev = netdev_priv(net);
-
- return mii_ethtool_sset(&dev->mii,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,
- .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,
-};
-
-static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
-{
- int ret = 0;
- void *buf;
- int i;
- unsigned long gpio_bits = dev->driver_info->data;
-
- get_endpoints(dev,intf);
-
- buf = kmalloc(ETH_ALEN, GFP_KERNEL);
- if(!buf) {
- ret = -ENOMEM;
- goto out1;
- }
-
- /* 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,
- (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);
- goto out2;
- }
-
- /* Get the MAC address */
- memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_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.phy_id_mask = 0x3f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = *((u8 *)buf + 1);
-
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax8817x_ethtool_ops;
-
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- mii_nway_restart(&dev->mii);
-
- return 0;
-out2:
- kfree(buf);
-out1:
- return ret;
-}
-
-static struct ethtool_ops ax88772_ethtool_ops = {
- .get_drvinfo = ax8817x_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,
-};
-
-static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
-{
- int ret;
- void *buf;
-
- get_endpoints(dev,intf);
-
- buf = kmalloc(6, GFP_KERNEL);
- if(!buf) {
- dbg ("Cannot allocate memory for buffer");
- ret = -ENOMEM;
- goto out1;
- }
-
- if ((ret = ax8817x_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, 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);
- 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);
- 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);
- 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);
- goto out2;
- }
-
- /* Get the MAC address */
- memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_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);
- goto out2;
- }
-
- if (((ret =
- ax8817x_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);
- 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.phy_id_mask = 0xff;
- dev->mii.reg_num_mask = 0xff;
-
- /* 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);
- 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);
- goto out2;
- }
- msleep(150);
-
-
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax88772_ethtool_ops;
-
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write(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, 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, 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);
- 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);
- goto out2;
- }
-
- kfree(buf);
-
- return 0;
-
-out2:
- kfree(buf);
-out1:
- return ret;
-}
-
-static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-{
- u32 *header;
- char *packet;
- struct sk_buff *ax_skb;
- u16 size;
-
- header = (u32 *) skb->data;
- le32_to_cpus(header);
- packet = (char *)(header + 1);
-
- skb_pull(skb, 4);
-
- while (skb->len > 0) {
- if ((short)(*header & 0x0000ffff) !=
- ~((short)((*header & 0xffff0000) >> 16))) {
- devdbg(dev,"header length data is error");
- }
- /* get the packet length */
- size = (u16) (*header & 0x0000ffff);
-
- if ((skb->len) - ((size + 1) & 0xfffe) == 0)
- return 2;
- if (size > ETH_FRAME_LEN) {
- devdbg(dev,"invalid rx length %d", size);
- return 0;
- }
- ax_skb = skb_clone(skb, GFP_ATOMIC);
- if (ax_skb) {
- ax_skb->len = size;
- ax_skb->data = packet;
- ax_skb->tail = packet + size;
- skb_return(dev, ax_skb);
- } else {
- return 0;
- }
-
- skb_pull(skb, (size + 1) & 0xfffe);
-
- if (skb->len == 0)
- break;
-
- header = (u32 *) skb->data;
- le32_to_cpus(header);
- packet = (char *)(header + 1);
- skb_pull(skb, 4);
- }
-
- if (skb->len < 0) {
- devdbg(dev,"invalid rx length %d", skb->len);
- return 0;
- }
- return 1;
-}
-
-static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- int flags)
-{
- int padlen;
- int headroom = skb_headroom(skb);
- int tailroom = skb_tailroom(skb);
- u32 *packet_len;
- u32 *padbytes_ptr;
-
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
-
- if ((!skb_cloned(skb))
- && ((headroom + tailroom) >= (4 + padlen))) {
- if ((headroom < 4) || (tailroom < padlen)) {
- skb->data = memmove(skb->head + 4, skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- }
- } else {
- struct sk_buff *skb2;
- skb2 = skb_copy_expand(skb, 4, padlen, flags);
- dev_kfree_skb_any(skb);
- skb = skb2;
- if (!skb)
- return NULL;
- }
-
- packet_len = (u32 *) skb_push(skb, 4);
-
- packet_len = (u32 *) skb->data;
- *packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-
- if ((skb->len % 512) == 0) {
- padbytes_ptr = (u32 *) skb->tail;
- *padbytes_ptr = 0xffff0000;
- skb_put(skb, padlen);
- }
- return skb;
-}
-
-static int ax88772_link_reset(struct usbnet *dev)
-{
- u16 lpa;
- u16 mode;
-
- mode = AX88772_MEDIUM_DEFAULT;
- lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
-
- if ((lpa & LPA_DUPLEX) == 0)
- mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
- if ((lpa & LPA_100) == 0)
- mode &= ~AX88772_MEDIUM_100MB;
- ax8817x_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,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x00130103,
-};
-
-static const struct driver_info dlink_dub_e100_info = {
- .description = "DLink DUB-E100 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x009f9d9f,
-};
-
-static const struct driver_info netgear_fa120_info = {
- .description = "Netgear FA-120 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x00130103,
-};
-
-static const struct driver_info hawking_uf200_info = {
- .description = "Hawking UF200 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x001f1d1f,
-};
-
-static const struct driver_info ax88772_info = {
- .description = "ASIX AX88772 USB 2.0 Ethernet",
- .bind = ax88772_bind,
- .status = ax8817x_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,
-};
-
-#endif /* CONFIG_USB_AX8817X */
-
-
-
-#ifdef CONFIG_USB_BELKIN
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller
- *
- * ... also two eTEK designs, including one sold as "Advance USBNET"
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info belkin_info = {
- .description = "Belkin, eTEK, or compatible",
-};
-
-#endif /* CONFIG_USB_BELKIN */
-
-
-
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class declarations.
- * Used by CDC Ethernet, and some CDC variants
- *
- *-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_CDCETHER
-#define NEED_GENERIC_CDC
-#endif
-
-#ifdef CONFIG_USB_ZAURUS
-/* Ethernet variant uses funky framing, broken ethernet addressing */
-#define NEED_GENERIC_CDC
-#endif
-
-#ifdef CONFIG_USB_RNDIS
-/* ACM variant uses even funkier framing, complex control RPC scheme */
-#define NEED_GENERIC_CDC
-#endif
-
-
-#ifdef NEED_GENERIC_CDC
-
-#include <linux/usb_cdc.h>
-
-struct cdc_state {
- struct usb_cdc_header_desc *header;
- struct usb_cdc_union_desc *u;
- struct usb_cdc_ether_desc *ether;
- struct usb_interface *control;
- struct usb_interface *data;
-};
-
-static struct usb_driver usbnet_driver;
-
-/*
- * probes control interface, claims data interface, collects the bulk
- * endpoints, activates data interface (if needed), maybe sets MTU.
- * all pure cdc, except for certain firmware workarounds.
- */
-static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- u8 *buf = intf->cur_altsetting->extra;
- int len = intf->cur_altsetting->extralen;
- struct usb_interface_descriptor *d;
- struct cdc_state *info = (void *) &dev->data;
- int status;
- int rndis;
-
- if (sizeof dev->data < sizeof *info)
- return -EDOM;
-
- /* expect strict spec conformance for the descriptors, but
- * cope with firmware which stores them in the wrong place
- */
- if (len == 0 && dev->udev->actconfig->extralen) {
- /* Motorola SB4100 (and others: Brad Hards says it's
- * from a Broadcom design) put CDC descriptors here
- */
- buf = dev->udev->actconfig->extra;
- len = dev->udev->actconfig->extralen;
- if (len)
- dev_dbg (&intf->dev,
- "CDC descriptors on config\n");
- }
-
- /* this assumes that if there's a non-RNDIS vendor variant
- * of cdc-acm, it'll fail RNDIS requests cleanly.
- */
- rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
-
- memset (info, 0, sizeof *info);
- info->control = intf;
- while (len > 3) {
- if (buf [1] != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* use bDescriptorSubType to identify the CDC descriptors.
- * We expect devices with CDC header and union descriptors.
- * For CDC Ethernet we need the ethernet descriptor.
- * For RNDIS, ignore two (pointless) CDC modem descriptors
- * in favor of a complicated OID-based RPC scheme doing what
- * CDC Ethernet achieves with a simple descriptor.
- */
- switch (buf [2]) {
- case USB_CDC_HEADER_TYPE:
- if (info->header) {
- dev_dbg (&intf->dev, "extra CDC header\n");
- goto bad_desc;
- }
- info->header = (void *) buf;
- if (info->header->bLength != sizeof *info->header) {
- dev_dbg (&intf->dev, "CDC header len %u\n",
- info->header->bLength);
- goto bad_desc;
- }
- break;
- case USB_CDC_UNION_TYPE:
- if (info->u) {
- dev_dbg (&intf->dev, "extra CDC union\n");
- goto bad_desc;
- }
- info->u = (void *) buf;
- if (info->u->bLength != sizeof *info->u) {
- dev_dbg (&intf->dev, "CDC union len %u\n",
- info->u->bLength);
- goto bad_desc;
- }
-
- /* we need a master/control interface (what we're
- * probed with) and a slave/data interface; union
- * descriptors sort this all out.
- */
- info->control = usb_ifnum_to_if(dev->udev,
- info->u->bMasterInterface0);
- info->data = usb_ifnum_to_if(dev->udev,
- info->u->bSlaveInterface0);
- if (!info->control || !info->data) {
- dev_dbg (&intf->dev,
- "master #%u/%p slave #%u/%p\n",
- info->u->bMasterInterface0,
- info->control,
- info->u->bSlaveInterface0,
- info->data);
- goto bad_desc;
- }
- if (info->control != intf) {
- dev_dbg (&intf->dev, "bogus CDC Union\n");
- /* Ambit USB Cable Modem (and maybe others)
- * interchanges master and slave interface.
- */
- if (info->data == intf) {
- info->data = info->control;
- info->control = intf;
- } else
- goto bad_desc;
- }
-
- /* a data interface altsetting does the real i/o */
- d = &info->data->cur_altsetting->desc;
- if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
- dev_dbg (&intf->dev, "slave class %u\n",
- d->bInterfaceClass);
- goto bad_desc;
- }
- break;
- case USB_CDC_ETHERNET_TYPE:
- if (info->ether) {
- dev_dbg (&intf->dev, "extra CDC ether\n");
- goto bad_desc;
- }
- info->ether = (void *) buf;
- if (info->ether->bLength != sizeof *info->ether) {
- dev_dbg (&intf->dev, "CDC ether len %u\n",
- info->ether->bLength);
- goto bad_desc;
- }
- dev->net->mtu = le16_to_cpup (
- &info->ether->wMaxSegmentSize)
- - ETH_HLEN;
- /* because of Zaurus, we may be ignoring the host
- * side link address we were given.
- */
- break;
- }
-next_desc:
- len -= buf [0]; /* bLength */
- buf += buf [0];
- }
-
- if (!info->header || !info->u || (!rndis && !info->ether)) {
- dev_dbg (&intf->dev, "missing cdc %s%s%sdescriptor\n",
- info->header ? "" : "header ",
- info->u ? "" : "union ",
- info->ether ? "" : "ether ");
- goto bad_desc;
- }
-
- /* claim data interface and set it up ... with side effects.
- * network traffic can't flow until an altsetting is enabled.
- */
- status = usb_driver_claim_interface (&usbnet_driver, info->data, dev);
- if (status < 0)
- return status;
- status = get_endpoints (dev, info->data);
- if (status < 0) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return status;
- }
-
- /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
- dev->status = NULL;
- if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
- struct usb_endpoint_descriptor *desc;
-
- dev->status = &info->control->cur_altsetting->endpoint [0];
- desc = &dev->status->desc;
- if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
- || !(desc->bEndpointAddress & USB_DIR_IN)
- || (le16_to_cpu(desc->wMaxPacketSize)
- < sizeof (struct usb_cdc_notification))
- || !desc->bInterval) {
- dev_dbg (&intf->dev, "bad notification endpoint\n");
- dev->status = NULL;
- }
- }
- if (rndis && !dev->status) {
- dev_dbg (&intf->dev, "missing RNDIS status endpoint\n");
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return -ENODEV;
- }
- return 0;
-
-bad_desc:
- dev_info (&dev->udev->dev, "bad CDC descriptors\n");
- return -ENODEV;
-}
-
-static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
-{
- struct cdc_state *info = (void *) &dev->data;
-
- /* disconnect master --> disconnect slave */
- if (intf == info->control && info->data) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- info->data = NULL;
- }
-
- /* and vice versa (just in case) */
- else if (intf == info->data && info->control) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->control, NULL);
- usb_driver_release_interface (&usbnet_driver, info->control);
- info->control = NULL;
- }
-}
-
-#endif /* NEED_GENERIC_CDC */
-
-
-#ifdef CONFIG_USB_CDCETHER
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class, Ethernet Control model
- *
- * Takes two interfaces. The DATA interface is inactive till an altsetting
- * is selected. Configuration data includes class descriptors.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with.
- *
- *-------------------------------------------------------------------------*/
-
-#include <linux/ctype.h>
-
-
-static void dumpspeed (struct usbnet *dev, __le32 *speeds)
-{
- if (netif_msg_timer (dev))
- devinfo (dev, "link speeds: %u kbps up, %u kbps down",
- __le32_to_cpu(speeds[0]) / 1000,
- __le32_to_cpu(speeds[1]) / 1000);
-}
-
-static void cdc_status (struct usbnet *dev, struct urb *urb)
-{
- struct usb_cdc_notification *event;
-
- if (urb->actual_length < sizeof *event)
- return;
-
- /* SPEED_CHANGE can get split into two 8-byte packets */
- if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) {
- dumpspeed (dev, (__le32 *) urb->transfer_buffer);
- return;
- }
-
- event = urb->transfer_buffer;
- switch (event->bNotificationType) {
- case USB_CDC_NOTIFY_NETWORK_CONNECTION:
- if (netif_msg_timer (dev))
- devdbg (dev, "CDC: carrier %s",
- event->wValue ? "on" : "off");
- if (event->wValue)
- netif_carrier_on(dev->net);
- else
- netif_carrier_off(dev->net);
- break;
- case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
- if (netif_msg_timer (dev))
- devdbg (dev, "CDC: speed change (len %d)",
- urb->actual_length);
- if (urb->actual_length != (sizeof *event + 8))
- set_bit (EVENT_STS_SPLIT, &dev->flags);
- else
- dumpspeed (dev, (__le32 *) &event[1]);
- break;
- // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */
- default:
- deverr (dev, "CDC: unexpected notification %02x!",
- event->bNotificationType);
- break;
- }
-}
-
-static u8 nibble (unsigned char c)
-{
- if (likely (isdigit (c)))
- return c - '0';
- c = toupper (c);
- if (likely (isxdigit (c)))
- return 10 + c - 'A';
- return 0;
-}
-
-static inline int
-get_ethernet_addr (struct usbnet *dev, struct usb_cdc_ether_desc *e)
-{
- int tmp, i;
- unsigned char buf [13];
-
- tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
- if (tmp != 12) {
- dev_dbg (&dev->udev->dev,
- "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp);
- if (tmp >= 0)
- tmp = -EINVAL;
- return tmp;
- }
- for (i = tmp = 0; i < 6; i++, tmp += 2)
- dev->net->dev_addr [i] =
- (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
- return 0;
-}
-
-static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- int status;
- struct cdc_state *info = (void *) &dev->data;
-
- status = generic_cdc_bind (dev, intf);
- if (status < 0)
- return status;
-
- status = get_ethernet_addr (dev, info->ether);
- if (status < 0) {
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return status;
- }
-
- /* FIXME cdc-ether has some multicast code too, though it complains
- * in routine cases. info->ether describes the multicast support.
- */
- return 0;
-}
-
-static const struct driver_info cdc_info = {
- .description = "CDC Ethernet Device",
- .flags = FLAG_ETHER,
- // .check_connect = cdc_check_connect,
- .bind = cdc_bind,
- .unbind = cdc_unbind,
- .status = cdc_status,
-};
-
-#endif /* CONFIG_USB_CDCETHER */
-
-
-
-#ifdef CONFIG_USB_EPSON2888
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * EPSON USB clients
- *
- * This is the same idea as Linux PDAs (below) except the firmware in the
- * device might not be Tux-powered. Epson provides reference firmware that
- * implements this interface. Product developers can reuse or modify that
- * code, such as by using their own product and vendor codes.
- *
- * Support was from Juro Bystricky <bystricky.juro@erd.epson.com>
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info epson2888_info = {
- .description = "Epson USB Device",
- .check_connect = always_connected,
-
- .in = 4, .out = 3,
-};
-
-#endif /* CONFIG_USB_EPSON2888 */
-
-
-#ifdef CONFIG_USB_GENESYS
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * GeneSys GL620USB-A (www.genesyslogic.com.tw)
- *
- * ... should partially interop with the Win32 driver for this hardware
- * The GeneSys docs imply there's some NDIS issue motivating this framing.
- *
- * Some info from GeneSys:
- * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk.
- * (Some cables, like the BAFO-100c, use the half duplex version.)
- * - For the full duplex model, the low bit of the version code says
- * which side is which ("left/right").
- * - For the half duplex type, a control/interrupt handshake settles
- * the transfer direction. (That's disabled here, partially coded.)
- * A control URB would block until other side writes an interrupt.
- *
- * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
- * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>.
- *
- *-------------------------------------------------------------------------*/
-
-// control msg write command
-#define GENELINK_CONNECT_WRITE 0xF0
-// interrupt pipe index
-#define GENELINK_INTERRUPT_PIPE 0x03
-// interrupt read buffer size
-#define INTERRUPT_BUFSIZE 0x08
-// interrupt pipe interval value
-#define GENELINK_INTERRUPT_INTERVAL 0x10
-// max transmit packet number per transmit
-#define GL_MAX_TRANSMIT_PACKETS 32
-// max packet length
-#define GL_MAX_PACKET_LEN 1514
-// max receive buffer size
-#define GL_RCV_BUF_SIZE \
- (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
-
-struct gl_packet {
- u32 packet_length;
- char packet_data [1];
-};
-
-struct gl_header {
- u32 packet_count;
- struct gl_packet packets;
-};
-
-#ifdef GENELINK_ACK
-
-// FIXME: this code is incomplete, not debugged; it doesn't
-// handle interrupts correctly. interrupts should be generic
-// code like all other device I/O, anyway.
-
-struct gl_priv {
- struct urb *irq_urb;
- char irq_buf [INTERRUPT_BUFSIZE];
-};
-
-static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
-{
- int retval;
-
- retval = usb_control_msg (dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- request,
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- value,
- 0, // index
- 0, // data buffer
- 0, // size
- CONTROL_TIMEOUT_MS);
- return retval;
-}
-
-static void gl_interrupt_complete (struct urb *urb, struct pt_regs *regs)
-{
- int status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
- }
-
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
-}
-
-static int gl_interrupt_read (struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
- int retval;
-
- // issue usb interrupt read
- if (priv && priv->irq_urb) {
- // submit urb
- if ((retval = usb_submit_urb (priv->irq_urb, GFP_KERNEL)) != 0)
- dbg ("gl_interrupt_read: submit fail - %X...", retval);
- else
- dbg ("gl_interrupt_read: submit success...");
- }
-
- return 0;
-}
-
-// check whether another side is connected
-static int genelink_check_connect (struct usbnet *dev)
-{
- int retval;
-
- dbg ("genelink_check_connect...");
-
- // detect whether another side is connected
- if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
- dbg ("%s: genelink_check_connect write fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- // usb interrupt read to ack another side
- if ((retval = gl_interrupt_read (dev)) != 0) {
- dbg ("%s: genelink_check_connect read fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- dbg ("%s: genelink_check_connect read success", dev->net->name);
- return 0;
-}
-
-// allocate and initialize the private data for genelink
-static int genelink_init (struct usbnet *dev)
-{
- struct gl_priv *priv;
-
- // allocate the private data structure
- if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
- dbg ("%s: cannot allocate private data per device",
- dev->net->name);
- return -ENOMEM;
- }
-
- // allocate irq urb
- if ((priv->irq_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
- dbg ("%s: cannot allocate private irq urb per device",
- dev->net->name);
- kfree (priv);
- return -ENOMEM;
- }
-
- // fill irq urb
- usb_fill_int_urb (priv->irq_urb, dev->udev,
- usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
- priv->irq_buf, INTERRUPT_BUFSIZE,
- gl_interrupt_complete, 0,
- GENELINK_INTERRUPT_INTERVAL);
-
- // set private data pointer
- dev->priv_data = priv;
-
- return 0;
-}
-
-// release the private data
-static int genelink_free (struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
-
- if (!priv)
- return 0;
-
-// FIXME: can't cancel here; it's synchronous, and
-// should have happened earlier in any case (interrupt
-// handling needs to be generic)
-
- // cancel irq urb first
- usb_kill_urb (priv->irq_urb);
-
- // free irq urb
- usb_free_urb (priv->irq_urb);
-
- // free the private data structure
- kfree (priv);
-
- return 0;
-}
-
-#endif
-
-static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
- struct gl_header *header;
- struct gl_packet *packet;
- struct sk_buff *gl_skb;
- u32 size;
-
- header = (struct gl_header *) skb->data;
-
- // get the packet count of the received skb
- le32_to_cpus (&header->packet_count);
- if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
- || (header->packet_count < 0)) {
- dbg ("genelink: invalid received packet count %d",
- header->packet_count);
- return 0;
- }
-
- // set the current packet pointer to the first packet
- packet = &header->packets;
-
- // decrement the length for the packet count size 4 bytes
- skb_pull (skb, 4);
-
- while (header->packet_count > 1) {
- // get the packet length
- size = packet->packet_length;
-
- // this may be a broken packet
- if (size > GL_MAX_PACKET_LEN) {
- dbg ("genelink: invalid rx length %d", size);
- return 0;
- }
-
- // allocate the skb for the individual packet
- gl_skb = alloc_skb (size, GFP_ATOMIC);
- if (gl_skb) {
-
- // copy the packet data to the new skb
- memcpy(skb_put(gl_skb, size), packet->packet_data, size);
- skb_return (dev, gl_skb);
- }
-
- // advance to the next packet
- packet = (struct gl_packet *)
- &packet->packet_data [size];
- header->packet_count--;
-
- // shift the data pointer to the next gl_packet
- skb_pull (skb, size + 4);
- }
-
- // skip the packet length field 4 bytes
- skb_pull (skb, 4);
-
- if (skb->len > GL_MAX_PACKET_LEN) {
- dbg ("genelink: invalid rx length %d", skb->len);
- return 0;
- }
- return 1;
-}
-
-static struct sk_buff *
-genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- int length = skb->len;
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
- u32 *packet_count;
- u32 *packet_len;
-
- // FIXME: magic numbers, bleech
- padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
-
- if ((!skb_cloned (skb))
- && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
- if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
- skb->data = memmove (skb->head + (4 + 4*1),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- }
- } else {
- struct sk_buff *skb2;
- skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
- dev_kfree_skb_any (skb);
- skb = skb2;
- if (!skb)
- return NULL;
- }
-
- // attach the packet count to the header
- packet_count = (u32 *) skb_push (skb, (4 + 4*1));
- packet_len = packet_count + 1;
-
- // FIXME little endian?
- *packet_count = 1;
- *packet_len = length;
-
- // add padding byte
- if ((skb->len % dev->maxpacket) == 0)
- skb_put (skb, 1);
-
- return skb;
-}
-
-static const struct driver_info genelink_info = {
- .description = "Genesys GeneLink",
- .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT,
- .rx_fixup = genelink_rx_fixup,
- .tx_fixup = genelink_tx_fixup,
-
- .in = 1, .out = 2,
-
-#ifdef GENELINK_ACK
- .check_connect =genelink_check_connect,
-#endif
-};
-
-#endif /* CONFIG_USB_GENESYS */
-
-
-
-#ifdef CONFIG_USB_NET1080
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Netchip 1080 driver ... http://www.netchip.com
- * Used in LapLink cables
- *
- *-------------------------------------------------------------------------*/
-
-#define dev_packet_id data[0]
-#define frame_errors data[1]
-
-/*
- * NetChip framing of ethernet packets, supporting additional error
- * checks for links that may drop bulk packets from inside messages.
- * Odd USB length == always short read for last usb packet.
- * - nc_header
- * - Ethernet header (14 bytes)
- * - payload
- * - (optional padding byte, if needed so length becomes odd)
- * - nc_trailer
- *
- * This framing is to be avoided for non-NetChip devices.
- */
-
-struct nc_header { // packed:
- __le16 hdr_len; // sizeof nc_header (LE, all)
- __le16 packet_len; // payload size (including ethhdr)
- __le16 packet_id; // detects dropped packets
-#define MIN_HEADER 6
-
- // all else is optional, and must start with:
- // u16 vendorId; // from usb-if
- // u16 productId;
-} __attribute__((__packed__));
-
-#define PAD_BYTE ((unsigned char)0xAC)
-
-struct nc_trailer {
- __le16 packet_id;
-} __attribute__((__packed__));
-
-// packets may use FLAG_FRAMING_NC and optional pad
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
- + sizeof (struct ethhdr) \
- + (mtu) \
- + 1 \
- + sizeof (struct nc_trailer))
-
-#define MIN_FRAMED FRAMED_SIZE(0)
-
-
-/*
- * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
- * before the hardware drops it. If that's done, the driver will need to
- * frame network packets to guard against the dropped USB packets. The win32
- * driver sets this for both sides of the link.
- */
-#define NC_READ_TTL_MS ((u8)255) // ms
-
-/*
- * We ignore most registers and EEPROM contents.
- */
-#define REG_USBCTL ((u8)0x04)
-#define REG_TTL ((u8)0x10)
-#define REG_STATUS ((u8)0x11)
-
-/*
- * Vendor specific requests to read/write data
- */
-#define REQUEST_REGISTER ((u8)0x10)
-#define REQUEST_EEPROM ((u8)0x11)
-
-static int
-nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
-{
- int status = usb_control_msg (dev->udev,
- usb_rcvctrlpipe (dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, regnum,
- retval_ptr, sizeof *retval_ptr,
- CONTROL_TIMEOUT_MS);
- if (status > 0)
- status = 0;
- if (!status)
- le16_to_cpus (retval_ptr);
- return status;
-}
-
-static inline int
-nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr)
-{
- return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr);
-}
-
-// no retval ... can become async, usable in_interrupt()
-static void
-nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
-{
- usb_control_msg (dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- req,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, regnum,
- NULL, 0, // data is in setup packet
- CONTROL_TIMEOUT_MS);
-}
-
-static inline void
-nc_register_write (struct usbnet *dev, u8 regnum, u16 value)
-{
- nc_vendor_write (dev, REQUEST_REGISTER, regnum, value);
-}
-
-
-#if 0
-static void nc_dump_registers (struct usbnet *dev)
-{
- u8 reg;
- u16 *vp = kmalloc (sizeof (u16));
-
- if (!vp) {
- dbg ("no memory?");
- return;
- }
-
- dbg ("%s registers:", dev->net->name);
- for (reg = 0; reg < 0x20; reg++) {
- int retval;
-
- // reading some registers is trouble
- if (reg >= 0x08 && reg <= 0xf)
- continue;
- if (reg >= 0x12 && reg <= 0x1e)
- continue;
-
- retval = nc_register_read (dev, reg, vp);
- if (retval < 0)
- dbg ("%s reg [0x%x] ==> error %d",
- dev->net->name, reg, retval);
- else
- dbg ("%s reg [0x%x] = 0x%x",
- dev->net->name, reg, *vp);
- }
- kfree (vp);
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Control register
- */
-
-#define USBCTL_WRITABLE_MASK 0x1f0f
-// bits 15-13 reserved, r/o
-#define USBCTL_ENABLE_LANG (1 << 12)
-#define USBCTL_ENABLE_MFGR (1 << 11)
-#define USBCTL_ENABLE_PROD (1 << 10)
-#define USBCTL_ENABLE_SERIAL (1 << 9)
-#define USBCTL_ENABLE_DEFAULTS (1 << 8)
-// bits 7-4 reserved, r/o
-#define USBCTL_FLUSH_OTHER (1 << 3)
-#define USBCTL_FLUSH_THIS (1 << 2)
-#define USBCTL_DISCONN_OTHER (1 << 1)
-#define USBCTL_DISCONN_THIS (1 << 0)
-
-static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
-{
- if (!netif_msg_link (dev))
- return;
- devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
- " this%s%s;"
- " other%s%s; r/o 0x%x",
- dev->udev->bus->bus_name, dev->udev->devpath,
- usbctl,
- (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
- (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
- (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
- (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
- (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
-
- (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
- (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
- (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
- (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
- usbctl & ~USBCTL_WRITABLE_MASK
- );
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Status register
- */
-
-#define STATUS_PORT_A (1 << 15)
-
-#define STATUS_CONN_OTHER (1 << 14)
-#define STATUS_SUSPEND_OTHER (1 << 13)
-#define STATUS_MAILBOX_OTHER (1 << 12)
-#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
-
-#define STATUS_CONN_THIS (1 << 6)
-#define STATUS_SUSPEND_THIS (1 << 5)
-#define STATUS_MAILBOX_THIS (1 << 4)
-#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
-
-#define STATUS_UNSPEC_MASK 0x0c8c
-#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
-
-
-static inline void nc_dump_status (struct usbnet *dev, u16 status)
-{
- if (!netif_msg_link (dev))
- return;
- devdbg (dev, "net1080 %s-%s status 0x%x:"
- " this (%c) PKT=%d%s%s%s;"
- " other PKT=%d%s%s%s; unspec 0x%x",
- dev->udev->bus->bus_name, dev->udev->devpath,
- status,
-
- // XXX the packet counts don't seem right
- // (1 at reset, not 0); maybe UNSPEC too
-
- (status & STATUS_PORT_A) ? 'A' : 'B',
- STATUS_PACKETS_THIS (status),
- (status & STATUS_CONN_THIS) ? " CON" : "",
- (status & STATUS_SUSPEND_THIS) ? " SUS" : "",
- (status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
-
- STATUS_PACKETS_OTHER (status),
- (status & STATUS_CONN_OTHER) ? " CON" : "",
- (status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
- (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
-
- status & STATUS_UNSPEC_MASK
- );
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * TTL register
- */
-
-#define TTL_THIS(ttl) (0x00ff & ttl)
-#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8))
-#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this))))
-
-static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
-{
- if (netif_msg_link (dev))
- devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
- dev->udev->bus->bus_name, dev->udev->devpath,
- ttl, TTL_THIS (ttl), TTL_OTHER (ttl));
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net1080_reset (struct usbnet *dev)
-{
- u16 usbctl, status, ttl;
- u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL);
- int retval;
-
- if (!vp)
- return -ENOMEM;
-
- // nc_dump_registers (dev);
-
- if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) {
- dbg ("can't read %s-%s status: %d",
- dev->udev->bus->bus_name, dev->udev->devpath, retval);
- goto done;
- }
- status = *vp;
- nc_dump_status (dev, status);
-
- if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
- dbg ("can't read USBCTL, %d", retval);
- goto done;
- }
- usbctl = *vp;
- nc_dump_usbctl (dev, usbctl);
-
- nc_register_write (dev, REG_USBCTL,
- USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
-
- if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) {
- dbg ("can't read TTL, %d", retval);
- goto done;
- }
- ttl = *vp;
- // nc_dump_ttl (dev, ttl);
-
- nc_register_write (dev, REG_TTL,
- MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
- dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
-
- if (netif_msg_link (dev))
- devinfo (dev, "port %c, peer %sconnected",
- (status & STATUS_PORT_A) ? 'A' : 'B',
- (status & STATUS_CONN_OTHER) ? "" : "dis"
- );
- retval = 0;
-
-done:
- kfree (vp);
- return retval;
-}
-
-static int net1080_check_connect (struct usbnet *dev)
-{
- int retval;
- u16 status;
- u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL);
-
- if (!vp)
- return -ENOMEM;
- retval = nc_register_read (dev, REG_STATUS, vp);
- status = *vp;
- kfree (vp);
- if (retval != 0) {
- dbg ("%s net1080_check_conn read - %d", dev->net->name, retval);
- return retval;
- }
- if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
- return -ENOLINK;
- return 0;
-}
-
-static void nc_flush_complete (struct urb *urb, struct pt_regs *regs)
-{
- kfree (urb->context);
- usb_free_urb(urb);
-}
-
-static void nc_ensure_sync (struct usbnet *dev)
-{
- dev->frame_errors++;
- if (dev->frame_errors > 5) {
- struct urb *urb;
- struct usb_ctrlrequest *req;
- int status;
-
- /* Send a flush */
- urb = usb_alloc_urb (0, SLAB_ATOMIC);
- if (!urb)
- return;
-
- req = kmalloc (sizeof *req, GFP_ATOMIC);
- if (!req) {
- usb_free_urb (urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT
- | USB_TYPE_VENDOR
- | USB_RECIP_DEVICE;
- req->bRequest = REQUEST_REGISTER;
- req->wValue = cpu_to_le16 (USBCTL_FLUSH_THIS
- | USBCTL_FLUSH_OTHER);
- req->wIndex = cpu_to_le16 (REG_USBCTL);
- req->wLength = cpu_to_le16 (0);
-
- /* queue an async control request, we don't need
- * to do anything when it finishes except clean up.
- */
- usb_fill_control_urb (urb, dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- (unsigned char *) req,
- NULL, 0,
- nc_flush_complete, req);
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status) {
- kfree (req);
- usb_free_urb (urb);
- return;
- }
-
- if (netif_msg_rx_err (dev))
- devdbg (dev, "flush net1080; too many framing errors");
- dev->frame_errors = 0;
- }
-}
-
-static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
- struct nc_header *header;
- struct nc_trailer *trailer;
- u16 hdr_len, packet_len;
-
- if (!(skb->len & 0x01)
- || MIN_FRAMED > skb->len
- || skb->len > FRAMED_SIZE (dev->net->mtu)) {
- dev->stats.rx_frame_errors++;
- dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
- (int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net->mtu),
- dev->net->mtu);
- nc_ensure_sync (dev);
- return 0;
- }
-
- header = (struct nc_header *) skb->data;
- hdr_len = le16_to_cpup (&header->hdr_len);
- packet_len = le16_to_cpup (&header->packet_len);
- if (FRAMED_SIZE (packet_len) > MAX_PACKET) {
- dev->stats.rx_frame_errors++;
- dbg ("packet too big, %d", packet_len);
- nc_ensure_sync (dev);
- return 0;
- } else if (hdr_len < MIN_HEADER) {
- dev->stats.rx_frame_errors++;
- dbg ("header too short, %d", hdr_len);
- nc_ensure_sync (dev);
- return 0;
- } else if (hdr_len > MIN_HEADER) {
- // out of band data for us?
- dbg ("header OOB, %d bytes", hdr_len - MIN_HEADER);
- nc_ensure_sync (dev);
- // switch (vendor/product ids) { ... }
- }
- skb_pull (skb, hdr_len);
-
- trailer = (struct nc_trailer *)
- (skb->data + skb->len - sizeof *trailer);
- skb_trim (skb, skb->len - sizeof *trailer);
-
- if ((packet_len & 0x01) == 0) {
- if (skb->data [packet_len] != PAD_BYTE) {
- dev->stats.rx_frame_errors++;
- dbg ("bad pad");
- return 0;
- }
- skb_trim (skb, skb->len - 1);
- }
- if (skb->len != packet_len) {
- dev->stats.rx_frame_errors++;
- dbg ("bad packet len %d (expected %d)",
- skb->len, packet_len);
- nc_ensure_sync (dev);
- return 0;
- }
- if (header->packet_id != get_unaligned (&trailer->packet_id)) {
- dev->stats.rx_fifo_errors++;
- dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- le16_to_cpu (header->packet_id),
- le16_to_cpu (trailer->packet_id));
- return 0;
- }
-#if 0
- devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
- header->packet_len, header->packet_id);
-#endif
- dev->frame_errors = 0;
- return 1;
-}
-
-static struct sk_buff *
-net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = ((skb->len + sizeof (struct nc_header)
- + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
- if (!skb_cloned (skb)) {
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
-
- if ((padlen + sizeof (struct nc_trailer)) <= tailroom
- && sizeof (struct nc_header) <= headroom)
- /* There's enough head and tail room */
- return skb;
-
- if ((sizeof (struct nc_header) + padlen
- + sizeof (struct nc_trailer)) <
- (headroom + tailroom)) {
- /* There's enough total room, so just readjust */
- skb->data = memmove (skb->head
- + sizeof (struct nc_header),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- return skb;
- }
- }
-
- /* Create a new skb to use with the correct size */
- skb2 = skb_copy_expand (skb,
- sizeof (struct nc_header),
- sizeof (struct nc_trailer) + padlen,
- flags);
- dev_kfree_skb_any (skb);
- return skb2;
-}
-
-static const struct driver_info net1080_info = {
- .description = "NetChip TurboCONNECT",
- .flags = FLAG_FRAMING_NC,
- .reset = net1080_reset,
- .check_connect =net1080_check_connect,
- .rx_fixup = net1080_rx_fixup,
- .tx_fixup = net1080_tx_fixup,
-};
-
-#endif /* CONFIG_USB_NET1080 */
-
-
-
-#ifdef CONFIG_USB_PL2301
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
- *
- * The protocol and handshaking used here should be bug-compatible
- * with the Linux 2.2 "plusb" driver, by Deti Fliegl.
- *
- *-------------------------------------------------------------------------*/
-
-/*
- * Bits 0-4 can be used for software handshaking; they're set from
- * one end, cleared from the other, "read" with the interrupt byte.
- */
-#define PL_S_EN (1<<7) /* (feature only) suspend enable */
-/* reserved bit -- rx ready (6) ? */
-#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */
-#define PL_RESET_OUT (1<<4) /* reset output pipe */
-#define PL_RESET_IN (1<<3) /* reset input pipe */
-#define PL_TX_C (1<<2) /* transmission complete */
-#define PL_TX_REQ (1<<1) /* transmission received */
-#define PL_PEER_E (1<<0) /* peer exists */
-
-static inline int
-pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
-{
- return usb_control_msg (dev->udev,
- usb_rcvctrlpipe (dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- val, index,
- NULL, 0,
- CONTROL_TIMEOUT_MS);
-}
-
-static inline int
-pl_clear_QuickLink_features (struct usbnet *dev, int val)
-{
- return pl_vendor_req (dev, 1, (u8) val, 0);
-}
-
-static inline int
-pl_set_QuickLink_features (struct usbnet *dev, int val)
-{
- return pl_vendor_req (dev, 3, (u8) val, 0);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pl_reset (struct usbnet *dev)
-{
- /* some units seem to need this reset, others reject it utterly.
- * FIXME be more like "naplink" or windows drivers.
- */
- (void) pl_set_QuickLink_features (dev,
- PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
- return 0;
-}
-
-static const struct driver_info prolific_info = {
- .description = "Prolific PL-2301/PL-2302",
- .flags = FLAG_NO_SETINT,
- /* some PL-2302 versions seem to fail usb_set_interface() */
- .reset = pl_reset,
-};
-
-#endif /* CONFIG_USB_PL2301 */
-
-
-#ifdef CONFIG_USB_KC2190
-#define HAVE_HARDWARE
-static const struct driver_info kc2190_info = {
- .description = "KC Technology KC-190",
-};
-#endif /* CONFIG_USB_KC2190 */
-
-
-#ifdef CONFIG_USB_ARMLINUX
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Intel's SA-1100 chip integrates basic USB support, and is used
- * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more.
- * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to
- * network using minimal USB framing data.
- *
- * This describes the driver currently in standard ARM Linux kernels.
- * The Zaurus uses a different driver (see later).
- *
- * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support
- * and different USB endpoint numbering than the SA1100 devices. The
- * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100
- * so we rely on the endpoint descriptors.
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info linuxdev_info = {
- .description = "Linux Device",
- .check_connect = always_connected,
-};
-
-static const struct driver_info yopy_info = {
- .description = "Yopy",
- .check_connect = always_connected,
-};
-
-static const struct driver_info blob_info = {
- .description = "Boot Loader OBject",
- .check_connect = always_connected,
-};
-
-#endif /* CONFIG_USB_ARMLINUX */
-
-
-#ifdef CONFIG_USB_ZAURUS
-#define HAVE_HARDWARE
-
-#include <linux/crc32.h>
-
-/*-------------------------------------------------------------------------
- *
- * Zaurus is also a SA-1110 based PDA, but one using a different driver
- * (and framing) for its USB slave/gadget controller than the case above.
- *
- * For the current version of that driver, the main way that framing is
- * nonstandard (also from perspective of the CDC ethernet model!) is a
- * crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around. Also, all Zaurii use the same
- * default Ethernet address.
- *
- * PXA based models use the same framing, and also can't implement
- * set_interface properly.
- *
- * All known Zaurii lie about their standards conformance. Most lie by
- * saying they support CDC Ethernet. Some lie and say they support CDC
- * MDLM (as if for access to cell phone modems). Someone, please beat
- * on Sharp (and other such vendors) for a while with a cluestick.
- *
- *-------------------------------------------------------------------------*/
-
-static struct sk_buff *
-zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = 2;
- if (!skb_cloned (skb)) {
- int tailroom = skb_tailroom (skb);
- if ((padlen + 4) <= tailroom)
- goto done;
- }
- skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags);
- dev_kfree_skb_any (skb);
- skb = skb2;
- if (skb) {
- u32 fcs;
-done:
- fcs = crc32_le (~0, skb->data, skb->len);
- fcs = ~fcs;
-
- *skb_put (skb, 1) = fcs & 0xff;
- *skb_put (skb, 1) = (fcs>> 8) & 0xff;
- *skb_put (skb, 1) = (fcs>>16) & 0xff;
- *skb_put (skb, 1) = (fcs>>24) & 0xff;
- }
- return skb;
-}
-
-static const struct driver_info zaurus_sl5x00_info = {
- .description = "Sharp Zaurus SL-5x00",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info)
-
-static const struct driver_info zaurus_pxa_info = {
- .description = "Sharp Zaurus, PXA-2xx based",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
-
-static const struct driver_info olympus_mxl_info = {
- .description = "Olympus R1000",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info)
-
-
-/* Some more recent products using Lineo/Belcarra code will wrongly claim
- * CDC MDLM conformance. They aren't conformant: data endpoints live
- * in the control interface, there's no data interface, and it's not used
- * to talk to a cell phone radio. But at least we can detect these two
- * pseudo-classes, rather than growing this product list with entries for
- * each new nonconformant product (sigh).
- */
-static const u8 safe_guid[16] = {
- 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
- 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-};
-static const u8 blan_guid[16] = {
- 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
- 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
-};
-
-static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- u8 *buf = intf->cur_altsetting->extra;
- int len = intf->cur_altsetting->extralen;
- struct usb_cdc_mdlm_desc *desc = NULL;
- struct usb_cdc_mdlm_detail_desc *detail = NULL;
-
- while (len > 3) {
- if (buf [1] != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* use bDescriptorSubType, and just verify that we get a
- * "BLAN" (or "SAFE") descriptor.
- */
- switch (buf [2]) {
- case USB_CDC_MDLM_TYPE:
- if (desc) {
- dev_dbg (&intf->dev, "extra MDLM\n");
- goto bad_desc;
- }
- desc = (void *) buf;
- if (desc->bLength != sizeof *desc) {
- dev_dbg (&intf->dev, "MDLM len %u\n",
- desc->bLength);
- goto bad_desc;
- }
- /* expect bcdVersion 1.0, ignore */
- if (memcmp(&desc->bGUID, blan_guid, 16)
- && memcmp(&desc->bGUID, safe_guid, 16) ) {
- /* hey, this one might _really_ be MDLM! */
- dev_dbg (&intf->dev, "MDLM guid\n");
- goto bad_desc;
- }
- break;
- case USB_CDC_MDLM_DETAIL_TYPE:
- if (detail) {
- dev_dbg (&intf->dev, "extra MDLM detail\n");
- goto bad_desc;
- }
- detail = (void *) buf;
- switch (detail->bGuidDescriptorType) {
- case 0: /* "SAFE" */
- if (detail->bLength != (sizeof *detail + 2))
- goto bad_detail;
- break;
- case 1: /* "BLAN" */
- if (detail->bLength != (sizeof *detail + 3))
- goto bad_detail;
- break;
- default:
- goto bad_detail;
- }
-
- /* assuming we either noticed BLAN already, or will
- * find it soon, there are some data bytes here:
- * - bmNetworkCapabilities (unused)
- * - bmDataCapabilities (bits, see below)
- * - bPad (ignored, for PADAFTER -- BLAN-only)
- * bits are:
- * - 0x01 -- Zaurus framing (add CRC)
- * - 0x02 -- PADBEFORE (CRC includes some padding)
- * - 0x04 -- PADAFTER (some padding after CRC)
- * - 0x08 -- "fermat" packet mangling (for hw bugs)
- * the PADBEFORE appears not to matter; we interop
- * with devices that use it and those that don't.
- */
- if ((detail->bDetailData[1] & ~02) != 0x01) {
- /* bmDataCapabilites == 0 would be fine too,
- * but framing is minidriver-coupled for now.
- */
-bad_detail:
- dev_dbg (&intf->dev,
- "bad MDLM detail, %d %d %d\n",
- detail->bLength,
- detail->bDetailData[0],
- detail->bDetailData[2]);
- goto bad_desc;
- }
- break;
- }
-next_desc:
- len -= buf [0]; /* bLength */
- buf += buf [0];
- }
-
- if (!desc || !detail) {
- dev_dbg (&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
- desc ? "" : "func ",
- detail ? "" : "detail ");
- goto bad_desc;
- }
-
- /* There's probably a CDC Ethernet descriptor there, but we can't
- * rely on the Ethernet address it provides since not all vendors
- * bother to make it unique. Likewise there's no point in tracking
- * of the CDC event notifications.
- */
- return get_endpoints (dev, intf);
-
-bad_desc:
- dev_info (&dev->udev->dev, "unsupported MDLM descriptors\n");
- return -ENODEV;
-}
-
-static const struct driver_info bogus_mdlm_info = {
- .description = "pseudo-MDLM (BLAN) device",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .tx_fixup = zaurus_tx_fixup,
- .bind = blan_mdlm_bind,
-};
-
-#else
-
-/* blacklist all those devices */
-#define ZAURUS_STRONGARM_INFO 0
-#define ZAURUS_PXA_INFO 0
-#define OLYMPUS_MXL_INFO 0
-
-#endif
+EXPORT_SYMBOL_GPL(usbnet_skb_return);
/*-------------------------------------------------------------------------
@@ -2868,22 +230,12 @@ static const struct driver_info bogus_mdlm_info = {
static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
+ int ll_mtu = new_mtu + net->hard_header_len;
- if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
+ if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
return -EINVAL;
-#ifdef CONFIG_USB_NET1080
- if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
- if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
- return -EINVAL;
- }
-#endif
-#ifdef CONFIG_USB_GENESYS
- if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
- && new_mtu > GL_MAX_PACKET_LEN)
- return -EINVAL;
-#endif
// no second zero-length packet read wanted after mtu-sized packets
- if (((new_mtu + sizeof (struct ethhdr)) % dev->maxpacket) == 0)
+ if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
net->mtu = new_mtu;
return 0;
@@ -2903,19 +255,18 @@ static struct net_device_stats *usbnet_get_stats (struct net_device *net)
* completion callbacks. 2.5 should have fixed those bugs...
*/
-static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
+static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
{
- struct sk_buff_head *list = skb->list;
unsigned long flags;
- spin_lock_irqsave (&list->lock, flags);
- __skb_unlink (skb, list);
- spin_unlock (&list->lock);
- spin_lock (&dev->done.lock);
- __skb_queue_tail (&dev->done, skb);
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_unlink(skb, list);
+ spin_unlock(&list->lock);
+ spin_lock(&dev->done.lock);
+ __skb_queue_tail(&dev->done, skb);
if (dev->done.qlen == 1)
- tasklet_schedule (&dev->bh);
- spin_unlock_irqrestore (&dev->done.lock, flags);
+ tasklet_schedule(&dev->bh);
+ spin_unlock_irqrestore(&dev->done.lock, flags);
}
/* some work can't be done in tasklets, so we use keventd
@@ -2923,7 +274,7 @@ static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
* NOTE: annoying asymmetry: if it's active, schedule_work() fails,
* but tasklet_schedule() doesn't. hope the failure is rare.
*/
-static void defer_kevent (struct usbnet *dev, int work)
+void usbnet_defer_kevent (struct usbnet *dev, int work)
{
set_bit (work, &dev->flags);
if (!schedule_work (&dev->kevent))
@@ -2931,50 +282,24 @@ static void defer_kevent (struct usbnet *dev, int work)
else
devdbg (dev, "kevent %d scheduled", work);
}
+EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
/*-------------------------------------------------------------------------*/
static void rx_complete (struct urb *urb, struct pt_regs *regs);
-static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
+static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags)
{
struct sk_buff *skb;
struct skb_data *entry;
int retval = 0;
unsigned long lockflags;
- size_t size;
-
-#ifdef CONFIG_USB_NET1080
- if (dev->driver_info->flags & FLAG_FRAMING_NC)
- size = FRAMED_SIZE (dev->net->mtu);
- else
-#endif
-#ifdef CONFIG_USB_GENESYS
- if (dev->driver_info->flags & FLAG_FRAMING_GL)
- size = GL_RCV_BUF_SIZE;
- else
-#endif
-#ifdef CONFIG_USB_ZAURUS
- if (dev->driver_info->flags & FLAG_FRAMING_Z)
- size = 6 + (sizeof (struct ethhdr) + dev->net->mtu);
- else
-#endif
-#ifdef CONFIG_USB_RNDIS
- if (dev->driver_info->flags & FLAG_FRAMING_RN)
- size = RNDIS_MAX_TRANSFER;
- else
-#endif
-#ifdef CONFIG_USB_AX8817X
- if (dev->driver_info->flags & FLAG_FRAMING_AX)
- size = 2048;
- else
-#endif
- size = (sizeof (struct ethhdr) + dev->net->mtu);
+ size_t size = dev->rx_urb_size;
if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
if (netif_msg_rx_err (dev))
devdbg (dev, "no rx skb");
- defer_kevent (dev, EVENT_RX_MEMORY);
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return;
}
@@ -2988,7 +313,6 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
usb_fill_bulk_urb (urb, dev->udev, dev->in,
skb->data, size, rx_complete, skb);
- urb->transfer_flags |= URB_ASYNC_UNLINK;
spin_lock_irqsave (&dev->rxq.lock, lockflags);
@@ -2997,10 +321,10 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
case -EPIPE:
- defer_kevent (dev, EVENT_RX_HALT);
+ usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
case -ENOMEM:
- defer_kevent (dev, EVENT_RX_MEMORY);
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
break;
case -ENODEV:
if (netif_msg_ifdown (dev))
@@ -3038,7 +362,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
// else network stack removes extra byte if we forced a short packet
if (skb->len)
- skb_return (dev, skb);
+ usbnet_skb_return (dev, skb);
else {
if (netif_msg_rx_err (dev))
devdbg (dev, "drop");
@@ -3064,7 +388,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
switch (urb_status) {
// success
case 0:
- if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) {
+ if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
@@ -3079,7 +403,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
// storm, recovering as needed.
case -EPIPE:
dev->stats.rx_errors++;
- defer_kevent (dev, EVENT_RX_HALT);
+ usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
// software-driven interface shutdown
@@ -3120,7 +444,7 @@ block:
break;
}
- defer_bh (dev, skb);
+ defer_bh(dev, skb, &dev->rxq);
if (urb) {
if (netif_running (dev->net)
@@ -3321,55 +645,58 @@ done:
/*-------------------------------------------------------------------------*/
-static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
+/* ethtool methods; minidrivers may need to add some more, but
+ * they'll probably want to use this base set.
+ */
+
+void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{
struct usbnet *dev = netdev_priv(net);
+ /* REVISIT don't always return "usbnet" */
strncpy (info->driver, driver_name, sizeof info->driver);
strncpy (info->version, DRIVER_VERSION, sizeof info->version);
strncpy (info->fw_version, dev->driver_info->description,
sizeof info->fw_version);
usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
}
+EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
static u32 usbnet_get_link (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- /* If a check_connect is defined, return it's results */
+ /* If a check_connect is defined, return its result */
if (dev->driver_info->check_connect)
return dev->driver_info->check_connect (dev) == 0;
- /* Otherwise, we're up to avoid breaking scripts */
+ /* Otherwise, say we're up (to avoid breaking scripts) */
return 1;
}
-static u32 usbnet_get_msglevel (struct net_device *net)
+u32 usbnet_get_msglevel (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
return dev->msg_enable;
}
+EXPORT_SYMBOL_GPL(usbnet_get_msglevel);
-static void usbnet_set_msglevel (struct net_device *net, u32 level)
+void usbnet_set_msglevel (struct net_device *net, u32 level)
{
struct usbnet *dev = netdev_priv(net);
dev->msg_enable = level;
}
+EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
-static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
-{
-#ifdef NEED_MII
- {
- struct usbnet *dev = netdev_priv(net);
-
- if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
- return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
- }
-#endif
- return -EOPNOTSUPP;
-}
+/* drivers may override default ethtool_ops in their bind() routine */
+static struct ethtool_ops usbnet_ethtool_ops = {
+ .get_drvinfo = usbnet_get_drvinfo,
+ .get_link = usbnet_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+};
/*-------------------------------------------------------------------------*/
@@ -3388,19 +715,24 @@ kevent (void *data)
if (test_bit (EVENT_TX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->txq);
status = usb_clear_halt (dev->udev, dev->out);
- if (status < 0 && status != -EPIPE) {
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
if (netif_msg_tx_err (dev))
deverr (dev, "can't clear tx halt, status %d",
status);
} else {
clear_bit (EVENT_TX_HALT, &dev->flags);
- netif_wake_queue (dev->net);
+ if (status != -ESHUTDOWN)
+ netif_wake_queue (dev->net);
}
}
if (test_bit (EVENT_RX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->rxq);
status = usb_clear_halt (dev->udev, dev->in);
- if (status < 0 && status != -EPIPE) {
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
if (netif_msg_rx_err (dev))
deverr (dev, "can't clear rx halt, status %d",
status);
@@ -3459,7 +791,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
switch (urb->status) {
case -EPIPE:
- defer_kevent (dev, EVENT_TX_HALT);
+ usbnet_defer_kevent (dev, EVENT_TX_HALT);
break;
/* software-driven interface shutdown */
@@ -3490,7 +822,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
urb->dev = NULL;
entry->state = tx_done;
- defer_bh (dev, skb);
+ defer_bh(dev, skb, &dev->txq);
}
/*-------------------------------------------------------------------------*/
@@ -3516,10 +848,6 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
struct skb_data *entry;
struct driver_info *info = dev->driver_info;
unsigned long flags;
-#ifdef CONFIG_USB_NET1080
- struct nc_header *header = NULL;
- struct nc_trailer *trailer = NULL;
-#endif /* CONFIG_USB_NET1080 */
// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
@@ -3545,24 +873,8 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
entry->state = tx_start;
entry->length = length;
- // FIXME: reorganize a bit, so that fixup() fills out NetChip
- // framing too. (Packet ID update needs the spinlock...)
- // [ BETTER: we already own net->xmit_lock, that's enough ]
-
-#ifdef CONFIG_USB_NET1080
- if (info->flags & FLAG_FRAMING_NC) {
- header = (struct nc_header *) skb_push (skb, sizeof *header);
- header->hdr_len = cpu_to_le16 (sizeof (*header));
- header->packet_len = cpu_to_le16 (length);
- if (!((skb->len + sizeof *trailer) & 0x01))
- *skb_put (skb, 1) = PAD_BYTE;
- trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
- }
-#endif /* CONFIG_USB_NET1080 */
-
usb_fill_bulk_urb (urb, dev->udev, dev->out,
skb->data, skb->len, tx_complete, skb);
- urb->transfer_flags |= URB_ASYNC_UNLINK;
/* don't assume the hardware handles USB_ZERO_PACKET
* NOTE: strictly conforming cdc-ether devices should expect
@@ -3575,22 +887,10 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
spin_lock_irqsave (&dev->txq.lock, flags);
-#ifdef CONFIG_USB_NET1080
- if (info->flags & FLAG_FRAMING_NC) {
- header->packet_id = cpu_to_le16 ((u16)dev->dev_packet_id++);
- put_unaligned (header->packet_id, &trailer->packet_id);
-#if 0
- devdbg (dev, "frame >tx h %d p %d id %d",
- header->hdr_len, header->packet_len,
- header->packet_id);
-#endif
- }
-#endif /* CONFIG_USB_NET1080 */
-
switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) {
case -EPIPE:
netif_stop_queue (net);
- defer_kevent (dev, EVENT_TX_HALT);
+ usbnet_defer_kevent (dev, EVENT_TX_HALT);
break;
default:
if (netif_msg_tx_err (dev))
@@ -3693,7 +993,7 @@ static void usbnet_bh (unsigned long param)
// precondition: never called in_interrupt
-static void usbnet_disconnect (struct usb_interface *intf)
+void usbnet_disconnect (struct usb_interface *intf)
{
struct usbnet *dev;
struct usb_device *xdev;
@@ -3707,7 +1007,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
xdev = interface_to_usbdev (intf);
if (netif_msg_probe (dev))
- devinfo (dev, "unregister usbnet usb-%s-%s, %s",
+ devinfo (dev, "unregister '%s' usb-%s-%s, %s",
+ intf->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description);
@@ -3723,15 +1024,14 @@ static void usbnet_disconnect (struct usb_interface *intf)
free_netdev(net);
usb_put_dev (xdev);
}
+EXPORT_SYMBOL_GPL(usbnet_disconnect);
/*-------------------------------------------------------------------------*/
-static struct ethtool_ops usbnet_ethtool_ops;
-
// precondition: never called in_interrupt
-static int
+int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
struct usbnet *dev;
@@ -3780,6 +1080,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
strcpy (net->name, "usb%d");
memcpy (net->dev_addr, node_id, sizeof node_id);
+ /* rx and tx sides can use different message sizes;
+ * bind() should set rx_urb_size in that case.
+ */
+ dev->hard_mtu = net->mtu + net->hard_header_len;
#if 0
// dma_supported() is deeply broken on almost all architectures
// possible with some EHCI controllers
@@ -3794,7 +1098,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
net->stop = usbnet_stop;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
net->tx_timeout = usbnet_tx_timeout;
- net->do_ioctl = usbnet_ioctl;
net->ethtool_ops = &usbnet_ethtool_ops;
// allow device-specific bind/init procedures
@@ -3807,8 +1110,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if ((dev->driver_info->flags & FLAG_ETHER) != 0
&& (net->dev_addr [0] & 0x02) == 0)
strcpy (net->name, "eth%d");
- } else if (!info->in || info->out)
- status = get_endpoints (dev, udev);
+
+ /* maybe the remote can't receive an Ethernet MTU */
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
+ net->mtu = dev->hard_mtu - net->hard_header_len;
+ } else if (!info->in || !info->out)
+ status = usbnet_get_endpoints (dev, udev);
else {
dev->in = usb_rcvbulkpipe (xdev, info->in);
dev->out = usb_sndbulkpipe (xdev, info->out);
@@ -3820,12 +1127,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
-
if (status == 0 && dev->status)
status = init_status (dev, udev);
if (status < 0)
goto out1;
+ if (!dev->rx_urb_size)
+ dev->rx_urb_size = dev->hard_mtu;
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
SET_NETDEV_DEV(net, &udev->dev);
@@ -3833,8 +1141,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if (status)
goto out3;
if (netif_msg_probe (dev))
- devinfo (dev, "register usbnet at usb-%s-%s, %s, "
+ devinfo (dev, "register '%s' at usb-%s-%s, %s, "
"%02x:%02x:%02x:%02x:%02x:%02x",
+ udev->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description,
net->dev_addr [0], net->dev_addr [1],
@@ -3858,12 +1167,15 @@ out:
usb_put_dev(xdev);
return status;
}
+EXPORT_SYMBOL_GPL(usbnet_probe);
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_PM
+/* FIXME these suspend/resume methods assume non-CDC style
+ * devices, with only one interface.
+ */
-static int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
+int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -3876,8 +1188,9 @@ static int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
intf->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_suspend);
-static int usbnet_resume (struct usb_interface *intf)
+int usbnet_resume (struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -3886,357 +1199,27 @@ static int usbnet_resume (struct usb_interface *intf)
tasklet_schedule (&dev->bh);
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_resume);
-#else /* !CONFIG_PM */
-
-#define usbnet_suspend NULL
-#define usbnet_resume NULL
-
-#endif /* CONFIG_PM */
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef HAVE_HARDWARE
-#error You need to configure some hardware for this driver
-#endif
-
-/*
- * chip vendor names won't normally be on the cables, and
- * may not be on the device.
- */
-
-static const struct usb_device_id products [] = {
-
-#ifdef CONFIG_USB_ALI_M5632
-{
- USB_DEVICE (0x0402, 0x5632), // ALi defaults
- .driver_info = (unsigned long) &ali_m5632_info,
-},
-#endif
-
-#ifdef CONFIG_USB_AN2720
-{
- USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
- .driver_info = (unsigned long) &an2720_info,
-}, {
- USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
- .driver_info = (unsigned long) &an2720_info,
-},
-#endif
-
-#ifdef CONFIG_USB_BELKIN
-{
- USB_DEVICE (0x050d, 0x0004), // Belkin
- .driver_info = (unsigned long) &belkin_info,
-}, {
- USB_DEVICE (0x056c, 0x8100), // eTEK
- .driver_info = (unsigned long) &belkin_info,
-}, {
- USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK)
- .driver_info = (unsigned long) &belkin_info,
-},
-#endif
-
-#ifdef CONFIG_USB_AX8817X
-{
- // Linksys USB200M
- USB_DEVICE (0x077b, 0x2226),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Netgear FA120
- USB_DEVICE (0x0846, 0x1040),
- .driver_info = (unsigned long) &netgear_fa120_info,
-}, {
- // DLink DUB-E100
- USB_DEVICE (0x2001, 0x1a00),
- .driver_info = (unsigned long) &dlink_dub_e100_info,
-}, {
- // Intellinet, ST Lab USB Ethernet
- USB_DEVICE (0x0b95, 0x1720),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Hawking UF200, TrendNet TU2-ET100
- USB_DEVICE (0x07b8, 0x420a),
- .driver_info = (unsigned long) &hawking_uf200_info,
-}, {
- // Billionton Systems, USB2AR
- USB_DEVICE (0x08dd, 0x90ff),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // ATEN UC210T
- USB_DEVICE (0x0557, 0x2009),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Buffalo LUA-U2-KTX
- USB_DEVICE (0x0411, 0x003d),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
- USB_DEVICE (0x6189, 0x182d),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // corega FEther USB2-TX
- USB_DEVICE (0x07aa, 0x0017),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Surecom EP-1427X-2
- USB_DEVICE (0x1189, 0x0893),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // goodway corp usb gwusb2e
- USB_DEVICE (0x1631, 0x6200),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // ASIX AX88772 10/100
- USB_DEVICE (0x0b95, 0x7720),
- .driver_info = (unsigned long) &ax88772_info,
-},
-#endif
-
-#ifdef CONFIG_USB_EPSON2888
-{
- USB_DEVICE (0x0525, 0x2888), // EPSON USB client
- .driver_info = (unsigned long) &epson2888_info,
-},
-#endif
-
-#ifdef CONFIG_USB_GENESYS
-{
- USB_DEVICE (0x05e3, 0x0502), // GL620USB-A
- .driver_info = (unsigned long) &genelink_info,
-},
- /* NOT: USB_DEVICE (0x05e3, 0x0501), // GL620USB
- * that's half duplex, not currently supported
- */
-#endif
-
-#ifdef CONFIG_USB_NET1080
-{
- USB_DEVICE (0x0525, 0x1080), // NetChip ref design
- .driver_info = (unsigned long) &net1080_info,
-}, {
- USB_DEVICE (0x06D0, 0x0622), // Laplink Gold
- .driver_info = (unsigned long) &net1080_info,
-},
-#endif
-
-#ifdef CONFIG_USB_PL2301
-{
- USB_DEVICE (0x067b, 0x0000), // PL-2301
- .driver_info = (unsigned long) &prolific_info,
-}, {
- USB_DEVICE (0x067b, 0x0001), // PL-2302
- .driver_info = (unsigned long) &prolific_info,
-},
-#endif
-
-#ifdef CONFIG_USB_KC2190
-{
- USB_DEVICE (0x050f, 0x0190), // KC-190
- .driver_info = (unsigned long) &kc2190_info,
-},
-#endif
-
-#ifdef CONFIG_USB_RNDIS
-{
- /* RNDIS is MSFT's un-official variant of CDC ACM */
- USB_INTERFACE_INFO (USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
- .driver_info = (unsigned long) &rndis_info,
-},
-#endif
-
-#ifdef CONFIG_USB_ARMLINUX
-/*
- * SA-1100 using standard ARM Linux kernels, or compatible.
- * Often used when talking to Linux PDAs (iPaq, Yopy, etc).
- * The sa-1100 "usb-eth" driver handles the basic framing.
- *
- * PXA25x or PXA210 ... these use a "usb-eth" driver much like
- * the sa1100 one, but hardware uses different endpoint numbers.
- *
- * Or the Linux "Ethernet" gadget on hardware that can't talk
- * CDC Ethernet (e.g., no altsettings), in either of two modes:
- * - acting just like the old "usb-eth" firmware, though
- * the implementation is different
- * - supporting RNDIS as the first/default configuration for
- * MS-Windows interop; Linux needs to use the other config
- */
-{
- // 1183 = 0x049F, both used as hex values?
- // Compaq "Itsy" vendor/product id
- USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible
- .driver_info = (unsigned long) &linuxdev_info,
-}, {
- USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy"
- .driver_info = (unsigned long) &yopy_info,
-}, {
- USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
- .driver_info = (unsigned long) &blob_info,
-}, {
- // Linux Ethernet/RNDIS gadget on pxa210/25x/26x
- // e.g. Gumstix, current OpenZaurus, ...
- USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
- .driver_info = (unsigned long) &linuxdev_info,
-},
-#endif
-
-#if defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_CDCETHER)
-/*
- * SA-1100 based Sharp Zaurus ("collie"), or compatible.
- * Same idea as above, but different framing.
- *
- * PXA-2xx based models are also lying-about-cdc.
- * Some models don't even tell the same lies ...
- *
- * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
- * unlike the older ones with 2.4 "embedix" kernels.
- *
- * NOTE: These entries do double-duty, serving as blacklist entries
- * whenever Zaurus support isn't enabled, but CDC Ethernet is.
- */
-#define ZAURUS_MASTER_INTERFACE \
- .bInterfaceClass = USB_CLASS_COMM, \
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
- .bInterfaceProtocol = USB_CDC_PROTO_NONE
-{
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8004,
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_STRONGARM_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8005, /* A-300 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8006, /* B-500/SL-5600 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8007, /* C-700 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x9031, /* C-750 C-760 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x9032, /* SL-6000 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- /* reported with some C860 units */
- .idProduct = 0x9050, /* C-860 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-},
-
-#ifdef CONFIG_USB_ZAURUS
- /* At least some (reports vary) PXA units have very different lies
- * about their standards support: they claim to be cell phones with
- * direct access to their radios. (They don't conform to CDC MDLM.)
- */
-{
- USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
- USB_CDC_PROTO_NONE),
- .driver_info = (unsigned long) &bogus_mdlm_info,
-},
-#endif
-
-/* Olympus has some models with a Zaurus-compatible option.
- * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
- */
-{
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x07B4,
- .idProduct = 0x0F02, /* R-1000 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = OLYMPUS_MXL_INFO,
-},
-#endif
-
-#ifdef CONFIG_USB_CDCETHER
-{
- /* CDC Ether uses two interfaces, not necessarily consecutive.
- * We match the main interface, ignoring the optional device
- * class so we could handle devices that aren't exclusively
- * CDC ether.
- *
- * NOTE: this match must come AFTER entries working around
- * bugs/quirks in a given product (like Zaurus, above).
- */
- USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
- USB_CDC_PROTO_NONE),
- .driver_info = (unsigned long) &cdc_info,
-},
-#endif
-
- { }, // END
-};
-MODULE_DEVICE_TABLE (usb, products);
-
-static struct usb_driver usbnet_driver = {
- .owner = THIS_MODULE,
- .name = driver_name,
- .id_table = products,
- .probe = usbnet_probe,
- .disconnect = usbnet_disconnect,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
-};
-
-/* Default ethtool_ops assigned. Devices can override in their bind() routine */
-static struct ethtool_ops usbnet_ethtool_ops = {
- .get_drvinfo = usbnet_get_drvinfo,
- .get_link = usbnet_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
-};
/*-------------------------------------------------------------------------*/
-static int __init usbnet_init (void)
+static int __init usbnet_init(void)
{
- // compiler should optimize these out
+ /* compiler should optimize this out */
BUG_ON (sizeof (((struct sk_buff *)0)->cb)
< sizeof (struct skb_data));
-#ifdef CONFIG_USB_CDCETHER
- BUG_ON ((sizeof (((struct usbnet *)0)->data)
- < sizeof (struct cdc_state)));
-#endif
random_ether_addr(node_id);
-
- return usb_register(&usbnet_driver);
+ return 0;
}
-module_init (usbnet_init);
+module_init(usbnet_init);
-static void __exit usbnet_exit (void)
+static void __exit usbnet_exit(void)
{
- usb_deregister (&usbnet_driver);
}
-module_exit (usbnet_exit);
+module_exit(usbnet_exit);
-MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (numerous vendors)");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB network driver framework");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
new file mode 100644
index 000000000000..7aa0abd1a9bd
--- /dev/null
+++ b/drivers/usb/net/usbnet.h
@@ -0,0 +1,193 @@
+/*
+ * USB Networking Link Interface
+ *
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.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
+ */
+
+
+#ifndef __USBNET_H
+#define __USBNET_H
+
+
+/* interface from usbnet core to each USB networking link we handle */
+struct usbnet {
+ /* housekeeping */
+ struct usb_device *udev;
+ struct driver_info *driver_info;
+ wait_queue_head_t *wait;
+
+ /* i/o info: pipes etc */
+ unsigned in, out;
+ struct usb_host_endpoint *status;
+ unsigned maxpacket;
+ struct timer_list delay;
+
+ /* protocol/interface state */
+ struct net_device *net;
+ struct net_device_stats stats;
+ int msg_enable;
+ unsigned long data [5];
+ u32 xid;
+ u32 hard_mtu; /* count any extra framing */
+ size_t rx_urb_size; /* size for rx urbs */
+ struct mii_if_info mii;
+
+ /* various kinds of pending driver work */
+ struct sk_buff_head rxq;
+ struct sk_buff_head txq;
+ struct sk_buff_head done;
+ struct urb *interrupt;
+ struct tasklet_struct bh;
+
+ struct work_struct kevent;
+ unsigned long flags;
+# define EVENT_TX_HALT 0
+# define EVENT_RX_HALT 1
+# define EVENT_RX_MEMORY 2
+# define EVENT_STS_SPLIT 3
+# define EVENT_LINK_RESET 4
+};
+
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
+{
+ return to_usb_driver(intf->dev.driver);
+}
+
+/* interface from the device/framing level "minidriver" to core */
+struct driver_info {
+ char *description;
+
+ int flags;
+/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
+#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
+#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
+#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
+
+#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
+#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
+
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+
+ /* init device ... can sleep, or cause probe() failure */
+ int (*bind)(struct usbnet *, struct usb_interface *);
+
+ /* cleanup device ... can sleep, but can't fail */
+ void (*unbind)(struct usbnet *, struct usb_interface *);
+
+ /* reset device ... can sleep */
+ int (*reset)(struct usbnet *);
+
+ /* see if peer is connected ... can sleep */
+ int (*check_connect)(struct usbnet *);
+
+ /* for status polling */
+ void (*status)(struct usbnet *, struct urb *);
+
+ /* link reset handling, called from defer_kevent */
+ int (*link_reset)(struct usbnet *);
+
+ /* fixup rx packet (strip framing) */
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+ /* fixup tx packet (add framing) */
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
+ struct sk_buff *skb, unsigned flags);
+
+ /* for new devices, use the descriptor-reading code instead */
+ int in; /* rx endpoint */
+ int out; /* tx endpoint */
+
+ unsigned long data; /* Misc driver specific data */
+};
+
+/* Minidrivers are just drivers using the "usbnet" core as a powerful
+ * network-specific subroutine library ... that happens to do pretty
+ * much everything except custom framing and chip-specific stuff.
+ */
+extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
+extern int usbnet_suspend (struct usb_interface *, pm_message_t );
+extern int usbnet_resume (struct usb_interface *);
+extern void usbnet_disconnect(struct usb_interface *);
+
+
+/* Drivers that reuse some of the standard USB CDC infrastructure
+ * (notably, using multiple interfaces according to the the CDC
+ * union descriptor) get some helper code.
+ */
+struct cdc_state {
+ struct usb_cdc_header_desc *header;
+ struct usb_cdc_union_desc *u;
+ struct usb_cdc_ether_desc *ether;
+ struct usb_interface *control;
+ struct usb_interface *data;
+};
+
+extern int usbnet_generic_cdc_bind (struct usbnet *, struct usb_interface *);
+extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
+
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* we record the state for each of our queued skbs */
+enum skb_state {
+ illegal = 0,
+ tx_start, tx_done,
+ rx_start, rx_done, rx_cleanup
+};
+
+struct skb_data { /* skb->cb is one of these */
+ struct urb *urb;
+ struct usbnet *dev;
+ enum skb_state state;
+ size_t length;
+};
+
+
+extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *);
+extern void usbnet_defer_kevent (struct usbnet *, int);
+extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
+
+extern u32 usbnet_get_msglevel (struct net_device *);
+extern void usbnet_set_msglevel (struct net_device *, u32);
+extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
+
+/* messaging support includes the interface name, so it must not be
+ * used before it has one ... notably, in minidriver bind() calls.
+ */
+#ifdef DEBUG
+#define devdbg(usbnet, fmt, arg...) \
+ printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#else
+#define devdbg(usbnet, fmt, arg...) do {} while(0)
+#endif
+
+#define deverr(usbnet, fmt, arg...) \
+ printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#define devwarn(usbnet, fmt, arg...) \
+ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+
+#define devinfo(usbnet, fmt, arg...) \
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
+
+
+#endif /* __USBNET_H */
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
new file mode 100644
index 000000000000..ee3b892aeabc
--- /dev/null
+++ b/drivers/usb/net/zaurus.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
+ * Copyright (C) 2002-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * All known Zaurii lie about their standards conformance. At least
+ * the earliest SA-1100 models lie by saying they support CDC Ethernet.
+ * Some later models (especially PXA-25x and PXA-27x based ones) lie
+ * and say they support CDC MDLM (for access to cell phone modems).
+ *
+ * There are non-Zaurus products that use these same protocols too.
+ *
+ * The annoying thing is that at the same time Sharp was developing
+ * that annoying standards-breaking software, the Linux community had
+ * a simple "CDC Subset" working reliably on the same SA-1100 hardware.
+ * That is, the same functionality but not violating standards.
+ *
+ * The CDC Ethernet nonconformance points are troublesome to hosts
+ * with a true CDC Ethernet implementation:
+ * - Framing appends a CRC, which the spec says drivers "must not" do;
+ * - Transfers data in altsetting zero, instead of altsetting 1;
+ * - All these peripherals use the same ethernet address.
+ *
+ * The CDC MDLM nonconformance is less immediately troublesome, since all
+ * MDLM implementations are quasi-proprietary anyway.
+ */
+
+static struct sk_buff *
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+
+ padlen = 2;
+ if (!skb_cloned(skb)) {
+ int tailroom = skb_tailroom(skb);
+ if ((padlen + 4) <= tailroom)
+ goto done;
+ }
+ skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (skb) {
+ u32 fcs;
+done:
+ fcs = crc32_le(~0, skb->data, skb->len);
+ fcs = ~fcs;
+
+ *skb_put (skb, 1) = fcs & 0xff;
+ *skb_put (skb, 1) = (fcs>> 8) & 0xff;
+ *skb_put (skb, 1) = (fcs>>16) & 0xff;
+ *skb_put (skb, 1) = (fcs>>24) & 0xff;
+ }
+ return skb;
+}
+
+static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ /* Belcarra's funky framing has other options; mostly
+ * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
+ */
+ dev->net->hard_header_len += 6;
+ dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
+ return usbnet_generic_cdc_bind(dev, intf);
+}
+
+/* PDA style devices are always connected if present */
+static int always_connected (struct usbnet *dev)
+{
+ return 0;
+}
+
+static const struct driver_info zaurus_sl5x00_info = {
+ .description = "Sharp Zaurus SL-5x00",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info)
+
+static const struct driver_info zaurus_pxa_info = {
+ .description = "Sharp Zaurus, PXA-2xx based",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
+
+static const struct driver_info olympus_mxl_info = {
+ .description = "Olympus R1000",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info)
+
+
+/* Some more recent products using Lineo/Belcarra code will wrongly claim
+ * CDC MDLM conformance. They aren't conformant: data endpoints live
+ * in the control interface, there's no data interface, and it's not used
+ * to talk to a cell phone radio. But at least we can detect these two
+ * pseudo-classes, rather than growing this product list with entries for
+ * each new nonconformant product (sigh).
+ */
+static const u8 safe_guid[16] = {
+ 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+ 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+};
+static const u8 blan_guid[16] = {
+ 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
+ 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
+};
+
+static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ u8 *buf = intf->cur_altsetting->extra;
+ int len = intf->cur_altsetting->extralen;
+ struct usb_cdc_mdlm_desc *desc = NULL;
+ struct usb_cdc_mdlm_detail_desc *detail = NULL;
+
+ while (len > 3) {
+ if (buf [1] != USB_DT_CS_INTERFACE)
+ goto next_desc;
+
+ /* use bDescriptorSubType, and just verify that we get a
+ * "BLAN" (or "SAFE") descriptor.
+ */
+ switch (buf [2]) {
+ case USB_CDC_MDLM_TYPE:
+ if (desc) {
+ dev_dbg(&intf->dev, "extra MDLM\n");
+ goto bad_desc;
+ }
+ desc = (void *) buf;
+ if (desc->bLength != sizeof *desc) {
+ dev_dbg(&intf->dev, "MDLM len %u\n",
+ desc->bLength);
+ goto bad_desc;
+ }
+ /* expect bcdVersion 1.0, ignore */
+ if (memcmp(&desc->bGUID, blan_guid, 16)
+ && memcmp(&desc->bGUID, safe_guid, 16) ) {
+ /* hey, this one might _really_ be MDLM! */
+ dev_dbg(&intf->dev, "MDLM guid\n");
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_MDLM_DETAIL_TYPE:
+ if (detail) {
+ dev_dbg(&intf->dev, "extra MDLM detail\n");
+ goto bad_desc;
+ }
+ detail = (void *) buf;
+ switch (detail->bGuidDescriptorType) {
+ case 0: /* "SAFE" */
+ if (detail->bLength != (sizeof *detail + 2))
+ goto bad_detail;
+ break;
+ case 1: /* "BLAN" */
+ if (detail->bLength != (sizeof *detail + 3))
+ goto bad_detail;
+ break;
+ default:
+ goto bad_detail;
+ }
+
+ /* assuming we either noticed BLAN already, or will
+ * find it soon, there are some data bytes here:
+ * - bmNetworkCapabilities (unused)
+ * - bmDataCapabilities (bits, see below)
+ * - bPad (ignored, for PADAFTER -- BLAN-only)
+ * bits are:
+ * - 0x01 -- Zaurus framing (add CRC)
+ * - 0x02 -- PADBEFORE (CRC includes some padding)
+ * - 0x04 -- PADAFTER (some padding after CRC)
+ * - 0x08 -- "fermat" packet mangling (for hw bugs)
+ * the PADBEFORE appears not to matter; we interop
+ * with devices that use it and those that don't.
+ */
+ if ((detail->bDetailData[1] & ~0x02) != 0x01) {
+ /* bmDataCapabilites == 0 would be fine too,
+ * but framing is minidriver-coupled for now.
+ */
+bad_detail:
+ dev_dbg(&intf->dev,
+ "bad MDLM detail, %d %d %d\n",
+ detail->bLength,
+ detail->bDetailData[0],
+ detail->bDetailData[2]);
+ goto bad_desc;
+ }
+ break;
+ }
+next_desc:
+ len -= buf [0]; /* bLength */
+ buf += buf [0];
+ }
+
+ if (!desc || !detail) {
+ dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
+ desc ? "" : "func ",
+ detail ? "" : "detail ");
+ goto bad_desc;
+ }
+
+ /* There's probably a CDC Ethernet descriptor there, but we can't
+ * rely on the Ethernet address it provides since not all vendors
+ * bother to make it unique. Likewise there's no point in tracking
+ * of the CDC event notifications.
+ */
+ return usbnet_get_endpoints(dev, intf);
+
+bad_desc:
+ dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n");
+ return -ENODEV;
+}
+
+static const struct driver_info bogus_mdlm_info = {
+ .description = "pseudo-MDLM (BLAN) device",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .tx_fixup = zaurus_tx_fixup,
+ .bind = blan_mdlm_bind,
+};
+
+static const struct usb_device_id products [] = {
+#define ZAURUS_MASTER_INTERFACE \
+ .bInterfaceClass = USB_CLASS_COMM, \
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8004,
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_STRONGARM_INFO,
+},
+
+/* PXA-2xx based models are also lying-about-cdc. If you add any
+ * more devices that claim to be CDC Ethernet, make sure they get
+ * added to the blacklist in cdc_ether too.
+ *
+ * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
+ * unlike the older ones with 2.4 "embedix" kernels.
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9031, /* C-750 C-760 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9032, /* SL-6000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9050, /* C-860 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+},
+
+
+/* At least some of the newest PXA units have very different lies about
+ * their standards support: they claim to be cell phones offering
+ * direct access to their radios! (No, they don't conform to CDC MDLM.)
+ */
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &bogus_mdlm_info,
+},
+
+/* Olympus has some models with a Zaurus-compatible option.
+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x07B4,
+ .idProduct = 0x0F02, /* R-1000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = OLYMPUS_MXL_INFO,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver zaurus_driver = {
+ .owner = THIS_MODULE,
+ .name = "zaurus",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init zaurus_init(void)
+{
+ return usb_register(&zaurus_driver);
+}
+module_init(zaurus_init);
+
+static void __exit zaurus_exit(void)
+{
+ usb_deregister(&zaurus_driver);
+}
+module_exit(zaurus_exit);
+
+MODULE_AUTHOR("Pavel Machek, David Brownell");
+MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index e32a80b39182..c4e479ee926a 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -21,7 +21,7 @@
#include <linux/string.h>
#include <linux/if_arp.h>
#include <linux/firmware.h>
-#include <ieee802_11.h>
+#include <net/ieee80211.h>
#include "zd1201.h"
static struct usb_device_id zd1201_table[] = {
@@ -338,24 +338,24 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
- if ((seq & IEEE802_11_SCTL_FRAG) ||
- (fc & IEEE802_11_FCTL_MOREFRAGS)) {
+ if ((seq & IEEE80211_SCTL_FRAG) ||
+ (fc & IEEE80211_FCTL_MOREFRAGS)) {
struct zd1201_frag *frag = NULL;
char *ptr;
if (datalen<14)
goto resubmit;
- if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
+ if ((seq & IEEE80211_SCTL_FRAG) == 0) {
frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
if (!frag)
goto resubmit;
- skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
+ skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
if (!skb) {
kfree(frag);
goto resubmit;
}
frag->skb = skb;
- frag->seq = seq & IEEE802_11_SCTL_SEQ;
+ frag->seq = seq & IEEE80211_SCTL_SEQ;
skb_reserve(skb, 2);
memcpy(skb_put(skb, 12), &data[datalen-14], 12);
memcpy(skb_put(skb, 2), &data[6], 2);
@@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
- if(frag->seq == (seq&IEEE802_11_SCTL_SEQ))
+ if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
break;
if (!frag)
goto resubmit;
@@ -372,7 +372,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
ptr = skb_put(skb, len);
if (ptr)
memcpy(ptr, data+8, len);
- if (fc & IEEE802_11_FCTL_MOREFRAGS)
+ if (fc & IEEE80211_FCTL_MOREFRAGS)
goto resubmit;
hlist_del_init(&frag->fnode);
kfree(frag);
@@ -847,7 +847,6 @@ static void zd1201_tx_timeout(struct net_device *dev)
return;
dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
dev->name);
- zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(zd->tx_urb);
zd->stats.tx_errors++;
/* Restart the timeout to quiet the watchdog: */
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 4ace9964fc6b..97c78c21e8d1 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.04"
+#define DRIVER_VERSION "v0.05"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
@@ -54,8 +54,11 @@ static void cp2101_shutdown(struct usb_serial*);
static int debug;
static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ } /* Terminating Entry */
};
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 012e63e05806..9ee1aaff2fcd 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -453,8 +453,8 @@ static int generic_startup (struct usb_serial *serial)
priv->cbr_mask = B300;
usb_set_serial_port_data(serial->port[0], priv);
- return (0);
-}
+ return 0;
+}
static int cypress_earthmate_startup (struct usb_serial *serial)
@@ -464,14 +464,15 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
+ dbg("%s - Failed setting up port %d", __FUNCTION__,
+ serial->port[0]->number);
return 1;
}
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_EARTHMATE;
-
- return (0);
+
+ return 0;
} /* cypress_earthmate_startup */
@@ -482,14 +483,15 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
+ dbg("%s - Failed setting up port %d", __FUNCTION__,
+ serial->port[0]->number);
return 1;
}
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_CYPHIDCOM;
- return (0);
+ return 0;
} /* cypress_hidcom_startup */
@@ -608,8 +610,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
timeout = max((HZ*2560)/bps,HZ/10);
else
timeout = 2*HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
+ schedule_timeout_interruptible(timeout);
dbg("%s - stopping urbs", __FUNCTION__);
usb_kill_urb (port->interrupt_in_urb);
@@ -909,7 +910,8 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
} /* cypress_ioctl */
-static void cypress_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void cypress_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
@@ -918,7 +920,7 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
unsigned long flags;
__u8 oldlines;
int linechange = 0;
-
+
dbg("%s - port %d", __FUNCTION__, port->number);
tty = port->tty;
@@ -931,10 +933,12 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
*(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ CLOCAL;
} else if (priv->chiptype == CT_CYPHIDCOM) {
*(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
}
priv->termios_initialized = 1;
}
@@ -946,12 +950,15 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
/* check if there are new settings */
if (old_termios) {
if ((cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - attempting to set new termios settings", __FUNCTION__);
- /* should make a copy of this in case something goes wrong in the function, we can restore it */
+ (RELEVANT_IFLAG(iflag) !=
+ RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg("%s - attempting to set new termios settings",
+ __FUNCTION__);
+ /* should make a copy of this in case something goes
+ * wrong in the function, we can restore it */
spin_lock_irqsave(&priv->lock, flags);
priv->tmp_termios = *(tty->termios);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
} else {
dbg("%s - nothing to do, exiting", __FUNCTION__);
return;
@@ -962,21 +969,34 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
/* set number of data bits, parity, stop bits */
/* when parity is disabled the parity type bit is ignored */
- stop_bits = cflag & CSTOPB ? 1 : 0; /* 1 means 2 stop bits, 0 means 1 stop bit */
-
+ /* 1 means 2 stop bits, 0 means 1 stop bit */
+ stop_bits = cflag & CSTOPB ? 1 : 0;
+
if (cflag & PARENB) {
parity_enable = 1;
- parity_type = cflag & PARODD ? 1 : 0; /* 1 means odd parity, 0 means even parity */
+ /* 1 means odd parity, 0 means even parity */
+ parity_type = cflag & PARODD ? 1 : 0;
} else
parity_enable = parity_type = 0;
if (cflag & CSIZE) {
switch (cflag & CSIZE) {
- case CS5: data_bits = 0; break;
- case CS6: data_bits = 1; break;
- case CS7: data_bits = 2; break;
- case CS8: data_bits = 3; break;
- default: err("%s - CSIZE was set, but not CS5-CS8", __FUNCTION__); data_bits = 3;
+ case CS5:
+ data_bits = 0;
+ break;
+ case CS6:
+ data_bits = 1;
+ break;
+ case CS7:
+ data_bits = 2;
+ break;
+ case CS8:
+ data_bits = 3;
+ break;
+ default:
+ err("%s - CSIZE was set, but not CS5-CS8",
+ __FUNCTION__);
+ data_bits = 3;
}
} else
data_bits = 3;
@@ -991,63 +1011,85 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
} else {
baud_mask = (cflag & CBAUD);
switch(baud_mask) {
- case B300: dbg("%s - setting baud 300bps", __FUNCTION__); break;
- case B600: dbg("%s - setting baud 600bps", __FUNCTION__); break;
- case B1200: dbg("%s - setting baud 1200bps", __FUNCTION__); break;
- case B2400: dbg("%s - setting baud 2400bps", __FUNCTION__); break;
- case B4800: dbg("%s - setting baud 4800bps", __FUNCTION__); break;
- case B9600: dbg("%s - setting baud 9600bps", __FUNCTION__); break;
- case B19200: dbg("%s - setting baud 19200bps", __FUNCTION__); break;
- case B38400: dbg("%s - setting baud 38400bps", __FUNCTION__); break;
- case B57600: dbg("%s - setting baud 57600bps", __FUNCTION__); break;
- case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break;
- default: dbg("%s - unknown masked baud rate", __FUNCTION__);
+ case B300:
+ dbg("%s - setting baud 300bps", __FUNCTION__);
+ break;
+ case B600:
+ dbg("%s - setting baud 600bps", __FUNCTION__);
+ break;
+ case B1200:
+ dbg("%s - setting baud 1200bps", __FUNCTION__);
+ break;
+ case B2400:
+ dbg("%s - setting baud 2400bps", __FUNCTION__);
+ break;
+ case B4800:
+ dbg("%s - setting baud 4800bps", __FUNCTION__);
+ break;
+ case B9600:
+ dbg("%s - setting baud 9600bps", __FUNCTION__);
+ break;
+ case B19200:
+ dbg("%s - setting baud 19200bps", __FUNCTION__);
+ break;
+ case B38400:
+ dbg("%s - setting baud 38400bps", __FUNCTION__);
+ break;
+ case B57600:
+ dbg("%s - setting baud 57600bps", __FUNCTION__);
+ break;
+ case B115200:
+ dbg("%s - setting baud 115200bps", __FUNCTION__);
+ break;
+ default:
+ dbg("%s - unknown masked baud rate", __FUNCTION__);
}
priv->line_control = (CONTROL_DTR | CONTROL_RTS);
}
spin_unlock_irqrestore(&priv->lock, flags);
-
- dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)", __FUNCTION__,
- stop_bits, parity_enable, parity_type, data_bits);
- cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
- parity_type, 0, CYPRESS_SET_CONFIG);
+ dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
+ "%d data_bits (+5)", __FUNCTION__, stop_bits,
+ parity_enable, parity_type, data_bits);
+
+ cypress_serial_control(port, baud_mask, data_bits, stop_bits,
+ parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
- /* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
- * this should confirm that all is working if it returns what we just set */
+ /* we perform a CYPRESS_GET_CONFIG so that the current settings are
+ * filled into the private structure this should confirm that all is
+ * working if it returns what we just set */
cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
- /* Here we can define custom tty settings for devices
- *
- * the main tty termios flag base comes from empeg.c
- */
+ /* Here we can define custom tty settings for devices; the main tty
+ * termios flag base comes from empeg.c */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
-
- dbg("Using custom termios settings for a baud rate of 4800bps.");
+ dbg("Using custom termios settings for a baud rate of "
+ "4800bps.");
/* define custom termios settings for NMEA protocol */
tty->termios->c_iflag /* input modes - */
- &= ~(IGNBRK /* disable ignore break */
- | BRKINT /* disable break causes interrupt */
- | PARMRK /* disable mark parity errors */
- | ISTRIP /* disable clear high bit of input characters */
- | INLCR /* disable translate NL to CR */
- | IGNCR /* disable ignore CR */
- | ICRNL /* disable translate CR to NL */
- | IXON); /* disable enable XON/XOFF flow control */
-
+ &= ~(IGNBRK /* disable ignore break */
+ | BRKINT /* disable break causes interrupt */
+ | PARMRK /* disable mark parity errors */
+ | ISTRIP /* disable clear high bit of input char */
+ | INLCR /* disable translate NL to CR */
+ | IGNCR /* disable ignore CR */
+ | ICRNL /* disable translate CR to NL */
+ | IXON); /* disable enable XON/XOFF flow control */
+
tty->termios->c_oflag /* output modes */
- &= ~OPOST; /* disable postprocess output characters */
-
- tty->termios->c_lflag /* line discipline modes */
- &= ~(ECHO /* disable echo input characters */
- | ECHONL /* disable echo new line */
- | ICANON /* disable erase, kill, werase, and rprnt special characters */
- | ISIG /* disable interrupt, quit, and suspend special characters */
- | IEXTEN); /* disable non-POSIX special characters */
+ &= ~OPOST; /* disable postprocess output char */
+ tty->termios->c_lflag /* line discipline modes */
+ &= ~(ECHO /* disable echo input characters */
+ | ECHONL /* disable echo new line */
+ | ICANON /* disable erase, kill, werase, and rprnt
+ special characters */
+ | ISIG /* disable interrupt, quit, and suspend
+ special characters */
+ | IEXTEN); /* disable non-POSIX special characters */
} /* CT_CYPHIDCOM: Application should handle this for device */
linechange = (priv->line_control != oldlines);
@@ -1060,7 +1102,7 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
}
} /* cypress_set_termios */
-
+
/* returns amount of data still left in soft buffer */
static int cypress_chars_in_buffer(struct usb_serial_port *port)
{
@@ -1088,7 +1130,7 @@ static void cypress_throttle (struct usb_serial_port *port)
spin_lock_irqsave(&priv->lock, flags);
priv->rx_flags = THROTTLED;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1110,7 +1152,8 @@ static void cypress_unthrottle (struct usb_serial_port *port)
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+ dev_err(&port->dev, "%s - failed submitting read urb, "
+ "error %d\n", __FUNCTION__, result);
}
}
@@ -1122,7 +1165,7 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
- char tty_flag = TTY_NORMAL;
+ char tty_flag = TTY_NORMAL;
int havedata = 0;
int bytes = 0;
int result;
@@ -1131,7 +1174,8 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) {
- dbg("%s - nonzero read status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero read status received: %d", __FUNCTION__,
+ urb->status);
return;
}
@@ -1155,51 +1199,55 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
case 32:
/* This is for the CY7C64013... */
priv->current_status = data[0] & 0xF8;
- bytes = data[1]+2;
- i=2;
+ bytes = data[1] + 2;
+ i = 2;
if (bytes > 2)
havedata = 1;
break;
case 8:
/* This is for the CY7C63743... */
priv->current_status = data[0] & 0xF8;
- bytes = (data[0] & 0x07)+1;
- i=1;
+ bytes = (data[0] & 0x07) + 1;
+ i = 1;
if (bytes > 1)
havedata = 1;
break;
default:
- dbg("%s - wrong packet size - received %d bytes", __FUNCTION__, urb->actual_length);
+ dbg("%s - wrong packet size - received %d bytes",
+ __FUNCTION__, urb->actual_length);
spin_unlock_irqrestore(&priv->lock, flags);
goto continue_read;
}
spin_unlock_irqrestore(&priv->lock, flags);
- usb_serial_debug_data (debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
+ urb->actual_length, data);
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
if (priv != NULL) {
if (priv->current_status != priv->prev_status) {
- priv->diff_status |= priv->current_status ^ priv->prev_status;
+ priv->diff_status |= priv->current_status ^
+ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = priv->current_status;
}
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
- /* hangup, as defined in acm.c... this might be a bad place for it though */
- if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) {
+ /* hangup, as defined in acm.c... this might be a bad place for it
+ * though */
+ if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ !(priv->current_status & UART_CD)) {
dbg("%s - calling hangup", __FUNCTION__);
tty_hangup(tty);
goto continue_read;
}
- /* There is one error bit... I'm assuming it is a parity error indicator
- * as the generic firmware will set this bit to 1 if a parity error occurs.
- * I can not find reference to any other error events.
- *
- */
+ /* There is one error bit... I'm assuming it is a parity error
+ * indicator as the generic firmware will set this bit to 1 if a
+ * parity error occurs.
+ * I can not find reference to any other error events. */
spin_lock_irqsave(&priv->lock, flags);
if (priv->current_status & CYP_ERROR) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1211,7 +1259,8 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
/* process read if there is data other than line status */
if (tty && (bytes > i)) {
for (; i < bytes ; ++i) {
- dbg("pushing byte number %d - %d - %c",i,data[i],data[i]);
+ dbg("pushing byte number %d - %d - %c", i, data[i],
+ data[i]);
if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
@@ -1221,25 +1270,28 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
}
spin_lock_irqsave(&priv->lock, flags);
- priv->bytes_in += bytes; /* control and status byte(s) are also counted */
+ /* control and status byte(s) are also counted */
+ priv->bytes_in += bytes;
spin_unlock_irqrestore(&priv->lock, flags);
continue_read:
-
- /* Continue trying to always read... unless the port has closed. */
+
+ /* Continue trying to always read... unless the port has closed. */
if (port->open_count > 0) {
- usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
- usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
- port->interrupt_in_urb->transfer_buffer,
- port->interrupt_in_urb->transfer_buffer_length,
- cypress_read_int_callback, port,
- interval);
- result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- if (result)
- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
+ usb_rcvintpipe(port->serial->dev,
+ port->interrupt_in_endpointAddress),
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
+ cypress_read_int_callback, port, interval);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting "
+ "read urb, error %d\n", __FUNCTION__,
+ result);
}
-
+
return;
} /* cypress_read_int_callback */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index d1964a0c4168..4e434cb10bb1 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -269,6 +269,8 @@
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
static int debug;
+static __u16 vendor = FTDI_VID;
+static __u16 product;
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
@@ -407,6 +409,34 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
+ /*
+ * These will probably use user-space drivers. Uncomment them if
+ * you need them or use the user-specified vendor/product module
+ * parameters (see ftdi_sio.h for the numbers). Make a fuss if
+ * you think the driver should recognize any of them by default.
+ */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -418,6 +448,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
+ { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
@@ -427,12 +458,21 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
- { } /* Terminating entry */
+ { }, /* Optional parameter entry */
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
@@ -874,7 +914,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
unsigned interfaces;
/* Assume it is not the original SIO device for now. */
- priv->baud_base = 48000000 / 16;
+ priv->baud_base = 48000000 / 2;
priv->write_offset = 0;
version = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -2030,6 +2070,15 @@ static int __init ftdi_init (void)
int retval;
dbg("%s", __FUNCTION__);
+ if (vendor > 0 && product > 0) {
+ /* Add user specified VID/PID to reserved element of table. */
+ int i;
+ for (i = 0; id_table_combined[i].idVendor; i++)
+ ;
+ id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ id_table_combined[i].idVendor = vendor;
+ id_table_combined[i].idProduct = product;
+ }
retval = usb_serial_register(&ftdi_sio_device);
if (retval)
goto failed_sio_register;
@@ -2066,4 +2115,9 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(vendor, ushort, 0);
+MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
+ __MODULE_STRING(FTDI_VID)")");
+module_param(product, ushort, 0);
+MODULE_PARM_DESC(vendor, "User specified product ID");
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 9f4342093e8b..2c35d74cc6d6 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -142,10 +142,43 @@
/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */
-/* ELV USB Module UO100 (PID sent by Stefan Frings) */
-#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
-/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
-#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */
+/*
+ * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
+ * All of these devices use FTDI's vendor ID (0x0403).
+ *
+ * The previously included PID for the UO 100 module was incorrect.
+ * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
+ *
+ * Armin Laeuger originally sent the PID for the UM 100 module.
+ */
+#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */
+#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */
+#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */
+#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */
+/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
+ * MS Windows, rather than the FTDI Virtual Com Port drivers.
+ * Maybe these will be easier to use with the libftdi/libusb user-space
+ * drivers, or possibly the Comedi drivers in some cases. */
+#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */
+#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */
+#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */
+#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */
+#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */
+#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */
+#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */
+#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */
+#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */
+#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */
+#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */
+#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */
+#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */
+#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
+#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */
+#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */
+#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */
+#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */
+#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */
+#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */
/*
* Definitions for ID TECH (www.idt-net.com) devices
@@ -222,6 +255,7 @@
*/
#define FALCOM_VID 0x0F94 /* Vendor Id */
#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */
+#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */
/*
* SUUNTO product ids
@@ -277,6 +311,18 @@
#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */
/*
+ * Xsens Technologies BV products (http://www.xsens.com).
+ */
+#define XSENS_CONVERTER_0_PID 0xD388
+#define XSENS_CONVERTER_1_PID 0xD389
+#define XSENS_CONVERTER_2_PID 0xD38A
+#define XSENS_CONVERTER_3_PID 0xD38B
+#define XSENS_CONVERTER_4_PID 0xD38C
+#define XSENS_CONVERTER_5_PID 0xD38D
+#define XSENS_CONVERTER_6_PID 0xD38E
+#define XSENS_CONVERTER_7_PID 0xD38F
+
+/*
* Evolution Robotics products (http://www.evolution.com/).
* Submitted by Shawn M. Lavelle.
*/
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index fb0926292228..3b958e60f5e8 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -383,11 +383,8 @@ static int keyspan_write(struct usb_serial_port *port,
dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) {
- if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
- break;
if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
break;
- this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb);
break;
}
@@ -402,7 +399,6 @@ static int keyspan_write(struct usb_serial_port *port,
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo + dataOffset;
- this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)", err);
@@ -1119,10 +1115,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
static inline void stop_urb(struct urb *urb)
{
- if (urb && urb->status == -EINPROGRESS) {
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ if (urb && urb->status == -EINPROGRESS)
usb_kill_urb(urb);
- }
}
static void keyspan_close(struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e9256408757f..92d0f925d053 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -45,29 +45,29 @@
#include "usb-serial.h"
/* Function prototypes */
-static int option_open (struct usb_serial_port *port, struct file *filp);
-static void option_close (struct usb_serial_port *port, struct file *filp);
-static int option_startup (struct usb_serial *serial);
-static void option_shutdown (struct usb_serial *serial);
-static void option_rx_throttle (struct usb_serial_port *port);
-static void option_rx_unthrottle (struct usb_serial_port *port);
-static int option_write_room (struct usb_serial_port *port);
+static int option_open(struct usb_serial_port *port, struct file *filp);
+static void option_close(struct usb_serial_port *port, struct file *filp);
+static int option_startup(struct usb_serial *serial);
+static void option_shutdown(struct usb_serial *serial);
+static void option_rx_throttle(struct usb_serial_port *port);
+static void option_rx_unthrottle(struct usb_serial_port *port);
+static int option_write_room(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
-static int option_write (struct usb_serial_port *port,
- const unsigned char *buf, int count);
+static int option_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
-static int option_chars_in_buffer (struct usb_serial_port *port);
-static int option_ioctl (struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static void option_set_termios (struct usb_serial_port *port,
- struct termios *old);
-static void option_break_ctl (struct usb_serial_port *port, int break_state);
-static int option_tiocmget (struct usb_serial_port *port, struct file *file);
-static int option_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear);
-static int option_send_setup (struct usb_serial_port *port);
+static int option_chars_in_buffer(struct usb_serial_port *port);
+static int option_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void option_set_termios(struct usb_serial_port *port,
+ struct termios *old);
+static void option_break_ctl(struct usb_serial_port *port, int break_state);
+static int option_tiocmget(struct usb_serial_port *port, struct file *file);
+static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
+static int option_send_setup(struct usb_serial_port *port);
/* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0
@@ -76,7 +76,6 @@ static int option_send_setup (struct usb_serial_port *port);
#define OPTION_PRODUCT_FUSION 0x6000
#define OPTION_PRODUCT_FUSION2 0x6300
-
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
@@ -129,7 +128,6 @@ static int debug;
#define debug 0
#endif
-
/* per port private data */
#define N_IN_URB 4
@@ -156,10 +154,8 @@ struct option_port_private {
unsigned long tx_start_time[N_OUT_URB];
};
-
/* Functions used by new usb-serial code. */
-static int __init
-option_init (void)
+static int __init option_init(void)
{
int retval;
retval = usb_serial_register(&option_3port_device);
@@ -179,8 +175,7 @@ failed_3port_device_register:
return retval;
}
-static void __exit
-option_exit (void)
+static void __exit option_exit(void)
{
usb_deregister (&option_driver);
usb_serial_deregister (&option_3port_device);
@@ -189,39 +184,31 @@ option_exit (void)
module_init(option_init);
module_exit(option_exit);
-static void
-option_rx_throttle (struct usb_serial_port *port)
+static void option_rx_throttle(struct usb_serial_port *port)
{
dbg("%s", __FUNCTION__);
}
-
-static void
-option_rx_unthrottle (struct usb_serial_port *port)
+static void option_rx_unthrottle(struct usb_serial_port *port)
{
dbg("%s", __FUNCTION__);
}
-
-static void
-option_break_ctl (struct usb_serial_port *port, int break_state)
+static void option_break_ctl(struct usb_serial_port *port, int break_state)
{
/* Unfortunately, I don't know how to send a break */
dbg("%s", __FUNCTION__);
}
-
-static void
-option_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+static void option_set_termios(struct usb_serial_port *port,
+ struct termios *old_termios)
{
dbg("%s", __FUNCTION__);
option_send_setup(port);
}
-static int
-option_tiocmget (struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct usb_serial_port *port, struct file *file)
{
unsigned int value;
struct option_port_private *portdata;
@@ -238,9 +225,8 @@ option_tiocmget (struct usb_serial_port *port, struct file *file)
return value;
}
-static int
-option_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear)
+static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
{
struct option_port_private *portdata;
@@ -258,17 +244,15 @@ option_tiocmset (struct usb_serial_port *port, struct file *file,
return option_send_setup(port);
}
-static int
-option_ioctl (struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int option_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
}
/* Write */
-static int
-option_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int option_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct option_port_private *portdata;
int i;
@@ -289,28 +273,29 @@ option_write (struct usb_serial_port *port,
this_urb = portdata->out_urbs[i];
if (this_urb->status == -EINPROGRESS) {
- if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
- continue;
- if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
+ if (time_before(jiffies,
+ portdata->tx_start_time[i] + 10 * HZ))
continue;
- this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb);
continue;
}
if (this_urb->status != 0)
- dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status);
+ dbg("usb_write %p failed (err=%d)",
+ this_urb, this_urb->status);
- dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
+ dbg("%s: endpoint %d buf %d", __FUNCTION__,
+ usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
memcpy (this_urb->transfer_buffer, buf, todo);
this_urb->transfer_buffer_length = todo;
- this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err) {
- dbg("usb_submit_urb %p (write bulk) failed (%d, has %d)", this_urb, err, this_urb->status);
+ dbg("usb_submit_urb %p (write bulk) failed "
+ "(%d, has %d)", this_urb,
+ err, this_urb->status);
continue;
}
portdata->tx_start_time[i] = jiffies;
@@ -323,8 +308,7 @@ option_write (struct usb_serial_port *port,
return count;
}
-static void
-option_indat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
{
int i, err;
int endpoint;
@@ -357,14 +341,14 @@ option_indat_callback (struct urb *urb, struct pt_regs *regs)
if (port->open_count && urb->status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err);
+ printk(KERN_ERR "%s: resubmit read urb failed. "
+ "(%d)", __FUNCTION__, err);
}
}
return;
}
-static void
-option_outdat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port;
@@ -376,8 +360,7 @@ option_outdat_callback (struct urb *urb, struct pt_regs *regs)
schedule_work(&port->work);
}
-static void
-option_instat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
{
int err;
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
@@ -395,10 +378,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
dbg("%s: NULL req_pkt\n", __FUNCTION__);
return;
}
- if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) {
+ if ((req_pkt->bRequestType == 0xA1) &&
+ (req_pkt->bRequest == 0x20)) {
int old_dcd_state;
unsigned char signals = *((unsigned char *)
- urb->transfer_buffer + sizeof(struct usb_ctrlrequest));
+ urb->transfer_buffer +
+ sizeof(struct usb_ctrlrequest));
dbg("%s: signal x%x", __FUNCTION__, signals);
@@ -408,12 +393,13 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
- && old_dcd_state && !portdata->dcd_state) {
+ if (port->tty && !C_CLOCAL(port->tty) &&
+ old_dcd_state && !portdata->dcd_state)
tty_hangup(port->tty);
- }
- } else
- dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest);
+ } else {
+ dbg("%s: type %x req %x", __FUNCTION__,
+ req_pkt->bRequestType,req_pkt->bRequest);
+ }
} else
dbg("%s: error %d", __FUNCTION__, urb->status);
@@ -422,13 +408,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err);
+ dbg("%s: resubmit intr urb failed. (%d)",
+ __FUNCTION__, err);
}
}
-
-static int
-option_write_room (struct usb_serial_port *port)
+static int option_write_room(struct usb_serial_port *port)
{
struct option_port_private *portdata;
int i;
@@ -447,9 +432,7 @@ option_write_room (struct usb_serial_port *port)
return data_len;
}
-
-static int
-option_chars_in_buffer (struct usb_serial_port *port)
+static int option_chars_in_buffer(struct usb_serial_port *port)
{
struct option_port_private *portdata;
int i;
@@ -467,9 +450,7 @@ option_chars_in_buffer (struct usb_serial_port *port)
return data_len;
}
-
-static int
-option_open (struct usb_serial_port *port, struct file *filp)
+static int option_open(struct usb_serial_port *port, struct file *filp)
{
struct option_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -490,17 +471,21 @@ option_open (struct usb_serial_port *port, struct file *filp)
if (! urb)
continue;
if (urb->dev != serial->dev) {
- dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev);
+ dbg("%s: dev %p != %p", __FUNCTION__,
+ urb->dev, serial->dev);
continue;
}
- /* make sure endpoint data toggle is synchronized with the device */
-
+ /*
+ * make sure endpoint data toggle is synchronized with the
+ * device
+ */
usb_clear_halt(urb->dev, urb->pipe);
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
- dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err,
+ dbg("%s: submit urb %d failed (%d) %d",
+ __FUNCTION__, i, err,
urb->transfer_buffer_length);
}
}
@@ -511,7 +496,8 @@ option_open (struct usb_serial_port *port, struct file *filp)
if (! urb)
continue;
urb->dev = serial->dev;
- /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), 0); */
}
port->tty->low_latency = 1;
@@ -521,17 +507,13 @@ option_open (struct usb_serial_port *port, struct file *filp)
return (0);
}
-static inline void
-stop_urb (struct urb *urb)
+static inline void stop_urb(struct urb *urb)
{
- if (urb && urb->status == -EINPROGRESS) {
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ if (urb && urb->status == -EINPROGRESS)
usb_kill_urb(urb);
- }
}
-static void
-option_close (struct usb_serial_port *port, struct file *filp)
+static void option_close(struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -555,12 +537,10 @@ option_close (struct usb_serial_port *port, struct file *filp)
port->tty = NULL;
}
-
/* Helper functions used by option_setup_urbs */
-static struct urb *
-option_setup_urb (struct usb_serial *serial, int endpoint,
- int dir, void *ctx, char *buf, int len,
- void (*callback)(struct urb *, struct pt_regs *regs))
+static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+ int dir, void *ctx, char *buf, int len,
+ void (*callback)(struct urb *, struct pt_regs *regs))
{
struct urb *urb;
@@ -582,8 +562,7 @@ option_setup_urb (struct usb_serial *serial, int endpoint,
}
/* Setup urbs */
-static void
-option_setup_urbs (struct usb_serial *serial)
+static void option_setup_urbs(struct usb_serial *serial)
{
int j;
struct usb_serial_port *port;
@@ -609,9 +588,7 @@ option_setup_urbs (struct usb_serial *serial)
}
}
-
-static int
-option_send_setup (struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
@@ -627,16 +604,15 @@ option_send_setup (struct usb_serial_port *port)
if (portdata->rts_state)
val |= 0x02;
- return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
}
return 0;
}
-
-static int
-option_startup (struct usb_serial *serial)
+static int option_startup(struct usb_serial *serial)
{
int i, err;
struct usb_serial_port *port;
@@ -647,9 +623,10 @@ option_startup (struct usb_serial *serial)
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL);
+ portdata = kmalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
- dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i);
+ dbg("%s: kmalloc for option_port_private (%d) failed!.",
+ __FUNCTION__, i);
return (1);
}
memset(portdata, 0, sizeof(struct option_port_private));
@@ -660,7 +637,8 @@ option_startup (struct usb_serial *serial)
continue;
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
- dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err);
+ dbg("%s: submit irq_in urb failed %d",
+ __FUNCTION__, err);
}
option_setup_urbs(serial);
@@ -668,8 +646,7 @@ option_startup (struct usb_serial *serial)
return (0);
}
-static void
-option_shutdown (struct usb_serial *serial)
+static void option_shutdown(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 7eab5d4cf3a8..3cf245bdda54 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -95,6 +95,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
+ { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
{ } /* Terminating entry */
};
@@ -538,8 +539,10 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- usb_clear_halt(serial->dev, port->write_urb->pipe);
- usb_clear_halt(serial->dev, port->read_urb->pipe);
+ if (priv->type != HX) {
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+ }
buf = kmalloc(10, GFP_KERNEL);
if (buf==NULL)
@@ -650,8 +653,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
timeout = max((HZ*2560)/bps,HZ/10);
else
timeout = 2*HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
+ schedule_timeout_interruptible(timeout);
/* shutdown our urbs */
dbg("%s - shutting down urbs", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index b734c4003c5a..7be9644f5a03 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -58,3 +58,7 @@
#define SYNTECH_VENDOR_ID 0x0745
#define SYNTECH_PRODUCT_ID 0x0001
+
+/* Nokia CA-42 Cable */
+#define NOKIA_CA42_VENDOR_ID 0x078b
+#define NOKIA_CA42_PRODUCT_ID 0x1234
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0267b26dde18..e77fbdfc782d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -531,7 +531,7 @@ bailout_kref_put:
static void serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
if (!port)
return;
@@ -561,7 +561,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
@@ -580,7 +580,7 @@ exit:
static int serial_write_room (struct tty_struct *tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -599,7 +599,7 @@ exit:
static int serial_chars_in_buffer (struct tty_struct *tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s = port %d", __FUNCTION__, port->number);
@@ -618,7 +618,7 @@ exit:
static void serial_throttle (struct tty_struct * tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -634,7 +634,7 @@ static void serial_throttle (struct tty_struct * tty)
static void serial_unthrottle (struct tty_struct * tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -650,7 +650,7 @@ static void serial_unthrottle (struct tty_struct * tty)
static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
@@ -672,7 +672,7 @@ exit:
static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -688,7 +688,7 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
static void serial_break (struct tty_struct *tty, int break_state)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -749,7 +749,7 @@ done:
static int serial_tiocmget (struct tty_struct *tty, struct file *file)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -768,7 +768,7 @@ exit:
static int serial_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -786,7 +786,7 @@ exit:
void usb_serial_port_softint(void *private)
{
- struct usb_serial_port *port = (struct usb_serial_port *)private;
+ struct usb_serial_port *port = private;
struct tty_struct *tty;
dbg("%s - port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index f1f1c0608c22..bb9819cc8826 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -111,3 +111,15 @@ config USB_STORAGE_JUMPSHOT
Say Y here to include additional code to support the Lexar Jumpshot
USB CompactFlash reader.
+
+config USB_STORAGE_ONETOUCH
+ bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
+ depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL
+ help
+ Say Y here to include additional code to support the Maxtor OneTouch
+ USB hard drive's onetouch button.
+
+ This code registers the button on the front of Maxtor OneTouch USB
+ hard drive's as an input device. An action can be associated with
+ this input in any keybinding software. (e.g. gnome's keyboard short-
+ cuts)
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 56652ccc2881..44ab8f9978fe 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -18,6 +18,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o
usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o
usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
initializers.o $(usb-storage-obj-y)
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
new file mode 100644
index 000000000000..2c9402dc702b
--- /dev/null
+++ b/drivers/usb/storage/onetouch.c
@@ -0,0 +1,210 @@
+/*
+ * Support for the Maxtor OneTouch USB hard drive's button
+ *
+ * Current development and maintenance by:
+ * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
+ *
+ * Initial work by:
+ * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
+ *
+ * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/kernel.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_input.h>
+#include "usb.h"
+#include "onetouch.h"
+#include "debug.h"
+
+void onetouch_release_input(void *onetouch_);
+
+struct usb_onetouch {
+ char name[128];
+ char phys[64];
+ struct input_dev dev; /* input device interface */
+ struct usb_device *udev; /* usb device */
+
+ struct urb *irq; /* urb for interrupt in report */
+ unsigned char *data; /* input data */
+ dma_addr_t data_dma;
+};
+
+static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_onetouch *onetouch = urb->context;
+ signed char *data = onetouch->data;
+ struct input_dev *dev = &onetouch->dev;
+ int status;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ /* -EPIPE: should clear the halt */
+ default: /* error */
+ goto resubmit;
+ }
+
+ input_regs(dev, regs);
+
+ input_report_key(&onetouch->dev, ONETOUCH_BUTTON,
+ data[0] & 0x02);
+
+ input_sync(dev);
+resubmit:
+ status = usb_submit_urb (urb, SLAB_ATOMIC);
+ if (status)
+ err ("can't resubmit intr, %s-%s/input0, status %d",
+ onetouch->udev->bus->bus_name,
+ onetouch->udev->devpath, status);
+}
+
+static int usb_onetouch_open(struct input_dev *dev)
+{
+ struct usb_onetouch *onetouch = dev->private;
+
+ onetouch->irq->dev = onetouch->udev;
+ if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
+ err("usb_submit_urb failed");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void usb_onetouch_close(struct input_dev *dev)
+{
+ struct usb_onetouch *onetouch = dev->private;
+
+ usb_kill_urb(onetouch->irq);
+}
+
+int onetouch_connect_input(struct us_data *ss)
+{
+ struct usb_device *udev = ss->pusb_dev;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_onetouch *onetouch;
+ int pipe, maxp;
+ char path[64];
+
+ interface = ss->pusb_intf->cur_altsetting;
+
+ if (interface->desc.bNumEndpoints != 3)
+ return -ENODEV;
+
+ endpoint = &interface->endpoint[2].desc;
+ if(!(endpoint->bEndpointAddress & USB_DIR_IN))
+ return -ENODEV;
+ if((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_INT)
+ return -ENODEV;
+
+ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+
+ if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL)))
+ return -ENOMEM;
+
+ onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
+ SLAB_ATOMIC, &onetouch->data_dma);
+ if (!onetouch->data){
+ kfree(onetouch);
+ return -ENOMEM;
+ }
+
+ onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!onetouch->irq){
+ kfree(onetouch);
+ usb_buffer_free(udev, ONETOUCH_PKT_LEN,
+ onetouch->data, onetouch->data_dma);
+ return -ENODEV;
+ }
+
+
+ onetouch->udev = udev;
+
+ set_bit(EV_KEY, onetouch->dev.evbit);
+ set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit);
+ clear_bit(0, onetouch->dev.keybit);
+
+ onetouch->dev.private = onetouch;
+ onetouch->dev.open = usb_onetouch_open;
+ onetouch->dev.close = usb_onetouch_close;
+
+ usb_make_path(udev, path, sizeof(path));
+ sprintf(onetouch->phys, "%s/input0", path);
+
+ onetouch->dev.name = onetouch->name;
+ onetouch->dev.phys = onetouch->phys;
+
+ usb_to_input_id(udev, &onetouch->dev.id);
+
+ onetouch->dev.dev = &udev->dev;
+
+ if (udev->manufacturer)
+ strcat(onetouch->name, udev->manufacturer);
+ if (udev->product)
+ sprintf(onetouch->name, "%s %s", onetouch->name,
+ udev->product);
+ if (!strlen(onetouch->name))
+ sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x",
+ onetouch->dev.id.vendor, onetouch->dev.id.product);
+
+ usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
+ (maxp > 8 ? 8 : maxp),
+ usb_onetouch_irq, onetouch, endpoint->bInterval);
+ onetouch->irq->transfer_dma = onetouch->data_dma;
+ onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ ss->extra_destructor = onetouch_release_input;
+ ss->extra = onetouch;
+
+ input_register_device(&onetouch->dev);
+ printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path);
+
+ return 0;
+}
+
+void onetouch_release_input(void *onetouch_)
+{
+ struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;
+
+ if (onetouch) {
+ usb_kill_urb(onetouch->irq);
+ input_unregister_device(&onetouch->dev);
+ usb_free_urb(onetouch->irq);
+ usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN,
+ onetouch->data, onetouch->data_dma);
+ printk(KERN_INFO "usb-input: deregistering %s\n",
+ onetouch->dev.name);
+ }
+}
diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h
new file mode 100644
index 000000000000..41c7aa8f0446
--- /dev/null
+++ b/drivers/usb/storage/onetouch.h
@@ -0,0 +1,9 @@
+#ifndef _ONETOUCH_H_
+#define _ONETOUCH_H_
+
+#define ONETOUCH_PKT_LEN 0x02
+#define ONETOUCH_BUTTON KEY_PROG1
+
+int onetouch_connect_input(struct us_data *ss);
+
+#endif
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index af294bb68c35..4837524eada7 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -156,6 +156,14 @@ static int slave_configure(struct scsi_device *sdev)
if (us->flags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
+ /* Some devices report a SCSI revision level above 2 but are
+ * unable to handle the REPORT LUNS command (for which
+ * support is mandatory at level 3). Since we already have
+ * a Get-Max-LUN request, we won't lose much by setting the
+ * revision level down to 2. The only devices that would be
+ * affected are those with sparse LUNs. */
+ sdev->scsi_level = SCSI_2;
+
/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
* Hardware Error) when any low-level error occurs,
* recoverable or not. Setting this flag tells the SCSI
@@ -219,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
-/* This is always called with scsi_lock(host) held */
static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ * bits are protected by the host lock. */
+ scsi_lock(us_to_host(us));
+
/* Is this command still active? */
if (us->srb != srb) {
+ scsi_unlock(us_to_host(us));
US_DEBUGP ("-- nothing to abort\n");
return FAILED;
}
/* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
* a device reset isn't already in progress (to avoid interfering
- * with the reset). To prevent races with auto-reset, we must
- * stop any ongoing USB transfers while still holding the host
- * lock. */
+ * with the reset). Note that we must retain the host lock while
+ * calling usb_stor_stop_transport(); otherwise it might interfere
+ * with an auto-reset that begins as soon as we release the lock. */
set_bit(US_FLIDX_TIMED_OUT, &us->flags);
if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
+ scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
-
- /* Reacquire the lock and allow USB transfers to resume */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
- clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
}
/* This invokes the transport reset mechanism to reset the state of the
* device */
-/* This is always called with scsi_lock(host) held */
static int device_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -271,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
}
/* Simulate a SCSI bus reset by resetting the device's USB port. */
-/* This is always called with scsi_lock(host) held */
static int bus_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -283,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
result = usb_stor_port_reset(us);
up(&(us->dev_semaphore));
- /* lock the host for the return */
return result < 0 ? FAILED : SUCCESS;
}
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index f3b60288696c..356342c6e7a2 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -839,34 +839,31 @@ static int usbat_identify_device(struct us_data *us,
rc = usbat_device_reset(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
+ msleep(25);
/*
- * By examining the device signature after a reset, we can identify
- * whether the device supports the ATAPI packet interface.
- * The flash-devices do not support this, whereas the HP CDRW's obviously
- * do.
- *
- * This method is not ideal, but works because no other devices have been
- * produced based on the USBAT/USBAT02.
- *
- * Section 9.1 of the ATAPI-4 spec states (amongst other things) that
- * after a device reset, a Cylinder low of 0x14 indicates that the device
- * does support packet commands.
+ * In attempt to distinguish between HP CDRW's and Flash readers, we now
+ * execute the IDENTIFY PACKET DEVICE command. On ATA devices (i.e. flash
+ * readers), this command should fail with error. On ATAPI devices (i.e.
+ * CDROM drives), it should succeed.
*/
- rc = usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, &status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ rc = usbat_write(us, USBAT_ATA, USBAT_ATA_CMD, 0xA1);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("usbat_identify_device: Cylinder low is %02X\n", status);
+ rc = usbat_get_status(us, &status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if (status == 0x14) {
+ // Check for error bit
+ if (status & 0x01) {
+ // Device is a CompactFlash reader/writer
+ US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+ info->devicetype = USBAT_DEV_FLASH;
+ } else {
// Device is HP 8200
US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
info->devicetype = USBAT_DEV_HP8200;
- } else {
- // Device is a CompactFlash reader/writer
- US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
- info->devicetype = USBAT_DEV_FLASH;
}
return USB_STOR_TRANSPORT_GOOD;
@@ -1239,16 +1236,10 @@ static int usbat_select_and_test_registers(struct us_data *us)
{
int selector;
unsigned char *status = us->iobuf;
- unsigned char max_selector = 0xB0;
- if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
- max_selector = 0xA0;
// try device = master, then device = slave.
-
- for (selector = 0xA0; selector <= max_selector; selector += 0x10) {
-
- if (usbat_get_device_type(us) == USBAT_DEV_HP8200 &&
- usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
+ for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
+ if (usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -1334,60 +1325,30 @@ int init_usbat(struct us_data *us)
US_DEBUGP("INIT 3\n");
- // At this point, we need to detect which device we are using
- if (usbat_set_transport(us, info))
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 4\n");
-
- if (usbat_get_device_type(us) == USBAT_DEV_HP8200) {
- msleep(250);
-
- // Write 0x80 to ISA port 0x3F
- rc = usbat_write(us, USBAT_ISA, 0x3F, 0x80);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 5\n");
-
- // Read ISA port 0x27
- rc = usbat_read(us, USBAT_ISA, 0x27, status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 6\n");
-
- rc = usbat_read_user_io(us, status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 7\n");
- }
-
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 8\n");
+ US_DEBUGP("INIT 4\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 9\n");
+ US_DEBUGP("INIT 5\n");
// Enable peripheral control signals and card detect
rc = usbat_device_enable_cdt(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 10\n");
+ US_DEBUGP("INIT 6\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 11\n");
+ US_DEBUGP("INIT 7\n");
msleep(1400);
@@ -1395,13 +1356,19 @@ int init_usbat(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 12\n");
+ US_DEBUGP("INIT 8\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 13\n");
+ US_DEBUGP("INIT 9\n");
+
+ // At this point, we need to detect which device we are using
+ if (usbat_set_transport(us, info))
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUGP("INIT 10\n");
if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {
subcountH = 0x02;
@@ -1412,7 +1379,7 @@ int init_usbat(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 14\n");
+ US_DEBUGP("INIT 11\n");
return USB_STOR_TRANSPORT_GOOD;
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index e6b1c6cf07f2..c1ba5301ebfc 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -96,8 +96,8 @@
* or before the URB_ACTIVE bit was set. If so, it's essential to cancel
* the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
* is still set). Either way, the function must then wait for the URB to
- * finish. Note that because the URB_ASYNC_UNLINK flag is set, the URB can
- * still be in progress even after a call to usb_unlink_urb() returns.
+ * finish. Note that the URB can still be in progress even after a call to
+ * usb_unlink_urb() returns.
*
* The idea is that (1) once the ABORTING or DISCONNECTING bit is set,
* either the stop_transport() function or the submitting function
@@ -158,8 +158,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
* hasn't been mapped for DMA. Yes, this is clunky, but it's
* easier than always having the caller tell us whether the
* transfer buffer has already been mapped. */
- us->current_urb->transfer_flags =
- URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
+ us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
if (us->current_urb->transfer_buffer == us->iobuf)
us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
us->current_urb->transfer_dma = us->iobuf_dma;
@@ -611,7 +610,6 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned char old_sc_data_direction;
unsigned char old_cmd_len;
unsigned char old_cmnd[MAX_COMMAND_SIZE];
- unsigned long old_serial_number;
int old_resid;
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
@@ -648,10 +646,6 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
old_sg = srb->use_sg;
srb->use_sg = 0;
- /* change the serial number -- toggle the high bit*/
- old_serial_number = srb->serial_number;
- srb->serial_number ^= 0x80000000;
-
/* issue the auto-sense command */
old_resid = srb->resid;
srb->resid = 0;
@@ -662,7 +656,6 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
srb->request_buffer = old_request_buffer;
srb->request_bufflen = old_request_bufflen;
srb->use_sg = old_sg;
- srb->serial_number = old_serial_number;
srb->sc_data_direction = old_sc_data_direction;
srb->cmd_len = old_cmd_len;
memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
@@ -985,7 +978,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
- bcb->Tag = srb->serial_number;
+ bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG)
bcb->Lun |= srb->device->id << 4;
@@ -1074,7 +1067,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status);
- if (bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) {
+ if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index bd0ab3039bdd..b79dad1b598c 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -79,6 +79,23 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0),
#endif
+/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
+UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
+ "VIA Technologies Inc.",
+ "USB 2.0 Card Reader",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
+ * for USB floppies that need the SINGLE_LUN enforcement.
+ */
+UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,
+ "NEC",
+ "NEC USB UF000x",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
@@ -89,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
+UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
+ "SMSC",
+ "FDC GOLD-2.30",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
@@ -96,6 +120,24 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+/*
+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
+ * The key does not actually break, but it returns zero sense which
+ * makes our SCSI stack to print confusing messages.
+ */
+UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
+ "USBest Technology", /* sold by Transcend */
+ "USB Mass Storage Device",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
+ "Neuros Audio",
+ "USB 2.0 HD 2.5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ US_FL_NEED_OVERRIDE ),
+
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
@@ -929,6 +971,18 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
US_FL_SINGLE_LUN ),
#endif
+/* Submitted by: Nick Sillik <n.sillik@temple.edu>
+ * Needed for OneTouch extension to usb-storage
+ *
+ */
+#ifdef CONFIG_USB_STORAGE_ONETOUCH
+ UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999,
+ "Maxtor",
+ "OneTouch External Harddrive",
+ US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+ 0),
+#endif
+
/* Submitted by Joris Struyve <joris@struyve.be> */
UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
"Medion",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 77e7fc258aa2..f9a9bfa1aef5 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -90,7 +90,9 @@
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
#include "jumpshot.h"
#endif
-
+#ifdef CONFIG_USB_STORAGE_ONETOUCH
+#include "onetouch.h"
+#endif
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -390,11 +392,16 @@ SkipForAbort:
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* the TIMED_OUT flag, not srb->result == DID_ABORT, because
- * a timeout/abort request might be received after all the
- * USB processing was complete. */
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))
+ * the timeout might have occurred after the command had
+ * already completed with a different result code. */
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
complete(&(us->notify));
+ /* Allow USB transfers to resume */
+ clear_bit(US_FLIDX_ABORTING, &us->flags);
+ clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+ }
+
/* finished working on this command */
us->srb = NULL;
scsi_unlock(host);
@@ -786,6 +793,7 @@ static void usb_stor_release_resources(struct us_data *us)
* any more commands.
*/
US_DEBUGP("-- sending exit command to thread\n");
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
up(&us->sema);
/* Call the destructor routine, if it exists */
@@ -816,6 +824,49 @@ static void dissociate_dev(struct us_data *us)
usb_set_intfdata(us->pusb_intf, NULL);
}
+/* First stage of disconnect processing: stop all commands and remove
+ * the host */
+static void quiesce_and_remove_host(struct us_data *us)
+{
+ /* Prevent new USB transfers, stop the current command, and
+ * interrupt a SCSI-scan or device-reset delay */
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
+ usb_stor_stop_transport(us);
+ wake_up(&us->delay_wait);
+
+ /* It doesn't matter if the SCSI-scanning thread is still running.
+ * The thread will exit when it sees the DISCONNECTING flag. */
+
+ /* Wait for the current command to finish, then remove the host */
+ down(&us->dev_semaphore);
+ up(&us->dev_semaphore);
+
+ /* queuecommand won't accept any new commands and the control
+ * thread won't execute a previously-queued command. If there
+ * is such a command pending, complete it with an error. */
+ if (us->srb) {
+ us->srb->result = DID_NO_CONNECT << 16;
+ scsi_lock(us_to_host(us));
+ us->srb->scsi_done(us->srb);
+ us->srb = NULL;
+ scsi_unlock(us_to_host(us));
+ }
+
+ /* Now we own no commands so it's safe to remove the SCSI host */
+ scsi_remove_host(us_to_host(us));
+}
+
+/* Second stage of disconnect processing: deallocate all resources */
+static void release_everything(struct us_data *us)
+{
+ usb_stor_release_resources(us);
+ dissociate_dev(us);
+
+ /* Drop our reference to the host; the SCSI core will free it
+ * (and "us" along with it) when the refcount becomes 0. */
+ scsi_host_put(us_to_host(us));
+}
+
/* Thread to carry out delayed SCSI-device scanning */
static int usb_stor_scan_thread(void * __us)
{
@@ -956,7 +1007,7 @@ static int storage_probe(struct usb_interface *intf,
if (result < 0) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
- scsi_remove_host(host);
+ quiesce_and_remove_host(us);
goto BadDevice;
}
atomic_inc(&total_threads);
@@ -969,10 +1020,7 @@ static int storage_probe(struct usb_interface *intf,
/* We come here if there are any problems */
BadDevice:
US_DEBUGP("storage_probe() failed\n");
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- usb_stor_release_resources(us);
- dissociate_dev(us);
- scsi_host_put(host);
+ release_everything(us);
return result;
}
@@ -982,28 +1030,8 @@ static void storage_disconnect(struct usb_interface *intf)
struct us_data *us = usb_get_intfdata(intf);
US_DEBUGP("storage_disconnect() called\n");
-
- /* Prevent new USB transfers, stop the current command, and
- * interrupt a SCSI-scan or device-reset delay */
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- usb_stor_stop_transport(us);
- wake_up(&us->delay_wait);
-
- /* It doesn't matter if the SCSI-scanning thread is still running.
- * The thread will exit when it sees the DISCONNECTING flag. */
-
- /* Wait for the current command to finish, then remove the host */
- down(&us->dev_semaphore);
- up(&us->dev_semaphore);
- scsi_remove_host(us_to_host(us));
-
- /* Wait for everything to become idle and release all our resources */
- usb_stor_release_resources(us);
- dissociate_dev(us);
-
- /* Drop our reference to the host; the SCSI core will free it
- * (and "us" along with it) when the refcount becomes 0. */
- scsi_host_put(us_to_host(us));
+ quiesce_and_remove_host(us);
+ release_everything(us);
}
/***********************************************************************
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 625b7aa98074..a195adae57b6 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -158,6 +158,7 @@ struct us_data {
/* SCSI interfaces */
struct scsi_cmnd *srb; /* current srb */
+ unsigned int tag; /* current dCBWTag */
/* thread information */
int pid; /* control thread */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cde0ed097af6..31ee13eef7af 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -650,7 +650,6 @@ config FB_NVIDIA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
@@ -681,7 +680,6 @@ config FB_RIVA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports graphics boards with the nVidia Riva/Geforce
chips.
@@ -720,7 +718,6 @@ config FB_I810
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel 810
and 815 chipsets. Say Y if you have and plan to use such a board.
@@ -754,6 +751,13 @@ config FB_I810_GTF
If unsure, say N.
+config FB_I810_I2C
+ bool "Enable DDC Support"
+ depends on FB_I810 && FB_I810_GTF
+ select I2C
+ select I2C_ALGOBIT
+ help
+
config FB_INTEL
tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
@@ -763,7 +767,6 @@ config FB_INTEL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel
830M/845G/852GM/855GM/865G chipsets.
@@ -960,8 +963,7 @@ config FB_RADEON
can be build either as modules or built-in.
There is a product page at
- <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
-
+ http://apps.ati.com/ATIcompare/
config FB_RADEON_I2C
bool "DDC/I2C for ATI Radeon support"
depends on FB_RADEON
@@ -1084,15 +1086,16 @@ config FB_SAVAGE_ACCEL
choose N here.
config FB_SIS
- tristate "SiS acceleration"
+ tristate "SiS/XGI display support"
depends on FB && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
help
- This is the frame buffer device driver for the SiS 300, 315 and
- 330 series VGA chipsets. Specs available at <http://www.sis.com>
+ This is the frame buffer device driver for the SiS 300, 315, 330
+ and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
+ Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
To compile this driver as a module, choose M here; the module
will be called sisfb.
@@ -1104,11 +1107,12 @@ config FB_SIS_300
Say Y here to support use of the SiS 300/305, 540, 630 and 730.
config FB_SIS_315
- bool "SiS 315/330 series support"
+ bool "SiS 315/330/340 series and XGI support"
depends on FB_SIS
help
- Say Y here to support use of the SiS 315 and 330 series
- (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760).
+ Say Y here to support use of the SiS 315, 330 and 340 series
+ (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
+ as XGI V3XT, V5, V8 and Z7.
config FB_NEOMAGIC
tristate "NeoMagic display support"
@@ -1180,6 +1184,32 @@ config FB_VOODOO1
Please read the <file:Documentation/fb/README-sstfb.txt> for supported
options and other important info support.
+config FB_CYBLA
+ tristate "Cyberblade/i1 support"
+ depends on FB && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select VIDEO_SELECT
+ ---help---
+ This driver is supposed to support the Trident Cyberblade/i1
+ graphics core integrated in the VIA VT8601A North Bridge,
+ also known as VIA Apollo PLE133.
+
+ Status:
+ - Developed, tested and working on EPIA 5000 and EPIA 800.
+ - Does work reliable on all systems with CRT/LCD connected to
+ normal VGA ports.
+ - Should work on systems that do use the internal LCD port, but
+ this is absolutely not tested.
+
+ Character imageblit, copyarea and rectangle fill are hw accelerated,
+ ypan scrolling is used by default.
+
+ Please do read <file:Documentation/fb/cyblafb/*>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cyblafb.
+
config FB_TRIDENT
tristate "Trident support"
depends on FB && PCI
@@ -1193,8 +1223,12 @@ config FB_TRIDENT
but also on some motherboards. For more information, read
<file:Documentation/fb/tridentfb.txt>
+ Cyberblade/i1 support will be removed soon, use the cyblafb driver
+ instead.
+
Say Y if you have such a graphics board.
+
To compile this driver as a module, choose M here: the
module will be called tridentfb.
@@ -1205,7 +1239,6 @@ config FB_TRIDENT_ACCEL
This will compile the Trident frame buffer device with
acceleration functions.
-
config FB_PM3
tristate "Permedia3 support"
depends on FB && PCI && BROKEN
@@ -1484,6 +1517,30 @@ config FB_S1D13XXX
working with S1D13806). Product specs at
<http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+config FB_S3C2410
+ tristate "S3C2410 LCD framebuffer support"
+ depends on FB && ARCH_S3C2410
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Samsung
+ S3C2410 processor.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called s3c2410fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+config FB_S3C2410_DEBUG
+ bool "S3C2410 lcd debug messages"
+ depends on FB_S3C2410
+ help
+ Turn on debugging messages. Note that you can set/unset at run time
+ through sysfs
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b018df4e95c8..1fff29f48ca8 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,7 +9,8 @@ obj-$(CONFIG_LOGO) += logo/
obj-$(CONFIG_SYSFS) += backlight/
obj-$(CONFIG_FB) += fb.o
-fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o
+fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+ modedb.o fbcvt.o
fb-objs := $(fb-y)
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
@@ -50,7 +51,8 @@ obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o
-obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
+obj-$(CONFIG_FB_CYBLA) += cyblafb.o
+obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_STI) += stifb.o
obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
@@ -92,6 +94,7 @@ obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
+obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 7bc1d44d8814..e380ee8b0247 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -806,8 +806,8 @@ static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, stru
/* Very simple test to make sure it appeared */
if (BIOS_IN16(0) != 0xaa55) {
- printk(KERN_ERR "aty128fb: Invalid ROM signature %x should be 0xaa55\n",
- BIOS_IN16(0));
+ printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
+ " be 0xaa55\n", BIOS_IN16(0));
goto failed;
}
@@ -2323,17 +2323,16 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
* can properly take care of D3 ? Also, with swsusp, we
* know we'll be rebooted, ...
*/
-#ifdef CONFIG_PPC_PMAC
+#ifndef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
- if (state >= 3)
- state = 2;
+ return 0;
#endif /* CONFIG_PPC_PMAC */
- if (state != 2 || state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
printk(KERN_DEBUG "aty128fb: suspending...\n");
@@ -2367,7 +2366,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
* used dummy fb ops, 2.5 need proper support for this at the
* fbdev level
*/
- if (state == 2)
+ if (state.event != PM_EVENT_ON)
aty128_set_suspend(par, 1);
release_console_sem();
@@ -2382,12 +2381,11 @@ static int aty128_do_resume(struct pci_dev *pdev)
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
/* Wakeup chip */
- if (pdev->dev.power.power_state == 2)
- aty128_set_suspend(par, 0);
+ aty128_set_suspend(par, 0);
par->asleep = 0;
/* Restore display & engine */
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 8c42538dc8c1..037fe9d32fe3 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -911,20 +911,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
vdisplay = par->lcd_height;
#endif
- if(vdisplay < 400) {
- h_sync_pol = 1;
- v_sync_pol = 0;
- } else if(vdisplay < 480) {
- h_sync_pol = 0;
- v_sync_pol = 1;
- } else if(vdisplay < 768) {
- h_sync_pol = 0;
- v_sync_pol = 0;
- } else {
- h_sync_pol = 1;
- v_sync_pol = 1;
- }
-
v_disp--;
v_sync_strt--;
v_sync_end--;
@@ -2022,17 +2008,16 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef CONFIG_PPC_PMAC
+#ifndef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
- if (state >= 3)
- state = 2;
+ return 0;
#endif /* CONFIG_PPC_PMAC */
- if (state != 2 || state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
acquire_console_sem();
@@ -2071,12 +2056,12 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
acquire_console_sem();
- if (pdev->dev.power.power_state == 2)
+ if (pdev->dev.power.power_state.event == 2)
aty_power_mgmt(0, par);
par->asleep = 0;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index e7e8b52014c3..046b47860266 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -329,8 +329,9 @@ static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev
/* Very simple test to make sure it appeared */
if (BIOS_IN16(0) != 0xaa55) {
- printk(KERN_ERR "radeonfb (%s): Invalid ROM signature %x should be"
- "0xaa55\n", pci_name(rinfo->pdev), BIOS_IN16(0));
+ printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
+ "should be 0xaa55\n",
+ pci_name(rinfo->pdev), BIOS_IN16(0));
goto failed;
}
/* Look for the PCI data to check the ROM type */
@@ -2312,19 +2313,27 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
/* request the mem regions */
- ret = pci_request_regions(pdev, "radeonfb");
+ ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
if (ret < 0) {
- printk( KERN_ERR "radeonfb (%s): cannot reserve PCI regions."
- " Someone already got them?\n", pci_name(rinfo->pdev));
+ printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
+ pci_name(rinfo->pdev));
goto err_release_fb;
}
+ ret = pci_request_region(pdev, 2, "radeonfb mmio");
+ if (ret < 0) {
+ printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
+ pci_name(rinfo->pdev));
+ goto err_release_pci0;
+ }
+
/* map the regions */
rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
if (!rinfo->mmio_base) {
- printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", pci_name(rinfo->pdev));
+ printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
+ pci_name(rinfo->pdev));
ret = -EIO;
- goto err_release_pci;
+ goto err_release_pci2;
}
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
@@ -2499,10 +2508,12 @@ err_unmap_rom:
if (rinfo->bios_seg)
radeon_unmap_ROM(rinfo, pdev);
iounmap(rinfo->mmio_base);
-err_release_pci:
- pci_release_regions(pdev);
+err_release_pci2:
+ pci_release_region(pdev, 2);
+err_release_pci0:
+ pci_release_region(pdev, 0);
err_release_fb:
- framebuffer_release(info);
+ framebuffer_release(info);
err_disable:
pci_disable_device(pdev);
err_out:
@@ -2548,7 +2559,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
iounmap(rinfo->mmio_base);
iounmap(rinfo->fb_base);
- pci_release_regions(pdev);
+ pci_release_region(pdev, 2);
+ pci_release_region(pdev, 0);
kfree(rinfo->mon1_EDID);
kfree(rinfo->mon2_EDID);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 762244164c81..a9d0414e4655 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -75,7 +75,7 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_ATI;
+ chan->adapter.id = I2C_HW_B_RADEON;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->rinfo->pdev->dev;
chan->algo.setsda = radeon_gpio_setsda;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 98352af39325..59a1b6f85067 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2526,18 +2526,18 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
struct radeonfb_info *rinfo = info->par;
int i;
- if (state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n",
- pci_name(pdev), state);
+ pci_name(pdev), state.event);
/* For suspend-to-disk, we cheat here. We don't suspend anything and
* let fbcon continue drawing until we are all set. That shouldn't
* really cause any problem at this point, provided that the wakeup
* code knows that any state in memory may not match the HW
*/
- if (state != PM_SUSPEND_MEM)
+ if (state.event == PM_EVENT_FREEZE)
goto done;
acquire_console_sem();
@@ -2616,7 +2616,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
struct radeonfb_info *rinfo = info->par;
int rc = 0;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
if (rinfo->no_schedule) {
@@ -2626,7 +2626,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
acquire_console_sem();
printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
- pci_name(pdev), pdev->dev.power.power_state);
+ pci_name(pdev), pdev->dev.power.power_state.event);
if (pci_enable_device(pdev)) {
@@ -2637,7 +2637,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
}
pci_set_master(pdev);
- if (pdev->dev.power.power_state == PM_SUSPEND_MEM) {
+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
/* Wakeup chip. Check from config space if we were powered off
* (todo: additionally, check CLK_PIN_CNTL too)
*/
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9aae884475be..4af321fae390 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,3 +3,4 @@
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
+obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 353cb3f73cf2..a32817678552 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -43,18 +43,10 @@ static void corgibl_send_intensity(int intensity)
intensity &= CORGI_LIMIT_MASK;
}
- /* Skip 0x20 as it will blank the display */
- if (intensity >= 0x20)
- intensity++;
-
spin_lock_irqsave(&bl_lock, flags);
- /* Bits 0-4 are accessed via the SSP interface */
- corgi_ssp_blduty_set(intensity & 0x1f);
- /* Bit 5 is via SCOOP */
- if (intensity & 0x0020)
- set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
- else
- reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+
+ corgibl_mach_set_intensity(intensity);
+
spin_unlock_irqrestore(&bl_lock, flags);
}
@@ -113,8 +105,8 @@ static int corgibl_get_power(struct backlight_device *bd)
static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
{
- if (intensity > CORGI_MAX_INTENSITY)
- intensity = CORGI_MAX_INTENSITY;
+ if (intensity > corgibl_data.max_brightness)
+ intensity = corgibl_data.max_brightness;
corgibl_send_intensity(intensity);
current_intensity=intensity;
return 0;
@@ -141,7 +133,6 @@ static struct backlight_properties corgibl_data = {
.owner = THIS_MODULE,
.get_power = corgibl_get_power,
.set_power = corgibl_set_power,
- .max_brightness = CORGI_MAX_INTENSITY,
.get_brightness = corgibl_get_intensity,
.set_brightness = corgibl_set_intensity,
};
@@ -150,12 +141,18 @@ static struct backlight_device *corgi_backlight_device;
static int __init corgibl_probe(struct device *dev)
{
+ struct corgibl_machinfo *machinfo = dev->platform_data;
+
+ corgibl_data.max_brightness = machinfo->max_intensity;
+ corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+
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);
printk("Corgi Backlight Driver Initialized.\n");
return 0;
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
new file mode 100644
index 000000000000..ada6e75eb048
--- /dev/null
+++ b/drivers/video/backlight/locomolcd.c
@@ -0,0 +1,157 @@
+/*
+ * Backlight control code for Sharp Zaurus SL-5500
+ *
+ * Copyright 2005 John Lenz <lenz@cs.wisc.edu>
+ * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
+ * GPL v2
+ *
+ * This driver assumes single CPU. That's okay, because collie is
+ * slightly old hardware, and noone is going to retrofit second CPU to
+ * old PDA.
+ */
+
+/* LCD power functions */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware/locomo.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch/collie.h>
+#else
+#include <asm/arch/poodle.h>
+#endif
+
+extern void (*sa1100fb_lcd_power)(int on);
+
+static struct locomo_dev *locomolcd_dev;
+
+static void locomolcd_on(int comadj)
+{
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+ mdelay(2);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+ mdelay(2);
+
+ locomo_m62332_senddata(locomolcd_dev, comadj, 0);
+ mdelay(5);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
+ mdelay(10);
+
+ /* TFTCRST | CPSOUT=0 | CPSEN */
+ locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
+
+ /* Set CPSD */
+ locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
+
+ /* TFTCRST | CPSOUT=0 | CPSEN */
+ locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
+ mdelay(10);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
+}
+
+static void locomolcd_off(int comadj)
+{
+ /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
+ locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
+ mdelay(1);
+
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+ mdelay(110);
+
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+ mdelay(700);
+
+ /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
+ locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+}
+
+void locomolcd_power(int on)
+{
+ int comadj = 118;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (!locomolcd_dev) {
+ local_irq_restore(flags);
+ return;
+ }
+
+ /* read comadj */
+#ifdef CONFIG_MACH_POODLE
+ comadj = 118;
+#else
+ comadj = 128;
+#endif
+
+ if (on)
+ locomolcd_on(comadj);
+ else
+ locomolcd_off(comadj);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(locomolcd_power);
+
+static int poodle_lcd_probe(struct locomo_dev *dev)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ locomolcd_dev = dev;
+
+ /* the poodle_lcd_power function is called for the first time
+ * from fs_initcall, which is before locomo is activated.
+ * We need to recall poodle_lcd_power here*/
+#ifdef CONFIG_MACH_POODLE
+ locomolcd_power(1);
+#endif
+ local_irq_restore(flags);
+ return 0;
+}
+
+static int poodle_lcd_remove(struct locomo_dev *dev)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ locomolcd_dev = NULL;
+ local_irq_restore(flags);
+ return 0;
+}
+
+static struct locomo_driver poodle_lcd_driver = {
+ .drv = {
+ .name = "locomo-backlight",
+ },
+ .devid = LOCOMO_DEVID_BACKLIGHT,
+ .probe = poodle_lcd_probe,
+ .remove = poodle_lcd_remove,
+};
+
+static int __init poodle_lcd_init(void)
+{
+ int ret = locomo_driver_register(&poodle_lcd_driver);
+ if (ret) return ret;
+
+#ifdef CONFIG_SA1100_COLLIE
+ sa1100fb_lcd_power = locomolcd_power;
+#endif
+ return 0;
+}
+device_initcall(poodle_lcd_init);
+
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index e75a965ec760..4131243cfdf8 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -462,9 +462,9 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *p = pci_get_drvdata(pdev);
- if (state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
- if (state != PM_SUSPEND_MEM)
+ if (state.event != PM_SUSPEND_MEM)
goto done;
acquire_console_sem();
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5fe182d6e4ab..eb83a7874c71 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -137,7 +137,7 @@ config FONT_8x8
config FONT_8x16
bool "VGA 8x16 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
+ depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index b562f6bb9d31..42c7b8dcd220 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -33,6 +33,10 @@ endif
obj-$(CONFIG_FB_STI) += sticore.o font.o
+ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
+obj-$(CONFIG_USB_SISUSBVGA) += font.o
+endif
+
# Targets that kbuild needs to know about
targets := promcon_tbl.c
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 3c731577fed6..9f70e512b88b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c)
{
int attribute = 0;
- if (fb_get_color_depth(&info->var) == 1) {
+ if (fb_get_color_depth(&info->var, &info->fix) == 1) {
if (attr_underline(c))
attribute |= FBCON_ATTRIBUTE_UNDERLINE;
if (attr_reverse(c))
@@ -103,42 +103,104 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
info->fbops->fb_fillrect(info, &region);
}
+static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
+ const u16 *s, u32 attr, u32 cnt,
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst)
+{
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 idx = vc->vc_font.width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = vc->vc_font.data + (scr_readw(s++)&
+ charmask)*cellsize;
+
+ if (attr) {
+ update_attr(buf, src, attr, vc);
+ src = buf;
+ }
+
+ if (likely(idx == 1))
+ __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+ else
+ fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+
+ dst += s_pitch;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+}
+
+static inline void bit_putcs_unaligned(struct vc_data *vc,
+ struct fb_info *info, const u16 *s,
+ u32 attr, u32 cnt, u32 d_pitch,
+ u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf,
+ u8 *dst)
+{
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 shift_low = 0, mod = vc->vc_font.width % 8;
+ u32 shift_high = 8;
+ u32 idx = vc->vc_font.width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = vc->vc_font.data + (scr_readw(s++)&
+ charmask)*cellsize;
+
+ if (attr) {
+ update_attr(buf, src, attr, vc);
+ src = buf;
+ }
+
+ fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
+ image->height, shift_high,
+ shift_low, mod);
+ shift_low += mod;
+ dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
+ shift_low &= 7;
+ shift_high = 8 - shift_low;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+
+}
+
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
const unsigned short *s, int count, int yy, int xx,
int fg, int bg)
{
- unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
- unsigned int width = (vc->vc_font.width + 7) >> 3;
- unsigned int cellsize = vc->vc_font.height * width;
- unsigned int maxcnt = info->pixmap.size/cellsize;
- unsigned int scan_align = info->pixmap.scan_align - 1;
- unsigned int buf_align = info->pixmap.buf_align - 1;
- unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
- unsigned int shift_high = 8, pitch, cnt, size, k;
- unsigned int idx = vc->vc_font.width >> 3;
- unsigned int attribute = get_attribute(info, scr_readw(s));
struct fb_image image;
- u8 *src, *dst, *buf = NULL;
-
- if (attribute) {
- buf = kmalloc(cellsize, GFP_KERNEL);
- if (!buf)
- return;
- }
+ u32 width = (vc->vc_font.width + 7)/8;
+ u32 cellsize = width * vc->vc_font.height;
+ u32 maxcnt = info->pixmap.size/cellsize;
+ u32 scan_align = info->pixmap.scan_align - 1;
+ u32 buf_align = info->pixmap.buf_align - 1;
+ u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
+ u32 attribute = get_attribute(info, scr_readw(s));
+ u8 *dst, *buf = NULL;
image.fg_color = fg;
image.bg_color = bg;
-
image.dx = xx * vc->vc_font.width;
image.dy = yy * vc->vc_font.height;
image.height = vc->vc_font.height;
image.depth = 1;
+ if (attribute) {
+ buf = kmalloc(cellsize, GFP_KERNEL);
+ if (!buf)
+ return;
+ }
+
while (count) {
if (count > maxcnt)
- cnt = k = maxcnt;
+ cnt = maxcnt;
else
- cnt = k = count;
+ cnt = count;
image.width = vc->vc_font.width * cnt;
pitch = ((image.width + 7) >> 3) + scan_align;
@@ -147,41 +209,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
size &= ~buf_align;
dst = fb_get_buffer_offset(info, &info->pixmap, size);
image.data = dst;
- if (mod) {
- while (k--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attribute) {
- update_attr(buf, src, attribute, vc);
- src = buf;
- }
-
- fb_pad_unaligned_buffer(dst, pitch, src, idx,
- image.height, shift_high,
- shift_low, mod);
- shift_low += mod;
- dst += (shift_low >= 8) ? width : width - 1;
- shift_low &= 7;
- shift_high = 8 - shift_low;
- }
- } else {
- while (k--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attribute) {
- update_attr(buf, src, attribute, vc);
- src = buf;
- }
-
- fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
- dst += width;
- }
- }
- info->fbops->fb_imageblit(info, &image);
+
+ if (!mod)
+ bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
+ width, cellsize, &image, buf, dst);
+ else
+ bit_putcs_unaligned(vc, info, s, attribute, cnt,
+ pitch, width, cellsize, &image,
+ buf, dst);
+
image.dx += cnt * vc->vc_font.width;
count -= cnt;
+ s += cnt;
}
/* buf is always NULL except when in monochrome mode, so in this case
@@ -189,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
NULL pointers just fine */
if (unlikely(buf))
kfree(buf);
+
}
static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 35c88bd7ba5e..0fc8bb499c3f 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -214,7 +214,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
static inline int get_color(struct vc_data *vc, struct fb_info *info,
u16 c, int is_fg)
{
- int depth = fb_get_color_depth(&info->var);
+ int depth = fb_get_color_depth(&info->var, &info->fix);
int color = 0;
if (console_blanked) {
@@ -230,9 +230,13 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
switch (depth) {
case 1:
{
+ int col = ~(0xfff << (max(info->var.green.length,
+ max(info->var.red.length,
+ info->var.blue.length)))) & 0xff;
+
/* 0 or 1 */
- int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
- int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
+ int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
+ int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
if (console_blanked)
fg = bg;
@@ -243,9 +247,25 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
case 2:
/*
* Scale down 16-colors to 4 colors. Default 4-color palette
- * is grayscale.
+ * is grayscale. However, simply dividing the values by 4
+ * will not work, as colors 1, 2 and 3 will be scaled-down
+ * to zero rendering them invisible. So empirically convert
+ * colors to a sane 4-level grayscale.
*/
- color /= 4;
+ switch (color) {
+ case 0:
+ color = 0; /* black */
+ break;
+ case 1 ... 6:
+ color = 2; /* white */
+ break;
+ case 7 ... 8:
+ color = 1; /* gray */
+ break;
+ default:
+ color = 3; /* intense white */
+ break;
+ }
break;
case 3:
/*
@@ -311,6 +331,35 @@ static void cursor_timer_handler(unsigned long dev_addr)
mod_timer(&ops->cursor_timer, jiffies + HZ/5);
}
+static void fbcon_add_cursor_timer(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+
+ if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
+ !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+ if (!info->queue.func)
+ INIT_WORK(&info->queue, fb_flashcursor, info);
+
+ init_timer(&ops->cursor_timer);
+ ops->cursor_timer.function = cursor_timer_handler;
+ ops->cursor_timer.expires = jiffies + HZ / 5;
+ ops->cursor_timer.data = (unsigned long ) info;
+ add_timer(&ops->cursor_timer);
+ ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
+ }
+}
+
+static void fbcon_del_cursor_timer(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+
+ if (info->queue.func == fb_flashcursor &&
+ ops->flags & FBCON_FLAGS_CURSOR_TIMER) {
+ del_timer_sync(&ops->cursor_timer);
+ ops->flags &= ~FBCON_FLAGS_CURSOR_TIMER;
+ }
+}
+
#ifndef MODULE
static int __init fb_console_setup(char *this_opt)
{
@@ -426,7 +475,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
* remove underline attribute from erase character
* if black and white framebuffer.
*/
- if (fb_get_color_depth(&info->var) == 1)
+ if (fb_get_color_depth(&info->var, &info->fix) == 1)
erase &= ~0x400;
logo_height = fb_prepare_logo(info);
logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -563,9 +612,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
}
if (!err) {
- if (oldinfo->queue.func == fb_flashcursor)
- del_timer_sync(&ops->cursor_timer);
-
+ fbcon_del_cursor_timer(oldinfo);
kfree(ops->cursor_state.mask);
kfree(ops->cursor_data);
kfree(oldinfo->fbcon_par);
@@ -576,22 +623,6 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
return err;
}
-static void con2fb_init_newinfo(struct fb_info *info)
-{
- if (!info->queue.func || info->queue.func == fb_flashcursor) {
- struct fbcon_ops *ops = info->fbcon_par;
-
- if (!info->queue.func)
- INIT_WORK(&info->queue, fb_flashcursor, info);
-
- init_timer(&ops->cursor_timer);
- ops->cursor_timer.function = cursor_timer_handler;
- ops->cursor_timer.expires = jiffies + HZ / 5;
- ops->cursor_timer.data = (unsigned long ) info;
- add_timer(&ops->cursor_timer);
- }
-}
-
static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
int unit, int show_logo)
{
@@ -675,7 +706,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
logo_shown != FBCON_LOGO_DONTSHOW);
if (!found)
- con2fb_init_newinfo(info);
+ fbcon_add_cursor_timer(info);
con2fb_map_boot[unit] = newidx;
con2fb_init_display(vc, info, unit, show_logo);
}
@@ -736,7 +767,7 @@ static const char *fbcon_startup(void)
const char *display_desc = "frame buffer device";
struct display *p = &fb_display[fg_console];
struct vc_data *vc = vc_cons[fg_console].d;
- struct font_desc *font = NULL;
+ const struct font_desc *font = NULL;
struct module *owner;
struct fb_info *info = NULL;
struct fbcon_ops *ops;
@@ -810,7 +841,7 @@ static const char *fbcon_startup(void)
info->var.yres);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
- vc->vc_font.data = p->fontdata = font->data;
+ vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
}
@@ -878,18 +909,7 @@ static const char *fbcon_startup(void)
}
#endif /* CONFIG_MAC */
- /* Initialize the work queue. If the driver provides its
- * own work queue this means it will use something besides
- * default timer to flash the cursor. */
- if (!info->queue.func) {
- INIT_WORK(&info->queue, fb_flashcursor, info);
-
- init_timer(&ops->cursor_timer);
- ops->cursor_timer.function = cursor_timer_handler;
- ops->cursor_timer.expires = jiffies + HZ / 5;
- ops->cursor_timer.data = (unsigned long ) info;
- add_timer(&ops->cursor_timer);
- }
+ fbcon_add_cursor_timer(info);
return display_desc;
}
@@ -921,7 +941,7 @@ static void fbcon_init(struct vc_data *vc, int init)
fb, copy the font from that console */
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -930,7 +950,7 @@ static void fbcon_init(struct vc_data *vc, int init)
}
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -1168,7 +1188,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
return;
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1178,7 +1198,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(var) != 1);
+ var->activate = FB_ACTIVATE_NOW;
+ info->var.activate = var->activate;
+ info->var.yoffset = info->var.xoffset = 0;
+ fb_set_var(info, var);
+
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -1662,6 +1687,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
+ if (logo_shown >= 0)
+ goto redraw_down;
switch (p->scrollmode) {
case SCROLL_MOVE:
ops->bmove(vc, info, t, 0, t + count, 0,
@@ -1898,7 +1925,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
static int fbcon_switch(struct vc_data *vc)
{
- struct fb_info *info;
+ struct fb_info *info, *old_info = NULL;
struct display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
int i, prev_console;
@@ -1931,7 +1958,8 @@ static int fbcon_switch(struct vc_data *vc)
}
prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon;
-
+ if (prev_console != -1)
+ old_info = registered_fb[con2fb_map[prev_console]];
/*
* FIXME: If we have multiple fbdev's loaded, we need to
* update all info->currcon. Perhaps, we can place this
@@ -1959,15 +1987,17 @@ static int fbcon_switch(struct vc_data *vc)
info->var.yoffset = info->var.xoffset = p->yscroll = 0;
fb_set_var(info, &var);
- if (prev_console != -1 &&
- registered_fb[con2fb_map[prev_console]] != info &&
- info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
+ if (old_info != NULL && old_info != info) {
+ if (info->fbops->fb_set_par)
+ info->fbops->fb_set_par(info);
+ fbcon_del_cursor_timer(old_info);
+ fbcon_add_cursor_timer(info);
+ }
set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
- vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
updatescrollmode(p, info, vc);
@@ -2048,11 +2078,16 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
fbcon_generic_blank(vc, info, blank);
}
- if (!blank)
- update_screen(vc);
- }
+ if (!blank)
+ update_screen(vc);
+ }
+
+ if (!blank)
+ fbcon_add_cursor_timer(info);
+ else
+ fbcon_del_cursor_timer(info);
- return 0;
+ return 0;
}
static void fbcon_free_font(struct display *p)
@@ -2115,7 +2150,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
}
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
- u8 * data, int userfont)
+ const u8 * data, int userfont)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
@@ -2133,7 +2168,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
cnt = FNTCHARCNT(data);
else
cnt = 256;
- vc->vc_font.data = p->fontdata = data;
+ vc->vc_font.data = (void *)(p->fontdata = data);
if ((p->userfont = userfont))
REFCOUNT(data)++;
vc->vc_font.width = w;
@@ -2290,7 +2325,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
- new_data = fb_display[i].fontdata;
+ new_data = (u8 *)fb_display[i].fontdata;
break;
}
}
@@ -2300,7 +2335,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- struct font_desc *f;
+ const struct font_desc *f;
if (!name)
f = get_default_font(info->var.xres, info->var.yres);
@@ -2332,7 +2367,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
if (!CON_IS_VISIBLE(vc))
return 0;
- depth = fb_get_color_depth(&info->var);
+ depth = fb_get_color_depth(&info->var, &info->fix);
if (depth > 3) {
for (i = j = 0; i < 16; i++) {
k = table[i];
@@ -2593,6 +2628,51 @@ static void fbcon_modechanged(struct fb_info *info)
}
}
+static void fbcon_set_all_vcs(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct vc_data *vc;
+ struct display *p;
+ int i, rows, cols;
+
+ if (!ops || ops->currcon < 0)
+ return;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ vc = vc_cons[i].d;
+ if (!vc || vc->vc_mode != KD_TEXT ||
+ registered_fb[con2fb_map[i]] != info)
+ continue;
+
+ p = &fb_display[vc->vc_num];
+
+ info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+ var_to_display(p, &info->var, info);
+ cols = info->var.xres / vc->vc_font.width;
+ rows = info->var.yres / vc->vc_font.height;
+ vc_resize(vc, cols, rows);
+
+ if (CON_IS_VISIBLE(vc)) {
+ updatescrollmode(p, info, vc);
+ scrollback_max = 0;
+ scrollback_current = 0;
+ update_var(vc->vc_num, info);
+ fbcon_set_palette(vc, color_table);
+ update_screen(vc);
+ if (softback_buf) {
+ int l = fbcon_softback_size / vc->vc_size_row;
+ if (l > 5)
+ softback_end = softback_buf + l * vc->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0
+ would screw the operation totally */
+ softback_top = 0;
+ }
+ }
+ }
+ }
+}
+
static int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
{
@@ -2708,6 +2788,9 @@ static int fbcon_event_notify(struct notifier_block *self,
case FB_EVENT_MODE_CHANGE:
fbcon_modechanged(info);
break;
+ case FB_EVENT_MODE_CHANGE_ALL:
+ fbcon_set_all_vcs(info);
+ break;
case FB_EVENT_MODE_DELETE:
mode = event->data;
ret = fbcon_mode_deleted(info, mode);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 5d377860bce2..0738cd62def2 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,7 +18,8 @@
#include <asm/io.h>
-#define FBCON_FLAGS_INIT 1
+#define FBCON_FLAGS_INIT 1
+#define FBCON_FLAGS_CURSOR_TIMER 2
/*
* This is the interface between the low-level console driver and the
@@ -29,7 +30,7 @@ struct display {
/* Filled in by the frame buffer device */
u_short inverse; /* != 0 text black on white as default */
/* Filled in by the low-level console driver */
- u_char *fontdata;
+ const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
short yscroll; /* Hardware scrolling */
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index ff0af96e4dfc..e6aa0eab5bb6 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 9216
-static unsigned char fontdata_10x18[FONTDATAMAX] = {
+static const unsigned char fontdata_10x18[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 0000000000 */
@@ -5132,7 +5132,7 @@ static unsigned char fontdata_10x18[FONTDATAMAX] = {
};
-struct font_desc font_10x18 = {
+const struct font_desc font_10x18 = {
FONT10x18_IDX,
"10x18",
10,
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index c52f1294044a..89976cd97494 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX (11*256)
-static unsigned char fontdata_6x11[FONTDATAMAX] = {
+static const unsigned char fontdata_6x11[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = {
};
-struct font_desc font_vga_6x11 = {
+const struct font_desc font_vga_6x11 = {
VGA6x11_IDX,
"ProFont6x11",
6,
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index 1fa7fcf2ff72..bbf116647397 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 3584
-static unsigned char fontdata_7x14[FONTDATAMAX] = {
+static const unsigned char fontdata_7x14[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 0000000 */
@@ -4108,7 +4108,7 @@ static unsigned char fontdata_7x14[FONTDATAMAX] = {
};
-struct font_desc font_7x14 = {
+const struct font_desc font_7x14 = {
FONT7x14_IDX,
"7x14",
7,
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index e6f8dbaa122b..74fe86f28ff4 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_8x16[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x16 = {
+const struct font_desc font_vga_8x16 = {
VGA8x16_IDX,
"VGA8x16",
8,
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 57fbe266a6b9..26199f8ee908 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x8 = {
+const struct font_desc font_vga_8x8 = {
VGA8x8_IDX,
"VGA8x8",
8,
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index d565505e3069..2d2e39632e2d 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -3,7 +3,7 @@
#include <linux/config.h>
#include <linux/font.h>
-static unsigned char acorndata_8x8[] = {
+static const unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -262,7 +262,7 @@ static unsigned char acorndata_8x8[] = {
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-struct font_desc font_acorn_8x8 = {
+const struct font_desc font_acorn_8x8 = {
ACORN8x8_IDX,
"Acorn8x8",
8,
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 593b95500a0c..d818234fdf11 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -43,7 +43,7 @@ __END__;
#define FONTDATAMAX 1536
-static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
+static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*{*/
/* Char 0: ' ' */
@@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*}*/
};
-struct font_desc font_mini_4x6 = {
+const struct font_desc font_mini_4x6 = {
MINI4x6_IDX,
"MINI4x6",
4,
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index 5fa95f118818..e646c88f55c7 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -13,7 +13,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
};
-struct font_desc font_pearl_8x8 = {
+const struct font_desc font_pearl_8x8 = {
PEARL8x8_IDX,
"PEARL8x8",
8,
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index c7bd967ea100..ab5eb93407b4 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 11264
-static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
+static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 000000000000 */
@@ -6151,7 +6151,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
};
-struct font_desc font_sun_12x22 = {
+const struct font_desc font_sun_12x22 = {
SUN12x22_IDX,
"SUN12x22",
12,
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 2af3ab354652..41f910f5529c 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
@@ -261,7 +261,7 @@ static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
-struct font_desc font_sun_8x16 = {
+const struct font_desc font_sun_8x16 = {
SUN8x16_IDX,
"SUN8x16",
8,
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index e79b29702649..4fd07d9eca03 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -23,7 +23,7 @@
#define NO_FONTS
-static struct font_desc *fonts[] = {
+static const struct font_desc *fonts[] = {
#ifdef CONFIG_FONT_8x8
#undef NO_FONTS
&font_vga_8x8,
@@ -84,7 +84,7 @@ static struct font_desc *fonts[] = {
*
*/
-struct font_desc *find_font(char *name)
+const struct font_desc *find_font(const char *name)
{
unsigned int i;
@@ -108,10 +108,10 @@ struct font_desc *find_font(char *name)
*
*/
-struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres)
{
int i, c, cc;
- struct font_desc *f, *g;
+ const struct font_desc *f, *g;
g = NULL;
cc = -10000;
@@ -138,7 +138,6 @@ struct font_desc *get_default_font(int xres, int yres)
return g;
}
-EXPORT_SYMBOL(fonts);
EXPORT_SYMBOL(find_font);
EXPORT_SYMBOL(get_default_font);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d27fa91e5886..0705cd741411 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -497,6 +497,57 @@ static void vgacon_cursor(struct vc_data *c, int mode)
}
}
+static int vgacon_doresize(struct vc_data *c,
+ unsigned int width, unsigned int height)
+{
+ unsigned long flags;
+ unsigned int scanlines = height * c->vc_font.height;
+ u8 scanlines_lo, r7, vsync_end, mode;
+
+ spin_lock_irqsave(&vga_lock, flags);
+
+ outb_p(VGA_CRTC_MODE, vga_video_port_reg);
+ mode = inb_p(vga_video_port_val);
+
+ if (mode & 0x04)
+ scanlines >>= 1;
+
+ scanlines -= 1;
+ scanlines_lo = scanlines & 0xff;
+
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ r7 = inb_p(vga_video_port_val) & ~0x42;
+
+ if (scanlines & 0x100)
+ r7 |= 0x02;
+ if (scanlines & 0x200)
+ r7 |= 0x40;
+
+ /* deprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ vsync_end = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end & ~0x80, vga_video_port_val);
+
+ outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
+ outb_p(width - 1, vga_video_port_val);
+ outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
+ outb_p(width >> 1, vga_video_port_val);
+
+ outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
+ outb_p(scanlines_lo, vga_video_port_val);
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ outb_p(r7,vga_video_port_val);
+
+ /* reprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end, vga_video_port_val);
+
+ spin_unlock_irqrestore(&vga_lock, flags);
+
+ return 0;
+}
+
static int vgacon_switch(struct vc_data *c)
{
/*
@@ -510,9 +561,13 @@ static int vgacon_switch(struct vc_data *c)
/* We can only copy out the size of the video buffer here,
* otherwise we get into VGA BIOS */
- if (!vga_is_gfx)
+ if (!vga_is_gfx) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
- c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+ vgacon_doresize(c, c->vc_cols, c->vc_rows);
+ }
+
return 0; /* Redrawing not needed */
}
@@ -962,6 +1017,17 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
#endif
+static int vgacon_resize(struct vc_data *c, unsigned int width,
+ unsigned int height)
+{
+ if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
+ return -EINVAL;
+
+ if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
+ vgacon_doresize(c, width, height);
+ return 0;
+}
+
static int vgacon_scrolldelta(struct vc_data *c, int lines)
{
if (!lines) /* Turn scrollback off */
@@ -1103,6 +1169,7 @@ const struct consw vga_con = {
.con_blank = vgacon_blank,
.con_font_set = vgacon_font_set,
.con_font_get = vgacon_font_get,
+ .con_resize = vgacon_resize,
.con_set_palette = vgacon_set_palette,
.con_scrolldelta = vgacon_scrolldelta,
.con_set_origin = vgacon_set_origin,
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
new file mode 100644
index 000000000000..ae2762cb5608
--- /dev/null
+++ b/drivers/video/cyblafb.c
@@ -0,0 +1,1456 @@
+/*
+ * Frame buffer driver for Trident Cyberblade/i1 graphics core
+ *
+ * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de>
+ *
+ * CREDITS:
+ * tridentfb.c by Jani Monoses
+ * see files above for further credits
+ *
+ * TODO:
+ *
+ */
+
+#define CYBLAFB_DEBUG 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/types.h>
+#include <video/cyblafb.h>
+
+#define VERSION "0.54"
+
+struct cyblafb_par {
+ u32 pseudo_pal[16];
+ struct fb_ops ops;
+};
+
+static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
+ .id = "CyBla",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .ypanstep = 1,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static char *mode __devinitdata = NULL;
+static int bpp __devinitdata = 8;
+static int ref __devinitdata = 75;
+static int fp __devinitdata;
+static int crt __devinitdata;
+static int memsize __devinitdata;
+static int vesafb __devinitdata;
+
+static int nativex;
+static int center;
+static int stretch;
+static int pciwb = 1;
+static int pcirb = 1;
+static int pciwr = 1;
+static int pcirr = 1;
+static int verbosity;
+static int displaytype;
+
+static void __iomem * io_virt; // iospace virtual memory address
+
+module_param(mode,charp,0);
+module_param(bpp,int,0);
+module_param(ref,int,0);
+module_param(fp,int,0);
+module_param(crt,int,0);
+module_param(nativex,int,0);
+module_param(center,int,0);
+module_param(stretch,int,0);
+module_param(pciwb,int,0);
+module_param(pcirb,int,0);
+module_param(pciwr,int,0);
+module_param(pcirr,int,0);
+module_param(memsize,int,0);
+module_param(verbosity,int,0);
+module_param(vesafb,int,0);
+
+//=========================================
+//
+// Port access macros for memory mapped io
+//
+//=========================================
+
+#define out8(r,v) writeb(v,io_virt+r)
+#define out32(r,v) writel(v,io_virt+r)
+#define in8(r) readb(io_virt+r)
+#define in32(r) readl(io_virt+r)
+
+//======================================
+//
+// Hardware access inline functions
+//
+//======================================
+
+static inline unsigned char read3X4(int reg)
+{
+ out8(0x3D4,reg);
+ return in8(0x3D5);
+}
+
+static inline unsigned char read3C4(int reg)
+{
+ out8(0x3C4,reg);
+ return in8(0x3C5);
+}
+
+static inline unsigned char read3CE(int reg)
+{
+ out8(0x3CE,reg);
+ return in8(0x3CF);
+}
+
+static inline void write3X4(int reg,unsigned char val)
+{
+ out8(0x3D4,reg);
+ out8(0x3D5,val);
+}
+
+static inline void write3C4(int reg,unsigned char val)
+{
+ out8(0x3C4,reg);
+ out8(0x3C5,val);
+}
+
+static inline void write3CE(int reg,unsigned char val)
+{
+ out8(0x3CE,reg);
+ out8(0x3CF,val);
+}
+
+static inline void write3C0(int reg,unsigned char val)
+{
+ in8(0x3DA); // read to reset index
+ out8(0x3C0,reg);
+ out8(0x3C0,val);
+}
+
+//=================================================
+//
+// Enable memory mapped io and unprotect registers
+//
+//=================================================
+
+static inline void enable_mmio(void)
+{
+ int tmp;
+
+ outb(0x0B,0x3C4);
+ inb(0x3C5); // Set NEW mode
+ outb(SR0E,0x3C4); // write enable a lot of extended ports
+ outb(0x80,0x3C5);
+
+ outb(SR11,0x3C4); // write enable those extended ports that
+ outb(0x87,0x3C5); // are not affected by SR0E_New
+
+ outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2
+ tmp=inb(0x3d5) & 0xBF;
+ outb(CR1E,0x3d4);
+ outb(tmp,0x3d5);
+
+ outb(CR39,0x3D4);
+ outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched
+}
+
+//=================================================
+//
+// Set pixel clock VCLK1
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+//=================================================
+
+static void set_vclk(struct cyblafb_par *par, int freq)
+{
+ u32 m,n,k;
+ int f,fi,d,di;
+ u8 lo=0,hi=0;
+
+ d = 2000;
+ k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
+ for(m = 0;m<64;m++)
+ for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 !
+ fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12);
+ if ((di = abs(fi - freq)) < d) {
+ d = di;
+ f = fi;
+ lo = (u8) n;
+ hi = (u8) ((k<<6) | m);
+ }
+ }
+ write3C4(SR19,hi);
+ write3C4(SR18,lo);
+ if(verbosity > 1)
+ output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
+ freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+}
+
+//================================================
+//
+// Cyberblade specific Graphics Engine (GE) setup
+//
+//================================================
+
+static void cyblafb_setup_GE(int pitch,int bpp)
+{
+ int base = (pitch>>3)<<20;
+
+ switch (bpp) {
+ case 8: base |= (0<<29); break;
+ case 15: base |= (5<<29); break;
+ case 16: base |= (1<<29); break;
+ case 24:
+ case 32: base |= (2<<29); break;
+ }
+
+ write3X4(CR36,0x90); // reset GE
+ write3X4(CR36,0x80); // enable GE
+
+ out32(GE24,1<<7); // reset all GE pointers
+ out32(GE24,0);
+
+ write3X4(CR2D,0x00); // GE Timinigs, no delays
+
+ out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
+ out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
+ out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
+ out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
+ out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
+ out32(GECC,base); // Source Stride / Buffer Base 1, p 133
+ out32(GED0,base); // Source Stride / Buffer Base 2, p 133
+ out32(GED4,base); // Source Stride / Buffer Base 3, p 133
+ out32(GE6C,0); // Pattern and Style, p 129, ok
+}
+
+//=====================================================================
+//
+// Although this is a .fb_sync function that could be enabled in
+// cyblafb_ops, we do not include it there. We sync immediately before
+// new GE operations to improve performance.
+//
+//=====================================================================
+
+static int cyblafb_sync(struct fb_info *info)
+{
+ int status, i=100000;
+ while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ i--;
+
+ if (i == 0) {
+ // The timeout might be caused by disabled mmio.
+ // Cause:
+ // - bit CR39 & 1 == 0 upon return, X trident driver bug
+ // - kdm bug (KD_GRAPHICS not set on first switch)
+ // - kernel design flaw (it believes in the correctness
+ // of kdm/X
+ // So we make sure that mmio is enabled first ...
+ enable_mmio();
+// show_trace(NULL,&status);
+ i=1000000;
+ while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ i--;
+ if (i == 0) {
+ output("GE Timeout, status: %x\n",status);
+ if(status & 0x80000000)
+ output("Bresenham Engine : Busy\n");
+ if(status & 0x40000000)
+ output("Setup Engine : Busy\n");
+ if(status & 0x20000000)
+ output("SP / DPE : Busy\n");
+ if(status & 0x10000000)
+ output("Memory Interface : Busy\n");
+ if(status & 0x08000000)
+ output("Com Lst Proc : Busy\n");
+ if(status & 0x04000000)
+ output("Block Write : Busy\n");
+ if(status & 0x02000000)
+ output("Command Buffer : Full\n");
+ if(status & 0x01000000)
+ output("RESERVED : Busy\n");
+ if(status & 0x00800000)
+ output("PCI Write Buffer : Busy\n");
+ cyblafb_setup_GE(info->var.xres,
+ info->var.bits_per_pixel);
+ }
+ }
+
+ return 0;
+}
+
+//==============================
+//
+// Cyberblade specific fillrect
+//
+//==============================
+
+static void cyblafb_fillrect(struct fb_info * info,
+ const struct fb_fillrect *fr)
+{
+ int bpp = info->var.bits_per_pixel;
+ int col;
+
+ switch (bpp) {
+ default:
+ case 8: col = fr->color;
+ col |= col <<8;
+ col |= col <<16;
+ break;
+ case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
+ col |= col <<16;
+ break;
+ case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
+ break;
+ }
+
+ cyblafb_sync(info);
+
+ out32(GE60,col);
+ out32(GE48,fr->rop ? 0x66:ROP_S);
+ out32(GE44,0x20000000|1<<19|1<<4|2<<2);
+ out32(GE08,point(fr->dx,fr->dy));
+ out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1));
+
+}
+
+//==============================
+//
+// Cyberblade specific copyarea
+//
+//==============================
+
+static void cyblafb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *ca)
+{
+ __u32 s1,s2,d1,d2;
+ int direction;
+
+ s1 = point(ca->sx,ca->sy);
+ s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
+ d1 = point(ca->dx,ca->dy);
+ d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
+ if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
+ direction = 0;
+ else
+ direction = 2;
+
+ cyblafb_sync(info);
+
+ out32(GE44,0xa0000000|1<<19|1<<2|direction);
+ out32(GE00,direction?s2:s1);
+ out32(GE04,direction?s1:s2);
+ out32(GE08,direction?d2:d1);
+ out32(GE0C,direction?d1:d2);
+
+}
+
+//=======================================================================
+//
+// Cyberblade specific imageblit
+//
+// Accelerated for the most usual case, blitting 1-bit deep character
+// character images. Everything else is passed to the generic imageblit.
+//
+//=======================================================================
+
+static void cyblafb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+
+ u32 fgcol, bgcol;
+
+ int i;
+ int bpp = info->var.bits_per_pixel;
+ int index = 0;
+ int index_end=image->height * image->width / 8;
+ int width_dds=image->width / 32;
+ int width_dbs=image->width % 32;
+
+ if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 ||
+ image->width % 8 != 0 || image->width == 0 || image->height == 0) {
+ cfb_imageblit(info,image);
+ return;
+ }
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ fgcol = ((u32*)(info->pseudo_palette))[image->fg_color];
+ bgcol = ((u32*)(info->pseudo_palette))[image->bg_color];
+ } else {
+ fgcol = image->fg_color;
+ bgcol = image->bg_color;
+ }
+
+ switch (bpp) {
+ case 8:
+ fgcol |= fgcol <<8; fgcol |= fgcol <<16;
+ bgcol |= bgcol <<8; bgcol |= bgcol <<16;
+ break;
+ case 16:
+ fgcol |= fgcol <<16;
+ bgcol |= bgcol <<16;
+ break;
+ default:
+ break;
+ }
+
+ cyblafb_sync(info);
+
+ out32(GE60,fgcol);
+ out32(GE64,bgcol);
+ out32(GE44,0xa0000000 | 1<<20 | 1<<19);
+ out32(GE08,point(image->dx,image->dy));
+ out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
+
+ while(index < index_end) {
+ for(i=0;i<width_dds;i++) {
+ out32(GE9C,*((u32*) ((u32)image->data + index)));
+ index+=4;
+ }
+ switch(width_dbs) {
+ case 0: break;
+ case 8: out32(GE9C,*((u8*)((u32)image->data+index)));
+ index+=1;
+ break;
+ case 16: out32(GE9C,*((u16*)((u32)image->data+index)));
+ index+=2;
+ break;
+ case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) |
+ (u32)(*((u8*)((u32)image->data+index+2)))<<16);
+ index+=3;
+ break;
+ }
+ }
+}
+
+//==========================================================
+//
+// Check if video mode is acceptable. We change var->??? if
+// video mode is slightly off or return error otherwise.
+// info->??? must not be changed!
+//
+//==========================================================
+
+static int cyblafb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int bpp = var->bits_per_pixel;
+ int s,t,maxvyres;
+
+ //
+ // we try to support 8, 16, 24 and 32 bpp modes,
+ // default to 8
+ //
+ // there is a 24 bpp mode, but for now we change requests to 32 bpp
+ // (This is what tridentfb does ... will be changed in the future)
+ //
+ //
+ if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+ bpp = 8;
+ if (bpp == 24 )
+ bpp = var->bits_per_pixel = 32;
+
+ //
+ // interlaced modes are broken, fail if one is requested
+ //
+ if (var->vmode & FB_VMODE_INTERLACED)
+ return -EINVAL;
+
+ //
+ // fail if requested resolution is higher than physical
+ // flatpanel resolution
+ //
+ if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex)
+ return -EINVAL;
+
+ //
+ // xres != xres_virtual is broken, fail if such an
+ // unusual mode is requested
+ //
+ if (var->xres != var->xres_virtual)
+ return -EINVAL;
+
+ //
+ // we do not allow vclk to exceed 230 MHz
+ //
+ if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
+ return -EINVAL;
+
+ //
+ // calc max yres_virtual that would fit in memory
+ // and max yres_virtual that could be used for scrolling
+ // and use minimum of the results as maxvyres
+ //
+ // adjust vyres_virtual to maxvyres if necessary
+ // fail if requested yres is bigger than maxvyres
+ //
+ s = (0x1fffff / (var->xres * bpp/8)) + var->yres;
+ t = info->fix.smem_len / (var->xres * bpp/8);
+ maxvyres = t < s ? t : s;
+ if (maxvyres < var->yres_virtual)
+ var->yres_virtual=maxvyres;
+ if (maxvyres < var->yres)
+ return -EINVAL;
+
+ switch (bpp) {
+ case 8:
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
+//=====================================================================
+//
+// Pan the display
+//
+// The datasheets defines crt start address to be 20 bits wide and
+// to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is
+// CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use
+// it, so it is also safe to be used here. BTW: datasheet CR0E on page
+// 90 really is CR1E, the real CRE is documented on page 72.
+//
+//=====================================================================
+
+static int cyblafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ unsigned int offset;
+
+ offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+
+ write3X4(CR0D,offset & 0xFF);
+ write3X4(CR0C,(offset & 0xFF00) >> 8);
+ write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
+ write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
+ write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
+
+ return 0;
+}
+
+//============================================
+//
+// This will really help in case of a bug ...
+// dump most gaphics core registers.
+//
+//============================================
+
+static void regdump(struct cyblafb_par *par)
+{
+ int i;
+
+ if (verbosity < 2)
+ return;
+
+ printk("\n");
+ for(i=0; i<=0xff; i++) {
+ outb(i,0x3d4);
+ printk("CR%02x=%02x ",i,inb(0x3d5));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ outb(0x30,0x3ce);
+ outb(inb(0x3cf) | 0x40,0x3cf);
+ for(i=0; i<=0x1f; i++) {
+ if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) {
+ outb(i,0x3d4);
+ printk("CR%02x=%02x ",i,inb(0x3d5));
+ } else
+ printk("------- ");
+ if (i%16==15)
+ printk("\n");
+ }
+ outb(0x30,0x3ce);
+ outb(inb(0x3cf) & 0xbf,0x3cf);
+
+ printk("\n");
+ for(i=0; i<=0x7f; i++) {
+ outb(i,0x3ce);
+ printk("GR%02x=%02x ",i,inb(0x3cf));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ printk("\n");
+ for(i=0; i<=0xff; i++) {
+ outb(i,0x3c4);
+ printk("SR%02x=%02x ",i,inb(0x3c5));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ printk("\n");
+ for(i=0; i <= 0x1F; i++) {
+ inb(0x3da); // next access is index!
+ outb(i,0x3c0);
+ printk("AR%02x=%02x ",i,inb(0x3c1));
+ if (i%16==15)
+ printk("\n");
+ }
+ printk("\n");
+
+ inb(0x3DA); // reset internal flag to 3c0 index
+ outb(0x20,0x3C0); // enable attr
+
+ return;
+}
+
+//======================================
+//
+// Set hardware to requested video mode
+//
+//======================================
+
+static int cyblafb_set_par(struct fb_info *info)
+{
+ struct cyblafb_par *par = info->par;
+ u32
+ htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch,
+ vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
+ struct fb_var_screeninfo *var = &info->var;
+ int bpp = var->bits_per_pixel;
+ int i;
+
+ if (verbosity > 0)
+ output("Switching to new mode: "
+ "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
+ var->xres,var->yres,var->xres_virtual,
+ var->yres_virtual,var->bits_per_pixel,var->pixclock,
+ var->left_margin,var->right_margin,var->upper_margin,
+ var->lower_margin,var->hsync_len,var->vsync_len);
+
+ htotal = (var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) / 8 - 5;
+ hdispend = var->xres/8 - 1;
+ hsyncstart = (var->xres + var->right_margin)/8;
+ hsyncend = var->hsync_len/8;
+ hblankstart = hdispend + 1;
+ hblankend = htotal + 3; // should be htotal + 5, bios does it this way
+ preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3);
+
+ vtotal = var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len - 2;
+ vdispend = var->yres - 1;
+ vsyncstart = var->yres + var->lower_margin;
+ vblankstart = var->yres;
+ vblankend = vtotal; // should be vtotal + 2, but bios does it this way
+ vsyncend = var->vsync_len;
+
+ enable_mmio(); // necessary! ... check X ...
+
+ write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+
+ write3CE(GR30,8);
+
+ if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
+
+ // stretch or center ?
+
+ out8(0x3C2,0xEB);
+
+ write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+
+ if (center) {
+ write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80);
+ write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80);
+ }
+ else if (stretch) {
+ write3CE(GR5D,0);
+ write3CE(GR52,(read3CE(GR52) & 0x7C) | 1);
+ write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
+ }
+
+ } else {
+ out8(0x3C2,0x2B);
+ write3CE(GR30,8);
+ }
+
+ //
+ // Setup CRxx regs
+ //
+
+ write3X4(CR00,htotal & 0xFF);
+ write3X4(CR01,hdispend & 0xFF);
+ write3X4(CR02,hblankstart & 0xFF);
+ write3X4(CR03,hblankend & 0x1F);
+ write3X4(CR04,hsyncstart & 0xFF);
+ write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
+ write3X4(CR06,vtotal & 0xFF);
+ write3X4(CR07,(vtotal & 0x100) >> 8 |
+ (vdispend & 0x100) >> 7 |
+ (vsyncstart & 0x100) >> 6 |
+ (vblankstart & 0x100) >> 5 |
+ 0x10 |
+ (vtotal & 0x200) >> 4 |
+ (vdispend & 0x200) >> 3 |
+ (vsyncstart & 0x200) >> 2);
+ write3X4(CR08,0);
+ write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 | // FIX !!!
+ ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
+ write3X4(CR0A,0); // Init to some reasonable default
+ write3X4(CR0B,0); // Init to some reasonable default
+ write3X4(CR0C,0); // Offset 0
+ write3X4(CR0D,0); // Offset 0
+ write3X4(CR0E,0); // Init to some reasonable default
+ write3X4(CR0F,0); // Init to some reasonable default
+ write3X4(CR10,vsyncstart & 0xFF);
+ write3X4(CR11,(vsyncend & 0x0F));
+ write3X4(CR12,vdispend & 0xFF);
+ write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF);
+ write3X4(CR14,0x40); // double word mode
+ write3X4(CR15,vblankstart & 0xFF);
+ write3X4(CR16,vblankend & 0xFF);
+ write3X4(CR17,0xC3);
+ write3X4(CR18,0xFF);
+ // CR19: needed for interlaced modes ... ignore it for now
+ write3X4(CR1A,0x07); // Arbitration Control Counter 1
+ write3X4(CR1B,0x07); // Arbitration Control Counter 2
+ write3X4(CR1C,0x07); // Arbitration Control Counter 3
+ write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-)
+ write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
+ // CR1F: do not set, contains BIOS info about memsize
+ write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode
+ write3X4(CR21,0x20); // enable linear memory access
+ // CR22: RO cpu latch readback
+ // CR23: ???
+ // CR24: RO AR flag state
+ // CR25: RAMDAC rw timing, pclk buffer tristate control ????
+ // CR26: ???
+ write3X4(CR27,(vdispend & 0x400) >> 6 |
+ (vsyncstart & 0x400) >> 5 |
+ (vblankstart & 0x400) >> 4 |
+ (vtotal & 0x400) >> 3 |
+ 0x8);
+ // CR28: ???
+ write3X4(CR29,(read3X4(CR29) & 0xCF) |
+ ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4));
+ write3X4(CR2A,read3X4(CR2A) | 0x40);
+ write3X4(CR2B,(htotal & 0x100) >> 8 |
+ (hdispend & 0x100) >> 7 |
+ // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ???
+ (hsyncstart & 0x100) >> 5 |
+ (hblankstart & 0x100) >> 4);
+ // CR2C: ???
+ // CR2D: initialized in cyblafb_setup_GE()
+ write3X4(CR2F,0x92); // conservative, better signal quality
+ // CR30: reserved
+ // CR31: reserved
+ // CR32: reserved
+ // CR33: reserved
+ // CR34: disabled in CR36
+ // CR35: disabled in CR36
+ // CR36: initialized in cyblafb_setup_GE
+ // CR37: i2c, ignore for now
+ write3X4(CR38,(bpp == 8) ? 0x00 : //
+ (bpp == 16) ? 0x05 : // highcolor
+ (bpp == 24) ? 0x29 : // packed 24bit truecolor
+ (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
+ write3X4(CR39,0x01 | // MMIO enable
+ (pcirb ? 0x02 : 0) | // pci read burst enable
+ (pciwb ? 0x04 : 0)); // pci write burst enable
+ write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase
+ (pcirr ? 0x40 : 0) | // pci read retry enable
+ (pciwr ? 0x80 : 0)); // pci write retry enable
+ write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0);
+ write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
+ write3X4(CR58,0x82); // Bios does this .... don't know more
+ //
+ // Setup SRxx regs
+ //
+ write3C4(SR00,3);
+ write3C4(SR01,1); //set char clock 8 dots wide
+ write3C4(SR02,0x0F); //enable 4 maps needed in chain4 mode
+ write3C4(SR03,0); //no character map select
+ write3C4(SR04,0x0E); //memory mode: ext mem, even, chain4
+
+ out8(0x3C4,0x0b);
+ in8(0x3C5); // Set NEW mode
+ write3C4(SR0D,0x00); // test ... check
+
+ set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
+ info->var.pixclock); //SR18,SR19
+
+ //
+ // Setup GRxx regs
+ //
+ write3CE(GR00,0x00); // test ... check
+ write3CE(GR01,0x00); // test ... check
+ write3CE(GR02,0x00); // test ... check
+ write3CE(GR03,0x00); // test ... check
+ write3CE(GR04,0x00); // test ... check
+ write3CE(GR05,0x40); // no CGA compat,allow 256 col
+ write3CE(GR06,0x05); // graphics mode
+ write3CE(GR07,0x0F); // planes?
+ write3CE(GR08,0xFF); // test ... check
+ write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4
+ write3CE(GR20,0xC0); // test ... check
+ write3CE(GR2F,0xA0); // PCLK = VCLK, no skew,
+
+ //
+ // Setup ARxx regs
+ //
+ for(i = 0;i < 0x10;i++) // set AR00 .. AR0f
+ write3C0(i,i);
+ write3C0(AR10,0x41); // graphics mode and support 256 color modes
+ write3C0(AR12,0x0F); // planes
+ write3C0(AR13,0); // horizontal pel panning
+ in8(0x3DA); // reset internal flag to 3c0 index
+ out8(0x3C0,0x20); // enable attr
+
+ //
+ // Setup hidden RAMDAC command register
+ //
+ in8(0x3C8); // these reads are
+ in8(0x3C6); // necessary to
+ in8(0x3C6); // unmask the RAMDAC
+ in8(0x3C6); // command reg, otherwise
+ in8(0x3C6); // we would write the pixelmask reg!
+ out8(0x3C6,(bpp == 8) ? 0x00 : // 256 colors
+ (bpp == 15) ? 0x10 : //
+ (bpp == 16) ? 0x30 : // hicolor
+ (bpp == 24) ? 0xD0 : // truecolor
+ (bpp == 32) ? 0xD0 : 0); // truecolor
+ in8(0x3C8);
+
+ //
+ // GR31 is not mentioned in the datasheet
+ //
+ if (displaytype == DISPLAY_FP)
+ write3CE(GR31,(read3CE(GR31) & 0x8F) |
+ ((info->var.yres > 1024) ? 0x50 :
+ (info->var.yres > 768) ? 0x30 :
+ (info->var.yres > 600) ? 0x20 :
+ (info->var.yres > 480) ? 0x10 : 0));
+
+ info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_TRUECOLOR;
+ info->fix.line_length = info->var.xres * (bpp >> 3);
+ info->cmap.len = (bpp == 8) ? 256: 16;
+
+ //
+ // init acceleration engine
+ //
+ cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+
+ regdump(par);
+
+ return 0;
+}
+
+//========================
+//
+// Set one color register
+//
+//========================
+
+static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ int bpp = info->var.bits_per_pixel;
+
+ if (regno >= info->cmap.len)
+ return 1;
+
+ if (bpp == 8) {
+ out8(0x3C6,0xFF);
+ out8(0x3C8,regno);
+ out8(0x3C9,red>>10);
+ out8(0x3C9,green>>10);
+ out8(0x3C9,blue>>10);
+
+ } else if (bpp == 16) // RGB 565
+ ((u32*)info->pseudo_palette)[regno] =
+ (red & 0xF800) |
+ ((green & 0xFC00) >> 5) |
+ ((blue & 0xF800) >> 11);
+ else if (bpp == 32) // ARGB 8888
+ ((u32*)info->pseudo_palette)[regno] =
+ ((transp & 0xFF00) <<16) |
+ ((red & 0xFF00) << 8) |
+ ((green & 0xFF00)) |
+ ((blue & 0xFF00)>>8);
+
+ return 0;
+}
+
+//==========================================================
+//
+// Try blanking the screen. For flat panels it does nothing
+//
+//==========================================================
+
+static int cyblafb_blank(int blank_mode, struct fb_info *info)
+{
+ unsigned char PMCont,DPMSCont;
+
+ if (displaytype == DISPLAY_FP)
+ return 0;
+
+ out8(0x83C8,0x04); // DPMS Control
+ PMCont = in8(0x83C6) & 0xFC;
+
+ DPMSCont = read3CE(GR23) & 0xFC;
+
+ switch (blank_mode)
+ {
+ case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On
+ case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On
+ PMCont |= 0x03;
+ DPMSCont |= 0x00;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
+ PMCont |= 0x02;
+ DPMSCont |= 0x01;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
+ PMCont |= 0x02;
+ DPMSCont |= 0x02;
+ break;
+ case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
+ PMCont |= 0x00;
+ DPMSCont |= 0x03;
+ break;
+ }
+
+ write3CE(GR23,DPMSCont);
+ out8(0x83C8,4);
+ out8(0x83C6,PMCont);
+ //
+ // let fbcon do a softblank for us
+ //
+ return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops cyblafb_ops __devinitdata = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = cyblafb_setcolreg,
+ .fb_pan_display = cyblafb_pan_display,
+ .fb_blank = cyblafb_blank,
+ .fb_check_var = cyblafb_check_var,
+ .fb_set_par = cyblafb_set_par,
+ .fb_fillrect = cyblafb_fillrect,
+ .fb_copyarea= cyblafb_copyarea,
+ .fb_imageblit = cyblafb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+//==========================================================================
+//
+// getstartupmode() decides about the inital video mode
+//
+// There is no reason to use modedb, a lot of video modes there would
+// need altered timings to display correctly. So I decided that it is much
+// better to provide a limited optimized set of modes plus the option of
+// using the mode in effect at startup time (might be selected using the
+// vga=??? paramter). After that the user might use fbset to select any
+// mode he likes, check_var will not try to alter geometry parameters as
+// it would be necessary otherwise.
+//
+//==========================================================================
+
+static int __devinit getstartupmode(struct fb_info *info)
+{
+ u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
+ vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend,
+ cr00,cr01,cr02,cr03,cr04,cr05,cr2b,
+ cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27,
+ cr38,
+ sr0d,sr18,sr19,
+ gr0f,
+ fi,pxclkdiv,vclkdiv,tmp,i;
+
+ struct modus {
+ int xres; int yres; int vyres; int bpp; int pxclk;
+ int left_margin; int right_margin; int upper_margin;
+ int lower_margin; int hsync_len; int vsync_len;
+ } modedb[5] = {
+ { 0, 0, 8000, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 640, 480, 3756, 0, 0, -40, 24, 17, 0, 216, 3},
+ { 800, 600, 3221, 0, 0, 96, 24, 14, 0, 136, 11},
+ {1024, 768, 2815, 0, 0, 144, 24, 29, 0, 120, 3},
+ {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160, 3}
+ };
+
+ outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5);
+ outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5);
+ outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5);
+ outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5);
+ outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5);
+ outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5);
+ outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5);
+ outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5);
+ outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5);
+ outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5);
+ outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf);
+
+ htotal = cr00 | (cr2b & 0x01) << 8;
+ hdispend = cr01 | (cr2b & 0x02) << 7;
+ hblankstart = cr02 | (cr2b & 0x10) << 4;
+ hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
+ hsyncstart = cr04 | (cr2b & 0x08) << 5;
+ hsyncend = cr05 & 0x1f;
+
+ modedb[0].xres = hblankstart * 8;
+ modedb[0].hsync_len = hsyncend * 8;
+ modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
+ modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
+ modedb[0].right_margin - modedb[0].hsync_len;
+
+ vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
+ | (cr27 & 0x80) << 3;
+ vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
+ | (cr27 & 0x10) << 6;
+ vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
+ | (cr27 & 0x20) << 5;
+ vsyncend = cr11 & 0x0f;
+ vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
+ | (cr27 & 0x40) << 4;
+ vblankend = cr16;
+
+ modedb[0].yres = vdispend + 1;
+ modedb[0].vsync_len = vsyncend;
+ modedb[0].lower_margin = vsyncstart - modedb[0].yres;
+ modedb[0].upper_margin = vtotal - modedb[0].yres -
+ modedb[0].lower_margin - modedb[0].vsync_len + 2;
+
+ tmp = cr38 & 0x3c;
+ modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
+ tmp == 8 ? 32 : 8;
+
+ fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+ pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
+ tmp = sr0d & 0x06;
+ vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
+ modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi;
+
+ if (verbosity > 0)
+ output("detected startup mode: "
+ "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
+ modedb[0].xres,modedb[0].yres,modedb[0].xres,
+ modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin,
+ modedb[0].right_margin,modedb[0].upper_margin,
+ modedb[0].lower_margin,modedb[0].hsync_len,
+ modedb[0].vsync_len);
+
+ //
+ // We use this goto target in case of a failed check_var. No, I really
+ // do not want to do it in another way!
+ //
+
+ tryagain:
+
+ i = (mode == NULL) ? 0 :
+ !strncmp(mode,"640x480",7) ? 1 :
+ !strncmp(mode,"800x600",7) ? 2 :
+ !strncmp(mode,"1024x768",8) ? 3 :
+ !strncmp(mode,"1280x1024",9) ? 4 : 0;
+
+ ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
+
+ if(i==0) {
+ info->var.pixclock = modedb[i].pxclk;
+ info->var.bits_per_pixel = modedb[i].bpp;
+ } else {
+ info->var.pixclock = (100000000 /
+ ((modedb[i].left_margin + modedb[i].xres +
+ modedb[i].right_margin + modedb[i].hsync_len
+ ) * (
+ modedb[i].upper_margin + modedb[i].yres +
+ modedb[i].lower_margin + modedb[i].vsync_len
+ ) *
+ ref / 10000
+ ));
+ info->var.bits_per_pixel = bpp;
+ }
+
+ info->var.left_margin = modedb[i].left_margin;
+ info->var.right_margin = modedb[i].right_margin;
+ info->var.xres = modedb[i].xres;
+ info->var.xres_virtual = modedb[i].xres;
+ info->var.xoffset = 0;
+ info->var.hsync_len = modedb[i].hsync_len;
+ info->var.upper_margin = modedb[i].upper_margin;
+ info->var.yres = modedb[i].yres;
+ info->var.yres_virtual = modedb[i].vyres;
+ info->var.yoffset = 0;
+ info->var.lower_margin = modedb[i].lower_margin;
+ info->var.vsync_len = modedb[i].vsync_len;
+ info->var.sync = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ if(cyblafb_check_var(&info->var,info)) {
+ // 640x480-8@75 should really never fail. One case would
+ // be fp == 1 and nativex < 640 ... give up then
+ if(i==1 && bpp == 8 && ref == 75){
+ output("Can't find a valid mode :-(\n");
+ return -EINVAL;
+ }
+ // Our detected mode is unlikely to fail. If it does,
+ // try 640x480-8@75 ...
+ if(i==0) {
+ mode="640x480";
+ bpp=8;
+ ref=75;
+ output("Detected mode failed check_var! "
+ "Trying 640x480-8@75\n");
+ goto tryagain;
+ }
+ // A specified video mode failed for some reason.
+ // Try the startup mode first
+ output("Specified mode '%s' failed check! "
+ "Falling back to startup mode.\n",mode);
+ mode=NULL;
+ goto tryagain;
+ }
+
+ return 0;
+
+}
+
+//========================================================
+//
+// Detect activated memory size. Undefined values require
+// memsize parameter.
+//
+//========================================================
+
+static unsigned int __devinit get_memsize(void)
+{
+ unsigned char tmp;
+ unsigned int k;
+
+ if (memsize)
+ k = memsize * Kb;
+ else {
+ tmp = read3X4(CR1F) & 0x0F;
+ switch (tmp) {
+ case 0x03: k = 1 * Mb; break;
+ case 0x07: k = 2 * Mb; break;
+ case 0x0F: k = 4 * Mb; break;
+ case 0x04: k = 8 * Mb; break;
+ default:
+ k = 1 * Mb;
+ output("Unknown memory size code %x in CR1F."
+ " We default to 1 Mb for now, please"
+ " do provide a memsize parameter!\n",
+ tmp);
+ }
+ }
+
+ if (verbosity > 0)
+ output("framebuffer size = %d Kb\n",k/Kb);
+ return k;
+}
+
+//=========================================================
+//
+// Detect if a flat panel monitor connected to the special
+// interface is active. Override is possible by fp and crt
+// parameters.
+//
+//=========================================================
+
+static unsigned int __devinit get_displaytype(void)
+{
+ if (fp)
+ return DISPLAY_FP;
+ if (crt)
+ return DISPLAY_CRT;
+ return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+}
+
+//=====================================
+//
+// Get native resolution of flat panel
+//
+//=====================================
+
+static int __devinit get_nativex(void)
+{
+ int x,y,tmp;
+
+ if (nativex)
+ return nativex;
+
+ tmp = (read3CE(GR52) >> 4) & 3;
+
+ switch (tmp) {
+ case 0: x = 1280; y = 1024; break;
+ case 2: x = 1024; y = 768; break;
+ case 3: x = 800; y = 600; break;
+ case 4: x = 1400; y = 1050; break;
+ case 1:
+ default: x = 640; y = 480; break;
+ }
+
+ if (verbosity > 0)
+ output("%dx%d flat panel found\n",x,y);
+ return x;
+}
+
+static int __devinit cybla_pci_probe(struct pci_dev * dev,
+ const struct pci_device_id * id)
+{
+ struct fb_info *info;
+ struct cyblafb_par *par;
+
+ info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev);
+
+ if (!info)
+ goto errout_alloc;
+
+ par = info->par;
+ par->ops = cyblafb_ops;
+
+ info->fix = cyblafb_fix;
+ info->fbops = &par->ops;
+ info->fix = cyblafb_fix;
+
+ if (pci_enable_device(dev)) {
+ output("could not enable device!\n");
+ goto errout_enable;
+ }
+
+ // might already be requested by vga console or vesafb,
+ // so we do care about success
+ request_region(0x3c0,32,"cyblafb");
+
+ //
+ // Graphics Engine Registers
+ //
+ request_region(GEBase,0x100,"cyblafb");
+
+ regdump(par);
+
+ enable_mmio();
+
+ // setup MMIO region
+ info->fix.mmio_start = pci_resource_start(dev,1);
+ info->fix.mmio_len = 0x20000;
+
+ if (!request_mem_region(info->fix.mmio_start,
+ info->fix.mmio_len,"cyblafb")) {
+ output("request_mem_region failed for mmio region!\n");
+ goto errout_mmio_reqmem;
+ }
+
+ io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+
+ if (!io_virt) {
+ output("ioremap failed for mmio region\n");
+ goto errout_mmio_remap;
+ }
+
+ // setup framebuffer memory ... might already be requested
+ // by vesafb. Not to fail in case of an unsuccessful request
+ // is useful for the development cycle
+ info->fix.smem_start = pci_resource_start(dev,0);
+ info->fix.smem_len = get_memsize();
+
+ if (!request_mem_region(info->fix.smem_start,
+ info->fix.smem_len,"cyblafb")) {
+ output("request_mem_region failed for smem region!\n");
+ if (!vesafb)
+ goto errout_smem_req;
+ }
+
+ info->screen_base = ioremap_nocache(info->fix.smem_start,
+ info->fix.smem_len);
+
+ if (!info->screen_base) {
+ output("ioremap failed for smem region\n");
+ goto errout_smem_remap;
+ }
+
+ displaytype = get_displaytype();
+
+ if(displaytype == DISPLAY_FP)
+ nativex = get_nativex();
+
+ //
+ // FBINFO_HWACCEL_YWRAP .... does not work (could be made to work?)
+ // FBINFO_PARTIAL_PAN_OK .... is not ok
+ // FBINFO_READS_FAST .... is necessary for optimal scrolling
+ //
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN
+ | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
+
+ info->pseudo_palette = par->pseudo_pal;
+
+ if(getstartupmode(info))
+ goto errout_findmode;
+
+ fb_alloc_cmap(&info->cmap,256,0);
+
+ if (register_framebuffer(info)) {
+ output("Could not register CyBla framebuffer\n");
+ goto errout_register;
+ }
+
+ pci_set_drvdata(dev,info);
+
+ //
+ // normal exit and error paths
+ //
+
+ return 0;
+
+ errout_register:
+ errout_findmode:
+ iounmap(info->screen_base);
+ errout_smem_remap:
+ release_mem_region(info->fix.smem_start,
+ info->fix.smem_len);
+ errout_smem_req:
+ iounmap(io_virt);
+ errout_mmio_remap:
+ release_mem_region(info->fix.mmio_start,
+ info->fix.mmio_len);
+ errout_mmio_reqmem:
+// release_region(0x3c0,32);
+ errout_enable:
+ framebuffer_release(info);
+ errout_alloc:
+ output("CyblaFB version %s aborting init.\n",VERSION);
+ return -ENODEV;
+}
+
+static void __devexit cybla_pci_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ unregister_framebuffer(info);
+ iounmap(io_virt);
+ iounmap(info->screen_base);
+ release_mem_region(info->fix.smem_start,info->fix.smem_len);
+ release_mem_region(info->fix.mmio_start,info->fix.mmio_len);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ output("CyblaFB version %s normal exit.\n",VERSION);
+}
+
+//
+// List of boards that we are trying to support
+//
+static struct pci_device_id cybla_devices[] = {
+ {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci,cybla_devices);
+
+static struct pci_driver cyblafb_pci_driver = {
+ .name = "cyblafb",
+ .id_table = cybla_devices,
+ .probe = cybla_pci_probe,
+ .remove = __devexit_p(cybla_pci_remove)
+};
+
+//=============================================================
+//
+// kernel command line example:
+//
+// video=cyblafb:1280x1024,bpp=16,ref=50 ...
+//
+// modprobe command line example:
+//
+// modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
+//
+//=============================================================
+
+static int __devinit cyblafb_init(void)
+{
+#ifndef MODULE
+ char *options = NULL;
+ char *opt;
+
+ if (fb_get_options("cyblafb",&options))
+ return -ENODEV;
+
+ if (options && *options)
+ while((opt = strsep(&options,",")) != NULL ) {
+ if (!*opt) continue;
+ else if (!strncmp(opt,"bpp=",4))
+ bpp = simple_strtoul(opt+4,NULL,0);
+ else if (!strncmp(opt,"ref=",4))
+ ref = simple_strtoul(opt+4,NULL,0);
+ else if (!strncmp(opt,"fp",2))
+ displaytype = DISPLAY_FP;
+ else if (!strncmp(opt,"crt",3))
+ displaytype = DISPLAY_CRT;
+ else if (!strncmp(opt,"nativex=",8))
+ nativex = simple_strtoul(opt+8,NULL,0);
+ else if (!strncmp(opt,"center",6))
+ center = 1;
+ else if (!strncmp(opt,"stretch",7))
+ stretch = 1;
+ else if (!strncmp(opt,"pciwb=",6))
+ pciwb = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pcirb=",6))
+ pcirb = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pciwr=",6))
+ pciwr = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pcirr=",6))
+ pcirr = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"memsize=",8))
+ memsize = simple_strtoul(opt+8,NULL,0);
+ else if (!strncmp(opt,"verbosity=",10))
+ verbosity = simple_strtoul(opt+10,NULL,0);
+ else if (!strncmp(opt,"vesafb",6))
+ vesafb = 1;
+ else
+ mode = opt;
+ }
+#endif
+ output("CyblaFB version %s initializing\n",VERSION);
+ return pci_module_init(&cyblafb_pci_driver);
+}
+
+static void __exit cyblafb_exit(void)
+{
+ pci_unregister_driver(&cyblafb_pci_driver);
+}
+
+module_init(cyblafb_init);
+module_exit(cyblafb_exit);
+
+MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
new file mode 100644
index 000000000000..cfa61b512de0
--- /dev/null
+++ b/drivers/video/fbcvt.c
@@ -0,0 +1,380 @@
+/*
+ * linux/drivers/video/fbcvt.c - VESA(TM) Coordinated Video Timings
+ *
+ * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
+ *
+ * Based from the VESA(TM) Coordinated Video Timing Generator by
+ * Graham Loveridge April 9, 2003 available at
+ * http://www.vesa.org/public/CVT/CVTd6r1.xls
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+
+#define FB_CVT_CELLSIZE 8
+#define FB_CVT_GTF_C 40
+#define FB_CVT_GTF_J 20
+#define FB_CVT_GTF_K 128
+#define FB_CVT_GTF_M 600
+#define FB_CVT_MIN_VSYNC_BP 550
+#define FB_CVT_MIN_VPORCH 3
+#define FB_CVT_MIN_BPORCH 6
+
+#define FB_CVT_RB_MIN_VBLANK 460
+#define FB_CVT_RB_HBLANK 160
+#define FB_CVT_RB_V_FPORCH 3
+
+#define FB_CVT_FLAG_REDUCED_BLANK 1
+#define FB_CVT_FLAG_MARGINS 2
+#define FB_CVT_FLAG_INTERLACED 4
+
+struct fb_cvt_data {
+ u32 xres;
+ u32 yres;
+ u32 refresh;
+ u32 f_refresh;
+ u32 pixclock;
+ u32 hperiod;
+ u32 hblank;
+ u32 hfreq;
+ u32 htotal;
+ u32 vtotal;
+ u32 vsync;
+ u32 hsync;
+ u32 h_front_porch;
+ u32 h_back_porch;
+ u32 v_front_porch;
+ u32 v_back_porch;
+ u32 h_margin;
+ u32 v_margin;
+ u32 interlace;
+ u32 aspect_ratio;
+ u32 active_pixels;
+ u32 flags;
+ u32 status;
+};
+
+static int fb_cvt_vbi_tab[] = {
+ 4, /* 4:3 */
+ 5, /* 16:9 */
+ 6, /* 16:10 */
+ 7, /* 5:4 */
+ 7, /* 15:9 */
+ 8, /* reserved */
+ 9, /* reserved */
+ 10 /* custom */
+};
+
+/* returns hperiod * 1000 */
+static u32 fb_cvt_hperiod(struct fb_cvt_data *cvt)
+{
+ u32 num = 1000000000/cvt->f_refresh;
+ u32 den;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ num -= FB_CVT_RB_MIN_VBLANK * 1000;
+ den = 2 * (cvt->yres/cvt->interlace + 2 * cvt->v_margin);
+ } else {
+ num -= FB_CVT_MIN_VSYNC_BP * 1000;
+ den = 2 * (cvt->yres/cvt->interlace + cvt->v_margin * 2
+ + FB_CVT_MIN_VPORCH + cvt->interlace/2);
+ }
+
+ return 2 * (num/den);
+}
+
+/* returns ideal duty cycle * 1000 */
+static u32 fb_cvt_ideal_duty_cycle(struct fb_cvt_data *cvt)
+{
+ u32 c_prime = (FB_CVT_GTF_C - FB_CVT_GTF_J) *
+ (FB_CVT_GTF_K) + 256 * FB_CVT_GTF_J;
+ u32 m_prime = (FB_CVT_GTF_K * FB_CVT_GTF_M);
+ u32 h_period_est = cvt->hperiod;
+
+ return (1000 * c_prime - ((m_prime * h_period_est)/1000))/256;
+}
+
+static u32 fb_cvt_hblank(struct fb_cvt_data *cvt)
+{
+ u32 hblank = 0;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ hblank = FB_CVT_RB_HBLANK;
+ else {
+ u32 ideal_duty_cycle = fb_cvt_ideal_duty_cycle(cvt);
+ u32 active_pixels = cvt->active_pixels;
+
+ if (ideal_duty_cycle < 20000)
+ hblank = (active_pixels * 20000)/
+ (100000 - 20000);
+ else {
+ hblank = (active_pixels * ideal_duty_cycle)/
+ (100000 - ideal_duty_cycle);
+ }
+ }
+
+ hblank &= ~((2 * FB_CVT_CELLSIZE) - 1);
+
+ return hblank;
+}
+
+static u32 fb_cvt_hsync(struct fb_cvt_data *cvt)
+{
+ u32 hsync;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ hsync = 32;
+ else
+ hsync = (FB_CVT_CELLSIZE * cvt->htotal)/100;
+
+ hsync &= ~(FB_CVT_CELLSIZE - 1);
+ return hsync;
+}
+
+static u32 fb_cvt_vbi_lines(struct fb_cvt_data *cvt)
+{
+ u32 vbi_lines, min_vbi_lines, act_vbi_lines;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ vbi_lines = (1000 * FB_CVT_RB_MIN_VBLANK)/cvt->hperiod + 1;
+ min_vbi_lines = FB_CVT_RB_V_FPORCH + cvt->vsync +
+ FB_CVT_MIN_BPORCH;
+
+ } else {
+ vbi_lines = (FB_CVT_MIN_VSYNC_BP * 1000)/cvt->hperiod + 1 +
+ FB_CVT_MIN_VPORCH;
+ min_vbi_lines = cvt->vsync + FB_CVT_MIN_BPORCH +
+ FB_CVT_MIN_VPORCH;
+ }
+
+ if (vbi_lines < min_vbi_lines)
+ act_vbi_lines = min_vbi_lines;
+ else
+ act_vbi_lines = vbi_lines;
+
+ return act_vbi_lines;
+}
+
+static u32 fb_cvt_vtotal(struct fb_cvt_data *cvt)
+{
+ u32 vtotal = cvt->yres/cvt->interlace;
+
+ vtotal += 2 * cvt->v_margin + cvt->interlace/2 + fb_cvt_vbi_lines(cvt);
+ vtotal |= cvt->interlace/2;
+
+ return vtotal;
+}
+
+static u32 fb_cvt_pixclock(struct fb_cvt_data *cvt)
+{
+ u32 pixclock;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ pixclock = (cvt->f_refresh * cvt->vtotal * cvt->htotal)/1000;
+ else
+ pixclock = (cvt->htotal * 1000000)/cvt->hperiod;
+
+ pixclock /= 250;
+ pixclock *= 250;
+ pixclock *= 1000;
+
+ return pixclock;
+}
+
+static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
+{
+ u32 xres = cvt->xres;
+ u32 yres = cvt->yres;
+ u32 aspect = -1;
+
+ if (xres == (yres * 4)/3 && !((yres * 4) % 3))
+ aspect = 0;
+ else if (xres == (yres * 16)/9 && !((yres * 16) % 9))
+ aspect = 1;
+ else if (xres == (yres * 16)/10 && !((yres * 16) % 10))
+ aspect = 2;
+ else if (xres == (yres * 5)/4 && !((yres * 5) % 4))
+ aspect = 3;
+ else if (xres == (yres * 15)/9 && !((yres * 15) % 9))
+ aspect = 4;
+ else {
+ printk(KERN_INFO "fbcvt: Aspect ratio not CVT "
+ "standard\n");
+ aspect = 7;
+ cvt->status = 1;
+ }
+
+ return aspect;
+}
+
+static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+{
+ u32 pixcount, pixcount_mod;
+ int cnt = 255, offset = 0, read = 0;
+ u8 *buf = kmalloc(256, GFP_KERNEL);
+
+ if (!buf)
+ return;
+
+ memset(buf, 0, 256);
+ pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
+ pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
+ pixcount_mod /= 1000;
+
+ read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
+ cvt->xres, cvt->yres, cvt->refresh);
+ offset += read;
+ cnt -= read;
+
+ if (cvt->status)
+ snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
+ "Pixel Image\n", pixcount, pixcount_mod);
+ else {
+ if (pixcount) {
+ read = snprintf(buf+offset, cnt, "%d", pixcount);
+ cnt -= read;
+ offset += read;
+ }
+
+ read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
+ cnt -= read;
+ offset += read;
+
+ if (cvt->aspect_ratio == 0)
+ read = snprintf(buf+offset, cnt, "3");
+ else if (cvt->aspect_ratio == 3)
+ read = snprintf(buf+offset, cnt, "4");
+ else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
+ read = snprintf(buf+offset, cnt, "9");
+ else if (cvt->aspect_ratio == 2)
+ read = snprintf(buf+offset, cnt, "A");
+ else
+ read = 0;
+ cnt -= read;
+ offset += read;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ read = snprintf(buf+offset, cnt, "-R");
+ cnt -= read;
+ offset += read;
+ }
+ }
+
+ printk(KERN_INFO "%s\n", buf);
+ kfree(buf);
+}
+
+static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
+ struct fb_videomode *mode)
+{
+ mode->refresh = cvt->f_refresh;
+ mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
+ mode->left_margin = cvt->h_front_porch;
+ mode->right_margin = cvt->h_back_porch;
+ mode->hsync_len = cvt->hsync;
+ mode->upper_margin = cvt->v_front_porch;
+ mode->lower_margin = cvt->v_back_porch;
+ mode->vsync_len = cvt->vsync;
+
+ mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ else
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+/*
+ * fb_find_mode_cvt - calculate mode using VESA(TM) CVT
+ * @mode: pointer to fb_videomode; xres, yres, refresh and vmode must be
+ * pre-filled with the desired values
+ * @margins: add margin to calculation (1.8% of xres and yres)
+ * @rb: compute with reduced blanking (for flatpanels)
+ *
+ * RETURNS:
+ * 0 for success
+ * @mode is filled with computed values. If interlaced, the refresh field
+ * will be filled with the field rate (2x the frame rate)
+ *
+ * DESCRIPTION:
+ * Computes video timings using VESA(TM) Coordinated Video Timings
+ */
+int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb)
+{
+ struct fb_cvt_data cvt;
+
+ memset(&cvt, 0, sizeof(cvt));
+
+ if (margins)
+ cvt.flags |= FB_CVT_FLAG_MARGINS;
+
+ if (rb)
+ cvt.flags |= FB_CVT_FLAG_REDUCED_BLANK;
+
+ if (mode->vmode & FB_VMODE_INTERLACED)
+ cvt.flags |= FB_CVT_FLAG_INTERLACED;
+
+ cvt.xres = mode->xres;
+ cvt.yres = mode->yres;
+ cvt.refresh = mode->refresh;
+ cvt.f_refresh = cvt.refresh;
+ cvt.interlace = 1;
+
+ if (!cvt.xres || !cvt.yres || !cvt.refresh) {
+ printk(KERN_INFO "fbcvt: Invalid input parameters\n");
+ return 1;
+ }
+
+ if (!(cvt.refresh == 50 || cvt.refresh == 60 || cvt.refresh == 70 ||
+ cvt.refresh == 85)) {
+ printk(KERN_INFO "fbcvt: Refresh rate not CVT "
+ "standard\n");
+ cvt.status = 1;
+ }
+
+ cvt.xres &= ~(FB_CVT_CELLSIZE - 1);
+
+ if (cvt.flags & FB_CVT_FLAG_INTERLACED) {
+ cvt.interlace = 2;
+ cvt.f_refresh *= 2;
+ }
+
+ if (cvt.flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ if (cvt.refresh != 60) {
+ printk(KERN_INFO "fbcvt: 60Hz refresh rate "
+ "advised for reduced blanking\n");
+ cvt.status = 1;
+ }
+ }
+
+ if (cvt.flags & FB_CVT_FLAG_MARGINS) {
+ cvt.h_margin = (cvt.xres * 18)/1000;
+ cvt.h_margin &= ~(FB_CVT_CELLSIZE - 1);
+ cvt.v_margin = ((cvt.yres/cvt.interlace)* 18)/1000;
+ }
+
+ cvt.aspect_ratio = fb_cvt_aspect_ratio(&cvt);
+ cvt.active_pixels = cvt.xres + 2 * cvt.h_margin;
+ cvt.hperiod = fb_cvt_hperiod(&cvt);
+ cvt.vsync = fb_cvt_vbi_tab[cvt.aspect_ratio];
+ cvt.vtotal = fb_cvt_vtotal(&cvt);
+ cvt.hblank = fb_cvt_hblank(&cvt);
+ cvt.htotal = cvt.active_pixels + cvt.hblank;
+ cvt.hsync = fb_cvt_hsync(&cvt);
+ cvt.pixclock = fb_cvt_pixclock(&cvt);
+ cvt.hfreq = cvt.pixclock/cvt.htotal;
+ cvt.h_back_porch = cvt.hblank/2 + cvt.h_margin;
+ cvt.h_front_porch = cvt.hblank - cvt.hsync - cvt.h_back_porch +
+ 2 * cvt.h_margin;
+ cvt.v_back_porch = 3 + cvt.v_margin;
+ cvt.v_front_porch = cvt.vtotal - cvt.yres/cvt.interlace -
+ cvt.v_back_porch - cvt.vsync;
+ fb_cvt_print_name(&cvt);
+ fb_cvt_convert_to_mode(&cvt, mode);
+
+ return 0;
+}
+EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 4ff853fbe0be..70be7009f8af 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -62,16 +62,26 @@ int num_registered_fb;
* Helpers
*/
-int fb_get_color_depth(struct fb_var_screeninfo *var)
+int fb_get_color_depth(struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix)
{
- if (var->green.length == var->blue.length &&
- var->green.length == var->red.length &&
- !var->green.offset && !var->blue.offset &&
- !var->red.offset)
- return var->green.length;
- else
- return (var->green.length + var->red.length +
- var->blue.length);
+ int depth = 0;
+
+ if (fix->visual == FB_VISUAL_MONO01 ||
+ fix->visual == FB_VISUAL_MONO10)
+ depth = 1;
+ else {
+ if (var->green.length == var->blue.length &&
+ var->green.length == var->red.length &&
+ var->green.offset == var->blue.offset &&
+ var->green.offset == var->red.offset)
+ depth = var->green.length;
+ else
+ depth = var->green.length + var->red.length +
+ var->blue.length;
+ }
+
+ return depth;
}
EXPORT_SYMBOL(fb_get_color_depth);
@@ -80,15 +90,7 @@ EXPORT_SYMBOL(fb_get_color_depth);
*/
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
{
- int i, j;
-
- for (i = height; i--; ) {
- /* s_pitch is a few bytes at the most, memcpy is suboptimal */
- for (j = 0; j < s_pitch; j++)
- dst[j] = src[j];
- src += s_pitch;
- dst += d_pitch;
- }
+ __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
}
EXPORT_SYMBOL(fb_pad_aligned_buffer);
@@ -249,13 +251,18 @@ static void fb_set_logo(struct fb_info *info,
const struct linux_logo *logo, u8 *dst,
int depth)
{
- int i, j, k, fg = 1;
+ int i, j, k;
const u8 *src = logo->data;
- u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+ u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+ u8 fg = 1, d;
- if (fb_get_color_depth(&info->var) == 3)
+ if (fb_get_color_depth(&info->var, &info->fix) == 3)
fg = 7;
+ if (info->fix.visual == FB_VISUAL_MONO01 ||
+ info->fix.visual == FB_VISUAL_MONO10)
+ fg = ~((u8) (0xfff << info->var.green.length));
+
switch (depth) {
case 4:
for (i = 0; i < logo->height; i++)
@@ -318,7 +325,7 @@ static struct logo_data {
int fb_prepare_logo(struct fb_info *info)
{
- int depth = fb_get_color_depth(&info->var);
+ int depth = fb_get_color_depth(&info->var, &info->fix);
memset(&fb_logo, 0, sizeof(struct logo_data));
@@ -684,11 +691,13 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
if (!err && (flags & FBINFO_MISC_USEREVENT)) {
struct fb_event event;
+ int evnt = (var->activate & FB_ACTIVATE_ALL) ?
+ FB_EVENT_MODE_CHANGE_ALL :
+ FB_EVENT_MODE_CHANGE;
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
- notifier_call_chain(&fb_notifier_list,
- FB_EVENT_MODE_CHANGE,
+ notifier_call_chain(&fb_notifier_list, evnt,
&event);
}
}
@@ -1012,6 +1021,7 @@ register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
+ struct fb_videomode mode;
if (num_registered_fb == FB_MAX)
return -ENXIO;
@@ -1042,16 +1052,11 @@ register_framebuffer(struct fb_info *fb_info)
}
fb_info->pixmap.offset = 0;
- if (!fb_info->modelist.prev ||
- !fb_info->modelist.next ||
- list_empty(&fb_info->modelist)) {
- struct fb_videomode mode;
-
+ if (!fb_info->modelist.prev || !fb_info->modelist.next)
INIT_LIST_HEAD(&fb_info->modelist);
- fb_var_to_videomode(&mode, &fb_info->var);
- fb_add_videomode(&mode, &fb_info->modelist);
- }
+ fb_var_to_videomode(&mode, &fb_info->var);
+ fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
devfs_mk_cdev(MKDEV(FB_MAJOR, i),
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index c2718bb94949..713226cdf3c6 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -29,6 +29,7 @@
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
+#include <video/edid.h>
#ifdef CONFIG_PPC_OF
#include <linux/pci.h>
#include <asm/prom.h>
@@ -313,11 +314,13 @@ static int edid_is_monitor_block(unsigned char *block)
return 0;
}
-static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
+static void calc_mode_timings(int xres, int yres, int refresh,
+ struct fb_videomode *mode)
{
struct fb_var_screeninfo var;
struct fb_info info;
+ memset(&var, 0, sizeof(struct fb_var_screeninfo));
var.xres = xres;
var.yres = yres;
fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
@@ -1251,9 +1254,41 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
-EINVAL : 0;
}
+#if defined(__i386__)
+#include <linux/pci.h>
+
+/*
+ * We need to ensure that the EDID block is only returned for
+ * the primary graphics adapter.
+ */
+
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+ struct pci_dev *dev = NULL;
+ struct resource *res = NULL;
+ unsigned char *edid = NULL;
+
+ if (device)
+ dev = to_pci_dev(device);
+
+ if (dev)
+ res = &dev->resource[PCI_ROM_RESOURCE];
+
+ if (res && res->flags & IORESOURCE_ROM_SHADOW)
+ edid = edid_info.dummy;
+
+ return edid;
+}
+#else
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+ return NULL;
+}
+#endif /* _i386_ */
+
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/geode/Kconfig b/drivers/video/geode/Kconfig
index b075fd02de31..5a9b89c3831b 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -3,15 +3,13 @@
#
config FB_GEODE
bool "AMD Geode family framebuffer support (EXPERIMENTAL)"
- default n
- depends on FB && EXPERIMENTAL && X86
+ depends on FB && PCI && EXPERIMENTAL && X86
---help---
Say 'Y' here to allow you to select framebuffer drivers for
the AMD Geode family of processors.
config FB_GEODE_GX1
tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
- default n
depends on FB_GEODE && EXPERIMENTAL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
@@ -21,9 +19,7 @@ config FB_GEODE_GX1
Framebuffer driver for the display controller integrated into the
AMD Geode GX1 processor.
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called gx1fb. If you want to compile it as a module,
- say M here and read <file:Documentation/modules.txt>.
+ To compile this driver as a module, choose M here: the module will be
+ called gx1fb.
If unsure, say N.
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
index f4983879fcc4..926d53eeb549 100644
--- a/drivers/video/geode/display_gx1.c
+++ b/drivers/video/geode/display_gx1.c
@@ -22,7 +22,7 @@
#include "geodefb.h"
#include "display_gx1.h"
-static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(gx1_conf_reg_lock);
static u8 gx1_read_conf_reg(u8 reg)
{
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
index b7bac0a526b3..ae04820e0c57 100644
--- a/drivers/video/geode/geodefb.h
+++ b/drivers/video/geode/geodefb.h
@@ -29,7 +29,6 @@ struct geodefb_par {
int enable_crt;
int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
int panel_y;
- struct pci_dev *vid_dev;
void __iomem *dc_regs;
void __iomem *vid_regs;
struct geode_dc_ops *dc_ops;
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 83830d24bcda..74a5fca86b8a 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -30,6 +30,62 @@ static char mode_option[32] = "640x480-16@60";
static int crt_option = 1;
static char panel_option[32] = "";
+/* Modes relevant to the GX1 (taken from modedb.c) */
+static const struct fb_videomode __initdata gx1_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 },
+};
+
static int gx1_line_delta(int xres, int bpp)
{
int line_delta = xres * (bpp >> 3);
@@ -47,8 +103,6 @@ static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct geodefb_par *par = info->par;
- printk(KERN_DEBUG "%s()\n", __FUNCTION__);
-
/* Maximum resolution is 1280x1024. */
if (var->xres > 1280 || var->yres > 1024)
return -EINVAL;
@@ -146,40 +200,48 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info)
return par->vid_ops->blank_display(info, blank_mode);
}
-static int __init gx1fb_map_video_memory(struct fb_info *info)
+static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
{
struct geodefb_par *par = info->par;
unsigned gx_base;
int fb_len;
+ int ret;
gx_base = gx1_gx_base();
if (!gx_base)
return -ENODEV;
- par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
- PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
- if (!par->vid_dev)
- return -ENODEV;
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ return ret;
- par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
- pci_resource_len(par->vid_dev, 1));
+ ret = pci_request_region(dev, 1, "gx1fb (video)");
+ if (ret < 0)
+ return ret;
+ par->vid_regs = ioremap(pci_resource_start(dev, 1),
+ pci_resource_len(dev, 1));
if (!par->vid_regs)
return -ENOMEM;
+ if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)"))
+ return -EBUSY;
par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
if (!par->dc_regs)
return -ENOMEM;
- info->fix.smem_start = gx_base + 0x800000;
+ ret = pci_request_region(dev, 0, "gx1fb (frame buffer)");
+ if (ret < 0 )
+ return -EBUSY;
if ((fb_len = gx1_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;
- printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
- info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
+ dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
return 0;
}
@@ -216,13 +278,13 @@ static struct fb_ops gx1fb_ops = {
.fb_cursor = soft_cursor,
};
-static struct fb_info * __init gx1fb_init_fbinfo(void)
+static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
{
- struct fb_info *info;
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, NULL);
+ info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
if (!info)
return NULL;
@@ -255,47 +317,37 @@ static struct fb_info * __init gx1fb_init_fbinfo(void)
/* CRT and panel options */
par->enable_crt = crt_option;
if (parse_panel_option(info) < 0)
- printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n",
- info->fix.id);
+ printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n");
if (!par->panel_x)
par->enable_crt = 1; /* fall back to CRT if no panel is specified */
return info;
}
-
-static struct fb_info *gx1fb_info;
-
-static int __init gx1fb_init(void)
+static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct geodefb_par *par;
struct fb_info *info;
- struct geodefb_par *par;
int ret;
-#ifndef MODULE
- if (fb_get_options("gx1fb", NULL))
- return -ENODEV;
-#endif
-
- info = gx1fb_init_fbinfo();
+ info = gx1fb_init_fbinfo(&pdev->dev);
if (!info)
return -ENOMEM;
- gx1fb_info = info;
-
par = info->par;
/* GX1 display controller and CS5530 video device */
par->dc_ops = &gx1_dc_ops;
par->vid_ops = &cs5530_vid_ops;
- if ((ret = gx1fb_map_video_memory(info)) < 0) {
- printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
+ if ((ret = gx1fb_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, NULL, 0, NULL, 16);
+ ret = fb_find_mode(&info->var, info, mode_option,
+ gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
if (ret == 0 || ret == 4) {
- printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
+ dev_err(&pdev->dev, "could not find valid video mode\n");
ret = -EINVAL;
goto err;
}
@@ -310,39 +362,83 @@ static int __init gx1fb_init(void)
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)
+ if (info->screen_base) {
iounmap(info->screen_base);
- if (par->vid_regs)
+ pci_release_region(pdev, 0);
+ }
+ if (par->vid_regs) {
iounmap(par->vid_regs);
- if (par->dc_regs)
+ pci_release_region(pdev, 1);
+ }
+ if (par->dc_regs) {
iounmap(par->dc_regs);
- if (par->vid_dev)
- pci_dev_put(par->vid_dev);
+ release_mem_region(gx1_gx_base() + 0x8300, 0x100);
+ }
+
+ pci_disable_device(pdev);
+
if (info)
framebuffer_release(info);
return ret;
}
-static void __exit gx1fb_cleanup(void)
+static void gx1fb_remove(struct pci_dev *pdev)
{
- struct fb_info *info = gx1fb_info;
- struct geodefb_par *par = gx1fb_info->par;
+ 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, 1);
+
iounmap(par->dc_regs);
+ release_mem_region(gx1_gx_base() + 0x8300, 0x100);
- pci_dev_put(par->vid_dev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
+static struct pci_device_id gx1fb_id_table[] = {
+ { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+ 0xff0000, 0 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gx1fb_id_table);
+
+static struct pci_driver gx1fb_driver = {
+ .name = "gx1fb",
+ .id_table = gx1fb_id_table,
+ .probe = gx1fb_probe,
+ .remove = gx1fb_remove,
+};
+
+static int __init gx1fb_init(void)
+{
+#ifndef MODULE
+ if (fb_get_options("gx1fb", NULL))
+ return -ENODEV;
+#endif
+ return pci_register_driver(&gx1fb_driver);
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+ pci_unregister_driver(&gx1fb_driver);
+}
+
module_init(gx1fb_init);
module_exit(gx1fb_cleanup);
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
index d3764acf8443..649c3943d431 100644
--- a/drivers/video/geode/video_cs5530.c
+++ b/drivers/video/geode/video_cs5530.c
@@ -69,8 +69,6 @@ static const struct cs5530_pll_entry cs5530_pll_table[] = {
{ 4310, 0x2FB1B802, }, /* 232.0000 */
};
-#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
-
static void cs5530_set_dclk_frequency(struct fb_info *info)
{
struct geodefb_par *par = info->par;
@@ -82,7 +80,7 @@ static void cs5530_set_dclk_frequency(struct fb_info *info)
value = cs5530_pll_table[0].pll_value;
min = cs5530_pll_table[0].pixclock - info->var.pixclock;
if (min < 0) min = -min;
- for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+ for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
if (diff < 0L) diff = -diff;
if (diff < min) {
diff --git a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile
index 794ae76c7c4b..96e08c8ded97 100644
--- a/drivers/video/i810/Makefile
+++ b/drivers/video/i810/Makefile
@@ -4,7 +4,6 @@
obj-$(CONFIG_FB_I810) += i810fb.o
-
i810fb-objs := i810_main.o i810_accel.o
ifdef CONFIG_FB_I810_GTF
@@ -12,3 +11,7 @@ i810fb-objs += i810_gtf.o
else
i810fb-objs += i810_dvt.o
endif
+
+ifdef CONFIG_FB_I810_I2C
+i810fb-objs += i810-i2c.o
+endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
new file mode 100644
index 000000000000..fda53aac1fc1
--- /dev/null
+++ b/drivers/video/i810/i810-i2c.c
@@ -0,0 +1,257 @@
+ /*-*- linux-c -*-
+ * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
+ *
+ * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include "i810.h"
+#include "i810_regs.h"
+#include "../edid.h"
+
+#define I810_DDC 0x50
+/* bit locations in the registers */
+#define SCL_DIR_MASK 0x0001
+#define SCL_DIR 0x0002
+#define SCL_VAL_MASK 0x0004
+#define SCL_VAL_OUT 0x0008
+#define SCL_VAL_IN 0x0010
+#define SDA_DIR_MASK 0x0100
+#define SDA_DIR 0x0200
+#define SDA_VAL_MASK 0x0400
+#define SDA_VAL_OUT 0x0800
+#define SDA_VAL_IN 0x1000
+
+#define DEBUG /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static void i810i2c_setscl(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+ SCL_DIR_MASK | SCL_VAL_MASK);
+ i810_readl(mmio, GPIOB); /* flush posted write */
+}
+
+static void i810i2c_setsda(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+ SDA_DIR_MASK | SDA_VAL_MASK);
+ i810_readl(mmio, GPIOB); /* flush posted write */
+}
+
+static int i810i2c_getscl(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, SCL_DIR_MASK);
+ i810_writel(mmio, GPIOB, 0);
+ return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN));
+}
+
+static int i810i2c_getsda(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, SDA_DIR_MASK);
+ i810_writel(mmio, GPIOB, 0);
+ return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN));
+}
+
+static void i810ddc_setscl(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+ SCL_DIR_MASK | SCL_VAL_MASK);
+ i810_readl(mmio, GPIOA); /* flush posted write */
+}
+
+static void i810ddc_setsda(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+ SDA_DIR_MASK | SDA_VAL_MASK);
+ i810_readl(mmio, GPIOA); /* flush posted write */
+}
+
+static int i810ddc_getscl(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, SCL_DIR_MASK);
+ i810_writel(mmio, GPIOA, 0);
+ return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN));
+}
+
+static int i810ddc_getsda(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, SDA_DIR_MASK);
+ i810_writel(mmio, GPIOA, 0);
+ return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN));
+}
+
+#define I2C_ALGO_DDC_I810 0x0e0000
+#define I2C_ALGO_I2C_I810 0x0f0000
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
+ int conn)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->dev->dev;
+ switch (conn) {
+ case 1:
+ chan->adapter.id = I2C_ALGO_DDC_I810;
+ chan->algo.setsda = i810ddc_setsda;
+ chan->algo.setscl = i810ddc_setscl;
+ chan->algo.getsda = i810ddc_getsda;
+ chan->algo.getscl = i810ddc_getscl;
+ break;
+ case 2:
+ chan->adapter.id = I2C_ALGO_I2C_I810;
+ chan->algo.setsda = i810i2c_setsda;
+ chan->algo.setscl = i810i2c_setscl;
+ chan->algo.getsda = i810i2c_getsda;
+ chan->algo.getscl = i810i2c_getscl;
+ break;
+ }
+ chan->algo.udelay = 10;
+ chan->algo.mdelay = 10;
+ chan->algo.timeout = (HZ/2);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ /* Raise SCL and SDA */
+ chan->algo.setsda(chan, 1);
+ chan->algo.setscl(chan, 1);
+ udelay(20);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
+ else
+ dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
+ "%s.\n", name);
+ return rc;
+}
+
+void i810_create_i2c_busses(struct i810fb_par *par)
+{
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+ i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1);
+ i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2);
+}
+
+void i810_delete_i2c_busses(struct i810fb_par *par)
+{
+ if (par->chan[0].par)
+ i2c_bit_del_bus(&par->chan[0].adapter);
+ par->chan[0].par = NULL;
+ if (par->chan[1].par)
+ i2c_bit_del_bus(&par->chan[1].adapter);
+ par->chan[1].par = NULL;
+}
+
+static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan)
+{
+ u8 start = 0x0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = I810_DDC,
+ .len = 1,
+ .buf = &start,
+ }, {
+ .addr = I810_DDC,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ },
+ };
+ u8 *buf;
+
+ buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!buf) {
+ DPRINTK("i810-i2c: Failed to allocate memory\n");
+ return NULL;
+ }
+ msgs[1].buf = buf;
+
+ if (i2c_transfer(&chan->adapter, msgs, 2) == 2) {
+ DPRINTK("i810-i2c: I2C Transfer successful\n");
+ return buf;
+ }
+ DPRINTK("i810-i2c: Unable to read EDID block.\n");
+ kfree(buf);
+ return NULL;
+}
+
+int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
+{
+ struct i810fb_par *par = info->par;
+ u8 *edid = NULL;
+ int i;
+
+ DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
+ if (conn < 3) {
+ for (i = 0; i < 3; i++) {
+ /* Do the real work */
+ edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
+ if (edid)
+ break;
+ }
+ } else {
+ DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, fb_firmware_edid(info->device),
+ EDID_LENGTH);
+ }
+
+ if (out_edid)
+ *out_edid = edid;
+
+ return (edid) ? 0 : 1;
+}
+
+
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index fe3b75794756..d48949ceaacc 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -16,6 +16,9 @@
#include <linux/list.h>
#include <linux/agp_backend.h>
#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
#include <video/vga.h>
/* Fence */
@@ -201,7 +204,6 @@
#define HAS_ACCELERATION 2
#define ALWAYS_SYNC 4
#define LOCKUP 8
-#define USE_HWCUR 16
struct gtt_data {
struct agp_memory *i810_fb_memory;
@@ -241,6 +243,14 @@ struct state_registers {
u8 cr39, cr41, cr70, sr01, msr;
};
+struct i810fb_par;
+
+struct i810fb_i2c_chan {
+ struct i810fb_par *par;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
struct i810fb_par {
struct mode_registers regs;
struct state_registers hw_state;
@@ -252,10 +262,12 @@ struct i810fb_par {
struct heap_data iring;
struct heap_data cursor_heap;
struct vgastate state;
+ struct i810fb_i2c_chan chan[2];
atomic_t use_count;
u32 pseudo_palette[17];
unsigned long mmio_start_phys;
u8 __iomem *mmio_start_virtual;
+ u8 *edid;
u32 pitch;
u32 pixconf;
u32 watermark;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 7513fb9b19cf..0dbc9ddb6766 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -92,20 +92,21 @@ static struct pci_driver i810fb_driver = {
.resume = i810fb_resume,
};
-static int vram __initdata = 4;
-static int bpp __initdata = 8;
-static int mtrr __initdata = 0;
-static int accel __initdata = 0;
-static int hsync1 __initdata = 0;
-static int hsync2 __initdata = 0;
-static int vsync1 __initdata = 0;
-static int vsync2 __initdata = 0;
-static int xres __initdata = 640;
-static int yres __initdata = 480;
-static int vyres __initdata = 0;
-static int sync __initdata = 0;
-static int ext_vga __initdata = 0;
-static int dcolor __initdata = 0;
+static char *mode_option __devinitdata = NULL;
+static int vram __devinitdata = 4;
+static int bpp __devinitdata = 8;
+static int mtrr __devinitdata;
+static int accel __devinitdata;
+static int hsync1 __devinitdata;
+static int hsync2 __devinitdata;
+static int vsync1 __devinitdata;
+static int vsync2 __devinitdata;
+static int xres __devinitdata;
+static int yres __devinitdata;
+static int vyres __devinitdata;
+static int sync __devinitdata;
+static int extvga __devinitdata;
+static int dcolor __devinitdata;
/*------------------------------------------------------------*/
@@ -310,6 +311,8 @@ static void i810_hires(u8 __iomem *mmio)
val = i810_readb(CR_DATA_CGA, mmio);
i810_writeb(CR_INDEX_CGA, mmio, CR80);
i810_writeb(CR_DATA_CGA, mmio, val | 1);
+ /* Stop LCD displays from flickering */
+ i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
}
/**
@@ -947,31 +950,24 @@ static int i810_check_params(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct i810fb_par *par = (struct i810fb_par *) info->par;
- int line_length, vidmem;
- u32 xres, yres, vxres, vyres;
-
- xres = var->xres;
- yres = var->yres;
- vxres = var->xres_virtual;
- vyres = var->yres_virtual;
-
+ int line_length, vidmem, mode_valid = 0, retval = 0;
+ u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
/*
* Memory limit
*/
- line_length = get_line_length(par, vxres,
- var->bits_per_pixel);
-
+ line_length = get_line_length(par, vxres, var->bits_per_pixel);
vidmem = line_length*vyres;
+
if (vidmem > par->fb.size) {
vyres = par->fb.size/line_length;
- if (vyres < yres) {
+ if (vyres < var->yres) {
vyres = yres;
vxres = par->fb.size/vyres;
vxres /= var->bits_per_pixel >> 3;
line_length = get_line_length(par, vxres,
var->bits_per_pixel);
vidmem = line_length * yres;
- if (vxres < xres) {
+ if (vxres < var->xres) {
printk("i810fb: required video memory, "
"%d bytes, for %dx%d-%d (virtual) "
"is out of range\n",
@@ -981,6 +977,10 @@ static int i810_check_params(struct fb_var_screeninfo *var,
}
}
}
+
+ var->xres_virtual = vxres;
+ var->yres_virtual = vyres;
+
/*
* Monitor limit
*/
@@ -996,26 +996,41 @@ static int i810_check_params(struct fb_var_screeninfo *var,
info->monspecs.dclkmax = 204000000;
break;
}
+
info->monspecs.dclkmin = 15000000;
- if (fb_validate_mode(var, info)) {
+ if (!fb_validate_mode(var, info))
+ mode_valid = 1;
+
+#ifdef CONFIG_FB_I810_I2C
+ if (!mode_valid && info->monspecs.gtf &&
+ !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+ mode_valid = 1;
+
+ if (!mode_valid && info->monspecs.modedb_len) {
+ struct fb_videomode *mode;
+
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ fb_videomode_to_var(var, mode);
+ mode_valid = 1;
+ }
+ }
+#endif
+ if (!mode_valid && info->monspecs.modedb_len == 0) {
if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
int default_sync = (info->monspecs.hfmin-HFMIN)
- |(info->monspecs.hfmax-HFMAX)
- |(info->monspecs.vfmin-VFMIN)
- |(info->monspecs.vfmax-VFMAX);
+ |(info->monspecs.hfmax-HFMAX)
+ |(info->monspecs.vfmin-VFMIN)
+ |(info->monspecs.vfmax-VFMAX);
printk("i810fb: invalid video mode%s\n",
- default_sync ? "" :
- ". Specifying vsyncN/hsyncN parameters may help");
- return -EINVAL;
+ default_sync ? "" : ". Specifying "
+ "vsyncN/hsyncN parameters may help");
+ retval = -EINVAL;
}
}
-
- var->xres = xres;
- var->yres = yres;
- var->xres_virtual = vxres;
- var->yres_virtual = vyres;
- return 0;
+
+ return retval;
}
/**
@@ -1375,7 +1390,6 @@ static int i810fb_set_par(struct fb_info *info)
decode_var(&info->var, par);
i810_load_regs(par);
i810_init_cursor(par);
-
encode_fix(&info->fix, info);
if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
@@ -1418,9 +1432,8 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
struct i810fb_par *par = (struct i810fb_par *)info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- if (!(par->dev_flags & USE_HWCUR) || !info->var.accel_flags ||
- par->dev_flags & LOCKUP)
- return soft_cursor(info, cursor);
+ if (!par->dev_flags & LOCKUP)
+ return -ENXIO;
if (cursor->image.width > 64 || cursor->image.height > 64)
return -ENXIO;
@@ -1506,12 +1519,12 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
struct i810fb_par *par = (struct i810fb_par *) info->par;
int blank = 0, prev_state = par->cur_state;
- if (state == prev_state)
+ if (state.event == prev_state)
return 0;
- par->cur_state = state;
+ par->cur_state = state.event;
- switch (state) {
+ switch (state.event) {
case 1:
blank = VESA_VSYNC_SUSPEND;
break;
@@ -1712,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
if (bpp < 8)
bpp = 8;
+ par->i810fb_ops = i810fb_ops;
+
+ if (xres)
+ info->var.xres = xres;
+ else
+ info->var.xres = 640;
+
+ if (yres)
+ info->var.yres = yres;
+ else
+ info->var.yres = 480;
+
if (!vyres)
- vyres = (vram << 20)/(xres*bpp >> 3);
+ vyres = (vram << 20)/(info->var.xres*bpp >> 3);
- par->i810fb_ops = i810fb_ops;
- info->var.xres = xres;
- info->var.yres = yres;
info->var.yres_virtual = vyres;
info->var.bits_per_pixel = bpp;
@@ -1744,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
i810_init_cursor(par);
/* mvo: enable external vga-connector (for laptops) */
- if (ext_vga) {
+ if (extvga) {
i810_writel(HVSYNC, mmio, 0);
i810_writel(PWR_CLKC, mmio, 3);
}
@@ -1814,8 +1836,80 @@ i810_allocate_pci_resource(struct i810fb_par *par,
return 0;
}
+static void __devinit i810fb_find_init_mode(struct fb_info *info)
+{
+ struct fb_videomode mode;
+ struct fb_var_screeninfo var;
+ struct fb_monspecs *specs = &info->monspecs;
+ int found = 0;
+#ifdef CONFIG_FB_I810_I2C
+ int i;
+ int err;
+ struct i810fb_par *par = info->par;
+#endif
+
+ INIT_LIST_HEAD(&info->modelist);
+ memset(&mode, 0, sizeof(struct fb_videomode));
+ var = info->var;
+#ifdef CONFIG_FB_I810_I2C
+ i810_create_i2c_busses(par);
+
+ for (i = 0; i < 3; i++) {
+ err = i810_probe_i2c_connector(info, &par->edid, i+1);
+ if (!err)
+ break;
+ }
+
+ if (!err)
+ printk("i810fb_init_pci: DDC probe successful\n");
+
+ fb_edid_to_monspecs(par->edid, specs);
+
+ if (specs->modedb == NULL)
+ printk("i810fb_init_pci: Unable to get Mode Database\n");
+
+ fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
+ &info->modelist);
+ if (specs->modedb != NULL) {
+ if (xres && yres) {
+ struct fb_videomode *m;
+
+ if ((m = fb_find_best_mode(&var, &info->modelist))) {
+ mode = *m;
+ found = 1;
+ }
+ }
+
+ if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+ mode = specs->modedb[i];
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ mode = specs->modedb[0];
+ found = 1;
+ }
+
+ fb_videomode_to_var(&var, &mode);
+ }
+#endif
+ if (mode_option)
+ fb_find_mode(&var, info, mode_option, specs->modedb,
+ specs->modedb_len, (found) ? &mode : NULL,
+ info->var.bits_per_pixel);
+
+ info->var = var;
+ fb_destroy_modedb(specs->modedb);
+ specs->modedb = NULL;
+}
+
#ifndef MODULE
-static int __init i810fb_setup(char *options)
+static int __devinit i810fb_setup(char *options)
{
char *this_opt, *suffix = NULL;
@@ -1827,8 +1921,8 @@ static int __init i810fb_setup(char *options)
mtrr = 1;
else if (!strncmp(this_opt, "accel", 5))
accel = 1;
- else if (!strncmp(this_opt, "ext_vga", 7))
- ext_vga = 1;
+ else if (!strncmp(this_opt, "extvga", 6))
+ extvga = 1;
else if (!strncmp(this_opt, "sync", 4))
sync = 1;
else if (!strncmp(this_opt, "vram:", 5))
@@ -1857,6 +1951,8 @@ static int __init i810fb_setup(char *options)
vsync2 = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "dcolor", 6))
dcolor = 1;
+ else
+ mode_option = this_opt;
}
return 0;
}
@@ -1867,6 +1963,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
{
struct fb_info *info;
struct i810fb_par *par = NULL;
+ struct fb_videomode mode;
int i, err = -1, vfreq, hfreq, pixclock;
i = 0;
@@ -1875,7 +1972,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
if (!info)
return -ENOMEM;
- par = (struct i810fb_par *) info->par;
+ par = info->par;
par->dev = dev;
if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
@@ -1906,15 +2003,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
info->fbops = &par->i810fb_ops;
info->pseudo_palette = par->pseudo_palette;
fb_alloc_cmap(&info->cmap, 256, 0);
+ i810fb_find_init_mode(info);
if ((err = info->fbops->fb_check_var(&info->var, info))) {
i810fb_release_resource(info, par);
return err;
}
+
+ fb_var_to_videomode(&mode, &info->var);
+ fb_add_videomode(&mode, &info->modelist);
encode_fix(&info->fix, info);
i810fb_init_ringbuffer(info);
err = register_framebuffer(info);
+
if (err < 0) {
i810fb_release_resource(info, par);
printk("i810fb_init: cannot register framebuffer device\n");
@@ -1953,6 +2055,8 @@ static void i810fb_release_resource(struct fb_info *info,
struct gtt_data *gtt = &par->i810_gtt;
unset_mtrr(par);
+ i810_delete_i2c_busses(par);
+
if (par->i810_gtt.i810_cursor_memory)
agp_free_memory(gtt->i810_cursor_memory);
if (par->i810_gtt.i810_fb_memory)
@@ -1962,7 +2066,8 @@ static void i810fb_release_resource(struct fb_info *info,
iounmap(par->mmio_start_virtual);
if (par->aperture.virtual)
iounmap(par->aperture.virtual);
-
+ if (par->edid)
+ kfree(par->edid);
if (par->res_flags & FRAMEBUFFER_REQ)
release_mem_region(par->aperture.physical,
par->aperture.size);
@@ -1988,7 +2093,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
}
#ifndef MODULE
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
char *option = NULL;
@@ -2006,7 +2111,7 @@ static int __init i810fb_init(void)
#ifdef MODULE
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
hsync1 *= 1000;
hsync2 *= 1000;
@@ -2046,14 +2151,16 @@ module_param(accel, bool, 0);
MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
module_param(mtrr, bool, 0);
MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
module_param(sync, bool, 0);
MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
" (default = 0)");
module_param(dcolor, bool, 0);
MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
" (default = 0 = TrueColor)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
MODULE_AUTHOR("Tony A. Daplas");
MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 43b4297b4d48..06072a6466f2 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -83,6 +83,22 @@ extern int i810fb_sync (struct fb_info *p);
extern void i810fb_init_ringbuffer(struct fb_info *info);
extern void i810fb_load_front (u32 offset, struct fb_info *info);
+#ifdef CONFIG_FB_I810_I2C
+/* I2C */
+extern int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+ int conn);
+extern void i810_create_i2c_busses(struct i810fb_par *par);
+extern void i810_delete_i2c_busses(struct i810fb_par *par);
+#else
+static inline int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+ int conn)
+{
+ return 1;
+}
+static inline void i810_create_i2c_busses(struct i810fb_par *par) { }
+static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
+#endif
+
/* Conditionals */
#ifdef CONFIG_X86
inline void flush_cache(void)
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 6680ec9ba69e..011e11626558 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -234,7 +234,6 @@ struct intelfb_info {
/* palette */
u32 pseudo_palette[17];
- struct { u8 red, green, blue, pad; } palette[256];
/* chip info */
int pci_chipset;
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index a112a1786855..bf62e6ed0382 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -117,14 +117,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
#include <linux/pagemap.h>
#include <linux/version.h>
@@ -242,7 +238,7 @@ static int voffset = 48;
static char *mode = NULL;
module_param(accel, bool, S_IRUGO);
-MODULE_PARM_DESC(accel, "Enable console acceleration");
+MODULE_PARM_DESC(accel, "Enable hardware acceleration");
module_param(vram, int, S_IRUGO);
MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
module_param(voffset, int, S_IRUGO);
@@ -498,7 +494,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct fb_info *info;
struct intelfb_info *dinfo;
- int i, j, err, dvo;
+ int i, err, dvo;
int aperture_size, stolen_size;
struct agp_kern_info gtt_info;
int agp_memtype;
@@ -845,13 +841,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
if (bailearly == 5)
bailout(dinfo);
- for (i = 0; i < 16; i++) {
- j = color_table[i];
- dinfo->palette[i].red = default_red[j];
- dinfo->palette[i].green = default_grn[j];
- dinfo->palette[i].blue = default_blu[j];
- }
-
if (bailearly == 6)
bailout(dinfo);
@@ -1363,10 +1352,6 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
green >>= 8;
blue >>= 8;
- dinfo->palette[regno].red = red;
- dinfo->palette[regno].green = green;
- dinfo->palette[regno].blue = blue;
-
intelfbhw_setcolreg(dinfo, regno, red, green, blue,
transp);
}
@@ -1499,7 +1484,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
#endif
if (!dinfo->hwcursor)
- return soft_cursor(info, cursor);
+ return -ENXIO;
intelfbhw_cursor_hide(dinfo);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index f5bed581dc45..5bafc3c54db7 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -29,14 +29,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
#include <linux/pagemap.h>
#include <linux/version.h>
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 98e00d8601e5..e02da41f1b26 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1285,7 +1285,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
vaddr_t vm;
unsigned int offs;
unsigned int offs2;
- unsigned char store;
+ unsigned char store, orig;
unsigned char bytes[32];
unsigned char* tmp;
@@ -1298,7 +1298,8 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
if (maxSize > 0x2000000) maxSize = 0x2000000;
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+ orig = mga_inb(M_EXTVGA_DATA);
+ mga_outb(M_EXTVGA_DATA, orig | 0x80);
store = mga_readb(vm, 0x1234);
tmp = bytes;
@@ -1323,7 +1324,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+ mga_outb(M_EXTVGA_DATA, orig);
*realSize = offs - 0x100000;
#ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1858,6 +1859,8 @@ static int initMatrox2(WPMINFO struct board* b){
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+ matroxfb_update_fix(PMINFO2);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
@@ -2010,11 +2013,11 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
}
/* not match... */
if (!b->vendor)
- return -1;
+ return -ENODEV;
if (dev > 0) {
/* not requested one... */
dev--;
- return -1;
+ return -ENODEV;
}
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
if (pci_enable_device(pdev)) {
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 67f85344f0cc..ad60bbb16cdf 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1271,7 +1271,7 @@ ERROR0:;
}
static int maven_attach_adapter(struct i2c_adapter* adapter) {
- if (adapter->id == (I2C_ALGO_BIT | I2C_HW_B_G400))
+ if (adapter->id == I2C_HW_B_G400)
return i2c_probe(adapter, &addr_data, &maven_detect_client);
return 0;
}
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index a18dd024fc86..d9d3e9f6c08e 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -68,6 +68,9 @@
* "David C. Hansen" <haveblue@us.ibm.com>
* Fixes
*
+ * "Ian Romanick" <idr@us.ibm.com>
+ * Find PInS data in BIOS on PowerPC systems.
+ *
* (following author is not in any relation with this code, but his code
* is included in this driver)
*
@@ -496,10 +499,35 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
get_bios_version(vbios, bd);
get_bios_output(vbios, bd);
get_bios_tvout(vbios, bd);
+#if defined(__powerpc__)
+ /* On PowerPC cards, the PInS offset isn't stored at the end of the
+ * BIOS image. Instead, you must search the entire BIOS image for
+ * the magic PInS signature.
+ *
+ * This actually applies to all OpenFirmware base cards. Since these
+ * cards could be put in a MIPS or SPARC system, should the condition
+ * be something different?
+ */
+ for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
+ unsigned char header[3];
+
+ header[0] = readb(vbios + pins_offset);
+ header[1] = readb(vbios + pins_offset + 1);
+ header[2] = readb(vbios + pins_offset + 2);
+ if ( (header[0] == 0x2E) && (header[1] == 0x41)
+ && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
+ printk(KERN_INFO "PInS data found at offset %u\n",
+ pins_offset);
+ get_pins(vbios + pins_offset, bd);
+ break;
+ }
+ }
+#else
pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
if (pins_offset <= 0xFF80) {
get_pins(vbios + pins_offset, bd);
}
+#endif
}
#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
@@ -755,6 +783,8 @@ void matroxfb_read_pins(WPMINFO2) {
}
#endif
matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios));
+ printk(KERN_INFO "PInS memtype = %u\n",
+ (ACCESS_FBINFO(values).reg.opt & 0x1C00) >> 10);
}
EXPORT_SYMBOL(matroxfb_DAC_in);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 3edc9f49344b..47516c44a390 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -456,12 +456,22 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
*
* Valid mode specifiers for @mode_option:
*
- * <xres>x<yres>[-<bpp>][@<refresh>] or
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
* <name>[-<bpp>][@<refresh>]
*
* with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
* <name> a string.
*
+ * If 'M' is present after yres (and before refresh/bpp if present),
+ * the function will compute the timings using VESA(tm) Coordinated
+ * Video Timings (CVT). If 'R' is present after 'M', will compute with
+ * reduced blanking (for flatpanels). If 'i' is present, compute
+ * interlaced mode. If 'm' is present, add margins equal to 1.8%
+ * of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ * 'i' and 'm' must be after 'M' and 'R'. Example:
+ *
+ * 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ *
* NOTE: The passed struct @var is _not_ cleared! This allows you
* to supply values for e.g. the grayscale and accel_flags fields.
*
@@ -495,7 +505,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
- int yres_specified = 0;
+ int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
u32 best, diff;
for (i = namelen-1; i >= 0; i--) {
@@ -506,6 +516,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
!yres_specified) {
refresh = my_atoi(&name[i+1]);
refresh_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
} else
goto done;
break;
@@ -514,6 +526,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
if (!bpp_specified && !yres_specified) {
bpp = my_atoi(&name[i+1]);
bpp_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
} else
goto done;
break;
@@ -526,6 +540,22 @@ int fb_find_mode(struct fb_var_screeninfo *var,
break;
case '0'...'9':
break;
+ case 'M':
+ if (!yres_specified)
+ cvt = 1;
+ break;
+ case 'R':
+ if (!cvt)
+ rb = 1;
+ break;
+ case 'm':
+ if (!cvt)
+ margins = 1;
+ break;
+ case 'i':
+ if (!cvt)
+ interlace = 1;
+ break;
default:
goto done;
}
@@ -535,6 +565,34 @@ int fb_find_mode(struct fb_var_screeninfo *var,
res_specified = 1;
}
done:
+ if (cvt) {
+ struct fb_videomode cvt_mode;
+ int ret;
+
+ DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
+ (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
+ "", (margins) ? " with margins" : "", (interlace) ?
+ " interlaced" : "");
+
+ cvt_mode.xres = xres;
+ cvt_mode.yres = yres;
+ cvt_mode.refresh = (refresh) ? refresh : 60;
+
+ if (interlace)
+ cvt_mode.vmode |= FB_VMODE_INTERLACED;
+ else
+ cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+
+ ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+
+ if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
+ DPRINTK("modedb CVT: CVT mode ok\n");
+ return 1;
+ }
+
+ DPRINTK("CVT mode invalid, getting mode from database\n");
+ }
+
DPRINTK("Trying specified video mode%s %ix%i\n",
refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 3757c1407c19..ace484fa61ce 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -90,14 +90,13 @@ static int nvidia_gpio_getsda(void *data)
return val;
}
-#define I2C_ALGO_NVIDIA 0x0e0000
static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
{
int rc;
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_NVIDIA;
+ chan->adapter.id = I2C_HW_B_NVIDIA;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pci_dev->dev;
chan->algo.setsda = nvidia_gpio_setsda;
@@ -195,8 +194,9 @@ static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
return NULL;
}
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
{
+ struct nvidia_par *par = info->par;
u8 *edid = NULL;
int i;
@@ -206,10 +206,17 @@ int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
if (edid)
break;
}
+
+ if (!edid && conn == 1) {
+ /* try to get from firmware */
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, fb_firmware_edid(info->device),
+ EDID_LENGTH);
+ }
+
if (out_edid)
*out_edid = edid;
- if (!edid)
- return 1;
- return 0;
+ return (edid) ? 0 : 1;
}
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index 9da320986f4c..afee284fc73c 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -95,6 +95,7 @@
#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+#ifdef __LITTLE_ENDIAN
#define reverse_order(l) \
do { \
u8 *a = (u8 *)(l); \
@@ -103,5 +104,8 @@ do { \
*a = byte_rev[*a], a++; \
*a = byte_rev[*a]; \
} while(0)
+#else
+#define reverse_order(l)
+#endif /* __LITTLE_ENDIAN */
#endif /* __NV_LOCAL_H__ */
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 7d12eb85310d..4fa2cf9a8af2 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -30,8 +30,9 @@
void nvidia_create_i2c_busses(struct nvidia_par *par) {}
void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
{
+ struct nvidia_par *par = info->par;
struct device_node *dp;
unsigned char *pedid = NULL;
unsigned char *disptype = NULL;
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 42847ce1b8dd..cac44fc7f587 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -34,7 +34,7 @@ void NVLockUnlock(struct nvidia_par *par, int);
#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
void nvidia_create_i2c_busses(struct nvidia_par *par);
void nvidia_delete_i2c_busses(struct nvidia_par *par);
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
u8 ** out_edid);
#else
#define nvidia_create_i2c_busses(...)
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 0bbdca2e0f91..11c84178f420 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -401,7 +401,7 @@ void NVCommonSetup(struct fb_info *info)
nvidia_create_i2c_busses(par);
if (!par->twoHeads) {
par->CRTCnumber = 0;
- nvidia_probe_i2c_connector(par, 1, &edidA);
+ nvidia_probe_i2c_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
@@ -488,14 +488,14 @@ void NVCommonSetup(struct fb_info *info)
oldhead = NV_RD32(par->PCRTC0, 0x00000860);
NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
- nvidia_probe_i2c_connector(par, 1, &edidA);
+ nvidia_probe_i2c_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
fb_edid_to_monspecs(edidA, monA);
}
- nvidia_probe_i2c_connector(par, 2, &edidB);
+ nvidia_probe_i2c_connector(info, 2, &edidB);
if (edidB && !fb_parse_edid(edidB, &var)) {
printk("nvidiafb: EDID found from BUS2\n");
monB = &monitorB;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 52b16850a54e..3620de0f252e 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -658,7 +658,7 @@ static int nvidia_calc_regs(struct fb_info *info)
{
struct nvidia_par *par = info->par;
struct _riva_hw_state *state = &par->ModeReg;
- int i, depth = fb_get_color_depth(&info->var);
+ int i, depth = fb_get_color_depth(&info->var, &info->fix);
int h_display = info->var.xres / 8 - 1;
int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
int h_end = (info->var.xres + info->var.right_margin +
@@ -893,7 +893,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
int i, set = cursor->set;
u16 fg, bg;
- if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+ if (!hwcur || cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
return -ENXIO;
NVShowHideCursor(par, 0);
@@ -978,6 +978,9 @@ static int nvidiafb_set_par(struct fb_info *info)
!par->twoHeads)
par->FPDither = 0;
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
nvidia_init_vga(info);
nvidia_calc_regs(info);
nvidia_write_regs(par);
@@ -992,9 +995,6 @@ static int nvidiafb_set_par(struct fb_info *info)
NVWriteCrtc(par, 0x11, 0x00);
info->fix.line_length = (info->var.xres_virtual *
info->var.bits_per_pixel) >> 3;
- info->fix.visual = (info->var.bits_per_pixel == 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
if (info->var.accel_flags) {
info->fbops->fb_imageblit = nvidiafb_imageblit;
info->fbops->fb_fillrect = nvidiafb_fillrect;
@@ -1328,7 +1328,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
char buf[16];
memset(buf, 0, 16);
- snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight);
+ snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
specs->modedb_len, &modedb, 8);
}
@@ -1356,8 +1356,6 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->pixmap.size = 8 * 1024;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
- if (!hwcur)
- info->fbops->fb_cursor = soft_cursor;
info->var.accel_flags = (!noaccel);
switch (par->Architecture) {
@@ -1473,10 +1471,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
par->Chipset = (pd->vendor << 16) | pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-#ifdef CONFIG_PCI_NAMES
- printk(KERN_INFO PFX "%s\n", pd->pretty_name);
-#endif
-
if (par->Architecture == 0) {
printk(KERN_ERR PFX "unknown NV_ARCH\n");
goto err_out_free_base0;
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 42a6591e863f..611922c0b22f 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -363,7 +363,7 @@ static void __init offb_init_nodriver(struct device_node *dp)
address = (u_long) dp->addrs[i].address;
#ifdef CONFIG_PPC64
- address += dp->phb->pci_mem_offset;
+ address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
#endif
/* kludge for valkyrie */
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index e0dad948467b..2e11b601c488 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -67,6 +67,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
+#include <linux/ctype.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
@@ -2594,7 +2595,7 @@ static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
{
char *next;
- if (!(CHAR_IS_NUM(options[0]))) {
+ if (!(isdigit(options[0]))) {
(*bn) = 0;
return (options);
}
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 3e00ad7f2e31..28d1fe5fe340 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -413,7 +413,7 @@ static struct fb_ops aafb_ops = {
static int __init init_one(int slot)
{
- unsigned long base_addr = get_tc_base_addr(slot);
+ unsigned long base_addr = CKSEG1ADDR(get_tc_base_addr(slot));
struct aafb_info *ip = &my_fb_info[slot];
memset(ip, 0, sizeof(struct aafb_info));
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f8095588e99d..c98f1c8d7dc2 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -1,57 +1,55 @@
/*
- * linux/drivers/video/pmag-ba-fb.c
+ * linux/drivers/video/pmag-ba-fb.c
*
- * PMAG-BA TurboChannel framebuffer card support ... derived from:
+ * PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
+ * derived from:
* "HP300 Topcat framebuffer support (derived from macfb of all things)
* Phil Blundell <philb@gnu.org> 1998", the original code can be
- * found in the file hpfb.c in the same directory.
+ * found in the file hpfb.c in the same directory.
*
* Based on digital document:
* "PMAG-BA TURBOchannel Color Frame Buffer
* Functional Specification", Revision 1.2, August 27, 1990
*
- * DECstation related code Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org>,
- * Karsten Merker <merker@linuxtag.org> and
+ * DECstation related code Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org>,
+ * Karsten Merker <merker@linuxtag.org> and
* Harald Koerfgen.
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
+ * Copyright (c) 2005 Maciej W. Rozycki
*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
+
+#include <linux/compiler.h>
#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/fb.h>
-#include <asm/bootinfo.h>
-#include <asm/dec/machtype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
#include <asm/dec/tc.h>
+
#include <video/pmag-ba-fb.h>
-struct pmag_ba_ramdac_regs {
- unsigned char addr_low;
- unsigned char pad0[3];
- unsigned char addr_hi;
- unsigned char pad1[3];
- unsigned char data;
- unsigned char pad2[3];
- unsigned char cmap;
+
+struct pmagbafb_par {
+ struct fb_info *next;
+ volatile void __iomem *mmio;
+ volatile u32 __iomem *dac;
+ int slot;
};
-/*
- * Max 3 TURBOchannel slots -> max 3 PMAG-BA :)
- */
-static struct fb_info pmagba_fb_info[3];
-static struct fb_var_screeninfo pmagbafb_defined = {
+static struct fb_info *root_pmagbafb_dev;
+
+static struct fb_var_screeninfo pmagbafb_defined __initdata = {
.xres = 1024,
.yres = 864,
.xres_virtual = 1024,
@@ -61,58 +59,71 @@ static struct fb_var_screeninfo pmagbafb_defined = {
.green.length = 8,
.blue.length = 8,
.activate = FB_ACTIVATE_NOW,
- .height = 274,
- .width = 195,
- .accel = FB_ACCEL_NONE,
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 14452,
+ .left_margin = 116,
+ .right_margin = 12,
+ .upper_margin = 34,
+ .lower_margin = 12,
+ .hsync_len = 128,
+ .vsync_len = 3,
+ .sync = FB_SYNC_ON_GREEN,
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbafb_fix = {
+static struct fb_fix_screeninfo pmagbafb_fix __initdata = {
.id = "PMAG-BA",
- .smem_len = (1024 * 864),
+ .smem_len = (1024 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.line_length = 1024,
+ .mmio_len = PMAG_BA_SIZE - PMAG_BA_BT459,
};
-/*
- * Turn hardware cursor off
- */
-void pmagbafb_erase_cursor(struct pmag_ba_ramdac_regs *bt459_regs)
+
+static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
{
- bt459_regs->addr_low = 0;
- bt459_regs->addr_hi = 3;
- bt459_regs->data = 0;
+ writeb(v, par->dac + reg / 4);
}
+static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
+{
+ return readb(par->dac + reg / 4);
+}
+
+
/*
- * Set the palette.
+ * Set the palette.
*/
-static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
{
- struct pmag_ba_ramdac_regs *bt459_regs = (struct pmag_ba_ramdac_regs *) info->par;
+ struct pmagbafb_par *par = info->par;
- if (regno >= info->cmap.len)
- return 1;
+ BUG_ON(regno >= info->cmap.len);
red >>= 8; /* The cmap fields are 16 bits */
- green >>= 8; /* wide, but the harware colormap */
+ green >>= 8; /* wide, but the hardware colormap */
blue >>= 8; /* registers are only 8 bits wide */
- bt459_regs->addr_low = (__u8) regno;
- bt459_regs->addr_hi = 0;
- bt459_regs->cmap = red;
- bt459_regs->cmap = green;
- bt459_regs->cmap = blue;
+ mb();
+ dac_write(par, BT459_ADDR_LO, regno);
+ dac_write(par, BT459_ADDR_HI, 0x00);
+ wmb();
+ dac_write(par, BT459_CMAP, red);
+ wmb();
+ dac_write(par, BT459_CMAP, green);
+ wmb();
+ dac_write(par, BT459_CMAP, blue);
+
return 0;
}
static struct fb_ops pmagbafb_ops = {
.owner = THIS_MODULE,
- .fb_get_fix = gen_get_fix,
- .fb_get_var = gen_get_var,
.fb_setcolreg = pmagbafb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
@@ -120,63 +131,133 @@ static struct fb_ops pmagbafb_ops = {
.fb_cursor = soft_cursor,
};
-int __init pmagbafb_init_one(int slot)
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbafb_erase_cursor(struct fb_info *info)
+{
+ struct pmagbafb_par *par = info->par;
+
+ mb();
+ dac_write(par, BT459_ADDR_LO, 0x00);
+ dac_write(par, BT459_ADDR_HI, 0x03);
+ wmb();
+ dac_write(par, BT459_DATA, 0x00);
+}
+
+
+static int __init pmagbafb_init_one(int slot)
{
- unsigned long base_addr = get_tc_base_addr(slot);
- struct fb_info *info = &pmagba_fb_info[slot];
- struct display *disp = &pmagba_disp[slot];
-
- printk("PMAG-BA framebuffer in slot %d\n", slot);
- /*
- * Framebuffer display memory base address and friends
- */
- pmagbafb_fix.smem_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET;
- info->par = (base_addr + PMAG_BA_BT459_OFFSET);
-
- /*
- * Configure the Bt459 RAM DAC
- */
- pmagbafb_erase_cursor((struct pmag_ba_ramdac_regs *) info->par);
-
- /*
- * Let there be consoles..
- */
+ struct fb_info *info;
+ struct pmagbafb_par *par;
+ unsigned long base_addr;
+
+ info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->slot = slot;
+ claim_tc_card(par->slot);
+
+ base_addr = get_tc_base_addr(par->slot);
+
+ par->next = root_pmagbafb_dev;
+ root_pmagbafb_dev = info;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ goto err_alloc;
+
info->fbops = &pmagbafb_ops;
+ info->fix = pmagbafb_fix;
info->var = pmagbafb_defined;
- info->fix = pmagbafb_fix;
- info->screen_base = pmagbafb_fix.smem_start;
info->flags = FBINFO_DEFAULT;
- fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ /* MMIO mapping setup. */
+ info->fix.mmio_start = base_addr;
+ par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+ if (!par->mmio)
+ goto err_cmap;
+ par->dac = par->mmio + PMAG_BA_BT459;
+
+ /* Frame buffer mapping setup. */
+ info->fix.smem_start = base_addr + PMAG_BA_FBMEM;
+ info->screen_base = ioremap_nocache(info->fix.smem_start,
+ info->fix.smem_len);
+ if (!info->screen_base)
+ goto err_mmio_map;
+ info->screen_size = info->fix.smem_len;
+
+ pmagbafb_erase_cursor(info);
if (register_framebuffer(info) < 0)
- return 1;
+ goto err_smem_map;
+
+ pr_info("fb%d: %s frame buffer device in slot %d\n",
+ info->node, info->fix.id, par->slot);
+
return 0;
+
+
+err_smem_map:
+ iounmap(info->screen_base);
+
+err_mmio_map:
+ iounmap(par->mmio);
+
+err_cmap:
+ fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+ root_pmagbafb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+ return -ENXIO;
}
-/*
- * Initialise the framebuffer
- */
+static void __exit pmagbafb_exit_one(void)
+{
+ struct fb_info *info = root_pmagbafb_dev;
+ struct pmagbafb_par *par = info->par;
-int __init pmagbafb_init(void)
+ unregister_framebuffer(info);
+ iounmap(info->screen_base);
+ iounmap(par->mmio);
+ fb_dealloc_cmap(&info->cmap);
+ root_pmagbafb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+}
+
+
+/*
+ * Initialise the framebuffer.
+ */
+static int __init pmagbafb_init(void)
{
- int sid;
- int found = 0;
+ int count = 0;
+ int slot;
if (fb_get_options("pmagbafb", NULL))
- return -ENODEV;
-
- if (TURBOCHANNEL) {
- while ((sid = search_tc_card("PMAG-BA")) >= 0) {
- found = 1;
- claim_tc_card(sid);
- pmagbafb_init_one(sid);
- }
- return found ? 0 : -ENODEV;
- } else {
- return -ENODEV;
+ return -ENXIO;
+
+ while ((slot = search_tc_card("PMAG-BA")) >= 0) {
+ if (pmagbafb_init_one(slot) < 0)
+ break;
+ count++;
}
+ return (count > 0) ? 0 : -ENXIO;
}
+static void __exit pmagbafb_exit(void)
+{
+ while (root_pmagbafb_dev)
+ pmagbafb_exit_one();
+}
+
+
module_init(pmagbafb_init);
+module_exit(pmagbafb_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index d14eaee91cff..a483b13e117b 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -1,114 +1,128 @@
/*
- * linux/drivers/video/pmagb-b-fb.c
+ * linux/drivers/video/pmagb-b-fb.c
*
- * PMAGB-B TurboChannel framebuffer card support ... derived from:
+ * PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support,
+ * derived from:
* "HP300 Topcat framebuffer support (derived from macfb of all things)
* Phil Blundell <philb@gnu.org> 1998", the original code can be
- * found in the file hpfb.c in the same directory.
+ * found in the file hpfb.c in the same directory.
*
- * DECstation related code Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org>,
- * Karsten Merker <merker@linuxtag.org> and
+ * DECstation related code Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org>,
+ * Karsten Merker <merker@linuxtag.org> and
* Harald Koerfgen.
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
+ * Copyright (c) 2005 Maciej W. Rozycki
*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
*/
-/*
- * We currently only support the PMAGB-B in high resolution mode
- * as I know of no way to detect low resolution mode set via jumper.
- * KM, 2001/01/07
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
+#include <linux/compiler.h>
#include <linux/delay.h>
-#include <linux/init.h>
+#include <linux/errno.h>
#include <linux/fb.h>
-#include <asm/bootinfo.h>
-#include <asm/dec/machtype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
#include <asm/dec/tc.h>
+
#include <video/pmagb-b-fb.h>
-struct pmagb_b_ramdac_regs {
- unsigned char addr_low;
- unsigned char pad0[3];
- unsigned char addr_hi;
- unsigned char pad1[3];
- unsigned char data;
- unsigned char pad2[3];
- unsigned char cmap;
+
+struct pmagbbfb_par {
+ struct fb_info *next;
+ volatile void __iomem *mmio;
+ volatile void __iomem *smem;
+ volatile u32 __iomem *sfb;
+ volatile u32 __iomem *dac;
+ unsigned int osc0;
+ unsigned int osc1;
+ int slot;
};
-/*
- * Max 3 TURBOchannel slots -> max 3 PMAGB-B :)
- */
-static struct fb_info pmagbb_fb_info[3];
-static struct fb_var_screeninfo pmagbbfb_defined = {
- .xres = 1280,
- .yres = 1024,
- .xres_virtual = 1280,
- .yres_virtual = 1024,
+static struct fb_info *root_pmagbbfb_dev;
+
+static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
.bits_per_pixel = 8,
.red.length = 8,
.green.length = 8,
.blue.length = 8,
.activate = FB_ACTIVATE_NOW,
- .height = 274,
- .width = 195,
+ .height = -1,
+ .width = -1,
.accel_flags = FB_ACCEL_NONE,
+ .sync = FB_SYNC_ON_GREEN,
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbafb_fix = {
+static struct fb_fix_screeninfo pmagbbfb_fix __initdata = {
.id = "PMAGB-BA",
- .smem_len = (1280 * 1024),
+ .smem_len = (2048 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
- .line_length = 1280,
+ .mmio_len = PMAGB_B_FBMEM,
+};
+
+
+static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v)
+{
+ writel(v, par->sfb + reg / 4);
}
-/*
- * Turn hardware cursor off
- */
-void pmagbbfb_erase_cursor(struct pmagb_b_ramdac_regs *bt459_regs)
+static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+ return readl(par->sfb + reg / 4);
+}
+
+static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v)
{
- bt459_regs->addr_low = 0;
- bt459_regs->addr_hi = 3;
- bt459_regs->data = 0;
+ writeb(v, par->dac + reg / 4);
}
+static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+ return readb(par->dac + reg / 4);
+}
+
+static inline void gp0_write(struct pmagbbfb_par *par, u32 v)
+{
+ writel(v, par->mmio + PMAGB_B_GP0);
+}
+
+
/*
- * Set the palette.
+ * Set the palette.
*/
-static int pmagbbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
{
- struct pmagb_b_ramdac_regs *bt459_regs = (struct pmagb_b_ramdac_regs *) info->par;
-
- if (regno >= info->cmap.len)
- return 1;
+ struct pmagbbfb_par *par = info->par;
+
+ BUG_ON(regno >= info->cmap.len);
red >>= 8; /* The cmap fields are 16 bits */
- green >>= 8; /* wide, but the harware colormap */
+ green >>= 8; /* wide, but the hardware colormap */
blue >>= 8; /* registers are only 8 bits wide */
- bt459_regs->addr_low = (__u8) regno;
- bt459_regs->addr_hi = 0;
- bt459_regs->cmap = red;
- bt459_regs->cmap = green;
- bt459_regs->cmap = blue;
+ mb();
+ dac_write(par, BT459_ADDR_LO, regno);
+ dac_write(par, BT459_ADDR_HI, 0x00);
+ wmb();
+ dac_write(par, BT459_CMAP, red);
+ wmb();
+ dac_write(par, BT459_CMAP, green);
+ wmb();
+ dac_write(par, BT459_CMAP, blue);
+
return 0;
}
@@ -121,62 +135,247 @@ static struct fb_ops pmagbbfb_ops = {
.fb_cursor = soft_cursor,
};
-int __init pmagbbfb_init_one(int slot)
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbbfb_erase_cursor(struct fb_info *info)
+{
+ struct pmagbbfb_par *par = info->par;
+
+ mb();
+ dac_write(par, BT459_ADDR_LO, 0x00);
+ dac_write(par, BT459_ADDR_HI, 0x03);
+ wmb();
+ dac_write(par, BT459_DATA, 0x00);
+}
+
+/*
+ * Set up screen parameters.
+ */
+static void __init pmagbbfb_screen_setup(struct fb_info *info)
+{
+ struct pmagbbfb_par *par = info->par;
+
+ info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4;
+ info->var.xres_virtual = info->var.xres;
+ info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK;
+ info->var.yres_virtual = info->var.yres;
+ info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_BP_SHIFT) &
+ SFB_VID_HOR_BP_MASK) * 4;
+ info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_FP_SHIFT) &
+ SFB_VID_HOR_FP_MASK) * 4;
+ info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK;
+ info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK;
+ info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_SYN_SHIFT) &
+ SFB_VID_HOR_SYN_MASK) * 4;
+ info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK;
+
+ info->fix.line_length = info->var.xres;
+};
+
+/*
+ * Determine oscillator configuration.
+ */
+static void __init pmagbbfb_osc_setup(struct fb_info *info)
{
- unsigned long base_addr = get_tc_base_addr(slot);
- struct fb_info *info = &pmagbb_fb_info[slot];
-
- printk("PMAGB-BA framebuffer in slot %d\n", slot);
- /*
- * Framebuffer display memory base address and friends
- */
- pmagbbfb_fix.smem_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET;
- info->par = (base_addr + PMAGB_B_BT459_OFFSET);
-
- /*
- * Configure the Bt459 RAM DAC
- */
- pmagbbfb_erase_cursor((struct pmagb_b_ramdac_regs *) info->par);
-
- /*
- * Let there be consoles..
- */
+ static unsigned int pmagbbfb_freqs[] __initdata = {
+ 130808, 119843, 104000, 92980, 74367, 72800,
+ 69197, 66000, 65000, 50350, 36000, 32000, 25175
+ };
+ struct pmagbbfb_par *par = info->par;
+ u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
+ u32 freq0, freq1, freqtc = get_tc_speed() / 250;
+ int i, j;
+
+ gp0_write(par, 0); /* select Osc0 */
+ for (j = 0; j < 16; j++) {
+ mb();
+ sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+ mb();
+ for (i = 0; i < 100; i++) { /* nominally max. 20.5us */
+ if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+ break;
+ udelay(1);
+ }
+ count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+ }
+
+ gp0_write(par, 1); /* select Osc1 */
+ for (j = 0; j < 16; j++) {
+ mb();
+ sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+
+ for (i = 0; i < 100; i++) { /* nominally max. 20.5us */
+ if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+ break;
+ udelay(1);
+ }
+ count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+ }
+
+ freq0 = (freqtc * count0 + counttc / 2) / counttc;
+ par->osc0 = freq0;
+ if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 &&
+ freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64)
+ par->osc0 = pmagbbfb_freqs[0];
+
+ freq1 = (par->osc0 * count1 + count0 / 2) / count0;
+ par->osc1 = freq1;
+ for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++)
+ if (freq1 >= pmagbbfb_freqs[i] -
+ (pmagbbfb_freqs[i] + 128) / 256 &&
+ freq1 <= pmagbbfb_freqs[i] +
+ (pmagbbfb_freqs[i] + 128) / 256) {
+ par->osc1 = pmagbbfb_freqs[i];
+ break;
+ }
+
+ if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 ||
+ par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512)
+ par->osc1 = 0;
+
+ gp0_write(par, par->osc1 != 0); /* reselect OscX */
+
+ info->var.pixclock = par->osc1 ?
+ (1000000000 + par->osc1 / 2) / par->osc1 :
+ (1000000000 + par->osc0 / 2) / par->osc0;
+};
+
+
+static int __init pmagbbfb_init_one(int slot)
+{
+ char freq0[12], freq1[12];
+ struct fb_info *info;
+ struct pmagbbfb_par *par;
+ unsigned long base_addr;
+ u32 vid_base;
+
+ info = framebuffer_alloc(sizeof(struct pmagbbfb_par), NULL);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->slot = slot;
+ claim_tc_card(par->slot);
+
+ base_addr = get_tc_base_addr(par->slot);
+
+ par->next = root_pmagbbfb_dev;
+ root_pmagbbfb_dev = info;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ goto err_alloc;
+
info->fbops = &pmagbbfb_ops;
- info->var = pmagbbfb_defined;
info->fix = pmagbbfb_fix;
- info->screen_base = pmagbbfb_fix.smem_start;
+ info->var = pmagbbfb_defined;
info->flags = FBINFO_DEFAULT;
- fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ /* MMIO mapping setup. */
+ info->fix.mmio_start = base_addr;
+ par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+ if (!par->mmio)
+ goto err_cmap;
+ par->sfb = par->mmio + PMAGB_B_SFB;
+ par->dac = par->mmio + PMAGB_B_BT459;
+
+ /* Frame buffer mapping setup. */
+ info->fix.smem_start = base_addr + PMAGB_B_FBMEM;
+ par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
+ if (!par->smem)
+ goto err_mmio_map;
+ vid_base = sfb_read(par, SFB_REG_VID_BASE);
+ info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
+ info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
+
+ pmagbbfb_erase_cursor(info);
+ pmagbbfb_screen_setup(info);
+ pmagbbfb_osc_setup(info);
if (register_framebuffer(info) < 0)
- return 1;
+ goto err_smem_map;
+
+ snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
+ par->osc0 / 1000, par->osc0 % 1000);
+ snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
+ par->osc1 / 1000, par->osc1 % 1000);
+
+ pr_info("fb%d: %s frame buffer device in slot %d\n",
+ info->node, info->fix.id, par->slot);
+ pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n",
+ info->node, freq0, par->osc1 ? freq1 : "disabled",
+ par->osc1 != 0);
+
return 0;
+
+
+err_smem_map:
+ iounmap(par->smem);
+
+err_mmio_map:
+ iounmap(par->mmio);
+
+err_cmap:
+ fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+ root_pmagbbfb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+ return -ENXIO;
}
-/*
- * Initialise the framebuffer
- */
+static void __exit pmagbbfb_exit_one(void)
+{
+ struct fb_info *info = root_pmagbbfb_dev;
+ struct pmagbbfb_par *par = info->par;
+
+ unregister_framebuffer(info);
+ iounmap(par->smem);
+ iounmap(par->mmio);
+ fb_dealloc_cmap(&info->cmap);
+ root_pmagbbfb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+}
-int __init pmagbbfb_init(void)
+
+/*
+ * Initialise the framebuffer.
+ */
+static int __init pmagbbfb_init(void)
{
- int sid;
- int found = 0;
+ int count = 0;
+ int slot;
if (fb_get_options("pmagbbfb", NULL))
- return -ENODEV;
+ return -ENXIO;
- if (TURBOCHANNEL) {
- while ((sid = search_tc_card("PMAGB-BA")) >= 0) {
- found = 1;
- claim_tc_card(sid);
- pmagbbfb_init_one(sid);
- }
- return found ? 0 : -ENODEV;
- } else {
- return -ENODEV;
+ while ((slot = search_tc_card("PMAGB-BA")) >= 0) {
+ if (pmagbbfb_init_one(slot) < 0)
+ break;
+ count++;
}
+ return (count > 0) ? 0 : -ENXIO;
+}
+
+static void __exit pmagbbfb_exit(void)
+{
+ while (root_pmagbbfb_dev)
+ pmagbbfb_exit_one();
}
+
module_init(pmagbbfb_init);
+module_exit(pmagbbfb_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 30112816420c..34d4dcc0320a 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -468,6 +468,36 @@ static inline unsigned int get_pcd(unsigned int pixclock)
}
/*
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
+ */
+static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+{
+ unsigned long long htime;
+
+ if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+ fbi->hsync_time=0;
+ return;
+ }
+
+ htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000;
+ do_div(htime, pcd * fbi->fb.var.hsync_len);
+ fbi->hsync_time = htime;
+}
+
+unsigned long pxafb_get_hsync_time(struct device *dev)
+{
+ struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+ /* If display is blanked/suspended, hsync isn't active */
+ if (!fbi || (fbi->state != C_ENABLE))
+ return 0;
+
+ return fbi->hsync_time;
+}
+EXPORT_SYMBOL(pxafb_get_hsync_time);
+
+/*
* pxafb_activate_var():
* Configures LCD Controller based on entries in var parameter. Settings are
* only written to the controller if changes were made.
@@ -631,6 +661,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
fbi->reg_lccr1 = new_regs.lccr1;
fbi->reg_lccr2 = new_regs.lccr2;
fbi->reg_lccr3 = new_regs.lccr3;
+ set_hsync_time(fbi, pcd);
local_irq_restore(flags);
/*
@@ -907,6 +938,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
case CPUFREQ_POSTCHANGE:
pcd = get_pcd(fbi->fb.var.pixclock);
+ set_hsync_time(fbi, pcd);
fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
break;
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index de15fec5f82f..22c00be786a8 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -83,6 +83,8 @@ struct pxafb_info {
u_int reg_lccr2;
u_int reg_lccr3;
+ unsigned long hsync_time;
+
volatile u_char state;
volatile u_char task_state;
struct semaphore ctrlr_sem;
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 71b69da0c40d..162012bb9264 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -21,7 +21,6 @@
#include <asm/uaccess.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/q40_master.h>
#include <linux/fb.h>
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index ae297e222681..3e9f96e9237d 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1936,10 +1936,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
default_par->Chipset = (pd->vendor << 16) | pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
-#ifdef CONFIG_PCI_NAMES
- printk(KERN_INFO PFX "%s\n", pd->pretty_name);
-#endif
-
if(default_par->riva.Architecture == 0) {
printk(KERN_ERR PFX "unknown NV_ARCH\n");
ret=-ENODEV;
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index da1334dfd51d..77151d8e0766 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -92,14 +92,13 @@ static int riva_gpio_getsda(void* data)
return val;
}
-#define I2C_ALGO_RIVA 0x0e0000
static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
{
int rc;
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_RIVA;
+ chan->adapter.id = I2C_HW_B_RIVA;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pdev->dev;
chan->algo.setsda = riva_gpio_setsda;
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 3848be2b9d2d..fa98d91c42eb 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -655,7 +655,7 @@ bail:
}
#ifdef CONFIG_PM
-static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
+static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct fb_info *info = dev_get_drvdata(dev);
struct s1d13xxxfb_par *s1dfb = info->par;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
new file mode 100644
index 000000000000..00c0223a352e
--- /dev/null
+++ b/drivers/video/s3c2410fb.c
@@ -0,0 +1,915 @@
+/*
+ * linux/drivers/video/s3c2410fb.c
+ * Copyright (c) Arnaud Patard, Ben Dooks
+ *
+ * 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.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.c and others
+ *
+ * ChangeLog
+ * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - u32 state -> pm_message_t state
+ * - S3C2410_{VA,SZ}_LCD -> S3C24XX
+ *
+ * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the ioctl
+ * - use readl/writel instead of __raw_writel/__raw_readl
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Added the possibility to set on or off the
+ * debugging mesaages
+ * - Replaced 0 and 1 by on or off when reading the
+ * /sys files
+ *
+ * 2005-03-23: Ben Dooks <ben-linux@fluff.org>
+ * - added non 16bpp modes
+ * - updated platform information for range of x/y/bpp
+ * - add code to ensure palette is written correctly
+ * - add pixel clock divisor control
+ *
+ * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the use of currcon as it no more exist
+ * - Added LCD power sysfs interface
+ *
+ * 2004-11-03: Ben Dooks <ben-linux@fluff.org>
+ * - minor cleanups
+ * - add suspend/resume support
+ * - s3c2410fb_setcolreg() not valid in >8bpp modes
+ * - removed last CONFIG_FB_S3C2410_FIXED
+ * - ensure lcd controller stopped before cleanup
+ * - added sysfs interface for backlight power
+ * - added mask for gpio configuration
+ * - ensured IRQs disabled during GPIO configuration
+ * - disable TPAL before enabling video
+ *
+ * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Suppress command line options
+ *
+ * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.c to s3c2410fb.c
+ * - Add support for different devices
+ * - Backlight support
+ *
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ * - added clock (de-)allocation code
+ * - added fixem fbmem option
+ *
+ * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ * - added a forgotten return in h1940fb_init
+ *
+ * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
+ * - code cleanup and extended debugging
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#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/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/fb.h>
+#include <asm/hardware/clock.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "s3c2410fb.h"
+
+
+static struct s3c2410fb_mach_info *mach_info;
+
+/* Debugging stuff */
+#ifdef CONFIG_FB_S3C2410_DEBUG
+static int debug = 1;
+#else
+static int debug = 0;
+#endif
+
+#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
+
+/* useful functions */
+
+/* s3c2410fb_set_lcdaddr
+ *
+ * initialise lcd controller address pointers
+*/
+
+static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->fb->var;
+ unsigned long saddr1, saddr2, saddr3;
+
+ saddr1 = fbi->fb->fix.smem_start >> 1;
+ saddr2 = fbi->fb->fix.smem_start;
+ saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
+ saddr2>>= 1;
+
+ saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+
+ dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
+ dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
+ dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
+
+ writel(saddr1, S3C2410_LCDSADDR1);
+ writel(saddr2, S3C2410_LCDSADDR2);
+ writel(saddr3, S3C2410_LCDSADDR3);
+}
+
+/* s3c2410fb_calc_pixclk()
+ *
+ * calculate divisor for clk->pixclk
+*/
+
+static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
+ unsigned long pixclk)
+{
+ unsigned long clk = clk_get_rate(fbi->clk);
+ unsigned long long div;
+
+ /* pixclk is in picoseoncds, our clock is in Hz
+ *
+ * Hz -> picoseconds is / 10^-12
+ */
+
+ div = (unsigned long long)clk * pixclk;
+ do_div(div,1000000UL);
+ do_div(div,1000000UL);
+
+ dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
+ return div;
+}
+
+/*
+ * s3c2410fb_check_var():
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ *
+ */
+static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+
+ dprintk("check_var(var=%p, info=%p)\n", var, info);
+
+ /* validate x/y resolution */
+
+ if (var->yres > fbi->mach_info->yres.max)
+ var->yres = fbi->mach_info->yres.max;
+ else if (var->yres < fbi->mach_info->yres.min)
+ var->yres = fbi->mach_info->yres.min;
+
+ if (var->xres > fbi->mach_info->xres.max)
+ var->yres = fbi->mach_info->xres.max;
+ else if (var->xres < fbi->mach_info->xres.min)
+ var->xres = fbi->mach_info->xres.min;
+
+ /* validate bpp */
+
+ if (var->bits_per_pixel > fbi->mach_info->bpp.max)
+ var->bits_per_pixel = fbi->mach_info->bpp.max;
+ else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
+ var->bits_per_pixel = fbi->mach_info->bpp.min;
+
+ /* set r/g/b positions */
+
+ if (var->bits_per_pixel == 16) {
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ var->transp.length = 0;
+ } else {
+ var->red.length = var->bits_per_pixel;
+ var->red.offset = 0;
+ var->green.length = var->bits_per_pixel;
+ var->green.offset = 0;
+ var->blue.length = var->bits_per_pixel;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ }
+
+ return 0;
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+*/
+
+static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
+ struct fb_var_screeninfo *var)
+{
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+
+ dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
+ dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
+ dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
+
+ switch (var->bits_per_pixel) {
+ case 1:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+ break;
+ case 2:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+ break;
+ case 4:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+ break;
+ case 8:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+ break;
+ case 16:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+ break;
+ }
+
+ /* check to see if we need to update sync/borders */
+
+ if (!fbi->mach_info->fixed_syncs) {
+ dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+ var->upper_margin, var->lower_margin,
+ var->vsync_len);
+
+ dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+ var->left_margin, var->right_margin,
+ var->hsync_len);
+
+ fbi->regs.lcdcon2 =
+ S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+ S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+ S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+ fbi->regs.lcdcon3 =
+ S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+ S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+
+ fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
+ fbi->regs.lcdcon4 |= S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+ }
+
+ /* update X/Y info */
+
+ fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+ fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+ fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
+ fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+
+ if (var->pixclock > 0) {
+ int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
+
+ clkdiv = (clkdiv / 2) -1;
+ if (clkdiv < 0)
+ clkdiv = 0;
+
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
+ }
+
+ /* write new registers */
+
+ dprintk("new register set:\n");
+ dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
+ dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
+ dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
+ dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
+ dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
+
+ writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ /* set lcd address pointers */
+ s3c2410fb_set_lcdaddr(fbi);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+}
+
+
+/*
+ * s3c2410fb_set_par - Optional function. Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ */
+static int s3c2410fb_set_par(struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+
+ if (var->bits_per_pixel == 16)
+ fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ else
+ fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8;
+
+ /* activate this new configuration */
+
+ s3c2410fb_activate_var(fbi, var);
+ return 0;
+}
+
+static void schedule_palette_update(struct s3c2410fb_info *fbi,
+ unsigned int regno, unsigned int val)
+{
+ unsigned long flags;
+ unsigned long irqen;
+
+ local_irq_save(flags);
+
+ fbi->palette_buffer[regno] = val;
+
+ if (!fbi->palette_ready) {
+ fbi->palette_ready = 1;
+
+ /* enable IRQ */
+ irqen = readl(S3C2410_LCDINTMSK);
+ irqen &= ~S3C2410_LCDINT_FRSYNC;
+ writel(irqen, S3C2410_LCDINTMSK);
+ }
+
+ local_irq_restore(flags);
+}
+
+/* from pxafb.c */
+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int s3c2410fb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+ unsigned int val;
+
+ /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n", regno, red, green, blue); */
+
+ switch (fbi->fb->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /* true-colour, use pseuo-palette */
+
+ if (regno < 16) {
+ u32 *pal = fbi->fb->pseudo_palette;
+
+ val = chan_to_field(red, &fbi->fb->var.red);
+ val |= chan_to_field(green, &fbi->fb->var.green);
+ val |= chan_to_field(blue, &fbi->fb->var.blue);
+
+ pal[regno] = val;
+ }
+ break;
+
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (regno < 256) {
+ /* currently assume RGB 5-6-5 mode */
+
+ val = ((red >> 0) & 0xf800);
+ val |= ((green >> 5) & 0x07e0);
+ val |= ((blue >> 11) & 0x001f);
+
+ writel(val, S3C2410_TFTPAL(regno));
+ schedule_palette_update(fbi, regno, val);
+ }
+
+ break;
+
+ default:
+ return 1; /* unknown type */
+ }
+
+ return 0;
+}
+
+
+/**
+ * s3c2410fb_blank
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ *
+ */
+static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
+{
+ dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (blank_mode == FB_BLANK_UNBLANK)
+ writel(0x0, S3C2410_TPAL);
+ else {
+ dprintk("setting TPAL to output 0x000000\n");
+ writel(S3C2410_TPAL_EN, S3C2410_TPAL);
+ }
+
+ return 0;
+}
+
+static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
+}
+static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (len < 1)
+ return -EINVAL;
+
+ if (strnicmp(buf, "on", 2) == 0 ||
+ strnicmp(buf, "1", 1) == 0) {
+ debug = 1;
+ printk(KERN_DEBUG "s3c2410fb: Debug On");
+ } else if (strnicmp(buf, "off", 3) == 0 ||
+ strnicmp(buf, "0", 1) == 0) {
+ debug = 0;
+ printk(KERN_DEBUG "s3c2410fb: Debug Off");
+ } else {
+ return -EINVAL;
+ }
+
+ return len;
+}
+
+
+static DEVICE_ATTR(debug, 0666,
+ s3c2410fb_debug_show,
+ s3c2410fb_debug_store);
+
+static struct fb_ops s3c2410fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = s3c2410fb_check_var,
+ .fb_set_par = s3c2410fb_set_par,
+ .fb_blank = s3c2410fb_blank,
+ .fb_setcolreg = s3c2410fb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+
+/*
+ * s3c2410fb_map_video_memory():
+ * Allocates the DRAM memory for the frame buffer. This buffer is
+ * remapped into a non-cached, non-buffered, memory region to
+ * allow palette and pixel writes to occur without flushing the
+ * cache. Once this area is remapped, all virtual memory
+ * access to the video memory should occur at the new region.
+ */
+static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi)
+{
+ dprintk("map_video_memory(fbi=%p)\n", fbi);
+
+ fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
+ fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+ &fbi->map_dma, GFP_KERNEL);
+
+ fbi->map_size = fbi->fb->fix.smem_len;
+
+ if (fbi->map_cpu) {
+ /* prevent initial garbage on screen */
+ dprintk("map_video_memory: clear %p:%08x\n",
+ fbi->map_cpu, fbi->map_size);
+ memset(fbi->map_cpu, 0xf0, fbi->map_size);
+
+ fbi->screen_dma = fbi->map_dma;
+ fbi->fb->screen_base = fbi->map_cpu;
+ fbi->fb->fix.smem_start = fbi->screen_dma;
+
+ dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",
+ fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);
+ }
+
+ return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi)
+{
+ dma_free_writecombine(fbi->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma);
+}
+
+static inline void modify_gpio(void __iomem *reg,
+ unsigned long set, unsigned long mask)
+{
+ unsigned long tmp;
+
+ tmp = readl(reg) & ~mask;
+ writel(tmp | set, reg);
+}
+
+
+/*
+ * s3c2410fb_init_registers - Initialise all LCD-related registers
+ */
+
+int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+{
+ unsigned long flags;
+
+ /* Initialise LCD with values from haret */
+
+ local_irq_save(flags);
+
+ /* modify the gpio(s) with interrupts set (bjd) */
+
+ modify_gpio(S3C2410_GPCUP, mach_info->gpcup, mach_info->gpcup_mask);
+ modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
+ modify_gpio(S3C2410_GPDUP, mach_info->gpdup, mach_info->gpdup_mask);
+ modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
+
+ local_irq_restore(flags);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ s3c2410fb_set_lcdaddr(fbi);
+
+ dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel);
+ writel(mach_info->lpcsel, S3C2410_LPCSEL);
+
+ dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL));
+
+ /* ensure temporary palette disabled */
+ writel(0x00, S3C2410_TPAL);
+
+ /* Enable video by setting the ENVID bit to 1 */
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ return 0;
+}
+
+static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
+{
+ unsigned int i;
+ unsigned long ent;
+
+ fbi->palette_ready = 0;
+
+ for (i = 0; i < 256; i++) {
+ if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)
+ continue;
+
+ writel(ent, S3C2410_TFTPAL(i));
+
+ /* it seems the only way to know exactly
+ * if the palette wrote ok, is to check
+ * to see if the value verifies ok
+ */
+
+ if (readw(S3C2410_TFTPAL(i)) == ent)
+ fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+ else
+ fbi->palette_ready = 1; /* retry */
+ }
+}
+
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
+{
+ struct s3c2410fb_info *fbi = dev_id;
+ unsigned long lcdirq = readl(S3C2410_LCDINTPND);
+
+ if (lcdirq & S3C2410_LCDINT_FRSYNC) {
+ if (fbi->palette_ready)
+ s3c2410fb_write_palette(fbi);
+
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND);
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static char driver_name[]="s3c2410fb";
+
+int __init s3c2410fb_probe(struct device *dev)
+{
+ struct s3c2410fb_info *info;
+ struct fb_info *fbinfo;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3c2410fb_hw *mregs;
+ int ret;
+ int irq;
+ int i;
+
+ mach_info = dev->platform_data;
+ if (mach_info == NULL) {
+ dev_err(dev,"no platform data for lcd, cannot attach\n");
+ return -EINVAL;
+ }
+
+ mregs = &mach_info->regs;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq for device\n");
+ return -ENOENT;
+ }
+
+ fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), dev);
+ if (!fbinfo) {
+ return -ENOMEM;
+ }
+
+
+ info = fbinfo->par;
+ info->fb = fbinfo;
+ dev_set_drvdata(dev, fbinfo);
+
+ s3c2410fb_init_registers(info);
+
+ dprintk("devinit\n");
+
+ strcpy(fbinfo->fix.id, driver_name);
+
+ memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
+
+ info->mach_info = dev->platform_data;
+
+ fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbinfo->fix.type_aux = 0;
+ fbinfo->fix.xpanstep = 0;
+ fbinfo->fix.ypanstep = 0;
+ fbinfo->fix.ywrapstep = 0;
+ fbinfo->fix.accel = FB_ACCEL_NONE;
+
+ fbinfo->var.nonstd = 0;
+ fbinfo->var.activate = FB_ACTIVATE_NOW;
+ fbinfo->var.height = mach_info->height;
+ fbinfo->var.width = mach_info->width;
+ fbinfo->var.accel_flags = 0;
+ fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+ fbinfo->fbops = &s3c2410fb_ops;
+ fbinfo->flags = FBINFO_FLAG_DEFAULT;
+ fbinfo->pseudo_palette = &info->pseudo_pal;
+
+ fbinfo->var.xres = mach_info->xres.defval;
+ fbinfo->var.xres_virtual = mach_info->xres.defval;
+ fbinfo->var.yres = mach_info->yres.defval;
+ fbinfo->var.yres_virtual = mach_info->yres.defval;
+ fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
+
+ fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1;
+ fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1;
+ fbinfo->var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
+
+ fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
+ fbinfo->var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
+ fbinfo->var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
+
+ fbinfo->var.red.offset = 11;
+ fbinfo->var.green.offset = 5;
+ fbinfo->var.blue.offset = 0;
+ fbinfo->var.transp.offset = 0;
+ fbinfo->var.red.length = 5;
+ fbinfo->var.green.length = 6;
+ fbinfo->var.blue.length = 5;
+ fbinfo->var.transp.length = 0;
+ fbinfo->fix.smem_len = mach_info->xres.max *
+ mach_info->yres.max *
+ mach_info->bpp.max / 8;
+
+ for (i = 0; i < 256; i++)
+ info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+
+ if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) {
+ ret = -EBUSY;
+ goto dealloc_fb;
+ }
+
+
+ dprintk("got LCD region\n");
+
+ ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, info);
+ if (ret) {
+ dev_err(dev, "cannot get irq %d - err %d\n", irq, ret);
+ ret = -EBUSY;
+ goto release_mem;
+ }
+
+ info->clk = clk_get(NULL, "lcd");
+ if (!info->clk || IS_ERR(info->clk)) {
+ printk(KERN_ERR "failed to get lcd clock source\n");
+ ret = -ENOENT;
+ goto release_irq;
+ }
+
+ clk_use(info->clk);
+ clk_enable(info->clk);
+ dprintk("got and enabled clock\n");
+
+ msleep(1);
+
+ /* Initialize video memory */
+ ret = s3c2410fb_map_video_memory(info);
+ if (ret) {
+ printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+ ret = -ENOMEM;
+ goto release_clock;
+ }
+ dprintk("got video memory\n");
+
+ ret = s3c2410fb_init_registers(info);
+
+ ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
+
+ ret = register_framebuffer(fbinfo);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
+ goto free_video_memory;
+ }
+
+ /* create device files */
+ device_create_file(dev, &dev_attr_debug);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ fbinfo->node, fbinfo->fix.id);
+
+ return 0;
+
+free_video_memory:
+ s3c2410fb_unmap_video_memory(info);
+release_clock:
+ clk_disable(info->clk);
+ clk_unuse(info->clk);
+ clk_put(info->clk);
+release_irq:
+ free_irq(irq,info);
+release_mem:
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+dealloc_fb:
+ framebuffer_release(fbinfo);
+ return ret;
+}
+
+/* s3c2410fb_stop_lcd
+ *
+ * shutdown the lcd controller
+*/
+
+static void s3c2410fb_stop_lcd(void)
+{
+ unsigned long flags;
+ unsigned long tmp;
+
+ local_irq_save(flags);
+
+ tmp = readl(S3C2410_LCDCON1);
+ writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+
+ local_irq_restore(flags);
+}
+
+/*
+ * Cleanup
+ */
+static int s3c2410fb_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+ int irq;
+
+ s3c2410fb_stop_lcd();
+ msleep(1);
+
+ s3c2410fb_unmap_video_memory(info);
+
+ if (info->clk) {
+ clk_disable(info->clk);
+ clk_unuse(info->clk);
+ clk_put(info->clk);
+ info->clk = NULL;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ free_irq(irq,info);
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+ unregister_framebuffer(fbinfo);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* suspend and resume support for the lcd controller */
+
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+
+ if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
+ s3c2410fb_stop_lcd();
+
+ /* sleep before disabling the clock, we need to ensure
+ * the LCD DMA engine is not going to get back on the bus
+ * before the clock goes off again (bjd) */
+
+ msleep(1);
+ clk_disable(info->clk);
+ }
+
+ return 0;
+}
+
+static int s3c2410fb_resume(struct device *dev, u32 level)
+{
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+
+ if (level == RESUME_ENABLE) {
+ clk_enable(info->clk);
+ msleep(1);
+
+ s3c2410fb_init_registers(info);
+
+ }
+
+ return 0;
+}
+
+#else
+#define s3c2410fb_suspend NULL
+#define s3c2410fb_resume NULL
+#endif
+
+static struct device_driver s3c2410fb_driver = {
+ .name = "s3c2410-lcd",
+ .bus = &platform_bus_type,
+ .probe = s3c2410fb_probe,
+ .suspend = s3c2410fb_suspend,
+ .resume = s3c2410fb_resume,
+ .remove = s3c2410fb_remove
+};
+
+int __devinit s3c2410fb_init(void)
+{
+ return driver_register(&s3c2410fb_driver);
+}
+
+static void __exit s3c2410fb_cleanup(void)
+{
+ driver_unregister(&s3c2410fb_driver);
+}
+
+
+module_init(s3c2410fb_init);
+module_exit(s3c2410fb_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
new file mode 100644
index 000000000000..be40968f899e
--- /dev/null
+++ b/drivers/video/s3c2410fb.h
@@ -0,0 +1,56 @@
+/*
+ * linux/drivers/s3c2410fb.h
+ * Copyright (c) Arnaud Patard
+ *
+ * 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.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.h
+ *
+ * ChangeLog
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Moved dprintk to s3c2410fb.c
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.h to s3c2410fb.h
+ * - Chenged h1940 to s3c2410
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#ifndef __S3C2410FB_H
+#define __S3C2410FB_H
+
+struct s3c2410fb_info {
+ struct fb_info *fb;
+ struct device *dev;
+ struct clk *clk;
+
+ struct s3c2410fb_mach_info *mach_info;
+
+ /* raw memory addresses */
+ dma_addr_t map_dma; /* physical */
+ u_char * map_cpu; /* virtual */
+ u_int map_size;
+
+ struct s3c2410fb_hw regs;
+
+ /* addresses of pieces placed in raw buffer */
+ u_char * screen_cpu; /* virtual address of buffer */
+ dma_addr_t screen_dma; /* physical address of buffer */
+ unsigned int palette_ready;
+
+ /* keep these registers in case we need to re-write palette */
+ u32 palette_buffer[256];
+ u32 pseudo_pal[16];
+};
+
+#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */
+
+int s3c2410fb_init(void);
+
+#endif
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 024a0cecff15..959404ad68f4 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -137,7 +137,6 @@ static int prosavage_gpio_getsda(void* data)
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
}
-#define I2C_ALGO_SAVAGE 0x0f0000
static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
const char *name)
{
@@ -147,7 +146,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
if (add_bus && chan->par) {
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_SAVAGE;
+ chan->adapter.id = I2C_HW_B_SAVAGE;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pcidev->dev;
chan->algo.udelay = 40;
@@ -260,8 +259,9 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
return buf;
}
-int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
+int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
{
+ struct savagefb_par *par = info->par;
u8 *edid = NULL;
int i;
@@ -271,12 +271,19 @@ int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
if (edid)
break;
}
+
+ if (!edid) {
+ /* try to get from firmware */
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, fb_firmware_edid(info->device),
+ EDID_LENGTH);
+ }
+
if (out_edid)
*out_edid = edid;
- if (!edid)
- return 1;
- return 0;
+ return (edid) ? 0 : 1;
}
MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 8594b1e42d71..d6f94742c9f2 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,6 +60,7 @@
#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
/* Chip tags. These are used to group the adapters into
* related families.
@@ -73,6 +74,8 @@ typedef enum {
S3_PROSAVAGE,
S3_SUPERSAVAGE,
S3_SAVAGE2000,
+ S3_PROSAVAGEDDR,
+ S3_TWISTER,
S3_LAST
} savage_chipset;
@@ -128,6 +131,10 @@ typedef enum {
#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
#define BCI_CMD_SEND_COLOR 0x00008000
+#define DISP_CRT 1
+#define DISP_LCD 2
+#define DISP_DFP 3
+
struct xtimings {
unsigned int Clock;
unsigned int HDisplay;
@@ -166,6 +173,10 @@ struct savagefb_par {
struct savagefb_i2c_chan chan;
unsigned char *edid;
u32 pseudo_palette[16];
+ int pm_state;
+ int display_type;
+ int dvi;
+ int crtonly;
int dacSpeedBpp;
int maxClock;
int minClock;
@@ -338,7 +349,7 @@ do { \
} \
}
-extern int savagefb_probe_i2c_connector(struct savagefb_par *par,
+extern int savagefb_probe_i2c_connector(struct fb_info *info,
u8 **out_edid);
extern void savagefb_create_i2c_busses(struct fb_info *info);
extern void savagefb_delete_i2c_busses(struct fb_info *info);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index f4633d1891f1..b5ca3ef8271f 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1400,6 +1400,58 @@ static int savagefb_pan_display (struct fb_var_screeninfo *var,
return 0;
}
+static int savagefb_blank(int blank, struct fb_info *info)
+{
+ struct savagefb_par *par = info->par;
+ u8 sr8 = 0, srd = 0;
+
+ if (par->display_type == DISP_CRT) {
+ vga_out8(0x3c4, 0x08);
+ sr8 = vga_in8(0x3c5);
+ sr8 |= 0x06;
+ vga_out8(0x3c5, sr8);
+ vga_out8(0x3c4, 0x0d);
+ srd = vga_in8(0x3c5);
+ srd &= 0x03;
+
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ srd |= 0x10;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ srd |= 0x40;
+ break;
+ case FB_BLANK_POWERDOWN:
+ srd |= 0x50;
+ break;
+ }
+
+ vga_out8(0x3c4, 0x0d);
+ vga_out8(0x3c5, srd);
+ }
+
+ if (par->display_type == DISP_LCD ||
+ par->display_type == DISP_DFP) {
+ switch(blank) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
+ break;
+ }
+ }
+
+ return (blank == FB_BLANK_NORMAL) ? 1 : 0;
+}
static struct fb_ops savagefb_ops = {
.owner = THIS_MODULE,
@@ -1407,6 +1459,7 @@ static struct fb_ops savagefb_ops = {
.fb_set_par = savagefb_set_par,
.fb_setcolreg = savagefb_setcolreg,
.fb_pan_display = savagefb_pan_display,
+ .fb_blank = savagefb_blank,
#if defined(CONFIG_FB_SAVAGE_ACCEL)
.fb_fillrect = savagefb_fillrect,
.fb_copyarea = savagefb_copyarea,
@@ -1583,8 +1636,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 };
static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-
- int videoRam, videoRambytes;
+ int videoRam, videoRambytes, dvi;
DBG("savage_init_hw");
@@ -1705,6 +1757,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
par->MCLK);
+ /* check for DVI/flat panel */
+ dvi = 0;
+
+ if (par->chip == S3_SAVAGE4) {
+ unsigned char sr30 = 0x00;
+
+ vga_out8(0x3c4, 0x30);
+ /* clear bit 1 */
+ vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
+ sr30 = vga_in8(0x3c5);
+ if (sr30 & 0x02 /*0x04 */) {
+ dvi = 1;
+ printk("savagefb: Digital Flat Panel Detected\n");
+ }
+ }
+
+ if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+ (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+ par->display_type = DISP_LCD;
+ else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
+ par->display_type = DISP_DFP;
+ else
+ par->display_type = DISP_CRT;
+
/* Check LCD panel parrmation */
if (par->chip == S3_SAVAGE_MX) {
@@ -1759,7 +1835,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
par->SavagePanelWidth = panelX;
par->SavagePanelHeight = panelY;
- }
+ } else
+ par->display_type = DISP_CRT;
}
savage_get_default_par (par);
@@ -1845,15 +1922,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
snprintf (info->fix.id, 16, "ProSavageKM");
break;
case FB_ACCEL_S3TWISTER_P:
- par->chip = S3_PROSAVAGE;
+ par->chip = S3_TWISTER;
snprintf (info->fix.id, 16, "TwisterP");
break;
case FB_ACCEL_S3TWISTER_K:
- par->chip = S3_PROSAVAGE;
+ par->chip = S3_TWISTER;
snprintf (info->fix.id, 16, "TwisterK");
break;
case FB_ACCEL_PROSAVAGE_DDR:
- par->chip = S3_PROSAVAGE;
+ par->chip = S3_PROSAVAGEDDR;
snprintf (info->fix.id, 16, "ProSavageDDR");
break;
case FB_ACCEL_PROSAVAGE_DDRK:
@@ -1899,12 +1976,11 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->pixmap.buf_align = 4;
info->pixmap.access_align = 32;
- fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+ err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+ if (!err)
info->flags |= FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
-
- err = 0;
}
#endif
return err;
@@ -1932,14 +2008,14 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
if (err)
goto failed_enable;
- if (pci_request_regions(dev, "savagefb")) {
+ if ((err = pci_request_regions(dev, "savagefb"))) {
printk(KERN_ERR "cannot request PCI regions\n");
goto failed_enable;
}
err = -ENOMEM;
- if (savage_init_fb_info(info, dev, id))
+ if ((err = savage_init_fb_info(info, dev, id)))
goto failed_init;
err = savage_map_mmio(info);
@@ -1947,6 +2023,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
goto failed_mmio;
video_len = savage_init_hw(par);
+ /* FIXME: cant be negative */
if (video_len < 0) {
err = video_len;
goto failed_mmio;
@@ -1959,7 +2036,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
INIT_LIST_HEAD(&info->modelist);
#if defined(CONFIG_FB_SAVAGE_I2C)
savagefb_create_i2c_busses(info);
- savagefb_probe_i2c_connector(par, &par->edid);
+ savagefb_probe_i2c_connector(info, &par->edid);
+ kfree(par->edid);
fb_edid_to_monspecs(par->edid, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
@@ -2110,15 +2188,31 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
struct savagefb_par *par = (struct savagefb_par *)info->par;
DBG("savagefb_suspend");
- printk(KERN_DEBUG "state: %u\n", state);
+
+
+ par->pm_state = state.event;
+
+ /*
+ * For PM_EVENT_FREEZE, do not power down so the console
+ * can remain active.
+ */
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ return 0;
+ }
acquire_console_sem();
- fb_set_suspend(info, pci_choose_state(dev, state));
- savage_disable_mmio(par);
- release_console_sem();
+ fb_set_suspend(info, 1);
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ savagefb_blank(FB_BLANK_POWERDOWN, info);
+ savage_disable_mmio(par);
+ pci_save_state(dev);
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
+ release_console_sem();
return 0;
}
@@ -2128,22 +2222,34 @@ static int savagefb_resume (struct pci_dev* dev)
struct fb_info *info =
(struct fb_info *)pci_get_drvdata(dev);
struct savagefb_par *par = (struct savagefb_par *)info->par;
+ int cur_state = par->pm_state;
DBG("savage_resume");
- pci_set_power_state(dev, 0);
- pci_restore_state(dev);
- if(pci_enable_device(dev))
- DBG("err");
+ par->pm_state = PM_EVENT_ON;
- SavagePrintRegs();
+ /*
+ * The adapter was not powered down coming back from a
+ * PM_EVENT_FREEZE.
+ */
+ if (cur_state == PM_EVENT_FREEZE) {
+ pci_set_power_state(dev, PCI_D0);
+ return 0;
+ }
acquire_console_sem();
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ if(pci_enable_device(dev))
+ DBG("err");
+
+ pci_set_master(dev);
savage_enable_mmio(par);
savage_init_hw(par);
savagefb_set_par (info);
-
+ savagefb_blank(FB_BLANK_UNBLANK, info);
fb_set_suspend (info, 0);
release_console_sem();
@@ -2277,3 +2383,6 @@ static int __init savagefb_init(void)
module_init(savagefb_init);
module_exit(savage_done);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/sis/300vtbl.h
index b6d5c71b2563..e4b4a2626da4 100644
--- a/drivers/video/sis/300vtbl.h
+++ b/drivers/video/sis/300vtbl.h
@@ -3,7 +3,7 @@
/*
* Register settings for SiS 300 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,31 +50,7 @@
*
*/
-static const SiS_StStruct SiS300_SModeIDTable[] =
-{
- {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
- {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
- {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00, 0},
- {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00, 0},
- {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00, 0},
- {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
- {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00, 0},
- {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00, 0},
- {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00, 0},
- {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00, 0},
- {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00, 0},
- {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00, 0},
- {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00, 0},
- {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00, 0},
- {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00, 0},
- {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00, 0},
- {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00, 0},
- {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
- {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00, 0},
- {0xff, 0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static const SiS_ExtStruct SiS300_EModeIDTable[] =
+static const struct SiS_Ext SiS300_EModeIDTable[] =
{
{0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x? */
{0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1},
@@ -110,7 +86,7 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0x59,0x921b,0x0138,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x8 */
{0x5c,0x921f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26,-1}, /* 512x384x32 */
{0x5d,0x021d,0x0139,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x16 */
- {0x5e,0x021f,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x32 */
+ {0x5e,0x021f,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x32 */
{0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1},
{0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x32 */
{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
@@ -119,8 +95,8 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
- {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x8 - not in BIOS! */
- {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x16 - not in BIOS! */
+ {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x8 */
+ {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x16 */
{0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d,-1}, /* 800x480x8 */
{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x8 */
{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x16 */
@@ -166,77 +142,77 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0xff,0x0000,0xffff,0, 0x00,0x00,0x00,0x00,0x00}
};
-static const SiS_Ext2Struct SiS300_RefIndex[] =
-{
- {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
- {0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
- {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
- {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0}, /* 03 */
- {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0}, /* 04 */
- {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0}, /* 05 */
- {0x0047,0x11,0x4e,0x00,0x05,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
- {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0}, /* 07 */
- {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
- {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
- {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
- {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
- {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 0c */
- {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0}, /* 0d */
- {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0}, /* 0e */
- {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0}, /* 0f */
- {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
- {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0}, /* 11 */
- {0x006f,0x32,0x03,0x06,0x14,0x32, 720, 576, 0}, /* 12 */
- {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0}, /* 13 */
- {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
- {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
- {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
- {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
- {0x0047,0x1a,0x52,0x00,0x06,0x37,1024, 768, 0}, /* 18 */
- {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
- {0x0387,0x1c,0x4d,0x00,0x07,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
- {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0}, /* 1b */
- {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0}, /* 1c */
- {0x0007,0x1f,0x98,0x00,0x07,0x3a,1280,1024, 0}, /* 1d */
- {0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
- {0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
- {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
- {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
- {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
- {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
- {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
- {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
- {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */ /* was c077 */
- {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
- {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
- {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
- {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
- {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
- {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */ /* VCLK 0x09 */
- {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0}, /* 2d */
- {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0}, /* 2e */
- {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0}, /* 2f */
- {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0}, /* 30 */
- {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0}, /* 31 */
- {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0}, /* 32 */
- {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0}, /* 33 */
- {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0}, /* 34 */
- {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0}, /* 35 */
- {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0}, /* 36 1152x864-60Hz */
- {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0}, /* 37 1152x864-75Hz */
- {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0}, /* 38 1152x864-85Hz */
- {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0}, /* 39 848x480-38Hzi */
- {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0}, /* 3a 848x480-60Hz */
- {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3b 856x480-38Hzi */
- {0xc047,0x42,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3c 856x480-60Hz */
- {0x0067,0x43,0x3e,0x0c,0x1b,0x48,1360, 768, 0}, /* 3d 1360x768-60Hz */
- {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0}, /* 3e 1280x768-60Hz */
- {0x006f,0x47,0x03,0x06,0x15,0x5f, 768, 576, 0}, /* 3f 768x576 */
- {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0}, /* 40 1360x1024-59Hz (BARCO1366 only) */
- {0xffff, 0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
+static const struct SiS_Ext2 SiS300_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 00 */
+ {0x0467,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 01 */
+ {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 02 - CRT1CRTC was 0x4f */
+ {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 03 */
+ {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 04 */
+ {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 05 */
+ {0x0047,0x11,0x0e,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 06 - CRT1CRTC was 0x51 */
+ {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 07 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 08 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 09 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0a */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0b */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0c */
+ {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0d */
+ {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0e */
+ {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0f */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0, 0x4a, 0x49}, /* 10 */
+ {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0, 0x00, 0x00}, /* 11 */
+ {0x006f,0x32,0x4a,0x06,0x14,0x32, 720, 576, 0, 0x00, 0x00}, /* 12 */ /* 4a was 03 */
+ {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 13 */
+ {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 14 */
+ {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 15 - CRT1CRTC was 0x97 */
+ {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 16 */
+ {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 17 - CRT1CRTC was 0x59 */
+ {0x0047,0x1a,0x12,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 18 */
+ {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 19 - CRT1CRTC was 0x5b */
+ {0x0387,0x1c,0x0d,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1a - CRT1CRTC was 0x5c */
+ {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1b */
+ {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1c */
+ {0x0007,0x1f,0x18,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1d */
+ {0x0007,0x20,0x19,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1e - CRT1CRTC was 0x60 */
+ {0x0007,0x21,0x1a,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1f */
+ {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 20 */
+ {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 21 - CRT1CRTC was 0x63 */
+ {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 22 */
+ {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0, 0x4b, 0x4b}, /* 23 */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0, 0x00, 0x00}, /* 24 */
+ {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0, 0x00, 0x00}, /* 25 */
+ {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0, 0x00, 0x00}, /* 26 */ /* was c077 */
+ {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0, 0x00, 0x00}, /* 27 */
+ {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0, 0x00, 0x00}, /* 28 */
+ {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 29 - 1280x960-60 */
+ {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 2a - 1280x960-85 */
+ {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0, 0x00, 0x00}, /* 2b */
+ {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0, 0x00, 0x00}, /* 2c */ /* VCLK 0x09 */
+ {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2d */
+ {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2e */
+ {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2f */
+ {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 30 */
+ {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 31 */
+ {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 32 */
+ {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 33 */
+ {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 34 */
+ {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 35 */
+ {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 36 1152x864-60Hz */
+ {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 37 1152x864-75Hz */
+ {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 38 1152x864-85Hz */
+ {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 39 848x480-38Hzi */
+ {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 3a 848x480-60Hz */
+ {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3b 856x480-38Hzi */
+ {0xc067,0x42,0x28,0x0c,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3c 856x480-60Hz */
+ {0x0067,0x43,0x3e,0x0d,0x1b,0x48,1360, 768, 0, 0x00, 0x00}, /* 3d 1360x768-60Hz */
+ {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0, 0x00, 0x00}, /* 3e 1280x768-60Hz */
+ {0x006f,0x47,0x4c,0x06,0x15,0x5f, 768, 576, 0, 0x00, 0x00}, /* 3f 768x576 */
+ {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0, 0x00, 0x00}, /* 40 1360x1024-59Hz (BARCO1366 only) */
+ {0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_VBMode SiS300_VBModeIDTable[] =
{
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -303,53 +279,26 @@ static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
-static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
+static const struct SiS_CRT1Table SiS300_CRT1Table[] =
{
-#if 1
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 - 320x200 */
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
0x00}},
-#endif
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f, /* 0x00 - corrected 320x200-72 - does not work */
- 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04,
- 0x00}},
-#endif
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* 0x01 */
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
0x00}},
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e, /* 0x01 - corrected 320x240-60 - does not work */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04,
- 0x00}},
-#endif
{{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 */
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
0x01}},
-#if 0
- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 - corrected 400x300-60 */
- 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
- 0x01}},
-#endif
{{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
0x01}},
{{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
0x00}},
-#if 0
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 0x05 */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
-#endif
{{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */
0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
0x00}},
-#if 0
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, /* 0x06 */
- 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
- 0x00}},
-#endif
{{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */
0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
0x00}},
@@ -359,19 +308,9 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
0x00}},
-#if 0
- {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e, /* 0x09 */
- 0xe4,0x87,0xdf,0xdf,0x04,0x00,0x00,0x01,
- 0x00}},
-#endif
{{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x09 - corrected 640x480-100 */
0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
0x00}},
-#if 0
- {{0x6c,0x4f,0x4f,0x83,0x59,0x9e,0x00,0x3e, /* 0x0a */
- 0xe5,0x8d,0xdf,0xdf,0x01,0x00,0x00,0x01,
- 0x00}},
-#endif
{{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x0a - corrected 640x480-120 */
0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
0x00}},
@@ -459,11 +398,6 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
0x00}},
-#if 0
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 0x27: 1280x960-70 - invalid! */
- 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}},
-#endif
{{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 0x27: 1280x960-60 - correct */
0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
0x01}},
@@ -497,9 +431,9 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
0x00}},
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 0x32 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}},
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, /* 0x32: 720x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}},
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* 0x33 - 1024x600 */
0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
0x01}},
@@ -560,18 +494,24 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, /* 1280x768-60 */
0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
0x01}}, /* 0x46 */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x47 */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x47 */
{{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52, /* 1360x1024 (Barco iQ Pro R300) */
0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
0x00}}, /* 0x48 */
{{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
- 0x41}} /* 0x49 */
+ 0x41}}, /* 0x49 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+ 0x40}}, /* 0x4a */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+ 0x00}} /* 0x4b */
};
-static const SiS_MCLKDataStruct SiS300_MCLKData_630[] =
+static const struct SiS_MCLKData SiS300_MCLKData_630[] =
{
{ 0x5a,0x64,0x80, 66},
{ 0xb3,0x45,0x80, 83},
@@ -583,7 +523,7 @@ static const SiS_MCLKDataStruct SiS300_MCLKData_630[] =
{ 0x37,0x61,0x80,100}
};
-static const SiS_MCLKDataStruct SiS300_MCLKData_300[] =
+static const struct SiS_MCLKData SiS300_MCLKData_300[] =
{
{ 0x68,0x43,0x80,125},
{ 0x68,0x43,0x80,125},
@@ -595,7 +535,7 @@ static const SiS_MCLKDataStruct SiS300_MCLKData_300[] =
{ 0x37,0x61,0x80,100}
};
-static SiS_VCLKDataStruct SiS300_VCLKData[] =
+static struct SiS_VCLKData SiS300_VCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -669,53 +609,26 @@ static SiS_VCLKDataStruct SiS300_VCLKData[] =
{ 0xe2,0x46,135}, /* 0x45 */ /* 1280x1024-75, better clock for VGA2 */
{ 0x70,0x29, 81}, /* 0x46 */ /* unused */
{ 0, 0, 0}, /* 0x47 custom (will be filled out) */
- { 0xce,0x25,189} /* 0x48 */ /* Replacement for index 0x1b for 730 (and 540?) */
+ { 0xce,0x25,189}, /* 0x48 */ /* Replacement for index 0x1b for 730 (and 540?) */
+ { 0x15,0xe1, 20}, /* 0x49 */ /* 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x4a */ /* 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x4b */ /* 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35} /* 0x4c */ /* 768@576@60 */
};
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR07 = 0x10;
-#endif
-
-static const DRAM4Type SiS300_SR15[8] =
+static const unsigned char SiS300_SR15[4 * 8] =
{
- {0x01,0x09,0xa3,0x00},
- {0x43,0x43,0x43,0x00},
- {0x1e,0x1e,0x1e,0x00},
- {0x2a,0x2a,0x2a,0x00},
- {0x06,0x06,0x06,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00}
+ 0x01,0x09,0xa3,0x00,
+ 0x43,0x43,0x43,0x00,
+ 0x1e,0x1e,0x1e,0x00,
+ 0x2a,0x2a,0x2a,0x00,
+ 0x06,0x06,0x06,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00
};
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR1F = 0x00;
-static UCHAR SiS300_SR21 = 0x16;
-static UCHAR SiS300_SR22 = 0xb2;
-static UCHAR SiS300_SR23 = 0xf6;
-static UCHAR SiS300_SR24 = 0x0d;
-static UCHAR SiS300_SR25[] = {0x0,0x0};
-static UCHAR SiS300_SR31 = 0x00;
-static UCHAR SiS300_SR32 = 0x11;
-static UCHAR SiS300_SR33 = 0x00;
-static UCHAR SiS300_CRT2Data_1_2 = 0x40;
-static UCHAR SiS300_CRT2Data_4_D = 0x00;
-static UCHAR SiS300_CRT2Data_4_E = 0x00;
-static UCHAR SiS300_CRT2Data_4_10 = 0x80;
-
-static const USHORT SiS300_RGBSenseData = 0xd1;
-static const USHORT SiS300_VideoSenseData = 0xb3;
-static const USHORT SiS300_YCSenseData = 0xb9;
-static const USHORT SiS300_RGBSenseData2 = 0x0190;
-static const USHORT SiS300_VideoSenseData2 = 0x0174;
-static const USHORT SiS300_YCSenseData2 = 0x016b;
-
-static const DRAM4Type SiS300_CR40[5];
-
-static UCHAR SiS300_CR49[2];
-#endif
-
-static const SiS_PanelDelayTblStruct SiS300_PanelDelayTbl[] =
+static const struct SiS_PanelDelayTbl SiS300_PanelDelayTbl[] =
{
{{0x05,0xaa}},
{{0x05,0x14}},
@@ -735,33 +648,11 @@ static const SiS_PanelDelayTblStruct SiS300_PanelDelayTbl[] =
{{0x05,0x60}}
};
-#if 0
-static const SiS_PanelDelayTblStruct SiS300_PanelDelayTblLVDS[] =
-{
- {{0x05,0xaa}},
- {{0x05,0x14}},
- {{0x05,0x36}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x90}},
- {{0x05,0x90}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}}, /* 2.07a (JVC): 14,96 */
- {{0x05,0x28}}, /* 2.04.5c: 20, 80 - Clevo (2.04.2c): 05, 28 */
- {{0x05,0x14}},
- {{0x05,0x14}}, /* Some BIOSes: 05, 40 */
- {{0x05,0x60}}
-};
-#endif
-
/**************************************************************/
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const SiS_LCDDataStruct SiS300_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1024x768Data[] =
{
{ 62, 25, 800, 546,1344, 806},
{ 32, 15, 930, 546,1344, 806},
@@ -772,7 +663,7 @@ static const SiS_LCDDataStruct SiS300_St2LCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS300_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1024x768Data[] =
{
{ 12, 5, 896, 512,1344, 806},
{ 12, 5, 896, 510,1344, 806},
@@ -789,7 +680,7 @@ static const SiS_LCDDataStruct SiS300_ExtLCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS300_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1280x1024Data[] =
{
{ 22, 5, 800, 510,1650,1088},
{ 22, 5, 800, 510,1650,1088},
@@ -801,7 +692,7 @@ static const SiS_LCDDataStruct SiS300_St2LCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_LCDDataStruct SiS300_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -813,53 +704,116 @@ static const SiS_LCDDataStruct SiS300_ExtLCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_1[] =
{ /* VESA Timing */
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
+ {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_2[] =
{ /* Non-VESA */
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+ {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_3[] =
{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
};
/**************************************************************/
/* LVDS/Chrontel -------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS300_CHTVUPALData[] =
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_1[]=
+{
+ { 832, 438,1331, 806},
+ { 832, 388,1331, 806},
+ { 832, 438,1331, 806},
+ { 832, 388,1331, 806},
+ { 832, 518,1331, 806},
+ {1050, 638,1344, 806},
+ {1344, 806,1344, 806},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066} /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066} /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ G series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1024Data_1[]=
+{
+ { 832, 438,1331, 806},
+ { 832, 409,1331, 806},
+ { 832, 438,1331, 806},
+ { 832, 409,1331, 806},
+ { 832, 518,1331, 806}, /* 640x480 */
+ {1050, 638,1344, 806}, /* 800x600 */
+ {1344, 806,1344, 806}, /* 1024x768 */
+};
+
+/* Custom data for 848x480 and 856x480 parallel LVDS panels */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_1[]=
+{
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 640x480 TODO */
+ {1088, 525,1088, 525}, /* 800x600 TODO */
+ {1088, 525,1088, 525}, /* 1024x768 TODO */
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 848x480 */
+ {1088, 525,1088, 525}, /* 856x480 */
+ {1088, 525,1088, 525} /* 1360x768 TODO */
+};
+
+/* Custom data for 848x480 parallel panel */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_2[]=
+{
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 640x480 */
+ {1088, 525,1088, 525}, /* 800x600 */
+ {1088, 525,1088, 525}, /* 1024x768 */
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 848x480 */
+ {1088, 525,1088, 525}, /* 856x480 */
+ {1088, 525,1088, 525} /* 1360x768 TODO */
+};
+
+static const struct SiS_LVDSData SiS300_CHTVUPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -869,7 +823,7 @@ static const SiS_LVDSDataStruct SiS300_CHTVUPALData[] =
{ 936, 836, 936, 836}
};
-static const SiS_LVDSDataStruct SiS300_CHTVOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -879,7 +833,7 @@ static const SiS_LVDSDataStruct SiS300_CHTVOPALData[] =
{ 960, 750, 960, 750}
};
-static const SiS_LVDSDataStruct SiS300_CHTVSOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVSOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -889,486 +843,8 @@ static const SiS_LVDSDataStruct SiS300_CHTVSOPALData[] =
{ 944, 625, 944, 625}
};
-
-static const SiS_LVDSDesStruct SiS300_PanelType00_1[] =
-{
- { 1059, 626 }, /* 2.08 */
- { 1059, 624 },
- { 1059, 626 },
- { 1059, 624 },
- { 1059, 624 },
- { 0, 627 },
- { 0, 627 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {0, 626},
- {0, 624},
- {0, 626},
- {0, 624},
- {0, 624},
- {0, 627},
- {0, 627},
- {0, 0},
- {0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType01_1[] =
-{
- { 0, 0 }, /* 2.08 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType02_1[] =
-{
- { 1059, 626 }, /* 2.08 */
- { 1059, 624 },
- { 1059, 626 },
- { 1059, 624 },
- { 1059, 624 },
- { 0, 627 },
- { 0, 627 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {0, 626},
- {0, 624},
- {0, 626},
- {0, 624},
- {0, 624},
- {0, 627},
- {0, 627},
- {0, 0},
- {0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType03_1[] =
-{
- { 8, 436},
- { 8, 440},
- { 8, 436},
- { 8, 440},
- { 8, 512},
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType04_1[] = /* 1280x1024 */
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType05_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType06_1[] = /* Clevo Trumpion 1024x768 */
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType07_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType08_1[] =
-{
- {1059, 626},
- {1059, 624},
- {1059, 626},
- {1059, 624},
- {1059, 624},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType09_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0a_1[] =
-{
- {1059, 626},
- {1059, 624},
- {1059, 626},
- {1059, 624},
- {1059, 624},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0b_1[] =
-{
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- { 0, 799},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0c_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0d_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0e_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0}, /* 640x480 */
- {1343, 0}, /* 800x600 */
- { 0, 805}, /* 1024x768 */
- { 0, 794}, /* 1280x1024 */
- { 0, 0} /* 1280x960 - not applicable */
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0f_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType00_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType01_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType02_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType03_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- {1152, 622},
- {1152, 597}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType04_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType05_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType06_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType07_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType08_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType09_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0a_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0b_2[] =
-{
- { 1152, 700},
- { 1152, 675},
- { 1152, 700},
- { 1152, 675},
- { 1152, 740},
- { 1232, 799},
- { 0, 799},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0c_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0d_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0e_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0f_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelTypeNS_1[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 805},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelTypeNS_2[] =
-{
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0}
-};
-
-/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */
+/* Custom des data for Barco iQ R200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */
{
{1330, 798}, /* 320x200 */
{1330, 794},
@@ -1381,7 +857,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x102
{ 0, 0} /* 1360x1024 */
};
-static const SiS_LVDSDesStruct SiS300_PanelType04_2a[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2a[] =
{
{1152, 622},
{1152, 597},
@@ -1394,8 +870,8 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_2a[] =
{ 0, 0}
};
-/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */
+/* Custom des data for Barco iQ G200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1b[] = /* 1024x768 */
{
{1330, 798}, /* 320x200 */
{1330, 794},
@@ -1406,7 +882,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */
{ 0, 805} /* 1024x768 / 512x384 */
};
-static const SiS_LVDSDesStruct SiS300_PanelType04_2b[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2b[] =
{
{1152, 622},
{1152, 597},
@@ -1419,376 +895,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_2b[] =
/* CRT1 CRTC for slave modes */
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[] =
-{
- {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] =
-{
- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04,
- 0x00 }},
- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xE2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-
-#if 0
- {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00 }},
- {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x41,0x31,0x85,0x35,0x1d,0x7c,0xf0,
- 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
- 0x02,0x88,0xFf,0x25,0x10,0x00,0x01,
- 0x01 }}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] =
-{
- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00 }},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x04,
- 0x00 }},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[] =
-{
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
- 0x1c,0x80,0xdf,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] =
-{
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba,
- 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05,
- 0x00 }},
- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x31,0x93,0x3e,0x86,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
- 0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UNTSC[] =
{
{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1810,7 +917,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1ONTSC[] =
{
{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1832,7 +939,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1854,7 +961,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1OPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1876,7 +983,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1SOPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1898,7 +1005,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] =
0x01 }}
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UNTSC[] =
{
{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1908,7 +1015,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 24: 800x600 NTSC 7/10 */
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_ONTSC[] =
{
{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1918,7 +1025,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 23: 800x600 NTSC 3/4 */
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1929,7 +1036,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_OPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1940,26 +1047,26 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_SOPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
- {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */
- {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* TW: Mode 19: 800x600 PAL 1/1 */
+ {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 13: 640x480 PAL 5/4 */
+ {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 19: 800x600 PAL 1/1 */
};
-static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e};
+static const unsigned char SiS300_CHTVVCLKUNTSC[] = { 0x29,0x29,0x29,0x29,0x2a,0x2e };
-static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-static const UCHAR SiS300_CHTVVCLKSONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKSONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-static const UCHAR SiS300_CHTVVCLKUPAL[] = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31};
+static const unsigned char SiS300_CHTVVCLKUPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x2f,0x31 };
-static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32};
+static const unsigned char SiS300_CHTVVCLKOPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x30,0x32 };
-static const UCHAR SiS300_CHTVVCLKSOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x36,0x29};
+static const unsigned char SiS300_CHTVVCLKSOPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x36,0x29 };
diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/sis/310vtbl.h
index 2c71d048f7c4..54fcbbf4ef63 100644
--- a/drivers/video/sis/310vtbl.h
+++ b/drivers/video/sis/310vtbl.h
@@ -1,9 +1,9 @@
/* $XFree86$ */
/* $XdotOrg$ */
/*
- * Register settings for SiS 315/330 series
+ * Register settings for SiS 315/330/340 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,37 +50,13 @@
*
*/
-static const SiS_StStruct SiS310_SModeIDTable[]=
-{
- {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
- {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
- {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01, 0x40},
- {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02, 0x40},
- {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02, 0x40},
- {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03, 0x40},
- {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05, 0x40},
- {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03, 0x40},
- {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03, 0x40},
- {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05, 0x40},
- {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05, 0x40},
- {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05, 0x40},
- {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05, 0x40},
- {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
-};
-
-static const SiS_ExtStruct SiS310_EModeIDTable[]=
+static const struct SiS_Ext SiS310_EModeIDTable[] =
{
{0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
{0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
- {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+ {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
{0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
- {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+ {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
{0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
{0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
{0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
@@ -103,10 +79,10 @@ static const SiS_ExtStruct SiS310_EModeIDTable[]=
{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
{0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8 */
{0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8 */
- {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8 */
+ {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8 */
{0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
{0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
- {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+ {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
{0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8 */
{0x5a,0x021b,0x0138,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8 fstn */
{0x5b,0x0a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
@@ -139,406 +115,335 @@ static const SiS_ExtStruct SiS310_EModeIDTable[]=
{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
- {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
- {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
- {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
- {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
- {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
- {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
- {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1}, /* 848x480 */
- {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1},
- {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1},
- {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1}, /* 856x480 */
- {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1},
- {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1},
- {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 1360x768 */
- {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
- {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x8 */
+ {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x16 */
+ {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x32*/
+ {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1}, /* 1152x864 */
+ {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+ {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+ {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1}, /* 848x480 */
+ {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1},
+ {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1},
+ {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 856x480 */
+ {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1}, /* 1360x768 */
+ {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
+ {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
{0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
{0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
{0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
- {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1}, /* 768x576 */
- {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1},
- {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1},
- {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, /* 1280x800 */
- {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
- {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
- {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, /* 1680x1050 */
- {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
- {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
- {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, /* 1920x1080(i) */
- {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
- {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
- {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1}, /* 960x540 */
- {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1},
- {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1},
- {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1}, /* 960x600 */
- {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1},
- {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1},
+ {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1}, /* 768x576 */
+ {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1},
+ {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1},
+ {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7}, /* 1280x800 */
+ {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+ {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+ {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9}, /* 1680x1050 */
+ {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+ {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+ {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1}, /* 1920x1080(i) */
+ {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+ {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+ {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1}, /* 960x540 */
+ {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1},
+ {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1},
+ {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1}, /* 960x600 */
+ {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1},
+ {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1},
+ {0x1a,0x0e3b,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8}, /* 1280x854 */
+ {0x1b,0x0e7d,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
+ {0x1c,0x0eff,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
{0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
};
-static const SiS_Ext2Struct SiS310_RefIndex[]=
-{
- {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
- {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
- {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
- {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
- {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
- {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
- {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
- {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
- {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
- {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
- {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
- {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
- {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
- {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
- {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
- {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
- {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
- {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
- {0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
- {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
- {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
- {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
- {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
- {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
- {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
- {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
- {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
- {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
- {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
- {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
- {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
- {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
- {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
- {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
- {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
- {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
- {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
- {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
- {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
- {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
- {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
- {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
- {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
- {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
- {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
- {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
- {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
- {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
- {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
- {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
- {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
- {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
- {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
- {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
- {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
- {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
- {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
- {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
- {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
- {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
- {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
- {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
- {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
- {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */ /* FSTN 320x240 */
- {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */ /* 0x5b was 0x12 */
- {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
- {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
- {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-60Hz */
- {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-75Hz */
- {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x45 1152x864-85Hz */
- {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-38Hzi */
- {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x47 848x480-60Hz */
- {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-38Hzi */
- {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x49 856x480-60Hz */
- {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x4a 1360x768-60Hz */
- {0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4b 768x576-56Hz */
- {0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4c 1280x800-60Hz */
- {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4d 1680x1050-60Hz */
- {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30}, /* 0x4e 1920x1080 60Hzi */
- {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30}, /* 0x4f 960x540 60Hz */
- {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30}, /* 0x50 960x600 60Hz */
- {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0}
-};
-
-#ifdef LINUX_XF86
-static const struct {
- UCHAR Ext_ModeID; /* ModeID in new ROM */
- UCHAR Ext_MyModeID; /* corresponding ModeID in my tables (0 = identical) */
- USHORT Ext_VESAID; /* corresponding VESA ID in new ROM */
-} SiS_EModeIDTable661[] = {
- { 0x6a, 0x00, 0x0102 },
- { 0x1d, 0x20, 0x0000 },
- { 0x1e, 0x21, 0x0000 },
- { 0x1f, 0x22, 0x0000 },
- { 0x20, 0x29, 0x0000 },
- { 0x21, 0x2a, 0x0000 },
- { 0x22, 0x2b, 0x0000 },
- { 0x23, 0x00, 0x011c },
- { 0x24, 0x00, 0x011d },
- { 0x25, 0x00, 0x011e },
- { 0x26, 0x00, 0x011f },
- { 0x27, 0x00, 0x0120 },
- { 0x28, 0x00, 0x0121 },
- { 0x2a, 0x14, 0x013d },
- { 0x2b, 0x15, 0x013e },
- { 0x2c, 0x16, 0x013f },
- { 0x2e, 0x00, 0x0101 },
- { 0x2f, 0x00, 0x0100 },
- { 0x30, 0x00, 0x0103 },
- { 0x37, 0x00, 0x0104 },
- { 0x38, 0x00, 0x0105 },
- { 0x3a, 0x00, 0x0107 },
- { 0x3c, 0x00, 0x0125 },
- { 0x3d, 0x00, 0x0126 },
- { 0x40, 0x00, 0x010d },
- { 0x41, 0x00, 0x010e },
- { 0x43, 0x00, 0x0110 },
- { 0x44, 0x00, 0x0111 },
- { 0x46, 0x00, 0x0113 },
- { 0x47, 0x00, 0x0114 },
- { 0x49, 0x00, 0x0116 },
- { 0x4a, 0x00, 0x0117 },
- { 0x4c, 0x00, 0x0119 },
- { 0x4d, 0x00, 0x011a },
- { 0x50, 0x00, 0x0127 },
- { 0x51, 0x00, 0x0128 },
- { 0x52, 0x00, 0x0129 },
- { 0x56, 0x00, 0x012a },
- { 0x57, 0x00, 0x012b },
- { 0x58, 0x00, 0x012c },
- { 0x59, 0x00, 0x012d },
- { 0x5a, 0x17, 0x012e },
- { 0x5b, 0x18, 0x012f },
- { 0x5c, 0x19, 0x0130 },
- { 0x5d, 0x00, 0x0131 },
- { 0x62, 0x00, 0x0112 },
- { 0x63, 0x00, 0x0115 },
- { 0x64, 0x00, 0x0118 },
- { 0x65, 0x00, 0x011b },
- { 0x66, 0x00, 0x0132 },
- { 0x75, 0x00, 0x013a },
- { 0x78, 0x00, 0x013b },
- { 0x79, 0x00, 0x013c },
- { 0x7b, 0x7c, 0x0136 },
- { 0x7c, 0x7d, 0x0137 },
- { 0x7d, 0x7e, 0x0138 },
- { 0xff, 0xff, 0xffff }
-};
-#endif
-
-static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
+static const struct SiS_Ext2 SiS310_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x0 */
+ {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1 */
+ {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2 */
+ {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3 */
+ {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4 */
+ {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x5 */
+ {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x6 */
+ {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x7 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x8 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x9 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xa */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xb */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xc */
+ {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xd */
+ {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xe */
+ {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xf */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e, 0x00, 0x00, 0x00, 0x00}, /* 0x10 */
+ {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x11 */
+ {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x12 (6f was 03) */
+ {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x13 */
+ {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x14 */
+ {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x15 */
+ {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x16 */
+ {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x17 */
+ {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x18 */
+ {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x19 */
+ {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1a */
+ {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1b */
+ {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1c */
+ {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1d */
+ {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1e */
+ {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1f */
+ {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x20 */
+ {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x21 */
+ {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x22 */
+ {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x23 */
+ {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x24 */
+ {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x00}, /* 0x25 */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x26 */
+ {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x27 */
+ {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x28 */
+ {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x29 */
+ {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2a */
+ {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2b */
+ {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2c */
+ {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2d */
+ {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2e */
+ {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2f */
+ {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x30 */
+ {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x31 */
+ {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x32 */
+ {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x33 */
+ {0x2077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x32, 0x40, 0x5e, 0x73}, /* 0x34 */
+ {0x2047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x33, 0x07, 0xff, 0xff}, /* 0x35 */
+ {0x2047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x34, 0x0a, 0xff, 0xff}, /* 0x36 */
+ {0x2077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x35, 0x0b, 0x5f, 0x74}, /* 0x37 */
+ {0x2047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x36, 0x11, 0xff, 0xff}, /* 0x38 */
+ {0x2047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x37, 0x16, 0xff, 0xff}, /* 0x39 */
+ {0x3137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x38, 0x19, 0x60, 0x75}, /* 0x3a */
+ {0x3107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x39, 0x1e, 0xff, 0xff}, /* 0x3b */
+ {0x3307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x3a, 0x20, 0xff, 0xff}, /* 0x3c */
+ {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3d */
+ {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3e */
+ {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3f */ /* FSTN 320x240 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x58, 0x19, 0x42, 0x5b}, /* 0x40 */ /* 0x5b was 0x12 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x59, 0x1e, 0xff, 0xff}, /* 0x41 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x5a, 0x20, 0xff, 0xff}, /* 0x42 */
+ {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x43 */
+ {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x44 1400x1050-75Hz */
+ {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x45 1152x864-60Hz */
+ {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x46 1152x864-75Hz */
+ {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x47 1152x864-85Hz */
+ {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x48 848x480-38Hzi */
+ {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x49 848x480-60Hz */
+ {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4a 856x480-38Hzi */
+ {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4b 856x480-60Hz */
+ {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4c 1360x768-60Hz */
+ {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4d 768x576-56Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5b, 0x19, 0x4f, 0x5c}, /* 0x4e 1280x800-60Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5c, 0x1e, 0xff, 0xff}, /* 0x4f 1280x800-75Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5d, 0x20, 0xff, 0xff}, /* 0x50 1280x800-85Hz */
+ {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x51 1680x1050-60Hz */
+ {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x52 1920x1080 60Hzi */
+ {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x53 960x540 60Hz */
+ {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x54 960x600 60Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x62, 0x19, 0x61, 0x76}, /* 0x55 1280x854-60Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x63, 0x1e, 0xff, 0xff}, /* 0x56 1280x854-75Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x64, 0x20, 0xff, 0xff}, /* 0x57 1280x854-85Hz */
+ {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiS310_CRT1Table[] =
{
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
- 0x00}}, /* 0x0 */
+ 0x00}}, /* 0x0 */
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
- 0x00}}, /* 0x1 */
+ 0x00}}, /* 0x1 */
{{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
- 0x01}}, /* 0x2 */
+ 0x01}}, /* 0x2 */
{{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
- 0x01}}, /* 0x3 */
+ 0x01}}, /* 0x3 */
{{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
- 0x00}}, /* 0x4 */
-#if 0
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}}, /* 0x5 */
-#endif
- {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */
+ 0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* corrected 640x480-60 */
0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
- 0x00}},
-#if 0
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e,
- 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
- 0x00}}, /* 0x6 */
-#endif
- {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */
+ 0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* corrected 640x480-72 */
0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
- 0x00}},
+ 0x00}}, /* 0x6 */
{{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
- 0x00}}, /* 0x7 */
+ 0x00}}, /* 0x7 */
{{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
- 0x00}}, /* 0x8 */
+ 0x00}}, /* 0x8 */
{{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, /* Corrected VBE */
- 0x61}}, /* 0x9 */
+ 0x61}}, /* 0x9 */
{{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
- 0x61}}, /* 0xa */
+ 0x61}}, /* 0xa */
{{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, /* Corrected VBE */
- 0x61}}, /* 0xb */
+ 0x61}}, /* 0xb */
{{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* Corrected VDE, VBE */
- 0x00}}, /* 0xc */
+ 0x00}}, /* 0xc */
{{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0xd */
+ 0x01}}, /* 0xd */
{{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
- 0x01}}, /* 0xe */
+ 0x01}}, /* 0xe */
{{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
- 0x01}}, /* 0xf */
+ 0x01}}, /* 0xf */
{{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
- 0x01}}, /* 0x10 */
+ 0x01}}, /* 0x10 */
{{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
- 0x01}}, /* 0x11 */
+ 0x01}}, /* 0x11 */
{{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
- 0x61}}, /* 0x12 */
+ 0x61}}, /* 0x12 */
{{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
- 0x61}}, /* 0x13 */
+ 0x61}}, /* 0x13 */
{{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
- 0x61}}, /* 0x14 */
+ 0x61}}, /* 0x14 */
{{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
- 0x00}}, /* 0x15 */
+ 0x00}}, /* 0x15 */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
- 0x01}}, /* 0x16 */
+ 0x01}}, /* 0x16 */
{{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
- 0x01}}, /* 0x17 */
+ 0x01}}, /* 0x17 */
{{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
- 0x01}}, /* 0x18 */
+ 0x01}}, /* 0x18 */
{{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
- 0x01}}, /* 0x19 */
+ 0x01}}, /* 0x19 */
{{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
- 0x62}}, /* 0x1a */
+ 0x62}}, /* 0x1a */
{{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
- 0x62}}, /* 0x1b */
+ 0x62}}, /* 0x1b */
{{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
- 0x00}}, /* 0x1c */
+ 0x00}}, /* 0x1c */
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
- 0x01}}, /* 0x1d */
+ 0x01}}, /* 0x1d */
{{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
- 0x01}}, /* 0x1e */
+ 0x01}}, /* 0x1e */
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
- 0x01}}, /* 0x1f */
+ 0x01}}, /* 0x1f */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x20 */
+ 0x00}}, /* 0x20 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x21 @ 4084 */
+ 0x00}}, /* 0x21 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x22 */
+ 0x00}}, /* 0x22 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x23 */
+ 0x00}}, /* 0x23 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x24 */
+ 0x00}}, /* 0x24 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x25 */
+ 0x00}}, /* 0x25 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x26 */
+ 0x00}}, /* 0x26 */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x27 */
+ 0x00}}, /* 0x27 */
{{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
- 0x63}}, /* 0x28 */
+ 0x63}}, /* 0x28 */
{{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
- 0x63}}, /* 0x29 */
+ 0x63}}, /* 0x29 */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2a */
+ 0x00}}, /* 0x2a */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2b */
+ 0x00}}, /* 0x2b */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2c */
+ 0x00}}, /* 0x2c */
{{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
- 0x44}}, /* 0x2d */
+ 0x44}}, /* 0x2d */
{{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
- 0x44}}, /* 0x2e */
+ 0x44}}, /* 0x2e */
{{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
- 0x44}}, /* 0x2f */
+ 0x44}}, /* 0x2f */
{{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
- 0x44}}, /* 0x30 */
+ 0x44}}, /* 0x30 */
{{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
- 0x00}}, /* 0x31 */
+ 0x00}}, /* 0x31 */
{{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
- 0x01}}, /* 0x32 */
+ 0x01}}, /* 0x32 */
{{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
- 0x01}}, /* 0x33 */
+ 0x01}}, /* 0x33 */
{{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
- 0x01}}, /* 0x34 */
+ 0x01}}, /* 0x34 */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
- 0x01}}, /* 0x35 */
+ 0x01}}, /* 0x35 */
{{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
- 0x01}}, /* 0x36 */
+ 0x01}}, /* 0x36 */
{{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */
0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
- 0x01}}, /* 0x37 */
+ 0x01}}, /* 0x37 */
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
- 0x01}}, /* 0x38 */
+ 0x01}}, /* 0x38 */
{{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
- 0x01}}, /* 0x39 */
+ 0x01}}, /* 0x39 */
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
- 0x01}}, /* 0x3a */
-#if 0
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 1280x960 - invalid */
- 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}}, /* 0x3b */
-#endif
+ 0x01}}, /* 0x3a */
{{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 1280x960-60 - corrected */
0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}}, /* 0x3b */
+ 0x01}}, /* 0x3b */
{{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}}, /* 0x3c */
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x3d */
+ 0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, /* 720x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x3d */
{{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
- 0x00}}, /* 0x3e */
+ 0x00}}, /* 0x3e */
{{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
- 0x00}}, /* 0x3f */
+ 0x00}}, /* 0x3f */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
0x01}}, /* 0x40 */
@@ -578,11 +483,11 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
0x01}}, /* 0x4c */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x4d */
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x4d */
+ {{0x5f,0x27,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* FSTN 320x240 (working) */
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
0x00}}, /* 0x4e */
{{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
@@ -601,10 +506,58 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
0x01}}, /* 0x53 */
{{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
- 0x41}} /* 0x54 */
-};
-
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
+ 0x41}}, /* 0x54 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+ 0x40}}, /* 0x55 */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+ 0x00}}, /* 0x56 */
+ {{0xd7,0xc7,0xc7,0x9b,0xd1,0x15,0xd1,0x10, /* 1600x1200 for LCDA */
+ 0xb2,0x86,0xaf,0xb0,0xd2,0x2f,0x00,0x03,
+ 0x00}}, /* 0x57 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 60 Hz */
+ 0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x58 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 75 Hz */
+ 0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x59 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xdc, /* 1280x768 (1280x1024) 85 Hz */
+ 0x95,0x89,0xff,0x94,0x2f,0x21,0x00,0x07,
+ 0x01}}, /* 0x5a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x800 (1280x1024) 60 Hz */
+ 0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+ 0x01}}, /* 0x5b */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x800 (1280x1024) 75 Hz */
+ 0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+ 0x01}}, /* 0x5c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x800 (1280x1024) 85 Hz */
+ 0xa5,0x89,0x1f,0xa4,0x2f,0x01,0x00,0x07,
+ 0x01}}, /* 0x5d */
+ {{0x7f,0x63,0x63,0x83,0x6d,0x1d,0x0b,0x3e, /* 800x480 (wide) 60 Hz */
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x06,
+ 0x00}}, /* 0x5e */
+ {{0xa0,0x7f,0x7f,0x84,0x85,0x97,0x52,0xf0, /* 1024x576 (wide) 60 Hz */
+ 0x41,0x85,0x3f,0x40,0x53,0x00,0x00,0x02,
+ 0x01}}, /* 0x5f */
+ {{0xc9,0x9f,0x9f,0x8d,0xb0,0x15,0xec,0xf0, /* 1280x720 (wide) 60 Hz */
+ 0xd4,0x89,0xcf,0xd3,0xed,0x20,0x00,0x07,
+ 0x01}}, /* 0x60 */
+ {{0xcb,0x9f,0x9f,0x8f,0xa5,0x13,0x5b,0xff, /* 1280x854-60 wide */
+ 0x56,0x89,0x55,0x55,0x5c,0x30,0x00,0x07,
+ 0x01}}, /* 0x61 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x854 (1280x1024) 60 Hz */
+ 0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+ 0x41}}, /* 0x62 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x854 (1280x1024) 75 Hz */
+ 0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+ 0x41}}, /* 0x63 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x854 (1280x1024) 85 Hz */
+ 0xc0,0x84,0x55,0xbf,0x2f,0x01,0x00,0x07,
+ 0x41}} /* 0x64 */
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_315[] =
{
{ 0x3b,0x22,0x01,143},
{ 0x5c,0x23,0x01,166},
@@ -616,7 +569,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
{ 0x5c,0x23,0x01,166}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_650[] =
{
{ 0x5a,0x64,0x82, 66},
{ 0xb3,0x45,0x82, 83},
@@ -628,7 +581,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
{ 0x37,0x22,0x82,133}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_330[] =
{
{ 0x5c,0x23,0x01,166},
{ 0x5c,0x23,0x01,166},
@@ -640,7 +593,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
{ 0x79,0x06,0x01,250}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_660[] =
{
{ 0x5c,0x23,0x82,166},
{ 0x5c,0x23,0x82,166},
@@ -652,7 +605,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_760[] =
{
{ 0x37,0x22,0x82,133},
{ 0x5c,0x23,0x82,166},
@@ -664,7 +617,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_761[] =
{
{ 0x37,0x22,0x82,133}, /* Preliminary */
{ 0x5c,0x23,0x82,166},
@@ -676,7 +629,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_340[] =
{
{ 0x79,0x06,0x01,250},
{ 0x7c,0x08,0x01,200},
@@ -688,9 +641,9 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
{ 0x29,0x01,0x81,300}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
+static const struct SiS_MCLKData SiS310_MCLKData_1[] = /* ECLK */
{
- { 0x29,0x21,0x82,150},
+ { 0x29,0x21,0x82,150},
{ 0x5c,0x23,0x82,166},
{ 0x65,0x23,0x82,183},
{ 0x37,0x21,0x82,200},
@@ -700,7 +653,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
{ 0x37,0x22,0x82,133}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_1_340[] =
{
{ 0x7c,0x08,0x01,200},
{ 0x7c,0x08,0x01,200},
@@ -712,7 +665,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
{ 0x29,0x01,0x81,300}
};
-static SiS_VCLKDataStruct SiS310_VCLKData[]=
+static struct SiS_VCLKData SiS310_VCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -805,7 +758,7 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
- { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
{ 0x45,0x25, 83}, /* 0x5c 1280x800 */
{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
@@ -823,10 +776,19 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
{ 0x45,0x25, 83}, /* 0x6c 1280x800 */
- { 0x70,0x28, 90} /* 0x6d 1152x864@60 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35}, /* 0x71 768x576@60 */
+ { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+ { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+ { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+ { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+ { 0x75,0x13, 84} /* 0x76 1280x854 60Hz (wide) */
};
-static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static struct SiS_VBVCLKData SiS310_VBVCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -858,12 +820,6 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x5e,0x43,113}, /* 0x1b */
{ 0xbc,0x44,116}, /* 0x1c */
{ 0xe0,0x46,132}, /* 0x1d */
-#if 0
- { 0xd4,0x28,135}, /* 0x1e */
- { 0xea,0x2a,139}, /* 0x1f */
- { 0x41,0x22,157}, /* 0x20 */
- { 0x70,0x24,162}, /* 0x21 */
-#endif
{ 0xe2,0x46,135}, /* 0x1e */ /* 1280x1024-75, better clock for VGA2 */
{ 0xe5,0x46,139}, /* 0x1f */ /* 1024x768-120, better clock for VGA2 */
{ 0x15,0x01,157}, /* 0x20 */ /* 1280x1024-85, better clock for VGA2 */
@@ -912,7 +868,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x34,0x61, 95}, /* 0x4b UNUSED */
{ 0x78,0x27,108}, /* 0x4c UNUSED */
{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
- { 0x41,0x4e, 21}, /* 0x4e UNUSED */
+ { 0x41,0x4e, 21}, /* 0x4e */
{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
{ 0x19,0x42, 42}, /* 0x50 UNUSED */
{ 0x54,0x46, 58}, /* 0x51 UNUSED */
@@ -925,7 +881,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
- { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
{ 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */
{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
@@ -943,57 +899,33 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
{ 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */
- { 0x70,0x28, 90} /* 0x6d 1152x864@60 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35}, /* 0x71 768@576@60 */
+ { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+ { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+ { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+ { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+ { 0x75,0x13, 84} /* 0x76 1280x854 60Hz (SiS LVDS) LCD */
};
-static const DRAM4Type SiS310_SR15[8] = {
- {0x00,0x04,0x60,0x60},
- {0x0f,0x0f,0x0f,0x0f},
- {0xba,0xba,0xba,0xba},
- {0xa9,0xa9,0xac,0xac},
- {0xa0,0xa0,0xa0,0xa8},
- {0x00,0x00,0x02,0x02},
- {0x30,0x30,0x40,0x40},
- {0x00,0xa5,0xfb,0xf6}
-};
-
-#ifdef LINUX_KERNEL
-
-static UCHAR SiS310_SR07 = 0x18;
-
-static const DRAM4Type SiS310_CR40[5] = {
- {0x77,0x77,0x33,0x33},
- {0x77,0x77,0x33,0x33},
- {0x00,0x00,0x00,0x00},
- {0x5b,0x5b,0x03,0x03},
- {0x00,0x00,0xf0,0xf8}
+static const unsigned char SiS310_SR15[4 * 8] =
+{
+ 0x00,0x04,0x60,0x60,
+ 0x0f,0x0f,0x0f,0x0f,
+ 0xba,0xba,0xba,0xba,
+ 0xa9,0xa9,0xac,0xac,
+ 0xa0,0xa0,0xa0,0xa8,
+ 0x00,0x00,0x02,0x02,
+ 0x30,0x30,0x40,0x40,
+ 0x00,0xa5,0xfb,0xf6
};
-static UCHAR SiS310_CR49[] = {0xaa,0x88};
-static UCHAR SiS310_SR1F = 0x00;
-static UCHAR SiS310_SR21 = 0xa5;
-static UCHAR SiS310_SR22 = 0xfb;
-static UCHAR SiS310_SR23 = 0xf6;
-static UCHAR SiS310_SR24 = 0x0d;
-static UCHAR SiS310_SR25[] = {0x33,0x3};
-static UCHAR SiS310_SR31 = 0x00;
-static UCHAR SiS310_SR32 = 0x11;
-static UCHAR SiS310_SR33 = 0x00;
-static UCHAR SiS310_CRT2Data_1_2 = 0x00;
-static UCHAR SiS310_CRT2Data_4_D = 0x00;
-static UCHAR SiS310_CRT2Data_4_E = 0x00;
-static UCHAR SiS310_CRT2Data_4_10 = 0x80;
-static const USHORT SiS310_RGBSenseData = 0xd1;
-static const USHORT SiS310_VideoSenseData = 0xb9;
-static const USHORT SiS310_YCSenseData = 0xb3;
-static const USHORT SiS310_RGBSenseData2 = 0x0190;
-static const USHORT SiS310_VideoSenseData2 = 0x0174;
-static const USHORT SiS310_YCSenseData2 = 0x016b;
-#endif
-
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTbl[] =
{
- {{0x10,0x40}},
+ {{0x10,0x40}},
{{0x10,0x40}},
{{0x10,0x40}},
{{0x10,0x40}},
@@ -1011,7 +943,7 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
{{0x10,0x40}}
};
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTblLVDS[] =
{
{{0x28,0xc8}},
{{0x28,0xc8}},
@@ -1035,18 +967,18 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const SiS_LCDDataStruct SiS310_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1024x768Data[] =
{
{ 62, 25, 800, 546,1344, 806},
{ 32, 15, 930, 546,1344, 806},
- { 62, 25, 800, 546,1344, 806},
+ { 62, 25, 800, 546,1344, 806},
{ 104, 45, 945, 496,1344, 806},
{ 62, 25, 800, 546,1344, 806},
{ 31, 18,1008, 624,1344, 806},
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1024x768Data[] =
{
{ 42, 25,1536, 419,1344, 806},
{ 48, 25,1536, 369,1344, 806},
@@ -1057,7 +989,7 @@ static const SiS_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS310_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1280x1024Data[] =
{
{ 22, 5, 800, 510,1650,1088},
{ 22, 5, 800, 510,1650,1088},
@@ -1069,7 +1001,7 @@ static const SiS_LCDDataStruct SiS310_St2LCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -1081,45 +1013,22 @@ static const SiS_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_1024x768_1[] =
{
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
};
-/* *** LCDA *** */
-
-#if 0
-static const SiS_LVDSDataStruct SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo, 651+301C */
- {1200, 450, 2048,1250},
- {1200, 400, 2048,1250},
- {1280, 450, 2048,1250},
- {1280, 400, 2048,1250},
- {1200, 530, 2048,1250},
- {1360, 650, 2048,1250},
- {1584, 818, 2048,1250},
- {1688,1066, 2048,1250},
- {1688,1066, 2048,1250},
-#if 0
- {2048,1250, 2048,1250} /* this should be correct */
-#endif
-#if 1
- {2160,1250, 2048,1250} /* ? */
-#endif
-};
-#endif
-
/**************************************************************/
/* LVDS, CHRONTEL ------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS310_CHTVUPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1130,7 +1039,7 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALData[]=
{1400,1000,1400,1000}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1138,10 +1047,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALData[]=
{1008, 625,1008, 625},
{ 840, 625, 840, 625},
{ 944, 625, 944, 625},
- {1400, 875,1400, 875}
+ {1400, 875,1400, 875}
};
-static const SiS_LVDSDataStruct SiS310_CHTVUPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALMData[] =
{
{ 840, 600, 840, 600},
{ 840, 600, 840, 600},
@@ -1149,10 +1058,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALMData[]=
{ 840, 600, 840, 600},
{ 784, 600, 784, 600},
{1064, 750,1064, 750},
- {1160, 945,1160, 945}
+ {1160, 945,1160, 945}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALMData[] =
{
{ 840, 525, 840, 525},
{ 840, 525, 840, 525},
@@ -1160,10 +1069,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALMData[]=
{ 840, 525, 840, 525},
{ 784, 525, 784, 525},
{1040, 700,1040, 700},
- {1160, 840,1160, 840}
+ {1160, 840,1160, 840}
};
-static const SiS_LVDSDataStruct SiS310_CHTVUPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALNData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1174,7 +1083,7 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALNData[]=
{1400,1000,1400,1000}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALNData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1182,10 +1091,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALNData[]=
{1008, 625,1008, 625},
{ 840, 625, 840, 625},
{ 944, 625, 944, 625},
- {1400, 875,1400, 875}
+ {1400, 875,1400, 875}
};
-static const SiS_LVDSDataStruct SiS310_CHTVSOPALData[]= /* (super overscan - no effect on 7019) */
+static const struct SiS_LVDSData SiS310_CHTVSOPALData[] = /* (super overscan - no effect on 7019) */
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1196,1333 +1105,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVSOPALData[]= /* (super overscan -
{1400, 875,1400, 875}
};
-
-static const SiS_LVDSDesStruct SiS310_PanelType00_1[]= /* 800x600 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType01_1[]= /* 1024x768 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 805},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType02_1[]= /* 1280x1024 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 1065},
- { 0, 0},
- { 0, 0}
-};
-
-
-static const SiS_LVDSDesStruct SiS310_PanelType03_1[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType04_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType05_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType06_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType07_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType08_1[]= /* 1400x1050 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType09_1[]= /* 1280x768 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0a_1[]= /* 1600x1200 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0b_1[]= /* 640x480_2 */
-{
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 8, 524},
- { 0, 524}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0c_1[]= /* 640x480_3 */
-{
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 8, 524},
- { 0, 524}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0d_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0e_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0f_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType00_2[]=
-{
- {980, 528},
- {980, 503},
- {980, 528},
- {980, 503},
- {980, 568},
- { 0, 628},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType01_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 806},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType02_2[]=
-{
- {1368, 754},
- {1368, 729},
- {1368, 754},
- {1368, 729},
- {1368, 794},
- {1448, 854},
- {1560, 938},
- { 0,1066},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType03_2[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType04_2[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType05_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType06_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType07_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType08_2[]= /* 1400x1050 */
-{
- {1308, 741},
- {1308, 716},
- {1308, 741},
- {1308, 716},
- {1308, 781},
- {1388, 841},
- {1500, 925},
- {1628,1053},
- { 0,1065},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType09_2[]= /* 1280x768 */
-{
- {1083, 622},
- {1083, 597},
- {1083, 622},
- {1083, 597},
- {1083, 662},
- {1163, 722},
- {1286, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0a_2[]= /* 1600x1200 */
-{
- {1568, 920},
- {1568, 895},
- {1568, 920},
- {1568, 895},
- {1568, 960},
- {1648,1020},
- {1760,1104},
- {1888,1232},
- {1948,1245},
- { 0, 0}
-#if 0
- {1568, 850},
- {1568, 825},
- {1568, 850},
- {1568, 825},
- {1568, 890},
- {1648, 950},
- {1760,1034},
- {1888,1162},
- {1948,1175},
- { 0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0b_2[]= /* 640x480_2 */
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0c_2[]= /* 640x480_3 */
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0d_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0e_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0f_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelTypeNS_1[]=
-{
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 806},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelTypeNS_2[] =
-{
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0}
-};
-
-/* CRT1 CRTC for SlaveModes and LCDA */
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] =
-{
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] =
-{
- {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0,
- 0x58,0x8d,0x57,0x73,0x20,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]=
-{
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
- 0x27,0x8c,0xdf,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
- 0x58,0x8d,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] =
-{
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba,
- 0x27,0x8c,0xdf,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0,
- 0x63,0x88,0x57,0x73,0x00,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] =
-{
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
- 0x00}},
- {{0x87,0x63,0x8B,0x67,0x18,0x7c,0xf0,
- 0x5A,0x81,0x57,0x7D,0x00,0x00,0x06,
- 0x01}},
- {{0xA3,0x7f,0x87,0x83,0x94,0x24,0xf5,
- 0x02,0x89,0xFf,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] =
-{
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00 }},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
- 0x00}},
- {{0x55,0x31,0x99,0x35,0x06,0x7c,0xf0,
- 0x5A,0x81,0x57,0x7D,0x00,0x00,0x01,
- 0x01}},
- {{0x63,0x3F,0x87,0x43,0x94,0x24,0xf5,
- 0x02,0x89,0xFf,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
- 0x01 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x7f,0x86,0xdf,0x25,0x10,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xbb,0x82,0x57,0x25,0x10,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x83,0x94,0x24,0xf5,
- 0x02,0x89,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] =
-{
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x7f,0x86,0xdf,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x71,0x31,0x95,0x46,0x97,0x24,0xf1,
- 0xbb,0x82,0x57,0x25,0x10,0x00,0x01,
- 0x01 }},
- {{0x63,0x3f,0x87,0x46,0x97,0x24,0xf5,
- 0x0f,0x86,0xff,0x25,0x30,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] =
-{
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x08,0x3e,
- 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06,
- 0x00}},
- {{0x92,0x63,0x96,0x6c,0x18,0x80,0xf0,
- 0x58,0x8c,0x57,0x81,0x20,0x00,0x06,
- 0x01}},
- {{0xae,0x7f,0x92,0x88,0x94,0x28,0xf5,
- 0x00,0x84,0xff,0x29,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] =
-{
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
- 0x01}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x08,0x3e,
- 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05,
- 0x00}},
- {{0x60,0x31,0x84,0x3a,0x86,0x80,0xf0,
- 0x58,0x8c,0x57,0x81,0x20,0x00,0x01,
- 0x01}},
- {{0x6e,0x3f,0x92,0x48,0x94,0x28,0xf5,
- 0x00,0x84,0xff,0x29,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] =
-{
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xf0,0x84,0x85,0x84,0x11,0x00,0x02,
- 0x01}},
- {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xfa,0x83,0x44,0x43,0x31,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xf0,0x84,0x85,0x84,0x11,0x00,0x06,
- 0x01}},
- {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x59,0x07,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] =
-{
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x5e,0x81,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
- 0xdf,0x82,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
- 0x57,0x8e,0x57,0x67,0x20,0x00,0x06,
- 0x01}},
- {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf1,
- 0xff,0x86,0xff,0x0f,0x10,0x00,0x02,
- 0x01,}},
- {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0xde,
- 0xff,0x86,0xff,0x0f,0x01,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
- 0x19,0x80,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#if 0
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x06,
- 0x01}},
- {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x02,
- 0x01}},
- {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
- 0x1a,0x80,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] =
-{
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xdf,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x57,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf1,
- 0xff,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
- 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
- 0x00}}
-#if 0
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
- 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] =
-{
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xff,0x83,0x85,0x84,0x11,0x00,0x02,
- 0x01}},
- {{0xce,0x63,0x92,0x8e,0x1c,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x7f,0x92,0x9c,0x0a,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xac,0x1a,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#if 0
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
- 0x03,0x87,0xdf,0x29,0x01,0x00,0x03,
- 0x00}},
- {{0xce,0x63,0x92,0x96,0x04,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x07,
- 0x01}},
- {{0xce,0x7f,0x92,0xa4,0x12,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xb4,0x02,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x03,
- 0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xff,0x83,0x85,0x84,0x11,0x00,0x06,
- 0x01}},
- {{0x9c,0x31,0x80,0x5c,0x8a,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x5c,0x0a,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}},
- {{0x7e,0x4f,0x82,0x5c,0x0a,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x06,
- 0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
- 0x00}}
-#if 0
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9e,
- 0x03,0x87,0xdf,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0x9c,0x31,0x80,0x64,0x92,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x64,0x12,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}},
- {{0x7e,0x4f,0x82,0x64,0x12,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x06,
- 0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] =
-{
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x56,0xBA,
- 0x03,0x86,0xDF,0x57,0x00,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xCE,0xF0,
- 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x02,
- 0x01}},
- {{0xB3,0x7F,0x97,0x8B,0x83,0x76,0xF5,
- 0x23,0x86,0xFF,0x77,0x10,0x00,0x06,
- 0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
- 0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
- 0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
- 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
- 0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
- 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
- 0x00}}
-#if 0
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x10,0x3e,
- 0xe0,0x84,0xdf,0x11,0x00,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0x88,0xf0,
- 0x58,0x8c,0x57,0x89,0x20,0x00,0x06,
- 0x01}},
- {{0xb3,0x7f,0x97,0x81,0x99,0x30,0xf5,
- 0x00,0x84,0xff,0x31,0x10,0x00,0x02,
- 0x01}},
- {{0xd3,0x9f,0x97,0xa1,0x19,0x30,0x5a,
- 0x00,0x84,0xff,0x31,0x09,0x00,0x07,
- 0x01}},
- {{0xe2,0xae,0x86,0xb0,0x88,0x4a,0x10,
- 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x03,
- 0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x81,0xe0,0x10,
- 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x07,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] =
-{
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
- 0x00}},
- {{0x5B,0x27,0x9F,0x29,0x01,0x8E,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x56,0xBA,
- 0x03,0x86,0xDF,0x57,0x00,0x00,0x01,
- 0x00}},
- {{0x65,0x31,0x89,0x3D,0x95,0xCE,0xF0,
- 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x01,
- 0x01}},
- {{0x73,0x3F,0x97,0x4B,0x83,0x76,0xF5,
- 0x23,0x86,0xFF,0x77,0x10,0x00,0x05,
- 0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
- 0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
- 0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
- 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
- 0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xE0,0x10,
- 0xB0,0x84,0xAF,0xE1,0x2F,0x00,0x06,
- 0x00}}
-#if 0
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x10,0x3e,
- 0xe0,0x84,0xdf,0x11,0x00,0x00,0x01,
- 0x00}},
- {{0x65,0x31,0x89,0x33,0x8b,0x88,0xf0,
- 0x58,0x8c,0x57,0x89,0x20,0x00,0x01,
- 0x01}},
- {{0x73,0x3f,0x97,0x41,0x99,0x30,0xf5,
- 0x00,0x84,0xff,0x31,0x10,0x00,0x01,
- 0x01}},
- {{0x83,0x4f,0x87,0x51,0x09,0x30,0x5a,
- 0x00,0x84,0xff,0x31,0x09,0x00,0x06,
- 0x01}},
- {{0x8a,0x56,0x8e,0x58,0x10,0x4a,0x10,
- 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0xe0,0x10,
- 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x06,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] =
-{
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x9F,
- 0x6B,0x8E,0x03,0x02,0x01,0x00,0x07,
- 0x01}},
- {{0xFB,0x63,0x9F,0xA1,0x99,0x26,0xD5,
- 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x07,
- 0x01}},
- {{0xFB,0x7F,0x9F,0xAF,0x87,0x26,0xDD,
- 0xFB,0x8E,0x13,0x12,0x31,0x00,0x03,
- 0x01}},
- {{0xFB,0x9F,0x9F,0xBF,0x97,0x26,0x5B,
- 0x7B,0x8E,0xFF,0x27,0x39,0x00,0x03,
- 0x01}},
- {{0xFB,0xAE,0x9F,0xC6,0x9E,0x26,0x11,
- 0x88,0x8B,0x19,0x27,0x1F,0x00,0x03,
- 0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
- 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
- 0x00}}
-#if 0
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x07,
- 0x01}},
- {{0xfb,0x63,0x9f,0x9a,0x92,0xe0,0xd4,
- 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x07,
- 0x01}},
- {{0xfb,0x7f,0x9f,0xa8,0x80,0xe0,0xd4,
- 0xef,0x83,0xff,0xe1,0x21,0x00,0x03,
- 0x01}},
- {{0xfb,0x9f,0x9f,0xb8,0x90,0xe0,0x5a,
- 0x6f,0x83,0xff,0xe1,0x29,0x00,0x03,
- 0x01}},
- {{0xfb,0xae,0x9f,0xbf,0x97,0xe0,0x10,
- 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x03,
- 0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x84,0xe0,0x10,
- 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x07,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] =
-{
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
- 0x01}},
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x07,0x8B,0xA0,0x9F,0x01,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
- 0x01}},
- {{0xC9,0x31,0x8D,0x6F,0x07,0x26,0xD5,
- 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x03,
- 0x01}},
- {{0xBB,0x3F,0x9F,0x6F,0x87,0x26,0xDD,
- 0xFB,0x8E,0x13,0x12,0x31,0x00,0x02,
- 0x01}},
- {{0xAB,0x4F,0x8F,0x68,0x80,0xE0,0x5A,
- 0x6F,0x83,0xFF,0xE1,0x29,0x00,0x02,
- 0x01}},
- {{0xA3,0x56,0x87,0x67,0x9F,0xE0,0x10,
- 0x7C,0x80,0x19,0xE1,0x0F,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9B,0x68,0x00,0xE0,0x10,
- 0xC7,0x8B,0xAF,0xE1,0x0F,0x00,0x02,
- 0x00}}
-#if 0
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x02,
- 0x01}},
- {{0xc9,0x31,0x8d,0x68,0x00,0xe0,0xd4,
- 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x03,
- 0x01}},
- {{0xbb,0x3f,0x9f,0x68,0x80,0xe0,0xd4,
- 0xef,0x83,0xff,0xe1,0x21,0x00,0x02,
- 0x01}},
- {{0xab,0x4f,0x8f,0x68,0x80,0xe0,0x5a,
- 0x6f,0x83,0xff,0xe1,0x29,0x00,0x02,
- 0x01}},
- {{0xa3,0x56,0x87,0x67,0x9f,0xe0,0x10,
- 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x68,0x00,0xe0,0x10,
- 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x02,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
- 0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-
/* CRT1 CRTC for Chrontel TV slave modes */
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] =
-{
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UNTSC[] =
+{
{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
0x00 }},
@@ -2546,7 +1132,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] =
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1ONTSC[] =
{
{{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -2571,8 +1157,8 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] =
-{
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UPAL[] =
+{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
0x00 }},
@@ -2596,7 +1182,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] =
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1OPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2621,8 +1207,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] =
0x01 }}
};
-
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UNTSC[] =
{
{{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2642,7 +1227,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
for PAL-M and PAL-N all above is corrected.
*/
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_ONTSC[] =
{
{{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2653,7 +1238,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
{{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPAL[] =
{
{{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2664,7 +1249,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
{{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPAL[] =
{
{{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2675,7 +1260,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
{{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALM[] =
{
{{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2691,7 +1276,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALM[] =
{
{{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2707,7 +1292,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALN[] =
{
{{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
{{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2723,7 +1308,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALN[] =
{
{{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
{{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2739,16 +1324,16 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
#endif
};
-static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKONTSC[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUNTSC[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKONTSC[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-static const UCHAR SiS310_CHTVVCLKUPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPAL[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPAL[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
-static const UCHAR SiS310_CHTVVCLKUPALM[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKOPALM[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUPALM[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKOPALM[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-static const UCHAR SiS310_CHTVVCLKUPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile
index aaed8c2b4a64..f7c0046e5b1d 100644
--- a/drivers/video/sis/Makefile
+++ b/drivers/video/sis/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_FB_SIS) += sisfb.o
-sisfb-objs := sis_main.o sis_accel.o init.o init301.o
+sisfb-objs := sis_main.o sis_accel.o init.o init301.o initextlfb.o
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index ecfd72178dbb..2ab3868efde3 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -2,11 +2,12 @@
/* $XdotOrg$ */
/*
* Mode initializing code (CRT1 section) for
- * for SiS 300/305/540/630/730 and
- * SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ * for SiS 300/305/540/630/730,
+ * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI Volari V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -53,17 +54,12 @@
*
* Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
* Used by permission.
- *
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if they are marked TW or not.
- *
*/
-
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "init.h"
#ifdef SIS300
@@ -84,24 +80,13 @@
#if defined(SIS300) || defined(SIS315H)
static void
-InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitCommonPointer(struct SiS_Private *SiS_Pr)
{
+ SiS_Pr->SiS_SModeIDTable = SiS_SModeIDTable;
SiS_Pr->SiS_StResInfo = SiS_StResInfo;
SiS_Pr->SiS_ModeResInfo = SiS_ModeResInfo;
SiS_Pr->SiS_StandTable = SiS_StandTable;
- SiS_Pr->SiS_NTSCPhase = SiS_NTSCPhase;
- SiS_Pr->SiS_PALPhase = SiS_PALPhase;
- SiS_Pr->SiS_NTSCPhase2 = SiS_NTSCPhase2;
- SiS_Pr->SiS_PALPhase2 = SiS_PALPhase2;
- SiS_Pr->SiS_PALMPhase = SiS_PALMPhase;
- SiS_Pr->SiS_PALNPhase = SiS_PALNPhase;
- SiS_Pr->SiS_PALMPhase2 = SiS_PALMPhase2;
- SiS_Pr->SiS_PALNPhase2 = SiS_PALNPhase2;
- SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase;
- SiS_Pr->SiS_SpecialPhaseM = SiS_SpecialPhaseM;
- SiS_Pr->SiS_SpecialPhaseJ = SiS_SpecialPhaseJ;
-
SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming;
SiS_Pr->SiS_PALTiming = SiS_PALTiming;
SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing;
@@ -137,6 +122,7 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
SiS_Pr->SiS_LCD1280x800Data = SiS_LCD1280x800Data;
SiS_Pr->SiS_LCD1280x800_2Data = SiS_LCD1280x800_2Data;
+ SiS_Pr->SiS_LCD1280x854Data = SiS_LCD1280x854Data;
SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data;
SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data;
SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data;
@@ -145,67 +131,30 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data;
SiS_Pr->SiS_NoScaleData = SiS_NoScaleData;
- SiS_Pr->SiS_LVDS320x480Data_1 = SiS_LVDS320x480Data_1;
+ SiS_Pr->SiS_LVDS320x240Data_1 = SiS_LVDS320x240Data_1;
+ SiS_Pr->SiS_LVDS320x240Data_2 = SiS_LVDS320x240Data_2;
+ SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1;
- SiS_Pr->SiS_LVDS800x600Data_2 = SiS_LVDS800x600Data_2;
- SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
- SiS_Pr->SiS_LVDS1024x768Data_2 = SiS_LVDS1024x768Data_2;
- SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1;
- SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2;
- SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1;
- SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2;
- SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1;
- SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2;
- SiS_Pr->SiS_LVDS1280x768Data_1 = SiS_LVDS1280x768Data_1;
- SiS_Pr->SiS_LVDS1280x768Data_2 = SiS_LVDS1280x768Data_2;
SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1;
- SiS_Pr->SiS_LVDS1024x600Data_2 = SiS_LVDS1024x600Data_2;
- SiS_Pr->SiS_LVDS1152x768Data_1 = SiS_LVDS1152x768Data_1;
- SiS_Pr->SiS_LVDS1152x768Data_2 = SiS_LVDS1152x768Data_2;
- SiS_Pr->SiS_LVDSXXXxXXXData_1 = SiS_LVDSXXXxXXXData_1;
- SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x960Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x960Data_2;
- SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x1024Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x1024Data_2;
- SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
- SiS_Pr->SiS_LVDS640x480Data_2 = SiS_LVDS640x480Data_2;
-
- SiS_Pr->SiS_LVDS848x480Data_1 = SiS_LVDS848x480Data_1;
- SiS_Pr->SiS_LVDS848x480Data_2 = SiS_LVDS848x480Data_2;
- SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
- SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
- SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
- SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
+ SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
- SiS_Pr->SiS_LVDSCRT11280x768_1 = SiS_LVDSCRT11280x768_1;
+ SiS_Pr->SiS_LVDSCRT1320x240_1 = SiS_LVDSCRT1320x240_1;
+ SiS_Pr->SiS_LVDSCRT1320x240_2 = SiS_LVDSCRT1320x240_2;
+ SiS_Pr->SiS_LVDSCRT1320x240_2_H = SiS_LVDSCRT1320x240_2_H;
+ SiS_Pr->SiS_LVDSCRT1320x240_3 = SiS_LVDSCRT1320x240_3;
+ SiS_Pr->SiS_LVDSCRT1320x240_3_H = SiS_LVDSCRT1320x240_3_H;
+ SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
+ SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
+#if 0
SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1;
- SiS_Pr->SiS_LVDSCRT11152x768_1 = SiS_LVDSCRT11152x768_1;
- SiS_Pr->SiS_LVDSCRT11280x768_1_H = SiS_LVDSCRT11280x768_1_H;
SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H;
- SiS_Pr->SiS_LVDSCRT11152x768_1_H = SiS_LVDSCRT11152x768_1_H;
- SiS_Pr->SiS_LVDSCRT11280x768_2 = SiS_LVDSCRT11280x768_2;
SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2;
- SiS_Pr->SiS_LVDSCRT11152x768_2 = SiS_LVDSCRT11152x768_2;
- SiS_Pr->SiS_LVDSCRT11280x768_2_H = SiS_LVDSCRT11280x768_2_H;
SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H;
- SiS_Pr->SiS_LVDSCRT11152x768_2_H = SiS_LVDSCRT11152x768_2_H;
- SiS_Pr->SiS_LVDSCRT1320x480_1 = SiS_LVDSCRT1320x480_1;
- SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
- SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
- SiS_Pr->SiS_LVDSCRT1640x480_2 = SiS_LVDSCRT1640x480_2;
- SiS_Pr->SiS_LVDSCRT1640x480_2_H = SiS_LVDSCRT1640x480_2_H;
- SiS_Pr->SiS_LVDSCRT1640x480_3 = SiS_LVDSCRT1640x480_3;
- SiS_Pr->SiS_LVDSCRT1640x480_3_H = SiS_LVDSCRT1640x480_3_H;
+#endif
SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
- SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
- SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
- SiS_Pr->SiS_CHTVUPALDesData = SiS_CHTVUPALDesData;
- SiS_Pr->SiS_CHTVOPALDesData = SiS_CHTVOPALDesData;
-
SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* lowest value LVDS/LCDA */
SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */
}
@@ -213,50 +162,24 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS300
static void
-InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo300Pointer(struct SiS_Private *SiS_Pr)
{
- InitCommonPointer(SiS_Pr, HwInfo);
+ InitCommonPointer(SiS_Pr);
- SiS_Pr->SiS_SModeIDTable = SiS300_SModeIDTable;
SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
SiS_Pr->SiS_EModeIDTable = SiS300_EModeIDTable;
SiS_Pr->SiS_RefIndex = SiS300_RefIndex;
SiS_Pr->SiS_CRT1Table = SiS300_CRT1Table;
- if(HwInfo->jChipType == SIS_300) {
- SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
+ if(SiS_Pr->ChipType == SIS_300) {
+ SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
} else {
- SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
+ SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
}
SiS_Pr->SiS_VCLKData = SiS300_VCLKData;
- SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
+ SiS_Pr->SiS_VBVCLKData = (struct SiS_VBVCLKData *)SiS300_VCLKData;
SiS_Pr->SiS_SR15 = SiS300_SR15;
-#ifdef LINUX_KERNEL
- SiS_Pr->pSiS_SR07 = &SiS300_SR07;
- SiS_Pr->SiS_CR40 = SiS300_CR40;
- SiS_Pr->SiS_CR49 = SiS300_CR49;
- SiS_Pr->pSiS_SR1F = &SiS300_SR1F;
- SiS_Pr->pSiS_SR21 = &SiS300_SR21;
- SiS_Pr->pSiS_SR22 = &SiS300_SR22;
- SiS_Pr->pSiS_SR23 = &SiS300_SR23;
- SiS_Pr->pSiS_SR24 = &SiS300_SR24;
- SiS_Pr->SiS_SR25 = SiS300_SR25;
- SiS_Pr->pSiS_SR31 = &SiS300_SR31;
- SiS_Pr->pSiS_SR32 = &SiS300_SR32;
- SiS_Pr->pSiS_SR33 = &SiS300_SR33;
- SiS_Pr->pSiS_CRT2Data_1_2 = &SiS300_CRT2Data_1_2;
- SiS_Pr->pSiS_CRT2Data_4_D = &SiS300_CRT2Data_4_D;
- SiS_Pr->pSiS_CRT2Data_4_E = &SiS300_CRT2Data_4_E;
- SiS_Pr->pSiS_CRT2Data_4_10 = &SiS300_CRT2Data_4_10;
- SiS_Pr->pSiS_RGBSenseData = &SiS300_RGBSenseData;
- SiS_Pr->pSiS_VideoSenseData = &SiS300_VideoSenseData;
- SiS_Pr->pSiS_YCSenseData = &SiS300_YCSenseData;
- SiS_Pr->pSiS_RGBSenseData2 = &SiS300_RGBSenseData2;
- SiS_Pr->pSiS_VideoSenseData2 = &SiS300_VideoSenseData2;
- SiS_Pr->pSiS_YCSenseData2 = &SiS300_YCSenseData2;
-#endif
-
SiS_Pr->SiS_PanelDelayTbl = SiS300_PanelDelayTbl;
SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
@@ -266,11 +189,8 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_St2LCD1280x1024Data = SiS300_St2LCD1280x1024Data;
SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS300_CRT2Part2_1024x768_1;
- SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
SiS_Pr->SiS_CRT2Part2_1024x768_2 = SiS300_CRT2Part2_1024x768_2;
- SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
SiS_Pr->SiS_CRT2Part2_1024x768_3 = SiS300_CRT2Part2_1024x768_3;
- SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
SiS_Pr->SiS_CHTVUPALData = SiS300_CHTVUPALData;
SiS_Pr->SiS_CHTVOPALData = SiS300_CHTVOPALData;
@@ -280,64 +200,16 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData; /* not supported on 300 series */
SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
- SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
- SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
- SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
- SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
- SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
- SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
- SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
- SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
- SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
- SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
- SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
- SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
- SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
- SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
- SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
- SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
- SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
- SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
- SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
- SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
- SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
- SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
- SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
- SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
- SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
- SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
- SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
- SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
- SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
- SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
- SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
- SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
-
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
- }
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
- }
-
- SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS300_LVDSCRT1800x600_1;
- SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS300_LVDSCRT1800x600_1_H;
- SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS300_LVDSCRT1800x600_2;
- SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS300_LVDSCRT1800x600_2_H;
- SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS300_LVDSCRT11024x768_1;
- SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS300_LVDSCRT11024x768_1_H;
- SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS300_LVDSCRT11024x768_2;
- SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS300_LVDSCRT11024x768_2_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS300_LVDSCRT11280x1024_1;
- SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS300_LVDSCRT11280x1024_2;
- SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS300_LVDSCRT1XXXxXXX_1;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS300_LVDSCRT1XXXxXXX_1_H;
+ SiS_Pr->SiS_LVDS848x480Data_1 = SiS300_LVDS848x480Data_1;
+ SiS_Pr->SiS_LVDS848x480Data_2 = SiS300_LVDS848x480Data_2;
+ SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
+ SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
+ SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
+
+ SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
+ SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
+ SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
+ SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
@@ -367,64 +239,38 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H
static void
-InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo310Pointer(struct SiS_Private *SiS_Pr)
{
- InitCommonPointer(SiS_Pr, HwInfo);
+ InitCommonPointer(SiS_Pr);
- SiS_Pr->SiS_SModeIDTable = SiS310_SModeIDTable;
SiS_Pr->SiS_EModeIDTable = SiS310_EModeIDTable;
- SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex;
+ SiS_Pr->SiS_RefIndex = SiS310_RefIndex;
SiS_Pr->SiS_CRT1Table = SiS310_CRT1Table;
- if(HwInfo->jChipType >= SIS_340) {
- SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 */
- } else if(HwInfo->jChipType >= SIS_761) {
+ if(SiS_Pr->ChipType >= SIS_340) {
+ SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 + XGI */
+ } else if(SiS_Pr->ChipType >= SIS_761) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761; /* 761 - preliminary */
- } else if(HwInfo->jChipType >= SIS_760) {
+ } else if(SiS_Pr->ChipType >= SIS_760) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760; /* 760 */
- } else if(HwInfo->jChipType >= SIS_661) {
+ } else if(SiS_Pr->ChipType >= SIS_661) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660; /* 661/741 */
- } else if(HwInfo->jChipType == SIS_330) {
+ } else if(SiS_Pr->ChipType == SIS_330) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330; /* 330 */
- } else if(HwInfo->jChipType > SIS_315PRO) {
+ } else if(SiS_Pr->ChipType > SIS_315PRO) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650; /* 550, 650, 740 */
} else {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315; /* 315 */
}
- if(HwInfo->jChipType >= SIS_340) {
- SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
+ if(SiS_Pr->ChipType >= SIS_340) {
+ SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
} else {
- SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
+ SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
}
SiS_Pr->SiS_VCLKData = SiS310_VCLKData;
SiS_Pr->SiS_VBVCLKData = SiS310_VBVCLKData;
SiS_Pr->SiS_SR15 = SiS310_SR15;
-#ifdef LINUX_KERNEL
- SiS_Pr->pSiS_SR07 = &SiS310_SR07;
- SiS_Pr->SiS_CR40 = SiS310_CR40;
- SiS_Pr->SiS_CR49 = SiS310_CR49;
- SiS_Pr->pSiS_SR1F = &SiS310_SR1F;
- SiS_Pr->pSiS_SR21 = &SiS310_SR21;
- SiS_Pr->pSiS_SR22 = &SiS310_SR22;
- SiS_Pr->pSiS_SR23 = &SiS310_SR23;
- SiS_Pr->pSiS_SR24 = &SiS310_SR24;
- SiS_Pr->SiS_SR25 = SiS310_SR25;
- SiS_Pr->pSiS_SR31 = &SiS310_SR31;
- SiS_Pr->pSiS_SR32 = &SiS310_SR32;
- SiS_Pr->pSiS_SR33 = &SiS310_SR33;
- SiS_Pr->pSiS_CRT2Data_1_2 = &SiS310_CRT2Data_1_2;
- SiS_Pr->pSiS_CRT2Data_4_D = &SiS310_CRT2Data_4_D;
- SiS_Pr->pSiS_CRT2Data_4_E = &SiS310_CRT2Data_4_E;
- SiS_Pr->pSiS_CRT2Data_4_10 = &SiS310_CRT2Data_4_10;
- SiS_Pr->pSiS_RGBSenseData = &SiS310_RGBSenseData;
- SiS_Pr->pSiS_VideoSenseData = &SiS310_VideoSenseData;
- SiS_Pr->pSiS_YCSenseData = &SiS310_YCSenseData;
- SiS_Pr->pSiS_RGBSenseData2 = &SiS310_RGBSenseData2;
- SiS_Pr->pSiS_VideoSenseData2 = &SiS310_VideoSenseData2;
- SiS_Pr->pSiS_YCSenseData2 = &SiS310_YCSenseData2;
-#endif
-
SiS_Pr->SiS_PanelDelayTbl = SiS310_PanelDelayTbl;
SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
@@ -435,41 +281,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS310_CRT2Part2_1024x768_1;
- SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
- SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
- SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
- SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
- SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
- SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
- SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
- SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
- SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
- SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
- SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
- SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
- SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
- SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
- SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
- SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
- SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
- SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
- SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
- SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
- SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
- SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
- SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
- SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
- SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
- SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
- SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
- SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
- SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
- SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
- SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
- SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
- SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
- SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
-
SiS_Pr->SiS_CHTVUPALData = SiS310_CHTVUPALData;
SiS_Pr->SiS_CHTVOPALData = SiS310_CHTVOPALData;
SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
@@ -478,33 +289,11 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
- SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS310_LVDSCRT1800x600_1;
- SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS310_LVDSCRT11024x768_1;
- SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS310_LVDSCRT11280x1024_1;
- SiS_Pr->SiS_LVDSCRT11400x1050_1 = SiS310_LVDSCRT11400x1050_1;
- SiS_Pr->SiS_LVDSCRT11600x1200_1 = SiS310_LVDSCRT11600x1200_1;
- SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS310_LVDSCRT1800x600_1_H;
- SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS310_LVDSCRT11024x768_1_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
- SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
- SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
- SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS310_LVDSCRT1800x600_2;
- SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS310_LVDSCRT11024x768_2;
- SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS310_LVDSCRT11280x1024_2;
- SiS_Pr->SiS_LVDSCRT11400x1050_2 = SiS310_LVDSCRT11400x1050_2;
- SiS_Pr->SiS_LVDSCRT11600x1200_2 = SiS310_LVDSCRT11600x1200_2;
- SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS310_LVDSCRT1800x600_2_H;
- SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS310_LVDSCRT11024x768_2_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
- SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
- SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS310_LVDSCRT1XXXxXXX_1;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS310_LVDSCRT1XXXxXXX_1_H;
- SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
- SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
- SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL;
- SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL;
- SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
+ SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
+ SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
+ SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL;
+ SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL;
+ SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
@@ -528,208 +317,203 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
#endif
-static void
-SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+BOOLEAN
+SiSInitPtr(struct SiS_Private *SiS_Pr)
{
- switch(HwInfo->jChipType) {
-#ifdef SIS315H
- case SIS_315H:
- case SIS_315:
- case SIS_315PRO:
- case SIS_550:
- case SIS_650:
- case SIS_740:
- case SIS_330:
- case SIS_661:
- case SIS_741:
- case SIS_660:
- case SIS_760:
- case SIS_761:
- case SIS_340:
- InitTo310Pointer(SiS_Pr, HwInfo);
- break;
-#endif
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- case SIS_300:
- case SIS_540:
- case SIS_630:
- case SIS_730:
- InitTo300Pointer(SiS_Pr, HwInfo);
- break;
+ InitTo300Pointer(SiS_Pr);
+#else
+ return FALSE;
+#endif
+ } else {
+#ifdef SIS315H
+ InitTo310Pointer(SiS_Pr);
+#else
+ return FALSE;
#endif
- default:
- break;
}
+ return TRUE;
}
/*********************************************/
/* HELPER: Get ModeID */
/*********************************************/
-#ifdef LINUX_XF86
-USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
switch(HDisplay)
{
- case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) {
- if(FSTN) ModeIndex = ModeIndex_320x240_FSTN[Depth];
- else ModeIndex = ModeIndex_320x240[Depth];
- }
- break;
- case 400:
- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- }
- break;
- case 512:
- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
- }
- break;
- case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
- else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
- break;
- case 720:
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
- break;
- case 768:
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
- break;
- case 800:
- if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
- else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
- break;
- case 848:
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
- break;
- case 856:
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
- break;
- case 960:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
- else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
- }
- break;
- case 1024:
- if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
- else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
- else if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
- }
- break;
- case 1152:
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
- if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
- }
- break;
- case 1280:
- switch(VDisplay) {
- case 720:
- ModeIndex = ModeIndex_1280x720[Depth];
- break;
- case 768:
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_1280x768[Depth];
- } else {
- ModeIndex = ModeIndex_310_1280x768[Depth];
- }
- break;
- case 800:
- if(VGAEngine == SIS_315_VGA) {
- ModeIndex = ModeIndex_1280x800[Depth];
- }
- break;
- case 960:
- ModeIndex = ModeIndex_1280x960[Depth];
- break;
- case 1024:
- ModeIndex = ModeIndex_1280x1024[Depth];
- break;
- }
- break;
- case 1360:
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
- if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
- }
- break;
- case 1400:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) {
- ModeIndex = ModeIndex_1400x1050[Depth];
- }
- }
- break;
- case 1600:
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
- break;
- case 1680:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
- }
- break;
- case 1920:
- if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
- else if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
- }
- break;
- case 2048:
- if(VDisplay == 1536) {
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_2048x1536[Depth];
- } else {
- ModeIndex = ModeIndex_310_2048x1536[Depth];
- }
- }
- break;
+ case 320:
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ else if(VDisplay == 240) {
+ if((VBFlags & CRT2_LCD) && (FSTN))
+ ModeIndex = ModeIndex_320x240_FSTN[Depth];
+ else
+ ModeIndex = ModeIndex_320x240[Depth];
+ }
+ break;
+ case 400:
+ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ }
+ break;
+ case 512:
+ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ }
+ break;
+ case 640:
+ if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
+ else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+ break;
+ case 720:
+ if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
+ else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+ break;
+ case 768:
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ break;
+ case 800:
+ if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+ else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+ break;
+ case 848:
+ if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+ break;
+ case 856:
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ break;
+ case 960:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+ else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
+ }
+ break;
+ case 1024:
+ if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+ else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+ else if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
+ }
+ break;
+ case 1152:
+ if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+ if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
+ }
+ break;
+ case 1280:
+ switch(VDisplay) {
+ case 720:
+ ModeIndex = ModeIndex_1280x720[Depth];
+ break;
+ case 768:
+ if(VGAEngine == SIS_300_VGA) {
+ ModeIndex = ModeIndex_300_1280x768[Depth];
+ } else {
+ ModeIndex = ModeIndex_310_1280x768[Depth];
+ }
+ break;
+ case 800:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x800[Depth];
+ }
+ break;
+ case 854:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x854[Depth];
+ }
+ break;
+ case 960:
+ ModeIndex = ModeIndex_1280x960[Depth];
+ break;
+ case 1024:
+ ModeIndex = ModeIndex_1280x1024[Depth];
+ break;
+ }
+ break;
+ case 1360:
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
+ }
+ break;
+ case 1400:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1050) {
+ ModeIndex = ModeIndex_1400x1050[Depth];
+ }
+ }
+ break;
+ case 1600:
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ break;
+ case 1680:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ }
+ break;
+ case 1920:
+ if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+ else if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
+ }
+ break;
+ case 2048:
+ if(VDisplay == 1536) {
+ if(VGAEngine == SIS_300_VGA) {
+ ModeIndex = ModeIndex_300_2048x1536[Depth];
+ } else {
+ ModeIndex = ModeIndex_310_2048x1536[Depth];
+ }
+ }
+ break;
}
- return(ModeIndex);
+ return ModeIndex;
}
-#endif
-USHORT
-SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, USHORT CustomT, int LCDwidth, int LCDheight)
+unsigned short
+SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
- if(VBFlags & (VB_LVDS | VB_30xBDH)) {
+ if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
switch(HDisplay)
{
case 320:
- if(CustomT != CUT_PANEL848) {
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) {
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(VDisplay == 200) {
+ if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
+ } else if(VDisplay == 240) {
if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
- else if(VGAEngine == SIS_315_VGA) {
- ModeIndex = ModeIndex_320x240_FSTN[Depth];
+ else if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_320x240_FSTN[Depth];
}
}
}
- break;
- case 400:
- if(CustomT != CUT_PANEL848) {
- if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 400:
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
}
}
- break;
+ break;
case 512:
- if(CustomT != CUT_PANEL848) {
- if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
if(VDisplay == 384) {
ModeIndex = ModeIndex_512x384[Depth];
@@ -739,9 +523,10 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
}
break;
case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
else if(VDisplay == 400) {
- if(CustomT != CUT_PANEL848) ModeIndex = ModeIndex_640x400[Depth];
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
+ ModeIndex = ModeIndex_640x400[Depth];
}
break;
case 800:
@@ -752,6 +537,11 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
}
break;
+ case 856:
+ if(CustomT == CUT_PANEL856) {
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ }
+ break;
case 1024:
if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
else if(VGAEngine == SIS_300_VGA) {
@@ -762,7 +552,7 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
break;
case 1152:
if(VGAEngine == SIS_300_VGA) {
- if((VDisplay == 768) && (LCDheight == 768)) {
+ if((VDisplay == 768) && (LCDheight == 768)) {
ModeIndex = ModeIndex_1152x768[Depth];
}
}
@@ -770,49 +560,49 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
case 1280:
if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
else if(VGAEngine == SIS_315_VGA) {
- if((VDisplay == 768) && (LCDheight == 768)) {
+ if((VDisplay == 768) && (LCDheight == 768)) {
ModeIndex = ModeIndex_310_1280x768[Depth];
}
}
break;
case 1360:
if(VGAEngine == SIS_300_VGA) {
- if(CustomT == CUT_BARCO1366) {
+ if(CustomT == CUT_BARCO1366) {
if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
}
}
if(CustomT == CUT_PANEL848) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
}
break;
case 1400:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
}
break;
case 1600:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
}
break;
}
- } else if(VBFlags & VB_SISBRIDGE) {
+ } else if(VBFlags2 & VB2_SISBRIDGE) {
switch(HDisplay)
{
case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
+ break;
+ case 400:
if(LCDwidth >= 800 && LCDheight >= 600) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
}
- break;
+ break;
case 512:
if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
break;
case 640:
@@ -821,96 +611,115 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
break;
case 720:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
}
break;
case 768:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
}
break;
case 800:
if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
}
break;
case 848:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
}
break;
case 856:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
}
break;
case 960:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+ if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
}
break;
case 1024:
if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
}
break;
case 1152:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+ if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
}
break;
case 1280:
switch(VDisplay) {
case 720:
- ModeIndex = ModeIndex_1280x720[Depth];
+ ModeIndex = ModeIndex_1280x720[Depth];
case 768:
- if(VGAEngine == SIS_300_VGA) {
+ if(VGAEngine == SIS_300_VGA) {
ModeIndex = ModeIndex_300_1280x768[Depth];
} else {
ModeIndex = ModeIndex_310_1280x768[Depth];
}
break;
case 800:
- if(VGAEngine == SIS_315_VGA) {
+ if(VGAEngine == SIS_315_VGA) {
ModeIndex = ModeIndex_1280x800[Depth];
}
break;
+ case 854:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x854[Depth];
+ }
+ break;
case 960:
- ModeIndex = ModeIndex_1280x960[Depth];
+ ModeIndex = ModeIndex_1280x960[Depth];
break;
case 1024:
- ModeIndex = ModeIndex_1280x1024[Depth];
+ ModeIndex = ModeIndex_1280x1024[Depth];
break;
}
break;
case 1360:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VGAEngine == SIS_315_VGA) { /* OVER1280 only? */
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
}
break;
case 1400:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
}
}
break;
case 1600:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
}
}
break;
#ifndef VB_FORBID_CRT2LCD_OVER_1600
case 1680:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ }
+ }
+ break;
+ case 1920:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+ if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+ }
+ }
+ break;
+ case 2048:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+ if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
}
}
break;
@@ -921,16 +730,17 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
return ModeIndex;
}
-USHORT
-SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
- if(VBFlags & VB_CHRONTEL) {
+ if(VBFlags2 & VB2_CHRONTEL) {
switch(HDisplay)
{
- case 512:
+ case 512:
if(VGAEngine == SIS_315_VGA) {
if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
@@ -944,27 +754,27 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 1024:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+ if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
}
break;
}
- } else if(VBFlags & VB_SISTVBRIDGE) {
+ } else if(VBFlags2 & VB2_SISTVBRIDGE) {
switch(HDisplay)
{
case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- break;
- case 512:
+ break;
+ case 400:
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 512:
if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
- (VBFlags & TV_HIVISION) ||
- ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ (VBFlags & TV_HIVISION) ||
+ ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
break;
case 640:
@@ -973,34 +783,34 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 720:
if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
- if(VDisplay == 480) {
- ModeIndex = ModeIndex_720x480[Depth];
- } else if(VDisplay == 576) {
+ if(VDisplay == 480) {
+ ModeIndex = ModeIndex_720x480[Depth];
+ } else if(VDisplay == 576) {
if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
- ModeIndex = ModeIndex_720x576[Depth];
- }
+ ModeIndex = ModeIndex_720x576[Depth];
+ }
}
break;
case 768:
if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
- if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+ if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
}
}
break;
case 800:
if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
else if(VDisplay == 480) {
- if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+ if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
ModeIndex = ModeIndex_800x480[Depth];
}
}
break;
case 960:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 600) {
+ if(VDisplay == 600) {
if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
ModeIndex = ModeIndex_960x600[Depth];
}
@@ -1009,25 +819,28 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 1024:
if(VDisplay == 768) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) {
+ if(VBFlags2 & VB2_30xBLV) {
ModeIndex = ModeIndex_1024x768[Depth];
}
} else if(VDisplay == 576) {
- if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+ if( (VBFlags & TV_HIVISION) ||
+ ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
+ ((VBFlags2 & VB2_30xBLV) &&
+ ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
ModeIndex = ModeIndex_1024x576[Depth];
}
}
break;
case 1280:
if(VDisplay == 720) {
- if((VBFlags & TV_HIVISION) ||
+ if((VBFlags & TV_HIVISION) ||
((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
- ModeIndex = ModeIndex_1280x720[Depth];
+ ModeIndex = ModeIndex_1280x720[Depth];
}
} else if(VDisplay == 1024) {
- if((VBFlags & TV_HIVISION) ||
+ if((VBFlags & TV_HIVISION) ||
((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
- ModeIndex = ModeIndex_1280x1024[Depth];
+ ModeIndex = ModeIndex_1280x1024[Depth];
}
}
break;
@@ -1036,99 +849,31 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
return ModeIndex;
}
-USHORT
-SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
- if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
+ if(HDisplay >= 1920) return 0;
switch(HDisplay)
{
- case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- break;
- case 512:
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
- break;
- case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
- else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
- break;
- case 720:
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
- break;
- case 768:
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
- break;
- case 800:
- if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
- else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
- break;
- case 848:
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
- break;
- case 856:
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
- break;
- case 960:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
- else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
- }
- break;
- case 1024:
- if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
- break;
- case 1152:
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
- else if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
- }
- break;
- case 1280:
- if(VDisplay == 768) {
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_1280x768[Depth];
- } else {
- ModeIndex = ModeIndex_310_1280x768[Depth];
- }
- } else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
- else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth];
- else if(VDisplay == 800) ModeIndex = ModeIndex_1280x800[Depth];
- else if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth];
- break;
- case 1360:
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
- break;
- case 1400:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
- }
- break;
case 1600:
- if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
- }
+ if(VDisplay == 1200) {
+ if(VGAEngine != SIS_315_VGA) return 0;
+ if(!(VBFlags2 & VB2_30xB)) return 0;
}
break;
case 1680:
- if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
- }
+ if(VDisplay == 1050) {
+ if(VGAEngine != SIS_315_VGA) return 0;
+ if(!(VBFlags2 & VB2_30xB)) return 0;
}
break;
}
- return ModeIndex;
+ return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
}
@@ -1137,83 +882,83 @@ SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int
/*********************************************/
void
-SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data)
+SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
{
- OutPortByte(port,index);
- OutPortByte(port + 1,data);
+ OutPortByte(port, index);
+ OutPortByte(port + 1, data);
}
void
-SiS_SetRegByte(SISIOADDRESS port, USHORT data)
+SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
{
- OutPortByte(port,data);
+ OutPortByte(port, data);
}
void
-SiS_SetRegShort(SISIOADDRESS port, USHORT data)
+SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
{
- OutPortWord(port,data);
+ OutPortWord(port, data);
}
void
-SiS_SetRegLong(SISIOADDRESS port, ULONG data)
+SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
{
- OutPortLong(port,data);
+ OutPortLong(port, data);
}
-UCHAR
-SiS_GetReg(SISIOADDRESS port, USHORT index)
+unsigned char
+SiS_GetReg(SISIOADDRESS port, unsigned short index)
{
- OutPortByte(port,index);
+ OutPortByte(port, index);
return(InPortByte(port + 1));
}
-UCHAR
+unsigned char
SiS_GetRegByte(SISIOADDRESS port)
{
return(InPortByte(port));
}
-USHORT
+unsigned short
SiS_GetRegShort(SISIOADDRESS port)
{
return(InPortWord(port));
}
-ULONG
+unsigned int
SiS_GetRegLong(SISIOADDRESS port)
{
return(InPortLong(port));
}
void
-SiS_SetRegANDOR(SISIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR)
+SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp = (temp & (DataAND)) | DataOR;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp = (temp & (DataAND)) | DataOR;
+ SiS_SetReg(Port, Index, temp);
}
void
-SiS_SetRegAND(SISIOADDRESS Port,USHORT Index,USHORT DataAND)
+SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp &= DataAND;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp &= DataAND;
+ SiS_SetReg(Port, Index, temp);
}
void
-SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
+SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp |= DataOR;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp |= DataOR;
+ SiS_SetReg(Port, Index, temp);
}
/*********************************************/
@@ -1221,13 +966,13 @@ SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
/*********************************************/
void
-SiS_DisplayOn(SiS_Private *SiS_Pr)
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
{
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
}
void
-SiS_DisplayOff(SiS_Private *SiS_Pr)
+SiS_DisplayOff(struct SiS_Private *SiS_Pr)
{
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
}
@@ -1238,7 +983,7 @@ SiS_DisplayOff(SiS_Private *SiS_Pr)
/*********************************************/
void
-SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
+SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
{
SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
@@ -1251,16 +996,17 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
- SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */
- SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */
- SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */
- SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
- SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */
- SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */
- SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
- SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
+ SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
+ SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
+ SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;
+ SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
+ SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
}
/*********************************************/
@@ -1268,7 +1014,7 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
/*********************************************/
static void
-SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
{
unsigned char cr5f, temp1, temp2;
@@ -1276,9 +1022,9 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* (SR11 is used for DDC and in enable/disablebridge) */
SiS_Pr->SiS_SensibleSR11 = FALSE;
SiS_Pr->SiS_MyCR63 = 0x63;
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
SiS_Pr->SiS_MyCR63 = 0x53;
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
SiS_Pr->SiS_SensibleSR11 = TRUE;
}
}
@@ -1286,43 +1032,52 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* You should use the macros, not these flags directly */
SiS_Pr->SiS_SysFlags = 0;
- if(HwInfo->jChipType == SIS_650) {
+ if(SiS_Pr->ChipType == SIS_650) {
cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
if((!temp1) || (temp2)) {
- switch(cr5f) {
+ switch(cr5f) {
case 0x80:
case 0x90:
case 0xc0:
- SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+ SiS_Pr->SiS_SysFlags |= SF_IsM650;
+ break;
case 0xa0:
case 0xb0:
case 0xe0:
- SiS_Pr->SiS_SysFlags |= SF_Is651; break;
+ SiS_Pr->SiS_SysFlags |= SF_Is651;
+ break;
}
} else {
- switch(cr5f) {
+ switch(cr5f) {
case 0x90:
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
switch(temp1) {
- case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
+ case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
}
break;
case 0xb0:
- SiS_Pr->SiS_SysFlags |= SF_Is652; break;
+ SiS_Pr->SiS_SysFlags |= SF_Is652;
+ break;
default:
- SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+ SiS_Pr->SiS_SysFlags |= SF_IsM650;
+ break;
}
}
}
- if(HwInfo->jChipType == SIS_760) {
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
- if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
+
+ if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
+ SiS_Pr->SiS_SysFlags |= SF_760LFB;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
+ SiS_Pr->SiS_SysFlags |= SF_760UMA;
+ }
}
}
@@ -1331,18 +1086,20 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
{
- switch(HwInfo->jChipType) {
+ switch(SiS_Pr->ChipType) {
+#ifdef SIS300
case SIS_300:
case SIS_540:
case SIS_630:
case SIS_730:
/* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
- * - RELOCATED VGA IO (0x20)
- * - MMIO ENABLE (0x1)
+ * - RELOCATED VGA IO ENABLED (0x20)
+ * - MMIO ENABLED (0x01)
+ * Leave other bits untouched.
*/
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
/* - Enable 2D (0x40)
* - Enable 3D (0x02)
* - Enable 3D Vertex command fetch (0x10) ?
@@ -1350,6 +1107,8 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
break;
+#endif
+#ifdef SIS315H
case SIS_315H:
case SIS_315:
case SIS_315PRO:
@@ -1362,21 +1121,30 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
case SIS_760:
case SIS_761:
case SIS_340:
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
- /* - Enable 2D (0x40)
- * - Enable 3D (0x02)
+ case XGI_40:
+ /* See above */
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ /* - Enable 3D G/L transformation engine (0x80)
+ * - Enable 2D (0x40)
* - Enable 3D vertex command fetch (0x10)
* - Enable 3D command parser (0x08)
- * - Enable 3D G/L transformation engine (0x80)
+ * - Enable 3D (0x02)
*/
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
break;
+ case XGI_20:
case SIS_550:
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ /* See above */
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
/* No 3D engine ! */
/* - Enable 2D (0x40)
+ * - disable 3D
*/
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x40);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
+ break;
+#endif
+ default:
+ break;
}
}
@@ -1384,38 +1152,40 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* HELPER: SetLVDSetc */
/*********************************************/
-static void
-SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
SiS_Pr->SiS_IF_DEF_LVDS = 0;
SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
SiS_Pr->SiS_IF_DEF_CH70xx = 0;
- SiS_Pr->SiS_IF_DEF_DSTN = 0;
- SiS_Pr->SiS_IF_DEF_FSTN = 0;
SiS_Pr->SiS_IF_DEF_CONEX = 0;
SiS_Pr->SiS_ChrontelInit = 0;
+ if(SiS_Pr->ChipType == XGI_20) return;
+
/* Check for SiS30x first */
temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
if((temp == 1) || (temp == 2)) return;
- switch(HwInfo->jChipType) {
+ switch(SiS_Pr->ChipType) {
#ifdef SIS300
case SIS_540:
case SIS_630:
case SIS_730:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- temp = (temp & 0x0E) >> 1;
- if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
- if((temp == 4) || (temp == 5)) {
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+ if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+ if((temp == 4) || (temp == 5)) {
/* Save power status (and error check) - UNUSED */
SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
SiS_Pr->SiS_IF_DEF_CH70xx = 1;
- }
+ }
break;
#endif
#ifdef SIS315H
@@ -1423,26 +1193,26 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
case SIS_650:
case SIS_740:
case SIS_330:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- temp = (temp & 0x0E) >> 1;
- if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
- break;
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+ if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+ break;
case SIS_661:
case SIS_741:
case SIS_660:
case SIS_760:
case SIS_761:
case SIS_340:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- temp = (temp & 0xe0) >> 5;
- if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
- if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */
- break;
+ case XGI_20:
+ case XGI_40:
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
+ if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+ if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */
+ break;
#endif
default:
- break;
+ break;
}
}
@@ -1451,35 +1221,55 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
{
SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
}
void
-SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
{
SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
}
/*********************************************/
+/* HELPER: Get modeflag */
+/*********************************************/
+
+unsigned short
+SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ if(SiS_Pr->UseCustomMode) {
+ return SiS_Pr->CModeFlag;
+ } else if(ModeNo <= 0x13) {
+ return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+}
+
+/*********************************************/
/* HELPER: Determine ROM usage */
/*********************************************/
BOOLEAN
-SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romversoffs, romvmaj = 1, romvmin = 0;
-
- if(HwInfo->jChipType >= SIS_761) {
- /* I very much assume 761 and 340 will use new layout */
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romversoffs, romvmaj = 1, romvmin = 0;
+
+ if(SiS_Pr->ChipType >= XGI_20) {
+ /* XGI ROMs don't qualify */
+ return FALSE;
+ } else if(SiS_Pr->ChipType >= SIS_761) {
+ /* I very much assume 761, 340 and newer will use new layout */
return TRUE;
- } else if(HwInfo->jChipType >= SIS_661) {
+ } else if(SiS_Pr->ChipType >= SIS_661) {
if((ROMAddr[0x1a] == 'N') &&
- (ROMAddr[0x1b] == 'e') &&
- (ROMAddr[0x1c] == 'w') &&
- (ROMAddr[0x1d] == 'V')) {
+ (ROMAddr[0x1b] == 'e') &&
+ (ROMAddr[0x1c] == 'w') &&
+ (ROMAddr[0x1d] == 'V')) {
return TRUE;
}
romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
@@ -1494,9 +1284,9 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
} else if(IS_SIS650740) {
if((ROMAddr[0x1a] == 'N') &&
- (ROMAddr[0x1b] == 'e') &&
- (ROMAddr[0x1c] == 'w') &&
- (ROMAddr[0x1d] == 'V')) {
+ (ROMAddr[0x1b] == 'e') &&
+ (ROMAddr[0x1c] == 'w') &&
+ (ROMAddr[0x1d] == 'V')) {
return TRUE;
}
}
@@ -1504,45 +1294,50 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
static void
-SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = 0;
SiS_Pr->SiS_UseROM = FALSE;
SiS_Pr->SiS_ROMNew = FALSE;
+ SiS_Pr->SiS_PWDOffset = 0;
- if((ROMAddr) && (HwInfo->UseROM)) {
- if(HwInfo->jChipType == SIS_300) {
- /* 300: We check if the code starts below 0x220 by
+ if(SiS_Pr->ChipType >= XGI_20) return;
+
+ if((ROMAddr) && (SiS_Pr->UseROM)) {
+ if(SiS_Pr->ChipType == SIS_300) {
+ /* 300: We check if the code starts below 0x220 by
* checking the jmp instruction at the beginning
* of the BIOS image.
*/
if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
SiS_Pr->SiS_UseROM = TRUE;
- } else if(HwInfo->jChipType < SIS_315H) {
+ } else if(SiS_Pr->ChipType < SIS_315H) {
/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
* the others do as well
*/
SiS_Pr->SiS_UseROM = TRUE;
} else {
- /* 315/330 series stick to the standard(s) */
+ /* 315/330 series stick to the standard(s) */
SiS_Pr->SiS_UseROM = TRUE;
- if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+ if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
SiS_Pr->SiS_EMIOffset = 14;
+ SiS_Pr->SiS_PWDOffset = 17;
SiS_Pr->SiS661LCD2TableSize = 36;
/* Find out about LCD data table entry size */
if((romptr = SISGETROMW(0x0102))) {
if(ROMAddr[romptr + (32 * 16)] == 0xff)
- SiS_Pr->SiS661LCD2TableSize = 32;
+ SiS_Pr->SiS661LCD2TableSize = 32;
else if(ROMAddr[romptr + (34 * 16)] == 0xff)
- SiS_Pr->SiS661LCD2TableSize = 34;
- else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94 */
- SiS_Pr->SiS661LCD2TableSize = 36;
+ SiS_Pr->SiS661LCD2TableSize = 34;
+ else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94, 2.05.00+ */
+ SiS_Pr->SiS661LCD2TableSize = 36;
else if( (ROMAddr[romptr + (38 * 16)] == 0xff) || /* 2.00.00 - 2.02.00 */
- (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00+ */
- SiS_Pr->SiS661LCD2TableSize = 38;
+ (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00 - <2.05.00 */
+ SiS_Pr->SiS661LCD2TableSize = 38; /* UMC data layout abandoned at 2.05.00 */
SiS_Pr->SiS_EMIOffset = 16;
+ SiS_Pr->SiS_PWDOffset = 19;
}
}
}
@@ -1555,9 +1350,9 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp;
+ unsigned short temp;
value &= 0x00ff;
temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
@@ -1569,9 +1364,9 @@ SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp;
+ unsigned short temp;
value &= 0x00ff;
temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
@@ -1583,22 +1378,22 @@ SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_SetSegmentReg(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
{
SiS_SetSegRegLower(SiS_Pr, value);
SiS_SetSegRegUpper(SiS_Pr, value);
}
static void
-SiS_ResetSegmentReg(SiS_Private *SiS_Pr)
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
{
SiS_SetSegmentReg(SiS_Pr, 0);
}
static void
-SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp = value >> 8;
+ unsigned short temp = value >> 8;
temp &= 0x07;
temp |= (temp << 4);
@@ -1607,15 +1402,15 @@ SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_ResetSegmentRegOver(SiS_Private *SiS_Pr)
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
{
SiS_SetSegmentRegOver(SiS_Pr, 0);
}
static void
-SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
{
- if((IS_SIS65x) || (HwInfo->jChipType >= SIS_661)) {
+ if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
SiS_ResetSegmentReg(SiS_Pr);
SiS_ResetSegmentRegOver(SiS_Pr);
}
@@ -1625,89 +1420,86 @@ SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
/* HELPER: GetVBType */
/*********************************************/
-static void
-SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_GetVBType(struct SiS_Private *SiS_Pr)
{
- USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27;
-
- SiS_Pr->SiS_VBType = 0;
-
- if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
- return;
-
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-
- if(flag > 3) return;
-
- rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-
- if(flag >= 2) {
- SiS_Pr->SiS_VBType = VB_SIS302B;
- } else if(flag == 1) {
- if(rev >= 0xC0) {
- SiS_Pr->SiS_VBType = VB_SIS301C;
- } else if(rev >= 0xB0) {
- SiS_Pr->SiS_VBType = VB_SIS301B;
- /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
- nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
- if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
- } else {
- SiS_Pr->SiS_VBType = VB_SIS301;
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
- if(rev >= 0xE0) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
- if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
- else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */
- } else if(rev >= 0xD0) {
- SiS_Pr->SiS_VBType = VB_SIS301LV;
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
- p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
- p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
- p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
- if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
- SiS_Pr->SiS_VBType |= VB_UMC;
- }
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
- }
+ unsigned short flag = 0, rev = 0, nolcd = 0;
+ unsigned short p4_0f, p4_25, p4_27;
+
+ SiS_Pr->SiS_VBType = 0;
+
+ if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+ return;
+
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+
+ if(flag > 3)
+ return;
+
+ rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+
+ if(flag >= 2) {
+ SiS_Pr->SiS_VBType = VB_SIS302B;
+ } else if(flag == 1) {
+ if(rev >= 0xC0) {
+ SiS_Pr->SiS_VBType = VB_SIS301C;
+ } else if(rev >= 0xB0) {
+ SiS_Pr->SiS_VBType = VB_SIS301B;
+ /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
+ nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
+ if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+ } else {
+ SiS_Pr->SiS_VBType = VB_SIS301;
+ }
+ }
+ if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
+ if(rev >= 0xE0) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+ if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+ else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */
+ } else if(rev >= 0xD0) {
+ SiS_Pr->SiS_VBType = VB_SIS301LV;
+ }
+ }
+ if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
+ p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
+ p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
+ if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
+ SiS_Pr->SiS_VBType |= VB_UMC;
+ }
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
+ }
}
/*********************************************/
/* HELPER: Check RAM size */
/*********************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
static BOOLEAN
-SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
- USHORT memorysize,modeflag;
-
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
- }
-
- memorysize = modeflag & MemoryInfoFlag;
- memorysize >>= MemorySizeShift; /* Get required memory size */
- memorysize++;
-
- if(AdapterMemSize < memorysize) return FALSE;
- return TRUE;
+ unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
+ unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+ unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
+
+ if(!AdapterMemSize) return TRUE;
+
+ if(AdapterMemSize < memorysize) return FALSE;
+ return TRUE;
}
#endif
@@ -1716,63 +1508,65 @@ SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
#ifdef SIS315H
-static UCHAR
-SiS_Get310DRAMType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char
+SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
{
- UCHAR data, temp;
+ unsigned char data;
if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
- data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
+ data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
} else {
- if(HwInfo->jChipType >= SIS_340) {
- /* TODO */
- data = 0;
- } if(HwInfo->jChipType >= SIS_661) {
- data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
- if(SiS_Pr->SiS_ROMNew) {
- data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
- }
- } else if(IS_SIS550650740) {
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
- } else { /* 315, 330 */
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
- if(HwInfo->jChipType == SIS_330) {
- if(data > 1) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30;
- switch(temp) {
- case 0x00: data = 1; break;
- case 0x10: data = 3; break;
- case 0x20: data = 3; break;
- case 0x30: data = 2; break;
- }
- } else {
- data = 0;
- }
- }
- }
+ if(SiS_Pr->ChipType >= XGI_20) {
+ /* Do I need this? SR17 seems to be zero anyway... */
+ data = 0;
+ } else if(SiS_Pr->ChipType >= SIS_340) {
+ /* TODO */
+ data = 0;
+ } if(SiS_Pr->ChipType >= SIS_661) {
+ if(SiS_Pr->SiS_ROMNew) {
+ data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+ } else {
+ data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+ }
+ } else if(IS_SIS550650740) {
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+ } else { /* 315, 330 */
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
+ if(SiS_Pr->ChipType == SIS_330) {
+ if(data > 1) {
+ switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
+ case 0x00: data = 1; break;
+ case 0x10: data = 3; break;
+ case 0x20: data = 3; break;
+ case 0x30: data = 2; break;
+ }
+ } else {
+ data = 0;
+ }
+ }
+ }
}
return data;
}
-static USHORT
-SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+SiS_GetMCLK(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index;
-
- index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- if(HwInfo->jChipType >= SIS_661) {
- if(SiS_Pr->SiS_ROMNew) {
- return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
- }
- return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
- } else if(index >= 4) {
- index -= 4;
- return(SiS_Pr->SiS_MCLKData_1[index].CLOCK);
- } else {
- return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
- }
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index;
+
+ index = SiS_Get310DRAMType(SiS_Pr);
+ if(SiS_Pr->ChipType >= SIS_661) {
+ if(SiS_Pr->SiS_ROMNew) {
+ return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
+ }
+ return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+ } else if(index >= 4) {
+ return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
+ } else {
+ return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+ }
}
#endif
@@ -1780,30 +1574,30 @@ SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* HELPER: ClearBuffer */
/*********************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
static void
-SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- UCHAR SISIOMEMTYPE *VideoMemoryAddress = HwInfo->pjVideoMemoryAddress;
- ULONG AdapterMemorySize = HwInfo->ulVideoMemorySize;
- USHORT SISIOMEMTYPE *pBuffer;
- int i;
-
- if(SiS_Pr->SiS_ModeType >= ModeEGA) {
- if(ModeNo > 0x13) {
- SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
- } else {
- pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
- for(i=0; i<0x4000; i++) writew(0x0000, &pBuffer[i]);
- }
- } else {
- if(SiS_Pr->SiS_ModeType < ModeCGA) {
- pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
- for(i=0; i<0x4000; i++) writew(0x0720, &pBuffer[i]);
- } else {
- SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
- }
- }
+ unsigned char SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
+ unsigned int memsize = SiS_Pr->VideoMemorySize;
+ unsigned short SISIOMEMTYPE *pBuffer;
+ int i;
+
+ if(!memaddr || !memsize) return;
+
+ if(SiS_Pr->SiS_ModeType >= ModeEGA) {
+ if(ModeNo > 0x13) {
+ SiS_SetMemory(memaddr, memsize, 0);
+ } else {
+ pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+ for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
+ }
+ } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
+ pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+ for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
+ } else {
+ SiS_SetMemory(memaddr, 0x8000, 0);
+ }
}
#endif
@@ -1812,35 +1606,36 @@ SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
BOOLEAN
-SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex)
{
- UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+ unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
- if(*ModeNo <= 0x13) {
+ if((*ModeNo) <= 0x13) {
if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
- for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
- if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break;
- if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) return FALSE;
+ for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+ if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
+ if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
}
- if(*ModeNo == 0x07) {
- if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
- /* else 350 lines */
+ if((*ModeNo) == 0x07) {
+ if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
}
- if(*ModeNo <= 0x03) {
- if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
- if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
- /* else 350 lines */
+ if((*ModeNo) <= 0x03) {
+ if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
+ if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
}
/* else 200 lines */
} else {
- for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
- if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break;
- if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return FALSE;
+ for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+ if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
+ if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
}
}
@@ -1851,10 +1646,10 @@ SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
/* HELPER: GetModePtr */
/*********************************************/
-UCHAR
-SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR index;
+ unsigned short index;
if(ModeNo <= 0x13) {
index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
@@ -1866,79 +1661,125 @@ SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
}
/*********************************************/
+/* HELPERS: Get some indices */
+/*********************************************/
+
+unsigned short
+SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+ if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+ if(UseWide == 1) {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
+ }
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
+ }
+}
+
+unsigned short
+SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+ if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+ if(UseWide == 1) {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
+ }
+}
+
+/*********************************************/
/* HELPER: LowModeTests */
/*********************************************/
static BOOLEAN
-SiS_DoLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp,temp1,temp2;
-
- if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
- return(TRUE);
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
- temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
- if((HwInfo->jChipType >= SIS_315H) ||
- (HwInfo->jChipType == SIS_300)) {
- if(temp2 == 0x55) return(FALSE);
- else return(TRUE);
- } else {
- if(temp2 != 0x55) return(TRUE);
- else {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
- return(FALSE);
- }
- }
+ unsigned short temp, temp1, temp2;
+
+ if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
+ return TRUE;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
+ temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
+ if((SiS_Pr->ChipType >= SIS_315H) ||
+ (SiS_Pr->ChipType == SIS_300)) {
+ if(temp2 == 0x55) return FALSE;
+ else return TRUE;
+ } else {
+ if(temp2 != 0x55) return TRUE;
+ else {
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
+ return FALSE;
+ }
+ }
}
static void
-SiS_SetLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- if(SiS_DoLowModeTest(SiS_Pr, ModeNo, HwInfo)) {
- SiS_Pr->SiS_SetFlag |= LowModeTests;
- }
+ if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
+ SiS_Pr->SiS_SetFlag |= LowModeTests;
+ }
}
/*********************************************/
-/* HELPER: ENABLE CRT1 */
+/* HELPER: OPEN/CLOSE CRT1 CRTC */
/*********************************************/
static void
-SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
+{
+ if(IS_SIS650) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+ if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+ } else if(IS_SIS661741660760) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+ if(!SiS_Pr->SiS_ROMNew) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+ }
+ }
+}
+
+static void
+SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
{
- if(IS_SIS650) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
- if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
- }
- } else if(IS_SIS661741660760) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
- if(!SiS_Pr->SiS_ROMNew) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
- }
- }
+#if 0 /* This locks some CRTC registers. We don't want that. */
+ unsigned short temp1 = 0, temp2 = 0;
+
+ if(IS_SIS661741660760) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ temp1 = 0xa0; temp2 = 0x08;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
+ }
+#endif
}
static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
{
- /* Enable CRT1 gating */
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+ /* Enable CRT1 gating */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
#if 0
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
- if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
- (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
- }
- }
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+ if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+ (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+ }
+ }
#endif
}
@@ -1946,57 +1787,54 @@ SiS_HandleCRT1(SiS_Private *SiS_Pr)
/* HELPER: GetColorDepth */
/*********************************************/
-USHORT
-SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
- SHORT index;
- USHORT modeflag;
-
- /* Do NOT check UseCustomMode, will skrew up FIFO */
- if(ModeNo == 0xfe) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- if(ModeNo <= 0x13)
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- index = (modeflag & ModeTypeMask) - ModeEGA;
- if(index < 0) index = 0;
- return(ColorDepth[index]);
+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+ unsigned short modeflag;
+ short index;
+
+ /* Do NOT check UseCustomMode, will skrew up FIFO */
+ if(ModeNo == 0xfe) {
+ modeflag = SiS_Pr->CModeFlag;
+ } else if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ index = (modeflag & ModeTypeMask) - ModeEGA;
+ if(index < 0) index = 0;
+ return ColorDepth[index];
}
/*********************************************/
/* HELPER: GetOffset */
/*********************************************/
-USHORT
-SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT xres, temp, colordepth, infoflag;
-
- if(SiS_Pr->UseCustomMode) {
- infoflag = SiS_Pr->CInfoFlag;
- xres = SiS_Pr->CHDisplay;
- } else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
- }
-
- colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
-
- temp = xres / 16;
- if(infoflag & InterlaceMode) temp <<= 1;
- temp *= colordepth;
- if(xres % 16) {
- colordepth >>= 1;
- temp += colordepth;
- }
-
- return(temp);
+ unsigned short xres, temp, colordepth, infoflag;
+
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ xres = SiS_Pr->CHDisplay;
+ } else {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+ xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
+ }
+
+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+ temp = xres / 16;
+ if(infoflag & InterlaceMode) temp <<= 1;
+ temp *= colordepth;
+ if(xres % 16) temp += (colordepth >> 1);
+
+ return temp;
}
/*********************************************/
@@ -2004,55 +1842,29 @@ SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR SRdata;
- USHORT i;
+ unsigned char SRdata;
+ int i;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03); /* Set SR0 */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
- SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0];
+ /* or "display off" */
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SRdata |= 0x01;
- }
- if(HwInfo->jChipType >= SIS_661) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
- }
+ /* determine whether to force x8 dotclock */
+ if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) SRdata |= 0x01;
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
- SRdata |= 0x20; /* screen off */
+ }
SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
for(i = 2; i <= 4; i++) {
- SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
}
}
@@ -2062,17 +1874,17 @@ SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR Miscdata;
+ unsigned char Miscdata;
Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
- if(HwInfo->jChipType < SIS_661) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- Miscdata |= 0x0C;
- }
+ if(SiS_Pr->ChipType < SIS_661) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ Miscdata |= 0x0C;
+ }
}
}
@@ -2084,33 +1896,34 @@ SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo
/*********************************************/
static void
-SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT StandTableIndex)
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR CRTCdata;
- USHORT i;
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* Unlock CRTC */
-
- for(i = 0; i <= 0x18; i++) {
- CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */
- }
- if(HwInfo->jChipType >= SIS_661) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- for(i = 0x13; i <= 0x14; i++) {
- CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
- }
- } else if( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision >= 0x30) ) { /* for 630S0 */
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
- }
- }
- }
+ unsigned char CRTCdata;
+ unsigned short i;
+
+ /* Unlock CRTC */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+ }
+
+ if(SiS_Pr->ChipType >= SIS_661) {
+ SiS_OpenCRTC(SiS_Pr);
+ for(i = 0x13; i <= 0x14; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+ }
+ } else if( ( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
+ }
+ }
+ }
}
/*********************************************/
@@ -2118,64 +1931,58 @@ SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR ARdata;
- USHORT i;
+ unsigned char ARdata;
+ unsigned short i;
for(i = 0; i <= 0x13; i++) {
ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
-#if 0
- if((i <= 0x0f) || (i == 0x11)) {
- if(ds:489 & 0x08) {
- continue;
- }
- }
-#endif
+
if(i == 0x13) {
- /* Pixel shift. If screen on LCD or TV is shifted left or right,
- * this might be the cause.
- */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata=0;
- }
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
- }
- }
- }
- if(HwInfo->jChipType >= SIS_661) {
+ /* Pixel shift. If screen on LCD or TV is shifted left or right,
+ * this might be the cause.
+ */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
+ }
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+ }
+ }
+ }
+ if(SiS_Pr->ChipType >= SIS_661) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(IS_SIS550650740660) {
- /* 315, 330 don't do this */
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
- } else {
- ARdata = 0;
- }
+ /* 315, 330 don't do this */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+ } else {
+ ARdata = 0;
+ }
}
} else {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
}
- }
+ }
}
- SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */
+ SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */
}
- SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */
+
+ SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */
SiS_GetRegByte(SiS_Pr->SiS_P3da);
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */
SiS_GetRegByte(SiS_Pr->SiS_P3da);
}
@@ -2184,10 +1991,10 @@ SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
/*********************************************/
static void
-SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR GRdata;
- USHORT i;
+ unsigned char GRdata;
+ unsigned short i;
for(i = 0; i <= 0x08; i++) {
GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
@@ -2205,22 +2012,22 @@ SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
/*********************************************/
static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT i;
+ unsigned short i;
- for(i = 0x0A; i <= 0x0E; i++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
- }
+ for(i = 0x0A; i <= 0x0E; i++) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
+ }
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
- if(ModeNo <= 0x13) {
- if(ModeNo == 0x06 || ModeNo >= 0x0e) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+ if(ModeNo <= 0x13) {
+ if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+ }
+ }
+ }
}
/*********************************************/
@@ -2228,32 +2035,24 @@ SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
static void
-SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H) {
- if(HwInfo->jChipType < SIS_661) {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_661) {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
}
} else {
if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
- (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
+ (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
return;
}
}
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
- }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
- }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
@@ -2264,19 +2063,19 @@ SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
{
- USHORT sync;
+ unsigned short sync;
- if(SiS_Pr->UseCustomMode) {
- sync = SiS_Pr->CInfoFlag >> 8;
- } else {
- sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
- }
+ if(SiS_Pr->UseCustomMode) {
+ sync = SiS_Pr->CInfoFlag >> 8;
+ } else {
+ sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
+ }
- sync &= 0xC0;
- sync |= 0x2f;
- SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
+ sync &= 0xC0;
+ sync |= 0x2f;
+ SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
}
/*********************************************/
@@ -2284,72 +2083,67 @@ SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
/*********************************************/
static void
-SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- UCHAR index;
- USHORT temp,i,j,modeflag;
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* unlock cr0-7 */
-
- if(SiS_Pr->UseCustomMode) {
-
- modeflag = SiS_Pr->CModeFlag;
-
- for(i=0,j=0;i<=7;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x10;i<=10;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x15;i<=12;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x0A;i<=15;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
- }
-
- temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
- temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
- } else {
-
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- for(i=0,j=0;i<=7;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x10;i<=10;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x15;i<=12;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x0A;i<=15;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
-
- temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
- temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
- }
-
- if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+ unsigned short temp, i, j, modeflag;
+ unsigned char *crt1data = NULL;
+
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->UseCustomMode) {
+
+ crt1data = &SiS_Pr->CCRT1CRTC[0];
+
+ } else {
+
+ temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
+
+ /* Alternate for 1600x1200 LCDA */
+ if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
+
+ crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
+
+ }
+
+ /* unlock cr0-7 */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0, j = 0; i <= 7; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x10; i <= 10; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x15; i <= 12; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x0A; i <= 15; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
+ }
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
+
+ temp = (crt1data[16] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
+
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+ }
+
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == XGI_20) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
+ if(!(temp = crt1data[5] & 0x1f)) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
+ temp = (crt1data[16] >> 5) + 3;
+ if(temp > 7) temp -= 7;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
+ }
+#endif
}
/*********************************************/
@@ -2359,33 +2153,32 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT temp, DisplayUnit, infoflag;
+ unsigned short temp, DisplayUnit, infoflag;
if(SiS_Pr->UseCustomMode) {
infoflag = SiS_Pr->CInfoFlag;
} else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
}
- DisplayUnit = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
+ DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
temp = (DisplayUnit >> 8) & 0x0f;
SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
- temp = DisplayUnit & 0xFF;
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,temp);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
if(infoflag & InterlaceMode) DisplayUnit >>= 1;
DisplayUnit <<= 5;
- temp = (DisplayUnit & 0xff00) >> 8;
+ temp = (DisplayUnit >> 8) + 1;
if(DisplayUnit & 0xff) temp++;
- temp++;
+ if(SiS_Pr->ChipType == XGI_20) {
+ if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
+ }
SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
}
@@ -2394,39 +2187,49 @@ SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT index=0, clka, clkb;
-
- if(SiS_Pr->UseCustomMode) {
- clka = SiS_Pr->CSR2B;
- clkb = SiS_Pr->CSR2C;
- } else {
- index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
- clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
- } else {
- clka = SiS_Pr->SiS_VCLKData[index].SR2B;
- clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
- }
- }
-
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
- }
-
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,clka);
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,clkb);
-
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
- }
+ unsigned short index = 0, clka, clkb;
+
+ if(SiS_Pr->UseCustomMode) {
+ clka = SiS_Pr->CSR2B;
+ clkb = SiS_Pr->CSR2C;
+ } else {
+ index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+ (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ /* Alternate for 1600x1200 LCDA */
+ if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
+ clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
+ clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
+ } else {
+ clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+ clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+ }
+ }
+
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+
+ if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
+ if(SiS_Pr->ChipType == XGI_20) {
+ unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+ if(mf & HalfDCLK) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
+ clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
+ clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+ }
+ }
+#endif
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+ }
}
/*********************************************/
@@ -2434,415 +2237,358 @@ SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS300
-static USHORT
-SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key)
+void
+SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+ unsigned short *idx2)
+{
+ unsigned short temp1, temp2;
+ static const unsigned char ThTiming[8] = {
+ 1, 2, 2, 3, 0, 1, 1, 2
+ };
+
+ temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
+ (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
+ (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
+ (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
+ (*idx1) <<= 1;
+}
+
+static unsigned short
+SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
+{
+ static const unsigned char ThLowA[8 * 3] = {
+ 61, 3,52, 5,68, 7,100,11,
+ 43, 3,42, 5,54, 7, 78,11,
+ 34, 3,37, 5,47, 7, 67,11
+ };
+
+ return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
+}
+
+unsigned short
+SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
+{
+ static const unsigned char ThLowB[8 * 3] = {
+ 81, 4,72, 6,88, 8,120,12,
+ 55, 4,54, 6,66, 8, 90,12,
+ 42, 4,45, 6,55, 8, 75,12
+ };
+
+ return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
+}
+
+static unsigned short
+SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
+ unsigned short colordepth, unsigned short key)
{
- const UCHAR ThLowA[] = { 61, 3,52, 5,68, 7,100,11,
- 43, 3,42, 5,54, 7, 78,11,
- 34, 3,37, 5,47, 7, 67,11 };
-
- const UCHAR ThLowB[] = { 81, 4,72, 6,88, 8,120,12,
- 55, 4,54, 6,66, 8, 90,12,
- 42, 4,45, 6,55, 8, 75,12 };
-
- const UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 };
-
- USHORT tempah, tempal, tempcl, tempbx, temp;
- ULONG longtemp;
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempah &= 0x62;
- tempah >>= 1;
- tempal = tempah;
- tempah >>= 3;
- tempal |= tempah;
- tempal &= 0x07;
- tempcl = ThTiming[tempal];
- tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempbx >>= 6;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- tempah >>= 4;
- tempah &= 0x0c;
- tempbx |= tempah;
- tempbx <<= 1;
- if(key == 0) {
- tempal = ThLowA[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowA[tempbx];
- } else {
- tempal = ThLowB[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowB[tempbx];
- }
- longtemp = tempal * VCLK * colordepth;
- temp = longtemp % (MCLK * 16);
- longtemp /= (MCLK * 16);
- if(temp) longtemp++;
- return((USHORT)longtemp);
+ unsigned short idx1, idx2;
+ unsigned int longtemp = VCLK * colordepth;
+
+ SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
+
+ if(key == 0) {
+ longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
+ } else {
+ longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
+ }
+ idx1 = longtemp % (MCLK * 16);
+ longtemp /= (MCLK * 16);
+ if(idx1) longtemp++;
+ return (unsigned short)longtemp;
}
-static USHORT
-SiS_CalcDelay(SiS_Private *SiS_Pr, USHORT VCLK, USHORT colordepth, USHORT MCLK)
+static unsigned short
+SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
+ unsigned short colordepth, unsigned short MCLK)
{
- USHORT tempax, tempbx;
-
- tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
- tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
- if(tempax < 4) tempax = 4;
- tempax -= 4;
- if(tempbx < tempax) tempbx = tempax;
- return(tempbx);
+ unsigned short temp1, temp2;
+
+ temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
+ temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
+ if(temp1 < 4) temp1 = 4;
+ temp1 -= 4;
+ if(temp2 < temp1) temp2 = temp1;
+ return temp2;
}
static void
-SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo,
- USHORT RefreshRateTableIndex)
+SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short ThresholdLow = 0;
+ unsigned short temp, index, VCLK, MCLK, colorth;
+ static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
+
+ if(ModeNo > 0x13) {
+
+ /* Get VCLK */
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+
+ /* Get half colordepth */
+ colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+ /* Get MCLK */
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
+ MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
+
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
+
+ do {
+ ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
+ if(ThresholdLow < 0x13) break;
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
+ ThresholdLow = 0x13;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
+ if(!temp) break;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
+ } while(0);
+
+ } else ThresholdLow = 2;
+
+ /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+ temp = (ThresholdLow << 4) | 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
+
+ temp = (ThresholdLow & 0x10) << 1;
+ if(ModeNo > 0x13) temp |= 0x40;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
+
+ /* What is this? */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+ /* Write CRT/CPU threshold high */
+ temp = ThresholdLow + 3;
+ if(temp > 0x0f) temp = 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+}
+
+unsigned short
+SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
{
- USHORT ThresholdLow = 0;
- USHORT index, VCLK, MCLK, colorth=0;
- USHORT tempah, temp;
-
- if(ModeNo > 0x13) {
-
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
- }
-
- switch (SiS_Pr->SiS_ModeType - ModeEGA) { /* Get half colordepth */
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- }
-
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- tempah &= 0xc3;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah);
-
- do {
- ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK);
- ThresholdLow++;
- if(ThresholdLow < 0x13) break;
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
- ThresholdLow = 0x13;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempah >>= 6;
- if(!(tempah)) break;
- tempah--;
- tempah <<= 6;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah);
- } while(0);
-
- } else ThresholdLow = 2;
-
- /* Write CRT/CPU threshold low, CRT/Engine threshold high */
- temp = (ThresholdLow << 4) | 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
-
- temp = (ThresholdLow & 0x10) << 1;
- if(ModeNo > 0x13) temp |= 0x40;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
-
- /* What is this? */
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
-
- /* Write CRT/CPU threshold high */
- temp = ThresholdLow + 3;
- if(temp > 0x0f) temp = 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+ static const unsigned char LatencyFactor[] = {
+ 97, 88, 86, 79, 77, 0, /* 64 bit BQ=2 */
+ 0, 87, 85, 78, 76, 54, /* 64 bit BQ=1 */
+ 97, 88, 86, 79, 77, 0, /* 128 bit BQ=2 */
+ 0, 79, 77, 70, 68, 48, /* 128 bit BQ=1 */
+ 80, 72, 69, 63, 61, 0, /* 64 bit BQ=2 */
+ 0, 70, 68, 61, 59, 37, /* 64 bit BQ=1 */
+ 86, 77, 75, 68, 66, 0, /* 128 bit BQ=2 */
+ 0, 68, 66, 59, 57, 37 /* 128 bit BQ=1 */
+ };
+ static const unsigned char LatencyFactor730[] = {
+ 69, 63, 61,
+ 86, 79, 77,
+ 103, 96, 94,
+ 120,113,111,
+ 137,130,128
+ };
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ return (unsigned short)LatencyFactor730[index];
+ } else {
+ return (unsigned short)LatencyFactor[index];
+ }
}
-static USHORT
-SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR key, PSIS_HW_INFO HwInfo)
+static unsigned short
+SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
{
- USHORT data,index;
- const UCHAR LatencyFactor[] = {
- 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
- 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
- 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
- 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
- 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
- 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
- 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
- 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */
- };
- const UCHAR LatencyFactor730[] = {
- 69, 63, 61,
- 86, 79, 77,
- 103, 96, 94,
- 120,113,111,
- 137,130,128, /* --- Table ends with this entry, data below */
- 137,130,128, /* to avoid using illegal values */
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- };
-
- if(HwInfo->jChipType == SIS_730) {
- index = ((key & 0x0f) * 3) + ((key & 0xC0) >> 6);
- data = LatencyFactor730[index];
- } else {
- index = (key & 0xE0) >> 5;
- if(key & 0x10) index +=6;
- if(!(key & 0x01)) index += 24;
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(data & 0x0080) index += 12;
- data = LatencyFactor[index];
- }
- return(data);
+ unsigned short index;
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
+ } else {
+ index = (key & 0xe0) >> 5;
+ if(key & 0x10) index += 6;
+ if(!(key & 0x01)) index += 24;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
+ }
+ return SiS_GetLatencyFactor630(SiS_Pr, index);
}
static void
-SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, USHORT ModeNo,
- PSIS_HW_INFO HwInfo,
- USHORT RefreshRateTableIndex)
+SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex)
{
- USHORT i,index,data,VCLK,MCLK,colorth=0;
- ULONG B,eax,bl,data2;
- USHORT ThresholdLow=0;
- UCHAR FQBQData[]= {
- 0x01,0x21,0x41,0x61,0x81,
- 0x31,0x51,0x71,0x91,0xb1,
- 0x00,0x20,0x40,0x60,0x80,
- 0x30,0x50,0x70,0x90,0xb0,
- 0xFF
- };
- UCHAR FQBQData730[]= {
- 0x34,0x74,0xb4,
- 0x23,0x63,0xa3,
- 0x12,0x52,0x92,
- 0x01,0x41,0x81,
- 0x00,0x40,0x80,
- 0xff
- };
-
- i=0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
- }
-
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
-
- data2 = SiS_Pr->SiS_ModeType - ModeEGA; /* Get half colordepth */
- switch (data2) {
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- }
-
- if(HwInfo->jChipType == SIS_730) {
-
- do {
- B = SiS_CalcDelay2(SiS_Pr, FQBQData730[i], HwInfo) * VCLK * colorth;
- bl = B / (MCLK * 16);
-
- if(B == bl * 16 * MCLK) {
- bl = bl + 1;
- } else {
- bl = bl + 2;
- }
-
- if(bl > 0x13) {
- if(FQBQData730[i+1] == 0xFF) {
- ThresholdLow = 0x13;
- break;
- }
- i++;
- } else {
- ThresholdLow = bl;
- break;
- }
- } while(FQBQData730[i] != 0xFF);
+ unsigned short ThresholdLow = 0;
+ unsigned short i, data, VCLK, MCLK16, colorth = 0;
+ unsigned int templ, datal;
+ const unsigned char *queuedata = NULL;
+ static const unsigned char FQBQData[21] = {
+ 0x01,0x21,0x41,0x61,0x81,
+ 0x31,0x51,0x71,0x91,0xb1,
+ 0x00,0x20,0x40,0x60,0x80,
+ 0x30,0x50,0x70,0x90,0xb0,
+ 0xff
+ };
+ static const unsigned char FQBQData730[16] = {
+ 0x34,0x74,0xb4,
+ 0x23,0x63,0xa3,
+ 0x12,0x52,0x92,
+ 0x01,0x41,0x81,
+ 0x00,0x40,0x80,
+ 0xff
+ };
+ static const unsigned short colortharray[6] = {
+ 1, 1, 2, 2, 3, 4
+ };
- } else {
+ i = 0;
- do {
- B = SiS_CalcDelay2(SiS_Pr, FQBQData[i], HwInfo) * VCLK * colorth;
- bl = B / (MCLK * 16);
+ if(ModeNo > 0x13) {
- if(B == bl * 16 * MCLK) {
- bl = bl + 1;
- } else {
- bl = bl + 2;
- }
+ /* Get VCLK */
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
+ }
- if(bl > 0x13) {
- if(FQBQData[i+1] == 0xFF) {
- ThresholdLow = 0x13;
- break;
- }
- i++;
- } else {
- ThresholdLow = bl;
- break;
- }
- } while(FQBQData[i] != 0xFF);
- }
- }
- else {
- if(HwInfo->jChipType == SIS_730) {
- } else {
- i = 9;
- }
- ThresholdLow = 0x02;
- }
+ /* Get MCLK * 16 */
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
+ MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
+
+ /* Get half colordepth */
+ colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ queuedata = &FQBQData730[0];
+ } else {
+ queuedata = &FQBQData[0];
+ }
+
+ do {
+ templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
+
+ datal = templ % MCLK16;
+ templ = (templ / MCLK16) + 1;
+ if(datal) templ++;
+
+ if(templ > 0x13) {
+ if(queuedata[i + 1] == 0xFF) {
+ ThresholdLow = 0x13;
+ break;
+ }
+ i++;
+ } else {
+ ThresholdLow = templ;
+ break;
+ }
+ } while(queuedata[i] != 0xFF);
+
+ } else {
+
+ if(SiS_Pr->ChipType != SIS_730) i = 9;
+ ThresholdLow = 0x02;
+
+ }
+
+ /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+ data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+
+ data = (ThresholdLow & 0x10) << 1;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+
+ /* What is this? */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+ /* Write CRT/CPU threshold high (gap = 3) */
+ data = ThresholdLow + 3;
+ if(data > 0x0f) data = 0x0f;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
/* Write foreground and background queue */
- if(HwInfo->jChipType == SIS_730) {
-
- data2 = FQBQData730[i];
- data2 = (data2 & 0xC0) >> 5;
- data2 <<= 8;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xfffff9ff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
+#ifdef SIS_LINUX_KERNEL
+ templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
#else
- /* We use pci functions X offers. We use pcitag 0, because
- * we want to read/write to the host bridge (which is always
- * 00:00.0 on 630, 730 and 540), not the VGA device.
- */
- eax = pciReadLong(0x00000000, 0x50);
- eax &= 0xfffff9ff;
- eax |= data2;
- pciWriteLong(0x00000000, 0x50, eax);
+ templ = pciReadLong(0x00000000, 0x50);
#endif
- /* Write GUI grant timer (PCI config 0xA3) */
- data2 = FQBQData730[i] << 8;
- data2 = (data2 & 0x0f00) | ((data2 & 0x3000) >> 8);
- data2 <<= 20;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0x00ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
-#else
- eax = pciReadLong(0x00000000, 0xA0);
- eax &= 0x00ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0xA0, eax);
-#endif
+ if(SiS_Pr->ChipType == SIS_730) {
- } else {
+ templ &= 0xfffff9ff;
+ templ |= ((queuedata[i] & 0xc0) << 3);
- data2 = FQBQData[i];
- data2 = (data2 & 0xf0) >> 4;
- data2 <<= 24;
+ } else {
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xf0ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
-#else
- eax = pciReadLong(0x00000000, 0x50);
- eax &= 0xf0ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0x50, eax);
-#endif
+ templ &= 0xf0ffffff;
+ if( (ModeNo <= 0x13) &&
+ (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
+ templ |= 0x0b000000;
+ } else {
+ templ |= ((queuedata[i] & 0xf0) << 20);
+ }
+
+ }
- /* Write GUI grant timer (PCI config 0xA3) */
- data2 = FQBQData[i];
- data2 &= 0x0f;
- data2 <<= 24;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xf0ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
+ templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
#else
- eax = pciReadLong(0x00000000, 0xA0);
- eax &= 0xf0ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0xA0, eax);
+ pciWriteLong(0x00000000, 0x50, templ);
+ templ = pciReadLong(0x00000000, 0xA0);
#endif
- }
+ /* GUI grant timer (PCI config 0xA3) */
+ if(SiS_Pr->ChipType == SIS_730) {
+
+ templ &= 0x00ffffff;
+ datal = queuedata[i] << 8;
+ templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
- /* Write CRT/CPU threshold low, CRT/Engine threshold high */
- data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+ } else {
- data = (ThresholdLow & 0x10) << 1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+ templ &= 0xf0ffffff;
+ templ |= ((queuedata[i] & 0x0f) << 24);
- /* What is this? */
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+ }
- /* Write CRT/CPU threshold high (gap = 3) */
- data = ThresholdLow + 3;
- if(data > 0x0f) data = 0x0f;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
-}
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
+#else
+ pciWriteLong(0x00000000, 0xA0, templ);
#endif
+}
+#endif /* SIS300 */
#ifdef SIS315H
static void
-SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT modeflag;
-
- /* disable auto-threshold */
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
-
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
- if(ModeNo > 0x13) {
- if(HwInfo->jChipType >= SIS_661) {
- if(!(modeflag & HalfDCLK)) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
- }
- } else {
- if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
- }
- }
- }
+ unsigned short modeflag;
+
+ /* disable auto-threshold */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
+
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->ChipType >= XGI_20) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ } else if(SiS_Pr->ChipType >= SIS_661) {
+ if(!(modeflag & HalfDCLK)) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ }
+ } else {
+ if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ }
+ }
+ }
}
#endif
@@ -2851,385 +2597,370 @@ SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetVCLKState(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT RefreshRateTableIndex,
- USHORT ModeIdIndex)
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
{
- USHORT data=0, VCLK=0, index=0;
+ unsigned short data = 0, VCLK = 0, index = 0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- }
- }
-
- if(HwInfo->jChipType < SIS_315H) {
-
- if(VCLK > 150) data |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
-
- data = 0x00;
- if(VCLK >= 150) data |= 0x08;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+ }
- } else {
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ if(VCLK > 150) data |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
- if(VCLK >= 166) data |= 0x0c;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+ data = 0x00;
+ if(VCLK >= 150) data |= 0x08;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+#endif
+ } else if(SiS_Pr->ChipType < XGI_20) {
+#ifdef SIS315H
+ if(VCLK >= 166) data |= 0x0c;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
- if(VCLK >= 166) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
- }
- }
+ if(VCLK >= 166) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ if(VCLK >= 200) data |= 0x0c;
+ if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+ if(SiS_Pr->ChipType != XGI_20) {
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
+ if(VCLK < 200) data |= 0x10;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
+ }
+#endif
+ }
- /* DAC speed */
- if(HwInfo->jChipType >= SIS_661) {
+ /* DAC speed */
+ if(SiS_Pr->ChipType >= SIS_661) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
- } else {
+ } else {
- data = 0x03;
- if((VCLK >= 135) && (VCLK < 160)) data = 0x02;
- else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
- else if(VCLK >= 260) data = 0x00;
+ data = 0x03;
+ if(VCLK >= 260) data = 0x00;
+ else if(VCLK >= 160) data = 0x01;
+ else if(VCLK >= 135) data = 0x02;
- if(HwInfo->jChipType == SIS_540) {
- if((VCLK == 203) || (VCLK < 234)) data = 0x02;
- }
+ if(SiS_Pr->ChipType == SIS_540) {
+ if((VCLK == 203) || (VCLK < 234)) data = 0x02;
+ }
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
- } else {
- if(HwInfo->jChipType > SIS_315PRO) {
- if(ModeNo > 0x13) data &= 0xfc;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
- }
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+ } else {
+ if(SiS_Pr->ChipType > SIS_315PRO) {
+ if(ModeNo > 0x13) data &= 0xfc;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
+ }
- }
+ }
}
static void
-SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT data,infoflag=0,modeflag;
- USHORT resindex,xres;
+ unsigned short data, infoflag = 0, modeflag, resindex;
#ifdef SIS315H
- USHORT data2,data3;
- ULONG longdata;
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short data2, data3;
#endif
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- infoflag = SiS_Pr->CInfoFlag;
- xres = SiS_Pr->CHDisplay;
- } else {
- resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(ModeNo > 0x13) {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
- } else {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
- }
- }
-
- /* Disable DPMS */
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
-
- data = 0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->SiS_ModeType > ModeEGA) {
- data |= 0x02;
- data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
- }
- if(infoflag & InterlaceMode) data |= 0x20;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
-
- if(HwInfo->jChipType != SIS_300) {
- data = 0;
- if(infoflag & InterlaceMode) {
- if(xres <= 800) data = 0x0020;
- else if(xres <= 1024) data = 0x0035;
- else data = 0x0048;
- }
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
- }
-
- if(modeflag & HalfDCLK) {
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
- }
-
- data = 0;
- if(modeflag & LineCompareOff) data = 0x08;
- if(HwInfo->jChipType == SIS_300) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
- if(SiS_Pr->SiS_ModeType == ModeEGA) {
- if(ModeNo > 0x13) {
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
- }
- }
- }
-
- if(HwInfo->jChipType >= SIS_661) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ } else {
+ resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ if(ModeNo > 0x13) {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+ }
+ }
+
+ /* Disable DPMS */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
+
+ data = 0;
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->SiS_ModeType > ModeEGA) {
+ data |= 0x02;
+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+ }
+ if(infoflag & InterlaceMode) data |= 0x20;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
+
+ if(SiS_Pr->ChipType != SIS_300) {
+ data = 0;
+ if(infoflag & InterlaceMode) {
+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+ int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
+ ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
+ int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
+ ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
+ data = hrs - (hto >> 1) + 3;
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
+ }
+
+ if(modeflag & HalfDCLK) {
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
+ }
+
+ data = 0;
+ if(modeflag & LineCompareOff) data = 0x08;
+ if(SiS_Pr->ChipType == SIS_300) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
+ } else {
+ if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
+ if(SiS_Pr->SiS_ModeType == ModeEGA) {
+ if(ModeNo > 0x13) {
+ data |= 0x40;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
+ }
#ifdef SIS315H
- if(HwInfo->jChipType == SIS_315PRO) {
-
- data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- data = SiS_Pr->SiS_SR15[2][data];
- if(SiS_Pr->SiS_ModeType == ModeText) {
- data &= 0xc7;
- } else {
- data2 = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- data2 >>= 1;
- if(infoflag & InterlaceMode) data2 >>= 1;
- data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
- if(!data3) data3++;
- data2 /= data3;
- if(data2 >= 0x50) {
- data &= 0x0f;
- data |= 0x50;
- }
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-
- } else if( (HwInfo->jChipType == SIS_330) ||
- ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
-
- data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- if(HwInfo->jChipType == SIS_330) {
- data = SiS_Pr->SiS_SR15[2][data];
- } else {
- if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6];
- else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
- else data = 0xba;
- }
- if(SiS_Pr->SiS_ModeType <= ModeEGA) {
- data &= 0xc7;
- } else {
- if(SiS_Pr->UseCustomMode) {
- data2 = SiS_Pr->CSRClock;
- } else {
- data2 = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+ }
- data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
- if(data3) data2 *= data3;
-
- longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
-
- data2 = longdata / data2;
-
- if(HwInfo->jChipType == SIS_330) {
- if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
- if (data2 >= 0x19c) data = 0xba;
- else if(data2 >= 0x140) data = 0x7a;
- else if(data2 >= 0x101) data = 0x3a;
- else if(data2 >= 0xf5) data = 0x32;
- else if(data2 >= 0xe2) data = 0x2a;
- else if(data2 >= 0xc4) data = 0x22;
- else if(data2 >= 0xac) data = 0x1a;
- else if(data2 >= 0x9e) data = 0x12;
- else if(data2 >= 0x8e) data = 0x0a;
- else data = 0x02;
- } else {
- if(data2 >= 0x127) data = 0xba;
- else data = 0x7a;
- }
- } else { /* 760+LFB */
- if (data2 >= 0x190) data = 0xba;
- else if(data2 >= 0xff) data = 0x7a;
- else if(data2 >= 0xd3) data = 0x3a;
- else if(data2 >= 0xa9) data = 0x1a;
- else if(data2 >= 0x93) data = 0x0a;
- else data = 0x02;
- }
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
- } else if(HwInfo->jChipType == SIS_340) {
- /* TODO */
- }
+ if(SiS_Pr->ChipType == SIS_315PRO) {
+
+ data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
+ if(SiS_Pr->SiS_ModeType == ModeText) {
+ data &= 0xc7;
+ } else {
+ data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
+ if(infoflag & InterlaceMode) data2 >>= 1;
+ data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+ if(data3) data2 /= data3;
+ if(data2 >= 0x50) {
+ data &= 0x0f;
+ data |= 0x50;
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+ } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
+
+ data = SiS_Get310DRAMType(SiS_Pr);
+ if(SiS_Pr->ChipType == SIS_330) {
+ data = SiS_Pr->SiS_SR15[(2 * 4) + data];
+ } else {
+ if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6];
+ else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+ else data = 0xba;
+ }
+ if(SiS_Pr->SiS_ModeType <= ModeEGA) {
+ data &= 0xc7;
+ } else {
+ if(SiS_Pr->UseCustomMode) {
+ data2 = SiS_Pr->CSRClock;
+ } else {
+ data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+ data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
+ }
+
+ data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+ if(data3) data2 *= data3;
+
+ data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
+
+ if(SiS_Pr->ChipType == SIS_330) {
+ if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+ if (data2 >= 0x19c) data = 0xba;
+ else if(data2 >= 0x140) data = 0x7a;
+ else if(data2 >= 0x101) data = 0x3a;
+ else if(data2 >= 0xf5) data = 0x32;
+ else if(data2 >= 0xe2) data = 0x2a;
+ else if(data2 >= 0xc4) data = 0x22;
+ else if(data2 >= 0xac) data = 0x1a;
+ else if(data2 >= 0x9e) data = 0x12;
+ else if(data2 >= 0x8e) data = 0x0a;
+ else data = 0x02;
+ } else {
+ if(data2 >= 0x127) data = 0xba;
+ else data = 0x7a;
+ }
+ } else { /* 76x+LFB */
+ if (data2 >= 0x190) data = 0xba;
+ else if(data2 >= 0xff) data = 0x7a;
+ else if(data2 >= 0xd3) data = 0x3a;
+ else if(data2 >= 0xa9) data = 0x1a;
+ else if(data2 >= 0x93) data = 0x0a;
+ else data = 0x02;
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+ }
+ /* XGI: Nothing. */
+ /* TODO: Check SiS340 */
#endif
- data = 0x60;
- if(SiS_Pr->SiS_ModeType != ModeText) {
- data ^= 0x60;
- if(SiS_Pr->SiS_ModeType != ModeEGA) {
- data ^= 0xA0;
- }
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
+ data = 0x60;
+ if(SiS_Pr->SiS_ModeType != ModeText) {
+ data ^= 0x60;
+ if(SiS_Pr->SiS_ModeType != ModeEGA) {
+ data ^= 0xA0;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
- SiS_SetVCLKState(SiS_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex);
+ SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
- }
- }
+ if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
+ (SiS_Pr->ChipType == XGI_40)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
+ }
+ } else if(SiS_Pr->ChipType == XGI_20) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
+ }
#endif
}
-/*********************************************/
-/* LOAD DAC */
-/*********************************************/
-
-#if 0
+#ifdef SIS315H
static void
-SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port)
+SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
{
+#if 0
+ /* TODO: Find out about IOAddress2 */
+ SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
+ SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
+ SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
int i;
- OutPortByte(port, 0);
- port++;
- for (i=0; i < (256 * 3); i++) {
- OutPortByte(port, 0);
+ if((SiS_Pr->ChipRevision != 0) ||
+ (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
+ return;
+
+ for(i = 0; i <= 4; i++) { /* SR00 - SR04 */
+ SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
}
+ for(i = 0; i <= 8; i++) { /* GR00 - GR08 */
+ SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
+ }
+ SiS_SetReg(P2_3c4,0x05,0x86);
+ SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06)); /* SR06 */
+ SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21)); /* SR21 */
+ SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc)); /* MISC */
+ SiS_SetReg(P2_3c4,0x05,0x00);
+#endif
}
#endif
+/*********************************************/
+/* LOAD DAC */
+/*********************************************/
+
static void
-SiS_WriteDAC(SiS_Private *SiS_Pr, SISIOADDRESS DACData, USHORT shiftflag,
- USHORT dl, USHORT ah, USHORT al, USHORT dh)
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
+ unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
{
- USHORT temp,bh,bl;
-
- bh = ah;
- bl = al;
- if(dl != 0) {
- temp = bh;
- bh = dh;
- dh = temp;
- if(dl == 1) {
- temp = bl;
- bl = dh;
- dh = temp;
- } else {
- temp = bl;
- bl = bh;
- bh = temp;
- }
- }
- if(shiftflag) {
- dh <<= 2;
- bh <<= 2;
- bl <<= 2;
- }
- SiS_SetRegByte(DACData,(USHORT)dh);
- SiS_SetRegByte(DACData,(USHORT)bh);
- SiS_SetRegByte(DACData,(USHORT)bl);
+ unsigned short d1, d2, d3;
+
+ switch(dl) {
+ case 0: d1 = dh; d2 = ah; d3 = al; break;
+ case 1: d1 = ah; d2 = al; d3 = dh; break;
+ default: d1 = al; d2 = dh; d3 = ah;
+ }
+ SiS_SetRegByte(DACData, (d1 << shiftflag));
+ SiS_SetRegByte(DACData, (d2 << shiftflag));
+ SiS_SetRegByte(DACData, (d3 << shiftflag));
}
void
-SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT data,data2;
- USHORT time,i,j,k,m,n,o;
- USHORT si,di,bx,dl,al,ah,dh;
- USHORT shiftflag;
+ unsigned short data, data2, time, i, j, k, m, n, o;
+ unsigned short si, di, bx, sf;
SISIOADDRESS DACAddr, DACData;
- const USHORT *table = NULL;
+ const unsigned char *table = NULL;
- if(ModeNo <= 0x13) {
- data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- if(SiS_Pr->UseCustomMode) {
- data = SiS_Pr->CModeFlag;
- } else {
- data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
- }
+ data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
- data &= DACInfoFlag;
- time = 64;
- if(data == 0x00) table = SiS_MDA_DAC;
- if(data == 0x08) table = SiS_CGA_DAC;
- if(data == 0x10) table = SiS_EGA_DAC;
- if(data == 0x18) {
+ j = time = 64;
+ if(data == 0x00) table = SiS_MDA_DAC;
+ else if(data == 0x08) table = SiS_CGA_DAC;
+ else if(data == 0x10) table = SiS_EGA_DAC;
+ else if(data == 0x18) {
+ j = 16;
time = 256;
table = SiS_VGA_DAC;
}
- if(time == 256) j = 16;
- else j = time;
if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */
(SiS_Pr->SiS_VBType & VB_NoLCD) ) ||
(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */
(!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
DACAddr = SiS_Pr->SiS_P3c8;
DACData = SiS_Pr->SiS_P3c9;
- shiftflag = 0;
- SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
+ sf = 0;
} else {
- shiftflag = 1;
DACAddr = SiS_Pr->SiS_Part5Port;
DACData = SiS_Pr->SiS_Part5Port + 1;
+ sf = 2;
}
SiS_SetRegByte(DACAddr,0x00);
- for(i=0; i<j; i++) {
+ for(i = 0; i < j; i++) {
data = table[i];
- for(k=0; k<3; k++) {
+ for(k = 0; k < 3; k++) {
data2 = 0;
- if(data & 0x01) data2 = 0x2A;
+ if(data & 0x01) data2 += 0x2A;
if(data & 0x02) data2 += 0x15;
- if(shiftflag) data2 <<= 2;
- SiS_SetRegByte(DACData, data2);
+ SiS_SetRegByte(DACData, (data2 << sf));
data >>= 2;
}
}
if(time == 256) {
for(i = 16; i < 32; i++) {
- data = table[i];
- if(shiftflag) data <<= 2;
+ data = table[i] << sf;
for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
}
si = 32;
for(m = 0; m < 9; m++) {
- di = si;
- bx = si + 4;
- dl = 0;
- for(n = 0; n < 3; n++) {
- for(o = 0; o < 5; o++) {
- dh = table[si];
- ah = table[di];
- al = table[bx];
+ di = si;
+ bx = si + 4;
+ for(n = 0; n < 3; n++) {
+ for(o = 0; o < 5; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
si++;
- SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
}
si -= 2;
for(o = 0; o < 3; o++) {
- dh = table[bx];
- ah = table[di];
- al = table[si];
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
si--;
- SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
}
- dl++;
} /* for n < 3 */
si += 5;
} /* for m < 9 */
@@ -3241,89 +2972,114 @@ SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT StandTableIndex,RefreshRateTableIndex;
-
- SiS_Pr->SiS_CRT1Mode = ModeNo;
- StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
- SiS_DisableBridge(SiS_Pr, HwInfo);
- }
- }
-
- SiS_ResetSegmentRegisters(SiS_Pr, HwInfo);
-
- SiS_SetSeqRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetMiscRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
- SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
- SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
- SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
-
- SiS_Pr->SiS_SelectCRT2Rate = 0;
- SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-
-#ifdef LINUX_XF86
- xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
+ unsigned short StandTableIndex, RefreshRateTableIndex;
+
+ SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+ StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
+ SiS_DisableBridge(SiS_Pr);
+ }
+ }
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
+
+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+ SiS_ResetCRT1VCLK(SiS_Pr);
+
+ SiS_Pr->SiS_SelectCRT2Rate = 0;
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+
+#ifdef SIS_XORG_XF86
+ xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
#endif
- if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ }
- RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
+ }
- if(RefreshRateTableIndex != 0xFFFF) {
- SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
- SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
- }
+ if(RefreshRateTableIndex != 0xFFFF) {
+ SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ switch(SiS_Pr->ChipType) {
#ifdef SIS300
- if(HwInfo->jChipType == SIS_300) {
- SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo,HwInfo,RefreshRateTableIndex);
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ||
- (HwInfo->jChipType == SIS_540)) {
- SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, HwInfo, RefreshRateTableIndex);
- }
+ case SIS_300:
+ SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
+ break;
+ case SIS_540:
+ case SIS_630:
+ case SIS_730:
+ SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
+ break;
#endif
+ default:
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- }
+ if(SiS_Pr->ChipType == XGI_20) {
+ unsigned char sr2b = 0, sr2c = 0;
+ switch(ModeNo) {
+ case 0x00:
+ case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
+ case 0x04:
+ case 0x05:
+ case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
+ }
+ if(sr2b) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
+ SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
+ }
+ }
+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
#endif
+ break;
+ }
+
+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- SiS_SetCRT1ModeRegs(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == XGI_40) {
+ SiS_SetupDualChip(SiS_Pr);
+ }
+#endif
- SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
-#ifdef LINUX_KERNEL
- if(SiS_Pr->SiS_flag_clearbuffer) {
- SiS_ClearBuffer(SiS_Pr,HwInfo,ModeNo);
- }
+#ifdef SIS_LINUX_KERNEL
+ if(SiS_Pr->SiS_flag_clearbuffer) {
+ SiS_ClearBuffer(SiS_Pr, ModeNo);
+ }
#endif
- if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
- SiS_WaitRetrace1(SiS_Pr);
- SiS_DisplayOn(SiS_Pr);
- }
+ if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
+ SiS_WaitRetrace1(SiS_Pr);
+ SiS_DisplayOn(SiS_Pr);
+ }
}
/*********************************************/
@@ -3331,33 +3087,62 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_InitVB(struct SiS_Private *SiS_Pr)
+{
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+
+ SiS_Pr->Init_P4_0E = 0;
+ if(SiS_Pr->SiS_ROMNew) {
+ SiS_Pr->Init_P4_0E = ROMAddr[0x82];
+ } else if(SiS_Pr->ChipType >= XGI_40) {
+ if(SiS_Pr->SiS_XGIROM) {
+ SiS_Pr->Init_P4_0E = ROMAddr[0x80];
+ }
+ }
+}
+
+static void
+SiS_ResetVB(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp;
+#ifdef SIS315H
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp;
/* VB programming clock */
if(SiS_Pr->SiS_UseROM) {
- if(HwInfo->jChipType < SIS_330) {
- temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+ if(SiS_Pr->ChipType < SIS_330) {
+ temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
- } else if(HwInfo->jChipType >= SIS_661) {
- temp = ROMAddr[0x7e] | 0x40;
- if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+ } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
+ temp = ROMAddr[0x7e] | 0x40;
+ if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
}
+ } else if(SiS_Pr->ChipType >= XGI_40) {
+ temp = 0x40;
+ if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
+ /* Can we do this on any chipset? */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
}
+#endif
}
/*********************************************/
-/* HELPER: SET VIDEO REGISTERS */
+/* HELPER: SET VIDEO/CAPTURE REGISTERS */
/*********************************************/
static void
-SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
{
- if((IS_SIS651) || (IS_SISM650)) {
+ /* SiS65x and XGI set up some sort of "lock mode" for text
+ * which locks CRT2 in some way to CRT1 timing. Disable
+ * this here.
+ */
+#ifdef SIS315H
+ if((IS_SIS651) || (IS_SISM650) ||
+ SiS_Pr->ChipType == SIS_340 ||
+ SiS_Pr->ChipType == XGI_40) {
SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */
SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */
@@ -3365,49 +3150,99 @@ SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
}
/* !!! This does not support modes < 0x13 !!! */
+#endif
}
/*********************************************/
-/* XFree86: SET SCREEN PITCH */
+/* HELPER: SET AGP TIMING FOR SiS760 */
/*********************************************/
-#ifdef LINUX_XF86
static void
-SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_Handle760(struct SiS_Private *SiS_Pr)
+{
+#ifdef SIS315H
+ unsigned int somebase;
+ unsigned char temp1, temp2, temp3;
+
+ if( (SiS_Pr->ChipType != SIS_760) ||
+ ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
+ (!(SiS_Pr->SiS_SysFlags & SF_760LFB)) ||
+ (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
+ return;
+
+#ifdef SIS_LINUX_KERNEL
+ somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
+#else
+ somebase = pciReadWord(0x00001000, 0x74);
+#endif
+ somebase &= 0xffff;
+
+ if(somebase == 0) return;
+
+ temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
+
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ temp1 = 0x21;
+ temp2 = 0x03;
+ temp3 |= 0x08;
+ } else {
+ temp1 = 0x25;
+ temp2 = 0x0b;
+ }
+
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
+ sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
+#else
+ pciWriteByte(0x00000000, 0x7e, temp1);
+ pciWriteByte(0x00000000, 0x8d, temp2);
+#endif
+
+ SiS_SetRegByte((somebase + 0x85), temp3);
+#endif
+}
+
+/*********************************************/
+/* X.org/XFree86: SET SCREEN PITCH */
+/*********************************************/
+
+#ifdef SIS_XORG_XF86
+static void
+SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort HDisplay = pSiS->scrnPitch >> 3;
+ unsigned short HDisplay = pSiS->scrnPitch >> 3;
SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay>>8));
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
}
static void
-SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort HDisplay = pSiS->scrnPitch2 >> 3;
+ unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
/* Unlock CRT2 */
if(pSiS->VGAEngine == SIS_315_VGA)
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
else
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
}
static void
-SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
BOOLEAN isslavemode = FALSE;
- if( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
+ if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
( ((pSiS->VGAEngine == SIS_300_VGA) &&
- (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
- ((pSiS->VGAEngine == SIS_315_VGA) &&
+ (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
+ ((pSiS->VGAEngine == SIS_315_VGA) &&
(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
isslavemode = TRUE;
}
@@ -3427,59 +3262,59 @@ SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
/* SiSSetMode() */
/*********************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
/* We need pScrn for setting the pitch correctly */
BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch)
+SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
#else
BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
+SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
#endif
{
- USHORT ModeIdIndex;
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- unsigned char backupreg=0;
-#ifdef LINUX_KERNEL
- USHORT KeepLockReg;
- ULONG temp;
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+ unsigned short RealModeNo, ModeIdIndex;
+ unsigned char backupreg = 0;
+#ifdef SIS_LINUX_KERNEL
+ unsigned short KeepLockReg;
SiS_Pr->UseCustomMode = FALSE;
SiS_Pr->CRT1UsesCustomMode = FALSE;
#endif
+ SiS_Pr->SiS_flag_clearbuffer = 0;
+
if(SiS_Pr->UseCustomMode) {
ModeNo = 0xfe;
+ } else {
+#ifdef SIS_LINUX_KERNEL
+ if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
+#endif
+ ModeNo &= 0x7f;
}
- SiSInitPtr(SiS_Pr, HwInfo);
+ /* Don't use FSTN mode for CRT1 */
+ RealModeNo = ModeNo;
+ if(ModeNo == 0x5b) ModeNo = 0x56;
+
+ SiSInitPtr(SiS_Pr);
SiSRegInit(SiS_Pr, BaseAddr);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
+ SiS_GetSysFlags(SiS_Pr);
-#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiS_Pr->SiS_VGAINFO = 0x11;
+#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
- else
-#endif
- SiS_Pr->SiS_VGAINFO = 0x11;
-
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
- SiS_Pr->SiS_flag_clearbuffer = 0;
-
- if(!SiS_Pr->UseCustomMode) {
-#ifdef LINUX_KERNEL
- if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
#endif
- ModeNo &= 0x7f;
- }
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
#endif
SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
+
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3487,13 +3322,13 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
ModeIdIndex = 0;
}
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
/* Init/restore some VB registers */
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_ResetVB(SiS_Pr, HwInfo);
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_ResetVB(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -3503,21 +3338,20 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
}
/* Get VB information (connectors, connected devices) */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, (SiS_Pr->UseCustomMode) ? 0 : 1);
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
-
-#ifdef LINUX_KERNEL
- /* 3. Check memory size (Kernel framebuffer driver only) */
- temp = SiS_CheckMemorySize(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
- if(!temp) return(0);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+#ifdef SIS_LINUX_KERNEL
+ /* Check memory size (kernel framebuffer driver only) */
+ if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
+ return FALSE;
+ }
#endif
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- }
+ SiS_OpenCRTC(SiS_Pr);
if(SiS_Pr->UseCustomMode) {
SiS_Pr->CRT1UsesCustomMode = TRUE;
@@ -3530,38 +3364,41 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
/* Set mode on CRT1 */
if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
(!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
- SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
}
/* Set mode on CRT2 */
if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
- (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
- (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
- (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+ (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
+ (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
+ SiS_SetCRT2Group(SiS_Pr, RealModeNo);
}
}
SiS_HandleCRT1(SiS_Pr);
- SiS_StrangeStuff(SiS_Pr, HwInfo);
+ SiS_StrangeStuff(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(HwInfo->jChipType >= SIS_315H) {
+#ifdef SIS315H
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
}
+#endif
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- if(!SiS_Pr->SiS_ROMNew) {
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+ if(!SiS_Pr->SiS_ROMNew) {
+ if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
} else {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3574,23 +3411,24 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
if((ModeNo == 0x03) || (ModeNo == 0x10)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
- }
+ }
}
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
+#endif
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
if(pScrn) {
/* SetPitch: Adapt to virtual size & position */
if((ModeNo > 0x13) && (dosetpitch)) {
- SiS_SetPitch(SiS_Pr, pScrn);
+ SiS_SetPitch(SiS_Pr, pScrn);
}
/* Backup/Set ModeNo in BIOS scratch area */
@@ -3598,33 +3436,37 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
}
#endif
-#ifdef LINUX_KERNEL /* We never lock registers in XF86 */
- if(KeepLockReg == 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- else SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
+ SiS_CloseCRTC(SiS_Pr);
+
+ SiS_Handle760(SiS_Pr);
+
+#ifdef SIS_LINUX_KERNEL
+ /* We never lock registers in XF86 */
+ if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
#endif
return TRUE;
}
/*********************************************/
-/* XFree86: SiSBIOSSetMode() */
+/* X.org/XFree86: SiSBIOSSetMode() */
/* for non-Dual-Head mode */
/*********************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
BOOLEAN
-SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort ModeNo = 0;
+ unsigned short ModeNo = 0;
SiS_Pr->UseCustomMode = FALSE;
if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
- SiS_Pr->CHDisplay,
+ SiS_Pr->CHDisplay,
(mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
(mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
SiS_Pr->CVDisplay)));
@@ -3632,32 +3474,33 @@ SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
/* Don't need vbflags here; checks done earlier */
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
+ ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
if(!ModeNo) return FALSE;
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
}
- return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE));
+ return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
}
/*********************************************/
-/* XFree86: SiSBIOSSetModeCRT2() */
+/* X.org/XFree86: SiSBIOSSetModeCRT2() */
/* for Dual-Head modes */
/*********************************************/
+
BOOLEAN
-SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
- USHORT ModeIdIndex;
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- UShort ModeNo = 0;
- unsigned char backupreg=0;
- SISPtr pSiS = SISPTR(pScrn);
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+ SISPtr pSiS = SISPTR(pScrn);
#ifdef SISDUALHEAD
SISEntPtr pSiSEnt = pSiS->entityPrivate;
#endif
+ unsigned short ModeIdIndex;
+ unsigned short ModeNo = 0;
+ unsigned char backupreg = 0;
SiS_Pr->UseCustomMode = FALSE;
@@ -3672,22 +3515,25 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
- if(!ModeNo) return FALSE;
+ ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
+ if(!ModeNo) return FALSE;
}
SiSRegInit(SiS_Pr, BaseAddr);
- SiSInitPtr(SiS_Pr, HwInfo);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiSInitPtr(SiS_Pr);
+ SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
#else
SiS_Pr->SiS_VGAINFO = 0x11;
#endif
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
+
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
/* Save mode info so we can set it from within SetMode for CRT1 */
#ifdef SISDUALHEAD
@@ -3700,23 +3546,20 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
#if 0
- /* We can't set CRT2 mode before CRT1 mode is set */
+ /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
if(pSiSEnt->CRT1ModeNo == -1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting CRT2 mode delayed until after setting CRT1 mode\n");
- return TRUE;
+ return TRUE;
}
#endif
pSiSEnt->CRT2ModeSet = TRUE;
}
#endif
- /* We don't clear the buffer in X */
- SiS_Pr->SiS_flag_clearbuffer=0;
-
if(SiS_Pr->UseCustomMode) {
- USHORT temptemp = SiS_Pr->CVDisplay;
+ unsigned short temptemp = SiS_Pr->CVDisplay;
if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
@@ -3728,13 +3571,11 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
- "Setting standard mode 0x%x on CRT2\n", ModeNo);
+ "Setting standard mode 0x%x on CRT2\n", ModeNo);
}
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3742,56 +3583,59 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
ModeIdIndex = 0;
}
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_ResetVB(SiS_Pr, HwInfo);
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_ResetVB(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
- backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
} else {
- backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
}
}
/* Get VB information (connectors, connected devices) */
if(!SiS_Pr->UseCustomMode) {
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 1);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
} else {
/* If this is a custom mode, we don't check the modeflag for CRT2Mode */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
}
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
/* Set mode on CRT2 */
if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
(SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
(SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ SiS_SetCRT2Group(SiS_Pr, ModeNo);
}
- SiS_StrangeStuff(SiS_Pr, HwInfo);
+ SiS_StrangeStuff(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- if(!SiS_Pr->SiS_ROMNew) {
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(!SiS_Pr->SiS_ROMNew) {
+ if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
} else {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3803,8 +3647,8 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
@@ -3812,25 +3656,27 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
/* SetPitch: Adapt to virtual size & position */
SiS_SetPitchCRT2(SiS_Pr, pScrn);
+ SiS_Handle760(SiS_Pr);
+
return TRUE;
}
/*********************************************/
-/* XFree86: SiSBIOSSetModeCRT1() */
+/* X.org/XFree86: SiSBIOSSetModeCRT1() */
/* for Dual-Head modes */
/*********************************************/
BOOLEAN
-SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
SISPtr pSiS = SISPTR(pScrn);
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- USHORT ModeIdIndex, ModeNo=0;
- UCHAR backupreg=0;
+ unsigned short ModeIdIndex, ModeNo = 0;
+ unsigned char backupreg = 0;
#ifdef SISDUALHEAD
SISEntPtr pSiSEnt = pSiS->entityPrivate;
- UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
+ unsigned char backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
BOOLEAN backupcustom;
#endif
@@ -3838,43 +3684,41 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
- USHORT temptemp = SiS_Pr->CVDisplay;
+ unsigned short temptemp = SiS_Pr->CVDisplay;
- if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
- else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
+ if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
+ else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting custom mode %dx%d on CRT1\n",
SiS_Pr->CHDisplay, temptemp);
ModeNo = 0xfe;
} else {
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
- if(!ModeNo) return FALSE;
+ ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
+ if(!ModeNo) return FALSE;
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting standard mode 0x%x on CRT1\n", ModeNo);
}
- SiSInitPtr(SiS_Pr, HwInfo);
+ SiSInitPtr(SiS_Pr);
SiSRegInit(SiS_Pr, BaseAddr);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
#else
SiS_Pr->SiS_VGAINFO = 0x11;
#endif
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
- /* We don't clear the buffer in X */
- SiS_Pr->SiS_flag_clearbuffer = 0;
SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
+
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3883,10 +3727,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
}
/* Determine VBType */
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
} else {
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3895,25 +3740,29 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
/* Get VB information (connectors, connected devices) */
/* (We don't care if the current mode is a CRT2 mode) */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- }
+ SiS_OpenCRTC(SiS_Pr);
/* Set mode on CRT1 */
- SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ SiS_SetCRT2Group(SiS_Pr, ModeNo);
}
/* SetPitch: Adapt to virtual size & position */
SiS_SetPitchCRT1(SiS_Pr, pScrn);
+ SiS_HandleCRT1(SiS_Pr);
+
+ SiS_StrangeStuff(SiS_Pr);
+
+ SiS_CloseCRTC(SiS_Pr);
+
#ifdef SISDUALHEAD
if(pSiS->DualHeadMode) {
pSiSEnt->CRT1ModeNo = ModeNo;
@@ -3933,7 +3782,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
#ifdef SISDUALHEAD
if(pSiS->DualHeadMode) {
if(pSiSEnt->CRT2ModeNo != -1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"(Re-)Setting mode for CRT2\n");
backupcustom = SiS_Pr->UseCustomMode;
backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
@@ -3952,9 +3801,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
}
- SiSBIOSSetModeCRT2(SiS_Pr, HwInfo, pSiSEnt->pScrn_1,
+
+ SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
+
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
@@ -3970,22 +3821,20 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
* possibly overwritten
*/
- SiS_HandleCRT1(SiS_Pr);
-
- SiS_StrangeStuff(SiS_Pr, HwInfo);
-
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
+ SiS_Handle760(SiS_Pr);
+
/* Backup/Set ModeNo in BIOS scratch area */
SiS_GetSetModeID(pScrn,ModeNo);
@@ -3993,84 +3842,6 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
}
#endif /* Linux_XF86 */
-
-#ifdef LINUX_XF86
-BOOLEAN
-SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- const USHORT PanelTypeTable300[16] = {
- 0xc101, 0xc117, 0x0121, 0xc135, 0xc142, 0xc152, 0xc162, 0xc072,
- 0xc181, 0xc192, 0xc1a1, 0xc1b6, 0xc1c2, 0xc0d2, 0xc1e2, 0xc1f2
- };
- const USHORT PanelTypeTable31030x[16] = {
- 0xc102, 0xc112, 0x0122, 0xc132, 0xc142, 0xc152, 0xc169, 0xc179,
- 0x0189, 0xc192, 0xc1a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
- const USHORT PanelTypeTable310LVDS[16] = {
- 0xc111, 0xc122, 0xc133, 0xc144, 0xc155, 0xc166, 0xc177, 0xc188,
- 0xc199, 0xc0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
- USHORT tempax,tempbx,temp;
-
- if(HwInfo->jChipType < SIS_315H) {
-
- tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempbx = tempax & 0x0F;
- if(!(tempax & 0x10)){
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1){
- tempbx = 0;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x38);
- if(temp & 0x40) tempbx |= 0x08;
- if(temp & 0x20) tempbx |= 0x02;
- if(temp & 0x01) tempbx |= 0x01;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x39);
- if(temp & 0x80) tempbx |= 0x04;
- } else {
- return 0;
- }
- }
- tempbx = PanelTypeTable300[tempbx];
- tempbx |= LCDSync;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
- temp = (tempbx & 0xFF00) >> 8;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
-
- } else {
-
- if(HwInfo->jChipType >= SIS_661) return 0;
-
- tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1a);
- tempax &= 0x1e;
- tempax >>= 1;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(tempax == 0) {
- /* TODO: Include HUGE detection routine
- (Probably not worth bothering)
- */
- return 0;
- }
- temp = tempax & 0xff;
- tempax--;
- tempbx = PanelTypeTable310LVDS[tempax];
- } else {
- tempbx = PanelTypeTable31030x[tempax];
- temp = tempbx & 0xff;
- }
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
- tempbx = (tempbx & 0xff00) >> 8;
- temp = tempbx & 0xc1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- temp = tempbx & 0x04;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp);
- }
-
- }
- return 1;
-}
-#endif
-
#ifndef GETBITSTR
#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
#define GENMASK(mask) BITMASK(1?mask,0?mask)
@@ -4078,26 +3849,28 @@ SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to))
#endif
-static void
-SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+void
+SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
{
+ int x = 1; /* Fix sync */
+
SiS_Pr->CCRT1CRTC[0] = ((SiS_Pr->CHTotal >> 3) - 5) & 0xff; /* CR0 */
SiS_Pr->CCRT1CRTC[1] = (SiS_Pr->CHDisplay >> 3) - 1; /* CR1 */
SiS_Pr->CCRT1CRTC[2] = (SiS_Pr->CHBlankStart >> 3) - 1; /* CR2 */
SiS_Pr->CCRT1CRTC[3] = (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; /* CR3 */
SiS_Pr->CCRT1CRTC[4] = (SiS_Pr->CHSyncStart >> 3) + 3; /* CR4 */
SiS_Pr->CCRT1CRTC[5] = ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | /* CR5 */
- (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+ (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
- SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */
- SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */
- | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
- | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
- | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+ SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */
+ SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */
+ | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+ | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
+ | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
| 0x10
- | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4)
- | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
- | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+ | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4)
+ | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+ | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* CR9 */
@@ -4106,55 +3879,44 @@ SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
else if(SiS_Pr->CHDisplay >= 640) SiS_Pr->CCRT1CRTC[16] |= 0x40;
}
-#if 0
- if (mode->VScan >= 32)
- regp->CRTC[9] |= 0x1F;
- else if (mode->VScan > 1)
- regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
- SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart ) & 0xFF; /* CR10 */
- SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd ) & 0x0F) | 0x80; /* CR11 */
+ SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart - x) & 0xFF; /* CR10 */
+ SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd - x) & 0x0F) | 0x80; /* CR11 */
SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay - 1) & 0xFF; /* CR12 */
SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF; /* CR15 */
SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd - 1) & 0xFF; /* CR16 */
SiS_Pr->CCRT1CRTC[13] = /* SRA */
- GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) |
- GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) |
- GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
- GETBITSTR((SiS_Pr->CVSyncStart ), 10:10, 3:3) |
- GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
- GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
+ GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) |
+ GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) |
+ GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+ GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
+ GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
+ GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
SiS_Pr->CCRT1CRTC[14] = /* SRB */
- GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
- GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
- GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
- GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
+ GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
+ GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
+ GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+ GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
SiS_Pr->CCRT1CRTC[15] = /* SRC */
- GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
- GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
+ GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+ GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
}
void
-SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
- int i,j;
+ unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
+ unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
+ int i, j;
/* 1:1 data: use data set by setcrt1crtc() */
if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
if(modeflag & HalfDCLK) VGAHDE >>= 1;
@@ -4164,32 +3926,91 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
- tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
- tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempax = SiS_Pr->PanelXRes;
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ tempbx = SiS_Pr->SiS_VGAHT;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempbx = SiS_Pr->PanelHT;
+ }
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ remaining = tempbx % 8;
+#endif
+ } else {
+#ifdef SIS315H
+ /* OK for LCDA, LVDS */
+ tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+ tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = SiS_Pr->PanelXRes;
+ }
+ tempbx += tempax;
+ if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+#endif
}
- tempbx += tempax;
- if(modeflag & HalfDCLK) tempbx -= VGAHDE;
SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
- tempax = VGAHDE;
- tempbx = SiS_Pr->CHTotal;
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempbx = SiS_Pr->PanelXRes;
- if(modeflag & HalfDCLK) tempbx >>= 1;
- tempax += ((tempbx - tempax) >> 1);
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
+ SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
+ SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->CHSyncStart >>= 1;
+ SiS_Pr->CHSyncEnd >>= 1;
+ }
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
+ tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
+ if(modeflag & HalfDCLK) {
+ tempax >>= 1;
+ tempbx >>= 1;
+ }
+ SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
+ tempax = SiS_Pr->PanelHRE + 7;
+ if(modeflag & HalfDCLK) tempax >>= 1;
+ SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
+ } else {
+ SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->CHSyncStart >>= 1;
+ tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
+ SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
+ } else {
+ SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
+ SiS_Pr->CHSyncStart += 8;
+ }
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ tempax = VGAHDE;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempbx = SiS_Pr->PanelXRes;
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ tempax += ((tempbx - tempax) >> 1);
+ }
+ tempax += SiS_Pr->PanelHRS;
+ SiS_Pr->CHSyncStart = tempax;
+ tempax += SiS_Pr->PanelHRE;
+ SiS_Pr->CHSyncEnd = tempax;
+#endif
}
- tempax += SiS_Pr->PanelHRS;
- SiS_Pr->CHSyncStart = tempax;
- tempax += SiS_Pr->PanelHRE;
- SiS_Pr->CHSyncEnd = tempax;
-
tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
tempax = SiS_Pr->SiS_VGAVDE;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
tempax = SiS_Pr->PanelYRes;
+ } else if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ /* Stupid hack for 640x400/320x200 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if((tempax + tempbx) == 438) tempbx += 16;
+ } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
+ tempax = 0;
+ tempbx = SiS_Pr->SiS_VGAVT;
+ }
+#endif
}
SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
@@ -4201,22 +4022,28 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
SiS_Pr->CVSyncStart = tempax;
tempax += SiS_Pr->PanelVRE;
SiS_Pr->CVSyncEnd = tempax;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_Pr->CVSyncStart--;
+ SiS_Pr->CVSyncEnd--;
+ }
SiS_CalcCRRegisters(SiS_Pr, 8);
+ SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
+ SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
- for(i=0,j=0;i<=7;i++,j++) {
+ for(i = 0, j = 0; i <= 7; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x10;i<=10;i++,j++) {
+ for(j = 0x10; i <= 10; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x15;i<=12;i++,j++) {
+ for(j = 0x15; i <= 12; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x0A;i<=15;i++,j++) {
+ for(j = 0x0A; i <= 15; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
}
@@ -4227,1092 +4054,192 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
if(modeflag & DoubleScanMode) tempax |= 0x80;
SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
- SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+ SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
-
xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+ SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+ SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
#endif
+#endif
}
-#ifdef LINUX_XF86
-
void
-SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c)
-{
- int out_n, out_dn, out_div, out_sbit, out_scale;
- unsigned int vclk[5];
-
-#define Midx 0
-#define Nidx 1
-#define VLDidx 2
-#define Pidx 3
-#define PSNidx 4
-
- if(SiS_compute_vclk(clock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) {
- (*p2b) = (out_div == 2) ? 0x80 : 0x00;
- (*p2b) |= ((out_n - 1) & 0x7f);
- (*p2c) = (out_dn - 1) & 0x1f;
- (*p2c) |= (((out_scale - 1) & 3) << 5);
- (*p2c) |= ((out_sbit & 0x01) << 7);
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
- clock, out_n, out_dn, out_div, out_sbit, out_scale);
+SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+ int xres, int yres,
+#ifdef SIS_XORG_XF86
+ DisplayModePtr current
#endif
- } else {
- SiSCalcClock(pScrn, clock, 2, vclk);
- (*p2b) = (vclk[VLDidx] == 2) ? 0x80 : 0x00;
- (*p2b) |= (vclk[Midx] - 1) & 0x7f;
- (*p2c) = (vclk[Nidx] - 1) & 0x1f;
- if(vclk[Pidx] <= 4) {
- /* postscale 1,2,3,4 */
- (*p2c) |= ((vclk[Pidx] - 1) & 3) << 5;
- } else {
- /* postscale 6,8 */
- (*p2c) |= (((vclk[Pidx] / 2) - 1) & 3) << 5;
- (*p2c) |= 0x80;
- }
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n",
- clock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]);
+#ifdef SIS_LINUX_KERNEL
+ struct fb_var_screeninfo *var, BOOLEAN writeres
#endif
- }
-}
-
-#endif
-
-/* ================ XFREE86/X.ORG ================= */
-
-/* Helper functions */
-
-#ifdef LINUX_XF86
-
-USHORT
-SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
+)
{
- SISPtr pSiS = SISPTR(pScrn);
- int depth = pSiS->CurrentLayout.bitsPerPixel;
-
- pSiS->SiS_Pr->CModeFlag = 0;
-
- pSiS->SiS_Pr->CDClock = mode->Clock;
-
- pSiS->SiS_Pr->CHDisplay = mode->HDisplay;
- pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart;
- pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd;
- pSiS->SiS_Pr->CHTotal = mode->HTotal;
-
- pSiS->SiS_Pr->CVDisplay = mode->VDisplay;
- pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart;
- pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd;
- pSiS->SiS_Pr->CVTotal = mode->VTotal;
-
- pSiS->SiS_Pr->CFlags = mode->Flags;
-
- if(pSiS->SiS_Pr->CFlags & V_INTERLACE) {
- pSiS->SiS_Pr->CVDisplay >>= 1;
- pSiS->SiS_Pr->CVSyncStart >>= 1;
- pSiS->SiS_Pr->CVSyncEnd >>= 1;
- pSiS->SiS_Pr->CVTotal >>= 1;
- }
- if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) {
- /* pSiS->SiS_Pr->CDClock <<= 1; */
- pSiS->SiS_Pr->CVDisplay <<= 1;
- pSiS->SiS_Pr->CVSyncStart <<= 1;
- pSiS->SiS_Pr->CVSyncEnd <<= 1;
- pSiS->SiS_Pr->CVTotal <<= 1;
- }
-
- pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
- pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
- pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1;
- pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal;
+ unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+ unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+ unsigned char sr_data, cr_data, cr_data2;
+ int A, B, C, D, E, F, temp;
- SiS_MakeClockRegs(pScrn, pSiS->SiS_Pr->CDClock, &pSiS->SiS_Pr->CSR2B, &pSiS->SiS_Pr->CSR2C);
+ sr_data = crdata[14];
- pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
+ /* Horizontal total */
+ HT = crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
+ A = HT + 5;
- SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
+ /* Horizontal display enable end */
+ HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
+ E = HDE + 1;
- switch(depth) {
- case 8: pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
- case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
- case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
- default: return 0;
- }
+ /* Horizontal retrace (=sync) start */
+ HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
+ F = HRS - E - 3;
- if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
- pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
+ /* Horizontal blank start */
+ HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
- if((pSiS->SiS_Pr->CVDisplay >= 1024) ||
- (pSiS->SiS_Pr->CVTotal >= 1024) ||
- (pSiS->SiS_Pr->CHDisplay >= 1024))
- pSiS->SiS_Pr->CModeFlag |= LineCompareOff;
+ sr_data = crdata[15];
+ cr_data = crdata[5];
- if(pSiS->SiS_Pr->CFlags & V_CLKDIV2)
- pSiS->SiS_Pr->CModeFlag |= HalfDCLK;
+ /* Horizontal blank end */
+ HBE = (crdata[3] & 0x1f) |
+ ((unsigned short)(cr_data & 0x80) >> 2) |
+ ((unsigned short)(sr_data & 0x03) << 6);
- pSiS->SiS_Pr->CInfoFlag = 0x0007;
+ /* Horizontal retrace (=sync) end */
+ HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
- if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
- pSiS->SiS_Pr->CInfoFlag |= 0x4000;
+ temp = HBE - ((E - 1) & 255);
+ B = (temp > 0) ? temp : (temp + 256);
- if(pSiS->SiS_Pr->CFlags & V_NVSYNC)
- pSiS->SiS_Pr->CInfoFlag |= 0x8000;
+ temp = HRE - ((E + F + 3) & 63);
+ C = (temp > 0) ? temp : (temp + 64);
- if(pSiS->SiS_Pr->CFlags & V_INTERLACE)
- pSiS->SiS_Pr->CInfoFlag |= InterlaceMode;
+ D = B - F - C;
- pSiS->SiS_Pr->UseCustomMode = TRUE;
+#ifdef SIS_XORG_XF86
+ current->HDisplay = (E * 8);
+ current->HSyncStart = (E * 8) + (F * 8);
+ current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
+ current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
- pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
- xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
- pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
- xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
- pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
- pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
- pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
- xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
- pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
- pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
- pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
- xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
- xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
- pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
-#endif
- return 1;
-}
-
-int
-SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy)
-{
- int i, j;
- BOOLEAN done = FALSE;
-
- i = 0;
- while((!done) && (SiS_PlasmaTable[i].vendor) && panelvendor) {
- if(SiS_PlasmaTable[i].vendor == panelvendor) {
- for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
- if(SiS_PlasmaTable[i].product[j] == panelproduct) {
- if(SiS_PlasmaTable[i].maxx && SiS_PlasmaTable[i].maxy) {
- (*maxx) = (int)SiS_PlasmaTable[i].maxx;
- (*maxy) = (int)SiS_PlasmaTable[i].maxy;
- (*prefx) = (int)SiS_PlasmaTable[i].prefx;
- (*prefy) = (int)SiS_PlasmaTable[i].prefy;
- done = TRUE;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "Identified %s, correcting max X res %d, max Y res %d\n",
- SiS_PlasmaTable[i].plasmaname,
- SiS_PlasmaTable[i].maxx, SiS_PlasmaTable[i].maxy);
- break;
- }
- }
- }
- }
- i++;
- }
- return (done) ? 1 : 0;
-}
-
-/* Build a list of supported modes:
- * Built-in modes for which we have all data are M_T_DEFAULT,
- * modes derived from DDC or database data are M_T_BUILTIN
- */
-DisplayModePtr
-SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi)
-{
- SISPtr pSiS = SISPTR(pScrn);
- unsigned short VRE, VBE, VRS, VBS, VDE, VT;
- unsigned short HRE, HBE, HRS, HBS, HDE, HT;
- unsigned char sr_data, cr_data, cr_data2, cr_data3;
- unsigned char sr2b, sr2c;
- float num, denum, postscalar, divider;
- int A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex;
- DisplayModePtr new = NULL, current = NULL, first = NULL;
- BOOLEAN done = FALSE;
-#if 0
- DisplayModePtr backup = NULL;
-#endif
-
- pSiS->backupmodelist = NULL;
- pSiS->AddedPlasmaModes = FALSE;
-
- /* Initialize our pointers */
- if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
- InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
+ xf86DrvMsg(0, X_INFO,
+ "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
+ A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
#else
- return NULL;
+ (void)VBS; (void)HBS; (void)A;
#endif
- } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
- InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return NULL;
-#endif
- } else return NULL;
-
- i = 0;
- while(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag != 0xFFFF) {
-
- index = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRT1CRTC;
-
- /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */
- if((!pSiS->FSTN) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a)) {
- i++;
- continue;
- }
- if((pSiS->FSTN) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) {
- i++;
- continue;
- }
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(10))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes,
- pSiS->SiS_Pr->SiS_RefIndex[i].YRes);
-
- current->status = MODE_OK;
-
- current->type = M_T_DEFAULT;
-
- vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK;
- if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F;
-
- sr2b = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
- sr2c = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
-
- divider = (sr2b & 0x80) ? 2.0 : 1.0;
- postscalar = (sr2c & 0x80) ?
- ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0);
- num = (sr2b & 0x7f) + 1.0;
- denum = (sr2c & 0x1f) + 1.0;
-
-#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "------------\n");
- xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n",
- sr2b, sr2c, divider, postscalar, num, denum);
#endif
-
- current->Clock = (int)(14318 * (divider / postscalar) * (num / denum));
-
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[14];
- /* inSISIDXREG(SISSR, 0x0b, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[0];
- /* inSISIDXREG(SISCR, 0x00, cr_data); */
-
- /* Horizontal total */
- HT = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[1];
- /* inSISIDXREG(SISCR, 0x01, cr_data); */
-
- /* Horizontal display enable end */
- HDE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x0C) << 6);
- E = HDE + 1; /* 0x80 0x64 */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
- /* inSISIDXREG(SISCR, 0x04, cr_data); */
-
- /* Horizontal retrace (=sync) start */
- HRS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0xC0) << 2);
- F = HRS - E - 3; /* 0x06 0x06 */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
- /* inSISIDXREG(SISCR, 0x02, cr_data); */
-
- /* Horizontal blank start */
- HBS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x30) << 4);
-
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[15];
- /* inSISIDXREG(SISSR, 0x0c, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[3];
- /* inSISIDXREG(SISCR, 0x03, cr_data); */
-
- cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[5];
- /* inSISIDXREG(SISCR, 0x05, cr_data2); */
-
- /* Horizontal blank end */
- HBE = (cr_data & 0x1f) |
- ((unsigned short) (cr_data2 & 0x80) >> 2) |
- ((unsigned short) (sr_data & 0x03) << 6);
-
- /* Horizontal retrace (=sync) end */
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
-
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
-
- D = B - F - C;
-
- if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
- ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) ||
- (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) {
-
- /* Terrible hack, but correct CRTC data for
- * these modes only produces a black screen...
- * (HRE is 0, leading into a too large C and
- * a negative D. The CRT controller does not
- * seem to like correcting HRE to 50
- */
- current->HDisplay = 320;
- current->HSyncStart = 328;
- current->HSyncEnd = 376;
- current->HTotal = 400;
-
- } else {
-
- current->HDisplay = (E * 8);
- current->HSyncStart = (E * 8) + (F * 8);
- current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
- current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
-
- }
-
-#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO,
- "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
- A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
+#ifdef SIS_LINUX_KERNEL
+ if(writeres) var->xres = xres = E * 8;
+ var->left_margin = D * 8;
+ var->right_margin = F * 8;
+ var->hsync_len = C * 8;
#endif
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[13];
- /* inSISIDXREG(SISSR, 0x0A, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[6];
- /* inSISIDXREG(SISCR, 0x06, cr_data); */
-
- cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[7];
- /* inSISIDXREG(SISCR, 0x07, cr_data2); */
-
- /* Vertical total */
- VT = (cr_data & 0xFF) |
- ((unsigned short) (cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[10];
- /* inSISIDXREG(SISCR, 0x12, cr_data); */
-
- /* Vertical display enable end */
- VDE = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x02) << 7) |
- ((unsigned short) (cr_data2 & 0x40) << 3) |
- ((unsigned short) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[8];
- /* inSISIDXREG(SISCR, 0x10, cr_data); */
-
- /* Vertical retrace (=sync) start */
- VRS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x04) << 6) |
- ((unsigned short) (cr_data2 & 0x80) << 2) |
- ((unsigned short) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[11];
- /* inSISIDXREG(SISCR, 0x15, cr_data); */
-
- cr_data3 = (pSiS->SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
- /* inSISIDXREG(SISCR, 0x09, cr_data3); */
-
- /* Vertical blank start */
- VBS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x08) << 5) |
- ((unsigned short) (cr_data3 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x04) << 8);
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[12];
- /* inSISIDXREG(SISCR, 0x16, cr_data); */
-
- /* Vertical blank end */
- VBE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[9];
- /* inSISIDXREG(SISCR, 0x11, cr_data); */
-
- /* Vertical retrace (=sync) end */
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- current->VDisplay = VDE + 1;
- current->VSyncStart = VRS + 1;
- current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1;
- if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
- current->VTotal = E + D + C + F;
-
+ /* Vertical */
+ sr_data = crdata[13];
+ cr_data = crdata[7];
+
+ /* Vertical total */
+ VT = crdata[6] |
+ ((unsigned short)(cr_data & 0x01) << 8) |
+ ((unsigned short)(cr_data & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x01) << 10);
+ A = VT + 2;
+
+ /* Vertical display enable end */
+ VDE = crdata[10] |
+ ((unsigned short)(cr_data & 0x02) << 7) |
+ ((unsigned short)(cr_data & 0x40) << 3) |
+ ((unsigned short)(sr_data & 0x02) << 9);
+ E = VDE + 1;
+
+ /* Vertical retrace (=sync) start */
+ VRS = crdata[8] |
+ ((unsigned short)(cr_data & 0x04) << 6) |
+ ((unsigned short)(cr_data & 0x80) << 2) |
+ ((unsigned short)(sr_data & 0x08) << 7);
+ F = VRS + 1 - E;
+
+ cr_data2 = (crdata[16] & 0x01) << 5;
+
+ /* Vertical blank start */
+ VBS = crdata[11] |
+ ((unsigned short)(cr_data & 0x08) << 5) |
+ ((unsigned short)(cr_data2 & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x04) << 8);
+
+ /* Vertical blank end */
+ VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
+ temp = VBE - ((E - 1) & 511);
+ B = (temp > 0) ? temp : (temp + 512);
+
+ /* Vertical retrace (=sync) end */
+ VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
+ temp = VRE - ((E + F - 1) & 31);
+ C = (temp > 0) ? temp : (temp + 32);
+
+ D = B - F - C;
+
+#ifdef SIS_XORG_XF86
+ current->VDisplay = VDE + 1;
+ current->VSyncStart = VRS + 1;
+ current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1;
+ if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
+ current->VTotal = E + D + C + F;
#if 0
- current->VDisplay = E;
- current->VSyncStart = E + D;
- current->VSyncEnd = E + D + C;
- current->VTotal = E + D + C + F;
+ current->VDisplay = E;
+ current->VSyncStart = E + D;
+ current->VSyncEnd = E + D + C;
+ current->VTotal = E + D + C + F;
#endif
-
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO,
- "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
- A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
+ xf86DrvMsg(0, X_INFO,
+ "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
+ A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
#endif
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x4000)
- current->Flags |= V_NHSYNC;
- else
- current->Flags |= V_PHSYNC;
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x8000)
- current->Flags |= V_NVSYNC;
- else
- current->Flags |= V_PVSYNC;
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x0080)
- current->Flags |= V_INTERLACE;
-
- j = 0;
- while(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
- pSiS->SiS_Pr->SiS_RefIndex[i].ModeID) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
- current->Flags |= V_DBLSCAN;
- }
- break;
- }
- j++;
- }
-
- if(current->Flags & V_INTERLACE) {
- current->VDisplay <<= 1;
- current->VSyncStart <<= 1;
- current->VSyncEnd <<= 1;
- current->VTotal <<= 1;
- current->VTotal |= 1;
- }
- if(current->Flags & V_DBLSCAN) {
- current->Clock >>= 1;
- current->VDisplay >>= 1;
- current->VSyncStart >>= 1;
- current->VSyncEnd >>= 1;
- current->VTotal >>= 1;
- }
-
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Built-in: %s %.2f %d %d %d %d %d %d %d %d\n",
- current->name, (float)current->Clock / 1000,
- current->HDisplay, current->HSyncStart, current->HSyncEnd, current->HTotal,
- current->VDisplay, current->VSyncStart, current->VSyncEnd, current->VTotal);
-#else
- (void)VBS; (void)HBS; (void)A;
#endif
-
- i++;
- }
-
- /* Add non-standard LCD modes for panel's detailed timings */
-
- if(!includelcdmodes) return first;
-
- if(pSiS->SiS_Pr->CP_Vendor) {
- xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n",
- pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product);
- }
-
- i = 0;
- while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) {
-
- if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) {
-
- for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
-
- if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) {
-
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Identified %s panel, adding specific modes\n",
- SiS_PlasmaTable[i].plasmaname);
-
- for(k=0; k<SiS_PlasmaTable[i].modenum; k++) {
-
- if(isfordvi) {
- if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue;
- } else {
- if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue;
- }
-
- l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f;
-
- if(pSiS->VBFlags & (VB_301|VB_301B|VB_302B|VB_301LV)) {
- if(isfordvi) {
- if(SiS_PlasmaMode[l].VDisplay > 1024) continue;
- }
- }
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(12))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- pSiS->AddedPlasmaModes = TRUE;
-
- strcpy(current->name, SiS_PlasmaMode[l].name);
- /* sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay,
- SiS_PlasmaMode[l].VDisplay); */
-
- current->status = MODE_OK;
-
- current->type = M_T_BUILTIN;
-
- current->Clock = SiS_PlasmaMode[l].clock;
- current->SynthClock = current->Clock;
-
- current->HDisplay = SiS_PlasmaMode[l].HDisplay;
- current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch;
- current->HSyncEnd = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth;
- current->HTotal = SiS_PlasmaMode[l].HTotal;
-
- current->VDisplay = SiS_PlasmaMode[l].VDisplay;
- current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch;
- current->VSyncEnd = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth;
- current->VTotal = SiS_PlasmaMode[l].VTotal;
-
- current->CrtcHDisplay = current->HDisplay;
- current->CrtcHBlankStart = current->HSyncStart;
- current->CrtcHSyncStart = current->HSyncStart;
- current->CrtcHSyncEnd = current->HSyncEnd;
- current->CrtcHBlankEnd = current->HSyncEnd;
- current->CrtcHTotal = current->HTotal;
-
- current->CrtcVDisplay = current->VDisplay;
- current->CrtcVBlankStart = current->VSyncStart;
- current->CrtcVSyncStart = current->VSyncStart;
- current->CrtcVSyncEnd = current->VSyncEnd;
- current->CrtcVBlankEnd = current->VSyncEnd;
- current->CrtcVTotal = current->VTotal;
-
- if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP)
- current->Flags |= V_PHSYNC;
- else
- current->Flags |= V_NHSYNC;
-
- if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP)
- current->Flags |= V_PVSYNC;
- else
- current->Flags |= V_NVSYNC;
-
- if(current->HDisplay > pSiS->LCDwidth)
- pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay;
- if(current->VDisplay > pSiS->LCDheight)
- pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay;
-
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "\tAdding \"%s\" to list of built-in modes\n", current->name);
-
- }
- done = TRUE;
- break;
- }
- }
- }
-
- i++;
-
- }
-
- if(pSiS->SiS_Pr->CP_HaveCustomData) {
-
- for(i=0; i<7; i++) {
-
- if(pSiS->SiS_Pr->CP_DataValid[i]) {
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(10))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i],
- pSiS->SiS_Pr->CP_VDisplay[i]);
-
- current->status = MODE_OK;
-
- current->type = M_T_BUILTIN;
-
- current->Clock = pSiS->SiS_Pr->CP_Clock[i];
- current->SynthClock = current->Clock;
-
- current->HDisplay = pSiS->SiS_Pr->CP_HDisplay[i];
- current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i];
- current->HSyncEnd = pSiS->SiS_Pr->CP_HSyncEnd[i];
- current->HTotal = pSiS->SiS_Pr->CP_HTotal[i];
-
- current->VDisplay = pSiS->SiS_Pr->CP_VDisplay[i];
- current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i];
- current->VSyncEnd = pSiS->SiS_Pr->CP_VSyncEnd[i];
- current->VTotal = pSiS->SiS_Pr->CP_VTotal[i];
-
- current->CrtcHDisplay = current->HDisplay;
- current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i];
- current->CrtcHSyncStart = current->HSyncStart;
- current->CrtcHSyncEnd = current->HSyncEnd;
- current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i];
- current->CrtcHTotal = current->HTotal;
-
- current->CrtcVDisplay = current->VDisplay;
- current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i];
- current->CrtcVSyncStart = current->VSyncStart;
- current->CrtcVSyncEnd = current->VSyncEnd;
- current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i];
- current->CrtcVTotal = current->VTotal;
-
- if(pSiS->SiS_Pr->CP_SyncValid[i]) {
- if(pSiS->SiS_Pr->CP_HSync_P[i])
- current->Flags |= V_PHSYNC;
- else
- current->Flags |= V_NHSYNC;
-
- if(pSiS->SiS_Pr->CP_VSync_P[i])
- current->Flags |= V_PVSYNC;
- else
- current->Flags |= V_NVSYNC;
- } else {
- /* No sync data? Use positive sync... */
- current->Flags |= V_PHSYNC;
- current->Flags |= V_PVSYNC;
- }
- }
- }
- }
-
- return first;
-
-}
-
-/* Translate a mode number into the VESA pendant */
-int
-SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber)
-{
- SISPtr pSiS = SISPTR(pScrn);
- int i = 0;
-
- /* Initialize our pointers */
- if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
- InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return -1;
-#endif
- } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
- InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return -1;
+#ifdef SIS_LINUX_KERNEL
+ if(writeres) var->yres = yres = E;
+ var->upper_margin = D;
+ var->lower_margin = F;
+ var->vsync_len = C;
#endif
- } else return -1;
-
- if(modenumber <= 0x13) return modenumber;
-#ifdef SIS315H
- if(pSiS->ROM661New) {
- while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
- if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
- return (int)SiS_EModeIDTable661[i].Ext_VESAID;
- }
- i++;
- }
- } else {
+ if((xres == 320) && ((yres == 200) || (yres == 240))) {
+ /* Terrible hack, but correct CRTC data for
+ * these modes only produces a black screen...
+ * (HRE is 0, leading into a too large C and
+ * a negative D. The CRT controller does not
+ * seem to like correcting HRE to 50)
+ */
+#ifdef SIS_XORG_XF86
+ current->HDisplay = 320;
+ current->HSyncStart = 328;
+ current->HSyncEnd = 376;
+ current->HTotal = 400;
#endif
- while(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID != 0xff) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID == modenumber) {
- return (int)pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID;
- }
- i++;
- }
-#ifdef SIS315H
- }
+#ifdef SIS_LINUX_KERNEL
+ var->left_margin = (400 - 376);
+ var->right_margin = (328 - 320);
+ var->hsync_len = (376 - 328);
#endif
- return -1;
-}
-/* Translate a new BIOS mode number into the driver's pendant */
-int
-SiSTranslateToOldMode(int modenumber)
-{
-#ifdef SIS315H
- int i = 0;
-
- while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
- if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
- if(SiS_EModeIDTable661[i].Ext_MyModeID)
- return (int)SiS_EModeIDTable661[i].Ext_MyModeID;
- else
- return modenumber;
- }
- i++;
}
-#endif
- return modenumber;
-}
-
-#endif /* Xfree86 */
-
-#ifdef LINUX_KERNEL
-int
-sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, unsigned char rateindex)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, ClockIndex = 0;
- USHORT RefreshRateTableIndex = 0;
- int Clock;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return 65 * 1000;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return 65 * 1000;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
- printk(KERN_ERR "Could not find mode %x\n", ModeNo);
- return 65 * 1000;
- }
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- ClockIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- if(HwInfo->jChipType < SIS_315H) {
- ClockIndex &= 0x3F;
- }
- Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
-
- return(Clock);
-}
-
-BOOLEAN
-sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, CRT1Index = 0;
- USHORT RefreshRateTableIndex = 0;
- unsigned char sr_data, cr_data, cr_data2;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return FALSE;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return FALSE;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
- cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
- *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
- sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
- cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
- cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
- *vtotal = ((cr_data & 0xFF) |
- ((unsigned short)(cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short)(sr_data & 0x01) << 10)) + 2;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode)
- *vtotal *= 2;
-
- return TRUE;
}
-int
-sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, unsigned char rateindex,
- struct fb_var_screeninfo *var)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, index = 0;
- USHORT RefreshRateTableIndex = 0;
- unsigned short VRE, VBE, VRS, VBS, VDE, VT;
- unsigned short HRE, HBE, HRS, HBS, HDE, HT;
- unsigned char sr_data, cr_data, cr_data2, cr_data3;
- int A, B, C, D, E, F, temp, j;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return 0;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return 0;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[14];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[0];
-
- /* Horizontal total */
- HT = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[1];
-
- /* Horizontal display enable end */
- HDE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x0C) << 6);
- E = HDE + 1;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[4];
-
- /* Horizontal retrace (=sync) start */
- HRS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0xC0) << 2);
- F = HRS - E - 3;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[2];
-
- /* Horizontal blank start */
- HBS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x30) << 4);
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[15];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[3];
-
- cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[5];
-
- /* Horizontal blank end */
- HBE = (cr_data & 0x1f) |
- ((unsigned short) (cr_data2 & 0x80) >> 2) |
- ((unsigned short) (sr_data & 0x03) << 6);
-
- /* Horizontal retrace (=sync) end */
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
-
- D = B - F - C;
-
- if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) &&
- ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) ||
- (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) {
-
- /* Terrible hack, but the correct CRTC data for
- * these modes only produces a black screen...
- */
- var->left_margin = (400 - 376);
- var->right_margin = (328 - 320);
- var->hsync_len = (376 - 328);
-
- } else {
-
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
-
- }
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6];
-
- cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7];
-
- /* Vertical total */
- VT = (cr_data & 0xFF) |
- ((unsigned short) (cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[10];
-
- /* Vertical display enable end */
- VDE = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x02) << 7) |
- ((unsigned short) (cr_data2 & 0x40) << 3) |
- ((unsigned short) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[8];
-
- /* Vertical retrace (=sync) start */
- VRS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x04) << 6) |
- ((unsigned short) (cr_data2 & 0x80) << 2) |
- ((unsigned short) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[11];
-
- cr_data3 = (SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
-
- /* Vertical blank start */
- VBS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x08) << 5) |
- ((unsigned short) (cr_data3 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x04) << 8);
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[12];
-
- /* Vertical blank end */
- VBE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[9];
-
- /* Vertical retrace (=sync) end */
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
-
- var->vmode = FB_VMODE_NONINTERLACED;
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
- var->vmode = FB_VMODE_INTERLACED;
- else {
- j = 0;
- while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
- if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
- SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
- if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
- var->vmode = FB_VMODE_DOUBLE;
- }
- break;
- }
- j++;
- }
- }
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-#if 0 /* Do this? */
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
-#endif
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
- }
-
- return 1;
-}
-
-#endif
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index 7e36b7ac1470..634c0a9d219b 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -3,7 +3,7 @@
/*
* Data and prototypes for init.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,18 +50,24 @@
*
*/
-#ifndef _INIT_
-#define _INIT_
+#ifndef _INIT_H_
+#define _INIT_H_
#include "osdef.h"
#include "initdef.h"
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#include "sis.h"
+#define SIS_NEED_inSISREG
+#define SIS_NEED_inSISREGW
+#define SIS_NEED_inSISREGL
+#define SIS_NEED_outSISREG
+#define SIS_NEED_outSISREGW
+#define SIS_NEED_outSISREGL
#include "sis_regs.h"
#endif
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include "vgatypes.h"
#include "vstruct.h"
#ifdef SIS_CP
@@ -73,6 +79,10 @@
#include <asm/io.h>
#include <linux/fb.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/sisfb.h>
#else
#include <video/sisfb.h>
@@ -80,44 +90,45 @@
#endif
/* Mode numbers */
-static const USHORT ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
-static const USHORT ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
-static const USHORT ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00}; /* FSTN */
-static const USHORT ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
-static const USHORT ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
-static const USHORT ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
-static const USHORT ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
-static const USHORT ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
-static const USHORT ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
-static const USHORT ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
-static const USHORT ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
-static const USHORT ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
-static const USHORT ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
-static const USHORT ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
-static const USHORT ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; /* 315 series only */
-static const USHORT ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; /* 315 series only */
-static const USHORT ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
-static const USHORT ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
-static const USHORT ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */
-static const USHORT ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
-static const USHORT ModeIndex_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e};
-static const USHORT ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */
-static const USHORT ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
-static const USHORT ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
-static const USHORT ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
-static const USHORT ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
-static const USHORT ModeIndex_1280x800[] = {0x14, 0x15, 0x00, 0x16};
-static const USHORT ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e};
-static const USHORT ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72}; /* 300 series, BARCO only */
-static const USHORT ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 315 series only */
-static const USHORT ModeIndex_1680x1050[] = {0x17, 0x18, 0x00, 0x19}; /* 315 series only */
-static const USHORT ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66};
-static const USHORT ModeIndex_1920x1080[] = {0x2c, 0x2d, 0x00, 0x73}; /* 315 series only */
-static const USHORT ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b};
-static const USHORT ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
-static const USHORT ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
-
-static const USHORT SiS_DRAMType[17][5]={
+static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00}; /* FSTN */
+static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; /* 315 series only */
+static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; /* 315 series only */
+static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+static const unsigned short ModeIndex_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e};
+static const unsigned short ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */
+static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
+static const unsigned short ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x800[] = {0x14, 0x15, 0x00, 0x16};
+static const unsigned short ModeIndex_1280x854[] = {0x1a, 0x1b, 0x00, 0x1c};
+static const unsigned short ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e};
+static const unsigned short ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72}; /* 300 series, BARCO only */
+static const unsigned short ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 315 series only */
+static const unsigned short ModeIndex_1680x1050[] = {0x17, 0x18, 0x00, 0x19}; /* 315 series only */
+static const unsigned short ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66};
+static const unsigned short ModeIndex_1920x1080[] = {0x2c, 0x2d, 0x00, 0x73}; /* 315 series only */
+static const unsigned short ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b};
+static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
+static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
+
+static const unsigned short SiS_DRAMType[17][5]={
{0x0C,0x0A,0x02,0x40,0x39},
{0x0D,0x0A,0x01,0x40,0x48},
{0x0C,0x09,0x02,0x20,0x35},
@@ -137,7 +148,7 @@ static const USHORT SiS_DRAMType[17][5]={
{0x09,0x08,0x01,0x01,0x00}
};
-static const USHORT SiS_SDRDRAM_TYPE[13][5] =
+static const unsigned short SiS_SDRDRAM_TYPE[13][5] =
{
{ 2,12, 9,64,0x35},
{ 1,13, 9,64,0x44},
@@ -154,7 +165,7 @@ static const USHORT SiS_SDRDRAM_TYPE[13][5] =
{ 1, 9, 8, 2,0x00}
};
-static const USHORT SiS_DDRDRAM_TYPE[4][5] =
+static const unsigned short SiS_DDRDRAM_TYPE[4][5] =
{
{ 2,12, 9,64,0x35},
{ 2,12, 8,32,0x31},
@@ -162,7 +173,7 @@ static const USHORT SiS_DDRDRAM_TYPE[4][5] =
{ 2, 9, 8, 4,0x01}
};
-static const USHORT SiS_MDA_DAC[] =
+static const unsigned char SiS_MDA_DAC[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
@@ -174,7 +185,7 @@ static const USHORT SiS_MDA_DAC[] =
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
};
-static const USHORT SiS_CGA_DAC[] =
+static const unsigned char SiS_CGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
@@ -186,7 +197,7 @@ static const USHORT SiS_CGA_DAC[] =
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
};
-static const USHORT SiS_EGA_DAC[] =
+static const unsigned char SiS_EGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
@@ -198,7 +209,7 @@ static const USHORT SiS_EGA_DAC[] =
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
};
-static const USHORT SiS_VGA_DAC[] =
+static const unsigned char SiS_VGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
@@ -212,7 +223,31 @@ static const USHORT SiS_VGA_DAC[] =
0x0B,0x0C,0x0D,0x0F,0x10
};
-static const SiS_StResInfoStruct SiS_StResInfo[]=
+static const struct SiS_St SiS_SModeIDTable[] =
+{
+ {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00,0x40},
+ {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00,0x40},
+ {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01,0x40},
+ {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02,0x40},
+ {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02,0x40},
+ {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05,0x40},
+ {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03,0x40},
+ {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05,0x40},
+ {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05,0x40},
+ {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05,0x40},
+ {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05,0x40},
+ {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiS_StResInfo[]=
{
{ 640,400},
{ 640,350},
@@ -221,7 +256,7 @@ static const SiS_StResInfoStruct SiS_StResInfo[]=
{ 640,480}
};
-static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
+static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
{
{ 320, 200, 8, 8}, /* 0x00 */
{ 320, 240, 8, 8}, /* 0x01 */
@@ -256,11 +291,12 @@ static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
{ 1280, 800, 8,16}, /* 0x1e */
{ 1920,1080, 8,16}, /* 0x1f */
{ 960, 540, 8,16}, /* 0x20 */
- { 960, 600, 8,16} /* 0x21 */
+ { 960, 600, 8,16}, /* 0x21 */
+ { 1280, 854, 8,16} /* 0x22 */
};
#if defined(SIS300) || defined(SIS315H)
-static const SiS_StandTableStruct SiS_StandTable[]=
+static const struct SiS_StandTable_S SiS_StandTable[]=
{
/* 0x00: MD_0_200 */
{
@@ -704,11 +740,11 @@ static const SiS_StandTableStruct SiS_StandTable[]=
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const UCHAR SiS_SoftSetting = 0x30; /* RAM setting */
+static const unsigned char SiS_SoftSetting = 0x30; /* RAM setting */
-static const UCHAR SiS_OutputSelect = 0x40;
+static const unsigned char SiS_OutputSelect = 0x40;
-static const UCHAR SiS_NTSCTiming[] = {
+static const unsigned char SiS_NTSCTiming[] = {
0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
@@ -719,7 +755,7 @@ static const UCHAR SiS_NTSCTiming[] = {
0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
};
-static const UCHAR SiS_PALTiming[] = {
+static const unsigned char SiS_PALTiming[] = {
0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
@@ -730,8 +766,8 @@ static const UCHAR SiS_PALTiming[] = {
0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
};
-static const UCHAR SiS_HiTVExtTiming[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVExtTiming[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -741,8 +777,8 @@ static const UCHAR SiS_HiTVExtTiming[] = {
0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
};
-static const UCHAR SiS_HiTVSt1Timing[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVSt1Timing[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
@@ -752,8 +788,8 @@ static const UCHAR SiS_HiTVSt1Timing[] = {
0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
};
-static const UCHAR SiS_HiTVSt2Timing[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVSt2Timing[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -764,8 +800,8 @@ static const UCHAR SiS_HiTVSt2Timing[] = {
};
#if 0
-static const UCHAR SiS_HiTVTextTiming[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVTextTiming[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
@@ -776,8 +812,8 @@ static const UCHAR SiS_HiTVTextTiming[] = {
};
#endif
-static const UCHAR SiS_HiTVGroup3Data[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+static const unsigned char SiS_HiTVGroup3Data[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
@@ -787,8 +823,8 @@ static const UCHAR SiS_HiTVGroup3Data[] = {
0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
};
-static const UCHAR SiS_HiTVGroup3Simu[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+static const unsigned char SiS_HiTVGroup3Simu[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
@@ -799,8 +835,8 @@ static const UCHAR SiS_HiTVGroup3Simu[] = {
};
#if 0
-static const UCHAR SiS_HiTVGroup3Text[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+static const unsigned char SiS_HiTVGroup3Text[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
@@ -811,136 +847,141 @@ static const UCHAR SiS_HiTVGroup3Text[] = {
};
#endif
-static const UCHAR SiS_NTSCPhase[] = {0x21,0xed,0xba,0x08};
-static const UCHAR SiS_PALPhase[] = {0x2a,0x05,0xe3,0x00};
-static const UCHAR SiS_PALMPhase[] = {0x21,0xE4,0x2E,0x9B};
-static const UCHAR SiS_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
-static const UCHAR SiS_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};
-static const UCHAR SiS_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
-static const UCHAR SiS_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4};
-static const UCHAR SiS_PALNPhase2[] = {0x21,0xF6,0x94,0x46};
-static const UCHAR SiS_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a};
-static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0};
-static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e};
-
-static const SiS_TVDataStruct SiS_StPALData[] =
+static const struct SiS_TVData SiS_StPALData[] =
{
- { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
- { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
- { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22}
+ { 1, 1, 864, 525,1270, 400, 100, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 350, 100, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 400, 0, 0, 720, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 864, 525,1270, 350, 0, 0, 720, 0,0xf4,0x0b,0x1c,0x0a},
+ { 1, 1, 864, 525,1270, 480, 50, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 600, 50, 0, 0,0x300,0xf4,0xff,0x1c,0x22}
};
-static const SiS_TVDataStruct SiS_ExtPALData[] =
+static const struct SiS_TVData SiS_ExtPALData[] =
{
- { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */
- { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
- { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18},
- { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a},
- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */
-/*{ 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16},*//* 800x600, 400x300 */
- { 36, 25,1060, 648,1270, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 - better */
- { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x576 */
- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 */
- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 (for NTSC equ) */
- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a} /* 720x480 test */
+ { 27, 10, 848, 448,1270, 530, 50, 0, 50, 0,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */
+ { 108, 35, 848, 398,1270, 530, 50, 0, 50, 0,0xf4,0xff,0x1c,0x22},
+ { 12, 5, 954, 448,1270, 530, 50, 0, 50, 0,0xf1,0x04,0x1f,0x18},
+ { 9, 4, 960, 463,1644, 438, 50, 0, 50, 0,0xf4,0x0b,0x1c,0x0a},
+ { 9, 4, 848, 528,1270, 530, 0, 0, 50, 0,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */
+ { 36, 25,1060, 648,1270, 530, 438, 0, 438, 0,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 */
+ { 3, 2,1080, 619,1270, 540, 438, 0, 438, 0,0xf3,0x00,0x1d,0x20}, /* 720x576 */
+ { 1, 1,1170, 821,1270, 520, 686, 0, 686, 0,0xF3,0x00,0x1D,0x20}, /* 1024x768 */
+ { 1, 1,1170, 821,1270, 520, 686, 0, 686, 0,0xF3,0x00,0x1D,0x20}, /* 1024x768 (for NTSC equ) */
+ { 9, 4, 848, 528,1270, 530, 0, 0, 50, 0,0xf5,0xfb,0x1b,0x2a} /* 720x480 */
};
-static const SiS_TVDataStruct SiS_StNTSCData[] =
+static const struct SiS_TVData SiS_StNTSCData[] =
{
- { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
- { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18}
+ { 1, 1, 858, 525,1270, 400, 50, 0, 760, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 350, 50, 0, 640, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 400, 0, 0, 720, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 350, 0, 0, 720, 0,0xf4,0x0b,0x1c,0x0a},
+ { 1, 1, 858, 525,1270, 480, 0, 0, 760, 0,0xf1,0x04,0x1f,0x18}
};
-static const SiS_TVDataStruct SiS_ExtNTSCData[] =
+static const struct SiS_TVData SiS_ExtNTSCData[] =
{
- { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */
- { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
- { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
- { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
- { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */
- { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */
-/*{ 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08},*/ /* 720x480 (old, from 650) */
- { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */
-/*{ 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} */ /* 1024x768 (525i) */
- { 1, 1,1100, 811,1412, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 1024x768 (525i) CORRECTED */
- { 65, 64,1056, 791,1270, 480, 455, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+ { 143, 65, 858, 443,1270, 440, 171, 0, 171, 0,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */
+ { 88, 35, 858, 393,1270, 440, 171, 0, 171, 0,0xf1,0x04,0x1f,0x18},
+ { 143, 70, 924, 443,1270, 440, 92, 0, 92, 0,0xf1,0x04,0x1f,0x18},
+ { 143, 70, 924, 393,1270, 440, 92, 0, 92, 0,0xf4,0x0b,0x1c,0x0a},
+ { 143, 76, 836, 523,1270, 440, 224, 0, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */
+ { 143, 120,1056, 643,1270, 440, 0, 1, 0, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */
+ { 143, 76, 836, 523,1270, 440, 0, 1, 0, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */
+ { 1, 1,1100, 811,1412, 440, 0, 1, 0, 0,0xee,0x0c,0x22,0x08}, /* 1024x768 (525i) CORRECTED */
+#if 0 /* flimmert und ist unten abgeschnitten (NTSCHT, NTSC clock) */
+ { 65, 64,1056, 791,1270, 480, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1,1100, 811,1412, 440, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1,1120, 821,1516, 420, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1, 938, 821,1516, 420, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0 /* zoom hin, unten abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1072, 791,1270, 480, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 1 /* zu weit links (squeezed) (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1100, 846,1270, 440, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0 /* zu weit links, rechts abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1100, 846,1412, 440, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
};
-static const SiS_TVDataStruct SiS_StHiTVData[] = /* Slave + TVSimu */
+static const struct SiS_TVData SiS_StHiTVData[] = /* Slave + TVSimu */
{
- { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x150, 1, 0, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_St2HiTVData[] = /* Slave */
+static const struct SiS_TVData SiS_St2HiTVData[] = /* Slave */
{
- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
+ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d, 1, 0, 0, 0, 0, 0, 0},
+ { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c, 1, 0, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_ExtHiTVData[] =
-{
- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */
- { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */
- { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */
- { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x1024 */
- { 4, 1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x480 */
- { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x576 */
- { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x720 */
- { 137, 32, 0x3d4,0x233,0x663,0x3bf,0x143, 0, 0, 0x00,0x00,0x00,0x00} /* 960x600 */
+static const struct SiS_TVData SiS_ExtHiTVData[] =
+{ /* all ok */
+ { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 5, 1, 0x348,0x233,0x670,0x3c0,0x166, 1, 0, 0, 0, 0, 0, 0}, /* 640x480 */
+ { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0}, /* 800x600 */
+ { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 1024x768 */
+ { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0}, /* 1280x1024 */
+ { 4, 1, 0x41a,0x233,0x60c,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0}, /* 800x480 */
+ { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 1024x576 */
+ { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0}, /* 1280x720 */
+ { 8, 3, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 960x600 */
};
-static const SiS_TVDataStruct SiS_St525pData[] =
+static const struct SiS_TVData SiS_St525pData[] =
{
- { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x1e0, 0, 0, 0x2f8, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_St750pData[] =
+static const struct SiS_TVData SiS_St750pData[] =
{
- { 1, 1, 0x672,0x2ee,0x500,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x190, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x15e, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x672,0x2ee,0x500,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x190, 0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x15e, 0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x1e0, 0, 0, 0x2f8, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_Ext750pData[] =
-{
- { 143, 65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00},
- { 88, 35, 0x35a,0x189,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00},
- { 18, 5, 0x339,0x1ae,0x500,0x2d0,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00},
- { 143, 70, 0x39c,0x189,0x4f6,0x1b8,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00},
- { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */
- { 5, 4, 0x5d8,0x29e,0x500,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */
- { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 720x480 test WORKS */
- { 68, 64, 0x55f,0x346,0x500,0x2a8,0x27e, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */
- { 5, 2, 0x3a7,0x226,0x500,0x2a8, 0,128, 0, 0x00,0x00,0x00,0x00}, /* 720x576 */
- { 25, 24, 0x5d8,0x2f3,0x460,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00} /* 1280x720 WORKS */
+static const struct SiS_TVData SiS_Ext750pData[] =
+{ /* all ok */
+ { 3, 1, 935, 470, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0}, /* 320x200/640x400 */
+ { 24, 7, 935, 420, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 935, 470, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 24, 7, 935, 420, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 2, 1, 1100, 590, 1130, 640, 50, 0, 0, 0, 0, 0, 0, 0}, /* 640x480 */
+ { 3, 2, 1210, 690, 1130, 660, 50, 0, 0, 0, 0, 0, 0, 0}, /* 800x600 OK */
+ { 2, 1, 1100, 562, 1130, 640, 0, 1, 0, 0, 0, 0, 0, 0}, /* 720x480 OK */
+ { 1, 1, 1375, 878, 1130, 640, 638, 0, 0, 0, 0, 0, 0, 0}, /* 1024x768 OK */
+ { 5, 3, 1100, 675, 1130, 640, 0, 1, 0, 0, 0, 0, 0, 0}, /* 720/768x576 OK */
+ { 25, 24, 1496, 755, 1120, 680, 50, 0, 0, 0, 0, 0, 0, 0} /* 1280x720 OK */
};
-static const SiS_LCDDataStruct SiS_LCD1280x720Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_LCD1280x720Data[] = /* 2.03.00 */
{
{ 44, 15, 864, 430, 1408, 806 }, /* 640x400 */
{ 128, 35, 792, 385, 1408, 806 },
@@ -962,7 +1003,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x720Data[] = /* 2.03.00 */
* (Note: 1280x768_3 is now special for SiS301/NetVista
*/
-static const SiS_LCDDataStruct SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
{
{ 64, 21, 858, 434, 1408, 806 }, /* 640x400 */
{ 32, 9, 858, 372, 1408, 806 },
@@ -977,7 +1018,7 @@ static const SiS_LCDDataStruct SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
{ 16, 15, 1600, 750, 1600, 806 } /* 1280x720 - from Ext */
};
-static const SiS_LCDDataStruct SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
{
{ 16, 5, 960, 410, 1600, 806 }, /* 640x400 */
{ 64, 21, 1152, 364, 1600, 806 },
@@ -993,7 +1034,7 @@ static const SiS_LCDDataStruct SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
};
#if 0 /* Not used; _3 now reserved for NetVista (SiS301) */
-static const SiS_LCDDataStruct SiS_LCD1280x768_3Data[] =
+static const struct SiS_LCDData SiS_LCD1280x768_3Data[] =
{
{ 64, 25, 1056, 422, 1664, 798 }, /* 640x400 */
{ 128, 39, 884, 396, 1408, 806 }, /* ,640 */
@@ -1009,7 +1050,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x768_3Data[] =
};
#endif
-static const SiS_LCDDataStruct SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
+static const struct SiS_LCDData SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
{
{ 128, 51, 1122, 412, 1408, 816 }, /* 640x400 */
{ 128, 49, 1232, 361, 1408, 816 },
@@ -1024,7 +1065,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
{ 0, 0, 0, 0, 0, 0 } /* 1280x720 */
};
-static const SiS_LCDDataStruct SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
+static const struct SiS_LCDData SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
{
{ 97, 42, 1344, 409, 1552, 812 }, /* 640x400 */
{ 97, 35, 1280, 358, 1552, 812 },
@@ -1039,7 +1080,42 @@ static const SiS_LCDDataStruct SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
{ 97, 90, 1600, 730, 1552, 812 } /* 1280x720 */
};
-static const SiS_LCDDataStruct SiS_LCD1280x960Data[] =
+#if 0
+static const struct SiS_LCDData SiS_LCD1280x800_3Data[] = /* 2.02.05a (LVDS); m250 */
+{
+ { 128, 51, 1122, 412, 1408, 816 }, /* 640x400 */
+ { 128, 49, 1232, 361, 1408, 816 },
+ { 128, 51, 1122, 412, 1408, 816 },
+ { 128, 49, 1232, 361, 1408, 816 },
+ { 8, 3, 880, 491, 1408, 816 }, /* 640x480 */
+ { 11, 6, 1024, 612, 1408, 816 }, /* 800x600 */
+ { 22, 21, 1400, 784, 1408, 816 }, /* 1024x768 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */
+ { 1, 1, 1408, 816, 1408, 816 }, /* 1280x800 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x768 - patch index */
+ { 0, 0, 0, 0, 0, 0 } /* 1280x720 */
+};
+#endif
+
+static const struct SiS_LCDData SiS_LCD1280x854Data[] = /* 2.21.00CS (LVDS) */
+{
+ { 56, 15, 936, 410, 1664, 861 }, /* 640x400 */
+ { 64, 25, 1586, 355, 1664, 861 },
+ { 56, 15, 936, 410, 1664, 861 },
+ { 64, 25, 1586, 355, 1664, 861 },
+ { 91, 45, 1464, 485, 1664, 861 }, /* 640x480 */
+ { 182, 75, 976, 605, 1664, 861 }, /* 800x600 */
+ { 91, 66, 1342, 774, 1664, 861 }, /* 1024x768 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */
+ { 26, 25, 1708, 807, 1664, 861 }, /* 1280x800 */
+ { 13, 12, 1708, 774, 1664, 861 }, /* 1280x768 - patch index */
+ { 52, 45, 1708, 725, 1664, 861 }, /* 1280x720 */
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 1, 1664, 861, 1664, 861 } /* 1280x854 */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x960Data[] =
{
{ 9, 2, 800, 500, 1800, 1000 },
{ 9, 2, 800, 500, 1800, 1000 },
@@ -1049,10 +1125,15 @@ static const SiS_LCDDataStruct SiS_LCD1280x960Data[] =
{ 30, 11, 1056, 625, 1800, 1000 },
{ 5, 3, 1350, 800, 1800, 1000 },
{ 1, 1, 1576, 1050, 1576, 1050 },
- { 1, 1, 1800, 1000, 1800, 1000 }
+ { 1, 1, 1800, 1000, 1800, 1000 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_StLCD1400x1050Data[] =
{
{ 211, 100, 2100, 408, 1688, 1066 },
{ 211, 64, 1536, 358, 1688, 1066 },
@@ -1062,10 +1143,15 @@ static const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] =
{ 211, 72, 1008, 609, 1688, 1066 },
{ 211, 128, 1400, 776, 1688, 1066 },
{ 211, 205, 1680, 1041, 1688, 1066 },
- { 1, 1, 1688, 1066, 1688, 1066 }
+ { 1, 1, 1688, 1066, 1688, 1066 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1400x1050Data[] =
{
/* { 211, 60, 1260, 410, 1688, 1066 }, 640x400 (6330) */
{ 211, 100, 2100, 408, 1688, 1066 }, /* 640x400 (6325) WORKS */
@@ -1080,10 +1166,13 @@ static const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] =
{ 211, 205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
{ 1, 1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
{ 0, 0, 0, 0, 0, 0 }, /* kludge */
- { 211, 120, 1400, 730, 1688, 1066 } /* 1280x720 */
+ { 211, 120, 1400, 730, 1688, 1066 }, /* 1280x720 */
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_LCD1680x1050Data[] =
+static const struct SiS_LCDData SiS_LCD1680x1050Data[] =
{
{ 95, 24, 1260, 410, 1900, 1066 }, /* 0 640x400 */
{ 10, 3, 1710, 362, 1900, 1066 },
@@ -1097,10 +1186,11 @@ static const SiS_LCDDataStruct SiS_LCD1680x1050Data[] =
{ 95, 69, 1800, 817, 1900, 1066 }, /* 9 1280x800 patch index */
{ 13, 9, 1900, 739, 1900, 1066 }, /* 10 1280x720 */
{ 95, 94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */
- { 1, 1, 1900, 1066, 1900, 1066 } /* 12 1680x1050 */
+ { 1, 1, 1900, 1066, 1900, 1066 }, /* 12 1680x1050 */
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_StLCD1600x1200Data[] =
{
{27, 4, 800, 500, 2160, 1250 },
{27, 4, 800, 500, 2160, 1250 },
@@ -1111,10 +1201,14 @@ static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] =
{ 5, 2,1350, 800, 2160, 1250 },
{135,88,1600,1100, 2160, 1250 },
{72, 49,1680,1092, 2160, 1250 },
- { 1, 1,2160,1250, 2160, 1250 }
+ { 1, 1,2160,1250, 2160, 1250 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1600x1200Data[] =
{
{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
/* {27, 4, 800, 500, 2160, 1250 }, 640x400 (6235) */
@@ -1127,10 +1221,14 @@ static const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] =
{ 5, 2,1350, 800, 2160, 1250 },
{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
- { 1, 1,2160,1250, 2160, 1250 }
+ { 1, 1,2160,1250, 2160, 1250 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_NoScaleData[] =
+static const struct SiS_LCDData SiS_NoScaleData[] =
{
{ 1, 1, 800, 449, 800, 449 }, /* 0x00: 320x200, 640x400 */
{ 1, 1, 800, 449, 800, 449 },
@@ -1162,14 +1260,18 @@ static const SiS_LCDDataStruct SiS_NoScaleData[] =
{ 1, 1,1808, 808,1808, 808 }, /* 0x1b: 1360x768 */
{ 1, 1,1104, 563,1104, 563 }, /* 0x1c: 960x540 */
{ 1, 1,1120, 618,1120, 618 }, /* 0x1d: 960x600 */
- { 1, 1,1408, 816,1408, 816 } /* 0x1f: 1280x800 (TMDS special) */
+ { 1, 1,1408, 816,1408, 816 }, /* 0x1f: 1280x800 (TMDS special) */
+ { 1, 1,1760,1235,1760,1235 }, /* 0x20: 1600x1200 for LCDA */
+ { 1, 1,2048,1320,2048,1320 }, /* 0x21: 1600x1200 for non-SiS LVDS */
+ { 1, 1,1664, 861,1664, 861 } /* 0x22: 1280x854 */
};
/**************************************************************/
/* LVDS ----------------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]=
+/* FSTN/DSTN 320x240, 2 variants */
+static const struct SiS_LVDSData SiS_LVDS320x240Data_1[]=
{
{ 848, 433, 400, 525},
{ 848, 389, 400, 525},
@@ -1177,157 +1279,40 @@ static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]=
{ 848, 389, 400, 525},
{ 848, 518, 400, 525},
{1056, 628, 400, 525},
- { 400, 525, 400, 525},
- { 800, 449,1000, 644},
- { 800, 525,1000, 635}
+ { 400, 525, 400, 525} /* xSTN */
};
-static const SiS_LVDSDataStruct SiS_LVDS640x480Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS320x240Data_2[]=
{
- { 800, 445, 800, 525}, /* 800, 449, 800, 449 */
+ { 800, 445, 800, 525},
{ 800, 395, 800, 525},
{ 800, 445, 800, 525},
{ 800, 395, 800, 525},
{ 800, 525, 800, 525},
- { 800, 525, 800, 525}, /* pseudo */
- { 800, 525, 800, 525} /* pseudo */
+ {1056, 628,1056, 628},
+ { 480, 525, 480, 525} /* xSTN */
};
-/* FSTN 320x240 */
-static const SiS_LVDSDataStruct SiS_LVDS640x480Data_2[]=
+static const struct SiS_LVDSData SiS_LVDS640x480Data_1[]=
{
- { 800, 445, 800, 525},
+ { 800, 445, 800, 525}, /* 800, 449, 800, 449 */
{ 800, 395, 800, 525},
{ 800, 445, 800, 525},
{ 800, 395, 800, 525},
- { 800, 525, 800, 525},
- { 800, 525, 800, 525}, /* pseudo */
- { 800, 525, 800, 525} /* pseudo */
+ { 800, 525, 800, 525}
};
-static const SiS_LVDSDataStruct SiS_LVDS800x600Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS800x600Data_1[]=
{
{ 848, 433,1060, 629},
{ 848, 389,1060, 629},
{ 848, 433,1060, 629},
{ 848, 389,1060, 629},
{ 848, 518,1060, 629},
- {1056, 628,1056, 628},
{1056, 628,1056, 628}
};
-static const SiS_LVDSDataStruct SiS_LVDS800x600Data_2[]=
-{
- {1056, 628,1056, 628}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_1[]=
-{
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 518,1344, 806}, /* 640x480 */
- {1050, 638,1344, 806}, /* 800x600 */
- {1344, 806,1344, 806}, /* 1024x768 */
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_1[]=
-{
- {1048, 442,1688,1066},
- {1048, 392,1688,1066},
- {1048, 442,1688,1066},
- {1048, 392,1688,1066},
- {1048, 522,1688,1066},
- {1208, 642,1688,1066},
- {1432, 810,1688,1066},
- {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_2[]=
-{
- {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_1[]=
-{
- { 928, 416, 1688,1066},
- { 928, 366, 1688,1066},
- { 928, 416, 1688,1066},
- { 928, 366, 1688,1066},
- { 928, 496, 1688,1066},
- {1088, 616, 1688,1066},
- {1312, 784, 1688,1066},
- {1568,1040, 1688,1066},
- {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_2[]=
-{
- {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_1[]=
-{
- {1088, 520, 2048,1320},
- {1088, 470, 2048,1320},
- {1088, 520, 2048,1320},
- {1088, 470, 2048,1320},
- {1088, 600, 2048,1320},
- {1248, 720, 2048,1320},
- {1472, 888, 2048,1320},
- {1728,1144, 2048,1320},
- {1848,1170, 2048,1320},
- {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_2[]=
-{
- {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_1[]=
-{
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 518,1344, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806},
- { 800, 449,1280, 801},
- { 800, 525,1280, 813}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_1[]=
-{
- { 768, 438, 1408, 806},
- { 768, 388, 1408, 806},
- { 768, 438, 1408, 806},
- { 768, 388, 1408, 806},
- { 768, 518, 1408, 806},
- { 928, 638, 1408, 806},
- {1152, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_2[]=
-{
- {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x600Data_1[] =
{
{ 840, 604,1344, 800},
{ 840, 560,1344, 800},
@@ -1338,124 +1323,18 @@ static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] =
{1344, 800,1344, 800}
};
-static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_2[] =
-{
- {1344, 800,1344, 800}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x768Data_1[]=
{
{ 840, 438,1344, 806},
{ 840, 409,1344, 806},
{ 840, 438,1344, 806},
{ 840, 409,1344, 806},
- { 840, 518,1344, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_2[] =
-{
- {1344, 806,1344, 806}
-};
-
-/* Pass 1:1 data */
-static const SiS_LVDSDataStruct SiS_LVDSXXXxXXXData_1[]=
-{
- { 800, 449, 800, 449},
- { 800, 449, 800, 449},
- { 900, 449, 900, 449},
- { 900, 449, 900, 449},
- { 800, 525, 800, 525}, /* 640x480 */
- {1056, 628, 1056, 628}, /* 800x600 */
- {1344, 806, 1344, 806}, /* 1024x768 */
- {1688,1066, 1688,1066}, /* 1280x1024 */ /* INSERTED */
- {1688, 806, 1688, 806}, /* 1280x768 */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_1[]=
-{
- { 832, 438,1331, 806},
- { 832, 388,1331, 806},
- { 832, 438,1331, 806},
- { 832, 388,1331, 806},
- { 832, 518,1331, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806},
- {1688,1066,1688,1066},
- {1688,1066,1688,1066} /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_2[]=
-{
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1688,1066,1688,1066},
- {1688,1066,1688,1066} /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_1[]=
-{
- { 832, 438,1331, 806},
- { 832, 409,1331, 806},
- { 832, 438,1331, 806},
- { 832, 409,1331, 806},
- { 832, 518,1331, 806}, /* 640x480 */
+ { 840, 518,1344, 806}, /* 640x480 */
{1050, 638,1344, 806}, /* 800x600 */
{1344, 806,1344, 806}, /* 1024x768 */
};
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct SiS_LVDS848x480Data_1[]=
-{
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 640x480 TODO */
- {1088, 525,1088, 525}, /* 800x600 TODO */
- {1088, 525,1088, 525}, /* 1024x768 TODO */
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 848x480 */
- {1088, 525,1088, 525} /* 1360x768 TODO */
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct SiS_LVDS848x480Data_2[]=
-{
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 640x480 */
- {1088, 525,1088, 525}, /* 800x600 */
- {1088, 525,1088, 525}, /* 1024x768 */
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 848x480 */
- {1088, 525,1088, 525} /* 1360x768 TODO */
-};
-
-static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVUNTSCData[]=
{
{ 840, 600, 840, 600},
{ 840, 600, 840, 600},
@@ -1466,7 +1345,7 @@ static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]=
{1160, 945,1160, 945}
};
-static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVONTSCData[]=
{
{ 840, 525, 840, 525},
{ 840, 525, 840, 525},
@@ -1477,55 +1356,9 @@ static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]=
{1160, 840,1160, 840}
};
-/* Chrontel TV Skew */
-
-static const SiS_LVDSDesStruct SiS_CHTVUNTSCDesData[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVONTSCDesData[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVUPALDesData[]=
-{
- {256, 0},
- {256, 0},
- {256, 0},
- {256, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVOPALDesData[]=
-{
- {256, 0},
- {256, 0},
- {256, 0},
- {256, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
/* CRT1 CRTC data for slave modes */
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_1[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1550,48 +1383,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] =
0x00 }}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1_H[] =
-{
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2[] =
{
{{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
@@ -1611,12 +1403,17 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] =
{{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
0x01}},
+#if 0
{{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
0x00}}
+#endif
+ {{0x5f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00}},
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2_H[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1641,7 +1438,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3[] =
{
{{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
@@ -1666,7 +1463,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3_H[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1691,778 +1488,175 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
- 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
- 0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
- 0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1[] =
-{
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e,
- 0xec,0x8e,0xdf,0x05,0x20,0x00,0x01,
- 0x00}},
- {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0,
- 0x64,0x86,0x57,0x7d,0x20,0x00,0x05,
- 0x01}},
- {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1[] =
{
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2[] =
-{
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3,
- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x02,
- 0x01}},
- {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1,
- 0xb6,0x88,0x57,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
{
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3,
- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x01,
- 0x01}},
- {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1,
- 0xb6,0x88,0x57,0x25,0x10,0x00,0x01,
- 0x01}},
- {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}}
-};
-
-/**************************************************************/
-/* COMMON --------------------------------------------------- */
-/**************************************************************/
-
-#ifdef LINUX_XF86
-
-#define SIS_PL_HSYNCP 0x01
-#define SIS_PL_HSYNCN 0x02
-#define SIS_PL_VSYNCP 0x04
-#define SIS_PL_VSYNCN 0x08
-#define SIS_PL_DVI 0x80
-
-typedef struct _SiS_PlasmaModes
-{
- const char *name;
- ULONG clock;
- USHORT HDisplay, HTotal, HFrontPorch, HSyncWidth;
- USHORT VDisplay, VTotal, VFrontPorch, VSyncWidth;
- UCHAR SyncFlags;
-} SiS_PlasmaModes;
-
-typedef struct _SiS_PlasmaTables
-{
- USHORT vendor;
- UCHAR productnum;
- USHORT product[5];
- const char *DDCnames[5];
- const char *plasmaname;
- USHORT maxx,maxy;
- USHORT prefx, prefy;
- UCHAR modenum;
- UCHAR plasmamodes[20]; /* | 0x80 = DVI-capable, | 0x40 = analog */
-} SiS_PlasmaTables;
-
-static const SiS_PlasmaModes SiS_PlasmaMode[] = {
- { "640x400", /* 00: IBM 400@70 */
- 25175,
- 640, 800, 17, 64,
- 400, 449, 13, 2,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "640x480", /* 01: VESA 480@72 */
- 31500,
- 640, 832, 24, 40,
- 480, 520, 9, 3,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "800x600", /* 02: VESA 600@72 */
- 50000,
- 800, 1040, 56, 120,
- 600, 666, 37, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "864x480", /* 03: Cereb wide 1 */
- 42526,
- 864, 1134, 22, 86,
- 480, 500, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCN },
- { "848x480", /* 04: VESA wide (NEC1) */
- 33750,
- 848, 1088, 16, 112,
- 480, 517, 6, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1024x576", /* 05: VESA wide (NEC2) */
- 47250,
- 1024, 1320, 16, 144,
- 576, 596, 2, 4,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720", /* 06: VESA wide (NEC3) */
- 76500,
- 1280, 1696, 48, 176,
- 720, 750, 4, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1360x765", /* 07: VESA wide (NEC4) */
- 85500,
- 1360, 1792, 64, 176,
- 765, 795, 4, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1024x600", /* 08: CEREB wide 2 */
- 51200,
- 1024, 1352, 51, 164,
- 600, 628, 1, 4,
- SIS_PL_HSYNCN | SIS_PL_VSYNCP },
- { "1024x768", /* 09: VESA 768@75 */
- 78750,
- 1024, 1312, 16, 96,
- 768, 800, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1152x864", /* 10: VESA 1152x864@75 */
- 108000,
- 1152, 1600, 64, 128,
- 864, 900, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x1024", /* 11: VESA 1024@60 */
- 108000,
- 1280, 1688, 48, 112,
- 1024, 1066, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x768", /* 12: W_XGA */
- 81000,
- 1280, 1688, 48, 112,
- 768, 802, 3, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCN },
- { "1280x768", /* 13: I/O Data W_XGA@56Hz */
- 76064,
- 1280, 1688, 48, 112,
- 768, 802, 2, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1376x768", /* 14: I/O Wide XGA */
- 87340,
- 1376, 1808, 32, 128,
- 768, 806, 3, 6,
- SIS_PL_HSYNCN | SIS_PL_VSYNCP },
- { "1280x960", /* 15: VESA 960@60 */
- 108000,
- 1280, 1800, 96, 112,
- 960, 1000, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1400x1050", /* 16: VESA 1050@60Hz */
- 108000,
- 1400, 1688, 48, 112,
- 1050, 1066, 1, 3,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "1360x768", /* 17: VESA wide (NEC4/2) */
- 85500,
- 1360, 1792, 64, 112,
- 765, 795, 3, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "800x600", /* 18: VESA 600@56 */
- 36000,
- 800, 1024, 24, 2,
- 600, 625, 1, 2,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1072x600", /* 19: Panasonic 1072x600 (sync?) */
- 54100,
- 1072, 1424, 48, 176,
- 600, 628, 16, 1,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "848x480", /* 20: Panasonic 848x480 (sync?) */
- 33070, /* is 852x480, but we can't use 852 */
- 848, 1068, 20, 40, /* differs from DDC data, better centered */
- 480, 516, 3, 5, /* won't work assumingly, because data is % 8 */
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "1280x720", /* 21: WIDE720(60) (aka "750p") (Panasonic) */
- 74300,
- 1280, 1650,110, 40,
- 720, 750, 5, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x768", /* 22: 1280x768@56.5 (Panasonic) */
- 76200, /* (According to manual not supported for HDMI; but works) */
- 1280, 1680, 16, 24,
- 768, 802, 2, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720@50", /* 23: WIDE720(50) (aka "750p") (Panasonic) */
- 74300, /* Panasonic states 45.0kHz. Not possible. This one works (with some overscan) */
- 1280, 1980,400, 80,
- 720, 750, 1, 2,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "720x480", /* 24: 720x480 (aka "525p" and "480p") (Panasonic) */
- 27000,
- 720, 856, 40, 32,
- 480, 525, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "720x576", /* 25: 720x576 (aka "625p"and "576p") (Panasonic) */
- 27500,
- 720, 864, 16, 64,
- 576, 625, 5, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720@50", /* 26: WIDE720(50) (aka "750p") (Generic) */
- 74300,
- 1280, 1980,400, 80,
- 720, 750, 5, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
+ {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}
};
-/*
-27.00 720 755 791 858 480 480 484 525
-27.50 720 732 795 864 576 581 587 625
-*/
-
-static const SiS_PlasmaTables SiS_PlasmaTable[] = {
-#if 0 /* Product IDs missing */
- { 0x38a3, 4,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42VP4/42VP4D/42VP4G/42VP4DG",
- 0, 0,
- 0, 0,
- 11, /* All DVI, except 0, 7, 13 */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
+BOOLEAN SiSInitPtr(struct SiS_Private *SiS_Pr);
+#ifdef SIS_XORG_XF86
+unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
#endif
-#if 0 /* Product IDs missing */
- { 0x38a3, 3,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42PD1/50PD1/50PD2",
- 0, 0,
- 0, 0,
- 5, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0, 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42PD3",
- 0, 0,
- 0, 0,
- 10, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 7|0x40, 8|0xc0, 9|0xc0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 2,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42VM3/61XM1",
- 0, 0,
- 0, 0,
- 11, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 8|0xc0, 9|0xc0,11|0xc0,
- 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 2,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42MP1/42MP2",
- 0, 0,
- 0, 0,
- 6, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 50MP1",
- 0, 0,
- 0, 0,
- 10, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
+unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, BOOLEAN FSTN,
+ unsigned short CustomT, int LCDwith, int LCDheight,
+ unsigned int VBFlags2);
+unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+
+void SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
+void SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
+void SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
+void SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
+unsigned char SiS_GetReg(SISIOADDRESS port, unsigned short index);
+unsigned char SiS_GetRegByte(SISIOADDRESS port);
+unsigned short SiS_GetRegShort(SISIOADDRESS port);
+unsigned int SiS_GetRegLong(SISIOADDRESS port);
+void SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
+ unsigned short DataOR);
+void SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
+void SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
+
+void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+#ifndef SIS_LINUX_KERNEL
+void SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
#endif
- { 0x38a3, 4,
- { 0xa482, 0xa483, 0x0000, 0x0000, 0x0000 },
- { "PX-42VM", "", "", "", "" },
- "NEC PlasmaSync 42MP3/42MP4/50MP2/61MP1",
- 0, 0,
- 0, 0,
- 11, /* All DVI except 0, 7, 13, 17 */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 17|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
-#if 0 /* Product IDs missing */
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 3300W",
- 0, 0,
- 0, 0,
- 3,
- { 0|0x40, 1|0xc0,18|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 4200W",
- 4, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 4210W",
- 0, 0,
- 0, 0,
- 6, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 5000W",
- 0, 0,
- 0, 0,
- 7, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,11|0xc0, 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
-#endif
- { 0x412f, 2,
- { 0x000c, 0x000b, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "Pioneer 503CMX/PDA-5002",
- 0, 0,
- 0, 0,
- 6, /* DVI unknown */
- { 1|0xc0, 2|0xc0, 9|0xc0,11|0xc0,12|0xc0,15|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xa00e, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "Panasonic TH-42",
- 0, 0,
- 0, 0,
- 5, /* No DVI output */
- { 1|0x40, 2|0x40, 4|0x40, 9|0x40,15|0x40, 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xa005, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "TH-42PW*4", "", "", "", "" },
- "Panasonic TH-42PW5",
- 0, 0,
- 0, 0,
- 1, /* No special modes otherwise; no DVI. */
- {20|0x40,19|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x4c2e, 1,
- { 0x9b05, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "PLV-Z2", "", "", "", "" },
- "Sanyo PLV-Z2 (non HDCP-mode)", /* HDCP mode would be id 9b06, but not needed */
- 1280, 768, /* as it then advertises correct size */
- 1280, 720,
- 1, /* 1280x720, no special modes otherwise */
- {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xd034, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "AE500U (DVI-D)", "", "", "", "" },
- "Panasonic AE500U",
- 1280, 768,
- 1280, 720,
- 1, /* 1280x720, no special modes otherwise */
- {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xd043, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "AE700U (HDMI)", "", "", "", "" },
- "Panasonic AE700U",
- 1360, 768,
- 1280, 720,
- 6, /* 1280x720/60, 1280x720/50, 1280x768@56(digital/analog), 720x480, 720x576 */
- {21|0xc0,23|0xc0,22|0x80,13|0x40,24|0x80,25|0x80, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x0000 }
-};
+void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+BOOLEAN SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_GetVBType(struct SiS_Private *SiS_Pr);
#endif
-#ifdef LINUX_XF86
-USHORT SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
+BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex);
+unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+#ifdef SIS300
+void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+ unsigned short *idx2);
+unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
+unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
#endif
-USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
- USHORT CustomT, int LCDwith, int LCDheight);
-USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-void SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data);
-void SiS_SetRegByte(SISIOADDRESS port, USHORT data);
-void SiS_SetRegShort(SISIOADDRESS port, USHORT data);
-void SiS_SetRegLong(SISIOADDRESS port, ULONG data);
-UCHAR SiS_GetReg(SISIOADDRESS port, USHORT index);
-UCHAR SiS_GetRegByte(SISIOADDRESS port);
-USHORT SiS_GetRegShort(SISIOADDRESS port);
-ULONG SiS_GetRegLong(SISIOADDRESS port);
-void SiS_SetRegANDOR(SISIOADDRESS Port, USHORT Index, USHORT DataAND, USHORT DataOR);
-void SiS_SetRegAND(SISIOADDRESS Port,USHORT Index, USHORT DataAND);
-void SiS_SetRegOR(SISIOADDRESS Port,USHORT Index, USHORT DataOR);
-void SiS_DisplayOn(SiS_Private *SiS_Pr);
-void SiS_DisplayOff(SiS_Private *SiS_Pr);
-void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex);
-UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
-void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-
-#ifdef LINUX_XF86
-BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
-BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-int SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber);
-int SiSTranslateToOldMode(int modenumber);
-BOOLEAN SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO);
-USHORT SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags);
-DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi);
-int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy);
-void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-#else
-BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo);
+void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
+ BOOLEAN dosetpitch);
+BOOLEAN SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+#endif
+#ifdef SIS_LINUX_KERNEL
+BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+#endif
+void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, DisplayModePtr current);
+#endif
+#ifdef SIS_LINUX_KERNEL
+void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
#endif
-#ifdef LINUX_KERNEL
-int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, UCHAR rateindex);
-int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, UCHAR rateindex,
- struct fb_var_screeninfo *var);
-BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, int *htotal, int *vtotal, UCHAR rateindex);
+/* From init301.c: */
+extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int chkcrt2mode);
+extern void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+extern void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+extern void SiS_DisableBridge(struct SiS_Private *);
+extern BOOLEAN SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+extern unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+extern BOOLEAN SiS_IsVAMode(struct SiS_Private *);
+extern BOOLEAN SiS_IsDualEdge(struct SiS_Private *);
+
+#ifdef SIS_XORG_XF86
+/* From other modules: */
+extern unsigned short SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ unsigned int VBFlags);
+extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
+ unsigned char value);
+extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
+extern unsigned short SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ unsigned int VBFlags);
#endif
-/* init301.c: */
-extern void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, int chkcrt2mode);
-extern void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo);
-extern void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT);
-extern USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo);
-extern void SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-extern USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-extern USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern BOOLEAN SiS_IsVAMode(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN SiS_IsDualEdge(SiS_Private *, PSIS_HW_INFO);
-
-#ifdef LINUX_XF86
-/* From other sis driver modules: */
-extern int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div,
- int *out_sbit, int *out_scale);
-extern void SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk);
-
-extern UCHAR SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, UCHAR value);
-extern UCHAR SiS_GetSetModeID(ScrnInfoPtr pScrn, UCHAR id);
-extern USHORT SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, ULONG VBFlags);
+#ifdef SIS_LINUX_KERNEL
+#ifdef SIS300
+extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
+ unsigned int val);
+#endif
+#ifdef SIS315H
+extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
+ unsigned char val);
+extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
#endif
#endif
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 274dacd54bb8..2d88f908170a 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -2,11 +2,12 @@
/* $XdotOrg$ */
/*
* Mode initializing code (CRT2 section)
- * for SiS 300/305/540/630/730 and
- * SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
+ * for SiS 300/305/540/630/730,
+ * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -38,7 +39,7 @@
* * 3) 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 EXPRESSED OR
+ * * 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,
@@ -54,20 +55,20 @@
* Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
* Used by permission.
*
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if marked TW or not.
- *
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#if 1
#define SET_EMI /* 302LV/ELV: Set EMI values */
#endif
+#if 1
+#define SET_PWD /* 301/302LV: Set PWD */
+#endif
+
#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */
#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */
#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */
@@ -85,26 +86,35 @@
#define SiS_I2CDELAY 1000
#define SiS_I2CDELAYSHORT 150
-static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
-static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx);
+static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
+#ifdef SIS_LINUX_KERNEL
+static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+#endif
/*********************************************/
/* HELPER: Lock/Unlock CRT2 */
/*********************************************/
void
-SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H)
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+ else if(SiS_Pr->ChipType >= SIS_315H)
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
else
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
}
-static void
-SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_LockCRT2(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H)
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+ else if(SiS_Pr->ChipType >= SIS_315H)
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
else
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
@@ -115,9 +125,9 @@ SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
+SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
{
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
DataAND &= 0x0f;
DataOR &= 0x0f;
}
@@ -129,12 +139,12 @@ SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, US
/*********************************************/
#ifdef SIS315H
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char *
+GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- UCHAR *myptr = NULL;
- USHORT romindex = 0, reg = 0, idx = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned char *myptr = NULL;
+ unsigned short romindex = 0, reg = 0, idx = 0;
/* Use the BIOS tables only for LVDS panels; TMDS is unreliable
* due to the variaty of panels the BIOS doesn't know about.
@@ -144,15 +154,15 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
if((SiS_Pr->SiS_ROMNew) &&
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
- if(HwInfo->jChipType < SIS_661) reg = 0x3c;
- else reg = 0x7d;
+ if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
+ else reg = 0x7d;
idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
if(idx < (8*26)) {
- myptr = (UCHAR *)&SiS_LCDStruct661[idx];
+ myptr = (unsigned char *)&SiS_LCDStruct661[idx];
}
romindex = SISGETROMW(0x100);
if(romindex) {
@@ -163,11 +173,11 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
return myptr;
}
-static USHORT
-GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = 0;
/* Use the BIOS tables only for LVDS panels; TMDS is unreliable
* due to the variaty of panels the BIOS doesn't know about.
@@ -177,12 +187,12 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
if((SiS_Pr->SiS_ROMNew) &&
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
romptr = SISGETROMW(0x102);
romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
}
- return(romptr);
+ return romptr;
}
#endif
@@ -191,186 +201,187 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static BOOLEAN
-SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo)
+SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RRTI, unsigned short *i)
{
- USHORT checkmask=0,modeid,infoflag;
+ unsigned short checkmask=0, modeid, infoflag;
- modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
+ modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
- checkmask |= SupportRAMDAC2;
- if(HwInfo->jChipType >= SIS_315H) {
- checkmask |= SupportRAMDAC2_135;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- checkmask |= SupportRAMDAC2_162;
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
- checkmask |= SupportRAMDAC2_202;
- }
- }
- }
+ checkmask |= SupportRAMDAC2;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ checkmask |= SupportRAMDAC2_135;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ checkmask |= SupportRAMDAC2_162;
+ if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
+ checkmask |= SupportRAMDAC2_202;
+ }
+ }
+ }
- } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- checkmask |= SupportLCD;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- if(modeid == 0x2e) checkmask |= Support64048060Hz;
- }
- }
- }
+ checkmask |= SupportLCD;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(modeid == 0x2e) checkmask |= Support64048060Hz;
+ }
+ }
+ }
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- checkmask |= SupportHiVision;
+ checkmask |= SupportHiVision;
- } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
+ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
- checkmask |= SupportTV;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- checkmask |= SupportTV1024;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- checkmask |= SupportYPbPr750p;
- }
- }
- }
+ checkmask |= SupportTV;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ checkmask |= SupportTV1024;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+ checkmask |= SupportYPbPr750p;
+ }
+ }
+ }
- }
+ }
- } else { /* LVDS */
+ } else { /* LVDS */
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- checkmask |= SupportCHTV;
- }
- }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ checkmask |= SupportCHTV;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- checkmask |= SupportLCD;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ checkmask |= SupportLCD;
+ }
- }
+ }
- /* Look backwards in table for matching CRT2 mode */
- for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
- infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
- if(infoflag & checkmask) return TRUE;
- if((*i) == 0) break;
- }
+ /* Look backwards in table for matching CRT2 mode */
+ for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+ if(infoflag & checkmask) return TRUE;
+ if((*i) == 0) break;
+ }
- /* Look through the whole mode-section of the table from the beginning
- * for a matching CRT2 mode if no mode was found yet.
- */
- for((*i) = 0; ; (*i)++) {
- if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
- infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
- if(infoflag & checkmask) return TRUE;
- }
- return FALSE;
+ /* Look through the whole mode-section of the table from the beginning
+ * for a matching CRT2 mode if no mode was found yet.
+ */
+ for((*i) = 0; ; (*i)++) {
+ if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+ if(infoflag & checkmask) return TRUE;
+ }
+ return FALSE;
}
/*********************************************/
/* Get rate index */
/*********************************************/
-USHORT
-SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
-{
- SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x00, 0x00, 0x00 };
- USHORT RRTI,i,backup_i;
- USHORT modeflag,index,temp,backupindex;
+unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+ unsigned short RRTI,i,backup_i;
+ unsigned short modeflag,index,temp,backupindex;
+ static const unsigned short LCDRefreshIndex[] = {
+ 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00
+ };
- /* Do NOT check for UseCustomMode here, will skrew up FIFO */
- if(ModeNo == 0xfe) return 0;
+ /* Do NOT check for UseCustomMode here, will skrew up FIFO */
+ if(ModeNo == 0xfe) return 0;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(modeflag & HalfDCLK) return 0;
- }
- }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(modeflag & HalfDCLK) return 0;
+ }
+ }
- if(ModeNo < 0x14) return 0xFFFF;
+ if(ModeNo < 0x14) return 0xFFFF;
- index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
- backupindex = index;
+ index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
+ backupindex = index;
- if(index > 0) index--;
+ if(index > 0) index--;
- if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
- else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
- temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
- if(index > temp) index = temp;
- }
- }
- } else {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
- }
- }
- }
+ if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
+ else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
+ temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
+ if(index > temp) index = temp;
+ }
+ }
+ } else {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
+ }
+ }
+ }
- RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
- if(HwInfo->jChipType >= SIS_315H) {
- if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
- if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
- (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
- if(backupindex <= 1) RRTI++;
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
+ if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
+ (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
+ if(backupindex <= 1) RRTI++;
+ }
+ }
+ }
- i = 0;
- do {
- if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
- temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
- temp &= ModeTypeMask;
- if(temp < SiS_Pr->SiS_ModeType) break;
- i++;
- index--;
- } while(index != 0xFFFF);
-
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
- if(temp & InterlaceMode) i++;
- }
- }
+ i = 0;
+ do {
+ if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
+ temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
+ temp &= ModeTypeMask;
+ if(temp < SiS_Pr->SiS_ModeType) break;
+ i++;
+ index--;
+ } while(index != 0xFFFF);
+
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
+ if(temp & InterlaceMode) i++;
+ }
+ }
- i--;
+ i--;
- if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
- backup_i = i;
- if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) {
- i = backup_i;
- }
- }
+ if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
+ backup_i = i;
+ if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
+ i = backup_i;
+ }
+ }
- return(RRTI + i);
+ return (RRTI + i);
}
/*********************************************/
@@ -378,15 +389,15 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp1,temp2;
+ unsigned short temp1, temp2;
- /* Store CRT1 ModeNo in CR34 */
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
- temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
- temp2 = ~(SetInSlaveMode >> 8);
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
+ /* Store CRT1 ModeNo in CR34 */
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
+ temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
+ temp2 = ~(SetInSlaveMode >> 8);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
}
/*********************************************/
@@ -395,35 +406,35 @@ SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
#ifdef SIS300
static BOOLEAN
-SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,temp1;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp,temp1;
- if(SiS_Pr->SiS_UseROM) {
- if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
- temp1 = SISGETROMW(0x23b);
- if(temp1 & temp) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_Pr->SiS_UseROM) {
+ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+ temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+ temp1 = SISGETROMW(0x23b);
+ if(temp1 & temp) return TRUE;
+ }
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,temp1;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp,temp1;
- if(SiS_Pr->SiS_UseROM) {
- if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
- temp1 = SISGETROMW(0x23d);
- if(temp1 & temp) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_Pr->SiS_UseROM) {
+ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+ temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+ temp1 = SISGETROMW(0x23d);
+ if(temp1 & temp) return TRUE;
+ }
+ }
+ return FALSE;
}
#endif
@@ -432,85 +443,76 @@ SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime)
+SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
{
- USHORT i, j;
+ unsigned int i, j;
- for(i=0; i<delaytime; i++) {
- j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
- }
+ for(i = 0; i < delaytime; i++) {
+ j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
+ }
}
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- USHORT temp,flag;
-
- flag = SiS_GetRegByte(0x61) & 0x10;
-
- while(delay) {
- temp = SiS_GetRegByte(0x61) & 0x10;
- if(temp == flag) continue;
- flag = temp;
- delay--;
- }
+ SiS_DDC2Delay(SiS_Pr, delay * 36);
}
#endif
#ifdef SIS315H
static void
-SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- while(delay--) {
- SiS_GenericDelay(SiS_Pr,0x19df);
- }
+ while(delay--) {
+ SiS_GenericDelay(SiS_Pr, 6623);
+ }
}
#endif
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- while(delay--) {
- SiS_GenericDelay(SiS_Pr,0x42);
- }
+ while(delay--) {
+ SiS_GenericDelay(SiS_Pr, 66);
+ }
}
#endif
static void
-SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
+SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
{
#if defined(SIS300) || defined(SIS315H)
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT PanelID, DelayIndex, Delay=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short PanelID, DelayIndex, Delay=0;
#endif
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
+ if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
}
DelayIndex = PanelID >> 4;
if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
- Delay = 3;
+ Delay = 3;
} else {
- if(DelayTime >= 2) DelayTime -= 2;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
- }
+ if(DelayTime >= 2) DelayTime -= 2;
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+ }
if(SiS_Pr->SiS_UseROM) {
- if(ROMAddr[0x220] & 0x40) {
- if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
- else Delay = (USHORT)ROMAddr[0x226];
- }
- }
+ if(ROMAddr[0x220] & 0x40) {
+ if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
+ else Delay = (unsigned short)ROMAddr[0x226];
+ }
+ }
}
SiS_ShortDelay(SiS_Pr, Delay);
@@ -520,23 +522,23 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
#ifdef SIS315H
- if((HwInfo->jChipType >= SIS_661) ||
- (HwInfo->jChipType <= SIS_315PRO) ||
- (HwInfo->jChipType == SIS_330) ||
+ if((SiS_Pr->ChipType >= SIS_661) ||
+ (SiS_Pr->ChipType <= SIS_315PRO) ||
+ (SiS_Pr->ChipType == SIS_330) ||
(SiS_Pr->SiS_ROMNew)) {
- if(!(DelayTime & 0x01)) {
+ if(!(DelayTime & 0x01)) {
SiS_DDC2Delay(SiS_Pr, 0x1000);
- } else {
+ } else {
SiS_DDC2Delay(SiS_Pr, 0x4000);
- }
+ }
} else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
- (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+ (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
}
@@ -546,35 +548,35 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
DelayIndex = PanelID >> 4;
}
if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
- Delay = 3;
- } else {
- if(DelayTime >= 2) DelayTime -= 2;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
- }
+ Delay = 3;
+ } else {
+ if(DelayTime >= 2) DelayTime -= 2;
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
+ }
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- if(ROMAddr[0x13c] & 0x40) {
- if(!(DelayTime & 0x01)) {
- Delay = (USHORT)ROMAddr[0x17e];
- } else {
- Delay = (USHORT)ROMAddr[0x17f];
- }
- }
- }
- }
+ if(ROMAddr[0x13c] & 0x40) {
+ if(!(DelayTime & 0x01)) {
+ Delay = (unsigned short)ROMAddr[0x17e];
+ } else {
+ Delay = (unsigned short)ROMAddr[0x17f];
+ }
+ }
+ }
+ }
SiS_ShortDelay(SiS_Pr, Delay);
}
} else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
- }
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+ }
Delay <<= 8;
SiS_DDC2Delay(SiS_Pr, Delay);
@@ -587,12 +589,11 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
#ifdef SIS315H
static void
-SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT DelayTime, USHORT DelayLoop)
+SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
{
int i;
- for(i=0; i<DelayLoop; i++) {
- SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime);
+ for(i = 0; i < DelayLoop; i++) {
+ SiS_PanelDelay(SiS_Pr, DelayTime);
}
}
#endif
@@ -602,86 +603,86 @@ SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
void
-SiS_WaitRetrace1(SiS_Private *SiS_Pr)
+SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
{
- USHORT watchdog;
+ unsigned short watchdog;
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
- if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
- watchdog = 65535;
- while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
- watchdog = 65535;
- while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
+ watchdog = 65535;
+ while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
+ watchdog = 65535;
+ while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
}
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
+SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
{
- USHORT watchdog;
+ unsigned short watchdog;
- watchdog = 65535;
- while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
- watchdog = 65535;
- while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
+ watchdog = 65535;
+ while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
+ watchdog = 65535;
+ while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
}
#endif
static void
-SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
- }
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
- SiS_WaitRetrace1(SiS_Pr);
- } else {
- SiS_WaitRetrace2(SiS_Pr, 0x25);
- }
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
+ }
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
+ SiS_WaitRetrace1(SiS_Pr);
+ } else {
+ SiS_WaitRetrace2(SiS_Pr, 0x25);
+ }
#endif
- } else {
+ } else {
#ifdef SIS315H
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
- SiS_WaitRetrace1(SiS_Pr);
- } else {
- SiS_WaitRetrace2(SiS_Pr, 0x30);
- }
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
+ SiS_WaitRetrace1(SiS_Pr);
+ } else {
+ SiS_WaitRetrace2(SiS_Pr, 0x30);
+ }
#endif
- }
+ }
}
static void
-SiS_VBWait(SiS_Private *SiS_Pr)
+SiS_VBWait(struct SiS_Private *SiS_Pr)
{
- USHORT tempal,temp,i,j;
+ unsigned short tempal,temp,i,j;
- temp = 0;
- for(i=0; i<3; i++) {
- for(j=0; j<100; j++) {
- tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
- if(temp & 0x01) {
- if((tempal & 0x08)) continue;
- else break;
- } else {
- if(!(tempal & 0x08)) continue;
- else break;
- }
- }
- temp ^= 0x01;
- }
+ temp = 0;
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 100; j++) {
+ tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
+ if(temp & 0x01) {
+ if((tempal & 0x08)) continue;
+ else break;
+ } else {
+ if(!(tempal & 0x08)) continue;
+ else break;
+ }
+ }
+ temp ^= 0x01;
+ }
}
static void
-SiS_VBLongWait(SiS_Private *SiS_Pr)
+SiS_VBLongWait(struct SiS_Private *SiS_Pr)
{
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_VBWait(SiS_Pr);
- } else {
- SiS_WaitRetrace1(SiS_Pr);
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ SiS_VBWait(SiS_Pr);
+ } else {
+ SiS_WaitRetrace1(SiS_Pr);
+ }
}
/*********************************************/
@@ -690,237 +691,225 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
#ifdef SIS300
static BOOLEAN
-SiS_Is301B(SiS_Private *SiS_Pr)
+SiS_Is301B(struct SiS_Private *SiS_Pr)
{
- if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
- return FALSE;
+ if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType == SIS_730) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13);
- if(flag & 0x20) return TRUE;
- }
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & 0x20) return TRUE;
- return FALSE;
+ if(SiS_Pr->ChipType == SIS_730) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
+ return FALSE;
}
BOOLEAN
-SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableDualEdge) return TRUE;
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
+ }
+ }
#endif
- return FALSE;
+ return FALSE;
}
BOOLEAN
-SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAMode(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
+ }
#endif
- return FALSE;
+ return FALSE;
}
#ifdef SIS315H
static BOOLEAN
-SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
{
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) return TRUE;
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
- return FALSE;
+ if(SiS_IsVAMode(SiS_Pr)) return TRUE;
+ if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualLink(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ||
- (SiS_IsVAMode(SiS_Pr, HwInfo))) {
- if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if((SiS_CRT2IsLCD(SiS_Pr)) ||
+ (SiS_IsVAMode(SiS_Pr))) {
+ if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
+ }
+ }
#endif
- return FALSE;
+ return FALSE;
}
#ifdef SIS315H
static BOOLEAN
-SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_TVEnabled(struct SiS_Private *SiS_Pr)
{
- if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
- if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
- }
- return FALSE;
+ if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+ if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
{
- if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
- return FALSE;
+ if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
{
- if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
- }
- return FALSE;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType == SIS_650) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f);
- flag &= 0xF0;
- /* Check for revision != A0 only */
- if((flag == 0xe0) || (flag == 0xc0) ||
- (flag == 0xb0) || (flag == 0x90)) return FALSE;
- } else if(HwInfo->jChipType >= SIS_661) return FALSE;
- return TRUE;
+ if(SiS_Pr->ChipType == SIS_650) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+ /* Check for revision != A0 only */
+ if((flag == 0xe0) || (flag == 0xc0) ||
+ (flag == 0xb0) || (flag == 0x90)) return FALSE;
+ } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
+ return TRUE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ /* YPrPb = 0x08 */
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsChScart(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 */
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ /* Scart = 0x04 */
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToTV) return TRUE;
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
- if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */
- } else {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToTV) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToTV) return TRUE;
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
+ if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */
+ } else {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToTV) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToLCD) return TRUE;
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & SetToLCDA) return TRUE;
- } else {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToLCD) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToLCD) return TRUE;
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(flag & SetToLCDA) return TRUE;
+ } else {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToLCD) return TRUE;
+ }
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_BridgeIsOn(SiS_Private *SiS_Pr)
+SiS_HaveBridge(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- return TRUE;
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
- if((flag == 1) || (flag == 2)) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ return TRUE;
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+ if((flag == 1) || (flag == 2)) return TRUE;
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(SiS_BridgeIsOn(SiS_Pr)) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- if(HwInfo->jChipType < SIS_315H) {
- flag &= 0xa0;
- if((flag == 0x80) || (flag == 0x20)) return TRUE;
- } else {
- flag &= 0x50;
- if((flag == 0x40) || (flag == 0x10)) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_HaveBridge(SiS_Pr)) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ flag &= 0xa0;
+ if((flag == 0x80) || (flag == 0x20)) return TRUE;
+ } else {
+ flag &= 0x50;
+ if((flag == 0x40) || (flag == 0x10)) return TRUE;
+ }
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
{
- USHORT flag1;
+ unsigned short flag1;
- flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
- if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
- return FALSE;
+ flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
+ if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
+ return FALSE;
}
/*********************************************/
@@ -928,119 +917,97 @@ SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
/*********************************************/
/* Setup general purpose IO for Chrontel communication */
+#ifdef SIS300
void
-SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
+SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
{
- unsigned long acpibase;
+ unsigned int acpibase;
unsigned short temp;
if(!(SiS_Pr->SiS_ChSW)) return;
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000874); /* get ACPI base */
- acpibase = SiS_GetRegLong(0xcfc);
+#ifdef SIS_LINUX_KERNEL
+ acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
#else
acpibase = pciReadLong(0x00000800, 0x74);
#endif
acpibase &= 0xFFFF;
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
+ if(!acpibase) return;
+ temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
temp &= 0xFEFF;
- SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp);
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
+ SiS_SetRegShort((acpibase + 0x3c), temp);
+ temp = SiS_GetRegShort((acpibase + 0x3c));
+ temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
temp &= 0xFEFF;
if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
- SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp);
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));
+ SiS_SetRegShort((acpibase + 0x3a), temp);
+ temp = SiS_GetRegShort((acpibase + 0x3a));
}
+#endif
void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, int checkcrt2mode)
+SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int checkcrt2mode)
{
- USHORT tempax,tempbx,temp;
- USHORT modeflag, resinfo=0;
+ unsigned short tempax, tempbx, temp;
+ unsigned short modeflag, resinfo = 0;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
+ SiS_Pr->SiS_SetFlag = 0;
- SiS_Pr->SiS_SetFlag = 0;
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
- SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
+ SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
- tempbx = 0;
- if(SiS_BridgeIsOn(SiS_Pr)) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-#if 0
- if(HwInfo->jChipType < SIS_661) {
- /* NO - YPbPr not set yet ! */
- if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
- temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */
- temp |= SetCRT2ToHiVision; /* 0x80 */
- }
- if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
- temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */
- temp |= SetCRT2ToSVIDEO; /* 0x08 */
- }
- }
-#endif
- tempbx |= temp;
- tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
- tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
- tempbx |= tempax;
+ if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+
+ tempbx = 0;
+
+ if(SiS_HaveBridge(SiS_Pr)) {
+
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ tempbx |= temp;
+ tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
+ tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
+ tempbx |= tempax;
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
if(ModeNo == 0x03) {
- /* Mode 0x03 is never in driver mode */
+ /* Mode 0x03 is never in driver mode */
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
}
if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
- /* Reset LCDA setting if not driver mode */
+ /* Reset LCDA setting if not driver mode */
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
if(IS_SIS650) {
- if(SiS_Pr->SiS_UseLCDA) {
+ if(SiS_Pr->SiS_UseLCDA) {
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
}
}
}
}
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
- tempbx |= SetCRT2ToLCDA;
+ if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
+ tempbx |= SetCRT2ToLCDA;
}
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
- tempbx &= ~(SetCRT2ToRAMDAC);
- }
-
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
- if(temp & 0x04) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
- if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
- else tempbx |= SetCRT2ToYPbPr525750;
- }
- } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) {
- if(temp & 0x04) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
- if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+ if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+ else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ tempbx |= SetCRT2ToYPbPr525750;
}
}
- }
+ }
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1048,7 +1015,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx |= SetCRT2ToLCDA;
}
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(temp & EnableCHYPbPr) {
+ if(temp & EnableCHYPbPr) {
tempbx |= SetCRT2ToCHYPbPr;
}
}
@@ -1057,44 +1024,49 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif /* SIS315H */
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
+ tempbx &= ~(SetCRT2ToRAMDAC);
+ }
+
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
temp = SetCRT2ToSVIDEO |
- SetCRT2ToAVIDEO |
- SetCRT2ToSCART |
- SetCRT2ToLCDA |
- SetCRT2ToLCD |
- SetCRT2ToRAMDAC |
- SetCRT2ToHiVision |
+ SetCRT2ToAVIDEO |
+ SetCRT2ToSCART |
+ SetCRT2ToLCDA |
+ SetCRT2ToLCD |
+ SetCRT2ToRAMDAC |
+ SetCRT2ToHiVision |
SetCRT2ToYPbPr525750;
- } else {
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- temp = SetCRT2ToAVIDEO |
+ } else {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ temp = SetCRT2ToAVIDEO |
SetCRT2ToSVIDEO |
SetCRT2ToSCART |
SetCRT2ToLCDA |
SetCRT2ToLCD |
SetCRT2ToCHYPbPr;
- } else {
- temp = SetCRT2ToLCDA |
+ } else {
+ temp = SetCRT2ToLCDA |
SetCRT2ToLCD;
}
} else {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- temp = SetCRT2ToTV | SetCRT2ToLCD;
- } else {
- temp = SetCRT2ToLCD;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ temp = SetCRT2ToTV | SetCRT2ToLCD;
+ } else {
+ temp = SetCRT2ToLCD;
}
}
- }
+ }
+
+ if(!(tempbx & temp)) {
+ tempax = DisableCRT2Display;
+ tempbx = 0;
+ }
- if(!(tempbx & temp)) {
- tempax = DisableCRT2Display;
- tempbx = 0;
- }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- USHORT clearmask = ( DriverMode |
+ unsigned short clearmask = ( DriverMode |
DisableCRT2Display |
LoadDACFlag |
SetNotSimuMode |
@@ -1102,106 +1074,104 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SetPALTV |
SwitchCRT2 |
SetSimuScanMode );
- if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
+
+ if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
- } else {
- if(HwInfo->jChipType >= SIS_315H) {
+
+ } else {
+
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempbx & SetCRT2ToLCDA) {
- tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
+ tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
}
}
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(tempbx & SetCRT2ToTV) {
- tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(tempbx & SetCRT2ToTV) {
+ tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
}
- }
- if(tempbx & SetCRT2ToLCD) {
- tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(tempbx & SetCRT2ToLCD) {
+ tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
+ }
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempbx & SetCRT2ToLCDA) {
tempbx |= SetCRT2ToLCD;
}
}
+
}
- if(tempax & DisableCRT2Display) {
- if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
- tempbx = SetSimuScanMode | DisableCRT2Display;
- }
- }
+ if(tempax & DisableCRT2Display) {
+ if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
+ tempbx = SetSimuScanMode | DisableCRT2Display;
+ }
+ }
- if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
+ if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
- modeflag &= (~CRT2Mode);
+ modeflag &= (~CRT2Mode);
}
}
- if(!(tempbx & SetSimuScanMode)) {
- if(tempbx & SwitchCRT2) {
- if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
- if( (HwInfo->jChipType >= SIS_315H) &&
- (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
- if(resinfo != SIS_RI_1600x1200) {
- tempbx |= SetSimuScanMode;
- }
- } else {
- tempbx |= SetSimuScanMode;
- }
+ if(!(tempbx & SetSimuScanMode)) {
+ if(tempbx & SwitchCRT2) {
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if(resinfo != SIS_RI_1600x1200) {
+ tempbx |= SetSimuScanMode;
+ }
}
- } else {
- if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
- if(!(tempbx & DriverMode)) {
- if(SiS_BridgeInSlavemode(SiS_Pr)) {
+ } else {
+ if(SiS_BridgeIsEnabled(SiS_Pr)) {
+ if(!(tempbx & DriverMode)) {
+ if(SiS_BridgeInSlavemode(SiS_Pr)) {
tempbx |= SetSimuScanMode;
- }
- }
- }
- }
- }
-
- if(!(tempbx & DisableCRT2Display)) {
- if(tempbx & DriverMode) {
- if(tempbx & SetSimuScanMode) {
- if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
- if( (HwInfo->jChipType >= SIS_315H) &&
- (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
- if(resinfo != SIS_RI_1600x1200) {
- tempbx |= SetInSlaveMode;
- }
- } else {
- tempbx |= SetInSlaveMode;
- }
- }
- }
- } else {
- tempbx |= SetInSlaveMode;
- }
- }
+ }
+ }
+ }
+ }
+ }
- }
+ if(!(tempbx & DisableCRT2Display)) {
+ if(tempbx & DriverMode) {
+ if(tempbx & SetSimuScanMode) {
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if(resinfo != SIS_RI_1600x1200) {
+ tempbx |= SetInSlaveMode;
+ }
+ }
+ }
+ } else {
+ tempbx |= SetInSlaveMode;
+ }
+ }
- SiS_Pr->SiS_VBInfo = tempbx;
+ }
- if(HwInfo->jChipType == SIS_630) {
- SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
- }
+ SiS_Pr->SiS_VBInfo = tempbx;
-#ifdef TWDEBUG
-#ifdef LINUX_KERNEL
- printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n",
+#ifdef SIS300
+ if(SiS_Pr->ChipType == SIS_630) {
+ SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
+ }
+#endif
+
+#ifdef SIS_LINUX_KERNEL
+#if 0
+ printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
#endif
-#ifdef LINUX_XF86
- xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
+#endif
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
#endif
#endif
@@ -1212,41 +1182,41 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
void
-SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
{
- UCHAR temp;
+ unsigned char temp;
- /* Note: This variable is only used on 30xLV systems.
- * CR38 has a different meaning on LVDS/CH7019 systems.
- * On 661 and later, these bits moved to CR35.
- *
- * On 301, 301B, only HiVision 1080i is supported.
- * On 30xLV, 301C, only YPbPr 1080i is supported.
- */
+ /* Note: This variable is only used on 30xLV systems.
+ * CR38 has a different meaning on LVDS/CH7019 systems.
+ * On 661 and later, these bits moved to CR35.
+ *
+ * On 301, 301B, only HiVision 1080i is supported.
+ * On 30xLV, 301C, only YPbPr 1080i is supported.
+ */
- SiS_Pr->SiS_YPbPr = 0;
- if(HwInfo->jChipType >= SIS_661) return;
+ SiS_Pr->SiS_YPbPr = 0;
+ if(SiS_Pr->ChipType >= SIS_661) return;
- if(SiS_Pr->SiS_VBType) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_YPbPr = YPbPrHiVision;
- }
- }
+ if(SiS_Pr->SiS_VBType) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+ }
+ }
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(temp & 0x08) {
- switch((temp >> 4)) {
- case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
- case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
- case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
- case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
- }
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(temp & 0x08) {
+ switch((temp >> 4)) {
+ case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
+ case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
+ case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
+ case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+ }
+ }
+ }
+ }
}
@@ -1255,199 +1225,204 @@ SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo)
+SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp, temp1, resinfo = 0, romindex = 0;
- UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp, temp1, resinfo = 0, romindex = 0;
+ unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
- SiS_Pr->SiS_TVMode = 0;
+ SiS_Pr->SiS_TVMode = 0;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
- if(SiS_Pr->UseCustomMode) return;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+ if(SiS_Pr->UseCustomMode) return;
- if(ModeNo > 0x13) {
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
+ if(ModeNo > 0x13) {
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
- if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- temp = 0;
- if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
- temp = 0x35;
- romindex = 0xfe;
- } else if(HwInfo->jChipType >= SIS_315H) {
- temp = 0x38;
- romindex = 0xf3;
- if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
- }
- if(temp) {
- if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- OutputSelect = ROMAddr[romindex];
- if(!(OutputSelect & EnablePALMN)) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
- }
- }
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(temp1 & EnablePALM) { /* 0x40 */
- SiS_Pr->SiS_TVMode |= TVSetPALM;
- SiS_Pr->SiS_TVMode &= ~TVSetPAL;
- } else if(temp1 & EnablePALN) { /* 0x80 */
- SiS_Pr->SiS_TVMode |= TVSetPALN;
- }
- } else {
- if(temp1 & EnableNTSCJ) { /* 0x40 */
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- }
- /* Translate HiVision/YPbPr to our new flags */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
- else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
- else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
- else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
- SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
- SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
- } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- }
- }
- } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_CHOverScan) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
- if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- if(SiS_Pr->SiS_CHSOverScan) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
- else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
- } else {
- if(temp & EnableNTSCJ) {
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- }
- }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ temp = 0;
+ if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
+ temp = 0x35;
+ romindex = 0xfe;
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = 0x38;
+ if(SiS_Pr->ChipType < XGI_20) {
+ romindex = 0xf3;
+ if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
+ }
+ }
+ if(temp) {
+ if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+ OutputSelect = ROMAddr[romindex];
+ if(!(OutputSelect & EnablePALMN)) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
+ }
+ }
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(temp1 & EnablePALM) { /* 0x40 */
+ SiS_Pr->SiS_TVMode |= TVSetPALM;
+ SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+ } else if(temp1 & EnablePALN) { /* 0x80 */
+ SiS_Pr->SiS_TVMode |= TVSetPALN;
+ }
+ } else {
+ if(temp1 & EnableNTSCJ) { /* 0x40 */
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ }
+ /* Translate HiVision/YPbPr to our new flags */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+ else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+ else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
+ else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
+ SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
+ SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
+ } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ }
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_CHOverScan) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
+ if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ if(SiS_Pr->SiS_CHSOverScan) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
+ else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
+ } else {
+ if(temp & EnableNTSCJ) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ }
+ }
- } else { /* 661 and later */
+ } else { /* 661 and later */
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if(temp1 & 0x01) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(temp1 & 0x08) {
- SiS_Pr->SiS_TVMode |= TVSetPALN;
- } else if(temp1 & 0x04) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SiS_Pr->SiS_TVMode &= ~TVSetPAL;
- }
- SiS_Pr->SiS_TVMode |= TVSetPALM;
- }
- } else {
- if(temp1 & 0x02) {
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_Pr->SiS_CHOverScan) {
- if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- }
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- temp1 &= 0xe0;
- if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
- else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
- else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
- if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
- SiS_Pr->SiS_TVMode |= TVAspect169;
- } else {
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
- if(temp1 & 0x02) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
- SiS_Pr->SiS_TVMode |= TVAspect169;
- } else {
- SiS_Pr->SiS_TVMode |= TVAspect43LB;
- }
- } else {
- SiS_Pr->SiS_TVMode |= TVAspect43;
- }
- }
- }
- }
- }
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ if(temp1 & 0x01) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(temp1 & 0x08) {
+ SiS_Pr->SiS_TVMode |= TVSetPALN;
+ } else if(temp1 & 0x04) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+ }
+ SiS_Pr->SiS_TVMode |= TVSetPALM;
+ }
+ } else {
+ if(temp1 & 0x02) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->SiS_CHOverScan) {
+ if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ temp1 &= 0xe0;
+ if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+ else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+ else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+ if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+ SiS_Pr->SiS_TVMode |= TVAspect169;
+ } else {
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+ if(temp1 & 0x02) {
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+ SiS_Pr->SiS_TVMode |= TVAspect169;
+ } else {
+ SiS_Pr->SiS_TVMode |= TVAspect43LB;
+ }
+ } else {
+ SiS_Pr->SiS_TVMode |= TVAspect43;
+ }
+ }
+ }
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
- SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
+ SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+ }
+ }
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
- if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
- if(resinfo == SIS_RI_1024x768) {
- SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
- }
- }
- }
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+ if(resinfo == SIS_RI_1024x768) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+ SiS_Pr->SiS_TVMode |= TVSet525p1024;
+ } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
+ }
+ }
+ }
- SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
- (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- }
- }
+ SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
+ (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ }
+ }
- }
+ }
- SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+ SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+ xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+#endif
#endif
}
@@ -1455,41 +1430,46 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_IN
/* GET LCD INFO */
/*********************************************/
-static USHORT
-SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
{
- USHORT temp = SiS_Pr->SiS_LCDResInfo;
+ unsigned short temp = SiS_Pr->SiS_LCDResInfo;
/* Translate my LCDResInfo to BIOS value */
- if(temp == Panel_1280x768_2) temp = Panel_1280x768;
- if(temp == Panel_1280x800_2) temp = Panel_1280x800;
+ switch(temp) {
+ case Panel_1280x768_2: temp = Panel_1280x768; break;
+ case Panel_1280x800_2: temp = Panel_1280x800; break;
+ case Panel_1280x854: temp = Panel661_1280x854; break;
+ }
return temp;
}
static void
-SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- UCHAR *ROMAddr;
- USHORT temp;
+ unsigned char *ROMAddr;
+ unsigned short temp;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
- SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+ SiS_Pr->PanelHT, SiS_Pr->PanelVT,
SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
#endif
+#endif
- if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+ if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
- SiS_Pr->SiS_NeedRomModeData = TRUE;
+ SiS_Pr->SiS_NeedRomModeData = TRUE;
SiS_Pr->PanelHT = temp;
}
if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
- SiS_Pr->SiS_NeedRomModeData = TRUE;
- SiS_Pr->PanelVT = temp;
+ SiS_Pr->SiS_NeedRomModeData = TRUE;
+ SiS_Pr->PanelVT = temp;
}
SiS_Pr->PanelHRS = SISGETROMW(10);
SiS_Pr->PanelHRE = SISGETROMW(12);
@@ -1497,56 +1477,58 @@ SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->PanelVRE = SISGETROMW(16);
SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
- SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
+ SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Paneldata BIOS: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
- SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+ SiS_Pr->PanelHT, SiS_Pr->PanelVT,
SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
#endif
+#endif
}
#endif
}
static void
-SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes)
-{
- int i = 0;
- while(nonscalingmodes[i] != 0xff) {
- if(nonscalingmodes[i++] == resinfo) {
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
- (SiS_Pr->UsePanelScaler == -1)) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
- }
- }
+SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
+ const unsigned char *nonscalingmodes)
+{
+ int i = 0;
+ while(nonscalingmodes[i] != 0xff) {
+ if(nonscalingmodes[i++] == resinfo) {
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
+ (SiS_Pr->UsePanelScaler == -1)) {
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
+ }
+ }
}
void
-SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
+ unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
+ BOOLEAN panelcanscale = FALSE;
#ifdef SIS300
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- const unsigned char SiS300SeriesLCDRes[] =
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ static const unsigned char SiS300SeriesLCDRes[] =
{ 0, 1, 2, 3, 7, 4, 5, 8,
0, 0, 10, 0, 0, 0, 0, 15 };
#endif
#ifdef SIS315H
- UCHAR *myptr = NULL;
+ unsigned char *myptr = NULL;
#endif
- USHORT temp,modeflag,resinfo=0,modexres=0,modeyres=0;
- BOOLEAN panelcanscale = FALSE;
SiS_Pr->SiS_LCDResInfo = 0;
SiS_Pr->SiS_LCDTypeInfo = 0;
@@ -1557,14 +1539,14 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVRE = 999; /* VSync end */
SiS_Pr->SiS_NeedRomModeData = FALSE;
+ /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
+ SiS_Pr->Alternate1600x1200 = FALSE;
+
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
@@ -1575,16 +1557,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* For broken BIOSes: Assume 1024x768 */
if(temp == 0) temp = 0x02;
- if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
- } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+ } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
} else {
SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
}
temp &= 0x0f;
#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
/* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(temp < 0x0f) temp &= 0x07;
@@ -1595,17 +1577,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif
/* Translate to our internal types */
- if(HwInfo->jChipType == SIS_550) {
- if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
- if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == SIS_550) {
+ if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
+ else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
+ else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
+ } else if(SiS_Pr->ChipType >= SIS_661) {
+ if(temp == Panel661_1280x854) temp = Panel_1280x854;
}
+#endif
- if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
if(temp == Panel310_1280x768) {
temp = Panel_1280x768_2;
}
if(SiS_Pr->SiS_ROMNew) {
- if(temp == Panel661_1280x800) {
+ if(temp == Panel661_1280x800) {
temp = Panel_1280x800_2;
}
}
@@ -1613,13 +1600,17 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDResInfo = temp;
+#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
+ SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+ SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+ } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ SiS_Pr->SiS_LCDResInfo = Panel_856x480;
}
}
+#endif
if(SiS_Pr->SiS_VBType & VB_SISVB) {
if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
@@ -1633,10 +1624,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
/* Need temp below! */
- /* These can't scale no matter what */
+ /* These must/can't scale no matter what */
switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
case Panel_1280x960:
SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+ break;
+ case Panel_640x480:
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
}
panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
@@ -1646,41 +1643,41 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* Dual link, Pass 1:1 BIOS default, etc. */
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
}
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if(SiS_Pr->SiS_ROMNew) {
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if(SiS_Pr->SiS_ROMNew) {
if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
- } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
- if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+ } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
+ if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
}
- } else if(HwInfo->jChipType >= SIS_315H) {
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
}
if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
- SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+ SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
} else if(!(SiS_Pr->SiS_ROMNew)) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
- if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+ if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
- }
+ }
}
}
#endif
@@ -1691,12 +1688,12 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- /* Always center screen on SiS LVDS (if scaling is disabled) */
- SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ /* Always center screen on SiS LVDS (if scaling is disabled) */
+ SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
} else {
- /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
- if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
- if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
+ if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
}
}
@@ -1704,19 +1701,15 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_320x480: SiS_Pr->PanelXRes = 320; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelHT = 400; SiS_Pr->PanelVT = 525;
- SiS_Pr->PanelVCLKIdx300 = VCLK28;
- SiS_Pr->PanelVCLKIdx315 = VCLK28;
- break;
- case Panel_640x480_2:
- case Panel_640x480_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
+ SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK28;
SiS_Pr->PanelVCLKIdx315 = VCLK28;
break;
case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelVRE = 3;
+ SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK28;
SiS_Pr->PanelVCLKIdx315 = VCLK28;
break;
@@ -1728,52 +1721,52 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVCLKIdx315 = VCLK40;
break;
case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
- SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+ SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- break;
+ break;
case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
SiS_Pr->PanelHRS = 23;
- SiS_Pr->PanelVRE = 5;
+ SiS_Pr->PanelVRE = 5;
}
SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
- SiS_Pr->PanelHRS = 24;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
SiS_Pr->PanelHRS = 23;
- SiS_Pr->PanelVRE = 5;
+ SiS_Pr->PanelVRE = 5;
}
- SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+ SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- break;
+ break;
case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
- break;
+ break;
case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
- SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
+ SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
/* Data above for TMDS (projector); get from BIOS for LVDS */
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
} else {
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
@@ -1781,77 +1774,100 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
break;
case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
- SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
+ SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
- SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
+ SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
+ break;
+ case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
+ SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
+ SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
+ SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
+ SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
- SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
+ SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
- if(resinfo == SIS_RI_1280x1024) {
+ if(resinfo == SIS_RI_1280x1024) {
SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
}
break;
case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
- SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; /* HRE OK for LVDS, not for LCDA */
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
- SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
+ SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
+ SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
+ SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
+ SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
+ SiS_Pr->Alternate1600x1200 = TRUE;
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
+ SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
+ SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
+ SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
+ }
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
- SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
- break;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ break;
case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
- break;
+ SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
+ break;
+ case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
+ SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
+ break;
case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
- SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+ SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
SiS_Pr->PanelHT = SiS_Pr->CHTotal;
SiS_Pr->PanelVT = SiS_Pr->CVTotal;
if(SiS_Pr->CP_PreferredIndex != -1) {
SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
- SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+ SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
@@ -1863,22 +1879,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
if(SiS_Pr->CP_PrefClock) {
- int idx;
- SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+ int idx;
+ SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
- if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300;
+ if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
else idx = VCLK_CUSTOM_315;
- SiS_Pr->SiS_VCLKData[idx].CLOCK =
- SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
- SiS_Pr->SiS_VCLKData[idx].SR2B =
- SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
- SiS_Pr->SiS_VCLKData[idx].SR2C =
- SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
+ SiS_Pr->SiS_VCLKData[idx].CLOCK =
+ SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
+ SiS_Pr->SiS_VCLKData[idx].SR2B =
+ SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
+ SiS_Pr->SiS_VCLKData[idx].SR2C =
+ SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
}
}
break;
default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
break;
}
@@ -1887,14 +1903,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
(SiS_Pr->SiS_IF_DEF_DSTN) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
SiS_Pr->PanelHRS = 999;
SiS_Pr->PanelHRE = 999;
}
if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
SiS_Pr->PanelVRS = 999;
SiS_Pr->PanelVRE = 999;
}
@@ -1912,18 +1930,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
case Panel_Custom:
case Panel_1152x864:
case Panel_1280x768: /* TMDS only */
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
break;
case Panel_800x600: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
}
case Panel_1024x768: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
0xff
@@ -1932,7 +1950,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
case Panel_1280x720: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
0xff
@@ -1944,7 +1962,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
case Panel_1280x768_2: { /* LVDS only */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,0xff
@@ -1952,23 +1970,23 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
switch(resinfo) {
case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
}
- break;
+ break;
}
case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1280x800_2: { /* SiS LVDS */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,0xff
@@ -1977,66 +1995,83 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
switch(resinfo) {
case SIS_RI_1280x720:
case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
}
- break;
+ break;
+ }
+ case Panel_1280x854: { /* SiS LVDS */
+ static const unsigned char nonscalingmodes[] = {
+ SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+ SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+ SIS_RI_1152x768,0xff
+ };
+ SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+ switch(resinfo) {
+ case SIS_RI_1280x720:
+ case SIS_RI_1280x768:
+ case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
+ }
+ break;
}
case Panel_1280x960: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- 0xff
+ SIS_RI_1280x854,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1280x1024: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- SIS_RI_1280x960,0xff
+ SIS_RI_1280x854,SIS_RI_1280x960,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
}
case Panel_1400x1050: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
- SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960,
- 0xff
+ SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
+ SIS_RI_1280x960,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- switch(resinfo) {
+ switch(resinfo) {
case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- break;
+ break;
}
break;
}
case Panel_1600x1200: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
+ SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1680x1050: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
- SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,
- 0xff
+ SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
+ SIS_RI_1360x1024,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
@@ -2044,25 +2079,25 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
+#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
+ if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
}
}
-#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_UseROM) {
+ if(SiS_Pr->SiS_UseROM) {
if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- if(!(ROMAddr[0x235] & 0x02)) {
- SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
- }
+ if(!(ROMAddr[0x235] & 0x02)) {
+ SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+ }
}
- }
- } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
- SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+ SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
}
}
}
@@ -2080,7 +2115,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_640x480:
- SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
break;
case Panel_1280x800:
/* Don't pass 1:1 by default (TMDS special) */
@@ -2097,7 +2132,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
- if(SiS_Pr->UseCustomMode) {
+ if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
}
@@ -2107,19 +2142,19 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
/* LVDS DDA */
- if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
+ if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
if(ModeNo == 0x12) {
if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
}
} else if(ModeNo > 0x13) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
- if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
- SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+ SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
}
}
}
@@ -2128,18 +2163,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
if(modeflag & HalfDCLK) {
- if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+ if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
} else if(ModeNo > 0x13) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
- if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- }
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+ if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ }
}
}
@@ -2148,21 +2183,21 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* VESA timing */
if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
- SiS_Pr->SiS_SetFlag |= LCDVESATiming;
+ SiS_Pr->SiS_SetFlag |= LCDVESATiming;
}
} else {
SiS_Pr->SiS_SetFlag |= LCDVESATiming;
}
-#ifdef LINUX_KERNEL
-#ifdef TWDEBUG
+#ifdef SIS_LINUX_KERNEL
+#if 0
printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
#endif
#endif
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
xf86DrvMsgVerb(0, X_PROBED, 4,
- "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
+ "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
#endif
}
@@ -2171,45 +2206,46 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* GET VCLK */
/*********************************************/
-USHORT
-SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
- USHORT modeflag,resinfo,tempbx;
- const UCHAR *CHTVVCLKPtr = NULL;
+ unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
+ unsigned short modeflag, resinfo, tempbx;
+ const unsigned char *CHTVVCLKPtr = NULL;
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
+ VCLKIndexGENCRT = VCLKIndexGEN;
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
+ VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
+ (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
}
if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- CRT2Index >>= 6;
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
+ CRT2Index >>= 6;
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = SiS_Pr->PanelVCLKIdx300;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- VCLKIndex = VCLKIndexGEN;
+ VCLKIndex = VCLKIndexGEN;
}
} else {
VCLKIndex = SiS_Pr->PanelVCLKIdx315;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
switch(resinfo) {
- /* Only those whose IndexGEN doesn't match VBVCLK array */
- case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
+ /* Correct those whose IndexGEN doesn't match VBVCLK array */
case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
@@ -2218,18 +2254,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+ case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
default: VCLKIndex = VCLKIndexGEN;
}
if(ModeNo <= 0x13) {
- if(HwInfo->jChipType <= SIS_315PRO) {
+ if(SiS_Pr->ChipType <= SIS_315PRO) {
if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
- } else {
+ } else {
if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
}
}
- if(HwInfo->jChipType <= SIS_315PRO) {
+ if(SiS_Pr->ChipType <= SIS_315PRO) {
if(VCLKIndex == 0) VCLKIndex = 0x41;
if(VCLKIndex == 1) VCLKIndex = 0x43;
if(VCLKIndex == 4) VCLKIndex = 0x44;
@@ -2237,49 +2274,46 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
- else VCLKIndex = HiTVVCLK;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(modeflag & Charx8Dot) VCLKIndex = HiTVSimuVCLK;
- else VCLKIndex = HiTVTextVCLK;
- }
- } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
- else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
- else VCLKIndex = TVVCLK;
-
- if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
- else VCLKIndex += TVCLKBASE_315;
-
- } else { /* VGA2 */
-
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30)) {
+ if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
+ else VCLKIndex = HiTVVCLK;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
+ } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
+ else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
+ else VCLKIndex = TVVCLK;
+
+ if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+ else VCLKIndex += TVCLKBASE_315;
+
+ } else { /* VGA2 */
+
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30)) {
if(VCLKIndex == 0x14) VCLKIndex = 0x34;
}
/* Better VGA2 clock for 1280x1024@75 */
if(VCLKIndex == 0x17) VCLKIndex = 0x45;
}
- }
- }
+ }
+ }
} else { /* If not programming CRT2 */
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType != SIS_630) &&
- (HwInfo->jChipType != SIS_300) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType != SIS_630) &&
+ (SiS_Pr->ChipType != SIS_300) ) {
if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
}
}
- }
+ }
}
} else { /* LVDS */
@@ -2288,12 +2322,12 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
+ if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
VCLKIndex &= 0x1f;
- tempbx = 0;
+ tempbx = 0;
if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
tempbx += 2;
if(SiS_Pr->SiS_ModeType > ModeVGA) {
if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
@@ -2306,66 +2340,68 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
}
}
- switch(tempbx) {
- case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
- case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
- case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
- case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
+ switch(tempbx) {
+ case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
+ case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
+ case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
+ case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
- case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
- case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
- case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
+ case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
+ case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
+ case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
- }
- VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+ }
+ VCLKIndex = CHTVVCLKPtr[VCLKIndex];
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = SiS_Pr->PanelVCLKIdx300;
} else {
VCLKIndex = SiS_Pr->PanelVCLKIdx315;
}
+#ifdef SIS300
/* Special Timing: Barco iQ Pro R series */
if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
- /* Special Timing: 848x480 parallel lvds */
- if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- if(HwInfo->jChipType < SIS_315H) {
+ /* Special Timing: 848x480 and 856x480 parallel lvds panels */
+ if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = VCLK34_300;
- /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
+ /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
} else {
VCLKIndex = VCLK34_315;
/* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
}
}
+#endif
- } else {
+ } else {
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
- }
- }
+ }
+ }
}
- }
+ }
} else { /* if not programming CRT2 */
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType != SIS_630) &&
- (HwInfo->jChipType != SIS_300) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType != SIS_630) &&
+ (SiS_Pr->ChipType != SIS_300) ) {
if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
}
#if 0
- if(HwInfo->jChipType == SIS_730) {
+ if(SiS_Pr->ChipType == SIS_730) {
if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
}
@@ -2377,11 +2413,13 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
#endif
+#endif
- return(VCLKIndex);
+ return VCLKIndex;
}
/*********************************************/
@@ -2389,26 +2427,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT i,j,modeflag;
- USHORT tempcl,tempah=0;
+ unsigned short i, j, modeflag, tempah=0;
+ short tempcl;
#if defined(SIS300) || defined(SIS315H)
- USHORT tempbl;
+ unsigned short tempbl;
#endif
#ifdef SIS315H
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT tempah2, tempbl2;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short tempah2, tempbl2;
#endif
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -2418,18 +2449,18 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else {
for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
}
tempcl = SiS_Pr->SiS_ModeType;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---- 300 series ---- */
- /* For 301BDH: (with LCD via LVDS) */
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+ /* For 301BDH: (with LCD via LVDS) */
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) {
tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
tempbl &= 0xef;
tempbl |= 0x02;
@@ -2438,16 +2469,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbl &= 0xfd;
}
SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
- }
+ }
- if(ModeNo > 0x13) {
- tempcl -= ModeVGA;
- if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
- tempah = ((0x10 >> tempcl) | 0x80);
- }
- } else tempah = 0x80;
+ if(ModeNo > 0x13) {
+ tempcl -= ModeVGA;
+ if(tempcl >= 0) {
+ tempah = ((0x10 >> tempcl) | 0x80);
+ }
+ } else tempah = 0x80;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
#endif /* SIS300 */
@@ -2455,22 +2486,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS315H /* ------- 315/330 series ------ */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08);
- }
- }
-
- if(ModeNo > 0x13) {
- tempcl -= ModeVGA;
- if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
- tempah = (0x08 >> tempcl);
- if (tempah == 0) tempah = 1;
- tempah |= 0x40;
- }
- } else tempah = 0x40;
+ if(ModeNo > 0x13) {
+ tempcl -= ModeVGA;
+ if(tempcl >= 0) {
+ tempah = (0x08 >> tempcl);
+ if (tempah == 0) tempah = 1;
+ tempah |= 0x40;
+ }
+ } else tempah = 0x40;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
#endif /* SIS315H */
@@ -2478,84 +2503,89 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
} else {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(IS_SIS740) {
+#ifdef SIS315H
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(IS_SIS740) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
} else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
}
- }
+ }
+#endif
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- tempah = 0x01;
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- tempah |= 0x02;
- }
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- tempah ^= 0x05;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- tempah ^= 0x01;
- }
- }
+ tempah = 0x01;
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ tempah |= 0x02;
+ }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ tempah ^= 0x05;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+ tempah ^= 0x01;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+ if(SiS_Pr->ChipType < SIS_315H) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
- tempah = (tempah << 5) & 0xFF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
- tempah = (tempah >> 5) & 0xFF;
+ tempah = (tempah << 5) & 0xFF;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
+ tempah = (tempah >> 5) & 0xFF;
- } else {
+ } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
+ else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
+ tempah &= ~0x08;
- }
+ }
- if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
- tempah |= 0x10;
- }
+ if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+ tempah |= 0x10;
+ }
tempah |= 0x80;
- if(SiS_Pr->SiS_VBType & VB_SIS301) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
- }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- tempah |= 0x20;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ tempah |= 0x20;
}
- }
- }
+ }
+ }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
tempah = 0x80;
if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
}
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40;
+ if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
- tempah |= 0x40;
- }
- }
+ tempah |= 0x40;
+ }
+ }
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
} else { /* LVDS */
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
#ifdef SIS315H
/* LVDS can only be slave in 8bpp modes */
@@ -2566,36 +2596,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- tempah |= 0x02;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tempah ^= 0x01;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- tempah = 1;
- }
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
#endif
- } else {
+ } else {
#ifdef SIS300
tempah = 0;
if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
- tempah |= 0x02;
- }
+ tempah |= 0x02;
+ }
tempah <<= 5;
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
#endif
- }
+ }
}
@@ -2603,10 +2627,10 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
#ifdef SIS315H
- unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+ /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
/* The following is nearly unpreditable and varies from machine
* to machine. Especially the 301DH seems to be a real trouble
@@ -2619,25 +2643,28 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* 740 variants match for 30xB, 301B-DH, 30xLV */
- if(!(IS_SIS740)) {
- tempah = 0x04; /* For all bridges */
- tempbl = 0xfb;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempah = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(!(IS_SIS740)) {
+ tempah = 0x04; /* For all bridges */
+ tempbl = 0xfb;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempbl = 0xff;
}
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
}
/* The following two are responsible for eventually wrong colors
* in TV output. The DH (VB_NoLCD) conditions are unknown; the
* b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
* in a 650 box (Jake). What is the criteria?
+ * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
+ * treatment like the 651+301B-DH(b0) case. Seems more to be the
+ * chipset than the bridge revision.
*/
- if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
tempah = 0x30;
tempbl = 0xc0;
if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
@@ -2649,20 +2676,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
} else if(SiS_Pr->SiS_VBType & VB_SIS301) {
/* Fixes "TV-blue-bug" on 315+301 */
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
- } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
- } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xB-DH rev b0 (or "DH on 651"?) */
+ } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
+ } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
+ tempah = 0x30; tempah2 = 0xc0;
+ tempbl = 0xcf; tempbl2 = 0x3f;
+ if(SiS_Pr->SiS_TVBlue == 0) {
+ tempah = tempah2 = 0x00;
+ } else if(SiS_Pr->SiS_TVBlue == -1) {
+ /* Set on 651/M650, clear on 315/650 */
+ if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
+ tempah = tempah2 = 0x00;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
} else {
- tempah = 0x30; tempah2 = 0xc0; /* For 30xB (and 301BDH rev b1) */
+ tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
tempbl = 0xcf; tempbl2 = 0x3f;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
tempah = tempah2 = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempbl = tempbl2 = 0xff;
}
}
@@ -2676,23 +2713,23 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
} else {
tempah = 0x00;
- tempbl = 0x7f;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempbl = 0xff;
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
+ tempbl = 0x7f;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempbl = 0xff;
+ if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
}
#endif /* SIS315H */
- } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
#ifdef SIS300
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
- if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
- ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+ if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+ ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
} else {
@@ -2702,9 +2739,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
}
}
@@ -2712,16 +2749,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else { /* LVDS */
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- tempah = 0x04;
+ tempah = 0x04;
tempbl = 0xfb;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempah = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+ if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
+ }
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
@@ -2730,7 +2767,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
- } else if(HwInfo->jChipType == SIS_550) {
+ } else if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
@@ -2748,212 +2785,120 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* GET RESOLUTION DATA */
/*********************************************/
-USHORT
-SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+unsigned short
+SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
- else return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
+ if(ModeNo <= 0x13)
+ return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+ else
+ return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
}
static void
-SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT xres,yres,modeflag=0,resindex;
+ unsigned short xres, yres, modeflag=0, resindex;
- if(SiS_Pr->UseCustomMode) {
- xres = SiS_Pr->CHDisplay;
- if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
- SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
- yres = SiS_Pr->CVDisplay;
- if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
- SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
- return;
- }
-
- resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
+ if(SiS_Pr->UseCustomMode) {
+ xres = SiS_Pr->CHDisplay;
+ if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
+ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+ /* DoubleScanMode-check done in CheckCalcCustomMode()! */
+ SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+ return;
+ }
- if(ModeNo <= 0x13) {
- xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
- yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
- } else {
- xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
- yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
+ if(ModeNo <= 0x13) {
+ xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
+ yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
+ } else {
+ xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+ yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
- if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- if(yres == 350) yres = 400;
- }
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
- if(ModeNo == 0x12) yres = 400;
- }
- }
+ if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
- if(modeflag & HalfDCLK) xres *= 2;
- if(modeflag & DoubleScanMode) yres *= 2;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
+ if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+ if(yres == 350) yres = 400;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
+ if(ModeNo == 0x12) yres = 400;
+ }
+ }
- }
+ if(modeflag & HalfDCLK) xres <<= 1;
+ if(modeflag & DoubleScanMode) yres <<= 1;
- if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+ }
-#if 0
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
- if(xres == 720) xres = 640;
- }
-#endif
+ if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- switch(SiS_Pr->SiS_LCDResInfo) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_1024x768:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- if(yres == 350) yres = 357;
- if(yres == 400) yres = 420;
- if(yres == 480) yres = 525;
- }
- }
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ if(yres == 350) yres = 357;
+ if(yres == 400) yres = 420;
+ if(yres == 480) yres = 525;
+ }
+ }
break;
case Panel_1280x1024:
if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
/* BIOS bug - does this regardless of scaling */
- if(yres == 400) yres = 405;
+ if(yres == 400) yres = 405;
+ }
+ if(yres == 350) yres = 360;
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ if(yres == 360) yres = 375;
}
- if(yres == 350) yres = 360;
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- if(yres == 360) yres = 375;
- }
break;
case Panel_1600x1200:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if(yres == 1024) yres = 1056;
- }
+ if(yres == 1024) yres = 1056;
+ }
break;
- }
- }
+ }
+ }
- } else {
+ } else {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
- if(xres == 720) xres = 640;
- }
- } else if(xres == 720) xres = 640;
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+ if(xres == 720) xres = 640;
+ }
+ } else if(xres == 720) xres = 640;
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
- yres = 400;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
- } else {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
- }
- if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
- }
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+ yres = 400;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+ } else {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+ }
+ if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
+ }
- }
- SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
- SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
+ }
+ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+ SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
}
/*********************************************/
/* GET CRT2 TIMING DATA */
/*********************************************/
-static BOOLEAN
-SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, USHORT *ResIndex,
- USHORT *DisplayType)
- {
- USHORT modeflag=0;
-
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
- }
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
- } else
- return FALSE;
-
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
-
- (*ResIndex) &= 0x3F;
-
- if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- (*DisplayType) = 18;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- (*DisplayType) += 2;
- if(SiS_Pr->SiS_ModeType > ModeVGA) {
- if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
- }
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- (*DisplayType) = 18; /* PALM uses NTSC data */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- (*DisplayType) = 20; /* PALN uses PAL data */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- }
- }
- } else {
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480: (*DisplayType) = 50; break;
- case Panel_640x480_2: (*DisplayType) = 52; break;
- case Panel_640x480_3: (*DisplayType) = 54; break;
- case Panel_800x600: (*DisplayType) = 0; break;
- case Panel_1024x600: (*DisplayType) = 23; break;
- case Panel_1024x768: (*DisplayType) = 4; break;
- case Panel_1152x768: (*DisplayType) = 27; break;
- case Panel_1280x768: (*DisplayType) = 40; break;
- case Panel_1280x1024: (*DisplayType) = 8; break;
- case Panel_1400x1050: (*DisplayType) = 14; break;
- case Panel_1600x1200: (*DisplayType) = 36; break;
- default: return FALSE;
- }
-
- if(modeflag & HalfDCLK) (*DisplayType)++;
-
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480:
- case Panel_640x480_2:
- case Panel_640x480_3:
- break;
- default:
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
- }
-
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- (*DisplayType) = 12;
- if(modeflag & HalfDCLK) (*DisplayType)++;
- }
- }
-
-#if 0
- if(SiS_Pr->SiS_IF_DEF_FSTN) {
- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
- (*DisplayType) = 22;
- }
- }
-#endif
-
- return TRUE;
-}
-
static void
-SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
+ unsigned short *ResIndex)
{
- USHORT tempbx=0,tempal=0,resinfo=0;
+ unsigned short tempbx=0, tempal=0, resinfo=0;
if(ModeNo <= 0x13) {
tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2966,18 +2911,20 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
- tempbx = SiS_Pr->SiS_LCDResInfo;
+ tempbx = SiS_Pr->SiS_LCDResInfo;
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+ /* patch index */
if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
if (resinfo == SIS_RI_1280x800) tempal = 9;
else if(resinfo == SIS_RI_1400x1050) tempal = 11;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) {
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
if (resinfo == SIS_RI_1280x768) tempal = 9;
}
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
/* Pass 1:1 only (center-screen handled outside) */
/* This is never called for the panel's native resolution */
/* since Pass1:1 will not be set in this case */
@@ -2991,8 +2938,8 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- tempbx = 200;
- if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+ tempbx = 200;
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
}
}
}
@@ -3000,23 +2947,23 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
} else { /* TV */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
- tempbx = 2;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
+ tempbx = 2;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
tempbx = 13;
- if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
- }
+ if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
+ }
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
- else tempbx = 5;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
- else tempbx = 4;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
- }
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
+ else tempbx = 5;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
+ } else {
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
+ else tempbx = 4;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
+ }
}
@@ -3024,26 +2971,34 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(ModeNo > 0x13) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
- if(tempal == 6) tempal = 7;
- if((resinfo == SIS_RI_720x480) ||
- (resinfo == SIS_RI_720x576) ||
- (resinfo == SIS_RI_768x576)) {
+ switch(resinfo) {
+ case SIS_RI_720x480:
tempal = 6;
- if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
- if(resinfo == SIS_RI_720x480) tempal = 9;
+ if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
+ break;
+ case SIS_RI_720x576:
+ case SIS_RI_768x576:
+ case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
+ tempal = 6;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
}
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
- if(resinfo == SIS_RI_1024x768) tempal = 8;
+ break;
+ case SIS_RI_800x480:
+ tempal = 4;
+ break;
+ case SIS_RI_512x384:
+ case SIS_RI_1024x768:
+ tempal = 7;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
}
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- if((resinfo == SIS_RI_720x576) ||
- (resinfo == SIS_RI_768x576)) {
- tempal = 8;
- }
- if(resinfo == SIS_RI_1280x720) tempal = 9;
+ break;
+ case SIS_RI_1280x720:
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
}
+ break;
}
}
}
@@ -3056,65 +3011,60 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx = 0;
if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- tempbx = 10;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- tempbx += 2;
+ tempbx = 90;
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ tempbx = 92;
if(SiS_Pr->SiS_ModeType > ModeVGA) {
if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
}
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- tempbx = 90;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- tempbx = 92;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- }
- }
+ if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
+ else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
+ }
+ if(tempbx != 99) {
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
+ }
} else {
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480: tempbx = 6; break;
- case Panel_640x480_2:
- case Panel_640x480_3: tempbx = 30; break;
- case Panel_800x600: tempbx = 0; break;
- case Panel_1024x600: tempbx = 15; break;
- case Panel_1024x768: tempbx = 2; break;
- case Panel_1152x768: tempbx = 17; break;
- case Panel_1280x768: tempbx = 18; break;
- case Panel_1280x1024: tempbx = 4; break;
- case Panel_1400x1050: tempbx = 8; break;
- case Panel_1600x1200: tempbx = 21; break;
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_640x480: tempbx = 12; break;
+ case Panel_320x240_1: tempbx = 10; break;
+ case Panel_320x240_2:
+ case Panel_320x240_3: tempbx = 14; break;
+ case Panel_800x600: tempbx = 16; break;
+ case Panel_1024x600: tempbx = 18; break;
+ case Panel_1152x768:
+ case Panel_1024x768: tempbx = 20; break;
+ case Panel_1280x768: tempbx = 22; break;
+ case Panel_1280x1024: tempbx = 24; break;
+ case Panel_1400x1050: tempbx = 26; break;
+ case Panel_1600x1200: tempbx = 28; break;
+#ifdef SIS300
case Panel_Barco1366: tempbx = 80; break;
+#endif
}
switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
case Panel_640x480:
- case Panel_640x480_2:
- case Panel_640x480_3:
break;
default:
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
}
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
+#ifdef SIS300
if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
tempbx = 82;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
- } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+ } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
tempbx = 84;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
}
-
- if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
- (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
- (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- tempal = 0;
- }
- }
+#endif
}
@@ -3124,12 +3074,11 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
}
static void
-SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT tempax=0,tempbx=0;
- USHORT temp1=0,modeflag=0,tempcx=0;
- USHORT index;
+ unsigned short tempax=0, tempbx=0, index, dotclock;
+ unsigned short temp1=0, modeflag=0, tempcx=0;
SiS_Pr->SiS_RVBHCMAX = 1;
SiS_Pr->SiS_RVBHCFACT = 1;
@@ -3143,10 +3092,12 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
+ dotclock = (modeflag & Charx8Dot) ? 8 : 9;
+
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
@@ -3158,22 +3109,16 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx |= tempcx;
temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
+ dotclock = 8;
+
}
if(temp1 & 0x01) tempbx |= 0x0100;
if(temp1 & 0x20) tempbx |= 0x0200;
tempax += 5;
-
- /* Charx8Dot is no more used (and assumed), so we set it */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- modeflag |= Charx8Dot;
- }
-
- if(modeflag & Charx8Dot) tempax *= 8;
- else tempax *= 9;
-
- if(modeflag & HalfDCLK) tempax <<= 1;
+ tempax *= dotclock;
+ if(modeflag & HalfDCLK) tempax <<= 1;
tempbx++;
@@ -3182,13 +3127,56 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
}
static void
-SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
+{
+ unsigned short ResIndex;
+
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ if(SiS_Pr->UseCustomMode) {
+ ResIndex = SiS_Pr->CHTotal;
+ if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+ } else {
+ if(ModeNo < 0x13) {
+ ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+ }
+ if(ResIndex == 0x09) {
+ if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
+ else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
+ }
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+ SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+ SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+ }
+ } else {
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ }
+ } else {
+ /* This handles custom modes and custom panels */
+ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
+ }
+}
+
+static void
+SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT CRT2Index, ResIndex;
- const SiS_LVDSDataStruct *LVDSData = NULL;
+ unsigned short CRT2Index, ResIndex, backup;
+ const struct SiS_LVDSData *LVDSData = NULL;
- SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
SiS_Pr->SiS_RVBHCMAX = 1;
@@ -3199,133 +3187,94 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
SiS_Pr->SiS_RY2COE = 0;
SiS_Pr->SiS_RY3COE = 0;
SiS_Pr->SiS_RY4COE = 0;
+ SiS_Pr->SiS_RVBHRS2 = 0;
}
if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
#ifdef SIS315H
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
- } else {
- if(ModeNo < 0x13) {
- ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
- }
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
- SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
- SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
- }
- } else {
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
- }
- } else {
- /* This handles custom modes and custom panels */
- SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
- SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
- }
-
- SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
-
+ SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
#endif
} else {
/* 301BDH needs LVDS Data */
+ backup = SiS_Pr->SiS_IF_DEF_LVDS;
if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
SiS_Pr->SiS_IF_DEF_LVDS = 1;
}
SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &CRT2Index, &ResIndex, HwInfo);
+ &CRT2Index, &ResIndex);
- /* 301BDH needs LVDS Data */
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- SiS_Pr->SiS_IF_DEF_LVDS = 0;
- }
+ SiS_Pr->SiS_IF_DEF_LVDS = backup;
- switch (CRT2Index) {
- case 0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
- case 1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2; break;
- case 2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
- case 3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2; break;
- case 4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1; break;
- case 5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2; break;
- case 6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
- case 7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1; break;
- case 8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1; break;
- case 9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2; break;
- case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
- case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
- case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
- case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
- case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1; break;
- case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
- case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2; break;
- case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1; break;
- case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2; break;
- case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1; break;
- case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2; break;
- case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1; break;
- case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2; break;
- case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2; break;
+ switch(CRT2Index) {
+ case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
+ case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
+ case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
+ case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
+ case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
+ case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
+#ifdef SIS300
case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
- case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2; break;
case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
- case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
- case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
- case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
- case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
- case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break; /* Super Overscan */
- default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
+#endif
+ case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
+ case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
+ case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
+ case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
+ case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
+ case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
+ case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
+ case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
+ case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
}
- SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
- SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
- SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
- SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
-
- if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
- SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- if(ResIndex < 0x08) {
- SiS_Pr->SiS_HDE = 1280;
- SiS_Pr->SiS_VDE = 1024;
- }
- }
- }
+ if(LVDSData) {
+ SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+ SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+ SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
+ SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
+ } else {
+ SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+
+ if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
+ (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+ (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+ if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
+ (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
+ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+#ifdef SIS300
+ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+ if(ResIndex < 0x08) {
+ SiS_Pr->SiS_HDE = 1280;
+ SiS_Pr->SiS_VDE = 1024;
+ }
+ }
+#endif
}
}
}
}
static void
-SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
-{
- UCHAR *ROMAddr = NULL;
- USHORT tempax,tempbx,modeflag,romptr=0;
- USHORT resinfo,CRT2Index,ResIndex;
- const SiS_LCDDataStruct *LCDPtr = NULL;
- const SiS_TVDataStruct *TVPtr = NULL;
+SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned char *ROMAddr = NULL;
+ unsigned short tempax, tempbx, modeflag, romptr=0;
+ unsigned short resinfo, CRT2Index, ResIndex;
+ const struct SiS_LCDData *LCDPtr = NULL;
+ const struct SiS_TVData *TVPtr = NULL;
#ifdef SIS315H
- SHORT resinfo661;
+ short resinfo661;
#endif
if(ModeNo <= 0x13) {
@@ -3340,67 +3289,69 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
#ifdef SIS315H
resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
- (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
- (resinfo661 >= 0) &&
+ (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+ (resinfo661 >= 0) &&
(SiS_Pr->SiS_NeedRomModeData) ) {
- if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+ if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
if((romptr = (SISGETROMW(21)))) {
- romptr += (resinfo661 * 10);
- ROMAddr = HwInfo->pjVirtualRomBase;
+ romptr += (resinfo661 * 10);
+ ROMAddr = SiS_Pr->VirtualRomBase;
}
}
}
#endif
}
-
+
SiS_Pr->SiS_NewFlickerMode = 0;
SiS_Pr->SiS_RVBHRS = 50;
SiS_Pr->SiS_RY1COE = 0;
SiS_Pr->SiS_RY2COE = 0;
SiS_Pr->SiS_RY3COE = 0;
SiS_Pr->SiS_RY4COE = 0;
+ SiS_Pr->SiS_RVBHRS2 = 0;
- SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo);
+ SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_RVBHCMAX = 1;
- SiS_Pr->SiS_RVBHCFACT = 1;
- SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
- SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+ SiS_Pr->SiS_RVBHCMAX = 1;
+ SiS_Pr->SiS_RVBHCFACT = 1;
SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
- SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+
+ tempax = SiS_Pr->CHTotal;
+ if(modeflag & HalfDCLK) tempax <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
} else {
- SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
- &CRT2Index,&ResIndex,HwInfo);
+ &CRT2Index,&ResIndex);
switch(CRT2Index) {
- case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
- case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
- case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
- case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
- case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
- case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
- case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
- case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
- case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
- case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
- case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
- case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
- case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
- default: TVPtr = SiS_Pr->SiS_StPALData; break;
+ case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
+ case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
+ case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
+ case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
+ case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
+ case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
+ case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
+ case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
+ case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
+ case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
+ case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
+ case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
+ case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
+ default: TVPtr = SiS_Pr->SiS_StPALData; break;
}
SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3409,73 +3360,77 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
- SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
- SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
+ SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
if(modeflag & HalfDCLK) {
- SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+ if(SiS_Pr->SiS_RVBHRS2) {
+ SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+ tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
+ if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
+ else SiS_Pr->SiS_RVBHRS2 += tempax;
+ }
+ } else {
+ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
}
+ SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if((resinfo == SIS_RI_1024x768) ||
- (resinfo == SIS_RI_1280x1024) ||
- (resinfo == SIS_RI_1280x720)) {
+ if((resinfo == SIS_RI_960x600) ||
+ (resinfo == SIS_RI_1024x768) ||
+ (resinfo == SIS_RI_1280x1024) ||
+ (resinfo == SIS_RI_1280x720)) {
SiS_Pr->SiS_NewFlickerMode = 0x40;
}
- if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+ if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
- SiS_Pr->SiS_HT = ExtHiTVHT;
- SiS_Pr->SiS_VT = ExtHiTVVT;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- SiS_Pr->SiS_HT = StHiTVHT;
- SiS_Pr->SiS_VT = StHiTVVT;
-#if 0
- if(!(modeflag & Charx8Dot)) {
- SiS_Pr->SiS_HT = StHiTextTVHT;
- SiS_Pr->SiS_VT = StHiTextTVVT;
- }
-#endif
- }
- }
+ SiS_Pr->SiS_HT = ExtHiTVHT;
+ SiS_Pr->SiS_VT = ExtHiTVVT;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+ SiS_Pr->SiS_HT = StHiTVHT;
+ SiS_Pr->SiS_VT = StHiTVVT;
+ }
+ }
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- SiS_Pr->SiS_HT = 1650;
- SiS_Pr->SiS_VT = 750;
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+ SiS_Pr->SiS_HT = 1650;
+ SiS_Pr->SiS_VT = 750;
} else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
SiS_Pr->SiS_HT = NTSCHT;
+ if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
SiS_Pr->SiS_VT = NTSCVT;
- } else {
- SiS_Pr->SiS_HT = NTSCHT;
+ } else {
+ SiS_Pr->SiS_HT = NTSCHT;
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
- SiS_Pr->SiS_VT = NTSCVT;
- }
+ SiS_Pr->SiS_VT = NTSCVT;
+ }
} else {
- SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
- SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
- SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
- SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
+ SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
+ SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
+ SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
+ SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
- if(modeflag & HalfDCLK) {
- SiS_Pr->SiS_RY1COE = 0x00;
- SiS_Pr->SiS_RY2COE = 0xf4;
- SiS_Pr->SiS_RY3COE = 0x10;
- SiS_Pr->SiS_RY4COE = 0x38;
- }
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->SiS_RY1COE = 0x00;
+ SiS_Pr->SiS_RY2COE = 0xf4;
+ SiS_Pr->SiS_RY3COE = 0x10;
+ SiS_Pr->SiS_RY4COE = 0x38;
+ }
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- SiS_Pr->SiS_HT = NTSCHT;
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+ SiS_Pr->SiS_HT = NTSCHT;
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
- SiS_Pr->SiS_VT = NTSCVT;
- } else {
- SiS_Pr->SiS_HT = PALHT;
- SiS_Pr->SiS_VT = PALVT;
- }
+ SiS_Pr->SiS_VT = NTSCVT;
+ } else {
+ SiS_Pr->SiS_HT = PALHT;
+ SiS_Pr->SiS_VT = PALVT;
+ }
}
@@ -3486,42 +3441,53 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
- SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
- SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+
+ tempax = SiS_Pr->CHTotal;
+ if(modeflag & HalfDCLK) tempax <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
} else {
- BOOLEAN gotit = FALSE;
+ BOOLEAN gotit = FALSE;
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+ if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
gotit = TRUE;
} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
#ifdef SIS315H
SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
- SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
- SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
- SiS_Pr->SiS_VGAVT = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
- SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
- SiS_Pr->SiS_VT = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+ SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+ SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+ SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
+ SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+ SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
+ SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
+ if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
+ SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+ tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
+ if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
+ else SiS_Pr->SiS_RVBHRS2 += tempax;
+ }
if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
else {
SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ SiS_Pr->SiS_RVBHCMAX = 1;
+ SiS_Pr->SiS_RVBHCFACT = 1;
SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_RVBHRS2 = 0;
gotit = TRUE;
}
#endif
@@ -3530,28 +3496,30 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(!gotit) {
- SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
- &CRT2Index,&ResIndex,HwInfo);
+ SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ &CRT2Index,&ResIndex);
- switch(CRT2Index) {
+ switch(CRT2Index) {
case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
case Panel_1280x720 :
case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
- case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
+ case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
case Panel_1280x800 :
case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
case Panel_1280x800_2 :
case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
+ case Panel_1280x854 :
+ case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
case Panel_1280x960 :
case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
- case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
- case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
- case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
- case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
- case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
- case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
+ case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
+ case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
+ case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
+ case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
+ case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
+ case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
case Panel_1680x1050 :
case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
@@ -3559,271 +3527,340 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
#endif
- default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
- }
+ default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
+ }
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+ xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+#endif
#endif
- SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
- SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
- SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
- SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
- SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
- SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
+ SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
+ SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+ SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
+ SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
+ SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
+ SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
}
tempax = SiS_Pr->PanelXRes;
- tempbx = SiS_Pr->PanelYRes;
+ tempbx = SiS_Pr->PanelYRes;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- if(HwInfo->jChipType < SIS_315H) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
- }
- } else {
- if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
- else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
- else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
- else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
- else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
- }
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
- else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
- if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
- else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
- else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1024x768:
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+ }
+ } else {
+ if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
+ else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
+ else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
+ else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
+ else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+ }
+ break;
+ case Panel_1280x960:
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
+ else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
+ break;
+ case Panel_1280x1024:
+ if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+ else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+ else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+ break;
+ case Panel_1600x1200:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
- }
- }
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
+ }
+ break;
+ }
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempax = SiS_Pr->SiS_VGAHDE;
- tempbx = SiS_Pr->SiS_VGAVDE;
- }
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = SiS_Pr->SiS_VGAHDE;
+ tempbx = SiS_Pr->SiS_VGAVDE;
+ }
- SiS_Pr->SiS_HDE = tempax;
- SiS_Pr->SiS_VDE = tempbx;
+ SiS_Pr->SiS_HDE = tempax;
+ SiS_Pr->SiS_VDE = tempbx;
}
}
}
static void
-SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- } else {
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- /* Need LVDS Data for LCD on 301B-DH */
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- } else {
- SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ } else {
+ if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+ /* Need LVDS Data for LCD on 301B-DH */
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ } else {
+ SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
- } else {
+ } else {
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- }
+ }
}
/*********************************************/
/* GET LVDS DES (SKEW) DATA */
/*********************************************/
-static void
-SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, USHORT *PanelIndex,
- USHORT *ResIndex, PSIS_HW_INFO HwInfo)
+static const struct SiS_LVDSDes *
+SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
{
- USHORT modeflag;
+ const struct SiS_LVDSDes *PanelDesPtr = NULL;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
+#ifdef SIS300
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDTypeInfo == 4) {
+ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
+ }
+ } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
+ }
+ }
+ }
+ }
+ }
+#endif
+ return PanelDesPtr;
+}
- (*ResIndex) &= 0x1F;
- (*PanelIndex) = 0;
+static void
+SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short modeflag, ResIndex;
+ const struct SiS_LVDSDes *PanelDesPtr = NULL;
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- (*PanelIndex) = 50;
- if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
- /* Nothing special needed for SOverscan */
- /* PALM uses NTSC data, PALN uses PAL data */
- }
- }
+ SiS_Pr->SiS_LCDHDES = 0;
+ SiS_Pr->SiS_LCDVDES = 0;
+ /* Some special cases */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
- if(HwInfo->jChipType >= SIS_661) {
- /* As long as we don's use the BIOS tables, we
- * need to convert the TypeInfo as for 315 series
- */
- (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
- }
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- (*PanelIndex) += 16;
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- (*PanelIndex) = 32;
- if(modeflag & HalfDCLK) (*PanelIndex)++;
+
+ /* Trumpion */
+ if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ }
}
+ return;
}
- }
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
- (*ResIndex) = 7;
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
- }
+ /* 640x480 on LVDS */
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
+ SiS_Pr->SiS_LCDHDES = 8;
+ if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+ else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+ else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+ return;
+ }
}
- }
-}
-
-static void
-SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
- USHORT modeflag;
- USHORT PanelIndex,ResIndex;
- const SiS_LVDSDesStruct *PanelDesPtr = NULL;
- SiS_Pr->SiS_LCDHDES = 0;
- SiS_Pr->SiS_LCDVDES = 0;
+ } /* LCD */
if( (SiS_Pr->UseCustomMode) ||
(SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
(SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
- ((SiS_Pr->SiS_VBType & VB_SISVB) &&
- (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
- (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
+ (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
return;
}
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
#ifdef SIS315H
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- /* non-pass 1:1 only, see above */
- if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
- SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+ /* non-pass 1:1 only, see above */
+ if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
}
if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
}
}
if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
- switch(SiS_Pr->SiS_CustomT) {
- case CUT_UNIWILL1024:
- case CUT_UNIWILL10242:
- case CUT_CLEVO1400:
+ switch(SiS_Pr->SiS_CustomT) {
+ case CUT_UNIWILL1024:
+ case CUT_UNIWILL10242:
+ case CUT_CLEVO1400:
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
}
break;
}
- if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1280x1024:
if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
}
+ break;
+ case Panel_1280x800: /* Verified for Averatec 6240 */
+ case Panel_1280x800_2: /* Verified for Asus A4L */
+ case Panel_1280x854: /* Not verified yet FIXME */
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ break;
}
}
#endif
} else {
- SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &PanelIndex, &ResIndex, HwInfo);
-
- switch(PanelIndex) {
- case 0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1; break; /* --- */
- case 1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1; break;
- case 2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1; break;
- case 3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1; break;
- case 4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1; break;
- case 5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1; break;
- case 6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1; break;
- case 7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1; break;
- case 8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1; break;
- case 9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1; break;
- case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1; break;
- case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1; break;
- case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1; break;
- case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1; break;
- case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1; break;
- case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1; break;
- case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2; break; /* --- */
- case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2; break;
- case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2; break;
- case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2; break;
- case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2; break;
- case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2; break;
- case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2; break;
- case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2; break;
- case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2; break;
- case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2; break;
- case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2; break;
- case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2; break;
- case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2; break;
- case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2; break;
- case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2; break;
- case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2; break;
- case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1; break; /* pass 1:1 */
- case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2; break;
- case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break; /* TV */
- case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
- case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData; break;
- case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData; break;
- default: return;
- }
-
- SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
- SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+ if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+ if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+ if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
+ }
+
+ } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
+
+ SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+ SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+
+ if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+ }
+ if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+ } else {
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_800x600:
+ case Panel_1024x768:
+ case Panel_1280x1024:
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+ break;
+ case Panel_1400x1050:
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ break;
+ }
+ }
+ }
+
+ } else {
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_800x600:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+ if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
+ else SiS_Pr->SiS_LCDVDES -= 4;
+ }
+ break;
+ case Panel_1024x768:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+ if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
+ if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
+ }
+ break;
+ case Panel_1024x600:
+ default:
+ if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
+ (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+ }
+ break;
+ }
+
+ switch(SiS_Pr->SiS_LCDTypeInfo) {
+ case 1:
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
+ break;
+ case 3: /* 640x480 only? */
+ SiS_Pr->SiS_LCDHDES = 8;
+ if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+ else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+ else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+ break;
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1024x768:
+ case Panel_1280x1024:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ }
+ break;
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
+ SiS_Pr->SiS_LCDVDES = 524;
+ break;
+ }
+#endif
+ }
+ }
if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
- } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
- if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
- if(HwInfo->jChipType < SIS_315H) {
+ } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+ if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+ if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
} else {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+#ifdef SIS315H
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
- if(!(modeflag & HalfDCLK)) {
- SiS_Pr->SiS_LCDHDES = 320;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+ if(!(modeflag & HalfDCLK)) {
+ SiS_Pr->SiS_LCDHDES = 320;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
- }
- }
- }
- }
- }
+ }
+#endif
+ }
+ }
+ }
+ }
}
}
}
@@ -3832,54 +3869,90 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
/* DISABLE VIDEO BRIDGE */
/*********************************************/
+#ifdef SIS315H
+static int
+SiS_HandlePWD(struct SiS_Private *SiS_Pr)
+{
+ int ret = 0;
+#ifdef SET_PWD
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
+ unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
+ unsigned short temp;
+
+ if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
+ (romptr) &&
+ (SiS_Pr->SiS_PWDOffset) ) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
+ temp = 0x00;
+ if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
+ temp = 0x80;
+ ret = 1;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
+#endif
+#endif
+ }
+#endif
+ return ret;
+}
+#endif
+
/* NEVER use any variables (VBInfo), this will be called
* from outside the context of modeswitch!
* MUST call getVBType before calling this
*/
void
-SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_DisableBridge(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT tempah,pushax=0,modenum;
+ unsigned short tempah, pushax=0, modenum;
#endif
- USHORT temp=0;
+ unsigned short temp=0;
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== For 30xB/LV ===== */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
} else {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
}
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_PanelDelay(SiS_Pr, 3);
}
if(SiS_Is301B(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
SiS_ShortDelay(SiS_Pr,1);
- }
+ }
SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
SiS_DisplayOff(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
- if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ SiS_UnLockCRT2(SiS_Pr);
+ if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
}
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
} else {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
}
@@ -3889,130 +3962,127 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
+ int didpwd = 0;
BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
(SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
}
}
#endif
- if( (modenum <= 0x13) ||
- (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
- if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+
+ didpwd = SiS_HandlePWD(SiS_Pr);
+
+ if( (modenum <= 0x13) ||
+ (SiS_IsVAMode(SiS_Pr)) ||
+ (!(SiS_IsDualEdge(SiS_Pr))) ) {
+ if(!didpwd) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
+ if(custom1) SiS_PanelDelay(SiS_Pr, 3);
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
+ }
}
if(!custom1) {
SiS_DDC2Delay(SiS_Pr,0xff00);
SiS_DDC2Delay(SiS_Pr,0xe000);
- SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
- pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+ SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+ pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
if(IS_SIS740) {
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
}
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_PanelDelay(SiS_Pr, 3);
}
- }
+ }
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- tempah = 0xef;
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /* if(SiS_Pr->ChipType < SIS_340) {*/
+ tempah = 0xef;
+ if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+ /*}*/
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
}
tempah = 0x3f;
- if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempah = 0x7f;
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+ if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
}
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
- if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+ if((SiS_IsVAMode(SiS_Pr)) ||
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
SiS_DisplayOff(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
}
- if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+ if((!(SiS_IsVAMode(SiS_Pr))) ||
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
- if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
SiS_DisplayOff(SiS_Pr);
}
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
}
- if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-
- if(!custom1) {
-
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
- if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
- if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- }
- }
- }
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+ if( (!(SiS_IsVAMode(SiS_Pr))) &&
+ (!(SiS_CRT2IsLCD(SiS_Pr))) &&
+ (!(SiS_IsDualEdge(SiS_Pr))) ) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
- }
- }
-
- } else {
+ if(custom1) SiS_PanelDelay(SiS_Pr, 2);
+ if(!didpwd) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+ }
+ if(custom1) SiS_PanelDelay(SiS_Pr, 4);
+ }
- if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
- if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
- (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- SiS_PanelDelay(SiS_Pr, HwInfo, 4);
+ if(!custom1) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 20);
}
}
-
}
- }
+
+ }
#endif /* SIS315H */
@@ -4020,36 +4090,36 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For 301 ================ */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
#endif
}
- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
- SiS_DisplayOff(SiS_Pr);
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
+ SiS_DisplayOff(SiS_Pr);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
- if(HwInfo->jChipType >= SIS_315H) {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
} else {
#ifdef SIS300
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
#endif
}
@@ -4058,34 +4128,34 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For LVDS =============*/
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- SiS_SetCH700x(SiS_Pr,0x090E);
+ SiS_SetCH700x(SiS_Pr,0x0E,0x09);
}
- if(HwInfo->jChipType == SIS_730) {
+ if(SiS_Pr->ChipType == SIS_730) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
}
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
} else {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_WaitVBRetrace(SiS_Pr);
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
SiS_DisplayOff(SiS_Pr);
- }
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
- }
- }
+ }
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
+ }
+ }
}
}
@@ -4094,14 +4164,14 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
#endif /* SIS300 */
@@ -4110,113 +4180,113 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
- if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
- }
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+ /* } */
+ }
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 1) {
- SiS_SetCH701x(SiS_Pr,0xac76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
}
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
}
}
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsVAMode(SiS_Pr)) ) {
SiS_Chrontel701xBLOff(SiS_Pr);
- SiS_Chrontel701xOff(SiS_Pr,HwInfo);
+ SiS_Chrontel701xOff(SiS_Pr);
}
- if(HwInfo->jChipType != SIS_740) {
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
- SiS_SetCH701x(SiS_Pr,0x0149);
- }
+ if(SiS_Pr->ChipType != SIS_740) {
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+ SiS_SetCH701x(SiS_Pr,0x49,0x01);
+ }
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
SiS_DisplayOff(SiS_Pr);
}
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
- if(HwInfo->jChipType == SIS_550) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
+ if(SiS_Pr->ChipType == SIS_550) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
}
}
} else {
- if(HwInfo->jChipType == SIS_740) {
- if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+ if(SiS_Pr->ChipType == SIS_740) {
+ if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
}
- } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ } else if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
/* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
} else {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
- if(HwInfo->jChipType == SIS_550) {
+ if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
} else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
}
}
@@ -4237,78 +4307,81 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
* from outside the context of a mode switch!
* MUST call getVBType before calling this
*/
-static void
-SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_EnableBridge(struct SiS_Private *SiS_Pr)
{
- USHORT temp=0,tempah;
+ unsigned short temp=0, tempah;
#ifdef SIS315H
- USHORT temp1,pushax=0;
+ unsigned short temp1, pushax=0;
BOOLEAN delaylong = FALSE;
#endif
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ====== For 301B et al ====== */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
} else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
- if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
+ if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
}
if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
- (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+ (SiS_CRT2IsLCD(SiS_Pr))) {
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
- SiS_DisplayOn(SiS_Pr);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_DisplayOn(SiS_Pr);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
- }
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+ }
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
- }
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+ }
}
} else {
temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
- if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+ if(SiS_BridgeInSlavemode(SiS_Pr)) {
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
SiS_DisplayOn(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
- }
+ }
}
}
@@ -4322,31 +4395,32 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
#ifdef SET_EMI
- UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0;
- /* USHORT emidelay=0; */
+ unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
+ int didpwd = 0;
+ /* unsigned short emidelay=0; */
#endif
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
}
#endif
}
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) { */
tempah = 0x10;
- if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
- if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
- else tempah = 0x08;
+ if(SiS_LCDAEnabled(SiS_Pr)) {
+ if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
+ else tempah = 0x08;
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
- }
+ /*}*/
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
SiS_DisplayOff(SiS_Pr);
@@ -4355,42 +4429,51 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
}
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_GenericDelay(SiS_Pr, 0x4500);
+ didpwd = SiS_HandlePWD(SiS_Pr);
+
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ if(!didpwd) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 17664);
+ }
+ }
+ } else {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 17664);
}
}
}
if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
delaylong = TRUE;
}
}
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
+ if(!(SiS_IsVAMode(SiS_Pr))) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) {
- if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) {
+ if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
}
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
} else {
@@ -4402,38 +4485,48 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+ if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
+ if( (SiS_LCDAEnabled(SiS_Pr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr)) ) {
+ /* Enable "LVDS PLL power on" (even on 301C) */
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
+ /* Enable "LVDS Driver Power on" (even on 301C) */
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
+ }
+ }
+
tempah = 0xc0;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempah = 0x80;
- if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+ if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ SiS_PanelDelay(SiS_Pr, 2);
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
- SiS_GenericDelay(SiS_Pr, 0x500);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+ SiS_GenericDelay(SiS_Pr, 2048);
}
#endif
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
#ifdef SET_EMI
cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_ROMNew) {
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
if(romptr) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
SiS_Pr->EMI_30 = 0;
SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
@@ -4511,21 +4604,21 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
if(!SiS_Pr->OverruleEMI) {
#ifdef COMPAL_HACK
if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
- if((cr36 & 0x0f) == 0x09) {
+ if((cr36 & 0x0f) == 0x09) {
r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
}
}
#endif
#ifdef COMPAQ_HACK
if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
- if((cr36 & 0x0f) == 0x03) {
+ if((cr36 & 0x0f) == 0x03) {
r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
}
}
#endif
#ifdef ASUS_HACK
if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
- if((cr36 & 0x0f) == 0x02) {
+ if((cr36 & 0x0f) == 0x02) {
/* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
/* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
/* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
@@ -4533,11 +4626,11 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
}
#endif
- }
+ }
if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_GenericDelay(SiS_Pr, 2048);
}
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
@@ -4547,36 +4640,44 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
#ifdef SET_EMI
- if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
- (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
- if(r30 & 0x40) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+ if( (SiS_LCDAEnabled(SiS_Pr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr)) ) {
+ if(r30 & 0x40) {
+ /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
+ SiS_PanelDelayLoop(SiS_Pr, 3, 5);
if(delaylong) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 5);
delaylong = FALSE;
}
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_WaitVBRetrace(SiS_Pr);
if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_GenericDelay(SiS_Pr, 1280);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
- }
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
+ /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
+ }
}
#endif
}
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
if(delaylong) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
}
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_WaitVBRetrace(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 2048);
+ SiS_WaitVBRetrace(SiS_Pr);
+ }
+ if(!didpwd) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+ } else {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
}
}
@@ -4586,7 +4687,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
@@ -4596,26 +4697,26 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For 301 ================ */
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
}
SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
- if(HwInfo->jChipType >= SIS_315H) {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
- if(!(temp & 0x80)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
+ if(!(temp & 0x80)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
}
}
@@ -4623,15 +4724,15 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_VBLongWait(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
SiS_VBLongWait(SiS_Pr);
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
}
}
@@ -4639,49 +4740,49 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* =================== For LVDS ================== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(HwInfo->jChipType == SIS_730) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(SiS_Pr->ChipType == SIS_730) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
}
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_DisplayOn(SiS_Pr);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
} else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
- SiS_WaitVBRetrace(SiS_Pr, HwInfo);
- SiS_SetCH700x(SiS_Pr,0x0B0E);
- }
+ if(!(SiS_CRT2IsLCD(SiS_Pr))) {
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
+ }
}
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
- SiS_WaitVBRetrace(SiS_Pr, HwInfo);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
- }
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+ }
}
}
@@ -4691,94 +4792,94 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
- if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+ /*}*/
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
- }
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ SiS_PanelDelay(SiS_Pr, 0);
+ }
}
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
temp &= 0x20;
SiS_Chrontel701xBLOff(SiS_Pr);
}
- if(HwInfo->jChipType != SIS_550) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+ if(SiS_Pr->ChipType != SIS_550) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
- if(HwInfo->jChipType == SIS_740) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ if(SiS_Pr->ChipType == SIS_740) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
}
}
}
temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
if(!(temp1 & 0x80)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(temp) {
- SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
+ if(temp) {
+ SiS_Chrontel701xBLOn(SiS_Pr);
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
- if(HwInfo->jChipType == SIS_550) {
+ if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
}
}
- } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
- if(HwInfo->jChipType != SIS_740) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ } else if(SiS_IsVAMode(SiS_Pr)) {
+ if(SiS_Pr->ChipType != SIS_740) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
}
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) {
- SiS_Chrontel701xOn(SiS_Pr,HwInfo);
- }
- if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
- SiS_ChrontelDoSomething1(SiS_Pr,HwInfo);
- }
+ if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
+ SiS_Chrontel701xOn(SiS_Pr);
+ }
+ if( (SiS_IsVAMode(SiS_Pr)) ||
+ (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+ SiS_ChrontelDoSomething1(SiS_Pr);
+ }
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
- SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
- SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo);
- }
- }
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if( (SiS_IsVAMode(SiS_Pr)) ||
+ (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+ SiS_Chrontel701xBLOn(SiS_Pr);
+ SiS_ChrontelInitTVVSync(SiS_Pr);
+ }
+ }
} else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
}
}
}
@@ -4797,243 +4898,204 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* Set CRT2 OFFSET / PITCH */
static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RRTI, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RRTI)
{
- USHORT offset;
- UCHAR temp;
+ unsigned short offset;
+ unsigned char temp;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
- offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
+ offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
- offset >>= 1;
- }
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
- temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
- if(offset % 8) temp++;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
+ temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
+ if(offset & 0x07) temp++;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
}
/* Set CRT2 sync and PanelLink mode */
static void
-SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
{
- USHORT tempah=0,tempbl,infoflag;
+ unsigned short tempah=0, tempbl, infoflag;
- tempbl = 0xC0;
+ tempbl = 0xC0;
- if(SiS_Pr->UseCustomMode) {
- infoflag = SiS_Pr->CInfoFlag;
- } else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- }
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ } else {
+ infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ }
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tempah = 0;
- } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
- tempah = SiS_Pr->SiS_LCDInfo;
- } else tempah = infoflag >> 8;
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
- (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- tempah |= 0xf0;
- }
- if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
- (SiS_Pr->SiS_IF_DEF_DSTN) ||
- (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
- tempah |= 0x30;
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(HwInfo->jChipType >= SIS_315H) {
- tempah >>= 3;
- tempah &= 0x18;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
- /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
- }
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ tempah = 0;
+ } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
+ tempah = SiS_Pr->SiS_LCDInfo;
+ } else tempah = infoflag >> 8;
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+ (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+ tempah |= 0xf0;
+ }
+ if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+ (SiS_Pr->SiS_IF_DEF_DSTN) ||
+ (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+ tempah |= 0x30;
+ }
+ if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+ (SiS_Pr->SiS_IF_DEF_DSTN) ) {
+ tempah &= ~0xc0;
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ tempah >>= 3;
+ tempah &= 0x18;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+ /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
+ }
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ }
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---- 300 series --- */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 630 - 301B(-DH) */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
- tempah = infoflag >> 8;
- tempbl = 0;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempah = SiS_Pr->SiS_LCDInfo;
- tempbl = (tempah >> 6) & 0x03;
- }
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- tempah |= 0xc0;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
+ tempah = infoflag >> 8;
+ tempbl = 0;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempah = SiS_Pr->SiS_LCDInfo;
+ tempbl = (tempah >> 6) & 0x03;
+ }
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ tempah |= 0xc0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
- } else { /* 630 - 301 */
+ } else { /* 630 - 301 */
- tempah = infoflag >> 8;
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ tempah = ((infoflag >> 8) & 0xc0) | 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- }
+ }
#endif /* SIS300 */
- } else {
+ } else {
#ifdef SIS315H /* ------- 315 series ------ */
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 315 - LVDS */
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
- tempbl = 0;
- if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
- tempah = infoflag >> 8;
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
- }
- } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
- tempah = infoflag >> 8;
- tempbl = 0x03;
- } else {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- tempbl = (tempah >> 6) & 0x03;
- tempbl |= 0x08;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
- }
+ tempbl = 0;
+ if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+ tempah = infoflag >> 8;
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+ }
+ } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+ tempah = infoflag >> 8;
+ tempbl = 0x03;
+ } else {
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+ tempbl = (tempah >> 6) & 0x03;
+ tempbl |= 0x08;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
+ }
- } else { /* 315 - TMDS */
+ } else { /* 315 - TMDS */
- tempah = tempbl = infoflag >> 8;
- if(!SiS_Pr->UseCustomMode) {
- tempbl = 0;
- if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- if(ModeNo <= 0x13) {
- tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
- }
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempah = SiS_Pr->SiS_LCDInfo;
+ tempah = tempbl = infoflag >> 8;
+ if(!SiS_Pr->UseCustomMode) {
+ tempbl = 0;
+ if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ if(ModeNo <= 0x13) {
+ tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempah = SiS_Pr->SiS_LCDInfo;
tempbl = (tempah >> 6) & 0x03;
}
- }
- }
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- /* Imitate BIOS bug */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
- }
- if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- tempah >>= 3;
- tempah &= 0x18;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
- }
- }
+ }
+ }
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+ /* Imitate BIOS bug */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
+ }
+ if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ tempah >>= 3;
+ tempah &= 0x18;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
+ }
+ }
- }
+ }
#endif /* SIS315H */
}
}
}
-/* Set CRT2 FIFO on 300/630/730 */
+/* Set CRT2 FIFO on 300/540/630/730 */
#ifdef SIS300
static void
-SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
- PSIS_HW_INFO HwInfo)
-{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,index;
- USHORT modeidindex,refreshratetableindex;
- USHORT VCLK=0,MCLK,colorth=0,data2=0;
- USHORT tempal, tempah, tempbx, tempcl, tempax;
- USHORT CRT1ModeNo,CRT2ModeNo;
- USHORT SelectRate_backup;
- ULONG data,eax;
- const UCHAR LatencyFactor[] = {
- 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
- 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
- 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
- 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
- 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
- 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
- 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
- 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */
- };
- const UCHAR LatencyFactor730[] = {
- 69, 63, 61,
- 86, 79, 77,
- 103, 96, 94,
- 120,113,111,
- 137,130,128, /* <-- last entry, data below */
- 137,130,128, /* to avoid using illegal values */
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- };
- const UCHAR ThLowB[] = {
- 81, 4, 72, 6, 88, 8,120,12,
- 55, 4, 54, 6, 66, 8, 90,12,
- 42, 4, 45, 6, 55, 8, 75,12
- };
- const UCHAR ThTiming[] = {
- 1, 2, 2, 3, 0, 1, 1, 2
+SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
+{
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp, index, modeidindex, refreshratetableindex;
+ unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
+ unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
+ unsigned int data, pci50, pciA0;
+ static const unsigned char colortharray[] = {
+ 1, 1, 2, 2, 3, 4
};
SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
@@ -5044,232 +5106,159 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
SiS_Pr->SiS_SelectCRT2Rate = 0;
- refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo);
+ refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
if(CRT1ModeNo >= 0x13) {
- index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ /* Get VCLK */
+ index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); /* Get colordepth */
- colorth >>= 1;
- if(!colorth) colorth++;
+ /* Get colordepth */
+ colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
+ if(!colorth) colorth++;
}
} else {
CRT1ModeNo = 0xfe;
- VCLK = SiS_Pr->CSRClock_CRT1; /* Get VCLK */
- data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2;
- switch(data2) { /* Get color depth */
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- default: colorth = 2;
- }
+
+ /* Get VCLK */
+ VCLK = SiS_Pr->CSRClock_CRT1;
+
+ /* Get color depth */
+ colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
}
if(CRT1ModeNo >= 0x13) {
- if(HwInfo->jChipType == SIS_300) {
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
- } else {
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
- }
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
+ /* Get MCLK */
+ if(SiS_Pr->ChipType == SIS_300) {
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
+ } else {
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
+ }
+ index &= 0x07;
+ MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
- data2 = (colorth * VCLK) / MCLK;
+ temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
+ if(!temp) temp++;
+ temp <<= 2;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- temp = ((temp & 0x00FF) >> 6) << 1;
- if(temp == 0) temp = 1;
- temp <<= 2;
- temp &= 0xff;
+ data2 = temp - ((colorth * VCLK) / MCLK);
- data2 = temp - data2;
+ temp = (28 * 16) % data2;
+ data2 = (28 * 16) / data2;
+ if(temp) data2++;
- if((28 * 16) % data2) {
- data2 = (28 * 16) / data2;
- data2++;
- } else {
- data2 = (28 * 16) / data2;
- }
+ if(SiS_Pr->ChipType == SIS_300) {
- if(HwInfo->jChipType == SIS_300) {
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempah &= 0x62;
- tempah >>= 1;
- tempal = tempah;
- tempah >>= 3;
- tempal |= tempah;
- tempal &= 0x07;
- tempcl = ThTiming[tempal];
- tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempbx >>= 6;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- tempah >>= 4;
- tempah &= 0x0c;
- tempbx |= tempah;
- tempbx <<= 1;
- tempal = ThLowB[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowB[tempbx];
- data = tempal;
-
- } else if(HwInfo->jChipType == SIS_730) {
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
+ SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
+ data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
+
+ } else {
+
+#ifdef SIS_LINUX_KERNEL
+ pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+ pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
#else
- eax = pciReadLong(0x00000000, 0x50);
+ pci50 = pciReadLong(0x00000000, 0x50);
+ pciA0 = pciReadLong(0x00000000, 0xA0);
#endif
- tempal = (USHORT)(eax >> 8);
- tempal &= 0x06;
- tempal <<= 5;
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
-#else
- eax = pciReadLong(0x00000000, 0xA0);
-#endif
- temp = (USHORT)(eax >> 28);
- temp &= 0x0F;
- tempal |= temp;
-
- tempbx = tempal; /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
- tempbx = 0; /* -- do it like the BIOS anyway... */
- tempax = tempbx;
- tempbx &= 0xc0;
- tempbx >>= 6;
- tempax &= 0x0f;
- tempax *= 3;
- tempbx += tempax;
-
- data = LatencyFactor730[tempbx];
- data += 15;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(!(temp & 0x80)) data += 5;
+ if(SiS_Pr->ChipType == SIS_730) {
- } else {
+ index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
+ index += (unsigned short)(((pci50 >> 9)) & 0x03);
- index = 0;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(temp & 0x0080) index += 12;
+ /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
+ index = 0; /* -- do it like the BIOS anyway... */
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
-#else
- /* We use pci functions X offers. We use tag 0, because
- * we want to read/write to the host bridge (which is always
- * 00:00.0 on 630, 730 and 540), not the VGA device.
- */
- eax = pciReadLong(0x00000000, 0xA0);
-#endif
- temp = (USHORT)(eax >> 24);
- if(!(temp&0x01)) index += 24;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
-#else
- eax = pciReadLong(0x00000000, 0x50);
-#endif
- temp=(USHORT)(eax >> 24);
- if(temp & 0x01) index += 6;
+ } else {
- temp = (temp & 0x0F) >> 1;
- index += temp;
+ pci50 >>= 24;
+ pciA0 >>= 24;
- data = LatencyFactor[index];
- data += 15;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(!(temp & 0x80)) data += 5;
- }
+ index = (pci50 >> 1) & 0x07;
- data += data2; /* CRT1 Request Period */
+ if(pci50 & 0x01) index += 6;
+ if(!(pciA0 & 0x01)) index += 24;
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
- if(!SiS_Pr->UseCustomMode) {
+ }
- CRT2ModeNo = ModeNo;
- SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
+ data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
- refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo);
+ }
- index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
- refreshratetableindex,HwInfo);
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ data += data2; /* CRT1 Request Period */
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- if(SiS_Pr->SiS_UseROM) {
- if(ROMAddr[0x220] & 0x01) {
- VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
- }
- }
- }
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
- } else {
+ if(!SiS_Pr->UseCustomMode) {
- CRT2ModeNo = 0xfe;
- VCLK = SiS_Pr->CSRClock; /* Get VCLK */
+ CRT2ModeNo = ModeNo;
+ SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
- }
+ refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
- colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
- colorth >>= 1;
- if(!colorth) colorth++;
+ /* Get VCLK */
+ index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- data = data * VCLK * colorth;
- if(data % (MCLK << 4)) {
- data = data / (MCLK << 4);
- data++;
- } else {
- data = data / (MCLK << 4);
- }
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+ if(SiS_Pr->SiS_UseROM) {
+ if(ROMAddr[0x220] & 0x01) {
+ VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
+ }
+ }
+ }
- if(data <= 6) data = 6;
- if(data > 0x14) data = 0x14;
+ } else {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01);
- if(HwInfo->jChipType == SIS_300) {
- if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
- else temp = (temp & (~0x1F)) | 0x16;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
- temp = (temp & (~0x1F)) | 0x13;
- }
- } else {
- if( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */
- {
- temp = (temp & (~0x1F)) | 0x1b;
- } else {
- temp = (temp & (~0x1F)) | 0x16;
- }
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+ /* Get VCLK */
+ CRT2ModeNo = 0xfe;
+ VCLK = SiS_Pr->CSRClock;
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */
- {
- if(data > 0x13) data = 0x13;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
+ }
+
+ /* Get colordepth */
+ colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
+ if(!colorth) colorth++;
+
+ data = data * VCLK * colorth;
+ temp = data % (MCLK << 4);
+ data = data / (MCLK << 4);
+ if(temp) data++;
+
+ if(data < 6) data = 6;
+ else if(data > 0x14) data = 0x14;
+
+ if(SiS_Pr->ChipType == SIS_300) {
+ temp = 0x16;
+ if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
+ temp = 0x13;
+ } else {
+ temp = 0x16;
+ if(( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision >= 0x30))
+ temp = 0x1b;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+
+ if((SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30)) {
+ if(data > 0x13) data = 0x13;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
} else { /* If mode <= 0x13, we just restore everything */
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
}
}
@@ -5278,10 +5267,10 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
/* Set CRT2 FIFO on 315/330 series */
#ifdef SIS315H
static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
{
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
- if( (HwInfo->jChipType == SIS_760) &&
+ if( (SiS_Pr->ChipType == SIS_760) &&
(SiS_Pr->SiS_SysFlags & SF_760LFB) &&
(SiS_Pr->SiS_ModeType == Mode32Bpp) &&
(SiS_Pr->SiS_VGAHDE >= 1280) &&
@@ -5299,337 +5288,162 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
#endif
-static USHORT
-SiS_GetVGAHT2(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
{
- ULONG tempax,tempbx;
+ unsigned int tempax,tempbx;
tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
- return((USHORT)tempax);
+ return (unsigned short)tempax;
}
/* Set Part 1 / SiS bridge slave mode */
static void
-SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
-{
- USHORT push1,push2;
- USHORT tempax,tempbx,tempcx,temp;
- USHORT resinfo,modeflag,xres=0;
- unsigned char p1_7, p1_8;
+SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
+ static const unsigned short CRTranslation[] = {
+ /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
+ 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
+ /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
+ 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
+ };
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
- resinfo = 0;
xres = SiS_Pr->CHDisplay;
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
}
/* The following is only done if bridge is in slave mode: */
- if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
- if(xres >= 1600) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(xres >= 1600) { /* BIOS: == 1600 */
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
}
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff); /* set MAX HT */
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) modeflag |= Charx8Dot;
+ SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
- if(modeflag & Charx8Dot) tempcx = 0x08;
- else tempcx = 0x09;
-
- tempax = SiS_Pr->SiS_VGAHDE; /* 0x04 Horizontal Display End */
- if(modeflag & HalfDCLK) tempax >>= 1;
- tempax = ((tempax / tempcx) - 1) & 0xff;
- tempbx = tempax;
-
- temp = tempax;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp);
+ SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
+ SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
- temp += 2;
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(resinfo == SIS_RI_800x600) temp -= 2;
- }
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp); /* 0x05 Horizontal Display Start */
-
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03); /* 0x06 Horizontal Blank end */
-
- tempax = 0xFFFF;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
- if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT;
- if(modeflag & HalfDCLK) tempax >>= 1;
- tempax = (tempax / tempcx) - 5;
- tempcx = tempax;
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- temp = tempcx - 1;
- if(!(modeflag & HalfDCLK)) {
- temp -= 6;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- temp -= 2;
- if(ModeNo > 0x13) temp -= 10;
- }
- }
- } else {
- tempcx = (tempcx + tempbx) >> 1;
- temp = (tempcx & 0x00FF) + 2;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- temp--;
- if(!(modeflag & HalfDCLK)) {
- if((modeflag & Charx8Dot)) {
- temp += 4;
- if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
- }
- }
- }
- } else {
- if(!(modeflag & HalfDCLK)) {
- temp -= 4;
- if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
- (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
- if(SiS_Pr->SiS_VGAHDE >= 800) {
- temp -= 7;
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_ModeType == ModeEGA) {
- if(SiS_Pr->SiS_VGAVDE == 1024) {
- temp += 15;
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
- temp += 7;
- }
- }
- }
- if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
- if(SiS_Pr->SiS_VGAHDE >= 1280) {
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
- }
- }
- }
- }
- }
- }
+ SiS_Pr->CHBlankStart += 16;
}
- p1_7 = temp;
- p1_8 = 0x00;
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(ModeNo <= 0x01) {
- p1_7 = 0x2a;
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61;
- else p1_8 = 0x41;
- } else if(SiS_Pr->SiS_ModeType == ModeText) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54;
- else p1_7 = 0x55;
- p1_8 = 0x00;
- } else if(ModeNo <= 0x13) {
- if(modeflag & HalfDCLK) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- p1_7 = 0x30;
- p1_8 = 0x03;
- } else {
- p1_7 = 0x2f;
- p1_8 = 0x02;
- }
- } else {
- p1_7 = 0x5b;
- p1_8 = 0x03;
- }
- } else if( ((HwInfo->jChipType >= SIS_315H) &&
- ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) ||
- ((HwInfo->jChipType < SIS_315H) &&
- (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- p1_7 = 0x30,
- p1_8 = 0x03;
- } else {
- p1_7 = 0x2f;
- p1_8 = 0x03;
- }
- }
- }
+ SiS_Pr->CHBlankEnd = 32;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
}
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) {
- p1_7 = 0x63;
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55;
- }
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(!(modeflag & HalfDCLK)) {
- p1_7 = 0xb2;
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- p1_7 = 0xab;
- }
- }
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
- if(modeflag & HalfDCLK) p1_7 = 0x30;
- }
- }
+ temp = SiS_Pr->SiS_VGAHT - 96;
+ if(!(modeflag & HalfDCLK)) temp -= 32;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
+ temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
+ temp -= 3;
+ temp <<= 3;
+ } else {
+ if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
}
+ SiS_Pr->CHSyncStart = temp;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7); /* 0x07 Horizontal Retrace Start */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8); /* 0x08 Horizontal Retrace End */
+ SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03); /* 0x18 SR08 (FIFO Threshold?) */
+ SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
+ VGAVDE = SiS_Pr->SiS_VGAVDE;
+ if (VGAVDE == 357) VGAVDE = 350;
+ else if(VGAVDE == 360) VGAVDE = 350;
+ else if(VGAVDE == 375) VGAVDE = 350;
+ else if(VGAVDE == 405) VGAVDE = 400;
+ else if(VGAVDE == 420) VGAVDE = 400;
+ else if(VGAVDE == 525) VGAVDE = 480;
+ else if(VGAVDE == 1056) VGAVDE = 1024;
+ SiS_Pr->CVDisplay = VGAVDE;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF); /* 0x09 Set Max VT */
+ SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
- tempcx = 0x121;
- tempbx = SiS_Pr->SiS_VGAVDE; /* 0x0E Vertical Display End */
- if (tempbx == 357) tempbx = 350;
- else if(tempbx == 360) tempbx = 350;
- else if(tempbx == 375) tempbx = 350;
- else if(tempbx == 405) tempbx = 400;
- else if(tempbx == 420) tempbx = 400;
- else if(tempbx == 525) tempbx = 480;
- push2 = tempbx;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if (tempbx == 350) tempbx += 5;
- else if(tempbx == 480) tempbx += 5;
- }
- }
- }
- tempbx -= 2;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp); /* 0x10 vertical Blank Start */
-
- tempbx = push2;
- tempbx--;
- temp = tempbx & 0x00FF;
-#if 0
- /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
- if(xxx()) {
- if(temp == 0xdf) temp = 0xda;
- }
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);
-
- temp = 0;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- if(HwInfo->jChipType >= SIS_661) {
- if(tempbx & 0x0200) temp |= 0x20;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp);
- if(tempbx & 0x0100) tempcx |= 0x000a;
- if(tempbx & 0x0400) tempcx |= 0x1200;
- } else {
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);
- if(tempbx & 0x0100) tempcx |= 0x0002;
- if(tempbx & 0x0400) tempcx |= 0x0600;
- }
+ SiS_Pr->CVBlankEnd = 1;
+ if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
- if(tempbx & 0x0200) tempcx |= 0x0040;
+ temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
+ SiS_Pr->CVSyncStart = VGAVDE + temp;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00); /* 0x11 Vertical Blank End */
+ temp >>= 3;
+ SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
- tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
+ SiS_CalcCRRegisters(SiS_Pr, 0);
+ SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
- if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) {
- if(resinfo != SIS_RI_1280x1024) {
- tempbx += (tempax << 1);
- }
- } else if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
- tempbx += (tempax << 1);
- }
+ for(i = 0; i <= 7; i++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
}
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- tempbx -= 10;
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- tempbx += 40;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
- }
- }
- }
- }
- tempax >>= 2;
- tempax++;
- tempax += tempbx;
- push1 = tempax;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(tempbx <= 513) {
- if(tempax >= 513) tempbx = 513;
- }
+ for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* 0x0C Vertical Retrace Start */
-
- tempbx--;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);
-
- if(tempbx & 0x0100) tempcx |= 0x0008;
-
- if(tempbx & 0x0200) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
+ for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- tempbx++;
-
- if(tempbx & 0x0100) tempcx |= 0x0004;
- if(tempbx & 0x0200) tempcx |= 0x0080;
- if(tempbx & 0x0400) {
- if(HwInfo->jChipType >= SIS_661) tempcx |= 0x0800;
- else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
- else tempcx |= 0x0C00;
+ for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- tempbx = push1;
- temp = tempbx & 0x000F;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp); /* 0x0D vertical Retrace End */
-
- if(tempbx & 0x0010) tempcx |= 0x2000;
-
- temp = tempcx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* 0x0A CR07 */
-
- temp = (tempcx & 0xFF00) >> 8;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* 0x17 SR0A */
+ temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
- tempax = modeflag;
- temp = (tempax & 0xFF00) >> 8;
- temp = (temp >> 1) & 0x09;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01; /* Always 8 dotclock */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* 0x16 SR01 */
+ temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* 0x0F CR14 */
+ temp = 0;
+ temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
+ if(modeflag & HalfDCLK) temp |= 0x08;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* 0x12 CR17 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
- temp = 0x00;
+ temp = 0;
if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
- if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
- temp = 0x80;
- }
+ temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* 0x1A SR0E */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
+
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
+ SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+ SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+ SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+ xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+ SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+ SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+ SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+ SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+ xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+ SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+ SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+ SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+ SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+ xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+#endif
}
/* Setup panel link
@@ -5637,18 +5451,18 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
* 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
*/
static void
-SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT modeflag,resinfo;
- USHORT push2,tempax,tempbx,tempcx,temp;
- ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+ unsigned short modeflag, resinfo = 0;
+ unsigned short push2, tempax, tempbx, tempcx, temp;
+ unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
BOOLEAN islvds = FALSE, issis = FALSE, chkdclkfirst = FALSE;
#ifdef SIS300
- USHORT crt2crtc;
+ unsigned short crt2crtc = 0;
#endif
#ifdef SIS315H
- USHORT pushcx;
+ unsigned short pushcx;
#endif
if(ModeNo <= 0x13) {
@@ -5659,15 +5473,11 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
- resinfo = 0;
-#ifdef SIS300
- crt2crtc = 0;
-#endif
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
#ifdef SIS300
- crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
#endif
}
@@ -5681,14 +5491,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
issis = TRUE;
}
- if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
chkdclkfirst = TRUE;
}
}
#ifdef SIS315H
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(IS_SIS330) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
} else if(IS_SIS740) {
@@ -5704,7 +5514,7 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
@@ -5720,10 +5530,10 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempax = SiS_Pr->SiS_LCDHDES;
if(islvds) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
- tempax -= 8;
+ if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
+ if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+ tempax -= 8;
}
}
}
@@ -5736,13 +5546,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = SiS_Pr->SiS_HDE;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
- tempbx >>= 1;
- }
if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
tempbx = SiS_Pr->PanelXRes;
}
+ if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
+ tempbx >>= 1;
+ }
}
tempax += tempbx;
@@ -5767,25 +5578,25 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp = (tempcx >> 3) & 0x00FF;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- switch(ModeNo) {
- case 0x04:
- case 0x05:
- case 0x0d: temp = 0x56; break;
- case 0x10: temp = 0x60; break;
- case 0x13: temp = 0x5f; break;
- case 0x40:
- case 0x41:
- case 0x4f:
- case 0x43:
- case 0x44:
- case 0x62:
- case 0x56:
- case 0x53:
- case 0x5d:
- case 0x5e: temp = 0x54; break;
- }
- }
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ switch(ModeNo) {
+ case 0x04:
+ case 0x05:
+ case 0x0d: temp = 0x56; break;
+ case 0x10: temp = 0x60; break;
+ case 0x13: temp = 0x5f; break;
+ case 0x40:
+ case 0x41:
+ case 0x4f:
+ case 0x43:
+ case 0x44:
+ case 0x62:
+ case 0x56:
+ case 0x53:
+ case 0x5d:
+ case 0x5e: temp = 0x54; break;
+ }
+ }
}
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
@@ -5793,12 +5604,12 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
temp += 2;
if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- temp += 8;
- if(SiS_Pr->PanelHRE != 999) {
- temp = tempcx + SiS_Pr->PanelHRE;
+ temp += 8;
+ if(SiS_Pr->PanelHRE != 999) {
+ temp = tempcx + SiS_Pr->PanelHRE;
if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
temp >>= 3;
- }
+ }
}
} else {
temp += 10;
@@ -5806,9 +5617,6 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp &= 0x1F;
temp |= ((tempcx & 0x07) << 5);
-#if 0
- if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20; /* WRONG? BIOS loads cl, not ah */
-#endif
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
/* Vertical */
@@ -5826,9 +5634,9 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
push2 = tempbx;
tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
}
}
@@ -5844,19 +5652,19 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(issis) tempbx++;
} else {
tempbx += tempcx;
- if(HwInfo->jChipType < SIS_315H) tempbx++;
+ if(SiS_Pr->ChipType < SIS_315H) tempbx++;
else if(issis) tempbx++;
}
- if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; /* BPLVRS */
+ if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
temp = tempbx & 0x00FF;
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(ModeNo == 0x10) temp = 0xa9;
+ if(ModeNo == 0x10) temp = 0xa9;
}
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
tempcx >>= 3;
tempcx++;
@@ -5879,13 +5687,13 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
tempbx = 0x87;
- if((HwInfo->jChipType >= SIS_315H) ||
- (HwInfo->jChipRevision >= 0x30)) {
+ if((SiS_Pr->ChipType >= SIS_315H) ||
+ (SiS_Pr->ChipRevision >= 0x30)) {
tempbx = 0x07;
if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
}
- /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+ /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
@@ -5896,59 +5704,58 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
- tempbx = push2; /* BPLVDEE */
+ tempbx = push2; /* BPLVDEE */
- tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
+ tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_640x480:
- tempbx = SiS_Pr->SiS_VGAVDE - 1;
- tempcx = SiS_Pr->SiS_VGAVDE;
+ tempbx = SiS_Pr->SiS_VGAVDE - 1;
+ tempcx = SiS_Pr->SiS_VGAVDE;
break;
case Panel_800x600:
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_800x600) tempcx++;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_800x600) tempcx++;
+ }
break;
case Panel_1024x600:
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_1024x600) tempcx++;
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_1024x600) tempcx++;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
if(resinfo == SIS_RI_800x600) tempcx++;
}
- }
+ }
break;
case Panel_1024x768:
- if(HwInfo->jChipType < SIS_315H) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_1024x768) tempcx++;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_1024x768) tempcx++;
}
- }
+ }
break;
}
}
temp = ((tempbx >> 8) & 0x07) << 3;
- temp = temp | ((tempcx >> 8) & 0x07);
+ temp |= ((tempcx >> 8) & 0x07);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
- /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++; */
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
/* Vertical scaling */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
tempeax = SiS_Pr->SiS_VGAVDE << 6;
- temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
- tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+ temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
+ tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
if(temp) tempeax++;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
- temp = (USHORT)(tempeax & 0x00FF);
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
tempvcfact = temp;
#endif /* SIS300 */
@@ -5963,20 +5770,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(temp) tempeax++;
tempvcfact = tempeax;
- temp = (USHORT)(tempeax & 0x00FF);
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
- temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
- temp = (USHORT)((tempeax & 0x00030000) >> 16);
+ temp = (unsigned short)((tempeax & 0x00030000) >> 16);
if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
- temp = (USHORT)(tempeax & 0x00FF);
+ if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
- temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
- temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+ temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
temp = 0;
if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
@@ -5997,29 +5804,29 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempecx = 0xFFFF;
} else {
tempecx = tempebx / SiS_Pr->SiS_HDE;
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
}
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
tempeax = (tempebx / tempecx) - 1;
} else {
tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
}
tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
- temp = (USHORT)(tempecx & 0x00FF);
+ temp = (unsigned short)(tempecx & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
- tempbx = (USHORT)(tempeax & 0xFFFF);
+ tempbx = (unsigned short)(tempeax & 0xFFFF);
} else {
tempeax = SiS_Pr->SiS_VGAVDE << 6;
tempbx = tempvcfact & 0x3f;
if(tempbx == 0) tempbx = 64;
tempeax /= tempbx;
- tempbx = (USHORT)(tempeax & 0xFFFF);
+ tempbx = (unsigned short)(tempeax & 0xFFFF);
}
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
@@ -6032,24 +5839,24 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
- tempecx >>= 16; /* BPLHCFACT */
+ tempecx >>= 16; /* BPLHCFACT */
if(!chkdclkfirst) {
if(modeflag & HalfDCLK) tempecx >>= 1;
}
- temp = (USHORT)((tempecx & 0xFF00) >> 8);
+ temp = (unsigned short)((tempecx & 0xFF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
- temp = (USHORT)(tempecx & 0x00FF);
+ temp = (unsigned short)(tempecx & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+ if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
}
} else {
if(islvds) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
} else {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
@@ -6061,17 +5868,26 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
- int i;
- UCHAR TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
- UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
- UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned char *trumpdata;
+ int i, j = crt2crtc;
+ unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
+ unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+ unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+ if(SiS_Pr->SiS_UseROM) {
+ trumpdata = &ROMAddr[0x8001 + (j * 80)];
+ } else {
+ if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
+ trumpdata = &SiS300_TrumpionData[j][0];
+ }
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
for(i=0; i<5; i++) {
- SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+ SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
}
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(ModeNo == 0x13) {
+ if(ModeNo == 0x13) {
for(i=0; i<4; i++) {
SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
}
@@ -6095,67 +5911,66 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
- tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+ tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
tempax += 64;
- temp = tempax & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
- temp = ((tempax & 0xFF00) >> 8) << 3;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
+ temp = (tempax >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
- tempax += 32; /* Blpe=lBlps+32 */
- temp = tempax & 0x00FF;
- if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml=0 */
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
+ tempax += 32; /* Blpe = lBlps+32 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
tempax = SiS_Pr->SiS_VDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
tempax >>= 1;
- temp = tempax & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
- temp = ((tempax & 0xFF00) >> 8) << 3;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
+ temp = (tempax >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
tempeax = SiS_Pr->SiS_HDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
- tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
- tempebx = 128;
- temp = (USHORT)(tempeax % tempebx);
- tempeax = tempeax / tempebx;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
+ tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
+ temp = tempeax & 0x7f;
+ tempeax >>= 7;
if(temp) tempeax++;
- temp = (USHORT)(tempeax & 0x003F);
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
+ temp = tempeax & 0x3f;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
tempax = SiS_Pr->SiS_HDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
- tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+ tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
pushcx = tempax;
temp = tempax & 0x00FF;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
temp = ((tempax & 0xFF00) >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
- tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
- tempeax = (tempax * pushcx);
- tempebx = 0x00100000 + tempeax;
- temp = (USHORT)tempebx & 0x000000FF;
+ tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+ tempeax = tempax * pushcx;
+ temp = tempeax & 0xFF;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
- temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+ temp = (tempeax & 0xFF00) >> 8;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
- temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
+ temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
- temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
+ temp = ((tempeax & 0x01000000) >> 24) << 7;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
@@ -6192,20 +6007,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* Set Part 1 */
static void
-SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
#if defined(SIS300) || defined(SIS315H)
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
#endif
- USHORT temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
- USHORT pushbx=0, CRT1Index=0, modeflag, resinfo=0;
+ unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
+ unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
#ifdef SIS315H
- USHORT tempbl=0;
+ unsigned short tempbl=0;
#endif
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
return;
}
@@ -6214,47 +6029,47 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
} else {
- CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
}
- SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- if( ! ((HwInfo->jChipType >= SIS_315H) &&
+ if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
(SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
- if(HwInfo->jChipType < SIS_315H ) {
+ if(SiS_Pr->ChipType < SIS_315H ) {
#ifdef SIS300
- SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+ SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
#endif
} else {
#ifdef SIS315H
- SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
+ SiS_SetCRT2FIFO_310(SiS_Pr);
#endif
}
/* 1. Horizontal setup */
- if(HwInfo->jChipType < SIS_315H ) {
+ if(SiS_Pr->ChipType < SIS_315H ) {
#ifdef SIS300 /* ------------- 300 series --------------*/
- temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
+ temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
- temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
+ temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
- temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
+ temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
- tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
- tempbx = pushbx + tempcx;
- tempcx <<= 1;
- tempcx += tempbx;
+ tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+ tempbx = pushbx + tempcx;
+ tempcx <<= 1;
+ tempcx += tempbx;
bridgeadd = 12;
@@ -6301,7 +6116,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
bridgeadd = 16;
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
if(resinfo == SIS_RI_1280x1024) {
@@ -6319,7 +6134,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->UseCustomMode) {
+ if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncStart + bridgeadd;
tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
tempax = SiS_Pr->SiS_VGAHT;
@@ -6341,22 +6156,22 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
}
- tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
- tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
+ tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
+ tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
tempcx &= 0x00FF;
tempcx |= (tempbx & 0xFF00);
- tempbx += bridgeadd;
- tempcx += bridgeadd;
+ tempbx += bridgeadd;
+ tempcx += bridgeadd;
tempax = SiS_Pr->SiS_VGAHT;
if(modeflag & HalfDCLK) tempax >>= 1;
tempax--;
if(tempcx > tempax) tempcx = tempax;
- }
+ }
- if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- tempbx = 1040;
- tempcx = 1044; /* HWCursor bug! */
- }
+ if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
+ tempbx = 1040;
+ tempcx = 1044; /* HWCursor bug! */
+ }
}
@@ -6372,18 +6187,18 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempcx = SiS_Pr->SiS_VGAVT - 1;
temp = tempcx & 0x00FF;
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
temp--;
}
- }
+ }
} else {
- temp--;
- }
- } else if(HwInfo->jChipType >= SIS_315H) {
+ temp--;
+ }
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
temp--;
}
}
@@ -6395,9 +6210,9 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
- if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
- tempbx++;
- tempax = tempbx;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+ tempbx++;
+ tempax = tempbx;
tempcx++;
tempcx -= tempax;
tempcx >>= 2;
@@ -6407,8 +6222,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempcx += tempbx;
tempcx++;
} else {
- tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
- tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
+ tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
+ tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -6416,7 +6231,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = SiS_Pr->CVSyncStart;
tempcx = SiS_Pr->CVSyncEnd;
}
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
unsigned char cr8, cr7, cr13;
if(SiS_Pr->UseCustomMode) {
cr8 = SiS_Pr->CCRT1CRTC[8];
@@ -6429,11 +6244,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
}
- tempbx = cr8;
- if(cr7 & 0x04) tempbx |= 0x0100;
- if(cr7 & 0x80) tempbx |= 0x0200;
- if(cr13 & 0x08) tempbx |= 0x0400;
- }
+ tempbx = cr8;
+ if(cr7 & 0x04) tempbx |= 0x0100;
+ if(cr7 & 0x80) tempbx |= 0x0200;
+ if(cr13 & 0x08) tempbx |= 0x0400;
+ }
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
@@ -6442,13 +6257,13 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* 3. Panel delay compensation */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---------- 300 series -------------- */
if(SiS_Pr->SiS_VBType & VB_SISVB) {
temp = 0x20;
- if(HwInfo->jChipType == SIS_300) {
+ if(SiS_Pr->ChipType == SIS_300) {
temp = 0x10;
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
@@ -6460,24 +6275,23 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
- else temp = 0x20;
- }
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
+ else temp = 0x20;
+ }
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x80) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
- temp = ROMAddr[0x221];
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+ temp = ROMAddr[0x221];
else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
temp = ROMAddr[0x222];
else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
temp = ROMAddr[0x223];
else
temp = ROMAddr[0x224];
- temp &= 0x3c;
}
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
+ if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
}
} else {
@@ -6487,15 +6301,17 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x80) {
- temp = ROMAddr[0x220] & 0x3c;
+ temp = ROMAddr[0x220];
}
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
+ if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
}
- }
+ }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+ temp &= 0x3c;
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
#endif /* SIS300 */
@@ -6503,16 +6319,16 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS315H /* --------------- 315/330 series ---------------*/
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(HwInfo->jChipType == SIS_740) temp = 0x03;
- else temp = 0x00;
+ if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
+ else temp = 0x00;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
tempbl = 0xF0;
- if(HwInfo->jChipType == SIS_650) {
+ if(SiS_Pr->ChipType == SIS_650) {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
}
@@ -6531,10 +6347,10 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} /* < 661 */
- tempax = 0;
- if(modeflag & DoubleScanMode) tempax |= 0x80;
- if(modeflag & HalfDCLK) tempax |= 0x40;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+ tempax = 0;
+ if(modeflag & DoubleScanMode) tempax |= 0x80;
+ if(modeflag & HalfDCLK) tempax |= 0x40;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
#endif /* SIS315H */
@@ -6544,21 +6360,21 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- /* For 301BDH with LCD, we set up the Panel Link */
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ /* For 301BDH with LCD, we set up the Panel Link */
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else {
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
- }
+ if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
+ }
} else {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
}
}
}
@@ -6569,11 +6385,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS315H
-static UCHAR *
-SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
+static unsigned char *
+SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
{
- const UCHAR *tableptr = NULL;
- USHORT a, b, p = 0;
+ const unsigned char *tableptr = NULL;
+ unsigned short a, b, p = 0;
a = SiS_Pr->SiS_VGAHDE;
b = SiS_Pr->SiS_HDE;
@@ -6606,25 +6422,25 @@ SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
}
p += 2;
- return((UCHAR *)&tableptr[p]);
+ return ((unsigned char *)&tableptr[p]);
}
static void
-SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- UCHAR *tableptr;
+ unsigned char *tableptr;
+ unsigned char temp;
int i, j;
- UCHAR temp;
- if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
- tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
+ tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo);
+ tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
}
@@ -6635,12 +6451,12 @@ SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
static BOOLEAN
-SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,USHORT *CRT2Index,
- USHORT *ResIndex,PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
+ unsigned short *ResIndex)
{
- if(HwInfo->jChipType < SIS_315H) return FALSE;
+ if(SiS_Pr->ChipType < SIS_315H) return FALSE;
if(ModeNo <= 0x13)
(*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -6661,82 +6477,79 @@ SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
}
}
- return(((*CRT2Index) != 0));
+ return (((*CRT2Index) != 0));
}
#endif
#ifdef SIS300
static void
-SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
{
- USHORT tempcx;
- const UCHAR atable[] = {
+ unsigned short tempcx;
+ static const unsigned char atable[] = {
0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
};
if(!SiS_Pr->UseCustomMode) {
- if( ( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision > 2) ) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
- (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
- (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
- if(ModeNo == 0x13) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
- } else {
- if((crt2crtc & 0x3F) == 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
- }
- }
+ if( ( ( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision > 2) ) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+ (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
+ (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+ if(ModeNo == 0x13) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+ } else if((crt2crtc & 0x3F) == 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+ }
}
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
- crt2crtc &= 0x1f;
- tempcx = 0;
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- tempcx += 7;
- }
- }
- tempcx += crt2crtc;
- if(crt2crtc >= 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
- }
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+ crt2crtc &= 0x1f;
+ tempcx = 0;
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ tempcx += 7;
+ }
+ }
+ tempcx += crt2crtc;
+ if(crt2crtc >= 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+ }
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(crt2crtc == 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
- }
- }
- }
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(crt2crtc == 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+ }
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+ }
}
}
}
/* For ECS A907. Highly preliminary. */
static void
-SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
- USHORT ModeNo)
+SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+ unsigned short ModeNo)
{
- USHORT crt2crtc, resindex;
- int i,j;
- const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+ const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
+ unsigned short crt2crtc, resindex;
+ int i, j;
- if(HwInfo->jChipType != SIS_300) return;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+ if(SiS_Pr->ChipType != SIS_300) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
if(SiS_Pr->UseCustomMode) return;
if(ModeNo <= 0x13) {
@@ -6758,13 +6571,13 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
for(j = 0x1c; j <= 0x1d; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
for(j = 0x1f; j <= 0x21; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
@@ -6772,15 +6585,15 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
#endif
static void
-SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- const UCHAR specialtv[] = {
+ const unsigned char specialtv[] = {
0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
0x58,0xe4,0x73,0xda,0x13
@@ -6813,16 +6626,16 @@ SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
}
static void
-SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp;
+ unsigned short temp;
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
if(SiS_Pr->SiS_VGAVDE == 525) {
temp = 0xc3;
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
temp++;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
@@ -6830,7 +6643,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
temp = 0x4d;
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
temp++;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
}
@@ -6838,7 +6651,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
/* Not always for LV, see SetGrp2 */
}
@@ -6872,17 +6685,17 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
}
static void
-SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
-{
- USHORT i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
- USHORT push2, modeflag, crt2crtc, bridgeoffset;
- ULONG longtemp;
- const UCHAR *PhasePoint;
- const UCHAR *TimingPoint;
+SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+ unsigned short push2, modeflag, crt2crtc, bridgeoffset;
+ unsigned int longtemp, PhaseIndex;
+ BOOLEAN newtvphase;
+ const unsigned char *TimingPoint;
#ifdef SIS315H
- USHORT resindex, CRT2Index;
- const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+ unsigned short resindex, CRT2Index;
+ const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
#endif
@@ -6908,9 +6721,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
- PhasePoint = SiS_Pr->SiS_PALPhase;
+ PhaseIndex = 0x01; /* SiS_PALPhase */
TimingPoint = SiS_Pr->SiS_PALTiming;
+ newtvphase = FALSE;
+ if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+ (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+ newtvphase = TRUE;
+ }
+
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
@@ -6918,82 +6738,54 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-#if 0
- if(!(modeflag & Charx8Dot)) TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
-#endif
}
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) TimingPoint = &SiS_YPbPrTable[2][0];
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0];
- else TimingPoint = &SiS_YPbPrTable[0][0];
+ i = 0;
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
+
+ TimingPoint = &SiS_YPbPrTable[i][0];
- PhasePoint = SiS_Pr->SiS_NTSCPhase;
+ PhaseIndex = 0x00; /* SiS_NTSCPhase */
} else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALPhase2;
- }
+ if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
} else {
TimingPoint = SiS_Pr->SiS_NTSCTiming;
- PhasePoint = SiS_Pr->SiS_NTSCPhase;
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_PALPhase;
- }
-
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_NTSCPhase2;
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_PALPhase2;
- }
- }
-
- }
+ PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
+ if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- PhasePoint = SiS_Pr->SiS_PALMPhase;
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALMPhase2;
- }
}
- if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- PhasePoint = SiS_Pr->SiS_PALNPhase;
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALNPhase2;
- }
+ if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
+ PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
+ if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
}
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- PhasePoint = SiS_Pr->SiS_SpecialPhase;
if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- PhasePoint = SiS_Pr->SiS_SpecialPhaseM;
+ PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
} else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_SpecialPhaseJ;
+ PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
+ } else {
+ PhaseIndex = 0x10; /* SiS_SpecialPhase */
}
}
- for(i=0x31, j=0; i<=0x34; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]);
+ for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
}
- for(i=0x01, j=0; i<=0x2D; i++, j++) {
+ for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
}
- for(i=0x39; i<=0x45; i++, j++) {
+ for(i = 0x39; i <= 0x45; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
}
@@ -7010,28 +6802,32 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
- else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
- else tempax = 440; /* NTSC, YPbPr 525, 750 */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
+ else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
+ else tempax = 440; /* NTSC, YPbPr 525 */
- if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
+ if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
tempax -= SiS_Pr->SiS_VDE;
- tempax >>= 2;
+ tempax >>= 1;
+ if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
+ tempax >>= 1;
+ }
tempax &= 0x00ff;
- temp = tempax + (USHORT)TimingPoint[0];
+ temp = tempax + (unsigned short)TimingPoint[0];
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
- temp = tempax + (USHORT)TimingPoint[1];
+ temp = tempax + (unsigned short)TimingPoint[1];
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 19 */
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 52 */
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
} else {
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7041,14 +6837,14 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
}
tempcx = SiS_Pr->SiS_HT;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
tempcx--;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
tempcx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
tempcx += 7;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
@@ -7075,7 +6871,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
tempcx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
j += 2;
tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
@@ -7094,7 +6890,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
} else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
tempbx >>= 1;
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
@@ -7123,23 +6919,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
}
-#if 0
- /* TEST qqqq */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- for(i=0x01, j=0; i<=0x2D; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
- }
- for(i=0x39; i<=0x45; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
- }
- }
-#endif
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
tempbx = SiS_Pr->SiS_VDE;
if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
@@ -7150,7 +6934,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
}
}
@@ -7165,14 +6949,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempch = tempcl = 0x01;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VGAHDE >= 1024) {
- if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
- tempch = 0x19;
+ if(SiS_Pr->SiS_VGAHDE >= 960) {
+ if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
tempcl = 0x20;
- if(SiS_Pr->SiS_VGAHDE >= 1280) {
- tempch = 0x14;
+ if(SiS_Pr->SiS_VGAHDE >= 1280) {
+ tempch = 20;
tempbx &= ~0x20;
- }
+ } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
+ tempch = 25;
+ } else {
+ tempch = 25; /* OK */
+ }
}
}
}
@@ -7180,7 +6967,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(!(tempbx & 0x20)) {
if(modeflag & HalfDCLK) tempcl <<= 1;
longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
tempax = longtemp / SiS_Pr->SiS_HDE;
if(longtemp % SiS_Pr->SiS_HDE) tempax++;
tempbx |= ((tempax >> 8) & 0x1F);
@@ -7190,7 +6977,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
tempcx &= 0x07;
if(tempbx & 0x20) tempcx = 0;
@@ -7219,7 +7006,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetTVSpecial(SiS_Pr, ModeNo);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
temp = 0;
if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
@@ -7246,7 +7033,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/* From here: Part2 LCD setup */
tempbx = SiS_Pr->SiS_HDE;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx--; /* RHACTE = HDE - 1 */
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
@@ -7256,10 +7043,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->SiS_ModeType == ModeEGA) {
if(SiS_Pr->SiS_VGAHDE >= 1024) {
temp = 0x02;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- temp = 0x01;
- }
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ temp = 0x01;
}
}
}
@@ -7289,11 +7074,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
#ifdef SIS315H
if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &CRT2Index, &resindex, HwInfo)) {
+ &CRT2Index, &resindex)) {
switch(CRT2Index) {
+ case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
+ default:
case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
- case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
- default: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3; break;
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7312,7 +7097,6 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
-
} else {
#endif
@@ -7349,9 +7133,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
@@ -7401,9 +7187,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempbx = SiS_Pr->CVSyncStart;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
@@ -7416,26 +7204,30 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
temp |= (SiS_Pr->CVSyncEnd & 0x0f);
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
#ifdef SIS300
- SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+ SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
#endif
bridgeoffset = 7;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) bridgeoffset += 2;
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) bridgeoffset++;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
+ if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
+ else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
+ /* Higher bridgeoffset shifts to the LEFT */
temp = 0;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
- temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
+ temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+ if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
}
}
temp += bridgeoffset;
@@ -7450,15 +7242,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
}
}
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualLink(SiS_Pr)) {
tempcx >>= 1;
tempbx >>= 1;
tempax >>= 1;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
#endif
+#endif
tempbx += bridgeoffset;
@@ -7480,13 +7274,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncStart;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx <<= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx += bridgeoffset;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
@@ -7501,20 +7298,23 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncEnd;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx <<= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx += bridgeoffset;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
#ifdef SIS300
- SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
+ SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
#endif
#ifdef SIS315H
} /* CRT2-LCD from table */
@@ -7526,11 +7326,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/*********************************************/
static void
-SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT i;
- const UCHAR *tempdi;
+ unsigned short i;
+ const unsigned char *tempdi;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
@@ -7570,7 +7369,7 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
for(i=0; i<=0x3E; i++) {
SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
}
@@ -7587,35 +7386,43 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS315H
+#if 0
static void
-SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
+SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
{
- USHORT temp, temp1, temp2;
+ unsigned short temp, temp1, temp2;
temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
- temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+ temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
- temp = (USHORT)((int)(temp) + shift);
+ temp = (unsigned short)((int)(temp) + shift);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
- temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+ temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
}
+#endif
static void
-SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT temp, temp1, resinfo = 0;
+ unsigned short temp, temp1, resinfo = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
+ if(SiS_Pr->ChipType >= XGI_20) return;
+
+ if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
+ if(!(ROMAddr[0x61] & 0x04)) return;
+ }
+
if(ModeNo > 0x13) {
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
}
@@ -7625,7 +7432,7 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
if(!(temp & 0x01)) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
- if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
+ if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
}
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
@@ -7633,24 +7440,29 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
else temp = 0x0402;
- if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
temp1 = 0;
if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+ if(ModeNo > 0x13) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
+ }
} else {
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
if(temp1 == 0x01) temp |= 0x01;
if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
- if(ModeNo > 0x13) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+ if(ModeNo > 0x13) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+ }
}
- if(HwInfo->jChipType >= SIS_661) { /* ? */
+#if 0
+ if(SiS_Pr->ChipType >= SIS_661) { /* ? */
if(SiS_Pr->SiS_TVMode & TVAspect43) {
if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
if(resinfo == SIS_RI_1024x768) {
@@ -7663,29 +7475,30 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
}
+#endif
+
}
+
}
#endif
static void
-SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT vclkindex;
- USHORT temp, reg1, reg2;
+ unsigned short vclkindex, temp, reg1, reg2;
if(SiS_Pr->UseCustomMode) {
reg1 = SiS_Pr->CSR2B;
reg2 = SiS_Pr->CSR2C;
} else {
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- HwInfo);
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
@@ -7705,11 +7518,35 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
static void
-SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
+{
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if((SiS_CRT2IsLCD(SiS_Pr)) ||
+ (SiS_IsVAMode(SiS_Pr))) {
+ if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
+ }
+ }
+ }
+ }
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+ }
+}
+
+static void
+SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
- ULONG tempebx,tempeax,templong;
+ unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
+ unsigned int tempebx, tempeax, templong;
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -7722,38 +7559,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
}
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+ }
}
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) {
+ if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
}
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
- }
-
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
- }
- }
- return;
+ SiS_SetDualLinkEtc(SiS_Pr);
+ return;
}
}
@@ -7777,16 +7600,16 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
tempbx = SiS_Pr->SiS_VGAHDE;
- if(modeflag & HalfDCLK) tempbx >>= 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
temp = 0;
if(tempbx > 800) temp = 0x60;
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
temp = 0;
- if(tempbx == 1024) temp = 0xA0;
- else if(tempbx > 1024) temp = 0xC0;
+ if(tempbx > 1024) temp = 0xC0;
+ else if(tempbx >= 960) temp = 0xA0;
} else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
temp = 0;
if(tempbx >= 1280) temp = 0x40;
@@ -7796,8 +7619,13 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(tempbx >= 1024) temp = 0xA0;
}
+ temp |= SiS_Pr->Init_P4_0E;
+
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
+ if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+ temp &= 0xf0;
+ temp |= 0x0A;
+ }
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
@@ -7824,15 +7652,15 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempeax /= tempebx;
if(templong) tempeax++;
- temp = (USHORT)(tempeax & 0x000000FF);
+ temp = (unsigned short)(tempeax & 0x000000FF);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
- temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
- temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+ temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
temp |= (tempcx & 0x4F);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
@@ -7840,23 +7668,26 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = 0;
if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
tempax = SiS_Pr->SiS_VGAHDE;
- if(modeflag & HalfDCLK) tempax >>= 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
+ if(modeflag & HalfDCLK) tempax >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
if(tempax > 800) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
tempax -= 800;
- } else { /* 651+301C: Only if TVNoHiviNoYPbPr */
+ } else {
tempbx = 0x08;
- if(tempax == 1024) tempax *= 25;
- else tempax *= 20;
+ if(tempax == 960) tempax *= 25; /* Correct */
+ else if(tempax == 1024) tempax *= 25;
+ else tempax *= 20;
temp = tempax % 32;
tempax /= 32;
if(temp) tempax++;
tempax++;
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
- (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
- if(resinfo == SIS_RI_1024x768) {
- /* Otherwise white line at right edge */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(resinfo == SIS_RI_1024x768 ||
+ resinfo == SIS_RI_1024x576 ||
+ resinfo == SIS_RI_1280x1024 ||
+ resinfo == SIS_RI_1280x720) {
+ /* Otherwise white line or garbage at right edge */
tempax = (tempax & 0xff00) | 0x20;
}
}
@@ -7868,7 +7699,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
temp = 0x0036; tempbx = 0xD0;
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -7884,36 +7715,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
tempbx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx -= 2;
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
temp = (tempbx >> 5) & 0x38;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
/* LCD-too-dark-error-source, see FinalizeLCD() */
}
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
- }
}
+ SiS_SetDualLinkEtc(SiS_Pr);
+
} /* 301B */
- SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
/*********************************************/
@@ -7921,8 +7740,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
@@ -7930,7 +7748,7 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_ModeType == ModeVGA) {
if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
- SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
}
}
}
@@ -7939,116 +7757,156 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* MODIFY CRT1 GROUP FOR SLAVE MODE */
/*********************************************/
-static void
-SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
- USHORT tempah,i,modeflag,j;
- USHORT ResIndex,DisplayType;
- const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
+static BOOLEAN
+SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
+ unsigned short *DisplayType)
+ {
+ unsigned short modeflag = 0;
+ BOOLEAN checkhd = TRUE;
- if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ /* Pass 1:1 not supported here */
+
+ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+
+ (*ResIndex) &= 0x3F;
+
+ if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+ (*DisplayType) = 80;
+ if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+ (*DisplayType) = 82;
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
+ }
+ }
+ if((*DisplayType) != 84) {
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+ }
+
+ } else {
+
+ (*DisplayType = 0);
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1: (*DisplayType) = 50;
+ checkhd = FALSE;
+ break;
+ case Panel_320x240_2: (*DisplayType) = 14;
+ break;
+ case Panel_320x240_3: (*DisplayType) = 18;
+ break;
+ case Panel_640x480: (*DisplayType) = 10;
+ break;
+ case Panel_1024x600: (*DisplayType) = 26;
+ break;
+ default: return TRUE;
+ }
+
+ if(checkhd) {
+ if(modeflag & HalfDCLK) (*DisplayType)++;
+ }
+
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
+ }
+
+ }
+
+ return TRUE;
+}
+
+static void
+SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
+ const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
+ static const unsigned short CRIdx[] = {
+ 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x10, 0x11, 0x15, 0x16
+ };
if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848))
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
return;
+ if(SiS_Pr->SiS_IF_DEF_LVDS) {
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+ } else return;
+
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+ }
+
if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
&ResIndex, &DisplayType))) {
return;
}
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+ switch(DisplayType) {
+ case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
+ case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
+ case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
+ case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
+ case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
+ case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
+ case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
+#if 0 /* Works better with calculated numbers */
+ case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
+ case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
+ case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
+ case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
+#endif
+ case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
+ case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
+ case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
+ case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
+ case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
}
- switch(DisplayType) {
- case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break;
- case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break;
- case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break;
- case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break;
- case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
- case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break;
- case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break;
- case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; break;
- case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break;
- case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break;
- case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break;
- case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H; break;
- case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1; break;
- case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H; break;
- case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1; break;
- case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H; break;
- case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2; break;
- case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H; break;
- case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
- case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
- case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
- case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
- case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1; break; /* FSTN */
- case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
- case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
- case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
- case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
- case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1; break;
- case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H; break;
- case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2; break;
- case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H; break;
- case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1; break;
- case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H; break;
- case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2; break;
- case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H; break;
- case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1; break;
- case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H; break;
- case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2; break;
- case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H; break;
- case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
- case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
- case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2; break;
- case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H; break;
- case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3; break;
- case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H; break;
- case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
- default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
- }
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
-
- for(i=0x02,j=1;i<=0x05;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x06,j=5;i<=0x07;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x10,j=7;i<=0x11;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x15,j=9;i<=0x16;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x0A,j=11;i<=0x0C;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
- }
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
- tempah &= 0xE0;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
- tempah &= 0x01;
- tempah <<= 5;
- if(modeflag & DoubleScanMode) tempah |= 0x080;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+ if(LVDSCRT1Ptr) {
+
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0; i <= 10; i++) {
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
+ }
+
+ for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
+ }
+
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
+
+ if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) tempah |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+
+ } else {
+
+ SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
+
+ }
}
/*********************************************/
@@ -8056,24 +7914,24 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT clkbase, vclkindex=0;
- UCHAR sr2b, sr2c;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short clkbase, vclkindex = 0;
+ unsigned char sr2b, sr2c;
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
- if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
- RefreshRateTableIndex--;
- }
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
- RefreshRateTableIndex, HwInfo);
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+ if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
+ RefreshRateTableIndex--;
+ }
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
} else {
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
- RefreshRateTableIndex, HwInfo);
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
}
sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
@@ -8082,7 +7940,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x01) {
- sr2b = ROMAddr[0x227];
+ sr2b = ROMAddr[0x227];
sr2c = ROMAddr[0x228];
}
}
@@ -8091,7 +7949,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
clkbase = 0x02B;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- clkbase += 3;
+ clkbase += 3;
}
}
@@ -8111,368 +7969,331 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex)
+SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
-#if defined(SIS300) || defined(SIS315H)
- USHORT temp, tempbx;
-#endif
- USHORT tempcl;
- USHORT TVType, resindex;
- const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
+ unsigned short TVType, resindex;
+ const struct SiS_CHTVRegData *CHTVRegData = NULL;
- if(ModeNo <= 0x13)
- tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- else
- tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ if(ModeNo <= 0x13)
+ resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ else
+ resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- TVType = 0;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- TVType += 2;
- if(SiS_Pr->SiS_ModeType > ModeVGA) {
- if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
- }
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- TVType = 4;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- TVType = 6;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- }
- }
- switch(TVType) {
- case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
- case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
- case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
- case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
- case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
- case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
- case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
- case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
- case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
- default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
- }
- resindex = tempcl & 0x3F;
+ resindex &= 0x3F;
+
+ TVType = 0;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ TVType += 2;
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
+ }
+ if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+ TVType = 4;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+ TVType = 6;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ }
+ }
+
+ switch(TVType) {
+ case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+ case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+ case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
+ case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
+ case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+ case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+ case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+ case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+ case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+ default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
+ }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
#ifdef SIS300
- /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
+ /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
- /* We don't support modes >800x600 */
- if (resindex > 5) return;
+ /* We don't support modes >800x600 */
+ if (resindex > 5) return;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- SiS_SetCH700x(SiS_Pr,0x4304); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
- SiS_SetCH700x(SiS_Pr,0x6909); /* Black level for PAL (105)*/
- } else {
- SiS_SetCH700x(SiS_Pr,0x0304); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
- SiS_SetCH700x(SiS_Pr,0x7109); /* Black level for NTSC (113)*/
- }
-
- temp = CHTVRegData[resindex].Reg[0];
- tempbx=((temp&0x00FF)<<8)|0x00; /* Mode register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[1];
- tempbx=((temp&0x00FF)<<8)|0x07; /* Start active video register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[2];
- tempbx=((temp&0x00FF)<<8)|0x08; /* Position overflow register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[3];
- tempbx=((temp&0x00FF)<<8)|0x0A; /* Horiz Position register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[4];
- tempbx=((temp&0x00FF)<<8)|0x0B; /* Vertical Position register */
- SiS_SetCH700x(SiS_Pr,tempbx);
-
- /* Set minimum flicker filter for Luma channel (SR1-0=00),
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
+ SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
+ } else {
+ SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
+ SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
+ }
+
+ SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
+ SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
+ SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
+ SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
+ SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
+
+ /* Set minimum flicker filter for Luma channel (SR1-0=00),
minimum text enhancement (S3-2=10),
maximum flicker filter for Chroma channel (S5-4=10)
=00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
- */
- SiS_SetCH700x(SiS_Pr,0x2801);
+ */
+ SiS_SetCH700x(SiS_Pr,0x01,0x28);
- /* Set video bandwidth
+ /* Set video bandwidth
High bandwith Luma composite video filter(S0=1)
low bandwith Luma S-video filter (S2-1=00)
disable peak filter in S-video channel (S3=0)
high bandwidth Chroma Filter (S5-4=11)
=00110001=0x31
- */
- SiS_SetCH700x(SiS_Pr,0xb103); /* old: 3103 */
+ */
+ SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
- /* Register 0x3D does not exist in non-macrovision register map
+ /* Register 0x3D does not exist in non-macrovision register map
(Maybe this is a macrovision register?)
- */
+ */
#ifndef SIS_CP
- SiS_SetCH70xx(SiS_Pr,0x003D);
+ SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
#endif
- /* Register 0x10 only contains 1 writable bit (S0) for sensing,
- all other bits a read-only. Macrovision?
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
+ /* Register 0x10 only contains 1 writable bit (S0) for sensing,
+ all other bits a read-only. Macrovision?
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
- /* Register 0x11 only contains 3 writable bits (S0-S2) for
- contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
+ /* Register 0x11 only contains 3 writable bits (S0-S2) for
+ contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
- /* Clear DSEN
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
-
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
- if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on, no need to set FSCI */
- } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF); /* Loop filter on for mode 23 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */
- }
- } else {
- if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
- } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
+ /* Clear DSEN
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
+
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
+ if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
+ } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
+ }
+ } else {
+ if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+ } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
#if 0
- SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0); /* FSCI for mode 24 is 428,554,851 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0); /* 198b3a63 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off for mode 24 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */
-#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
+#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+ }
}
- }
- } else { /* ---- PAL ---- */
- /* We don't play around with FSCI in PAL mode */
+ } else { /* ---- PAL ---- */
+ /* We don't play around with FSCI in PAL mode */
if(resindex == 0x04) {
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
} else {
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
}
- }
-
+ }
+
#endif /* 300 */
- } else {
+ } else {
- /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
+ /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
#ifdef SIS315H
- /* We don't support modes >1024x768 */
- if (resindex > 6) return;
-
- temp = CHTVRegData[resindex].Reg[0];
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- temp |= 0x10;
- }
- tempbx=((temp & 0x00FF) << 8) | 0x00;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[1];
- tempbx=((temp & 0x00FF) << 8) | 0x01;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[2];
- tempbx=((temp & 0x00FF) << 8) | 0x02;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[3];
- tempbx=((temp & 0x00FF) << 8) | 0x04;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[4];
- tempbx=((temp & 0x00FF) << 8) | 0x03;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[5];
- tempbx=((temp & 0x00FF) << 8) | 0x05;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[6];
- tempbx=((temp & 0x00FF) << 8) | 0x06;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[7];
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- temp = 0x66;
- }
- tempbx=((temp & 0x00FF) << 8) | 0x07;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[8];
- tempbx=((temp & 0x00FF) << 8) | 0x08;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[9];
- tempbx=((temp & 0x00FF) << 8) | 0x15;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[10];
- tempbx=((temp & 0x00FF) << 8) | 0x1f;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[11];
- tempbx=((temp & 0x00FF) << 8) | 0x0c;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[12];
- tempbx=((temp & 0x00FF) << 8) | 0x0d;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[13];
- tempbx=((temp & 0x00FF) << 8) | 0x0e;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[14];
- tempbx=((temp & 0x00FF) << 8) | 0x0f;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[15];
- tempbx=((temp & 0x00FF) << 8) | 0x10;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
- /* D1 should be set for PAL, PAL-N and NTSC-J,
- but I won't do that for PAL unless somebody
- tells me to do so. Since the BIOS uses
- non-default CIV values and blacklevels,
- this might be compensated anyway.
- */
- if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
- SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21));
+ unsigned short temp;
+
+ /* We don't support modes >1024x768 */
+ if (resindex > 6) return;
+
+ temp = CHTVRegData[resindex].Reg[0];
+ if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
+ SiS_SetCH701x(SiS_Pr,0x00,temp);
+
+ SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
+ SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
+ SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
+ SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
+ SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
+ SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
+
+ temp = CHTVRegData[resindex].Reg[7];
+ if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
+ SiS_SetCH701x(SiS_Pr,0x07,temp);
+
+ SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
+ SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
+ SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
+ SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
+ SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
+ SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
+ SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
+ SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
+
+ temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
+ /* D1 should be set for PAL, PAL-N and NTSC-J,
+ but I won't do that for PAL unless somebody
+ tells me to do so. Since the BIOS uses
+ non-default CIV values and blacklevels,
+ this might be compensated anyway.
+ */
+ if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
+ SiS_SetCH701x(SiS_Pr,0x21,temp);
#endif /* 315 */
- }
+ }
#ifdef SIS_CP
- SIS_CP_INIT301_CP3
+ SIS_CP_INIT301_CP3
#endif
}
+#ifdef SIS315H /* ----------- 315 series only ---------- */
+
void
-SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- /* Enable Chrontel 7019 LCD panel backlight */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
- SiS_SetCH701x(SiS_Pr,0x6566);
- } else {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
- temp |= 0x20;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- }
- }
+ /* Enable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_SetCH701x(SiS_Pr,0x66,0x65);
+ } else {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp |= 0x20;
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ }
+ }
}
void
-SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr)
+SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- /* Disable Chrontel 7019 LCD panel backlight */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
- temp &= 0xDF;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- }
+ /* Disable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp &= 0xDF;
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ }
}
-#ifdef SIS315H /* ----------- 315 series only ---------- */
-
static void
-SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
- UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
- UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
- UCHAR asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
- UCHAR asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
- UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
- UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
- UCHAR *tableptr = NULL;
+SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
+{
+ static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
+ static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
+ static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
+ static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+ static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+ static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+ static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+ const unsigned char *tableptr = NULL;
int i;
/* Set up Power up/down timing */
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
- else tableptr = table1024_740;
+ if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
+ else tableptr = table1024_740;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
else tableptr = table1400_740;
} else return;
} else {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- tableptr = table1024_650;
+ tableptr = table1024_650;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
- tableptr = table1400_650;
+ tableptr = table1400_650;
} else return;
}
for(i=0; i<5; i++) {
- SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+ SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
}
}
static void
-SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
- 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
- UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
- 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
- UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
- 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
- UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
- UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
- 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
- UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
- UCHAR *tableptr = NULL;
- USHORT tempbh;
+SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
+{
+ const unsigned char *tableptr = NULL;
+ unsigned short tempbh;
int i;
+ static const unsigned char regtable[] = {
+ 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+ 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
+ };
+ static const unsigned char table1024_740[] = {
+ 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+ 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1280_740[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1400_740[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1600_740[] = {
+ 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
+ };
+ static const unsigned char table1024_650[] = {
+ 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+ 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
+ };
+ static const unsigned char table1280_650[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
+ };
+ static const unsigned char table1400_650[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
+ 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
+ };
+ static const unsigned char table1600_650[] = {
+ 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
+ };
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
@@ -8499,138 +8320,139 @@ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
}
- if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
- else tempbh = 0x0c;
+ if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
+ else tempbh = 0x0c;
for(i = 0; i < tempbh; i++) {
- SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+ SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
}
- SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo);
+ SiS_ChrontelPowerSequencing(SiS_Pr);
tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
tempbh |= 0xc0;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
+ SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
tempbh &= 0xfb;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
tempbh = SiS_GetCH701x(SiS_Pr,0x64);
tempbh |= 0x40;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
+ SiS_SetCH701x(SiS_Pr,0x64,tempbh);
tempbh = SiS_GetCH701x(SiS_Pr,0x03);
tempbh &= 0x3f;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,tempbh);
}
}
static void
-SiS_ChrontelResetVSync(SiS_Private *SiS_Pr)
+SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
{
unsigned char temp, temp1;
temp1 = SiS_GetCH701x(SiS_Pr,0x49);
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x7f; /* Use external VSYNC */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_LongDelay(SiS_Pr,3);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_LongDelay(SiS_Pr, 3);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80; /* Use internal VSYNC */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_SetCH701x(SiS_Pr,0x49,temp1);
}
static void
-SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x1c);
temp |= 0x04; /* Invert XCLK phase */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,temp);
}
- if(SiS_IsYPbPr(SiS_Pr, HwInfo)) {
+ if(SiS_IsYPbPr(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x01);
temp &= 0x3f;
temp |= 0x80; /* Enable YPrPb (HDTV) */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ SiS_SetCH701x(SiS_Pr,0x01,temp);
}
- if(SiS_IsChScart(SiS_Pr, HwInfo)) {
+ if(SiS_IsChScart(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x01);
temp &= 0x3f;
temp |= 0xc0; /* Enable SCART + CVBS */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ SiS_SetCH701x(SiS_Pr,0x01,temp);
}
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_ChrontelResetVSync(SiS_Pr);
- SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
+ SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
} else {
- SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
+ SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
temp = SiS_GetCH701x(SiS_Pr,0x49);
- if(SiS_IsYPbPr(SiS_Pr,HwInfo)) {
+ if(SiS_IsYPbPr(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x73);
temp |= 0x60;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
+ SiS_SetCH701x(SiS_Pr,0x73,temp);
}
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x7f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_LongDelay(SiS_Pr,2);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
}
}
}
static void
-SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
/* Complete power down of LVDS */
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
- SiS_LongDelay(SiS_Pr,1);
- SiS_GenericDelay(SiS_Pr,0x16ff);
- SiS_SetCH701x(SiS_Pr,0xac76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_GenericDelay(SiS_Pr, 5887);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
} else {
- SiS_LongDelay(SiS_Pr,2);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfc;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
}
}
}
static void
-SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
temp &= 0x01;
if(!temp) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x49);
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
}
+
/* Reset Chrontel 7019 datapath */
- SiS_SetCH701x(SiS_Pr,0x1048);
- SiS_LongDelay(SiS_Pr,1);
- SiS_SetCH701x(SiS_Pr,0x1848);
+ SiS_SetCH701x(SiS_Pr,0x48,0x10);
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_SetCH701x(SiS_Pr,0x48,0x18);
- if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
SiS_ChrontelResetVSync(SiS_Pr);
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
+ SiS_SetCH701x(SiS_Pr,0x49,temp);
}
} else {
@@ -8638,72 +8460,72 @@ SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* Clear/set/clear GPIO */
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp &= 0xef;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp |= 0x10;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp &= 0xef;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(!temp) {
- SiS_SetCH701xForLCD(SiS_Pr, HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
}
}
} else { /* 650 */
/* Reset Chrontel 7019 datapath */
- SiS_SetCH701x(SiS_Pr,0x1048);
- SiS_LongDelay(SiS_Pr,1);
- SiS_SetCH701x(SiS_Pr,0x1848);
+ SiS_SetCH701x(SiS_Pr,0x48,0x10);
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_SetCH701x(SiS_Pr,0x48,0x18);
}
}
static void
-SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
SiS_ChrontelResetVSync(SiS_Pr);
}
} else {
- SiS_SetCH701x(SiS_Pr,0xaf76); /* Power up LVDS block */
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
temp = SiS_GetCH701x(SiS_Pr,0x49);
temp &= 1;
if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x70;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* enable VSYNC */
- SiS_LongDelay(SiS_Pr,3);
+ SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
+ SiS_LongDelay(SiS_Pr, 3);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* disable VSYNC */
+ SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
}
}
}
static void
-SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp,temp1;
+ unsigned short temp,temp1;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 1) {
temp++;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+ SiS_SetCH701x(SiS_Pr,0x61,temp);
}
- SiS_SetCH701x(SiS_Pr,0x4566); /* Panel power on */
- SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on */
- SiS_LongDelay(SiS_Pr,1);
- SiS_GenericDelay(SiS_Pr,0x16ff);
+ SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_GenericDelay(SiS_Pr, 5887);
} else { /* 650 */
@@ -8711,38 +8533,38 @@ SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 2) {
temp++;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+ SiS_SetCH701x(SiS_Pr,0x61,temp);
temp1 = 1;
}
- SiS_SetCH701x(SiS_Pr,0xac76);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
temp = SiS_GetCH701x(SiS_Pr,0x66);
temp |= 0x5f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
if(ModeNo > 0x13) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
- SiS_GenericDelay(SiS_Pr,0x3ff);
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+ SiS_GenericDelay(SiS_Pr, 1023);
} else {
- SiS_GenericDelay(SiS_Pr,0x2ff);
+ SiS_GenericDelay(SiS_Pr, 767);
}
} else {
if(!temp1)
- SiS_GenericDelay(SiS_Pr,0x2ff);
+ SiS_GenericDelay(SiS_Pr, 767);
}
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp |= 0x03;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
temp = SiS_GetCH701x(SiS_Pr,0x66);
temp &= 0x7f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- SiS_LongDelay(SiS_Pr,1);
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ SiS_LongDelay(SiS_Pr, 1);
}
}
static void
-SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
{
- USHORT temp,tempcl,tempch;
+ unsigned short temp,tempcl,tempch;
SiS_LongDelay(SiS_Pr, 1);
tempcl = 3;
@@ -8753,87 +8575,87 @@ SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
temp &= 0x04; /* PLL stable? -> bail out */
if(temp == 0x04) break;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
/* Power down LVDS output, PLL normal operation */
- SiS_SetCH701x(SiS_Pr,0xac76);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
}
- SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
if(tempcl == 0) {
if(tempch == 3) break;
- SiS_ChrontelResetDB(SiS_Pr,HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
tempcl = 3;
tempch++;
}
tempcl--;
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfb; /* Reset PLL */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- SiS_LongDelay(SiS_Pr,2);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp |= 0x04; /* PLL normal operation */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- if(HwInfo->jChipType == SIS_740) {
- SiS_SetCH701x(SiS_Pr,0xe078); /* PLL loop filter */
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
} else {
- SiS_SetCH701x(SiS_Pr,0x6078);
+ SiS_SetCH701x(SiS_Pr,0x78,0x60);
}
- SiS_LongDelay(SiS_Pr,2);
+ SiS_LongDelay(SiS_Pr, 2);
} while(0);
- SiS_SetCH701x(SiS_Pr,0x0077); /* MV? */
+ SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
}
static void
-SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
temp = SiS_GetCH701x(SiS_Pr,0x03);
temp |= 0x80; /* Set datapath 1 to TV */
temp &= 0xbf; /* Set datapath 2 to LVDS */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,temp);
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x1c);
temp &= 0xfb; /* Normal XCLK phase */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
temp = SiS_GetCH701x(SiS_Pr,0x64);
temp |= 0x40; /* ? Bit not defined */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
+ SiS_SetCH701x(SiS_Pr,0x64,temp);
temp = SiS_GetCH701x(SiS_Pr,0x03);
temp &= 0x3f; /* D1 input to both LVDS and TV */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,temp);
if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
- SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */
+ SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
SiS_LongDelay(SiS_Pr, 1);
- SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */
- SiS_ChrontelResetDB(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+ SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
+ SiS_ChrontelDoSomething3(SiS_Pr, 0);
} else {
temp = SiS_GetCH701x(SiS_Pr,0x66);
if(temp != 0x45) {
- SiS_ChrontelResetDB(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
+ SiS_ChrontelDoSomething3(SiS_Pr, 0);
}
}
} else { /* 650 */
- SiS_ChrontelResetDB(SiS_Pr,HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr,HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
- SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo);
- SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on, LVDS normal operation */
+ SiS_ChrontelDoSomething3(SiS_Pr,temp);
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
}
@@ -8845,15 +8667,12 @@ SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
BOOLEAN
-SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
#ifdef SIS300
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
-#endif
- USHORT ModeIdIndex, RefreshRateTableIndex;
-#if 0
- USHORT temp;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
#endif
+ unsigned short ModeIdIndex, RefreshRateTableIndex;
SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
@@ -8866,37 +8685,37 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/* Used for shifting CR33 */
SiS_Pr->SiS_SelectCRT2Rate = 4;
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
- RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
SiS_SaveCRT2Info(SiS_Pr,ModeNo);
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_DisableBridge(SiS_Pr,HwInfo);
- if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) {
+ SiS_DisableBridge(SiS_Pr);
+ if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
}
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- SiS_LockCRT2(SiS_Pr, HwInfo);
+ SiS_LockCRT2(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
return TRUE;
}
- SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
/* Set up Panel Link for LVDS and LCDA */
SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
- ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
- SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
+ SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
@@ -8907,86 +8726,79 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
#endif
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#ifdef SIS315H
- SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#endif
- SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#ifdef SIS315H
- SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
#endif
- SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
- SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
- /* For 301BDH (Panel link initialization): */
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
- if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- }
- }
- }
- SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- }
- }
+ /* For 301BDH (Panel link initialization): */
+ if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+
+ if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
+ SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
} else {
- SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
- }
+ SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
+ SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
#ifdef SIS315H
- SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
#endif
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- }
- }
- }
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+ }
+ }
+ }
}
#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
if(SiS_Pr->SiS_UseOEM) {
if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
- RefreshRateTableIndex);
+ SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else {
- SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
- RefreshRateTableIndex);
+ SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
}
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex);
+ SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
}
SiS_DisplayOn(SiS_Pr);
}
@@ -8995,21 +8807,21 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
#endif
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(HwInfo->jChipType < SIS_661) {
- SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ if(SiS_Pr->ChipType < SIS_661) {
+ SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else {
- SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
}
}
#endif
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_EnableBridge(SiS_Pr, HwInfo);
+ SiS_EnableBridge(SiS_Pr);
}
SiS_DisplayOn(SiS_Pr);
@@ -9017,15 +8829,15 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
/* Disable LCD panel when using TV */
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
} else {
/* Disable TV when using LCD */
- SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
}
}
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_LockCRT2(SiS_Pr,HwInfo);
+ SiS_LockCRT2(SiS_Pr);
}
return TRUE;
@@ -9037,13 +8849,13 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
void
-SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
{
/* Switch on LCD backlight on SiS30xLV */
SiS_DDC2Delay(SiS_Pr,0xff00);
if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
}
if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
@@ -9051,12 +8863,11 @@ SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
void
-SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
{
/* Switch off LCD backlight on SiS30xLV */
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- SiS_DDC2Delay(SiS_Pr,0xe000);
+ SiS_DDC2Delay(SiS_Pr,0xff00);
}
/*********************************************/
@@ -9064,7 +8875,7 @@ SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetupDDCN(SiS_Private *SiS_Pr)
+SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
{
SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
@@ -9075,12 +8886,12 @@ SiS_SetupDDCN(SiS_Private *SiS_Pr)
}
#ifdef SIS300
-static UCHAR *
-SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+static unsigned char *
+SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
{
int i, j, num;
- USHORT tempah,temp;
- UCHAR *mydataptr;
+ unsigned short tempah,temp;
+ unsigned char *mydataptr;
for(i=0; i<20; i++) { /* Do 20 attempts to write */
mydataptr = dataptr;
@@ -9088,7 +8899,7 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
if(!num) return mydataptr;
if(i) {
SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
}
if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
tempah = SiS_Pr->SiS_DDC_DeviceAddr;
@@ -9110,12 +8921,12 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
}
static BOOLEAN
-SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
{
SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
SiS_SetSwitchDDC2(SiS_Pr);
@@ -9124,9 +8935,11 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
if(!dataptr) return FALSE;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
#endif
+#endif
return TRUE;
}
#endif
@@ -9139,155 +8952,121 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
*/
static BOOLEAN
-SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor)
+SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
{
- USHORT tempah,temp,i;
+ unsigned short temp, i;
for(i=0; i<20; i++) { /* Do 20 attempts to write */
if(i) {
- SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
- }
- if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = tempbx & 0x00FF; /* Write RAB */
- tempah |= myor; /* (700x: set bit 7, see datasheet) */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
- if(temp) continue; /* (ERROR: no ack) */
- tempah = (tempbx & 0xFF00) >> 8;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */
- if(temp) continue; /* (ERROR: no ack) */
- if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
+ SiS_SetStop(SiS_Pr);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+ }
+ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
+ if(temp) continue; /* (ERROR: no ack) */
+ if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
SiS_Pr->SiS_ChrontelInit = 1;
return TRUE;
}
return FALSE;
}
-#if 0
-#ifdef SIS300
-/* Write Trumpion register */
-static void
-SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
- SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
- SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
- SiS_SetupDDCN(SiS_Pr);
- SiS_SetChReg(SiS_Pr, tempbx, 0);
-}
-#endif
-#endif
-
/* Write to Chrontel 700x */
-/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
void
-SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
if(!(SiS_Pr->SiS_ChrontelInit)) {
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
}
- if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
+ if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
(!(SiS_Pr->SiS_ChrontelInit)) ) {
- SiS_Pr->SiS_DDC_Index = 0x0a; /* Bit 7 = SC; Bit 6 = SD */
- SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Index = 0x0a;
+ SiS_Pr->SiS_DDC_Data = 0x80;
+ SiS_Pr->SiS_DDC_Clk = 0x40;
SiS_SetupDDCN(SiS_Pr);
- SiS_SetChReg(SiS_Pr, tempbx, 0x80);
+ SiS_SetChReg(SiS_Pr, reg, val, 0x80);
}
}
/* Write to Chrontel 701x */
/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
void
-SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
- SiS_SetChReg(SiS_Pr, tempbx, 0);
+ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+ SiS_SetChReg(SiS_Pr, reg, val, 0);
}
-static void
-SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
- SiS_SetCH700x(SiS_Pr,tempbx);
+ SiS_SetCH700x(SiS_Pr, reg, val);
else
- SiS_SetCH701x(SiS_Pr,tempbx);
+ SiS_SetCH701x(SiS_Pr, reg, val);
}
-static USHORT
-SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor)
+static unsigned short
+SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
{
- USHORT tempah,temp,i;
+ unsigned short tempah, temp, i;
for(i=0; i<20; i++) { /* Do 20 attempts to read */
if(i) {
- SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
- }
- if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = SiS_Pr->SiS_DDC_ReadAddr | myor; /* Write RAB (700x: | 0x80) */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
- if(temp) continue; /* (ERROR: no ack) */
- if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
- if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
+ SiS_SetStop(SiS_Pr);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+ }
+ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
+ if(temp) continue; /* (ERROR: no ack) */
+ if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
+ if(temp) continue; /* (ERROR: no ack) */
+ tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
+ if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
SiS_Pr->SiS_ChrontelInit = 1;
- return(tempah);
+ return tempah;
}
return 0xFFFF;
}
-#if 0
-#ifdef SIS300
-/* Read from Trumpion */
-static USHORT
-SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
- SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB */
- SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
- SiS_SetupDDCN(SiS_Pr);
- SiS_Pr->SiS_DDC_ReadAddr = tempbx;
- return(SiS_GetChReg(SiS_Pr,0));
-}
-#endif
-#endif
-
/* Read from Chrontel 700x */
/* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
- USHORT result;
+ unsigned short result;
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
if(!(SiS_Pr->SiS_ChrontelInit)) {
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
}
@@ -9303,52 +9082,69 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
result = SiS_GetChReg(SiS_Pr,0x80);
}
- return(result);
+ return result;
}
/* Read from Chrontel 701x */
/* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
SiS_Pr->SiS_DDC_ReadAddr = tempbx;
- return(SiS_GetChReg(SiS_Pr,0));
+ return SiS_GetChReg(SiS_Pr,0);
}
/* Read from Chrontel 70xx */
/* Parameter is [Register no (S7-S0)] */
-static USHORT
-SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+unsigned short
+SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
- return(SiS_GetCH700x(SiS_Pr, tempbx));
+ return SiS_GetCH700x(SiS_Pr, tempbx);
else
- return(SiS_GetCH701x(SiS_Pr, tempbx));
+ return SiS_GetCH701x(SiS_Pr, tempbx);
+}
+
+void
+SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char myor, unsigned short myand)
+{
+ unsigned short tempbl;
+
+ tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
+ SiS_SetCH70xx(SiS_Pr, reg, tempbl);
}
/* Our own DDC functions */
-static USHORT
-SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
+ unsigned int VBFlags2)
{
unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
unsigned char flag, cr32;
- USHORT temp = 0, myadaptnum = adaptnum;
+ unsigned short temp = 0, myadaptnum = adaptnum;
if(adaptnum != 0) {
- if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF;
- if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
- }
-
+ if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
+ if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
+ }
+
/* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
-
+
SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
SiS_Pr->SiS_DDC_SecAddr = 0;
@@ -9360,7 +9156,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
#if 0
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
if(myadaptnum == 0) {
if(!(cr32 & 0x20)) {
myadaptnum = 2;
@@ -9376,20 +9172,20 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
#endif
if(VGAEngine == SIS_300_VGA) { /* 300 series */
-
+
if(myadaptnum != 0) {
flag = 0;
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
SiS_Pr->SiS_DDC_Index = 0x0f;
}
}
- if(!(VBFlags & VB_301)) {
+ if(!(VBFlags2 & VB2_301)) {
if((cr32 & 0x80) && (checkcr32)) {
if(myadaptnum >= 1) {
if(!(cr32 & 0x08)) {
- myadaptnum = 1;
+ myadaptnum = 1;
if(!(cr32 & 0x10)) return 0xFFFF;
}
}
@@ -9401,17 +9197,17 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
} else { /* 315/330 series */
- /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
+ /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
if(myadaptnum == 2) {
myadaptnum = 1;
- }
+ }
}
if(myadaptnum == 1) {
- flag = 0;
- if(VBFlags & VB_SISBRIDGE) {
+ flag = 0;
+ if(VBFlags2 & VB2_SISBRIDGE) {
SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
SiS_Pr->SiS_DDC_Index = 0x0f;
}
@@ -9429,93 +9225,96 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
temp = myadaptnum;
if(myadaptnum == 1) {
temp = 0;
- if(VBFlags & VB_LVDS) flag = 0xff;
+ if(VBFlags2 & VB2_LVDS) flag = 0xff;
}
if(flag) temp = 0;
}
-
+
SiS_Pr->SiS_DDC_Data = 0x02 << temp;
SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
SiS_SetupDDCN(SiS_Pr);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
#endif
-
+#endif
return 0;
}
-static USHORT
-SiS_WriteDABDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
- return 0xFFFF;
+ return 0xFFFF;
}
if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
- return 0xFFFF;
+ return 0xFFFF;
}
- return(0);
+ return 0;
}
-static USHORT
-SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
- return 0xFFFF;
+ return 0xFFFF;
}
- return(0);
+ return 0;
}
-static USHORT
-SiS_PrepareDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
- if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr));
- return(0);
+ if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
+ return 0;
}
static void
-SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno)
+SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
{
SiS_SetSCLKLow(SiS_Pr);
if(yesno) {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
SiS_Pr->SiS_DDC_Data);
} else {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
0);
}
SiS_SetSCLKHigh(SiS_Pr);
}
-static USHORT
-SiS_DoProbeDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
{
unsigned char mask, value;
- USHORT temp, ret=0;
+ unsigned short temp, ret=0;
BOOLEAN failed = FALSE;
SiS_SetSwitchDDC2(SiS_Pr);
if(SiS_PrepareDDC(SiS_Pr)) {
SiS_SetStop(SiS_Pr);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
#endif
- return(0xFFFF);
+#endif
+ return 0xFFFF;
}
mask = 0xf0;
value = 0x20;
if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
- temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
SiS_SendACK(SiS_Pr, 0);
if(temp == 0) {
mask = 0xff;
@@ -9523,34 +9322,41 @@ SiS_DoProbeDDC(SiS_Private *SiS_Pr)
} else {
failed = TRUE;
ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
#endif
+#endif
}
}
if(failed == FALSE) {
- temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
SiS_SendACK(SiS_Pr, 1);
temp &= mask;
if(temp == value) ret = 0;
else {
ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
#endif
+#endif
if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
if(temp == 0x30) ret = 0;
}
}
}
SiS_SetStop(SiS_Pr);
- return(ret);
+ return ret;
}
-static USHORT
-SiS_ProbeDDC(SiS_Private *SiS_Pr)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
flag = 0x180;
SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
@@ -9560,16 +9366,19 @@ SiS_ProbeDDC(SiS_Private *SiS_Pr)
SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
if(!(flag & 0x1a)) flag = 0;
- return(flag);
+ return flag;
}
-static USHORT
-SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
{
- USHORT flag, length, i;
+ unsigned short flag, length, i;
unsigned char chksum,gotcha;
- if(DDCdatatype > 4) return 0xFFFF;
+ if(DDCdatatype > 4) return 0xFFFF;
flag = 0;
SiS_SetSwitchDDC2(SiS_Pr);
@@ -9579,21 +9388,21 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
chksum = 0;
gotcha = 0;
for(i=0; i<length; i++) {
- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
chksum += buffer[i];
gotcha |= buffer[i];
SiS_SendACK(SiS_Pr, 0);
}
- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
chksum += buffer[i];
SiS_SendACK(SiS_Pr, 1);
- if(gotcha) flag = (USHORT)chksum;
+ if(gotcha) flag = (unsigned short)chksum;
else flag = 0xFFFF;
} else {
flag = 0xFFFF;
}
SiS_SetStop(SiS_Pr);
- return(flag);
+ return flag;
}
/* Our private DDC functions
@@ -9617,17 +9426,25 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
if DDCdatatype = 0: Returns supported DDC modes
*/
-USHORT
-SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
+unsigned short
+SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+ unsigned int VBFlags2)
{
- unsigned char sr1f,cr17=1;
- USHORT result;
+ unsigned char sr1f, cr17=1;
+ unsigned short result;
- if(adaptnum > 2) return 0xFFFF;
- if(DDCdatatype > 4) return 0xFFFF;
- if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
- if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF;
+ if(adaptnum > 2)
+ return 0xFFFF;
+
+ if(DDCdatatype > 4)
+ return 0xFFFF;
+
+ if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
+ return 0xFFFF;
+
+ if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
+ return 0xFFFF;
sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
@@ -9656,10 +9473,12 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
(buffer[4] == 0xff) && (buffer[5] == 0xff) &&
(buffer[6] == 0xff) && (buffer[7] == 0x00) &&
(buffer[0x12] == 1)) {
- if(adaptnum == 1) {
- if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
- } else {
- if(buffer[0x14] & 0x80) result = 0xFFFE;
+ if(!SiS_Pr->DDCPortMixup) {
+ if(adaptnum == 1) {
+ if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
+ } else {
+ if(buffer[0x14] & 0x80) result = 0xFFFE;
+ }
}
}
}
@@ -9671,832 +9490,10 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
return result;
}
-#ifdef LINUX_XF86
-
-static BOOLEAN
-checkedid1(unsigned char *buffer)
-{
- /* Check header */
- if((buffer[0] != 0x00) ||
- (buffer[1] != 0xff) ||
- (buffer[2] != 0xff) ||
- (buffer[3] != 0xff) ||
- (buffer[4] != 0xff) ||
- (buffer[5] != 0xff) ||
- (buffer[6] != 0xff) ||
- (buffer[7] != 0x00))
- return FALSE;
-
- /* Check EDID version and revision */
- if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE;
-
- /* Check week of manufacture for sanity */
- if(buffer[0x10] > 53) return FALSE;
-
- /* Check year of manufacture for sanity */
- if(buffer[0x11] > 40) return FALSE;
-
- return TRUE;
-}
-
-static BOOLEAN
-checkedid2(unsigned char *buffer)
-{
- USHORT year = buffer[6] | (buffer[7] << 8);
-
- /* Check EDID version */
- if((buffer[0] & 0xf0) != 0x20) return FALSE;
-
- /* Check week of manufacture for sanity */
- if(buffer[5] > 53) return FALSE;
-
- /* Check year of manufacture for sanity */
- if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE;
-
- return TRUE;
-}
-
-/* Sense the LCD parameters (CR36, CR37) via DDC */
-/* SiS30x(B) only */
-USHORT
-SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
- USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
- USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct;
- int maxx=0, maxy=0, prefx=0, prefy=0;
- unsigned char cr37=0, seekcode;
- BOOLEAN checkexpand = FALSE;
- BOOLEAN havesync = FALSE;
- BOOLEAN indb = FALSE;
- int retry, i;
- unsigned char buffer[256];
-
- for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
- SiS_Pr->CP_HaveCustomData = FALSE;
- SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
- SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
- SiS_Pr->CP_PreferredIndex = -1;
- SiS_Pr->CP_PrefClock = 0;
- SiS_Pr->PanelSelfDetected = FALSE;
-
- if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
- if(pSiS->VBFlags & VB_30xBDH) return 0;
-
- if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
-
- SiS_Pr->SiS_DDC_SecAddr = 0x00;
-
- /* Probe supported DA's */
- flag = SiS_ProbeDDC(SiS_Pr);
-#ifdef TWDEBUG
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
- "CRT2 DDC capabilities 0x%x\n", flag);
-#endif
- if(flag & 0x10) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */
- DDCdatatype = 4;
- } else if(flag & 0x08) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */
- DDCdatatype = 3;
- } else if(flag & 0x02) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */
- DDCdatatype = 1;
- } else return 0; /* no DDC support (or no device attached) */
-
- /* Read the entire EDID */
- retry = 2;
- do {
- if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "CRT2: DDC read failed (attempt %d), %s\n",
- (3-retry), (retry == 1) ? "giving up" : "retrying");
- retry--;
- if(retry == 0) return 0xFFFF;
- } else break;
- } while(1);
-
-#ifdef TWDEBUG
- for(i=0; i<256; i+=16) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffer[i], buffer[i+1], buffer[i+2], buffer[i+3],
- buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7],
- buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11],
- buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
- }
-#endif
-
- /* Analyze EDID and retrieve LCD panel information */
- paneltype = 0;
- switch(DDCdatatype) {
- case 1: /* Analyze EDID V1 */
- /* Catch a few clear cases: */
- if(!(checkedid1(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: EDID corrupt\n");
- return 0;
- }
-
- if(!(buffer[0x14] & 0x80)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Attached display expects analog input (0x%02x)\n",
- buffer[0x14]);
- return 0;
- }
-
- if((buffer[0x18] & 0x18) != 0x08) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n",
- ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
- ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
- "undefined"),
- buffer[0x18]);
- }
-
- /* Now analyze the first Detailed Timing Block and see
- * if the preferred timing mode is stored there. If so,
- * check if this is a standard panel for which we already
- * know the timing.
- */
-
- paneltype = Panel_Custom;
- checkexpand = FALSE;
-
- panelvendor = buffer[9] | (buffer[8] << 8);
- panelproduct = buffer[10] | (buffer[11] << 8);
-
- /* Overrule bogus preferred modes from database */
- if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
- if(prefx) SiS_Pr->CP_PreferredX = xres = prefx;
- if(prefy) SiS_Pr->CP_PreferredY = yres = prefy;
- }
-
- if(buffer[0x18] & 0x02) {
-
- USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8));
- USHORT phb = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8));
- USHORT pvb = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8));
-
- if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
- if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
-
- switch(xres) {
-#if 0 /* Treat as custom */
- case 800:
- if(yres == 600) {
- paneltype = Panel_800x600;
- checkexpand = TRUE;
- }
- break;
-#endif
- case 1024:
- if(yres == 768) {
- paneltype = Panel_1024x768;
- checkexpand = TRUE;
- }
- break;
- case 1280:
- if(yres == 1024) {
- paneltype = Panel_1280x1024;
- checkexpand = TRUE;
- } else if(yres == 960) {
- if(pSiS->VGAEngine == SIS_300_VGA) {
- paneltype = Panel300_1280x960;
- } else {
- paneltype = Panel310_1280x960;
- }
- } else if(yres == 768) {
- if( (pclk == 8100) &&
- (phb == (1688 - 1280)) &&
- (pvb == (802 - 768)) ) {
- paneltype = Panel_1280x768;
- checkexpand = FALSE;
- cr37 |= 0x10;
- }
- } else if(yres == 800) {
- if( (pclk == 6900) &&
- (phb == (1408 - 1280)) &&
- (pvb == (816 - 800)) ) {
- paneltype = Panel_1280x800;
- }
- }
- break;
- case 1400:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(yres == 1050) {
- paneltype = Panel310_1400x1050;
- checkexpand = TRUE;
- }
- }
- break;
- case 1600:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(pSiS->VBFlags & VB_301C) {
- if(yres == 1200) {
- paneltype = Panel310_1600x1200;
- checkexpand = TRUE;
- }
- }
- }
- break;
- }
-
- /* Save sync: This is used if "Pass 1:1" is off; in this case
- * we always use the panel's native mode = this "preferred mode"
- * we just have been analysing. Hence, we also need its sync.
- */
- if((buffer[0x47] & 0x18) == 0x18) {
- cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- } else {
- /* What now? There is no digital separate output timing... */
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- cr37 |= 0xc0; /* Default */
- }
-
- }
-
- /* Check against our database; eg. Sanyo Z2 projector reports
- * 1024x768 as preferred mode, although it supports 1280x720
- * natively in non-HDCP mode. Treat such wrongly reporting
- * panels as custom and fixup actual maximum resolutions.
- */
- if(paneltype != Panel_Custom) {
- if(indb) {
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = maxx;
- SiS_Pr->CP_MaxY = maxy;
- /* Leave preferred unchanged (MUST contain a valid mode!) */
- }
- }
-
- /* If we still don't know what panel this is, we take it
- * as a custom panel and derive the timing data from the
- * detailed timing blocks
- */
- if(paneltype == Panel_Custom) {
-
- int i, temp, base = 0x36;
- unsigned long estpack;
- const unsigned short estx[] = {
- 720, 720, 640, 640, 640, 640, 800, 800,
- 800, 800, 832,1024,1024,1024,1024,1280,
- 1152
- };
- const unsigned short esty[] = {
- 400, 400, 480, 480, 480, 480, 600, 600,
- 600, 600, 624, 768, 768, 768, 768,1024,
- 870
- };
- const int estclk[] = {
- 0, 0, 25100, 0, 31500, 31500, 36100, 40000,
- 50100, 49500, 0, 0, 65100, 75200, 78700,135200,
- 0
- };
-
- paneltype = 0;
- SiS_Pr->CP_Supports64048075 = TRUE;
-
- /* Find the maximum resolution */
-
- /* 1. From Established timings */
- estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
- for(i=16; i>=0; i--) {
- if(estpack & (1 << i)) {
- if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
- if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
- if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i];
- }
- }
-
- /* By default we drive the LCD at 75Hz in 640x480 mode; if
- * the panel does not provide this mode, use 60hz
- */
- if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE;
-
- /* 2. From Standard Timings */
- for(i=0x26; i < 0x36; i+=2) {
- if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
- temp = (buffer[i] + 31) * 8;
- if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
- switch((buffer[i+1] & 0xc0) >> 6) {
- case 0x03: temp = temp * 9 / 16; break;
- case 0x02: temp = temp * 4 / 5; break;
- case 0x01: temp = temp * 3 / 4; break;
- }
- if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
- }
- }
-
- /* Now extract the Detailed Timings and convert them into modes */
-
- for(i = 0; i < 4; i++, base += 18) {
-
- /* Is this a detailed timing block or a monitor descriptor? */
- if(buffer[base] || buffer[base+1] || buffer[base+2]) {
-
- xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
- yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
-
- SiS_Pr->CP_HDisplay[i] = xres;
- SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
- SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
- SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
- SiS_Pr->CP_HBlankStart[i] = xres + 1;
- SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
- SiS_Pr->CP_VDisplay[i] = yres;
- SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
- SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
- SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
- SiS_Pr->CP_VBlankStart[i] = yres + 1;
- SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
- SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
-
- SiS_Pr->CP_DataValid[i] = TRUE;
-
- /* Sort out invalid timings, interlace and too high clocks */
- if((SiS_Pr->CP_HDisplay[i] & 7) ||
- (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
- (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
- ((!(pSiS->VBFlags & VB_301C)) &&
- ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) ||
- (SiS_Pr->CP_HDisplay[i] > 1600)))) ||
- (buffer[base+17] & 0x80)) {
-
- SiS_Pr->CP_DataValid[i] = FALSE;
-
- } else {
-
- SiS_Pr->CP_HaveCustomData = TRUE;
-
- if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
- if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
- if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
- if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
- SiS_Pr->CP_PreferredIndex = i;
- SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
- SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
- }
-
- /* Extract the sync polarisation information. This only works
- * if the Flags indicate a digital separate output.
- */
- if((buffer[base+17] & 0x18) == 0x18) {
- SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
- SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
- SiS_Pr->CP_SyncValid[i] = TRUE;
- if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) {
- cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- }
- } else {
- SiS_Pr->CP_SyncValid[i] = FALSE;
- }
-
- }
-
- } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) {
-
- /* Maximum pixclock from Monitor Range Limits */
- if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) {
- int maxclk = buffer[base+9] * 10;
- /* More than 170 is not supported anyway */
- if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000;
- }
-
- }
-
- }
-
- if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) {
- paneltype = Panel_Custom;
- checkexpand = FALSE;
- cr37 |= 0x10;
- SiS_Pr->CP_Vendor = panelvendor;
- SiS_Pr->CP_Product = panelproduct;
- }
-
- }
-
- if(paneltype && checkexpand) {
- /* If any of the Established low-res modes is supported, the
- * panel can scale automatically. For 800x600 panels, we only
- * check the even lower ones.
- */
- if(paneltype == Panel_800x600) {
- if(buffer[0x23] & 0xfc) cr37 |= 0x10;
- } else {
- if(buffer[0x23]) cr37 |= 0x10;
- }
- }
-
- break;
-
- case 3: /* Analyze EDID V2 */
- case 4:
- index = 0;
-
- if(!(checkedid2(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: EDID corrupt\n");
- return 0;
- }
-
- if((buffer[0x41] & 0x0f) == 0x03) {
- index = 0x42 + 3;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display supports TMDS input on primary interface\n");
- } else if((buffer[0x41] & 0xf0) == 0x30) {
- index = 0x46 + 3;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display supports TMDS input on secondary interface\n");
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display does not support TMDS video interface (0x%02x)\n",
- buffer[0x41]);
- return 0;
- }
-
- SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8);
- SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8);
-
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8);
- SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8);
-
- switch(xres) {
-#if 0
- case 800:
- if(yres == 600) {
- paneltype = Panel_800x600;
- checkexpand = TRUE;
- }
- break;
-#endif
- case 1024:
- if(yres == 768) {
- paneltype = Panel_1024x768;
- checkexpand = TRUE;
- }
- break;
- case 1280:
- if(yres == 960) {
- if(pSiS->VGAEngine == SIS_315_VGA) {
- paneltype = Panel310_1280x960;
- } else {
- paneltype = Panel300_1280x960;
- }
- } else if(yres == 1024) {
- paneltype = Panel_1280x1024;
- checkexpand = TRUE;
- }
- /* 1280x768 treated as custom here */
- break;
- case 1400:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(yres == 1050) {
- paneltype = Panel310_1400x1050;
- checkexpand = TRUE;
- }
- }
- break;
- case 1600:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(pSiS->VBFlags & VB_301C) {
- if(yres == 1200) {
- paneltype = Panel310_1600x1200;
- checkexpand = TRUE;
- }
- }
- }
- break;
- }
-
- /* Determine if RGB18 or RGB24 */
- if(index) {
- if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
- cr37 |= 0x01;
- }
- }
-
- if(checkexpand) {
- /* TODO - for now, we let the panel scale */
- cr37 |= 0x10;
- }
-
- /* Now seek 4-Byte Timing codes and extract sync pol info */
- index = 0x80;
- if(buffer[0x7e] & 0x20) { /* skip Luminance Table (if provided) */
- lumsize = buffer[0x80] & 0x1f;
- if(buffer[0x80] & 0x80) lumsize *= 3;
- lumsize++; /* luminance header byte */
- index += lumsize;
- }
-#if 0 /* "pixel rate" = pixel clock? */
- if(buffer[0x7e] & 0x1c) {
- for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) {
- if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) {
- int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000;
- if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
- }
- }
- }
-#endif
- index += (((buffer[0x7e] & 0x1c) >> 2) * 8); /* skip Frequency Ranges */
- if(buffer[0x7e] & 0x03) {
- for(i=0; i<(buffer[0x7e] & 0x03); i++) {
- if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) {
- int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10;
- if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
- }
- }
- }
- index += ((buffer[0x7e] & 0x03) * 27); /* skip Detailed Range Limits */
- numcodes = (buffer[0x7f] & 0xf8) >> 3;
- if(numcodes) {
- myindex = index;
- seekcode = (xres - 256) / 16;
- for(i=0; i<numcodes; i++) {
- if(buffer[myindex] == seekcode) break;
- myindex += 4;
- }
- if(buffer[myindex] == seekcode) {
- cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
- havesync = TRUE;
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- }
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- }
-
- /* Check against our database; Eg. Sanyo projector reports
- * 1024x768 in non-HDPC mode, although it supports 1280x720.
- * Treat such wrongly reporting panels as custom.
- */
- if(paneltype != Panel_Custom) {
- int maxx, maxy, prefx, prefy;
- if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = maxx;
- SiS_Pr->CP_MaxY = maxy;
- cr37 |= 0x10;
- /* Leave preferred unchanged (MUST be a valid mode!) */
- }
- }
-
- /* Now seek the detailed timing descriptions for custom panels */
- if(paneltype == Panel_Custom) {
-
- SiS_Pr->CP_Supports64048075 = TRUE;
-
- index += (numcodes * 4);
- numcodes = buffer[0x7f] & 0x07;
- for(i=0; i<numcodes; i++, index += 18) {
- xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
- yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
-
- SiS_Pr->CP_HDisplay[i] = xres;
- SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
- SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
- SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
- SiS_Pr->CP_HBlankStart[i] = xres + 1;
- SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
- SiS_Pr->CP_VDisplay[i] = yres;
- SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
- SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
- SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
- SiS_Pr->CP_VBlankStart[i] = yres + 1;
- SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
- SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
-
- SiS_Pr->CP_DataValid[i] = TRUE;
-
- if((SiS_Pr->CP_HDisplay[i] & 7) ||
- (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
- (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
- ((!(pSiS->VBFlags & VB_301C)) &&
- ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024)))) ||
- (buffer[index + 17] & 0x80)) {
-
- SiS_Pr->CP_DataValid[i] = FALSE;
-
- } else {
-
- SiS_Pr->CP_HaveCustomData = TRUE;
-
- if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
- if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
- SiS_Pr->CP_PreferredIndex = i;
- SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
- SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
- if(!havesync) {
- cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- }
- }
-
- SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
- SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
- SiS_Pr->CP_SyncValid[i] = TRUE;
-
- }
- }
-
- cr37 |= 0x10;
-
- }
-
- break;
-
- }
-
- /* 1280x960 panels are always RGB24, unable to scale and use
- * high active sync polarity
- */
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
- } else {
- if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
- }
-
- for(i = 0; i < 7; i++) {
- if(SiS_Pr->CP_DataValid[i]) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "Non-standard LCD/DVI-D timing data no. %d:\n", i);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
- SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
- SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
- SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
- SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
- " To use this, add \"%dx%d\" to the list of Modes in the Screen section\n",
- SiS_Pr->CP_HDisplay[i],
- SiS_Pr->CP_VDisplay[i]);
- }
- }
-
- if(paneltype) {
- if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
- if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
- cr37 &= 0xf1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
- SiS_Pr->PanelSelfDetected = TRUE;
-#ifdef TWDEBUG
- xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3,
- "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
-#endif
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
- }
- return 0;
-}
-
-USHORT
-SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
- USHORT DDCdatatype,flag;
- BOOLEAN foundcrt = FALSE;
- int retry;
- unsigned char buffer[256];
-
- if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
-
- if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
-
- SiS_Pr->SiS_DDC_SecAddr = 0x00;
-
- /* Probe supported DA's */
- flag = SiS_ProbeDDC(SiS_Pr);
- if(flag & 0x10) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */
- DDCdatatype = 4;
- } else if(flag & 0x08) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */
- DDCdatatype = 3;
- } else if(flag & 0x02) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */
- DDCdatatype = 1;
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "VGA2 sense: Do DDC answer\n");
- return 0; /* no DDC support (or no device attached) */
- }
-
- /* Read the entire EDID */
- retry = 2;
- do {
- if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "VGA2 sense: DDC read failed (attempt %d), %s\n",
- (3-retry), (retry == 1) ? "giving up" : "retrying");
- retry--;
- if(retry == 0) return 0xFFFF;
- } else break;
- } while(1);
-
- /* Analyze EDID. We don't have many chances to
- * distinguish a flat panel from a CRT...
- */
- switch(DDCdatatype) {
- case 1:
- if(!(checkedid1(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: EDID corrupt\n");
- return 0;
- }
- if(buffer[0x14] & 0x80) { /* Display uses digital input */
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: Attached display expects digital input\n");
- return 0;
- }
- SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
- SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
- foundcrt = TRUE;
- break;
- case 3:
- case 4:
- if(!(checkedid2(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: EDID corrupt\n");
- return 0;
- }
- if( ((buffer[0x41] & 0x0f) != 0x01) && /* Display does not support analog input */
- ((buffer[0x41] & 0x0f) != 0x02) &&
- ((buffer[0x41] & 0xf0) != 0x10) &&
- ((buffer[0x41] & 0xf0) != 0x20) ) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: Attached display does not support analog input (0x%02x)\n",
- buffer[0x41]);
- return 0;
- }
- SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
- SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
- foundcrt = TRUE;
- break;
- }
-
- if(foundcrt) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
- }
- return(0);
-}
-
-#endif
-
-void
-SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
-{
- USHORT tempbl;
-
- tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
- tempbl = (((tempbl & tempbh) << 8) | tempax);
- SiS_SetCH70xx(SiS_Pr,tempbl);
-}
-
/* Generic I2C functions for Chrontel & DDC --------- */
static void
-SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
+SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
{
SiS_SetSCLKHigh(SiS_Pr);
SiS_WaitRetrace1(SiS_Pr);
@@ -10505,125 +9502,127 @@ SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
SiS_WaitRetrace1(SiS_Pr);
}
-USHORT
-SiS_ReadDDC1Bit(SiS_Private *SiS_Pr)
+unsigned short
+SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
{
SiS_WaitRetrace1(SiS_Pr);
- return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
+ return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
}
/* Set I2C start condition */
/* This is done by a SD high-to-low transition while SC is high */
-static USHORT
-SiS_SetStart(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStart(struct SiS_Private *SiS_Pr)
{
- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* SD->high */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* SD->high */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* SD->low = start condition */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* SD->low = start condition */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
return 0;
}
/* Set I2C stop condition */
/* This is done by a SD low-to-high transition while SC is high */
-static USHORT
-SiS_SetStop(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStop(struct SiS_Private *SiS_Pr)
{
- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* SD->low */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* SD->low */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
return 0;
}
/* Write 8 bits of data */
-static USHORT
-SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
{
- USHORT i,flag,temp;
+ unsigned short i,flag,temp;
flag = 0x80;
- for(i=0; i<8; i++) {
- SiS_SetSCLKLow(SiS_Pr); /* SC->low */
+ for(i = 0; i < 8; i++) {
+ SiS_SetSCLKLow(SiS_Pr); /* SC->low */
if(tempax & flag) {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
} else {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* Write bit (0) to SD */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* Write bit (0) to SD */
}
- SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
+ SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
flag >>= 1;
}
- temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
- return(temp);
+ temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
+ return temp;
}
-static USHORT
-SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
{
- USHORT i,temp,getdata;
+ unsigned short i, temp, getdata;
- getdata=0;
- for(i=0; i<8; i++) {
+ getdata = 0;
+ for(i = 0; i < 8; i++) {
getdata <<= 1;
SiS_SetSCLKLow(SiS_Pr);
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
SiS_Pr->SiS_DDC_Data);
SiS_SetSCLKHigh(SiS_Pr);
temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
}
- return(getdata);
+ return getdata;
}
-static USHORT
-SiS_SetSCLKLow(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
{
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NClk,
- 0x00); /* SetSCLKLow() */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NClk,
+ 0x00); /* SetSCLKLow() */
SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
return 0;
}
-static USHORT
-SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
{
- USHORT temp, watchdog=1000;
+ unsigned short temp, watchdog=1000;
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NClk,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NClk,
SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
do {
temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
} while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
if (!watchdog) {
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
#endif
+#endif
return 0xFFFF;
}
SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
@@ -10632,21 +9631,21 @@ SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
/* Check I2C acknowledge */
/* Returns 0 if ack ok, non-0 if ack not ok */
-static USHORT
-SiS_CheckACK(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_CheckACK(struct SiS_Private *SiS_Pr)
{
- USHORT tempah;
+ unsigned short tempah;
SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* (SD->high) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* (SD->high) */
SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
- if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* Ack OK if bit = 0 */
- else return(0);
+ if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
+ return 0;
}
/* End of I2C functions ----------------------- */
@@ -10656,67 +9655,67 @@ SiS_CheckACK(SiS_Private *SiS_Pr)
#ifdef SIS315H
-static USHORT
-GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetRAMDACromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x128);
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB)
romptr = SISGETROMW(0x12a);
} else {
romptr = SISGETROMW(0x1a8);
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB)
romptr = SISGETROMW(0x1aa);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x120);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x122);
} else {
romptr = SISGETROMW(0x1a0);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x1a2);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetTVromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x114);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x11a);
} else {
romptr = SISGETROMW(0x194);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x19a);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
- if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+ if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
index >>= 4;
index *= 3;
@@ -10729,7 +9728,12 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
- else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+ if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
+ } else {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+ }
index--;
index *= 3;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -10737,10 +9741,10 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
return index;
}
-static USHORT
-GetLCDPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -10748,10 +9752,10 @@ GetLCDPtrIndex(SiS_Private *SiS_Pr)
return index;
}
-static USHORT
-GetTVPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetTVPtrIndex(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = 0;
if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
@@ -10769,10 +9773,10 @@ GetTVPtrIndex(SiS_Private *SiS_Pr)
return index;
}
-static ULONG
-GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
+static unsigned int
+GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
{
- USHORT index = 0, temp = 0;
+ unsigned short index = 0, temp = 0;
if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
@@ -10784,7 +9788,7 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
index += addme;
@@ -10792,25 +9796,25 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
}
temp += 0x0100;
}
- return(ULONG)(index | (temp << 16));
+ return (unsigned int)(index | (temp << 16));
}
-static ULONG
-GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
{
- return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+ return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
}
#if 0
-static ULONG
-GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
{
- return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+ return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
}
#endif
static int
-GetOEMTVPtr661(SiS_Private *SiS_Pr)
+GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
{
int index = 0;
@@ -10833,10 +9837,10 @@ GetOEMTVPtr661(SiS_Private *SiS_Pr)
}
static void
-SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT delay=0,index,myindex,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short delay=0,index,myindex,temp,romptr=0;
BOOLEAN dochiptest = TRUE;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -10848,19 +9852,19 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/* Find delay (from ROM, internal tables, PCI subsystem) */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
-
+
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
+ romptr = GetRAMDACromptr(SiS_Pr);
}
if(romptr) delay = ROMAddr[romptr];
else {
delay = 0x04;
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
if(IS_SIS650) {
delay = 0x0a;
} else if(IS_SIS740) {
delay = 0x00;
- } else if(HwInfo->jChipType < SIS_330) {
+ } else if(SiS_Pr->ChipType < SIS_330) {
delay = 0x0c;
} else {
delay = 0x0c;
@@ -10901,8 +9905,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
} else {
delay = 0x0c;
- if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
- else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ delay = 0x03;
+ if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
+ delay = 0x00;
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(IS_SIS740) delay = 0x01;
else delay = 0x03;
}
@@ -10947,12 +9955,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
if(!gotitfrompci) {
- index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo);
+ index = GetLCDPtrIndexBIOS(SiS_Pr);
myindex = GetLCDPtrIndex(SiS_Pr);
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
- if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
/* Always use the second pointer on 650; some BIOSes */
@@ -10978,11 +9986,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
(!(SiS_Pr->SiS_ROMNew)) &&
(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
(SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
- (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
+ (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
+ (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
+ ((romptr = GetLCDromptr(SiS_Pr)))) {
/* Data for 1280x1024 wrong in 301B BIOS */
- romptr = GetLCDromptr(SiS_Pr, HwInfo);
- if(!romptr) return;
+ /* Data for 1600x1200 wrong in 301C BIOS */
delay = ROMAddr[(romptr + index)];
} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
@@ -10993,14 +10002,15 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else {
delay = SiS310_LCDDelayCompensation_301[myindex];
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(IS_SIS740) delay = 0x01;
- else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
+ else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
} else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
if(IS_SIS740) delay = 0x01; /* ? */
else delay = 0x03;
- } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
if(IS_SIS740) delay = 0x01;
else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
}
@@ -11013,14 +10023,14 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
dochiptest = FALSE;
}
-
+
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
index = GetTVPtrIndex(SiS_Pr);
-
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
- if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
/* Always use the second pointer on 650; some BIOSes */
@@ -11062,7 +10072,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- romptr = GetTVromptr(SiS_Pr, HwInfo);
+ romptr = GetTVromptr(SiS_Pr);
if(!romptr) return;
delay = ROMAddr[romptr + index];
@@ -11073,7 +10083,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else {
delay = SiS310_TVDelayCompensation_301[index];
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if(IS_SIS740) {
delay = SiS310_TVDelayCompensation_740301B[index];
/* LV: use 301 data? BIOS bug? */
@@ -11085,18 +10095,18 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
}
- if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+ if(SiS_LCDAEnabled(SiS_Pr)) {
delay &= 0x0f;
dochiptest = FALSE;
}
-
+
} else return;
/* Write delay */
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
@@ -11134,11 +10144,10 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
}
static void
-SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,temp1,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,temp1,romptr=0;
if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
@@ -11152,14 +10161,14 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
temp1 = temp;
if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
temp1 = GetOEMTVPtr661(SiS_Pr);
temp1 >>= 1;
romptr = SISGETROMW(0x260);
- if(HwInfo->jChipType >= SIS_760) {
+ if(SiS_Pr->ChipType >= SIS_760) {
romptr = SISGETROMW(0x360);
}
- } else if(HwInfo->jChipType >= SIS_330) {
+ } else if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x192);
} else {
romptr = SISGETROMW(0x112);
@@ -11178,11 +10187,10 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,temp1,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,temp1,romptr=0;
temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
@@ -11192,14 +10200,14 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
romptr = SISGETROMW(0x26c);
- if(HwInfo->jChipType >= SIS_760) {
+ if(SiS_Pr->ChipType >= SIS_760) {
romptr = SISGETROMW(0x36c);
}
temp1 = GetOEMTVPtr661(SiS_Pr);
temp1 >>= 1;
- } else if(HwInfo->jChipType >= SIS_330) {
+ } else if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x1a4);
} else {
romptr = SISGETROMW(0x124);
@@ -11217,10 +10225,9 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- USHORT index, temp, i, j;
+ unsigned short index, temp, i, j;
if(ModeNo <= 0x13) {
index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
@@ -11235,7 +10242,7 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x35, j=0; i<=0x38; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
}
@@ -11250,23 +10257,22 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,i,j,resinfo,romptr=0;
- ULONG lindex;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,i,j,resinfo,romptr=0;
+ unsigned int lindex;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
/* NTSC-J data not in BIOS, and already set in SetGroup2 */
if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
- if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+ if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
lindex <<= 2;
for(j=0, i=0x31; i<=0x34; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
}
return;
}
@@ -11286,17 +10292,17 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
*/
if(SiS_Pr->SiS_UseROM) {
romptr = SISGETROMW(0x116);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x196);
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
romptr = SISGETROMW(0x11c);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x19c);
}
if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
romptr = SISGETROMW(0x116);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x196);
}
}
@@ -11311,7 +10317,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = temp % 2;
temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
for(j=0, i=0x31; i<=0x34; i++, j++) {
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
@@ -11320,7 +10326,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
if((resinfo == SIS_RI_640x480) ||
(resinfo == SIS_RI_800x600)) {
@@ -11339,11 +10345,11 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
- USHORT ModeIdIndex, USHORT RTI)
+SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RTI)
{
- USHORT delay = 0, romptr = 0, index, lcdpdcindex;
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
return;
@@ -11359,7 +10365,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
if(SiS_Pr->UseCustomMode) {
index = SiS_Pr->CSRClock;
} else if(ModeNo > 0x13) {
- index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+ index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
index = SiS_Pr->SiS_VCLKData[index].CLOCK;
}
if(index < 25) index = 25;
@@ -11387,7 +10393,36 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
delay |= (delay << 8);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->ChipType >= XGI_20) {
+
+ delay = 0x0606;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+ delay = 0x0404;
+ if(SiS_Pr->SiS_XGIROM) {
+ index = GetTVPtrIndex(SiS_Pr);
+ if((romptr = SISGETROMW(0x35e))) {
+ delay = (ROMAddr[romptr + index] & 0x0f) << 1;
+ delay |= (delay << 8);
+ }
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
+ delay -= 0x0404;
+ }
+ }
+ }
+
+ } else if(SiS_Pr->ChipType >= SIS_340) {
+
+ delay = 0x0606;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ delay = 0x0404;
+ }
+ /* TODO (eventually) */
+
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
/* 3. TV */
@@ -11406,7 +10441,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
/* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
- ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+ ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
@@ -11426,6 +10461,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
case Panel_1280x768_2:delay = 0x0004; break;
case Panel_1280x800:
case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
+ case Panel_1280x854: delay = 0x0004; break; /* FIXME */
case Panel_1280x1024: delay = 0x1e04; break;
case Panel_1400x1050: delay = 0x0004; break;
case Panel_1600x1200: delay = 0x0400; break;
@@ -11469,10 +10505,10 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
}
static void
-SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI)
+SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
{
- USHORT infoflag;
- UCHAR temp;
+ unsigned short infoflag;
+ unsigned char temp;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
@@ -11513,12 +10549,16 @@ SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, US
}
static void
-SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SetPanelParms661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr, temp1, temp2;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr, temp1, temp2;
+
+ if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
+ }
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(SiS_Pr->LVDSHL != -1) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
}
@@ -11526,8 +10566,8 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
if(SiS_Pr->SiS_ROMNew) {
- if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
temp2 = 0xfc;
if(SiS_Pr->LVDSHL != -1) {
@@ -11546,48 +10586,47 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
static void
-SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI)
+SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
{
if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
- SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+ SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
- SetPanelParms661(SiS_Pr,HwInfo);
+ SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+ SetPanelParms661(SiS_Pr);
}
} else {
- SetDelayComp(SiS_Pr,HwInfo,ModeNo);
+ SetDelayComp(SiS_Pr,ModeNo);
}
if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
+ SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
+ SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
}
}
}
static void
-SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI)
+SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+ SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
- SetPanelParms661(SiS_Pr,HwInfo);
+ SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+ SetPanelParms661(SiS_Pr);
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
+ SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
+ SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
}
}
}
@@ -11601,13 +10640,12 @@ SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
* pray that we have a backup...
*/
static void
-SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
- USHORT resinfo,modeflag;
+ unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
+ unsigned short resinfo,modeflag;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
if(SiS_Pr->SiS_ROMNew) return;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
@@ -11678,7 +10716,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
#ifdef SET_EMI
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
@@ -11806,11 +10844,11 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS300
static void
-SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
+SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefTabIndex)
{
- USHORT crt2crtc=0, modeflag, myindex=0;
- UCHAR temp;
+ unsigned short crt2crtc=0, modeflag, myindex=0;
+ unsigned char temp;
int i;
if(ModeNo <= 0x13) {
@@ -11849,21 +10887,21 @@ SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
-static USHORT
-GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
+static unsigned short
+GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT tempbx=0,romptr=0;
- UCHAR customtable300[] = {
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short tempbx=0,romptr=0;
+ static const unsigned char customtable300[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};
- UCHAR customtable630[] = {
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ static const unsigned char customtable630[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};
- if(HwInfo->jChipType == SIS_300) {
+ if(SiS_Pr->ChipType == SIS_300) {
tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
@@ -11912,11 +10950,10 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
}
static void
-SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
@@ -11927,22 +10964,22 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
/* The Panel Compensation Delay should be set according to tables
- * here. Unfortunately, various BIOS versions don't case about
+ * here. Unfortunately, various BIOS versions don't care about
* a uniform way using eg. ROM byte 0x220, but use different
* hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
- * Thus we don't set this if the user select a custom pdc or if
+ * Thus we don't set this if the user selected a custom pdc or if
* we otherwise detected a valid pdc.
*/
if(SiS_Pr->PDC != -1) return;
- temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
+ temp = GetOEMLCDPtr(SiS_Pr, 0);
if(SiS_Pr->UseCustomMode)
index = 0;
else
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
- if(HwInfo->jChipType != SIS_300) {
+ if(SiS_Pr->ChipType != SIS_300) {
if(romptr) {
romptr += (temp * 2);
romptr = SISGETROMW(romptr);
@@ -11986,12 +11023,11 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
#if 0 /* Unfinished; Data table missing */
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp;
if((SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x237] & 0x01)) return;
@@ -11999,8 +11035,8 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/* No rom pointer in BIOS header! */
}
- temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1);
- if(temp = 0xFFFF) return;
+ temp = GetOEMLCDPtr(SiS_Pr, 1);
+ if(temp == 0xFFFF) return;
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
for(i=0x14, j=0; i<=0x17; i++, j++) {
@@ -12018,10 +11054,10 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
#endif
}
-static USHORT
-GetOEMTVPtr(SiS_Private *SiS_Pr)
+static unsigned short
+GetOEMTVPtr(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = 0;
if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
@@ -12037,11 +11073,10 @@ GetOEMTVPtr(SiS_Private *SiS_Pr)
}
static void
-SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12070,11 +11105,10 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12099,11 +11133,10 @@ SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,i,j,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,i,j,temp,romptr=0;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
@@ -12119,7 +11152,7 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x31, j=0; i<=0x34; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
}
@@ -12140,11 +11173,10 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,i,j,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,i,j,romptr=0;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
@@ -12162,7 +11194,7 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x35, j=0; i<=0x38; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
}
@@ -12185,11 +11217,11 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
-static USHORT
-SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
+static unsigned short
+SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
{
- USHORT ModeIdIndex;
- UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+ unsigned short ModeIdIndex;
+ unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
if(*ModeNo <= 5) *ModeNo |= 1;
@@ -12210,10 +11242,10 @@ SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
}
static void
-SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex)
+SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefTableIndex)
{
- USHORT OEMModeIdIndex=0;
+ unsigned short OEMModeIdIndex = 0;
if(!SiS_Pr->UseCustomMode) {
OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
@@ -12221,18 +11253,18 @@ SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
}
}
if(SiS_Pr->UseCustomMode) return;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex);
+ SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
- SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
- SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
+ SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
+ SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
}
}
}
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index f84eb54164a5..f475b21a85cf 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -3,7 +3,7 @@
/*
* Data and prototypes for init301.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,18 +50,18 @@
*
*/
-#ifndef _INIT301_
-#define _INIT301_
+#ifndef _INIT301_H_
+#define _INIT301_H_
#include "osdef.h"
#include "initdef.h"
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#include "sis.h"
#include "sis_regs.h"
#endif
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include "vgatypes.h"
#include "vstruct.h"
#ifdef SIS_CP
@@ -69,8 +69,13 @@
#endif
#include <linux/config.h>
#include <linux/version.h>
-#include <asm/io.h>
#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/sisfb.h>
#else
@@ -78,7 +83,7 @@
#endif
#endif
-static const UCHAR SiS_YPbPrTable[3][64] = {
+static const unsigned char SiS_YPbPrTable[3][64] = {
{
0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
@@ -90,17 +95,17 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
},
{
- 0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+ 0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
+ 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
- 0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
+ 0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
},
{
-#if 1
+#if 0 /* OK, but sticks to left edge */
0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
@@ -110,20 +115,42 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
#endif
-#if 0
- 0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c, /* TEST (0.93) - BAD */
+#if 1 /* Perfect */
+ 0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
- 0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
- 0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
- 0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+ 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+ 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+ 0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
+ 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
#endif
}
};
-static const UCHAR SiS_HiTVGroup3_1[] = {
+static const unsigned char SiS_TVPhase[] =
+{
+ 0x21,0xED,0xBA,0x08, /* 0x00 SiS_NTSCPhase */
+ 0x2A,0x05,0xE3,0x00, /* 0x01 SiS_PALPhase */
+ 0x21,0xE4,0x2E,0x9B, /* 0x02 SiS_PALMPhase */
+ 0x21,0xF4,0x3E,0xBA, /* 0x03 SiS_PALNPhase */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x05 SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x21,0xF0,0x7B,0xD6, /* 0x08 SiS_NTSCPhase2 */
+ 0x2A,0x09,0x86,0xE9, /* 0x09 SiS_PALPhase2 */
+ 0x21,0xE6,0xEF,0xA4, /* 0x0a SiS_PALMPhase2 */
+ 0x21,0xF6,0x94,0x46, /* 0x0b SiS_PALNPhase2 */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x0d SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x1e,0x8c,0x5c,0x7a, /* 0x10 SiS_SpecialPhase */
+ 0x25,0xd4,0xfd,0x5e /* 0x11 SiS_SpecialPhaseJ */
+};
+
+static const unsigned char SiS_HiTVGroup3_1[] = {
0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -134,7 +161,7 @@ static const UCHAR SiS_HiTVGroup3_1[] = {
0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
};
-static const UCHAR SiS_HiTVGroup3_2[] = {
+static const unsigned char SiS_HiTVGroup3_2[] = {
0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -147,7 +174,7 @@ static const UCHAR SiS_HiTVGroup3_2[] = {
/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
-static const UCHAR SiS_Part2CLVX_1[] = {
+static const unsigned char SiS_Part2CLVX_1[] = {
0x00,0x00,
0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -155,7 +182,7 @@ static const UCHAR SiS_Part2CLVX_1[] = {
0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
};
-static const UCHAR SiS_Part2CLVX_2[] = {
+static const unsigned char SiS_Part2CLVX_2[] = {
0x00,0x00,
0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -163,7 +190,7 @@ static const UCHAR SiS_Part2CLVX_2[] = {
0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
};
-static const UCHAR SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
+static const unsigned char SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
0xE0,0x01,
0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
@@ -182,7 +209,7 @@ static const UCHAR SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_4[] = { /* PAL */
+static const unsigned char SiS_Part2CLVX_4[] = { /* PAL */
0x58,0x02,
0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -201,7 +228,7 @@ static const UCHAR SiS_Part2CLVX_4[] = { /* PAL */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_5[] = { /* 750p */
+static const unsigned char SiS_Part2CLVX_5[] = { /* 750p */
0x00,0x03,
0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -210,7 +237,7 @@ static const UCHAR SiS_Part2CLVX_5[] = { /* 750p */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_6[] = { /* 1080i */
+static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
0x00,0x04,
0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
@@ -221,7 +248,7 @@ static const UCHAR SiS_Part2CLVX_6[] = { /* 1080i */
#ifdef SIS315H
/* 661 et al LCD data structure (2.03.00) */
-static const UCHAR SiS_LCDStruct661[] = {
+static const unsigned char SiS_LCDStruct661[] = {
/* 1024x768 */
/* type|CR37| HDE | VDE | HT | VT | hss | hse */
0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
@@ -249,11 +276,20 @@ static const UCHAR SiS_LCDStruct661[] = {
/* 1680x1050 */
0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+ /* 1280x800_3 */
+ 0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
+ 0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
+ /* 800x600 */
+ 0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
+ 0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
+ /* 1280x854 */
+ 0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
+ 0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
};
#endif
#ifdef SIS300
-static UCHAR SiS300_TrumpionData[7][80] = {
+static unsigned char SiS300_TrumpionData[14][80] = {
{ 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
@@ -288,119 +324,182 @@ static UCHAR SiS300_TrumpionData[7][80] = {
0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
- 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+ /* variant 2 */
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+ 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+ 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+ 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+ 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+ 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+ 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
};
#endif
-void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_EnableCRT2(SiS_Private *SiS_Pr);
-USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-BOOLEAN SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
- USHORT ModeIdIndex, PSIS_HW_INFO HwInfo,
- int checkcrt2mode);
-void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
-void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo);
-void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_LockCRT2(struct SiS_Private *SiS_Pr);
+#endif
+void SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
+unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+BOOLEAN SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+BOOLEAN SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int checkcrt2mode);
+void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex);
+unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
+void SiS_DisableBridge(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_EnableBridge(struct SiS_Private *SiS_Pr);
+#endif
+BOOLEAN SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
-void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
+void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#ifndef SIS_LINUX_KERNEL
+void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#endif
+void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char orval,unsigned short andval);
#ifdef SIS315H
-static void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
+static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
+static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
+void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
#endif /* 315 */
#ifdef SIS300
-#if 0
-static void SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-static USHORT SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-#endif
-static BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
+static BOOLEAN SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
#endif
-void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, UCHAR *buffer);
-#ifdef LINUX_XF86
-USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-#endif
+void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype,
+ unsigned char *buffer, unsigned int VBFlags2);
-static void SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-static USHORT SiS_SetStart(SiS_Private *SiS_Pr);
-static USHORT SiS_SetStop(SiS_Private *SiS_Pr);
-static USHORT SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-static USHORT SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-static USHORT SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT SiS_CheckACK(SiS_Private *SiS_Pr);
-static USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
-static USHORT SiS_WriteDABDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_PrepareDDC(SiS_Private *SiS_Pr);
-static void SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
-static USHORT SiS_DoProbeDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_ProbeDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, UCHAR *buffer);
+#ifdef SIS_XORG_XF86
+unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+ int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+ BOOLEAN checkcr32, unsigned int VBFlags2);
+unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+ unsigned char *buffer);
+#else
+static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+ int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+ BOOLEAN checkcr32, unsigned int VBFlags2);
+static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+ unsigned char *buffer);
+#endif
+static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
+static unsigned short SiS_CheckACK(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
+static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
+static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
+#ifdef SIS300
+static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
+static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
+#endif
#ifdef SIS315H
-static void SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
#endif
+
+extern void SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_SetRegByte(SISIOADDRESS, unsigned short);
+extern void SiS_SetRegShort(SISIOADDRESS, unsigned short);
+extern void SiS_SetRegLong(SISIOADDRESS, unsigned int);
+extern unsigned char SiS_GetReg(SISIOADDRESS, unsigned short);
+extern unsigned char SiS_GetRegByte(SISIOADDRESS);
+extern unsigned short SiS_GetRegShort(SISIOADDRESS);
+extern unsigned int SiS_GetRegLong(SISIOADDRESS);
+extern void SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
+extern void SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+extern void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+extern BOOLEAN SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex);
+extern void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+extern unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+extern unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
#ifdef SIS300
-static void SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-static void SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+extern void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
+ unsigned short *tempcl);
+extern unsigned short SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
+extern unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+#ifdef SIS_LINUX_KERNEL
+extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
#endif
-
-extern void SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_SetRegByte(SISIOADDRESS, USHORT);
-extern void SiS_SetRegShort(SISIOADDRESS, USHORT);
-extern void SiS_SetRegLong(SISIOADDRESS, ULONG);
-extern UCHAR SiS_GetReg(SISIOADDRESS, USHORT);
-extern UCHAR SiS_GetRegByte(SISIOADDRESS);
-extern USHORT SiS_GetRegShort(SISIOADDRESS);
-extern ULONG SiS_GetRegLong(SISIOADDRESS);
-extern void SiS_SetRegANDOR(SISIOADDRESS, USHORT, USHORT, USHORT);
-extern void SiS_SetRegOR(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_SetRegAND(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_DisplayOff(SiS_Private *SiS_Pr);
-extern void SiS_DisplayOn(SiS_Private *SiS_Pr);
-extern BOOLEAN SiS_SearchModeID(SiS_Private *, USHORT *, USHORT *);
-extern UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetOffset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO, USHORT ModeNo,
- USHORT ModeIdIndex);
-extern void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-#ifdef LINUX_XF86
-extern void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-extern int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct,
- int *maxx, int *maxy, int *prefx, int *prefy);
#endif
#endif
diff --git a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h
index 55a82d6dc4cf..264b55a5947b 100644
--- a/drivers/video/sis/initdef.h
+++ b/drivers/video/sis/initdef.h
@@ -3,7 +3,7 @@
/*
* Global definitions for init.c and init301.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -53,19 +53,20 @@
#ifndef _INITDEF_
#define _INITDEF_
-#define IS_SIS330 (HwInfo->jChipType == SIS_330)
-#define IS_SIS550 (HwInfo->jChipType == SIS_550)
-#define IS_SIS650 (HwInfo->jChipType == SIS_650) /* All versions, incl 651, M65x */
-#define IS_SIS740 (HwInfo->jChipType == SIS_740)
+#define IS_SIS330 (SiS_Pr->ChipType == SIS_330)
+#define IS_SIS550 (SiS_Pr->ChipType == SIS_550)
+#define IS_SIS650 (SiS_Pr->ChipType == SIS_650) /* All versions, incl 651, M65x */
+#define IS_SIS740 (SiS_Pr->ChipType == SIS_740)
#define IS_SIS651 (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
#define IS_SISM650 (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
#define IS_SIS65x (IS_SIS651 || IS_SISM650) /* Only special versions of 65x */
-#define IS_SIS661 (HwInfo->jChipType == SIS_661)
-#define IS_SIS741 (HwInfo->jChipType == SIS_741)
-#define IS_SIS660 (HwInfo->jChipType == SIS_660)
-#define IS_SIS760 (HwInfo->jChipType == SIS_760)
-#define IS_SIS661741660760 (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760)
-#define IS_SIS650740 ((HwInfo->jChipType >= SIS_650) && (HwInfo->jChipType < SIS_330))
+#define IS_SIS661 (SiS_Pr->ChipType == SIS_661)
+#define IS_SIS741 (SiS_Pr->ChipType == SIS_741)
+#define IS_SIS660 (SiS_Pr->ChipType == SIS_660)
+#define IS_SIS760 (SiS_Pr->ChipType == SIS_760)
+#define IS_SIS761 (SiS_Pr->ChipType == SIS_761)
+#define IS_SIS661741660760 (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760 || IS_SIS761)
+#define IS_SIS650740 ((SiS_Pr->ChipType >= SIS_650) && (SiS_Pr->ChipType < SIS_330))
#define IS_SIS550650740 (IS_SIS550 || IS_SIS650740)
#define IS_SIS650740660 (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
#define IS_SIS550650740660 (IS_SIS550 || IS_SIS650740660)
@@ -73,24 +74,37 @@
#define SISGETROMW(x) (ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
/* SiS_VBType */
-#define VB_SIS301 0x0001
-#define VB_SIS301B 0x0002
-#define VB_SIS302B 0x0004
-#define VB_SIS301LV 0x0008
-#define VB_SIS302LV 0x0010
+#define VB_SIS301 0x0001
+#define VB_SIS301B 0x0002
+#define VB_SIS302B 0x0004
+#define VB_SIS301LV 0x0008
+#define VB_SIS302LV 0x0010
#define VB_SIS302ELV 0x0020
-#define VB_SIS301C 0x0040
+#define VB_SIS301C 0x0040
+#define VB_SIS307T 0x0080
+#define VB_SIS307LV 0x0100
#define VB_UMC 0x4000
#define VB_NoLCD 0x8000
-#define VB_SIS301BLV302BLV (VB_SIS301B|VB_SIS301C|VB_SIS302B|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SIS301B302B (VB_SIS301B|VB_SIS301C|VB_SIS302B)
-#define VB_SIS301LV302LV (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISVB (VB_SIS301 | VB_SIS301BLV302BLV)
-#define VB_SISTMDS (VB_SIS301 | VB_SIS301B302B)
-#define VB_SISLVDS VB_SIS301LV302LV
-#define VB_SISLCDA (VB_SIS302B|VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISYPBPR (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISHIVISION (VB_SIS301|VB_SIS301B|VB_SIS302B)
+#define VB_SIS30xB (VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SIS30xC (VB_SIS301C | VB_SIS307T)
+#define VB_SISTMDS (VB_SIS301 | VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SISLVDS (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SIS30xBLV (VB_SIS30xB | VB_SISLVDS)
+#define VB_SIS30xCLV (VB_SIS30xC | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISVB (VB_SIS301 | VB_SIS30xBLV)
+#define VB_SISLCDA (VB_SIS302B | VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISTMDSLCDA (VB_SIS301C | VB_SIS307T)
+#define VB_SISPART4SCALER (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISHIVISION (VB_SIS301 | VB_SIS301B | VB_SIS302B)
+#define VB_SISYPBPR (VB_SIS301C | VB_SIS307T | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISTAP4SCALER (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPART4OVERFLOW (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPWD (VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISEMI (VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPOWER (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISDUALLINK (VB_SIS302LV | VB_SIS302ELV | VB_SIS307T | VB_SIS307LV)
+#define VB_SISVGA2 VB_SISTMDS
+#define VB_SISRAMDAC202 (VB_SIS301C | VB_SIS307T)
/* VBInfo */
#define SetSimuScanMode 0x0001 /* CR 30 */
@@ -160,6 +174,7 @@
#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
#define InterlaceMode 0x0080
#define SyncPP 0x0000
+#define HaveWideTiming 0x2000 /* Have specific wide- and non-wide timing */
#define SyncPN 0x4000
#define SyncNP 0x8000
#define SyncNN 0xc000
@@ -188,6 +203,7 @@
#define TVSetTVSimuMode 0x0200 /* new 0x200, prev. 0x800 */
#define TVRPLLDIV2XO 0x0400 /* prev 0x1000 */
#define TVSetNTSC1024 0x0800 /* new 0x100, prev. 0x2000 */
+#define TVSet525p1024 0x1000 /* TW */
#define TVAspect43 0x2000
#define TVAspect169 0x4000
#define TVAspect43LB 0x8000
@@ -208,7 +224,8 @@
#define SF_IsM661 0x0020
#define SF_IsM741 0x0040
#define SF_IsM760 0x0080
-#define SF_760LFB 0x8000 /* 760: We have LFB */
+#define SF_760UMA 0x4000 /* 76x: We have UMA */
+#define SF_760LFB 0x8000 /* 76x: We have LFB */
/* CR32 (Newer 630, and 315 series)
@@ -228,25 +245,19 @@
#define TVOverScanShift 4
/* CR35 (661 series only)
-
[0] 1 = PAL, 0 = NTSC
[1] 1 = NTSC-J (if D0 = 0)
[2] 1 = PALM (if D0 = 1)
[3] 1 = PALN (if D0 = 1)
[4] 1 = Overscan (Chrontel only)
[7:5] (only if D2 in CR38 is set)
- 000 525i
- 001 525p
+ 000 525i
+ 001 525p
010 750p
011 1080i (or HiVision on 301, 301B)
-
- These bits are being translated to TVMode flag.
-
*/
-/*
- CR37
-
+/* CR37
[0] Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS)
[3:1] External chip
300 series:
@@ -260,7 +271,7 @@
010 LVDS
011 LVDS + Chrontel 7019
660 series [2:1] only:
- reserved (now in CR38)
+ reserved (chip type now in CR38)
All other combinations reserved
[3] 661 only: Pass 1:1 data
[4] LVDS: 0: Panel Link expands / 1: Panel Link does not expand
@@ -320,6 +331,7 @@
#define Enable302LV_DualLink 0x04 /* 302LV only; enable dual link */
/* CR39 (661 and later)
+ D[7] LVDS (SiS or third party)
D[1:0] YPbPr Aspect Ratio
00 4:3 letterbox
01 4:3
@@ -341,7 +353,7 @@
0101 Set Contrast event
0110 Set Mute event
0111 Set Volume Up/Down event
- [4] Enable Backlight Control by BIOS/driver
+ [4] Enable Backlight Control by BIOS/driver
(set by driver; set means that the BIOS should
not touch the backlight registers because eg.
the driver already switched off the backlight)
@@ -350,6 +362,26 @@
[7] TV UnderScan/OverScan (set by BIOS)
*/
+/* CR7C - 661 and later
+ [7] DualEdge enabled (or: to be enabled)
+ [6] CRT2 = TV/LCD/VGA enabled (or: to be enabled)
+ [5] Init done (set at end of SiS_Init)
+ {4] LVDS LCD capabilities
+ [3] LVDS LCD capabilities
+ [2] LVDS LCD capabilities (PWD)
+ [1] LVDS LCD capabilities (PWD)
+ [0] LVDS=1, TMDS=0 (SiS or third party)
+*/
+
+/* CR7E - 661 and later
+ VBType:
+ [7] LVDS (third party)
+ [3] 301C
+ [2] 302LV
+ [1] 301LV
+ [0] 301B
+*/
+
/* LCDResInfo */
#define Panel300_800x600 0x01 /* CR36 */
#define Panel300_1024x768 0x02
@@ -359,7 +391,6 @@
#define Panel300_1024x600 0x06
#define Panel300_1152x768 0x07
#define Panel300_1280x768 0x0a
-#define Panel300_320x480 0x0e /* fstn - This is fake, can be any */
#define Panel300_Custom 0x0f
#define Panel300_Barco1366 0x10
@@ -374,9 +405,9 @@
#define Panel310_1400x1050 0x09
#define Panel310_1280x768 0x0a
#define Panel310_1600x1200 0x0b
-#define Panel310_640x480_2 0x0c
-#define Panel310_640x480_3 0x0d
-#define Panel310_320x480 0x0e /* fstn - TW: This is fake, can be any */
+#define Panel310_320x240_2 0x0c /* xSTN */
+#define Panel310_320x240_3 0x0d /* xSTN */
+#define Panel310_320x240_1 0x0e /* xSTN - This is fake, can be any */
#define Panel310_Custom 0x0f
#define Panel661_800x600 0x01
@@ -386,7 +417,7 @@
#define Panel661_1024x600 0x05
#define Panel661_1152x864 0x06
#define Panel661_1280x960 0x07
-#define Panel661_1152x768 0x08
+#define Panel661_1280x854 0x08
#define Panel661_1400x1050 0x09
#define Panel661_1280x768 0x0a
#define Panel661_1600x1200 0x0b
@@ -410,14 +441,16 @@
#define Panel_1680x1050 0x0d /* 661etc */
#define Panel_1280x720 0x0e /* 661etc */
#define Panel_Custom 0x0f /* MUST BE 0x0f (for DVI DDC detection) */
-#define Panel_320x480 0x10 /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_320x240_1 0x10 /* SiS 550 xSTN */
#define Panel_Barco1366 0x11
#define Panel_848x480 0x12
-#define Panel_640x480_2 0x13 /* SiS 550 */
-#define Panel_640x480_3 0x14 /* SiS 550 */
+#define Panel_320x240_2 0x13 /* SiS 550 xSTN */
+#define Panel_320x240_3 0x14 /* SiS 550 xSTN */
#define Panel_1280x768_2 0x15 /* 30xLV */
#define Panel_1280x768_3 0x16 /* (unused) */
#define Panel_1280x800_2 0x17 /* 30xLV */
+#define Panel_856x480 0x18
+#define Panel_1280x854 0x19 /* 661etc */
/* Index in ModeResInfo table */
#define SIS_RI_320x200 0
@@ -454,6 +487,7 @@
#define SIS_RI_1920x1080 31
#define SIS_RI_960x540 32
#define SIS_RI_960x600 33
+#define SIS_RI_1280x854 34
/* CR5F */
#define IsM650 0x80
@@ -482,16 +516,18 @@
#define VCLK100_300 0x43 /* Index in VCLKData table (300) */
#define VCLK34_300 0x3d /* Index in VCLKData table (300) */
#define VCLK_CUSTOM_300 0x47
-#define VCLK65_315 0x0b /* Index in (VB)VCLKData table (315) */
-#define VCLK108_2_315 0x19 /* Index in (VB)VCLKData table (315) */
-#define VCLK81_315 0x5b /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315 0x5e /* Index in (VB)VCLKData table (315) */
-#define VCLK108_3_315 0x45 /* Index in VBVCLKData table (315) */
-#define VCLK100_315 0x46 /* Index in VBVCLKData table (315) */
+
+#define VCLK65_315 0x0b /* Indices in (VB)VCLKData table (315) */
+#define VCLK108_2_315 0x19
+#define VCLK81_315 0x5b
+#define VCLK162_315 0x5e
+#define VCLK108_3_315 0x45
+#define VCLK100_315 0x46
#define VCLK34_315 0x55
#define VCLK68_315 0x0d
-#define VCLK_1280x800_315_2 0x5c /* Index in VBVCLKData table (315) */
-#define VCLK121_315 0x5d /* Index in VBVCLKData table (315) */
+#define VCLK_1280x800_315_2 0x5c
+#define VCLK121_315 0x5d
+#define VCLK130_315 0x72
#define VCLK_1280x720 0x5f
#define VCLK_1280x768_2 0x60
#define VCLK_1280x768_3 0x61 /* (unused?) */
@@ -507,6 +543,7 @@
#define VCLK_1152x864 0x64
#define VCLK_1360x768 0x58
#define VCLK_1280x800_315 0x6c
+#define VCLK_1280x854 0x76
#define TVCLKBASE_300 0x21 /* Indices on TV clocks in VCLKData table (300) */
#define TVCLKBASE_315 0x3a /* Indices on TV clocks in (VB)VCLKData table (315) */
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
new file mode 100644
index 000000000000..cc856d90903c
--- /dev/null
+++ b/drivers/video/sis/initextlfb.c
@@ -0,0 +1,238 @@
+/*
+ * SiS 300/540/630[S]/730[S]
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * Linux kernel specific extensions to init.c/init301.c
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or 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
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ */
+
+#include "osdef.h"
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+ unsigned char modeno, unsigned char rateindex);
+int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ int *htotal, int *vtotal, unsigned char rateindex);
+
+extern BOOLEAN SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex);
+extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+ int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int
+sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, ClockIndex = 0;
+ unsigned short RRTI = 0;
+ int Clock;
+
+ if(!SiSInitPtr(SiS_Pr)) return 65000;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
+ printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+ return 65000;
+ }
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
+ } else {
+ RRTI += rateindex;
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
+ }
+
+ Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
+
+ return Clock;
+}
+
+int
+sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
+ int j;
+
+ if(!SiSInitPtr(SiS_Pr)) return 0;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+ } else {
+ RRTI += rateindex;
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+ }
+
+ SiS_Generic_ConvertCRData(SiS_Pr,
+ (unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
+ SiS_Pr->SiS_RefIndex[RRTI].XRes,
+ SiS_Pr->SiS_RefIndex[RRTI].YRes,
+ var, FALSE);
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
+ var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
+ var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+ var->vmode = FB_VMODE_NONINTERLACED;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
+ var->vmode = FB_VMODE_INTERLACED;
+ else {
+ j = 0;
+ while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+ if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
+ SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
+ if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+ var->vmode = FB_VMODE_DOUBLE;
+ }
+ break;
+ }
+ j++;
+ }
+ }
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+#if 0 /* Do this? */
+ var->upper_margin <<= 1;
+ var->lower_margin <<= 1;
+ var->vsync_len <<= 1;
+#endif
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->upper_margin >>= 1;
+ var->lower_margin >>= 1;
+ var->vsync_len >>= 1;
+ }
+
+ return 1;
+}
+#endif /* Linux >= 2.5 */
+
+BOOLEAN
+sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
+ int *vtotal, unsigned char rateindex)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, CRT1Index = 0;
+ unsigned short RRTI = 0;
+ unsigned char sr_data, cr_data, cr_data2;
+
+ if(!SiSInitPtr(SiS_Pr)) return FALSE;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+ } else {
+ RRTI += rateindex;
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+ }
+
+ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
+ *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
+
+ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
+ cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+ *vtotal = ((cr_data & 0xFF) |
+ ((unsigned short)(cr_data2 & 0x01) << 8) |
+ ((unsigned short)(cr_data2 & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x01) << 10)) + 2;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
+ *vtotal *= 2;
+
+ return TRUE;
+}
+
+
+
diff --git a/drivers/video/sis/oem300.h b/drivers/video/sis/oem300.h
index b1358b750f53..b73f26840143 100644
--- a/drivers/video/sis/oem300.h
+++ b/drivers/video/sis/oem300.h
@@ -3,7 +3,7 @@
/*
* OEM Data for 300 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,7 +50,7 @@
*
*/
-static const UCHAR SiS300_OEMTVDelay301[8][4] =
+static const unsigned char SiS300_OEMTVDelay301[8][4] =
{
{0x08,0x08,0x08,0x08},
{0x08,0x08,0x08,0x08},
@@ -62,7 +62,7 @@ static const UCHAR SiS300_OEMTVDelay301[8][4] =
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
+static const unsigned char SiS300_OEMTVDelayLVDS[8][4] =
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -74,7 +74,7 @@ static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_OEMTVFlicker[8][4] =
+static const unsigned char SiS300_OEMTVFlicker[8][4] =
{
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
@@ -86,25 +86,7 @@ static const UCHAR SiS300_OEMTVFlicker[8][4] =
{0x00,0x00,0x00,0x00}
};
-#if 0 /* TW: Not used */
-static const UCHAR SiS300_OEMLCDDelay1[12][4]={
- {0x2c,0x2c,0x2c,0x2c},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x2c,0x2c,0x2c,0x2c},
- {0x2c,0x2c,0x2c,0x2c},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x24,0x24,0x24,0x24},
- {0x24,0x24,0x24,0x24},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x24,0x24,0x24,0x24}
-};
-#endif
-
-/* From 630/301B BIOS */
-static const UCHAR SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302LV */
+static const unsigned char SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302LV */
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -172,8 +154,7 @@ static const UCHAR SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302
{0x20,0x20,0x20,0x20}
};
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay4[12][4] =
+static const unsigned char SiS300_OEMLCDDelay4[12][4] =
{
{0x2c,0x2c,0x2c,0x2c},
{0x20,0x20,0x20,0x20},
@@ -189,8 +170,7 @@ static const UCHAR SiS300_OEMLCDDelay4[12][4] =
{0x24,0x24,0x24,0x24}
};
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay5[32][4] =
+static const unsigned char SiS300_OEMLCDDelay5[32][4] =
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -226,8 +206,8 @@ static const UCHAR SiS300_OEMLCDDelay5[32][4] =
{0x20,0x20,0x20,0x20},
};
-/* Added for LVDS */
-static const UCHAR SiS300_OEMLCDDelay3[64][4] = { /* For LVDS */
+static const unsigned char SiS300_OEMLCDDelay3[64][4] = /* For LVDS */
+{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -294,7 +274,7 @@ static const UCHAR SiS300_OEMLCDDelay3[64][4] = { /* For LVDS */
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_Phase1[8][5][4] =
+static const unsigned char SiS300_Phase1[8][5][4] =
{
{
{0x21,0xed,0x00,0x08},
@@ -354,11 +334,10 @@ static const UCHAR SiS300_Phase1[8][5][4] =
}
};
-
-static const UCHAR SiS300_Phase2[8][5][4] =
+static const unsigned char SiS300_Phase2[8][5][4] =
{
{
- {0x21,0xed,0x00,0x08},
+ {0x21,0xed,0x00,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
@@ -372,42 +351,42 @@ static const UCHAR SiS300_Phase2[8][5][4] =
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x21,0xed,0x00,0x08},
+ {0x21,0xed,0x00,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
@@ -415,7 +394,7 @@ static const UCHAR SiS300_Phase2[8][5][4] =
}
};
-static const UCHAR SiS300_Filter1[10][16][4] =
+static const unsigned char SiS300_Filter1[10][16][4] =
{
{
{0x00,0xf4,0x10,0x38},
@@ -599,7 +578,7 @@ static const UCHAR SiS300_Filter1[10][16][4] =
},
};
-static const UCHAR SiS300_Filter2[10][9][7] =
+static const unsigned char SiS300_Filter2[10][9][7] =
{
{
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -714,142 +693,144 @@ static const UCHAR SiS300_Filter2[10][9][7] =
};
/* Custom data for Barco iQ Pro R300 */
-static const UCHAR barco_p1[2][9][7][3] = {
- {
- { { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x1e, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x16, 0x00 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x1e, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x11, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x26, 0x00 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x30, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0x00, 0x00 },
- { 0x17, 0xa0, 0x00 },
- { 0x1a, 0xa0, 0x00 },
- { 0x1b, 0x2a, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0x00, 0x00 },
- { 0x17, 0xaa, 0x00 },
- { 0x1a, 0xa0, 0x00 },
- { 0x1b, 0x2a, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0, 0, 0 }
- }
- },
- {
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 },
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x1e, 0x00 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe6, 0x00 },
- { 0x1b, 0x11, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x26, 0x00 }
- },
- {
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe0, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x30, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- }
- }
+static const unsigned char barco_p1[2][9][7][3] =
+{
+ {
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x1e, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x16, 0x00 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x1e, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x11, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x26, 0x00 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x30, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0x00, 0x00 },
+ { 0x17, 0xa0, 0x00 },
+ { 0x1a, 0xa0, 0x00 },
+ { 0x1b, 0x2a, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0x00, 0x00 },
+ { 0x17, 0xaa, 0x00 },
+ { 0x1a, 0xa0, 0x00 },
+ { 0x1b, 0x2a, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0, 0, 0 }
+ }
+ },
+ {
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 },
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x1e, 0x00 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe6, 0x00 },
+ { 0x1b, 0x11, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x26, 0x00 }
+ },
+ {
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe0, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x30, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ }
+ }
};
diff --git a/drivers/video/sis/oem310.h b/drivers/video/sis/oem310.h
index 2b7db916b7e7..8fce56e4482c 100644
--- a/drivers/video/sis/oem310.h
+++ b/drivers/video/sis/oem310.h
@@ -1,9 +1,9 @@
/* $XFree86$ */
/* $XdotOrg$ */
/*
- * OEM Data for 315/330 series
+ * OEM Data for 315/330/340 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,206 +50,206 @@
*
*/
-static const UCHAR SiS310_LCDDelayCompensation_301[] = /* 301 */
+static const unsigned char SiS310_LCDDelayCompensation_301[] = /* 301 */
{
- 0x00,0x00,0x00, /* 800x600 */
- 0x0b,0x0b,0x0b, /* 1024x768 */
- 0x08,0x08,0x08, /* 1280x1024 */
- 0x00,0x00,0x00, /* 640x480 (unknown) */
- 0x00,0x00,0x00, /* 1024x600 (unknown) */
- 0x00,0x00,0x00, /* 1152x864 (unknown) */
- 0x08,0x08,0x08, /* 1280x960 (guessed) */
- 0x00,0x00,0x00, /* 1152x768 (unknown) */
- 0x08,0x08,0x08, /* 1400x1050 */
- 0x08,0x08,0x08, /* 1280x768 (guessed) */
- 0x00,0x00,0x00, /* 1600x1200 */
- 0x00,0x00,0x00, /* 320x480 (unknown) */
- 0x00,0x00,0x00,
- 0x00,0x00,0x00,
- 0x00,0x00,0x00
+ 0x00,0x00,0x00, /* 800x600 */
+ 0x0b,0x0b,0x0b, /* 1024x768 */
+ 0x08,0x08,0x08, /* 1280x1024 */
+ 0x00,0x00,0x00, /* 640x480 (unknown) */
+ 0x00,0x00,0x00, /* 1024x600 (unknown) */
+ 0x00,0x00,0x00, /* 1152x864 (unknown) */
+ 0x08,0x08,0x08, /* 1280x960 (guessed) */
+ 0x00,0x00,0x00, /* 1152x768 (unknown) */
+ 0x08,0x08,0x08, /* 1400x1050 */
+ 0x08,0x08,0x08, /* 1280x768 (guessed) */
+ 0x00,0x00,0x00, /* 1600x1200 */
+ 0x00,0x00,0x00, /* 320x480 (unknown) */
+ 0x00,0x00,0x00,
+ 0x00,0x00,0x00,
+ 0x00,0x00,0x00
};
/* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const UCHAR SiS310_LCDDelayCompensation_650301LV[] = /* 650 + 30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_650301LV[] = /* 650 + 30xLV */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x01,0x01,0x01, /* 1024x768 */
- 0x01,0x01,0x01, /* 1280x1024 */
- 0x01,0x01,0x01, /* 640x480 (unknown) */
- 0x01,0x01,0x01, /* 1024x600 (unknown) */
- 0x01,0x01,0x01, /* 1152x864 (unknown) */
- 0x01,0x01,0x01, /* 1280x960 (guessed) */
- 0x01,0x01,0x01, /* 1152x768 (unknown) */
- 0x01,0x01,0x01, /* 1400x1050 */
- 0x01,0x01,0x01, /* 1280x768 (guessed) */
- 0x01,0x01,0x01, /* 1600x1200 */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x01,0x01,0x01, /* 1024x768 */
+ 0x01,0x01,0x01, /* 1280x1024 */
+ 0x01,0x01,0x01, /* 640x480 (unknown) */
+ 0x01,0x01,0x01, /* 1024x600 (unknown) */
+ 0x01,0x01,0x01, /* 1152x864 (unknown) */
+ 0x01,0x01,0x01, /* 1280x960 (guessed) */
+ 0x01,0x01,0x01, /* 1152x768 (unknown) */
+ 0x01,0x01,0x01, /* 1400x1050 */
+ 0x01,0x01,0x01, /* 1280x768 (guessed) */
+ 0x01,0x01,0x01, /* 1600x1200 */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */
+static const unsigned char SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */
{
- 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */
- 0x33,0x33,0x33, /* 1024x768 */
- 0x33,0x33,0x33, /* 1280x1024 */
- 0x33,0x33,0x33, /* 640x480 (unknown) */
- 0x33,0x33,0x33, /* 1024x600 (unknown) */
- 0x33,0x33,0x33, /* 1152x864 (unknown) */
- 0x33,0x33,0x33, /* 1280x960 (guessed) */
- 0x33,0x33,0x33, /* 1152x768 (unknown) */
- 0x33,0x33,0x33, /* 1400x1050 */
- 0x33,0x33,0x33, /* 1280x768 (guessed) */
- 0x33,0x33,0x33, /* 1600x1200 */
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33
+ 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */
+ 0x33,0x33,0x33, /* 1024x768 */
+ 0x33,0x33,0x33, /* 1280x1024 */
+ 0x33,0x33,0x33, /* 640x480 (unknown) */
+ 0x33,0x33,0x33, /* 1024x600 (unknown) */
+ 0x33,0x33,0x33, /* 1152x864 (unknown) */
+ 0x33,0x33,0x33, /* 1280x960 (guessed) */
+ 0x33,0x33,0x33, /* 1152x768 (unknown) */
+ 0x33,0x33,0x33, /* 1400x1050 */
+ 0x33,0x33,0x33, /* 1280x768 (guessed) */
+ 0x33,0x33,0x33, /* 1600x1200 */
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33
};
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] = /* M650/651 302LV */
+static const unsigned char SiS310_LCDDelayCompensation_651302LV[] = /* M650/651 302LV */
{
- 0x33,0x33,0x33, /* 800x600 (guessed) */
- 0x33,0x33,0x33, /* 1024x768 */
- 0x33,0x33,0x33, /* 1280x1024 */
- 0x33,0x33,0x33, /* 640x480 (unknown) */
- 0x33,0x33,0x33, /* 1024x600 (unknown) */
- 0x33,0x33,0x33, /* 1152x864 (unknown) */
- 0x33,0x33,0x33, /* 1280x960 (guessed) */
- 0x33,0x33,0x33, /* 1152x768 (unknown) */
- 0x33,0x33,0x33, /* 1400x1050 */
- 0x33,0x33,0x33, /* 1280x768 (guessed) */
- 0x33,0x33,0x33, /* 1600x1200 */
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33
+ 0x33,0x33,0x33, /* 800x600 (guessed) */
+ 0x33,0x33,0x33, /* 1024x768 */
+ 0x33,0x33,0x33, /* 1280x1024 */
+ 0x33,0x33,0x33, /* 640x480 (unknown) */
+ 0x33,0x33,0x33, /* 1024x600 (unknown) */
+ 0x33,0x33,0x33, /* 1152x864 (unknown) */
+ 0x33,0x33,0x33, /* 1280x960 (guessed) */
+ 0x33,0x33,0x33, /* 1152x768 (unknown) */
+ 0x33,0x33,0x33, /* 1400x1050 */
+ 0x33,0x33,0x33, /* 1280x768 (guessed) */
+ 0x33,0x33,0x33, /* 1600x1200 */
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33
};
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] = /* 30xB */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301B[] = /* 30xB */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x0C,0x0C,0x0C, /* 1024x768 */
- 0x0C,0x0C,0x0C, /* 1280x1024 */
- 0x08,0x08,0x08, /* 640x480 */
- 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x0C,0x0C,0x0C, /* 1024x768 */
+ 0x0C,0x0C,0x0C, /* 1280x1024 */
+ 0x08,0x08,0x08, /* 640x480 */
+ 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] = /* 315+30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301LV[] = /* 315+30xLV */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x04,0x04,0x04, /* 1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
- 0x0C,0x0C,0x0C, /* 1280x1024 */
- 0x08,0x08,0x08, /* 640x480 */
- 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x04,0x04,0x04, /* 1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+ 0x0C,0x0C,0x0C, /* 1280x1024 */
+ 0x08,0x08,0x08, /* 640x480 */
+ 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_TVDelayCompensation_301[] = /* 301 */
+static const unsigned char SiS310_TVDelayCompensation_301[] = /* 301 */
{
- 0x02,0x02, /* NTSC Enhanced, Standard */
- 0x02,0x02, /* PAL */
- 0x08,0x0b /* HiVision */
+ 0x02,0x02, /* NTSC Enhanced, Standard */
+ 0x02,0x02, /* PAL */
+ 0x08,0x0b /* HiVision */
};
-static const UCHAR SiS310_TVDelayCompensation_301B[] = /* 30xB, 30xLV */
+static const unsigned char SiS310_TVDelayCompensation_301B[] = /* 30xB, 30xLV */
{
- 0x03,0x03,
- 0x03,0x03,
- 0x03,0x03
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03
};
-static const UCHAR SiS310_TVDelayCompensation_740301B[] = /* 740 + 30xB (30xLV?) */
+static const unsigned char SiS310_TVDelayCompensation_740301B[] = /* 740 + 30xB (30xLV?) */
{
- 0x05,0x05,
- 0x05,0x05,
- 0x05,0x05
+ 0x05,0x05,
+ 0x05,0x05,
+ 0x05,0x05
};
-static const UCHAR SiS310_TVDelayCompensation_651301LV[] = /* M650, 651, 301LV */
+static const unsigned char SiS310_TVDelayCompensation_651301LV[] = /* M650, 651, 301LV */
{
- 0x33,0x33,
- 0x33,0x33,
- 0x33,0x33
+ 0x33,0x33,
+ 0x33,0x33,
+ 0x33,0x33
};
-static const UCHAR SiS310_TVDelayCompensation_651302LV[] = /* M650, 651, 302LV */
+static const unsigned char SiS310_TVDelayCompensation_651302LV[] = /* M650, 651, 302LV */
{
- 0x33,0x33,
- 0x33,0x33,
- 0x33,0x33
+ 0x33,0x33,
+ 0x33,0x33,
+ 0x33,0x33
};
-static const UCHAR SiS_TVDelay661_301[] = /* 661, 301 */
+static const unsigned char SiS_TVDelay661_301[] = /* 661, 301 */
{
- 0x44,0x44,
- 0x44,0x44,
- 0x00,0x00,
- 0x44,0x44,
- 0x44,0x44,
- 0x44,0x44
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x00,0x00,
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x44,0x44
};
-static const UCHAR SiS_TVDelay661_301B[] = /* 661, 301B et al */
+static const unsigned char SiS_TVDelay661_301B[] = /* 661, 301B et al */
{
- 0x44,0x44,
- 0x44,0x44,
- 0x00,0x00,
- 0x44,0x44,
- 0x44,0x44,
- 0x44,0x44
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x00,0x00,
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x44,0x44
};
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] = /* LVDS */
+static const unsigned char SiS310_TVDelayCompensation_LVDS[] = /* LVDS */
{
- 0x0a,0x0a,
- 0x0a,0x0a,
- 0x0a,0x0a
+ 0x0a,0x0a,
+ 0x0a,0x0a,
+ 0x0a,0x0a
};
-static const UCHAR SiS310_TVAntiFlick1[6][2] =
+static const unsigned char SiS310_TVAntiFlick1[6][2] =
{
- {0x4,0x0},
- {0x4,0x8},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0}
+ {0x4,0x0},
+ {0x4,0x8},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0}
};
-static const UCHAR SiS310_TVEdge1[6][2] =
+static const unsigned char SiS310_TVEdge1[6][2] =
{
- {0x0,0x4},
- {0x0,0x4},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0}
+ {0x0,0x4},
+ {0x0,0x4},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0}
};
-static const UCHAR SiS310_TVYFilter1[5][8][4] =
+static const unsigned char SiS310_TVYFilter1[5][8][4] =
{
- {
+ {
{0x00,0xf4,0x10,0x38}, /* NTSC */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x25,0x18},
@@ -258,8 +258,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xee,0x0c,0x22,0x08},
{0xeb,0x15,0x25,0xf6}
- },
- {
+ },
+ {
{0x00,0xf4,0x10,0x38}, /* PAL */
{0x00,0xf4,0x10,0x38},
{0xf1,0xf7,0x1f,0x32},
@@ -268,8 +268,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xf1,0xf7,0x1f,0x32},
{0xf3,0x00,0x1d,0x20},
{0xfc,0xfb,0x14,0x2a}
- },
- {
+ },
+ {
{0x00,0x00,0x00,0x00}, /* HiVision */
{0x00,0xf4,0x10,0x38},
{0x00,0xf4,0x10,0x38},
@@ -278,9 +278,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x25,0x18},
{0xee,0x0c,0x22,0x08}
- },
- {
- {0x00,0xf4,0x10,0x38}, /* PAL-M */
+ },
+ {
+ {0x00,0xf4,0x10,0x38}, /* PAL-M */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x10,0x18},
{0xf7,0x06,0x19,0x14},
@@ -288,9 +288,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xeb,0x04,0x25,0x18},
{0xeb,0x15,0x25,0xf6}
- },
- {
- {0x00,0xf4,0x10,0x38}, /* PAL-N */
+ },
+ {
+ {0x00,0xf4,0x10,0x38}, /* PAL-N */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x10,0x18},
{0xf7,0x06,0x19,0x14},
@@ -298,12 +298,12 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xeb,0x04,0x25,0x18},
{0xeb,0x15,0x25,0xf6}
- }
+ }
};
-static const UCHAR SiS310_TVYFilter2[5][9][7] =
+static const unsigned char SiS310_TVYFilter2[5][9][7] =
{
- {
+ {
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* NTSC */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -313,8 +313,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
+ },
+ {
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -324,8 +324,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
+ },
+ {
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, /* HiVision */
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
@@ -335,9 +335,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}
- },
- {
- {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-M */
+ },
+ {
+ {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-M */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -346,9 +346,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
- {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-N */
+ },
+ {
+ {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-N */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -357,58 +357,39 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- }
+ }
};
-static const UCHAR SiS310_TVPhaseIncr1[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr1[3][2][4] =
{
- {
+ {
{0x21,0xed,0xba,0x08},
{0x21,0xed,0xba,0x08}
- },
- {
+ },
+ {
{0x2a,0x05,0xe3,0x00},
{0x2a,0x05,0xe3,0x00}
- },
- {
+ },
+ {
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
- }
+ }
};
-static const UCHAR SiS310_TVPhaseIncr2[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr2[3][2][4] =
{
- {
+ {
{0x21,0xf0,0x7b,0xd6},
{0x21,0xf0,0x7b,0xd6}
- },
- {
+ },
+ {
{0x2a,0x0a,0x41,0xe9},
{0x2a,0x0a,0x41,0xe9}
- },
- {
+ },
+ {
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
- }
-};
-
-static const UCHAR SiS661_TVPhase[] = {
- 0x21,0xED,0xBA,0x08,
- 0x2A,0x05,0xE3,0x00,
- 0x21,0xE4,0x2E,0x9B,
- 0x21,0xF4,0x3E,0xBA,
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x21,0xF0,0x7B,0xD6,
- 0x2A,0x09,0x86,0xE9,
- 0x21,0xE6,0xEF,0xA4,
- 0x21,0xF6,0x94,0x46,
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00
+ }
};
/**************************************************************/
@@ -417,7 +398,7 @@ static const UCHAR SiS661_TVPhase[] = {
/* Inventec / Compaq Presario 3045US, 3017 */
-static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtCompaq1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -431,17 +412,17 @@ static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] =
/* Asus A2xxxH _2 */
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_Asus1024x768_3[] =
{
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
};
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
index 15939b057713..841ca3190cd4 100644
--- a/drivers/video/sis/osdef.h
+++ b/drivers/video/sis/osdef.h
@@ -3,7 +3,7 @@
/*
* OS depending defines
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -55,8 +55,11 @@
#define _SIS_OSDEF_H_
/* The choices are: */
-#define LINUX_KERNEL /* Linux kernel framebuffer */
-/* #define LINUX_XF86 */ /* XFree86/X.org */
+#define SIS_LINUX_KERNEL /* Linux kernel framebuffer */
+#undef SIS_XORG_XF86 /* XFree86/X.org */
+
+#undef SIS_LINUX_KERNEL_24
+#undef SIS_LINUX_KERNEL_26
#ifdef OutPortByte
#undef OutPortByte
@@ -86,8 +89,9 @@
/* LINUX KERNEL */
/**********************************************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include <linux/config.h>
+#include <linux/version.h>
#ifdef CONFIG_FB_SIS_300
#define SIS300
@@ -97,6 +101,12 @@
#define SIS315H
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define SIS_LINUX_KERNEL_26
+#else
+#define SIS_LINUX_KERNEL_24
+#endif
+
#if !defined(SIS300) && !defined(SIS315H)
#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
#warning sisfb will not work!
@@ -109,13 +119,15 @@
#define InPortWord(p) inw((SISIOADDRESS)(p))
#define InPortLong(p) inl((SISIOADDRESS)(p))
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* LINUX_KERNEL */
/**********************************************************************/
/* XFree86/X.org */
/**********************************************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
+
#define SIS300
#define SIS315H
@@ -126,6 +138,7 @@
#define InPortWord(p) inSISREGW((IOADDRESS)(p))
#define InPortLong(p) inSISREGL((IOADDRESS)(p))
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* XF86 */
#endif /* _OSDEF_H_ */
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d0103c162e43..0b6e625d7331 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -1,8 +1,10 @@
/*
- * SiS 300/630/730/540/315/550/[M]650/651/[M]661[FM]X/740/[M]741[GX]/330/[M]760[GX]
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]661[F|M]X/740/[M]741[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,8 +21,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
-#ifndef _SIS_H
-#define _SIS_H
+#ifndef _SIS_H_
+#define _SIS_H_
#include <linux/config.h>
#include <linux/version.h>
@@ -35,26 +37,37 @@
#include "vgatypes.h"
#include "vstruct.h"
-#define VER_MAJOR 1
-#define VER_MINOR 7
-#define VER_LEVEL 17
-
-#undef SIS_CONFIG_COMPAT
+#define VER_MAJOR 1
+#define VER_MINOR 8
+#define VER_LEVEL 9
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#include <linux/spinlock.h>
+#define SIS_PCI_GET_CLASS(a, b) pci_get_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_get_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_get_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a) pci_dev_put(a)
#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
#include <linux/ioctl32.h>
-#define SIS_CONFIG_COMPAT
-#endif
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
-#ifdef __x86_64__
-/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#define SIS_OLD_CONFIG_COMPAT
+#else
+#include <linux/smp_lock.h>
+#define SIS_NEW_CONFIG_COMPAT
+#endif
+#endif /* CONFIG_COMPAT */
+#else /* 2.4 */
+#define SIS_PCI_GET_CLASS(a, b) pci_find_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_find_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_find_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__ /* Shouldn't we check for CONFIG_IA32_EMULATION here? */
#include <asm/ioctl32.h>
-#define SIS_CONFIG_COMPAT
+#define SIS_OLD_CONFIG_COMPAT
#endif
#endif
-
+#endif /* 2.4 */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
#define SIS_IOTYPE1 void __iomem
#define SIS_IOTYPE2 __iomem
@@ -79,228 +92,312 @@
/* To be included in pci_ids.h */
#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA 0x6325
+#define PCI_DEVICE_ID_SI_650_VGA 0x6325
#endif
#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650 0x0650
+#define PCI_DEVICE_ID_SI_650 0x0650
#endif
#ifndef PCI_DEVICE_ID_SI_651
-#define PCI_DEVICE_ID_SI_651 0x0651
+#define PCI_DEVICE_ID_SI_651 0x0651
#endif
#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740 0x0740
+#define PCI_DEVICE_ID_SI_740 0x0740
#endif
#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330 0x0330
+#define PCI_DEVICE_ID_SI_330 0x0330
#endif
#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA 0x6330
+#define PCI_DEVICE_ID_SI_660_VGA 0x6330
#endif
#ifndef PCI_DEVICE_ID_SI_661
-#define PCI_DEVICE_ID_SI_661 0x0661
+#define PCI_DEVICE_ID_SI_661 0x0661
#endif
#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741 0x0741
+#define PCI_DEVICE_ID_SI_741 0x0741
#endif
#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660 0x0660
+#define PCI_DEVICE_ID_SI_660 0x0660
#endif
#ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760 0x0760
+#define PCI_DEVICE_ID_SI_760 0x0760
+#endif
+#ifndef PCI_DEVICE_ID_SI_761
+#define PCI_DEVICE_ID_SI_761 0x0761
+#endif
+
+#ifndef PCI_VENDOR_ID_XGI
+#define PCI_VENDOR_ID_XGI 0x18ca
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_20
+#define PCI_DEVICE_ID_XGI_20 0x0020
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_40
+#define PCI_DEVICE_ID_XGI_40 0x0040
#endif
/* To be included in fb.h */
#ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 65x, 740, 661, 741 */
+#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 65x, 740, 661, 741 */
#endif
#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre"), 760 */
+#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre"), 76x */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_V
+#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari Vx (V3XT, V5, V8) */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_Z
+#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
#endif
-
-#define MAX_ROM_SCAN 0x10000
/* ivideo->caps */
-#define HW_CURSOR_CAP 0x80
-#define TURBO_QUEUE_CAP 0x40
-#define AGP_CMD_QUEUE_CAP 0x20
-#define VM_CMD_QUEUE_CAP 0x10
-#define MMIO_CMD_QUEUE_CAP 0x08
+#define HW_CURSOR_CAP 0x80
+#define TURBO_QUEUE_CAP 0x40
+#define AGP_CMD_QUEUE_CAP 0x20
+#define VM_CMD_QUEUE_CAP 0x10
+#define MMIO_CMD_QUEUE_CAP 0x08
/* For 300 series */
-#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */
+#define TURBO_QUEUE_AREA_SIZE (512 * 1024) /* 512K */
+#define HW_CURSOR_AREA_SIZE_300 4096 /* 4K */
/* For 315/Xabre series */
-#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD 0x1F
-#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */
-
-#define SIS_OH_ALLOC_SIZE 4000
-#define SENTINEL 0x7fffffff
-
-#define SEQ_ADR 0x14
-#define SEQ_DATA 0x15
-#define DAC_ADR 0x18
-#define DAC_DATA 0x19
-#define CRTC_ADR 0x24
-#define CRTC_DATA 0x25
-#define DAC2_ADR (0x16-0x30)
-#define DAC2_DATA (0x17-0x30)
-#define VB_PART1_ADR (0x04-0x30)
-#define VB_PART1_DATA (0x05-0x30)
-#define VB_PART2_ADR (0x10-0x30)
-#define VB_PART2_DATA (0x11-0x30)
-#define VB_PART3_ADR (0x12-0x30)
-#define VB_PART3_DATA (0x13-0x30)
-#define VB_PART4_ADR (0x14-0x30)
-#define VB_PART4_DATA (0x15-0x30)
-
-#define SISSR ivideo->SiS_Pr.SiS_P3c4
-#define SISCR ivideo->SiS_Pr.SiS_P3d4
-#define SISDACA ivideo->SiS_Pr.SiS_P3c8
-#define SISDACD ivideo->SiS_Pr.SiS_P3c9
-#define SISPART1 ivideo->SiS_Pr.SiS_Part1Port
-#define SISPART2 ivideo->SiS_Pr.SiS_Part2Port
-#define SISPART3 ivideo->SiS_Pr.SiS_Part3Port
-#define SISPART4 ivideo->SiS_Pr.SiS_Part4Port
-#define SISPART5 ivideo->SiS_Pr.SiS_Part5Port
-#define SISDAC2A SISPART5
-#define SISDAC2D (SISPART5 + 1)
-#define SISMISCR (ivideo->SiS_Pr.RelIO + 0x1c)
-#define SISMISCW ivideo->SiS_Pr.SiS_P3c2
-#define SISINPSTAT (ivideo->SiS_Pr.RelIO + 0x2a)
-#define SISPEL ivideo->SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD 0x05 /* SRs */
-#define IND_SIS_COLOR_MODE 0x06
-#define IND_SIS_RAMDAC_CONTROL 0x07
-#define IND_SIS_DRAM_SIZE 0x14
-#define IND_SIS_MODULE_ENABLE 0x1E
-#define IND_SIS_PCI_ADDRESS_SET 0x20
-#define IND_SIS_TURBOQUEUE_ADR 0x26
-#define IND_SIS_TURBOQUEUE_SET 0x27
-#define IND_SIS_POWER_ON_TRAP 0x38
-#define IND_SIS_POWER_ON_TRAP2 0x39
-#define IND_SIS_CMDQUEUE_SET 0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
-
-#define IND_SIS_AGP_IO_PAD 0x48
-
-#define SIS_CRT2_WENABLE_300 0x24 /* Part1 */
-#define SIS_CRT2_WENABLE_315 0x2F
-
-#define SIS_PASSWORD 0x86 /* SR05 */
-
-#define SIS_INTERLACED_MODE 0x20 /* SR06 */
-#define SIS_8BPP_COLOR_MODE 0x0
-#define SIS_15BPP_COLOR_MODE 0x1
-#define SIS_16BPP_COLOR_MODE 0x2
-#define SIS_32BPP_COLOR_MODE 0x4
-
-#define SIS_ENABLE_2D 0x40 /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
-#define SIS_PCI_ADDR_ENABLE 0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330 series SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
-#define SIS_MMIO_CMD_ENABLE 0x20
-#define SIS_CMD_QUEUE_SIZE_512k 0x00
-#define SIS_CMD_QUEUE_SIZE_1M 0x04
-#define SIS_CMD_QUEUE_SIZE_2M 0x08
-#define SIS_CMD_QUEUE_SIZE_4M 0x0C
-#define SIS_CMD_QUEUE_RESET 0x01
-#define SIS_CMD_AUTO_CORR 0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
-#define SIS_MODE_SELECT_CRT2 0x02
-#define SIS_VB_OUTPUT_COMPOSITE 0x04
-#define SIS_VB_OUTPUT_SVIDEO 0x08
-#define SIS_VB_OUTPUT_SCART 0x10
-#define SIS_VB_OUTPUT_LCD 0x20
-#define SIS_VB_OUTPUT_CRT2 0x40
-#define SIS_VB_OUTPUT_HIVISION 0x80
-
-#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */
-#define SIS_DRIVER_MODE 0x40
-
-#define SIS_VB_COMPOSITE 0x01 /* CR32 */
-#define SIS_VB_SVIDEO 0x02
-#define SIS_VB_SCART 0x04
-#define SIS_VB_LCD 0x08
-#define SIS_VB_CRT2 0x10
-#define SIS_CRT1 0x20
-#define SIS_VB_HIVISION 0x40
-#define SIS_VB_YPBPR 0x80
-#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
- SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
-
-#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301 0x01 /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS 0x02
-#define SIS_EXTERNAL_CHIP_TRUMPION 0x03
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04
-#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05
-#define SIS310_EXTERNAL_CHIP_LVDS 0x02
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
-
-#define SIS_AGP_2X 0x20 /* CR48 */
-
-#define HW_DEVICE_EXTENSION SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION PSIS_HW_INFO
+#define COMMAND_QUEUE_AREA_SIZE (512 * 1024) /* 512K */
+#define COMMAND_QUEUE_AREA_SIZE_Z7 (128 * 1024) /* 128k for XGI Z7 */
+#define HW_CURSOR_AREA_SIZE_315 16384 /* 16K */
+#define COMMAND_QUEUE_THRESHOLD 0x1F
+
+#define SIS_OH_ALLOC_SIZE 4000
+#define SENTINEL 0x7fffffff
+
+#define SEQ_ADR 0x14
+#define SEQ_DATA 0x15
+#define DAC_ADR 0x18
+#define DAC_DATA 0x19
+#define CRTC_ADR 0x24
+#define CRTC_DATA 0x25
+#define DAC2_ADR (0x16-0x30)
+#define DAC2_DATA (0x17-0x30)
+#define VB_PART1_ADR (0x04-0x30)
+#define VB_PART1_DATA (0x05-0x30)
+#define VB_PART2_ADR (0x10-0x30)
+#define VB_PART2_DATA (0x11-0x30)
+#define VB_PART3_ADR (0x12-0x30)
+#define VB_PART3_DATA (0x13-0x30)
+#define VB_PART4_ADR (0x14-0x30)
+#define VB_PART4_DATA (0x15-0x30)
+
+#define SISSR ivideo->SiS_Pr.SiS_P3c4
+#define SISCR ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1 ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2 ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3 ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4 ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5 ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A SISPART5
+#define SISDAC2D (SISPART5 + 1)
+#define SISMISCR (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL ivideo->SiS_Pr.SiS_P3c6
+#define SISVGAENABLE (ivideo->SiS_Pr.RelIO + 0x13)
+#define SISVID (ivideo->SiS_Pr.RelIO + 0x02 - 0x30)
+#define SISCAP (ivideo->SiS_Pr.RelIO + 0x00 - 0x30)
+
+#define IND_SIS_PASSWORD 0x05 /* SRs */
+#define IND_SIS_COLOR_MODE 0x06
+#define IND_SIS_RAMDAC_CONTROL 0x07
+#define IND_SIS_DRAM_SIZE 0x14
+#define IND_SIS_MODULE_ENABLE 0x1E
+#define IND_SIS_PCI_ADDRESS_SET 0x20
+#define IND_SIS_TURBOQUEUE_ADR 0x26
+#define IND_SIS_TURBOQUEUE_SET 0x27
+#define IND_SIS_POWER_ON_TRAP 0x38
+#define IND_SIS_POWER_ON_TRAP2 0x39
+#define IND_SIS_CMDQUEUE_SET 0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
+
+#define IND_SIS_AGP_IO_PAD 0x48
+
+#define SIS_CRT2_WENABLE_300 0x24 /* Part1 */
+#define SIS_CRT2_WENABLE_315 0x2F
+
+#define SIS_PASSWORD 0x86 /* SR05 */
+
+#define SIS_INTERLACED_MODE 0x20 /* SR06 */
+#define SIS_8BPP_COLOR_MODE 0x0
+#define SIS_15BPP_COLOR_MODE 0x1
+#define SIS_16BPP_COLOR_MODE 0x2
+#define SIS_32BPP_COLOR_MODE 0x4
+
+#define SIS_ENABLE_2D 0x40 /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
+#define SIS_PCI_ADDR_ENABLE 0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330/340 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
+#define SIS_MMIO_CMD_ENABLE 0x20
+#define SIS_CMD_QUEUE_SIZE_512k 0x00
+#define SIS_CMD_QUEUE_SIZE_1M 0x04
+#define SIS_CMD_QUEUE_SIZE_2M 0x08
+#define SIS_CMD_QUEUE_SIZE_4M 0x0C
+#define SIS_CMD_QUEUE_RESET 0x01
+#define SIS_CMD_AUTO_CORR 0x02
+
+#define SIS_CMD_QUEUE_SIZE_Z7_64k 0x00 /* XGI Z7 */
+#define SIS_CMD_QUEUE_SIZE_Z7_128k 0x04
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
+#define SIS_MODE_SELECT_CRT2 0x02
+#define SIS_VB_OUTPUT_COMPOSITE 0x04
+#define SIS_VB_OUTPUT_SVIDEO 0x08
+#define SIS_VB_OUTPUT_SCART 0x10
+#define SIS_VB_OUTPUT_LCD 0x20
+#define SIS_VB_OUTPUT_CRT2 0x40
+#define SIS_VB_OUTPUT_HIVISION 0x80
+
+#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */
+#define SIS_DRIVER_MODE 0x40
+
+#define SIS_VB_COMPOSITE 0x01 /* CR32 */
+#define SIS_VB_SVIDEO 0x02
+#define SIS_VB_SCART 0x04
+#define SIS_VB_LCD 0x08
+#define SIS_VB_CRT2 0x10
+#define SIS_CRT1 0x20
+#define SIS_VB_HIVISION 0x40
+#define SIS_VB_YPBPR 0x80
+#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+ SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301 0x01 /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS 0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION 0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05
+#define SIS310_EXTERNAL_CHIP_LVDS 0x02
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
+
+#define SIS_AGP_2X 0x20 /* CR48 */
+
+/* vbflags, private entries (others in sisfb.h) */
+#define VB_CONEXANT 0x00000800 /* 661 series only */
+#define VB_TRUMPION VB_CONEXANT /* 300 series only */
+#define VB_302ELV 0x00004000
+#define VB_301 0x00100000 /* Video bridge type */
+#define VB_301B 0x00200000
+#define VB_302B 0x00400000
+#define VB_30xBDH 0x00800000 /* 30xB DH version (w/o LCD support) */
+#define VB_LVDS 0x01000000
+#define VB_CHRONTEL 0x02000000
+#define VB_301LV 0x04000000
+#define VB_302LV 0x08000000
+#define VB_301C 0x10000000
+
+#define VB_SISBRIDGE (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
+#define VB_VIDEOBRIDGE (VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
+
+/* vbflags2 (static stuff only!) */
+#define VB2_SISUMC 0x00000001
+#define VB2_301 0x00000002 /* Video bridge type */
+#define VB2_301B 0x00000004
+#define VB2_301C 0x00000008
+#define VB2_307T 0x00000010
+#define VB2_302B 0x00000800
+#define VB2_301LV 0x00001000
+#define VB2_302LV 0x00002000
+#define VB2_302ELV 0x00004000
+#define VB2_307LV 0x00008000
+#define VB2_30xBDH 0x08000000 /* 30xB DH version (w/o LCD support) */
+#define VB2_CONEXANT 0x10000000
+#define VB2_TRUMPION 0x20000000
+#define VB2_LVDS 0x40000000
+#define VB2_CHRONTEL 0x80000000
+
+#define VB2_SISLVDSBRIDGE (VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_SISTMDSBRIDGE (VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+#define VB2_SISBRIDGE (VB2_SISLVDSBRIDGE | VB2_SISTMDSBRIDGE)
+
+#define VB2_SISTMDSLCDABRIDGE (VB2_301C | VB2_307T)
+#define VB2_SISLCDABRIDGE (VB2_SISTMDSLCDABRIDGE | VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+
+#define VB2_SISHIVISIONBRIDGE (VB2_301 | VB2_301B | VB2_302B)
+#define VB2_SISYPBPRBRIDGE (VB2_301C | VB2_307T | VB2_SISLVDSBRIDGE)
+#define VB2_SISYPBPRARBRIDGE (VB2_301C | VB2_307T | VB2_307LV)
+#define VB2_SISTAP4SCALER (VB2_301C | VB2_307T | VB2_302ELV | VB2_307LV)
+#define VB2_SISTVBRIDGE (VB2_SISHIVISIONBRIDGE | VB2_SISYPBPRBRIDGE)
+
+#define VB2_SISVGA2BRIDGE (VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+
+#define VB2_VIDEOBRIDGE (VB2_SISBRIDGE | VB2_LVDS | VB2_CHRONTEL | VB2_CONEXANT)
+
+#define VB2_30xB (VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+#define VB2_30xBLV (VB2_30xB | VB2_SISLVDSBRIDGE)
+#define VB2_30xC (VB2_301C | VB2_307T)
+#define VB2_30xCLV (VB2_301C | VB2_307T | VB2_302ELV| VB2_307LV)
+#define VB2_SISEMIBRIDGE (VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCD162MHZBRIDGE (VB2_301C | VB2_307T)
+#define VB2_LCDOVER1280BRIDGE (VB2_301C | VB2_307T | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCDOVER1600BRIDGE (VB2_307T | VB2_307LV)
+#define VB2_RAMDAC202MHZBRIDGE (VB2_301C | VB2_307T)
/* I/O port access macros */
-#define inSISREG(base) inb(base)
+#define inSISREG(base) inb(base)
-#define outSISREG(base,val) outb(val,base)
+#define outSISREG(base,val) outb(val,base)
#define orSISREG(base,val) \
- do { \
- u8 __Temp = inSISREG(base); \
- outSISREG(base, __Temp | (val)); \
- } while (0)
+ do { \
+ u8 __Temp = inSISREG(base); \
+ outSISREG(base, __Temp | (val));\
+ } while (0)
#define andSISREG(base,val) \
- do { \
- u8 __Temp = inSISREG(base); \
- outSISREG(base, __Temp & (val)); \
- } while (0)
-
-#define inSISIDXREG(base,idx,var) \
- do { \
- outSISREG(base, idx); \
- var = inSISREG((base)+1); \
- } while (0)
-
-#define outSISIDXREG(base,idx,val) \
- do { \
- outSISREG(base, idx); \
- outSISREG((base)+1, val); \
- } while (0)
-
-#define orSISIDXREG(base,idx,val) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = inSISREG((base)+1) | (val); \
- outSISREG((base)+1, __Temp); \
- } while (0)
-
-#define andSISIDXREG(base,idx,and) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = inSISREG((base)+1) & (and); \
- outSISREG((base)+1, __Temp); \
- } while (0)
-
-#define setSISIDXREG(base,idx,and,or) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = (inSISREG((base)+1) & (and)) | (or); \
- outSISREG((base)+1, __Temp); \
- } while (0)
+ do { \
+ u8 __Temp = inSISREG(base); \
+ outSISREG(base, __Temp & (val));\
+ } while (0)
+
+#define inSISIDXREG(base,idx,var) \
+ do { \
+ outSISREG(base, idx); \
+ var = inSISREG((base)+1); \
+ } while (0)
+
+#define outSISIDXREG(base,idx,val) \
+ do { \
+ outSISREG(base, idx); \
+ outSISREG((base)+1, val); \
+ } while (0)
+
+#define orSISIDXREG(base,idx,val) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = inSISREG((base)+1) | (val); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
+
+#define andSISIDXREG(base,idx,and) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = inSISREG((base)+1) & (and); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
+
+#define setSISIDXREG(base,idx,and,or) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = (inSISREG((base)+1) & (and)) | (or); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
/* MMIO access macros */
#define MMIO_IN8(base, offset) readb((base+offset))
@@ -322,19 +419,19 @@
#define MMIO_QUEUE_READPORT Q_READ_PTR
#ifndef FB_BLANK_UNBLANK
-#define FB_BLANK_UNBLANK 0
+#define FB_BLANK_UNBLANK 0
#endif
#ifndef FB_BLANK_NORMAL
-#define FB_BLANK_NORMAL 1
+#define FB_BLANK_NORMAL 1
#endif
#ifndef FB_BLANK_VSYNC_SUSPEND
-#define FB_BLANK_VSYNC_SUSPEND 2
+#define FB_BLANK_VSYNC_SUSPEND 2
#endif
#ifndef FB_BLANK_HSYNC_SUSPEND
-#define FB_BLANK_HSYNC_SUSPEND 3
+#define FB_BLANK_HSYNC_SUSPEND 3
#endif
#ifndef FB_BLANK_POWERDOWN
-#define FB_BLANK_POWERDOWN 4
+#define FB_BLANK_POWERDOWN 4
#endif
enum _SIS_LCD_TYPE {
@@ -347,18 +444,19 @@ enum _SIS_LCD_TYPE {
LCD_1600x1200,
LCD_1920x1440,
LCD_2048x1536,
- LCD_320x480, /* FSTN */
+ LCD_320x240, /* FSTN */
LCD_1400x1050,
LCD_1152x864,
LCD_1152x768,
LCD_1280x768,
LCD_1024x600,
- LCD_640x480_2, /* DSTN */
- LCD_640x480_3, /* DSTN */
+ LCD_320x240_2, /* DSTN */
+ LCD_320x240_3, /* DSTN */
LCD_848x480,
LCD_1280x800,
LCD_1680x1050,
LCD_1280x720,
+ LCD_1280x854,
LCD_CUSTOM,
LCD_UNKNOWN
};
@@ -368,31 +466,50 @@ enum _SIS_CMDTYPE {
AGP_CMD_QUEUE,
VM_CMD_QUEUE,
};
-typedef unsigned int SIS_CMDTYPE;
+
+struct SIS_OH {
+ struct SIS_OH *poh_next;
+ struct SIS_OH *poh_prev;
+ u32 offset;
+ u32 size;
+};
+
+struct SIS_OHALLOC {
+ struct SIS_OHALLOC *poha_next;
+ struct SIS_OH aoh[1];
+};
+
+struct SIS_HEAP {
+ struct SIS_OH oh_free;
+ struct SIS_OH oh_used;
+ struct SIS_OH *poh_freelist;
+ struct SIS_OHALLOC *poha_chain;
+ u32 max_freesize;
+ struct sis_video_info *vinfo;
+};
/* Our "par" */
struct sis_video_info {
int cardnumber;
struct fb_info *memyselfandi;
- SIS_HW_INFO sishw_ext;
- SiS_Private SiS_Pr;
+ struct SiS_Private SiS_Pr;
- sisfb_info sisfbinfo; /* For ioctl SISFB_GET_INFO */
+ struct sisfb_info sisfbinfo; /* For ioctl SISFB_GET_INFO */
struct fb_var_screeninfo default_var;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
struct fb_fix_screeninfo sisfb_fix;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[17];
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- struct display sis_disp;
+ struct display sis_disp;
struct display_switch sisfb_sw;
struct {
u16 red, green, blue, pad;
- } sis_palette[256];
+ } sis_palette[256];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
@@ -400,10 +517,10 @@ struct sis_video_info {
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
- } sis_fbcon_cmap;
+ } sis_fbcon_cmap;
#endif
- struct sisfb_monitor {
+ struct sisfb_monitor {
u16 hmin;
u16 hmax;
u16 vmin;
@@ -411,163 +528,166 @@ struct sis_video_info {
u32 dclockmax;
u8 feature;
BOOLEAN datavalid;
- } sisfb_thismonitor;
+ } sisfb_thismonitor;
- int chip_id;
+ unsigned short chip_id; /* PCI ID of chip */
+ unsigned short chip_vendor; /* PCI ID of vendor */
char myid[40];
struct pci_dev *nbridge;
+ struct pci_dev *lpcdev;
int mni; /* Mode number index */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- int currcon;
+ int currcon;
#endif
unsigned long video_size;
- unsigned long video_base;
+ unsigned long video_base;
unsigned long mmio_size;
- unsigned long mmio_base;
- unsigned long vga_base;
+ unsigned long mmio_base;
+ unsigned long vga_base;
+
+ unsigned long video_offset;
- SIS_IOTYPE1 *video_vbase;
- SIS_IOTYPE1 *mmio_vbase;
+ unsigned long UMAsize, LFBsize;
- unsigned char *bios_abase;
+ SIS_IOTYPE1 *video_vbase;
+ SIS_IOTYPE1 *mmio_vbase;
- int mtrr;
+ unsigned char *bios_abase;
+
+ int mtrr;
u32 sisfb_mem;
- u32 sisfb_parm_mem;
- int sisfb_accel;
- int sisfb_ypan;
- int sisfb_max;
- int sisfb_userom;
- int sisfb_useoem;
+ u32 sisfb_parm_mem;
+ int sisfb_accel;
+ int sisfb_ypan;
+ int sisfb_max;
+ int sisfb_userom;
+ int sisfb_useoem;
int sisfb_mode_idx;
int sisfb_parm_rate;
int sisfb_crt1off;
int sisfb_forcecrt1;
int sisfb_crt2type;
int sisfb_crt2flags;
- int sisfb_dstn;
- int sisfb_fstn;
+ int sisfb_dstn;
+ int sisfb_fstn;
int sisfb_tvplug;
int sisfb_tvstd;
- int sisfb_filter;
int sisfb_nocrt2rate;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
int sisfb_inverse;
#endif
- u32 heapstart; /* offset */
- SIS_IOTYPE1 *sisfb_heap_start; /* address */
- SIS_IOTYPE1 *sisfb_heap_end; /* address */
- u32 sisfb_heap_size;
+ u32 heapstart; /* offset */
+ SIS_IOTYPE1 *sisfb_heap_start; /* address */
+ SIS_IOTYPE1 *sisfb_heap_end; /* address */
+ u32 sisfb_heap_size;
int havenoheap;
-#if 0
- SIS_HEAP sisfb_heap;
-#endif
+ struct SIS_HEAP sisfb_heap; /* This card's vram heap */
- int video_bpp;
- int video_cmap_len;
- int video_width;
- int video_height;
- unsigned int refresh_rate;
+ int video_bpp;
+ int video_cmap_len;
+ int video_width;
+ int video_height;
+ unsigned int refresh_rate;
- unsigned int chip;
- u8 revision_id;
+ unsigned int chip;
+ u8 revision_id;
+ int sisvga_enabled; /* PCI device was enabled */
- int video_linelength; /* real pitch */
+ int video_linelength; /* real pitch */
int scrnpitchCRT1; /* pitch regarding interlace */
- u16 DstColor; /* For 2d acceleration */
- u32 SiS310_AccelDepth;
- u32 CommandReg;
- int cmdqueuelength;
+ u16 DstColor; /* For 2d acceleration */
+ u32 SiS310_AccelDepth;
+ u32 CommandReg;
+ int cmdqueuelength; /* Current (for accel) */
+ u32 cmdQueueSize; /* Total size in KB */
- spinlock_t lockaccel; /* Do not use outside of kernel! */
+ spinlock_t lockaccel; /* Do not use outside of kernel! */
- unsigned int pcibus;
- unsigned int pcislot;
- unsigned int pcifunc;
+ unsigned int pcibus;
+ unsigned int pcislot;
+ unsigned int pcifunc;
- int accel;
+ int accel;
+ int engineok;
- u16 subsysvendor;
- u16 subsysdevice;
+ u16 subsysvendor;
+ u16 subsysdevice;
- u32 vbflags; /* Replacing deprecated stuff from above */
- u32 currentvbflags;
+ u32 vbflags; /* Replacing deprecated stuff from above */
+ u32 currentvbflags;
+ u32 vbflags2;
int lcdxres, lcdyres;
int lcddefmodeidx, tvdefmodeidx, defmodeidx;
- u32 CRT2LCDType; /* defined in "SIS_LCD_TYPE" */
-
- int current_bpp;
- int current_width;
- int current_height;
- int current_htotal;
- int current_vtotal;
+ u32 CRT2LCDType; /* defined in "SIS_LCD_TYPE" */
+ u32 curFSTN, curDSTN;
+
+ int current_bpp;
+ int current_width;
+ int current_height;
+ int current_htotal;
+ int current_vtotal;
int current_linelength;
- __u32 current_pixclock;
- int current_refresh_rate;
+ __u32 current_pixclock;
+ int current_refresh_rate;
+
+ unsigned int current_base;
- u8 mode_no;
- u8 rate_idx;
- int modechanged;
- unsigned char modeprechange;
+ u8 mode_no;
+ u8 rate_idx;
+ int modechanged;
+ unsigned char modeprechange;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- u8 sisfb_lastrates[128];
+ u8 sisfb_lastrates[128];
#endif
- int newrom;
- int registered;
+ int newrom;
+ int haveXGIROM;
+ int registered;
int warncount;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ int ioctl32registered;
+#endif
- int sisvga_engine;
- int hwcursor_size;
- int CRT2_write_enable;
- u8 caps;
+ int sisvga_engine;
+ int hwcursor_size;
+ int CRT2_write_enable;
+ u8 caps;
- u8 detectedpdc;
- u8 detectedpdca;
- u8 detectedlcda;
+ u8 detectedpdc;
+ u8 detectedpdca;
+ u8 detectedlcda;
- SIS_IOTYPE1 *hwcursor_vbase;
+ SIS_IOTYPE1 *hwcursor_vbase;
- int chronteltype;
- int tvxpos, tvypos;
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+ int chronteltype;
+ int tvxpos, tvypos;
+ u8 p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
int tvx, tvy;
- u8 sisfblocked;
+ u8 sisfblocked;
+
+ struct sisfb_info sisfb_infoblock;
+
+ struct sisfb_cmd sisfb_command;
+
+ u32 sisfb_id;
+
+ u8 sisfb_can_post;
+ u8 sisfb_card_posted;
+ u8 sisfb_was_boot_device;
struct sis_video_info *next;
};
-typedef struct _SIS_OH {
- struct _SIS_OH *poh_next;
- struct _SIS_OH *poh_prev;
- u32 offset;
- u32 size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
- struct _SIS_OHALLOC *poha_next;
- SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
- SIS_OH oh_free;
- SIS_OH oh_used;
- SIS_OH *poh_freelist;
- SIS_OHALLOC *poha_chain;
- u32 max_freesize;
- struct sis_video_info *vinfo;
-} SIS_HEAP;
-
#endif
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 30e90a553e80..bab933e6c6a6 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -1,6 +1,8 @@
/*
- * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver
- * for Linux kernels 2.4.x and 2.6.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
* 2D acceleration part
*
@@ -19,7 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
* Based on the XFree86/X.org driver which is
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
* (see http://www.winischhofer.net/
@@ -30,13 +32,11 @@
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/errno.h>
#include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/console.h>
-#include <linux/selection.h>
+#endif
#include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
#include <linux/types.h>
#include <asm/io.h>
@@ -188,7 +188,7 @@ SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
}
#endif
-/* 315/330 series ------------------------------------------------- */
+/* 315/330/340 series ---------------------------------------------- */
#ifdef CONFIG_FB_SIS_315
static void
@@ -202,7 +202,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
{
SiS310SetupDSTColorDepth(ivideo->DstColor);
SiS310SetupSRCPitch(ivideo->video_linelength)
- SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+ SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
if(trans_color != -1) {
SiS310SetupROP(0x0A)
SiS310SetupSRCTrans(trans_color)
@@ -213,7 +213,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
}
SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
- /* The 315 series is smart enough to know the direction */
+ /* The chip is smart enough to know the direction */
}
static void
@@ -223,35 +223,38 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int
u32 srcbase = 0, dstbase = 0;
int mymin = min(src_y, dst_y);
int mymax = max(src_y, dst_y);
-
+
/* Although the chip knows the direction to use
- * if the source and destination areas overlap,
+ * if the source and destination areas overlap,
* that logic fails if we fiddle with the bitmap
* addresses. Therefore, we check if the source
- * and destination blitting areas overlap and
- * adapt the bitmap addresses synchronously
+ * and destination blitting areas overlap and
+ * adapt the bitmap addresses synchronously
* if the coordinates exceed the valid range.
- * The the areas do not overlap, we do our
+ * The the areas do not overlap, we do our
* normal check.
*/
- if((mymax - mymin) < height) {
- if((src_y >= 2048) || (dst_y >= 2048)) {
- srcbase = ivideo->video_linelength * mymin;
- dstbase = ivideo->video_linelength * mymin;
- src_y -= mymin;
- dst_y -= mymin;
- }
+ if((mymax - mymin) < height) {
+ if((src_y >= 2048) || (dst_y >= 2048)) {
+ srcbase = ivideo->video_linelength * mymin;
+ dstbase = ivideo->video_linelength * mymin;
+ src_y -= mymin;
+ dst_y -= mymin;
+ }
} else {
- if(src_y >= 2048) {
- srcbase = ivideo->video_linelength * src_y;
- src_y = 0;
- }
- if(dst_y >= 2048) {
- dstbase = ivideo->video_linelength * dst_y;
- dst_y = 0;
- }
+ if(src_y >= 2048) {
+ srcbase = ivideo->video_linelength * src_y;
+ src_y = 0;
+ }
+ if(dst_y >= 2048) {
+ dstbase = ivideo->video_linelength * dst_y;
+ dst_y = 0;
+ }
}
+ srcbase += ivideo->video_offset;
+ dstbase += ivideo->video_offset;
+
SiS310SetupSRCBase(srcbase);
SiS310SetupDSTBase(dstbase);
SiS310SetupRect(width, height)
@@ -264,7 +267,7 @@ static void
SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
{
SiS310SetupPATFG(color)
- SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+ SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
SiS310SetupDSTColorDepth(ivideo->DstColor);
SiS310SetupROP(sisPatALUConv[rop])
SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
@@ -279,6 +282,7 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
dstbase = ivideo->video_linelength * y;
y = 0;
}
+ dstbase += ivideo->video_offset;
SiS310SetupDSTBase(dstbase)
SiS310SetupDSTXY(x,y)
SiS310SetupRect(w,h)
@@ -294,384 +298,153 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
int sisfb_initaccel(struct sis_video_info *ivideo)
{
#ifdef SISFB_USE_SPINLOCKS
- spin_lock_init(&ivideo->lockaccel);
+ spin_lock_init(&ivideo->lockaccel);
#endif
- return(0);
+ return 0;
}
void sisfb_syncaccel(struct sis_video_info *ivideo)
{
- if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- SiS300Sync(ivideo);
+ SiS300Sync(ivideo);
#endif
- } else {
+ } else {
#ifdef CONFIG_FB_SIS_315
- SiS310Sync(ivideo);
+ SiS310Sync(ivideo);
#endif
- }
+ }
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */
int fbcon_sis_sync(struct fb_info *info)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- CRITFLAGS
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ CRITFLAGS
- if(!ivideo->accel)
- return 0;
+ if((!ivideo->accel) || (!ivideo->engineok))
+ return 0;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- SiS310Sync(ivideo);
-#endif
- }
- CRITEND
- return 0;
+ CRITBEGIN
+ sisfb_syncaccel(ivideo);
+ CRITEND
+
+ return 0;
}
void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- u32 col = 0;
- u32 vxres = info->var.xres_virtual;
- u32 vyres = info->var.yres_virtual;
- int width, height;
- CRITFLAGS
-
- if(info->state != FBINFO_STATE_RUNNING) {
- return;
- }
-
- if(!ivideo->accel) {
- cfb_fillrect(info, rect);
- return;
- }
-
- if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
- return;
- }
-
- /* Clipping */
- width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
- height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
-
- switch(info->var.bits_per_pixel) {
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ u32 col = 0;
+ u32 vxres = info->var.xres_virtual;
+ u32 vyres = info->var.yres_virtual;
+ int width, height;
+ CRITFLAGS
+
+ if(info->state != FBINFO_STATE_RUNNING)
+ return;
+
+ if((!ivideo->accel) || (!ivideo->engineok)) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
+ return;
+
+ /* Clipping */
+ width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+ height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
+ switch(info->var.bits_per_pixel) {
case 8: col = rect->color;
break;
case 16:
case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
break;
- }
+ }
- if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
- SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
- CRITEND
- SiS300Sync(ivideo);
+ CRITBEGIN
+ SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+ SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+ CRITEND
#endif
- } else {
+ } else {
#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
- SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
- CRITEND
- SiS310Sync(ivideo);
+ CRITBEGIN
+ SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+ SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+ CRITEND
#endif
- }
+ }
+ sisfb_syncaccel(ivideo);
}
void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- u32 vxres = info->var.xres_virtual;
- u32 vyres = info->var.yres_virtual;
- int width = area->width;
- int height = area->height;
- CRITFLAGS
-
- if(info->state != FBINFO_STATE_RUNNING) {
- return;
- }
-
- if(!ivideo->accel) {
- cfb_copyarea(info, area);
- return;
- }
-
- if(!width || !height ||
- area->sx >= vxres || area->sy >= vyres ||
- area->dx >= vxres || area->dy >= vyres) {
- return;
- }
-
- /* Clipping */
- if((area->sx + width) > vxres) width = vxres - area->sx;
- if((area->dx + width) > vxres) width = vxres - area->dx;
- if((area->sy + height) > vyres) height = vyres - area->sy;
- if((area->dy + height) > vyres) height = vyres - area->dy;
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- int xdir, ydir;
-
- if(area->sx < area->dx) xdir = 0;
- else xdir = 1;
- if(area->sy < area->dy) ydir = 0;
- else ydir = 1;
-
- CRITBEGIN
- SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
- SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
- width, height);
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
- SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
- width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
-
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */
-
-void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
- int dsty, int dstx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ u32 vxres = info->var.xres_virtual;
+ u32 vyres = info->var.yres_virtual;
+ int width = area->width;
+ int height = area->height;
CRITFLAGS
- if(!ivideo->accel) {
- switch(ivideo->video_bpp) {
- case 8:
-#ifdef FBCON_HAS_CFB8
- fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- case 16:
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- case 32:
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- }
- return;
- }
-
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
- dstx *= fontwidth(p);
- dsty *= fontheight(p);
- width *= fontwidth(p);
- height *= fontheight(p);
+ if(info->state != FBINFO_STATE_RUNNING)
+ return;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- int xdir, ydir;
-
- if(srcx < dstx) xdir = 0;
- else xdir = 1;
- if(srcy < dsty) ydir = 0;
- else ydir = 1;
-
- CRITBEGIN
- SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
- SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
- SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
+ if((!ivideo->accel) || (!ivideo->engineok)) {
+ cfb_copyarea(info, area);
+ return;
}
-}
-static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width, int color)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- CRITFLAGS
+ if(!width || !height ||
+ area->sx >= vxres || area->sy >= vyres ||
+ area->dx >= vxres || area->dy >= vyres)
+ return;
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
- width *= fontwidth(p);
- height *= fontheight(p);
+ /* Clipping */
+ if((area->sx + width) > vxres) width = vxres - area->sx;
+ if((area->dx + width) > vxres) width = vxres - area->dx;
+ if((area->sy + height) > vyres) height = vyres - area->sy;
+ if((area->dy + height) > vyres) height = vyres - area->dy;
if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, color, 3);
- SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
- CRITEND
- SiS300Sync(ivideo);
+ int xdir, ydir;
+
+ if(area->sx < area->dx) xdir = 0;
+ else xdir = 1;
+ if(area->sy < area->dy) ydir = 0;
+ else ydir = 1;
+
+ CRITBEGIN
+ SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+ SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+ area->dx, area->dy, width, height);
+ CRITEND
#endif
} else {
#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, color, 3);
- SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
-
-void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB8
- fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+ CRITBEGIN
+ SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+ SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+ area->dx, area->dy, width, height);
+ CRITEND
#endif
- return;
}
- bgx = attr_bgcol_ec(p, conp);
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
+ sisfb_syncaccel(ivideo);
}
-void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
#endif
- return;
- }
-
- bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
-#endif
- return;
- }
-
- bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-
-void fbcon_sis_revc(struct display *p, int srcx, int srcy)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- CRITFLAGS
-
- if(!ivideo->accel) {
- switch(ivideo->video_bpp) {
- case 16:
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_revc(p, srcx, srcy);
-#endif
- break;
- case 32:
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_revc(p, srcx, srcy);
-#endif
- break;
- }
- return;
- }
-
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, 0, 0x0a);
- SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, 0, 0x0a);
- SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */
-#ifdef FBCON_HAS_CFB8
-struct display_switch fbcon_sis8 = {
- .setup = fbcon_cfb8_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear8,
- .putc = fbcon_cfb8_putc,
- .putcs = fbcon_cfb8_putcs,
- .revc = fbcon_cfb8_revc,
- .clear_margins = fbcon_cfb8_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB16
-struct display_switch fbcon_sis16 = {
- .setup = fbcon_cfb16_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear16,
- .putc = fbcon_cfb16_putc,
- .putcs = fbcon_cfb16_putcs,
- .revc = fbcon_sis_revc,
- .clear_margins = fbcon_cfb16_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB32
-struct display_switch fbcon_sis32 = {
- .setup = fbcon_cfb32_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear32,
- .putc = fbcon_cfb32_putc,
- .putcs = fbcon_cfb32_putcs,
- .revc = fbcon_sis_revc,
- .clear_margins = fbcon_cfb32_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
+#include "sisfb_accel_2_4.h"
#endif /* KERNEL VERSION */
diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h
index bb28f331d60d..046e2c4a8e09 100644
--- a/drivers/video/sis/sis_accel.h
+++ b/drivers/video/sis/sis_accel.h
@@ -1,6 +1,8 @@
/*
- * SiS 300/630/730/540/315/550/650/740 frame buffer driver
- * for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
* 2D acceleration part
*
@@ -283,6 +285,8 @@
{ \
while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
CmdQueLen = 0; \
}
@@ -402,6 +406,7 @@ void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
int srcx, int height, int width);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+int fbcon_sis_sync(struct fb_info *info);
void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
#endif
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 698266036819..42c54b69726e 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1,9 +1,10 @@
/*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,11 +20,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
*
* Author of (practically wiped) code base:
* SiS (www.sis.com)
- * Copyright (C) 1999 Silicon Integrated Systems, Inc.
+ * Copyright (C) 1999 Silicon Integrated Systems, Inc.
*
* See http://www.winischhofer.net/ for more information and updates
*
@@ -46,16 +47,15 @@
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
-#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
#include <linux/selection.h>
-#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/vt_kern.h>
+#endif
#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/types.h>
@@ -94,71 +94,75 @@ extern struct display_switch fbcon_sis32;
#endif
#endif
+static void sisfb_handle_command(struct sis_video_info *ivideo,
+ struct sisfb_cmd *sisfb_command);
+
/* ------------------ Internal helper routines ----------------- */
static void __init
sisfb_setdefaultparms(void)
{
- sisfb_off = 0;
- sisfb_parm_mem = 0;
- sisfb_accel = -1;
- sisfb_ypan = -1;
- sisfb_max = -1;
- sisfb_userom = -1;
- sisfb_useoem = -1;
+ sisfb_off = 0;
+ sisfb_parm_mem = 0;
+ sisfb_accel = -1;
+ sisfb_ypan = -1;
+ sisfb_max = -1;
+ sisfb_userom = -1;
+ sisfb_useoem = -1;
#ifdef MODULE
/* Module: "None" for 2.4, default mode for 2.5+ */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sisfb_mode_idx = -1;
+ sisfb_mode_idx = -1;
#else
- sisfb_mode_idx = MODE_INDEX_NONE;
+ sisfb_mode_idx = MODE_INDEX_NONE;
#endif
#else
/* Static: Default mode */
- sisfb_mode_idx = -1;
-#endif
- sisfb_parm_rate = -1;
- sisfb_crt1off = 0;
- sisfb_forcecrt1 = -1;
- sisfb_crt2type = -1;
- sisfb_crt2flags = 0;
- sisfb_pdc = 0xff;
- sisfb_pdca = 0xff;
- sisfb_scalelcd = -1;
+ sisfb_mode_idx = -1;
+#endif
+ sisfb_parm_rate = -1;
+ sisfb_crt1off = 0;
+ sisfb_forcecrt1 = -1;
+ sisfb_crt2type = -1;
+ sisfb_crt2flags = 0;
+ sisfb_pdc = 0xff;
+ sisfb_pdca = 0xff;
+ sisfb_scalelcd = -1;
sisfb_specialtiming = CUT_NONE;
- sisfb_lvdshl = -1;
- sisfb_dstn = 0;
- sisfb_fstn = 0;
- sisfb_tvplug = -1;
- sisfb_tvstd = -1;
- sisfb_tvxposoffset = 0;
- sisfb_tvyposoffset = 0;
- sisfb_filter = -1;
- sisfb_nocrt2rate = 0;
+ sisfb_lvdshl = -1;
+ sisfb_dstn = 0;
+ sisfb_fstn = 0;
+ sisfb_tvplug = -1;
+ sisfb_tvstd = -1;
+ sisfb_tvxposoffset = 0;
+ sisfb_tvyposoffset = 0;
+ sisfb_nocrt2rate = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sisfb_inverse = 0;
- sisfb_fontname[0] = 0;
+ sisfb_inverse = 0;
+ sisfb_fontname[0] = 0;
#endif
#if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = 0;
- sisfb_videoram = 0;
+ sisfb_resetcard = 0;
+ sisfb_videoram = 0;
#endif
}
+/* ------------- Parameter parsing -------------- */
+
static void __devinit
sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
{
int i = 0, j = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(vesamode == 0) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
sisfb_mode_idx = MODE_INDEX_NONE;
#else
- if(!quiet) {
- printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
- }
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+
sisfb_mode_idx = DEFAULT_MODE;
#endif
return;
@@ -169,95 +173,102 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
while(sisbios_mode[i++].mode_no[0] != 0) {
if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
(sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
+ if(sisfb_fstn) {
+ if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+ sisbios_mode[i-1].mode_no[1] == 0x56 ||
+ sisbios_mode[i-1].mode_no[1] == 0x53)
+ continue;
+ } else {
+ if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+ sisbios_mode[i-1].mode_no[1] == 0x5b)
+ continue;
+ }
+ sisfb_mode_idx = i - 1;
+ j = 1;
+ break;
}
}
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+ if((!j) && !quiet)
+ printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
}
-static void
+static void __devinit
sisfb_search_mode(char *name, BOOLEAN quiet)
{
- int i = 0;
unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+ int i = 0;
char strbuf[16], strbuf1[20];
char *nameptr = name;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(name == NULL) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+
+ sisfb_mode_idx = DEFAULT_MODE;
+ return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
+ if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+
+ sisfb_mode_idx = DEFAULT_MODE;
+ return;
}
#endif
if(strlen(name) <= 19) {
- strcpy(strbuf1, name);
- for(i=0; i<strlen(strbuf1); i++) {
- if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
- }
+ strcpy(strbuf1, name);
+ for(i = 0; i < strlen(strbuf1); i++) {
+ if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+ }
- /* This does some fuzzy mode naming detection */
- if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
- if((rate <= 32) || (depth > 32)) {
- j = rate; rate = depth; depth = j;
- }
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- sisfb_parm_rate = rate;
- } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- } else {
- xres = 0;
- if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
- sprintf(strbuf, "%ux%ux8", xres, yres);
- nameptr = strbuf;
- } else {
- sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
- return;
- }
- }
+ /* This does some fuzzy mode naming detection */
+ if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+ if((rate <= 32) || (depth > 32)) {
+ j = rate; rate = depth; depth = j;
+ }
+ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+ nameptr = strbuf;
+ sisfb_parm_rate = rate;
+ } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+ nameptr = strbuf;
+ } else {
+ xres = 0;
+ if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+ sprintf(strbuf, "%ux%ux8", xres, yres);
+ nameptr = strbuf;
+ } else {
+ sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+ return;
+ }
+ }
}
i = 0; j = 0;
while(sisbios_mode[i].mode_no[0] != 0) {
if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+ if(sisfb_fstn) {
+ if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+ sisbios_mode[i-1].mode_no[1] == 0x56 ||
+ sisbios_mode[i-1].mode_no[1] == 0x53)
+ continue;
+ } else {
+ if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+ sisbios_mode[i-1].mode_no[1] == 0x5b)
+ continue;
+ }
+ sisfb_mode_idx = i - 1;
+ j = 1;
+ break;
+ }
+ }
+
+ if((!j) && !quiet)
+ printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
}
#ifndef MODULE
@@ -265,7 +276,7 @@ static void __devinit
sisfb_get_vga_mode_from_kernel(void)
{
#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
- char mymode[32];
+ char mymode[32];
int mydepth = screen_info.lfb_depth;
if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
@@ -274,15 +285,17 @@ sisfb_get_vga_mode_from_kernel(void)
(screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
(mydepth >= 8) && (mydepth <= 32) ) {
- if(mydepth == 24) mydepth = 32;
+ if(mydepth == 24) mydepth = 32;
- sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
- screen_info.lfb_height,
+ sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
+ screen_info.lfb_height,
mydepth);
- printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+ printk(KERN_DEBUG
+ "sisfb: Using vga mode %s pre-set by kernel as default\n",
+ mymode);
- sisfb_search_mode(mymode, TRUE);
+ sisfb_search_mode(mymode, TRUE);
}
#endif
return;
@@ -294,26 +307,25 @@ sisfb_search_crt2type(const char *name)
{
int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(name == NULL) return;
while(sis_crt2type[i].type_no != -1) {
- if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
- sisfb_crt2type = sis_crt2type[i].type_no;
- sisfb_tvplug = sis_crt2type[i].tvplug_no;
- sisfb_crt2flags = sis_crt2type[i].flags;
- break;
- }
- i++;
+ if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+ sisfb_crt2type = sis_crt2type[i].type_no;
+ sisfb_tvplug = sis_crt2type[i].tvplug_no;
+ sisfb_crt2flags = sis_crt2type[i].flags;
+ break;
+ }
+ i++;
}
sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
- if(sisfb_crt2type < 0) {
+ if(sisfb_crt2type < 0)
printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
- }
}
static void __init
@@ -321,16 +333,17 @@ sisfb_search_tvstd(const char *name)
{
int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
+ if(name == NULL)
+ return;
while(sis_tvtype[i].type_no != -1) {
- if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
- sisfb_tvstd = sis_tvtype[i].type_no;
- break;
- }
- i++;
+ if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+ sisfb_tvstd = sis_tvtype[i].type_no;
+ break;
+ }
+ i++;
}
}
@@ -340,38 +353,101 @@ sisfb_search_specialtiming(const char *name)
int i = 0;
BOOLEAN found = FALSE;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
+ if(name == NULL)
+ return;
if(!strnicmp(name, "none", 4)) {
- sisfb_specialtiming = CUT_FORCENONE;
+ sisfb_specialtiming = CUT_FORCENONE;
printk(KERN_DEBUG "sisfb: Special timing disabled\n");
} else {
- while(mycustomttable[i].chipID != 0) {
- if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
- sisfb_specialtiming = mycustomttable[i].SpecialID;
- found = TRUE;
- printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
- mycustomttable[i].vendorName, mycustomttable[i].cardName,
- mycustomttable[i].optionName);
- break;
- }
- i++;
- }
- if(!found) {
- printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
- printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
- i = 0;
- while(mycustomttable[i].chipID != 0) {
- printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
- mycustomttable[i].optionName,
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- i++;
- }
- }
- }
+ while(mycustomttable[i].chipID != 0) {
+ if(!strnicmp(name,mycustomttable[i].optionName,
+ strlen(mycustomttable[i].optionName))) {
+ sisfb_specialtiming = mycustomttable[i].SpecialID;
+ found = TRUE;
+ printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName,
+ mycustomttable[i].optionName);
+ break;
+ }
+ i++;
+ }
+ if(!found) {
+ printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+ printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+ i = 0;
+ while(mycustomttable[i].chipID != 0) {
+ printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+ mycustomttable[i].optionName,
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName);
+ i++;
+ }
+ }
+ }
+}
+
+/* ----------- Various detection routines ----------- */
+
+static void __devinit
+sisfb_detect_custom_timing(struct sis_video_info *ivideo)
+{
+ unsigned char *biosver = NULL;
+ unsigned char *biosdate = NULL;
+ BOOLEAN footprint;
+ u32 chksum = 0;
+ int i, j;
+
+ if(ivideo->SiS_Pr.UseROM) {
+ biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
+ biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
+ for(i = 0; i < 32768; i++)
+ chksum += ivideo->SiS_Pr.VirtualRomBase[i];
+ }
+
+ i = 0;
+ do {
+ if( (mycustomttable[i].chipID == ivideo->chip) &&
+ ((!strlen(mycustomttable[i].biosversion)) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (!strncmp(mycustomttable[i].biosversion, biosver,
+ strlen(mycustomttable[i].biosversion))))) &&
+ ((!strlen(mycustomttable[i].biosdate)) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (!strncmp(mycustomttable[i].biosdate, biosdate,
+ strlen(mycustomttable[i].biosdate))))) &&
+ ((!mycustomttable[i].bioschksum) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (mycustomttable[i].bioschksum == chksum))) &&
+ (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+ (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
+ footprint = TRUE;
+ for(j = 0; j < 5; j++) {
+ if(mycustomttable[i].biosFootprintAddr[j]) {
+ if(ivideo->SiS_Pr.UseROM) {
+ if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+ mycustomttable[i].biosFootprintData[j]) {
+ footprint = FALSE;
+ }
+ } else
+ footprint = FALSE;
+ }
+ }
+ if(footprint) {
+ ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+ printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName);
+ printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
+ mycustomttable[i].optionName);
+ break;
+ }
+ }
+ i++;
+ } while(mycustomttable[i].chipID);
}
static BOOLEAN __devinit
@@ -384,22 +460,23 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
buffer[2] != 0xff || buffer[3] != 0xff ||
buffer[4] != 0xff || buffer[5] != 0xff ||
buffer[6] != 0xff || buffer[7] != 0x00) {
- printk(KERN_DEBUG "sisfb: Bad EDID header\n");
- return FALSE;
+ printk(KERN_DEBUG "sisfb: Bad EDID header\n");
+ return FALSE;
}
if(buffer[0x12] != 0x01) {
- printk(KERN_INFO "sisfb: EDID version %d not supported\n",
- buffer[0x12]);
- return FALSE;
+ printk(KERN_INFO "sisfb: EDID version %d not supported\n",
+ buffer[0x12]);
+ return FALSE;
}
monitor->feature = buffer[0x18];
if(!buffer[0x14] & 0x80) {
- if(!(buffer[0x14] & 0x08)) {
- printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n");
- }
+ if(!(buffer[0x14] & 0x08)) {
+ printk(KERN_INFO
+ "sisfb: WARNING: Monitor does not support separate syncs\n");
+ }
}
if(buffer[0x13] >= 0x01) {
@@ -409,7 +486,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
j = 0x36;
for(i=0; i<4; i++) {
if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
- buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
+ buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
buffer[j + 4] == 0x00) {
monitor->hmin = buffer[j + 7];
monitor->hmax = buffer[j + 8];
@@ -435,7 +512,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
for(i = 0; i < 13; i++) {
if(emodes & sisfb_ddcsmodes[i].mask) {
- if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
+ if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
@@ -446,80 +523,81 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
for(i = 0; i < 8; i++) {
xres = (buffer[index] + 31) * 8;
switch(buffer[index + 1] & 0xc0) {
- case 0xc0: yres = (xres * 9) / 16; break;
- case 0x80: yres = (xres * 4) / 5; break;
- case 0x40: yres = (xres * 3) / 4; break;
- default: yres = xres; break;
+ case 0xc0: yres = (xres * 9) / 16; break;
+ case 0x80: yres = (xres * 4) / 5; break;
+ case 0x40: yres = (xres * 3) / 4; break;
+ default: yres = xres; break;
}
refresh = (buffer[index + 1] & 0x3f) + 60;
if((xres >= 640) && (yres >= 480)) {
- for(j = 0; j < 8; j++) {
- if((xres == sisfb_ddcfmodes[j].x) &&
- (yres == sisfb_ddcfmodes[j].y) &&
+ for(j = 0; j < 8; j++) {
+ if((xres == sisfb_ddcfmodes[j].x) &&
+ (yres == sisfb_ddcfmodes[j].y) &&
(refresh == sisfb_ddcfmodes[j].v)) {
if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
- }
- }
+ if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
+ }
+ }
}
index += 2;
- }
+ }
if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
monitor->datavalid = TRUE;
}
}
- return(monitor->datavalid);
+ return monitor->datavalid;
}
static void __devinit
sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
{
- USHORT temp, i, realcrtno = crtno;
- u8 buffer[256];
+ unsigned short temp, i, realcrtno = crtno;
+ unsigned char buffer[256];
monitor->datavalid = FALSE;
if(crtno) {
- if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
- else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
- else return;
- }
+ if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
+ else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
+ else return;
+ }
- if((ivideo->sisfb_crt1off) && (!crtno)) return;
+ if((ivideo->sisfb_crt1off) && (!crtno))
+ return;
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 0, &buffer[0]);
- if((!temp) || (temp == 0xffff)) {
- printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 0, &buffer[0], ivideo->vbflags2);
+ if((!temp) || (temp == 0xffff)) {
+ printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
return;
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
- printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
- crtno + 1,
- (temp & 0x1a) ? "" : "[none of the supported]",
- (temp & 0x02) ? "2 " : "",
- (temp & 0x08) ? "D&P" : "",
- (temp & 0x10) ? "FPDI-2" : "");
- if(temp & 0x02) {
+ } else {
+ printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
+ printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
+ crtno + 1,
+ (temp & 0x1a) ? "" : "[none of the supported]",
+ (temp & 0x02) ? "2 " : "",
+ (temp & 0x08) ? "D&P" : "",
+ (temp & 0x10) ? "FPDI-2" : "");
+ if(temp & 0x02) {
i = 3; /* Number of retrys */
do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 1, &buffer[0]);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 1, &buffer[0], ivideo->vbflags2);
} while((temp) && i--);
- if(!temp) {
- if(sisfb_interpret_edid(monitor, &buffer[0])) {
+ if(!temp) {
+ if(sisfb_interpret_edid(monitor, &buffer[0])) {
printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
- monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
+ monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
monitor->dclockmax / 1000);
} else {
- printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
- }
+ printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
+ }
} else {
- printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
+ printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
}
} else {
printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
@@ -527,6 +605,8 @@ sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, i
}
}
+/* -------------- Mode validation --------------- */
+
static BOOLEAN
sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
int mode_idx, int rate_idx, int rate)
@@ -534,42 +614,49 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
int htotal, vtotal;
unsigned int dclock, hsync;
- if(!monitor->datavalid) return TRUE;
+ if(!monitor->datavalid)
+ return TRUE;
- if(mode_idx < 0) return FALSE;
+ if(mode_idx < 0)
+ return FALSE;
/* Skip for 320x200, 320x240, 640x400 */
- switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
- case 0x59:
- case 0x41:
- case 0x4f:
- case 0x50:
- case 0x56:
- case 0x53:
- case 0x2f:
- case 0x5d:
- case 0x5e:
- return TRUE;
+ switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
+ case 0x59:
+ case 0x41:
+ case 0x4f:
+ case 0x50:
+ case 0x56:
+ case 0x53:
+ case 0x2f:
+ case 0x5d:
+ case 0x5e:
+ return TRUE;
#ifdef CONFIG_FB_SIS_315
case 0x5a:
case 0x5b:
if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
#endif
- }
+ }
- if(rate < (monitor->vmin - 1)) return FALSE;
- if(rate > (monitor->vmax + 1)) return FALSE;
+ if(rate < (monitor->vmin - 1))
+ return FALSE;
+ if(rate > (monitor->vmax + 1))
+ return FALSE;
- if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+ if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
sisbios_mode[mode_idx].mode_no[ivideo->mni],
- &htotal, &vtotal, rate_idx)) {
+ &htotal, &vtotal, rate_idx)) {
dclock = (htotal * vtotal * rate) / 1000;
- if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+ if(dclock > (monitor->dclockmax + 1000))
+ return FALSE;
hsync = dclock / htotal;
- if(hsync < (monitor->hmin - 1)) return FALSE;
- if(hsync > (monitor->hmax + 1)) return FALSE;
+ if(hsync < (monitor->hmin - 1))
+ return FALSE;
+ if(hsync > (monitor->hmax + 1))
+ return FALSE;
} else {
- return FALSE;
+ return FALSE;
}
return TRUE;
}
@@ -577,82 +664,79 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
static int
sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
{
- u16 xres=0, yres, myres;
+ u16 xres=0, yres, myres;
#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
- }
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+ return -1 ;
+ }
#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
- }
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+ return -1;
+ }
#endif
- myres = sisbios_mode[myindex].yres;
-
- switch(vbflags & VB_DISPTYPE_DISP2) {
+ myres = sisbios_mode[myindex].yres;
- case CRT2_LCD:
+ switch(vbflags & VB_DISPTYPE_DISP2) {
- xres = ivideo->lcdxres; yres = ivideo->lcdyres;
+ case CRT2_LCD:
+ xres = ivideo->lcdxres; yres = ivideo->lcdyres;
- if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
- if(sisbios_mode[myindex].xres > xres) return(-1);
- if(myres > yres) return(-1);
- }
+ if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+ (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+ if(sisbios_mode[myindex].xres > xres)
+ return -1;
+ if(myres > yres)
+ return -1;
+ }
- if(vbflags & (VB_LVDS | VB_30xBDH)) {
- if(sisbios_mode[myindex].xres == 320) {
- if((myres == 240) || (myres == 480)) {
- if(!ivideo->sisfb_fstn) {
- if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
- sisbios_mode[myindex].mode_no[1] == 0x5b)
- return(-1);
- } else {
- if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
- sisbios_mode[myindex].mode_no[1] == 0x56 ||
- sisbios_mode[myindex].mode_no[1] == 0x53)
- return(-1);
- }
- }
- }
- }
+ if(ivideo->sisfb_fstn) {
+ if(sisbios_mode[myindex].xres == 320) {
+ if(myres == 240) {
+ switch(sisbios_mode[myindex].mode_no[1]) {
+ case 0x50: myindex = MODE_FSTN_8; break;
+ case 0x56: myindex = MODE_FSTN_16; break;
+ case 0x53: return -1;
+ }
+ }
+ }
+ }
- if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
- ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
- return(-1);
- }
- break;
+ if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
+ ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
- case CRT2_TV:
- if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
- }
- break;
+ case CRT2_TV:
+ if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
- case CRT2_VGA:
- if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
+ case CRT2_VGA:
+ if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
}
- break;
- }
- return(myindex);
+ return myindex;
}
static u8
sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
{
- u16 xres, yres;
int i = 0;
-
- xres = sisbios_mode[mode_idx].xres;
- yres = sisbios_mode[mode_idx].yres;
+ u16 xres = sisbios_mode[mode_idx].xres;
+ u16 yres = sisbios_mode[mode_idx].yres;
ivideo->rate_idx = 0;
while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
@@ -672,14 +756,14 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
rate, sisfb_vrate[i-1].refresh);
ivideo->rate_idx = sisfb_vrate[i-1].idx;
ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
- }
+ }
break;
} else if((rate - sisfb_vrate[i].refresh) <= 2) {
DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- }
+ ivideo->rate_idx = sisfb_vrate[i].idx;
+ break;
+ }
}
i++;
}
@@ -695,252 +779,321 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
static BOOLEAN
sisfb_bridgeisslave(struct sis_video_info *ivideo)
{
- unsigned char P1_00;
+ unsigned char P1_00;
- if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
+ if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
+ return FALSE;
- inSISIDXREG(SISPART1,0x00,P1_00);
- if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
- return TRUE;
- } else {
- return FALSE;
- }
+ inSISIDXREG(SISPART1,0x00,P1_00);
+ if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+ ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
static BOOLEAN
sisfballowretracecrt1(struct sis_video_info *ivideo)
{
- u8 temp;
+ u8 temp;
- inSISIDXREG(SISCR,0x17,temp);
- if(!(temp & 0x80)) return FALSE;
+ inSISIDXREG(SISCR,0x17,temp);
+ if(!(temp & 0x80))
+ return FALSE;
- inSISIDXREG(SISSR,0x1f,temp);
- if(temp & 0xc0) return FALSE;
+ inSISIDXREG(SISSR,0x1f,temp);
+ if(temp & 0xc0)
+ return FALSE;
- return TRUE;
+ return TRUE;
}
static BOOLEAN
sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
{
- if(!sisfballowretracecrt1(ivideo)) return FALSE;
+ if(!sisfballowretracecrt1(ivideo))
+ return FALSE;
- if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
- else return FALSE;
+ if(inSISREG(SISINPSTAT) & 0x08)
+ return TRUE;
+ else
+ return FALSE;
}
static void
sisfbwaitretracecrt1(struct sis_video_info *ivideo)
{
- int watchdog;
+ int watchdog;
- if(!sisfballowretracecrt1(ivideo)) return;
+ if(!sisfballowretracecrt1(ivideo))
+ return;
- watchdog = 65536;
- while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
- watchdog = 65536;
- while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+ watchdog = 65536;
+ while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+ watchdog = 65536;
+ while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
}
static BOOLEAN
sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
{
- unsigned char temp, reg;
+ unsigned char temp, reg;
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: reg = 0x25; break;
- case SIS_315_VGA: reg = 0x30; break;
- default: return FALSE;
- }
+ switch(ivideo->sisvga_engine) {
+ case SIS_300_VGA: reg = 0x25; break;
+ case SIS_315_VGA: reg = 0x30; break;
+ default: return FALSE;
+ }
- inSISIDXREG(SISPART1, reg, temp);
- if(temp & 0x02) return TRUE;
- else return FALSE;
+ inSISIDXREG(SISPART1, reg, temp);
+ if(temp & 0x02)
+ return TRUE;
+ else
+ return FALSE;
}
static BOOLEAN
sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
{
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- if(sisfb_bridgeisslave(ivideo)) {
- return(sisfbcheckvretracecrt1(ivideo));
- } else {
- return(sisfbcheckvretracecrt2(ivideo));
- }
- }
- return(sisfbcheckvretracecrt1(ivideo));
+ if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+ if(!sisfb_bridgeisslave(ivideo)) {
+ return sisfbcheckvretracecrt2(ivideo);
+ }
+ }
+ return sisfbcheckvretracecrt1(ivideo);
}
static u32
sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
{
- u8 idx, reg1, reg2, reg3, reg4;
- u32 ret = 0;
-
- (*vcount) = (*hcount) = 0;
-
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_HBLANK |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: idx = 0x25; break;
- default:
- case SIS_315_VGA: idx = 0x30; break;
- }
- inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
- inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
- inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
- inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
- if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
- (*vcount) = reg3 | ((reg4 & 0x70) << 4);
- (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
- } else if(sisfballowretracecrt1(ivideo)) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- reg1 = inSISREG(SISINPSTAT);
- if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- inSISIDXREG(SISCR,0x20,reg1);
- inSISIDXREG(SISCR,0x1b,reg1);
- inSISIDXREG(SISCR,0x1c,reg2);
- inSISIDXREG(SISCR,0x1d,reg3);
- (*vcount) = reg2 | ((reg3 & 0x07) << 8);
- (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
- }
- return ret;
+ u8 idx, reg1, reg2, reg3, reg4;
+ u32 ret = 0;
+
+ (*vcount) = (*hcount) = 0;
+
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+
+ ret |= (FB_VBLANK_HAVE_VSYNC |
+ FB_VBLANK_HAVE_HBLANK |
+ FB_VBLANK_HAVE_VBLANK |
+ FB_VBLANK_HAVE_VCOUNT |
+ FB_VBLANK_HAVE_HCOUNT);
+ switch(ivideo->sisvga_engine) {
+ case SIS_300_VGA: idx = 0x25; break;
+ default:
+ case SIS_315_VGA: idx = 0x30; break;
+ }
+ inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+ inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+ inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+ inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+ if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+ if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
+ if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
+ (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+ (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+
+ } else if(sisfballowretracecrt1(ivideo)) {
+
+ ret |= (FB_VBLANK_HAVE_VSYNC |
+ FB_VBLANK_HAVE_VBLANK |
+ FB_VBLANK_HAVE_VCOUNT |
+ FB_VBLANK_HAVE_HCOUNT);
+ reg1 = inSISREG(SISINPSTAT);
+ if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+ if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+ inSISIDXREG(SISCR,0x20,reg1);
+ inSISIDXREG(SISCR,0x1b,reg1);
+ inSISIDXREG(SISCR,0x1c,reg2);
+ inSISIDXREG(SISCR,0x1d,reg3);
+ (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+ (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+ }
+
+ return ret;
}
static int
sisfb_myblank(struct sis_video_info *ivideo, int blank)
{
- u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
- BOOLEAN backlight = TRUE;
-
- switch(blank) {
- case FB_BLANK_UNBLANK: /* on */
- sr01 = 0x00;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_NORMAL: /* blank */
- sr01 = 0x20;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x80;
- cr63 = 0x40;
- p2_0 = 0x40;
- p1_13 = 0x80;
- backlight = FALSE;
- break;
- case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x40;
- cr63 = 0x40;
- p2_0 = 0x80;
- p1_13 = 0x40;
- backlight = FALSE;
- break;
- case FB_BLANK_POWERDOWN: /* off */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0xc0;
- cr63 = 0x40;
- p2_0 = 0xc0;
- p1_13 = 0xc0;
- backlight = FALSE;
- break;
- default:
- return 1;
- }
-
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
-
- if( (!ivideo->sisfb_thismonitor.datavalid) ||
- ((ivideo->sisfb_thismonitor.datavalid) &&
- (ivideo->sisfb_thismonitor.feature & 0xe0))) {
-
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
- }
-
- if(!(sisfb_bridgeisslave(ivideo))) {
- setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
- setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
- }
- }
-
- }
-
- if(ivideo->currentvbflags & CRT2_LCD) {
-
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
- if(backlight) {
- SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- } else {
- SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(ivideo->vbflags & VB_CHRONTEL) {
- if(backlight) {
- SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
- } else {
- SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
- }
- }
- }
-
- if(((ivideo->sisvga_engine == SIS_300_VGA) &&
- (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) &&
- ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
- setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
- }
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
-
- } else if(ivideo->currentvbflags & CRT2_VGA) {
-
- if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
-
- }
-
- return(0);
+ u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
+ BOOLEAN backlight = TRUE;
+
+ switch(blank) {
+ case FB_BLANK_UNBLANK: /* on */
+ sr01 = 0x00;
+ sr11 = 0x00;
+ sr1f = 0x00;
+ cr63 = 0x00;
+ p2_0 = 0x20;
+ p1_13 = 0x00;
+ backlight = TRUE;
+ break;
+ case FB_BLANK_NORMAL: /* blank */
+ sr01 = 0x20;
+ sr11 = 0x00;
+ sr1f = 0x00;
+ cr63 = 0x00;
+ p2_0 = 0x20;
+ p1_13 = 0x00;
+ backlight = TRUE;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0x80;
+ cr63 = 0x40;
+ p2_0 = 0x40;
+ p1_13 = 0x80;
+ backlight = FALSE;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0x40;
+ cr63 = 0x40;
+ p2_0 = 0x80;
+ p1_13 = 0x40;
+ backlight = FALSE;
+ break;
+ case FB_BLANK_POWERDOWN: /* off */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0xc0;
+ cr63 = 0x40;
+ p2_0 = 0xc0;
+ p1_13 = 0xc0;
+ backlight = FALSE;
+ break;
+ default:
+ return 1;
+ }
+
+ if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
+
+ if( (!ivideo->sisfb_thismonitor.datavalid) ||
+ ((ivideo->sisfb_thismonitor.datavalid) &&
+ (ivideo->sisfb_thismonitor.feature & 0xe0))) {
+
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+ }
+
+ if(!(sisfb_bridgeisslave(ivideo))) {
+ setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+ setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+ }
+ }
+
+ }
+
+ if(ivideo->currentvbflags & CRT2_LCD) {
+
+ if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+ if(backlight) {
+ SiS_SiS30xBLOn(&ivideo->SiS_Pr);
+ } else {
+ SiS_SiS30xBLOff(&ivideo->SiS_Pr);
+ }
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ if(backlight) {
+ SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
+ } else {
+ SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
+ }
+ }
+#endif
+ }
+
+ if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+ (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
+ ((ivideo->sisvga_engine == SIS_315_VGA) &&
+ ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
+ setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
+ }
+
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if((ivideo->vbflags2 & VB2_30xB) &&
+ (!(ivideo->vbflags2 & VB2_30xBDH))) {
+ setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
+ }
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+ if((ivideo->vbflags2 & VB2_30xB) &&
+ (!(ivideo->vbflags2 & VB2_30xBDH))) {
+ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+ }
+ }
+
+ } else if(ivideo->currentvbflags & CRT2_VGA) {
+
+ if(ivideo->vbflags2 & VB2_30xB) {
+ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+ }
+
+ }
+
+ return 0;
+}
+
+/* ------------- Callbacks from init.c/init301.c -------------- */
+
+#ifdef CONFIG_FB_SIS_300
+unsigned int
+sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u32 val = 0;
+
+ pci_read_config_dword(ivideo->nbridge, reg, &val);
+ return (unsigned int)val;
+}
+
+void
+sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+ pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
}
+unsigned int
+sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u32 val = 0;
+
+ if(!ivideo->lpcdev) return 0;
+
+ pci_read_config_dword(ivideo->lpcdev, reg, &val);
+ return (unsigned int)val;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+void
+sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+ pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
+}
+
+unsigned int
+sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u16 val = 0;
+
+ if(!ivideo->lpcdev) return 0;
+
+ pci_read_config_word(ivideo->lpcdev, reg, &val);
+ return (unsigned int)val;
+}
+#endif
+
/* ----------- FBDev related routines for all series ----------- */
static int
@@ -952,7 +1105,7 @@ sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
static void
sisfb_set_vparms(struct sis_video_info *ivideo)
{
- switch(ivideo->video_bpp) {
+ switch(ivideo->video_bpp) {
case 8:
ivideo->DstColor = 0x0000;
ivideo->SiS310_AccelDepth = 0x00000000;
@@ -972,14 +1125,13 @@ sisfb_set_vparms(struct sis_video_info *ivideo)
ivideo->video_cmap_len = 16;
printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
ivideo->accel = 0;
- break;
- }
+ }
}
static int
sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
{
- int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3));
+ int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
if(maxyres > 32767) maxyres = 32767;
@@ -996,30 +1148,29 @@ sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
ivideo->scrnpitchCRT1 <<= 1;
}
}
-
}
static void
sisfb_set_pitch(struct sis_video_info *ivideo)
{
- BOOLEAN isslavemode = FALSE;
+ BOOLEAN isslavemode = FALSE;
unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
unsigned short HDisplay2 = ivideo->video_linelength >> 3;
- if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+ if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
- /* We need to set pitch for CRT1 if bridge is in slave mode, too */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
- outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
- setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+ /* We need to set pitch for CRT1 if bridge is in slave mode, too */
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
+ outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
+ setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
}
- /* We must not set the pitch for CRT2 if bridge is in slave mode */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
+ /* We must not set the pitch for CRT2 if bridge is in slave mode */
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
- outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
- setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
- }
+ outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
+ setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+ }
}
static void
@@ -1056,12 +1207,41 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
}
static int
+sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
+{
+ unsigned short modeno = ivideo->mode_no;
+
+ /* >=2.6.12's fbcon clears the screen anyway */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ if(!clrscrn) modeno |= 0x80;
+#else
+ modeno |= 0x80;
+#endif
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ sisfb_pre_setmode(ivideo);
+
+ if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
+ printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
+ return -EINVAL;
+ }
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ sisfb_post_setmode(ivideo);
+
+ return 0;
+}
+
+
+static int
sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
unsigned int htotal = 0, vtotal = 0;
unsigned int drate = 0, hrate = 0;
- int found_mode = 0;
+ int found_mode = 0, ret;
int old_mode;
u32 pixclock;
@@ -1088,11 +1268,11 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
}
if(pixclock && htotal && vtotal) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ drate = 1000000000 / pixclock;
+ hrate = (drate * 1000) / htotal;
+ ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else {
- ivideo->refresh_rate = 60;
+ ivideo->refresh_rate = 60;
}
old_mode = ivideo->sisfb_mode_idx;
@@ -1113,6 +1293,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(found_mode) {
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+ ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
} else {
ivideo->sisfb_mode_idx = -1;
}
@@ -1131,10 +1312,10 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
+ printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ }
}
#endif
@@ -1143,24 +1324,9 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
#else
if(isactive) {
#endif
- sisfb_pre_setmode(ivideo);
-
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
- printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
- return -EINVAL;
- }
-
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
- sisfb_post_setmode(ivideo);
-
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
-
- sisfb_calc_pitch(ivideo, var);
- sisfb_set_pitch(ivideo);
-
+ /* If acceleration to be used? Need to know
+ * before pre/post_set_mode()
+ */
ivideo->accel = 0;
#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
#ifdef STUPID_ACCELF_TEXT_SHIT
@@ -1175,6 +1341,17 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
#endif
+ if((ret = sisfb_set_mode(ivideo, 1))) {
+ return ret;
+ }
+
+ ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+ ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+ ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+ sisfb_calc_pitch(ivideo, var);
+ sisfb_set_pitch(ivideo);
+
sisfb_set_vparms(ivideo);
ivideo->current_width = ivideo->video_width;
@@ -1186,572 +1363,79 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
ivideo->current_pixclock = var->pixclock;
ivideo->current_refresh_rate = ivideo->refresh_rate;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
+ ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
#endif
}
return 0;
}
-static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+static void
+sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
{
- unsigned int base;
-
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
-
- base = (var->yoffset * var->xres_virtual) + var->xoffset;
-
- /* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
- case 32:
- break;
- case 16:
- base >>= 1;
- break;
- case 8:
- default:
- base >>= 2;
- break;
- }
-
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- outSISIDXREG(SISCR, 0x0D, base & 0xFF);
+ outSISIDXREG(SISCR, 0x0D, base & 0xFF);
outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
if(ivideo->sisvga_engine == SIS_315_VGA) {
setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
}
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
- outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
- outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
- outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
- }
- }
- return 0;
}
-/* ------------ FBDev related routines for 2.4 series ----------- */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
static void
-sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
-{
- u16 VRE, VBE, VRS, VBS, VDE, VT;
- u16 HRE, HBE, HRS, HBS, HDE, HT;
- u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
- int A, B, C, D, E, F, temp;
- unsigned int hrate, drate, maxyres;
-
- inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
-
- if(sr_data & SIS_INTERLACED_MODE)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
-
- switch((sr_data & 0x1C) >> 2) {
- case SIS_8BPP_COLOR_MODE:
- var->bits_per_pixel = 8;
- break;
- case SIS_16BPP_COLOR_MODE:
- var->bits_per_pixel = 16;
- break;
- case SIS_32BPP_COLOR_MODE:
- var->bits_per_pixel = 32;
- break;
- }
-
- sisfb_bpp_to_var(ivideo, var);
-
- inSISIDXREG(SISSR, 0x0A, sr_data);
- inSISIDXREG(SISCR, 0x06, cr_data);
- inSISIDXREG(SISCR, 0x07, cr_data2);
-
- VT = (cr_data & 0xFF) |
- ((u16) (cr_data2 & 0x01) << 8) |
- ((u16) (cr_data2 & 0x20) << 4) |
- ((u16) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- inSISIDXREG(SISCR, 0x12, cr_data);
-
- VDE = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x02) << 7) |
- ((u16) (cr_data2 & 0x40) << 3) |
- ((u16) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- inSISIDXREG(SISCR, 0x10, cr_data);
-
- VRS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x04) << 6) |
- ((u16) (cr_data2 & 0x80) << 2) |
- ((u16) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- inSISIDXREG(SISCR, 0x15, cr_data);
- inSISIDXREG(SISCR, 0x09, cr_data3);
-
- if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
-
- VBS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x08) << 5) |
- ((u16) (cr_data3 & 0x20) << 4) |
- ((u16) (sr_data & 0x04) << 8);
-
- inSISIDXREG(SISCR, 0x16, cr_data);
-
- VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- inSISIDXREG(SISCR, 0x11, cr_data);
-
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->yres = E;
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- var->yres <<= 1;
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->yres >>= 1;
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
- }
-
- inSISIDXREG(SISSR, 0x0b, sr_data);
- inSISIDXREG(SISCR, 0x00, cr_data);
-
- HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- inSISIDXREG(SISCR, 0x01, cr_data);
-
- HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
- E = HDE + 1;
-
- inSISIDXREG(SISCR, 0x04, cr_data);
-
- HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
- F = HRS - E - 3;
-
- inSISIDXREG(SISCR, 0x02, cr_data);
-
- HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
-
- inSISIDXREG(SISSR, 0x0c, sr_data);
- inSISIDXREG(SISCR, 0x03, cr_data);
- inSISIDXREG(SISCR, 0x05, cr_data2);
-
- HBE = (cr_data & 0x1f) |
- ((u16) (cr_data2 & 0x80) >> 2) |
- ((u16) (sr_data & 0x03) << 6);
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
-
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
-
- D = B - F - C;
-
- var->xres = E * 8;
- if(var->xres_virtual < var->xres) {
- var->xres_virtual = var->xres;
- }
-
- if((var->xres == 320) &&
- (var->yres == 200 || var->yres == 240)) {
- /* Terrible hack, but the correct CRTC data for
- * these modes only produces a black screen...
- */
- var->left_margin = (400 - 376);
- var->right_margin = (328 - 320);
- var->hsync_len = (376 - 328);
- } else {
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
- }
- var->activate = FB_ACTIVATE_NOW;
-
- var->sync = 0;
-
- mr_data = inSISREG(SISMISCR);
- if(mr_data & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
- if(mr_data & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
-
- VT += 2;
- VT <<= 1;
- HT = (HT + 5) * 8;
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- VT <<= 1;
- }
- hrate = ivideo->refresh_rate * VT / 2;
- drate = (hrate * HT) / 1000;
- var->pixclock = (u32) (1000000000 / drate);
-
- if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
- } else {
- var->yres_virtual = var->yres;
- }
-
-}
-
-static int
-sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *info)
+sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(regno >= ivideo->video_cmap_len) return 1;
-
- *red = ivideo->sis_palette[regno].red;
- *green = ivideo->sis_palette[regno].green;
- *blue = ivideo->sis_palette[regno].blue;
- *transp = 0;
-
- return 0;
-}
-
-static int
-sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(regno >= ivideo->video_cmap_len) return 1;
-
- ivideo->sis_palette[regno].red = red;
- ivideo->sis_palette[regno].green = green;
- ivideo->sis_palette[regno].blue = blue;
-
- switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- outSISREG(SISDACA, regno);
- outSISREG(SISDACD, (red >> 10));
- outSISREG(SISDACD, (green >> 10));
- outSISREG(SISDACD, (blue >> 10));
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
- outSISREG(SISDAC2D, (red >> 8));
- outSISREG(SISDAC2D, (green >> 8));
- outSISREG(SISDAC2D, (blue >> 8));
+ if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+ orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
+ outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
+ outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
+ outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
}
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- ivideo->sis_fbcon_cmap.cfb16[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
- break;
-#endif
- }
-
- return 0;
-}
-
-static void
-sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- struct display_switch *sw;
- struct fb_fix_screeninfo fix;
- long flags;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- sisfb_get_fix(&fix, con, info);
-
- display->var = *var;
- display->screen_base = (char *)ivideo->video_vbase;
- display->visual = fix.visual;
- display->type = fix.type;
- display->type_aux = fix.type_aux;
- display->ypanstep = fix.ypanstep;
- display->ywrapstep = fix.ywrapstep;
- display->line_length = fix.line_length;
- display->can_soft_blank = 1;
- display->inverse = ivideo->sisfb_inverse;
- display->next_line = fix.line_length;
-
- save_flags(flags);
-
- switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
- break;
-#endif
- default:sw = &fbcon_dummy;
- break;
- }
- memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
- display->dispsw = &ivideo->sisfb_sw;
-
- restore_flags(flags);
-
- if(ivideo->sisfb_ypan) {
- /* display->scrollmode = 0; */
- } else {
- display->scrollmode = SCROLL_YREDRAW;
- ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
- }
-}
-
-static void
-sisfb_do_install_cmap(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(con != ivideo->currcon) return;
-
- if(fb_display[con].cmap.len) {
- fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
- } else {
- int size = sisfb_get_cmap_len(&fb_display[con].var);
- fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
}
}
static int
-sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(con == -1) {
- memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
- } else {
- *var = fb_display[con].var;
- }
-
- if(ivideo->sisfb_fstn) {
- if(var->xres == 320 && var->yres == 480) var->yres = 240;
- }
-
- return 0;
-}
-
-static int
-sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
-
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
-
- if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
- sisfb_crtc_to_var(ivideo, var);
+ if(var->xoffset > (var->xres_virtual - var->xres)) {
return -EINVAL;
}
-
- sisfb_crtc_to_var(ivideo, var);
-
- sisfb_set_disp(con, var, info);
-
- if(info->changevar) {
- (*info->changevar)(con);
- }
-
- if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
- return err;
- }
-
- sisfb_do_install_cmap(con, info);
-
-#if 0 /* Why was this called here? */
- unsigned int cols, rows;
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-#endif
- return 0;
-}
-
-static int
-sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- if(con == ivideo->currcon) {
-
- return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
-
- } else if(display->cmap.len) {
-
- fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
-
- } else {
-
- int size = sisfb_get_cmap_len(&display->var);
- fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-
+ if(var->yoffset > (var->yres_virtual - var->yres)) {
+ return -EINVAL;
}
- return 0;
-}
+ ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
-static int
-sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- int err, size;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- size = sisfb_get_cmap_len(&display->var);
- if(display->cmap.len != size) {
- err = fb_alloc_cmap(&display->cmap, size, 0);
- if(err) return err;
- }
-
- if(con == ivideo->currcon) {
- return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
- } else {
- fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
- }
-
- return 0;
-}
-
-static int
-sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
-
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
-
- if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
- (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
- return -EINVAL;
+ /* calculate base bpp dep. */
+ switch(var->bits_per_pixel) {
+ case 32:
+ break;
+ case 16:
+ ivideo->current_base >>= 1;
+ break;
+ case 8:
+ default:
+ ivideo->current_base >>= 2;
+ break;
}
- if(con == ivideo->currcon) {
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
- }
+ ivideo->current_base += (ivideo->video_offset >> 2);
- fb_display[con].var.xoffset = var->xoffset;
- fb_display[con].var.yoffset = var->yoffset;
+ sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+ sisfb_set_base_CRT2(ivideo, ivideo->current_base);
return 0;
}
-static int
-sisfb_update_var(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- return(sisfb_pan_var(ivideo, &fb_display[con].var));
-}
-
-static int
-sisfb_switch(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int cols, rows;
-
- if(fb_display[ivideo->currcon].cmap.len) {
- fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
- }
-
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
-
- if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
- sizeof(struct fb_var_screeninfo))) {
- ivideo->currcon = con;
- return 1;
- }
-
- ivideo->currcon = con;
-
- sisfb_do_set_var(&fb_display[con].var, 1, info);
-
- sisfb_set_disp(con, &fb_display[con].var, info);
-
- sisfb_do_install_cmap(con, info);
-
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-
- sisfb_update_var(con, info);
+/* ------------ FBDev related routines for 2.4 series ----------- */
- return 1;
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void
-sisfb_blank(int blank, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+#include "sisfb_fbdev_2_4.h"
- sisfb_myblank(ivideo, blank);
-}
#endif
/* ------------ FBDev related routines for 2.6 series ----------- */
@@ -1761,13 +1445,13 @@ sisfb_blank(int blank, struct fb_info *info)
static int
sisfb_open(struct fb_info *info, int user)
{
- return 0;
+ return 0;
}
static int
sisfb_release(struct fb_info *info, int user)
{
- return 0;
+ return 0;
}
static int
@@ -1776,16 +1460,17 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
+ if(regno >= sisfb_get_cmap_len(&info->var))
+ return 1;
switch(info->var.bits_per_pixel) {
case 8:
- outSISREG(SISDACA, regno);
+ outSISREG(SISDACA, regno);
outSISREG(SISDACD, (red >> 10));
outSISREG(SISDACD, (green >> 10));
outSISREG(SISDACD, (blue >> 10));
if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
+ outSISREG(SISDAC2A, regno);
outSISREG(SISDAC2D, (red >> 8));
outSISREG(SISDAC2D, (green >> 8));
outSISREG(SISDAC2D, (blue >> 8));
@@ -1793,7 +1478,9 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
break;
case 16:
((u32 *)(info->pseudo_palette))[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
break;
case 32:
red >>= 8;
@@ -1811,13 +1498,13 @@ sisfb_set_par(struct fb_info *info)
{
int err;
- if((err = sisfb_do_set_var(&info->var, 1, info))) {
+ if((err = sisfb_do_set_var(&info->var, 1, info)))
return err;
- }
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
sisfb_get_fix(&info->fix, info->currcon, info);
#else
- sisfb_get_fix(&info->fix, -1, info);
+ sisfb_get_fix(&info->fix, -1, info);
#endif
return 0;
}
@@ -1829,7 +1516,7 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
unsigned int drate = 0, hrate = 0, maxyres;
int found_mode = 0;
- int refresh_rate, search_idx;
+ int refresh_rate, search_idx, tidx;
BOOLEAN recalc_clock = FALSE;
u32 pixclock;
@@ -1848,7 +1535,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
vtotal += var->yres;
vtotal <<= 1;
- } else vtotal += var->yres;
+ } else
+ vtotal += var->yres;
if(!(htotal) || !(vtotal)) {
SISFAIL("sisfb: no valid timing data");
@@ -1860,60 +1548,68 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if( (sisbios_mode[search_idx].xres == var->xres) &&
(sisbios_mode[search_idx].yres == var->yres) &&
(sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
+ if((tidx = sisfb_validate_mode(ivideo, search_idx,
+ ivideo->currentvbflags)) > 0) {
+ found_mode = 1;
+ search_idx = tidx;
+ break;
}
}
search_idx++;
}
if(!found_mode) {
- search_idx = 0;
+ search_idx = 0;
while(sisbios_mode[search_idx].mode_no[0] != 0) {
if( (var->xres <= sisbios_mode[search_idx].xres) &&
(var->yres <= sisbios_mode[search_idx].yres) &&
(var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
- if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
- }
+ if((tidx = sisfb_validate_mode(ivideo,search_idx,
+ ivideo->currentvbflags)) > 0) {
+ found_mode = 1;
+ search_idx = tidx;
+ break;
+ }
}
search_idx++;
- }
+ }
if(found_mode) {
- printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel,
+ printk(KERN_DEBUG
+ "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
+ var->xres, var->yres, var->bits_per_pixel,
sisbios_mode[search_idx].xres,
sisbios_mode[search_idx].yres,
var->bits_per_pixel);
var->xres = sisbios_mode[search_idx].xres;
- var->yres = sisbios_mode[search_idx].yres;
-
-
+ var->yres = sisbios_mode[search_idx].yres;
} else {
- printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n",
+ printk(KERN_ERR
+ "sisfb: Failed to find supported mode near %dx%dx%d\n",
var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
+ return -EINVAL;
}
}
- if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */
- ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
+ if( ((ivideo->vbflags2 & VB2_LVDS) ||
+ ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
(var->bits_per_pixel == 8) ) {
- refresh_rate = 60;
+ /* Slave modes on LVDS and 301B-DH */
+ refresh_rate = 60;
recalc_clock = TRUE;
- } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */
- (ivideo->current_vtotal == vtotal) &&
- (ivideo->current_pixclock == pixclock) ) {
+ } else if( (ivideo->current_htotal == htotal) &&
+ (ivideo->current_vtotal == vtotal) &&
+ (ivideo->current_pixclock == pixclock) ) {
+ /* x=x & y=y & c=c -> assume depth change */
drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */
- (ivideo->current_vtotal != vtotal) ) &&
- (ivideo->current_pixclock == var->pixclock) ) {
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ } else if( ( (ivideo->current_htotal != htotal) ||
+ (ivideo->current_vtotal != vtotal) ) &&
+ (ivideo->current_pixclock == var->pixclock) ) {
+ /* x!=x | y!=y & c=c -> invalid pixclock */
if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
- refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+ refresh_rate =
+ ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
} else if(ivideo->sisfb_parm_rate != -1) {
/* Sic, sisfb_parm_rate - want to know originally desired rate here */
refresh_rate = ivideo->sisfb_parm_rate;
@@ -1923,8 +1619,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
recalc_clock = TRUE;
} else if((pixclock) && (htotal) && (vtotal)) {
drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else if(ivideo->current_refresh_rate) {
refresh_rate = ivideo->current_refresh_rate;
recalc_clock = TRUE;
@@ -1937,72 +1633,72 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Eventually recalculate timing and clock */
if(recalc_clock) {
- if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
- var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
- &ivideo->sishw_ext,
+ if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
+ var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
sisbios_mode[search_idx].mode_no[ivideo->mni],
myrateindex));
- sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var);
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->pixclock <<= 1;
- }
+ sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
+ sisbios_mode[search_idx].mode_no[ivideo->mni],
+ myrateindex, var);
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->pixclock <<= 1;
+ }
}
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
- myrateindex, refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
+ myrateindex, refresh_rate)) {
+ printk(KERN_INFO
+ "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ }
}
/* Adapt RGB settings */
sisfb_bpp_to_var(ivideo, var);
-
+
/* Sanity check for offsets */
if(var->xoffset < 0) var->xoffset = 0;
if(var->yoffset < 0) var->yoffset = 0;
- if(var->xres > var->xres_virtual) {
- var->xres_virtual = var->xres;
- }
+ if(var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
+ maxyres = sisfb_calc_maxyres(ivideo, var);
+ if(ivideo->sisfb_max) {
+ var->yres_virtual = maxyres;
+ } else {
+ if(var->yres_virtual > maxyres) {
+ var->yres_virtual = maxyres;
+ }
+ }
+ if(var->yres_virtual <= var->yres) {
+ var->yres_virtual = var->yres;
+ }
} else {
- if(var->yres != var->yres_virtual) {
- var->yres_virtual = var->yres;
- }
- var->xoffset = 0;
- var->yoffset = 0;
+ if(var->yres != var->yres_virtual) {
+ var->yres_virtual = var->yres;
+ }
+ var->xoffset = 0;
+ var->yoffset = 0;
}
-
+
/* Truncate offsets to maximum if too high */
if(var->xoffset > var->xres_virtual - var->xres) {
- var->xoffset = var->xres_virtual - var->xres - 1;
+ var->xoffset = var->xres_virtual - var->xres - 1;
}
if(var->yoffset > var->yres_virtual - var->yres) {
- var->yoffset = var->yres_virtual - var->yres - 1;
+ var->yoffset = var->yres_virtual - var->yres - 1;
}
-
+
/* Set everything else to 0 */
- var->red.msb_right =
- var->green.msb_right =
- var->blue.msb_right =
- var->transp.offset =
- var->transp.length =
- var->transp.msb_right = 0;
+ var->red.msb_right =
+ var->green.msb_right =
+ var->blue.msb_right =
+ var->transp.offset =
+ var->transp.length =
+ var->transp.msb_right = 0;
return 0;
}
@@ -2013,21 +1709,21 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
int err;
- if(var->xoffset > (var->xres_virtual - var->xres)) {
+ if(var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
+
+ if(var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
- }
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
+ if(var->vmode & FB_VMODE_YWRAP)
+ return -EINVAL;
if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual) {
+ var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
- }
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
+ if((err = sisfb_pan_var(ivideo, var)) < 0)
+ return err;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -2040,7 +1736,7 @@ sisfb_blank(int blank, struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- return(sisfb_myblank(ivideo, blank));
+ return sisfb_myblank(ivideo, blank);
}
#endif
@@ -2056,153 +1752,184 @@ sisfb_ioctl(struct inode *inode, struct file *file,
struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct sis_memreq sismemreq;
- struct fb_vblank sisvbblank;
- sisfb_info x;
+ struct sis_memreq sismemreq;
+ struct fb_vblank sisvbblank;
u32 gpu32 = 0;
#ifndef __user
#define __user
#endif
u32 __user *argp = (u32 __user *)arg;
- switch (cmd) {
+ switch(cmd) {
case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO)) {
+ if(!capable(CAP_SYS_RAWIO))
return -EPERM;
- }
- if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) {
- return -EFAULT;
- }
+
+ if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
+ return -EFAULT;
+
sis_malloc(&sismemreq);
+
if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
sis_free((u32)sismemreq.offset);
- return -EFAULT;
+ return -EFAULT;
}
break;
case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO)) {
+ if(!capable(CAP_SYS_RAWIO))
return -EPERM;
- }
- if(get_user(gpu32, argp)) {
+
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
sis_free(gpu32);
break;
case FBIOGET_VBLANK:
sisvbblank.count = 0;
sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
- if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) {
+
+ if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
return -EFAULT;
- }
+
break;
case SISFB_GET_INFO_SIZE:
- return put_user(sizeof(sisfb_info), argp);
+ return put_user(sizeof(struct sisfb_info), argp);
case SISFB_GET_INFO_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_INFO: /* For communication with X driver */
- x.sisfb_id = SISFB_ID;
- x.sisfb_version = VER_MAJOR;
- x.sisfb_revision = VER_MINOR;
- x.sisfb_patchlevel = VER_LEVEL;
- x.chip_id = ivideo->chip_id;
- x.memory = ivideo->video_size / 1024;
- x.heapstart = ivideo->heapstart / 1024;
+ ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
+ ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
+ ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
+ ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
+ ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
+ ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
+ ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
+ ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
if(ivideo->modechanged) {
- x.fbvidmode = ivideo->mode_no;
+ ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
} else {
- x.fbvidmode = ivideo->modeprechange;
- }
- x.sisfb_caps = ivideo->caps;
- x.sisfb_tqlen = 512; /* yet fixed */
- x.sisfb_pcibus = ivideo->pcibus;
- x.sisfb_pcislot = ivideo->pcislot;
- x.sisfb_pcifunc = ivideo->pcifunc;
- x.sisfb_lcdpdc = ivideo->detectedpdc;
- x.sisfb_lcdpdca = ivideo->detectedpdca;
- x.sisfb_lcda = ivideo->detectedlcda;
- x.sisfb_vbflags = ivideo->vbflags;
- x.sisfb_currentvbflags = ivideo->currentvbflags;
- x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
- x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
- x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
- x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
- x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
- x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
- x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
- x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
- x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
- x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
-
- if(copy_to_user((void __user *)arg, &x, sizeof(x))) {
- return -EFAULT;
+ ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
}
+ ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
+ ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
+ ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
+ ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
+ ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
+ ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
+ ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
+ ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
+ ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
+ ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
+ ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+ ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+ ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+ ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+ ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+ ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+ ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+ ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+ ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
+ ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
+ ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
+ ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
+ ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
+ ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
+
+ if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
+ sizeof(ivideo->sisfb_infoblock)))
+ return -EFAULT;
+
break;
case SISFB_GET_VBRSTATUS_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_VBRSTATUS:
- if(sisfb_CheckVBRetrace(ivideo)) {
+ if(sisfb_CheckVBRetrace(ivideo))
return put_user((u32)1, argp);
- } else {
+ else
return put_user((u32)0, argp);
- }
case SISFB_GET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_AUTOMAXIMIZE:
- if(ivideo->sisfb_max) return put_user((u32)1, argp);
- else return put_user((u32)0, argp);
+ if(ivideo->sisfb_max)
+ return put_user((u32)1, argp);
+ else
+ return put_user((u32)0, argp);
case SISFB_SET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_SET_AUTOMAXIMIZE:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
ivideo->sisfb_max = (gpu32) ? 1 : 0;
break;
case SISFB_SET_TVPOSOFFSET:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
break;
case SISFB_GET_TVPOSOFFSET:
- return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
- argp);
+ return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
+ argp);
+
+ case SISFB_COMMAND:
+ if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
+ sizeof(struct sisfb_cmd)))
+ return -EFAULT;
+
+ sisfb_handle_command(ivideo, &ivideo->sisfb_command);
+
+ if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
+ sizeof(struct sisfb_cmd)))
+ return -EFAULT;
+
+ break;
case SISFB_SET_LOCK:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
ivideo->sisfblocked = (gpu32) ? 1 : 0;
break;
default:
+#ifdef SIS_NEW_CONFIG_COMPAT
return -ENOIOCTLCMD;
+#else
+ return -EINVAL;
+#endif
}
return 0;
}
-#ifdef CONFIG_COMPAT
-static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info)
+#ifdef SIS_NEW_CONFIG_COMPAT
+static long
+sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info)
{
int ret;
+
lock_kernel();
ret = sisfb_ioctl(NULL, f, cmd, arg, info);
unlock_kernel();
@@ -2219,7 +1946,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
strcpy(fix->id, ivideo->myid);
- fix->smem_start = ivideo->video_base;
+ fix->smem_start = ivideo->video_base + ivideo->video_offset;
fix->smem_len = ivideo->sisfb_mem;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
@@ -2231,11 +1958,17 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
fix->mmio_start = ivideo->mmio_base;
fix->mmio_len = ivideo->mmio_size;
if(ivideo->sisvga_engine == SIS_300_VGA) {
- fix->accel = FB_ACCEL_SIS_GLAMOUR;
- } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
- fix->accel = FB_ACCEL_SIS_XABRE;
+ fix->accel = FB_ACCEL_SIS_GLAMOUR;
+ } else if((ivideo->chip == SIS_330) ||
+ (ivideo->chip == SIS_760) ||
+ (ivideo->chip == SIS_761)) {
+ fix->accel = FB_ACCEL_SIS_XABRE;
+ } else if(ivideo->chip == XGI_20) {
+ fix->accel = FB_ACCEL_XGI_VOLARI_Z;
+ } else if(ivideo->chip >= XGI_40) {
+ fix->accel = FB_ACCEL_XGI_VOLARI_V;
} else {
- fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
+ fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
}
return 0;
@@ -2251,40 +1984,41 @@ static struct fb_ops sisfb_ops = {
.fb_set_var = sisfb_set_var,
.fb_get_cmap = sisfb_get_cmap,
.fb_set_cmap = sisfb_set_cmap,
- .fb_pan_display = sisfb_pan_display,
+ .fb_pan_display = sisfb_pan_display,
.fb_ioctl = sisfb_ioctl
};
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static struct fb_ops sisfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = sisfb_open,
- .fb_release = sisfb_release,
- .fb_check_var = sisfb_check_var,
- .fb_set_par = sisfb_set_par,
- .fb_setcolreg = sisfb_setcolreg,
- .fb_pan_display = sisfb_pan_display,
- .fb_blank = sisfb_blank,
- .fb_fillrect = fbcon_sis_fillrect,
- .fb_copyarea = fbcon_sis_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
- .fb_sync = fbcon_sis_sync,
- .fb_ioctl = sisfb_ioctl,
-#ifdef CONFIG_COMPAT
- .fb_compat_ioctl = sisfb_compat_ioctl,
+ .owner = THIS_MODULE,
+ .fb_open = sisfb_open,
+ .fb_release = sisfb_release,
+ .fb_check_var = sisfb_check_var,
+ .fb_set_par = sisfb_set_par,
+ .fb_setcolreg = sisfb_setcolreg,
+ .fb_pan_display = sisfb_pan_display,
+ .fb_blank = sisfb_blank,
+ .fb_fillrect = fbcon_sis_fillrect,
+ .fb_copyarea = fbcon_sis_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+ .fb_sync = fbcon_sis_sync,
+#ifdef SIS_NEW_CONFIG_COMPAT
+ .fb_compat_ioctl= sisfb_compat_ioctl,
#endif
+ .fb_ioctl = sisfb_ioctl
};
#endif
/* ---------------- Chip generation dependent routines ---------------- */
-static struct pci_dev * sisfb_get_northbridge(int basechipid)
+static struct pci_dev * __devinit
+sisfb_get_northbridge(int basechipid)
{
struct pci_dev *pdev = NULL;
int nbridgenum, nbridgeidx, i;
- const unsigned short nbridgeids[] = {
+ static const unsigned short nbridgeids[] = {
PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
PCI_DEVICE_ID_SI_730,
@@ -2292,13 +2026,14 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
PCI_DEVICE_ID_SI_651,
PCI_DEVICE_ID_SI_740,
- PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */
+ PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
PCI_DEVICE_ID_SI_741,
PCI_DEVICE_ID_SI_660,
- PCI_DEVICE_ID_SI_760
+ PCI_DEVICE_ID_SI_760,
+ PCI_DEVICE_ID_SI_761
};
- switch(basechipid) {
+ switch(basechipid) {
#ifdef CONFIG_FB_SIS_300
case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
@@ -2306,35 +2041,40 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
#ifdef CONFIG_FB_SIS_315
case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
- case SIS_660: nbridgeidx = 7; nbridgenum = 4; break;
+ case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
#endif
default: return NULL;
}
for(i = 0; i < nbridgenum; i++) {
- if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
+ if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
+ nbridgeids[nbridgeidx+i], NULL)))
+ break;
}
return pdev;
}
-static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
+static int __devinit
+sisfb_get_dram_size(struct sis_video_info *ivideo)
{
#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
u8 reg;
#endif
ivideo->video_size = 0;
+ ivideo->UMAsize = ivideo->LFBsize = 0;
switch(ivideo->chip) {
#ifdef CONFIG_FB_SIS_300
case SIS_300:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = ((reg & 0x3F) + 1) << 20;
break;
case SIS_540:
case SIS_630:
case SIS_730:
- if(!ivideo->nbridge) return -1;
- pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+ if(!ivideo->nbridge)
+ return -1;
+ pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
break;
#endif
@@ -2342,45 +2082,68 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
case SIS_315H:
case SIS_315PRO:
case SIS_315:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
switch((reg >> 2) & 0x03) {
case 0x01:
case 0x03:
- ivideo->video_size <<= 1;
- break;
+ ivideo->video_size <<= 1;
+ break;
case 0x02:
- ivideo->video_size += (ivideo->video_size/2);
+ ivideo->video_size += (ivideo->video_size/2);
}
- break;
+ break;
case SIS_330:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
if(reg & 0x0c) ivideo->video_size <<= 1;
- break;
+ break;
case SIS_550:
case SIS_650:
case SIS_740:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
break;
case SIS_661:
case SIS_741:
- inSISIDXREG(SISCR, 0x79, reg);
+ inSISIDXREG(SISCR, 0x79, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- break;
+ break;
case SIS_660:
case SIS_760:
+ case SIS_761:
inSISIDXREG(SISCR, 0x79, reg);
reg = (reg & 0xf0) >> 4;
- if(reg) ivideo->video_size = (1 << reg) << 20;
+ if(reg) {
+ ivideo->video_size = (1 << reg) << 20;
+ ivideo->UMAsize = ivideo->video_size;
+ }
inSISIDXREG(SISCR, 0x78, reg);
reg &= 0x30;
if(reg) {
- if(reg == 0x10) ivideo->video_size += (32 << 20);
- else ivideo->video_size += (64 << 20);
+ if(reg == 0x10) {
+ ivideo->LFBsize = (32 << 20);
+ } else {
+ ivideo->LFBsize = (64 << 20);
+ }
+ ivideo->video_size += ivideo->LFBsize;
}
- break;
+ break;
+ case SIS_340:
+ case XGI_20:
+ case XGI_40:
+ inSISIDXREG(SISSR, 0x14, reg);
+ ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+ if(ivideo->chip != XGI_20) {
+ reg = (reg & 0x0c) >> 2;
+ if(ivideo->revision_id == 2) {
+ if(reg & 0x01) reg = 0x02;
+ else reg = 0x00;
+ }
+ if(reg == 0x02) ivideo->video_size <<= 1;
+ else if(reg == 0x03) ivideo->video_size <<= 2;
+ }
+ break;
#endif
default:
return -1;
@@ -2390,17 +2153,24 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
/* -------------- video bridge device detection --------------- */
-static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_detect_VB_connect(struct sis_video_info *ivideo)
{
u8 cr32, temp;
+ /* No CRT2 on XGI Z7 */
+ if(ivideo->chip == XGI_20) {
+ ivideo->sisfb_crt1off = 0;
+ return;
+ }
+
#ifdef CONFIG_FB_SIS_300
if(ivideo->sisvga_engine == SIS_300_VGA) {
inSISIDXREG(SISSR, 0x17, temp);
if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
/* PAL/NTSC is stored on SR16 on such machines */
if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
- inSISIDXREG(SISSR, 0x16, temp);
+ inSISIDXREG(SISSR, 0x16, temp);
if(temp & 0x20)
ivideo->vbflags |= TV_PAL;
else
@@ -2435,28 +2205,29 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
if(ivideo->sisfb_tvplug != -1) {
if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+ (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
if(ivideo->sisfb_tvplug & TV_YPBPR) {
- ivideo->sisfb_tvplug = -1;
+ ivideo->sisfb_tvplug = -1;
printk(KERN_ERR "sisfb: YPbPr not supported\n");
}
}
}
if(ivideo->sisfb_tvplug != -1) {
if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+ (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
if(ivideo->sisfb_tvplug & TV_HIVISION) {
- ivideo->sisfb_tvplug = -1;
+ ivideo->sisfb_tvplug = -1;
printk(KERN_ERR "sisfb: HiVision not supported\n");
}
}
}
if(ivideo->sisfb_tvstd != -1) {
- if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
- (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+ if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
+ (!((ivideo->sisvga_engine == SIS_315_VGA) &&
+ (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
- ivideo->sisfb_tvstd = -1;
- printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+ ivideo->sisfb_tvstd = -1;
+ printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
}
}
}
@@ -2468,7 +2239,7 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
- else {
+ else {
if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
}
@@ -2485,165 +2256,44 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
}
if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
if(ivideo->sisvga_engine == SIS_300_VGA) {
- inSISIDXREG(SISSR, 0x38, temp);
+ inSISIDXREG(SISSR, 0x38, temp);
if(temp & 0x01) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
- inSISIDXREG(SISSR, 0x38, temp);
+ inSISIDXREG(SISSR, 0x38, temp);
if(temp & 0x01) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
- } else {
- inSISIDXREG(SISCR, 0x79, temp);
+ } else {
+ inSISIDXREG(SISCR, 0x79, temp);
if(temp & 0x20) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
- }
+ }
}
}
/* Copy forceCRT1 option to CRT1off if option is given */
- if(ivideo->sisfb_forcecrt1 != -1) {
- ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
- }
-}
-
-static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
-{
- char stdstr[] = "sisfb: Detected";
- char bridgestr[] = "video bridge";
- u8 vb_chipid;
- u8 reg;
-
- inSISIDXREG(SISPART4, 0x00, vb_chipid);
- switch(vb_chipid) {
- case 0x01:
- inSISIDXREG(SISPART4, 0x01, reg);
- if(reg < 0xb0) {
- ivideo->vbflags |= VB_301;
- printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
- } else if(reg < 0xc0) {
- ivideo->vbflags |= VB_301B;
- inSISIDXREG(SISPART4,0x23,reg);
- if(!(reg & 0x02)) {
- ivideo->vbflags |= VB_30xBDH;
- printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
- } else {
- printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
- }
- } else if(reg < 0xd0) {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
- } else if(reg < 0xe0) {
- ivideo->vbflags |= VB_301LV;
- printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
- } else if(reg <= 0xe1) {
- inSISIDXREG(SISPART4,0x39,reg);
- if(reg == 0xff) {
- ivideo->vbflags |= VB_302LV;
- printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
- } else {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
-#if 0
- ivideo->vbflags |= VB_302ELV;
- printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
-#endif
- }
- }
- break;
- case 0x02:
- ivideo->vbflags |= VB_302B;
- printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
- break;
- }
-
- if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
- inSISIDXREG(SISCR, 0x37, reg);
- reg &= SIS_EXTERNAL_CHIP_MASK;
- reg >>= 1;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- switch(reg) {
- case SIS_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS_EXTERNAL_CHIP_TRUMPION:
- ivideo->vbflags |= VB_TRUMPION;
- break;
- case SIS_EXTERNAL_CHIP_CHRONTEL:
- ivideo->vbflags |= VB_CHRONTEL;
- break;
- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
-#endif
- } else if(ivideo->chip < SIS_661) {
-#ifdef CONFIG_FB_SIS_315
- switch (reg) {
- case SIS310_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
- } else if(ivideo->chip >= SIS_661) {
-#ifdef CONFIG_FB_SIS_315
- inSISIDXREG(SISCR, 0x38, reg);
- reg >>= 5;
- switch(reg) {
- case 0x02:
- ivideo->vbflags |= VB_LVDS;
- break;
- case 0x03:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- case 0x04:
- ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
- }
- if(ivideo->vbflags & VB_LVDS) {
- printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
- }
- if(ivideo->vbflags & VB_TRUMPION) {
- printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
- }
- if(ivideo->vbflags & VB_CHRONTEL) {
- printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
- }
- if(ivideo->vbflags & VB_CONEXANT) {
- printk(KERN_INFO "%s Conexant external device\n", stdstr);
- }
- }
-
- if(ivideo->vbflags & VB_SISBRIDGE) {
- SiS_Sense30x(ivideo);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- SiS_SenseCh(ivideo);
+ if(ivideo->sisfb_forcecrt1 != -1) {
+ ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
}
}
/* ------------------ Sensing routines ------------------ */
-static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
+static BOOLEAN __devinit
+sisfb_test_DDC1(struct sis_video_info *ivideo)
{
unsigned short old;
int count = 48;
old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
do {
- if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
+ if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
} while(count--);
return (count == -1) ? FALSE : TRUE;
}
-static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_sense_crt1(struct sis_video_info *ivideo)
{
BOOLEAN mustwait = FALSE;
u8 sr1F, cr17;
@@ -2699,7 +2349,8 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
if(temp == 0xffff) {
i = 3;
do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+ ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
} while(((temp == 0) || (temp == 0xffff)) && i--);
if((temp == 0) || (temp == 0xffff)) {
@@ -2723,7 +2374,96 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
}
/* Determine and detect attached devices on SiS30x */
-static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
+static void __devinit
+SiS_SenseLCD(struct sis_video_info *ivideo)
+{
+ unsigned char buffer[256];
+ unsigned short temp, realcrtno, i;
+ u8 reg, cr37 = 0, paneltype = 0;
+ u16 xres, yres;
+
+ ivideo->SiS_Pr.PanelSelfDetected = FALSE;
+
+ /* LCD detection only for TMDS bridges */
+ if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+ return;
+ if(ivideo->vbflags2 & VB2_30xBDH)
+ return;
+
+ /* If LCD already set up by BIOS, skip it */
+ inSISIDXREG(SISCR, 0x32, reg);
+ if(reg & 0x08)
+ return;
+
+ realcrtno = 1;
+ if(ivideo->SiS_Pr.DDCPortMixup)
+ realcrtno = 0;
+
+ /* Check DDC capabilities */
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 0, &buffer[0], ivideo->vbflags2);
+
+ if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+ return;
+
+ /* Read DDC data */
+ i = 3; /* Number of retrys */
+ do {
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+ ivideo->sisvga_engine, realcrtno, 1,
+ &buffer[0], ivideo->vbflags2);
+ } while((temp) && i--);
+
+ if(temp)
+ return;
+
+ /* No digital device */
+ if(!(buffer[0x14] & 0x80))
+ return;
+
+ /* First detailed timing preferred timing? */
+ if(!(buffer[0x18] & 0x02))
+ return;
+
+ xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
+ yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
+
+ switch(xres) {
+ case 1024:
+ if(yres == 768)
+ paneltype = 0x02;
+ break;
+ case 1280:
+ if(yres == 1024)
+ paneltype = 0x03;
+ break;
+ case 1600:
+ if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+ paneltype = 0x0b;
+ break;
+ }
+
+ if(!paneltype)
+ return;
+
+ if(buffer[0x23])
+ cr37 |= 0x10;
+
+ if((buffer[0x47] & 0x18) == 0x18)
+ cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
+ else
+ cr37 |= 0xc0;
+
+ outSISIDXREG(SISCR, 0x36, paneltype);
+ cr37 &= 0xf1;
+ setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
+ orSISIDXREG(SISCR, 0x32, 0x08);
+
+ ivideo->SiS_Pr.PanelSelfDetected = TRUE;
+}
+
+static int __devinit
+SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
{
int temp, mytest, result, i, j;
@@ -2749,10 +2489,11 @@ static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 tes
}
if((result == 0) || (result >= 2)) break;
}
- return(result);
+ return result;
}
-static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
+static void __devinit
+SiS_Sense30x(struct sis_video_info *ivideo)
{
u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
u16 svhs=0, svhs_c=0;
@@ -2762,36 +2503,51 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
char stdstr[] = "sisfb: Detected";
char tvstr[] = "TV connected to";
- if(ivideo->vbflags & VB_301) {
+ if(ivideo->vbflags2 & VB2_301) {
svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
inSISIDXREG(SISPART4,0x01,myflag);
if(myflag & 0x04) {
svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
}
- } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+ } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
- } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+ } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
svhs = 0x0200; cvbs = 0x0100;
- } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+ } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
- } else return;
+ } else
+ return;
vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
svhs_c = 0x0408; cvbs_c = 0x0808;
}
+
biosflag = 2;
+ if(ivideo->haveXGIROM) {
+ biosflag = ivideo->bios_abase[0x58] & 0x03;
+ } else if(ivideo->newrom) {
+ if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
+ } else if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->bios_abase) {
+ biosflag = ivideo->bios_abase[0xfe] & 0x03;
+ }
+ }
if(ivideo->chip == SIS_300) {
inSISIDXREG(SISSR,0x3b,myflag);
if(!(myflag & 0x01)) vga2 = vga2_c = 0;
}
+ if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
+ vga2 = vga2_c = 0;
+ }
+
inSISIDXREG(SISSR,0x1e,backupSR_1e);
orSISIDXREG(SISSR,0x1e,0x20);
inSISIDXREG(SISPART4,0x0d,backupP4_0d);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xC) {
setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
} else {
orSISIDXREG(SISPART4,0x0d,0x04);
@@ -2802,11 +2558,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
inSISIDXREG(SISPART2,0x4d,backupP2_4d);
- if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+ if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
}
- if(!(ivideo->vbflags & VB_301C)) {
+ if(!(ivideo->vbflags2 & VB2_30xCLV)) {
SISDoSense(ivideo, 0, 0);
}
@@ -2826,12 +2582,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
andSISIDXREG(SISCR, 0x32, 0x3f);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xCLV) {
orSISIDXREG(SISPART4,0x0d,0x04);
}
- if((ivideo->sisvga_engine == SIS_315_VGA) &&
- (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+ if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
if((result = SISDoSense(ivideo, svhs, 0x0604))) {
@@ -2864,7 +2619,7 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
outSISIDXREG(SISPART4,0x0d,backupP4_0d);
outSISIDXREG(SISSR,0x1e,backupSR_1e);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xCLV) {
inSISIDXREG(SISPART2,0x00,biosflag);
if(biosflag & 0x20) {
for(myflag = 2; myflag > 0; myflag--) {
@@ -2878,7 +2633,8 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
}
/* Determine and detect attached TV's on Chrontel */
-static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
+static void __devinit
+SiS_SenseCh(struct sis_video_info *ivideo)
{
#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
u8 temp1, temp2;
@@ -2899,7 +2655,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
/* See Chrontel TB31 for explanation */
temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
}
temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
@@ -2909,15 +2665,15 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
/* Read power status */
temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
if((temp1 & 0x03) != 0x03) {
- /* Power all outputs */
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+ /* Power all outputs */
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
}
/* Sense connected TV devices */
for(i = 0; i < 3; i++) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
if(!(temp1 & 0x08)) test[i] = 0x02;
@@ -2930,7 +2686,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
else if(test[0] == test[2]) temp1 = test[0];
else if(test[1] == test[2]) temp1 = test[1];
else {
- printk(KERN_INFO
+ printk(KERN_INFO
"sisfb: TV detection unreliable - test results varied\n");
temp1 = test[2];
}
@@ -2945,11 +2701,11 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
orSISIDXREG(SISCR, 0x32, 0x01);
andSISIDXREG(SISCR, 0x32, ~0x06);
} else {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
andSISIDXREG(SISCR, 0x32, ~0x07);
}
} else if(temp1 == 0) {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
andSISIDXREG(SISCR, 0x32, ~0x07);
}
/* Set general purpose IO for Chrontel communication */
@@ -2960,19 +2716,19 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
#ifdef CONFIG_FB_SIS_315
ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
- temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+ temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
temp2 |= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 ^= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
- temp1 = 0;
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
+ temp1 = 0;
if(temp2 & 0x02) temp1 |= 0x01;
if(temp2 & 0x10) temp1 |= 0x01;
if(temp2 & 0x04) temp1 |= 0x02;
@@ -2983,18 +2739,18 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
ivideo->vbflags |= TV_AVIDEO;
orSISIDXREG(SISCR, 0x32, 0x01);
andSISIDXREG(SISCR, 0x32, ~0x06);
- break;
+ break;
case 0x02:
printk(KERN_INFO "%s SVIDEO output\n", stdstr);
ivideo->vbflags |= TV_SVIDEO;
orSISIDXREG(SISCR, 0x32, 0x02);
andSISIDXREG(SISCR, 0x32, ~0x05);
- break;
+ break;
case 0x04:
printk(KERN_INFO "%s SCART output\n", stdstr);
orSISIDXREG(SISCR, 0x32, 0x04);
andSISIDXREG(SISCR, 0x32, ~0x03);
- break;
+ break;
default:
andSISIDXREG(SISCR, 0x32, ~0x07);
}
@@ -3002,165 +2758,589 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
}
}
-/* ------------------------ Heap routines -------------------------- */
-
-static u32 __devinit
-sisfb_getheapstart(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_get_VB_type(struct sis_video_info *ivideo)
{
- u32 ret = ivideo->sisfb_parm_mem * 1024;
- u32 max = ivideo->video_size - ivideo->hwcursor_size;
- u32 def;
+ char stdstr[] = "sisfb: Detected";
+ char bridgestr[] = "video bridge";
+ u8 vb_chipid;
+ u8 reg;
- /* Calculate heap start = end of memory for console
- *
- * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
- * C = console, D = heap, H = HWCursor, Q = cmd-queue
- *
- * Basically given by "mem" parameter
- *
- * maximum = videosize - cmd_queue - hwcursor
- * (results in a heap of size 0)
- * default = SiS 300: depends on videosize
- * SiS 315/330: 32k below max
- */
+ /* No CRT2 on XGI Z7 */
+ if(ivideo->chip == XGI_20)
+ return;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- max -= TURBO_QUEUE_AREA_SIZE;
- if(ivideo->video_size > 0x1000000) {
- def = 0xc00000;
- } else if(ivideo->video_size > 0x800000) {
- def = 0x800000;
- } else {
- def = 0x400000;
- }
- } else {
- max -= COMMAND_QUEUE_AREA_SIZE;
- def = max - 0x8000;
+ inSISIDXREG(SISPART4, 0x00, vb_chipid);
+ switch(vb_chipid) {
+ case 0x01:
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if(reg < 0xb0) {
+ ivideo->vbflags |= VB_301; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301;
+ printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
+ } else if(reg < 0xc0) {
+ ivideo->vbflags |= VB_301B; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301B;
+ inSISIDXREG(SISPART4,0x23,reg);
+ if(!(reg & 0x02)) {
+ ivideo->vbflags |= VB_30xBDH; /* Deprecated */
+ ivideo->vbflags2 |= VB2_30xBDH;
+ printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
+ } else {
+ printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+ }
+ } else if(reg < 0xd0) {
+ ivideo->vbflags |= VB_301C; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301C;
+ printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
+ } else if(reg < 0xe0) {
+ ivideo->vbflags |= VB_301LV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301LV;
+ printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
+ } else if(reg <= 0xe1) {
+ inSISIDXREG(SISPART4,0x39,reg);
+ if(reg == 0xff) {
+ ivideo->vbflags |= VB_302LV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302LV;
+ printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+ } else {
+ ivideo->vbflags |= VB_301C; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301C;
+ printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0
+ ivideo->vbflags |= VB_302ELV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302ELV;
+ printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif
+ }
+ }
+ break;
+ case 0x02:
+ ivideo->vbflags |= VB_302B; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302B;
+ printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+ break;
}
- if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
- ret = def;
- }
+ if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+ inSISIDXREG(SISCR, 0x37, reg);
+ reg &= SIS_EXTERNAL_CHIP_MASK;
+ reg >>= 1;
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+ switch(reg) {
+ case SIS_EXTERNAL_CHIP_LVDS:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case SIS_EXTERNAL_CHIP_TRUMPION:
+ ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
+ break;
+ case SIS_EXTERNAL_CHIP_CHRONTEL:
+ ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
+ ivideo->vbflags2 |= VB2_CHRONTEL;
+ break;
+ case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
+#endif
+ } else if(ivideo->chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+ switch (reg) {
+ case SIS310_EXTERNAL_CHIP_LVDS:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+ } else if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+ inSISIDXREG(SISCR, 0x38, reg);
+ reg >>= 5;
+ switch(reg) {
+ case 0x02:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case 0x03:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ case 0x04:
+ ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+ }
+ if(ivideo->vbflags2 & VB2_LVDS) {
+ printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+ }
+ if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
+ printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+ }
+ if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
+ printk(KERN_INFO "%s Conexant external device\n", stdstr);
+ }
+ }
- return ret;
+ if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+ SiS_SenseLCD(ivideo);
+ SiS_Sense30x(ivideo);
+ } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ SiS_SenseCh(ivideo);
+ }
}
-static int __devinit
-sisfb_heap_init(struct sis_video_info *ivideo)
+/* ---------- Engine initialization routines ------------ */
+
+static void
+sisfb_engine_init(struct sis_video_info *ivideo)
{
- SIS_OH *poh;
- ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
+ /* Initialize command queue (we use MMIO only) */
- ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
- ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size;
+ /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
- /* Initialize command queue (We use MMIO only) */
+ ivideo->caps &= ~(TURBO_QUEUE_CAP |
+ MMIO_CMD_QUEUE_CAP |
+ VM_CMD_QUEUE_CAP |
+ AGP_CMD_QUEUE_CAP);
+
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ u32 tqueue_pos;
+ u8 tq_state;
+
+ tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
+
+ inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+ tq_state |= 0xf0;
+ tq_state &= 0xfc;
+ tq_state |= (u8)(tqueue_pos >> 8);
+ outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+
+ outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+
+ ivideo->caps |= TURBO_QUEUE_CAP;
+ }
+#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- u32 tempq = 0;
- u8 temp = 0;
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ u32 tempq = 0, templ;
+ u8 temp;
+
+ if(ivideo->chip == XGI_20) {
+ switch(ivideo->cmdQueueSize) {
+ case (64 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
+ break;
+ case (128 * 1024):
+ default:
+ temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
+ }
+ } else {
+ switch(ivideo->cmdQueueSize) {
+ case (4 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_4M;
+ break;
+ case (2 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_2M;
+ break;
+ case (1 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_1M;
+ break;
+ default:
+ case (512 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_512k;
+ }
+ }
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+ if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
+ /* Must disable dual pipe on XGI_40. Can't do
+ * this in MMIO mode, because it requires
+ * setting/clearing a bit in the MMIO fire trigger
+ * register.
+ */
+ if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
+
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+
+ tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
+
+ tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+ MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
+
+ writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
+ writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
+ writel(0x168F0000, ivideo->video_vbase + tempq + 8);
+ writel(0x168F0000, ivideo->video_vbase + tempq + 12);
+
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
+
+ sisfb_syncaccel(ivideo);
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+ }
+ }
+
+ tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+ MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+ temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+
+ tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+ MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
- ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+ }
+#endif
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+ ivideo->engineok = 1;
+}
- tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+static void __devinit
+sisfb_detect_lcd_type(struct sis_video_info *ivideo)
+{
+ u8 reg;
+ int i;
- temp = SIS_CMD_QUEUE_SIZE_512k;
- temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+ inSISIDXREG(SISCR, 0x36, reg);
+ reg &= 0x0f;
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ ivideo->CRT2LCDType = sis300paneltype[reg];
+ } else if(ivideo->chip >= SIS_661) {
+ ivideo->CRT2LCDType = sis661paneltype[reg];
+ } else {
+ ivideo->CRT2LCDType = sis310paneltype[reg];
+ if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+ if((ivideo->CRT2LCDType != LCD_320x240_2) &&
+ (ivideo->CRT2LCDType != LCD_320x240_3)) {
+ ivideo->CRT2LCDType = LCD_320x240;
+ }
+ }
+ }
- tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
+ if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
+ /* For broken BIOSes: Assume 1024x768, RGB18 */
+ ivideo->CRT2LCDType = LCD_1024x768;
+ setSISIDXREG(SISCR,0x36,0xf0,0x02);
+ setSISIDXREG(SISCR,0x37,0xee,0x01);
+ printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
+ }
- ivideo->caps |= MMIO_CMD_QUEUE_CAP;
- }
+ for(i = 0; i < SIS_LCD_NUMBER; i++) {
+ if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
+ ivideo->lcdxres = sis_lcd_data[i].xres;
+ ivideo->lcdyres = sis_lcd_data[i].yres;
+ ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+ break;
+ }
+ }
+
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+ ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
+ } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+ ivideo->lcdxres = 848; ivideo->lcdyres = 480;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_848;
+ } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
+ ivideo->lcdxres = 856; ivideo->lcdyres = 480;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_856;
+ }
#endif
+ printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
+ ivideo->lcdxres, ivideo->lcdyres);
+}
+
+static void __devinit
+sisfb_save_pdc_emi(struct sis_video_info *ivideo)
+{
#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- unsigned long tqueue_pos;
- u8 tq_state;
+ /* Save the current PanelDelayCompensation if the LCD is currently used */
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
+ int tmp;
+ inSISIDXREG(SISCR,0x30,tmp);
+ if(tmp & 0x20) {
+ /* Currently on LCD? If yes, read current pdc */
+ inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+ ivideo->detectedpdc &= 0x3c;
+ if(ivideo->SiS_Pr.PDC == -1) {
+ /* Let option override detection */
+ ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+ }
+ printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+ ivideo->detectedpdc);
+ }
+ if((ivideo->SiS_Pr.PDC != -1) &&
+ (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
+ ivideo->SiS_Pr.PDC);
+ }
+ }
+ }
+#endif
- ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
- tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+ /* Try to find about LCDA */
+ if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
+ int tmp;
+ inSISIDXREG(SISPART1,0x13,tmp);
+ if(tmp & 0x04) {
+ ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+ ivideo->detectedlcda = 0x03;
+ }
+ }
- inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
- tq_state |= 0xf0;
- tq_state &= 0xfc;
- tq_state |= (u8)(tqueue_pos >> 8);
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+ /* Save PDC */
+ if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+ int tmp;
+ inSISIDXREG(SISCR,0x30,tmp);
+ if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+ /* Currently on LCD? If yes, read current pdc */
+ u8 pdc;
+ inSISIDXREG(SISPART1,0x2D,pdc);
+ ivideo->detectedpdc = (pdc & 0x0f) << 1;
+ ivideo->detectedpdca = (pdc & 0xf0) >> 3;
+ inSISIDXREG(SISPART1,0x35,pdc);
+ ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
+ inSISIDXREG(SISPART1,0x20,pdc);
+ ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+ if(ivideo->newrom) {
+ /* New ROM invalidates other PDC resp. */
+ if(ivideo->detectedlcda != 0xff) {
+ ivideo->detectedpdc = 0xff;
+ } else {
+ ivideo->detectedpdca = 0xff;
+ }
+ }
+ if(ivideo->SiS_Pr.PDC == -1) {
+ if(ivideo->detectedpdc != 0xff) {
+ ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+ }
+ }
+ if(ivideo->SiS_Pr.PDCA == -1) {
+ if(ivideo->detectedpdca != 0xff) {
+ ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
+ }
+ }
+ if(ivideo->detectedpdc != 0xff) {
+ printk(KERN_INFO
+ "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+ ivideo->detectedpdc);
+ }
+ if(ivideo->detectedpdca != 0xff) {
+ printk(KERN_INFO
+ "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+ ivideo->detectedpdca);
+ }
+ }
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+ /* Save EMI */
+ if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
+ inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+ inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+ inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+ inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+ ivideo->SiS_Pr.HaveEMI = TRUE;
+ if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+ ivideo->SiS_Pr.HaveEMILCD = TRUE;
+ }
+ }
+ }
- ivideo->caps |= TURBO_QUEUE_CAP;
- }
+ /* Let user override detected PDCs (all bridges) */
+ if(ivideo->vbflags2 & VB2_30xBLV) {
+ if((ivideo->SiS_Pr.PDC != -1) &&
+ (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+ ivideo->SiS_Pr.PDC);
+ }
+ if((ivideo->SiS_Pr.PDCA != -1) &&
+ (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+ ivideo->SiS_Pr.PDCA);
+ }
+ }
+
+ }
#endif
+}
- /* Reserve memory for the HWCursor */
- ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
- ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
- ivideo->caps |= HW_CURSOR_CAP;
+/* -------------------- Memory manager routines ---------------------- */
- ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
+{
+ u32 ret = ivideo->sisfb_parm_mem * 1024;
+ u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+ u32 def;
- if(ivideo->cardnumber == 0) {
+ /* Calculate heap start = end of memory for console
+ *
+ * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+ * C = console, D = heap, H = HWCursor, Q = cmd-queue
+ *
+ * On 76x in UMA+LFB mode, the layout is as follows:
+ * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
+ * where the heap is the entire UMA area, eventually
+ * into the LFB area if the given mem parameter is
+ * higher than the size of the UMA memory.
+ *
+ * Basically given by "mem" parameter
+ *
+ * maximum = videosize - cmd_queue - hwcursor
+ * (results in a heap of size 0)
+ * default = SiS 300: depends on videosize
+ * SiS 315/330/340/XGI: 32k below max
+ */
- printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
- (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->video_size > 0x1000000) {
+ def = 0xc00000;
+ } else if(ivideo->video_size > 0x800000) {
+ def = 0x800000;
+ } else {
+ def = 0x400000;
+ }
+ } else if(ivideo->UMAsize && ivideo->LFBsize) {
+ ret = def = 0;
+ } else {
+ def = maxoffs - 0x8000;
+ }
- sisfb_heap.vinfo = ivideo;
+ /* Use default for secondary card for now (FIXME) */
+ if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
+ ret = def;
- sisfb_heap.poha_chain = NULL;
- sisfb_heap.poh_freelist = NULL;
+ return ret;
+}
- poh = sisfb_poh_new_node();
- if(poh == NULL) return 1;
+static u32 __devinit
+sisfb_getheapsize(struct sis_video_info *ivideo)
+{
+ u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+ u32 ret = 0;
+
+ if(ivideo->UMAsize && ivideo->LFBsize) {
+ if( (!ivideo->sisfb_parm_mem) ||
+ ((ivideo->sisfb_parm_mem * 1024) > max) ||
+ ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
+ ret = ivideo->UMAsize;
+ max -= ivideo->UMAsize;
+ } else {
+ ret = max - (ivideo->sisfb_parm_mem * 1024);
+ max = ivideo->sisfb_parm_mem * 1024;
+ }
+ ivideo->video_offset = ret;
+ ivideo->sisfb_mem = max;
+ } else {
+ ret = max - ivideo->heapstart;
+ ivideo->sisfb_mem = ivideo->heapstart;
+ }
- poh->poh_next = &sisfb_heap.oh_free;
- poh->poh_prev = &sisfb_heap.oh_free;
- poh->size = ivideo->sisfb_heap_size;
- poh->offset = ivideo->heapstart;
+ return ret;
+}
- sisfb_heap.oh_free.poh_next = poh;
- sisfb_heap.oh_free.poh_prev = poh;
- sisfb_heap.oh_free.size = 0;
- sisfb_heap.max_freesize = poh->size;
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+ struct SIS_OH *poh;
- sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.size = SENTINEL;
+ ivideo->video_offset = 0;
+ if(ivideo->sisfb_parm_mem) {
+ if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
+ (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
+ ivideo->sisfb_parm_mem = 0;
+ }
+ }
- } else {
+ ivideo->heapstart = sisfb_getheapstart(ivideo);
+ ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
- printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+ ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+ ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
- }
+ printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+ (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
- return 0;
+ ivideo->sisfb_heap.vinfo = ivideo;
+
+ ivideo->sisfb_heap.poha_chain = NULL;
+ ivideo->sisfb_heap.poh_freelist = NULL;
+
+ poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
+ if(poh == NULL)
+ return 1;
+
+ poh->poh_next = &ivideo->sisfb_heap.oh_free;
+ poh->poh_prev = &ivideo->sisfb_heap.oh_free;
+ poh->size = ivideo->sisfb_heap_size;
+ poh->offset = ivideo->heapstart;
+
+ ivideo->sisfb_heap.oh_free.poh_next = poh;
+ ivideo->sisfb_heap.oh_free.poh_prev = poh;
+ ivideo->sisfb_heap.oh_free.size = 0;
+ ivideo->sisfb_heap.max_freesize = poh->size;
+
+ ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
+ ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
+ ivideo->sisfb_heap.oh_used.size = SENTINEL;
+
+ if(ivideo->cardnumber == 0) {
+ /* For the first card, make this heap the "global" one
+ * for old DRM (which could handle only one card)
+ */
+ sisfb_heap = &ivideo->sisfb_heap;
+ }
+
+ return 0;
}
-static SIS_OH *
-sisfb_poh_new_node(void)
+static struct SIS_OH *
+sisfb_poh_new_node(struct SIS_HEAP *memheap)
{
- int i;
- unsigned long cOhs;
- SIS_OHALLOC *poha;
- SIS_OH *poh;
+ struct SIS_OHALLOC *poha;
+ struct SIS_OH *poh;
+ unsigned long cOhs;
+ int i;
- if(sisfb_heap.poh_freelist == NULL) {
+ if(memheap->poh_freelist == NULL) {
poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
- if(!poha) return NULL;
+ if(!poha)
+ return NULL;
- poha->poha_next = sisfb_heap.poha_chain;
- sisfb_heap.poha_chain = poha;
+ poha->poha_next = memheap->poha_chain;
+ memheap->poha_chain = poha;
- cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+ cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
poh = &poha->aoh[0];
for(i = cOhs - 1; i != 0; i--) {
@@ -3169,32 +3349,32 @@ sisfb_poh_new_node(void)
}
poh->poh_next = NULL;
- sisfb_heap.poh_freelist = &poha->aoh[0];
+ memheap->poh_freelist = &poha->aoh[0];
}
- poh = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh->poh_next;
+ poh = memheap->poh_freelist;
+ memheap->poh_freelist = poh->poh_next;
- return (poh);
+ return poh;
}
-static SIS_OH *
-sisfb_poh_allocate(u32 size)
+static struct SIS_OH *
+sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
{
- SIS_OH *pohThis;
- SIS_OH *pohRoot;
- int bAllocated = 0;
+ struct SIS_OH *pohThis;
+ struct SIS_OH *pohRoot;
+ int bAllocated = 0;
- if(size > sisfb_heap.max_freesize) {
+ if(size > memheap->max_freesize) {
DPRINTK("sisfb: Can't allocate %dk video memory\n",
(unsigned int) size / 1024);
- return (NULL);
+ return NULL;
}
- pohThis = sisfb_heap.oh_free.poh_next;
+ pohThis = memheap->oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
- if (size <= pohThis->size) {
+ while(pohThis != &memheap->oh_free) {
+ if(size <= pohThis->size) {
bAllocated = 1;
break;
}
@@ -3204,18 +3384,16 @@ sisfb_poh_allocate(u32 size)
if(!bAllocated) {
DPRINTK("sisfb: Can't allocate %dk video memory\n",
(unsigned int) size / 1024);
- return (NULL);
+ return NULL;
}
if(size == pohThis->size) {
pohRoot = pohThis;
sisfb_delete_node(pohThis);
} else {
- pohRoot = sisfb_poh_new_node();
-
- if(pohRoot == NULL) {
- return (NULL);
- }
+ pohRoot = sisfb_poh_new_node(memheap);
+ if(pohRoot == NULL)
+ return NULL;
pohRoot->offset = pohThis->offset;
pohRoot->size = size;
@@ -3224,33 +3402,25 @@ sisfb_poh_allocate(u32 size)
pohThis->size -= size;
}
- sisfb_heap.max_freesize -= size;
+ memheap->max_freesize -= size;
- pohThis = &sisfb_heap.oh_used;
+ pohThis = &memheap->oh_used;
sisfb_insert_node(pohThis, pohRoot);
- return (pohRoot);
+ return pohRoot;
}
static void
-sisfb_delete_node(SIS_OH *poh)
+sisfb_delete_node(struct SIS_OH *poh)
{
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
-
- poh_prev = poh->poh_prev;
- poh_next = poh->poh_next;
-
- poh_prev->poh_next = poh_next;
- poh_next->poh_prev = poh_prev;
+ poh->poh_prev->poh_next = poh->poh_next;
+ poh->poh_next->poh_prev = poh->poh_prev;
}
static void
-sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
{
- SIS_OH *pohTemp;
-
- pohTemp = pohList->poh_next;
+ struct SIS_OH *pohTemp = pohList->poh_next;
pohList->poh_next = poh;
pohTemp->poh_prev = poh;
@@ -3259,20 +3429,20 @@ sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
poh->poh_next = pohTemp;
}
-static SIS_OH *
-sisfb_poh_free(u32 base)
+static struct SIS_OH *
+sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
{
- SIS_OH *pohThis;
- SIS_OH *poh_freed;
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
- u32 ulUpper;
- u32 ulLower;
- int foundNode = 0;
+ struct SIS_OH *pohThis;
+ struct SIS_OH *poh_freed;
+ struct SIS_OH *poh_prev;
+ struct SIS_OH *poh_next;
+ u32 ulUpper;
+ u32 ulLower;
+ int foundNode = 0;
- poh_freed = sisfb_heap.oh_used.poh_next;
+ poh_freed = memheap->oh_used.poh_next;
- while(poh_freed != &sisfb_heap.oh_used) {
+ while(poh_freed != &memheap->oh_used) {
if(poh_freed->offset == base) {
foundNode = 1;
break;
@@ -3281,17 +3451,18 @@ sisfb_poh_free(u32 base)
poh_freed = poh_freed->poh_next;
}
- if(!foundNode) return(NULL);
+ if(!foundNode)
+ return NULL;
- sisfb_heap.max_freesize += poh_freed->size;
+ memheap->max_freesize += poh_freed->size;
poh_prev = poh_next = NULL;
ulUpper = poh_freed->offset + poh_freed->size;
ulLower = poh_freed->offset;
- pohThis = sisfb_heap.oh_free.poh_next;
+ pohThis = memheap->oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
+ while(pohThis != &memheap->oh_free) {
if(pohThis->offset == ulUpper) {
poh_next = pohThis;
} else if((pohThis->offset + pohThis->size) == ulLower) {
@@ -3305,70 +3476,88 @@ sisfb_poh_free(u32 base)
if(poh_prev && poh_next) {
poh_prev->size += (poh_freed->size + poh_next->size);
sisfb_delete_node(poh_next);
- sisfb_free_node(poh_freed);
- sisfb_free_node(poh_next);
- return(poh_prev);
+ sisfb_free_node(memheap, poh_freed);
+ sisfb_free_node(memheap, poh_next);
+ return poh_prev;
}
if(poh_prev) {
poh_prev->size += poh_freed->size;
- sisfb_free_node(poh_freed);
- return(poh_prev);
+ sisfb_free_node(memheap, poh_freed);
+ return poh_prev;
}
if(poh_next) {
poh_next->size += poh_freed->size;
poh_next->offset = poh_freed->offset;
- sisfb_free_node(poh_freed);
- return(poh_next);
+ sisfb_free_node(memheap, poh_freed);
+ return poh_next;
}
- sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
+ sisfb_insert_node(&memheap->oh_free, poh_freed);
- return(poh_freed);
+ return poh_freed;
}
static void
-sisfb_free_node(SIS_OH *poh)
+sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
{
- if(poh == NULL) return;
+ if(poh == NULL)
+ return;
- poh->poh_next = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh;
+ poh->poh_next = memheap->poh_freelist;
+ memheap->poh_freelist = poh;
}
-void
-sis_malloc(struct sis_memreq *req)
+static void
+sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
{
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh = NULL;
+ struct SIS_OH *poh = NULL;
- if((ivideo) && (!ivideo->havenoheap)) {
- poh = sisfb_poh_allocate((u32)req->size);
- }
+ if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
+ poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
if(poh == NULL) {
- req->offset = req->size = 0;
- DPRINTK("sisfb: Video RAM allocation failed\n");
+ req->offset = req->size = 0;
+ DPRINTK("sisfb: Video RAM allocation failed\n");
} else {
- req->offset = poh->offset;
- req->size = poh->size;
- DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
- (poh->offset + ivideo->video_vbase));
+ req->offset = poh->offset;
+ req->size = poh->size;
+ DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+ (poh->offset + ivideo->video_vbase));
}
}
-/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+void
+sis_malloc(struct sis_memreq *req)
+{
+ struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+ if(&ivideo->sisfb_heap == sisfb_heap)
+ sis_int_malloc(ivideo, req);
+ else
+ req->offset = req->size = 0;
+}
void
-sis_free(u32 base)
+sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
{
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh;
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+ sis_int_malloc(ivideo, req);
+}
+
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
- if((!ivideo) || (ivideo->havenoheap)) return;
+static void
+sis_int_free(struct sis_video_info *ivideo, u32 base)
+{
+ struct SIS_OH *poh;
- poh = sisfb_poh_free((u32)base);
+ if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
+ return;
+
+ poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
if(poh == NULL) {
DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3376,9 +3565,63 @@ sis_free(u32 base)
}
}
+void
+sis_free(u32 base)
+{
+ struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+ sis_int_free(ivideo, base);
+}
+
+void
+sis_free_new(struct pci_dev *pdev, u32 base)
+{
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+ sis_int_free(ivideo, base);
+}
+
/* --------------------- SetMode routines ------------------------- */
static void
+sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
+{
+ u8 cr30, cr31;
+
+ /* Check if MMIO and engines are enabled,
+ * and sync in case they are. Can't use
+ * ivideo->accel here, as this might have
+ * been changed before this is called.
+ */
+ inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
+ inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
+ /* MMIO and 2D/3D engine enabled? */
+ if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ /* Don't care about TurboQueue. It's
+ * enough to know that the engines
+ * are enabled
+ */
+ sisfb_syncaccel(ivideo);
+ }
+#endif
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ /* Check that any queue mode is
+ * enabled, and that the queue
+ * is not in the state of "reset"
+ */
+ inSISIDXREG(SISSR, 0x26, cr30);
+ if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
+ sisfb_syncaccel(ivideo);
+ }
+ }
+#endif
+ }
+}
+
+static void
sisfb_pre_setmode(struct sis_video_info *ivideo)
{
u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
@@ -3386,6 +3629,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
inSISIDXREG(SISCR, 0x31, cr31);
cr31 &= ~0x60;
cr31 |= 0x04;
@@ -3413,41 +3658,43 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
case CRT2_TV:
cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
- if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+ if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
#ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
+ if(ivideo->chip >= SIS_661) {
+ cr38 |= 0x04;
+ if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
cr35 &= ~0x01;
ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+ cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
cr38 |= 0x08;
- if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
+ if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
cr31 &= ~0x01;
ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- }
-#endif
- } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- cr35 |= 0x60;
- } else {
- cr30 |= 0x80;
- }
+ }
+#endif
+ } else if((ivideo->vbflags & TV_HIVISION) &&
+ (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
+ if(ivideo->chip >= SIS_661) {
+ cr38 |= 0x04;
+ cr35 |= 0x60;
+ } else {
+ cr30 |= 0x80;
+ }
cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= 0x01;
- cr35 |= 0x01;
+ cr31 |= 0x01;
+ cr35 |= 0x01;
ivideo->currentvbflags |= TV_HIVISION;
} else if(ivideo->vbflags & TV_SCART) {
cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
@@ -3466,8 +3713,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
}
cr31 |= SIS_DRIVER_MODE;
- if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
- if(ivideo->vbflags & TV_PAL) {
+ if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
+ if(ivideo->vbflags & TV_PAL) {
cr31 |= 0x01; cr35 |= 0x01;
ivideo->currentvbflags |= TV_PAL;
if(ivideo->vbflags & TV_PALM) {
@@ -3476,14 +3723,14 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
} else if(ivideo->vbflags & TV_PALN) {
cr38 |= 0x80; cr35 |= 0x08;
ivideo->currentvbflags |= TV_PALN;
- }
- } else {
+ }
+ } else {
cr31 &= ~0x01; cr35 &= ~0x01;
ivideo->currentvbflags |= TV_NTSC;
if(ivideo->vbflags & TV_NTSCJ) {
cr38 |= 0x40; cr35 |= 0x02;
ivideo->currentvbflags |= TV_NTSCJ;
- }
+ }
}
}
break;
@@ -3493,6 +3740,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
cr31 |= SIS_DRIVER_MODE;
SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+ ivideo->curFSTN = ivideo->sisfb_fstn;
+ ivideo->curDSTN = ivideo->sisfb_dstn;
break;
case CRT2_VGA:
@@ -3525,9 +3774,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
}
outSISIDXREG(SISCR, 0x31, cr31);
- if(ivideo->accel) sisfb_syncaccel(ivideo);
-
ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+
+ sisfb_check_engine_and_sync(ivideo);
}
/* Fix SR11 for 661 and later */
@@ -3535,125 +3784,129 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
static void
sisfb_fixup_SR11(struct sis_video_info *ivideo)
{
- u8 tmpreg;
-
- if(ivideo->chip >= SIS_661) {
- inSISIDXREG(SISSR,0x11,tmpreg);
- if(tmpreg & 0x20) {
- inSISIDXREG(SISSR,0x3e,tmpreg);
- tmpreg = (tmpreg + 1) & 0xff;
- outSISIDXREG(SISSR,0x3e,tmpreg);
- inSISIDXREG(SISSR,0x11,tmpreg);
- }
- if(tmpreg & 0xf0) {
- andSISIDXREG(SISSR,0x11,0x0f);
- }
- }
+ u8 tmpreg;
+
+ if(ivideo->chip >= SIS_661) {
+ inSISIDXREG(SISSR,0x11,tmpreg);
+ if(tmpreg & 0x20) {
+ inSISIDXREG(SISSR,0x3e,tmpreg);
+ tmpreg = (tmpreg + 1) & 0xff;
+ outSISIDXREG(SISSR,0x3e,tmpreg);
+ inSISIDXREG(SISSR,0x11,tmpreg);
+ }
+ if(tmpreg & 0xf0) {
+ andSISIDXREG(SISSR,0x11,0x0f);
+ }
+ }
}
#endif
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
{
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvxpos = val;
+ if(val > 32) val = 32;
+ if(val < -32) val = -32;
+ ivideo->tvxpos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
+ if(ivideo->sisfblocked) return;
+ if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
+ if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_CHRONTEL) {
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
- int x = ivideo->tvx;
+ int x = ivideo->tvx;
- switch(ivideo->chronteltype) {
- case 1:
- x += val;
- if(x < 0) x = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
-
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
- unsigned short temp;
-
- p2_1f = ivideo->p2_1f;
- p2_20 = ivideo->p2_20;
- p2_2b = ivideo->p2_2b;
- p2_42 = ivideo->p2_42;
- p2_43 = ivideo->p2_43;
-
- temp = p2_1f | ((p2_20 & 0xf0) << 4);
- temp += (val * 2);
- p2_1f = temp & 0xff;
- p2_20 = (temp & 0xf00) >> 4;
- p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
- temp = p2_43 | ((p2_42 & 0xf0) << 4);
- temp += (val * 2);
- p2_43 = temp & 0xff;
- p2_42 = (temp & 0xf00) >> 4;
- outSISIDXREG(SISPART2,0x1f,p2_1f);
- setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
- setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
- setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
- outSISIDXREG(SISPART2,0x43,p2_43);
- }
- }
+ switch(ivideo->chronteltype) {
+ case 1:
+ x += val;
+ if(x < 0) x = 0;
+ outSISIDXREG(SISSR,0x05,0x86);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
+ break;
+ case 2:
+ /* Not supported by hardware */
+ break;
+ }
+
+ } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+ u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+ unsigned short temp;
+
+ p2_1f = ivideo->p2_1f;
+ p2_20 = ivideo->p2_20;
+ p2_2b = ivideo->p2_2b;
+ p2_42 = ivideo->p2_42;
+ p2_43 = ivideo->p2_43;
+
+ temp = p2_1f | ((p2_20 & 0xf0) << 4);
+ temp += (val * 2);
+ p2_1f = temp & 0xff;
+ p2_20 = (temp & 0xf00) >> 4;
+ p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+ temp = p2_43 | ((p2_42 & 0xf0) << 4);
+ temp += (val * 2);
+ p2_43 = temp & 0xff;
+ p2_42 = (temp & 0xf00) >> 4;
+ outSISIDXREG(SISPART2,0x1f,p2_1f);
+ setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+ setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+ setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+ outSISIDXREG(SISPART2,0x43,p2_43);
+ }
+ }
}
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
{
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvypos = val;
-
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
-
- if(ivideo->currentvbflags & CRT2_TV) {
-
- if(ivideo->vbflags & VB_CHRONTEL) {
-
- int y = ivideo->tvy;
-
- switch(ivideo->chronteltype) {
- case 1:
- y -= val;
- if(y < 0) y = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
-
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
- char p2_01, p2_02;
- val /= 2;
- p2_01 = ivideo->p2_01;
- p2_02 = ivideo->p2_02;
-
- p2_01 += val;
- p2_02 += val;
- while((p2_01 <= 0) || (p2_02 <= 0)) {
- p2_01 += 2;
- p2_02 += 2;
- }
- outSISIDXREG(SISPART2,0x01,p2_01);
- outSISIDXREG(SISPART2,0x02,p2_02);
- }
- }
+ if(val > 32) val = 32;
+ if(val < -32) val = -32;
+ ivideo->tvypos = val;
+
+ if(ivideo->sisfblocked) return;
+ if(!ivideo->modechanged) return;
+
+ if(ivideo->currentvbflags & CRT2_TV) {
+
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+
+ int y = ivideo->tvy;
+
+ switch(ivideo->chronteltype) {
+ case 1:
+ y -= val;
+ if(y < 0) y = 0;
+ outSISIDXREG(SISSR,0x05,0x86);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
+ break;
+ case 2:
+ /* Not supported by hardware */
+ break;
+ }
+
+ } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+ char p2_01, p2_02;
+ val /= 2;
+ p2_01 = ivideo->p2_01;
+ p2_02 = ivideo->p2_02;
+
+ p2_01 += val;
+ p2_02 += val;
+ if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
+ while((p2_01 <= 0) || (p2_02 <= 0)) {
+ p2_01 += 2;
+ p2_02 += 2;
+ }
+ }
+ outSISIDXREG(SISPART2,0x01,p2_01);
+ outSISIDXREG(SISPART2,0x02,p2_02);
+ }
+ }
}
static void
@@ -3668,207 +3921,172 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
u8 reg1;
#endif
- outSISIDXREG(SISSR,0x05,0x86);
+ outSISIDXREG(SISSR, 0x05, 0x86);
#ifdef CONFIG_FB_SIS_315
sisfb_fixup_SR11(ivideo);
#endif
/* Now we actually HAVE changed the display mode */
- ivideo->modechanged = 1;
+ ivideo->modechanged = 1;
/* We can't switch off CRT1 if bridge is in slave mode */
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
- } else ivideo->sisfb_crt1off = 0;
+ } else
+ ivideo->sisfb_crt1off = 0;
#ifdef CONFIG_FB_SIS_300
if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x00;
- } else {
- crt1isoff = FALSE;
- reg = 0x80;
- }
- setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+ if((ivideo->sisfb_crt1off) && (doit)) {
+ crt1isoff = TRUE;
+ reg = 0x00;
+ } else {
+ crt1isoff = FALSE;
+ reg = 0x80;
+ }
+ setSISIDXREG(SISCR, 0x17, 0x7f, reg);
}
#endif
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x40;
- reg1 = 0xc0;
- } else {
- crt1isoff = FALSE;
- reg = 0x00;
- reg1 = 0x00;
-
- }
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
- setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
+ if((ivideo->sisfb_crt1off) && (doit)) {
+ crt1isoff = TRUE;
+ reg = 0x40;
+ reg1 = 0xc0;
+ } else {
+ crt1isoff = FALSE;
+ reg = 0x00;
+ reg1 = 0x00;
+ }
+ setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+ setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
}
#endif
if(crt1isoff) {
- ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
- ivideo->currentvbflags |= VB_SINGLE_MODE;
+ ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+ ivideo->currentvbflags |= VB_SINGLE_MODE;
} else {
- ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
- ivideo->currentvbflags |= VB_MIRROR_MODE;
- } else {
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- }
+ ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+ if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+ ivideo->currentvbflags |= VB_MIRROR_MODE;
+ } else {
+ ivideo->currentvbflags |= VB_SINGLE_MODE;
+ }
}
- andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+ andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_SISBRIDGE) {
- inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
- inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
- inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
- inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
- inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
- inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
- inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- if(ivideo->chronteltype == 1) {
- ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
- ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
- ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
- ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
- }
- }
+ if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+ inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+ inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+ inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+ inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+ inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+ inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+ inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+ } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ if(ivideo->chronteltype == 1) {
+ ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+ ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+ ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+ ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+ }
+ }
}
if(ivideo->tvxpos) {
- sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+ sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
}
if(ivideo->tvypos) {
- sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+ sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
}
- if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */
+ /* Eventually sync engines */
+ sisfb_check_engine_and_sync(ivideo);
- unsigned char filter_tb = 0;
+ /* (Re-)Initialize chip engines */
+ if(ivideo->accel) {
+ sisfb_engine_init(ivideo);
+ } else {
+ ivideo->engineok = 0;
+ }
+}
- switch (ivideo->video_width) {
- case 320:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
- break;
- case 640:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
- break;
- case 720:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
- break;
- case 400:
- case 800:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
- break;
- default:
- ivideo->sisfb_filter = -1;
- break;
- }
+static int
+sisfb_reset_mode(struct sis_video_info *ivideo)
+{
+ if(sisfb_set_mode(ivideo, 0))
+ return 1;
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
+ sisfb_set_pitch(ivideo);
+ sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+ sisfb_set_base_CRT2(ivideo, ivideo->current_base);
- if(ivideo->vbflags & TV_NTSC) {
-
- andSISIDXREG(SISPART2, 0x3a, 0x1f);
-
- if (ivideo->vbflags & TV_SVIDEO) {
-
- andSISIDXREG(SISPART2, 0x30, 0xdf);
-
- } else if (ivideo->vbflags & TV_AVIDEO) {
-
- orSISIDXREG(SISPART2, 0x30, 0x20);
-
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x04);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0x18);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xEE);
- outSISIDXREG(SISPART2, 0x36, 0x0C);
- outSISIDXREG(SISPART2, 0x37, 0x22);
- outSISIDXREG(SISPART2, 0x38, 0x08);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x15);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0xF6);
- break;
- }
- }
+ return 0;
+}
+
+static void
+sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
+{
+ int mycrt1off;
- } else if(ivideo->vbflags & TV_PAL) {
-
- andSISIDXREG(SISPART2, 0x3A, 0x1F);
-
- if (ivideo->vbflags & TV_SVIDEO) {
-
- andSISIDXREG(SISPART2, 0x30, 0xDF);
-
- } else if (ivideo->vbflags & TV_AVIDEO) {
-
- orSISIDXREG(SISPART2, 0x30, 0x20);
-
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xF1);
- outSISIDXREG(SISPART2, 0x36, 0xF7);
- outSISIDXREG(SISPART2, 0x37, 0x1F);
- outSISIDXREG(SISPART2, 0x38, 0x32);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xF3);
- outSISIDXREG(SISPART2, 0x36, 0x00);
- outSISIDXREG(SISPART2, 0x37, 0x1D);
- outSISIDXREG(SISPART2, 0x38, 0x20);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xFC);
- outSISIDXREG(SISPART2, 0x36, 0xFB);
- outSISIDXREG(SISPART2, 0x37, 0x14);
- outSISIDXREG(SISPART2, 0x38, 0x2A);
- break;
+ switch(sisfb_command->sisfb_cmd) {
+ case SISFB_CMD_GETVBFLAGS:
+ if(!ivideo->modechanged) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+ } else {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
+ sisfb_command->sisfb_result[2] = ivideo->vbflags2;
+ }
+ break;
+ case SISFB_CMD_SWITCHCRT1:
+ /* arg[0]: 0 = off, 1 = on, 99 = query */
+ if(!ivideo->modechanged) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+ } else if(sisfb_command->sisfb_arg[0] == 99) {
+ /* Query */
+ sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ } else if(ivideo->sisfblocked) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
+ } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
+ (sisfb_command->sisfb_arg[0] == 0)) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
+ } else {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
+ if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
+ ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
+ ivideo->sisfb_crt1off = mycrt1off;
+ if(sisfb_reset_mode(ivideo)) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
}
}
+ sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
}
-
- if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
- outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
- outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
- outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
- outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
- }
-
+ break;
+ /* more to come */
+ default:
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
+ printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
+ sisfb_command->sisfb_cmd);
}
}
#ifndef MODULE
-SISINITSTATIC int __init sisfb_setup(char *options)
+SISINITSTATIC int __init
+sisfb_setup(char *options)
{
char *this_opt;
-
- sisfb_setdefaultparms();
- printk(KERN_DEBUG "sisfb: Options %s\n", options);
+ sisfb_setdefaultparms();
- if(!options || !(*options)) {
+ if(!options || !(*options))
return 0;
- }
while((this_opt = strsep(&options, ",")) != NULL) {
@@ -3880,9 +4098,9 @@ SISINITSTATIC int __init sisfb_setup(char *options)
/* Need to check crt2 type first for fstn/dstn */
sisfb_search_crt2type(this_opt + 14);
} else if(!strnicmp(this_opt, "tvmode:",7)) {
- sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "tvstandard:",11)) {
sisfb_search_tvstd(this_opt + 7);
+ } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+ sisfb_search_tvstd(this_opt + 11);
} else if(!strnicmp(this_opt, "mode:", 5)) {
sisfb_search_mode(this_opt + 5, FALSE);
} else if(!strnicmp(this_opt, "vesa:", 5)) {
@@ -3892,74 +4110,72 @@ SISINITSTATIC int __init sisfb_setup(char *options)
sisfb_inverse = 1;
/* fb_invert_cmaps(); */
} else if(!strnicmp(this_opt, "font:", 5)) {
- if(strlen(this_opt + 5) < 40) {
+ if(strlen(this_opt + 5) < 40) {
strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
}
#endif
} else if(!strnicmp(this_opt, "rate:", 5)) {
sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "filter:", 7)) {
- sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
- } else if(!strnicmp(this_opt, "mem:",4)) {
- sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
+ } else if(!strnicmp(this_opt, "mem:",4)) {
+ sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc:", 4)) {
- sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+ sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc1:", 5)) {
- sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+ sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
} else if(!strnicmp(this_opt, "noaccel", 7)) {
sisfb_accel = 0;
} else if(!strnicmp(this_opt, "accel", 5)) {
sisfb_accel = -1;
} else if(!strnicmp(this_opt, "noypan", 6)) {
- sisfb_ypan = 0;
+ sisfb_ypan = 0;
} else if(!strnicmp(this_opt, "ypan", 4)) {
- sisfb_ypan = -1;
+ sisfb_ypan = -1;
} else if(!strnicmp(this_opt, "nomax", 5)) {
- sisfb_max = 0;
+ sisfb_max = 0;
} else if(!strnicmp(this_opt, "max", 3)) {
- sisfb_max = -1;
+ sisfb_max = -1;
} else if(!strnicmp(this_opt, "userom:", 7)) {
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "useoem:", 7)) {
sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
sisfb_nocrt2rate = 1;
- } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
- unsigned long temp = 2;
- temp = simple_strtoul(this_opt + 9, NULL, 0);
- if((temp == 0) || (temp == 1)) {
+ } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+ unsigned long temp = 2;
+ temp = simple_strtoul(this_opt + 9, NULL, 0);
+ if((temp == 0) || (temp == 1)) {
sisfb_scalelcd = temp ^ 1;
- }
+ }
} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
+ int temp = 0;
+ temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+ if((temp >= -32) && (temp <= 32)) {
sisfb_tvxposoffset = temp;
- }
+ }
} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
+ int temp = 0;
+ temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+ if((temp >= -32) && (temp <= 32)) {
sisfb_tvyposoffset = temp;
- }
+ }
} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
sisfb_search_specialtiming(this_opt + 14);
} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
- int temp = 4;
- temp = simple_strtoul(this_opt + 7, NULL, 0);
- if((temp >= 0) && (temp <= 3)) {
+ int temp = 4;
+ temp = simple_strtoul(this_opt + 7, NULL, 0);
+ if((temp >= 0) && (temp <= 3)) {
sisfb_lvdshl = temp;
- }
+ }
} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
sisfb_search_mode(this_opt, TRUE);
#if !defined(__i386__) && !defined(__x86_64__)
- } else if(!strnicmp(this_opt, "resetcard", 9)) {
- sisfb_resetcard = 1;
+ } else if(!strnicmp(this_opt, "resetcard", 9)) {
+ sisfb_resetcard = 1;
} else if(!strnicmp(this_opt, "videoram:", 9)) {
- sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+ sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
#endif
} else {
printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
@@ -3967,63 +4183,99 @@ SISINITSTATIC int __init sisfb_setup(char *options)
}
-
-
return 0;
}
#endif
-static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
+static int __devinit
+sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+{
+ SIS_IOTYPE1 *rom;
+ int romptr;
+
+ if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
+ return 0;
+
+ romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+ if(romptr > (0x10000 - 8))
+ return 0;
+
+ rom = rom_base + romptr;
+
+ if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
+ (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
+ return 0;
+
+ if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
+ return 0;
+
+ if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
+ return 0;
+
+ return 1;
+}
+
+static unsigned char * __devinit
+sisfb_find_rom(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- USHORT pciid;
- int romptr;
- UCHAR *myrombase;
- u32 temp;
- SIS_IOTYPE1 *rom_base, *rom;
+ SIS_IOTYPE1 *rom_base;
+ unsigned char *myrombase = NULL;
+ u32 temp;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+ size_t romsize;
+
+ /* First, try the official pci ROM functions (except
+ * on integrated chipsets which have no ROM).
+ */
- if(!(myrombase = vmalloc(65536))) return NULL;
+ if(!ivideo->nbridge) {
-#if defined(__i386__) || defined(__x86_64__)
+ if((rom_base = pci_map_rom(pdev, &romsize))) {
- for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+ if(sisfb_check_rom(rom_base, ivideo)) {
- rom_base = ioremap(temp, 0x10000);
- if(!rom_base) continue;
+ if((myrombase = vmalloc(65536))) {
- if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
- iounmap(rom_base);
- continue;
- }
+ /* Work around bug in pci/rom.c: Folks forgot to check
+ * whether the size retrieved from the BIOS image eventually
+ * is larger than the mapped size
+ */
+ if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
+ romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr > (0x10000 - 8)) {
- iounmap(rom_base);
- continue;
- }
+ memcpy_fromio(myrombase, rom_base,
+ (romsize > 65536) ? 65536 : romsize);
+ }
+ }
+ pci_unmap_rom(pdev, rom_base);
+ }
+ }
- rom = rom_base + romptr;
+ if(myrombase) return myrombase;
+#endif
- if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
- (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
- iounmap(rom_base);
- continue;
- }
+ /* Otherwise do it the conventional way. */
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid != 0x1039) {
- iounmap(rom_base);
- continue;
- }
+#if defined(__i386__) || defined(__x86_64__)
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- return myrombase;
- }
+ for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+
+ rom_base = ioremap(temp, 65536);
+ if(!rom_base)
+ continue;
+
+ if(!sisfb_check_rom(rom_base, ivideo)) {
+ iounmap(rom_base);
+ continue;
+ }
+
+ if((myrombase = vmalloc(65536)))
+ memcpy_fromio(myrombase, rom_base, 65536);
+
+ iounmap(rom_base);
+ break;
- iounmap(rom_base);
}
#else
@@ -4034,752 +4286,1603 @@ static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
rom_base = ioremap(ivideo->video_base, 65536);
if(rom_base) {
- if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
- romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr <= (0x10000 - 8)) {
- rom = rom_base + romptr;
- if((readb(rom) == 'P') && (readb(rom + 1) == 'C') &&
- (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid == 0x1039) {
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
- return myrombase;
- }
- }
- }
- }
- }
- iounmap(rom_base);
+ if(sisfb_check_rom(rom_base, ivideo)) {
+ if((myrombase = vmalloc(65536)))
+ memcpy_fromio(myrombase, rom_base, 65536);
+ }
+ iounmap(rom_base);
}
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
+
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
#endif
- vfree(myrombase);
- return NULL;
+ return myrombase;
+}
+
+static void __devinit
+sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
+ unsigned int min)
+{
+ ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
+
+ if(!ivideo->video_vbase) {
+ printk(KERN_ERR
+ "sisfb: Unable to map maximum video RAM for size detection\n");
+ (*mapsize) >>= 1;
+ while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
+ (*mapsize) >>= 1;
+ if((*mapsize) < (min << 20))
+ break;
+ }
+ if(ivideo->video_vbase) {
+ printk(KERN_ERR
+ "sisfb: Video RAM size detection limited to %dMB\n",
+ (int)((*mapsize) >> 20));
+ }
+ }
}
#ifdef CONFIG_FB_SIS_300
static int __devinit
-sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress)
+sisfb_post_300_buswidth(struct sis_video_info *ivideo)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+ unsigned short temp;
+ unsigned char reg;
int i, j;
- USHORT temp;
- UCHAR reg;
-
- andSISIDXREG(SISSR,0x15,0xFB);
- orSISIDXREG(SISSR,0x15,0x04);
- outSISIDXREG(SISSR,0x13,0x00);
- outSISIDXREG(SISSR,0x14,0xBF);
-
- for(i=0; i<2; i++) {
- temp = 0x1234;
- for(j=0; j<4; j++) {
- writew(temp, FBAddress);
- if(readw(FBAddress) == temp) break;
- orSISIDXREG(SISSR,0x3c,0x01);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- andSISIDXREG(SISSR,0x3c,0xfe);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- temp++;
- }
+
+ andSISIDXREG(SISSR, 0x15, 0xFB);
+ orSISIDXREG(SISSR, 0x15, 0x04);
+ outSISIDXREG(SISSR, 0x13, 0x00);
+ outSISIDXREG(SISSR, 0x14, 0xBF);
+
+ for(i = 0; i < 2; i++) {
+ temp = 0x1234;
+ for(j = 0; j < 4; j++) {
+ writew(temp, FBAddress);
+ if(readw(FBAddress) == temp)
+ break;
+ orSISIDXREG(SISSR, 0x3c, 0x01);
+ inSISIDXREG(SISSR, 0x05, reg);
+ inSISIDXREG(SISSR, 0x05, reg);
+ andSISIDXREG(SISSR, 0x3c, 0xfe);
+ inSISIDXREG(SISSR, 0x05, reg);
+ inSISIDXREG(SISSR, 0x05, reg);
+ temp++;
+ }
}
writel(0x01234567L, FBAddress);
- writel(0x456789ABL, (FBAddress+4));
- writel(0x89ABCDEFL, (FBAddress+8));
- writel(0xCDEF0123L, (FBAddress+12));
- inSISIDXREG(SISSR,0x3b,reg);
+ writel(0x456789ABL, (FBAddress + 4));
+ writel(0x89ABCDEFL, (FBAddress + 8));
+ writel(0xCDEF0123L, (FBAddress + 12));
+
+ inSISIDXREG(SISSR, 0x3b, reg);
if(reg & 0x01) {
- if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */
+ if(readl((FBAddress + 12)) == 0xCDEF0123L)
+ return 4; /* Channel A 128bit */
}
- if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */
- return(1); /* 32bit */
+
+ if(readl((FBAddress + 4)) == 0x456789ABL)
+ return 2; /* Channel B 64bit */
+
+ return 1; /* 32bit */
+}
+
+static int __devinit
+sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
+ int PseudoRankCapacity, int PseudoAdrPinCount,
+ unsigned int mapsize)
+{
+ SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+ unsigned short sr14;
+ unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
+ unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
+ static const unsigned short SiS_DRAMType[17][5] = {
+ {0x0C,0x0A,0x02,0x40,0x39},
+ {0x0D,0x0A,0x01,0x40,0x48},
+ {0x0C,0x09,0x02,0x20,0x35},
+ {0x0D,0x09,0x01,0x20,0x44},
+ {0x0C,0x08,0x02,0x10,0x31},
+ {0x0D,0x08,0x01,0x10,0x40},
+ {0x0C,0x0A,0x01,0x20,0x34},
+ {0x0C,0x09,0x01,0x08,0x32},
+ {0x0B,0x08,0x02,0x08,0x21},
+ {0x0C,0x08,0x01,0x08,0x30},
+ {0x0A,0x08,0x02,0x04,0x11},
+ {0x0B,0x0A,0x01,0x10,0x28},
+ {0x09,0x08,0x02,0x02,0x01},
+ {0x0B,0x09,0x01,0x08,0x24},
+ {0x0B,0x08,0x01,0x04,0x20},
+ {0x0A,0x08,0x01,0x02,0x10},
+ {0x09,0x08,0x01,0x01,0x00}
+ };
+
+ for(k = 0; k <= 16; k++) {
+
+ RankCapacity = buswidth * SiS_DRAMType[k][3];
+
+ if(RankCapacity != PseudoRankCapacity)
+ continue;
+
+ if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+ continue;
+
+ BankNumHigh = RankCapacity * 16 * iteration - 1;
+ if(iteration == 3) { /* Rank No */
+ BankNumMid = RankCapacity * 16 - 1;
+ } else {
+ BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
+ }
+
+ PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+ PhysicalAdrHigh = BankNumHigh;
+ PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+ PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+
+ andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
+ orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
+ sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
+ if(buswidth == 4) sr14 |= 0x80;
+ else if(buswidth == 2) sr14 |= 0x40;
+ outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
+ outSISIDXREG(SISSR, 0x14, sr14);
+
+ BankNumHigh <<= 16;
+ BankNumMid <<= 16;
+
+ if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
+ (BankNumMid + PhysicalAdrHigh >= mapsize) ||
+ (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
+ (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+ continue;
+
+ /* Write data */
+ writew(((unsigned short)PhysicalAdrHigh),
+ (FBAddr + BankNumHigh + PhysicalAdrHigh));
+ writew(((unsigned short)BankNumMid),
+ (FBAddr + BankNumMid + PhysicalAdrHigh));
+ writew(((unsigned short)PhysicalAdrHalfPage),
+ (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
+ writew(((unsigned short)PhysicalAdrOtherPage),
+ (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
+
+ /* Read data */
+ if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+ return 1;
+ }
+
+ return 0;
}
static void __devinit
-sisfb_setramsize300(struct pci_dev *pdev)
+sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
- SIS_IOTYPE1 *Addr;
- USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
- int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
- int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
- int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
- const USHORT SiS_DRAMType[17][5] = {
- {0x0C,0x0A,0x02,0x40,0x39},
- {0x0D,0x0A,0x01,0x40,0x48},
- {0x0C,0x09,0x02,0x20,0x35},
- {0x0D,0x09,0x01,0x20,0x44},
- {0x0C,0x08,0x02,0x10,0x31},
- {0x0D,0x08,0x01,0x10,0x40},
- {0x0C,0x0A,0x01,0x20,0x34},
- {0x0C,0x09,0x01,0x08,0x32},
- {0x0B,0x08,0x02,0x08,0x21},
- {0x0C,0x08,0x01,0x08,0x30},
- {0x0A,0x08,0x02,0x04,0x11},
- {0x0B,0x0A,0x01,0x10,0x28},
- {0x09,0x08,0x02,0x02,0x01},
- {0x0B,0x09,0x01,0x08,0x24},
- {0x0B,0x08,0x01,0x04,0x20},
- {0x0A,0x08,0x01,0x02,0x10},
- {0x09,0x08,0x01,0x01,0x00}
- };
-
- buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
-
- MB2Bank = 16;
- Done = 0;
- for(i = 6; i >= 0; i--) {
- if(Done) break;
- PseudoRankCapacity = 1 << i;
- for(j = 4; j >= 1; j--) {
- if(Done) break;
- PseudoTotalCapacity = PseudoRankCapacity * j;
- PseudoAdrPinCount = 15 - j;
- if(PseudoTotalCapacity <= 64) {
- for(k = 0; k <= 16; k++) {
- if(Done) break;
- RankCapacity = buswidth * SiS_DRAMType[k][3];
- AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
- if(RankCapacity == PseudoRankCapacity)
- if(AdrPinCount <= PseudoAdrPinCount) {
- if(j == 3) { /* Rank No */
- BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
- BankNumMid = RankCapacity * MB2Bank * 1 - 1;
- } else {
- BankNumHigh = RankCapacity * MB2Bank * j - 1;
- BankNumMid = RankCapacity * MB2Bank * j / 2 - 1;
- }
- PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
- PhysicalAdrHigh = BankNumHigh;
- PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
- PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
- /* Write data */
- andSISIDXREG(SISSR,0x15,0xFB); /* Test */
- orSISIDXREG(SISSR,0x15,0x04); /* Test */
- TotalCapacity = SiS_DRAMType[k][3] * buswidth;
- sr13 = SiS_DRAMType[k][4];
- if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80;
- if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40;
- if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00;
- outSISIDXREG(SISSR,0x13,sr13);
- outSISIDXREG(SISSR,0x14,sr14);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
- writew(((USHORT)PhysicalAdrHigh), Addr);
- Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
- writew(((USHORT)BankNumMid), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
- writew(((USHORT)PhysicalAdrHalfPage), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
- /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
- writew(((USHORT)PhysicalAdrOtherPage), Addr);
- /* Read data */
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- data = readw(Addr); /* *((USHORT *)(Addr)); */
- if(data == PhysicalAdrHigh) Done = 1;
- } /* if */
- } /* for k */
- } /* if */
- } /* for j */
- } /* for i */
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ int i, j, buswidth;
+ int PseudoRankCapacity, PseudoAdrPinCount;
+
+ buswidth = sisfb_post_300_buswidth(ivideo);
+
+ for(i = 6; i >= 0; i--) {
+ PseudoRankCapacity = 1 << i;
+ for(j = 4; j >= 1; j--) {
+ PseudoAdrPinCount = 15 - j;
+ if((PseudoRankCapacity * j) <= 64) {
+ if(sisfb_post_300_rwtest(ivideo,
+ j,
+ buswidth,
+ PseudoRankCapacity,
+ PseudoAdrPinCount,
+ mapsize))
+ return;
+ }
+ }
+ }
}
-static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
+static void __devinit
+sisfb_post_sis300(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
u16 index, rindex, memtype = 0;
+ unsigned int mapsize;
- outSISIDXREG(SISSR,0x05,0x86);
+ if(!ivideo->SiS_Pr.UseROM)
+ bios = NULL;
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x07;
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ if(bios) {
+ if(bios[0x52] & 0x80) {
+ memtype = bios[0x52];
+ } else {
+ inSISIDXREG(SISSR, 0x3a, memtype);
+ }
+ memtype &= 0x07;
}
+ v3 = 0x80; v6 = 0x80;
if(ivideo->revision_id <= 0x13) {
- v1 = 0x44; v2 = 0x42; v3 = 0x80;
- v4 = 0x44; v5 = 0x42; v6 = 0x80;
+ v1 = 0x44; v2 = 0x42;
+ v4 = 0x44; v5 = 0x42;
} else {
- v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */
- v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x7c;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
+ v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
+ v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
+ if(bios) {
+ index = memtype * 5;
+ rindex = index + 0x54;
+ v1 = bios[rindex++];
+ v2 = bios[rindex++];
+ v3 = bios[rindex++];
+ rindex = index + 0x7c;
+ v4 = bios[rindex++];
+ v5 = bios[rindex++];
+ v6 = bios[rindex++];
+ }
}
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
+ outSISIDXREG(SISSR, 0x28, v1);
+ outSISIDXREG(SISSR, 0x29, v2);
+ outSISIDXREG(SISSR, 0x2a, v3);
+ outSISIDXREG(SISSR, 0x2e, v4);
+ outSISIDXREG(SISSR, 0x2f, v5);
+ outSISIDXREG(SISSR, 0x30, v6);
+
v1 = 0x10;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
- outSISIDXREG(SISSR,0x07,v1); /* DAC speed */
- outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */
+ if(bios)
+ v1 = bios[0xa4];
+ outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
+
+ outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
+
v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- memtype += 0xa5;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
- }
- if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
- andSISIDXREG(SISSR,0x15,0xfb);
- orSISIDXREG(SISSR,0x15,0x04);
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
- orSISIDXREG(SISSR,0x19,0x20);
- }
+ if(bios) {
+ memtype += 0xa5;
+ v1 = bios[memtype];
+ v2 = bios[memtype + 8];
+ v3 = bios[memtype + 16];
+ v4 = bios[memtype + 24];
+ v5 = bios[memtype + 32];
+ v6 = bios[memtype + 40];
+ v7 = bios[memtype + 48];
+ v8 = bios[memtype + 56];
+ }
+ if(ivideo->revision_id >= 0x80)
+ v3 &= 0xfd;
+ outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+ outSISIDXREG(SISSR, 0x16, v2);
+ outSISIDXREG(SISSR, 0x17, v3);
+ outSISIDXREG(SISSR, 0x18, v4);
+ outSISIDXREG(SISSR, 0x19, v5);
+ outSISIDXREG(SISSR, 0x1a, v6);
+ outSISIDXREG(SISSR, 0x1b, v7);
+ outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
+ andSISIDXREG(SISSR, 0x15 ,0xfb);
+ orSISIDXREG(SISSR, 0x15, 0x04);
+ if(bios) {
+ if(bios[0x53] & 0x02) {
+ orSISIDXREG(SISSR, 0x19, 0x20);
+ }
}
v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
- if(ivideo->revision_id >= 0x80) v1 |= 0x01;
- outSISIDXREG(SISSR,0x1f,v1);
- outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */
+ if(ivideo->revision_id >= 0x80)
+ v1 |= 0x01;
+ outSISIDXREG(SISSR, 0x1f, v1);
+ outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
- }
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISCR,0x37,0x00);
- orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */
- outSISIDXREG(SISPART1,0x00,0x00);
+ if(bios) {
+ v1 = bios[0xe8];
+ v2 = bios[0xe9];
+ v3 = bios[0xea];
+ }
+ outSISIDXREG(SISSR, 0x23, v1);
+ outSISIDXREG(SISSR, 0x24, v2);
+ outSISIDXREG(SISSR, 0x25, v3);
+ outSISIDXREG(SISSR, 0x21, 0x84);
+ outSISIDXREG(SISSR, 0x22, 0x00);
+ outSISIDXREG(SISCR, 0x37, 0x00);
+ orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
+ outSISIDXREG(SISPART1, 0x00, 0x00);
v1 = 0x40; v2 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
+ if(bios) {
+ v1 = bios[0xec];
+ v2 = bios[0xeb];
}
- outSISIDXREG(SISPART1,0x02,v1);
- if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
- inSISIDXREG(SISPART4,0x00,reg);
+ outSISIDXREG(SISPART1, 0x02, v1);
+
+ if(ivideo->revision_id >= 0x80)
+ v2 &= ~0x01;
+
+ inSISIDXREG(SISPART4, 0x00, reg);
if((reg == 1) || (reg == 2)) {
- outSISIDXREG(SISCR,0x37,0x02);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v4 = 0x00; v5 = 0x00; v6 = 0x10;
- if(ivideo->sishw_ext.UseROM) {
- v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
- }
- outSISIDXREG(SISPART4,0x0d,v4);
- outSISIDXREG(SISPART4,0x0e,v5);
- outSISIDXREG(SISPART4,0x10,v6);
- outSISIDXREG(SISPART4,0x0f,0x3f);
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
+ outSISIDXREG(SISCR, 0x37, 0x02);
+ outSISIDXREG(SISPART2, 0x00, 0x1c);
+ v4 = 0x00; v5 = 0x00; v6 = 0x10;
+ if(ivideo->SiS_Pr.UseROM) {
+ v4 = bios[0xf5];
+ v5 = bios[0xf6];
+ v6 = bios[0xf7];
+ }
+ outSISIDXREG(SISPART4, 0x0d, v4);
+ outSISIDXREG(SISPART4, 0x0e, v5);
+ outSISIDXREG(SISPART4, 0x10, v6);
+ outSISIDXREG(SISPART4, 0x0f, 0x3f);
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if(reg >= 0xb0) {
+ inSISIDXREG(SISPART4, 0x23, reg);
+ reg &= 0x20;
+ reg <<= 1;
+ outSISIDXREG(SISPART4, 0x23, reg);
+ }
} else {
- v2 &= ~0x10;
+ v2 &= ~0x10;
}
- outSISIDXREG(SISSR,0x32,v2);
- andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */
- inSISIDXREG(SISSR,0x16,reg);
+ outSISIDXREG(SISSR, 0x32, v2);
+
+ andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
+
+ inSISIDXREG(SISSR, 0x16, reg);
reg &= 0xc3;
- outSISIDXREG(SISCR,0x35,reg);
- outSISIDXREG(SISCR,0x83,0x00);
+ outSISIDXREG(SISCR, 0x35, reg);
+ outSISIDXREG(SISCR, 0x83, 0x00);
#if !defined(__i386__) && !defined(__x86_64__)
if(sisfb_videoram) {
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- reg = ((sisfb_videoram >> 10) - 1) | 0x40;
- outSISIDXREG(SISSR,0x14,reg);
+ outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
+ reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+ outSISIDXREG(SISSR, 0x14, reg);
} else {
#endif
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- sisfb_setramsize300(pdev);
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */
- }
+ /* Need to map max FB size for finding out about RAM size */
+ mapsize = 64 << 20;
+ sisfb_post_map_vram(ivideo, &mapsize, 4);
+
+ if(ivideo->video_vbase) {
+ sisfb_post_300_ramsize(pdev, mapsize);
+ iounmap(ivideo->video_vbase);
+ } else {
+ printk(KERN_DEBUG
+ "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+ outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
+ outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
+ }
#if !defined(__i386__) && !defined(__x86_64__)
}
#endif
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
+ if(bios) {
+ v1 = bios[0xe6];
+ v2 = bios[0xe7];
} else {
- inSISIDXREG(SISSR,0x3a,reg);
- if((reg & 0x30) == 0x30) {
- v1 = 0x04; /* PCI */
- v2 = 0x92;
- } else {
- v1 = 0x14; /* AGP */
- v2 = 0xb2;
- }
+ inSISIDXREG(SISSR, 0x3a, reg);
+ if((reg & 0x30) == 0x30) {
+ v1 = 0x04; /* PCI */
+ v2 = 0x92;
+ } else {
+ v1 = 0x14; /* AGP */
+ v2 = 0xb2;
+ }
}
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
+ outSISIDXREG(SISSR, 0x21, v1);
+ outSISIDXREG(SISSR, 0x22, v2);
+
+ /* Sense CRT1 */
+ sisfb_sense_crt1(ivideo);
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Display off */
+ orSISIDXREG(SISSR, 0x01, 0x20);
+
+ /* Save mode number in CR34 */
+ outSISIDXREG(SISCR, 0x34, 0x2e);
+
+ /* Let everyone know what the current mode is */
+ ivideo->modeprechange = 0x2e;
}
#endif
#ifdef CONFIG_FB_SIS_315
-static void __devinit sisfb_post_sis315330(struct pci_dev *pdev)
+#if 0
+static void __devinit
+sisfb_post_sis315330(struct pci_dev *pdev)
{
-#ifdef YET_TO_BE_DONE
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
- u16 index, rindex, memtype = 0;
- u32 reg1_32, reg2_32, reg3_32;
+ /* TODO */
+}
+#endif
+
+static void __devinit
+sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
+{
+ unsigned int i;
+ u8 reg;
+
+ for(i = 0; i <= (delay * 10 * 36); i++) {
+ inSISIDXREG(SISSR, 0x05, reg);
+ reg++;
+ }
+}
+
+static int __devinit
+sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
+ unsigned short pcivendor)
+{
+ struct pci_dev *pdev = NULL;
+ unsigned short temp;
+ int ret = 0;
+
+ while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
+ temp = pdev->vendor;
+ SIS_PCI_PUT_DEVICE(pdev);
+ if(temp == pcivendor) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int __devinit
+sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
+ unsigned int enda, unsigned int mapsize)
+{
+ unsigned int pos;
int i;
- /* Unlock */
- /* outSISIDXREG(0x3c4,0x05,0x86); */
- outSISIDXREG(SISSR,0x05,0x86);
+ writel(0, ivideo->video_vbase);
- /* Enable relocated i/o ports */
- /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */
- setSISIDXREG(SISSR,0x20,~0x10,0x20);
+ for(i = starta; i <= enda; i++) {
+ pos = 1 << i;
+ if(pos < mapsize)
+ writel(pos, ivideo->video_vbase + pos);
+ }
+
+ sisfb_post_xgi_delay(ivideo, 150);
+
+ if(readl(ivideo->video_vbase) != 0)
+ return 0;
- /* Clear regs */
+ for(i = starta; i <= enda; i++) {
+ pos = 1 << i;
+ if(pos < mapsize) {
+ if(readl(ivideo->video_vbase + pos) != pos)
+ return 0;
+ } else
+ return 0;
+ }
+
+ return 1;
+}
+
+static void __devinit
+sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
+{
+ unsigned int buswidth, ranksize, channelab, mapsize;
+ int i, j, k, l;
+ u8 reg, sr14;
+ static const u8 dramsr13[12 * 5] = {
+ 0x02, 0x0e, 0x0b, 0x80, 0x5d,
+ 0x02, 0x0e, 0x0a, 0x40, 0x59,
+ 0x02, 0x0d, 0x0b, 0x40, 0x4d,
+ 0x02, 0x0e, 0x09, 0x20, 0x55,
+ 0x02, 0x0d, 0x0a, 0x20, 0x49,
+ 0x02, 0x0c, 0x0b, 0x20, 0x3d,
+ 0x02, 0x0e, 0x08, 0x10, 0x51,
+ 0x02, 0x0d, 0x09, 0x10, 0x45,
+ 0x02, 0x0c, 0x0a, 0x10, 0x39,
+ 0x02, 0x0d, 0x08, 0x08, 0x41,
+ 0x02, 0x0c, 0x09, 0x08, 0x35,
+ 0x02, 0x0c, 0x08, 0x04, 0x31
+ };
+ static const u8 dramsr13_4[4 * 5] = {
+ 0x02, 0x0d, 0x09, 0x40, 0x45,
+ 0x02, 0x0c, 0x09, 0x20, 0x35,
+ 0x02, 0x0c, 0x08, 0x10, 0x31,
+ 0x02, 0x0b, 0x08, 0x08, 0x21
+ };
+
+ /* Enable linear mode, disable 0xa0000 address decoding */
+ /* We disable a0000 address decoding, because
+ * - if running on x86, if the card is disabled, it means
+ * that another card is in the system. We don't want
+ * to interphere with that primary card's textmode.
+ * - if running on non-x86, there usually is no VGA window
+ * at a0000.
+ */
+ orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
+
+ /* Need to map max FB size for finding out about RAM size */
+ mapsize = 256 << 20;
+ sisfb_post_map_vram(ivideo, &mapsize, 32);
+
+ if(!ivideo->video_vbase) {
+ printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
+ outSISIDXREG(SISSR, 0x13, 0x35);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ /* TODO */
+ return;
+ }
+
+ /* Non-interleaving */
+ outSISIDXREG(SISSR, 0x15, 0x00);
+ /* No tiling */
+ outSISIDXREG(SISSR, 0x1c, 0x00);
+
+ if(ivideo->chip == XGI_20) {
+
+ channelab = 1;
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(!(reg & 0x01)) { /* Single 32/16 */
+ buswidth = 32;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x52);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x02;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ outSISIDXREG(SISSR, 0x14, 0x42);
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
+ goto bail_out;
+
+ buswidth = 16;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x01;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+ else
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ } else { /* Dual 16/8 */
+ buswidth = 16;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x01;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ outSISIDXREG(SISSR, 0x14, 0x31);
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
+ goto bail_out;
+
+ buswidth = 8;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x30);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x00;
+ if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
+ goto bail_out;
+ else
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ }
+
+ } else { /* XGI_40 */
+
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(!(reg & 0x10)) {
+ inSISIDXREG(SISSR, 0x39, reg);
+ reg >>= 1;
+ }
+
+ if(reg & 0x01) { /* DDRII */
+ buswidth = 32;
+ if(ivideo->revision_id == 2) {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x44);
+ sr14 = 0x04;
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x34);
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ channelab = 1;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x40);
+ sr14 = 0x00;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x30);
+ } else {
+ channelab = 3;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x4c);
+ sr14 = 0x0c;
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
+ goto bail_out;
+
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x14, 0x48);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x08;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x3c);
+ sr14 = 0x0c;
+
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
+ channelab = 3;
+ } else {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x14, 0x38);
+ sr14 = 0x08;
+ }
+ }
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ } else { /* DDR */
+
+ buswidth = 64;
+ if(ivideo->revision_id == 2) {
+ channelab = 1;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x52);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x02;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x42);
+ } else {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x5a);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x0a;
+ if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x4a);
+ }
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ }
+ }
+
+bail_out:
+ setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ j = (ivideo->chip == XGI_20) ? 5 : 9;
+ k = (ivideo->chip == XGI_20) ? 12 : 4;
+
+ for(i = 0; i < k; i++) {
+
+ reg = (ivideo->chip == XGI_20) ?
+ dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
+ setSISIDXREG(SISSR, 0x13, 0x80, reg);
+ sisfb_post_xgi_delay(ivideo, 50);
+
+ ranksize = (ivideo->chip == XGI_20) ?
+ dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
+
+ inSISIDXREG(SISSR, 0x13, reg);
+ if(reg & 0x80) ranksize <<= 1;
+
+ if(ivideo->chip == XGI_20) {
+ if(buswidth == 16) ranksize <<= 1;
+ else if(buswidth == 32) ranksize <<= 2;
+ } else {
+ if(buswidth == 64) ranksize <<= 1;
+ }
+
+ reg = 0;
+ l = channelab;
+ if(l == 3) l = 4;
+ if((ranksize * l) <= 256) {
+ while((ranksize >>= 1)) reg += 0x10;
+ }
+
+ if(!reg) continue;
+
+ setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
+ break;
+ }
+
+ iounmap(ivideo->video_vbase);
+}
+
+static void __devinit
+sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
+{
+ u8 v1, v2, v3;
+ int index;
+ static const u8 cs90[8 * 3] = {
+ 0x16, 0x01, 0x01,
+ 0x3e, 0x03, 0x01,
+ 0x7c, 0x08, 0x01,
+ 0x79, 0x06, 0x01,
+ 0x29, 0x01, 0x81,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01
+ };
+ static const u8 csb8[8 * 3] = {
+ 0x5c, 0x23, 0x01,
+ 0x29, 0x01, 0x01,
+ 0x7c, 0x08, 0x01,
+ 0x79, 0x06, 0x01,
+ 0x29, 0x01, 0x81,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01
+ };
+
+ regb = 0; /* ! */
+
+ index = regb * 3;
+ v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
+ if(ivideo->haveXGIROM) {
+ v1 = ivideo->bios_abase[0x90 + index];
+ v2 = ivideo->bios_abase[0x90 + index + 1];
+ v3 = ivideo->bios_abase[0x90 + index + 2];
+ }
+ outSISIDXREG(SISSR, 0x28, v1);
+ outSISIDXREG(SISSR, 0x29, v2);
+ outSISIDXREG(SISSR, 0x2a, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ index = regb * 3;
+ v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
+ if(ivideo->haveXGIROM) {
+ v1 = ivideo->bios_abase[0xb8 + index];
+ v2 = ivideo->bios_abase[0xb8 + index + 1];
+ v3 = ivideo->bios_abase[0xb8 + index + 2];
+ }
+ outSISIDXREG(SISSR, 0x2e, v1);
+ outSISIDXREG(SISSR, 0x2f, v2);
+ outSISIDXREG(SISSR, 0x30, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+}
+
+static int __devinit
+sisfb_post_xgi(struct pci_dev *pdev)
+{
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ unsigned char *bios = ivideo->bios_abase;
+ struct pci_dev *mypdev = NULL;
+ const u8 *ptr, *ptr2;
+ u8 v1, v2, v3, v4, v5, reg, ramtype;
+ u32 rega, regb, regd;
+ int i, j, k, index;
+ static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
+ static const u8 cs76[2] = { 0xa3, 0xfb };
+ static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
+ static const u8 cs158[8] = {
+ 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs160[8] = {
+ 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs168[8] = {
+ 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs128[3 * 8] = {
+ 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs148[2 * 8] = {
+ 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs31a[8 * 4] = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs33a[8 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs45a[8 * 2] = {
+ 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs170[7 * 8] = {
+ 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs1a8[3 * 8] = {
+ 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs100[2 * 8] = {
+ 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ /* VGA enable */
+ reg = inSISREG(SISVGAENABLE) | 0x01;
+ outSISREG(SISVGAENABLE, reg);
+
+ /* Misc */
+ reg = inSISREG(SISMISCR) | 0x01;
+ outSISREG(SISMISCW, reg);
+
+ /* Unlock SR */
+ outSISIDXREG(SISSR, 0x05, 0x86);
+ inSISIDXREG(SISSR, 0x05, reg);
+ if(reg != 0xa1)
+ return 0;
+
+ /* Clear some regs */
for(i = 0; i < 0x22; i++) {
- outSISIDXREG(SISSR,(0x06 + i),0x00);
+ if(0x06 + i == 0x20) continue;
+ outSISIDXREG(SISSR, 0x06 + i, 0x00);
}
- v1 = 0x0d;
- if( is 330) v1 = 0x0b;
- for(i = 0; i < v1; i++) {
- outSISIDXREG(SISSR,(0x31 + i),0x00);
+ for(i = 0; i < 0x0b; i++) {
+ outSISIDXREG(SISSR, 0x31 + i, 0x00);
}
for(i = 0; i < 0x10; i++) {
- outSISIDXREG(SISCR,(0x30 + i),0x00);
- }
-
- /* Reset clocks */
- reg = inSISREG(SISMISCR);
- outSISIDXREG(SISSR,0x28,0x81);
- outSISIDXREG(SISSR,0x2A,0x00);
- outSISIDXREG(SISSR,0x29,0xE1);
- outSISREG(SISMISCW,(reg | 0x0c));
- outSISIDXREG(SISSR,0x2B,0x81);
- outSISIDXREG(SISSR,0x2D,0x00);
- outSISIDXREG(SISSR,0x2C,0xE1);
- outSISIDXREG(SISSR,0x2E,0x81);
- outSISIDXREG(SISSR,0x30,0x00);
- outSISIDXREG(SISSR,0x2F,0xE1);
- SiS_DDC2Delay(....);
- outSISREG(SISMISCW,reg);
-
- /* Get memory type */
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x03;
- if( is 330 ) {
- if(memtype <= 1) memtype = 0;
- else {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- switch(reg) {
- case 0x00: memtype = 1; break;
- case 0x10: memtype = 3; break;
- case 0x20: memtype = 3; break;
- default: memtype = 2;
- }
- }
- }
+ outSISIDXREG(SISCR, 0x30 + i, 0x00);
}
- /* Set clocks */
- v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */
- v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x68;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- if( is 330 ) {
- inSISIDXREG(SISSR,0x3a,reg);
- reg &= 0x03;
- if(reg >= 2) {
- ...
- }
+ ptr = cs78;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x78];
+ }
+ for(i = 0; i < 3; i++) {
+ outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
+ }
+
+ ptr = cs76;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x76];
+ }
+ for(i = 0; i < 2; i++) {
+ outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
+ }
+
+ v1 = 0x18; v2 = 0x00;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x74];
+ v2 = bios[0x75];
+ }
+ outSISIDXREG(SISSR, 0x07, v1);
+ outSISIDXREG(SISSR, 0x11, 0x0f);
+ outSISIDXREG(SISSR, 0x1f, v2);
+ /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
+ outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+ outSISIDXREG(SISSR, 0x27, 0x74);
+
+ ptr = cs7b;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x7b];
+ }
+ for(i = 0; i < 3; i++) {
+ outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
}
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
-
- /* End of comp with 330 */
-
- v1 = 0x18;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
- outSISIDXREG(SISSR,0x07,v1);
- outSISIDXREG(SISSR,0x11,0x0f);
-
- v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
- v5 = 0xa0; v6 = 0x00; v7 = 0x30;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0x7d;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- }
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
-
- v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xa2;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- }
- outSISIDXREG(SISCR,0x40,v1);
- outSISIDXREG(SISCR,0x41,v2);
- outSISIDXREG(SISCR,0x42,v3);
- outSISIDXREG(SISCR,0x43,v4);
- outSISIDXREG(SISCR,0x44,v5);
-
- if( is 330 ) {
-
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
-
- v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
- v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xbe;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
- }
- outSISIDXREG(SISCR,0x68,v1);
- outSISIDXREG(SISCR,0x69,v2);
- outSISIDXREG(SISCR,0x6a,v3);
- outSISIDXREG(SISCR,0x6b,v4);
- outSISIDXREG(SISCR,0x6c,v5);
- outSISIDXREG(SISCR,0x6d,v6);
- outSISIDXREG(SISCR,0x6e,v7);
- outSISIDXREG(SISCR,0x6f,v8);
-
- v1 = 0x20;
- inSISIDXREG(SISSR,0x3b,reg);
-
- if(!(reg & 0x04)) {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- if(reg) v1 = 0x23;
- }
- outSISIDXREG(SISCR,0x48,v1);
- outSISIDXREG(SISCR,0x4c,0x20);
-
- xx= xxx();
- if(xx >= 1) {
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
- }
+ if(ivideo->chip == XGI_40) {
+ if(ivideo->revision_id == 2) {
+ setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
+ }
+ outSISIDXREG(SISCR, 0x7d, 0xfe);
+ outSISIDXREG(SISCR, 0x7e, 0x0f);
+ }
+ if(ivideo->revision_id == 0) { /* 40 *and* 20? */
+ andSISIDXREG(SISCR, 0x58, 0xd7);
+ inSISIDXREG(SISCR, 0xcb, reg);
+ if(reg & 0x20) {
+ setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+ }
+ }
+ reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
+ setSISIDXREG(SISCR, 0x38, 0x1f, reg);
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISSR, 0x36, 0x70);
} else {
+ outSISIDXREG(SISVID, 0x00, 0x86);
+ outSISIDXREG(SISVID, 0x32, 0x00);
+ outSISIDXREG(SISVID, 0x30, 0x00);
+ outSISIDXREG(SISVID, 0x32, 0x01);
+ outSISIDXREG(SISVID, 0x30, 0x00);
+ andSISIDXREG(SISVID, 0x2f, 0xdf);
+ andSISIDXREG(SISCAP, 0x00, 0x3f);
+
+ outSISIDXREG(SISPART1, 0x2f, 0x01);
+ outSISIDXREG(SISPART1, 0x00, 0x00);
+ outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
+ outSISIDXREG(SISPART1, 0x2e, 0x08);
+ andSISIDXREG(SISPART1, 0x35, 0x7f);
+ andSISIDXREG(SISPART1, 0x50, 0xfe);
+
+ inSISIDXREG(SISPART4, 0x00, reg);
+ if(reg == 1 || reg == 2) {
+ outSISIDXREG(SISPART2, 0x00, 0x1c);
+ outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
+ outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
+ outSISIDXREG(SISPART4, 0x10, bios[0x81]);
+ andSISIDXREG(SISPART4, 0x0f, 0x3f);
+
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if((reg & 0xf0) >= 0xb0) {
+ inSISIDXREG(SISPART4, 0x23, reg);
+ if(reg & 0x20) reg |= 0x40;
+ outSISIDXREG(SISPART4, 0x23, reg);
+ reg = (reg & 0x20) ? 0x02 : 0x00;
+ setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
+ }
+ }
- outSISIDXREG(SISCR,0x48,0x23);
+ v1 = bios[0x77];
+
+ inSISIDXREG(SISSR, 0x3b, reg);
+ if(reg & 0x02) {
+ inSISIDXREG(SISSR, 0x3a, reg);
+ v2 = (reg & 0x30) >> 3;
+ if(!(v2 & 0x04)) v2 ^= 0x02;
+ inSISIDXREG(SISSR, 0x39, reg);
+ if(reg & 0x80) v2 |= 0x80;
+ v2 |= 0x01;
+
+ if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
+ SIS_PCI_PUT_DEVICE(mypdev);
+ if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
+ v2 &= 0xf9;
+ v2 |= 0x08;
+ v1 &= 0xfe;
+ } else {
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
+ if(!mypdev)
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
+ if(!mypdev)
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
+ if(mypdev) {
+ pci_read_config_dword(mypdev, 0x94, &regd);
+ regd &= 0xfffffeff;
+ pci_write_config_dword(mypdev, 0x94, regd);
+ v1 &= 0xfe;
+ SIS_PCI_PUT_DEVICE(mypdev);
+ } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
+ v1 &= 0xfe;
+ } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
+ if((v2 & 0x06) == 4)
+ v2 ^= 0x06;
+ v2 |= 0x08;
+ }
+ }
+ setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
+ }
+ outSISIDXREG(SISSR, 0x22, v1);
+
+ if(ivideo->revision_id == 2) {
+ inSISIDXREG(SISSR, 0x3b, v1);
+ inSISIDXREG(SISSR, 0x3a, v2);
+ regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
+ if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
+ setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+
+ if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
+ /* TODO: set CR5f &0xf1 | 0x01 for version 6570
+ * of nforce 2 ROM
+ */
+ if(0)
+ setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+ SIS_PCI_PUT_DEVICE(mypdev);
+ }
+ }
- andSISIDXREG(SISSR,0x16,0x0f);
- if(memtype <= 1) {
- orSISIDXREG(SISSR,0x16,0x80);
- } else {
- v1 = 0x0f;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype];
- }
- if(!(v1 & 0x10)) v2 = 0xc0;
- else v2 = 0xd0;
- orSISIDXREG(SISSR,0x16,v2);
- andSISIDXREG(SISSR,0x16,0x0f);
- if(!(v1 & 0x10)) v2 = 0x80;
- else v2 = 0xA0;
- orSISIDXREG(SISSR,0x16,v2);
- }
-
- if(memtype >= 2) {
- const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
- const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg1_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg2_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- reg3_32 = reg2_32 << 1;
- reg2_32 >>= 1;
- reg3_32 += reg2_32;
- v1 = 0x40;
- if(reg3_32 > reg1_32) v1 = 0x10;
- outSISIDXREG(SISCR,0x59,v1);
- }
+ v1 = 0x30;
+ inSISIDXREG(SISSR, 0x3b, reg);
+ inSISIDXREG(SISCR, 0x5f, v2);
+ if((!(reg & 0x02)) && (v2 & 0x0e))
+ v1 |= 0x08;
+ outSISIDXREG(SISSR, 0x27, v1);
+
+ if(bios[0x64] & 0x01) {
+ setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
+ }
+ v1 = bios[0x4f7];
+ pci_read_config_dword(pdev, 0x50, &regd);
+ regd = (regd >> 20) & 0x0f;
+ if(regd == 1) {
+ v1 &= 0xfc;
+ orSISIDXREG(SISCR, 0x5f, 0x08);
+ }
+ outSISIDXREG(SISCR, 0x48, v1);
+
+ setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+ setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+ setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+ setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+ setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+ outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
+ setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+ outSISIDXREG(SISCR, 0x74, 0xd0);
+ setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+ setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+ setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+ v1 = bios[0x501];
+ if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
+ v1 = 0xf0;
+ SIS_PCI_PUT_DEVICE(mypdev);
+ }
+ outSISIDXREG(SISCR, 0x77, v1);
}
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99];
+ /* RAM type */
+
+ regb = 0; /* ! */
+
+ v1 = 0xff;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x140 + regb];
}
- outSISIDXREG(SISSR,0x1f,v1);
+ outSISIDXREG(SISCR, 0x6d, v1);
- outSISIDXREG(SISSR,0x20,0x20);
+ ptr = cs128;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x128];
+ }
+ for(i = 0, j = 0; i < 3; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
+ }
- v1 = 0xf6; v2 = 0x0d; v3 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e];
+ ptr = cs31a;
+ ptr2 = cs33a;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
+ ptr = (const u8 *)&bios[index];
+ ptr2 = (const u8 *)&bios[index + 0x20];
+ }
+ for(i = 0; i < 2; i++) {
+ if(i == 0) {
+ regd = le32_to_cpu(((u32 *)ptr)[regb]);
+ rega = 0x6b;
+ } else {
+ regd = le32_to_cpu(((u32 *)ptr2)[regb]);
+ rega = 0x6e;
+ }
+ reg = 0x00;
+ for(j = 0; j < 16; j++) {
+ reg &= 0xf3;
+ if(regd & 0x01) reg |= 0x04;
+ if(regd & 0x02) reg |= 0x08;
+ regd >>= 2;
+ outSISIDXREG(SISCR, rega, reg);
+ inSISIDXREG(SISCR, rega, reg);
+ inSISIDXREG(SISCR, rega, reg);
+ reg += 0x10;
+ }
}
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISSR,0x27,0x1f);
+ andSISIDXREG(SISCR, 0x6e, 0xfc);
- v1 = 0x00; v2 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1];
- }
- outSISIDXREG(SISSR,0x31,v1);
- outSISIDXREG(SISSR,0x33,v2);
-
- v1 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0];
- }
- v2 = inSISIDXREG(SISPART4,0x00);
- if((v2 != 1) && (v2 != 2)) v1 &= 0xef;
- outSISIDXREG(SISSR,0x32,v1);
-
- /* AGP */
- pci_read_config_long(pdev, 0x50, &reg1_32);
- reg1_32 >>= 20;
- reg1_32 &= 0x0f;
- if(reg1_32 == 1) {
- v1 = 0xAA; v2 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E];
- }
- } else {
- v1 = 0x88; v2 = 0x03;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
- }
+ ptr = NULL;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
+ ptr = (const u8 *)&bios[index];
+ }
+ for(i = 0; i < 4; i++) {
+ setSISIDXREG(SISCR, 0x6e, 0xfc, i);
+ reg = 0x00;
+ for(j = 0; j < 2; j++) {
+ regd = 0;
+ if(ptr) {
+ regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
+ ptr += 4;
+ }
+ /* reg = 0x00; */
+ for(k = 0; k < 16; k++) {
+ reg &= 0xfc;
+ if(regd & 0x01) reg |= 0x01;
+ if(regd & 0x02) reg |= 0x02;
+ regd >>= 2;
+ outSISIDXREG(SISCR, 0x6f, reg);
+ inSISIDXREG(SISCR, 0x6f, reg);
+ inSISIDXREG(SISCR, 0x6f, reg);
+ reg += 0x08;
+ }
+ }
}
- outSISIDXREG(SISCR,0x49,v1);
- outSISIDXREG(SISSR,0x25,v2);
- v1 = inSISIDXREG(SISPART4,0x00);
- if((v1 == 1) || (v1 == 2)) {
- orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */
- outSISIDXREG(SISPART1,0x00,0x00);
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
- }
- outSISIDXREG(SISPART1,0x02,v1);
- outSISIDXREG(SISPART1,0x2E,0x08);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v1 = 0x40; v2 = 0x00; v3 = 0x80;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
- }
- outSISIDXREG(SISPART4,0x0d,v1);
- outSISIDXREG(SISPART4,0x0e,v2);
- outSISIDXREG(SISPART4,0x10,v3);
- outSISIDXREG(SISPART4,0x0F,0x3F);
-
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
+ ptr = cs148;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x148];
+ }
+ for(i = 0, j = 0; i < 2; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
}
- outSISIDXREG(SISCR,0x37,0x02); /* Why? */
-
- outSISIDXREG(SISCR,0x83,0x00);
- outSISIDXREG(SISCR,0x90,0x00);
- andSISIDXREG(SISSR,0x5B,0xDF);
- outSISIDXREG(SISVID,0x00,0x86);
- outSISIDXREG(SISVID,0x32,0x00);
- outSISIDXREG(SISVID,0x30,0x00);
- outSISIDXREG(SISVID,0x32,0x01);
- outSISIDXREG(SISVID,0x30,0x00);
- orSISIDXREG(SISCR,0x63,0x80);
- /* End of Init1 */
-
- /* Set Mode 0x2e */
-
- /* Ramsize */
- orSISIDXREG(SISSR,0x16,0x0f);
- orSISIDXREG(SISSR,0x18,0xA9);
- orSISIDXREG(SISSR,0x19,0xA0);
- orSISIDXREG(SISSR,0x1B,0x30);
- andSISIDXREG(SISSR,0x17,0xF8);
- orSISIDXREG(SISSR,0x19,0x03);
- andSIDIDXREG(SISSR,0x13,0x00);
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- /* Find out about bus width */
- if(memtype <= 1) {
- outSISIDXREG(SISSR,0x14,0x02);
- andSISIDXREG(SISSR,0x16,0x0F);
- orSISIDXREG(SISSR,0x16,0x80);
+ andSISIDXREG(SISCR, 0x89, 0x8f);
- ...
+ ptr = cs45a;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
+ ptr = (const u8 *)&bios[index];
+ }
+ regd = le16_to_cpu(((const u16 *)ptr)[regb]);
+ reg = 0x80;
+ for(i = 0; i < 5; i++) {
+ reg &= 0xfc;
+ if(regd & 0x01) reg |= 0x01;
+ if(regd & 0x02) reg |= 0x02;
+ regd >>= 2;
+ outSISIDXREG(SISCR, 0x89, reg);
+ inSISIDXREG(SISCR, 0x89, reg);
+ inSISIDXREG(SISCR, 0x89, reg);
+ reg += 0x10;
+ }
- } else {
+ v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x118 + regb];
+ v2 = bios[0xf8 + regb];
+ v3 = bios[0x120 + regb];
+ v4 = bios[0x1ca];
+ }
+ outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
+ outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
+ orSISIDXREG(SISCR, 0x40, v1 & 0x80);
+ outSISIDXREG(SISCR, 0x41, v2);
- ...
+ ptr = cs170;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x170];
+ }
+ for(i = 0, j = 0; i < 7; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
+ }
- }
+ outSISIDXREG(SISCR, 0x59, v3);
- /* Find out about size */
+ ptr = cs1a8;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x1a8];
+ }
+ for(i = 0, j = 0; i < 3; i++, j += 8) {
+ outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
+ }
+ ptr = cs100;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x100];
+ }
+ for(i = 0, j = 0; i < 2; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
+ }
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */
+ outSISIDXREG(SISCR, 0xcf, v4);
+
+ outSISIDXREG(SISCR, 0x83, 0x09);
+ outSISIDXREG(SISCR, 0x87, 0x00);
+
+ if(ivideo->chip == XGI_40) {
+ if( (ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2) ) {
+ outSISIDXREG(SISCR, 0x8c, 0x87);
+ }
+ }
+
+ outSISIDXREG(SISSR, 0x17, 0x00);
+ outSISIDXREG(SISSR, 0x1a, 0x87);
+
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISSR, 0x15, 0x00);
+ outSISIDXREG(SISSR, 0x1c, 0x00);
+ }
+
+ ramtype = 0x00; v1 = 0x10;
+ if(ivideo->haveXGIROM) {
+ ramtype = bios[0x62];
+ v1 = bios[0x1d2];
+ }
+ if(!(ramtype & 0x80)) {
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISCR, 0x97, v1);
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(reg & 0x10) {
+ ramtype = (reg & 0x01) << 1;
+ }
+ } else {
+ inSISIDXREG(SISSR, 0x39, reg);
+ ramtype = reg & 0x02;
+ if(!(ramtype)) {
+ inSISIDXREG(SISSR, 0x3a, reg);
+ ramtype = (reg >> 1) & 0x01;
+ }
+ }
+ }
+ ramtype &= 0x07;
+
+ regb = 0; /* ! */
+
+ switch(ramtype) {
+ case 0:
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2)) {
+ v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x158];
+ v2 = bios[regb + 0x160];
+ v3 = bios[regb + 0x168];
+ }
+ outSISIDXREG(SISCR, 0x82, v1);
+ outSISIDXREG(SISCR, 0x85, v2);
+ outSISIDXREG(SISCR, 0x86, v3);
+ } else {
+ outSISIDXREG(SISCR, 0x82, 0x88);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+ outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+ }
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISCR, 0x97, 0x00);
+ }
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ outSISIDXREG(SISSR, 0x18, 0x01);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ } else {
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ }
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ } else {
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ }
+ } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
+ /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
+ }
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 4);
+ v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
+ v2 = bios[index];
+ v3 = bios[index + 1];
+ v4 = bios[index + 2];
+ v5 = bios[index + 3];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+ outSISIDXREG(SISSR, 0x16, v2);
+ outSISIDXREG(SISSR, 0x16, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x1b, 0x03);
+ sisfb_post_xgi_delay(ivideo, 0x22);
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x00);
+ outSISIDXREG(SISSR, 0x16, v4);
+ outSISIDXREG(SISSR, 0x16, v5);
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ break;
+ case 1:
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ inSISIDXREG(SISCR, 0x86, reg);
+ v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x168];
+ v2 = bios[regb + 0x160];
+ v3 = bios[regb + 0x158];
+ }
+ outSISIDXREG(SISCR, 0x86, v1);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, v2);
+ outSISIDXREG(SISCR, 0x82, v3);
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ outSISIDXREG(SISSR, 0x28, 0x64);
+ outSISIDXREG(SISSR, 0x29, 0x63);
+ sisfb_post_xgi_delay(ivideo, 15);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ outSISIDXREG(SISSR, 0x18, 0xc5);
+ outSISIDXREG(SISSR, 0x19, 0x23);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISCR, 0x97,0x11);
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ sisfb_post_xgi_delay(ivideo, 0x46);
+ outSISIDXREG(SISSR, 0x18, 0xc5);
+ outSISIDXREG(SISSR, 0x19, 0x23);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISSR, 0x1b, 0x04);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ sisfb_post_xgi_delay(ivideo, 1);
+ v1 = 0x31;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x06);
+ outSISIDXREG(SISSR, 0x16, 0x04);
+ outSISIDXREG(SISSR, 0x16, 0x84);
+ sisfb_post_xgi_delay(ivideo, 1);
+ break;
+ default:
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ if((ivideo->chip == XGI_40) &&
+ ((ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2))) {
+ outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+ outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+ outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+ } else {
+ outSISIDXREG(SISCR, 0x82, 0x88);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ v1 = cs160[regb]; v2 = cs158[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x160];
+ v2 = bios[regb + 0x158];
+ }
+ outSISIDXREG(SISCR, 0x85, v1);
+ outSISIDXREG(SISCR, 0x82, v2);
+ }
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISCR, 0x97, 0x11);
+ }
+ if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ } else {
+ outSISIDXREG(SISCR, 0x98, 0x03);
+ }
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x18, 0x01);
+ } else {
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ }
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ }
+ sisfb_post_xgi_delay(ivideo, 4);
+ v1 = 0x31;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x01);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x16, bios[0x53e]);
+ outSISIDXREG(SISSR, 0x16, bios[0x53f]);
+ } else {
+ outSISIDXREG(SISSR, 0x16, 0x05);
+ outSISIDXREG(SISSR, 0x16, 0x85);
+ }
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x1b, 0x01);
+ } else {
+ outSISIDXREG(SISSR, 0x1b, 0x03);
+ }
+ sisfb_post_xgi_delay(ivideo, 0x22);
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x00);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x16, bios[0x540]);
+ outSISIDXREG(SISSR, 0x16, bios[0x541]);
+ } else {
+ outSISIDXREG(SISSR, 0x16, 0x05);
+ outSISIDXREG(SISSR, 0x16, 0x85);
+ }
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ }
+
+ regb = 0; /* ! */
+ v1 = 0x03;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x110 + regb];
+ }
+ outSISIDXREG(SISSR, 0x1b, v1);
+
+ /* RAM size */
+ v1 = 0x00; v2 = 0x00;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x62];
+ v2 = bios[0x63];
}
+ regb = 0; /* ! */
+ regd = 1 << regb;
+ if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
+
+ outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
+ outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
+
+ } else {
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Disable read-cache */
+ andSISIDXREG(SISSR, 0x21, 0xdf);
+ sisfb_post_xgi_ramsize(ivideo);
+ /* Enable read-cache */
+ orSISIDXREG(SISSR, 0x21, 0x20);
- /* AGP (Missing: Checks for VIA and AMD hosts) */
- v1 = 0xA5; v2 = 0xFB;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
}
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
+#if 0
+ printk(KERN_DEBUG "-----------------\n");
+ for(i = 0; i < 0xff; i++) {
+ inSISIDXREG(SISCR, i, reg);
+ printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
+ }
+ for(i = 0; i < 0x40; i++) {
+ inSISIDXREG(SISSR, i, reg);
+ printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
+ }
+ printk(KERN_DEBUG "-----------------\n");
#endif
- return;
+
+ /* Sense CRT1 */
+ if(ivideo->chip == XGI_20) {
+ orSISIDXREG(SISCR, 0x32, 0x20);
+ } else {
+ inSISIDXREG(SISPART4, 0x00, reg);
+ if((reg == 1) || (reg == 2)) {
+ sisfb_sense_crt1(ivideo);
+ } else {
+ orSISIDXREG(SISCR, 0x32, 0x20);
+ }
+ }
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Display off */
+ orSISIDXREG(SISSR, 0x01, 0x20);
+
+ /* Save mode number in CR34 */
+ outSISIDXREG(SISCR, 0x34, 0x2e);
+
+ /* Let everyone know what the current mode is */
+ ivideo->modeprechange = 0x2e;
+
+ if(ivideo->chip == XGI_40) {
+ inSISIDXREG(SISCR, 0xca, reg);
+ inSISIDXREG(SISCR, 0xcc, v1);
+ if((reg & 0x10) && (!(v1 & 0x04))) {
+ printk(KERN_ERR
+ "sisfb: Please connect power to the card.\n");
+ return 0;
+ }
+ }
+
+ return 1;
}
#endif
-
-static int __devinit sisfb_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit
+sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
- struct sis_video_info *ivideo = NULL;
- struct fb_info *sis_fb_info = NULL;
+ struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
+ struct sis_video_info *ivideo = NULL;
+ struct fb_info *sis_fb_info = NULL;
u16 reg16;
u8 reg;
- int sisvga_enabled = 0, i;
+ int i, ret;
- if(sisfb_off) return -ENXIO;
+ if(sisfb_off)
+ return -ENXIO;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
- if(!sis_fb_info) return -ENOMEM;
+ if(!sis_fb_info)
+ return -ENOMEM;
#else
sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
- if(!sis_fb_info) return -ENOMEM;
+ if(!sis_fb_info)
+ return -ENOMEM;
memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
#endif
@@ -4787,27 +5890,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo = (struct sis_video_info *)sis_fb_info->par;
ivideo->memyselfandi = sis_fb_info;
+ ivideo->sisfb_id = SISFB_ID;
+
if(card_list == NULL) {
- ivideo->cardnumber = 0;
+ ivideo->cardnumber = 0;
} else {
- struct sis_video_info *countvideo = card_list;
- ivideo->cardnumber = 1;
- while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++;
+ struct sis_video_info *countvideo = card_list;
+ ivideo->cardnumber = 1;
+ while((countvideo = countvideo->next) != 0)
+ ivideo->cardnumber++;
}
strncpy(ivideo->myid, chipinfo->chip_name, 30);
ivideo->warncount = 0;
ivideo->chip_id = pdev->device;
+ ivideo->chip_vendor = pdev->vendor;
pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
- ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
+ ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
pci_read_config_word(pdev, PCI_COMMAND, &reg16);
- sisvga_enabled = reg16 & 0x01;
+ ivideo->sisvga_enabled = reg16 & 0x01;
ivideo->pcibus = pdev->bus->number;
ivideo->pcislot = PCI_SLOT(pdev->devfn);
ivideo->pcifunc = PCI_FUNC(pdev->devfn);
ivideo->subsysvendor = pdev->subsystem_vendor;
ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ ivideo->ioctl32registered = 0;
+#endif
#ifndef MODULE
if(sisfb_mode_idx == -1) {
@@ -4827,6 +5937,24 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->sisfb_thismonitor.datavalid = FALSE;
+ ivideo->current_base = 0;
+
+ ivideo->engineok = 0;
+
+ ivideo->sisfb_was_boot_device = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+ if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
+ if(ivideo->sisvga_enabled)
+ ivideo->sisfb_was_boot_device = 1;
+ else {
+ printk(KERN_DEBUG "sisfb: PCI device is disabled, "
+ "but marked as boot video device ???\n");
+ printk(KERN_DEBUG "sisfb: I will not accept this "
+ "as the primary VGA device\n");
+ }
+ }
+#endif
+
ivideo->sisfb_parm_mem = sisfb_parm_mem;
ivideo->sisfb_accel = sisfb_accel;
ivideo->sisfb_ypan = sisfb_ypan;
@@ -4846,7 +5974,6 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->sisfb_tvstd = sisfb_tvstd;
ivideo->tvxpos = sisfb_tvxposoffset;
ivideo->tvypos = sisfb_tvyposoffset;
- ivideo->sisfb_filter = sisfb_filter;
ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
ivideo->sisfb_inverse = sisfb_inverse;
@@ -4854,7 +5981,7 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->refresh_rate = 0;
if(ivideo->sisfb_parm_rate != -1) {
- ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+ ivideo->refresh_rate = ivideo->sisfb_parm_rate;
}
ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
@@ -4863,8 +5990,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
- ivideo->SiS_Pr.SiS_CHOverScan = -1;
- ivideo->SiS_Pr.SiS_ChSW = FALSE;
+ ivideo->SiS_Pr.SiS_CHOverScan = -1;
+ ivideo->SiS_Pr.SiS_ChSW = FALSE;
ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
ivideo->SiS_Pr.HaveEMI = FALSE;
ivideo->SiS_Pr.HaveEMILCD = FALSE;
@@ -4873,12 +6000,13 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
ivideo->SiS_Pr.PDC = -1;
ivideo->SiS_Pr.PDCA = -1;
+ ivideo->SiS_Pr.DDCPortMixup = FALSE;
#ifdef CONFIG_FB_SIS_315
if(ivideo->chip >= SIS_330) {
- ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
- if(ivideo->chip >= SIS_661) {
- ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
- }
+ ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+ if(ivideo->chip >= SIS_661) {
+ ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+ }
}
#endif
@@ -4891,9 +6019,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
switch(ivideo->nbridge->device) {
#ifdef CONFIG_FB_SIS_300
case PCI_DEVICE_ID_SI_730:
- ivideo->chip = SIS_730;
+ ivideo->chip = SIS_730;
strcpy(ivideo->myid, "SiS 730");
- break;
+ break;
#endif
#ifdef CONFIG_FB_SIS_315
case PCI_DEVICE_ID_SI_651:
@@ -4901,22 +6029,28 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
strcpy(ivideo->myid, "SiS 651");
break;
case PCI_DEVICE_ID_SI_740:
- ivideo->chip = SIS_740;
+ ivideo->chip = SIS_740;
strcpy(ivideo->myid, "SiS 740");
break;
case PCI_DEVICE_ID_SI_661:
- ivideo->chip = SIS_661;
+ ivideo->chip = SIS_661;
strcpy(ivideo->myid, "SiS 661");
break;
case PCI_DEVICE_ID_SI_741:
- ivideo->chip = SIS_741;
+ ivideo->chip = SIS_741;
strcpy(ivideo->myid, "SiS 741");
break;
case PCI_DEVICE_ID_SI_760:
- ivideo->chip = SIS_760;
+ ivideo->chip = SIS_760;
strcpy(ivideo->myid, "SiS 760");
break;
+ case PCI_DEVICE_ID_SI_761:
+ ivideo->chip = SIS_761;
+ strcpy(ivideo->myid, "SiS 761");
+ break;
#endif
+ default:
+ break;
}
}
@@ -4924,71 +6058,83 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
strcpy(sis_fb_info->modename, ivideo->myid);
#endif
- ivideo->sishw_ext.jChipType = ivideo->chip;
+ ivideo->SiS_Pr.ChipType = ivideo->chip;
+
+ ivideo->SiS_Pr.ivideo = (void *)ivideo;
#ifdef CONFIG_FB_SIS_315
- if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
- (ivideo->sishw_ext.jChipType == SIS_315)) {
- ivideo->sishw_ext.jChipType = SIS_315H;
+ if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
+ (ivideo->SiS_Pr.ChipType == SIS_315)) {
+ ivideo->SiS_Pr.ChipType = SIS_315H;
}
#endif
+ if(!ivideo->sisvga_enabled) {
+ if(pci_enable_device(pdev)) {
+ if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+ pci_set_drvdata(pdev, NULL);
+ kfree(sis_fb_info);
+ return -EIO;
+ }
+ }
+
ivideo->video_base = pci_resource_start(pdev, 0);
ivideo->mmio_base = pci_resource_start(pdev, 1);
ivideo->mmio_size = pci_resource_len(pdev, 1);
ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
- ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
+ ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
- if(!sisvga_enabled) {
- if(pci_enable_device(pdev)) {
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EIO;
- }
- }
-
- SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
+ SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
#ifdef CONFIG_FB_SIS_300
/* Find PCI systems for Chrontel/GPIO communication setup */
if(ivideo->chip == SIS_630) {
- i=0;
- do {
- if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
- mychswtable[i].subsysCard == ivideo->subsysdevice) {
- ivideo->SiS_Pr.SiS_ChSW = TRUE;
- printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
- mychswtable[i].vendorName, mychswtable[i].cardName);
- break;
- }
- i++;
- } while(mychswtable[i].subsysVendor != 0);
+ i = 0;
+ do {
+ if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+ mychswtable[i].subsysCard == ivideo->subsysdevice) {
+ ivideo->SiS_Pr.SiS_ChSW = TRUE;
+ printk(KERN_DEBUG "sisfb: Identified [%s %s] "
+ "requiring Chrontel/GPIO setup\n",
+ mychswtable[i].vendorName,
+ mychswtable[i].cardName);
+ ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
+ break;
+ }
+ i++;
+ } while(mychswtable[i].subsysVendor != 0);
+ }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+ if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
+ ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
}
#endif
- outSISIDXREG(SISSR, 0x05, 0x86);
+ outSISIDXREG(SISSR, 0x05, 0x86);
- if( (!sisvga_enabled)
+ if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
+ || (sisfb_resetcard)
#endif
- ) {
- for(i = 0x30; i <= 0x3f; i++) {
- outSISIDXREG(SISCR,i,0x00);
- }
+ ) {
+ for(i = 0x30; i <= 0x3f; i++) {
+ outSISIDXREG(SISCR, i, 0x00);
+ }
}
/* Find out about current video mode */
ivideo->modeprechange = 0x03;
- inSISIDXREG(SISCR,0x34,reg);
+ inSISIDXREG(SISCR, 0x34, reg);
if(reg & 0x7f) {
ivideo->modeprechange = reg & 0x7f;
- } else if(sisvga_enabled) {
+ } else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
- unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000);
+ unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
if(tt) {
- ivideo->modeprechange = readb(tt + 0x449);
- iounmap(tt);
+ ivideo->modeprechange = readb(tt + 0x49);
+ iounmap(tt);
}
#endif
}
@@ -4996,219 +6142,221 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#ifdef MODULE
if((reg & 0x80) && (reg != 0xff)) {
- if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
- printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EBUSY;
- }
+ if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni])
+ != 0xFF) {
+ printk(KERN_INFO "sisfb: Cannot initialize display mode, "
+ "X server is active\n");
+ ret = -EBUSY;
+ goto error_4;
+ }
}
-#endif
#endif
-
- ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
-#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->chip != SIS_300) {
- inSISIDXREG(SISSR, 0x1a, reg);
- if(!(reg & 0x10)) {
- ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
- }
- }
- }
#endif
+ /* Search and copy ROM image */
ivideo->bios_abase = NULL;
+ ivideo->SiS_Pr.VirtualRomBase = NULL;
+ ivideo->SiS_Pr.UseROM = FALSE;
+ ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
if(ivideo->sisfb_userom) {
- ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
- ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;
- if(ivideo->sishw_ext.pjVirtualRomBase) {
- printk(KERN_INFO "sisfb: Video ROM found and copied\n");
- ivideo->sishw_ext.UseROM = TRUE;
- } else {
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM not found\n");
- }
+ ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
+ ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
+ ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
+ printk(KERN_INFO "sisfb: Video ROM %sfound\n",
+ ivideo->SiS_Pr.UseROM ? "" : "not ");
+ if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
+ ivideo->SiS_Pr.UseROM = FALSE;
+ ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
+ if( (ivideo->revision_id == 2) &&
+ (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
+ ivideo->SiS_Pr.DDCPortMixup = TRUE;
+ }
+ }
} else {
- ivideo->sishw_ext.pjVirtualRomBase = NULL;
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
+ printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
}
- /* Find systems for special custom timing */
+ /* Find systems for special custom timing */
if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
- int j;
- unsigned char *biosver = NULL;
- unsigned char *biosdate = NULL;
- BOOLEAN footprint;
- u32 chksum = 0;
-
- if(ivideo->sishw_ext.UseROM) {
- biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
- biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
- for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
- }
-
- i=0;
- do {
- if( (mycustomttable[i].chipID == ivideo->chip) &&
- ((!strlen(mycustomttable[i].biosversion)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
- ((!strlen(mycustomttable[i].biosdate)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
- ((!mycustomttable[i].bioschksum) ||
- (ivideo->sishw_ext.UseROM &&
- (mycustomttable[i].bioschksum == chksum))) &&
- (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
- (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
- footprint = TRUE;
- for(j = 0; j < 5; j++) {
- if(mycustomttable[i].biosFootprintAddr[j]) {
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
- mycustomttable[i].biosFootprintData[j]) {
- footprint = FALSE;
- }
- } else footprint = FALSE;
- }
- }
- if(footprint) {
- ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
- printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
- mycustomttable[i].optionName);
- break;
- }
- }
- i++;
- } while(mycustomttable[i].chipID);
+ sisfb_detect_custom_timing(ivideo);
}
-#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if( (!sisvga_enabled)
+ /* POST card in case this has not been done by the BIOS */
+ if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
+ || (sisfb_resetcard)
#endif
- ) {
+ ) {
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
if(ivideo->chip == SIS_300) {
sisfb_post_sis300(pdev);
+ ivideo->sisfb_can_post = 1;
}
}
- }
#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if( (!sisvga_enabled)
-#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
-#endif
- ) {
- if((ivideo->chip == SIS_315H) ||
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ int result = 1;
+ /* if((ivideo->chip == SIS_315H) ||
(ivideo->chip == SIS_315) ||
(ivideo->chip == SIS_315PRO) ||
(ivideo->chip == SIS_330)) {
sisfb_post_sis315330(pdev);
+ } else */ if(ivideo->chip == XGI_20) {
+ result = sisfb_post_xgi(pdev);
+ ivideo->sisfb_can_post = 1;
+ } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+ result = sisfb_post_xgi(pdev);
+ ivideo->sisfb_can_post = 1;
+ } else {
+ printk(KERN_INFO "sisfb: Card is not "
+ "POSTed and sisfb can't do this either.\n");
+ }
+ if(!result) {
+ printk(KERN_ERR "sisfb: Failed to POST card\n");
+ ret = -ENODEV;
+ goto error_3;
}
}
- }
#endif
+ }
+ ivideo->sisfb_card_posted = 1;
+
+ /* Find out about RAM size */
if(sisfb_get_dram_size(ivideo)) {
- printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
+ ret = -ENODEV;
+ goto error_3;
}
+
+ /* Enable PCI addressing and MMIO */
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+ /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
+ orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+ /* Enable 2D accelerator engine */
+ orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
}
if(sisfb_pdc != 0xff) {
- if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
- else sisfb_pdc &= 0x1f;
- ivideo->SiS_Pr.PDC = sisfb_pdc;
+ if(ivideo->sisvga_engine == SIS_300_VGA)
+ sisfb_pdc &= 0x3c;
+ else
+ sisfb_pdc &= 0x1f;
+ ivideo->SiS_Pr.PDC = sisfb_pdc;
}
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+ if(sisfb_pdca != 0xff)
+ ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
}
#endif
if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
+ printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
+ (int)(ivideo->video_size >> 20));
printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ ret = -ENODEV;
+ goto error_3;
}
if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ ret = -ENODEV;
+ goto error_2;
}
ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
- ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
+ ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
if(!ivideo->video_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
+ ret = -ENODEV;
+ goto error_1;
}
ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
if(!ivideo->mmio_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
- iounmap(ivideo->video_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+ printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
+ ret = -ENODEV;
+error_0: iounmap(ivideo->video_vbase);
+error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
+error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+error_3: vfree(ivideo->bios_abase);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+error_4:
+#endif
+ if(ivideo->lpcdev)
+ SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+ if(ivideo->nbridge)
+ SIS_PCI_PUT_DEVICE(ivideo->nbridge);
pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ if(!ivideo->sisvga_enabled)
+ pci_disable_device(pdev);
+ kfree(sis_fb_info);
+ return ret;
}
- printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024);
+ printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
+ ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
+
+ if(ivideo->video_offset) {
+ printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
+ ivideo->video_offset / 1024);
+ }
printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+ ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+
+ /* Determine the size of the command queue */
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
+ } else {
+ if(ivideo->chip == XGI_20) {
+ ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
+ } else {
+ ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
+ }
+ }
+
+ /* Engines are no longer initialized here; this is
+ * now done after the first mode-switch (if the
+ * submitted var has its acceleration flags set).
+ */
+
+ /* Calculate the base of the (unused) hw cursor */
+ ivideo->hwcursor_vbase = ivideo->video_vbase
+ + ivideo->video_size
+ - ivideo->cmdQueueSize
+ - ivideo->hwcursor_size;
+ ivideo->caps |= HW_CURSOR_CAP;
+
+ /* Initialize offscreen memory manager */
if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
}
/* Used for clearing the screen only, therefore respect our mem limit */
- ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
+ ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
+ ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
- ivideo->mtrr = 0;
+ ivideo->mtrr = -1;
ivideo->vbflags = 0;
ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
ivideo->tvdefmodeidx = DEFAULT_TVMODE;
ivideo->defmodeidx = DEFAULT_MODE;
- ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
+ ivideo->newrom = 0;
+ if(ivideo->chip < XGI_20) {
+ if(ivideo->bios_abase) {
+ ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
+ }
+ }
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
@@ -5217,192 +6365,57 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
sisfb_get_VB_type(ivideo);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
sisfb_detect_VB_connect(ivideo);
}
ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
- if(ivideo->sisfb_crt2type != -1) {
- if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
- ivideo->currentvbflags |= CRT2_LCD;
- } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
- ivideo->currentvbflags |= ivideo->sisfb_crt2type;
- }
- } else {
- /* Chrontel 700x TV detection often unreliable, therefore use a
- * different default order on such machines
- */
- if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
- if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- } else {
- if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- }
- }
+ /* Decide on which CRT2 device to use */
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+ if(ivideo->sisfb_crt2type != -1) {
+ if((ivideo->sisfb_crt2type == CRT2_LCD) &&
+ (ivideo->vbflags & CRT2_LCD)) {
+ ivideo->currentvbflags |= CRT2_LCD;
+ } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+ ivideo->currentvbflags |= ivideo->sisfb_crt2type;
+ }
+ } else {
+ /* Chrontel 700x TV detection often unreliable, therefore
+ * use a different default order on such machines
+ */
+ if((ivideo->sisvga_engine == SIS_300_VGA) &&
+ (ivideo->vbflags2 & VB2_CHRONTEL)) {
+ if(ivideo->vbflags & CRT2_LCD)
+ ivideo->currentvbflags |= CRT2_LCD;
+ else if(ivideo->vbflags & CRT2_TV)
+ ivideo->currentvbflags |= CRT2_TV;
+ else if(ivideo->vbflags & CRT2_VGA)
+ ivideo->currentvbflags |= CRT2_VGA;
+ } else {
+ if(ivideo->vbflags & CRT2_TV)
+ ivideo->currentvbflags |= CRT2_TV;
+ else if(ivideo->vbflags & CRT2_LCD)
+ ivideo->currentvbflags |= CRT2_LCD;
+ else if(ivideo->vbflags & CRT2_VGA)
+ ivideo->currentvbflags |= CRT2_VGA;
+ }
+ }
}
if(ivideo->vbflags & CRT2_LCD) {
- inSISIDXREG(SISCR, 0x36, reg);
- reg &= 0x0f;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- ivideo->CRT2LCDType = sis300paneltype[reg];
- } else if(ivideo->chip >= SIS_661) {
- ivideo->CRT2LCDType = sis661paneltype[reg];
- } else {
- ivideo->CRT2LCDType = sis310paneltype[reg];
- if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
- if((ivideo->CRT2LCDType != LCD_640x480_2) &&
- (ivideo->CRT2LCDType != LCD_640x480_3)) {
- ivideo->CRT2LCDType = LCD_320x480;
- }
- }
- }
- if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
- /* For broken BIOSes: Assume 1024x768, RGB18 */
- ivideo->CRT2LCDType = LCD_1024x768;
- setSISIDXREG(SISCR,0x36,0xf0,0x02);
- setSISIDXREG(SISCR,0x37,0xee,0x01);
- printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
- }
- for(i = 0; i < SIS_LCD_NUMBER; i++) {
- if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
- ivideo->lcdxres = sis_lcd_data[i].xres;
- ivideo->lcdyres = sis_lcd_data[i].yres;
- ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
- break;
- }
- }
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
- ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
- } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47;
- }
- printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
- ivideo->lcdxres, ivideo->lcdyres);
- }
-
-#ifdef CONFIG_FB_SIS_300
- /* Save the current PanelDelayCompensation if the LCD is currently used */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if(tmp & 0x20) {
- /* Currently on LCD? If yes, read current pdc */
- inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
- ivideo->detectedpdc &= 0x3c;
- if(ivideo->SiS_Pr.PDC == -1) {
- /* Let option override detection */
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
- ivideo->detectedpdc);
- }
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
- ivideo->SiS_Pr.PDC);
- }
- }
+ sisfb_detect_lcd_type(ivideo);
}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
-
- /* Try to find about LCDA */
- if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISPART1,0x13,tmp);
- if(tmp & 0x04) {
- ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
- ivideo->detectedlcda = 0x03;
- }
- }
-
- /* Save PDC */
- if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- /* Currently on LCD? If yes, read current pdc */
- u8 pdc;
- inSISIDXREG(SISPART1,0x2D,pdc);
- ivideo->detectedpdc = (pdc & 0x0f) << 1;
- ivideo->detectedpdca = (pdc & 0xf0) >> 3;
- inSISIDXREG(SISPART1,0x35,pdc);
- ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
- inSISIDXREG(SISPART1,0x20,pdc);
- ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
- if(ivideo->newrom) {
- /* New ROM invalidates other PDC resp. */
- if(ivideo->detectedlcda != 0xff) {
- ivideo->detectedpdc = 0xff;
- } else {
- ivideo->detectedpdca = 0xff;
- }
- }
- if(ivideo->SiS_Pr.PDC == -1) {
- if(ivideo->detectedpdc != 0xff) {
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- }
- if(ivideo->SiS_Pr.PDCA == -1) {
- if(ivideo->detectedpdca != 0xff) {
- ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
- }
- }
- if(ivideo->detectedpdc != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->detectedpdc);
- }
- if(ivideo->detectedpdca != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->detectedpdca);
- }
- }
-
- /* Save EMI */
- if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
- inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
- inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
- inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
- inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
- ivideo->SiS_Pr.HaveEMI = TRUE;
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- ivideo->SiS_Pr.HaveEMILCD = TRUE;
- }
- }
- }
-
- /* Let user override detected PDCs (all bridges) */
- if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->SiS_Pr.PDC);
- }
- if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
- printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->SiS_Pr.PDCA);
- }
- }
- }
-#endif
+ sisfb_save_pdc_emi(ivideo);
if(!ivideo->sisfb_crt1off) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
+ sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
} else {
- if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
- (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
- }
+ if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
+ (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+ sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
+ }
}
if(ivideo->sisfb_mode_idx >= 0) {
@@ -5434,7 +6447,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
if(ivideo->refresh_rate != 0) {
- sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+ sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
+ ivideo->sisfb_mode_idx);
}
if(ivideo->rate_idx == 0) {
@@ -5443,9 +6457,12 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
}
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
- ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
+ ivideo->sisfb_mode_idx,
+ ivideo->rate_idx,
+ ivideo->refresh_rate)) {
+ printk(KERN_INFO "sisfb: WARNING: Refresh rate "
+ "exceeds monitor specs!\n");
}
}
@@ -5454,28 +6471,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
sisfb_set_vparms(ivideo);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /* ---------------- For 2.4: Now switch the mode ------------------ */
-
- printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+ /* ---------------- For 2.4: Now switch the mode ------------------ */
+
+ printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
+ ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
+ /* Determine whether or not acceleration is to be
+ * used. Need to know before pre/post_set_mode()
+ */
+ ivideo->accel = 0;
+ ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
+ if(ivideo->sisfb_accel) {
+ ivideo->accel = -1;
+ ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+ }
+
+ /* Now switch the mode */
sisfb_pre_setmode(ivideo);
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+ if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
ivideo->mode_no);
- iounmap(ivideo->video_vbase);
+ ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
+ goto error_0;
}
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -5488,18 +6511,17 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
/* Force reset of x virtual in crtc_to_var */
ivideo->default_var.xres_virtual = 0;
+ /* Copy mode timing to var */
sisfb_crtc_to_var(ivideo, &ivideo->default_var);
+ /* Find out about screen pitch */
sisfb_calc_pitch(ivideo, &ivideo->default_var);
sisfb_set_pitch(ivideo);
- ivideo->accel = 0;
- if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
- }
+ /* Init the accelerator (does nothing currently) */
sisfb_initaccel(ivideo);
-
+
+ /* Init some fbinfo entries */
sis_fb_info->node = -1;
sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
sis_fb_info->fbops = &sisfb_ops;
@@ -5515,41 +6537,42 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+ ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
+ /* Set up the default var according to chosen default display mode */
ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
sisfb_bpp_to_var(ivideo, &ivideo->default_var);
-
+
ivideo->default_var.pixclock = (u32) (1000000000 /
- sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx));
-
- if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
- if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- ivideo->default_var.pixclock <<= 1;
- }
- }
+ sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
+
+ if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
+ ivideo->rate_idx, &ivideo->default_var)) {
+ if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ ivideo->default_var.pixclock <<= 1;
+ }
+ }
if(ivideo->sisfb_ypan) {
- /* Maximize regardless of sisfb_max at startup */
- ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var);
- if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
- ivideo->default_var.yres_virtual = ivideo->default_var.yres;
- }
+ /* Maximize regardless of sisfb_max at startup */
+ ivideo->default_var.yres_virtual =
+ sisfb_calc_maxyres(ivideo, &ivideo->default_var);
+ if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
+ ivideo->default_var.yres_virtual = ivideo->default_var.yres;
+ }
}
sisfb_calc_pitch(ivideo, &ivideo->default_var);
ivideo->accel = 0;
if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
+ ivideo->accel = -1;
#ifdef STUPID_ACCELF_TEXT_SHIT
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+ ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
#endif
}
sisfb_initaccel(ivideo);
@@ -5566,21 +6589,21 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#endif
sis_fb_info->var = ivideo->default_var;
sis_fb_info->fix = ivideo->sisfb_fix;
- sis_fb_info->screen_base = ivideo->video_vbase;
+ sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
sis_fb_info->fbops = &sisfb_ops;
sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
-
+
fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
#endif /* 2.6 */
- printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
+ printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
#ifdef CONFIG_MTRR
ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
MTRR_TYPE_WRCOMB, 1);
- if(!ivideo->mtrr) {
+ if(ivideo->mtrr < 0) {
printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
}
#endif
@@ -5591,14 +6614,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
if(register_framebuffer(sis_fb_info) < 0) {
printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
- iounmap(ivideo->video_vbase);
+ ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
+ goto error_0;
}
ivideo->registered = 1;
@@ -5607,21 +6625,47 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->next = card_list;
card_list = ivideo;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ {
+ int ret;
+ /* Our ioctls are all "32/64bit compatible" */
+ ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
+ ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
+ ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
+ if(ret)
+ printk(KERN_ERR
+ "sisfb: Error registering ioctl32 translations\n");
+ else
+ ivideo->ioctl32registered = 1;
+ }
+#endif
+
printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
- ivideo->sisfb_accel ? "enabled" : "disabled",
- ivideo->sisfb_ypan ?
- (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled");
+ ivideo->sisfb_accel ? "enabled" : "disabled",
+ ivideo->sisfb_ypan ?
+ (ivideo->sisfb_max ? "enabled (auto-max)" :
+ "enabled (no auto-max)") :
+ "disabled");
- printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n",
+ printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- GET_FB_IDX(sis_fb_info->node),
+ GET_FB_IDX(sis_fb_info->node),
#else
- sis_fb_info->node,
+ sis_fb_info->node,
#endif
ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
- printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
+ printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
} /* if mode = "none" */
@@ -5634,26 +6678,62 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
static void __devexit sisfb_remove(struct pci_dev *pdev)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- struct fb_info *sis_fb_info = ivideo->memyselfandi;
- int registered = ivideo->registered;
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ struct fb_info *sis_fb_info = ivideo->memyselfandi;
+ int registered = ivideo->registered;
+ int modechanged = ivideo->modechanged;
+
+#ifdef SIS_OLD_CONFIG_COMPAT
+ if(ivideo->ioctl32registered) {
+ int ret;
+ ret = unregister_ioctl32_conversion(FBIO_ALLOC);
+ ret |= unregister_ioctl32_conversion(FBIO_FREE);
+ ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
+ if(ret)
+ printk(KERN_ERR
+ "sisfb: Error unregistering ioctl32 translations\n");
+ }
+#endif
/* Unmap */
- iounmap(ivideo->video_vbase);
iounmap(ivideo->mmio_vbase);
- vfree(ivideo->bios_abase);
+ iounmap(ivideo->video_vbase);
/* Release mem regions */
release_mem_region(ivideo->video_base, ivideo->video_size);
release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+ vfree(ivideo->bios_abase);
+
+ if(ivideo->lpcdev)
+ SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+
+ if(ivideo->nbridge)
+ SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+
#ifdef CONFIG_MTRR
/* Release MTRR region */
- if(ivideo->mtrr) {
+ if(ivideo->mtrr >= 0)
mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
- }
#endif
+ pci_set_drvdata(pdev, NULL);
+
+ /* If device was disabled when starting, disable
+ * it when quitting.
+ */
+ if(!ivideo->sisvga_enabled)
+ pci_disable_device(pdev);
+
/* Unregister the framebuffer */
if(ivideo->registered) {
unregister_framebuffer(sis_fb_info);
@@ -5664,7 +6744,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
#endif
}
- pci_set_drvdata(pdev, NULL);
+ /* OK, our ivideo is gone for good from here. */
/* TODO: Restore the initial mode
* This sounds easy but is as good as impossible
@@ -5673,15 +6753,15 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
* from machine to machine. Depends on the type
* of integration between chipset and bridge.
*/
- if(registered) {
- printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
- }
+ if(registered && modechanged)
+ printk(KERN_INFO
+ "sisfb: Restoring of text mode not supported yet\n");
};
static struct pci_driver sisfb_driver = {
.name = "sisfb",
.id_table = sisfb_pci_table,
- .probe = sisfb_probe,
+ .probe = sisfb_probe,
.remove = __devexit_p(sisfb_remove)
};
@@ -5693,10 +6773,11 @@ SISINITSTATIC int __init sisfb_init(void)
if(fb_get_options("sisfb", &options))
return -ENODEV;
+
sisfb_setup(options);
#endif
#endif
- return(pci_register_driver(&sisfb_driver));
+ return pci_register_driver(&sisfb_driver);
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -5711,36 +6792,129 @@ module_init(sisfb_init);
#ifdef MODULE
-static char *mode = NULL;
-static int vesa = -1;
-static unsigned int rate = 0;
-static unsigned int crt1off = 1;
-static unsigned int mem = 0;
-static char *forcecrt2type = NULL;
-static int forcecrt1 = -1;
-static int pdc = -1;
-static int pdc1 = -1;
-static int noaccel = -1;
-static int noypan = -1;
-static int nomax = -1;
+static char *mode = NULL;
+static int vesa = -1;
+static unsigned int rate = 0;
+static unsigned int crt1off = 1;
+static unsigned int mem = 0;
+static char *forcecrt2type = NULL;
+static int forcecrt1 = -1;
+static int pdc = -1;
+static int pdc1 = -1;
+static int noaccel = -1;
+static int noypan = -1;
+static int nomax = -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int inverse = 0;
+#endif
+static int userom = -1;
+static int useoem = -1;
+static char *tvstandard = NULL;
+static int nocrt2rate = 0;
+static int scalelcd = -1;
+static char *specialtiming = NULL;
+static int lvdshl = -1;
+static int tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int resetcard = 0;
+static int videoram = 0;
+#endif
+
+static int __init sisfb_init_module(void)
+{
+ sisfb_setdefaultparms();
+
+ if(rate)
+ sisfb_parm_rate = rate;
+
+ if((scalelcd == 0) || (scalelcd == 1))
+ sisfb_scalelcd = scalelcd ^ 1;
+
+ /* Need to check crt2 type first for fstn/dstn */
+
+ if(forcecrt2type)
+ sisfb_search_crt2type(forcecrt2type);
+
+ if(tvstandard)
+ sisfb_search_tvstd(tvstandard);
+
+ if(mode)
+ sisfb_search_mode(mode, FALSE);
+ else if(vesa != -1)
+ sisfb_search_vesamode(vesa, FALSE);
+
+ sisfb_crt1off = (crt1off == 0) ? 1 : 0;
+
+ sisfb_forcecrt1 = forcecrt1;
+ if(forcecrt1 == 1)
+ sisfb_crt1off = 0;
+ else if(forcecrt1 == 0)
+ sisfb_crt1off = 1;
+
+ if(noaccel == 1)
+ sisfb_accel = 0;
+ else if(noaccel == 0)
+ sisfb_accel = 1;
+
+ if(noypan == 1)
+ sisfb_ypan = 0;
+ else if(noypan == 0)
+ sisfb_ypan = 1;
+
+ if(nomax == 1)
+ sisfb_max = 0;
+ else if(nomax == 0)
+ sisfb_max = 1;
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int inverse = 0;
-#endif
-static int userom = -1;
-static int useoem = -1;
-static char *tvstandard = NULL;
-static int nocrt2rate = 0;
-static int scalelcd = -1;
-static char *specialtiming = NULL;
-static int lvdshl = -1;
-static int tvxposoffset = 0, tvyposoffset = 0;
-static int filter = -1;
+ if(inverse) sisfb_inverse = 1;
+#endif
+
+ if(mem)
+ sisfb_parm_mem = mem;
+
+ if(userom != -1)
+ sisfb_userom = userom;
+
+ if(useoem != -1)
+ sisfb_useoem = useoem;
+
+ if(pdc != -1)
+ sisfb_pdc = (pdc & 0x7f);
+
+ if(pdc1 != -1)
+ sisfb_pdca = (pdc1 & 0x1f);
+
+ sisfb_nocrt2rate = nocrt2rate;
+
+ if(specialtiming)
+ sisfb_search_specialtiming(specialtiming);
+
+ if((lvdshl >= 0) && (lvdshl <= 3))
+ sisfb_lvdshl = lvdshl;
+
+ sisfb_tvxposoffset = tvxposoffset;
+ sisfb_tvyposoffset = tvyposoffset;
+
#if !defined(__i386__) && !defined(__x86_64__)
-static int resetcard = 0;
-static int videoram = 0;
+ sisfb_resetcard = (resetcard) ? 1 : 0;
+ if(videoram)
+ sisfb_videoram = videoram;
#endif
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
+ return sisfb_init();
+}
+
+static void __exit sisfb_remove_module(void)
+{
+ pci_unregister_driver(&sisfb_driver);
+ printk(KERN_DEBUG "sisfb: Module unloaded\n");
+}
+
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
@@ -5764,7 +6938,6 @@ MODULE_PARM(lvdshl, "i");
MODULE_PARM(tvstandard, "s");
MODULE_PARM(tvxposoffset, "i");
MODULE_PARM(tvyposoffset, "i");
-MODULE_PARM(filter, "i");
MODULE_PARM(nocrt2rate, "i");
MODULE_PARM(inverse, "i");
#if !defined(__i386__) && !defined(__x86_64__)
@@ -5793,7 +6966,6 @@ module_param(lvdshl, int, 0);
module_param(tvstandard, charp, 0);
module_param(tvxposoffset, int, 0);
module_param(tvyposoffset, int, 0);
-module_param(filter, int, 0);
module_param(nocrt2rate, int, 0);
#if !defined(__i386__) && !defined(__x86_64__)
module_param(resetcard, int, 0);
@@ -5801,25 +6973,35 @@ module_param(videoram, int, 0);
#endif
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mem,
"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
"for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
"on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
"the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
- "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+ "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
"The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
"for XFree86 4.x/X.org 6.7 and later.\n");
+#else
+MODULE_PARM_DESC(mem,
+ "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+ "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+ "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+ "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+ "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
+ "The value is to be specified without 'KB'.\n");
+#endif
MODULE_PARM_DESC(noaccel,
- "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+ "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
"(default: 0)\n");
MODULE_PARM_DESC(noypan,
- "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- "will be performed by redrawing the screen. (default: 0)\n");
+ "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+ "will be performed by redrawing the screen. (default: 0)\n");
MODULE_PARM_DESC(nomax,
- "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+ "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
"memory for the virtual screen in order to optimize scrolling performance. If\n"
"this is set to anything other than 0, sisfb will not do this and thereby \n"
"enable the user to positively specify a virtual Y size of the screen using\n"
@@ -5827,30 +7009,30 @@ MODULE_PARM_DESC(nomax,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mode,
- "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
- "1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+ "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+ "1024x768x16. Other formats supported include XxY-Depth and\n"
+ "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
"number, it will be interpreted as a VESA mode number. (default: none if\n"
"sisfb is a module; this leaves the console untouched and the driver will\n"
"only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
"is in the kernel)\n");
MODULE_PARM_DESC(vesa,
- "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
- "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+ "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+ "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
"and the driver will only do the video memory management for eg. DRM/DRI;\n"
"0x0103 if sisfb is in the kernel)\n");
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mode,
- "\nSelects the desired default display mode in the format XxYxDepth,\n"
- "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+ "\nSelects the desired default display mode in the format XxYxDepth,\n"
+ "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
"XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
"number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
MODULE_PARM_DESC(vesa,
- "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
- "0x117 (default: 0x0103)\n");
+ "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+ "0x117 (default: 0x0103)\n");
#endif
MODULE_PARM_DESC(rate,
@@ -5880,16 +7062,16 @@ MODULE_PARM_DESC(scalelcd,
"themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
MODULE_PARM_DESC(pdc,
- "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+ "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
"should detect this correctly in most cases; however, sometimes this is not\n"
"possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
- "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
- "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
- "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+ "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
+ "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
+ "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
#ifdef CONFIG_FB_SIS_315
MODULE_PARM_DESC(pdc1,
- "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+ "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
"series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
"startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
"implemented yet.\n");
@@ -5913,17 +7095,13 @@ MODULE_PARM_DESC(tvyposoffset,
"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
"Default: 0\n");
-MODULE_PARM_DESC(filter,
- "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
- "(Possible values 0-7, default: [no filter])\n");
-
MODULE_PARM_DESC(nocrt2rate,
"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
"CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(inverse,
- "\nSetting this to anything but 0 should invert the display colors, but this\n"
+ "\nSetting this to anything but 0 should invert the display colors, but this\n"
"does not seem to work. (default: 0)\n");
#endif
@@ -5931,98 +7109,23 @@ MODULE_PARM_DESC(inverse,
#ifdef CONFIG_FB_SIS_300
MODULE_PARM_DESC(resetcard,
"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
- "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
- "Default: 0\n");
+ "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
+ "currently). Default: 0\n");
MODULE_PARM_DESC(videoram,
"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
"some non-x86 architectures where the memory auto detection fails. Only\n"
- "relevant if resetcard is set, too. Default: [auto-detect]\n");
-#endif
+ "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
#endif
-
-static int __devinit sisfb_init_module(void)
-{
- sisfb_setdefaultparms();
-
- if(rate) sisfb_parm_rate = rate;
-
- if((scalelcd == 0) || (scalelcd == 1)) {
- sisfb_scalelcd = scalelcd ^ 1;
- }
-
- /* Need to check crt2 type first for fstn/dstn */
-
- if(forcecrt2type)
- sisfb_search_crt2type(forcecrt2type);
-
- if(tvstandard)
- sisfb_search_tvstd(tvstandard);
-
- if(mode)
- sisfb_search_mode(mode, FALSE);
- else if(vesa != -1)
- sisfb_search_vesamode(vesa, FALSE);
-
- sisfb_crt1off = (crt1off == 0) ? 1 : 0;
-
- sisfb_forcecrt1 = forcecrt1;
- if(forcecrt1 == 1) sisfb_crt1off = 0;
- else if(forcecrt1 == 0) sisfb_crt1off = 1;
-
- if(noaccel == 1) sisfb_accel = 0;
- else if(noaccel == 0) sisfb_accel = 1;
-
- if(noypan == 1) sisfb_ypan = 0;
- else if(noypan == 0) sisfb_ypan = 1;
-
- if(nomax == 1) sisfb_max = 0;
- else if(nomax == 0) sisfb_max = 1;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(inverse) sisfb_inverse = 1;
#endif
- if(mem) sisfb_parm_mem = mem;
-
- if(userom != -1) sisfb_userom = userom;
- if(useoem != -1) sisfb_useoem = useoem;
-
- if(pdc != -1) sisfb_pdc = (pdc & 0x7f);
- if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
-
- sisfb_nocrt2rate = nocrt2rate;
-
- if(specialtiming)
- sisfb_search_specialtiming(specialtiming);
-
- if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl;
-
- if(filter != -1) sisfb_filter = filter;
-
- sisfb_tvxposoffset = tvxposoffset;
- sisfb_tvyposoffset = tvyposoffset;
-
-#if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = (resetcard) ? 1 : 0;
- if(videoram) sisfb_videoram = videoram;
-#endif
-
- return(sisfb_init());
-}
-
-static void __exit sisfb_remove_module(void)
-{
- pci_unregister_driver(&sisfb_driver);
- printk(KERN_DEBUG "sisfb: Module unloaded\n");
-}
-
-module_init(sisfb_init_module);
-module_exit(sisfb_remove_module);
-
#endif /* /MODULE */
+/* _GPL only for new symbols. */
EXPORT_SYMBOL(sis_malloc);
EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL_GPL(sis_malloc_new);
+EXPORT_SYMBOL_GPL(sis_free_new);
+
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index a6678a7aff35..445bcbba03ae 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -1,9 +1,10 @@
/*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/305/540/630(S)/730(S),
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,13 +24,9 @@
#ifndef _SISFB_MAIN
#define _SISFB_MAIN
-#include <linux/spinlock.h>
-
#include "vstruct.h"
#include "sis.h"
-#define MODE_INDEX_NONE 0 /* index for mode=none */
-
/* Fbcon stuff */
static struct fb_var_screeninfo my_default_var = {
.xres = 0,
@@ -60,6 +57,8 @@ static struct fb_var_screeninfo my_default_var = {
.vmode = FB_VMODE_NONINTERLACED,
};
+#define MODE_INDEX_NONE 0 /* index for mode=none */
+
/* Boot-time parameters */
static int sisfb_off = 0;
static int sisfb_parm_mem = 0;
@@ -93,7 +92,6 @@ static int sisfb_tvplug = -1; /* Tv plug type (for overriding autodetection) */
static int sisfb_tvstd = -1;
static int sisfb_tvxposoffset = 0;
static int sisfb_tvyposoffset = 0;
-static int sisfb_filter = -1;
static int sisfb_nocrt2rate = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static int sisfb_inverse = 0;
@@ -106,12 +104,12 @@ static int sisfb_videoram = 0;
/* List of supported chips */
static struct sisfb_chip_info {
- int chip;
- int vgaengine;
+ int chip;
+ int vgaengine;
int mni;
- int hwcursor_size;
+ int hwcursor_size;
int CRT2_write_enable;
- const char *chip_name;
+ const char *chip_name;
} sisfb_chip_info[] __devinitdata = {
{ SIS_300, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
{ SIS_540, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
@@ -123,6 +121,8 @@ static struct sisfb_chip_info {
{ SIS_650, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
{ SIS_330, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
{ SIS_660, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+ { XGI_20, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI Z7" },
+ { XGI_40, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
};
static struct pci_device_id __devinitdata sisfb_pci_table[] = {
@@ -139,6 +139,8 @@ static struct pci_device_id __devinitdata sisfb_pci_table[] = {
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+ { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0,10},
+ { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0,11},
#endif
{ 0 }
};
@@ -147,13 +149,12 @@ MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
static struct sis_video_info *card_list = NULL;
-/* TODO: This is not handled card-wise because the DRM
- does not refer to a unique fb when calling sis_alloc
- or sis_free. Therefore, this is handled globally for
- now (hoping that nobody is crazy enough to run two
- SiS cards at the same time).
+/* The memory heap is now handled card-wise, by using
+ sis_malloc_new/sis_free_new. However, the DRM does
+ not do this yet. Until it does, we keep a "global"
+ heap which is actually the first card's one.
*/
-static SIS_HEAP sisfb_heap;
+static struct SIS_HEAP *sisfb_heap;
#define MD_SIS300 1
#define MD_SIS315 2
@@ -181,8 +182,10 @@ static const struct _sisbios_mode {
{"320x240x16", {0x56,0x56}, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS300|MD_SIS315},
{"320x240x24", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
{"320x240x32", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
- {"320x240x8", {0x5a,0x5a}, 0x0132, 0x0000, 320, 480, 8, 1, 40, 30, MD_SIS315}, /* FSTN */
-/*10*/ {"320x240x16", {0x5b,0x5b}, 0x0135, 0x0000, 320, 480, 16, 1, 40, 30, MD_SIS315}, /* FSTN */
+#define MODE_FSTN_8 9
+#define MODE_FSTN_16 10
+ {"320x240x8", {0x5a,0x5a}, 0x0132, 0x0000, 320, 240, 8, 1, 40, 15, MD_SIS315}, /* FSTN */
+/*10*/ {"320x240x16", {0x5b,0x5b}, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS315}, /* FSTN */
{"400x300x8", {0x51,0x51}, 0x0133, 0x0000, 400, 300, 8, 1, 50, 18, MD_SIS300|MD_SIS315},
{"400x300x16", {0x57,0x57}, 0x0136, 0x0000, 400, 300, 16, 1, 50, 18, MD_SIS300|MD_SIS315},
{"400x300x24", {0x54,0x54}, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315},
@@ -215,18 +218,20 @@ static const struct _sisbios_mode {
/*40*/ {"800x480x16", {0x7a,0x7a}, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
{"800x480x24", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
{"800x480x32", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE 43 /* index for 800x600x8 */
-#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */
-#define DEFAULT_TVMODE 43 /* index for 800x600x8 */
+#define DEFAULT_MODE 43 /* index for 800x600x8 */
+#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */
+#define DEFAULT_TVMODE 43 /* index for 800x600x8 */
{"800x600x8", {0x30,0x30}, 0x0103, 0x0103, 800, 600, 8, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x16", {0x47,0x47}, 0x0114, 0x0114, 800, 600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x24", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x32", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
{"848x480x8", {0x39,0x39}, 0x0000, 0x0000, 848, 480, 8, 2, 106, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_848 48
{"848x480x16", {0x3b,0x3b}, 0x0000, 0x0000, 848, 480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
{"848x480x24", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
/*50*/ {"848x480x32", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
{"856x480x8", {0x3f,0x3f}, 0x0000, 0x0000, 856, 480, 8, 2, 107, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_856 52
{"856x480x16", {0x42,0x42}, 0x0000, 0x0000, 856, 480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
{"856x480x24", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
{"856x480x32", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
@@ -270,42 +275,47 @@ static const struct _sisbios_mode {
{"1280x800x16", {0x15,0x15}, 0x0000, 0x0000, 1280, 800, 16, 1, 160, 50, MD_SIS315},
{"1280x800x24", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315},
{"1280x800x32", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315},
+ {"1280x854x8", {0x14,0x14}, 0x0000, 0x0000, 1280, 854, 8, 1, 160, 53, MD_SIS315},
+ {"1280x854x16", {0x15,0x15}, 0x0000, 0x0000, 1280, 854, 16, 1, 160, 53, MD_SIS315},
+ {"1280x854x24", {0x16,0x16}, 0x0000, 0x0000, 1280, 854, 32, 1, 160, 53, MD_SIS315},
+ {"1280x854x32", {0x16,0x16}, 0x0000, 0x0000, 1280, 854, 32, 1, 160, 53, MD_SIS315},
{"1280x960x8", {0x7c,0x7c}, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_SIS300|MD_SIS315},
- {"1280x960x16", {0x7d,0x7d}, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*100*/ {"1280x960x16", {0x7d,0x7d}, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x960x24", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x960x32", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x1024x8", {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024, 8, 2, 160, 64, MD_SIS300|MD_SIS315},
-/*100*/ {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+ {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1360x768x8", {0x48,0x48}, 0x0000, 0x0000, 1360, 768, 8, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x768x16", {0x4b,0x4b}, 0x0000, 0x0000, 1360, 768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x768x24", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
- {"1360x768x32", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+/*110*/ {"1360x768x32", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x1024x8", {0x67,0x67}, 0x0000, 0x0000, 1360, 1024, 8, 1, 170, 64, MD_SIS300 },
+#define DEFAULT_MODE_1360 112
{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300 },
{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
-/*110*/ {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
+ {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
{"1400x1050x8", {0x26,0x26}, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_SIS315},
{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_SIS315},
{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
{"1600x1200x8", {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_SIS300|MD_SIS315},
- {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*120*/ {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1680x1050x8", {0x17,0x17}, 0x0000, 0x0000, 1680, 1050, 8, 1, 210, 65, MD_SIS315},
-/*120*/ {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65, MD_SIS315},
+ {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65, MD_SIS315},
{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315},
{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315},
{"1920x1080x8", {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080, 8, 1, 240, 67, MD_SIS315},
{"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67, MD_SIS315},
{"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
- {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
+/*130*/ {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
{"1920x1440x8", {0x68,0x68}, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_SIS300|MD_SIS315},
{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-/*130*/ {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+ {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
{"2048x1536x8", {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_SIS315},
{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_SIS315},
{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315},
@@ -313,13 +323,13 @@ static const struct _sisbios_mode {
{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
};
-#define SIS_LCD_NUMBER 17
-static const struct _sis_lcd_data {
+#define SIS_LCD_NUMBER 18
+static struct _sis_lcd_data {
u32 lcdtype;
u16 xres;
u16 yres;
u8 default_mode_idx;
-} sis_lcd_data[] = {
+} sis_lcd_data[] __devinitdata = {
{ LCD_640x480, 640, 480, 23 },
{ LCD_800x600, 800, 600, 43 },
{ LCD_1024x600, 1024, 600, 67 },
@@ -329,34 +339,38 @@ static const struct _sis_lcd_data {
{ LCD_1280x720, 1280, 720, 83 },
{ LCD_1280x768, 1280, 768, 87 },
{ LCD_1280x800, 1280, 800, 91 },
- { LCD_1280x960, 1280, 960, 95 },
- { LCD_1280x1024, 1280, 1024, 99 },
- { LCD_1400x1050, 1400, 1050, 111 },
- { LCD_1680x1050, 1680, 1050, 119 },
- { LCD_1600x1200, 1600, 1200, 115 },
- { LCD_640x480_2, 640, 480, 23 },
- { LCD_640x480_3, 640, 480, 23 },
- { LCD_320x480, 320, 480, 9 },
+ { LCD_1280x854, 1280, 854, 95 },
+ { LCD_1280x960, 1280, 960, 99 },
+ { LCD_1280x1024, 1280, 1024, 103 },
+ { LCD_1400x1050, 1400, 1050, 115 },
+ { LCD_1680x1050, 1680, 1050, 123 },
+ { LCD_1600x1200, 1600, 1200, 119 },
+ { LCD_320x240_2, 320, 240, 9 },
+ { LCD_320x240_3, 320, 240, 9 },
+ { LCD_320x240, 320, 240, 9 },
};
/* CR36 evaluation */
-static const USHORT sis300paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
- LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN,
- LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN };
-
-static const USHORT sis310paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
- LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
- LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN, LCD_UNKNOWN };
-
-static const USHORT sis661paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
- LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
- LCD_1280x800, LCD_1680x1050, LCD_1280x720, LCD_UNKNOWN };
+static unsigned short sis300paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
+ LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN,
+ LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN
+};
+
+static unsigned short sis310paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+ LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
+ LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN, LCD_UNKNOWN
+};
+
+static unsigned short sis661paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+ LCD_1280x854, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
+ LCD_1280x800, LCD_1680x1050, LCD_1280x720, LCD_UNKNOWN
+};
#define FL_550_DSTN 0x01
#define FL_550_FSTN 0x02
@@ -413,7 +427,6 @@ static const struct _sis_vrate {
} sisfb_vrate[] = {
{1, 320, 200, 70, TRUE},
{1, 320, 240, 60, TRUE},
- {1, 320, 480, 60, TRUE},
{1, 400, 300, 60, TRUE},
{1, 512, 384, 60, TRUE},
{1, 640, 400, 72, TRUE},
@@ -437,10 +450,11 @@ static const struct _sis_vrate {
{4, 1024, 768, 75, FALSE}, {5, 1024, 768, 85, TRUE}, {6, 1024, 768, 100, TRUE},
{7, 1024, 768, 120, TRUE},
{1, 1152, 768, 60, TRUE},
- {1, 1152, 864, 60, TRUE}, {1, 1152, 864, 75, TRUE}, {2, 1152, 864, 84, TRUE},
+ {1, 1152, 864, 60, TRUE}, {2, 1152, 864, 75, TRUE}, {3, 1152, 864, 84, TRUE},
{1, 1280, 720, 60, TRUE}, {2, 1280, 720, 75, TRUE}, {3, 1280, 720, 85, TRUE},
{1, 1280, 768, 60, TRUE},
{1, 1280, 800, 60, TRUE},
+ {1, 1280, 854, 60, TRUE},
{1, 1280, 960, 60, TRUE}, {2, 1280, 960, 85, TRUE},
{1, 1280, 1024, 43, TRUE}, {2, 1280, 1024, 60, TRUE}, {3, 1280, 1024, 75, TRUE},
{4, 1280, 1024, 85, TRUE},
@@ -459,12 +473,12 @@ static const struct _sis_vrate {
{0, 0, 0, 0, FALSE}
};
-static const struct _sisfbddcsmodes {
+static struct _sisfbddcsmodes {
u32 mask;
u16 h;
u16 v;
u32 d;
-} sisfb_ddcsmodes[] = {
+} sisfb_ddcsmodes[] __devinitdata = {
{ 0x10000, 67, 75, 108000},
{ 0x08000, 48, 72, 50000},
{ 0x04000, 46, 75, 49500},
@@ -480,49 +494,49 @@ static const struct _sisfbddcsmodes {
{ 0x00001, 38, 60, 40000}
};
-static const struct _sisfbddcfmodes {
+static struct _sisfbddcfmodes {
u16 x;
u16 y;
u16 v;
u16 h;
u32 d;
-} sisfb_ddcfmodes[] = {
- { 1280, 1024, 85, 92, 157500},
- { 1600, 1200, 60, 75, 162000},
- { 1600, 1200, 65, 82, 175500},
- { 1600, 1200, 70, 88, 189000},
- { 1600, 1200, 75, 94, 202500},
- { 1600, 1200, 85, 107,229500},
- { 1920, 1440, 60, 90, 234000},
- { 1920, 1440, 75, 113,297000}
+} sisfb_ddcfmodes[] __devinitdata = {
+ { 1280, 1024, 85, 92, 157500},
+ { 1600, 1200, 60, 75, 162000},
+ { 1600, 1200, 65, 82, 175500},
+ { 1600, 1200, 70, 88, 189000},
+ { 1600, 1200, 75, 94, 202500},
+ { 1600, 1200, 85, 107,229500},
+ { 1920, 1440, 60, 90, 234000},
+ { 1920, 1440, 75, 113,297000}
};
#ifdef CONFIG_FB_SIS_300
static struct _chswtable {
- u16 subsysVendor;
- u16 subsysCard;
- char *vendorName;
- char *cardName;
+ u16 subsysVendor;
+ u16 subsysCard;
+ char *vendorName;
+ char *cardName;
} mychswtable[] __devinitdata = {
- { 0x1631, 0x1002, "Mitachi", "0x1002" },
+ { 0x1631, 0x1002, "Mitachi", "0x1002" },
{ 0x1071, 0x7521, "Mitac" , "7521P" },
{ 0, 0, "" , "" }
};
#endif
static struct _customttable {
- u16 chipID;
- char *biosversion;
- char *biosdate;
- u32 bioschksum;
- u16 biosFootprintAddr[5];
- u8 biosFootprintData[5];
- u16 pcisubsysvendor;
- u16 pcisubsyscard;
- char *vendorName;
- char *cardName;
- u32 SpecialID;
- char *optionName;
+ u16 chipID;
+ char *biosversion;
+ char *biosdate;
+ u32 bioschksum;
+ u16 biosFootprintAddr[5];
+ u8 biosFootprintData[5];
+ u16 pcisubsysvendor;
+ u16 pcisubsyscard;
+ char *vendorName;
+ char *cardName;
+ u32 SpecialID;
+ char *optionName;
} mycustomttable[] __devinitdata = {
{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
0x3240A8,
@@ -643,6 +657,13 @@ static struct _customttable {
0, 0,
"Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
},
+ { 4322, "", "", /* never autodetected */
+ 0,
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ 0, 0,
+ "Generic", "LVDS/Parallel 856x480", CUT_PANEL856, "PANEL856x480"
+ },
{ 0, "", "",
0,
{ 0, 0, 0, 0 },
@@ -652,155 +673,6 @@ static struct _customttable {
}
};
-static const struct _sis_TV_filter {
- u8 filter[9][4];
-} sis_TV_filter[] = {
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xEB,0x04,0x25,0x18},
- {0xF1,0x05,0x1F,0x16},
- {0xF6,0x06,0x1A,0x14},
- {0xFA,0x06,0x16,0x14},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */
- {0xF1,0x04,0x1F,0x18},
- {0xEE,0x0D,0x22,0x06},
- {0xF7,0x06,0x19,0x14},
- {0xF4,0x0B,0x1C,0x0A},
- {0xFA,0x07,0x16,0x12},
- {0xF9,0x0A,0x17,0x0C},
- {0x00,0x07,0x10,0x12},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 - 320 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 - 640 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xEB,0x04,0x25,0x18},
- {0xF1,0x05,0x1F,0x16},
- {0xF6,0x06,0x1A,0x14},
- {0xFA,0x06,0x16,0x14},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 - 720 */
- {0xEB,0x04,0x25,0x18},
- {0xE7,0x0E,0x29,0x04},
- {0xEE,0x0C,0x22,0x08},
- {0xF6,0x0B,0x1A,0x0A},
- {0xF9,0x0A,0x17,0x0C},
- {0xFC,0x0A,0x14,0x0C},
- {0x00,0x08,0x10,0x10},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 - 800 */
- {0xEC,0x02,0x24,0x1C},
- {0xF2,0x04,0x1E,0x18},
- {0xEB,0x15,0x25,0xF6},
- {0xF4,0x10,0x1C,0x00},
- {0xF8,0x0F,0x18,0x02},
- {0x00,0x04,0x10,0x18},
- {0x01,0x06,0x0F,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xF1,0xF7,0x01,0x32},
- {0xF5,0xFB,0x1B,0x2A},
- {0xF9,0xFF,0x17,0x22},
- {0xFB,0x01,0x15,0x1E},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */
- {0xF5,0xFB,0x1B,0x2A},
- {0xEE,0xFE,0x22,0x24},
- {0xF3,0x00,0x1D,0x20},
- {0xF9,0x03,0x17,0x1A},
- {0xFB,0x02,0x14,0x1E},
- {0xFB,0x04,0x15,0x18},
- {0x00,0x06,0x10,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 - 320 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 - 640 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xF1,0xF7,0x1F,0x32},
- {0xF5,0xFB,0x1B,0x2A},
- {0xF9,0xFF,0x17,0x22},
- {0xFB,0x01,0x15,0x1E},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 - 720 */
- {0xF5,0xEE,0x1B,0x2A},
- {0xEE,0xFE,0x22,0x24},
- {0xF3,0x00,0x1D,0x20},
- {0xF9,0x03,0x17,0x1A},
- {0xFB,0x02,0x14,0x1E},
- {0xFB,0x04,0x15,0x18},
- {0x00,0x06,0x10,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 - 800 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0xEB,0x05,0x25,0x16},
- {0xF1,0x05,0x1F,0x16},
- {0xFA,0x07,0x16,0x12},
- {0x00,0x07,0x10,0x12},
- {0xFF,0xFF,0xFF,0xFF} }}
-};
-
/* ---------------------- Prototypes ------------------------- */
/* Interface used by the world */
@@ -811,145 +683,159 @@ SISINITSTATIC int sisfb_setup(char *options);
/* Interface to the low level console driver */
SISINITSTATIC int sisfb_init(void);
-
/* fbdev routines */
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix,
- int con,
- struct fb_info *info);
-static int sisfb_get_var(struct fb_var_screeninfo *var,
- int con,
- struct fb_info *info);
-static int sisfb_set_var(struct fb_var_screeninfo *var,
- int con,
- struct fb_info *info);
-static void sisfb_crtc_to_var(struct sis_video_info *ivideo,
- struct fb_var_screeninfo *var);
-static int sisfb_get_cmap(struct fb_cmap *cmap,
- int kspc,
- int con,
- struct fb_info *info);
-static int sisfb_set_cmap(struct fb_cmap *cmap,
- int kspc,
- int con,
- struct fb_info *info);
-static int sisfb_update_var(int con,
- struct fb_info *info);
-static int sisfb_switch(int con,
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix,
+ int con,
+ struct fb_info *info);
+static int sisfb_get_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static int sisfb_set_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static void sisfb_crtc_to_var(struct sis_video_info *ivideo,
+ struct fb_var_screeninfo *var);
+static int sisfb_get_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int sisfb_set_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int sisfb_update_var(int con,
+ struct fb_info *info);
+static int sisfb_switch(int con,
struct fb_info *info);
-static void sisfb_blank(int blank,
- struct fb_info *info);
-static void sisfb_set_disp(int con,
- struct fb_var_screeninfo *var,
- struct fb_info *info);
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *fb_info);
-static void sisfb_do_install_cmap(int con,
- struct fb_info *info);
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info);
-#endif
+static void sisfb_blank(int blank,
+ struct fb_info *info);
+static void sisfb_set_disp(int con,
+ struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *fb_info);
+static void sisfb_do_install_cmap(int con,
+ struct fb_info *info);
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
-static int sisfb_set_par(struct fb_info *info);
-static int sisfb_blank(int blank,
- struct fb_info *info);
-extern void fbcon_sis_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect);
-extern void fbcon_sis_copyarea(struct fb_info *info,
- const struct fb_copyarea *area);
-extern int fbcon_sis_sync(struct fb_info *info);
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info);
+static int sisfb_set_par(struct fb_info *info);
+static int sisfb_blank(int blank,
+ struct fb_info *info);
+extern void fbcon_sis_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect);
+extern void fbcon_sis_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+extern int fbcon_sis_sync(struct fb_info *info);
#endif
-
+
/* Internal 2D accelerator functions */
-extern int sisfb_initaccel(struct sis_video_info *ivideo);
-extern void sisfb_syncaccel(struct sis_video_info *ivideo);
+extern int sisfb_initaccel(struct sis_video_info *ivideo);
+extern void sisfb_syncaccel(struct sis_video_info *ivideo);
/* Internal general routines */
-static void sisfb_search_mode(char *name, BOOLEAN quiet);
-static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
-static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
- int index);
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info);
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info);
-static void sisfb_pre_setmode(struct sis_video_info *ivideo);
-static void sisfb_post_setmode(struct sis_video_info *ivideo);
-static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo);
-static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
-static void sisfb_get_VB_type(struct sis_video_info *ivideo);
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+static void sisfb_search_mode(char *name, BOOLEAN quiet);
+static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+ int index);
+static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static void sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void sisfb_post_setmode(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+#ifdef CONFIG_FB_SIS_300
+unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
+unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+#ifdef CONFIG_FB_SIS_315
+void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
+unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
/* SiS-specific exported functions */
-void sis_malloc(struct sis_memreq *req);
-void sis_free(u32 base);
+void sis_malloc(struct sis_memreq *req);
+void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+void sis_free(u32 base);
+void sis_free_new(struct pci_dev *pdev, u32 base);
/* Internal heap routines */
-static int sisfb_heap_init(struct sis_video_info *ivideo);
-static SIS_OH *sisfb_poh_new_node(void);
-static SIS_OH *sisfb_poh_allocate(u32 size);
-static void sisfb_delete_node(SIS_OH *poh);
-static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH *sisfb_poh_free(u32 base);
-static void sisfb_free_node(SIS_OH *poh);
-
-/* Sensing routines */
-static void SiS_Sense30x(struct sis_video_info *ivideo);
-static void SiS_SenseCh(struct sis_video_info *ivideo);
+static int sisfb_heap_init(struct sis_video_info *ivideo);
+static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
+static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
+static void sisfb_delete_node(struct SIS_OH *poh);
+static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
+static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
+static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
/* Routines from init.c/init301.c */
-extern USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth,
- BOOLEAN FSTN, USHORT CustomT, int LCDwith, int LCDheight);
-extern USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-extern USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-extern void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo, USHORT ModeNo);
-extern void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-extern void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-
-extern BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-
-extern BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+extern unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, BOOLEAN FSTN, unsigned short CustomT,
+ int LCDwith, int LCDheight, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+extern BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+extern void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+
+extern BOOLEAN SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+extern BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ int *htotal, int *vtotal, unsigned char rateindex);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-extern int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr,
- PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, unsigned char rateindex);
-extern int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, unsigned char rateindex,
- struct fb_var_screeninfo *var);
+extern int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+ unsigned char modeno, unsigned char rateindex);
+extern int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
#endif
/* Chrontel TV, DDC and DPMS functions */
-extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
-extern void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-extern void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-extern USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
-extern USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-extern void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
-extern void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
+extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char myor, unsigned char myand);
+extern void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+extern void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
+extern unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+ unsigned int VBFlags2);
+extern unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+#ifdef CONFIG_FB_SIS_315
+extern void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+extern void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
+#endif
+extern void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+extern void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
#endif
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index 507bba1a71b5..831b9f42264b 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -3,7 +3,7 @@
/*
* General type definitions for universal mode switching modules
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,11 +50,10 @@
*
*/
-#ifndef _VGATYPES_
-#define _VGATYPES_
+#ifndef _VGATYPES_H_
+#define _VGATYPES_H_
-#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */
-#include <linux/ioctl.h>
+#ifdef SIS_LINUX_KERNEL
#include <linux/version.h>
#endif
@@ -66,41 +65,13 @@
#define TRUE 1
#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CHAR
-typedef char CHAR;
-#endif
-
-#ifndef SHORT
-typedef short SHORT;
-#endif
-
-#ifndef LONG
-typedef long LONG;
-#endif
-
-#ifndef UCHAR
-typedef unsigned char UCHAR;
-#endif
-
-#ifndef USHORT
-typedef unsigned short USHORT;
-#endif
-
-#ifndef ULONG
-typedef unsigned long ULONG;
-#endif
-
#ifndef BOOLEAN
-typedef unsigned char BOOLEAN;
+typedef unsigned int BOOLEAN;
#endif
#define SISIOMEMTYPE
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
typedef unsigned long SISIOADDRESS;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
#include <linux/types.h> /* Need __iomem */
@@ -109,7 +80,7 @@ typedef unsigned long SISIOADDRESS;
#endif
#endif
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
typedef unsigned long IOADDRESS;
typedef unsigned long SISIOADDRESS;
@@ -118,7 +89,7 @@ typedef IOADDRESS SISIOADDRESS;
#endif
#endif
-enum _SIS_CHIP_TYPE {
+typedef enum _SIS_CHIP_TYPE {
SIS_VGALegacy = 0,
SIS_530,
SIS_OLD,
@@ -128,115 +99,27 @@ enum _SIS_CHIP_TYPE {
SIS_540,
SIS_315H, /* SiS 310 */
SIS_315,
- SIS_315PRO,
+ SIS_315PRO, /* SiS 325 */
SIS_550,
SIS_650,
SIS_740,
SIS_330,
SIS_661,
SIS_741,
- SIS_660,
+ SIS_670,
+ SIS_660 = 35,
SIS_760,
SIS_761,
- SIS_340,
+ SIS_762,
+ SIS_770,
+ SIS_340 = 55,
+ SIS_341,
+ SIS_342,
+ XGI_20 = 75,
+ XGI_40,
MAX_SIS_CHIP
-};
-
-#ifndef SIS_HW_INFO
-typedef struct _SIS_HW_INFO SIS_HW_INFO, *PSIS_HW_INFO;
-
-struct _SIS_HW_INFO
-{
-#ifdef LINUX_XF86
- PCITAG PciTag; /* PCI Tag */
-#endif
-
- UCHAR *pjVirtualRomBase; /* ROM image */
-
- BOOLEAN UseROM; /* Use the ROM image if provided */
-
-#ifdef LINUX_KERNEL
- UCHAR SISIOMEMTYPE *pjVideoMemoryAddress;
- /* base virtual memory address */
- /* of Linear VGA memory */
-
- ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */
-#endif
-
- SISIOADDRESS ulIOAddress; /* base I/O address of VGA ports (0x3B0; relocated) */
-
- UCHAR jChipType; /* Used to Identify SiS Graphics Chip */
- /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
+} SIS_CHIP_TYPE;
- UCHAR jChipRevision; /* Used to Identify SiS Graphics Chip Revision */
-
- BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-};
-#endif
-
-/* Addtional IOCTLs for communication sisfb <> X driver */
-/* If changing this, sisfb.h must also be changed (for sisfb) */
-
-#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */
-
-/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_SIZE 0x8004f300
-#define SISFB_GET_INFO 0x8000f301 /* Must be patched with result from ..._SIZE at D[29:16] */
-/* deprecated ioctl number (for older versions of sisfb) */
-#define SISFB_GET_INFO_OLD 0x80046ef8
-
-/* ioctls for tv parameters (position) */
-#define SISFB_SET_TVPOSOFFSET 0x4004f304
-
-/* lock sisfb from register access */
-#define SISFB_SET_LOCK 0x4004f306
-
-/* Structure argument for SISFB_GET_INFO ioctl */
-typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
-
-struct _SISFB_INFO {
- CARD32 sisfb_id; /* for identifying sisfb */
-#ifndef SISFB_ID
-#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */
-#endif
- CARD32 chip_id; /* PCI ID of detected chip */
- CARD32 memory; /* video memory in KB which sisfb manages */
- CARD32 heapstart; /* heap start (= sisfb "mem" argument) in KB */
- CARD8 fbvidmode; /* current sisfb mode */
-
- CARD8 sisfb_version;
- CARD8 sisfb_revision;
- CARD8 sisfb_patchlevel;
-
- CARD8 sisfb_caps; /* sisfb's capabilities */
-
- CARD32 sisfb_tqlen; /* turbo queue length (in KB) */
-
- CARD32 sisfb_pcibus; /* The card's PCI ID */
- CARD32 sisfb_pcislot;
- CARD32 sisfb_pcifunc;
-
- CARD8 sisfb_lcdpdc;
-
- CARD8 sisfb_lcda;
-
- CARD32 sisfb_vbflags;
- CARD32 sisfb_currentvbflags;
-
- CARD32 sisfb_scalelcd;
- CARD32 sisfb_specialtiming;
-
- CARD8 sisfb_haveemi;
- CARD8 sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
- CARD8 sisfb_haveemilcd;
-
- CARD8 sisfb_lcdpdca;
-
- CARD16 sisfb_tvxpos, sisfb_tvypos; /* Warning: Values + 32 ! */
-
- CARD8 reserved[208]; /* for future use */
-};
-#endif
#endif
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index d4d55c98bce6..9ae32923c142 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -3,7 +3,7 @@
/*
* General structure definitions for universal mode switching modules
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,627 +50,514 @@
*
*/
-#ifndef _VSTRUCT_
-#define _VSTRUCT_
-
-typedef struct _SiS_PanelDelayTblStruct
-{
- UCHAR timer[2];
-} SiS_PanelDelayTblStruct;
-
-typedef struct _SiS_LCDDataStruct
-{
- USHORT RVBHCMAX;
- USHORT RVBHCFACT;
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT LCDHT;
- USHORT LCDVT;
-} SiS_LCDDataStruct;
-
-typedef struct _SiS_TVDataStruct
-{
- USHORT RVBHCMAX;
- USHORT RVBHCFACT;
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT TVHDE;
- USHORT TVVDE;
- USHORT RVBHRS;
- UCHAR FlickerMode;
- USHORT HALFRVBHRS;
- UCHAR RY1COE;
- UCHAR RY2COE;
- UCHAR RY3COE;
- UCHAR RY4COE;
-} SiS_TVDataStruct;
-
-typedef struct _SiS_LVDSDataStruct
-{
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT LCDHT;
- USHORT LCDVT;
-} SiS_LVDSDataStruct;
-
-typedef struct _SiS_LVDSDesStruct
-{
- USHORT LCDHDES;
- USHORT LCDVDES;
-} SiS_LVDSDesStruct;
-
-typedef struct _SiS_LVDSCRT1DataStruct
-{
- UCHAR CR[15];
-} SiS_LVDSCRT1DataStruct;
-
-typedef struct _SiS_LCDACRT1DataStruct
-{
- UCHAR CR[17];
-} SiS_LCDACRT1DataStruct;
-
-typedef struct _SiS_CHTVRegDataStruct
-{
- UCHAR Reg[16];
-} SiS_CHTVRegDataStruct;
-
-typedef struct _SiS_StStruct
-{
- UCHAR St_ModeID;
- USHORT St_ModeFlag;
- UCHAR St_StTableIndex;
- UCHAR St_CRT2CRTC;
- UCHAR St_ResInfo;
- UCHAR VB_StTVFlickerIndex;
- UCHAR VB_StTVEdgeIndex;
- UCHAR VB_StTVYFilterIndex;
- UCHAR St_PDC;
-} SiS_StStruct;
-
-typedef struct _SiS_VBModeStruct
-{
- UCHAR ModeID;
- UCHAR VB_TVDelayIndex;
- UCHAR VB_TVFlickerIndex;
- UCHAR VB_TVPhaseIndex;
- UCHAR VB_TVYFilterIndex;
- UCHAR VB_LCDDelayIndex;
- UCHAR _VB_LCDHIndex;
- UCHAR _VB_LCDVIndex;
-} SiS_VBModeStruct;
-
-typedef struct _SiS_StandTableStruct
-{
- UCHAR CRT_COLS;
- UCHAR ROWS;
- UCHAR CHAR_HEIGHT;
- USHORT CRT_LEN;
- UCHAR SR[4];
- UCHAR MISC;
- UCHAR CRTC[0x19];
- UCHAR ATTR[0x14];
- UCHAR GRC[9];
-} SiS_StandTableStruct;
-
-typedef struct _SiS_ExtStruct
-{
- UCHAR Ext_ModeID;
- USHORT Ext_ModeFlag;
- USHORT Ext_VESAID;
- UCHAR Ext_RESINFO;
- UCHAR VB_ExtTVFlickerIndex;
- UCHAR VB_ExtTVEdgeIndex;
- UCHAR VB_ExtTVYFilterIndex;
- UCHAR VB_ExtTVYFilterIndexROM661;
- UCHAR REFindex;
- CHAR ROMMODEIDX661;
-} SiS_ExtStruct;
-
-typedef struct _SiS_Ext2Struct
-{
- USHORT Ext_InfoFlag;
- UCHAR Ext_CRT1CRTC;
- UCHAR Ext_CRTVCLK;
- UCHAR Ext_CRT2CRTC;
- UCHAR Ext_CRT2CRTC_NS;
- UCHAR ModeID;
- USHORT XRes;
- USHORT YRes;
- UCHAR Ext_PDC;
-} SiS_Ext2Struct;
-
-typedef struct _SiS_Part2PortTblStruct
-{
- UCHAR CR[12];
-} SiS_Part2PortTblStruct;
-
-typedef struct _SiS_CRT1TableStruct
-{
- UCHAR CR[17];
-} SiS_CRT1TableStruct;
-
-typedef struct _SiS_MCLKDataStruct
-{
- UCHAR SR28,SR29,SR2A;
- USHORT CLOCK;
-} SiS_MCLKDataStruct;
-
-typedef struct _SiS_VCLKDataStruct
-{
- UCHAR SR2B,SR2C;
- USHORT CLOCK;
-} SiS_VCLKDataStruct;
-
-typedef struct _SiS_VBVCLKDataStruct
-{
- UCHAR Part4_A,Part4_B;
- USHORT CLOCK;
-} SiS_VBVCLKDataStruct;
-
-typedef struct _SiS_StResInfoStruct
-{
- USHORT HTotal;
- USHORT VTotal;
-} SiS_StResInfoStruct;
-
-typedef struct _SiS_ModeResInfoStruct
-{
- USHORT HTotal;
- USHORT VTotal;
- UCHAR XChar;
- UCHAR YChar;
-} SiS_ModeResInfoStruct;
-
-
-
-typedef UCHAR DRAM4Type[4];
+#ifndef _VSTRUCT_H_
+#define _VSTRUCT_H_
+
+struct SiS_PanelDelayTbl {
+ unsigned char timer[2];
+};
+
+struct SiS_LCDData {
+ unsigned short RVBHCMAX;
+ unsigned short RVBHCFACT;
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short LCDHT;
+ unsigned short LCDVT;
+};
+
+struct SiS_TVData {
+ unsigned short RVBHCMAX;
+ unsigned short RVBHCFACT;
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short TVHDE;
+ unsigned short TVVDE;
+ unsigned short RVBHRS;
+ unsigned char FlickerMode;
+ unsigned short HALFRVBHRS;
+ unsigned short RVBHRS2;
+ unsigned char RY1COE;
+ unsigned char RY2COE;
+ unsigned char RY3COE;
+ unsigned char RY4COE;
+};
+
+struct SiS_LVDSData {
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short LCDHT;
+ unsigned short LCDVT;
+};
+
+struct SiS_LVDSDes {
+ unsigned short LCDHDES;
+ unsigned short LCDVDES;
+};
+
+struct SiS_LVDSCRT1Data {
+ unsigned char CR[15];
+};
+
+struct SiS_CHTVRegData {
+ unsigned char Reg[16];
+};
+
+struct SiS_St {
+ unsigned char St_ModeID;
+ unsigned short St_ModeFlag;
+ unsigned char St_StTableIndex;
+ unsigned char St_CRT2CRTC;
+ unsigned char St_ResInfo;
+ unsigned char VB_StTVFlickerIndex;
+ unsigned char VB_StTVEdgeIndex;
+ unsigned char VB_StTVYFilterIndex;
+ unsigned char St_PDC;
+};
+
+struct SiS_VBMode {
+ unsigned char ModeID;
+ unsigned char VB_TVDelayIndex;
+ unsigned char VB_TVFlickerIndex;
+ unsigned char VB_TVPhaseIndex;
+ unsigned char VB_TVYFilterIndex;
+ unsigned char VB_LCDDelayIndex;
+ unsigned char _VB_LCDHIndex;
+ unsigned char _VB_LCDVIndex;
+};
+
+struct SiS_StandTable_S {
+ unsigned char CRT_COLS;
+ unsigned char ROWS;
+ unsigned char CHAR_HEIGHT;
+ unsigned short CRT_LEN;
+ unsigned char SR[4];
+ unsigned char MISC;
+ unsigned char CRTC[0x19];
+ unsigned char ATTR[0x14];
+ unsigned char GRC[9];
+};
+
+struct SiS_Ext {
+ unsigned char Ext_ModeID;
+ unsigned short Ext_ModeFlag;
+ unsigned short Ext_VESAID;
+ unsigned char Ext_RESINFO;
+ unsigned char VB_ExtTVFlickerIndex;
+ unsigned char VB_ExtTVEdgeIndex;
+ unsigned char VB_ExtTVYFilterIndex;
+ unsigned char VB_ExtTVYFilterIndexROM661;
+ unsigned char REFindex;
+ char ROMMODEIDX661;
+};
+
+struct SiS_Ext2 {
+ unsigned short Ext_InfoFlag;
+ unsigned char Ext_CRT1CRTC;
+ unsigned char Ext_CRTVCLK;
+ unsigned char Ext_CRT2CRTC;
+ unsigned char Ext_CRT2CRTC_NS;
+ unsigned char ModeID;
+ unsigned short XRes;
+ unsigned short YRes;
+ unsigned char Ext_PDC;
+ unsigned char Ext_FakeCRT2CRTC;
+ unsigned char Ext_FakeCRT2Clk;
+ unsigned char Ext_CRT1CRTC_NORM;
+ unsigned char Ext_CRTVCLK_NORM;
+ unsigned char Ext_CRT1CRTC_WIDE;
+ unsigned char Ext_CRTVCLK_WIDE;
+};
+
+struct SiS_Part2PortTbl {
+ unsigned char CR[12];
+};
+
+struct SiS_CRT1Table {
+ unsigned char CR[17];
+};
+
+struct SiS_MCLKData {
+ unsigned char SR28,SR29,SR2A;
+ unsigned short CLOCK;
+};
+
+struct SiS_VCLKData {
+ unsigned char SR2B,SR2C;
+ unsigned short CLOCK;
+};
+
+struct SiS_VBVCLKData {
+ unsigned char Part4_A,Part4_B;
+ unsigned short CLOCK;
+};
+
+struct SiS_StResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+};
+
+struct SiS_ModeResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+ unsigned char XChar;
+ unsigned char YChar;
+};
/* Defines for SiS_CustomT */
/* Never change these for sisfb compatibility */
-#define CUT_NONE 0
-#define CUT_FORCENONE 1
-#define CUT_BARCO1366 2
-#define CUT_BARCO1024 3
-#define CUT_COMPAQ1280 4
-#define CUT_COMPAQ12802 5
-#define CUT_PANEL848 6
-#define CUT_CLEVO1024 7
-#define CUT_CLEVO10242 8
-#define CUT_CLEVO1400 9
-#define CUT_CLEVO14002 10
-#define CUT_UNIWILL1024 11
-#define CUT_ASUSL3000D 12
-#define CUT_UNIWILL10242 13
-#define CUT_ACER1280 14
-#define CUT_COMPAL1400_1 15
-#define CUT_COMPAL1400_2 16
-#define CUT_ASUSA2H_1 17
-#define CUT_ASUSA2H_2 18
-
-typedef struct _SiS_Private
+#define CUT_NONE 0
+#define CUT_FORCENONE 1
+#define CUT_BARCO1366 2
+#define CUT_BARCO1024 3
+#define CUT_COMPAQ1280 4
+#define CUT_COMPAQ12802 5
+#define CUT_PANEL848 6
+#define CUT_CLEVO1024 7
+#define CUT_CLEVO10242 8
+#define CUT_CLEVO1400 9
+#define CUT_CLEVO14002 10
+#define CUT_UNIWILL1024 11
+#define CUT_ASUSL3000D 12
+#define CUT_UNIWILL10242 13
+#define CUT_ACER1280 14
+#define CUT_COMPAL1400_1 15
+#define CUT_COMPAL1400_2 16
+#define CUT_ASUSA2H_1 17
+#define CUT_ASUSA2H_2 18
+#define CUT_UNKNOWNLCD 19
+#define CUT_AOP8060 20
+#define CUT_PANEL856 21
+
+struct SiS_Private
{
-#ifdef LINUX_KERNEL
- SISIOADDRESS RelIO;
+ unsigned char ChipType;
+ unsigned char ChipRevision;
+#ifdef SIS_XORG_XF86
+ PCITAG PciTag;
#endif
- SISIOADDRESS SiS_P3c4;
- SISIOADDRESS SiS_P3d4;
- SISIOADDRESS SiS_P3c0;
- SISIOADDRESS SiS_P3ce;
- SISIOADDRESS SiS_P3c2;
- SISIOADDRESS SiS_P3ca;
- SISIOADDRESS SiS_P3c6;
- SISIOADDRESS SiS_P3c7;
- SISIOADDRESS SiS_P3c8;
- SISIOADDRESS SiS_P3c9;
- SISIOADDRESS SiS_P3cb;
- SISIOADDRESS SiS_P3cd;
- SISIOADDRESS SiS_P3da;
- SISIOADDRESS SiS_Part1Port;
- SISIOADDRESS SiS_Part2Port;
- SISIOADDRESS SiS_Part3Port;
- SISIOADDRESS SiS_Part4Port;
- SISIOADDRESS SiS_Part5Port;
- SISIOADDRESS SiS_VidCapt;
- SISIOADDRESS SiS_VidPlay;
- USHORT SiS_IF_DEF_LVDS;
- USHORT SiS_IF_DEF_CH70xx;
- USHORT SiS_IF_DEF_CONEX;
- USHORT SiS_IF_DEF_TRUMPION;
- USHORT SiS_IF_DEF_DSTN;
- USHORT SiS_IF_DEF_FSTN;
- USHORT SiS_SysFlags;
- UCHAR SiS_VGAINFO;
-#ifdef LINUX_XF86
- USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#ifdef SIS_LINUX_KERNEL
+ void *ivideo;
#endif
- BOOLEAN SiS_UseROM;
- BOOLEAN SiS_ROMNew;
- BOOLEAN SiS_NeedRomModeData;
- BOOLEAN PanelSelfDetected;
- int SiS_CHOverScan;
- BOOLEAN SiS_CHSOverScan;
- BOOLEAN SiS_ChSW;
- BOOLEAN SiS_UseLCDA;
- int SiS_UseOEM;
- ULONG SiS_CustomT;
- USHORT SiS_Backup70xx;
- BOOLEAN HaveEMI;
- BOOLEAN HaveEMILCD;
- BOOLEAN OverruleEMI;
- UCHAR EMI_30,EMI_31,EMI_32,EMI_33;
- USHORT SiS_EMIOffset;
- SHORT PDC, PDCA;
- UCHAR SiS_MyCR63;
- USHORT SiS_CRT1Mode;
- USHORT SiS_flag_clearbuffer;
- int SiS_RAMType;
- UCHAR SiS_ChannelAB;
- UCHAR SiS_DataBusWidth;
- USHORT SiS_ModeType;
- USHORT SiS_VBInfo;
- USHORT SiS_TVMode;
- USHORT SiS_LCDResInfo;
- USHORT SiS_LCDTypeInfo;
- USHORT SiS_LCDInfo;
- USHORT SiS_LCDInfo661;
- USHORT SiS_VBType;
- USHORT SiS_VBExtInfo;
- USHORT SiS_YPbPr;
- USHORT SiS_SelectCRT2Rate;
- USHORT SiS_SetFlag;
- USHORT SiS_RVBHCFACT;
- USHORT SiS_RVBHCMAX;
- USHORT SiS_RVBHRS;
- USHORT SiS_VGAVT;
- USHORT SiS_VGAHT;
- USHORT SiS_VT;
- USHORT SiS_HT;
- USHORT SiS_VGAVDE;
- USHORT SiS_VGAHDE;
- USHORT SiS_VDE;
- USHORT SiS_HDE;
- USHORT SiS_NewFlickerMode;
- USHORT SiS_RY1COE;
- USHORT SiS_RY2COE;
- USHORT SiS_RY3COE;
- USHORT SiS_RY4COE;
- USHORT SiS_LCDHDES;
- USHORT SiS_LCDVDES;
- USHORT SiS_DDC_Port;
- USHORT SiS_DDC_Index;
- USHORT SiS_DDC_Data;
- USHORT SiS_DDC_NData;
- USHORT SiS_DDC_Clk;
- USHORT SiS_DDC_NClk;
- USHORT SiS_DDC_DeviceAddr;
- USHORT SiS_DDC_ReadAddr;
- USHORT SiS_DDC_SecAddr;
- USHORT SiS_ChrontelInit;
- BOOLEAN SiS_SensibleSR11;
- USHORT SiS661LCD2TableSize;
-
- USHORT SiS_PanelMinLVDS;
- USHORT SiS_PanelMin301;
-
- const SiS_StStruct *SiS_SModeIDTable;
- const SiS_StandTableStruct *SiS_StandTable;
- const SiS_ExtStruct *SiS_EModeIDTable;
- const SiS_Ext2Struct *SiS_RefIndex;
- const SiS_VBModeStruct *SiS_VBModeIDTable;
- const SiS_CRT1TableStruct *SiS_CRT1Table;
- const SiS_MCLKDataStruct *SiS_MCLKData_0;
- const SiS_MCLKDataStruct *SiS_MCLKData_1;
- SiS_VCLKDataStruct *SiS_VCLKData;
- SiS_VBVCLKDataStruct *SiS_VBVCLKData;
- const SiS_StResInfoStruct *SiS_StResInfo;
- const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-
- const UCHAR *pSiS_OutputSelect;
- const UCHAR *pSiS_SoftSetting;
-
- const DRAM4Type *SiS_SR15; /* pointer : point to array */
-#ifdef LINUX_KERNEL
- UCHAR *pSiS_SR07;
- const DRAM4Type *SiS_CR40; /* pointer : point to array */
- UCHAR *SiS_CR49;
- UCHAR *SiS_SR25;
- UCHAR *pSiS_SR1F;
- UCHAR *pSiS_SR21;
- UCHAR *pSiS_SR22;
- UCHAR *pSiS_SR23;
- UCHAR *pSiS_SR24;
- UCHAR *pSiS_SR31;
- UCHAR *pSiS_SR32;
- UCHAR *pSiS_SR33;
- UCHAR *pSiS_CRT2Data_1_2;
- UCHAR *pSiS_CRT2Data_4_D;
- UCHAR *pSiS_CRT2Data_4_E;
- UCHAR *pSiS_CRT2Data_4_10;
- const USHORT *pSiS_RGBSenseData;
- const USHORT *pSiS_VideoSenseData;
- const USHORT *pSiS_YCSenseData;
- const USHORT *pSiS_RGBSenseData2;
- const USHORT *pSiS_VideoSenseData2;
- const USHORT *pSiS_YCSenseData2;
+ unsigned char *VirtualRomBase;
+ BOOLEAN UseROM;
+#ifdef SIS_LINUX_KERNEL
+ unsigned char SISIOMEMTYPE *VideoMemoryAddress;
+ unsigned int VideoMemorySize;
#endif
+ SISIOADDRESS IOAddress;
+ SISIOADDRESS IOAddress2; /* For dual chip XGI volari */
- const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
- const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+#ifdef SIS_LINUX_KERNEL
+ SISIOADDRESS RelIO;
+#endif
+ SISIOADDRESS SiS_P3c4;
+ SISIOADDRESS SiS_P3d4;
+ SISIOADDRESS SiS_P3c0;
+ SISIOADDRESS SiS_P3ce;
+ SISIOADDRESS SiS_P3c2;
+ SISIOADDRESS SiS_P3ca;
+ SISIOADDRESS SiS_P3c6;
+ SISIOADDRESS SiS_P3c7;
+ SISIOADDRESS SiS_P3c8;
+ SISIOADDRESS SiS_P3c9;
+ SISIOADDRESS SiS_P3cb;
+ SISIOADDRESS SiS_P3cc;
+ SISIOADDRESS SiS_P3cd;
+ SISIOADDRESS SiS_P3da;
+ SISIOADDRESS SiS_Part1Port;
+ SISIOADDRESS SiS_Part2Port;
+ SISIOADDRESS SiS_Part3Port;
+ SISIOADDRESS SiS_Part4Port;
+ SISIOADDRESS SiS_Part5Port;
+ SISIOADDRESS SiS_VidCapt;
+ SISIOADDRESS SiS_VidPlay;
+ unsigned short SiS_IF_DEF_LVDS;
+ unsigned short SiS_IF_DEF_CH70xx;
+ unsigned short SiS_IF_DEF_CONEX;
+ unsigned short SiS_IF_DEF_TRUMPION;
+ unsigned short SiS_IF_DEF_DSTN;
+ unsigned short SiS_IF_DEF_FSTN;
+ unsigned short SiS_SysFlags;
+ unsigned char SiS_VGAINFO;
+#ifdef SIS_XORG_XF86
+ unsigned short SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#endif
+ BOOLEAN SiS_UseROM;
+ BOOLEAN SiS_ROMNew;
+ BOOLEAN SiS_XGIROM;
+ BOOLEAN SiS_NeedRomModeData;
+ BOOLEAN PanelSelfDetected;
+ BOOLEAN DDCPortMixup;
+ int SiS_CHOverScan;
+ BOOLEAN SiS_CHSOverScan;
+ BOOLEAN SiS_ChSW;
+ BOOLEAN SiS_UseLCDA;
+ int SiS_UseOEM;
+ unsigned int SiS_CustomT;
+ int SiS_UseWide, SiS_UseWideCRT2;
+ int SiS_TVBlue;
+ unsigned short SiS_Backup70xx;
+ BOOLEAN HaveEMI;
+ BOOLEAN HaveEMILCD;
+ BOOLEAN OverruleEMI;
+ unsigned char EMI_30,EMI_31,EMI_32,EMI_33;
+ unsigned short SiS_EMIOffset;
+ unsigned short SiS_PWDOffset;
+ short PDC, PDCA;
+ unsigned char SiS_MyCR63;
+ unsigned short SiS_CRT1Mode;
+ unsigned short SiS_flag_clearbuffer;
+ int SiS_RAMType;
+ unsigned char SiS_ChannelAB;
+ unsigned char SiS_DataBusWidth;
+ unsigned short SiS_ModeType;
+ unsigned short SiS_VBInfo;
+ unsigned short SiS_TVMode;
+ unsigned short SiS_LCDResInfo;
+ unsigned short SiS_LCDTypeInfo;
+ unsigned short SiS_LCDInfo;
+ unsigned short SiS_LCDInfo661;
+ unsigned short SiS_VBType;
+ unsigned short SiS_VBExtInfo;
+ unsigned short SiS_YPbPr;
+ unsigned short SiS_SelectCRT2Rate;
+ unsigned short SiS_SetFlag;
+ unsigned short SiS_RVBHCFACT;
+ unsigned short SiS_RVBHCMAX;
+ unsigned short SiS_RVBHRS;
+ unsigned short SiS_RVBHRS2;
+ unsigned short SiS_VGAVT;
+ unsigned short SiS_VGAHT;
+ unsigned short SiS_VT;
+ unsigned short SiS_HT;
+ unsigned short SiS_VGAVDE;
+ unsigned short SiS_VGAHDE;
+ unsigned short SiS_VDE;
+ unsigned short SiS_HDE;
+ unsigned short SiS_NewFlickerMode;
+ unsigned short SiS_RY1COE;
+ unsigned short SiS_RY2COE;
+ unsigned short SiS_RY3COE;
+ unsigned short SiS_RY4COE;
+ unsigned short SiS_LCDHDES;
+ unsigned short SiS_LCDVDES;
+ unsigned short SiS_DDC_Port;
+ unsigned short SiS_DDC_Index;
+ unsigned short SiS_DDC_Data;
+ unsigned short SiS_DDC_NData;
+ unsigned short SiS_DDC_Clk;
+ unsigned short SiS_DDC_NClk;
+ unsigned short SiS_DDC_DeviceAddr;
+ unsigned short SiS_DDC_ReadAddr;
+ unsigned short SiS_DDC_SecAddr;
+ unsigned short SiS_ChrontelInit;
+ BOOLEAN SiS_SensibleSR11;
+ unsigned short SiS661LCD2TableSize;
+
+ unsigned short SiS_PanelMinLVDS;
+ unsigned short SiS_PanelMin301;
+
+ const struct SiS_St *SiS_SModeIDTable;
+ const struct SiS_StandTable_S *SiS_StandTable;
+ const struct SiS_Ext *SiS_EModeIDTable;
+ const struct SiS_Ext2 *SiS_RefIndex;
+ const struct SiS_VBMode *SiS_VBModeIDTable;
+ const struct SiS_CRT1Table *SiS_CRT1Table;
+ const struct SiS_MCLKData *SiS_MCLKData_0;
+ const struct SiS_MCLKData *SiS_MCLKData_1;
+ struct SiS_VCLKData *SiS_VCLKData;
+ struct SiS_VBVCLKData *SiS_VBVCLKData;
+ const struct SiS_StResInfo_S *SiS_StResInfo;
+ const struct SiS_ModeResInfo_S *SiS_ModeResInfo;
+
+ const unsigned char *pSiS_OutputSelect;
+ const unsigned char *pSiS_SoftSetting;
+
+ const unsigned char *SiS_SR15;
+
+ const struct SiS_PanelDelayTbl *SiS_PanelDelayTbl;
+ const struct SiS_PanelDelayTbl *SiS_PanelDelayTblLVDS;
/* SiS bridge */
- const UCHAR *SiS_NTSCPhase;
- const UCHAR *SiS_PALPhase;
- const UCHAR *SiS_NTSCPhase2;
- const UCHAR *SiS_PALPhase2;
- const UCHAR *SiS_PALMPhase;
- const UCHAR *SiS_PALNPhase;
- const UCHAR *SiS_PALMPhase2;
- const UCHAR *SiS_PALNPhase2;
- const UCHAR *SiS_SpecialPhase;
- const UCHAR *SiS_SpecialPhaseM;
- const UCHAR *SiS_SpecialPhaseJ;
- const SiS_LCDDataStruct *SiS_ExtLCD1024x768Data;
- const SiS_LCDDataStruct *SiS_St2LCD1024x768Data;
- const SiS_LCDDataStruct *SiS_LCD1280x720Data;
- const SiS_LCDDataStruct *SiS_StLCD1280x768_2Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1280x768_2Data;
- const SiS_LCDDataStruct *SiS_LCD1280x800Data;
- const SiS_LCDDataStruct *SiS_LCD1280x800_2Data;
- const SiS_LCDDataStruct *SiS_LCD1280x960Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1280x1024Data;
- const SiS_LCDDataStruct *SiS_St2LCD1280x1024Data;
- const SiS_LCDDataStruct *SiS_StLCD1400x1050Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1400x1050Data;
- const SiS_LCDDataStruct *SiS_StLCD1600x1200Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1600x1200Data;
- const SiS_LCDDataStruct *SiS_LCD1680x1050Data;
- const SiS_LCDDataStruct *SiS_NoScaleData;
- const SiS_TVDataStruct *SiS_StPALData;
- const SiS_TVDataStruct *SiS_ExtPALData;
- const SiS_TVDataStruct *SiS_StNTSCData;
- const SiS_TVDataStruct *SiS_ExtNTSCData;
- const SiS_TVDataStruct *SiS_St1HiTVData;
- const SiS_TVDataStruct *SiS_St2HiTVData;
- const SiS_TVDataStruct *SiS_ExtHiTVData;
- const SiS_TVDataStruct *SiS_St525iData;
- const SiS_TVDataStruct *SiS_St525pData;
- const SiS_TVDataStruct *SiS_St750pData;
- const SiS_TVDataStruct *SiS_Ext525iData;
- const SiS_TVDataStruct *SiS_Ext525pData;
- const SiS_TVDataStruct *SiS_Ext750pData;
- const UCHAR *SiS_NTSCTiming;
- const UCHAR *SiS_PALTiming;
- const UCHAR *SiS_HiTVExtTiming;
- const UCHAR *SiS_HiTVSt1Timing;
- const UCHAR *SiS_HiTVSt2Timing;
- const UCHAR *SiS_HiTVGroup3Data;
- const UCHAR *SiS_HiTVGroup3Simu;
+ const struct SiS_LCDData *SiS_ExtLCD1024x768Data;
+ const struct SiS_LCDData *SiS_St2LCD1024x768Data;
+ const struct SiS_LCDData *SiS_LCD1280x720Data;
+ const struct SiS_LCDData *SiS_StLCD1280x768_2Data;
+ const struct SiS_LCDData *SiS_ExtLCD1280x768_2Data;
+ const struct SiS_LCDData *SiS_LCD1280x800Data;
+ const struct SiS_LCDData *SiS_LCD1280x800_2Data;
+ const struct SiS_LCDData *SiS_LCD1280x854Data;
+ const struct SiS_LCDData *SiS_LCD1280x960Data;
+ const struct SiS_LCDData *SiS_ExtLCD1280x1024Data;
+ const struct SiS_LCDData *SiS_St2LCD1280x1024Data;
+ const struct SiS_LCDData *SiS_StLCD1400x1050Data;
+ const struct SiS_LCDData *SiS_ExtLCD1400x1050Data;
+ const struct SiS_LCDData *SiS_StLCD1600x1200Data;
+ const struct SiS_LCDData *SiS_ExtLCD1600x1200Data;
+ const struct SiS_LCDData *SiS_LCD1680x1050Data;
+ const struct SiS_LCDData *SiS_NoScaleData;
+ const struct SiS_TVData *SiS_StPALData;
+ const struct SiS_TVData *SiS_ExtPALData;
+ const struct SiS_TVData *SiS_StNTSCData;
+ const struct SiS_TVData *SiS_ExtNTSCData;
+ const struct SiS_TVData *SiS_St1HiTVData;
+ const struct SiS_TVData *SiS_St2HiTVData;
+ const struct SiS_TVData *SiS_ExtHiTVData;
+ const struct SiS_TVData *SiS_St525iData;
+ const struct SiS_TVData *SiS_St525pData;
+ const struct SiS_TVData *SiS_St750pData;
+ const struct SiS_TVData *SiS_Ext525iData;
+ const struct SiS_TVData *SiS_Ext525pData;
+ const struct SiS_TVData *SiS_Ext750pData;
+ const unsigned char *SiS_NTSCTiming;
+ const unsigned char *SiS_PALTiming;
+ const unsigned char *SiS_HiTVExtTiming;
+ const unsigned char *SiS_HiTVSt1Timing;
+ const unsigned char *SiS_HiTVSt2Timing;
+ const unsigned char *SiS_HiTVGroup3Data;
+ const unsigned char *SiS_HiTVGroup3Simu;
#if 0
- const UCHAR *SiS_HiTVTextTiming;
- const UCHAR *SiS_HiTVGroup3Text;
+ const unsigned char *SiS_HiTVTextTiming;
+ const unsigned char *SiS_HiTVGroup3Text;
#endif
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_1;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_2;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_3;
/* LVDS, Chrontel */
- const SiS_LVDSDataStruct *SiS_LVDS800x600Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS800x600Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS640x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS640x480Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS320x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSXXXxXXXData_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_2;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS848x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS848x480Data_2;
- const SiS_LVDSDataStruct *SiS_CHTVUNTSCData;
- const SiS_LVDSDataStruct *SiS_CHTVONTSCData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALMData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALMData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALNData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALNData;
- const SiS_LVDSDataStruct *SiS_CHTVSOPALData;
-
- const SiS_LVDSDesStruct *SiS_PanelType00_1;
- const SiS_LVDSDesStruct *SiS_PanelType01_1;
- const SiS_LVDSDesStruct *SiS_PanelType02_1;
- const SiS_LVDSDesStruct *SiS_PanelType03_1;
- const SiS_LVDSDesStruct *SiS_PanelType04_1;
- const SiS_LVDSDesStruct *SiS_PanelType05_1;
- const SiS_LVDSDesStruct *SiS_PanelType06_1;
- const SiS_LVDSDesStruct *SiS_PanelType07_1;
- const SiS_LVDSDesStruct *SiS_PanelType08_1;
- const SiS_LVDSDesStruct *SiS_PanelType09_1;
- const SiS_LVDSDesStruct *SiS_PanelType0a_1;
- const SiS_LVDSDesStruct *SiS_PanelType0b_1;
- const SiS_LVDSDesStruct *SiS_PanelType0c_1;
- const SiS_LVDSDesStruct *SiS_PanelType0d_1;
- const SiS_LVDSDesStruct *SiS_PanelType0e_1;
- const SiS_LVDSDesStruct *SiS_PanelType0f_1;
- const SiS_LVDSDesStruct *SiS_PanelTypeNS_1;
- const SiS_LVDSDesStruct *SiS_PanelType00_2;
- const SiS_LVDSDesStruct *SiS_PanelType01_2;
- const SiS_LVDSDesStruct *SiS_PanelType02_2;
- const SiS_LVDSDesStruct *SiS_PanelType03_2;
- const SiS_LVDSDesStruct *SiS_PanelType04_2;
- const SiS_LVDSDesStruct *SiS_PanelType05_2;
- const SiS_LVDSDesStruct *SiS_PanelType06_2;
- const SiS_LVDSDesStruct *SiS_PanelType07_2;
- const SiS_LVDSDesStruct *SiS_PanelType08_2;
- const SiS_LVDSDesStruct *SiS_PanelType09_2;
- const SiS_LVDSDesStruct *SiS_PanelType0a_2;
- const SiS_LVDSDesStruct *SiS_PanelType0b_2;
- const SiS_LVDSDesStruct *SiS_PanelType0c_2;
- const SiS_LVDSDesStruct *SiS_PanelType0d_2;
- const SiS_LVDSDesStruct *SiS_PanelType0e_2;
- const SiS_LVDSDesStruct *SiS_PanelType0f_2;
- const SiS_LVDSDesStruct *SiS_PanelTypeNS_2;
- const SiS_LVDSDesStruct *SiS_CHTVUNTSCDesData;
- const SiS_LVDSDesStruct *SiS_CHTVONTSCDesData;
- const SiS_LVDSDesStruct *SiS_CHTVUPALDesData;
- const SiS_LVDSDesStruct *SiS_CHTVOPALDesData;
-
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1320x480_1;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UNTSC;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1OPAL;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1SOPAL;
-
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPAL;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALM;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALM;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
-
- const UCHAR *SiS_CHTVVCLKUNTSC;
- const UCHAR *SiS_CHTVVCLKONTSC;
- const UCHAR *SiS_CHTVVCLKUPAL;
- const UCHAR *SiS_CHTVVCLKOPAL;
- const UCHAR *SiS_CHTVVCLKUPALM;
- const UCHAR *SiS_CHTVVCLKOPALM;
- const UCHAR *SiS_CHTVVCLKUPALN;
- const UCHAR *SiS_CHTVVCLKOPALN;
- const UCHAR *SiS_CHTVVCLKSOPAL;
-
- USHORT PanelXRes, PanelHT;
- USHORT PanelYRes, PanelVT;
- USHORT PanelHRS, PanelHRE;
- USHORT PanelVRS, PanelVRE;
- USHORT PanelVCLKIdx300;
- USHORT PanelVCLKIdx315;
-
- BOOLEAN UseCustomMode;
- BOOLEAN CRT1UsesCustomMode;
- USHORT CHDisplay;
- USHORT CHSyncStart;
- USHORT CHSyncEnd;
- USHORT CHTotal;
- USHORT CHBlankStart;
- USHORT CHBlankEnd;
- USHORT CVDisplay;
- USHORT CVSyncStart;
- USHORT CVSyncEnd;
- USHORT CVTotal;
- USHORT CVBlankStart;
- USHORT CVBlankEnd;
- ULONG CDClock;
- ULONG CFlags;
- UCHAR CCRT1CRTC[17];
- UCHAR CSR2B;
- UCHAR CSR2C;
- USHORT CSRClock;
- USHORT CSRClock_CRT1;
- USHORT CModeFlag;
- USHORT CModeFlag_CRT1;
- USHORT CInfoFlag;
-
- int LVDSHL;
-
- BOOLEAN Backup;
- UCHAR Backup_Mode;
- UCHAR Backup_14;
- UCHAR Backup_15;
- UCHAR Backup_16;
- UCHAR Backup_17;
- UCHAR Backup_18;
- UCHAR Backup_19;
- UCHAR Backup_1a;
- UCHAR Backup_1b;
- UCHAR Backup_1c;
- UCHAR Backup_1d;
-
- int UsePanelScaler;
- int CenterScreen;
-
- USHORT CP_Vendor, CP_Product;
- BOOLEAN CP_HaveCustomData;
- int CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
- int CP_MaxX, CP_MaxY, CP_MaxClock;
- UCHAR CP_PrefSR2B, CP_PrefSR2C;
- USHORT CP_PrefClock;
- BOOLEAN CP_Supports64048075;
- int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
- int CP_HTotal[7], CP_VTotal[7];
- int CP_HSyncStart[7], CP_VSyncStart[7];
- int CP_HSyncEnd[7], CP_VSyncEnd[7];
- int CP_HBlankStart[7], CP_VBlankStart[7];
- int CP_HBlankEnd[7], CP_VBlankEnd[7];
- int CP_Clock[7];
- BOOLEAN CP_DataValid[7];
- BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
-} SiS_Private;
+ const struct SiS_LVDSData *SiS_LVDS320x240Data_1;
+ const struct SiS_LVDSData *SiS_LVDS320x240Data_2;
+ const struct SiS_LVDSData *SiS_LVDS640x480Data_1;
+ const struct SiS_LVDSData *SiS_LVDS800x600Data_1;
+ const struct SiS_LVDSData *SiS_LVDS1024x600Data_1;
+ const struct SiS_LVDSData *SiS_LVDS1024x768Data_1;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1366Data_1;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1366Data_2;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1024Data_1;
+ const struct SiS_LVDSData *SiS_LVDS848x480Data_1;
+ const struct SiS_LVDSData *SiS_LVDS848x480Data_2;
+ const struct SiS_LVDSData *SiS_CHTVUNTSCData;
+ const struct SiS_LVDSData *SiS_CHTVONTSCData;
+ const struct SiS_LVDSData *SiS_CHTVUPALData;
+ const struct SiS_LVDSData *SiS_CHTVOPALData;
+ const struct SiS_LVDSData *SiS_CHTVUPALMData;
+ const struct SiS_LVDSData *SiS_CHTVOPALMData;
+ const struct SiS_LVDSData *SiS_CHTVUPALNData;
+ const struct SiS_LVDSData *SiS_CHTVOPALNData;
+ const struct SiS_LVDSData *SiS_CHTVSOPALData;
+
+ const struct SiS_LVDSDes *SiS_PanelType04_1a;
+ const struct SiS_LVDSDes *SiS_PanelType04_2a;
+ const struct SiS_LVDSDes *SiS_PanelType04_1b;
+ const struct SiS_LVDSDes *SiS_PanelType04_2b;
+
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_1;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_2;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_2_H;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_3;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_3_H;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1640x480_1;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1640x480_1_H;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1UNTSC;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1ONTSC;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1UPAL;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1OPAL;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1SOPAL;
+
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UNTSC;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_ONTSC;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPAL;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPAL;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPALM;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPALM;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPALN;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPALN;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_SOPAL;
+
+ const unsigned char *SiS_CHTVVCLKUNTSC;
+ const unsigned char *SiS_CHTVVCLKONTSC;
+ const unsigned char *SiS_CHTVVCLKUPAL;
+ const unsigned char *SiS_CHTVVCLKOPAL;
+ const unsigned char *SiS_CHTVVCLKUPALM;
+ const unsigned char *SiS_CHTVVCLKOPALM;
+ const unsigned char *SiS_CHTVVCLKUPALN;
+ const unsigned char *SiS_CHTVVCLKOPALN;
+ const unsigned char *SiS_CHTVVCLKSOPAL;
+
+ unsigned short PanelXRes, PanelHT;
+ unsigned short PanelYRes, PanelVT;
+ unsigned short PanelHRS, PanelHRE;
+ unsigned short PanelVRS, PanelVRE;
+ unsigned short PanelVCLKIdx300;
+ unsigned short PanelVCLKIdx315;
+ BOOLEAN Alternate1600x1200;
+
+ BOOLEAN UseCustomMode;
+ BOOLEAN CRT1UsesCustomMode;
+ unsigned short CHDisplay;
+ unsigned short CHSyncStart;
+ unsigned short CHSyncEnd;
+ unsigned short CHTotal;
+ unsigned short CHBlankStart;
+ unsigned short CHBlankEnd;
+ unsigned short CVDisplay;
+ unsigned short CVSyncStart;
+ unsigned short CVSyncEnd;
+ unsigned short CVTotal;
+ unsigned short CVBlankStart;
+ unsigned short CVBlankEnd;
+ unsigned int CDClock;
+ unsigned int CFlags;
+ unsigned char CCRT1CRTC[17];
+ unsigned char CSR2B;
+ unsigned char CSR2C;
+ unsigned short CSRClock;
+ unsigned short CSRClock_CRT1;
+ unsigned short CModeFlag;
+ unsigned short CModeFlag_CRT1;
+ unsigned short CInfoFlag;
+
+ int LVDSHL;
+
+ BOOLEAN Backup;
+ unsigned char Backup_Mode;
+ unsigned char Backup_14;
+ unsigned char Backup_15;
+ unsigned char Backup_16;
+ unsigned char Backup_17;
+ unsigned char Backup_18;
+ unsigned char Backup_19;
+ unsigned char Backup_1a;
+ unsigned char Backup_1b;
+ unsigned char Backup_1c;
+ unsigned char Backup_1d;
+
+ unsigned char Init_P4_0E;
+
+ int UsePanelScaler;
+ int CenterScreen;
+
+ unsigned short CP_Vendor, CP_Product;
+ BOOLEAN CP_HaveCustomData;
+ int CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
+ int CP_MaxX, CP_MaxY, CP_MaxClock;
+ unsigned char CP_PrefSR2B, CP_PrefSR2C;
+ unsigned short CP_PrefClock;
+ BOOLEAN CP_Supports64048075;
+ int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
+ int CP_HTotal[7], CP_VTotal[7];
+ int CP_HSyncStart[7], CP_VSyncStart[7];
+ int CP_HSyncEnd[7], CP_VSyncEnd[7];
+ int CP_HBlankStart[7], CP_VBlankStart[7];
+ int CP_HBlankEnd[7], CP_VBlankEnd[7];
+ int CP_Clock[7];
+ BOOLEAN CP_DataValid[7];
+ BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+};
#endif
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 698ca9232e73..81a6d9f188cf 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1061,6 +1061,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
chip_id = id->device;
+ if(chip_id == CYBERBLADEi1)
+ output("*** Please do use cyblafb, Cyberblade/i1 support "
+ "will soon be removed from tridentfb!\n");
+
+
/* If PCI id is 0x9660 then further detect chip type */
if (chip_id == TGUI9660) {
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index a272592b0373..1ca80264c7b0 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -19,6 +19,7 @@
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <video/vga.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -54,6 +55,7 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
+static int vga_compat;
/* --------------------------------------------------------------------- */
@@ -86,6 +88,37 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
+static int vesafb_blank(int blank, struct fb_info *info)
+{
+ int err = 1;
+
+ if (vga_compat) {
+ int loop = 10000;
+ u8 seq = 0, crtc17 = 0;
+
+ err = 0;
+
+ if (blank) {
+ seq = 0x20;
+ crtc17 = 0x00;
+ } else {
+ seq = 0x00;
+ crtc17 = 0x80;
+ }
+
+ vga_wseq(NULL, 0x00, 0x01);
+ seq |= vga_rseq(NULL, 0x01) & ~0x20;
+ vga_wseq(NULL, 0x00, seq);
+
+ crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
+ while (loop--);
+ vga_wcrt(NULL, 0x17, crtc17);
+ vga_wseq(NULL, 0x00, 0x03);
+ }
+
+ return err;
+}
+
static void vesa_setpalette(int regno, unsigned red, unsigned green,
unsigned blue)
{
@@ -176,6 +209,7 @@ static struct fb_ops vesafb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = vesafb_setcolreg,
.fb_pan_display = vesafb_pan_display,
+ .fb_blank = vesafb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
@@ -429,6 +463,10 @@ static int __init vesafb_probe(struct device *device)
info->flags = FBINFO_FLAG_DEFAULT |
(ypan) ? FBINFO_HWACCEL_YPAN : 0;
+ vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
+ printk("vesafb: Mode is %sVGA compatible\n",
+ (vga_compat) ? "" : "not ");
+
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
goto err;
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index 0ea62d8bc703..ca92940f3943 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -342,16 +342,11 @@ static void vga_cleanup(struct vgastate *state)
if (state->vidstate != NULL) {
struct regstate *saved = (struct regstate *) state->vidstate;
- if (saved->vga_font0)
- vfree(saved->vga_font0);
- if (saved->vga_font1)
- vfree(saved->vga_font1);
- if (saved->vga_text)
- vfree(saved->vga_text);
- if (saved->vga_cmap)
- vfree(saved->vga_cmap);
- if (saved->attr)
- vfree(saved->attr);
+ vfree(saved->vga_font0);
+ vfree(saved->vga_font1);
+ vfree(saved->vga_text);
+ vfree(saved->vga_cmap);
+ vfree(saved->attr);
kfree(saved);
state->vidstate = NULL;
}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index adcda697ea60..0030c071da8f 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -5,9 +5,15 @@
*
* Copyright (C) 2002, ATI Corp.
* Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton
*
* Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
+ * Generic platform support by Ian Molton <spyro@f2s.com>
+ * and Richard Purdie <rpurdie@rpsys.net>
+ *
+ * w32xx support by Ian Molton
+ *
* 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.
@@ -21,7 +27,7 @@
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/string.h>
-#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <video/w100fb.h>
@@ -30,114 +36,78 @@
/*
* Prototypes
*/
-static void w100fb_save_buffer(void);
-static void w100fb_clear_buffer(void);
-static void w100fb_restore_buffer(void);
-static void w100fb_clear_screen(u32 mode, long int offset);
-static void w100_resume(void);
static void w100_suspend(u32 mode);
-static void w100_init_qvga_rotation(u16 deg);
-static void w100_init_vga_rotation(u16 deg);
static void w100_vsync(void);
-static void w100_init_sharp_lcd(u32 mode);
-static void w100_pwm_setup(void);
-static void w100_InitExtMem(u32 mode);
-static void w100_hw_init(void);
-static u16 w100_set_fastsysclk(u16 Freq);
-
-static void lcdtg_hw_init(u32 mode);
-static void lcdtg_lcd_change(u32 mode);
-static void lcdtg_resume(void);
-static void lcdtg_suspend(void);
-
-
-/* Register offsets & lengths */
-#define REMAPPED_FB_LEN 0x15ffff
-
-#define BITS_PER_PIXEL 16
+static void w100_hw_init(struct w100fb_par*);
+static void w100_pwm_setup(struct w100fb_par*);
+static void w100_init_clocks(struct w100fb_par*);
+static void w100_setup_memory(struct w100fb_par*);
+static void w100_init_lcd(struct w100fb_par*);
+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);
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
/* Pseudo palette size */
#define MAX_PALETTES 16
-/* for resolution change */
-#define LCD_MODE_INIT (-1)
-#define LCD_MODE_480 0
-#define LCD_MODE_320 1
-#define LCD_MODE_240 2
-#define LCD_MODE_640 3
-
-#define LCD_SHARP_QVGA 0
-#define LCD_SHARP_VGA 1
-
-#define LCD_MODE_PORTRAIT 0
-#define LCD_MODE_LANDSCAPE 1
-
#define W100_SUSPEND_EXTMEM 0
#define W100_SUSPEND_ALL 1
-/* General frame buffer data structures */
-struct w100fb_par {
- u32 xres;
- u32 yres;
- int fastsysclk_mode;
- int lcdMode;
- int rotation_flag;
- int blanking_flag;
- int comadj;
- int phadadj;
-};
-
-static struct w100fb_par *current_par;
+#define BITS_PER_PIXEL 16
/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
static void *remapped_base;
static void *remapped_regs;
static void *remapped_fbuf;
-/* External Function */
-static void(*w100fb_ssp_send)(u8 adrs, u8 data);
+#define REMAPPED_FB_LEN 0x15ffff
+
+/* This is the offset in the w100's address space we map the current
+ framebuffer memory to. We use the position of external memory as
+ we can remap internal memory to there if external isn't present. */
+#define W100_FB_BASE MEM_EXT_BASE_VALUE
+
/*
* Sysfs functions
*/
-
-static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- return sprintf(buf, "%d\n",par->rotation_flag);
+ return sprintf(buf, "%d\n",par->flip);
}
-static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned int rotate;
+ unsigned int flip;
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- rotate = simple_strtoul(buf, NULL, 10);
+ flip = simple_strtoul(buf, NULL, 10);
+
+ if (flip > 0)
+ par->flip = 1;
+ else
+ par->flip = 0;
- if (rotate > 0) par->rotation_flag = 1;
- else par->rotation_flag = 0;
+ w100_update_disable();
+ w100_set_dispregs(par);
+ w100_update_enable();
- if (par->lcdMode == LCD_MODE_320)
- w100_init_qvga_rotation(par->rotation_flag ? 270 : 90);
- else if (par->lcdMode == LCD_MODE_240)
- w100_init_qvga_rotation(par->rotation_flag ? 180 : 0);
- else if (par->lcdMode == LCD_MODE_640)
- w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
- else if (par->lcdMode == LCD_MODE_480)
- w100_init_vga_rotation(par->rotation_flag ? 180 : 0);
+ calc_hsync(par);
return count;
}
-static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store);
+static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long param;
- unsigned long regs;
+ unsigned long regs, param;
regs = simple_strtoul(buf, NULL, 16);
param = readl(remapped_regs + regs);
printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
@@ -148,8 +118,7 @@ static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long regs;
- unsigned long param;
+ unsigned long regs, param;
sscanf(buf, "%lx %lx", &regs, &param);
if (regs <= 0x2000) {
@@ -163,54 +132,56 @@ static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *att
static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
-static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- return sprintf(buf, "%d\n",par->fastsysclk_mode);
+ return sprintf(buf, "%d\n",par->fastpll_mode);
}
-static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- int param;
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- param = simple_strtoul(buf, NULL, 10);
-
- if (param == 75) {
- printk("Set fastsysclk %d\n", param);
- par->fastsysclk_mode = param;
- w100_set_fastsysclk(par->fastsysclk_mode);
- } else if (param == 100) {
- printk("Set fastsysclk %d\n", param);
- par->fastsysclk_mode = param;
- w100_set_fastsysclk(par->fastsysclk_mode);
+ if (simple_strtoul(buf, NULL, 10) > 0) {
+ par->fastpll_mode=1;
+ printk("w100fb: Using fast system clock (if possible)\n");
+ } else {
+ par->fastpll_mode=0;
+ printk("w100fb: Using normal system clock\n");
}
+
+ w100_init_clocks(par);
+ calc_hsync(par);
+
return count;
}
-static DEVICE_ATTR(fastsysclk, 0644, fastsysclk_show, fastsysclk_store);
+static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
/*
- * The touchscreen on this device needs certain information
- * from the video driver to function correctly. We export it here.
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
*/
-int w100fb_get_xres(void) {
- return current_par->xres;
-}
+unsigned long w100fb_get_hsynclen(struct device *dev)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
-int w100fb_get_blanking(void) {
- return current_par->blanking_flag;
+ /* If display is blanked/suspended, hsync isn't active */
+ if (par->blanked)
+ return 0;
+ else
+ return par->hsync_len;
}
+EXPORT_SYMBOL(w100fb_get_hsynclen);
-int w100fb_get_fastsysclk(void) {
- return current_par->fastsysclk_mode;
+static void w100fb_clear_screen(struct w100fb_par *par)
+{
+ memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
}
-EXPORT_SYMBOL(w100fb_get_xres);
-EXPORT_SYMBOL(w100fb_get_blanking);
-EXPORT_SYMBOL(w100fb_get_fastsysclk);
/*
@@ -234,7 +205,6 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* according to the RGB bitfield information.
*/
if (regno < MAX_PALETTES) {
-
u32 *pal = info->pseudo_palette;
val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -250,115 +220,90 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
*/
static int w100fb_blank(int blank_mode, struct fb_info *info)
{
- struct w100fb_par *par;
- par=info->par;
+ struct w100fb_par *par = info->par;
+ struct w100_tg_info *tg = par->mach->tg;
switch(blank_mode) {
- case FB_BLANK_NORMAL: /* Normal blanking */
- case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
- case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
- case FB_BLANK_POWERDOWN: /* Poweroff */
- if (par->blanking_flag == 0) {
- w100fb_save_buffer();
- lcdtg_suspend();
- par->blanking_flag = 1;
+ case FB_BLANK_NORMAL: /* Normal blanking */
+ case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+ case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+ case FB_BLANK_POWERDOWN: /* Poweroff */
+ if (par->blanked == 0) {
+ if(tg && tg->suspend)
+ tg->suspend(par);
+ par->blanked = 1;
}
break;
case FB_BLANK_UNBLANK: /* Unblanking */
- if (par->blanking_flag != 0) {
- w100fb_restore_buffer();
- lcdtg_resume();
- par->blanking_flag = 0;
+ if (par->blanked != 0) {
+ if(tg && tg->resume)
+ tg->resume(par);
+ par->blanked = 0;
}
break;
}
return 0;
}
+
/*
* Change the resolution by calling the appropriate hardware functions
*/
-static void w100fb_changeres(int rotate_mode, u32 mode)
+static void w100fb_activate_var(struct w100fb_par *par)
{
- u16 rotation=0;
-
- switch(rotate_mode) {
- case LCD_MODE_LANDSCAPE:
- rotation=(current_par->rotation_flag ? 270 : 90);
- break;
- case LCD_MODE_PORTRAIT:
- rotation=(current_par->rotation_flag ? 180 : 0);
- break;
- }
+ struct w100_tg_info *tg = par->mach->tg;
- w100_pwm_setup();
- switch(mode) {
- case LCD_SHARP_QVGA:
- w100_vsync();
- w100_suspend(W100_SUSPEND_EXTMEM);
- w100_init_sharp_lcd(LCD_SHARP_QVGA);
- w100_init_qvga_rotation(rotation);
- w100_InitExtMem(LCD_SHARP_QVGA);
- w100fb_clear_screen(LCD_SHARP_QVGA, 0);
- lcdtg_lcd_change(LCD_SHARP_QVGA);
- break;
- case LCD_SHARP_VGA:
- w100fb_clear_screen(LCD_SHARP_QVGA, 0);
- writel(0xBFFFA000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- w100_InitExtMem(LCD_SHARP_VGA);
- w100fb_clear_screen(LCD_SHARP_VGA, 0x200000);
- w100_vsync();
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- if (rotation != 0)
- w100_init_vga_rotation(rotation);
- lcdtg_lcd_change(LCD_SHARP_VGA);
- break;
- }
+ w100_pwm_setup(par);
+ w100_setup_memory(par);
+ w100_init_clocks(par);
+ w100fb_clear_screen(par);
+ w100_vsync();
+
+ w100_update_disable();
+ w100_init_lcd(par);
+ w100_set_dispregs(par);
+ w100_update_enable();
+
+ calc_hsync(par);
+
+ if (!par->blanked && tg && tg->change)
+ tg->change(par);
}
-/*
- * Set up the display for the fb subsystem
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
*/
-static void w100fb_activate_var(struct fb_info *info)
+static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
{
- u32 temp32;
- struct w100fb_par *par=info->par;
- struct fb_var_screeninfo *var = &info->var;
+ struct w100_mode *mode = NULL;
+ struct w100_mode *modelist = par->mach->modelist;
+ unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+ unsigned int i;
+
+ for (i = 0 ; i < par->mach->num_modes ; i++) {
+ if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
+ modelist[i].xres < best_x && modelist[i].yres < best_y) {
+ best_x = modelist[i].xres;
+ best_y = modelist[i].yres;
+ mode = &modelist[i];
+ } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
+ modelist[i].xres < best_y && modelist[i].yres < best_x) {
+ best_x = modelist[i].yres;
+ best_y = modelist[i].xres;
+ mode = &modelist[i];
+ }
+ }
- /* Set the hardware to 565 */
- temp32 = readl(remapped_regs + mmDISP_DEBUG2);
- temp32 &= 0xff7fffff;
- temp32 |= 0x00800000;
- writel(temp32, remapped_regs + mmDISP_DEBUG2);
+ if (mode && saveval) {
+ *x = best_x;
+ *y = best_y;
+ }
- if (par->lcdMode == LCD_MODE_INIT) {
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
- par->lcdMode = LCD_MODE_640;
- lcdtg_hw_init(LCD_SHARP_VGA);
- } else if (var->xres == 320 && var->yres == 240) {
- if (par->lcdMode != LCD_MODE_320) {
- w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_QVGA);
- par->lcdMode = LCD_MODE_320;
- }
- } else if (var->xres == 240 && var->yres == 320) {
- if (par->lcdMode != LCD_MODE_240) {
- w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_QVGA);
- par->lcdMode = LCD_MODE_240;
- }
- } else if (var->xres == 640 && var->yres == 480) {
- if (par->lcdMode != LCD_MODE_640) {
- w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_VGA);
- par->lcdMode = LCD_MODE_640;
- }
- } else if (var->xres == 480 && var->yres == 640) {
- if (par->lcdMode != LCD_MODE_480) {
- w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_VGA);
- par->lcdMode = LCD_MODE_480;
- }
- } else printk(KERN_ERR "W100FB: Resolution error!\n");
+ return mode;
}
@@ -366,31 +311,19 @@ static void w100fb_activate_var(struct fb_info *info)
* w100fb_check_var():
* Get the video params out of 'var'. If a value doesn't fit, round it up,
* if it's too big, return -EINVAL.
- *
*/
static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- if (var->xres < var->yres) { /* Portrait mode */
- if ((var->xres > 480) || (var->yres > 640)) {
- return -EINVAL;
- } else if ((var->xres > 240) || (var->yres > 320)) {
- var->xres = 480;
- var->yres = 640;
- } else {
- var->xres = 240;
- var->yres = 320;
- }
- } else { /* Landscape mode */
- if ((var->xres > 640) || (var->yres > 480)) {
- return -EINVAL;
- } else if ((var->xres > 320) || (var->yres > 240)) {
- var->xres = 640;
- var->yres = 480;
- } else {
- var->xres = 320;
- var->yres = 240;
- }
- }
+ struct w100fb_par *par=info->par;
+
+ if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
+ return -EINVAL;
+
+ if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
+ return -EINVAL;
+
+ if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
+ return -EINVAL;
var->xres_virtual = max(var->xres_virtual, var->xres);
var->yres_virtual = max(var->yres_virtual, var->yres);
@@ -409,13 +342,11 @@ static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->transp.offset = var->transp.length = 0;
var->nonstd = 0;
-
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
-
var->sync = 0;
- var->pixclock = 0x04; /* 171521; */
+ var->pixclock = 0x04; /* 171521; */
return 0;
}
@@ -430,274 +361,286 @@ static int w100fb_set_par(struct fb_info *info)
{
struct w100fb_par *par=info->par;
- par->xres = info->var.xres;
- par->yres = info->var.yres;
-
- info->fix.visual = FB_VISUAL_TRUECOLOR;
-
- info->fix.ypanstep = 0;
- info->fix.ywrapstep = 0;
+ if (par->xres != info->var.xres || par->yres != info->var.yres) {
+ par->xres = info->var.xres;
+ par->yres = info->var.yres;
+ par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
- if (par->blanking_flag)
- w100fb_clear_buffer();
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
- w100fb_activate_var(info);
+ if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
+ par->extmem_active = 1;
+ info->fix.smem_len = par->mach->mem->size+1;
+ } else {
+ par->extmem_active = 0;
+ info->fix.smem_len = MEM_INT_SIZE+1;
+ }
- if (par->lcdMode == LCD_MODE_480) {
- info->fix.line_length = (480 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x200000;
- } else if (par->lcdMode == LCD_MODE_320) {
- info->fix.line_length = (320 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x60000;
- } else if (par->lcdMode == LCD_MODE_240) {
- info->fix.line_length = (240 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x60000;
- } else if (par->lcdMode == LCD_MODE_INIT || par->lcdMode == LCD_MODE_640) {
- info->fix.line_length = (640 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x200000;
+ w100fb_activate_var(par);
}
-
return 0;
}
/*
- * Frame buffer operations
+ * Frame buffer operations
*/
static struct fb_ops w100fb_ops = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.fb_check_var = w100fb_check_var,
- .fb_set_par = w100fb_set_par,
+ .fb_set_par = w100fb_set_par,
.fb_setcolreg = w100fb_setcolreg,
- .fb_blank = w100fb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
+ .fb_blank = w100fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
+ .fb_cursor = soft_cursor,
};
-
-static void w100fb_clear_screen(u32 mode, long int offset)
+#ifdef CONFIG_PM
+static void w100fb_save_vidmem(struct w100fb_par *par)
{
- int i, numPix = 0;
-
- if (mode == LCD_SHARP_VGA)
- numPix = 640 * 480;
- else if (mode == LCD_SHARP_QVGA)
- numPix = 320 * 240;
+ int memsize;
- for (i = 0; i < numPix; i++)
- writew(0xffff, remapped_fbuf + offset + (2*i));
-}
-
-
-/* Need to split up the buffers to stay within the limits of kmalloc */
-#define W100_BUF_NUM 6
-static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL };
-
-static void w100fb_save_buffer(void)
-{
- int i, j, bufsize;
-
- bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
- for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] == NULL)
- gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL);
- if (gSaveImagePtr[i] == NULL) {
- w100fb_clear_buffer();
- printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i);
- break;
- }
- for (j = 0; j < bufsize/4; j++)
- *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4);
+ if (par->extmem_active) {
+ memsize=par->mach->mem->size;
+ par->saved_extmem = vmalloc(memsize);
+ if (par->saved_extmem)
+ memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
}
+ memsize=MEM_INT_SIZE;
+ par->saved_intmem = vmalloc(memsize);
+ if (par->saved_intmem && par->extmem_active)
+ memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
+ else if (par->saved_intmem)
+ memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
}
-
-static void w100fb_restore_buffer(void)
+static void w100fb_restore_vidmem(struct w100fb_par *par)
{
- int i, j, bufsize;
+ int memsize;
- bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
- for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] == NULL) {
- printk(KERN_WARNING "can't find pre-off image buffer %d\n", i);
- w100fb_clear_buffer();
- break;
- }
- for (j = 0; j < (bufsize/4); j++)
- writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4));
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
+ if (par->extmem_active && par->saved_extmem) {
+ memsize=par->mach->mem->size;
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
+ vfree(par->saved_extmem);
}
-}
-
-
-static void w100fb_clear_buffer(void)
-{
- int i;
- for (i = 0; i < W100_BUF_NUM; i++) {
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
+ if (par->saved_intmem) {
+ memsize=MEM_INT_SIZE;
+ if (par->extmem_active)
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
+ else
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
+ vfree(par->saved_intmem);
}
}
-
-#ifdef CONFIG_PM
-static int w100fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level)
{
if (level == SUSPEND_POWER_DOWN) {
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
+ struct w100_tg_info *tg = par->mach->tg;
- w100fb_save_buffer();
- lcdtg_suspend();
+ w100fb_save_vidmem(par);
+ if(tg && tg->suspend)
+ tg->suspend(par);
w100_suspend(W100_SUSPEND_ALL);
- par->blanking_flag = 1;
+ par->blanked = 1;
}
return 0;
}
-static int w100fb_resume(struct device *dev, u32 level)
+static int w100fb_resume(struct device *dev, uint32_t level)
{
if (level == RESUME_POWER_ON) {
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
-
- w100_resume();
- w100fb_restore_buffer();
- lcdtg_resume();
- par->blanking_flag = 0;
+ struct w100_tg_info *tg = par->mach->tg;
+
+ w100_hw_init(par);
+ w100fb_activate_var(par);
+ w100fb_restore_vidmem(par);
+ if(tg && tg->resume)
+ tg->resume(par);
+ par->blanked = 0;
}
return 0;
}
#else
-#define w100fb_suspend NULL
-#define w100fb_resume NULL
+#define w100fb_suspend NULL
+#define w100fb_resume NULL
#endif
int __init w100fb_probe(struct device *dev)
{
+ int err = -EIO;
struct w100fb_mach_info *inf;
- struct fb_info *info;
+ struct fb_info *info = NULL;
struct w100fb_par *par;
struct platform_device *pdev = to_platform_device(dev);
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ unsigned int chip_id;
if (!mem)
return -EINVAL;
- /* remap the areas we're going to use */
+ /* Remap the chip base address */
remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
if (remapped_base == NULL)
- return -EIO;
+ goto out;
+ /* Map the register space */
remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
- if (remapped_regs == NULL) {
- iounmap(remapped_base);
- return -EIO;
+ if (remapped_regs == NULL)
+ goto out;
+
+ /* Identify the chip */
+ printk("Found ");
+ chip_id = readl(remapped_regs + mmCHIP_ID);
+ switch(chip_id) {
+ case CHIP_ID_W100: printk("w100"); break;
+ case CHIP_ID_W3200: printk("w3200"); break;
+ case CHIP_ID_W3220: printk("w3220"); break;
+ default:
+ printk("Unknown imageon chip ID\n");
+ err = -ENODEV;
+ goto out;
}
+ printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
- remapped_fbuf = ioremap_nocache(mem->start+MEM_EXT_BASE_VALUE, REMAPPED_FB_LEN);
- if (remapped_fbuf == NULL) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- return -EIO;
- }
+ /* Remap the framebuffer */
+ remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
+ if (remapped_fbuf == NULL)
+ goto out;
info=framebuffer_alloc(sizeof(struct w100fb_par), dev);
if (!info) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
}
- info->device=dev;
par = info->par;
- current_par=info->par;
dev_set_drvdata(dev, info);
inf = dev->platform_data;
- par->phadadj = inf->phadadj;
- par->comadj = inf->comadj;
- par->fastsysclk_mode = 75;
- par->lcdMode = LCD_MODE_INIT;
- par->rotation_flag=0;
- par->blanking_flag=0;
- w100fb_ssp_send = inf->w100fb_ssp_send;
-
- w100_hw_init();
- w100_pwm_setup();
+ par->chip_id = chip_id;
+ par->mach = inf;
+ par->fastpll_mode = 0;
+ par->blanked = 0;
+
+ par->pll_table=w100_get_xtal_table(inf->xtal_freq);
+ if (!par->pll_table) {
+ printk(KERN_ERR "No matching Xtal definition found\n");
+ err = -EINVAL;
+ goto out;
+ }
info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
if (!info->pseudo_palette) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
}
info->fbops = &w100fb_ops;
info->flags = FBINFO_DEFAULT;
info->node = -1;
- info->screen_base = remapped_fbuf;
+ info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
info->screen_size = REMAPPED_FB_LEN;
- info->var.xres = 640;
+ strcpy(info->fix.id, "w100fb");
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+ info->fix.smem_start = mem->start+W100_FB_BASE;
+ info->fix.mmio_start = mem->start+W100_REG_BASE;
+ info->fix.mmio_len = W100_REG_LEN;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ par->mode = &inf->modelist[0];
+ if(inf->init_mode & INIT_MODE_ROTATED) {
+ info->var.xres = par->mode->yres;
+ info->var.yres = par->mode->xres;
+ }
+ else {
+ info->var.xres = par->mode->xres;
+ info->var.yres = par->mode->yres;
+ }
+
+ if(inf->init_mode &= INIT_MODE_FLIPPED)
+ par->flip = 1;
+ else
+ par->flip = 0;
+
info->var.xres_virtual = info->var.xres;
- info->var.yres = 480;
info->var.yres_virtual = info->var.yres;
- info->var.pixclock = 0x04; /* 171521; */
+ info->var.pixclock = 0x04; /* 171521; */
info->var.sync = 0;
info->var.grayscale = 0;
info->var.xoffset = info->var.yoffset = 0;
info->var.accel_flags = 0;
info->var.activate = FB_ACTIVATE_NOW;
- strcpy(info->fix.id, "w100fb");
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.type_aux = 0;
- info->fix.accel = FB_ACCEL_NONE;
- info->fix.smem_start = mem->start+MEM_EXT_BASE_VALUE;
- info->fix.mmio_start = mem->start+W100_REG_BASE;
- info->fix.mmio_len = W100_REG_LEN;
+ w100_hw_init(par);
+
+ if (w100fb_check_var(&info->var, info) < 0) {
+ err = -EINVAL;
+ goto out;
+ }
- w100fb_check_var(&info->var, info);
w100fb_set_par(info);
if (register_framebuffer(info) < 0) {
- kfree(info->pseudo_palette);
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
- device_create_file(dev, &dev_attr_fastsysclk);
+ device_create_file(dev, &dev_attr_fastpllclk);
device_create_file(dev, &dev_attr_reg_read);
device_create_file(dev, &dev_attr_reg_write);
- device_create_file(dev, &dev_attr_rotation);
+ device_create_file(dev, &dev_attr_flip);
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
return 0;
+out:
+ fb_dealloc_cmap(&info->cmap);
+ kfree(info->pseudo_palette);
+ if (remapped_fbuf != NULL)
+ iounmap(remapped_fbuf);
+ if (remapped_regs != NULL)
+ iounmap(remapped_regs);
+ if (remapped_base != NULL)
+ iounmap(remapped_base);
+ if (info)
+ framebuffer_release(info);
+ return err;
}
static int w100fb_remove(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
- device_remove_file(dev, &dev_attr_fastsysclk);
+ device_remove_file(dev, &dev_attr_fastpllclk);
device_remove_file(dev, &dev_attr_reg_read);
device_remove_file(dev, &dev_attr_reg_write);
- device_remove_file(dev, &dev_attr_rotation);
+ device_remove_file(dev, &dev_attr_flip);
unregister_framebuffer(info);
- w100fb_clear_buffer();
+ vfree(par->saved_intmem);
+ vfree(par->saved_extmem);
kfree(info->pseudo_palette);
+ fb_dealloc_cmap(&info->cmap);
iounmap(remapped_base);
iounmap(remapped_regs);
@@ -721,10 +664,54 @@ static void w100_soft_reset(void)
udelay(100);
}
+static void w100_update_disable(void)
+{
+ union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+ /* Prevent display updates */
+ disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+ disp_db_buf_wr_cntl.f.update_db_buf = 0;
+ disp_db_buf_wr_cntl.f.en_db_buf = 0;
+ writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+static void w100_update_enable(void)
+{
+ union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+ /* Enable display updates */
+ disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+ disp_db_buf_wr_cntl.f.update_db_buf = 1;
+ disp_db_buf_wr_cntl.f.en_db_buf = 1;
+ writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+unsigned long w100fb_gpio_read(int port)
+{
+ unsigned long value;
+
+ if (port==W100_GPIO_PORT_A)
+ value = readl(remapped_regs + mmGPIO_DATA);
+ else
+ value = readl(remapped_regs + mmGPIO_DATA2);
+
+ return value;
+}
+
+void w100fb_gpio_write(int port, unsigned long value)
+{
+ if (port==W100_GPIO_PORT_A)
+ value = writel(value, remapped_regs + mmGPIO_DATA);
+ else
+ value = writel(value, remapped_regs + mmGPIO_DATA2);
+}
+EXPORT_SYMBOL(w100fb_gpio_read);
+EXPORT_SYMBOL(w100fb_gpio_write);
+
/*
* Initialization of critical w100 hardware
*/
-static void w100_hw_init(void)
+static void w100_hw_init(struct w100fb_par *par)
{
u32 temp32;
union cif_cntl_u cif_cntl;
@@ -735,8 +722,8 @@ static void w100_hw_init(void)
union cpu_defaults_u cpu_default;
union cif_write_dbg_u cif_write_dbg;
union wrap_start_dir_u wrap_start_dir;
- union mc_ext_mem_location_u mc_ext_mem_loc;
union cif_io_u cif_io;
+ struct w100_gpio_regs *gpio = par->mach->gpio;
w100_soft_reset();
@@ -791,19 +778,6 @@ static void w100_hw_init(void)
cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
- /* This location is relative to internal w100 addresses */
- writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
-
- mc_ext_mem_loc.val = defMC_EXT_MEM_LOCATION;
- mc_ext_mem_loc.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
- mc_ext_mem_loc.f.mc_ext_mem_top = MEM_EXT_TOP_VALUE >> 8;
- writel((u32) (mc_ext_mem_loc.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
-
- if ((current_par->lcdMode == LCD_MODE_240) || (current_par->lcdMode == LCD_MODE_320))
- w100_InitExtMem(LCD_SHARP_QVGA);
- else
- w100_InitExtMem(LCD_SHARP_VGA);
-
wrap_start_dir.val = defWRAP_START_DIR;
wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
@@ -813,21 +787,24 @@ static void w100_hw_init(void)
writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
-}
+ /* Set the hardware to 565 colour */
+ temp32 = readl(remapped_regs + mmDISP_DEBUG2);
+ temp32 &= 0xff7fffff;
+ temp32 |= 0x00800000;
+ writel(temp32, remapped_regs + mmDISP_DEBUG2);
-/*
- * Types
- */
+ /* Initialise the GPIO lines */
+ if (gpio) {
+ writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
+ writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
+ writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
+ writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
+ writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
+ writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
+ }
+}
-struct pll_parm {
- u16 freq; /* desired Fout for PLL */
- u8 M;
- u8 N_int;
- u8 N_fac;
- u8 tfgoal;
- u8 lock_time;
-};
struct power_state {
union clk_pin_cntl_u clk_pin_cntl;
@@ -835,317 +812,275 @@ struct power_state {
union pll_cntl_u pll_cntl;
union sclk_cntl_u sclk_cntl;
union pclk_cntl_u pclk_cntl;
- union clk_test_cntl_u clk_test_cntl;
union pwrmgt_cntl_u pwrmgt_cntl;
- u32 freq; /* Fout for PLL calibration */
- u8 tf100; /* for pll calibration */
- u8 tf80; /* for pll calibration */
- u8 tf20; /* for pll calibration */
- u8 M; /* for pll calibration */
- u8 N_int; /* for pll calibration */
- u8 N_fac; /* for pll calibration */
- u8 lock_time; /* for pll calibration */
- u8 tfgoal; /* for pll calibration */
- u8 auto_mode; /* hardware auto switch? */
- u8 pwm_mode; /* 0 fast, 1 normal/slow */
- u16 fast_sclk; /* fast clk freq */
- u16 norm_sclk; /* slow clk freq */
+ int auto_mode; /* system clock auto changing? */
};
-/*
- * Global state variables
- */
-
static struct power_state w100_pwr_state;
-/* This table is specific for 12.5MHz ref crystal. */
-static struct pll_parm gPLLTable[] = {
- /*freq M N_int N_fac tfgoal lock_time */
- { 50, 0, 1, 0, 0xE0, 56}, /* 50.00 MHz */
- { 75, 0, 5, 0, 0xDE, 37}, /* 75.00 MHz */
- {100, 0, 7, 0, 0xE0, 28}, /* 100.00 MHz */
- {125, 0, 9, 0, 0xE0, 22}, /* 125.00 MHz */
- {150, 0, 11, 0, 0xE0, 17}, /* 150.00 MHz */
- { 0, 0, 0, 0, 0, 0} /* Terminator */
+/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
+
+/* 12.5MHz Crystal PLL Table */
+static struct w100_pll_info xtal_12500000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
+ { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
+ {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
+ {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
+ {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
+ { 0, 0, 0, 0, 0, 0}, /* Terminator */
};
+/* 14.318MHz Crystal PLL Table */
+static struct w100_pll_info xtal_14318000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
+ { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
+ { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
+ { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
+ {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
+ { 0, 0, 0, 0, 0, 0},
+};
-static u8 w100_pll_get_testcount(u8 testclk_sel)
+/* 16MHz Crystal PLL Table */
+static struct w100_pll_info xtal_16000000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
+ { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
+ { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
+ { 0, 0, 0, 0, 0, 0},
+};
+
+static struct pll_entries {
+ int xtal_freq;
+ struct w100_pll_info *pll_table;
+} w100_pll_tables[] = {
+ { 12500000, &xtal_12500000[0] },
+ { 14318000, &xtal_14318000[0] },
+ { 16000000, &xtal_16000000[0] },
+ { 0 },
+};
+
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
{
+ struct pll_entries *pll_entry = w100_pll_tables;
+
+ do {
+ if (freq == pll_entry->xtal_freq)
+ return pll_entry->pll_table;
+ pll_entry++;
+ } while (pll_entry->xtal_freq);
+ return 0;
+}
+
+
+static unsigned int w100_get_testcount(unsigned int testclk_sel)
+{
+ union clk_test_cntl_u clk_test_cntl;
+
udelay(5);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- w100_pwr_state.clk_test_cntl.f.testclk_sel = testclk_sel;
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x1; /*reset test count */
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Select the test clock source and reset */
+ clk_test_cntl.f.start_check_freq = 0x0;
+ clk_test_cntl.f.testclk_sel = testclk_sel;
+ clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x1;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Run clock test */
+ clk_test_cntl.f.start_check_freq = 0x1;
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+ /* Give the test time to complete */
udelay(20);
- w100_pwr_state.clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Return the result */
+ clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
+ clk_test_cntl.f.start_check_freq = 0x0;
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- return w100_pwr_state.clk_test_cntl.f.test_count;
+ return clk_test_cntl.f.test_count;
}
-static u8 w100_pll_adjust(void)
+static int w100_pll_adjust(struct w100_pll_info *pll)
{
+ unsigned int tf80;
+ unsigned int tf20;
+
+ /* Initial Settings */
+ w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
+ w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
+ w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
+ w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
+ w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
+ w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
+ w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
+
+ /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
+ * therefore, commented out the following lines
+ * tf80 meant tf100
+ */
do {
- /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
- * therefore, commented out the following lines
- * tf80 meant tf100
- * set VCO input = 0.8 * VDD
- */
+ /* set VCO input = 0.8 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.tf80 = w100_pll_get_testcount(0x1); /* PLLCLK */
- if (w100_pwr_state.tf80 >= (w100_pwr_state.tfgoal)) {
+ tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
+ if (tf80 >= (pll->tfgoal)) {
/* set VCO input = 0.2 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.tf20 = w100_pll_get_testcount(0x1); /* PLLCLK */
- if (w100_pwr_state.tf20 <= (w100_pwr_state.tfgoal))
- return 1; // Success
+ tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
+ if (tf20 <= (pll->tfgoal))
+ return 1; /* Success */
if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
- ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
- (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
+ ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
+ (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
/* slow VCO config */
w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
- writel((u32) (w100_pwr_state.pll_cntl.val),
- remapped_regs + mmPLL_CNTL);
continue;
}
}
if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- continue;
- }
- if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
+ } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- continue;
+ } else {
+ return 0; /* Error */
}
- return 0; // error
} while(1);
}
/*
* w100_pll_calibration
- * freq = target frequency of the PLL
- * (note: crystal = 14.3MHz)
*/
-static u8 w100_pll_calibration(u32 freq)
+static int w100_pll_calibration(struct w100_pll_info *pll)
{
- u8 status;
-
- /* initial setting */
- w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
- w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
- w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
- w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
- w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
- w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
- w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+ int status;
- /* check for (tf80 >= tfgoal) && (tf20 =< tfgoal) */
- if ((w100_pwr_state.tf80 < w100_pwr_state.tfgoal) || (w100_pwr_state.tf20 > w100_pwr_state.tfgoal)) {
- status=w100_pll_adjust();
- }
- /* PLL Reset And Lock */
+ status = w100_pll_adjust(pll);
+ /* PLL Reset And Lock */
/* set VCO input = 0.5 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* reset time */
- udelay(1);
+ udelay(1); /* reset time */
/* enable charge pump */
- w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
+ w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* set VCO input = Hi-Z */
- /* disable DAC */
+ /* set VCO input = Hi-Z, disable DAC */
w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* lock time */
- udelay(400); /* delay 400 us */
+ udelay(400); /* lock time */
/* PLL locked */
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x1; /* PLL clock */
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
- w100_pwr_state.tf100 = w100_pll_get_testcount(0x1); /* PLLCLK */
-
return status;
}
-static u8 w100_pll_set_clk(void)
+static int w100_pll_set_clk(struct w100_pll_info *pll)
{
- u8 status;
+ int status;
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
+ if (w100_pwr_state.auto_mode == 1) /* auto mode */
{
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
}
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal clock */
+ /* Set system clock source to XTAL whilst adjusting the PLL! */
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = w100_pwr_state.M;
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = w100_pwr_state.N_int;
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = w100_pwr_state.N_fac;
- w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = w100_pwr_state.lock_time;
+ w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
+ w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- status = w100_pll_calibration (w100_pwr_state.freq);
+ status = w100_pll_calibration(pll);
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
+ if (w100_pwr_state.auto_mode == 1) /* auto mode */
{
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
}
return status;
}
-
-/* assume reference crystal clk is 12.5MHz,
- * and that doubling is not enabled.
- *
- * Freq = 12 == 12.5MHz.
- */
-static u16 w100_set_slowsysclk(u16 freq)
-{
- if (w100_pwr_state.norm_sclk == freq)
- return freq;
-
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
- return 0;
-
- if (freq == 12) {
- w100_pwr_state.norm_sclk = freq;
- w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal src */
-
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
- w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x1;
- writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
-
- w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x1;
- w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;
- writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- w100_pwr_state.pwm_mode = 1; /* normal mode */
- return freq;
- } else
- return 0;
-}
-
-
-static u16 w100_set_fastsysclk(u16 freq)
+/* freq = target frequency of the PLL */
+static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
{
- u16 pll_freq;
- int i;
-
- while(1) {
- pll_freq = (u16) (freq * (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast + 1));
- i = 0;
- do {
- if (pll_freq == gPLLTable[i].freq) {
- w100_pwr_state.freq = gPLLTable[i].freq * 1000000;
- w100_pwr_state.M = gPLLTable[i].M;
- w100_pwr_state.N_int = gPLLTable[i].N_int;
- w100_pwr_state.N_fac = gPLLTable[i].N_fac;
- w100_pwr_state.tfgoal = gPLLTable[i].tfgoal;
- w100_pwr_state.lock_time = gPLLTable[i].lock_time;
- w100_pwr_state.tf20 = 0xff; /* set highest */
- w100_pwr_state.tf80 = 0x00; /* set lowest */
-
- w100_pll_set_clk();
- w100_pwr_state.pwm_mode = 0; /* fast mode */
- w100_pwr_state.fast_sclk = freq;
- return freq;
- }
- i++;
- } while(gPLLTable[i].freq);
+ struct w100_pll_info *pll = par->pll_table;
- if (w100_pwr_state.auto_mode == 1)
- break;
-
- if (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast == 0)
- break;
-
- w100_pwr_state.sclk_cntl.f.sclk_post_div_fast -= 1;
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- }
+ do {
+ if (freq == pll->freq) {
+ return w100_pll_set_clk(pll);
+ }
+ pll++;
+ } while(pll->freq);
return 0;
}
-
/* Set up an initial state. Some values/fields set
here will be overwritten. */
-static void w100_pwm_setup(void)
+static void w100_pwm_setup(struct w100fb_par *par)
{
w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
- w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = 0x0; /* no freq doubling */
+ w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* Crystal Clk */
- w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
- w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
- w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x0; /* Crystal Clk */
- w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
- w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
+ w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
+ w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
+ w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
- w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
+ w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
@@ -1154,7 +1089,7 @@ static void w100_pwm_setup(void)
w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
- w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
+ w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
@@ -1164,220 +1099,275 @@ static void w100_pwm_setup(void)
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
- w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
+ w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.clk_test_cntl.f.testclk_sel = 0x1; /* PLLCLK (for testing) */
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
- w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- w100_pwr_state.auto_mode = 0; /* manual mode */
- w100_pwr_state.pwm_mode = 1; /* normal mode (0, 1, 2) */
- w100_pwr_state.freq = 50000000; /* 50 MHz */
- w100_pwr_state.M = 3; /* M = 4 */
- w100_pwr_state.N_int = 6; /* N = 7.0 */
- w100_pwr_state.N_fac = 0;
- w100_pwr_state.tfgoal = 0xE0;
- w100_pwr_state.lock_time = 56;
- w100_pwr_state.tf20 = 0xff; /* set highest */
- w100_pwr_state.tf80 = 0x00; /* set lowest */
- w100_pwr_state.tf100 = 0x00; /* set lowest */
- w100_pwr_state.fast_sclk = 50; /* 50.0 MHz */
- w100_pwr_state.norm_sclk = 12; /* 12.5 MHz */
+ w100_pwr_state.auto_mode = 0; /* manual mode */
}
-static void w100_init_sharp_lcd(u32 mode)
+/*
+ * Setup the w100 clocks for the specified mode
+ */
+static void w100_init_clocks(struct w100fb_par *par)
{
- u32 temp32;
- union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+ struct w100_mode *mode = par->mode;
- /* Prevent display updates */
- disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
- disp_db_buf_wr_cntl.f.update_db_buf = 0;
- disp_db_buf_wr_cntl.f.en_db_buf = 0;
- writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+ if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
+ w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
- switch(mode) {
- case LCD_SHARP_QVGA:
- w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */
- /* not use PLL */
-
- writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- writel(0x85FF8000, remapped_regs + mmMC_FB_LOCATION);
- writel(0x00000003, remapped_regs + mmLCD_FORMAT);
- writel(0x00CF1C06, remapped_regs + mmGRAPHIC_CTRL);
- writel(0x01410145, remapped_regs + mmCRTC_TOTAL);
- writel(0x01170027, remapped_regs + mmACTIVE_H_DISP);
- writel(0x01410001, remapped_regs + mmACTIVE_V_DISP);
- writel(0x01170027, remapped_regs + mmGRAPHIC_H_DISP);
- writel(0x01410001, remapped_regs + mmGRAPHIC_V_DISP);
- writel(0x81170027, remapped_regs + mmCRTC_SS);
- writel(0xA0140000, remapped_regs + mmCRTC_LS);
- writel(0x00400008, remapped_regs + mmCRTC_REV);
- writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
- writel(0xC0140014, remapped_regs + mmCRTC_GS);
- writel(0x00010141, remapped_regs + mmCRTC_VPOS_GS);
- writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
- writel(0x80100110, remapped_regs + mmCRTC_GOE);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
- writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
- writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
- writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
- writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
- writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
- writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
- writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
- writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
- writel(0x000001e0, remapped_regs + mmGRAPHIC_PITCH);
- writel(0x000000bf, remapped_regs + mmGPIO_DATA);
- writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
- writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
- writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
- break;
- case LCD_SHARP_VGA:
- w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */
- w100_set_fastsysclk(current_par->fastsysclk_mode); /* use PLL -- 75.0MHz */
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
- w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x2;
- writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
- writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
- writel(0x9FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- writel(0x00000003, remapped_regs + mmLCD_FORMAT);
- writel(0x00DE1D66, remapped_regs + mmGRAPHIC_CTRL);
-
- writel(0x0283028B, remapped_regs + mmCRTC_TOTAL);
- writel(0x02360056, remapped_regs + mmACTIVE_H_DISP);
- writel(0x02830003, remapped_regs + mmACTIVE_V_DISP);
- writel(0x02360056, remapped_regs + mmGRAPHIC_H_DISP);
- writel(0x02830003, remapped_regs + mmGRAPHIC_V_DISP);
- writel(0x82360056, remapped_regs + mmCRTC_SS);
- writel(0xA0280000, remapped_regs + mmCRTC_LS);
- writel(0x00400008, remapped_regs + mmCRTC_REV);
- writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
- writel(0x80280028, remapped_regs + mmCRTC_GS);
- writel(0x02830002, remapped_regs + mmCRTC_VPOS_GS);
- writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
- writel(0x80100110, remapped_regs + mmCRTC_GOE);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
- writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
- writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
- writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
- writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
- writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
- writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
- writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
- writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
- writel(0x000003C0, remapped_regs + mmGRAPHIC_PITCH);
- writel(0x000000bf, remapped_regs + mmGPIO_DATA);
- writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
- writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
- writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
- break;
- default:
- break;
- }
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
+ writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+}
+
+static void w100_init_lcd(struct w100fb_par *par)
+{
+ u32 temp32;
+ struct w100_mode *mode = par->mode;
+ struct w100_gen_regs *regs = par->mach->regs;
+ union active_h_disp_u active_h_disp;
+ union active_v_disp_u active_v_disp;
+ union graphic_h_disp_u graphic_h_disp;
+ union graphic_v_disp_u graphic_v_disp;
+ union crtc_total_u crtc_total;
+
+ /* w3200 doesnt like undefined bits being set so zero register values first */
+
+ active_h_disp.val = 0;
+ active_h_disp.f.active_h_start=mode->left_margin;
+ active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
+ writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
+
+ active_v_disp.val = 0;
+ active_v_disp.f.active_v_start=mode->upper_margin;
+ active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
+ writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
+
+ graphic_h_disp.val = 0;
+ graphic_h_disp.f.graphic_h_start=mode->left_margin;
+ graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
+ writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
+
+ graphic_v_disp.val = 0;
+ graphic_v_disp.f.graphic_v_start=mode->upper_margin;
+ graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
+ writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
+
+ crtc_total.val = 0;
+ crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
+ crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
+ writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
+
+ writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
+ writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
+ writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
+ writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
+ writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
+ writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
+ writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
+ writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
+ writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
+
+ writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
+ writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
+ writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
+ writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
+ writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
+ writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
+
+ writel(0x00000000, remapped_regs + mmCRTC_FRAME);
+ writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
+ writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
+ writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
/* Hack for overlay in ext memory */
temp32 = readl(remapped_regs + mmDISP_DEBUG2);
temp32 |= 0xc0000000;
writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
- /* Re-enable display updates */
- disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
- disp_db_buf_wr_cntl.f.update_db_buf = 1;
- disp_db_buf_wr_cntl.f.en_db_buf = 1;
- writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
}
-static void w100_set_vga_rotation_regs(u16 divider, unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_setup_memory(struct w100fb_par *par)
{
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
- w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
- writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+ union mc_ext_mem_location_u extmem_location;
+ union mc_fb_location_u intmem_location;
+ struct w100_mem_info *mem = par->mach->mem;
+ struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
- writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
- writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
- writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+ if (!par->extmem_active) {
+ w100_suspend(W100_SUSPEND_EXTMEM);
- /* Re-enable display updates */
- writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
-}
+ /* Map Internal Memory at FB Base */
+ intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
+ intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
+ writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
+ /* Unmap External Memory - value is *probably* irrelevant but may have meaning
+ to acceleration libraries */
+ extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
+ extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
+ writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+ } else {
+ /* Map Internal Memory to its default location */
+ intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
+ intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
+ writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
-static void w100_init_vga_rotation(u16 deg)
-{
- switch(deg) {
- case 0:
- w100_set_vga_rotation_regs(0x02, 0x00DE1D66, 0x00800000, 0x000003c0);
- break;
- case 90:
- w100_set_vga_rotation_regs(0x06, 0x00DE1D0e, 0x00895b00, 0x00000500);
- break;
- case 180:
- w100_set_vga_rotation_regs(0x02, 0x00DE1D7e, 0x00895ffc, 0x000003c0);
- break;
- case 270:
- w100_set_vga_rotation_regs(0x06, 0x00DE1D16, 0x008004fc, 0x00000500);
- break;
- default:
- /* not-support */
- break;
+ /* Map External Memory at FB Base */
+ extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
+ extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
+ writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+
+ writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
+ writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
+ writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
+ writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
+ if (bm_mem) {
+ writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
+ writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
+ writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
+ writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
+ writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
+ writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
+ writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
+ }
}
}
-
-static void w100_set_qvga_rotation_regs(unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_set_dispregs(struct w100fb_par *par)
{
- writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
- writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
- writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+ unsigned long rot=0, divider, offset=0;
+ union graphic_ctrl_u graphic_ctrl;
+
+ /* See if the mode has been rotated */
+ if (par->xres == par->mode->xres) {
+ if (par->flip) {
+ rot=3; /* 180 degree */
+ offset=(par->xres * par->yres) - 1;
+ } /* else 0 degree */
+ divider = par->mode->pixclk_divider;
+ } else {
+ if (par->flip) {
+ rot=2; /* 270 degree */
+ offset=par->xres - 1;
+ } else {
+ rot=1; /* 90 degree */
+ offset=par->xres * (par->yres - 1);
+ }
+ divider = par->mode->pixclk_divider_rotated;
+ }
- /* Re-enable display updates */
- writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
+ graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
+ switch (par->chip_id) {
+ case CHIP_ID_W100:
+ graphic_ctrl.f_w100.color_depth=6;
+ graphic_ctrl.f_w100.en_crtc=1;
+ graphic_ctrl.f_w100.en_graphic_req=1;
+ graphic_ctrl.f_w100.en_graphic_crtc=1;
+ graphic_ctrl.f_w100.lcd_pclk_on=1;
+ graphic_ctrl.f_w100.lcd_sclk_on=1;
+ graphic_ctrl.f_w100.low_power_on=0;
+ graphic_ctrl.f_w100.req_freq=0;
+ graphic_ctrl.f_w100.portrait_mode=rot;
+
+ /* Zaurus needs this */
+ switch(par->xres) {
+ case 240:
+ case 320:
+ default:
+ graphic_ctrl.f_w100.total_req_graphic=0xa0;
+ break;
+ case 480:
+ case 640:
+ switch(rot) {
+ case 0: /* 0 */
+ case 3: /* 180 */
+ graphic_ctrl.f_w100.low_power_on=1;
+ graphic_ctrl.f_w100.req_freq=5;
+ break;
+ case 1: /* 90 */
+ case 2: /* 270 */
+ graphic_ctrl.f_w100.req_freq=4;
+ break;
+ default:
+ break;
+ }
+ graphic_ctrl.f_w100.total_req_graphic=0xf0;
+ break;
+ }
+ break;
+ case CHIP_ID_W3200:
+ case CHIP_ID_W3220:
+ graphic_ctrl.f_w32xx.color_depth=6;
+ graphic_ctrl.f_w32xx.en_crtc=1;
+ graphic_ctrl.f_w32xx.en_graphic_req=1;
+ graphic_ctrl.f_w32xx.en_graphic_crtc=1;
+ graphic_ctrl.f_w32xx.lcd_pclk_on=1;
+ graphic_ctrl.f_w32xx.lcd_sclk_on=1;
+ graphic_ctrl.f_w32xx.low_power_on=0;
+ graphic_ctrl.f_w32xx.req_freq=0;
+ graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
+ graphic_ctrl.f_w32xx.portrait_mode=rot;
+ break;
+ }
+
+ /* Set the pixel clock source and divider */
+ w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
+ w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
+ writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+
+ writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
+ writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
+ writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
}
-static void w100_init_qvga_rotation(u16 deg)
+/*
+ * Work out how long the sync pulse lasts
+ * Value is 1/(time in seconds)
+ */
+static void calc_hsync(struct w100fb_par *par)
{
- switch(deg) {
- case 0:
- w100_set_qvga_rotation_regs(0x00d41c06, 0x00800000, 0x000001e0);
- break;
- case 90:
- w100_set_qvga_rotation_regs(0x00d41c0E, 0x00825580, 0x00000280);
- break;
- case 180:
- w100_set_qvga_rotation_regs(0x00d41c1e, 0x008257fc, 0x000001e0);
- break;
- case 270:
- w100_set_qvga_rotation_regs(0x00d41c16, 0x0080027c, 0x00000280);
- break;
- default:
- /* not-support */
- break;
- }
-}
+ unsigned long hsync;
+ struct w100_mode *mode = par->mode;
+ union crtc_ss_u crtc_ss;
+
+ if (mode->pixclk_src == CLK_SRC_XTAL)
+ hsync=par->mach->xtal_freq;
+ else
+ hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
+ hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
+
+ crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
+ if (crtc_ss.val)
+ par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
+ else
+ par->hsync_len = 0;
+}
static void w100_suspend(u32 mode)
{
@@ -1387,30 +1377,28 @@ static void w100_suspend(u32 mode)
writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
- val &= ~(0x00100000); /* bit20=0 */
- val |= 0xFF000000; /* bit31:24=0xff */
+ val &= ~(0x00100000); /* bit20=0 */
+ val |= 0xFF000000; /* bit31:24=0xff */
writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val &= ~(0x00040000); /* bit18=0 */
- val |= 0x00080000; /* bit19=1 */
+ val &= ~(0x00040000); /* bit18=0 */
+ val |= 0x00080000; /* bit19=1 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
- udelay(1); /* wait 1us */
+ udelay(1); /* wait 1us */
if (mode == W100_SUSPEND_EXTMEM) {
-
/* CKE: Tri-State */
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val |= 0x40000000; /* bit30=1 */
+ val |= 0x40000000; /* bit30=1 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
/* CLK: Stop */
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val &= ~(0x00000001); /* bit0=0 */
+ val &= ~(0x00000001); /* bit0=0 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
} else {
-
writel(0x00000000, remapped_regs + mmSCLK_CNTL);
writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
@@ -1418,43 +1406,16 @@ static void w100_suspend(u32 mode)
udelay(5);
val = readl(remapped_regs + mmPLL_CNTL);
- val |= 0x00000004; /* bit2=1 */
+ val |= 0x00000004; /* bit2=1 */
writel(val, remapped_regs + mmPLL_CNTL);
writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
}
}
-
-static void w100_resume(void)
-{
- u32 temp32;
-
- w100_hw_init();
- w100_pwm_setup();
-
- temp32 = readl(remapped_regs + mmDISP_DEBUG2);
- temp32 &= 0xff7fffff;
- temp32 |= 0x00800000;
- writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
- if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- if (current_par->lcdMode == LCD_MODE_640) {
- w100_init_vga_rotation(current_par->rotation_flag ? 270 : 90);
- }
- } else {
- w100_init_sharp_lcd(LCD_SHARP_QVGA);
- if (current_par->lcdMode == LCD_MODE_320) {
- w100_init_qvga_rotation(current_par->rotation_flag ? 270 : 90);
- }
- }
-}
-
-
static void w100_vsync(void)
{
u32 tmp;
- int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
+ int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
tmp = readl(remapped_regs + mmACTIVE_V_DISP);
@@ -1490,363 +1451,6 @@ static void w100_vsync(void)
writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
}
-
-static void w100_InitExtMem(u32 mode)
-{
- switch(mode) {
- case LCD_SHARP_QVGA:
- /* QVGA doesn't use external memory
- nothing to do, really. */
- break;
- case LCD_SHARP_VGA:
- writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
- writel(0x00040003, remapped_regs + mmMEM_EXT_CNTL);
- writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x00650021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x10002a4a, remapped_regs + mmMEM_EXT_TIMING_CNTL);
- writel(0x7ff87012, remapped_regs + mmMEM_IO_CNTL);
- break;
- default:
- break;
- }
-}
-
-
-#define RESCTL_ADRS 0x00
-#define PHACTRL_ADRS 0x01
-#define DUTYCTRL_ADRS 0x02
-#define POWERREG0_ADRS 0x03
-#define POWERREG1_ADRS 0x04
-#define GPOR3_ADRS 0x05
-#define PICTRL_ADRS 0x06
-#define POLCTRL_ADRS 0x07
-
-#define RESCTL_QVGA 0x01
-#define RESCTL_VGA 0x00
-
-#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
-#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
-#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
-
-#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
-#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
-#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
-
-#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
-#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
-#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
-#define POWER0_COM_ON 0x08 /* COM Powewr Supply ON */
-#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
-
-#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
-#define POWER0_COM_OFF 0x00 /* COM Powewr Supply OFF */
-#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
-
-#define PICTRL_INIT_STATE 0x01
-#define PICTRL_INIOFF 0x02
-#define PICTRL_POWER_DOWN 0x04
-#define PICTRL_COM_SIGNAL_OFF 0x08
-#define PICTRL_DAC_SIGNAL_OFF 0x10
-
-#define PICTRL_POWER_ACTIVE (0)
-
-#define POLCTRL_SYNC_POL_FALL 0x01
-#define POLCTRL_EN_POL_FALL 0x02
-#define POLCTRL_DATA_POL_FALL 0x04
-#define POLCTRL_SYNC_ACT_H 0x08
-#define POLCTRL_EN_ACT_L 0x10
-
-#define POLCTRL_SYNC_POL_RISE 0x00
-#define POLCTRL_EN_POL_RISE 0x00
-#define POLCTRL_DATA_POL_RISE 0x00
-#define POLCTRL_SYNC_ACT_L 0x00
-#define POLCTRL_EN_ACT_H 0x00
-
-#define PHACTRL_PHASE_MANUAL 0x01
-
-#define PHAD_QVGA_DEFAULT_VAL (9)
-#define COMADJ_DEFAULT (125)
-
-static void lcdtg_ssp_send(u8 adrs, u8 data)
-{
- w100fb_ssp_send(adrs,data);
-}
-
-/*
- * This is only a psuedo I2C interface. We can't use the standard kernel
- * routines as the interface is write only. We just assume the data is acked...
- */
-static void lcdtg_ssp_i2c_send(u8 data)
-{
- lcdtg_ssp_send(POWERREG0_ADRS, data);
- udelay(10);
-}
-
-static void lcdtg_i2c_send_bit(u8 data)
-{
- lcdtg_ssp_i2c_send(data);
- lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(data);
-}
-
-static void lcdtg_i2c_send_start(u8 base)
-{
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(base);
-}
-
-static void lcdtg_i2c_send_stop(u8 base)
-{
- lcdtg_ssp_i2c_send(base);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
-}
-
-static void lcdtg_i2c_send_byte(u8 base, u8 data)
-{
- int i;
- for (i = 0; i < 8; i++) {
- if (data & 0x80)
- lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
- else
- lcdtg_i2c_send_bit(base);
- data <<= 1;
- }
-}
-
-static void lcdtg_i2c_wait_ack(u8 base)
-{
- lcdtg_i2c_send_bit(base);
-}
-
-static void lcdtg_set_common_voltage(u8 base_data, u8 data)
-{
- /* Set Common Voltage to M62332FP via I2C */
- lcdtg_i2c_send_start(base_data);
- lcdtg_i2c_send_byte(base_data, 0x9c);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_byte(base_data, 0x00);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_byte(base_data, data);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_stop(base_data);
-}
-
-static struct lcdtg_register_setting {
- u8 adrs;
- u8 data;
- u32 wait;
-} lcdtg_power_on_table[] = {
-
- /* Initialize Internal Logic & Port */
- { PICTRL_ADRS,
- PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE |
- PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF,
- 0 },
-
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | POWER0_COM_OFF |
- POWER0_VCC5_OFF,
- 0 },
-
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF,
- 0 },
-
- /* VDD(+8V),SVSS(-4V) ON */
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON /* VDD ON */,
- 3000 },
-
- /* DAC ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_OFF | POWER0_VCC5_OFF,
- 0 },
-
- /* INIB = H, INI = L */
- { PICTRL_ADRS,
- /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
- PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF,
- 0 },
-
- /* Set Common Voltage */
- { 0xfe, 0, 0 },
-
- /* VCC5 ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_OFF | POWER0_VCC5_ON /* VCC5 ON */,
- 0 },
-
- /* GVSS(-8V) ON */
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_ON /* GVSS ON */ |
- POWER1_VDD_ON /* VDD ON */,
- 2000 },
-
- /* COM SIGNAL ON (PICTL[3] = L) */
- { PICTRL_ADRS,
- PICTRL_INIT_STATE,
- 0 },
-
- /* COM ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_ON /* COM ON */ | POWER0_VCC5_ON /* VCC5_ON */,
- 0 },
-
- /* VW ON */
- { POWERREG1_ADRS,
- POWER1_VW_ON /* VW ON */ | POWER1_GVSS_ON /* GVSS ON */ |
- POWER1_VDD_ON /* VDD ON */,
- 0 /* Wait 100ms */ },
-
- /* Signals output enable */
- { PICTRL_ADRS,
- 0 /* Signals output enable */,
- 0 },
-
- { PHACTRL_ADRS,
- PHACTRL_PHASE_MANUAL,
- 0 },
-
- /* Initialize for Input Signals from ATI */
- { POLCTRL_ADRS,
- POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | POLCTRL_DATA_POL_RISE |
- POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H,
- 1000 /*100000*/ /* Wait 100ms */ },
-
- /* end mark */
- { 0xff, 0, 0 }
-};
-
-static void lcdtg_resume(void)
-{
- if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
- lcdtg_hw_init(LCD_SHARP_VGA);
- } else {
- lcdtg_hw_init(LCD_SHARP_QVGA);
- }
-}
-
-static void lcdtg_suspend(void)
-{
- int i;
-
- for (i = 0; i < (current_par->xres * current_par->yres); i++) {
- writew(0xffff, remapped_fbuf + (2*i));
- }
-
- /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
- mdelay(34);
-
- /* (1)VW OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
-
- /* (2)COM OFF */
- lcdtg_ssp_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
-
- /* (3)Set Common Voltage Bias 0V */
- lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
-
- /* (4)GVSS OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
-
- /* (5)VCC5 OFF */
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
- /* (6)Set PDWN, INIOFF, DACOFF */
- lcdtg_ssp_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
- PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
-
- /* (7)DAC OFF */
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
- /* (8)VDD OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
-
-}
-
-static void lcdtg_set_phadadj(u32 mode)
-{
- int adj;
-
- if (mode == LCD_SHARP_VGA) {
- /* Setting for VGA */
- adj = current_par->phadadj;
- if (adj < 0) {
- adj = PHACTRL_PHASE_MANUAL;
- } else {
- adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
- }
- } else {
- /* Setting for QVGA */
- adj = (PHAD_QVGA_DEFAULT_VAL << 1) | PHACTRL_PHASE_MANUAL;
- }
- lcdtg_ssp_send(PHACTRL_ADRS, adj);
-}
-
-static void lcdtg_hw_init(u32 mode)
-{
- int i;
- int comadj;
-
- i = 0;
- while(lcdtg_power_on_table[i].adrs != 0xff) {
- if (lcdtg_power_on_table[i].adrs == 0xfe) {
- /* Set Common Voltage */
- comadj = current_par->comadj;
- if (comadj < 0) {
- comadj = COMADJ_DEFAULT;
- }
- lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
- } else if (lcdtg_power_on_table[i].adrs == PHACTRL_ADRS) {
- /* Set Phase Adjuct */
- lcdtg_set_phadadj(mode);
- } else {
- /* Other */
- lcdtg_ssp_send(lcdtg_power_on_table[i].adrs, lcdtg_power_on_table[i].data);
- }
- if (lcdtg_power_on_table[i].wait != 0)
- udelay(lcdtg_power_on_table[i].wait);
- i++;
- }
-
- switch(mode) {
- case LCD_SHARP_QVGA:
- /* Set Lcd Resolution (QVGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
- break;
- case LCD_SHARP_VGA:
- /* Set Lcd Resolution (VGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
- break;
- default:
- break;
- }
-}
-
-static void lcdtg_lcd_change(u32 mode)
-{
- /* Set Phase Adjuct */
- lcdtg_set_phadadj(mode);
-
- if (mode == LCD_SHARP_VGA)
- /* Set Lcd Resolution (VGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
- else if (mode == LCD_SHARP_QVGA)
- /* Set Lcd Resolution (QVGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
-}
-
-
static struct device_driver w100fb_driver = {
.name = "w100fb",
.bus = &platform_bus_type,
@@ -1870,4 +1474,4 @@ module_init(w100fb_init);
module_exit(w100fb_cleanup);
MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h
index 41624f961237..7a58a1e3e427 100644
--- a/drivers/video/w100fb.h
+++ b/drivers/video/w100fb.h
@@ -5,9 +5,12 @@
*
* Copyright (C) 2002, ATI Corp.
* Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
*
* Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
+ * w32xx support by Ian Molton
+ *
* 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.
@@ -19,7 +22,7 @@
/* Block CIF Start: */
#define mmCHIP_ID 0x0000
-#define mmREVISION_ID 0x0004
+#define mmREVISION_ID 0x0004
#define mmWRAP_BUF_A 0x0008
#define mmWRAP_BUF_B 0x000C
#define mmWRAP_TOP_DIR 0x0010
@@ -88,7 +91,7 @@
#define mmDISP_DEBUG 0x04D4
#define mmDISP_DB_BUF_CNTL 0x04D8
#define mmDISP_CRC_SIG 0x04DC
-#define mmCRTC_DEFAULT_COUNT 0x04E0
+#define mmCRTC_DEFAULT_COUNT 0x04E0
#define mmLCD_BACKGROUND_COLOR 0x04E4
#define mmCRTC_PS2 0x04E8
#define mmCRTC_PS2_VPOS 0x04EC
@@ -119,17 +122,17 @@
/* Block DISPLAY End: */
/* Block GFX Start: */
-#define mmBRUSH_OFFSET 0x108C
-#define mmBRUSH_Y_X 0x1074
-#define mmDEFAULT_PITCH_OFFSET 0x10A0
-#define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8
-#define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC
-#define mmGLOBAL_ALPHA 0x1210
-#define mmFILTER_COEF 0x1214
-#define mmMVC_CNTL_START 0x11E0
-#define mmE2_ARITHMETIC_CNTL 0x1220
-#define mmENG_CNTL 0x13E8
-#define mmENG_PERF_CNT 0x13F0
+#define mmBRUSH_OFFSET 0x108C
+#define mmBRUSH_Y_X 0x1074
+#define mmDEFAULT_PITCH_OFFSET 0x10A0
+#define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8
+#define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC
+#define mmGLOBAL_ALPHA 0x1210
+#define mmFILTER_COEF 0x1214
+#define mmMVC_CNTL_START 0x11E0
+#define mmE2_ARITHMETIC_CNTL 0x1220
+#define mmENG_CNTL 0x13E8
+#define mmENG_PERF_CNT 0x13F0
/* Block GFX End: */
/* Block IDCT Start: */
@@ -141,22 +144,38 @@
/* Block IDCT End: */
/* Block MC Start: */
-#define mmMEM_CNTL 0x0180
-#define mmMEM_ARB 0x0184
-#define mmMC_FB_LOCATION 0x0188
-#define mmMEM_EXT_CNTL 0x018C
-#define mmMC_EXT_MEM_LOCATION 0x0190
-#define mmMEM_EXT_TIMING_CNTL 0x0194
-#define mmMEM_SDRAM_MODE_REG 0x0198
-#define mmMEM_IO_CNTL 0x019C
-#define mmMC_DEBUG 0x01A0
-#define mmMC_BIST_CTRL 0x01A4
-#define mmMC_BIST_COLLAR_READ 0x01A8
-#define mmTC_MISMATCH 0x01AC
-#define mmMC_PERF_MON_CNTL 0x01B0
-#define mmMC_PERF_COUNTERS 0x01B4
+#define mmMEM_CNTL 0x0180
+#define mmMEM_ARB 0x0184
+#define mmMC_FB_LOCATION 0x0188
+#define mmMEM_EXT_CNTL 0x018C
+#define mmMC_EXT_MEM_LOCATION 0x0190
+#define mmMEM_EXT_TIMING_CNTL 0x0194
+#define mmMEM_SDRAM_MODE_REG 0x0198
+#define mmMEM_IO_CNTL 0x019C
+#define mmMC_DEBUG 0x01A0
+#define mmMC_BIST_CTRL 0x01A4
+#define mmMC_BIST_COLLAR_READ 0x01A8
+#define mmTC_MISMATCH 0x01AC
+#define mmMC_PERF_MON_CNTL 0x01B0
+#define mmMC_PERF_COUNTERS 0x01B4
/* Block MC End: */
+/* Block BM Start: */
+#define mmBM_EXT_MEM_BANDWIDTH 0x0A00
+#define mmBM_OFFSET 0x0A04
+#define mmBM_MEM_EXT_TIMING_CNTL 0x0A08
+#define mmBM_MEM_EXT_CNTL 0x0A0C
+#define mmBM_MEM_MODE_REG 0x0A10
+#define mmBM_MEM_IO_CNTL 0x0A18
+#define mmBM_CONFIG 0x0A1C
+#define mmBM_STATUS 0x0A20
+#define mmBM_DEBUG 0x0A24
+#define mmBM_PERF_MON_CNTL 0x0A28
+#define mmBM_PERF_COUNTERS 0x0A2C
+#define mmBM_PERF2_MON_CNTL 0x0A30
+#define mmBM_PERF2_COUNTERS 0x0A34
+/* Block BM End: */
+
/* Block RBBM Start: */
#define mmWAIT_UNTIL 0x1400
#define mmISYNC_CNTL 0x1404
@@ -176,439 +195,575 @@
/* Block CG End: */
/* default value definitions */
-#define defWRAP_TOP_DIR 0x00000000
-#define defWRAP_START_DIR 0x00000000
-#define defCFGREG_BASE 0x00000000
-#define defCIF_IO 0x000C0902
-#define defINTF_CNTL 0x00000011
-#define defCPU_DEFAULTS 0x00000006
-#define defHW_INT 0x00000000
-#define defMC_EXT_MEM_LOCATION 0x07ff0000
-#define defTC_MISMATCH 0x00000000
+#define defWRAP_TOP_DIR 0x00000000
+#define defWRAP_START_DIR 0x00000000
+#define defCFGREG_BASE 0x00000000
+#define defCIF_IO 0x000C0902
+#define defINTF_CNTL 0x00000011
+#define defCPU_DEFAULTS 0x00000006
+#define defHW_INT 0x00000000
+#define defMC_EXT_MEM_LOCATION 0x07ff0000
+#define defTC_MISMATCH 0x00000000
#define W100_CFG_BASE 0x0
#define W100_CFG_LEN 0x10
#define W100_REG_BASE 0x10000
#define W100_REG_LEN 0x2000
#define MEM_INT_BASE_VALUE 0x100000
-#define MEM_INT_TOP_VALUE_W100 0x15ffff
#define MEM_EXT_BASE_VALUE 0x800000
-#define MEM_EXT_TOP_VALUE 0x9fffff
+#define MEM_INT_SIZE 0x05ffff
+#define MEM_WINDOW_BASE 0x100000
+#define MEM_WINDOW_SIZE 0xf00000
+
#define WRAP_BUF_BASE_VALUE 0x80000
#define WRAP_BUF_TOP_VALUE 0xbffff
+#define CHIP_ID_W100 0x57411002
+#define CHIP_ID_W3200 0x56441002
+#define CHIP_ID_W3220 0x57441002
-/* data structure definitions */
+/* Register structure definitions */
struct wrap_top_dir_t {
- unsigned long top_addr : 23;
- unsigned long : 9;
+ unsigned long top_addr : 23;
+ unsigned long : 9;
} __attribute__((packed));
union wrap_top_dir_u {
- unsigned long val : 32;
- struct wrap_top_dir_t f;
+ unsigned long val : 32;
+ struct wrap_top_dir_t f;
} __attribute__((packed));
struct wrap_start_dir_t {
- unsigned long start_addr : 23;
- unsigned long : 9;
+ unsigned long start_addr : 23;
+ unsigned long : 9;
} __attribute__((packed));
union wrap_start_dir_u {
- unsigned long val : 32;
- struct wrap_start_dir_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union cif_cntl_u {
- unsigned long val : 32;
- struct cif_cntl_t f;
+ unsigned long val : 32;
+ struct cif_cntl_t f;
} __attribute__((packed));
struct cfgreg_base_t {
- unsigned long cfgreg_base : 24;
- unsigned long : 8;
+ unsigned long cfgreg_base : 24;
+ unsigned long : 8;
} __attribute__((packed));
union cfgreg_base_u {
- unsigned long val : 32;
- struct cfgreg_base_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union cif_io_u {
- unsigned long val : 32;
- struct cif_io_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union cif_read_dbg_u {
- unsigned long val : 32;
- struct cif_read_dbg_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union cif_write_dbg_u {
- unsigned long val : 32;
- struct cif_write_dbg_t f;
+ unsigned long val : 32;
+ struct cif_write_dbg_t f;
} __attribute__((packed));
struct intf_cntl_t {
- unsigned char ad_inc_a : 1;
- unsigned char ring_buf_a : 1;
- unsigned char rd_fetch_trigger_a : 1;
- unsigned char rd_data_rdy_a : 1;
- unsigned char ad_inc_b : 1;
- unsigned char ring_buf_b : 1;
- unsigned char rd_fetch_trigger_b : 1;
- unsigned char rd_data_rdy_b : 1;
+ unsigned char ad_inc_a : 1;
+ unsigned char ring_buf_a : 1;
+ unsigned char rd_fetch_trigger_a : 1;
+ unsigned char rd_data_rdy_a : 1;
+ unsigned char ad_inc_b : 1;
+ unsigned char ring_buf_b : 1;
+ unsigned char rd_fetch_trigger_b : 1;
+ unsigned char rd_data_rdy_b : 1;
} __attribute__((packed));
union intf_cntl_u {
- unsigned char val : 8;
- struct intf_cntl_t f;
+ unsigned char val : 8;
+ struct intf_cntl_t f;
} __attribute__((packed));
struct cpu_defaults_t {
- unsigned char unpack_rd_data : 1;
- unsigned char access_ind_addr_a: 1;
- unsigned char access_ind_addr_b: 1;
- unsigned char access_scratch_reg : 1;
- unsigned char pack_wr_data : 1;
- unsigned char transition_size : 1;
- unsigned char en_read_buf_mode : 1;
- unsigned char rd_fetch_scratch : 1;
+ unsigned char unpack_rd_data : 1;
+ unsigned char access_ind_addr_a : 1;
+ unsigned char access_ind_addr_b : 1;
+ unsigned char access_scratch_reg : 1;
+ unsigned char pack_wr_data : 1;
+ unsigned char transition_size : 1;
+ unsigned char en_read_buf_mode : 1;
+ unsigned char rd_fetch_scratch : 1;
} __attribute__((packed));
union cpu_defaults_u {
- unsigned char val : 8;
- struct cpu_defaults_t f;
+ unsigned char val : 8;
+ struct cpu_defaults_t f;
+} __attribute__((packed));
+
+struct crtc_total_t {
+ unsigned long crtc_h_total : 10;
+ unsigned long : 6;
+ unsigned long crtc_v_total : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union crtc_total_u {
+ unsigned long 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;
+} __attribute__((packed));
+
+union crtc_ss_u {
+ unsigned long 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;
+} __attribute__((packed));
+
+union active_h_disp_u {
+ unsigned long 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;
+} __attribute__((packed));
+
+union active_v_disp_u {
+ unsigned long 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;
+} __attribute__((packed));
+
+union graphic_h_disp_u {
+ unsigned long 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;
+} __attribute__((packed));
+
+union graphic_v_disp_u{
+ unsigned long 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;
+} __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;
+} __attribute__((packed));
+
+union graphic_ctrl_u {
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union video_ctrl_u {
- unsigned long val : 32;
- struct video_ctrl_t f;
+ unsigned long 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;
+ unsigned long en_db_buf : 1;
+ unsigned long update_db_buf_done : 1;
+ unsigned long db_buf_cntl : 6;
+ unsigned long : 24;
} __attribute__((packed));
union disp_db_buf_cntl_rd_u {
- unsigned long val : 32;
- struct disp_db_buf_cntl_rd_t f;
+ unsigned long 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;
+ unsigned long en_db_buf : 1;
+ unsigned long update_db_buf : 1;
+ unsigned long db_buf_cntl : 6;
+ unsigned long : 24;
} __attribute__((packed));
union disp_db_buf_cntl_wr_u {
- unsigned long val : 32;
- struct disp_db_buf_cntl_wr_t f;
+ unsigned long 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;
+ unsigned long gamma1 : 8;
+ unsigned long gamma2 : 8;
+ unsigned long gamma3 : 8;
+ unsigned long gamma4 : 8;
} __attribute__((packed));
union gamma_value1_u {
- unsigned long val : 32;
- struct gamma_value1_t f;
+ unsigned long 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;
+ unsigned long gamma5 : 8;
+ unsigned long gamma6 : 8;
+ unsigned long gamma7 : 8;
+ unsigned long gamma8 : 8;
} __attribute__((packed));
union gamma_value2_u {
- unsigned long val : 32;
- struct gamma_value2_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union gamma_slope_u {
- unsigned long val : 32;
- struct gamma_slope_t f;
+ unsigned long 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;
+ unsigned long mc_ext_mem_start : 16;
+ unsigned long mc_ext_mem_top : 16;
} __attribute__((packed));
union mc_ext_mem_location_u {
- unsigned long val : 32;
- struct mc_ext_mem_location_t f;
+ unsigned long 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;
+} __attribute__((packed));
+
+union mc_fb_location_u {
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union clk_pin_cntl_u {
- unsigned long val : 32;
- struct clk_pin_cntl_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union pll_ref_fb_div_u {
- unsigned long val : 32;
- struct pll_ref_fb_div_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union pll_cntl_u {
- unsigned long val : 32;
- struct pll_cntl_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union sclk_cntl_u {
- unsigned long val : 32;
- struct sclk_cntl_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union pclk_cntl_u {
- unsigned long val : 32;
- struct pclk_cntl_t f;
+ unsigned long val : 32;
+ struct pclk_cntl_t f;
} __attribute__((packed));
+
+#define TESTCLK_SRC_PLL 0x01
+#define TESTCLK_SRC_SCLK 0x02
+#define TESTCLK_SRC_PCLK 0x03
+/* 4 and 5 seem to by XTAL/M */
+#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;
+ 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;
} __attribute__((packed));
union clk_test_cntl_u {
- unsigned long val : 32;
- struct clk_test_cntl_t f;
+ unsigned long 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;
+ 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;
} __attribute__((packed));
union pwrmgt_cntl_u {
- unsigned long val : 32;
- struct pwrmgt_cntl_t f;
+ unsigned long val : 32;
+ struct pwrmgt_cntl_t f;
} __attribute__((packed));
#endif
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 711b90903e7b..9a1e00dd3e02 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -54,4 +54,20 @@ config W1_SMEM
Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+config W1_DS2433
+ tristate "4kb EEPROM family support (DS2433)"
+ depends on W1
+ help
+ Say Y here if you want to use a 1-wire
+ 4kb EEPROM family device (DS2433).
+
+config W1_DS2433_CRC
+ bool "Protect DS2433 data with a CRC16"
+ depends on W1_DS2433
+ select CRC16
+ help
+ Say Y here to protect DS2433 data with a CRC16.
+ Each block has 30 bytes of data and a two byte CRC16.
+ Full block writes are only allowed if the CRC is valid.
+
endmenu
diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile
index 80725c348e70..01fb54391470 100644
--- a/drivers/w1/Makefile
+++ b/drivers/w1/Makefile
@@ -6,6 +6,10 @@ ifneq ($(CONFIG_NET), y)
EXTRA_CFLAGS += -DNETLINK_DISABLED
endif
+ifeq ($(CONFIG_W1_DS2433_CRC), y)
+EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC
+endif
+
obj-$(CONFIG_W1) += wire.o
wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
@@ -13,8 +17,9 @@ obj-$(CONFIG_W1_MATROX) += matrox_w1.o
obj-$(CONFIG_W1_THERM) += w1_therm.o
obj-$(CONFIG_W1_SMEM) += w1_smem.o
-obj-$(CONFIG_W1_DS9490) += ds9490r.o
+obj-$(CONFIG_W1_DS9490) += ds9490r.o
ds9490r-objs := dscore.o
obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
+obj-$(CONFIG_W1_DS2433) += w1_ds2433.o
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
index 7bddd8ac7d7f..a79d16d5666f 100644
--- a/drivers/w1/ds_w1_bridge.c
+++ b/drivers/w1/ds_w1_bridge.c
@@ -1,8 +1,8 @@
/*
- * ds_w1_bridge.c
+ * ds_w1_bridge.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
#include "../w1/w1.h"
#include "../w1/w1_int.h"
#include "dscore.h"
-
+
static struct ds_device *ds_dev;
static struct w1_bus_master *ds_bus_master;
@@ -120,7 +120,7 @@ static u8 ds9490r_reset(unsigned long data)
static int __devinit ds_w1_init(void)
{
int err;
-
+
ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
if (!ds_bus_master) {
printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
@@ -136,14 +136,14 @@ static int __devinit ds_w1_init(void)
memset(ds_bus_master, 0, sizeof(*ds_bus_master));
- ds_bus_master->data = (unsigned long)ds_dev;
- ds_bus_master->touch_bit = &ds9490r_touch_bit;
- ds_bus_master->read_bit = &ds9490r_read_bit;
- ds_bus_master->write_bit = &ds9490r_write_bit;
- ds_bus_master->read_byte = &ds9490r_read_byte;
- ds_bus_master->write_byte = &ds9490r_write_byte;
- ds_bus_master->read_block = &ds9490r_read_block;
- ds_bus_master->write_block = &ds9490r_write_block;
+ ds_bus_master->data = (unsigned long)ds_dev;
+ ds_bus_master->touch_bit = &ds9490r_touch_bit;
+ ds_bus_master->read_bit = &ds9490r_read_bit;
+ ds_bus_master->write_bit = &ds9490r_write_bit;
+ ds_bus_master->read_byte = &ds9490r_read_byte;
+ ds_bus_master->write_byte = &ds9490r_write_byte;
+ ds_bus_master->read_block = &ds9490r_read_block;
+ ds_bus_master->write_block = &ds9490r_write_block;
ds_bus_master->reset_bus = &ds9490r_reset;
err = w1_add_master_device(ds_bus_master);
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index eee6644d33d6..15fb250451e5 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -1,8 +1,8 @@
/*
- * dscore.c
+ * dscore.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,19 +32,16 @@ static struct usb_device_id ds_id_table [] = {
};
MODULE_DEVICE_TABLE(usb, ds_id_table);
-int ds_probe(struct usb_interface *, const struct usb_device_id *);
-void ds_disconnect(struct usb_interface *);
+static int ds_probe(struct usb_interface *, const struct usb_device_id *);
+static void ds_disconnect(struct usb_interface *);
int ds_touch_bit(struct ds_device *, u8, u8 *);
int ds_read_byte(struct ds_device *, u8 *);
int ds_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(struct ds_device *, u8);
-int ds_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
+static int ds_start_pulse(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
@@ -79,11 +76,11 @@ void ds_put_device(struct ds_device *dev)
static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -94,11 +91,11 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
MODE_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -109,11 +106,11 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
COMM_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -126,19 +123,20 @@ static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int of
printk("%45s: %8x\n", str, buf[off]);
}
-int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned char *buf, int size)
+static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+ unsigned char *buf, int size)
{
int count, err;
-
+
memset(st, 0, sizeof(st));
-
+
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
if (err < 0) {
printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
return err;
}
-
+
if (count >= sizeof(*st))
memcpy(st, buf, sizeof(*st));
@@ -149,13 +147,13 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
{
unsigned char buf[64];
int count, err = 0, i;
-
+
memcpy(st, buf, sizeof(*st));
-
+
count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
if (count < 0)
return err;
-
+
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
for (i=0; i<count; ++i)
printk("%02x ", buf[i]);
@@ -199,7 +197,7 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
return err;
}
#endif
-
+
return err;
}
@@ -207,9 +205,9 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{
int count, err;
struct ds_status st;
-
+
count = 0;
- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
buf, size, &count, 1000);
if (err < 0) {
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
@@ -234,7 +232,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
{
int count, err;
-
+
count = 0;
err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
if (err < 0) {
@@ -245,12 +243,14 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
return err;
}
+#if 0
+
int ds_stop_pulse(struct ds_device *dev, int limit)
{
struct ds_status st;
int count = 0, err = 0;
u8 buf[0x20];
-
+
do {
err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
if (err)
@@ -275,7 +275,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)
int ds_detect(struct ds_device *dev, struct ds_status *st)
{
int err;
-
+
err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
if (err)
return err;
@@ -283,11 +283,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
if (err)
return err;
-
+
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
if (err)
return err;
-
+
err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
if (err)
return err;
@@ -297,7 +297,9 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
return err;
}
-int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+#endif /* 0 */
+
+static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
{
u8 buf[0x20];
int err, count = 0;
@@ -305,7 +307,7 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
do {
err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
#if 0
- if (err >= 0) {
+ if (err >= 0) {
int i;
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
for (i=0; i<err; ++i)
@@ -319,10 +321,8 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
ds_recv_status(dev, st);
return -1;
- }
- else {
+ } else
return 0;
- }
}
int ds_reset(struct ds_device *dev, struct ds_status *st)
@@ -345,6 +345,7 @@ int ds_reset(struct ds_device *dev, struct ds_status *st)
return 0;
}
+#if 0
int ds_set_speed(struct ds_device *dev, int speed)
{
int err;
@@ -356,20 +357,21 @@ int ds_set_speed(struct ds_device *dev, int speed)
speed = SPEED_FLEXIBLE;
speed &= 0xff;
-
+
err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
if (err)
return err;
return err;
}
+#endif /* 0 */
-int ds_start_pulse(struct ds_device *dev, int delay)
+static int ds_start_pulse(struct ds_device *dev, int delay)
{
int err;
u8 del = 1 + (u8)(delay >> 4);
struct ds_status st;
-
+
#if 0
err = ds_stop_pulse(dev, 10);
if (err)
@@ -390,7 +392,7 @@ int ds_start_pulse(struct ds_device *dev, int delay)
mdelay(delay);
ds_wait_status(dev, &st);
-
+
return err;
}
@@ -400,7 +402,7 @@ int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
struct ds_status st;
u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
u16 cmd;
-
+
err = ds_send_control(dev, value, 0);
if (err)
return err;
@@ -430,7 +432,7 @@ int ds_write_bit(struct ds_device *dev, u8 bit)
{
int err;
struct ds_status st;
-
+
err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
if (err)
return err;
@@ -445,7 +447,7 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
int err;
struct ds_status st;
u8 rbyte;
-
+
err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
if (err)
return err;
@@ -453,11 +455,11 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
err = ds_wait_status(dev, &st);
if (err)
return err;
-
+
err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
if (err < 0)
return err;
-
+
ds_start_pulse(dev, PULLUP_PULSE_DURATION);
return !(byte == rbyte);
@@ -470,11 +472,11 @@ int ds_read_bit(struct ds_device *dev, u8 *bit)
err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
if (err)
return err;
-
+
err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
if (err)
return err;
-
+
err = ds_recv_data(dev, bit, sizeof(*bit));
if (err < 0)
return err;
@@ -492,7 +494,7 @@ int ds_read_byte(struct ds_device *dev, u8 *byte)
return err;
ds_wait_status(dev, &st);
-
+
err = ds_recv_data(dev, byte, sizeof(*byte));
if (err < 0)
return err;
@@ -509,17 +511,17 @@ int ds_read_block(struct ds_device *dev, u8 *buf, int len)
return -E2BIG;
memset(buf, 0xFF, len);
-
+
err = ds_send_data(dev, buf, len);
if (err < 0)
return err;
-
+
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
if (err)
return err;
ds_wait_status(dev, &st);
-
+
memset(buf, 0x00, len);
err = ds_recv_data(dev, buf, len);
@@ -530,11 +532,11 @@ int ds_write_block(struct ds_device *dev, u8 *buf, int len)
{
int err;
struct ds_status st;
-
+
err = ds_send_data(dev, buf, len);
if (err < 0)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
@@ -548,10 +550,12 @@ int ds_write_block(struct ds_device *dev, u8 *buf, int len)
return err;
ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
+
return !(err == len);
}
+#if 0
+
int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
{
int err;
@@ -559,11 +563,11 @@ int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int condi
struct ds_status st;
memset(buf, 0, sizeof(buf));
-
+
err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
if (err)
return err;
-
+
ds_wait_status(ds_dev, &st);
value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
@@ -589,7 +593,7 @@ int ds_match_access(struct ds_device *dev, u64 init)
err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
if (err)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
@@ -609,11 +613,11 @@ int ds_set_path(struct ds_device *dev, u64 init)
memcpy(buf, &init, 8);
buf[8] = BRANCH_MAIN;
-
+
err = ds_send_data(dev, buf, sizeof(buf));
if (err)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
@@ -625,7 +629,10 @@ int ds_set_path(struct ds_device *dev, u64 init)
return 0;
}
-int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
+#endif /* 0 */
+
+static int ds_probe(struct usb_interface *intf,
+ const struct usb_device_id *udev_id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
@@ -653,7 +660,7 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
return err;
}
-
+
iface_desc = &intf->altsetting[0];
if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
@@ -662,37 +669,37 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
atomic_set(&ds_dev->refcnt, 0);
memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
-
+
/*
- * This loop doesn'd show control 0 endpoint,
+ * This loop doesn'd show control 0 endpoint,
* so we will fill only 1-3 endpoints entry.
*/
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
ds_dev->ep[i+1] = endpoint->bEndpointAddress;
-
+
printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
}
-
+
#if 0
{
int err, i;
u64 buf[3];
u64 init=0xb30000002078ee81ull;
struct ds_status st;
-
+
ds_reset(ds_dev, &st);
err = ds_search(ds_dev, init, buf, 3, 0);
if (err < 0)
return err;
for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]);
-
- printk("Resetting...\n");
+
+ printk("Resetting...\n");
ds_reset(ds_dev, &st);
printk("Setting path for %llx.\n", init);
err = ds_set_path(ds_dev, init);
@@ -707,12 +714,12 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
err = ds_search(ds_dev, init, buf, 3, 0);
printk("ds_search() returned %d\n", err);
-
+
if (err < 0)
return err;
for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]);
-
+
return 0;
}
#endif
@@ -720,10 +727,10 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
return 0;
}
-void ds_disconnect(struct usb_interface *intf)
+static void ds_disconnect(struct usb_interface *intf)
{
struct ds_device *dev;
-
+
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
@@ -740,7 +747,7 @@ void ds_disconnect(struct usb_interface *intf)
ds_dev = NULL;
}
-int ds_init(void)
+static int ds_init(void)
{
int err;
@@ -753,7 +760,7 @@ int ds_init(void)
return 0;
}
-void ds_fini(void)
+static void ds_fini(void)
{
usb_deregister(&ds_driver);
}
@@ -776,8 +783,8 @@ EXPORT_SYMBOL(ds_get_device);
EXPORT_SYMBOL(ds_put_device);
/*
- * This functions can be used for EEPROM programming,
- * when driver will be included into mainline this will
+ * This functions can be used for EEPROM programming,
+ * when driver will be included into mainline this will
* require uncommenting.
*/
#if 0
diff --git a/drivers/w1/dscore.h b/drivers/w1/dscore.h
index 9c767ef4ac24..6cf5671d6ebe 100644
--- a/drivers/w1/dscore.h
+++ b/drivers/w1/dscore.h
@@ -1,8 +1,8 @@
/*
- * dscore.h
+ * dscore.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -122,7 +122,7 @@
struct ds_device
{
- struct usb_device *udev;
+ struct usb_device *udev;
struct usb_interface *intf;
int ep[NUM_EP];
@@ -156,11 +156,7 @@ int ds_read_byte(struct ds_device *, u8 *);
int ds_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(struct ds_device *, u8);
-int ds_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
int ds_write_block(struct ds_device *, u8 *, int);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 0bbf029b1ef1..1b6b74c116a9 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -45,10 +45,12 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
static int w1_timeout = 10;
+static int w1_control_timeout = 1;
int w1_max_slave_count = 10;
int w1_max_slave_ttl = 10;
module_param_named(timeout, w1_timeout, int, 0);
+module_param_named(control_timeout, w1_control_timeout, int, 0);
module_param_named(max_slave_count, w1_max_slave_count, int, 0);
module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
@@ -59,19 +61,6 @@ static pid_t control_thread;
static int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete);
-/* stuff for the default family */
-static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
- return(sprintf(buf, "%s\n", sl->name));
-}
-static struct w1_family_ops w1_default_fops = {
- .rname = &w1_famdefault_read_name,
-};
-static struct w1_family w1_default_family = {
- .fops = &w1_default_fops,
-};
-
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
return 1;
@@ -82,73 +71,116 @@ static int w1_master_probe(struct device *dev)
return -ENODEV;
}
-static int w1_master_remove(struct device *dev)
-{
- return 0;
-}
-
static void w1_master_release(struct device *dev)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
- complete(&md->dev_released);
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
+
+ if (md->nls && md->nls->sk_socket)
+ sock_release(md->nls->sk_socket);
+ memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+ kfree(md);
}
static void w1_slave_release(struct device *dev)
{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
+
+ while (atomic_read(&sl->refcnt)) {
+ dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
+ sl->name, atomic_read(&sl->refcnt));
+ if (msleep_interruptible(1000))
+ flush_signals(current);
+ }
+
+ w1_family_put(sl->family);
+ sl->master->slave_count--;
- complete(&sl->dev_released);
+ complete(&sl->released);
}
-static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "No family registered.\n");
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+
+ return sprintf(buf, "%s\n", sl->name);
}
-static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
- return sprintf(buf, "No family registered.\n");
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+ atomic_inc(&sl->refcnt);
+ if (off > 8) {
+ count = 0;
+ } else {
+ if (off + count > 8)
+ count = 8 - off;
+
+ memcpy(buf, (u8 *)&sl->reg_num, count);
+ }
+ atomic_dec(&sl->refcnt);
+
+ return count;
}
-static struct device_attribute w1_slave_attribute =
- __ATTR(name, S_IRUGO, w1_default_read_name, NULL);
-
-static struct bin_attribute w1_slave_bin_attribute = {
- .attr = {
- .name = "w1_slave",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .size = W1_SLAVE_DATA_SIZE,
- .read = &w1_default_read_bin,
+static struct device_attribute w1_slave_attr_name =
+ __ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
+
+static struct bin_attribute w1_slave_attr_bin_id = {
+ .attr = {
+ .name = "id",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = 8,
+ .read = w1_slave_read_id,
};
+/* Default family */
+static struct w1_family w1_default_family;
+
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
+ .hotplug = w1_hotplug,
};
-struct device_driver w1_driver = {
- .name = "w1_driver",
+struct device_driver w1_master_driver = {
+ .name = "w1_master_driver",
.bus = &w1_bus_type,
.probe = w1_master_probe,
- .remove = w1_master_remove,
};
-struct device w1_device = {
+struct device w1_master_device = {
.parent = NULL,
.bus = &w1_bus_type,
.bus_id = "w1 bus master",
- .driver = &w1_driver,
+ .driver = &w1_master_driver,
.release = &w1_master_release
};
+struct device_driver w1_slave_driver = {
+ .name = "w1_slave_driver",
+ .bus = &w1_bus_type,
+};
+
+struct device w1_slave_device = {
+ .parent = NULL,
+ .bus = &w1_bus_type,
+ .bus_id = "w1 bus slave",
+ .driver = &w1_slave_driver,
+ .release = &w1_slave_release
+};
+
static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible (&md->mutex))
@@ -165,7 +197,7 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
struct device_attribute *attr,
const char * buf, size_t count)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
if (down_interruptible (&md->mutex))
return -EBUSY;
@@ -181,7 +213,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible (&md->mutex))
@@ -196,7 +228,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -217,7 +249,7 @@ static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct devic
static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -231,7 +263,7 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru
static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -245,7 +277,7 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi
static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -259,7 +291,7 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
int c = PAGE_SIZE;
if (down_interruptible(&md->mutex))
@@ -329,12 +361,55 @@ void w1_destroy_master_attributes(struct w1_master *master)
sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}
+#ifdef CONFIG_HOTPLUG
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct w1_master *md = NULL;
+ struct w1_slave *sl = NULL;
+ char *event_owner, *name;
+ int err, cur_index=0, cur_len=0;
+
+ if (dev->driver == &w1_master_driver) {
+ md = container_of(dev, struct w1_master, dev);
+ event_owner = "master";
+ name = md->name;
+ } else if (dev->driver == &w1_slave_driver) {
+ sl = container_of(dev, struct w1_slave, dev);
+ event_owner = "slave";
+ name = sl->name;
+ } else {
+ dev_dbg(dev, "Unknown hotplug event.\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id);
+
+ if (dev->driver != &w1_slave_driver || !sl)
+ return 0;
+
+ err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+ if (err)
+ return err;
+
+ err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+ if (err)
+ return err;
+
+ return 0;
+};
+#else
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ return 0;
+}
+#endif
+
static int __w1_attach_slave_device(struct w1_slave *sl)
{
int err;
sl->dev.parent = &sl->master->dev;
- sl->dev.driver = sl->master->driver;
+ sl->dev.driver = &w1_slave_driver;
sl->dev.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release;
@@ -347,8 +422,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
(unsigned int) sl->reg_num.family,
(unsigned long long) sl->reg_num.id);
- dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
- &sl->dev.bus_id[0]);
+ dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]);
err = device_register(&sl->dev);
if (err < 0) {
@@ -358,36 +432,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
return err;
}
- memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
- memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
-
- sl->attr_bin.read = sl->family->fops->rbin;
- sl->attr_name.show = sl->family->fops->rname;
+ /* Create "name" entry */
+ err = device_create_file(&sl->dev, &w1_slave_attr_name);
+ if (err < 0) {
+ dev_err(&sl->dev,
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
+ goto out_unreg;
+ }
- err = device_create_file(&sl->dev, &sl->attr_name);
+ /* Create "id" entry */
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
if (err < 0) {
dev_err(&sl->dev,
"sysfs file creation for [%s] failed. err=%d\n",
sl->dev.bus_id, err);
- device_unregister(&sl->dev);
- return err;
+ goto out_rem1;
}
- if ( sl->attr_bin.read ) {
- err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
- if (err < 0) {
- dev_err(&sl->dev,
- "sysfs file creation for [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
- device_remove_file(&sl->dev, &sl->attr_name);
- device_unregister(&sl->dev);
- return err;
- }
+ /* if the family driver needs to initialize something... */
+ if (sl->family->fops && sl->family->fops->add_slave &&
+ ((err = sl->family->fops->add_slave(sl)) < 0)) {
+ dev_err(&sl->dev,
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
+ goto out_rem2;
}
list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
return 0;
+
+out_rem2:
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+out_rem1:
+ device_remove_file(&sl->dev, &w1_slave_attr_name);
+out_unreg:
+ device_unregister(&sl->dev);
+ return err;
}
static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
@@ -413,7 +495,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
atomic_set(&sl->refcnt, 0);
- init_completion(&sl->dev_released);
+ init_completion(&sl->released);
spin_lock(&w1_flock);
f = w1_family_registered(rn->family);
@@ -452,28 +534,23 @@ static void w1_slave_detach(struct w1_slave *sl)
{
struct w1_netlink_msg msg;
- dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
-
- while (atomic_read(&sl->refcnt)) {
- printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
- sl->name, atomic_read(&sl->refcnt));
+ dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl);
- if (msleep_interruptible(1000))
- flush_signals(current);
- }
-
- if ( sl->attr_bin.read ) {
- sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
- }
- device_remove_file(&sl->dev, &sl->attr_name);
- device_unregister(&sl->dev);
- w1_family_put(sl->family);
+ list_del(&sl->w1_slave_entry);
- sl->master->slave_count--;
+ if (sl->family->fops && sl->family->fops->remove_slave)
+ sl->family->fops->remove_slave(sl);
memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg);
+
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+ device_remove_file(&sl->dev, &w1_slave_attr_name);
+ device_unregister(&sl->dev);
+
+ wait_for_completion(&sl->released);
+ kfree(sl);
}
static struct w1_master *w1_search_master(unsigned long data)
@@ -500,14 +577,13 @@ void w1_reconnect_slaves(struct w1_family *f)
spin_lock_bh(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+ dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
dev->name, f->fid);
set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
}
spin_unlock_bh(&w1_mlock);
}
-
static void w1_slave_found(unsigned long data, u64 rn)
{
int slave_count;
@@ -646,7 +722,7 @@ static int w1_control(void *data)
have_to_wait = 0;
try_to_freeze();
- msleep_interruptible(w1_timeout * 1000);
+ msleep_interruptible(w1_control_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
@@ -679,33 +755,30 @@ static int w1_control(void *data)
list_del(&dev->w1_master_entry);
spin_unlock_bh(&w1_mlock);
+ down(&dev->mutex);
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
- list_del(&sl->w1_slave_entry);
-
w1_slave_detach(sl);
- kfree(sl);
}
w1_destroy_master_attributes(dev);
+ up(&dev->mutex);
atomic_dec(&dev->refcnt);
continue;
}
if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
- dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+ dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
down(&dev->mutex);
- list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
if (sl->family->fid == W1_FAMILY_DEFAULT) {
struct w1_reg_num rn;
- list_del(&sl->w1_slave_entry);
- w1_slave_detach(sl);
memcpy(&rn, &sl->reg_num, sizeof(rn));
-
- kfree(sl);
+ w1_slave_detach(sl);
w1_attach_slave_device(dev, &rn);
}
}
+ dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name);
clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
up(&dev->mutex);
}
@@ -749,10 +822,7 @@ int w1_process(void *data)
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
- list_del (&sl->w1_slave_entry);
-
- w1_slave_detach (sl);
- kfree (sl);
+ w1_slave_detach(sl);
dev->slave_count--;
} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
@@ -783,7 +853,7 @@ static int w1_init(void)
goto err_out_exit_init;
}
- retval = driver_register(&w1_driver);
+ retval = driver_register(&w1_master_driver);
if (retval) {
printk(KERN_ERR
"Failed to register master driver. err=%d.\n",
@@ -791,18 +861,29 @@ static int w1_init(void)
goto err_out_bus_unregister;
}
+ retval = driver_register(&w1_slave_driver);
+ if (retval) {
+ printk(KERN_ERR
+ "Failed to register master driver. err=%d.\n",
+ retval);
+ goto err_out_master_unregister;
+ }
+
control_thread = kernel_thread(&w1_control, NULL, 0);
if (control_thread < 0) {
printk(KERN_ERR "Failed to create control thread. err=%d\n",
control_thread);
retval = control_thread;
- goto err_out_driver_unregister;
+ goto err_out_slave_unregister;
}
return 0;
-err_out_driver_unregister:
- driver_unregister(&w1_driver);
+err_out_slave_unregister:
+ driver_unregister(&w1_slave_driver);
+
+err_out_master_unregister:
+ driver_unregister(&w1_master_driver);
err_out_bus_unregister:
bus_unregister(&w1_bus_type);
@@ -821,7 +902,8 @@ static void w1_fini(void)
control_needs_exit = 1;
wait_for_completion(&w1_control_complete);
- driver_unregister(&w1_driver);
+ driver_unregister(&w1_slave_driver);
+ driver_unregister(&w1_master_driver);
bus_unregister(&w1_bus_type);
}
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 4f0a986e33e3..d8900780c3bf 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -75,11 +75,9 @@ struct w1_slave
struct w1_master *master;
struct w1_family *family;
+ void *family_data;
struct device dev;
- struct completion dev_released;
-
- struct bin_attribute attr_bin;
- struct device_attribute attr_name;
+ struct completion released;
};
typedef void (* w1_slave_found_callback)(unsigned long, u64);
@@ -179,7 +177,6 @@ struct w1_master
struct device_driver *driver;
struct device dev;
- struct completion dev_released;
struct completion dev_exited;
struct w1_bus_master *bus_master;
@@ -191,6 +188,21 @@ struct w1_master
int w1_create_master_attributes(struct w1_master *);
void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
+static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
+{
+ return container_of(dev, struct w1_slave, dev);
+}
+
+static inline struct w1_slave* kobj_to_w1_slave(struct kobject *kobj)
+{
+ return dev_to_w1_slave(container_of(kobj, struct device, kobj));
+}
+
+static inline struct w1_master* dev_to_w1_master(struct device *dev)
+{
+ return container_of(dev, struct w1_master, dev);
+}
+
#endif /* __KERNEL__ */
#endif /* __W1_H */
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
new file mode 100644
index 000000000000..279e0e0363d6
--- /dev/null
+++ b/drivers/w1/w1_ds2433.c
@@ -0,0 +1,331 @@
+/*
+ * w1_ds2433.c - w1 family 23 (DS2433) driver
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#ifdef CONFIG_W1_F23_CRC
+#include <linux/crc16.h>
+
+#define CRC16_INIT 0
+#define CRC16_VALID 0xb001
+
+#endif
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_int.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
+
+#define W1_EEPROM_SIZE 512
+#define W1_PAGE_COUNT 16
+#define W1_PAGE_SIZE 32
+#define W1_PAGE_BITS 5
+#define W1_PAGE_MASK 0x1F
+
+#define W1_F23_TIME 300
+
+#define W1_F23_READ_EEPROM 0xF0
+#define W1_F23_WRITE_SCRATCH 0x0F
+#define W1_F23_READ_SCRATCH 0xAA
+#define W1_F23_COPY_SCRATCH 0x55
+
+struct w1_f23_data {
+ u8 memory[W1_EEPROM_SIZE];
+ u32 validcrc;
+};
+
+/**
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size)
+{
+ if (off > size)
+ return 0;
+
+ if ((off + count) > size)
+ return (size - off);
+
+ return count;
+}
+
+#ifdef CONFIG_W1_F23_CRC
+static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
+ int block)
+{
+ u8 wrbuf[3];
+ int off = block * W1_PAGE_SIZE;
+
+ if (data->validcrc & (1 << block))
+ return 0;
+
+ if (w1_reset_select_slave(sl)) {
+ data->validcrc = 0;
+ return -EIO;
+ }
+
+ wrbuf[0] = W1_F23_READ_EEPROM;
+ wrbuf[1] = off & 0xff;
+ wrbuf[2] = off >> 8;
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
+
+ /* cache the block if the CRC is valid */
+ if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
+ data->validcrc |= (1 << block);
+
+ return 0;
+}
+#endif /* CONFIG_W1_F23_CRC */
+
+static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+#ifdef CONFIG_W1_F23_CRC
+ struct w1_f23_data *data = sl->family_data;
+ int i, min_page, max_page;
+#else
+ u8 wrbuf[3];
+#endif
+
+ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ if (down_interruptible(&sl->master->mutex)) {
+ count = 0;
+ goto out_dec;
+ }
+
+#ifdef CONFIG_W1_F23_CRC
+
+ min_page = (off >> W1_PAGE_BITS);
+ max_page = (off + count - 1) >> W1_PAGE_BITS;
+ for (i = min_page; i <= max_page; i++) {
+ if (w1_f23_refresh_block(sl, data, i)) {
+ count = -EIO;
+ goto out_up;
+ }
+ }
+ memcpy(buf, &data->memory[off], count);
+
+#else /* CONFIG_W1_F23_CRC */
+
+ /* read directly from the EEPROM */
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_up;
+ }
+
+ wrbuf[0] = W1_F23_READ_EEPROM;
+ wrbuf[1] = off & 0xff;
+ wrbuf[2] = off >> 8;
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, buf, count);
+
+#endif /* CONFIG_W1_F23_CRC */
+
+out_up:
+ up(&sl->master->mutex);
+out_dec:
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+/**
+ * Writes to the scratchpad and reads it back for verification.
+ * Then copies the scratchpad to EEPROM.
+ * The data must be on one page.
+ * The master must be locked.
+ *
+ * @param sl The slave structure
+ * @param addr Address for the write
+ * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+ * @param data The data to write
+ * @return 0=Success -1=failure
+ */
+static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+{
+ u8 wrbuf[4];
+ u8 rdbuf[W1_PAGE_SIZE + 3];
+ u8 es = (addr + len - 1) & 0x1f;
+
+ /* Write the data to the scratchpad */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F23_WRITE_SCRATCH;
+ wrbuf[1] = addr & 0xff;
+ wrbuf[2] = addr >> 8;
+
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_write_block(sl->master, data, len);
+
+ /* Read the scratchpad and verify */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ w1_write_8(sl->master, W1_F23_READ_SCRATCH);
+ w1_read_block(sl->master, rdbuf, len + 3);
+
+ /* Compare what was read against the data written */
+ if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
+ (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
+ return -1;
+
+ /* Copy the scratchpad to EEPROM */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F23_COPY_SCRATCH;
+ wrbuf[3] = es;
+ w1_write_block(sl->master, wrbuf, 4);
+
+ /* Sleep for 5 ms to wait for the write to complete */
+ msleep(5);
+
+ /* Reset the bus to wake up the EEPROM (this may not be needed) */
+ w1_reset_bus(sl->master);
+
+ return 0;
+}
+
+static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ int addr, len, idx;
+
+ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ return 0;
+
+#ifdef CONFIG_W1_F23_CRC
+ /* can only write full blocks in cached mode */
+ if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
+ dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
+ (int)off, count);
+ return -EINVAL;
+ }
+
+ /* make sure the block CRCs are valid */
+ for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
+ if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) {
+ dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off);
+ return -EINVAL;
+ }
+ }
+#endif /* CONFIG_W1_F23_CRC */
+
+ atomic_inc(&sl->refcnt);
+ if (down_interruptible(&sl->master->mutex)) {
+ count = 0;
+ goto out_dec;
+ }
+
+ /* Can only write data to one page at a time */
+ idx = 0;
+ while (idx < count) {
+ addr = off + idx;
+ len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
+ if (len > (count - idx))
+ len = count - idx;
+
+ if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) {
+ count = -EIO;
+ goto out_up;
+ }
+ idx += len;
+ }
+
+out_up:
+ up(&sl->master->mutex);
+out_dec:
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static struct bin_attribute w1_f23_bin_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = W1_EEPROM_SIZE,
+ .read = w1_f23_read_bin,
+ .write = w1_f23_write_bin,
+};
+
+static int w1_f23_add_slave(struct w1_slave *sl)
+{
+ int err;
+#ifdef CONFIG_W1_F23_CRC
+ struct w1_f23_data *data;
+
+ data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ memset(data, 0, sizeof(struct w1_f23_data));
+ sl->family_data = data;
+
+#endif /* CONFIG_W1_F23_CRC */
+
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+
+#ifdef CONFIG_W1_F23_CRC
+ if (err)
+ kfree(data);
+#endif /* CONFIG_W1_F23_CRC */
+
+ return err;
+}
+
+static void w1_f23_remove_slave(struct w1_slave *sl)
+{
+#ifdef CONFIG_W1_F23_CRC
+ if (sl->family_data) {
+ kfree(sl->family_data);
+ sl->family_data = NULL;
+ }
+#endif /* CONFIG_W1_F23_CRC */
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+}
+
+static struct w1_family_ops w1_f23_fops = {
+ .add_slave = w1_f23_add_slave,
+ .remove_slave = w1_f23_remove_slave,
+};
+
+static struct w1_family w1_family_23 = {
+ .fid = W1_EEPROM_DS2433,
+ .fops = &w1_f23_fops,
+};
+
+static int __init w1_f23_init(void)
+{
+ return w1_register_family(&w1_family_23);
+}
+
+static void __exit w1_f23_fini(void)
+{
+ w1_unregister_family(&w1_family_23);
+}
+
+module_init(w1_f23_init);
+module_exit(w1_f23_fini);
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 02eee57d3c0c..88c517a4c178 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -29,23 +29,12 @@ DEFINE_SPINLOCK(w1_flock);
static LIST_HEAD(w1_families);
extern void w1_reconnect_slaves(struct w1_family *f);
-static int w1_check_family(struct w1_family *f)
-{
- if (!f->fops->rname || !f->fops->rbin)
- return -EINVAL;
-
- return 0;
-}
-
int w1_register_family(struct w1_family *newf)
{
struct list_head *ent, *n;
struct w1_family *f;
int ret = 0;
- if (w1_check_family(newf))
- return -EINVAL;
-
spin_lock(&w1_flock);
list_for_each_safe(ent, n, &w1_families) {
f = list_entry(ent, struct w1_family, family_entry);
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index b26da01bbc38..2ca0489c716a 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -31,14 +31,17 @@
#define W1_FAMILY_SMEM_81 0x81
#define W1_THERM_DS18S20 0x10
#define W1_THERM_DS1822 0x22
+#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
#define MAXNAMELEN 32
+struct w1_slave;
+
struct w1_family_ops
{
- ssize_t (* rname)(struct device *, struct device_attribute *, char *);
- ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
+ int (* add_slave)(struct w1_slave *);
+ void (* remove_slave)(struct w1_slave *);
};
struct w1_family
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index b5a5e04b6d37..c3f67eafc7ec 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -29,9 +29,9 @@
static u32 w1_ids = 1;
-extern struct device_driver w1_driver;
+extern struct device_driver w1_master_driver;
extern struct bus_type w1_bus_type;
-extern struct device w1_device;
+extern struct device w1_master_device;
extern int w1_max_slave_count;
extern int w1_max_slave_ttl;
extern struct list_head w1_masters;
@@ -76,7 +76,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
INIT_LIST_HEAD(&dev->slist);
init_MUTEX(&dev->mutex);
- init_completion(&dev->dev_released);
init_completion(&dev->dev_exited);
memcpy(&dev->dev, device, sizeof(struct device));
@@ -86,19 +85,16 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
dev->driver = driver;
- dev->groups = 23;
+ dev->groups = 1;
dev->seq = 1;
- dev->nls = netlink_kernel_create(NETLINK_W1, NULL);
- if (!dev->nls) {
- printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
- NETLINK_NFLOG, dev->dev.bus_id);
- }
+ dev_init_netlink(dev);
err = device_register(&dev->dev);
if (err) {
printk(KERN_ERR "Failed to register master device. err=%d\n", err);
- if (dev->nls && dev->nls->sk_socket)
- sock_release(dev->nls->sk_socket);
+
+ dev_fini_netlink(dev);
+
memset(dev, 0, sizeof(struct w1_master));
kfree(dev);
dev = NULL;
@@ -107,13 +103,9 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
return dev;
}
-static void w1_free_dev(struct w1_master *dev)
+void w1_free_dev(struct w1_master *dev)
{
device_unregister(&dev->dev);
- if (dev->nls && dev->nls->sk_socket)
- sock_release(dev->nls->sk_socket);
- memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
- kfree(dev);
}
int w1_add_master_device(struct w1_bus_master *master)
@@ -129,7 +121,7 @@ int w1_add_master_device(struct w1_bus_master *master)
return(-EINVAL);
}
- dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
+ dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
if (!dev)
return -ENOMEM;
@@ -188,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
__func__, dev->kpid);
while (atomic_read(&dev->refcnt)) {
- printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+ dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
dev->name, atomic_read(&dev->refcnt));
if (msleep_interruptible(1000))
@@ -225,3 +217,5 @@ void w1_remove_master_device(struct w1_bus_master *bm)
EXPORT_SYMBOL(w1_add_master_device);
EXPORT_SYMBOL(w1_remove_master_device);
+
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1);
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 00f032220173..e2a043354ddf 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -277,6 +277,29 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
w1_search(dev, cb);
}
+/**
+ * Resets the bus and then selects the slave by sending either a skip rom
+ * or a rom match.
+ * The w1 master lock must be held.
+ *
+ * @param sl the slave to select
+ * @return 0=success, anything else=error
+ */
+int w1_reset_select_slave(struct w1_slave *sl)
+{
+ if (w1_reset_bus(sl->master))
+ return -1;
+
+ if (sl->master->slave_count == 1)
+ w1_write_8(sl->master, W1_SKIP_ROM);
+ else {
+ u8 match[9] = {W1_MATCH_ROM, };
+ memcpy(&match[1], (u8 *)&sl->reg_num, 8);
+ w1_write_block(sl->master, match, 9);
+ }
+ return 0;
+}
+
EXPORT_SYMBOL(w1_touch_bit);
EXPORT_SYMBOL(w1_write_8);
EXPORT_SYMBOL(w1_read_8);
@@ -286,3 +309,4 @@ EXPORT_SYMBOL(w1_delay);
EXPORT_SYMBOL(w1_read_block);
EXPORT_SYMBOL(w1_write_block);
EXPORT_SYMBOL(w1_search_devices);
+EXPORT_SYMBOL(w1_reset_select_slave);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index af5829778aaa..232860184a29 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -34,5 +34,6 @@ u8 w1_calc_crc8(u8 *, int);
void w1_write_block(struct w1_master *, const u8 *, int);
u8 w1_read_block(struct w1_master *, u8 *, int);
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
+int w1_reset_select_slave(struct w1_slave *sl);
#endif /* __W1_IO_H */
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 2a82fb055c70..328645da7972 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -51,16 +51,42 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
memcpy(data, msg, sizeof(struct w1_netlink_msg));
- NETLINK_CB(skb).dst_groups = dev->groups;
+ NETLINK_CB(skb).dst_group = dev->groups;
netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC);
nlmsg_failure:
return;
}
+
+int dev_init_netlink(struct w1_master *dev)
+{
+ dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE);
+ if (!dev->nls) {
+ printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
+ NETLINK_W1, dev->dev.bus_id);
+ }
+
+ return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+ if (dev->nls && dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+}
#else
#warning Netlink support is disabled. Please compile with NET support enabled.
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
{
}
+
+int dev_init_netlink(struct w1_master *dev)
+{
+ return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+}
#endif
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 8615756946df..eb0c8b3152c8 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -52,6 +52,8 @@ struct w1_netlink_msg
#ifdef __KERNEL__
void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
+int dev_init_netlink(struct w1_master *dev);
+void dev_fini_netlink(struct w1_master *dev);
#endif /* __KERNEL__ */
#endif /* __W1_NETLINK_H */
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
index 70d2d469963c..e3209d0aca9b 100644
--- a/drivers/w1/w1_smem.c
+++ b/drivers/w1/w1_smem.c
@@ -36,61 +36,12 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
-static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
-static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
-
-static struct w1_family_ops w1_smem_fops = {
- .rname = &w1_smem_read_name,
- .rbin = &w1_smem_read_bin,
-};
-
-static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- return sprintf(buf, "%s\n", sl->name);
-}
-
-static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
- int i;
-
- atomic_inc(&sl->refcnt);
- if (down_interruptible(&sl->master->mutex)) {
- count = 0;
- goto out_dec;
- }
-
- if (off > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
- if (off + count > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
- for (i = 0; i < 8; ++i)
- count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
- count += sprintf(buf + count, "\n");
-
-out:
- up(&sl->master->mutex);
-out_dec:
- atomic_dec(&sl->refcnt);
-
- return count;
-}
-
static struct w1_family w1_smem_family_01 = {
.fid = W1_FAMILY_SMEM_01,
- .fops = &w1_smem_fops,
};
static struct w1_family w1_smem_family_81 = {
.fid = W1_FAMILY_SMEM_81,
- .fops = &w1_smem_fops,
};
static int __init w1_smem_init(void)
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 165526c9360a..4577df3cfc48 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -42,12 +42,31 @@ static u8 bad_roms[][9] = {
{}
};
-static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+static struct bin_attribute w1_therm_bin_attr = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = W1_SLAVE_DATA_SIZE,
+ .read = w1_therm_read_bin,
+};
+
+static int w1_therm_add_slave(struct w1_slave *sl)
+{
+ return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
+static void w1_therm_remove_slave(struct w1_slave *sl)
+{
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
static struct w1_family_ops w1_therm_fops = {
- .rname = &w1_therm_read_name,
- .rbin = &w1_therm_read_bin,
+ .add_slave = w1_therm_add_slave,
+ .remove_slave = w1_therm_remove_slave,
};
static struct w1_family w1_therm_family_DS18S20 = {
@@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = {
.fid = W1_THERM_DS18B20,
.fops = &w1_therm_fops,
};
+
static struct w1_family w1_therm_family_DS1822 = {
.fid = W1_THERM_DS1822,
.fops = &w1_therm_fops,
@@ -90,13 +110,6 @@ static struct w1_therm_family_converter w1_therm_families[] = {
},
};
-static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- return sprintf(buf, "%s\n", sl->name);
-}
-
static inline int w1_DS18B20_convert_temp(u8 rom[9])
{
int t = (rom[1] << 8) | rom[0];
@@ -148,8 +161,7 @@ static int w1_therm_check_rom(u8 rom[9])
static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
- struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict;
int i, max_trying = 10;
@@ -178,15 +190,10 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
crc = 0;
while (max_trying--) {
- if (!w1_reset_bus (dev)) {
+ if (!w1_reset_select_slave(sl)) {
int count = 0;
- u8 match[9] = {W1_MATCH_ROM, };
unsigned int tm = 750;
- memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-
- w1_write_block(dev, match, 9);
-
w1_write_8(dev, W1_CONVERT_TEMP);
while (tm) {
@@ -195,8 +202,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
flush_signals(current);
}
- if (!w1_reset_bus (dev)) {
- w1_write_block(dev, match, 9);
+ if (!w1_reset_select_slave(sl)) {
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
@@ -207,7 +213,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (rom[8] == crc && rom[0])
verdict = 1;
-
}
}
diff --git a/fs/9p/9p.c b/fs/9p/9p.c
new file mode 100644
index 000000000000..e847f504a47c
--- /dev/null
+++ b/fs/9p/9p.c
@@ -0,0 +1,359 @@
+/*
+ * linux/fs/9p/9p.c
+ *
+ * This file contains functions 9P2000 functions
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "mux.h"
+
+/**
+ * v9fs_t_version - negotiate protocol parameters with sever
+ * @v9ses: 9P2000 session information
+ * @msize: requested max size packet
+ * @version: requested version.extension string
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
+ char *version, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
+ msg.id = TVERSION;
+ msg.params.tversion.msize = msize;
+ msg.params.tversion.version = version;
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_attach - mount the server
+ * @v9ses: 9P2000 session information
+ * @uname: user name doing the attach
+ * @aname: remote name being attached to
+ * @fid: mount fid to attatch to root node
+ * @afid: authentication fid (in this case result key)
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
+ u32 fid, u32 afid, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
+ aname, fid, afid);
+ msg.id = TATTACH;
+ msg.params.tattach.fid = fid;
+ msg.params.tattach.afid = afid;
+ msg.params.tattach.uname = uname;
+ msg.params.tattach.aname = aname;
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_clunk - release a fid (finish a transaction)
+ * @v9ses: 9P2000 session information
+ * @fid: fid to release
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d\n", fid);
+ msg.id = TCLUNK;
+ msg.params.tclunk.fid = fid;
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_v9fs_t_flush - flush a pending transaction
+ * @v9ses: 9P2000 session information
+ * @tag: tid to release
+ *
+ */
+
+int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "oldtag %d\n", tag);
+ msg.id = TFLUSH;
+ msg.params.tflush.oldtag = tag;
+ return v9fs_mux_rpc(v9ses, &msg, NULL);
+}
+
+/**
+ * v9fs_t_stat - read a file's meta-data
+ * @v9ses: 9P2000 session information
+ * @fid: fid pointing to file or directory to get info about
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d\n", fid);
+ if (fcall)
+ *fcall = NULL;
+
+ msg.id = TSTAT;
+ msg.params.tstat.fid = fid;
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_wstat - write a file's meta-data
+ * @v9ses: 9P2000 session information
+ * @fid: fid pointing to file or directory to write info about
+ * @stat: metadata
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_stat *stat, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length);
+ msg.id = TWSTAT;
+ msg.params.twstat.fid = fid;
+ msg.params.twstat.stat = stat;
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_walk - walk a fid to a new file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to walk
+ * @newfid: new fid (for clone operations)
+ * @name: path to walk fid to
+ * @fcall: pointer to response fcall
+ *
+ */
+
+/* TODO: support multiple walk */
+
+int
+v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
+ char *name, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
+ msg.id = TWALK;
+ msg.params.twalk.fid = fid;
+ msg.params.twalk.newfid = newfid;
+
+ if (name) {
+ msg.params.twalk.nwname = 1;
+ msg.params.twalk.wnames = &name;
+ } else {
+ msg.params.twalk.nwname = 0;
+ }
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_open - open a file
+ *
+ * @v9ses - 9P2000 session information
+ * @fid - fid to open
+ * @mode - mode to open file (R, RW, etc)
+ * @fcall - pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
+ struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+ long errorno = -1;
+
+ dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
+ msg.id = TOPEN;
+ msg.params.topen.fid = fid;
+ msg.params.topen.mode = mode;
+
+ errorno = v9fs_mux_rpc(v9ses, &msg, fcall);
+
+ return errorno;
+}
+
+/**
+ * v9fs_t_remove - remove a file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to remove
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d\n", fid);
+ msg.id = TREMOVE;
+ msg.params.tremove.fid = fid;
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_create - create a file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to create
+ * @name: name of the file or directory to create
+ * @perm: permissions to create with
+ * @mode: mode to open file (R, RW, etc)
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
+ u32 perm, u8 mode, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+
+ dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
+ fid, name, perm, mode);
+
+ msg.id = TCREATE;
+ msg.params.tcreate.fid = fid;
+ msg.params.tcreate.name = name;
+ msg.params.tcreate.perm = perm;
+ msg.params.tcreate.mode = mode;
+
+ return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_read - read data
+ * @v9ses: 9P2000 session information
+ * @fid: fid to read from
+ * @offset: offset to start read at
+ * @count: how many bytes to read
+ * @fcall: pointer to response fcall (with data)
+ *
+ */
+
+int
+v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
+ u32 count, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+ struct v9fs_fcall *rc = NULL;
+ long errorno = -1;
+
+ dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid,
+ (long unsigned int)offset, count);
+ msg.id = TREAD;
+ msg.params.tread.fid = fid;
+ msg.params.tread.offset = offset;
+ msg.params.tread.count = count;
+ errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
+
+ if (!errorno) {
+ errorno = rc->params.rread.count;
+ dump_data(rc->params.rread.data, rc->params.rread.count);
+ }
+
+ if (fcall)
+ *fcall = rc;
+ else
+ kfree(rc);
+
+ return errorno;
+}
+
+/**
+ * v9fs_t_write - write data
+ * @v9ses: 9P2000 session information
+ * @fid: fid to write to
+ * @offset: offset to start write at
+ * @count: how many bytes to write
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
+ u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
+{
+ struct v9fs_fcall msg;
+ struct v9fs_fcall *rc = NULL;
+ long errorno = -1;
+
+ dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
+ (unsigned long long)offset, count);
+ dump_data(data, count);
+
+ msg.id = TWRITE;
+ msg.params.twrite.fid = fid;
+ msg.params.twrite.offset = offset;
+ msg.params.twrite.count = count;
+ msg.params.twrite.data = data;
+
+ errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
+
+ if (!errorno)
+ errorno = rc->params.rwrite.count;
+
+ if (fcall)
+ *fcall = rc;
+ else
+ kfree(rc);
+
+ return errorno;
+}
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
new file mode 100644
index 000000000000..f55424216be2
--- /dev/null
+++ b/fs/9p/9p.h
@@ -0,0 +1,341 @@
+/*
+ * linux/fs/9p/9p.h
+ *
+ * 9P protocol definitions.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+/* Message Types */
+enum {
+ TVERSION = 100,
+ RVERSION,
+ TAUTH = 102,
+ RAUTH,
+ TATTACH = 104,
+ RATTACH,
+ TERROR = 106,
+ RERROR,
+ TFLUSH = 108,
+ RFLUSH,
+ TWALK = 110,
+ RWALK,
+ TOPEN = 112,
+ ROPEN,
+ TCREATE = 114,
+ RCREATE,
+ TREAD = 116,
+ RREAD,
+ TWRITE = 118,
+ RWRITE,
+ TCLUNK = 120,
+ RCLUNK,
+ TREMOVE = 122,
+ RREMOVE,
+ TSTAT = 124,
+ RSTAT,
+ TWSTAT = 126,
+ RWSTAT,
+};
+
+/* modes */
+enum {
+ V9FS_OREAD = 0x00,
+ V9FS_OWRITE = 0x01,
+ V9FS_ORDWR = 0x02,
+ V9FS_OEXEC = 0x03,
+ V9FS_OEXCL = 0x04,
+ V9FS_OTRUNC = 0x10,
+ V9FS_OREXEC = 0x20,
+ V9FS_ORCLOSE = 0x40,
+ V9FS_OAPPEND = 0x80,
+};
+
+/* permissions */
+enum {
+ V9FS_DMDIR = 0x80000000,
+ V9FS_DMAPPEND = 0x40000000,
+ V9FS_DMEXCL = 0x20000000,
+ V9FS_DMMOUNT = 0x10000000,
+ V9FS_DMAUTH = 0x08000000,
+ V9FS_DMTMP = 0x04000000,
+ V9FS_DMSYMLINK = 0x02000000,
+ V9FS_DMLINK = 0x01000000,
+ /* 9P2000.u extensions */
+ V9FS_DMDEVICE = 0x00800000,
+ V9FS_DMNAMEDPIPE = 0x00200000,
+ V9FS_DMSOCKET = 0x00100000,
+ V9FS_DMSETUID = 0x00080000,
+ V9FS_DMSETGID = 0x00040000,
+};
+
+/* qid.types */
+enum {
+ V9FS_QTDIR = 0x80,
+ V9FS_QTAPPEND = 0x40,
+ V9FS_QTEXCL = 0x20,
+ V9FS_QTMOUNT = 0x10,
+ V9FS_QTAUTH = 0x08,
+ V9FS_QTTMP = 0x04,
+ V9FS_QTSYMLINK = 0x02,
+ V9FS_QTLINK = 0x01,
+ V9FS_QTFILE = 0x00,
+};
+
+/* ample room for Twrite/Rread header (iounit) */
+#define V9FS_IOHDRSZ 24
+
+/* qids are the unique ID for a file (like an inode */
+struct v9fs_qid {
+ u8 type;
+ u32 version;
+ u64 path;
+};
+
+/* Plan 9 file metadata (stat) structure */
+struct v9fs_stat {
+ u16 size;
+ u16 type;
+ u32 dev;
+ struct v9fs_qid qid;
+ u32 mode;
+ u32 atime;
+ u32 mtime;
+ u64 length;
+ char *name;
+ char *uid;
+ char *gid;
+ char *muid;
+ char *extension; /* 9p2000.u extensions */
+ u32 n_uid; /* 9p2000.u extensions */
+ u32 n_gid; /* 9p2000.u extensions */
+ u32 n_muid; /* 9p2000.u extensions */
+ char data[0];
+};
+
+/* Structures for Protocol Operations */
+
+struct Tversion {
+ u32 msize;
+ char *version;
+};
+
+struct Rversion {
+ u32 msize;
+ char *version;
+};
+
+struct Tauth {
+ u32 afid;
+ char *uname;
+ char *aname;
+};
+
+struct Rauth {
+ struct v9fs_qid qid;
+};
+
+struct Rerror {
+ char *error;
+ u32 errno; /* 9p2000.u extension */
+};
+
+struct Tflush {
+ u32 oldtag;
+};
+
+struct Rflush {
+};
+
+struct Tattach {
+ u32 fid;
+ u32 afid;
+ char *uname;
+ char *aname;
+};
+
+struct Rattach {
+ struct v9fs_qid qid;
+};
+
+struct Twalk {
+ u32 fid;
+ u32 newfid;
+ u32 nwname;
+ char **wnames;
+};
+
+struct Rwalk {
+ u32 nwqid;
+ struct v9fs_qid *wqids;
+};
+
+struct Topen {
+ u32 fid;
+ u8 mode;
+};
+
+struct Ropen {
+ struct v9fs_qid qid;
+ u32 iounit;
+};
+
+struct Tcreate {
+ u32 fid;
+ char *name;
+ u32 perm;
+ u8 mode;
+};
+
+struct Rcreate {
+ struct v9fs_qid qid;
+ u32 iounit;
+};
+
+struct Tread {
+ u32 fid;
+ u64 offset;
+ u32 count;
+};
+
+struct Rread {
+ u32 count;
+ u8 *data;
+};
+
+struct Twrite {
+ u32 fid;
+ u64 offset;
+ u32 count;
+ u8 *data;
+};
+
+struct Rwrite {
+ u32 count;
+};
+
+struct Tclunk {
+ u32 fid;
+};
+
+struct Rclunk {
+};
+
+struct Tremove {
+ u32 fid;
+};
+
+struct Rremove {
+};
+
+struct Tstat {
+ u32 fid;
+};
+
+struct Rstat {
+ struct v9fs_stat *stat;
+};
+
+struct Twstat {
+ u32 fid;
+ struct v9fs_stat *stat;
+};
+
+struct Rwstat {
+};
+
+/*
+ * fcall is the primary packet structure
+ *
+ */
+
+struct v9fs_fcall {
+ u32 size;
+ u8 id;
+ u16 tag;
+
+ union {
+ struct Tversion tversion;
+ struct Rversion rversion;
+ struct Tauth tauth;
+ struct Rauth rauth;
+ struct Rerror rerror;
+ struct Tflush tflush;
+ struct Rflush rflush;
+ struct Tattach tattach;
+ struct Rattach rattach;
+ struct Twalk twalk;
+ struct Rwalk rwalk;
+ struct Topen topen;
+ struct Ropen ropen;
+ struct Tcreate tcreate;
+ struct Rcreate rcreate;
+ struct Tread tread;
+ struct Rread rread;
+ struct Twrite twrite;
+ struct Rwrite rwrite;
+ struct Tclunk tclunk;
+ struct Rclunk rclunk;
+ struct Tremove tremove;
+ struct Rremove rremove;
+ struct Tstat tstat;
+ struct Rstat rstat;
+ struct Twstat twstat;
+ struct Rwstat rwstat;
+ } params;
+};
+
+#define FCALL_ERROR(fcall) (fcall ? fcall->params.rerror.error : "")
+
+int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
+ char *version, struct v9fs_fcall **rcall);
+
+int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
+ u32 fid, u32 afid, struct v9fs_fcall **rcall);
+
+int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_fcall **rcall);
+
+int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag);
+
+int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_fcall **rcall);
+
+int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_stat *stat, struct v9fs_fcall **rcall);
+
+int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
+ char *name, struct v9fs_fcall **rcall);
+
+int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
+ struct v9fs_fcall **rcall);
+
+int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
+ struct v9fs_fcall **rcall);
+
+int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
+ u32 perm, u8 mode, struct v9fs_fcall **rcall);
+
+int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
+ u64 offset, u32 count, struct v9fs_fcall **rcall);
+
+int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
+ u32 count, void *data, struct v9fs_fcall **rcall);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
new file mode 100644
index 000000000000..e4e4ffe5a7dc
--- /dev/null
+++ b/fs/9p/Makefile
@@ -0,0 +1,17 @@
+obj-$(CONFIG_9P_FS) := 9p2000.o
+
+9p2000-objs := \
+ vfs_super.o \
+ vfs_inode.o \
+ vfs_file.o \
+ vfs_dir.o \
+ vfs_dentry.o \
+ error.o \
+ mux.o \
+ trans_fd.o \
+ trans_sock.o \
+ 9p.o \
+ conv.o \
+ v9fs.o \
+ fid.o
+
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
new file mode 100644
index 000000000000..1554731bd653
--- /dev/null
+++ b/fs/9p/conv.c
@@ -0,0 +1,693 @@
+/*
+ * linux/fs/9p/conv.c
+ *
+ * 9P protocol conversion functions
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "conv.h"
+
+/*
+ * Buffer to help with string parsing
+ */
+struct cbuf {
+ unsigned char *sp;
+ unsigned char *p;
+ unsigned char *ep;
+};
+
+static inline void buf_init(struct cbuf *buf, void *data, int datalen)
+{
+ buf->sp = buf->p = data;
+ buf->ep = data + datalen;
+}
+
+static inline int buf_check_overflow(struct cbuf *buf)
+{
+ return buf->p > buf->ep;
+}
+
+static inline void buf_check_size(struct cbuf *buf, int len)
+{
+ if (buf->p+len > buf->ep) {
+ if (buf->p < buf->ep) {
+ eprintk(KERN_ERR, "buffer overflow\n");
+ buf->p = buf->ep + 1;
+ }
+ }
+}
+
+static inline void *buf_alloc(struct cbuf *buf, int len)
+{
+ void *ret = NULL;
+
+ buf_check_size(buf, len);
+ ret = buf->p;
+ buf->p += len;
+
+ return ret;
+}
+
+static inline void buf_put_int8(struct cbuf *buf, u8 val)
+{
+ buf_check_size(buf, 1);
+
+ buf->p[0] = val;
+ buf->p++;
+}
+
+static inline void buf_put_int16(struct cbuf *buf, u16 val)
+{
+ buf_check_size(buf, 2);
+
+ *(__le16 *) buf->p = cpu_to_le16(val);
+ buf->p += 2;
+}
+
+static inline void buf_put_int32(struct cbuf *buf, u32 val)
+{
+ buf_check_size(buf, 4);
+
+ *(__le32 *)buf->p = cpu_to_le32(val);
+ buf->p += 4;
+}
+
+static inline void buf_put_int64(struct cbuf *buf, u64 val)
+{
+ buf_check_size(buf, 8);
+
+ *(__le64 *)buf->p = cpu_to_le64(val);
+ buf->p += 8;
+}
+
+static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
+{
+ buf_check_size(buf, slen + 2);
+
+ buf_put_int16(buf, slen);
+ memcpy(buf->p, s, slen);
+ buf->p += slen;
+}
+
+static inline void buf_put_string(struct cbuf *buf, const char *s)
+{
+ buf_put_stringn(buf, s, strlen(s));
+}
+
+static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen)
+{
+ buf_check_size(buf, datalen);
+
+ memcpy(buf->p, data, datalen);
+ buf->p += datalen;
+}
+
+static inline u8 buf_get_int8(struct cbuf *buf)
+{
+ u8 ret = 0;
+
+ buf_check_size(buf, 1);
+ ret = buf->p[0];
+
+ buf->p++;
+
+ return ret;
+}
+
+static inline u16 buf_get_int16(struct cbuf *buf)
+{
+ u16 ret = 0;
+
+ buf_check_size(buf, 2);
+ ret = le16_to_cpu(*(__le16 *)buf->p);
+
+ buf->p += 2;
+
+ return ret;
+}
+
+static inline u32 buf_get_int32(struct cbuf *buf)
+{
+ u32 ret = 0;
+
+ buf_check_size(buf, 4);
+ ret = le32_to_cpu(*(__le32 *)buf->p);
+
+ buf->p += 4;
+
+ return ret;
+}
+
+static inline u64 buf_get_int64(struct cbuf *buf)
+{
+ u64 ret = 0;
+
+ buf_check_size(buf, 8);
+ ret = le64_to_cpu(*(__le64 *)buf->p);
+
+ buf->p += 8;
+
+ return ret;
+}
+
+static inline int
+buf_get_string(struct cbuf *buf, char *data, unsigned int datalen)
+{
+
+ u16 len = buf_get_int16(buf);
+ buf_check_size(buf, len);
+ if (len + 1 > datalen)
+ return 0;
+
+ memcpy(data, buf->p, len);
+ data[len] = 0;
+ buf->p += len;
+
+ return len + 1;
+}
+
+static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
+{
+ char *ret = NULL;
+ int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p);
+
+ if (n > 0) {
+ ret = sbuf->p;
+ sbuf->p += n;
+ }
+
+ return ret;
+}
+
+static inline int buf_get_data(struct cbuf *buf, void *data, int datalen)
+{
+ buf_check_size(buf, datalen);
+
+ memcpy(data, buf->p, datalen);
+ buf->p += datalen;
+
+ return datalen;
+}
+
+static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
+ int datalen)
+{
+ char *ret = NULL;
+ int n = 0;
+
+ buf_check_size(dbuf, datalen);
+
+ n = buf_get_data(buf, dbuf->p, datalen);
+
+ if (n > 0) {
+ ret = dbuf->p;
+ dbuf->p += n;
+ }
+
+ return ret;
+}
+
+/**
+ * v9fs_size_stat - calculate the size of a variable length stat struct
+ * @v9ses: session information
+ * @stat: metadata (stat) structure
+ *
+ */
+
+static int v9fs_size_stat(struct v9fs_session_info *v9ses,
+ struct v9fs_stat *stat)
+{
+ int size = 0;
+
+ if (stat == NULL) {
+ eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
+ return 0;
+ }
+
+ size = /* 2 + *//* size[2] */
+ 2 + /* type[2] */
+ 4 + /* dev[4] */
+ 1 + /* qid.type[1] */
+ 4 + /* qid.vers[4] */
+ 8 + /* qid.path[8] */
+ 4 + /* mode[4] */
+ 4 + /* atime[4] */
+ 4 + /* mtime[4] */
+ 8 + /* length[8] */
+ 8; /* minimum sum of string lengths */
+
+ if (stat->name)
+ size += strlen(stat->name);
+ if (stat->uid)
+ size += strlen(stat->uid);
+ if (stat->gid)
+ size += strlen(stat->gid);
+ if (stat->muid)
+ size += strlen(stat->muid);
+
+ if (v9ses->extended) {
+ size += 4 + /* n_uid[4] */
+ 4 + /* n_gid[4] */
+ 4 + /* n_muid[4] */
+ 2; /* string length of extension[4] */
+ if (stat->extension)
+ size += strlen(stat->extension);
+ }
+
+ return size;
+}
+
+/**
+ * serialize_stat - safely format a stat structure for transmission
+ * @v9ses: session info
+ * @stat: metadata (stat) structure
+ * @bufp: buffer to serialize structure into
+ *
+ */
+
+static int
+serialize_stat(struct v9fs_session_info *v9ses, struct v9fs_stat *stat,
+ struct cbuf *bufp)
+{
+ buf_put_int16(bufp, stat->size);
+ buf_put_int16(bufp, stat->type);
+ buf_put_int32(bufp, stat->dev);
+ buf_put_int8(bufp, stat->qid.type);
+ buf_put_int32(bufp, stat->qid.version);
+ buf_put_int64(bufp, stat->qid.path);
+ buf_put_int32(bufp, stat->mode);
+ buf_put_int32(bufp, stat->atime);
+ buf_put_int32(bufp, stat->mtime);
+ buf_put_int64(bufp, stat->length);
+
+ buf_put_string(bufp, stat->name);
+ buf_put_string(bufp, stat->uid);
+ buf_put_string(bufp, stat->gid);
+ buf_put_string(bufp, stat->muid);
+
+ if (v9ses->extended) {
+ buf_put_string(bufp, stat->extension);
+ buf_put_int32(bufp, stat->n_uid);
+ buf_put_int32(bufp, stat->n_gid);
+ buf_put_int32(bufp, stat->n_muid);
+ }
+
+ if (buf_check_overflow(bufp))
+ return 0;
+
+ return stat->size;
+}
+
+/**
+ * deserialize_stat - safely decode a recieved metadata (stat) structure
+ * @v9ses: session info
+ * @bufp: buffer to deserialize
+ * @stat: metadata (stat) structure
+ * @dbufp: buffer to deserialize variable strings into
+ *
+ */
+
+static inline int
+deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp,
+ struct v9fs_stat *stat, struct cbuf *dbufp)
+{
+
+ stat->size = buf_get_int16(bufp);
+ stat->type = buf_get_int16(bufp);
+ stat->dev = buf_get_int32(bufp);
+ stat->qid.type = buf_get_int8(bufp);
+ stat->qid.version = buf_get_int32(bufp);
+ stat->qid.path = buf_get_int64(bufp);
+ stat->mode = buf_get_int32(bufp);
+ stat->atime = buf_get_int32(bufp);
+ stat->mtime = buf_get_int32(bufp);
+ stat->length = buf_get_int64(bufp);
+ stat->name = buf_get_stringb(bufp, dbufp);
+ stat->uid = buf_get_stringb(bufp, dbufp);
+ stat->gid = buf_get_stringb(bufp, dbufp);
+ stat->muid = buf_get_stringb(bufp, dbufp);
+
+ if (v9ses->extended) {
+ stat->extension = buf_get_stringb(bufp, dbufp);
+ stat->n_uid = buf_get_int32(bufp);
+ stat->n_gid = buf_get_int32(bufp);
+ stat->n_muid = buf_get_int32(bufp);
+ }
+
+ if (buf_check_overflow(bufp) || buf_check_overflow(dbufp))
+ return 0;
+
+ return stat->size + 2;
+}
+
+/**
+ * deserialize_statb - wrapper for decoding a received metadata structure
+ * @v9ses: session info
+ * @bufp: buffer to deserialize
+ * @dbufp: buffer to deserialize variable strings into
+ *
+ */
+
+static inline struct v9fs_stat *deserialize_statb(struct v9fs_session_info
+ *v9ses, struct cbuf *bufp,
+ struct cbuf *dbufp)
+{
+ struct v9fs_stat *ret = buf_alloc(dbufp, sizeof(struct v9fs_stat));
+
+ if (ret) {
+ int n = deserialize_stat(v9ses, bufp, ret, dbufp);
+ if (n <= 0)
+ return NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * v9fs_deserialize_stat - decode a received metadata structure
+ * @v9ses: session info
+ * @buf: buffer to deserialize
+ * @buflen: length of received buffer
+ * @stat: metadata structure to decode into
+ * @statlen: length of destination metadata structure
+ *
+ */
+
+int
+v9fs_deserialize_stat(struct v9fs_session_info *v9ses, void *buf,
+ u32 buflen, struct v9fs_stat *stat, u32 statlen)
+{
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+ struct cbuf dbuffer;
+ struct cbuf *dbufp = &dbuffer;
+
+ buf_init(bufp, buf, buflen);
+ buf_init(dbufp, (char *)stat + sizeof(struct v9fs_stat),
+ statlen - sizeof(struct v9fs_stat));
+
+ return deserialize_stat(v9ses, bufp, stat, dbufp);
+}
+
+static inline int
+v9fs_size_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall)
+{
+ int size = 4 + 1 + 2; /* size[4] msg[1] tag[2] */
+ int i = 0;
+
+ switch (fcall->id) {
+ default:
+ eprintk(KERN_ERR, "bad msg type %d\n", fcall->id);
+ return 0;
+ case TVERSION: /* msize[4] version[s] */
+ size += 4 + 2 + strlen(fcall->params.tversion.version);
+ break;
+ case TAUTH: /* afid[4] uname[s] aname[s] */
+ size += 4 + 2 + strlen(fcall->params.tauth.uname) +
+ 2 + strlen(fcall->params.tauth.aname);
+ break;
+ case TFLUSH: /* oldtag[2] */
+ size += 2;
+ break;
+ case TATTACH: /* fid[4] afid[4] uname[s] aname[s] */
+ size += 4 + 4 + 2 + strlen(fcall->params.tattach.uname) +
+ 2 + strlen(fcall->params.tattach.aname);
+ break;
+ case TWALK: /* fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
+ size += 4 + 4 + 2;
+ /* now compute total for the array of names */
+ for (i = 0; i < fcall->params.twalk.nwname; i++)
+ size += 2 + strlen(fcall->params.twalk.wnames[i]);
+ break;
+ case TOPEN: /* fid[4] mode[1] */
+ size += 4 + 1;
+ break;
+ case TCREATE: /* fid[4] name[s] perm[4] mode[1] */
+ size += 4 + 2 + strlen(fcall->params.tcreate.name) + 4 + 1;
+ break;
+ case TREAD: /* fid[4] offset[8] count[4] */
+ size += 4 + 8 + 4;
+ break;
+ case TWRITE: /* fid[4] offset[8] count[4] data[count] */
+ size += 4 + 8 + 4 + fcall->params.twrite.count;
+ break;
+ case TCLUNK: /* fid[4] */
+ size += 4;
+ break;
+ case TREMOVE: /* fid[4] */
+ size += 4;
+ break;
+ case TSTAT: /* fid[4] */
+ size += 4;
+ break;
+ case TWSTAT: /* fid[4] stat[n] */
+ fcall->params.twstat.stat->size =
+ v9fs_size_stat(v9ses, fcall->params.twstat.stat);
+ size += 4 + 2 + 2 + fcall->params.twstat.stat->size;
+ }
+ return size;
+}
+
+/*
+ * v9fs_serialize_fcall - marshall fcall struct into a packet
+ * @v9ses: session information
+ * @fcall: structure to convert
+ * @data: buffer to serialize fcall into
+ * @datalen: length of buffer to serialize fcall into
+ *
+ */
+
+int
+v9fs_serialize_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall,
+ void *data, u32 datalen)
+{
+ int i = 0;
+ struct v9fs_stat *stat = NULL;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ buf_init(bufp, data, datalen);
+
+ if (!fcall) {
+ eprintk(KERN_ERR, "no fcall\n");
+ return -EINVAL;
+ }
+
+ fcall->size = v9fs_size_fcall(v9ses, fcall);
+
+ buf_put_int32(bufp, fcall->size);
+ buf_put_int8(bufp, fcall->id);
+ buf_put_int16(bufp, fcall->tag);
+
+ dprintk(DEBUG_CONV, "size %d id %d tag %d\n", fcall->size, fcall->id,
+ fcall->tag);
+
+ /* now encode it */
+ switch (fcall->id) {
+ default:
+ eprintk(KERN_ERR, "bad msg type: %d\n", fcall->id);
+ return -EPROTO;
+ case TVERSION:
+ buf_put_int32(bufp, fcall->params.tversion.msize);
+ buf_put_string(bufp, fcall->params.tversion.version);
+ break;
+ case TAUTH:
+ buf_put_int32(bufp, fcall->params.tauth.afid);
+ buf_put_string(bufp, fcall->params.tauth.uname);
+ buf_put_string(bufp, fcall->params.tauth.aname);
+ break;
+ case TFLUSH:
+ buf_put_int16(bufp, fcall->params.tflush.oldtag);
+ break;
+ case TATTACH:
+ buf_put_int32(bufp, fcall->params.tattach.fid);
+ buf_put_int32(bufp, fcall->params.tattach.afid);
+ buf_put_string(bufp, fcall->params.tattach.uname);
+ buf_put_string(bufp, fcall->params.tattach.aname);
+ break;
+ case TWALK:
+ buf_put_int32(bufp, fcall->params.twalk.fid);
+ buf_put_int32(bufp, fcall->params.twalk.newfid);
+ buf_put_int16(bufp, fcall->params.twalk.nwname);
+ for (i = 0; i < fcall->params.twalk.nwname; i++)
+ buf_put_string(bufp, fcall->params.twalk.wnames[i]);
+ break;
+ case TOPEN:
+ buf_put_int32(bufp, fcall->params.topen.fid);
+ buf_put_int8(bufp, fcall->params.topen.mode);
+ break;
+ case TCREATE:
+ buf_put_int32(bufp, fcall->params.tcreate.fid);
+ buf_put_string(bufp, fcall->params.tcreate.name);
+ buf_put_int32(bufp, fcall->params.tcreate.perm);
+ buf_put_int8(bufp, fcall->params.tcreate.mode);
+ break;
+ case TREAD:
+ buf_put_int32(bufp, fcall->params.tread.fid);
+ buf_put_int64(bufp, fcall->params.tread.offset);
+ buf_put_int32(bufp, fcall->params.tread.count);
+ break;
+ case TWRITE:
+ buf_put_int32(bufp, fcall->params.twrite.fid);
+ buf_put_int64(bufp, fcall->params.twrite.offset);
+ buf_put_int32(bufp, fcall->params.twrite.count);
+ buf_put_data(bufp, fcall->params.twrite.data,
+ fcall->params.twrite.count);
+ break;
+ case TCLUNK:
+ buf_put_int32(bufp, fcall->params.tclunk.fid);
+ break;
+ case TREMOVE:
+ buf_put_int32(bufp, fcall->params.tremove.fid);
+ break;
+ case TSTAT:
+ buf_put_int32(bufp, fcall->params.tstat.fid);
+ break;
+ case TWSTAT:
+ buf_put_int32(bufp, fcall->params.twstat.fid);
+ stat = fcall->params.twstat.stat;
+
+ buf_put_int16(bufp, stat->size + 2);
+ serialize_stat(v9ses, stat, bufp);
+ break;
+ }
+
+ if (buf_check_overflow(bufp))
+ return -EIO;
+
+ return fcall->size;
+}
+
+/**
+ * deserialize_fcall - unmarshal a response
+ * @v9ses: session information
+ * @msgsize: size of rcall message
+ * @buf: recieved buffer
+ * @buflen: length of received buffer
+ * @rcall: fcall structure to populate
+ * @rcalllen: length of fcall structure to populate
+ *
+ */
+
+int
+v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
+ void *buf, u32 buflen, struct v9fs_fcall *rcall,
+ int rcalllen)
+{
+
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+ struct cbuf dbuffer;
+ struct cbuf *dbufp = &dbuffer;
+ int i = 0;
+
+ buf_init(bufp, buf, buflen);
+ buf_init(dbufp, (char *)rcall + sizeof(struct v9fs_fcall),
+ rcalllen - sizeof(struct v9fs_fcall));
+
+ rcall->size = msgsize;
+ rcall->id = buf_get_int8(bufp);
+ rcall->tag = buf_get_int16(bufp);
+
+ dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
+ rcall->tag);
+ switch (rcall->id) {
+ default:
+ eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id);
+ return -EPROTO;
+ case RVERSION:
+ rcall->params.rversion.msize = buf_get_int32(bufp);
+ rcall->params.rversion.version = buf_get_stringb(bufp, dbufp);
+ break;
+ case RFLUSH:
+ break;
+ case RATTACH:
+ rcall->params.rattach.qid.type = buf_get_int8(bufp);
+ rcall->params.rattach.qid.version = buf_get_int32(bufp);
+ rcall->params.rattach.qid.path = buf_get_int64(bufp);
+ break;
+ case RWALK:
+ rcall->params.rwalk.nwqid = buf_get_int16(bufp);
+ rcall->params.rwalk.wqids = buf_alloc(bufp,
+ rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid));
+ if (rcall->params.rwalk.wqids)
+ for (i = 0; i < rcall->params.rwalk.nwqid; i++) {
+ rcall->params.rwalk.wqids[i].type =
+ buf_get_int8(bufp);
+ rcall->params.rwalk.wqids[i].version =
+ buf_get_int16(bufp);
+ rcall->params.rwalk.wqids[i].path =
+ buf_get_int64(bufp);
+ }
+ break;
+ case ROPEN:
+ rcall->params.ropen.qid.type = buf_get_int8(bufp);
+ rcall->params.ropen.qid.version = buf_get_int32(bufp);
+ rcall->params.ropen.qid.path = buf_get_int64(bufp);
+ rcall->params.ropen.iounit = buf_get_int32(bufp);
+ break;
+ case RCREATE:
+ rcall->params.rcreate.qid.type = buf_get_int8(bufp);
+ rcall->params.rcreate.qid.version = buf_get_int32(bufp);
+ rcall->params.rcreate.qid.path = buf_get_int64(bufp);
+ rcall->params.rcreate.iounit = buf_get_int32(bufp);
+ break;
+ case RREAD:
+ rcall->params.rread.count = buf_get_int32(bufp);
+ rcall->params.rread.data = buf_get_datab(bufp, dbufp,
+ rcall->params.rread.count);
+ break;
+ case RWRITE:
+ rcall->params.rwrite.count = buf_get_int32(bufp);
+ break;
+ case RCLUNK:
+ break;
+ case RREMOVE:
+ break;
+ case RSTAT:
+ buf_get_int16(bufp);
+ rcall->params.rstat.stat =
+ deserialize_statb(v9ses, bufp, dbufp);
+ break;
+ case RWSTAT:
+ break;
+ case RERROR:
+ rcall->params.rerror.error = buf_get_stringb(bufp, dbufp);
+ if (v9ses->extended)
+ rcall->params.rerror.errno = buf_get_int16(bufp);
+ break;
+ }
+
+ if (buf_check_overflow(bufp) || buf_check_overflow(dbufp))
+ return -EIO;
+
+ return rcall->size;
+}
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
new file mode 100644
index 000000000000..ee849613c61a
--- /dev/null
+++ b/fs/9p/conv.h
@@ -0,0 +1,36 @@
+/*
+ * linux/fs/9p/conv.h
+ *
+ * 9P protocol conversion definitions
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+int v9fs_deserialize_stat(struct v9fs_session_info *, void *buf,
+ u32 buflen, struct v9fs_stat *stat, u32 statlen);
+int v9fs_serialize_fcall(struct v9fs_session_info *, struct v9fs_fcall *tcall,
+ void *buf, u32 buflen);
+int v9fs_deserialize_fcall(struct v9fs_session_info *, u32 msglen,
+ void *buf, u32 buflen, struct v9fs_fcall *rcall,
+ int rcalllen);
+
+/* this one is actually in error.c right now */
+int v9fs_errstr2errno(char *errstr);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
new file mode 100644
index 000000000000..4445f06919d9
--- /dev/null
+++ b/fs/9p/debug.h
@@ -0,0 +1,70 @@
+/*
+ * linux/fs/9p/debug.h - V9FS Debug Definitions
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#define DEBUG_ERROR (1<<0)
+#define DEBUG_CURRENT (1<<1)
+#define DEBUG_9P (1<<2)
+#define DEBUG_VFS (1<<3)
+#define DEBUG_CONV (1<<4)
+#define DEBUG_MUX (1<<5)
+#define DEBUG_TRANS (1<<6)
+#define DEBUG_SLABS (1<<7)
+
+#define DEBUG_DUMP_PKT 0
+
+extern int v9fs_debug_level;
+
+#define dprintk(level, format, arg...) \
+do { \
+ if((v9fs_debug_level & level)==level) \
+ printk(KERN_NOTICE "-- %s (%d): " \
+ format , __FUNCTION__, current->pid , ## arg); \
+} while(0)
+
+#define eprintk(level, format, arg...) \
+do { \
+ printk(level "v9fs: %s (%d): " \
+ format , __FUNCTION__, current->pid , ## arg); \
+} while(0)
+
+#if DEBUG_DUMP_PKT
+static inline void dump_data(const unsigned char *data, unsigned int datalen)
+{
+ int i, j;
+ int len = datalen;
+
+ printk(KERN_DEBUG "data ");
+ for (i = 0; i < len; i += 4) {
+ for (j = 0; (j < 4) && (i + j < len); j++)
+ printk(KERN_DEBUG "%02x", data[i + j]);
+ printk(KERN_DEBUG " ");
+ }
+ printk(KERN_DEBUG "\n");
+}
+#else /* DEBUG_DUMP_PKT */
+static inline void dump_data(const unsigned char *data, unsigned int datalen)
+{
+
+}
+#endif /* DEBUG_DUMP_PKT */
diff --git a/fs/9p/error.c b/fs/9p/error.c
new file mode 100644
index 000000000000..fee5d19179c5
--- /dev/null
+++ b/fs/9p/error.c
@@ -0,0 +1,93 @@
+/*
+ * linux/fs/9p/error.c
+ *
+ * Error string handling
+ *
+ * Plan 9 uses error strings, Unix uses error numbers. These functions
+ * try to help manage that and provide for dynamically adding error
+ * mappings.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/list.h>
+#include <linux/jhash.h>
+
+#include "debug.h"
+#include "error.h"
+
+/**
+ * v9fs_error_init - preload
+ * @errstr: error string
+ *
+ */
+
+int v9fs_error_init(void)
+{
+ struct errormap *c;
+ int bucket;
+
+ /* initialize hash table */
+ for (bucket = 0; bucket < ERRHASHSZ; bucket++)
+ INIT_HLIST_HEAD(&hash_errmap[bucket]);
+
+ /* load initial error map into hash table */
+ for (c = errmap; c->name != NULL; c++) {
+ bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ;
+ INIT_HLIST_NODE(&c->list);
+ hlist_add_head(&c->list, &hash_errmap[bucket]);
+ }
+
+ return 1;
+}
+
+/**
+ * errstr2errno - convert error string to error number
+ * @errstr: error string
+ *
+ */
+
+int v9fs_errstr2errno(char *errstr)
+{
+ int errno = 0;
+ struct hlist_node *p = NULL;
+ struct errormap *c = NULL;
+ int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ;
+
+ hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
+ if (!strcmp(c->name, errstr)) {
+ errno = c->val;
+ break;
+ }
+ }
+
+ if (errno == 0) {
+ /* TODO: if error isn't found, add it dynamically */
+ printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
+ errstr);
+ errno = 1;
+ }
+
+ return -errno;
+}
diff --git a/fs/9p/error.h b/fs/9p/error.h
new file mode 100644
index 000000000000..78f89acf7c9a
--- /dev/null
+++ b/fs/9p/error.h
@@ -0,0 +1,178 @@
+/*
+ * linux/fs/9p/error.h
+ *
+ * Huge Nasty Error Table
+ *
+ * Plan 9 uses error strings, Unix uses error numbers. This table tries to
+ * match UNIX strings and Plan 9 strings to unix error numbers. It is used
+ * to preload the dynamic error table which can also track user-specific error
+ * strings.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/errno.h>
+#include <asm/errno.h>
+
+struct errormap {
+ char *name;
+ int val;
+
+ struct hlist_node list;
+};
+
+#define ERRHASHSZ 32
+static struct hlist_head hash_errmap[ERRHASHSZ];
+
+/* FixMe - reduce to a reasonable size */
+static struct errormap errmap[] = {
+ {"Operation not permitted", EPERM},
+ {"wstat prohibited", EPERM},
+ {"No such file or directory", ENOENT},
+ {"directory entry not found", ENOENT},
+ {"file not found", ENOENT},
+ {"Interrupted system call", EINTR},
+ {"Input/output error", EIO},
+ {"No such device or address", ENXIO},
+ {"Argument list too long", E2BIG},
+ {"Bad file descriptor", EBADF},
+ {"Resource temporarily unavailable", EAGAIN},
+ {"Cannot allocate memory", ENOMEM},
+ {"Permission denied", EACCES},
+ {"Bad address", EFAULT},
+ {"Block device required", ENOTBLK},
+ {"Device or resource busy", EBUSY},
+ {"File exists", EEXIST},
+ {"Invalid cross-device link", EXDEV},
+ {"No such device", ENODEV},
+ {"Not a directory", ENOTDIR},
+ {"Is a directory", EISDIR},
+ {"Invalid argument", EINVAL},
+ {"Too many open files in system", ENFILE},
+ {"Too many open files", EMFILE},
+ {"Text file busy", ETXTBSY},
+ {"File too large", EFBIG},
+ {"No space left on device", ENOSPC},
+ {"Illegal seek", ESPIPE},
+ {"Read-only file system", EROFS},
+ {"Too many links", EMLINK},
+ {"Broken pipe", EPIPE},
+ {"Numerical argument out of domain", EDOM},
+ {"Numerical result out of range", ERANGE},
+ {"Resource deadlock avoided", EDEADLK},
+ {"File name too long", ENAMETOOLONG},
+ {"No locks available", ENOLCK},
+ {"Function not implemented", ENOSYS},
+ {"Directory not empty", ENOTEMPTY},
+ {"Too many levels of symbolic links", ELOOP},
+ {"No message of desired type", ENOMSG},
+ {"Identifier removed", EIDRM},
+ {"No data available", ENODATA},
+ {"Machine is not on the network", ENONET},
+ {"Package not installed", ENOPKG},
+ {"Object is remote", EREMOTE},
+ {"Link has been severed", ENOLINK},
+ {"Communication error on send", ECOMM},
+ {"Protocol error", EPROTO},
+ {"Bad message", EBADMSG},
+ {"File descriptor in bad state", EBADFD},
+ {"Streams pipe error", ESTRPIPE},
+ {"Too many users", EUSERS},
+ {"Socket operation on non-socket", ENOTSOCK},
+ {"Message too long", EMSGSIZE},
+ {"Protocol not available", ENOPROTOOPT},
+ {"Protocol not supported", EPROTONOSUPPORT},
+ {"Socket type not supported", ESOCKTNOSUPPORT},
+ {"Operation not supported", EOPNOTSUPP},
+ {"Protocol family not supported", EPFNOSUPPORT},
+ {"Network is down", ENETDOWN},
+ {"Network is unreachable", ENETUNREACH},
+ {"Network dropped connection on reset", ENETRESET},
+ {"Software caused connection abort", ECONNABORTED},
+ {"Connection reset by peer", ECONNRESET},
+ {"No buffer space available", ENOBUFS},
+ {"Transport endpoint is already connected", EISCONN},
+ {"Transport endpoint is not connected", ENOTCONN},
+ {"Cannot send after transport endpoint shutdown", ESHUTDOWN},
+ {"Connection timed out", ETIMEDOUT},
+ {"Connection refused", ECONNREFUSED},
+ {"Host is down", EHOSTDOWN},
+ {"No route to host", EHOSTUNREACH},
+ {"Operation already in progress", EALREADY},
+ {"Operation now in progress", EINPROGRESS},
+ {"Is a named type file", EISNAM},
+ {"Remote I/O error", EREMOTEIO},
+ {"Disk quota exceeded", EDQUOT},
+/* errors from fossil, vacfs, and u9fs */
+ {"fid unknown or out of range", EBADF},
+ {"permission denied", EACCES},
+ {"file does not exist", ENOENT},
+ {"authentication failed", ECONNREFUSED},
+ {"bad offset in directory read", ESPIPE},
+ {"bad use of fid", EBADF},
+ {"wstat can't convert between files and directories", EPERM},
+ {"directory is not empty", ENOTEMPTY},
+ {"file exists", EEXIST},
+ {"file already exists", EEXIST},
+ {"file or directory already exists", EEXIST},
+ {"fid already in use", EBADF},
+ {"file in use", ETXTBSY},
+ {"i/o error", EIO},
+ {"file already open for I/O", ETXTBSY},
+ {"illegal mode", EINVAL},
+ {"illegal name", ENAMETOOLONG},
+ {"not a directory", ENOTDIR},
+ {"not a member of proposed group", EPERM},
+ {"not owner", EACCES},
+ {"only owner can change group in wstat", EACCES},
+ {"read only file system", EROFS},
+ {"no access to special file", EPERM},
+ {"i/o count too large", EIO},
+ {"unknown group", EINVAL},
+ {"unknown user", EINVAL},
+ {"bogus wstat buffer", EPROTO},
+ {"exclusive use file already open", EAGAIN},
+ {"corrupted directory entry", EIO},
+ {"corrupted file entry", EIO},
+ {"corrupted block label", EIO},
+ {"corrupted meta data", EIO},
+ {"illegal offset", EINVAL},
+ {"illegal path element", ENOENT},
+ {"root of file system is corrupted", EIO},
+ {"corrupted super block", EIO},
+ {"protocol botch", EPROTO},
+ {"file system is full", ENOSPC},
+ {"file is in use", EAGAIN},
+ {"directory entry is not allocated", ENOENT},
+ {"file is read only", EROFS},
+ {"file has been removed", EIDRM},
+ {"only support truncation to zero length", EPERM},
+ {"cannot remove root", EPERM},
+ {"file too big", EFBIG},
+ {"venti i/o error", EIO},
+ /* these are not errors */
+ {"u9fs rhostsauth: no authentication required", 0},
+ {"u9fs authnone: no authentication required", 0},
+ {NULL, -1}
+};
+
+extern int v9fs_error_init(void);
+extern int v9fs_errstr2errno(char *errstr);
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
new file mode 100644
index 000000000000..821c9c4d76aa
--- /dev/null
+++ b/fs/9p/fid.c
@@ -0,0 +1,241 @@
+/*
+ * V9FS FID Management
+ *
+ * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "transport.h"
+#include "mux.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * v9fs_fid_insert - add a fid to a dentry
+ * @fid: fid to add
+ * @dentry: dentry that it is being added to
+ *
+ */
+
+static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
+{
+ struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
+ dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
+ dentry->d_iname, dentry);
+ if (dentry->d_fsdata == NULL) {
+ dentry->d_fsdata =
+ kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (dentry->d_fsdata == NULL) {
+ dprintk(DEBUG_ERROR, "Out of memory\n");
+ return -ENOMEM;
+ }
+ fid_list = (struct list_head *)dentry->d_fsdata;
+ INIT_LIST_HEAD(fid_list); /* Initialize list head */
+ }
+
+ fid->uid = current->uid;
+ fid->pid = current->pid;
+ list_add(&fid->list, fid_list);
+ return 0;
+}
+
+/**
+ * v9fs_fid_create - allocate a FID structure
+ * @dentry - dentry to link newly created fid to
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_create(struct dentry *dentry)
+{
+ struct v9fs_fid *new;
+
+ new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+ if (new == NULL) {
+ dprintk(DEBUG_ERROR, "Out of Memory\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ new->fid = -1;
+ new->fidopen = 0;
+ new->fidcreate = 0;
+ new->fidclunked = 0;
+ new->iounit = 0;
+
+ if (v9fs_fid_insert(new, dentry) == 0)
+ return new;
+ else {
+ dprintk(DEBUG_ERROR, "Problems inserting to dentry\n");
+ kfree(new);
+ return NULL;
+ }
+}
+
+/**
+ * v9fs_fid_destroy - deallocate a FID structure
+ * @fid: fid to destroy
+ *
+ */
+
+void v9fs_fid_destroy(struct v9fs_fid *fid)
+{
+ list_del(&fid->list);
+ kfree(fid);
+}
+
+/**
+ * v9fs_fid_lookup - retrieve the right fid from a particular dentry
+ * @dentry: dentry to look for fid in
+ * @type: intent of lookup (operation or traversal)
+ *
+ * search list of fids associated with a dentry for a fid with a matching
+ * thread id or uid. If that fails, look up the dentry's parents to see if you
+ * can find a matching fid.
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type)
+{
+ struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
+ struct v9fs_fid *current_fid = NULL;
+ struct v9fs_fid *temp = NULL;
+ struct v9fs_fid *return_fid = NULL;
+ int found_parent = 0;
+ int found_user = 0;
+
+ dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry,
+ type);
+
+ if (fid_list && !list_empty(fid_list)) {
+ list_for_each_entry_safe(current_fid, temp, fid_list, list) {
+ if (current_fid->uid == current->uid) {
+ if (return_fid == NULL) {
+ if ((type == FID_OP)
+ || (!current_fid->fidopen)) {
+ return_fid = current_fid;
+ found_user = 1;
+ }
+ }
+ }
+ if (current_fid->pid == current->real_parent->pid) {
+ if ((return_fid == NULL) || (found_parent)
+ || (found_user)) {
+ if ((type == FID_OP)
+ || (!current_fid->fidopen)) {
+ return_fid = current_fid;
+ found_parent = 1;
+ found_user = 0;
+ }
+ }
+ }
+ if (current_fid->pid == current->pid) {
+ if ((type == FID_OP) ||
+ (!current_fid->fidopen)) {
+ return_fid = current_fid;
+ found_parent = 0;
+ found_user = 0;
+ }
+ }
+ }
+ }
+
+ /* we are at the root but didn't match */
+ if ((!return_fid) && (dentry->d_parent == dentry)) {
+ /* TODO: clone attach with new uid */
+ return_fid = current_fid;
+ }
+
+ if (!return_fid) {
+ struct dentry *par = current->fs->pwd->d_parent;
+ int count = 1;
+ while (par != NULL) {
+ if (par == dentry)
+ break;
+ count++;
+ if (par == par->d_parent) {
+ dprintk(DEBUG_ERROR,
+ "got to root without finding dentry\n");
+ break;
+ }
+ par = par->d_parent;
+ }
+
+/* XXX - there may be some duplication we can get rid of */
+ if (par == dentry) {
+ /* we need to fid_lookup the starting point */
+ int fidnum = -1;
+ int oldfid = -1;
+ int result = -1;
+ struct v9fs_session_info *v9ses =
+ v9fs_inode2v9ses(current->fs->pwd->d_inode);
+
+ current_fid =
+ v9fs_fid_lookup(current->fs->pwd, FID_WALK);
+ if (current_fid == NULL) {
+ dprintk(DEBUG_ERROR,
+ "process cwd doesn't have a fid\n");
+ return return_fid;
+ }
+ oldfid = current_fid->fid;
+ par = current->fs->pwd;
+ /* TODO: take advantage of multiwalk */
+
+ fidnum = v9fs_get_idpool(&v9ses->fidpool);
+ if (fidnum < 0) {
+ dprintk(DEBUG_ERROR,
+ "could not get a new fid num\n");
+ return return_fid;
+ }
+
+ while (par != dentry) {
+ result =
+ v9fs_t_walk(v9ses, oldfid, fidnum, "..",
+ NULL);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR,
+ "problem walking to parent\n");
+
+ break;
+ }
+ oldfid = fidnum;
+ if (par == par->d_parent) {
+ dprintk(DEBUG_ERROR,
+ "can't find dentry\n");
+ break;
+ }
+ par = par->d_parent;
+ }
+ if (par == dentry) {
+ return_fid = v9fs_fid_create(dentry);
+ return_fid->fid = fidnum;
+ }
+ }
+ }
+
+ return return_fid;
+}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
new file mode 100644
index 000000000000..7db478ccca36
--- /dev/null
+++ b/fs/9p/fid.h
@@ -0,0 +1,57 @@
+/*
+ * V9FS FID Management
+ *
+ * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/list.h>
+
+#define FID_OP 0
+#define FID_WALK 1
+
+struct v9fs_fid {
+ struct list_head list; /* list of fids associated with a dentry */
+ struct list_head active; /* XXX - debug */
+
+ u32 fid;
+ unsigned char fidopen; /* set when fid is opened */
+ unsigned char fidcreate; /* set when fid was just created */
+ unsigned char fidclunked; /* set when fid has already been clunked */
+
+ struct v9fs_qid qid;
+ u32 iounit;
+
+ /* readdir stuff */
+ int rdir_fpos;
+ loff_t rdir_pos;
+ struct v9fs_fcall *rdir_fcall;
+
+ /* management stuff */
+ pid_t pid; /* thread associated with this fid */
+ uid_t uid; /* user associated with this fid */
+
+ /* private data */
+ struct file *filp; /* backpointer to File struct for open files */
+ struct v9fs_session_info *v9ses; /* session info for this FID */
+};
+
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type);
+void v9fs_fid_destroy(struct v9fs_fid *fid);
+struct v9fs_fid *v9fs_fid_create(struct dentry *);
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
new file mode 100644
index 000000000000..8835b576f744
--- /dev/null
+++ b/fs/9p/mux.c
@@ -0,0 +1,475 @@
+/*
+ * linux/fs/9p/mux.c
+ *
+ * Protocol Multiplexer
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "transport.h"
+#include "conv.h"
+#include "mux.h"
+
+/**
+ * dprintcond - print condition of session info
+ * @v9ses: session info structure
+ * @req: RPC request structure
+ *
+ */
+
+static inline int
+dprintcond(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+ dprintk(DEBUG_MUX, "condition: %d, %p\n", v9ses->transport->status,
+ req->rcall);
+ return 0;
+}
+
+/**
+ * xread - force read of a certain number of bytes
+ * @v9ses: session info structure
+ * @ptr: pointer to buffer
+ * @sz: number of bytes to read
+ *
+ * Chuck Cranor CS-533 project1
+ */
+
+static int xread(struct v9fs_session_info *v9ses, void *ptr, unsigned long sz)
+{
+ int rd = 0;
+ int ret = 0;
+ while (rd < sz) {
+ ret = v9ses->transport->read(v9ses->transport, ptr, sz - rd);
+ if (ret <= 0) {
+ dprintk(DEBUG_ERROR, "xread errno %d\n", ret);
+ return ret;
+ }
+ rd += ret;
+ ptr += ret;
+ }
+ return (rd);
+}
+
+/**
+ * read_message - read a full 9P2000 fcall packet
+ * @v9ses: session info structure
+ * @rcall: fcall structure to read into
+ * @rcalllen: size of fcall buffer
+ *
+ */
+
+static int
+read_message(struct v9fs_session_info *v9ses,
+ struct v9fs_fcall *rcall, int rcalllen)
+{
+ unsigned char buf[4];
+ void *data;
+ int size = 0;
+ int res = 0;
+
+ res = xread(v9ses, buf, sizeof(buf));
+ if (res < 0) {
+ dprintk(DEBUG_ERROR,
+ "Reading of count field failed returned: %d\n", res);
+ return res;
+ }
+
+ if (res < 4) {
+ dprintk(DEBUG_ERROR,
+ "Reading of count field failed returned: %d\n", res);
+ return -EIO;
+ }
+
+ size = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+ dprintk(DEBUG_MUX, "got a packet count: %d\n", size);
+
+ /* adjust for the four bytes of size */
+ size -= 4;
+
+ if (size > v9ses->maxdata) {
+ dprintk(DEBUG_ERROR, "packet too big: %d\n", size);
+ return -E2BIG;
+ }
+
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data) {
+ eprintk(KERN_WARNING, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ res = xread(v9ses, data, size);
+ if (res < size) {
+ dprintk(DEBUG_ERROR, "Reading of fcall failed returned: %d\n",
+ res);
+ kfree(data);
+ return res;
+ }
+
+ /* we now have an in-memory string that is the reply.
+ * deserialize it. There is very little to go wrong at this point
+ * save for v9fs_alloc errors.
+ */
+ res = v9fs_deserialize_fcall(v9ses, size, data, v9ses->maxdata,
+ rcall, rcalllen);
+
+ kfree(data);
+
+ if (res < 0)
+ return res;
+
+ return 0;
+}
+
+/**
+ * v9fs_recv - receive an RPC response for a particular tag
+ * @v9ses: session info structure
+ * @req: RPC request structure
+ *
+ */
+
+static int v9fs_recv(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+ int ret = 0;
+
+ dprintk(DEBUG_MUX, "waiting for response: %d\n", req->tcall->tag);
+ ret = wait_event_interruptible(v9ses->read_wait,
+ ((v9ses->transport->status != Connected) ||
+ (req->rcall != 0) || (req->err < 0) ||
+ dprintcond(v9ses, req)));
+
+ dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall);
+
+ spin_lock(&v9ses->muxlock);
+ list_del(&req->next);
+ spin_unlock(&v9ses->muxlock);
+
+ if (req->err < 0)
+ return req->err;
+
+ if (v9ses->transport->status == Disconnected)
+ return -ECONNRESET;
+
+ return ret;
+}
+
+/**
+ * v9fs_send - send a 9P request
+ * @v9ses: session info structure
+ * @req: RPC request to send
+ *
+ */
+
+static int v9fs_send(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+ int ret = -1;
+ void *data = NULL;
+ struct v9fs_fcall *tcall = req->tcall;
+
+ data = kmalloc(v9ses->maxdata + V9FS_IOHDRSZ, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ tcall->size = 0; /* enforce size recalculation */
+ ret =
+ v9fs_serialize_fcall(v9ses, tcall, data,
+ v9ses->maxdata + V9FS_IOHDRSZ);
+ if (ret < 0)
+ goto free_data;
+
+ spin_lock(&v9ses->muxlock);
+ list_add(&req->next, &v9ses->mux_fcalls);
+ spin_unlock(&v9ses->muxlock);
+
+ dprintk(DEBUG_MUX, "sending message: tag %d size %d\n", tcall->tag,
+ tcall->size);
+ ret = v9ses->transport->write(v9ses->transport, data, tcall->size);
+
+ if (ret != tcall->size) {
+ spin_lock(&v9ses->muxlock);
+ list_del(&req->next);
+ kfree(req->rcall);
+
+ spin_unlock(&v9ses->muxlock);
+ if (ret >= 0)
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
+
+ free_data:
+ kfree(data);
+ return ret;
+}
+
+/**
+ * v9fs_mux_rpc - send a request, receive a response
+ * @v9ses: session info structure
+ * @tcall: fcall to send
+ * @rcall: buffer to place response into
+ *
+ */
+
+long
+v9fs_mux_rpc(struct v9fs_session_info *v9ses, struct v9fs_fcall *tcall,
+ struct v9fs_fcall **rcall)
+{
+ int tid = -1;
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_rpcreq req;
+ int ret = -1;
+
+ if (!v9ses)
+ return -EINVAL;
+
+ if (!v9ses->transport || v9ses->transport->status != Connected)
+ return -EIO;
+
+ if (rcall)
+ *rcall = NULL;
+
+ if (tcall->id != TVERSION) {
+ tid = v9fs_get_idpool(&v9ses->tidpool);
+ if (tid < 0)
+ return -ENOMEM;
+ }
+
+ tcall->tag = tid;
+
+ req.tcall = tcall;
+ req.err = 0;
+ req.rcall = NULL;
+
+ ret = v9fs_send(v9ses, &req);
+
+ if (ret < 0) {
+ if (tcall->id != TVERSION)
+ v9fs_put_idpool(tid, &v9ses->tidpool);
+ dprintk(DEBUG_MUX, "error %d\n", ret);
+ return ret;
+ }
+
+ ret = v9fs_recv(v9ses, &req);
+
+ fcall = req.rcall;
+
+ dprintk(DEBUG_MUX, "received: tag=%x, ret=%d\n", tcall->tag, ret);
+ if (ret == -ERESTARTSYS) {
+ if (v9ses->transport->status != Disconnected
+ && tcall->id != TFLUSH) {
+ unsigned long flags;
+
+ dprintk(DEBUG_MUX, "flushing the tag: %d\n",
+ tcall->tag);
+ clear_thread_flag(TIF_SIGPENDING);
+ v9fs_t_flush(v9ses, tcall->tag);
+ spin_lock_irqsave(&current->sighand->siglock, flags);
+ recalc_sigpending();
+ spin_unlock_irqrestore(&current->sighand->siglock,
+ flags);
+ dprintk(DEBUG_MUX, "flushing done\n");
+ }
+
+ goto release_req;
+ } else if (ret < 0)
+ goto release_req;
+
+ if (!fcall)
+ ret = -EIO;
+ else {
+ if (fcall->id == RERROR) {
+ ret = v9fs_errstr2errno(fcall->params.rerror.error);
+ if (ret == 0) { /* string match failed */
+ if (fcall->params.rerror.errno)
+ ret = -(fcall->params.rerror.errno);
+ else
+ ret = -ESERVERFAULT;
+ }
+ } else if (fcall->id != tcall->id + 1) {
+ dprintk(DEBUG_ERROR,
+ "fcall mismatch: expected %d, got %d\n",
+ tcall->id + 1, fcall->id);
+ ret = -EIO;
+ }
+ }
+
+ release_req:
+ if (tcall->id != TVERSION)
+ v9fs_put_idpool(tid, &v9ses->tidpool);
+ if (rcall)
+ *rcall = fcall;
+ else
+ kfree(fcall);
+
+ return ret;
+}
+
+/**
+ * v9fs_mux_cancel_requests - cancels all pending requests
+ *
+ * @v9ses: session info structure
+ * @err: error code to return to the requests
+ */
+void v9fs_mux_cancel_requests(struct v9fs_session_info *v9ses, int err)
+{
+ struct v9fs_rpcreq *rptr;
+ struct v9fs_rpcreq *rreq;
+
+ dprintk(DEBUG_MUX, " %d\n", err);
+ spin_lock(&v9ses->muxlock);
+ list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+ rreq->err = err;
+ }
+ spin_unlock(&v9ses->muxlock);
+ wake_up_all(&v9ses->read_wait);
+}
+
+/**
+ * v9fs_recvproc - kproc to handle demultiplexing responses
+ * @data: session info structure
+ *
+ */
+
+static int v9fs_recvproc(void *data)
+{
+ struct v9fs_session_info *v9ses = (struct v9fs_session_info *)data;
+ struct v9fs_fcall *rcall = NULL;
+ struct v9fs_rpcreq *rptr;
+ struct v9fs_rpcreq *req;
+ struct v9fs_rpcreq *rreq;
+ int err = 0;
+
+ allow_signal(SIGKILL);
+ set_current_state(TASK_INTERRUPTIBLE);
+ complete(&v9ses->proccmpl);
+ while (!kthread_should_stop() && err >= 0) {
+ req = rptr = rreq = NULL;
+
+ rcall = kmalloc(v9ses->maxdata + V9FS_IOHDRSZ, GFP_KERNEL);
+ if (!rcall) {
+ eprintk(KERN_ERR, "no memory for buffers\n");
+ break;
+ }
+
+ err = read_message(v9ses, rcall, v9ses->maxdata + V9FS_IOHDRSZ);
+ spin_lock(&v9ses->muxlock);
+ if (err < 0) {
+ list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+ rreq->err = err;
+ }
+ if(err != -ERESTARTSYS)
+ eprintk(KERN_ERR,
+ "Transport error while reading message %d\n", err);
+ } else {
+ list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+ if (rreq->tcall->tag == rcall->tag) {
+ req = rreq;
+ req->rcall = rcall;
+ break;
+ }
+ }
+ }
+
+ if (req && (req->tcall->id == TFLUSH)) {
+ struct v9fs_rpcreq *treq = NULL;
+ list_for_each_entry_safe(treq, rptr, &v9ses->mux_fcalls, next) {
+ if (treq->tcall->tag ==
+ req->tcall->params.tflush.oldtag) {
+ list_del(&rptr->next);
+ kfree(treq->rcall);
+ break;
+ }
+ }
+ }
+
+ spin_unlock(&v9ses->muxlock);
+
+ if (!req) {
+ if (err >= 0)
+ dprintk(DEBUG_ERROR,
+ "unexpected response: id %d tag %d\n",
+ rcall->id, rcall->tag);
+
+ kfree(rcall);
+ }
+
+ wake_up_all(&v9ses->read_wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ v9ses->transport->close(v9ses->transport);
+
+ /* Inform all pending processes about the failure */
+ wake_up_all(&v9ses->read_wait);
+
+ if (signal_pending(current))
+ complete(&v9ses->proccmpl);
+
+ dprintk(DEBUG_MUX, "recvproc: end\n");
+ v9ses->recvproc = NULL;
+
+ return err >= 0;
+}
+
+/**
+ * v9fs_mux_init - initialize multiplexer (spawn kproc)
+ * @v9ses: session info structure
+ * @dev_name: mount device information (to create unique kproc)
+ *
+ */
+
+int v9fs_mux_init(struct v9fs_session_info *v9ses, const char *dev_name)
+{
+ char procname[60];
+
+ strncpy(procname, dev_name, sizeof(procname));
+ procname[sizeof(procname) - 1] = 0;
+
+ init_waitqueue_head(&v9ses->read_wait);
+ init_completion(&v9ses->fcread);
+ init_completion(&v9ses->proccmpl);
+ spin_lock_init(&v9ses->muxlock);
+ INIT_LIST_HEAD(&v9ses->mux_fcalls);
+ v9ses->recvproc = NULL;
+ v9ses->curfcall = NULL;
+
+ v9ses->recvproc = kthread_create(v9fs_recvproc, v9ses,
+ "v9fs_recvproc %s", procname);
+
+ if (IS_ERR(v9ses->recvproc)) {
+ eprintk(KERN_ERR, "cannot create receiving thread\n");
+ v9fs_session_close(v9ses);
+ return -ECONNABORTED;
+ }
+
+ wake_up_process(v9ses->recvproc);
+ wait_for_completion(&v9ses->proccmpl);
+
+ return 0;
+}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
new file mode 100644
index 000000000000..4994cb10badf
--- /dev/null
+++ b/fs/9p/mux.h
@@ -0,0 +1,41 @@
+/*
+ * linux/fs/9p/mux.h
+ *
+ * Multiplexer Definitions
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+/* structure to manage each RPC transaction */
+
+struct v9fs_rpcreq {
+ struct v9fs_fcall *tcall;
+ struct v9fs_fcall *rcall;
+ int err; /* error code if response failed */
+
+ /* XXX - could we put scatter/gather buffers here? */
+
+ struct list_head next;
+};
+
+int v9fs_mux_init(struct v9fs_session_info *v9ses, const char *dev_name);
+long v9fs_mux_rpc(struct v9fs_session_info *v9ses,
+ struct v9fs_fcall *tcall, struct v9fs_fcall **rcall);
+void v9fs_mux_cancel_requests(struct v9fs_session_info *v9ses, int err);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
new file mode 100644
index 000000000000..63b58ce98ff4
--- /dev/null
+++ b/fs/9p/trans_fd.c
@@ -0,0 +1,172 @@
+/*
+ * linux/fs/9p/trans_fd.c
+ *
+ * File Descriptor Transport Layer
+ *
+ * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "transport.h"
+
+struct v9fs_trans_fd {
+ struct file *in_file;
+ struct file *out_file;
+};
+
+/**
+ * v9fs_fd_recv - receive from a socket
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+
+static int v9fs_fd_recv(struct v9fs_transport *trans, void *v, int len)
+{
+ struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+
+ if (!trans || trans->status != Connected || !ts)
+ return -EIO;
+
+ return kernel_read(ts->in_file, ts->in_file->f_pos, v, len);
+}
+
+/**
+ * v9fs_fd_send - send to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+
+static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len)
+{
+ struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+ mm_segment_t oldfs = get_fs();
+ int ret = 0;
+
+ if (!trans || trans->status != Connected || !ts)
+ return -EIO;
+
+ set_fs(get_ds());
+ /* The cast to a user pointer is valid due to the set_fs() */
+ ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos);
+ set_fs(oldfs);
+
+ return ret;
+}
+
+/**
+ * v9fs_fd_init - initialize file descriptor transport
+ * @v9ses: session information
+ * @addr: address of server to mount
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+ struct v9fs_trans_fd *ts = NULL;
+ struct v9fs_transport *trans = v9ses->transport;
+
+ if((v9ses->wfdno == ~0) || (v9ses->rfdno == ~0)) {
+ printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+ return -ENOPROTOOPT;
+ }
+
+ sema_init(&trans->writelock, 1);
+ sema_init(&trans->readlock, 1);
+
+ ts = kmalloc(sizeof(struct v9fs_trans_fd), GFP_KERNEL);
+
+ if (!ts)
+ return -ENOMEM;
+
+ ts->in_file = fget( v9ses->rfdno );
+ ts->out_file = fget( v9ses->wfdno );
+
+ if (!ts->in_file || !ts->out_file) {
+ if (ts->in_file)
+ fput(ts->in_file);
+
+ if (ts->out_file)
+ fput(ts->out_file);
+
+ kfree(ts);
+ return -EIO;
+ }
+
+ trans->priv = ts;
+ trans->status = Connected;
+
+ return 0;
+}
+
+
+/**
+ * v9fs_fd_close - shutdown file descriptor
+ * @trans: private socket structure
+ *
+ */
+
+static void v9fs_fd_close(struct v9fs_transport *trans)
+{
+ struct v9fs_trans_fd *ts;
+
+ if (!trans)
+ return;
+
+ trans->status = Disconnected;
+ ts = trans->priv;
+
+ if (!ts)
+ return;
+
+ if (ts->in_file)
+ fput(ts->in_file);
+
+ if (ts->out_file)
+ fput(ts->out_file);
+
+ kfree(ts);
+}
+
+struct v9fs_transport v9fs_trans_fd = {
+ .init = v9fs_fd_init,
+ .write = v9fs_fd_send,
+ .read = v9fs_fd_recv,
+ .close = v9fs_fd_close,
+};
+
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
new file mode 100644
index 000000000000..01e26f0013ac
--- /dev/null
+++ b/fs/9p/trans_sock.c
@@ -0,0 +1,290 @@
+/*
+ * linux/fs/9p/trans_socket.c
+ *
+ * Socket Transport Layer
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
+ * Copyright (C) 1995, 1996 by Olaf Kirch <okir@monad.swb.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; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "transport.h"
+
+#define V9FS_PORT 564
+
+struct v9fs_trans_sock {
+ struct socket *s;
+};
+
+/**
+ * v9fs_sock_recv - receive from a socket
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+
+static int v9fs_sock_recv(struct v9fs_transport *trans, void *v, int len)
+{
+ struct msghdr msg;
+ struct kvec iov;
+ int result;
+ mm_segment_t oldfs;
+ struct v9fs_trans_sock *ts = trans ? trans->priv : NULL;
+
+ if (trans->status == Disconnected)
+ return -EREMOTEIO;
+
+ result = -EINVAL;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+
+ iov.iov_base = v;
+ iov.iov_len = len;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = MSG_NOSIGNAL;
+
+ result = kernel_recvmsg(ts->s, &msg, &iov, 1, len, 0);
+
+ dprintk(DEBUG_TRANS, "socket state %d\n", ts->s->state);
+ set_fs(oldfs);
+
+ if (result <= 0) {
+ if (result != -ERESTARTSYS)
+ trans->status = Disconnected;
+ }
+
+ return result;
+}
+
+/**
+ * v9fs_sock_send - send to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+
+static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
+{
+ struct kvec iov;
+ struct msghdr msg;
+ int result = -1;
+ mm_segment_t oldfs;
+ struct v9fs_trans_sock *ts = trans ? trans->priv : NULL;
+
+ dprintk(DEBUG_TRANS, "Sending packet size %d (%x)\n", len, len);
+ dump_data(v, len);
+
+ down(&trans->writelock);
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ iov.iov_base = v;
+ iov.iov_len = len;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = MSG_NOSIGNAL;
+ result = kernel_sendmsg(ts->s, &msg, &iov, 1, len);
+ set_fs(oldfs);
+
+ if (result < 0) {
+ if (result != -ERESTARTSYS)
+ trans->status = Disconnected;
+ }
+
+ up(&trans->writelock);
+ return result;
+}
+
+/**
+ * v9fs_tcp_init - initialize TCP socket
+ * @v9ses: session information
+ * @addr: address of server to mount
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+ struct socket *csocket = NULL;
+ struct sockaddr_in sin_server;
+ int rc = 0;
+ struct v9fs_trans_sock *ts = NULL;
+ struct v9fs_transport *trans = v9ses->transport;
+
+ sema_init(&trans->writelock, 1);
+ sema_init(&trans->readlock, 1);
+
+ ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
+
+ if (!ts)
+ return -ENOMEM;
+
+ trans->priv = ts;
+ ts->s = NULL;
+
+ if (!addr)
+ return -EINVAL;
+
+ dprintk(DEBUG_TRANS, "Connecting to %s\n", addr);
+
+ sin_server.sin_family = AF_INET;
+ sin_server.sin_addr.s_addr = in_aton(addr);
+ sin_server.sin_port = htons(v9ses->port);
+ sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+ rc = csocket->ops->connect(csocket,
+ (struct sockaddr *)&sin_server,
+ sizeof(struct sockaddr_in), 0);
+ if (rc < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_tcp: problem connecting socket to %s\n",
+ addr);
+ return rc;
+ }
+ csocket->sk->sk_allocation = GFP_NOIO;
+ ts->s = csocket;
+ trans->status = Connected;
+
+ return 0;
+}
+
+/**
+ * v9fs_unix_init - initialize UNIX domain socket
+ * @v9ses: session information
+ * @dev_name: path to named pipe
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
+ char *data)
+{
+ int rc;
+ struct socket *csocket;
+ struct sockaddr_un sun_server;
+ struct v9fs_transport *trans;
+ struct v9fs_trans_sock *ts;
+
+ rc = 0;
+ csocket = NULL;
+ trans = v9ses->transport;
+
+ if (strlen(dev_name) > UNIX_PATH_MAX) {
+ eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
+ dev_name);
+ return -ENOMEM;
+ }
+
+ ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ trans->priv = ts;
+ ts->s = NULL;
+
+ sema_init(&trans->writelock, 1);
+ sema_init(&trans->readlock, 1);
+
+ sun_server.sun_family = PF_UNIX;
+ strcpy(sun_server.sun_path, dev_name);
+ sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+ rc = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+ sizeof(struct sockaddr_un) - 1, 0); /* -1 *is* important */
+ if (rc < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_unix: problem connecting socket: %s: %d\n",
+ dev_name, rc);
+ return rc;
+ }
+ csocket->sk->sk_allocation = GFP_NOIO;
+ ts->s = csocket;
+ trans->status = Connected;
+
+ return 0;
+}
+
+/**
+ * v9fs_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+
+static void v9fs_sock_close(struct v9fs_transport *trans)
+{
+ struct v9fs_trans_sock *ts;
+
+ if (!trans)
+ return;
+
+ ts = trans->priv;
+
+ if ((ts) && (ts->s)) {
+ dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s);
+ sock_release(ts->s);
+ ts->s = NULL;
+ trans->status = Disconnected;
+ dprintk(DEBUG_TRANS, "socket closed\n");
+ }
+
+ if (ts)
+ kfree(ts);
+
+ trans->priv = NULL;
+}
+
+struct v9fs_transport v9fs_trans_tcp = {
+ .init = v9fs_tcp_init,
+ .write = v9fs_sock_send,
+ .read = v9fs_sock_recv,
+ .close = v9fs_sock_close,
+};
+
+struct v9fs_transport v9fs_trans_unix = {
+ .init = v9fs_unix_init,
+ .write = v9fs_sock_send,
+ .read = v9fs_sock_recv,
+ .close = v9fs_sock_close,
+};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
new file mode 100644
index 000000000000..9e9cd418efd5
--- /dev/null
+++ b/fs/9p/transport.h
@@ -0,0 +1,46 @@
+/*
+ * linux/fs/9p/transport.h
+ *
+ * Transport Definition
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+enum v9fs_transport_status {
+ Connected,
+ Disconnected,
+ Hung,
+};
+
+struct v9fs_transport {
+ enum v9fs_transport_status status;
+ struct semaphore writelock;
+ struct semaphore readlock;
+ void *priv;
+
+ int (*init) (struct v9fs_session_info *, const char *, char *);
+ int (*write) (struct v9fs_transport *, void *, int);
+ int (*read) (struct v9fs_transport *, void *, int);
+ void (*close) (struct v9fs_transport *);
+};
+
+extern struct v9fs_transport v9fs_trans_tcp;
+extern struct v9fs_transport v9fs_trans_unix;
+extern struct v9fs_transport v9fs_trans_fd;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
new file mode 100644
index 000000000000..13bdbbab4387
--- /dev/null
+++ b/fs/9p/v9fs.c
@@ -0,0 +1,452 @@
+/*
+ * linux/fs/9p/v9fs.c
+ *
+ * This file contains functions assisting in mapping VFS to 9P2000
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/parser.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "transport.h"
+#include "mux.h"
+#include "conv.h"
+
+/* TODO: sysfs or debugfs interface */
+int v9fs_debug_level = 0; /* feature-rific global debug level */
+
+/*
+ * Option Parsing (code inspired by NFS code)
+ *
+ */
+
+enum {
+ /* Options that take integer arguments */
+ Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
+ Opt_rfdno, Opt_wfdno,
+ /* String options */
+ Opt_name, Opt_remotename,
+ /* Options that take no arguments */
+ Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+ /* Error token */
+ Opt_err
+};
+
+static match_table_t tokens = {
+ {Opt_port, "port=%u"},
+ {Opt_msize, "msize=%u"},
+ {Opt_uid, "uid=%u"},
+ {Opt_gid, "gid=%u"},
+ {Opt_afid, "afid=%u"},
+ {Opt_rfdno, "rfdno=%u"},
+ {Opt_wfdno, "wfdno=%u"},
+ {Opt_debug, "debug=%u"},
+ {Opt_name, "name=%s"},
+ {Opt_remotename, "aname=%s"},
+ {Opt_unix, "proto=unix"},
+ {Opt_tcp, "proto=tcp"},
+ {Opt_fd, "proto=fd"},
+ {Opt_tcp, "tcp"},
+ {Opt_unix, "unix"},
+ {Opt_fd, "fd"},
+ {Opt_legacy, "noextend"},
+ {Opt_nodevmap, "nodevmap"},
+ {Opt_err, NULL}
+};
+
+/*
+ * Parse option string.
+ */
+
+/**
+ * v9fs_parse_options - parse mount options into session structure
+ * @options: options string passed from mount
+ * @v9ses: existing v9fs session information
+ *
+ */
+
+static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ int ret;
+
+ /* setup defaults */
+ v9ses->port = V9FS_PORT;
+ v9ses->maxdata = 9000;
+ v9ses->proto = PROTO_TCP;
+ v9ses->extended = 1;
+ v9ses->afid = ~0;
+ v9ses->debug = 0;
+ v9ses->rfdno = ~0;
+ v9ses->wfdno = ~0;
+
+ if (!options)
+ return;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ if (!*p)
+ continue;
+ token = match_token(p, tokens, args);
+ if (token < Opt_name) {
+ if ((ret = match_int(&args[0], &option)) < 0) {
+ dprintk(DEBUG_ERROR,
+ "integer field, but no integer?\n");
+ continue;
+ }
+
+ }
+ switch (token) {
+ case Opt_port:
+ v9ses->port = option;
+ break;
+ case Opt_msize:
+ v9ses->maxdata = option;
+ break;
+ case Opt_uid:
+ v9ses->uid = option;
+ break;
+ case Opt_gid:
+ v9ses->gid = option;
+ break;
+ case Opt_afid:
+ v9ses->afid = option;
+ break;
+ case Opt_rfdno:
+ v9ses->rfdno = option;
+ break;
+ case Opt_wfdno:
+ v9ses->wfdno = option;
+ break;
+ case Opt_debug:
+ v9ses->debug = option;
+ break;
+ case Opt_tcp:
+ v9ses->proto = PROTO_TCP;
+ break;
+ case Opt_unix:
+ v9ses->proto = PROTO_UNIX;
+ break;
+ case Opt_fd:
+ v9ses->proto = PROTO_FD;
+ break;
+ case Opt_name:
+ match_strcpy(v9ses->name, &args[0]);
+ break;
+ case Opt_remotename:
+ match_strcpy(v9ses->remotename, &args[0]);
+ break;
+ case Opt_legacy:
+ v9ses->extended = 0;
+ break;
+ case Opt_nodevmap:
+ v9ses->nodev = 1;
+ break;
+ default:
+ continue;
+ }
+ }
+}
+
+/**
+ * v9fs_inode2v9ses - safely extract v9fs session info from super block
+ * @inode: inode to extract information from
+ *
+ * Paranoid function to extract v9ses information from superblock,
+ * if anything is missing it will report an error.
+ *
+ */
+
+struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
+{
+ return (inode->i_sb->s_fs_info);
+}
+
+/**
+ * v9fs_get_idpool - allocate numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ * the lock included in struct idr?
+ */
+
+int v9fs_get_idpool(struct v9fs_idpool *p)
+{
+ int i = 0;
+ int error;
+
+retry:
+ if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
+ return 0;
+
+ if (down_interruptible(&p->lock) == -EINTR) {
+ eprintk(KERN_WARNING, "Interrupted while locking\n");
+ return -1;
+ }
+
+ error = idr_get_new(&p->pool, NULL, &i);
+ up(&p->lock);
+
+ if (error == -EAGAIN)
+ goto retry;
+ else if (error)
+ return -1;
+
+ return i;
+}
+
+/**
+ * v9fs_put_idpool - release numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ * the lock included in struct idr?
+ */
+
+void v9fs_put_idpool(int id, struct v9fs_idpool *p)
+{
+ if (down_interruptible(&p->lock) == -EINTR) {
+ eprintk(KERN_WARNING, "Interrupted while locking\n");
+ return;
+ }
+ idr_remove(&p->pool, id);
+ up(&p->lock);
+}
+
+/**
+ * v9fs_session_init - initialize session
+ * @v9ses: session information structure
+ * @dev_name: device being mounted
+ * @data: options
+ *
+ */
+
+int
+v9fs_session_init(struct v9fs_session_info *v9ses,
+ const char *dev_name, char *data)
+{
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_transport *trans_proto;
+ int n = 0;
+ int newfid = -1;
+ int retval = -EINVAL;
+
+ v9ses->name = __getname();
+ if (!v9ses->name)
+ return -ENOMEM;
+
+ v9ses->remotename = __getname();
+ if (!v9ses->remotename) {
+ putname(v9ses->name);
+ return -ENOMEM;
+ }
+
+ strcpy(v9ses->name, V9FS_DEFUSER);
+ strcpy(v9ses->remotename, V9FS_DEFANAME);
+
+ v9fs_parse_options(data, v9ses);
+
+ /* set global debug level */
+ v9fs_debug_level = v9ses->debug;
+
+ /* id pools that are session-dependent: FIDs and TIDs */
+ idr_init(&v9ses->fidpool.pool);
+ init_MUTEX(&v9ses->fidpool.lock);
+ idr_init(&v9ses->tidpool.pool);
+ init_MUTEX(&v9ses->tidpool.lock);
+
+
+ switch (v9ses->proto) {
+ case PROTO_TCP:
+ trans_proto = &v9fs_trans_tcp;
+ break;
+ case PROTO_UNIX:
+ trans_proto = &v9fs_trans_unix;
+ *v9ses->remotename = 0;
+ break;
+ case PROTO_FD:
+ trans_proto = &v9fs_trans_fd;
+ *v9ses->remotename = 0;
+ break;
+ default:
+ printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
+ retval = -ENOPROTOOPT;
+ goto SessCleanUp;
+ };
+
+ v9ses->transport = trans_proto;
+
+ if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
+ eprintk(KERN_ERR, "problem initializing transport\n");
+ goto SessCleanUp;
+ }
+
+ v9ses->inprogress = 0;
+ v9ses->shutdown = 0;
+ v9ses->session_hung = 0;
+
+ if ((retval = v9fs_mux_init(v9ses, dev_name)) < 0) {
+ dprintk(DEBUG_ERROR, "problem initializing mux\n");
+ goto SessCleanUp;
+ }
+
+ if (v9ses->afid == ~0) {
+ if (v9ses->extended)
+ retval =
+ v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
+ &fcall);
+ else
+ retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
+ &fcall);
+
+ if (retval < 0) {
+ dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
+ goto FreeFcall;
+ }
+
+ /* Really should check for 9P1 and report error */
+ if (!strcmp(fcall->params.rversion.version, "9P2000.u")) {
+ dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
+ v9ses->extended = 1;
+ } else {
+ dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
+ v9ses->extended = 0;
+ }
+
+ n = fcall->params.rversion.msize;
+ kfree(fcall);
+
+ if (n < v9ses->maxdata)
+ v9ses->maxdata = n;
+ }
+
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "couldn't allocate FID\n");
+ retval = -ENOMEM;
+ goto SessCleanUp;
+ }
+ /* it is a little bit ugly, but we have to prevent newfid */
+ /* being the same as afid, so if it is, get a new fid */
+ if (v9ses->afid != ~0 && newfid == v9ses->afid) {
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "couldn't allocate FID\n");
+ retval = -ENOMEM;
+ goto SessCleanUp;
+ }
+ }
+
+ if ((retval =
+ v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
+ v9ses->afid, NULL))
+ < 0) {
+ dprintk(DEBUG_ERROR, "cannot attach\n");
+ goto SessCleanUp;
+ }
+
+ if (v9ses->afid != ~0) {
+ if (v9fs_t_clunk(v9ses, v9ses->afid, NULL))
+ dprintk(DEBUG_ERROR, "clunk failed\n");
+ }
+
+ return newfid;
+
+ FreeFcall:
+ kfree(fcall);
+
+ SessCleanUp:
+ v9fs_session_close(v9ses);
+ return retval;
+}
+
+/**
+ * v9fs_session_close - shutdown a session
+ * @v9ses: session information structure
+ *
+ */
+
+void v9fs_session_close(struct v9fs_session_info *v9ses)
+{
+ if (v9ses->recvproc) {
+ send_sig(SIGKILL, v9ses->recvproc, 1);
+ wait_for_completion(&v9ses->proccmpl);
+ }
+
+ if (v9ses->transport)
+ v9ses->transport->close(v9ses->transport);
+
+ putname(v9ses->name);
+ putname(v9ses->remotename);
+}
+
+/**
+ * v9fs_session_cancel - mark transport as disconnected
+ * and cancel all pending requests.
+ */
+void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
+ v9ses->transport->status = Disconnected;
+ v9fs_mux_cancel_requests(v9ses, -EIO);
+}
+
+extern int v9fs_error_init(void);
+
+/**
+ * v9fs_init - Initialize module
+ *
+ */
+
+static int __init init_v9fs(void)
+{
+ v9fs_error_init();
+
+ printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
+
+ return register_filesystem(&v9fs_fs_type);
+}
+
+/**
+ * v9fs_init - shutdown module
+ *
+ */
+
+static void __exit exit_v9fs(void)
+{
+ unregister_filesystem(&v9fs_fs_type);
+}
+
+module_init(init_v9fs)
+module_exit(exit_v9fs)
+
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
+MODULE_LICENSE("GPL");
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
new file mode 100644
index 000000000000..45dcef42bdd6
--- /dev/null
+++ b/fs/9p/v9fs.h
@@ -0,0 +1,103 @@
+/*
+ * V9FS definitions.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+/*
+ * Idpool structure provides lock and id management
+ *
+ */
+
+struct v9fs_idpool {
+ struct semaphore lock;
+ struct idr pool;
+};
+
+/*
+ * Session structure provides information for an opened session
+ *
+ */
+
+struct v9fs_session_info {
+ /* options */
+ unsigned int maxdata;
+ unsigned char extended; /* set to 1 if we are using UNIX extensions */
+ unsigned char nodev; /* set to 1 if no disable device mapping */
+ unsigned short port; /* port to connect to */
+ unsigned short debug; /* debug level */
+ unsigned short proto; /* protocol to use */
+ unsigned int afid; /* authentication fid */
+ unsigned int rfdno; /* read file descriptor number */
+ unsigned int wfdno; /* write file descriptor number */
+
+
+ char *name; /* user name to mount as */
+ char *remotename; /* name of remote hierarchy being mounted */
+ unsigned int uid; /* default uid/muid for legacy support */
+ unsigned int gid; /* default gid for legacy support */
+
+ /* book keeping */
+ struct v9fs_idpool fidpool; /* The FID pool for file descriptors */
+ struct v9fs_idpool tidpool; /* The TID pool for transactions ids */
+
+ /* transport information */
+ struct v9fs_transport *transport;
+
+ int inprogress; /* session in progress => true */
+ int shutdown; /* session shutting down. no more attaches. */
+ unsigned char session_hung;
+
+ /* mux private data */
+ struct v9fs_fcall *curfcall;
+ wait_queue_head_t read_wait;
+ struct completion fcread;
+ struct completion proccmpl;
+ struct task_struct *recvproc;
+
+ spinlock_t muxlock;
+ struct list_head mux_fcalls;
+};
+
+/* possible values of ->proto */
+enum {
+ PROTO_TCP,
+ PROTO_UNIX,
+ PROTO_FD,
+};
+
+int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
+struct v9fs_session_info *v9fs_inode2v9ses(struct inode *);
+void v9fs_session_close(struct v9fs_session_info *v9ses);
+int v9fs_get_idpool(struct v9fs_idpool *p);
+void v9fs_put_idpool(int id, struct v9fs_idpool *p);
+void v9fs_session_cancel(struct v9fs_session_info *v9ses);
+
+#define V9FS_MAGIC 0x01021997
+
+/* other default globals */
+#define V9FS_PORT 564
+#define V9FS_DEFUSER "nobody"
+#define V9FS_DEFANAME ""
+
+/* inital pool sizes for fids and tags */
+#define V9FS_START_FIDS 8192
+#define V9FS_START_TIDS 256
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
new file mode 100644
index 000000000000..2f2cea7ee3e7
--- /dev/null
+++ b/fs/9p/v9fs_vfs.h
@@ -0,0 +1,53 @@
+/*
+ * V9FS VFS extensions.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+/* plan9 semantics are that created files are implicitly opened.
+ * But linux semantics are that you call create, then open.
+ * the plan9 approach is superior as it provides an atomic
+ * open.
+ * we track the create fid here. When the file is opened, if fidopen is
+ * non-zero, we use the fid and can skip some steps.
+ * there may be a better way to do this, but I don't know it.
+ * one BAD way is to clunk the fid on create, then open it again:
+ * you lose the atomicity of file open
+ */
+
+/* special case:
+ * unlink calls remove, which is an implicit clunk. So we have to track
+ * that kind of thing so that we don't try to clunk a dead fid.
+ */
+
+extern struct file_system_type v9fs_fs_type;
+extern struct file_operations v9fs_file_operations;
+extern struct file_operations v9fs_dir_operations;
+extern struct dentry_operations v9fs_dentry_operations;
+
+struct inode *v9fs_get_inode(struct super_block *sb, int mode);
+ino_t v9fs_qid2ino(struct v9fs_qid *qid);
+void v9fs_mistat2inode(struct v9fs_stat *, struct inode *,
+ struct super_block *);
+int v9fs_dir_release(struct inode *inode, struct file *filp);
+int v9fs_file_open(struct inode *inode, struct file *file);
+void v9fs_inode2mistat(struct inode *inode, struct v9fs_stat *mistat);
+void v9fs_dentry_release(struct dentry *);
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
new file mode 100644
index 000000000000..306c96741f81
--- /dev/null
+++ b/fs/9p/vfs_dentry.c
@@ -0,0 +1,126 @@
+/*
+ * linux/fs/9p/vfs_dentry.c
+ *
+ * This file contians vfs dentry ops for the 9P2000 protocol.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/namei.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * v9fs_dentry_validate - VFS dcache hook to validate cache
+ * @dentry: dentry that is being validated
+ * @nd: path data
+ *
+ * dcache really shouldn't be used for 9P2000 as at all due to
+ * potential attached semantics to directory traversal (walk).
+ *
+ * FUTURE: look into how to use dcache to allow multi-stage
+ * walks in Plan 9 & potential for better dcache operation which
+ * would remain valid for Plan 9 semantics. Older versions
+ * had validation via stat for those interested. However, since
+ * stat has the same approximate overhead as walk there really
+ * is no difference. The only improvement would be from a
+ * time-decay cache like NFS has and that undermines the
+ * synchronous nature of 9P2000.
+ *
+ */
+
+static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
+{
+ struct dentry *dc = current->fs->pwd;
+
+ dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
+ if (v9fs_fid_lookup(dentry, FID_OP)) {
+ dprintk(DEBUG_VFS, "VALID\n");
+ return 1;
+ }
+
+ while (dc != NULL) {
+ if (dc == dentry) {
+ dprintk(DEBUG_VFS, "VALID\n");
+ return 1;
+ }
+ if (dc == dc->d_parent)
+ break;
+
+ dc = dc->d_parent;
+ }
+
+ dprintk(DEBUG_VFS, "INVALID\n");
+ return 0;
+}
+
+/**
+ * v9fs_dentry_release - called when dentry is going to be freed
+ * @dentry: dentry that is being release
+ *
+ */
+
+void v9fs_dentry_release(struct dentry *dentry)
+{
+ dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+ if (dentry->d_fsdata != NULL) {
+ struct list_head *fid_list = dentry->d_fsdata;
+ struct v9fs_fid *temp = NULL;
+ struct v9fs_fid *current_fid = NULL;
+ struct v9fs_fcall *fcall = NULL;
+
+ list_for_each_entry_safe(current_fid, temp, fid_list, list) {
+ if (v9fs_t_clunk
+ (current_fid->v9ses, current_fid->fid, &fcall))
+ dprintk(DEBUG_ERROR, "clunk failed: %s\n",
+ FCALL_ERROR(fcall));
+
+ v9fs_put_idpool(current_fid->fid,
+ &current_fid->v9ses->fidpool);
+
+ kfree(fcall);
+ v9fs_fid_destroy(current_fid);
+ }
+
+ kfree(dentry->d_fsdata); /* free the list_head */
+ }
+}
+
+struct dentry_operations v9fs_dentry_operations = {
+ .d_revalidate = v9fs_dentry_validate,
+ .d_release = v9fs_dentry_release,
+};
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
new file mode 100644
index 000000000000..c478a7384186
--- /dev/null
+++ b/fs/9p/vfs_dir.c
@@ -0,0 +1,226 @@
+/*
+ * linux/fs/9p/vfs_dir.c
+ *
+ * This file contains vfs directory ops for the 9P2000 protocol.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * dt_type - return file type
+ * @mistat: mistat structure
+ *
+ */
+
+static inline int dt_type(struct v9fs_stat *mistat)
+{
+ unsigned long perm = mistat->mode;
+ int rettype = DT_REG;
+
+ if (perm & V9FS_DMDIR)
+ rettype = DT_DIR;
+ if (perm & V9FS_DMSYMLINK)
+ rettype = DT_LNK;
+
+ return rettype;
+}
+
+/**
+ * v9fs_dir_readdir - read a directory
+ * @filep: opened file structure
+ * @dirent: directory structure ???
+ * @filldir: function to populate directory structure ???
+ *
+ */
+
+static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct v9fs_fcall *fcall = NULL;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_fid *file = filp->private_data;
+ unsigned int i, n;
+ int fid = -1;
+ int ret = 0;
+ struct v9fs_stat *mi = NULL;
+ int over = 0;
+
+ dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
+
+ fid = file->fid;
+
+ mi = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ if (!mi)
+ return -ENOMEM;
+
+ if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) {
+ kfree(file->rdir_fcall);
+ file->rdir_fcall = NULL;
+ }
+
+ if (file->rdir_fcall) {
+ n = file->rdir_fcall->params.rread.count;
+ i = file->rdir_fpos;
+ while (i < n) {
+ int s = v9fs_deserialize_stat(v9ses,
+ file->rdir_fcall->params.rread.data + i,
+ n - i, mi, v9ses->maxdata);
+
+ if (s == 0) {
+ dprintk(DEBUG_ERROR,
+ "error while deserializing mistat\n");
+ ret = -EIO;
+ goto FreeStructs;
+ }
+
+ over = filldir(dirent, mi->name, strlen(mi->name),
+ filp->f_pos, v9fs_qid2ino(&mi->qid),
+ dt_type(mi));
+
+ if (over) {
+ file->rdir_fpos = i;
+ file->rdir_pos = filp->f_pos;
+ break;
+ }
+
+ i += s;
+ filp->f_pos += s;
+ }
+
+ if (!over) {
+ kfree(file->rdir_fcall);
+ file->rdir_fcall = NULL;
+ }
+ }
+
+ while (!over) {
+ ret = v9fs_t_read(v9ses, fid, filp->f_pos,
+ v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
+ if (ret < 0) {
+ dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
+ ret, fcall);
+ goto FreeStructs;
+ } else if (ret == 0)
+ break;
+
+ n = ret;
+ i = 0;
+ while (i < n) {
+ int s = v9fs_deserialize_stat(v9ses,
+ fcall->params.rread.data + i, n - i, mi,
+ v9ses->maxdata);
+
+ if (s == 0) {
+ dprintk(DEBUG_ERROR,
+ "error while deserializing mistat\n");
+ return -EIO;
+ }
+
+ over = filldir(dirent, mi->name, strlen(mi->name),
+ filp->f_pos, v9fs_qid2ino(&mi->qid),
+ dt_type(mi));
+
+ if (over) {
+ file->rdir_fcall = fcall;
+ file->rdir_fpos = i;
+ file->rdir_pos = filp->f_pos;
+ fcall = NULL;
+ break;
+ }
+
+ i += s;
+ filp->f_pos += s;
+ }
+
+ kfree(fcall);
+ }
+
+ FreeStructs:
+ kfree(fcall);
+ kfree(mi);
+ return ret;
+}
+
+/**
+ * v9fs_dir_release - close a directory
+ * @inode: inode of the directory
+ * @filp: file pointer to a directory
+ *
+ */
+
+int v9fs_dir_release(struct inode *inode, struct file *filp)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_fid *fid = filp->private_data;
+ int fidnum = -1;
+
+ dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp,
+ fid->fid);
+ fidnum = fid->fid;
+
+ filemap_fdatawrite(inode->i_mapping);
+ filemap_fdatawait(inode->i_mapping);
+
+ if (fidnum >= 0) {
+ fid->fidopen--;
+ dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
+ fid->fid);
+
+ if (fid->fidopen == 0) {
+ if (v9fs_t_clunk(v9ses, fidnum, NULL))
+ dprintk(DEBUG_ERROR, "clunk failed\n");
+
+ v9fs_put_idpool(fid->fid, &v9ses->fidpool);
+ }
+
+ kfree(fid->rdir_fcall);
+
+ filp->private_data = NULL;
+ v9fs_fid_destroy(fid);
+ }
+
+ d_drop(filp->f_dentry);
+ return 0;
+}
+
+struct file_operations v9fs_dir_operations = {
+ .read = generic_read_dir,
+ .readdir = v9fs_dir_readdir,
+ .open = v9fs_file_open,
+ .release = v9fs_dir_release,
+};
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
new file mode 100644
index 000000000000..1f8ae7d580ab
--- /dev/null
+++ b/fs/9p/vfs_file.c
@@ -0,0 +1,401 @@
+/*
+ * linux/fs/9p/vfs_file.c
+ *
+ * This file contians vfs file ops for 9P2000.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "fid.h"
+
+/**
+ * v9fs_file_open - open a file (or directory)
+ * @inode: inode to be opened
+ * @file: file being opened
+ *
+ */
+
+int v9fs_file_open(struct inode *inode, struct file *file)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK);
+ struct v9fs_fid *v9newfid = NULL;
+ struct v9fs_fcall *fcall = NULL;
+ int open_mode = 0;
+ unsigned int iounit = 0;
+ int newfid = -1;
+ long result = -1;
+
+ dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file,
+ v9fid);
+
+ if (!v9fid) {
+ struct dentry *dentry = file->f_dentry;
+ dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
+
+ /* XXX - some duplication from lookup, generalize later */
+ /* basically vfs_lookup is too heavy weight */
+ v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP);
+ if (!v9fid)
+ return -EBADF;
+
+ v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
+ if (!v9fid)
+ return -EBADF;
+
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ return -ENOSPC;
+ }
+
+ result =
+ v9fs_t_walk(v9ses, v9fid->fid, newfid,
+ (char *)file->f_dentry->d_name.name, NULL);
+ if (result < 0) {
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ dprintk(DEBUG_ERROR, "rewalk didn't work\n");
+ return -EBADF;
+ }
+
+ v9fid = v9fs_fid_create(dentry);
+ if (v9fid == NULL) {
+ dprintk(DEBUG_ERROR, "couldn't insert\n");
+ return -ENOMEM;
+ }
+ v9fid->fid = newfid;
+ }
+
+ if (v9fid->fidcreate) {
+ /* create case */
+ newfid = v9fid->fid;
+ iounit = v9fid->iounit;
+ v9fid->fidcreate = 0;
+ } else {
+ if (!S_ISDIR(inode->i_mode))
+ newfid = v9fid->fid;
+ else {
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "allocation failed\n");
+ return -ENOSPC;
+ }
+ /* This would be a somewhat critical clone */
+ result =
+ v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL,
+ &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR, "clone error: %s\n",
+ FCALL_ERROR(fcall));
+ kfree(fcall);
+ return result;
+ }
+
+ v9newfid = v9fs_fid_create(file->f_dentry);
+ v9newfid->fid = newfid;
+ v9newfid->qid = v9fid->qid;
+ v9newfid->iounit = v9fid->iounit;
+ v9newfid->fidopen = 0;
+ v9newfid->fidclunked = 0;
+ v9newfid->v9ses = v9ses;
+ v9fid = v9newfid;
+ kfree(fcall);
+ }
+
+ /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
+ /* translate open mode appropriately */
+ open_mode = file->f_flags & 0x3;
+
+ if (file->f_flags & O_EXCL)
+ open_mode |= V9FS_OEXCL;
+
+ if (v9ses->extended) {
+ if (file->f_flags & O_TRUNC)
+ open_mode |= V9FS_OTRUNC;
+
+ if (file->f_flags & O_APPEND)
+ open_mode |= V9FS_OAPPEND;
+ }
+
+ result = v9fs_t_open(v9ses, newfid, open_mode, &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR,
+ "open failed, open_mode 0x%x: %s\n", open_mode,
+ FCALL_ERROR(fcall));
+ kfree(fcall);
+ return result;
+ }
+
+ iounit = fcall->params.ropen.iounit;
+ kfree(fcall);
+ }
+
+
+ file->private_data = v9fid;
+
+ v9fid->rdir_pos = 0;
+ v9fid->rdir_fcall = NULL;
+ v9fid->fidopen = 1;
+ v9fid->filp = file;
+ v9fid->iounit = iounit;
+
+ return 0;
+}
+
+/**
+ * v9fs_file_lock - lock a file (or directory)
+ * @inode: inode to be opened
+ * @file: file being opened
+ *
+ * XXX - this looks like a local only lock, we should extend into 9P
+ * by using open exclusive
+ */
+
+static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
+{
+ int res = 0;
+ struct inode *inode = filp->f_dentry->d_inode;
+
+ dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
+
+ /* No mandatory locks */
+ if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ return -ENOLCK;
+
+ if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
+ filemap_fdatawrite(inode->i_mapping);
+ filemap_fdatawait(inode->i_mapping);
+ invalidate_inode_pages(&inode->i_data);
+ }
+
+ return res;
+}
+
+/**
+ * v9fs_read - read from a file (internal)
+ * @filep: file pointer to read
+ * @data: data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+
+static ssize_t
+v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_fid *v9f = filp->private_data;
+ struct v9fs_fcall *fcall = NULL;
+ int fid = v9f->fid;
+ int rsize = 0;
+ int result = 0;
+ int total = 0;
+
+ dprintk(DEBUG_VFS, "\n");
+
+ rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+ if (v9f->iounit != 0 && rsize > v9f->iounit)
+ rsize = v9f->iounit;
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall);
+
+ if (result < 0) {
+ printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n",
+ result);
+
+ kfree(fcall);
+ return total;
+ } else
+ *offset += result;
+
+ /* XXX - extra copy */
+ memcpy(buffer, fcall->params.rread.data, result);
+ count -= result;
+ buffer += result;
+ total += result;
+
+ kfree(fcall);
+
+ if (result < rsize)
+ break;
+ } while (count);
+
+ return total;
+}
+
+/**
+ * v9fs_file_read - read from a file
+ * @filep: file pointer to read
+ * @data: data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+
+static ssize_t
+v9fs_file_read(struct file *filp, char __user * data, size_t count,
+ loff_t * offset)
+{
+ int retval = -1;
+ int ret = 0;
+ char *buffer;
+
+ buffer = kmalloc(count, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = v9fs_read(filp, buffer, count, offset);
+ if (retval > 0) {
+ if ((ret = copy_to_user(data, buffer, retval)) != 0) {
+ dprintk(DEBUG_ERROR, "Problem copying to user %d\n",
+ ret);
+ retval = ret;
+ }
+ }
+
+ kfree(buffer);
+
+ return retval;
+}
+
+/**
+ * v9fs_write - write to a file
+ * @filep: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+
+static ssize_t
+v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_fid *v9fid = filp->private_data;
+ struct v9fs_fcall *fcall;
+ int fid = v9fid->fid;
+ int result = -EIO;
+ int rsize = 0;
+ int total = 0;
+
+ dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count,
+ (int)*offset);
+ rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+ if (v9fid->iounit != 0 && rsize > v9fid->iounit)
+ rsize = v9fid->iounit;
+
+ dump_data(buffer, count);
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ result =
+ v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall);
+ if (result < 0) {
+ eprintk(KERN_ERR, "error while writing: %s(%d)\n",
+ FCALL_ERROR(fcall), result);
+ kfree(fcall);
+ return result;
+ } else
+ *offset += result;
+
+ kfree(fcall);
+
+ if (result != rsize) {
+ eprintk(KERN_ERR,
+ "short write: v9fs_t_write returned %d\n",
+ result);
+ break;
+ }
+
+ count -= result;
+ buffer += result;
+ total += result;
+ } while (count);
+
+ return total;
+}
+
+/**
+ * v9fs_file_write - write to a file
+ * @filep: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+
+static ssize_t
+v9fs_file_write(struct file *filp, const char __user * data,
+ size_t count, loff_t * offset)
+{
+ int ret = -1;
+ char *buffer;
+
+ buffer = kmalloc(count, GFP_KERNEL);
+ if (buffer == NULL)
+ return -ENOMEM;
+
+ ret = copy_from_user(buffer, data, count);
+ if (ret) {
+ dprintk(DEBUG_ERROR, "Problem copying from user\n");
+ ret = -EFAULT;
+ } else {
+ ret = v9fs_write(filp, buffer, count, offset);
+ }
+
+ kfree(buffer);
+
+ return ret;
+}
+
+struct file_operations v9fs_file_operations = {
+ .llseek = generic_file_llseek,
+ .read = v9fs_file_read,
+ .write = v9fs_file_write,
+ .open = v9fs_file_open,
+ .release = v9fs_dir_release,
+ .lock = v9fs_file_lock,
+};
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
new file mode 100644
index 000000000000..0c13fc600049
--- /dev/null
+++ b/fs/9p/vfs_inode.c
@@ -0,0 +1,1338 @@
+/*
+ * linux/fs/9p/vfs_inode.c
+ *
+ * This file contains vfs inode ops for the 9P2000 protocol.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/namei.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+static struct inode_operations v9fs_dir_inode_operations;
+static struct inode_operations v9fs_dir_inode_operations_ext;
+static struct inode_operations v9fs_file_inode_operations;
+static struct inode_operations v9fs_symlink_inode_operations;
+
+/**
+ * unixmode2p9mode - convert unix mode bits to plan 9
+ * @v9ses: v9fs session information
+ * @mode: mode to convert
+ *
+ */
+
+static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
+{
+ int res;
+ res = mode & 0777;
+ if (S_ISDIR(mode))
+ res |= V9FS_DMDIR;
+ if (v9ses->extended) {
+ if (S_ISLNK(mode))
+ res |= V9FS_DMSYMLINK;
+ if (v9ses->nodev == 0) {
+ if (S_ISSOCK(mode))
+ res |= V9FS_DMSOCKET;
+ if (S_ISFIFO(mode))
+ res |= V9FS_DMNAMEDPIPE;
+ if (S_ISBLK(mode))
+ res |= V9FS_DMDEVICE;
+ if (S_ISCHR(mode))
+ res |= V9FS_DMDEVICE;
+ }
+
+ if ((mode & S_ISUID) == S_ISUID)
+ res |= V9FS_DMSETUID;
+ if ((mode & S_ISGID) == S_ISGID)
+ res |= V9FS_DMSETGID;
+ if ((mode & V9FS_DMLINK))
+ res |= V9FS_DMLINK;
+ }
+
+ return res;
+}
+
+/**
+ * p9mode2unixmode- convert plan9 mode bits to unix mode bits
+ * @v9ses: v9fs session information
+ * @mode: mode to convert
+ *
+ */
+
+static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
+{
+ int res;
+
+ res = mode & 0777;
+
+ if ((mode & V9FS_DMDIR) == V9FS_DMDIR)
+ res |= S_IFDIR;
+ else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended))
+ res |= S_IFLNK;
+ else if ((mode & V9FS_DMSOCKET) && (v9ses->extended)
+ && (v9ses->nodev == 0))
+ res |= S_IFSOCK;
+ else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended)
+ && (v9ses->nodev == 0))
+ res |= S_IFIFO;
+ else if ((mode & V9FS_DMDEVICE) && (v9ses->extended)
+ && (v9ses->nodev == 0))
+ res |= S_IFBLK;
+ else
+ res |= S_IFREG;
+
+ if (v9ses->extended) {
+ if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID)
+ res |= S_ISUID;
+
+ if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID)
+ res |= S_ISGID;
+ }
+
+ return res;
+}
+
+/**
+ * v9fs_blank_mistat - helper function to setup a 9P stat structure
+ * @v9ses: 9P session info (for determining extended mode)
+ * @mistat: structure to initialize
+ *
+ */
+
+static void
+v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat)
+{
+ mistat->type = ~0;
+ mistat->dev = ~0;
+ mistat->qid.type = ~0;
+ mistat->qid.version = ~0;
+ *((long long *)&mistat->qid.path) = ~0;
+ mistat->mode = ~0;
+ mistat->atime = ~0;
+ mistat->mtime = ~0;
+ mistat->length = ~0;
+ mistat->name = mistat->data;
+ mistat->uid = mistat->data;
+ mistat->gid = mistat->data;
+ mistat->muid = mistat->data;
+ if (v9ses->extended) {
+ mistat->n_uid = ~0;
+ mistat->n_gid = ~0;
+ mistat->n_muid = ~0;
+ mistat->extension = mistat->data;
+ }
+ *mistat->data = 0;
+}
+
+/**
+ * v9fs_mistat2unix - convert mistat to unix stat
+ * @mistat: Plan 9 metadata (mistat) structure
+ * @buf: unix metadata (stat) structure to populate
+ * @sb: superblock
+ *
+ */
+
+static void
+v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf,
+ struct super_block *sb)
+{
+ struct v9fs_session_info *v9ses = sb ? sb->s_fs_info : NULL;
+
+ buf->st_nlink = 1;
+
+ buf->st_atime = mistat->atime;
+ buf->st_mtime = mistat->mtime;
+ buf->st_ctime = mistat->mtime;
+
+ buf->st_uid = (unsigned short)-1;
+ buf->st_gid = (unsigned short)-1;
+
+ if (v9ses && v9ses->extended) {
+ /* TODO: string to uid mapping via user-space daemon */
+ if (mistat->n_uid != -1)
+ sscanf(mistat->uid, "%x", (unsigned int *)&buf->st_uid);
+
+ if (mistat->n_gid != -1)
+ sscanf(mistat->gid, "%x", (unsigned int *)&buf->st_gid);
+ }
+
+ if (buf->st_uid == (unsigned short)-1)
+ buf->st_uid = v9ses->uid;
+ if (buf->st_gid == (unsigned short)-1)
+ buf->st_gid = v9ses->gid;
+
+ buf->st_mode = p9mode2unixmode(v9ses, mistat->mode);
+ if ((S_ISBLK(buf->st_mode)) || (S_ISCHR(buf->st_mode))) {
+ char type = 0;
+ int major = -1;
+ int minor = -1;
+ sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
+ switch (type) {
+ case 'c':
+ buf->st_mode &= ~S_IFBLK;
+ buf->st_mode |= S_IFCHR;
+ break;
+ case 'b':
+ break;
+ default:
+ dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
+ type, mistat->extension);
+ };
+ buf->st_rdev = MKDEV(major, minor);
+ } else
+ buf->st_rdev = 0;
+
+ buf->st_size = mistat->length;
+
+ buf->st_blksize = sb->s_blocksize;
+ buf->st_blocks =
+ (buf->st_size + buf->st_blksize - 1) >> sb->s_blocksize_bits;
+}
+
+/**
+ * v9fs_get_inode - helper function to setup an inode
+ * @sb: superblock
+ * @mode: mode to setup inode with
+ *
+ */
+
+struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+{
+ struct inode *inode = NULL;
+ struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+ dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+
+ inode = new_inode(sb);
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = sb->s_blocksize;
+ inode->i_blocks = 0;
+ inode->i_rdev = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ switch (mode & S_IFMT) {
+ case S_IFIFO:
+ case S_IFBLK:
+ case S_IFCHR:
+ case S_IFSOCK:
+ if(!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "special files without extended mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+ init_special_inode(inode, inode->i_mode,
+ inode->i_rdev);
+ break;
+ case S_IFREG:
+ inode->i_op = &v9fs_file_inode_operations;
+ inode->i_fop = &v9fs_file_operations;
+ break;
+ case S_IFLNK:
+ if(!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n");
+ return ERR_PTR(-EINVAL);
+ }
+ inode->i_op = &v9fs_symlink_inode_operations;
+ break;
+ case S_IFDIR:
+ inode->i_nlink++;
+ if(v9ses->extended)
+ inode->i_op = &v9fs_dir_inode_operations_ext;
+ else
+ inode->i_op = &v9fs_dir_inode_operations;
+ inode->i_fop = &v9fs_dir_operations;
+ break;
+ default:
+ dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+ mode, mode & S_IFMT);
+ return ERR_PTR(-EINVAL);
+ }
+ } else {
+ eprintk(KERN_WARNING, "Problem allocating inode\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ return inode;
+}
+
+/**
+ * v9fs_create - helper function to create files and directories
+ * @dir: directory inode file is being created in
+ * @file_dentry: dentry file is being created in
+ * @perm: permissions file is being created with
+ * @open_mode: resulting open mode for file
+ *
+ */
+
+static int
+v9fs_create(struct inode *dir,
+ struct dentry *file_dentry,
+ unsigned int perm, unsigned int open_mode)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+ struct super_block *sb = dir->i_sb;
+ struct v9fs_fid *dirfid =
+ v9fs_fid_lookup(file_dentry->d_parent, FID_WALK);
+ struct v9fs_fid *fid = NULL;
+ struct inode *file_inode = NULL;
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_qid qid;
+ struct stat newstat;
+ int dirfidnum = -1;
+ long newfid = -1;
+ int result = 0;
+ unsigned int iounit = 0;
+
+ perm = unixmode2p9mode(v9ses, perm);
+
+ dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir,
+ file_dentry, perm, open_mode);
+
+ if (!dirfid)
+ return -EBADF;
+
+ dirfidnum = dirfid->fid;
+ if (dirfidnum < 0) {
+ dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n",
+ dir->i_ino);
+ return -EBADF;
+ }
+
+ if (file_dentry->d_inode) {
+ dprintk(DEBUG_ERROR,
+ "Odd. There is an inode for dir %lu, name :%s:\n",
+ dir->i_ino, file_dentry->d_name.name);
+ return -EEXIST;
+ }
+
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "no free fids available\n");
+ return -ENOSPC;
+ }
+
+ result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ newfid = 0;
+ goto CleanUpFid;
+ }
+
+ kfree(fcall);
+
+ result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name,
+ perm, open_mode, &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR, "create fails: %s(%d)\n",
+ FCALL_ERROR(fcall), result);
+
+ goto CleanUpFid;
+ }
+
+ iounit = fcall->params.rcreate.iounit;
+ qid = fcall->params.rcreate.qid;
+ kfree(fcall);
+
+ fid = v9fs_fid_create(file_dentry);
+ if (!fid) {
+ result = -ENOMEM;
+ goto CleanUpFid;
+ }
+
+ fid->fid = newfid;
+ fid->fidopen = 0;
+ fid->fidcreate = 1;
+ fid->qid = qid;
+ fid->iounit = iounit;
+ fid->rdir_pos = 0;
+ fid->rdir_fcall = NULL;
+ fid->v9ses = v9ses;
+
+ if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) ||
+ (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
+ (perm & V9FS_DMDEVICE))
+ return 0;
+
+ result = v9fs_t_stat(v9ses, newfid, &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall),
+ result);
+ goto CleanUpFid;
+ }
+
+ v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
+
+ file_inode = v9fs_get_inode(sb, newstat.st_mode);
+ if ((!file_inode) || IS_ERR(file_inode)) {
+ dprintk(DEBUG_ERROR, "create inode failed\n");
+ result = -EBADF;
+ goto CleanUpFid;
+ }
+
+ v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb);
+ kfree(fcall);
+ d_instantiate(file_dentry, file_inode);
+
+ if (perm & V9FS_DMDIR) {
+ if (v9fs_t_clunk(v9ses, newfid, &fcall))
+ dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n",
+ FCALL_ERROR(fcall));
+
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ kfree(fcall);
+ fid->fidopen = 0;
+ fid->fidcreate = 0;
+ d_drop(file_dentry);
+ }
+
+ return 0;
+
+ CleanUpFid:
+ kfree(fcall);
+
+ if (newfid) {
+ if (v9fs_t_clunk(v9ses, newfid, &fcall))
+ dprintk(DEBUG_ERROR, "clunk failed: %s\n",
+ FCALL_ERROR(fcall));
+
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ kfree(fcall);
+ }
+ return result;
+}
+
+/**
+ * v9fs_remove - helper function to remove files and directories
+ * @dir: directory inode that is being deleted
+ * @file: dentry that is being deleted
+ * @rmdir: removing a directory
+ *
+ */
+
+static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
+{
+ struct v9fs_fcall *fcall = NULL;
+ struct super_block *sb = NULL;
+ struct v9fs_session_info *v9ses = NULL;
+ struct v9fs_fid *v9fid = NULL;
+ struct inode *file_inode = NULL;
+ int fid = -1;
+ int result = 0;
+
+ dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
+ rmdir);
+
+ file_inode = file->d_inode;
+ sb = file_inode->i_sb;
+ v9ses = v9fs_inode2v9ses(file_inode);
+ v9fid = v9fs_fid_lookup(file, FID_OP);
+
+ if (!v9fid) {
+ dprintk(DEBUG_ERROR,
+ "no v9fs_fid\n");
+ return -EBADF;
+ }
+
+ fid = v9fid->fid;
+ if (fid < 0) {
+ dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n",
+ file_inode->i_ino);
+ return -EBADF;
+ }
+
+ result = v9fs_t_remove(v9ses, fid, &fcall);
+ if (result < 0)
+ dprintk(DEBUG_ERROR, "remove of file fails: %s(%d)\n",
+ FCALL_ERROR(fcall), result);
+ else {
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ v9fs_fid_destroy(v9fid);
+ }
+
+ kfree(fcall);
+ return result;
+}
+
+/**
+ * v9fs_vfs_create - VFS hook to create files
+ * @inode: directory inode that is being deleted
+ * @dentry: dentry that is being deleted
+ * @perm: create permissions
+ * @nd: path information
+ *
+ */
+
+static int
+v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm,
+ struct nameidata *nd)
+{
+ return v9fs_create(inode, dentry, perm, O_RDWR);
+}
+
+/**
+ * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
+ * @inode: inode that is being unlinked
+ * @dentry: dentry that is being unlinked
+ * @mode: mode for new directory
+ *
+ */
+
+static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode)
+{
+ return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY);
+}
+
+/**
+ * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
+ * @dir: inode that is being walked from
+ * @dentry: dentry that is being walked to?
+ * @nameidata: path data
+ *
+ */
+
+static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nameidata)
+{
+ struct super_block *sb;
+ struct v9fs_session_info *v9ses;
+ struct v9fs_fid *dirfid;
+ struct v9fs_fid *fid;
+ struct inode *inode;
+ struct v9fs_fcall *fcall = NULL;
+ struct stat newstat;
+ int dirfidnum = -1;
+ int newfid = -1;
+ int result = 0;
+
+ dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
+ dir, dentry->d_iname, dentry, nameidata);
+
+ sb = dir->i_sb;
+ v9ses = v9fs_inode2v9ses(dir);
+ dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
+
+ if (!dirfid) {
+ dprintk(DEBUG_ERROR, "no dirfid\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ dirfidnum = dirfid->fid;
+
+ if (dirfidnum < 0) {
+ dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n",
+ dir, dir->i_ino);
+ return ERR_PTR(-EBADF);
+ }
+
+ newfid = v9fs_get_idpool(&v9ses->fidpool);
+ if (newfid < 0) {
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ return ERR_PTR(-ENOSPC);
+ }
+
+ result =
+ v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name,
+ NULL);
+ if (result < 0) {
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ if (result == -ENOENT) {
+ d_add(dentry, NULL);
+ dprintk(DEBUG_ERROR,
+ "Return negative dentry %p count %d\n",
+ dentry, atomic_read(&dentry->d_count));
+ return NULL;
+ }
+ dprintk(DEBUG_ERROR, "walk error:%d\n", result);
+ goto FreeFcall;
+ }
+
+ result = v9fs_t_stat(v9ses, newfid, &fcall);
+ if (result < 0) {
+ dprintk(DEBUG_ERROR, "stat error\n");
+ goto FreeFcall;
+ }
+
+ v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
+ inode = v9fs_get_inode(sb, newstat.st_mode);
+
+ if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
+ eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
+ PTR_ERR(inode));
+
+ result = -ENOSPC;
+ goto FreeFcall;
+ }
+
+ inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid);
+
+ fid = v9fs_fid_create(dentry);
+ if (fid == NULL) {
+ dprintk(DEBUG_ERROR, "couldn't insert\n");
+ result = -ENOMEM;
+ goto FreeFcall;
+ }
+
+ fid->fid = newfid;
+ fid->fidopen = 0;
+ fid->v9ses = v9ses;
+ fid->qid = fcall->params.rstat.stat->qid;
+
+ dentry->d_op = &v9fs_dentry_operations;
+ v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb);
+
+ d_add(dentry, inode);
+ kfree(fcall);
+
+ return NULL;
+
+ FreeFcall:
+ kfree(fcall);
+ return ERR_PTR(result);
+}
+
+/**
+ * v9fs_vfs_unlink - VFS unlink hook to delete an inode
+ * @i: inode that is being unlinked
+ * @d: dentry that is being unlinked
+ *
+ */
+
+static int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
+{
+ return v9fs_remove(i, d, 0);
+}
+
+/**
+ * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
+ * @i: inode that is being unlinked
+ * @d: dentry that is being unlinked
+ *
+ */
+
+static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
+{
+ return v9fs_remove(i, d, 1);
+}
+
+/**
+ * v9fs_vfs_rename - VFS hook to rename an inode
+ * @old_dir: old dir inode
+ * @old_dentry: old dentry
+ * @new_dir: new dir inode
+ * @new_dentry: new dentry
+ *
+ */
+
+static int
+v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ struct inode *old_inode = old_dentry->d_inode;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
+ struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK);
+ struct v9fs_fid *olddirfid =
+ v9fs_fid_lookup(old_dentry->d_parent, FID_WALK);
+ struct v9fs_fid *newdirfid =
+ v9fs_fid_lookup(new_dentry->d_parent, FID_WALK);
+ struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ struct v9fs_fcall *fcall = NULL;
+ int fid = -1;
+ int olddirfidnum = -1;
+ int newdirfidnum = -1;
+ int retval = 0;
+
+ dprintk(DEBUG_VFS, "\n");
+
+ if (!mistat)
+ return -ENOMEM;
+
+ if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
+ dprintk(DEBUG_ERROR, "problem with arguments\n");
+ return -EBADF;
+ }
+
+ /* 9P can only handle file rename in the same directory */
+ if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
+ dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
+ retval = -EPERM;
+ goto FreeFcallnBail;
+ }
+
+ fid = oldfid->fid;
+ olddirfidnum = olddirfid->fid;
+ newdirfidnum = newdirfid->fid;
+
+ if (fid < 0) {
+ dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
+ old_inode->i_ino);
+ retval = -EBADF;
+ goto FreeFcallnBail;
+ }
+
+ v9fs_blank_mistat(v9ses, mistat);
+
+ strcpy(mistat->data + 1, v9ses->name);
+ mistat->name = mistat->data + 1 + strlen(v9ses->name);
+
+ if (new_dentry->d_name.len >
+ (v9ses->maxdata - strlen(v9ses->name) - sizeof(struct v9fs_stat))) {
+ dprintk(DEBUG_ERROR, "new name too long\n");
+ goto FreeFcallnBail;
+ }
+
+ strcpy(mistat->name, new_dentry->d_name.name);
+ retval = v9fs_t_wstat(v9ses, fid, mistat, &fcall);
+
+ FreeFcallnBail:
+ kfree(mistat);
+
+ if (retval < 0)
+ dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+ FCALL_ERROR(fcall));
+
+ kfree(fcall);
+ return retval;
+}
+
+/**
+ * v9fs_vfs_getattr - retreive file metadata
+ * @mnt - mount information
+ * @dentry - file to get attributes on
+ * @stat - metadata structure to populate
+ *
+ */
+
+static int
+v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+ int err = -EPERM;
+
+ dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
+ if (!fid) {
+ dprintk(DEBUG_ERROR,
+ "couldn't find fid associated with dentry\n");
+ return -EBADF;
+ }
+
+ err = v9fs_t_stat(v9ses, fid->fid, &fcall);
+
+ if (err < 0)
+ dprintk(DEBUG_ERROR, "stat error\n");
+ else {
+ v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode,
+ dentry->d_inode->i_sb);
+ generic_fillattr(dentry->d_inode, stat);
+ }
+
+ kfree(fcall);
+ return err;
+}
+
+/**
+ * v9fs_vfs_setattr - set file metadata
+ * @dentry: file whose metadata to set
+ * @iattr: metadata assignment structure
+ *
+ */
+
+static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ int res = -EPERM;
+
+ dprintk(DEBUG_VFS, "\n");
+
+ if (!mistat)
+ return -ENOMEM;
+
+ if (!fid) {
+ dprintk(DEBUG_ERROR,
+ "Couldn't find fid associated with dentry\n");
+ return -EBADF;
+ }
+
+ v9fs_blank_mistat(v9ses, mistat);
+ if (iattr->ia_valid & ATTR_MODE)
+ mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode);
+
+ if (iattr->ia_valid & ATTR_MTIME)
+ mistat->mtime = iattr->ia_mtime.tv_sec;
+
+ if (iattr->ia_valid & ATTR_ATIME)
+ mistat->atime = iattr->ia_atime.tv_sec;
+
+ if (iattr->ia_valid & ATTR_SIZE)
+ mistat->length = iattr->ia_size;
+
+ if (v9ses->extended) {
+ char *ptr = mistat->data+1;
+
+ if (iattr->ia_valid & ATTR_UID) {
+ mistat->uid = ptr;
+ ptr += 1+sprintf(ptr, "%08x", iattr->ia_uid);
+ mistat->n_uid = iattr->ia_uid;
+ }
+
+ if (iattr->ia_valid & ATTR_GID) {
+ mistat->gid = ptr;
+ ptr += 1+sprintf(ptr, "%08x", iattr->ia_gid);
+ mistat->n_gid = iattr->ia_gid;
+ }
+ }
+
+ res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall);
+
+ if (res < 0)
+ dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall));
+
+ kfree(mistat);
+ kfree(fcall);
+
+ if (res >= 0)
+ res = inode_setattr(dentry->d_inode, iattr);
+
+ return res;
+}
+
+/**
+ * v9fs_mistat2inode - populate an inode structure with mistat info
+ * @mistat: Plan 9 metadata (mistat) structure
+ * @inode: inode to populate
+ * @sb: superblock of filesystem
+ *
+ */
+
+void
+v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
+ struct super_block *sb)
+{
+ struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+ inode->i_nlink = 1;
+
+ inode->i_atime.tv_sec = mistat->atime;
+ inode->i_mtime.tv_sec = mistat->mtime;
+ inode->i_ctime.tv_sec = mistat->mtime;
+
+ inode->i_uid = -1;
+ inode->i_gid = -1;
+
+ if (v9ses->extended) {
+ /* TODO: string to uid mapping via user-space daemon */
+ inode->i_uid = mistat->n_uid;
+ inode->i_gid = mistat->n_gid;
+
+ if (mistat->n_uid == -1)
+ sscanf(mistat->uid, "%x", &inode->i_uid);
+
+ if (mistat->n_gid == -1)
+ sscanf(mistat->gid, "%x", &inode->i_gid);
+ }
+
+ if (inode->i_uid == -1)
+ inode->i_uid = v9ses->uid;
+ if (inode->i_gid == -1)
+ inode->i_gid = v9ses->gid;
+
+ inode->i_mode = p9mode2unixmode(v9ses, mistat->mode);
+ if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
+ char type = 0;
+ int major = -1;
+ int minor = -1;
+ sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
+ switch (type) {
+ case 'c':
+ inode->i_mode &= ~S_IFBLK;
+ inode->i_mode |= S_IFCHR;
+ break;
+ case 'b':
+ break;
+ default:
+ dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
+ type, mistat->extension);
+ };
+ inode->i_rdev = MKDEV(major, minor);
+ } else
+ inode->i_rdev = 0;
+
+ inode->i_size = mistat->length;
+
+ inode->i_blksize = sb->s_blocksize;
+ inode->i_blocks =
+ (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
+}
+
+/**
+ * v9fs_qid2ino - convert qid into inode number
+ * @qid: qid to hash
+ *
+ * BUG: potential for inode number collisions?
+ */
+
+ino_t v9fs_qid2ino(struct v9fs_qid *qid)
+{
+ u64 path = qid->path + 2;
+ ino_t i = 0;
+
+ if (sizeof(ino_t) == sizeof(path))
+ memcpy(&i, &path, sizeof(ino_t));
+ else
+ i = (ino_t) (path ^ (path >> 32));
+
+ return i;
+}
+
+/**
+ * v9fs_vfs_symlink - helper function to create symlinks
+ * @dir: directory inode containing symlink
+ * @dentry: dentry for symlink
+ * @symname: symlink data
+ *
+ * See 9P2000.u RFC for more information
+ *
+ */
+
+static int
+v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+ int retval = -EPERM;
+ struct v9fs_fid *newfid;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+
+ dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+ symname);
+
+ if (!mistat)
+ return -ENOMEM;
+
+ if (!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "not extended\n");
+ goto FreeFcall;
+ }
+
+ /* issue a create */
+ retval = v9fs_create(dir, dentry, S_IFLNK, 0);
+ if (retval != 0)
+ goto FreeFcall;
+
+ newfid = v9fs_fid_lookup(dentry, FID_OP);
+
+ /* issue a twstat */
+ v9fs_blank_mistat(v9ses, mistat);
+ strcpy(mistat->data + 1, symname);
+ mistat->extension = mistat->data + 1;
+ retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+ if (retval < 0) {
+ dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeFcall;
+ }
+
+ kfree(fcall);
+
+ if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+ dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeFcall;
+ }
+
+ d_drop(dentry); /* FID - will this also clunk? */
+
+ FreeFcall:
+ kfree(mistat);
+ kfree(fcall);
+
+ return retval;
+}
+
+/**
+ * v9fs_readlink - read a symlink's location (internal version)
+ * @dentry: dentry for symlink
+ * @buffer: buffer to load symlink location into
+ * @buflen: length of buffer
+ *
+ */
+
+static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ int retval = -EPERM;
+
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+
+ if (!fid) {
+ dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n");
+ retval = -EBADF;
+ goto FreeFcall;
+ }
+
+ if (!v9ses->extended) {
+ retval = -EBADF;
+ dprintk(DEBUG_ERROR, "not extended\n");
+ goto FreeFcall;
+ }
+
+ dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
+ retval = v9fs_t_stat(v9ses, fid->fid, &fcall);
+
+ if (retval < 0) {
+ dprintk(DEBUG_ERROR, "stat error\n");
+ goto FreeFcall;
+ }
+
+ if (!fcall)
+ return -EIO;
+
+ if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) {
+ retval = -EINVAL;
+ goto FreeFcall;
+ }
+
+ /* copy extension buffer into buffer */
+ if (strlen(fcall->params.rstat.stat->extension) < buflen)
+ buflen = strlen(fcall->params.rstat.stat->extension);
+
+ memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1);
+
+ retval = buflen;
+
+ FreeFcall:
+ kfree(fcall);
+
+ return retval;
+}
+
+/**
+ * v9fs_vfs_readlink - read a symlink's location
+ * @dentry: dentry for symlink
+ * @buf: buffer to load symlink location into
+ * @buflen: length of buffer
+ *
+ */
+
+static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
+ int buflen)
+{
+ int retval;
+ int ret;
+ char *link = __getname();
+
+ if (strlen(link) < buflen)
+ buflen = strlen(link);
+
+ dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+ retval = v9fs_readlink(dentry, link, buflen);
+
+ if (retval > 0) {
+ if ((ret = copy_to_user(buffer, link, retval)) != 0) {
+ dprintk(DEBUG_ERROR, "problem copying to user: %d\n",
+ ret);
+ retval = ret;
+ }
+ }
+
+ putname(link);
+ return retval;
+}
+
+/**
+ * v9fs_vfs_follow_link - follow a symlink path
+ * @dentry: dentry for symlink
+ * @nd: nameidata
+ *
+ */
+
+static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ int len = 0;
+ char *link = __getname();
+
+ dprintk(DEBUG_VFS, "%s n", dentry->d_name.name);
+
+ if (!link)
+ link = ERR_PTR(-ENOMEM);
+ else {
+ len = v9fs_readlink(dentry, link, strlen(link));
+
+ if (len < 0) {
+ putname(link);
+ link = ERR_PTR(len);
+ } else
+ link[len] = 0;
+ }
+ nd_set_link(nd, link);
+
+ return NULL;
+}
+
+/**
+ * v9fs_vfs_put_link - release a symlink path
+ * @dentry: dentry for symlink
+ * @nd: nameidata
+ *
+ */
+
+static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+{
+ char *s = nd_get_link(nd);
+
+ dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
+ if (!IS_ERR(s))
+ putname(s);
+}
+
+/**
+ * v9fs_vfs_link - create a hardlink
+ * @old_dentry: dentry for file to link to
+ * @dir: inode destination for new link
+ * @dentry: dentry for link
+ *
+ */
+
+/* XXX - lots of code dup'd from symlink and creates,
+ * figure out a better reuse strategy
+ */
+
+static int
+v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+{
+ int retval = -EPERM;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP);
+ struct v9fs_fid *newfid = NULL;
+ char *symname = __getname();
+
+ dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+ old_dentry->d_name.name);
+
+ if (!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "not extended\n");
+ goto FreeMem;
+ }
+
+ /* get fid of old_dentry */
+ sprintf(symname, "hardlink(%d)\n", oldfid->fid);
+
+ /* issue a create */
+ retval = v9fs_create(dir, dentry, V9FS_DMLINK, 0);
+ if (retval != 0)
+ goto FreeMem;
+
+ newfid = v9fs_fid_lookup(dentry, FID_OP);
+ if (!newfid) {
+ dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
+ goto FreeMem;
+ }
+
+ /* issue a twstat */
+ v9fs_blank_mistat(v9ses, mistat);
+ strcpy(mistat->data + 1, symname);
+ mistat->extension = mistat->data + 1;
+ retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+ if (retval < 0) {
+ dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeMem;
+ }
+
+ kfree(fcall);
+
+ if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+ dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeMem;
+ }
+
+ d_drop(dentry); /* FID - will this also clunk? */
+
+ kfree(fcall);
+ fcall = NULL;
+
+ FreeMem:
+ kfree(mistat);
+ kfree(fcall);
+ putname(symname);
+ return retval;
+}
+
+/**
+ * v9fs_vfs_mknod - create a special file
+ * @dir: inode destination for new link
+ * @dentry: dentry for file
+ * @mode: mode for creation
+ * @dev_t: device associated with special file
+ *
+ */
+
+static int
+v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+{
+ int retval = -EPERM;
+ struct v9fs_fid *newfid;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+ struct v9fs_fcall *fcall = NULL;
+ struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ char *symname = __getname();
+
+ dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
+ dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
+
+ if (!mistat)
+ return -ENOMEM;
+
+ if (!new_valid_dev(rdev)) {
+ retval = -EINVAL;
+ goto FreeMem;
+ }
+
+ if (!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "not extended\n");
+ goto FreeMem;
+ }
+
+ /* issue a create */
+ retval = v9fs_create(dir, dentry, mode, 0);
+
+ if (retval != 0)
+ goto FreeMem;
+
+ newfid = v9fs_fid_lookup(dentry, FID_OP);
+ if (!newfid) {
+ dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
+ retval = -EINVAL;
+ goto FreeMem;
+ }
+
+ /* build extension */
+ if (S_ISBLK(mode))
+ sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev));
+ else if (S_ISCHR(mode))
+ sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev));
+ else if (S_ISFIFO(mode))
+ ; /* DO NOTHING */
+ else {
+ retval = -EINVAL;
+ goto FreeMem;
+ }
+
+ if (!S_ISFIFO(mode)) {
+ /* issue a twstat */
+ v9fs_blank_mistat(v9ses, mistat);
+ strcpy(mistat->data + 1, symname);
+ mistat->extension = mistat->data + 1;
+ retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+ if (retval < 0) {
+ dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeMem;
+ }
+ }
+
+ /* need to update dcache so we show up */
+ kfree(fcall);
+
+ if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+ dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+ FCALL_ERROR(fcall));
+ goto FreeMem;
+ }
+
+ d_drop(dentry); /* FID - will this also clunk? */
+
+ FreeMem:
+ kfree(mistat);
+ kfree(fcall);
+ putname(symname);
+
+ return retval;
+}
+
+static struct inode_operations v9fs_dir_inode_operations_ext = {
+ .create = v9fs_vfs_create,
+ .lookup = v9fs_vfs_lookup,
+ .symlink = v9fs_vfs_symlink,
+ .link = v9fs_vfs_link,
+ .unlink = v9fs_vfs_unlink,
+ .mkdir = v9fs_vfs_mkdir,
+ .rmdir = v9fs_vfs_rmdir,
+ .mknod = v9fs_vfs_mknod,
+ .rename = v9fs_vfs_rename,
+ .readlink = v9fs_vfs_readlink,
+ .getattr = v9fs_vfs_getattr,
+ .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_dir_inode_operations = {
+ .create = v9fs_vfs_create,
+ .lookup = v9fs_vfs_lookup,
+ .unlink = v9fs_vfs_unlink,
+ .mkdir = v9fs_vfs_mkdir,
+ .rmdir = v9fs_vfs_rmdir,
+ .mknod = v9fs_vfs_mknod,
+ .rename = v9fs_vfs_rename,
+ .getattr = v9fs_vfs_getattr,
+ .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_file_inode_operations = {
+ .getattr = v9fs_vfs_getattr,
+ .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_symlink_inode_operations = {
+ .readlink = v9fs_vfs_readlink,
+ .follow_link = v9fs_vfs_follow_link,
+ .put_link = v9fs_vfs_put_link,
+ .getattr = v9fs_vfs_getattr,
+ .setattr = v9fs_vfs_setattr,
+};
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
new file mode 100644
index 000000000000..868f350b2c5f
--- /dev/null
+++ b/fs/9p/vfs_super.c
@@ -0,0 +1,280 @@
+/*
+ * linux/fs/9p/vfs_super.c
+ *
+ * This file contians superblock ops for 9P2000. It is intended that
+ * you mount this file system on directories.
+ *
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+static void v9fs_clear_inode(struct inode *);
+static struct super_operations v9fs_super_ops;
+
+/**
+ * v9fs_clear_inode - release an inode
+ * @inode: inode to release
+ *
+ */
+
+static void v9fs_clear_inode(struct inode *inode)
+{
+ filemap_fdatawrite(inode->i_mapping);
+}
+
+/**
+ * v9fs_set_super - set the superblock
+ * @s: super block
+ * @data: file system specific data
+ *
+ */
+
+static int v9fs_set_super(struct super_block *s, void *data)
+{
+ s->s_fs_info = data;
+ return set_anon_super(s, data);
+}
+
+/**
+ * v9fs_fill_super - populate superblock with info
+ * @sb: superblock
+ * @v9ses: session information
+ *
+ */
+
+static void
+v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
+ int flags)
+{
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
+ sb->s_blocksize = 1 << sb->s_blocksize_bits;
+ sb->s_magic = V9FS_MAGIC;
+ sb->s_op = &v9fs_super_ops;
+
+ sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
+ MS_NODIRATIME | MS_NOATIME;
+}
+
+/**
+ * v9fs_get_sb - mount a superblock
+ * @fs_type: file system type
+ * @flags: mount flags
+ * @dev_name: device name that was mounted
+ * @data: mount options
+ *
+ */
+
+static struct super_block *v9fs_get_sb(struct file_system_type
+ *fs_type, int flags,
+ const char *dev_name, void *data)
+{
+ struct super_block *sb = NULL;
+ struct v9fs_fcall *fcall = NULL;
+ struct inode *inode = NULL;
+ struct dentry *root = NULL;
+ struct v9fs_session_info *v9ses = NULL;
+ struct v9fs_fid *root_fid = NULL;
+ int mode = S_IRWXUGO | S_ISVTX;
+ uid_t uid = current->fsuid;
+ gid_t gid = current->fsgid;
+ int stat_result = 0;
+ int newfid = 0;
+ int retval = 0;
+
+ dprintk(DEBUG_VFS, " \n");
+
+ v9ses = kcalloc(1, sizeof(struct v9fs_session_info), GFP_KERNEL);
+ if (!v9ses)
+ return ERR_PTR(-ENOMEM);
+
+ if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
+ dprintk(DEBUG_ERROR, "problem initiating session\n");
+ retval = newfid;
+ goto free_session;
+ }
+
+ sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
+
+ v9fs_fill_super(sb, v9ses, flags);
+
+ inode = v9fs_get_inode(sb, S_IFDIR | mode);
+ if (IS_ERR(inode)) {
+ retval = PTR_ERR(inode);
+ goto put_back_sb;
+ }
+
+ inode->i_uid = uid;
+ inode->i_gid = gid;
+
+ root = d_alloc_root(inode);
+
+ if (!root) {
+ retval = -ENOMEM;
+ goto release_inode;
+ }
+
+ sb->s_root = root;
+
+ /* Setup the Root Inode */
+ root_fid = v9fs_fid_create(root);
+ if (root_fid == NULL) {
+ retval = -ENOMEM;
+ goto release_dentry;
+ }
+
+ root_fid->fidopen = 0;
+ root_fid->v9ses = v9ses;
+
+ stat_result = v9fs_t_stat(v9ses, newfid, &fcall);
+ if (stat_result < 0) {
+ dprintk(DEBUG_ERROR, "stat error\n");
+ v9fs_t_clunk(v9ses, newfid, NULL);
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+ } else {
+ root_fid->fid = newfid;
+ root_fid->qid = fcall->params.rstat.stat->qid;
+ root->d_inode->i_ino =
+ v9fs_qid2ino(&fcall->params.rstat.stat->qid);
+ v9fs_mistat2inode(fcall->params.rstat.stat, root->d_inode, sb);
+ }
+
+ kfree(fcall);
+
+ if (stat_result < 0) {
+ retval = stat_result;
+ goto release_dentry;
+ }
+
+ return sb;
+
+ release_dentry:
+ dput(sb->s_root);
+
+ release_inode:
+ iput(inode);
+
+ put_back_sb:
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ v9fs_session_close(v9ses);
+
+ free_session:
+ kfree(v9ses);
+
+ return ERR_PTR(retval);
+}
+
+/**
+ * v9fs_kill_super - Kill Superblock
+ * @s: superblock
+ *
+ */
+
+static void v9fs_kill_super(struct super_block *s)
+{
+ struct v9fs_session_info *v9ses = s->s_fs_info;
+
+ dprintk(DEBUG_VFS, " %p\n", s);
+
+ v9fs_dentry_release(s->s_root); /* clunk root */
+
+ kill_anon_super(s);
+
+ v9fs_session_close(v9ses);
+ kfree(v9ses);
+ dprintk(DEBUG_VFS, "exiting kill_super\n");
+}
+
+/**
+ * v9fs_show_options - Show mount options in /proc/mounts
+ * @m: seq_file to write to
+ * @mnt: mount descriptor
+ *
+ */
+
+static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
+
+ if (v9ses->debug != 0)
+ seq_printf(m, ",debug=%u", v9ses->debug);
+ if (v9ses->port != V9FS_PORT)
+ seq_printf(m, ",port=%u", v9ses->port);
+ if (v9ses->maxdata != 9000)
+ seq_printf(m, ",msize=%u", v9ses->maxdata);
+ if (v9ses->afid != ~0)
+ seq_printf(m, ",afid=%u", v9ses->afid);
+ if (v9ses->proto == PROTO_UNIX)
+ seq_puts(m, ",proto=unix");
+ if (v9ses->extended == 0)
+ seq_puts(m, ",noextend");
+ if (v9ses->nodev == 1)
+ seq_puts(m, ",nodevmap");
+ seq_printf(m, ",name=%s", v9ses->name);
+ seq_printf(m, ",aname=%s", v9ses->remotename);
+ seq_printf(m, ",uid=%u", v9ses->uid);
+ seq_printf(m, ",gid=%u", v9ses->gid);
+ return 0;
+}
+
+static void
+v9fs_umount_begin(struct super_block *sb)
+{
+ struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+ v9fs_session_cancel(v9ses);
+}
+
+static struct super_operations v9fs_super_ops = {
+ .statfs = simple_statfs,
+ .clear_inode = v9fs_clear_inode,
+ .show_options = v9fs_show_options,
+ .umount_begin = v9fs_umount_begin,
+};
+
+struct file_system_type v9fs_fs_type = {
+ .name = "9P",
+ .get_sb = v9fs_get_sb,
+ .kill_sb = v9fs_kill_super,
+ .owner = THIS_MODULE,
+};
diff --git a/fs/Kconfig b/fs/Kconfig
index e54be7058359..068ccea2f184 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -382,10 +382,8 @@ config QUOTA
usage (also called disk quotas). Currently, it works for the
ext2, ext3, and reiserfs file system. ext3 also supports journalled
quotas for which you don't need to run quotacheck(8) after an unclean
- shutdown. You need additional software in order to use quota support
- (you can download sources from
- <http://www.sf.net/projects/linuxquota/>). For further details, read
- the Quota mini-HOWTO, available from
+ shutdown.
+ For further details, read the Quota mini-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, or the documentation provided
with the quota tools. Probably the quota support is only useful for
multi user systems. If unsure, say N.
@@ -403,8 +401,7 @@ config QFMT_V2
depends on QUOTA
help
This quota format allows using quotas with 32-bit UIDs/GIDs. If you
- need this functionality say Y here. Note that you will need recent
- quota utilities (>= 3.01) for new quota format with this kernel.
+ need this functionality say Y here.
config QUOTACTL
bool
@@ -465,6 +462,19 @@ config AUTOFS4_FS
local network, you probably do not need an automounter, and can say
N here.
+config FUSE_FS
+ tristate "Filesystem in Userspace support"
+ help
+ With FUSE it is possible to implement a fully functional filesystem
+ in a userspace program.
+
+ There's also companion library: libfuse. This library along with
+ utilities is available from the FUSE homepage:
+ <http://fuse.sourceforge.net/>
+
+ If you want to develop a userspace FS, or if you want to use
+ a filesystem based on FUSE, answer Y or M.
+
menu "CD-ROM/DVD Filesystems"
config ISO9660_FS
@@ -783,28 +793,6 @@ config SYSFS
Designers of embedded systems may wish to say N here to conserve space.
-config DEVPTS_FS_XATTR
- bool "/dev/pts Extended Attributes"
- depends on UNIX98_PTYS
- help
- Extended attributes are name:value pairs associated with inodes by
- the kernel or by users (see the attr(5) manual page, or visit
- <http://acl.bestbits.at/> for details).
-
- If unsure, say N.
-
-config DEVPTS_FS_SECURITY
- bool "/dev/pts Security Labels"
- depends on DEVPTS_FS_XATTR
- help
- Security labels support alternative access control models
- implemented by security modules like SELinux. This option
- enables an extended attribute handler for file security
- labels in the /dev/pts filesystem.
-
- If you are not using a security module that requires using
- extended attributes for file security labels, say N.
-
config TMPFS
bool "Virtual memory file system support (former shm fs)"
help
@@ -817,27 +805,6 @@ config TMPFS
See <file:Documentation/filesystems/tmpfs.txt> for details.
-config TMPFS_XATTR
- bool "tmpfs Extended Attributes"
- depends on TMPFS
- help
- Extended attributes are name:value pairs associated with inodes by
- the kernel or by users (see the attr(5) manual page, or visit
- <http://acl.bestbits.at/> for details).
-
- If unsure, say N.
-
-config TMPFS_SECURITY
- bool "tmpfs Security Labels"
- depends on TMPFS_XATTR
- help
- Security labels support alternative access control models
- implemented by security modules like SELinux. This option
- enables an extended attribute handler for file security
- labels in the tmpfs filesystem.
- If you are not using a security module that requires using
- extended attributes for file security labels, say N.
-
config HUGETLBFS
bool "HugeTLB file system support"
depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN
@@ -859,6 +826,18 @@ config RAMFS
To compile this as a module, choose M here: the module will be called
ramfs.
+config RELAYFS_FS
+ tristate "Relayfs file system support"
+ ---help---
+ Relayfs is a high-speed data relay filesystem designed to provide
+ an efficient mechanism for tools and facilities to relay large
+ amounts of data from kernel space to user space.
+
+ To compile this code as a module, choose M here: the module will be
+ called relayfs.
+
+ If unsure, say N.
+
endmenu
menu "Miscellaneous filesystems"
@@ -1737,6 +1716,17 @@ config AFS_FS
config RXRPC
tristate
+config 9P_FS
+ tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
+ depends on INET && EXPERIMENTAL
+ help
+ If you say Y here, you will get experimental support for
+ Plan 9 resource sharing via the 9P2000 protocol.
+
+ See <http://v9fs.sf.net> for more information.
+
+ If unsure, say N.
+
endmenu
menu "Partition Types"
diff --git a/fs/Makefile b/fs/Makefile
index cf95eb894fd5..1972da186272 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -89,10 +89,13 @@ obj-$(CONFIG_QNX4FS_FS) += qnx4/
obj-$(CONFIG_AUTOFS_FS) += autofs/
obj-$(CONFIG_AUTOFS4_FS) += autofs4/
obj-$(CONFIG_ADFS_FS) += adfs/
+obj-$(CONFIG_FUSE_FS) += fuse/
obj-$(CONFIG_UDF_FS) += udf/
+obj-$(CONFIG_RELAYFS_FS) += relayfs/
obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
obj-$(CONFIG_JFS_FS) += jfs/
obj-$(CONFIG_XFS_FS) += xfs/
+obj-$(CONFIG_9P_FS) += 9p/
obj-$(CONFIG_AFS_FS) += afs/
obj-$(CONFIG_BEFS_FS) += befs/
obj-$(CONFIG_HOSTFS) += hostfs/
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 63f5df9afb71..fd528433de43 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -97,7 +97,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
extern struct inode_operations adfs_file_inode_operations;
extern struct file_operations adfs_file_operations;
-extern inline __u32 signed_asl(__u32 val, signed int shift)
+static inline __u32 signed_asl(__u32 val, signed int shift)
{
if (shift >= 0)
val <<= shift;
@@ -112,7 +112,7 @@ extern inline __u32 signed_asl(__u32 val, signed int shift)
*
* The root directory ID should always be looked up in the map [3.4]
*/
-extern inline int
+static inline int
__adfs_block_map(struct super_block *sb, unsigned int object_id,
unsigned int block)
{
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 7aa6f2004536..9ebe881c6786 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -255,6 +255,7 @@ void
affs_delete_inode(struct inode *inode)
{
pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
+ truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
if (S_ISREG(inode->i_mode))
affs_truncate(inode);
diff --git a/fs/aio.c b/fs/aio.c
index 06d7d4390fe7..38f62680fd63 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -29,6 +29,7 @@
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/security.h>
+#include <linux/rcuref.h>
#include <asm/kmap_types.h>
#include <asm/uaccess.h>
@@ -499,7 +500,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
/* Must be done under the lock to serialise against cancellation.
* Call this aio_fput as it duplicates fput via the fput_work.
*/
- if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) {
+ if (unlikely(rcuref_dec_and_test(&req->ki_filp->f_count))) {
get_ioctx(ctx);
spin_lock(&fput_lock);
list_add(&req->ki_list, &fput_head);
@@ -546,6 +547,24 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id)
return ioctx;
}
+static int lock_kiocb_action(void *param)
+{
+ schedule();
+ return 0;
+}
+
+static inline void lock_kiocb(struct kiocb *iocb)
+{
+ wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action,
+ TASK_UNINTERRUPTIBLE);
+}
+
+static inline void unlock_kiocb(struct kiocb *iocb)
+{
+ kiocbClearLocked(iocb);
+ wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
+}
+
/*
* use_mm
* Makes the calling kernel thread take on the specified
@@ -567,6 +586,10 @@ static void use_mm(struct mm_struct *mm)
atomic_inc(&mm->mm_count);
tsk->mm = mm;
tsk->active_mm = mm;
+ /*
+ * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
+ * it won't work. Update it accordingly if you change it here
+ */
activate_mm(active_mm, mm);
task_unlock(tsk);
@@ -782,7 +805,9 @@ static int __aio_run_iocbs(struct kioctx *ctx)
* Hold an extra reference while retrying i/o.
*/
iocb->ki_users++; /* grab extra reference */
+ lock_kiocb(iocb);
aio_run_iocb(iocb);
+ unlock_kiocb(iocb);
if (__aio_put_req(ctx, iocb)) /* drop extra ref */
put_ioctx(ctx);
}
@@ -1523,10 +1548,9 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
goto out_put_req;
spin_lock_irq(&ctx->ctx_lock);
- if (likely(list_empty(&ctx->run_list))) {
- aio_run_iocb(req);
- } else {
- list_add_tail(&req->ki_run_list, &ctx->run_list);
+ aio_run_iocb(req);
+ unlock_kiocb(req);
+ if (!list_empty(&ctx->run_list)) {
/* drain the run list */
while (__aio_run_iocbs(ctx))
;
@@ -1657,6 +1681,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
if (NULL != cancel) {
struct io_event tmp;
pr_debug("calling cancel\n");
+ lock_kiocb(kiocb);
memset(&tmp, 0, sizeof(tmp));
tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
tmp.data = kiocb->ki_user_data;
@@ -1668,8 +1693,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
if (copy_to_user(result, &tmp, sizeof(tmp)))
ret = -EFAULT;
}
+ unlock_kiocb(kiocb);
} else
- printk(KERN_DEBUG "iocb has no cancel operation\n");
+ ret = -EINVAL;
put_ioctx(ctx);
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 6171431272dc..990c28da5aec 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -105,6 +105,7 @@ struct autofs_sb_info {
struct file *pipe;
pid_t oz_pgrp;
int catatonic;
+ struct super_block *sb;
unsigned long exp_timeout;
ino_t next_dir_ino;
struct autofs_wait_queue *queues; /* Wait queue pointer */
@@ -134,7 +135,7 @@ void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
void autofs_hash_delete(struct autofs_dir_ent *);
struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
void autofs_hash_dputall(struct autofs_dirhash *);
-void autofs_hash_nuke(struct autofs_dirhash *);
+void autofs_hash_nuke(struct autofs_sb_info *);
/* Expiration-handling functions */
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index 448143fd0796..5ccfcf26310d 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -232,13 +232,13 @@ void autofs_hash_dputall(struct autofs_dirhash *dh)
/* Delete everything. This is used on filesystem destruction, so we
make no attempt to keep the pointers valid */
-void autofs_hash_nuke(struct autofs_dirhash *dh)
+void autofs_hash_nuke(struct autofs_sb_info *sbi)
{
int i;
struct autofs_dir_ent *ent, *nent;
for ( i = 0 ; i < AUTOFS_HASH_SIZE ; i++ ) {
- for ( ent = dh->h[i] ; ent ; ent = nent ) {
+ for ( ent = sbi->dirhash.h[i] ; ent ; ent = nent ) {
nent = ent->next;
if ( ent->dentry )
dput(ent->dentry);
@@ -246,4 +246,5 @@ void autofs_hash_nuke(struct autofs_dirhash *dh)
kfree(ent);
}
}
+ shrink_dcache_sb(sbi->sb);
}
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 4888c1fabbf7..65e5ed42190e 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -27,7 +27,7 @@ static void autofs_put_super(struct super_block *sb)
if ( !sbi->catatonic )
autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
- autofs_hash_nuke(&sbi->dirhash);
+ autofs_hash_nuke(sbi);
for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
if ( test_bit(n, sbi->symlink_bitmap) )
kfree(sbi->symlink[n].data);
@@ -148,6 +148,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
s->s_magic = AUTOFS_SUPER_MAGIC;
s->s_op = &autofs_sops;
s->s_time_gran = 1;
+ sbi->sb = s;
root_inode = iget(s, AUTOFS_ROOT_INO);
root = d_alloc_root(root_inode);
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 1020dbc88bec..1fbc53f14aba 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -20,7 +20,6 @@ struct bfs_sb_info {
unsigned long si_lasti;
unsigned long * si_imap;
struct buffer_head * si_sbh; /* buffer header w/superblock */
- struct bfs_super_block * si_bfs_sb; /* superblock in si_sbh->b_data */
};
/*
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 5a1e5ce057ff..e240c335eb23 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -2,6 +2,7 @@
* fs/bfs/dir.c
* BFS directory operations.
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ * Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005
*/
#include <linux/time.h>
@@ -20,9 +21,9 @@
#define dprintf(x...)
#endif
-static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino);
+static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino);
static struct buffer_head * bfs_find_entry(struct inode * dir,
- const char * name, int namelen, struct bfs_dirent ** res_dir);
+ const unsigned char * name, int namelen, struct bfs_dirent ** res_dir);
static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
{
@@ -53,7 +54,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
de = (struct bfs_dirent *)(bh->b_data + offset);
if (de->ino) {
int size = strnlen(de->name, BFS_NAMELEN);
- if (filldir(dirent, de->name, size, f->f_pos, de->ino, DT_UNKNOWN) < 0) {
+ if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) {
brelse(bh);
unlock_kernel();
return 0;
@@ -107,7 +108,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
inode->i_mapping->a_ops = &bfs_aops;
inode->i_mode = mode;
inode->i_ino = ino;
- BFS_I(inode)->i_dsk_ino = ino;
+ BFS_I(inode)->i_dsk_ino = cpu_to_le16(ino);
BFS_I(inode)->i_sblock = 0;
BFS_I(inode)->i_eblock = 0;
insert_inode_hash(inode);
@@ -139,7 +140,7 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st
lock_kernel();
bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
if (bh) {
- unsigned long ino = le32_to_cpu(de->ino);
+ unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
brelse(bh);
inode = iget(dir->i_sb, ino);
if (!inode) {
@@ -183,7 +184,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
inode = dentry->d_inode;
lock_kernel();
bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
- if (!bh || de->ino != inode->i_ino)
+ if (!bh || le16_to_cpu(de->ino) != inode->i_ino)
goto out_brelse;
if (!inode->i_nlink) {
@@ -224,7 +225,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
old_dentry->d_name.name,
old_dentry->d_name.len, &old_de);
- if (!old_bh || old_de->ino != old_inode->i_ino)
+ if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino)
goto end_rename;
error = -EPERM;
@@ -270,7 +271,7 @@ struct inode_operations bfs_dir_inops = {
.rename = bfs_rename,
};
-static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
+static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino)
{
struct buffer_head * bh;
struct bfs_dirent * de;
@@ -304,7 +305,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
}
dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
- de->ino = ino;
+ de->ino = cpu_to_le16((u16)ino);
for (i=0; i<BFS_NAMELEN; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
mark_buffer_dirty(bh);
@@ -317,7 +318,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
return -ENOSPC;
}
-static inline int bfs_namecmp(int len, const char * name, const char * buffer)
+static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer)
{
if (len < BFS_NAMELEN && buffer[len])
return 0;
@@ -325,7 +326,7 @@ static inline int bfs_namecmp(int len, const char * name, const char * buffer)
}
static struct buffer_head * bfs_find_entry(struct inode * dir,
- const char * name, int namelen, struct bfs_dirent ** res_dir)
+ const unsigned char * name, int namelen, struct bfs_dirent ** res_dir)
{
unsigned long block, offset;
struct buffer_head * bh;
@@ -346,7 +347,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
}
de = (struct bfs_dirent *)(bh->b_data + offset);
offset += BFS_DIRENT_SIZE;
- if (de->ino && bfs_namecmp(namelen, name, de->name)) {
+ if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) {
*res_dir = de;
return bh;
}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 747fd1ea55e0..807723b65daf 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -40,8 +40,8 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo
return 0;
}
-static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned long end,
- unsigned long where)
+static int bfs_move_blocks(struct super_block *sb, unsigned long start,
+ unsigned long end, unsigned long where)
{
unsigned long i;
@@ -57,20 +57,21 @@ static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned
static int bfs_get_block(struct inode * inode, sector_t block,
struct buffer_head * bh_result, int create)
{
- long phys;
+ unsigned long phys;
int err;
struct super_block *sb = inode->i_sb;
struct bfs_sb_info *info = BFS_SB(sb);
struct bfs_inode_info *bi = BFS_I(inode);
struct buffer_head *sbh = info->si_sbh;
- if (block < 0 || block > info->si_blocks)
+ if (block > info->si_blocks)
return -EIO;
phys = bi->i_sblock + block;
if (!create) {
if (phys <= bi->i_eblock) {
- dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
+ dprintf("c=%d, b=%08lx, phys=%09lx (granted)\n",
+ create, (unsigned long)block, phys);
map_bh(bh_result, sb, phys);
}
return 0;
@@ -80,7 +81,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
of blocks allocated for this file, we can grant it */
if (inode->i_size && phys <= bi->i_eblock) {
dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
- create, block, phys);
+ create, (unsigned long)block, phys);
map_bh(bh_result, sb, phys);
return 0;
}
@@ -88,11 +89,12 @@ static int bfs_get_block(struct inode * inode, sector_t block,
/* the rest has to be protected against itself */
lock_kernel();
- /* if the last data block for this file is the last allocated block, we can
- extend the file trivially, without moving it anywhere */
+ /* if the last data block for this file is the last allocated
+ block, we can extend the file trivially, without moving it
+ anywhere */
if (bi->i_eblock == info->si_lf_eblk) {
dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
- create, block, phys);
+ create, (unsigned long)block, phys);
map_bh(bh_result, sb, phys);
info->si_freeb -= phys - bi->i_eblock;
info->si_lf_eblk = bi->i_eblock = phys;
@@ -114,7 +116,8 @@ static int bfs_get_block(struct inode * inode, sector_t block,
} else
err = 0;
- dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
+ dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n",
+ create, (unsigned long)block, phys);
bi->i_sblock = phys;
phys += block;
info->si_lf_eblk = bi->i_eblock = phys;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 64e0fb33fc0c..c7b39aa279d7 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -3,6 +3,8 @@
* BFS superblock and inode operations.
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
* From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
+ *
+ * Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
*/
#include <linux/module.h>
@@ -54,46 +56,50 @@ static void bfs_read_inode(struct inode * inode)
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
- inode->i_mode = 0x0000FFFF & di->i_mode;
- if (di->i_vtype == BFS_VDIR) {
+ inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
+ if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
inode->i_mode |= S_IFDIR;
inode->i_op = &bfs_dir_inops;
inode->i_fop = &bfs_dir_operations;
- } else if (di->i_vtype == BFS_VREG) {
+ } else if (le32_to_cpu(di->i_vtype) == BFS_VREG) {
inode->i_mode |= S_IFREG;
inode->i_op = &bfs_file_inops;
inode->i_fop = &bfs_file_operations;
inode->i_mapping->a_ops = &bfs_aops;
}
- inode->i_uid = di->i_uid;
- inode->i_gid = di->i_gid;
- inode->i_nlink = di->i_nlink;
+ BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
+ BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock);
+ inode->i_uid = le32_to_cpu(di->i_uid);
+ inode->i_gid = le32_to_cpu(di->i_gid);
+ inode->i_nlink = le32_to_cpu(di->i_nlink);
inode->i_size = BFS_FILESIZE(di);
inode->i_blocks = BFS_FILEBLOCKS(di);
+ if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
inode->i_blksize = PAGE_SIZE;
- inode->i_atime.tv_sec = di->i_atime;
- inode->i_mtime.tv_sec = di->i_mtime;
- inode->i_ctime.tv_sec = di->i_ctime;
+ inode->i_atime.tv_sec = le32_to_cpu(di->i_atime);
+ inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime);
+ inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime);
inode->i_atime.tv_nsec = 0;
inode->i_mtime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0;
- BFS_I(inode)->i_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
- BFS_I(inode)->i_sblock = di->i_sblock;
- BFS_I(inode)->i_eblock = di->i_eblock;
+ BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */
brelse(bh);
}
static int bfs_write_inode(struct inode * inode, int unused)
{
- unsigned long ino = inode->i_ino;
+ unsigned int ino = (u16)inode->i_ino;
+ unsigned long i_sblock;
struct bfs_inode * di;
struct buffer_head * bh;
int block, off;
+ dprintf("ino=%08x\n", ino);
+
if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
- printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino);
return -EIO;
}
@@ -101,7 +107,7 @@ static int bfs_write_inode(struct inode * inode, int unused)
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino);
unlock_kernel();
return -EIO;
}
@@ -109,24 +115,26 @@ static int bfs_write_inode(struct inode * inode, int unused)
off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
- if (inode->i_ino == BFS_ROOT_INO)
- di->i_vtype = BFS_VDIR;
+ if (ino == BFS_ROOT_INO)
+ di->i_vtype = cpu_to_le32(BFS_VDIR);
else
- di->i_vtype = BFS_VREG;
-
- di->i_ino = inode->i_ino;
- di->i_mode = inode->i_mode;
- di->i_uid = inode->i_uid;
- di->i_gid = inode->i_gid;
- di->i_nlink = inode->i_nlink;
- di->i_atime = inode->i_atime.tv_sec;
- di->i_mtime = inode->i_mtime.tv_sec;
- di->i_ctime = inode->i_ctime.tv_sec;
- di->i_sblock = BFS_I(inode)->i_sblock;
- di->i_eblock = BFS_I(inode)->i_eblock;
- di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
+ di->i_vtype = cpu_to_le32(BFS_VREG);
+
+ di->i_ino = cpu_to_le16(ino);
+ di->i_mode = cpu_to_le32(inode->i_mode);
+ di->i_uid = cpu_to_le32(inode->i_uid);
+ di->i_gid = cpu_to_le32(inode->i_gid);
+ di->i_nlink = cpu_to_le32(inode->i_nlink);
+ di->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
+ di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
+ di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
+ i_sblock = BFS_I(inode)->i_sblock;
+ di->i_sblock = cpu_to_le32(i_sblock);
+ di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock);
+ di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
mark_buffer_dirty(bh);
+ dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off);
brelse(bh);
unlock_kernel();
return 0;
@@ -140,11 +148,14 @@ static void bfs_delete_inode(struct inode * inode)
int block, off;
struct super_block * s = inode->i_sb;
struct bfs_sb_info * info = BFS_SB(s);
+ struct bfs_inode_info * bi = BFS_I(inode);
- dprintf("ino=%08lx\n", inode->i_ino);
+ dprintf("ino=%08lx\n", ino);
- if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > info->si_lasti) {
- printf("invalid ino=%08lx\n", inode->i_ino);
+ truncate_inode_pages(&inode->i_data, 0);
+
+ if (ino < BFS_ROOT_INO || ino > info->si_lasti) {
+ printf("invalid ino=%08lx\n", ino);
return;
}
@@ -160,13 +171,13 @@ static void bfs_delete_inode(struct inode * inode)
return;
}
off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
- di = (struct bfs_inode *)bh->b_data + off;
- if (di->i_ino) {
- info->si_freeb += BFS_FILEBLOCKS(di);
+ di = (struct bfs_inode *) bh->b_data + off;
+ if (bi->i_dsk_ino) {
+ info->si_freeb += 1 + bi->i_eblock - bi->i_sblock;
info->si_freei++;
- clear_bit(di->i_ino, info->si_imap);
+ clear_bit(ino, info->si_imap);
dump_imap("delete_inode", s);
- }
+ }
di->i_ino = 0;
di->i_sblock = 0;
mark_buffer_dirty(bh);
@@ -272,14 +283,14 @@ static struct super_operations bfs_sops = {
void dump_imap(const char *prefix, struct super_block * s)
{
-#if 0
+#ifdef DEBUG
int i;
char *tmpbuf = (char *)get_zeroed_page(GFP_KERNEL);
if (!tmpbuf)
return;
for (i=BFS_SB(s)->si_lasti; i>=0; i--) {
- if (i>PAGE_SIZE-100) break;
+ if (i > PAGE_SIZE-100) break;
if (test_bit(i, BFS_SB(s)->si_imap))
strcat(tmpbuf, "1");
else
@@ -295,7 +306,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
struct buffer_head * bh;
struct bfs_super_block * bfs_sb;
struct inode * inode;
- int i, imap_len;
+ unsigned i, imap_len;
struct bfs_sb_info * info;
info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -310,19 +321,18 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
if(!bh)
goto out;
bfs_sb = (struct bfs_super_block *)bh->b_data;
- if (bfs_sb->s_magic != BFS_MAGIC) {
+ if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
if (!silent)
printf("No BFS filesystem on %s (magic=%08x)\n",
- s->s_id, bfs_sb->s_magic);
+ s->s_id, le32_to_cpu(bfs_sb->s_magic));
goto out;
}
if (BFS_UNCLEAN(bfs_sb, s) && !silent)
printf("%s is unclean, continuing\n", s->s_id);
s->s_magic = BFS_MAGIC;
- info->si_bfs_sb = bfs_sb;
info->si_sbh = bh;
- info->si_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode)
+ info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode)
+ BFS_ROOT_INO - 1;
imap_len = info->si_lasti/8 + 1;
@@ -346,8 +356,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
goto out;
}
- info->si_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
- info->si_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
+ info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
+ info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - cpu_to_le32(bfs_sb->s_start))>>BFS_BSIZE_BITS;
info->si_freei = 0;
info->si_lf_eblk = 0;
info->si_lf_sblk = 0;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index c8998dc66882..7974efa107bc 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
down_write(&current->mm->mmap_sem);
- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
+ textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
diff --git a/fs/bio.c b/fs/bio.c
index 1f2d4649b188..83a349574567 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/mempool.h>
#include <linux/workqueue.h>
+#include <scsi/sg.h> /* for struct sg_iovec */
#define BIO_POOL_SIZE 256
@@ -104,18 +105,22 @@ static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int
return bvl;
}
-/*
- * default destructor for a bio allocated with bio_alloc_bioset()
- */
-static void bio_destructor(struct bio *bio)
+void bio_free(struct bio *bio, struct bio_set *bio_set)
{
const int pool_idx = BIO_POOL_IDX(bio);
- struct bio_set *bs = bio->bi_set;
BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
- mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]);
- mempool_free(bio, bs->bio_pool);
+ mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
+ mempool_free(bio, bio_set->bio_pool);
+}
+
+/*
+ * default destructor for a bio allocated with bio_alloc_bioset()
+ */
+static void bio_fs_destructor(struct bio *bio)
+{
+ bio_free(bio, fs_bio_set);
}
inline void bio_init(struct bio *bio)
@@ -171,8 +176,6 @@ struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, stru
bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
}
bio->bi_io_vec = bvl;
- bio->bi_destructor = bio_destructor;
- bio->bi_set = bs;
}
out:
return bio;
@@ -180,7 +183,12 @@ out:
struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs)
{
- return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+ struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+
+ if (bio)
+ bio->bi_destructor = bio_fs_destructor;
+
+ return bio;
}
void zero_fill_bio(struct bio *bio)
@@ -273,8 +281,10 @@ struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask)
{
struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
- if (b)
+ if (b) {
+ b->bi_destructor = bio_fs_destructor;
__bio_clone(b, bio);
+ }
return b;
}
@@ -546,22 +556,34 @@ out_bmd:
return ERR_PTR(ret);
}
-static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
- unsigned long uaddr, unsigned int len,
- int write_to_vm)
+static struct bio *__bio_map_user_iov(request_queue_t *q,
+ struct block_device *bdev,
+ struct sg_iovec *iov, int iov_count,
+ int write_to_vm)
{
- unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- unsigned long start = uaddr >> PAGE_SHIFT;
- const int nr_pages = end - start;
- int ret, offset, i;
+ int i, j;
+ int nr_pages = 0;
struct page **pages;
struct bio *bio;
+ int cur_page = 0;
+ int ret, offset;
- /*
- * transfer and buffer must be aligned to at least hardsector
- * size for now, in the future we can relax this restriction
- */
- if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+ for (i = 0; i < iov_count; i++) {
+ unsigned long uaddr = (unsigned long)iov[i].iov_base;
+ unsigned long len = iov[i].iov_len;
+ unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = uaddr >> PAGE_SHIFT;
+
+ nr_pages += end - start;
+ /*
+ * transfer and buffer must be aligned to at least hardsector
+ * size for now, in the future we can relax this restriction
+ */
+ if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!nr_pages)
return ERR_PTR(-EINVAL);
bio = bio_alloc(GFP_KERNEL, nr_pages);
@@ -573,42 +595,54 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
if (!pages)
goto out;
- down_read(&current->mm->mmap_sem);
- ret = get_user_pages(current, current->mm, uaddr, nr_pages,
- write_to_vm, 0, pages, NULL);
- up_read(&current->mm->mmap_sem);
-
- if (ret < nr_pages)
- goto out;
-
- bio->bi_bdev = bdev;
-
- offset = uaddr & ~PAGE_MASK;
- for (i = 0; i < nr_pages; i++) {
- unsigned int bytes = PAGE_SIZE - offset;
-
- if (len <= 0)
- break;
-
- if (bytes > len)
- bytes = len;
+ memset(pages, 0, nr_pages * sizeof(struct page *));
+
+ for (i = 0; i < iov_count; i++) {
+ unsigned long uaddr = (unsigned long)iov[i].iov_base;
+ unsigned long len = iov[i].iov_len;
+ unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = uaddr >> PAGE_SHIFT;
+ const int local_nr_pages = end - start;
+ const int page_limit = cur_page + local_nr_pages;
+
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, uaddr,
+ local_nr_pages,
+ write_to_vm, 0, &pages[cur_page], NULL);
+ up_read(&current->mm->mmap_sem);
+
+ if (ret < local_nr_pages)
+ goto out_unmap;
+
+
+ offset = uaddr & ~PAGE_MASK;
+ for (j = cur_page; j < page_limit; j++) {
+ unsigned int bytes = PAGE_SIZE - offset;
+
+ if (len <= 0)
+ break;
+
+ if (bytes > len)
+ bytes = len;
+
+ /*
+ * sorry...
+ */
+ if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
+ break;
+
+ len -= bytes;
+ offset = 0;
+ }
+ cur_page = j;
/*
- * sorry...
+ * release the pages we didn't map into the bio, if any
*/
- if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes)
- break;
-
- len -= bytes;
- offset = 0;
+ while (j < page_limit)
+ page_cache_release(pages[j++]);
}
- /*
- * release the pages we didn't map into the bio, if any
- */
- while (i < nr_pages)
- page_cache_release(pages[i++]);
-
kfree(pages);
/*
@@ -617,9 +651,17 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
if (!write_to_vm)
bio->bi_rw |= (1 << BIO_RW);
+ bio->bi_bdev = bdev;
bio->bi_flags |= (1 << BIO_USER_MAPPED);
return bio;
-out:
+
+ out_unmap:
+ for (i = 0; i < nr_pages; i++) {
+ if(!pages[i])
+ break;
+ page_cache_release(pages[i]);
+ }
+ out:
kfree(pages);
bio_put(bio);
return ERR_PTR(ret);
@@ -639,9 +681,33 @@ out:
struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
unsigned long uaddr, unsigned int len, int write_to_vm)
{
+ struct sg_iovec iov;
+
+ iov.iov_base = (void __user *)uaddr;
+ iov.iov_len = len;
+
+ return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm);
+}
+
+/**
+ * bio_map_user_iov - map user sg_iovec table into bio
+ * @q: the request_queue_t for the bio
+ * @bdev: destination block device
+ * @iov: the iovec.
+ * @iov_count: number of elements in the iovec
+ * @write_to_vm: bool indicating writing to pages or not
+ *
+ * Map the user space address into a bio suitable for io to a block
+ * device. Returns an error pointer in case of error.
+ */
+struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
+ struct sg_iovec *iov, int iov_count,
+ int write_to_vm)
+{
struct bio *bio;
+ int len = 0, i;
- bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm);
+ bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
if (IS_ERR(bio))
return bio;
@@ -654,6 +720,9 @@ struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
*/
bio_get(bio);
+ for (i = 0; i < iov_count; i++)
+ len += iov[i].iov_len;
+
if (bio->bi_size == len)
return bio;
@@ -698,6 +767,82 @@ void bio_unmap_user(struct bio *bio)
bio_put(bio);
}
+static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err)
+{
+ if (bio->bi_size)
+ return 1;
+
+ bio_put(bio);
+ return 0;
+}
+
+
+static struct bio *__bio_map_kern(request_queue_t *q, void *data,
+ unsigned int len, unsigned int gfp_mask)
+{
+ unsigned long kaddr = (unsigned long)data;
+ unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = kaddr >> PAGE_SHIFT;
+ const int nr_pages = end - start;
+ int offset, i;
+ struct bio *bio;
+
+ bio = bio_alloc(gfp_mask, nr_pages);
+ if (!bio)
+ return ERR_PTR(-ENOMEM);
+
+ offset = offset_in_page(kaddr);
+ for (i = 0; i < nr_pages; i++) {
+ unsigned int bytes = PAGE_SIZE - offset;
+
+ if (len <= 0)
+ break;
+
+ if (bytes > len)
+ bytes = len;
+
+ if (__bio_add_page(q, bio, virt_to_page(data), bytes,
+ offset) < bytes)
+ break;
+
+ data += bytes;
+ len -= bytes;
+ offset = 0;
+ }
+
+ bio->bi_end_io = bio_map_kern_endio;
+ return bio;
+}
+
+/**
+ * bio_map_kern - map kernel address into bio
+ * @q: the request_queue_t for the bio
+ * @data: pointer to buffer to map
+ * @len: length in bytes
+ * @gfp_mask: allocation flags for bio allocation
+ *
+ * Map the kernel address into a bio suitable for io to a block
+ * device. Returns an error pointer in case of error.
+ */
+struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
+ unsigned int gfp_mask)
+{
+ struct bio *bio;
+
+ bio = __bio_map_kern(q, data, len, gfp_mask);
+ if (IS_ERR(bio))
+ return bio;
+
+ if (bio->bi_size == len)
+ return bio;
+
+ /*
+ * Don't support partial mappings.
+ */
+ bio_put(bio);
+ return ERR_PTR(-EINVAL);
+}
+
/*
* bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
* for performing direct-IO in BIOs.
@@ -1075,6 +1220,7 @@ subsys_initcall(init_bio);
EXPORT_SYMBOL(bio_alloc);
EXPORT_SYMBOL(bio_put);
+EXPORT_SYMBOL(bio_free);
EXPORT_SYMBOL(bio_endio);
EXPORT_SYMBOL(bio_init);
EXPORT_SYMBOL(__bio_clone);
@@ -1085,6 +1231,7 @@ EXPORT_SYMBOL(bio_add_page);
EXPORT_SYMBOL(bio_get_nr_vecs);
EXPORT_SYMBOL(bio_map_user);
EXPORT_SYMBOL(bio_unmap_user);
+EXPORT_SYMBOL(bio_map_kern);
EXPORT_SYMBOL(bio_pair_release);
EXPORT_SYMBOL(bio_split);
EXPORT_SYMBOL(bio_split_pool);
diff --git a/fs/buffer.c b/fs/buffer.c
index 6a25d7df89b1..6cbfceabd95d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -40,6 +40,7 @@
#include <linux/cpu.h>
#include <linux/bitops.h>
#include <linux/mpage.h>
+#include <linux/bit_spinlock.h>
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
static void invalidate_bh_lrus(void);
@@ -917,8 +918,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
* contents - it is a noop if I/O is still in
* flight on potentially older contents.
*/
- wait_on_buffer(bh);
- ll_rw_block(WRITE, 1, &bh);
+ ll_rw_block(SWRITE, 1, &bh);
brelse(bh);
spin_lock(lock);
}
@@ -2793,21 +2793,22 @@ int submit_bh(int rw, struct buffer_head * bh)
/**
* ll_rw_block: low-level access to block devices (DEPRECATED)
- * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
+ * @rw: whether to %READ or %WRITE or %SWRITE or maybe %READA (readahead)
* @nr: number of &struct buffer_heads in the array
* @bhs: array of pointers to &struct buffer_head
*
- * ll_rw_block() takes an array of pointers to &struct buffer_heads,
- * and requests an I/O operation on them, either a %READ or a %WRITE.
- * The third %READA option is described in the documentation for
- * generic_make_request() which ll_rw_block() calls.
+ * ll_rw_block() takes an array of pointers to &struct buffer_heads, and
+ * requests an I/O operation on them, either a %READ or a %WRITE. The third
+ * %SWRITE is like %WRITE only we make sure that the *current* data in buffers
+ * are sent to disk. The fourth %READA option is described in the documentation
+ * for generic_make_request() which ll_rw_block() calls.
*
* This function drops any buffer that it cannot get a lock on (with the
- * BH_Lock state bit), any buffer that appears to be clean when doing a
- * write request, and any buffer that appears to be up-to-date when doing
- * read request. Further it marks as clean buffers that are processed for
- * writing (the buffer cache won't assume that they are actually clean until
- * the buffer gets unlocked).
+ * BH_Lock state bit) unless SWRITE is required, any buffer that appears to be
+ * clean when doing a write request, and any buffer that appears to be
+ * up-to-date when doing read request. Further it marks as clean buffers that
+ * are processed for writing (the buffer cache won't assume that they are
+ * actually clean until the buffer gets unlocked).
*
* ll_rw_block sets b_end_io to simple completion handler that marks
* the buffer up-to-date (if approriate), unlocks the buffer and wakes
@@ -2823,11 +2824,13 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
for (i = 0; i < nr; i++) {
struct buffer_head *bh = bhs[i];
- if (test_set_buffer_locked(bh))
+ if (rw == SWRITE)
+ lock_buffer(bh);
+ else if (test_set_buffer_locked(bh))
continue;
get_bh(bh);
- if (rw == WRITE) {
+ if (rw == WRITE || rw == SWRITE) {
if (test_clear_buffer_dirty(bh)) {
bh->b_end_io = end_buffer_write_sync;
submit_bh(WRITE, bh);
@@ -3046,10 +3049,9 @@ struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags)
{
struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags);
if (ret) {
- preempt_disable();
- __get_cpu_var(bh_accounting).nr++;
+ get_cpu_var(bh_accounting).nr++;
recalc_bh_state();
- preempt_enable();
+ put_cpu_var(bh_accounting);
}
return ret;
}
@@ -3059,10 +3061,9 @@ void free_buffer_head(struct buffer_head *bh)
{
BUG_ON(!list_empty(&bh->b_assoc_buffers));
kmem_cache_free(bh_cachep, bh);
- preempt_disable();
- __get_cpu_var(bh_accounting).nr--;
+ get_cpu_var(bh_accounting).nr--;
recalc_bh_state();
- preempt_enable();
+ put_cpu_var(bh_accounting);
}
EXPORT_SYMBOL(free_buffer_head);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc47a7f9..2335f14a1583 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -836,7 +836,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* go from value to value + temp_len condensing
double commas to singles. Note that this ends up
allocating a few bytes too many, which is ok */
- vol->password = kcalloc(1, temp_len, GFP_KERNEL);
+ vol->password = kzalloc(temp_len, GFP_KERNEL);
if(vol->password == NULL) {
printk("CIFS: no memory for pass\n");
return 1;
@@ -851,7 +851,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
}
vol->password[j] = 0;
} else {
- vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
+ vol->password = kzalloc(temp_len+1, GFP_KERNEL);
if(vol->password == NULL) {
printk("CIFS: no memory for pass\n");
return 1;
@@ -1317,7 +1317,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
sessinit is sent but no second negprot */
struct rfc1002_session_packet * ses_init_buf;
struct smb_hdr * smb_buf;
- ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+ ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
if(ses_init_buf) {
ses_init_buf->trailer.session_req.called_len = 32;
rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
@@ -1964,7 +1964,7 @@ 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 */
- ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverOS,
@@ -1976,7 +1976,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *)bcc_ptr,
remaining_words-1);
- ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
+ ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverNOS,
@@ -1994,7 +1994,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2*(len+1),GFP_KERNEL);
+ kzalloc(2*(len+1),GFP_KERNEL);
if(ses->serverDomain == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverDomain,
@@ -2005,22 +2005,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ 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 */
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
ses->serverNOS =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
strncpy(ses->serverOS,bcc_ptr, len);
@@ -2030,7 +2030,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
strncpy(ses->serverNOS, bcc_ptr, len);
@@ -2039,7 +2039,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverDomain == NULL)
goto sesssetup_nomem;
strncpy(ses->serverDomain, bcc_ptr, len);
@@ -2240,7 +2240,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
(wchar_t *)
bcc_ptr, len,
@@ -2254,7 +2254,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->serverNOS,
(wchar_t *)bcc_ptr,
@@ -2267,7 +2267,7 @@ CIFSSpnegoSessSetup(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) */
- ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
+ ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
cifs_strfromUCS_le(ses->serverDomain,
(wchar_t *)bcc_ptr,
len,
@@ -2278,10 +2278,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2,GFP_KERNEL);
+ kzalloc(2,GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
- ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
- ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+ ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
@@ -2289,7 +2289,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS, bcc_ptr, len);
bcc_ptr += len;
@@ -2297,14 +2297,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
+ ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
@@ -2554,7 +2554,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
(wchar_t *)
bcc_ptr, len,
@@ -2569,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
@@ -2586,7 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2 *
+ kzalloc(2 *
(len +
1),
GFP_KERNEL);
@@ -2612,13 +2612,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2,
+ kzalloc(2,
GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
ses->serverNOS =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
@@ -2626,7 +2626,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
ses->serverOS =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverOS,
bcc_ptr, len);
@@ -2637,7 +2637,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
len = strnlen(bcc_ptr, 1024);
ses->serverNOS =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
@@ -2646,7 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
len = strnlen(bcc_ptr, 1024);
ses->serverDomain =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
@@ -2948,7 +2948,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
(wchar_t *)
bcc_ptr, len,
@@ -2963,7 +2963,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
@@ -2979,7 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string not always null terminated (e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2 *
+ kzalloc(2 *
(len +
1),
GFP_KERNEL);
@@ -3004,17 +3004,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
= 0;
} /* else no more room so create dummy domain string */
else
- ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
+ ses->serverDomain = kzalloc(2,GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
- ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
- ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+ ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) -
(long) pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr += len;
@@ -3022,14 +3022,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
+ ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
@@ -3141,7 +3141,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
if(tcon->nativeFileSystem)
kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
- kcalloc(1, length + 2, GFP_KERNEL);
+ kzalloc(length + 2, GFP_KERNEL);
cifs_strfromUCS_le(tcon->nativeFileSystem,
(wchar_t *) bcc_ptr,
length, nls_codepage);
@@ -3159,7 +3159,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
if(tcon->nativeFileSystem)
kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
- kcalloc(1, length + 1, GFP_KERNEL);
+ kzalloc(length + 1, GFP_KERNEL);
strncpy(tcon->nativeFileSystem, bcc_ptr,
length);
}
@@ -3215,10 +3215,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
}
cifs_sb->tcon = NULL;
- if (ses) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 2);
- }
+ if (ses)
+ schedule_timeout_interruptible(msecs_to_jiffies(500));
if (ses)
sesInfoFree(ses);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d4a1fa..d335269bd91c 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -145,24 +145,23 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return -ENOMEM;
}
- if(nd) {
- if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
- desiredAccess = GENERIC_READ;
- else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
- desiredAccess = GENERIC_WRITE;
- write_only = TRUE;
- } else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request */
- /* can cause unnecessary access denied on create */
- /* desiredAccess = GENERIC_ALL; */
- desiredAccess = GENERIC_READ | GENERIC_WRITE;
+ if(nd && (nd->flags & LOOKUP_OPEN)) {
+ int oflags = nd->intent.open.flags;
+
+ desiredAccess = 0;
+ if (oflags & FMODE_READ)
+ desiredAccess |= GENERIC_READ;
+ if (oflags & FMODE_WRITE) {
+ desiredAccess |= GENERIC_WRITE;
+ if (!(oflags & FMODE_READ))
+ write_only = TRUE;
}
- if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
disposition = FILE_CREATE;
- else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
disposition = FILE_OVERWRITE_IF;
- else if((nd->intent.open.flags & O_CREAT) == O_CREAT)
+ else if((oflags & O_CREAT) == O_CREAT)
disposition = FILE_OPEN_IF;
else {
cFYI(1,("Create flag not set in create function"));
diff --git a/fs/compat.c b/fs/compat.c
index 6b06b6bae35e..ac3fb9ed8eea 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -310,96 +310,6 @@ static int __init init_sys32_ioctl(void)
__initcall(init_sys32_ioctl);
-int register_ioctl32_conversion(unsigned int cmd,
- ioctl_trans_handler_t handler)
-{
- struct ioctl_trans *t;
- struct ioctl_trans *new_t;
- unsigned long hash = ioctl32_hash(cmd);
-
- new_t = kmalloc(sizeof(*new_t), GFP_KERNEL);
- if (!new_t)
- return -ENOMEM;
-
- down_write(&ioctl32_sem);
- for (t = ioctl32_hash_table[hash]; t; t = t->next) {
- if (t->cmd == cmd) {
- printk(KERN_ERR "Trying to register duplicated ioctl32 "
- "handler %x\n", cmd);
- up_write(&ioctl32_sem);
- kfree(new_t);
- return -EINVAL;
- }
- }
- new_t->next = NULL;
- new_t->cmd = cmd;
- new_t->handler = handler;
- ioctl32_insert_translation(new_t);
-
- up_write(&ioctl32_sem);
- return 0;
-}
-EXPORT_SYMBOL(register_ioctl32_conversion);
-
-static inline int builtin_ioctl(struct ioctl_trans *t)
-{
- return t >= ioctl_start && t < (ioctl_start + ioctl_table_size);
-}
-
-/* Problem:
- This function cannot unregister duplicate ioctls, because they are not
- unique.
- When they happen we need to extend the prototype to pass the handler too. */
-
-int unregister_ioctl32_conversion(unsigned int cmd)
-{
- unsigned long hash = ioctl32_hash(cmd);
- struct ioctl_trans *t, *t1;
-
- down_write(&ioctl32_sem);
-
- t = ioctl32_hash_table[hash];
- if (!t) {
- up_write(&ioctl32_sem);
- return -EINVAL;
- }
-
- if (t->cmd == cmd) {
- if (builtin_ioctl(t)) {
- printk("%p tried to unregister builtin ioctl %x\n",
- __builtin_return_address(0), cmd);
- } else {
- ioctl32_hash_table[hash] = t->next;
- up_write(&ioctl32_sem);
- kfree(t);
- return 0;
- }
- }
- while (t->next) {
- t1 = t->next;
- if (t1->cmd == cmd) {
- if (builtin_ioctl(t1)) {
- printk("%p tried to unregister builtin "
- "ioctl %x\n",
- __builtin_return_address(0), cmd);
- goto out;
- } else {
- t->next = t1->next;
- up_write(&ioctl32_sem);
- kfree(t1);
- return 0;
- }
- }
- t = t1;
- }
- printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n",
- cmd);
-out:
- up_write(&ioctl32_sem);
- return -EINVAL;
-}
-EXPORT_SYMBOL(unregister_ioctl32_conversion);
-
static void compat_ioctl_error(struct file *filp, unsigned int fd,
unsigned int cmd, unsigned long arg)
{
@@ -720,14 +630,14 @@ compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb)
struct compat_ncp_mount_data {
compat_int_t version;
compat_uint_t ncp_fd;
- compat_uid_t mounted_uid;
+ __compat_uid_t mounted_uid;
compat_pid_t wdog_pid;
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
compat_uint_t time_out;
compat_uint_t retry_count;
compat_uint_t flags;
- compat_uid_t uid;
- compat_gid_t gid;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
compat_mode_t file_mode;
compat_mode_t dir_mode;
};
@@ -784,9 +694,9 @@ static void *do_ncp_super_data_conv(void *raw_data)
struct compat_smb_mount_data {
compat_int_t version;
- compat_uid_t mounted_uid;
- compat_uid_t uid;
- compat_gid_t gid;
+ __compat_uid_t mounted_uid;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
compat_mode_t file_mode;
compat_mode_t dir_mode;
};
@@ -1365,6 +1275,16 @@ out:
}
/*
+ * Exactly like fs/open.c:sys_open(), except that it doesn't set the
+ * O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_open(const char __user *filename, int flags, int mode)
+{
+ return do_sys_open(filename, flags, mode);
+}
+
+/*
* compat_count() counts the number of arguments/envelopes. It is basically
* a copy of count() from fs/exec.c, except that it works with 32 bit argv
* and envp pointers.
@@ -1699,6 +1619,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
char *bits;
long timeout;
int size, max_fdset, ret = -EINVAL;
+ struct fdtable *fdt;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -1724,7 +1645,10 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
goto out_nofds;
/* max_fdset can increase, so grab it once to avoid race */
- max_fdset = current->files->max_fdset;
+ rcu_read_lock();
+ fdt = files_fdtable(current->files);
+ max_fdset = fdt->max_fdset;
+ rcu_read_unlock();
if (n > max_fdset)
n = max_fdset;
@@ -1808,8 +1732,8 @@ struct compat_nfsctl_export {
compat_dev_t ex32_dev;
compat_ino_t ex32_ino;
compat_int_t ex32_flags;
- compat_uid_t ex32_anon_uid;
- compat_gid_t ex32_anon_gid;
+ __compat_uid_t ex32_anon_uid;
+ __compat_gid_t ex32_anon_gid;
};
struct compat_nfsctl_fdparm {
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 155e612635f1..e28a74203f3b 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -798,13 +798,16 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
r = (void *) &r4;
}
- if (ret)
- return -EFAULT;
+ if (ret) {
+ ret = -EFAULT;
+ goto out;
+ }
set_fs (KERNEL_DS);
ret = sys_ioctl (fd, cmd, (unsigned long) r);
set_fs (old_fs);
+out:
if (mysock)
sockfd_put(mysock);
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6c285efa2004..7fe85415ae7c 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -39,12 +39,47 @@ static DECLARE_MUTEX(read_mutex);
#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
#define OFFSET(x) ((x)->i_ino)
-static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
+
+static int cramfs_iget5_test(struct inode *inode, void *opaque)
+{
+ struct cramfs_inode *cramfs_inode = opaque;
+
+ if (inode->i_ino != CRAMINO(cramfs_inode))
+ return 0; /* does not match */
+
+ if (inode->i_ino != 1)
+ return 1;
+
+ /* all empty directories, char, block, pipe, and sock, share inode #1 */
+
+ if ((inode->i_mode != cramfs_inode->mode) ||
+ (inode->i_gid != cramfs_inode->gid) ||
+ (inode->i_uid != cramfs_inode->uid))
+ return 0; /* does not match */
+
+ if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
+ (inode->i_rdev != old_decode_dev(cramfs_inode->size)))
+ return 0; /* does not match */
+
+ return 1; /* matches */
+}
+
+static int cramfs_iget5_set(struct inode *inode, void *opaque)
+{
+ struct cramfs_inode *cramfs_inode = opaque;
+ inode->i_ino = CRAMINO(cramfs_inode);
+ return 0;
+}
+
+static struct inode *get_cramfs_inode(struct super_block *sb,
+ struct cramfs_inode * cramfs_inode)
{
- struct inode * inode = new_inode(sb);
+ struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
+ cramfs_iget5_test, cramfs_iget5_set,
+ cramfs_inode);
static struct timespec zerotime;
- if (inode) {
+ if (inode && (inode->i_state & I_NEW)) {
inode->i_mode = cramfs_inode->mode;
inode->i_uid = cramfs_inode->uid;
inode->i_size = cramfs_inode->size;
@@ -58,7 +93,6 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
but it's the best we can do without reading the directory
contents. 1 yields the right result in GNU find, even
without -noleaf option. */
- insert_inode_hash(inode);
if (S_ISREG(inode->i_mode)) {
inode->i_fop = &generic_ro_fops;
inode->i_data.a_ops = &cramfs_aops;
@@ -74,6 +108,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
init_special_inode(inode, inode->i_mode,
old_decode_dev(cramfs_inode->size));
}
+ unlock_new_inode(inode);
}
return inode;
}
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index 5034365b06a8..8def89f2c438 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/vmalloc.h>
#include <linux/zlib.h>
+#include <linux/cramfs_fs.h>
static z_stream stream;
static int initialized;
diff --git a/fs/dcache.c b/fs/dcache.c
index a15a2e1f5520..7376b61269fb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -337,12 +337,10 @@ struct dentry * d_find_alias(struct inode *inode)
*/
void d_prune_aliases(struct inode *inode)
{
- struct list_head *tmp, *head = &inode->i_dentry;
+ struct dentry *dentry;
restart:
spin_lock(&dcache_lock);
- tmp = head;
- while ((tmp = tmp->next) != head) {
- struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+ list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
spin_lock(&dentry->d_lock);
if (!atomic_read(&dentry->d_count)) {
__dget_locked(dentry);
@@ -463,10 +461,7 @@ void shrink_dcache_sb(struct super_block * sb)
* superblock to the most recent end of the unused list.
*/
spin_lock(&dcache_lock);
- next = dentry_unused.next;
- while (next != &dentry_unused) {
- tmp = next;
- next = tmp->next;
+ list_for_each_safe(tmp, next, &dentry_unused) {
dentry = list_entry(tmp, struct dentry, d_lru);
if (dentry->d_sb != sb)
continue;
@@ -478,10 +473,7 @@ void shrink_dcache_sb(struct super_block * sb)
* Pass two ... free the dentries for this superblock.
*/
repeat:
- next = dentry_unused.next;
- while (next != &dentry_unused) {
- tmp = next;
- next = tmp->next;
+ list_for_each_safe(tmp, next, &dentry_unused) {
dentry = list_entry(tmp, struct dentry, d_lru);
if (dentry->d_sb != sb)
continue;
diff --git a/fs/devpts/Makefile b/fs/devpts/Makefile
index 5800df2e50c8..236696efcbac 100644
--- a/fs/devpts/Makefile
+++ b/fs/devpts/Makefile
@@ -5,4 +5,3 @@
obj-$(CONFIG_UNIX98_PTYS) += devpts.o
devpts-$(CONFIG_UNIX98_PTYS) := inode.o
-devpts-$(CONFIG_DEVPTS_FS_SECURITY) += xattr_security.o
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1571c8d6c232..f2be44d4491f 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -18,28 +18,9 @@
#include <linux/mount.h>
#include <linux/tty.h>
#include <linux/devpts_fs.h>
-#include <linux/xattr.h>
#define DEVPTS_SUPER_MAGIC 0x1cd1
-extern struct xattr_handler devpts_xattr_security_handler;
-
-static struct xattr_handler *devpts_xattr_handlers[] = {
-#ifdef CONFIG_DEVPTS_FS_SECURITY
- &devpts_xattr_security_handler,
-#endif
- NULL
-};
-
-static struct inode_operations devpts_file_inode_operations = {
-#ifdef CONFIG_DEVPTS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-#endif
-};
-
static struct vfsmount *devpts_mnt;
static struct dentry *devpts_root;
@@ -102,7 +83,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
- s->s_xattr = devpts_xattr_handlers;
s->s_time_gran = 1;
inode = new_inode(s);
@@ -175,7 +155,6 @@ int devpts_pty_new(struct tty_struct *tty)
inode->i_gid = config.setgid ? config.gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
- inode->i_op = &devpts_file_inode_operations;
inode->u.generic_ip = tty;
dentry = get_node(number);
diff --git a/fs/devpts/xattr_security.c b/fs/devpts/xattr_security.c
deleted file mode 100644
index 864cb5c79baa..000000000000
--- a/fs/devpts/xattr_security.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Security xattr support for devpts.
- *
- * Author: Stephen Smalley <sds@epoch.ncsc.mil>
- * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/xattr.h>
-
-static size_t
-devpts_xattr_security_list(struct inode *inode, char *list, size_t list_len,
- const char *name, size_t name_len)
-{
- return security_inode_listsecurity(inode, list, list_len);
-}
-
-static int
-devpts_xattr_security_get(struct inode *inode, const char *name,
- void *buffer, size_t size)
-{
- if (strcmp(name, "") == 0)
- return -EINVAL;
- return security_inode_getsecurity(inode, name, buffer, size);
-}
-
-static int
-devpts_xattr_security_set(struct inode *inode, const char *name,
- const void *value, size_t size, int flags)
-{
- if (strcmp(name, "") == 0)
- return -EINVAL;
- return security_inode_setsecurity(inode, name, value, size, flags);
-}
-
-struct xattr_handler devpts_xattr_security_handler = {
- .prefix = XATTR_SECURITY_PREFIX,
- .list = devpts_xattr_security_list,
- .get = devpts_xattr_security_get,
- .set = devpts_xattr_security_set,
-};
diff --git a/fs/exec.c b/fs/exec.c
index 222ab1c572d8..14dd03907ccb 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -798,6 +798,7 @@ no_thread_group:
static inline void flush_old_files(struct files_struct * files)
{
long j = -1;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
for (;;) {
@@ -805,12 +806,13 @@ static inline void flush_old_files(struct files_struct * files)
j++;
i = j * __NFDBITS;
- if (i >= files->max_fds || i >= files->max_fdset)
+ fdt = files_fdtable(files);
+ if (i >= fdt->max_fds || i >= fdt->max_fdset)
break;
- set = files->close_on_exec->fds_bits[j];
+ set = fdt->close_on_exec->fds_bits[j];
if (!set)
continue;
- files->close_on_exec->fds_bits[j] = 0;
+ fdt->close_on_exec->fds_bits[j] = 0;
spin_unlock(&files->file_lock);
for ( ; set ; i++,set >>= 1) {
if (set & 1) {
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 161f156d98c8..c8d07030c897 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -615,6 +615,11 @@ got:
DQUOT_DROP(inode);
goto fail2;
}
+ err = ext2_init_security(inode,dir);
+ if (err) {
+ DQUOT_FREE_INODE(inode);
+ goto fail2;
+ }
mark_inode_dirty(inode);
ext2_debug("allocating inode %lu\n", inode->i_ino);
ext2_preread_inode(inode);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 53dceb0c6593..fdba4d1d3c60 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -71,6 +71,8 @@ void ext2_put_inode(struct inode *inode)
*/
void ext2_delete_inode (struct inode * inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
+
if (is_bad_inode(inode))
goto no_delete;
EXT2_I(inode)->i_dtime = get_seconds();
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index dcfe331dc4c4..3c0c7c6a5b44 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -19,6 +19,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/blkdev.h>
@@ -27,6 +28,8 @@
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
#include <linux/vfs.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
#include <asm/uaccess.h>
#include "ext2.h"
#include "xattr.h"
@@ -201,6 +204,26 @@ static void ext2_clear_inode(struct inode *inode)
#endif
}
+static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct ext2_sb_info *sbi = EXT2_SB(vfs->mnt_sb);
+
+ if (sbi->s_mount_opt & EXT2_MOUNT_GRPID)
+ seq_puts(seq, ",grpid");
+ else
+ seq_puts(seq, ",nogrpid");
+
+#if defined(CONFIG_QUOTA)
+ if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)
+ seq_puts(seq, ",usrquota");
+
+ if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA)
+ seq_puts(seq, ",grpquota");
+#endif
+
+ return 0;
+}
+
#ifdef CONFIG_QUOTA
static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off);
static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
@@ -218,6 +241,7 @@ static struct super_operations ext2_sops = {
.statfs = ext2_statfs,
.remount_fs = ext2_remount,
.clear_inode = ext2_clear_inode,
+ .show_options = ext2_show_options,
#ifdef CONFIG_QUOTA
.quota_read = ext2_quota_read,
.quota_write = ext2_quota_write,
@@ -256,10 +280,11 @@ static unsigned long get_sb_block(void **data)
enum {
Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
- Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
- Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
- Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
- Opt_ignore, Opt_err,
+ Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
+ Opt_err_ro, Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug,
+ Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
+ Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
+ Opt_usrquota, Opt_grpquota
};
static match_table_t tokens = {
@@ -288,10 +313,10 @@ static match_table_t tokens = {
{Opt_acl, "acl"},
{Opt_noacl, "noacl"},
{Opt_xip, "xip"},
- {Opt_ignore, "grpquota"},
+ {Opt_grpquota, "grpquota"},
{Opt_ignore, "noquota"},
- {Opt_ignore, "quota"},
- {Opt_ignore, "usrquota"},
+ {Opt_quota, "quota"},
+ {Opt_usrquota, "usrquota"},
{Opt_err, NULL}
};
@@ -406,6 +431,26 @@ static int parse_options (char * options,
printk("EXT2 xip option not supported\n");
#endif
break;
+
+#if defined(CONFIG_QUOTA)
+ case Opt_quota:
+ case Opt_usrquota:
+ set_opt(sbi->s_mount_opt, USRQUOTA);
+ break;
+
+ case Opt_grpquota:
+ set_opt(sbi->s_mount_opt, GRPQUOTA);
+ break;
+#else
+ case Opt_quota:
+ case Opt_usrquota:
+ case Opt_grpquota:
+ printk(KERN_ERR
+ "EXT2-fs: quota operations not supported.\n");
+
+ break;
+#endif
+
case Opt_ignore:
break;
default:
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index 5f3bfde3b810..67cfeb66e897 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -116,3 +116,11 @@ exit_ext2_xattr(void)
# endif /* CONFIG_EXT2_FS_XATTR */
+#ifdef CONFIG_EXT2_FS_SECURITY
+extern int ext2_init_security(struct inode *inode, struct inode *dir);
+#else
+static inline int ext2_init_security(struct inode *inode, struct inode *dir)
+{
+ return 0;
+}
+#endif
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 6a6c59fbe599..a26612798471 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -8,6 +8,7 @@
#include <linux/fs.h>
#include <linux/smp_lock.h>
#include <linux/ext2_fs.h>
+#include <linux/security.h>
#include "xattr.h"
static size_t
@@ -45,6 +46,27 @@ ext2_xattr_security_set(struct inode *inode, const char *name,
value, size, flags);
}
+int
+ext2_init_security(struct inode *inode, struct inode *dir)
+{
+ int err;
+ size_t len;
+ void *value;
+ char *name;
+
+ err = security_inode_init_security(inode, dir, &name, &value, &len);
+ if (err) {
+ if (err == -EOPNOTSUPP)
+ return 0;
+ return err;
+ }
+ err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
+ name, value, len, 0);
+ kfree(name);
+ kfree(value);
+ return err;
+}
+
struct xattr_handler ext2_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.list = ext2_xattr_security_list,
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 6981bd014ede..96552769d039 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -607,6 +607,11 @@ got:
DQUOT_DROP(inode);
goto fail2;
}
+ err = ext3_init_security(handle,inode, dir);
+ if (err) {
+ DQUOT_FREE_INODE(inode);
+ goto fail2;
+ }
err = ext3_mark_inode_dirty(handle, inode);
if (err) {
ext3_std_error(sb, err);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 9989fdcf4d5a..b5177c90d6f1 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -187,6 +187,8 @@ void ext3_delete_inode (struct inode * inode)
{
handle_t *handle;
+ truncate_inode_pages(&inode->i_data, 0);
+
if (is_bad_inode(inode))
goto no_delete;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 3c3c6e399fb3..a93c3609025d 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -35,6 +35,7 @@
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/quotaops.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include "xattr.h"
#include "acl.h"
@@ -509,8 +510,41 @@ static void ext3_clear_inode(struct inode *inode)
kfree(rsv);
}
-#ifdef CONFIG_QUOTA
+static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct ext3_sb_info *sbi = EXT3_SB(vfs->mnt_sb);
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_JOURNAL_DATA)
+ seq_puts(seq, ",data=journal");
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_ORDERED_DATA)
+ seq_puts(seq, ",data=ordered");
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_WRITEBACK_DATA)
+ seq_puts(seq, ",data=writeback");
+
+#if defined(CONFIG_QUOTA)
+ if (sbi->s_jquota_fmt)
+ seq_printf(seq, ",jqfmt=%s",
+ (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
+
+ if (sbi->s_qf_names[USRQUOTA])
+ seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+
+ if (sbi->s_qf_names[GRPQUOTA])
+ seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+ if (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA)
+ seq_puts(seq, ",usrquota");
+
+ if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
+ seq_puts(seq, ",grpquota");
+#endif
+
+ return 0;
+}
+
+#ifdef CONFIG_QUOTA
#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
@@ -569,6 +603,7 @@ static struct super_operations ext3_sops = {
.statfs = ext3_statfs,
.remount_fs = ext3_remount,
.clear_inode = ext3_clear_inode,
+ .show_options = ext3_show_options,
#ifdef CONFIG_QUOTA
.quota_read = ext3_quota_read,
.quota_write = ext3_quota_write,
@@ -590,7 +625,8 @@ enum {
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
- Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
+ Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+ Opt_grpquota
};
static match_table_t tokens = {
@@ -634,10 +670,10 @@ static match_table_t tokens = {
{Opt_grpjquota, "grpjquota=%s"},
{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
- {Opt_quota, "grpquota"},
+ {Opt_grpquota, "grpquota"},
{Opt_noquota, "noquota"},
{Opt_quota, "quota"},
- {Opt_quota, "usrquota"},
+ {Opt_usrquota, "usrquota"},
{Opt_barrier, "barrier=%u"},
{Opt_err, NULL},
{Opt_resize, "resize"},
@@ -903,7 +939,13 @@ clear_qf_name:
sbi->s_jquota_fmt = QFMT_VFS_V0;
break;
case Opt_quota:
+ case Opt_usrquota:
set_opt(sbi->s_mount_opt, QUOTA);
+ set_opt(sbi->s_mount_opt, USRQUOTA);
+ break;
+ case Opt_grpquota:
+ set_opt(sbi->s_mount_opt, QUOTA);
+ set_opt(sbi->s_mount_opt, GRPQUOTA);
break;
case Opt_noquota:
if (sb_any_quota_enabled(sb)) {
@@ -912,8 +954,13 @@ clear_qf_name:
return 0;
}
clear_opt(sbi->s_mount_opt, QUOTA);
+ clear_opt(sbi->s_mount_opt, USRQUOTA);
+ clear_opt(sbi->s_mount_opt, GRPQUOTA);
break;
#else
+ case Opt_quota:
+ case Opt_usrquota:
+ case Opt_grpquota:
case Opt_usrjquota:
case Opt_grpjquota:
case Opt_offusrjquota:
@@ -924,7 +971,6 @@ clear_qf_name:
"EXT3-fs: journalled quota options not "
"supported.\n");
break;
- case Opt_quota:
case Opt_noquota:
break;
#endif
@@ -962,14 +1008,38 @@ clear_qf_name:
}
}
#ifdef CONFIG_QUOTA
- if (!sbi->s_jquota_fmt && (sbi->s_qf_names[USRQUOTA] ||
- sbi->s_qf_names[GRPQUOTA])) {
- printk(KERN_ERR
- "EXT3-fs: journalled quota format not specified.\n");
- return 0;
+ if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+ if ((sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA) &&
+ sbi->s_qf_names[USRQUOTA])
+ clear_opt(sbi->s_mount_opt, USRQUOTA);
+
+ if ((sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA) &&
+ sbi->s_qf_names[GRPQUOTA])
+ clear_opt(sbi->s_mount_opt, GRPQUOTA);
+
+ if ((sbi->s_qf_names[USRQUOTA] &&
+ (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)) ||
+ (sbi->s_qf_names[GRPQUOTA] &&
+ (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA))) {
+ printk(KERN_ERR "EXT3-fs: old and new quota "
+ "format mixing.\n");
+ return 0;
+ }
+
+ if (!sbi->s_jquota_fmt) {
+ printk(KERN_ERR "EXT3-fs: journalled quota format "
+ "not specified.\n");
+ return 0;
+ }
+ } else {
+ if (sbi->s_jquota_fmt) {
+ printk(KERN_ERR "EXT3-fs: journalled quota format "
+ "specified with no journalling "
+ "enabled.\n");
+ return 0;
+ }
}
#endif
-
return 1;
}
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index eb31a69e82dc..2ceae38f3d49 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -133,3 +133,14 @@ exit_ext3_xattr(void)
#define ext3_xattr_handlers NULL
# endif /* CONFIG_EXT3_FS_XATTR */
+
+#ifdef CONFIG_EXT3_FS_SECURITY
+extern int ext3_init_security(handle_t *handle, struct inode *inode,
+ struct inode *dir);
+#else
+static inline int ext3_init_security(handle_t *handle, struct inode *inode,
+ struct inode *dir)
+{
+ return 0;
+}
+#endif
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index ddc1c41750e1..b9c40c15647b 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -9,6 +9,7 @@
#include <linux/smp_lock.h>
#include <linux/ext3_jbd.h>
#include <linux/ext3_fs.h>
+#include <linux/security.h>
#include "xattr.h"
static size_t
@@ -47,6 +48,27 @@ ext3_xattr_security_set(struct inode *inode, const char *name,
value, size, flags);
}
+int
+ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+{
+ int err;
+ size_t len;
+ void *value;
+ char *name;
+
+ err = security_inode_init_security(inode, dir, &name, &value, &len);
+ if (err) {
+ if (err == -EOPNOTSUPP)
+ return 0;
+ return err;
+ }
+ err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
+ name, value, len, 0);
+ kfree(name);
+ kfree(value);
+ return err;
+}
+
struct xattr_handler ext3_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.list = ext3_xattr_security_list,
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index e5ae1b720dde..895049b2ac9c 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -30,6 +30,29 @@ static inline loff_t fat_make_i_pos(struct super_block *sb,
| (de - (struct msdos_dir_entry *)bh->b_data);
}
+static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
+ sector_t phys)
+{
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ int sec;
+
+ /* This is not a first sector of cluster, or sec_per_clus == 1 */
+ if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1)
+ return;
+ /* root dir of FAT12/FAT16 */
+ if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
+ return;
+
+ bh = sb_getblk(sb, phys);
+ if (bh && !buffer_uptodate(bh)) {
+ for (sec = 0; sec < sbi->sec_per_clus; sec++)
+ sb_breadahead(sb, phys + sec);
+ }
+ brelse(bh);
+}
+
/* Returns the inode number of the directory entry at offset pos. If bh is
non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
returned in bh.
@@ -58,6 +81,8 @@ next:
if (err || !phys)
return -1; /* beyond EOF or error */
+ fat_dir_readahead(dir, iblock, phys);
+
*bh = sb_bread(sb, phys);
if (*bh == NULL) {
printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
@@ -635,8 +660,7 @@ RecEnd:
EODir:
filp->f_pos = cpos;
FillFailed:
- if (bh)
- brelse(bh);
+ brelse(bh);
if (unicode)
free_page((unsigned long)unicode);
out:
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 96ae85b67eba..a7cbe68e2259 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -335,6 +335,8 @@ EXPORT_SYMBOL(fat_build_inode);
static void fat_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
+
if (!is_bad_inode(inode)) {
inode->i_size = 0;
fat_truncate(inode);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 6fbc9d8fcc36..863b46e0d78a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -16,6 +16,7 @@
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/signal.h>
+#include <linux/rcupdate.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
@@ -24,21 +25,25 @@
void fastcall set_close_on_exec(unsigned int fd, int flag)
{
struct files_struct *files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
if (flag)
- FD_SET(fd, files->close_on_exec);
+ FD_SET(fd, fdt->close_on_exec);
else
- FD_CLR(fd, files->close_on_exec);
+ FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
}
static inline int get_close_on_exec(unsigned int fd)
{
struct files_struct *files = current->files;
+ struct fdtable *fdt;
int res;
- spin_lock(&files->file_lock);
- res = FD_ISSET(fd, files->close_on_exec);
- spin_unlock(&files->file_lock);
+ rcu_read_lock();
+ fdt = files_fdtable(files);
+ res = FD_ISSET(fd, fdt->close_on_exec);
+ rcu_read_unlock();
return res;
}
@@ -54,24 +59,26 @@ static int locate_fd(struct files_struct *files,
unsigned int newfd;
unsigned int start;
int error;
+ struct fdtable *fdt;
error = -EINVAL;
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
repeat:
+ fdt = files_fdtable(files);
/*
* Someone might have closed fd's in the range
- * orig_start..files->next_fd
+ * orig_start..fdt->next_fd
*/
start = orig_start;
- if (start < files->next_fd)
- start = files->next_fd;
+ if (start < fdt->next_fd)
+ start = fdt->next_fd;
newfd = start;
- if (start < files->max_fdset) {
- newfd = find_next_zero_bit(files->open_fds->fds_bits,
- files->max_fdset, start);
+ if (start < fdt->max_fdset) {
+ newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
+ fdt->max_fdset, start);
}
error = -EMFILE;
@@ -89,9 +96,15 @@ repeat:
if (error)
goto repeat;
- if (start <= files->next_fd)
- files->next_fd = newfd + 1;
-
+ /*
+ * We reacquired files_lock, so we are safe as long as
+ * we reacquire the fdtable pointer and use it while holding
+ * the lock, no one can free it during that time.
+ */
+ fdt = files_fdtable(files);
+ if (start <= fdt->next_fd)
+ fdt->next_fd = newfd + 1;
+
error = newfd;
out:
@@ -101,13 +114,16 @@ out:
static int dupfd(struct file *file, unsigned int start)
{
struct files_struct * files = current->files;
+ struct fdtable *fdt;
int fd;
spin_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
- FD_SET(fd, files->open_fds);
- FD_CLR(fd, files->close_on_exec);
+ /* locate_fd() may have expanded fdtable, load the ptr */
+ fdt = files_fdtable(files);
+ FD_SET(fd, fdt->open_fds);
+ FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
fd_install(fd, file);
} else {
@@ -123,6 +139,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
int err = -EBADF;
struct file * file, *tofree;
struct files_struct * files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
if (!(file = fcheck(oldfd)))
@@ -148,13 +165,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
/* Yes. It's a race. In user space. Nothing sane to do */
err = -EBUSY;
- tofree = files->fd[newfd];
- if (!tofree && FD_ISSET(newfd, files->open_fds))
+ fdt = files_fdtable(files);
+ tofree = fdt->fd[newfd];
+ if (!tofree && FD_ISSET(newfd, fdt->open_fds))
goto out_fput;
- files->fd[newfd] = file;
- FD_SET(newfd, files->open_fds);
- FD_CLR(newfd, files->close_on_exec);
+ rcu_assign_pointer(fdt->fd[newfd], file);
+ FD_SET(newfd, fdt->open_fds);
+ FD_CLR(newfd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
if (tofree)
diff --git a/fs/file.c b/fs/file.c
index 92b5f25985d2..2127a7b9dc3a 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -13,6 +13,25 @@
#include <linux/vmalloc.h>
#include <linux/file.h>
#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/workqueue.h>
+
+struct fdtable_defer {
+ spinlock_t lock;
+ struct work_struct wq;
+ struct timer_list timer;
+ struct fdtable *next;
+};
+
+/*
+ * We use this list to defer free fdtables that have vmalloced
+ * sets/arrays. By keeping a per-cpu list, we avoid having to embed
+ * the work_struct in fdtable itself which avoids a 64 byte (i386) increase in
+ * this per-task structure.
+ */
+static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
/*
@@ -48,82 +67,143 @@ void free_fd_array(struct file **array, int num)
vfree(array);
}
-/*
- * Expand the fd array in the files_struct. Called with the files
- * spinlock held for write.
- */
+static void __free_fdtable(struct fdtable *fdt)
+{
+ int fdset_size, fdarray_size;
-static int expand_fd_array(struct files_struct *files, int nr)
- __releases(files->file_lock)
- __acquires(files->file_lock)
+ fdset_size = fdt->max_fdset / 8;
+ fdarray_size = fdt->max_fds * sizeof(struct file *);
+ free_fdset(fdt->open_fds, fdset_size);
+ free_fdset(fdt->close_on_exec, fdset_size);
+ free_fd_array(fdt->fd, fdarray_size);
+ kfree(fdt);
+}
+
+static void fdtable_timer(unsigned long data)
{
- struct file **new_fds;
- int error, nfds;
+ struct fdtable_defer *fddef = (struct fdtable_defer *)data;
-
- error = -EMFILE;
- if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
+ spin_lock(&fddef->lock);
+ /*
+ * If someone already emptied the queue return.
+ */
+ if (!fddef->next)
goto out;
+ if (!schedule_work(&fddef->wq))
+ mod_timer(&fddef->timer, 5);
+out:
+ spin_unlock(&fddef->lock);
+}
- nfds = files->max_fds;
- spin_unlock(&files->file_lock);
+static void free_fdtable_work(struct fdtable_defer *f)
+{
+ struct fdtable *fdt;
- /*
- * Expand to the max in easy steps, and keep expanding it until
- * we have enough for the requested fd array size.
- */
+ spin_lock_bh(&f->lock);
+ fdt = f->next;
+ f->next = NULL;
+ spin_unlock_bh(&f->lock);
+ while(fdt) {
+ struct fdtable *next = fdt->next;
+ __free_fdtable(fdt);
+ fdt = next;
+ }
+}
- do {
-#if NR_OPEN_DEFAULT < 256
- if (nfds < 256)
- nfds = 256;
- else
-#endif
- if (nfds < (PAGE_SIZE / sizeof(struct file *)))
- nfds = PAGE_SIZE / sizeof(struct file *);
- else {
- nfds = nfds * 2;
- if (nfds > NR_OPEN)
- nfds = NR_OPEN;
- }
- } while (nfds <= nr);
+static void free_fdtable_rcu(struct rcu_head *rcu)
+{
+ struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
+ int fdset_size, fdarray_size;
+ struct fdtable_defer *fddef;
- error = -ENOMEM;
- new_fds = alloc_fd_array(nfds);
- spin_lock(&files->file_lock);
- if (!new_fds)
- goto out;
+ BUG_ON(!fdt);
+ fdset_size = fdt->max_fdset / 8;
+ fdarray_size = fdt->max_fds * sizeof(struct file *);
- /* Copy the existing array and install the new pointer */
-
- if (nfds > files->max_fds) {
- struct file **old_fds;
- int i;
-
- old_fds = xchg(&files->fd, new_fds);
- i = xchg(&files->max_fds, nfds);
-
- /* Don't copy/clear the array if we are creating a new
- fd array for fork() */
- if (i) {
- memcpy(new_fds, old_fds, i * sizeof(struct file *));
- /* clear the remainder of the array */
- memset(&new_fds[i], 0,
- (nfds-i) * sizeof(struct file *));
-
- spin_unlock(&files->file_lock);
- free_fd_array(old_fds, i);
- spin_lock(&files->file_lock);
- }
+ if (fdt->free_files) {
+ /*
+ * The this fdtable was embedded in the files structure
+ * and the files structure itself was getting destroyed.
+ * It is now safe to free the files structure.
+ */
+ kmem_cache_free(files_cachep, fdt->free_files);
+ return;
+ }
+ if (fdt->max_fdset <= __FD_SETSIZE && fdt->max_fds <= NR_OPEN_DEFAULT) {
+ /*
+ * The fdtable was embedded
+ */
+ return;
+ }
+ if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
+ kfree(fdt->open_fds);
+ kfree(fdt->close_on_exec);
+ kfree(fdt->fd);
+ kfree(fdt);
} else {
- /* Somebody expanded the array while we slept ... */
- spin_unlock(&files->file_lock);
- free_fd_array(new_fds, nfds);
- spin_lock(&files->file_lock);
+ fddef = &get_cpu_var(fdtable_defer_list);
+ spin_lock(&fddef->lock);
+ fdt->next = fddef->next;
+ fddef->next = fdt;
+ /*
+ * vmallocs are handled from the workqueue context.
+ * If the per-cpu workqueue is running, then we
+ * defer work scheduling through a timer.
+ */
+ if (!schedule_work(&fddef->wq))
+ mod_timer(&fddef->timer, 5);
+ spin_unlock(&fddef->lock);
+ put_cpu_var(fdtable_defer_list);
}
- error = 0;
-out:
- return error;
+}
+
+void free_fdtable(struct fdtable *fdt)
+{
+ if (fdt->free_files || fdt->max_fdset > __FD_SETSIZE ||
+ fdt->max_fds > NR_OPEN_DEFAULT)
+ call_rcu(&fdt->rcu, free_fdtable_rcu);
+}
+
+/*
+ * Expand the fdset in the files_struct. Called with the files spinlock
+ * held for write.
+ */
+static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt)
+{
+ int i;
+ int count;
+
+ BUG_ON(nfdt->max_fdset < fdt->max_fdset);
+ BUG_ON(nfdt->max_fds < fdt->max_fds);
+ /* Copy the existing tables and install the new pointers */
+
+ i = fdt->max_fdset / (sizeof(unsigned long) * 8);
+ count = (nfdt->max_fdset - fdt->max_fdset) / 8;
+
+ /*
+ * Don't copy the entire array if the current fdset is
+ * not yet initialised.
+ */
+ if (i) {
+ memcpy (nfdt->open_fds, fdt->open_fds,
+ fdt->max_fdset/8);
+ memcpy (nfdt->close_on_exec, fdt->close_on_exec,
+ fdt->max_fdset/8);
+ memset (&nfdt->open_fds->fds_bits[i], 0, count);
+ memset (&nfdt->close_on_exec->fds_bits[i], 0, count);
+ }
+
+ /* Don't copy/clear the array if we are creating a new
+ fd array for fork() */
+ if (fdt->max_fds) {
+ memcpy(nfdt->fd, fdt->fd,
+ fdt->max_fds * sizeof(struct file *));
+ /* clear the remainder of the array */
+ memset(&nfdt->fd[fdt->max_fds], 0,
+ (nfdt->max_fds - fdt->max_fds) *
+ sizeof(struct file *));
+ }
+ nfdt->next_fd = fdt->next_fd;
}
/*
@@ -154,26 +234,21 @@ void free_fdset(fd_set *array, int num)
vfree(array);
}
-/*
- * Expand the fdset in the files_struct. Called with the files spinlock
- * held for write.
- */
-static int expand_fdset(struct files_struct *files, int nr)
- __releases(file->file_lock)
- __acquires(file->file_lock)
+static struct fdtable *alloc_fdtable(int nr)
{
- fd_set *new_openset = NULL, *new_execset = NULL;
- int error, nfds = 0;
-
- error = -EMFILE;
- if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN)
- goto out;
+ struct fdtable *fdt = NULL;
+ int nfds = 0;
+ fd_set *new_openset = NULL, *new_execset = NULL;
+ struct file **new_fds;
- nfds = files->max_fdset;
- spin_unlock(&files->file_lock);
+ fdt = kmalloc(sizeof(*fdt), GFP_KERNEL);
+ if (!fdt)
+ goto out;
+ memset(fdt, 0, sizeof(*fdt));
- /* Expand to the max in easy steps */
- do {
+ nfds = __FD_SETSIZE;
+ /* Expand to the max in easy steps */
+ do {
if (nfds < (PAGE_SIZE * 8))
nfds = PAGE_SIZE * 8;
else {
@@ -183,49 +258,88 @@ static int expand_fdset(struct files_struct *files, int nr)
}
} while (nfds <= nr);
- error = -ENOMEM;
- new_openset = alloc_fdset(nfds);
- new_execset = alloc_fdset(nfds);
- spin_lock(&files->file_lock);
- if (!new_openset || !new_execset)
+ new_openset = alloc_fdset(nfds);
+ new_execset = alloc_fdset(nfds);
+ if (!new_openset || !new_execset)
+ goto out;
+ fdt->open_fds = new_openset;
+ fdt->close_on_exec = new_execset;
+ fdt->max_fdset = nfds;
+
+ nfds = NR_OPEN_DEFAULT;
+ /*
+ * Expand to the max in easy steps, and keep expanding it until
+ * we have enough for the requested fd array size.
+ */
+ do {
+#if NR_OPEN_DEFAULT < 256
+ if (nfds < 256)
+ nfds = 256;
+ else
+#endif
+ if (nfds < (PAGE_SIZE / sizeof(struct file *)))
+ nfds = PAGE_SIZE / sizeof(struct file *);
+ else {
+ nfds = nfds * 2;
+ if (nfds > NR_OPEN)
+ nfds = NR_OPEN;
+ }
+ } while (nfds <= nr);
+ new_fds = alloc_fd_array(nfds);
+ if (!new_fds)
+ goto out;
+ fdt->fd = new_fds;
+ fdt->max_fds = nfds;
+ fdt->free_files = NULL;
+ return fdt;
+out:
+ if (new_openset)
+ free_fdset(new_openset, nfds);
+ if (new_execset)
+ free_fdset(new_execset, nfds);
+ kfree(fdt);
+ return NULL;
+}
+
+/*
+ * Expands the file descriptor table - it will allocate a new fdtable and
+ * both fd array and fdset. It is expected to be called with the
+ * files_lock held.
+ */
+static int expand_fdtable(struct files_struct *files, int nr)
+ __releases(files->file_lock)
+ __acquires(files->file_lock)
+{
+ int error = 0;
+ struct fdtable *fdt;
+ struct fdtable *nfdt = NULL;
+
+ spin_unlock(&files->file_lock);
+ nfdt = alloc_fdtable(nr);
+ if (!nfdt) {
+ error = -ENOMEM;
+ spin_lock(&files->file_lock);
goto out;
+ }
- error = 0;
-
- /* Copy the existing tables and install the new pointers */
- if (nfds > files->max_fdset) {
- int i = files->max_fdset / (sizeof(unsigned long) * 8);
- int count = (nfds - files->max_fdset) / 8;
-
- /*
- * Don't copy the entire array if the current fdset is
- * not yet initialised.
- */
- if (i) {
- memcpy (new_openset, files->open_fds, files->max_fdset/8);
- memcpy (new_execset, files->close_on_exec, files->max_fdset/8);
- memset (&new_openset->fds_bits[i], 0, count);
- memset (&new_execset->fds_bits[i], 0, count);
- }
-
- nfds = xchg(&files->max_fdset, nfds);
- new_openset = xchg(&files->open_fds, new_openset);
- new_execset = xchg(&files->close_on_exec, new_execset);
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+ /*
+ * Check again since another task may have expanded the
+ * fd table while we dropped the lock
+ */
+ if (nr >= fdt->max_fds || nr >= fdt->max_fdset) {
+ copy_fdtable(nfdt, fdt);
+ } else {
+ /* Somebody expanded while we dropped file_lock */
spin_unlock(&files->file_lock);
- free_fdset (new_openset, nfds);
- free_fdset (new_execset, nfds);
+ __free_fdtable(nfdt);
spin_lock(&files->file_lock);
- return 0;
- }
- /* Somebody expanded the array while we slept ... */
-
+ goto out;
+ }
+ rcu_assign_pointer(files->fdt, nfdt);
+ free_fdtable(fdt);
out:
- spin_unlock(&files->file_lock);
- if (new_openset)
- free_fdset(new_openset, nfds);
- if (new_execset)
- free_fdset(new_execset, nfds);
- spin_lock(&files->file_lock);
return error;
}
@@ -237,18 +351,39 @@ out:
int expand_files(struct files_struct *files, int nr)
{
int err, expand = 0;
+ struct fdtable *fdt;
- if (nr >= files->max_fdset) {
- expand = 1;
- if ((err = expand_fdset(files, nr)))
+ fdt = files_fdtable(files);
+ if (nr >= fdt->max_fdset || nr >= fdt->max_fds) {
+ if (fdt->max_fdset >= NR_OPEN ||
+ fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) {
+ err = -EMFILE;
goto out;
- }
- if (nr >= files->max_fds) {
+ }
expand = 1;
- if ((err = expand_fd_array(files, nr)))
+ if ((err = expand_fdtable(files, nr)))
goto out;
}
err = expand;
out:
return err;
}
+
+static void __devinit fdtable_defer_list_init(int cpu)
+{
+ struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
+ spin_lock_init(&fddef->lock);
+ INIT_WORK(&fddef->wq, (void (*)(void *))free_fdtable_work, fddef);
+ init_timer(&fddef->timer);
+ fddef->timer.data = (unsigned long)fddef;
+ fddef->timer.function = fdtable_timer;
+ fddef->next = NULL;
+}
+
+void __init files_defer_init(void)
+{
+ int i;
+ /* Really early - can't use for_each_cpu */
+ for (i = 0; i < NR_CPUS; i++)
+ fdtable_defer_list_init(i);
+}
diff --git a/fs/file_table.c b/fs/file_table.c
index 1d3de78e6bc9..86ec8ae985b4 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -14,6 +14,7 @@
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/eventpoll.h>
+#include <linux/rcupdate.h>
#include <linux/mount.h>
#include <linux/cdev.h>
#include <linux/fsnotify.h>
@@ -53,11 +54,17 @@ void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
spin_unlock_irqrestore(&filp_count_lock, flags);
}
-static inline void file_free(struct file *f)
+static inline void file_free_rcu(struct rcu_head *head)
{
+ struct file *f = container_of(head, struct file, f_rcuhead);
kmem_cache_free(filp_cachep, f);
}
+static inline void file_free(struct file *f)
+{
+ call_rcu(&f->f_rcuhead, file_free_rcu);
+}
+
/* Find an unused file structure and return a pointer to it.
* Returns NULL, if there are no more free file structures or
* we run out of memory.
@@ -89,7 +96,6 @@ struct file *get_empty_filp(void)
rwlock_init(&f->f_owner.lock);
/* f->f_version: 0 */
INIT_LIST_HEAD(&f->f_list);
- f->f_maxcount = INT_MAX;
return f;
over:
@@ -111,7 +117,7 @@ EXPORT_SYMBOL(get_empty_filp);
void fastcall fput(struct file *file)
{
- if (atomic_dec_and_test(&file->f_count))
+ if (rcuref_dec_and_test(&file->f_count))
__fput(file);
}
@@ -157,11 +163,17 @@ struct file fastcall *fget(unsigned int fd)
struct file *file;
struct files_struct *files = current->files;
- spin_lock(&files->file_lock);
+ rcu_read_lock();
file = fcheck_files(files, fd);
- if (file)
- get_file(file);
- spin_unlock(&files->file_lock);
+ if (file) {
+ if (!rcuref_inc_lf(&file->f_count)) {
+ /* File object ref couldn't be taken */
+ rcu_read_unlock();
+ return NULL;
+ }
+ }
+ rcu_read_unlock();
+
return file;
}
@@ -183,21 +195,25 @@ struct file fastcall *fget_light(unsigned int fd, int *fput_needed)
if (likely((atomic_read(&files->count) == 1))) {
file = fcheck_files(files, fd);
} else {
- spin_lock(&files->file_lock);
+ rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
- get_file(file);
- *fput_needed = 1;
+ if (rcuref_inc_lf(&file->f_count))
+ *fput_needed = 1;
+ else
+ /* Didn't get the reference, someone's freed */
+ file = NULL;
}
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
}
+
return file;
}
void put_filp(struct file *file)
{
- if (atomic_dec_and_test(&file->f_count)) {
+ if (rcuref_dec_and_test(&file->f_count)) {
security_file_free(file);
file_kill(file);
file_free(file);
@@ -258,4 +274,5 @@ void __init files_init(unsigned long mempages)
files_stat.max_files = n;
if (files_stat.max_files < NR_FILE)
files_stat.max_files = NR_FILE;
+ files_defer_init();
}
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 27f66d3e8a04..6aa6fbe4f8ee 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -155,7 +155,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
sbp->s_flags |= MS_RDONLY;
- infp = kcalloc(1, sizeof(*infp), GFP_KERNEL);
+ infp = kzalloc(sizeof(*infp), GFP_KERNEL);
if (!infp) {
printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
return -ENOMEM;
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
new file mode 100644
index 000000000000..c3e1f760cac9
--- /dev/null
+++ b/fs/fuse/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the FUSE filesystem.
+#
+
+obj-$(CONFIG_FUSE_FS) += fuse.o
+
+fuse-objs := dev.o dir.o file.o inode.o
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
new file mode 100644
index 000000000000..d4c869c6d01b
--- /dev/null
+++ b/fs/fuse/dev.c
@@ -0,0 +1,877 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/uio.h>
+#include <linux/miscdevice.h>
+#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+MODULE_ALIAS_MISCDEV(FUSE_MINOR);
+
+static kmem_cache_t *fuse_req_cachep;
+
+static inline struct fuse_conn *fuse_get_conn(struct file *file)
+{
+ struct fuse_conn *fc;
+ spin_lock(&fuse_lock);
+ fc = file->private_data;
+ if (fc && !fc->mounted)
+ fc = NULL;
+ spin_unlock(&fuse_lock);
+ return fc;
+}
+
+static inline void fuse_request_init(struct fuse_req *req)
+{
+ memset(req, 0, sizeof(*req));
+ INIT_LIST_HEAD(&req->list);
+ init_waitqueue_head(&req->waitq);
+ atomic_set(&req->count, 1);
+}
+
+struct fuse_req *fuse_request_alloc(void)
+{
+ struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL);
+ if (req)
+ fuse_request_init(req);
+ return req;
+}
+
+void fuse_request_free(struct fuse_req *req)
+{
+ kmem_cache_free(fuse_req_cachep, req);
+}
+
+static inline void block_sigs(sigset_t *oldset)
+{
+ sigset_t mask;
+
+ siginitsetinv(&mask, sigmask(SIGKILL));
+ sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static inline void restore_sigs(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
+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)
+{
+ atomic_inc(&req->count);
+}
+
+/* Must be called with > 1 refcount */
+static void __fuse_put_request(struct fuse_req *req)
+{
+ BUG_ON(atomic_read(&req->count) < 2);
+ atomic_dec(&req->count);
+}
+
+static struct fuse_req *do_get_request(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;
+
+ block_sigs(&oldset);
+ intr = down_interruptible(&fc->outstanding_sem);
+ restore_sigs(&oldset);
+ return intr ? NULL : do_get_request(fc);
+}
+
+static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+ spin_lock(&fuse_lock);
+ if (req->preallocated)
+ list_add(&req->list, &fc->unused_list);
+ else
+ fuse_request_free(req);
+
+ /* If we are in debt decrease that first */
+ if (fc->outstanding_debt)
+ fc->outstanding_debt--;
+ else
+ up(&fc->outstanding_sem);
+ spin_unlock(&fuse_lock);
+}
+
+void fuse_put_request(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)
+{
+ iput(req->inode);
+ iput(req->inode2);
+ if (req->file)
+ fput(req->file);
+ spin_lock(&fuse_lock);
+ list_del(&req->bg_entry);
+ spin_unlock(&fuse_lock);
+}
+
+/*
+ * This function is called when a request is finished. Either a reply
+ * has arrived or it was interrupted (and not yet sent) or some error
+ * occured during communication with userspace, or the device file was
+ * closed. It decreases the referece count for the request. In case
+ * of a background request the referece to the stored objects are
+ * released. The requester thread is woken up (if still waiting), and
+ * finally the request is either freed or put on the unused_list
+ *
+ * Called with fuse_lock, unlocks it
+ */
+static void request_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+ int putback;
+ req->finished = 1;
+ putback = atomic_dec_and_test(&req->count);
+ spin_unlock(&fuse_lock);
+ if (req->background) {
+ down_read(&fc->sbput_sem);
+ if (fc->mounted)
+ fuse_release_background(req);
+ up_read(&fc->sbput_sem);
+ }
+ wake_up(&req->waitq);
+ if (req->in.h.opcode == FUSE_INIT) {
+ int i;
+
+ if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
+ fc->conn_error = 1;
+
+ /* 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);
+ }
+ if (putback)
+ fuse_putback_request(fc, req);
+}
+
+/*
+ * Unfortunately request interruption not just solves the deadlock
+ * problem, it causes problems too. These stem from the fact, that an
+ * interrupted request is continued to be processed in userspace,
+ * while all the locks and object references (inode and file) held
+ * during the operation are released.
+ *
+ * To release the locks is exactly why there's a need to interrupt the
+ * request, so there's not a lot that can be done about this, except
+ * introduce additional locking in userspace.
+ *
+ * More important is to keep inode and file references until userspace
+ * has replied, otherwise FORGET and RELEASE could be sent while the
+ * inode/file is still used by the filesystem.
+ *
+ * For this reason the concept of "background" request is introduced.
+ * An interrupted request is backgrounded if it has been already sent
+ * to userspace. Backgrounding involves getting an extra reference to
+ * inode(s) or file used in the request, and adding the request to
+ * fc->background list. When a reply is received for a background
+ * request, the object references are released, and the request is
+ * removed from the list. If the filesystem is unmounted while there
+ * are still background requests, the list is walked and references
+ * are released as if a reply was received.
+ *
+ * There's one more use for a background request. The RELEASE message is
+ * always sent as background, since it doesn't return an error or
+ * data.
+ */
+static void background_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+ req->background = 1;
+ list_add(&req->bg_entry, &fc->background);
+ if (req->inode)
+ req->inode = igrab(req->inode);
+ if (req->inode2)
+ req->inode2 = igrab(req->inode2);
+ if (req->file)
+ get_file(req->file);
+}
+
+/* Called with fuse_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);
+ block_sigs(&oldset);
+ wait_event_interruptible(req->waitq, req->finished);
+ restore_sigs(&oldset);
+ spin_lock(&fuse_lock);
+ if (req->finished)
+ return;
+
+ req->out.h.error = -EINTR;
+ req->interrupted = 1;
+ if (req->locked) {
+ /* This is uninterruptible sleep, because data is
+ being copied to/from the buffers of req. During
+ locked state, there mustn't be any filesystem
+ operation (e.g. page fault), since that could lead
+ to deadlock */
+ spin_unlock(&fuse_lock);
+ wait_event(req->waitq, !req->locked);
+ spin_lock(&fuse_lock);
+ }
+ if (!req->sent && !list_empty(&req->list)) {
+ list_del(&req->list);
+ __fuse_put_request(req);
+ } else if (!req->finished && req->sent)
+ background_request(fc, req);
+}
+
+static unsigned len_args(unsigned numargs, struct fuse_arg *args)
+{
+ unsigned nbytes = 0;
+ unsigned i;
+
+ for (i = 0; i < numargs; i++)
+ nbytes += args[i].size;
+
+ return nbytes;
+}
+
+static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+ fc->reqctr++;
+ /* zero is special */
+ if (fc->reqctr == 0)
+ fc->reqctr = 1;
+ 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);
+ wake_up(&fc->waitq);
+}
+
+/*
+ * This can only be interrupted by a SIGKILL
+ */
+void request_send(struct fuse_conn *fc, struct fuse_req *req)
+{
+ req->isreply = 1;
+ spin_lock(&fuse_lock);
+ if (!fc->connected)
+ req->out.h.error = -ENOTCONN;
+ else if (fc->conn_error)
+ req->out.h.error = -ECONNREFUSED;
+ else {
+ queue_request(fc, req);
+ /* acquire extra reference, since request is still needed
+ after request_end() */
+ __fuse_get_request(req);
+
+ request_wait_answer(fc, req);
+ }
+ spin_unlock(&fuse_lock);
+}
+
+static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
+{
+ spin_lock(&fuse_lock);
+ if (fc->connected) {
+ queue_request(fc, req);
+ spin_unlock(&fuse_lock);
+ } else {
+ req->out.h.error = -ENOTCONN;
+ request_end(fc, req);
+ }
+}
+
+void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
+{
+ req->isreply = 0;
+ request_send_nowait(fc, 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);
+}
+
+void fuse_send_init(struct fuse_conn *fc)
+{
+ /* This is called from fuse_read_super() so there's guaranteed
+ to be a request available */
+ struct fuse_req *req = do_get_request(fc);
+ struct fuse_init_in_out *arg = &req->misc.init_in_out;
+ arg->major = FUSE_KERNEL_VERSION;
+ arg->minor = FUSE_KERNEL_MINOR_VERSION;
+ req->in.h.opcode = FUSE_INIT;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(*arg);
+ req->in.args[0].value = arg;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(*arg);
+ req->out.args[0].value = arg;
+ request_send_background(fc, req);
+}
+
+/*
+ * Lock the request. Up to the next unlock_request() there mustn't be
+ * anything that could cause a page-fault. If the request was already
+ * interrupted bail out.
+ */
+static inline int lock_request(struct fuse_req *req)
+{
+ int err = 0;
+ if (req) {
+ spin_lock(&fuse_lock);
+ if (req->interrupted)
+ err = -ENOENT;
+ else
+ req->locked = 1;
+ spin_unlock(&fuse_lock);
+ }
+ return err;
+}
+
+/*
+ * Unlock request. If it was interrupted during being locked, the
+ * requester thread is currently waiting for it to be unlocked, so
+ * wake it up.
+ */
+static inline void unlock_request(struct fuse_req *req)
+{
+ if (req) {
+ spin_lock(&fuse_lock);
+ req->locked = 0;
+ if (req->interrupted)
+ wake_up(&req->waitq);
+ spin_unlock(&fuse_lock);
+ }
+}
+
+struct fuse_copy_state {
+ int write;
+ struct fuse_req *req;
+ const struct iovec *iov;
+ unsigned long nr_segs;
+ unsigned long seglen;
+ unsigned long addr;
+ struct page *pg;
+ void *mapaddr;
+ void *buf;
+ 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)
+{
+ memset(cs, 0, sizeof(*cs));
+ cs->write = write;
+ cs->req = req;
+ cs->iov = iov;
+ cs->nr_segs = nr_segs;
+}
+
+/* Unmap and put previous page of userspace buffer */
+static inline void fuse_copy_finish(struct fuse_copy_state *cs)
+{
+ if (cs->mapaddr) {
+ kunmap_atomic(cs->mapaddr, KM_USER0);
+ if (cs->write) {
+ flush_dcache_page(cs->pg);
+ set_page_dirty_lock(cs->pg);
+ }
+ put_page(cs->pg);
+ cs->mapaddr = NULL;
+ }
+}
+
+/*
+ * Get another pagefull of userspace buffer, and map it to kernel
+ * address space, and lock request
+ */
+static int fuse_copy_fill(struct fuse_copy_state *cs)
+{
+ unsigned long offset;
+ int err;
+
+ unlock_request(cs->req);
+ fuse_copy_finish(cs);
+ if (!cs->seglen) {
+ BUG_ON(!cs->nr_segs);
+ cs->seglen = cs->iov[0].iov_len;
+ cs->addr = (unsigned long) cs->iov[0].iov_base;
+ cs->iov ++;
+ cs->nr_segs --;
+ }
+ down_read(&current->mm->mmap_sem);
+ err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
+ &cs->pg, NULL);
+ up_read(&current->mm->mmap_sem);
+ if (err < 0)
+ return err;
+ BUG_ON(err != 1);
+ offset = cs->addr % PAGE_SIZE;
+ cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
+ cs->buf = cs->mapaddr + offset;
+ cs->len = min(PAGE_SIZE - offset, cs->seglen);
+ cs->seglen -= cs->len;
+ cs->addr += cs->len;
+
+ return lock_request(cs->req);
+}
+
+/* Do as much copy to/from userspace buffer as we can */
+static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val,
+ unsigned *size)
+{
+ unsigned ncpy = min(*size, cs->len);
+ if (val) {
+ if (cs->write)
+ memcpy(cs->buf, *val, ncpy);
+ else
+ memcpy(*val, cs->buf, ncpy);
+ *val += ncpy;
+ }
+ *size -= ncpy;
+ cs->len -= ncpy;
+ cs->buf += ncpy;
+ return ncpy;
+}
+
+/*
+ * Copy a page in the request to/from the userspace buffer. Must be
+ * done atomically
+ */
+static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page,
+ unsigned offset, unsigned count, int zeroing)
+{
+ if (page && zeroing && count < PAGE_SIZE) {
+ void *mapaddr = kmap_atomic(page, KM_USER1);
+ memset(mapaddr, 0, PAGE_SIZE);
+ kunmap_atomic(mapaddr, KM_USER1);
+ }
+ while (count) {
+ int err;
+ if (!cs->len && (err = fuse_copy_fill(cs)))
+ return err;
+ if (page) {
+ void *mapaddr = kmap_atomic(page, KM_USER1);
+ void *buf = mapaddr + offset;
+ offset += fuse_copy_do(cs, &buf, &count);
+ kunmap_atomic(mapaddr, KM_USER1);
+ } else
+ offset += fuse_copy_do(cs, NULL, &count);
+ }
+ if (page && !cs->write)
+ flush_dcache_page(page);
+ return 0;
+}
+
+/* Copy pages in the request to/from userspace buffer */
+static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
+ int zeroing)
+{
+ unsigned i;
+ struct fuse_req *req = cs->req;
+ unsigned offset = req->page_offset;
+ unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+
+ for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
+ struct page *page = req->pages[i];
+ int err = fuse_copy_page(cs, page, offset, count, zeroing);
+ if (err)
+ return err;
+
+ nbytes -= count;
+ count = min(nbytes, (unsigned) PAGE_SIZE);
+ offset = 0;
+ }
+ return 0;
+}
+
+/* Copy a single argument in the request to/from userspace buffer */
+static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
+{
+ while (size) {
+ int err;
+ if (!cs->len && (err = fuse_copy_fill(cs)))
+ return err;
+ fuse_copy_do(cs, &val, &size);
+ }
+ return 0;
+}
+
+/* Copy request arguments to/from userspace buffer */
+static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
+ unsigned argpages, struct fuse_arg *args,
+ int zeroing)
+{
+ int err = 0;
+ unsigned i;
+
+ for (i = 0; !err && i < numargs; i++) {
+ struct fuse_arg *arg = &args[i];
+ if (i == numargs - 1 && argpages)
+ err = fuse_copy_pages(cs, arg->size, zeroing);
+ else
+ err = fuse_copy_one(cs, arg->value, arg->size);
+ }
+ return err;
+}
+
+/* Wait until a request is available on the pending list */
+static void request_wait(struct fuse_conn *fc)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue_exclusive(&fc->waitq, &wait);
+ while (fc->mounted && list_empty(&fc->pending)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current))
+ break;
+
+ spin_unlock(&fuse_lock);
+ schedule();
+ spin_lock(&fuse_lock);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&fc->waitq, &wait);
+}
+
+/*
+ * Read a single request into the userspace filesystem's buffer. This
+ * function waits until a request is available, then removes it from
+ * the pending list and copies request data to userspace buffer. If
+ * no reply is needed (FORGET) or request has been interrupted or
+ * there was an error during the copying then it's finished by calling
+ * request_end(). Otherwise add it to the processing list, and set
+ * the 'sent' flag.
+ */
+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;
+
+ spin_lock(&fuse_lock);
+ fc = file->private_data;
+ err = -EPERM;
+ if (!fc)
+ goto err_unlock;
+ request_wait(fc);
+ err = -ENODEV;
+ if (!fc->mounted)
+ goto err_unlock;
+ err = -ERESTARTSYS;
+ if (list_empty(&fc->pending))
+ goto err_unlock;
+
+ req = list_entry(fc->pending.next, struct fuse_req, list);
+ list_del_init(&req->list);
+ spin_unlock(&fuse_lock);
+
+ in = &req->in;
+ reqsize = req->in.h.len;
+ fuse_copy_init(&cs, 1, req, iov, nr_segs);
+ err = -EINVAL;
+ if (iov_length(iov, nr_segs) >= reqsize) {
+ 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);
+ req->locked = 0;
+ if (!err && req->interrupted)
+ err = -ENOENT;
+ if (err) {
+ if (!req->interrupted)
+ req->out.h.error = -EIO;
+ request_end(fc, req);
+ return err;
+ }
+ if (!req->isreply)
+ request_end(fc, req);
+ else {
+ req->sent = 1;
+ list_add_tail(&req->list, &fc->processing);
+ spin_unlock(&fuse_lock);
+ }
+ return reqsize;
+
+ err_unlock:
+ spin_unlock(&fuse_lock);
+ return err;
+}
+
+static ssize_t fuse_dev_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *off)
+{
+ struct iovec iov;
+ iov.iov_len = nbytes;
+ iov.iov_base = buf;
+ return fuse_dev_readv(file, &iov, 1, off);
+}
+
+/* Look up request on processing list by unique ID */
+static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
+{
+ struct list_head *entry;
+
+ list_for_each(entry, &fc->processing) {
+ struct fuse_req *req;
+ req = list_entry(entry, struct fuse_req, list);
+ if (req->in.h.unique == unique)
+ return req;
+ }
+ return NULL;
+}
+
+static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
+ unsigned nbytes)
+{
+ unsigned reqsize = sizeof(struct fuse_out_header);
+
+ if (out->h.error)
+ return nbytes != reqsize ? -EINVAL : 0;
+
+ reqsize += len_args(out->numargs, out->args);
+
+ if (reqsize < nbytes || (reqsize > nbytes && !out->argvar))
+ return -EINVAL;
+ else if (reqsize > nbytes) {
+ struct fuse_arg *lastarg = &out->args[out->numargs-1];
+ unsigned diffsize = reqsize - nbytes;
+ if (diffsize > lastarg->size)
+ return -EINVAL;
+ lastarg->size -= diffsize;
+ }
+ return fuse_copy_args(cs, out->numargs, out->argpages, out->args,
+ out->page_zeroing);
+}
+
+/*
+ * Write a single reply to a request. First the header is copied from
+ * the write buffer. The request is then searched on the processing
+ * list by the unique ID found in the header. If found, then remove
+ * it from the list and copy the rest of the buffer to the request.
+ * The request is finished by calling request_end()
+ */
+static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *off)
+{
+ int err;
+ unsigned nbytes = iov_length(iov, nr_segs);
+ struct fuse_req *req;
+ struct fuse_out_header oh;
+ struct fuse_copy_state cs;
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+ return -ENODEV;
+
+ fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
+ if (nbytes < sizeof(struct fuse_out_header))
+ return -EINVAL;
+
+ err = fuse_copy_one(&cs, &oh, sizeof(oh));
+ if (err)
+ goto err_finish;
+ err = -EINVAL;
+ if (!oh.unique || oh.error <= -1000 || oh.error > 0 ||
+ oh.len != nbytes)
+ goto err_finish;
+
+ spin_lock(&fuse_lock);
+ req = request_find(fc, oh.unique);
+ err = -EINVAL;
+ if (!req)
+ goto err_unlock;
+
+ list_del_init(&req->list);
+ if (req->interrupted) {
+ request_end(fc, req);
+ fuse_copy_finish(&cs);
+ return -ENOENT;
+ }
+ req->out.h = oh;
+ req->locked = 1;
+ cs.req = req;
+ spin_unlock(&fuse_lock);
+
+ err = copy_out_args(&cs, &req->out, nbytes);
+ fuse_copy_finish(&cs);
+
+ spin_lock(&fuse_lock);
+ req->locked = 0;
+ if (!err) {
+ if (req->interrupted)
+ err = -ENOENT;
+ } else if (!req->interrupted)
+ req->out.h.error = -EIO;
+ request_end(fc, req);
+
+ return err ? err : nbytes;
+
+ err_unlock:
+ spin_unlock(&fuse_lock);
+ err_finish:
+ fuse_copy_finish(&cs);
+ return err;
+}
+
+static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *off)
+{
+ struct iovec iov;
+ iov.iov_len = nbytes;
+ iov.iov_base = (char __user *) buf;
+ return fuse_dev_writev(file, &iov, 1, off);
+}
+
+static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
+{
+ struct fuse_conn *fc = fuse_get_conn(file);
+ unsigned mask = POLLOUT | POLLWRNORM;
+
+ if (!fc)
+ return -ENODEV;
+
+ poll_wait(file, &fc->waitq, wait);
+
+ spin_lock(&fuse_lock);
+ if (!list_empty(&fc->pending))
+ mask |= POLLIN | POLLRDNORM;
+ spin_unlock(&fuse_lock);
+
+ return mask;
+}
+
+/* Abort all requests on the given list (pending or processing) */
+static void end_requests(struct fuse_conn *fc, struct list_head *head)
+{
+ while (!list_empty(head)) {
+ struct fuse_req *req;
+ req = list_entry(head->next, struct fuse_req, list);
+ list_del_init(&req->list);
+ req->out.h.error = -ECONNABORTED;
+ request_end(fc, req);
+ spin_lock(&fuse_lock);
+ }
+}
+
+static int fuse_dev_release(struct inode *inode, struct file *file)
+{
+ struct fuse_conn *fc;
+
+ spin_lock(&fuse_lock);
+ fc = file->private_data;
+ if (fc) {
+ fc->connected = 0;
+ end_requests(fc, &fc->pending);
+ end_requests(fc, &fc->processing);
+ fuse_release_conn(fc);
+ }
+ spin_unlock(&fuse_lock);
+ return 0;
+}
+
+struct file_operations fuse_dev_operations = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = fuse_dev_read,
+ .readv = fuse_dev_readv,
+ .write = fuse_dev_write,
+ .writev = fuse_dev_writev,
+ .poll = fuse_dev_poll,
+ .release = fuse_dev_release,
+};
+
+static struct miscdevice fuse_miscdevice = {
+ .minor = FUSE_MINOR,
+ .name = "fuse",
+ .fops = &fuse_dev_operations,
+};
+
+int __init fuse_dev_init(void)
+{
+ int err = -ENOMEM;
+ fuse_req_cachep = kmem_cache_create("fuse_request",
+ sizeof(struct fuse_req),
+ 0, 0, NULL, NULL);
+ if (!fuse_req_cachep)
+ goto out;
+
+ err = misc_register(&fuse_miscdevice);
+ if (err)
+ goto out_cache_clean;
+
+ return 0;
+
+ out_cache_clean:
+ kmem_cache_destroy(fuse_req_cachep);
+ out:
+ return err;
+}
+
+void fuse_dev_cleanup(void)
+{
+ misc_deregister(&fuse_miscdevice);
+ kmem_cache_destroy(fuse_req_cachep);
+}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
new file mode 100644
index 000000000000..e79e49b3eec7
--- /dev/null
+++ b/fs/fuse/dir.c
@@ -0,0 +1,982 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/namei.h>
+
+static inline unsigned long time_to_jiffies(unsigned long sec,
+ unsigned long nsec)
+{
+ struct timespec ts = {sec, nsec};
+ return jiffies + timespec_to_jiffies(&ts);
+}
+
+static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
+ struct dentry *entry,
+ struct fuse_entry_out *outarg)
+{
+ req->in.h.opcode = FUSE_LOOKUP;
+ req->in.h.nodeid = get_node_id(dir);
+ req->inode = dir;
+ req->in.numargs = 1;
+ req->in.args[0].size = entry->d_name.len + 1;
+ req->in.args[0].value = entry->d_name.name;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(struct fuse_entry_out);
+ req->out.args[0].value = outarg;
+}
+
+static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
+{
+ if (!entry->d_inode || is_bad_inode(entry->d_inode))
+ return 0;
+ else if (time_after(jiffies, entry->d_time)) {
+ int err;
+ struct fuse_entry_out outarg;
+ struct inode *inode = entry->d_inode;
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req = fuse_get_request(fc);
+ if (!req)
+ return 0;
+
+ fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err) {
+ if (outarg.nodeid != get_node_id(inode)) {
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
+ return 0;
+ }
+ fi->nlookup ++;
+ }
+ fuse_put_request(fc, req);
+ if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
+ return 0;
+
+ fuse_change_attributes(inode, &outarg.attr);
+ entry->d_time = time_to_jiffies(outarg.entry_valid,
+ outarg.entry_valid_nsec);
+ fi->i_time = time_to_jiffies(outarg.attr_valid,
+ outarg.attr_valid_nsec);
+ }
+ return 1;
+}
+
+static struct dentry_operations fuse_dentry_operations = {
+ .d_revalidate = fuse_dentry_revalidate,
+};
+
+static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
+ struct inode **inodep)
+{
+ int err;
+ struct fuse_entry_out outarg;
+ struct inode *inode = NULL;
+ struct fuse_conn *fc = get_fuse_conn(dir);
+ struct fuse_req *req;
+
+ if (entry->d_name.len > FUSE_NAME_MAX)
+ return -ENAMETOOLONG;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ fuse_lookup_init(req, dir, entry, &outarg);
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err) {
+ inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
+ &outarg.attr);
+ if (!inode) {
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
+ return -ENOMEM;
+ }
+ }
+ fuse_put_request(fc, req);
+ if (err && err != -ENOENT)
+ return err;
+
+ if (inode) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ entry->d_time = time_to_jiffies(outarg.entry_valid,
+ outarg.entry_valid_nsec);
+ fi->i_time = time_to_jiffies(outarg.attr_valid,
+ outarg.attr_valid_nsec);
+ }
+
+ entry->d_op = &fuse_dentry_operations;
+ *inodep = inode;
+ return 0;
+}
+
+void fuse_invalidate_attr(struct inode *inode)
+{
+ get_fuse_inode(inode)->i_time = jiffies - 1;
+}
+
+static void fuse_invalidate_entry(struct dentry *entry)
+{
+ d_invalidate(entry);
+ entry->d_time = jiffies - 1;
+}
+
+static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
+ struct inode *dir, struct dentry *entry,
+ int mode)
+{
+ struct fuse_entry_out outarg;
+ struct inode *inode;
+ struct fuse_inode *fi;
+ int err;
+
+ req->in.h.nodeid = get_node_id(dir);
+ req->inode = dir;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (err) {
+ fuse_put_request(fc, req);
+ return err;
+ }
+ inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
+ &outarg.attr);
+ if (!inode) {
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
+ return -ENOMEM;
+ }
+ fuse_put_request(fc, req);
+
+ /* Don't allow userspace to do really stupid things... */
+ if ((inode->i_mode ^ mode) & S_IFMT) {
+ iput(inode);
+ return -EIO;
+ }
+
+ entry->d_time = time_to_jiffies(outarg.entry_valid,
+ outarg.entry_valid_nsec);
+
+ fi = get_fuse_inode(inode);
+ fi->i_time = time_to_jiffies(outarg.attr_valid,
+ outarg.attr_valid_nsec);
+
+ d_instantiate(entry, inode);
+ fuse_invalidate_attr(dir);
+ return 0;
+}
+
+static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
+ dev_t rdev)
+{
+ 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;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.mode = mode;
+ inarg.rdev = new_encode_dev(rdev);
+ req->in.h.opcode = FUSE_MKNOD;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = entry->d_name.len + 1;
+ req->in.args[1].value = entry->d_name.name;
+ return create_new_entry(fc, req, dir, entry, mode);
+}
+
+static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
+ struct nameidata *nd)
+{
+ return fuse_mknod(dir, entry, mode, 0);
+}
+
+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;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.mode = mode;
+ req->in.h.opcode = FUSE_MKDIR;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = entry->d_name.len + 1;
+ req->in.args[1].value = entry->d_name.name;
+ return create_new_entry(fc, req, dir, entry, S_IFDIR);
+}
+
+static int fuse_symlink(struct inode *dir, struct dentry *entry,
+ const char *link)
+{
+ struct fuse_conn *fc = get_fuse_conn(dir);
+ unsigned len = strlen(link) + 1;
+ struct fuse_req *req;
+
+ if (len > FUSE_SYMLINK_MAX)
+ return -ENAMETOOLONG;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ req->in.h.opcode = FUSE_SYMLINK;
+ req->in.numargs = 2;
+ req->in.args[0].size = entry->d_name.len + 1;
+ req->in.args[0].value = entry->d_name.name;
+ req->in.args[1].size = len;
+ req->in.args[1].value = link;
+ return create_new_entry(fc, req, dir, entry, S_IFLNK);
+}
+
+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;
+
+ req->in.h.opcode = FUSE_UNLINK;
+ req->in.h.nodeid = get_node_id(dir);
+ req->inode = dir;
+ req->in.numargs = 1;
+ req->in.args[0].size = entry->d_name.len + 1;
+ req->in.args[0].value = entry->d_name.name;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err) {
+ struct inode *inode = entry->d_inode;
+
+ /* Set nlink to zero so the inode can be cleared, if
+ the inode does have more links this will be
+ discovered at the next lookup/getattr */
+ inode->i_nlink = 0;
+ fuse_invalidate_attr(inode);
+ fuse_invalidate_attr(dir);
+ } else if (err == -EINTR)
+ fuse_invalidate_entry(entry);
+ return err;
+}
+
+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;
+
+ req->in.h.opcode = FUSE_RMDIR;
+ req->in.h.nodeid = get_node_id(dir);
+ req->inode = dir;
+ req->in.numargs = 1;
+ req->in.args[0].size = entry->d_name.len + 1;
+ req->in.args[0].value = entry->d_name.name;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err) {
+ entry->d_inode->i_nlink = 0;
+ fuse_invalidate_attr(dir);
+ } else if (err == -EINTR)
+ fuse_invalidate_entry(entry);
+ return err;
+}
+
+static int fuse_rename(struct inode *olddir, struct dentry *oldent,
+ struct inode *newdir, struct dentry *newent)
+{
+ 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;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.newdir = get_node_id(newdir);
+ req->in.h.opcode = FUSE_RENAME;
+ req->in.h.nodeid = get_node_id(olddir);
+ req->inode = olddir;
+ req->inode2 = newdir;
+ req->in.numargs = 3;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = oldent->d_name.len + 1;
+ req->in.args[1].value = oldent->d_name.name;
+ req->in.args[2].size = newent->d_name.len + 1;
+ req->in.args[2].value = newent->d_name.name;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err) {
+ fuse_invalidate_attr(olddir);
+ if (olddir != newdir)
+ fuse_invalidate_attr(newdir);
+ } else if (err == -EINTR) {
+ /* If request was interrupted, DEITY only knows if the
+ rename actually took place. If the invalidation
+ fails (e.g. some process has CWD under the renamed
+ directory), then there can be inconsistency between
+ the dcache and the real filesystem. Tough luck. */
+ fuse_invalidate_entry(oldent);
+ if (newent->d_inode)
+ fuse_invalidate_entry(newent);
+ }
+
+ return err;
+}
+
+static int fuse_link(struct dentry *entry, struct inode *newdir,
+ struct dentry *newent)
+{
+ int err;
+ 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;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.oldnodeid = get_node_id(inode);
+ req->in.h.opcode = FUSE_LINK;
+ req->inode2 = inode;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = newent->d_name.len + 1;
+ req->in.args[1].value = newent->d_name.name;
+ err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
+ /* Contrary to "normal" filesystems it can happen that link
+ makes two "logical" inodes point to the same "physical"
+ inode. We invalidate the attributes of the old one, so it
+ will reflect changes in the backing inode (link count,
+ etc.)
+ */
+ if (!err || err == -EINTR)
+ fuse_invalidate_attr(inode);
+ return err;
+}
+
+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;
+
+ req->in.h.opcode = FUSE_GETATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(arg);
+ req->out.args[0].value = &arg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err) {
+ if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
+ make_bad_inode(inode);
+ err = -EIO;
+ } else {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ fuse_change_attributes(inode, &arg.attr);
+ fi->i_time = time_to_jiffies(arg.attr_valid,
+ arg.attr_valid_nsec);
+ }
+ }
+ return err;
+}
+
+/*
+ * Calling into a user-controlled filesystem gives the filesystem
+ * daemon ptrace-like capabilities over the requester process. This
+ * means, that the filesystem daemon is able to record the exact
+ * filesystem operations performed, and can also control the behavior
+ * of the requester process in otherwise impossible ways. For example
+ * it can delay the operation for arbitrary length of time allowing
+ * DoS against the requester.
+ *
+ * For this reason only those processes can call into the filesystem,
+ * for which the owner of the mount has ptrace privilege. This
+ * excludes processes started by other users, suid or sgid processes.
+ */
+static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
+{
+ if (fc->flags & FUSE_ALLOW_OTHER)
+ return 1;
+
+ if (task->euid == fc->user_id &&
+ task->suid == fc->user_id &&
+ task->uid == fc->user_id &&
+ task->egid == fc->group_id &&
+ task->sgid == fc->group_id &&
+ task->gid == fc->group_id)
+ return 1;
+
+ return 0;
+}
+
+static int fuse_revalidate(struct dentry *entry)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+ if (get_node_id(inode) != FUSE_ROOT_ID &&
+ time_before_eq(jiffies, fi->i_time))
+ return 0;
+
+ return fuse_do_getattr(inode);
+}
+
+static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+ else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
+ int err = generic_permission(inode, mask, NULL);
+
+ /* If permission is denied, try to refresh file
+ attributes. This is also needed, because the root
+ node will at first have no permissions */
+ if (err == -EACCES) {
+ err = fuse_do_getattr(inode);
+ if (!err)
+ err = generic_permission(inode, mask, NULL);
+ }
+
+ /* FIXME: Need some mechanism to revoke permissions:
+ currently if the filesystem suddenly changes the
+ file mode, we will not be informed about it, and
+ continue to allow access to the file/directory.
+
+ This is actually not so grave, since the user can
+ simply keep access to the file/directory anyway by
+ keeping it open... */
+
+ return err;
+ } else {
+ int mode = inode->i_mode;
+ if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+ return -EROFS;
+ if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
+ return -EACCES;
+ return 0;
+ }
+}
+
+static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
+ void *dstbuf, filldir_t filldir)
+{
+ while (nbytes >= FUSE_NAME_OFFSET) {
+ struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
+ size_t reclen = FUSE_DIRENT_SIZE(dirent);
+ int over;
+ if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
+ return -EIO;
+ if (reclen > nbytes)
+ break;
+
+ over = filldir(dstbuf, dirent->name, dirent->namelen,
+ file->f_pos, dirent->ino, dirent->type);
+ if (over)
+ break;
+
+ buf += reclen;
+ nbytes -= reclen;
+ file->f_pos = dirent->off;
+ }
+
+ return 0;
+}
+
+static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos,
+ size_t count)
+{
+ return fuse_send_read_common(req, file, inode, pos, count, 1);
+}
+
+static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
+{
+ int err;
+ size_t nbytes;
+ struct page *page;
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ fuse_put_request(fc, req);
+ return -ENOMEM;
+ }
+ req->num_pages = 1;
+ req->pages[0] = page;
+ nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err)
+ err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
+ filldir);
+
+ __free_page(page);
+ fuse_invalidate_attr(inode); /* atime changed */
+ return err;
+}
+
+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);
+ char *link;
+
+ if (!req)
+ return ERR_PTR(-EINTR);
+
+ link = (char *) __get_free_page(GFP_KERNEL);
+ if (!link) {
+ link = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+ req->in.h.opcode = FUSE_READLINK;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->out.argvar = 1;
+ req->out.numargs = 1;
+ req->out.args[0].size = PAGE_SIZE - 1;
+ req->out.args[0].value = link;
+ request_send(fc, req);
+ if (req->out.h.error) {
+ free_page((unsigned long) link);
+ link = ERR_PTR(req->out.h.error);
+ } else
+ link[req->out.args[0].size] = '\0';
+ out:
+ fuse_put_request(fc, req);
+ fuse_invalidate_attr(inode); /* atime changed */
+ return link;
+}
+
+static void free_link(char *link)
+{
+ if (!IS_ERR(link))
+ free_page((unsigned long) link);
+}
+
+static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ nd_set_link(nd, read_link(dentry));
+ return NULL;
+}
+
+static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+{
+ free_link(nd_get_link(nd));
+}
+
+static int fuse_dir_open(struct inode *inode, struct file *file)
+{
+ return fuse_open_common(inode, file, 1);
+}
+
+static int fuse_dir_release(struct inode *inode, struct file *file)
+{
+ return fuse_release_common(inode, file, 1);
+}
+
+static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
+{
+ /* nfsd can call this with no file */
+ return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
+}
+
+static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
+{
+ unsigned ivalid = iattr->ia_valid;
+ unsigned fvalid = 0;
+
+ memset(fattr, 0, sizeof(*fattr));
+
+ if (ivalid & ATTR_MODE)
+ fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
+ if (ivalid & ATTR_UID)
+ fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
+ if (ivalid & ATTR_GID)
+ fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
+ if (ivalid & ATTR_SIZE)
+ fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
+ /* You can only _set_ these together (they may change by themselves) */
+ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
+ fvalid |= FATTR_ATIME | FATTR_MTIME;
+ fattr->atime = iattr->ia_atime.tv_sec;
+ fattr->mtime = iattr->ia_mtime.tv_sec;
+ }
+
+ return fvalid;
+}
+
+static int fuse_setattr(struct dentry *entry, struct iattr *attr)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_req *req;
+ struct fuse_setattr_in inarg;
+ struct fuse_attr_out outarg;
+ int err;
+ int is_truncate = 0;
+
+ if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
+ err = inode_change_ok(inode, attr);
+ if (err)
+ return err;
+ }
+
+ if (attr->ia_valid & ATTR_SIZE) {
+ unsigned long limit;
+ is_truncate = 1;
+ limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
+ send_sig(SIGXFSZ, current, 0);
+ return -EFBIG;
+ }
+ }
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.valid = iattr_to_fattr(attr, &inarg.attr);
+ req->in.h.opcode = FUSE_SETATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err) {
+ if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
+ make_bad_inode(inode);
+ err = -EIO;
+ } else {
+ if (is_truncate) {
+ loff_t origsize = i_size_read(inode);
+ i_size_write(inode, outarg.attr.size);
+ if (origsize > outarg.attr.size)
+ vmtruncate(inode, outarg.attr.size);
+ }
+ fuse_change_attributes(inode, &outarg.attr);
+ fi->i_time = time_to_jiffies(outarg.attr_valid,
+ outarg.attr_valid_nsec);
+ }
+ } else if (err == -EINTR)
+ fuse_invalidate_attr(inode);
+
+ return err;
+}
+
+static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
+ struct kstat *stat)
+{
+ struct inode *inode = entry->d_inode;
+ int err = fuse_revalidate(entry);
+ if (!err)
+ generic_fillattr(inode, stat);
+
+ return err;
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+ struct nameidata *nd)
+{
+ struct inode *inode;
+ int err = fuse_lookup_iget(dir, entry, &inode);
+ if (err)
+ return ERR_PTR(err);
+ if (inode && S_ISDIR(inode->i_mode)) {
+ /* Don't allow creating an alias to a directory */
+ struct dentry *alias = d_find_alias(inode);
+ if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
+ dput(alias);
+ iput(inode);
+ return ERR_PTR(-EIO);
+ }
+ }
+ return d_splice_alias(inode, entry);
+}
+
+static int fuse_setxattr(struct dentry *entry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ struct fuse_setxattr_in inarg;
+ int err;
+
+ if (size > FUSE_XATTR_SIZE_MAX)
+ return -E2BIG;
+
+ if (fc->no_setxattr)
+ return -EOPNOTSUPP;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ inarg.flags = flags;
+ req->in.h.opcode = FUSE_SETXATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 3;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = strlen(name) + 1;
+ req->in.args[1].value = name;
+ req->in.args[2].size = size;
+ req->in.args[2].value = value;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (err == -ENOSYS) {
+ fc->no_setxattr = 1;
+ err = -EOPNOTSUPP;
+ }
+ return err;
+}
+
+static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
+ void *value, size_t size)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ struct fuse_getxattr_in inarg;
+ struct fuse_getxattr_out outarg;
+ ssize_t ret;
+
+ if (fc->no_getxattr)
+ return -EOPNOTSUPP;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ req->in.h.opcode = FUSE_GETXATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = strlen(name) + 1;
+ req->in.args[1].value = name;
+ /* This is really two different operations rolled into one */
+ req->out.numargs = 1;
+ if (size) {
+ req->out.argvar = 1;
+ req->out.args[0].size = size;
+ req->out.args[0].value = value;
+ } else {
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ }
+ request_send(fc, req);
+ ret = req->out.h.error;
+ if (!ret)
+ ret = size ? req->out.args[0].size : outarg.size;
+ else {
+ if (ret == -ENOSYS) {
+ fc->no_getxattr = 1;
+ ret = -EOPNOTSUPP;
+ }
+ }
+ fuse_put_request(fc, req);
+ return ret;
+}
+
+static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ struct fuse_getxattr_in inarg;
+ struct fuse_getxattr_out outarg;
+ ssize_t ret;
+
+ if (fc->no_listxattr)
+ return -EOPNOTSUPP;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ req->in.h.opcode = FUSE_LISTXATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ /* This is really two different operations rolled into one */
+ req->out.numargs = 1;
+ if (size) {
+ req->out.argvar = 1;
+ req->out.args[0].size = size;
+ req->out.args[0].value = list;
+ } else {
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ }
+ request_send(fc, req);
+ ret = req->out.h.error;
+ if (!ret)
+ ret = size ? req->out.args[0].size : outarg.size;
+ else {
+ if (ret == -ENOSYS) {
+ fc->no_listxattr = 1;
+ ret = -EOPNOTSUPP;
+ }
+ }
+ fuse_put_request(fc, req);
+ return ret;
+}
+
+static int fuse_removexattr(struct dentry *entry, const char *name)
+{
+ struct inode *inode = entry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ int err;
+
+ if (fc->no_removexattr)
+ return -EOPNOTSUPP;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ req->in.h.opcode = FUSE_REMOVEXATTR;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = strlen(name) + 1;
+ req->in.args[0].value = name;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (err == -ENOSYS) {
+ fc->no_removexattr = 1;
+ err = -EOPNOTSUPP;
+ }
+ return err;
+}
+
+static struct inode_operations fuse_dir_inode_operations = {
+ .lookup = fuse_lookup,
+ .mkdir = fuse_mkdir,
+ .symlink = fuse_symlink,
+ .unlink = fuse_unlink,
+ .rmdir = fuse_rmdir,
+ .rename = fuse_rename,
+ .link = fuse_link,
+ .setattr = fuse_setattr,
+ .create = fuse_create,
+ .mknod = fuse_mknod,
+ .permission = fuse_permission,
+ .getattr = fuse_getattr,
+ .setxattr = fuse_setxattr,
+ .getxattr = fuse_getxattr,
+ .listxattr = fuse_listxattr,
+ .removexattr = fuse_removexattr,
+};
+
+static struct file_operations fuse_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .readdir = fuse_readdir,
+ .open = fuse_dir_open,
+ .release = fuse_dir_release,
+ .fsync = fuse_dir_fsync,
+};
+
+static struct inode_operations fuse_common_inode_operations = {
+ .setattr = fuse_setattr,
+ .permission = fuse_permission,
+ .getattr = fuse_getattr,
+ .setxattr = fuse_setxattr,
+ .getxattr = fuse_getxattr,
+ .listxattr = fuse_listxattr,
+ .removexattr = fuse_removexattr,
+};
+
+static struct inode_operations fuse_symlink_inode_operations = {
+ .setattr = fuse_setattr,
+ .follow_link = fuse_follow_link,
+ .put_link = fuse_put_link,
+ .readlink = generic_readlink,
+ .getattr = fuse_getattr,
+ .setxattr = fuse_setxattr,
+ .getxattr = fuse_getxattr,
+ .listxattr = fuse_listxattr,
+ .removexattr = fuse_removexattr,
+};
+
+void fuse_init_common(struct inode *inode)
+{
+ inode->i_op = &fuse_common_inode_operations;
+}
+
+void fuse_init_dir(struct inode *inode)
+{
+ inode->i_op = &fuse_dir_inode_operations;
+ inode->i_fop = &fuse_dir_operations;
+}
+
+void fuse_init_symlink(struct inode *inode)
+{
+ inode->i_op = &fuse_symlink_inode_operations;
+}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
new file mode 100644
index 000000000000..6454022b0536
--- /dev/null
+++ b/fs/fuse/file.c
@@ -0,0 +1,555 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+static struct file_operations fuse_direct_io_file_operations;
+
+int fuse_open_common(struct inode *inode, struct file *file, int isdir)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ struct fuse_open_in inarg;
+ struct fuse_open_out outarg;
+ struct fuse_file *ff;
+ int err;
+
+ err = generic_file_open(inode, file);
+ if (err)
+ return err;
+
+ /* If opening the root node, no lookup has been performed on
+ it, so the attributes must be refreshed */
+ if (get_node_id(inode) == FUSE_ROOT_ID) {
+ int err = fuse_do_getattr(inode);
+ if (err)
+ return err;
+ }
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ err = -ENOMEM;
+ ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
+ if (!ff)
+ goto out_put_request;
+
+ ff->release_req = fuse_request_alloc();
+ if (!ff->release_req) {
+ kfree(ff);
+ goto out_put_request;
+ }
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+ req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (err) {
+ fuse_request_free(ff->release_req);
+ kfree(ff);
+ } else {
+ if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO))
+ file->f_op = &fuse_direct_io_file_operations;
+ if (!(outarg.open_flags & FOPEN_KEEP_CACHE))
+ invalidate_inode_pages(inode->i_mapping);
+ ff->fh = outarg.fh;
+ file->private_data = ff;
+ }
+
+ out_put_request:
+ fuse_put_request(fc, req);
+ return err;
+}
+
+int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_req *req = ff->release_req;
+ struct fuse_release_in *inarg = &req->misc.release_in;
+
+ inarg->fh = ff->fh;
+ inarg->flags = file->f_flags & ~O_EXCL;
+ req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(struct fuse_release_in);
+ req->in.args[0].value = inarg;
+ request_send_background(fc, req);
+ kfree(ff);
+
+ /* Return value is ignored by VFS */
+ return 0;
+}
+
+static int fuse_open(struct inode *inode, struct file *file)
+{
+ return fuse_open_common(inode, file, 0);
+}
+
+static int fuse_release(struct inode *inode, struct file *file)
+{
+ return fuse_release_common(inode, file, 0);
+}
+
+static int fuse_flush(struct file *file)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_req *req;
+ struct fuse_flush_in inarg;
+ int err;
+
+ if (fc->no_flush)
+ return 0;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.fh = ff->fh;
+ req->in.h.opcode = FUSE_FLUSH;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->file = file;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (err == -ENOSYS) {
+ fc->no_flush = 1;
+ err = 0;
+ }
+ return err;
+}
+
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+ int isdir)
+{
+ struct inode *inode = de->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_req *req;
+ struct fuse_fsync_in inarg;
+ int err;
+
+ if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
+ return 0;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.fh = ff->fh;
+ inarg.fsync_flags = datasync ? 1 : 0;
+ req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->file = file;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (err == -ENOSYS) {
+ if (isdir)
+ fc->no_fsyncdir = 1;
+ else
+ fc->no_fsync = 1;
+ err = 0;
+ }
+ return err;
+}
+
+static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+{
+ return fuse_fsync_common(file, de, datasync, 0);
+}
+
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count,
+ int isdir)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_read_in inarg;
+
+ memset(&inarg, 0, sizeof(struct fuse_read_in));
+ inarg.fh = ff->fh;
+ inarg.offset = pos;
+ inarg.size = count;
+ req->in.h.opcode = isdir ? FUSE_READDIR : FUSE_READ;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->file = file;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(struct fuse_read_in);
+ req->in.args[0].value = &inarg;
+ req->out.argpages = 1;
+ req->out.argvar = 1;
+ req->out.numargs = 1;
+ req->out.args[0].size = count;
+ request_send(fc, req);
+ return req->out.args[0].size;
+}
+
+static inline size_t fuse_send_read(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos,
+ size_t count)
+{
+ return fuse_send_read_common(req, file, inode, pos, count, 0);
+}
+
+static int fuse_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT;
+ struct fuse_req *req = fuse_get_request(fc);
+ int err = -EINTR;
+ if (!req)
+ goto out;
+
+ req->out.page_zeroing = 1;
+ req->num_pages = 1;
+ req->pages[0] = page;
+ fuse_send_read(req, file, inode, pos, PAGE_CACHE_SIZE);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err)
+ SetPageUptodate(page);
+ fuse_invalidate_attr(inode); /* atime changed */
+ out:
+ unlock_page(page);
+ return err;
+}
+
+static int fuse_send_readpages(struct fuse_req *req, struct file *file,
+ struct inode *inode)
+{
+ loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT;
+ size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+ unsigned i;
+ req->out.page_zeroing = 1;
+ fuse_send_read(req, file, inode, pos, count);
+ for (i = 0; i < req->num_pages; i++) {
+ struct page *page = req->pages[i];
+ if (!req->out.h.error)
+ SetPageUptodate(page);
+ unlock_page(page);
+ }
+ return req->out.h.error;
+}
+
+struct fuse_readpages_data {
+ struct fuse_req *req;
+ struct file *file;
+ struct inode *inode;
+};
+
+static int fuse_readpages_fill(void *_data, struct page *page)
+{
+ struct fuse_readpages_data *data = _data;
+ struct fuse_req *req = data->req;
+ struct inode *inode = data->inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (req->num_pages &&
+ (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
+ (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
+ req->pages[req->num_pages - 1]->index + 1 != page->index)) {
+ int err = fuse_send_readpages(req, data->file, inode);
+ if (err) {
+ unlock_page(page);
+ return err;
+ }
+ fuse_reset_request(req);
+ }
+ req->pages[req->num_pages] = page;
+ req->num_pages ++;
+ return 0;
+}
+
+static int fuse_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages)
+{
+ struct inode *inode = mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_readpages_data data;
+ int err;
+ data.file = file;
+ data.inode = inode;
+ data.req = fuse_get_request(fc);
+ if (!data.req)
+ return -EINTR;
+
+ err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
+ if (!err && data.req->num_pages)
+ err = fuse_send_readpages(data.req, file, inode);
+ fuse_put_request(fc, data.req);
+ fuse_invalidate_attr(inode); /* atime changed */
+ return err;
+}
+
+static size_t fuse_send_write(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ struct fuse_write_in inarg;
+ struct fuse_write_out outarg;
+
+ memset(&inarg, 0, sizeof(struct fuse_write_in));
+ inarg.fh = ff->fh;
+ inarg.offset = pos;
+ inarg.size = count;
+ req->in.h.opcode = FUSE_WRITE;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->file = file;
+ req->in.argpages = 1;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(struct fuse_write_in);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = count;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(struct fuse_write_out);
+ req->out.args[0].value = &outarg;
+ request_send(fc, req);
+ return outarg.size;
+}
+
+static int fuse_prepare_write(struct file *file, struct page *page,
+ unsigned offset, unsigned to)
+{
+ /* No op */
+ return 0;
+}
+
+static int fuse_commit_write(struct file *file, struct page *page,
+ unsigned offset, unsigned to)
+{
+ int err;
+ size_t nres;
+ unsigned count = to - offset;
+ struct inode *inode = page->mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
+ struct fuse_req *req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ req->num_pages = 1;
+ req->pages[0] = page;
+ req->page_offset = offset;
+ nres = fuse_send_write(req, file, inode, pos, count);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (!err && nres != count)
+ err = -EIO;
+ if (!err) {
+ pos += count;
+ if (pos > i_size_read(inode))
+ i_size_write(inode, pos);
+
+ if (offset == 0 && to == PAGE_CACHE_SIZE) {
+ clear_page_dirty(page);
+ SetPageUptodate(page);
+ }
+ }
+ fuse_invalidate_attr(inode);
+ return err;
+}
+
+static void fuse_release_user_pages(struct fuse_req *req, int write)
+{
+ unsigned i;
+
+ for (i = 0; i < req->num_pages; i++) {
+ struct page *page = req->pages[i];
+ if (write)
+ set_page_dirty_lock(page);
+ put_page(page);
+ }
+}
+
+static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+ unsigned nbytes, int write)
+{
+ unsigned long user_addr = (unsigned long) buf;
+ unsigned offset = user_addr & ~PAGE_MASK;
+ int npages;
+
+ /* This doesn't work with nfsd */
+ if (!current->mm)
+ return -EPERM;
+
+ nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+ npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ npages = min(npages, FUSE_MAX_PAGES_PER_REQ);
+ down_read(&current->mm->mmap_sem);
+ npages = get_user_pages(current, current->mm, user_addr, npages, write,
+ 0, req->pages, NULL);
+ up_read(&current->mm->mmap_sem);
+ if (npages < 0)
+ return npages;
+
+ req->num_pages = npages;
+ req->page_offset = offset;
+ return 0;
+}
+
+static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos, int write)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ size_t nmax = write ? fc->max_write : fc->max_read;
+ loff_t pos = *ppos;
+ ssize_t res = 0;
+ struct fuse_req *req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ while (count) {
+ size_t tmp;
+ size_t nres;
+ size_t nbytes = min(count, nmax);
+ int err = fuse_get_user_pages(req, buf, nbytes, !write);
+ if (err) {
+ res = err;
+ break;
+ }
+ tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+ nbytes = min(nbytes, tmp);
+ if (write)
+ nres = fuse_send_write(req, file, inode, pos, nbytes);
+ else
+ nres = fuse_send_read(req, file, inode, pos, nbytes);
+ fuse_release_user_pages(req, !write);
+ if (req->out.h.error) {
+ if (!res)
+ res = req->out.h.error;
+ break;
+ } else if (nres > nbytes) {
+ res = -EIO;
+ break;
+ }
+ count -= nres;
+ res += nres;
+ pos += nres;
+ buf += nres;
+ if (nres != nbytes)
+ break;
+ if (count)
+ fuse_reset_request(req);
+ }
+ fuse_put_request(fc, req);
+ if (res > 0) {
+ if (write && pos > i_size_read(inode))
+ i_size_write(inode, pos);
+ *ppos = pos;
+ }
+ fuse_invalidate_attr(inode);
+
+ return res;
+}
+
+static ssize_t fuse_direct_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return fuse_direct_io(file, buf, count, ppos, 0);
+}
+
+static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ ssize_t res;
+ /* Don't allow parallel writes to the same file */
+ down(&inode->i_sem);
+ res = fuse_direct_io(file, buf, count, ppos, 1);
+ up(&inode->i_sem);
+ return res;
+}
+
+static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if ((vma->vm_flags & VM_SHARED)) {
+ if ((vma->vm_flags & VM_WRITE))
+ return -ENODEV;
+ else
+ vma->vm_flags &= ~VM_MAYWRITE;
+ }
+ return generic_file_mmap(file, vma);
+}
+
+static int fuse_set_page_dirty(struct page *page)
+{
+ printk("fuse_set_page_dirty: should not happen\n");
+ dump_stack();
+ return 0;
+}
+
+static struct file_operations fuse_file_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_file_read,
+ .write = generic_file_write,
+ .mmap = fuse_file_mmap,
+ .open = fuse_open,
+ .flush = fuse_flush,
+ .release = fuse_release,
+ .fsync = fuse_fsync,
+ .sendfile = generic_file_sendfile,
+};
+
+static struct file_operations fuse_direct_io_file_operations = {
+ .llseek = generic_file_llseek,
+ .read = fuse_direct_read,
+ .write = fuse_direct_write,
+ .open = fuse_open,
+ .flush = fuse_flush,
+ .release = fuse_release,
+ .fsync = fuse_fsync,
+ /* no mmap and sendfile */
+};
+
+static struct address_space_operations fuse_file_aops = {
+ .readpage = fuse_readpage,
+ .prepare_write = fuse_prepare_write,
+ .commit_write = fuse_commit_write,
+ .readpages = fuse_readpages,
+ .set_page_dirty = fuse_set_page_dirty,
+};
+
+void fuse_init_file_inode(struct inode *inode)
+{
+ inode->i_fop = &fuse_file_operations;
+ inode->i_data.a_ops = &fuse_file_aops;
+}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
new file mode 100644
index 000000000000..24d761518d86
--- /dev/null
+++ b/fs/fuse/fuse_i.h
@@ -0,0 +1,451 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include <linux/fuse.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/backing-dev.h>
+#include <asm/semaphore.h>
+
+/** 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
+
+/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem
+ module will check permissions based on the file mode. Otherwise no
+ permission checking is done in the kernel */
+#define FUSE_DEFAULT_PERMISSIONS (1 << 0)
+
+/** If the FUSE_ALLOW_OTHER flag is given, then not only the user
+ doing the mount will be allowed to access the filesystem */
+#define FUSE_ALLOW_OTHER (1 << 1)
+
+
+/** FUSE inode */
+struct fuse_inode {
+ /** Inode data */
+ struct inode inode;
+
+ /** Unique ID, which identifies the inode between userspace
+ * and kernel */
+ u64 nodeid;
+
+ /** Number of lookups on this inode */
+ u64 nlookup;
+
+ /** The request used for sending the FORGET message */
+ struct fuse_req *forget_req;
+
+ /** Time in jiffies until the file attributes are valid */
+ unsigned long i_time;
+};
+
+/** FUSE specific file data */
+struct fuse_file {
+ /** Request reserved for flush and release */
+ struct fuse_req *release_req;
+
+ /** File handle used by userspace */
+ u64 fh;
+};
+
+/** One input argument of a request */
+struct fuse_in_arg {
+ unsigned size;
+ const void *value;
+};
+
+/** The request input */
+struct fuse_in {
+ /** The request header */
+ struct fuse_in_header h;
+
+ /** True if the data for the last argument is in req->pages */
+ unsigned argpages:1;
+
+ /** Number of arguments */
+ unsigned numargs;
+
+ /** Array of arguments */
+ struct fuse_in_arg args[3];
+};
+
+/** One output argument of a request */
+struct fuse_arg {
+ unsigned size;
+ void *value;
+};
+
+/** The request output */
+struct fuse_out {
+ /** Header returned from userspace */
+ struct fuse_out_header h;
+
+ /** Last argument is variable length (can be shorter than
+ arg->size) */
+ unsigned argvar:1;
+
+ /** Last argument is a list of pages to copy data to */
+ unsigned argpages:1;
+
+ /** Zero partially or not copied pages */
+ unsigned page_zeroing:1;
+
+ /** Number or arguments */
+ unsigned numargs;
+
+ /** Array of arguments */
+ struct fuse_arg args[3];
+};
+
+struct fuse_req;
+struct fuse_conn;
+
+/**
+ * A request to the client
+ */
+struct fuse_req {
+ /** This can be on either unused_list, pending or processing
+ lists in fuse_conn */
+ struct list_head list;
+
+ /** Entry on the background list */
+ struct list_head bg_entry;
+
+ /** refcount */
+ atomic_t count;
+
+ /** True if the request has reply */
+ unsigned isreply:1;
+
+ /** The request is preallocated */
+ unsigned preallocated:1;
+
+ /** The request was interrupted */
+ unsigned interrupted:1;
+
+ /** Request is sent in the background */
+ unsigned background:1;
+
+ /** Data is being copied to/from the request */
+ unsigned locked:1;
+
+ /** Request has been sent to userspace */
+ unsigned sent:1;
+
+ /** The request is finished */
+ unsigned finished:1;
+
+ /** The request input */
+ struct fuse_in in;
+
+ /** The request output */
+ struct fuse_out out;
+
+ /** Used to wake up the task waiting for completion of request*/
+ wait_queue_head_t waitq;
+
+ /** Data for asynchronous requests */
+ union {
+ struct fuse_forget_in forget_in;
+ struct fuse_release_in release_in;
+ struct fuse_init_in_out init_in_out;
+ } misc;
+
+ /** page vector */
+ struct page *pages[FUSE_MAX_PAGES_PER_REQ];
+
+ /** number of pages in vector */
+ unsigned num_pages;
+
+ /** offset of data on first page */
+ unsigned page_offset;
+
+ /** Inode used in the request */
+ struct inode *inode;
+
+ /** Second inode used in the request (or NULL) */
+ struct inode *inode2;
+
+ /** File used in the request (or NULL) */
+ struct file *file;
+};
+
+/**
+ * A Fuse connection.
+ *
+ * This structure is created, when the filesystem is mounted, and is
+ * destroyed, when the client device is closed and the filesystem is
+ * unmounted.
+ */
+struct fuse_conn {
+ /** Reference count */
+ int count;
+
+ /** The user id for this mount */
+ uid_t user_id;
+
+ /** The group id for this mount */
+ gid_t group_id;
+
+ /** The fuse mount flags for this mount */
+ unsigned flags;
+
+ /** Maximum read size */
+ unsigned max_read;
+
+ /** Maximum write size */
+ unsigned max_write;
+
+ /** Readers of the connection are waiting on this */
+ wait_queue_head_t waitq;
+
+ /** The list of pending requests */
+ struct list_head pending;
+
+ /** The list of requests being processed */
+ struct list_head processing;
+
+ /** Requests put in the background (RELEASE or any other
+ interrupted request) */
+ struct list_head background;
+
+ /** Controls the maximum number of outstanding requests */
+ struct semaphore outstanding_sem;
+
+ /** This counts the number of outstanding requests if
+ outstanding_sem would go negative */
+ unsigned outstanding_debt;
+
+ /** 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;
+
+ /** Mount is active */
+ unsigned mounted : 1;
+
+ /** Connection established */
+ unsigned connected : 1;
+
+ /** Connection failed (version mismatch) */
+ unsigned conn_error : 1;
+
+ /** Is fsync not implemented by fs? */
+ unsigned no_fsync : 1;
+
+ /** Is fsyncdir not implemented by fs? */
+ unsigned no_fsyncdir : 1;
+
+ /** Is flush not implemented by fs? */
+ unsigned no_flush : 1;
+
+ /** Is setxattr not implemented by fs? */
+ unsigned no_setxattr : 1;
+
+ /** Is getxattr not implemented by fs? */
+ unsigned no_getxattr : 1;
+
+ /** Is listxattr not implemented by fs? */
+ unsigned no_listxattr : 1;
+
+ /** Is removexattr not implemented by fs? */
+ unsigned no_removexattr : 1;
+
+ /** Backing dev info */
+ struct backing_dev_info bdi;
+};
+
+static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
+{
+ return (struct fuse_conn **) &sb->s_fs_info;
+}
+
+static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
+{
+ return *get_fuse_conn_super_p(sb);
+}
+
+static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
+{
+ return get_fuse_conn_super(inode->i_sb);
+}
+
+static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
+{
+ return container_of(inode, struct fuse_inode, inode);
+}
+
+static inline u64 get_node_id(struct inode *inode)
+{
+ return get_fuse_inode(inode)->nodeid;
+}
+
+/** 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;
+
+/**
+ * Get a filled in inode
+ */
+struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+ int generation, struct fuse_attr *attr);
+
+/**
+ * Send FORGET command
+ */
+void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+ unsigned long nodeid, u64 nlookup);
+
+/**
+ * Send READ or READDIR request
+ */
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count,
+ int isdir);
+
+/**
+ * Send OPEN or OPENDIR request
+ */
+int fuse_open_common(struct inode *inode, struct file *file, int isdir);
+
+/**
+ * Send RELEASE or RELEASEDIR request
+ */
+int fuse_release_common(struct inode *inode, struct file *file, int isdir);
+
+/**
+ * Send FSYNC or FSYNCDIR request
+ */
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+ int isdir);
+
+/**
+ * Initialise file operations on a regular file
+ */
+void fuse_init_file_inode(struct inode *inode);
+
+/**
+ * Initialise inode operations on regular files and special files
+ */
+void fuse_init_common(struct inode *inode);
+
+/**
+ * Initialise inode and file operations on a directory
+ */
+void fuse_init_dir(struct inode *inode);
+
+/**
+ * Initialise inode operations on a symlink
+ */
+void fuse_init_symlink(struct inode *inode);
+
+/**
+ * Change attributes of an inode
+ */
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr);
+
+/**
+ * Check if the connection can be released, and if yes, then free the
+ * connection structure
+ */
+void fuse_release_conn(struct fuse_conn *fc);
+
+/**
+ * Initialize the client device
+ */
+int fuse_dev_init(void);
+
+/**
+ * Cleanup the client device
+ */
+void fuse_dev_cleanup(void);
+
+/**
+ * Allocate a request
+ */
+struct fuse_req *fuse_request_alloc(void);
+
+/**
+ * Free a request
+ */
+void fuse_request_free(struct fuse_req *req);
+
+/**
+ * Reinitialize a request, the preallocated flag is left unmodified
+ */
+void fuse_reset_request(struct fuse_req *req);
+
+/**
+ * Reserve a preallocated request
+ */
+struct fuse_req *fuse_get_request(struct fuse_conn *fc);
+
+/**
+ * Decrement reference count of a request. If count goes to zero put
+ * on unused list (preallocated) or free reqest (not preallocated).
+ */
+void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request (synchronous)
+ */
+void request_send(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request with no reply
+ */
+void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request in the background
+ */
+void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Release inodes and file assiciated with background request
+ */
+void fuse_release_background(struct fuse_req *req);
+
+/**
+ * Get the attributes of a file
+ */
+int fuse_do_getattr(struct inode *inode);
+
+/**
+ * Invalidate inode attributes
+ */
+void fuse_invalidate_attr(struct inode *inode);
+
+/**
+ * Send the INIT message
+ */
+void fuse_send_init(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
new file mode 100644
index 000000000000..e69a546844d0
--- /dev/null
+++ b/fs/fuse/inode.c
@@ -0,0 +1,591 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <linux/statfs.h>
+
+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;
+
+#define FUSE_SUPER_MAGIC 0x65735546
+
+struct fuse_mount_data {
+ int fd;
+ unsigned rootmode;
+ unsigned user_id;
+ unsigned group_id;
+ unsigned fd_present : 1;
+ unsigned rootmode_present : 1;
+ unsigned user_id_present : 1;
+ unsigned group_id_present : 1;
+ unsigned flags;
+ unsigned max_read;
+};
+
+static struct inode *fuse_alloc_inode(struct super_block *sb)
+{
+ struct inode *inode;
+ struct fuse_inode *fi;
+
+ inode = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL);
+ if (!inode)
+ return NULL;
+
+ fi = get_fuse_inode(inode);
+ fi->i_time = jiffies - 1;
+ fi->nodeid = 0;
+ fi->nlookup = 0;
+ fi->forget_req = fuse_request_alloc();
+ if (!fi->forget_req) {
+ kmem_cache_free(fuse_inode_cachep, inode);
+ return NULL;
+ }
+
+ return inode;
+}
+
+static void fuse_destroy_inode(struct inode *inode)
+{
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ if (fi->forget_req)
+ fuse_request_free(fi->forget_req);
+ kmem_cache_free(fuse_inode_cachep, inode);
+}
+
+static void fuse_read_inode(struct inode *inode)
+{
+ /* No op */
+}
+
+void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+ unsigned long nodeid, u64 nlookup)
+{
+ struct fuse_forget_in *inarg = &req->misc.forget_in;
+ inarg->nlookup = nlookup;
+ req->in.h.opcode = FUSE_FORGET;
+ req->in.h.nodeid = nodeid;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(struct fuse_forget_in);
+ req->in.args[0].value = inarg;
+ request_send_noreply(fc, req);
+}
+
+static void fuse_clear_inode(struct inode *inode)
+{
+ if (inode->i_sb->s_flags & MS_ACTIVE) {
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup);
+ fi->forget_req = NULL;
+ }
+}
+
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
+{
+ if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
+ invalidate_inode_pages(inode->i_mapping);
+
+ inode->i_ino = attr->ino;
+ inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
+ inode->i_nlink = attr->nlink;
+ inode->i_uid = attr->uid;
+ inode->i_gid = attr->gid;
+ i_size_write(inode, attr->size);
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = attr->blocks;
+ inode->i_atime.tv_sec = attr->atime;
+ inode->i_atime.tv_nsec = attr->atimensec;
+ inode->i_mtime.tv_sec = attr->mtime;
+ inode->i_mtime.tv_nsec = attr->mtimensec;
+ inode->i_ctime.tv_sec = attr->ctime;
+ inode->i_ctime.tv_nsec = attr->ctimensec;
+}
+
+static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
+{
+ inode->i_mode = attr->mode & S_IFMT;
+ i_size_write(inode, attr->size);
+ if (S_ISREG(inode->i_mode)) {
+ fuse_init_common(inode);
+ fuse_init_file_inode(inode);
+ } else if (S_ISDIR(inode->i_mode))
+ fuse_init_dir(inode);
+ else if (S_ISLNK(inode->i_mode))
+ fuse_init_symlink(inode);
+ else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+ fuse_init_common(inode);
+ init_special_inode(inode, inode->i_mode,
+ new_decode_dev(attr->rdev));
+ } else {
+ /* Don't let user create weird files */
+ inode->i_mode = S_IFREG;
+ fuse_init_common(inode);
+ fuse_init_file_inode(inode);
+ }
+}
+
+static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
+{
+ unsigned long nodeid = *(unsigned long *) _nodeidp;
+ if (get_node_id(inode) == nodeid)
+ return 1;
+ else
+ return 0;
+}
+
+static int fuse_inode_set(struct inode *inode, void *_nodeidp)
+{
+ unsigned long nodeid = *(unsigned long *) _nodeidp;
+ get_fuse_inode(inode)->nodeid = nodeid;
+ return 0;
+}
+
+struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+ int generation, struct fuse_attr *attr)
+{
+ struct inode *inode;
+ struct fuse_inode *fi;
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ int retried = 0;
+
+ retry:
+ inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
+ if (!inode)
+ return NULL;
+
+ if ((inode->i_state & I_NEW)) {
+ inode->i_flags |= S_NOATIME|S_NOCMTIME;
+ inode->i_generation = generation;
+ inode->i_data.backing_dev_info = &fc->bdi;
+ fuse_init_inode(inode, attr);
+ unlock_new_inode(inode);
+ } else if ((inode->i_mode ^ attr->mode) & S_IFMT) {
+ BUG_ON(retried);
+ /* Inode has changed type, any I/O on the old should fail */
+ make_bad_inode(inode);
+ iput(inode);
+ retried = 1;
+ goto retry;
+ }
+
+ fi = get_fuse_inode(inode);
+ fi->nlookup ++;
+ fuse_change_attributes(inode, attr);
+ return inode;
+}
+
+static void fuse_put_super(struct super_block *sb)
+{
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+
+ down_write(&fc->sbput_sem);
+ while (!list_empty(&fc->background))
+ fuse_release_background(list_entry(fc->background.next,
+ struct fuse_req, bg_entry));
+
+ spin_lock(&fuse_lock);
+ fc->mounted = 0;
+ fc->user_id = 0;
+ fc->group_id = 0;
+ fc->flags = 0;
+ /* Flush all readers on this fs */
+ wake_up_all(&fc->waitq);
+ up_write(&fc->sbput_sem);
+ fuse_release_conn(fc);
+ spin_unlock(&fuse_lock);
+}
+
+static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
+{
+ stbuf->f_type = FUSE_SUPER_MAGIC;
+ stbuf->f_bsize = attr->bsize;
+ stbuf->f_blocks = attr->blocks;
+ stbuf->f_bfree = attr->bfree;
+ stbuf->f_bavail = attr->bavail;
+ stbuf->f_files = attr->files;
+ stbuf->f_ffree = attr->ffree;
+ stbuf->f_namelen = attr->namelen;
+ /* fsid is left zero */
+}
+
+static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ struct fuse_req *req;
+ struct fuse_statfs_out outarg;
+ int err;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ req->in.numargs = 0;
+ req->in.h.opcode = FUSE_STATFS;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].value = &outarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err)
+ convert_fuse_statfs(buf, &outarg.st);
+ fuse_put_request(fc, req);
+ return err;
+}
+
+enum {
+ OPT_FD,
+ OPT_ROOTMODE,
+ OPT_USER_ID,
+ OPT_GROUP_ID,
+ OPT_DEFAULT_PERMISSIONS,
+ OPT_ALLOW_OTHER,
+ OPT_MAX_READ,
+ OPT_ERR
+};
+
+static match_table_t tokens = {
+ {OPT_FD, "fd=%u"},
+ {OPT_ROOTMODE, "rootmode=%o"},
+ {OPT_USER_ID, "user_id=%u"},
+ {OPT_GROUP_ID, "group_id=%u"},
+ {OPT_DEFAULT_PERMISSIONS, "default_permissions"},
+ {OPT_ALLOW_OTHER, "allow_other"},
+ {OPT_MAX_READ, "max_read=%u"},
+ {OPT_ERR, NULL}
+};
+
+static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
+{
+ char *p;
+ memset(d, 0, sizeof(struct fuse_mount_data));
+ d->max_read = ~0;
+
+ while ((p = strsep(&opt, ",")) != NULL) {
+ int token;
+ int value;
+ substring_t args[MAX_OPT_ARGS];
+ if (!*p)
+ continue;
+
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case OPT_FD:
+ if (match_int(&args[0], &value))
+ return 0;
+ d->fd = value;
+ d->fd_present = 1;
+ break;
+
+ case OPT_ROOTMODE:
+ if (match_octal(&args[0], &value))
+ return 0;
+ d->rootmode = value;
+ d->rootmode_present = 1;
+ break;
+
+ case OPT_USER_ID:
+ if (match_int(&args[0], &value))
+ return 0;
+ d->user_id = value;
+ d->user_id_present = 1;
+ break;
+
+ case OPT_GROUP_ID:
+ if (match_int(&args[0], &value))
+ return 0;
+ d->group_id = value;
+ d->group_id_present = 1;
+ break;
+
+ case OPT_DEFAULT_PERMISSIONS:
+ d->flags |= FUSE_DEFAULT_PERMISSIONS;
+ break;
+
+ case OPT_ALLOW_OTHER:
+ d->flags |= FUSE_ALLOW_OTHER;
+ break;
+
+ case OPT_MAX_READ:
+ if (match_int(&args[0], &value))
+ return 0;
+ d->max_read = value;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+
+ if (!d->fd_present || !d->rootmode_present ||
+ !d->user_id_present || !d->group_id_present)
+ return 0;
+
+ return 1;
+}
+
+static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
+
+ seq_printf(m, ",user_id=%u", fc->user_id);
+ seq_printf(m, ",group_id=%u", fc->group_id);
+ if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
+ seq_puts(m, ",default_permissions");
+ if (fc->flags & FUSE_ALLOW_OTHER)
+ seq_puts(m, ",allow_other");
+ if (fc->max_read != ~0)
+ seq_printf(m, ",max_read=%u", fc->max_read);
+ return 0;
+}
+
+static void free_conn(struct fuse_conn *fc)
+{
+ 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);
+}
+
+/* Must be called with the fuse lock held */
+void fuse_release_conn(struct fuse_conn *fc)
+{
+ fc->count--;
+ if (!fc->count)
+ free_conn(fc);
+}
+
+static struct fuse_conn *new_conn(void)
+{
+ struct fuse_conn *fc;
+
+ fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+ if (fc != NULL) {
+ int i;
+ memset(fc, 0, sizeof(*fc));
+ init_waitqueue_head(&fc->waitq);
+ INIT_LIST_HEAD(&fc->pending);
+ INIT_LIST_HEAD(&fc->processing);
+ INIT_LIST_HEAD(&fc->unused_list);
+ INIT_LIST_HEAD(&fc->background);
+ sema_init(&fc->outstanding_sem, 0);
+ init_rwsem(&fc->sbput_sem);
+ for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
+ struct fuse_req *req = fuse_request_alloc();
+ if (!req) {
+ free_conn(fc);
+ 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;
+ }
+ return fc;
+}
+
+static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
+{
+ struct fuse_conn *fc;
+
+ if (file->f_op != &fuse_dev_operations)
+ return ERR_PTR(-EINVAL);
+ fc = new_conn();
+ if (fc == NULL)
+ return ERR_PTR(-ENOMEM);
+ spin_lock(&fuse_lock);
+ if (file->private_data) {
+ free_conn(fc);
+ fc = ERR_PTR(-EINVAL);
+ } else {
+ file->private_data = fc;
+ *get_fuse_conn_super_p(sb) = fc;
+ fc->mounted = 1;
+ fc->connected = 1;
+ fc->count = 2;
+ }
+ spin_unlock(&fuse_lock);
+ return fc;
+}
+
+static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
+{
+ struct fuse_attr attr;
+ memset(&attr, 0, sizeof(attr));
+
+ attr.mode = mode;
+ attr.ino = FUSE_ROOT_ID;
+ return fuse_iget(sb, 1, 0, &attr);
+}
+
+static struct super_operations fuse_super_operations = {
+ .alloc_inode = fuse_alloc_inode,
+ .destroy_inode = fuse_destroy_inode,
+ .read_inode = fuse_read_inode,
+ .clear_inode = fuse_clear_inode,
+ .put_super = fuse_put_super,
+ .statfs = fuse_statfs,
+ .show_options = fuse_show_options,
+};
+
+static int fuse_fill_super(struct super_block *sb, void *data, int silent)
+{
+ struct fuse_conn *fc;
+ struct inode *root;
+ struct fuse_mount_data d;
+ struct file *file;
+ int err;
+
+ if (!parse_fuse_opt((char *) data, &d))
+ return -EINVAL;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = FUSE_SUPER_MAGIC;
+ sb->s_op = &fuse_super_operations;
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+
+ file = fget(d.fd);
+ if (!file)
+ return -EINVAL;
+
+ fc = get_conn(file, sb);
+ fput(file);
+ if (IS_ERR(fc))
+ return PTR_ERR(fc);
+
+ fc->flags = d.flags;
+ fc->user_id = d.user_id;
+ fc->group_id = d.group_id;
+ fc->max_read = d.max_read;
+ if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
+ fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+ fc->max_write = FUSE_MAX_IN / 2;
+
+ err = -ENOMEM;
+ root = get_root_inode(sb, d.rootmode);
+ if (root == NULL)
+ goto err;
+
+ sb->s_root = d_alloc_root(root);
+ if (!sb->s_root) {
+ iput(root);
+ goto err;
+ }
+ fuse_send_init(fc);
+ return 0;
+
+ err:
+ spin_lock(&fuse_lock);
+ fuse_release_conn(fc);
+ spin_unlock(&fuse_lock);
+ return err;
+}
+
+static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *raw_data)
+{
+ return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super);
+}
+
+static struct file_system_type fuse_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "fuse",
+ .get_sb = fuse_get_sb,
+ .kill_sb = kill_anon_super,
+};
+
+static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
+ unsigned long flags)
+{
+ struct inode * inode = foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ inode_init_once(inode);
+}
+
+static int __init fuse_fs_init(void)
+{
+ int err;
+
+ err = register_filesystem(&fuse_fs_type);
+ if (err)
+ printk("fuse: failed to register filesystem\n");
+ else {
+ fuse_inode_cachep = kmem_cache_create("fuse_inode",
+ sizeof(struct fuse_inode),
+ 0, SLAB_HWCACHE_ALIGN,
+ fuse_inode_init_once, NULL);
+ if (!fuse_inode_cachep) {
+ unregister_filesystem(&fuse_fs_type);
+ err = -ENOMEM;
+ }
+ }
+
+ return err;
+}
+
+static void fuse_fs_cleanup(void)
+{
+ unregister_filesystem(&fuse_fs_type);
+ kmem_cache_destroy(fuse_inode_cachep);
+}
+
+static int __init fuse_init(void)
+{
+ int res;
+
+ 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;
+
+ res = fuse_dev_init();
+ if (res)
+ goto err_fs_cleanup;
+
+ return 0;
+
+ err_fs_cleanup:
+ fuse_fs_cleanup();
+ err:
+ return res;
+}
+
+static void __exit fuse_exit(void)
+{
+ printk(KERN_DEBUG "fuse exit\n");
+
+ fuse_fs_cleanup();
+ fuse_dev_cleanup();
+}
+
+module_init(fuse_init);
+module_exit(fuse_exit);
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index a096c5a56664..3d5cdc6847c0 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -13,8 +13,6 @@
#include "btree.h"
-#define REF_PAGES 0
-
void hfs_bnode_read(struct hfs_bnode *node, void *buf,
int off, int len)
{
@@ -289,9 +287,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
page_cache_release(page);
goto fail;
}
-#if !REF_PAGES
page_cache_release(page);
-#endif
node->page[i] = page;
}
@@ -449,13 +445,6 @@ void hfs_bnode_get(struct hfs_bnode *node)
{
if (node) {
atomic_inc(&node->refcnt);
-#if REF_PAGES
- {
- int i;
- for (i = 0; i < node->tree->pages_per_bnode; i++)
- get_page(node->page[i]);
- }
-#endif
dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
}
@@ -472,20 +461,12 @@ void hfs_bnode_put(struct hfs_bnode *node)
node->tree->cnid, node->this, atomic_read(&node->refcnt));
if (!atomic_read(&node->refcnt))
BUG();
- if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
-#if REF_PAGES
- for (i = 0; i < tree->pages_per_bnode; i++)
- put_page(node->page[i]);
-#endif
+ if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
return;
- }
for (i = 0; i < tree->pages_per_bnode; i++) {
if (!node->page[i])
continue;
mark_page_accessed(node->page[i]);
-#if REF_PAGES
- put_page(node->page[i]);
-#endif
}
if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 65dedefcabfc..2fcd679f0238 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -20,12 +20,12 @@
*
* Given the ID of the parent and the name build a search key.
*/
-void hfs_cat_build_key(btree_key *key, u32 parent, struct qstr *name)
+void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, struct qstr *name)
{
key->cat.reserved = 0;
key->cat.ParID = cpu_to_be32(parent);
if (name) {
- hfs_triv2mac(&key->cat.CName, name);
+ hfs_asc2mac(sb, &key->cat.CName, name);
key->key_len = 6 + key->cat.CName.len;
} else {
memset(&key->cat.CName, 0, sizeof(struct hfs_name));
@@ -62,13 +62,14 @@ static int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
}
}
-static int hfs_cat_build_thread(hfs_cat_rec *rec, int type,
+static int hfs_cat_build_thread(struct super_block *sb,
+ hfs_cat_rec *rec, int type,
u32 parentid, struct qstr *name)
{
rec->type = type;
memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved));
rec->thread.ParID = cpu_to_be32(parentid);
- hfs_triv2mac(&rec->thread.CName, name);
+ hfs_asc2mac(sb, &rec->thread.CName, name);
return sizeof(struct hfs_cat_thread);
}
@@ -93,8 +94,8 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
sb = dir->i_sb;
hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
- hfs_cat_build_key(fd.search_key, cnid, NULL);
- entry_size = hfs_cat_build_thread(&entry, S_ISDIR(inode->i_mode) ?
+ hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
+ entry_size = hfs_cat_build_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
HFS_CDR_THD : HFS_CDR_FTH,
dir->i_ino, str);
err = hfs_brec_find(&fd);
@@ -107,7 +108,7 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
if (err)
goto err2;
- hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+ hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
entry_size = hfs_cat_build_record(&entry, cnid, inode);
err = hfs_brec_find(&fd);
if (err != -ENOENT) {
@@ -127,7 +128,7 @@ int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *
return 0;
err1:
- hfs_cat_build_key(fd.search_key, cnid, NULL);
+ hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
if (!hfs_brec_find(&fd))
hfs_brec_remove(&fd);
err2:
@@ -176,7 +177,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
hfs_cat_rec rec;
int res, len, type;
- hfs_cat_build_key(fd->search_key, cnid, NULL);
+ hfs_cat_build_key(sb, fd->search_key, cnid, NULL);
res = hfs_brec_read(fd, &rec, sizeof(rec));
if (res)
return res;
@@ -211,7 +212,7 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
sb = dir->i_sb;
hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
- hfs_cat_build_key(fd.search_key, dir->i_ino, str);
+ hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
res = hfs_brec_find(&fd);
if (res)
goto out;
@@ -239,7 +240,7 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
if (res)
goto out;
- hfs_cat_build_key(fd.search_key, cnid, NULL);
+ hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
res = hfs_brec_find(&fd);
if (!res) {
res = hfs_brec_remove(&fd);
@@ -280,7 +281,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
dst_fd = src_fd;
/* find the old dir entry and read the data */
- hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+ hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -289,7 +290,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
src_fd.entrylength);
/* create new dir entry with the data from the old entry */
- hfs_cat_build_key(dst_fd.search_key, dst_dir->i_ino, dst_name);
+ hfs_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
err = hfs_brec_find(&dst_fd);
if (err != -ENOENT) {
if (!err)
@@ -305,7 +306,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
mark_inode_dirty(dst_dir);
/* finally remove the old entry */
- hfs_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+ hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -321,7 +322,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
goto out;
/* remove old thread entry */
- hfs_cat_build_key(src_fd.search_key, cnid, NULL);
+ hfs_cat_build_key(sb, src_fd.search_key, cnid, NULL);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -330,8 +331,8 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
goto out;
/* create new thread entry */
- hfs_cat_build_key(dst_fd.search_key, cnid, NULL);
- entry_size = hfs_cat_build_thread(&entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
+ hfs_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
+ entry_size = hfs_cat_build_thread(sb, &entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
dst_dir->i_ino, dst_name);
err = hfs_brec_find(&dst_fd);
if (err != -ENOENT) {
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index c55998262aed..e1f24befba58 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -28,7 +28,7 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
dentry->d_op = &hfs_dentry_operations;
hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
- hfs_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+ hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
res = hfs_brec_read(&fd, &rec, sizeof(rec));
if (res) {
hfs_find_exit(&fd);
@@ -56,7 +56,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct inode *inode = filp->f_dentry->d_inode;
struct super_block *sb = inode->i_sb;
int len, err;
- char strbuf[HFS_NAMELEN + 1];
+ char strbuf[HFS_MAX_NAMELEN];
union hfs_cat_rec entry;
struct hfs_find_data fd;
struct hfs_readdir_data *rd;
@@ -66,7 +66,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
return 0;
hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
- hfs_cat_build_key(fd.search_key, inode->i_ino, NULL);
+ hfs_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
err = hfs_brec_find(&fd);
if (err)
goto out;
@@ -111,7 +111,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
type = entry.type;
- len = hfs_mac2triv(strbuf, &fd.key->cat.CName);
+ len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName);
if (type == HFS_CDR_DIR) {
if (fd.entrylength < sizeof(struct hfs_cat_dir)) {
printk("HFS: small dir entry\n");
@@ -307,7 +307,8 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
old_dir, &old_dentry->d_name,
new_dir, &new_dentry->d_name);
if (!res)
- hfs_cat_build_key((btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
+ hfs_cat_build_key(old_dir->i_sb,
+ (btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
new_dir->i_ino, &new_dentry->d_name);
return res;
}
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index df6b33adee3b..88099ab1a180 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -25,6 +25,7 @@
#define HFS_SECTOR_SIZE 512 /* size of an HFS sector */
#define HFS_SECTOR_SIZE_BITS 9 /* log_2(HFS_SECTOR_SIZE) */
#define HFS_NAMELEN 31 /* maximum length of an HFS filename */
+#define HFS_MAX_NAMELEN 128
#define HFS_MAX_VALENCE 32767U
/* Meanings of the drAtrb field of the MDB,
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 0dc8ef8e14de..aae019aadf88 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -141,6 +141,8 @@ struct hfs_sb_info {
int session, part;
+ struct nls_table *nls_io, *nls_disk;
+
struct semaphore bitmap_lock;
unsigned long flags;
@@ -168,7 +170,7 @@ extern int hfs_cat_create(u32, struct inode *, struct qstr *, struct inode *);
extern int hfs_cat_delete(u32, struct inode *, struct qstr *);
extern int hfs_cat_move(u32, struct inode *, struct qstr *,
struct inode *, struct qstr *);
-extern void hfs_cat_build_key(btree_key *, u32, 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;
@@ -222,8 +224,8 @@ extern int hfs_strcmp(const unsigned char *, unsigned int,
extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
/* trans.c */
-extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
-extern int hfs_mac2triv(char *, const struct hfs_name *);
+extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
+extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
extern struct timezone sys_tz;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 751912326094..f1570b9f9de3 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -160,7 +160,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
init_MUTEX(&HFS_I(inode)->extents_lock);
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
- hfs_cat_build_key((btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
+ hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
inode->i_ino = HFS_SB(sb)->next_id++;
inode->i_mode = mode;
inode->i_uid = current->fsuid;
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 217e32f37e0b..0a473f79c89f 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -10,6 +10,7 @@
#include <linux/cdrom.h>
#include <linux/genhd.h>
+#include <linux/nls.h>
#include "hfs_fs.h"
#include "btree.h"
@@ -343,6 +344,11 @@ void hfs_mdb_put(struct super_block *sb)
brelse(HFS_SB(sb)->mdb_bh);
brelse(HFS_SB(sb)->alt_mdb_bh);
+ if (HFS_SB(sb)->nls_io)
+ unload_nls(HFS_SB(sb)->nls_io);
+ if (HFS_SB(sb)->nls_disk)
+ unload_nls(HFS_SB(sb)->nls_disk);
+
kfree(HFS_SB(sb));
sb->s_fs_info = NULL;
}
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index ab783f6afa3b..c5074aeafcae 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -15,8 +15,11 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/blkdev.h>
+#include <linux/mount.h>
#include <linux/init.h>
+#include <linux/nls.h>
#include <linux/parser.h>
+#include <linux/seq_file.h>
#include <linux/vfs.h>
#include "hfs_fs.h"
@@ -111,6 +114,32 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
+static int hfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+ struct hfs_sb_info *sbi = HFS_SB(mnt->mnt_sb);
+
+ if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f))
+ seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator);
+ if (sbi->s_type != cpu_to_be32(0x3f3f3f3f))
+ seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type);
+ seq_printf(seq, ",uid=%u,gid=%u", sbi->s_uid, sbi->s_gid);
+ if (sbi->s_file_umask != 0133)
+ seq_printf(seq, ",file_umask=%o", sbi->s_file_umask);
+ if (sbi->s_dir_umask != 0022)
+ seq_printf(seq, ",dir_umask=%o", sbi->s_dir_umask);
+ if (sbi->part >= 0)
+ seq_printf(seq, ",part=%u", sbi->part);
+ if (sbi->session >= 0)
+ seq_printf(seq, ",session=%u", sbi->session);
+ if (sbi->nls_disk)
+ seq_printf(seq, ",codepage=%s", sbi->nls_disk->charset);
+ if (sbi->nls_io)
+ seq_printf(seq, ",iocharset=%s", sbi->nls_io->charset);
+ if (sbi->s_quiet)
+ seq_printf(seq, ",quiet");
+ return 0;
+}
+
static struct inode *hfs_alloc_inode(struct super_block *sb)
{
struct hfs_inode_info *i;
@@ -133,11 +162,13 @@ static struct super_operations hfs_super_operations = {
.write_super = hfs_write_super,
.statfs = hfs_statfs,
.remount_fs = hfs_remount,
+ .show_options = hfs_show_options,
};
enum {
opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask,
opt_part, opt_session, opt_type, opt_creator, opt_quiet,
+ opt_codepage, opt_iocharset,
opt_err
};
@@ -152,6 +183,8 @@ static match_table_t tokens = {
{ opt_type, "type=%s" },
{ opt_creator, "creator=%s" },
{ opt_quiet, "quiet" },
+ { opt_codepage, "codepage=%s" },
+ { opt_iocharset, "iocharset=%s" },
{ opt_err, NULL }
};
@@ -257,11 +290,46 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
case opt_quiet:
hsb->s_quiet = 1;
break;
+ case opt_codepage:
+ if (hsb->nls_disk) {
+ printk("HFS+-fs: unable to change codepage\n");
+ return 0;
+ }
+ p = match_strdup(&args[0]);
+ hsb->nls_disk = load_nls(p);
+ if (!hsb->nls_disk) {
+ printk("HFS+-fs: unable to load codepage \"%s\"\n", p);
+ kfree(p);
+ return 0;
+ }
+ kfree(p);
+ break;
+ case opt_iocharset:
+ if (hsb->nls_io) {
+ printk("HFS: unable to change iocharset\n");
+ return 0;
+ }
+ p = match_strdup(&args[0]);
+ hsb->nls_io = load_nls(p);
+ if (!hsb->nls_io) {
+ printk("HFS: unable to load iocharset \"%s\"\n", p);
+ kfree(p);
+ return 0;
+ }
+ kfree(p);
+ break;
default:
return 0;
}
}
+ if (hsb->nls_disk && !hsb->nls_io) {
+ hsb->nls_io = load_nls_default();
+ if (!hsb->nls_io) {
+ printk("HFS: unable to load default iocharset\n");
+ return 0;
+ }
+ }
hsb->s_dir_umask &= 0777;
hsb->s_file_umask &= 0577;
diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c
index fb9720abbadd..e673a88b8ae7 100644
--- a/fs/hfs/trans.c
+++ b/fs/hfs/trans.c
@@ -9,12 +9,15 @@
* with ':' vs. '/' as the path-element separator.
*/
+#include <linux/types.h>
+#include <linux/nls.h>
+
#include "hfs_fs.h"
/*================ Global functions ================*/
/*
- * hfs_mac2triv()
+ * hfs_mac2asc()
*
* Given a 'Pascal String' (a string preceded by a length byte) in
* the Macintosh character set produce the corresponding filename using
@@ -27,23 +30,58 @@
* by ':' which never appears in HFS filenames. All other characters
* are passed unchanged from input to output.
*/
-int hfs_mac2triv(char *out, const struct hfs_name *in)
+int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
{
- const char *p;
- char c;
- int i, len;
+ struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
+ struct nls_table *nls_io = HFS_SB(sb)->nls_io;
+ const char *src;
+ char *dst;
+ int srclen, dstlen, size;
+
+ src = in->name;
+ srclen = in->len;
+ dst = out;
+ dstlen = HFS_MAX_NAMELEN;
+ if (nls_io) {
+ wchar_t ch;
- len = in->len;
- p = in->name;
- for (i = 0; i < len; i++) {
- c = *p++;
- *out++ = c == '/' ? ':' : c;
+ while (srclen > 0) {
+ if (nls_disk) {
+ size = nls_disk->char2uni(src, srclen, &ch);
+ if (size <= 0) {
+ ch = '?';
+ size = 1;
+ }
+ src += size;
+ srclen -= size;
+ } else {
+ ch = *src++;
+ srclen--;
+ }
+ if (ch == '/')
+ ch = ':';
+ size = nls_io->uni2char(ch, dst, dstlen);
+ if (size < 0) {
+ if (size == -ENAMETOOLONG)
+ goto out;
+ *dst = '?';
+ size = 1;
+ }
+ dst += size;
+ dstlen -= size;
+ }
+ } else {
+ char ch;
+
+ while (--srclen >= 0)
+ *dst++ = (ch = *src++) == '/' ? ':' : ch;
}
- return i;
+out:
+ return dst - out;
}
/*
- * hfs_triv2mac()
+ * hfs_asc2mac()
*
* Given an ASCII string (not null-terminated) and its length,
* generate the corresponding filename in the Macintosh character set
@@ -54,19 +92,57 @@ int hfs_mac2triv(char *out, const struct hfs_name *in)
* This routine is a inverse to hfs_mac2triv().
* A ':' is replaced by a '/'.
*/
-void hfs_triv2mac(struct hfs_name *out, struct qstr *in)
+void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, struct qstr *in)
{
+ struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
+ struct nls_table *nls_io = HFS_SB(sb)->nls_io;
const char *src;
- char *dst, c;
- int i, len;
+ char *dst;
+ int srclen, dstlen, size;
- out->len = len = min((unsigned int)HFS_NAMELEN, in->len);
src = in->name;
+ srclen = in->len;
dst = out->name;
- for (i = 0; i < len; i++) {
- c = *src++;
- *dst++ = c == ':' ? '/' : c;
+ dstlen = HFS_NAMELEN;
+ if (nls_io) {
+ wchar_t ch;
+
+ while (srclen > 0) {
+ size = nls_io->char2uni(src, srclen, &ch);
+ if (size < 0) {
+ ch = '?';
+ size = 1;
+ }
+ src += size;
+ srclen -= size;
+ if (ch == ':')
+ ch = '/';
+ if (nls_disk) {
+ size = nls_disk->uni2char(ch, dst, dstlen);
+ if (size < 0) {
+ if (size == -ENAMETOOLONG)
+ goto out;
+ *dst = '?';
+ size = 1;
+ }
+ dst += size;
+ dstlen -= size;
+ } else {
+ *dst++ = ch > 0xff ? '?' : ch;
+ dstlen--;
+ }
+ }
+ } else {
+ char ch;
+
+ if (dstlen > srclen)
+ dstlen = srclen;
+ while (--dstlen >= 0)
+ *dst++ = (ch = *src++) == ':' ? '/' : ch;
}
- for (; i < HFS_NAMELEN; i++)
+out:
+ out->len = dst - (char *)out->name;
+ dstlen = HFS_NAMELEN - out->len;
+ while (--dstlen >= 0)
*dst++ = 0;
}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 8868d3b766fd..b85abc6e6f83 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -18,8 +18,6 @@
#include "hfsplus_fs.h"
#include "hfsplus_raw.h"
-#define REF_PAGES 0
-
/* Copy a specified range of bytes from the raw data of a node */
void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
{
@@ -450,9 +448,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
page_cache_release(page);
goto fail;
}
-#if !REF_PAGES
page_cache_release(page);
-#endif
node->page[i] = page;
}
@@ -612,13 +608,6 @@ void hfs_bnode_get(struct hfs_bnode *node)
{
if (node) {
atomic_inc(&node->refcnt);
-#if REF_PAGES
- {
- int i;
- for (i = 0; i < node->tree->pages_per_bnode; i++)
- get_page(node->page[i]);
- }
-#endif
dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
}
@@ -635,20 +624,12 @@ void hfs_bnode_put(struct hfs_bnode *node)
node->tree->cnid, node->this, atomic_read(&node->refcnt));
if (!atomic_read(&node->refcnt))
BUG();
- if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) {
-#if REF_PAGES
- for (i = 0; i < tree->pages_per_bnode; i++)
- put_page(node->page[i]);
-#endif
+ if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
return;
- }
for (i = 0; i < tree->pages_per_bnode; i++) {
if (!node->page[i])
continue;
mark_page_accessed(node->page[i]);
-#if REF_PAGES
- put_page(node->page[i]);
-#endif
}
if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 533094a570df..2bc0cdd30e56 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -343,8 +343,9 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
/* options.c */
-int parse_options(char *, struct hfsplus_sb_info *);
-void fill_defaults(struct hfsplus_sb_info *);
+int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
+void hfsplus_fill_defaults(struct hfsplus_sb_info *);
+int hfsplus_show_options(struct seq_file *, struct vfsmount *);
/* tables.c */
extern u16 hfsplus_case_fold_table[];
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 1cca0102c98d..cca0818aa4ca 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -13,6 +13,8 @@
#include <linux/sched.h>
#include <linux/parser.h>
#include <linux/nls.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
#include "hfsplus_fs.h"
enum {
@@ -38,7 +40,7 @@ static match_table_t tokens = {
};
/* Initialize an options object to reasonable defaults */
-void fill_defaults(struct hfsplus_sb_info *opts)
+void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
{
if (!opts)
return;
@@ -63,7 +65,7 @@ static inline int match_fourchar(substring_t *arg, u32 *result)
/* Parse options from mount. Returns 0 on failure */
/* input is the options passed to mount() as a string */
-int parse_options(char *input, struct hfsplus_sb_info *sbi)
+int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -160,3 +162,23 @@ done:
return 1;
}
+
+int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+ struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb);
+
+ if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
+ seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
+ if (sbi->type != HFSPLUS_DEF_CR_TYPE)
+ seq_printf(seq, ",type=%.4s", (char *)&sbi->type);
+ seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask, sbi->uid, sbi->gid);
+ if (sbi->part >= 0)
+ seq_printf(seq, ",part=%u", sbi->part);
+ if (sbi->session >= 0)
+ seq_printf(seq, ",session=%u", sbi->session);
+ if (sbi->nls)
+ seq_printf(seq, ",nls=%s", sbi->nls->charset);
+ if (sbi->flags & HFSPLUS_SB_NODECOMPOSE)
+ seq_printf(seq, ",nodecompose");
+ return 0;
+}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index d55ad67b8e42..fd0f0f050e1d 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -217,8 +217,7 @@ static void hfsplus_put_super(struct super_block *sb)
vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
- ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
- wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+ sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
}
hfs_btree_close(HFSPLUS_SB(sb).cat_tree);
@@ -277,6 +276,7 @@ static struct super_operations hfsplus_sops = {
.write_super = hfsplus_write_super,
.statfs = hfsplus_statfs,
.remount_fs = hfsplus_remount,
+ .show_options = hfsplus_show_options,
};
static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
@@ -297,8 +297,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
sb->s_fs_info = sbi;
INIT_HLIST_HEAD(&sbi->rsrc_inodes);
- fill_defaults(sbi);
- if (!parse_options(data, sbi)) {
+ hfsplus_fill_defaults(sbi);
+ if (!hfsplus_parse_options(data, sbi)) {
if (!silent)
printk("HFS+-fs: unable to parse mount options\n");
err = -EINVAL;
@@ -415,8 +415,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
- ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh);
- wait_on_buffer(HFSPLUS_SB(sb).s_vhbh);
+ sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
if (!HFSPLUS_SB(sb).hidden_dir) {
printk("HFS+: create hidden dir...\n");
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 67bca0d4a33b..cca3fb693f99 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -49,7 +49,6 @@ struct hostfs_iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
- unsigned int ia_attr_flags;
};
extern int stat_file(const char *path, unsigned long long *inode_out,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index b2d18200a003..59c5062cd63f 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -284,6 +284,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
static void hostfs_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
if(HOSTFS_I(inode)->fd != -1) {
close_file(&HOSTFS_I(inode)->fd);
HOSTFS_I(inode)->fd = -1;
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 38b1741fa539..e3d17e9ea6c1 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -284,6 +284,7 @@ void hpfs_write_if_changed(struct inode *inode)
void hpfs_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
lock_kernel();
hpfs_remove_fnode(inode->i_sb, inode->i_ino);
unlock_kernel();
diff --git a/fs/inode.c b/fs/inode.c
index e57f1724db3e..f80a79ff156b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1034,19 +1034,21 @@ void generic_delete_inode(struct inode *inode)
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
- if (inode->i_data.nrpages)
- truncate_inode_pages(&inode->i_data, 0);
-
security_inode_delete(inode);
if (op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
if (!is_bad_inode(inode))
DQUOT_INIT(inode);
- /* s_op->delete_inode internally recalls clear_inode() */
+ /* Filesystems implementing their own
+ * s_op->delete_inode are required to call
+ * truncate_inode_pages and clear_inode()
+ * internally */
delete(inode);
- } else
+ } else {
+ truncate_inode_pages(&inode->i_data, 0);
clear_inode(inode);
+ }
spin_lock(&inode_lock);
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
@@ -1195,9 +1197,6 @@ void update_atime(struct inode *inode)
if (!timespec_equal(&inode->i_atime, &now)) {
inode->i_atime = now;
mark_inode_dirty_sync(inode);
- } else {
- if (!timespec_equal(&inode->i_atime, &now))
- inode->i_atime = now;
}
}
diff --git a/fs/inotify.c b/fs/inotify.c
index 2e4e2a57708c..a37e9fb1da58 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -37,6 +37,7 @@
#include <asm/ioctls.h>
static atomic_t inotify_cookie;
+static atomic_t inotify_watches;
static kmem_cache_t *watch_cachep;
static kmem_cache_t *event_cachep;
@@ -422,6 +423,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev,
get_inotify_watch(watch);
atomic_inc(&dev->user->inotify_watches);
+ atomic_inc(&inotify_watches);
return watch;
}
@@ -454,6 +456,7 @@ static void remove_watch_no_event(struct inotify_watch *watch,
list_del(&watch->d_list);
atomic_dec(&dev->user->inotify_watches);
+ atomic_dec(&inotify_watches);
idr_remove(&dev->idr, watch->wd);
put_inotify_watch(watch);
}
@@ -532,6 +535,9 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
struct dentry *parent;
struct inode *inode;
+ if (!atomic_read (&inotify_watches))
+ return;
+
spin_lock(&dentry->d_lock);
parent = dentry->d_parent;
inode = parent->d_inode;
@@ -925,6 +931,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
struct nameidata nd;
struct file *filp;
int ret, fput_needed;
+ int mask_add = 0;
filp = fget_light(fd, &fput_needed);
if (unlikely(!filp))
@@ -947,6 +954,9 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
down(&inode->inotify_sem);
down(&dev->sem);
+ if (mask & IN_MASK_ADD)
+ mask_add = 1;
+
/* don't let user-space set invalid bits: we don't want flags set */
mask &= IN_ALL_EVENTS;
if (unlikely(!mask)) {
@@ -960,7 +970,10 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
*/
old = inode_find_dev(inode, dev);
if (unlikely(old)) {
- old->mask = mask;
+ if (mask_add)
+ old->mask |= mask;
+ else
+ old->mask = mask;
ret = old->wd;
goto out;
}
@@ -1043,6 +1056,7 @@ static int __init inotify_setup(void)
inotify_max_user_watches = 8192;
atomic_set(&inotify_cookie, 0);
+ atomic_set(&inotify_watches, 0);
watch_cachep = kmem_cache_create("inotify_watch_cache",
sizeof(struct inotify_watch),
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 5a97e346bd95..014a51fd00d7 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -204,7 +204,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
int i;
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, *batch_count, bhs);
+ ll_rw_block(SWRITE, *batch_count, bhs);
spin_lock(&journal->j_list_lock);
for (i = 0; i < *batch_count; i++) {
struct buffer_head *bh = bhs[i];
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index dac720c837ab..2a3e310f79ef 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -358,7 +358,7 @@ write_out_data:
jbd_debug(2, "submit %d writes\n",
bufs);
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, bufs, wbuf);
+ ll_rw_block(SWRITE, bufs, wbuf);
journal_brelse_array(wbuf, bufs);
bufs = 0;
goto write_out_data;
@@ -381,7 +381,7 @@ write_out_data:
if (bufs) {
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, bufs, wbuf);
+ ll_rw_block(SWRITE, bufs, wbuf);
journal_brelse_array(wbuf, bufs);
spin_lock(&journal->j_list_lock);
}
@@ -720,11 +720,17 @@ wait_for_iobuf:
J_ASSERT(commit_transaction->t_log_list == NULL);
restart_loop:
+ /*
+ * As there are other places (journal_unmap_buffer()) adding buffers
+ * to this list we have to be careful and hold the j_list_lock.
+ */
+ spin_lock(&journal->j_list_lock);
while (commit_transaction->t_forget) {
transaction_t *cp_transaction;
struct buffer_head *bh;
jh = commit_transaction->t_forget;
+ spin_unlock(&journal->j_list_lock);
bh = jh2bh(jh);
jbd_lock_bh_state(bh);
J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
@@ -792,9 +798,25 @@ restart_loop:
journal_remove_journal_head(bh); /* needs a brelse */
release_buffer_page(bh);
}
+ cond_resched_lock(&journal->j_list_lock);
+ }
+ spin_unlock(&journal->j_list_lock);
+ /*
+ * This is a bit sleazy. We borrow j_list_lock to protect
+ * journal->j_committing_transaction in __journal_remove_checkpoint.
+ * Really, __journal_remove_checkpoint should be using j_state_lock but
+ * it's a bit hassle to hold that across __journal_remove_checkpoint
+ */
+ spin_lock(&journal->j_state_lock);
+ spin_lock(&journal->j_list_lock);
+ /*
+ * Now recheck if some buffers did not get attached to the transaction
+ * while the lock was dropped...
+ */
+ if (commit_transaction->t_forget) {
spin_unlock(&journal->j_list_lock);
- if (cond_resched())
- goto restart_loop;
+ spin_unlock(&journal->j_state_lock);
+ goto restart_loop;
}
/* Done with this transaction! */
@@ -803,14 +825,6 @@ restart_loop:
J_ASSERT(commit_transaction->t_state == T_COMMIT);
- /*
- * This is a bit sleazy. We borrow j_list_lock to protect
- * journal->j_committing_transaction in __journal_remove_checkpoint.
- * Really, __jornal_remove_checkpoint should be using j_state_lock but
- * it's a bit hassle to hold that across __journal_remove_checkpoint
- */
- spin_lock(&journal->j_state_lock);
- spin_lock(&journal->j_list_lock);
commit_transaction->t_state = T_FINISHED;
J_ASSERT(commit_transaction == journal->j_committing_transaction);
journal->j_commit_sequence = commit_transaction->t_tid;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 5e7b43949517..7ae2c4fe506b 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -65,7 +65,6 @@ EXPORT_SYMBOL(journal_set_features);
EXPORT_SYMBOL(journal_create);
EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_recover);
EXPORT_SYMBOL(journal_update_superblock);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
@@ -81,6 +80,7 @@ EXPORT_SYMBOL(journal_try_to_free_buffers);
EXPORT_SYMBOL(journal_force_commit);
static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+static void __journal_abort_soft (journal_t *journal, int errno);
/*
* Helper function used to manage commit timeouts
@@ -93,16 +93,6 @@ static void commit_timeout(unsigned long __data)
wake_up_process(p);
}
-/* Static check for data structure consistency. There's no code
- * invoked --- we'll just get a linker failure if things aren't right.
- */
-void __journal_internal_check(void)
-{
- extern void journal_bad_superblock_size(void);
- if (sizeof(struct journal_superblock_s) != 1024)
- journal_bad_superblock_size();
-}
-
/*
* kjournald: The main thread function used to manage a logging device
* journal.
@@ -119,16 +109,12 @@ void __journal_internal_check(void)
* known as checkpointing, and this thread is responsible for that job.
*/
-journal_t *current_journal; // AKPM: debug
-
-int kjournald(void *arg)
+static int kjournald(void *arg)
{
journal_t *journal = (journal_t *) arg;
transaction_t *transaction;
struct timer_list timer;
- current_journal = journal;
-
daemonize("kjournald");
/* Set up an interval timer which can be used to trigger a
@@ -193,6 +179,8 @@ loop:
if (transaction && time_after_eq(jiffies,
transaction->t_expires))
should_sleep = 0;
+ if (journal->j_flags & JFS_UNMOUNT)
+ should_sleep = 0;
if (should_sleep) {
spin_unlock(&journal->j_state_lock);
schedule();
@@ -969,7 +957,7 @@ void journal_update_superblock(journal_t *journal, int wait)
if (wait)
sync_dirty_buffer(bh);
else
- ll_rw_block(WRITE, 1, &bh);
+ ll_rw_block(SWRITE, 1, &bh);
out:
/* If we have just flushed the log (by marking s_start==0), then
@@ -1439,7 +1427,7 @@ int journal_wipe(journal_t *journal, int write)
* device this journal is present.
*/
-const char *journal_dev_name(journal_t *journal, char *buffer)
+static const char *journal_dev_name(journal_t *journal, char *buffer)
{
struct block_device *bdev;
@@ -1485,7 +1473,7 @@ void __journal_abort_hard(journal_t *journal)
/* Soft abort: record the abort error status in the journal superblock,
* but don't do any other IO. */
-void __journal_abort_soft (journal_t *journal, int errno)
+static void __journal_abort_soft (journal_t *journal, int errno)
{
if (journal->j_flags & JFS_ABORT)
return;
@@ -1880,7 +1868,7 @@ EXPORT_SYMBOL(journal_enable_debug);
static struct proc_dir_entry *proc_jbd_debug;
-int read_jbd_debug(char *page, char **start, off_t off,
+static int read_jbd_debug(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int ret;
@@ -1890,7 +1878,7 @@ int read_jbd_debug(char *page, char **start, off_t off,
return ret;
}
-int write_jbd_debug(struct file *file, const char __user *buffer,
+static int write_jbd_debug(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char buf[32];
@@ -1979,6 +1967,14 @@ static int __init journal_init(void)
{
int ret;
+/* Static check for data structure consistency. There's no code
+ * invoked --- we'll just get a linker failure if things aren't right.
+ */
+ extern void journal_bad_superblock_size(void);
+ if (sizeof(struct journal_superblock_s) != 1024)
+ journal_bad_superblock_size();
+
+
ret = journal_init_caches();
if (ret != 0)
journal_destroy_caches();
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index d327a598f861..a56144183462 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -116,7 +116,8 @@ static inline int hash(journal_t *journal, unsigned long block)
(block << (hash_shift - 12))) & (table->hash_size - 1);
}
-int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
+static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
+ tid_t seq)
{
struct list_head *hash_list;
struct jbd_revoke_record_s *record;
@@ -613,7 +614,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh);
- ll_rw_block(WRITE, 1, &bh);
+ ll_rw_block(SWRITE, 1, &bh);
}
#endif
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 77b7662b840b..49bbc2be3d72 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -490,23 +490,21 @@ void journal_unlock_updates (journal_t *journal)
*/
static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
{
- struct buffer_head *bh = jh2bh(jh);
int jlist;
- if (buffer_dirty(bh)) {
- /* If this buffer is one which might reasonably be dirty
- * --- ie. data, or not part of this journal --- then
- * we're OK to leave it alone, but otherwise we need to
- * move the dirty bit to the journal's own internal
- * JBDDirty bit. */
- jlist = jh->b_jlist;
-
- if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
- jlist == BJ_Shadow || jlist == BJ_Forget) {
- if (test_clear_buffer_dirty(jh2bh(jh))) {
- set_bit(BH_JBDDirty, &jh2bh(jh)->b_state);
- }
- }
+ /* If this buffer is one which might reasonably be dirty
+ * --- ie. data, or not part of this journal --- then
+ * we're OK to leave it alone, but otherwise we need to
+ * move the dirty bit to the journal's own internal
+ * JBDDirty bit. */
+ jlist = jh->b_jlist;
+
+ if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+ jlist == BJ_Shadow || jlist == BJ_Forget) {
+ struct buffer_head *bh = jh2bh(jh);
+
+ if (test_clear_buffer_dirty(bh))
+ set_buffer_jbddirty(bh);
}
}
@@ -574,9 +572,14 @@ repeat:
if (jh->b_next_transaction)
J_ASSERT_JH(jh, jh->b_next_transaction ==
transaction);
- JBUFFER_TRACE(jh, "Unexpected dirty buffer");
- jbd_unexpected_dirty_buffer(jh);
- }
+ }
+ /*
+ * In any case we need to clean the dirty flag and we must
+ * do it under the buffer lock to be sure we don't race
+ * with running write-out.
+ */
+ JBUFFER_TRACE(jh, "Unexpected dirty buffer");
+ jbd_unexpected_dirty_buffer(jh);
}
unlock_buffer(bh);
@@ -1337,8 +1340,7 @@ int journal_stop(handle_t *handle)
if (handle->h_sync) {
do {
old_handle_count = transaction->t_handle_count;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (old_handle_count != transaction->t_handle_count);
}
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index bfbeb4c86e03..3dcc6d2162cb 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -1629,9 +1629,6 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
}
-extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
-extern loff_t generic_file_llseek(struct file *, loff_t, int) __attribute__((weak));
-
static struct file_operations jffs_file_operations =
{
.open = generic_file_open,
@@ -1747,6 +1744,7 @@ jffs_delete_inode(struct inode *inode)
D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
inode->i_ino));
+ truncate_inode_pages(&inode->i_data, 0);
lock_kernel();
inode->i_size = 0;
inode->i_blocks = 0;
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 456d7e6e29c2..27f199e94cfc 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -1701,12 +1701,10 @@ jffs_find_file(struct jffs_control *c, __u32 ino)
{
struct jffs_file *f;
int i = ino % c->hash_len;
- struct list_head *tmp;
D3(printk("jffs_find_file(): ino: %u\n", ino));
- for (tmp = c->hash[i].next; tmp != &c->hash[i]; tmp = tmp->next) {
- f = list_entry(tmp, struct jffs_file, hash);
+ list_for_each_entry(f, &c->hash[i], hash) {
if (ino != f->ino)
continue;
D3(printk("jffs_find_file(): Found file with ino "
@@ -2102,13 +2100,12 @@ jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
int result = 0;
for (pos = 0; pos < c->hash_len; pos++) {
- struct list_head *p, *next;
- for (p = c->hash[pos].next; p != &c->hash[pos]; p = next) {
- /* We need a reference to the next file in the
- list because `func' might remove the current
- file `f'. */
- next = p->next;
- r = func(list_entry(p, struct jffs_file, hash));
+ struct jffs_file *f, *next;
+
+ /* We must do _safe, because 'func' might remove the
+ current file 'f' from the list. */
+ list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
+ r = func(f);
if (r < 0)
return r;
result += r;
@@ -2613,9 +2610,8 @@ jffs_print_hash_table(struct jffs_control *c)
printk("JFFS: Dumping the file system's hash table...\n");
for (i = 0; i < c->hash_len; i++) {
- struct list_head *p;
- for (p = c->hash[i].next; p != &c->hash[i]; p = p->next) {
- struct jffs_file *f=list_entry(p,struct jffs_file,hash);
+ struct jffs_file *f;
+ list_for_each_entry(f, &c->hash[i], hash) {
printk("*** c->hash[%u]: \"%s\" "
"(ino: %u, pino: %u)\n",
i, (f->name ? f->name : ""),
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index bd9ed9b0247b..8279bf0133ff 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -21,9 +21,6 @@
#include <linux/jffs2.h>
#include "nodelist.h"
-extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
-extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak));
-
static int jffs2_commit_write (struct file *filp, struct page *pg,
unsigned start, unsigned end);
static int jffs2_prepare_write (struct file *filp, struct page *pg,
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index e892dab40c26..461e4934ca7c 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -23,6 +23,7 @@
#include <linux/quotaops.h>
#include <linux/posix_acl_xattr.h>
#include "jfs_incore.h"
+#include "jfs_txnmgr.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
@@ -75,7 +76,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
return acl;
}
-static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
+ struct posix_acl *acl)
{
char *ea_name;
struct jfs_inode_info *ji = JFS_IP(inode);
@@ -110,7 +112,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
if (rc < 0)
goto out;
}
- rc = __jfs_setxattr(inode, ea_name, value, size, 0);
+ rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
out:
kfree(value);
@@ -143,7 +145,7 @@ int jfs_permission(struct inode *inode, int mask, struct nameidata *nd)
return generic_permission(inode, mask, jfs_check_acl);
}
-int jfs_init_acl(struct inode *inode, struct inode *dir)
+int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
{
struct posix_acl *acl = NULL;
struct posix_acl *clone;
@@ -159,7 +161,7 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
if (acl) {
if (S_ISDIR(inode->i_mode)) {
- rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+ rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
if (rc)
goto cleanup;
}
@@ -173,7 +175,8 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
if (rc >= 0) {
inode->i_mode = mode;
if (rc > 0)
- rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+ rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
+ clone);
}
posix_acl_release(clone);
cleanup:
@@ -202,8 +205,15 @@ static int jfs_acl_chmod(struct inode *inode)
return -ENOMEM;
rc = posix_acl_chmod_masq(clone, inode->i_mode);
- if (!rc)
- rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+ if (!rc) {
+ tid_t tid = txBegin(inode->i_sb, 0);
+ down(&JFS_IP(inode)->commit_sem);
+ rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
+ if (!rc)
+ rc = txCommit(tid, 1, &inode, 0);
+ txEnd(tid);
+ up(&JFS_IP(inode)->commit_sem);
+ }
posix_acl_release(clone);
return rc;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 767c7ecb429e..0ec62d5310db 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -128,21 +128,23 @@ void jfs_delete_inode(struct inode *inode)
{
jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
- if (is_bad_inode(inode) ||
- (JFS_IP(inode)->fileset != cpu_to_le32(FILESYSTEM_I)))
- return;
+ if (!is_bad_inode(inode) &&
+ (JFS_IP(inode)->fileset == cpu_to_le32(FILESYSTEM_I))) {
- if (test_cflag(COMMIT_Freewmap, inode))
- jfs_free_zero_link(inode);
+ truncate_inode_pages(&inode->i_data, 0);
- diFree(inode);
+ if (test_cflag(COMMIT_Freewmap, inode))
+ jfs_free_zero_link(inode);
- /*
- * Free the inode from the quota allocation.
- */
- DQUOT_INIT(inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
+ diFree(inode);
+
+ /*
+ * Free the inode from the quota allocation.
+ */
+ DQUOT_INIT(inode);
+ DQUOT_FREE_INODE(inode);
+ DQUOT_DROP(inode);
+ }
clear_inode(inode);
}
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index a3acd3eec059..a76293767c73 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -21,8 +21,16 @@
#ifdef CONFIG_JFS_POSIX_ACL
int jfs_permission(struct inode *, int, struct nameidata *);
-int jfs_init_acl(struct inode *, struct inode *);
+int jfs_init_acl(tid_t, struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);
-#endif /* CONFIG_JFS_POSIX_ACL */
+#else
+
+static inline int jfs_init_acl(tid_t tid, struct inode *inode,
+ struct inode *dir)
+{
+ return 0;
+}
+
+#endif
#endif /* _H_JFS_ACL */
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 86ccac80f0ab..72a5588faeca 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -37,6 +37,9 @@
#define JFS_ERR_CONTINUE 0x00000004 /* continue */
#define JFS_ERR_PANIC 0x00000008 /* panic */
+#define JFS_USRQUOTA 0x00000010
+#define JFS_GRPQUOTA 0x00000020
+
/* platform option (conditional compilation) */
#define JFS_AIX 0x80000000 /* AIX support */
/* POSIX name/directory support */
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h
index a1052f3f0bee..25e9990bccd1 100644
--- a/fs/jfs/jfs_xattr.h
+++ b/fs/jfs/jfs_xattr.h
@@ -52,8 +52,8 @@ struct jfs_ea_list {
#define END_EALIST(ealist) \
((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
-extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
- int);
+extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *,
+ size_t, int);
extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
int);
extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
@@ -61,4 +61,14 @@ extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
extern int jfs_removexattr(struct dentry *, const char *);
+#ifdef CONFIG_JFS_SECURITY
+extern int jfs_init_security(tid_t, struct inode *, struct inode *);
+#else
+static inline int jfs_init_security(tid_t tid, struct inode *inode,
+ struct inode *dir)
+{
+ return 0;
+}
+#endif
+
#endif /* H_JFS_XATTR */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 1cae14e741eb..1abe7343f920 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -39,6 +39,24 @@ struct dentry_operations jfs_ci_dentry_operations;
static s64 commitZeroLink(tid_t, struct inode *);
/*
+ * NAME: free_ea_wmap(inode)
+ *
+ * FUNCTION: free uncommitted extended attributes from working map
+ *
+ */
+static inline void free_ea_wmap(struct inode *inode)
+{
+ dxd_t *ea = &JFS_IP(inode)->ea;
+
+ if (ea->flag & DXD_EXTENT) {
+ /* free EA pages from cache */
+ invalidate_dxd_metapages(inode, *ea);
+ dbFree(inode, addressDXD(ea), lengthDXD(ea));
+ }
+ ea->flag = 0;
+}
+
+/*
* NAME: jfs_create(dip, dentry, mode)
*
* FUNCTION: create a regular file in the parent directory <dip>
@@ -89,8 +107,19 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
down(&JFS_IP(dip)->commit_sem);
down(&JFS_IP(ip)->commit_sem);
+ rc = jfs_init_acl(tid, ip, dip);
+ if (rc)
+ goto out3;
+
+ rc = jfs_init_security(tid, ip, dip);
+ if (rc) {
+ txAbort(tid, 0);
+ goto out3;
+ }
+
if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
jfs_err("jfs_create: dtSearch returned %d", rc);
+ txAbort(tid, 0);
goto out3;
}
@@ -139,6 +168,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
up(&JFS_IP(dip)->commit_sem);
up(&JFS_IP(ip)->commit_sem);
if (rc) {
+ free_ea_wmap(ip);
ip->i_nlink = 0;
iput(ip);
} else
@@ -147,11 +177,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
out2:
free_UCSname(&dname);
-#ifdef CONFIG_JFS_POSIX_ACL
- if (rc == 0)
- jfs_init_acl(ip, dip);
-#endif
-
out1:
jfs_info("jfs_create: rc:%d", rc);
@@ -216,8 +241,19 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
down(&JFS_IP(dip)->commit_sem);
down(&JFS_IP(ip)->commit_sem);
+ rc = jfs_init_acl(tid, ip, dip);
+ if (rc)
+ goto out3;
+
+ rc = jfs_init_security(tid, ip, dip);
+ if (rc) {
+ txAbort(tid, 0);
+ goto out3;
+ }
+
if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
jfs_err("jfs_mkdir: dtSearch returned %d", rc);
+ txAbort(tid, 0);
goto out3;
}
@@ -267,6 +303,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
up(&JFS_IP(dip)->commit_sem);
up(&JFS_IP(ip)->commit_sem);
if (rc) {
+ free_ea_wmap(ip);
ip->i_nlink = 0;
iput(ip);
} else
@@ -275,10 +312,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
out2:
free_UCSname(&dname);
-#ifdef CONFIG_JFS_POSIX_ACL
- if (rc == 0)
- jfs_init_acl(ip, dip);
-#endif
out1:
@@ -885,6 +918,10 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
down(&JFS_IP(dip)->commit_sem);
down(&JFS_IP(ip)->commit_sem);
+ rc = jfs_init_security(tid, ip, dip);
+ if (rc)
+ goto out3;
+
tblk = tid_to_tblock(tid);
tblk->xflag |= COMMIT_CREATE;
tblk->ino = ip->i_ino;
@@ -1000,6 +1037,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
up(&JFS_IP(dip)->commit_sem);
up(&JFS_IP(ip)->commit_sem);
if (rc) {
+ free_ea_wmap(ip);
ip->i_nlink = 0;
iput(ip);
} else
@@ -1008,11 +1046,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
out2:
free_UCSname(&dname);
-#ifdef CONFIG_JFS_POSIX_ACL
- if (rc == 0)
- jfs_init_acl(ip, dip);
-#endif
-
out1:
jfs_info("jfs_symlink: rc:%d", rc);
return rc;
@@ -1328,8 +1361,20 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
down(&JFS_IP(dir)->commit_sem);
down(&JFS_IP(ip)->commit_sem);
- if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
+ rc = jfs_init_acl(tid, ip, dir);
+ if (rc)
+ goto out3;
+
+ rc = jfs_init_security(tid, ip, dir);
+ if (rc) {
+ txAbort(tid, 0);
+ goto out3;
+ }
+
+ if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
+ txAbort(tid, 0);
goto out3;
+ }
tblk = tid_to_tblock(tid);
tblk->xflag |= COMMIT_CREATE;
@@ -1337,8 +1382,10 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
ino = ip->i_ino;
- if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
+ if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
+ txAbort(tid, 0);
goto out3;
+ }
ip->i_op = &jfs_file_inode_operations;
jfs_ip->dev = new_encode_dev(rdev);
@@ -1360,6 +1407,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
up(&JFS_IP(ip)->commit_sem);
up(&JFS_IP(dir)->commit_sem);
if (rc) {
+ free_ea_wmap(ip);
ip->i_nlink = 0;
iput(ip);
} else
@@ -1368,11 +1416,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
out1:
free_UCSname(&dname);
-#ifdef CONFIG_JFS_POSIX_ACL
- if (rc == 0)
- jfs_init_acl(ip, dir);
-#endif
-
out:
jfs_info("jfs_mknod: returning %d", rc);
return rc;
@@ -1390,6 +1433,8 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
jfs_info("jfs_lookup: name = %s", name);
+ if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
+ dentry->d_op = &jfs_ci_dentry_operations;
if ((name[0] == '.') && (len == 1))
inum = dip->i_ino;
@@ -1417,9 +1462,6 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
return ERR_PTR(-EACCES);
}
- if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
- dentry->d_op = &jfs_ci_dentry_operations;
-
dentry = d_splice_alias(ip, dentry);
if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 9ff89720f93b..71bc34b96b2b 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -23,9 +23,11 @@
#include <linux/parser.h>
#include <linux/completion.h>
#include <linux/vfs.h>
+#include <linux/mount.h>
#include <linux/moduleparam.h>
#include <linux/posix_acl.h>
#include <asm/uaccess.h>
+#include <linux/seq_file.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
@@ -192,7 +194,8 @@ static void jfs_put_super(struct super_block *sb)
enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
- Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err,
+ Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
+ Opt_usrquota, Opt_grpquota
};
static match_table_t tokens = {
@@ -204,8 +207,8 @@ static match_table_t tokens = {
{Opt_errors, "errors=%s"},
{Opt_ignore, "noquota"},
{Opt_ignore, "quota"},
- {Opt_ignore, "usrquota"},
- {Opt_ignore, "grpquota"},
+ {Opt_usrquota, "usrquota"},
+ {Opt_grpquota, "grpquota"},
{Opt_err, NULL}
};
@@ -293,6 +296,24 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
}
break;
}
+
+#if defined(CONFIG_QUOTA)
+ case Opt_quota:
+ case Opt_usrquota:
+ *flag |= JFS_USRQUOTA;
+ break;
+ case Opt_grpquota:
+ *flag |= JFS_GRPQUOTA;
+ break;
+#else
+ case Opt_usrquota:
+ case Opt_grpquota:
+ case Opt_quota:
+ printk(KERN_ERR
+ "JFS: quota operations not supported\n");
+ break;
+#endif
+
default:
printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p);
@@ -539,6 +560,26 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
return 0;
}
+static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
+
+ if (sbi->flag & JFS_NOINTEGRITY)
+ seq_puts(seq, ",nointegrity");
+ else
+ seq_puts(seq, ",integrity");
+
+#if defined(CONFIG_QUOTA)
+ if (sbi->flag & JFS_USRQUOTA)
+ seq_puts(seq, ",usrquota");
+
+ if (sbi->flag & JFS_GRPQUOTA)
+ seq_puts(seq, ",grpquota");
+#endif
+
+ return 0;
+}
+
static struct super_operations jfs_super_operations = {
.alloc_inode = jfs_alloc_inode,
.destroy_inode = jfs_destroy_inode,
@@ -552,6 +593,7 @@ static struct super_operations jfs_super_operations = {
.unlockfs = jfs_unlockfs,
.statfs = jfs_statfs,
.remount_fs = jfs_remount,
+ .show_options = jfs_show_options
};
static struct export_operations jfs_export_operations = {
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 554ec739e49b..23aa5066b5a4 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -21,6 +21,7 @@
#include <linux/xattr.h>
#include <linux/posix_acl_xattr.h>
#include <linux/quotaops.h>
+#include <linux/security.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
@@ -633,12 +634,12 @@ static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
}
}
-static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
+static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
+ int new_size)
{
struct jfs_inode_info *ji = JFS_IP(inode);
unsigned long old_blocks, new_blocks;
int rc = 0;
- tid_t tid;
if (new_size == 0) {
ea_release(inode, ea_buf);
@@ -664,9 +665,6 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
if (rc)
return rc;
- tid = txBegin(inode->i_sb, 0);
- down(&ji->commit_sem);
-
old_blocks = new_blocks = 0;
if (ji->ea.flag & DXD_EXTENT) {
@@ -695,11 +693,8 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
DQUOT_FREE_BLOCK(inode, old_blocks);
inode->i_ctime = CURRENT_TIME;
- rc = txCommit(tid, 1, &inode, 0);
- txEnd(tid);
- up(&ji->commit_sem);
- return rc;
+ return 0;
}
/*
@@ -810,8 +805,8 @@ static int can_set_xattr(struct inode *inode, const char *name,
return permission(inode, MAY_WRITE, NULL);
}
-int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
- size_t value_len, int flags)
+int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
+ const void *value, size_t value_len, int flags)
{
struct jfs_ea_list *ealist;
struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL;
@@ -825,9 +820,6 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
int rc;
int length;
- if ((rc = can_set_xattr(inode, name, value, value_len)))
- return rc;
-
if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
GFP_KERNEL);
@@ -939,7 +931,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
ealist->size = cpu_to_le32(new_size);
- rc = ea_put(inode, &ea_buf, new_size);
+ rc = ea_put(tid, inode, &ea_buf, new_size);
goto out;
release:
@@ -955,12 +947,29 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t value_len, int flags)
{
+ struct inode *inode = dentry->d_inode;
+ struct jfs_inode_info *ji = JFS_IP(inode);
+ int rc;
+ tid_t tid;
+
+ if ((rc = can_set_xattr(inode, name, value, value_len)))
+ return rc;
+
if (value == NULL) { /* empty EA, do not remove */
value = "";
value_len = 0;
}
- return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
+ tid = txBegin(inode->i_sb, 0);
+ down(&ji->commit_sem);
+ rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len,
+ flags);
+ if (!rc)
+ rc = txCommit(tid, 1, &inode, 0);
+ txEnd(tid);
+ up(&ji->commit_sem);
+
+ return rc;
}
static int can_get_xattr(struct inode *inode, const char *name)
@@ -1122,5 +1131,56 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
int jfs_removexattr(struct dentry *dentry, const char *name)
{
- return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+ struct inode *inode = dentry->d_inode;
+ struct jfs_inode_info *ji = JFS_IP(inode);
+ int rc;
+ tid_t tid;
+
+ if ((rc = can_set_xattr(inode, name, NULL, 0)))
+ return rc;
+
+ tid = txBegin(inode->i_sb, 0);
+ down(&ji->commit_sem);
+ rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+ if (!rc)
+ rc = txCommit(tid, 1, &inode, 0);
+ txEnd(tid);
+ up(&ji->commit_sem);
+
+ return rc;
+}
+
+#ifdef CONFIG_JFS_SECURITY
+int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)
+{
+ int rc;
+ size_t len;
+ void *value;
+ char *suffix;
+ char *name;
+
+ rc = security_inode_init_security(inode, dir, &suffix, &value, &len);
+ if (rc) {
+ if (rc == -EOPNOTSUPP)
+ return 0;
+ return rc;
+ }
+ name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix),
+ GFP_NOFS);
+ if (!name) {
+ rc = -ENOMEM;
+ goto kmalloc_failed;
+ }
+ strcpy(name, XATTR_SECURITY_PREFIX);
+ strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
+
+ rc = __jfs_setxattr(tid, inode, name, value, len, 0);
+
+ kfree(name);
+kmalloc_failed:
+ kfree(suffix);
+ kfree(value);
+
+ return rc;
}
+#endif
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 14b3ce87fa29..87332f30141b 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -299,8 +299,7 @@ nlmclnt_alloc_call(void)
return call;
}
printk("nlmclnt_alloc_call: failed, waiting for memory\n");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(5*HZ);
+ schedule_timeout_interruptible(5*HZ);
}
return NULL;
}
diff --git a/fs/locks.c b/fs/locks.c
index 11956b6179ff..c2c09b4798d6 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2198,21 +2198,23 @@ void steal_locks(fl_owner_t from)
{
struct files_struct *files = current->files;
int i, j;
+ struct fdtable *fdt;
if (from == files)
return;
lock_kernel();
j = 0;
+ fdt = files_fdtable(files);
for (;;) {
unsigned long set;
i = j * __NFDBITS;
- if (i >= files->max_fdset || i >= files->max_fds)
+ if (i >= fdt->max_fdset || i >= fdt->max_fds)
break;
- set = files->open_fds->fds_bits[j++];
+ set = fdt->open_fds->fds_bits[j++];
while (set) {
if (set & 1) {
- struct file *file = files->fd[i];
+ struct file *file = fdt->fd[i];
if (file)
__steal_locks(file, from);
}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 3f18c21198d7..790cc0d0e970 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -24,6 +24,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data);
static void minix_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
minix_truncate(inode);
minix_free_inode(inode);
diff --git a/fs/namei.c b/fs/namei.c
index 91ce1f24bbb6..043d587216b5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -525,6 +525,22 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd)
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.
@@ -552,9 +568,7 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
nd->depth--;
return err;
loop:
- dput(path->dentry);
- if (path->mnt != nd->mnt)
- mntput(path->mnt);
+ dput_path(path, nd);
path_release(nd);
return err;
}
@@ -813,13 +827,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
err = -ENOTDIR;
if (!inode->i_op)
break;
- } else {
- dput(nd->dentry);
- if (nd->mnt != next.mnt)
- mntput(nd->mnt);
- nd->mnt = next.mnt;
- nd->dentry = next.dentry;
- }
+ } else
+ path_to_nameidata(&next, nd);
err = -ENOTDIR;
if (!inode->i_op->lookup)
break;
@@ -859,13 +868,8 @@ last_component:
if (err)
goto return_err;
inode = nd->dentry->d_inode;
- } else {
- dput(nd->dentry);
- if (nd->mnt != next.mnt)
- mntput(nd->mnt);
- nd->mnt = next.mnt;
- nd->dentry = next.dentry;
- }
+ } else
+ path_to_nameidata(&next, nd);
err = -ENOENT;
if (!inode)
break;
@@ -901,9 +905,7 @@ return_reval:
return_base:
return 0;
out_dput:
- dput(next.dentry);
- if (nd->mnt != next.mnt)
- mntput(next.mnt);
+ dput_path(&next, nd);
break;
}
path_release(nd);
@@ -1314,10 +1316,8 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
return error;
DQUOT_INIT(dir);
error = dir->i_op->create(dir, dentry, mode, nd);
- if (!error) {
+ if (!error)
fsnotify_create(dir, dentry->d_name.name);
- security_inode_post_create(dir, dentry, mode);
- }
return error;
}
@@ -1507,11 +1507,7 @@ do_last:
if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
goto do_link;
- dput(nd->dentry);
- nd->dentry = path.dentry;
- if (nd->mnt != path.mnt)
- mntput(nd->mnt);
- nd->mnt = path.mnt;
+ path_to_nameidata(&path, nd);
error = -EISDIR;
if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
goto exit;
@@ -1522,9 +1518,7 @@ ok:
return 0;
exit_dput:
- dput(path.dentry);
- if (nd->mnt != path.mnt)
- mntput(path.mnt);
+ dput_path(&path, nd);
exit:
path_release(nd);
return error;
@@ -1639,10 +1633,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
DQUOT_INIT(dir);
error = dir->i_op->mknod(dir, dentry, mode, dev);
- if (!error) {
+ if (!error)
fsnotify_create(dir, dentry->d_name.name);
- security_inode_post_mknod(dir, dentry, mode, dev);
- }
return error;
}
@@ -1712,10 +1704,8 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
DQUOT_INIT(dir);
error = dir->i_op->mkdir(dir, dentry, mode);
- if (!error) {
+ if (!error)
fsnotify_mkdir(dir, dentry->d_name.name);
- security_inode_post_mkdir(dir,dentry, mode);
- }
return error;
}
@@ -1951,10 +1941,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
DQUOT_INIT(dir);
error = dir->i_op->symlink(dir, dentry, oldname);
- if (!error) {
+ if (!error)
fsnotify_create(dir, dentry->d_name.name);
- security_inode_post_symlink(dir, dentry, oldname);
- }
return error;
}
@@ -2024,10 +2012,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
DQUOT_INIT(dir);
error = dir->i_op->link(old_dentry, dir, new_dentry);
up(&old_dentry->d_inode->i_sem);
- if (!error) {
+ if (!error)
fsnotify_create(dir, new_dentry->d_name.name);
- security_inode_post_link(old_dentry, dir, new_dentry);
- }
return error;
}
@@ -2146,11 +2132,8 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
d_rehash(new_dentry);
dput(new_dentry);
}
- if (!error) {
+ if (!error)
d_move(old_dentry,new_dentry);
- security_inode_post_rename(old_dir, old_dentry,
- new_dir, new_dentry);
- }
return error;
}
@@ -2176,7 +2159,6 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
/* The following d_move() should become unconditional */
if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
d_move(old_dentry, new_dentry);
- security_inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
}
if (target)
up(&target->i_sem);
diff --git a/fs/namespace.c b/fs/namespace.c
index 79bd8a46e1e7..2fa9fdf7d6f5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -40,7 +40,7 @@ static inline int sysfs_init(void)
__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
static struct list_head *mount_hashtable;
-static int hash_mask, hash_bits;
+static int hash_mask __read_mostly, hash_bits __read_mostly;
static kmem_cache_t *mnt_cache;
static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
@@ -537,7 +537,6 @@ lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
{
struct vfsmount *res, *p, *q, *r, *s;
- struct list_head *h;
struct nameidata nd;
res = q = clone_mnt(mnt, dentry);
@@ -546,8 +545,7 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
q->mnt_mountpoint = mnt->mnt_mountpoint;
p = mnt;
- for (h = mnt->mnt_mounts.next; h != &mnt->mnt_mounts; h = h->next) {
- r = list_entry(h, struct vfsmount, mnt_child);
+ list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry))
continue;
@@ -1334,8 +1332,12 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p
error = -EINVAL;
if (user_nd.mnt->mnt_root != user_nd.dentry)
goto out2; /* not a mountpoint */
+ if (user_nd.mnt->mnt_parent == user_nd.mnt)
+ goto out2; /* not attached */
if (new_nd.mnt->mnt_root != new_nd.dentry)
goto out2; /* not a mountpoint */
+ if (new_nd.mnt->mnt_parent == new_nd.mnt)
+ goto out2; /* not attached */
tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
spin_lock(&vfsmount_lock);
if (tmp != new_nd.mnt) {
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 44795d2f4b30..8c8839203cd5 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -286,6 +286,8 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
static void
ncp_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
+
if (S_ISDIR(inode->i_mode)) {
DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 541b418327c8..6922469d6fc5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -146,6 +146,8 @@ nfs_delete_inode(struct inode * inode)
{
dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
+ truncate_inode_pages(&inode->i_data, 0);
+
nfs_wb_all(inode);
/*
* The following should never happen...
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 2681485cf2d0..edc95514046d 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -34,8 +34,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
res = rpc_call_sync(clnt, msg, flags);
if (res != -EJUKEBOX)
break;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
+ schedule_timeout_interruptible(NFS_JUKEBOX_RETRY_TIME);
res = -ERESTARTSYS;
} while (!signalled());
rpc_clnt_sigunmask(clnt, &oldset);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0c5a308e4963..9701ca8c9428 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2418,14 +2418,11 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
*timeout = NFS4_POLL_RETRY_MAX;
rpc_clnt_sigmask(clnt, &oldset);
if (clnt->cl_intr) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(*timeout);
+ schedule_timeout_interruptible(*timeout);
if (signalled())
res = -ERESTARTSYS;
- } else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(*timeout);
- }
+ } else
+ schedule_timeout_uninterruptible(*timeout);
rpc_clnt_sigunmask(clnt, &oldset);
*timeout <<= 1;
return res;
@@ -2578,8 +2575,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4
static unsigned long
nfs4_set_lock_task_retry(unsigned long timeout)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(timeout);
+ schedule_timeout_interruptible(timeout);
timeout <<= 1;
if (timeout > NFS4_LOCK_MAXTIMEOUT)
return NFS4_LOCK_MAXTIMEOUT;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 9a11aa39e2e4..057aff745506 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -26,6 +26,7 @@
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/hash.h>
+#include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -221,6 +222,7 @@ static int expkey_show(struct seq_file *m,
}
struct cache_detail svc_expkey_cache = {
+ .owner = THIS_MODULE,
.hash_size = EXPKEY_HASHMAX,
.hash_table = expkey_table,
.name = "nfsd.fh",
@@ -456,6 +458,7 @@ static int svc_export_show(struct seq_file *m,
return 0;
}
struct cache_detail svc_export_cache = {
+ .owner = THIS_MODULE,
.hash_size = EXPORT_HASHMAX,
.hash_table = export_table,
.name = "nfsd.export",
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 5605a26efc57..13369650cdf9 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -187,6 +187,7 @@ static int idtoname_parse(struct cache_detail *, char *, int);
static struct ent *idtoname_lookup(struct ent *, int);
static struct cache_detail idtoname_cache = {
+ .owner = THIS_MODULE,
.hash_size = ENT_HASHMAX,
.hash_table = idtoname_table,
.name = "nfs4.idtoname",
@@ -320,6 +321,7 @@ static struct ent *nametoid_lookup(struct ent *, int);
static int nametoid_parse(struct cache_detail *, char *, int);
static struct cache_detail nametoid_cache = {
+ .owner = THIS_MODULE,
.hash_size = ENT_HASHMAX,
.hash_table = nametoid_table,
.name = "nfs4.nametoid",
@@ -404,8 +406,10 @@ nfsd_idmap_init(void)
void
nfsd_idmap_shutdown(void)
{
- cache_unregister(&idtoname_cache);
- cache_unregister(&nametoid_cache);
+ if (cache_unregister(&idtoname_cache))
+ printk(KERN_ERR "nfsd: failed to unregister idtoname cache\n");
+ if (cache_unregister(&nametoid_cache))
+ printk(KERN_ERR "nfsd: failed to unregister nametoid cache\n");
}
/*
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e08edc17c6a0..361b4007d4a0 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -162,7 +162,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
static inline int
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
{
int status;
dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -238,8 +238,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
*/
status = nfsd4_process_open2(rqstp, current_fh, open);
out:
- if (open->op_stateowner)
+ if (open->op_stateowner) {
nfs4_get_stateowner(open->op_stateowner);
+ *replay_owner = open->op_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -809,8 +811,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
break;
case OP_CLOSE:
- op->status = nfsd4_close(rqstp, current_fh, &op->u.close);
- replay_owner = op->u.close.cl_stateowner;
+ op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
break;
case OP_COMMIT:
op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
@@ -831,15 +832,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
break;
case OP_LOCK:
- op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock);
- replay_owner = op->u.lock.lk_stateowner;
+ op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
break;
case OP_LOCKT:
op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
break;
case OP_LOCKU:
- op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku);
- replay_owner = op->u.locku.lu_stateowner;
+ op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
@@ -853,16 +852,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfs_ok;
break;
case OP_OPEN:
- op->status = nfsd4_open(rqstp, current_fh, &op->u.open);
- replay_owner = op->u.open.op_stateowner;
+ op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
break;
case OP_OPEN_CONFIRM:
- op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm);
- replay_owner = op->u.open_confirm.oc_stateowner;
+ op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
break;
case OP_OPEN_DOWNGRADE:
- op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade);
- replay_owner = op->u.open_downgrade.od_stateowner;
+ op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
break;
case OP_PUTFH:
op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 57ed50fe7f85..954cf893d50c 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -93,7 +93,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
clname->len, clname->data);
- tfm = crypto_alloc_tfm("md5", 0);
+ tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL)
goto out;
cksum.len = crypto_tfm_alg_digestsize(tfm);
@@ -114,8 +114,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
kfree(cksum.data);
status = nfs_ok;
out:
- if (tfm)
- crypto_free_tfm(tfm);
+ crypto_free_tfm(tfm);
return status;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b83f8fb441e1..6bbefd06f10d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -624,7 +624,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
cb->cb_ident = se->se_callback_ident;
return;
out_err:
- printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
+ dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
"will not receive delegations\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
@@ -678,13 +678,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
int status;
char dname[HEXDIR_LEN];
- status = nfserr_inval;
if (!check_name(clname))
- goto out;
+ return nfserr_inval;
status = nfs4_make_rec_clidname(dname, &clname);
if (status)
- goto out;
+ return status;
/*
* XXX The Duplicate Request Cache (DRC) has been checked (??)
@@ -2014,7 +2013,7 @@ STALE_STATEID(stateid_t *stateid)
{
if (stateid->si_boot == boot_time)
return 0;
- printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
+ dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
return 1;
@@ -2275,7 +2274,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
check_replay:
if (seqid == sop->so_seqid - 1) {
- printk("NFSD: preprocess_seqid_op: retransmission?\n");
+ dprintk("NFSD: preprocess_seqid_op: retransmission?\n");
/* indicate replay to calling function */
return NFSERR_REPLAY_ME;
}
@@ -2286,7 +2285,7 @@ check_replay:
}
int
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateowner *sop;
@@ -2320,8 +2319,10 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
nfsd4_create_clid_dir(sop->so_client);
out:
- if (oc->oc_stateowner)
+ if (oc->oc_stateowner) {
nfs4_get_stateowner(oc->oc_stateowner);
+ *replay_owner = oc->oc_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2352,7 +2353,7 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
}
int
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
+nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateid *stp;
@@ -2394,8 +2395,10 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
status = nfs_ok;
out:
- if (od->od_stateowner)
+ if (od->od_stateowner) {
nfs4_get_stateowner(od->od_stateowner);
+ *replay_owner = od->od_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2404,7 +2407,7 @@ out:
* nfs4_unlock_state() called after encode
*/
int
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
+nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateid *stp;
@@ -2430,8 +2433,10 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
/* release_state_owner() calls nfsd_close() if needed */
release_state_owner(stp, OPEN_STATE);
out:
- if (close->cl_stateowner)
+ if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
+ *replay_owner = close->cl_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2500,8 +2505,7 @@ find_stateid(stateid_t *stid, int flags)
(local->st_stateid.si_fileid == f_id))
return local;
}
- } else
- printk("NFSD: find_stateid: ERROR: no state flag\n");
+ }
return NULL;
}
@@ -2624,7 +2628,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_is_open_owner = 0;
sop->so_id = current_ownerid++;
sop->so_client = clp;
- sop->so_seqid = lock->lk_new_lock_seqid;
+ /* It is the openowner seqid that will be incremented in encode in the
+ * case of new lockowners; so increment the lock seqid manually: */
+ sop->so_seqid = lock->lk_new_lock_seqid + 1;
sop->so_confirmed = 1;
rp = &sop->so_replay;
rp->rp_status = NFSERR_SERVERFAULT;
@@ -2676,9 +2682,10 @@ check_lock_length(u64 offset, u64 length)
* LOCK operation
*/
int
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
+nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
{
struct nfs4_stateowner *open_sop = NULL;
+ struct nfs4_stateowner *lock_sop = NULL;
struct nfs4_stateid *lock_stp;
struct file *filp;
struct file_lock file_lock;
@@ -2705,19 +2712,19 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
struct nfs4_file *fp;
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(&lock->lk_new_clientid)) {
- printk("NFSD: nfsd4_lock: clientid is stale!\n");
+ if (STALE_CLIENTID(&lock->lk_new_clientid))
goto out;
- }
/* validate and update open stateid and open seqid */
status = nfs4_preprocess_seqid_op(current_fh,
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
- &open_sop, &open_stp, lock);
+ &lock->lk_stateowner, &open_stp,
+ lock);
if (status)
goto out;
+ open_sop = lock->lk_stateowner;
/* create lockowner and lock stateid */
fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2727,16 +2734,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* the same file, or should they just be allowed (and
* create new stateids)? */
status = nfserr_resource;
- if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
+ lock_sop = alloc_init_lock_stateowner(strhashval,
+ open_sop->so_client, open_stp, lock);
+ if (lock_sop == NULL)
goto out;
- if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner,
- fp, open_stp)) == NULL) {
- release_stateowner(lock->lk_stateowner);
- lock->lk_stateowner = NULL;
+ lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
+ if (lock_stp == NULL) {
+ release_stateowner(lock_sop);
goto out;
}
- /* bump the open seqid used to create the lock */
- open_sop->so_seqid++;
} else {
/* lock (lock owner + lock stateid) already exists */
status = nfs4_preprocess_seqid_op(current_fh,
@@ -2746,12 +2752,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
&lock->lk_stateowner, &lock_stp, lock);
if (status)
goto out;
+ lock_sop = lock->lk_stateowner;
}
/* lock->lk_stateowner and lock_stp have been created or found */
filp = lock_stp->st_vfs_file;
if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
- printk("NFSD: nfsd4_lock: permission denied!\n");
+ dprintk("NFSD: nfsd4_lock: permission denied!\n");
goto out;
}
@@ -2776,7 +2783,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
status = nfserr_inval;
goto out;
}
- file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
+ file_lock.fl_owner = (fl_owner_t)lock_sop;
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
@@ -2832,14 +2839,13 @@ out_destroy_new_stateid:
* An error encountered after instantiation of the new
* stateid has forced us to destroy it.
*/
- if (!seqid_mutating_err(status))
- open_sop->so_seqid--;
-
release_state_owner(lock_stp, LOCK_STATE);
}
out:
- if (lock->lk_stateowner)
+ if (lock->lk_stateowner) {
nfs4_get_stateowner(lock->lk_stateowner);
+ *replay_owner = lock->lk_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2866,13 +2872,11 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
nfs4_lock_state();
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(&lockt->lt_clientid)) {
- printk("NFSD: nfsd4_lockt: clientid is stale!\n");
+ if (STALE_CLIENTID(&lockt->lt_clientid))
goto out;
- }
if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
- printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
+ dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
if (status == nfserr_symlink)
status = nfserr_inval;
goto out;
@@ -2930,7 +2934,7 @@ out:
}
int
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
+nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
{
struct nfs4_stateid *stp;
struct file *filp = NULL;
@@ -2976,7 +2980,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
file_lock.fl_ops->fl_release_private(&file_lock);
if (status) {
- printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
+ dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
goto out_nfserr;
}
/*
@@ -2986,8 +2990,10 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
out:
- if (locku->lu_stateowner)
+ if (locku->lu_stateowner) {
nfs4_get_stateowner(locku->lu_stateowner);
+ *replay_owner = locku->lu_stateowner;
+ }
nfs4_unlock_state();
return status;
@@ -3036,10 +3042,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
/* XXX check for lease expiration */
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(clid)) {
- printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n");
+ if (STALE_CLIENTID(clid))
return status;
- }
nfs4_lock_state();
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 9eecc9939dfe..49eafbdb15c1 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -22,6 +22,77 @@ ToDo/Notes:
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
+2.1.24 - Lots of bug fixes and support more clean journal states.
+
+ - Support journals ($LogFile) which have been modified by chkdsk. This
+ means users can boot into Windows after we marked the volume dirty.
+ The Windows boot will run chkdsk and then reboot. The user can then
+ immediately boot into Linux rather than having to do a full Windows
+ boot first before rebooting into Linux and we will recognize such a
+ journal and empty it as it is clean by definition.
+ - Support journals ($LogFile) with only one restart page as well as
+ journals with two different restart pages. We sanity check both and
+ either use the only sane one or the more recent one of the two in the
+ case that both are valid.
+ - Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
+ ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
+ hence cannot fail.
+ - Use ntfs_malloc_nofs_nofail() in the two critical regions in
+ fs/ntfs/runlist.c::ntfs_runlists_merge(). This means we no longer
+ need to panic() if the allocation fails as it now cannot fail.
+ - Fix two nasty runlist merging bugs that had gone unnoticed so far.
+ Thanks to Stefano Picerno for the bug report.
+ - Remove two bogus BUG_ON()s from fs/ntfs/mft.c.
+ - Fix handling of valid but empty mapping pairs array in
+ fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress().
+ - Report unrepresentable inodes during ntfs_readdir() as KERN_WARNING
+ messages and include the inode number. Thanks to Yura Pakhuchiy for
+ pointing this out.
+ - Change ntfs_rl_truncate_nolock() to throw away the runlist if the new
+ length is zero.
+ - Add runlist.[hc]::ntfs_rl_punch_nolock() which punches a caller
+ specified hole into a runlist.
+ - Fix a bug in fs/ntfs/index.c::ntfs_index_lookup(). When the returned
+ index entry is in the index root, we forgot to set the @ir pointer in
+ the index context. Thanks to Yura Pakhuchiy for finding this bug.
+ - Remove bogus setting of PageError in ntfs_read_compressed_block().
+ - Add fs/ntfs/attrib.[hc]::ntfs_resident_attr_value_resize().
+ - Fix a bug in ntfs_map_runlist_nolock() where we forgot to protect
+ access to the allocated size in the ntfs inode with the size lock.
+ - Fix ntfs_attr_vcn_to_lcn_nolock() and ntfs_attr_find_vcn_nolock() to
+ return LCN_ENOENT when there is no runlist and the allocated size is
+ zero.
+ - Fix load_attribute_list() to handle the case of a NULL runlist.
+ - Fix handling of sparse attributes in ntfs_attr_make_non_resident().
+ - Add BUG() checks to ntfs_attr_make_non_resident() and ntfs_attr_set()
+ to ensure that these functions are never called for compressed or
+ encrypted attributes.
+ - Fix cluster (de)allocators to work when the runlist is NULL and more
+ importantly to take a locked runlist rather than them locking it
+ which leads to lock reversal.
+ - Truncate {a,c,m}time to the ntfs supported time granularity when
+ updating the times in the inode in ntfs_setattr().
+ - Fixup handling of sparse, compressed, and encrypted attributes in
+ fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode(),
+ fs/ntfs/aops.c::ntfs_{read,write}page().
+ - Make ntfs_write_block() not instantiate sparse blocks if they contain
+ only zeroes.
+ - Optimize fs/ntfs/aops.c::ntfs_write_block() by extending the page
+ lock protection over the buffer submission for i/o which allows the
+ removal of the get_bh()/put_bh() pairs for each buffer.
+ - Fix fs/ntfs/aops.c::ntfs_{read,write}_block() to handle the case
+ where a concurrent truncate has truncated the runlist under our feet.
+ - Fix page_has_buffers()/page_buffers() handling in fs/ntfs/aops.c.
+ - In fs/ntfs/aops.c::ntfs_end_buffer_async_read(), use a bit spin lock
+ in the first buffer head instead of a driver global spin lock to
+ improve scalability.
+ - Minor fix to error handling and error message display in
+ fs/ntfs/aops.c::ntfs_prepare_nonresident_write().
+ - Change the mount options {u,f,d}mask to always parse the number as
+ an octal number to conform to how chmod(1) works, too. Thanks to
+ Giuseppe Bilotta and Horst von Brand for pointing out the errors of
+ my ways.
+
2.1.23 - Implement extension of resident files and make writing safe as well as
many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index f083f27d8b69..894b2b876d35 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
unistr.o upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.23\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.24\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 78adad7a988d..b6cc8cf24626 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -27,6 +27,7 @@
#include <linux/swap.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
+#include <linux/bit_spinlock.h>
#include "aops.h"
#include "attrib.h"
@@ -55,9 +56,8 @@
*/
static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
{
- static DEFINE_SPINLOCK(page_uptodate_lock);
unsigned long flags;
- struct buffer_head *tmp;
+ struct buffer_head *first, *tmp;
struct page *page;
ntfs_inode *ni;
int page_uptodate = 1;
@@ -89,11 +89,13 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
}
} else {
clear_buffer_uptodate(bh);
+ SetPageError(page);
ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.",
(unsigned long long)bh->b_blocknr);
- SetPageError(page);
}
- spin_lock_irqsave(&page_uptodate_lock, flags);
+ first = page_buffers(page);
+ local_irq_save(flags);
+ bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
clear_buffer_async_read(bh);
unlock_buffer(bh);
tmp = bh;
@@ -108,7 +110,8 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
}
tmp = tmp->b_this_page;
} while (tmp != bh);
- spin_unlock_irqrestore(&page_uptodate_lock, flags);
+ bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+ local_irq_restore(flags);
/*
* If none of the buffers had errors then we can set the page uptodate,
* but we first have to perform the post read mst fixups, if the
@@ -141,7 +144,8 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
unlock_page(page);
return;
still_busy:
- spin_unlock_irqrestore(&page_uptodate_lock, flags);
+ bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+ local_irq_restore(flags);
return;
}
@@ -185,13 +189,15 @@ static int ntfs_read_block(struct page *page)
blocksize_bits = VFS_I(ni)->i_blkbits;
blocksize = 1 << blocksize_bits;
- if (!page_has_buffers(page))
+ if (!page_has_buffers(page)) {
create_empty_buffers(page, blocksize, 0);
- bh = head = page_buffers(page);
- if (unlikely(!bh)) {
- unlock_page(page);
- return -ENOMEM;
+ if (unlikely(!page_has_buffers(page))) {
+ unlock_page(page);
+ return -ENOMEM;
+ }
}
+ bh = head = page_buffers(page);
+ BUG_ON(!bh);
iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
read_lock_irqsave(&ni->size_lock, flags);
@@ -204,6 +210,7 @@ static int ntfs_read_block(struct page *page)
nr = i = 0;
do {
u8 *kaddr;
+ int err;
if (unlikely(buffer_uptodate(bh)))
continue;
@@ -211,6 +218,7 @@ static int ntfs_read_block(struct page *page)
arr[nr++] = bh;
continue;
}
+ err = 0;
bh->b_bdev = vol->sb->s_bdev;
/* Is the block within the allowed limits? */
if (iblock < lblock) {
@@ -252,7 +260,6 @@ lock_retry_remap:
goto handle_hole;
/* If first try and runlist unmapped, map and retry. */
if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
- int err;
is_retry = TRUE;
/*
* Attempt to map runlist, dropping lock for
@@ -263,20 +270,30 @@ lock_retry_remap:
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
- lcn = err;
} else if (!rl)
up_read(&ni->runlist.lock);
+ /*
+ * If buffer is outside the runlist, treat it as a
+ * hole. This can happen due to concurrent truncate
+ * for example.
+ */
+ if (err == -ENOENT || lcn == LCN_ENOENT) {
+ err = 0;
+ goto handle_hole;
+ }
/* Hard error, zero out region. */
+ if (!err)
+ err = -EIO;
bh->b_blocknr = -1;
SetPageError(page);
ntfs_error(vol->sb, "Failed to read from inode 0x%lx, "
"attribute type 0x%x, vcn 0x%llx, "
"offset 0x%x because its location on "
"disk could not be determined%s "
- "(error code %lli).", ni->mft_no,
+ "(error code %i).", ni->mft_no,
ni->type, (unsigned long long)vcn,
vcn_ofs, is_retry ? " even after "
- "retrying" : "", (long long)lcn);
+ "retrying" : "", err);
}
/*
* Either iblock was outside lblock limits or
@@ -289,9 +306,10 @@ handle_hole:
handle_zblock:
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr + i * blocksize, 0, blocksize);
- flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
- set_buffer_uptodate(bh);
+ flush_dcache_page(page);
+ if (likely(!err))
+ set_buffer_uptodate(bh);
} while (i++, iblock++, (bh = bh->b_this_page) != head);
/* Release the lock if we took it. */
@@ -367,31 +385,38 @@ retry_readpage:
return 0;
}
ni = NTFS_I(page->mapping->host);
-
+ /*
+ * Only $DATA attributes can be encrypted and only unnamed $DATA
+ * attributes can be compressed. Index root can have the flags set but
+ * this means to create compressed/encrypted files, not that the
+ * attribute is compressed/encrypted.
+ */
+ if (ni->type != AT_INDEX_ROOT) {
+ /* If attribute is encrypted, deny access, just like NT4. */
+ if (NInoEncrypted(ni)) {
+ BUG_ON(ni->type != AT_DATA);
+ err = -EACCES;
+ goto err_out;
+ }
+ /* Compressed data streams are handled in compress.c. */
+ if (NInoNonResident(ni) && NInoCompressed(ni)) {
+ BUG_ON(ni->type != AT_DATA);
+ BUG_ON(ni->name_len);
+ return ntfs_read_compressed_block(page);
+ }
+ }
/* NInoNonResident() == NInoIndexAllocPresent() */
if (NInoNonResident(ni)) {
- /*
- * Only unnamed $DATA attributes can be compressed or
- * encrypted.
- */
- if (ni->type == AT_DATA && !ni->name_len) {
- /* If file is encrypted, deny access, just like NT4. */
- if (NInoEncrypted(ni)) {
- err = -EACCES;
- goto err_out;
- }
- /* Compressed data streams are handled in compress.c. */
- if (NInoCompressed(ni))
- return ntfs_read_compressed_block(page);
- }
- /* Normal data stream. */
+ /* Normal, non-resident data stream. */
return ntfs_read_block(page);
}
/*
* Attribute is resident, implying it is not compressed or encrypted.
* This also means the attribute is smaller than an mft record and
* hence smaller than a page, so can simply zero out any pages with
- * index above 0.
+ * index above 0. Note the attribute can actually be marked compressed
+ * but if it is resident the actual data is not compressed so we are
+ * ok to ignore the compressed flag here.
*/
if (unlikely(page->index > 0)) {
kaddr = kmap_atomic(page, KM_USER0);
@@ -511,19 +536,21 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
BUG_ON(!PageUptodate(page));
create_empty_buffers(page, blocksize,
(1 << BH_Uptodate) | (1 << BH_Dirty));
+ if (unlikely(!page_has_buffers(page))) {
+ ntfs_warning(vol->sb, "Error allocating page "
+ "buffers. Redirtying page so we try "
+ "again later.");
+ /*
+ * Put the page back on mapping->dirty_pages, but leave
+ * its buffers' dirty state as-is.
+ */
+ redirty_page_for_writepage(wbc, page);
+ unlock_page(page);
+ return 0;
+ }
}
bh = head = page_buffers(page);
- if (unlikely(!bh)) {
- ntfs_warning(vol->sb, "Error allocating page buffers. "
- "Redirtying page so we try again later.");
- /*
- * Put the page back on mapping->dirty_pages, but leave its
- * buffer's dirty state as-is.
- */
- redirty_page_for_writepage(wbc, page);
- unlock_page(page);
- return 0;
- }
+ BUG_ON(!bh);
/* NOTE: Different naming scheme to ntfs_read_block()! */
@@ -670,6 +697,27 @@ lock_retry_remap:
}
/* It is a hole, need to instantiate it. */
if (lcn == LCN_HOLE) {
+ u8 *kaddr;
+ unsigned long *bpos, *bend;
+
+ /* Check if the buffer is zero. */
+ kaddr = kmap_atomic(page, KM_USER0);
+ bpos = (unsigned long *)(kaddr + bh_offset(bh));
+ bend = (unsigned long *)((u8*)bpos + blocksize);
+ do {
+ if (unlikely(*bpos))
+ break;
+ } while (likely(++bpos < bend));
+ kunmap_atomic(kaddr, KM_USER0);
+ if (bpos == bend) {
+ /*
+ * Buffer is zero and sparse, no need to write
+ * it.
+ */
+ bh->b_blocknr = -1;
+ clear_buffer_dirty(bh);
+ continue;
+ }
// TODO: Instantiate the hole.
// clear_buffer_new(bh);
// unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
@@ -690,20 +738,37 @@ lock_retry_remap:
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
- lcn = err;
} else if (!rl)
up_read(&ni->runlist.lock);
+ /*
+ * If buffer is outside the runlist, truncate has cut it out
+ * of the runlist. Just clean and clear the buffer and set it
+ * uptodate so it can get discarded by the VM.
+ */
+ if (err == -ENOENT || lcn == LCN_ENOENT) {
+ u8 *kaddr;
+
+ bh->b_blocknr = -1;
+ clear_buffer_dirty(bh);
+ kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + bh_offset(bh), 0, blocksize);
+ kunmap_atomic(kaddr, KM_USER0);
+ flush_dcache_page(page);
+ set_buffer_uptodate(bh);
+ err = 0;
+ continue;
+ }
/* Failed to map the buffer, even after retrying. */
+ if (!err)
+ err = -EIO;
bh->b_blocknr = -1;
ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
"attribute type 0x%x, vcn 0x%llx, offset 0x%x "
"because its location on disk could not be "
- "determined%s (error code %lli).", ni->mft_no,
+ "determined%s (error code %i).", ni->mft_no,
ni->type, (unsigned long long)vcn,
vcn_ofs, is_retry ? " even after "
- "retrying" : "", (long long)lcn);
- if (!err)
- err = -EIO;
+ "retrying" : "", err);
break;
} while (block++, (bh = bh->b_this_page) != head);
@@ -714,7 +779,7 @@ lock_retry_remap:
/* For the error case, need to reset bh to the beginning. */
bh = head;
- /* Just an optimization, so ->readpage() isn't called later. */
+ /* Just an optimization, so ->readpage() is not called later. */
if (unlikely(!PageUptodate(page))) {
int uptodate = 1;
do {
@@ -730,7 +795,6 @@ lock_retry_remap:
/* Setup all mapped, dirty buffers for async write i/o. */
do {
- get_bh(bh);
if (buffer_mapped(bh) && buffer_dirty(bh)) {
lock_buffer(bh);
if (test_clear_buffer_dirty(bh)) {
@@ -768,14 +832,8 @@ lock_retry_remap:
BUG_ON(PageWriteback(page));
set_page_writeback(page); /* Keeps try_to_free_buffers() away. */
- unlock_page(page);
- /*
- * Submit the prepared buffers for i/o. Note the page is unlocked,
- * and the async write i/o completion handler can end_page_writeback()
- * at any time after the *first* submit_bh(). So the buffers can then
- * disappear...
- */
+ /* Submit the prepared buffers for i/o. */
need_end_writeback = TRUE;
do {
struct buffer_head *next = bh->b_this_page;
@@ -783,9 +841,9 @@ lock_retry_remap:
submit_bh(WRITE, bh);
need_end_writeback = FALSE;
}
- put_bh(bh);
bh = next;
} while (bh != head);
+ unlock_page(page);
/* If no i/o was started, need to end_page_writeback(). */
if (unlikely(need_end_writeback))
@@ -860,7 +918,6 @@ static int ntfs_write_mst_block(struct page *page,
sync = (wbc->sync_mode == WB_SYNC_ALL);
/* Make sure we have mapped buffers. */
- BUG_ON(!page_has_buffers(page));
bh = head = page_buffers(page);
BUG_ON(!bh);
@@ -1280,38 +1337,42 @@ retry_writepage:
ntfs_debug("Write outside i_size - truncated?");
return 0;
}
+ /*
+ * Only $DATA attributes can be encrypted and only unnamed $DATA
+ * attributes can be compressed. Index root can have the flags set but
+ * this means to create compressed/encrypted files, not that the
+ * attribute is compressed/encrypted.
+ */
+ if (ni->type != AT_INDEX_ROOT) {
+ /* If file is encrypted, deny access, just like NT4. */
+ if (NInoEncrypted(ni)) {
+ unlock_page(page);
+ BUG_ON(ni->type != AT_DATA);
+ ntfs_debug("Denying write access to encrypted "
+ "file.");
+ return -EACCES;
+ }
+ /* Compressed data streams are handled in compress.c. */
+ if (NInoNonResident(ni) && NInoCompressed(ni)) {
+ BUG_ON(ni->type != AT_DATA);
+ BUG_ON(ni->name_len);
+ // TODO: Implement and replace this with
+ // return ntfs_write_compressed_block(page);
+ unlock_page(page);
+ ntfs_error(vi->i_sb, "Writing to compressed files is "
+ "not supported yet. Sorry.");
+ return -EOPNOTSUPP;
+ }
+ // TODO: Implement and remove this check.
+ if (NInoNonResident(ni) && NInoSparse(ni)) {
+ unlock_page(page);
+ ntfs_error(vi->i_sb, "Writing to sparse files is not "
+ "supported yet. Sorry.");
+ return -EOPNOTSUPP;
+ }
+ }
/* NInoNonResident() == NInoIndexAllocPresent() */
if (NInoNonResident(ni)) {
- /*
- * Only unnamed $DATA attributes can be compressed, encrypted,
- * and/or sparse.
- */
- if (ni->type == AT_DATA && !ni->name_len) {
- /* If file is encrypted, deny access, just like NT4. */
- if (NInoEncrypted(ni)) {
- unlock_page(page);
- ntfs_debug("Denying write access to encrypted "
- "file.");
- return -EACCES;
- }
- /* Compressed data streams are handled in compress.c. */
- if (NInoCompressed(ni)) {
- // TODO: Implement and replace this check with
- // return ntfs_write_compressed_block(page);
- unlock_page(page);
- ntfs_error(vi->i_sb, "Writing to compressed "
- "files is not supported yet. "
- "Sorry.");
- return -EOPNOTSUPP;
- }
- // TODO: Implement and remove this check.
- if (NInoSparse(ni)) {
- unlock_page(page);
- ntfs_error(vi->i_sb, "Writing to sparse files "
- "is not supported yet. Sorry.");
- return -EOPNOTSUPP;
- }
- }
/* We have to zero every time due to mmap-at-end-of-file. */
if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) {
/* The page straddles i_size. */
@@ -1324,14 +1385,16 @@ retry_writepage:
/* Handle mst protected attributes. */
if (NInoMstProtected(ni))
return ntfs_write_mst_block(page, wbc);
- /* Normal data stream. */
+ /* Normal, non-resident data stream. */
return ntfs_write_block(page, wbc);
}
/*
- * Attribute is resident, implying it is not compressed, encrypted,
- * sparse, or mst protected. This also means the attribute is smaller
- * than an mft record and hence smaller than a page, so can simply
- * return error on any pages with index above 0.
+ * Attribute is resident, implying it is not compressed, encrypted, or
+ * mst protected. This also means the attribute is smaller than an mft
+ * record and hence smaller than a page, so can simply return error on
+ * any pages with index above 0. Note the attribute can actually be
+ * marked compressed but if it is resident the actual data is not
+ * compressed so we are ok to ignore the compressed flag here.
*/
BUG_ON(page_has_buffers(page));
BUG_ON(!PageUptodate(page));
@@ -1380,30 +1443,14 @@ retry_writepage:
BUG_ON(PageWriteback(page));
set_page_writeback(page);
unlock_page(page);
-
/*
- * Here, we don't need to zero the out of bounds area everytime because
- * the below memcpy() already takes care of the mmap-at-end-of-file
- * requirements. If the file is converted to a non-resident one, then
- * the code path use is switched to the non-resident one where the
- * zeroing happens on each ntfs_writepage() invocation.
- *
- * The above also applies nicely when i_size is decreased.
- *
- * When i_size is increased, the memory between the old and new i_size
- * _must_ be zeroed (or overwritten with new data). Otherwise we will
- * expose data to userspace/disk which should never have been exposed.
- *
- * FIXME: Ensure that i_size increases do the zeroing/overwriting and
- * if we cannot guarantee that, then enable the zeroing below. If the
- * zeroing below is enabled, we MUST move the unlock_page() from above
- * to after the kunmap_atomic(), i.e. just before the
- * end_page_writeback().
- * UPDATE: ntfs_prepare/commit_write() do the zeroing on i_size
- * increases for resident attributes so those are ok.
- * TODO: ntfs_truncate(), others?
+ * Here, we do not need to zero the out of bounds area everytime
+ * because the below memcpy() already takes care of the
+ * mmap-at-end-of-file requirements. If the file is converted to a
+ * non-resident one, then the code path use is switched to the
+ * non-resident one where the zeroing happens on each ntfs_writepage()
+ * invocation.
*/
-
attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
i_size = i_size_read(vi);
if (unlikely(attr_len > i_size)) {
@@ -1681,27 +1728,25 @@ lock_retry_remap:
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
- lcn = err;
} else if (!rl)
up_read(&ni->runlist.lock);
/*
* Failed to map the buffer, even after
* retrying.
*/
+ if (!err)
+ err = -EIO;
bh->b_blocknr = -1;
ntfs_error(vol->sb, "Failed to write to inode "
"0x%lx, attribute type 0x%x, "
"vcn 0x%llx, offset 0x%x "
"because its location on disk "
"could not be determined%s "
- "(error code %lli).",
+ "(error code %i).",
ni->mft_no, ni->type,
(unsigned long long)vcn,
vcn_ofs, is_retry ? " even "
- "after retrying" : "",
- (long long)lcn);
- if (!err)
- err = -EIO;
+ "after retrying" : "", err);
goto err_out;
}
/* We now have a successful remap, i.e. lcn >= 0. */
@@ -2357,6 +2402,7 @@ void mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) {
buffers_to_free = bh;
}
bh = head = page_buffers(page);
+ BUG_ON(!bh);
do {
bh_ofs = bh_offset(bh);
if (bh_ofs + bh_size <= ofs)
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index cd0f9e740b14..3f9a4ff42ee5 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -43,6 +43,9 @@
* which is not an error as such. This is -ENOENT. It means that @vcn is out
* of bounds of the runlist.
*
+ * Note the runlist can be NULL after this function returns if @vcn is zero and
+ * the attribute has zero allocated size, i.e. there simply is no runlist.
+ *
* Locking: - The runlist must be locked for writing.
* - This function modifies the runlist.
*/
@@ -54,6 +57,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
ATTR_RECORD *a;
ntfs_attr_search_ctx *ctx;
runlist_element *rl;
+ unsigned long flags;
int err = 0;
ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
@@ -85,8 +89,11 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
* ntfs_mapping_pairs_decompress() fails.
*/
end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1;
- if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1))
+ if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1)) {
+ read_lock_irqsave(&ni->size_lock, flags);
end_vcn = ni->allocated_size >> ni->vol->cluster_size_bits;
+ read_unlock_irqrestore(&ni->size_lock, flags);
+ }
if (unlikely(vcn >= end_vcn)) {
err = -ENOENT;
goto err_out;
@@ -165,6 +172,7 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
const BOOL write_locked)
{
LCN lcn;
+ unsigned long flags;
BOOL is_retry = FALSE;
ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
@@ -173,6 +181,14 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
BUG_ON(!ni);
BUG_ON(!NInoNonResident(ni));
BUG_ON(vcn < 0);
+ if (!ni->runlist.rl) {
+ read_lock_irqsave(&ni->size_lock, flags);
+ if (!ni->allocated_size) {
+ read_unlock_irqrestore(&ni->size_lock, flags);
+ return LCN_ENOENT;
+ }
+ read_unlock_irqrestore(&ni->size_lock, flags);
+ }
retry_remap:
/* Convert vcn to lcn. If that fails map the runlist and retry once. */
lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn);
@@ -255,6 +271,7 @@ retry_remap:
runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
const BOOL write_locked)
{
+ unsigned long flags;
runlist_element *rl;
int err = 0;
BOOL is_retry = FALSE;
@@ -265,6 +282,14 @@ runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
BUG_ON(!ni);
BUG_ON(!NInoNonResident(ni));
BUG_ON(vcn < 0);
+ if (!ni->runlist.rl) {
+ read_lock_irqsave(&ni->size_lock, flags);
+ if (!ni->allocated_size) {
+ read_unlock_irqrestore(&ni->size_lock, flags);
+ return ERR_PTR(-ENOENT);
+ }
+ read_unlock_irqrestore(&ni->size_lock, flags);
+ }
retry_remap:
rl = ni->runlist.rl;
if (likely(rl && vcn >= rl[0].vcn)) {
@@ -528,6 +553,11 @@ int load_attribute_list(ntfs_volume *vol, runlist *runlist, u8 *al_start,
block_size_bits = sb->s_blocksize_bits;
down_read(&runlist->lock);
rl = runlist->rl;
+ if (!rl) {
+ ntfs_error(sb, "Cannot read attribute list since runlist is "
+ "missing.");
+ goto err_out;
+ }
/* Read all clusters specified by the runlist one run at a time. */
while (rl->length) {
lcn = ntfs_rl_vcn_to_lcn(rl, rl->vcn);
@@ -1247,6 +1277,46 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
}
/**
+ * ntfs_resident_attr_value_resize - resize the value of a resident attribute
+ * @m: mft record containing attribute record
+ * @a: attribute record whose value to resize
+ * @new_size: new size in bytes to which to resize the attribute value of @a
+ *
+ * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
+ * If the value is made bigger, the newly allocated space is cleared.
+ *
+ * Return 0 on success and -errno on error. The following error codes are
+ * defined:
+ * -ENOSPC - Not enough space in the mft record @m to perform the resize.
+ *
+ * Note: On error, no modifications have been performed whatsoever.
+ *
+ * Warning: If you make a record smaller without having copied all the data you
+ * are interested in the data may be overwritten.
+ */
+int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
+ const u32 new_size)
+{
+ u32 old_size;
+
+ /* Resize the resident part of the attribute record. */
+ if (ntfs_attr_record_resize(m, a,
+ le16_to_cpu(a->data.resident.value_offset) + new_size))
+ return -ENOSPC;
+ /*
+ * The resize succeeded! If we made the attribute value bigger, clear
+ * the area between the old size and @new_size.
+ */
+ old_size = le32_to_cpu(a->data.resident.value_length);
+ if (new_size > old_size)
+ memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) +
+ old_size, 0, new_size - old_size);
+ /* Finally update the length of the attribute value. */
+ a->data.resident.value_length = cpu_to_le32(new_size);
+ return 0;
+}
+
+/**
* ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
* @ni: ntfs inode describing the attribute to convert
*
@@ -1302,6 +1372,12 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
return err;
}
/*
+ * FIXME: Compressed and encrypted attributes are not supported when
+ * writing and we should never have gotten here for them.
+ */
+ BUG_ON(NInoCompressed(ni));
+ BUG_ON(NInoEncrypted(ni));
+ /*
* The size needs to be aligned to a cluster boundary for allocation
* purposes.
*/
@@ -1377,10 +1453,15 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
BUG_ON(a->non_resident);
/*
* Calculate new offsets for the name and the mapping pairs array.
- * We assume the attribute is not compressed or sparse.
*/
- name_ofs = (offsetof(ATTR_REC,
- data.non_resident.compressed_size) + 7) & ~7;
+ if (NInoSparse(ni) || NInoCompressed(ni))
+ name_ofs = (offsetof(ATTR_REC,
+ data.non_resident.compressed_size) +
+ sizeof(a->data.non_resident.compressed_size) +
+ 7) & ~7;
+ else
+ name_ofs = (offsetof(ATTR_REC,
+ data.non_resident.compressed_size) + 7) & ~7;
mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
/*
* Determine the size of the resident part of the now non-resident
@@ -1419,24 +1500,23 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
a->name_length * sizeof(ntfschar));
a->name_offset = cpu_to_le16(name_ofs);
- /*
- * FIXME: For now just clear all of these as we do not support them
- * when writing.
- */
- a->flags &= cpu_to_le16(0xffff & ~le16_to_cpu(ATTR_IS_SPARSE |
- ATTR_IS_ENCRYPTED | ATTR_COMPRESSION_MASK));
/* Setup the fields specific to non-resident attributes. */
a->data.non_resident.lowest_vcn = 0;
a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >>
vol->cluster_size_bits);
a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs);
- a->data.non_resident.compression_unit = 0;
memset(&a->data.non_resident.reserved, 0,
sizeof(a->data.non_resident.reserved));
a->data.non_resident.allocated_size = cpu_to_sle64(new_size);
a->data.non_resident.data_size =
a->data.non_resident.initialized_size =
cpu_to_sle64(attr_size);
+ if (NInoSparse(ni) || NInoCompressed(ni)) {
+ a->data.non_resident.compression_unit = 4;
+ a->data.non_resident.compressed_size =
+ a->data.non_resident.allocated_size;
+ } else
+ a->data.non_resident.compression_unit = 0;
/* Generate the mapping pairs array into the attribute record. */
err = ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs,
arec_size - mp_ofs, rl, 0, -1, NULL);
@@ -1446,16 +1526,19 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
goto undo_err_out;
}
/* Setup the in-memory attribute structure to be non-resident. */
- /*
- * FIXME: For now just clear all of these as we do not support them
- * when writing.
- */
- NInoClearSparse(ni);
- NInoClearEncrypted(ni);
- NInoClearCompressed(ni);
ni->runlist.rl = rl;
write_lock_irqsave(&ni->size_lock, flags);
ni->allocated_size = new_size;
+ if (NInoSparse(ni) || NInoCompressed(ni)) {
+ ni->itype.compressed.size = ni->allocated_size;
+ ni->itype.compressed.block_size = 1U <<
+ (a->data.non_resident.compression_unit +
+ vol->cluster_size_bits);
+ ni->itype.compressed.block_size_bits =
+ ffs(ni->itype.compressed.block_size) - 1;
+ ni->itype.compressed.block_clusters = 1U <<
+ a->data.non_resident.compression_unit;
+ }
write_unlock_irqrestore(&ni->size_lock, flags);
/*
* This needs to be last since the address space operations ->readpage
@@ -1603,6 +1686,12 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
BUG_ON(cnt < 0);
if (!cnt)
goto done;
+ /*
+ * FIXME: Compressed and encrypted attributes are not supported when
+ * writing and we should never have gotten here for them.
+ */
+ BUG_ON(NInoCompressed(ni));
+ BUG_ON(NInoEncrypted(ni));
mapping = VFS_I(ni)->i_mapping;
/* Work out the starting index and page offset. */
idx = ofs >> PAGE_CACHE_SHIFT;
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
index 0e4ac6d3c0e7..0618ed6fd7b3 100644
--- a/fs/ntfs/attrib.h
+++ b/fs/ntfs/attrib.h
@@ -99,6 +99,8 @@ extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
const ATTR_TYPE type);
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
+extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
+ const u32 new_size);
extern int ntfs_attr_make_non_resident(ntfs_inode *ni);
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index 6d265cfd49aa..25d24106f893 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -539,7 +539,6 @@ int ntfs_read_compressed_block(struct page *page)
if (unlikely(!pages || !bhs)) {
kfree(bhs);
kfree(pages);
- SetPageError(page);
unlock_page(page);
ntfs_error(vol->sb, "Failed to allocate internal buffers.");
return -ENOMEM;
@@ -871,9 +870,6 @@ lock_retry_remap:
for (; prev_cur_page < cur_page; prev_cur_page++) {
page = pages[prev_cur_page];
if (page) {
- if (prev_cur_page == xpage &&
- !xpage_done)
- SetPageError(page);
flush_dcache_page(page);
kunmap(page);
unlock_page(page);
@@ -904,8 +900,6 @@ lock_retry_remap:
"Terminating them with extreme "
"prejudice. Inode 0x%lx, page index "
"0x%lx.", ni->mft_no, page->index);
- if (cur_page == xpage && !xpage_done)
- SetPageError(page);
flush_dcache_page(page);
kunmap(page);
unlock_page(page);
@@ -953,8 +947,6 @@ err_out:
for (i = cur_page; i < max_page; i++) {
page = pages[i];
if (page) {
- if (i == xpage && !xpage_done)
- SetPageError(page);
flush_dcache_page(page);
kunmap(page);
unlock_page(page);
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 46779471c542..795c3d1930f5 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1051,7 +1051,8 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
ie->key.file_name.file_name_length, &name,
NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1);
if (name_len <= 0) {
- ntfs_debug("Skipping unrepresentable file.");
+ ntfs_warning(vol->sb, "Skipping unrepresentable inode 0x%llx.",
+ (long long)MREF_LE(ie->data.dir.indexed_file));
return 0;
}
if (ie->key.file_name.file_attributes &
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index e0f530ce6b99..be9fd1dd423d 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -1,7 +1,7 @@
/*
- * file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
+ * file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2005 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -94,6 +94,11 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
if (!datasync || !NInoNonResident(NTFS_I(vi)))
ret = ntfs_write_inode(vi, 1);
write_inode_now(vi, !datasync);
+ /*
+ * NOTE: If we were to use mapping->private_list (see ext2 and
+ * fs/buffer.c) for dirty blocks then we could optimize the below to be
+ * sync_mapping_buffers(vi->i_mapping).
+ */
err = sync_blockdev(vi->i_sb->s_bdev);
if (unlikely(err && !ret))
ret = err;
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index 11fd5307d780..8f2d5727546f 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -205,6 +205,7 @@ int ntfs_index_lookup(const void *key, const int key_len,
&ie->key, key_len)) {
ir_done:
ictx->is_in_root = TRUE;
+ ictx->ir = ir;
ictx->actx = actx;
ictx->base_ni = base_ni;
ictx->ia = NULL;
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 886214a77f90..dc4bbe3acf5c 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1013,41 +1013,50 @@ skip_large_dir_stuff:
}
a = ctx->attr;
/* Setup the state. */
- if (a->non_resident) {
- NInoSetNonResident(ni);
- if (a->flags & (ATTR_COMPRESSION_MASK |
- ATTR_IS_SPARSE)) {
- if (a->flags & ATTR_COMPRESSION_MASK) {
- NInoSetCompressed(ni);
- if (vol->cluster_size > 4096) {
- ntfs_error(vi->i_sb, "Found "
+ if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
+ if (a->flags & ATTR_COMPRESSION_MASK) {
+ NInoSetCompressed(ni);
+ if (vol->cluster_size > 4096) {
+ ntfs_error(vi->i_sb, "Found "
"compressed data but "
"compression is "
"disabled due to "
"cluster size (%i) > "
"4kiB.",
vol->cluster_size);
- goto unm_err_out;
- }
- if ((a->flags & ATTR_COMPRESSION_MASK)
- != ATTR_IS_COMPRESSED) {
- ntfs_error(vi->i_sb, "Found "
- "unknown compression "
- "method or corrupt "
- "file.");
- goto unm_err_out;
- }
+ goto unm_err_out;
+ }
+ if ((a->flags & ATTR_COMPRESSION_MASK)
+ != ATTR_IS_COMPRESSED) {
+ ntfs_error(vi->i_sb, "Found unknown "
+ "compression method "
+ "or corrupt file.");
+ goto unm_err_out;
}
- if (a->flags & ATTR_IS_SPARSE)
- NInoSetSparse(ni);
+ }
+ if (a->flags & ATTR_IS_SPARSE)
+ NInoSetSparse(ni);
+ }
+ if (a->flags & ATTR_IS_ENCRYPTED) {
+ if (NInoCompressed(ni)) {
+ ntfs_error(vi->i_sb, "Found encrypted and "
+ "compressed data.");
+ goto unm_err_out;
+ }
+ NInoSetEncrypted(ni);
+ }
+ if (a->non_resident) {
+ NInoSetNonResident(ni);
+ if (NInoCompressed(ni) || NInoSparse(ni)) {
if (a->data.non_resident.compression_unit !=
4) {
ntfs_error(vi->i_sb, "Found "
- "nonstandard compression unit "
- "(%u instead of 4). Cannot "
- "handle this.",
- a->data.non_resident.
- compression_unit);
+ "nonstandard "
+ "compression unit (%u "
+ "instead of 4). "
+ "Cannot handle this.",
+ a->data.non_resident.
+ compression_unit);
err = -EOPNOTSUPP;
goto unm_err_out;
}
@@ -1065,14 +1074,6 @@ skip_large_dir_stuff:
a->data.non_resident.
compressed_size);
}
- if (a->flags & ATTR_IS_ENCRYPTED) {
- if (a->flags & ATTR_COMPRESSION_MASK) {
- ntfs_error(vi->i_sb, "Found encrypted "
- "and compressed data.");
- goto unm_err_out;
- }
- NInoSetEncrypted(ni);
- }
if (a->data.non_resident.lowest_vcn) {
ntfs_error(vi->i_sb, "First extent of $DATA "
"attribute has non zero "
@@ -1212,6 +1213,75 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
if (unlikely(err))
goto unm_err_out;
a = ctx->attr;
+ if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
+ if (a->flags & ATTR_COMPRESSION_MASK) {
+ NInoSetCompressed(ni);
+ if ((ni->type != AT_DATA) || (ni->type == AT_DATA &&
+ ni->name_len)) {
+ ntfs_error(vi->i_sb, "Found compressed "
+ "non-data or named data "
+ "attribute. Please report "
+ "you saw this message to "
+ "linux-ntfs-dev@lists."
+ "sourceforge.net");
+ goto unm_err_out;
+ }
+ if (vol->cluster_size > 4096) {
+ ntfs_error(vi->i_sb, "Found compressed "
+ "attribute but compression is "
+ "disabled due to cluster size "
+ "(%i) > 4kiB.",
+ vol->cluster_size);
+ goto unm_err_out;
+ }
+ if ((a->flags & ATTR_COMPRESSION_MASK) !=
+ ATTR_IS_COMPRESSED) {
+ ntfs_error(vi->i_sb, "Found unknown "
+ "compression method.");
+ goto unm_err_out;
+ }
+ }
+ /*
+ * The encryption flag set in an index root just means to
+ * compress all files.
+ */
+ if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
+ ntfs_error(vi->i_sb, "Found mst protected attribute "
+ "but the attribute is %s. Please "
+ "report you saw this message to "
+ "linux-ntfs-dev@lists.sourceforge.net",
+ NInoCompressed(ni) ? "compressed" :
+ "sparse");
+ goto unm_err_out;
+ }
+ if (a->flags & ATTR_IS_SPARSE)
+ NInoSetSparse(ni);
+ }
+ if (a->flags & ATTR_IS_ENCRYPTED) {
+ if (NInoCompressed(ni)) {
+ ntfs_error(vi->i_sb, "Found encrypted and compressed "
+ "data.");
+ goto unm_err_out;
+ }
+ /*
+ * The encryption flag set in an index root just means to
+ * encrypt all files.
+ */
+ if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
+ ntfs_error(vi->i_sb, "Found mst protected attribute "
+ "but the attribute is encrypted. "
+ "Please report you saw this message "
+ "to linux-ntfs-dev@lists.sourceforge."
+ "net");
+ goto unm_err_out;
+ }
+ if (ni->type != AT_DATA) {
+ ntfs_error(vi->i_sb, "Found encrypted non-data "
+ "attribute.");
+ goto unm_err_out;
+ }
+ NInoSetEncrypted(ni);
+ }
if (!a->non_resident) {
/* Ensure the attribute name is placed before the value. */
if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=
@@ -1220,11 +1290,10 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"the attribute value.");
goto unm_err_out;
}
- if (NInoMstProtected(ni) || a->flags) {
+ if (NInoMstProtected(ni)) {
ntfs_error(vi->i_sb, "Found mst protected attribute "
- "or attribute with non-zero flags but "
- "the attribute is resident. Please "
- "report you saw this message to "
+ "but the attribute is resident. "
+ "Please report you saw this message to "
"linux-ntfs-dev@lists.sourceforge.net");
goto unm_err_out;
}
@@ -1250,50 +1319,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"the mapping pairs array.");
goto unm_err_out;
}
- if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
- if (a->flags & ATTR_COMPRESSION_MASK) {
- NInoSetCompressed(ni);
- if ((ni->type != AT_DATA) || (ni->type ==
- AT_DATA && ni->name_len)) {
- ntfs_error(vi->i_sb, "Found compressed "
- "non-data or named "
- "data attribute. "
- "Please report you "
- "saw this message to "
- "linux-ntfs-dev@lists."
- "sourceforge.net");
- goto unm_err_out;
- }
- if (vol->cluster_size > 4096) {
- ntfs_error(vi->i_sb, "Found compressed "
- "attribute but "
- "compression is "
- "disabled due to "
- "cluster size (%i) > "
- "4kiB.",
- vol->cluster_size);
- goto unm_err_out;
- }
- if ((a->flags & ATTR_COMPRESSION_MASK) !=
- ATTR_IS_COMPRESSED) {
- ntfs_error(vi->i_sb, "Found unknown "
- "compression method.");
- goto unm_err_out;
- }
- }
- if (NInoMstProtected(ni)) {
- ntfs_error(vi->i_sb, "Found mst protected "
- "attribute but the attribute "
- "is %s. Please report you "
- "saw this message to "
- "linux-ntfs-dev@lists."
- "sourceforge.net",
- NInoCompressed(ni) ?
- "compressed" : "sparse");
- goto unm_err_out;
- }
- if (a->flags & ATTR_IS_SPARSE)
- NInoSetSparse(ni);
+ if ((NInoCompressed(ni) || NInoSparse(ni)) &&
+ ni->type != AT_INDEX_ROOT) {
if (a->data.non_resident.compression_unit != 4) {
ntfs_error(vi->i_sb, "Found nonstandard "
"compression unit (%u instead "
@@ -1313,23 +1340,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
ni->itype.compressed.size = sle64_to_cpu(
a->data.non_resident.compressed_size);
}
- if (a->flags & ATTR_IS_ENCRYPTED) {
- if (a->flags & ATTR_COMPRESSION_MASK) {
- ntfs_error(vi->i_sb, "Found encrypted and "
- "compressed data.");
- goto unm_err_out;
- }
- if (NInoMstProtected(ni)) {
- ntfs_error(vi->i_sb, "Found mst protected "
- "attribute but the attribute "
- "is encrypted. Please report "
- "you saw this message to "
- "linux-ntfs-dev@lists."
- "sourceforge.net");
- goto unm_err_out;
- }
- NInoSetEncrypted(ni);
- }
if (a->data.non_resident.lowest_vcn) {
ntfs_error(vi->i_sb, "First extent of attribute has "
"non-zero lowest_vcn.");
@@ -1348,12 +1358,12 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
vi->i_mapping->a_ops = &ntfs_mst_aops;
else
vi->i_mapping->a_ops = &ntfs_aops;
- if (NInoCompressed(ni) || NInoSparse(ni))
+ if ((NInoCompressed(ni) || NInoSparse(ni)) && ni->type != AT_INDEX_ROOT)
vi->i_blocks = ni->itype.compressed.size >> 9;
else
vi->i_blocks = ni->allocated_size >> 9;
/*
- * Make sure the base inode doesn't go away and attach it to the
+ * Make sure the base inode does not go away and attach it to the
* attribute inode.
*/
igrab(base_vi);
@@ -1480,7 +1490,10 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
"after the attribute value.");
goto unm_err_out;
}
- /* Compressed/encrypted/sparse index root is not allowed. */
+ /*
+ * Compressed/encrypted/sparse index root is not allowed, except for
+ * directories of course but those are not dealt with here.
+ */
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |
ATTR_IS_SPARSE)) {
ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "
@@ -2430,16 +2443,18 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
* We skipped the truncate but must still update
* timestamps.
*/
- ia_valid |= ATTR_MTIME|ATTR_CTIME;
+ ia_valid |= ATTR_MTIME | ATTR_CTIME;
}
}
-
if (ia_valid & ATTR_ATIME)
- vi->i_atime = attr->ia_atime;
+ vi->i_atime = timespec_trunc(attr->ia_atime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- vi->i_mtime = attr->ia_mtime;
+ vi->i_mtime = timespec_trunc(attr->ia_mtime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- vi->i_ctime = attr->ia_ctime;
+ vi->i_ctime = timespec_trunc(attr->ia_ctime,
+ vi->i_sb->s_time_gran);
mark_inode_dirty(vi);
out:
return err;
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index a4bc07616e5d..7b5934290685 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -54,6 +54,8 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
int ret = 0;
ntfs_debug("Entering.");
+ if (!rl)
+ return 0;
for (; rl->length; rl++) {
int err;
@@ -163,17 +165,9 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
BUG_ON(zone < FIRST_ZONE);
BUG_ON(zone > LAST_ZONE);
- /* Return empty runlist if @count == 0 */
- // FIXME: Do we want to just return NULL instead? (AIA)
- if (!count) {
- rl = ntfs_malloc_nofs(PAGE_SIZE);
- if (!rl)
- return ERR_PTR(-ENOMEM);
- rl[0].vcn = start_vcn;
- rl[0].lcn = LCN_RL_NOT_MAPPED;
- rl[0].length = 0;
- return rl;
- }
+ /* Return NULL if @count is zero. */
+ if (!count)
+ return NULL;
/* Take the lcnbmp lock for writing. */
down_write(&vol->lcnbmp_lock);
/*
@@ -788,7 +782,8 @@ out:
* @vi: vfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
* @count: number of clusters to free or -1 for all clusters
- * @is_rollback: if TRUE this is a rollback operation
+ * @write_locked: true if the runlist is locked for writing
+ * @is_rollback: true if this is a rollback operation
*
* Free @count clusters starting at the cluster @start_vcn in the runlist
* described by the vfs inode @vi.
@@ -806,17 +801,17 @@ out:
* Return the number of deallocated clusters (not counting sparse ones) on
* success and -errno on error.
*
- * Locking: - The runlist described by @vi must be unlocked on entry and is
- * unlocked on return.
- * - This function takes the runlist lock of @vi for reading and
- * sometimes for writing and sometimes modifies the runlist.
+ * Locking: - The runlist described by @vi must be locked on entry and is
+ * locked on return. Note if the runlist is locked for reading the
+ * lock may be dropped and reacquired. Note the runlist may be
+ * modified when needed runlist fragments need to be mapped.
* - The volume lcn bitmap must be unlocked on entry and is unlocked
* on return.
* - This function takes the volume lcn bitmap lock for writing and
* modifies the bitmap contents.
*/
s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
- const BOOL is_rollback)
+ const BOOL write_locked, const BOOL is_rollback)
{
s64 delta, to_free, total_freed, real_freed;
ntfs_inode *ni;
@@ -848,8 +843,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
total_freed = real_freed = 0;
- down_read(&ni->runlist.lock);
- rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE);
+ rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked);
if (IS_ERR(rl)) {
if (!is_rollback)
ntfs_error(vol->sb, "Failed to find first runlist "
@@ -903,7 +897,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
/* Attempt to map runlist. */
vcn = rl->vcn;
- rl = ntfs_attr_find_vcn_nolock(ni, vcn, FALSE);
+ rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked);
if (IS_ERR(rl)) {
err = PTR_ERR(rl);
if (!is_rollback)
@@ -950,7 +944,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
/* Update the total done clusters. */
total_freed += to_free;
}
- up_read(&ni->runlist.lock);
if (likely(!is_rollback))
up_write(&vol->lcnbmp_lock);
@@ -960,7 +953,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
ntfs_debug("Done.");
return real_freed;
err_out:
- up_read(&ni->runlist.lock);
if (is_rollback)
return err;
/* If no real clusters were freed, no need to rollback. */
@@ -973,7 +965,8 @@ err_out:
* If rollback fails, set the volume errors flag, emit an error
* message, and return the error code.
*/
- delta = __ntfs_cluster_free(vi, start_vcn, total_freed, TRUE);
+ delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked,
+ TRUE);
if (delta < 0) {
ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
"inconsistent metadata! Unmount and run "
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
index 4cac1c024af6..e4d7fb98d685 100644
--- a/fs/ntfs/lcnalloc.h
+++ b/fs/ntfs/lcnalloc.h
@@ -43,13 +43,14 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
const NTFS_CLUSTER_ALLOCATION_ZONES zone);
extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
- s64 count, const BOOL is_rollback);
+ s64 count, const BOOL write_locked, const BOOL is_rollback);
/**
* ntfs_cluster_free - free clusters on an ntfs volume
* @vi: vfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
* @count: number of clusters to free or -1 for all clusters
+ * @write_locked: true if the runlist is locked for writing
*
* Free @count clusters starting at the cluster @start_vcn in the runlist
* described by the vfs inode @vi.
@@ -64,19 +65,19 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
* Return the number of deallocated clusters (not counting sparse ones) on
* success and -errno on error.
*
- * Locking: - The runlist described by @vi must be unlocked on entry and is
- * unlocked on return.
- * - This function takes the runlist lock of @vi for reading and
- * sometimes for writing and sometimes modifies the runlist.
+ * Locking: - The runlist described by @vi must be locked on entry and is
+ * locked on return. Note if the runlist is locked for reading the
+ * lock may be dropped and reacquired. Note the runlist may be
+ * modified when needed runlist fragments need to be mapped.
* - The volume lcn bitmap must be unlocked on entry and is unlocked
* on return.
* - This function takes the volume lcn bitmap lock for writing and
* modifies the bitmap contents.
*/
static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
- s64 count)
+ s64 count, const BOOL write_locked)
{
- return __ntfs_cluster_free(vi, start_vcn, count, FALSE);
+ return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE);
}
extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
@@ -93,8 +94,10 @@ extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
*
* Return 0 on success and -errno on error.
*
- * Locking: This function takes the volume lcn bitmap lock for writing and
- * modifies the bitmap contents.
+ * Locking: - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
+ * - The caller must have locked the runlist @rl for reading or
+ * writing.
*/
static inline int ntfs_cluster_free_from_rl(ntfs_volume *vol,
const runlist_element *rl)
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 8edb8e20fb08..0173e95500d9 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -121,7 +121,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
*/
if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
ntfs_error(vi->i_sb, "$LogFile restart page is not modified "
- "chkdsk but a chkdsk LSN is specified.");
+ "by chkdsk but a chkdsk LSN is specified.");
return FALSE;
}
ntfs_debug("Done.");
@@ -312,10 +312,12 @@ err_out:
* @vi: $LogFile inode to which the restart page belongs
* @rp: restart page to check
* @pos: position in @vi at which the restart page resides
- * @wrp: copy of the multi sector transfer deprotected restart page
+ * @wrp: [OUT] copy of the multi sector transfer deprotected restart page
+ * @lsn: [OUT] set to the current logfile lsn on success
*
- * Check the restart page @rp for consistency and return TRUE if it is
- * consistent and FALSE otherwise.
+ * Check the restart page @rp for consistency and return 0 if it is consistent
+ * and -errno otherwise. The restart page may have been modified by chkdsk in
+ * which case its magic is CHKD instead of RSTR.
*
* This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
* require the full restart page.
@@ -323,25 +325,33 @@ err_out:
* If @wrp is not NULL, on success, *@wrp will point to a buffer containing a
* copy of the complete multi sector transfer deprotected page. On failure,
* *@wrp is undefined.
+ *
+ * Simillarly, if @lsn is not NULL, on succes *@lsn will be set to the current
+ * logfile lsn according to this restart page. On failure, *@lsn is undefined.
+ *
+ * The following error codes are defined:
+ * -EINVAL - The restart page is inconsistent.
+ * -ENOMEM - Not enough memory to load the restart page.
+ * -EIO - Failed to reading from $LogFile.
*/
-static BOOL ntfs_check_and_load_restart_page(struct inode *vi,
- RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp)
+static int ntfs_check_and_load_restart_page(struct inode *vi,
+ RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp,
+ LSN *lsn)
{
RESTART_AREA *ra;
RESTART_PAGE_HEADER *trp;
- int size;
- BOOL ret;
+ int size, err;
ntfs_debug("Entering.");
/* Check the restart page header for consistency. */
if (!ntfs_check_restart_page_header(vi, rp, pos)) {
/* Error output already done inside the function. */
- return FALSE;
+ return -EINVAL;
}
/* Check the restart area for consistency. */
if (!ntfs_check_restart_area(vi, rp)) {
/* Error output already done inside the function. */
- return FALSE;
+ return -EINVAL;
}
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
/*
@@ -352,7 +362,7 @@ static BOOL ntfs_check_and_load_restart_page(struct inode *vi,
if (!trp) {
ntfs_error(vi->i_sb, "Failed to allocate memory for $LogFile "
"restart page buffer.");
- return FALSE;
+ return -ENOMEM;
}
/*
* Read the whole of the restart page into the buffer. If it fits
@@ -379,6 +389,9 @@ static BOOL ntfs_check_and_load_restart_page(struct inode *vi,
if (IS_ERR(page)) {
ntfs_error(vi->i_sb, "Error mapping $LogFile "
"page (index %lu).", idx);
+ err = PTR_ERR(page);
+ if (err != -EIO && err != -ENOMEM)
+ err = -EIO;
goto err_out;
}
size = min_t(int, to_read, PAGE_CACHE_SIZE);
@@ -392,29 +405,57 @@ static BOOL ntfs_check_and_load_restart_page(struct inode *vi,
/* Perform the multi sector transfer deprotection on the buffer. */
if (post_read_mst_fixup((NTFS_RECORD*)trp,
le32_to_cpu(rp->system_page_size))) {
- ntfs_error(vi->i_sb, "Multi sector transfer error detected in "
- "$LogFile restart page.");
- goto err_out;
+ /*
+ * A multi sector tranfer error was detected. We only need to
+ * abort if the restart page contents exceed the multi sector
+ * transfer fixup of the first sector.
+ */
+ if (le16_to_cpu(rp->restart_area_offset) +
+ le16_to_cpu(ra->restart_area_length) >
+ NTFS_BLOCK_SIZE - sizeof(u16)) {
+ ntfs_error(vi->i_sb, "Multi sector transfer error "
+ "detected in $LogFile restart page.");
+ err = -EINVAL;
+ goto err_out;
+ }
+ }
+ /*
+ * If the restart page is modified by chkdsk or there are no active
+ * logfile clients, the logfile is consistent. Otherwise, need to
+ * check the log client records for consistency, too.
+ */
+ err = 0;
+ if (ntfs_is_rstr_record(rp->magic) &&
+ ra->client_in_use_list != LOGFILE_NO_CLIENT) {
+ if (!ntfs_check_log_client_array(vi, trp)) {
+ err = -EINVAL;
+ goto err_out;
+ }
+ }
+ if (lsn) {
+ if (ntfs_is_rstr_record(rp->magic))
+ *lsn = sle64_to_cpu(ra->current_lsn);
+ else /* if (ntfs_is_chkd_record(rp->magic)) */
+ *lsn = sle64_to_cpu(rp->chkdsk_lsn);
}
- /* Check the log client records for consistency. */
- ret = ntfs_check_log_client_array(vi, trp);
- if (ret && wrp)
- *wrp = trp;
- else
- ntfs_free(trp);
ntfs_debug("Done.");
- return ret;
+ if (wrp)
+ *wrp = trp;
+ else {
err_out:
- ntfs_free(trp);
- return FALSE;
+ ntfs_free(trp);
+ }
+ return err;
}
/**
* ntfs_check_logfile - check the journal for consistency
* @log_vi: struct inode of loaded journal $LogFile to check
+ * @rp: [OUT] on success this is a copy of the current restart page
*
* Check the $LogFile journal for consistency and return TRUE if it is
- * consistent and FALSE if not.
+ * consistent and FALSE if not. On success, the current restart page is
+ * returned in *@rp. Caller must call ntfs_free(*@rp) when finished with it.
*
* At present we only check the two restart pages and ignore the log record
* pages.
@@ -424,19 +465,18 @@ err_out:
* if the $LogFile was created on a system with a different page size to ours
* yet and mst deprotection would fail if our page size is smaller.
*/
-BOOL ntfs_check_logfile(struct inode *log_vi)
+BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
{
- s64 size, pos, rstr1_pos, rstr2_pos;
+ s64 size, pos;
+ LSN rstr1_lsn, rstr2_lsn;
ntfs_volume *vol = NTFS_SB(log_vi->i_sb);
struct address_space *mapping = log_vi->i_mapping;
struct page *page = NULL;
u8 *kaddr = NULL;
RESTART_PAGE_HEADER *rstr1_ph = NULL;
RESTART_PAGE_HEADER *rstr2_ph = NULL;
- int log_page_size, log_page_mask, ofs;
+ int log_page_size, log_page_mask, err;
BOOL logfile_is_empty = TRUE;
- BOOL rstr1_found = FALSE;
- BOOL rstr2_found = FALSE;
u8 log_page_bits;
ntfs_debug("Entering.");
@@ -491,7 +531,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi)
if (IS_ERR(page)) {
ntfs_error(vol->sb, "Error mapping $LogFile "
"page (index %lu).", idx);
- return FALSE;
+ goto err_out;
}
}
kaddr = (u8*)page_address(page) + (pos & ~PAGE_CACHE_MASK);
@@ -510,99 +550,95 @@ BOOL ntfs_check_logfile(struct inode *log_vi)
*/
if (ntfs_is_rcrd_recordp((le32*)kaddr))
break;
- /*
- * A modified by chkdsk restart page means we cannot handle
- * this log file.
- */
- if (ntfs_is_chkd_recordp((le32*)kaddr)) {
- ntfs_error(vol->sb, "$LogFile has been modified by "
- "chkdsk. Mount this volume in "
- "Windows.");
- goto err_out;
- }
- /* If not a restart page, continue. */
- if (!ntfs_is_rstr_recordp((le32*)kaddr)) {
- /* Skip to the minimum page size for the next one. */
+ /* If not a (modified by chkdsk) restart page, continue. */
+ if (!ntfs_is_rstr_recordp((le32*)kaddr) &&
+ !ntfs_is_chkd_recordp((le32*)kaddr)) {
if (!pos)
pos = NTFS_BLOCK_SIZE >> 1;
continue;
}
- /* We now know we have a restart page. */
- if (!pos) {
- rstr1_found = TRUE;
- rstr1_pos = pos;
- } else {
- if (rstr2_found) {
- ntfs_error(vol->sb, "Found more than two "
- "restart pages in $LogFile.");
- goto err_out;
- }
- rstr2_found = TRUE;
- rstr2_pos = pos;
- }
/*
- * Check the restart page for consistency and get a copy of the
- * complete multi sector transfer deprotected restart page.
+ * Check the (modified by chkdsk) restart page for consistency
+ * and get a copy of the complete multi sector transfer
+ * deprotected restart page.
*/
- if (!ntfs_check_and_load_restart_page(log_vi,
+ err = ntfs_check_and_load_restart_page(log_vi,
(RESTART_PAGE_HEADER*)kaddr, pos,
- !pos ? &rstr1_ph : &rstr2_ph)) {
- /* Error output already done inside the function. */
- goto err_out;
+ !rstr1_ph ? &rstr1_ph : &rstr2_ph,
+ !rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
+ if (!err) {
+ /*
+ * If we have now found the first (modified by chkdsk)
+ * restart page, continue looking for the second one.
+ */
+ if (!pos) {
+ pos = NTFS_BLOCK_SIZE >> 1;
+ continue;
+ }
+ /*
+ * We have now found the second (modified by chkdsk)
+ * restart page, so we can stop looking.
+ */
+ break;
}
/*
- * We have a valid restart page. The next one must be after
- * a whole system page size as specified by the valid restart
- * page.
+ * Error output already done inside the function. Note, we do
+ * not abort if the restart page was invalid as we might still
+ * find a valid one further in the file.
*/
+ if (err != -EINVAL) {
+ ntfs_unmap_page(page);
+ goto err_out;
+ }
+ /* Continue looking. */
if (!pos)
- pos = le32_to_cpu(rstr1_ph->system_page_size) >> 1;
+ pos = NTFS_BLOCK_SIZE >> 1;
}
- if (page) {
+ if (page)
ntfs_unmap_page(page);
- page = NULL;
- }
if (logfile_is_empty) {
NVolSetLogFileEmpty(vol);
is_empty:
ntfs_debug("Done. ($LogFile is empty.)");
return TRUE;
}
- if (!rstr1_found || !rstr2_found) {
- ntfs_error(vol->sb, "Did not find two restart pages in "
- "$LogFile.");
- goto err_out;
+ if (!rstr1_ph) {
+ BUG_ON(rstr2_ph);
+ ntfs_error(vol->sb, "Did not find any restart pages in "
+ "$LogFile and it was not empty.");
+ return FALSE;
+ }
+ /* If both restart pages were found, use the more recent one. */
+ if (rstr2_ph) {
+ /*
+ * If the second restart area is more recent, switch to it.
+ * Otherwise just throw it away.
+ */
+ if (rstr2_lsn > rstr1_lsn) {
+ ntfs_free(rstr1_ph);
+ rstr1_ph = rstr2_ph;
+ /* rstr1_lsn = rstr2_lsn; */
+ } else
+ ntfs_free(rstr2_ph);
+ rstr2_ph = NULL;
}
- /*
- * The two restart areas must be identical except for the update
- * sequence number.
- */
- ofs = le16_to_cpu(rstr1_ph->usa_ofs);
- if (memcmp(rstr1_ph, rstr2_ph, ofs) || (ofs += sizeof(u16),
- memcmp((u8*)rstr1_ph + ofs, (u8*)rstr2_ph + ofs,
- le32_to_cpu(rstr1_ph->system_page_size) - ofs))) {
- ntfs_error(vol->sb, "The two restart pages in $LogFile do not "
- "match.");
- goto err_out;
- }
- ntfs_free(rstr1_ph);
- ntfs_free(rstr2_ph);
/* All consistency checks passed. */
+ if (rp)
+ *rp = rstr1_ph;
+ else
+ ntfs_free(rstr1_ph);
ntfs_debug("Done.");
return TRUE;
err_out:
- if (page)
- ntfs_unmap_page(page);
if (rstr1_ph)
ntfs_free(rstr1_ph);
- if (rstr2_ph)
- ntfs_free(rstr2_ph);
return FALSE;
}
/**
* ntfs_is_logfile_clean - check in the journal if the volume is clean
* @log_vi: struct inode of loaded journal $LogFile to check
+ * @rp: copy of the current restart page
*
* Analyze the $LogFile journal and return TRUE if it indicates the volume was
* shutdown cleanly and FALSE if not.
@@ -619,11 +655,9 @@ err_out:
* is empty this function requires that NVolLogFileEmpty() is true otherwise an
* empty volume will be reported as dirty.
*/
-BOOL ntfs_is_logfile_clean(struct inode *log_vi)
+BOOL ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
{
ntfs_volume *vol = NTFS_SB(log_vi->i_sb);
- struct page *page;
- RESTART_PAGE_HEADER *rp;
RESTART_AREA *ra;
ntfs_debug("Entering.");
@@ -632,24 +666,15 @@ BOOL ntfs_is_logfile_clean(struct inode *log_vi)
ntfs_debug("Done. ($LogFile is empty.)");
return TRUE;
}
- /*
- * Read the first restart page. It will be possibly incomplete and
- * will not be multi sector transfer deprotected but we only need the
- * first NTFS_BLOCK_SIZE bytes so it does not matter.
- */
- page = ntfs_map_page(log_vi->i_mapping, 0);
- if (IS_ERR(page)) {
- ntfs_error(vol->sb, "Error mapping $LogFile page (index 0).");
+ BUG_ON(!rp);
+ if (!ntfs_is_rstr_record(rp->magic) &&
+ !ntfs_is_chkd_record(rp->magic)) {
+ ntfs_error(vol->sb, "Restart page buffer is invalid. This is "
+ "probably a bug in that the $LogFile should "
+ "have been consistency checked before calling "
+ "this function.");
return FALSE;
}
- rp = (RESTART_PAGE_HEADER*)page_address(page);
- if (!ntfs_is_rstr_record(rp->magic)) {
- ntfs_error(vol->sb, "No restart page found at offset zero in "
- "$LogFile. This is probably a bug in that "
- "the $LogFile should have been consistency "
- "checked before calling this function.");
- goto err_out;
- }
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
/*
* If the $LogFile has active clients, i.e. it is open, and we do not
@@ -659,15 +684,11 @@ BOOL ntfs_is_logfile_clean(struct inode *log_vi)
if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
!(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
ntfs_debug("Done. $LogFile indicates a dirty shutdown.");
- goto err_out;
+ return FALSE;
}
- ntfs_unmap_page(page);
/* $LogFile indicates a clean shutdown. */
ntfs_debug("Done. $LogFile indicates a clean shutdown.");
return TRUE;
-err_out:
- ntfs_unmap_page(page);
- return FALSE;
}
/**
diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h
index 4ee4378de061..42388f95ea6d 100644
--- a/fs/ntfs/logfile.h
+++ b/fs/ntfs/logfile.h
@@ -2,7 +2,7 @@
* logfile.h - Defines for NTFS kernel journal ($LogFile) handling. Part of
* the Linux-NTFS project.
*
- * Copyright (c) 2000-2004 Anton Altaparmakov
+ * Copyright (c) 2000-2005 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -296,9 +296,11 @@ typedef struct {
/* sizeof() = 160 (0xa0) bytes */
} __attribute__ ((__packed__)) LOG_CLIENT_RECORD;
-extern BOOL ntfs_check_logfile(struct inode *log_vi);
+extern BOOL ntfs_check_logfile(struct inode *log_vi,
+ RESTART_PAGE_HEADER **rp);
-extern BOOL ntfs_is_logfile_clean(struct inode *log_vi);
+extern BOOL ntfs_is_logfile_clean(struct inode *log_vi,
+ const RESTART_PAGE_HEADER *rp);
extern BOOL ntfs_empty_logfile(struct inode *log_vi);
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
index fac5944df6d8..3288bcc2c4aa 100644
--- a/fs/ntfs/malloc.h
+++ b/fs/ntfs/malloc.h
@@ -27,27 +27,63 @@
#include <linux/highmem.h>
/**
- * ntfs_malloc_nofs - allocate memory in multiples of pages
- * @size number of bytes to allocate
+ * __ntfs_malloc - allocate memory in multiples of pages
+ * @size: number of bytes to allocate
+ * @gfp_mask: extra flags for the allocator
+ *
+ * Internal function. You probably want ntfs_malloc_nofs()...
*
* Allocates @size bytes of memory, rounded up to multiples of PAGE_SIZE and
* returns a pointer to the allocated memory.
*
* If there was insufficient memory to complete the request, return NULL.
+ * Depending on @gfp_mask the allocation may be guaranteed to succeed.
*/
-static inline void *ntfs_malloc_nofs(unsigned long size)
+static inline void *__ntfs_malloc(unsigned long size,
+ unsigned int __nocast gfp_mask)
{
if (likely(size <= PAGE_SIZE)) {
BUG_ON(!size);
/* kmalloc() has per-CPU caches so is faster for now. */
- return kmalloc(PAGE_SIZE, GFP_NOFS);
- /* return (void *)__get_free_page(GFP_NOFS | __GFP_HIGHMEM); */
+ return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM);
+ /* return (void *)__get_free_page(gfp_mask); */
}
if (likely(size >> PAGE_SHIFT < num_physpages))
- return __vmalloc(size, GFP_NOFS | __GFP_HIGHMEM, PAGE_KERNEL);
+ return __vmalloc(size, gfp_mask, PAGE_KERNEL);
return NULL;
}
+/**
+ * ntfs_malloc_nofs - allocate memory in multiples of pages
+ * @size: number of bytes to allocate
+ *
+ * Allocates @size bytes of memory, rounded up to multiples of PAGE_SIZE and
+ * returns a pointer to the allocated memory.
+ *
+ * If there was insufficient memory to complete the request, return NULL.
+ */
+static inline void *ntfs_malloc_nofs(unsigned long size)
+{
+ return __ntfs_malloc(size, GFP_NOFS | __GFP_HIGHMEM);
+}
+
+/**
+ * ntfs_malloc_nofs_nofail - allocate memory in multiples of pages
+ * @size: number of bytes to allocate
+ *
+ * Allocates @size bytes of memory, rounded up to multiples of PAGE_SIZE and
+ * returns a pointer to the allocated memory.
+ *
+ * This function guarantees that the allocation will succeed. It will sleep
+ * for as long as it takes to complete the allocation.
+ *
+ * If there was insufficient memory to complete the request, return NULL.
+ */
+static inline void *ntfs_malloc_nofs_nofail(unsigned long size)
+{
+ return __ntfs_malloc(size, GFP_NOFS | __GFP_HIGHMEM | __GFP_NOFAIL);
+}
+
static inline void ntfs_free(void *addr)
{
if (likely(((unsigned long)addr < VMALLOC_START) ||
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 317f7c679fd3..2c32b84385a8 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -511,7 +511,6 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no,
} while (bh);
tail->b_this_page = head;
attach_page_buffers(page, head);
- BUG_ON(!page_has_buffers(page));
}
bh = head = page_buffers(page);
BUG_ON(!bh);
@@ -692,7 +691,6 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
*/
if (!NInoTestClearDirty(ni))
goto done;
- BUG_ON(!page_has_buffers(page));
bh = head = page_buffers(page);
BUG_ON(!bh);
rl = NULL;
@@ -1955,7 +1953,7 @@ restore_undo_alloc:
a = ctx->attr;
a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1);
undo_alloc:
- if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1) < 0) {
+ if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) {
ntfs_error(vol->sb, "Failed to free clusters from mft data "
"attribute.%s", es);
NVolSetErrors(vol);
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index 758855b0414e..f5b2ac929081 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -35,7 +35,7 @@ static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
int size)
{
if (likely((dst != src) && (size > 0)))
- memmove(base + dst, base + src, size * sizeof (*base));
+ memmove(base + dst, base + src, size * sizeof(*base));
}
/**
@@ -95,6 +95,51 @@ static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
}
/**
+ * ntfs_rl_realloc_nofail - Reallocate memory for runlists
+ * @rl: original runlist
+ * @old_size: number of runlist elements in the original runlist @rl
+ * @new_size: number of runlist elements we need space for
+ *
+ * As the runlists grow, more memory will be required. To prevent the
+ * kernel having to allocate and reallocate large numbers of small bits of
+ * memory, this function returns an entire page of memory.
+ *
+ * This function guarantees that the allocation will succeed. It will sleep
+ * for as long as it takes to complete the allocation.
+ *
+ * It is up to the caller to serialize access to the runlist @rl.
+ *
+ * N.B. If the new allocation doesn't require a different number of pages in
+ * memory, the function will return the original pointer.
+ *
+ * On success, return a pointer to the newly allocated, or recycled, memory.
+ * On error, return -errno. The following error codes are defined:
+ * -ENOMEM - Not enough memory to allocate runlist array.
+ * -EINVAL - Invalid parameters were passed in.
+ */
+static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
+ int old_size, int new_size)
+{
+ runlist_element *new_rl;
+
+ old_size = PAGE_ALIGN(old_size * sizeof(*rl));
+ new_size = PAGE_ALIGN(new_size * sizeof(*rl));
+ if (old_size == new_size)
+ return rl;
+
+ new_rl = ntfs_malloc_nofs_nofail(new_size);
+ BUG_ON(!new_rl);
+
+ if (likely(rl != NULL)) {
+ if (unlikely(old_size > new_size))
+ old_size = new_size;
+ memcpy(new_rl, rl, old_size);
+ ntfs_free(rl);
+ }
+ return new_rl;
+}
+
+/**
* ntfs_are_rl_mergeable - test if two runlists can be joined together
* @dst: original runlist
* @src: new runlist to test for mergeability with @dst
@@ -497,6 +542,7 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
/* Scan to the end of the source runlist. */
for (dend = 0; likely(drl[dend].length); dend++)
;
+ dend++;
drl = ntfs_rl_realloc(drl, dend, dend + 1);
if (IS_ERR(drl))
return drl;
@@ -566,8 +612,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
((drl[dins].vcn + drl[dins].length) <= /* End of hole */
(srl[send - 1].vcn + srl[send - 1].length)));
- /* Or we'll lose an end marker */
- if (start && finish && (drl[dins].length == 0))
+ /* Or we will lose an end marker. */
+ if (finish && !drl[dins].length)
ss++;
if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
finish = FALSE;
@@ -621,11 +667,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
/* Add an unmapped runlist element. */
if (!slots) {
- /* FIXME/TODO: We need to have the
- * extra memory already! (AIA) */
- drl = ntfs_rl_realloc(drl, ds, ds + 2);
- if (!drl)
- goto critical_error;
+ drl = ntfs_rl_realloc_nofail(drl, ds,
+ ds + 2);
slots = 2;
}
ds++;
@@ -640,13 +683,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
drl[ds].length = marker_vcn - drl[ds].vcn;
/* Finally add the ENOENT terminator. */
ds++;
- if (!slots) {
- /* FIXME/TODO: We need to have the extra
- * memory already! (AIA) */
- drl = ntfs_rl_realloc(drl, ds, ds + 1);
- if (!drl)
- goto critical_error;
- }
+ if (!slots)
+ drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
drl[ds].vcn = marker_vcn;
drl[ds].lcn = LCN_ENOENT;
drl[ds].length = (s64)0;
@@ -659,11 +697,6 @@ finished:
ntfs_debug("Merged runlist:");
ntfs_debug_dump_runlist(drl);
return drl;
-
-critical_error:
- /* Critical error! We cannot afford to fail here. */
- ntfs_error(NULL, "Critical error! Not enough memory.");
- panic("NTFS: Cannot continue.");
}
/**
@@ -727,6 +760,9 @@ runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
ntfs_error(vol->sb, "Corrupt attribute.");
return ERR_PTR(-EIO);
}
+ /* If the mapping pairs array is valid but empty, nothing to do. */
+ if (!vcn && !*buf)
+ return old_rl;
/* Current position in runlist array. */
rlpos = 0;
/* Allocate first page and set current runlist size to one page. */
@@ -1419,6 +1455,7 @@ err_out:
/**
* ntfs_rl_truncate_nolock - truncate a runlist starting at a specified vcn
+ * @vol: ntfs volume (needed for error output)
* @runlist: runlist to truncate
* @new_length: the new length of the runlist in VCNs
*
@@ -1426,12 +1463,16 @@ err_out:
* holding the runlist elements to a length of @new_length VCNs.
*
* If @new_length lies within the runlist, the runlist elements with VCNs of
- * @new_length and above are discarded.
+ * @new_length and above are discarded. As a special case if @new_length is
+ * zero, the runlist is discarded and set to NULL.
*
* If @new_length lies beyond the runlist, a sparse runlist element is added to
* the end of the runlist @runlist or if the last runlist element is a sparse
* one already, this is extended.
*
+ * Note, no checking is done for unmapped runlist elements. It is assumed that
+ * the caller has mapped any elements that need to be mapped already.
+ *
* Return 0 on success and -errno on error.
*
* Locking: The caller must hold @runlist->lock for writing.
@@ -1446,6 +1487,13 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
BUG_ON(!runlist);
BUG_ON(new_length < 0);
rl = runlist->rl;
+ if (!new_length) {
+ ntfs_debug("Freeing runlist.");
+ runlist->rl = NULL;
+ if (rl)
+ ntfs_free(rl);
+ return 0;
+ }
if (unlikely(!rl)) {
/*
* Create a runlist consisting of a sparse runlist element of
@@ -1553,4 +1601,288 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
return 0;
}
+/**
+ * ntfs_rl_punch_nolock - punch a hole into a runlist
+ * @vol: ntfs volume (needed for error output)
+ * @runlist: runlist to punch a hole into
+ * @start: starting VCN of the hole to be created
+ * @length: size of the hole to be created in units of clusters
+ *
+ * Punch a hole into the runlist @runlist starting at VCN @start and of size
+ * @length clusters.
+ *
+ * Return 0 on success and -errno on error, in which case @runlist has not been
+ * modified.
+ *
+ * If @start and/or @start + @length are outside the runlist return error code
+ * -ENOENT.
+ *
+ * If the runlist contains unmapped or error elements between @start and @start
+ * + @length return error code -EINVAL.
+ *
+ * Locking: The caller must hold @runlist->lock for writing.
+ */
+int ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist,
+ const VCN start, const s64 length)
+{
+ const VCN end = start + length;
+ s64 delta;
+ runlist_element *rl, *rl_end, *rl_real_end, *trl;
+ int old_size;
+ BOOL lcn_fixup = FALSE;
+
+ ntfs_debug("Entering for start 0x%llx, length 0x%llx.",
+ (long long)start, (long long)length);
+ BUG_ON(!runlist);
+ BUG_ON(start < 0);
+ BUG_ON(length < 0);
+ BUG_ON(end < 0);
+ rl = runlist->rl;
+ if (unlikely(!rl)) {
+ if (likely(!start && !length))
+ return 0;
+ return -ENOENT;
+ }
+ /* Find @start in the runlist. */
+ while (likely(rl->length && start >= rl[1].vcn))
+ rl++;
+ rl_end = rl;
+ /* Find @end in the runlist. */
+ while (likely(rl_end->length && end >= rl_end[1].vcn)) {
+ /* Verify there are no unmapped or error elements. */
+ if (unlikely(rl_end->lcn < LCN_HOLE))
+ return -EINVAL;
+ rl_end++;
+ }
+ /* Check the last element. */
+ if (unlikely(rl_end->length && rl_end->lcn < LCN_HOLE))
+ return -EINVAL;
+ /* This covers @start being out of bounds, too. */
+ if (!rl_end->length && end > rl_end->vcn)
+ return -ENOENT;
+ if (!length)
+ return 0;
+ if (!rl->length)
+ return -ENOENT;
+ rl_real_end = rl_end;
+ /* Determine the runlist size. */
+ while (likely(rl_real_end->length))
+ rl_real_end++;
+ old_size = rl_real_end - runlist->rl + 1;
+ /* If @start is in a hole simply extend the hole. */
+ if (rl->lcn == LCN_HOLE) {
+ /*
+ * If both @start and @end are in the same sparse run, we are
+ * done.
+ */
+ if (end <= rl[1].vcn) {
+ ntfs_debug("Done (requested hole is already sparse).");
+ return 0;
+ }
+extend_hole:
+ /* Extend the hole. */
+ rl->length = end - rl->vcn;
+ /* If @end is in a hole, merge it with the current one. */
+ if (rl_end->lcn == LCN_HOLE) {
+ rl_end++;
+ rl->length = rl_end->vcn - rl->vcn;
+ }
+ /* We have done the hole. Now deal with the remaining tail. */
+ rl++;
+ /* Cut out all runlist elements up to @end. */
+ if (rl < rl_end)
+ memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
+ sizeof(*rl));
+ /* Adjust the beginning of the tail if necessary. */
+ if (end > rl->vcn) {
+ s64 delta = end - rl->vcn;
+ rl->vcn = end;
+ rl->length -= delta;
+ /* Only adjust the lcn if it is real. */
+ if (rl->lcn >= 0)
+ rl->lcn += delta;
+ }
+shrink_allocation:
+ /* Reallocate memory if the allocation changed. */
+ if (rl < rl_end) {
+ rl = ntfs_rl_realloc(runlist->rl, old_size,
+ old_size - (rl_end - rl));
+ if (IS_ERR(rl))
+ ntfs_warning(vol->sb, "Failed to shrink "
+ "runlist buffer. This just "
+ "wastes a bit of memory "
+ "temporarily so we ignore it "
+ "and return success.");
+ else
+ runlist->rl = rl;
+ }
+ ntfs_debug("Done (extend hole).");
+ return 0;
+ }
+ /*
+ * If @start is at the beginning of a run things are easier as there is
+ * no need to split the first run.
+ */
+ if (start == rl->vcn) {
+ /*
+ * @start is at the beginning of a run.
+ *
+ * If the previous run is sparse, extend its hole.
+ *
+ * If @end is not in the same run, switch the run to be sparse
+ * and extend the newly created hole.
+ *
+ * Thus both of these cases reduce the problem to the above
+ * case of "@start is in a hole".
+ */
+ if (rl > runlist->rl && (rl - 1)->lcn == LCN_HOLE) {
+ rl--;
+ goto extend_hole;
+ }
+ if (end >= rl[1].vcn) {
+ rl->lcn = LCN_HOLE;
+ goto extend_hole;
+ }
+ /*
+ * The final case is when @end is in the same run as @start.
+ * For this need to split the run into two. One run for the
+ * sparse region between the beginning of the old run, i.e.
+ * @start, and @end and one for the remaining non-sparse
+ * region, i.e. between @end and the end of the old run.
+ */
+ trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
+ if (IS_ERR(trl))
+ goto enomem_out;
+ old_size++;
+ if (runlist->rl != trl) {
+ rl = trl + (rl - runlist->rl);
+ rl_end = trl + (rl_end - runlist->rl);
+ rl_real_end = trl + (rl_real_end - runlist->rl);
+ runlist->rl = trl;
+ }
+split_end:
+ /* Shift all the runs up by one. */
+ memmove(rl + 1, rl, (rl_real_end - rl + 1) * sizeof(*rl));
+ /* Finally, setup the two split runs. */
+ rl->lcn = LCN_HOLE;
+ rl->length = length;
+ rl++;
+ rl->vcn += length;
+ /* Only adjust the lcn if it is real. */
+ if (rl->lcn >= 0 || lcn_fixup)
+ rl->lcn += length;
+ rl->length -= length;
+ ntfs_debug("Done (split one).");
+ return 0;
+ }
+ /*
+ * @start is neither in a hole nor at the beginning of a run.
+ *
+ * If @end is in a hole, things are easier as simply truncating the run
+ * @start is in to end at @start - 1, deleting all runs after that up
+ * to @end, and finally extending the beginning of the run @end is in
+ * to be @start is all that is needed.
+ */
+ if (rl_end->lcn == LCN_HOLE) {
+ /* Truncate the run containing @start. */
+ rl->length = start - rl->vcn;
+ rl++;
+ /* Cut out all runlist elements up to @end. */
+ if (rl < rl_end)
+ memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
+ sizeof(*rl));
+ /* Extend the beginning of the run @end is in to be @start. */
+ rl->vcn = start;
+ rl->length = rl[1].vcn - start;
+ goto shrink_allocation;
+ }
+ /*
+ * If @end is not in a hole there are still two cases to distinguish.
+ * Either @end is or is not in the same run as @start.
+ *
+ * The second case is easier as it can be reduced to an already solved
+ * problem by truncating the run @start is in to end at @start - 1.
+ * Then, if @end is in the next run need to split the run into a sparse
+ * run followed by a non-sparse run (already covered above) and if @end
+ * is not in the next run switching it to be sparse, again reduces the
+ * problem to the already covered case of "@start is in a hole".
+ */
+ if (end >= rl[1].vcn) {
+ /*
+ * If @end is not in the next run, reduce the problem to the
+ * case of "@start is in a hole".
+ */
+ if (rl[1].length && end >= rl[2].vcn) {
+ /* Truncate the run containing @start. */
+ rl->length = start - rl->vcn;
+ rl++;
+ rl->vcn = start;
+ rl->lcn = LCN_HOLE;
+ goto extend_hole;
+ }
+ trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
+ if (IS_ERR(trl))
+ goto enomem_out;
+ old_size++;
+ if (runlist->rl != trl) {
+ rl = trl + (rl - runlist->rl);
+ rl_end = trl + (rl_end - runlist->rl);
+ rl_real_end = trl + (rl_real_end - runlist->rl);
+ runlist->rl = trl;
+ }
+ /* Truncate the run containing @start. */
+ rl->length = start - rl->vcn;
+ rl++;
+ /*
+ * @end is in the next run, reduce the problem to the case
+ * where "@start is at the beginning of a run and @end is in
+ * the same run as @start".
+ */
+ delta = rl->vcn - start;
+ rl->vcn = start;
+ if (rl->lcn >= 0) {
+ rl->lcn -= delta;
+ /* Need this in case the lcn just became negative. */
+ lcn_fixup = TRUE;
+ }
+ rl->length += delta;
+ goto split_end;
+ }
+ /*
+ * The first case from above, i.e. @end is in the same run as @start.
+ * We need to split the run into three. One run for the non-sparse
+ * region between the beginning of the old run and @start, one for the
+ * sparse region between @start and @end, and one for the remaining
+ * non-sparse region, i.e. between @end and the end of the old run.
+ */
+ trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 2);
+ if (IS_ERR(trl))
+ goto enomem_out;
+ old_size += 2;
+ if (runlist->rl != trl) {
+ rl = trl + (rl - runlist->rl);
+ rl_end = trl + (rl_end - runlist->rl);
+ rl_real_end = trl + (rl_real_end - runlist->rl);
+ runlist->rl = trl;
+ }
+ /* Shift all the runs up by two. */
+ memmove(rl + 2, rl, (rl_real_end - rl + 1) * sizeof(*rl));
+ /* Finally, setup the three split runs. */
+ rl->length = start - rl->vcn;
+ rl++;
+ rl->vcn = start;
+ rl->lcn = LCN_HOLE;
+ rl->length = length;
+ rl++;
+ delta = end - rl->vcn;
+ rl->vcn = end;
+ rl->lcn += delta;
+ rl->length -= delta;
+ ntfs_debug("Done (split both).");
+ return 0;
+enomem_out:
+ ntfs_error(vol->sb, "Not enough memory to extend runlist buffer.");
+ return -ENOMEM;
+}
+
#endif /* NTFS_RW */
diff --git a/fs/ntfs/runlist.h b/fs/ntfs/runlist.h
index aa0ee6540e7c..47728fbb610b 100644
--- a/fs/ntfs/runlist.h
+++ b/fs/ntfs/runlist.h
@@ -94,6 +94,9 @@ extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
extern int ntfs_rl_truncate_nolock(const ntfs_volume *vol,
runlist *const runlist, const s64 new_length);
+int ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist,
+ const VCN start, const s64 length);
+
#endif /* NTFS_RW */
#endif /* _LINUX_NTFS_RUNLIST_H */
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 41aa8eb6755b..453d0d51ea4b 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -126,6 +126,14 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
if (*v) \
goto needs_val; \
}
+#define NTFS_GETOPT_OCTAL(option, variable) \
+ if (!strcmp(p, option)) { \
+ if (!v || !*v) \
+ goto needs_arg; \
+ variable = simple_strtoul(ov = v, &v, 8); \
+ if (*v) \
+ goto needs_val; \
+ }
#define NTFS_GETOPT_BOOL(option, variable) \
if (!strcmp(p, option)) { \
BOOL val; \
@@ -157,9 +165,9 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
*v++ = 0;
NTFS_GETOPT("uid", uid)
else NTFS_GETOPT("gid", gid)
- else NTFS_GETOPT("umask", fmask = dmask)
- else NTFS_GETOPT("fmask", fmask)
- else NTFS_GETOPT("dmask", dmask)
+ else NTFS_GETOPT_OCTAL("umask", fmask = dmask)
+ else NTFS_GETOPT_OCTAL("fmask", fmask)
+ else NTFS_GETOPT_OCTAL("dmask", dmask)
else NTFS_GETOPT("mft_zone_multiplier", mft_zone_multiplier)
else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE)
else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files)
@@ -1133,7 +1141,8 @@ mft_unmap_out:
*
* Return TRUE on success or FALSE on error.
*/
-static BOOL load_and_check_logfile(ntfs_volume *vol)
+static BOOL load_and_check_logfile(ntfs_volume *vol,
+ RESTART_PAGE_HEADER **rp)
{
struct inode *tmp_ino;
@@ -1145,7 +1154,7 @@ static BOOL load_and_check_logfile(ntfs_volume *vol)
/* Caller will display error message. */
return FALSE;
}
- if (!ntfs_check_logfile(tmp_ino)) {
+ if (!ntfs_check_logfile(tmp_ino, rp)) {
iput(tmp_ino);
/* ntfs_check_logfile() will have displayed error output. */
return FALSE;
@@ -1689,6 +1698,7 @@ static BOOL load_system_files(ntfs_volume *vol)
VOLUME_INFORMATION *vi;
ntfs_attr_search_ctx *ctx;
#ifdef NTFS_RW
+ RESTART_PAGE_HEADER *rp;
int err;
#endif /* NTFS_RW */
@@ -1841,8 +1851,9 @@ get_ctx_vol_failed:
* Get the inode for the logfile, check it and determine if the volume
* was shutdown cleanly.
*/
- if (!load_and_check_logfile(vol) ||
- !ntfs_is_logfile_clean(vol->logfile_ino)) {
+ rp = NULL;
+ if (!load_and_check_logfile(vol, &rp) ||
+ !ntfs_is_logfile_clean(vol->logfile_ino, rp)) {
static const char *es1a = "Failed to load $LogFile";
static const char *es1b = "$LogFile is not clean";
static const char *es2 = ". Mount in Windows.";
@@ -1857,6 +1868,10 @@ get_ctx_vol_failed:
"continue nor on_errors="
"remount-ro was specified%s",
es1, es2);
+ if (vol->logfile_ino) {
+ BUG_ON(!rp);
+ ntfs_free(rp);
+ }
goto iput_logfile_err_out;
}
sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
@@ -1867,6 +1882,7 @@ get_ctx_vol_failed:
/* This will prevent a read-write remount. */
NVolSetErrors(vol);
}
+ ntfs_free(rp);
#endif /* NTFS_RW */
/* Get the root directory inode so we can do path lookups. */
vol->root_ino = ntfs_iget(sb, FILE_root);
diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c
index 19c42e231b44..a389a5a16c84 100644
--- a/fs/ntfs/unistr.c
+++ b/fs/ntfs/unistr.c
@@ -372,7 +372,8 @@ retry: wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o,
return -EINVAL;
conversion_err:
ntfs_error(vol->sb, "Unicode name contains characters that cannot be "
- "converted to character set %s.", nls->charset);
+ "converted to character set %s. You might want to "
+ "try to use the mount option nls=utf8.", nls->charset);
if (ns != *outs)
kfree(ns);
if (wc != -ENAMETOOLONG)
diff --git a/fs/open.c b/fs/open.c
index 32bf05e2996d..f0d90cf0495c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -24,6 +24,7 @@
#include <linux/personality.h>
#include <linux/pagemap.h>
#include <linux/syscalls.h>
+#include <linux/rcupdate.h>
#include <asm/unistd.h>
@@ -737,52 +738,15 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
return error;
}
-/*
- * Note that while the flag value (low two bits) for sys_open means:
- * 00 - read-only
- * 01 - write-only
- * 10 - read-write
- * 11 - special
- * it is changed into
- * 00 - no permissions needed
- * 01 - read-permission
- * 10 - write-permission
- * 11 - read-write
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-struct file *filp_open(const char * filename, int flags, int mode)
+static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ int flags, struct file *f)
{
- int namei_flags, error;
- struct nameidata nd;
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
- namei_flags++;
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
- error = open_namei(filename, namei_flags, mode, &nd);
- if (!error)
- return dentry_open(nd.dentry, nd.mnt, flags);
-
- return ERR_PTR(error);
-}
-
-EXPORT_SYMBOL(filp_open);
-
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-{
- struct file * f;
struct inode *inode;
int error;
- error = -ENFILE;
- f = get_empty_filp();
- if (!f)
- goto cleanup_dentry;
f->f_flags = flags;
- f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
+ f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
+ FMODE_PREAD | FMODE_PWRITE;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
@@ -827,12 +791,63 @@ cleanup_all:
f->f_vfsmnt = NULL;
cleanup_file:
put_filp(f);
-cleanup_dentry:
dput(dentry);
mntput(mnt);
return ERR_PTR(error);
}
+/*
+ * Note that while the flag value (low two bits) for sys_open means:
+ * 00 - read-only
+ * 01 - write-only
+ * 10 - read-write
+ * 11 - special
+ * it is changed into
+ * 00 - no permissions needed
+ * 01 - read-permission
+ * 10 - write-permission
+ * 11 - read-write
+ * for the internal routines (ie open_namei()/follow_link() etc). 00 is
+ * used by symlinks.
+ */
+struct file *filp_open(const char * filename, int flags, int mode)
+{
+ int namei_flags, error;
+ struct nameidata nd;
+ struct file *f;
+
+ namei_flags = flags;
+ if ((namei_flags+1) & O_ACCMODE)
+ namei_flags++;
+ if (namei_flags & O_TRUNC)
+ namei_flags |= 2;
+
+ error = -ENFILE;
+ f = get_empty_filp();
+ if (f == NULL)
+ return ERR_PTR(error);
+
+ error = open_namei(filename, namei_flags, mode, &nd);
+ if (!error)
+ return __dentry_open(nd.dentry, nd.mnt, flags, f);
+
+ put_filp(f);
+ return ERR_PTR(error);
+}
+EXPORT_SYMBOL(filp_open);
+
+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+{
+ int error;
+ struct file *f;
+
+ error = -ENFILE;
+ f = get_empty_filp();
+ if (f == NULL)
+ return ERR_PTR(error);
+
+ return __dentry_open(dentry, mnt, flags, f);
+}
EXPORT_SYMBOL(dentry_open);
/*
@@ -842,14 +857,16 @@ int get_unused_fd(void)
{
struct files_struct * files = current->files;
int fd, error;
+ struct fdtable *fdt;
error = -EMFILE;
spin_lock(&files->file_lock);
repeat:
- fd = find_next_zero_bit(files->open_fds->fds_bits,
- files->max_fdset,
- files->next_fd);
+ fdt = files_fdtable(files);
+ fd = find_next_zero_bit(fdt->open_fds->fds_bits,
+ fdt->max_fdset,
+ fdt->next_fd);
/*
* N.B. For clone tasks sharing a files structure, this test
@@ -872,14 +889,14 @@ repeat:
goto repeat;
}
- FD_SET(fd, files->open_fds);
- FD_CLR(fd, files->close_on_exec);
- files->next_fd = fd + 1;
+ FD_SET(fd, fdt->open_fds);
+ FD_CLR(fd, fdt->close_on_exec);
+ fdt->next_fd = fd + 1;
#if 1
/* Sanity check */
- if (files->fd[fd] != NULL) {
+ if (fdt->fd[fd] != NULL) {
printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
- files->fd[fd] = NULL;
+ fdt->fd[fd] = NULL;
}
#endif
error = fd;
@@ -893,9 +910,10 @@ EXPORT_SYMBOL(get_unused_fd);
static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
{
- __FD_CLR(fd, files->open_fds);
- if (fd < files->next_fd)
- files->next_fd = fd;
+ struct fdtable *fdt = files_fdtable(files);
+ __FD_CLR(fd, fdt->open_fds);
+ if (fd < fdt->next_fd)
+ fdt->next_fd = fd;
}
void fastcall put_unused_fd(unsigned int fd)
@@ -924,25 +942,21 @@ EXPORT_SYMBOL(put_unused_fd);
void fastcall fd_install(unsigned int fd, struct file * file)
{
struct files_struct *files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
- if (unlikely(files->fd[fd] != NULL))
- BUG();
- files->fd[fd] = file;
+ fdt = files_fdtable(files);
+ BUG_ON(fdt->fd[fd] != NULL);
+ rcu_assign_pointer(fdt->fd[fd], file);
spin_unlock(&files->file_lock);
}
EXPORT_SYMBOL(fd_install);
-asmlinkage long sys_open(const char __user * filename, int flags, int mode)
+long do_sys_open(const char __user *filename, int flags, int mode)
{
- char * tmp;
- int fd;
-
- if (force_o_largefile())
- flags |= O_LARGEFILE;
+ char *tmp = getname(filename);
+ int fd = PTR_ERR(tmp);
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
fd = get_unused_fd();
if (fd >= 0) {
@@ -959,6 +973,14 @@ asmlinkage long sys_open(const char __user * filename, int flags, int mode)
}
return fd;
}
+
+asmlinkage long sys_open(const char __user *filename, int flags, int mode)
+{
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
+
+ return do_sys_open(filename, flags, mode);
+}
EXPORT_SYMBOL_GPL(sys_open);
#ifndef __alpha__
@@ -1007,15 +1029,17 @@ asmlinkage long sys_close(unsigned int fd)
{
struct file * filp;
struct files_struct *files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
- if (fd >= files->max_fds)
+ fdt = files_fdtable(files);
+ if (fd >= fdt->max_fds)
goto out_unlock;
- filp = files->fd[fd];
+ filp = fdt->fd[fd];
if (!filp)
goto out_unlock;
- files->fd[fd] = NULL;
- FD_CLR(fd, files->close_on_exec);
+ rcu_assign_pointer(fdt->fd[fd], NULL);
+ FD_CLR(fd, fdt->close_on_exec);
__put_unused_fd(files, fd);
spin_unlock(&files->file_lock);
return filp_close(filp, files);
diff --git a/fs/pipe.c b/fs/pipe.c
index 25aa09f9d09d..66aa0b938d6a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -39,7 +39,11 @@ void pipe_wait(struct inode * inode)
{
DEFINE_WAIT(wait);
- prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE);
+ /*
+ * 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);
up(PIPE_SEM(*inode));
schedule();
finish_wait(PIPE_WAIT(*inode), &wait);
@@ -415,6 +419,10 @@ pipe_poll(struct file *filp, poll_table *wait)
if (filp->f_mode & FMODE_WRITE) {
mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0;
+ /*
+ * Most Unices do not set POLLERR for FIFOs but on Linux they
+ * behave exactly like pipes for poll().
+ */
if (!PIPE_READERS(*inode))
mask |= POLLERR;
}
@@ -422,9 +430,6 @@ pipe_poll(struct file *filp, poll_table *wait)
return mask;
}
-/* FIXME: most Unices do not set POLLERR for fifos */
-#define fifo_poll pipe_poll
-
static int
pipe_release(struct inode *inode, int decr, int decw)
{
@@ -568,7 +573,7 @@ struct file_operations read_fifo_fops = {
.read = pipe_read,
.readv = pipe_readv,
.write = bad_pipe_w,
- .poll = fifo_poll,
+ .poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_read_open,
.release = pipe_read_release,
@@ -580,7 +585,7 @@ struct file_operations write_fifo_fops = {
.read = bad_pipe_r,
.write = pipe_write,
.writev = pipe_writev,
- .poll = fifo_poll,
+ .poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_write_open,
.release = pipe_write_release,
@@ -593,7 +598,7 @@ struct file_operations rdwr_fifo_fops = {
.readv = pipe_readv,
.write = pipe_write,
.writev = pipe_writev,
- .poll = fifo_poll,
+ .poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_rdwr_open,
.release = pipe_rdwr_release,
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 37668fe998ad..d88d518d30f6 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -159,6 +159,7 @@ static inline char * task_state(struct task_struct *p, char *buffer)
{
struct group_info *group_info;
int g;
+ struct fdtable *fdt = NULL;
read_lock(&tasklist_lock);
buffer += sprintf(buffer,
@@ -179,10 +180,12 @@ static inline char * task_state(struct task_struct *p, char *buffer)
p->gid, p->egid, p->sgid, p->fsgid);
read_unlock(&tasklist_lock);
task_lock(p);
+ if (p->files)
+ fdt = files_fdtable(p->files);
buffer += sprintf(buffer,
"FDSize:\t%d\n"
"Groups:\t",
- p->files ? p->files->max_fds : 0);
+ fdt ? fdt->max_fds : 0);
group_info = p->group_info;
get_group_info(group_info);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 491f2d9f89ac..23db452ab428 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -11,6 +11,40 @@
* go into icache. We cache the reference to task_struct upon lookup too.
* Eventually it should become a filesystem in its own. We don't use the
* rest of procfs anymore.
+ *
+ *
+ * Changelog:
+ * 17-Jan-2005
+ * Allan Bezerra
+ * Bruna Moreira <bruna.moreira@indt.org.br>
+ * Edjard Mota <edjard.mota@indt.org.br>
+ * Ilias Biris <ilias.biris@indt.org.br>
+ * Mauricio Lin <mauricio.lin@indt.org.br>
+ *
+ * Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
+ *
+ * A new process specific entry (smaps) included in /proc. It shows the
+ * size of rss for each memory area. The maps entry lacks information
+ * about physical memory size (rss) for each mapped file, i.e.,
+ * rss information for executables and library files.
+ * This additional information is useful for any tools that need to know
+ * about physical memory consumption for a process specific library.
+ *
+ * Changelog:
+ * 21-Feb-2005
+ * Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
+ * Pud inclusion in the page table walking.
+ *
+ * ChangeLog:
+ * 10-Mar-2005
+ * 10LE Instituto Nokia de Tecnologia - INdT:
+ * A better way to walks through the page table as suggested by Hugh Dickins.
+ *
+ * Simo Piiroinen <simo.piiroinen@nokia.com>:
+ * Smaps information related to shared, private, clean and dirty pages.
+ *
+ * Paul Mundt <paul.mundt@nokia.com>:
+ * Overall revision about smaps.
*/
#include <asm/uaccess.h>
@@ -28,6 +62,7 @@
#include <linux/namespace.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
+#include <linux/rcupdate.h>
#include <linux/kallsyms.h>
#include <linux/mount.h>
#include <linux/security.h>
@@ -65,8 +100,10 @@ enum pid_directory_inos {
PROC_TGID_STAT,
PROC_TGID_STATM,
PROC_TGID_MAPS,
+ PROC_TGID_NUMA_MAPS,
PROC_TGID_MOUNTS,
PROC_TGID_WCHAN,
+ PROC_TGID_SMAPS,
#ifdef CONFIG_SCHEDSTATS
PROC_TGID_SCHEDSTAT,
#endif
@@ -83,7 +120,6 @@ enum pid_directory_inos {
#ifdef CONFIG_AUDITSYSCALL
PROC_TGID_LOGINUID,
#endif
- PROC_TGID_FD_DIR,
PROC_TGID_OOM_SCORE,
PROC_TGID_OOM_ADJUST,
PROC_TID_INO,
@@ -102,8 +138,10 @@ enum pid_directory_inos {
PROC_TID_STAT,
PROC_TID_STATM,
PROC_TID_MAPS,
+ PROC_TID_NUMA_MAPS,
PROC_TID_MOUNTS,
PROC_TID_WCHAN,
+ PROC_TID_SMAPS,
#ifdef CONFIG_SCHEDSTATS
PROC_TID_SCHEDSTAT,
#endif
@@ -120,9 +158,11 @@ enum pid_directory_inos {
#ifdef CONFIG_AUDITSYSCALL
PROC_TID_LOGINUID,
#endif
- PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
PROC_TID_OOM_SCORE,
PROC_TID_OOM_ADJUST,
+
+ /* Add new entries before this */
+ PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};
struct pid_entry {
@@ -144,6 +184,9 @@ static struct pid_entry tgid_base_stuff[] = {
E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+ E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+#endif
E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
#ifdef CONFIG_SECCOMP
E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -152,6 +195,7 @@ static struct pid_entry tgid_base_stuff[] = {
E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+ E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
#ifdef CONFIG_SECURITY
E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
#endif
@@ -180,6 +224,9 @@ static struct pid_entry tid_base_stuff[] = {
E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+ E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+#endif
E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
#ifdef CONFIG_SECCOMP
E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
@@ -188,6 +235,7 @@ static struct pid_entry tid_base_stuff[] = {
E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+ E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
#ifdef CONFIG_SECURITY
E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
#endif
@@ -236,30 +284,36 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
files = get_files_struct(task);
if (files) {
- spin_lock(&files->file_lock);
+ rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
*mnt = mntget(file->f_vfsmnt);
*dentry = dget(file->f_dentry);
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
return 0;
}
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
}
return -ENOENT;
}
-static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+static struct fs_struct *get_fs_struct(struct task_struct *task)
{
struct fs_struct *fs;
- int result = -ENOENT;
- task_lock(proc_task(inode));
- fs = proc_task(inode)->fs;
+ task_lock(task);
+ fs = task->fs;
if(fs)
atomic_inc(&fs->count);
- task_unlock(proc_task(inode));
+ task_unlock(task);
+ return fs;
+}
+
+static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+{
+ struct fs_struct *fs = get_fs_struct(proc_task(inode));
+ int result = -ENOENT;
if (fs) {
read_lock(&fs->lock);
*mnt = mntget(fs->pwdmnt);
@@ -273,13 +327,8 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs
static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
- struct fs_struct *fs;
+ struct fs_struct *fs = get_fs_struct(proc_task(inode));
int result = -ENOENT;
- task_lock(proc_task(inode));
- fs = proc_task(inode)->fs;
- if(fs)
- atomic_inc(&fs->count);
- task_unlock(proc_task(inode));
if (fs) {
read_lock(&fs->lock);
*mnt = mntget(fs->rootmnt);
@@ -298,33 +347,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
(task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
security_ptrace(current,task) == 0))
-static int may_ptrace_attach(struct task_struct *task)
-{
- int retval = 0;
-
- task_lock(task);
-
- if (!task->mm)
- goto out;
- if (((current->uid != task->euid) ||
- (current->uid != task->suid) ||
- (current->uid != task->uid) ||
- (current->gid != task->egid) ||
- (current->gid != task->sgid) ||
- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
- goto out;
- rmb();
- if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
- goto out;
- if (security_ptrace(current, task))
- goto out;
-
- retval = 1;
-out:
- task_unlock(task);
- return retval;
-}
-
static int proc_pid_environ(struct task_struct *task, char * buffer)
{
int res = 0;
@@ -334,7 +356,7 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
if (len > PAGE_SIZE)
len = PAGE_SIZE;
res = access_process_vm(task, mm->env_start, buffer, len, 0);
- if (!may_ptrace_attach(task))
+ if (!ptrace_may_attach(task))
res = -ESRCH;
mmput(mm);
}
@@ -515,6 +537,46 @@ static struct file_operations proc_maps_operations = {
.release = seq_release,
};
+#ifdef CONFIG_NUMA
+extern struct seq_operations proc_pid_numa_maps_op;
+static int numa_maps_open(struct inode *inode, struct file *file)
+{
+ struct task_struct *task = proc_task(inode);
+ int ret = seq_open(file, &proc_pid_numa_maps_op);
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ m->private = task;
+ }
+ return ret;
+}
+
+static struct file_operations proc_numa_maps_operations = {
+ .open = numa_maps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif
+
+extern struct seq_operations proc_pid_smaps_op;
+static int smaps_open(struct inode *inode, struct file *file)
+{
+ struct task_struct *task = proc_task(inode);
+ int ret = seq_open(file, &proc_pid_smaps_op);
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ m->private = task;
+ }
+ return ret;
+}
+
+static struct file_operations proc_smaps_operations = {
+ .open = smaps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
extern struct seq_operations mounts_op;
static int mounts_open(struct inode *inode, struct file *file)
{
@@ -597,7 +659,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
int ret = -ESRCH;
struct mm_struct *mm;
- if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
+ if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
goto out;
ret = -ENOMEM;
@@ -623,7 +685,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
retval = access_process_vm(task, src, page, this_len, 0);
- if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) {
+ if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {
if (!ret)
ret = -EIO;
break;
@@ -661,7 +723,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
struct task_struct *task = proc_task(file->f_dentry->d_inode);
unsigned long dst = *ppos;
- if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
+ if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
return -ESRCH;
page = (char *)__get_free_page(GFP_USER);
@@ -978,6 +1040,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
int retval;
char buf[NUMBUF];
struct files_struct * files;
+ struct fdtable *fdt;
retval = -ENOENT;
if (!pid_alive(p))
@@ -1000,15 +1063,16 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
files = get_files_struct(p);
if (!files)
goto out;
- spin_lock(&files->file_lock);
+ rcu_read_lock();
+ fdt = files_fdtable(files);
for (fd = filp->f_pos-2;
- fd < files->max_fds;
+ fd < fdt->max_fds;
fd++, filp->f_pos++) {
unsigned int i,j;
if (!fcheck_files(files, fd))
continue;
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
j = NUMBUF;
i = fd;
@@ -1020,12 +1084,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
- spin_lock(&files->file_lock);
+ rcu_read_lock();
break;
}
- spin_lock(&files->file_lock);
+ rcu_read_lock();
}
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
}
out:
@@ -1200,9 +1264,9 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
files = get_files_struct(task);
if (files) {
- spin_lock(&files->file_lock);
+ rcu_read_lock();
if (fcheck_files(files, fd)) {
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
if (task_dumpable(task)) {
inode->i_uid = task->euid;
@@ -1214,7 +1278,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
security_task_to_inode(task, inode);
return 1;
}
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
}
d_drop(dentry);
@@ -1306,7 +1370,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
if (!files)
goto out_unlock;
inode->i_mode = S_IFLNK;
- spin_lock(&files->file_lock);
+ rcu_read_lock();
file = fcheck_files(files, fd);
if (!file)
goto out_unlock2;
@@ -1314,7 +1378,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;
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
@@ -1324,7 +1388,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
return NULL;
out_unlock2:
- spin_unlock(&files->file_lock);
+ rcu_read_unlock();
put_files_struct(files);
out_unlock:
iput(inode);
@@ -1524,6 +1588,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
case PROC_TGID_MAPS:
inode->i_fop = &proc_maps_operations;
break;
+#ifdef CONFIG_NUMA
+ case PROC_TID_NUMA_MAPS:
+ case PROC_TGID_NUMA_MAPS:
+ inode->i_fop = &proc_numa_maps_operations;
+ break;
+#endif
case PROC_TID_MEM:
case PROC_TGID_MEM:
inode->i_op = &proc_mem_inode_operations;
@@ -1539,6 +1609,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
case PROC_TGID_MOUNTS:
inode->i_fop = &proc_mounts_operations;
break;
+ case PROC_TID_SMAPS:
+ case PROC_TGID_SMAPS:
+ inode->i_fop = &proc_smaps_operations;
+ break;
#ifdef CONFIG_SECURITY
case PROC_TID_ATTR:
inode->i_nlink = 2;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index abe8920313fb..8a8c34461d48 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -249,6 +249,18 @@ out:
return error;
}
+static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+ struct proc_dir_entry *de = PROC_I(inode)->pde;
+ if (de && de->nlink)
+ inode->i_nlink = de->nlink;
+
+ generic_fillattr(inode, stat);
+ return 0;
+}
+
static struct inode_operations proc_file_inode_operations = {
.setattr = proc_notify_change,
};
@@ -475,6 +487,7 @@ static struct file_operations proc_dir_operations = {
*/
static struct inode_operations proc_dir_inode_operations = {
.lookup = proc_lookup,
+ .getattr = proc_getattr,
.setattr = proc_notify_change,
};
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 133c28685105..effa6c0c467a 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -60,6 +60,8 @@ static void proc_delete_inode(struct inode *inode)
struct proc_dir_entry *de;
struct task_struct *tsk;
+ truncate_inode_pages(&inode->i_data, 0);
+
/* Let go of any associated process */
tsk = PROC_I(inode)->task;
if (tsk)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 28b4a0253a92..c7ef3e48e35b 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -2,8 +2,13 @@
#include <linux/hugetlb.h>
#include <linux/mount.h>
#include <linux/seq_file.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/mempolicy.h>
+
#include <asm/elf.h>
#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
#include "internal.h"
char *task_mem(struct mm_struct *mm, char *buffer)
@@ -87,49 +92,58 @@ static void pad_len_spaces(struct seq_file *m, int len)
seq_printf(m, "%*c", len, ' ');
}
-static int show_map(struct seq_file *m, void *v)
+struct mem_size_stats
+{
+ unsigned long resident;
+ unsigned long shared_clean;
+ unsigned long shared_dirty;
+ unsigned long private_clean;
+ unsigned long private_dirty;
+};
+
+static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
{
struct task_struct *task = m->private;
- struct vm_area_struct *map = v;
- struct mm_struct *mm = map->vm_mm;
- struct file *file = map->vm_file;
- int flags = map->vm_flags;
+ struct vm_area_struct *vma = v;
+ struct mm_struct *mm = vma->vm_mm;
+ struct file *file = vma->vm_file;
+ int flags = vma->vm_flags;
unsigned long ino = 0;
dev_t dev = 0;
int len;
if (file) {
- struct inode *inode = map->vm_file->f_dentry->d_inode;
+ struct inode *inode = vma->vm_file->f_dentry->d_inode;
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
}
seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
- map->vm_start,
- map->vm_end,
+ vma->vm_start,
+ vma->vm_end,
flags & VM_READ ? 'r' : '-',
flags & VM_WRITE ? 'w' : '-',
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? 's' : 'p',
- map->vm_pgoff << PAGE_SHIFT,
+ vma->vm_pgoff << PAGE_SHIFT,
MAJOR(dev), MINOR(dev), ino, &len);
/*
* Print the dentry name for named mappings, and a
* special [heap] marker for the heap:
*/
- if (map->vm_file) {
+ if (file) {
pad_len_spaces(m, len);
- seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+ seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
} else {
if (mm) {
- if (map->vm_start <= mm->start_brk &&
- map->vm_end >= mm->brk) {
+ if (vma->vm_start <= mm->start_brk &&
+ vma->vm_end >= mm->brk) {
pad_len_spaces(m, len);
seq_puts(m, "[heap]");
} else {
- if (map->vm_start <= mm->start_stack &&
- map->vm_end >= mm->start_stack) {
+ if (vma->vm_start <= mm->start_stack &&
+ vma->vm_end >= mm->start_stack) {
pad_len_spaces(m, len);
seq_puts(m, "[stack]");
@@ -141,24 +155,146 @@ static int show_map(struct seq_file *m, void *v)
}
}
seq_putc(m, '\n');
- if (m->count < m->size) /* map is copied successfully */
- m->version = (map != get_gate_vma(task))? map->vm_start: 0;
+
+ if (mss)
+ seq_printf(m,
+ "Size: %8lu kB\n"
+ "Rss: %8lu kB\n"
+ "Shared_Clean: %8lu kB\n"
+ "Shared_Dirty: %8lu kB\n"
+ "Private_Clean: %8lu kB\n"
+ "Private_Dirty: %8lu kB\n",
+ (vma->vm_end - vma->vm_start) >> 10,
+ mss->resident >> 10,
+ mss->shared_clean >> 10,
+ mss->shared_dirty >> 10,
+ mss->private_clean >> 10,
+ mss->private_dirty >> 10);
+
+ if (m->count < m->size) /* vma is copied successfully */
+ m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
return 0;
}
+static int show_map(struct seq_file *m, void *v)
+{
+ return show_map_internal(m, v, 0);
+}
+
+static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long addr, unsigned long end,
+ struct mem_size_stats *mss)
+{
+ pte_t *pte, ptent;
+ unsigned long pfn;
+ struct page *page;
+
+ pte = pte_offset_map(pmd, addr);
+ do {
+ ptent = *pte;
+ if (pte_none(ptent) || !pte_present(ptent))
+ continue;
+
+ mss->resident += PAGE_SIZE;
+ pfn = pte_pfn(ptent);
+ if (!pfn_valid(pfn))
+ continue;
+
+ page = pfn_to_page(pfn);
+ if (page_count(page) >= 2) {
+ if (pte_dirty(ptent))
+ mss->shared_dirty += PAGE_SIZE;
+ else
+ mss->shared_clean += PAGE_SIZE;
+ } else {
+ if (pte_dirty(ptent))
+ mss->private_dirty += PAGE_SIZE;
+ else
+ mss->private_clean += PAGE_SIZE;
+ }
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ pte_unmap(pte - 1);
+ cond_resched_lock(&vma->vm_mm->page_table_lock);
+}
+
+static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ struct mem_size_stats *mss)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ smaps_pte_range(vma, pmd, addr, next, mss);
+ } while (pmd++, addr = next, addr != end);
+}
+
+static inline void smaps_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ struct mem_size_stats *mss)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ smaps_pmd_range(vma, pud, addr, next, mss);
+ } while (pud++, addr = next, addr != end);
+}
+
+static inline void smaps_pgd_range(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct mem_size_stats *mss)
+{
+ pgd_t *pgd;
+ unsigned long next;
+
+ pgd = pgd_offset(vma->vm_mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ smaps_pud_range(vma, pgd, addr, next, mss);
+ } while (pgd++, addr = next, addr != end);
+}
+
+static int show_smap(struct seq_file *m, void *v)
+{
+ struct vm_area_struct *vma = v;
+ struct mm_struct *mm = vma->vm_mm;
+ struct mem_size_stats mss;
+
+ memset(&mss, 0, sizeof mss);
+
+ if (mm) {
+ spin_lock(&mm->page_table_lock);
+ smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss);
+ spin_unlock(&mm->page_table_lock);
+ }
+
+ return show_map_internal(m, v, &mss);
+}
+
static void *m_start(struct seq_file *m, loff_t *pos)
{
struct task_struct *task = m->private;
unsigned long last_addr = m->version;
struct mm_struct *mm;
- struct vm_area_struct *map, *tail_map;
+ struct vm_area_struct *vma, *tail_vma;
loff_t l = *pos;
/*
* We remember last_addr rather than next_addr to hit with
* mmap_cache most of the time. We have zero last_addr at
- * the begining and also after lseek. We will have -1 last_addr
- * after the end of the maps.
+ * the beginning and also after lseek. We will have -1 last_addr
+ * after the end of the vmas.
*/
if (last_addr == -1UL)
@@ -168,47 +304,47 @@ static void *m_start(struct seq_file *m, loff_t *pos)
if (!mm)
return NULL;
- tail_map = get_gate_vma(task);
+ tail_vma = get_gate_vma(task);
down_read(&mm->mmap_sem);
/* Start with last addr hint */
- if (last_addr && (map = find_vma(mm, last_addr))) {
- map = map->vm_next;
+ if (last_addr && (vma = find_vma(mm, last_addr))) {
+ vma = vma->vm_next;
goto out;
}
/*
- * Check the map index is within the range and do
+ * Check the vma index is within the range and do
* sequential scan until m_index.
*/
- map = NULL;
+ vma = NULL;
if ((unsigned long)l < mm->map_count) {
- map = mm->mmap;
- while (l-- && map)
- map = map->vm_next;
+ vma = mm->mmap;
+ while (l-- && vma)
+ vma = vma->vm_next;
goto out;
}
if (l != mm->map_count)
- tail_map = NULL; /* After gate map */
+ tail_vma = NULL; /* After gate vma */
out:
- if (map)
- return map;
+ if (vma)
+ return vma;
- /* End of maps has reached */
- m->version = (tail_map != NULL)? 0: -1UL;
+ /* End of vmas has been reached */
+ m->version = (tail_vma != NULL)? 0: -1UL;
up_read(&mm->mmap_sem);
mmput(mm);
- return tail_map;
+ return tail_vma;
}
static void m_stop(struct seq_file *m, void *v)
{
struct task_struct *task = m->private;
- struct vm_area_struct *map = v;
- if (map && map != get_gate_vma(task)) {
- struct mm_struct *mm = map->vm_mm;
+ struct vm_area_struct *vma = v;
+ if (vma && vma != get_gate_vma(task)) {
+ struct mm_struct *mm = vma->vm_mm;
up_read(&mm->mmap_sem);
mmput(mm);
}
@@ -217,14 +353,14 @@ static void m_stop(struct seq_file *m, void *v)
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
struct task_struct *task = m->private;
- struct vm_area_struct *map = v;
- struct vm_area_struct *tail_map = get_gate_vma(task);
+ struct vm_area_struct *vma = v;
+ struct vm_area_struct *tail_vma = get_gate_vma(task);
(*pos)++;
- if (map && (map != tail_map) && map->vm_next)
- return map->vm_next;
+ if (vma && (vma != tail_vma) && vma->vm_next)
+ return vma->vm_next;
m_stop(m, v);
- return (map != tail_map)? tail_map: NULL;
+ return (vma != tail_vma)? tail_vma: NULL;
}
struct seq_operations proc_pid_maps_op = {
@@ -233,3 +369,140 @@ struct seq_operations proc_pid_maps_op = {
.stop = m_stop,
.show = show_map
};
+
+struct seq_operations proc_pid_smaps_op = {
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_smap
+};
+
+#ifdef CONFIG_NUMA
+
+struct numa_maps {
+ unsigned long pages;
+ unsigned long anon;
+ unsigned long mapped;
+ unsigned long mapcount_max;
+ unsigned long node[MAX_NUMNODES];
+};
+
+/*
+ * Calculate numa node maps for a vma
+ */
+static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma)
+{
+ struct page *page;
+ unsigned long vaddr;
+ struct mm_struct *mm = vma->vm_mm;
+ int i;
+ struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL);
+
+ if (!md)
+ return NULL;
+ md->pages = 0;
+ md->anon = 0;
+ md->mapped = 0;
+ md->mapcount_max = 0;
+ for_each_node(i)
+ md->node[i] =0;
+
+ spin_lock(&mm->page_table_lock);
+ for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) {
+ page = follow_page(mm, vaddr, 0);
+ if (page) {
+ int count = page_mapcount(page);
+
+ if (count)
+ md->mapped++;
+ if (count > md->mapcount_max)
+ md->mapcount_max = count;
+ md->pages++;
+ if (PageAnon(page))
+ md->anon++;
+ md->node[page_to_nid(page)]++;
+ }
+ }
+ spin_unlock(&mm->page_table_lock);
+ return md;
+}
+
+static int show_numa_map(struct seq_file *m, void *v)
+{
+ struct task_struct *task = m->private;
+ struct vm_area_struct *vma = v;
+ struct mempolicy *pol;
+ struct numa_maps *md;
+ struct zone **z;
+ int n;
+ int first;
+
+ if (!vma->vm_mm)
+ return 0;
+
+ md = get_numa_maps(vma);
+ if (!md)
+ return 0;
+
+ seq_printf(m, "%08lx", vma->vm_start);
+ pol = get_vma_policy(task, vma, vma->vm_start);
+ /* Print policy */
+ switch (pol->policy) {
+ case MPOL_PREFERRED:
+ seq_printf(m, " prefer=%d", pol->v.preferred_node);
+ break;
+ case MPOL_BIND:
+ seq_printf(m, " bind={");
+ first = 1;
+ for (z = pol->v.zonelist->zones; *z; z++) {
+
+ if (!first)
+ seq_putc(m, ',');
+ else
+ first = 0;
+ seq_printf(m, "%d/%s", (*z)->zone_pgdat->node_id,
+ (*z)->name);
+ }
+ seq_putc(m, '}');
+ break;
+ case MPOL_INTERLEAVE:
+ seq_printf(m, " interleave={");
+ first = 1;
+ for_each_node(n) {
+ if (test_bit(n, pol->v.nodes)) {
+ if (!first)
+ seq_putc(m,',');
+ else
+ first = 0;
+ seq_printf(m, "%d",n);
+ }
+ }
+ seq_putc(m, '}');
+ break;
+ default:
+ seq_printf(m," default");
+ break;
+ }
+ seq_printf(m, " MaxRef=%lu Pages=%lu Mapped=%lu",
+ md->mapcount_max, md->pages, md->mapped);
+ if (md->anon)
+ seq_printf(m," Anon=%lu",md->anon);
+
+ for_each_online_node(n) {
+ if (md->node[n])
+ seq_printf(m, " N%d=%lu", n, md->node[n]);
+ }
+ seq_putc(m, '\n');
+ kfree(md);
+ if (m->count < m->size) /* vma is copied successfully */
+ m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0;
+ return 0;
+}
+
+struct seq_operations proc_pid_numa_maps_op = {
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_numa_map
+};
+#endif
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index b79162a35478..80f32911c0cb 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -63,6 +63,7 @@ int qnx4_sync_inode(struct inode *inode)
static void qnx4_delete_inode(struct inode *inode)
{
QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
+ truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
qnx4_truncate(inode);
lock_kernel();
diff --git a/fs/read_write.c b/fs/read_write.c
index 563abd09b5c8..b60324aaa2b6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -188,7 +188,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
struct inode *inode;
loff_t pos;
- if (unlikely(count > file->f_maxcount))
+ if (unlikely(count > INT_MAX))
goto Einval;
pos = *ppos;
if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index c9f178fb494f..c20babd6216d 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -667,7 +667,7 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
if (th->t_trans_id) {
int err;
// update any changes we made to blk count
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
err =
journal_end(th, inode->i_sb,
JOURNAL_PER_BALANCE_CNT * 3 + 1 +
@@ -855,17 +855,18 @@ static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_han
if (th->t_trans_id) {
reiserfs_write_lock(inode->i_sb);
- reiserfs_update_sd(th, inode); // And update on-disk metadata
+ // this sets the proper flags for O_SYNC to trigger a commit
+ mark_inode_dirty(inode);
reiserfs_write_unlock(inode->i_sb);
} else
- inode->i_sb->s_op->dirty_inode(inode);
+ mark_inode_dirty(inode);
sd_update = 1;
}
if (th->t_trans_id) {
reiserfs_write_lock(inode->i_sb);
if (!sd_update)
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
status = journal_end(th, th->t_super, th->t_blocks_allocated);
if (status)
retval = status;
@@ -1320,7 +1321,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
return err;
}
reiserfs_update_inode_transaction(inode);
- reiserfs_update_sd(&th, inode);
+ mark_inode_dirty(inode);
err = journal_end(&th, inode->i_sb, 1);
if (err) {
reiserfs_write_unlock(inode->i_sb);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ff291c973a56..d76ee6c4f9b8 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -33,6 +33,8 @@ void reiserfs_delete_inode(struct inode *inode)
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th;
+ truncate_inode_pages(&inode->i_data, 0);
+
reiserfs_write_lock(inode->i_sb);
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
@@ -2637,6 +2639,12 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
}
reiserfs_update_inode_transaction(inode);
inode->i_size = pos;
+ /*
+ * this will just nest into our transaction. It's important
+ * to use mark_inode_dirty so the inode gets pushed around on the
+ * dirty lists, and so that O_SYNC works as expected
+ */
+ mark_inode_dirty(inode);
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
@@ -2647,21 +2655,13 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!update_sd)
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
ret = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
if (ret)
goto out;
}
- /* we test for O_SYNC here so we can commit the transaction
- ** for any packed tails the file might have had
- */
- if (f && (f->f_flags & O_SYNC)) {
- reiserfs_write_lock(inode->i_sb);
- ret = reiserfs_commit_for_inode(inode);
- reiserfs_write_unlock(inode->i_sb);
- }
out:
return ret;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index ca7989b04be3..4b15761434bc 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1034,7 +1034,7 @@ static int flush_commit_list(struct super_block *s,
SB_ONDISK_JOURNAL_SIZE(s);
tbh = journal_find_get_block(s, bn);
if (buffer_dirty(tbh)) /* redundant, ll_rw_block() checks */
- ll_rw_block(WRITE, 1, &tbh);
+ ll_rw_block(SWRITE, 1, &tbh);
put_bh(tbh);
}
atomic_dec(&journal->j_async_throttle);
@@ -2172,7 +2172,7 @@ static int journal_read_transaction(struct super_block *p_s_sb,
/* flush out the real blocks */
for (i = 0; i < get_desc_trans_len(desc); i++) {
set_buffer_dirty(real_blocks[i]);
- ll_rw_block(WRITE, 1, real_blocks + i);
+ ll_rw_block(SWRITE, 1, real_blocks + i);
}
for (i = 0; i < get_desc_trans_len(desc); i++) {
wait_on_buffer(real_blocks[i]);
@@ -2868,8 +2868,7 @@ static void let_transaction_grow(struct super_block *sb, unsigned long trans_id)
struct reiserfs_journal *journal = SB_JOURNAL(sb);
unsigned long bcount = journal->j_bcount;
while (1) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
journal->j_current_jl->j_state |= LIST_COMMIT_PENDING;
while ((atomic_read(&journal->j_wcount) > 0 ||
atomic_read(&journal->j_jlock)) &&
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 6951c35755be..44b02fc02ebe 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1934,8 +1934,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
if (SB_AP_BITMAP(s))
brelse(SB_AP_BITMAP(s)[j].bh);
}
- if (SB_AP_BITMAP(s))
- vfree(SB_AP_BITMAP(s));
+ vfree(SB_AP_BITMAP(s));
}
if (SB_BUFFER_WITH_SB(s))
brelse(SB_BUFFER_WITH_SB(s));
diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile
new file mode 100644
index 000000000000..e76e182cdb38
--- /dev/null
+++ b/fs/relayfs/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RELAYFS_FS) += relayfs.o
+
+relayfs-y := relay.o inode.o buffers.o
+
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
new file mode 100644
index 000000000000..2aa8e2719999
--- /dev/null
+++ b/fs/relayfs/buffers.c
@@ -0,0 +1,189 @@
+/*
+ * RelayFS buffer management code.
+ *
+ * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
+ * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+/*
+ * close() vm_op implementation for relayfs file mapping.
+ */
+static void relay_file_mmap_close(struct vm_area_struct *vma)
+{
+ struct rchan_buf *buf = vma->vm_private_data;
+ buf->chan->cb->buf_unmapped(buf, vma->vm_file);
+}
+
+/*
+ * nopage() vm_op implementation for relayfs file mapping.
+ */
+static struct page *relay_buf_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int *type)
+{
+ struct page *page;
+ struct rchan_buf *buf = vma->vm_private_data;
+ unsigned long offset = address - vma->vm_start;
+
+ if (address > vma->vm_end)
+ return NOPAGE_SIGBUS; /* Disallow mremap */
+ if (!buf)
+ return NOPAGE_OOM;
+
+ page = vmalloc_to_page(buf->start + offset);
+ if (!page)
+ return NOPAGE_OOM;
+ get_page(page);
+
+ if (type)
+ *type = VM_FAULT_MINOR;
+
+ return page;
+}
+
+/*
+ * vm_ops for relay file mappings.
+ */
+static struct vm_operations_struct relay_file_mmap_ops = {
+ .nopage = relay_buf_nopage,
+ .close = relay_file_mmap_close,
+};
+
+/**
+ * relay_mmap_buf: - mmap channel buffer to process address space
+ * @buf: relay channel buffer
+ * @vma: vm_area_struct describing memory to be mapped
+ *
+ * Returns 0 if ok, negative on error
+ *
+ * Caller should already have grabbed mmap_sem.
+ */
+int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
+{
+ unsigned long length = vma->vm_end - vma->vm_start;
+ struct file *filp = vma->vm_file;
+
+ if (!buf)
+ return -EBADF;
+
+ if (length != (unsigned long)buf->chan->alloc_size)
+ return -EINVAL;
+
+ vma->vm_ops = &relay_file_mmap_ops;
+ vma->vm_private_data = buf;
+ buf->chan->cb->buf_mapped(buf, filp);
+
+ return 0;
+}
+
+/**
+ * relay_alloc_buf - allocate a channel buffer
+ * @buf: the buffer struct
+ * @size: total size of the buffer
+ *
+ * Returns a pointer to the resulting buffer, NULL if unsuccessful
+ */
+static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
+{
+ void *mem;
+ unsigned int i, j, n_pages;
+
+ size = PAGE_ALIGN(size);
+ n_pages = size >> PAGE_SHIFT;
+
+ buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
+ if (!buf->page_array)
+ return NULL;
+
+ for (i = 0; i < n_pages; i++) {
+ buf->page_array[i] = alloc_page(GFP_KERNEL);
+ if (unlikely(!buf->page_array[i]))
+ goto depopulate;
+ }
+ mem = vmap(buf->page_array, n_pages, GFP_KERNEL, PAGE_KERNEL);
+ if (!mem)
+ goto depopulate;
+
+ memset(mem, 0, size);
+ buf->page_count = n_pages;
+ return mem;
+
+depopulate:
+ for (j = 0; j < i; j++)
+ __free_page(buf->page_array[j]);
+ kfree(buf->page_array);
+ return NULL;
+}
+
+/**
+ * relay_create_buf - allocate and initialize a channel buffer
+ * @alloc_size: size of the buffer to allocate
+ * @n_subbufs: number of sub-buffers in the channel
+ *
+ * Returns channel buffer if successful, NULL otherwise
+ */
+struct rchan_buf *relay_create_buf(struct rchan *chan)
+{
+ struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
+ if (!buf->padding)
+ goto free_buf;
+
+ buf->start = relay_alloc_buf(buf, chan->alloc_size);
+ if (!buf->start)
+ goto free_buf;
+
+ buf->chan = chan;
+ kref_get(&buf->chan->kref);
+ return buf;
+
+free_buf:
+ kfree(buf->padding);
+ kfree(buf);
+ return NULL;
+}
+
+/**
+ * relay_destroy_buf - destroy an rchan_buf struct and associated buffer
+ * @buf: the buffer struct
+ */
+void relay_destroy_buf(struct rchan_buf *buf)
+{
+ struct rchan *chan = buf->chan;
+ unsigned int i;
+
+ if (likely(buf->start)) {
+ vunmap(buf->start);
+ for (i = 0; i < buf->page_count; i++)
+ __free_page(buf->page_array[i]);
+ kfree(buf->page_array);
+ }
+ kfree(buf->padding);
+ kfree(buf);
+ kref_put(&chan->kref, relay_destroy_channel);
+}
+
+/**
+ * relay_remove_buf - remove a channel buffer
+ *
+ * Removes the file from the relayfs fileystem, which also frees the
+ * rchan_buf_struct and the channel buffer. Should only be called from
+ * kref_put().
+ */
+void relay_remove_buf(struct kref *kref)
+{
+ struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
+ relayfs_remove(buf->dentry);
+}
diff --git a/fs/relayfs/buffers.h b/fs/relayfs/buffers.h
new file mode 100644
index 000000000000..37a12493f641
--- /dev/null
+++ b/fs/relayfs/buffers.h
@@ -0,0 +1,12 @@
+#ifndef _BUFFERS_H
+#define _BUFFERS_H
+
+/* This inspired by rtai/shmem */
+#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE
+
+extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma);
+extern struct rchan_buf *relay_create_buf(struct rchan *chan);
+extern void relay_destroy_buf(struct rchan_buf *buf);
+extern void relay_remove_buf(struct kref *kref);
+
+#endif/* _BUFFERS_H */
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
new file mode 100644
index 000000000000..0f7f88d067ad
--- /dev/null
+++ b/fs/relayfs/inode.c
@@ -0,0 +1,609 @@
+/*
+ * VFS-related code for RelayFS, a high-speed data relay filesystem.
+ *
+ * Copyright (C) 2003-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
+ * Copyright (C) 2003-2005 - Karim Yaghmour <karim@opersys.com>
+ *
+ * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/backing-dev.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+#define RELAYFS_MAGIC 0xF0B4A981
+
+static struct vfsmount * relayfs_mount;
+static int relayfs_mount_count;
+static kmem_cache_t * relayfs_inode_cachep;
+
+static struct backing_dev_info relayfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
+ struct rchan *chan)
+{
+ struct rchan_buf *buf = NULL;
+ struct inode *inode;
+
+ if (S_ISREG(mode)) {
+ BUG_ON(!chan);
+ buf = relay_create_buf(chan);
+ if (!buf)
+ return NULL;
+ }
+
+ inode = new_inode(sb);
+ if (!inode) {
+ relay_destroy_buf(buf);
+ return NULL;
+ }
+
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_fop = &relayfs_file_operations;
+ RELAYFS_I(inode)->buf = buf;
+ break;
+ case S_IFDIR:
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ break;
+ default:
+ break;
+ }
+
+ return inode;
+}
+
+/**
+ * relayfs_create_entry - create a relayfs directory or file
+ * @name: the name of the file to create
+ * @parent: parent directory
+ * @mode: mode
+ * @chan: relay channel associated with the file
+ *
+ * Returns the new dentry, NULL on failure
+ *
+ * Creates a file or directory with the specifed permissions.
+ */
+static struct dentry *relayfs_create_entry(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct rchan *chan)
+{
+ struct dentry *d;
+ struct inode *inode;
+ int error = 0;
+
+ BUG_ON(!name || !(S_ISREG(mode) || S_ISDIR(mode)));
+
+ error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count);
+ if (error) {
+ printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error);
+ return NULL;
+ }
+
+ if (!parent && relayfs_mount && relayfs_mount->mnt_sb)
+ parent = relayfs_mount->mnt_sb->s_root;
+
+ if (!parent) {
+ simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+ return NULL;
+ }
+
+ parent = dget(parent);
+ down(&parent->d_inode->i_sem);
+ d = lookup_one_len(name, parent, strlen(name));
+ if (IS_ERR(d)) {
+ d = NULL;
+ goto release_mount;
+ }
+
+ if (d->d_inode) {
+ d = NULL;
+ goto release_mount;
+ }
+
+ inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan);
+ if (!inode) {
+ d = NULL;
+ goto release_mount;
+ }
+
+ d_instantiate(d, inode);
+ dget(d); /* Extra count - pin the dentry in core */
+
+ if (S_ISDIR(mode))
+ parent->d_inode->i_nlink++;
+
+ goto exit;
+
+release_mount:
+ simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+
+exit:
+ up(&parent->d_inode->i_sem);
+ dput(parent);
+ return d;
+}
+
+/**
+ * relayfs_create_file - create a file in the relay filesystem
+ * @name: the name of the file to create
+ * @parent: parent directory
+ * @mode: mode, if not specied the default perms are used
+ * @chan: channel associated with the file
+ *
+ * Returns file dentry if successful, NULL otherwise.
+ *
+ * The file will be created user r on behalf of current user.
+ */
+struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
+ int mode, struct rchan *chan)
+{
+ if (!mode)
+ mode = S_IRUSR;
+ mode = (mode & S_IALLUGO) | S_IFREG;
+
+ return relayfs_create_entry(name, parent, mode, chan);
+}
+
+/**
+ * relayfs_create_dir - create a directory in the relay filesystem
+ * @name: the name of the directory to create
+ * @parent: parent directory, NULL if parent should be fs root
+ *
+ * Returns directory dentry if successful, NULL otherwise.
+ *
+ * The directory will be created world rwx on behalf of current user.
+ */
+struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
+{
+ int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+ return relayfs_create_entry(name, parent, mode, NULL);
+}
+
+/**
+ * relayfs_remove - remove a file or directory in the relay filesystem
+ * @dentry: file or directory dentry
+ *
+ * Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove(struct dentry *dentry)
+{
+ struct dentry *parent;
+ int error = 0;
+
+ if (!dentry)
+ return -EINVAL;
+ parent = dentry->d_parent;
+ if (!parent)
+ return -EINVAL;
+
+ parent = dget(parent);
+ down(&parent->d_inode->i_sem);
+ if (dentry->d_inode) {
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ error = simple_rmdir(parent->d_inode, dentry);
+ else
+ error = simple_unlink(parent->d_inode, dentry);
+ if (!error)
+ d_delete(dentry);
+ }
+ if (!error)
+ dput(dentry);
+ up(&parent->d_inode->i_sem);
+ dput(parent);
+
+ if (!error)
+ simple_release_fs(&relayfs_mount, &relayfs_mount_count);
+
+ return error;
+}
+
+/**
+ * relayfs_remove_dir - remove a directory in the relay filesystem
+ * @dentry: directory dentry
+ *
+ * Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove_dir(struct dentry *dentry)
+{
+ return relayfs_remove(dentry);
+}
+
+/**
+ * relayfs_open - open file op for relayfs files
+ * @inode: the inode
+ * @filp: the file
+ *
+ * Increments the channel buffer refcount.
+ */
+static int relayfs_open(struct inode *inode, struct file *filp)
+{
+ struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ kref_get(&buf->kref);
+
+ return 0;
+}
+
+/**
+ * relayfs_mmap - mmap file op for relayfs files
+ * @filp: the file
+ * @vma: the vma describing what to map
+ *
+ * Calls upon relay_mmap_buf to map the file into user space.
+ */
+static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ return relay_mmap_buf(RELAYFS_I(inode)->buf, vma);
+}
+
+/**
+ * relayfs_poll - poll file op for relayfs files
+ * @filp: the file
+ * @wait: poll table
+ *
+ * Poll implemention.
+ */
+static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
+{
+ unsigned int mask = 0;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+
+ if (buf->finalized)
+ return POLLERR;
+
+ if (filp->f_mode & FMODE_READ) {
+ poll_wait(filp, &buf->read_wait, wait);
+ if (!relay_buf_empty(buf))
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ return mask;
+}
+
+/**
+ * relayfs_release - release file op for relayfs files
+ * @inode: the inode
+ * @filp: the file
+ *
+ * Decrements the channel refcount, as the filesystem is
+ * no longer using it.
+ */
+static int relayfs_release(struct inode *inode, struct file *filp)
+{
+ struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ kref_put(&buf->kref, relay_remove_buf);
+
+ return 0;
+}
+
+/**
+ * relayfs_read_consume - update the consumed count for the buffer
+ */
+static void relayfs_read_consume(struct rchan_buf *buf,
+ size_t read_pos,
+ size_t bytes_consumed)
+{
+ size_t subbuf_size = buf->chan->subbuf_size;
+ size_t n_subbufs = buf->chan->n_subbufs;
+ size_t read_subbuf;
+
+ if (buf->bytes_consumed + bytes_consumed > subbuf_size) {
+ relay_subbufs_consumed(buf->chan, buf->cpu, 1);
+ buf->bytes_consumed = 0;
+ }
+
+ buf->bytes_consumed += bytes_consumed;
+ read_subbuf = read_pos / buf->chan->subbuf_size;
+ if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
+ if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
+ (buf->offset == subbuf_size))
+ return;
+ relay_subbufs_consumed(buf->chan, buf->cpu, 1);
+ buf->bytes_consumed = 0;
+ }
+}
+
+/**
+ * relayfs_read_avail - boolean, are there unconsumed bytes available?
+ */
+static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
+{
+ size_t bytes_produced, bytes_consumed, write_offset;
+ size_t subbuf_size = buf->chan->subbuf_size;
+ size_t n_subbufs = buf->chan->n_subbufs;
+ size_t produced = buf->subbufs_produced % n_subbufs;
+ size_t consumed = buf->subbufs_consumed % n_subbufs;
+
+ write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
+
+ if (consumed > produced) {
+ if ((produced > n_subbufs) &&
+ (produced + n_subbufs - consumed <= n_subbufs))
+ produced += n_subbufs;
+ } else if (consumed == produced) {
+ if (buf->offset > subbuf_size) {
+ produced += n_subbufs;
+ if (buf->subbufs_produced == buf->subbufs_consumed)
+ consumed += n_subbufs;
+ }
+ }
+
+ if (buf->offset > subbuf_size)
+ bytes_produced = (produced - 1) * subbuf_size + write_offset;
+ else
+ bytes_produced = produced * subbuf_size + write_offset;
+ bytes_consumed = consumed * subbuf_size + buf->bytes_consumed;
+
+ if (bytes_produced == bytes_consumed)
+ return 0;
+
+ relayfs_read_consume(buf, read_pos, 0);
+
+ return 1;
+}
+
+/**
+ * relayfs_read_subbuf_avail - return bytes available in sub-buffer
+ */
+static size_t relayfs_read_subbuf_avail(size_t read_pos,
+ struct rchan_buf *buf)
+{
+ size_t padding, avail = 0;
+ size_t read_subbuf, read_offset, write_subbuf, write_offset;
+ size_t subbuf_size = buf->chan->subbuf_size;
+
+ write_subbuf = (buf->data - buf->start) / subbuf_size;
+ write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
+ read_subbuf = read_pos / subbuf_size;
+ read_offset = read_pos % subbuf_size;
+ padding = buf->padding[read_subbuf];
+
+ if (read_subbuf == write_subbuf) {
+ if (read_offset + padding < write_offset)
+ avail = write_offset - (read_offset + padding);
+ } else
+ avail = (subbuf_size - padding) - read_offset;
+
+ return avail;
+}
+
+/**
+ * relayfs_read_start_pos - find the first available byte to read
+ *
+ * If the read_pos is in the middle of padding, return the
+ * position of the first actually available byte, otherwise
+ * return the original value.
+ */
+static size_t relayfs_read_start_pos(size_t read_pos,
+ struct rchan_buf *buf)
+{
+ size_t read_subbuf, padding, padding_start, padding_end;
+ size_t subbuf_size = buf->chan->subbuf_size;
+ size_t n_subbufs = buf->chan->n_subbufs;
+
+ read_subbuf = read_pos / subbuf_size;
+ padding = buf->padding[read_subbuf];
+ padding_start = (read_subbuf + 1) * subbuf_size - padding;
+ padding_end = (read_subbuf + 1) * subbuf_size;
+ if (read_pos >= padding_start && read_pos < padding_end) {
+ read_subbuf = (read_subbuf + 1) % n_subbufs;
+ read_pos = read_subbuf * subbuf_size;
+ }
+
+ return read_pos;
+}
+
+/**
+ * relayfs_read_end_pos - return the new read position
+ */
+static size_t relayfs_read_end_pos(struct rchan_buf *buf,
+ size_t read_pos,
+ size_t count)
+{
+ size_t read_subbuf, padding, end_pos;
+ size_t subbuf_size = buf->chan->subbuf_size;
+ size_t n_subbufs = buf->chan->n_subbufs;
+
+ read_subbuf = read_pos / subbuf_size;
+ padding = buf->padding[read_subbuf];
+ if (read_pos % subbuf_size + count + padding == subbuf_size)
+ end_pos = (read_subbuf + 1) * subbuf_size;
+ else
+ end_pos = read_pos + count;
+ if (end_pos >= subbuf_size * n_subbufs)
+ end_pos = 0;
+
+ return end_pos;
+}
+
+/**
+ * relayfs_read - read file op for relayfs files
+ * @filp: the file
+ * @buffer: the userspace buffer
+ * @count: number of bytes to read
+ * @ppos: position to read from
+ *
+ * Reads count bytes or the number of bytes available in the
+ * current sub-buffer being read, whichever is smaller.
+ */
+static ssize_t relayfs_read(struct file *filp,
+ char __user *buffer,
+ size_t count,
+ loff_t *ppos)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ size_t read_start, avail;
+ ssize_t ret = 0;
+ void *from;
+
+ down(&inode->i_sem);
+ if(!relayfs_read_avail(buf, *ppos))
+ goto out;
+
+ read_start = relayfs_read_start_pos(*ppos, buf);
+ avail = relayfs_read_subbuf_avail(read_start, buf);
+ if (!avail)
+ goto out;
+
+ from = buf->start + read_start;
+ ret = count = min(count, avail);
+ if (copy_to_user(buffer, from, count)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ relayfs_read_consume(buf, read_start, count);
+ *ppos = relayfs_read_end_pos(buf, read_start, count);
+out:
+ up(&inode->i_sem);
+ return ret;
+}
+
+/**
+ * relayfs alloc_inode() implementation
+ */
+static struct inode *relayfs_alloc_inode(struct super_block *sb)
+{
+ struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
+ if (!p)
+ return NULL;
+ p->buf = NULL;
+
+ return &p->vfs_inode;
+}
+
+/**
+ * relayfs destroy_inode() implementation
+ */
+static void relayfs_destroy_inode(struct inode *inode)
+{
+ if (RELAYFS_I(inode)->buf)
+ relay_destroy_buf(RELAYFS_I(inode)->buf);
+
+ kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
+}
+
+static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+{
+ struct relayfs_inode_info *i = p;
+ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
+ inode_init_once(&i->vfs_inode);
+}
+
+struct file_operations relayfs_file_operations = {
+ .open = relayfs_open,
+ .poll = relayfs_poll,
+ .mmap = relayfs_mmap,
+ .read = relayfs_read,
+ .llseek = no_llseek,
+ .release = relayfs_release,
+};
+
+static struct super_operations relayfs_ops = {
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
+ .alloc_inode = relayfs_alloc_inode,
+ .destroy_inode = relayfs_destroy_inode,
+};
+
+static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
+{
+ struct inode *inode;
+ struct dentry *root;
+ int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = RELAYFS_MAGIC;
+ sb->s_op = &relayfs_ops;
+ inode = relayfs_get_inode(sb, mode, NULL);
+
+ if (!inode)
+ return -ENOMEM;
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ sb->s_root = root;
+
+ return 0;
+}
+
+static struct super_block * relayfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ return get_sb_single(fs_type, flags, data, relayfs_fill_super);
+}
+
+static struct file_system_type relayfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "relayfs",
+ .get_sb = relayfs_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+static int __init init_relayfs_fs(void)
+{
+ int err;
+
+ relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache",
+ sizeof(struct relayfs_inode_info), 0,
+ 0, init_once, NULL);
+ if (!relayfs_inode_cachep)
+ return -ENOMEM;
+
+ err = register_filesystem(&relayfs_fs_type);
+ if (err)
+ kmem_cache_destroy(relayfs_inode_cachep);
+
+ return err;
+}
+
+static void __exit exit_relayfs_fs(void)
+{
+ unregister_filesystem(&relayfs_fs_type);
+ kmem_cache_destroy(relayfs_inode_cachep);
+}
+
+module_init(init_relayfs_fs)
+module_exit(exit_relayfs_fs)
+
+EXPORT_SYMBOL_GPL(relayfs_file_operations);
+EXPORT_SYMBOL_GPL(relayfs_create_dir);
+EXPORT_SYMBOL_GPL(relayfs_remove_dir);
+
+MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
+MODULE_DESCRIPTION("Relay Filesystem");
+MODULE_LICENSE("GPL");
+
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
new file mode 100644
index 000000000000..16446a15c96d
--- /dev/null
+++ b/fs/relayfs/relay.c
@@ -0,0 +1,431 @@
+/*
+ * Public API and common code for RelayFS.
+ *
+ * See Documentation/filesystems/relayfs.txt for an overview of relayfs.
+ *
+ * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
+ * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/errno.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+#include "buffers.h"
+
+/**
+ * relay_buf_empty - boolean, is the channel buffer empty?
+ * @buf: channel buffer
+ *
+ * Returns 1 if the buffer is empty, 0 otherwise.
+ */
+int relay_buf_empty(struct rchan_buf *buf)
+{
+ return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1;
+}
+
+/**
+ * relay_buf_full - boolean, is the channel buffer full?
+ * @buf: channel buffer
+ *
+ * Returns 1 if the buffer is full, 0 otherwise.
+ */
+int relay_buf_full(struct rchan_buf *buf)
+{
+ size_t ready = buf->subbufs_produced - buf->subbufs_consumed;
+ return (ready >= buf->chan->n_subbufs) ? 1 : 0;
+}
+
+/*
+ * High-level relayfs kernel API and associated functions.
+ */
+
+/*
+ * rchan_callback implementations defining default channel behavior. Used
+ * in place of corresponding NULL values in client callback struct.
+ */
+
+/*
+ * subbuf_start() default callback. Does nothing.
+ */
+static int subbuf_start_default_callback (struct rchan_buf *buf,
+ void *subbuf,
+ void *prev_subbuf,
+ size_t prev_padding)
+{
+ if (relay_buf_full(buf))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * buf_mapped() default callback. Does nothing.
+ */
+static void buf_mapped_default_callback(struct rchan_buf *buf,
+ struct file *filp)
+{
+}
+
+/*
+ * buf_unmapped() default callback. Does nothing.
+ */
+static void buf_unmapped_default_callback(struct rchan_buf *buf,
+ struct file *filp)
+{
+}
+
+/* relay channel default callbacks */
+static struct rchan_callbacks default_channel_callbacks = {
+ .subbuf_start = subbuf_start_default_callback,
+ .buf_mapped = buf_mapped_default_callback,
+ .buf_unmapped = buf_unmapped_default_callback,
+};
+
+/**
+ * wakeup_readers - wake up readers waiting on a channel
+ * @private: the channel buffer
+ *
+ * This is the work function used to defer reader waking. The
+ * reason waking is deferred is that calling directly from write
+ * causes problems if you're writing from say the scheduler.
+ */
+static void wakeup_readers(void *private)
+{
+ struct rchan_buf *buf = private;
+ wake_up_interruptible(&buf->read_wait);
+}
+
+/**
+ * __relay_reset - reset a channel buffer
+ * @buf: the channel buffer
+ * @init: 1 if this is a first-time initialization
+ *
+ * See relay_reset for description of effect.
+ */
+static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
+{
+ size_t i;
+
+ if (init) {
+ init_waitqueue_head(&buf->read_wait);
+ kref_init(&buf->kref);
+ INIT_WORK(&buf->wake_readers, NULL, NULL);
+ } else {
+ cancel_delayed_work(&buf->wake_readers);
+ flush_scheduled_work();
+ }
+
+ buf->subbufs_produced = 0;
+ buf->subbufs_consumed = 0;
+ buf->bytes_consumed = 0;
+ buf->finalized = 0;
+ buf->data = buf->start;
+ buf->offset = 0;
+
+ for (i = 0; i < buf->chan->n_subbufs; i++)
+ buf->padding[i] = 0;
+
+ buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0);
+}
+
+/**
+ * relay_reset - reset the channel
+ * @chan: the channel
+ *
+ * This has the effect of erasing all data from all channel buffers
+ * and restarting the channel in its initial state. The buffers
+ * are not freed, so any mappings are still in effect.
+ *
+ * NOTE: Care should be taken that the channel isn't actually
+ * being used by anything when this call is made.
+ */
+void relay_reset(struct rchan *chan)
+{
+ unsigned int i;
+
+ if (!chan)
+ return;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!chan->buf[i])
+ continue;
+ __relay_reset(chan->buf[i], 0);
+ }
+}
+
+/**
+ * relay_open_buf - create a new channel buffer in relayfs
+ *
+ * Internal - used by relay_open().
+ */
+static struct rchan_buf *relay_open_buf(struct rchan *chan,
+ const char *filename,
+ struct dentry *parent)
+{
+ struct rchan_buf *buf;
+ struct dentry *dentry;
+
+ /* Create file in fs */
+ dentry = relayfs_create_file(filename, parent, S_IRUSR, chan);
+ if (!dentry)
+ return NULL;
+
+ buf = RELAYFS_I(dentry->d_inode)->buf;
+ buf->dentry = dentry;
+ __relay_reset(buf, 1);
+
+ return buf;
+}
+
+/**
+ * relay_close_buf - close a channel buffer
+ * @buf: channel buffer
+ *
+ * Marks the buffer finalized and restores the default callbacks.
+ * The channel buffer and channel buffer data structure are then freed
+ * automatically when the last reference is given up.
+ */
+static inline void relay_close_buf(struct rchan_buf *buf)
+{
+ buf->finalized = 1;
+ buf->chan->cb = &default_channel_callbacks;
+ cancel_delayed_work(&buf->wake_readers);
+ flush_scheduled_work();
+ kref_put(&buf->kref, relay_remove_buf);
+}
+
+static inline void setup_callbacks(struct rchan *chan,
+ struct rchan_callbacks *cb)
+{
+ if (!cb) {
+ chan->cb = &default_channel_callbacks;
+ return;
+ }
+
+ if (!cb->subbuf_start)
+ cb->subbuf_start = subbuf_start_default_callback;
+ if (!cb->buf_mapped)
+ cb->buf_mapped = buf_mapped_default_callback;
+ if (!cb->buf_unmapped)
+ cb->buf_unmapped = buf_unmapped_default_callback;
+ chan->cb = cb;
+}
+
+/**
+ * relay_open - create a new relayfs channel
+ * @base_filename: base name of files to create
+ * @parent: dentry of parent directory, NULL for root directory
+ * @subbuf_size: size of sub-buffers
+ * @n_subbufs: number of sub-buffers
+ * @cb: client callback functions
+ *
+ * Returns channel pointer if successful, NULL otherwise.
+ *
+ * Creates a channel buffer for each cpu using the sizes and
+ * attributes specified. The created channel buffer files
+ * will be named base_filename0...base_filenameN-1. File
+ * permissions will be S_IRUSR.
+ */
+struct rchan *relay_open(const char *base_filename,
+ struct dentry *parent,
+ size_t subbuf_size,
+ size_t n_subbufs,
+ struct rchan_callbacks *cb)
+{
+ unsigned int i;
+ struct rchan *chan;
+ char *tmpname;
+
+ if (!base_filename)
+ return NULL;
+
+ if (!(subbuf_size && n_subbufs))
+ return NULL;
+
+ chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
+ if (!chan)
+ return NULL;
+
+ chan->version = RELAYFS_CHANNEL_VERSION;
+ chan->n_subbufs = n_subbufs;
+ chan->subbuf_size = subbuf_size;
+ chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
+ setup_callbacks(chan, cb);
+ kref_init(&chan->kref);
+
+ tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+ if (!tmpname)
+ goto free_chan;
+
+ for_each_online_cpu(i) {
+ sprintf(tmpname, "%s%d", base_filename, i);
+ chan->buf[i] = relay_open_buf(chan, tmpname, parent);
+ chan->buf[i]->cpu = i;
+ if (!chan->buf[i])
+ goto free_bufs;
+ }
+
+ kfree(tmpname);
+ return chan;
+
+free_bufs:
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!chan->buf[i])
+ break;
+ relay_close_buf(chan->buf[i]);
+ }
+ kfree(tmpname);
+
+free_chan:
+ kref_put(&chan->kref, relay_destroy_channel);
+ return NULL;
+}
+
+/**
+ * relay_switch_subbuf - switch to a new sub-buffer
+ * @buf: channel buffer
+ * @length: size of current event
+ *
+ * Returns either the length passed in or 0 if full.
+
+ * Performs sub-buffer-switch tasks such as invoking callbacks,
+ * updating padding counts, waking up readers, etc.
+ */
+size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
+{
+ void *old, *new;
+ size_t old_subbuf, new_subbuf;
+
+ if (unlikely(length > buf->chan->subbuf_size))
+ goto toobig;
+
+ if (buf->offset != buf->chan->subbuf_size + 1) {
+ buf->prev_padding = buf->chan->subbuf_size - buf->offset;
+ old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
+ buf->padding[old_subbuf] = buf->prev_padding;
+ buf->subbufs_produced++;
+ if (waitqueue_active(&buf->read_wait)) {
+ PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
+ schedule_delayed_work(&buf->wake_readers, 1);
+ }
+ }
+
+ old = buf->data;
+ new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
+ new = buf->start + new_subbuf * buf->chan->subbuf_size;
+ buf->offset = 0;
+ if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
+ buf->offset = buf->chan->subbuf_size + 1;
+ return 0;
+ }
+ buf->data = new;
+ buf->padding[new_subbuf] = 0;
+
+ if (unlikely(length + buf->offset > buf->chan->subbuf_size))
+ goto toobig;
+
+ return length;
+
+toobig:
+ printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length);
+ WARN_ON(1);
+ return 0;
+}
+
+/**
+ * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count
+ * @chan: the channel
+ * @cpu: the cpu associated with the channel buffer to update
+ * @subbufs_consumed: number of sub-buffers to add to current buf's count
+ *
+ * Adds to the channel buffer's consumed sub-buffer count.
+ * subbufs_consumed should be the number of sub-buffers newly consumed,
+ * not the total consumed.
+ *
+ * NOTE: kernel clients don't need to call this function if the channel
+ * mode is 'overwrite'.
+ */
+void relay_subbufs_consumed(struct rchan *chan,
+ unsigned int cpu,
+ size_t subbufs_consumed)
+{
+ struct rchan_buf *buf;
+
+ if (!chan)
+ return;
+
+ if (cpu >= NR_CPUS || !chan->buf[cpu])
+ return;
+
+ buf = chan->buf[cpu];
+ buf->subbufs_consumed += subbufs_consumed;
+ if (buf->subbufs_consumed > buf->subbufs_produced)
+ buf->subbufs_consumed = buf->subbufs_produced;
+}
+
+/**
+ * relay_destroy_channel - free the channel struct
+ *
+ * Should only be called from kref_put().
+ */
+void relay_destroy_channel(struct kref *kref)
+{
+ struct rchan *chan = container_of(kref, struct rchan, kref);
+ kfree(chan);
+}
+
+/**
+ * relay_close - close the channel
+ * @chan: the channel
+ *
+ * Closes all channel buffers and frees the channel.
+ */
+void relay_close(struct rchan *chan)
+{
+ unsigned int i;
+
+ if (!chan)
+ return;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!chan->buf[i])
+ continue;
+ relay_close_buf(chan->buf[i]);
+ }
+
+ kref_put(&chan->kref, relay_destroy_channel);
+}
+
+/**
+ * relay_flush - close the channel
+ * @chan: the channel
+ *
+ * Flushes all channel buffers i.e. forces buffer switch.
+ */
+void relay_flush(struct rchan *chan)
+{
+ unsigned int i;
+
+ if (!chan)
+ return;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!chan->buf[i])
+ continue;
+ relay_switch_subbuf(chan->buf[i], 0);
+ }
+}
+
+EXPORT_SYMBOL_GPL(relay_open);
+EXPORT_SYMBOL_GPL(relay_close);
+EXPORT_SYMBOL_GPL(relay_flush);
+EXPORT_SYMBOL_GPL(relay_reset);
+EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
+EXPORT_SYMBOL_GPL(relay_switch_subbuf);
+EXPORT_SYMBOL_GPL(relay_buf_full);
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
new file mode 100644
index 000000000000..703503fa22b6
--- /dev/null
+++ b/fs/relayfs/relay.h
@@ -0,0 +1,12 @@
+#ifndef _RELAY_H
+#define _RELAY_H
+
+struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct rchan *chan);
+extern int relayfs_remove(struct dentry *dentry);
+extern int relay_buf_empty(struct rchan_buf *buf);
+extern void relay_destroy_channel(struct kref *kref);
+
+#endif /* _RELAY_H */
diff --git a/fs/select.c b/fs/select.c
index b80e7eb0ac0d..f10a10317d54 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -22,6 +22,7 @@
#include <linux/personality.h> /* for STICKY_TIMEOUTS */
#include <linux/file.h>
#include <linux/fs.h>
+#include <linux/rcupdate.h>
#include <asm/uaccess.h>
@@ -132,11 +133,13 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds)
unsigned long *open_fds;
unsigned long set;
int max;
+ struct fdtable *fdt;
/* handle last in-complete long-word first */
set = ~(~0UL << (n & (__NFDBITS-1)));
n /= __NFDBITS;
- open_fds = current->files->open_fds->fds_bits+n;
+ fdt = files_fdtable(current->files);
+ open_fds = fdt->open_fds->fds_bits+n;
max = 0;
if (set) {
set &= BITS(fds, n);
@@ -183,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
int retval, i;
long __timeout = *timeout;
- spin_lock(&current->files->file_lock);
+ rcu_read_lock();
retval = max_select_fd(n, fds);
- spin_unlock(&current->files->file_lock);
+ rcu_read_unlock();
if (retval < 0)
return retval;
@@ -299,6 +302,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
char *bits;
long timeout;
int ret, size, max_fdset;
+ struct fdtable *fdt;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -326,7 +330,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
goto out_nofds;
/* max_fdset can increase, so grab it once to avoid race */
- max_fdset = current->files->max_fdset;
+ rcu_read_lock();
+ fdt = files_fdtable(current->files);
+ max_fdset = fdt->max_fdset;
+ rcu_read_unlock();
if (n > max_fdset)
n = max_fdset;
@@ -464,9 +471,15 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
unsigned int i;
struct poll_list *head;
struct poll_list *walk;
+ struct fdtable *fdt;
+ int max_fdset;
/* Do a sanity check on nfds ... */
- if (nfds > current->files->max_fdset && nfds > OPEN_MAX)
+ rcu_read_lock();
+ fdt = files_fdtable(current->files);
+ max_fdset = fdt->max_fdset;
+ rcu_read_unlock();
+ if (nfds > max_fdset && nfds > OPEN_MAX)
return -EINVAL;
if (timeout) {
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 4765aaac9fd2..10b994428fef 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -331,6 +331,7 @@ static void
smb_delete_inode(struct inode *ino)
{
DEBUG1("ino=%ld\n", ino->i_ino);
+ truncate_inode_pages(&ino->i_data, 0);
lock_kernel();
if (smb_close(ino))
PARANOIA("could not close inode %ld\n", ino->i_ino);
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 220babe91efd..38ab558835c4 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -2397,8 +2397,7 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
if (req->rq_rcls == ERRSRV && req->rq_err == ERRerror) {
/* a damn Win95 bug - sometimes it clags if you
ask it too fast */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/5);
+ schedule_timeout_interruptible(msecs_to_jiffies(200));
continue;
}
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
index 93f3cd22a2e9..6815b1b12b68 100644
--- a/fs/smbfs/sock.c
+++ b/fs/smbfs/sock.c
@@ -15,12 +15,12 @@
#include <linux/file.h>
#include <linux/in.h>
#include <linux/net.h>
-#include <linux/tcp.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
#include <linux/smp_lock.h>
#include <linux/workqueue.h>
#include <net/scm.h>
+#include <net/tcp_states.h>
#include <net/ip.h>
#include <linux/smb_fs.h>
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 0530077d9dd8..fa33eceb0011 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -292,6 +292,7 @@ int sysv_sync_inode(struct inode * inode)
static void sysv_delete_inode(struct inode *inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
sysv_truncate(inode);
lock_kernel();
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 3d68de39fad6..b83890beaaac 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -87,6 +87,8 @@ static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
*/
void udf_delete_inode(struct inode * inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
+
if (is_bad_inode(inode))
goto no_delete;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 997640c99c7d..faf1512173eb 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -114,8 +114,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
sb->s_dirt = 1;
@@ -200,8 +199,7 @@ do_more:
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
@@ -459,8 +457,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
sb->s_dirt = 1;
@@ -585,8 +582,7 @@ succed:
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
sb->s_dirt = 1;
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 61a6b1542fc5..0938945b9cbc 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -124,8 +124,7 @@ void ufs_free_inode (struct inode * inode)
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
@@ -249,8 +248,7 @@ cg_found:
ubh_mark_buffer_dirty (USPI_UBH);
ubh_mark_buffer_dirty (UCPI_UBH);
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_wait_on_buffer (UCPI_UBH);
- ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi);
+ ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
ubh_wait_on_buffer (UCPI_UBH);
}
sb->s_dirt = 1;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 718627ca8b5c..55f4aa16e3fc 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -804,6 +804,7 @@ int ufs_sync_inode (struct inode *inode)
void ufs_delete_inode (struct inode * inode)
{
+ truncate_inode_pages(&inode->i_data, 0);
/*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
lock_kernel();
mark_inode_dirty(inode);
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index e312bf8bad9f..61d2e35012a4 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -285,8 +285,7 @@ next:;
}
}
if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
- ubh_wait_on_buffer (ind_ubh);
- ubh_ll_rw_block (WRITE, 1, &ind_ubh);
+ ubh_ll_rw_block (SWRITE, 1, &ind_ubh);
ubh_wait_on_buffer (ind_ubh);
}
ubh_brelse (ind_ubh);
@@ -353,8 +352,7 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
}
}
if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
- ubh_wait_on_buffer (dind_bh);
- ubh_ll_rw_block (WRITE, 1, &dind_bh);
+ ubh_ll_rw_block (SWRITE, 1, &dind_bh);
ubh_wait_on_buffer (dind_bh);
}
ubh_brelse (dind_bh);
@@ -418,8 +416,7 @@ static int ufs_trunc_tindirect (struct inode * inode)
}
}
if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
- ubh_wait_on_buffer (tind_bh);
- ubh_ll_rw_block (WRITE, 1, &tind_bh);
+ ubh_ll_rw_block (SWRITE, 1, &tind_bh);
ubh_wait_on_buffer (tind_bh);
}
ubh_brelse (tind_bh);
diff --git a/fs/umsdos/notes b/fs/umsdos/notes
deleted file mode 100644
index 3c47d1f4fc47..000000000000
--- a/fs/umsdos/notes
+++ /dev/null
@@ -1,17 +0,0 @@
-This file contain idea and things I don't want to forget
-
-Possible bug in fs/read_write.c
-Function sys_readdir()
-
- There is a call the verify_area that does not take in account
- the count parameter. I guess it should read
-
- error = verify_area(VERIFY_WRITE, dirent, count*sizeof (*dirent));
-
- instead of
-
- error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
-
- Of course, now , count is always 1
-
-
diff --git a/fs/xattr.c b/fs/xattr.c
index 6acd5c63da91..3f9c64bea151 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -51,20 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
}
}
+ down(&d->d_inode->i_sem);
+ error = security_inode_setxattr(d, kname, kvalue, size, flags);
+ if (error)
+ goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
- down(&d->d_inode->i_sem);
- error = security_inode_setxattr(d, kname, kvalue, size, flags);
- if (error)
- goto out;
- error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
+ error = d->d_inode->i_op->setxattr(d, kname, kvalue,
+ size, flags);
if (!error) {
fsnotify_xattr(d);
- security_inode_post_setxattr(d, kname, kvalue, size, flags);
+ security_inode_post_setxattr(d, kname, kvalue,
+ size, flags);
}
-out:
- up(&d->d_inode->i_sem);
+ } else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
+ sizeof XATTR_SECURITY_PREFIX - 1)) {
+ const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
+ error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
+ size, flags);
+ if (!error)
+ fsnotify_xattr(d);
}
+out:
+ up(&d->d_inode->i_sem);
if (kvalue)
kfree(kvalue);
return error;
@@ -139,20 +148,25 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
return -ENOMEM;
}
+ error = security_inode_getxattr(d, kname);
+ if (error)
+ goto out;
error = -EOPNOTSUPP;
- if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
- error = security_inode_getxattr(d, kname);
- if (error)
- goto out;
+ if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
- if (error > 0) {
- if (size && copy_to_user(value, kvalue, error))
- error = -EFAULT;
- } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
- /* The file system tried to returned a value bigger
- than XATTR_SIZE_MAX bytes. Not possible. */
- error = -E2BIG;
- }
+ else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
+ sizeof XATTR_SECURITY_PREFIX - 1)) {
+ const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
+ error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
+ size);
+ }
+ if (error > 0) {
+ if (size && copy_to_user(value, kvalue, error))
+ error = -EFAULT;
+ } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
+ /* The file system tried to returned a value bigger
+ than XATTR_SIZE_MAX bytes. Not possible. */
+ error = -E2BIG;
}
out:
if (kvalue)
@@ -221,20 +235,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
return -ENOMEM;
}
+ error = security_inode_listxattr(d);
+ if (error)
+ goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
- error = security_inode_listxattr(d);
- if (error)
- goto out;
error = d->d_inode->i_op->listxattr(d, klist, size);
- if (error > 0) {
- if (size && copy_to_user(list, klist, error))
- error = -EFAULT;
- } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
- /* The file system tried to returned a list bigger
- than XATTR_LIST_MAX bytes. Not possible. */
- error = -E2BIG;
- }
+ } else {
+ error = security_inode_listsecurity(d->d_inode, klist, size);
+ if (size && error >= size)
+ error = -ERANGE;
+ }
+ if (error > 0) {
+ if (size && copy_to_user(list, klist, error))
+ error = -EFAULT;
+ } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
+ /* The file system tried to returned a list bigger
+ than XATTR_LIST_MAX bytes. Not possible. */
+ error = -E2BIG;
}
out:
if (klist)
@@ -307,6 +325,8 @@ removexattr(struct dentry *d, char __user *name)
down(&d->d_inode->i_sem);
error = d->d_inode->i_op->removexattr(d, kname);
up(&d->d_inode->i_sem);
+ if (!error)
+ fsnotify_xattr(d);
}
out:
return error;
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
index c92306f0fdc5..8e8f32dabe53 100644
--- a/fs/xfs/Kconfig
+++ b/fs/xfs/Kconfig
@@ -1,5 +1,3 @@
-menu "XFS support"
-
config XFS_FS
tristate "XFS filesystem support"
select EXPORTFS if NFSD!=n
@@ -22,27 +20,11 @@ config XFS_FS
config XFS_EXPORT
bool
- default y if XFS_FS && EXPORTFS
-
-config XFS_RT
- bool "Realtime support (EXPERIMENTAL)"
- depends on XFS_FS && EXPERIMENTAL
- help
- If you say Y here you will be able to mount and use XFS filesystems
- which contain a realtime subvolume. The realtime subvolume is a
- separate area of disk space where only file data is stored. The
- realtime subvolume is designed to provide very deterministic
- data rates suitable for media streaming applications.
-
- See the xfs man page in section 5 for a bit more information.
-
- This feature is unsupported at this time, is not yet fully
- functional, and may cause serious problems.
-
- If unsure, say N.
+ depends on XFS_FS && EXPORTFS
+ default y
config XFS_QUOTA
- bool "Quota support"
+ tristate "XFS Quota support"
depends on XFS_FS
help
If you say Y here, you will be able to set limits for disk usage on
@@ -59,7 +41,7 @@ config XFS_QUOTA
they are completely independent subsystems.
config XFS_SECURITY
- bool "Security Label support"
+ bool "XFS Security Label support"
depends on XFS_FS
help
Security labels support alternative access control models
@@ -71,7 +53,7 @@ config XFS_SECURITY
extended attributes for inode security labels, say N.
config XFS_POSIX_ACL
- bool "POSIX ACL support"
+ bool "XFS POSIX ACL support"
depends on XFS_FS
help
POSIX Access Control Lists (ACLs) support permissions for users and
@@ -82,4 +64,19 @@ config XFS_POSIX_ACL
If you don't know what Access Control Lists are, say N.
-endmenu
+config XFS_RT
+ bool "XFS Realtime support (EXPERIMENTAL)"
+ depends on XFS_FS && EXPERIMENTAL
+ help
+ If you say Y here you will be able to mount and use XFS filesystems
+ which contain a realtime subvolume. The realtime subvolume is a
+ separate area of disk space where only file data is stored. The
+ realtime subvolume is designed to provide very deterministic
+ data rates suitable for media streaming applications.
+
+ See the xfs man page in section 5 for a bit more information.
+
+ This feature is unsupported at this time, is not yet fully
+ functional, and may cause serious problems.
+
+ If unsure, say N.
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index d3ff78354638..49e3e7e5e3dc 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -1,150 +1 @@
-#
-# Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of version 2 of the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like. Any license provided herein, whether implied or
-# otherwise, applies only to this software file. Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write the Free Software Foundation, Inc., 59
-# Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
-# Mountain View, CA 94043, or:
-#
-# http://www.sgi.com
-#
-# For further information regarding this notice, see:
-#
-# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
-#
-
-EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
-
-ifeq ($(CONFIG_XFS_DEBUG),y)
- EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG
- EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
-endif
-ifeq ($(CONFIG_XFS_TRACE),y)
- EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
- EXTRA_CFLAGS += -DXFS_ATTR_TRACE
- EXTRA_CFLAGS += -DXFS_BLI_TRACE
- EXTRA_CFLAGS += -DXFS_BMAP_TRACE
- EXTRA_CFLAGS += -DXFS_BMBT_TRACE
- EXTRA_CFLAGS += -DXFS_DIR_TRACE
- EXTRA_CFLAGS += -DXFS_DIR2_TRACE
- EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
- EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
- EXTRA_CFLAGS += -DXFS_LOG_TRACE
- EXTRA_CFLAGS += -DXFS_RW_TRACE
- EXTRA_CFLAGS += -DPAGEBUF_TRACE
- EXTRA_CFLAGS += -DXFS_VNODE_TRACE
-endif
-
-obj-$(CONFIG_XFS_FS) += xfs.o
-
-xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
- xfs_dquot.o \
- xfs_dquot_item.o \
- xfs_trans_dquot.o \
- xfs_qm_syscalls.o \
- xfs_qm_bhv.o \
- xfs_qm.o)
-ifeq ($(CONFIG_XFS_QUOTA),y)
-xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o
-endif
-
-xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
-xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
-xfs-$(CONFIG_PROC_FS) += linux-2.6/xfs_stats.o
-xfs-$(CONFIG_SYSCTL) += linux-2.6/xfs_sysctl.o
-xfs-$(CONFIG_COMPAT) += linux-2.6/xfs_ioctl32.o
-xfs-$(CONFIG_XFS_EXPORT) += linux-2.6/xfs_export.o
-
-
-xfs-y += xfs_alloc.o \
- xfs_alloc_btree.o \
- xfs_attr.o \
- xfs_attr_leaf.o \
- xfs_behavior.o \
- xfs_bit.o \
- xfs_bmap.o \
- xfs_bmap_btree.o \
- xfs_btree.o \
- xfs_buf_item.o \
- xfs_da_btree.o \
- xfs_dir.o \
- xfs_dir2.o \
- xfs_dir2_block.o \
- xfs_dir2_data.o \
- xfs_dir2_leaf.o \
- xfs_dir2_node.o \
- xfs_dir2_sf.o \
- xfs_dir_leaf.o \
- xfs_error.o \
- xfs_extfree_item.o \
- xfs_fsops.o \
- xfs_ialloc.o \
- xfs_ialloc_btree.o \
- xfs_iget.o \
- xfs_inode.o \
- xfs_inode_item.o \
- xfs_iocore.o \
- xfs_iomap.o \
- xfs_itable.o \
- xfs_dfrag.o \
- xfs_log.o \
- xfs_log_recover.o \
- xfs_macros.o \
- xfs_mount.o \
- xfs_rename.o \
- xfs_trans.o \
- xfs_trans_ail.o \
- xfs_trans_buf.o \
- xfs_trans_extfree.o \
- xfs_trans_inode.o \
- xfs_trans_item.o \
- xfs_utils.o \
- xfs_vfsops.o \
- xfs_vnodeops.o \
- xfs_rw.o \
- xfs_dmops.o \
- xfs_qmops.o
-
-xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
-
-# Objects in linux-2.6/
-xfs-y += $(addprefix linux-2.6/, \
- kmem.o \
- xfs_aops.o \
- xfs_buf.o \
- xfs_file.o \
- xfs_fs_subr.o \
- xfs_globals.o \
- xfs_ioctl.o \
- xfs_iops.o \
- xfs_lrw.o \
- xfs_super.o \
- xfs_vfs.o \
- xfs_vnode.o)
-
-# Objects in support/
-xfs-y += $(addprefix support/, \
- debug.o \
- move.o \
- qsort.o \
- uuid.o)
-
-xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
-
+include $(TOPDIR)/fs/xfs/Makefile-linux-$(VERSION).$(PATCHLEVEL)
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
new file mode 100644
index 000000000000..d8c87fa21ad1
--- /dev/null
+++ b/fs/xfs/Makefile-linux-2.6
@@ -0,0 +1,152 @@
+#
+# Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA 94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
+
+XFS_LINUX := linux-2.6
+
+ifeq ($(CONFIG_XFS_DEBUG),y)
+ EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG
+ EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
+endif
+ifeq ($(CONFIG_XFS_TRACE),y)
+ EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
+ EXTRA_CFLAGS += -DXFS_ATTR_TRACE
+ EXTRA_CFLAGS += -DXFS_BLI_TRACE
+ EXTRA_CFLAGS += -DXFS_BMAP_TRACE
+ EXTRA_CFLAGS += -DXFS_BMBT_TRACE
+ EXTRA_CFLAGS += -DXFS_DIR_TRACE
+ EXTRA_CFLAGS += -DXFS_DIR2_TRACE
+ EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
+ EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
+ EXTRA_CFLAGS += -DXFS_LOG_TRACE
+ EXTRA_CFLAGS += -DXFS_RW_TRACE
+ EXTRA_CFLAGS += -DPAGEBUF_TRACE
+ EXTRA_CFLAGS += -DXFS_VNODE_TRACE
+endif
+
+obj-$(CONFIG_XFS_FS) += xfs.o
+
+xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
+ xfs_dquot.o \
+ xfs_dquot_item.o \
+ xfs_trans_dquot.o \
+ xfs_qm_syscalls.o \
+ xfs_qm_bhv.o \
+ xfs_qm.o)
+
+ifeq ($(CONFIG_XFS_QUOTA),y)
+xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o
+endif
+
+xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
+xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
+xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o
+xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o
+xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o
+xfs-$(CONFIG_XFS_EXPORT) += $(XFS_LINUX)/xfs_export.o
+
+
+xfs-y += xfs_alloc.o \
+ xfs_alloc_btree.o \
+ xfs_attr.o \
+ xfs_attr_leaf.o \
+ xfs_behavior.o \
+ xfs_bit.o \
+ xfs_bmap.o \
+ xfs_bmap_btree.o \
+ xfs_btree.o \
+ xfs_buf_item.o \
+ xfs_da_btree.o \
+ xfs_dir.o \
+ xfs_dir2.o \
+ xfs_dir2_block.o \
+ xfs_dir2_data.o \
+ xfs_dir2_leaf.o \
+ xfs_dir2_node.o \
+ xfs_dir2_sf.o \
+ xfs_dir_leaf.o \
+ xfs_error.o \
+ xfs_extfree_item.o \
+ xfs_fsops.o \
+ xfs_ialloc.o \
+ xfs_ialloc_btree.o \
+ xfs_iget.o \
+ xfs_inode.o \
+ xfs_inode_item.o \
+ xfs_iocore.o \
+ xfs_iomap.o \
+ xfs_itable.o \
+ xfs_dfrag.o \
+ xfs_log.o \
+ xfs_log_recover.o \
+ xfs_macros.o \
+ xfs_mount.o \
+ xfs_rename.o \
+ xfs_trans.o \
+ xfs_trans_ail.o \
+ xfs_trans_buf.o \
+ xfs_trans_extfree.o \
+ xfs_trans_inode.o \
+ xfs_trans_item.o \
+ xfs_utils.o \
+ xfs_vfsops.o \
+ xfs_vnodeops.o \
+ xfs_rw.o \
+ xfs_dmops.o \
+ xfs_qmops.o
+
+xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
+
+# Objects in linux/
+xfs-y += $(addprefix $(XFS_LINUX)/, \
+ kmem.o \
+ xfs_aops.o \
+ xfs_buf.o \
+ xfs_file.o \
+ xfs_fs_subr.o \
+ xfs_globals.o \
+ xfs_ioctl.o \
+ xfs_iops.o \
+ xfs_lrw.o \
+ xfs_super.o \
+ xfs_vfs.o \
+ xfs_vnode.o)
+
+# Objects in support/
+xfs-y += $(addprefix support/, \
+ debug.o \
+ move.o \
+ uuid.o)
+
+xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
+
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index 364ea8c386b1..4b184559f231 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -45,11 +45,11 @@
void *
-kmem_alloc(size_t size, int flags)
+kmem_alloc(size_t size, unsigned int __nocast flags)
{
- int retries = 0;
- int lflags = kmem_flags_convert(flags);
- void *ptr;
+ int retries = 0;
+ unsigned int lflags = kmem_flags_convert(flags);
+ void *ptr;
do {
if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
@@ -67,7 +67,7 @@ kmem_alloc(size_t size, int flags)
}
void *
-kmem_zalloc(size_t size, int flags)
+kmem_zalloc(size_t size, unsigned int __nocast flags)
{
void *ptr;
@@ -89,7 +89,8 @@ kmem_free(void *ptr, size_t size)
}
void *
-kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
+kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
+ unsigned int __nocast flags)
{
void *new;
@@ -104,11 +105,11 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
}
void *
-kmem_zone_alloc(kmem_zone_t *zone, int flags)
+kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
{
- int retries = 0;
- int lflags = kmem_flags_convert(flags);
- void *ptr;
+ int retries = 0;
+ unsigned int lflags = kmem_flags_convert(flags);
+ void *ptr;
do {
ptr = kmem_cache_alloc(zone, lflags);
@@ -123,7 +124,7 @@ kmem_zone_alloc(kmem_zone_t *zone, int flags)
}
void *
-kmem_zone_zalloc(kmem_zone_t *zone, int flags)
+kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags)
{
void *ptr;
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 1397b669b059..109fcf27e256 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -39,10 +39,10 @@
/*
* memory management routines
*/
-#define KM_SLEEP 0x0001
-#define KM_NOSLEEP 0x0002
-#define KM_NOFS 0x0004
-#define KM_MAYFAIL 0x0008
+#define KM_SLEEP 0x0001u
+#define KM_NOSLEEP 0x0002u
+#define KM_NOFS 0x0004u
+#define KM_MAYFAIL 0x0008u
#define kmem_zone kmem_cache_s
#define kmem_zone_t kmem_cache_t
@@ -81,9 +81,9 @@ typedef unsigned long xfs_pflags_t;
*(NSTATEP) = *(OSTATEP); \
} while (0)
-static __inline unsigned int kmem_flags_convert(int flags)
+static __inline unsigned int kmem_flags_convert(unsigned int __nocast flags)
{
- int lflags = __GFP_NOWARN; /* we'll report problems, if need be */
+ unsigned int lflags = __GFP_NOWARN; /* we'll report problems, if need be */
#ifdef DEBUG
if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) {
@@ -125,12 +125,13 @@ kmem_zone_destroy(kmem_zone_t *zone)
BUG();
}
-extern void *kmem_zone_zalloc(kmem_zone_t *, int);
-extern void *kmem_zone_alloc(kmem_zone_t *, int);
+extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
+extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
-extern void *kmem_alloc(size_t, int);
-extern void *kmem_realloc(void *, size_t, size_t, int);
-extern void *kmem_zalloc(size_t, int);
+extern void *kmem_alloc(size_t, unsigned int __nocast);
+extern void *kmem_realloc(void *, size_t, size_t,
+ unsigned int __nocast);
+extern void *kmem_zalloc(size_t, unsigned int __nocast);
extern void kmem_free(void *, size_t);
typedef struct shrinker *kmem_shaker_t;
diff --git a/fs/xfs/linux-2.6/spin.h b/fs/xfs/linux-2.6/spin.h
index bcf60a0b8df0..0039504069a5 100644
--- a/fs/xfs/linux-2.6/spin.h
+++ b/fs/xfs/linux-2.6/spin.h
@@ -45,6 +45,9 @@
typedef spinlock_t lock_t;
#define SPLDECL(s) unsigned long s
+#ifndef DEFINE_SPINLOCK
+#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED
+#endif
#define spinlock_init(lock, name) spin_lock_init(lock)
#define spinlock_destroy(lock)
diff --git a/fs/xfs/linux-2.6/time.h b/fs/xfs/linux-2.6/time.h
index 6c6fd0faa8e1..b0d2873ab274 100644
--- a/fs/xfs/linux-2.6/time.h
+++ b/fs/xfs/linux-2.6/time.h
@@ -39,8 +39,7 @@ typedef struct timespec timespec_t;
static inline void delay(long ticks)
{
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(ticks);
+ schedule_timeout_uninterruptible(ticks);
}
static inline void nanotime(struct timespec *tvp)
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index a3a4b5aaf5d9..c6c077978fe3 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -104,66 +104,114 @@ xfs_page_trace(
#define xfs_page_trace(tag, inode, page, mask)
#endif
-void
-linvfs_unwritten_done(
- struct buffer_head *bh,
- int uptodate)
+/*
+ * Schedule IO completion handling on a xfsdatad if this was
+ * the final hold on this ioend.
+ */
+STATIC void
+xfs_finish_ioend(
+ xfs_ioend_t *ioend)
{
- xfs_buf_t *pb = (xfs_buf_t *)bh->b_private;
+ if (atomic_dec_and_test(&ioend->io_remaining))
+ queue_work(xfsdatad_workqueue, &ioend->io_work);
+}
- ASSERT(buffer_unwritten(bh));
- bh->b_end_io = NULL;
- clear_buffer_unwritten(bh);
- if (!uptodate)
- pagebuf_ioerror(pb, EIO);
- if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
- pagebuf_iodone(pb, 1, 1);
- }
- end_buffer_async_write(bh, uptodate);
+STATIC void
+xfs_destroy_ioend(
+ xfs_ioend_t *ioend)
+{
+ vn_iowake(ioend->io_vnode);
+ mempool_free(ioend, xfs_ioend_pool);
}
/*
* Issue transactions to convert a buffer range from unwritten
- * to written extents (buffered IO).
+ * to written extents.
*/
STATIC void
-linvfs_unwritten_convert(
- xfs_buf_t *bp)
+xfs_end_bio_unwritten(
+ void *data)
{
- vnode_t *vp = XFS_BUF_FSPRIVATE(bp, vnode_t *);
- int error;
+ xfs_ioend_t *ioend = data;
+ vnode_t *vp = ioend->io_vnode;
+ xfs_off_t offset = ioend->io_offset;
+ size_t size = ioend->io_size;
+ struct buffer_head *bh, *next;
+ int error;
+
+ if (ioend->io_uptodate)
+ VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
+
+ /* ioend->io_buffer_head is only non-NULL for buffered I/O */
+ for (bh = ioend->io_buffer_head; bh; bh = next) {
+ next = bh->b_private;
+
+ bh->b_end_io = NULL;
+ clear_buffer_unwritten(bh);
+ end_buffer_async_write(bh, ioend->io_uptodate);
+ }
- BUG_ON(atomic_read(&bp->pb_hold) < 1);
- VOP_BMAP(vp, XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp),
- BMAPI_UNWRITTEN, NULL, NULL, error);
- XFS_BUF_SET_FSPRIVATE(bp, NULL);
- XFS_BUF_CLR_IODONE_FUNC(bp);
- XFS_BUF_UNDATAIO(bp);
- iput(LINVFS_GET_IP(vp));
- pagebuf_iodone(bp, 0, 0);
+ xfs_destroy_ioend(ioend);
}
/*
- * Issue transactions to convert a buffer range from unwritten
- * to written extents (direct IO).
+ * Allocate and initialise an IO completion structure.
+ * We need to track unwritten extent write completion here initially.
+ * We'll need to extend this for updating the ondisk inode size later
+ * (vs. incore size).
*/
-STATIC void
-linvfs_unwritten_convert_direct(
- struct kiocb *iocb,
- loff_t offset,
- ssize_t size,
- void *private)
+STATIC xfs_ioend_t *
+xfs_alloc_ioend(
+ struct inode *inode)
{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
- ASSERT(!private || inode == (struct inode *)private);
+ xfs_ioend_t *ioend;
- /* private indicates an unwritten extent lay beneath this IO */
- if (private && size > 0) {
- vnode_t *vp = LINVFS_GET_VP(inode);
- int error;
+ ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS);
- VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
- }
+ /*
+ * Set the count to 1 initially, which will prevent an I/O
+ * completion callback from happening before we have started
+ * all the I/O from calling the completion routine too early.
+ */
+ atomic_set(&ioend->io_remaining, 1);
+ ioend->io_uptodate = 1; /* cleared if any I/O fails */
+ ioend->io_vnode = LINVFS_GET_VP(inode);
+ ioend->io_buffer_head = NULL;
+ atomic_inc(&ioend->io_vnode->v_iocount);
+ ioend->io_offset = 0;
+ ioend->io_size = 0;
+
+ INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend);
+
+ return ioend;
+}
+
+void
+linvfs_unwritten_done(
+ struct buffer_head *bh,
+ int uptodate)
+{
+ xfs_ioend_t *ioend = bh->b_private;
+ static spinlock_t unwritten_done_lock = SPIN_LOCK_UNLOCKED;
+ unsigned long flags;
+
+ ASSERT(buffer_unwritten(bh));
+ bh->b_end_io = NULL;
+
+ if (!uptodate)
+ ioend->io_uptodate = 0;
+
+ /*
+ * Deep magic here. We reuse b_private in the buffer_heads to build
+ * a chain for completing the I/O from user context after we've issued
+ * a transaction to convert the unwritten extent.
+ */
+ spin_lock_irqsave(&unwritten_done_lock, flags);
+ bh->b_private = ioend->io_buffer_head;
+ ioend->io_buffer_head = bh;
+ spin_unlock_irqrestore(&unwritten_done_lock, flags);
+
+ xfs_finish_ioend(ioend);
}
STATIC int
@@ -255,7 +303,7 @@ xfs_probe_unwritten_page(
struct address_space *mapping,
pgoff_t index,
xfs_iomap_t *iomapp,
- xfs_buf_t *pb,
+ xfs_ioend_t *ioend,
unsigned long max_offset,
unsigned long *fsbs,
unsigned int bbits)
@@ -283,7 +331,7 @@ xfs_probe_unwritten_page(
break;
xfs_map_at_offset(page, bh, p_offset, bbits, iomapp);
set_buffer_unwritten_io(bh);
- bh->b_private = pb;
+ bh->b_private = ioend;
p_offset += bh->b_size;
(*fsbs)++;
} while ((bh = bh->b_this_page) != head);
@@ -434,34 +482,15 @@ xfs_map_unwritten(
{
struct buffer_head *bh = curr;
xfs_iomap_t *tmp;
- xfs_buf_t *pb;
- loff_t offset, size;
+ xfs_ioend_t *ioend;
+ loff_t offset;
unsigned long nblocks = 0;
offset = start_page->index;
offset <<= PAGE_CACHE_SHIFT;
offset += p_offset;
- /* get an "empty" pagebuf to manage IO completion
- * Proper values will be set before returning */
- pb = pagebuf_lookup(iomapp->iomap_target, 0, 0, 0);
- if (!pb)
- return -EAGAIN;
-
- /* Take a reference to the inode to prevent it from
- * being reclaimed while we have outstanding unwritten
- * extent IO on it.
- */
- if ((igrab(inode)) != inode) {
- pagebuf_free(pb);
- return -EAGAIN;
- }
-
- /* Set the count to 1 initially, this will stop an I/O
- * completion callout which happens before we have started
- * all the I/O from calling pagebuf_iodone too early.
- */
- atomic_set(&pb->pb_io_remaining, 1);
+ ioend = xfs_alloc_ioend(inode);
/* First map forwards in the page consecutive buffers
* covering this unwritten extent
@@ -474,12 +503,12 @@ xfs_map_unwritten(
break;
xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp);
set_buffer_unwritten_io(bh);
- bh->b_private = pb;
+ bh->b_private = ioend;
p_offset += bh->b_size;
nblocks++;
} while ((bh = bh->b_this_page) != head);
- atomic_add(nblocks, &pb->pb_io_remaining);
+ atomic_add(nblocks, &ioend->io_remaining);
/* If we reached the end of the page, map forwards in any
* following pages which are also covered by this extent.
@@ -496,13 +525,13 @@ xfs_map_unwritten(
tloff = min(tlast, tloff);
for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
page = xfs_probe_unwritten_page(mapping,
- tindex, iomapp, pb,
+ tindex, iomapp, ioend,
PAGE_CACHE_SIZE, &bs, bbits);
if (!page)
break;
nblocks += bs;
- atomic_add(bs, &pb->pb_io_remaining);
- xfs_convert_page(inode, page, iomapp, wbc, pb,
+ atomic_add(bs, &ioend->io_remaining);
+ xfs_convert_page(inode, page, iomapp, wbc, ioend,
startio, all_bh);
/* stop if converting the next page might add
* enough blocks that the corresponding byte
@@ -514,12 +543,12 @@ xfs_map_unwritten(
if (tindex == tlast &&
(pg_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) {
page = xfs_probe_unwritten_page(mapping,
- tindex, iomapp, pb,
+ tindex, iomapp, ioend,
pg_offset, &bs, bbits);
if (page) {
nblocks += bs;
- atomic_add(bs, &pb->pb_io_remaining);
- xfs_convert_page(inode, page, iomapp, wbc, pb,
+ atomic_add(bs, &ioend->io_remaining);
+ xfs_convert_page(inode, page, iomapp, wbc, ioend,
startio, all_bh);
if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
goto enough;
@@ -528,21 +557,9 @@ xfs_map_unwritten(
}
enough:
- size = nblocks; /* NB: using 64bit number here */
- size <<= block_bits; /* convert fsb's to byte range */
-
- XFS_BUF_DATAIO(pb);
- XFS_BUF_ASYNC(pb);
- XFS_BUF_SET_SIZE(pb, size);
- XFS_BUF_SET_COUNT(pb, size);
- XFS_BUF_SET_OFFSET(pb, offset);
- XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode));
- XFS_BUF_SET_IODONE_FUNC(pb, linvfs_unwritten_convert);
-
- if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
- pagebuf_iodone(pb, 1, 1);
- }
-
+ ioend->io_size = (xfs_off_t)nblocks << block_bits;
+ ioend->io_offset = offset;
+ xfs_finish_ioend(ioend);
return 0;
}
@@ -787,7 +804,7 @@ xfs_page_state_convert(
continue;
if (!iomp) {
err = xfs_map_blocks(inode, offset, len, &iomap,
- BMAPI_READ|BMAPI_IGNSTATE);
+ BMAPI_WRITE|BMAPI_IGNSTATE);
if (err) {
goto error;
}
@@ -1028,6 +1045,44 @@ linvfs_get_blocks_direct(
create, 1, BMAPI_WRITE|BMAPI_DIRECT);
}
+STATIC void
+linvfs_end_io_direct(
+ struct kiocb *iocb,
+ loff_t offset,
+ ssize_t size,
+ void *private)
+{
+ xfs_ioend_t *ioend = iocb->private;
+
+ /*
+ * 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
+ * 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
+ * it anyway to keep the code uniform and simpler.
+ *
+ * The core direct I/O code might be changed to always call the
+ * completion handler in the future, in which case all this can
+ * go away.
+ */
+ if (private && size > 0) {
+ ioend->io_offset = offset;
+ ioend->io_size = size;
+ xfs_finish_ioend(ioend);
+ } else {
+ ASSERT(size >= 0);
+ xfs_destroy_ioend(ioend);
+ }
+
+ /*
+ * blockdev_direct_IO can return an error even afer the I/O
+ * completion handler was called. Thus we need to protect
+ * against double-freeing.
+ */
+ iocb->private = NULL;
+}
+
STATIC ssize_t
linvfs_direct_IO(
int rw,
@@ -1042,16 +1097,23 @@ linvfs_direct_IO(
xfs_iomap_t iomap;
int maps = 1;
int error;
+ ssize_t ret;
VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error);
if (error)
return -error;
- return blockdev_direct_IO_own_locking(rw, iocb, inode,
+ iocb->private = xfs_alloc_ioend(inode);
+
+ ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
iomap.iomap_target->pbr_bdev,
iov, offset, nr_segs,
linvfs_get_blocks_direct,
- linvfs_unwritten_convert_direct);
+ linvfs_end_io_direct);
+
+ if (unlikely(ret <= 0 && iocb->private))
+ xfs_destroy_ioend(iocb->private);
+ return ret;
}
@@ -1202,6 +1264,16 @@ out_unlock:
return error;
}
+STATIC int
+linvfs_invalidate_page(
+ struct page *page,
+ unsigned long offset)
+{
+ xfs_page_trace(XFS_INVALIDPAGE_ENTER,
+ page->mapping->host, page, offset);
+ return block_invalidatepage(page, offset);
+}
+
/*
* Called to move a page into cleanable state - and from there
* to be released. Possibly the page is already clean. We always
@@ -1279,6 +1351,7 @@ struct address_space_operations linvfs_aops = {
.writepage = linvfs_writepage,
.sync_page = block_sync_page,
.releasepage = linvfs_release_page,
+ .invalidatepage = linvfs_invalidate_page,
.prepare_write = linvfs_prepare_write,
.commit_write = generic_commit_write,
.bmap = linvfs_bmap,
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
new file mode 100644
index 000000000000..2fa62974a04d
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_AOPS_H__
+#define __XFS_AOPS_H__
+
+extern struct workqueue_struct *xfsdatad_workqueue;
+extern mempool_t *xfs_ioend_pool;
+
+typedef void (*xfs_ioend_func_t)(void *);
+
+typedef struct xfs_ioend {
+ unsigned int io_uptodate; /* I/O status register */
+ atomic_t io_remaining; /* hold count */
+ struct vnode *io_vnode; /* file being written to */
+ struct buffer_head *io_buffer_head;/* buffer linked list head */
+ size_t io_size; /* size of the extent */
+ xfs_off_t io_offset; /* offset in the file */
+ struct work_struct io_work; /* xfsdatad work queue */
+} xfs_ioend_t;
+
+#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 df0cba239dd5..e82cf72ac599 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -54,6 +54,7 @@
#include <linux/percpu.h>
#include <linux/blkdev.h>
#include <linux/hash.h>
+#include <linux/kthread.h>
#include "xfs_linux.h"
@@ -67,7 +68,7 @@ STATIC int xfsbufd_wakeup(int, unsigned int);
STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
STATIC struct workqueue_struct *xfslogd_workqueue;
-STATIC struct workqueue_struct *xfsdatad_workqueue;
+struct workqueue_struct *xfsdatad_workqueue;
/*
* Pagebuf debugging
@@ -590,8 +591,10 @@ found:
PB_SET_OWNER(pb);
}
- if (pb->pb_flags & PBF_STALE)
+ if (pb->pb_flags & PBF_STALE) {
+ ASSERT((pb->pb_flags & _PBF_DELWRI_Q) == 0);
pb->pb_flags &= PBF_MAPPED;
+ }
PB_TRACE(pb, "got_lock", 0);
XFS_STATS_INC(pb_get_locked);
return (pb);
@@ -700,25 +703,6 @@ xfs_buf_read_flags(
}
/*
- * Create a skeletal pagebuf (no pages associated with it).
- */
-xfs_buf_t *
-pagebuf_lookup(
- xfs_buftarg_t *target,
- loff_t ioff,
- size_t isize,
- page_buf_flags_t flags)
-{
- xfs_buf_t *pb;
-
- pb = pagebuf_allocate(flags);
- if (pb) {
- _pagebuf_initialize(pb, target, ioff, isize, flags);
- }
- return pb;
-}
-
-/*
* If we are not low on memory then do the readahead in a deadlock
* safe manner.
*/
@@ -913,22 +897,23 @@ pagebuf_rele(
do_free = 0;
}
- if (pb->pb_flags & PBF_DELWRI) {
- pb->pb_flags |= PBF_ASYNC;
- atomic_inc(&pb->pb_hold);
- pagebuf_delwri_queue(pb, 0);
- do_free = 0;
- } else if (pb->pb_flags & PBF_FS_MANAGED) {
+ if (pb->pb_flags & PBF_FS_MANAGED) {
do_free = 0;
}
if (do_free) {
+ ASSERT((pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q)) == 0);
list_del_init(&pb->pb_hash_list);
spin_unlock(&hash->bh_lock);
pagebuf_free(pb);
} else {
spin_unlock(&hash->bh_lock);
}
+ } else {
+ /*
+ * Catch reference count leaks
+ */
+ ASSERT(atomic_read(&pb->pb_hold) >= 0);
}
}
@@ -1006,13 +991,24 @@ pagebuf_lock(
* pagebuf_unlock
*
* pagebuf_unlock releases the lock on the buffer object created by
- * pagebuf_lock or pagebuf_cond_lock (not any
- * pinning of underlying pages created by pagebuf_pin).
+ * pagebuf_lock or pagebuf_cond_lock (not any pinning of underlying pages
+ * created by pagebuf_pin).
+ *
+ * If the buffer is marked delwri but is not queued, do so before we
+ * unlock the buffer as we need to set flags correctly. We also need to
+ * take a reference for the delwri queue because the unlocker is going to
+ * drop their's and they don't know we just queued it.
*/
void
pagebuf_unlock( /* unlock buffer */
xfs_buf_t *pb) /* buffer to unlock */
{
+ if ((pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q)) == PBF_DELWRI) {
+ atomic_inc(&pb->pb_hold);
+ pb->pb_flags |= PBF_ASYNC;
+ pagebuf_delwri_queue(pb, 0);
+ }
+
PB_CLEAR_OWNER(pb);
up(&pb->pb_sema);
PB_TRACE(pb, "unlock", 0);
@@ -1249,8 +1245,8 @@ bio_end_io_pagebuf(
int error)
{
xfs_buf_t *pb = (xfs_buf_t *)bio->bi_private;
- unsigned int i, blocksize = pb->pb_target->pbr_bsize;
- struct bio_vec *bvec = bio->bi_io_vec;
+ unsigned int blocksize = pb->pb_target->pbr_bsize;
+ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
if (bio->bi_size)
return 1;
@@ -1258,10 +1254,12 @@ bio_end_io_pagebuf(
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
pb->pb_error = EIO;
- for (i = 0; i < bio->bi_vcnt; i++, bvec++) {
+ do {
struct page *page = bvec->bv_page;
- if (pb->pb_error) {
+ if (unlikely(pb->pb_error)) {
+ if (pb->pb_flags & PBF_READ)
+ ClearPageUptodate(page);
SetPageError(page);
} else if (blocksize == PAGE_CACHE_SIZE) {
SetPageUptodate(page);
@@ -1270,10 +1268,13 @@ bio_end_io_pagebuf(
set_page_region(page, bvec->bv_offset, bvec->bv_len);
}
+ if (--bvec >= bio->bi_io_vec)
+ prefetchw(&bvec->bv_page->flags);
+
if (_pagebuf_iolocked(pb)) {
unlock_page(page);
}
- }
+ } while (bvec >= bio->bi_io_vec);
_pagebuf_iodone(pb, 1);
bio_put(bio);
@@ -1511,6 +1512,11 @@ again:
ASSERT(btp == bp->pb_target);
if (!(bp->pb_flags & PBF_FS_MANAGED)) {
spin_unlock(&hash->bh_lock);
+ /*
+ * Catch superblock reference count leaks
+ * immediately
+ */
+ BUG_ON(bp->pb_bn == 0);
delay(100);
goto again;
}
@@ -1686,17 +1692,20 @@ pagebuf_delwri_queue(
int unlock)
{
PB_TRACE(pb, "delwri_q", (long)unlock);
- ASSERT(pb->pb_flags & PBF_DELWRI);
+ ASSERT((pb->pb_flags & (PBF_DELWRI|PBF_ASYNC)) ==
+ (PBF_DELWRI|PBF_ASYNC));
spin_lock(&pbd_delwrite_lock);
/* If already in the queue, dequeue and place at tail */
if (!list_empty(&pb->pb_list)) {
+ ASSERT(pb->pb_flags & _PBF_DELWRI_Q);
if (unlock) {
atomic_dec(&pb->pb_hold);
}
list_del(&pb->pb_list);
}
+ pb->pb_flags |= _PBF_DELWRI_Q;
list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
pb->pb_queuetime = jiffies;
spin_unlock(&pbd_delwrite_lock);
@@ -1713,10 +1722,11 @@ pagebuf_delwri_dequeue(
spin_lock(&pbd_delwrite_lock);
if ((pb->pb_flags & PBF_DELWRI) && !list_empty(&pb->pb_list)) {
+ ASSERT(pb->pb_flags & _PBF_DELWRI_Q);
list_del_init(&pb->pb_list);
dequeued = 1;
}
- pb->pb_flags &= ~PBF_DELWRI;
+ pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q);
spin_unlock(&pbd_delwrite_lock);
if (dequeued)
@@ -1733,9 +1743,7 @@ pagebuf_runall_queues(
}
/* Defines for pagebuf daemon */
-STATIC DECLARE_COMPLETION(xfsbufd_done);
STATIC struct task_struct *xfsbufd_task;
-STATIC int xfsbufd_active;
STATIC int xfsbufd_force_flush;
STATIC int xfsbufd_force_sleep;
@@ -1761,14 +1769,8 @@ xfsbufd(
xfs_buftarg_t *target;
xfs_buf_t *pb, *n;
- /* Set up the thread */
- daemonize("xfsbufd");
current->flags |= PF_MEMALLOC;
- xfsbufd_task = current;
- xfsbufd_active = 1;
- barrier();
-
INIT_LIST_HEAD(&tmp);
do {
if (unlikely(freezing(current))) {
@@ -1778,10 +1780,10 @@ xfsbufd(
xfsbufd_force_sleep = 0;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100);
+ schedule_timeout_interruptible
+ (xfs_buf_timer_centisecs * msecs_to_jiffies(10));
- age = (xfs_buf_age_centisecs * HZ) / 100;
+ age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
spin_lock(&pbd_delwrite_lock);
list_for_each_entry_safe(pb, n, &pbd_delwrite_queue, pb_list) {
PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
@@ -1795,7 +1797,7 @@ xfsbufd(
break;
}
- pb->pb_flags &= ~PBF_DELWRI;
+ pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q);
pb->pb_flags |= PBF_WRITE;
list_move(&pb->pb_list, &tmp);
}
@@ -1816,9 +1818,9 @@ xfsbufd(
purge_addresses();
xfsbufd_force_flush = 0;
- } while (xfsbufd_active);
+ } while (!kthread_should_stop());
- complete_and_exit(&xfsbufd_done, 0);
+ return 0;
}
/*
@@ -1845,15 +1847,13 @@ xfs_flush_buftarg(
if (pb->pb_target != target)
continue;
- ASSERT(pb->pb_flags & PBF_DELWRI);
+ ASSERT(pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q));
PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
if (pagebuf_ispin(pb)) {
pincount++;
continue;
}
- pb->pb_flags &= ~PBF_DELWRI;
- pb->pb_flags |= PBF_WRITE;
list_move(&pb->pb_list, &tmp);
}
spin_unlock(&pbd_delwrite_lock);
@@ -1862,12 +1862,14 @@ xfs_flush_buftarg(
* Dropped the delayed write list lock, now walk the temporary list
*/
list_for_each_entry_safe(pb, n, &tmp, pb_list) {
+ pagebuf_lock(pb);
+ pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q);
+ pb->pb_flags |= PBF_WRITE;
if (wait)
pb->pb_flags &= ~PBF_ASYNC;
else
list_del_init(&pb->pb_list);
- pagebuf_lock(pb);
pagebuf_iostrategy(pb);
}
@@ -1901,9 +1903,11 @@ xfs_buf_daemons_start(void)
if (!xfsdatad_workqueue)
goto out_destroy_xfslogd_workqueue;
- error = kernel_thread(xfsbufd, NULL, CLONE_FS|CLONE_FILES);
- if (error < 0)
+ xfsbufd_task = kthread_run(xfsbufd, NULL, "xfsbufd");
+ if (IS_ERR(xfsbufd_task)) {
+ error = PTR_ERR(xfsbufd_task);
goto out_destroy_xfsdatad_workqueue;
+ }
return 0;
out_destroy_xfsdatad_workqueue:
@@ -1920,10 +1924,7 @@ xfs_buf_daemons_start(void)
STATIC void
xfs_buf_daemons_stop(void)
{
- xfsbufd_active = 0;
- barrier();
- wait_for_completion(&xfsbufd_done);
-
+ kthread_stop(xfsbufd_task);
destroy_workqueue(xfslogd_workqueue);
destroy_workqueue(xfsdatad_workqueue);
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 3f8f69a66aea..67c19f799232 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -89,6 +89,7 @@ typedef enum page_buf_flags_e { /* pb_flags values */
_PBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */
_PBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */
_PBF_RUN_QUEUES = (1 << 19),/* run block device task queue */
+ _PBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */
} page_buf_flags_t;
#define PBF_UPDATE (PBF_READ | PBF_WRITE)
@@ -206,13 +207,6 @@ extern xfs_buf_t *xfs_buf_read_flags( /* allocate and read a buffer */
#define xfs_buf_read(target, blkno, len, flags) \
xfs_buf_read_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED)
-extern xfs_buf_t *pagebuf_lookup(
- xfs_buftarg_t *,
- loff_t, /* starting offset of range */
- size_t, /* length of range */
- page_buf_flags_t); /* PBF_READ, PBF_WRITE, */
- /* PBF_FORCEIO, */
-
extern xfs_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */
/* no memory or disk address */
size_t len,
@@ -344,8 +338,6 @@ extern void pagebuf_trace(
-
-
/* These are just for xfs_syncsub... it sets an internal variable
* then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
*/
@@ -452,7 +444,7 @@ extern void pagebuf_trace(
#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr)
-extern inline xfs_caddr_t xfs_buf_offset(xfs_buf_t *bp, size_t offset)
+static inline xfs_caddr_t xfs_buf_offset(xfs_buf_t *bp, size_t offset)
{
if (bp->pb_flags & PBF_MAPPED)
return XFS_BUF_PTR(bp) + offset;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index f1ce4323f56e..3881622bcf08 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -311,6 +311,31 @@ linvfs_fsync(
#define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
+#ifdef CONFIG_XFS_DMAPI
+
+STATIC struct page *
+linvfs_filemap_nopage(
+ struct vm_area_struct *area,
+ unsigned long address,
+ int *type)
+{
+ struct inode *inode = area->vm_file->f_dentry->d_inode;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
+ int error;
+
+ ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
+
+ error = XFS_SEND_MMAP(mp, area, 0);
+ if (error)
+ return NULL;
+
+ return filemap_nopage(area, address, type);
+}
+
+#endif /* CONFIG_XFS_DMAPI */
+
+
STATIC int
linvfs_readdir(
struct file *filp,
@@ -390,14 +415,6 @@ done:
return -error;
}
-#ifdef CONFIG_XFS_DMAPI
-STATIC void
-linvfs_mmap_close(
- struct vm_area_struct *vma)
-{
- xfs_dm_mm_put(vma);
-}
-#endif /* CONFIG_XFS_DMAPI */
STATIC int
linvfs_file_mmap(
@@ -411,16 +428,11 @@ linvfs_file_mmap(
vma->vm_ops = &linvfs_file_vm_ops;
- if (vp->v_vfsp->vfs_flag & VFS_DMI) {
- xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
-
- error = -XFS_SEND_MMAP(mp, vma, 0);
- if (error)
- return error;
#ifdef CONFIG_XFS_DMAPI
+ if (vp->v_vfsp->vfs_flag & VFS_DMI) {
vma->vm_ops = &linvfs_dmapi_file_vm_ops;
-#endif
}
+#endif /* CONFIG_XFS_DMAPI */
VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
if (!error)
@@ -474,6 +486,7 @@ linvfs_ioctl_invis(
return error;
}
+#ifdef CONFIG_XFS_DMAPI
#ifdef HAVE_VMOP_MPROTECT
STATIC int
linvfs_mprotect(
@@ -494,6 +507,7 @@ linvfs_mprotect(
return error;
}
#endif /* HAVE_VMOP_MPROTECT */
+#endif /* CONFIG_XFS_DMAPI */
#ifdef HAVE_FOP_OPEN_EXEC
/* If the user is attempting to execute a file that is offline then
@@ -528,49 +542,10 @@ open_exec_out:
}
#endif /* HAVE_FOP_OPEN_EXEC */
-/*
- * Temporary workaround to the AIO direct IO write problem.
- * This code can go and we can revert to do_sync_write once
- * the writepage(s) rework is merged.
- */
-STATIC ssize_t
-linvfs_write(
- struct file *filp,
- const char __user *buf,
- size_t len,
- loff_t *ppos)
-{
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, filp);
- kiocb.ki_pos = *ppos;
- ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
- *ppos = kiocb.ki_pos;
- return ret;
-}
-STATIC ssize_t
-linvfs_write_invis(
- struct file *filp,
- const char __user *buf,
- size_t len,
- loff_t *ppos)
-{
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, filp);
- kiocb.ki_pos = *ppos;
- ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
- *ppos = kiocb.ki_pos;
- return ret;
-}
-
-
struct file_operations linvfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .write = linvfs_write,
+ .write = do_sync_write,
.readv = linvfs_readv,
.writev = linvfs_writev,
.aio_read = linvfs_aio_read,
@@ -592,7 +567,7 @@ struct file_operations linvfs_file_operations = {
struct file_operations linvfs_invis_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .write = linvfs_write_invis,
+ .write = do_sync_write,
.readv = linvfs_readv_invis,
.writev = linvfs_writev_invis,
.aio_read = linvfs_aio_read_invis,
@@ -626,8 +601,7 @@ static struct vm_operations_struct linvfs_file_vm_ops = {
#ifdef CONFIG_XFS_DMAPI
static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
- .close = linvfs_mmap_close,
- .nopage = filemap_nopage,
+ .nopage = linvfs_filemap_nopage,
.populate = filemap_populate,
#ifdef HAVE_VMOP_MPROTECT
.mprotect = linvfs_mprotect,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 05a447e51cc0..6a3326bcd8d0 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -141,13 +141,19 @@ xfs_find_handle(
return -XFS_ERROR(EINVAL);
}
- /* we need the vnode */
- vp = LINVFS_GET_VP(inode);
- if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFDIR:
+ case S_IFLNK:
+ break;
+ default:
iput(inode);
return -XFS_ERROR(EBADF);
}
+ /* we need the vnode */
+ vp = LINVFS_GET_VP(inode);
+
/* now we can grab the fsid */
memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
hsize = sizeof(xfs_fsid_t);
@@ -386,7 +392,7 @@ xfs_readlink_by_handle(
return -error;
/* Restrict this handle operation to symlinks only. */
- if (vp->v_type != VLNK) {
+ if (!S_ISLNK(inode->i_mode)) {
VN_RELE(vp);
return -XFS_ERROR(EINVAL);
}
@@ -982,10 +988,10 @@ xfs_ioc_space(
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
return -XFS_ERROR(EPERM);
- if (!(filp->f_flags & FMODE_WRITE))
+ if (!(filp->f_mode & FMODE_WRITE))
return -XFS_ERROR(EBADF);
- if (vp->v_type != VREG)
+ if (!VN_ISREG(vp))
return -XFS_ERROR(EINVAL);
if (copy_from_user(&bf, arg, sizeof(bf)))
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 0f8f1384eb36..4636b7f86f1f 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -47,8 +47,52 @@
#include "xfs_vnode.h"
#include "xfs_dfrag.h"
+#define _NATIVE_IOC(cmd, type) \
+ _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
+
#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
#define BROKEN_X86_ALIGNMENT
+/* on ia32 l_start is on a 32-bit boundary */
+typedef struct xfs_flock64_32 {
+ __s16 l_type;
+ __s16 l_whence;
+ __s64 l_start __attribute__((packed));
+ /* len == 0 means until end of file */
+ __s64 l_len __attribute__((packed));
+ __s32 l_sysid;
+ __u32 l_pid;
+ __s32 l_pad[4]; /* reserve area */
+} xfs_flock64_32_t;
+
+#define XFS_IOC_ALLOCSP_32 _IOW ('X', 10, struct xfs_flock64_32)
+#define XFS_IOC_FREESP_32 _IOW ('X', 11, struct xfs_flock64_32)
+#define XFS_IOC_ALLOCSP64_32 _IOW ('X', 36, struct xfs_flock64_32)
+#define XFS_IOC_FREESP64_32 _IOW ('X', 37, struct xfs_flock64_32)
+#define XFS_IOC_RESVSP_32 _IOW ('X', 40, struct xfs_flock64_32)
+#define XFS_IOC_UNRESVSP_32 _IOW ('X', 41, struct xfs_flock64_32)
+#define XFS_IOC_RESVSP64_32 _IOW ('X', 42, struct xfs_flock64_32)
+#define XFS_IOC_UNRESVSP64_32 _IOW ('X', 43, struct xfs_flock64_32)
+
+/* just account for different alignment */
+STATIC unsigned long
+xfs_ioctl32_flock(
+ unsigned long arg)
+{
+ xfs_flock64_32_t __user *p32 = (void __user *)arg;
+ xfs_flock64_t __user *p = compat_alloc_user_space(sizeof(*p));
+
+ if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) ||
+ copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) ||
+ copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) ||
+ copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) ||
+ copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) ||
+ 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;
+}
+
#else
typedef struct xfs_fsop_bulkreq32 {
@@ -103,7 +147,6 @@ __linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
/* not handled
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
- case XFS_IOC_PATH_TO_HANDLE:
case XFS_IOC_PATH_TO_FSHANDLE:
case XFS_IOC_OPEN_BY_HANDLE:
case XFS_IOC_FSSETDM_BY_HANDLE:
@@ -124,8 +167,21 @@ __linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
case XFS_IOC_ERROR_CLEARALL:
break;
-#ifndef BROKEN_X86_ALIGNMENT
- /* xfs_flock_t and xfs_bstat_t have wrong u32 vs u64 alignment */
+#ifdef BROKEN_X86_ALIGNMENT
+ /* xfs_flock_t has wrong u32 vs u64 alignment */
+ case XFS_IOC_ALLOCSP_32:
+ case XFS_IOC_FREESP_32:
+ case XFS_IOC_ALLOCSP64_32:
+ case XFS_IOC_FREESP64_32:
+ case XFS_IOC_RESVSP_32:
+ case XFS_IOC_UNRESVSP_32:
+ case XFS_IOC_RESVSP64_32:
+ case XFS_IOC_UNRESVSP64_32:
+ arg = xfs_ioctl32_flock(arg);
+ cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
+ break;
+
+#else /* These are handled fine if no alignment issues */
case XFS_IOC_ALLOCSP:
case XFS_IOC_FREESP:
case XFS_IOC_RESVSP:
@@ -134,6 +190,9 @@ __linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
case XFS_IOC_FREESP64:
case XFS_IOC_RESVSP64:
case XFS_IOC_UNRESVSP64:
+ break;
+
+ /* xfs_bstat_t still has wrong u32 vs u64 alignment */
case XFS_IOC_SWAPEXT:
break;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index f252605514eb..77708a8c9f87 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -140,7 +140,6 @@ linvfs_mknod(
memset(&va, 0, sizeof(va));
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
- va.va_type = IFTOVT(mode);
va.va_mode = mode;
switch (mode & S_IFMT) {
@@ -308,14 +307,13 @@ linvfs_symlink(
cvp = NULL;
memset(&va, 0, sizeof(va));
- va.va_type = VLNK;
- va.va_mode = irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO;
+ va.va_mode = S_IFLNK |
+ (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
error = 0;
VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
if (!error && cvp) {
- ASSERT(cvp->v_type == VLNK);
ip = LINVFS_GET_IP(cvp);
d_instantiate(dentry, ip);
validate_fields(dir);
@@ -425,9 +423,14 @@ linvfs_follow_link(
return NULL;
}
-static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+STATIC void
+linvfs_put_link(
+ struct dentry *dentry,
+ struct nameidata *nd,
+ void *p)
{
- char *s = nd_get_link(nd);
+ char *s = nd_get_link(nd);
+
if (!IS_ERR(s))
kfree(s);
}
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 42dc5e4662ed..68c5d885ed9c 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -64,7 +64,6 @@
#include <sema.h>
#include <time.h>
-#include <support/qsort.h>
#include <support/ktrace.h>
#include <support/debug.h>
#include <support/move.h>
@@ -104,6 +103,7 @@
#include <xfs_stats.h>
#include <xfs_sysctl.h>
#include <xfs_iops.h>
+#include <xfs_aops.h>
#include <xfs_super.h>
#include <xfs_globals.h>
#include <xfs_fs_subr.h>
@@ -254,11 +254,18 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#define MAX(a,b) (max(a,b))
#define howmany(x, y) (((x)+((y)-1))/(y))
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#define qsort(a,n,s,fn) sort(a,n,s,fn,NULL)
+/*
+ * Various platform dependent calls that don't fit anywhere else
+ */
#define xfs_stack_trace() dump_stack()
-
#define xfs_itruncate_data(ip, off) \
(-vmtruncate(LINVFS_GET_IP(XFS_ITOV(ip)), (off)))
+#define xfs_statvfs_fsid(statp, mp) \
+ ({ u64 id = huge_encode_dev((mp)->m_dev); \
+ __kernel_fsid_t *fsid = &(statp)->f_fsid; \
+ (fsid->val[0] = (u32)id, fsid->val[1] = (u32)(id >> 32)); })
/* Move the kernel do_div definition off to one side */
@@ -371,6 +378,4 @@ static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y)
return(x * y);
}
-#define qsort(a, n, s, cmp) sort(a, n, s, cmp, NULL)
-
#endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index acab58c48043..3b5fabe8dae9 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -660,9 +660,6 @@ xfs_write(
(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
- if (ioflags & IO_ISAIO)
- return XFS_ERROR(-ENOSYS);
-
if ((pos & target->pbr_smask) || (count & target->pbr_smask))
return XFS_ERROR(-EINVAL);
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index f197a720e394..6294dcdb797c 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -70,9 +70,10 @@ struct xfs_iomap;
#define XFS_SENDFILE_ENTER 21
#define XFS_WRITEPAGE_ENTER 22
#define XFS_RELEASEPAGE_ENTER 23
-#define XFS_IOMAP_ALLOC_ENTER 24
-#define XFS_IOMAP_ALLOC_MAP 25
-#define XFS_IOMAP_UNWRITTEN 26
+#define XFS_INVALIDPAGE_ENTER 24
+#define XFS_IOMAP_ALLOC_ENTER 25
+#define XFS_IOMAP_ALLOC_MAP 26
+#define XFS_IOMAP_UNWRITTEN 27
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 *,
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index f6dd7de25927..2302454d8d47 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -70,11 +70,15 @@
#include <linux/namei.h>
#include <linux/init.h>
#include <linux/mount.h>
+#include <linux/mempool.h>
#include <linux/writeback.h>
+#include <linux/kthread.h>
STATIC struct quotactl_ops linvfs_qops;
STATIC struct super_operations linvfs_sops;
-STATIC kmem_zone_t *linvfs_inode_zone;
+STATIC kmem_zone_t *xfs_vnode_zone;
+STATIC kmem_zone_t *xfs_ioend_zone;
+mempool_t *xfs_ioend_pool;
STATIC struct xfs_mount_args *
xfs_args_allocate(
@@ -138,24 +142,25 @@ STATIC __inline__ void
xfs_set_inodeops(
struct inode *inode)
{
- vnode_t *vp = LINVFS_GET_VP(inode);
-
- if (vp->v_type == VNON) {
- vn_mark_bad(vp);
- } else if (S_ISREG(inode->i_mode)) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
inode->i_op = &linvfs_file_inode_operations;
inode->i_fop = &linvfs_file_operations;
inode->i_mapping->a_ops = &linvfs_aops;
- } else if (S_ISDIR(inode->i_mode)) {
+ break;
+ case S_IFDIR:
inode->i_op = &linvfs_dir_inode_operations;
inode->i_fop = &linvfs_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
+ break;
+ case S_IFLNK:
inode->i_op = &linvfs_symlink_inode_operations;
if (inode->i_blocks)
inode->i_mapping->a_ops = &linvfs_aops;
- } else {
+ break;
+ default:
inode->i_op = &linvfs_file_inode_operations;
init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ break;
}
}
@@ -167,16 +172,23 @@ xfs_revalidate_inode(
{
struct inode *inode = LINVFS_GET_IP(vp);
- inode->i_mode = (ip->i_d.di_mode & MODEMASK) | VTTOIF(vp->v_type);
+ inode->i_mode = ip->i_d.di_mode;
inode->i_nlink = ip->i_d.di_nlink;
inode->i_uid = ip->i_d.di_uid;
inode->i_gid = ip->i_d.di_gid;
- if (((1 << vp->v_type) & ((1<<VBLK) | (1<<VCHR))) == 0) {
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFBLK:
+ case S_IFCHR:
+ inode->i_rdev =
+ MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
+ sysv_minor(ip->i_df.if_u2.if_rdev));
+ break;
+ default:
inode->i_rdev = 0;
- } else {
- xfs_dev_t dev = ip->i_df.if_u2.if_rdev;
- inode->i_rdev = MKDEV(sysv_major(dev) & 0x1ff, sysv_minor(dev));
+ break;
}
+
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_generation = ip->i_d.di_gen;
i_size_write(inode, ip->i_d.di_size);
@@ -231,7 +243,6 @@ xfs_initialize_vnode(
* finish our work.
*/
if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
- vp->v_type = IFTOVT(ip->i_d.di_mode);
xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
xfs_set_inodeops(inode);
@@ -274,8 +285,7 @@ linvfs_alloc_inode(
{
vnode_t *vp;
- vp = (vnode_t *)kmem_cache_alloc(linvfs_inode_zone,
- kmem_flags_convert(KM_SLEEP));
+ vp = kmem_cache_alloc(xfs_vnode_zone, kmem_flags_convert(KM_SLEEP));
if (!vp)
return NULL;
return LINVFS_GET_IP(vp);
@@ -285,11 +295,11 @@ STATIC void
linvfs_destroy_inode(
struct inode *inode)
{
- kmem_cache_free(linvfs_inode_zone, LINVFS_GET_VP(inode));
+ kmem_zone_free(xfs_vnode_zone, LINVFS_GET_VP(inode));
}
STATIC void
-init_once(
+linvfs_inode_init_once(
void *data,
kmem_cache_t *cachep,
unsigned long flags)
@@ -302,21 +312,41 @@ init_once(
}
STATIC int
-init_inodecache( void )
+linvfs_init_zones(void)
{
- linvfs_inode_zone = kmem_cache_create("linvfs_icache",
+ xfs_vnode_zone = kmem_cache_create("xfs_vnode",
sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT,
- init_once, NULL);
- if (linvfs_inode_zone == NULL)
- return -ENOMEM;
+ linvfs_inode_init_once, NULL);
+ if (!xfs_vnode_zone)
+ goto out;
+
+ xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend");
+ if (!xfs_ioend_zone)
+ goto out_destroy_vnode_zone;
+
+ xfs_ioend_pool = mempool_create(4 * MAX_BUF_PER_PAGE,
+ mempool_alloc_slab, mempool_free_slab,
+ xfs_ioend_zone);
+ if (!xfs_ioend_pool)
+ goto out_free_ioend_zone;
+
return 0;
+
+
+ out_free_ioend_zone:
+ kmem_zone_destroy(xfs_ioend_zone);
+ out_destroy_vnode_zone:
+ kmem_zone_destroy(xfs_vnode_zone);
+ out:
+ return -ENOMEM;
}
STATIC void
-destroy_inodecache( void )
+linvfs_destroy_zones(void)
{
- if (kmem_cache_destroy(linvfs_inode_zone))
- printk(KERN_WARNING "%s: cache still in use!\n", __FUNCTION__);
+ mempool_destroy(xfs_ioend_pool);
+ kmem_zone_destroy(xfs_vnode_zone);
+ kmem_zone_destroy(xfs_ioend_zone);
}
/*
@@ -354,17 +384,38 @@ linvfs_clear_inode(
struct inode *inode)
{
vnode_t *vp = LINVFS_GET_VP(inode);
+ int error, cache;
- if (vp) {
- vn_rele(vp);
- vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
- /*
- * Do all our cleanup, and remove this vnode.
- */
- vn_remove(vp);
+ vn_trace_entry(vp, "clear_inode", (inst_t *)__return_address);
+
+ XFS_STATS_INC(vn_rele);
+ XFS_STATS_INC(vn_remove);
+ XFS_STATS_INC(vn_reclaim);
+ XFS_STATS_DEC(vn_active);
+
+ /*
+ * This can happen because xfs_iget_core calls xfs_idestroy if we
+ * find an inode with di_mode == 0 but without IGET_CREATE set.
+ */
+ if (vp->v_fbhv)
+ VOP_INACTIVE(vp, NULL, cache);
+
+ VN_LOCK(vp);
+ vp->v_flag &= ~VMODIFIED;
+ VN_UNLOCK(vp, 0);
+
+ if (vp->v_fbhv) {
+ VOP_RECLAIM(vp, error);
+ if (error)
+ panic("vn_purge: cannot reclaim");
}
-}
+ ASSERT(vp->v_fbhv == NULL);
+
+#ifdef XFS_VNODE_TRACE
+ ktrace_free(vp->v_trace);
+#endif
+}
/*
* Enqueue a work item to be picked up by the vfs xfssyncd thread.
@@ -416,7 +467,7 @@ xfs_flush_inode(
igrab(inode);
xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
- delay(HZ/2);
+ delay(msecs_to_jiffies(500));
}
/*
@@ -441,7 +492,7 @@ xfs_flush_device(
igrab(inode);
xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
- delay(HZ/2);
+ delay(msecs_to_jiffies(500));
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
@@ -466,25 +517,15 @@ xfssyncd(
{
long timeleft;
vfs_t *vfsp = (vfs_t *) arg;
- struct list_head tmp;
struct vfs_sync_work *work, *n;
+ LIST_HEAD (tmp);
- daemonize("xfssyncd");
-
- vfsp->vfs_sync_work.w_vfs = vfsp;
- vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
- vfsp->vfs_sync_task = current;
- wmb();
- wake_up(&vfsp->vfs_wait_sync_task);
-
- INIT_LIST_HEAD(&tmp);
- timeleft = (xfs_syncd_centisecs * HZ) / 100;
+ timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeleft = schedule_timeout(timeleft);
+ timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
- if (vfsp->vfs_flag & VFS_UMOUNT)
+ if (kthread_should_stop())
break;
spin_lock(&vfsp->vfs_sync_lock);
@@ -495,7 +536,8 @@ xfssyncd(
*/
if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
if (!timeleft)
- timeleft = (xfs_syncd_centisecs * HZ) / 100;
+ timeleft = xfs_syncd_centisecs *
+ msecs_to_jiffies(10);
INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
list_add_tail(&vfsp->vfs_sync_work.w_list,
&vfsp->vfs_sync_list);
@@ -513,10 +555,6 @@ xfssyncd(
}
}
- vfsp->vfs_sync_task = NULL;
- wmb();
- wake_up(&vfsp->vfs_wait_sync_task);
-
return 0;
}
@@ -524,13 +562,11 @@ STATIC int
linvfs_start_syncd(
vfs_t *vfsp)
{
- int pid;
-
- pid = kernel_thread(xfssyncd, (void *) vfsp,
- CLONE_VM | CLONE_FS | CLONE_FILES);
- if (pid < 0)
- return -pid;
- wait_event(vfsp->vfs_wait_sync_task, vfsp->vfs_sync_task);
+ vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
+ vfsp->vfs_sync_work.w_vfs = vfsp;
+ vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd");
+ if (IS_ERR(vfsp->vfs_sync_task))
+ return -PTR_ERR(vfsp->vfs_sync_task);
return 0;
}
@@ -538,11 +574,7 @@ STATIC void
linvfs_stop_syncd(
vfs_t *vfsp)
{
- vfsp->vfs_flag |= VFS_UMOUNT;
- wmb();
-
- wake_up_process(vfsp->vfs_sync_task);
- wait_event(vfsp->vfs_wait_sync_task, !vfsp->vfs_sync_task);
+ kthread_stop(vfsp->vfs_sync_task);
}
STATIC void
@@ -866,9 +898,9 @@ init_xfs_fs( void )
ktrace_init(64);
- error = init_inodecache();
+ error = linvfs_init_zones();
if (error < 0)
- goto undo_inodecache;
+ goto undo_zones;
error = pagebuf_init();
if (error < 0)
@@ -889,9 +921,9 @@ undo_register:
pagebuf_terminate();
undo_pagebuf:
- destroy_inodecache();
+ linvfs_destroy_zones();
-undo_inodecache:
+undo_zones:
return error;
}
@@ -903,7 +935,7 @@ exit_xfs_fs( void )
unregister_filesystem(&xfs_fs_type);
xfs_cleanup();
pagebuf_terminate();
- destroy_inodecache();
+ linvfs_destroy_zones();
ktrace_uninit();
}
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 669c61644959..34cc902ec119 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -251,7 +251,6 @@ vfs_allocate( void )
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
INIT_LIST_HEAD(&vfsp->vfs_sync_list);
spin_lock_init(&vfsp->vfs_sync_lock);
- init_waitqueue_head(&vfsp->vfs_wait_sync_task);
init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
return vfsp;
}
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 7ee1f714e9ba..f0ab574fb47a 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -65,7 +65,6 @@ typedef struct vfs {
spinlock_t vfs_sync_lock; /* work item list lock */
int vfs_sync_seq; /* sync thread generation no. */
wait_queue_head_t vfs_wait_single_sync_task;
- wait_queue_head_t vfs_wait_sync_task;
} vfs_t;
#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */
@@ -96,7 +95,6 @@ typedef enum {
#define VFS_RDONLY 0x0001 /* read-only vfs */
#define VFS_GRPID 0x0002 /* group-ID assigned from directory */
#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */
-#define VFS_UMOUNT 0x0008 /* unmount in progress */
#define VFS_END 0x0008 /* max flag */
#define SYNC_ATTR 0x0001 /* sync attributes */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 250cad54e892..268f45bf6a9a 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -42,93 +42,33 @@ DEFINE_SPINLOCK(vnumber_lock);
*/
#define NVSYNC 37
#define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC])
-sv_t vsync[NVSYNC];
-
-/*
- * Translate stat(2) file types to vnode types and vice versa.
- * Aware of numeric order of S_IFMT and vnode type values.
- */
-enum vtype iftovt_tab[] = {
- VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
- VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
-};
-
-u_short vttoif_tab[] = {
- 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 0, S_IFSOCK
-};
+STATIC wait_queue_head_t vsync[NVSYNC];
void
vn_init(void)
{
- register sv_t *svp;
- register int i;
+ int i;
- for (svp = vsync, i = 0; i < NVSYNC; i++, svp++)
- init_sv(svp, SV_DEFAULT, "vsy", i);
+ for (i = 0; i < NVSYNC; i++)
+ init_waitqueue_head(&vsync[i]);
}
-/*
- * Clean a vnode of filesystem-specific data and prepare it for reuse.
- */
-STATIC int
-vn_reclaim(
+void
+vn_iowait(
struct vnode *vp)
{
- int error;
+ wait_queue_head_t *wq = vptosync(vp);
- XFS_STATS_INC(vn_reclaim);
- vn_trace_entry(vp, "vn_reclaim", (inst_t *)__return_address);
-
- /*
- * Only make the VOP_RECLAIM call if there are behaviors
- * to call.
- */
- if (vp->v_fbhv) {
- VOP_RECLAIM(vp, error);
- if (error)
- return -error;
- }
- ASSERT(vp->v_fbhv == NULL);
-
- VN_LOCK(vp);
- vp->v_flag &= (VRECLM|VWAIT);
- VN_UNLOCK(vp, 0);
-
- vp->v_type = VNON;
- vp->v_fbhv = NULL;
-
-#ifdef XFS_VNODE_TRACE
- ktrace_free(vp->v_trace);
- vp->v_trace = NULL;
-#endif
-
- return 0;
-}
-
-STATIC void
-vn_wakeup(
- struct vnode *vp)
-{
- VN_LOCK(vp);
- if (vp->v_flag & VWAIT)
- sv_broadcast(vptosync(vp));
- vp->v_flag &= ~(VRECLM|VWAIT|VMODIFIED);
- VN_UNLOCK(vp, 0);
+ wait_event(*wq, (atomic_read(&vp->v_iocount) == 0));
}
-int
-vn_wait(
+void
+vn_iowake(
struct vnode *vp)
{
- VN_LOCK(vp);
- if (vp->v_flag & (VINACT | VRECLM)) {
- vp->v_flag |= VWAIT;
- sv_wait(vptosync(vp), PINOD, &vp->v_lock, 0);
- return 1;
- }
- VN_UNLOCK(vp, 0);
- return 0;
+ if (atomic_dec_and_test(&vp->v_iocount))
+ wake_up(vptosync(vp));
}
struct vnode *
@@ -154,6 +94,8 @@ vn_initialize(
/* Initialize the first behavior and the behavior chain head. */
vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
+ atomic_set(&vp->v_iocount, 0);
+
#ifdef XFS_VNODE_TRACE
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif /* XFS_VNODE_TRACE */
@@ -163,30 +105,6 @@ vn_initialize(
}
/*
- * Get a reference on a vnode.
- */
-vnode_t *
-vn_get(
- struct vnode *vp,
- vmap_t *vmap)
-{
- struct inode *inode;
-
- XFS_STATS_INC(vn_get);
- inode = LINVFS_GET_IP(vp);
- if (inode->i_state & I_FREEING)
- return NULL;
-
- inode = ilookup(vmap->v_vfsp->vfs_super, vmap->v_ino);
- if (!inode) /* Inode not present */
- return NULL;
-
- vn_trace_exit(vp, "vn_get", (inst_t *)__return_address);
-
- return vp;
-}
-
-/*
* Revalidate the Linux inode from the vattr.
* Note: i_size _not_ updated; we must hold the inode
* semaphore when doing that - callers responsibility.
@@ -198,7 +116,7 @@ vn_revalidate_core(
{
struct inode *inode = LINVFS_GET_IP(vp);
- inode->i_mode = VTTOIF(vap->va_type) | vap->va_mode;
+ inode->i_mode = vap->va_mode;
inode->i_nlink = vap->va_nlink;
inode->i_uid = vap->va_uid;
inode->i_gid = vap->va_gid;
@@ -247,71 +165,6 @@ vn_revalidate(
}
/*
- * purge a vnode from the cache
- * At this point the vnode is guaranteed to have no references (vn_count == 0)
- * The caller has to make sure that there are no ways someone could
- * get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock).
- */
-void
-vn_purge(
- struct vnode *vp,
- vmap_t *vmap)
-{
- vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address);
-
-again:
- /*
- * Check whether vp has already been reclaimed since our caller
- * sampled its version while holding a filesystem cache lock that
- * its VOP_RECLAIM function acquires.
- */
- VN_LOCK(vp);
- if (vp->v_number != vmap->v_number) {
- VN_UNLOCK(vp, 0);
- return;
- }
-
- /*
- * If vp is being reclaimed or inactivated, wait until it is inert,
- * then proceed. Can't assume that vnode is actually reclaimed
- * just because the reclaimed flag is asserted -- a vn_alloc
- * reclaim can fail.
- */
- if (vp->v_flag & (VINACT | VRECLM)) {
- ASSERT(vn_count(vp) == 0);
- vp->v_flag |= VWAIT;
- sv_wait(vptosync(vp), PINOD, &vp->v_lock, 0);
- goto again;
- }
-
- /*
- * Another process could have raced in and gotten this vnode...
- */
- if (vn_count(vp) > 0) {
- VN_UNLOCK(vp, 0);
- return;
- }
-
- XFS_STATS_DEC(vn_active);
- vp->v_flag |= VRECLM;
- VN_UNLOCK(vp, 0);
-
- /*
- * Call VOP_RECLAIM and clean vp. The FSYNC_INVAL flag tells
- * vp's filesystem to flush and invalidate all cached resources.
- * When vn_reclaim returns, vp should have no private data,
- * either in a system cache or attached to v_data.
- */
- if (vn_reclaim(vp) != 0)
- panic("vn_purge: cannot reclaim");
-
- /*
- * Wakeup anyone waiting for vp to be reclaimed.
- */
- vn_wakeup(vp);
-}
-
-/*
* Add a reference to a referenced vnode.
*/
struct vnode *
@@ -330,80 +183,6 @@ vn_hold(
return vp;
}
-/*
- * Call VOP_INACTIVE on last reference.
- */
-void
-vn_rele(
- struct vnode *vp)
-{
- int vcnt;
- int cache;
-
- XFS_STATS_INC(vn_rele);
-
- VN_LOCK(vp);
-
- vn_trace_entry(vp, "vn_rele", (inst_t *)__return_address);
- vcnt = vn_count(vp);
-
- /*
- * Since we always get called from put_inode we know
- * that i_count won't be decremented after we
- * return.
- */
- if (!vcnt) {
- /*
- * As soon as we turn this on, noone can find us in vn_get
- * until we turn off VINACT or VRECLM
- */
- vp->v_flag |= VINACT;
- VN_UNLOCK(vp, 0);
-
- /*
- * Do not make the VOP_INACTIVE call if there
- * are no behaviors attached to the vnode to call.
- */
- if (vp->v_fbhv)
- VOP_INACTIVE(vp, NULL, cache);
-
- VN_LOCK(vp);
- if (vp->v_flag & VWAIT)
- sv_broadcast(vptosync(vp));
-
- vp->v_flag &= ~(VINACT|VWAIT|VRECLM|VMODIFIED);
- }
-
- VN_UNLOCK(vp, 0);
-
- vn_trace_exit(vp, "vn_rele", (inst_t *)__return_address);
-}
-
-/*
- * Finish the removal of a vnode.
- */
-void
-vn_remove(
- struct vnode *vp)
-{
- vmap_t vmap;
-
- /* Make sure we don't do this to the same vnode twice */
- if (!(vp->v_fbhv))
- return;
-
- XFS_STATS_INC(vn_remove);
- vn_trace_exit(vp, "vn_remove", (inst_t *)__return_address);
-
- /*
- * After the following purge the vnode
- * will no longer exist.
- */
- VMAP(vp, vmap);
- vn_purge(vp, &vmap);
-}
-
-
#ifdef XFS_VNODE_TRACE
#define KTRACE_ENTER(vp, vk, s, line, ra) \
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index a6e57c647be4..35f306cebb87 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -65,10 +65,6 @@ struct vattr;
struct xfs_iomap;
struct attrlist_cursor_kern;
-/*
- * Vnode types. VNON means no type.
- */
-enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VFIFO, VBAD, VSOCK };
typedef xfs_ino_t vnumber_t;
typedef struct dentry vname_t;
@@ -77,15 +73,14 @@ typedef bhv_head_t vn_bhv_head_t;
/*
* MP locking protocols:
* v_flag, v_vfsp VN_LOCK/VN_UNLOCK
- * v_type read-only or fs-dependent
*/
typedef struct vnode {
__u32 v_flag; /* vnode flags (see below) */
- enum vtype v_type; /* vnode type */
struct vfs *v_vfsp; /* ptr to containing VFS */
vnumber_t v_number; /* in-core vnode number */
vn_bhv_head_t v_bh; /* behavior head */
spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
+ atomic_t v_iocount; /* outstanding I/O count */
#ifdef XFS_VNODE_TRACE
struct ktrace *v_trace; /* trace header structure */
#endif
@@ -93,6 +88,12 @@ typedef struct vnode {
/* inode MUST be last */
} vnode_t;
+#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode)
+#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode)
+#define VN_ISDIR(vp) S_ISDIR((vp)->v_inode.i_mode)
+#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode)
+#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode)
+
#define v_fbhv v_bh.bh_first /* first behavior */
#define v_fops v_bh.bh_first->bd_ops /* first behavior ops */
@@ -133,22 +134,8 @@ typedef enum {
#define LINVFS_GET_IP(vp) (&(vp)->v_inode)
/*
- * Convert between vnode types and inode formats (since POSIX.1
- * defines mode word of stat structure in terms of inode formats).
- */
-extern enum vtype iftovt_tab[];
-extern u_short vttoif_tab[];
-#define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
-#define VTTOIF(indx) (vttoif_tab[(int)(indx)])
-#define MAKEIMODE(indx, mode) (int)(VTTOIF(indx) | (mode))
-
-
-/*
* Vnode flags.
*/
-#define VINACT 0x1 /* vnode is being inactivated */
-#define VRECLM 0x2 /* vnode is being reclaimed */
-#define VWAIT 0x4 /* waiting for VINACT/VRECLM to end */
#define VMODIFIED 0x8 /* XFS inode state possibly differs */
/* to the Linux inode state. */
@@ -408,7 +395,6 @@ typedef struct vnodeops {
*/
typedef struct vattr {
int va_mask; /* bit-mask of attributes present */
- enum vtype va_type; /* vnode type (for create) */
mode_t va_mode; /* file access mode and type */
xfs_nlink_t va_nlink; /* number of references to file */
uid_t va_uid; /* owner user id */
@@ -498,27 +484,12 @@ typedef struct vattr {
* Check whether mandatory file locking is enabled.
*/
#define MANDLOCK(vp, mode) \
- ((vp)->v_type == VREG && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
+ (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
extern void vn_init(void);
-extern int vn_wait(struct vnode *);
extern vnode_t *vn_initialize(struct inode *);
/*
- * Acquiring and invalidating vnodes:
- *
- * if (vn_get(vp, version, 0))
- * ...;
- * vn_purge(vp, version);
- *
- * vn_get and vn_purge must be called with vmap_t arguments, sampled
- * while a lock that the vnode's VOP_RECLAIM function acquires is
- * held, to ensure that the vnode sampled with the lock held isn't
- * recycled (VOP_RECLAIMed) or deallocated between the release of the lock
- * and the subsequent vn_get or vn_purge.
- */
-
-/*
* vnode_map structures _must_ match vn_epoch and vnode structure sizes.
*/
typedef struct vnode_map {
@@ -531,11 +502,11 @@ typedef struct vnode_map {
(vmap).v_number = (vp)->v_number, \
(vmap).v_ino = (vp)->v_inode.i_ino; }
-extern void vn_purge(struct vnode *, vmap_t *);
-extern vnode_t *vn_get(struct vnode *, vmap_t *);
extern int vn_revalidate(struct vnode *);
extern void vn_revalidate_core(struct vnode *, vattr_t *);
-extern void vn_remove(struct vnode *);
+
+extern void vn_iowait(struct vnode *vp);
+extern void vn_iowake(struct vnode *vp);
static inline int vn_count(struct vnode *vp)
{
@@ -546,7 +517,6 @@ static inline int vn_count(struct vnode *vp)
* Vnode reference counting functions (and macros for compatibility).
*/
extern vnode_t *vn_hold(struct vnode *);
-extern void vn_rele(struct vnode *);
#if defined(XFS_VNODE_TRACE)
#define VN_HOLD(vp) \
@@ -560,6 +530,12 @@ extern void vn_rele(struct vnode *);
#define VN_RELE(vp) (iput(LINVFS_GET_IP(vp)))
#endif
+static inline struct vnode *vn_grab(struct vnode *vp)
+{
+ struct inode *inode = igrab(LINVFS_GET_IP(vp));
+ return inode ? LINVFS_GET_VP(inode) : NULL;
+}
+
/*
* Vname handling macros.
*/
diff --git a/fs/xfs/quota/Makefile b/fs/xfs/quota/Makefile
new file mode 100644
index 000000000000..7a4f725b2824
--- /dev/null
+++ b/fs/xfs/quota/Makefile
@@ -0,0 +1 @@
+include $(TOPDIR)/fs/xfs/quota/Makefile-linux-$(VERSION).$(PATCHLEVEL)
diff --git a/fs/xfs/quota/Makefile-linux-2.6 b/fs/xfs/quota/Makefile-linux-2.6
new file mode 100644
index 000000000000..93e60e839355
--- /dev/null
+++ b/fs/xfs/quota/Makefile-linux-2.6
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA 94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+EXTRA_CFLAGS += -I $(TOPDIR)/fs/xfs -I $(TOPDIR)/fs/xfs/linux-2.6
+
+ifeq ($(CONFIG_XFS_DEBUG),y)
+ EXTRA_CFLAGS += -g -DDEBUG
+ #EXTRA_CFLAGS += -DQUOTADEBUG
+endif
+ifeq ($(CONFIG_XFS_TRACE),y)
+ EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
+ EXTRA_CFLAGS += -DXFS_VNODE_TRACE
+endif
+
+xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \
+ xfs_dquot_item.o \
+ xfs_trans_dquot.o \
+ xfs_qm_syscalls.o \
+ xfs_qm_bhv.o \
+ xfs_qm.o
+
+ifeq ($(CONFIG_XFS_QUOTA),y)
+xfs-$(CONFIG_PROC_FS) += xfs_qm_stats.o
+endif
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 46ce1e3ce1d6..e2e8d35fa4d0 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -421,7 +421,7 @@ xfs_qm_init_dquot_blk(
*/
STATIC int
xfs_qm_dqalloc(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_mount_t *mp,
xfs_dquot_t *dqp,
xfs_inode_t *quotip,
@@ -433,6 +433,7 @@ xfs_qm_dqalloc(
xfs_bmbt_irec_t map;
int nmaps, error, committed;
xfs_buf_t *bp;
+ xfs_trans_t *tp = *tpp;
ASSERT(tp != NULL);
xfs_dqtrace_entry(dqp, "DQALLOC");
@@ -492,10 +493,32 @@ xfs_qm_dqalloc(
xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
- if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
+ /*
+ * xfs_bmap_finish() may commit the current transaction and
+ * start a second transaction if the freelist is not empty.
+ *
+ * Since we still want to modify this buffer, we need to
+ * ensure that the buffer is not released on commit of
+ * the first transaction and ensure the buffer is added to the
+ * second transaction.
+ *
+ * If there is only one transaction then don't stop the buffer
+ * from being released when it commits later on.
+ */
+
+ xfs_trans_bhold(tp, bp);
+
+ if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) {
goto error1;
}
+ if (committed) {
+ tp = *tpp;
+ xfs_trans_bjoin(tp, bp);
+ } else {
+ xfs_trans_bhold_release(tp, bp);
+ }
+
*O_bpp = bp;
return 0;
@@ -514,7 +537,7 @@ xfs_qm_dqalloc(
*/
STATIC int
xfs_qm_dqtobp(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_dquot_t *dqp,
xfs_disk_dquot_t **O_ddpp,
xfs_buf_t **O_bpp,
@@ -528,6 +551,7 @@ xfs_qm_dqtobp(
xfs_disk_dquot_t *ddq;
xfs_dqid_t id;
boolean_t newdquot;
+ xfs_trans_t *tp = (tpp ? *tpp : NULL);
mp = dqp->q_mount;
id = INT_GET(dqp->q_core.d_id, ARCH_CONVERT);
@@ -579,9 +603,10 @@ xfs_qm_dqtobp(
return (ENOENT);
ASSERT(tp);
- if ((error = xfs_qm_dqalloc(tp, mp, dqp, quotip,
+ if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
dqp->q_fileoffset, &bp)))
return (error);
+ tp = *tpp;
newdquot = B_TRUE;
} else {
/*
@@ -645,7 +670,7 @@ xfs_qm_dqtobp(
/* ARGSUSED */
STATIC int
xfs_qm_dqread(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_dqid_t id,
xfs_dquot_t *dqp, /* dquot to get filled in */
uint flags)
@@ -653,15 +678,19 @@ xfs_qm_dqread(
xfs_disk_dquot_t *ddqp;
xfs_buf_t *bp;
int error;
+ xfs_trans_t *tp;
+
+ ASSERT(tpp);
/*
* get a pointer to the on-disk dquot and the buffer containing it
* dqp already knows its own type (GROUP/USER).
*/
xfs_dqtrace_entry(dqp, "DQREAD");
- if ((error = xfs_qm_dqtobp(tp, dqp, &ddqp, &bp, flags))) {
+ if ((error = xfs_qm_dqtobp(tpp, dqp, &ddqp, &bp, flags))) {
return (error);
}
+ tp = *tpp;
/* copy everything from disk dquot to the incore dquot */
memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
@@ -740,7 +769,7 @@ xfs_qm_idtodq(
* Read it from disk; xfs_dqread() takes care of
* all the necessary initialization of dquot's fields (locks, etc)
*/
- if ((error = xfs_qm_dqread(tp, id, dqp, flags))) {
+ if ((error = xfs_qm_dqread(&tp, id, dqp, flags))) {
/*
* This can happen if quotas got turned off (ESRCH),
* or if the dquot didn't exist on disk and we ask to
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 39175103c8e0..8ebc87176c78 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -113,20 +113,6 @@ typedef struct xfs_dquot {
#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
-/*
- * Quota Accounting/Enforcement flags
- */
-#define XFS_ALL_QUOTA_ACCT \
- (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
-#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
-#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
-
-#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
-#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
-#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
-#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
-
#ifdef DEBUG
static inline int
XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index f5271b7b1e84..e74eaa7dd1bc 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -509,6 +509,7 @@ xfs_qm_qoff_logitem_format(xfs_qoff_logitem_t *qf,
log_vector->i_addr = (xfs_caddr_t)&(qf->qql_format);
log_vector->i_len = sizeof(xfs_qoff_logitem_t);
+ XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_QUOTAOFF);
qf->qql_format.qf_size = 1;
}
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index f665ca8f9e96..efde16e0a913 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -365,16 +365,6 @@ xfs_qm_mount_quotas(
int error = 0;
uint sbf;
- /*
- * If a file system had quotas running earlier, but decided to
- * mount without -o uquota/pquota/gquota options, revoke the
- * quotachecked license, and bail out.
- */
- if (! XFS_IS_QUOTA_ON(mp) &&
- (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
- mp->m_qflags = 0;
- goto write_changes;
- }
/*
* If quotas on realtime volumes is not supported, we disable
@@ -388,11 +378,8 @@ xfs_qm_mount_quotas(
goto write_changes;
}
-#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
- cmn_err(CE_NOTE, "Attempting to turn on disk quotas.");
-#endif
-
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+
/*
* Allocate the quotainfo structure inside the mount struct, and
* create quotainode(s), and change/rev superblock if necessary.
@@ -410,19 +397,14 @@ xfs_qm_mount_quotas(
*/
if (XFS_QM_NEED_QUOTACHECK(mp) &&
!(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
-#ifdef DEBUG
- cmn_err(CE_NOTE, "Doing a quotacheck. Please wait.");
-#endif
if ((error = xfs_qm_quotacheck(mp))) {
/* Quotacheck has failed and quotas have
* been disabled.
*/
return XFS_ERROR(error);
}
-#ifdef DEBUG
- cmn_err(CE_NOTE, "Done quotacheck.");
-#endif
}
+
write_changes:
/*
* We actually don't have to acquire the SB_LOCK at all.
@@ -2010,7 +1992,7 @@ xfs_qm_quotacheck(
ASSERT(mp->m_quotainfo != NULL);
ASSERT(xfs_Gqm != NULL);
xfs_qm_destroy_quotainfo(mp);
- xfs_mount_reset_sbqflags(mp);
+ (void)xfs_mount_reset_sbqflags(mp);
} else {
cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
}
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index b03eecf3b6cb..0b00b3c67015 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -184,8 +184,6 @@ typedef struct xfs_dquot_acct {
#define XFS_QM_HOLD(xqm) ((xqm)->qm_nrefs++)
#define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--)
-extern void xfs_mount_reset_sbqflags(xfs_mount_t *);
-
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index dc3c37a1e158..8890a18a99d8 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -229,48 +229,6 @@ xfs_qm_syncall(
return error;
}
-/*
- * Clear the quotaflags in memory and in the superblock.
- */
-void
-xfs_mount_reset_sbqflags(
- xfs_mount_t *mp)
-{
- xfs_trans_t *tp;
- unsigned long s;
-
- mp->m_qflags = 0;
- /*
- * It is OK to look at sb_qflags here in mount path,
- * without SB_LOCK.
- */
- if (mp->m_sb.sb_qflags == 0)
- return;
- s = XFS_SB_LOCK(mp);
- mp->m_sb.sb_qflags = 0;
- XFS_SB_UNLOCK(mp, s);
-
- /*
- * if the fs is readonly, let the incore superblock run
- * with quotas off but don't flush the update out to disk
- */
- if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
- return;
-#ifdef QUOTADEBUG
- xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
-#endif
- tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
- if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
- XFS_DEFAULT_LOG_COUNT)) {
- xfs_trans_cancel(tp, 0);
- xfs_fs_cmn_err(CE_ALERT, mp,
- "xfs_mount_reset_sbqflags: Superblock update failed!");
- return;
- }
- xfs_mod_sb(tp, XFS_SB_QFLAGS);
- xfs_trans_commit(tp, 0, NULL);
-}
-
STATIC int
xfs_qm_newmount(
xfs_mount_t *mp,
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 68e98962dbef..15e02e8a9d4f 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -1053,7 +1053,6 @@ xfs_qm_dqrele_all_inodes(
struct xfs_mount *mp,
uint flags)
{
- vmap_t vmap;
xfs_inode_t *ip, *topino;
uint ireclaims;
vnode_t *vp;
@@ -1061,8 +1060,8 @@ xfs_qm_dqrele_all_inodes(
ASSERT(mp->m_quotainfo);
-again:
XFS_MOUNT_ILOCK(mp);
+again:
ip = mp->m_inodes;
if (ip == NULL) {
XFS_MOUNT_IUNLOCK(mp);
@@ -1090,18 +1089,14 @@ again:
}
vnode_refd = B_FALSE;
if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
- /*
- * Sample vp mapping while holding the mplock, lest
- * we come across a non-existent vnode.
- */
- VMAP(vp, vmap);
ireclaims = mp->m_ireclaims;
topino = mp->m_inodes;
- XFS_MOUNT_IUNLOCK(mp);
+ vp = vn_grab(vp);
+ if (!vp)
+ goto again;
+ XFS_MOUNT_IUNLOCK(mp);
/* XXX restart limit ? */
- if ( ! (vp = vn_get(vp, &vmap)))
- goto again;
xfs_ilock(ip, XFS_ILOCK_EXCL);
vnode_refd = B_TRUE;
} else {
@@ -1137,7 +1132,6 @@ again:
*/
if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) {
/* XXX use a sentinel */
- XFS_MOUNT_IUNLOCK(mp);
goto again;
}
ip = ip->i_mnext;
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 4ed7b6928cd7..4e1a5ec22fa3 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -31,6 +31,7 @@
*/
#include "debug.h"
+#include "spin.h"
#include <asm/page.h>
#include <linux/sched.h>
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index 3dae14c8c55a..fa8394f9437d 100644
--- a/fs/xfs/support/ktrace.c
+++ b/fs/xfs/support/ktrace.c
@@ -170,7 +170,7 @@ ktrace_enter(
void *val14,
void *val15)
{
- static lock_t wrap_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(wrap_lock);
unsigned long flags;
int index;
ktrace_entry_t *ktep;
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 8d01dce8c532..92fd1d67f878 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -85,7 +85,7 @@ xfs_acl_vhasacl_default(
{
int error;
- if (vp->v_type != VDIR)
+ if (!VN_ISDIR(vp))
return 0;
xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
return (error == 0);
@@ -389,7 +389,7 @@ xfs_acl_allow_set(
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
return EPERM;
- if (kind == _ACL_TYPE_DEFAULT && vp->v_type != VDIR)
+ if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
return ENOTDIR;
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
return EROFS;
@@ -750,7 +750,7 @@ xfs_acl_inherit(
* If the new file is a directory, its default ACL is a copy of
* the containing directory's default ACL.
*/
- if (vp->v_type == VDIR)
+ if (VN_ISDIR(vp))
xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
if (!error && !basicperms)
xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h
index ae35189b3d70..5ab0dd885b1b 100644
--- a/fs/xfs/xfs_arch.h
+++ b/fs/xfs/xfs_arch.h
@@ -40,22 +40,28 @@
#include <asm/byteorder.h>
-#ifdef __LITTLE_ENDIAN
-# define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
#ifdef __BIG_ENDIAN
-# define __BYTE_ORDER __BIG_ENDIAN
+#define XFS_NATIVE_HOST 1
+#else
+#undef XFS_NATIVE_HOST
+#endif
+
+#else /* __KERNEL__ */
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define XFS_NATIVE_HOST 1
+#else
+#undef XFS_NATIVE_HOST
#endif
#endif /* __KERNEL__ */
/* do we need conversion? */
-
#define ARCH_NOCONVERT 1
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-# define ARCH_CONVERT 0
-#else
+#ifdef XFS_NATIVE_HOST
# define ARCH_CONVERT ARCH_NOCONVERT
+#else
+# define ARCH_CONVERT 0
#endif
/* generic swapping macros */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 6f5d283888aa..3e76def1283d 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4754,10 +4754,20 @@ xfs_bmapi(
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
-(alen), rsvd);
- if (!error)
+ if (!error) {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
-(indlen), rsvd);
+ if (error && rt) {
+ xfs_mod_incore_sb(ip->i_mount,
+ XFS_SBS_FREXTENTS,
+ extsz, rsvd);
+ } else if (error) {
+ xfs_mod_incore_sb(ip->i_mount,
+ XFS_SBS_FDBLOCKS,
+ alen, rsvd);
+ }
+ }
if (error) {
if (XFS_IS_QUOTA_ON(ip->i_mount))
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 09c413576ba8..09a77b17565b 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2017,7 +2017,7 @@ xfs_bmbt_get_state(
ext_flag);
}
-#if __BYTE_ORDER != __BIG_ENDIAN
+#ifndef XFS_NATIVE_HOST
/* Endian flipping versions of the bmbt extraction functions */
void
xfs_bmbt_disk_get_all(
@@ -2087,7 +2087,7 @@ xfs_bmbt_disk_get_state(
return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
ext_flag);
}
-#endif
+#endif /* XFS_NATIVE_HOST */
/*
@@ -2531,7 +2531,7 @@ xfs_bmbt_set_allf(
#endif /* XFS_BIG_BLKNOS */
}
-#if __BYTE_ORDER != __BIG_ENDIAN
+#ifndef XFS_NATIVE_HOST
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
@@ -2617,7 +2617,7 @@ xfs_bmbt_disk_set_allf(
}
#endif /* XFS_BIG_BLKNOS */
}
-#endif
+#endif /* XFS_NATIVE_HOST */
/*
* Set the blockcount field in a bmap extent record.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 0a40cf126c28..2cf4fe45cbcb 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -62,7 +62,7 @@ typedef struct xfs_bmdr_block
* l1:0-20 are blockcount.
*/
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#ifndef XFS_NATIVE_HOST
#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
#define BMBT_EXNTFLAG_BITOFF 0
@@ -87,7 +87,7 @@ typedef struct xfs_bmdr_block
#define BMBT_BLOCKCOUNT_BITOFF 64 /* Start of second 64 bit container */
#define BMBT_BLOCKCOUNT_BITLEN 21
-#endif
+#endif /* XFS_NATIVE_HOST */
#define BMBT_USE_64 1
@@ -505,7 +505,7 @@ xfs_exntst_t
xfs_bmbt_get_state(
xfs_bmbt_rec_t *r);
-#if __BYTE_ORDER != __BIG_ENDIAN
+#ifndef XFS_NATIVE_HOST
void
xfs_bmbt_disk_get_all(
xfs_bmbt_rec_t *r,
@@ -538,7 +538,7 @@ xfs_bmbt_disk_get_startoff(
xfs_bmbt_get_blockcount(r)
#define xfs_bmbt_disk_get_startoff(r) \
xfs_bmbt_get_startoff(r)
-#endif
+#endif /* XFS_NATIVE_HOST */
int
xfs_bmbt_increment(
@@ -623,7 +623,7 @@ xfs_bmbt_set_state(
xfs_bmbt_rec_t *r,
xfs_exntst_t v);
-#if __BYTE_ORDER != __BIG_ENDIAN
+#ifndef XFS_NATIVE_HOST
void
xfs_bmbt_disk_set_all(
xfs_bmbt_rec_t *r,
@@ -641,7 +641,7 @@ xfs_bmbt_disk_set_allf(
xfs_bmbt_set_all(r, s)
#define xfs_bmbt_disk_set_allf(r, o, b, c, v) \
xfs_bmbt_set_allf(r, o, b, c, v)
-#endif
+#endif /* XFS_NATIVE_HOST */
void
xfs_bmbt_to_bmdr(
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 30b8285ad476..a264657acfd9 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -274,6 +274,7 @@ xfs_buf_item_format(
((bip->bli_format.blf_map_size - 1) * sizeof(uint)));
vecp->i_addr = (xfs_caddr_t)&bip->bli_format;
vecp->i_len = base_size;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BFORMAT);
vecp++;
nvecs = 1;
@@ -320,12 +321,14 @@ xfs_buf_item_format(
buffer_offset = first_bit * XFS_BLI_CHUNK;
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
vecp->i_len = nbits * XFS_BLI_CHUNK;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
nvecs++;
break;
} else if (next_bit != last_bit + 1) {
buffer_offset = first_bit * XFS_BLI_CHUNK;
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
vecp->i_len = nbits * XFS_BLI_CHUNK;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
nvecs++;
vecp++;
first_bit = next_bit;
@@ -337,6 +340,7 @@ xfs_buf_item_format(
buffer_offset = first_bit * XFS_BLI_CHUNK;
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
vecp->i_len = nbits * XFS_BLI_CHUNK;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
/* You would think we need to bump the nvecs here too, but we do not
* this number is used by recovery, and it gets confused by the boundary
* split here
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index dd423ce1bc8d..480bffc1f29f 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -127,13 +127,13 @@ typedef union {
* Watch the order here (endian-ness dependent).
*/
struct {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#ifndef XFS_NATIVE_HOST
xfs_dahash_t h; /* hash value */
__uint32_t be; /* block and entry */
-#else /* __BYTE_ORDER == __BIG_ENDIAN */
+#else
__uint32_t be; /* block and entry */
xfs_dahash_t h; /* hash value */
-#endif /* __BYTE_ORDER == __BIG_ENDIAN */
+#endif /* XFS_NATIVE_HOST */
} s;
} xfs_dircook_t;
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 55c17adaaa37..19e872856f6b 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index db7cbd1bc857..cc7d1494a45d 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -107,6 +107,7 @@ xfs_efi_item_format(xfs_efi_log_item_t *efip,
log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format);
log_vector->i_len = size;
+ XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_EFI_FORMAT);
ASSERT(size >= sizeof(xfs_efi_log_format_t));
}
@@ -426,6 +427,7 @@ xfs_efd_item_format(xfs_efd_log_item_t *efdp,
log_vector->i_addr = (xfs_caddr_t)&(efdp->efd_format);
log_vector->i_len = size;
+ XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_EFD_FORMAT);
ASSERT(size >= sizeof(xfs_efd_log_format_t));
}
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index d3da00045f26..0d9ae8fb4138 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -30,6 +30,8 @@
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
+#include <linux/delay.h>
+
#include "xfs.h"
#include "xfs_macros.h"
@@ -505,17 +507,15 @@ xfs_iget(
vnode_t *vp = NULL;
int error;
-retry:
XFS_STATS_INC(xs_ig_attempts);
+retry:
if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
bhv_desc_t *bdp;
xfs_inode_t *ip;
- int newnode;
vp = LINVFS_GET_VP(inode);
if (inode->i_state & I_NEW) {
-inode_allocate:
vn_initialize(inode);
error = xfs_iget_core(vp, mp, tp, ino, flags,
lock_flags, ipp, bno);
@@ -526,32 +526,25 @@ inode_allocate:
iput(inode);
}
} else {
- /* These are true if the inode is in inactive or
- * reclaim. The linux inode is about to go away,
- * wait for that path to finish, and try again.
+ /*
+ * If the inode is not fully constructed due to
+ * filehandle mistmatches wait for the inode to go
+ * away and try again.
+ *
+ * iget_locked will call __wait_on_freeing_inode
+ * to wait for the inode to go away.
*/
- if (vp->v_flag & (VINACT | VRECLM)) {
- vn_wait(vp);
+ if (is_bad_inode(inode) ||
+ ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp),
+ &xfs_vnodeops)) == NULL)) {
iput(inode);
+ delay(1);
goto retry;
}
- if (is_bad_inode(inode)) {
- iput(inode);
- return EIO;
- }
-
- bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
- if (bdp == NULL) {
- XFS_STATS_INC(xs_ig_dup);
- goto inode_allocate;
- }
ip = XFS_BHVTOI(bdp);
if (lock_flags != 0)
xfs_ilock(ip, lock_flags);
- newnode = (ip->i_d.di_mode == 0);
- if (newnode)
- xfs_iocore_inode_reinit(ip);
XFS_STATS_INC(xs_ig_found);
*ipp = ip;
error = 0;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 34bdf5909687..db43308aae93 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1128,7 +1128,6 @@ xfs_ialloc(
ASSERT(ip != NULL);
vp = XFS_ITOV(ip);
- vp->v_type = IFTOVT(mode);
ip->i_d.di_mode = (__uint16_t)mode;
ip->i_d.di_onlink = 0;
ip->i_d.di_nlink = nlink;
@@ -1250,7 +1249,7 @@ xfs_ialloc(
*/
xfs_trans_log_inode(tp, ip, flags);
- /* now that we have a v_type we can set Linux inode ops (& unlock) */
+ /* now that we have an i_mode we can set Linux inode ops (& unlock) */
VFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
*ipp = ip;
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 0eed30f5cb19..50e2cadf9091 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -248,6 +248,7 @@ xfs_inode_item_format(
vecp->i_addr = (xfs_caddr_t)&iip->ili_format;
vecp->i_len = sizeof(xfs_inode_log_format_t);
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IFORMAT);
vecp++;
nvecs = 1;
@@ -292,6 +293,7 @@ xfs_inode_item_format(
vecp->i_addr = (xfs_caddr_t)&ip->i_d;
vecp->i_len = sizeof(xfs_dinode_core_t);
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
vecp++;
nvecs++;
iip->ili_format.ilf_fields |= XFS_ILOG_CORE;
@@ -339,7 +341,7 @@ xfs_inode_item_format(
nrecs = ip->i_df.if_bytes /
(uint)sizeof(xfs_bmbt_rec_t);
ASSERT(nrecs > 0);
-#if __BYTE_ORDER == __BIG_ENDIAN
+#ifdef XFS_NATIVE_HOST
if (nrecs == ip->i_d.di_nextents) {
/*
* There are no delayed allocation
@@ -349,6 +351,7 @@ xfs_inode_item_format(
vecp->i_addr =
(char *)(ip->i_df.if_u1.if_extents);
vecp->i_len = ip->i_df.if_bytes;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);
} else
#endif
{
@@ -367,6 +370,7 @@ xfs_inode_item_format(
vecp->i_addr = (xfs_caddr_t)ext_buffer;
vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
XFS_DATA_FORK);
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);
}
ASSERT(vecp->i_len <= ip->i_df.if_bytes);
iip->ili_format.ilf_dsize = vecp->i_len;
@@ -384,6 +388,7 @@ xfs_inode_item_format(
ASSERT(ip->i_df.if_broot != NULL);
vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot;
vecp->i_len = ip->i_df.if_broot_bytes;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IBROOT);
vecp++;
nvecs++;
iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes;
@@ -409,6 +414,7 @@ xfs_inode_item_format(
ASSERT((ip->i_df.if_real_bytes == 0) ||
(ip->i_df.if_real_bytes == data_bytes));
vecp->i_len = (int)data_bytes;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ILOCAL);
vecp++;
nvecs++;
iip->ili_format.ilf_dsize = (unsigned)data_bytes;
@@ -467,7 +473,7 @@ xfs_inode_item_format(
#endif
ASSERT(nrecs > 0);
ASSERT(nrecs == ip->i_d.di_anextents);
-#if __BYTE_ORDER == __BIG_ENDIAN
+#ifdef XFS_NATIVE_HOST
/*
* There are not delayed allocation extents
* for attributes, so just point at the array.
@@ -486,6 +492,7 @@ xfs_inode_item_format(
vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
XFS_ATTR_FORK);
#endif
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_EXT);
iip->ili_format.ilf_asize = vecp->i_len;
vecp++;
nvecs++;
@@ -500,6 +507,7 @@ xfs_inode_item_format(
ASSERT(ip->i_afp->if_broot != NULL);
vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot;
vecp->i_len = ip->i_afp->if_broot_bytes;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_BROOT);
vecp++;
nvecs++;
iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes;
@@ -523,6 +531,7 @@ xfs_inode_item_format(
ASSERT((ip->i_afp->if_real_bytes == 0) ||
(ip->i_afp->if_real_bytes == data_bytes));
vecp->i_len = (int)data_bytes;
+ XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_LOCAL);
vecp++;
nvecs++;
iip->ili_format.ilf_asize = (unsigned)data_bytes;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 2edd6769e5d3..d0f5be63cddb 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -226,13 +226,12 @@ xfs_iomap(
xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
lockmode = XFS_LCK_MAP_SHARED(mp, io);
bmapi_flags = XFS_BMAPI_ENTIRE;
- if (flags & BMAPI_IGNSTATE)
- bmapi_flags |= XFS_BMAPI_IGSTATE;
break;
case BMAPI_WRITE:
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
- bmapi_flags = 0;
+ if (flags & BMAPI_IGNSTATE)
+ bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
XFS_ILOCK(mp, io, lockmode);
break;
case BMAPI_ALLOCATE:
@@ -391,9 +390,9 @@ xfs_iomap_write_direct(
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
xfs_bmap_free_t free_list;
int aeof;
- xfs_filblks_t datablocks, qblocks, resblks;
+ xfs_filblks_t qblocks, resblks;
int committed;
- int numrtextents;
+ int resrtextents;
/*
* Make sure that the dquots are there. This doesn't hold
@@ -434,14 +433,14 @@ xfs_iomap_write_direct(
if (!(extsz = ip->i_d.di_extsize))
extsz = mp->m_sb.sb_rextsize;
- numrtextents = qblocks = (count_fsb + extsz - 1);
- do_div(numrtextents, mp->m_sb.sb_rextsize);
+ resrtextents = qblocks = (count_fsb + extsz - 1);
+ do_div(resrtextents, mp->m_sb.sb_rextsize);
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
quota_flag = XFS_QMOPT_RES_RTBLKS;
- datablocks = 0;
} else {
- datablocks = qblocks = count_fsb;
+ resrtextents = 0;
+ resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb);
quota_flag = XFS_QMOPT_RES_REGBLKS;
- numrtextents = 0;
}
/*
@@ -449,9 +448,8 @@ xfs_iomap_write_direct(
*/
xfs_iunlock(ip, XFS_ILOCK_EXCL);
tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
- resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
error = xfs_trans_reserve(tp, resblks,
- XFS_WRITE_LOG_RES(mp), numrtextents,
+ XFS_WRITE_LOG_RES(mp), resrtextents,
XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 1cd2ac163877..54a6f1142403 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -159,11 +159,15 @@ xfs_buftarg_t *xlog_target;
void
xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
{
- if (! log->l_grant_trace) {
- log->l_grant_trace = ktrace_alloc(1024, KM_NOSLEEP);
- if (! log->l_grant_trace)
+ unsigned long cnts;
+
+ if (!log->l_grant_trace) {
+ log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP);
+ if (!log->l_grant_trace)
return;
}
+ /* ticket counts are 1 byte each */
+ cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8;
ktrace_enter(log->l_grant_trace,
(void *)tic,
@@ -178,10 +182,10 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
(void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn)),
(void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn)),
(void *)string,
- (void *)((unsigned long)13),
- (void *)((unsigned long)14),
- (void *)((unsigned long)15),
- (void *)((unsigned long)16));
+ (void *)((unsigned long)tic->t_trans_type),
+ (void *)cnts,
+ (void *)((unsigned long)tic->t_curr_res),
+ (void *)((unsigned long)tic->t_unit_res));
}
void
@@ -274,9 +278,11 @@ xfs_log_done(xfs_mount_t *mp,
* Release ticket if not permanent reservation or a specifc
* request has been made to release a permanent reservation.
*/
+ xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
xlog_ungrant_log_space(log, ticket);
xlog_state_put_ticket(log, ticket);
} else {
+ xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
xlog_regrant_reserve_log_space(log, ticket);
}
@@ -399,7 +405,8 @@ xfs_log_reserve(xfs_mount_t *mp,
int cnt,
xfs_log_ticket_t *ticket,
__uint8_t client,
- uint flags)
+ uint flags,
+ uint t_type)
{
xlog_t *log = mp->m_log;
xlog_ticket_t *internal_ticket;
@@ -421,13 +428,19 @@ xfs_log_reserve(xfs_mount_t *mp,
if (*ticket != NULL) {
ASSERT(flags & XFS_LOG_PERM_RESERV);
internal_ticket = (xlog_ticket_t *)*ticket;
+ xlog_trace_loggrant(log, internal_ticket, "xfs_log_reserve: existing ticket (permanent trans)");
xlog_grant_push_ail(mp, internal_ticket->t_unit_res);
retval = xlog_regrant_write_log_space(log, internal_ticket);
} else {
/* may sleep if need to allocate more tickets */
internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
client, flags);
+ internal_ticket->t_trans_type = t_type;
*ticket = internal_ticket;
+ xlog_trace_loggrant(log, internal_ticket,
+ (internal_ticket->t_flags & XLOG_TIC_PERM_RESERV) ?
+ "xfs_log_reserve: create new ticket (permanent trans)" :
+ "xfs_log_reserve: create new ticket");
xlog_grant_push_ail(mp,
(internal_ticket->t_unit_res *
internal_ticket->t_cnt));
@@ -601,8 +614,9 @@ xfs_log_unmount_write(xfs_mount_t *mp)
if (! (XLOG_FORCED_SHUTDOWN(log))) {
reg[0].i_addr = (void*)&magic;
reg[0].i_len = sizeof(magic);
+ XLOG_VEC_SET_TYPE(&reg[0], XLOG_REG_TYPE_UNMOUNT);
- error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0);
+ error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0, 0);
if (!error) {
/* remove inited flag */
((xlog_ticket_t *)tic)->t_flags = 0;
@@ -1272,6 +1286,7 @@ xlog_commit_record(xfs_mount_t *mp,
reg[0].i_addr = NULL;
reg[0].i_len = 0;
+ XLOG_VEC_SET_TYPE(&reg[0], XLOG_REG_TYPE_COMMIT);
ASSERT_ALWAYS(iclog);
if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
@@ -1605,6 +1620,117 @@ xlog_state_finish_copy(xlog_t *log,
/*
+ * print out info relating to regions written which consume
+ * the reservation
+ */
+#if defined(XFS_LOG_RES_DEBUG)
+STATIC void
+xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
+{
+ uint i;
+ uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t);
+
+ /* match with XLOG_REG_TYPE_* in xfs_log.h */
+ static char *res_type_str[XLOG_REG_TYPE_MAX] = {
+ "bformat",
+ "bchunk",
+ "efi_format",
+ "efd_format",
+ "iformat",
+ "icore",
+ "iext",
+ "ibroot",
+ "ilocal",
+ "iattr_ext",
+ "iattr_broot",
+ "iattr_local",
+ "qformat",
+ "dquot",
+ "quotaoff",
+ "LR header",
+ "unmount",
+ "commit",
+ "trans header"
+ };
+ static char *trans_type_str[XFS_TRANS_TYPE_MAX] = {
+ "SETATTR_NOT_SIZE",
+ "SETATTR_SIZE",
+ "INACTIVE",
+ "CREATE",
+ "CREATE_TRUNC",
+ "TRUNCATE_FILE",
+ "REMOVE",
+ "LINK",
+ "RENAME",
+ "MKDIR",
+ "RMDIR",
+ "SYMLINK",
+ "SET_DMATTRS",
+ "GROWFS",
+ "STRAT_WRITE",
+ "DIOSTRAT",
+ "WRITE_SYNC",
+ "WRITEID",
+ "ADDAFORK",
+ "ATTRINVAL",
+ "ATRUNCATE",
+ "ATTR_SET",
+ "ATTR_RM",
+ "ATTR_FLAG",
+ "CLEAR_AGI_BUCKET",
+ "QM_SBCHANGE",
+ "DUMMY1",
+ "DUMMY2",
+ "QM_QUOTAOFF",
+ "QM_DQALLOC",
+ "QM_SETQLIM",
+ "QM_DQCLUSTER",
+ "QM_QINOCREATE",
+ "QM_QUOTAOFF_END",
+ "SB_UNIT",
+ "FSYNC_TS",
+ "GROWFSRT_ALLOC",
+ "GROWFSRT_ZERO",
+ "GROWFSRT_FREE",
+ "SWAPEXT"
+ };
+
+ xfs_fs_cmn_err(CE_WARN, mp,
+ "xfs_log_write: reservation summary:\n"
+ " trans type = %s (%u)\n"
+ " unit res = %d bytes\n"
+ " current res = %d bytes\n"
+ " total reg = %u bytes (o/flow = %u bytes)\n"
+ " ophdrs = %u (ophdr space = %u bytes)\n"
+ " ophdr + reg = %u bytes\n"
+ " num regions = %u\n",
+ ((ticket->t_trans_type <= 0 ||
+ ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
+ "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
+ ticket->t_trans_type,
+ ticket->t_unit_res,
+ ticket->t_curr_res,
+ ticket->t_res_arr_sum, ticket->t_res_o_flow,
+ ticket->t_res_num_ophdrs, ophdr_spc,
+ ticket->t_res_arr_sum +
+ ticket->t_res_o_flow + ophdr_spc,
+ ticket->t_res_num);
+
+ for (i = 0; i < ticket->t_res_num; i++) {
+ uint r_type = ticket->t_res_arr[i].r_type;
+ cmn_err(CE_WARN,
+ "region[%u]: %s - %u bytes\n",
+ i,
+ ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
+ "bad-rtype" : res_type_str[r_type-1]),
+ ticket->t_res_arr[i].r_len);
+ }
+}
+#else
+#define xlog_print_tic_res(mp, ticket)
+#endif
+
+/*
* Write some region out to in-core log
*
* This will be called when writing externally provided regions or when
@@ -1677,16 +1803,21 @@ xlog_write(xfs_mount_t * mp,
* xlog_op_header_t and may need to be double word aligned.
*/
len = 0;
- if (ticket->t_flags & XLOG_TIC_INITED) /* acct for start rec of xact */
+ if (ticket->t_flags & XLOG_TIC_INITED) { /* acct for start rec of xact */
len += sizeof(xlog_op_header_t);
+ XLOG_TIC_ADD_OPHDR(ticket);
+ }
for (index = 0; index < nentries; index++) {
len += sizeof(xlog_op_header_t); /* each region gets >= 1 */
+ XLOG_TIC_ADD_OPHDR(ticket);
len += reg[index].i_len;
+ XLOG_TIC_ADD_REGION(ticket, reg[index].i_len, reg[index].i_type);
}
contwr = *start_lsn = 0;
if (ticket->t_curr_res < len) {
+ xlog_print_tic_res(mp, ticket);
#ifdef DEBUG
xlog_panic(
"xfs_log_write: reservation ran out. Need to up reservation");
@@ -1790,6 +1921,7 @@ xlog_write(xfs_mount_t * mp,
len += sizeof(xlog_op_header_t); /* from splitting of region */
/* account for new log op header */
ticket->t_curr_res -= sizeof(xlog_op_header_t);
+ XLOG_TIC_ADD_OPHDR(ticket);
}
xlog_verify_dest_ptr(log, ptr);
@@ -2282,6 +2414,9 @@ restart:
*/
if (log_offset == 0) {
ticket->t_curr_res -= log->l_iclog_hsize;
+ XLOG_TIC_ADD_REGION(ticket,
+ log->l_iclog_hsize,
+ XLOG_REG_TYPE_LRHEADER);
INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
ASSIGN_LSN(head->h_lsn, log);
ASSERT(log->l_curr_block >= 0);
@@ -2468,6 +2603,7 @@ xlog_regrant_write_log_space(xlog_t *log,
#endif
tic->t_curr_res = tic->t_unit_res;
+ XLOG_TIC_RESET_RES(tic);
if (tic->t_cnt > 0)
return (0);
@@ -2608,6 +2744,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w');
XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r');
ticket->t_curr_res = ticket->t_unit_res;
+ XLOG_TIC_RESET_RES(ticket);
xlog_trace_loggrant(log, ticket,
"xlog_regrant_reserve_log_space: sub current res");
xlog_verify_grant_head(log, 1);
@@ -2624,6 +2761,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
xlog_verify_grant_head(log, 0);
GRANT_UNLOCK(log, s);
ticket->t_curr_res = ticket->t_unit_res;
+ XLOG_TIC_RESET_RES(ticket);
} /* xlog_regrant_reserve_log_space */
@@ -3179,29 +3317,57 @@ xlog_ticket_get(xlog_t *log,
* and their unit amount is the total amount of space required.
*
* The following lines of code account for non-transaction data
- * which occupy space in the on-disk log.
+ * which occupy space in the on-disk log.
+ *
+ * Normal form of a transaction is:
+ * <oph><trans-hdr><start-oph><reg1-oph><reg1><reg2-oph>...<commit-oph>
+ * and then there are LR hdrs, split-recs and roundoff at end of syncs.
+ *
+ * We need to account for all the leadup data and trailer data
+ * around the transaction data.
+ * And then we need to account for the worst case in terms of using
+ * more space.
+ * The worst case will happen if:
+ * - the placement of the transaction happens to be such that the
+ * roundoff is at its maximum
+ * - the transaction data is synced before the commit record is synced
+ * i.e. <transaction-data><roundoff> | <commit-rec><roundoff>
+ * Therefore the commit record is in its own Log Record.
+ * This can happen as the commit record is called with its
+ * own region to xlog_write().
+ * This then means that in the worst case, roundoff can happen for
+ * the commit-rec as well.
+ * The commit-rec is smaller than padding in this scenario and so it is
+ * not added separately.
*/
+ /* for trans header */
+ unit_bytes += sizeof(xlog_op_header_t);
+ unit_bytes += sizeof(xfs_trans_header_t);
+
/* for start-rec */
- unit_bytes += sizeof(xlog_op_header_t);
+ unit_bytes += sizeof(xlog_op_header_t);
+
+ /* for LR headers */
+ num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log);
+ unit_bytes += log->l_iclog_hsize * num_headers;
+
+ /* for commit-rec LR header - note: padding will subsume the ophdr */
+ unit_bytes += log->l_iclog_hsize;
+
+ /* for split-recs - ophdrs added when data split over LRs */
+ unit_bytes += sizeof(xlog_op_header_t) * num_headers;
- /* for padding */
+ /* for roundoff padding for transaction data and one for commit record */
if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
- log->l_mp->m_sb.sb_logsunit > 1) {
+ log->l_mp->m_sb.sb_logsunit > 1) {
/* log su roundoff */
- unit_bytes += log->l_mp->m_sb.sb_logsunit;
+ unit_bytes += 2*log->l_mp->m_sb.sb_logsunit;
} else {
/* BB roundoff */
- unit_bytes += BBSIZE;
+ unit_bytes += 2*BBSIZE;
}
- /* for commit-rec */
- unit_bytes += sizeof(xlog_op_header_t);
-
- /* for LR headers */
- num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log);
- unit_bytes += log->l_iclog_hsize * num_headers;
-
tic->t_unit_res = unit_bytes;
tic->t_curr_res = unit_bytes;
tic->t_cnt = cnt;
@@ -3209,10 +3375,13 @@ xlog_ticket_get(xlog_t *log,
tic->t_tid = (xlog_tid_t)((__psint_t)tic & 0xffffffff);
tic->t_clientid = client;
tic->t_flags = XLOG_TIC_INITED;
+ tic->t_trans_type = 0;
if (xflags & XFS_LOG_PERM_RESERV)
tic->t_flags |= XLOG_TIC_PERM_RESERV;
sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
+ XLOG_TIC_RESET_RES(tic);
+
return tic;
} /* xlog_ticket_get */
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 0db122ddda3f..18961119fc65 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -114,9 +114,44 @@ xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
#define XFS_VOLUME 0x2
#define XFS_LOG 0xaa
+
+/* Region types for iovec's i_type */
+#if defined(XFS_LOG_RES_DEBUG)
+#define XLOG_REG_TYPE_BFORMAT 1
+#define XLOG_REG_TYPE_BCHUNK 2
+#define XLOG_REG_TYPE_EFI_FORMAT 3
+#define XLOG_REG_TYPE_EFD_FORMAT 4
+#define XLOG_REG_TYPE_IFORMAT 5
+#define XLOG_REG_TYPE_ICORE 6
+#define XLOG_REG_TYPE_IEXT 7
+#define XLOG_REG_TYPE_IBROOT 8
+#define XLOG_REG_TYPE_ILOCAL 9
+#define XLOG_REG_TYPE_IATTR_EXT 10
+#define XLOG_REG_TYPE_IATTR_BROOT 11
+#define XLOG_REG_TYPE_IATTR_LOCAL 12
+#define XLOG_REG_TYPE_QFORMAT 13
+#define XLOG_REG_TYPE_DQUOT 14
+#define XLOG_REG_TYPE_QUOTAOFF 15
+#define XLOG_REG_TYPE_LRHEADER 16
+#define XLOG_REG_TYPE_UNMOUNT 17
+#define XLOG_REG_TYPE_COMMIT 18
+#define XLOG_REG_TYPE_TRANSHDR 19
+#define XLOG_REG_TYPE_MAX 19
+#endif
+
+#if defined(XFS_LOG_RES_DEBUG)
+#define XLOG_VEC_SET_TYPE(vecp, t) ((vecp)->i_type = (t))
+#else
+#define XLOG_VEC_SET_TYPE(vecp, t)
+#endif
+
+
typedef struct xfs_log_iovec {
xfs_caddr_t i_addr; /* beginning address of region */
int i_len; /* length in bytes of region */
+#if defined(XFS_LOG_RES_DEBUG)
+ uint i_type; /* type of region */
+#endif
} xfs_log_iovec_t;
typedef void* xfs_log_ticket_t;
@@ -159,7 +194,8 @@ int xfs_log_reserve(struct xfs_mount *mp,
int count,
xfs_log_ticket_t *ticket,
__uint8_t clientid,
- uint flags);
+ uint flags,
+ uint t_type);
int xfs_log_write(struct xfs_mount *mp,
xfs_log_iovec_t region[],
int nentries,
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 1a1d452f15f9..a884cea82fca 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -112,7 +112,7 @@ struct xfs_mount;
* this has endian issues, of course.
*/
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#ifndef XFS_NATIVE_HOST
#define GET_CLIENT_ID(i,arch) \
((i) & 0xff)
#else
@@ -335,18 +335,66 @@ typedef __uint32_t xlog_tid_t;
#define XLOG_COVER_OPS 5
+
+/* Ticket reservation region accounting */
+#if defined(XFS_LOG_RES_DEBUG)
+#define XLOG_TIC_LEN_MAX 15
+#define XLOG_TIC_RESET_RES(t) ((t)->t_res_num = \
+ (t)->t_res_arr_sum = (t)->t_res_num_ophdrs = 0)
+#define XLOG_TIC_ADD_OPHDR(t) ((t)->t_res_num_ophdrs++)
+#define XLOG_TIC_ADD_REGION(t, len, type) \
+ do { \
+ if ((t)->t_res_num == XLOG_TIC_LEN_MAX) { \
+ /* add to overflow and start again */ \
+ (t)->t_res_o_flow += (t)->t_res_arr_sum; \
+ (t)->t_res_num = 0; \
+ (t)->t_res_arr_sum = 0; \
+ } \
+ (t)->t_res_arr[(t)->t_res_num].r_len = (len); \
+ (t)->t_res_arr[(t)->t_res_num].r_type = (type); \
+ (t)->t_res_arr_sum += (len); \
+ (t)->t_res_num++; \
+ } while (0)
+
+/*
+ * Reservation region
+ * As would be stored in xfs_log_iovec but without the i_addr which
+ * we don't care about.
+ */
+typedef struct xlog_res {
+ uint r_len;
+ uint r_type;
+} xlog_res_t;
+#else
+#define XLOG_TIC_RESET_RES(t)
+#define XLOG_TIC_ADD_OPHDR(t)
+#define XLOG_TIC_ADD_REGION(t, len, type)
+#endif
+
+
typedef struct xlog_ticket {
- sv_t t_sema; /* sleep on this semaphore :20 */
- struct xlog_ticket *t_next; /* : 4 */
- struct xlog_ticket *t_prev; /* : 4 */
- xlog_tid_t t_tid; /* transaction identifier : 4 */
- int t_curr_res; /* current reservation in bytes : 4 */
- int t_unit_res; /* unit reservation in bytes : 4 */
- __uint8_t t_ocnt; /* original count : 1 */
- __uint8_t t_cnt; /* current count : 1 */
- __uint8_t t_clientid; /* who does this belong to; : 1 */
- __uint8_t t_flags; /* properties of reservation : 1 */
+ sv_t t_sema; /* sleep on this semaphore : 20 */
+ struct xlog_ticket *t_next; /* :4|8 */
+ struct xlog_ticket *t_prev; /* :4|8 */
+ xlog_tid_t t_tid; /* transaction identifier : 4 */
+ int t_curr_res; /* current reservation in bytes : 4 */
+ int t_unit_res; /* unit reservation in bytes : 4 */
+ char t_ocnt; /* original count : 1 */
+ char t_cnt; /* current count : 1 */
+ char t_clientid; /* who does this belong to; : 1 */
+ char t_flags; /* properties of reservation : 1 */
+ uint t_trans_type; /* transaction type : 4 */
+
+#if defined (XFS_LOG_RES_DEBUG)
+ /* reservation array fields */
+ uint t_res_num; /* num in array : 4 */
+ xlog_res_t t_res_arr[XLOG_TIC_LEN_MAX]; /* array of res : X */
+ uint t_res_num_ophdrs; /* num op hdrs : 4 */
+ uint t_res_arr_sum; /* array sum : 4 */
+ uint t_res_o_flow; /* sum overflow : 4 */
+#endif
} xlog_ticket_t;
+
#endif
@@ -366,14 +414,10 @@ typedef struct xlog_op_header {
#define XLOG_FMT_IRIX_BE 3
/* our fmt */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define XLOG_FMT XLOG_FMT_LINUX_LE
-#else
-#if __BYTE_ORDER == __BIG_ENDIAN
+#ifdef XFS_NATIVE_HOST
#define XLOG_FMT XLOG_FMT_LINUX_BE
#else
-#error unknown byte order
-#endif
+#define XLOG_FMT XLOG_FMT_LINUX_LE
#endif
typedef struct xlog_rec_header {
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 0aac28ddb81c..14faabaabf29 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1387,7 +1387,7 @@ xlog_recover_add_to_cont_trans(
old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
old_len = item->ri_buf[item->ri_cnt-1].i_len;
- ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0);
+ ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
memcpy(&ptr[old_len], dp, len); /* d, s, l */
item->ri_buf[item->ri_cnt-1].i_len += len;
item->ri_buf[item->ri_cnt-1].i_addr = ptr;
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 4f40c92863d5..a6cd6324e946 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -42,7 +42,8 @@
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
-
+#include "xfs_quota.h"
+#include "xfs_error.h"
STATIC struct xfs_dquot *
xfs_dqvopchown_default(
@@ -54,8 +55,79 @@ xfs_dqvopchown_default(
return NULL;
}
+/*
+ * Clear the quotaflags in memory and in the superblock.
+ */
+int
+xfs_mount_reset_sbqflags(xfs_mount_t *mp)
+{
+ int error;
+ xfs_trans_t *tp;
+ unsigned long s;
+
+ mp->m_qflags = 0;
+ /*
+ * It is OK to look at sb_qflags here in mount path,
+ * without SB_LOCK.
+ */
+ if (mp->m_sb.sb_qflags == 0)
+ return 0;
+ s = XFS_SB_LOCK(mp);
+ mp->m_sb.sb_qflags = 0;
+ XFS_SB_UNLOCK(mp, s);
+
+ /*
+ * if the fs is readonly, let the incore superblock run
+ * with quotas off but don't flush the update out to disk
+ */
+ if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
+ return 0;
+#ifdef QUOTADEBUG
+ xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
+#endif
+ tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
+ if ((error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+ XFS_DEFAULT_LOG_COUNT))) {
+ xfs_trans_cancel(tp, 0);
+ xfs_fs_cmn_err(CE_ALERT, mp,
+ "xfs_mount_reset_sbqflags: Superblock update failed!");
+ return error;
+ }
+ xfs_mod_sb(tp, XFS_SB_QFLAGS);
+ error = xfs_trans_commit(tp, 0, NULL);
+ return error;
+}
+
+STATIC int
+xfs_noquota_init(
+ xfs_mount_t *mp,
+ uint *needquotamount,
+ uint *quotaflags)
+{
+ int error = 0;
+
+ *quotaflags = 0;
+ *needquotamount = B_FALSE;
+
+ ASSERT(!XFS_IS_QUOTA_ON(mp));
+
+ /*
+ * If a file system had quotas running earlier, but decided to
+ * mount without -o uquota/pquota/gquota options, revoke the
+ * quotachecked license.
+ */
+ if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
+ cmn_err(CE_NOTE,
+ "XFS resetting qflags for filesystem %s",
+ mp->m_fsname);
+
+ error = xfs_mount_reset_sbqflags(mp);
+ }
+ return error;
+}
+
xfs_qmops_t xfs_qmcore_stub = {
- .xfs_qminit = (xfs_qminit_t) fs_noerr,
+ .xfs_qminit = (xfs_qminit_t) xfs_noquota_init,
.xfs_qmdone = (xfs_qmdone_t) fs_noerr,
.xfs_qmmount = (xfs_qmmount_t) fs_noerr,
.xfs_qmunmount = (xfs_qmunmount_t) fs_noerr,
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 7134576ae7fa..32cb79752d5d 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -160,6 +160,20 @@ typedef struct xfs_qoff_logformat {
#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
/*
+ * Quota Accounting/Enforcement flags
+ */
+#define XFS_ALL_QUOTA_ACCT \
+ (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
+#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
+#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
+
+#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
+#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
+#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
+#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
+#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
+
+/*
* Incore only flags for quotaoff - these bits get cleared when quota(s)
* are in the process of getting turned off. These flags are in m_qflags but
* never in sb_qflags.
@@ -362,6 +376,7 @@ typedef struct xfs_dqtrxops {
f | XFS_QMOPT_RES_REGBLKS)
extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
+extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
extern struct bhv_vfsops xfs_qmops;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 06dfca531f79..92efe272b83d 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -276,7 +276,7 @@ xfs_trans_reserve(
error = xfs_log_reserve(tp->t_mountp, logspace, logcount,
&tp->t_ticket,
- XFS_TRANSACTION, log_flags);
+ XFS_TRANSACTION, log_flags, tp->t_type);
if (error) {
goto undo_blocks;
}
@@ -1032,6 +1032,7 @@ xfs_trans_fill_vecs(
tp->t_header.th_num_items = nitems;
log_vector->i_addr = (xfs_caddr_t)&tp->t_header;
log_vector->i_len = sizeof(xfs_trans_header_t);
+ XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_TRANSHDR);
}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index ec541d66fa2a..a263aec8b3a6 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -112,6 +112,7 @@ typedef struct xfs_trans_header {
#define XFS_TRANS_GROWFSRT_ZERO 38
#define XFS_TRANS_GROWFSRT_FREE 39
#define XFS_TRANS_SWAPEXT 40
+#define XFS_TRANS_TYPE_MAX 40
/* new transaction types need to be reflected in xfs_logprint(8) */
@@ -998,6 +999,7 @@ struct xfs_buf *xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_bjoin(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_bhold(xfs_trans_t *, struct xfs_buf *);
+void xfs_trans_bhold_release(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_binval(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 7bc5eab4c2c1..2a71b4f91bfa 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -379,8 +379,8 @@ xfs_trans_delete_ail(
else {
xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
"xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL");
- xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
AIL_UNLOCK(mp, s);
+ xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
}
}
}
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 144da7a85466..e733293dd7f4 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -714,6 +714,29 @@ xfs_trans_bhold(xfs_trans_t *tp,
}
/*
+ * Cancel the previous buffer hold request made on this buffer
+ * for this transaction.
+ */
+void
+xfs_trans_bhold_release(xfs_trans_t *tp,
+ xfs_buf_t *bp)
+{
+ xfs_buf_log_item_t *bip;
+
+ ASSERT(XFS_BUF_ISBUSY(bp));
+ ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
+ ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
+
+ bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+ ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
+ ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
+ ASSERT(atomic_read(&bip->bli_refcount) > 0);
+ ASSERT(bip->bli_flags & XFS_BLI_HOLD);
+ bip->bli_flags &= ~XFS_BLI_HOLD;
+ xfs_buf_item_trace("BHOLD RELEASE", bip);
+}
+
+/*
* This is called to mark bytes first through last inclusive of the given
* buffer as needing to be logged when the transaction is committed.
* The buffer must already be associated with the given transaction.
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 42bcc0215203..f1a904e23ade 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -795,7 +795,6 @@ xfs_statvfs(
xfs_mount_t *mp;
xfs_sb_t *sbp;
unsigned long s;
- u64 id;
mp = XFS_BHVTOM(bdp);
sbp = &(mp->m_sb);
@@ -823,9 +822,7 @@ xfs_statvfs(
statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
XFS_SB_UNLOCK(mp, s);
- id = huge_encode_dev(mp->m_dev);
- statp->f_fsid.val[0] = (u32)id;
- statp->f_fsid.val[1] = (u32)(id >> 32);
+ xfs_statvfs_fsid(statp, mp);
statp->f_namelen = MAXNAMELEN - 1;
return 0;
@@ -906,7 +903,6 @@ xfs_sync_inodes(
xfs_inode_t *ip_next;
xfs_buf_t *bp;
vnode_t *vp = NULL;
- vmap_t vmap;
int error;
int last_error;
uint64_t fflag;
@@ -1101,48 +1097,21 @@ xfs_sync_inodes(
* lock in xfs_ireclaim() after the inode is pulled from
* the mount list will sleep until we release it here.
* This keeps the vnode from being freed while we reference
- * it. It is also cheaper and simpler than actually doing
- * a vn_get() for every inode we touch here.
+ * it.
*/
if (xfs_ilock_nowait(ip, lock_flags) == 0) {
-
if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {
ip = ip->i_mnext;
continue;
}
- /*
- * We need to unlock the inode list lock in order
- * to lock the inode. Insert a marker record into
- * the inode list to remember our position, dropping
- * the lock is now done inside the IPOINTER_INSERT
- * macro.
- *
- * We also use the inode list lock to protect us
- * in taking a snapshot of the vnode version number
- * for use in calling vn_get().
- */
- VMAP(vp, vmap);
- IPOINTER_INSERT(ip, mp);
-
- vp = vn_get(vp, &vmap);
+ vp = vn_grab(vp);
if (vp == NULL) {
- /*
- * The vnode was reclaimed once we let go
- * of the inode list lock. Skip to the
- * next list entry. Remove the marker.
- */
-
- XFS_MOUNT_ILOCK(mp);
-
- mount_locked = B_TRUE;
- vnode_refed = B_FALSE;
-
- IPOINTER_REMOVE(ip, mp);
-
+ ip = ip->i_mnext;
continue;
}
+ IPOINTER_INSERT(ip, mp);
xfs_ilock(ip, lock_flags);
ASSERT(vp == XFS_ITOV(ip));
@@ -1533,7 +1502,10 @@ xfs_syncsub(
* eventually kicked out of the cache.
*/
if (flags & SYNC_REFCACHE) {
- xfs_refcache_purge_some(mp);
+ if (flags & SYNC_WAIT)
+ xfs_refcache_purge_mp(mp);
+ else
+ xfs_refcache_purge_some(mp);
}
/*
@@ -1649,6 +1621,10 @@ xfs_vget(
#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
+#define MNTOPT_GRPID "grpid" /* group-ID from parent directory */
+#define MNTOPT_NOGRPID "nogrpid" /* group-ID from current process */
+#define MNTOPT_BSDGROUPS "bsdgroups" /* group-ID from parent directory */
+#define MNTOPT_SYSVGROUPS "sysvgroups" /* group-ID from current process */
#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
@@ -1769,6 +1745,12 @@ xfs_parseargs(
}
args->flags |= XFSMNT_IHASHSIZE;
args->ihashsize = simple_strtoul(value, &eov, 10);
+ } else if (!strcmp(this_char, MNTOPT_GRPID) ||
+ !strcmp(this_char, MNTOPT_BSDGROUPS)) {
+ vfsp->vfs_flag |= VFS_GRPID;
+ } else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
+ !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
+ vfsp->vfs_flag &= ~VFS_GRPID;
} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
args->flags |= XFSMNT_WSYNC;
} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
@@ -1890,6 +1872,7 @@ xfs_showargs(
};
struct proc_xfs_info *xfs_infop;
struct xfs_mount *mp = XFS_BHVTOM(bhv);
+ struct vfs *vfsp = XFS_MTOVFS(mp);
for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
if (mp->m_flags & xfs_infop->flag)
@@ -1926,7 +1909,10 @@ xfs_showargs(
if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT))
seq_printf(m, "," MNTOPT_64BITINODE);
-
+
+ if (vfsp->vfs_flag & VFS_GRPID)
+ seq_printf(m, "," MNTOPT_GRPID);
+
return 0;
}
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 1377c868f3f4..58bfe629b933 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -104,7 +104,7 @@ xfs_open(
* If it's a directory with any blocks, read-ahead block 0
* as we're almost certain to have the next operation be a read there.
*/
- if (vp->v_type == VDIR && ip->i_d.di_nextents > 0) {
+ if (VN_ISDIR(vp) && ip->i_d.di_nextents > 0) {
mode = xfs_ilock_map_shared(ip);
if (ip->i_d.di_nextents > 0)
(void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
@@ -163,18 +163,21 @@ xfs_getattr(
/*
* Copy from in-core inode.
*/
- vap->va_type = vp->v_type;
- vap->va_mode = ip->i_d.di_mode & MODEMASK;
+ vap->va_mode = ip->i_d.di_mode;
vap->va_uid = ip->i_d.di_uid;
vap->va_gid = ip->i_d.di_gid;
vap->va_projid = ip->i_d.di_projid;
/*
* Check vnode type block/char vs. everything else.
- * Do it with bitmask because that's faster than looking
- * for multiple values individually.
*/
- if (((1 << vp->v_type) & ((1<<VBLK) | (1<<VCHR))) == 0) {
+ switch (ip->i_d.di_mode & S_IFMT) {
+ case S_IFBLK:
+ case S_IFCHR:
+ vap->va_rdev = ip->i_df.if_u2.if_rdev;
+ vap->va_blocksize = BLKDEV_IOSIZE;
+ break;
+ default:
vap->va_rdev = 0;
if (!(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
@@ -224,9 +227,7 @@ xfs_getattr(
(ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
(mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
}
- } else {
- vap->va_rdev = ip->i_df.if_u2.if_rdev;
- vap->va_blocksize = BLKDEV_IOSIZE;
+ break;
}
vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec;
@@ -468,7 +469,7 @@ xfs_setattr(
m |= S_ISGID;
#if 0
/* Linux allows this, Irix doesn't. */
- if ((vap->va_mode & S_ISVTX) && vp->v_type != VDIR)
+ if ((vap->va_mode & S_ISVTX) && !VN_ISDIR(vp))
m |= S_ISVTX;
#endif
if (m && !capable(CAP_FSETID))
@@ -546,10 +547,10 @@ xfs_setattr(
goto error_return;
}
- if (vp->v_type == VDIR) {
+ if (VN_ISDIR(vp)) {
code = XFS_ERROR(EISDIR);
goto error_return;
- } else if (vp->v_type != VREG) {
+ } else if (!VN_ISREG(vp)) {
code = XFS_ERROR(EINVAL);
goto error_return;
}
@@ -1567,7 +1568,7 @@ xfs_release(
vp = BHV_TO_VNODE(bdp);
ip = XFS_BHVTOI(bdp);
- if ((vp->v_type != VREG) || (ip->i_d.di_mode == 0)) {
+ if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) {
return 0;
}
@@ -1895,7 +1896,7 @@ xfs_create(
dp = XFS_BHVTOI(dir_bdp);
mp = dp->i_mount;
- dm_di_mode = vap->va_mode|VTTOIF(vap->va_type);
+ dm_di_mode = vap->va_mode;
namelen = VNAMELEN(dentry);
if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
@@ -1973,8 +1974,7 @@ xfs_create(
(error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
goto error_return;
rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
- error = xfs_dir_ialloc(&tp, dp,
- MAKEIMODE(vap->va_type,vap->va_mode), 1,
+ error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
rdev, credp, prid, resblks > 0,
&ip, &committed);
if (error) {
@@ -2620,7 +2620,7 @@ xfs_link(
vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
target_namelen = VNAMELEN(dentry);
- if (src_vp->v_type == VDIR)
+ if (VN_ISDIR(src_vp))
return XFS_ERROR(EPERM);
src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
@@ -2805,7 +2805,7 @@ xfs_mkdir(
tp = NULL;
dp_joined_to_trans = B_FALSE;
- dm_di_mode = vap->va_mode|VTTOIF(vap->va_type);
+ dm_di_mode = vap->va_mode;
if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
@@ -2879,8 +2879,7 @@ xfs_mkdir(
/*
* create the directory inode.
*/
- error = xfs_dir_ialloc(&tp, dp,
- MAKEIMODE(vap->va_type,vap->va_mode), 2,
+ error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 2,
0, credp, prid, resblks > 0,
&cdp, NULL);
if (error) {
@@ -3650,7 +3649,7 @@ xfs_rwlock(
vnode_t *vp;
vp = BHV_TO_VNODE(bdp);
- if (vp->v_type == VDIR)
+ if (VN_ISDIR(vp))
return 1;
ip = XFS_BHVTOI(bdp);
if (locktype == VRWLOCK_WRITE) {
@@ -3681,7 +3680,7 @@ xfs_rwunlock(
vnode_t *vp;
vp = BHV_TO_VNODE(bdp);
- if (vp->v_type == VDIR)
+ if (VN_ISDIR(vp))
return;
ip = XFS_BHVTOI(bdp);
if (locktype == VRWLOCK_WRITE) {
@@ -3847,51 +3846,10 @@ xfs_reclaim(
return 0;
}
- if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
- if (ip->i_d.di_size > 0) {
- /*
- * Flush and invalidate any data left around that is
- * a part of this file.
- *
- * Get the inode's i/o lock so that buffers are pushed
- * out while holding the proper lock. We can't hold
- * the inode lock here since flushing out buffers may
- * cause us to try to get the lock in xfs_strategy().
- *
- * We don't have to call remapf() here, because there
- * cannot be any mapped file references to this vnode
- * since it is being reclaimed.
- */
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
-
- /*
- * If we hit an IO error, we need to make sure that the
- * buffer and page caches of file data for
- * the file are tossed away. We don't want to use
- * VOP_FLUSHINVAL_PAGES here because we don't want dirty
- * pages to stay attached to the vnode, but be
- * marked P_BAD. pdflush/vnode_pagebad
- * hates that.
- */
- if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
- VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_NONE);
- } else {
- VOP_TOSS_PAGES(vp, 0, -1, FI_NONE);
- }
+ vn_iowait(vp);
- ASSERT(VN_CACHED(vp) == 0);
- ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) ||
- ip->i_delayed_blks == 0);
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- } else if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
- /*
- * di_size field may not be quite accurate if we're
- * shutting down.
- */
- VOP_TOSS_PAGES(vp, 0, -1, FI_NONE);
- ASSERT(VN_CACHED(vp) == 0);
- }
- }
+ ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
+ ASSERT(VN_CACHED(vp) == 0);
/* If we have nothing to flush with this inode then complete the
* teardown now, otherwise break the link between the xfs inode
@@ -4567,7 +4525,7 @@ xfs_change_file_space(
/*
* must be a regular file and have write permission
*/
- if (vp->v_type != VREG)
+ if (!VN_ISREG(vp))
return XFS_ERROR(EINVAL);
xfs_ilock(ip, XFS_ILOCK_SHARED);
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 2f6ab189fc6f..427cff1a3f83 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -44,7 +44,6 @@
#ifndef _ACCONFIG_H
#define _ACCONFIG_H
-
/******************************************************************************
*
* Configuration options
@@ -64,7 +63,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20050408
+#define ACPI_CA_VERSION 0x20050902
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
@@ -78,11 +77,10 @@
/* Maximum objects in the various object caches */
-#define ACPI_MAX_STATE_CACHE_DEPTH 64 /* State objects */
-#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */
-#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 64 /* Parse tree objects */
-#define ACPI_MAX_OBJECT_CACHE_DEPTH 64 /* Interpreter operand objects */
-#define ACPI_MAX_WALK_CACHE_DEPTH 4 /* Objects for parse tree walks */
+#define ACPI_MAX_STATE_CACHE_DEPTH 96 /* State objects */
+#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 */
/*
* Should the subystem abort the loading of an ACPI table if the
@@ -90,7 +88,6 @@
*/
#define ACPI_CHECKSUM_ABORT FALSE
-
/******************************************************************************
*
* Subsystem Constants
@@ -104,7 +101,7 @@
/* String size constants */
#define ACPI_MAX_STRING_LENGTH 512
-#define ACPI_PATHNAME_MAX 256 /* A full namespace pathname */
+#define ACPI_PATHNAME_MAX 256 /* A full namespace pathname */
/* Maximum count for a semaphore object */
@@ -118,7 +115,6 @@
#define ACPI_SYSMEM_REGION_WINDOW_SIZE 4096
-
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
@@ -156,15 +152,15 @@
/* Names within the namespace are 4 bytes long */
#define ACPI_NAME_SIZE 4
-#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */
+#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */
#define ACPI_PATH_SEPARATOR '.'
/* Constants used in searching for the RSDP in low memory */
-#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */
+#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */
#define ACPI_EBDA_PTR_LENGTH 2
#define ACPI_EBDA_WINDOW_SIZE 1024
-#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */
#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000
#define ACPI_RSDP_SCAN_STEP 16
@@ -199,18 +195,15 @@
#define ACPI_NUM_OSI_STRINGS 10
-
/******************************************************************************
*
* ACPI AML Debugger
*
*****************************************************************************/
-#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */
+#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */
#define ACPI_DEBUGGER_COMMAND_PROMPT '-'
#define ACPI_DEBUGGER_EXECUTE_PROMPT '%'
-
-#endif /* _ACCONFIG_H */
-
+#endif /* _ACCONFIG_H */
diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h
index 8ba372b0f245..70ce3b4d006e 100644
--- a/include/acpi/acdebug.h
+++ b/include/acpi/acdebug.h
@@ -44,22 +44,17 @@
#ifndef __ACDEBUG_H__
#define __ACDEBUG_H__
-
#define ACPI_DEBUG_BUFFER_SIZE 4196
-struct command_info
-{
- char *name; /* Command Name */
- u8 min_args; /* Minimum arguments required */
+struct command_info {
+ char *name; /* Command Name */
+ u8 min_args; /* Minimum arguments required */
};
-
-struct argument_info
-{
- char *name; /* Argument Name */
+struct argument_info {
+ char *name; /* Argument Name */
};
-
#define PARAM_LIST(pl) pl
#define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose)
#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\
@@ -68,275 +63,155 @@ struct argument_info
#define EX_NO_SINGLE_STEP 1
#define EX_SINGLE_STEP 2
-
/*
* dbxface - external debugger interfaces
*/
-acpi_status
-acpi_db_initialize (
- void);
+acpi_status acpi_db_initialize(void);
-void
-acpi_db_terminate (
- void);
+void acpi_db_terminate(void);
acpi_status
-acpi_db_single_step (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 op_type);
-
+acpi_db_single_step(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op, u32 op_type);
/*
* dbcmds - debug commands and output routines
*/
-acpi_status
-acpi_db_disassemble_method (
- char *name);
+acpi_status acpi_db_disassemble_method(char *name);
-void
-acpi_db_display_table_info (
- char *table_arg);
+void acpi_db_display_table_info(char *table_arg);
-void
-acpi_db_unload_acpi_table (
- char *table_arg,
- char *instance_arg);
+void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg);
void
-acpi_db_set_method_breakpoint (
- char *location,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+acpi_db_set_method_breakpoint(char *location,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
-void
-acpi_db_set_method_call_breakpoint (
- union acpi_parse_object *op);
+void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
-void
-acpi_db_disassemble_aml (
- char *statements,
- union acpi_parse_object *op);
+void acpi_db_get_bus_info(void);
-void
-acpi_db_dump_namespace (
- char *start_arg,
- char *depth_arg);
+void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
-void
-acpi_db_dump_namespace_by_owner (
- char *owner_arg,
- char *depth_arg);
+void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
-void
-acpi_db_send_notify (
- char *name,
- u32 value);
+void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
-void
-acpi_db_set_method_data (
- char *type_arg,
- char *index_arg,
- char *value_arg);
+void acpi_db_send_notify(char *name, u32 value);
-acpi_status
-acpi_db_display_objects (
- char *obj_type_arg,
- char *display_count_arg);
+void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
acpi_status
-acpi_db_find_name_in_namespace (
- char *name_arg);
+acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
-void
-acpi_db_set_scope (
- char *name);
+acpi_status acpi_db_find_name_in_namespace(char *name_arg);
-acpi_status
-acpi_db_sleep (
- char *object_arg);
+void acpi_db_set_scope(char *name);
-void
-acpi_db_find_references (
- char *object_arg);
+acpi_status acpi_db_sleep(char *object_arg);
-void
-acpi_db_display_locks (
- void);
+void acpi_db_find_references(char *object_arg);
-void
-acpi_db_display_resources (
- char *object_arg);
+void acpi_db_display_locks(void);
-void
-acpi_db_display_gpes (
- void);
+void acpi_db_display_resources(char *object_arg);
-void
-acpi_db_check_integrity (
- void);
+void acpi_db_display_gpes(void);
-void
-acpi_db_generate_gpe (
- char *gpe_arg,
- char *block_arg);
+void acpi_db_check_integrity(void);
+void acpi_db_generate_gpe(char *gpe_arg, char *block_arg);
/*
* dbdisply - debug display commands
*/
-void
-acpi_db_display_method_info (
- union acpi_parse_object *op);
+void acpi_db_display_method_info(union acpi_parse_object *op);
-void
-acpi_db_decode_and_display_object (
- char *target,
- char *output_type);
+void acpi_db_decode_and_display_object(char *target, char *output_type);
void
-acpi_db_display_result_object (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+acpi_db_display_result_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
-acpi_status
-acpi_db_display_all_methods (
- char *display_count_arg);
+acpi_status acpi_db_display_all_methods(char *display_count_arg);
-void
-acpi_db_display_arguments (
- void);
+void acpi_db_display_arguments(void);
-void
-acpi_db_display_locals (
- void);
+void acpi_db_display_locals(void);
-void
-acpi_db_display_results (
- void);
+void acpi_db_display_results(void);
-void
-acpi_db_display_calling_tree (
- void);
+void acpi_db_display_calling_tree(void);
-void
-acpi_db_display_object_type (
- char *object_arg);
+void acpi_db_display_object_type(char *object_arg);
void
-acpi_db_display_argument_object (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
/*
* dbexec - debugger control method execution
*/
-void
-acpi_db_execute (
- char *name,
- char **args,
- u32 flags);
+void acpi_db_execute(char *name, char **args, u32 flags);
void
-acpi_db_create_execution_threads (
- char *num_threads_arg,
- char *num_loops_arg,
- char *method_name_arg);
-
+acpi_db_create_execution_threads(char *num_threads_arg,
+ char *num_loops_arg, char *method_name_arg);
/*
* dbfileio - Debugger file I/O commands
*/
acpi_object_type
-acpi_db_match_argument (
- char *user_argument,
- struct argument_info *arguments);
+acpi_db_match_argument(char *user_argument, struct argument_info *arguments);
-void
-acpi_db_close_debug_file (
- void);
+void acpi_db_close_debug_file(void);
-void
-acpi_db_open_debug_file (
- char *name);
+void acpi_db_open_debug_file(char *name);
-acpi_status
-acpi_db_load_acpi_table (
- char *filename);
+acpi_status acpi_db_load_acpi_table(char *filename);
acpi_status
-acpi_db_get_table_from_file (
- char *filename,
- struct acpi_table_header **table);
+acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table);
acpi_status
-acpi_db_read_table_from_file (
- char *filename,
- struct acpi_table_header **table);
-
+acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table);
/*
* dbhistry - debugger HISTORY command
*/
-void
-acpi_db_add_to_history (
- char *command_line);
+void acpi_db_add_to_history(char *command_line);
-void
-acpi_db_display_history (
- void);
-
-char *
-acpi_db_get_from_history (
- char *command_num_arg);
+void acpi_db_display_history(void);
+char *acpi_db_get_from_history(char *command_num_arg);
/*
* dbinput - user front-end to the AML debugger
*/
acpi_status
-acpi_db_command_dispatch (
- char *input_buffer,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
-void ACPI_SYSTEM_XFACE
-acpi_db_execute_thread (
- void *context);
+acpi_db_command_dispatch(char *input_buffer,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
/*
* dbstats - Generation and display of ACPI table statistics
*/
-void
-acpi_db_generate_statistics (
- union acpi_parse_object *root,
- u8 is_method);
-
-acpi_status
-acpi_db_display_statistics (
- char *type_arg);
+void acpi_db_generate_statistics(union acpi_parse_object *root, u8 is_method);
+acpi_status acpi_db_display_statistics(char *type_arg);
/*
* dbutils - AML debugger utilities
*/
-void
-acpi_db_set_output_destination (
- u32 where);
+void acpi_db_set_output_destination(u32 where);
-void
-acpi_db_dump_object (
- union acpi_object *obj_desc,
- u32 level);
+void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level);
-void
-acpi_db_prep_namestring (
- char *name);
+void acpi_db_prep_namestring(char *name);
-struct acpi_namespace_node *
-acpi_db_local_ns_lookup (
- char *name);
+struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name);
-#endif /* __ACDEBUG_H__ */
+#endif /* __ACDEBUG_H__ */
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index dbfa877121ba..3d96dcb1bb4b 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -46,327 +46,219 @@
#include "amlresrc.h"
-
#define BLOCK_NONE 0
#define BLOCK_PAREN 1
#define BLOCK_BRACE 2
#define BLOCK_COMMA_LIST 4
-struct acpi_external_list
-{
- char *path;
- struct acpi_external_list *next;
+struct acpi_external_list {
+ char *path;
+ struct acpi_external_list *next;
};
-extern struct acpi_external_list *acpi_gbl_external_list;
-extern const char *acpi_gbl_io_decode[2];
-extern const char *acpi_gbl_word_decode[4];
-extern const char *acpi_gbl_consume_decode[2];
-extern const char *acpi_gbl_min_decode[2];
-extern const char *acpi_gbl_max_decode[2];
-extern const char *acpi_gbl_DECdecode[2];
-extern const char *acpi_gbl_RNGdecode[4];
-extern const char *acpi_gbl_MEMdecode[4];
-extern const char *acpi_gbl_RWdecode[2];
-extern const char *acpi_gbl_irq_decode[2];
-extern const char *acpi_gbl_HEdecode[2];
-extern const char *acpi_gbl_LLdecode[2];
-extern const char *acpi_gbl_SHRdecode[2];
-extern const char *acpi_gbl_TYPdecode[4];
-extern const char *acpi_gbl_BMdecode[2];
-extern const char *acpi_gbl_SIZdecode[4];
-extern const char *acpi_gbl_TTPdecode[2];
-extern const char *acpi_gbl_MTPdecode[4];
-extern const char *acpi_gbl_TRSdecode[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];
-
-
-struct acpi_op_walk_info
-{
- u32 level;
- u32 bit_offset;
+extern struct acpi_external_list *acpi_gbl_external_list;
+extern const char *acpi_gbl_io_decode[2];
+extern const char *acpi_gbl_word_decode[4];
+extern const char *acpi_gbl_consume_decode[2];
+extern const char *acpi_gbl_min_decode[2];
+extern const char *acpi_gbl_max_decode[2];
+extern const char *acpi_gbl_DECdecode[2];
+extern const char *acpi_gbl_RNGdecode[4];
+extern const char *acpi_gbl_MEMdecode[4];
+extern const char *acpi_gbl_RWdecode[2];
+extern const char *acpi_gbl_irq_decode[2];
+extern const char *acpi_gbl_HEdecode[2];
+extern const char *acpi_gbl_LLdecode[2];
+extern const char *acpi_gbl_SHRdecode[2];
+extern const char *acpi_gbl_TYPdecode[4];
+extern const char *acpi_gbl_BMdecode[2];
+extern const char *acpi_gbl_SIZdecode[4];
+extern const char *acpi_gbl_TTPdecode[2];
+extern const char *acpi_gbl_MTPdecode[4];
+extern const char *acpi_gbl_TRSdecode[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];
+
+struct acpi_op_walk_info {
+ u32 level;
+ u32 bit_offset;
+ struct acpi_walk_state *walk_state;
};
typedef
-acpi_status (*asl_walk_callback) (
- union acpi_parse_object *op,
- u32 level,
- void *context);
-
+acpi_status(*asl_walk_callback) (union acpi_parse_object * op,
+ u32 level, void *context);
/*
* dmwalk
*/
void
-acpi_dm_disassemble (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *origin,
- u32 num_opcodes);
-
+acpi_dm_disassemble(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *origin, u32 num_opcodes);
/*
* dmopcode
*/
void
-acpi_dm_disassemble_one_op (
- struct acpi_walk_state *walk_state,
- struct acpi_op_walk_info *info,
- union acpi_parse_object *op);
+acpi_dm_disassemble_one_op(struct acpi_walk_state *walk_state,
+ struct acpi_op_walk_info *info,
+ union acpi_parse_object *op);
-void
-acpi_dm_decode_internal_object (
- union acpi_operand_object *obj_desc);
+void acpi_dm_decode_internal_object(union acpi_operand_object *obj_desc);
-u32
-acpi_dm_list_type (
- union acpi_parse_object *op);
+u32 acpi_dm_list_type(union acpi_parse_object *op);
-void
-acpi_dm_method_flags (
- union acpi_parse_object *op);
-
-void
-acpi_dm_field_flags (
- union acpi_parse_object *op);
+void acpi_dm_method_flags(union acpi_parse_object *op);
-void
-acpi_dm_address_space (
- u8 space_id);
+void acpi_dm_field_flags(union acpi_parse_object *op);
-void
-acpi_dm_region_flags (
- union acpi_parse_object *op);
+void acpi_dm_address_space(u8 space_id);
-void
-acpi_dm_match_op (
- union acpi_parse_object *op);
+void acpi_dm_region_flags(union acpi_parse_object *op);
-u8
-acpi_dm_comma_if_list_member (
- union acpi_parse_object *op);
+void acpi_dm_match_op(union acpi_parse_object *op);
-void
-acpi_dm_comma_if_field_member (
- union acpi_parse_object *op);
+u8 acpi_dm_comma_if_list_member(union acpi_parse_object *op);
+void acpi_dm_comma_if_field_member(union acpi_parse_object *op);
/*
* dmnames
*/
-u32
-acpi_dm_dump_name (
- char *name);
+u32 acpi_dm_dump_name(char *name);
acpi_status
-acpi_ps_display_object_pathname (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
-void
-acpi_dm_namestring (
- char *name);
+acpi_ps_display_object_pathname(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+void acpi_dm_namestring(char *name);
/*
* dmobject
*/
void
-acpi_dm_display_internal_object (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+acpi_dm_display_internal_object(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
-void
-acpi_dm_display_arguments (
- struct acpi_walk_state *walk_state);
+void acpi_dm_display_arguments(struct acpi_walk_state *walk_state);
-void
-acpi_dm_display_locals (
- struct acpi_walk_state *walk_state);
+void acpi_dm_display_locals(struct acpi_walk_state *walk_state);
void
-acpi_dm_dump_method_info (
- acpi_status status,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
+acpi_dm_dump_method_info(acpi_status status,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
/*
* dmbuffer
*/
-void
-acpi_dm_disasm_byte_list (
- u32 level,
- u8 *byte_data,
- u32 byte_count);
+void acpi_dm_disasm_byte_list(u32 level, u8 * byte_data, u32 byte_count);
void
-acpi_dm_byte_list (
- struct acpi_op_walk_info *info,
- union acpi_parse_object *op);
+acpi_dm_byte_list(struct acpi_op_walk_info *info, union acpi_parse_object *op);
-void
-acpi_is_eisa_id (
- union acpi_parse_object *op);
+void acpi_dm_is_eisa_id(union acpi_parse_object *op);
-void
-acpi_dm_eisa_id (
- u32 encoded_id);
-
-u8
-acpi_dm_is_unicode_buffer (
- union acpi_parse_object *op);
+void acpi_dm_eisa_id(u32 encoded_id);
-u8
-acpi_dm_is_string_buffer (
- union acpi_parse_object *op);
+u8 acpi_dm_is_unicode_buffer(union acpi_parse_object *op);
+u8 acpi_dm_is_string_buffer(union acpi_parse_object *op);
/*
* dmresrc
*/
void
-acpi_dm_resource_descriptor (
- struct acpi_op_walk_info *info,
- u8 *byte_data,
- u32 byte_count);
+acpi_dm_resource_descriptor(struct acpi_op_walk_info *info,
+ u8 * byte_data, u32 byte_count);
-u8
-acpi_dm_is_resource_descriptor (
- union acpi_parse_object *op);
+u8 acpi_dm_is_resource_descriptor(union acpi_parse_object *op);
-void
-acpi_dm_indent (
- u32 level);
+void acpi_dm_indent(u32 level);
-void
-acpi_dm_bit_list (
- u16 mask);
-
-void
-acpi_dm_decode_attribute (
- u8 attribute);
+void acpi_dm_bit_list(u16 mask);
+void acpi_dm_decode_attribute(u8 attribute);
/*
* dmresrcl
*/
void
-acpi_dm_word_descriptor (
- struct asl_word_address_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_word_descriptor(struct asl_word_address_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_dword_descriptor (
- struct asl_dword_address_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_dword_descriptor(struct asl_dword_address_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_extended_descriptor (
- struct asl_extended_address_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_extended_descriptor(struct asl_extended_address_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_qword_descriptor (
- struct asl_qword_address_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_qword_descriptor(struct asl_qword_address_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_memory24_descriptor (
- struct asl_memory_24_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_memory24_descriptor(struct asl_memory_24_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_memory32_descriptor (
- struct asl_memory_32_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_memory32_descriptor(struct asl_memory_32_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_fixed_mem32_descriptor (
- struct asl_fixed_memory_32_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_fixed_mem32_descriptor(struct asl_fixed_memory_32_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_generic_register_descriptor (
- struct asl_general_register_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_generic_register_descriptor(struct asl_general_register_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_interrupt_descriptor (
- struct asl_extended_xrupt_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_interrupt_descriptor(struct asl_extended_xrupt_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_vendor_large_descriptor (
- struct asl_large_vendor_desc *resource,
- u32 length,
- u32 level);
-
+acpi_dm_vendor_large_descriptor(struct asl_large_vendor_desc *resource,
+ u32 length, u32 level);
/*
* dmresrcs
*/
void
-acpi_dm_irq_descriptor (
- struct asl_irq_format_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_irq_descriptor(struct asl_irq_format_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_dma_descriptor (
- struct asl_dma_format_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_dma_descriptor(struct asl_dma_format_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_io_descriptor (
- struct asl_io_port_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_io_descriptor(struct asl_io_port_desc *resource, u32 length, u32 level);
void
-acpi_dm_fixed_io_descriptor (
- struct asl_fixed_io_port_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_fixed_io_descriptor(struct asl_fixed_io_port_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_start_dependent_descriptor (
- struct asl_start_dependent_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_start_dependent_descriptor(struct asl_start_dependent_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_end_dependent_descriptor (
- struct asl_start_dependent_desc *resource,
- u32 length,
- u32 level);
+acpi_dm_end_dependent_descriptor(struct asl_start_dependent_desc *resource,
+ u32 length, u32 level);
void
-acpi_dm_vendor_small_descriptor (
- struct asl_small_vendor_desc *resource,
- u32 length,
- u32 level);
-
+acpi_dm_vendor_small_descriptor(struct asl_small_vendor_desc *resource,
+ u32 length, u32 level);
/*
* dmutils
*/
-void
-acpi_dm_add_to_external_list (
- char *path);
+void acpi_dm_add_to_external_list(char *path);
-#endif /* __ACDISASM_H__ */
+#endif /* __ACDISASM_H__ */
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index 8f5f2f71b1de..065f24a77cfc 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -41,419 +41,304 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#ifndef _ACDISPAT_H_
#define _ACDISPAT_H_
-
#define NAMEOF_LOCAL_NTE "__L0"
#define NAMEOF_ARG_NTE "__A0"
-
/*
* dsopcode - support for late evaluation
*/
acpi_status
-acpi_ds_get_buffer_field_arguments (
- union acpi_operand_object *obj_desc);
-
-acpi_status
-acpi_ds_get_region_arguments (
- union acpi_operand_object *rgn_desc);
+acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ds_get_buffer_arguments (
- union acpi_operand_object *obj_desc);
+acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *rgn_desc);
-acpi_status
-acpi_ds_get_package_arguments (
- union acpi_operand_object *obj_desc);
+acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ds_eval_buffer_field_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc);
acpi_status
-acpi_ds_eval_region_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
acpi_status
-acpi_ds_eval_data_object_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object *obj_desc);
+acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
acpi_status
-acpi_ds_initialize_region (
- acpi_handle obj_handle);
+acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object *obj_desc);
+acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);
/*
* dsctrl - Parser/Interpreter interface, control stack routines
*/
acpi_status
-acpi_ds_exec_begin_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
acpi_status
-acpi_ds_exec_end_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
+acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
/*
* dsexec - Parser/Interpreter interface, method execution callbacks
*/
acpi_status
-acpi_ds_get_predicate_value (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *result_obj);
-
-acpi_status
-acpi_ds_exec_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op);
+acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *result_obj);
acpi_status
-acpi_ds_exec_end_op (
- struct acpi_walk_state *state);
+acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op);
+acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *state);
/*
* dsfield - Parser/Interpreter interface for AML fields
*/
acpi_status
-acpi_ds_create_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state);
+acpi_ds_create_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_create_bank_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state);
+acpi_ds_create_bank_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_create_index_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state);
+acpi_ds_create_index_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_create_buffer_field (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state);
+acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_init_field_objects (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state);
-
+acpi_ds_init_field_objects(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state);
/*
* dsload - Parser/Interpreter interface, namespace load callbacks
*/
acpi_status
-acpi_ds_load1_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op);
+acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op);
-acpi_status
-acpi_ds_load1_end_op (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_load2_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op);
+acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op);
-acpi_status
-acpi_ds_load2_end_op (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_init_callbacks (
- struct acpi_walk_state *walk_state,
- u32 pass_number);
-
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
/*
* dsmthdat - method data (locals/args)
*/
acpi_status
-acpi_ds_store_object_to_local (
- u16 opcode,
- u32 index,
- union acpi_operand_object *src_desc,
- struct acpi_walk_state *walk_state);
+acpi_ds_store_object_to_local(u16 opcode,
+ u32 index,
+ union acpi_operand_object *src_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_method_data_get_entry (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- union acpi_operand_object ***node);
+acpi_ds_method_data_get_entry(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object ***node);
-void
-acpi_ds_method_data_delete_all (
- struct acpi_walk_state *walk_state);
+void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state);
-u8
-acpi_ds_is_method_value (
- union acpi_operand_object *obj_desc);
+u8 acpi_ds_is_method_value(union acpi_operand_object *obj_desc);
acpi_status
-acpi_ds_method_data_get_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **dest_desc);
+acpi_ds_method_data_get_value(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object **dest_desc);
acpi_status
-acpi_ds_method_data_init_args (
- union acpi_operand_object **params,
- u32 max_param_count,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_init_args(union acpi_operand_object **params,
+ u32 max_param_count,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_method_data_get_node (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **node);
-
-void
-acpi_ds_method_data_init (
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_get_node(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **node);
+void acpi_ds_method_data_init(struct acpi_walk_state *walk_state);
/*
* dsmethod - Parser/Interpreter interface - control method parsing
*/
-acpi_status
-acpi_ds_parse_method (
- acpi_handle obj_handle);
+acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node);
acpi_status
-acpi_ds_call_control_method (
- struct acpi_thread_state *thread,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+acpi_ds_call_control_method(struct acpi_thread_state *thread,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
acpi_status
-acpi_ds_restart_control_method (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *return_desc);
+acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *return_desc);
-acpi_status
-acpi_ds_terminate_control_method (
- struct acpi_walk_state *walk_state);
+void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_begin_method_execution (
- struct acpi_namespace_node *method_node,
- union acpi_operand_object *obj_desc,
- struct acpi_namespace_node *calling_method_node);
-
+acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
+ union acpi_operand_object *obj_desc,
+ struct acpi_namespace_node *calling_method_node);
/*
* dsinit
*/
acpi_status
-acpi_ds_initialize_objects (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *start_node);
-
+acpi_ds_initialize_objects(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *start_node);
/*
* dsobject - Parser/Interpreter interface - object initialization and conversion
*/
acpi_status
-acpi_ds_build_internal_buffer_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 buffer_length,
- union acpi_operand_object **obj_desc_ptr);
+acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 buffer_length,
+ union acpi_operand_object **obj_desc_ptr);
acpi_status
-acpi_ds_build_internal_package_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 package_length,
- union acpi_operand_object **obj_desc);
+acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 package_length,
+ union acpi_operand_object **obj_desc);
acpi_status
-acpi_ds_init_object_from_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u16 opcode,
- union acpi_operand_object **obj_desc);
+acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u16 opcode, union acpi_operand_object **obj_desc);
acpi_status
-acpi_ds_create_node (
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- union acpi_parse_object *op);
-
+acpi_ds_create_node(struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ union acpi_parse_object *op);
/*
* dsutils - Parser/Interpreter interface utility routines
*/
-void
-acpi_ds_clear_implicit_return (
- struct acpi_walk_state *walk_state);
+void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state);
u8
-acpi_ds_do_implicit_return (
- union acpi_operand_object *return_desc,
- struct acpi_walk_state *walk_state,
- u8 add_reference);
+acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference);
u8
-acpi_ds_is_result_used (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state);
+acpi_ds_is_result_used(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state);
void
-acpi_ds_delete_result_if_not_used (
- union acpi_parse_object *op,
- union acpi_operand_object *result_obj,
- struct acpi_walk_state *walk_state);
+acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
+ union acpi_operand_object *result_obj,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_create_operand (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg,
- u32 args_remaining);
+acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg, u32 args_remaining);
acpi_status
-acpi_ds_create_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *first_arg);
+acpi_ds_create_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *first_arg);
-acpi_status
-acpi_ds_resolve_operands (
- struct acpi_walk_state *walk_state);
-
-void
-acpi_ds_clear_operands (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state);
+void acpi_ds_clear_operands(struct acpi_walk_state *walk_state);
/*
* dswscope - Scope Stack manipulation
*/
acpi_status
-acpi_ds_scope_stack_push (
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_walk_state *walk_state);
+acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ds_scope_stack_pop (
- struct acpi_walk_state *walk_state);
-
-void
-acpi_ds_scope_stack_clear (
- struct acpi_walk_state *walk_state);
-
+void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state);
/*
* dswstate - parser WALK_STATE management routines
*/
acpi_status
-acpi_ds_obj_stack_push (
- void *object,
- struct acpi_walk_state *walk_state);
+acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_obj_stack_pop (
- u32 pop_count,
- struct acpi_walk_state *walk_state);
+acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
-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,
- struct acpi_thread_state *thread);
+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,
+ struct acpi_thread_state
+ *thread);
acpi_status
-acpi_ds_init_aml_walk (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- struct acpi_namespace_node *method_node,
- u8 *aml_start,
- u32 aml_length,
- struct acpi_parameter_info *info,
- u32 pass_number);
+acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *method_node,
+ u8 * aml_start,
+ u32 aml_length,
+ struct acpi_parameter_info *info, u8 pass_number);
acpi_status
-acpi_ds_obj_stack_pop_and_delete (
- u32 pop_count,
- struct acpi_walk_state *walk_state);
+acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
+ struct acpi_walk_state *walk_state);
-void
-acpi_ds_delete_walk_state (
- struct acpi_walk_state *walk_state);
+void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state);
-struct acpi_walk_state *
-acpi_ds_pop_walk_state (
- struct acpi_thread_state *thread);
+struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state
+ *thread);
void
-acpi_ds_push_walk_state (
- struct acpi_walk_state *walk_state,
- struct acpi_thread_state *thread);
+acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
+ struct acpi_thread_state *thread);
-acpi_status
-acpi_ds_result_stack_pop (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ds_result_stack_push (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ds_result_stack_clear (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_result_stack_clear(struct acpi_walk_state *walk_state);
-struct acpi_walk_state *
-acpi_ds_get_current_walk_state (
- struct acpi_thread_state *thread);
+struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
+ *thread);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_ds_result_remove (
- union acpi_operand_object **object,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_result_remove(union acpi_operand_object **object,
+ u32 index, struct acpi_walk_state *walk_state);
#endif
acpi_status
-acpi_ds_result_pop (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state);
+acpi_ds_result_pop(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_result_push (
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state);
+acpi_ds_result_push(union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_result_pop_from_bottom (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state);
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-void
-acpi_ds_delete_walk_state_cache (
- void);
-#endif
+acpi_ds_result_pop_from_bottom(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state);
-#endif /* _ACDISPAT_H_ */
+#endif /* _ACDISPAT_H_ */
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index 61a27c8c5079..bfa54600ecd9 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -44,250 +44,167 @@
#ifndef __ACEVENTS_H__
#define __ACEVENTS_H__
-
/*
* evevent
*/
-acpi_status
-acpi_ev_initialize_events (
- void);
+acpi_status acpi_ev_initialize_events(void);
-acpi_status
-acpi_ev_install_xrupt_handlers (
- void);
-
-u32
-acpi_ev_fixed_event_detect (
- void);
+acpi_status acpi_ev_install_xrupt_handlers(void);
+u32 acpi_ev_fixed_event_detect(void);
/*
* evmisc
*/
-u8
-acpi_ev_is_notify_object (
- struct acpi_namespace_node *node);
+u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node);
-acpi_status
-acpi_ev_acquire_global_lock(
- u16 timeout);
+acpi_status acpi_ev_acquire_global_lock(u16 timeout);
-acpi_status
-acpi_ev_release_global_lock(
- void);
+acpi_status acpi_ev_release_global_lock(void);
-acpi_status
-acpi_ev_init_global_lock_handler (
- void);
+acpi_status acpi_ev_init_global_lock_handler(void);
-u32
-acpi_ev_get_gpe_number_index (
- u32 gpe_number);
+u32 acpi_ev_get_gpe_number_index(u32 gpe_number);
acpi_status
-acpi_ev_queue_notify_request (
- struct acpi_namespace_node *node,
- u32 notify_value);
-
+acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
+ u32 notify_value);
/*
* evgpe - GPE handling and dispatch
*/
acpi_status
-acpi_ev_update_gpe_enable_masks (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type);
+acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
+ u8 type);
acpi_status
-acpi_ev_enable_gpe (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 write_to_hardware);
+acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
+ u8 write_to_hardware);
-acpi_status
-acpi_ev_disable_gpe (
- struct acpi_gpe_event_info *gpe_event_info);
-
-struct acpi_gpe_event_info *
-acpi_ev_get_gpe_event_info (
- acpi_handle gpe_device,
- u32 gpe_number);
+acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
+ u32 gpe_number);
/*
* evgpeblk
*/
-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,
- u32 flags);
+u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status
-acpi_ev_delete_gpe_handlers (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback);
acpi_status
-acpi_ev_create_gpe_block (
- struct acpi_namespace_node *gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u8 gpe_block_base_number,
- u32 interrupt_level,
- struct acpi_gpe_block_info **return_gpe_block);
+acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
acpi_status
-acpi_ev_delete_gpe_block (
- struct acpi_gpe_block_info *gpe_block);
+acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u8 gpe_block_base_number,
+ u32 interrupt_number,
+ struct acpi_gpe_block_info **return_gpe_block);
-u32
-acpi_ev_gpe_dispatch (
- struct acpi_gpe_event_info *gpe_event_info,
- u32 gpe_number);
+acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
u32
-acpi_ev_gpe_detect (
- struct acpi_gpe_xrupt_info *gpe_xrupt_list);
+acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
+ u32 gpe_number);
-acpi_status
-acpi_ev_set_gpe_type (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type);
+u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
-acpi_ev_check_for_wake_only_gpe (
- struct acpi_gpe_event_info *gpe_event_info);
+acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type);
acpi_status
-acpi_ev_gpe_initialize (
- void);
+acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status acpi_ev_gpe_initialize(void);
/*
* evregion - Address Space handling
*/
-acpi_status
-acpi_ev_install_region_handlers (
- void);
+acpi_status acpi_ev_install_region_handlers(void);
-acpi_status
-acpi_ev_initialize_op_regions (
- void);
+acpi_status acpi_ev_initialize_op_regions(void);
acpi_status
-acpi_ev_address_space_dispatch (
- union acpi_operand_object *region_obj,
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- void *value);
+acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ u32 function,
+ acpi_physical_address address,
+ u32 bit_width, void *value);
acpi_status
-acpi_ev_attach_region (
- union acpi_operand_object *handler_obj,
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked);
+acpi_ev_attach_region(union acpi_operand_object *handler_obj,
+ union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked);
void
-acpi_ev_detach_region (
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked);
+acpi_ev_detach_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked);
acpi_status
-acpi_ev_install_space_handler (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context);
+acpi_ev_install_space_handler(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context);
acpi_status
-acpi_ev_execute_reg_methods (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id);
+acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id);
acpi_status
-acpi_ev_execute_reg_method (
- union acpi_operand_object *region_obj,
- u32 function);
-
+acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function);
/*
* evregini - Region initialization and setup
*/
acpi_status
-acpi_ev_system_memory_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_system_memory_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context,
+ void **region_context);
acpi_status
-acpi_ev_io_space_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_io_space_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context);
acpi_status
-acpi_ev_pci_config_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_pci_config_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context);
acpi_status
-acpi_ev_cmos_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_cmos_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context);
acpi_status
-acpi_ev_pci_bar_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_pci_bar_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context);
acpi_status
-acpi_ev_default_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_ev_default_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context);
acpi_status
-acpi_ev_initialize_region (
- union acpi_operand_object *region_obj,
- u8 acpi_ns_locked);
-
+acpi_ev_initialize_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_locked);
/*
* evsci - SCI (System Control Interrupt) handling/dispatch
*/
-u32 ACPI_SYSTEM_XFACE
-acpi_ev_gpe_xrupt_handler (
- void *context);
-
-u32
-acpi_ev_install_sci_handler (
- void);
+u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
-acpi_status
-acpi_ev_remove_sci_handler (
- void);
+u32 acpi_ev_install_sci_handler(void);
-u32
-acpi_ev_initialize_sCI (
- u32 program_sCI);
+acpi_status acpi_ev_remove_sci_handler(void);
-void
-acpi_ev_terminate (
- void);
+u32 acpi_ev_initialize_sCI(u32 program_sCI);
+void acpi_ev_terminate(void);
-#endif /* __ACEVENTS_H__ */
+#endif /* __ACEVENTS_H__ */
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 60d737b2d70f..4f005eb65928 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -44,7 +44,6 @@
#ifndef __ACEXCEP_H__
#define __ACEXCEP_H__
-
/*
* Exceptions returned by external ACPI interfaces
*/
@@ -55,11 +54,9 @@
#define AE_CODE_CONTROL 0x4000
#define AE_CODE_MASK 0xF000
-
#define ACPI_SUCCESS(a) (!(a))
#define ACPI_FAILURE(a) (a)
-
#define AE_OK (acpi_status) 0x0000
/*
@@ -95,9 +92,9 @@
#define AE_ABORT_METHOD (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
#define AE_SAME_HANDLER (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
#define AE_WAKE_ONLY_GPE (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
+#define AE_OWNER_ID_LIMIT (acpi_status) (0x001F | AE_CODE_ENVIRONMENTAL)
-#define AE_CODE_ENV_MAX 0x001E
-
+#define AE_CODE_ENV_MAX 0x001F
/*
* Programmer exceptions
@@ -114,7 +111,6 @@
#define AE_CODE_PGM_MAX 0x0009
-
/*
* Acpi table exceptions
*/
@@ -127,7 +123,6 @@
#define AE_CODE_TBL_MAX 0x0006
-
/*
* AML exceptions. These are caused by problems with
* the actual AML byte stream
@@ -168,7 +163,6 @@
#define AE_CODE_AML_MAX 0x0021
-
/*
* Internal exceptions used for control
*/
@@ -186,16 +180,13 @@
#define AE_CODE_CTRL_MAX 0x000B
-
#ifdef DEFINE_ACPI_GLOBALS
-
/*
* String versions of the exception codes above
* These strings must match the corresponding defines exactly
*/
-char const *acpi_gbl_exception_names_env[] =
-{
+char const *acpi_gbl_exception_names_env[] = {
"AE_OK",
"AE_ERROR",
"AE_NO_ACPI_TABLES",
@@ -226,11 +217,11 @@ char const *acpi_gbl_exception_names_env[] =
"AE_LOGICAL_ADDRESS",
"AE_ABORT_METHOD",
"AE_SAME_HANDLER",
- "AE_WAKE_ONLY_GPE"
+ "AE_WAKE_ONLY_GPE",
+ "AE_OWNER_ID_LIMIT"
};
-char const *acpi_gbl_exception_names_pgm[] =
-{
+char const *acpi_gbl_exception_names_pgm[] = {
"AE_BAD_PARAMETER",
"AE_BAD_CHARACTER",
"AE_BAD_PATHNAME",
@@ -242,8 +233,7 @@ char const *acpi_gbl_exception_names_pgm[] =
"AE_BAD_DECIMAL_CONSTANT"
};
-char const *acpi_gbl_exception_names_tbl[] =
-{
+char const *acpi_gbl_exception_names_tbl[] = {
"AE_BAD_SIGNATURE",
"AE_BAD_HEADER",
"AE_BAD_CHECKSUM",
@@ -252,8 +242,7 @@ char const *acpi_gbl_exception_names_tbl[] =
"AE_INVALID_TABLE_LENGTH"
};
-char const *acpi_gbl_exception_names_aml[] =
-{
+char const *acpi_gbl_exception_names_aml[] = {
"AE_AML_ERROR",
"AE_AML_PARSE",
"AE_AML_BAD_OPCODE",
@@ -289,8 +278,7 @@ char const *acpi_gbl_exception_names_aml[] =
"AE_AML_BAD_RESOURCE_LENGTH"
};
-char const *acpi_gbl_exception_names_ctrl[] =
-{
+char const *acpi_gbl_exception_names_ctrl[] = {
"AE_CTRL_RETURN_VALUE",
"AE_CTRL_PENDING",
"AE_CTRL_TERMINATE",
@@ -304,6 +292,6 @@ char const *acpi_gbl_exception_names_ctrl[] =
"AE_CTRL_SKIP"
};
-#endif /* ACPI GLOBALS */
+#endif /* ACPI GLOBALS */
-#endif /* __ACEXCEP_H__ */
+#endif /* __ACEXCEP_H__ */
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 4946696088c3..e9c2790139ec 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -44,7 +44,6 @@
#ifndef __ACGLOBAL_H__
#define __ACGLOBAL_H__
-
/*
* Ensure that the globals are actually defined and initialized only once.
*
@@ -63,9 +62,8 @@
* Keep local copies of these FADT-based registers. NOTE: These globals
* are first in this file for alignment reasons on 64-bit systems.
*/
-ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;
-ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
-
+ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;
+ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
/*****************************************************************************
*
@@ -75,13 +73,12 @@ ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
/* Runtime configuration of debug print levels */
-extern u32 acpi_dbg_level;
-extern u32 acpi_dbg_layer;
+extern u32 acpi_dbg_level;
+extern u32 acpi_dbg_layer;
/* Procedure nesting level for debug output */
-extern u32 acpi_gbl_nesting_level;
-
+extern u32 acpi_gbl_nesting_level;
/*****************************************************************************
*
@@ -98,7 +95,7 @@ extern u32 acpi_gbl_nesting_level;
* 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
*/
-ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE);
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
/*
* Automatically serialize ALL control methods? Default is FALSE, meaning
@@ -106,22 +103,21 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE)
* Only change this if the ASL code is poorly written and cannot handle
* reentrancy even though methods are marked "not_serialized".
*/
-ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE);
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
/*
* Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPI CA is fully compatible with other ACPI implementations.
* Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
*/
-ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE);
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
/*
* Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
* RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
* be enabled just before going to sleep.
*/
-ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
-
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
/*****************************************************************************
*
@@ -137,42 +133,46 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
* These tables are single-table only; meaning that there can be at most one
* of each in the system. Each global points to the actual table.
*/
-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 acpi_table_header *acpi_gbl_DSDT;
-ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS;
-ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS;
+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 acpi_table_header *acpi_gbl_DSDT;
+ACPI_EXTERN 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
* sufficient; Therefore, there isn't one!
*/
+/* The root table can be either an RSDT or an XSDT */
+
+ACPI_EXTERN u8 acpi_gbl_root_table_type;
+#define ACPI_TABLE_TYPE_RSDT 'R'
+#define ACPI_TABLE_TYPE_XSDT 'X'
/*
* Handle both ACPI 1.0 and ACPI 2.0 Integer widths:
* If we are executing a method that exists in a 32-bit ACPI table,
* use only the lower 32 bits of the (internal) 64-bit Integer.
*/
-ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
-ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
-ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
+ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
+ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
+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[NUM_ACPI_TABLE_TYPES];
+extern struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES];
/*
* 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[NUM_MUTEX];
/*****************************************************************************
*
@@ -180,41 +180,56 @@ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX];
*
****************************************************************************/
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+/* Lists for tracking memory allocations */
-ACPI_EXTERN struct acpi_memory_list acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS];
-ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify;
-ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify;
-ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler;
-ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
-ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
-ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore;
-
-ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count;
-ACPI_EXTERN u32 acpi_gbl_original_mode;
-ACPI_EXTERN u32 acpi_gbl_rsdp_original_location;
-ACPI_EXTERN u32 acpi_gbl_ns_lookup_count;
-ACPI_EXTERN u32 acpi_gbl_ps_find_count;
-ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save;
-ACPI_EXTERN u16 acpi_gbl_next_table_owner_id;
-ACPI_EXTERN u16 acpi_gbl_next_method_owner_id;
-ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
-ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
-ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
-ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
-ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
-ACPI_EXTERN u8 acpi_gbl_global_lock_present;
-ACPI_EXTERN u8 acpi_gbl_events_initialized;
-ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
-
-extern u8 acpi_gbl_shutdown;
-extern u32 acpi_gbl_startup_flags;
-extern const u8 acpi_gbl_decode_to8bit[8];
-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];
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
+#endif
+/* Object caches */
+
+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;
+ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache;
+
+/* Global handlers */
+
+ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify;
+ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify;
+ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler;
+ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
+ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
+ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore;
+
+/* Misc */
+
+ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count;
+ACPI_EXTERN u32 acpi_gbl_original_mode;
+ACPI_EXTERN u32 acpi_gbl_rsdp_original_location;
+ACPI_EXTERN u32 acpi_gbl_ns_lookup_count;
+ACPI_EXTERN u32 acpi_gbl_ps_find_count;
+ACPI_EXTERN u32 acpi_gbl_owner_id_mask;
+ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save;
+ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
+ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
+ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
+ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
+ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
+ACPI_EXTERN u8 acpi_gbl_global_lock_present;
+ACPI_EXTERN u8 acpi_gbl_events_initialized;
+ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
+
+extern u8 acpi_gbl_shutdown;
+extern u32 acpi_gbl_startup_flags;
+extern const u8 acpi_gbl_decode_to8bit[8];
+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];
/*****************************************************************************
*
@@ -230,36 +245,34 @@ extern const char *acpi_gbl_valid_osi_strings[ACPI_
#define NUM_PREDEFINED_NAMES 9
#endif
-ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
-ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
-ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
+ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
+ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
+ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
-extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES];
-extern const struct acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES];
+extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES];
+extern const struct acpi_predefined_names
+ acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES];
#ifdef ACPI_DEBUG_OUTPUT
-ACPI_EXTERN u32 acpi_gbl_current_node_count;
-ACPI_EXTERN u32 acpi_gbl_current_node_size;
-ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count;
-ACPI_EXTERN acpi_size acpi_gbl_entry_stack_pointer;
-ACPI_EXTERN acpi_size acpi_gbl_lowest_stack_pointer;
-ACPI_EXTERN u32 acpi_gbl_deepest_nesting;
+ACPI_EXTERN u32 acpi_gbl_current_node_count;
+ACPI_EXTERN u32 acpi_gbl_current_node_size;
+ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count;
+ACPI_EXTERN acpi_size acpi_gbl_entry_stack_pointer;
+ACPI_EXTERN acpi_size acpi_gbl_lowest_stack_pointer;
+ACPI_EXTERN u32 acpi_gbl_deepest_nesting;
#endif
-
/*****************************************************************************
*
* Interpreter globals
*
****************************************************************************/
-
-ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list;
+ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list;
/* Control method single step flag */
-ACPI_EXTERN u8 acpi_gbl_cm_single_step;
-
+ACPI_EXTERN u8 acpi_gbl_cm_single_step;
/*****************************************************************************
*
@@ -267,8 +280,7 @@ ACPI_EXTERN u8 acpi_gbl_cm_single_step;
*
****************************************************************************/
-ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root;
-
+ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root;
/*****************************************************************************
*
@@ -276,10 +288,10 @@ ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root;
*
****************************************************************************/
-extern struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG];
-ACPI_EXTERN u8 acpi_gbl_sleep_type_a;
-ACPI_EXTERN u8 acpi_gbl_sleep_type_b;
-
+extern struct acpi_bit_register_info
+ acpi_gbl_bit_register_info[ACPI_NUM_BITREG];
+ACPI_EXTERN u8 acpi_gbl_sleep_type_a;
+ACPI_EXTERN u8 acpi_gbl_sleep_type_b;
/*****************************************************************************
*
@@ -287,12 +299,14 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b;
*
****************************************************************************/
-extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS];
-ACPI_EXTERN struct acpi_fixed_event_handler acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS];
-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];
-ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
-
+extern struct acpi_fixed_event_info
+ acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS];
+ACPI_EXTERN struct acpi_fixed_event_handler
+ acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS];
+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];
+ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
/*****************************************************************************
*
@@ -300,58 +314,55 @@ ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
*
****************************************************************************/
-ACPI_EXTERN u8 acpi_gbl_db_output_flags;
+ACPI_EXTERN u8 acpi_gbl_db_output_flags;
#ifdef ACPI_DISASSEMBLER
-ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
-ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
+ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
+ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
#endif
-
#ifdef ACPI_DEBUGGER
-extern u8 acpi_gbl_method_executing;
-extern u8 acpi_gbl_abort_method;
-extern u8 acpi_gbl_db_terminate_threads;
-
-ACPI_EXTERN int optind;
-ACPI_EXTERN char *optarg;
-
-ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
-ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
-ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
-
-
-ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[80];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[80];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[40];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[40];
-ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
-ACPI_EXTERN char *acpi_gbl_db_buffer;
-ACPI_EXTERN char *acpi_gbl_db_filename;
-ACPI_EXTERN u32 acpi_gbl_db_debug_level;
-ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
-ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr;
-ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
+extern u8 acpi_gbl_method_executing;
+extern u8 acpi_gbl_abort_method;
+extern u8 acpi_gbl_db_terminate_threads;
+
+ACPI_EXTERN int optind;
+ACPI_EXTERN char *optarg;
+
+ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
+ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
+ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
+
+ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN char acpi_gbl_db_line_buf[80];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[80];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[40];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[40];
+ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
+ACPI_EXTERN char *acpi_gbl_db_buffer;
+ACPI_EXTERN char *acpi_gbl_db_filename;
+ACPI_EXTERN u32 acpi_gbl_db_debug_level;
+ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
+ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr;
+ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
/*
* Statistic globals
*/
-ACPI_EXTERN u16 acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX+1];
-ACPI_EXTERN u16 acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX+1];
-ACPI_EXTERN u16 acpi_gbl_obj_type_count_misc;
-ACPI_EXTERN u16 acpi_gbl_node_type_count_misc;
-ACPI_EXTERN u32 acpi_gbl_num_nodes;
-ACPI_EXTERN u32 acpi_gbl_num_objects;
-
+ACPI_EXTERN u16 acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1];
+ACPI_EXTERN u16 acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1];
+ACPI_EXTERN u16 acpi_gbl_obj_type_count_misc;
+ACPI_EXTERN u16 acpi_gbl_node_type_count_misc;
+ACPI_EXTERN u32 acpi_gbl_num_nodes;
+ACPI_EXTERN u32 acpi_gbl_num_objects;
-ACPI_EXTERN u32 acpi_gbl_size_of_parse_tree;
-ACPI_EXTERN u32 acpi_gbl_size_of_method_trees;
-ACPI_EXTERN u32 acpi_gbl_size_of_node_entries;
-ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects;
+ACPI_EXTERN u32 acpi_gbl_size_of_parse_tree;
+ACPI_EXTERN u32 acpi_gbl_size_of_method_trees;
+ACPI_EXTERN u32 acpi_gbl_size_of_node_entries;
+ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects;
-#endif /* ACPI_DEBUGGER */
+#endif /* ACPI_DEBUGGER */
-#endif /* __ACGLOBAL_H__ */
+#endif /* __ACGLOBAL_H__ */
diff --git a/include/acpi/achware.h b/include/acpi/achware.h
index 9d63641b8e7d..3644d7248e7e 100644
--- a/include/acpi/achware.h
+++ b/include/acpi/achware.h
@@ -44,7 +44,6 @@
#ifndef __ACHWARE_H__
#define __ACHWARE_H__
-
/* PM Timer ticks per second (HZ) */
#define PM_TIMER_FREQUENCY 3579545
@@ -57,126 +56,78 @@
#define ACPI_SST_SLEEPING 3
#define ACPI_SST_SLEEP_CONTEXT 4
-
/* Prototypes */
-
/*
* hwacpi - high level functions
*/
-acpi_status
-acpi_hw_initialize (
- void);
+acpi_status acpi_hw_initialize(void);
-acpi_status
-acpi_hw_set_mode (
- u32 mode);
-
-u32
-acpi_hw_get_mode (
- void);
+acpi_status acpi_hw_set_mode(u32 mode);
+u32 acpi_hw_get_mode(void);
/*
* hwregs - ACPI Register I/O
*/
-struct acpi_bit_register_info *
-acpi_hw_get_bit_register_info (
- u32 register_id);
-
-acpi_status
-acpi_hw_register_read (
- u8 use_lock,
- u32 register_id,
- u32 *return_value);
+struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
acpi_status
-acpi_hw_register_write (
- u8 use_lock,
- u32 register_id,
- u32 value);
+acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value);
-acpi_status
-acpi_hw_low_level_read (
- u32 width,
- u32 *value,
- struct acpi_generic_address *reg);
+acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value);
acpi_status
-acpi_hw_low_level_write (
- u32 width,
- u32 value,
- struct acpi_generic_address *reg);
+acpi_hw_low_level_read(u32 width,
+ u32 * value, struct acpi_generic_address *reg);
acpi_status
-acpi_hw_clear_acpi_status (
- u32 flags);
+acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address *reg);
+acpi_status acpi_hw_clear_acpi_status(u32 flags);
/*
* hwgpe - GPE support
*/
acpi_status
-acpi_hw_write_gpe_enable_reg (
- struct acpi_gpe_event_info *gpe_event_info);
+acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
-acpi_hw_disable_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
-acpi_status
-acpi_hw_clear_gpe (
- struct acpi_gpe_event_info *gpe_event_info);
+acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
-acpi_hw_clear_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_hw_get_gpe_status (
- struct acpi_gpe_event_info *gpe_event_info,
- acpi_event_status *event_status);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
+ acpi_event_status * event_status);
+#endif /* ACPI_FUTURE_USAGE */
-acpi_status
-acpi_hw_disable_all_gpes (
- u32 flags);
+acpi_status acpi_hw_disable_all_gpes(void);
-acpi_status
-acpi_hw_enable_all_runtime_gpes (
- u32 flags);
+acpi_status acpi_hw_enable_all_runtime_gpes(void);
-acpi_status
-acpi_hw_enable_all_wakeup_gpes (
- u32 flags);
+acpi_status acpi_hw_enable_all_wakeup_gpes(void);
acpi_status
-acpi_hw_enable_runtime_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
-
+acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
#ifdef ACPI_FUTURE_USAGE
/*
* hwtimer - ACPI Timer prototypes
*/
-acpi_status
-acpi_get_timer_resolution (
- u32 *resolution);
+acpi_status acpi_get_timer_resolution(u32 * resolution);
-acpi_status
-acpi_get_timer (
- u32 *ticks);
+acpi_status acpi_get_timer(u32 * ticks);
acpi_status
-acpi_get_timer_duration (
- u32 start_ticks,
- u32 end_ticks,
- u32 *time_elapsed);
-#endif /* ACPI_FUTURE_USAGE */
-
+acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed);
+#endif /* ACPI_FUTURE_USAGE */
-#endif /* __ACHWARE_H__ */
+#endif /* __ACHWARE_H__ */
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 5c7172477a0f..2c9c1a1d1b7f 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -44,29 +44,22 @@
#ifndef __ACINTERP_H__
#define __ACINTERP_H__
-
#define ACPI_WALK_OPERANDS (&(walk_state->operands [walk_state->num_operands -1]))
-
/*
* exconvrt - object conversion
*/
acpi_status
-acpi_ex_convert_to_integer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 flags);
+acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc, u32 flags);
acpi_status
-acpi_ex_convert_to_buffer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc);
+acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc);
acpi_status
-acpi_ex_convert_to_string (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 type);
+acpi_ex_convert_to_string(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc, u32 type);
/* Types for ->String conversion */
@@ -76,587 +69,412 @@ acpi_ex_convert_to_string (
#define ACPI_EXPLICIT_CONVERT_DECIMAL 0x00000003
acpi_status
-acpi_ex_convert_to_target_type (
- acpi_object_type destination_type,
- union acpi_operand_object *source_desc,
- union acpi_operand_object **result_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_convert_to_target_type(acpi_object_type destination_type,
+ union acpi_operand_object *source_desc,
+ union acpi_operand_object **result_desc,
+ struct acpi_walk_state *walk_state);
/*
* exfield - ACPI AML (p-code) execution - field manipulation
*/
acpi_status
-acpi_ex_common_buffer_setup (
- union acpi_operand_object *obj_desc,
- u32 buffer_length,
- u32 *datum_count);
+acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc,
+ u32 buffer_length, u32 * datum_count);
acpi_status
-acpi_ex_write_with_update_rule (
- union acpi_operand_object *obj_desc,
- acpi_integer mask,
- acpi_integer field_value,
- u32 field_datum_byte_offset);
+acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
+ acpi_integer mask,
+ acpi_integer field_value,
+ u32 field_datum_byte_offset);
void
-acpi_ex_get_buffer_datum(
- acpi_integer *datum,
- void *buffer,
- u32 buffer_length,
- u32 byte_granularity,
- u32 buffer_offset);
+acpi_ex_get_buffer_datum(acpi_integer * datum,
+ void *buffer,
+ u32 buffer_length,
+ u32 byte_granularity, u32 buffer_offset);
void
-acpi_ex_set_buffer_datum (
- acpi_integer merged_datum,
- void *buffer,
- u32 buffer_length,
- u32 byte_granularity,
- u32 buffer_offset);
+acpi_ex_set_buffer_datum(acpi_integer merged_datum,
+ void *buffer,
+ u32 buffer_length,
+ u32 byte_granularity, u32 buffer_offset);
acpi_status
-acpi_ex_read_data_from_field (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **ret_buffer_desc);
+acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **ret_buffer_desc);
acpi_status
-acpi_ex_write_data_to_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc);
-
+acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc);
/*
* exfldio - low level field I/O
*/
acpi_status
-acpi_ex_extract_from_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length);
+acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length);
acpi_status
-acpi_ex_insert_into_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length);
+acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length);
acpi_status
-acpi_ex_access_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 read_write);
-
+acpi_ex_access_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 read_write);
/*
* exmisc - misc support routines
*/
acpi_status
-acpi_ex_get_object_reference (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **return_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **return_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_concat_template (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *obj_desc2,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_concat_template(union acpi_operand_object *obj_desc,
+ union acpi_operand_object *obj_desc2,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_do_concatenate (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *obj_desc2,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_do_concatenate(union acpi_operand_object *obj_desc,
+ union acpi_operand_object *obj_desc2,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_do_logical_numeric_op (
- u16 opcode,
- acpi_integer integer0,
- acpi_integer integer1,
- u8 *logical_result);
+acpi_ex_do_logical_numeric_op(u16 opcode,
+ acpi_integer integer0,
+ acpi_integer integer1, u8 * logical_result);
acpi_status
-acpi_ex_do_logical_op (
- u16 opcode,
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- u8 *logical_result);
+acpi_ex_do_logical_op(u16 opcode,
+ union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1, u8 * logical_result);
acpi_integer
-acpi_ex_do_math_op (
- u16 opcode,
- acpi_integer operand0,
- acpi_integer operand1);
+acpi_ex_do_math_op(u16 opcode, acpi_integer operand0, acpi_integer operand1);
-acpi_status
-acpi_ex_create_mutex (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_create_processor (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_create_power_resource (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_create_region (
- u8 *aml_start,
- u32 aml_length,
- u8 region_space,
- struct acpi_walk_state *walk_state);
+acpi_ex_create_region(u8 * aml_start,
+ u32 aml_length,
+ u8 region_space, struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_create_table_region (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_create_event (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_create_alias (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_create_method (
- u8 *aml_start,
- u32 aml_length,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_create_method(u8 * aml_start,
+ u32 aml_length, struct acpi_walk_state *walk_state);
/*
* exconfig - dynamic table load/unload
*/
acpi_status
-acpi_ex_load_op (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *target,
- struct acpi_walk_state *walk_state);
+acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ union acpi_operand_object *target,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_load_table_op (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **return_desc);
-
-acpi_status
-acpi_ex_unload_table (
- union acpi_operand_object *ddb_handle);
+acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
+ union acpi_operand_object **return_desc);
+acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle);
/*
* exmutex - mutex support
*/
acpi_status
-acpi_ex_acquire_mutex (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_release_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state);
-void
-acpi_ex_release_all_mutexes (
- struct acpi_thread_state *thread);
-
-void
-acpi_ex_unlink_mutex (
- union acpi_operand_object *obj_desc);
+void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
/*
* exprep - ACPI AML execution - prep utilities
*/
acpi_status
-acpi_ex_prep_common_field_object (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u8 field_attribute,
- u32 field_bit_position,
- u32 field_bit_length);
-
-acpi_status
-acpi_ex_prep_field_value (
- struct acpi_create_field_info *info);
+acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
+ u8 field_flags,
+ u8 field_attribute,
+ u32 field_bit_position, u32 field_bit_length);
+acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info);
/*
* exsystem - Interface to OS services
*/
acpi_status
-acpi_ex_system_do_notify_op (
- union acpi_operand_object *value,
- union acpi_operand_object *obj_desc);
+acpi_ex_system_do_notify_op(union acpi_operand_object *value,
+ union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ex_system_do_suspend(
- acpi_integer time);
+acpi_status acpi_ex_system_do_suspend(acpi_integer time);
-acpi_status
-acpi_ex_system_do_stall (
- u32 time);
+acpi_status acpi_ex_system_do_stall(u32 time);
acpi_status
-acpi_ex_system_acquire_mutex(
- union acpi_operand_object *time,
- union acpi_operand_object *obj_desc);
+acpi_ex_system_acquire_mutex(union acpi_operand_object *time,
+ union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ex_system_release_mutex(
- union acpi_operand_object *obj_desc);
+acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ex_system_signal_event(
- union acpi_operand_object *obj_desc);
+acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc);
acpi_status
-acpi_ex_system_wait_event(
- union acpi_operand_object *time,
- union acpi_operand_object *obj_desc);
+acpi_ex_system_wait_event(union acpi_operand_object *time,
+ union acpi_operand_object *obj_desc);
-acpi_status
-acpi_ex_system_reset_event(
- union acpi_operand_object *obj_desc);
-
-acpi_status
-acpi_ex_system_wait_semaphore (
- acpi_handle semaphore,
- u16 timeout);
+acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc);
+acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout);
/*
* exoparg1 - ACPI AML execution, 1 operand
*/
-acpi_status
-acpi_ex_opcode_0A_0T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_1A_0T_0R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_1A_0T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_1A_1T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_1A_1T_0R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state);
/*
* exoparg2 - ACPI AML execution, 2 operands
*/
-acpi_status
-acpi_ex_opcode_2A_0T_0R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_2A_0T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ex_opcode_2A_1T_1R (
- struct acpi_walk_state *walk_state);
-
-acpi_status
-acpi_ex_opcode_2A_2T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state);
/*
* exoparg3 - ACPI AML execution, 3 operands
*/
-acpi_status
-acpi_ex_opcode_3A_0T_0R (
- struct acpi_walk_state *walk_state);
-
-acpi_status
-acpi_ex_opcode_3A_1T_1R (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state);
+acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state);
/*
* exoparg6 - ACPI AML execution, 6 operands
*/
-acpi_status
-acpi_ex_opcode_6A_0T_1R (
- struct acpi_walk_state *walk_state);
-
+acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state *walk_state);
/*
* exresolv - Object resolution and get value functions
*/
acpi_status
-acpi_ex_resolve_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state);
+acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_resolve_multiple (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *operand,
- acpi_object_type *return_type,
- union acpi_operand_object **return_desc);
-
+acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *operand,
+ acpi_object_type * return_type,
+ union acpi_operand_object **return_desc);
/*
* exresnte - resolve namespace node
*/
acpi_status
-acpi_ex_resolve_node_to_value (
- struct acpi_namespace_node **stack_ptr,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_resolve_node_to_value(struct acpi_namespace_node **stack_ptr,
+ struct acpi_walk_state *walk_state);
/*
* exresop - resolve operand to value
*/
acpi_status
-acpi_ex_resolve_operands (
- u16 opcode,
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_resolve_operands(u16 opcode,
+ union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state);
/*
* exdump - Interpreter debug output routines
*/
-void
-acpi_ex_dump_operand (
- union acpi_operand_object *obj_desc,
- u32 depth);
+void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth);
void
-acpi_ex_dump_operands (
- union acpi_operand_object **operands,
- acpi_interpreter_mode interpreter_mode,
- char *ident,
- u32 num_levels,
- char *note,
- char *module_name,
- u32 line_number);
+acpi_ex_dump_operands(union acpi_operand_object **operands,
+ acpi_interpreter_mode interpreter_mode,
+ char *ident,
+ u32 num_levels,
+ char *note, char *module_name, u32 line_number);
#ifdef ACPI_FUTURE_USAGE
void
-acpi_ex_dump_object_descriptor (
- union acpi_operand_object *object,
- u32 flags);
-
-void
-acpi_ex_dump_node (
- struct acpi_namespace_node *node,
- u32 flags);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags);
+void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags);
+#endif /* ACPI_FUTURE_USAGE */
/*
* exnames - AML namestring support
*/
acpi_status
-acpi_ex_get_name_string (
- acpi_object_type data_type,
- u8 *in_aml_address,
- char **out_name_string,
- u32 *out_name_length);
-
+acpi_ex_get_name_string(acpi_object_type data_type,
+ u8 * in_aml_address,
+ char **out_name_string, u32 * out_name_length);
/*
* exstore - Object store support
*/
acpi_status
-acpi_ex_store (
- union acpi_operand_object *val_desc,
- union acpi_operand_object *dest_desc,
- struct acpi_walk_state *walk_state);
+acpi_ex_store(union acpi_operand_object *val_desc,
+ union acpi_operand_object *dest_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_store_object_to_node (
- union acpi_operand_object *source_desc,
- struct acpi_namespace_node *node,
- struct acpi_walk_state *walk_state,
- u8 implicit_conversion);
+acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
+ struct acpi_namespace_node *node,
+ struct acpi_walk_state *walk_state,
+ u8 implicit_conversion);
#define ACPI_IMPLICIT_CONVERSION TRUE
#define ACPI_NO_IMPLICIT_CONVERSION FALSE
-
/*
* exstoren - resolve/store object
*/
acpi_status
-acpi_ex_resolve_object (
- union acpi_operand_object **source_desc_ptr,
- acpi_object_type target_type,
- struct acpi_walk_state *walk_state);
+acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
+ acpi_object_type target_type,
+ struct acpi_walk_state *walk_state);
acpi_status
-acpi_ex_store_object_to_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc,
- union acpi_operand_object **new_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc,
+ union acpi_operand_object **new_desc,
+ struct acpi_walk_state *walk_state);
/*
* exstorob - store object - buffer/string
*/
acpi_status
-acpi_ex_store_buffer_to_buffer (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc);
+acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc);
acpi_status
-acpi_ex_store_string_to_string (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc);
-
+acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc);
/*
* excopy - object copy
*/
acpi_status
-acpi_ex_copy_integer_to_index_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc);
+acpi_ex_copy_integer_to_index_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc);
acpi_status
-acpi_ex_copy_integer_to_bank_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc);
+acpi_ex_copy_integer_to_bank_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc);
acpi_status
-acpi_ex_copy_data_to_named_field (
- union acpi_operand_object *source_desc,
- struct acpi_namespace_node *node);
+acpi_ex_copy_data_to_named_field(union acpi_operand_object *source_desc,
+ struct acpi_namespace_node *node);
acpi_status
-acpi_ex_copy_integer_to_buffer_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc);
-
+acpi_ex_copy_integer_to_buffer_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc);
/*
* exutils - interpreter/scanner utilities
*/
-acpi_status
-acpi_ex_enter_interpreter (
- void);
+acpi_status acpi_ex_enter_interpreter(void);
-void
-acpi_ex_exit_interpreter (
- void);
+void acpi_ex_exit_interpreter(void);
-void
-acpi_ex_truncate_for32bit_table (
- union acpi_operand_object *obj_desc);
+void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
-u8
-acpi_ex_acquire_global_lock (
- u32 rule);
+u8 acpi_ex_acquire_global_lock(u32 rule);
-void
-acpi_ex_release_global_lock (
- u8 locked);
+void acpi_ex_release_global_lock(u8 locked);
-void
-acpi_ex_eisa_id_to_string (
- u32 numeric_id,
- char *out_string);
-
-void
-acpi_ex_unsigned_integer_to_string (
- acpi_integer value,
- char *out_string);
+void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string);
+void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string);
/*
* exregion - default op_region handlers
*/
acpi_status
-acpi_ex_system_memory_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_system_io_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_pci_config_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_cmos_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_pci_bar_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_embedded_controller_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-acpi_status
-acpi_ex_sm_bus_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-
-acpi_status
-acpi_ex_data_table_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
-
-#endif /* __INTERP_H__ */
+acpi_ex_system_memory_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context,
+ void *region_context);
+
+acpi_status
+acpi_ex_system_io_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+acpi_status
+acpi_ex_pci_config_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+acpi_status
+acpi_ex_cmos_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+acpi_status
+acpi_ex_pci_bar_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+acpi_status
+acpi_ex_embedded_controller_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context,
+ void *region_context);
+
+acpi_status
+acpi_ex_sm_bus_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+acpi_status
+acpi_ex_data_table_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context);
+
+#endif /* __INTERP_H__ */
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index 030e641115cb..9fba0fddda90 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -44,17 +44,20 @@
#ifndef __ACLOCAL_H__
#define __ACLOCAL_H__
+#define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */
-#define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */
-
-typedef void * acpi_mutex;
-typedef u32 acpi_mutex_handle;
-
+typedef void *acpi_mutex;
+typedef u32 acpi_mutex_handle;
/* Total number of aml opcodes defined */
#define AML_NUM_OPCODES 0x7F
+/* Forward declarations */
+
+struct acpi_walk_state;
+struct acpi_obj_mutex;
+union acpi_parse_object;
/*****************************************************************************
*
@@ -62,7 +65,6 @@ typedef u32 acpi_mutex_handle;
*
****************************************************************************/
-
/*
* Predefined handles for the mutex objects used within the subsystem
* All mutex objects are automatically created by acpi_ut_mutex_initialize.
@@ -89,14 +91,12 @@ typedef u32 acpi_mutex_handle;
#define MAX_MUTEX 12
#define NUM_MUTEX MAX_MUTEX+1
-
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
#ifdef DEFINE_ACPI_GLOBALS
/* Names for the mutexes used in the subsystem */
-static char *acpi_gbl_mutex_names[] =
-{
+static char *acpi_gbl_mutex_names[] = {
"ACPI_MTX_Execute",
"ACPI_MTX_Interpreter",
"ACPI_MTX_Parser",
@@ -115,34 +115,28 @@ static char *acpi_gbl_mutex_names[] =
#endif
#endif
+/* Owner IDs are used to track namespace nodes for selective deletion */
-/* Table for the global mutexes */
+typedef u8 acpi_owner_id;
+#define ACPI_OWNER_ID_MAX 0xFF
-struct acpi_mutex_info
-{
- acpi_mutex mutex;
- u32 use_count;
- u32 owner_id;
-};
+/* This Thread ID means that the mutex is not in use (unlocked) */
-/* This owner ID means that the mutex is not in use (unlocked) */
+#define ACPI_MUTEX_NOT_ACQUIRED (u32) -1
-#define ACPI_MUTEX_NOT_ACQUIRED (u32) (-1)
+/* Table for the global mutexes */
+struct acpi_mutex_info {
+ acpi_mutex mutex;
+ u32 use_count;
+ u32 thread_id;
+};
/* Lock flag parameter for various interfaces */
#define ACPI_MTX_DO_NOT_LOCK 0
#define ACPI_MTX_LOCK 1
-
-typedef u16 acpi_owner_id;
-#define ACPI_OWNER_TYPE_TABLE 0x0
-#define ACPI_OWNER_TYPE_METHOD 0x1
-#define ACPI_FIRST_METHOD_ID 0x0001
-#define ACPI_FIRST_TABLE_ID 0xF000
-
-
/* Field access granularities */
#define ACPI_FIELD_BYTE_GRANULARITY 1
@@ -150,7 +144,6 @@ typedef u16 acpi_owner_id;
#define ACPI_FIELD_DWORD_GRANULARITY 4
#define ACPI_FIELD_QWORD_GRANULARITY 8
-
/*****************************************************************************
*
* Namespace typedefs and structs
@@ -159,15 +152,12 @@ typedef u16 acpi_owner_id;
/* Operational modes of the AML interpreter/scanner */
-typedef enum
-{
- ACPI_IMODE_LOAD_PASS1 = 0x01,
- ACPI_IMODE_LOAD_PASS2 = 0x02,
- ACPI_IMODE_EXECUTE = 0x0E
-
+typedef enum {
+ ACPI_IMODE_LOAD_PASS1 = 0x01,
+ ACPI_IMODE_LOAD_PASS2 = 0x02,
+ 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.
@@ -175,34 +165,37 @@ typedef enum
* 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];
-};
-
-struct acpi_namespace_node
-{
- u8 descriptor; /* Used to differentiate object descriptor types */
- u8 type; /* Type associated with this name */
- u16 owner_id;
- 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*/
- u16 reference_count; /* Current count of references and children */
- u8 flags;
+union acpi_name_union {
+ u32 integer;
+ char ascii[4];
+};
+
+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_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 */
+
+#ifdef ACPI_ASL_COMPILER
+ u32 value;
+ union acpi_parse_object *op;
+#endif
};
-
#define ACPI_ENTRY_NOT_FOUND NULL
-
/* Node flags */
#define ANOBJ_RESERVED 0x01
#define ANOBJ_END_OF_PEER_LIST 0x02
-#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */
+#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
@@ -212,91 +205,77 @@ struct acpi_namespace_node
/*
* ACPI Table Descriptor. One per ACPI table
*/
-struct acpi_table_desc
-{
- struct acpi_table_desc *prev;
- struct acpi_table_desc *next;
- struct acpi_table_desc *installed_desc;
- struct acpi_table_header *pointer;
- u8 *aml_start;
- u64 physical_address;
- u32 aml_length;
- acpi_size length;
- acpi_owner_id table_id;
- u8 type;
- u8 allocation;
- u8 loaded_into_namespace;
+struct acpi_table_desc {
+ struct acpi_table_desc *prev;
+ struct acpi_table_desc *next;
+ struct acpi_table_desc *installed_desc;
+ struct acpi_table_header *pointer;
+ u8 *aml_start;
+ u64 physical_address;
+ u32 aml_length;
+ acpi_size length;
+ acpi_owner_id owner_id;
+ u8 type;
+ u8 allocation;
+ u8 loaded_into_namespace;
};
-struct acpi_table_list
-{
- struct acpi_table_desc *next;
- u32 count;
+struct acpi_table_list {
+ struct acpi_table_desc *next;
+ u32 count;
};
-
-struct acpi_find_context
-{
- char *search_for;
- acpi_handle *list;
- u32 *count;
+struct acpi_find_context {
+ char *search_for;
+ acpi_handle *list;
+ u32 *count;
};
-
-struct acpi_ns_search_data
-{
- struct acpi_namespace_node *node;
+struct acpi_ns_search_data {
+ struct acpi_namespace_node *node;
};
-
/*
* Predefined Namespace items
*/
-struct acpi_predefined_names
-{
- char *name;
- u8 type;
- char *val;
+struct acpi_predefined_names {
+ char *name;
+ u8 type;
+ char *val;
};
-
/* Object types used during package copies */
-
#define ACPI_COPY_TYPE_SIMPLE 0
#define ACPI_COPY_TYPE_PACKAGE 1
/* Info structure used to convert external<->internal namestrings */
-struct acpi_namestring_info
-{
- char *external_name;
- char *next_external_char;
- char *internal_name;
- u32 length;
- u32 num_segments;
- u32 num_carats;
- u8 fully_qualified;
+struct acpi_namestring_info {
+ char *external_name;
+ char *next_external_char;
+ char *internal_name;
+ u32 length;
+ u32 num_segments;
+ u32 num_carats;
+ u8 fully_qualified;
};
-
/* Field creation info */
-struct acpi_create_field_info
-{
- struct acpi_namespace_node *region_node;
- struct acpi_namespace_node *field_node;
- struct acpi_namespace_node *register_node;
- struct acpi_namespace_node *data_register_node;
- u32 bank_value;
- u32 field_bit_position;
- u32 field_bit_length;
- u8 field_flags;
- u8 attribute;
- u8 field_type;
+struct acpi_create_field_info {
+ struct acpi_namespace_node *region_node;
+ struct acpi_namespace_node *field_node;
+ struct acpi_namespace_node *register_node;
+ struct acpi_namespace_node *data_register_node;
+ u32 bank_value;
+ u32 field_bit_position;
+ u32 field_bit_length;
+ u8 field_flags;
+ u8 attribute;
+ u8 field_type;
};
-
/*****************************************************************************
*
* Event typedefs and structs
@@ -305,108 +284,95 @@ struct acpi_create_field_info
/* Dispatch info for each GPE -- either a method or handler, cannot be both */
-struct acpi_handler_info
-{
- acpi_event_handler address; /* Address of handler, if any */
- void *context; /* Context to be passed to handler */
- struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
+struct acpi_handler_info {
+ acpi_event_handler address; /* Address of handler, if any */
+ void *context; /* Context to be passed to handler */
+ struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
};
-union acpi_gpe_dispatch_info
-{
- struct acpi_namespace_node *method_node; /* Method node for this GPE level */
- struct acpi_handler_info *handler;
+union acpi_gpe_dispatch_info {
+ struct acpi_namespace_node *method_node; /* Method node for this GPE level */
+ struct acpi_handler_info *handler;
};
/*
* Information about a GPE, one per each GPE in an array.
* NOTE: Important to keep this struct as small as possible.
*/
-struct acpi_gpe_event_info
-{
- union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */
- struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
- u8 flags; /* Misc info about this GPE */
- u8 register_bit; /* This GPE bit within the register */
+struct acpi_gpe_event_info {
+ union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */
+ struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
+ u8 flags; /* Misc info about this GPE */
+ u8 register_bit; /* This GPE bit within the register */
};
/* Information about a GPE register pair, one per each status/enable pair in an array */
-struct acpi_gpe_register_info
-{
- struct acpi_generic_address status_address; /* Address of status reg */
- struct acpi_generic_address enable_address; /* Address of enable reg */
- u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
- u8 enable_for_run; /* GPEs to keep enabled when running */
- u8 base_gpe_number; /* Base GPE number for this register */
+struct acpi_gpe_register_info {
+ struct acpi_generic_address status_address; /* Address of status reg */
+ struct acpi_generic_address enable_address; /* Address of enable reg */
+ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
+ u8 enable_for_run; /* GPEs to keep enabled when running */
+ u8 base_gpe_number; /* Base GPE number for this register */
};
/*
* Information about a GPE register block, one per each installed block --
* GPE0, GPE1, and one per each installed GPE Block Device.
*/
-struct acpi_gpe_block_info
-{
- struct acpi_namespace_node *node;
- struct acpi_gpe_block_info *previous;
- struct acpi_gpe_block_info *next;
- struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
- struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
- struct acpi_gpe_event_info *event_info; /* One for each GPE */
- struct acpi_generic_address block_address; /* Base address of the block */
- u32 register_count; /* Number of register pairs in block */
- u8 block_base_number;/* Base GPE number for this block */
+struct acpi_gpe_block_info {
+ struct acpi_namespace_node *node;
+ struct acpi_gpe_block_info *previous;
+ struct acpi_gpe_block_info *next;
+ struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
+ struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
+ struct acpi_gpe_event_info *event_info; /* One for each GPE */
+ struct acpi_generic_address block_address; /* Base address of the block */
+ u32 register_count; /* Number of register pairs in block */
+ u8 block_base_number; /* Base GPE number for this block */
};
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
-struct acpi_gpe_xrupt_info
-{
- struct acpi_gpe_xrupt_info *previous;
- struct acpi_gpe_xrupt_info *next;
- struct acpi_gpe_block_info *gpe_block_list_head; /* List of GPE blocks for this xrupt */
- u32 interrupt_level; /* System interrupt level */
+struct acpi_gpe_xrupt_info {
+ struct acpi_gpe_xrupt_info *previous;
+ struct acpi_gpe_xrupt_info *next;
+ struct acpi_gpe_block_info *gpe_block_list_head; /* List of GPE blocks for this xrupt */
+ u32 interrupt_number; /* System interrupt number */
};
-
-struct acpi_gpe_walk_info
-{
- struct acpi_namespace_node *gpe_device;
- struct acpi_gpe_block_info *gpe_block;
+struct acpi_gpe_walk_info {
+ struct acpi_namespace_node *gpe_device;
+ struct acpi_gpe_block_info *gpe_block;
};
-
-typedef acpi_status (*ACPI_GPE_CALLBACK) (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
-
+typedef acpi_status(*ACPI_GPE_CALLBACK) (struct acpi_gpe_xrupt_info *
+ gpe_xrupt_info,
+ struct acpi_gpe_block_info *
+ gpe_block);
/* Information about each particular fixed event */
-struct acpi_fixed_event_handler
-{
- acpi_event_handler handler; /* Address of handler. */
- void *context; /* Context to be passed to handler */
+struct acpi_fixed_event_handler {
+ acpi_event_handler handler; /* Address of handler. */
+ void *context; /* Context to be passed to handler */
};
-struct acpi_fixed_event_info
-{
- u8 status_register_id;
- u8 enable_register_id;
- u16 status_bit_mask;
- u16 enable_bit_mask;
+struct acpi_fixed_event_info {
+ u8 status_register_id;
+ u8 enable_register_id;
+ u16 status_bit_mask;
+ u16 enable_bit_mask;
};
/* Information used during field processing */
-struct acpi_field_info
-{
- u8 skip_field;
- u8 field_flag;
- u32 pkg_length;
+struct acpi_field_info {
+ u8 skip_field;
+ u8 field_flag;
+ u32 pkg_length;
};
-
/*****************************************************************************
*
* Generic "state" object for stacks
@@ -419,14 +385,6 @@ struct acpi_field_info
#define ACPI_CONTROL_PREDICATE_FALSE 0xC3
#define ACPI_CONTROL_PREDICATE_TRUE 0xC4
-
-/* Forward declarations */
-
-struct acpi_walk_state ;
-struct acpi_obj_mutex;
-union acpi_parse_object ;
-
-
#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\
u8 data_type; /* To differentiate various internal objs */\
u8 flags; \
@@ -435,147 +393,112 @@ union acpi_parse_object ;
u16 reserved; \
void *next; \
-struct acpi_common_state
-{
- ACPI_STATE_COMMON
-};
-
+struct acpi_common_state {
+ACPI_STATE_COMMON};
/*
* Update state - used to traverse complex objects such as packages
*/
-struct acpi_update_state
-{
- ACPI_STATE_COMMON
- union acpi_operand_object *object;
+struct acpi_update_state {
+ ACPI_STATE_COMMON union acpi_operand_object *object;
};
-
/*
* Pkg state - used to traverse nested package structures
*/
-struct acpi_pkg_state
-{
- ACPI_STATE_COMMON
- 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;
+struct acpi_pkg_state {
+ ACPI_STATE_COMMON 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;
};
-
/*
* Control state - one per if/else and while constructs.
* Allows nesting of these constructs
*/
-struct acpi_control_state
-{
- ACPI_STATE_COMMON
- 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;
+struct acpi_control_state {
+ ACPI_STATE_COMMON 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;
};
-
/*
* Scope state - current scope during namespace lookups
*/
-struct acpi_scope_state
-{
- ACPI_STATE_COMMON
- struct acpi_namespace_node *node;
+struct acpi_scope_state {
+ ACPI_STATE_COMMON struct acpi_namespace_node *node;
};
-
-struct acpi_pscope_state
-{
- ACPI_STATE_COMMON
- 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 */
+struct acpi_pscope_state {
+ ACPI_STATE_COMMON 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 */
};
-
/*
* Thread state - one per thread across multiple walk states. Multiple walk
* 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 */
- 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 */
+struct acpi_thread_state {
+ ACPI_STATE_COMMON 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 */
};
-
/*
* Result values - used to accumulate the results of nested
* AML arguments
*/
-struct acpi_result_values
-{
+struct acpi_result_values {
ACPI_STATE_COMMON
- union acpi_operand_object *obj_desc [ACPI_OBJ_NUM_OPERANDS];
- u8 num_results;
- u8 last_insert;
+ union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
+ u8 num_results;
+ u8 last_insert;
};
-
-typedef
-acpi_status (*acpi_parse_downwards) (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op);
-
typedef
-acpi_status (*acpi_parse_upwards) (
- struct acpi_walk_state *walk_state);
+acpi_status(*acpi_parse_downwards) (struct acpi_walk_state * walk_state,
+ union acpi_parse_object ** out_op);
+typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state);
/*
* Notify info - used to pass info to the deferred notify
* handler/dispatcher.
*/
-struct acpi_notify_info
-{
- ACPI_STATE_COMMON
- struct acpi_namespace_node *node;
- union acpi_operand_object *handler_obj;
+struct acpi_notify_info {
+ ACPI_STATE_COMMON struct acpi_namespace_node *node;
+ union acpi_operand_object *handler_obj;
};
-
/* Generic state is union of structs above */
-union acpi_generic_state
-{
- struct acpi_common_state common;
- struct acpi_control_state control;
- struct acpi_update_state update;
- struct acpi_scope_state scope;
- struct acpi_pscope_state parse_scope;
- struct acpi_pkg_state pkg;
- struct acpi_thread_state thread;
- struct acpi_result_values results;
- struct acpi_notify_info notify;
+union acpi_generic_state {
+ struct acpi_common_state common;
+ struct acpi_control_state control;
+ struct acpi_update_state update;
+ struct acpi_scope_state scope;
+ struct acpi_pscope_state parse_scope;
+ struct acpi_pkg_state pkg;
+ struct acpi_thread_state thread;
+ struct acpi_result_values results;
+ struct acpi_notify_info notify;
};
-
/*****************************************************************************
*
* Interpreter typedefs and structs
*
****************************************************************************/
-typedef
-acpi_status (*ACPI_EXECUTE_OP) (
- struct acpi_walk_state *walk_state);
-
+typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
/*****************************************************************************
*
@@ -586,28 +509,26 @@ acpi_status (*ACPI_EXECUTE_OP) (
/*
* AML opcode, name, and argument layout
*/
-struct acpi_opcode_info
-{
+struct acpi_opcode_info {
#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT)
- char *name; /* Opcode name (disassembler/debug only) */
+ char *name; /* Opcode name (disassembler/debug only) */
#endif
- u32 parse_args; /* Grammar/Parse time arguments */
- u32 runtime_args; /* Interpret time arguments */
- u32 flags; /* Misc flags */
- u8 object_type; /* Corresponding internal object type */
- u8 class; /* Opcode class */
- u8 type; /* Opcode type */
+ u32 parse_args; /* Grammar/Parse time arguments */
+ u32 runtime_args; /* Interpret time arguments */
+ u32 flags; /* Misc flags */
+ u8 object_type; /* Corresponding internal object type */
+ u8 class; /* Opcode class */
+ u8 type; /* Opcode type */
};
-union acpi_parse_value
-{
- acpi_integer integer; /* Integer constant (Up to 64 bits) */
- struct uint64_struct integer64; /* Structure overlay for 2 32-bit Dwords */
- u32 size; /* bytelist or field size */
- char *string; /* NULL terminated string */
- u8 *buffer; /* buffer or string */
- char *name; /* NULL terminated string */
- union acpi_parse_object *arg; /* arguments and contained ops */
+union acpi_parse_value {
+ acpi_integer integer; /* Integer constant (Up to 64 bits) */
+ struct uint64_struct integer64; /* Structure overlay for 2 32-bit Dwords */
+ u32 size; /* bytelist or field size */
+ char *string; /* NULL terminated string */
+ u8 *buffer; /* buffer or string */
+ char *name; /* NULL terminated string */
+ union acpi_parse_object *arg; /* arguments and contained ops */
};
#define ACPI_PARSE_COMMON \
@@ -636,84 +557,72 @@ union acpi_parse_value
/*
* generic operation (for example: If, While, Store)
*/
-struct acpi_parse_obj_common
-{
- ACPI_PARSE_COMMON
-};
-
+struct acpi_parse_obj_common {
+ACPI_PARSE_COMMON};
/*
* Extended Op for named ops (Scope, Method, etc.), deferred ops (Methods and op_regions),
* and bytelists.
*/
-struct acpi_parse_obj_named
-{
- ACPI_PARSE_COMMON
- u8 *path;
- u8 *data; /* AML body or bytelist data */
- u32 length; /* AML length */
- u32 name; /* 4-byte name or zero if no name */
+struct acpi_parse_obj_named {
+ ACPI_PARSE_COMMON u8 * path;
+ u8 *data; /* AML body or bytelist data */
+ u32 length; /* AML length */
+ u32 name; /* 4-byte name or zero if no name */
};
-
/* The parse node is the fundamental element of the parse tree */
-struct acpi_parse_obj_asl
-{
- ACPI_PARSE_COMMON
- union acpi_parse_object *child;
- union acpi_parse_object *parent_method;
- char *filename;
- char *external_name;
- char *namepath;
- char name_seg[4];
- u32 extra_value;
- u32 column;
- u32 line_number;
- u32 logical_line_number;
- u32 logical_byte_offset;
- u32 end_line;
- u32 end_logical_line;
- u32 acpi_btype;
- u32 aml_length;
- u32 aml_subtree_length;
- u32 final_aml_length;
- u32 final_aml_offset;
- u32 compile_flags;
- u16 parse_opcode;
- u8 aml_opcode_length;
- u8 aml_pkg_len_bytes;
- u8 extra;
- char parse_op_name[12];
-};
-
-union acpi_parse_object
-{
- struct acpi_parse_obj_common common;
- struct acpi_parse_obj_named named;
- struct acpi_parse_obj_asl asl;
+struct acpi_parse_obj_asl {
+ ACPI_PARSE_COMMON union acpi_parse_object *child;
+ union acpi_parse_object *parent_method;
+ char *filename;
+ char *external_name;
+ char *namepath;
+ char name_seg[4];
+ u32 extra_value;
+ u32 column;
+ u32 line_number;
+ u32 logical_line_number;
+ u32 logical_byte_offset;
+ u32 end_line;
+ u32 end_logical_line;
+ u32 acpi_btype;
+ u32 aml_length;
+ u32 aml_subtree_length;
+ u32 final_aml_length;
+ u32 final_aml_offset;
+ u32 compile_flags;
+ u16 parse_opcode;
+ u8 aml_opcode_length;
+ u8 aml_pkg_len_bytes;
+ u8 extra;
+ char parse_op_name[12];
+};
+
+union acpi_parse_object {
+ struct acpi_parse_obj_common common;
+ struct acpi_parse_obj_named named;
+ struct acpi_parse_obj_asl asl;
};
-
/*
* Parse state - one state per parser invocation and each control
* 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 */
- u8 *pkg_start; /* Current package begin */
- u8 *pkg_end; /* Current package end */
- union acpi_parse_object *start_op; /* Root of parse tree */
- struct acpi_namespace_node *start_node;
- union acpi_generic_state *scope; /* Current scope */
- union acpi_parse_object *start_scope;
+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 */
+ u8 *pkg_start; /* Current package begin */
+ u8 *pkg_end; /* Current package end */
+ union acpi_parse_object *start_op; /* Root of parse tree */
+ struct acpi_namespace_node *start_node;
+ union acpi_generic_state *scope; /* Current scope */
+ union acpi_parse_object *start_scope;
};
-
/* Parse object flags */
#define ACPI_PARSEOP_GENERIC 0x01
@@ -729,7 +638,6 @@ struct acpi_parse_state
#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
#define ACPI_PARSEOP_SPECIAL 0x10
-
/*****************************************************************************
*
* Hardware (ACPI registers) and PNP
@@ -737,15 +645,14 @@ struct acpi_parse_state
****************************************************************************/
#define PCI_ROOT_HID_STRING "PNP0A03"
+#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08"
-struct acpi_bit_register_info
-{
- u8 parent_register;
- u8 bit_position;
- u16 access_bit_mask;
+struct acpi_bit_register_info {
+ u8 parent_register;
+ u8 bit_position;
+ u16 access_bit_mask;
};
-
/*
* Register IDs
* These are the full ACPI registers
@@ -760,7 +667,6 @@ struct acpi_bit_register_info
#define ACPI_REGISTER_PROCESSOR_BLOCK 0x08
#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x09
-
/* Masks used to access the bit_registers */
#define ACPI_BITMASK_TIMER_STATUS 0x0001
@@ -769,7 +675,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
-#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
+#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 | \
@@ -785,7 +691,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
-#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_SCI_ENABLE 0x0001
#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
@@ -795,7 +701,6 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_ARB_DISABLE 0x0001
-
/* Raw bit position of each bit_register */
#define ACPI_BITPOSITION_TIMER_STATUS 0x00
@@ -804,7 +709,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09
#define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A
-#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */
+#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_WAKE_STATUS 0x0F
#define ACPI_BITPOSITION_TIMER_ENABLE 0x00
@@ -812,7 +717,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09
#define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A
-#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */
+#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_SCI_ENABLE 0x00
#define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01
@@ -822,7 +727,6 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_ARB_DISABLE 0x00
-
/*****************************************************************************
*
* Resource descriptors
@@ -841,8 +745,7 @@ struct acpi_bit_register_info
#define ACPI_RDESC_TYPE_SMALL 0x00
#define ACPI_RDESC_TYPE_MASK 0x80
-#define ACPI_RDESC_SMALL_MASK 0x78 /* Only bits 6:3 contain the type */
-
+#define ACPI_RDESC_SMALL_MASK 0x78 /* Only bits 6:3 contain the type */
/*
* Small resource descriptor types
@@ -871,7 +774,6 @@ struct acpi_bit_register_info
#define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A
#define ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE 0x8B
-
/*****************************************************************************
*
* Miscellaneous
@@ -880,49 +782,36 @@ struct acpi_bit_register_info
#define ACPI_ASCII_ZERO 0x30
-
/*****************************************************************************
*
* Debugger
*
****************************************************************************/
-struct acpi_db_method_info
-{
- acpi_handle thread_gate;
- char *name;
- char **args;
- u32 flags;
- u32 num_loops;
- char pathname[128];
+struct acpi_db_method_info {
+ acpi_handle thread_gate;
+ char *name;
+ char **args;
+ u32 flags;
+ u32 num_loops;
+ char pathname[128];
};
-struct acpi_integrity_info
-{
- u32 nodes;
- u32 objects;
+struct acpi_integrity_info {
+ u32 nodes;
+ u32 objects;
};
-
#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01
#define ACPI_DB_CONSOLE_OUTPUT 0x02
#define ACPI_DB_DUPLICATE_OUTPUT 0x03
-
/*****************************************************************************
*
* Debug
*
****************************************************************************/
-struct acpi_debug_print_info
-{
- u32 component_id;
- char *proc_name;
- char *module_name;
-};
-
-
/* Entry for a memory allocation (debug only) */
#define ACPI_MEM_MALLOC 0
@@ -938,51 +827,36 @@ struct acpi_debug_print_info
char module[ACPI_MAX_MODULE_NAME]; \
u8 alloc_type;
-struct acpi_debug_mem_header
-{
- ACPI_COMMON_DEBUG_MEM_HEADER
-};
+struct acpi_debug_mem_header {
+ACPI_COMMON_DEBUG_MEM_HEADER};
-struct acpi_debug_mem_block
-{
- ACPI_COMMON_DEBUG_MEM_HEADER
- u64 user_space;
+struct acpi_debug_mem_block {
+ ACPI_COMMON_DEBUG_MEM_HEADER u64 user_space;
};
-
#define ACPI_MEM_LIST_GLOBAL 0
#define ACPI_MEM_LIST_NSNODE 1
+#define ACPI_MEM_LIST_MAX 1
+#define ACPI_NUM_MEM_LISTS 2
-#define ACPI_MEM_LIST_FIRST_CACHE_LIST 2
-#define ACPI_MEM_LIST_STATE 2
-#define ACPI_MEM_LIST_PSNODE 3
-#define ACPI_MEM_LIST_PSNODE_EXT 4
-#define ACPI_MEM_LIST_OPERAND 5
-#define ACPI_MEM_LIST_WALK 6
-#define ACPI_MEM_LIST_MAX 6
-#define ACPI_NUM_MEM_LISTS 7
-
-
-struct acpi_memory_list
-{
- void *list_head;
- u16 link_offset;
- u16 max_cache_depth;
- u16 cache_depth;
- u16 object_size;
+struct acpi_memory_list {
+ char *list_name;
+ void *list_head;
+ u16 object_size;
+ u16 max_depth;
+ u16 current_depth;
+ u16 link_offset;
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
/* Statistics for debug memory tracking only */
- u32 total_allocated;
- u32 total_freed;
- u32 current_total_size;
- u32 cache_requests;
- u32 cache_hits;
- char *list_name;
+ u32 total_allocated;
+ u32 total_freed;
+ u32 current_total_size;
+ u32 requests;
+ u32 hits;
#endif
};
-
-#endif /* __ACLOCAL_H__ */
+#endif /* __ACLOCAL_H__ */
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 09be937d2c39..702cc4e57f5f 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -44,7 +44,6 @@
#ifndef __ACMACROS_H__
#define __ACMACROS_H__
-
/*
* Data manipulation macros
*/
@@ -57,7 +56,6 @@
#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
-
#if ACPI_MACHINE_WIDTH == 16
/*
@@ -168,7 +166,7 @@
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
@@ -183,9 +181,9 @@
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[7];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[6];\
@@ -219,14 +217,14 @@
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d,s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s)
#define ACPI_MOVE_32_TO_64(d,s) ACPI_MOVE_32_TO_32(d,s)
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d,s) ACPI_MOVE_32_TO_32(d,s)
#else
@@ -238,14 +236,14 @@
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d,s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s)
#define ACPI_MOVE_32_TO_64(d,s) *(u64 *)(void *)(d) = *(u32 *)(void *)(s)
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d,s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s)
#endif
@@ -266,7 +264,7 @@
/* 32-bit source, 16/32/64 destination */
-#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
@@ -277,8 +275,8 @@
/* 64-bit source, 16/32/64 destination */
-#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
-#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
+#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */
+#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d,s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\
@@ -305,7 +303,6 @@
#error unknown ACPI_MACHINE_WIDTH
#endif
-
/*
* Fast power-of-two math macros for non-optimized compilers
*/
@@ -329,7 +326,6 @@
#define ACPI_MUL_16(a) _ACPI_MUL(a,4)
#define ACPI_MOD_16(a) _ACPI_MOD(a,16)
-
/*
* Rounding macros (Power of two boundaries only)
*/
@@ -344,7 +340,6 @@
#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_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7)
#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a))
@@ -365,7 +360,6 @@
#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
-
/* Bitfields within ACPI registers */
#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask)
@@ -381,7 +375,6 @@
#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)
-
/* Macro to test the object type */
#define ACPI_GET_OBJECT_TYPE(d) (((union acpi_operand_object *)(void *)(d))->common.type)
@@ -430,28 +423,28 @@
#define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F))
#define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH))
-
/*
* Reporting macros that are never compiled out
*/
#define ACPI_PARAM_LIST(pl) pl
/*
- * Error reporting. These versions add callers module and line#. Since
- * _THIS_MODULE gets compiled out when ACPI_DEBUG_OUTPUT isn't defined, only
- * use it in debug mode.
+ * Error reporting. These versions add callers module and line#.
+ *
+ * Since _acpi_module_name gets compiled out when ACPI_DEBUG_OUTPUT
+ * isn't defined, only use it in debug mode.
*/
#ifdef ACPI_DEBUG_OUTPUT
-#define ACPI_REPORT_INFO(fp) {acpi_ut_report_info(_THIS_MODULE,__LINE__,_COMPONENT); \
+#define ACPI_REPORT_INFO(fp) {acpi_ut_report_info(_acpi_module_name,__LINE__,_COMPONENT); \
acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_ERROR(fp) {acpi_ut_report_error(_THIS_MODULE,__LINE__,_COMPONENT); \
+#define ACPI_REPORT_ERROR(fp) {acpi_ut_report_error(_acpi_module_name,__LINE__,_COMPONENT); \
acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_WARNING(fp) {acpi_ut_report_warning(_THIS_MODULE,__LINE__,_COMPONENT); \
+#define ACPI_REPORT_WARNING(fp) {acpi_ut_report_warning(_acpi_module_name,__LINE__,_COMPONENT); \
acpi_os_printf ACPI_PARAM_LIST(fp);}
-#define ACPI_REPORT_NSERROR(s,e) acpi_ns_report_error(_THIS_MODULE,__LINE__,_COMPONENT, s, e);
+#define ACPI_REPORT_NSERROR(s,e) acpi_ns_report_error(_acpi_module_name,__LINE__,_COMPONENT, s, e);
-#define ACPI_REPORT_METHOD_ERROR(s,n,p,e) acpi_ns_report_method_error(_THIS_MODULE,__LINE__,_COMPONENT, s, n, p, e);
+#define ACPI_REPORT_METHOD_ERROR(s,n,p,e) acpi_ns_report_method_error(_acpi_module_name,__LINE__,_COMPONENT, s, n, p, e);
#else
@@ -480,36 +473,58 @@
* Debug macros that are conditionally compiled
*/
#ifdef ACPI_DEBUG_OUTPUT
+#define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_acpi_module_name = name;
-#define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_THIS_MODULE = name;
+/*
+ * Common parameters used for debug output functions:
+ * line number, function name, module(file) name, component ID
+ */
+#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _acpi_module_name, _COMPONENT
/*
- * Function entry tracing.
- * The first parameter should be the procedure name as a quoted string. This is declared
- * as a local string ("_proc_name) so that it can be also used by the function exit macros below.
+ * Function entry tracing
+ */
+
+/*
+ * If ACPI_GET_FUNCTION_NAME was not defined in the compiler-dependent header,
+ * define it now. This is the case where there the compiler does not support
+ * a __FUNCTION__ macro or equivalent. We save the function name on the
+ * local stack.
+ */
+#ifndef ACPI_GET_FUNCTION_NAME
+#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
+ * 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(a) struct acpi_debug_print_info _debug_info; \
- _debug_info.component_id = _COMPONENT; \
- _debug_info.proc_name = a; \
- _debug_info.module_name = _THIS_MODULE;
-
-#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace(__LINE__,&_debug_info)
-#define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_ptr(__LINE__,&_debug_info,(void *)b)
-#define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_u32(__LINE__,&_debug_info,(u32)b)
-#define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_str(__LINE__,&_debug_info,(char *)b)
-
-#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr()
+#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = name;
+
+#else
+/* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */
+
+#define ACPI_FUNCTION_NAME(name)
+#endif
+
+#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
+ 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)
+#define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \
+ 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)
+
+#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr()
/*
* Function exit tracing.
* 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 "_proc_name" is defined.
+ * so that "_acpi_function_name" is defined.
*/
#ifdef ACPI_USE_DO_WHILE_0
#define ACPI_DO_WHILE0(a) do a while(0)
@@ -517,10 +532,10 @@
#define ACPI_DO_WHILE0(a) a
#endif
-#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_debug_info);return;})
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_debug_info,(s));return((s));})
-#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_debug_info,(acpi_integer)(s));return((s));})
-#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_debug_info,(u8 *)(s));return((s));})
+#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(ACPI_DEBUG_PARAMETERS);return;})
+#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(ACPI_DEBUG_PARAMETERS,(s));return((s));})
+#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(ACPI_DEBUG_PARAMETERS,(acpi_integer)(s));return((s));})
+#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(ACPI_DEBUG_PARAMETERS,(u8 *)(s));return((s));})
/* Conditional execution */
@@ -531,12 +546,10 @@
#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
#define _VERBOSE_STRUCTURES
-
/* Stack and buffer dumping */
#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a),0)
-#define ACPI_DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__)
-
+#define ACPI_DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_acpi_module_name,__LINE__)
#define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b)
#define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d)
@@ -544,7 +557,6 @@
#define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT)
#define ACPI_BREAK_MSG(a) acpi_os_signal (ACPI_SIGNAL_BREAKPOINT,(a))
-
/*
* Generate INT3 on ACPI_ERROR (Debug only!)
*/
@@ -565,14 +577,13 @@
#define ACPI_DEBUG_PRINT(pl) acpi_ut_debug_print ACPI_PARAM_LIST(pl)
#define ACPI_DEBUG_PRINT_RAW(pl) acpi_ut_debug_print_raw ACPI_PARAM_LIST(pl)
-
#else
/*
* This is the non-debug case -- make everything go away,
* leaving no executable debug code!
*/
#define ACPI_MODULE_NAME(name)
-#define _THIS_MODULE ""
+#define _acpi_module_name ""
#define ACPI_DEBUG_EXEC(a)
#define ACPI_NORMAL_EXEC(a) a;
@@ -616,7 +627,6 @@
#define ACPI_DEBUGGER_EXEC(a)
#endif
-
/*
* For 16-bit code, we want to shrink some things even though
* we are using ACPI_DEBUG_OUTPUT to get the debug output
@@ -627,7 +637,6 @@
#define ACPI_DEBUG_ONLY_MEMBERS(a)
#endif
-
#ifdef ACPI_DEBUG_OUTPUT
/*
* 1) Set name to blanks
@@ -640,7 +649,6 @@
#define ACPI_ADD_OBJECT_NAME(a,b)
#endif
-
/*
* Memory allocation tracking (DEBUG ONLY)
*/
@@ -648,21 +656,20 @@
/* Memory allocation */
-#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_THIS_MODULE,__LINE__)
-#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate((acpi_size)(a), _COMPONENT,_THIS_MODULE,__LINE__)
+#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_MEM_TRACKING(a)
-
#else
/* Memory allocation */
-#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_THIS_MODULE,__LINE__)
-#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_THIS_MODULE,__LINE__)
-#define ACPI_MEM_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_THIS_MODULE,__LINE__)
+#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
-#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
-#endif /* ACMACROS_H */
+#endif /* ACMACROS_H */
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index deb7cb06f5f0..4f9063f3e951 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -71,14 +71,13 @@
/* Definitions of the predefined namespace names */
-#define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */
-#define ACPI_ROOT_NAME (u32) 0x5F5F5F5C /* Root name is "\___" */
-#define ACPI_SYS_BUS_NAME (u32) 0x5F53425F /* Sys bus name is "_SB_" */
+#define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */
+#define ACPI_ROOT_NAME (u32) 0x5F5F5F5C /* Root name is "\___" */
+
+#define ACPI_PREFIX_MIXED (u32) 0x69706341 /* "Acpi" */
+#define ACPI_PREFIX_LOWER (u32) 0x69706361 /* "acpi" */
#define ACPI_NS_ROOT_PATH "\\"
#define ACPI_NS_SYSTEM_BUS "_SB_"
-
-#endif /* __ACNAMES_H__ */
-
-
+#endif /* __ACNAMES_H__ */
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index d1b3ce80056f..dd3501f7e5d6 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -44,7 +44,6 @@
#ifndef __ACNAMESP_H__
#define __ACNAMESP_H__
-
/* To search the entire name space, pass this as search_base */
#define ACPI_NS_ALL ((acpi_handle)0)
@@ -54,8 +53,8 @@
* and should be one-to-one with values of acpi_object_type
*/
#define ACPI_NS_NORMAL 0
-#define ACPI_NS_NEWSCOPE 1 /* a definition of this type opens a name scope */
-#define ACPI_NS_LOCAL 2 /* suppress search of enclosing scopes */
+#define ACPI_NS_NEWSCOPE 1 /* a definition of this type opens a name scope */
+#define ACPI_NS_LOCAL 2 /* suppress search of enclosing scopes */
/* Flags for acpi_ns_lookup, acpi_ns_search_and_enter */
@@ -68,357 +67,237 @@
#define ACPI_NS_WALK_UNLOCK TRUE
#define ACPI_NS_WALK_NO_UNLOCK FALSE
-
/*
* nsinit - Namespace initialization
*/
-acpi_status
-acpi_ns_initialize_objects (
- void);
-
-acpi_status
-acpi_ns_initialize_devices (
- void);
+acpi_status acpi_ns_initialize_objects(void);
+acpi_status acpi_ns_initialize_devices(void);
/*
* nsload - Namespace loading
*/
-acpi_status
-acpi_ns_load_namespace (
- void);
+acpi_status acpi_ns_load_namespace(void);
acpi_status
-acpi_ns_load_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *node);
-
+acpi_ns_load_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *node);
/*
* nswalk - walk the namespace
*/
acpi_status
-acpi_ns_walk_namespace (
- acpi_object_type type,
- acpi_handle start_object,
- u32 max_depth,
- u8 unlock_before_callback,
- acpi_walk_callback user_function,
- void *context,
- void **return_value);
-
-struct acpi_namespace_node *
-acpi_ns_get_next_node (
- acpi_object_type type,
- struct acpi_namespace_node *parent,
- struct acpi_namespace_node *child);
-
+acpi_ns_walk_namespace(acpi_object_type type,
+ acpi_handle start_object,
+ u32 max_depth,
+ u8 unlock_before_callback,
+ acpi_walk_callback user_function,
+ void *context, void **return_value);
+
+struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
+ struct acpi_namespace_node
+ *parent,
+ struct acpi_namespace_node
+ *child);
/*
* nsparse - table parsing
*/
acpi_status
-acpi_ns_parse_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *scope);
+acpi_ns_parse_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *scope);
acpi_status
-acpi_ns_one_complete_parse (
- u32 pass_number,
- struct acpi_table_desc *table_desc);
-
+acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc);
/*
* nsaccess - Top-level namespace access
*/
-acpi_status
-acpi_ns_root_initialize (
- void);
+acpi_status acpi_ns_root_initialize(void);
acpi_status
-acpi_ns_lookup (
- union acpi_generic_state *scope_info,
- char *name,
- acpi_object_type type,
- acpi_interpreter_mode interpreter_mode,
- u32 flags,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **ret_node);
-
+acpi_ns_lookup(union acpi_generic_state *scope_info,
+ char *name,
+ acpi_object_type type,
+ acpi_interpreter_mode interpreter_mode,
+ u32 flags,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **ret_node);
/*
* nsalloc - Named object allocation/deallocation
*/
-struct acpi_namespace_node *
-acpi_ns_create_node (
- u32 name);
-
-void
-acpi_ns_delete_node (
- struct acpi_namespace_node *node);
+struct acpi_namespace_node *acpi_ns_create_node(u32 name);
-void
-acpi_ns_delete_namespace_subtree (
- struct acpi_namespace_node *parent_handle);
+void acpi_ns_delete_node(struct acpi_namespace_node *node);
void
-acpi_ns_delete_namespace_by_owner (
- u16 table_id);
+acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle);
-void
-acpi_ns_detach_object (
- struct acpi_namespace_node *node);
+void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id);
-void
-acpi_ns_delete_children (
- struct acpi_namespace_node *parent);
+void acpi_ns_detach_object(struct acpi_namespace_node *node);
-int
-acpi_ns_compare_names (
- char *name1,
- char *name2);
+void acpi_ns_delete_children(struct acpi_namespace_node *parent);
+int acpi_ns_compare_names(char *name1, char *name2);
/*
* nsdump - Namespace dump/print utilities
*/
#ifdef ACPI_FUTURE_USAGE
-void
-acpi_ns_dump_tables (
- acpi_handle search_base,
- u32 max_depth);
-#endif /* ACPI_FUTURE_USAGE */
+void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth);
+#endif /* ACPI_FUTURE_USAGE */
-void
-acpi_ns_dump_entry (
- acpi_handle handle,
- u32 debug_level);
+void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level);
void
-acpi_ns_dump_pathname (
- acpi_handle handle,
- char *msg,
- u32 level,
- u32 component);
+acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component);
-void
-acpi_ns_print_pathname (
- u32 num_segments,
- char *pathname);
+void acpi_ns_print_pathname(u32 num_segments, char *pathname);
acpi_status
-acpi_ns_dump_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ns_dump_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
#ifdef ACPI_FUTURE_USAGE
void
-acpi_ns_dump_objects (
- acpi_object_type type,
- u8 display_type,
- u32 max_depth,
- u32 ownder_id,
- acpi_handle start_handle);
-#endif /* ACPI_FUTURE_USAGE */
-
+acpi_ns_dump_objects(acpi_object_type type,
+ u8 display_type,
+ u32 max_depth,
+ acpi_owner_id owner_id, acpi_handle start_handle);
+#endif /* ACPI_FUTURE_USAGE */
/*
* nseval - Namespace evaluation functions
*/
-acpi_status
-acpi_ns_evaluate_by_handle (
- struct acpi_parameter_info *info);
+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_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_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info);
/*
* nsnames - Name and Scope manipulation
*/
-u32
-acpi_ns_opens_scope (
- acpi_object_type type);
+u32 acpi_ns_opens_scope(acpi_object_type type);
-char *
-acpi_ns_get_external_pathname (
- struct acpi_namespace_node *node);
+char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node);
-char *
-acpi_ns_name_of_current_scope (
- struct acpi_walk_state *walk_state);
+char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ns_handle_to_pathname (
- acpi_handle target_handle,
- struct acpi_buffer *buffer);
+acpi_ns_handle_to_pathname(acpi_handle target_handle,
+ struct acpi_buffer *buffer);
u8
-acpi_ns_pattern_match (
- struct acpi_namespace_node *obj_node,
- char *search_for);
+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_size
-acpi_ns_get_pathname_length (
- struct acpi_namespace_node *node);
+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_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node);
/*
* nsobject - Object management for namespace nodes
*/
acpi_status
-acpi_ns_attach_object (
- struct acpi_namespace_node *node,
- union acpi_operand_object *object,
- acpi_object_type type);
+acpi_ns_attach_object(struct acpi_namespace_node *node,
+ union acpi_operand_object *object, acpi_object_type type);
-union acpi_operand_object *
-acpi_ns_get_attached_object (
- struct acpi_namespace_node *node);
+union acpi_operand_object *acpi_ns_get_attached_object(struct
+ acpi_namespace_node
+ *node);
-union acpi_operand_object *
-acpi_ns_get_secondary_object (
- union acpi_operand_object *obj_desc);
+union acpi_operand_object *acpi_ns_get_secondary_object(union
+ acpi_operand_object
+ *obj_desc);
acpi_status
-acpi_ns_attach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void *data);
+acpi_ns_attach_data(struct acpi_namespace_node *node,
+ acpi_object_handler handler, void *data);
acpi_status
-acpi_ns_detach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler);
+acpi_ns_detach_data(struct acpi_namespace_node *node,
+ acpi_object_handler handler);
acpi_status
-acpi_ns_get_attached_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void **data);
-
+acpi_ns_get_attached_data(struct acpi_namespace_node *node,
+ acpi_object_handler handler, void **data);
/*
* nssearch - Namespace searching and entry
*/
acpi_status
-acpi_ns_search_and_enter (
- u32 entry_name,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- acpi_interpreter_mode interpreter_mode,
- acpi_object_type type,
- u32 flags,
- struct acpi_namespace_node **ret_node);
+acpi_ns_search_and_enter(u32 entry_name,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ acpi_interpreter_mode interpreter_mode,
+ acpi_object_type type,
+ 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_node(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,
- struct acpi_namespace_node *parent_node,
- struct acpi_namespace_node *node,
- acpi_object_type type);
-
+acpi_ns_install_node(struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *parent_node,
+ struct acpi_namespace_node *node, acpi_object_type type);
/*
* nsutils - Utility functions
*/
-u8
-acpi_ns_valid_root_prefix (
- char prefix);
+u8 acpi_ns_valid_root_prefix(char prefix);
-acpi_object_type
-acpi_ns_get_type (
- struct acpi_namespace_node *node);
+acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node);
-u32
-acpi_ns_local (
- acpi_object_type type);
+u32 acpi_ns_local(acpi_object_type type);
void
-acpi_ns_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *internal_name,
- acpi_status lookup_status);
+acpi_ns_report_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *internal_name, acpi_status lookup_status);
void
-acpi_ns_report_method_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *message,
- struct acpi_namespace_node *node,
- char *path,
- acpi_status lookup_status);
+acpi_ns_report_method_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *message,
+ struct acpi_namespace_node *node,
+ char *path, acpi_status lookup_status);
-void
-acpi_ns_print_node_pathname (
- struct acpi_namespace_node *node,
- char *msg);
+void acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *msg);
-acpi_status
-acpi_ns_build_internal_name (
- struct acpi_namestring_info *info);
+acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info);
-void
-acpi_ns_get_internal_name_length (
- struct acpi_namestring_info *info);
+void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info);
-acpi_status
-acpi_ns_internalize_name (
- char *dotted_name,
- char **converted_name);
+acpi_status acpi_ns_internalize_name(char *dotted_name, char **converted_name);
acpi_status
-acpi_ns_externalize_name (
- u32 internal_name_length,
- char *internal_name,
- u32 *converted_name_length,
- char **converted_name);
+acpi_ns_externalize_name(u32 internal_name_length,
+ char *internal_name,
+ u32 * converted_name_length, char **converted_name);
-struct acpi_namespace_node *
-acpi_ns_map_handle_to_node (
- acpi_handle handle);
+struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle);
-acpi_handle
-acpi_ns_convert_entry_to_handle(
- struct acpi_namespace_node *node);
-
-void
-acpi_ns_terminate (
- void);
+acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node);
-struct acpi_namespace_node *
-acpi_ns_get_parent_node (
- struct acpi_namespace_node *node);
+void acpi_ns_terminate(void);
+struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node
+ *node);
-struct acpi_namespace_node *
-acpi_ns_get_next_valid_node (
- struct acpi_namespace_node *node);
+struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct
+ acpi_namespace_node
+ *node);
-#endif /* __ACNAMESP_H__ */
+#endif /* __ACNAMESP_H__ */
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index e079b94e4fce..4a326ba6d482 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -45,7 +45,6 @@
#ifndef _ACOBJECT_H
#define _ACOBJECT_H
-
/*
* 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
@@ -81,7 +80,6 @@
#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
@@ -96,8 +94,7 @@
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 */
-
+ struct acpi_namespace_node *node; /* Link back to parent node */
/*
* Fields common to both Strings and Buffers
@@ -105,15 +102,13 @@
#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 */
-
+ union acpi_operand_object *handler; /* Handler for Address space */
/******************************************************************************
*
@@ -121,161 +116,110 @@
*
*****************************************************************************/
-struct acpi_object_common
-{
- ACPI_OBJECT_COMMON_HEADER
-};
+struct acpi_object_common {
+ACPI_OBJECT_COMMON_HEADER};
-
-struct acpi_object_integer
-{
- ACPI_OBJECT_COMMON_HEADER
- acpi_integer value;
+struct acpi_object_integer {
+ ACPI_OBJECT_COMMON_HEADER acpi_integer value;
};
-
/*
* Note: The String and Buffer object must be identical through the Pointer
* element. There is code that depends on this.
*/
-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 */
+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 */
};
-
-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;
- u32 aml_length;
+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;
+ u32 aml_length;
};
-
-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 */
- union acpi_operand_object **elements; /* Array of pointers to acpi_objects */
+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 */
+ union acpi_operand_object **elements; /* Array of pointers to acpi_objects */
};
-
/******************************************************************************
*
* Complex data types
*
*****************************************************************************/
-struct acpi_object_event
-{
- ACPI_OBJECT_COMMON_HEADER
- void *semaphore;
+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 owning_id;
+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 */
- struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
- void *semaphore; /* Actual OS synchronization object */
- union acpi_operand_object *prev; /* Link for list of acquired mutexes */
- union acpi_operand_object *next; /* Link for list of acquired mutexes */
- struct acpi_namespace_node *node; /* Containing namespace node */
- u8 original_sync_level; /* Owner's original sync level (0-15) */
+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 */
+ struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+ void *semaphore; /* Actual OS synchronization object */
+ union acpi_operand_object *prev; /* Link for list of acquired mutexes */
+ union acpi_operand_object *next; /* Link for list of acquired mutexes */
+ struct acpi_namespace_node *node; /* Containing namespace node */
+ u8 original_sync_level; /* Owner's original sync level (0-15) */
};
-
-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 *next;
- u32 length;
- acpi_physical_address address;
+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 *next;
+ u32 length;
+ acpi_physical_address address;
};
-
/******************************************************************************
*
* Objects that can be notified. All share a common notify_info area.
*
*****************************************************************************/
-struct acpi_object_notify_common /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_NOTIFY_INFO
-};
-
-
-struct acpi_object_device
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_NOTIFY_INFO
- struct acpi_gpe_block_info *gpe_block;
-};
-
+struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
+ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
-struct acpi_object_power_resource
-{
+struct acpi_object_device {
ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_NOTIFY_INFO
- u32 system_level;
- u32 resource_order;
+ ACPI_COMMON_NOTIFY_INFO struct acpi_gpe_block_info *gpe_block;
};
-
-struct acpi_object_processor
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_NOTIFY_INFO
- u32 proc_id;
- u32 length;
- acpi_io_address address;
+struct acpi_object_power_resource {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 system_level;
+ u32 resource_order;
};
-
-struct acpi_object_thermal_zone
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_NOTIFY_INFO
+struct acpi_object_processor {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 proc_id;
+ u32 length;
+ acpi_io_address address;
};
+struct acpi_object_thermal_zone {
+ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
/******************************************************************************
*
@@ -283,90 +227,63 @@ struct acpi_object_thermal_zone
*
*****************************************************************************/
-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) */
+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) */
};
-
-struct acpi_object_region_field
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_FIELD_INFO
- union acpi_operand_object *region_obj; /* Containing op_region object */
+struct acpi_object_region_field {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */
};
-
-struct acpi_object_bank_field
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_FIELD_INFO
- union acpi_operand_object *region_obj; /* Containing op_region object */
- union acpi_operand_object *bank_obj; /* bank_select Register object */
+struct acpi_object_bank_field {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */
+ union acpi_operand_object *bank_obj; /* bank_select Register object */
};
-
-struct acpi_object_index_field
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_FIELD_INFO
-
- /*
- * No "region_obj" pointer needed since the Index and Data registers
- * are each field definitions unto themselves.
- */
- union acpi_operand_object *index_obj; /* Index register */
- union acpi_operand_object *data_obj; /* Data register */
+struct acpi_object_index_field {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO
+ /*
+ * No "region_obj" pointer needed since the Index and Data registers
+ * are each field definitions unto themselves.
+ */
+ union acpi_operand_object *index_obj; /* Index register */
+ union acpi_operand_object *data_obj; /* Data register */
};
-
/* The buffer_field is different in that it is part of a Buffer, not an op_region */
-struct acpi_object_buffer_field
-{
- ACPI_OBJECT_COMMON_HEADER
- ACPI_COMMON_FIELD_INFO
- union acpi_operand_object *buffer_obj; /* Containing Buffer object */
+struct acpi_object_buffer_field {
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *buffer_obj; /* Containing Buffer object */
};
-
/******************************************************************************
*
* Objects for handlers
*
*****************************************************************************/
-struct acpi_object_notify_handler
-{
- ACPI_OBJECT_COMMON_HEADER
- struct acpi_namespace_node *node; /* Parent device */
- acpi_notify_handler handler;
- void *context;
+struct acpi_object_notify_handler {
+ ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */
+ acpi_notify_handler 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;
- acpi_adr_space_handler handler;
- struct acpi_namespace_node *node; /* Parent device */
- void *context;
- acpi_adr_space_setup setup;
- union acpi_operand_object *region_list; /* regions using this handler */
- union acpi_operand_object *next;
+struct acpi_object_addr_handler {
+ ACPI_OBJECT_COMMON_HEADER u8 space_id;
+ u16 hflags;
+ acpi_adr_space_handler handler;
+ struct acpi_namespace_node *node; /* Parent device */
+ void *context;
+ acpi_adr_space_setup setup;
+ union acpi_operand_object *region_list; /* regions using this handler */
+ union acpi_operand_object *next;
};
-
/******************************************************************************
*
* Special internal objects
@@ -377,18 +294,15 @@ struct acpi_object_addr_handler
* The Reference object type is used for these opcodes:
* Arg[0-6], Local[0-7], index_op, name_op, zero_op, one_op, ones_op, debug_op
*/
-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 */
- struct acpi_namespace_node *node;
- union acpi_operand_object **where;
+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 */
+ struct acpi_namespace_node *node;
+ union acpi_operand_object **where;
};
-
/*
* Extra object is used as additional storage for types that
* have AML code in their declarations (term_args) that must be
@@ -396,73 +310,62 @@ 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) */
- void *region_context; /* Region-specific data */
+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) */
+ void *region_context; /* Region-specific data */
};
-
/* Additional data that can be attached to namespace nodes */
-struct acpi_object_data
-{
- ACPI_OBJECT_COMMON_HEADER
- acpi_object_handler handler;
- void *pointer;
+struct acpi_object_data {
+ ACPI_OBJECT_COMMON_HEADER acpi_object_handler handler;
+ void *pointer;
};
-
/* Structure used when objects are cached for reuse */
-struct acpi_object_cache_list
-{
- ACPI_OBJECT_COMMON_HEADER
- union acpi_operand_object *next; /* Link for object cache and internal lists*/
+struct acpi_object_cache_list {
+ ACPI_OBJECT_COMMON_HEADER union acpi_operand_object *next; /* Link for object cache and internal lists */
};
-
/******************************************************************************
*
* union acpi_operand_object Descriptor - a giant union of all of the above
*
*****************************************************************************/
-union acpi_operand_object
-{
- struct acpi_object_common common;
- struct acpi_object_integer integer;
- struct acpi_object_string string;
- struct acpi_object_buffer buffer;
- struct acpi_object_package package;
- struct acpi_object_event event;
- struct acpi_object_method method;
- struct acpi_object_mutex mutex;
- struct acpi_object_region region;
- struct acpi_object_notify_common common_notify;
- struct acpi_object_device device;
- struct acpi_object_power_resource power_resource;
- struct acpi_object_processor processor;
- struct acpi_object_thermal_zone thermal_zone;
- struct acpi_object_field_common common_field;
- struct acpi_object_region_field field;
- struct acpi_object_buffer_field buffer_field;
- struct acpi_object_bank_field bank_field;
- struct acpi_object_index_field index_field;
- struct acpi_object_notify_handler notify;
- struct acpi_object_addr_handler address_space;
- struct acpi_object_reference reference;
- struct acpi_object_extra extra;
- struct acpi_object_data data;
- struct acpi_object_cache_list cache;
+union acpi_operand_object {
+ struct acpi_object_common common;
+ struct acpi_object_integer integer;
+ struct acpi_object_string string;
+ struct acpi_object_buffer buffer;
+ struct acpi_object_package package;
+ struct acpi_object_event event;
+ struct acpi_object_method method;
+ struct acpi_object_mutex mutex;
+ struct acpi_object_region region;
+ struct acpi_object_notify_common common_notify;
+ struct acpi_object_device device;
+ struct acpi_object_power_resource power_resource;
+ struct acpi_object_processor processor;
+ struct acpi_object_thermal_zone thermal_zone;
+ struct acpi_object_field_common common_field;
+ struct acpi_object_region_field field;
+ struct acpi_object_buffer_field buffer_field;
+ struct acpi_object_bank_field bank_field;
+ struct acpi_object_index_field index_field;
+ struct acpi_object_notify_handler notify;
+ struct acpi_object_addr_handler address_space;
+ struct acpi_object_reference reference;
+ struct acpi_object_extra extra;
+ struct acpi_object_data data;
+ struct acpi_object_cache_list cache;
};
-
/******************************************************************************
*
* union acpi_descriptor - objects that share a common descriptor identifier
@@ -471,7 +374,7 @@ union acpi_operand_object
/* Object descriptor types */
-#define ACPI_DESC_TYPE_CACHED 0x01 /* Used only when object is cached */
+#define ACPI_DESC_TYPE_CACHED 0x01 /* Used only when object is cached */
#define ACPI_DESC_TYPE_STATE 0x02
#define ACPI_DESC_TYPE_STATE_UPDATE 0x03
#define ACPI_DESC_TYPE_STATE_PACKAGE 0x04
@@ -488,14 +391,11 @@ union acpi_operand_object
#define ACPI_DESC_TYPE_NAMED 0x0F
#define ACPI_DESC_TYPE_MAX 0x0F
-
-union acpi_descriptor
-{
- u8 descriptor_id; /* To differentiate various internal objs */\
- union acpi_operand_object object;
- struct acpi_namespace_node node;
- union acpi_parse_object op;
+union acpi_descriptor {
+ u8 descriptor_id; /* To differentiate various internal objs */
+ union acpi_operand_object object;
+ struct acpi_namespace_node node;
+ union acpi_parse_object op;
};
-
-#endif /* _ACOBJECT_H */
+#endif /* _ACOBJECT_H */
diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h
index 118ecba4cf05..64da42992199 100644
--- a/include/acpi/acopcode.h
+++ b/include/acpi/acopcode.h
@@ -62,7 +62,6 @@
#define _NAM 0x6C
#define _PFX 0x6D
-
/*
* All AML opcodes and the parse-time arguments for each. Used by the AML
* parser Each list is compressed into a 32-bit number and stored in the
@@ -191,7 +190,6 @@
#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA)
#define ARGP_ZERO_OP ARG_NONE
-
/*
* All AML opcodes and the runtime arguments for each. Used by the AML
* interpreter Each list is compressed into a 32-bit number and stored
@@ -246,7 +244,7 @@
#define ARGI_FIELD_OP ARGI_INVALID_OPCODE
#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
-#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_IF_OP ARGI_INVALID_OPCODE
#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE
@@ -322,4 +320,4 @@
#define ARGI_WORD_OP ARGI_INVALID_OPCODE
#define ARGI_ZERO_OP ARG_NONE
-#endif /* __ACOPCODE_H__ */
+#endif /* __ACOPCODE_H__ */
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 2fbe180fee6b..68d7edf0f697 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -73,12 +73,10 @@
#define ACPI_ALL_COMPONENTS 0x00003FFF
#define ACPI_COMPONENT_DEFAULT (ACPI_ALL_COMPONENTS)
-
/* Component IDs reserved for ACPI drivers */
#define ACPI_ALL_DRIVERS 0xFFFF0000
-
/*
* Raw debug output levels, do not use these in the DEBUG_PRINT macros
*/
@@ -132,11 +130,10 @@
#define ACPI_LV_VERBOSE 0xF0000000
-
/*
* Debug level macros that are used in the DEBUG_PRINT macros
*/
-#define ACPI_DEBUG_LEVEL(dl) (u32) dl,__LINE__,&_debug_info
+#define ACPI_DEBUG_LEVEL(dl) (u32) dl,ACPI_DEBUG_PARAMETERS
/* Exception level -- used in the global "debug_level" */
@@ -147,7 +144,6 @@
#define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO)
#define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS)
-
/* Trace level -- also used in the global "debug_level" */
#define ACPI_DB_INIT_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES)
@@ -174,12 +170,10 @@
#define ACPI_DB_ALL ACPI_DEBUG_LEVEL (ACPI_LV_ALL)
-
/* Defaults for debug_level, debug and normal */
#define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
#define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
-
-#endif /* __ACOUTPUT_H__ */
+#endif /* __ACOUTPUT_H__ */
diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
index 698276571818..d352d40de1f3 100644
--- a/include/acpi/acparser.h
+++ b/include/acpi/acparser.h
@@ -41,18 +41,15 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#ifndef __ACPARSER_H__
#define __ACPARSER_H__
-
#define OP_HAS_RETURN_VALUE 1
/* variable # arguments */
#define ACPI_VAR_ARGS ACPI_UINT32_MAX
-
#define ACPI_PARSE_DELETE_TREE 0x0001
#define ACPI_PARSE_NO_TREE_DELETE 0x0000
#define ACPI_PARSE_TREE_MASK 0x0001
@@ -63,7 +60,7 @@
#define ACPI_PARSE_MODE_MASK 0x0030
#define ACPI_PARSE_DEFERRED_OP 0x0100
-
+#define ACPI_PARSE_DISASSEMBLE 0x0200
/******************************************************************************
*
@@ -71,251 +68,165 @@
*
*****************************************************************************/
-
/*
* psxface - Parser external interfaces
*/
-acpi_status
-acpi_psx_load_table (
- u8 *pcode_addr,
- u32 pcode_length);
-
-acpi_status
-acpi_psx_execute (
- struct acpi_parameter_info *info);
-
+acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info);
/*
* psargs - Parse AML opcode arguments
*/
-u8 *
-acpi_ps_get_next_package_end (
- struct acpi_parse_state *parser_state);
+u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state);
-char *
-acpi_ps_get_next_namestring (
- struct acpi_parse_state *parser_state);
+char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state);
void
-acpi_ps_get_next_simple_arg (
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object *arg);
+acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object *arg);
acpi_status
-acpi_ps_get_next_namepath (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *arg,
- u8 method_call);
+acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ union acpi_parse_object *arg, u8 method_call);
acpi_status
-acpi_ps_get_next_arg (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object **return_arg);
-
+acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object **return_arg);
/*
* psfind
*/
-union acpi_parse_object *
-acpi_ps_find_name (
- union acpi_parse_object *scope,
- u32 name,
- u32 opcode);
-
-union acpi_parse_object*
-acpi_ps_get_parent (
- union acpi_parse_object *op);
+union acpi_parse_object *acpi_ps_find_name(union acpi_parse_object *scope,
+ u32 name, u32 opcode);
+union acpi_parse_object *acpi_ps_get_parent(union acpi_parse_object *op);
/*
* psopcode - AML Opcode information
*/
-const struct acpi_opcode_info *
-acpi_ps_get_opcode_info (
- u16 opcode);
-
-char *
-acpi_ps_get_opcode_name (
- u16 opcode);
+const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
+char *acpi_ps_get_opcode_name(u16 opcode);
/*
* psparse - top level parsing routines
*/
-acpi_status
-acpi_ps_parse_aml (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state);
-u32
-acpi_ps_get_opcode_size (
- u32 opcode);
+u32 acpi_ps_get_opcode_size(u32 opcode);
-u16
-acpi_ps_peek_opcode (
- struct acpi_parse_state *state);
+u16 acpi_ps_peek_opcode(struct acpi_parse_state *state);
+acpi_status
+acpi_ps_complete_this_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+
+acpi_status
+acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ acpi_status callback_status);
+
+/*
+ * psloop - main parse loop
+ */
+acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state);
/*
* psscope - Scope stack management routines
*/
acpi_status
-acpi_ps_init_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *root);
+acpi_ps_init_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object *root);
-union acpi_parse_object *
-acpi_ps_get_parent_scope (
- struct acpi_parse_state *state);
+union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
+ *state);
-u8
-acpi_ps_has_completed_scope (
- struct acpi_parse_state *parser_state);
+u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state);
void
-acpi_ps_pop_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object **op,
- u32 *arg_list,
- u32 *arg_count);
+acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object **op,
+ u32 * arg_list, u32 * arg_count);
acpi_status
-acpi_ps_push_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *op,
- u32 remaining_args,
- u32 arg_count);
-
-void
-acpi_ps_cleanup_scope (
- struct acpi_parse_state *state);
+acpi_ps_push_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object *op,
+ u32 remaining_args, u32 arg_count);
+void acpi_ps_cleanup_scope(struct acpi_parse_state *state);
/*
* pstree - parse tree manipulation routines
*/
void
-acpi_ps_append_arg(
- union acpi_parse_object *op,
- union acpi_parse_object *arg);
-
-union acpi_parse_object*
-acpi_ps_find (
- union acpi_parse_object *scope,
- char *path,
- u16 opcode,
- u32 create);
-
-union acpi_parse_object *
-acpi_ps_get_arg(
- union acpi_parse_object *op,
- u32 argn);
+acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg);
-#ifdef ACPI_FUTURE_USAGE
-union acpi_parse_object *
-acpi_ps_get_depth_next (
- union acpi_parse_object *origin,
- union acpi_parse_object *op);
-#endif /* ACPI_FUTURE_USAGE */
+union acpi_parse_object *acpi_ps_find(union acpi_parse_object *scope,
+ char *path, u16 opcode, u32 create);
+union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn);
+
+#ifdef ACPI_FUTURE_USAGE
+union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
+ union acpi_parse_object *op);
+#endif /* ACPI_FUTURE_USAGE */
/*
* pswalk - parse tree walk routines
*/
acpi_status
-acpi_ps_walk_parsed_aml (
- union acpi_parse_object *start_op,
- union acpi_parse_object *end_op,
- union acpi_operand_object *mth_desc,
- struct acpi_namespace_node *start_node,
- union acpi_operand_object **params,
- union acpi_operand_object **caller_return_desc,
- acpi_owner_id owner_id,
- acpi_parse_downwards descending_callback,
- acpi_parse_upwards ascending_callback);
-
-acpi_status
-acpi_ps_get_next_walk_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_parse_upwards ascending_callback);
+acpi_ps_walk_parsed_aml(union acpi_parse_object *start_op,
+ union acpi_parse_object *end_op,
+ union acpi_operand_object *mth_desc,
+ struct acpi_namespace_node *start_node,
+ union acpi_operand_object **params,
+ union acpi_operand_object **caller_return_desc,
+ acpi_owner_id owner_id,
+ acpi_parse_downwards descending_callback,
+ acpi_parse_upwards ascending_callback);
acpi_status
-acpi_ps_delete_completed_op (
- struct acpi_walk_state *walk_state);
+acpi_ps_get_next_walk_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ acpi_parse_upwards ascending_callback);
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *root);
+acpi_status acpi_ps_delete_completed_op(struct acpi_walk_state *walk_state);
+void acpi_ps_delete_parse_tree(union acpi_parse_object *root);
/*
* psutils - parser utilities
*/
-union acpi_parse_object *
-acpi_ps_create_scope_op (
- void);
+union acpi_parse_object *acpi_ps_create_scope_op(void);
-void
-acpi_ps_init_op (
- union acpi_parse_object *op,
- u16 opcode);
+void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode);
-union acpi_parse_object *
-acpi_ps_alloc_op (
- u16 opcode);
+union acpi_parse_object *acpi_ps_alloc_op(u16 opcode);
-void
-acpi_ps_free_op (
- union acpi_parse_object *op);
+void acpi_ps_free_op(union acpi_parse_object *op);
-u8
-acpi_ps_is_leading_char (
- u32 c);
+u8 acpi_ps_is_leading_char(u32 c);
-u8
-acpi_ps_is_prefix_char (
- u32 c);
+u8 acpi_ps_is_prefix_char(u32 c);
#ifdef ACPI_FUTURE_USAGE
-u32
-acpi_ps_get_name(
- union acpi_parse_object *op);
-#endif /* ACPI_FUTURE_USAGE */
-
-void
-acpi_ps_set_name(
- union acpi_parse_object *op,
- u32 name);
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-void
-acpi_ps_delete_parse_cache (
- void);
-#endif
+u32 acpi_ps_get_name(union acpi_parse_object *op);
+#endif /* ACPI_FUTURE_USAGE */
+void acpi_ps_set_name(union acpi_parse_object *op, u32 name);
/*
* psdump - display parser tree
*/
u32
-acpi_ps_sprint_path (
- char *buffer_start,
- u32 buffer_size,
- union acpi_parse_object *op);
+acpi_ps_sprint_path(char *buffer_start,
+ u32 buffer_size, union acpi_parse_object *op);
u32
-acpi_ps_sprint_op (
- char *buffer_start,
- u32 buffer_size,
- union acpi_parse_object *op);
-
-void
-acpi_ps_show (
- union acpi_parse_object *op);
+acpi_ps_sprint_op(char *buffer_start,
+ u32 buffer_size, union acpi_parse_object *op);
+void acpi_ps_show(union acpi_parse_object *op);
-#endif /* __ACPARSER_H__ */
+#endif /* __ACPARSER_H__ */
diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h
index a69d78942040..ccf34f9dac64 100644
--- a/include/acpi/acpi.h
+++ b/include/acpi/acpi.h
@@ -49,22 +49,21 @@
* We put them here because we don't want to duplicate them
* in the rest of the source code again and again.
*/
-#include "acnames.h" /* Global ACPI names and strings */
-#include "acconfig.h" /* Configuration constants */
-#include "platform/acenv.h" /* Target environment specific items */
-#include "actypes.h" /* Fundamental common data types */
-#include "acexcep.h" /* ACPI exception codes */
-#include "acmacros.h" /* C macros */
-#include "actbl.h" /* ACPI table definitions */
-#include "aclocal.h" /* Internal data types */
-#include "acoutput.h" /* Error output and Debug macros */
-#include "acpiosxf.h" /* Interfaces to the ACPI-to-OS layer*/
-#include "acpixf.h" /* ACPI core subsystem external interfaces */
-#include "acobject.h" /* ACPI internal object */
-#include "acstruct.h" /* Common structures */
-#include "acglobal.h" /* All global variables */
-#include "achware.h" /* Hardware defines and interfaces */
-#include "acutils.h" /* Utility interfaces */
+#include "acnames.h" /* Global ACPI names and strings */
+#include "acconfig.h" /* Configuration constants */
+#include "platform/acenv.h" /* Target environment specific items */
+#include "actypes.h" /* Fundamental common data types */
+#include "acexcep.h" /* ACPI exception codes */
+#include "acmacros.h" /* C macros */
+#include "actbl.h" /* ACPI table definitions */
+#include "aclocal.h" /* Internal data types */
+#include "acoutput.h" /* Error output and Debug macros */
+#include "acpiosxf.h" /* Interfaces to the ACPI-to-OS layer */
+#include "acpixf.h" /* ACPI core subsystem external interfaces */
+#include "acobject.h" /* ACPI internal object */
+#include "acstruct.h" /* Common structures */
+#include "acglobal.h" /* All global variables */
+#include "achware.h" /* Hardware defines and interfaces */
+#include "acutils.h" /* Utility interfaces */
-
-#endif /* __ACPI_H__ */
+#endif /* __ACPI_H__ */
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8d0e1290bc76..0b54e9a4a8a1 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -35,48 +35,41 @@
/* TBD: Make dynamic */
#define ACPI_MAX_HANDLES 10
struct acpi_handle_list {
- u32 count;
- acpi_handle handles[ACPI_MAX_HANDLES];
+ u32 count;
+ acpi_handle handles[ACPI_MAX_HANDLES];
};
-
/* acpi_utils.h */
acpi_status
-acpi_extract_package (
- union acpi_object *package,
- struct acpi_buffer *format,
- struct acpi_buffer *buffer);
+acpi_extract_package(union acpi_object *package,
+ struct acpi_buffer *format, struct acpi_buffer *buffer);
acpi_status
-acpi_evaluate_integer (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- unsigned long *data);
+acpi_evaluate_integer(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments, unsigned long *data);
acpi_status
-acpi_evaluate_reference (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- struct acpi_handle_list *list);
-
+acpi_evaluate_reference(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments,
+ struct acpi_handle_list *list);
-#ifdef CONFIG_ACPI_BUS
+#ifdef CONFIG_ACPI
#include <linux/proc_fs.h>
#define ACPI_BUS_FILE_ROOT "acpi"
-extern struct proc_dir_entry *acpi_root_dir;
-extern FADT_DESCRIPTOR acpi_fadt;
+extern struct proc_dir_entry *acpi_root_dir;
+extern FADT_DESCRIPTOR acpi_fadt;
enum acpi_bus_removal_type {
- ACPI_BUS_REMOVAL_NORMAL = 0,
+ ACPI_BUS_REMOVAL_NORMAL = 0,
ACPI_BUS_REMOVAL_EJECT,
ACPI_BUS_REMOVAL_SUPRISE,
ACPI_BUS_REMOVAL_TYPE_COUNT
};
enum acpi_bus_device_type {
- ACPI_BUS_TYPE_DEVICE = 0,
+ ACPI_BUS_TYPE_DEVICE = 0,
ACPI_BUS_TYPE_POWER,
ACPI_BUS_TYPE_PROCESSOR,
ACPI_BUS_TYPE_THERMAL,
@@ -89,61 +82,60 @@ enum acpi_bus_device_type {
struct acpi_driver;
struct acpi_device;
-
/*
* ACPI Driver
* -----------
*/
-typedef int (*acpi_op_add) (struct acpi_device *device);
-typedef int (*acpi_op_remove) (struct acpi_device *device, int type);
-typedef int (*acpi_op_lock) (struct acpi_device *device, int type);
-typedef int (*acpi_op_start) (struct acpi_device *device);
-typedef int (*acpi_op_stop) (struct acpi_device *device, int type);
-typedef int (*acpi_op_suspend) (struct acpi_device *device, int state);
-typedef int (*acpi_op_resume) (struct acpi_device *device, int state);
-typedef int (*acpi_op_scan) (struct acpi_device *device);
-typedef int (*acpi_op_bind) (struct acpi_device *device);
-typedef int (*acpi_op_unbind) (struct acpi_device *device);
-typedef int (*acpi_op_match) (struct acpi_device *device,
- struct acpi_driver *driver);
+typedef int (*acpi_op_add) (struct acpi_device * device);
+typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
+typedef int (*acpi_op_lock) (struct acpi_device * device, int type);
+typedef int (*acpi_op_start) (struct acpi_device * device);
+typedef int (*acpi_op_stop) (struct acpi_device * device, int type);
+typedef int (*acpi_op_suspend) (struct acpi_device * device, int state);
+typedef int (*acpi_op_resume) (struct acpi_device * device, int state);
+typedef int (*acpi_op_scan) (struct acpi_device * device);
+typedef int (*acpi_op_bind) (struct acpi_device * device);
+typedef int (*acpi_op_unbind) (struct acpi_device * device);
+typedef int (*acpi_op_match) (struct acpi_device * device,
+ struct acpi_driver * driver);
struct acpi_bus_ops {
- u32 acpi_op_add:1;
- u32 acpi_op_remove:1;
- u32 acpi_op_lock:1;
- u32 acpi_op_start:1;
- u32 acpi_op_stop:1;
- u32 acpi_op_suspend:1;
- u32 acpi_op_resume:1;
- u32 acpi_op_scan:1;
- u32 acpi_op_bind:1;
- u32 acpi_op_unbind:1;
- u32 acpi_op_match:1;
- u32 reserved:21;
+ u32 acpi_op_add:1;
+ u32 acpi_op_remove:1;
+ u32 acpi_op_lock:1;
+ u32 acpi_op_start:1;
+ u32 acpi_op_stop:1;
+ u32 acpi_op_suspend:1;
+ u32 acpi_op_resume:1;
+ u32 acpi_op_scan:1;
+ u32 acpi_op_bind:1;
+ u32 acpi_op_unbind:1;
+ u32 acpi_op_match:1;
+ u32 reserved:21;
};
struct acpi_device_ops {
- acpi_op_add add;
- acpi_op_remove remove;
- acpi_op_lock lock;
- acpi_op_start start;
- acpi_op_stop stop;
- acpi_op_suspend suspend;
- acpi_op_resume resume;
- acpi_op_scan scan;
- acpi_op_bind bind;
- acpi_op_unbind unbind;
- acpi_op_match match;
+ acpi_op_add add;
+ acpi_op_remove remove;
+ acpi_op_lock lock;
+ acpi_op_start start;
+ acpi_op_stop stop;
+ acpi_op_suspend suspend;
+ acpi_op_resume resume;
+ acpi_op_scan scan;
+ acpi_op_bind bind;
+ acpi_op_unbind unbind;
+ acpi_op_match match;
};
struct acpi_driver {
- struct list_head node;
- char name[80];
- char class[80];
- atomic_t references;
- char *ids; /* Supported Hardware IDs */
- struct acpi_device_ops ops;
+ struct list_head node;
+ char name[80];
+ char class[80];
+ atomic_t references;
+ char *ids; /* Supported Hardware IDs */
+ struct acpi_device_ops ops;
};
/*
@@ -154,60 +146,57 @@ struct acpi_driver {
/* Status (_STA) */
struct acpi_device_status {
- u32 present:1;
- u32 enabled:1;
- u32 show_in_ui:1;
- u32 functional:1;
- u32 battery_present:1;
- u32 reserved:27;
+ u32 present:1;
+ u32 enabled:1;
+ u32 show_in_ui:1;
+ u32 functional:1;
+ u32 battery_present:1;
+ u32 reserved:27;
};
-
/* Flags */
struct acpi_device_flags {
- u32 dynamic_status:1;
- u32 hardware_id:1;
- u32 compatible_ids:1;
- u32 bus_address:1;
- u32 unique_id:1;
- u32 removable:1;
- u32 ejectable:1;
- u32 lockable:1;
- u32 suprise_removal_ok:1;
- u32 power_manageable:1;
- u32 performance_manageable:1;
- u32 wake_capable:1; /* Wakeup(_PRW) supported? */
- u32 reserved:20;
+ u32 dynamic_status:1;
+ u32 hardware_id:1;
+ u32 compatible_ids:1;
+ u32 bus_address:1;
+ u32 unique_id:1;
+ u32 removable:1;
+ u32 ejectable:1;
+ u32 lockable:1;
+ u32 suprise_removal_ok:1;
+ u32 power_manageable:1;
+ u32 performance_manageable:1;
+ u32 wake_capable:1; /* Wakeup(_PRW) supported? */
+ u32 reserved:20;
};
-
/* File System */
struct acpi_device_dir {
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
};
#define acpi_device_dir(d) ((d)->dir.entry)
-
/* Plug and Play */
-typedef char acpi_bus_id[5];
-typedef unsigned long acpi_bus_address;
-typedef char acpi_hardware_id[9];
-typedef char acpi_unique_id[9];
-typedef char acpi_device_name[40];
-typedef char acpi_device_class[20];
+typedef char acpi_bus_id[5];
+typedef unsigned long acpi_bus_address;
+typedef char acpi_hardware_id[9];
+typedef char acpi_unique_id[9];
+typedef char acpi_device_name[40];
+typedef char acpi_device_class[20];
struct acpi_device_pnp {
- acpi_bus_id bus_id; /* Object name */
- acpi_bus_address bus_address; /* _ADR */
- acpi_hardware_id hardware_id; /* _HID */
- struct acpi_compatible_id_list *cid_list; /* _CIDs */
- acpi_unique_id unique_id; /* _UID */
- acpi_device_name device_name; /* Driver-determined */
- acpi_device_class device_class; /* " */
+ acpi_bus_id bus_id; /* Object name */
+ acpi_bus_address bus_address; /* _ADR */
+ acpi_hardware_id hardware_id; /* _HID */
+ struct acpi_compatible_id_list *cid_list; /* _CIDs */
+ acpi_unique_id unique_id; /* _UID */
+ acpi_device_name device_name; /* Driver-determined */
+ acpi_device_class device_class; /* " */
};
#define acpi_device_bid(d) ((d)->pnp.bus_id)
@@ -217,114 +206,111 @@ struct acpi_device_pnp {
#define acpi_device_name(d) ((d)->pnp.device_name)
#define acpi_device_class(d) ((d)->pnp.device_class)
-
/* Power Management */
struct acpi_device_power_flags {
- u32 explicit_get:1; /* _PSC present? */
- u32 power_resources:1; /* Power resources */
- u32 inrush_current:1; /* Serialize Dx->D0 */
- u32 power_removed:1; /* Optimize Dx->D0 */
- u32 reserved:28;
+ u32 explicit_get:1; /* _PSC present? */
+ u32 power_resources:1; /* Power resources */
+ u32 inrush_current:1; /* Serialize Dx->D0 */
+ u32 power_removed:1; /* Optimize Dx->D0 */
+ u32 reserved:28;
};
struct acpi_device_power_state {
struct {
- u8 valid:1;
- u8 explicit_set:1; /* _PSx present? */
- u8 reserved:6;
- } flags;
- int power; /* % Power (compared to D0) */
- int latency; /* Dx->D0 time (microseconds) */
- struct acpi_handle_list resources; /* Power resources referenced */
+ u8 valid:1;
+ u8 explicit_set:1; /* _PSx present? */
+ u8 reserved:6;
+ } flags;
+ int power; /* % Power (compared to D0) */
+ int latency; /* Dx->D0 time (microseconds) */
+ struct acpi_handle_list resources; /* Power resources referenced */
};
struct acpi_device_power {
- int state; /* Current state */
+ int state; /* Current state */
struct acpi_device_power_flags flags;
- struct acpi_device_power_state states[4]; /* Power states (D0-D3) */
+ struct acpi_device_power_state states[4]; /* Power states (D0-D3) */
};
-
/* Performance Management */
struct acpi_device_perf_flags {
- u8 reserved:8;
+ u8 reserved:8;
};
struct acpi_device_perf_state {
struct {
- u8 valid:1;
- u8 reserved:7;
- } flags;
- u8 power; /* % Power (compared to P0) */
- u8 performance; /* % Performance ( " ) */
- int latency; /* Px->P0 time (microseconds) */
+ u8 valid:1;
+ u8 reserved:7;
+ } flags;
+ u8 power; /* % Power (compared to P0) */
+ u8 performance; /* % Performance ( " ) */
+ int latency; /* Px->P0 time (microseconds) */
};
struct acpi_device_perf {
- int state;
+ int state;
struct acpi_device_perf_flags flags;
- int state_count;
+ int state_count;
struct acpi_device_perf_state *states;
};
/* Wakeup Management */
struct acpi_device_wakeup_flags {
- u8 valid:1; /* Can successfully enable wakeup? */
- u8 run_wake:1; /* Run-Wake GPE devices */
+ u8 valid:1; /* Can successfully enable wakeup? */
+ u8 run_wake:1; /* Run-Wake GPE devices */
};
struct acpi_device_wakeup_state {
- u8 enabled:1;
- u8 active:1;
+ u8 enabled:1;
+ u8 active:1;
};
struct acpi_device_wakeup {
- acpi_handle gpe_device;
- acpi_integer gpe_number;;
- acpi_integer sleep_state;
- struct acpi_handle_list resources;
- struct acpi_device_wakeup_state state;
- struct acpi_device_wakeup_flags flags;
+ acpi_handle gpe_device;
+ acpi_integer gpe_number;;
+ acpi_integer sleep_state;
+ struct acpi_handle_list resources;
+ struct acpi_device_wakeup_state state;
+ struct acpi_device_wakeup_flags flags;
};
/* Device */
struct acpi_device {
- acpi_handle handle;
- struct acpi_device *parent;
- struct list_head children;
- struct list_head node;
- struct list_head wakeup_list;
- struct list_head g_list;
+ acpi_handle handle;
+ struct acpi_device *parent;
+ struct list_head children;
+ struct list_head node;
+ struct list_head wakeup_list;
+ struct list_head g_list;
struct acpi_device_status status;
struct acpi_device_flags flags;
- struct acpi_device_pnp pnp;
+ struct acpi_device_pnp pnp;
struct acpi_device_power power;
struct acpi_device_wakeup wakeup;
- struct acpi_device_perf performance;
- struct acpi_device_dir dir;
- struct acpi_device_ops ops;
- struct acpi_driver *driver;
- void *driver_data;
- struct kobject kobj;
+ struct acpi_device_perf performance;
+ struct acpi_device_dir dir;
+ struct acpi_device_ops ops;
+ struct acpi_driver *driver;
+ void *driver_data;
+ struct kobject kobj;
};
#define acpi_driver_data(d) ((d)->driver_data)
-
/*
* Events
* ------
*/
struct acpi_bus_event {
- struct list_head node;
- acpi_device_class device_class;
- acpi_bus_id bus_id;
- u32 type;
- u32 data;
+ struct list_head node;
+ acpi_device_class device_class;
+ acpi_bus_id bus_id;
+ u32 type;
+ u32 data;
};
extern struct subsystem acpi_subsys;
@@ -335,34 +321,32 @@ extern struct subsystem acpi_subsys;
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context);
-int acpi_bus_get_status (struct acpi_device *device);
-int acpi_bus_get_power (acpi_handle handle, int *state);
-int acpi_bus_set_power (acpi_handle handle, int state);
-int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data);
-int acpi_bus_receive_event (struct acpi_bus_event *event);
-int acpi_bus_register_driver (struct acpi_driver *driver);
-int acpi_bus_unregister_driver (struct acpi_driver *driver);
-int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
- acpi_handle handle, int type);
-int acpi_bus_start (struct acpi_device *device);
-
-
-int acpi_match_ids (struct acpi_device *device, char *ids);
+int acpi_bus_get_status(struct acpi_device *device);
+int acpi_bus_get_power(acpi_handle handle, int *state);
+int acpi_bus_set_power(acpi_handle handle, int state);
+int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data);
+int acpi_bus_receive_event(struct acpi_bus_event *event);
+int acpi_bus_register_driver(struct acpi_driver *driver);
+int acpi_bus_unregister_driver(struct acpi_driver *driver);
+int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
+ acpi_handle handle, int type);
+int acpi_bus_start(struct acpi_device *device);
+
+int acpi_match_ids(struct acpi_device *device, char *ids);
int acpi_create_dir(struct acpi_device *);
void acpi_remove_dir(struct acpi_device *);
-
/*
* Bind physical devices with ACPI devices
*/
#include <linux/device.h>
struct acpi_bus_type {
- struct list_head list;
- struct bus_type *bus;
- /* For general devices under the bus*/
- int (*find_device)(struct device *, acpi_handle*);
+ struct list_head list;
+ struct bus_type *bus;
+ /* For general devices under the bus */
+ int (*find_device) (struct device *, acpi_handle *);
/* For bridges, such as PCI root bridge, IDE controller */
- int (*find_bridge)(struct device *, acpi_handle *);
+ int (*find_bridge) (struct device *, acpi_handle *);
};
int register_acpi_bus_type(struct acpi_bus_type *);
int unregister_acpi_bus_type(struct acpi_bus_type *);
@@ -372,6 +356,6 @@ acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
-#endif /*CONFIG_ACPI_BUS*/
+#endif /* CONFIG_ACPI */
#endif /*__ACPI_BUS_H__*/
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 579fe191b7e7..c1b4e1f882e4 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -29,7 +29,6 @@
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
-
#define ACPI_MAX_STRING 80
#define ACPI_BUS_COMPONENT 0x00010000
@@ -44,60 +43,55 @@
#define ACPI_BUTTON_HID_POWERF "ACPI_FPB"
#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB"
-
/* --------------------------------------------------------------------------
PCI
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PCI
-
#define ACPI_PCI_COMPONENT 0x00400000
/* ACPI PCI Interrupt Link (pci_link.c) */
-int acpi_irq_penalty_init (void);
-int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level,
- int *active_high_low, char **name);
+int acpi_irq_penalty_init(void);
+int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *edge_level,
+ int *active_high_low, char **name);
int acpi_pci_link_free_irq(acpi_handle handle);
/* ACPI PCI Interrupt Routing (pci_irq.c) */
-int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt (int segment, int bus);
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt(int segment, int bus);
/* ACPI PCI Device Binding (pci_bind.c) */
struct pci_bus;
-acpi_status acpi_get_pci_id (acpi_handle handle, struct acpi_pci_id *id);
-int acpi_pci_bind (struct acpi_device *device);
-int acpi_pci_unbind (struct acpi_device *device);
-int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus);
+acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id);
+int acpi_pci_bind(struct acpi_device *device);
+int acpi_pci_unbind(struct acpi_device *device);
+int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id,
+ struct pci_bus *bus);
/* Arch-defined function to add a bus to the system */
-struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int bus);
-
-#endif /*CONFIG_ACPI_PCI*/
-
+struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain,
+ int bus);
/* --------------------------------------------------------------------------
Power Resource
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_POWER
-int acpi_enable_wakeup_device_power (struct acpi_device *dev);
-int acpi_disable_wakeup_device_power (struct acpi_device *dev);
-int acpi_power_get_inferred_state (struct acpi_device *device);
-int acpi_power_transition (struct acpi_device *device, int state);
+int acpi_enable_wakeup_device_power(struct acpi_device *dev);
+int acpi_disable_wakeup_device_power(struct acpi_device *dev);
+int acpi_power_get_inferred_state(struct acpi_device *device);
+int acpi_power_transition(struct acpi_device *device, int state);
#endif
-
/* --------------------------------------------------------------------------
Embedded Controller
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_EC
-int acpi_ec_ecdt_probe (void);
+int acpi_ec_ecdt_probe(void);
#endif
/* --------------------------------------------------------------------------
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index ea489f235216..98e0b8cd14ed 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -7,7 +7,6 @@
*
*****************************************************************************/
-
/*
* Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
@@ -51,7 +50,6 @@
#include "platform/acenv.h"
#include "actypes.h"
-
/* Priorities for acpi_os_queue_for_execution */
#define OSD_PRIORITY_GPE 1
@@ -62,200 +60,136 @@
#define ACPI_NO_UNIT_LIMIT ((u32) -1)
#define ACPI_MUTEX_SEM 1
-
/* Functions for acpi_os_signal */
#define ACPI_SIGNAL_FATAL 0
#define ACPI_SIGNAL_BREAKPOINT 1
-struct acpi_signal_fatal_info
-{
- u32 type;
- u32 code;
- u32 argument;
+struct acpi_signal_fatal_info {
+ u32 type;
+ u32 code;
+ u32 argument;
};
-
/*
* OSL Initialization and shutdown primitives
*/
-acpi_status
-acpi_os_initialize (
- void);
-
-acpi_status
-acpi_os_terminate (
- void);
+acpi_status acpi_os_initialize(void);
+acpi_status acpi_os_terminate(void);
/*
* ACPI Table interfaces
*/
-acpi_status
-acpi_os_get_root_pointer (
- u32 flags,
- struct acpi_pointer *address);
+acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *address);
acpi_status
-acpi_os_predefined_override (
- const struct acpi_predefined_names *init_val,
- acpi_string *new_val);
+acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
+ acpi_string * new_val);
acpi_status
-acpi_os_table_override (
- struct acpi_table_header *existing_table,
- struct acpi_table_header **new_table);
-
+acpi_os_table_override(struct acpi_table_header *existing_table,
+ struct acpi_table_header **new_table);
/*
* Synchronization primitives
*/
acpi_status
-acpi_os_create_semaphore (
- u32 max_units,
- u32 initial_units,
- acpi_handle *out_handle);
-
-acpi_status
-acpi_os_delete_semaphore (
- acpi_handle handle);
+acpi_os_create_semaphore(u32 max_units,
+ u32 initial_units, acpi_handle * out_handle);
-acpi_status
-acpi_os_wait_semaphore (
- acpi_handle handle,
- u32 units,
- u16 timeout);
+acpi_status acpi_os_delete_semaphore(acpi_handle handle);
-acpi_status
-acpi_os_signal_semaphore (
- acpi_handle handle,
- u32 units);
+acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout);
-acpi_status
-acpi_os_create_lock (
- acpi_handle *out_handle);
+acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units);
-void
-acpi_os_delete_lock (
- acpi_handle handle);
+acpi_status acpi_os_create_lock(acpi_handle * out_handle);
-void
-acpi_os_acquire_lock (
- acpi_handle handle,
- u32 flags);
+void acpi_os_delete_lock(acpi_handle handle);
-void
-acpi_os_release_lock (
- acpi_handle handle,
- u32 flags);
+unsigned long acpi_os_acquire_lock(acpi_handle handle);
+void acpi_os_release_lock(acpi_handle handle, unsigned long flags);
/*
* Memory allocation and mapping
*/
-void *
-acpi_os_allocate (
- acpi_size size);
+void *acpi_os_allocate(acpi_size size);
-void
-acpi_os_free (
- void * memory);
+void acpi_os_free(void *memory);
acpi_status
-acpi_os_map_memory (
- acpi_physical_address physical_address,
- acpi_size size,
- void __iomem **logical_address);
+acpi_os_map_memory(acpi_physical_address physical_address,
+ acpi_size size, void __iomem ** logical_address);
-void
-acpi_os_unmap_memory (
- void __iomem *logical_address,
- acpi_size size);
+void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_os_get_physical_address (
- void *logical_address,
- acpi_physical_address *physical_address);
+acpi_os_get_physical_address(void *logical_address,
+ acpi_physical_address * physical_address);
#endif
+/*
+ * Memory/Object Cache
+ */
+acpi_status
+acpi_os_create_cache(char *cache_name,
+ u16 object_size,
+ u16 max_depth, acpi_cache_t ** return_cache);
+
+acpi_status acpi_os_delete_cache(acpi_cache_t * cache);
+
+acpi_status acpi_os_purge_cache(acpi_cache_t * cache);
+
+void *acpi_os_acquire_object(acpi_cache_t * cache);
+
+acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object);
/*
* Interrupt handlers
*/
acpi_status
-acpi_os_install_interrupt_handler (
- u32 gsi,
- acpi_osd_handler service_routine,
- void *context);
+acpi_os_install_interrupt_handler(u32 gsi,
+ acpi_osd_handler service_routine,
+ void *context);
acpi_status
-acpi_os_remove_interrupt_handler (
- u32 gsi,
- acpi_osd_handler service_routine);
-
+acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine);
/*
* Threads and Scheduling
*/
-u32
-acpi_os_get_thread_id (
- void);
+u32 acpi_os_get_thread_id(void);
acpi_status
-acpi_os_queue_for_execution (
- u32 priority,
- acpi_osd_exec_callback function,
- void *context);
+acpi_os_queue_for_execution(u32 priority,
+ acpi_osd_exec_callback function, void *context);
-void
-acpi_os_wait_events_complete(
- void * context);
+void acpi_os_wait_events_complete(void *context);
-void
-acpi_os_wait_events_complete (
- void *context);
+void acpi_os_wait_events_complete(void *context);
-void
-acpi_os_sleep (
- acpi_integer milliseconds);
-
-void
-acpi_os_stall (
- u32 microseconds);
+void acpi_os_sleep(acpi_integer milliseconds);
+void acpi_os_stall(u32 microseconds);
/*
* Platform and hardware-independent I/O interfaces
*/
-acpi_status
-acpi_os_read_port (
- acpi_io_address address,
- u32 *value,
- u32 width);
-
-acpi_status
-acpi_os_write_port (
- acpi_io_address address,
- u32 value,
- u32 width);
+acpi_status acpi_os_read_port(acpi_io_address address, u32 * value, u32 width);
+acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width);
/*
* Platform and hardware-independent physical memory interfaces
*/
acpi_status
-acpi_os_read_memory (
- acpi_physical_address address,
- u32 *value,
- u32 width);
+acpi_os_read_memory(acpi_physical_address address, u32 * value, u32 width);
acpi_status
-acpi_os_write_memory (
- acpi_physical_address address,
- u32 value,
- u32 width);
-
+acpi_os_write_memory(acpi_physical_address address, u32 value, u32 width);
/*
* Platform and hardware-independent PCI configuration space access
@@ -263,111 +197,69 @@ acpi_os_write_memory (
* certain compilers complain.
*/
acpi_status
-acpi_os_read_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- void *value,
- u32 width);
+acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
+ u32 reg, void *value, u32 width);
acpi_status
-acpi_os_write_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- acpi_integer value,
- u32 width);
+acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
+ u32 reg, acpi_integer value, u32 width);
/*
* Interim function needed for PCI IRQ routing
*/
void
-acpi_os_derive_pci_id(
- acpi_handle rhandle,
- acpi_handle chandle,
- struct acpi_pci_id **pci_id);
+acpi_os_derive_pci_id(acpi_handle rhandle,
+ acpi_handle chandle, struct acpi_pci_id **pci_id);
/*
* Miscellaneous
*/
-u8
-acpi_os_readable (
- void *pointer,
- acpi_size length);
+u8 acpi_os_readable(void *pointer, acpi_size length);
#ifdef ACPI_FUTURE_USAGE
-u8
-acpi_os_writable (
- void *pointer,
- acpi_size length);
+u8 acpi_os_writable(void *pointer, acpi_size length);
#endif
-u64
-acpi_os_get_timer (
- void);
+u64 acpi_os_get_timer(void);
-acpi_status
-acpi_os_signal (
- u32 function,
- void *info);
+acpi_status acpi_os_signal(u32 function, void *info);
/*
* Debug print routines
*/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_os_printf (
- const char *format,
- ...);
-
-void
-acpi_os_vprintf (
- const char *format,
- va_list args);
+void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...);
-void
-acpi_os_redirect_output (
- void *destination);
+void acpi_os_vprintf(const char *format, va_list args);
+void acpi_os_redirect_output(void *destination);
#ifdef ACPI_FUTURE_USAGE
/*
* Debug input
*/
-u32
-acpi_os_get_line (
- char *buffer);
+u32 acpi_os_get_line(char *buffer);
#endif
-
/*
* Directory manipulation
*/
-void *
-acpi_os_open_directory (
- char *pathname,
- char *wildcard_spec,
- char requested_file_type);
+void *acpi_os_open_directory(char *pathname,
+ char *wildcard_spec, char requested_file_type);
/* requeste_file_type values */
#define REQUEST_FILE_ONLY 0
#define REQUEST_DIR_ONLY 1
+char *acpi_os_get_next_filename(void *dir_handle);
-char *
-acpi_os_get_next_filename (
- void *dir_handle);
-
-void
-acpi_os_close_directory (
- 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);
+acpi_os_dbg_assert(void *failed_assertion,
+ void *file_name, u32 line_number, char *message);
-#endif /* __ACPIOSXF_H__ */
+#endif /* __ACPIOSXF_H__ */
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index f8f619f8e4f8..2a9dbc13b0f2 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -42,447 +42,283 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#ifndef __ACXFACE_H__
#define __ACXFACE_H__
#include "actypes.h"
#include "actbl.h"
-
/*
* Global interfaces
*/
-acpi_status
-acpi_initialize_subsystem (
- void);
+acpi_status acpi_initialize_subsystem(void);
-acpi_status
-acpi_enable_subsystem (
- u32 flags);
+acpi_status acpi_enable_subsystem(u32 flags);
-acpi_status
-acpi_initialize_objects (
- u32 flags);
+acpi_status acpi_initialize_objects(u32 flags);
-acpi_status
-acpi_terminate (
- void);
+acpi_status acpi_terminate(void);
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_subsystem_status (
- void);
+acpi_status acpi_subsystem_status(void);
#endif
-acpi_status
-acpi_enable (
- void);
+acpi_status acpi_enable(void);
-acpi_status
-acpi_disable (
- void);
+acpi_status acpi_disable(void);
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_get_system_info (
- struct acpi_buffer *ret_buffer);
+acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer);
#endif
-const char *
-acpi_format_exception (
- acpi_status exception);
+const char *acpi_format_exception(acpi_status exception);
-acpi_status
-acpi_purge_cached_objects (
- void);
+acpi_status acpi_purge_cached_objects(void);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_install_initialization_handler (
- acpi_init_handler handler,
- u32 function);
+acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
#endif
/*
* ACPI Memory managment
*/
-void *
-acpi_allocate (
- u32 size);
-
-void *
-acpi_callocate (
- u32 size);
+void *acpi_allocate(u32 size);
-void
-acpi_free (
- void *address);
+void *acpi_callocate(u32 size);
+void acpi_free(void *address);
/*
* ACPI table manipulation interfaces
*/
acpi_status
-acpi_find_root_pointer (
- u32 flags,
- struct acpi_pointer *rsdp_address);
+acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address);
-acpi_status
-acpi_load_tables (
- void);
+acpi_status acpi_load_tables(void);
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_load_table (
- struct acpi_table_header *table_ptr);
+acpi_status acpi_load_table(struct acpi_table_header *table_ptr);
-acpi_status
-acpi_unload_table (
- acpi_table_type table_type);
+acpi_status acpi_unload_table(acpi_table_type table_type);
acpi_status
-acpi_get_table_header (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header *out_table_header);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_get_table_header(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header *out_table_header);
+#endif /* ACPI_FUTURE_USAGE */
acpi_status
-acpi_get_table (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_buffer *ret_buffer);
+acpi_get_table(acpi_table_type table_type,
+ u32 instance, struct acpi_buffer *ret_buffer);
acpi_status
-acpi_get_firmware_table (
- acpi_string signature,
- u32 instance,
- u32 flags,
- struct acpi_table_header **table_pointer);
-
+acpi_get_firmware_table(acpi_string signature,
+ u32 instance,
+ u32 flags, struct acpi_table_header **table_pointer);
/*
* Namespace and name interfaces
*/
acpi_status
-acpi_walk_namespace (
- acpi_object_type type,
- acpi_handle start_object,
- u32 max_depth,
- acpi_walk_callback user_function,
- void *context,
- void **return_value);
+acpi_walk_namespace(acpi_object_type type,
+ acpi_handle start_object,
+ u32 max_depth,
+ acpi_walk_callback user_function,
+ void *context, void **return_value);
acpi_status
-acpi_get_devices (
- char *HID,
- acpi_walk_callback user_function,
- void *context,
- void **return_value);
+acpi_get_devices(char *HID,
+ acpi_walk_callback user_function,
+ void *context, void **return_value);
acpi_status
-acpi_get_name (
- acpi_handle handle,
- u32 name_type,
- struct acpi_buffer *ret_path_ptr);
+acpi_get_name(acpi_handle handle,
+ u32 name_type, struct acpi_buffer *ret_path_ptr);
acpi_status
-acpi_get_handle (
- acpi_handle parent,
- acpi_string pathname,
- acpi_handle *ret_handle);
+acpi_get_handle(acpi_handle parent,
+ acpi_string pathname, acpi_handle * ret_handle);
acpi_status
-acpi_attach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void *data);
+acpi_attach_data(acpi_handle obj_handle,
+ acpi_object_handler handler, void *data);
acpi_status
-acpi_detach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler);
+acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler);
acpi_status
-acpi_get_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void **data);
-
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data);
/*
* Object manipulation and enumeration
*/
acpi_status
-acpi_evaluate_object (
- acpi_handle object,
- acpi_string pathname,
- struct acpi_object_list *parameter_objects,
- struct acpi_buffer *return_object_buffer);
+acpi_evaluate_object(acpi_handle object,
+ acpi_string pathname,
+ struct acpi_object_list *parameter_objects,
+ struct acpi_buffer *return_object_buffer);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_evaluate_object_typed (
- acpi_handle object,
- acpi_string pathname,
- struct acpi_object_list *external_params,
- struct acpi_buffer *return_buffer,
- acpi_object_type return_type);
+acpi_evaluate_object_typed(acpi_handle object,
+ acpi_string pathname,
+ struct acpi_object_list *external_params,
+ struct acpi_buffer *return_buffer,
+ acpi_object_type return_type);
#endif
acpi_status
-acpi_get_object_info (
- acpi_handle handle,
- struct acpi_buffer *return_buffer);
+acpi_get_object_info(acpi_handle handle, struct acpi_buffer *return_buffer);
acpi_status
-acpi_get_next_object (
- acpi_object_type type,
- acpi_handle parent,
- acpi_handle child,
- acpi_handle *out_handle);
+acpi_get_next_object(acpi_object_type type,
+ acpi_handle parent,
+ acpi_handle child, acpi_handle * out_handle);
-acpi_status
-acpi_get_type (
- acpi_handle object,
- acpi_object_type *out_type);
-
-acpi_status
-acpi_get_parent (
- acpi_handle object,
- acpi_handle *out_handle);
+acpi_status acpi_get_type(acpi_handle object, acpi_object_type * out_type);
+acpi_status acpi_get_parent(acpi_handle object, acpi_handle * out_handle);
/*
* Event handler interfaces
*/
acpi_status
-acpi_install_fixed_event_handler (
- u32 acpi_event,
- acpi_event_handler handler,
- void *context);
+acpi_install_fixed_event_handler(u32 acpi_event,
+ acpi_event_handler handler, void *context);
acpi_status
-acpi_remove_fixed_event_handler (
- u32 acpi_event,
- acpi_event_handler handler);
+acpi_remove_fixed_event_handler(u32 acpi_event, acpi_event_handler handler);
acpi_status
-acpi_install_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler,
- void *context);
+acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler handler, void *context);
acpi_status
-acpi_remove_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler);
+acpi_remove_notify_handler(acpi_handle device,
+ u32 handler_type, acpi_notify_handler handler);
acpi_status
-acpi_install_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context);
+acpi_install_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context);
acpi_status
-acpi_remove_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler);
+acpi_remove_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler);
acpi_status
-acpi_install_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 type,
- acpi_event_handler address,
- void *context);
+acpi_install_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number,
+ u32 type, acpi_event_handler address, void *context);
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_install_exception_handler (
- acpi_exception_handler handler);
+acpi_status acpi_install_exception_handler(acpi_exception_handler handler);
#endif
-
/*
* Event interfaces
*/
-acpi_status
-acpi_acquire_global_lock (
- u16 timeout,
- u32 *handle);
+acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle);
-acpi_status
-acpi_release_global_lock (
- u32 handle);
+acpi_status acpi_release_global_lock(u32 handle);
acpi_status
-acpi_remove_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- acpi_event_handler address);
+acpi_remove_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number, acpi_event_handler address);
-acpi_status
-acpi_enable_event (
- u32 event,
- u32 flags);
+acpi_status acpi_enable_event(u32 event, u32 flags);
-acpi_status
-acpi_disable_event (
- u32 event,
- u32 flags);
+acpi_status acpi_disable_event(u32 event, u32 flags);
-acpi_status
-acpi_clear_event (
- u32 event);
+acpi_status acpi_clear_event(u32 event);
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_get_event_status (
- u32 event,
- acpi_event_status *event_status);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
+#endif /* ACPI_FUTURE_USAGE */
-acpi_status
-acpi_set_gpe_type (
- acpi_handle gpe_device,
- u32 gpe_number,
- u8 type);
+acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type);
-acpi_status
-acpi_enable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags);
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
-acpi_status
-acpi_disable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags);
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
-acpi_status
-acpi_clear_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags);
+acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_gpe_status (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags,
- acpi_event_status *event_status);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_get_gpe_status(acpi_handle gpe_device,
+ u32 gpe_number,
+ u32 flags, acpi_event_status * event_status);
+#endif /* ACPI_FUTURE_USAGE */
acpi_status
-acpi_install_gpe_block (
- acpi_handle gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u32 interrupt_level);
-
-acpi_status
-acpi_remove_gpe_block (
- acpi_handle gpe_device);
+acpi_install_gpe_block(acpi_handle gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count, u32 interrupt_number);
+acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
/*
* Resource interfaces
*/
typedef
-acpi_status (*ACPI_WALK_RESOURCE_CALLBACK) (
- struct acpi_resource *resource,
- void *context);
-
+acpi_status(*ACPI_WALK_RESOURCE_CALLBACK) (struct acpi_resource * resource,
+ void *context);
acpi_status
-acpi_get_current_resources(
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer);
+acpi_get_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_possible_resources(
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer);
+acpi_get_possible_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer);
#endif
acpi_status
-acpi_walk_resources (
- acpi_handle device_handle,
- char *path,
- ACPI_WALK_RESOURCE_CALLBACK user_function,
- void *context);
+acpi_walk_resources(acpi_handle device_handle,
+ char *path,
+ ACPI_WALK_RESOURCE_CALLBACK user_function, void *context);
acpi_status
-acpi_set_current_resources (
- acpi_handle device_handle,
- struct acpi_buffer *in_buffer);
+acpi_set_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *in_buffer);
acpi_status
-acpi_get_irq_routing_table (
- acpi_handle bus_device_handle,
- struct acpi_buffer *ret_buffer);
+acpi_get_irq_routing_table(acpi_handle bus_device_handle,
+ struct acpi_buffer *ret_buffer);
acpi_status
-acpi_resource_to_address64 (
- struct acpi_resource *resource,
- struct acpi_resource_address64 *out);
+acpi_resource_to_address64(struct acpi_resource *resource,
+ struct acpi_resource_address64 *out);
/*
* Hardware (ACPI device) interfaces
*/
-acpi_status
-acpi_get_register (
- u32 register_id,
- u32 *return_value,
- u32 flags);
+acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags);
-acpi_status
-acpi_set_register (
- u32 register_id,
- u32 value,
- u32 flags);
+acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags);
acpi_status
-acpi_set_firmware_waking_vector (
- acpi_physical_address physical_address);
+acpi_set_firmware_waking_vector(acpi_physical_address physical_address);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_firmware_waking_vector (
- acpi_physical_address *physical_address);
+acpi_get_firmware_waking_vector(acpi_physical_address * physical_address);
#endif
acpi_status
-acpi_get_sleep_type_data (
- u8 sleep_state,
- u8 *slp_typ_a,
- u8 *slp_typ_b);
+acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b);
-acpi_status
-acpi_enter_sleep_state_prep (
- u8 sleep_state);
+acpi_status acpi_enter_sleep_state_prep(u8 sleep_state);
-acpi_status asmlinkage
-acpi_enter_sleep_state (
- u8 sleep_state);
+acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state);
-acpi_status asmlinkage
-acpi_enter_sleep_state_s4bios (
- void);
-
-acpi_status
-acpi_leave_sleep_state (
- u8 sleep_state);
+acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void);
+acpi_status acpi_leave_sleep_state(u8 sleep_state);
-#endif /* __ACXFACE_H__ */
+#endif /* __ACXFACE_H__ */
diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h
index ed679264c12c..38e798b05d08 100644
--- a/include/acpi/acresrc.h
+++ b/include/acpi/acresrc.h
@@ -44,303 +44,216 @@
#ifndef __ACRESRC_H__
#define __ACRESRC_H__
-
/*
* Function prototypes called from Acpi* APIs
*/
acpi_status
-acpi_rs_get_prt_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer);
-
+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(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);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+#endif /* ACPI_FUTURE_USAGE */
acpi_status
-acpi_rs_get_method_data (
- acpi_handle handle,
- char *path,
- struct acpi_buffer *ret_buffer);
+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(acpi_handle handle, struct acpi_buffer *ret_buffer);
acpi_status
-acpi_rs_create_resource_list (
- union acpi_operand_object *byte_stream_buffer,
- struct acpi_buffer *output_buffer);
+acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
+ struct acpi_buffer *output_buffer);
acpi_status
-acpi_rs_create_byte_stream (
- struct acpi_resource *linked_list_buffer,
- struct acpi_buffer *output_buffer);
+acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
+ struct acpi_buffer *output_buffer);
acpi_status
-acpi_rs_create_pci_routing_table (
- union acpi_operand_object *package_object,
- struct acpi_buffer *output_buffer);
-
+acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
+ struct acpi_buffer *output_buffer);
/*
* rsdump
*/
#ifdef ACPI_FUTURE_USAGE
-void
-acpi_rs_dump_resource_list (
- struct acpi_resource *resource);
-
-void
-acpi_rs_dump_irq_list (
- u8 *route_table);
-#endif /* ACPI_FUTURE_USAGE */
+void acpi_rs_dump_resource_list(struct acpi_resource *resource);
+void acpi_rs_dump_irq_list(u8 * route_table);
+#endif /* ACPI_FUTURE_USAGE */
/*
* rscalc
*/
acpi_status
-acpi_rs_get_byte_stream_start (
- u8 *byte_stream_buffer,
- u8 **byte_stream_start,
- u32 *size);
+acpi_rs_get_byte_stream_start(u8 * byte_stream_buffer,
+ u8 ** byte_stream_start, u32 * size);
acpi_status
-acpi_rs_get_list_length (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- acpi_size *size_needed);
+acpi_rs_get_list_length(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, acpi_size * size_needed);
acpi_status
-acpi_rs_get_byte_stream_length (
- struct acpi_resource *linked_list_buffer,
- acpi_size *size_needed);
+acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list_buffer,
+ acpi_size * size_needed);
acpi_status
-acpi_rs_get_pci_routing_table_length (
- union acpi_operand_object *package_object,
- acpi_size *buffer_size_needed);
+acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
+ acpi_size * buffer_size_needed);
acpi_status
-acpi_rs_byte_stream_to_list (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- u8 *output_buffer);
+acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, u8 * output_buffer);
acpi_status
-acpi_rs_list_to_byte_stream (
- struct acpi_resource *linked_list,
- acpi_size byte_stream_size_needed,
- u8 *output_buffer);
+acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
+ acpi_size byte_stream_size_needed,
+ u8 * output_buffer);
acpi_status
-acpi_rs_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_fixed_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_fixed_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_dma_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_dma_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_dma_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_dma_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_address16_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_address16_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_address16_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_address16_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_address32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_address32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_address32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_address32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_address64_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_address64_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_address64_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_address64_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_start_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size);
acpi_status
-acpi_rs_end_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size);
acpi_status
-acpi_rs_start_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer,
+ acpi_size * bytes_consumed);
acpi_status
-acpi_rs_end_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_memory24_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_memory24_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_memory24_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_memory24_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_memory32_range_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size);
acpi_status
-acpi_rs_fixed_memory32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size);
acpi_status
-acpi_rs_memory32_range_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_fixed_memory32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_extended_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_extended_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_end_tag_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_end_tag_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
acpi_status
-acpi_rs_vendor_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size);
+acpi_rs_vendor_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size);
acpi_status
-acpi_rs_vendor_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed);
+acpi_rs_vendor_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed);
-u8
-acpi_rs_get_resource_type (
- u8 resource_start_byte);
+u8 acpi_rs_get_resource_type(u8 resource_start_byte);
-#endif /* __ACRESRC_H__ */
+#endif /* __ACRESRC_H__ */
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index e6b9e36a2eda..99d235339801 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -44,14 +44,12 @@
#ifndef __ACSTRUCT_H__
#define __ACSTRUCT_H__
-
/*****************************************************************************
*
* Tree walking typedefs and structs
*
****************************************************************************/
-
/*
* 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.
@@ -65,152 +63,142 @@
#define ACPI_WALK_CONST_REQUIRED 3
#define ACPI_WALK_CONST_OPTIONAL 4
-struct acpi_walk_state
-{
- u8 data_type; /* To differentiate various internal objs MUST BE FIRST!*/\
- u8 walk_type;
- acpi_owner_id owner_id; /* Owner of objects created during the walk */
- u8 last_predicate; /* Result of last predicate */
- u8 reserved; /* For alignment */
- u8 current_result; /* */
- u8 next_op_info; /* Info about next_op */
- u8 num_operands; /* Stack pointer for Operands[] array */
- u8 return_used;
- u16 opcode; /* Current AML opcode */
- u8 scope_depth;
- u8 reserved1;
- 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;
- u32 prev_arg_types;
-
- u8 *aml_last_while;
- struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
- 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 */
- 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 */
+struct acpi_walk_state {
+ u8 data_type; /* To differentiate various internal objs MUST BE FIRST! */
+ 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; /* */
+ u8 next_op_info; /* Info about next_op */
+ u8 num_operands; /* Stack pointer for Operands[] array */
+ 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;
+ u32 prev_arg_types;
+
+ u8 *aml_last_while;
+ struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
+ 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 */
+ 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 */
-struct acpi_init_walk_info
-{
- u16 method_count;
- u16 device_count;
- u16 op_region_count;
- u16 field_count;
- u16 buffer_count;
- u16 package_count;
- u16 op_region_init;
- u16 field_init;
- u16 buffer_init;
- u16 package_init;
- u16 object_count;
- struct acpi_table_desc *table_desc;
+struct acpi_init_walk_info {
+ u16 method_count;
+ u16 device_count;
+ u16 op_region_count;
+ u16 field_count;
+ u16 buffer_count;
+ u16 package_count;
+ u16 op_region_init;
+ u16 field_init;
+ u16 buffer_init;
+ u16 package_init;
+ u16 object_count;
+ 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;
+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 owner_id;
- u8 display_type;
+struct acpi_walk_info {
+ u32 debug_level;
+ u32 count;
+ acpi_owner_id owner_id;
+ u8 display_type;
};
/* Display Types */
-#define ACPI_DISPLAY_SUMMARY 0
-#define ACPI_DISPLAY_OBJECTS 1
+#define ACPI_DISPLAY_SUMMARY (u8) 0
+#define ACPI_DISPLAY_OBJECTS (u8) 1
+#define ACPI_DISPLAY_MASK (u8) 1
-struct acpi_get_devices_info
-{
- acpi_walk_callback user_function;
- void *context;
- char *hid;
-};
+#define ACPI_DISPLAY_SHORT (u8) 2
+struct acpi_get_devices_info {
+ acpi_walk_callback user_function;
+ void *context;
+ char *hid;
+};
-union acpi_aml_operands
-{
- union acpi_operand_object *operands[7];
+union acpi_aml_operands {
+ union acpi_operand_object *operands[7];
- struct
- {
- struct acpi_object_integer *type;
- struct acpi_object_integer *code;
- struct acpi_object_integer *argument;
+ struct {
+ struct acpi_object_integer *type;
+ struct acpi_object_integer *code;
+ struct acpi_object_integer *argument;
} fatal;
- struct
- {
- union acpi_operand_object *source;
- struct acpi_object_integer *index;
- union acpi_operand_object *target;
+ struct {
+ union acpi_operand_object *source;
+ struct acpi_object_integer *index;
+ union acpi_operand_object *target;
} index;
- struct
- {
- union acpi_operand_object *source;
- struct acpi_object_integer *index;
- struct acpi_object_integer *length;
- union acpi_operand_object *target;
+ struct {
+ union acpi_operand_object *source;
+ struct acpi_object_integer *index;
+ struct acpi_object_integer *length;
+ union acpi_operand_object *target;
} mid;
};
-
/* Internal method parameter list */
-struct acpi_parameter_info
-{
- struct acpi_namespace_node *node;
- union acpi_operand_object **parameters;
- union acpi_operand_object *return_object;
- u8 parameter_type;
- u8 return_object_type;
+struct acpi_parameter_info {
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object **parameters;
+ union acpi_operand_object *return_object;
+ u8 pass_number;
+ u8 parameter_type;
+ u8 return_object_type;
};
/* Types for parameter_type above */
@@ -218,5 +206,4 @@ struct acpi_parameter_info
#define ACPI_PARAM_ARGS 0
#define ACPI_PARAM_GPE 1
-
#endif
diff --git a/include/acpi/actables.h b/include/acpi/actables.h
index 39df92e21a0d..f92c1858b808 100644
--- a/include/acpi/actables.h
+++ b/include/acpi/actables.h
@@ -44,146 +44,101 @@
#ifndef __ACTABLES_H__
#define __ACTABLES_H__
-
/* Used in acpi_tb_map_acpi_table for size parameter if table header is to be used */
#define SIZE_IN_HEADER 0
-
/*
* tbconvrt - Table conversion routines
*/
-acpi_status
-acpi_tb_convert_to_xsdt (
- struct acpi_table_desc *table_info);
+acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info);
-acpi_status
-acpi_tb_convert_table_fadt (
- void);
+acpi_status acpi_tb_convert_table_fadt(void);
-acpi_status
-acpi_tb_build_common_facs (
- struct acpi_table_desc *table_info);
+acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info);
u32
-acpi_tb_get_table_count (
- struct rsdp_descriptor *RSDP,
- struct acpi_table_header *RSDT);
-
+acpi_tb_get_table_count(struct rsdp_descriptor *RSDP,
+ struct acpi_table_header *RSDT);
/*
* tbget - Table "get" routines
*/
acpi_status
-acpi_tb_get_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info);
-
-acpi_status
-acpi_tb_get_table_header (
- struct acpi_pointer *address,
- struct acpi_table_header *return_header);
+acpi_tb_get_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info);
acpi_status
-acpi_tb_get_table_body (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info);
+acpi_tb_get_table_header(struct acpi_pointer *address,
+ struct acpi_table_header *return_header);
acpi_status
-acpi_tb_get_table_ptr (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header **table_ptr_loc);
+acpi_tb_get_table_body(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info);
acpi_status
-acpi_tb_verify_rsdp (
- struct acpi_pointer *address);
+acpi_tb_get_table_ptr(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header **table_ptr_loc);
-void
-acpi_tb_get_rsdt_address (
- struct acpi_pointer *out_address);
+acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address);
-acpi_status
-acpi_tb_validate_rsdt (
- struct acpi_table_header *table_ptr);
+void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address);
+acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr);
/*
* tbgetall - get multiple required tables
*/
-acpi_status
-acpi_tb_get_required_tables (
- void);
-
+acpi_status acpi_tb_get_required_tables(void);
/*
* tbinstall - Table installation
*/
-acpi_status
-acpi_tb_install_table (
- struct acpi_table_desc *table_info);
+acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info);
acpi_status
-acpi_tb_recognize_table (
- struct acpi_table_desc *table_info,
- u8 search_type);
+acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type);
acpi_status
-acpi_tb_init_table_descriptor (
- acpi_table_type table_type,
- struct acpi_table_desc *table_info);
-
+acpi_tb_init_table_descriptor(acpi_table_type table_type,
+ struct acpi_table_desc *table_info);
/*
* tbremove - Table removal and deletion
*/
-void
-acpi_tb_delete_all_tables (
- void);
-
-void
-acpi_tb_delete_tables_by_type (
- acpi_table_type type);
+void acpi_tb_delete_all_tables(void);
-void
-acpi_tb_delete_single_table (
- struct acpi_table_desc *table_desc);
+void acpi_tb_delete_tables_by_type(acpi_table_type type);
-struct acpi_table_desc *
-acpi_tb_uninstall_table (
- struct acpi_table_desc *table_desc);
+void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc);
+struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
+ *table_desc);
/*
* tbxfroot - RSDP, RSDT utilities
*/
acpi_status
-acpi_tb_find_table (
- char *signature,
- char *oem_id,
- char *oem_table_id,
- struct acpi_table_header **table_ptr);
+acpi_tb_find_table(char *signature,
+ char *oem_id,
+ char *oem_table_id, struct acpi_table_header **table_ptr);
-acpi_status
-acpi_tb_get_table_rsdt (
- void);
+acpi_status acpi_tb_get_table_rsdt(void);
+acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp);
/*
* tbutils - common table utilities
*/
+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);
+acpi_tb_verify_table_checksum(struct acpi_table_header *table_header);
-u8
-acpi_tb_checksum (
- void *buffer,
- u32 length);
+u8 acpi_tb_generate_checksum(void *buffer, u32 length);
acpi_status
-acpi_tb_validate_table_header (
- struct acpi_table_header *table_header);
+acpi_tb_validate_table_header(struct acpi_table_header *table_header);
-#endif /* __ACTABLES_H__ */
+#endif /* __ACTABLES_H__ */
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index b5cdcca444c8..a46f406e1c94 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -44,27 +44,24 @@
#ifndef __ACTBL_H__
#define __ACTBL_H__
-
/*
* Values for description table header signatures
*/
#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 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_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 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 */
/*
* Common table types. The base code can remain
@@ -75,7 +72,6 @@
#define FACS_DESCRIPTOR struct facs_descriptor_rev2
#define FADT_DESCRIPTOR struct fadt_descriptor_rev2
-
#pragma pack(1)
/*
@@ -84,45 +80,37 @@
* NOTE: The tables that are specific to ACPI versions (1.0, 2.0, etc.)
* are in separate files.
*/
-struct rsdp_descriptor /* Root System Descriptor Pointer */
-{
- char signature [8]; /* ACPI signature, contains "RSD PTR " */
- u8 checksum; /* To make sum of struct == 0 */
- char oem_id [6]; /* OEM identification */
- u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */
- u32 rsdt_physical_address; /* 32-bit physical address of RSDT */
- u32 length; /* XSDT Length in bytes including hdr */
- u64 xsdt_physical_address; /* 64-bit physical address of XSDT */
- u8 extended_checksum; /* Checksum of entire table */
- char reserved [3]; /* Reserved field must be 0 */
+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;
+struct acpi_common_facs { /* Common FACS for internal use */
+ u32 *global_lock;
+ u64 *firmware_waking_vector;
+ u8 vector_width;
};
-
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
- char signature [4]; /* ACPI signature (4 ASCII characters) */\
- u32 length; /* Length of table, in bytes, including header */\
+ char signature[4]; /* ASCII table signature */\
+ u32 length; /* Length of table in bytes, including this header */\
u8 revision; /* ACPI Specification minor version # */\
u8 checksum; /* To make sum of entire table == 0 */\
- char oem_id [6]; /* OEM identification */\
- char oem_table_id [8]; /* OEM table identification */\
+ 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]; /* ASL compiler vendor ID */\
- u32 asl_compiler_revision; /* ASL compiler revision number */
-
-
-struct acpi_table_header /* ACPI common table header */
-{
- ACPI_TABLE_HEADER_DEF
-};
+ 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 */
+ACPI_TABLE_HEADER_DEF};
/*
* MADT values and structures
@@ -135,12 +123,15 @@ struct acpi_table_header /* ACPI common table header */
/* Master MADT */
-struct multiple_apic_table
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 local_apic_address; /* Physical address of local APIC */
- u32 PCATcompat : 1; /* A one indicates system also has dual 8259s */
- u32 reserved1 : 31;
+struct multiple_apic_table {
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 local_apic_address; /* Physical address of local APIC */
+
+ /* Flags (32 bits) */
+
+ 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 */
};
/* Values for Type in APIC_HEADER_DEF */
@@ -154,7 +145,7 @@ struct multiple_apic_table
#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 APIC_RESERVED 9 /* 9 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
@@ -163,10 +154,8 @@ struct multiple_apic_table
u8 type; \
u8 length;
-struct apic_header
-{
- APIC_HEADER_DEF
-};
+struct apic_header {
+APIC_HEADER_DEF};
/* Values for MPS INTI flags */
@@ -180,117 +169,90 @@ struct apic_header
#define TRIGGER_RESERVED 2
#define TRIGGER_LEVEL 3
-/* Common flag definitions */
+/* Common flag definitions (16 bits each) */
#define MPS_INTI_FLAGS \
- u16 polarity : 2; /* Polarity of APIC I/O input signals */\
- u16 trigger_mode : 2; /* Trigger mode of APIC input signals */\
- u16 reserved1 : 12; /* Reserved, must be zero */
+ 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 \
- u32 processor_enabled: 1; /* Processor is usable if set */\
- u32 reserved2 : 31; /* Reserved, must be zero */
+ 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 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 madt_interrupt_override
-{
- APIC_HEADER_DEF
- u8 bus; /* 0 - ISA */
- u8 source; /* Interrupt source (IRQ) */
- u32 interrupt; /* Global system interrupt */
- MPS_INTI_FLAGS
-};
+struct madt_interrupt_override {
+ APIC_HEADER_DEF u8 bus; /* 0 - ISA */
+ u8 source; /* Interrupt source (IRQ) */
+ u32 interrupt; /* Global system interrupt */
+ MPS_INTI_FLAGS};
-struct madt_nmi_source
-{
- APIC_HEADER_DEF
- MPS_INTI_FLAGS
- u32 interrupt; /* Global system interrupt */
+struct madt_nmi_source {
+ APIC_HEADER_DEF MPS_INTI_FLAGS u32 interrupt; /* Global system interrupt */
};
-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 */
+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 */
};
-struct madt_address_override
-{
- APIC_HEADER_DEF
- u16 reserved; /* Reserved - must be zero */
- u64 address; /* APIC physical address */
+struct madt_address_override {
+ APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */
+ u64 address; /* APIC physical address */
};
-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 */
+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 */
};
-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 */
+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 */
};
-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 */
+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 */
};
-
/*
* Smart Battery
*/
-struct smart_battery_table
-{
- ACPI_TABLE_HEADER_DEF
- u32 warning_level;
- u32 low_level;
- u32 critical_level;
+struct smart_battery_table {
+ ACPI_TABLE_HEADER_DEF u32 warning_level;
+ u32 low_level;
+ u32 critical_level;
};
-
#pragma pack()
-
/*
* ACPI Table information. We save the table address, length,
* and type of memory allocation (mapped or allocated) for each
@@ -314,39 +276,35 @@ struct smart_battery_table
/* Data about each known table type */
-struct acpi_table_support
-{
- char *name;
- char *signature;
- void **global_ptr;
- u8 sig_length;
- u8 flags;
+struct acpi_table_support {
+ char *name;
+ char *signature;
+ void **global_ptr;
+ u8 sig_length;
+ u8 flags;
};
-
/*
* Get the ACPI version-specific tables
*/
-#include "actbl1.h" /* Acpi 1.0 table definitions */
-#include "actbl2.h" /* Acpi 2.0 table definitions */
+#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 */
+extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1,
+ * needed for certain workarounds */
#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;
+struct hpet_table {
+ ACPI_TABLE_HEADER_DEF u32 hardware_id;
+ struct acpi_generic_address base_address;
+ u8 hpet_number;
+ u16 clock_tick;
+ u8 attributes;
};
#pragma pack()
-#endif /* __ACTBL_H__ */
+#endif /* __ACTBL_H__ */
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 33de5f4d2ccc..67312c3a915a 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -49,88 +49,87 @@
/*
* ACPI 1.0 Root System Description Table (RSDT)
*/
-struct rsdt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 table_offset_entry [1]; /* Array of pointers to other */
- /* ACPI tables */
+struct rsdt_descriptor_rev1 {
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */
};
-
/*
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
*/
-struct facs_descriptor_rev1
-{
- char signature[4]; /* ACPI 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 */
- u32 S4bios_f : 1; /* Indicates if S4BIOS support is present */
- u32 reserved1 : 31; /* Must be 0 */
- u8 resverved3 [40]; /* Reserved - must be zero */
-};
+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 */
+
+ /* 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 */
+
+ u8 reserved2[40]; /* Reserved, must be zero */
+};
/*
* ACPI 1.0 Fixed ACPI Description Table (FADT)
*/
-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 */
- 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 */
- 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; /* Reserved */
- u8 reserved4a; /* Reserved */
- u8 reserved4b; /* Reserved */
- u32 wb_invd : 1; /* The wbinvd instruction works properly */
- u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
- u32 proc_c1 : 1; /* All processors support C1 state */
- u32 plvl2_up : 1; /* C2 state works on MP system */
- u32 pwr_button : 1; /* Power button is handled as a generic feature */
- u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
- u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
- u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
- u32 reserved5 : 23; /* Reserved - must be zero */
-};
+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 */
-#pragma pack()
+ /* Flags (32 bits) */
-#endif /* __ACTBL1_H__ */
+ 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 */
+};
+#pragma pack()
+#endif /* __ACTBL1_H__ */
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index e1729c967e05..50305ce2681a 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -64,62 +64,56 @@
#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 table headers */
+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 table headers */
+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]; /* ACPI signature */
- u32 length; /* Length of structure, in bytes */
- u32 hardware_signature; /* Hardware configuration signature */
- u32 firmware_waking_vector; /* 32bit physical address of the Firmware Waking Vector. */
- u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */
- u32 S4bios_f : 1; /* S4Bios_f - Indicates if S4BIOS support is present */
- u32 reserved1 : 31; /* Must be 0 */
- u64 xfirmware_waking_vector; /* 64bit physical address of the Firmware Waking Vector. */
- u8 version; /* Version of this table */
- u8 reserved3 [31]; /* Reserved - must be zero */
+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 */
+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 */ \
@@ -161,129 +155,123 @@ struct acpi_generic_address
/*
* 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 */
- u32 wb_invd : 1; /* The wbinvd instruction works properly */
- u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
- u32 proc_c1 : 1; /* All processors support C1 state */
- u32 plvl2_up : 1; /* C2 state works on MP system */
- u32 pwr_button : 1; /* Power button is handled as a generic feature */
- u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
- u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
- u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits */
- u32 dock_cap : 1; /* Supports Docking */
- u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG */
- u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed */
- u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices */
- u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */
- /* must be executed after writing the SLP_TYPx register */
- /* ACPI 3.0 flag bits */
-
- u32 pci_exp_wak : 1; /* System supports PCIEXP_WAKE (STS/EN) bits */
- u32 use_platform_clock : 1; /* OSPM should use platform-provided timer */
- u32 S4rtc_sts_valid : 1; /* Contents of RTC_STS valid after S4 wake */
- u32 remote_power_on_capable : 1; /* System is compatible with remote power on */
- u32 force_apic_cluster_model : 1; /* All local APICs must use cluster model */
- u32 force_apic_physical_destination_mode : 1; /* all local x_aPICs must use physical dest mode */
- u32 reserved6 : 12;/* 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 reserved7[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 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 */
- 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]; /* These three bytes must be zero */
+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 */
+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;
- u32 enabled :1;
- u32 reserved3 :31;
- u8 local_sapic_eid;
- u8 proximity_domain_hi[3];
- u32 reserved4;
-};
+struct static_resource_alloc {
+ u8 type;
+ u8 length;
+ u8 proximity_domain_lo;
+ u8 apic_id;
-struct memory_affinity
-{
- u8 type;
- u8 length;
- u32 proximity_domain;
- u16 reserved3;
- u64 base_address;
- u64 address_length;
- u32 reserved4;
- u32 enabled :1;
- u32 hot_pluggable :1;
- u32 non_volatile :1;
- u32 reserved5 :29;
- u64 reserved6;
+ /* 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 system_resource_affinity
-{
- ACPI_TABLE_HEADER_DEF
- u32 reserved1; /* Must be value '1' */
- u64 reserved2;
+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];
+struct system_locality_info {
+ ACPI_TABLE_HEADER_DEF u64 locality_count;
+ u8 entry[1][1];
};
-
#pragma pack()
-#endif /* __ACTBL2_H__ */
-
+#endif /* __ACTBL2_H__ */
diff --git a/include/acpi/actbl71.h b/include/acpi/actbl71.h
index 7b4fb44261f3..10ac05bb36bc 100644
--- a/include/acpi/actbl71.h
+++ b/include/acpi/actbl71.h
@@ -27,7 +27,6 @@
#ifndef __ACTBL71_H__
#define __ACTBL71_H__
-
/* 0.71 FADT address_space data item bitmasks defines */
/* If the associated bit is zero then it is in memory space else in io space */
@@ -40,105 +39,96 @@
/* Only for clarity in declarations */
-typedef u64 IO_ADDRESS;
-
+typedef u64 IO_ADDRESS;
#pragma pack(1)
-struct /* Root System Descriptor Pointer */
-{
- NATIVE_CHAR signature [8]; /* contains "RSD PTR " */
- u8 checksum; /* to make sum of struct == 0 */
- NATIVE_CHAR oem_id [6]; /* OEM identification */
- u8 reserved; /* Must be 0 for 1.0, 2 for 2.0 */
- u64 rsdt_physical_address; /* 64-bit physical address of RSDT */
+struct { /* Root System Descriptor Pointer */
+ NATIVE_CHAR signature[8]; /* contains "RSD PTR " */
+ u8 checksum; /* to make sum of struct == 0 */
+ NATIVE_CHAR oem_id[6]; /* OEM identification */
+ u8 reserved; /* Must be 0 for 1.0, 2 for 2.0 */
+ u64 rsdt_physical_address; /* 64-bit physical address of RSDT */
};
-
/*****************************************/
/* IA64 Extensions to ACPI Spec Rev 0.71 */
/* for the Root System Description Table */
/*****************************************/
-struct
-{
- struct acpi_table_header header; /* Table header */
- u32 reserved_pad; /* IA64 alignment, must be 0 */
- u64 table_offset_entry [1]; /* Array of pointers to other */
- /* tables' headers */
+struct {
+ struct acpi_table_header header; /* Table header */
+ u32 reserved_pad; /* IA64 alignment, must be 0 */
+ u64 table_offset_entry[1]; /* Array of pointers to other */
+ /* tables' headers */
};
-
/*******************************************/
/* IA64 Extensions to ACPI Spec Rev 0.71 */
/* for the Firmware ACPI Control Structure */
/*******************************************/
-struct
-{
- NATIVE_CHAR signature[4]; /* signature "FACS" */
- u32 length; /* length of structure, in bytes */
- u32 hardware_signature; /* hardware configuration signature */
- u32 reserved4; /* must be 0 */
- u64 firmware_waking_vector; /* ACPI OS waking vector */
- u64 global_lock; /* Global Lock */
- u32 S4bios_f : 1; /* Indicates if S4BIOS support is present */
- u32 reserved1 : 31; /* must be 0 */
- u8 reserved3 [28]; /* reserved - must be zero */
+struct {
+ NATIVE_CHAR signature[4]; /* signature "FACS" */
+ u32 length; /* length of structure, in bytes */
+ u32 hardware_signature; /* hardware configuration signature */
+ u32 reserved4; /* must be 0 */
+ u64 firmware_waking_vector; /* ACPI OS waking vector */
+ u64 global_lock; /* Global Lock */
+ u32 S4bios_f:1; /* Indicates if S4BIOS support is present */
+ u32 reserved1:31; /* must be 0 */
+ u8 reserved3[28]; /* reserved - must be zero */
};
-
/******************************************/
/* IA64 Extensions to ACPI Spec Rev 0.71 */
/* for the Fixed ACPI Description Table */
/******************************************/
-struct
-{
- struct acpi_table_header header; /* table header */
- u32 reserved_pad; /* IA64 alignment, must be 0 */
- u64 firmware_ctrl; /* 64-bit Physical address of FACS */
- u64 dsdt; /* 64-bit Physical address of DSDT */
- u8 model; /* System Interrupt Model */
- u8 address_space; /* Address Space Bitmask */
- u16 sci_int; /* System vector of SCI interrupt */
- 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 */
- u64 smi_cmd; /* Port address of SMI command port */
- u64 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- u64 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- u64 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- u64 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- u64 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- u64 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- u64 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- u64 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 */
- u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */
- u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */
- 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; /* reserved */
- u32 flush_cash : 1; /* PAL_FLUSH_CACHE is correctly supported */
- u32 reserved5 : 1; /* reserved - must be zero */
- u32 proc_c1 : 1; /* all processors support C1 state */
- u32 plvl2_up : 1; /* C2 state works on MP system */
- u32 pwr_button : 1; /* Power button is handled as a generic feature */
- u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
- u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
- u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- u32 tmr_val_ext : 1; /* tmr_val is 32 bits */
- u32 dock_cap : 1; /* Supports Docking */
- u32 reserved6 : 22; /* reserved - must be zero */
+struct {
+ struct acpi_table_header header; /* table header */
+ u32 reserved_pad; /* IA64 alignment, must be 0 */
+ u64 firmware_ctrl; /* 64-bit Physical address of FACS */
+ u64 dsdt; /* 64-bit Physical address of DSDT */
+ u8 model; /* System Interrupt Model */
+ u8 address_space; /* Address Space Bitmask */
+ u16 sci_int; /* System vector of SCI interrupt */
+ 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 */
+ u64 smi_cmd; /* Port address of SMI command port */
+ u64 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
+ u64 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
+ u64 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
+ u64 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
+ u64 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
+ u64 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
+ u64 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
+ u64 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 */
+ u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */
+ u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */
+ 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; /* reserved */
+ u32 flush_cash:1; /* PAL_FLUSH_CACHE is correctly supported */
+ u32 reserved5:1; /* reserved - must be zero */
+ u32 proc_c1:1; /* all processors support C1 state */
+ u32 plvl2_up:1; /* C2 state works on MP system */
+ u32 pwr_button:1; /* Power button is handled as a generic feature */
+ u32 sleep_button:1; /* Sleep button is handled as a generic feature, or not present */
+ u32 fixed_rTC:1; /* RTC wakeup stat not in fixed register space */
+ u32 rtcs4:1; /* RTC wakeup stat not possible from S4 */
+ u32 tmr_val_ext:1; /* tmr_val is 32 bits */
+ u32 dock_cap:1; /* Supports Docking */
+ u32 reserved6:22; /* reserved - must be zero */
};
#pragma pack()
-#endif /* __ACTBL71_H__ */
-
+#endif /* __ACTBL71_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 3a451dc48ac8..6213b27516e8 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -46,35 +46,31 @@
/*! [Begin] no source code translation (keep the typedefs) */
-
-
/*
* Data type ranges
* Note: These macros are designed to be compiler independent as well as
* working around problems that some 32-bit compilers have with 64-bit
* constants.
*/
-#define ACPI_UINT8_MAX (UINT8) (~((UINT8) 0)) /* 0xFF */
-#define ACPI_UINT16_MAX (UINT16)(~((UINT16) 0)) /* 0xFFFF */
-#define ACPI_UINT32_MAX (UINT32)(~((UINT32) 0)) /* 0xFFFFFFFF */
-#define ACPI_UINT64_MAX (UINT64)(~((UINT64) 0)) /* 0xFFFFFFFFFFFFFFFF */
+#define ACPI_UINT8_MAX (UINT8) (~((UINT8) 0)) /* 0xFF */
+#define ACPI_UINT16_MAX (UINT16)(~((UINT16) 0)) /* 0xFFFF */
+#define ACPI_UINT32_MAX (UINT32)(~((UINT32) 0)) /* 0xFFFFFFFF */
+#define ACPI_UINT64_MAX (UINT64)(~((UINT64) 0)) /* 0xFFFFFFFFFFFFFFFF */
#define ACPI_ASCII_MAX 0x7F
-
#ifdef DEFINE_ALTERNATE_TYPES
/*
* Types used only in translated source, defined here to enable
* cross-platform compilation only.
*/
-typedef int s32;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef COMPILER_DEPENDENT_UINT64 u64;
+typedef int s32;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef COMPILER_DEPENDENT_UINT64 u64;
#endif
-
/*
* Data types - Fixed across all compilation models (16/32/64)
*
@@ -102,30 +98,29 @@ typedef COMPILER_DEPENDENT_UINT64 u64;
/*
* 64-bit type definitions
*/
-typedef unsigned char UINT8;
-typedef unsigned char BOOLEAN;
-typedef unsigned short UINT16;
-typedef int INT32;
-typedef unsigned int UINT32;
-typedef COMPILER_DEPENDENT_INT64 INT64;
-typedef COMPILER_DEPENDENT_UINT64 UINT64;
+typedef unsigned char UINT8;
+typedef unsigned char BOOLEAN;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+typedef COMPILER_DEPENDENT_INT64 INT64;
+typedef COMPILER_DEPENDENT_UINT64 UINT64;
/*! [End] no source code translation !*/
-typedef s64 acpi_native_int;
-typedef u64 acpi_native_uint;
+typedef s64 acpi_native_int;
+typedef u64 acpi_native_uint;
-typedef u64 acpi_table_ptr;
-typedef u64 acpi_io_address;
-typedef u64 acpi_physical_address;
-typedef u64 acpi_size;
+typedef u64 acpi_table_ptr;
+typedef u64 acpi_io_address;
+typedef u64 acpi_physical_address;
+typedef u64 acpi_size;
-#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 /* No hardware alignment support in IA64 */
-#define ACPI_USE_NATIVE_DIVIDE /* Native 64-bit integer support */
+#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 /* No hardware alignment support in IA64 */
+#define ACPI_USE_NATIVE_DIVIDE /* Native 64-bit integer support */
#define ACPI_MAX_PTR ACPI_UINT64_MAX
#define ACPI_SIZE_MAX ACPI_UINT64_MAX
-
#elif ACPI_MACHINE_WIDTH == 16
/*! [Begin] no source code translation (keep the typedefs) */
@@ -133,32 +128,31 @@ typedef u64 acpi_size;
/*
* 16-bit type definitions
*/
-typedef unsigned char UINT8;
-typedef unsigned char BOOLEAN;
-typedef unsigned int UINT16;
-typedef long INT32;
-typedef int INT16;
-typedef unsigned long UINT32;
-
-struct
-{
- UINT32 Lo;
- UINT32 Hi;
+typedef unsigned char UINT8;
+typedef unsigned char BOOLEAN;
+typedef unsigned int UINT16;
+typedef long INT32;
+typedef int INT16;
+typedef unsigned long UINT32;
+
+struct {
+ UINT32 Lo;
+ UINT32 Hi;
};
/*! [End] no source code translation !*/
-typedef u16 acpi_native_uint;
-typedef s16 acpi_native_int;
+typedef u16 acpi_native_uint;
+typedef s16 acpi_native_int;
-typedef u32 acpi_table_ptr;
-typedef u32 acpi_io_address;
-typedef char *acpi_physical_address;
-typedef u16 acpi_size;
+typedef u32 acpi_table_ptr;
+typedef u32 acpi_io_address;
+typedef char *acpi_physical_address;
+typedef u16 acpi_size;
#define ALIGNED_ADDRESS_BOUNDARY 0x00000002
#define ACPI_MISALIGNED_TRANSFERS
-#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */
+#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */
#define ACPI_MAX_PTR ACPI_UINT16_MAX
#define ACPI_SIZE_MAX ACPI_UINT16_MAX
@@ -168,7 +162,6 @@ typedef u16 acpi_size;
*/
#define ACPI_NO_INTEGER64_SUPPORT
-
#elif ACPI_MACHINE_WIDTH == 32
/*! [Begin] no source code translation (keep the typedefs) */
@@ -176,23 +169,23 @@ typedef u16 acpi_size;
/*
* 32-bit type definitions (default)
*/
-typedef unsigned char UINT8;
-typedef unsigned char BOOLEAN;
-typedef unsigned short UINT16;
-typedef int INT32;
-typedef unsigned int UINT32;
-typedef COMPILER_DEPENDENT_INT64 INT64;
-typedef COMPILER_DEPENDENT_UINT64 UINT64;
+typedef unsigned char UINT8;
+typedef unsigned char BOOLEAN;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+typedef COMPILER_DEPENDENT_INT64 INT64;
+typedef COMPILER_DEPENDENT_UINT64 UINT64;
/*! [End] no source code translation !*/
-typedef s32 acpi_native_int;
-typedef u32 acpi_native_uint;
+typedef s32 acpi_native_int;
+typedef u32 acpi_native_uint;
-typedef u64 acpi_table_ptr;
-typedef u32 acpi_io_address;
-typedef u64 acpi_physical_address;
-typedef u32 acpi_size;
+typedef u64 acpi_table_ptr;
+typedef u32 acpi_io_address;
+typedef u64 acpi_physical_address;
+typedef u32 acpi_size;
#define ALIGNED_ADDRESS_BOUNDARY 0x00000004
#define ACPI_MISALIGNED_TRANSFERS
@@ -203,29 +196,27 @@ typedef u32 acpi_size;
#error unknown ACPI_MACHINE_WIDTH
#endif
-
/*
- * Miscellaneous common types
+ * This type is used for bitfields in ACPI tables. The only type that is
+ * even remotely portable is u8. Anything else is not portable, so
+ * do not add any more bitfield types.
*/
-typedef u16 UINT16_BIT;
-typedef u32 UINT32_BIT;
-typedef acpi_native_uint ACPI_PTRDIFF;
+typedef u8 UINT8_BIT;
+typedef acpi_native_uint ACPI_PTRDIFF;
/*
* Pointer overlays to avoid lots of typecasting for
* code that accepts both physical and logical pointers.
*/
-union acpi_pointers
-{
- acpi_physical_address physical;
- void *logical;
- acpi_table_ptr value;
+union acpi_pointers {
+ acpi_physical_address physical;
+ void *logical;
+ acpi_table_ptr value;
};
-struct acpi_pointer
-{
- u32 pointer_type;
- union acpi_pointers pointer;
+struct acpi_pointer {
+ u32 pointer_type;
+ union acpi_pointers pointer;
};
/* pointer_types for above */
@@ -243,6 +234,14 @@ struct acpi_pointer
#define ACPI_LOGMODE_PHYSPTR ACPI_LOGICAL_ADDRESSING | ACPI_PHYSICAL_POINTER
#define ACPI_LOGMODE_LOGPTR ACPI_LOGICAL_ADDRESSING | ACPI_LOGICAL_POINTER
+/*
+ * If acpi_cache_t was not defined in the OS-dependent header,
+ * define it now. This is typically the case where the local cache
+ * manager implementation is to be used (ACPI_USE_LOCAL_CACHE)
+ */
+#ifndef acpi_cache_t
+#define acpi_cache_t struct acpi_memory_list
+#endif
/*
* Useful defines
@@ -261,34 +260,29 @@ struct acpi_pointer
#define NULL (void *) 0
#endif
-
/*
* Local datatypes
*/
-typedef u32 acpi_status; /* All ACPI Exceptions */
-typedef u32 acpi_name; /* 4-byte ACPI name */
-typedef char * acpi_string; /* Null terminated ASCII string */
-typedef void * acpi_handle; /* Actually a ptr to an Node */
-
-struct uint64_struct
-{
- u32 lo;
- u32 hi;
+typedef u32 acpi_status; /* All ACPI Exceptions */
+typedef u32 acpi_name; /* 4-byte ACPI name */
+typedef char *acpi_string; /* Null terminated ASCII string */
+typedef void *acpi_handle; /* Actually a ptr to an Node */
+
+struct uint64_struct {
+ u32 lo;
+ u32 hi;
};
-union uint64_overlay
-{
- u64 full;
- struct uint64_struct part;
+union uint64_overlay {
+ u64 full;
+ struct uint64_struct part;
};
-struct uint32_struct
-{
- u32 lo;
- u32 hi;
+struct uint32_struct {
+ u32 lo;
+ u32 hi;
};
-
/*
* Acpi integer width. In ACPI version 1, integers are
* 32 bits. In ACPI version 2, integers are 64 bits.
@@ -300,26 +294,24 @@ struct uint32_struct
/* 32-bit integers only, no 64-bit support */
-typedef u32 acpi_integer;
+typedef u32 acpi_integer;
#define ACPI_INTEGER_MAX ACPI_UINT32_MAX
#define ACPI_INTEGER_BIT_SIZE 32
-#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */
-
-#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */
+#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */
+#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */
#else
/* 64-bit integers */
-typedef u64 acpi_integer;
+typedef u64 acpi_integer;
#define ACPI_INTEGER_MAX ACPI_UINT64_MAX
#define ACPI_INTEGER_BIT_SIZE 64
-#define ACPI_MAX_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */
-
+#define ACPI_MAX_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */
#if ACPI_MACHINE_WIDTH == 64
-#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */
+#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */
#endif
#endif
@@ -333,7 +325,6 @@ typedef u64 acpi_integer;
*/
#define ACPI_ROOT_OBJECT (acpi_handle) ACPI_PTR_ADD (char, NULL, ACPI_MAX_PTR)
-
/*
* Initialization sequence
*/
@@ -400,7 +391,7 @@ typedef u64 acpi_integer;
/*
* Table types. These values are passed to the table related APIs
*/
-typedef u32 acpi_table_type;
+typedef u32 acpi_table_type;
#define ACPI_TABLE_RSDP (acpi_table_type) 0
#define ACPI_TABLE_DSDT (acpi_table_type) 1
@@ -421,22 +412,22 @@ typedef u32 acpi_table_type;
* NOTE: Types must be kept in sync with the global acpi_ns_properties
* and acpi_ns_type_names arrays.
*/
-typedef u32 acpi_object_type;
+typedef u32 acpi_object_type;
#define ACPI_TYPE_ANY 0x00
-#define ACPI_TYPE_INTEGER 0x01 /* Byte/Word/Dword/Zero/One/Ones */
+#define ACPI_TYPE_INTEGER 0x01 /* Byte/Word/Dword/Zero/One/Ones */
#define ACPI_TYPE_STRING 0x02
#define ACPI_TYPE_BUFFER 0x03
-#define ACPI_TYPE_PACKAGE 0x04 /* byte_const, multiple data_term/Constant/super_name */
+#define ACPI_TYPE_PACKAGE 0x04 /* byte_const, multiple data_term/Constant/super_name */
#define ACPI_TYPE_FIELD_UNIT 0x05
-#define ACPI_TYPE_DEVICE 0x06 /* Name, multiple Node */
+#define ACPI_TYPE_DEVICE 0x06 /* Name, multiple Node */
#define ACPI_TYPE_EVENT 0x07
-#define ACPI_TYPE_METHOD 0x08 /* Name, byte_const, multiple Code */
+#define ACPI_TYPE_METHOD 0x08 /* Name, byte_const, multiple Code */
#define ACPI_TYPE_MUTEX 0x09
#define ACPI_TYPE_REGION 0x0A
-#define ACPI_TYPE_POWER 0x0B /* Name,byte_const,word_const,multi Node */
-#define ACPI_TYPE_PROCESSOR 0x0C /* Name,byte_const,Dword_const,byte_const,multi nm_o */
-#define ACPI_TYPE_THERMAL 0x0D /* Name, multiple Node */
+#define ACPI_TYPE_POWER 0x0B /* Name,byte_const,word_const,multi Node */
+#define ACPI_TYPE_PROCESSOR 0x0C /* Name,byte_const,Dword_const,byte_const,multi nm_o */
+#define ACPI_TYPE_THERMAL 0x0D /* Name, multiple Node */
#define ACPI_TYPE_BUFFER_FIELD 0x0E
#define ACPI_TYPE_DDB_HANDLE 0x0F
#define ACPI_TYPE_DEBUG_OBJECT 0x10
@@ -453,16 +444,16 @@ typedef u32 acpi_object_type;
#define ACPI_TYPE_LOCAL_REGION_FIELD 0x11
#define ACPI_TYPE_LOCAL_BANK_FIELD 0x12
#define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13
-#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */
+#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */
#define ACPI_TYPE_LOCAL_ALIAS 0x15
#define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16
#define ACPI_TYPE_LOCAL_NOTIFY 0x17
#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18
#define ACPI_TYPE_LOCAL_RESOURCE 0x19
#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A
-#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple object_list Nodes */
+#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple object_list Nodes */
-#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */
+#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */
/*
* These are special object types that never appear in
@@ -506,7 +497,7 @@ typedef u32 acpi_object_type;
#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE)
#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
-#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */
+#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */
#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF
/*
@@ -519,7 +510,7 @@ typedef u32 acpi_object_type;
/*
* Event Types: Fixed & General Purpose
*/
-typedef u32 acpi_event_type;
+typedef u32 acpi_event_type;
/*
* Fixed events
@@ -547,7 +538,7 @@ typedef u32 acpi_event_type;
* | +----- Set?
* +----------- <Reserved>
*/
-typedef u32 acpi_event_status;
+typedef u32 acpi_event_status;
#define ACPI_EVENT_FLAG_DISABLED (acpi_event_status) 0x00
#define ACPI_EVENT_FLAG_ENABLED (acpi_event_status) 0x01
@@ -564,7 +555,6 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1
-
/*
* GPE info flags - Per GPE
* +-+-+-+---+---+-+
@@ -585,22 +575,22 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_TYPE_MASK (u8) 0x06
#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06
#define ACPI_GPE_TYPE_WAKE (u8) 0x02
-#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */
+#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */
#define ACPI_GPE_DISPATCH_MASK (u8) 0x18
#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08
#define ACPI_GPE_DISPATCH_METHOD (u8) 0x10
-#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */
+#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */
#define ACPI_GPE_RUN_ENABLE_MASK (u8) 0x20
#define ACPI_GPE_RUN_ENABLED (u8) 0x20
-#define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */
+#define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */
#define ACPI_GPE_WAKE_ENABLE_MASK (u8) 0x40
#define ACPI_GPE_WAKE_ENABLED (u8) 0x40
-#define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */
+#define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */
-#define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */
+#define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */
#define ACPI_GPE_SYSTEM_MASK (u8) 0x80
#define ACPI_GPE_SYSTEM_RUNNING (u8) 0x80
@@ -609,13 +599,12 @@ typedef u32 acpi_event_status;
/*
* Flags for GPE and Lock interfaces
*/
-#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */
-#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */
+#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */
+#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */
#define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0
-
/* Notify types */
#define ACPI_SYSTEM_NOTIFY 0x1
@@ -625,10 +614,9 @@ typedef u32 acpi_event_status;
#define ACPI_MAX_SYS_NOTIFY 0x7f
-
/* Address Space (Operation Region) Types */
-typedef u8 acpi_adr_space_type;
+typedef u8 acpi_adr_space_type;
#define ACPI_ADR_SPACE_SYSTEM_MEMORY (acpi_adr_space_type) 0
#define ACPI_ADR_SPACE_SYSTEM_IO (acpi_adr_space_type) 1
@@ -640,7 +628,6 @@ typedef u8 acpi_adr_space_type;
#define ACPI_ADR_SPACE_DATA_TABLE (acpi_adr_space_type) 7
#define ACPI_ADR_SPACE_FIXED_HARDWARE (acpi_adr_space_type) 127
-
/*
* bit_register IDs
* These are bitfields defined within the full ACPI registers
@@ -674,74 +661,62 @@ typedef u8 acpi_adr_space_type;
#define ACPI_BITREG_MAX 0x15
#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1
-
/*
* External ACPI object definition
*/
-union acpi_object
-{
- acpi_object_type type; /* See definition of acpi_ns_type for values */
- struct
- {
- acpi_object_type type;
- acpi_integer value; /* The actual number */
+union acpi_object {
+ acpi_object_type type; /* See definition of acpi_ns_type for values */
+ struct {
+ acpi_object_type type;
+ acpi_integer value; /* The actual number */
} integer;
- struct
- {
- acpi_object_type type;
- u32 length; /* # of bytes in string, excluding trailing null */
- char *pointer; /* points to the string value */
+ struct {
+ acpi_object_type type;
+ u32 length; /* # of bytes in string, excluding trailing null */
+ char *pointer; /* points to the string value */
} string;
- struct
- {
- acpi_object_type type;
- u32 length; /* # of bytes in buffer */
- u8 *pointer; /* points to the buffer */
+ struct {
+ acpi_object_type type;
+ u32 length; /* # of bytes in buffer */
+ u8 *pointer; /* points to the buffer */
} buffer;
- struct
- {
- acpi_object_type type;
- u32 fill1;
- acpi_handle handle; /* object reference */
+ struct {
+ acpi_object_type type;
+ u32 fill1;
+ acpi_handle handle; /* object reference */
} reference;
- struct
- {
- acpi_object_type type;
- u32 count; /* # of elements in package */
- union acpi_object *elements; /* Pointer to an array of ACPI_OBJECTs */
+ struct {
+ acpi_object_type type;
+ u32 count; /* # of elements in package */
+ union acpi_object *elements; /* Pointer to an array of ACPI_OBJECTs */
} package;
- struct
- {
- acpi_object_type type;
- u32 proc_id;
- acpi_io_address pblk_address;
- u32 pblk_length;
+ struct {
+ acpi_object_type type;
+ u32 proc_id;
+ acpi_io_address pblk_address;
+ u32 pblk_length;
} processor;
- struct
- {
- acpi_object_type type;
- u32 system_level;
- u32 resource_order;
+ struct {
+ acpi_object_type type;
+ u32 system_level;
+ u32 resource_order;
} power_resource;
};
-
/*
* List of objects, used as a parameter list for control method evaluation
*/
-struct acpi_object_list
-{
- u32 count;
- union acpi_object *pointer;
+struct acpi_object_list {
+ u32 count;
+ union acpi_object *pointer;
};
-
/*
* Miscellaneous common Data Structures used by the interfaces
*/
@@ -749,13 +724,11 @@ struct acpi_object_list
#define ACPI_ALLOCATE_BUFFER (acpi_size) (-1)
#define ACPI_ALLOCATE_LOCAL_BUFFER (acpi_size) (-2)
-struct acpi_buffer
-{
- acpi_size length; /* Length in bytes of the buffer */
- void *pointer; /* pointer to buffer */
+struct acpi_buffer {
+ acpi_size length; /* Length in bytes of the buffer */
+ void *pointer; /* pointer to buffer */
};
-
/*
* name_type for acpi_get_name
*/
@@ -763,7 +736,6 @@ struct acpi_buffer
#define ACPI_SINGLE_NAME 1
#define ACPI_NAME_TYPE_MAX 1
-
/*
* Structure and flags for acpi_get_system_info
*/
@@ -772,139 +744,106 @@ struct acpi_buffer
#define ACPI_SYS_MODE_LEGACY 0x0002
#define ACPI_SYS_MODES_MASK 0x0003
-
/*
* ACPI Table Info. One per ACPI table _type_
*/
-struct acpi_table_info
-{
- u32 count;
+struct acpi_table_info {
+ u32 count;
};
-
/*
* System info returned by acpi_get_system_info()
*/
-struct acpi_system_info
-{
- u32 acpi_ca_version;
- u32 flags;
- u32 timer_resolution;
- u32 reserved1;
- u32 reserved2;
- u32 debug_level;
- u32 debug_layer;
- u32 num_table_types;
- struct acpi_table_info table_info [NUM_ACPI_TABLE_TYPES];
+struct acpi_system_info {
+ u32 acpi_ca_version;
+ u32 flags;
+ u32 timer_resolution;
+ u32 reserved1;
+ u32 reserved2;
+ u32 debug_level;
+ u32 debug_layer;
+ u32 num_table_types;
+ struct acpi_table_info table_info[NUM_ACPI_TABLE_TYPES];
};
-
/*
* Types specific to the OS service interfaces
*/
-typedef u32
-(ACPI_SYSTEM_XFACE *acpi_osd_handler) (
- void *context);
+typedef u32(ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
typedef void
-(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) (
- void *context);
+ (ACPI_SYSTEM_XFACE * acpi_osd_exec_callback) (void *context);
/*
* Various handlers and callback procedures
*/
-typedef
-u32 (*acpi_event_handler) (
- void *context);
+typedef u32(*acpi_event_handler) (void *context);
typedef
-void (*acpi_notify_handler) (
- acpi_handle device,
- u32 value,
- void *context);
+void (*acpi_notify_handler) (acpi_handle device, u32 value, void *context);
typedef
-void (*acpi_object_handler) (
- acpi_handle object,
- u32 function,
- void *data);
+void (*acpi_object_handler) (acpi_handle object, u32 function, void *data);
-typedef
-acpi_status (*acpi_init_handler) (
- acpi_handle object,
- u32 function);
+typedef acpi_status(*acpi_init_handler) (acpi_handle object, u32 function);
#define ACPI_INIT_DEVICE_INI 1
typedef
-acpi_status (*acpi_exception_handler) (
- acpi_status aml_status,
- acpi_name name,
- u16 opcode,
- u32 aml_offset,
- void *context);
-
+acpi_status(*acpi_exception_handler) (acpi_status aml_status,
+ acpi_name name,
+ u16 opcode,
+ u32 aml_offset, void *context);
/* Address Spaces (For Operation Regions) */
typedef
-acpi_status (*acpi_adr_space_handler) (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context);
+acpi_status(*acpi_adr_space_handler) (u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context,
+ void *region_context);
#define ACPI_DEFAULT_HANDLER NULL
-
typedef
-acpi_status (*acpi_adr_space_setup) (
- acpi_handle region_handle,
- u32 function,
- void *handler_context,
- void **region_context);
+acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle,
+ u32 function,
+ void *handler_context,
+ void **region_context);
#define ACPI_REGION_ACTIVATE 0
#define ACPI_REGION_DEACTIVATE 1
typedef
-acpi_status (*acpi_walk_callback) (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value);
-
+acpi_status(*acpi_walk_callback) (acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value);
/* Interrupt handler return values */
#define ACPI_INTERRUPT_NOT_HANDLED 0x00
#define ACPI_INTERRUPT_HANDLED 0x01
-
/* Common string version of device HIDs and UIDs */
-struct acpi_device_id
-{
- char value[ACPI_DEVICE_ID_LENGTH];
+struct acpi_device_id {
+ char value[ACPI_DEVICE_ID_LENGTH];
};
/* Common string version of device CIDs */
-struct acpi_compatible_id
-{
- char value[ACPI_MAX_CID_LENGTH];
+struct acpi_compatible_id {
+ char value[ACPI_MAX_CID_LENGTH];
};
-struct acpi_compatible_id_list
-{
- u32 count;
- u32 size;
- struct acpi_compatible_id id[1];
+struct acpi_compatible_id_list {
+ u32 count;
+ u32 size;
+ struct acpi_compatible_id id[1];
};
-
/* Structure and flags for acpi_get_object_info */
#define ACPI_VALID_STA 0x0001
@@ -914,55 +853,45 @@ struct acpi_compatible_id_list
#define ACPI_VALID_CID 0x0010
#define ACPI_VALID_SXDS 0x0020
-
#define ACPI_COMMON_OBJ_INFO \
acpi_object_type type; /* ACPI object type */ \
- acpi_name name /* ACPI object Name */
-
+ acpi_name name /* ACPI object Name */
-struct acpi_obj_info_header
-{
+struct acpi_obj_info_header {
ACPI_COMMON_OBJ_INFO;
};
-
/* Structure returned from Get Object Info */
-struct acpi_device_info
-{
+struct acpi_device_info {
ACPI_COMMON_OBJ_INFO;
- u32 valid; /* Indicates which fields below are valid */
- u32 current_status; /* _STA value */
- acpi_integer address; /* _ADR value if any */
- struct acpi_device_id hardware_id; /* _HID value if any */
- struct acpi_device_id unique_id; /* _UID value if any */
- u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
- struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */
+ u32 valid; /* Indicates which fields below are valid */
+ u32 current_status; /* _STA value */
+ acpi_integer address; /* _ADR value if any */
+ struct acpi_device_id hardware_id; /* _HID value if any */
+ struct acpi_device_id unique_id; /* _UID value if any */
+ u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
+ struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */
};
-
/* Context structs for address space handlers */
-struct acpi_pci_id
-{
- u16 segment;
- u16 bus;
- u16 device;
- u16 function;
+struct acpi_pci_id {
+ u16 segment;
+ u16 bus;
+ u16 device;
+ u16 function;
};
-
-struct acpi_mem_space_context
-{
- u32 length;
- acpi_physical_address address;
- acpi_physical_address mapped_physical_address;
- u8 *mapped_logical_address;
- acpi_size mapped_length;
+struct acpi_mem_space_context {
+ u32 length;
+ acpi_physical_address address;
+ acpi_physical_address mapped_physical_address;
+ u8 *mapped_logical_address;
+ acpi_size mapped_length;
};
-
/*
* Definitions for Resource Attributes
*/
@@ -992,8 +921,8 @@ struct acpi_mem_space_context
/*
* IO Port Descriptor Decode
*/
-#define ACPI_DECODE_10 (u8) 0x00 /* 10-bit IO address decode */
-#define ACPI_DECODE_16 (u8) 0x01 /* 16-bit IO address decode */
+#define ACPI_DECODE_10 (u8) 0x00 /* 10-bit IO address decode */
+#define ACPI_DECODE_16 (u8) 0x01 /* 16-bit IO address decode */
/*
* IRQ Attributes
@@ -1045,32 +974,28 @@ struct acpi_mem_space_context
#define ACPI_PRODUCER (u8) 0x00
#define ACPI_CONSUMER (u8) 0x01
-
/*
* Structures used to describe device resources
*/
-struct acpi_resource_irq
-{
- u32 edge_level;
- u32 active_high_low;
- u32 shared_exclusive;
- u32 number_of_interrupts;
- u32 interrupts[1];
+struct acpi_resource_irq {
+ u32 edge_level;
+ u32 active_high_low;
+ u32 shared_exclusive;
+ u32 number_of_interrupts;
+ u32 interrupts[1];
};
-struct acpi_resource_dma
-{
- u32 type;
- u32 bus_master;
- u32 transfer;
- u32 number_of_channels;
- u32 channels[1];
+struct acpi_resource_dma {
+ u32 type;
+ u32 bus_master;
+ u32 transfer;
+ u32 number_of_channels;
+ u32 channels[1];
};
-struct acpi_resource_start_dpf
-{
- u32 compatibility_priority;
- u32 performance_robustness;
+struct acpi_resource_start_dpf {
+ u32 compatibility_priority;
+ u32 performance_robustness;
};
/*
@@ -1078,149 +1003,127 @@ struct acpi_resource_start_dpf
* needed because it has no fields
*/
-struct acpi_resource_io
-{
- u32 io_decode;
- u32 min_base_address;
- u32 max_base_address;
- u32 alignment;
- u32 range_length;
+struct acpi_resource_io {
+ u32 io_decode;
+ u32 min_base_address;
+ u32 max_base_address;
+ u32 alignment;
+ u32 range_length;
};
-struct acpi_resource_fixed_io
-{
- u32 base_address;
- u32 range_length;
+struct acpi_resource_fixed_io {
+ u32 base_address;
+ u32 range_length;
};
-struct acpi_resource_vendor
-{
- u32 length;
- u8 reserved[1];
+struct acpi_resource_vendor {
+ u32 length;
+ u8 reserved[1];
};
-struct acpi_resource_end_tag
-{
- u8 checksum;
+struct acpi_resource_end_tag {
+ u8 checksum;
};
-struct acpi_resource_mem24
-{
- u32 read_write_attribute;
- u32 min_base_address;
- u32 max_base_address;
- u32 alignment;
- u32 range_length;
+struct acpi_resource_mem24 {
+ u32 read_write_attribute;
+ u32 min_base_address;
+ u32 max_base_address;
+ u32 alignment;
+ u32 range_length;
};
-struct acpi_resource_mem32
-{
- u32 read_write_attribute;
- u32 min_base_address;
- u32 max_base_address;
- u32 alignment;
- u32 range_length;
+struct acpi_resource_mem32 {
+ u32 read_write_attribute;
+ u32 min_base_address;
+ u32 max_base_address;
+ u32 alignment;
+ u32 range_length;
};
-struct acpi_resource_fixed_mem32
-{
- u32 read_write_attribute;
- u32 range_base_address;
- u32 range_length;
+struct acpi_resource_fixed_mem32 {
+ u32 read_write_attribute;
+ u32 range_base_address;
+ u32 range_length;
};
-struct acpi_memory_attribute
-{
- u16 cache_attribute;
- u16 read_write_attribute;
+struct acpi_memory_attribute {
+ u16 cache_attribute;
+ u16 read_write_attribute;
};
-struct acpi_io_attribute
-{
- u16 range_attribute;
- u16 translation_attribute;
+struct acpi_io_attribute {
+ u16 range_attribute;
+ u16 translation_attribute;
};
-struct acpi_bus_attribute
-{
- u16 reserved1;
- u16 reserved2;
+struct acpi_bus_attribute {
+ u16 reserved1;
+ u16 reserved2;
};
-union acpi_resource_attribute
-{
- struct acpi_memory_attribute memory;
- struct acpi_io_attribute io;
- struct acpi_bus_attribute bus;
+union acpi_resource_attribute {
+ struct acpi_memory_attribute memory;
+ struct acpi_io_attribute io;
+ struct acpi_bus_attribute bus;
};
-struct acpi_resource_source
-{
- u32 index;
- u32 string_length;
- char *string_ptr;
+struct acpi_resource_source {
+ u32 index;
+ u32 string_length;
+ char *string_ptr;
};
-struct acpi_resource_address16
-{
- u32 resource_type;
- u32 producer_consumer;
- u32 decode;
- u32 min_address_fixed;
- u32 max_address_fixed;
- union acpi_resource_attribute attribute;
- u32 granularity;
- u32 min_address_range;
- u32 max_address_range;
- u32 address_translation_offset;
- u32 address_length;
- struct acpi_resource_source resource_source;
-};
+/* Fields common to all address descriptors, 16/32/64 bit */
-struct acpi_resource_address32
-{
- u32 resource_type;
- u32 producer_consumer;
- u32 decode;
- u32 min_address_fixed;
- u32 max_address_fixed;
+#define ACPI_RESOURCE_ADDRESS_COMMON \
+ u32 resource_type; \
+ u32 producer_consumer; \
+ u32 decode; \
+ u32 min_address_fixed; \
+ u32 max_address_fixed; \
union acpi_resource_attribute attribute;
- u32 granularity;
- u32 min_address_range;
- u32 max_address_range;
- u32 address_translation_offset;
- u32 address_length;
- struct acpi_resource_source resource_source;
+
+struct acpi_resource_address {
+ACPI_RESOURCE_ADDRESS_COMMON};
+
+struct acpi_resource_address16 {
+ ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
+ u32 min_address_range;
+ u32 max_address_range;
+ u32 address_translation_offset;
+ u32 address_length;
+ struct acpi_resource_source resource_source;
};
-struct acpi_resource_address64
-{
- u32 resource_type;
- u32 producer_consumer;
- u32 decode;
- u32 min_address_fixed;
- u32 max_address_fixed;
- union acpi_resource_attribute attribute;
- u64 granularity;
- u64 min_address_range;
- u64 max_address_range;
- u64 address_translation_offset;
- u64 address_length;
- u64 type_specific_attributes;
- struct acpi_resource_source resource_source;
+struct acpi_resource_address32 {
+ ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
+ u32 min_address_range;
+ u32 max_address_range;
+ u32 address_translation_offset;
+ u32 address_length;
+ struct acpi_resource_source resource_source;
};
-struct acpi_resource_ext_irq
-{
- u32 producer_consumer;
- u32 edge_level;
- u32 active_high_low;
- u32 shared_exclusive;
- u32 number_of_interrupts;
- struct acpi_resource_source resource_source;
- u32 interrupts[1];
+struct acpi_resource_address64 {
+ ACPI_RESOURCE_ADDRESS_COMMON u64 granularity;
+ u64 min_address_range;
+ u64 max_address_range;
+ u64 address_translation_offset;
+ u64 address_length;
+ u64 type_specific_attributes;
+ struct acpi_resource_source resource_source;
};
+struct acpi_resource_ext_irq {
+ u32 producer_consumer;
+ u32 edge_level;
+ u32 active_high_low;
+ u32 shared_exclusive;
+ u32 number_of_interrupts;
+ struct acpi_resource_source resource_source;
+ u32 interrupts[1];
+};
/* ACPI_RESOURCE_TYPEs */
@@ -1240,35 +1143,34 @@ struct acpi_resource_ext_irq
#define ACPI_RSTYPE_ADDRESS64 13
#define ACPI_RSTYPE_EXT_IRQ 14
-typedef u32 acpi_resource_type;
-
-union acpi_resource_data
-{
- struct acpi_resource_irq irq;
- struct acpi_resource_dma dma;
- struct acpi_resource_start_dpf start_dpf;
- struct acpi_resource_io io;
- struct acpi_resource_fixed_io fixed_io;
- struct acpi_resource_vendor vendor_specific;
- struct acpi_resource_end_tag end_tag;
- struct acpi_resource_mem24 memory24;
- struct acpi_resource_mem32 memory32;
- struct acpi_resource_fixed_mem32 fixed_memory32;
- struct acpi_resource_address16 address16;
- struct acpi_resource_address32 address32;
- struct acpi_resource_address64 address64;
- struct acpi_resource_ext_irq extended_irq;
+typedef u32 acpi_resource_type;
+
+union acpi_resource_data {
+ struct acpi_resource_irq irq;
+ struct acpi_resource_dma dma;
+ struct acpi_resource_start_dpf start_dpf;
+ struct acpi_resource_io io;
+ struct acpi_resource_fixed_io fixed_io;
+ struct acpi_resource_vendor vendor_specific;
+ struct acpi_resource_end_tag end_tag;
+ struct acpi_resource_mem24 memory24;
+ struct acpi_resource_mem32 memory32;
+ struct acpi_resource_fixed_mem32 fixed_memory32;
+ struct acpi_resource_address address; /* Common 16/32/64 address fields */
+ struct acpi_resource_address16 address16;
+ struct acpi_resource_address32 address32;
+ struct acpi_resource_address64 address64;
+ struct acpi_resource_ext_irq extended_irq;
};
-struct acpi_resource
-{
- acpi_resource_type id;
- u32 length;
- union acpi_resource_data data;
+struct acpi_resource {
+ acpi_resource_type id;
+ u32 length;
+ union acpi_resource_data data;
};
#define ACPI_RESOURCE_LENGTH 12
-#define ACPI_RESOURCE_LENGTH_NO_DATA 8 /* Id + Length fields */
+#define ACPI_RESOURCE_LENGTH_NO_DATA 8 /* Id + Length fields */
#define ACPI_SIZEOF_RESOURCE(type) (ACPI_RESOURCE_LENGTH_NO_DATA + sizeof (type))
@@ -1284,19 +1186,16 @@ struct acpi_resource
* END: of definitions for Resource Attributes
*/
-
-struct acpi_pci_routing_table
-{
- u32 length;
- u32 pin;
- acpi_integer address; /* here for 64-bit alignment */
- u32 source_index;
- char source[4]; /* pad to 64 bits so sizeof() works in all cases */
+struct acpi_pci_routing_table {
+ u32 length;
+ u32 pin;
+ acpi_integer address; /* here for 64-bit alignment */
+ u32 source_index;
+ char source[4]; /* pad to 64 bits so sizeof() works in all cases */
};
/*
* END: of definitions for PCI Routing tables
*/
-
-#endif /* __ACTYPES_H__ */
+#endif /* __ACTYPES_H__ */
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 192d0bea3884..c1086452696e 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -44,20 +44,17 @@
#ifndef _ACUTILS_H
#define _ACUTILS_H
-
typedef
-acpi_status (*acpi_pkg_callback) (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
-
-struct acpi_pkg_info
-{
- u8 *free_space;
- acpi_size length;
- u32 object_space;
- u32 num_packages;
+acpi_status(*acpi_pkg_callback) (u8 object_type,
+ union acpi_operand_object * source_object,
+ union acpi_generic_state * state,
+ void *context);
+
+struct acpi_pkg_info {
+ u8 *free_space;
+ acpi_size length;
+ u32 object_space;
+ u32 num_packages;
};
#define REF_INCREMENT (u16) 0
@@ -71,167 +68,89 @@ struct acpi_pkg_info
#define DB_DWORD_DISPLAY 4
#define DB_QWORD_DISPLAY 8
-
/*
* utglobal - Global data structures and procedures
*/
-void
-acpi_ut_init_globals (
- void);
+void acpi_ut_init_globals(void);
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-char *
-acpi_ut_get_mutex_name (
- u32 mutex_id);
+char *acpi_ut_get_mutex_name(u32 mutex_id);
#endif
-char *
-acpi_ut_get_type_name (
- acpi_object_type type);
-
-char *
-acpi_ut_get_node_name (
- void *object);
-
-char *
-acpi_ut_get_descriptor_name (
- void *object);
+char *acpi_ut_get_type_name(acpi_object_type type);
-char *
-acpi_ut_get_object_type_name (
- union acpi_operand_object *obj_desc);
+char *acpi_ut_get_node_name(void *object);
-char *
-acpi_ut_get_region_name (
- u8 space_id);
+char *acpi_ut_get_descriptor_name(void *object);
-char *
-acpi_ut_get_event_name (
- u32 event_id);
+char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
-char
-acpi_ut_hex_to_ascii_char (
- acpi_integer integer,
- u32 position);
+char *acpi_ut_get_region_name(u8 space_id);
-u8
-acpi_ut_valid_object_type (
- acpi_object_type type);
+char *acpi_ut_get_event_name(u32 event_id);
-acpi_owner_id
-acpi_ut_allocate_owner_id (
- u32 id_type);
+char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position);
+u8 acpi_ut_valid_object_type(acpi_object_type type);
/*
* utinit - miscellaneous initialization and shutdown
*/
-acpi_status
-acpi_ut_hardware_initialize (
- void);
+acpi_status acpi_ut_hardware_initialize(void);
-void
-acpi_ut_subsystem_shutdown (
- void);
-
-acpi_status
-acpi_ut_validate_fadt (
- void);
+void acpi_ut_subsystem_shutdown(void);
+acpi_status acpi_ut_validate_fadt(void);
/*
* utclib - Local implementations of C library functions
*/
#ifndef ACPI_USE_SYSTEM_CLIBRARY
-acpi_size
-acpi_ut_strlen (
- const char *string);
-
-char *
-acpi_ut_strcpy (
- char *dst_string,
- const char *src_string);
-
-char *
-acpi_ut_strncpy (
- char *dst_string,
- const char *src_string,
- acpi_size count);
-
-int
-acpi_ut_memcmp (
- const char *buffer1,
- const char *buffer2,
- acpi_size count);
-
-int
-acpi_ut_strncmp (
- const char *string1,
- const char *string2,
- acpi_size count);
-
-int
-acpi_ut_strcmp (
- const char *string1,
- const char *string2);
-
-char *
-acpi_ut_strcat (
- char *dst_string,
- const char *src_string);
-
-char *
-acpi_ut_strncat (
- char *dst_string,
- const char *src_string,
- acpi_size count);
-
-u32
-acpi_ut_strtoul (
- const char *string,
- char **terminator,
- u32 base);
-
-char *
-acpi_ut_strstr (
- char *string1,
- char *string2);
-
-void *
-acpi_ut_memcpy (
- void *dest,
- const void *src,
- acpi_size count);
-
-void *
-acpi_ut_memset (
- void *dest,
- acpi_native_uint value,
- acpi_size count);
-
-int
-acpi_ut_to_upper (
- int c);
-
-int
-acpi_ut_to_lower (
- int c);
+acpi_size acpi_ut_strlen(const char *string);
+
+char *acpi_ut_strcpy(char *dst_string, const char *src_string);
+
+char *acpi_ut_strncpy(char *dst_string,
+ const char *src_string, acpi_size count);
+
+int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count);
+
+int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count);
+
+int acpi_ut_strcmp(const char *string1, const char *string2);
+
+char *acpi_ut_strcat(char *dst_string, const char *src_string);
+
+char *acpi_ut_strncat(char *dst_string,
+ const char *src_string, acpi_size count);
+
+u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base);
+
+char *acpi_ut_strstr(char *string1, char *string2);
+
+void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count);
+
+void *acpi_ut_memset(void *dest, acpi_native_uint value, acpi_size count);
+
+int acpi_ut_to_upper(int c);
+
+int acpi_ut_to_lower(int c);
extern const u8 _acpi_ctype[];
-#define _ACPI_XA 0x00 /* extra alphabetic - not supported */
-#define _ACPI_XS 0x40 /* extra space */
-#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */
-#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */
-#define _ACPI_DI 0x04 /* '0'-'9' */
-#define _ACPI_LO 0x02 /* 'a'-'z' */
-#define _ACPI_PU 0x10 /* punctuation */
-#define _ACPI_SP 0x08 /* space */
-#define _ACPI_UP 0x01 /* 'A'-'Z' */
-#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */
+#define _ACPI_XA 0x00 /* extra alphabetic - not supported */
+#define _ACPI_XS 0x40 /* extra space */
+#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */
+#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */
+#define _ACPI_DI 0x04 /* '0'-'9' */
+#define _ACPI_LO 0x02 /* 'a'-'z' */
+#define _ACPI_PU 0x10 /* punctuation */
+#define _ACPI_SP 0x08 /* space */
+#define _ACPI_UP 0x01 /* 'A'-'Z' */
+#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */
#define ACPI_IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI))
#define ACPI_IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP))
@@ -242,502 +161,323 @@ extern const u8 _acpi_ctype[];
#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
#define ACPI_IS_ASCII(c) ((c) < 0x80)
-#endif /* ACPI_USE_SYSTEM_CLIBRARY */
-
+#endif /* ACPI_USE_SYSTEM_CLIBRARY */
/*
* utcopy - Object construction and conversion interfaces
*/
acpi_status
-acpi_ut_build_simple_object(
- union acpi_operand_object *obj,
- union acpi_object *user_obj,
- u8 *data_space,
- u32 *buffer_space_used);
+acpi_ut_build_simple_object(union acpi_operand_object *obj,
+ union acpi_object *user_obj,
+ u8 * data_space, u32 * buffer_space_used);
acpi_status
-acpi_ut_build_package_object (
- union acpi_operand_object *obj,
- u8 *buffer,
- u32 *space_used);
+acpi_ut_build_package_object(union acpi_operand_object *obj,
+ u8 * buffer, u32 * space_used);
acpi_status
-acpi_ut_copy_iobject_to_eobject (
- union acpi_operand_object *obj,
- struct acpi_buffer *ret_buffer);
+acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj,
+ struct acpi_buffer *ret_buffer);
acpi_status
-acpi_ut_copy_eobject_to_iobject (
- union acpi_object *obj,
- union acpi_operand_object **internal_obj);
+acpi_ut_copy_eobject_to_iobject(union acpi_object *obj,
+ union acpi_operand_object **internal_obj);
acpi_status
-acpi_ut_copy_isimple_to_isimple (
- union acpi_operand_object *source_obj,
- union acpi_operand_object *dest_obj);
+acpi_ut_copy_isimple_to_isimple(union acpi_operand_object *source_obj,
+ union acpi_operand_object *dest_obj);
acpi_status
-acpi_ut_copy_iobject_to_iobject (
- union acpi_operand_object *source_desc,
- union acpi_operand_object **dest_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
+ union acpi_operand_object **dest_desc,
+ struct acpi_walk_state *walk_state);
/*
* utcreate - Object creation
*/
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);
/*
* utdebug - Debug interfaces
*/
-void
-acpi_ut_init_stack_ptr_trace (
- void);
+void acpi_ut_init_stack_ptr_trace(void);
-void
-acpi_ut_track_stack_ptr (
- void);
+void acpi_ut_track_stack_ptr(void);
void
-acpi_ut_trace (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info);
+acpi_ut_trace(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id);
void
-acpi_ut_trace_ptr (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- void *pointer);
+acpi_ut_trace_ptr(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, void *pointer);
void
-acpi_ut_trace_u32 (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u32 integer);
+acpi_ut_trace_u32(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u32 integer);
void
-acpi_ut_trace_str (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *string);
+acpi_ut_trace_str(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *string);
void
-acpi_ut_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info);
+acpi_ut_exit(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id);
void
-acpi_ut_status_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_status status);
+acpi_ut_status_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_status status);
void
-acpi_ut_value_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_integer value);
+acpi_ut_value_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_integer value);
void
-acpi_ut_ptr_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u8 *ptr);
+acpi_ut_ptr_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u8 * ptr);
-void
-acpi_ut_report_info (
- char *module_name,
- u32 line_number,
- u32 component_id);
+void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id);
-void
-acpi_ut_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id);
+void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id);
void
-acpi_ut_report_warning (
- char *module_name,
- u32 line_number,
- u32 component_id);
+acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id);
-void
-acpi_ut_dump_buffer (
- u8 *buffer,
- u32 count,
- u32 display,
- u32 component_id);
+void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...) ACPI_PRINTF_LIKE_FUNC;
+acpi_ut_debug_print(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name,
+ u32 component_id, char *format, ...) ACPI_PRINTF_LIKE_FUNC;
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print_raw (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...) ACPI_PRINTF_LIKE_FUNC;
-
+acpi_ut_debug_print_raw(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name,
+ u32 component_id,
+ char *format, ...) ACPI_PRINTF_LIKE_FUNC;
/*
* utdelete - Object deletion and reference counts
*/
-void
-acpi_ut_add_reference (
- union acpi_operand_object *object);
+void acpi_ut_add_reference(union acpi_operand_object *object);
-void
-acpi_ut_remove_reference (
- union acpi_operand_object *object);
+void acpi_ut_remove_reference(union acpi_operand_object *object);
-void
-acpi_ut_delete_internal_package_object (
- union acpi_operand_object *object);
+void acpi_ut_delete_internal_package_object(union acpi_operand_object *object);
-void
-acpi_ut_delete_internal_simple_object (
- union acpi_operand_object *object);
-
-void
-acpi_ut_delete_internal_object_list (
- union acpi_operand_object **obj_list);
+void acpi_ut_delete_internal_simple_object(union acpi_operand_object *object);
+void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
/*
* uteval - object evaluation
*/
-acpi_status
-acpi_ut_osi_implementation (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ut_evaluate_object (
- struct acpi_namespace_node *prefix_node,
- char *path,
- u32 expected_return_btypes,
- union acpi_operand_object **return_desc);
+acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
+ char *path,
+ u32 expected_return_btypes,
+ union acpi_operand_object **return_desc);
acpi_status
-acpi_ut_evaluate_numeric_object (
- char *object_name,
- struct acpi_namespace_node *device_node,
- acpi_integer *address);
+acpi_ut_evaluate_numeric_object(char *object_name,
+ struct acpi_namespace_node *device_node,
+ acpi_integer * address);
acpi_status
-acpi_ut_execute_HID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *hid);
+acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *hid);
acpi_status
-acpi_ut_execute_CID (
- struct acpi_namespace_node *device_node,
- struct acpi_compatible_id_list **return_cid_list);
+acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
+ struct acpi_compatible_id_list **return_cid_list);
acpi_status
-acpi_ut_execute_STA (
- struct acpi_namespace_node *device_node,
- u32 *status_flags);
+acpi_ut_execute_STA(struct acpi_namespace_node *device_node,
+ u32 * status_flags);
acpi_status
-acpi_ut_execute_UID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *uid);
+acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *uid);
acpi_status
-acpi_ut_execute_sxds (
- struct acpi_namespace_node *device_node,
- u8 *highest);
-
+acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
/*
* utobject - internal object create/delete/cache routines
*/
-union acpi_operand_object *
-acpi_ut_create_internal_object_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id,
- acpi_object_type type);
-
-void *
-acpi_ut_allocate_object_desc_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id);
-
-#define acpi_ut_create_internal_object(t) acpi_ut_create_internal_object_dbg (_THIS_MODULE,__LINE__,_COMPONENT,t)
-#define acpi_ut_allocate_object_desc() acpi_ut_allocate_object_desc_dbg (_THIS_MODULE,__LINE__,_COMPONENT)
+union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ acpi_object_type
+ type);
-void
-acpi_ut_delete_object_desc (
- union acpi_operand_object *object);
+void *acpi_ut_allocate_object_desc_dbg(char *module_name,
+ u32 line_number, u32 component_id);
-u8
-acpi_ut_valid_internal_object (
- void *object);
+#define acpi_ut_create_internal_object(t) acpi_ut_create_internal_object_dbg (_acpi_module_name,__LINE__,_COMPONENT,t)
+#define acpi_ut_allocate_object_desc() acpi_ut_allocate_object_desc_dbg (_acpi_module_name,__LINE__,_COMPONENT)
-union acpi_operand_object *
-acpi_ut_create_buffer_object (
- acpi_size buffer_size);
+void acpi_ut_delete_object_desc(union acpi_operand_object *object);
-union acpi_operand_object *
-acpi_ut_create_string_object (
- acpi_size string_size);
+u8 acpi_ut_valid_internal_object(void *object);
-acpi_status
-acpi_ut_get_object_size(
- union acpi_operand_object *obj,
- acpi_size *obj_length);
+union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
+union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
+
+acpi_status
+acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
/*
* utstate - Generic state creation/cache routines
*/
void
-acpi_ut_push_generic_state (
- union acpi_generic_state **list_head,
- union acpi_generic_state *state);
+acpi_ut_push_generic_state(union acpi_generic_state **list_head,
+ union acpi_generic_state *state);
-union acpi_generic_state *
-acpi_ut_pop_generic_state (
- union acpi_generic_state **list_head);
+union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
+ **list_head);
+union acpi_generic_state *acpi_ut_create_generic_state(void);
-union acpi_generic_state *
-acpi_ut_create_generic_state (
- void);
+struct acpi_thread_state *acpi_ut_create_thread_state(void);
-struct acpi_thread_state *
-acpi_ut_create_thread_state (
- void);
+union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
+ *object, u16 action);
-union acpi_generic_state *
-acpi_ut_create_update_state (
- union acpi_operand_object *object,
- u16 action);
-
-union acpi_generic_state *
-acpi_ut_create_pkg_state (
- void *internal_object,
- void *external_object,
- u16 index);
+union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
+ void *external_object,
+ u16 index);
acpi_status
-acpi_ut_create_update_state_and_push (
- union acpi_operand_object *object,
- u16 action,
- union acpi_generic_state **state_list);
+acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
+ u16 action,
+ union acpi_generic_state **state_list);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_ut_create_pkg_state_and_push (
- void *internal_object,
- void *external_object,
- u16 index,
- union acpi_generic_state **state_list);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_ut_create_pkg_state_and_push(void *internal_object,
+ void *external_object,
+ u16 index,
+ union acpi_generic_state **state_list);
+#endif /* ACPI_FUTURE_USAGE */
-union acpi_generic_state *
-acpi_ut_create_control_state (
- void);
-
-void
-acpi_ut_delete_generic_state (
- union acpi_generic_state *state);
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-void
-acpi_ut_delete_generic_state_cache (
- void);
-
-void
-acpi_ut_delete_object_cache (
- void);
-#endif
+union acpi_generic_state *acpi_ut_create_control_state(void);
+void acpi_ut_delete_generic_state(union acpi_generic_state *state);
/*
* utmath
*/
acpi_status
-acpi_ut_divide (
- acpi_integer in_dividend,
- acpi_integer in_divisor,
- acpi_integer *out_quotient,
- acpi_integer *out_remainder);
+acpi_ut_divide(acpi_integer in_dividend,
+ acpi_integer in_divisor,
+ acpi_integer * out_quotient, acpi_integer * out_remainder);
acpi_status
-acpi_ut_short_divide (
- acpi_integer in_dividend,
- u32 divisor,
- acpi_integer *out_quotient,
- u32 *out_remainder);
+acpi_ut_short_divide(acpi_integer in_dividend,
+ u32 divisor,
+ acpi_integer * out_quotient, u32 * out_remainder);
/*
* utmisc
*/
+acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
+
+void acpi_ut_release_owner_id(acpi_owner_id * owner_id);
+
acpi_status
-acpi_ut_walk_package_tree (
- union acpi_operand_object *source_object,
- void *target_object,
- acpi_pkg_callback walk_callback,
- void *context);
+acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
+ void *target_object,
+ acpi_pkg_callback walk_callback, void *context);
-char *
-acpi_ut_strupr (
- char *src_string);
+void acpi_ut_strupr(char *src_string);
-void
-acpi_ut_print_string (
- char *string,
- u8 max_length);
+void acpi_ut_print_string(char *string, u8 max_length);
-u8
-acpi_ut_valid_acpi_name (
- u32 name);
+u8 acpi_ut_valid_acpi_name(u32 name);
-u8
-acpi_ut_valid_acpi_character (
- char character);
+u8 acpi_ut_valid_acpi_character(char character);
acpi_status
-acpi_ut_strtoul64 (
- char *string,
- u32 base,
- acpi_integer *ret_integer);
+acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0
-acpi_status
-acpi_ut_mutex_initialize (
- void);
-
-void
-acpi_ut_mutex_terminate (
- void);
-
-acpi_status
-acpi_ut_acquire_mutex (
- acpi_mutex_handle mutex_id);
-
-acpi_status
-acpi_ut_release_mutex (
- acpi_mutex_handle mutex_id);
-
-u8 *
-acpi_ut_get_resource_end_tag (
- union acpi_operand_object *obj_desc);
+u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc);
-u8
-acpi_ut_generate_checksum (
- u8 *buffer,
- u32 length);
+u8 acpi_ut_generate_checksum(u8 * buffer, u32 length);
-u32
-acpi_ut_dword_byte_swap (
- u32 value);
+u32 acpi_ut_dword_byte_swap(u32 value);
-void
-acpi_ut_set_integer_width (
- u8 revision);
+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);
+acpi_ut_display_init_pathname(u8 type,
+ struct acpi_namespace_node *obj_handle,
+ char *path);
#endif
+/*
+ * utmutex - mutex support
+ */
+acpi_status acpi_ut_mutex_initialize(void);
+
+void acpi_ut_mutex_terminate(void);
+
+acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id);
+
+acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id);
/*
* utalloc - memory allocation and object caching
*/
-void *
-acpi_ut_acquire_from_cache (
- u32 list_id);
+acpi_status acpi_ut_create_caches(void);
-void
-acpi_ut_release_to_cache (
- u32 list_id,
- void *object);
+acpi_status acpi_ut_delete_caches(void);
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-void
-acpi_ut_delete_generic_cache (
- u32 list_id);
-#endif
+acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer);
acpi_status
-acpi_ut_validate_buffer (
- struct acpi_buffer *buffer);
+acpi_ut_initialize_buffer(struct acpi_buffer *buffer,
+ acpi_size required_length);
-acpi_status
-acpi_ut_initialize_buffer (
- struct acpi_buffer *buffer,
- acpi_size required_length);
-
-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(acpi_size size, u32 component, char *module, u32 line);
+
+void *acpi_ut_callocate(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_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_free_and_track (
- void *address,
- u32 component,
- char *module,
- u32 line);
+acpi_ut_free_and_track(void *address, u32 component, char *module, u32 line);
#ifdef ACPI_FUTURE_USAGE
-void
-acpi_ut_dump_allocation_info (
- void);
-#endif /* ACPI_FUTURE_USAGE */
+void acpi_ut_dump_allocation_info(void);
+#endif /* ACPI_FUTURE_USAGE */
-void
-acpi_ut_dump_allocations (
- u32 component,
- char *module);
+void acpi_ut_dump_allocations(u32 component, char *module);
#endif
-#endif /* _ACUTILS_H */
+#endif /* _ACUTILS_H */
diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
index 55e97ed29190..7fdf5299f501 100644
--- a/include/acpi/amlcode.h
+++ b/include/acpi/amlcode.h
@@ -59,17 +59,17 @@
#define AML_WORD_OP (u16) 0x0b
#define AML_DWORD_OP (u16) 0x0c
#define AML_STRING_OP (u16) 0x0d
-#define AML_QWORD_OP (u16) 0x0e /* ACPI 2.0 */
+#define AML_QWORD_OP (u16) 0x0e /* ACPI 2.0 */
#define AML_SCOPE_OP (u16) 0x10
#define AML_BUFFER_OP (u16) 0x11
#define AML_PACKAGE_OP (u16) 0x12
-#define AML_VAR_PACKAGE_OP (u16) 0x13 /* ACPI 2.0 */
+#define AML_VAR_PACKAGE_OP (u16) 0x13 /* ACPI 2.0 */
#define AML_METHOD_OP (u16) 0x14
#define AML_DUAL_NAME_PREFIX (u16) 0x2e
#define AML_MULTI_NAME_PREFIX_OP (u16) 0x2f
#define AML_NAME_CHAR_SUBSEQ (u16) 0x30
#define AML_NAME_CHAR_FIRST (u16) 0x41
-#define AML_OP_PREFIX (u16) 0x5b
+#define AML_EXTENDED_OP_PREFIX (u16) 0x5b
#define AML_ROOT_PREFIX (u16) 0x5c
#define AML_PARENT_PREFIX (u16) 0x5e
#define AML_LOCAL_OP (u16) 0x60
@@ -109,8 +109,8 @@
#define AML_FIND_SET_LEFT_BIT_OP (u16) 0x81
#define AML_FIND_SET_RIGHT_BIT_OP (u16) 0x82
#define AML_DEREF_OF_OP (u16) 0x83
-#define AML_CONCAT_RES_OP (u16) 0x84 /* ACPI 2.0 */
-#define AML_MOD_OP (u16) 0x85 /* ACPI 2.0 */
+#define AML_CONCAT_RES_OP (u16) 0x84 /* ACPI 2.0 */
+#define AML_MOD_OP (u16) 0x85 /* ACPI 2.0 */
#define AML_NOTIFY_OP (u16) 0x86
#define AML_SIZE_OF_OP (u16) 0x87
#define AML_INDEX_OP (u16) 0x88
@@ -120,21 +120,21 @@
#define AML_CREATE_BYTE_FIELD_OP (u16) 0x8c
#define AML_CREATE_BIT_FIELD_OP (u16) 0x8d
#define AML_TYPE_OP (u16) 0x8e
-#define AML_CREATE_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */
+#define AML_CREATE_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */
#define AML_LAND_OP (u16) 0x90
#define AML_LOR_OP (u16) 0x91
#define AML_LNOT_OP (u16) 0x92
#define AML_LEQUAL_OP (u16) 0x93
#define AML_LGREATER_OP (u16) 0x94
#define AML_LLESS_OP (u16) 0x95
-#define AML_TO_BUFFER_OP (u16) 0x96 /* ACPI 2.0 */
-#define AML_TO_DECSTRING_OP (u16) 0x97 /* ACPI 2.0 */
-#define AML_TO_HEXSTRING_OP (u16) 0x98 /* ACPI 2.0 */
-#define AML_TO_INTEGER_OP (u16) 0x99 /* ACPI 2.0 */
-#define AML_TO_STRING_OP (u16) 0x9c /* ACPI 2.0 */
-#define AML_COPY_OP (u16) 0x9d /* ACPI 2.0 */
-#define AML_MID_OP (u16) 0x9e /* ACPI 2.0 */
-#define AML_CONTINUE_OP (u16) 0x9f /* ACPI 2.0 */
+#define AML_TO_BUFFER_OP (u16) 0x96 /* ACPI 2.0 */
+#define AML_TO_DECSTRING_OP (u16) 0x97 /* ACPI 2.0 */
+#define AML_TO_HEXSTRING_OP (u16) 0x98 /* ACPI 2.0 */
+#define AML_TO_INTEGER_OP (u16) 0x99 /* ACPI 2.0 */
+#define AML_TO_STRING_OP (u16) 0x9c /* ACPI 2.0 */
+#define AML_COPY_OP (u16) 0x9d /* ACPI 2.0 */
+#define AML_MID_OP (u16) 0x9e /* ACPI 2.0 */
+#define AML_CONTINUE_OP (u16) 0x9f /* ACPI 2.0 */
#define AML_IF_OP (u16) 0xa0
#define AML_ELSE_OP (u16) 0xa1
#define AML_WHILE_OP (u16) 0xa2
@@ -146,7 +146,7 @@
/* prefixed opcodes */
-#define AML_EXTOP (u16) 0x005b /* prefix for 2-byte opcodes */
+#define AML_EXTENDED_OPCODE (u16) 0x5b00 /* prefix for 2-byte opcodes */
#define AML_MUTEX_OP (u16) 0x5b01
#define AML_EVENT_OP (u16) 0x5b02
@@ -154,7 +154,7 @@
#define AML_SHIFT_LEFT_BIT_OP (u16) 0x5b11
#define AML_COND_REF_OF_OP (u16) 0x5b12
#define AML_CREATE_FIELD_OP (u16) 0x5b13
-#define AML_LOAD_TABLE_OP (u16) 0x5b1f /* ACPI 2.0 */
+#define AML_LOAD_TABLE_OP (u16) 0x5b1f /* ACPI 2.0 */
#define AML_LOAD_OP (u16) 0x5b20
#define AML_STALL_OP (u16) 0x5b21
#define AML_SLEEP_OP (u16) 0x5b22
@@ -169,7 +169,7 @@
#define AML_REVISION_OP (u16) 0x5b30
#define AML_DEBUG_OP (u16) 0x5b31
#define AML_FATAL_OP (u16) 0x5b32
-#define AML_TIMER_OP (u16) 0x5b33 /* ACPI 3.0 */
+#define AML_TIMER_OP (u16) 0x5b33 /* ACPI 3.0 */
#define AML_REGION_OP (u16) 0x5b80
#define AML_FIELD_OP (u16) 0x5b81
#define AML_DEVICE_OP (u16) 0x5b82
@@ -178,8 +178,7 @@
#define AML_THERMAL_ZONE_OP (u16) 0x5b85
#define AML_INDEX_FIELD_OP (u16) 0x5b86
#define AML_BANK_FIELD_OP (u16) 0x5b87
-#define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */
-
+#define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */
/* Bogus opcodes (they are actually two separate opcodes) */
@@ -187,7 +186,6 @@
#define AML_LLESSEQUAL_OP (u16) 0x9294
#define AML_LNOTEQUAL_OP (u16) 0x9293
-
/*
* Internal opcodes
* Use only "Unknown" AML opcodes, don't attempt to use
@@ -203,7 +201,6 @@
#define AML_INT_RETURN_VALUE_OP (u16) 0x0036
#define AML_INT_EVAL_SUBTREE_OP (u16) 0x0037
-
#define ARG_NONE 0x0
/*
@@ -245,7 +242,7 @@
/* Single, simple types */
-#define ARGI_ANYTYPE 0x01 /* Don't care */
+#define ARGI_ANYTYPE 0x01 /* Don't care */
#define ARGI_PACKAGE 0x02
#define ARGI_EVENT 0x03
#define ARGI_MUTEX 0x04
@@ -256,8 +253,8 @@
#define ARGI_INTEGER 0x06
#define ARGI_STRING 0x07
#define ARGI_BUFFER 0x08
-#define ARGI_BUFFER_OR_STRING 0x09 /* Used by MID op only */
-#define ARGI_COMPUTEDATA 0x0A /* Buffer, String, or Integer */
+#define ARGI_BUFFER_OR_STRING 0x09 /* Used by MID op only */
+#define ARGI_COMPUTEDATA 0x0A /* Buffer, String, or Integer */
/* Reference objects */
@@ -265,30 +262,28 @@
#define ARGI_OBJECT_REF 0x0C
#define ARGI_DEVICE_REF 0x0D
#define ARGI_REFERENCE 0x0E
-#define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */
-#define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */
-#define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */
+#define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */
+#define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */
+#define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */
/* Multiple/complex types */
-#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a Node - Used only by size_of operator*/
-#define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */
-#define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */
-#define ARGI_REGION_OR_FIELD 0x15 /* Used by LOAD op only */
+#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a Node - Used only by size_of operator */
+#define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */
+#define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */
+#define ARGI_REGION_OR_FIELD 0x15 /* Used by LOAD op only */
#define ARGI_DATAREFOBJ 0x16
/* Note: types above can expand to 0x1F maximum */
#define ARGI_INVALID_OPCODE 0xFFFFFFFF
-
/*
* hash offsets
*/
#define AML_EXTOP_HASH_OFFSET 22
#define AML_LNOT_HASH_OFFSET 19
-
/*
* opcode groups and types
*/
@@ -296,7 +291,6 @@
#define OPGRP_FIELD 0x02
#define OPGRP_BYTELIST 0x04
-
/*
* Opcode information
*/
@@ -322,31 +316,30 @@
/* Convenient flag groupings */
#define AML_FLAGS_EXEC_0A_0T_1R AML_HAS_RETVAL
-#define AML_FLAGS_EXEC_1A_0T_0R AML_HAS_ARGS /* Monadic1 */
-#define AML_FLAGS_EXEC_1A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Monadic2 */
+#define AML_FLAGS_EXEC_1A_0T_0R AML_HAS_ARGS /* Monadic1 */
+#define AML_FLAGS_EXEC_1A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Monadic2 */
#define AML_FLAGS_EXEC_1A_1T_0R AML_HAS_ARGS | AML_HAS_TARGET
-#define AML_FLAGS_EXEC_1A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* monadic2_r */
-#define AML_FLAGS_EXEC_2A_0T_0R AML_HAS_ARGS /* Dyadic1 */
-#define AML_FLAGS_EXEC_2A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Dyadic2 */
-#define AML_FLAGS_EXEC_2A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* dyadic2_r */
+#define AML_FLAGS_EXEC_1A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* monadic2_r */
+#define AML_FLAGS_EXEC_2A_0T_0R AML_HAS_ARGS /* Dyadic1 */
+#define AML_FLAGS_EXEC_2A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Dyadic2 */
+#define AML_FLAGS_EXEC_2A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* dyadic2_r */
#define AML_FLAGS_EXEC_2A_2T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL
#define AML_FLAGS_EXEC_3A_0T_0R AML_HAS_ARGS
#define AML_FLAGS_EXEC_3A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL
#define AML_FLAGS_EXEC_6A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL
-
/*
* The opcode Type is used in a dispatch table, do not change
* without updating the table.
*/
#define AML_TYPE_EXEC_0A_0T_1R 0x00
-#define AML_TYPE_EXEC_1A_0T_0R 0x01 /* Monadic1 */
-#define AML_TYPE_EXEC_1A_0T_1R 0x02 /* Monadic2 */
+#define AML_TYPE_EXEC_1A_0T_0R 0x01 /* Monadic1 */
+#define AML_TYPE_EXEC_1A_0T_1R 0x02 /* Monadic2 */
#define AML_TYPE_EXEC_1A_1T_0R 0x03
-#define AML_TYPE_EXEC_1A_1T_1R 0x04 /* monadic2_r */
-#define AML_TYPE_EXEC_2A_0T_0R 0x05 /* Dyadic1 */
-#define AML_TYPE_EXEC_2A_0T_1R 0x06 /* Dyadic2 */
-#define AML_TYPE_EXEC_2A_1T_1R 0x07 /* dyadic2_r */
+#define AML_TYPE_EXEC_1A_1T_1R 0x04 /* monadic2_r */
+#define AML_TYPE_EXEC_2A_0T_0R 0x05 /* Dyadic1 */
+#define AML_TYPE_EXEC_2A_0T_1R 0x06 /* Dyadic2 */
+#define AML_TYPE_EXEC_2A_1T_1R 0x07 /* dyadic2_r */
#define AML_TYPE_EXEC_2A_2T_1R 0x08
#define AML_TYPE_EXEC_3A_0T_0R 0x09
#define AML_TYPE_EXEC_3A_1T_1R 0x0A
@@ -399,40 +392,33 @@
#define AML_CLASS_METHOD_CALL 0x09
#define AML_CLASS_UNKNOWN 0x0A
-
/* Predefined Operation Region space_iDs */
-typedef enum
-{
- REGION_MEMORY = 0,
+typedef enum {
+ REGION_MEMORY = 0,
REGION_IO,
REGION_PCI_CONFIG,
REGION_EC,
REGION_SMBUS,
REGION_CMOS,
REGION_PCI_BAR,
- REGION_DATA_TABLE, /* Internal use only */
- REGION_FIXED_HW = 0x7F
-
+ REGION_DATA_TABLE, /* Internal use only */
+ REGION_FIXED_HW = 0x7F
} AML_REGION_TYPES;
-
/* Comparison operation codes for match_op operator */
-typedef enum
-{
- MATCH_MTR = 0,
- MATCH_MEQ = 1,
- MATCH_MLE = 2,
- MATCH_MLT = 3,
- MATCH_MGE = 4,
- MATCH_MGT = 5
-
+typedef enum {
+ MATCH_MTR = 0,
+ MATCH_MEQ = 1,
+ MATCH_MLE = 2,
+ MATCH_MLT = 3,
+ MATCH_MGE = 4,
+ MATCH_MGT = 5
} AML_MATCH_OPERATOR;
#define MAX_MATCH_OPERATOR 5
-
/*
* field_flags
*
@@ -450,60 +436,47 @@ typedef enum
#define AML_FIELD_LOCK_RULE_MASK 0x10
#define AML_FIELD_UPDATE_RULE_MASK 0x60
-
/* 1) Field Access Types */
-typedef enum
-{
- AML_FIELD_ACCESS_ANY = 0x00,
- AML_FIELD_ACCESS_BYTE = 0x01,
- AML_FIELD_ACCESS_WORD = 0x02,
- AML_FIELD_ACCESS_DWORD = 0x03,
- AML_FIELD_ACCESS_QWORD = 0x04, /* ACPI 2.0 */
- AML_FIELD_ACCESS_BUFFER = 0x05 /* ACPI 2.0 */
-
+typedef enum {
+ AML_FIELD_ACCESS_ANY = 0x00,
+ AML_FIELD_ACCESS_BYTE = 0x01,
+ AML_FIELD_ACCESS_WORD = 0x02,
+ AML_FIELD_ACCESS_DWORD = 0x03,
+ AML_FIELD_ACCESS_QWORD = 0x04, /* ACPI 2.0 */
+ AML_FIELD_ACCESS_BUFFER = 0x05 /* ACPI 2.0 */
} AML_ACCESS_TYPE;
-
/* 2) Field Lock Rules */
-typedef enum
-{
- AML_FIELD_LOCK_NEVER = 0x00,
- AML_FIELD_LOCK_ALWAYS = 0x10
-
+typedef enum {
+ AML_FIELD_LOCK_NEVER = 0x00,
+ AML_FIELD_LOCK_ALWAYS = 0x10
} AML_LOCK_RULE;
-
/* 3) Field Update Rules */
-typedef enum
-{
- AML_FIELD_UPDATE_PRESERVE = 0x00,
- AML_FIELD_UPDATE_WRITE_AS_ONES = 0x20,
+typedef enum {
+ AML_FIELD_UPDATE_PRESERVE = 0x00,
+ AML_FIELD_UPDATE_WRITE_AS_ONES = 0x20,
AML_FIELD_UPDATE_WRITE_AS_ZEROS = 0x40
-
} AML_UPDATE_RULE;
-
/*
* Field Access Attributes.
* This byte is extracted from the AML via the
* access_as keyword
*/
-typedef enum
-{
- AML_FIELD_ATTRIB_SMB_QUICK = 0x02,
- AML_FIELD_ATTRIB_SMB_SEND_RCV = 0x04,
- AML_FIELD_ATTRIB_SMB_BYTE = 0x06,
- AML_FIELD_ATTRIB_SMB_WORD = 0x08,
- AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A,
- AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C,
+typedef enum {
+ AML_FIELD_ATTRIB_SMB_QUICK = 0x02,
+ AML_FIELD_ATTRIB_SMB_SEND_RCV = 0x04,
+ AML_FIELD_ATTRIB_SMB_BYTE = 0x06,
+ AML_FIELD_ATTRIB_SMB_WORD = 0x08,
+ AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A,
+ AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C,
AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D
-
} AML_ACCESS_ATTRIBUTE;
-
/* Bit fields in method_flags byte */
#define AML_METHOD_ARG_COUNT 0x07
@@ -516,5 +489,4 @@ typedef enum
#define AML_METHOD_RESERVED1 0x02
#define AML_METHOD_RESERVED2 0x04
-
-#endif /* __AMLCODE_H__ */
+#endif /* __AMLCODE_H__ */
diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h
index b20ec303df07..051786e4b210 100644
--- a/include/acpi/amlresrc.h
+++ b/include/acpi/amlresrc.h
@@ -42,29 +42,27 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#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_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_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_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_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"
@@ -72,12 +70,11 @@
#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_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) */
-
+#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) */
/* Default sizes for "small" resource descriptors */
@@ -89,15 +86,12 @@
#define ASL_RDESC_FIXED_IO_SIZE 0x03
#define ASL_RDESC_END_TAG_SIZE 0x01
-
-struct asl_resource_node
-{
- u32 buffer_length;
- void *buffer;
- struct asl_resource_node *next;
+struct asl_resource_node {
+ u32 buffer_length;
+ void *buffer;
+ struct asl_resource_node *next;
};
-
/*
* Resource descriptors defined in the ACPI specification.
*
@@ -106,214 +100,175 @@ struct asl_resource_node
*/
#pragma pack(1)
-struct asl_irq_format_desc
-{
- u8 descriptor_type;
- u16 irq_mask;
- u8 flags;
+struct asl_irq_format_desc {
+ u8 descriptor_type;
+ u16 irq_mask;
+ u8 flags;
};
-
-struct asl_irq_noflags_desc
-{
- u8 descriptor_type;
- u16 irq_mask;
+struct asl_irq_noflags_desc {
+ u8 descriptor_type;
+ u16 irq_mask;
};
-
-struct asl_dma_format_desc
-{
- u8 descriptor_type;
- u8 dma_channel_mask;
- u8 flags;
+struct asl_dma_format_desc {
+ u8 descriptor_type;
+ u8 dma_channel_mask;
+ u8 flags;
};
-
-struct asl_start_dependent_desc
-{
- u8 descriptor_type;
- u8 flags;
+struct asl_start_dependent_desc {
+ u8 descriptor_type;
+ u8 flags;
};
-
-struct asl_start_dependent_noprio_desc
-{
- u8 descriptor_type;
+struct asl_start_dependent_noprio_desc {
+ u8 descriptor_type;
};
-
-struct asl_end_dependent_desc
-{
- u8 descriptor_type;
+struct asl_end_dependent_desc {
+ u8 descriptor_type;
};
-
-struct asl_io_port_desc
-{
- u8 descriptor_type;
- u8 information;
- u16 address_min;
- u16 address_max;
- u8 alignment;
- u8 length;
+struct asl_io_port_desc {
+ u8 descriptor_type;
+ u8 information;
+ u16 address_min;
+ u16 address_max;
+ u8 alignment;
+ u8 length;
};
-
-struct asl_fixed_io_port_desc
-{
- u8 descriptor_type;
- u16 base_address;
- u8 length;
+struct asl_fixed_io_port_desc {
+ u8 descriptor_type;
+ u16 base_address;
+ u8 length;
};
-
-struct asl_small_vendor_desc
-{
- u8 descriptor_type;
- u8 vendor_defined[7];
+struct asl_small_vendor_desc {
+ u8 descriptor_type;
+ u8 vendor_defined[7];
};
-
-struct asl_end_tag_desc
-{
- u8 descriptor_type;
- u8 checksum;
+struct asl_end_tag_desc {
+ u8 descriptor_type;
+ u8 checksum;
};
-
/* LARGE descriptors */
-struct asl_memory_24_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 information;
- u16 address_min;
- u16 address_max;
- u16 alignment;
- u16 range_length;
+struct asl_memory_24_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 information;
+ u16 address_min;
+ u16 address_max;
+ u16 alignment;
+ u16 range_length;
};
-
-struct asl_large_vendor_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 vendor_defined[1];
+struct asl_large_vendor_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 vendor_defined[1];
};
-
-struct asl_memory_32_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 information;
- u32 address_min;
- u32 address_max;
- u32 alignment;
- u32 range_length;
+struct asl_memory_32_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 information;
+ u32 address_min;
+ u32 address_max;
+ u32 alignment;
+ u32 range_length;
};
-
-struct asl_fixed_memory_32_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 information;
- u32 base_address;
- u32 range_length;
+struct asl_fixed_memory_32_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 information;
+ u32 base_address;
+ u32 range_length;
};
-
-struct asl_extended_address_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 resource_type;
- u8 flags;
- u8 specific_flags;
- u8 revision_iD;
- u8 reserved;
- u64 granularity;
- u64 address_min;
- u64 address_max;
- u64 translation_offset;
- u64 address_length;
- u64 type_specific_attributes;
- u8 optional_fields[2]; /* Used for length calculation only */
+struct asl_extended_address_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 resource_type;
+ u8 flags;
+ u8 specific_flags;
+ u8 revision_iD;
+ u8 reserved;
+ u64 granularity;
+ u64 address_min;
+ u64 address_max;
+ u64 translation_offset;
+ u64 address_length;
+ u64 type_specific_attributes;
+ u8 optional_fields[2]; /* Used for length calculation only */
};
-#define ASL_EXTENDED_ADDRESS_DESC_REVISION 1 /* ACPI 3.0 */
-
-
-struct asl_qword_address_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 resource_type;
- u8 flags;
- u8 specific_flags;
- u64 granularity;
- u64 address_min;
- u64 address_max;
- u64 translation_offset;
- u64 address_length;
- u8 optional_fields[2];
+#define ASL_EXTENDED_ADDRESS_DESC_REVISION 1 /* ACPI 3.0 */
+
+struct asl_qword_address_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 resource_type;
+ u8 flags;
+ u8 specific_flags;
+ u64 granularity;
+ u64 address_min;
+ u64 address_max;
+ u64 translation_offset;
+ u64 address_length;
+ u8 optional_fields[2];
};
-
-struct asl_dword_address_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 resource_type;
- u8 flags;
- u8 specific_flags;
- u32 granularity;
- u32 address_min;
- u32 address_max;
- u32 translation_offset;
- u32 address_length;
- u8 optional_fields[2];
+struct asl_dword_address_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 resource_type;
+ u8 flags;
+ u8 specific_flags;
+ u32 granularity;
+ u32 address_min;
+ u32 address_max;
+ u32 translation_offset;
+ u32 address_length;
+ u8 optional_fields[2];
};
-
-struct asl_word_address_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 resource_type;
- u8 flags;
- u8 specific_flags;
- u16 granularity;
- u16 address_min;
- u16 address_max;
- u16 translation_offset;
- u16 address_length;
- u8 optional_fields[2];
+struct asl_word_address_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 resource_type;
+ u8 flags;
+ u8 specific_flags;
+ u16 granularity;
+ u16 address_min;
+ u16 address_max;
+ u16 translation_offset;
+ u16 address_length;
+ u8 optional_fields[2];
};
-
-struct asl_extended_xrupt_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 flags;
- u8 table_length;
- u32 interrupt_number[1];
+struct asl_extended_xrupt_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 flags;
+ u8 table_length;
+ u32 interrupt_number[1];
/* res_source_index, res_source optional fields follow */
};
-
-struct asl_general_register_desc
-{
- u8 descriptor_type;
- u16 length;
- u8 address_space_id;
- u8 bit_width;
- u8 bit_offset;
- u8 access_size; /* ACPI 3.0, was Reserved */
- u64 address;
+struct asl_general_register_desc {
+ u8 descriptor_type;
+ u16 length;
+ u8 address_space_id;
+ u8 bit_width;
+ u8 bit_offset;
+ u8 access_size; /* ACPI 3.0, was Reserved */
+ u64 address;
};
/* restore default alignment */
@@ -322,32 +277,29 @@ struct asl_general_register_desc
/* Union of all resource descriptors, so we can allocate the worst case */
-union asl_resource_desc
-{
- struct asl_irq_format_desc irq;
- struct asl_dma_format_desc dma;
- struct asl_start_dependent_desc std;
- struct asl_end_dependent_desc end;
- struct asl_io_port_desc iop;
- struct asl_fixed_io_port_desc fio;
- struct asl_small_vendor_desc smv;
- struct asl_end_tag_desc et;
-
- struct asl_memory_24_desc M24;
- struct asl_large_vendor_desc lgv;
- struct asl_memory_32_desc M32;
- struct asl_fixed_memory_32_desc F32;
- struct asl_qword_address_desc qas;
- struct asl_dword_address_desc das;
- struct asl_word_address_desc was;
- struct asl_extended_address_desc eas;
- struct asl_extended_xrupt_desc exx;
- struct asl_general_register_desc grg;
- u32 u32_item;
- u16 u16_item;
- u8 U8item;
+union asl_resource_desc {
+ struct asl_irq_format_desc irq;
+ struct asl_dma_format_desc dma;
+ struct asl_start_dependent_desc std;
+ struct asl_end_dependent_desc end;
+ struct asl_io_port_desc iop;
+ struct asl_fixed_io_port_desc fio;
+ struct asl_small_vendor_desc smv;
+ struct asl_end_tag_desc et;
+
+ struct asl_memory_24_desc M24;
+ struct asl_large_vendor_desc lgv;
+ struct asl_memory_32_desc M32;
+ struct asl_fixed_memory_32_desc F32;
+ struct asl_qword_address_desc qas;
+ struct asl_dword_address_desc das;
+ struct asl_word_address_desc was;
+ struct asl_extended_address_desc eas;
+ struct asl_extended_xrupt_desc exx;
+ struct asl_general_register_desc grg;
+ u32 u32_item;
+ u16 u16_item;
+ u8 U8item;
};
-
#endif
-
diff --git a/include/acpi/container.h b/include/acpi/container.h
index d716df04d9dc..a703f14e049e 100644
--- a/include/acpi/container.h
+++ b/include/acpi/container.h
@@ -9,5 +9,4 @@ struct acpi_container {
int state;
};
-#endif /* __ACPI_CONTAINER_H */
-
+#endif /* __ACPI_CONTAINER_H */
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index fd6730e4e567..91f4a12a99a1 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -14,7 +14,6 @@
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
#define ACPI_PDC_C_C1_FFH (0x0100)
-
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT)
@@ -25,5 +24,4 @@
ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT)
-#endif /* __PDC_INTEL_H__ */
-
+#endif /* __PDC_INTEL_H__ */
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index adf969efa510..16609c1ab2eb 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -44,40 +44,42 @@
#ifndef __ACENV_H__
#define __ACENV_H__
-
/*
* Configuration for ACPI tools and utilities
*/
-#ifdef _ACPI_DUMP_APP
+#ifdef ACPI_LIBRARY
+#define ACPI_USE_LOCAL_CACHE
+#endif
+
+#ifdef ACPI_DUMP_APP
#ifndef MSDOS
#define ACPI_DEBUG_OUTPUT
#endif
#define ACPI_APPLICATION
#define ACPI_DISASSEMBLER
#define ACPI_NO_METHOD_EXECUTION
-#define ACPI_USE_SYSTEM_CLIBRARY
-#define ACPI_ENABLE_OBJECT_CACHE
#endif
-#ifdef _ACPI_EXEC_APP
+#ifdef ACPI_EXEC_APP
#undef DEBUGGER_THREADING
#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED
#define ACPI_DEBUG_OUTPUT
#define ACPI_APPLICATION
#define ACPI_DEBUGGER
#define ACPI_DISASSEMBLER
-#define ACPI_USE_SYSTEM_CLIBRARY
-#define ACPI_ENABLE_OBJECT_CACHE
#endif
-#ifdef _ACPI_ASL_COMPILER
+#ifdef ACPI_ASL_COMPILER
#define ACPI_DEBUG_OUTPUT
#define ACPI_APPLICATION
#define ACPI_DISASSEMBLER
#define ACPI_CONSTANT_EVAL_ONLY
+#endif
+
+#ifdef ACPI_APPLICATION
#define ACPI_USE_SYSTEM_CLIBRARY
-#define ACPI_ENABLE_OBJECT_CACHE
+#define ACPI_USE_LOCAL_CACHE
#endif
/*
@@ -131,7 +133,7 @@
#elif defined(WIN64)
#include "acwin64.h"
-#elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */
+#elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */
#include "acdos16.h"
#elif defined(__FreeBSD__)
@@ -177,7 +179,6 @@
/*! [End] no source code translation !*/
-
/*
* Debugger threading model
* Use single threaded if the entire subsystem is contained in an application
@@ -196,8 +197,7 @@
#else
#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED
#endif
-#endif /* !DEBUGGER_THREADING */
-
+#endif /* !DEBUGGER_THREADING */
/******************************************************************************
*
@@ -219,7 +219,7 @@
#include <string.h>
#include <ctype.h>
-#endif /* ACPI_USE_STANDARD_HEADERS */
+#endif /* ACPI_USE_STANDARD_HEADERS */
/*
* We will be linking to the standard Clib functions
@@ -238,15 +238,15 @@
#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (acpi_size)(n))
#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (acpi_size)(n))
-#define ACPI_TOUPPER toupper
-#define ACPI_TOLOWER tolower
-#define ACPI_IS_XDIGIT isxdigit
-#define ACPI_IS_DIGIT isdigit
-#define ACPI_IS_SPACE isspace
-#define ACPI_IS_UPPER isupper
-#define ACPI_IS_PRINT isprint
-#define ACPI_IS_ALPHA isalpha
-#define ACPI_IS_ASCII isascii
+#define ACPI_TOUPPER(i) toupper((int) (i))
+#define ACPI_TOLOWER(i) tolower((int) (i))
+#define ACPI_IS_XDIGIT(i) isxdigit((int) (i))
+#define ACPI_IS_DIGIT(i) isdigit((int) (i))
+#define ACPI_IS_SPACE(i) isspace((int) (i))
+#define ACPI_IS_UPPER(i) isupper((int) (i))
+#define ACPI_IS_PRINT(i) isprint((int) (i))
+#define ACPI_IS_ALPHA(i) isalpha((int) (i))
+#define ACPI_IS_ASCII(i) isascii((int) (i))
#else
@@ -257,18 +257,18 @@
*****************************************************************************/
/*
- * Use local definitions of C library macros and functions
- * NOTE: The function implementations may not be as efficient
- * as an inline or assembly code implementation provided by a
- * native C library.
- */
+ * Use local definitions of C library macros and functions
+ * NOTE: The function implementations may not be as efficient
+ * as an inline or assembly code implementation provided by a
+ * native C library.
+ */
#ifndef va_arg
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
-#endif /* _VALIST */
+#endif /* _VALIST */
/*
* Storage alignment properties
@@ -284,8 +284,7 @@ typedef char *va_list;
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
-#endif /* va_arg */
-
+#endif /* va_arg */
#define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2))
#define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c))
@@ -303,8 +302,7 @@ typedef char *va_list;
#define ACPI_TOUPPER acpi_ut_to_upper
#define ACPI_TOLOWER acpi_ut_to_lower
-#endif /* ACPI_USE_SYSTEM_CLIBRARY */
-
+#endif /* ACPI_USE_SYSTEM_CLIBRARY */
/******************************************************************************
*
@@ -345,8 +343,7 @@ typedef char *va_list;
#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq)
#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq)
-#endif /* ACPI_ASM_MACROS */
-
+#endif /* ACPI_ASM_MACROS */
#ifdef ACPI_APPLICATION
@@ -356,11 +353,10 @@ typedef char *va_list;
#define BREAKPOINT3
#endif
-
/******************************************************************************
*
* Compiler-specific information is contained in the compiler-specific
* headers.
*
*****************************************************************************/
-#endif /* __ACENV_H__ */
+#endif /* __ACENV_H__ */
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index 91fda36b042b..4c0e0ba09ba0 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -44,16 +44,20 @@
#ifndef __ACGCC_H__
#define __ACGCC_H__
+/* Function name is used for debug output. Non-ANSI, compiler-dependent */
+
+#define ACPI_GET_FUNCTION_NAME __FUNCTION__
+
/* This macro is used to tag functions as "printf-like" because
* some compilers (like GCC) can catch printf format string problems.
*/
-#define ACPI_PRINTF_LIKE_FUNC __attribute__ ((__format__ (__printf__, 4, 5)))
+#define ACPI_PRINTF_LIKE_FUNC __attribute__ ((__format__ (__printf__, 6, 7)))
/* Some compilers complain about unused variables. Sometimes we don't want to
- * use all the variables (most specifically for _THIS_MODULE). This allow us
+ * use all the variables (for example, _acpi_module_name). This allows us
* to to tell the compiler warning in a per-variable manner that a variable
* is unused.
*/
#define ACPI_UNUSED_VAR __attribute__ ((unused))
-#endif /* __ACGCC_H__ */
+#endif /* __ACGCC_H__ */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index a3de0db85694..c93e6562f0e1 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -62,7 +62,16 @@
#define ACPI_MACHINE_WIDTH BITS_PER_LONG
-#else /* !__KERNEL__ */
+/* 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
+
+#else /* !__KERNEL__ */
#include <stdarg.h>
#include <string.h>
@@ -83,10 +92,10 @@
#define __cdecl
#define ACPI_FLUSH_CPU_CACHE()
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
/* Linux uses GCC */
#include "acgcc.h"
-#endif /* __ACLINUX_H__ */
+#endif /* __ACLINUX_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 50cfea4ff6ca..7a00d5089de9 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -23,45 +23,44 @@
struct acpi_processor_cx;
struct acpi_power_register {
- u8 descriptor;
- u16 length;
- u8 space_id;
- u8 bit_width;
- u8 bit_offset;
- u8 reserved;
- u64 address;
+ u8 descriptor;
+ u16 length;
+ u8 space_id;
+ u8 bit_width;
+ u8 bit_offset;
+ u8 reserved;
+ u64 address;
} __attribute__ ((packed));
-
struct acpi_processor_cx_policy {
- u32 count;
+ u32 count;
struct acpi_processor_cx *state;
struct {
- u32 time;
- u32 ticks;
- u32 count;
- u32 bm;
- } threshold;
+ u32 time;
+ u32 ticks;
+ u32 count;
+ u32 bm;
+ } threshold;
};
struct acpi_processor_cx {
- u8 valid;
- u8 type;
- u32 address;
- u32 latency;
- u32 latency_ticks;
- u32 power;
- u32 usage;
+ u8 valid;
+ u8 type;
+ u32 address;
+ u32 latency;
+ u32 latency_ticks;
+ u32 power;
+ u32 usage;
struct acpi_processor_cx_policy promotion;
struct acpi_processor_cx_policy demotion;
};
struct acpi_processor_power {
struct acpi_processor_cx *state;
- unsigned long bm_check_timestamp;
- u32 default_state;
- u32 bm_activity;
- int count;
+ unsigned long bm_check_timestamp;
+ u32 default_state;
+ u32 bm_activity;
+ int count;
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
/* the _PDC objects passed by the driver, if any */
@@ -71,85 +70,82 @@ struct acpi_processor_power {
/* Performance Management */
struct acpi_pct_register {
- u8 descriptor;
- u16 length;
- u8 space_id;
- u8 bit_width;
- u8 bit_offset;
- u8 reserved;
- u64 address;
+ u8 descriptor;
+ u16 length;
+ u8 space_id;
+ u8 bit_width;
+ u8 bit_offset;
+ u8 reserved;
+ u64 address;
} __attribute__ ((packed));
struct acpi_processor_px {
- acpi_integer core_frequency; /* megahertz */
- acpi_integer power; /* milliWatts */
- acpi_integer transition_latency; /* microseconds */
- acpi_integer bus_master_latency; /* microseconds */
- acpi_integer control; /* control value */
- acpi_integer status; /* success indicator */
+ acpi_integer core_frequency; /* megahertz */
+ acpi_integer power; /* milliWatts */
+ acpi_integer transition_latency; /* microseconds */
+ acpi_integer bus_master_latency; /* microseconds */
+ acpi_integer control; /* control value */
+ acpi_integer status; /* success indicator */
};
struct acpi_processor_performance {
- unsigned int state;
- unsigned int platform_limit;
+ unsigned int state;
+ unsigned int platform_limit;
struct acpi_pct_register control_register;
struct acpi_pct_register status_register;
- unsigned int state_count;
+ unsigned int state_count;
struct acpi_processor_px *states;
/* the _PDC objects passed by the driver, if any */
struct acpi_object_list *pdc;
};
-
-
/* Throttling Control */
struct acpi_processor_tx {
- u16 power;
- u16 performance;
+ u16 power;
+ u16 performance;
};
struct acpi_processor_throttling {
- int state;
- u32 address;
- u8 duty_offset;
- u8 duty_width;
- int state_count;
+ int state;
+ u32 address;
+ u8 duty_offset;
+ u8 duty_width;
+ int state_count;
struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING];
};
/* Limit Interface */
struct acpi_processor_lx {
- int px; /* performace state */
- int tx; /* throttle level */
+ int px; /* performace state */
+ int tx; /* throttle level */
};
struct acpi_processor_limit {
- struct acpi_processor_lx state; /* current limit */
+ struct acpi_processor_lx state; /* current limit */
struct acpi_processor_lx thermal; /* thermal limit */
- struct acpi_processor_lx user; /* user limit */
+ struct acpi_processor_lx user; /* user limit */
};
-
struct acpi_processor_flags {
- u8 power:1;
- u8 performance:1;
- u8 throttling:1;
- u8 limit:1;
- u8 bm_control:1;
- u8 bm_check:1;
- u8 has_cst:1;
- u8 power_setup_done:1;
+ u8 power:1;
+ u8 performance:1;
+ u8 throttling:1;
+ u8 limit:1;
+ u8 bm_control:1;
+ u8 bm_check:1;
+ u8 has_cst:1;
+ u8 power_setup_done:1;
};
struct acpi_processor {
- acpi_handle handle;
- u32 acpi_id;
- u32 id;
- u32 pblk;
- int performance_platform_limit;
+ acpi_handle handle;
+ u32 acpi_id;
+ u32 id;
+ u32 pblk;
+ int performance_platform_limit;
struct acpi_processor_flags flags;
struct acpi_processor_power power;
struct acpi_processor_performance *performance;
@@ -158,50 +154,49 @@ struct acpi_processor {
};
struct acpi_processor_errata {
- u8 smp;
+ u8 smp;
struct {
- u8 throttle:1;
- u8 fdma:1;
- u8 reserved:6;
- u32 bmisx;
- } piix4;
+ u8 throttle:1;
+ u8 fdma:1;
+ u8 reserved:6;
+ u32 bmisx;
+ } piix4;
};
-extern int acpi_processor_register_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu);
-extern void acpi_processor_unregister_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu);
+extern int acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu);
+extern void acpi_processor_unregister_performance(struct
+ acpi_processor_performance
+ *performance,
+ unsigned int cpu);
/* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */
int acpi_processor_notify_smm(struct module *calling_module);
-
-
/* for communication between multiple parts of the processor kernel module */
-extern struct acpi_processor *processors[NR_CPUS];
+extern struct acpi_processor *processors[NR_CPUS];
extern struct acpi_processor_errata errata;
int acpi_processor_set_pdc(struct acpi_processor *pr,
- struct acpi_object_list *pdc_in);
+ struct acpi_object_list *pdc_in);
#ifdef ARCH_HAS_POWER_PDC_INIT
void acpi_processor_power_init_pdc(struct acpi_processor_power *pow,
- unsigned int cpu);
+ unsigned int cpu);
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
- unsigned int cpu);
+ unsigned int cpu);
#else
-static inline void acpi_processor_power_init_pdc(
- struct acpi_processor_power *pow, unsigned int cpu)
+static inline void acpi_processor_power_init_pdc(struct acpi_processor_power
+ *pow, unsigned int cpu)
{
pow->pdc = NULL;
return;
}
-static inline void acpi_processor_power_init_bm_check(
- struct acpi_processor_flags *flags, unsigned int cpu)
+static inline void acpi_processor_power_init_bm_check(struct
+ acpi_processor_flags
+ *flags, unsigned int cpu)
{
flags->bm_check = 1;
return;
@@ -215,51 +210,62 @@ void acpi_processor_ppc_init(void);
void acpi_processor_ppc_exit(void);
int acpi_processor_ppc_has_changed(struct acpi_processor *pr);
#else
-static inline void acpi_processor_ppc_init(void) { return; }
-static inline void acpi_processor_ppc_exit(void) { return; }
-static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) {
+static inline void acpi_processor_ppc_init(void)
+{
+ return;
+}
+static inline void acpi_processor_ppc_exit(void)
+{
+ return;
+}
+static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+{
static unsigned int printout = 1;
if (printout) {
- printk(KERN_WARNING "Warning: Processor Platform Limit event detected, but not handled.\n");
- printk(KERN_WARNING "Consider compiling CPUfreq support into your kernel.\n");
+ printk(KERN_WARNING
+ "Warning: Processor Platform Limit event detected, but not handled.\n");
+ printk(KERN_WARNING
+ "Consider compiling CPUfreq support into your kernel.\n");
printout = 0;
}
return 0;
}
-#endif /* CONFIG_CPU_FREQ */
+#endif /* CONFIG_CPU_FREQ */
/* in processor_throttling.c */
-int acpi_processor_get_throttling_info (struct acpi_processor *pr);
-int acpi_processor_set_throttling (struct acpi_processor *pr, int state);
-ssize_t acpi_processor_write_throttling (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data);
+int acpi_processor_get_throttling_info(struct acpi_processor *pr);
+int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+ssize_t acpi_processor_write_throttling(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data);
extern struct file_operations acpi_processor_throttling_fops;
/* in processor_idle.c */
-int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device);
-int acpi_processor_cst_has_changed (struct acpi_processor *pr);
-int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device);
-
+int acpi_processor_power_init(struct acpi_processor *pr,
+ struct acpi_device *device);
+int acpi_processor_cst_has_changed(struct acpi_processor *pr);
+int acpi_processor_power_exit(struct acpi_processor *pr,
+ struct acpi_device *device);
/* in processor_thermal.c */
-int acpi_processor_get_limit_info (struct acpi_processor *pr);
-ssize_t acpi_processor_write_limit (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data);
+int acpi_processor_get_limit_info(struct acpi_processor *pr);
+ssize_t acpi_processor_write_limit(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data);
extern struct file_operations acpi_processor_limit_fops;
#ifdef CONFIG_CPU_FREQ
void acpi_thermal_cpufreq_init(void);
void acpi_thermal_cpufreq_exit(void);
#else
-static inline void acpi_thermal_cpufreq_init(void) { return; }
-static inline void acpi_thermal_cpufreq_exit(void) { return; }
+static inline void acpi_thermal_cpufreq_init(void)
+{
+ return;
+}
+static inline void acpi_thermal_cpufreq_exit(void)
+{
+ return;
+}
#endif
-
#endif
diff --git a/include/asm-alpha/auxvec.h b/include/asm-alpha/auxvec.h
new file mode 100644
index 000000000000..e96fe880e310
--- /dev/null
+++ b/include/asm-alpha/auxvec.h
@@ -0,0 +1,24 @@
+#ifndef __ASM_ALPHA_AUXVEC_H
+#define __ASM_ALPHA_AUXVEC_H
+
+/* Reserve these numbers for any future use of a VDSO. */
+#if 0
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+#endif
+
+/* More complete cache descriptions than AT_[DIU]CACHEBSIZE. If the
+ value is -1, then the cache doesn't exist. Otherwise:
+
+ bit 0-3: Cache set-associativity; 0 means fully associative.
+ bit 4-7: Log2 of cacheline size.
+ bit 8-31: Size of the entire cache >> 8.
+ bit 32-63: Reserved.
+*/
+
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+#endif /* __ASM_ALPHA_AUXVEC_H */
diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h
index e94a945a2314..6c2d78fba264 100644
--- a/include/asm-alpha/elf.h
+++ b/include/asm-alpha/elf.h
@@ -1,6 +1,8 @@
#ifndef __ASM_ALPHA_ELF_H
#define __ASM_ALPHA_ELF_H
+#include <asm/auxvec.h>
+
/* Special values for the st_other field in the symbol table. */
#define STO_ALPHA_NOPV 0x80
@@ -142,26 +144,6 @@ extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task);
: amask (AMASK_CIX) ? "ev6" : "ev67"); \
})
-/* Reserve these numbers for any future use of a VDSO. */
-#if 0
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-#endif
-
-/* More complete cache descriptions than AT_[DIU]CACHEBSIZE. If the
- value is -1, then the cache doesn't exist. Otherwise:
-
- bit 0-3: Cache set-associativity; 0 means fully associative.
- bit 4-7: Log2 of cacheline size.
- bit 8-31: Size of the entire cache >> 8.
- bit 32-63: Reserved.
-*/
-
-#define AT_L1I_CACHESHAPE 34
-#define AT_L1D_CACHESHAPE 35
-#define AT_L2_CACHESHAPE 36
-#define AT_L3_CACHESHAPE 37
-
#ifdef __KERNEL__
#define SET_PERSONALITY(EX, IBCS2) \
diff --git a/include/asm-alpha/fcntl.h b/include/asm-alpha/fcntl.h
index 6b7d6c1649ce..87f2cf459e26 100644
--- a/include/asm-alpha/fcntl.h
+++ b/include/asm-alpha/fcntl.h
@@ -3,10 +3,6 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
#define O_CREAT 01000 /* not fcntl */
#define O_TRUNC 02000 /* not fcntl */
#define O_EXCL 04000 /* not fcntl */
@@ -14,20 +10,13 @@
#define O_NONBLOCK 00004
#define O_APPEND 00010
-#define O_NDELAY O_NONBLOCK
#define O_SYNC 040000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 0100000 /* must be a directory */
#define O_NOFOLLOW 0200000 /* don't follow links */
#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */
#define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */
#define O_NOATIME 04000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
#define F_GETLK 7
#define F_SETLK 8
#define F_SETLKW 9
@@ -37,9 +26,6 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
/* for posix fcntl() and lockf() */
#define F_RDLCK 1
#define F_WRLCK 2
@@ -51,25 +37,6 @@
#define F_INPROGRESS 64
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- __kernel_off_t l_start;
- __kernel_off_t l_len;
- __kernel_pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
+#include <asm-generic/fcntl.h>
#endif
diff --git a/include/asm-alpha/futex.h b/include/asm-alpha/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-alpha/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-alpha/hdreg.h b/include/asm-alpha/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-alpha/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index 0577daffc720..fa0b41b164a7 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -63,20 +63,6 @@ typedef unsigned long pgprot_t;
#endif /* STRICT_MM_TYPECHECKS */
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#ifdef USE_48_BIT_KSEG
#define PAGE_OFFSET 0xffff800000000000UL
#else
@@ -112,4 +98,6 @@ extern __inline__ int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _ALPHA_PAGE_H */
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
index f681e675b823..4e115f368d5f 100644
--- a/include/asm-alpha/pci.h
+++ b/include/asm-alpha/pci.h
@@ -254,6 +254,19 @@ extern void pcibios_resource_to_bus(struct pci_dev *, struct pci_bus_region *,
extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
static inline int pci_proc_domain(struct pci_bus *bus)
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 22b53e369f59..8393bf374b2b 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -339,13 +339,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define kern_addr_valid(addr) (1)
#endif
-#define io_remap_page_range(vma, start, busaddr, size, prot) \
-({ \
- void *va = (void __force *)ioremap(busaddr, size); \
- unsigned long pfn = virt_to_phys(va) >> PAGE_SHIFT; \
- remap_pfn_range(vma, start, pfn, size, prot); \
-})
-
#define io_remap_pfn_range(vma, start, pfn, size, prot) \
remap_pfn_range(vma, start, pfn, size, prot)
diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
index d00259d3dc78..b5193229132a 100644
--- a/include/asm-alpha/socket.h
+++ b/include/asm-alpha/socket.h
@@ -25,6 +25,8 @@
#define SO_ERROR 0x1007
#define SO_SNDBUF 0x1001
#define SO_RCVBUF 0x1002
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
#define SO_RCVLOWAT 0x1010
#define SO_SNDLOWAT 0x1011
#define SO_RCVTIMEO 0x1012
diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
index 80780dba9986..8197c69eff44 100644
--- a/include/asm-alpha/spinlock.h
+++ b/include/asm-alpha/spinlock.h
@@ -6,7 +6,6 @@
#include <linux/kernel.h>
#include <asm/current.h>
-
/*
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
@@ -14,43 +13,18 @@
* We make no fairness assumptions. They have a cost.
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- int on_cpu;
- int line_no;
- void *previous;
- struct task_struct * task;
- const char *base_file;
-#endif
-} spinlock_t;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPIN_LOCK_UNLOCKED (spinlock_t){ 0, -1, 0, NULL, NULL, NULL }
-#else
-#define SPIN_LOCK_UNLOCKED (spinlock_t){ 0 }
-#endif
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) do { barrier(); } while ((x)->lock)
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-extern void _raw_spin_unlock(spinlock_t * lock);
-extern void debug_spin_lock(spinlock_t * lock, const char *, int);
-extern int debug_spin_trylock(spinlock_t * lock, const char *, int);
-#define _raw_spin_lock(LOCK) \
- debug_spin_lock(LOCK, __BASE_FILE__, __LINE__)
-#define _raw_spin_trylock(LOCK) \
- debug_spin_trylock(LOCK, __BASE_FILE__, __LINE__)
-#else
-static inline void _raw_spin_unlock(spinlock_t * lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_unlock_wait(x) \
+ do { cpu_relax(); } while ((x)->lock)
+
+static inline void __raw_spin_unlock(raw_spinlock_t * lock)
{
mb();
lock->lock = 0;
}
-static inline void _raw_spin_lock(spinlock_t * lock)
+static inline void __raw_spin_lock(raw_spinlock_t * lock)
{
long tmp;
@@ -70,80 +44,64 @@ static inline void _raw_spin_lock(spinlock_t * lock)
: "m"(lock->lock) : "memory");
}
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
return !test_and_set_bit(0, &lock->lock);
}
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
/***********************************************************/
-typedef struct {
- volatile unsigned int lock;
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t){ 0 }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-static inline int read_can_lock(rwlock_t *lock)
+static inline int __raw_read_can_lock(raw_rwlock_t *lock)
{
return (lock->lock & 1) == 0;
}
-static inline int write_can_lock(rwlock_t *lock)
+static inline int __raw_write_can_lock(raw_rwlock_t *lock)
{
return lock->lock == 0;
}
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _raw_write_lock(rwlock_t * lock);
-extern void _raw_read_lock(rwlock_t * lock);
-#else
-static inline void _raw_write_lock(rwlock_t * lock)
+static inline void __raw_read_lock(raw_rwlock_t *lock)
{
long regx;
__asm__ __volatile__(
"1: ldl_l %1,%0\n"
- " bne %1,6f\n"
- " lda %1,1\n"
+ " blbs %1,6f\n"
+ " subl %1,2,%1\n"
" stl_c %1,%0\n"
" beq %1,6f\n"
" mb\n"
".subsection 2\n"
"6: ldl %1,%0\n"
- " bne %1,6b\n"
+ " blbs %1,6b\n"
" br 1b\n"
".previous"
: "=m" (*lock), "=&r" (regx)
: "m" (*lock) : "memory");
}
-static inline void _raw_read_lock(rwlock_t * lock)
+static inline void __raw_write_lock(raw_rwlock_t *lock)
{
long regx;
__asm__ __volatile__(
"1: ldl_l %1,%0\n"
- " blbs %1,6f\n"
- " subl %1,2,%1\n"
+ " bne %1,6f\n"
+ " lda %1,1\n"
" stl_c %1,%0\n"
" beq %1,6f\n"
" mb\n"
".subsection 2\n"
"6: ldl %1,%0\n"
- " blbs %1,6b\n"
+ " bne %1,6b\n"
" br 1b\n"
".previous"
: "=m" (*lock), "=&r" (regx)
: "m" (*lock) : "memory");
}
-#endif /* CONFIG_DEBUG_RWLOCK */
-static inline int _raw_read_trylock(rwlock_t * lock)
+static inline int __raw_read_trylock(raw_rwlock_t * lock)
{
long regx;
int success;
@@ -165,7 +123,7 @@ static inline int _raw_read_trylock(rwlock_t * lock)
return success;
}
-static inline int _raw_write_trylock(rwlock_t * lock)
+static inline int __raw_write_trylock(raw_rwlock_t * lock)
{
long regx;
int success;
@@ -187,13 +145,7 @@ static inline int _raw_write_trylock(rwlock_t * lock)
return success;
}
-static inline void _raw_write_unlock(rwlock_t * lock)
-{
- mb();
- lock->lock = 0;
-}
-
-static inline void _raw_read_unlock(rwlock_t * lock)
+static inline void __raw_read_unlock(raw_rwlock_t * lock)
{
long regx;
__asm__ __volatile__(
@@ -209,4 +161,10 @@ static inline void _raw_read_unlock(rwlock_t * lock)
: "m" (*lock) : "memory");
}
+static inline void __raw_write_unlock(raw_rwlock_t * lock)
+{
+ mb();
+ lock->lock = 0;
+}
+
#endif /* _ALPHA_SPINLOCK_H */
diff --git a/include/asm-alpha/spinlock_types.h b/include/asm-alpha/spinlock_types.h
new file mode 100644
index 000000000000..8141eb5ebf0d
--- /dev/null
+++ b/include/asm-alpha/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef _ALPHA_SPINLOCK_TYPES_H
+#define _ALPHA_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-alpha/types.h b/include/asm-alpha/types.h
index 43264d219246..f5716139ec89 100644
--- a/include/asm-alpha/types.h
+++ b/include/asm-alpha/types.h
@@ -56,8 +56,6 @@ typedef unsigned long u64;
typedef u64 dma_addr_t;
typedef u64 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ALPHA_TYPES_H */
diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
index 4c39ee750f38..22de3b434a22 100644
--- a/include/asm-alpha/uaccess.h
+++ b/include/asm-alpha/uaccess.h
@@ -48,12 +48,6 @@
__access_ok(((unsigned long)(addr)),(size),get_fs()); \
})
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 7495026e2c18..e350dcb544e8 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -383,39 +383,45 @@ __ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count)
*vaddr++ = inl(io_addr);
}
-#define __is_io_address(p) (((unsigned long)p >= 0x0) && \
- ((unsigned long)p <= 0x0000ffff))
+#define PIO_OFFSET 0x10000UL
+#define PIO_MASK 0x0ffffUL
+
+#define __is_io_address(p) (((unsigned long)p >= PIO_OFFSET) && \
+ ((unsigned long)p <= (PIO_MASK + PIO_OFFSET)))
static inline unsigned int
-__ixp4xx_ioread8(void __iomem *port)
+__ixp4xx_ioread8(void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- return (unsigned int)__ixp4xx_inb((unsigned int)port);
+ return (unsigned int)__ixp4xx_inb(port & PIO_MASK);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- return (unsigned int)__raw_readb((u32)port);
+ return (unsigned int)__raw_readb(port);
#else
- return (unsigned int)__ixp4xx_readb((u32)port);
+ return (unsigned int)__ixp4xx_readb(port);
#endif
}
static inline void
-__ixp4xx_ioread8_rep(u32 port, u8 *vaddr, u32 count)
+__ixp4xx_ioread8_rep(void __iomem *addr, void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_insb(port, vaddr, count);
+ __ixp4xx_insb(port & PIO_MASK, vaddr, count);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_readsb((void __iomem *)port, vaddr, count);
+ __raw_readsb(addr, vaddr, count);
#else
__ixp4xx_readsb(port, vaddr, count);
#endif
}
static inline unsigned int
-__ixp4xx_ioread16(void __iomem *port)
+__ixp4xx_ioread16(void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- return (unsigned int)__ixp4xx_inw((unsigned int)port);
+ return (unsigned int)__ixp4xx_inw(port & PIO_MASK);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
return le16_to_cpu(__raw_readw((u32)port));
@@ -425,23 +431,25 @@ __ixp4xx_ioread16(void __iomem *port)
}
static inline void
-__ixp4xx_ioread16_rep(u32 port, u16 *vaddr, u32 count)
+__ixp4xx_ioread16_rep(void __iomem *addr, void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_insw(port, vaddr, count);
+ __ixp4xx_insw(port & PIO_MASK, vaddr, count);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_readsw((void __iomem *)port, vaddr, count);
+ __raw_readsw(addr, vaddr, count);
#else
__ixp4xx_readsw(port, vaddr, count);
#endif
}
static inline unsigned int
-__ixp4xx_ioread32(void __iomem *port)
+__ixp4xx_ioread32(void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- return (unsigned int)__ixp4xx_inl((unsigned int)port);
+ return (unsigned int)__ixp4xx_inl(port & PIO_MASK);
else {
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
return le32_to_cpu(__raw_readl((u32)port));
@@ -452,90 +460,100 @@ __ixp4xx_ioread32(void __iomem *port)
}
static inline void
-__ixp4xx_ioread32_rep(u32 port, u32 *vaddr, u32 count)
+__ixp4xx_ioread32_rep(void __iomem *addr, void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_insl(port, vaddr, count);
+ __ixp4xx_insl(port & PIO_MASK, vaddr, count);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_readsl((void __iomem *)port, vaddr, count);
+ __raw_readsl(addr, vaddr, count);
#else
__ixp4xx_readsl(port, vaddr, count);
#endif
}
static inline void
-__ixp4xx_iowrite8(u8 value, void __iomem *port)
+__ixp4xx_iowrite8(u8 value, void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outb(value, (unsigned int)port);
+ __ixp4xx_outb(value, port & PIO_MASK);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_writeb(value, (u32)port);
+ __raw_writeb(value, port);
#else
- __ixp4xx_writeb(value, (u32)port);
+ __ixp4xx_writeb(value, port);
#endif
}
static inline void
-__ixp4xx_iowrite8_rep(u32 port, u8 *vaddr, u32 count)
+__ixp4xx_iowrite8_rep(void __iomem *addr, const void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outsb(port, vaddr, count);
+ __ixp4xx_outsb(port & PIO_MASK, vaddr, count);
+ else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_writesb((void __iomem *)port, vaddr, count);
+ __raw_writesb(addr, vaddr, count);
#else
__ixp4xx_writesb(port, vaddr, count);
#endif
}
static inline void
-__ixp4xx_iowrite16(u16 value, void __iomem *port)
+__ixp4xx_iowrite16(u16 value, void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outw(value, (unsigned int)port);
+ __ixp4xx_outw(value, port & PIO_MASK);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_writew(cpu_to_le16(value), (u32)port);
+ __raw_writew(cpu_to_le16(value), addr);
#else
- __ixp4xx_writew(value, (u32)port);
+ __ixp4xx_writew(value, port);
#endif
}
static inline void
-__ixp4xx_iowrite16_rep(u32 port, u16 *vaddr, u32 count)
+__ixp4xx_iowrite16_rep(void __iomem *addr, const void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outsw(port, vaddr, count);
+ __ixp4xx_outsw(port & PIO_MASK, vaddr, count);
+ else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_readsw((void __iomem *)port, vaddr, count);
+ __raw_writesw(addr, vaddr, count);
#else
__ixp4xx_writesw(port, vaddr, count);
#endif
}
static inline void
-__ixp4xx_iowrite32(u32 value, void __iomem *port)
+__ixp4xx_iowrite32(u32 value, void __iomem *addr)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outl(value, (unsigned int)port);
+ __ixp4xx_outl(value, port & PIO_MASK);
else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_writel(cpu_to_le32(value), (u32)port);
+ __raw_writel(cpu_to_le32(value), port);
#else
- __ixp4xx_writel(value, (u32)port);
+ __ixp4xx_writel(value, port);
#endif
}
static inline void
-__ixp4xx_iowrite32_rep(u32 port, u32 *vaddr, u32 count)
+__ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count)
{
+ unsigned long port = (unsigned long __force)addr;
if (__is_io_address(port))
- __ixp4xx_outsl(port, vaddr, count);
+ __ixp4xx_outsl(port & PIO_MASK, vaddr, count);
+ else
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- __raw_readsl((void __iomem *)port, vaddr, count);
+ __raw_writesl(addr, vaddr, count);
#else
- __ixp4xx_outsl(port, vaddr, count);
+ __ixp4xx_writesl(port, vaddr, count);
#endif
}
@@ -555,7 +573,7 @@ __ixp4xx_iowrite32_rep(u32 port, u32 *vaddr, u32 count)
#define iowrite16_rep(p, v, c) __ixp4xx_iowrite16_rep(p, v, c)
#define iowrite32_rep(p, v, c) __ixp4xx_iowrite32_rep(p, v, c)
-#define ioport_map(port, nr) ((void __iomem*)port)
+#define ioport_map(port, nr) ((void __iomem*)(port + PIO_OFFSET))
#define ioport_unmap(addr)
#endif // __ASM_ARM_ARCH_IO_H
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index 3a626c03ea26..d13ee7f78c70 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -83,17 +83,6 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
#define IXP4XX_GPIO_OUT 0x1
#define IXP4XX_GPIO_IN 0x2
-#define IXP4XX_GPIO_INTSTYLE_MASK 0x7C /* Bits [6:2] define interrupt style */
-
-/*
- * GPIO interrupt types.
- */
-#define IXP4XX_GPIO_ACTIVE_HIGH 0x4 /* Default */
-#define IXP4XX_GPIO_ACTIVE_LOW 0x8
-#define IXP4XX_GPIO_RISING_EDGE 0x10
-#define IXP4XX_GPIO_FALLING_EDGE 0x20
-#define IXP4XX_GPIO_TRANSITIONAL 0x40
-
/* GPIO signal types */
#define IXP4XX_GPIO_LOW 0
#define IXP4XX_GPIO_HIGH 1
@@ -102,7 +91,13 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
#define IXP4XX_GPIO_CLK_0 14
#define IXP4XX_GPIO_CLK_1 15
-extern void gpio_line_config(u8 line, u32 style);
+static inline void gpio_line_config(u8 line, u32 direction)
+{
+ if (direction == IXP4XX_GPIO_OUT)
+ *IXP4XX_GPIO_GPOER |= (1 << line);
+ else
+ *IXP4XX_GPIO_GPOER &= ~(1 << line);
+}
static inline void gpio_line_get(u8 line, int *value)
{
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index 79138dcfb4ac..d64ee9211eed 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -30,6 +30,9 @@
#define __ASM_ARCH_OMAP_H4_H
/* Placeholder for H4 specific defines */
+/* GPMC CS1 */
+#define OMAP24XX_ETHR_START 0x08000300
+#define OMAP24XX_ETHR_GPIO_IRQ 92
#endif /* __ASM_ARCH_OMAP_H4_H */
diff --git a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h
index 0f1abaefe4de..79574e0ed13d 100644
--- a/include/asm-arm/arch-omap/board-innovator.h
+++ b/include/asm-arm/arch-omap/board-innovator.h
@@ -36,31 +36,6 @@
#define OMAP1510P1_EMIFS_PRI_VALUE 0x00
#define OMAP1510P1_EMIFF_PRI_VALUE 0x00
-/*
- * These definitions define an area of FLASH set aside
- * for the use of MTD/JFFS2. This is the area of flash
- * that a JFFS2 filesystem will reside which is mounted
- * at boot with the "root=/dev/mtdblock/0 rw"
- * command line option. The flash address used here must
- * fall within the legal range defined by rrload for storing
- * the filesystem component. This address will be sufficiently
- * deep into the overall flash range to avoid the other
- * components also stored in flash such as the bootloader,
- * the bootloader params, and the kernel.
- * The SW2 settings for the map below are:
- * 1 off, 2 off, 3 on, 4 off.
- */
-
-/* Intel flash_0, partitioned as expected by rrload */
-#define OMAP_FLASH_0_BASE 0xD8000000
-#define OMAP_FLASH_0_START 0x00000000
-#define OMAP_FLASH_0_SIZE SZ_16M
-
-/* Intel flash_1, used for cramfs or other flash file systems */
-#define OMAP_FLASH_1_BASE 0xD9000000
-#define OMAP_FLASH_1_START 0x01000000
-#define OMAP_FLASH_1_SIZE SZ_16M
-
#define NR_FPGA_IRQS 24
#define NR_IRQS IH_BOARD_BASE + NR_FPGA_IRQS
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 0c224cc74fe4..691e52a52b43 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -36,23 +36,14 @@
#define OMAP_SDRAM_DEVICE D256M_1X16_4B
#endif
-/*
- * These definitions define an area of FLASH set aside
- * for the use of MTD/JFFS2. This is the area of flash
- * that a JFFS2 filesystem will reside which is mounted
- * at boot with the "root=/dev/mtdblock/0 rw"
- * command line option.
- */
-
-/* Intel flash_0, partitioned as expected by rrload */
-#define OMAP_FLASH_0_BASE 0xD8000000 /* VA */
-#define OMAP_FLASH_0_START 0x00000000 /* PA */
-#define OMAP_FLASH_0_SIZE SZ_32M
-
#define MAXIRQNUM IH_BOARD_BASE
#define MAXFIQNUM MAXIRQNUM
#define MAXSWINUM MAXIRQNUM
#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-voiceblue.h b/include/asm-arm/arch-omap/board-voiceblue.h
index 33977b8956fb..ed6d346ee123 100644
--- a/include/asm-arm/arch-omap/board-voiceblue.h
+++ b/include/asm-arm/arch-omap/board-voiceblue.h
@@ -11,11 +11,6 @@
#ifndef __ASM_ARCH_VOICEBLUE_H
#define __ASM_ARCH_VOICEBLUE_H
-#if (EXTERNAL_MAX_NR_PORTS < 4)
-#undef EXTERNAL_MAX_NR_PORTS
-#define EXTERNAL_MAX_NR_PORTS 4
-#endif
-
extern void voiceblue_wdt_enable(void);
extern void voiceblue_wdt_disable(void);
extern void voiceblue_wdt_ping(void);
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index 95bd625480c1..a0040cd86639 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -30,10 +30,23 @@ struct omap_clock_config {
u8 system_clock_type;
};
+struct omap_mmc_conf {
+ unsigned enabled:1;
+ /* nomux means "standard" muxing is wrong on this board, and that
+ * board-specific code handled it before common init logic.
+ */
+ unsigned nomux:1;
+ /* switch pin can be for card detect (default) or card cover */
+ unsigned cover:1;
+ /* 4 wire signaling is optional, and is only used for SD/SDIO */
+ unsigned wire4:1;
+ s16 power_pin;
+ s16 switch_pin;
+ s16 wp_pin;
+};
+
struct omap_mmc_config {
- u8 mmc_blocks;
- s16 mmc1_power_pin, mmc2_power_pin;
- s16 mmc1_switch_pin, mmc2_switch_pin;
+ struct omap_mmc_conf mmc[2];
};
struct omap_serial_console_config {
diff --git a/include/asm-arm/arch-omap/cpu.h b/include/asm-arm/arch-omap/cpu.h
index e8786713ee5c..1119e2b53e72 100644
--- a/include/asm-arm/arch-omap/cpu.h
+++ b/include/asm-arm/arch-omap/cpu.h
@@ -38,146 +38,179 @@ extern unsigned int system_rev;
/*
* Test if multicore OMAP support is needed
*/
-#undef MULTI_OMAP
+#undef MULTI_OMAP1
+#undef MULTI_OMAP2
#undef OMAP_NAME
#ifdef CONFIG_ARCH_OMAP730
# ifdef OMAP_NAME
-# undef MULTI_OMAP
-# define MULTI_OMAP
+# undef MULTI_OMAP1
+# define MULTI_OMAP1
# else
# define OMAP_NAME omap730
# endif
#endif
#ifdef CONFIG_ARCH_OMAP1510
# ifdef OMAP_NAME
-# undef MULTI_OMAP
-# define MULTI_OMAP
+# undef MULTI_OMAP1
+# define MULTI_OMAP1
# else
# define OMAP_NAME omap1510
# endif
#endif
#ifdef CONFIG_ARCH_OMAP16XX
# ifdef OMAP_NAME
-# undef MULTI_OMAP
-# define MULTI_OMAP
+# undef MULTI_OMAP1
+# define MULTI_OMAP1
# else
-# define OMAP_NAME omap1610
+# define OMAP_NAME omap16xx
# endif
#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-# ifdef OMAP_NAME
-# undef MULTI_OMAP
-# define MULTI_OMAP
+#ifdef CONFIG_ARCH_OMAP24XX
+# if (defined(OMAP_NAME) || defined(MULTI_OMAP1))
+# error "OMAP1 and OMAP2 can't be selected at the same time"
# else
-# define OMAP_NAME omap1710
+# undef MULTI_OMAP2
+# define OMAP_NAME omap24xx
# endif
#endif
/*
- * Generate various OMAP cpu specific macros, and cpu class
- * specific macros
+ * Macros to group OMAP into cpu classes.
+ * These can be used in most places.
+ * cpu_is_omap7xx(): True for OMAP730
+ * cpu_is_omap15xx(): True for OMAP1510 and OMAP5910
+ * cpu_is_omap16xx(): True for OMAP1610, OMAP5912 and OMAP1710
+ * cpu_is_omap24xx(): True for OMAP2420
*/
-#define GET_OMAP_TYPE ((system_rev >> 24) & 0xff)
#define GET_OMAP_CLASS (system_rev & 0xff)
-#define IS_OMAP_TYPE(type, id) \
-static inline int is_omap ##type (void) \
-{ \
- return (GET_OMAP_TYPE == (id)) ? 1 : 0; \
-}
-
#define IS_OMAP_CLASS(class, id) \
static inline int is_omap ##class (void) \
{ \
return (GET_OMAP_CLASS == (id)) ? 1 : 0; \
}
-IS_OMAP_TYPE(730, 0x07)
-IS_OMAP_TYPE(1510, 0x15)
-IS_OMAP_TYPE(1610, 0x16)
-IS_OMAP_TYPE(5912, 0x16)
-IS_OMAP_TYPE(1710, 0x17)
-IS_OMAP_TYPE(2420, 0x24)
-
IS_OMAP_CLASS(7xx, 0x07)
IS_OMAP_CLASS(15xx, 0x15)
IS_OMAP_CLASS(16xx, 0x16)
IS_OMAP_CLASS(24xx, 0x24)
-/*
- * Macros to group OMAP types into cpu classes.
- * These can be used in most places.
- * cpu_is_omap15xx(): True for 1510 and 5910
- * cpu_is_omap16xx(): True for 1610, 5912 and 1710
- */
-#if defined(MULTI_OMAP)
-# define cpu_is_omap7xx() is_omap7xx()
-# define cpu_is_omap15xx() is_omap15xx()
-# if !(defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP730))
-# define cpu_is_omap16xx() 1
-# else
+#define cpu_is_omap7xx() 0
+#define cpu_is_omap15xx() 0
+#define cpu_is_omap16xx() 0
+#define cpu_is_omap24xx() 0
+
+#if defined(MULTI_OMAP1)
+# if defined(CONFIG_ARCH_OMAP730)
+# undef cpu_is_omap7xx
+# define cpu_is_omap7xx() is_omap7xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+# undef cpu_is_omap15xx
+# define cpu_is_omap15xx() is_omap15xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+# undef cpu_is_omap16xx
# define cpu_is_omap16xx() is_omap16xx()
# endif
#else
# if defined(CONFIG_ARCH_OMAP730)
+# undef cpu_is_omap7xx
# define cpu_is_omap7xx() 1
-# else
-# define cpu_is_omap7xx() 0
# endif
# if defined(CONFIG_ARCH_OMAP1510)
+# undef cpu_is_omap15xx
# define cpu_is_omap15xx() 1
-# else
-# define cpu_is_omap15xx() 0
# endif
# if defined(CONFIG_ARCH_OMAP16XX)
+# undef cpu_is_omap16xx
# define cpu_is_omap16xx() 1
-# else
-# define cpu_is_omap16xx() 0
+# endif
+# if defined(CONFIG_ARCH_OMAP24XX)
+# undef cpu_is_omap24xx
+# define cpu_is_omap24xx() 1
# endif
#endif
-#if defined(MULTI_OMAP)
-# define cpu_is_omap730() is_omap730()
-# define cpu_is_omap1510() is_omap1510()
-# define cpu_is_omap1610() is_omap1610()
-# define cpu_is_omap5912() is_omap5912()
-# define cpu_is_omap1710() is_omap1710()
+/*
+ * Macros to detect individual cpu types.
+ * These are only rarely needed.
+ * cpu_is_omap730(): True for OMAP730
+ * cpu_is_omap1510(): True for OMAP1510
+ * cpu_is_omap1610(): True for OMAP1610
+ * cpu_is_omap1611(): True for OMAP1611
+ * cpu_is_omap5912(): True for OMAP5912
+ * cpu_is_omap1621(): True for OMAP1621
+ * cpu_is_omap1710(): True for OMAP1710
+ * cpu_is_omap2420(): True for OMAP2420
+ */
+#define GET_OMAP_TYPE ((system_rev >> 16) & 0xffff)
+
+#define IS_OMAP_TYPE(type, id) \
+static inline int is_omap ##type (void) \
+{ \
+ return (GET_OMAP_TYPE == (id)) ? 1 : 0; \
+}
+
+IS_OMAP_TYPE(730, 0x0730)
+IS_OMAP_TYPE(1510, 0x1510)
+IS_OMAP_TYPE(1610, 0x1610)
+IS_OMAP_TYPE(1611, 0x1611)
+IS_OMAP_TYPE(5912, 0x1611)
+IS_OMAP_TYPE(1621, 0x1621)
+IS_OMAP_TYPE(1710, 0x1710)
+IS_OMAP_TYPE(2420, 0x2420)
+
+#define cpu_is_omap730() 0
+#define cpu_is_omap1510() 0
+#define cpu_is_omap1610() 0
+#define cpu_is_omap5912() 0
+#define cpu_is_omap1611() 0
+#define cpu_is_omap1621() 0
+#define cpu_is_omap1710() 0
+#define cpu_is_omap2420() 0
+
+#if defined(MULTI_OMAP1)
+# if defined(CONFIG_ARCH_OMAP730)
+# undef cpu_is_omap730
+# define cpu_is_omap730() is_omap730()
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+# undef cpu_is_omap1510
+# define cpu_is_omap1510() is_omap1510()
+# endif
#else
# if defined(CONFIG_ARCH_OMAP730)
+# undef cpu_is_omap730
# define cpu_is_omap730() 1
-# else
-# define cpu_is_omap730() 0
# endif
# if defined(CONFIG_ARCH_OMAP1510)
+# undef cpu_is_omap1510
# define cpu_is_omap1510() 1
-# else
-# define cpu_is_omap1510() 0
# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-# define cpu_is_omap1610() 1
-# else
-# define cpu_is_omap1610() 0
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-# define cpu_is_omap5912() 1
-# else
-# define cpu_is_omap5912() 0
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
+#endif
+
+/*
+ * Whether we have MULTI_OMAP1 or not, we still need to distinguish
+ * between 1611B/5912 and 1710.
+ */
+#if defined(CONFIG_ARCH_OMAP16XX)
+# undef cpu_is_omap1610
+# undef cpu_is_omap1611
+# undef cpu_is_omap5912
+# undef cpu_is_omap1621
+# undef cpu_is_omap1710
# define cpu_is_omap1610() is_omap1610()
+# define cpu_is_omap1611() is_omap1611()
# define cpu_is_omap5912() is_omap5912()
+# define cpu_is_omap1621() is_omap1621()
# define cpu_is_omap1710() is_omap1710()
-# else
-# define cpu_is_omap1610() 0
-# define cpu_is_omap5912() 0
-# define cpu_is_omap1710() 0
-# endif
-# if defined(CONFIG_ARCH_OMAP2420)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
+# undef cpu_is_omap2420
# define cpu_is_omap2420() 1
-# else
-# define cpu_is_omap2420() 0
-# endif
#endif
#endif
diff --git a/include/asm-arm/arch-omap/debug-macro.S b/include/asm-arm/arch-omap/debug-macro.S
index 83bb458afd0b..ca4f577f9675 100644
--- a/include/asm-arm/arch-omap/debug-macro.S
+++ b/include/asm-arm/arch-omap/debug-macro.S
@@ -14,6 +14,7 @@
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
+#ifdef CONFIG_ARCH_OMAP1
moveq \rx, #0xff000000 @ physical base address
movne \rx, #0xfe000000 @ virtual base
orr \rx, \rx, #0x00fb0000
@@ -23,6 +24,18 @@
#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3)
orr \rx, \rx, #0x00000800 @ UART 2 & 3
#endif
+
+#elif CONFIG_ARCH_OMAP2
+ moveq \rx, #0x48000000 @ physical base address
+ movne \rx, #0xd8000000 @ virtual base
+ orr \rx, \rx, #0x0006a000
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
+ add \rx, \rx, #0x00002000 @ UART 2
+#endif
+#ifdef CONFIG_OMAP_LL_DEBUG_UART3
+ add \rx, \rx, #0x00004000 @ UART 3
+#endif
+#endif
.endm
.macro senduart,rd,rx
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index ce114ce5af5d..04ebef5c6e95 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -240,6 +240,7 @@ extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
extern dma_addr_t omap_get_dma_src_pos(int lch);
extern dma_addr_t omap_get_dma_dst_pos(int lch);
+extern int omap_get_dma_src_addr_counter(int lch);
extern void omap_clear_dma(int lch);
extern int omap_dma_running(void);
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
new file mode 100644
index 000000000000..11772c792f3e
--- /dev/null
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -0,0 +1,92 @@
+/*
+ * linux/include/asm-arm/arm/arch-omap/dmtimer.h
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS 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
+ * 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_TIMER_H
+#define __ASM_ARCH_TIMER_H
+
+#include <linux/list.h>
+
+#define OMAP_TIMER_SRC_ARMXOR 0x00
+#define OMAP_TIMER_SRC_32_KHZ 0x01
+#define OMAP_TIMER_SRC_EXT_CLK 0x02
+
+/* timer control reg bits */
+#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
+#define OMAP_TIMER_CTRL_PT (1 << 12)
+#define OMAP_TIMER_CTRL_TRG_OVERFLOW (0x1 << 10)
+#define OMAP_TIMER_CTRL_TRG_OFANDMATCH (0x2 << 10)
+#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
+#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
+#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
+#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
+#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
+#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
+#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */
+#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
+#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
+
+/* timer interrupt enable bits */
+#define OMAP_TIMER_INT_CAPTURE (1 << 2)
+#define OMAP_TIMER_INT_OVERFLOW (1 << 1)
+#define OMAP_TIMER_INT_MATCH (1 << 0)
+
+
+struct omap_dm_timer {
+ struct list_head timer_list;
+
+ u32 base;
+ unsigned int irq;
+};
+
+u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg);
+void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value);
+
+struct omap_dm_timer * omap_dm_timer_request(void);
+void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value);
+void omap_dm_timer_enable_compare(struct omap_dm_timer *timer);
+void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer);
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer);
+void omap_dm_timer_start(struct omap_dm_timer *timer);
+void omap_dm_timer_stop(struct omap_dm_timer *timer);
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load);
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+
+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);
+
+#endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
new file mode 100644
index 000000000000..57bf4f39ca58
--- /dev/null
+++ b/include/asm-arm/arch-omap/dsp.h
@@ -0,0 +1,244 @@
+/*
+ * linux/include/asm-arm/arch-omap/dsp.h
+ *
+ * Header for OMAP DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2005/06/01: DSP Gateway version 3.3
+ */
+
+#ifndef ASM_ARCH_DSP_H
+#define ASM_ARCH_DSP_H
+
+
+/*
+ * for /dev/dspctl/ctl
+ */
+#define OMAP_DSP_IOCTL_RESET 1
+#define OMAP_DSP_IOCTL_RUN 2
+#define OMAP_DSP_IOCTL_SETRSTVECT 3
+#define OMAP_DSP_IOCTL_CPU_IDLE 4
+#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON 5
+#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF 6
+#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON 7
+#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF 8
+#define OMAP_DSP_IOCTL_GBL_IDLE 9
+#define OMAP_DSP_IOCTL_DSPCFG 10
+#define OMAP_DSP_IOCTL_DSPUNCFG 11
+#define OMAP_DSP_IOCTL_TASKCNT 12
+#define OMAP_DSP_IOCTL_POLL 13
+#define OMAP_DSP_IOCTL_REGMEMR 40
+#define OMAP_DSP_IOCTL_REGMEMW 41
+#define OMAP_DSP_IOCTL_REGIOR 42
+#define OMAP_DSP_IOCTL_REGIOW 43
+#define OMAP_DSP_IOCTL_GETVAR 44
+#define OMAP_DSP_IOCTL_SETVAR 45
+#define OMAP_DSP_IOCTL_RUNLEVEL 50
+#define OMAP_DSP_IOCTL_SUSPEND 51
+#define OMAP_DSP_IOCTL_RESUME 52
+#define OMAP_DSP_IOCTL_FBEN 53
+#define OMAP_DSP_IOCTL_FBDIS 54
+#define OMAP_DSP_IOCTL_MBSEND 99
+
+/*
+ * for taskdev
+ * (ioctls below should be >= 0x10000)
+ */
+#define OMAP_DSP_TASK_IOCTL_BFLSH 0x10000
+#define OMAP_DSP_TASK_IOCTL_SETBSZ 0x10001
+#define OMAP_DSP_TASK_IOCTL_LOCK 0x10002
+#define OMAP_DSP_TASK_IOCTL_UNLOCK 0x10003
+#define OMAP_DSP_TASK_IOCTL_GETNAME 0x10004
+
+/*
+ * for /dev/dspctl/mem
+ */
+#define OMAP_DSP_MEM_IOCTL_EXMAP 1
+#define OMAP_DSP_MEM_IOCTL_EXUNMAP 2
+#define OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH 3
+#define OMAP_DSP_MEM_IOCTL_FBEXPORT 5
+#define OMAP_DSP_MEM_IOCTL_MMUITACK 7
+#define OMAP_DSP_MEM_IOCTL_MMUINIT 9
+#define OMAP_DSP_MEM_IOCTL_KMEM_RESERVE 11
+#define OMAP_DSP_MEM_IOCTL_KMEM_RELEASE 12
+
+struct omap_dsp_mapinfo {
+ unsigned long dspadr;
+ unsigned long size;
+};
+
+/*
+ * for /dev/dspctl/twch
+ */
+#define OMAP_DSP_TWCH_IOCTL_MKDEV 1
+#define OMAP_DSP_TWCH_IOCTL_RMDEV 2
+#define OMAP_DSP_TWCH_IOCTL_TADD 11
+#define OMAP_DSP_TWCH_IOCTL_TDEL 12
+#define OMAP_DSP_TWCH_IOCTL_TKILL 13
+
+#define OMAP_DSP_DEVSTATE_NOTASK 0x00000001
+#define OMAP_DSP_DEVSTATE_ATTACHED 0x00000002
+#define OMAP_DSP_DEVSTATE_GARBAGE 0x00000004
+#define OMAP_DSP_DEVSTATE_INVALID 0x00000008
+#define OMAP_DSP_DEVSTATE_ADDREQ 0x00000100
+#define OMAP_DSP_DEVSTATE_DELREQ 0x00000200
+#define OMAP_DSP_DEVSTATE_ADDFAIL 0x00001000
+#define OMAP_DSP_DEVSTATE_ADDING 0x00010000
+#define OMAP_DSP_DEVSTATE_DELING 0x00020000
+#define OMAP_DSP_DEVSTATE_KILLING 0x00040000
+#define OMAP_DSP_DEVSTATE_STATE_MASK 0x7fffffff
+#define OMAP_DSP_DEVSTATE_STALE 0x80000000
+
+struct omap_dsp_taddinfo {
+ unsigned char minor;
+ unsigned long taskadr;
+};
+#define OMAP_DSP_TADD_ABORTADR 0xffffffff
+
+
+/*
+ * error cause definition (for error detection device)
+ */
+#define OMAP_DSP_ERRDT_WDT 0x00000001
+#define OMAP_DSP_ERRDT_MMU 0x00000002
+
+
+/*
+ * mailbox protocol definitions
+ */
+
+struct omap_dsp_mailbox_cmd {
+ unsigned short cmd;
+ unsigned short data;
+};
+
+struct omap_dsp_reginfo {
+ unsigned short adr;
+ unsigned short val;
+};
+
+struct omap_dsp_varinfo {
+ unsigned char varid;
+ unsigned short val[0];
+};
+
+#define OMAP_DSP_MBPROT_REVISION 0x0019
+
+#define OMAP_DSP_MBCMD_WDSND 0x10
+#define OMAP_DSP_MBCMD_WDREQ 0x11
+#define OMAP_DSP_MBCMD_BKSND 0x20
+#define OMAP_DSP_MBCMD_BKREQ 0x21
+#define OMAP_DSP_MBCMD_BKYLD 0x23
+#define OMAP_DSP_MBCMD_BKSNDP 0x24
+#define OMAP_DSP_MBCMD_BKREQP 0x25
+#define OMAP_DSP_MBCMD_TCTL 0x30
+#define OMAP_DSP_MBCMD_TCTLDATA 0x31
+#define OMAP_DSP_MBCMD_POLL 0x32
+#define OMAP_DSP_MBCMD_WDT 0x50 /* v3.3: obsolete */
+#define OMAP_DSP_MBCMD_RUNLEVEL 0x51
+#define OMAP_DSP_MBCMD_PM 0x52
+#define OMAP_DSP_MBCMD_SUSPEND 0x53
+#define OMAP_DSP_MBCMD_KFUNC 0x54
+#define OMAP_DSP_MBCMD_TCFG 0x60
+#define OMAP_DSP_MBCMD_TADD 0x62
+#define OMAP_DSP_MBCMD_TDEL 0x63
+#define OMAP_DSP_MBCMD_TSTOP 0x65
+#define OMAP_DSP_MBCMD_DSPCFG 0x70
+#define OMAP_DSP_MBCMD_REGRW 0x72
+#define OMAP_DSP_MBCMD_GETVAR 0x74
+#define OMAP_DSP_MBCMD_SETVAR 0x75
+#define OMAP_DSP_MBCMD_ERR 0x78
+#define OMAP_DSP_MBCMD_DBG 0x79
+
+#define OMAP_DSP_MBCMD_TCTL_TINIT 0x0000
+#define OMAP_DSP_MBCMD_TCTL_TEN 0x0001
+#define OMAP_DSP_MBCMD_TCTL_TDIS 0x0002
+#define OMAP_DSP_MBCMD_TCTL_TCLR 0x0003
+#define OMAP_DSP_MBCMD_TCTL_TCLR_FORCE 0x0004
+
+#define OMAP_DSP_MBCMD_RUNLEVEL_USER 0x01
+#define OMAP_DSP_MBCMD_RUNLEVEL_SUPER 0x0e
+#define OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY 0x10
+
+#define OMAP_DSP_MBCMD_PM_DISABLE 0x00
+#define OMAP_DSP_MBCMD_PM_ENABLE 0x01
+
+#define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00
+
+#define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002
+#define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003
+
+#define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000
+#define OMAP_DSP_MBCMD_TDEL_KILL 0x0001
+
+#define OMAP_DSP_MBCMD_DSPCFG_REQ 0x00
+#define OMAP_DSP_MBCMD_DSPCFG_SYSADRH 0x28
+#define OMAP_DSP_MBCMD_DSPCFG_SYSADRL 0x29
+#define OMAP_DSP_MBCMD_DSPCFG_PROTREV 0x70
+#define OMAP_DSP_MBCMD_DSPCFG_ABORT 0x78
+#define OMAP_DSP_MBCMD_DSPCFG_LAST 0x80
+
+#define OMAP_DSP_MBCMD_REGRW_MEMR 0x00
+#define OMAP_DSP_MBCMD_REGRW_MEMW 0x01
+#define OMAP_DSP_MBCMD_REGRW_IOR 0x02
+#define OMAP_DSP_MBCMD_REGRW_IOW 0x03
+#define OMAP_DSP_MBCMD_REGRW_DATA 0x04
+
+#define OMAP_DSP_MBCMD_VARID_ICRMASK 0x00
+#define OMAP_DSP_MBCMD_VARID_LOADINFO 0x01
+
+#define OMAP_DSP_TTYP_ARCV 0x0001
+#define OMAP_DSP_TTYP_ASND 0x0002
+#define OMAP_DSP_TTYP_BKMD 0x0004
+#define OMAP_DSP_TTYP_BKDM 0x0008
+#define OMAP_DSP_TTYP_PVMD 0x0010
+#define OMAP_DSP_TTYP_PVDM 0x0020
+
+#define OMAP_DSP_EID_BADTID 0x10
+#define OMAP_DSP_EID_BADTCN 0x11
+#define OMAP_DSP_EID_BADBID 0x20
+#define OMAP_DSP_EID_BADCNT 0x21
+#define OMAP_DSP_EID_NOTLOCKED 0x22
+#define OMAP_DSP_EID_STVBUF 0x23
+#define OMAP_DSP_EID_BADADR 0x24
+#define OMAP_DSP_EID_BADTCTL 0x30
+#define OMAP_DSP_EID_BADPARAM 0x50
+#define OMAP_DSP_EID_FATAL 0x58
+#define OMAP_DSP_EID_NOMEM 0xc0
+#define OMAP_DSP_EID_NORES 0xc1
+#define OMAP_DSP_EID_IPBFULL 0xc2
+#define OMAP_DSP_EID_WDT 0xd0
+#define OMAP_DSP_EID_TASKNOTRDY 0xe0
+#define OMAP_DSP_EID_TASKBSY 0xe1
+#define OMAP_DSP_EID_TASKERR 0xef
+#define OMAP_DSP_EID_BADCFGTYP 0xf0
+#define OMAP_DSP_EID_DEBUG 0xf8
+#define OMAP_DSP_EID_BADSEQ 0xfe
+#define OMAP_DSP_EID_BADCMD 0xff
+
+#define OMAP_DSP_TNM_LEN 16
+
+#define OMAP_DSP_TID_FREE 0xff
+#define OMAP_DSP_TID_ANON 0xfe
+
+#define OMAP_DSP_BID_NULL 0xffff
+#define OMAP_DSP_BID_PVT 0xfffe
+
+#endif /* ASM_ARCH_DSP_H */
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
new file mode 100644
index 000000000000..4fcce6944056
--- /dev/null
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-omap/dsp_common.h
+ *
+ * Header for OMAP DSP subsystem control
+ *
+ * Copyright (C) 2004,2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2005/06/03: DSP Gateway version 3.3
+ */
+
+#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);
+
+#endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S
index 57b126889b98..0d29b9c56a95 100644
--- a/include/asm-arm/arch-omap/entry-macro.S
+++ b/include/asm-arm/arch-omap/entry-macro.S
@@ -8,6 +8,8 @@
* warranty of any kind, whether express or implied.
*/
+#if defined(CONFIG_ARCH_OMAP1)
+
.macro disable_fiq
.endm
@@ -30,3 +32,29 @@
1510:
.endm
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#include <asm/arch/omap24xx.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =VA_IC_BASE
+ ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
+ cmp \irqnr, #0x0
+ bne 2222f
+ ldr \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */
+ cmp \irqnr, #0x0
+ bne 2222f
+ ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
+ cmp \irqnr, #0x0
+2222:
+ ldrne \irqnr, [\base, #IRQ_SIR_IRQ]
+
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
+#endif
diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
index fad2fc93ee70..74cb2b93b700 100644
--- a/include/asm-arm/arch-omap/gpio.h
+++ b/include/asm-arm/arch-omap/gpio.h
@@ -3,7 +3,7 @@
*
* OMAP GPIO handling defines and functions
*
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003-2005 Nokia Corporation
*
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*
@@ -30,7 +30,23 @@
#include <asm/arch/irqs.h>
#include <asm/io.h>
-#define OMAP_MPUIO_BASE 0xfffb5000
+#define OMAP_MPUIO_BASE (void __iomem *)0xfffb5000
+
+#ifdef CONFIG_ARCH_OMAP730
+#define OMAP_MPUIO_INPUT_LATCH 0x00
+#define OMAP_MPUIO_OUTPUT 0x02
+#define OMAP_MPUIO_IO_CNTL 0x04
+#define OMAP_MPUIO_KBR_LATCH 0x08
+#define OMAP_MPUIO_KBC 0x0a
+#define OMAP_MPUIO_GPIO_EVENT_MODE 0x0c
+#define OMAP_MPUIO_GPIO_INT_EDGE 0x0e
+#define OMAP_MPUIO_KBD_INT 0x10
+#define OMAP_MPUIO_GPIO_INT 0x12
+#define OMAP_MPUIO_KBD_MASKIT 0x14
+#define OMAP_MPUIO_GPIO_MASKIT 0x16
+#define OMAP_MPUIO_GPIO_DEBOUNCING 0x18
+#define OMAP_MPUIO_LATCH 0x1a
+#else
#define OMAP_MPUIO_INPUT_LATCH 0x00
#define OMAP_MPUIO_OUTPUT 0x04
#define OMAP_MPUIO_IO_CNTL 0x08
@@ -44,6 +60,7 @@
#define OMAP_MPUIO_GPIO_MASKIT 0x2c
#define OMAP_MPUIO_GPIO_DEBOUNCING 0x30
#define OMAP_MPUIO_LATCH 0x34
+#endif
#define OMAP_MPUIO(nr) (OMAP_MAX_GPIO_LINES + (nr))
#define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES)
@@ -52,18 +69,11 @@
IH_MPUIO_BASE + ((nr) & 0x0f) : \
IH_GPIO_BASE + ((nr) & 0x3f))
-/* For EDGECTRL */
-#define OMAP_GPIO_NO_EDGE 0x00
-#define OMAP_GPIO_FALLING_EDGE 0x01
-#define OMAP_GPIO_RISING_EDGE 0x02
-#define OMAP_GPIO_BOTH_EDGES 0x03
-
extern int omap_gpio_init(void); /* Call from board init only */
extern int omap_request_gpio(int gpio);
extern void omap_free_gpio(int gpio);
extern void omap_set_gpio_direction(int gpio, int is_input);
extern void omap_set_gpio_dataout(int gpio, int enable);
extern int omap_get_gpio_datain(int gpio);
-extern void omap_set_gpio_edge_ctrl(int gpio, int edge);
#endif
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 48258c7f6541..60201e1dd6ad 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -43,6 +43,7 @@
#include <asm/arch/cpu.h>
#endif
#include <asm/arch/io.h>
+#include <asm/arch/serial.h>
/*
* ---------------------------------------------------------------------------
@@ -89,11 +90,12 @@
/* DPLL control registers */
#define DPLL_CTL (0xfffecf00)
-/* DSP clock control */
+/* DSP clock control. Must use __raw_readw() and __raw_writew() with these */
#define DSP_CONFIG_REG_BASE (0xe1008000)
#define DSP_CKCTL (DSP_CONFIG_REG_BASE + 0x0)
#define DSP_IDLECT1 (DSP_CONFIG_REG_BASE + 0x4)
#define DSP_IDLECT2 (DSP_CONFIG_REG_BASE + 0x8)
+#define DSP_RSTCT2 (DSP_CONFIG_REG_BASE + 0x14)
/*
* ---------------------------------------------------------------------------
@@ -142,6 +144,13 @@
* Interrupts
* ---------------------------------------------------------------------------
*/
+#ifdef CONFIG_ARCH_OMAP1
+
+/*
+ * XXX: These probably want to be moved to arch/arm/mach-omap/omap1/irq.c
+ * or something similar.. -- PFM.
+ */
+
#define OMAP_IH1_BASE 0xfffecb00
#define OMAP_IH2_BASE 0xfffe0000
@@ -170,6 +179,8 @@
#define IRQ_ILR0_REG_OFFSET 0x1c
#define IRQ_GMR_REG_OFFSET 0xa0
+#endif
+
/*
* ----------------------------------------------------------------------------
* System control registers
@@ -260,32 +271,17 @@
/*
* ---------------------------------------------------------------------------
- * Serial ports
- * ---------------------------------------------------------------------------
- */
-#define OMAP_UART1_BASE (unsigned char *)0xfffb0000
-#define OMAP_UART2_BASE (unsigned char *)0xfffb0800
-#define OMAP_UART3_BASE (unsigned char *)0xfffb9800
-#define OMAP_MAX_NR_PORTS 3
-#define OMAP1510_BASE_BAUD (12000000/16)
-#define OMAP16XX_BASE_BAUD (48000000/16)
-
-#define is_omap_port(p) ({int __ret = 0; \
- if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
- p == IO_ADDRESS(OMAP_UART2_BASE) || \
- p == IO_ADDRESS(OMAP_UART3_BASE)) \
- __ret = 1; \
- __ret; \
- })
-
-/*
- * ---------------------------------------------------------------------------
* Processor specific defines
* ---------------------------------------------------------------------------
*/
#include "omap730.h"
#include "omap1510.h"
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#include "omap24xx.h"
+#endif
+
#include "omap16xx.h"
/*
@@ -312,7 +308,6 @@
#ifdef CONFIG_MACH_OMAP_H4
#include "board-h4.h"
-#error "Support for H4 board not yet implemented."
#endif
#ifdef CONFIG_MACH_OMAP_OSK
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
index 1c8c9fcc766e..11fbf629bf75 100644
--- a/include/asm-arm/arch-omap/io.h
+++ b/include/asm-arm/arch-omap/io.h
@@ -49,16 +49,24 @@
* I/O mapping
* ----------------------------------------------------------------------------
*/
-#define IO_PHYS 0xFFFB0000
-#define IO_OFFSET 0x01000000 /* Virtual IO = 0xfefb0000 */
-#define IO_VIRT (IO_PHYS - IO_OFFSET)
-#define IO_SIZE 0x40000
-#define IO_ADDRESS(x) ((x) - IO_OFFSET)
-#define PCIO_BASE 0
+#if defined(CONFIG_ARCH_OMAP1)
+#define IO_PHYS 0xFFFB0000
+#define IO_OFFSET -0x01000000 /* Virtual IO = 0xfefb0000 */
+#define IO_SIZE 0x40000
-#define io_p2v(x) ((x) - IO_OFFSET)
-#define io_v2p(x) ((x) + IO_OFFSET)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define IO_PHYS 0x48000000 /* L4 peripherals; other stuff has to be mapped *
+ * manually. */
+#define IO_OFFSET 0x90000000 /* Virtual IO = 0xd8000000 */
+#define IO_SIZE 0x08000000
+#endif
+
+#define IO_VIRT (IO_PHYS + IO_OFFSET)
+#define IO_ADDRESS(x) ((x) + IO_OFFSET)
+#define PCIO_BASE 0
+#define io_p2v(x) ((x) + IO_OFFSET)
+#define io_v2p(x) ((x) - IO_OFFSET)
#ifndef __ASSEMBLER__
@@ -96,6 +104,8 @@ typedef struct { volatile u32 offset[4096]; } __regbase32;
->offset[((vaddr)&4095)>>2]
#define __REG32(paddr) __REGV32(io_p2v(paddr))
+extern void omap_map_common_io(void);
+
#else
#define __REG8(paddr) io_p2v(paddr)
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 0d05a7c957d1..74e108ccac16 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -135,7 +135,6 @@
/*
* OMAP-1510 specific IRQ numbers for interrupt handler 2
*/
-#define INT_1510_OS_32kHz_TIMER (22 + IH2_BASE)
#define INT_1510_COM_SPI_RO (31 + IH2_BASE)
/*
@@ -232,6 +231,11 @@
#define INT_730_DMA_CH15 (62 + IH2_BASE)
#define INT_730_NAND (63 + IH2_BASE)
+#define INT_24XX_GPIO_BANK1 29
+#define INT_24XX_GPIO_BANK2 30
+#define INT_24XX_GPIO_BANK3 31
+#define INT_24XX_GPIO_BANK4 32
+
/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
* 16 MPUIO lines */
#define OMAP_MAX_GPIO_LINES 192
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index f6b57dd846a3..84f81e315a25 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -36,12 +36,11 @@
/*
* Physical DRAM offset.
*/
+#if defined(CONFIG_ARCH_OMAP1)
#define PHYS_OFFSET (0x10000000UL)
-
-/*
- * OMAP-1510 Local Bus address offset
- */
-#define OMAP1510_LB_OFFSET (0x30000000UL)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define PHYS_OFFSET (0x80000000UL)
+#endif
/*
* Conversion between SDRAM and fake PCI bus, used by USB
@@ -64,6 +63,11 @@
*/
#ifdef CONFIG_ARCH_OMAP1510
+/*
+ * OMAP-1510 Local Bus address offset
+ */
+#define OMAP1510_LB_OFFSET (0x30000000UL)
+
#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
#define is_lbus_device(dev) (cpu_is_omap1510() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
diff --git a/include/asm-arm/arch-omap/mtd-xip.h b/include/asm-arm/arch-omap/mtd-xip.h
new file mode 100644
index 000000000000..a73a28571fee
--- /dev/null
+++ b/include/asm-arm/arch-omap/mtd-xip.h
@@ -0,0 +1,61 @@
+/*
+ * MTD primitives for XIP support. Architecture specific functions.
+ *
+ * Do not include this file directly. It's included from linux/mtd/xip.h
+ *
+ * Author: Vladimir Barinov <vbarinov@ru.mvista.com>
+ *
+ * (c) 2005 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 __ARCH_OMAP_MTD_XIP_H__
+#define __ARCH_OMAP_MTD_XIP_H__
+
+#include <asm/hardware.h>
+#define OMAP_MPU_TIMER_BASE (0xfffec500)
+#define OMAP_MPU_TIMER_OFFSET 0x100
+
+typedef struct {
+ u32 cntl; /* CNTL_TIMER, R/W */
+ u32 load_tim; /* LOAD_TIM, W */
+ u32 read_tim; /* READ_TIM, R */
+} xip_omap_mpu_timer_regs_t;
+
+#define xip_omap_mpu_timer_base(n) \
+((volatile xip_omap_mpu_timer_regs_t*)IO_ADDRESS(OMAP_MPU_TIMER_BASE + \
+ (n)*OMAP_MPU_TIMER_OFFSET))
+
+static inline unsigned long xip_omap_mpu_timer_read(int nr)
+{
+ volatile xip_omap_mpu_timer_regs_t* timer = xip_omap_mpu_timer_base(nr);
+ return timer->read_tim;
+}
+
+#define xip_irqpending() \
+ (omap_readl(OMAP_IH1_ITR) & ~omap_readl(OMAP_IH1_MIR))
+#define xip_currtime() (~xip_omap_mpu_timer_read(0))
+
+/*
+ * It's permitted to do approxmation for xip_elapsed_since macro
+ * (see linux/mtd/xip.h)
+ */
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+#define xip_elapsed_since(x) (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 7)
+#else
+#define xip_elapsed_since(x) (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 6)
+#endif
+
+/*
+ * xip_cpu_idle() is used when waiting for a delay equal or larger than
+ * the system timer tick period. This should put the CPU into idle mode
+ * to save power and to be woken up only when some interrupts are pending.
+ * As above, this should not rely upon standard kernel code.
+ */
+
+#define xip_cpu_idle() asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (1))
+
+#endif /* __ARCH_OMAP_MTD_XIP_H__ */
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 5bd3f0097fc6..1b1ad4105349 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -185,6 +185,7 @@ typedef enum {
/* MPUIO */
MPUIO2,
+ N15_1610_MPUIO2,
MPUIO4,
MPUIO5,
T20_1610_MPUIO5,
@@ -210,6 +211,7 @@ typedef enum {
/* Misc ballouts */
BALLOUT_V8_ARMIO3,
+ N20_HDQ,
/* OMAP-1610 MMC2 */
W8_1610_MMC2_DAT0,
@@ -235,6 +237,7 @@ typedef enum {
P20_1610_GPIO4,
V9_1610_GPIO7,
W8_1610_GPIO9,
+ N20_1610_GPIO11,
N19_1610_GPIO13,
P10_1610_GPIO22,
V5_1610_GPIO24,
@@ -250,7 +253,7 @@ typedef enum {
U18_1610_UWIRE_SDI,
W21_1610_UWIRE_SDO,
N14_1610_UWIRE_CS0,
- P15_1610_UWIRE_CS0,
+ P15_1610_UWIRE_CS3,
N15_1610_UWIRE_CS1,
/* OMAP-1610 Flash */
@@ -411,7 +414,8 @@ MUX_CFG("N21_1710_GPIO14", 6, 9, 0, 1, 1, 1, 1, 1, 1)
MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1)
/* MPUIO */
-MUX_CFG("MPUIO2", 7, 18, 0, 1, 1, 1, NA, 0, 1)
+MUX_CFG("MPUIO2", 7, 18, 0, 1, 14, 1, NA, 0, 1)
+MUX_CFG("N15_1610_MPUIO2", 7, 18, 0, 1, 14, 1, 1, 0, 1)
MUX_CFG("MPUIO4", 7, 15, 0, 1, 13, 1, NA, 0, 1)
MUX_CFG("MPUIO5", 7, 12, 0, 1, 12, 1, NA, 0, 1)
@@ -438,6 +442,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)
/* OMAP-1610 MMC2 */
MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1)
@@ -463,6 +468,7 @@ MUX_CFG("J18_1610_ETM_D7", 5, 27, 1, 0, 19, 0, 0, 0, 1)
MUX_CFG("P20_1610_GPIO4", 6, 27, 0, 1, 7, 0, 1, 1, 1)
MUX_CFG("V9_1610_GPIO7", B, 12, 1, 2, 20, 0, 2, 1, 1)
MUX_CFG("W8_1610_GPIO9", B, 21, 0, 2, 23, 0, 2, 1, 1)
+MUX_CFG("N20_1610_GPIO11", 6, 18, 0, 1, 4, 0, 1, 1, 1)
MUX_CFG("N19_1610_GPIO13", 6, 12, 0, 1, 2, 0, 1, 1, 1)
MUX_CFG("P10_1610_GPIO22", C, 0, 7, 2, 26, 0, 2, 1, 1)
MUX_CFG("V5_1610_GPIO24", B, 15, 7, 2, 21, 0, 2, 1, 1)
diff --git a/include/asm-arm/arch-omap/omap1510.h b/include/asm-arm/arch-omap/omap1510.h
index f491a48ef2e1..f086a3933906 100644
--- a/include/asm-arm/arch-omap/omap1510.h
+++ b/include/asm-arm/arch-omap/omap1510.h
@@ -36,10 +36,6 @@
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP1510_SRAM_BASE 0xD0000000
-#define OMAP1510_SRAM_SIZE (SZ_128K + SZ_64K)
-#define OMAP1510_SRAM_START 0x20000000
-
#define OMAP1510_DSP_BASE 0xE0000000
#define OMAP1510_DSP_SIZE 0x28000
#define OMAP1510_DSP_START 0xE0000000
@@ -48,14 +44,5 @@
#define OMAP1510_DSPREG_SIZE SZ_128K
#define OMAP1510_DSPREG_START 0xE1000000
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1510_SRAM_IDLE_SUSPEND (OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
-#define OMAP1510_SRAM_API_SUSPEND (OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
-
#endif /* __ASM_ARCH_OMAP1510_H */
diff --git a/include/asm-arm/arch-omap/omap16xx.h b/include/asm-arm/arch-omap/omap16xx.h
index 38a9b95e6a33..f0c7f0fb4dc0 100644
--- a/include/asm-arm/arch-omap/omap16xx.h
+++ b/include/asm-arm/arch-omap/omap16xx.h
@@ -36,11 +36,6 @@
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP16XX_SRAM_BASE 0xD0000000
-#define OMAP1610_SRAM_SIZE (SZ_16K)
-#define OMAP5912_SRAM_SIZE 0x3E800
-#define OMAP16XX_SRAM_START 0x20000000
-
#define OMAP16XX_DSP_BASE 0xE0000000
#define OMAP16XX_DSP_SIZE 0x28000
#define OMAP16XX_DSP_START 0xE0000000
@@ -50,17 +45,6 @@
#define OMAP16XX_DSPREG_START 0xE1000000
/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1610_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
-#define OMAP1610_SRAM_API_SUSPEND (OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
-#define OMAP5912_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
-#define OMAP5912_SRAM_API_SUSPEND (OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
-
-/*
* ---------------------------------------------------------------------------
* Interrupts
* ---------------------------------------------------------------------------
diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
new file mode 100644
index 000000000000..a9105466a417
--- /dev/null
+++ b/include/asm-arm/arch-omap/omap24xx.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_ARCH_OMAP24XX_H
+#define __ASM_ARCH_OMAP24XX_H
+
+#define OMAP24XX_L4_IO_BASE 0x48000000
+
+/* interrupt controller */
+#define OMAP24XX_IC_BASE (OMAP24XX_L4_IO_BASE + 0xfe000)
+#define VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE)
+
+#define OMAP24XX_IVA_INTC_BASE 0x40000000
+
+#define IRQ_SIR_IRQ 0x0040
+
+#endif /* __ASM_ARCH_OMAP24XX_H */
+
diff --git a/include/asm-arm/arch-omap/omap730.h b/include/asm-arm/arch-omap/omap730.h
index 599ab00f5488..755b64c5e9f0 100644
--- a/include/asm-arm/arch-omap/omap730.h
+++ b/include/asm-arm/arch-omap/omap730.h
@@ -36,10 +36,6 @@
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-#define OMAP730_SRAM_BASE 0xD0000000
-#define OMAP730_SRAM_SIZE (SZ_128K + SZ_64K + SZ_8K)
-#define OMAP730_SRAM_START 0x20000000
-
#define OMAP730_DSP_BASE 0xE0000000
#define OMAP730_DSP_SIZE 0x50000
#define OMAP730_DSP_START 0xE0000000
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h
index f209fc0953fb..fbd742d0c499 100644
--- a/include/asm-arm/arch-omap/pm.h
+++ b/include/asm-arm/arch-omap/pm.h
@@ -61,7 +61,10 @@
#define PER_EN 0x1
#define CPU_SUSPEND_SIZE 200
-#define ULPD_LOW_POWER_EN 0x0001
+#define ULPD_LOW_PWR_EN 0x0001
+#define ULPD_DEEP_SLEEP_TRANSITION_EN 0x0010
+#define ULPD_SETUP_ANALOG_CELL_3_VAL 0
+#define ULPD_POWER_CTRL_REG_VAL 0x0219
#define DSP_IDLE_DELAY 10
#define DSP_IDLE 0x0040
@@ -86,46 +89,35 @@
#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5
#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00
#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2
-#define OMAP1510_ULPD_LOW_POWER_REQ 0x0001
-#define OMAP1610_DEEP_SLEEP_REQUEST 0x17c7
-#define OMAP1610_BIG_SLEEP_REQUEST TBD
+/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
+#define OMAP1610_IDLECT1_SLEEP_VAL 0x13c7
+#define OMAP1610_IDLECT2_SLEEP_VAL 0x09c7
+#define OMAP1610_IDLECT3_VAL 0x3f
+#define OMAP1610_IDLECT3_SLEEP_ORMASK 0x2c
+#define OMAP1610_IDLECT3 0xfffece24
#define OMAP1610_IDLE_LOOP_REQUEST 0x0400
-#define OMAP1610_IDLE_CLOCK_DOMAINS 0x09c7
-#define OMAP1610_ULPD_LOW_POWER_REQ 0x3
-
-#ifndef OMAP1510_SRAM_IDLE_SUSPEND
-#define OMAP1510_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_IDLE_SUSPEND
-#define OMAP1610_SRAM_IDLE_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_IDLE_SUSPEND
-#define OMAP5912_SRAM_IDLE_SUSPEND 0
-#endif
-
-#ifndef OMAP1510_SRAM_API_SUSPEND
-#define OMAP1510_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP1610_SRAM_API_SUSPEND
-#define OMAP1610_SRAM_API_SUSPEND 0
-#endif
-#ifndef OMAP5912_SRAM_API_SUSPEND
-#define OMAP5912_SRAM_API_SUSPEND 0
-#endif
#if !defined(CONFIG_ARCH_OMAP1510) && \
- !defined(CONFIG_ARCH_OMAP16XX)
+ !defined(CONFIG_ARCH_OMAP16XX) && \
+ !defined(CONFIG_ARCH_OMAP24XX)
#error "Power management for this processor not implemented yet"
#endif
#ifndef __ASSEMBLER__
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
-extern int omap1510_cpu_suspend(unsigned short, unsigned short);
-extern int omap1610_cpu_suspend(unsigned short, unsigned short);
-extern int omap1510_idle_loop_suspend(void);
-extern int omap1610_idle_loop_suspend(void);
+extern void omap1510_cpu_suspend(unsigned short, unsigned short);
+extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap1510_idle_loop_suspend(void);
+extern void omap1610_idle_loop_suspend(void);
+
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+extern void omap_serial_wake_trigger(int enable);
+#else
+#define omap_serial_wake_trigger(x) {}
+#endif /* CONFIG_OMAP_SERIAL_WAKE */
+
extern unsigned int omap1510_cpu_suspend_sz;
extern unsigned int omap1510_idle_loop_suspend_sz;
extern unsigned int omap1610_cpu_suspend_sz;
@@ -161,6 +153,7 @@ enum arm_save_state {
ARM_SLEEP_SAVE_ARM_CKCTL,
ARM_SLEEP_SAVE_ARM_IDLECT1,
ARM_SLEEP_SAVE_ARM_IDLECT2,
+ ARM_SLEEP_SAVE_ARM_IDLECT3,
ARM_SLEEP_SAVE_ARM_EWUPCT,
ARM_SLEEP_SAVE_ARM_RSTCT1,
ARM_SLEEP_SAVE_ARM_RSTCT2,
diff --git a/include/asm-arm/arch-omap/serial.h b/include/asm-arm/arch-omap/serial.h
new file mode 100644
index 000000000000..79a5297af9fc
--- /dev/null
+++ b/include/asm-arm/arch-omap/serial.h
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-omap/serial.h
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#if defined(CONFIG_ARCH_OMAP1)
+/* OMAP1 serial ports */
+#define OMAP_UART1_BASE 0xfffb0000
+#define OMAP_UART2_BASE 0xfffb0800
+#define OMAP_UART3_BASE 0xfffb9800
+#elif defined(CONFIG_ARCH_OMAP2)
+/* OMAP2 serial ports */
+#define OMAP_UART1_BASE 0x4806a000
+#define OMAP_UART2_BASE 0x4806c000
+#define OMAP_UART3_BASE 0x4806e000
+#endif
+
+#define OMAP_MAX_NR_PORTS 3
+#define OMAP1510_BASE_BAUD (12000000/16)
+#define OMAP16XX_BASE_BAUD (48000000/16)
+
+#define is_omap_port(p) ({int __ret = 0; \
+ if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
+ p == IO_ADDRESS(OMAP_UART2_BASE) || \
+ p == IO_ADDRESS(OMAP_UART3_BASE)) \
+ __ret = 1; \
+ __ret; \
+ })
+
+#endif
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
index 3e640aba8c20..3545c86859cc 100644
--- a/include/asm-arm/arch-omap/uncompress.h
+++ b/include/asm-arm/arch-omap/uncompress.h
@@ -20,7 +20,7 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/serial_reg.h>
-#include <asm/arch/hardware.h>
+#include <asm/arch/serial.h>
unsigned int system_rev;
@@ -34,8 +34,9 @@ static void
putstr(const char *s)
{
volatile u8 * uart = 0;
- int shift;
+ int shift = 2;
+#ifdef CONFIG_ARCH_OMAP
#ifdef CONFIG_OMAP_LL_DEBUG_UART3
uart = (volatile u8 *)(OMAP_UART3_BASE);
#elif CONFIG_OMAP_LL_DEBUG_UART2
@@ -44,6 +45,7 @@ putstr(const char *s)
uart = (volatile u8 *)(OMAP_UART1_BASE);
#endif
+#ifdef CONFIG_ARCH_OMAP1
/* Determine which serial port to use */
do {
/* MMU is not on, so cpu_is_omapXXXX() won't work here */
@@ -51,14 +53,14 @@ putstr(const char *s)
if (omap_id == OMAP_ID_730)
shift = 0;
- else
- shift = 2;
if (check_port(uart, shift))
break;
/* Silent boot if no serial ports are enabled. */
return;
} while (0);
+#endif /* CONFIG_ARCH_OMAP1 */
+#endif
/*
* Now, xmit each character
diff --git a/include/asm-arm/arch-pxa/akita.h b/include/asm-arm/arch-pxa/akita.h
new file mode 100644
index 000000000000..4a1fbcfccc39
--- /dev/null
+++ b/include/asm-arm/arch-pxa/akita.h
@@ -0,0 +1,30 @@
+/*
+ * Hardware specific definitions for SL-C1000 (Akita)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * 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.
+ *
+ */
+
+/* Akita IO Expander GPIOs */
+
+#define AKITA_IOEXP_RESERVED_7 (1 << 7)
+#define AKITA_IOEXP_IR_ON (1 << 6)
+#define AKITA_IOEXP_AKIN_PULLUP (1 << 5)
+#define AKITA_IOEXP_BACKLIGHT_CONT (1 << 4)
+#define AKITA_IOEXP_BACKLIGHT_ON (1 << 3)
+#define AKITA_IOEXP_MIC_BIAS (1 << 2)
+#define AKITA_IOEXP_RESERVED_1 (1 << 1)
+#define AKITA_IOEXP_RESERVED_0 (1 << 0)
+
+/* Direction Bitfield 0=output 1=input */
+#define AKITA_IOEXP_IO_DIR 0
+/* Default Values */
+#define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP)
+
+void akita_set_ioexp(struct device *dev, unsigned char bitmask);
+void akita_reset_ioexp(struct device *dev, unsigned char bitmask);
+
diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
index 324db06b5dd4..e554caa0d18b 100644
--- a/include/asm-arm/arch-pxa/corgi.h
+++ b/include/asm-arm/arch-pxa/corgi.h
@@ -103,18 +103,8 @@
* Shared data structures
*/
extern struct platform_device corgiscoop_device;
-
-/*
- * External Functions
- */
-extern unsigned long corgi_ssp_ads7846_putget(unsigned long);
-extern unsigned long corgi_ssp_ads7846_get(void);
-extern void corgi_ssp_ads7846_put(ulong data);
-extern void corgi_ssp_ads7846_lock(void);
-extern void corgi_ssp_ads7846_unlock(void);
-extern void corgi_ssp_lcdtg_send (u8 adrs, u8 data);
-extern void corgi_ssp_blduty_set(int duty);
-extern int corgi_ssp_max1111_get(ulong data);
+extern struct platform_device corgissp_device;
+extern struct platform_device corgifb_device;
#endif /* __ASM_ARCH_CORGI_H */
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index 72b04d846a23..cf35721cfa45 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -44,24 +44,12 @@
#ifndef __ASSEMBLY__
-#if 0
-# define __REG(x) (*((volatile u32 *)io_p2v(x)))
-#else
-/*
- * This __REG() version gives the same results as the one above, except
- * that we are fooling gcc somehow so it generates far better and smaller
- * assembly code for access to contigous registers. It's a shame that gcc
- * doesn't guess this by itself.
- */
-#include <asm/types.h>
-typedef struct { volatile u32 offset[4096]; } __regbase;
-# define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-# define __REG(x) __REGP(io_p2v(x))
-#endif
+# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
/* With indexed regs we don't want to feed the index through io_p2v()
especially if it is a variable, otherwise horrible code will result. */
-# define __REG2(x,y) (*(volatile u32 *)((u32)&__REG(x) + (y)))
+# define __REG2(x,y) \
+ (*(volatile unsigned long *)((unsigned long)&__REG(x) + (y)))
# define __PREG(x) (io_v2p((u32)&(x)))
diff --git a/include/asm-arm/arch-pxa/i2c.h b/include/asm-arm/arch-pxa/i2c.h
new file mode 100644
index 000000000000..46ec2243974a
--- /dev/null
+++ b/include/asm-arm/arch-pxa/i2c.h
@@ -0,0 +1,70 @@
+/*
+ * i2c_pxa.h
+ *
+ * Copyright (C) 2002 Intrinsyc 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 _I2C_PXA_H_
+#define _I2C_PXA_H_
+
+#if 0
+#define DEF_TIMEOUT 3
+#else
+/* need a longer timeout if we're dealing with the fact we may well be
+ * looking at a multi-master environment
+*/
+#define DEF_TIMEOUT 32
+#endif
+
+#define BUS_ERROR (-EREMOTEIO)
+#define XFER_NAKED (-ECONNREFUSED)
+#define I2C_RETRY (-2000) /* an error has occurred retry transmit */
+
+/* ICR initialize bit values
+*
+* 15. FM 0 (100 Khz operation)
+* 14. UR 0 (No unit reset)
+* 13. SADIE 0 (Disables the unit from interrupting on slave addresses
+* matching its slave address)
+* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration
+* in master mode)
+* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode)
+* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent)
+* 9. IRFIE 1 (Enable interrupts from full buffer received)
+* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty)
+* 7. GCD 1 (Disables i2c unit response to general call messages as a slave)
+* 6. IUE 0 (Disable unit until we change settings)
+* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL)
+* 4. MA 0 (Only send stop with the ICR stop bit)
+* 3. TB 0 (We are not transmitting a byte initially)
+* 2. ACKNAK 0 (Send an ACK after the unit receives a byte)
+* 1. STOP 0 (Do not send a STOP)
+* 0. START 0 (Do not send a START)
+*
+*/
+#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
+
+/* I2C status register init values
+ *
+ * 10. BED 1 (Clear bus error detected)
+ * 9. SAD 1 (Clear slave address detected)
+ * 7. IRF 1 (Clear IDBR Receive Full)
+ * 6. ITE 1 (Clear IDBR Transmit Empty)
+ * 5. ALD 1 (Clear Arbitration Loss Detected)
+ * 4. SSD 1 (Clear Slave Stop Detected)
+ */
+#define I2C_ISR_INIT 0x7FF /* status register init */
+
+struct i2c_slave_client;
+
+struct i2c_pxa_platform_data {
+ unsigned int slave_addr;
+ struct i2c_slave_client *slave;
+};
+
+extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
+#endif
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
index 7492ea7ea614..88c17dd02ed2 100644
--- a/include/asm-arm/arch-pxa/mmc.h
+++ b/include/asm-arm/arch-pxa/mmc.h
@@ -9,7 +9,9 @@ struct mmc_host;
struct pxamci_platform_data {
unsigned int ocr_mask; /* available voltages */
+ unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */
int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
+ int (*get_ro)(struct device *);
void (*setpower)(struct device *, unsigned int);
void (*exit)(struct device *, void *);
};
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 51f0fe0ac165..939d9e5020a0 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -818,6 +818,23 @@
#define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge
Interrupt Enable */
+#define UP2OCR __REG(0x40600020) /* USB Port 2 Output Control register */
+
+#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */
+#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */
+#define UP2OCR_DPPDE (1 << 2) /* Host Port 2 Transceiver D+ Pull Down Enable */
+#define UP2OCR_DMPDE (1 << 3) /* Host Port 2 Transceiver D- Pull Down Enable */
+#define UP2OCR_DPPUE (1 << 4) /* Host Port 2 Transceiver D+ Pull Up Enable */
+#define UP2OCR_DMPUE (1 << 5) /* Host Port 2 Transceiver D- Pull Up Enable */
+#define UP2OCR_DPPUBE (1 << 6) /* Host Port 2 Transceiver D+ Pull Up Bypass Enable */
+#define UP2OCR_DMPUBE (1 << 7) /* Host Port 2 Transceiver D- Pull Up Bypass Enable */
+#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */
+#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */
+#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */
+#define UP2OCR_HXS (1 << 16) /* Host Port 2 Transceiver Output Select */
+#define UP2OCR_HXOE (1 << 17) /* Host Port 2 Transceiver Output Enable */
+#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */
+
#define UDCCSN(x) __REG2(0x40600100, (x) << 2)
#define UDCCSR0 __REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
#define UDCCSR0_SA (1 << 7) /* Setup Active */
@@ -1423,6 +1440,7 @@
#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
+#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT)
#define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT)
#define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT)
#define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT)
@@ -1510,6 +1528,8 @@
#define PSSR_BFS (1 << 1) /* Battery Fault Status */
#define PSSR_SSS (1 << 0) /* Software Sleep Status */
+#define PSLR_SL_ROD (1 << 20) /* Sleep-Mode/Depp-Sleep Mode nRESET_OUT Disable */
+
#define PCFR_RO (1 << 15) /* RDH Override */
#define PCFR_PO (1 << 14) /* PH Override */
#define PCFR_GPROD (1 << 12) /* GPIO nRESET_OUT Disable */
@@ -1517,6 +1537,7 @@
#define PCFR_FVC (1 << 10) /* Frequency/Voltage Change */
#define PCFR_DC_EN (1 << 7) /* Sleep/deep-sleep DC-DC Converter Enable */
#define PCFR_PI2CEN (1 << 6) /* Enable PI2C controller */
+#define PCFR_GPR_EN (1 << 4) /* nRESET_GPIO Pin Enable */
#define PCFR_DS (1 << 3) /* Deep Sleep Mode */
#define PCFR_FS (1 << 2) /* Float Static Chip Selects */
#define PCFR_FP (1 << 1) /* Float PCMCIA controls */
@@ -1810,6 +1831,11 @@
#define LCCR0_PDD_S 12
#define LCCR0_BM (1 << 20) /* Branch mask */
#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
+#define LCCR0_LCDT (1 << 22) /* LCD panel type */
+#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */
+#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */
+#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */
+#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */
#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
#define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \
@@ -2062,7 +2088,10 @@
#define UHCFMN __REG(0x4C00003C) /* UHC Frame Number */
#define UHCPERS __REG(0x4C000040) /* UHC Periodic Start */
#define UHCLS __REG(0x4C000044) /* UHC Low Speed Threshold */
+
#define UHCRHDA __REG(0x4C000048) /* UHC Root Hub Descriptor A */
+#define UHCRHDA_NOCP (1 << 12) /* No over current protection */
+
#define UHCRHDB __REG(0x4C00004C) /* UHC Root Hub Descriptor B */
#define UHCRHS __REG(0x4C000050) /* UHC Root Hub Status */
#define UHCRHPS1 __REG(0x4C000054) /* UHC Root Hub Port 1 Status */
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index 27d71e9d413b..21c0e16dce5f 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -66,3 +66,4 @@ struct pxafb_mach_info {
};
void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
+unsigned long pxafb_get_hsync_time(struct device *dev);
diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h
new file mode 100644
index 000000000000..311f2bb5386a
--- /dev/null
+++ b/include/asm-arm/arch-pxa/sharpsl.h
@@ -0,0 +1,32 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+unsigned long corgi_ssp_ads7846_putget(unsigned long);
+unsigned long corgi_ssp_ads7846_get(void);
+void corgi_ssp_ads7846_put(unsigned long data);
+void corgi_ssp_ads7846_lock(void);
+void corgi_ssp_ads7846_unlock(void);
+void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
+void corgi_ssp_blduty_set(int duty);
+int corgi_ssp_max1111_get(unsigned long data);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+struct corgits_machinfo {
+ unsigned long (*get_hsync_len)(void);
+ void (*put_hsync)(void);
+ void (*wait_hsync)(void);
+};
+
+/*
+ * SharpSL Backlight
+ */
+
+struct corgibl_machinfo {
+ int max_intensity;
+ void (*set_bl_intensity)(int intensity);
+};
+
diff --git a/include/asm-arm/arch-pxa/spitz.h b/include/asm-arm/arch-pxa/spitz.h
new file mode 100644
index 000000000000..62e1fe4d025f
--- /dev/null
+++ b/include/asm-arm/arch-pxa/spitz.h
@@ -0,0 +1,158 @@
+/*
+ * Hardware specific definitions for SL-Cx000 series of PDAs
+ *
+ * Copyright (c) 2005 Alexander Wykes
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * 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_SPITZ_H
+#define __ASM_ARCH_SPITZ_H 1
+#endif
+
+/* Spitz/Akita GPIOs */
+
+#define SPITZ_GPIO_KEY_INT (0) /* Key Interrupt */
+#define SPITZ_GPIO_RESET (1)
+#define SPITZ_GPIO_nSD_DETECT (9)
+#define SPITZ_GPIO_TP_INT (11) /* Touch Panel interrupt */
+#define SPITZ_GPIO_AK_INT (13) /* Remote Control */
+#define SPITZ_GPIO_ADS7846_CS (14)
+#define SPITZ_GPIO_SYNC (16)
+#define SPITZ_GPIO_MAX1111_CS (20)
+#define SPITZ_GPIO_FATAL_BAT (21)
+#define SPITZ_GPIO_HSYNC (22)
+#define SPITZ_GPIO_nSD_CLK (32)
+#define SPITZ_GPIO_USB_DEVICE (35)
+#define SPITZ_GPIO_USB_HOST (37)
+#define SPITZ_GPIO_USB_CONNECT (41)
+#define SPITZ_GPIO_LCDCON_CS (53)
+#define SPITZ_GPIO_nPCE (54)
+#define SPITZ_GPIO_nSD_WP (81)
+#define SPITZ_GPIO_ON_RESET (89)
+#define SPITZ_GPIO_BAT_COVER (90)
+#define SPITZ_GPIO_CF_CD (94)
+#define SPITZ_GPIO_ON_KEY (95)
+#define SPITZ_GPIO_SWA (97)
+#define SPITZ_GPIO_SWB (96)
+#define SPITZ_GPIO_CHRG_FULL (101)
+#define SPITZ_GPIO_CO (101)
+#define SPITZ_GPIO_CF_IRQ (105)
+#define SPITZ_GPIO_AC_IN (115)
+#define SPITZ_GPIO_HP_IN (116)
+
+/* Spitz Only GPIOs */
+
+#define SPITZ_GPIO_CF2_IRQ (106) /* CF slot1 Ready */
+#define SPITZ_GPIO_CF2_CD (93)
+
+
+/* Spitz/Akita Keyboard Definitions */
+
+#define SPITZ_KEY_STROBE_NUM (11)
+#define SPITZ_KEY_SENSE_NUM (7)
+#define SPITZ_GPIO_G0_STROBE_BIT 0x0f800000
+#define SPITZ_GPIO_G1_STROBE_BIT 0x00100000
+#define SPITZ_GPIO_G2_STROBE_BIT 0x01000000
+#define SPITZ_GPIO_G3_STROBE_BIT 0x00041880
+#define SPITZ_GPIO_G0_SENSE_BIT 0x00021000
+#define SPITZ_GPIO_G1_SENSE_BIT 0x000000d4
+#define SPITZ_GPIO_G2_SENSE_BIT 0x08000000
+#define SPITZ_GPIO_G3_SENSE_BIT 0x00000000
+
+#define SPITZ_GPIO_KEY_STROBE0 88
+#define SPITZ_GPIO_KEY_STROBE1 23
+#define SPITZ_GPIO_KEY_STROBE2 24
+#define SPITZ_GPIO_KEY_STROBE3 25
+#define SPITZ_GPIO_KEY_STROBE4 26
+#define SPITZ_GPIO_KEY_STROBE5 27
+#define SPITZ_GPIO_KEY_STROBE6 52
+#define SPITZ_GPIO_KEY_STROBE7 103
+#define SPITZ_GPIO_KEY_STROBE8 107
+#define SPITZ_GPIO_KEY_STROBE9 108
+#define SPITZ_GPIO_KEY_STROBE10 114
+
+#define SPITZ_GPIO_KEY_SENSE0 12
+#define SPITZ_GPIO_KEY_SENSE1 17
+#define SPITZ_GPIO_KEY_SENSE2 91
+#define SPITZ_GPIO_KEY_SENSE3 34
+#define SPITZ_GPIO_KEY_SENSE4 36
+#define SPITZ_GPIO_KEY_SENSE5 38
+#define SPITZ_GPIO_KEY_SENSE6 39
+
+
+/* Spitz Scoop Device (No. 1) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP_LED_GREEN SCOOP_GPCR_PA11 /* Keep */
+#define SPITZ_SCP_JK_B SCOOP_GPCR_PA12 /* Keep */
+#define SPITZ_SCP_CHRG_ON SCOOP_GPCR_PA13 /* Keep */
+#define SPITZ_SCP_MUTE_L SCOOP_GPCR_PA14 /* Low */
+#define SPITZ_SCP_MUTE_R SCOOP_GPCR_PA15 /* Low */
+#define SPITZ_SCP_CF_POWER SCOOP_GPCR_PA16 /* Keep */
+#define SPITZ_SCP_LED_ORANGE SCOOP_GPCR_PA17 /* Keep */
+#define SPITZ_SCP_JK_A SCOOP_GPCR_PA18 /* Low */
+#define SPITZ_SCP_ADC_TEMP_ON SCOOP_GPCR_PA19 /* Low */
+
+#define SPITZ_SCP_IO_DIR (SPITZ_SCP_LED_GREEN | SPITZ_SCP_JK_B | SPITZ_SCP_CHRG_ON | \
+ SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_LED_ORANGE | \
+ SPITZ_SCP_CF_POWER | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_IO_OUT (SPITZ_SCP_CHRG_ON | SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R)
+#define SPITZ_SCP_SUS_CLR (SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_SUS_SET 0
+
+/* Spitz Scoop Device (No. 2) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP2_IR_ON SCOOP_GPCR_PA11 /* High */
+#define SPITZ_SCP2_AKIN_PULLUP SCOOP_GPCR_PA12 /* Keep */
+#define SPITZ_SCP2_RESERVED_1 SCOOP_GPCR_PA13 /* High */
+#define SPITZ_SCP2_RESERVED_2 SCOOP_GPCR_PA14 /* Low */
+#define SPITZ_SCP2_RESERVED_3 SCOOP_GPCR_PA15 /* Low */
+#define SPITZ_SCP2_RESERVED_4 SCOOP_GPCR_PA16 /* Low */
+#define SPITZ_SCP2_BACKLIGHT_CONT SCOOP_GPCR_PA17 /* Low */
+#define SPITZ_SCP2_BACKLIGHT_ON SCOOP_GPCR_PA18 /* Low */
+#define SPITZ_SCP2_MIC_BIAS SCOOP_GPCR_PA19 /* Low */
+
+#define SPITZ_SCP2_IO_DIR (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1 | \
+ SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+ SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+
+#define SPITZ_SCP2_IO_OUT (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1)
+#define SPITZ_SCP2_SUS_CLR (SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+ SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+#define SPITZ_SCP2_SUS_SET (SPITZ_SCP2_IR_ON | SPITZ_SCP2_RESERVED_1)
+
+
+/* Spitz IRQ Definitions */
+
+#define SPITZ_IRQ_GPIO_KEY_INT IRQ_GPIO(SPITZ_GPIO_KEY_INT)
+#define SPITZ_IRQ_GPIO_AC_IN IRQ_GPIO(SPITZ_GPIO_AC_IN)
+#define SPITZ_IRQ_GPIO_AK_INT IRQ_GPIO(SPITZ_GPIO_AK_INT)
+#define SPITZ_IRQ_GPIO_HP_IN IRQ_GPIO(SPITZ_GPIO_HP_IN)
+#define SPITZ_IRQ_GPIO_TP_INT IRQ_GPIO(SPITZ_GPIO_TP_INT)
+#define SPITZ_IRQ_GPIO_SYNC IRQ_GPIO(SPITZ_GPIO_SYNC)
+#define SPITZ_IRQ_GPIO_ON_KEY IRQ_GPIO(SPITZ_GPIO_ON_KEY)
+#define SPITZ_IRQ_GPIO_SWA IRQ_GPIO(SPITZ_GPIO_SWA)
+#define SPITZ_IRQ_GPIO_SWB IRQ_GPIO(SPITZ_GPIO_SWB)
+#define SPITZ_IRQ_GPIO_BAT_COVER IRQ_GPIO(SPITZ_GPIO_BAT_COVER)
+#define SPITZ_IRQ_GPIO_FATAL_BAT IRQ_GPIO(SPITZ_GPIO_FATAL_BAT)
+#define SPITZ_IRQ_GPIO_CO IRQ_GPIO(SPITZ_GPIO_CO)
+#define SPITZ_IRQ_GPIO_CF_IRQ IRQ_GPIO(SPITZ_GPIO_CF_IRQ)
+#define SPITZ_IRQ_GPIO_CF_CD IRQ_GPIO(SPITZ_GPIO_CF_CD)
+#define SPITZ_IRQ_GPIO_CF2_IRQ IRQ_GPIO(SPITZ_GPIO_CF2_IRQ)
+#define SPITZ_IRQ_GPIO_nSD_INT IRQ_GPIO(SPITZ_GPIO_nSD_INT)
+#define SPITZ_IRQ_GPIO_nSD_DETECT IRQ_GPIO(SPITZ_GPIO_nSD_DETECT)
+
+/*
+ * Shared data structures
+ */
+extern struct platform_device spitzscoop_device;
+extern struct platform_device spitzscoop2_device;
+extern struct platform_device spitzssp_device;
+extern struct sharpsl_charger_machinfo spitz_pm_machinfo;
+
+extern void spitz_lcd_power(int on);
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
new file mode 100644
index 000000000000..5675b1796b55
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/anubis-cpld.h
@@ -0,0 +1,24 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-cpld.h
+ *
+ * (c) 2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * ANUBIS - CPLD control constants
+ *
+ * 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.
+ *
+ * Changelog:
+ *
+*/
+
+#ifndef __ASM_ARCH_ANUBISCPLD_H
+#define __ASM_ARCH_ANUBISCPLD_H
+
+/* CTRL2 - NAND WP control, IDE Reset assert/check */
+
+#define ANUBIS_CTRL1_NANDSEL (0x3)
+
+#endif /* __ASM_ARCH_ANUBISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-irq.h b/include/asm-arm/arch-s3c2410/anubis-irq.h
new file mode 100644
index 000000000000..82f15dbd97e8
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/anubis-irq.h
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-irq.h
+ *
+ * (c) 2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * ANUBIS - IRQ Number definitions
+ *
+ * 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.
+ *
+ * Changelog:
+ */
+
+#ifndef __ASM_ARCH_ANUBISIRQ_H
+#define __ASM_ARCH_ANUBISIRQ_H
+
+#define IRQ_IDE0 IRQ_EINT2
+#define IRQ_IDE1 IRQ_EINT3
+#define IRQ_ASIX IRQ_EINT1
+
+#endif /* __ASM_ARCH_ANUBISIRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
new file mode 100644
index 000000000000..97741d6e506a
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/anubis-map.h
@@ -0,0 +1,46 @@
+/* linux/include/asm-arm/arch-s3c2410/anubis-map.h
+ *
+ * (c) 2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * ANUBIS - Memory map definitions
+ *
+ * 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.
+ *
+ * Changelog:
+*/
+
+/* needs arch/map.h including with this */
+
+#ifndef __ASM_ARCH_ANUBISMAP_H
+#define __ASM_ARCH_ANUBISMAP_H
+
+/* start peripherals off after the S3C2410 */
+
+#define ANUBIS_IOADDR(x) (S3C2410_ADDR((x) + 0x02000000))
+
+#define ANUBIS_PA_CPLD (S3C2410_CS1 | (1<<26))
+
+/* we put the CPLD registers next, to get them out of the way */
+
+#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) /* 0x01300000 */
+#define ANUBIS_PA_CTRL1 (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL2 ANUBIS_IOADDR(0x00100000) /* 0x01400000 */
+#define ANUBIS_PA_CTRL2 (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL3 ANUBIS_IOADDR(0x00200000) /* 0x01500000 */
+#define ANUBIS_PA_CTRL3 (ANUBIS_PA_CPLD)
+
+#define ANUBIS_VA_CTRL4 ANUBIS_IOADDR(0x00300000) /* 0x01600000 */
+#define ANUBIS_PA_CTRL4 (ANUBIS_PA_CPLD)
+
+#define ANUBIS_IDEPRI ANUBIS_IOADDR(0x01000000)
+#define ANUBIS_IDEPRIAUX ANUBIS_IOADDR(0x01100000)
+#define ANUBIS_IDESEC ANUBIS_IOADDR(0x01200000)
+#define ANUBIS_IDESECAUX ANUBIS_IOADDR(0x01300000)
+
+#endif /* __ASM_ARCH_ANUBISMAP_H */
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
new file mode 100644
index 000000000000..ac57bc887d82
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -0,0 +1,69 @@
+/* linux/include/asm/arch-s3c2410/fb.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Changelog:
+ * 07-Sep-2004 RTP Created file
+ * 03-Nov-2004 BJD Updated and minor cleanups
+ * 03-Aug-2005 RTP Renamed to fb.h
+*/
+
+#ifndef __ASM_ARM_FB_H
+#define __ASM_ARM_FB_H
+
+#include <asm/arch/regs-lcd.h>
+
+struct s3c2410fb_val {
+ unsigned int defval;
+ unsigned int min;
+ unsigned int max;
+};
+
+struct s3c2410fb_hw {
+ unsigned long lcdcon1;
+ unsigned long lcdcon2;
+ unsigned long lcdcon3;
+ unsigned long lcdcon4;
+ unsigned long lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+ unsigned char fixed_syncs; /* do not update sync/border */
+
+ /* Screen size */
+ int width;
+ int height;
+
+ /* Screen info */
+ struct s3c2410fb_val xres;
+ struct s3c2410fb_val yres;
+ struct s3c2410fb_val bpp;
+
+ /* lcd configuration registers */
+ struct s3c2410fb_hw regs;
+
+ /* GPIOs */
+
+ unsigned long gpcup;
+ unsigned long gpcup_mask;
+ unsigned long gpccon;
+ unsigned long gpccon_mask;
+ unsigned long gpdup;
+ unsigned long gpdup_mask;
+ unsigned long gpdcon;
+ unsigned long gpdcon_mask;
+
+ /* lpc3600 control register */
+ unsigned long lpcsel;
+};
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info);
+
+#endif /* __ASM_ARM_FB_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index e5e938b79acc..16f4c3cc1388 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -1,7 +1,7 @@
/* linux/include/asm/arch-s3c2410/regs-clock.h
*
- * Copyright (c) 2003,2004 Simtec Electronics <linux@simtec.co.uk>
- * http://www.simtec.co.uk/products/SWLINUX/
+ * Copyright (c) 2003,2004,2005 Simtec Electronics <linux@simtec.co.uk>
+ * http://armlinux.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
@@ -17,6 +17,7 @@
* 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion
* 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat)
* 10-Mar-2005 Lucas Villa Real Changed S3C2410_VA to S3C24XX_VA
+ * 27-Aug-2005 Ben Dooks Add clock-slow info
*/
#ifndef __ASM_ARM_REGS_CLOCK
@@ -74,6 +75,12 @@
#define S3C2410_CLKDIVN_PDIVN (1<<0)
#define S3C2410_CLKDIVN_HDIVN (1<<1)
+#define S3C2410_CLKSLOW_UCLK_OFF (1<<7)
+#define S3C2410_CLKSLOW_MPLL_OFF (1<<5)
+#define S3C2410_CLKSLOW_SLOW (1<<4)
+#define S3C2410_CLKSLOW_SLOWVAL(x) (x)
+#define S3C2410_CLKSLOW_GET_SLOWVAL(x) ((x) & 7)
+
#ifndef __ASSEMBLY__
static inline unsigned int
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index 7f882ea92b2a..b6b1b4e8bbeb 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -51,21 +51,32 @@
#define S3C2410_LCDCON1_ENVID (1)
+#define S3C2410_LCDCON1_MODEMASK 0x1E
+
#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
+#define S3C2410_LCDCON2_GET_VBPD(x) ( ((x) >> 24) & 0xFF)
+#define S3C2410_LCDCON2_GET_VFPD(x) ( ((x) >> 6) & 0xFF)
+#define S3C2410_LCDCON2_GET_VSPW(x) ( ((x) >> 0) & 0x3F)
+
#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
+#define S3C2410_LCDCON3_GET_HBPD(x) ( ((x) >> 19) & 0x7F)
+#define S3C2410_LCDCON3_GET_HFPD(x) ( ((x) >> 0) & 0xFF)
+
#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
#define S3C2410_LCDCON4_WLH(x) ((x) << 0)
+#define S3C2410_LCDCON4_GET_HSPW(x) ( ((x) >> 0) & 0xFF)
+
#define S3C2410_LCDCON5_BPP24BL (1<<12)
#define S3C2410_LCDCON5_FRM565 (1<<11)
#define S3C2410_LCDCON5_INVVCLK (1<<10)
@@ -100,10 +111,16 @@
#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
#define S3C2410_TPAL S3C2410_LCDREG(0x50)
+#define S3C2410_TPAL_EN (1<<24)
+
/* interrupt info */
#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
+#define S3C2410_LCDINT_FIWSEL (1<<2)
+#define S3C2410_LCDINT_FRSYNC (1<<1)
+#define S3C2410_LCDINT_FICNT (1<<0)
+
#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)
#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index 10c62db34362..19c3b1e186bb 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -49,23 +49,9 @@
( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))<<VIO_SHIFT)) + PIO_START )
#ifndef __ASSEMBLY__
-#include <asm/types.h>
-#if 0
-# define __REG(x) (*((volatile u32 *)io_p2v(x)))
-#else
-/*
- * This __REG() version gives the same results as the one above, except
- * that we are fooling gcc somehow so it generates far better and smaller
- * assembly code for access to contigous registers. It's a shame that gcc
- * doesn't guess this by itself.
- */
-typedef struct { volatile u32 offset[4096]; } __regbase;
-# define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-# define __REG(x) __REGP(io_p2v(x))
-#endif
-
-# define __PREG(x) (io_v2p((u32)&(x)))
+# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
+# define __PREG(x) (io_v2p((unsigned long)&(x)))
#else
diff --git a/include/asm-arm/arch-sa1100/mcp.h b/include/asm-arm/arch-sa1100/mcp.h
new file mode 100644
index 000000000000..f58a22755c61
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/mcp.h
@@ -0,0 +1,21 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/mcp.h
+ *
+ * Copyright (C) 2005 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.
+ */
+#ifndef __ASM_ARM_ARCH_MCP_H
+#define __ASM_ARM_ARCH_MCP_H
+
+#include <linux/types.h>
+
+struct mcp_plat_data {
+ u32 mccr0;
+ u32 mccr1;
+ unsigned int sclk_rate;
+};
+
+#endif
diff --git a/include/asm-arm/auxvec.h b/include/asm-arm/auxvec.h
new file mode 100644
index 000000000000..c0536f6b29a7
--- /dev/null
+++ b/include/asm-arm/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMARM_AUXVEC_H
+#define __ASMARM_AUXVEC_H
+
+#endif
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 035cdcff43d2..e81baff4f54b 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -256,7 +256,7 @@ extern void dmac_flush_range(unsigned long, unsigned long);
* Convert calls to our calling convention.
*/
#define flush_cache_all() __cpuc_flush_kern_all()
-
+#ifndef CONFIG_CPU_CACHE_VIPT
static inline void flush_cache_mm(struct mm_struct *mm)
{
if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
@@ -279,6 +279,11 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l
__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
}
}
+#else
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
+#endif
/*
* flush_cache_user_range is used when we want to ensure that the
diff --git a/include/asm-arm/fcntl.h b/include/asm-arm/fcntl.h
index 485b6bdf4d7a..a80b6607b2ef 100644
--- a/include/asm-arm/fcntl.h
+++ b/include/asm-arm/fcntl.h
@@ -1,87 +1,11 @@
#ifndef _ARM_FCNTL_H
#define _ARM_FCNTL_H
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
-#define O_NOATIME 01000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
+#include <asm-generic/fcntl.h>
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-arm/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-arm/hardware/gic.h b/include/asm-arm/hardware/gic.h
new file mode 100644
index 000000000000..3fa5eb70f64e
--- /dev/null
+++ b/include/asm-arm/hardware/gic.h
@@ -0,0 +1,41 @@
+/*
+ * linux/include/asm-arm/hardware/gic.h
+ *
+ * Copyright (C) 2002 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.
+ */
+#ifndef __ASM_ARM_HARDWARE_GIC_H
+#define __ASM_ARM_HARDWARE_GIC_H
+
+#include <linux/compiler.h>
+
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_PRIMASK 0x04
+#define GIC_CPU_BINPOINT 0x08
+#define GIC_CPU_INTACK 0x0c
+#define GIC_CPU_EOI 0x10
+#define GIC_CPU_RUNNINGPRI 0x14
+#define GIC_CPU_HIGHPRI 0x18
+
+#define GIC_DIST_CTRL 0x000
+#define GIC_DIST_CTR 0x004
+#define GIC_DIST_ENABLE_SET 0x100
+#define GIC_DIST_ENABLE_CLEAR 0x180
+#define GIC_DIST_PENDING_SET 0x200
+#define GIC_DIST_PENDING_CLEAR 0x280
+#define GIC_DIST_ACTIVE_BIT 0x300
+#define GIC_DIST_PRI 0x400
+#define GIC_DIST_TARGET 0x800
+#define GIC_DIST_CONFIG 0xc00
+#define GIC_DIST_SOFTINT 0xf00
+
+#ifndef __ASSEMBLY__
+void gic_dist_init(void __iomem *base);
+void gic_cpu_init(void __iomem *base);
+void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
+#endif
+
+#endif
diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
index 7ea771ff6144..527404b5a8df 100644
--- a/include/asm-arm/hardware/scoop.h
+++ b/include/asm-arm/hardware/scoop.h
@@ -40,6 +40,19 @@ struct scoop_config {
unsigned short io_dir;
};
+/* Structure for linking scoop devices to PCMCIA sockets */
+struct scoop_pcmcia_dev {
+ struct device *dev; /* Pointer to this socket's scoop device */
+ int irq; /* irq for socket */
+ int cd_irq;
+ const char *cd_irq_str;
+ unsigned char keep_vs;
+ unsigned char keep_rd;
+};
+
+extern int scoop_num;
+extern struct scoop_pcmcia_dev *scoop_devs;
+
void reset_scoop(struct device *dev);
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
diff --git a/include/asm-arm/hdreg.h b/include/asm-arm/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-arm/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
index a43a353f6c7b..0ce6ca588d8c 100644
--- a/include/asm-arm/mach/irq.h
+++ b/include/asm-arm/mach/irq.h
@@ -42,11 +42,11 @@ struct irqchip {
/*
* Set the type of the IRQ.
*/
- int (*type)(unsigned int, unsigned int);
+ int (*set_type)(unsigned int, unsigned int);
/*
* Set wakeup-enable on the selected IRQ
*/
- int (*wake)(unsigned int, unsigned int);
+ int (*set_wake)(unsigned int, unsigned int);
#ifdef CONFIG_SMP
/*
@@ -92,6 +92,14 @@ struct irqdesc {
extern struct irqdesc irq_desc[];
/*
+ * Helpful inline function for calling irq descriptor handlers.
+ */
+static inline void desc_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ desc->handle(irq, desc, regs);
+}
+
+/*
* This is internal. Do not use it.
*/
extern void (*init_arch_irq)(void);
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 2cf279a44017..96c6db7dd0e1 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -47,9 +47,7 @@ struct sys_timer {
#ifdef CONFIG_NO_IDLE_HZ
-#define DYN_TICK_SKIPPING (1 << 2)
#define DYN_TICK_ENABLED (1 << 1)
-#define DYN_TICK_SUITABLE (1 << 0)
struct dyn_tick_timer {
unsigned int state; /* Current state */
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 019c45d75730..4da1d532cbeb 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -163,20 +163,6 @@ typedef unsigned long pgprot_t;
/* the upper-most page table pointer */
extern pmd_t *top_pmd;
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#include <asm/memory.h>
#endif /* !__ASSEMBLY__ */
@@ -186,4 +172,6 @@ static inline int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index 38ea5899a580..ead3ced38cb8 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -64,6 +64,19 @@ extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
{
}
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 478c49b56e18..366bafbdfbb1 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -445,12 +445,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define HAVE_ARCH_UNMAPPED_AREA
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h
index 46d20585d951..3c51da6438c9 100644
--- a/include/asm-arm/socket.h
+++ b/include/asm-arm/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 1f906d09b688..cb4906b45555 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -16,21 +16,14 @@
* Unlocked value: 0
* Locked value: 1
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while (0)
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) do { barrier(); } while (spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned long tmp;
@@ -47,7 +40,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
smp_mb();
}
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
unsigned long tmp;
@@ -67,7 +60,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
}
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
smp_mb();
@@ -80,23 +73,14 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
/*
* RWLOCKS
- */
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while (0)
-#define rwlock_is_locked(x) (*((volatile unsigned int *)(x)) != 0)
-
-/*
+ *
+ *
* Write locks are easy - we just set bit 31. When unlocking, we can
* just write zero since the lock is exclusively held.
*/
-static inline void _raw_write_lock(rwlock_t *rw)
+#define rwlock_is_locked(x) (*((volatile unsigned int *)(x)) != 0)
+
+static inline void __raw_write_lock(rwlock_t *rw)
{
unsigned long tmp;
@@ -113,7 +97,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
smp_mb();
}
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(rwlock_t *rw)
{
unsigned long tmp;
@@ -133,7 +117,7 @@ static inline int _raw_write_trylock(rwlock_t *rw)
}
}
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
smp_mb();
@@ -156,7 +140,7 @@ static inline void _raw_write_unlock(rwlock_t *rw)
* currently active. However, we know we won't have any write
* locks.
*/
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned long tmp, tmp2;
@@ -173,7 +157,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
smp_mb();
}
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(rwlock_t *rw)
{
unsigned long tmp, tmp2;
@@ -190,6 +174,6 @@ static inline void _raw_read_unlock(rwlock_t *rw)
: "cc");
}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-arm/spinlock_types.h b/include/asm-arm/spinlock_types.h
new file mode 100644
index 000000000000..43e83f6d2ee5
--- /dev/null
+++ b/include/asm-arm/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-arm/types.h b/include/asm-arm/types.h
index f4c92e4c8c02..22992ee0627a 100644
--- a/include/asm-arm/types.h
+++ b/include/asm-arm/types.h
@@ -52,8 +52,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index a7c018b8a0d4..a2fdad0138b3 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -77,12 +77,6 @@ static inline void set_fs (mm_segment_t fs)
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
/*
* Single-value transfer routines. They automatically use the right
* size if we just have the right pointer type. Note that the functions
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index abb36e54c966..c49df635a80f 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -295,7 +295,7 @@
#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267)
#define __NR_tgkill (__NR_SYSCALL_BASE+268)
#define __NR_utimes (__NR_SYSCALL_BASE+269)
-#define __NR_fadvise64_64 (__NR_SYSCALL_BASE+270)
+#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE+270)
#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271)
#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272)
#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273)
@@ -355,6 +355,9 @@
#define __NR_inotify_init (__NR_SYSCALL_BASE+316)
#define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317)
#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318)
+#define __NR_mbind (__NR_SYSCALL_BASE+319)
+#define __NR_get_mempolicy (__NR_SYSCALL_BASE+320)
+#define __NR_set_mempolicy (__NR_SYSCALL_BASE+321)
/*
* The following SWIs are ARM private.
@@ -515,7 +518,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
#define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE
diff --git a/include/asm-arm26/auxvec.h b/include/asm-arm26/auxvec.h
new file mode 100644
index 000000000000..c0536f6b29a7
--- /dev/null
+++ b/include/asm-arm26/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMARM_AUXVEC_H
+#define __ASMARM_AUXVEC_H
+
+#endif
diff --git a/include/asm-arm26/fcntl.h b/include/asm-arm26/fcntl.h
index 485b6bdf4d7a..d85995e7459e 100644
--- a/include/asm-arm26/fcntl.h
+++ b/include/asm-arm26/fcntl.h
@@ -3,85 +3,11 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
-#define O_NOATIME 01000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
+#include <asm-generic/fcntl.h>
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff --git a/include/asm-arm26/futex.h b/include/asm-arm26/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-arm26/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h
index 791ee1da9bfa..dc28daab8aa8 100644
--- a/include/asm-arm26/hardirq.h
+++ b/include/asm-arm26/hardirq.h
@@ -22,8 +22,6 @@ typedef struct {
# error HARDIRQ_BITS is too low!
#endif
-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-
#ifndef CONFIG_SMP
extern asmlinkage void __do_softirq(void);
diff --git a/include/asm-arm26/hdreg.h b/include/asm-arm26/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-arm26/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-arm26/page.h b/include/asm-arm26/page.h
index c334079b082b..d3f23ac4d468 100644
--- a/include/asm-arm26/page.h
+++ b/include/asm-arm26/page.h
@@ -89,20 +89,6 @@ typedef unsigned long pgprot_t;
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#include <asm/memory.h>
#endif /* !__ASSEMBLY__ */
@@ -112,4 +98,6 @@ static inline int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 4a0a00da425f..f602cf572411 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -294,12 +294,9 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
#include <asm-generic/pgtable.h>
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
diff --git a/include/asm-arm26/socket.h b/include/asm-arm26/socket.h
index 46d20585d951..3c51da6438c9 100644
--- a/include/asm-arm26/socket.h
+++ b/include/asm-arm26/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-arm26/types.h b/include/asm-arm26/types.h
index 56cbe573a234..81bd357ada02 100644
--- a/include/asm-arm26/types.h
+++ b/include/asm-arm26/types.h
@@ -52,8 +52,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-arm26/uaccess.h b/include/asm-arm26/uaccess.h
index ab9ce38c6aec..3f2dd1093e58 100644
--- a/include/asm-arm26/uaccess.h
+++ b/include/asm-arm26/uaccess.h
@@ -40,12 +40,6 @@ extern int fixup_exception(struct pt_regs *regs);
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
/*
* Single-value transfer routines. They automatically use the right
* size if we just have the right pointer type. Note that the functions
diff --git a/include/asm-cris/auxvec.h b/include/asm-cris/auxvec.h
new file mode 100644
index 000000000000..cb30b01bf19f
--- /dev/null
+++ b/include/asm-cris/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMCRIS_AUXVEC_H
+#define __ASMCRIS_AUXVEC_H
+
+#endif
diff --git a/include/asm-cris/fcntl.h b/include/asm-cris/fcntl.h
index 61c563242b51..46ab12db5739 100644
--- a/include/asm-cris/fcntl.h
+++ b/include/asm-cris/fcntl.h
@@ -1,90 +1 @@
-#ifndef _CRIS_FCNTL_H
-#define _CRIS_FCNTL_H
-
-/* verbatim copy of i386 version */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get f_flags */
-#define F_SETFD 2 /* set f_flags */
-#define F_GETFL 3 /* more flags (cloexec) */
-#define F_SETFL 4
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-cris/futex.h b/include/asm-cris/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-cris/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h
index 8e787fdaedd4..4fab5c3b2e15 100644
--- a/include/asm-cris/irq.h
+++ b/include/asm-cris/irq.h
@@ -1,6 +1,11 @@
#ifndef _ASM_IRQ_H
#define _ASM_IRQ_H
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
#include <asm/arch/irq.h>
extern __inline__ int irq_canonicalize(int irq)
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index bbf17bd39385..c99c478c482f 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -70,19 +70,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef __ASSEMBLY__
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
#endif /* __ASSEMBLY__ */
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
@@ -90,5 +77,7 @@ static inline int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _CRIS_PAGE_H */
diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h
index f159b4f165f7..8b1da3e58c55 100644
--- a/include/asm-cris/socket.h
+++ b/include/asm-cris/socket.h
@@ -16,6 +16,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-cris/types.h b/include/asm-cris/types.h
index 8fa6d6c7afce..84557c9bac93 100644
--- a/include/asm-cris/types.h
+++ b/include/asm-cris/types.h
@@ -52,8 +52,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
index 6db17221fd9e..7d50086eb5ea 100644
--- a/include/asm-cris/uaccess.h
+++ b/include/asm-cris/uaccess.h
@@ -91,13 +91,6 @@
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
#include <asm/arch/uaccess.h>
/*
diff --git a/include/asm-frv/auxvec.h b/include/asm-frv/auxvec.h
new file mode 100644
index 000000000000..07710778fa10
--- /dev/null
+++ b/include/asm-frv/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __FRV_AUXVEC_H
+#define __FRV_AUXVEC_H
+
+#endif
diff --git a/include/asm-frv/fcntl.h b/include/asm-frv/fcntl.h
index d61b999f9973..46ab12db5739 100644
--- a/include/asm-frv/fcntl.h
+++ b/include/asm-frv/fcntl.h
@@ -1,88 +1 @@
-#ifndef _ASM_FCNTL_H
-#define _ASM_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif /* _ASM_FCNTL_H */
-
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-frv/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index f7914f1782b0..4feba567e7fd 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -45,21 +45,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size) __attribute_const__;
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size - 1) >> (PAGE_SHIFT - 1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#define devmem_is_allowed(pfn) 1
#define __pa(vaddr) virt_to_phys((void *) vaddr)
@@ -102,4 +87,6 @@ extern unsigned long max_pfn;
#define WANT_PAGE_VIRTUAL 1
#endif
+#include <asm-generic/page.h>
+
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index d0a9c2f9c13e..473fb4bb6329 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -500,9 +500,6 @@ static inline int pte_file(pte_t pte)
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h
index c3be17c7de4b..7177f8b9817c 100644
--- a/include/asm-frv/socket.h
+++ b/include/asm-frv/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-frv/types.h b/include/asm-frv/types.h
index 1a5b6546bb41..50605df6d8ac 100644
--- a/include/asm-frv/types.h
+++ b/include/asm-frv/types.h
@@ -65,8 +65,6 @@ typedef u64 u_quad_t;
typedef u32 dma_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index 32dc52e883e5..991b50fbba24 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -67,12 +67,6 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
#define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
-/* this function will go away soon - use access_ok() / __range_ok() instead */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
- return __range_ok(addr, size);
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
new file mode 100644
index 000000000000..b663520dcdc4
--- /dev/null
+++ b/include/asm-generic/fcntl.h
@@ -0,0 +1,149 @@
+#ifndef _ASM_GENERIC_FCNTL_H
+#define _ASM_GENERIC_FCNTL_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+#define O_ACCMODE 00000003
+#define O_RDONLY 00000000
+#define O_WRONLY 00000001
+#define O_RDWR 00000002
+#ifndef O_CREAT
+#define O_CREAT 00000100 /* not fcntl */
+#endif
+#ifndef O_EXCL
+#define O_EXCL 00000200 /* not fcntl */
+#endif
+#ifndef O_NOCTTY
+#define O_NOCTTY 00000400 /* not fcntl */
+#endif
+#ifndef O_TRUNC
+#define O_TRUNC 00001000 /* not fcntl */
+#endif
+#ifndef O_APPEND
+#define O_APPEND 00002000
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 00004000
+#endif
+#ifndef O_SYNC
+#define O_SYNC 00010000
+#endif
+#ifndef FASYNC
+#define FASYNC 00020000 /* fcntl, for BSD compatibility */
+#endif
+#ifndef O_DIRECT
+#define O_DIRECT 00040000 /* direct disk access hint */
+#endif
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 00100000
+#endif
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 00200000 /* must be a directory */
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 00400000 /* don't follow links */
+#endif
+#ifndef O_NOATIME
+#define O_NOATIME 01000000
+#endif
+#ifndef O_NDELAY
+#define O_NDELAY O_NONBLOCK
+#endif
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#ifndef F_GETLK
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+#endif
+#ifndef F_SETOWN
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+#endif
+#ifndef F_SETSIG
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+#endif
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#ifndef F_RDLCK
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+#endif
+
+/* for old implementation of bsd flock () */
+#ifndef F_EXLCK
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+#endif
+
+/* for leases */
+#ifndef F_INPROGRESS
+#define F_INPROGRESS 16
+#endif
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock ... */
+#define LOCK_READ 64 /* which allows concurrent read operations */
+#define LOCK_WRITE 128 /* which allows concurrent write operations */
+#define LOCK_RW 192 /* which allows concurrent read & write ops */
+
+#define F_LINUX_SPECIFIC_BASE 1024
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK
+#ifndef __ARCH_FLOCK_PAD
+#define __ARCH_FLOCK_PAD
+#endif
+
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+ __ARCH_FLOCK_PAD
+};
+#endif
+
+#ifndef CONFIG_64BIT
+
+#ifndef F_GETLK64
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+#endif
+
+#ifndef HAVE_ARCH_STRUCT_FLOCK64
+#ifndef __ARCH_FLOCK64_PAD
+#define __ARCH_FLOCK64_PAD
+#endif
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+ __ARCH_FLOCK64_PAD
+};
+#endif
+#endif /* !CONFIG_64BIT */
+
+#endif /* _ASM_GENERIC_FCNTL_H */
diff --git a/include/asm-generic/hdreg.h b/include/asm-generic/hdreg.h
deleted file mode 100644
index 7051fba8bcf9..000000000000
--- a/include/asm-generic/hdreg.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#warning <asm/hdreg.h> is obsolete, please do not use it
-
-#ifndef __ASM_GENERIC_HDREG_H
-#define __ASM_GENERIC_HDREG_H
-
-typedef unsigned long ide_ioreg_t;
-
-#endif /* __ASM_GENERIC_HDREG_H */
diff --git a/include/asm-generic/page.h b/include/asm-generic/page.h
new file mode 100644
index 000000000000..a96b5d986b6e
--- /dev/null
+++ b/include/asm-generic/page.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_GENERIC_PAGE_H
+#define _ASM_GENERIC_PAGE_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+
+/* Pure 2^n version of get_order */
+static __inline__ __attribute_const__ int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size - 1) >> (PAGE_SHIFT - 1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_GENERIC_PAGE_H */
diff --git a/include/asm-generic/pci.h b/include/asm-generic/pci.h
index ee1d8b5d8168..c36a77d3bf44 100644
--- a/include/asm-generic/pci.h
+++ b/include/asm-generic/pci.h
@@ -30,6 +30,19 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
res->end = region->end;
}
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
#define pcibios_scan_all_fns(a, b) 0
#ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index f40593565173..f86c1e549466 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -101,6 +101,22 @@ do { \
})
#endif
+#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+#define ptep_get_and_clear_full(__mm, __address, __ptep, __full) \
+({ \
+ pte_t __pte; \
+ __pte = ptep_get_and_clear((__mm), (__address), (__ptep)); \
+ __pte; \
+})
+#endif
+
+#ifndef __HAVE_ARCH_PTE_CLEAR_FULL
+#define pte_clear_full(__mm, __address, __ptep, __full) \
+do { \
+ pte_clear((__mm), (__address), (__ptep)); \
+} while (0)
+#endif
+
#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define ptep_clear_flush(__vma, __address, __ptep) \
({ \
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 450eae22c39a..886dbd116899 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -12,5 +12,6 @@ extern char _sextratext[] __attribute__((weak));
extern char _eextratext[] __attribute__((weak));
extern char _end[];
extern char __per_cpu_start[], __per_cpu_end[];
+extern char __kprobes_text_start[], __kprobes_text_end[];
#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index faff403e1061..7d0298347ee7 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -23,7 +23,11 @@
* and page free order so much..
*/
#ifdef CONFIG_SMP
- #define FREE_PTE_NR 506
+ #ifdef ARCH_FREE_PTR_NR
+ #define FREE_PTR_NR ARCH_FREE_PTR_NR
+ #else
+ #define FREE_PTE_NR 506
+ #endif
#define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
#else
#define FREE_PTE_NR 1
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 6c90f0f36eec..4dc8ddb401c1 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -16,9 +16,9 @@
* The main single-value unaligned transfer routines.
*/
#define get_unaligned(ptr) \
- ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
+ __get_unaligned((ptr), sizeof(*(ptr)))
#define put_unaligned(x,ptr) \
- __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+ __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
/*
* This function doesn't actually exist. The idea is that when
@@ -36,19 +36,19 @@ struct __una_u16 { __u16 x __attribute__((packed)); };
* Elemental unaligned loads
*/
-static inline unsigned long __uldq(const __u64 *addr)
+static inline __u64 __uldq(const __u64 *addr)
{
const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
return ptr->x;
}
-static inline unsigned long __uldl(const __u32 *addr)
+static inline __u32 __uldl(const __u32 *addr)
{
const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
return ptr->x;
}
-static inline unsigned long __uldw(const __u16 *addr)
+static inline __u16 __uldw(const __u16 *addr)
{
const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
return ptr->x;
@@ -78,7 +78,7 @@ static inline void __ustw(__u16 val, __u16 *addr)
#define __get_unaligned(ptr, size) ({ \
const void *__gu_p = ptr; \
- unsigned long val; \
+ __typeof__(*(ptr)) val; \
switch (size) { \
case 1: \
val = *(const __u8 *)__gu_p; \
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index b3bb326ae5b6..a9c55490fb82 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -6,6 +6,9 @@
#define VMLINUX_SYMBOL(_sym_) _sym_
#endif
+/* Align . to a 8 byte boundary equals to maximum function alignment. */
+#define ALIGN_FUNCTION() . = ALIGN(8)
+
#define RODATA \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
*(.rodata) *(.rodata.*) \
@@ -79,12 +82,62 @@
VMLINUX_SYMBOL(__security_initcall_end) = .; \
}
+/* sched.text is aling to function alignment to secure we have same
+ * address even at second ld pass when generating System.map */
#define SCHED_TEXT \
+ ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__sched_text_start) = .; \
*(.sched.text) \
VMLINUX_SYMBOL(__sched_text_end) = .;
+/* spinlock.text is aling to function alignment to secure we have same
+ * address even at second ld pass when generating System.map */
#define LOCK_TEXT \
+ ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__lock_text_start) = .; \
*(.spinlock.text) \
VMLINUX_SYMBOL(__lock_text_end) = .;
+
+#define KPROBES_TEXT \
+ ALIGN_FUNCTION(); \
+ VMLINUX_SYMBOL(__kprobes_text_start) = .; \
+ *(.kprobes.text) \
+ VMLINUX_SYMBOL(__kprobes_text_end) = .;
+
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to
+ the beginning of the section so we begin them at 0. */
+#define DWARF_DEBUG \
+ /* DWARF 1 */ \
+ .debug 0 : { *(.debug) } \
+ .line 0 : { *(.line) } \
+ /* GNU DWARF 1 extensions */ \
+ .debug_srcinfo 0 : { *(.debug_srcinfo) } \
+ .debug_sfnames 0 : { *(.debug_sfnames) } \
+ /* DWARF 1.1 and DWARF 2 */ \
+ .debug_aranges 0 : { *(.debug_aranges) } \
+ .debug_pubnames 0 : { *(.debug_pubnames) } \
+ /* DWARF 2 */ \
+ .debug_info 0 : { *(.debug_info \
+ .gnu.linkonce.wi.*) } \
+ .debug_abbrev 0 : { *(.debug_abbrev) } \
+ .debug_line 0 : { *(.debug_line) } \
+ .debug_frame 0 : { *(.debug_frame) } \
+ .debug_str 0 : { *(.debug_str) } \
+ .debug_loc 0 : { *(.debug_loc) } \
+ .debug_macinfo 0 : { *(.debug_macinfo) } \
+ /* SGI/MIPS DWARF 2 extensions */ \
+ .debug_weaknames 0 : { *(.debug_weaknames) } \
+ .debug_funcnames 0 : { *(.debug_funcnames) } \
+ .debug_typenames 0 : { *(.debug_typenames) } \
+ .debug_varnames 0 : { *(.debug_varnames) } \
+
+ /* Stabs debugging sections. */
+#define STABS_DEBUG \
+ .stab 0 : { *(.stab) } \
+ .stabstr 0 : { *(.stabstr) } \
+ .stab.excl 0 : { *(.stab.excl) } \
+ .stab.exclstr 0 : { *(.stab.exclstr) } \
+ .stab.index 0 : { *(.stab.index) } \
+ .stab.indexstr 0 : { *(.stab.indexstr) } \
+ .comment 0 : { *(.comment) }
diff --git a/include/asm-h8300/auxvec.h b/include/asm-h8300/auxvec.h
new file mode 100644
index 000000000000..1d36fe38b088
--- /dev/null
+++ b/include/asm-h8300/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMH8300_AUXVEC_H
+#define __ASMH8300_AUXVEC_H
+
+#endif
diff --git a/include/asm-h8300/fcntl.h b/include/asm-h8300/fcntl.h
index 355350a57bf9..1952cb2e3b06 100644
--- a/include/asm-h8300/fcntl.h
+++ b/include/asm-h8300/fcntl.h
@@ -1,87 +1,11 @@
#ifndef _H8300_FCNTL_H
#define _H8300_FCNTL_H
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
-#define O_NOATIME 01000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
+#include <asm-generic/fcntl.h>
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
#endif /* _H8300_FCNTL_H */
diff --git a/include/asm-h8300/futex.h b/include/asm-h8300/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-h8300/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-h8300/hdreg.h b/include/asm-h8300/hdreg.h
deleted file mode 100644
index 36d0c06687d8..000000000000
--- a/include/asm-h8300/hdreg.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * linux/include/asm-h8300/hdreg.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-#warning this file is obsolete, please do not use it
-
-#ifndef _H8300_HDREG_H
-#define _H8300_HDREG_H
-
-typedef unsigned int q40ide_ioreg_t;
-typedef unsigned char * ide_ioreg_t;
-
-#endif /* _H8300_HDREG_H */
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index e3b7960d445b..e8c02b8c2d99 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -54,20 +54,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
extern unsigned long memory_start;
extern unsigned long memory_end;
@@ -101,4 +87,6 @@ extern unsigned long memory_end;
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _H8300_PAGE_H */
diff --git a/include/asm-h8300/pgtable.h b/include/asm-h8300/pgtable.h
index 69076eb31476..f6e296fc1297 100644
--- a/include/asm-h8300/pgtable.h
+++ b/include/asm-h8300/pgtable.h
@@ -52,8 +52,6 @@ extern int is_in_rom(unsigned long);
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h
index af33b8525dcf..d98cf85bafc1 100644
--- a/include/asm-h8300/socket.h
+++ b/include/asm-h8300/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-h8300/types.h b/include/asm-h8300/types.h
index 21f4fc07ac0e..bf91e0d4dde7 100644
--- a/include/asm-h8300/types.h
+++ b/include/asm-h8300/types.h
@@ -58,8 +58,6 @@ typedef u32 dma_addr_t;
#define HAVE_SECTOR_T
typedef u64 sector_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h
index 1480f307a474..ebe58c6c8387 100644
--- a/include/asm-h8300/uaccess.h
+++ b/include/asm-h8300/uaccess.h
@@ -24,12 +24,6 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend));
}
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
-{
- return access_ok(type,addr,size)?0:-EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index cf828ace13f9..df4ed323aa4d 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -103,7 +103,7 @@ __acpi_release_global_lock (unsigned int *lock)
:"=r"(n_hi), "=r"(n_lo) \
:"0"(n_hi), "1"(n_lo))
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern int acpi_lapic;
extern int acpi_ioapic;
extern int acpi_noirq;
@@ -146,13 +146,6 @@ static inline void check_acpi_pci(void) { }
#endif
-#else /* CONFIG_ACPI_BOOT */
-# define acpi_lapic 0
-# define acpi_ioapic 0
-
-#endif
-
-#ifdef CONFIG_ACPI_PCI
static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
static inline void acpi_disable_pci(void)
{
@@ -160,11 +153,16 @@ static inline void acpi_disable_pci(void)
acpi_noirq_set();
}
extern int acpi_irq_balance_set(char *str);
-#else
+
+#else /* !CONFIG_ACPI */
+
+#define acpi_lapic 0
+#define acpi_ioapic 0
static inline void acpi_noirq_set(void) { }
static inline void acpi_disable_pci(void) { }
-static inline int acpi_irq_balance_set(char *str) { return 0; }
-#endif
+
+#endif /* !CONFIG_ACPI */
+
#ifdef CONFIG_ACPI_SLEEP
diff --git a/include/asm-i386/agp.h b/include/asm-i386/agp.h
index b82f5f3ab887..9075083bab76 100644
--- a/include/asm-i386/agp.h
+++ b/include/asm-i386/agp.h
@@ -19,7 +19,7 @@ int unmap_page_from_agp(struct page *page);
/* Could use CLFLUSH here if the cpu supports it. But then it would
need to be called for each cacheline of the whole page so it may not be
worth it. Would need a page for it. */
-#define flush_agp_cache() asm volatile("wbinvd":::"memory")
+#define flush_agp_cache() wbinvd()
/* Convert a physical address to an address suitable for the GART. */
#define phys_to_gart(x) (x)
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 6a1b1882285c..8c454aa58ac6 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -130,6 +130,8 @@ extern unsigned int nmi_watchdog;
#define NMI_LOCAL_APIC 2
#define NMI_INVALID 3
+extern int disable_timer_pin_1;
+
#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 a96a8f48fbfc..03185cef8e0a 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -16,6 +16,7 @@
#define GET_APIC_VERSION(x) ((x)&0xFF)
#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFF)
#define APIC_INTEGRATED(x) ((x)&0xF0)
+#define APIC_XAPIC(x) ((x) >= 0x14)
#define APIC_TASKPRI 0x80
#define APIC_TPRI_MASK 0xFF
#define APIC_ARBPRI 0x90
diff --git a/include/asm-i386/auxvec.h b/include/asm-i386/auxvec.h
new file mode 100644
index 000000000000..395e13016bfb
--- /dev/null
+++ b/include/asm-i386/auxvec.h
@@ -0,0 +1,11 @@
+#ifndef __ASMi386_AUXVEC_H
+#define __ASMi386_AUXVEC_H
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+#endif
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
index 6789fc275da3..ea54540638d2 100644
--- a/include/asm-i386/bugs.h
+++ b/include/asm-i386/bugs.h
@@ -118,7 +118,10 @@ static void __init check_hlt(void)
printk("disabled\n");
return;
}
- __asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
+ halt();
+ halt();
+ halt();
+ halt();
printk("OK.\n");
}
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index f949e44c2a35..67d3630c4e89 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -83,7 +83,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
"adcl $0, %0 ;\n"
"notl %0 ;\n"
"2: ;\n"
- /* Since the input registers which are loaded with iph and ipl
+ /* Since the input registers which are loaded with iph and ihl
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl)
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 11e67811a990..6df1a53c190e 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -27,8 +27,18 @@ struct Xgt_desc_struct {
extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
-#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
-#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
+#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
+#define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
+
+#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
+
+#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
+#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
+#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
+#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
/*
* This is the ldt that every process will get unless we need
@@ -39,14 +49,14 @@ extern void set_intr_gate(unsigned int irq, void * addr);
#define _set_tssldt_desc(n,addr,limit,type) \
__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
- "movw %%ax,2(%2)\n\t" \
- "rorl $16,%%eax\n\t" \
- "movb %%al,4(%2)\n\t" \
+ "movw %w1,2(%2)\n\t" \
+ "rorl $16,%1\n\t" \
+ "movb %b1,4(%2)\n\t" \
"movb %4,5(%2)\n\t" \
"movb $0,6(%2)\n\t" \
- "movb %%ah,7(%2)\n\t" \
- "rorl $16,%%eax" \
- : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
+ "movb %h1,7(%2)\n\t" \
+ "rorl $16,%1" \
+ : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
{
@@ -86,6 +96,13 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
(info)->seg_not_present == 1 && \
(info)->useable == 0 )
+static inline void write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
+{
+ __u32 *lp = (__u32 *)((char *)ldt + entry*8);
+ *lp = entry_a;
+ *(lp+1) = entry_b;
+}
+
#if TLS_SIZE != 24
# error update this code.
#endif
diff --git a/include/asm-i386/div64.h b/include/asm-i386/div64.h
index 28ed8b296afc..75c67c785bb8 100644
--- a/include/asm-i386/div64.h
+++ b/include/asm-i386/div64.h
@@ -35,7 +35,7 @@
*/
#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
-extern inline long
+static inline long
div_ll_X_l_rem(long long divs, long div, long *rem)
{
long dum2;
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index 130bdc8c68cf..fa11117d3cfa 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -9,6 +9,7 @@
#include <asm/user.h>
#include <asm/processor.h>
#include <asm/system.h> /* for savesegment */
+#include <asm/auxvec.h>
#include <linux/utsname.h>
@@ -109,13 +110,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
#define ELF_PLATFORM (system_utsname.machine)
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) do { } while (0)
diff --git a/include/asm-i386/fcntl.h b/include/asm-i386/fcntl.h
index 511cde94a3ed..46ab12db5739 100644
--- a/include/asm-i386/fcntl.h
+++ b/include/asm-i386/fcntl.h
@@ -1,88 +1 @@
-#ifndef _I386_FCNTL_H
-#define _I386_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index c94cac958389..cfb1c61d3b9c 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -76,7 +76,7 @@ enum fixed_addresses {
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
FIX_ACPI_BEGIN,
FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
#endif
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
new file mode 100644
index 000000000000..44b9db806474
--- /dev/null
+++ b/include/asm-i386/futex.h
@@ -0,0 +1,108 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile ( \
+"1: " insn "\n" \
+"2: .section .fixup,\"ax\"\n\
+3: mov %3, %1\n\
+ jmp 2b\n\
+ .previous\n\
+ .section __ex_table,\"a\"\n\
+ .align 8\n\
+ .long 1b,3b\n\
+ .previous" \
+ : "=r" (oldval), "=r" (ret), "=m" (*uaddr) \
+ : "i" (-EFAULT), "m" (*uaddr), "0" (oparg), "1" (0))
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile ( \
+"1: movl %2, %0\n\
+ movl %0, %3\n" \
+ insn "\n" \
+"2: " LOCK_PREFIX "cmpxchgl %3, %2\n\
+ jnz 1b\n\
+3: .section .fixup,\"ax\"\n\
+4: mov %5, %1\n\
+ jmp 3b\n\
+ .previous\n\
+ .section __ex_table,\"a\"\n\
+ .align 8\n\
+ .long 1b,4b,2b,4b\n\
+ .previous" \
+ : "=&a" (oldval), "=&r" (ret), "=m" (*uaddr), \
+ "=&r" (tem) \
+ : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0))
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ inc_preempt_count();
+
+ if (op == FUTEX_OP_SET)
+ __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
+ else {
+#ifndef CONFIG_X86_BSWAP
+ if (boot_cpu_data.x86 == 3)
+ ret = -ENOSYS;
+ else
+#endif
+ switch (op) {
+ case FUTEX_OP_ADD:
+ __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
+ oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op2("orl %4, %3", ret, oldval, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op2("andl %4, %3", ret, oldval, uaddr,
+ ~oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op2("xorl %4, %3", ret, oldval, 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-i386/hdreg.h b/include/asm-i386/hdreg.h
deleted file mode 100644
index 5989bbc97cbf..000000000000
--- a/include/asm-i386/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
index 002c203ccd6a..51c4e5fe6062 100644
--- a/include/asm-i386/io_apic.h
+++ b/include/asm-i386/io_apic.h
@@ -195,12 +195,12 @@ extern int skip_ioapic_setup;
*/
#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
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);
-#endif /*CONFIG_ACPI_BOOT*/
+#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 b3f8d5f59d5d..316138e89910 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -41,9 +41,16 @@ enum die_val {
DIE_PAGE_FAULT,
};
-static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+static inline int notify_die(enum die_val val, const char *str,
+ struct pt_regs *regs, long err, int trap, int sig)
{
- struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+ struct die_args args = {
+ .regs = regs,
+ .str = str,
+ .err = err,
+ .trapnr = trap,
+ .signr = sig
+ };
return notifier_call_chain(&i386die_chain, val, &args);
}
diff --git a/include/asm-i386/mach-default/mach_reboot.h b/include/asm-i386/mach-default/mach_reboot.h
index 521e227db679..06ae4d81ba6a 100644
--- a/include/asm-i386/mach-default/mach_reboot.h
+++ b/include/asm-i386/mach-default/mach_reboot.h
@@ -22,7 +22,15 @@ static inline void mach_reboot(void)
for (i = 0; i < 100; i++) {
kb_wait();
udelay(50);
- outb(0xfe, 0x64); /* pulse reset low */
+ outb(0x60, 0x64); /* write Controller Command Byte */
+ udelay(50);
+ kb_wait();
+ udelay(50);
+ outb(0x14, 0x60); /* set "System flag" */
+ udelay(50);
+ kb_wait();
+ udelay(50);
+ outb(0xfe, 0x64); /* pulse reset low */
udelay(50);
}
}
diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
index 85809e0898d7..28a84f6185a7 100644
--- a/include/asm-i386/mach-es7000/mach_mpparse.h
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h
@@ -1,6 +1,8 @@
#ifndef __ASM_MACH_MPPARSE_H
#define __ASM_MACH_MPPARSE_H
+#include <linux/acpi.h>
+
static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
struct mpc_config_translation *translation)
{
@@ -12,8 +14,9 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
{
}
-extern int parse_unisys_oem (char *oemptr, int oem_entries);
-extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
+extern int parse_unisys_oem (char *oemptr);
+extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+extern void setup_unisys();
static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
char *productid)
@@ -22,18 +25,33 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
struct mp_config_oemtable *oem_table =
(struct mp_config_oemtable *)mpc->mpc_oemptr;
if (!strncmp(oem, "UNISYS", 6))
- return parse_unisys_oem((char *)oem_table, oem_table->oem_length);
+ return parse_unisys_oem((char *)oem_table);
}
return 0;
}
+static inline int es7000_check_dsdt()
+{
+ struct acpi_table_header *header = NULL;
+ if(!acpi_get_table_header_early(ACPI_DSDT, &header))
+ acpi_table_print(header, 0);
+ if (!strncmp(header->oem_id, "UNISYS", 6))
+ return 1;
+ return 0;
+}
+
/* Hook from generic ACPI tables.c */
static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
unsigned long oem_addr;
- int oem_entries;
- if (!find_unisys_acpi_oem_table(&oem_addr, &oem_entries))
- return parse_unisys_oem((char *)oem_addr, oem_entries);
+ if (!find_unisys_acpi_oem_table(&oem_addr)) {
+ if (es7000_check_dsdt())
+ return parse_unisys_oem((char *)oem_addr);
+ else {
+ setup_unisys();
+ return 1;
+ }
+ }
return 0;
}
diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
index b13767a4e934..d9dc039da94a 100644
--- a/include/asm-i386/mach-generic/mach_apic.h
+++ b/include/asm-i386/mach-generic/mach_apic.h
@@ -28,4 +28,6 @@
#define enable_apic_mode (genapic->enable_apic_mode)
#define phys_pkg_id (genapic->phys_pkg_id)
+extern void generic_bigsmp_probe(void);
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 516421300ea2..348fe3a4879d 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -29,7 +29,7 @@ static inline void get_memcfg_numa(void)
#ifdef CONFIG_X86_NUMAQ
if (get_memcfg_numaq())
return;
-#elif CONFIG_ACPI_SRAT
+#elif defined(CONFIG_ACPI_SRAT)
if (get_memcfg_from_srat())
return;
#endif
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index d9fafba075bc..64a0b8e6afeb 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -11,6 +11,7 @@ extern int mp_bus_id_to_local [MAX_MP_BUSSES];
extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
+extern unsigned int def_to_bigsmp;
extern unsigned int boot_cpu_physical_apicid;
extern int smp_found_config;
extern void find_smp_config (void);
@@ -26,14 +27,14 @@ extern unsigned long mp_lapic_addr;
extern int pic_mode;
extern int using_apic_timer;
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern void mp_register_lapic (u8 id, u8 enabled);
extern void mp_register_lapic_address (u64 address);
extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
extern void mp_config_acpi_legacy_irqs (void);
extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
-#endif /*CONFIG_ACPI_BOOT*/
+#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index c76fce8badbb..62b76cd96957 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -47,6 +47,21 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
: "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
ret__; })
+/* rdmsr with exception handling */
+#define rdmsr_safe(msr,a,b) ({ int ret__; \
+ asm volatile("2: rdmsr ; xorl %0,%0\n" \
+ "1:\n\t" \
+ ".section .fixup,\"ax\"\n\t" \
+ "3: movl %4,%0 ; jmp 1b\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n\t" \
+ " .long 2b,3b\n\t" \
+ ".previous" \
+ : "=r" (ret__), "=a" (*(a)), "=d" (*(b)) \
+ : "c" (msr), "i" (-EFAULT));\
+ ret__; })
+
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
diff --git a/include/asm-i386/numa.h b/include/asm-i386/numa.h
new file mode 100644
index 000000000000..96fcb157db1d
--- /dev/null
+++ b/include/asm-i386/numa.h
@@ -0,0 +1,3 @@
+
+int pxm_to_nid(int pxm);
+
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 8d93f732d72d..73296d9924fb 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -68,7 +68,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
#endif
#define pgd_val(x) ((x).pgd)
@@ -104,20 +103,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
*/
extern unsigned int __VMALLOC_RESERVE;
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
extern int sysctl_legacy_va_layout;
extern int page_is_ram(unsigned long pagenr);
@@ -156,4 +141,6 @@ extern int page_is_ram(unsigned long pagenr);
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index d609f9c2c1f0..2e3f4a344a2d 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -64,7 +64,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define set_pmd(pmdptr,pmdval) \
set_64bit((unsigned long long *)(pmdptr),pmd_val(pmdval))
#define set_pud(pudptr,pudval) \
- set_64bit((unsigned long long *)(pudptr),pud_val(pudval))
+ (*(pudptr) = (pudval))
/*
* Pentium-II erratum A13: in PAE mode we explicitly have to flush
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 77c6497f416e..d101ac414f07 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -86,9 +86,7 @@ void paging_init(void);
#endif
/*
- * The 4MB page is guessing.. Detailed in the infamous "Chapter H"
- * of the Pentium details, but assuming intel did the straightforward
- * thing, this bit set in the page directory entry just means that
+ * _PAGE_PSE set in the page directory entry just means that
* the page directory entry points directly to a 4MB-aligned block of
* memory.
*/
@@ -119,8 +117,10 @@ void paging_init(void);
#define _PAGE_UNUSED2 0x400
#define _PAGE_UNUSED3 0x800
-#define _PAGE_FILE 0x040 /* set:pagecache unset:swap */
-#define _PAGE_PROTNONE 0x080 /* If not present */
+/* If _PAGE_PRESENT is clear, we use these: */
+#define _PAGE_FILE 0x040 /* nonlinear file mapping, saved PTE; unset:swap */
+#define _PAGE_PROTNONE 0x080 /* if the user mapped it with PROT_NONE;
+ pte_present gives true */
#ifdef CONFIG_X86_PAE
#define _PAGE_NX (1ULL<<_PAGE_BIT_NX)
#else
@@ -215,11 +215,13 @@ extern unsigned long pg0[];
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
+#define __LARGE_PTE (_PAGE_PSE | _PAGE_PRESENT)
static inline int pte_user(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; }
+static inline int pte_huge(pte_t pte) { return ((pte).pte_low & __LARGE_PTE) == __LARGE_PTE; }
/*
* The following only works if pte_present() is not true.
@@ -236,7 +238,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
-static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PRESENT | _PAGE_PSE; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= __LARGE_PTE; return pte; }
#ifdef CONFIG_X86_PAE
# include <asm/pgtable-3level.h>
@@ -258,12 +260,39 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
}
+static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
+{
+ pte_t pte;
+ if (full) {
+ pte = *ptep;
+ *ptep = __pte(0);
+ } else {
+ pte = ptep_get_and_clear(mm, addr, ptep);
+ }
+ return pte;
+}
+
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
}
/*
+ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+ *
+ * dst - pointer to pgd range anwhere on a pgd page
+ * src - ""
+ * count - the number of pgds to copy.
+ *
+ * dst and src can be on the same page, but the range must not overlap,
+ * and must not cross a page boundary.
+ */
+static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+{
+ memcpy(dst, src, count * sizeof(pgd_t));
+}
+
+/*
* Macro to mark a page protection value as "uncacheable". On processors which do not support
* it, this is a no-op.
*/
@@ -402,9 +431,6 @@ extern void noexec_setup(const char *str);
#define kern_addr_valid(addr) (1)
#endif /* CONFIG_FLATMEM */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
@@ -415,6 +441,7 @@ extern void noexec_setup(const char *str);
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index d0d8b0160090..0a4ec764377c 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -203,9 +203,7 @@ static inline unsigned int cpuid_edx(unsigned int op)
return edx;
}
-#define load_cr3(pgdir) \
- asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)))
-
+#define load_cr3(pgdir) write_cr3(__pa(pgdir))
/*
* Intel CPU features in CR4
@@ -232,22 +230,20 @@ extern unsigned long mmu_cr4_features;
static inline void set_in_cr4 (unsigned long mask)
{
+ unsigned cr4;
mmu_cr4_features |= mask;
- __asm__("movl %%cr4,%%eax\n\t"
- "orl %0,%%eax\n\t"
- "movl %%eax,%%cr4\n"
- : : "irg" (mask)
- :"ax");
+ cr4 = read_cr4();
+ cr4 |= mask;
+ write_cr4(cr4);
}
static inline void clear_in_cr4 (unsigned long mask)
{
+ unsigned cr4;
mmu_cr4_features &= ~mask;
- __asm__("movl %%cr4,%%eax\n\t"
- "andl %0,%%eax\n\t"
- "movl %%eax,%%cr4\n"
- : : "irg" (~mask)
- :"ax");
+ cr4 = read_cr4();
+ cr4 &= ~mask;
+ write_cr4(cr4);
}
/*
@@ -281,6 +277,11 @@ static inline void clear_in_cr4 (unsigned long mask)
outb((data), 0x23); \
} while (0)
+static inline void serialize_cpu(void)
+{
+ __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+}
+
static inline void __monitor(const void *eax, unsigned long ecx,
unsigned long edx)
{
@@ -454,6 +455,7 @@ struct thread_struct {
unsigned int saved_fs, saved_gs;
/* IO permissions */
unsigned long *io_bitmap_ptr;
+ unsigned long iopl;
/* max allowed port in the bitmap, in bytes: */
unsigned long io_bitmap_max;
};
@@ -474,7 +476,6 @@ struct thread_struct {
.esp0 = sizeof(init_stack) + (long)&init_stack, \
.ss0 = __KERNEL_DS, \
.ss1 = __KERNEL_CS, \
- .ldt = GDT_ENTRY_LDT, \
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
}
@@ -511,6 +512,21 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa
: /* no output */ \
:"r" (value))
+/*
+ * Set IOPL bits in EFLAGS from given mask
+ */
+static inline void set_iopl_mask(unsigned mask)
+{
+ unsigned int reg;
+ __asm__ __volatile__ ("pushfl;"
+ "popl %0;"
+ "andl %1, %0;"
+ "orl %2, %0;"
+ "pushl %0;"
+ "popfl"
+ : "=&r" (reg)
+ : "i" (~X86_EFLAGS_IOPL), "r" (mask));
+}
/* Forward declaration, a strange C thing */
struct task_struct;
@@ -663,7 +679,7 @@ static inline void rep_nop(void)
However we don't do prefetches for pre XP Athlons currently
That should be fixed. */
#define ARCH_HAS_PREFETCH
-extern inline void prefetch(const void *x)
+static inline void prefetch(const void *x)
{
alternative_input(ASM_NOP4,
"prefetchnta (%1)",
@@ -677,7 +693,7 @@ extern inline void prefetch(const void *x)
/* 3dnow! prefetch to get an exclusive cache line. Useful for
spinlocks to avoid one state transition in the cache coherency protocol. */
-extern inline void prefetchw(const void *x)
+static inline void prefetchw(const void *x)
{
alternative_input(ASM_NOP4,
"prefetchw (%1)",
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index 05532875e39e..7e0f2945d17d 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -61,6 +61,13 @@ struct pt_regs {
struct task_struct;
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
+/*
+ * user_mode_vm(regs) determines whether a register set came from user mode.
+ * This is true if V8086 mode was enabled OR if the register set was from
+ * protected mode with RPL-3 CS value. This tricky test checks that with
+ * one comparison. Many places in the kernel can bypass this full check
+ * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
+ */
static inline int user_mode(struct pt_regs *regs)
{
return (regs->xcs & 3) != 0;
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 7a32184d54bf..826a8ca50ac8 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -44,7 +44,7 @@ extern unsigned char boot_params[PARAM_SIZE];
#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
-#define EFI_MEMMAP ((efi_memory_desc_t *) *((unsigned long *)(PARAM+0x1d0)))
+#define EFI_MEMMAP ((void *) *((unsigned long *)(PARAM+0x1d0)))
#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index a283738b80b3..13250199976d 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -59,7 +59,7 @@ extern void cpu_uninit(void);
extern cpumask_t cpu_callout_map;
extern cpumask_t cpu_callin_map;
-#define cpu_possible_map cpu_callout_map
+extern cpumask_t cpu_possible_map;
/* We don't mark CPUs online until __cpu_up(), so we need another measure */
static inline int num_booting_cpus(void)
diff --git a/include/asm-i386/socket.h b/include/asm-i386/socket.h
index 07f6b38ad140..802ae76195b7 100644
--- a/include/asm-i386/socket.h
+++ b/include/asm-i386/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index f9ff31f40036..23604350cdf4 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -7,46 +7,21 @@
#include <linux/config.h>
#include <linux/compiler.h>
-asmlinkage int printk(const char * fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile unsigned int slock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
*/
-#define spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
-#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+#define __raw_spin_is_locked(x) \
+ (*(volatile signed char *)(&(x)->slock) <= 0)
-#define spin_lock_string \
+#define __raw_spin_lock_string \
"\n1:\t" \
"lock ; decb %0\n\t" \
"jns 3f\n" \
@@ -57,7 +32,7 @@ typedef struct {
"jmp 1b\n" \
"3:\n\t"
-#define spin_lock_string_flags \
+#define __raw_spin_lock_string_flags \
"\n1:\t" \
"lock ; decb %0\n\t" \
"jns 4f\n\t" \
@@ -73,86 +48,71 @@ typedef struct {
"jmp 1b\n" \
"4:\n\t"
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+ __asm__ __volatile__(
+ __raw_spin_lock_string
+ :"=m" (lock->slock) : : "memory");
+}
+
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+ __asm__ __volatile__(
+ __raw_spin_lock_string_flags
+ :"=m" (lock->slock) : "r" (flags) : "memory");
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+ char oldval;
+ __asm__ __volatile__(
+ "xchgb %b0,%1"
+ :"=q" (oldval), "=m" (lock->slock)
+ :"0" (0) : "memory");
+ return oldval > 0;
+}
+
/*
- * This works. Despite all the confusion.
- * (except on PPro SMP or if we are using OOSTORE)
+ * __raw_spin_unlock based on writing $1 to the low byte.
+ * This method works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE, so we use xchgb there)
* (PPro errata 66, 92)
*/
#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
"movb $1,%0" \
:"=m" (lock->slock) : : "memory"
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(lock->magic != SPINLOCK_MAGIC);
- BUG_ON(!spin_is_locked(lock));
-#endif
__asm__ __volatile__(
- spin_unlock_string
+ __raw_spin_unlock_string
);
}
#else
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
"xchgb %b0, %1" \
:"=q" (oldval), "=m" (lock->slock) \
:"0" (oldval) : "memory"
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
char oldval = 1;
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(lock->magic != SPINLOCK_MAGIC);
- BUG_ON(!spin_is_locked(lock));
-#endif
- __asm__ __volatile__(
- spin_unlock_string
- );
-}
-#endif
-
-static inline int _raw_spin_trylock(spinlock_t *lock)
-{
- char oldval;
__asm__ __volatile__(
- "xchgb %b0,%1"
- :"=q" (oldval), "=m" (lock->slock)
- :"0" (0) : "memory");
- return oldval > 0;
+ __raw_spin_unlock_string
+ );
}
-static inline void _raw_spin_lock(spinlock_t *lock)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
- printk("eip: %p\n", __builtin_return_address(0));
- BUG();
- }
#endif
- __asm__ __volatile__(
- spin_lock_string
- :"=m" (lock->slock) : : "memory");
-}
-static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
- printk("eip: %p\n", __builtin_return_address(0));
- BUG();
- }
-#endif
- __asm__ __volatile__(
- spin_lock_string_flags
- :"=m" (lock->slock) : "r" (flags) : "memory");
-}
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
/*
* Read-write spinlocks, allowing multiple readers
@@ -163,72 +123,41 @@ static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
+ *
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores. See
+ * semaphore.h for details. -ben
+ *
+ * the helpers are in arch/i386/kernel/semaphore.c
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC 0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
/**
* read_can_lock - would read_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define read_can_lock(x) ((int)(x)->lock > 0)
+#define __raw_read_can_lock(x) ((int)(x)->lock > 0)
/**
* write_can_lock - would write_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+#define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-/*
- * On x86, we implement read-write locks as a 32-bit counter
- * with the high bit (sign) being the "contended" bit.
- *
- * The inline assembly is non-obvious. Think about it.
- *
- * Changed to use the same technique as rw semaphores. See
- * semaphore.h for details. -ben
- */
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
-
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
__build_read_lock(rw, "__read_lock_failed");
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
__build_write_lock(rw, "__write_lock_failed");
}
-#define _raw_read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
-#define _raw_write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
-
-static inline int _raw_read_trylock(rwlock_t *lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
atomic_dec(count);
@@ -238,7 +167,7 @@ static inline int _raw_read_trylock(rwlock_t *lock)
return 0;
}
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
if (atomic_sub_and_test(RW_LOCK_BIAS, count))
@@ -247,4 +176,15 @@ static inline int _raw_write_trylock(rwlock_t *lock)
return 0;
}
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+ asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+ asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
+ : "=m" (rw->lock) : : "memory");
+}
+
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-i386/spinlock_types.h b/include/asm-i386/spinlock_types.h
new file mode 100644
index 000000000000..59efe849f351
--- /dev/null
+++ b/include/asm-i386/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
+
+#endif
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 3db717a244f0..acd5c26b69ba 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -14,8 +14,7 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc
#define switch_to(prev,next,last) do { \
unsigned long esi,edi; \
- asm volatile("pushfl\n\t" \
- "pushl %%ebp\n\t" \
+ asm volatile("pushl %%ebp\n\t" \
"movl %%esp,%0\n\t" /* save ESP */ \
"movl %5,%%esp\n\t" /* restore ESP */ \
"movl $1f,%1\n\t" /* save EIP */ \
@@ -23,7 +22,6 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc
"jmp __switch_to\n" \
"1:\t" \
"popl %%ebp\n\t" \
- "popfl" \
:"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
"=a" (last),"=S" (esi),"=D" (edi) \
:"m" (next->thread.esp),"m" (next->thread.eip), \
@@ -93,13 +91,13 @@ static inline unsigned long _get_base(char * addr)
".align 4\n\t" \
".long 1b,3b\n" \
".previous" \
- : :"m" (value))
+ : :"rm" (value))
/*
* Save a segment register away
*/
#define savesegment(seg, value) \
- asm volatile("mov %%" #seg ",%0":"=m" (value))
+ asm volatile("mov %%" #seg ",%0":"=rm" (value))
/*
* Clear and set 'TS' bit respectively
@@ -107,13 +105,33 @@ static inline unsigned long _get_base(char * addr)
#define clts() __asm__ __volatile__ ("clts")
#define read_cr0() ({ \
unsigned int __dummy; \
- __asm__( \
+ __asm__ __volatile__( \
"movl %%cr0,%0\n\t" \
:"=r" (__dummy)); \
__dummy; \
})
#define write_cr0(x) \
- __asm__("movl %0,%%cr0": :"r" (x));
+ __asm__ __volatile__("movl %0,%%cr0": :"r" (x));
+
+#define read_cr2() ({ \
+ unsigned int __dummy; \
+ __asm__ __volatile__( \
+ "movl %%cr2,%0\n\t" \
+ :"=r" (__dummy)); \
+ __dummy; \
+})
+#define write_cr2(x) \
+ __asm__ __volatile__("movl %0,%%cr2": :"r" (x));
+
+#define read_cr3() ({ \
+ unsigned int __dummy; \
+ __asm__ ( \
+ "movl %%cr3,%0\n\t" \
+ :"=r" (__dummy)); \
+ __dummy; \
+})
+#define write_cr3(x) \
+ __asm__ __volatile__("movl %0,%%cr3": :"r" (x));
#define read_cr4() ({ \
unsigned int __dummy; \
@@ -123,7 +141,7 @@ static inline unsigned long _get_base(char * addr)
__dummy; \
})
#define write_cr4(x) \
- __asm__("movl %0,%%cr4": :"r" (x));
+ __asm__ __volatile__("movl %0,%%cr4": :"r" (x));
#define stts() write_cr0(8 | read_cr0())
#endif /* __KERNEL__ */
@@ -447,6 +465,8 @@ struct alt_instr {
#define local_irq_enable() __asm__ __volatile__("sti": : :"memory")
/* used in the idle loop; sti takes one instruction cycle to complete */
#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory")
+/* used when interrupts are already enabled or to shutdown the processor */
+#define halt() __asm__ __volatile__("hlt": : :"memory")
#define irqs_disabled() \
({ \
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 95add81237ea..8fbf791651bf 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -48,7 +48,7 @@ struct thread_info {
#else /* !__ASSEMBLY__ */
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
#endif
@@ -139,6 +139,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_IRET 5 /* return with iret */
+#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SECCOMP 8 /* secure computing */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
@@ -150,13 +151,15 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_IRET (1<<TIF_IRET)
+#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
- (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
+ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|\
+ _TIF_SECCOMP|_TIF_SYSCALL_EMU))
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index dcf1e07db08a..aed16437479d 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -1,6 +1,7 @@
#ifndef _ASMi386_TIMER_H
#define _ASMi386_TIMER_H
#include <linux/init.h>
+#include <linux/pm.h>
/**
* struct timer_ops - used to define a timer source
@@ -23,6 +24,8 @@ struct timer_opts {
unsigned long long (*monotonic_clock)(void);
void (*delay)(unsigned long);
unsigned long (*read_timer)(void);
+ int (*suspend)(pm_message_t state);
+ int (*resume)(void);
};
struct init_timer_opts {
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 2461b731781e..0ec27c9e8e45 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -60,7 +60,7 @@ static inline int node_to_first_cpu(int node)
return first_cpu(mask);
}
-#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_node(bus) ((long) (bus)->sysdata)
#define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
/* sched_domains SD_NODE_INIT for NUMAQ machines */
diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h
index 901b77c42b8a..ced00fe8fe61 100644
--- a/include/asm-i386/types.h
+++ b/include/asm-i386/types.h
@@ -63,8 +63,6 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 886867aea947..89ab7e2bc5aa 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -83,30 +83,6 @@ extern struct movsl_mask {
*/
#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
-/**
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only. This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index a7cb377745bf..fbaf90a3968c 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -332,7 +332,7 @@ type name(type1 arg1) \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
- : "0" (__NR_##name),"b" ((long)(arg1))); \
+ : "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \
__syscall_return(type,__res); \
}
@@ -342,7 +342,7 @@ type name(type1 arg1,type2 arg2) \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
- : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
+ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \
__syscall_return(type,__res); \
}
@@ -353,7 +353,7 @@ long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3))); \
+ "d" ((long)(arg3)) : "memory"); \
__syscall_return(type,__res); \
}
@@ -364,7 +364,7 @@ long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3)),"S" ((long)(arg4))); \
+ "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
__syscall_return(type,__res); \
}
@@ -376,7 +376,7 @@ long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
+ "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) : "memory"); \
__syscall_return(type,__res); \
}
@@ -389,7 +389,7 @@ __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; p
: "=a" (__res) \
: "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
- "0" ((long)(arg6))); \
+ "0" ((long)(arg6)) : "memory"); \
__syscall_return(type,__res); \
}
diff --git a/include/asm-i386/xor.h b/include/asm-i386/xor.h
index f80e2dbe1b56..23c86cef3b25 100644
--- a/include/asm-i386/xor.h
+++ b/include/asm-i386/xor.h
@@ -535,14 +535,14 @@ static struct xor_block_template xor_block_p5_mmx = {
#define XMMS_SAVE do { \
preempt_disable(); \
+ cr0 = read_cr0(); \
+ clts(); \
__asm__ __volatile__ ( \
- "movl %%cr0,%0 ;\n\t" \
- "clts ;\n\t" \
- "movups %%xmm0,(%1) ;\n\t" \
- "movups %%xmm1,0x10(%1) ;\n\t" \
- "movups %%xmm2,0x20(%1) ;\n\t" \
- "movups %%xmm3,0x30(%1) ;\n\t" \
- : "=&r" (cr0) \
+ "movups %%xmm0,(%0) ;\n\t" \
+ "movups %%xmm1,0x10(%0) ;\n\t" \
+ "movups %%xmm2,0x20(%0) ;\n\t" \
+ "movups %%xmm3,0x30(%0) ;\n\t" \
+ : \
: "r" (xmm_save) \
: "memory"); \
} while(0)
@@ -550,14 +550,14 @@ static struct xor_block_template xor_block_p5_mmx = {
#define XMMS_RESTORE do { \
__asm__ __volatile__ ( \
"sfence ;\n\t" \
- "movups (%1),%%xmm0 ;\n\t" \
- "movups 0x10(%1),%%xmm1 ;\n\t" \
- "movups 0x20(%1),%%xmm2 ;\n\t" \
- "movups 0x30(%1),%%xmm3 ;\n\t" \
- "movl %0,%%cr0 ;\n\t" \
+ "movups (%0),%%xmm0 ;\n\t" \
+ "movups 0x10(%0),%%xmm1 ;\n\t" \
+ "movups 0x20(%0),%%xmm2 ;\n\t" \
+ "movups 0x30(%0),%%xmm3 ;\n\t" \
: \
- : "r" (cr0), "r" (xmm_save) \
+ : "r" (xmm_save) \
: "memory"); \
+ write_cr0(cr0); \
preempt_enable(); \
} while(0)
diff --git a/include/asm-ia64/acpi-ext.h b/include/asm-ia64/acpi-ext.h
index 9271d74c64cc..56d2ddc97b30 100644
--- a/include/asm-ia64/acpi-ext.h
+++ b/include/asm-ia64/acpi-ext.h
@@ -11,6 +11,7 @@
#define _ASM_IA64_ACPI_EXT_H
#include <linux/types.h>
+#include <acpi/actypes.h>
extern acpi_status hp_acpi_csr_space (acpi_handle, u64 *base, u64 *length);
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index 4c06d455139c..3a544ffc5008 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -116,6 +116,11 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
extern u16 ia64_acpiid_to_sapicid[];
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP 0x8
+
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/
diff --git a/include/asm-ia64/auxvec.h b/include/asm-ia64/auxvec.h
new file mode 100644
index 000000000000..23cebe5685b9
--- /dev/null
+++ b/include/asm-ia64/auxvec.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_IA64_AUXVEC_H
+#define _ASM_IA64_AUXVEC_H
+
+/*
+ * Architecture-neutral AT_ values are in the range 0-17. Leave some room for more of
+ * them, start the architecture-specific ones at 32.
+ */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+#endif /* _ASM_IA64_AUXVEC_H */
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index 0c05e5bad8a0..aaf11f4e9169 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -13,10 +13,10 @@ typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_key_t;
typedef s32 compat_pid_t;
-typedef u16 compat_uid_t;
-typedef u16 compat_gid_t;
-typedef u32 compat_uid32_t;
-typedef u32 compat_gid32_t;
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u16 compat_dev_t;
@@ -50,8 +50,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
compat_dev_t st_rdev;
u16 __pad2;
u32 st_size;
@@ -120,10 +120,10 @@ typedef u32 compat_sigset_word;
struct compat_ipc64_perm {
compat_key_t key;
- compat_uid32_t uid;
- compat_gid32_t gid;
- compat_uid32_t cuid;
- compat_gid32_t cgid;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
unsigned short mode;
unsigned short __pad1;
unsigned short seq;
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 7d4ccc4b976e..446fce036fd9 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -12,6 +12,7 @@
#include <asm/fpu.h>
#include <asm/page.h>
+#include <asm/auxvec.h>
/*
* This is used to ensure we don't load something for the wrong architecture.
@@ -177,13 +178,6 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
relevant until we have real hardware to play with... */
#define ELF_PLATFORM NULL
-/*
- * Architecture-neutral AT_ values are in the range 0-17. Leave some room for more of
- * them, start the architecture-specific ones at 32.
- */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
#define elf_read_implies_exec(ex, executable_stack) \
diff --git a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h
index c9f8d835d0cc..1dd275dc8f65 100644
--- a/include/asm-ia64/fcntl.h
+++ b/include/asm-ia64/fcntl.h
@@ -1,86 +1,13 @@
#ifndef _ASM_IA64_FCNTL_H
#define _ASM_IA64_FCNTL_H
/*
- * Based on <asm-i386/fcntl.h>.
- *
* Modified 1998-2000
* David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
*/
-/*
- * open/fcntl - O_SYNC is only implemented on blocks devices and on
- * files located on an ext2 file system
- */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
+#define force_o_largefile() \
+ (personality(current->personality) != PER_LINUX32)
-#define force_o_largefile() ( ! (current->personality & PER_LINUX32) )
+#include <asm-generic/fcntl.h>
#endif /* _ASM_IA64_FCNTL_H */
diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-ia64/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-ia64/hdreg.h b/include/asm-ia64/hdreg.h
deleted file mode 100644
index 83b5161d2678..000000000000
--- a/include/asm-ia64/hdreg.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/include/asm-ia64/hdreg.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-#warning this file is obsolete, please do not use it
-
-#ifndef __ASM_IA64_HDREG_H
-#define __ASM_IA64_HDREG_H
-
-typedef unsigned short ide_ioreg_t;
-
-#endif /* __ASM_IA64_HDREG_H */
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index 041ab8c51a64..0cf119b42f7d 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -116,13 +116,6 @@ __ia64_local_vector_to_irq (ia64_vector vec)
* and to obtain the irq descriptor for a given irq number.
*/
-/* Return a pointer to the irq descriptor for IRQ. */
-static inline irq_desc_t *
-irq_descp (int irq)
-{
- return irq_desc + irq;
-}
-
/* Extract the IA-64 vector that corresponds to IRQ. */
static inline ia64_vector
irq_to_vector (int irq)
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index 54e7637a326c..cf772a67f858 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -23,7 +23,7 @@
#define __SLOW_DOWN_IO do { } while (0)
#define SLOW_DOWN_IO do { } while (0)
-#define __IA64_UNCACHED_OFFSET 0xc000000000000000UL /* region 6 */
+#define __IA64_UNCACHED_OFFSET RGN_BASE(RGN_UNCACHED)
/*
* The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
@@ -41,7 +41,7 @@
#define IO_SPACE_BASE(space) ((space) << IO_SPACE_BITS)
#define IO_SPACE_PORT(port) ((port) & (IO_SPACE_SIZE - 1))
-#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff))
+#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | ((p) & 0xfff))
struct io_space {
unsigned long mmio_base; /* base in MMIO space */
diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
index a429fe225b07..20f98f1751a1 100644
--- a/include/asm-ia64/iosapic.h
+++ b/include/asm-ia64/iosapic.h
@@ -80,12 +80,9 @@ extern int iosapic_remove (unsigned int gsi_base);
#endif /* CONFIG_HOTPLUG */
extern int gsi_to_vector (unsigned int gsi);
extern int gsi_to_irq (unsigned int gsi);
-extern void iosapic_enable_intr (unsigned int vector);
extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
unsigned long trigger);
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
extern void iosapic_unregister_intr (unsigned int irq);
-#endif
extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long polarity,
unsigned long trigger);
@@ -97,7 +94,6 @@ extern int __init iosapic_register_platform_intr (u32 int_type,
unsigned long trigger);
extern unsigned int iosapic_version (char __iomem *addr);
-extern void iosapic_pci_fixup (int);
#ifdef CONFIG_NUMA
extern void __devinit map_iosapic_to_node (unsigned int, int);
#endif
diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h
index bd07d11d9f37..dbe86c0bbce5 100644
--- a/include/asm-ia64/irq.h
+++ b/include/asm-ia64/irq.h
@@ -14,6 +14,11 @@
#define NR_IRQS 256
#define NR_IRQ_VECTORS NR_IRQS
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
static __inline__ int
irq_canonicalize (int irq)
{
@@ -30,14 +35,4 @@ extern void disable_irq_nosync (unsigned int);
extern void enable_irq (unsigned int);
extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
-#ifdef CONFIG_SMP
-extern void move_irq(int irq);
-#else
-#define move_irq(irq)
-#endif
-
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#endif /* _ASM_IA64_IRQ_H */
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index bf36a32e37e4..573a3574a24f 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -92,6 +92,7 @@ struct arch_specific_insn {
kprobe_opcode_t insn;
#define INST_FLAG_FIX_RELATIVE_IP_ADDR 1
#define INST_FLAG_FIX_BRANCH_REG 2
+ #define INST_FLAG_BREAK_INST 4
unsigned long inst_flag;
unsigned short target_br_reg;
};
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 149ad0118455..97a28b8b2ddd 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -11,8 +11,6 @@
#ifndef _ASM_IA64_MCA_H
#define _ASM_IA64_MCA_H
-#define IA64_MCA_STACK_SIZE 8192
-
#if !defined(__ASSEMBLY__)
#include <linux/interrupt.h>
@@ -48,7 +46,8 @@ typedef union cmcv_reg_u {
enum {
IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0,
- IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1
+ IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1,
+ IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2,
};
/* Information maintained by the MC infrastructure */
@@ -63,18 +62,42 @@ typedef struct ia64_mc_info_s {
} ia64_mc_info_t;
-typedef struct ia64_mca_sal_to_os_state_s {
- u64 imsto_os_gp; /* GP of the os registered with the SAL */
- u64 imsto_pal_proc; /* PAL_PROC entry point - physical addr */
- u64 imsto_sal_proc; /* SAL_PROC entry point - physical addr */
- u64 imsto_sal_gp; /* GP of the SAL - physical */
- u64 imsto_rendez_state; /* Rendez state information */
- u64 imsto_sal_check_ra; /* Return address in SAL_CHECK while going
- * back to SAL from OS after MCA handling.
- */
- u64 pal_min_state; /* from PAL in r17 */
- u64 proc_state_param; /* from PAL in r18. See SDV 2:268 11.3.2.1 */
-} ia64_mca_sal_to_os_state_t;
+/* Handover state from SAL to OS and vice versa, for both MCA and INIT events.
+ * Besides the handover state, it also contains some saved registers from the
+ * time of the event.
+ * Note: mca_asm.S depends on the precise layout of this structure.
+ */
+
+struct ia64_sal_os_state {
+ /* SAL to OS, must be at offset 0 */
+ u64 os_gp; /* GP of the os registered with the SAL, physical */
+ u64 pal_proc; /* PAL_PROC entry point, physical */
+ u64 sal_proc; /* SAL_PROC entry point, physical */
+ u64 rv_rc; /* MCA - Rendezvous state, INIT - reason code */
+ u64 proc_state_param; /* from R18 */
+ u64 monarch; /* 1 for a monarch event, 0 for a slave */
+ /* common, must follow SAL to OS */
+ u64 sal_ra; /* Return address in SAL, physical */
+ u64 sal_gp; /* GP of the SAL - physical */
+ pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */
+ u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */
+ struct task_struct *prev_task; /* previous task, NULL if it is not useful */
+ /* Some interrupt registers are not saved in minstate, pt_regs or
+ * switch_stack. Because MCA/INIT can occur when interrupts are
+ * disabled, we need to save the additional interrupt registers over
+ * MCA/INIT and resume.
+ */
+ u64 isr;
+ u64 ifa;
+ u64 itir;
+ u64 iipa;
+ u64 iim;
+ u64 iha;
+ /* OS to SAL, must follow common */
+ u64 os_status; /* OS status to SAL, enum below */
+ u64 context; /* 0 if return to same context
+ 1 if return to new context */
+};
enum {
IA64_MCA_CORRECTED = 0x0, /* Error has been corrected by OS_MCA */
@@ -84,35 +107,21 @@ enum {
};
enum {
+ IA64_INIT_RESUME = 0x0, /* Resume after return from INIT */
+ IA64_INIT_WARM_BOOT = -1, /* Warm boot of the system need from SAL */
+};
+
+enum {
IA64_MCA_SAME_CONTEXT = 0x0, /* SAL to return to same context */
IA64_MCA_NEW_CONTEXT = -1 /* SAL to return to new context */
};
-typedef struct ia64_mca_os_to_sal_state_s {
- u64 imots_os_status; /* OS status to SAL as to what happened
- * with the MCA handling.
- */
- u64 imots_sal_gp; /* GP of the SAL - physical */
- u64 imots_context; /* 0 if return to same context
- 1 if return to new context */
- u64 *imots_new_min_state; /* Pointer to structure containing
- * new values of registers in the min state
- * save area.
- */
- u64 imots_sal_check_ra; /* Return address in SAL_CHECK while going
- * back to SAL from OS after MCA handling.
- */
-} ia64_mca_os_to_sal_state_t;
-
/* Per-CPU MCA state that is too big for normal per-CPU variables. */
struct ia64_mca_cpu {
- u64 stack[IA64_MCA_STACK_SIZE/8]; /* MCA memory-stack */
- u64 proc_state_dump[512];
- u64 stackframe[32];
- u64 rbstore[IA64_MCA_STACK_SIZE/8]; /* MCA reg.-backing store */
+ u64 mca_stack[KERNEL_STACK_SIZE/8];
u64 init_stack[KERNEL_STACK_SIZE/8];
-} __attribute__ ((aligned(16)));
+};
/* Array of physical addresses of each CPU's MCA area. */
extern unsigned long __per_cpu_mca[NR_CPUS];
@@ -121,12 +130,29 @@ extern void ia64_mca_init(void);
extern void ia64_mca_cpu_init(void *);
extern void ia64_os_mca_dispatch(void);
extern void ia64_os_mca_dispatch_end(void);
-extern void ia64_mca_ucmc_handler(void);
+extern void ia64_mca_ucmc_handler(struct pt_regs *, struct ia64_sal_os_state *);
+extern void ia64_init_handler(struct pt_regs *,
+ struct switch_stack *,
+ struct ia64_sal_os_state *);
extern void ia64_monarch_init_handler(void);
extern void ia64_slave_init_handler(void);
extern void ia64_mca_cmc_vector_setup(void);
-extern int ia64_reg_MCA_extension(void*);
+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 *);
+
+#else /* __ASSEMBLY__ */
+
+#define IA64_MCA_CORRECTED 0x0 /* Error has been corrected by OS_MCA */
+#define IA64_MCA_WARM_BOOT -1 /* Warm boot of the system need from SAL */
+#define IA64_MCA_COLD_BOOT -2 /* Cold boot of the system need from SAL */
+#define IA64_MCA_HALT -3 /* System to be halted by SAL */
+
+#define IA64_INIT_RESUME 0x0 /* Resume after return from INIT */
+#define IA64_INIT_WARM_BOOT -1 /* Warm boot of the system need from SAL */
+
+#define IA64_MCA_SAME_CONTEXT 0x0 /* SAL to return to same context */
+#define IA64_MCA_NEW_CONTEXT -1 /* SAL to return to new context */
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_IA64_MCA_H */
diff --git a/include/asm-ia64/mca_asm.h b/include/asm-ia64/mca_asm.h
index 836953e0f91f..27c9203d8ce3 100644
--- a/include/asm-ia64/mca_asm.h
+++ b/include/asm-ia64/mca_asm.h
@@ -8,6 +8,8 @@
* Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2002 Intel Corp.
* Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
+ * Copyright (C) 2005 Silicon Graphics, Inc
+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
*/
#ifndef _ASM_IA64_MCA_ASM_H
#define _ASM_IA64_MCA_ASM_H
@@ -207,106 +209,33 @@
;;
/*
- * The following offsets capture the order in which the
- * RSE related registers from the old context are
- * saved onto the new stack frame.
+ * The MCA and INIT stacks in struct ia64_mca_cpu look like normal kernel
+ * stacks, except that the SAL/OS state and a switch_stack are stored near the
+ * top of the MCA/INIT stack. To support concurrent entry to MCA or INIT, as
+ * well as MCA over INIT, each event needs its own SAL/OS state. All entries
+ * are 16 byte aligned.
*
- * +-----------------------+
- * |NDIRTY [BSP - BSPSTORE]|
- * +-----------------------+
- * | RNAT |
- * +-----------------------+
- * | BSPSTORE |
- * +-----------------------+
- * | IFS |
- * +-----------------------+
- * | PFS |
- * +-----------------------+
- * | RSC |
- * +-----------------------+ <-------- Bottom of new stack frame
+ * +---------------------------+
+ * | pt_regs |
+ * +---------------------------+
+ * | switch_stack |
+ * +---------------------------+
+ * | SAL/OS state |
+ * +---------------------------+
+ * | 16 byte scratch area |
+ * +---------------------------+ <-------- SP at start of C MCA handler
+ * | ..... |
+ * +---------------------------+
+ * | RBS for MCA/INIT handler |
+ * +---------------------------+
+ * | struct task for MCA/INIT |
+ * +---------------------------+ <-------- Bottom of MCA/INIT stack
*/
-#define rse_rsc_offset 0
-#define rse_pfs_offset (rse_rsc_offset+0x08)
-#define rse_ifs_offset (rse_pfs_offset+0x08)
-#define rse_bspstore_offset (rse_ifs_offset+0x08)
-#define rse_rnat_offset (rse_bspstore_offset+0x08)
-#define rse_ndirty_offset (rse_rnat_offset+0x08)
-/*
- * rse_switch_context
- *
- * 1. Save old RSC onto the new stack frame
- * 2. Save PFS onto new stack frame
- * 3. Cover the old frame and start a new frame.
- * 4. Save IFS onto new stack frame
- * 5. Save the old BSPSTORE on the new stack frame
- * 6. Save the old RNAT on the new stack frame
- * 7. Write BSPSTORE with the new backing store pointer
- * 8. Read and save the new BSP to calculate the #dirty registers
- * NOTE: Look at pages 11-10, 11-11 in PRM Vol 2
- */
-#define rse_switch_context(temp,p_stackframe,p_bspstore) \
- ;; \
- mov temp=ar.rsc;; \
- st8 [p_stackframe]=temp,8;; \
- mov temp=ar.pfs;; \
- st8 [p_stackframe]=temp,8; \
- cover ;; \
- mov temp=cr.ifs;; \
- st8 [p_stackframe]=temp,8;; \
- mov temp=ar.bspstore;; \
- st8 [p_stackframe]=temp,8;; \
- mov temp=ar.rnat;; \
- st8 [p_stackframe]=temp,8; \
- mov ar.bspstore=p_bspstore;; \
- mov temp=ar.bsp;; \
- sub temp=temp,p_bspstore;; \
- st8 [p_stackframe]=temp,8;;
-
-/*
- * rse_return_context
- * 1. Allocate a zero-sized frame
- * 2. Store the number of dirty registers RSC.loadrs field
- * 3. Issue a loadrs to insure that any registers from the interrupted
- * context which were saved on the new stack frame have been loaded
- * back into the stacked registers
- * 4. Restore BSPSTORE
- * 5. Restore RNAT
- * 6. Restore PFS
- * 7. Restore IFS
- * 8. Restore RSC
- * 9. Issue an RFI
- */
-#define rse_return_context(psr_mask_reg,temp,p_stackframe) \
- ;; \
- alloc temp=ar.pfs,0,0,0,0; \
- add p_stackframe=rse_ndirty_offset,p_stackframe;; \
- ld8 temp=[p_stackframe];; \
- shl temp=temp,16;; \
- mov ar.rsc=temp;; \
- loadrs;; \
- add p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\
- ld8 temp=[p_stackframe];; \
- mov ar.bspstore=temp;; \
- add p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\
- ld8 temp=[p_stackframe];; \
- mov ar.rnat=temp;; \
- add p_stackframe=-rse_rnat_offset+rse_pfs_offset,p_stackframe;; \
- ld8 temp=[p_stackframe];; \
- mov ar.pfs=temp;; \
- add p_stackframe=-rse_pfs_offset+rse_ifs_offset,p_stackframe;; \
- ld8 temp=[p_stackframe];; \
- mov cr.ifs=temp;; \
- add p_stackframe=-rse_ifs_offset+rse_rsc_offset,p_stackframe;; \
- ld8 temp=[p_stackframe];; \
- mov ar.rsc=temp ; \
- mov temp=psr;; \
- or temp=temp,psr_mask_reg;; \
- mov cr.ipsr=temp;; \
- mov temp=ip;; \
- add temp=0x30,temp;; \
- mov cr.iip=temp;; \
- srlz.i;; \
- rfi;;
+#define ALIGN16(x) ((x)&~15)
+#define MCA_PT_REGS_OFFSET ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)
+#define MCA_SWITCH_STACK_OFFSET ALIGN16(MCA_PT_REGS_OFFSET-IA64_SWITCH_STACK_SIZE)
+#define MCA_SOS_OFFSET ALIGN16(MCA_SWITCH_STACK_OFFSET-IA64_SAL_OS_STATE_SIZE)
+#define MCA_SP_OFFSET ALIGN16(MCA_SOS_OFFSET-16)
#endif /* _ASM_IA64_MCA_ASM_H */
diff --git a/include/asm-ia64/mmu.h b/include/asm-ia64/mmu.h
index ae1525352a25..611432ba579c 100644
--- a/include/asm-ia64/mmu.h
+++ b/include/asm-ia64/mmu.h
@@ -2,10 +2,12 @@
#define __MMU_H
/*
- * Type for a context number. We declare it volatile to ensure proper ordering when it's
- * accessed outside of spinlock'd critical sections (e.g., as done in activate_mm() and
- * init_new_context()).
+ * Type for a context number. We declare it volatile to ensure proper
+ * ordering when it's accessed outside of spinlock'd critical sections
+ * (e.g., as done in activate_mm() and init_new_context()).
*/
typedef volatile unsigned long mm_context_t;
+typedef unsigned long nv_mm_context_t;
+
#endif
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
index e3e5fededb04..8d6e72f7b08e 100644
--- a/include/asm-ia64/mmu_context.h
+++ b/include/asm-ia64/mmu_context.h
@@ -19,6 +19,7 @@
#define ia64_rid(ctx,addr) (((ctx) << 3) | (addr >> 61))
+# include <asm/page.h>
# ifndef __ASSEMBLY__
#include <linux/compiler.h>
@@ -55,34 +56,46 @@ static inline void
delayed_tlb_flush (void)
{
extern void local_flush_tlb_all (void);
+ unsigned long flags;
if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) {
- local_flush_tlb_all();
- __ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
+ spin_lock_irqsave(&ia64_ctx.lock, flags);
+ {
+ if (__ia64_per_cpu_var(ia64_need_tlb_flush)) {
+ local_flush_tlb_all();
+ __ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
+ }
+ }
+ spin_unlock_irqrestore(&ia64_ctx.lock, flags);
}
}
-static inline mm_context_t
+static inline nv_mm_context_t
get_mmu_context (struct mm_struct *mm)
{
unsigned long flags;
- mm_context_t context = mm->context;
-
- if (context)
- return context;
-
- spin_lock_irqsave(&ia64_ctx.lock, flags);
- {
- /* re-check, now that we've got the lock: */
- context = mm->context;
- if (context == 0) {
- cpus_clear(mm->cpu_vm_mask);
- if (ia64_ctx.next >= ia64_ctx.limit)
- wrap_mmu_context(mm);
- mm->context = context = ia64_ctx.next++;
+ nv_mm_context_t context = mm->context;
+
+ if (unlikely(!context)) {
+ spin_lock_irqsave(&ia64_ctx.lock, flags);
+ {
+ /* re-check, now that we've got the lock: */
+ context = mm->context;
+ if (context == 0) {
+ cpus_clear(mm->cpu_vm_mask);
+ if (ia64_ctx.next >= ia64_ctx.limit)
+ wrap_mmu_context(mm);
+ mm->context = context = ia64_ctx.next++;
+ }
}
+ spin_unlock_irqrestore(&ia64_ctx.lock, flags);
}
- spin_unlock_irqrestore(&ia64_ctx.lock, flags);
+ /*
+ * Ensure we're not starting to use "context" before any old
+ * uses of it are gone from our TLB.
+ */
+ delayed_tlb_flush();
+
return context;
}
@@ -104,13 +117,13 @@ destroy_context (struct mm_struct *mm)
}
static inline void
-reload_context (mm_context_t context)
+reload_context (nv_mm_context_t context)
{
unsigned long rid;
unsigned long rid_incr = 0;
unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
- old_rr4 = ia64_get_rr(0x8000000000000000UL);
+ old_rr4 = ia64_get_rr(RGN_BASE(RGN_HPAGE));
rid = context << 3; /* make space for encoding the region number */
rid_incr = 1 << 8;
@@ -122,6 +135,10 @@ reload_context (mm_context_t context)
rr4 = rr0 + 4*rid_incr;
#ifdef CONFIG_HUGETLB_PAGE
rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
+
+# if RGN_HPAGE != 4
+# error "reload_context assumes RGN_HPAGE is 4"
+# endif
#endif
ia64_set_rr(0x0000000000000000UL, rr0);
@@ -138,7 +155,7 @@ reload_context (mm_context_t context)
static inline void
activate_context (struct mm_struct *mm)
{
- mm_context_t context;
+ nv_mm_context_t context;
do {
context = get_mmu_context(mm);
@@ -157,8 +174,6 @@ activate_context (struct mm_struct *mm)
static inline void
activate_mm (struct mm_struct *prev, struct mm_struct *next)
{
- delayed_tlb_flush();
-
/*
* We may get interrupts here, but that's OK because interrupt handlers cannot
* touch user-space.
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 08894f73abf0..9edffad8c28b 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -13,6 +13,19 @@
#include <asm/types.h>
/*
+ * The top three bits of an IA64 address are its Region Number.
+ * Different regions are assigned to different purposes.
+ */
+#define RGN_SHIFT (61)
+#define RGN_BASE(r) (__IA64_UL_CONST(r)<<RGN_SHIFT)
+#define RGN_BITS (RGN_BASE(-1))
+
+#define RGN_KERNEL 7 /* Identity mapped region */
+#define RGN_UNCACHED 6 /* Identity mapped I/O region */
+#define RGN_GATE 5 /* Gate page, Kernel text, etc */
+#define RGN_HPAGE 4 /* For Huge TLB pages */
+
+/*
* PAGE_SHIFT determines the actual kernel page size.
*/
#if defined(CONFIG_IA64_PAGE_SIZE_4KB)
@@ -36,10 +49,9 @@
#define RGN_MAP_LIMIT ((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE) /* per region addr limit */
+
#ifdef CONFIG_HUGETLB_PAGE
-# define REGION_HPAGE (4UL) /* note: this is hardcoded in reload_context()!*/
-# define REGION_SHIFT 61
-# define HPAGE_REGION_BASE (REGION_HPAGE << REGION_SHIFT)
+# define HPAGE_REGION_BASE RGN_BASE(RGN_HPAGE)
# define HPAGE_SHIFT hpage_shift
# define HPAGE_SHIFT_DEFAULT 28 /* check ia64 SDM for architecture supported size */
# define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT)
@@ -130,16 +142,13 @@ typedef union ia64_va {
#define REGION_NUMBER(x) ({ia64_va _v; _v.l = (long) (x); _v.f.reg;})
#define REGION_OFFSET(x) ({ia64_va _v; _v.l = (long) (x); _v.f.off;})
-#define REGION_SIZE REGION_NUMBER(1)
-#define REGION_KERNEL 7
-
#ifdef CONFIG_HUGETLB_PAGE
# define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \
| (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
# define is_hugepage_only_range(mm, addr, len) \
- (REGION_NUMBER(addr) == REGION_HPAGE && \
- REGION_NUMBER((addr)+(len)-1) == REGION_HPAGE)
+ (REGION_NUMBER(addr) == RGN_HPAGE && \
+ REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
extern unsigned int hpage_shift;
#endif
@@ -197,7 +206,7 @@ get_order (unsigned long size)
# define __pgprot(x) (x)
#endif /* !STRICT_MM_TYPECHECKS */
-#define PAGE_OFFSET __IA64_UL_CONST(0xe000000000000000)
+#define PAGE_OFFSET RGN_BASE(RGN_KERNEL)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | \
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 2303a10ee595..e828377ad295 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -75,6 +75,8 @@
#define PAL_CACHE_READ 259 /* read tag & data of cacheline for diagnostic testing */
#define PAL_CACHE_WRITE 260 /* write tag & data of cacheline for diagnostic testing */
#define PAL_VM_TR_READ 261 /* read contents of translation register */
+#define PAL_GET_PSTATE 262 /* get the current P-state */
+#define PAL_SET_PSTATE 263 /* set the P-state */
#ifndef __ASSEMBLY__
@@ -1111,6 +1113,25 @@ ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf)
return iprv.status;
}
+/* Get the current P-state information */
+static inline s64
+ia64_pal_get_pstate (u64 *pstate_index)
+{
+ struct ia64_pal_retval iprv;
+ PAL_CALL_STK(iprv, PAL_GET_PSTATE, 0, 0, 0);
+ *pstate_index = iprv.v0;
+ return iprv.status;
+}
+
+/* Set the P-state */
+static inline s64
+ia64_pal_set_pstate (u64 pstate_index)
+{
+ struct ia64_pal_retval iprv;
+ PAL_CALL_STK(iprv, PAL_SET_PSTATE, pstate_index, 0, 0);
+ return iprv.status;
+}
+
/* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
* suspended, but cache and TLB coherency is maintained.
*/
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index dba9f220be71..ef616fd4cb1b 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -156,6 +156,19 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev,
extern void pcibios_bus_to_resource(struct pci_dev *dev,
struct resource *res, struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
#define pcibios_scan_all_fns(a, b) 0
#endif /* _ASM_IA64_PCI_H */
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 48586e08f432..3339c7b55a6f 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -204,21 +204,18 @@ ia64_phys_addr_valid (unsigned long addr)
#define set_pte(ptep, pteval) (*(ptep) = (pteval))
#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-#define RGN_SIZE (1UL << 61)
-#define RGN_KERNEL 7
-
-#define VMALLOC_START 0xa000000200000000UL
+#define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL)
#ifdef CONFIG_VIRTUAL_MEM_MAP
-# define VMALLOC_END_INIT (0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END_INIT (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
# define VMALLOC_END vmalloc_end
extern unsigned long vmalloc_end;
#else
-# define VMALLOC_END (0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
#endif
/* fs/proc/kcore.c */
-#define kc_vaddr_to_offset(v) ((v) - 0xa000000000000000UL)
-#define kc_offset_to_vaddr(o) ((o) + 0xa000000000000000UL)
+#define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE))
+#define kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE))
/*
* Conversion functions: convert page frame number (pfn) and a protection value to a page
@@ -446,10 +443,6 @@ extern void paging_init (void);
#define pte_to_pgoff(pte) ((pte_val(pte) << 1) >> 3)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 2) | _PAGE_FILE })
-/* XXX is this right? */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 91bbd1f22461..94e07e727395 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -20,9 +20,6 @@
#include <asm/ptrace.h>
#include <asm/ustack.h>
-/* Our arch specific arch_init_sched_domain is in arch/ia64/kernel/domain.c */
-#define ARCH_HAS_SCHED_DOMAIN
-
#define IA64_NUM_DBG_REGS 8
/*
* Limits for PMC and PMD are set to less than maximum architected values
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index 0bef19538406..fc544929ac34 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -57,7 +57,7 @@
#include <linux/config.h>
#include <asm/fpu.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/*
* Base-2 logarithm of number of pages to allocate per task structure
@@ -119,7 +119,7 @@ struct pt_regs {
unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
unsigned long ar_pfs; /* prev function state */
unsigned long ar_rsc; /* RSE configuration */
- /* The following two are valid only if cr_ipsr.cpl > 0: */
+ /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */
unsigned long ar_rnat; /* RSE NaT */
unsigned long ar_bspstore; /* RSE bspstore */
diff --git a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h
index 6ece5061dc19..e18b5ab0cb75 100644
--- a/include/asm-ia64/rwsem.h
+++ b/include/asm-ia64/rwsem.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
* Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 2005 Christoph Lameter <clameter@sgi.com>
*
* Based on asm-i386/rwsem.h and other architecture implementation.
*
@@ -11,9 +12,9 @@
*
* The lock count is initialized to 0 (no active and no waiting lockers).
*
- * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case
- * of an uncontended lock. Readers increment by 1 and see a positive value
- * when uncontended, negative if there are writers (and maybe) readers
+ * When a writer subtracts WRITE_BIAS, it'll get 0xffffffff00000001 for
+ * the case of an uncontended lock. Readers increment by 1 and see a positive
+ * value when uncontended, negative if there are writers (and maybe) readers
* waiting (in which case it goes to sleep).
*/
@@ -29,7 +30,7 @@
* the semaphore definition
*/
struct rw_semaphore {
- signed int count;
+ signed long count;
spinlock_t wait_lock;
struct list_head wait_list;
#if RWSEM_DEBUG
@@ -37,10 +38,10 @@ struct rw_semaphore {
#endif
};
-#define RWSEM_UNLOCKED_VALUE 0x00000000
-#define RWSEM_ACTIVE_BIAS 0x00000001
-#define RWSEM_ACTIVE_MASK 0x0000ffff
-#define RWSEM_WAITING_BIAS (-0x00010000)
+#define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000)
+#define RWSEM_ACTIVE_BIAS __IA64_UL_CONST(0x0000000000000001)
+#define RWSEM_ACTIVE_MASK __IA64_UL_CONST(0x00000000ffffffff)
+#define RWSEM_WAITING_BIAS -__IA64_UL_CONST(0x0000000100000000)
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
@@ -83,7 +84,7 @@ init_rwsem (struct rw_semaphore *sem)
static inline void
__down_read (struct rw_semaphore *sem)
{
- int result = ia64_fetchadd4_acq((unsigned int *)&sem->count, 1);
+ long result = ia64_fetchadd8_acq((unsigned long *)&sem->count, 1);
if (result < 0)
rwsem_down_read_failed(sem);
@@ -95,7 +96,7 @@ __down_read (struct rw_semaphore *sem)
static inline void
__down_write (struct rw_semaphore *sem)
{
- int old, new;
+ long old, new;
do {
old = sem->count;
@@ -112,7 +113,7 @@ __down_write (struct rw_semaphore *sem)
static inline void
__up_read (struct rw_semaphore *sem)
{
- int result = ia64_fetchadd4_rel((unsigned int *)&sem->count, -1);
+ long result = ia64_fetchadd8_rel((unsigned long *)&sem->count, -1);
if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
rwsem_wake(sem);
@@ -124,7 +125,7 @@ __up_read (struct rw_semaphore *sem)
static inline void
__up_write (struct rw_semaphore *sem)
{
- int old, new;
+ long old, new;
do {
old = sem->count;
@@ -141,7 +142,7 @@ __up_write (struct rw_semaphore *sem)
static inline int
__down_read_trylock (struct rw_semaphore *sem)
{
- int tmp;
+ long tmp;
while ((tmp = sem->count) >= 0) {
if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) {
return 1;
@@ -156,7 +157,7 @@ __down_read_trylock (struct rw_semaphore *sem)
static inline int
__down_write_trylock (struct rw_semaphore *sem)
{
- int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
+ long tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
RWSEM_ACTIVE_WRITE_BIAS);
return tmp == RWSEM_UNLOCKED_VALUE;
}
@@ -167,7 +168,7 @@ __down_write_trylock (struct rw_semaphore *sem)
static inline void
__downgrade_write (struct rw_semaphore *sem)
{
- int old, new;
+ long old, new;
do {
old = sem->count;
@@ -182,7 +183,7 @@ __downgrade_write (struct rw_semaphore *sem)
* Implement atomic add functionality. These used to be "inline" functions, but GCC v3.1
* doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd.
*/
-#define rwsem_atomic_add(delta, sem) atomic_add(delta, (atomic_t *)(&(sem)->count))
-#define rwsem_atomic_update(delta, sem) atomic_add_return(delta, (atomic_t *)(&(sem)->count))
+#define rwsem_atomic_add(delta, sem) atomic64_add(delta, (atomic64_t *)(&(sem)->count))
+#define rwsem_atomic_update(delta, sem) atomic64_add_return(delta, (atomic64_t *)(&(sem)->count))
#endif /* _ASM_IA64_RWSEM_H */
diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h
index 103d745dc5f2..2c32e4b77b54 100644
--- a/include/asm-ia64/sn/addrs.h
+++ b/include/asm-ia64/sn/addrs.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 1992-1999,2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 1992-1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_ADDRS_H
@@ -65,7 +65,6 @@
#define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT)
#define AS_MASK ((u64)AS_BITMASK << AS_SHIFT)
-#define REGION_BITS 0xe000000000000000UL
/*
@@ -79,38 +78,30 @@
#define AS_CAC_SPACE (AS_CAC_VAL << AS_SHIFT)
-/*
- * Base addresses for various address ranges.
- */
-#define CACHED 0xe000000000000000UL
-#define UNCACHED 0xc000000000000000UL
-#define UNCACHED_PHYS 0x8000000000000000UL
-
-
/*
* Virtual Mode Local & Global MMR space.
*/
#define SH1_LOCAL_MMR_OFFSET 0x8000000000UL
#define SH2_LOCAL_MMR_OFFSET 0x0200000000UL
#define LOCAL_MMR_OFFSET (is_shub2() ? SH2_LOCAL_MMR_OFFSET : SH1_LOCAL_MMR_OFFSET)
-#define LOCAL_MMR_SPACE (UNCACHED | LOCAL_MMR_OFFSET)
-#define LOCAL_PHYS_MMR_SPACE (UNCACHED_PHYS | LOCAL_MMR_OFFSET)
+#define LOCAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | LOCAL_MMR_OFFSET)
+#define LOCAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | LOCAL_MMR_OFFSET)
#define SH1_GLOBAL_MMR_OFFSET 0x0800000000UL
#define SH2_GLOBAL_MMR_OFFSET 0x0300000000UL
#define GLOBAL_MMR_OFFSET (is_shub2() ? SH2_GLOBAL_MMR_OFFSET : SH1_GLOBAL_MMR_OFFSET)
-#define GLOBAL_MMR_SPACE (UNCACHED | GLOBAL_MMR_OFFSET)
+#define GLOBAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | GLOBAL_MMR_OFFSET)
/*
* Physical mode addresses
*/
-#define GLOBAL_PHYS_MMR_SPACE (UNCACHED_PHYS | GLOBAL_MMR_OFFSET)
+#define GLOBAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | GLOBAL_MMR_OFFSET)
/*
* Clear region & AS bits.
*/
-#define TO_PHYS_MASK (~(REGION_BITS | AS_MASK))
+#define TO_PHYS_MASK (~(RGN_BITS | AS_MASK))
/*
@@ -126,6 +117,7 @@
#define GLOBAL_MMR_PHYS_ADDR(n,a) (GLOBAL_PHYS_MMR_SPACE | REMOTE_ADDR(n,a))
#define GLOBAL_CAC_ADDR(n,a) (CAC_BASE | REMOTE_ADDR(n,a))
#define CHANGE_NASID(n,x) ((void *)(((u64)(x) & ~NASID_MASK) | NASID_SPACE(n)))
+#define IS_TIO_NASID(n) ((n) & 1)
/* non-II mmr's start at top of big window space (4G) */
@@ -134,10 +126,10 @@
/*
* general address defines
*/
-#define CAC_BASE (CACHED | AS_CAC_SPACE)
-#define AMO_BASE (UNCACHED | AS_AMO_SPACE)
-#define AMO_PHYS_BASE (UNCACHED_PHYS | AS_AMO_SPACE)
-#define GET_BASE (CACHED | AS_GET_SPACE)
+#define CAC_BASE (PAGE_OFFSET | AS_CAC_SPACE)
+#define AMO_BASE (__IA64_UNCACHED_OFFSET | AS_AMO_SPACE)
+#define AMO_PHYS_BASE (RGN_BASE(RGN_HPAGE) | AS_AMO_SPACE)
+#define GET_BASE (PAGE_OFFSET | AS_GET_SPACE)
/*
* Convert Memory addresses between various addressing modes.
@@ -155,17 +147,35 @@
* the chiplet id is zero. If we implement TIO-TIO dma, we might need
* to insert a chiplet id into this macro. However, it is our belief
* right now that this chiplet id will be ICE, which is also zero.
- * Nasid starts on bit 40.
*/
-#define PHYS_TO_TIODMA(x) ( (((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x))
-#define PHYS_TO_DMA(x) ( (((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x))
+#define SH1_TIO_PHYS_TO_DMA(x) \
+ ((((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x))
+
+#define SH2_NETWORK_BANK_OFFSET(x) \
+ ((u64)(x) & ((1UL << (sn_hub_info->nasid_shift - 4)) -1))
+
+#define SH2_NETWORK_BANK_SELECT(x) \
+ ((((u64)(x) & (0x3UL << (sn_hub_info->nasid_shift - 4))) \
+ >> (sn_hub_info->nasid_shift - 4)) << 36)
+
+#define SH2_NETWORK_ADDRESS(x) \
+ (SH2_NETWORK_BANK_OFFSET(x) | SH2_NETWORK_BANK_SELECT(x))
+
+#define SH2_TIO_PHYS_TO_DMA(x) \
+ (((u64)(NASID_GET(x)) << 40) | SH2_NETWORK_ADDRESS(x))
+
+#define PHYS_TO_TIODMA(x) \
+ (is_shub1() ? SH1_TIO_PHYS_TO_DMA(x) : SH2_TIO_PHYS_TO_DMA(x))
+
+#define PHYS_TO_DMA(x) \
+ ((((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x))
/*
* Macros to test for address type.
*/
-#define IS_AMO_ADDRESS(x) (((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_BASE)
-#define IS_AMO_PHYS_ADDRESS(x) (((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_PHYS_BASE)
+#define IS_AMO_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_BASE)
+#define IS_AMO_PHYS_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_PHYS_BASE)
/*
@@ -180,18 +190,20 @@
#define TIO_SWIN_BASE(n, w) (TIO_IO_BASE(n) + \
((u64) (w) << TIO_SWIN_SIZE_BITS))
#define NODE_IO_BASE(n) (GLOBAL_MMR_SPACE | NASID_SPACE(n))
-#define TIO_IO_BASE(n) (UNCACHED | NASID_SPACE(n))
+#define TIO_IO_BASE(n) (__IA64_UNCACHED_OFFSET | NASID_SPACE(n))
#define BWIN_SIZE (1UL << BWIN_SIZE_BITS)
#define NODE_BWIN_BASE0(n) (NODE_IO_BASE(n) + BWIN_SIZE)
#define NODE_BWIN_BASE(n, w) (NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS))
#define RAW_NODE_SWIN_BASE(n, w) (NODE_IO_BASE(n) + ((u64) (w) << SWIN_SIZE_BITS))
#define BWIN_WIDGET_MASK 0x7
#define BWIN_WINDOWNUM(x) (((x) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK)
+#define SH1_IS_BIG_WINDOW_ADDR(x) ((x) & BWIN_TOP)
#define TIO_BWIN_WINDOW_SELECT_MASK 0x7
#define TIO_BWIN_WINDOWNUM(x) (((x) >> TIO_BWIN_SIZE_BITS) & TIO_BWIN_WINDOW_SELECT_MASK)
-
+#define TIO_HWIN_SHIFT_BITS 33
+#define TIO_HWIN(x) (NODE_OFFSET(x) >> TIO_HWIN_SHIFT_BITS)
/*
* The following definitions pertain to the IO special address
@@ -216,10 +228,6 @@
#define TIO_SWIN_WIDGETNUM(x) (((x) >> TIO_SWIN_SIZE_BITS) & TIO_SWIN_WIDGET_MASK)
-#define TIO_IOSPACE_ADDR(n,x) \
- /* Move in the Chiplet ID for TIO Local Block MMR */ \
- (REMOTE_ADDR(n,x) | 1UL << (NASID_SHIFT - 2))
-
/*
* The following macros produce the correct base virtual address for
* the hub registers. The REMOTE_HUB_* macro produce
@@ -234,18 +242,40 @@
* Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S().
* They're always safe.
*/
+/* Shub1 TIO & MMR addressing macros */
+#define SH1_TIO_IOSPACE_ADDR(n,x) \
+ GLOBAL_MMR_ADDR(n,x)
+
+#define SH1_REMOTE_BWIN_MMR(n,x) \
+ GLOBAL_MMR_ADDR(n,x)
+
+#define SH1_REMOTE_SWIN_MMR(n,x) \
+ (NODE_SWIN_BASE(n,1) + 0x800000UL + (x))
+
+#define SH1_REMOTE_MMR(n,x) \
+ (SH1_IS_BIG_WINDOW_ADDR(x) ? SH1_REMOTE_BWIN_MMR(n,x) : \
+ SH1_REMOTE_SWIN_MMR(n,x))
+
+/* Shub1 TIO & MMR addressing macros */
+#define SH2_TIO_IOSPACE_ADDR(n,x) \
+ ((__IA64_UNCACHED_OFFSET | REMOTE_ADDR(n,x) | 1UL << (NASID_SHIFT - 2)))
+
+#define SH2_REMOTE_MMR(n,x) \
+ GLOBAL_MMR_ADDR(n,x)
+
+
+/* TIO & MMR addressing macros that work on both shub1 & shub2 */
+#define TIO_IOSPACE_ADDR(n,x) \
+ ((u64 *)(is_shub1() ? SH1_TIO_IOSPACE_ADDR(n,x) : \
+ SH2_TIO_IOSPACE_ADDR(n,x)))
+
+#define SH_REMOTE_MMR(n,x) \
+ (is_shub1() ? SH1_REMOTE_MMR(n,x) : SH2_REMOTE_MMR(n,x))
+
#define REMOTE_HUB_ADDR(n,x) \
- ((n & 1) ? \
- /* TIO: */ \
- (is_shub2() ? \
- /* TIO on Shub2 */ \
- (volatile u64 *)(TIO_IOSPACE_ADDR(n,x)) \
- : /* TIO on shub1 */ \
- (volatile u64 *)(GLOBAL_MMR_ADDR(n,x))) \
- \
- : /* SHUB1 and SHUB2 MMRs: */ \
- (((x) & BWIN_TOP) ? ((volatile u64 *)(GLOBAL_MMR_ADDR(n,x))) \
- : ((volatile u64 *)(NODE_SWIN_BASE(n,1) + 0x800000 + (x)))))
+ (IS_TIO_NASID(n) ? ((volatile u64*)TIO_IOSPACE_ADDR(n,x)) : \
+ ((volatile u64*)SH_REMOTE_MMR(n,x)))
+
#define HUB_L(x) (*((volatile typeof(*x) *)x))
#define HUB_S(x,d) (*((volatile typeof(*x) *)x) = (d))
diff --git a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h
index 84b254603b8d..f083c9434066 100644
--- a/include/asm-ia64/sn/geo.h
+++ b/include/asm-ia64/sn/geo.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_GEO_H
@@ -108,7 +108,6 @@ typedef union geoid_u {
#define INVALID_SLAB (slabid_t)-1
#define INVALID_SLOT (slotid_t)-1
#define INVALID_MODULE ((moduleid_t)-1)
-#define INVALID_PARTID ((partid_t)-1)
static inline slabid_t geo_slab(geoid_t g)
{
diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h
index e190dd4213d5..e35074f526d9 100644
--- a/include/asm-ia64/sn/intr.h
+++ b/include/asm-ia64/sn/intr.h
@@ -12,13 +12,12 @@
#include <linux/rcupdate.h>
#define SGI_UART_VECTOR (0xe9)
-#define SGI_PCIBR_ERROR (0x33)
/* Reserved IRQs : Note, not to exceed IA64_SN2_FIRST_DEVICE_VECTOR */
#define SGI_XPC_ACTIVATE (0x30)
#define SGI_II_ERROR (0x31)
#define SGI_XBOW_ERROR (0x32)
-#define SGI_PCIBR_ERROR (0x33)
+#define SGI_PCIASIC_ERROR (0x33)
#define SGI_ACPI_SCI_INT (0x34)
#define SGI_TIOCA_ERROR (0x35)
#define SGI_TIO_ERROR (0x36)
diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
index 7138b1eafd6b..47bb8100fd00 100644
--- a/include/asm-ia64/sn/nodepda.h
+++ b/include/asm-ia64/sn/nodepda.h
@@ -37,7 +37,6 @@ struct phys_cpuid {
struct nodepda_s {
void *pdinfo; /* Platform-dependent per-node info */
- spinlock_t bist_lock;
/*
* The BTEs on this node are shared by the local cpus
@@ -55,6 +54,8 @@ struct nodepda_s {
* Array of physical cpu identifiers. Indexed by cpuid.
*/
struct phys_cpuid phys_cpuid[NR_CPUS];
+ spinlock_t ptc_lock ____cacheline_aligned_in_smp;
+ spinlock_t bist_lock;
};
typedef struct nodepda_s nodepda_t;
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h
index 976f5eff0539..ad0e8e8ae53f 100644
--- a/include/asm-ia64/sn/pcibus_provider_defs.h
+++ b/include/asm-ia64/sn/pcibus_provider_defs.h
@@ -18,8 +18,9 @@
#define PCIIO_ASIC_TYPE_PIC 2
#define PCIIO_ASIC_TYPE_TIOCP 3
#define PCIIO_ASIC_TYPE_TIOCA 4
+#define PCIIO_ASIC_TYPE_TIOCE 5
-#define PCIIO_ASIC_MAX_TYPES 5
+#define PCIIO_ASIC_MAX_TYPES 6
/*
* Common pciio bus provider data. There should be one of these as the
@@ -30,7 +31,8 @@
struct pcibus_bussoft {
uint32_t bs_asic_type; /* chipset type */
uint32_t bs_xid; /* xwidget id */
- uint64_t bs_persist_busnum; /* Persistent Bus Number */
+ uint32_t bs_persist_busnum; /* Persistent Bus Number */
+ uint32_t bs_persist_segment; /* Segment Number */
uint64_t bs_legacy_io; /* legacy io pio addr */
uint64_t bs_legacy_mem; /* legacy mem pio addr */
uint64_t bs_base; /* widget base */
@@ -47,6 +49,8 @@ struct sn_pcibus_provider {
dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
+ void (*force_interrupt)(struct sn_irq_info *);
+ void (*target_interrupt)(struct sn_irq_info *);
};
extern struct sn_pcibus_provider *sn_pci_provider[];
diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h
index ea5590c76ca4..1c5108d44d8b 100644
--- a/include/asm-ia64/sn/pda.h
+++ b/include/asm-ia64/sn/pda.h
@@ -39,7 +39,6 @@ typedef struct pda_s {
unsigned long pio_write_status_val;
volatile unsigned long *pio_shub_war_cam_addr;
- unsigned long sn_soft_irr[4];
unsigned long sn_in_service_ivecs[4];
int sn_lb_int_war_ticks;
int sn_last_irq;
diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
index df75f4c4aec3..291ef3d69da2 100644
--- a/include/asm-ia64/sn/sn2/sn_hwperf.h
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h
@@ -43,6 +43,7 @@ struct sn_hwperf_object_info {
/* macros for object classification */
#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"))
@@ -214,6 +215,15 @@ struct sn_hwperf_ioctl_args {
*/
#define SN_HWPERF_GET_NODE_NASID (102|SN_HWPERF_OP_MEM_COPYOUT)
+/*
+ * Given a node id, determine the id of the nearest node with CPUs
+ * and the id of the nearest node that has memory. The argument
+ * node would normally be a "headless" node, e.g. an "IO node".
+ * Return 0 on success.
+ */
+extern int sn_hwperf_get_nearest_node(cnodeid_t node,
+ cnodeid_t *near_mem, cnodeid_t *near_cpu);
+
/* return codes */
#define SN_HWPERF_OP_OK 0
#define SN_HWPERF_OP_NOMEM 1
diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h
new file mode 100644
index 000000000000..e68a80853d5d
--- /dev/null
+++ b/include/asm-ia64/sn/sn_feature_sets.h
@@ -0,0 +1,57 @@
+#ifndef _ASM_IA64_SN_FEATURE_SETS_H
+#define _ASM_IA64_SN_FEATURE_SETS_H
+
+/*
+ * SN PROM Features
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include <asm/types.h>
+#include <asm/bitops.h>
+
+/* --------------------- PROM Features -----------------------------*/
+extern int sn_prom_feature_available(int id);
+
+#define MAX_PROM_FEATURE_SETS 2
+
+/*
+ * The following defines features that may or may not be supported by the
+ * current PROM. The OS uses sn_prom_feature_available(feature) to test for
+ * the presence of a PROM feature. Down rev (old) PROMs will always test
+ * "false" for new features.
+ *
+ * Use:
+ * if (sn_prom_feature_available(PRF_FEATURE_XXX))
+ * ...
+ */
+
+/*
+ * Example: feature XXX
+ */
+#define PRF_FEATURE_XXX 0
+
+
+
+/* --------------------- OS Features -------------------------------*/
+
+/*
+ * The following defines OS features that are optionally present in
+ * the operating system.
+ * During boot, PROM is notified of these features via a series of calls:
+ *
+ * ia64_sn_set_os_feature(feature1);
+ *
+ * Once enabled, a feature cannot be disabled.
+ *
+ * By default, features are disabled unless explicitly enabled.
+ */
+#define OSF_MCA_SLV_TO_OS_INIT_SLV 0
+#define OSF_FEAT_LOG_SBES 1
+
+#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 27976d223186..fea35b33d4e4 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -55,7 +55,6 @@
#define SN_SAL_BUS_CONFIG 0x02000037
#define SN_SAL_SYS_SERIAL_GET 0x02000038
#define SN_SAL_PARTITION_SERIAL_GET 0x02000039
-#define SN_SAL_SYSCTL_PARTITION_GET 0x0200003a
#define SN_SAL_SYSTEM_POWER_DOWN 0x0200003b
#define SN_SAL_GET_MASTER_BASEIO_NASID 0x0200003c
#define SN_SAL_COHERENCE 0x0200003d
@@ -78,7 +77,11 @@
#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
#define SN_SAL_BTE_RECOVER 0x02000061
-#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000062
+#define SN_SAL_RESERVED_DO_NOT_USE 0x02000062
+#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000064
+
+#define SN_SAL_GET_PROM_FEATURE_SET 0x02000065
+#define SN_SAL_SET_OS_FEATURE_SET 0x02000066
/*
* Service-specific constants
@@ -118,8 +121,8 @@
/*
* Error Handling Features
*/
-#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV 0x1
-#define SAL_ERR_FEAT_LOG_SBES 0x2
+#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV 0x1 // obsolete
+#define SAL_ERR_FEAT_LOG_SBES 0x2 // obsolete
#define SAL_ERR_FEAT_MFR_OVERRIDE 0x4
#define SAL_ERR_FEAT_SBE_THRESHOLD 0xffff0000
@@ -152,12 +155,6 @@ sn_sal_rev(void)
}
/*
- * Specify the minimum PROM revsion required for this kernel.
- * Note that they're stored in hex format...
- */
-#define SN_SAL_MIN_VERSION 0x0404
-
-/*
* Returns the master console nasid, if the call fails, return an illegal
* value.
*/
@@ -336,7 +333,7 @@ ia64_sn_plat_cpei_handler(void)
}
/*
- * Set Error Handling Features
+ * Set Error Handling Features (Obsolete)
*/
static inline u64
ia64_sn_plat_set_error_handling_features(void)
@@ -586,35 +583,6 @@ sn_partition_serial_number_val(void) {
}
/*
- * Returns the partition id of the nasid passed in as an argument,
- * or INVALID_PARTID if the partition id cannot be retrieved.
- */
-static inline partid_t
-ia64_sn_sysctl_partition_get(nasid_t nasid)
-{
- struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,
- 0, 0, 0, 0, 0, 0);
- if (ret_stuff.status != 0)
- return INVALID_PARTID;
- return ((partid_t)ret_stuff.v0);
-}
-
-/*
- * Returns the partition id of the current processor.
- */
-
-extern partid_t sn_partid;
-
-static inline partid_t
-sn_local_partid(void) {
- if (unlikely(sn_partid < 0)) {
- sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id()));
- }
- return sn_partid;
-}
-
-/*
* Returns the physical address of the partition's reserved page through
* an iterative number of calls.
*
@@ -749,7 +717,8 @@ ia64_sn_power_down(void)
{
struct ia64_sal_retval ret_stuff;
SAL_CALL(ret_stuff, SN_SAL_SYSTEM_POWER_DOWN, 0, 0, 0, 0, 0, 0, 0);
- while(1);
+ while(1)
+ cpu_relax();
/* never returns */
}
@@ -1018,24 +987,6 @@ ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift,
ret_stuff.v2 = 0;
SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0);
-/***** BEGIN HACK - temp til old proms no longer supported ********/
- if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
- int nasid = get_sapicid() & 0xfff;;
-#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL
-#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48
- if (shubtype) *shubtype = 0;
- if (nasid_bitmask) *nasid_bitmask = 0x7ff;
- if (nasid_shift) *nasid_shift = 38;
- if (systemsize) *systemsize = 11;
- if (sharing_domain_size) *sharing_domain_size = 9;
- if (partid) *partid = ia64_sn_sysctl_partition_get(nasid);
- if (coher) *coher = nasid >> 9;
- if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >>
- SH_SHUB_ID_NODES_PER_BIT_SHFT;
- return 0;
- }
-/***** END HACK *******/
-
if (ret_stuff.status < 0)
return ret_stuff.status;
@@ -1068,12 +1019,10 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
}
static inline int
-ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab,
- u64 buf, u64 len)
+ia64_sn_ioif_get_pci_topology(u64 buf, u64 len)
{
struct ia64_sal_retval rv;
- SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY,
- rack, bay, slot, slab, buf, len, 0);
+ SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, buf, len, 0, 0, 0, 0, 0);
return (int) rv.status;
}
@@ -1100,4 +1049,25 @@ ia64_sn_is_fake_prom(void)
return (rv.status == 0);
}
+static inline int
+ia64_sn_get_prom_feature_set(int set, unsigned long *feature_set)
+{
+ struct ia64_sal_retval rv;
+
+ SAL_CALL_NOLOCK(rv, SN_SAL_GET_PROM_FEATURE_SET, set, 0, 0, 0, 0, 0, 0);
+ if (rv.status != 0)
+ return rv.status;
+ *feature_set = rv.v0;
+ return 0;
+}
+
+static inline int
+ia64_sn_set_os_feature(int feature)
+{
+ struct ia64_sal_retval rv;
+
+ SAL_CALL_NOLOCK(rv, SN_SAL_SET_OS_FEATURE_SET, feature, 0, 0, 0, 0, 0, 0);
+ return rv.status;
+}
+
#endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/sn/tioce.h b/include/asm-ia64/sn/tioce.h
new file mode 100644
index 000000000000..22879853e46c
--- /dev/null
+++ b/include/asm-ia64/sn/tioce.h
@@ -0,0 +1,740 @@
+/**************************************************************************
+ * *
+ * Unpublished copyright (c) 2005, Silicon Graphics, Inc. *
+ * THIS IS UNPUBLISHED CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF SGI. *
+ * *
+ * The copyright notice above does not evidence any actual or intended *
+ * publication or disclosure of this source code, which includes *
+ * information that is confidential and/or proprietary, and is a trade *
+ * secret, of Silicon Graphics, Inc. ANY REPRODUCTION, MODIFICATION, *
+ * DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH *
+ * USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN CONSENT OF *
+ * SILICON GRAPHICS, INC. IS STRICTLY PROHIBITED, AND IN VIOLATION OF *
+ * APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR *
+ * POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT *
+ * CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS *
+ * CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY *
+ * DESCRIBE, IN WHOLE OR IN PART. *
+ * *
+ **************************************************************************/
+
+#ifndef __ASM_IA64_SN_TIOCE_H__
+#define __ASM_IA64_SN_TIOCE_H__
+
+/* CE ASIC part & mfgr information */
+#define TIOCE_PART_NUM 0xCE00
+#define TIOCE_MFGR_NUM 0x36
+#define TIOCE_REV_A 0x1
+
+/* CE Virtual PPB Vendor/Device IDs */
+#define CE_VIRT_PPB_VENDOR_ID 0x10a9
+#define CE_VIRT_PPB_DEVICE_ID 0x4002
+
+/* CE Host Bridge Vendor/Device IDs */
+#define CE_HOST_BRIDGE_VENDOR_ID 0x10a9
+#define CE_HOST_BRIDGE_DEVICE_ID 0x4003
+
+
+#define TIOCE_NUM_M40_ATES 4096
+#define TIOCE_NUM_M3240_ATES 2048
+#define TIOCE_NUM_PORTS 2
+
+/*
+ * Register layout for TIOCE. MMR offsets are shown at the far right of the
+ * structure definition.
+ */
+typedef volatile struct tioce {
+ /*
+ * ADMIN : Administration Registers
+ */
+ uint64_t ce_adm_id; /* 0x000000 */
+ uint64_t ce_pad_000008; /* 0x000008 */
+ uint64_t ce_adm_dyn_credit_status; /* 0x000010 */
+ uint64_t ce_adm_last_credit_status; /* 0x000018 */
+ uint64_t ce_adm_credit_limit; /* 0x000020 */
+ uint64_t ce_adm_force_credit; /* 0x000028 */
+ uint64_t ce_adm_control; /* 0x000030 */
+ uint64_t ce_adm_mmr_chn_timeout; /* 0x000038 */
+ uint64_t ce_adm_ssp_ure_timeout; /* 0x000040 */
+ uint64_t ce_adm_ssp_dre_timeout; /* 0x000048 */
+ uint64_t ce_adm_ssp_debug_sel; /* 0x000050 */
+ uint64_t ce_adm_int_status; /* 0x000058 */
+ uint64_t ce_adm_int_status_alias; /* 0x000060 */
+ uint64_t ce_adm_int_mask; /* 0x000068 */
+ uint64_t ce_adm_int_pending; /* 0x000070 */
+ uint64_t ce_adm_force_int; /* 0x000078 */
+ uint64_t ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */
+ uint64_t ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */
+ uint64_t ce_adm_error_summary; /* 0x000100 */
+ uint64_t ce_adm_error_summary_alias; /* 0x000108 */
+ uint64_t ce_adm_error_mask; /* 0x000110 */
+ uint64_t ce_adm_first_error; /* 0x000118 */
+ uint64_t ce_adm_error_overflow; /* 0x000120 */
+ uint64_t ce_adm_error_overflow_alias; /* 0x000128 */
+ uint64_t ce_pad_000130[2]; /* 0x000130 -- 0x000138 */
+ uint64_t ce_adm_tnum_error; /* 0x000140 */
+ uint64_t ce_adm_mmr_err_detail; /* 0x000148 */
+ uint64_t ce_adm_msg_sram_perr_detail; /* 0x000150 */
+ uint64_t ce_adm_bap_sram_perr_detail; /* 0x000158 */
+ uint64_t ce_adm_ce_sram_perr_detail; /* 0x000160 */
+ uint64_t ce_adm_ce_credit_oflow_detail; /* 0x000168 */
+ uint64_t ce_adm_tx_link_idle_max_timer; /* 0x000170 */
+ uint64_t ce_adm_pcie_debug_sel; /* 0x000178 */
+ uint64_t ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */
+
+ uint64_t ce_adm_pcie_debug_sel_top; /* 0x000200 */
+ uint64_t ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */
+ uint64_t ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */
+ uint64_t ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */
+ uint64_t ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */
+ uint64_t ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */
+ uint64_t ce_adm_pcie_trig_compare_top; /* 0x000230 */
+ uint64_t ce_adm_pcie_trig_compare_en_top; /* 0x000238 */
+ uint64_t ce_adm_ssp_debug_sel_top; /* 0x000240 */
+ uint64_t ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */
+ uint64_t ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */
+ uint64_t ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */
+ uint64_t ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */
+ uint64_t ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */
+ uint64_t ce_adm_ssp_trig_compare_top; /* 0x000270 */
+ uint64_t ce_adm_ssp_trig_compare_en_top; /* 0x000278 */
+ uint64_t ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */
+
+ uint64_t ce_adm_bap_ctrl; /* 0x000400 */
+ uint64_t ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */
+
+ uint64_t ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */
+ uint64_t ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */
+
+ uint64_t ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */
+ uint64_t ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */
+
+ uint64_t ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */
+ uint64_t ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */
+
+ uint64_t ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */
+
+ /*
+ * LSI : LSI's PCI Express Link Registers (Link#1 and Link#2)
+ * Link#1 MMRs at start at 0x002000, Link#2 MMRs at 0x003000
+ * NOTE: the comment offsets at far right: let 'z' = {2 or 3}
+ */
+ #define ce_lsi(link_num) ce_lsi[link_num-1]
+ struct ce_lsi_reg {
+ uint64_t ce_lsi_lpu_id; /* 0x00z000 */
+ uint64_t ce_lsi_rst; /* 0x00z008 */
+ uint64_t ce_lsi_dbg_stat; /* 0x00z010 */
+ uint64_t ce_lsi_dbg_cfg; /* 0x00z018 */
+ uint64_t ce_lsi_ltssm_ctrl; /* 0x00z020 */
+ uint64_t ce_lsi_lk_stat; /* 0x00z028 */
+ uint64_t ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */
+ uint64_t ce_lsi_int_and_stat; /* 0x00z040 */
+ uint64_t ce_lsi_int_mask; /* 0x00z048 */
+ uint64_t ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */
+ uint64_t ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */
+ uint64_t ce_pad_00z108; /* 0x00z108 */
+ uint64_t ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */
+ uint64_t ce_pad_00z118; /* 0x00z118 */
+ uint64_t ce_lsi_lk_perf_cnt1; /* 0x00z120 */
+ uint64_t ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */
+ uint64_t ce_lsi_lk_perf_cnt2; /* 0x00z130 */
+ uint64_t ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */
+ uint64_t ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */
+ uint64_t ce_lsi_lk_lyr_cfg; /* 0x00z200 */
+ uint64_t ce_lsi_lk_lyr_status; /* 0x00z208 */
+ uint64_t ce_lsi_lk_lyr_int_stat; /* 0x00z210 */
+ uint64_t ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */
+ uint64_t ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */
+ uint64_t ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */
+ uint64_t ce_lsi_fc_upd_ctl; /* 0x00z240 */
+ uint64_t ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */
+ uint64_t ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */
+ uint64_t ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */
+ uint64_t ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */
+ uint64_t ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */
+ uint64_t ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */
+ uint64_t ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */
+ uint64_t ce_lsi_rply_tmr_thr; /* 0x00z410 */
+ uint64_t ce_lsi_rply_tmr; /* 0x00z418 */
+ uint64_t ce_lsi_rply_num_stat; /* 0x00z420 */
+ uint64_t ce_lsi_rty_buf_max_addr; /* 0x00z428 */
+ uint64_t ce_lsi_rty_fifo_ptr; /* 0x00z430 */
+ uint64_t ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */
+ uint64_t ce_lsi_rty_fifo_cred; /* 0x00z440 */
+ uint64_t ce_lsi_seq_cnt; /* 0x00z448 */
+ uint64_t ce_lsi_ack_sent_seq_num; /* 0x00z450 */
+ uint64_t ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */
+ uint64_t ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */
+ uint64_t ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */
+ uint64_t ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */
+ uint64_t ce_pad_00z478; /* 0x00z478 */
+ uint64_t ce_lsi_mem_addr_ctl; /* 0x00z480 */
+ uint64_t ce_lsi_mem_d_ld0; /* 0x00z488 */
+ uint64_t ce_lsi_mem_d_ld1; /* 0x00z490 */
+ uint64_t ce_lsi_mem_d_ld2; /* 0x00z498 */
+ uint64_t ce_lsi_mem_d_ld3; /* 0x00z4A0 */
+ uint64_t ce_lsi_mem_d_ld4; /* 0x00z4A8 */
+ uint64_t ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */
+ uint64_t ce_lsi_rty_d_cnt; /* 0x00z4C0 */
+ uint64_t ce_lsi_seq_buf_cnt; /* 0x00z4C8 */
+ uint64_t ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */
+ uint64_t ce_pad_00z4D8; /* 0x00z4D8 */
+ uint64_t ce_lsi_ack_lat_thr; /* 0x00z4E0 */
+ uint64_t ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */
+ uint64_t ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */
+ uint64_t ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */
+ uint64_t ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */
+ uint64_t ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */
+ uint64_t ce_lsi_phy_lyr_cfg; /* 0x00z600 */
+ uint64_t ce_pad_00z608; /* 0x00z608 */
+ uint64_t ce_lsi_phy_lyr_int_stat; /* 0x00z610 */
+ uint64_t ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */
+ uint64_t ce_lsi_phy_lyr_int_mask; /* 0x00z620 */
+ uint64_t ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */
+ uint64_t ce_lsi_rcv_phy_cfg; /* 0x00z680 */
+ uint64_t ce_lsi_rcv_phy_stat1; /* 0x00z688 */
+ uint64_t ce_lsi_rcv_phy_stat2; /* 0x00z690 */
+ uint64_t ce_lsi_rcv_phy_stat3; /* 0x00z698 */
+ uint64_t ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */
+ uint64_t ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */
+ uint64_t ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */
+ uint64_t ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */
+ uint64_t ce_lsi_tx_phy_cfg; /* 0x00z700 */
+ uint64_t ce_lsi_tx_phy_stat; /* 0x00z708 */
+ uint64_t ce_lsi_tx_phy_int_stat; /* 0x00z710 */
+ uint64_t ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */
+ uint64_t ce_lsi_tx_phy_int_mask; /* 0x00z720 */
+ uint64_t ce_lsi_tx_phy_stat2; /* 0x00z728 */
+ uint64_t ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */
+ uint64_t ce_lsi_ltssm_cfg1; /* 0x00z780 */
+ uint64_t ce_lsi_ltssm_cfg2; /* 0x00z788 */
+ uint64_t ce_lsi_ltssm_cfg3; /* 0x00z790 */
+ uint64_t ce_lsi_ltssm_cfg4; /* 0x00z798 */
+ uint64_t ce_lsi_ltssm_cfg5; /* 0x00z7A0 */
+ uint64_t ce_lsi_ltssm_stat1; /* 0x00z7A8 */
+ uint64_t ce_lsi_ltssm_stat2; /* 0x00z7B0 */
+ uint64_t ce_lsi_ltssm_int_stat; /* 0x00z7B8 */
+ uint64_t ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */
+ uint64_t ce_lsi_ltssm_int_mask; /* 0x00z7C8 */
+ uint64_t ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */
+ uint64_t ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */
+ uint64_t ce_lsi_gb_cfg1; /* 0x00z800 */
+ uint64_t ce_lsi_gb_cfg2; /* 0x00z808 */
+ uint64_t ce_lsi_gb_cfg3; /* 0x00z810 */
+ uint64_t ce_lsi_gb_cfg4; /* 0x00z818 */
+ uint64_t ce_lsi_gb_stat; /* 0x00z820 */
+ uint64_t ce_lsi_gb_int_stat; /* 0x00z828 */
+ uint64_t ce_lsi_gb_int_stat_test; /* 0x00z830 */
+ uint64_t ce_lsi_gb_int_mask; /* 0x00z838 */
+ uint64_t ce_lsi_gb_pwr_dn1; /* 0x00z840 */
+ uint64_t ce_lsi_gb_pwr_dn2; /* 0x00z848 */
+ uint64_t ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */
+ } ce_lsi[2];
+
+ uint64_t ce_pad_004000[10]; /* 0x004000 -- 0x004048 */
+
+ /*
+ * CRM: Coretalk Receive Module Registers
+ */
+ uint64_t ce_crm_debug_mux; /* 0x004050 */
+ uint64_t ce_pad_004058; /* 0x004058 */
+ uint64_t ce_crm_ssp_err_cmd_wrd; /* 0x004060 */
+ uint64_t ce_crm_ssp_err_addr; /* 0x004068 */
+ uint64_t ce_crm_ssp_err_syn; /* 0x004070 */
+
+ uint64_t ce_pad_004078[499]; /* 0x004078 -- 0x005008 */
+
+ /*
+ * CXM: Coretalk Xmit Module Registers
+ */
+ uint64_t ce_cxm_dyn_credit_status; /* 0x005010 */
+ uint64_t ce_cxm_last_credit_status; /* 0x005018 */
+ uint64_t ce_cxm_credit_limit; /* 0x005020 */
+ uint64_t ce_cxm_force_credit; /* 0x005028 */
+ uint64_t ce_cxm_disable_bypass; /* 0x005030 */
+ uint64_t ce_pad_005038[3]; /* 0x005038 -- 0x005048 */
+ uint64_t ce_cxm_debug_mux; /* 0x005050 */
+
+ uint64_t ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */
+
+ /*
+ * DTL: Downstream Transaction Layer Regs (Link#1 and Link#2)
+ * DTL: Link#1 MMRs at start at 0x006000, Link#2 MMRs at 0x008000
+ * DTL: the comment offsets at far right: let 'y' = {6 or 8}
+ *
+ * UTL: Downstream Transaction Layer Regs (Link#1 and Link#2)
+ * UTL: Link#1 MMRs at start at 0x007000, Link#2 MMRs at 0x009000
+ * UTL: the comment offsets at far right: let 'z' = {7 or 9}
+ */
+ #define ce_dtl(link_num) ce_dtl_utl[link_num-1]
+ #define ce_utl(link_num) ce_dtl_utl[link_num-1]
+ struct ce_dtl_utl_reg {
+ /* DTL */
+ uint64_t ce_dtl_dtdr_credit_limit; /* 0x00y000 */
+ uint64_t ce_dtl_dtdr_credit_force; /* 0x00y008 */
+ uint64_t ce_dtl_dyn_credit_status; /* 0x00y010 */
+ uint64_t ce_dtl_dtl_last_credit_stat; /* 0x00y018 */
+ uint64_t ce_dtl_dtl_ctrl; /* 0x00y020 */
+ uint64_t ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */
+ uint64_t ce_dtl_debug_sel; /* 0x00y050 */
+ uint64_t ce_pad_00y058[501]; /* 0x00y058 -- 0x00yFF8 */
+
+ /* UTL */
+ uint64_t ce_utl_utl_ctrl; /* 0x00z000 */
+ uint64_t ce_utl_debug_sel; /* 0x00z008 */
+ uint64_t ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */
+ } ce_dtl_utl[2];
+
+ uint64_t ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */
+
+ /*
+ * URE: Upstream Request Engine
+ */
+ uint64_t ce_ure_dyn_credit_status; /* 0x00B010 */
+ uint64_t ce_ure_last_credit_status; /* 0x00B018 */
+ uint64_t ce_ure_credit_limit; /* 0x00B020 */
+ uint64_t ce_pad_00B028; /* 0x00B028 */
+ uint64_t ce_ure_control; /* 0x00B030 */
+ uint64_t ce_ure_status; /* 0x00B038 */
+ uint64_t ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */
+ uint64_t ce_ure_debug_sel; /* 0x00B050 */
+ uint64_t ce_ure_pcie_debug_sel; /* 0x00B058 */
+ uint64_t ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */
+ uint64_t ce_ure_ssp_err_addr; /* 0x00B068 */
+ uint64_t ce_ure_page_map; /* 0x00B070 */
+ uint64_t ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */
+ uint64_t ce_ure_pipe_sel1; /* 0x00B088 */
+ uint64_t ce_ure_pipe_mask1; /* 0x00B090 */
+ uint64_t ce_ure_pipe_sel2; /* 0x00B098 */
+ uint64_t ce_ure_pipe_mask2; /* 0x00B0A0 */
+ uint64_t ce_ure_pcie1_credits_sent; /* 0x00B0A8 */
+ uint64_t ce_ure_pcie1_credits_used; /* 0x00B0B0 */
+ uint64_t ce_ure_pcie1_credit_limit; /* 0x00B0B8 */
+ uint64_t ce_ure_pcie2_credits_sent; /* 0x00B0C0 */
+ uint64_t ce_ure_pcie2_credits_used; /* 0x00B0C8 */
+ uint64_t ce_ure_pcie2_credit_limit; /* 0x00B0D0 */
+ uint64_t ce_ure_pcie_force_credit; /* 0x00B0D8 */
+ uint64_t ce_ure_rd_tnum_val; /* 0x00B0E0 */
+ uint64_t ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */
+ uint64_t ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */
+ uint64_t ce_ure_rd_tnum_error; /* 0x00B0F8 */
+ uint64_t ce_ure_rd_tnum_first_cl; /* 0x00B100 */
+ uint64_t ce_ure_rd_tnum_link_buf; /* 0x00B108 */
+ uint64_t ce_ure_wr_tnum_val; /* 0x00B110 */
+ uint64_t ce_ure_sram_err_addr0; /* 0x00B118 */
+ uint64_t ce_ure_sram_err_addr1; /* 0x00B120 */
+ uint64_t ce_ure_sram_err_addr2; /* 0x00B128 */
+ uint64_t ce_ure_sram_rd_addr0; /* 0x00B130 */
+ uint64_t ce_ure_sram_rd_addr1; /* 0x00B138 */
+ uint64_t ce_ure_sram_rd_addr2; /* 0x00B140 */
+ uint64_t ce_ure_sram_wr_addr0; /* 0x00B148 */
+ uint64_t ce_ure_sram_wr_addr1; /* 0x00B150 */
+ uint64_t ce_ure_sram_wr_addr2; /* 0x00B158 */
+ uint64_t ce_ure_buf_flush10; /* 0x00B160 */
+ uint64_t ce_ure_buf_flush11; /* 0x00B168 */
+ uint64_t ce_ure_buf_flush12; /* 0x00B170 */
+ uint64_t ce_ure_buf_flush13; /* 0x00B178 */
+ uint64_t ce_ure_buf_flush20; /* 0x00B180 */
+ uint64_t ce_ure_buf_flush21; /* 0x00B188 */
+ uint64_t ce_ure_buf_flush22; /* 0x00B190 */
+ uint64_t ce_ure_buf_flush23; /* 0x00B198 */
+ uint64_t ce_ure_pcie_control1; /* 0x00B1A0 */
+ uint64_t ce_ure_pcie_control2; /* 0x00B1A8 */
+
+ uint64_t ce_pad_00B1B0[458]; /* 0x00B1B0 -- 0x00BFF8 */
+
+ /* Upstream Data Buffer, Port1 */
+ struct ce_ure_maint_ups_dat1_data {
+ uint64_t data63_0[512]; /* 0x00C000 -- 0x00CFF8 */
+ uint64_t data127_64[512]; /* 0x00D000 -- 0x00DFF8 */
+ uint64_t parity[512]; /* 0x00E000 -- 0x00EFF8 */
+ } ce_ure_maint_ups_dat1;
+
+ /* Upstream Header Buffer, Port1 */
+ struct ce_ure_maint_ups_hdr1_data {
+ uint64_t data63_0[512]; /* 0x00F000 -- 0x00FFF8 */
+ uint64_t data127_64[512]; /* 0x010000 -- 0x010FF8 */
+ uint64_t parity[512]; /* 0x011000 -- 0x011FF8 */
+ } ce_ure_maint_ups_hdr1;
+
+ /* Upstream Data Buffer, Port2 */
+ struct ce_ure_maint_ups_dat2_data {
+ uint64_t data63_0[512]; /* 0x012000 -- 0x012FF8 */
+ uint64_t data127_64[512]; /* 0x013000 -- 0x013FF8 */
+ uint64_t parity[512]; /* 0x014000 -- 0x014FF8 */
+ } ce_ure_maint_ups_dat2;
+
+ /* Upstream Header Buffer, Port2 */
+ struct ce_ure_maint_ups_hdr2_data {
+ uint64_t data63_0[512]; /* 0x015000 -- 0x015FF8 */
+ uint64_t data127_64[512]; /* 0x016000 -- 0x016FF8 */
+ uint64_t parity[512]; /* 0x017000 -- 0x017FF8 */
+ } ce_ure_maint_ups_hdr2;
+
+ /* Downstream Data Buffer */
+ struct ce_ure_maint_dns_dat_data {
+ uint64_t data63_0[512]; /* 0x018000 -- 0x018FF8 */
+ uint64_t data127_64[512]; /* 0x019000 -- 0x019FF8 */
+ uint64_t parity[512]; /* 0x01A000 -- 0x01AFF8 */
+ } ce_ure_maint_dns_dat;
+
+ /* Downstream Header Buffer */
+ struct ce_ure_maint_dns_hdr_data {
+ uint64_t data31_0[64]; /* 0x01B000 -- 0x01B1F8 */
+ uint64_t data95_32[64]; /* 0x01B200 -- 0x01B3F8 */
+ uint64_t parity[64]; /* 0x01B400 -- 0x01B5F8 */
+ } ce_ure_maint_dns_hdr;
+
+ /* RCI Buffer Data */
+ struct ce_ure_maint_rci_data {
+ uint64_t data41_0[64]; /* 0x01B600 -- 0x01B7F8 */
+ uint64_t data69_42[64]; /* 0x01B800 -- 0x01B9F8 */
+ } ce_ure_maint_rci;
+
+ /* Response Queue */
+ uint64_t ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */
+
+ uint64_t ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */
+
+ /* Admin Build-a-Packet Buffer */
+ struct ce_adm_maint_bap_buf_data {
+ uint64_t data63_0[258]; /* 0x024000 -- 0x024808 */
+ uint64_t data127_64[258]; /* 0x024810 -- 0x025018 */
+ uint64_t parity[258]; /* 0x025020 -- 0x025828 */
+ } ce_adm_maint_bap_buf;
+
+ uint64_t ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */
+
+ /* URE: 40bit PMU ATE Buffer */ /* 0x030000 -- 0x037FF8 */
+ uint64_t ce_ure_ate40[TIOCE_NUM_M40_ATES];
+
+ /* URE: 32/40bit PMU ATE Buffer */ /* 0x038000 -- 0x03BFF8 */
+ uint64_t ce_ure_ate3240[TIOCE_NUM_M3240_ATES];
+
+ uint64_t ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */
+
+ /*
+ * DRE: Down Stream Request Engine
+ */
+ uint64_t ce_dre_dyn_credit_status1; /* 0x040010 */
+ uint64_t ce_dre_dyn_credit_status2; /* 0x040018 */
+ uint64_t ce_dre_last_credit_status1; /* 0x040020 */
+ uint64_t ce_dre_last_credit_status2; /* 0x040028 */
+ uint64_t ce_dre_credit_limit1; /* 0x040030 */
+ uint64_t ce_dre_credit_limit2; /* 0x040038 */
+ uint64_t ce_dre_force_credit1; /* 0x040040 */
+ uint64_t ce_dre_force_credit2; /* 0x040048 */
+ uint64_t ce_dre_debug_mux1; /* 0x040050 */
+ uint64_t ce_dre_debug_mux2; /* 0x040058 */
+ uint64_t ce_dre_ssp_err_cmd_wrd; /* 0x040060 */
+ uint64_t ce_dre_ssp_err_addr; /* 0x040068 */
+ uint64_t ce_dre_comp_err_cmd_wrd; /* 0x040070 */
+ uint64_t ce_dre_comp_err_addr; /* 0x040078 */
+ uint64_t ce_dre_req_status; /* 0x040080 */
+ uint64_t ce_dre_config1; /* 0x040088 */
+ uint64_t ce_dre_config2; /* 0x040090 */
+ uint64_t ce_dre_config_req_status; /* 0x040098 */
+ uint64_t ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */
+ uint64_t ce_dre_dyn_fifo; /* 0x040100 */
+ uint64_t ce_pad_040108[3]; /* 0x040108 -- 0x040118 */
+ uint64_t ce_dre_last_fifo; /* 0x040120 */
+
+ uint64_t ce_pad_040128[27]; /* 0x040128 -- 0x0401F8 */
+
+ /* DRE Downstream Head Queue */
+ struct ce_dre_maint_ds_head_queue {
+ uint64_t data63_0[32]; /* 0x040200 -- 0x0402F8 */
+ uint64_t data127_64[32]; /* 0x040300 -- 0x0403F8 */
+ uint64_t parity[32]; /* 0x040400 -- 0x0404F8 */
+ } ce_dre_maint_ds_head_q;
+
+ uint64_t ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */
+
+ /* DRE Downstream Data Queue */
+ struct ce_dre_maint_ds_data_queue {
+ uint64_t data63_0[256]; /* 0x041000 -- 0x0417F8 */
+ uint64_t ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */
+ uint64_t data127_64[256]; /* 0x042000 -- 0x0427F8 */
+ uint64_t ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */
+ uint64_t parity[256]; /* 0x043000 -- 0x0437F8 */
+ uint64_t ce_pad_043800[256]; /* 0x043800 -- 0x043FF8 */
+ } ce_dre_maint_ds_data_q;
+
+ /* DRE URE Upstream Response Queue */
+ struct ce_dre_maint_ure_us_rsp_queue {
+ uint64_t data63_0[8]; /* 0x044000 -- 0x044038 */
+ uint64_t ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */
+ uint64_t data127_64[8]; /* 0x044100 -- 0x044138 */
+ uint64_t ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */
+ uint64_t parity[8]; /* 0x044200 -- 0x044238 */
+ uint64_t ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */
+ } ce_dre_maint_ure_us_rsp_q;
+
+ uint64_t ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */
+
+ uint64_t ce_end_of_struct; /* 0x044400 */
+} tioce_t;
+
+
+/* ce_adm_int_mask/ce_adm_int_status register bit defines */
+#define CE_ADM_INT_CE_ERROR_SHFT 0
+#define CE_ADM_INT_LSI1_IP_ERROR_SHFT 1
+#define CE_ADM_INT_LSI2_IP_ERROR_SHFT 2
+#define CE_ADM_INT_PCIE_ERROR_SHFT 3
+#define CE_ADM_INT_PORT1_HOTPLUG_EVENT_SHFT 4
+#define CE_ADM_INT_PORT2_HOTPLUG_EVENT_SHFT 5
+#define CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT 6
+#define CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT 7
+#define CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT 8
+#define CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT 9
+#define CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT 10
+#define CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT 11
+#define CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT 12
+#define CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT 13
+#define CE_ADM_INT_PCIE_MSG_SHFT 14 /*see int_dest_14*/
+#define CE_ADM_INT_PCIE_MSG_SLOT_0_SHFT 14
+#define CE_ADM_INT_PCIE_MSG_SLOT_1_SHFT 15
+#define CE_ADM_INT_PCIE_MSG_SLOT_2_SHFT 16
+#define CE_ADM_INT_PCIE_MSG_SLOT_3_SHFT 17
+#define CE_ADM_INT_PORT1_PM_PME_MSG_SHFT 22
+#define CE_ADM_INT_PORT2_PM_PME_MSG_SHFT 23
+
+/* ce_adm_force_int register bit defines */
+#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT 0
+#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT 1
+#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT 2
+#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT 3
+#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT 4
+#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT 5
+#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT 6
+#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT 7
+#define CE_ADM_FORCE_INT_ALWAYS_SHFT 8
+
+/* ce_adm_int_dest register bit masks & shifts */
+#define INTR_VECTOR_SHFT 56
+
+/* ce_adm_error_mask and ce_adm_error_summary register bit masks */
+#define CE_ADM_ERR_CRM_SSP_REQ_INVALID (0x1ULL << 0)
+#define CE_ADM_ERR_SSP_REQ_HEADER (0x1ULL << 1)
+#define CE_ADM_ERR_SSP_RSP_HEADER (0x1ULL << 2)
+#define CE_ADM_ERR_SSP_PROTOCOL_ERROR (0x1ULL << 3)
+#define CE_ADM_ERR_SSP_SBE (0x1ULL << 4)
+#define CE_ADM_ERR_SSP_MBE (0x1ULL << 5)
+#define CE_ADM_ERR_CXM_CREDIT_OFLOW (0x1ULL << 6)
+#define CE_ADM_ERR_DRE_SSP_REQ_INVAL (0x1ULL << 7)
+#define CE_ADM_ERR_SSP_REQ_LONG (0x1ULL << 8)
+#define CE_ADM_ERR_SSP_REQ_OFLOW (0x1ULL << 9)
+#define CE_ADM_ERR_SSP_REQ_SHORT (0x1ULL << 10)
+#define CE_ADM_ERR_SSP_REQ_SIDEBAND (0x1ULL << 11)
+#define CE_ADM_ERR_SSP_REQ_ADDR_ERR (0x1ULL << 12)
+#define CE_ADM_ERR_SSP_REQ_BAD_BE (0x1ULL << 13)
+#define CE_ADM_ERR_PCIE_COMPL_TIMEOUT (0x1ULL << 14)
+#define CE_ADM_ERR_PCIE_UNEXP_COMPL (0x1ULL << 15)
+#define CE_ADM_ERR_PCIE_ERR_COMPL (0x1ULL << 16)
+#define CE_ADM_ERR_DRE_CREDIT_OFLOW (0x1ULL << 17)
+#define CE_ADM_ERR_DRE_SRAM_PE (0x1ULL << 18)
+#define CE_ADM_ERR_SSP_RSP_INVALID (0x1ULL << 19)
+#define CE_ADM_ERR_SSP_RSP_LONG (0x1ULL << 20)
+#define CE_ADM_ERR_SSP_RSP_SHORT (0x1ULL << 21)
+#define CE_ADM_ERR_SSP_RSP_SIDEBAND (0x1ULL << 22)
+#define CE_ADM_ERR_URE_SSP_RSP_UNEXP (0x1ULL << 23)
+#define CE_ADM_ERR_URE_SSP_WR_REQ_TIMEOUT (0x1ULL << 24)
+#define CE_ADM_ERR_URE_SSP_RD_REQ_TIMEOUT (0x1ULL << 25)
+#define CE_ADM_ERR_URE_ATE3240_PAGE_FAULT (0x1ULL << 26)
+#define CE_ADM_ERR_URE_ATE40_PAGE_FAULT (0x1ULL << 27)
+#define CE_ADM_ERR_URE_CREDIT_OFLOW (0x1ULL << 28)
+#define CE_ADM_ERR_URE_SRAM_PE (0x1ULL << 29)
+#define CE_ADM_ERR_ADM_SSP_RSP_UNEXP (0x1ULL << 30)
+#define CE_ADM_ERR_ADM_SSP_REQ_TIMEOUT (0x1ULL << 31)
+#define CE_ADM_ERR_MMR_ACCESS_ERROR (0x1ULL << 32)
+#define CE_ADM_ERR_MMR_ADDR_ERROR (0x1ULL << 33)
+#define CE_ADM_ERR_ADM_CREDIT_OFLOW (0x1ULL << 34)
+#define CE_ADM_ERR_ADM_SRAM_PE (0x1ULL << 35)
+#define CE_ADM_ERR_DTL1_MIN_PDATA_CREDIT_ERR (0x1ULL << 36)
+#define CE_ADM_ERR_DTL1_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 37)
+#define CE_ADM_ERR_DTL1_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 38)
+#define CE_ADM_ERR_DTL1_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 39)
+#define CE_ADM_ERR_DTL1_COMP_HD_CRED_MAX_ERR (0x1ULL << 40)
+#define CE_ADM_ERR_DTL1_COMP_D_CRED_MAX_ERR (0x1ULL << 41)
+#define CE_ADM_ERR_DTL1_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 42)
+#define CE_ADM_ERR_DTL1_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 43)
+#define CE_ADM_ERR_DTL1_POSTED_HD_CRED_MAX_ERR (0x1ULL << 44)
+#define CE_ADM_ERR_DTL1_POSTED_D_CRED_MAX_ERR (0x1ULL << 45)
+#define CE_ADM_ERR_DTL2_MIN_PDATA_CREDIT_ERR (0x1ULL << 46)
+#define CE_ADM_ERR_DTL2_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 47)
+#define CE_ADM_ERR_DTL2_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 48)
+#define CE_ADM_ERR_DTL2_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 49)
+#define CE_ADM_ERR_DTL2_COMP_HD_CRED_MAX_ERR (0x1ULL << 50)
+#define CE_ADM_ERR_DTL2_COMP_D_CRED_MAX_ERR (0x1ULL << 51)
+#define CE_ADM_ERR_DTL2_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 52)
+#define CE_ADM_ERR_DTL2_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 53)
+#define CE_ADM_ERR_DTL2_POSTED_HD_CRED_MAX_ERR (0x1ULL << 54)
+#define CE_ADM_ERR_DTL2_POSTED_D_CRED_MAX_ERR (0x1ULL << 55)
+#define CE_ADM_ERR_PORT1_PCIE_COR_ERR (0x1ULL << 56)
+#define CE_ADM_ERR_PORT1_PCIE_NFAT_ERR (0x1ULL << 57)
+#define CE_ADM_ERR_PORT1_PCIE_FAT_ERR (0x1ULL << 58)
+#define CE_ADM_ERR_PORT2_PCIE_COR_ERR (0x1ULL << 59)
+#define CE_ADM_ERR_PORT2_PCIE_NFAT_ERR (0x1ULL << 60)
+#define CE_ADM_ERR_PORT2_PCIE_FAT_ERR (0x1ULL << 61)
+
+/* ce_adm_ure_ups_buf_barrier_flush register bit masks and shifts */
+#define FLUSH_SEL_PORT1_PIPE0_SHFT 0
+#define FLUSH_SEL_PORT1_PIPE1_SHFT 4
+#define FLUSH_SEL_PORT1_PIPE2_SHFT 8
+#define FLUSH_SEL_PORT1_PIPE3_SHFT 12
+#define FLUSH_SEL_PORT2_PIPE0_SHFT 16
+#define FLUSH_SEL_PORT2_PIPE1_SHFT 20
+#define FLUSH_SEL_PORT2_PIPE2_SHFT 24
+#define FLUSH_SEL_PORT2_PIPE3_SHFT 28
+
+/* ce_dre_config1 register bit masks and shifts */
+#define CE_DRE_RO_ENABLE (0x1ULL << 0)
+#define CE_DRE_DYN_RO_ENABLE (0x1ULL << 1)
+#define CE_DRE_SUP_CONFIG_COMP_ERROR (0x1ULL << 2)
+#define CE_DRE_SUP_IO_COMP_ERROR (0x1ULL << 3)
+#define CE_DRE_ADDR_MODE_SHFT 4
+
+/* ce_dre_config_req_status register bit masks */
+#define CE_DRE_LAST_CONFIG_COMPLETION (0x7ULL << 0)
+#define CE_DRE_DOWNSTREAM_CONFIG_ERROR (0x1ULL << 3)
+#define CE_DRE_CONFIG_COMPLETION_VALID (0x1ULL << 4)
+#define CE_DRE_CONFIG_REQUEST_ACTIVE (0x1ULL << 5)
+
+/* ce_ure_control register bit masks & shifts */
+#define CE_URE_RD_MRG_ENABLE (0x1ULL << 0)
+#define CE_URE_WRT_MRG_ENABLE1 (0x1ULL << 4)
+#define CE_URE_WRT_MRG_ENABLE2 (0x1ULL << 5)
+#define CE_URE_RSPQ_BYPASS_DISABLE (0x1ULL << 24)
+#define CE_URE_UPS_DAT1_PAR_DISABLE (0x1ULL << 32)
+#define CE_URE_UPS_HDR1_PAR_DISABLE (0x1ULL << 33)
+#define CE_URE_UPS_DAT2_PAR_DISABLE (0x1ULL << 34)
+#define CE_URE_UPS_HDR2_PAR_DISABLE (0x1ULL << 35)
+#define CE_URE_ATE_PAR_DISABLE (0x1ULL << 36)
+#define CE_URE_RCI_PAR_DISABLE (0x1ULL << 37)
+#define CE_URE_RSPQ_PAR_DISABLE (0x1ULL << 38)
+#define CE_URE_DNS_DAT_PAR_DISABLE (0x1ULL << 39)
+#define CE_URE_DNS_HDR_PAR_DISABLE (0x1ULL << 40)
+#define CE_URE_MALFORM_DISABLE (0x1ULL << 44)
+#define CE_URE_UNSUP_DISABLE (0x1ULL << 45)
+
+/* ce_ure_page_map register bit masks & shifts */
+#define CE_URE_ATE3240_ENABLE (0x1ULL << 0)
+#define CE_URE_ATE40_ENABLE (0x1ULL << 1)
+#define CE_URE_PAGESIZE_SHFT 4
+#define CE_URE_PAGESIZE_MASK (0x7ULL << CE_URE_PAGESIZE_SHFT)
+#define CE_URE_4K_PAGESIZE (0x0ULL << CE_URE_PAGESIZE_SHFT)
+#define CE_URE_16K_PAGESIZE (0x1ULL << CE_URE_PAGESIZE_SHFT)
+#define CE_URE_64K_PAGESIZE (0x2ULL << CE_URE_PAGESIZE_SHFT)
+#define CE_URE_128K_PAGESIZE (0x3ULL << CE_URE_PAGESIZE_SHFT)
+#define CE_URE_256K_PAGESIZE (0x4ULL << CE_URE_PAGESIZE_SHFT)
+
+/* ce_ure_pipe_sel register bit masks & shifts */
+#define PKT_TRAFIC_SHRT 16
+#define BUS_SRC_ID_SHFT 8
+#define DEV_SRC_ID_SHFT 3
+#define FNC_SRC_ID_SHFT 0
+#define CE_URE_TC_MASK (0x07ULL << PKT_TRAFIC_SHRT)
+#define CE_URE_BUS_MASK (0xFFULL << BUS_SRC_ID_SHFT)
+#define CE_URE_DEV_MASK (0x1FULL << DEV_SRC_ID_SHFT)
+#define CE_URE_FNC_MASK (0x07ULL << FNC_SRC_ID_SHFT)
+#define CE_URE_PIPE_BUS(b) (((uint64_t)(b) << BUS_SRC_ID_SHFT) & \
+ CE_URE_BUS_MASK)
+#define CE_URE_PIPE_DEV(d) (((uint64_t)(d) << DEV_SRC_ID_SHFT) & \
+ CE_URE_DEV_MASK)
+#define CE_URE_PIPE_FNC(f) (((uint64_t)(f) << FNC_SRC_ID_SHFT) & \
+ CE_URE_FNC_MASK)
+
+#define CE_URE_SEL1_SHFT 0
+#define CE_URE_SEL2_SHFT 20
+#define CE_URE_SEL3_SHFT 40
+#define CE_URE_SEL1_MASK (0x7FFFFULL << CE_URE_SEL1_SHFT)
+#define CE_URE_SEL2_MASK (0x7FFFFULL << CE_URE_SEL2_SHFT)
+#define CE_URE_SEL3_MASK (0x7FFFFULL << CE_URE_SEL3_SHFT)
+
+
+/* ce_ure_pipe_mask register bit masks & shifts */
+#define CE_URE_MASK1_SHFT 0
+#define CE_URE_MASK2_SHFT 20
+#define CE_URE_MASK3_SHFT 40
+#define CE_URE_MASK1_MASK (0x7FFFFULL << CE_URE_MASK1_SHFT)
+#define CE_URE_MASK2_MASK (0x7FFFFULL << CE_URE_MASK2_SHFT)
+#define CE_URE_MASK3_MASK (0x7FFFFULL << CE_URE_MASK3_SHFT)
+
+
+/* ce_ure_pcie_control1 register bit masks & shifts */
+#define CE_URE_SI (0x1ULL << 0)
+#define CE_URE_ELAL_SHFT 4
+#define CE_URE_ELAL_MASK (0x7ULL << CE_URE_ELAL_SHFT)
+#define CE_URE_ELAL1_SHFT 8
+#define CE_URE_ELAL1_MASK (0x7ULL << CE_URE_ELAL1_SHFT)
+#define CE_URE_SCC (0x1ULL << 12)
+#define CE_URE_PN1_SHFT 16
+#define CE_URE_PN1_MASK (0xFFULL << CE_URE_PN1_SHFT)
+#define CE_URE_PN2_SHFT 24
+#define CE_URE_PN2_MASK (0xFFULL << CE_URE_PN2_SHFT)
+#define CE_URE_PN1_SET(n) (((uint64_t)(n) << CE_URE_PN1_SHFT) & \
+ CE_URE_PN1_MASK)
+#define CE_URE_PN2_SET(n) (((uint64_t)(n) << CE_URE_PN2_SHFT) & \
+ CE_URE_PN2_MASK)
+
+/* ce_ure_pcie_control2 register bit masks & shifts */
+#define CE_URE_ABP (0x1ULL << 0)
+#define CE_URE_PCP (0x1ULL << 1)
+#define CE_URE_MSP (0x1ULL << 2)
+#define CE_URE_AIP (0x1ULL << 3)
+#define CE_URE_PIP (0x1ULL << 4)
+#define CE_URE_HPS (0x1ULL << 5)
+#define CE_URE_HPC (0x1ULL << 6)
+#define CE_URE_SPLV_SHFT 7
+#define CE_URE_SPLV_MASK (0xFFULL << CE_URE_SPLV_SHFT)
+#define CE_URE_SPLS_SHFT 15
+#define CE_URE_SPLS_MASK (0x3ULL << CE_URE_SPLS_SHFT)
+#define CE_URE_PSN1_SHFT 19
+#define CE_URE_PSN1_MASK (0x1FFFULL << CE_URE_PSN1_SHFT)
+#define CE_URE_PSN2_SHFT 32
+#define CE_URE_PSN2_MASK (0x1FFFULL << CE_URE_PSN2_SHFT)
+#define CE_URE_PSN1_SET(n) (((uint64_t)(n) << CE_URE_PSN1_SHFT) & \
+ CE_URE_PSN1_MASK)
+#define CE_URE_PSN2_SET(n) (((uint64_t)(n) << CE_URE_PSN2_SHFT) & \
+ CE_URE_PSN2_MASK)
+
+/*
+ * PIO address space ranges for CE
+ */
+
+/* Local CE Registers Space */
+#define CE_PIO_MMR 0x00000000
+#define CE_PIO_MMR_LEN 0x04000000
+
+/* PCI Compatible Config Space */
+#define CE_PIO_CONFIG_SPACE 0x04000000
+#define CE_PIO_CONFIG_SPACE_LEN 0x04000000
+
+/* PCI I/O Space Alias */
+#define CE_PIO_IO_SPACE_ALIAS 0x08000000
+#define CE_PIO_IO_SPACE_ALIAS_LEN 0x08000000
+
+/* PCI Enhanced Config Space */
+#define CE_PIO_E_CONFIG_SPACE 0x10000000
+#define CE_PIO_E_CONFIG_SPACE_LEN 0x10000000
+
+/* PCI I/O Space */
+#define CE_PIO_IO_SPACE 0x100000000
+#define CE_PIO_IO_SPACE_LEN 0x100000000
+
+/* PCI MEM Space */
+#define CE_PIO_MEM_SPACE 0x200000000
+#define CE_PIO_MEM_SPACE_LEN TIO_HWIN_SIZE
+
+
+/*
+ * CE PCI Enhanced Config Space shifts & masks
+ */
+#define CE_E_CONFIG_BUS_SHFT 20
+#define CE_E_CONFIG_BUS_MASK (0xFF << CE_E_CONFIG_BUS_SHFT)
+#define CE_E_CONFIG_DEVICE_SHFT 15
+#define CE_E_CONFIG_DEVICE_MASK (0x1F << CE_E_CONFIG_DEVICE_SHFT)
+#define CE_E_CONFIG_FUNC_SHFT 12
+#define CE_E_CONFIG_FUNC_MASK (0x7 << CE_E_CONFIG_FUNC_SHFT)
+
+#endif /* __ASM_IA64_SN_TIOCE_H__ */
diff --git a/include/asm-ia64/sn/tioce_provider.h b/include/asm-ia64/sn/tioce_provider.h
new file mode 100644
index 000000000000..7f63dec0a79a
--- /dev/null
+++ b/include/asm-ia64/sn/tioce_provider.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+ * Copyright (C) 2005, Silicon Graphics, Inc. *
+ * *
+ * These coded instructions, statements, and computer programs contain *
+ * unpublished proprietary information of Silicon Graphics, Inc., and *
+ * are protected by Federal copyright law. They may not be disclosed *
+ * to third parties or copied or duplicated in any form, in whole or *
+ * in part, without the prior written consent of Silicon Graphics, Inc. *
+ * *
+ **************************************************************************/
+
+#ifndef _ASM_IA64_SN_CE_PROVIDER_H
+#define _ASM_IA64_SN_CE_PROVIDER_H
+
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/tioce.h>
+
+/*
+ * Common TIOCE structure shared between the prom and kernel
+ *
+ * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES TO THE
+ * PROM VERSION.
+ */
+struct tioce_common {
+ struct pcibus_bussoft ce_pcibus; /* common pciio header */
+
+ uint32_t ce_rev;
+ uint64_t ce_kernel_private;
+ uint64_t ce_prom_private;
+};
+
+struct tioce_kernel {
+ struct tioce_common *ce_common;
+ spinlock_t ce_lock;
+ struct list_head ce_dmamap_list;
+
+ uint64_t ce_ate40_shadow[TIOCE_NUM_M40_ATES];
+ uint64_t ce_ate3240_shadow[TIOCE_NUM_M3240_ATES];
+ uint32_t ce_ate3240_pagesize;
+
+ uint8_t ce_port1_secondary;
+
+ /* per-port resources */
+ struct {
+ int dirmap_refcnt;
+ uint64_t dirmap_shadow;
+ } ce_port[TIOCE_NUM_PORTS];
+};
+
+struct tioce_dmamap {
+ struct list_head ce_dmamap_list; /* headed by tioce_kernel */
+ uint32_t refcnt;
+
+ uint64_t nbytes; /* # bytes mapped */
+
+ uint64_t ct_start; /* coretalk start address */
+ uint64_t pci_start; /* bus start address */
+
+ uint64_t *ate_hw; /* hw ptr of first ate in map */
+ uint64_t *ate_shadow; /* shadow ptr of firat ate */
+ uint16_t ate_count; /* # ate's in the map */
+};
+
+extern int tioce_init_provider(void);
+
+#endif /* __ASM_IA64_SN_CE_PROVIDER_H */
diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
index 21a9f10d6baa..a255006fb7b5 100644
--- a/include/asm-ia64/socket.h
+++ b/include/asm-ia64/socket.h
@@ -23,6 +23,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
index 909936f25512..5b78611411c3 100644
--- a/include/asm-ia64/spinlock.h
+++ b/include/asm-ia64/spinlock.h
@@ -17,28 +17,20 @@
#include <asm/intrinsics.h>
#include <asm/system.h>
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-#define spin_lock_init(x) ((x)->lock = 0)
+#define __raw_spin_lock_init(x) ((x)->lock = 0)
#ifdef ASM_SUPPORTED
/*
* Try to get the lock. If we fail to get the lock, make a non-standard call to
* ia64_spinlock_contention(). We do not use a normal call because that would force all
- * callers of spin_lock() to be non-leaf routines. Instead, ia64_spinlock_contention() is
- * carefully coded to touch only those registers that spin_lock() marks "clobbered".
+ * callers of __raw_spin_lock() to be non-leaf routines. Instead, ia64_spinlock_contention() is
+ * carefully coded to touch only those registers that __raw_spin_lock() marks "clobbered".
*/
#define IA64_SPINLOCK_CLOBBERS "ar.ccv", "ar.pfs", "p14", "p15", "r27", "r28", "r29", "r30", "b6", "memory"
static inline void
-_raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+__raw_spin_lock_flags (raw_spinlock_t *lock, unsigned long flags)
{
register volatile unsigned int *ptr asm ("r31") = &lock->lock;
@@ -93,10 +85,18 @@ _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
# endif /* CONFIG_MCKINLEY */
#endif
}
-#define _raw_spin_lock(lock) _raw_spin_lock_flags(lock, 0)
+
+#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0)
+
+/* Unlock by doing an ordered store and releasing the cacheline with nta */
+static inline void __raw_spin_unlock(raw_spinlock_t *x) {
+ barrier();
+ asm volatile ("st4.rel.nta [%0] = r0\n\t" :: "r"(x));
+}
+
#else /* !ASM_SUPPORTED */
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-# define _raw_spin_lock(x) \
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+# define __raw_spin_lock(x) \
do { \
__u32 *ia64_spinlock_ptr = (__u32 *) (x); \
__u64 ia64_spinlock_val; \
@@ -109,29 +109,20 @@ do { \
} while (ia64_spinlock_val); \
} \
} while (0)
+#define __raw_spin_unlock(x) do { barrier(); ((raw_spinlock_t *) x)->lock = 0; } while (0)
#endif /* !ASM_SUPPORTED */
-#define spin_is_locked(x) ((x)->lock != 0)
-#define _raw_spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0)
-#define _raw_spin_trylock(x) (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
-#define spin_unlock_wait(x) do { barrier(); } while ((x)->lock)
-
-typedef struct {
- volatile unsigned int read_counter : 31;
- volatile unsigned int write_lock : 1;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_trylock(x) (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-#define read_can_lock(rw) (*(volatile int *)(rw) >= 0)
-#define write_can_lock(rw) (*(volatile int *)(rw) == 0)
+#define __raw_read_can_lock(rw) (*(volatile int *)(rw) >= 0)
+#define __raw_write_can_lock(rw) (*(volatile int *)(rw) == 0)
-#define _raw_read_lock(rw) \
+#define __raw_read_lock(rw) \
do { \
- rwlock_t *__read_lock_ptr = (rw); \
+ raw_rwlock_t *__read_lock_ptr = (rw); \
\
while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, acq) < 0)) { \
ia64_fetchadd(-1, (int *) __read_lock_ptr, rel); \
@@ -140,14 +131,14 @@ do { \
} \
} while (0)
-#define _raw_read_unlock(rw) \
+#define __raw_read_unlock(rw) \
do { \
- rwlock_t *__read_lock_ptr = (rw); \
+ raw_rwlock_t *__read_lock_ptr = (rw); \
ia64_fetchadd(-1, (int *) __read_lock_ptr, rel); \
} while (0)
#ifdef ASM_SUPPORTED
-#define _raw_write_lock(rw) \
+#define __raw_write_lock(rw) \
do { \
__asm__ __volatile__ ( \
"mov ar.ccv = r0\n" \
@@ -162,7 +153,7 @@ do { \
:: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \
} while(0)
-#define _raw_write_trylock(rw) \
+#define __raw_write_trylock(rw) \
({ \
register long result; \
\
@@ -174,9 +165,16 @@ do { \
(result == 0); \
})
+static inline void __raw_write_unlock(raw_rwlock_t *x)
+{
+ u8 *y = (u8 *)x;
+ barrier();
+ asm volatile ("st1.rel.nta [%0] = r0\n\t" :: "r"(y+3) : "memory" );
+}
+
#else /* !ASM_SUPPORTED */
-#define _raw_write_lock(l) \
+#define __raw_write_lock(l) \
({ \
__u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1); \
__u32 *ia64_write_lock_ptr = (__u32 *) (l); \
@@ -187,7 +185,7 @@ do { \
} while (ia64_val); \
})
-#define _raw_write_trylock(rw) \
+#define __raw_write_trylock(rw) \
({ \
__u64 ia64_val; \
__u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1); \
@@ -195,14 +193,14 @@ do { \
(ia64_val == 0); \
})
-#endif /* !ASM_SUPPORTED */
+static inline void __raw_write_unlock(raw_rwlock_t *x)
+{
+ barrier();
+ x->write_lock = 0;
+}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#endif /* !ASM_SUPPORTED */
-#define _raw_write_unlock(x) \
-({ \
- smp_mb__before_clear_bit(); /* need barrier before releasing lock... */ \
- clear_bit(31, (x)); \
-})
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
#endif /* _ASM_IA64_SPINLOCK_H */
diff --git a/include/asm-ia64/spinlock_types.h b/include/asm-ia64/spinlock_types.h
new file mode 100644
index 000000000000..474e46f1ab4a
--- /dev/null
+++ b/include/asm-ia64/spinlock_types.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_IA64_SPINLOCK_TYPES_H
+#define _ASM_IA64_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int read_counter : 31;
+ volatile unsigned int write_lock : 1;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0, 0 }
+
+#endif
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index cd2cf76b2db1..635235fa1e32 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -19,12 +19,13 @@
#include <asm/pal.h>
#include <asm/percpu.h>
-#define GATE_ADDR __IA64_UL_CONST(0xa000000000000000)
+#define GATE_ADDR RGN_BASE(RGN_GATE)
+
/*
* 0xa000000000000000+2*PERCPU_PAGE_SIZE
* - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
*/
-#define KERNEL_START __IA64_UL_CONST(0xa000000100000000)
+#define KERNEL_START (GATE_ADDR+0x100000000)
#define PERCPU_ADDR (-PERCPU_PAGE_SIZE)
#ifndef __ASSEMBLY__
@@ -274,6 +275,7 @@ extern void ia64_load_extra (struct task_struct *task);
*/
#define __ARCH_WANT_UNLOCKED_CTXSW
+#define ARCH_HAS_PREFETCH_SWITCH_STACK
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
void cpu_idle_wait(void);
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 7dc8951708a3..cf4a950a0f4f 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -5,7 +5,7 @@
#ifndef _ASM_IA64_THREAD_INFO_H
#define _ASM_IA64_THREAD_INFO_H
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
@@ -76,6 +76,7 @@ struct thread_info {
#define TIF_SIGDELAYED 5 /* signal delayed from MCA/INIT/NMI/PMI context */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
+#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -85,6 +86,7 @@ struct thread_info {
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
/* "work to do on user-return" bits */
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED)
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 399bc29729fd..a9f738bf18a7 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -98,29 +98,6 @@ void build_cpu_to_node_map(void);
.nr_balance_failed = 0, \
}
-/* sched_domains SD_ALLNODES_INIT for IA64 NUMA machines */
-#define SD_ALLNODES_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
- .parent = NULL, \
- .groups = NULL, \
- .min_interval = 64, \
- .max_interval = 64*num_online_cpus(), \
- .busy_factor = 128, \
- .imbalance_pct = 133, \
- .cache_hot_time = (10*1000000), \
- .cache_nice_tries = 1, \
- .busy_idx = 3, \
- .idle_idx = 3, \
- .newidle_idx = 0, /* unused */ \
- .wake_idx = 0, /* unused */ \
- .forkexec_idx = 0, /* unused */ \
- .per_cpu_gain = 100, \
- .flags = SD_LOAD_BALANCE, \
- .last_balance = jiffies, \
- .balance_interval = 64, \
- .nr_balance_failed = 0, \
-}
-
#endif /* CONFIG_NUMA */
#include <asm-generic/topology.h>
diff --git a/include/asm-ia64/types.h b/include/asm-ia64/types.h
index a677565aa954..902850d12424 100644
--- a/include/asm-ia64/types.h
+++ b/include/asm-ia64/types.h
@@ -67,8 +67,6 @@ typedef __u64 u64;
typedef u64 dma_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
# endif /* __KERNEL__ */
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h
index 8edd9a90949c..3a7829bb5954 100644
--- a/include/asm-ia64/uaccess.h
+++ b/include/asm-ia64/uaccess.h
@@ -72,13 +72,6 @@
})
#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs())
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated
-verify_area (int type, const void __user *addr, unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
diff --git a/include/asm-ia64/unwind.h b/include/asm-ia64/unwind.h
index 61426ad3ecdb..5df0276b0493 100644
--- a/include/asm-ia64/unwind.h
+++ b/include/asm-ia64/unwind.h
@@ -114,13 +114,6 @@ extern void unw_remove_unwind_table (void *handle);
*/
extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
-/*
- * Prepare to unwind from interruption. The pt-regs and switch-stack structures must have
- * be "adjacent" (no state modifications between pt-regs and switch-stack).
- */
-extern void unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
- struct pt_regs *pt, struct switch_stack *sw);
-
extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
struct switch_stack *sw);
diff --git a/include/asm-m32r/auxvec.h b/include/asm-m32r/auxvec.h
new file mode 100644
index 000000000000..f76dcc860fae
--- /dev/null
+++ b/include/asm-m32r/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_M32R__AUXVEC_H
+#define _ASM_M32R__AUXVEC_H
+
+#endif /* _ASM_M32R__AUXVEC_H */
diff --git a/include/asm-m32r/checksum.h b/include/asm-m32r/checksum.h
index 99f37dbf2558..877ebf46e9ff 100644
--- a/include/asm-m32r/checksum.h
+++ b/include/asm-m32r/checksum.h
@@ -105,7 +105,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
" addx %0, %3 \n"
" .fillinsn\n"
"2: \n"
- /* Since the input registers which are loaded with iph and ipl
+ /* Since the input registers which are loaded with iph and ihl
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=&r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmpreg0), "=&r" (tmpreg1)
diff --git a/include/asm-m32r/fcntl.h b/include/asm-m32r/fcntl.h
index 3e3089572028..46ab12db5739 100644
--- a/include/asm-m32r/fcntl.h
+++ b/include/asm-m32r/fcntl.h
@@ -1,92 +1 @@
-#ifndef _ASM_M32R_FCNTL_H
-#define _ASM_M32R_FCNTL_H
-
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif /* _ASM_M32R_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-m32r/futex.h b/include/asm-m32r/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-m32r/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-m32r/hdreg.h b/include/asm-m32r/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-m32r/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 1c6abb9f3f1f..4ab578876361 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -61,25 +61,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* This handles the memory map.. */
-#ifndef __ASSEMBLY__
-
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size - 1) >> (PAGE_SHIFT - 1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
-
- return order;
-}
-
-#endif /* __ASSEMBLY__ */
-
#define __MEMORY_START CONFIG_MEMORY_START
#define __MEMORY_SIZE CONFIG_MEMORY_SIZE
@@ -111,5 +92,7 @@ static __inline__ int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _ASM_M32R_PAGE_H */
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index da805e970844..388e5ee9fa27 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -378,9 +378,6 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h
index 159519d99042..8b6680f223c0 100644
--- a/include/asm-m32r/socket.h
+++ b/include/asm-m32r/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
index 6608d8371c50..7de7def28da9 100644
--- a/include/asm-m32r/spinlock.h
+++ b/include/asm-m32r/spinlock.h
@@ -14,57 +14,30 @@
#include <asm/atomic.h>
#include <asm/page.h>
-extern int printk(const char * fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-#define RW_LOCK_BIAS 0x01000000
-#define RW_LOCK_BIAS_STR "0x01000000"
-
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile int slock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
+ * (the type definitions are in asm/spinlock_types.h)
+ *
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
*/
-#define spin_is_locked(x) (*(volatile int *)(&(x)->slock) <= 0)
-#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) (*(volatile int *)(&(x)->slock) <= 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+ do { cpu_relax(); } while (__raw_spin_is_locked(x))
/**
- * _raw_spin_trylock - Try spin lock and return a result
+ * __raw_spin_trylock - Try spin lock and return a result
* @lock: Pointer to the lock variable
*
- * _raw_spin_trylock() tries to get the lock and returns a result.
+ * __raw_spin_trylock() tries to get the lock and returns a result.
* On the m32r, the result value is 1 (= Success) or 0 (= Failure).
*/
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
int oldval;
unsigned long tmp1, tmp2;
@@ -78,7 +51,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
* }
*/
__asm__ __volatile__ (
- "# spin_trylock \n\t"
+ "# __raw_spin_trylock \n\t"
"ldi %1, #0; \n\t"
"mvfc %2, psw; \n\t"
"clrpsw #0x40 -> nop; \n\t"
@@ -97,16 +70,10 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
return (oldval > 0);
}
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned long tmp0, tmp1;
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
- printk("pc: %p\n", __builtin_return_address(0));
- BUG();
- }
-#endif
/*
* lock->slock : =1 : unlock
* : <=0 : lock
@@ -118,7 +85,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
* }
*/
__asm__ __volatile__ (
- "# spin_lock \n\t"
+ "# __raw_spin_lock \n\t"
".fillinsn \n"
"1: \n\t"
"mvfc %1, psw; \n\t"
@@ -145,12 +112,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
);
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(lock->magic != SPINLOCK_MAGIC);
- BUG_ON(!spin_is_locked(lock));
-#endif
mb();
lock->slock = 1;
}
@@ -164,59 +127,32 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
+ *
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores. See
+ * semaphore.h for details. -ben
*/
-typedef struct {
- volatile int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC 0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
/**
* read_can_lock - would read_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define read_can_lock(x) ((int)(x)->lock > 0)
+#define __raw_read_can_lock(x) ((int)(x)->lock > 0)
/**
* write_can_lock - would write_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-
-/*
- * On x86, we implement read-write locks as a 32-bit counter
- * with the high bit (sign) being the "contended" bit.
- *
- * The inline assembly is non-obvious. Think about it.
- *
- * Changed to use the same technique as rw semaphores. See
- * semaphore.h for details. -ben
- */
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
+#define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned long tmp0, tmp1;
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
/*
* rw->lock : >0 : unlock
* : <=0 : lock
@@ -264,13 +200,10 @@ static inline void _raw_read_lock(rwlock_t *rw)
);
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
unsigned long tmp0, tmp1, tmp2;
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
/*
* rw->lock : =RW_LOCK_BIAS_STR : unlock
* : !=RW_LOCK_BIAS_STR : lock
@@ -320,7 +253,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
);
}
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned long tmp0, tmp1;
@@ -342,7 +275,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
);
}
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
unsigned long tmp0, tmp1, tmp2;
@@ -366,9 +299,9 @@ static inline void _raw_write_unlock(rwlock_t *rw)
);
}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
if (atomic_sub_and_test(RW_LOCK_BIAS, count))
diff --git a/include/asm-m32r/spinlock_types.h b/include/asm-m32r/spinlock_types.h
new file mode 100644
index 000000000000..7e9941c45f40
--- /dev/null
+++ b/include/asm-m32r/spinlock_types.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_M32R_SPINLOCK_TYPES_H
+#define _ASM_M32R_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+typedef struct {
+ volatile int lock;
+} raw_rwlock_t;
+
+#define RW_LOCK_BIAS 0x01000000
+#define RW_LOCK_BIAS_STR "0x01000000"
+
+#define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
+
+#endif
diff --git a/include/asm-m32r/types.h b/include/asm-m32r/types.h
index ca0a887d2237..fcf24c64c3ba 100644
--- a/include/asm-m32r/types.h
+++ b/include/asm-m32r/types.h
@@ -55,8 +55,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u64 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index bbb8ac4018a0..93d863c455a1 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -120,31 +120,6 @@ static inline int access_ok(int type, const void *addr, unsigned long size)
}
#endif /* CONFIG_MMU */
-/**
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only. This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void __user *addr,
- unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-m68k/auxvec.h b/include/asm-m68k/auxvec.h
new file mode 100644
index 000000000000..844d6d52204b
--- /dev/null
+++ b/include/asm-m68k/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index e4773946f10d..8aba971b1368 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -130,20 +130,25 @@ static inline void __flush_page_to_ram(void *vaddr)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page))
-#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr, page_to_pfn(page));\
- memcpy(dst, src, len); \
- } while (0)
-
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr, page_to_pfn(page));\
- memcpy(dst, src, len); \
- } while (0)
+extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+ unsigned long addr, int len);
extern void flush_icache_range(unsigned long address, unsigned long endaddr);
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr,
+ void *dst, void *src, int len)
+{
+ flush_cache_page(vma, vaddr, page_to_pfn(page));
+ memcpy(dst, src, len);
+ flush_icache_user_range(vma, page, vaddr, len);
+}
+static inline void copy_from_user_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vaddr,
+ void *dst, void *src, int len)
+{
+ flush_cache_page(vma, vaddr, page_to_pfn(page));
+ memcpy(dst, src, len);
+}
+
#endif /* _M68K_CACHEFLUSH_H */
diff --git a/include/asm-m68k/fcntl.h b/include/asm-m68k/fcntl.h
index 0d4212983a33..1c369b20dc45 100644
--- a/include/asm-m68k/fcntl.h
+++ b/include/asm-m68k/fcntl.h
@@ -1,87 +1,11 @@
#ifndef _M68K_FCNTL_H
#define _M68K_FCNTL_H
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
-#define O_NOATIME 01000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
+#include <asm-generic/fcntl.h>
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
#endif /* _M68K_FCNTL_H */
diff --git a/include/asm-m68k/futex.h b/include/asm-m68k/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-m68k/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-m68k/hdreg.h b/include/asm-m68k/hdreg.h
deleted file mode 100644
index 5989bbc97cbf..000000000000
--- a/include/asm-m68k/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index 206313e2a817..f206dfbc1d48 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -107,20 +107,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#endif /* !__ASSEMBLY__ */
#include <asm/page_offset.h>
@@ -192,4 +178,6 @@ static inline void *__va(unsigned long x)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _M68K_PAGE_H */
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 0c87fc84f7a4..add129e93fd7 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -141,9 +141,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
index 8d0b9fc2d07e..f578ca4b776a 100644
--- a/include/asm-m68k/socket.h
+++ b/include/asm-m68k/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-m68k/string.h b/include/asm-m68k/string.h
index 44def078132a..6c59215b285e 100644
--- a/include/asm-m68k/string.h
+++ b/include/asm-m68k/string.h
@@ -80,43 +80,6 @@ static inline char * strchr(const char * s, int c)
return( (char *) s);
}
-#if 0
-#define __HAVE_ARCH_STRPBRK
-static inline char *strpbrk(const char *cs,const char *ct)
-{
- const char *sc1,*sc2;
-
- for( sc1 = cs; *sc1 != '\0'; ++sc1)
- for( sc2 = ct; *sc2 != '\0'; ++sc2)
- if (*sc1 == *sc2)
- return((char *) sc1);
- return( NULL );
-}
-#endif
-
-#if 0
-#define __HAVE_ARCH_STRSPN
-static inline size_t strspn(const char *s, const char *accept)
-{
- const char *p;
- const char *a;
- size_t count = 0;
-
- for (p = s; *p != '\0'; ++p)
- {
- for (a = accept; *a != '\0'; ++a)
- if (*p == *a)
- break;
- if (*a == '\0')
- return count;
- else
- ++count;
- }
-
- return count;
-}
-#endif
-
/* strstr !! */
#define __HAVE_ARCH_STRLEN
@@ -173,370 +136,18 @@ static inline int strncmp(const char * cs,const char * ct,size_t count)
}
#define __HAVE_ARCH_MEMSET
-/*
- * This is really ugly, but its highly optimizatiable by the
- * compiler and is meant as compensation for gcc's missing
- * __builtin_memset(). For the 680[23]0 it might be worth considering
- * the optimal number of misaligned writes compared to the number of
- * tests'n'branches needed to align the destination address. The
- * 680[46]0 doesn't really care due to their copy-back caches.
- * 10/09/96 - Jes Sorensen
- */
-static inline void * __memset_g(void * s, int c, size_t count)
-{
- void *xs = s;
- size_t temp;
-
- if (!count)
- return xs;
-
- c &= 0xff;
- c |= c << 8;
- c |= c << 16;
-
- if (count < 36){
- long *ls = s;
-
- switch(count){
- case 32: case 33: case 34: case 35:
- *ls++ = c;
- case 28: case 29: case 30: case 31:
- *ls++ = c;
- case 24: case 25: case 26: case 27:
- *ls++ = c;
- case 20: case 21: case 22: case 23:
- *ls++ = c;
- case 16: case 17: case 18: case 19:
- *ls++ = c;
- case 12: case 13: case 14: case 15:
- *ls++ = c;
- case 8: case 9: case 10: case 11:
- *ls++ = c;
- case 4: case 5: case 6: case 7:
- *ls++ = c;
- break;
- default:
- break;
- }
- s = ls;
- if (count & 0x02){
- short *ss = s;
- *ss++ = c;
- s = ss;
- }
- if (count & 0x01){
- char *cs = s;
- *cs++ = c;
- s = cs;
- }
- return xs;
- }
-
- if ((long) s & 1)
- {
- char *cs = s;
- *cs++ = c;
- s = cs;
- count--;
- }
- if (count > 2 && (long) s & 2)
- {
- short *ss = s;
- *ss++ = c;
- s = ss;
- count -= 2;
- }
- temp = count >> 2;
- if (temp)
- {
- long *ls = s;
- temp--;
- do
- *ls++ = c;
- while (temp--);
- s = ls;
- }
- if (count & 2)
- {
- short *ss = s;
- *ss++ = c;
- s = ss;
- }
- if (count & 1)
- {
- char *cs = s;
- *cs = c;
- }
- return xs;
-}
-
-/*
- * __memset_page assumes that data is longword aligned. Most, if not
- * all, of these page sized memsets are performed on page aligned
- * areas, thus we do not need to check if the destination is longword
- * aligned. Of course we suffer a serious performance loss if this is
- * not the case but I think the risk of this ever happening is
- * extremely small. We spend a lot of time clearing pages in
- * get_empty_page() so I think it is worth it anyway. Besides, the
- * 680[46]0 do not really care about misaligned writes due to their
- * copy-back cache.
- *
- * The optimized case for the 680[46]0 is implemented using the move16
- * instruction. My tests showed that this implementation is 35-45%
- * faster than the original implementation using movel, the only
- * caveat is that the destination address must be 16-byte aligned.
- * 01/09/96 - Jes Sorensen
- */
-static inline void * __memset_page(void * s,int c,size_t count)
-{
- unsigned long data, tmp;
- void *xs = s;
-
- c = c & 255;
- data = c | (c << 8);
- data |= data << 16;
-
-#ifdef CPU_M68040_OR_M68060_ONLY
-
- if (((unsigned long) s) & 0x0f)
- __memset_g(s, c, count);
- else{
- unsigned long *sp = s;
- *sp++ = data;
- *sp++ = data;
- *sp++ = data;
- *sp++ = data;
-
- __asm__ __volatile__("1:\t"
- ".chip 68040\n\t"
- "move16 %2@+,%0@+\n\t"
- ".chip 68k\n\t"
- "subqw #8,%2\n\t"
- "subqw #8,%2\n\t"
- "dbra %1,1b\n\t"
- : "=a" (sp), "=d" (tmp)
- : "a" (s), "0" (sp), "1" ((count - 16) / 16 - 1)
- );
- }
-
-#else
- __asm__ __volatile__("1:\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "movel %2,%0@+\n\t"
- "dbra %1,1b\n\t"
- : "=a" (s), "=d" (tmp)
- : "d" (data), "0" (s), "1" (count / 32 - 1)
- );
-#endif
-
- return xs;
-}
-
-extern void *memset(void *,int,__kernel_size_t);
-
-#define __memset_const(s,c,count) \
-((count==PAGE_SIZE) ? \
- __memset_page((s),(c),(count)) : \
- __memset_g((s),(c),(count)))
-
-#define memset(s, c, count) \
-(__builtin_constant_p(count) ? \
- __memset_const((s),(c),(count)) : \
- __memset_g((s),(c),(count)))
+extern void *memset(void *, int, __kernel_size_t);
+#define memset(d, c, n) __builtin_memset(d, c, n)
#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, size_t );
-/*
- * __builtin_memcpy() does not handle page-sized memcpys very well,
- * thus following the same assumptions as for page-sized memsets, this
- * function copies page-sized areas using an unrolled loop, without
- * considering alignment.
- *
- * For the 680[46]0 only kernels we use the move16 instruction instead
- * as it writes through the data-cache, invalidating the cache-lines
- * touched. In this way we do not use up the entire data-cache (well,
- * half of it on the 68060) by copying a page. An unrolled loop of two
- * move16 instructions seem to the fastest. The only caveat is that
- * both source and destination must be 16-byte aligned, if not we fall
- * back to the generic memcpy function. - Jes
- */
-static inline void * __memcpy_page(void * to, const void * from, size_t count)
-{
- unsigned long tmp;
- void *xto = to;
-
-#ifdef CPU_M68040_OR_M68060_ONLY
-
- if (((unsigned long) to | (unsigned long) from) & 0x0f)
- return memcpy(to, from, count);
-
- __asm__ __volatile__("1:\t"
- ".chip 68040\n\t"
- "move16 %1@+,%0@+\n\t"
- "move16 %1@+,%0@+\n\t"
- ".chip 68k\n\t"
- "dbra %2,1b\n\t"
- : "=a" (to), "=a" (from), "=d" (tmp)
- : "0" (to), "1" (from) , "2" (count / 32 - 1)
- );
-#else
- __asm__ __volatile__("1:\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+\n\t"
- "dbra %2,1b\n\t"
- : "=a" (to), "=a" (from), "=d" (tmp)
- : "0" (to), "1" (from) , "2" (count / 32 - 1)
- );
-#endif
- return xto;
-}
-
-#define __memcpy_const(to, from, n) \
-((n==PAGE_SIZE) ? \
- __memcpy_page((to),(from),(n)) : \
- __builtin_memcpy((to),(from),(n)))
-
-#define memcpy(to, from, n) \
-(__builtin_constant_p(n) ? \
- __memcpy_const((to),(from),(n)) : \
- memcpy((to),(from),(n)))
+extern void *memcpy(void *, const void *, __kernel_size_t);
+#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
#define __HAVE_ARCH_MEMMOVE
-static inline void * memmove(void * dest,const void * src, size_t n)
-{
- void *xdest = dest;
- size_t temp;
-
- if (!n)
- return xdest;
-
- if (dest < src)
- {
- if ((long) dest & 1)
- {
- char *cdest = dest;
- const char *csrc = src;
- *cdest++ = *csrc++;
- dest = cdest;
- src = csrc;
- n--;
- }
- if (n > 2 && (long) dest & 2)
- {
- short *sdest = dest;
- const short *ssrc = src;
- *sdest++ = *ssrc++;
- dest = sdest;
- src = ssrc;
- n -= 2;
- }
- temp = n >> 2;
- if (temp)
- {
- long *ldest = dest;
- const long *lsrc = src;
- temp--;
- do
- *ldest++ = *lsrc++;
- while (temp--);
- dest = ldest;
- src = lsrc;
- }
- if (n & 2)
- {
- short *sdest = dest;
- const short *ssrc = src;
- *sdest++ = *ssrc++;
- dest = sdest;
- src = ssrc;
- }
- if (n & 1)
- {
- char *cdest = dest;
- const char *csrc = src;
- *cdest = *csrc;
- }
- }
- else
- {
- dest = (char *) dest + n;
- src = (const char *) src + n;
- if ((long) dest & 1)
- {
- char *cdest = dest;
- const char *csrc = src;
- *--cdest = *--csrc;
- dest = cdest;
- src = csrc;
- n--;
- }
- if (n > 2 && (long) dest & 2)
- {
- short *sdest = dest;
- const short *ssrc = src;
- *--sdest = *--ssrc;
- dest = sdest;
- src = ssrc;
- n -= 2;
- }
- temp = n >> 2;
- if (temp)
- {
- long *ldest = dest;
- const long *lsrc = src;
- temp--;
- do
- *--ldest = *--lsrc;
- while (temp--);
- dest = ldest;
- src = lsrc;
- }
- if (n & 2)
- {
- short *sdest = dest;
- const short *ssrc = src;
- *--sdest = *--ssrc;
- dest = sdest;
- src = ssrc;
- }
- if (n & 1)
- {
- char *cdest = dest;
- const char *csrc = src;
- *--cdest = *--csrc;
- }
- }
- return xdest;
-}
+extern void *memmove(void *, const void *, __kernel_size_t);
#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void * ,const void * ,size_t );
-#define memcmp(cs, ct, n) \
-(__builtin_constant_p(n) ? \
- __builtin_memcmp((cs),(ct),(n)) : \
- memcmp((cs),(ct),(n)))
-
-#define __HAVE_ARCH_MEMCHR
-static inline void *memchr(const void *cs, int c, size_t count)
-{
- /* Someone else can optimize this, I don't care - tonym@mac.linux-m68k.org */
- unsigned char *ret = (unsigned char *)cs;
- for(;count>0;count--,ret++)
- if(*ret == c) return ret;
-
- return NULL;
-}
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
#endif /* _M68K_STRING_H_ */
diff --git a/include/asm-m68k/types.h b/include/asm-m68k/types.h
index f391cbe39b96..b5a1febc97d4 100644
--- a/include/asm-m68k/types.h
+++ b/include/asm-m68k/types.h
@@ -60,8 +60,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index 605e6cb811f8..f5cedf19cf68 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -14,12 +14,6 @@
/* We let the MMU do all checking */
#define access_ok(type,addr,size) 1
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-m68knommu/auxvec.h b/include/asm-m68knommu/auxvec.h
new file mode 100644
index 000000000000..844d6d52204b
--- /dev/null
+++ b/include/asm-m68knommu/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index f95e32b40425..c42f88a9b9f9 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -259,7 +259,7 @@ static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
#define find_first_bit(addr, size) \
find_next_bit((addr), (size), 0)
-static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (const void * addr, int size, int offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index aa7a2ffa41af..026bbc9565b4 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -2,23 +2,23 @@
#define _M68KNOMMU_CACHEFLUSH_H
/*
- * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
+ * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
*/
#include <linux/mm.h>
#define flush_cache_all() __flush_cache_all()
#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
-#define flush_dcache_range(start,len) do { } while (0)
+#define flush_cache_range(vma, start, end) __flush_cache_all()
+#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_dcache_range(start,len) __flush_cache_all()
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_range(start,len) __flush_cache_all()
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
-#define flush_cache_vmap(start, end) flush_cache_all()
-#define flush_cache_vunmap(start, end) flush_cache_all()
+#define flush_cache_vmap(start, end) do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
@@ -50,22 +50,23 @@ extern inline void __flush_cache_all(void)
"movec %%d0,%%CACR\n\t"
: : : "d0", "a0" );
#endif /* CONFIG_M5407 */
-#ifdef CONFIG_M5272
+#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
__asm__ __volatile__ (
- "movel #0x01000000, %%d0\n\t"
- "movec %%d0, %%CACR\n\t"
- "nop\n\t"
- "movel #0x80000100, %%d0\n\t"
+ "movel #0x81400100, %%d0\n\t"
"movec %%d0, %%CACR\n\t"
"nop\n\t"
: : : "d0" );
-#endif /* CONFIG_M5272 */
-#if 0 /* CONFIG_M5249 */
+#endif /* CONFIG_M527x || CONFIG_M528x */
+#ifdef CONFIG_M5272
__asm__ __volatile__ (
"movel #0x01000000, %%d0\n\t"
"movec %%d0, %%CACR\n\t"
"nop\n\t"
- "movel #0xa0000200, %%d0\n\t"
+ : : : "d0" );
+#endif /* CONFIG_M5272 */
+#if CONFIG_M5249
+ __asm__ __volatile__ (
+ "movel #0xa1000200, %%d0\n\t"
"movec %%d0, %%CACR\n\t"
"nop\n\t"
: : : "d0" );
diff --git a/include/asm-m68knommu/checksum.h b/include/asm-m68knommu/checksum.h
index 92cf102c2534..294ec7583ac9 100644
--- a/include/asm-m68knommu/checksum.h
+++ b/include/asm-m68knommu/checksum.h
@@ -25,7 +25,8 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+ int len, int sum);
/*
@@ -35,8 +36,8 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
- int len, int sum, int *csum_err);
+extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+ unsigned char *dst, int len, int sum, int *csum_err);
#define csum_partial_copy_nocheck(src, dst, len, sum) \
csum_partial_copy((src), (dst), (len), (sum))
diff --git a/include/asm-m68knommu/coldfire.h b/include/asm-m68knommu/coldfire.h
index 16f32cc80c40..1df3f666a28e 100644
--- a/include/asm-m68knommu/coldfire.h
+++ b/include/asm-m68knommu/coldfire.h
@@ -22,7 +22,7 @@
#define MCF_MBAR2 0x80000000
#define MCF_IPSBAR 0x40000000
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#undef MCF_MBAR
#define MCF_MBAR MCF_IPSBAR
#endif
@@ -54,6 +54,8 @@
#define MCF_CLK 54000000
#elif defined(CONFIG_CLOCK_60MHz)
#define MCF_CLK 60000000
+#elif defined(CONFIG_CLOCK_62_5MHz)
+#define MCF_CLK 62500000
#elif defined(CONFIG_CLOCK_64MHz)
#define MCF_CLK 64000000
#elif defined(CONFIG_CLOCK_66MHz)
@@ -76,7 +78,7 @@
* One some ColdFire family members the bus clock (used by internal
* peripherals) is not the same as the CPU clock.
*/
-#if defined(CONFIG_M5249) || defined(CONFIG_M527x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M5249) || defined(CONFIG_M527x)
#define MCF_BUSCLK (MCF_CLK / 2)
#else
#define MCF_BUSCLK MCF_CLK
diff --git a/include/asm-m68knommu/futex.h b/include/asm-m68knommu/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-m68knommu/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-m68knommu/hdreg.h b/include/asm-m68knommu/hdreg.h
deleted file mode 100644
index 5cdd9b084d37..000000000000
--- a/include/asm-m68knommu/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/hdreg.h>
diff --git a/include/asm-m68knommu/m523xsim.h b/include/asm-m68knommu/m523xsim.h
new file mode 100644
index 000000000000..926cfb805df7
--- /dev/null
+++ b/include/asm-m68knommu/m523xsim.h
@@ -0,0 +1,46 @@
+/****************************************************************************/
+
+/*
+ * m523xsim.h -- ColdFire 523x System Integration Module support.
+ *
+ * (C) Copyright 2003-2005, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/****************************************************************************/
+#ifndef m523xsim_h
+#define m523xsim_h
+/****************************************************************************/
+
+#include <linux/config.h>
+
+/*
+ * Define the 523x SIM register set addresses.
+ */
+#define MCFICM_INTC0 0x0c00 /* Base for Interrupt Ctrl 0 */
+#define MCFICM_INTC1 0x0d00 /* Base for Interrupt Ctrl 0 */
+#define MCFINTC_IPRH 0x00 /* Interrupt pending 32-63 */
+#define MCFINTC_IPRL 0x04 /* Interrupt pending 1-31 */
+#define MCFINTC_IMRH 0x08 /* Interrupt mask 32-63 */
+#define MCFINTC_IMRL 0x0c /* Interrupt mask 1-31 */
+#define MCFINTC_INTFRCH 0x10 /* Interrupt force 32-63 */
+#define MCFINTC_INTFRCL 0x14 /* Interrupt force 1-31 */
+#define MCFINTC_IRLR 0x18 /* */
+#define MCFINTC_IACKL 0x19 /* */
+#define MCFINTC_ICR0 0x40 /* Base ICR register */
+
+#define MCFINT_VECBASE 64 /* Vector base number */
+#define MCFINT_UART0 13 /* Interrupt number for UART0 */
+#define MCFINT_PIT1 36 /* Interrupt number for PIT1 */
+#define MCFINT_QSPI 18 /* Interrupt number for QSPI */
+
+/*
+ * SDRAM configuration registers.
+ */
+#define MCFSIM_DCR 0x44 /* SDRAM control */
+#define MCFSIM_DACR0 0x48 /* SDRAM base address 0 */
+#define MCFSIM_DMR0 0x4c /* SDRAM address mask 0 */
+#define MCFSIM_DACR1 0x50 /* SDRAM base address 1 */
+#define MCFSIM_DMR1 0x54 /* SDRAM address mask 1 */
+
+/****************************************************************************/
+#endif /* m523xsim_h */
diff --git a/include/asm-m68knommu/m527xsim.h b/include/asm-m68knommu/m527xsim.h
index d280d013da03..e7878d0f7d7a 100644
--- a/include/asm-m68knommu/m527xsim.h
+++ b/include/asm-m68knommu/m527xsim.h
@@ -37,13 +37,14 @@
/*
* SDRAM configuration registers.
*/
-#ifdef CONFIG_M5271EVB
+#ifdef CONFIG_M5271
#define MCFSIM_DCR 0x40 /* SDRAM control */
#define MCFSIM_DACR0 0x48 /* SDRAM base address 0 */
#define MCFSIM_DMR0 0x4c /* SDRAM address mask 0 */
#define MCFSIM_DACR1 0x50 /* SDRAM base address 1 */
#define MCFSIM_DMR1 0x54 /* SDRAM address mask 1 */
-#else
+#endif
+#ifdef CONFIG_M5275
#define MCFSIM_DMR 0x40 /* SDRAM mode */
#define MCFSIM_DCR 0x44 /* SDRAM control */
#define MCFSIM_DCFG1 0x48 /* SDRAM configuration 1 */
@@ -54,5 +55,21 @@
#define MCFSIM_DMR1 0x5c /* SDRAM address mask 1 */
#endif
+/*
+ * GPIO pins setups to enable the UARTs.
+ */
+#ifdef CONFIG_M5271
+#define MCF_GPIO_PAR_UART 0x100048 /* PAR UART address */
+#define UART0_ENABLE_MASK 0x000f
+#define UART1_ENABLE_MASK 0x0ff0
+#define UART2_ENABLE_MASK 0x3000
+#endif
+#ifdef CONFIG_M5275
+#define MCF_GPIO_PAR_UART 0x10007c /* PAR UART address */
+#define UART0_ENABLE_MASK 0x000f
+#define UART1_ENABLE_MASK 0x00f0
+#define UART2_ENABLE_MASK 0x3f00
+#endif
+
/****************************************************************************/
#endif /* m527xsim_h */
diff --git a/include/asm-m68knommu/m528xsim.h b/include/asm-m68knommu/m528xsim.h
index 371993a206ac..610774a17f70 100644
--- a/include/asm-m68knommu/m528xsim.h
+++ b/include/asm-m68knommu/m528xsim.h
@@ -41,5 +41,117 @@
#define MCFSIM_DACR1 0x50 /* SDRAM base address 1 */
#define MCFSIM_DMR1 0x54 /* SDRAM address mask 1 */
+/*
+ * Derek Cheung - 6 Feb 2005
+ * add I2C and QSPI register definition using Freescale's MCF5282
+ */
+/* set Port AS pin for I2C or UART */
+#define MCF5282_GPIO_PASPAR (volatile u16 *) (MCF_IPSBAR + 0x00100056)
+
+/* Interrupt Mask Register Register Low */
+#define MCF5282_INTC0_IMRL (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
+/* Interrupt Control Register 7 */
+#define MCF5282_INTC0_ICR17 (volatile u8 *) (MCF_IPSBAR + 0x0C51)
+
+
+
+/*********************************************************************
+*
+* Inter-IC (I2C) Module
+*
+*********************************************************************/
+/* Read/Write access macros for general use */
+#define MCF5282_I2C_I2ADR (volatile u8 *) (MCF_IPSBAR + 0x0300) // Address
+#define MCF5282_I2C_I2FDR (volatile u8 *) (MCF_IPSBAR + 0x0304) // Freq Divider
+#define MCF5282_I2C_I2CR (volatile u8 *) (MCF_IPSBAR + 0x0308) // Control
+#define MCF5282_I2C_I2SR (volatile u8 *) (MCF_IPSBAR + 0x030C) // Status
+#define MCF5282_I2C_I2DR (volatile u8 *) (MCF_IPSBAR + 0x0310) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF5282_I2C_I2ADR_ADDR(x) (((x)&0x7F)<<0x01)
+
+#define MCF5282_I2C_I2FDR_IC(x) (((x)&0x3F))
+
+#define MCF5282_I2C_I2CR_IEN (0x80) // I2C enable
+#define MCF5282_I2C_I2CR_IIEN (0x40) // interrupt enable
+#define MCF5282_I2C_I2CR_MSTA (0x20) // master/slave mode
+#define MCF5282_I2C_I2CR_MTX (0x10) // transmit/receive mode
+#define MCF5282_I2C_I2CR_TXAK (0x08) // transmit acknowledge enable
+#define MCF5282_I2C_I2CR_RSTA (0x04) // repeat start
+
+#define MCF5282_I2C_I2SR_ICF (0x80) // data transfer bit
+#define MCF5282_I2C_I2SR_IAAS (0x40) // I2C addressed as a slave
+#define MCF5282_I2C_I2SR_IBB (0x20) // I2C bus busy
+#define MCF5282_I2C_I2SR_IAL (0x10) // aribitration lost
+#define MCF5282_I2C_I2SR_SRW (0x04) // slave read/write
+#define MCF5282_I2C_I2SR_IIF (0x02) // I2C interrupt
+#define MCF5282_I2C_I2SR_RXAK (0x01) // received acknowledge
+
+
+
+/*********************************************************************
+*
+* Queued Serial Peripheral Interface (QSPI) Module
+*
+*********************************************************************/
+/* Derek - 21 Feb 2005 */
+/* change to the format used in I2C */
+/* Read/Write access macros for general use */
+#define MCF5282_QSPI_QMR MCF_IPSBAR + 0x0340
+#define MCF5282_QSPI_QDLYR MCF_IPSBAR + 0x0344
+#define MCF5282_QSPI_QWR MCF_IPSBAR + 0x0348
+#define MCF5282_QSPI_QIR MCF_IPSBAR + 0x034C
+#define MCF5282_QSPI_QAR MCF_IPSBAR + 0x0350
+#define MCF5282_QSPI_QDR MCF_IPSBAR + 0x0354
+#define MCF5282_QSPI_QCR MCF_IPSBAR + 0x0354
+
+/* Bit level definitions and macros */
+#define MCF5282_QSPI_QMR_MSTR (0x8000)
+#define MCF5282_QSPI_QMR_DOHIE (0x4000)
+#define MCF5282_QSPI_QMR_BITS_16 (0x0000)
+#define MCF5282_QSPI_QMR_BITS_8 (0x2000)
+#define MCF5282_QSPI_QMR_BITS_9 (0x2400)
+#define MCF5282_QSPI_QMR_BITS_10 (0x2800)
+#define MCF5282_QSPI_QMR_BITS_11 (0x2C00)
+#define MCF5282_QSPI_QMR_BITS_12 (0x3000)
+#define MCF5282_QSPI_QMR_BITS_13 (0x3400)
+#define MCF5282_QSPI_QMR_BITS_14 (0x3800)
+#define MCF5282_QSPI_QMR_BITS_15 (0x3C00)
+#define MCF5282_QSPI_QMR_CPOL (0x0200)
+#define MCF5282_QSPI_QMR_CPHA (0x0100)
+#define MCF5282_QSPI_QMR_BAUD(x) (((x)&0x00FF))
+
+#define MCF5282_QSPI_QDLYR_SPE (0x80)
+#define MCF5282_QSPI_QDLYR_QCD(x) (((x)&0x007F)<<8)
+#define MCF5282_QSPI_QDLYR_DTL(x) (((x)&0x00FF))
+
+#define MCF5282_QSPI_QWR_HALT (0x8000)
+#define MCF5282_QSPI_QWR_WREN (0x4000)
+#define MCF5282_QSPI_QWR_WRTO (0x2000)
+#define MCF5282_QSPI_QWR_CSIV (0x1000)
+#define MCF5282_QSPI_QWR_ENDQP(x) (((x)&0x000F)<<8)
+#define MCF5282_QSPI_QWR_CPTQP(x) (((x)&0x000F)<<4)
+#define MCF5282_QSPI_QWR_NEWQP(x) (((x)&0x000F))
+
+#define MCF5282_QSPI_QIR_WCEFB (0x8000)
+#define MCF5282_QSPI_QIR_ABRTB (0x4000)
+#define MCF5282_QSPI_QIR_ABRTL (0x1000)
+#define MCF5282_QSPI_QIR_WCEFE (0x0800)
+#define MCF5282_QSPI_QIR_ABRTE (0x0400)
+#define MCF5282_QSPI_QIR_SPIFE (0x0100)
+#define MCF5282_QSPI_QIR_WCEF (0x0008)
+#define MCF5282_QSPI_QIR_ABRT (0x0004)
+#define MCF5282_QSPI_QIR_SPIF (0x0001)
+
+#define MCF5282_QSPI_QAR_ADDR(x) (((x)&0x003F))
+
+#define MCF5282_QSPI_QDR_COMMAND(x) (((x)&0xFF00))
+#define MCF5282_QSPI_QCR_DATA(x) (((x)&0x00FF)<<8)
+#define MCF5282_QSPI_QCR_CONT (0x8000)
+#define MCF5282_QSPI_QCR_BITSE (0x4000)
+#define MCF5282_QSPI_QCR_DT (0x2000)
+#define MCF5282_QSPI_QCR_DSCK (0x1000)
+#define MCF5282_QSPI_QCR_CS (((x)&0x000F)<<8)
+
/****************************************************************************/
#endif /* m528xsim_h */
diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
index bdd8c53ef34c..b17cd920977f 100644
--- a/include/asm-m68knommu/mcfcache.h
+++ b/include/asm-m68knommu/mcfcache.h
@@ -33,7 +33,7 @@
.endm
#endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
-#if defined(CONFIG_M527x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
/*
* New version 2 cores have a configurable split cache arrangement.
* For now I am just enabling instruction cache - but ultimately I
@@ -51,23 +51,20 @@
movec %d0,%CACR /* enable cache */
nop
.endm
-#endif /* CONFIG_M527x */
+#endif /* CONFIG_M523x || CONFIG_M527x */
#if defined(CONFIG_M528x)
-/*
- * Cache is totally broken on early 5282 silicon. So far now we
- * disable its cache all together.
- */
.macro CACHE_ENABLE
- movel #0x01000000,%d0
- movec %d0,%CACR /* invalidate cache */
nop
- movel #0x0000c000,%d0 /* set SDRAM cached only */
- movec %d0,%ACR0
- movel #0x00000000,%d0 /* no other regions cached */
- movec %d0,%ACR1
- movel #0x00000000,%d0 /* configure cache */
- movec %d0,%CACR /* enable cache */
+ movel #0x01000000, %d0
+ movec %d0, %CACR /* Invalidate cache */
+ nop
+ movel #0x0000c020, %d0 /* Set SDRAM cached only */
+ movec %d0, %ACR0
+ movel #0xff00c000, %d0 /* Cache Flash also */
+ movec %d0, %ACR1
+ movel #0x80000200, %d0 /* Setup cache mask */
+ movec %d0, %CACR /* Enable cache */
nop
.endm
#endif /* CONFIG_M528x */
diff --git a/include/asm-m68knommu/mcfdma.h b/include/asm-m68knommu/mcfdma.h
index 350c6090b5c1..b93f8ba8a248 100644
--- a/include/asm-m68knommu/mcfdma.h
+++ b/include/asm-m68knommu/mcfdma.h
@@ -21,7 +21,7 @@
#define MCFDMA_BASE1 0x240 /* Base address of DMA 1 */
#elif defined(CONFIG_M5272)
#define MCFDMA_BASE0 0x0e0 /* Base address of DMA 0 */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/* These are relative to the IPSBAR, not MBAR */
#define MCFDMA_BASE0 0x100 /* Base address of DMA 0 */
#define MCFDMA_BASE1 0x140 /* Base address of DMA 1 */
diff --git a/include/asm-m68knommu/mcfsim.h b/include/asm-m68knommu/mcfsim.h
index 522e513c2bc6..b0c7736f7a99 100644
--- a/include/asm-m68knommu/mcfsim.h
+++ b/include/asm-m68knommu/mcfsim.h
@@ -15,13 +15,15 @@
#include <linux/config.h>
/*
- * Include 5204, 5206/e, 5249, 5270/5271, 5272, 5280/5282, 5307 or
- * 5407 specific addresses.
+ * Include 5204, 5206/e, 5235, 5249, 5270/5271, 5272, 5280/5282,
+ * 5307 or 5407 specific addresses.
*/
#if defined(CONFIG_M5204)
#include <asm/m5204sim.h>
#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e)
#include <asm/m5206sim.h>
+#elif defined(CONFIG_M523x)
+#include <asm/m523xsim.h>
#elif defined(CONFIG_M5249)
#include <asm/m5249sim.h>
#elif defined(CONFIG_M527x)
diff --git a/include/asm-m68knommu/mcfuart.h b/include/asm-m68knommu/mcfuart.h
index 54d4a85f4fdf..9c1210613bc7 100644
--- a/include/asm-m68knommu/mcfuart.h
+++ b/include/asm-m68knommu/mcfuart.h
@@ -29,7 +29,7 @@
#define MCFUART_BASE1 0x140 /* Base address of UART1 */
#define MCFUART_BASE2 0x180 /* Base address of UART2 */
#endif
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define MCFUART_BASE1 0x200 /* Base address of UART1 */
#define MCFUART_BASE2 0x240 /* Base address of UART2 */
#define MCFUART_BASE3 0x280 /* Base address of UART3 */
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 05e03df0ec29..942dfbead27f 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -48,20 +48,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
extern unsigned long memory_start;
extern unsigned long memory_end;
@@ -73,8 +59,8 @@ extern unsigned long memory_end;
#ifndef __ASSEMBLY__
-#define __pa(vaddr) virt_to_phys((void *)vaddr)
-#define __va(paddr) phys_to_virt((unsigned long)paddr)
+#define __pa(vaddr) virt_to_phys((void *)(vaddr))
+#define __va(paddr) phys_to_virt((unsigned long)(paddr))
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
@@ -84,6 +70,7 @@ extern unsigned long memory_end;
#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 pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
((void *)(kaddr) < (void *)memory_end))
@@ -92,4 +79,6 @@ extern unsigned long memory_end;
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _M68KNOMMU_PAGE_H */
diff --git a/include/asm-m68knommu/pgtable.h b/include/asm-m68knommu/pgtable.h
index e2a69fffa370..00893055e6c2 100644
--- a/include/asm-m68knommu/pgtable.h
+++ b/include/asm-m68knommu/pgtable.h
@@ -56,8 +56,6 @@ extern int is_in_rom(unsigned long);
* No page table caches to initialise.
*/
#define pgtable_cache_init() do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h
index 230b8d56d17f..12309b181d29 100644
--- a/include/asm-m68knommu/scatterlist.h
+++ b/include/asm-m68knommu/scatterlist.h
@@ -1,6 +1,8 @@
#ifndef _M68KNOMMU_SCATTERLIST_H
#define _M68KNOMMU_SCATTERLIST_H
+#include <linux/mm.h>
+
struct scatterlist {
struct page *page;
unsigned int offset;
@@ -8,6 +10,10 @@ struct scatterlist {
unsigned int length;
};
+#define sg_address(sg) (page_address((sg)->page) + (sg)->offset
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
#define ISA_DMA_THRESHOLD (0xffffffff)
#endif /* !(_M68KNOMMU_SCATTERLIST_H) */
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index c341b66c147b..53cbbad0f130 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -57,9 +57,18 @@ asmlinkage void resume(void);
: "cc", "%d0", "memory")
#define local_irq_disable() __asm__ __volatile__ ( \
"move %/sr,%%d0\n\t" \
- "ori.l #0x0700,%%d0\n\t" \
+ "ori.l #0x0700,%%d0\n\t" \
"move %%d0,%/sr\n" \
- : /* no inputs */ \
+ : /* no outputs */ \
+ : \
+ : "cc", "%d0", "memory")
+/* For spinlocks etc */
+#define local_irq_save(x) __asm__ __volatile__ ( \
+ "movew %%sr,%0\n\t" \
+ "movew #0x0700,%%d0\n\t" \
+ "or.l %0,%%d0\n\t" \
+ "movew %%d0,%/sr" \
+ : "=d" (x) \
: \
: "cc", "%d0", "memory")
#else
@@ -75,7 +84,9 @@ asmlinkage void resume(void);
#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
/* For spinlocks etc */
+#ifndef local_irq_save
#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
+#endif
#define irqs_disabled() \
({ \
@@ -234,9 +245,9 @@ cmpxchg(volatile int *p, int old, int new)
#ifdef CONFIG_COLDFIRE
#if defined(CONFIG_M5272) && defined(CONFIG_NETtel)
/*
- * Need to account for broken early mask of 5272 silicon. So don't
- * jump through the original start address. Jump strait into the
- * known start of the FLASH code.
+ * Need to account for broken early mask of 5272 silicon. So don't
+ * jump through the original start address. Jump strait into the
+ * known start of the FLASH code.
*/
#define HARD_RESET_NOW() ({ \
asm(" \
@@ -244,7 +255,9 @@ cmpxchg(volatile int *p, int old, int new)
jmp 0xf0000400; \
"); \
})
-#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
+#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+ defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
+ defined(CONFIG_CLEOPATRA)
#define HARD_RESET_NOW() ({ \
asm(" \
movew #0x2700, %sr; \
@@ -257,6 +270,26 @@ cmpxchg(volatile int *p, int old, int new)
jmp (%a0); \
"); \
})
+#elif defined(CONFIG_M5272)
+/*
+ * Retrieve the boot address in flash using CSBR0 and CSOR0
+ * find the reset vector at flash_address + 4 (e.g. 0x400)
+ * remap it in the flash's current location (e.g. 0xf0000400)
+ * and jump there.
+ */
+#define HARD_RESET_NOW() ({ \
+ asm(" \
+ movew #0x2700, %%sr; \
+ move.l %0+0x40,%%d0; \
+ and.l %0+0x44,%%d0; \
+ andi.l #0xfffff000,%%d0; \
+ mov.l %%d0,%%a0; \
+ or.l 4(%%a0),%%d0; \
+ mov.l %%d0,%%a0; \
+ jmp (%%a0);" \
+ : /* No output */ \
+ : "o" (*(char *)MCF_MBAR) ); \
+})
#elif defined(CONFIG_M528x)
/*
* The MCF528x has a bit (SOFTRST) in memory (Reset Control Register RCR),
@@ -270,6 +303,15 @@ cmpxchg(volatile int *p, int old, int new)
while(1) \
*reset |= (0x01 << 7);\
})
+#elif defined(CONFIG_M523x)
+#define HARD_RESET_NOW() ({ \
+ asm(" \
+ movew #0x2700, %sr; \
+ movel #0x01000000, %sp; \
+ moveal #0x40110000, %a0; \
+ moveb #0x80, (%a0); \
+ "); \
+})
#else
#define HARD_RESET_NOW() ({ \
asm(" \
diff --git a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
index f0be74bb353c..05be9515a2d2 100644
--- a/include/asm-m68knommu/uaccess.h
+++ b/include/asm-m68knommu/uaccess.h
@@ -23,12 +23,6 @@ static inline int _access_ok(unsigned long addr, unsigned long size)
(is_in_rom(addr) && is_in_rom(addr+size)));
}
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
- return access_ok(type,addr,size)?0:-EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-mips/a.out.h b/include/asm-mips/a.out.h
index e42b3093e903..2b3dc3bed4da 100644
--- a/include/asm-mips/a.out.h
+++ b/include/asm-mips/a.out.h
@@ -35,10 +35,10 @@ struct exec
#ifdef __KERNEL__
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define STACK_TOP TASK_SIZE
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
#endif
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 2caa8c427204..7dc2619f5006 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -48,7 +48,7 @@
#define CPHYSADDR(a) ((_ACAST32_ (a)) & 0x1fffffff)
#define XPHYSADDR(a) ((_ACAST64_ (a)) & 0x000000ffffffffff)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* Memory segments (64bit kernel mode addresses)
diff --git a/include/asm-mips/asmmacro-32.h b/include/asm-mips/asmmacro-32.h
index ac8823df2554..11daf5ceb7b4 100644
--- a/include/asm-mips/asmmacro-32.h
+++ b/include/asm-mips/asmmacro-32.h
@@ -7,7 +7,7 @@
#ifndef _ASM_ASMMACRO_32_H
#define _ASM_ASMMACRO_32_H
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
diff --git a/include/asm-mips/asmmacro-64.h b/include/asm-mips/asmmacro-64.h
index bbed35511f5a..559c355b9b86 100644
--- a/include/asm-mips/asmmacro-64.h
+++ b/include/asm-mips/asmmacro-64.h
@@ -8,7 +8,7 @@
#ifndef _ASM_ASMMACRO_64_H
#define _ASM_ASMMACRO_64_H
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 37a460aa0378..30b18ea6cb11 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -7,14 +7,14 @@
*/
#ifndef _ASM_ASMMACRO_H
#define _ASM_ASMMACRO_H
-
+
#include <linux/config.h>
#include <asm/hazards.h>
-
-#ifdef CONFIG_MIPS32
+
+#ifdef CONFIG_32BIT
#include <asm/asmmacro-32.h>
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#include <asm/asmmacro-64.h>
#endif
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 7d89e87bc8c6..c0bd8d014e14 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -334,7 +334,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
*/
#define atomic_add_negative(i,v) (atomic_add_return(i, (v)) < 0)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
typedef struct { volatile __s64 counter; } atomic64_t;
@@ -639,7 +639,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
*/
#define atomic64_add_negative(i,v) (atomic64_add_return(i, (v)) < 0)
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/*
* atomic*_return operations are serializing but not the non-*_return
diff --git a/include/asm-mips/auxvec.h b/include/asm-mips/auxvec.h
new file mode 100644
index 000000000000..7cf7f2d21943
--- /dev/null
+++ b/include/asm-mips/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_AUXVEC_H
+#define _ASM_AUXVEC_H
+
+#endif /* _ASM_AUXVEC_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 779d2187a6a4..eb8d79dba11c 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -20,13 +20,13 @@
#define SZLONG_MASK 31UL
#define __LL "ll "
#define __SC "sc "
-#define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x))
+#define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x))
#elif (_MIPS_SZLONG == 64)
#define SZLONG_LOG 6
#define SZLONG_MASK 63UL
#define __LL "lld "
#define __SC "scd "
-#define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x))
+#define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x))
#endif
#ifdef __KERNEL__
@@ -533,14 +533,14 @@ static inline unsigned long ffz(unsigned long word)
int b = 0, s;
word = ~word;
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s;
s = 8; if (word << 24 != 0) s = 0; b += s; word >>= s;
s = 4; if (word << 28 != 0) s = 0; b += s; word >>= s;
s = 2; if (word << 30 != 0) s = 0; b += s; word >>= s;
s = 1; if (word << 31 != 0) s = 0; b += s;
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
s = 32; if (word << 32 != 0) s = 0; b += s; word >>= s;
s = 16; if (word << 48 != 0) s = 0; b += s; word >>= s;
s = 8; if (word << 56 != 0) s = 0; b += s; word >>= s;
@@ -683,7 +683,7 @@ found_middle:
*/
static inline int sched_find_first_bit(const unsigned long *b)
{
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
if (unlikely(b[0]))
return __ffs(b[0]);
if (unlikely(b[1]))
@@ -694,7 +694,7 @@ static inline int sched_find_first_bit(const unsigned long *b)
return __ffs(b[3]) + 96;
return __ffs(b[4]) + 128;
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
if (unlikely(b[0]))
return __ffs(b[0]);
if (unlikely(b[1]))
diff --git a/include/asm-mips/bugs.h b/include/asm-mips/bugs.h
index 18cced19cca4..b14b961c2100 100644
--- a/include/asm-mips/bugs.h
+++ b/include/asm-mips/bugs.h
@@ -15,7 +15,7 @@ extern void check_bugs64(void);
static inline void check_bugs(void)
{
check_bugs32();
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
check_bugs64();
#endif
}
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index c25cc92b9950..c1ea5a8714f3 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -128,7 +128,7 @@ static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
{
__asm__(
".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
"addu\t%0, %2\n\t"
"sltu\t$1, %0, %2\n\t"
"addu\t%0, $1\n\t"
@@ -141,7 +141,7 @@ static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
"sltu\t$1, %0, %4\n\t"
"addu\t%0, $1\n\t"
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
"daddu\t%0, %2\n\t"
"daddu\t%0, %3\n\t"
"daddu\t%0, %4\n\t"
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index d78002afb1e1..2c084cd4bc0a 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -15,8 +15,10 @@ typedef s32 compat_clock_t;
typedef s32 compat_suseconds_t;
typedef s32 compat_pid_t;
-typedef s32 compat_uid_t;
-typedef s32 compat_gid_t;
+typedef u32 __compat_uid_t;
+typedef u32 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u32 compat_mode_t;
typedef u32 compat_ino_t;
typedef u32 compat_dev_t;
@@ -52,8 +54,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid32_t st_uid;
+ __compat_gid32_t st_gid;
compat_dev_t st_rdev;
s32 st_pad2[2];
compat_off_t st_size;
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 1df2c299de82..9a2de642eee6 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -106,7 +106,7 @@
#define PLAT_TRAMPOLINE_STUFF_LINE 0UL
#endif
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
# ifndef cpu_has_nofpuex
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
# endif
@@ -124,7 +124,7 @@
# endif
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
# ifndef cpu_has_nofpuex
# define cpu_has_nofpuex 0
# endif
diff --git a/include/asm-mips/ddb5xxx/ddb5477.h b/include/asm-mips/ddb5xxx/ddb5477.h
index ae3e2a38fd5f..a438548e6ef3 100644
--- a/include/asm-mips/ddb5xxx/ddb5477.h
+++ b/include/asm-mips/ddb5xxx/ddb5477.h
@@ -247,7 +247,7 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq);
* All PCI irq but INTC are active low.
*/
-/*
+/*
* irq number block assignment
*/
@@ -285,7 +285,7 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq);
#define VRC5477_IRQ_IOPCI_INTB (17 + VRC5477_IRQ_BASE) /* USB-P */
#define VRC5477_IRQ_IOPCI_INTC (18 + VRC5477_IRQ_BASE) /* AC97 */
#define VRC5477_IRQ_IOPCI_INTD (19 + VRC5477_IRQ_BASE) /* Reserved */
-#define VRC5477_IRQ_UART1 (20 + VRC5477_IRQ_BASE)
+#define VRC5477_IRQ_UART1 (20 + VRC5477_IRQ_BASE)
#define VRC5477_IRQ_SPT0 (21 + VRC5477_IRQ_BASE) /* special purpose timer 0 */
#define VRC5477_IRQ_GPT0 (22 + VRC5477_IRQ_BASE) /* general purpose timer 0 */
#define VRC5477_IRQ_GPT1 (23 + VRC5477_IRQ_BASE) /* general purpose timer 1 */
@@ -301,7 +301,7 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq);
/*
* i2859 irq assignment
*/
-#define I8259_IRQ_RESERVED_0 (0 + I8259_IRQ_BASE)
+#define I8259_IRQ_RESERVED_0 (0 + I8259_IRQ_BASE)
#define I8259_IRQ_KEYBOARD (1 + I8259_IRQ_BASE) /* M1543 default */
#define I8259_IRQ_CASCADE (2 + I8259_IRQ_BASE)
#define I8259_IRQ_UART_B (3 + I8259_IRQ_BASE) /* M1543 default, may conflict with RTC according to schematic diagram */
diff --git a/include/asm-mips/dec/prom.h b/include/asm-mips/dec/prom.h
index b63e2f2317d1..a05d6d3395fe 100644
--- a/include/asm-mips/dec/prom.h
+++ b/include/asm-mips/dec/prom.h
@@ -48,15 +48,15 @@
*/
#define REX_PROM_MAGIC 0x30464354
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
-#else /* !CONFIG_MIPS64 */
+#else /* !CONFIG_64BIT */
#define prom_is_rex(magic) ((magic) == REX_PROM_MAGIC)
-#endif /* !CONFIG_MIPS64 */
+#endif /* !CONFIG_64BIT */
/*
@@ -105,7 +105,7 @@ extern int (*__pmax_read)(int, void *, int);
extern int (*__pmax_close)(int);
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* On MIPS64 we have to call PROM functions via a helper
@@ -138,7 +138,7 @@ int _prom_printf(int (*)(char *, ...), char *, ...) __DEC_PROM_O32;
#define prom_getenv(x) _prom_getenv(__prom_getenv, x)
#define prom_printf(x...) _prom_printf(__prom_printf, x)
-#else /* !CONFIG_MIPS64 */
+#else /* !CONFIG_64BIT */
/*
* On plain MIPS we just call PROM functions directly.
@@ -160,7 +160,7 @@ int _prom_printf(int (*)(char *, ...), char *, ...) __DEC_PROM_O32;
#define pmax_read __pmax_read
#define pmax_close __pmax_close
-#endif /* !CONFIG_MIPS64 */
+#endif /* !CONFIG_64BIT */
extern void prom_meminit(u32);
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index d0f68447e5a7..a606dbee0412 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -57,11 +57,11 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj)
* The common rates of 1000 and 128 are rounded wrongly by the
* catchall case for 64-bit. Excessive precission? Probably ...
*/
-#if defined(CONFIG_MIPS64) && (HZ == 128)
+#if defined(CONFIG_64BIT) && (HZ == 128)
usecs *= 0x0008637bd05af6c7UL; /* 2**64 / (1000000 / HZ) */
-#elif defined(CONFIG_MIPS64) && (HZ == 1000)
+#elif defined(CONFIG_64BIT) && (HZ == 1000)
usecs *= 0x004189374BC6A7f0UL; /* 2**64 / (1000000 / HZ) */
-#elif defined(CONFIG_MIPS64)
+#elif defined(CONFIG_64BIT)
usecs *= (0x8000000000000000UL / (500000 / HZ));
#else /* 32-bit junk follows here */
usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 7b92c8045cc2..e48811440015 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -125,7 +125,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef double elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
/*
* This is used to ensure we don't load something for the wrong architecture.
@@ -153,9 +153,9 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
*/
#define ELF_CLASS ELFCLASS32
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
@@ -177,7 +177,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
*/
#define ELF_CLASS ELFCLASS64
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/*
* These are used to set parameters in the core dumps.
@@ -193,7 +193,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#ifdef __KERNEL__
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define SET_PERSONALITY(ex, ibcs2) \
do { \
@@ -202,9 +202,9 @@ do { \
set_personality(PER_LINUX); \
} while (0)
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define SET_PERSONALITY(ex, ibcs2) \
do { current->thread.mflags &= ~MF_ABI_MASK; \
@@ -222,7 +222,7 @@ do { current->thread.mflags &= ~MF_ABI_MASK; \
set_personality(PER_LINUX); \
} while (0)
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h
index 2436392e7990..06c5d13faf66 100644
--- a/include/asm-mips/fcntl.h
+++ b/include/asm-mips/fcntl.h
@@ -8,33 +8,16 @@
#ifndef _ASM_FCNTL_H
#define _ASM_FCNTL_H
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0x0003
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
#define O_APPEND 0x0008
#define O_SYNC 0x0010
#define O_NONBLOCK 0x0080
#define O_CREAT 0x0100 /* not fcntl */
-#define O_TRUNC 0x0200 /* not fcntl */
#define O_EXCL 0x0400 /* not fcntl */
#define O_NOCTTY 0x0800 /* not fcntl */
#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
#define O_LARGEFILE 0x2000 /* allow large file opens */
#define O_DIRECT 0x8000 /* direct disk access hint */
-#define O_DIRECTORY 0x10000 /* must be a directory */
-#define O_NOFOLLOW 0x20000 /* don't follow links */
-#define O_NOATIME 0x40000
-#define O_NDELAY O_NONBLOCK
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
#define F_GETLK 14
#define F_SETLK 6
#define F_SETLKW 7
@@ -50,33 +33,6 @@
#define F_SETLKW64 35
#endif
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
/*
* The flavours of struct flock. "struct flock" is the ABI compliant
* variant. Finally struct flock64 is the LFS variant of struct flock. As
@@ -86,7 +42,7 @@
#ifndef __mips64
-typedef struct flock {
+struct flock {
short l_type;
short l_whence;
__kernel_off_t l_start;
@@ -94,32 +50,17 @@ typedef struct flock {
long l_sysid;
__kernel_pid_t l_pid;
long pad[4];
-} flock_t;
-
-typedef struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-} flock64_t;
+};
-#else /* 64-bit definitions */
+#define HAVE_ARCH_STRUCT_FLOCK
-typedef struct flock {
- short l_type;
- short l_whence;
- __kernel_off_t l_start;
- __kernel_off_t l_len;
- __kernel_pid_t l_pid;
-} flock_t;
-
-#ifdef __KERNEL__
-#define flock64 flock
#endif
-#endif
+#include <asm-generic/fcntl.h>
-#define F_LINUX_SPECIFIC_BASE 1024
+typedef struct flock flock_t;
+#ifndef __mips64
+typedef struct flock64 flock64_t;
+#endif
#endif /* _ASM_FCNTL_H */
diff --git a/include/asm-mips/fpregdef.h b/include/asm-mips/fpregdef.h
index 1d9aa0979181..2b5fddc8f487 100644
--- a/include/asm-mips/fpregdef.h
+++ b/include/asm-mips/fpregdef.h
@@ -13,7 +13,7 @@
#define _ASM_FPREGDEF_H
#include <asm/sgidefs.h>
-
+
#if _MIPS_SIM == _MIPS_SIM_ABI32
/*
@@ -56,7 +56,7 @@
#define fcr31 $31 /* FPU status register */
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
-
+
#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
#define fv0 $f0 /* return value */
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 6cb38d5c0407..ea24e733b1bc 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -82,7 +82,7 @@ do { \
static inline int is_fpu_owner(void)
{
- return cpu_has_fpu && test_thread_flag(TIF_USEDFPU);
+ return cpu_has_fpu && test_thread_flag(TIF_USEDFPU);
}
static inline void own_fpu(void)
@@ -90,7 +90,7 @@ static inline void own_fpu(void)
if (cpu_has_fpu) {
__enable_fpu();
KSTK_STATUS(current) |= ST0_CU1;
- set_thread_flag(TIF_USEDFPU);
+ set_thread_flag(TIF_USEDFPU);
}
}
@@ -98,7 +98,7 @@ static inline void lose_fpu(void)
{
if (cpu_has_fpu) {
KSTK_STATUS(current) &= ~ST0_CU1;
- clear_thread_flag(TIF_USEDFPU);
+ clear_thread_flag(TIF_USEDFPU);
__disable_fpu();
}
}
@@ -127,7 +127,7 @@ static inline void restore_fp(struct task_struct *tsk)
static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
{
if (cpu_has_fpu) {
- if ((tsk == current) && is_fpu_owner())
+ if ((tsk == current) && is_fpu_owner())
_save_fp(current);
return tsk->thread.fpu.hard.fpr;
}
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
new file mode 100644
index 000000000000..9feff4ce1424
--- /dev/null
+++ b/include/asm-mips/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ inc_preempt_count();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-mips/hdreg.h b/include/asm-mips/hdreg.h
deleted file mode 100644
index 5989bbc97cbf..000000000000
--- a/include/asm-mips/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
diff --git a/include/asm-mips/hp-lj/asic.h b/include/asm-mips/hp-lj/asic.h
deleted file mode 100644
index fc2ca656da00..000000000000
--- a/include/asm-mips/hp-lj/asic.h
+++ /dev/null
@@ -1,7 +0,0 @@
-
-typedef enum { IllegalAsic, UnknownAsic, AndrosAsic, HarmonyAsic } AsicId;
-
-AsicId GetAsicId(void);
-
-const char* const GetAsicName(void);
-
diff --git a/include/asm-mips/ip32/mace.h b/include/asm-mips/ip32/mace.h
index 2b7b0fdeac19..432011b16c26 100644
--- a/include/asm-mips/ip32/mace.h
+++ b/include/asm-mips/ip32/mace.h
@@ -94,7 +94,7 @@ struct mace_video {
unsigned long xxx; /* later... */
};
-/*
+/*
* Ethernet interface
*/
struct mace_ethernet {
@@ -129,7 +129,7 @@ struct mace_ethernet {
volatile unsigned long rx_fifo;
};
-/*
+/*
* Peripherals
*/
@@ -251,7 +251,7 @@ struct mace_timers {
timer_reg audio_out2;
timer_reg video_in1;
timer_reg video_in2;
- timer_reg video_out;
+ timer_reg video_out;
};
struct mace_perif {
@@ -272,7 +272,7 @@ struct mace_perif {
};
-/*
+/*
* ISA peripherals
*/
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index b90b11d0b886..3f2470e9e678 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -49,7 +49,4 @@ do { \
extern void arch_init_irq(void);
-struct irqaction;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/lasat/serial.h b/include/asm-mips/lasat/serial.h
index 21d0fb7cee64..9e88c7669c7a 100644
--- a/include/asm-mips/lasat/serial.h
+++ b/include/asm-mips/lasat/serial.h
@@ -1,13 +1,13 @@
#include <asm/lasat/lasat.h>
/* Lasat 100 boards serial configuration */
-#define LASAT_BASE_BAUD_100 ( 7372800 / 16 )
+#define LASAT_BASE_BAUD_100 ( 7372800 / 16 )
#define LASAT_UART_REGS_BASE_100 0x1c8b0000
#define LASAT_UART_REGS_SHIFT_100 2
#define LASATINT_UART_100 8
/* * LASAT 200 boards serial configuration */
-#define LASAT_BASE_BAUD_200 (100000000 / 16 / 12)
+#define LASAT_BASE_BAUD_200 (100000000 / 16 / 12)
#define LASAT_UART_REGS_BASE_200 (Vrc5074_PHYS_BASE + 0x0300)
#define LASAT_UART_REGS_SHIFT_200 3
#define LASATINT_UART_200 13
diff --git a/include/asm-mips/local.h b/include/asm-mips/local.h
index 7eb6bf661b80..c38844f615fc 100644
--- a/include/asm-mips/local.h
+++ b/include/asm-mips/local.h
@@ -5,7 +5,7 @@
#include <linux/percpu.h>
#include <asm/atomic.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
typedef atomic_t local_t;
@@ -20,7 +20,7 @@ typedef atomic_t local_t;
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
typedef atomic64_t local_t;
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 2b36ea346910..148bae2fa7d3 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -1383,7 +1383,7 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#define PCI_IO_START 0
#define PCI_IO_END 0
#define PCI_MEM_START 0
-#define PCI_MEM_END 0
+#define PCI_MEM_END 0
#define PCI_FIRST_DEVFN 0
#define PCI_LAST_DEVFN 0
#endif
diff --git a/include/asm-mips/mach-db1x00/db1x00.h b/include/asm-mips/mach-db1x00/db1x00.h
index 4691398a414f..efafe65258b6 100644
--- a/include/asm-mips/mach-db1x00/db1x00.h
+++ b/include/asm-mips/mach-db1x00/db1x00.h
@@ -23,7 +23,7 @@
*
* ########################################################################
*
- *
+ *
*/
#ifndef __ASM_DB1X00_H
#define __ASM_DB1X00_H
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 63c0a81c7832..5a2c1efb4eb7 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -12,7 +12,7 @@
#include <linux/config.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define CAC_BASE 0x80000000
#define IO_BASE 0xa0000000
@@ -32,9 +32,9 @@
#define HIGHMEM_START 0x20000000UL
#endif
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* This handles the memory map.
@@ -67,6 +67,6 @@
#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
#endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index 30d42fcafe3d..e96166f27c49 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -12,7 +12,7 @@
#include <linux/config.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define CAC_BASE 0x80000000
#define IO_BASE 0xa0000000
@@ -32,9 +32,9 @@
#define HIGHMEM_START 0x20000000UL
#endif
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define PAGE_OFFSET 0xffffffff80000000UL
#ifndef HIGHMEM_START
@@ -50,6 +50,6 @@
#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
#endif /* __ASM_MACH_IP22_SPACES_H */
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index b932237f2193..04713973c6c3 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -18,7 +18,7 @@
* so, for 64bit IP32 kernel we just don't use ll/sc.
* This does not affect luserland.
*/
-#if defined(CONFIG_CPU_R5000) && defined(CONFIG_MIPS64)
+#if defined(CONFIG_CPU_R5000) && defined(CONFIG_64BIT)
#define cpu_has_llsc 0
#else
#define cpu_has_llsc 1
diff --git a/include/asm-mips/mach-jazz/floppy.h b/include/asm-mips/mach-jazz/floppy.h
index 8cf0d042c864..c9dad99b1232 100644
--- a/include/asm-mips/mach-jazz/floppy.h
+++ b/include/asm-mips/mach-jazz/floppy.h
@@ -92,7 +92,7 @@ static inline int fd_request_irq(void)
return request_irq(FLOPPY_IRQ, floppy_interrupt,
SA_INTERRUPT | SA_SAMPLE_RANDOM, "floppy", NULL);
}
-
+
static inline void fd_free_irq(void)
{
free_irq(FLOPPY_IRQ, NULL);
diff --git a/include/asm-mips/mach-pb1x00/pb1500.h b/include/asm-mips/mach-pb1x00/pb1500.h
index d6c779747b3c..ff6d40c87a25 100644
--- a/include/asm-mips/mach-pb1x00/pb1500.h
+++ b/include/asm-mips/mach-pb1x00/pb1500.h
@@ -33,11 +33,11 @@
#define PCI_BOARD_REG 0xAE000010
#define PCMCIA_BOARD_REG 0xAE000010
#define PC_DEASSERT_RST 0x80
- #define PC_DRV_EN 0x10
+ #define PC_DRV_EN 0x10
#define PB1500_G_CONTROL 0xAE000014
#define PB1500_RST_VDDI 0xAE00001C
#define PB1500_LEDS 0xAE000018
-
+
#define PB1500_HEX_LED 0xAF000004
#define PB1500_HEX_LED_BLANK 0xAF000008
diff --git a/include/asm-mips/mach-qemu/cpu-feature-overrides.h b/include/asm-mips/mach-qemu/cpu-feature-overrides.h
new file mode 100644
index 000000000000..f4e370e27168
--- /dev/null
+++ b/include/asm-mips/mach-qemu/cpu-feature-overrides.h
@@ -0,0 +1,31 @@
+/*
+ * 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 Ralf Baechle
+ */
+#ifndef __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * QEMU only comes with a hazard-free MIPS32 processor, so things are easy.
+ */
+#define cpu_has_mips16 0
+#define cpu_has_divec 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_prefetch 0
+#define cpu_has_mcheck 0
+#define cpu_has_ejtag 0
+
+#define cpu_has_llsc 1
+#define cpu_has_vtag_icache 0
+#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
+#define cpu_has_ic_fills_f_dc 0
+
+#define cpu_has_dsp 0
+
+#define cpu_has_nofpuex 0
+#define cpu_has_64bits 0
+
+#endif /* __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-qemu/param.h b/include/asm-mips/mach-qemu/param.h
new file mode 100644
index 000000000000..cb30ee490ae6
--- /dev/null
+++ b/include/asm-mips/mach-qemu/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) 2005 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_QEMU_PARAM_H
+#define __ASM_MACH_QEMU_PARAM_H
+
+#define HZ 100 /* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_QEMU_PARAM_H */
diff --git a/include/asm-mips/mach-vr41xx/timex.h b/include/asm-mips/mach-vr41xx/timex.h
deleted file mode 100644
index 8d71485d003a..000000000000
--- a/include/asm-mips/mach-vr41xx/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-/*
- * Changes:
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- * - CLOCK_TICK_RATE is changed into 32768 from 6144000.
- */
-#ifndef __ASM_MACH_VR41XX_TIMEX_H
-#define __ASM_MACH_VR41XX_TIMEX_H
-
-#define CLOCK_TICK_RATE 32768
-
-#endif /* __ASM_MACH_VR41XX_TIMEX_H */
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 48b77c9fb4f2..45cd72d172e8 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -28,17 +28,17 @@ extern unsigned long pgd_current[];
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define TLBMISS_HANDLER_SETUP() \
write_c0_context((unsigned long) smp_processor_id() << 23); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
-#if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
#define TLBMISS_HANDLER_SETUP() \
write_c0_context((unsigned long) &pgd_current[smp_processor_id()] << 23); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
-#if defined(CONFIG_MIPS64) && defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
#define TLBMISS_HANDLER_SETUP() \
write_c0_context((unsigned long) smp_processor_id() << 23); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index 90ee24aad955..0be58b2aeb9f 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -25,7 +25,7 @@ typedef struct
Elf64_Sxword r_addend; /* Addend. */
} Elf64_Mips_Rela;
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
@@ -33,7 +33,7 @@ typedef struct
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
diff --git a/include/asm-mips/msgbuf.h b/include/asm-mips/msgbuf.h
index 513b2824838b..a1533959742e 100644
--- a/include/asm-mips/msgbuf.h
+++ b/include/asm-mips/msgbuf.h
@@ -15,25 +15,25 @@
struct msqid64_ds {
struct ipc64_perm msg_perm;
-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused1;
#endif
__kernel_time_t msg_stime; /* last msgsnd time */
-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused1;
#endif
-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused2;
#endif
__kernel_time_t msg_rtime; /* last msgrcv time */
-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused2;
#endif
-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused3;
#endif
__kernel_time_t msg_ctime; /* last change time */
-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN)
unsigned long __unused3;
#endif
unsigned long msg_cbytes; /* current number of bytes on queue */
diff --git a/include/asm-mips/paccess.h b/include/asm-mips/paccess.h
index 36cec9e31696..309bc3099f68 100644
--- a/include/asm-mips/paccess.h
+++ b/include/asm-mips/paccess.h
@@ -16,10 +16,10 @@
#include <linux/config.h>
#include <linux/errno.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define __PA_ADDR ".word"
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define __PA_ADDR ".dword"
#endif
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 5cae35cd9ba9..652b6d67a571 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -103,20 +103,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */
@@ -148,4 +134,6 @@ static __inline__ int get_order(unsigned long size)
#define WANT_PAGE_VIRTUAL
#endif
+#include <asm-generic/page.h>
+
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index d70dc355c1f3..c9a00ca1c012 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -94,7 +94,7 @@ struct pci_dev;
*/
extern unsigned int PCI_DMA_BUS_IS_PHYS;
-#ifdef CONFIG_MAPPED_DMA_IO
+#ifdef CONFIG_DMA_NEED_PCI_MAP_STATE
/* pci_unmap_{single,page} is not a nop, thus... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
@@ -104,7 +104,7 @@ extern unsigned int PCI_DMA_BUS_IS_PHYS;
#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
-#else /* CONFIG_MAPPED_DMA_IO */
+#else /* CONFIG_DMA_NEED_PCI_MAP_STATE */
/* pci_unmap_{page,single} is a nop so... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
@@ -114,7 +114,7 @@ extern unsigned int PCI_DMA_BUS_IS_PHYS;
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-#endif /* CONFIG_MAPPED_DMA_IO */
+#endif /* CONFIG_DMA_NEED_PCI_MAP_STATE */
/* This is always fine. */
#define pci_dac_dma_supported(pci_dev, mask) (1)
@@ -142,6 +142,8 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
extern void pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region, struct resource *res);
+extern void pcibios_bus_to_resource(struct pci_dev *dev,
+ struct resource *res, struct pci_bus_region *region);
#ifdef CONFIG_PCI_DOMAINS
@@ -167,4 +169,17 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
/* Do platform specific device initialization at pci_enable_device() time */
extern int pcibios_plat_dev_init(struct pci_dev *dev);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
#endif /* _ASM_PCI_H */
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index 2d63f5ba403f..ce57288d43bd 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -85,7 +85,7 @@ static inline void pte_free(struct page *pte)
#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define pgd_populate(mm, pmd, pte) BUG()
/*
@@ -97,7 +97,7 @@ static inline void pte_free(struct page *pte)
#define __pmd_free_tlb(tlb,x) do { } while (0)
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define pgd_populate(mm, pgd, pmd) set_pgd(pgd, __pgd(pmd))
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index e76ccd6e3a5d..cbd1672c94cb 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -11,10 +11,10 @@
#include <asm-generic/4level-fixup.h>
#include <linux/config.h>
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#include <asm/pgtable-32.h>
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#include <asm/pgtable-64.h>
#endif
@@ -358,16 +358,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
-static inline int io_remap_page_range(struct vm_area_struct *vma,
- unsigned long vaddr,
- unsigned long paddr,
- unsigned long size,
- pgprot_t prot)
-{
- phys_t phys_addr_high = fixup_bigphys_addr(paddr, size);
- return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
-}
-
static inline int io_remap_pfn_range(struct vm_area_struct *vma,
unsigned long vaddr,
unsigned long pfn,
@@ -378,8 +368,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, vaddr, pfn, size, prot);
}
#else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 13c54d5b3b48..d6466aa09fb7 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -33,7 +33,7 @@ extern void (*cpu_wait)(void);
extern unsigned int vced_count, vcei_count;
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
/*
* User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
@@ -47,7 +47,7 @@ extern unsigned int vced_count, vcei_count;
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
/*
* User space process size: 1TB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing. TASK_SIZE
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index d3c46d633826..2b5c624c3d4f 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -28,7 +28,7 @@
* system call/exception. As usual the registers k0/k1 aren't being saved.
*/
struct pt_regs {
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
/* Pad bytes for argument save space on the stack. */
unsigned long pad0[6];
#endif
diff --git a/include/asm-mips/qemu.h b/include/asm-mips/qemu.h
new file mode 100644
index 000000000000..905c39585903
--- /dev/null
+++ b/include/asm-mips/qemu.h
@@ -0,0 +1,24 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_QEMU_H
+#define __ASM_QEMU_H
+
+/*
+ * Interrupt numbers
+ */
+#define Q_PIC_IRQ_BASE 0
+#define Q_COUNT_COMPARE_IRQ 16
+
+/*
+ * Qemu clock rate. Unlike on real MIPS this has no relation to the
+ * instruction issue rate, so the choosen value is pure fiction, just needs
+ * to match the value in Qemu itself.
+ */
+#define QEMU_C0_COUNTER_CLOCK 100000000
+
+#endif /* __ASM_QEMU_H */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index da03a32c1ca7..5bea49feec66 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -171,11 +171,11 @@ static inline void blast_dcache16(void)
unsigned long start = INDEX_BASE;
unsigned long end = start + current_cpu_data.dcache.waysize;
unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
- unsigned long ws_end = current_cpu_data.dcache.ways <<
+ unsigned long ws_end = current_cpu_data.dcache.ways <<
current_cpu_data.dcache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
}
@@ -200,8 +200,8 @@ static inline void blast_dcache16_page_indexed(unsigned long page)
current_cpu_data.dcache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x200)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
}
@@ -214,8 +214,8 @@ static inline void blast_icache16(void)
current_cpu_data.icache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x200)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -239,8 +239,8 @@ static inline void blast_icache16_page_indexed(unsigned long page)
current_cpu_data.icache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x200)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -249,11 +249,11 @@ static inline void blast_scache16(void)
unsigned long start = INDEX_BASE;
unsigned long end = start + current_cpu_data.scache.waysize;
unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
- unsigned long ws_end = current_cpu_data.scache.ways <<
+ unsigned long ws_end = current_cpu_data.scache.ways <<
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -278,8 +278,8 @@ static inline void blast_scache16_page_indexed(unsigned long page)
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x200)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x200)
cache16_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -318,8 +318,8 @@ static inline void blast_dcache32(void)
current_cpu_data.dcache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
}
@@ -343,8 +343,8 @@ static inline void blast_dcache32_page_indexed(unsigned long page)
current_cpu_data.dcache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
}
@@ -357,8 +357,8 @@ static inline void blast_icache32(void)
current_cpu_data.icache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -383,7 +383,7 @@ static inline void blast_icache32_page_indexed(unsigned long page)
unsigned long ws, addr;
for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400)
+ for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -392,11 +392,11 @@ static inline void blast_scache32(void)
unsigned long start = INDEX_BASE;
unsigned long end = start + current_cpu_data.scache.waysize;
unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
- unsigned long ws_end = current_cpu_data.scache.ways <<
+ unsigned long ws_end = current_cpu_data.scache.ways <<
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -421,8 +421,8 @@ static inline void blast_scache32_page_indexed(unsigned long page)
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x400)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400)
cache32_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -461,8 +461,8 @@ static inline void blast_icache64(void)
current_cpu_data.icache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x800)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x800)
cache64_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -487,7 +487,7 @@ static inline void blast_icache64_page_indexed(unsigned long page)
unsigned long ws, addr;
for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x800)
+ for (addr = start; addr < end; addr += 0x800)
cache64_unroll32(addr|ws,Index_Invalidate_I);
}
@@ -496,11 +496,11 @@ static inline void blast_scache64(void)
unsigned long start = INDEX_BASE;
unsigned long end = start + current_cpu_data.scache.waysize;
unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
- unsigned long ws_end = current_cpu_data.scache.ways <<
+ unsigned long ws_end = current_cpu_data.scache.ways <<
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
for (addr = start; addr < end; addr += 0x800)
cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -525,8 +525,8 @@ static inline void blast_scache64_page_indexed(unsigned long page)
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x800)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x800)
cache64_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -561,11 +561,11 @@ static inline void blast_scache128(void)
unsigned long start = INDEX_BASE;
unsigned long end = start + current_cpu_data.scache.waysize;
unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit;
- unsigned long ws_end = current_cpu_data.scache.ways <<
+ unsigned long ws_end = current_cpu_data.scache.ways <<
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
for (addr = start; addr < end; addr += 0x1000)
cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
@@ -590,8 +590,8 @@ static inline void blast_scache128_page_indexed(unsigned long page)
current_cpu_data.scache.waybit;
unsigned long ws, addr;
- for (ws = 0; ws < ws_end; ws += ws_inc)
- for (addr = start; addr < end; addr += 0x1000)
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x1000)
cache128_unroll32(addr|ws,Index_Writeback_Inv_SD);
}
diff --git a/include/asm-mips/reg.h b/include/asm-mips/reg.h
index 7b33bbca9585..6173004cc88e 100644
--- a/include/asm-mips/reg.h
+++ b/include/asm-mips/reg.h
@@ -14,7 +14,7 @@
#include <linux/config.h>
-#if defined(CONFIG_MIPS32) || defined(WANT_COMPAT_REG_H)
+#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
#define EF_R0 6
#define EF_R1 7
@@ -70,7 +70,7 @@
#endif
-#if CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define EF_R0 0
#define EF_R1 1
@@ -124,6 +124,6 @@
#define EF_SIZE 304 /* size in bytes */
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
#endif /* __ASM_MIPS_REG_H */
diff --git a/include/asm-mips/resource.h b/include/asm-mips/resource.h
index fd3c6d17a5f6..1fba00c22077 100644
--- a/include/asm-mips/resource.h
+++ b/include/asm-mips/resource.h
@@ -27,7 +27,7 @@
* but we keep the old value on MIPS32,
* for compatibility:
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
# define RLIM_INFINITY 0x7fffffffUL
#endif
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
index 31c0c2347f4f..3c4b637fd925 100644
--- a/include/asm-mips/rtc.h
+++ b/include/asm-mips/rtc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-mips/rtc.h
+ * include/asm-mips/rtc.h
*
* (Really an interface for drivers/char/genrtc.c)
*
diff --git a/include/asm-mips/sgi/gio.h b/include/asm-mips/sgi/gio.h
index a38d66f99872..889cf028c95d 100644
--- a/include/asm-mips/sgi/gio.h
+++ b/include/asm-mips/sgi/gio.h
@@ -16,7 +16,7 @@
*
* The Indigo and Indy have two GIO bus connectors. Indigo2 (all models) have
* three physical connectors, but only two slots, GFX and EXP0.
- *
+ *
* There is 10MB of GIO address space for GIO64 slot devices
* slot# slot type address range size
* ----- --------- ----------------------- -----
diff --git a/include/asm-mips/sgi/hpc3.h b/include/asm-mips/sgi/hpc3.h
index a5b988d7327a..ac3dfc7af5b0 100644
--- a/include/asm-mips/sgi/hpc3.h
+++ b/include/asm-mips/sgi/hpc3.h
@@ -221,7 +221,7 @@ struct hpc3_regs {
#define HPC3_BESTAT_PIDMASK 0x3f700 /* DMA channel parity identifier */
u32 _unused1[0x14000/4 - 5]; /* padding */
-
+
/* Now direct PIO per-HPC3 peripheral access to external regs. */
volatile u32 scsi0_ext[256]; /* SCSI channel 0 external regs */
u32 _unused2[0x7c00/4];
@@ -304,7 +304,7 @@ struct hpc3_regs {
volatile u32 bbram[8192-50-14]; /* Battery backed ram */
};
-/*
+/*
* It is possible to have two HPC3's within the address space on
* one machine, though only having one is more likely on an Indy.
*/
diff --git a/include/asm-mips/sgi/ioc.h b/include/asm-mips/sgi/ioc.h
index 169187f53fbc..f3e3dc9bb732 100644
--- a/include/asm-mips/sgi/ioc.h
+++ b/include/asm-mips/sgi/ioc.h
@@ -16,7 +16,7 @@
#include <linux/types.h>
#include <asm/sgi/pi1.h>
-/*
+/*
* All registers are 8-bit wide alligned on 32-bit boundary. Bad things
* happen if you try word access them. You have been warned.
*/
@@ -138,7 +138,7 @@ struct sgioc_regs {
u8 _sysid[3];
volatile u8 sysid;
#define SGIOC_SYSID_FULLHOUSE 0x01
-#define SGIOC_SYSID_BOARDREV(x) ((x & 0xe0) > 5)
+#define SGIOC_SYSID_BOARDREV(x) ((x & 0xe0) > 5)
#define SGIOC_SYSID_CHIPREV(x) ((x & 0x1e) > 1)
u32 _unused2;
u8 _read[3];
diff --git a/include/asm-mips/sgi/ip22.h b/include/asm-mips/sgi/ip22.h
index 97d73adb4e40..bbfc05c3cab9 100644
--- a/include/asm-mips/sgi/ip22.h
+++ b/include/asm-mips/sgi/ip22.h
@@ -12,7 +12,7 @@
#ifndef _SGI_IP22_H
#define _SGI_IP22_H
-/*
+/*
* These are the virtual IRQ numbers, we divide all IRQ's into
* 'spaces', the 'space' determines where and how to enable/disable
* that particular IRQ on an SGI machine. HPC DMA and MC DMA interrups
diff --git a/include/asm-mips/sgi/mc.h b/include/asm-mips/sgi/mc.h
index fd98f930607c..c52f7834c7c8 100644
--- a/include/asm-mips/sgi/mc.h
+++ b/include/asm-mips/sgi/mc.h
@@ -182,14 +182,14 @@ struct sgimc_regs {
volatile u32 dtlb_hi3;
u32 _unused33;
volatile u32 dtlb_lo3;
-
+
u32 _unused34[0x0392];
-
+
u32 _unused35;
volatile u32 rpsscounter; /* Chirps at 100ns */
u32 _unused36[0x1000/4-2*4];
-
+
u32 _unused37;
volatile u32 maddronly; /* Address DMA goes at */
u32 _unused38;
diff --git a/include/asm-mips/sgiarcs.h b/include/asm-mips/sgiarcs.h
index 59450335f049..722b77a8c5e5 100644
--- a/include/asm-mips/sgiarcs.h
+++ b/include/asm-mips/sgiarcs.h
@@ -367,7 +367,7 @@ struct linux_smonblock {
* Macros for calling a 32-bit ARC implementation from 64-bit code
*/
-#if defined(CONFIG_MIPS64) && defined(CONFIG_ARC32)
+#if defined(CONFIG_64BIT) && defined(CONFIG_ARC32)
#define __arc_clobbers \
"$2","$3" /* ... */, "$8","$9","$10","$11", \
@@ -476,10 +476,10 @@ struct linux_smonblock {
__res; \
})
-#endif /* defined(CONFIG_MIPS64) && defined(CONFIG_ARC32) */
+#endif /* defined(CONFIG_64BIT) && defined(CONFIG_ARC32) */
-#if (defined(CONFIG_MIPS32) && defined(CONFIG_ARC32)) || \
- (defined(CONFIG_MIPS64) && defined(CONFIG_ARC64))
+#if (defined(CONFIG_32BIT) && defined(CONFIG_ARC32)) || \
+ (defined(CONFIG_64BIT) && defined(CONFIG_ARC64))
#define ARC_CALL0(dest) \
({ long __res; \
diff --git a/include/asm-mips/sibyte/carmel.h b/include/asm-mips/sibyte/carmel.h
index 7ac5da13ce8a..b5e7dae19f0f 100644
--- a/include/asm-mips/sibyte/carmel.h
+++ b/include/asm-mips/sibyte/carmel.h
@@ -25,12 +25,12 @@
#define SIBYTE_BOARD_NAME "Carmel"
-#define GPIO_PHY_INTERRUPT 2
-#define GPIO_NONMASKABLE_INT 3
-#define GPIO_CF_INSERTED 6
-#define GPIO_MONTEREY_RESET 7
-#define GPIO_QUADUART_INT 8
-#define GPIO_CF_INT 9
+#define GPIO_PHY_INTERRUPT 2
+#define GPIO_NONMASKABLE_INT 3
+#define GPIO_CF_INSERTED 6
+#define GPIO_MONTEREY_RESET 7
+#define GPIO_QUADUART_INT 8
+#define GPIO_CF_INT 9
#define GPIO_FPGA_CCLK 10
#define GPIO_FPGA_DOUT 11
#define GPIO_FPGA_DIN 12
diff --git a/include/asm-mips/sibyte/sb1250_defs.h b/include/asm-mips/sibyte/sb1250_defs.h
index 96088fb074a4..40ef97c76c8b 100644
--- a/include/asm-mips/sibyte/sb1250_defs.h
+++ b/include/asm-mips/sibyte/sb1250_defs.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
- * Global constants and macros File: sb1250_defs.h
- *
+ *
+ * Global constants and macros File: sb1250_defs.h
+ *
* This file contains macros and definitions used by the other
* include files.
*
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -105,7 +105,7 @@
#define SIBYTE_HDR_FMASK_112x_ALL 0x0000f00
#define SIBYTE_HDR_FMASK_112x_PASS1 0x0000100
-/* Bit mask for chip/revision. (use _ALL for all revisions of a chip). */
+/* Bit mask for chip/revision. (use _ALL for all revisions of a chip). */
#define SIBYTE_HDR_FMASK(chip, pass) \
(SIBYTE_HDR_FMASK_ ## chip ## _ ## pass)
#define SIBYTE_HDR_FMASK_ALLREVS(chip) \
@@ -150,31 +150,31 @@
/* *********************************************************************
* Naming schemes for constants in these files:
- *
- * M_xxx MASK constant (identifies bits in a register).
+ *
+ * M_xxx MASK constant (identifies bits in a register).
* For multi-bit fields, all bits in the field will
* be set.
*
* K_xxx "Code" constant (value for data in a multi-bit
* field). The value is right justified.
*
- * V_xxx "Value" constant. This is the same as the
+ * V_xxx "Value" constant. This is the same as the
* corresponding "K_xxx" constant, except it is
* shifted to the correct position in the register.
*
* S_xxx SHIFT constant. This is the number of bits that
- * a field value (code) needs to be shifted
+ * a field value (code) needs to be shifted
* (towards the left) to put the value in the right
* position for the register.
*
- * A_xxx ADDRESS constant. This will be a physical
+ * A_xxx ADDRESS constant. This will be a physical
* address. Use the PHYS_TO_K1 macro to generate
* a K1SEG address.
*
* R_xxx RELATIVE offset constant. This is an offset from
* an A_xxx constant (usually the first register in
* a group).
- *
+ *
* G_xxx(X) GET value. This macro obtains a multi-bit field
* from a register, masks it, and shifts it to
* the bottom of the register (retrieving a K_xxx
@@ -189,7 +189,7 @@
/*
- * Cast to 64-bit number. Presumably the syntax is different in
+ * Cast to 64-bit number. Presumably the syntax is different in
* assembly language.
*
* Note: you'll need to define uint32_t and uint64_t in your headers.
diff --git a/include/asm-mips/sibyte/sb1250_dma.h b/include/asm-mips/sibyte/sb1250_dma.h
index f1b08d32338d..3cdb48f50ed0 100644
--- a/include/asm-mips/sibyte/sb1250_dma.h
+++ b/include/asm-mips/sibyte/sb1250_dma.h
@@ -1,24 +1,24 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* DMA definitions File: sb1250_dma.h
- *
+ *
* This module contains constants and macros useful for
* programming the SB1250's DMA controllers, both the data mover
* and the Ethernet DMA.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -28,7 +28,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -43,9 +43,9 @@
* DMA Registers
********************************************************************* */
-/*
+/*
* Ethernet and Serial DMA Configuration Register 0 (Table 7-4)
- * Registers: DMA_CONFIG0_MAC_x_RX_CH_0
+ * Registers: DMA_CONFIG0_MAC_x_RX_CH_0
* Registers: DMA_CONFIG0_MAC_x_TX_CH_0
* Registers: DMA_CONFIG0_SER_x_RX
* Registers: DMA_CONFIG0_SER_x_TX
@@ -98,7 +98,7 @@
/*
* Ethernet and Serial DMA Configuration Register 1 (Table 7-5)
- * Registers: DMA_CONFIG1_MAC_x_RX_CH_0
+ * Registers: DMA_CONFIG1_MAC_x_RX_CH_0
* Registers: DMA_CONFIG1_DMA_x_TX_CH_0
* Registers: DMA_CONFIG1_SER_x_RX
* Registers: DMA_CONFIG1_SER_x_TX
@@ -152,11 +152,11 @@
/*
* DMA Descriptor Count Registers (Table 7-8)
*/
-
+
/* No bitfields */
-/*
+/*
* Current Descriptor Address Register (Table 7-11)
*/
@@ -275,14 +275,14 @@
#define V_DMA_DSCRB_STATUS(x) _SB_MAKEVALUE(x,S_DMA_DSCRB_STATUS)
#define G_DMA_DSCRB_STATUS(x) _SB_GETVALUE(x,S_DMA_DSCRB_STATUS,M_DMA_DSCRB_STATUS)
-/*
+/*
* Ethernet Descriptor Status Bits (Table 7-15)
*/
#define M_DMA_ETHRX_BADIP4CS _SB_MAKEMASK1(51)
#define M_DMA_ETHRX_DSCRERR _SB_MAKEMASK1(52)
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
/* Note: BADTCPCS is actually in DSCR_B options field */
#define M_DMA_ETHRX_BADTCPCS _SB_MAKEMASK1(0)
#endif /* 1250 PASS2 || 112x PASS1 */
@@ -324,7 +324,7 @@
#define M_DMA_ETHTX_SOP _SB_MAKEMASK1(63)
-/*
+/*
* Ethernet Transmit Options (Table 7-17)
*/
@@ -377,7 +377,7 @@
* Data Mover Registers
********************************************************************* */
-/*
+/*
* Data Mover Descriptor Base Address Register (Table 7-22)
* Register: DM_DSCR_BASE_0
* Register: DM_DSCR_BASE_1
@@ -414,7 +414,7 @@
#define M_DM_DSCR_BASE_ABORT _SB_MAKEMASK1(62)
#define M_DM_DSCR_BASE_ENABL _SB_MAKEMASK1(63)
-/*
+/*
* Data Mover Descriptor Count Register (Table 7-25)
*/
diff --git a/include/asm-mips/sibyte/sb1250_genbus.h b/include/asm-mips/sibyte/sb1250_genbus.h
index 0d9dfac3d7db..f1f509f295c4 100644
--- a/include/asm-mips/sibyte/sb1250_genbus.h
+++ b/include/asm-mips/sibyte/sb1250_genbus.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* Generic Bus Constants File: sb1250_genbus.h
- *
- * This module contains constants and macros useful for
+ *
+ * This module contains constants and macros useful for
* manipulating the SB1250's Generic Bus interface
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
diff --git a/include/asm-mips/sibyte/sb1250_int.h b/include/asm-mips/sibyte/sb1250_int.h
index c3f74df211f4..e173e2ea4c98 100644
--- a/include/asm-mips/sibyte/sb1250_int.h
+++ b/include/asm-mips/sibyte/sb1250_int.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* Interrupt Mapper definitions File: sb1250_int.h
- *
+ *
* This module contains constants for manipulating the SB1250's
* interrupt mapper and definitions for the interrupt sources.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -43,7 +43,7 @@
/*
* Interrupt sources (Table 4-8, UM 0.2)
- *
+ *
* First, the interrupt numbers.
*/
diff --git a/include/asm-mips/sibyte/sb1250_l2c.h b/include/asm-mips/sibyte/sb1250_l2c.h
index 799db828d963..8afe8e01581b 100644
--- a/include/asm-mips/sibyte/sb1250_l2c.h
+++ b/include/asm-mips/sibyte/sb1250_l2c.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* L2 Cache constants and macros File: sb1250_l2c.h
- *
+ *
* This module contains constants useful for manipulating the
* level 2 cache.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
diff --git a/include/asm-mips/sibyte/sb1250_ldt.h b/include/asm-mips/sibyte/sb1250_ldt.h
index d8753885df17..f2617ded0a8f 100644
--- a/include/asm-mips/sibyte/sb1250_ldt.h
+++ b/include/asm-mips/sibyte/sb1250_ldt.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* LDT constants File: sb1250_ldt.h
- *
- * This module contains constants and macros to describe
- * the LDT interface on the SB1250.
- *
+ *
+ * This module contains constants and macros to describe
+ * the LDT interface on the SB1250.
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -155,7 +155,7 @@
/*
* LDT Status Register (Table 8-14). Note that these constants
- * assume you've read the command and status register
+ * assume you've read the command and status register
* together (32-bit read at offset 0x04)
*
* These bits also apply to the secondary status
@@ -183,8 +183,8 @@
#define M_LDT_STATUS_DETPARERR _SB_MAKEMASK1_32(31)
/*
- * Bridge Control Register (Table 8-16). Note that these
- * constants assume you've read the register as a 32-bit
+ * Bridge Control Register (Table 8-16). Note that these
+ * constants assume you've read the register as a 32-bit
* read (offset 0x3C)
*/
diff --git a/include/asm-mips/sibyte/sb1250_mac.h b/include/asm-mips/sibyte/sb1250_mac.h
index 81f603f03a98..18e74e43f4a2 100644
--- a/include/asm-mips/sibyte/sb1250_mac.h
+++ b/include/asm-mips/sibyte/sb1250_mac.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* MAC constants and macros File: sb1250_mac.h
- *
+ *
* This module contains constants and macros for the SB1250's
* ethernet controllers.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -311,7 +311,7 @@
/*
* These constants are used to configure the fields within the Frame
- * Configuration Register.
+ * Configuration Register.
*/
#define K_MAC_IFG_RX_10 _SB_MAKE64(0) /* See table 176, not used */
@@ -393,7 +393,7 @@
* Register: MAC_INT_MASK_2
*/
-/*
+/*
* Use these constants to shift the appropriate channel
* into the CH0 position so the same tests can be used
* on each channel.
diff --git a/include/asm-mips/sibyte/sb1250_mc.h b/include/asm-mips/sibyte/sb1250_mc.h
index 93a48334b874..1dd41c927996 100644
--- a/include/asm-mips/sibyte/sb1250_mc.h
+++ b/include/asm-mips/sibyte/sb1250_mc.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
- * Memory Controller constants File: sb1250_mc.h
- *
+ *
+ * Memory Controller constants File: sb1250_mc.h
+ *
* This module contains constants and macros useful for
* programming the memory controller.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -166,7 +166,7 @@
#define K_MC_REF_RATE_100MHz 0x62
#define K_MC_REF_RATE_133MHz 0x81
-#define K_MC_REF_RATE_200MHz 0xC4
+#define K_MC_REF_RATE_200MHz 0xC4
#define V_MC_REF_RATE_100MHz V_MC_REF_RATE(K_MC_REF_RATE_100MHz)
#define V_MC_REF_RATE_133MHz V_MC_REF_RATE(K_MC_REF_RATE_133MHz)
@@ -228,7 +228,7 @@
V_MC_ADDR_DRIVE_DEFAULT | \
V_MC_DATA_DRIVE_DEFAULT | \
V_MC_CLOCK_DRIVE_DEFAULT | \
- V_MC_REF_RATE_DEFAULT
+ V_MC_REF_RATE_DEFAULT
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index 5d496c6faba6..9db80cd13a79 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* Register Definitions File: sb1250_regs.h
- *
+ *
* This module contains the addresses of the on-chip peripherals
* on the SB1250.
- *
+ *
* SB1250 specification level: 01/02/2002
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -40,20 +40,20 @@
/* *********************************************************************
* Some general notes:
- *
+ *
* For the most part, when there is more than one peripheral
* of the same type on the SOC, the constants below will be
* offsets from the base of each peripheral. For example,
* the MAC registers are described as offsets from the first
* MAC register, and there will be a MAC_REGISTER() macro
- * to calculate the base address of a given MAC.
- *
+ * to calculate the base address of a given MAC.
+ *
* The information in this file is based on the SB1250 SOC
* manual version 0.2, July 2000.
********************************************************************* */
-/* *********************************************************************
+/* *********************************************************************
* Memory Controller Registers
********************************************************************* */
@@ -101,7 +101,7 @@
#define R_MC_TEST_ECC 0x0000000420
#define R_MC_MCLK_CFG 0x0000000500
-/* *********************************************************************
+/* *********************************************************************
* L2 Cache Control Registers
********************************************************************* */
@@ -126,7 +126,7 @@
#define A_L2_EEC_ADDRESS A_L2_ECC_TAG
-/* *********************************************************************
+/* *********************************************************************
* PCI Interface Registers
********************************************************************* */
@@ -134,7 +134,7 @@
#define A_PCI_TYPE01_HEADER 0x00DE000800
-/* *********************************************************************
+/* *********************************************************************
* Ethernet DMA and MACs
********************************************************************* */
@@ -184,7 +184,7 @@
(R_MAC_DMA_CHANNEL_BASE(txrx,chan) + \
(reg))
-/*
+/*
* DMA channel registers, relative to A_MAC_DMA_CHANNEL_BASE
*/
@@ -259,7 +259,7 @@
#define MAC_CHMAP_COUNT 4
-/* *********************************************************************
+/* *********************************************************************
* DUART Registers
********************************************************************* */
@@ -363,7 +363,7 @@
#endif /* 1250 PASS2 || 112x PASS1 */
-/* *********************************************************************
+/* *********************************************************************
* Synchronous Serial Registers
********************************************************************* */
@@ -397,7 +397,7 @@
(reg))
-/*
+/*
* DMA channel registers, relative to A_SER_DMA_CHANNEL_BASE
*/
@@ -457,7 +457,7 @@
#define R_SER_RMON_RX_ERRORS 0x000001F0
#define R_SER_RMON_RX_BADADDR 0x000001F8
-/* *********************************************************************
+/* *********************************************************************
* Generic Bus Registers
********************************************************************* */
@@ -513,7 +513,7 @@
#define R_IO_PCMCIA_CFG 0x0A60
#define R_IO_PCMCIA_STATUS 0x0A70
-/* *********************************************************************
+/* *********************************************************************
* GPIO Registers
********************************************************************* */
@@ -537,7 +537,7 @@
#define R_GPIO_PIN_CLR 0x30
#define R_GPIO_PIN_SET 0x38
-/* *********************************************************************
+/* *********************************************************************
* SMBus Registers
********************************************************************* */
@@ -573,7 +573,7 @@
#define R_SMB_CONTROL 0x0000000060
#define R_SMB_PEC 0x0000000070
-/* *********************************************************************
+/* *********************************************************************
* Timer Registers
********************************************************************* */
@@ -641,7 +641,7 @@
#endif /* 1250 PASS2 || 112x PASS1 */
-/* *********************************************************************
+/* *********************************************************************
* System Control Registers
********************************************************************* */
@@ -649,7 +649,7 @@
#define A_SCD_SYSTEM_CFG 0x0010020008
#define A_SCD_SYSTEM_MANUF 0x0010038000
-/* *********************************************************************
+/* *********************************************************************
* System Address Trap Registers
********************************************************************* */
@@ -672,7 +672,7 @@
#endif /* 1250 PASS2 || 112x PASS1 */
-/* *********************************************************************
+/* *********************************************************************
* System Interrupt Mapper Registers
********************************************************************* */
@@ -701,7 +701,7 @@
#define R_IMR_INTERRUPT_MAP_BASE 0x0200
#define R_IMR_INTERRUPT_MAP_COUNT 64
-/* *********************************************************************
+/* *********************************************************************
* System Performance Counter Registers
********************************************************************* */
@@ -711,7 +711,7 @@
#define A_SCD_PERF_CNT_2 0x00100204E0
#define A_SCD_PERF_CNT_3 0x00100204E8
-/* *********************************************************************
+/* *********************************************************************
* System Bus Watcher Registers
********************************************************************* */
@@ -726,13 +726,13 @@
#define A_BUS_L2_ERRORS 0x00100208C0
#define A_BUS_MEM_IO_ERRORS 0x00100208C8
-/* *********************************************************************
+/* *********************************************************************
* System Debug Controller Registers
********************************************************************* */
#define A_SCD_JTAG_BASE 0x0010000000
-/* *********************************************************************
+/* *********************************************************************
* System Trace Buffer Registers
********************************************************************* */
@@ -755,7 +755,7 @@
#define A_SCD_TRACE_SEQUENCE_6 0x0010020A90
#define A_SCD_TRACE_SEQUENCE_7 0x0010020A98
-/* *********************************************************************
+/* *********************************************************************
* System Generic DMA Registers
********************************************************************* */
diff --git a/include/asm-mips/sibyte/sb1250_scd.h b/include/asm-mips/sibyte/sb1250_scd.h
index 22e8041959e2..dbbd682fb47e 100644
--- a/include/asm-mips/sibyte/sb1250_scd.h
+++ b/include/asm-mips/sibyte/sb1250_scd.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* SCD Constants and Macros File: sb1250_scd.h
- *
+ *
* This module contains constants and macros useful for
* manipulating the System Control and Debug module on the 1250.
- *
+ *
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -130,40 +130,40 @@
/* System Manufacturing Register
* Register: SCD_SYSTEM_MANUF
*/
-
+
/* Wafer ID: bits 31:0 */
#define S_SYS_WAFERID1_200 _SB_MAKE64(0)
#define M_SYS_WAFERID1_200 _SB_MAKEMASK(32,S_SYS_WAFERID1_200)
#define V_SYS_WAFERID1_200(x) _SB_MAKEVALUE(x,S_SYS_WAFERID1_200)
#define G_SYS_WAFERID1_200(x) _SB_GETVALUE(x,S_SYS_WAFERID1_200,M_SYS_WAFERID1_200)
-
+
#define S_SYS_BIN _SB_MAKE64(32)
#define M_SYS_BIN _SB_MAKEMASK(4,S_SYS_BIN)
#define V_SYS_BIN _SB_MAKEVALUE(x,S_SYS_BIN)
#define G_SYS_BIN _SB_GETVALUE(x,S_SYS_BIN,M_SYS_BIN)
-
+
/* Wafer ID: bits 39:36 */
#define S_SYS_WAFERID2_200 _SB_MAKE64(36)
#define M_SYS_WAFERID2_200 _SB_MAKEMASK(4,S_SYS_WAFERID2_200)
#define V_SYS_WAFERID2_200(x) _SB_MAKEVALUE(x,S_SYS_WAFERID2_200)
#define G_SYS_WAFERID2_200(x) _SB_GETVALUE(x,S_SYS_WAFERID2_200,M_SYS_WAFERID2_200)
-
+
/* Wafer ID: bits 39:0 */
#define S_SYS_WAFERID_300 _SB_MAKE64(0)
#define M_SYS_WAFERID_300 _SB_MAKEMASK(40,S_SYS_WAFERID_300)
#define V_SYS_WAFERID_300(x) _SB_MAKEVALUE(x,S_SYS_WAFERID_300)
#define G_SYS_WAFERID_300(x) _SB_GETVALUE(x,S_SYS_WAFERID_300,M_SYS_WAFERID_300)
-
+
#define S_SYS_XPOS _SB_MAKE64(40)
#define M_SYS_XPOS _SB_MAKEMASK(6,S_SYS_XPOS)
#define V_SYS_XPOS(x) _SB_MAKEVALUE(x,S_SYS_XPOS)
#define G_SYS_XPOS(x) _SB_GETVALUE(x,S_SYS_XPOS,M_SYS_XPOS)
-
+
#define S_SYS_YPOS _SB_MAKE64(46)
#define M_SYS_YPOS _SB_MAKEMASK(6,S_SYS_YPOS)
#define V_SYS_YPOS(x) _SB_MAKEVALUE(x,S_SYS_YPOS)
#define G_SYS_YPOS(x) _SB_GETVALUE(x,S_SYS_YPOS,M_SYS_YPOS)
-
+
/*
* System Config Register (Table 4-2)
* Register: SCD_SYSTEM_CFG
diff --git a/include/asm-mips/sibyte/sb1250_smbus.h b/include/asm-mips/sibyte/sb1250_smbus.h
index 287cbfe9efa2..335c53e92936 100644
--- a/include/asm-mips/sibyte/sb1250_smbus.h
+++ b/include/asm-mips/sibyte/sb1250_smbus.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* SMBUS Constants File: sb1250_smbus.h
- *
- * This module contains constants and macros useful for
+ *
+ * This module contains constants and macros useful for
* manipulating the SB1250's SMbus devices.
- *
+ *
* SB1250 specification level: 01/02/2002
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
diff --git a/include/asm-mips/sibyte/sb1250_syncser.h b/include/asm-mips/sibyte/sb1250_syncser.h
index 8d5e8edd3c4b..fa2760d38b8b 100644
--- a/include/asm-mips/sibyte/sb1250_syncser.h
+++ b/include/asm-mips/sibyte/sb1250_syncser.h
@@ -7,17 +7,17 @@
* manipulating the SB1250's Synchronous Serial
*
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
*
*********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index 7655d6945cca..923ea4f44e0f 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -1,23 +1,23 @@
/* *********************************************************************
* SB1250 Board Support Package
- *
+ *
* UART Constants File: sb1250_uart.h
- *
- * This module contains constants and macros useful for
+ *
+ * This module contains constants and macros useful for
* manipulating the SB1250's UARTs
*
* SB1250 specification level: User's manual 1/02/02
- *
+ *
* Author: Mitch Lichtenberg
- *
- *********************************************************************
+ *
+ *********************************************************************
*
* Copyright 2000,2001,2002,2003
* Broadcom Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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,
@@ -27,7 +27,7 @@
*
* You 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,
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
********************************************************************* */
@@ -37,7 +37,7 @@
#include "sb1250_defs.h"
-/* **********************************************************************
+/* **********************************************************************
* DUART Registers
********************************************************************** */
@@ -145,7 +145,7 @@
#define V_DUART_MISC_CMD_START_BREAK V_DUART_MISC_CMD(K_DUART_MISC_CMD_START_BREAK)
#define V_DUART_MISC_CMD_STOP_BREAK V_DUART_MISC_CMD(K_DUART_MISC_CMD_STOP_BREAK)
-#define M_DUART_CMD_RESERVED _SB_MAKEMASK1(7)
+#define M_DUART_CMD_RESERVED _SB_MAKEMASK1(7)
/*
* DUART Status Register (Table 10-6)
@@ -165,7 +165,7 @@
/*
* DUART Baud Rate Register (Table 10-7)
- * Register: DUART_CLK_SEL_A
+ * Register: DUART_CLK_SEL_A
* Register: DUART_CLK_SEL_B
*/
@@ -332,7 +332,7 @@
(chan == 0 ? M_DUART_OUT_PIN_CLR0 : M_DUART_OUT_PIN_CLR1)
#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
-/*
+/*
* Full Interrupt Control Register
*/
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index 18939e84b6f2..f7fbebaa0744 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -10,7 +10,7 @@
#define _ASM_SIGCONTEXT_H
#include <asm/sgidefs.h>
-
+
#if _MIPS_SIM == _MIPS_SIM_ABI32
/*
@@ -38,7 +38,7 @@ struct sigcontext {
};
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
-
+
#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
/*
diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
index a0e26e6c994d..698becab5a9e 100644
--- a/include/asm-mips/siginfo.h
+++ b/include/asm-mips/siginfo.h
@@ -25,10 +25,10 @@ struct siginfo;
/*
* Careful to keep union _sifields from shifting ...
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
#endif
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#endif
diff --git a/include/asm-mips/sim.h b/include/asm-mips/sim.h
index 6333169be329..9c2af1b00e19 100644
--- a/include/asm-mips/sim.h
+++ b/include/asm-mips/sim.h
@@ -11,12 +11,12 @@
#include <linux/config.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#define __str2(x) #x
#define __str(x) __str2(x)
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define save_static_function(symbol) \
__asm__ ( \
@@ -42,9 +42,9 @@ __asm__ ( \
#define nabi_no_regargs
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define save_static_function(symbol) \
__asm__ ( \
@@ -78,6 +78,6 @@ __asm__ ( \
unsigned long __dummy6, \
unsigned long __dummy7,
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
#endif /* _ASM_SIM_H */
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 020b4db70ee5..753b6620e6fa 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -37,6 +37,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_SNDBUF 0x1001 /* Send buffer size. */
#define SO_RCVBUF 0x1002 /* Receive buffer. */
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
@@ -80,7 +82,7 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
* @SOCK_STREAM - stream (connection) socket
* @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message
- * @SOCK_SEQPACKET - sequential packet socket
+ * @SOCK_SEQPACKET - sequential packet socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user level.
*/
diff --git a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h
index 114d3eb98a6a..4d0135b11156 100644
--- a/include/asm-mips/spinlock.h
+++ b/include/asm-mips/spinlock.h
@@ -16,20 +16,10 @@
* Your basic SMP spinlocks, allowing only a single CPU anywhere
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-
-#define spin_lock_init(x) do { (x)->lock = 0; } while(0)
-
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) do { barrier(); } while ((x)->lock)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+ do { cpu_relax(); } while ((x)->lock)
/*
* Simple spin lock operations. There are two variants, one clears IRQ's
@@ -38,13 +28,13 @@ typedef struct {
* We make no fairness assumptions. They have a cost.
*/
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned int tmp;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set noreorder # _raw_spin_lock \n"
+ " .set noreorder # __raw_spin_lock \n"
"1: ll %1, %2 \n"
" bnez %1, 1b \n"
" li %1, 1 \n"
@@ -58,7 +48,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_spin_lock \n"
+ " .set noreorder # __raw_spin_lock \n"
"1: ll %1, %2 \n"
" bnez %1, 1b \n"
" li %1, 1 \n"
@@ -72,10 +62,10 @@ static inline void _raw_spin_lock(spinlock_t *lock)
}
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
__asm__ __volatile__(
- " .set noreorder # _raw_spin_unlock \n"
+ " .set noreorder # __raw_spin_unlock \n"
" sync \n"
" sw $0, %0 \n"
" .set\treorder \n"
@@ -84,13 +74,13 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
: "memory");
}
-static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
+static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
{
unsigned int temp, res;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set noreorder # _raw_spin_trylock \n"
+ " .set noreorder # __raw_spin_trylock \n"
"1: ll %0, %3 \n"
" ori %2, %0, 1 \n"
" sc %2, %1 \n"
@@ -104,7 +94,7 @@ static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_spin_trylock \n"
+ " .set noreorder # __raw_spin_trylock \n"
"1: ll %0, %3 \n"
" ori %2, %0, 1 \n"
" sc %2, %1 \n"
@@ -129,24 +119,13 @@ static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
* read-locks.
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned int tmp;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set noreorder # _raw_read_lock \n"
+ " .set noreorder # __raw_read_lock \n"
"1: ll %1, %2 \n"
" bltz %1, 1b \n"
" addu %1, 1 \n"
@@ -160,7 +139,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_read_lock \n"
+ " .set noreorder # __raw_read_lock \n"
"1: ll %1, %2 \n"
" bltz %1, 1b \n"
" addu %1, 1 \n"
@@ -177,13 +156,13 @@ static inline void _raw_read_lock(rwlock_t *rw)
/* Note the use of sub, not subu which will make the kernel die with an
overflow exception if we ever try to unlock an rwlock that is already
unlocked or is being held by a writer. */
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned int tmp;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- "1: ll %1, %2 # _raw_read_unlock \n"
+ "1: ll %1, %2 # __raw_read_unlock \n"
" sub %1, 1 \n"
" sc %1, %0 \n"
" beqzl %1, 1b \n"
@@ -193,7 +172,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_read_unlock \n"
+ " .set noreorder # __raw_read_unlock \n"
"1: ll %1, %2 \n"
" sub %1, 1 \n"
" sc %1, %0 \n"
@@ -206,13 +185,13 @@ static inline void _raw_read_unlock(rwlock_t *rw)
}
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
unsigned int tmp;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set noreorder # _raw_write_lock \n"
+ " .set noreorder # __raw_write_lock \n"
"1: ll %1, %2 \n"
" bnez %1, 1b \n"
" lui %1, 0x8000 \n"
@@ -226,7 +205,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_write_lock \n"
+ " .set noreorder # __raw_write_lock \n"
"1: ll %1, %2 \n"
" bnez %1, 1b \n"
" lui %1, 0x8000 \n"
@@ -241,26 +220,26 @@ static inline void _raw_write_lock(rwlock_t *rw)
}
}
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
__asm__ __volatile__(
- " sync # _raw_write_unlock \n"
+ " sync # __raw_write_unlock \n"
" sw $0, %0 \n"
: "=m" (rw->lock)
: "m" (rw->lock)
: "memory");
}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
{
unsigned int tmp;
int ret;
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set noreorder # _raw_write_trylock \n"
+ " .set noreorder # __raw_write_trylock \n"
" li %2, 0 \n"
"1: ll %1, %3 \n"
" bnez %1, 2f \n"
@@ -277,7 +256,7 @@ static inline int _raw_write_trylock(rwlock_t *rw)
: "memory");
} else {
__asm__ __volatile__(
- " .set noreorder # _raw_write_trylock \n"
+ " .set noreorder # __raw_write_trylock \n"
" li %2, 0 \n"
"1: ll %1, %3 \n"
" bnez %1, 2f \n"
diff --git a/include/asm-mips/spinlock_types.h b/include/asm-mips/spinlock_types.h
new file mode 100644
index 000000000000..ce26c5048b15
--- /dev/null
+++ b/include/asm-mips/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 86283c25fd5b..7b5e64600bc8 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -15,7 +15,7 @@
#include <asm/asm.h>
#include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
.macro SAVE_AT
.set push
@@ -26,7 +26,7 @@
.macro SAVE_TEMP
mfhi v1
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
LONG_S $8, PT_R8(sp)
LONG_S $9, PT_R9(sp)
#endif
@@ -56,7 +56,7 @@
#ifdef CONFIG_SMP
.macro get_saved_sp /* SMP variation */
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
mfc0 k0, CP0_CONTEXT
lui k1, %hi(kernelsp)
srl k0, k0, 23
@@ -64,7 +64,7 @@
addu k1, k0
LONG_L k1, %lo(kernelsp)(k1)
#endif
-#if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
MFC0 k1, CP0_CONTEXT
dsra k1, 23
lui k0, %hi(pgd_current)
@@ -74,7 +74,7 @@
daddu k1, k0
LONG_L k1, %lo(kernelsp)(k1)
#endif
-#if defined(CONFIG_MIPS64) && defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
MFC0 k1, CP0_CONTEXT
dsrl k1, 23
dsll k1, k1, 3
@@ -83,20 +83,20 @@
.endm
.macro set_saved_sp stackp temp temp2
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
mfc0 \temp, CP0_CONTEXT
srl \temp, 23
sll \temp, 2
LONG_S \stackp, kernelsp(\temp)
#endif
-#if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
lw \temp, TI_CPU(gp)
dsll \temp, 3
lui \temp2, %hi(kernelsp)
daddu \temp, \temp2
LONG_S \stackp, %lo(kernelsp)(\temp)
#endif
-#if defined(CONFIG_MIPS64) && defined(CONFIG_BUILD_ELF64)
+#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
lw \temp, TI_CPU(gp)
dsll \temp, 3
LONG_S \stackp, kernelsp(\temp)
@@ -140,7 +140,7 @@
LONG_S $6, PT_R6(sp)
MFC0 v1, CP0_EPC
LONG_S $7, PT_R7(sp)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
LONG_S $8, PT_R8(sp)
LONG_S $9, PT_R9(sp)
#endif
@@ -169,7 +169,7 @@
.macro RESTORE_TEMP
LONG_L $24, PT_LO(sp)
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
LONG_L $8, PT_R8(sp)
LONG_L $9, PT_R9(sp)
#endif
@@ -217,7 +217,7 @@
LONG_L $31, PT_R31(sp)
LONG_L $28, PT_R28(sp)
LONG_L $25, PT_R25(sp)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
LONG_L $8, PT_R8(sp)
LONG_L $9, PT_R9(sp)
#endif
@@ -262,7 +262,7 @@
LONG_L $31, PT_R31(sp)
LONG_L $28, PT_R28(sp)
LONG_L $25, PT_R25(sp)
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
LONG_L $8, PT_R8(sp)
LONG_L $9, PT_R9(sp)
#endif
diff --git a/include/asm-mips/statfs.h b/include/asm-mips/statfs.h
index 5076fec65780..c3ddf973c1c0 100644
--- a/include/asm-mips/statfs.h
+++ b/include/asm-mips/statfs.h
@@ -57,7 +57,7 @@ struct statfs64 {
};
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
-
+
#if _MIPS_SIM == _MIPS_SIM_ABI64
struct statfs64 { /* Same as struct statfs */
diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h
index b18345504f8a..5a06f6d13899 100644
--- a/include/asm-mips/string.h
+++ b/include/asm-mips/string.h
@@ -16,7 +16,7 @@
* Most of the inline functions are rather naive implementations so I just
* didn't bother updating them for 64-bit ...
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#ifndef IN_STRING_C
@@ -130,7 +130,7 @@ strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count)
return __res;
}
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
#define __HAVE_ARCH_MEMSET
extern void *memset(void *__s, int __c, size_t __count);
@@ -141,7 +141,7 @@ extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define __HAVE_ARCH_MEMSCAN
static __inline__ void *memscan(void *__addr, int __c, size_t __size)
{
@@ -161,6 +161,6 @@ static __inline__ void *memscan(void *__addr, int __c, size_t __size)
return __addr;
}
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
#endif /* _ASM_STRING_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 169f3d4265b1..6663efd49b27 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -208,7 +208,7 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
return retval;
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
{
__u64 retval;
@@ -330,7 +330,7 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
return retval;
}
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
unsigned long new)
{
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index 42fcd6f2c206..a70cb0854c8a 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -62,10 +62,10 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define current_thread_info() __current_thread_info
/* thread information allocation */
-#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS32)
+#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
#define THREAD_SIZE_ORDER (1)
#endif
-#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS64)
+#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_64BIT)
#define THREAD_SIZE_ORDER (2)
#endif
#ifdef CONFIG_PAGE_SIZE_8KB
diff --git a/include/asm-mips/titan_dep.h b/include/asm-mips/titan_dep.h
index fd9599e40a0a..fee1908c65d2 100644
--- a/include/asm-mips/titan_dep.h
+++ b/include/asm-mips/titan_dep.h
@@ -228,4 +228,4 @@ extern unsigned long ocd_base;
#define RM9K_READ_8(ofs, val) *(val) = *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs)
#define RM9K_READ_16(ofs, val) *(val) = *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs)
-#endif
+#endif
diff --git a/include/asm-mips/tx4927/tx4927.h b/include/asm-mips/tx4927/tx4927.h
index 5d939db6e220..3bb7f0087d68 100644
--- a/include/asm-mips/tx4927/tx4927.h
+++ b/include/asm-mips/tx4927/tx4927.h
@@ -45,14 +45,14 @@
/* TX4927 SDRAM controller (64-bit registers) */
-#define TX4927_SDRAMC_BASE 0x8000
-#define TX4927_SDRAMC_SDCCR0 0x8000
+#define TX4927_SDRAMC_BASE 0x8000
+#define TX4927_SDRAMC_SDCCR0 0x8000
#define TX4927_SDRAMC_SDCCR1 0x8008
#define TX4927_SDRAMC_SDCCR2 0x8010
#define TX4927_SDRAMC_SDCCR3 0x8018
#define TX4927_SDRAMC_SDCTR 0x8040
#define TX4927_SDRAMC_SDCMD 0x8058
-#define TX4927_SDRAMC_LIMIT 0x8fff
+#define TX4927_SDRAMC_LIMIT 0x8fff
/* TX4927 external bus controller (64-bit registers) */
@@ -289,8 +289,8 @@
/* TX4927 serial port 0 (32-bit registers) */
-#define TX4927_SIO0_BASE 0xf300
-#define TX4927_SIO0_SILCR0 0xf300
+#define TX4927_SIO0_BASE 0xf300
+#define TX4927_SIO0_SILCR0 0xf300
#define TX4927_SIO0_SILCR0_RESERVED_16_31 BM_16_31
#define TX4927_SIO0_SILCR0_RWUB BM_15_15
#define TX4927_SIO0_SILCR0_TWUB BM_14_14
@@ -309,7 +309,7 @@
#define TX4927_SIO0_SILCR0_UMODE_DATA_7_BIT (~BM_00_01)
#define TX4927_SIO0_SILCR0_UMODE_DATA_8_BIT_MC BM_01_01
#define TX4927_SIO0_SILCR0_UMODE_DATA_7_BIT_MC BM_00_01
-#define TX4927_SIO0_SIDICR0 0xf304
+#define TX4927_SIO0_SIDICR0 0xf304
#define TX4927_SIO0_SIDICR0_RESERVED_16_31 BM_16_31
#define TX4927_SIO0_SIDICR0_TDE BM_15_15
#define TX4927_SIO0_SIDICR0_RDE BM_14_14
@@ -330,7 +330,7 @@
#define TX4927_SIO0_SIDICR0_STIE_TRDY BM_02_02
#define TX4927_SIO0_SIDICR0_STIE_TXALS BM_01_01
#define TX4927_SIO0_SIDICR0_STIE_UBRKD BM_00_00
-#define TX4927_SIO0_SIDISR0 0xf308
+#define TX4927_SIO0_SIDISR0 0xf308
#define TX4927_SIO0_SIDISR0_RESERVED_16_31 BM_16_31
#define TX4927_SIO0_SIDISR0_UBRK BM_15_15
#define TX4927_SIO0_SIDISR0_UVALID BM_14_14
@@ -344,7 +344,7 @@
#define TX4927_SIO0_SIDISR0_STIS BM_06_06
#define TX4927_SIO0_SIDISR0_RESERVED_05_05 BM_05_05
#define TX4927_SIO0_SIDISR0_RFDN BM_00_04
-#define TX4927_SIO0_SISCISR0 0xf30c
+#define TX4927_SIO0_SISCISR0 0xf30c
#define TX4927_SIO0_SISCISR0_RESERVED_06_31 BM_06_31
#define TX4927_SIO0_SISCISR0_OERS BM_05_05
#define TX4927_SIO0_SISCISR0_CTSS BM_04_04
@@ -352,7 +352,7 @@
#define TX4927_SIO0_SISCISR0_TRDY BM_02_02
#define TX4927_SIO0_SISCISR0_TXALS BM_01_01
#define TX4927_SIO0_SISCISR0_UBRKD BM_00_00
-#define TX4927_SIO0_SIFCR0 0xf310
+#define TX4927_SIO0_SIFCR0 0xf310
#define TX4927_SIO0_SIFCR0_RESERVED_16_31 BM_16_31
#define TX4927_SIO0_SIFCR0_SWRST BM_16_31
#define TX4927_SIO0_SIFCR0_RESERVED_09_14 BM_09_14
@@ -370,7 +370,7 @@
#define TX4927_SIO0_SIFCR0_TFRST BM_02_02
#define TX4927_SIO0_SIFCR0_RFRST BM_01_01
#define TX4927_SIO0_SIFCR0_FRSTE BM_00_00
-#define TX4927_SIO0_SIFLCR0 0xf314
+#define TX4927_SIO0_SIFLCR0 0xf314
#define TX4927_SIO0_SIFLCR0_RESERVED_13_31 BM_13_31
#define TX4927_SIO0_SIFLCR0_RCS BM_12_12
#define TX4927_SIO0_SIFLCR0_TES BM_11_11
@@ -381,7 +381,7 @@
#define TX4927_SIO0_SIFLCR0_RESERVED_05_06 BM_05_06
#define TX4927_SIO0_SIFLCR0_RTSTL BM_01_04
#define TX4927_SIO0_SIFLCR0_TBRK BM_00_00
-#define TX4927_SIO0_SIBGR0 0xf318
+#define TX4927_SIO0_SIBGR0 0xf318
#define TX4927_SIO0_SIBGR0_RESERVED_10_31 BM_10_31
#define TX4927_SIO0_SIBGR0_BCLK BM_08_09
#define TX4927_SIO0_SIBGR0_BCLK_T0 (~BM_08_09)
@@ -389,28 +389,28 @@
#define TX4927_SIO0_SIBGR0_BCLK_T4 BM_09_09
#define TX4927_SIO0_SIBGR0_BCLK_T6 BM_08_09
#define TX4927_SIO0_SIBGR0_BRD BM_00_07
-#define TX4927_SIO0_SITFIF00 0xf31c
+#define TX4927_SIO0_SITFIF00 0xf31c
#define TX4927_SIO0_SITFIF00_RESERVED_08_31 BM_08_31
#define TX4927_SIO0_SITFIF00_TXD BM_00_07
-#define TX4927_SIO0_SIRFIFO0 0xf320
+#define TX4927_SIO0_SIRFIFO0 0xf320
#define TX4927_SIO0_SIRFIFO0_RESERVED_08_31 BM_08_31
#define TX4927_SIO0_SIRFIFO0_RXD BM_00_07
-#define TX4927_SIO0_SIRFIFO0 0xf320
-#define TX4927_SIO0_LIMIT 0xf3ff
+#define TX4927_SIO0_SIRFIFO0 0xf320
+#define TX4927_SIO0_LIMIT 0xf3ff
/* TX4927 serial port 1 (32-bit registers) */
-#define TX4927_SIO1_BASE 0xf400
-#define TX4927_SIO1_SILCR1 0xf400
-#define TX4927_SIO1_SIDICR1 0xf404
-#define TX4927_SIO1_SIDISR1 0xf408
-#define TX4927_SIO1_SISCISR1 0xf40c
-#define TX4927_SIO1_SIFCR1 0xf410
-#define TX4927_SIO1_SIFLCR1 0xf414
-#define TX4927_SIO1_SIBGR1 0xf418
-#define TX4927_SIO1_SITFIF01 0xf41c
-#define TX4927_SIO1_SIRFIFO1 0xf420
-#define TX4927_SIO1_LIMIT 0xf4ff
+#define TX4927_SIO1_BASE 0xf400
+#define TX4927_SIO1_SILCR1 0xf400
+#define TX4927_SIO1_SIDICR1 0xf404
+#define TX4927_SIO1_SIDISR1 0xf408
+#define TX4927_SIO1_SISCISR1 0xf40c
+#define TX4927_SIO1_SIFCR1 0xf410
+#define TX4927_SIO1_SIFLCR1 0xf414
+#define TX4927_SIO1_SIBGR1 0xf418
+#define TX4927_SIO1_SITFIF01 0xf41c
+#define TX4927_SIO1_SIRFIFO1 0xf420
+#define TX4927_SIO1_LIMIT 0xf4ff
/* TX4927 parallel port (32-bit registers) */
diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h
index 170433492246..165f6b8b217f 100644
--- a/include/asm-mips/tx4927/tx4927_pci.h
+++ b/include/asm-mips/tx4927/tx4927_pci.h
@@ -5,8 +5,8 @@
*
* Copyright (C) 2000-2001 Toshiba Corporation
*/
-#ifndef __ASM_TX4927_TX4927_PCI_H
-#define __ASM_TX4927_TX4927_PCI_H
+#ifndef __ASM_TX4927_TX4927_PCI_H
+#define __ASM_TX4927_TX4927_PCI_H
#define TX4927_CCFG_TOE 0x00004000
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
index d2f0c76b00a9..421b3aea14cc 100644
--- a/include/asm-mips/types.h
+++ b/include/asm-mips/types.h
@@ -78,7 +78,7 @@ typedef unsigned long long u64;
#endif
#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \
- || defined(CONFIG_MIPS64)
+ || defined(CONFIG_64BIT)
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
@@ -99,8 +99,6 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 07114898e065..5c2c98329012 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -22,7 +22,7 @@
*
* For historical reasons, these macros are grossly misnamed.
*/
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
#define __UA_LIMIT 0x80000000UL
@@ -32,9 +32,9 @@
#define __UA_t0 "$8"
#define __UA_t1 "$9"
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
#define __UA_LIMIT (- TASK_SIZE)
@@ -44,7 +44,7 @@
#define __UA_t0 "$12"
#define __UA_t1 "$13"
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
/*
* USER_DS is a bitmask that has the bits set that may not be set in a valid
@@ -112,29 +112,6 @@
likely(__access_ok((unsigned long)(addr), (size),__access_mask))
/*
- * verify_area: - Obsolete/deprecated and will go away soon,
- * use access_ok() instead.
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only. This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
-/*
* put_user: - Write a simple value into user space.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 6d21cc964f76..ad4d48056307 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -1124,7 +1124,7 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
# ifndef __mips64
# define __ARCH_WANT_STAT64
# endif
-# ifdef CONFIG_MIPS32
+# ifdef CONFIG_32BIT
# define __ARCH_WANT_SYS_TIME
# endif
# ifdef CONFIG_MIPS32_O32
diff --git a/include/asm-mips/vr4181/irq.h b/include/asm-mips/vr4181/irq.h
deleted file mode 100644
index 4bf0ea970ed0..000000000000
--- a/include/asm-mips/vr4181/irq.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Macros for vr4181 IRQ numbers.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
- *
- */
-
-/*
- * Strategy:
- *
- * Vr4181 has conceptually three levels of interrupt controllers:
- * 1. the CPU itself with 8 intr level.
- * 2. system interrupt controller, cascaded from int0 pin in CPU, 32 intrs
- * 3. GPIO interrupts : forwarding external interrupts to sys intr controller
- */
-
-/* decide the irq block assignment */
-#define VR4181_NUM_CPU_IRQ 8
-#define VR4181_NUM_SYS_IRQ 32
-#define VR4181_NUM_GPIO_IRQ 16
-
-#define VR4181_IRQ_BASE 0
-
-#define VR4181_CPU_IRQ_BASE VR4181_IRQ_BASE
-#define VR4181_SYS_IRQ_BASE (VR4181_CPU_IRQ_BASE + VR4181_NUM_CPU_IRQ)
-#define VR4181_GPIO_IRQ_BASE (VR4181_SYS_IRQ_BASE + VR4181_NUM_SYS_IRQ)
-
-/* CPU interrupts */
-
-/*
- IP0 - Software interrupt
- IP1 - Software interrupt
- IP2 - All but battery, high speed modem, and real time clock
- IP3 - RTC Long1 (system timer)
- IP4 - RTC Long2
- IP5 - High Speed Modem (unused on VR4181)
- IP6 - Unused
- IP7 - Timer interrupt from CPO_COMPARE
-*/
-
-#define VR4181_IRQ_SW1 (VR4181_CPU_IRQ_BASE + 0)
-#define VR4181_IRQ_SW2 (VR4181_CPU_IRQ_BASE + 1)
-#define VR4181_IRQ_INT0 (VR4181_CPU_IRQ_BASE + 2)
-#define VR4181_IRQ_INT1 (VR4181_CPU_IRQ_BASE + 3)
-#define VR4181_IRQ_INT2 (VR4181_CPU_IRQ_BASE + 4)
-#define VR4181_IRQ_INT3 (VR4181_CPU_IRQ_BASE + 5)
-#define VR4181_IRQ_INT4 (VR4181_CPU_IRQ_BASE + 6)
-#define VR4181_IRQ_TIMER (VR4181_CPU_IRQ_BASE + 7)
-
-
-/* Cascaded from VR4181_IRQ_INT0 (ICU mapped interrupts) */
-
-/*
- IP2 - same as VR4181_IRQ_INT1
- IP8 - This is a cascade to GPIO IRQ's. Do not use.
- IP16 - same as VR4181_IRQ_INT2
- IP18 - CompactFlash
-*/
-
-#define VR4181_IRQ_BATTERY (VR4181_SYS_IRQ_BASE + 0)
-#define VR4181_IRQ_POWER (VR4181_SYS_IRQ_BASE + 1)
-#define VR4181_IRQ_RTCL1 (VR4181_SYS_IRQ_BASE + 2)
-#define VR4181_IRQ_ETIMER (VR4181_SYS_IRQ_BASE + 3)
-#define VR4181_IRQ_RFU12 (VR4181_SYS_IRQ_BASE + 4)
-#define VR4181_IRQ_PIU (VR4181_SYS_IRQ_BASE + 5)
-#define VR4181_IRQ_AIU (VR4181_SYS_IRQ_BASE + 6)
-#define VR4181_IRQ_KIU (VR4181_SYS_IRQ_BASE + 7)
-#define VR4181_IRQ_GIU (VR4181_SYS_IRQ_BASE + 8)
-#define VR4181_IRQ_SIU (VR4181_SYS_IRQ_BASE + 9)
-#define VR4181_IRQ_RFU18 (VR4181_SYS_IRQ_BASE + 10)
-#define VR4181_IRQ_SOFT (VR4181_SYS_IRQ_BASE + 11)
-#define VR4181_IRQ_RFU20 (VR4181_SYS_IRQ_BASE + 12)
-#define VR4181_IRQ_DOZEPIU (VR4181_SYS_IRQ_BASE + 13)
-#define VR4181_IRQ_RFU22 (VR4181_SYS_IRQ_BASE + 14)
-#define VR4181_IRQ_RFU23 (VR4181_SYS_IRQ_BASE + 15)
-#define VR4181_IRQ_RTCL2 (VR4181_SYS_IRQ_BASE + 16)
-#define VR4181_IRQ_LED (VR4181_SYS_IRQ_BASE + 17)
-#define VR4181_IRQ_ECU (VR4181_SYS_IRQ_BASE + 18)
-#define VR4181_IRQ_CSU (VR4181_SYS_IRQ_BASE + 19)
-#define VR4181_IRQ_USB (VR4181_SYS_IRQ_BASE + 20)
-#define VR4181_IRQ_DMA (VR4181_SYS_IRQ_BASE + 21)
-#define VR4181_IRQ_LCD (VR4181_SYS_IRQ_BASE + 22)
-#define VR4181_IRQ_RFU31 (VR4181_SYS_IRQ_BASE + 23)
-#define VR4181_IRQ_RFU32 (VR4181_SYS_IRQ_BASE + 24)
-#define VR4181_IRQ_RFU33 (VR4181_SYS_IRQ_BASE + 25)
-#define VR4181_IRQ_RFU34 (VR4181_SYS_IRQ_BASE + 26)
-#define VR4181_IRQ_RFU35 (VR4181_SYS_IRQ_BASE + 27)
-#define VR4181_IRQ_RFU36 (VR4181_SYS_IRQ_BASE + 28)
-#define VR4181_IRQ_RFU37 (VR4181_SYS_IRQ_BASE + 29)
-#define VR4181_IRQ_RFU38 (VR4181_SYS_IRQ_BASE + 30)
-#define VR4181_IRQ_RFU39 (VR4181_SYS_IRQ_BASE + 31)
-
-/* Cascaded from VR4181_IRQ_GIU */
-#define VR4181_IRQ_GPIO0 (VR4181_GPIO_IRQ_BASE + 0)
-#define VR4181_IRQ_GPIO1 (VR4181_GPIO_IRQ_BASE + 1)
-#define VR4181_IRQ_GPIO2 (VR4181_GPIO_IRQ_BASE + 2)
-#define VR4181_IRQ_GPIO3 (VR4181_GPIO_IRQ_BASE + 3)
-#define VR4181_IRQ_GPIO4 (VR4181_GPIO_IRQ_BASE + 4)
-#define VR4181_IRQ_GPIO5 (VR4181_GPIO_IRQ_BASE + 5)
-#define VR4181_IRQ_GPIO6 (VR4181_GPIO_IRQ_BASE + 6)
-#define VR4181_IRQ_GPIO7 (VR4181_GPIO_IRQ_BASE + 7)
-#define VR4181_IRQ_GPIO8 (VR4181_GPIO_IRQ_BASE + 8)
-#define VR4181_IRQ_GPIO9 (VR4181_GPIO_IRQ_BASE + 9)
-#define VR4181_IRQ_GPIO10 (VR4181_GPIO_IRQ_BASE + 10)
-#define VR4181_IRQ_GPIO11 (VR4181_GPIO_IRQ_BASE + 11)
-#define VR4181_IRQ_GPIO12 (VR4181_GPIO_IRQ_BASE + 12)
-#define VR4181_IRQ_GPIO13 (VR4181_GPIO_IRQ_BASE + 13)
-#define VR4181_IRQ_GPIO14 (VR4181_GPIO_IRQ_BASE + 14)
-#define VR4181_IRQ_GPIO15 (VR4181_GPIO_IRQ_BASE + 15)
-
-
-// Alternative to above GPIO IRQ defines
-#define VR4181_IRQ_GPIO(pin) ((VR4181_IRQ_GPIO0) + (pin))
-
-#define VR4181_IRQ_MAX (VR4181_IRQ_BASE + VR4181_NUM_CPU_IRQ + \
- VR4181_NUM_SYS_IRQ + VR4181_NUM_GPIO_IRQ)
diff --git a/include/asm-mips/vr4181/vr4181.h b/include/asm-mips/vr4181/vr4181.h
deleted file mode 100644
index 5c5d60741515..000000000000
--- a/include/asm-mips/vr4181/vr4181.h
+++ /dev/null
@@ -1,413 +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 by Michael Klar
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- */
-#ifndef __ASM_VR4181_VR4181_H
-#define __ASM_VR4181_VR4181_H
-
-#include <asm/addrspace.h>
-
-#include <asm/vr4181/irq.h>
-
-#ifndef __ASSEMBLY__
-#define __preg8 (volatile unsigned char*)
-#define __preg16 (volatile unsigned short*)
-#define __preg32 (volatile unsigned int*)
-#else
-#define __preg8
-#define __preg16
-#define __preg32
-#endif
-
-// Embedded CPU peripheral registers
-// Note that many of the registers have different physical address for VR4181
-
-// Bus Control Unit (BCU)
-#define VR4181_BCUCNTREG1 __preg16(KSEG1 + 0x0A000000) /* BCU control register 1 (R/W) */
-#define VR4181_CMUCLKMSK __preg16(KSEG1 + 0x0A000004) /* Clock mask register (R/W) */
-#define VR4181_CMUCLKMSK_MSKCSUPCLK 0x0040
-#define VR4181_CMUCLKMSK_MSKAIUPCLK 0x0020
-#define VR4181_CMUCLKMSK_MSKPIUPCLK 0x0010
-#define VR4181_CMUCLKMSK_MSKADUPCLK 0x0008
-#define VR4181_CMUCLKMSK_MSKSIU18M 0x0004
-#define VR4181_CMUCLKMSK_MSKADU18M 0x0002
-#define VR4181_CMUCLKMSK_MSKUSB 0x0001
-#define VR4181_CMUCLKMSK_MSKSIU VR4181_CMUCLKMSK_MSKSIU18M
-#define VR4181_BCUSPEEDREG __preg16(KSEG1 + 0x0A00000C) /* BCU access time parameter (R/W) */
-#define VR4181_BCURFCNTREG __preg16(KSEG1 + 0x0A000010) /* BCU refresh control register (R/W) */
-#define VR4181_REVIDREG __preg16(KSEG1 + 0x0A000014) /* Revision ID register (R) */
-#define VR4181_CLKSPEEDREG __preg16(KSEG1 + 0x0A000018) /* Clock speed register (R) */
-#define VR4181_EDOMCYTREG __preg16(KSEG1 + 0x0A000300) /* Memory cycle timing register (R/W) */
-#define VR4181_MEMCFG_REG __preg16(KSEG1 + 0x0A000304) /* Memory configuration register (R/W) */
-#define VR4181_MODE_REG __preg16(KSEG1 + 0x0A000308) /* SDRAM mode register (R/W) */
-#define VR4181_SDTIMINGREG __preg16(KSEG1 + 0x0A00030C) /* SDRAM timing register (R/W) */
-
-// DMA Control Unit (DCU)
-#define VR4181_MICDEST1REG1 __preg16(KSEG1 + 0x0A000020) /* Microphone destination 1 address register 1 (R/W) */
-#define VR4181_MICDEST1REG2 __preg16(KSEG1 + 0x0A000022) /* Microphone destination 1 address register 2 (R/W) */
-#define VR4181_MICDEST2REG1 __preg16(KSEG1 + 0x0A000024) /* Microphone destination 2 address register 1 (R/W) */
-#define VR4181_MICDEST2REG2 __preg16(KSEG1 + 0x0A000026) /* Microphone destination 2 address register 2 (R/W) */
-#define VR4181_SPKRRC1REG1 __preg16(KSEG1 + 0x0A000028) /* Speaker Source 1 address register 1 (R/W) */
-#define VR4181_SPKRRC1REG2 __preg16(KSEG1 + 0x0A00002A) /* Speaker Source 1 address register 2 (R/W) */
-#define VR4181_SPKRRC2REG1 __preg16(KSEG1 + 0x0A00002C) /* Speaker Source 2 address register 1 (R/W) */
-#define VR4181_SPKRRC2REG2 __preg16(KSEG1 + 0x0A00002E) /* Speaker Source 2 address register 2 (R/W) */
-#define VR4181_DMARSTREG __preg16(KSEG1 + 0x0A000040) /* DMA Reset register (R/W) */
-#define VR4181_AIUDMAMSKREG __preg16(KSEG1 + 0x0A000046) /* Audio DMA mask register (R/W) */
-#define VR4181_USBDMAMSKREG __preg16(KSEG1 + 0x0A000600) /* USB DMA Mask register (R/W) */
-#define VR4181_USBRXS1AREG1 __preg16(KSEG1 + 0x0A000602) /* USB Rx source 1 address register 1 (R/W) */
-#define VR4181_USBRXS1AREG2 __preg16(KSEG1 + 0x0A000604) /* USB Rx source 1 address register 2 (R/W) */
-#define VR4181_USBRXS2AREG1 __preg16(KSEG1 + 0x0A000606) /* USB Rx source 2 address register 1 (R/W) */
-#define VR4181_USBRXS2AREG2 __preg16(KSEG1 + 0x0A000608) /* USB Rx source 2 address register 2 (R/W) */
-#define VR4181_USBTXS1AREG1 __preg16(KSEG1 + 0x0A00060A) /* USB Tx source 1 address register 1 (R/W) */
-#define VR4181_USBTXS1AREG2 __preg16(KSEG1 + 0x0A00060C) /* USB Tx source 1 address register 2 (R/W) */
-#define VR4181_USBTXS2AREG1 __preg16(KSEG1 + 0x0A00060E) /* USB Tx source 2 address register 1 (R/W) */
-#define VR4181_USBTXS2AREG2 __preg16(KSEG1 + 0x0A000610) /* USB Tx source 2 address register 2 (R/W) */
-#define VR4181_USBRXD1AREG1 __preg16(KSEG1 + 0x0A00062A) /* USB Rx destination 1 address register 1 (R/W) */
-#define VR4181_USBRXD1AREG2 __preg16(KSEG1 + 0x0A00062C) /* USB Rx destination 1 address register 2 (R/W) */
-#define VR4181_USBRXD2AREG1 __preg16(KSEG1 + 0x0A00062E) /* USB Rx destination 2 address register 1 (R/W) */
-#define VR4181_USBRXD2AREG2 __preg16(KSEG1 + 0x0A000630) /* USB Rx destination 2 address register 2 (R/W) */
-#define VR4181_USBTXD1AREG1 __preg16(KSEG1 + 0x0A000632) /* USB Tx destination 1 address register 1 (R/W) */
-#define VR4181_USBTXD1AREG2 __preg16(KSEG1 + 0x0A000634) /* USB Tx destination 1 address register 2 (R/W) */
-#define VR4181_USBTXD2AREG1 __preg16(KSEG1 + 0x0A000636) /* USB Tx destination 2 address register 1 (R/W) */
-#define VR4181_USBTXD2AREG2 __preg16(KSEG1 + 0x0A000638) /* USB Tx destination 2 address register 2 (R/W) */
-#define VR4181_RxRCLENREG __preg16(KSEG1 + 0x0A000652) /* USB Rx record length register (R/W) */
-#define VR4181_TxRCLENREG __preg16(KSEG1 + 0x0A000654) /* USB Tx record length register (R/W) */
-#define VR4181_MICRCLENREG __preg16(KSEG1 + 0x0A000658) /* Microphone record length register (R/W) */
-#define VR4181_SPKRCLENREG __preg16(KSEG1 + 0x0A00065A) /* Speaker record length register (R/W) */
-#define VR4181_USBCFGREG __preg16(KSEG1 + 0x0A00065C) /* USB configuration register (R/W) */
-#define VR4181_MICDMACFGREG __preg16(KSEG1 + 0x0A00065E) /* Microphone DMA configuration register (R/W) */
-#define VR4181_SPKDMACFGREG __preg16(KSEG1 + 0x0A000660) /* Speaker DMA configuration register (R/W) */
-#define VR4181_DMAITRQREG __preg16(KSEG1 + 0x0A000662) /* DMA interrupt request register (R/W) */
-#define VR4181_DMACLTREG __preg16(KSEG1 + 0x0A000664) /* DMA control register (R/W) */
-#define VR4181_DMAITMKREG __preg16(KSEG1 + 0x0A000666) /* DMA interrupt mask register (R/W) */
-
-// ISA Bridge
-#define VR4181_ISABRGCTL __preg16(KSEG1 + 0x0B0002C0) /* ISA Bridge Control Register (R/W) */
-#define VR4181_ISABRGSTS __preg16(KSEG1 + 0x0B0002C2) /* ISA Bridge Status Register (R/W) */
-#define VR4181_XISACTL __preg16(KSEG1 + 0x0B0002C4) /* External ISA Control Register (R/W) */
-
-// Clocked Serial Interface (CSI)
-#define VR4181_CSIMODE __preg16(KSEG1 + 0x0B000900) /* CSI Mode Register (R/W) */
-#define VR4181_CSIRXDATA __preg16(KSEG1 + 0x0B000902) /* CSI Receive Data Register (R) */
-#define VR4181_CSITXDATA __preg16(KSEG1 + 0x0B000904) /* CSI Transmit Data Register (R/W) */
-#define VR4181_CSILSTAT __preg16(KSEG1 + 0x0B000906) /* CSI Line Status Register (R/W) */
-#define VR4181_CSIINTMSK __preg16(KSEG1 + 0x0B000908) /* CSI Interrupt Mask Register (R/W) */
-#define VR4181_CSIINTSTAT __preg16(KSEG1 + 0x0B00090a) /* CSI Interrupt Status Register (R/W) */
-#define VR4181_CSITXBLEN __preg16(KSEG1 + 0x0B00090c) /* CSI Transmit Burst Length Register (R/W) */
-#define VR4181_CSIRXBLEN __preg16(KSEG1 + 0x0B00090e) /* CSI Receive Burst Length Register (R/W) */
-
-// Interrupt Control Unit (ICU)
-#define VR4181_SYSINT1REG __preg16(KSEG1 + 0x0A000080) /* Level 1 System interrupt register 1 (R) */
-#define VR4181_MSYSINT1REG __preg16(KSEG1 + 0x0A00008C) /* Level 1 mask system interrupt register 1 (R/W) */
-#define VR4181_NMIREG __preg16(KSEG1 + 0x0A000098) /* NMI register (R/W) */
-#define VR4181_SOFTINTREG __preg16(KSEG1 + 0x0A00009A) /* Software interrupt register (R/W) */
-#define VR4181_SYSINT2REG __preg16(KSEG1 + 0x0A000200) /* Level 1 System interrupt register 2 (R) */
-#define VR4181_MSYSINT2REG __preg16(KSEG1 + 0x0A000206) /* Level 1 mask system interrupt register 2 (R/W) */
-#define VR4181_PIUINTREGro __preg16(KSEG1 + 0x0B000082) /* Level 2 PIU interrupt register (R) */
-#define VR4181_AIUINTREG __preg16(KSEG1 + 0x0B000084) /* Level 2 AIU interrupt register (R) */
-#define VR4181_MPIUINTREG __preg16(KSEG1 + 0x0B00008E) /* Level 2 mask PIU interrupt register (R/W) */
-#define VR4181_MAIUINTREG __preg16(KSEG1 + 0x0B000090) /* Level 2 mask AIU interrupt register (R/W) */
-#define VR4181_MKIUINTREG __preg16(KSEG1 + 0x0B000092) /* Level 2 mask KIU interrupt register (R/W) */
-#define VR4181_KIUINTREG __preg16(KSEG1 + 0x0B000198) /* Level 2 KIU interrupt register (R) */
-
-// Power Management Unit (PMU)
-#define VR4181_PMUINTREG __preg16(KSEG1 + 0x0B0000A0) /* PMU Status Register (R/W) */
-#define VR4181_PMUINT_POWERSW 0x1 /* Power switch */
-#define VR4181_PMUINT_BATT 0x2 /* Low batt during normal operation */
-#define VR4181_PMUINT_DEADMAN 0x4 /* Deadman's switch */
-#define VR4181_PMUINT_RESET 0x8 /* Reset switch */
-#define VR4181_PMUINT_RTCRESET 0x10 /* RTC Reset */
-#define VR4181_PMUINT_TIMEOUT 0x20 /* HAL Timer Reset */
-#define VR4181_PMUINT_BATTLOW 0x100 /* Battery low */
-#define VR4181_PMUINT_RTC 0x200 /* RTC Alarm */
-#define VR4181_PMUINT_DCD 0x400 /* DCD# */
-#define VR4181_PMUINT_GPIO0 0x1000 /* GPIO0 */
-#define VR4181_PMUINT_GPIO1 0x2000 /* GPIO1 */
-#define VR4181_PMUINT_GPIO2 0x4000 /* GPIO2 */
-#define VR4181_PMUINT_GPIO3 0x8000 /* GPIO3 */
-
-#define VR4181_PMUCNTREG __preg16(KSEG1 + 0x0B0000A2) /* PMU Control Register (R/W) */
-#define VR4181_PMUWAITREG __preg16(KSEG1 + 0x0B0000A8) /* PMU Wait Counter Register (R/W) */
-#define VR4181_PMUDIVREG __preg16(KSEG1 + 0x0B0000AC) /* PMU Divide Mode Register (R/W) */
-#define VR4181_DRAMHIBCTL __preg16(KSEG1 + 0x0B0000B2) /* DRAM Hibernate Control Register (R/W) */
-
-// Real Time Clock Unit (RTC)
-#define VR4181_ETIMELREG __preg16(KSEG1 + 0x0B0000C0) /* Elapsed Time L Register (R/W) */
-#define VR4181_ETIMEMREG __preg16(KSEG1 + 0x0B0000C2) /* Elapsed Time M Register (R/W) */
-#define VR4181_ETIMEHREG __preg16(KSEG1 + 0x0B0000C4) /* Elapsed Time H Register (R/W) */
-#define VR4181_ECMPLREG __preg16(KSEG1 + 0x0B0000C8) /* Elapsed Compare L Register (R/W) */
-#define VR4181_ECMPMREG __preg16(KSEG1 + 0x0B0000CA) /* Elapsed Compare M Register (R/W) */
-#define VR4181_ECMPHREG __preg16(KSEG1 + 0x0B0000CC) /* Elapsed Compare H Register (R/W) */
-#define VR4181_RTCL1LREG __preg16(KSEG1 + 0x0B0000D0) /* RTC Long 1 L Register (R/W) */
-#define VR4181_RTCL1HREG __preg16(KSEG1 + 0x0B0000D2) /* RTC Long 1 H Register (R/W) */
-#define VR4181_RTCL1CNTLREG __preg16(KSEG1 + 0x0B0000D4) /* RTC Long 1 Count L Register (R) */
-#define VR4181_RTCL1CNTHREG __preg16(KSEG1 + 0x0B0000D6) /* RTC Long 1 Count H Register (R) */
-#define VR4181_RTCL2LREG __preg16(KSEG1 + 0x0B0000D8) /* RTC Long 2 L Register (R/W) */
-#define VR4181_RTCL2HREG __preg16(KSEG1 + 0x0B0000DA) /* RTC Long 2 H Register (R/W) */
-#define VR4181_RTCL2CNTLREG __preg16(KSEG1 + 0x0B0000DC) /* RTC Long 2 Count L Register (R) */
-#define VR4181_RTCL2CNTHREG __preg16(KSEG1 + 0x0B0000DE) /* RTC Long 2 Count H Register (R) */
-#define VR4181_RTCINTREG __preg16(KSEG1 + 0x0B0001DE) /* RTC Interrupt Register (R/W) */
-
-// Deadman's Switch Unit (DSU)
-#define VR4181_DSUCNTREG __preg16(KSEG1 + 0x0B0000E0) /* DSU Control Register (R/W) */
-#define VR4181_DSUSETREG __preg16(KSEG1 + 0x0B0000E2) /* DSU Dead Time Set Register (R/W) */
-#define VR4181_DSUCLRREG __preg16(KSEG1 + 0x0B0000E4) /* DSU Clear Register (W) */
-#define VR4181_DSUTIMREG __preg16(KSEG1 + 0x0B0000E6) /* DSU Elapsed Time Register (R/W) */
-
-// General Purpose I/O Unit (GIU)
-#define VR4181_GPMD0REG __preg16(KSEG1 + 0x0B000300) /* GPIO Mode 0 Register (R/W) */
-#define VR4181_GPMD1REG __preg16(KSEG1 + 0x0B000302) /* GPIO Mode 1 Register (R/W) */
-#define VR4181_GPMD2REG __preg16(KSEG1 + 0x0B000304) /* GPIO Mode 2 Register (R/W) */
-#define VR4181_GPMD3REG __preg16(KSEG1 + 0x0B000306) /* GPIO Mode 3 Register (R/W) */
-#define VR4181_GPDATHREG __preg16(KSEG1 + 0x0B000308) /* GPIO Data High Register (R/W) */
-#define VR4181_GPDATHREG_GPIO16 0x0001
-#define VR4181_GPDATHREG_GPIO17 0x0002
-#define VR4181_GPDATHREG_GPIO18 0x0004
-#define VR4181_GPDATHREG_GPIO19 0x0008
-#define VR4181_GPDATHREG_GPIO20 0x0010
-#define VR4181_GPDATHREG_GPIO21 0x0020
-#define VR4181_GPDATHREG_GPIO22 0x0040
-#define VR4181_GPDATHREG_GPIO23 0x0080
-#define VR4181_GPDATHREG_GPIO24 0x0100
-#define VR4181_GPDATHREG_GPIO25 0x0200
-#define VR4181_GPDATHREG_GPIO26 0x0400
-#define VR4181_GPDATHREG_GPIO27 0x0800
-#define VR4181_GPDATHREG_GPIO28 0x1000
-#define VR4181_GPDATHREG_GPIO29 0x2000
-#define VR4181_GPDATHREG_GPIO30 0x4000
-#define VR4181_GPDATHREG_GPIO31 0x8000
-#define VR4181_GPDATLREG __preg16(KSEG1 + 0x0B00030A) /* GPIO Data Low Register (R/W) */
-#define VR4181_GPDATLREG_GPIO0 0x0001
-#define VR4181_GPDATLREG_GPIO1 0x0002
-#define VR4181_GPDATLREG_GPIO2 0x0004
-#define VR4181_GPDATLREG_GPIO3 0x0008
-#define VR4181_GPDATLREG_GPIO4 0x0010
-#define VR4181_GPDATLREG_GPIO5 0x0020
-#define VR4181_GPDATLREG_GPIO6 0x0040
-#define VR4181_GPDATLREG_GPIO7 0x0080
-#define VR4181_GPDATLREG_GPIO8 0x0100
-#define VR4181_GPDATLREG_GPIO9 0x0200
-#define VR4181_GPDATLREG_GPIO10 0x0400
-#define VR4181_GPDATLREG_GPIO11 0x0800
-#define VR4181_GPDATLREG_GPIO12 0x1000
-#define VR4181_GPDATLREG_GPIO13 0x2000
-#define VR4181_GPDATLREG_GPIO14 0x4000
-#define VR4181_GPDATLREG_GPIO15 0x8000
-#define VR4181_GPINTEN __preg16(KSEG1 + 0x0B00030C) /* GPIO Interrupt Enable Register (R/W) */
-#define VR4181_GPINTMSK __preg16(KSEG1 + 0x0B00030E) /* GPIO Interrupt Mask Register (R/W) */
-#define VR4181_GPINTTYPH __preg16(KSEG1 + 0x0B000310) /* GPIO Interrupt Type High Register (R/W) */
-#define VR4181_GPINTTYPL __preg16(KSEG1 + 0x0B000312) /* GPIO Interrupt Type Low Register (R/W) */
-#define VR4181_GPINTSTAT __preg16(KSEG1 + 0x0B000314) /* GPIO Interrupt Status Register (R/W) */
-#define VR4181_GPHIBSTH __preg16(KSEG1 + 0x0B000316) /* GPIO Hibernate Pin State High Register (R/W) */
-#define VR4181_GPHIBSTL __preg16(KSEG1 + 0x0B000318) /* GPIO Hibernate Pin State Low Register (R/W) */
-#define VR4181_GPSICTL __preg16(KSEG1 + 0x0B00031A) /* GPIO Serial Interface Control Register (R/W) */
-#define VR4181_KEYEN __preg16(KSEG1 + 0x0B00031C) /* Keyboard Scan Pin Enable Register (R/W) */
-#define VR4181_PCS0STRA __preg16(KSEG1 + 0x0B000320) /* Programmable Chip Select [0] Start Address Register (R/W) */
-#define VR4181_PCS0STPA __preg16(KSEG1 + 0x0B000322) /* Programmable Chip Select [0] Stop Address Register (R/W) */
-#define VR4181_PCS0HIA __preg16(KSEG1 + 0x0B000324) /* Programmable Chip Select [0] High Address Register (R/W) */
-#define VR4181_PCS1STRA __preg16(KSEG1 + 0x0B000326) /* Programmable Chip Select [1] Start Address Register (R/W) */
-#define VR4181_PCS1STPA __preg16(KSEG1 + 0x0B000328) /* Programmable Chip Select [1] Stop Address Register (R/W) */
-#define VR4181_PCS1HIA __preg16(KSEG1 + 0x0B00032A) /* Programmable Chip Select [1] High Address Register (R/W) */
-#define VR4181_PCSMODE __preg16(KSEG1 + 0x0B00032C) /* Programmable Chip Select Mode Register (R/W) */
-#define VR4181_LCDGPMODE __preg16(KSEG1 + 0x0B00032E) /* LCD General Purpose Mode Register (R/W) */
-#define VR4181_MISCREG0 __preg16(KSEG1 + 0x0B000330) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG1 __preg16(KSEG1 + 0x0B000332) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG2 __preg16(KSEG1 + 0x0B000334) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG3 __preg16(KSEG1 + 0x0B000336) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG4 __preg16(KSEG1 + 0x0B000338) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG5 __preg16(KSEG1 + 0x0B00033A) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG6 __preg16(KSEG1 + 0x0B00033C) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG7 __preg16(KSEG1 + 0x0B00033D) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG8 __preg16(KSEG1 + 0x0B000340) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG9 __preg16(KSEG1 + 0x0B000342) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG10 __preg16(KSEG1 + 0x0B000344) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG11 __preg16(KSEG1 + 0x0B000346) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG12 __preg16(KSEG1 + 0x0B000348) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG13 __preg16(KSEG1 + 0x0B00034A) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG14 __preg16(KSEG1 + 0x0B00034C) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_MISCREG15 __preg16(KSEG1 + 0x0B00034E) /* Misc. R/W Battery Backed Registers for Non-Volatile Storage (R/W) */
-#define VR4181_SECIRQMASKL VR4181_GPINTEN
-// No SECIRQMASKH for VR4181
-
-// Touch Panel Interface Unit (PIU)
-#define VR4181_PIUCNTREG __preg16(KSEG1 + 0x0B000122) /* PIU Control register (R/W) */
-#define VR4181_PIUCNTREG_PIUSEQEN 0x0004
-#define VR4181_PIUCNTREG_PIUPWR 0x0002
-#define VR4181_PIUCNTREG_PADRST 0x0001
-
-#define VR4181_PIUINTREG __preg16(KSEG1 + 0x0B000124) /* PIU Interrupt cause register (R/W) */
-#define VR4181_PIUINTREG_OVP 0x8000
-#define VR4181_PIUINTREG_PADCMD 0x0040
-#define VR4181_PIUINTREG_PADADP 0x0020
-#define VR4181_PIUINTREG_PADPAGE1 0x0010
-#define VR4181_PIUINTREG_PADPAGE0 0x0008
-#define VR4181_PIUINTREG_PADDLOST 0x0004
-#define VR4181_PIUINTREG_PENCHG 0x0001
-
-#define VR4181_PIUSIVLREG __preg16(KSEG1 + 0x0B000126) /* PIU Data sampling interval register (R/W) */
-#define VR4181_PIUSTBLREG __preg16(KSEG1 + 0x0B000128) /* PIU A/D converter start delay register (R/W) */
-#define VR4181_PIUCMDREG __preg16(KSEG1 + 0x0B00012A) /* PIU A/D command register (R/W) */
-#define VR4181_PIUASCNREG __preg16(KSEG1 + 0x0B000130) /* PIU A/D port scan register (R/W) */
-#define VR4181_PIUAMSKREG __preg16(KSEG1 + 0x0B000132) /* PIU A/D scan mask register (R/W) */
-#define VR4181_PIUCIVLREG __preg16(KSEG1 + 0x0B00013E) /* PIU Check interval register (R) */
-#define VR4181_PIUPB00REG __preg16(KSEG1 + 0x0B0002A0) /* PIU Page 0 Buffer 0 register (R/W) */
-#define VR4181_PIUPB01REG __preg16(KSEG1 + 0x0B0002A2) /* PIU Page 0 Buffer 1 register (R/W) */
-#define VR4181_PIUPB02REG __preg16(KSEG1 + 0x0B0002A4) /* PIU Page 0 Buffer 2 register (R/W) */
-#define VR4181_PIUPB03REG __preg16(KSEG1 + 0x0B0002A6) /* PIU Page 0 Buffer 3 register (R/W) */
-#define VR4181_PIUPB10REG __preg16(KSEG1 + 0x0B0002A8) /* PIU Page 1 Buffer 0 register (R/W) */
-#define VR4181_PIUPB11REG __preg16(KSEG1 + 0x0B0002AA) /* PIU Page 1 Buffer 1 register (R/W) */
-#define VR4181_PIUPB12REG __preg16(KSEG1 + 0x0B0002AC) /* PIU Page 1 Buffer 2 register (R/W) */
-#define VR4181_PIUPB13REG __preg16(KSEG1 + 0x0B0002AE) /* PIU Page 1 Buffer 3 register (R/W) */
-#define VR4181_PIUAB0REG __preg16(KSEG1 + 0x0B0002B0) /* PIU A/D scan Buffer 0 register (R/W) */
-#define VR4181_PIUAB1REG __preg16(KSEG1 + 0x0B0002B2) /* PIU A/D scan Buffer 1 register (R/W) */
-#define VR4181_PIUAB2REG __preg16(KSEG1 + 0x0B0002B4) /* PIU A/D scan Buffer 2 register (R/W) */
-#define VR4181_PIUAB3REG __preg16(KSEG1 + 0x0B0002B6) /* PIU A/D scan Buffer 3 register (R/W) */
-#define VR4181_PIUPB04REG __preg16(KSEG1 + 0x0B0002BC) /* PIU Page 0 Buffer 4 register (R/W) */
-#define VR4181_PIUPB14REG __preg16(KSEG1 + 0x0B0002BE) /* PIU Page 1 Buffer 4 register (R/W) */
-
-// Audio Interface Unit (AIU)
-#define VR4181_SODATREG __preg16(KSEG1 + 0x0B000166) /* Speaker Output Data Register (R/W) */
-#define VR4181_SCNTREG __preg16(KSEG1 + 0x0B000168) /* Speaker Output Control Register (R/W) */
-#define VR4181_MIDATREG __preg16(KSEG1 + 0x0B000170) /* Mike Input Data Register (R/W) */
-#define VR4181_MCNTREG __preg16(KSEG1 + 0x0B000172) /* Mike Input Control Register (R/W) */
-#define VR4181_DVALIDREG __preg16(KSEG1 + 0x0B000178) /* Data Valid Register (R/W) */
-#define VR4181_SEQREG __preg16(KSEG1 + 0x0B00017A) /* Sequential Register (R/W) */
-#define VR4181_INTREG __preg16(KSEG1 + 0x0B00017C) /* Interrupt Register (R/W) */
-#define VR4181_SDMADATREG __preg16(KSEG1 + 0x0B000160) /* Speaker DMA Data Register (R/W) */
-#define VR4181_MDMADATREG __preg16(KSEG1 + 0x0B000162) /* Microphone DMA Data Register (R/W) */
-#define VR4181_DAVREF_SETUP __preg16(KSEG1 + 0x0B000164) /* DAC Vref setup register (R/W) */
-#define VR4181_SCNVC_END __preg16(KSEG1 + 0x0B00016E) /* Speaker sample rate control (R/W) */
-#define VR4181_MIDATREG __preg16(KSEG1 + 0x0B000170) /* Microphone Input Data Register (R/W) */
-#define VR4181_MCNTREG __preg16(KSEG1 + 0x0B000172) /* Microphone Input Control Register (R/W) */
-#define VR4181_MCNVC_END __preg16(KSEG1 + 0x0B00017E) /* Microphone sample rate control (R/W) */
-
-// Keyboard Interface Unit (KIU)
-#define VR4181_KIUDAT0 __preg16(KSEG1 + 0x0B000180) /* KIU Data0 Register (R/W) */
-#define VR4181_KIUDAT1 __preg16(KSEG1 + 0x0B000182) /* KIU Data1 Register (R/W) */
-#define VR4181_KIUDAT2 __preg16(KSEG1 + 0x0B000184) /* KIU Data2 Register (R/W) */
-#define VR4181_KIUDAT3 __preg16(KSEG1 + 0x0B000186) /* KIU Data3 Register (R/W) */
-#define VR4181_KIUDAT4 __preg16(KSEG1 + 0x0B000188) /* KIU Data4 Register (R/W) */
-#define VR4181_KIUDAT5 __preg16(KSEG1 + 0x0B00018A) /* KIU Data5 Register (R/W) */
-#define VR4181_KIUSCANREP __preg16(KSEG1 + 0x0B000190) /* KIU Scan/Repeat Register (R/W) */
-#define VR4181_KIUSCANREP_KEYEN 0x8000
-#define VR4181_KIUSCANREP_SCANSTP 0x0008
-#define VR4181_KIUSCANREP_SCANSTART 0x0004
-#define VR4181_KIUSCANREP_ATSTP 0x0002
-#define VR4181_KIUSCANREP_ATSCAN 0x0001
-#define VR4181_KIUSCANS __preg16(KSEG1 + 0x0B000192) /* KIU Scan Status Register (R) */
-#define VR4181_KIUWKS __preg16(KSEG1 + 0x0B000194) /* KIU Wait Keyscan Stable Register (R/W) */
-#define VR4181_KIUWKI __preg16(KSEG1 + 0x0B000196) /* KIU Wait Keyscan Interval Register (R/W) */
-#define VR4181_KIUINT __preg16(KSEG1 + 0x0B000198) /* KIU Interrupt Register (R/W) */
-#define VR4181_KIUINT_KDATLOST 0x0004
-#define VR4181_KIUINT_KDATRDY 0x0002
-#define VR4181_KIUINT_SCANINT 0x0001
-#define VR4181_KIUDAT6 __preg16(KSEG1 + 0x0B00018C) /* Scan Line 6 Key Data Register (R) */
-#define VR4181_KIUDAT7 __preg16(KSEG1 + 0x0B00018E) /* Scan Line 7 Key Data Register (R) */
-
-// CompactFlash Controller
-#define VR4181_PCCARDINDEX __preg8(KSEG1 + 0x0B0008E0) /* PC Card Controller Index Register */
-#define VR4181_PCCARDDATA __preg8(KSEG1 + 0x0B0008E1) /* PC Card Controller Data Register */
-#define VR4181_INTSTATREG __preg16(KSEG1 + 0x0B0008F8) /* Interrupt Status Register (R/W) */
-#define VR4181_INTMSKREG __preg16(KSEG1 + 0x0B0008FA) /* Interrupt Mask Register (R/W) */
-#define VR4181_CFG_REG_1 __preg16(KSEG1 + 0x0B0008FE) /* Configuration Register 1 */
-
-// LED Control Unit (LED)
-#define VR4181_LEDHTSREG __preg16(KSEG1 + 0x0B000240) /* LED H Time Set register (R/W) */
-#define VR4181_LEDLTSREG __preg16(KSEG1 + 0x0B000242) /* LED L Time Set register (R/W) */
-#define VR4181_LEDCNTREG __preg16(KSEG1 + 0x0B000248) /* LED Control register (R/W) */
-#define VR4181_LEDASTCREG __preg16(KSEG1 + 0x0B00024A) /* LED Auto Stop Time Count register (R/W) */
-#define VR4181_LEDINTREG __preg16(KSEG1 + 0x0B00024C) /* LED Interrupt register (R/W) */
-
-// Serial Interface Unit (SIU / SIU1 and SIU2)
-#define VR4181_SIURB __preg8(KSEG1 + 0x0C000010) /* Receiver Buffer Register (Read) DLAB = 0 (R) */
-#define VR4181_SIUTH __preg8(KSEG1 + 0x0C000010) /* Transmitter Holding Register (Write) DLAB = 0 (W) */
-#define VR4181_SIUDLL __preg8(KSEG1 + 0x0C000010) /* Divisor Latch (Least Significant Byte) DLAB = 1 (R/W) */
-#define VR4181_SIUIE __preg8(KSEG1 + 0x0C000011) /* Interrupt Enable DLAB = 0 (R/W) */
-#define VR4181_SIUDLM __preg8(KSEG1 + 0x0C000011) /* Divisor Latch (Most Significant Byte) DLAB = 1 (R/W) */
-#define VR4181_SIUIID __preg8(KSEG1 + 0x0C000012) /* Interrupt Identification Register (Read) (R) */
-#define VR4181_SIUFC __preg8(KSEG1 + 0x0C000012) /* FIFO Control Register (Write) (W) */
-#define VR4181_SIULC __preg8(KSEG1 + 0x0C000013) /* Line Control Register (R/W) */
-#define VR4181_SIUMC __preg8(KSEG1 + 0x0C000014) /* MODEM Control Register (R/W) */
-#define VR4181_SIULS __preg8(KSEG1 + 0x0C000015) /* Line Status Register (R/W) */
-#define VR4181_SIUMS __preg8(KSEG1 + 0x0C000016) /* MODEM Status Register (R/W) */
-#define VR4181_SIUSC __preg8(KSEG1 + 0x0C000017) /* Scratch Register (R/W) */
-#define VR4181_SIURESET __preg8(KSEG1 + 0x0C000019) /* SIU Reset Register (R/W) */
-#define VR4181_SIUACTMSK __preg8(KSEG1 + 0x0C00001C) /* SIU Activity Mask (R/W) */
-#define VR4181_SIUACTTMR __preg8(KSEG1 + 0x0C00001E) /* SIU Activity Timer (R/W) */
-#define VR4181_SIURB_2 __preg8(KSEG1 + 0x0C000000) /* Receive Buffer Register (Read) (R) */
-#define VR4181_SIUTH_2 __preg8(KSEG1 + 0x0C000000) /* Transmitter Holding Register (Write) (W) */
-#define VR4181_SIUDLL_2 __preg8(KSEG1 + 0x0C000000) /* Divisor Latch (Least Significant Byte) (R/W) */
-#define VR4181_SIUIE_2 __preg8(KSEG1 + 0x0C000001) /* Interrupt Enable (DLAB = 0) (R/W) */
-#define VR4181_SIUDLM_2 __preg8(KSEG1 + 0x0C000001) /* Divisor Latch (Most Significant Byte) (DLAB = 1) (R/W) */
-#define VR4181_SIUIID_2 __preg8(KSEG1 + 0x0C000002) /* Interrupt Identification Register (Read) (R) */
-#define VR4181_SIUFC_2 __preg8(KSEG1 + 0x0C000002) /* FIFO Control Register (Write) (W) */
-#define VR4181_SIULC_2 __preg8(KSEG1 + 0x0C000003) /* Line Control Register (R/W) */
-#define VR4181_SIUMC_2 __preg8(KSEG1 + 0x0C000004) /* Modem Control Register (R/W) */
-#define VR4181_SIULS_2 __preg8(KSEG1 + 0x0C000005) /* Line Status Register (R/W) */
-#define VR4181_SIUMS_2 __preg8(KSEG1 + 0x0C000006) /* Modem Status Register (R/W) */
-#define VR4181_SIUSC_2 __preg8(KSEG1 + 0x0C000007) /* Scratch Register (R/W) */
-#define VR4181_SIUIRSEL_2 __preg8(KSEG1 + 0x0C000008) /* SIU IrDA Selectot (R/W) */
-#define VR4181_SIURESET_2 __preg8(KSEG1 + 0x0C000009) /* SIU Reset Register (R/W) */
-#define VR4181_SIUCSEL_2 __preg8(KSEG1 + 0x0C00000A) /* IrDA Echo-back Control (R/W) */
-#define VR4181_SIUACTMSK_2 __preg8(KSEG1 + 0x0C00000C) /* SIU Activity Mask Register (R/W) */
-#define VR4181_SIUACTTMR_2 __preg8(KSEG1 + 0x0C00000E) /* SIU Activity Timer Register (R/W) */
-
-
-// USB Module
-#define VR4181_USBINFIFO __preg16(KSEG1 + 0x0B000780) /* USB Bulk Input FIFO (Bulk In End Point) (W) */
-#define VR4181_USBOUTFIFO __preg16(KSEG1 + 0x0B000782) /* USB Bulk Output FIFO (Bulk Out End Point) (R) */
-#define VR4181_USBCTLFIFO __preg16(KSEG1 + 0x0B000784) /* USB Control FIFO (Control End Point) (W) */
-#define VR4181_USBSTAT __preg16(KSEG1 + 0x0B000786) /* Interrupt Status Register (R/W) */
-#define VR4181_USBINTMSK __preg16(KSEG1 + 0x0B000788) /* Interrupt Mask Register (R/W) */
-#define VR4181_USBCTLREG __preg16(KSEG1 + 0x0B00078A) /* Control Register (R/W) */
-#define VR4181_USBSTPREG __preg16(KSEG1 + 0x0B00078C) /* USB Transfer Stop Register (R/W) */
-
-// LCD Controller
-#define VR4181_HRTOTALREG __preg16(KSEG1 + 0x0A000400) /* Horizontal total Register (R/W) */
-#define VR4181_HRVISIBREG __preg16(KSEG1 + 0x0A000402) /* Horizontal Visible Register (R/W) */
-#define VR4181_LDCLKSTREG __preg16(KSEG1 + 0x0A000404) /* Load clock start Register (R/W) */
-#define VR4181_LDCLKNDREG __preg16(KSEG1 + 0x0A000406) /* Load clock end Register (R/W) */
-#define VR4181_VRTOTALREG __preg16(KSEG1 + 0x0A000408) /* Vertical Total Register (R/W) */
-#define VR4181_VRVISIBREG __preg16(KSEG1 + 0x0A00040A) /* Vertical Visible Register (R/W) */
-#define VR4181_FVSTARTREG __preg16(KSEG1 + 0x0A00040C) /* FLM vertical start Register (R/W) */
-#define VR4181_FVENDREG __preg16(KSEG1 + 0x0A00040E) /* FLM vertical end Register (R/W) */
-#define VR4181_LCDCTRLREG __preg16(KSEG1 + 0x0A000410) /* LCD control Register (R/W) */
-#define VR4181_LCDINRQREG __preg16(KSEG1 + 0x0A000412) /* LCD Interrupt request Register (R/W) */
-#define VR4181_LCDCFGREG0 __preg16(KSEG1 + 0x0A000414) /* LCD Configuration Register 0 (R/W) */
-#define VR4181_LCDCFGREG1 __preg16(KSEG1 + 0x0A000416) /* LCD Configuration Register 1 (R/W) */
-#define VR4181_FBSTAD1REG __preg16(KSEG1 + 0x0A000418) /* Frame Buffer Start Address 1 Register (R/W) */
-#define VR4181_FBSTAD2REG __preg16(KSEG1 + 0x0A00041A) /* Frame Buffer Start Address 2 Register (R/W) */
-#define VR4181_FBNDAD1REG __preg16(KSEG1 + 0x0A000420) /* Frame Buffer End Address 1 Register (R/W) */
-#define VR4181_FBNDAD2REG __preg16(KSEG1 + 0x0A000422) /* Frame Buffer End Address 2 register (R/W) */
-#define VR4181_FHSTARTREG __preg16(KSEG1 + 0x0A000424) /* FLM horizontal Start Register (R/W) */
-#define VR4181_FHENDREG __preg16(KSEG1 + 0x0A000426) /* FLM horizontal End Register (R/W) */
-#define VR4181_PWRCONREG1 __preg16(KSEG1 + 0x0A000430) /* Power Control register 1 (R/W) */
-#define VR4181_PWRCONREG2 __preg16(KSEG1 + 0x0A000432) /* Power Control register 2 (R/W) */
-#define VR4181_LCDIMSKREG __preg16(KSEG1 + 0x0A000434) /* LCD Interrupt Mask register (R/W) */
-#define VR4181_CPINDCTREG __preg16(KSEG1 + 0x0A00047E) /* Color palette Index and control Register (R/W) */
-#define VR4181_CPALDATREG __preg32(KSEG1 + 0x0A000480) /* Color palette data register (32bits Register) (R/W) */
-
-// physical address spaces
-#define VR4181_LCD 0x0a000000
-#define VR4181_INTERNAL_IO_2 0x0b000000
-#define VR4181_INTERNAL_IO_1 0x0c000000
-#define VR4181_ISA_MEM 0x10000000
-#define VR4181_ISA_IO 0x14000000
-#define VR4181_ROM 0x18000000
-
-// This is the base address for IO port decoding to which the 16 bit IO port address
-// is added. Defining it to 0 will usually cause a kernel oops any time port IO is
-// attempted, which can be handy for turning up parts of the kernel that make
-// incorrect architecture assumptions (by assuming that everything acts like a PC),
-// but we need it correctly defined to use the PCMCIA/CF controller:
-#define VR4181_PORT_BASE (KSEG1 + VR4181_ISA_IO)
-#define VR4181_ISAMEM_BASE (KSEG1 + VR4181_ISA_MEM)
-
-#endif /* __ASM_VR4181_VR4181_H */
diff --git a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/include/asm-mips/vr41xx/tb0287.h
index 5c1b757bfb0c..dd9832313afe 100644
--- a/arch/mips/vr41xx/tanbac-tb0229/setup.c
+++ b/include/asm-mips/vr41xx/tb0287.h
@@ -1,10 +1,9 @@
/*
- * setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
+ * tb0287.h, Include file for TANBAC TB0287 mini-ITX board.
*
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Media Lab Inc. <ito@mlb.co.jp>
*
- * Modified for TANBAC TB0229:
- * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
+ * This code is largely based on tb0219.h.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,8 +19,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef __TANBAC_TB0287_H
+#define __TANBAC_TB0287_H
-const char *get_system_type(void)
-{
- return "TANBAC TB0229";
-}
+#include <asm/vr41xx/vr41xx.h>
+
+/*
+ * General-Purpose I/O Pin Number
+ */
+#define TB0287_PCI_SLOT_PIN 2
+#define TB0287_SM501_PIN 3
+#define TB0287_SIL680A_PIN 8
+#define TB0287_RTL8110_PIN 13
+
+/*
+ * Interrupt Number
+ */
+#define TB0287_PCI_SLOT_IRQ GIU_IRQ(TB0287_PCI_SLOT_PIN)
+#define TB0287_SM501_IRQ GIU_IRQ(TB0287_SM501_PIN)
+#define TB0287_SIL680A_IRQ GIU_IRQ(TB0287_SIL680A_PIN)
+#define TB0287_RTL8110_IRQ GIU_IRQ(TB0287_RTL8110_PIN)
+
+#endif /* __TANBAC_TB0287_H */
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index 7d41e44463f9..bd2723c30901 100644
--- a/include/asm-mips/vr41xx/vr41xx.h
+++ b/include/asm-mips/vr41xx/vr41xx.h
@@ -7,7 +7,7 @@
* Copyright (C) 2001, 2002 Paul Mundt
* Copyright (C) 2002 MontaVista Software, Inc.
* Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -79,11 +79,11 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
#define MIPS_SOFTINT0_IRQ MIPS_CPU_IRQ(0)
#define MIPS_SOFTINT1_IRQ MIPS_CPU_IRQ(1)
-#define INT0_CASCADE_IRQ MIPS_CPU_IRQ(2)
-#define INT1_CASCADE_IRQ MIPS_CPU_IRQ(3)
-#define INT2_CASCADE_IRQ MIPS_CPU_IRQ(4)
-#define INT3_CASCADE_IRQ MIPS_CPU_IRQ(5)
-#define INT4_CASCADE_IRQ MIPS_CPU_IRQ(6)
+#define INT0_IRQ MIPS_CPU_IRQ(2)
+#define INT1_IRQ MIPS_CPU_IRQ(3)
+#define INT2_IRQ MIPS_CPU_IRQ(4)
+#define INT3_IRQ MIPS_CPU_IRQ(5)
+#define INT4_IRQ MIPS_CPU_IRQ(6)
#define TIMER_IRQ MIPS_CPU_IRQ(7)
/* SYINT1 Interrupt Numbers */
@@ -97,7 +97,7 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
#define PIU_IRQ SYSINT1_IRQ(5)
#define AIU_IRQ SYSINT1_IRQ(6)
#define KIU_IRQ SYSINT1_IRQ(7)
-#define GIUINT_CASCADE_IRQ SYSINT1_IRQ(8)
+#define GIUINT_IRQ SYSINT1_IRQ(8)
#define SIU_IRQ SYSINT1_IRQ(9)
#define BUSERR_IRQ SYSINT1_IRQ(10)
#define SOFTINT_IRQ SYSINT1_IRQ(11)
@@ -128,7 +128,7 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
#define GIU_IRQ_LAST GIU_IRQ(31)
extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
-extern int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq));
+extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *));
#define PIUINT_COMMAND 0x0040
#define PIUINT_DATA 0x0020
diff --git a/include/asm-mips/vr41xx/vrc4173.h b/include/asm-mips/vr41xx/vrc4173.h
index 58e193c51b45..bb7a85c186e4 100644
--- a/include/asm-mips/vr41xx/vrc4173.h
+++ b/include/asm-mips/vr41xx/vrc4173.h
@@ -21,8 +21,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __NEC_VRC4173_H
-#define __NEC_VRC4173_H
+#ifndef __NEC_VRC4173_H
+#define __NEC_VRC4173_H
#include <linux/config.h>
#include <asm/io.h>
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index c4a704121343..04ee53b34c2e 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -113,7 +113,7 @@
*/
#define BCM1250_M3_WAR 1
-/*
+/*
* This is a DUART workaround related to glitches around register accesses
*/
#define SIBYTE_1956_WAR 1
@@ -122,7 +122,7 @@
/*
* Fill buffers not flushed on CACHE instructions
- *
+ *
* Hit_Invalidate_I cacheops invalidate an icache line but the refill
* for that line can get stale data from the fill buffer instead of
* accessing memory if the previous icache miss was also to that line.
diff --git a/include/asm-mips/xxs1500.h b/include/asm-mips/xxs1500.h
index 75c0ddfeca13..4d84a90b0f20 100644
--- a/include/asm-mips/xxs1500.h
+++ b/include/asm-mips/xxs1500.h
@@ -22,7 +22,7 @@
*
* ########################################################################
*
- *
+ *
*/
#ifndef __ASM_XXS1500_H
#define __ASM_XXS1500_H
diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
index cbc286f49b36..30b023411fef 100644
--- a/include/asm-parisc/assembly.h
+++ b/include/asm-parisc/assembly.h
@@ -63,7 +63,7 @@
.level 2.0w
#endif
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/asmregs.h>
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index e24f7579adb0..048a2c7fd0c0 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -24,19 +24,19 @@
# define ATOMIC_HASH_SIZE 4
# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
-extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
+extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
-/* Can't use _raw_spin_lock_irq because of #include problems, so
+/* Can't use raw_spin_lock_irq because of #include problems, so
* this is the substitute */
#define _atomic_spin_lock_irqsave(l,f) do { \
- spinlock_t *s = ATOMIC_HASH(l); \
+ raw_spinlock_t *s = ATOMIC_HASH(l); \
local_irq_save(f); \
- _raw_spin_lock(s); \
+ __raw_spin_lock(s); \
} while(0)
#define _atomic_spin_unlock_irqrestore(l,f) do { \
- spinlock_t *s = ATOMIC_HASH(l); \
- _raw_spin_unlock(s); \
+ raw_spinlock_t *s = ATOMIC_HASH(l); \
+ __raw_spin_unlock(s); \
local_irq_restore(f); \
} while(0)
diff --git a/include/asm-parisc/auxvec.h b/include/asm-parisc/auxvec.h
new file mode 100644
index 000000000000..9c3ac4b89dc9
--- /dev/null
+++ b/include/asm-parisc/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMPARISC_AUXVEC_H
+#define __ASMPARISC_AUXVEC_H
+
+#endif
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 928e5ef850bd..af7db694b22d 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -2,7 +2,7 @@
#define _PARISC_BITOPS_H
#include <linux/compiler.h>
-#include <asm/system.h>
+#include <asm/spinlock.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 06732719d927..aa592d8c0e39 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -3,6 +3,7 @@
#include <linux/config.h>
#include <linux/mm.h>
+#include <asm/cache.h> /* for flush_user_dcache_range_asm() proto */
/* The usual comment is "Caches aren't brain-dead on the <architecture>".
* Unfortunately, that doesn't apply to PA-RISC. */
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 7630d1ad2391..38b918feead9 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -13,8 +13,10 @@ typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
-typedef u32 compat_uid_t;
-typedef u32 compat_gid_t;
+typedef u32 __compat_uid_t;
+typedef u32 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u32 compat_dev_t;
@@ -67,8 +69,8 @@ struct compat_stat {
compat_dev_t st_realdev;
u16 st_basemode;
u16 st_spareshort;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid32_t st_uid;
+ __compat_gid32_t st_gid;
u32 st_spare4[3];
};
diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
index def35230716a..317851fa78f3 100644
--- a/include/asm-parisc/fcntl.h
+++ b/include/asm-parisc/fcntl.h
@@ -3,38 +3,22 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_ACCMODE 00000003
-#define O_RDONLY 00000000
-#define O_WRONLY 00000001
-#define O_RDWR 00000002
#define O_APPEND 00000010
#define O_BLKSEEK 00000100 /* HPUX only */
#define O_CREAT 00000400 /* not fcntl */
-#define O_TRUNC 00001000 /* not fcntl */
#define O_EXCL 00002000 /* not fcntl */
#define O_LARGEFILE 00004000
#define O_SYNC 00100000
#define O_NONBLOCK 00200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NDELAY O_NONBLOCK
#define O_NOCTTY 00400000 /* not fcntl */
#define O_DSYNC 01000000 /* HPUX only */
#define O_RSYNC 02000000 /* HPUX only */
#define O_NOATIME 04000000
-#define FASYNC 00020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 00040000 /* direct disk access hint - currently ignored */
#define O_DIRECTORY 00010000 /* must be a directory */
#define O_NOFOLLOW 00000200 /* don't follow links */
#define O_INVISIBLE 04000000 /* invisible I/O, for DMAPI/XDSM */
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get f_flags */
-#define F_SETFD 2 /* set f_flags */
-#define F_GETFL 3 /* more flags (cloexec) */
-#define F_SETFL 4
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
#define F_GETLK64 8
#define F_SETLK64 9
#define F_SETLKW64 10
@@ -44,49 +28,11 @@
#define F_SETSIG 13 /* for sockets. */
#define F_GETSIG 14 /* for sockets. */
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
/* for posix fcntl() and lockf() */
#define F_RDLCK 01
#define F_WRLCK 02
#define F_UNLCK 03
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
+#include <asm-generic/fcntl.h>
#endif
diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-parisc/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-parisc/hdreg.h b/include/asm-parisc/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-parisc/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index 75654ba93353..f876bdf22056 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -26,6 +26,11 @@
#define NR_IRQS (CPU_IRQ_MAX + 1)
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
static __inline__ int irq_canonicalize(int irq)
{
return (irq == 2) ? 9 : irq;
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 4a12692f94b4..44eae9f8274d 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -74,20 +74,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
typedef struct __physmem_range {
unsigned long start_pfn;
unsigned long pages; /* PAGE_SIZE pages */
@@ -159,4 +145,6 @@ extern int npmem_ranges;
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _PARISC_PAGE_H */
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 98d79a3d54fa..d0b761f690b5 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -257,6 +257,19 @@ extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
{
}
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index f001bb01e38f..820c6e712cd7 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -498,9 +498,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif /* !__ASSEMBLY__ */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index 0b61f51d8467..a9dfadd05658 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -11,6 +11,7 @@
#ifndef __ASSEMBLY__
#include <linux/config.h>
#include <linux/threads.h>
+#include <linux/spinlock_types.h>
#include <asm/hardware.h>
#include <asm/page.h>
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
index 4a77996c1862..1bf54dc53c10 100644
--- a/include/asm-parisc/socket.h
+++ b/include/asm-parisc/socket.h
@@ -16,6 +16,8 @@
/* To add :#define SO_REUSEPORT 0x0200 */
#define SO_SNDBUF 0x1001
#define SO_RCVBUF 0x1002
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
#define SO_SNDLOWAT 0x1003
#define SO_RCVLOWAT 0x1004
#define SO_SNDTIMEO 0x1005
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
index 679ea1c651ef..43eaa6e742e0 100644
--- a/include/asm-parisc/spinlock.h
+++ b/include/asm-parisc/spinlock.h
@@ -2,30 +2,25 @@
#define __ASM_SPINLOCK_H
#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/spinlock_types.h>
/* Note that PA-RISC has to use `1' to mean unlocked and `0' to mean locked
* since it only has load-and-zero. Moreover, at least on some PA processors,
* the semaphore address has to be 16-byte aligned.
*/
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-#define __SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 } }
-#undef SPIN_LOCK_UNLOCKED
-#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-static inline int spin_is_locked(spinlock_t *x)
+static inline int __raw_spin_is_locked(raw_spinlock_t *x)
{
volatile unsigned int *a = __ldcw_align(x);
return *a == 0;
}
-#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+ do { cpu_relax(); } while (__raw_spin_is_locked(x))
-static inline void _raw_spin_lock(spinlock_t *x)
+static inline void __raw_spin_lock(raw_spinlock_t *x)
{
volatile unsigned int *a;
@@ -36,7 +31,7 @@ static inline void _raw_spin_lock(spinlock_t *x)
mb();
}
-static inline void _raw_spin_unlock(spinlock_t *x)
+static inline void __raw_spin_unlock(raw_spinlock_t *x)
{
volatile unsigned int *a;
mb();
@@ -45,7 +40,7 @@ static inline void _raw_spin_unlock(spinlock_t *x)
mb();
}
-static inline int _raw_spin_trylock(spinlock_t *x)
+static inline int __raw_spin_trylock(raw_spinlock_t *x)
{
volatile unsigned int *a;
int ret;
@@ -57,131 +52,38 @@ static inline int _raw_spin_trylock(spinlock_t *x)
return ret;
}
-
-#define spin_lock_own(LOCK, LOCATION) ((void)0)
-
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-#define SPINLOCK_MAGIC 0x1D244B3C
-
-#define __SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 }, SPINLOCK_MAGIC, 10, __FILE__ , NULL, 0, -1, NULL, NULL }
-#undef SPIN_LOCK_UNLOCKED
-#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-#define CHECK_LOCK(x) \
- do { \
- if (unlikely((x)->magic != SPINLOCK_MAGIC)) { \
- printk(KERN_ERR "%s:%d: spin_is_locked" \
- " on uninitialized spinlock %p.\n", \
- __FILE__, __LINE__, (x)); \
- } \
- } while(0)
-
-#define spin_is_locked(x) \
- ({ \
- CHECK_LOCK(x); \
- volatile unsigned int *a = __ldcw_align(x); \
- if (unlikely((*a == 0) && (x)->babble)) { \
- (x)->babble--; \
- printk("KERN_WARNING \
- %s:%d: spin_is_locked(%s/%p) already" \
- " locked by %s:%d in %s at %p(%d)\n", \
- __FILE__,__LINE__, (x)->module, (x), \
- (x)->bfile, (x)->bline, (x)->task->comm,\
- (x)->previous, (x)->oncpu); \
- } \
- *a == 0; \
- })
-
-#define spin_unlock_wait(x) \
- do { \
- CHECK_LOCK(x); \
- volatile unsigned int *a = __ldcw_align(x); \
- if (unlikely((*a == 0) && (x)->babble)) { \
- (x)->babble--; \
- printk("KERN_WARNING \
- %s:%d: spin_unlock_wait(%s/%p)" \
- " owned by %s:%d in %s at %p(%d)\n", \
- __FILE__,__LINE__, (x)->module, (x), \
- (x)->bfile, (x)->bline, (x)->task->comm,\
- (x)->previous, (x)->oncpu); \
- } \
- barrier(); \
- } while (*((volatile unsigned char *)(__ldcw_align(x))) == 0)
-
-extern void _dbg_spin_lock(spinlock_t *lock, const char *base_file, int line_no);
-extern void _dbg_spin_unlock(spinlock_t *lock, const char *, int);
-extern int _dbg_spin_trylock(spinlock_t * lock, const char *, int);
-
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#define _raw_spin_unlock(lock) _dbg_spin_unlock(lock, __FILE__, __LINE__)
-#define _raw_spin_lock(lock) _dbg_spin_lock(lock, __FILE__, __LINE__)
-#define _raw_spin_trylock(lock) _dbg_spin_trylock(lock, __FILE__, __LINE__)
-
-/* just in case we need it */
-#define spin_lock_own(LOCK, LOCATION) \
-do { \
- volatile unsigned int *a = __ldcw_align(LOCK); \
- if (!((*a == 0) && ((LOCK)->oncpu == smp_processor_id()))) \
- printk("KERN_WARNING \
- %s: called on %d from %p but lock %s on %d\n", \
- LOCATION, smp_processor_id(), \
- __builtin_return_address(0), \
- (*a == 0) ? "taken" : "freed", (LOCK)->on_cpu); \
-} while (0)
-
-#endif /* !(CONFIG_DEBUG_SPINLOCK) */
/*
* Read-write spinlocks, allowing multiple readers
* but only one writer.
*/
-typedef struct {
- spinlock_t lock;
- volatile int counter;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { __SPIN_LOCK_UNLOCKED, 0 }
-
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while (0)
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
/* read_lock, read_unlock are pretty straightforward. Of course it somehow
* sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_read_lock(rw) _dbg_read_lock(rw, __FILE__, __LINE__)
-#else
-static __inline__ void _raw_read_lock(rwlock_t *rw)
+static __inline__ void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned long flags;
local_irq_save(flags);
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
rw->counter++;
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
local_irq_restore(flags);
}
-#endif /* CONFIG_DEBUG_RWLOCK */
-static __inline__ void _raw_read_unlock(rwlock_t *rw)
+static __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned long flags;
local_irq_save(flags);
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
rw->counter--;
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
local_irq_restore(flags);
}
@@ -194,20 +96,17 @@ static __inline__ void _raw_read_unlock(rwlock_t *rw)
* writers) in interrupt handlers someone fucked up and we'd dead-lock
* sooner or later anyway. prumpf */
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_write_lock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_write_lock(rw) _dbg_write_lock(rw, __FILE__, __LINE__)
-#else
-static __inline__ void _raw_write_lock(rwlock_t *rw)
+static __inline__ void __raw_write_lock(raw_rwlock_t *rw)
{
retry:
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
if(rw->counter != 0) {
/* this basically never happens */
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
- while(rw->counter != 0);
+ while (rw->counter != 0)
+ cpu_relax();
goto retry;
}
@@ -215,26 +114,21 @@ retry:
/* got it. now leave without unlocking */
rw->counter = -1; /* remember we are locked */
}
-#endif /* CONFIG_DEBUG_RWLOCK */
/* write_unlock is absolutely trivial - we don't have to wait for anything */
-static __inline__ void _raw_write_unlock(rwlock_t *rw)
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
{
rw->counter = 0;
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
}
-#ifdef CONFIG_DEBUG_RWLOCK
-extern int _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
-#else
-static __inline__ int _raw_write_trylock(rwlock_t *rw)
+static __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
{
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
if (rw->counter != 0) {
/* this basically never happens */
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
return 0;
}
@@ -243,14 +137,13 @@ static __inline__ int _raw_write_trylock(rwlock_t *rw)
rw->counter = -1; /* remember we are locked */
return 1;
}
-#endif /* CONFIG_DEBUG_RWLOCK */
-static __inline__ int is_read_locked(rwlock_t *rw)
+static __inline__ int __raw_is_read_locked(raw_rwlock_t *rw)
{
return rw->counter > 0;
}
-static __inline__ int is_write_locked(rwlock_t *rw)
+static __inline__ int __raw_is_write_locked(raw_rwlock_t *rw)
{
return rw->counter < 0;
}
diff --git a/include/asm-parisc/spinlock_types.h b/include/asm-parisc/spinlock_types.h
new file mode 100644
index 000000000000..785bba822fbf
--- /dev/null
+++ b/include/asm-parisc/spinlock_types.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock[4];
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 } }
+
+typedef struct {
+ raw_spinlock_t lock;
+ volatile int counter;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { __RAW_SPIN_LOCK_UNLOCKED, 0 }
+
+#endif
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index 81c543339036..26ff844a21c1 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -160,29 +160,7 @@ static inline void set_eiem(unsigned long val)
})
#ifdef CONFIG_SMP
-/*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile unsigned int lock[4];
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned long magic;
- volatile unsigned int babble;
- const char *module;
- char *bfile;
- int bline;
- int oncpu;
- void *previous;
- struct task_struct * task;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
-
+# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
#endif
#define KERNEL_START (0x10100000 - 0x1000)
diff --git a/include/asm-parisc/types.h b/include/asm-parisc/types.h
index 8fe7a44ea205..d21b9d0d63ea 100644
--- a/include/asm-parisc/types.h
+++ b/include/asm-parisc/types.h
@@ -56,8 +56,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u64 dma64_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index c1b5bdea53ee..f6c417c8c484 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -40,10 +40,6 @@ static inline long access_ok(int type, const void __user * addr,
return 1;
}
-#define verify_area(type,addr,size) (0) /* FIXME: all users should go away soon,
- * and use access_ok instead, then this
- * should be removed. */
-
#define put_user __put_user
#define get_user __get_user
diff --git a/include/asm-powerpc/8253pit.h b/include/asm-powerpc/8253pit.h
new file mode 100644
index 000000000000..b70d6e53b303
--- /dev/null
+++ b/include/asm-powerpc/8253pit.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_POWERPC_8253PIT_H
+#define _ASM_POWERPC_8253PIT_H
+
+/*
+ * 8253/8254 Programmable Interval Timer
+ */
+
+#define PIT_TICK_RATE 1193182UL
+
+#endif /* _ASM_POWERPC_8253PIT_H */
diff --git a/include/asm-ppc/agp.h b/include/asm-powerpc/agp.h
index ca9e423307f4..885b4631a6cf 100644
--- a/include/asm-ppc/agp.h
+++ b/include/asm-powerpc/agp.h
@@ -1,10 +1,8 @@
-#ifndef AGP_H
-#define AGP_H 1
+#ifndef _ASM_POWERPC_AGP_H
+#define _ASM_POWERPC_AGP_H
#include <asm/io.h>
-/* nothing much needed here */
-
#define map_page_into_agp(page)
#define unmap_page_from_agp(page)
#define flush_agp_mappings()
@@ -20,4 +18,4 @@
#define free_gatt_pages(table, order) \
free_pages((unsigned long)(table), (order))
-#endif
+#endif /* _ASM_POWERPC_AGP_H */
diff --git a/include/asm-ppc64/siginfo.h b/include/asm-powerpc/bugs.h
index 3a7c23dcb5aa..42fdb73e3068 100644
--- a/include/asm-ppc64/siginfo.h
+++ b/include/asm-powerpc/bugs.h
@@ -1,5 +1,5 @@
-#ifndef _PPC64_SIGINFO_H
-#define _PPC64_SIGINFO_H
+#ifndef _ASM_POWERPC_BUGS_H
+#define _ASM_POWERPC_BUGS_H
/*
* This program is free software; you can redistribute it and/or
@@ -8,9 +8,11 @@
* 2 of the License, or (at your option) any later version.
*/
-#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
-#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+/*
+ * This file is included by 'init/main.c' to check for
+ * architecture-dependent bugs.
+ */
-#include <asm-generic/siginfo.h>
+static inline void check_bugs(void) { }
-#endif /* _PPC64_SIGINFO_H */
+#endif /* _ASM_POWERPC_BUGS_H */
diff --git a/include/asm-powerpc/cputime.h b/include/asm-powerpc/cputime.h
new file mode 100644
index 000000000000..6d68ad7e0ea3
--- /dev/null
+++ b/include/asm-powerpc/cputime.h
@@ -0,0 +1 @@
+#include <asm-generic/cputime.h>
diff --git a/include/asm-ppc/div64.h b/include/asm-powerpc/div64.h
index 6cd978cefb28..6cd978cefb28 100644
--- a/include/asm-ppc/div64.h
+++ b/include/asm-powerpc/div64.h
diff --git a/include/asm-powerpc/emergency-restart.h b/include/asm-powerpc/emergency-restart.h
new file mode 100644
index 000000000000..3711bd9d50bd
--- /dev/null
+++ b/include/asm-powerpc/emergency-restart.h
@@ -0,0 +1 @@
+#include <asm-generic/emergency-restart.h>
diff --git a/include/asm-ppc/errno.h b/include/asm-powerpc/errno.h
index 19f20bd41ae6..8c145fd17d86 100644
--- a/include/asm-ppc/errno.h
+++ b/include/asm-powerpc/errno.h
@@ -1,5 +1,5 @@
-#ifndef _PPC_ERRNO_H
-#define _PPC_ERRNO_H
+#ifndef _ASM_POWERPC_ERRNO_H
+#define _ASM_POWERPC_ERRNO_H
#include <asm-generic/errno.h>
@@ -8,4 +8,4 @@
#define _LAST_ERRNO 516
-#endif
+#endif /* _ASM_POWERPC_ERRNO_H */
diff --git a/include/asm-powerpc/fcntl.h b/include/asm-powerpc/fcntl.h
new file mode 100644
index 000000000000..ce5c4516d404
--- /dev/null
+++ b/include/asm-powerpc/fcntl.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_FCNTL_H
+#define _ASM_FCNTL_H
+
+#define O_DIRECTORY 040000 /* must be a directory */
+#define O_NOFOLLOW 0100000 /* don't follow links */
+#define O_LARGEFILE 0200000
+#define O_DIRECT 0400000 /* direct disk access hint */
+
+#include <asm-generic/fcntl.h>
+
+#endif /* _ASM_FCNTL_H */
diff --git a/include/asm-ppc/ioctl.h b/include/asm-powerpc/ioctl.h
index 93c6acfdd0fd..8eb99848c402 100644
--- a/include/asm-ppc/ioctl.h
+++ b/include/asm-powerpc/ioctl.h
@@ -1,5 +1,5 @@
-#ifndef _PPC_IOCTL_H
-#define _PPC_IOCTL_H
+#ifndef _ASM_POWERPC_IOCTL_H
+#define _ASM_POWERPC_IOCTL_H
/*
@@ -66,4 +66,4 @@ extern unsigned int __invalid_size_argument_for_IOC;
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
-#endif
+#endif /* _ASM_POWERPC_IOCTL_H */
diff --git a/include/asm-ppc/ioctls.h b/include/asm-powerpc/ioctls.h
index f5b7f2b055e7..5b94ff489b8b 100644
--- a/include/asm-ppc/ioctls.h
+++ b/include/asm-powerpc/ioctls.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_PPC_IOCTLS_H
-#define _ASM_PPC_IOCTLS_H
+#ifndef _ASM_POWERPC_IOCTLS_H
+#define _ASM_POWERPC_IOCTLS_H
#include <asm/ioctl.h>
@@ -104,4 +104,4 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#endif /* _ASM_PPC_IOCTLS_H */
+#endif /* _ASM_POWERPC_IOCTLS_H */
diff --git a/include/asm-ppc/ipc.h b/include/asm-powerpc/ipc.h
index a46e3d9c2a3f..a46e3d9c2a3f 100644
--- a/include/asm-ppc/ipc.h
+++ b/include/asm-powerpc/ipc.h
diff --git a/include/asm-powerpc/linkage.h b/include/asm-powerpc/linkage.h
new file mode 100644
index 000000000000..e1c4ac1cc4ba
--- /dev/null
+++ b/include/asm-powerpc/linkage.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_POWERPC_LINKAGE_H
+#define _ASM_POWERPC_LINKAGE_H
+
+/* Nothing to see here... */
+
+#endif /* _ASM_POWERPC_LINKAGE_H */
diff --git a/include/asm-ppc64/local.h b/include/asm-powerpc/local.h
index c11c530f74d0..c11c530f74d0 100644
--- a/include/asm-ppc64/local.h
+++ b/include/asm-powerpc/local.h
diff --git a/include/asm-ppc64/mc146818rtc.h b/include/asm-powerpc/mc146818rtc.h
index f713e1bbb533..f2741c8b59a1 100644
--- a/include/asm-ppc64/mc146818rtc.h
+++ b/include/asm-powerpc/mc146818rtc.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_POWERPC_MC146818RTC_H
+#define _ASM_POWERPC_MC146818RTC_H
+
/*
* Machine dependent access functions for RTC registers.
*
@@ -6,8 +9,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#ifndef __ASM_PPC64_MC146818RTC_H
-#define __ASM_PPC64_MC146818RTC_H
+
+#ifdef __KERNEL__
#include <asm/io.h>
@@ -29,4 +32,5 @@ outb_p((addr),RTC_PORT(0)); \
outb_p((val),RTC_PORT(1)); \
})
-#endif /* __ASM_PPC64_MC146818RTC_H */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_MC146818RTC_H */
diff --git a/include/asm-ppc64/mman.h b/include/asm-powerpc/mman.h
index d4f93446a52c..f5e5342fcac5 100644
--- a/include/asm-ppc64/mman.h
+++ b/include/asm-powerpc/mman.h
@@ -1,5 +1,5 @@
-#ifndef __PPC64_MMAN_H__
-#define __PPC64_MMAN_H__
+#ifndef _ASM_POWERPC_MMAN_H
+#define _ASM_POWERPC_MMAN_H
/*
* This program is free software; you can redistribute it and/or
@@ -49,4 +49,4 @@
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
-#endif /* __PPC64_MMAN_H__ */
+#endif /* _ASM_POWERPC_MMAN_H */
diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h
new file mode 100644
index 000000000000..7ecd05e03051
--- /dev/null
+++ b/include/asm-powerpc/module.h
@@ -0,0 +1,77 @@
+#ifndef _ASM_POWERPC_MODULE_H
+#define _ASM_POWERPC_MODULE_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/list.h>
+#include <asm/bug.h>
+
+
+#ifndef __powerpc64__
+/*
+ * Thanks to Paul M for explaining this.
+ *
+ * PPC can only do rel jumps += 32MB, and often the kernel and other
+ * modules are furthur away than this. So, we jump to a table of
+ * trampolines attached to the module (the Procedure Linkage Table)
+ * whenever that happens.
+ */
+
+struct ppc_plt_entry {
+ /* 16 byte jump instruction sequence (4 instructions) */
+ unsigned int jump[4];
+};
+#endif /* __powerpc64__ */
+
+
+struct mod_arch_specific {
+#ifdef __powerpc64__
+ unsigned int stubs_section; /* Index of stubs section in module */
+ unsigned int toc_section; /* What section is the TOC? */
+#else
+ /* Indices of PLT sections within module. */
+ unsigned int core_plt_section;
+ unsigned int init_plt_section;
+#endif
+
+ /* List of BUG addresses, source line numbers and filenames */
+ struct list_head bug_list;
+ struct bug_entry *bug_table;
+ unsigned int num_bugs;
+};
+
+extern struct bug_entry *module_find_bug(unsigned long bugaddr);
+
+/*
+ * Select ELF headers.
+ * Make empty section for module_frob_arch_sections to expand.
+ */
+
+#ifdef __powerpc64__
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Sym Elf64_Sym
+# define Elf_Ehdr Elf64_Ehdr
+# ifdef MODULE
+ asm(".section .stubs,\"ax\",@nobits; .align 3; .previous");
+# endif
+#else
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Sym Elf32_Sym
+# define Elf_Ehdr Elf32_Ehdr
+# ifdef MODULE
+ asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
+ asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
+# endif /* MODULE */
+#endif
+
+
+struct exception_table_entry;
+void sort_ex_table(struct exception_table_entry *start,
+ struct exception_table_entry *finish);
+
+#endif /* _ASM_POWERPC_MODULE_H */
diff --git a/include/asm-ppc/msgbuf.h b/include/asm-powerpc/msgbuf.h
index 1053452a9376..dd76743c7537 100644
--- a/include/asm-ppc/msgbuf.h
+++ b/include/asm-powerpc/msgbuf.h
@@ -1,17 +1,25 @@
-#ifndef _PPC_MSGBUF_H
-#define _PPC_MSGBUF_H
+#ifndef _ASM_POWERPC_MSGBUF_H
+#define _ASM_POWERPC_MSGBUF_H
/*
- * The msqid64_ds structure for the PPC architecture.
+ * The msqid64_ds structure for the PowerPC architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
*/
struct msqid64_ds {
struct ipc64_perm msg_perm;
+#ifndef __powerpc64__
unsigned int __unused1;
+#endif
__kernel_time_t msg_stime; /* last msgsnd time */
+#ifndef __powerpc64__
unsigned int __unused2;
+#endif
__kernel_time_t msg_rtime; /* last msgrcv time */
+#ifndef __powerpc64__
unsigned int __unused3;
+#endif
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
@@ -22,4 +30,4 @@ struct msqid64_ds {
unsigned long __unused5;
};
-#endif /* _PPC_MSGBUF_H */
+#endif /* _ASM_POWERPC_MSGBUF_H */
diff --git a/include/asm-ppc/namei.h b/include/asm-powerpc/namei.h
index 29c9ec832133..657443474a6a 100644
--- a/include/asm-ppc/namei.h
+++ b/include/asm-powerpc/namei.h
@@ -1,14 +1,14 @@
+#ifndef _ASM_POWERPC_NAMEI_H
+#define _ASM_POWERPC_NAMEI_H
+
+#ifdef __KERNEL__
+
/*
- * include/asm-ppc/namei.h
* Adapted from include/asm-alpha/namei.h
*
* Included from fs/namei.c
*/
-#ifdef __KERNEL__
-#ifndef __PPC_NAMEI_H
-#define __PPC_NAMEI_H
-
/* This dummy routine maybe changed to something useful
* for /usr/gnemul/ emulation stuff.
* Look at asm-sparc/namei.h for details.
@@ -16,5 +16,5 @@
#define __emul_prefix() NULL
-#endif /* __PPC_NAMEI_H */
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_NAMEI_H */
diff --git a/include/asm-ppc/param.h b/include/asm-powerpc/param.h
index b24a4e37196a..bdc724f70884 100644
--- a/include/asm-ppc/param.h
+++ b/include/asm-powerpc/param.h
@@ -1,8 +1,10 @@
-#ifndef _ASM_PPC_PARAM_H
-#define _ASM_PPC_PARAM_H
+#ifndef _ASM_POWERPC_PARAM_H
+#define _ASM_POWERPC_PARAM_H
+
+#include <linux/config.h>
#ifdef __KERNEL__
-#define HZ 1000 /* internal timer frequency */
+#define HZ CONFIG_HZ /* internal kernel timer frequency */
#define USER_HZ 100 /* for user interfaces in "ticks" */
#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */
#endif /* __KERNEL__ */
@@ -19,4 +21,4 @@
#define MAXHOSTNAMELEN 64 /* max length of hostname */
-#endif
+#endif /* _ASM_POWERPC_PARAM_H */
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
new file mode 100644
index 000000000000..06a959d67234
--- /dev/null
+++ b/include/asm-powerpc/percpu.h
@@ -0,0 +1 @@
+#include <asm-generic/percpu.h>
diff --git a/include/asm-ppc/poll.h b/include/asm-powerpc/poll.h
index be5024913c62..edd2054da86b 100644
--- a/include/asm-ppc/poll.h
+++ b/include/asm-powerpc/poll.h
@@ -1,5 +1,5 @@
-#ifndef __PPC_POLL_H
-#define __PPC_POLL_H
+#ifndef _ASM_POWERPC_POLL_H
+#define _ASM_POWERPC_POLL_H
#define POLLIN 0x0001
#define POLLPRI 0x0002
@@ -20,4 +20,4 @@ struct pollfd {
short revents;
};
-#endif
+#endif /* _ASM_POWERPC_POLL_H */
diff --git a/include/asm-powerpc/resource.h b/include/asm-powerpc/resource.h
new file mode 100644
index 000000000000..04bc4db8921b
--- /dev/null
+++ b/include/asm-powerpc/resource.h
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/include/asm-ppc64/sembuf.h b/include/asm-powerpc/sembuf.h
index 172e59000767..99a41938ae3d 100644
--- a/include/asm-ppc64/sembuf.h
+++ b/include/asm-powerpc/sembuf.h
@@ -1,27 +1,36 @@
-#ifndef _PPC64_SEMBUF_H
-#define _PPC64_SEMBUF_H
+#ifndef _ASM_POWERPC_SEMBUF_H
+#define _ASM_POWERPC_SEMBUF_H
-/*
- * The semid64_ds structure for PPC architecture.
- *
- *
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * The semid64_ds structure for PPC architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
*
* Pad space is left for:
- * - 2 miscellaneous 64-bit values
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
*/
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+#ifndef __powerpc64__
+ unsigned long __unused1;
+#endif
__kernel_time_t sem_otime; /* last semop time */
+#ifndef __powerpc64__
+ unsigned long __unused2;
+#endif
__kernel_time_t sem_ctime; /* last change time */
unsigned long sem_nsems; /* no. of semaphores in array */
-
- unsigned long __unused1;
- unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
};
-#endif /* _PPC64_SEMBUF_H */
+#endif /* _ASM_POWERPC_SEMBUF_H */
diff --git a/include/asm-powerpc/setup.h b/include/asm-powerpc/setup.h
new file mode 100644
index 000000000000..3d9740aae018
--- /dev/null
+++ b/include/asm-powerpc/setup.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_POWERPC_SETUP_H
+#define _ASM_POWERPC_SETUP_H
+
+#ifdef __KERNEL__
+
+#define COMMAND_LINE_SIZE 512
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_SETUP_H */
diff --git a/include/asm-ppc64/shmbuf.h b/include/asm-powerpc/shmbuf.h
index 02e99d6ec925..8efa39698b6c 100644
--- a/include/asm-ppc64/shmbuf.h
+++ b/include/asm-powerpc/shmbuf.h
@@ -1,31 +1,47 @@
-#ifndef _PPC64_SHMBUF_H
-#define _PPC64_SHMBUF_H
+#ifndef _ASM_POWERPC_SHMBUF_H
+#define _ASM_POWERPC_SHMBUF_H
-/*
- * The shmid64_ds structure for PPC64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- *
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+/*
+ * The shmid64_ds structure for PPC architecture.
+ *
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
+#ifndef __powerpc64__
+ unsigned long __unused1;
+#endif
__kernel_time_t shm_atime; /* last attach time */
+#ifndef __powerpc64__
+ unsigned long __unused2;
+#endif
__kernel_time_t shm_dtime; /* last detach time */
+#ifndef __powerpc64__
+ unsigned long __unused3;
+#endif
__kernel_time_t shm_ctime; /* last change time */
+#ifndef __powerpc64__
+ unsigned long __unused4;
+#endif
size_t shm_segsz; /* size of segment (bytes) */
__kernel_pid_t shm_cpid; /* pid of creator */
__kernel_pid_t shm_lpid; /* pid of last operator */
unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused1;
- unsigned long __unused2;
+ unsigned long __unused5;
+ unsigned long __unused6;
};
struct shminfo64 {
@@ -40,4 +56,4 @@ struct shminfo64 {
unsigned long __unused4;
};
-#endif /* _PPC64_SHMBUF_H */
+#endif /* _ASM_POWERPC_SHMBUF_H */
diff --git a/include/asm-powerpc/shmparam.h b/include/asm-powerpc/shmparam.h
new file mode 100644
index 000000000000..5cda42a6d39e
--- /dev/null
+++ b/include/asm-powerpc/shmparam.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_POWERPC_SHMPARAM_H
+#define _ASM_POWERPC_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
+
+#endif /* _ASM_POWERPC_SHMPARAM_H */
diff --git a/include/asm-powerpc/siginfo.h b/include/asm-powerpc/siginfo.h
new file mode 100644
index 000000000000..12f1bce037be
--- /dev/null
+++ b/include/asm-powerpc/siginfo.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_POWERPC_SIGINFO_H
+#define _ASM_POWERPC_SIGINFO_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifdef __powerpc64__
+# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+# define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+#endif
+
+#include <asm-generic/siginfo.h>
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
+#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */
+#undef NSIGTRAP
+#define NSIGTRAP 4
+
+#endif /* _ASM_POWERPC_SIGINFO_H */
diff --git a/include/asm-ppc64/socket.h b/include/asm-powerpc/socket.h
index 59e00dfc8b8e..e4b8177d4acc 100644
--- a/include/asm-ppc64/socket.h
+++ b/include/asm-powerpc/socket.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
+#ifndef _ASM_POWERPC_SOCKET_H
+#define _ASM_POWERPC_SOCKET_H
/*
* This program is free software; you can redistribute it and/or
@@ -10,7 +10,7 @@
#include <asm/sockios.h>
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
#define SOL_SOCKET 1
#define SO_DEBUG 1
@@ -21,6 +21,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
@@ -50,8 +52,8 @@
#define SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
-#define SO_ACCEPTCONN 30
+#define SO_ACCEPTCONN 30
-#define SO_PEERSEC 31
+#define SO_PEERSEC 31
-#endif /* _ASM_SOCKET_H */
+#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/include/asm-ppc64/sockios.h b/include/asm-powerpc/sockios.h
index 6bd1a22af4f6..590078d8ed28 100644
--- a/include/asm-ppc64/sockios.h
+++ b/include/asm-powerpc/sockios.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_PPC64_SOCKIOS_H
-#define _ASM_PPC64_SOCKIOS_H
+#ifndef _ASM_POWERPC_SOCKIOS_H
+#define _ASM_POWERPC_SOCKIOS_H
/*
* This program is free software; you can redistribute it and/or
@@ -16,4 +16,4 @@
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8906 /* Get stamp */
-#endif /* _ASM_PPC64_SOCKIOS_H */
+#endif /* _ASM_POWERPC_SOCKIOS_H */
diff --git a/include/asm-ppc/string.h b/include/asm-powerpc/string.h
index 225575997392..8606a696c088 100644
--- a/include/asm-ppc/string.h
+++ b/include/asm-powerpc/string.h
@@ -1,5 +1,5 @@
-#ifndef _PPC_STRING_H_
-#define _PPC_STRING_H_
+#ifndef _ASM_POWERPC_STRING_H
+#define _ASM_POWERPC_STRING_H
#ifdef __KERNEL__
@@ -29,4 +29,4 @@ extern void * memchr(const void *,int,__kernel_size_t);
#endif /* __KERNEL__ */
-#endif
+#endif /* _ASM_POWERPC_STRING_H */
diff --git a/include/asm-ppc64/termbits.h b/include/asm-powerpc/termbits.h
index d1a2bee10cef..ebf6055481dc 100644
--- a/include/asm-ppc64/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -1,5 +1,5 @@
-#ifndef _PPC64_TERMBITS_H
-#define _PPC64_TERMBITS_H
+#ifndef _ASM_POWERPC_TERMBITS_H
+#define _ASM_POWERPC_TERMBITS_H
/*
* This program is free software; you can redistribute it and/or
@@ -8,8 +8,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/posix_types.h>
-
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
@@ -190,4 +188,4 @@ struct termios {
#define TCSADRAIN 1
#define TCSAFLUSH 2
-#endif /* _PPC64_TERMBITS_H */
+#endif /* _ASM_POWERPC_TERMBITS_H */
diff --git a/include/asm-ppc64/termios.h b/include/asm-powerpc/termios.h
index 02c3d283aa62..c5b8e5358f83 100644
--- a/include/asm-ppc64/termios.h
+++ b/include/asm-powerpc/termios.h
@@ -1,5 +1,5 @@
-#ifndef _PPC64_TERMIOS_H
-#define _PPC64_TERMIOS_H
+#ifndef _ASM_POWERPC_TERMIOS_H
+#define _ASM_POWERPC_TERMIOS_H
/*
* Liberally adapted from alpha/termios.h. In particular, the c_cc[]
@@ -87,6 +87,7 @@ struct termio {
#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
#define N_HDLC 13 /* synchronous HDLC */
#define N_SYNC_PPP 14
+#define N_HCI 15 /* Bluetooth HCI UART */
#ifdef __KERNEL__
/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */
@@ -232,4 +233,4 @@ struct termio {
#endif /* __KERNEL__ */
-#endif /* _PPC64_TERMIOS_H */
+#endif /* _ASM_POWERPC_TERMIOS_H */
diff --git a/include/asm-ppc/timex.h b/include/asm-powerpc/timex.h
index cffc8712077c..51c5b316be55 100644
--- a/include/asm-ppc/timex.h
+++ b/include/asm-powerpc/timex.h
@@ -1,11 +1,11 @@
+#ifndef _ASM_POWERPC_TIMEX_H
+#define _ASM_POWERPC_TIMEX_H
+
+#ifdef __KERNEL__
+
/*
- * include/asm-ppc/timex.h
- *
- * ppc architecture timex specifications
+ * PowerPC architecture timex specifications
*/
-#ifdef __KERNEL__
-#ifndef _ASMppc_TIMEX_H
-#define _ASMppc_TIMEX_H
#include <linux/config.h>
#include <asm/cputable.h>
@@ -14,14 +14,21 @@
typedef unsigned long cycles_t;
-/*
- * For the "cycle" counter we use the timebase lower half.
- * Currently only used on SMP.
- */
-
static inline cycles_t get_cycles(void)
{
- cycles_t ret = 0;
+ cycles_t ret;
+
+#ifdef __powerpc64__
+
+ __asm__ __volatile__("mftb %0" : "=r" (ret) : );
+
+#else
+ /*
+ * For the "cycle" counter we use the timebase lower half.
+ * Currently only used on SMP.
+ */
+
+ ret = 0;
__asm__ __volatile__(
"98: mftb %0\n"
@@ -33,8 +40,10 @@ static inline cycles_t get_cycles(void)
" .long 99b\n"
".previous"
: "=r" (ret) : "i" (CPU_FTR_601));
+#endif
+
return ret;
}
-#endif
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_TIMEX_H */
diff --git a/include/asm-ppc64/topology.h b/include/asm-powerpc/topology.h
index 1e9b19073230..2512e3836bf4 100644
--- a/include/asm-ppc64/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -1,11 +1,12 @@
-#ifndef _ASM_PPC64_TOPOLOGY_H
-#define _ASM_PPC64_TOPOLOGY_H
+#ifndef _ASM_POWERPC_TOPOLOGY_H
+#define _ASM_POWERPC_TOPOLOGY_H
#include <linux/config.h>
-#include <asm/mmzone.h>
#ifdef CONFIG_NUMA
+#include <asm/mmzone.h>
+
static inline int cpu_to_node(int cpu)
{
int node;
@@ -66,4 +67,4 @@ static inline int node_to_first_cpu(int node)
#endif /* CONFIG_NUMA */
-#endif /* _ASM_PPC64_TOPOLOGY_H */
+#endif /* _ASM_POWERPC_TOPOLOGY_H */
diff --git a/include/asm-ppc/unaligned.h b/include/asm-powerpc/unaligned.h
index 45520d9b85d1..6c95dfa2652f 100644
--- a/include/asm-ppc/unaligned.h
+++ b/include/asm-powerpc/unaligned.h
@@ -1,6 +1,7 @@
+#ifndef _ASM_POWERPC_UNALIGNED_H
+#define _ASM_POWERPC_UNALIGNED_H
+
#ifdef __KERNEL__
-#ifndef __PPC_UNALIGNED_H
-#define __PPC_UNALIGNED_H
/*
* The PowerPC can do unaligned accesses itself in big endian mode.
@@ -14,5 +15,5 @@
#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-#endif
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_UNALIGNED_H */
diff --git a/include/asm-ppc/user.h b/include/asm-powerpc/user.h
index d662b2151370..e59ade4b3dfb 100644
--- a/include/asm-ppc/user.h
+++ b/include/asm-powerpc/user.h
@@ -1,13 +1,14 @@
-#ifdef __KERNEL__
-#ifndef _PPC_USER_H
-#define _PPC_USER_H
+#ifndef _ASM_POWERPC_USER_H
+#define _ASM_POWERPC_USER_H
-/* Adapted from <asm-alpha/user.h> */
+#ifdef __KERNEL__
-#include <linux/ptrace.h>
+#include <asm/ptrace.h>
#include <asm/page.h>
/*
+ * Adapted from <asm-alpha/user.h>
+ *
* Core file format: The core file is written in such a way that gdb
* can understand it and provide useful information to the user (under
* linux we use the `trad-core' bfd, NOT the osf-core). The file contents
@@ -50,5 +51,5 @@ struct user {
#define HOST_DATA_START_ADDR (u.start_data)
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-#endif /* _PPC_USER_H */
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_USER_H */
diff --git a/include/asm-ppc/xor.h b/include/asm-powerpc/xor.h
index c82eb12a5b18..c82eb12a5b18 100644
--- a/include/asm-ppc/xor.h
+++ b/include/asm-powerpc/xor.h
diff --git a/include/asm-ppc/8253pit.h b/include/asm-ppc/8253pit.h
deleted file mode 100644
index 285f78488ccb..000000000000
--- a/include/asm-ppc/8253pit.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
-
-#ifndef _8253PIT_H
-#define _8253PIT_H
-
-#define PIT_TICK_RATE 1193182UL
-
-#endif
diff --git a/include/asm-ppc/auxvec.h b/include/asm-ppc/auxvec.h
new file mode 100644
index 000000000000..172358df29c8
--- /dev/null
+++ b/include/asm-ppc/auxvec.h
@@ -0,0 +1,14 @@
+#ifndef __PPC_AUXVEC_H
+#define __PPC_AUXVEC_H
+
+/*
+ * We need to put in some extra aux table entries to tell glibc what
+ * the cache block size is, so it can use the dcbz instruction safely.
+ */
+#define AT_DCACHEBSIZE 19
+#define AT_ICACHEBSIZE 20
+#define AT_UCACHEBSIZE 21
+/* A special ignored type value for PPC, for glibc compatibility. */
+#define AT_IGNOREPPC 22
+
+#endif
diff --git a/include/asm-ppc/bugs.h b/include/asm-ppc/bugs.h
deleted file mode 100644
index 8dce1e290fd0..000000000000
--- a/include/asm-ppc/bugs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * This file is included by 'init/main.c'
- */
-
-extern void
-check_bugs(void);
diff --git a/include/asm-ppc/cputime.h b/include/asm-ppc/cputime.h
deleted file mode 100644
index 8e9faf5ce720..000000000000
--- a/include/asm-ppc/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PPC_CPUTIME_H
-#define __PPC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __PPC_CPUTIME_H */
diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
index 6f74f59938d4..92b8ee78dcc2 100644
--- a/include/asm-ppc/dma-mapping.h
+++ b/include/asm-ppc/dma-mapping.h
@@ -60,7 +60,8 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
}
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, int gfp)
+ dma_addr_t * dma_handle,
+ unsigned int __nocast gfp)
{
#ifdef CONFIG_NOT_COHERENT_CACHE
return __dma_alloc_coherent(size, dma_handle, gfp);
diff --git a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h
index 2c056966efd3..c25cc35e6ab5 100644
--- a/include/asm-ppc/elf.h
+++ b/include/asm-ppc/elf.h
@@ -7,6 +7,7 @@
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/cputable.h>
+#include <asm/auxvec.h>
/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE 0
@@ -122,16 +123,6 @@ extern int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpu);
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
-/*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE 19
-#define AT_ICACHEBSIZE 20
-#define AT_UCACHEBSIZE 21
-/* A special ignored type value for PPC, for glibc compatibility. */
-#define AT_IGNOREPPC 22
-
extern int dcache_bsize;
extern int icache_bsize;
extern int ucache_bsize;
diff --git a/include/asm-ppc/emergency-restart.h b/include/asm-ppc/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/include/asm-ppc/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h
deleted file mode 100644
index 5e28e41fb29f..000000000000
--- a/include/asm-ppc/fcntl.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef _PPC_FCNTL_H
-#define _PPC_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECTORY 040000 /* must be a directory */
-#define O_NOFOLLOW 0100000 /* don't follow links */
-#define O_LARGEFILE 0200000
-#define O_DIRECT 0400000 /* direct disk access hint */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-#ifdef __KERNEL__
-#define F_POSIX 1
-#define F_FLOCK 2
-#define F_BROKEN 4 /* broken flock() emulation */
-#endif /* __KERNEL__ */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
diff --git a/include/asm-ppc/futex.h b/include/asm-ppc/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-ppc/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-ppc/hdreg.h b/include/asm-ppc/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-ppc/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h
index e807be96e981..e992369cb8e9 100644
--- a/include/asm-ppc/ibm4xx.h
+++ b/include/asm-ppc/ibm4xx.h
@@ -19,10 +19,6 @@
#ifdef CONFIG_40x
-#if defined(CONFIG_ASH)
-#include <platforms/4xx/ash.h>
-#endif
-
#if defined(CONFIG_BUBINGA)
#include <platforms/4xx/bubinga.h>
#endif
@@ -35,14 +31,6 @@
#include <platforms/4xx/ep405.h>
#endif
-#if defined(CONFIG_OAK)
-#include <platforms/4xx/oak.h>
-#endif
-
-#if defined(CONFIG_REDWOOD_4)
-#include <platforms/4xx/redwood.h>
-#endif
-
#if defined(CONFIG_REDWOOD_5)
#include <platforms/4xx/redwood5.h>
#endif
diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h
index 3f7b5669e6d5..6f10a25bd628 100644
--- a/include/asm-ppc/ibm_ocp.h
+++ b/include/asm-ppc/ibm_ocp.h
@@ -67,6 +67,7 @@ struct ocp_func_emac_data {
int phy_mode; /* PHY type or configurable mode */
u8 mac_addr[6]; /* EMAC mac address */
u32 phy_map; /* EMAC phy map */
+ u32 phy_feat_exc; /* Excluded PHY features */
};
/* Sysfs support */
@@ -83,6 +84,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx) \
OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, tah_idx) \
OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, phy_mode) \
OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_map) \
+OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_feat_exc)\
\
void ocp_show_emac_data(struct device *dev) \
{ \
@@ -98,8 +100,22 @@ void ocp_show_emac_data(struct device *dev) \
device_create_file(dev, &dev_attr_emac_tah_idx); \
device_create_file(dev, &dev_attr_emac_phy_mode); \
device_create_file(dev, &dev_attr_emac_phy_map); \
+ device_create_file(dev, &dev_attr_emac_phy_feat_exc); \
}
+/*
+ * PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY)
+ */
+#define PHY_MODE_NA 0
+#define PHY_MODE_MII 1
+#define PHY_MODE_RMII 2
+#define PHY_MODE_SMII 3
+#define PHY_MODE_RGMII 4
+#define PHY_MODE_TBI 5
+#define PHY_MODE_GMII 6
+#define PHY_MODE_RTBI 7
+#define PHY_MODE_SGMII 8
+
#ifdef CONFIG_40x
/*
* Helper function to copy MAC addresses from the bd_t to OCP EMAC
@@ -133,6 +149,7 @@ struct ocp_func_mal_data {
int txde_irq; /* TX Descriptor Error IRQ */
int rxde_irq; /* RX Descriptor Error IRQ */
int serr_irq; /* MAL System Error IRQ */
+ int dcr_base; /* MALx_CFG DCR number */
};
#define OCP_SYSFS_MAL_DATA() \
@@ -143,6 +160,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, rxeob_irq) \
OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, txde_irq) \
OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, rxde_irq) \
OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, serr_irq) \
+OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, dcr_base) \
\
void ocp_show_mal_data(struct device *dev) \
{ \
@@ -153,6 +171,7 @@ void ocp_show_mal_data(struct device *dev) \
device_create_file(dev, &dev_attr_mal_txde_irq); \
device_create_file(dev, &dev_attr_mal_rxde_irq); \
device_create_file(dev, &dev_attr_mal_serr_irq); \
+ device_create_file(dev, &dev_attr_mal_dcr_base); \
}
/*
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index a9b33324f562..55752474d0d9 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -19,6 +19,11 @@
#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
#if defined(CONFIG_40x)
#include <asm/ibm4xx.h>
@@ -337,6 +342,7 @@ static __inline__ int irq_canonicalize(int irq)
#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
+#define SIU_INT_USB ((uint)0x0b + CPM_IRQ_OFFSET)
#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
@@ -398,9 +404,5 @@ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
extern atomic_t ppc_n_lost_interrupts;
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#endif /* _ASM_IRQ_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h
index 2589f182a6ad..6d6fc78731e5 100644
--- a/include/asm-ppc/kmap_types.h
+++ b/include/asm-ppc/kmap_types.h
@@ -17,6 +17,7 @@ enum km_type {
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_PPC_SYNC_PAGE,
+ KM_PPC_SYNC_ICACHE,
KM_TYPE_NR
};
diff --git a/include/asm-ppc/linkage.h b/include/asm-ppc/linkage.h
deleted file mode 100644
index 291c2d01c44f..000000000000
--- a/include/asm-ppc/linkage.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-/* Nothing to see here... */
-
-#endif
diff --git a/include/asm-ppc/local.h b/include/asm-ppc/local.h
deleted file mode 100644
index b08e3eced10e..000000000000
--- a/include/asm-ppc/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PPC_LOCAL_H
-#define __PPC_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif /* __PPC_LOCAL_H */
diff --git a/include/asm-ppc/mc146818rtc.h b/include/asm-ppc/mc146818rtc.h
deleted file mode 100644
index 227018b2fef8..000000000000
--- a/include/asm-ppc/mc146818rtc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifdef __KERNEL__
-#ifndef __ASM_PPC_MC146818RTC_H
-#define __ASM_PPC_MC146818RTC_H
-
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
-#endif
-
-/*
- * The yet supported machines all access the RTC index register via
- * an ISA port access but the way to access the date register differs ...
- */
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-#define RTC_IRQ 8
-
-#endif /* __ASM_PPC_MC146818RTC_H */
-#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/mman.h b/include/asm-ppc/mman.h
deleted file mode 100644
index 5fd19fd4936c..000000000000
--- a/include/asm-ppc/mman.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef __PPC_MMAN_H__
-#define __PPC_MMAN_H__
-
-#define PROT_READ 0x1 /* page can be read */
-#define PROT_WRITE 0x2 /* page can be written */
-#define PROT_EXEC 0x4 /* page can be executed */
-#define PROT_SEM 0x8 /* page may be used for atomic ops */
-#define PROT_NONE 0x0 /* page can not be accessed */
-#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
-#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
-
-#define MAP_SHARED 0x01 /* Share changes */
-#define MAP_PRIVATE 0x02 /* Changes are private */
-#define MAP_TYPE 0x0f /* Mask for type of mapping */
-#define MAP_FIXED 0x10 /* Interpret addr exactly */
-#define MAP_ANONYMOUS 0x20 /* don't use a file */
-#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */
-#define MAP_NORESERVE 0x40 /* don't reserve swap pages */
-#define MAP_LOCKED 0x80
-
-#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
-#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
-#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK 0x10000 /* do not block on IO */
-
-#define MS_ASYNC 1 /* sync memory asynchronously */
-#define MS_INVALIDATE 2 /* invalidate the caches */
-#define MS_SYNC 4 /* synchronous memory sync */
-
-#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
-#define MCL_FUTURE 0x4000 /* lock all additions to address space */
-
-#define MADV_NORMAL 0x0 /* default page-in behavior */
-#define MADV_RANDOM 0x1 /* page-in minimum required */
-#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
-#define MADV_WILLNEED 0x3 /* pre-fault pages */
-#define MADV_DONTNEED 0x4 /* discard these pages */
-
-/* compatibility flags */
-#define MAP_ANON MAP_ANONYMOUS
-#define MAP_FILE 0
-
-#endif /* __PPC_MMAN_H__ */
diff --git a/include/asm-ppc/module.h b/include/asm-ppc/module.h
deleted file mode 100644
index fb63492562b0..000000000000
--- a/include/asm-ppc/module.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _ASM_PPC_MODULE_H
-#define _ASM_PPC_MODULE_H
-/* Module stuff for PPC. (C) 2001 Rusty Russell */
-
-#include <linux/list.h>
-#include <asm/bug.h>
-
-/* Thanks to Paul M for explaining this.
-
- PPC can only do rel jumps += 32MB, and often the kernel and other
- modules are furthur away than this. So, we jump to a table of
- trampolines attached to the module (the Procedure Linkage Table)
- whenever that happens.
-*/
-
-struct ppc_plt_entry
-{
- /* 16 byte jump instruction sequence (4 instructions) */
- unsigned int jump[4];
-};
-
-struct mod_arch_specific
-{
- /* Indices of PLT sections within module. */
- unsigned int core_plt_section, init_plt_section;
-
- /* List of BUG addresses, source line numbers and filenames */
- struct list_head bug_list;
- struct bug_entry *bug_table;
- unsigned int num_bugs;
-};
-
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-/* Make empty sections for module_frob_arch_sections to expand. */
-#ifdef MODULE
-asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
-asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
-#endif
-#endif /* _ASM_PPC_MODULE_H */
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 89eb8a2ac693..9694eca16e92 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -67,6 +67,24 @@
#define IO_VIRT_ADDR IO_PHYS_ADDR
#endif
+enum ppc_sys_devices {
+ MPC82xx_CPM_FCC1,
+ MPC82xx_CPM_FCC2,
+ MPC82xx_CPM_FCC3,
+ MPC82xx_CPM_I2C,
+ MPC82xx_CPM_SCC1,
+ MPC82xx_CPM_SCC2,
+ MPC82xx_CPM_SCC3,
+ MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_SPI,
+ MPC82xx_CPM_MCC1,
+ MPC82xx_CPM_MCC2,
+ MPC82xx_CPM_SMC1,
+ MPC82xx_CPM_SMC2,
+ MPC82xx_CPM_USB,
+ MPC82xx_SEC1,
+};
+
#ifndef __ASSEMBLY__
/* The "residual" data board information structure the boot loader
* hands to us.
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index 7c31f2d564a1..dc8e59896050 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -36,10 +36,6 @@
#include <platforms/tqm8xx.h>
#endif
-#if defined(CONFIG_SPD823TS)
-#include <platforms/spd8xx.h>
-#endif
-
#if defined(CONFIG_IVMS8) || defined(CONFIG_IVML24)
#include <platforms/ivms8.h>
#endif
diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
index cc25b921ad4f..75c2ffa26b26 100644
--- a/include/asm-ppc/mv64x60.h
+++ b/include/asm-ppc/mv64x60.h
@@ -119,6 +119,14 @@ extern spinlock_t mv64x60_lock;
#define MV64x60_64BIT_WIN_COUNT 24
+/* Watchdog Platform Device, Driver Data */
+#define MV64x60_WDT_NAME "wdt"
+
+struct mv64x60_wdt_pdata {
+ int timeout; /* watchdog expiry in seconds, default 10 */
+ int bus_clk; /* bus clock in MHz, default 133 */
+};
+
/*
* Define a structure that's used to pass in config information to the
* core routines.
@@ -278,6 +286,13 @@ mv64x60_modify(struct mv64x60_handle *bh, u32 offs, u32 data, u32 mask)
#define mv64x60_set_bits(bh, offs, bits) mv64x60_modify(bh, offs, ~0, bits)
#define mv64x60_clr_bits(bh, offs, bits) mv64x60_modify(bh, offs, 0, bits)
+#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
+#define MV64XXX_DEV_NAME "mv64xxx"
+
+struct mv64xxx_pdata {
+ u32 hs_reg_valid;
+};
+#endif
/* Externally visible function prototypes */
int mv64x60_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si);
diff --git a/include/asm-ppc/mv64x60_defs.h b/include/asm-ppc/mv64x60_defs.h
index 2f428746c02b..f8f7f16b9b53 100644
--- a/include/asm-ppc/mv64x60_defs.h
+++ b/include/asm-ppc/mv64x60_defs.h
@@ -333,7 +333,7 @@
/*
*****************************************************************************
*
- * SRAM Cotnroller Registers
+ * SRAM Controller Registers
*
*****************************************************************************
*/
@@ -352,7 +352,7 @@
/*
*****************************************************************************
*
- * SDRAM/MEM Cotnroller Registers
+ * SDRAM/MEM Controller Registers
*
*****************************************************************************
*/
@@ -375,6 +375,7 @@
/* SDRAM Control Registers */
#define MV64360_D_UNIT_CONTROL_LOW 0x1404
#define MV64360_D_UNIT_CONTROL_HIGH 0x1424
+#define MV64460_D_UNIT_MMASK 0x14b0
/* SDRAM Error Report Registers (64360) */
#define MV64360_SDRAM_ERR_DATA_LO 0x1444
@@ -388,7 +389,7 @@
/*
*****************************************************************************
*
- * Device/BOOT Cotnroller Registers
+ * Device/BOOT Controller Registers
*
*****************************************************************************
*/
@@ -680,6 +681,8 @@
#define MV64x60_PCI1_SLAVE_P2P_IO_REMAP 0x0dec
#define MV64x60_PCI1_SLAVE_CPU_REMAP 0x0df0
+#define MV64360_PCICFG_CPCI_HOTSWAP 0x68
+
/*
*****************************************************************************
*
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index a811e440c978..9dd06cd40096 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -109,6 +109,19 @@ extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
extern void pcibios_add_platform_entries(struct pci_dev *dev);
struct file;
diff --git a/include/asm-ppc/percpu.h b/include/asm-ppc/percpu.h
deleted file mode 100644
index d66667cd5878..000000000000
--- a/include/asm-ppc/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARCH_PPC_PERCPU__
-#define __ARCH_PPC_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_PPC_PERCPU__ */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 92f30b28b252..eee601bb9ada 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -812,15 +812,6 @@ extern void kernel_set_cachemode (unsigned long address, unsigned long size,
#ifdef CONFIG_PHYS_64BIT
extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long paddr, unsigned long size, pgprot_t prot);
-static inline int io_remap_page_range(struct vm_area_struct *vma,
- unsigned long vaddr,
- unsigned long paddr,
- unsigned long size,
- pgprot_t prot)
-{
- phys_addr_t paddr64 = fixup_bigphys_addr(paddr, size);
- return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
-}
static inline int io_remap_pfn_range(struct vm_area_struct *vma,
unsigned long vaddr,
@@ -832,8 +823,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
}
#else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
index 8beb162873f4..e9683bcff19b 100644
--- a/include/asm-ppc/pmac_feature.h
+++ b/include/asm-ppc/pmac_feature.h
@@ -32,6 +32,7 @@
#define __PPC_ASM_PMAC_FEATURE_H
#include <asm/macio.h>
+#include <asm/machdep.h>
/*
* Known Mac motherboard models
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 8ea624566231..048f7c8596ee 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -21,7 +21,9 @@
#include <linux/device.h>
#include <linux/types.h>
-#if defined(CONFIG_83xx)
+#if defined(CONFIG_8260)
+#include <asm/mpc8260.h>
+#elif defined(CONFIG_83xx)
#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
@@ -50,6 +52,7 @@ extern struct ppc_sys_spec *cur_ppc_sys_spec;
/* determine which specific SOC we are */
extern void identify_ppc_sys_by_id(u32 id) __init;
extern void identify_ppc_sys_by_name(char *name) __init;
+extern void identify_ppc_sys_by_name_and_id(char *name, u32 id) __init;
/* describes all devices that may exist in a given family of processors */
extern struct platform_device ppc_sys_platform_devices[];
diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
index 9d4e4ea530c3..7043c164b537 100644
--- a/include/asm-ppc/ptrace.h
+++ b/include/asm-ppc/ptrace.h
@@ -142,4 +142,11 @@ do { \
#define PTRACE_GETEVRREGS 20
#define PTRACE_SETEVRREGS 21
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG 25
+#define PTRACE_SET_DEBUGREG 26
+
#endif
diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
index 88b4222154d4..73c33e3ef9c6 100644
--- a/include/asm-ppc/reg.h
+++ b/include/asm-ppc/reg.h
@@ -366,12 +366,6 @@
#define PVR_STB03XXX 0x40310000
#define PVR_NP405H 0x41410000
#define PVR_NP405L 0x41610000
-#define PVR_440GP_RB 0x40120440
-#define PVR_440GP_RC1 0x40120481
-#define PVR_440GP_RC2 0x40200481
-#define PVR_440GX_RA 0x51b21850
-#define PVR_440GX_RB 0x51b21851
-#define PVR_440GX_RC 0x51b21892
#define PVR_601 0x00010000
#define PVR_602 0x00050000
#define PVR_603 0x00030000
diff --git a/include/asm-ppc/resource.h b/include/asm-ppc/resource.h
deleted file mode 100644
index 86a1ea23a6ed..000000000000
--- a/include/asm-ppc/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PPC_RESOURCE_H
-#define _PPC_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/include/asm-ppc/segment.h b/include/asm-ppc/segment.h
deleted file mode 100644
index 0f2f7428d437..000000000000
--- a/include/asm-ppc/segment.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/uaccess.h>
diff --git a/include/asm-ppc/sembuf.h b/include/asm-ppc/sembuf.h
deleted file mode 100644
index 883f682f85b8..000000000000
--- a/include/asm-ppc/sembuf.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _PPC_SEMBUF_H
-#define _PPC_SEMBUF_H
-
-/*
- * The semid64_ds structure for PPC architecture.
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- unsigned int __unused1;
- __kernel_time_t sem_otime; /* last semop time */
- unsigned int __unused2;
- __kernel_time_t sem_ctime; /* last change time */
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _PPC_SEMBUF_H */
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 6d47438be58c..485a924e4d06 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -18,8 +18,6 @@
#include <platforms/powerpmc250.h>
#elif defined(CONFIG_LOPEC)
#include <platforms/lopec.h>
-#elif defined(CONFIG_MCPN765)
-#include <platforms/mcpn765.h>
#elif defined(CONFIG_MVME5100)
#include <platforms/mvme5100.h>
#elif defined(CONFIG_PAL4)
diff --git a/include/asm-ppc/setup.h b/include/asm-ppc/setup.h
deleted file mode 100644
index d2d19ee103df..000000000000
--- a/include/asm-ppc/setup.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifdef __KERNEL__
-#ifndef _PPC_SETUP_H
-#define _PPC_SETUP_H
-
-#define m68k_num_memory num_memory
-#define m68k_memory memory
-
-#include <asm-m68k/setup.h>
-/* We have a bigger command line buffer. */
-#undef COMMAND_LINE_SIZE
-#define COMMAND_LINE_SIZE 512
-
-#endif /* _PPC_SETUP_H */
-#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/shmbuf.h b/include/asm-ppc/shmbuf.h
deleted file mode 100644
index 7ac0bd38cbd8..000000000000
--- a/include/asm-ppc/shmbuf.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _PPC_SHMBUF_H
-#define _PPC_SHMBUF_H
-
-/*
- * The shmid64_ds structure for PPC architecture.
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- unsigned int __unused1;
- __kernel_time_t shm_atime; /* last attach time */
- unsigned int __unused2;
- __kernel_time_t shm_dtime; /* last detach time */
- unsigned int __unused3;
- __kernel_time_t shm_ctime; /* last change time */
- unsigned int __unused4;
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused5;
- unsigned long __unused6;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _PPC_SHMBUF_H */
diff --git a/include/asm-ppc/shmparam.h b/include/asm-ppc/shmparam.h
deleted file mode 100644
index d6250602ae64..000000000000
--- a/include/asm-ppc/shmparam.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PPC_SHMPARAM_H
-#define _PPC_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _PPC_SHMPARAM_H */
diff --git a/include/asm-ppc/siginfo.h b/include/asm-ppc/siginfo.h
deleted file mode 100644
index 4b9435bb9049..000000000000
--- a/include/asm-ppc/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PPC_SIGINFO_H
-#define _PPC_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index 17530c232c76..829481c0a9dc 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -41,6 +41,10 @@ extern void smp_send_xmon_break(int cpu);
struct pt_regs;
extern void smp_message_recv(int, struct pt_regs *);
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+extern void cpu_die(void) __attribute__((noreturn));
+
#define NO_PROC_ID 0xFF /* No processor magic marker */
#define PROC_CHANGE_PENALTY 20
@@ -64,6 +68,8 @@ extern struct klock_info_struct klock_info;
#else /* !(CONFIG_SMP) */
+static inline void cpu_die(void) { }
+
#endif /* !(CONFIG_SMP) */
#endif /* !(_PPC_SMP_H) */
diff --git a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h
deleted file mode 100644
index 4134376b0f66..000000000000
--- a/include/asm-ppc/socket.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp */
-
-/* For setsockopt(2) */
-#define SOL_SOCKET 1
-
-#define SO_DEBUG 1
-#define SO_REUSEADDR 2
-#define SO_TYPE 3
-#define SO_ERROR 4
-#define SO_DONTROUTE 5
-#define SO_BROADCAST 6
-#define SO_SNDBUF 7
-#define SO_RCVBUF 8
-#define SO_KEEPALIVE 9
-#define SO_OOBINLINE 10
-#define SO_NO_CHECK 11
-#define SO_PRIORITY 12
-#define SO_LINGER 13
-#define SO_BSDCOMPAT 14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_RCVLOWAT 16
-#define SO_SNDLOWAT 17
-#define SO_RCVTIMEO 18
-#define SO_SNDTIMEO 19
-#define SO_PASSCRED 20
-#define SO_PEERCRED 21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION 22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
-#define SO_SECURITY_ENCRYPTION_NETWORK 24
-
-#define SO_BINDTODEVICE 25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER 26
-#define SO_DETACH_FILTER 27
-
-#define SO_PEERNAME 28
-#define SO_TIMESTAMP 29
-#define SCM_TIMESTAMP SO_TIMESTAMP
-
-#define SO_ACCEPTCONN 30
-
-#define SO_PEERSEC 31
-
-#endif /* _ASM_SOCKET_H */
diff --git a/include/asm-ppc/sockios.h b/include/asm-ppc/sockios.h
deleted file mode 100644
index 385aedc55ceb..000000000000
--- a/include/asm-ppc/sockios.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_PPC_SOCKIOS_H
-#define _ASM_PPC_SOCKIOS_H
-
-#if 0 /* These are defined this way on Alpha - maybe later. */
-/* Socket-level I/O control calls. */
-
-#define FIOGETOWN _IOR('f', 123, int)
-#define FIOSETOWN _IOW('f', 124, int)
-
-#define SIOCATMARK _IOR('s', 7, int)
-#define SIOCSPGRP _IOW('s', 8, pid_t)
-#define SIOCGPGRP _IOR('s', 9, pid_t)
-
-#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */
-#endif
-
-#endif /* _ASM_PPC_SOCKIOS_H */
diff --git a/include/asm-ppc/spinlock.h b/include/asm-ppc/spinlock.h
index 909199aae104..20edcf2a6e0c 100644
--- a/include/asm-ppc/spinlock.h
+++ b/include/asm-ppc/spinlock.h
@@ -5,41 +5,21 @@
/*
* Simple spin lock operations.
+ *
+ * (the type definitions are in asm/raw_spinlock_types.h)
*/
-typedef struct {
- volatile unsigned long lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- volatile unsigned long owner_pc;
- volatile unsigned long owner_cpu;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#ifdef __KERNEL__
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_DEBUG_INIT , 0, 0
-#else
-#define SPINLOCK_DEBUG_INIT /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 SPINLOCK_DEBUG_INIT }
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-static inline void _raw_spin_lock(spinlock_t *lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned long tmp;
__asm__ __volatile__(
- "b 1f # spin_lock\n\
+ "b 1f # __raw_spin_lock\n\
2: lwzx %0,0,%1\n\
cmpwi 0,%0,0\n\
bne+ 2b\n\
@@ -55,21 +35,13 @@ static inline void _raw_spin_lock(spinlock_t *lock)
: "cr0", "memory");
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
- __asm__ __volatile__("eieio # spin_unlock": : :"memory");
+ __asm__ __volatile__("eieio # __raw_spin_unlock": : :"memory");
lock->lock = 0;
}
-#define _raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
-
-#else
-
-extern void _raw_spin_lock(spinlock_t *lock);
-extern void _raw_spin_unlock(spinlock_t *lock);
-extern int _raw_spin_trylock(spinlock_t *lock);
-
-#endif
+#define __raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
/*
* Read-write spinlocks, allowing multiple readers
@@ -81,22 +53,11 @@ extern int _raw_spin_trylock(spinlock_t *lock);
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-typedef struct {
- volatile signed int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
+#define __raw_read_can_lock(rw) ((rw)->lock >= 0)
+#define __raw_write_can_lock(rw) (!(rw)->lock)
-#define read_can_lock(rw) ((rw)->lock >= 0)
-#define write_can_lock(rw) (!(rw)->lock)
-
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-static __inline__ int _raw_read_trylock(rwlock_t *rw)
+static __inline__ int __raw_read_trylock(raw_rwlock_t *rw)
{
signed int tmp;
@@ -116,7 +77,7 @@ static __inline__ int _raw_read_trylock(rwlock_t *rw)
return tmp > 0;
}
-static __inline__ void _raw_read_lock(rwlock_t *rw)
+static __inline__ void __raw_read_lock(raw_rwlock_t *rw)
{
signed int tmp;
@@ -137,7 +98,7 @@ static __inline__ void _raw_read_lock(rwlock_t *rw)
: "cr0", "memory");
}
-static __inline__ void _raw_read_unlock(rwlock_t *rw)
+static __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
{
signed int tmp;
@@ -153,7 +114,7 @@ static __inline__ void _raw_read_unlock(rwlock_t *rw)
: "cr0", "memory");
}
-static __inline__ int _raw_write_trylock(rwlock_t *rw)
+static __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
{
signed int tmp;
@@ -173,7 +134,7 @@ static __inline__ int _raw_write_trylock(rwlock_t *rw)
return tmp == 0;
}
-static __inline__ void _raw_write_lock(rwlock_t *rw)
+static __inline__ void __raw_write_lock(raw_rwlock_t *rw)
{
signed int tmp;
@@ -194,22 +155,10 @@ static __inline__ void _raw_write_lock(rwlock_t *rw)
: "cr0", "memory");
}
-static __inline__ void _raw_write_unlock(rwlock_t *rw)
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
{
__asm__ __volatile__("eieio # write_unlock": : :"memory");
rw->lock = 0;
}
-#else
-
-extern void _raw_read_lock(rwlock_t *rw);
-extern void _raw_read_unlock(rwlock_t *rw);
-extern void _raw_write_lock(rwlock_t *rw);
-extern void _raw_write_unlock(rwlock_t *rw);
-extern int _raw_read_trylock(rwlock_t *rw);
-extern int _raw_write_trylock(rwlock_t *rw);
-
-#endif
-
#endif /* __ASM_SPINLOCK_H */
-#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/spinlock_types.h b/include/asm-ppc/spinlock_types.h
new file mode 100644
index 000000000000..7919ccc75b8a
--- /dev/null
+++ b/include/asm-ppc/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned long lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile signed int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index 82395f30004b..d754ab570fe0 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -84,9 +84,15 @@ extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
extern void cvt_df(double *from, float *to, unsigned long *fpscr);
extern int call_rtas(const char *, int, int, unsigned long *, ...);
extern void cacheable_memzero(void *p, unsigned int nb);
+extern void *cacheable_memcpy(void *, const void *, unsigned int);
extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
extern void bad_page_fault(struct pt_regs *, unsigned long, int);
extern void die(const char *, struct pt_regs *, long);
+extern void _exception(int, struct pt_regs *, int, unsigned long);
+#ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+#endif /* CONFIG_BOOKE_WDT */
struct device_node;
extern void note_scsi_host(struct device_node *, void *);
diff --git a/include/asm-ppc/termbits.h b/include/asm-ppc/termbits.h
deleted file mode 100644
index c343fb7bdfed..000000000000
--- a/include/asm-ppc/termbits.h
+++ /dev/null
@@ -1,185 +0,0 @@
-#ifndef _PPC_TERMBITS_H
-#define _PPC_TERMBITS_H
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-/*
- * termios type and macro definitions. Be careful about adding stuff
- * to this file since it's used in GNU libc and there are strict rules
- * concerning namespace pollution.
- */
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_cc[NCCS]; /* control characters */
- cc_t c_line; /* line discipline (== c_cc[19]) */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VMIN 5
-#define VEOL 6
-#define VTIME 7
-#define VEOL2 8
-#define VSWTC 9
-
-#define VWERASE 10
-#define VREPRINT 11
-#define VSUSP 12
-#define VSTART 13
-#define VSTOP 14
-#define VLNEXT 15
-#define VDISCARD 16
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IXON 0001000
-#define IXOFF 0002000
-#define IXANY 0004000
-#define IUCLC 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define ONLCR 0000002
-#define OLCUC 0000004
-
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-
-#define OFILL 00000100
-#define OFDEL 00000200
-#define NLDLY 00001400
-#define NL0 00000000
-#define NL1 00000400
-#define NL2 00001000
-#define NL3 00001400
-#define TABDLY 00006000
-#define TAB0 00000000
-#define TAB1 00002000
-#define TAB2 00004000
-#define TAB3 00006000
-#define XTABS 00006000 /* required by POSIX to == TAB3 */
-#define CRDLY 00030000
-#define CR0 00000000
-#define CR1 00010000
-#define CR2 00020000
-#define CR3 00030000
-#define FFDLY 00040000
-#define FF0 00000000
-#define FF1 00040000
-#define BSDLY 00100000
-#define BS0 00000000
-#define BS1 00100000
-#define VTDLY 00200000
-#define VT0 00000000
-#define VT1 00200000
-
-/* c_cflag bit meaning */
-#define CBAUD 0000377
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CBAUDEX 0000000
-#define B57600 00020
-#define B115200 00021
-#define B230400 00022
-#define B460800 00023
-#define B500000 00024
-#define B576000 00025
-#define B921600 00026
-#define B1000000 00027
-#define B1152000 00030
-#define B1500000 00031
-#define B2000000 00032
-#define B2500000 00033
-#define B3000000 00034
-#define B3500000 00035
-#define B4000000 00036
-
-#define CSIZE 00001400
-#define CS5 00000000
-#define CS6 00000400
-#define CS7 00001000
-#define CS8 00001400
-
-#define CSTOPB 00002000
-#define CREAD 00004000
-#define PARENB 00010000
-#define PARODD 00020000
-#define HUPCL 00040000
-
-#define CLOCAL 00100000
-#define CRTSCTS 020000000000 /* flow control */
-
-/* c_lflag bits */
-#define ISIG 0x00000080
-#define ICANON 0x00000100
-#define XCASE 0x00004000
-#define ECHO 0x00000008
-#define ECHOE 0x00000002
-#define ECHOK 0x00000004
-#define ECHONL 0x00000010
-#define NOFLSH 0x80000000
-#define TOSTOP 0x00400000
-#define ECHOCTL 0x00000040
-#define ECHOPRT 0x00000020
-#define ECHOKE 0x00000001
-#define FLUSHO 0x00800000
-#define PENDIN 0x20000000
-#define IEXTEN 0x00000400
-
-/* Values for the ACTION argument to `tcflow'. */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* Values for the QUEUE_SELECTOR argument to `tcflush'. */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-#endif /* _PPC_TERMBITS_H */
diff --git a/include/asm-ppc/termios.h b/include/asm-ppc/termios.h
deleted file mode 100644
index 97c6287a6cba..000000000000
--- a/include/asm-ppc/termios.h
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifndef _PPC_TERMIOS_H
-#define _PPC_TERMIOS_H
-
-/*
- * Liberally adapted from alpha/termios.h. In particular, the c_cc[]
- * fields have been reordered so that termio & termios share the
- * common subset in the same order (for brain dead programs that don't
- * know or care about the differences).
- */
-
-#include <asm/ioctls.h>
-#include <asm/termbits.h>
-
-struct sgttyb {
- char sg_ispeed;
- char sg_ospeed;
- char sg_erase;
- char sg_kill;
- short sg_flags;
-};
-
-struct tchars {
- char t_intrc;
- char t_quitc;
- char t_startc;
- char t_stopc;
- char t_eofc;
- char t_brkc;
-};
-
-struct ltchars {
- char t_suspc;
- char t_dsuspc;
- char t_rprntc;
- char t_flushc;
- char t_werasc;
- char t_lnextc;
-};
-
-#define FIOCLEX _IO('f', 1)
-#define FIONCLEX _IO('f', 2)
-#define FIOASYNC _IOW('f', 125, int)
-#define FIONBIO _IOW('f', 126, int)
-#define FIONREAD _IOR('f', 127, int)
-#define TIOCINQ FIONREAD
-#define FIOQSIZE _IOR('f', 128, loff_t)
-
-#define TIOCGETP _IOR('t', 8, struct sgttyb)
-#define TIOCSETP _IOW('t', 9, struct sgttyb)
-#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */
-
-#define TIOCSETC _IOW('t', 17, struct tchars)
-#define TIOCGETC _IOR('t', 18, struct tchars)
-#define TCGETS _IOR('t', 19, struct termios)
-#define TCSETS _IOW('t', 20, struct termios)
-#define TCSETSW _IOW('t', 21, struct termios)
-#define TCSETSF _IOW('t', 22, struct termios)
-
-#define TCGETA _IOR('t', 23, struct termio)
-#define TCSETA _IOW('t', 24, struct termio)
-#define TCSETAW _IOW('t', 25, struct termio)
-#define TCSETAF _IOW('t', 28, struct termio)
-
-#define TCSBRK _IO('t', 29)
-#define TCXONC _IO('t', 30)
-#define TCFLSH _IO('t', 31)
-
-#define TIOCSWINSZ _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ _IOR('t', 104, struct winsize)
-#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
-#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
-#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
-
-#define TIOCGLTC _IOR('t', 116, struct ltchars)
-#define TIOCSLTC _IOW('t', 117, struct ltchars)
-#define TIOCSPGRP _IOW('t', 118, int)
-#define TIOCGPGRP _IOR('t', 119, int)
-
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-
-#define TIOCSTI 0x5412
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-
-struct winsize {
- unsigned short ws_row;
- unsigned short ws_col;
- unsigned short ws_xpixel;
- unsigned short ws_ypixel;
-};
-
-#define NCC 10
-struct termio {
- unsigned short c_iflag; /* input mode flags */
- unsigned short c_oflag; /* output mode flags */
- unsigned short c_cflag; /* control mode flags */
- unsigned short c_lflag; /* local mode flags */
- unsigned char c_line; /* line discipline */
- unsigned char c_cc[NCC]; /* control characters */
-};
-
-/* c_cc characters */
-#define _VINTR 0
-#define _VQUIT 1
-#define _VERASE 2
-#define _VKILL 3
-#define _VEOF 4
-#define _VMIN 5
-#define _VEOL 6
-#define _VTIME 7
-#define _VEOL2 8
-#define _VSWTC 9
-
-#ifdef __KERNEL__
-/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */
-#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025"
-#endif /* __KERNEL__ */
-
-/* modem lines */
-#define TIOCM_LE 0x001
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_ST 0x008
-#define TIOCM_SR 0x010
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RNG 0x080
-#define TIOCM_DSR 0x100
-#define TIOCM_CD TIOCM_CAR
-#define TIOCM_RI TIOCM_RNG
-#define TIOCM_OUT1 0x2000
-#define TIOCM_OUT2 0x4000
-#define TIOCM_LOOP 0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-
-/* line disciplines */
-#define N_TTY 0
-#define N_SLIP 1
-#define N_MOUSE 2
-#define N_PPP 3
-#define N_STRIP 4
-#define N_AX25 5
-#define N_X25 6 /* X.25 async */
-#define N_6PACK 7
-#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964 9 /* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC 13 /* synchronous HDLC */
-#define N_SYNC_PPP 14
-#define N_HCI 15 /* Bluetooth HCI UART */
-
-#ifdef __KERNEL__
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- unsigned short __tmp; \
- get_user(__tmp,&(termio)->x); \
- (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _PPC_TERMIOS_H */
diff --git a/include/asm-ppc/topology.h b/include/asm-ppc/topology.h
deleted file mode 100644
index 6a029bbba6e1..000000000000
--- a/include/asm-ppc/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_PPC_TOPOLOGY_H
-#define _ASM_PPC_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_PPC_TOPOLOGY_H */
diff --git a/include/asm-ppc/types.h b/include/asm-ppc/types.h
index a787bc032587..77dc24d7d2ad 100644
--- a/include/asm-ppc/types.h
+++ b/include/asm-ppc/types.h
@@ -62,8 +62,6 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
index b044ae03ac56..63f56224da8c 100644
--- a/include/asm-ppc/uaccess.h
+++ b/include/asm-ppc/uaccess.h
@@ -37,13 +37,6 @@
#define access_ok(type, addr, size) \
(__chk_user_ptr(addr),__access_ok((unsigned long)(addr),(size)))
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-ppc64/8253pit.h b/include/asm-ppc64/8253pit.h
deleted file mode 100644
index 285f78488ccb..000000000000
--- a/include/asm-ppc64/8253pit.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
-
-#ifndef _8253PIT_H
-#define _8253PIT_H
-
-#define PIT_TICK_RATE 1193182UL
-
-#endif
diff --git a/include/asm-ppc64/abs_addr.h b/include/asm-ppc64/abs_addr.h
index 6d4e8e787058..84c24d4cdb71 100644
--- a/include/asm-ppc64/abs_addr.h
+++ b/include/asm-ppc64/abs_addr.h
@@ -16,93 +16,51 @@
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/lmb.h>
+#include <asm/firmware.h>
-typedef u32 msChunks_entry;
-struct msChunks {
+struct mschunks_map {
unsigned long num_chunks;
unsigned long chunk_size;
unsigned long chunk_shift;
unsigned long chunk_mask;
- msChunks_entry *abs;
+ u32 *mapping;
};
-extern struct msChunks msChunks;
+extern struct mschunks_map mschunks_map;
-extern unsigned long msChunks_alloc(unsigned long, unsigned long, unsigned long);
-extern unsigned long reloc_offset(void);
+/* Chunks are 256 KB */
+#define MSCHUNKS_CHUNK_SHIFT (18)
+#define MSCHUNKS_CHUNK_SIZE (1UL << MSCHUNKS_CHUNK_SHIFT)
+#define MSCHUNKS_OFFSET_MASK (MSCHUNKS_CHUNK_SIZE - 1)
-#ifdef CONFIG_MSCHUNKS
-
-static inline unsigned long
-chunk_to_addr(unsigned long chunk)
+static inline unsigned long chunk_to_addr(unsigned long chunk)
{
- unsigned long offset = reloc_offset();
- struct msChunks *_msChunks = PTRRELOC(&msChunks);
-
- return chunk << _msChunks->chunk_shift;
+ return chunk << MSCHUNKS_CHUNK_SHIFT;
}
-static inline unsigned long
-addr_to_chunk(unsigned long addr)
+static inline unsigned long addr_to_chunk(unsigned long addr)
{
- unsigned long offset = reloc_offset();
- struct msChunks *_msChunks = PTRRELOC(&msChunks);
-
- return addr >> _msChunks->chunk_shift;
+ return addr >> MSCHUNKS_CHUNK_SHIFT;
}
-static inline unsigned long
-chunk_offset(unsigned long addr)
+static inline unsigned long phys_to_abs(unsigned long pa)
{
- unsigned long offset = reloc_offset();
- struct msChunks *_msChunks = PTRRELOC(&msChunks);
+ unsigned long chunk;
- return addr & _msChunks->chunk_mask;
-}
+ /* This is a no-op on non-iSeries */
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return pa;
-static inline unsigned long
-abs_chunk(unsigned long pchunk)
-{
- unsigned long offset = reloc_offset();
- struct msChunks *_msChunks = PTRRELOC(&msChunks);
- if ( pchunk >= _msChunks->num_chunks ) {
- return pchunk;
- }
- return PTRRELOC(_msChunks->abs)[pchunk];
-}
+ chunk = addr_to_chunk(pa);
-/* A macro so it can take pointers or unsigned long. */
-#define phys_to_abs(pa) \
- ({ unsigned long _pa = (unsigned long)(pa); \
- chunk_to_addr(abs_chunk(addr_to_chunk(_pa))) + chunk_offset(_pa); \
- })
+ if (chunk < mschunks_map.num_chunks)
+ chunk = mschunks_map.mapping[chunk];
-static inline unsigned long
-physRpn_to_absRpn(unsigned long rpn)
-{
- unsigned long pa = rpn << PAGE_SHIFT;
- unsigned long aa = phys_to_abs(pa);
- return (aa >> PAGE_SHIFT);
+ return chunk_to_addr(chunk) + (pa & MSCHUNKS_OFFSET_MASK);
}
-/* A macro so it can take pointers or unsigned long. */
-#define abs_to_phys(aa) lmb_abs_to_phys((unsigned long)(aa))
-
-#else /* !CONFIG_MSCHUNKS */
-
-#define chunk_to_addr(chunk) ((unsigned long)(chunk))
-#define addr_to_chunk(addr) (addr)
-#define chunk_offset(addr) (0)
-#define abs_chunk(pchunk) (pchunk)
-
-#define phys_to_abs(pa) (pa)
-#define physRpn_to_absRpn(rpn) (rpn)
-#define abs_to_phys(aa) (aa)
-
-#endif /* !CONFIG_MSCHUNKS */
-
/* Convenience macros */
#define virt_to_abs(va) phys_to_abs(__pa(va))
-#define abs_to_virt(aa) __va(abs_to_phys(aa))
+#define abs_to_virt(aa) __va(aa)
#endif /* _ABS_ADDR_H */
diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
deleted file mode 100644
index ca9e423307f4..000000000000
--- a/include/asm-ppc64/agp.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef AGP_H
-#define AGP_H 1
-
-#include <asm/io.h>
-
-/* nothing much needed here */
-
-#define map_page_into_agp(page)
-#define unmap_page_from_agp(page)
-#define flush_agp_mappings()
-#define flush_agp_cache() mb()
-
-/* Convert a physical address to an address suitable for the GART. */
-#define phys_to_gart(x) (x)
-#define gart_to_phys(x) (x)
-
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order) \
- ((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order) \
- free_pages((unsigned long)(table), (order))
-
-#endif
diff --git a/include/asm-ppc64/auxvec.h b/include/asm-ppc64/auxvec.h
new file mode 100644
index 000000000000..ac6381a106e1
--- /dev/null
+++ b/include/asm-ppc64/auxvec.h
@@ -0,0 +1,19 @@
+#ifndef __PPC64_AUXVEC_H
+#define __PPC64_AUXVEC_H
+
+/*
+ * We need to put in some extra aux table entries to tell glibc what
+ * the cache block size is, so it can use the dcbz instruction safely.
+ */
+#define AT_DCACHEBSIZE 19
+#define AT_ICACHEBSIZE 20
+#define AT_UCACHEBSIZE 21
+/* A special ignored type value for PPC, for glibc compatibility. */
+#define AT_IGNOREPPC 22
+
+/* The vDSO location. We have to use the same value as x86 for glibc's
+ * sake :-)
+ */
+#define AT_SYSINFO_EHDR 33
+
+#endif /* __PPC64_AUXVEC_H */
diff --git a/include/asm-ppc64/bugs.h b/include/asm-ppc64/bugs.h
deleted file mode 100644
index 861074b3cf71..000000000000
--- a/include/asm-ppc64/bugs.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * This file is included by 'init/main.c' to check for architecture-dependent
- * bugs.
- *
- */
-#ifndef _ASM_PPC64_BUGS_H
-#define _ASM_PPC64_BUGS_H
-
-static void check_bugs(void) {
-}
-
-#endif /* _ASM_PPC64_BUGS_H */
diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h
index 12414f5fc666..6ec62cd2d1d1 100644
--- a/include/asm-ppc64/compat.h
+++ b/include/asm-ppc64/compat.h
@@ -13,8 +13,10 @@ typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
-typedef u32 compat_uid_t;
-typedef u32 compat_gid_t;
+typedef u32 __compat_uid_t;
+typedef u32 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u32 compat_mode_t;
typedef u32 compat_ino_t;
typedef u32 compat_dev_t;
@@ -48,8 +50,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid32_t st_uid;
+ __compat_gid32_t st_gid;
compat_dev_t st_rdev;
compat_off_t st_size;
compat_off_t st_blksize;
@@ -144,10 +146,10 @@ static inline void __user *compat_alloc_user_space(long len)
*/
struct compat_ipc64_perm {
compat_key_t key;
- compat_uid_t uid;
- compat_gid_t gid;
- compat_uid_t cuid;
- compat_gid_t cgid;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
+ __compat_uid_t cuid;
+ __compat_gid_t cgid;
compat_mode_t mode;
unsigned int seq;
unsigned int __pad2;
diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h
index d67fa9e26079..acc9b4d6c168 100644
--- a/include/asm-ppc64/cputable.h
+++ b/include/asm-ppc64/cputable.h
@@ -36,6 +36,7 @@
* via the mkdefs mechanism.
*/
struct cpu_spec;
+struct op_ppc64_model;
typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
@@ -52,15 +53,19 @@ struct cpu_spec {
unsigned int icache_bsize;
unsigned int dcache_bsize;
+ /* number of performance monitor counters */
+ unsigned int num_pmcs;
+
/* this is called to initialize various CPU bits like L1 cache,
* BHT, SPD, etc... from head.S before branching to identify_machine
*/
cpu_setup_t cpu_setup;
- /* This is used to identify firmware features which are available
- * to the kernel.
- */
- unsigned long firmware_features;
+ /* Used by oprofile userspace to select the right counters */
+ char *oprofile_cpu_type;
+
+ /* Processor specific oprofile operations */
+ struct op_ppc64_model *oprofile_model;
};
extern struct cpu_spec cpu_specs[];
@@ -71,39 +76,6 @@ static inline unsigned long cpu_has_feature(unsigned long feature)
return cur_cpu_spec->cpu_features & feature;
}
-
-/* firmware feature bitmask values */
-#define FIRMWARE_MAX_FEATURES 63
-
-#define FW_FEATURE_PFT (1UL<<0)
-#define FW_FEATURE_TCE (1UL<<1)
-#define FW_FEATURE_SPRG0 (1UL<<2)
-#define FW_FEATURE_DABR (1UL<<3)
-#define FW_FEATURE_COPY (1UL<<4)
-#define FW_FEATURE_ASR (1UL<<5)
-#define FW_FEATURE_DEBUG (1UL<<6)
-#define FW_FEATURE_TERM (1UL<<7)
-#define FW_FEATURE_PERF (1UL<<8)
-#define FW_FEATURE_DUMP (1UL<<9)
-#define FW_FEATURE_INTERRUPT (1UL<<10)
-#define FW_FEATURE_MIGRATE (1UL<<11)
-#define FW_FEATURE_PERFMON (1UL<<12)
-#define FW_FEATURE_CRQ (1UL<<13)
-#define FW_FEATURE_VIO (1UL<<14)
-#define FW_FEATURE_RDMA (1UL<<15)
-#define FW_FEATURE_LLAN (1UL<<16)
-#define FW_FEATURE_BULK (1UL<<17)
-#define FW_FEATURE_XDABR (1UL<<18)
-#define FW_FEATURE_MULTITCE (1UL<<19)
-#define FW_FEATURE_SPLPAR (1UL<<20)
-
-typedef struct {
- unsigned long val;
- char * name;
-} firmware_feature_t;
-
-extern firmware_feature_t firmware_features_table[];
-
#endif /* __ASSEMBLY__ */
/* CPU kernel features */
@@ -133,17 +105,15 @@ extern firmware_feature_t firmware_features_table[];
#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000)
#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
-#define CPU_FTR_PMC8 ASM_CONST(0x0000008000000000)
+/* unused ASM_CONST(0x0000008000000000) */
#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000)
-/* Platform firmware features */
-#define FW_FTR_ ASM_CONST(0x0000000000000001)
-
#ifndef __ASSEMBLY__
+
#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \
PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU)
@@ -156,10 +126,9 @@ extern firmware_feature_t firmware_features_table[];
#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE)
#else
#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE)
-#endif
+#endif /* CONFIG_PPC_ISERIES */
-#define COMMON_PPC64_FW (0)
-#endif
+#endif /* __ASSEMBLY */
#ifdef __ASSEMBLY__
diff --git a/include/asm-ppc64/cputime.h b/include/asm-ppc64/cputime.h
deleted file mode 100644
index 8e9faf5ce720..000000000000
--- a/include/asm-ppc64/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PPC_CPUTIME_H
-#define __PPC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __PPC_CPUTIME_H */
diff --git a/include/asm-ppc64/div64.h b/include/asm-ppc64/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/include/asm-ppc64/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
index 94298b106a4b..40c8eb57493e 100644
--- a/include/asm-ppc64/eeh.h
+++ b/include/asm-ppc64/eeh.h
@@ -219,23 +219,24 @@ static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr)
static inline void eeh_memset_io(volatile void __iomem *addr, int c,
unsigned long n)
{
+ void *p = (void __force *)addr;
u32 lc = c;
lc |= lc << 8;
lc |= lc << 16;
- while(n && !EEH_CHECK_ALIGN(addr, 4)) {
- *((volatile u8 *)addr) = c;
- addr = (void *)((unsigned long)addr + 1);
+ while(n && !EEH_CHECK_ALIGN(p, 4)) {
+ *((volatile u8 *)p) = c;
+ p++;
n--;
}
while(n >= 4) {
- *((volatile u32 *)addr) = lc;
- addr = (void *)((unsigned long)addr + 4);
+ *((volatile u32 *)p) = lc;
+ p += 4;
n -= 4;
}
while(n) {
- *((volatile u8 *)addr) = c;
- addr = (void *)((unsigned long)addr + 1);
+ *((volatile u8 *)p) = c;
+ p++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
@@ -250,22 +251,22 @@ static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *sr
while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
- vsrc = (void *)((unsigned long)vsrc + 1);
- dest = (void *)((unsigned long)dest + 1);
+ vsrc++;
+ dest++;
n--;
}
while(n > 4) {
*((u32 *)dest) = *((volatile u32 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
- vsrc = (void *)((unsigned long)vsrc + 4);
- dest = (void *)((unsigned long)dest + 4);
+ vsrc += 4;
+ dest += 4;
n -= 4;
}
while(n) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
- vsrc = (void *)((unsigned long)vsrc + 1);
- dest = (void *)((unsigned long)dest + 1);
+ vsrc++;
+ dest++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
@@ -286,20 +287,20 @@ static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src,
while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
*((volatile u8 *)vdest) = *((u8 *)src);
- src = (void *)((unsigned long)src + 1);
- vdest = (void *)((unsigned long)vdest + 1);
+ src++;
+ vdest++;
n--;
}
while(n > 4) {
*((volatile u32 *)vdest) = *((volatile u32 *)src);
- src = (void *)((unsigned long)src + 4);
- vdest = (void *)((unsigned long)vdest + 4);
+ src += 4;
+ vdest += 4;
n-=4;
}
while(n) {
*((volatile u8 *)vdest) = *((u8 *)src);
- src = (void *)((unsigned long)src + 1);
- vdest = (void *)((unsigned long)vdest + 1);
+ src++;
+ vdest++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
index 085eedb956fe..c919a89343db 100644
--- a/include/asm-ppc64/elf.h
+++ b/include/asm-ppc64/elf.h
@@ -4,6 +4,7 @@
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/cputable.h>
+#include <asm/auxvec.h>
/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE 0
@@ -237,21 +238,6 @@ do { \
#endif
-/*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE 19
-#define AT_ICACHEBSIZE 20
-#define AT_UCACHEBSIZE 21
-/* A special ignored type value for PPC, for glibc compatibility. */
-#define AT_IGNOREPPC 22
-
-/* The vDSO location. We have to use the same value as x86 for glibc's
- * sake :-)
- */
-#define AT_SYSINFO_EHDR 33
-
extern int dcache_bsize;
extern int icache_bsize;
extern int ucache_bsize;
diff --git a/include/asm-ppc64/emergency-restart.h b/include/asm-ppc64/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/include/asm-ppc64/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/include/asm-ppc64/errno.h b/include/asm-ppc64/errno.h
deleted file mode 100644
index 69bc3b0c6cbe..000000000000
--- a/include/asm-ppc64/errno.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _PPC64_ERRNO_H
-#define _PPC64_ERRNO_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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-generic/errno.h>
-
-#undef EDEADLOCK
-#define EDEADLOCK 58 /* File locking deadlock error */
-
-#define _LAST_ERRNO 516
-
-#endif
diff --git a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h
deleted file mode 100644
index 842560d50656..000000000000
--- a/include/asm-ppc64/fcntl.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef _PPC64_FCNTL_H
-#define _PPC64_FCNTL_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECTORY 040000 /* must be a directory */
-#define O_NOFOLLOW 0100000 /* don't follow links */
-#define O_LARGEFILE 0200000
-#define O_DIRECT 0400000 /* direct disk access hint */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-#ifdef __KERNEL__
-#define F_POSIX 1
-#define F_FLOCK 2
-#define F_BROKEN 4 /* broken flock() emulation */
-#endif /* __KERNEL__ */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif /* _PPC64_FCNTL_H */
diff --git a/include/asm-ppc64/firmware.h b/include/asm-ppc64/firmware.h
new file mode 100644
index 000000000000..22bb85cf60af
--- /dev/null
+++ b/include/asm-ppc64/firmware.h
@@ -0,0 +1,101 @@
+/*
+ * include/asm-ppc64/firmware.h
+ *
+ * Extracted from include/asm-ppc64/cputable.h
+ *
+ * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * Modifications for ppc64:
+ * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_PPC_FIRMWARE_H
+#define __ASM_PPC_FIRMWARE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+/* firmware feature bitmask values */
+#define FIRMWARE_MAX_FEATURES 63
+
+#define FW_FEATURE_PFT (1UL<<0)
+#define FW_FEATURE_TCE (1UL<<1)
+#define FW_FEATURE_SPRG0 (1UL<<2)
+#define FW_FEATURE_DABR (1UL<<3)
+#define FW_FEATURE_COPY (1UL<<4)
+#define FW_FEATURE_ASR (1UL<<5)
+#define FW_FEATURE_DEBUG (1UL<<6)
+#define FW_FEATURE_TERM (1UL<<7)
+#define FW_FEATURE_PERF (1UL<<8)
+#define FW_FEATURE_DUMP (1UL<<9)
+#define FW_FEATURE_INTERRUPT (1UL<<10)
+#define FW_FEATURE_MIGRATE (1UL<<11)
+#define FW_FEATURE_PERFMON (1UL<<12)
+#define FW_FEATURE_CRQ (1UL<<13)
+#define FW_FEATURE_VIO (1UL<<14)
+#define FW_FEATURE_RDMA (1UL<<15)
+#define FW_FEATURE_LLAN (1UL<<16)
+#define FW_FEATURE_BULK (1UL<<17)
+#define FW_FEATURE_XDABR (1UL<<18)
+#define FW_FEATURE_MULTITCE (1UL<<19)
+#define FW_FEATURE_SPLPAR (1UL<<20)
+#define FW_FEATURE_ISERIES (1UL<<21)
+
+enum {
+ FW_FEATURE_PSERIES_POSSIBLE = FW_FEATURE_PFT | FW_FEATURE_TCE |
+ FW_FEATURE_SPRG0 | FW_FEATURE_DABR | FW_FEATURE_COPY |
+ FW_FEATURE_ASR | FW_FEATURE_DEBUG | FW_FEATURE_TERM |
+ FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT |
+ FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
+ FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
+ FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
+ FW_FEATURE_SPLPAR,
+ FW_FEATURE_PSERIES_ALWAYS = 0,
+ FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES,
+ FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES,
+ FW_FEATURE_POSSIBLE =
+#ifdef CONFIG_PPC_PSERIES
+ FW_FEATURE_PSERIES_POSSIBLE |
+#endif
+#ifdef CONFIG_PPC_ISERIES
+ FW_FEATURE_ISERIES_POSSIBLE |
+#endif
+ 0,
+ FW_FEATURE_ALWAYS =
+#ifdef CONFIG_PPC_PSERIES
+ FW_FEATURE_PSERIES_ALWAYS &
+#endif
+#ifdef CONFIG_PPC_ISERIES
+ FW_FEATURE_ISERIES_ALWAYS &
+#endif
+ FW_FEATURE_POSSIBLE,
+};
+
+/* This is used to identify firmware features which are available
+ * to the kernel.
+ */
+extern unsigned long ppc64_firmware_features;
+
+static inline unsigned long firmware_has_feature(unsigned long feature)
+{
+ return (FW_FEATURE_ALWAYS & feature) ||
+ (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
+}
+
+#ifdef CONFIG_PPC_PSERIES
+typedef struct {
+ unsigned long val;
+ char * name;
+} firmware_feature_t;
+
+extern firmware_feature_t firmware_features_table[];
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* __ASM_PPC_FIRMWARE_H */
diff --git a/include/asm-ppc64/futex.h b/include/asm-ppc64/futex.h
new file mode 100644
index 000000000000..cb2640b3a408
--- /dev/null
+++ b/include/asm-ppc64/futex.h
@@ -0,0 +1,83 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/memory.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile (SYNC_ON_SMP \
+"1: lwarx %0,0,%2\n" \
+ insn \
+"2: stwcx. %1,0,%2\n\
+ bne- 1b\n\
+ li %1,0\n\
+3: .section .fixup,\"ax\"\n\
+4: li %1,%3\n\
+ b 3b\n\
+ .previous\n\
+ .section __ex_table,\"a\"\n\
+ .align 3\n\
+ .llong 1b,4b,2b,4b\n\
+ .previous" \
+ : "=&r" (oldval), "=&r" (ret) \
+ : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \
+ : "cr0", "memory")
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ inc_preempt_count();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-ppc64/hdreg.h b/include/asm-ppc64/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-ppc64/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
index 4f668a4baff0..ab7c3cf24888 100644
--- a/include/asm-ppc64/hvcall.h
+++ b/include/asm-ppc64/hvcall.h
@@ -56,6 +56,11 @@
#define H_PP1 (1UL<<(63-62))
#define H_PP2 (1UL<<(63-63))
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR (1UL<<(63-61))
+#define H_DABRX_KERNEL (1UL<<(63-62))
+#define H_DABRX_USER (1UL<<(63-63))
+
/* pSeries hypervisor opcodes */
#define H_REMOVE 0x04
#define H_ENTER 0x08
@@ -101,6 +106,7 @@
#define H_VIO_SIGNAL 0x104
#define H_SEND_CRQ 0x108
#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
diff --git a/include/asm-ppc64/imalloc.h b/include/asm-ppc64/imalloc.h
index e46ff68a6e41..42adf7033a81 100644
--- a/include/asm-ppc64/imalloc.h
+++ b/include/asm-ppc64/imalloc.h
@@ -6,7 +6,7 @@
*/
#define PHBS_IO_BASE VMALLOC_END
#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END (VMALLOC_START + EADDR_MASK)
+#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE)
/* imalloc region types */
diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
index aba1dfa388ba..59c958aea4db 100644
--- a/include/asm-ppc64/io.h
+++ b/include/asm-ppc64/io.h
@@ -20,10 +20,10 @@
#include <asm-generic/iomap.h>
-#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c))
-#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c))
-#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c))
-#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 *)(p), (a), (c))
+#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c))
+#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c))
+#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c))
+#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c))
#define SIO_CONFIG_RA 0x398
@@ -71,8 +71,8 @@ extern unsigned long io_page_mask;
* Neither do the standard versions now, these are just here
* for older code.
*/
-#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
#else
static inline unsigned char __raw_readb(const volatile void __iomem *addr)
@@ -136,9 +136,9 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
-#define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns))
-#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
#endif
@@ -147,16 +147,16 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
#define readl_relaxed(addr) readl(addr)
#define readq_relaxed(addr) readq(addr)
-extern void _insb(volatile u8 *port, void *buf, int ns);
-extern void _outsb(volatile u8 *port, const void *buf, int ns);
-extern void _insw(volatile u16 *port, void *buf, int ns);
-extern void _outsw(volatile u16 *port, const void *buf, int ns);
-extern void _insl(volatile u32 *port, void *buf, int nl);
-extern void _outsl(volatile u32 *port, const void *buf, int nl);
-extern void _insw_ns(volatile u16 *port, void *buf, int ns);
-extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
-extern void _insl_ns(volatile u32 *port, void *buf, int nl);
-extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+extern void _insb(volatile u8 __iomem *port, void *buf, int ns);
+extern void _outsb(volatile u8 __iomem *port, const void *buf, int ns);
+extern void _insw(volatile u16 __iomem *port, void *buf, int ns);
+extern void _outsw(volatile u16 __iomem *port, const void *buf, int ns);
+extern void _insl(volatile u32 __iomem *port, void *buf, int nl);
+extern void _outsl(volatile u32 __iomem *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 __iomem *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 __iomem *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl);
#define mmiowb()
@@ -176,8 +176,8 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
* Neither do the standard versions now, these are just here
* for older code.
*/
-#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+#define outsw_ns(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define outsl_ns(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
#define IO_SPACE_LIMIT ~(0UL)
diff --git a/include/asm-ppc64/ioctl.h b/include/asm-ppc64/ioctl.h
deleted file mode 100644
index 42b8c5da7fbc..000000000000
--- a/include/asm-ppc64/ioctl.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef _PPC64_IOCTL_H
-#define _PPC64_IOCTL_H
-
-
-/*
- * This was copied from the alpha as it's a bit cleaner there.
- * -- Cort
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 13
-#define _IOC_DIRBITS 3
-
-#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT 0
-#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
- * And this turns out useful to catch old ioctl numbers in header
- * files for us.
- */
-#define _IOC_NONE 1U
-#define _IOC_READ 2U
-#define _IOC_WRITE 4U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* provoke compile error for invalid uses of size argument */
-extern unsigned int __invalid_size_argument_for_IOC;
-#define _IOC_TYPECHECK(t) \
- ((sizeof(t) == sizeof(t[1]) && \
- sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
- sizeof(t) : __invalid_size_argument_for_IOC)
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode them.. */
-#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* various drivers, such as the pcmcia stuff, need these... */
-#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
-
-#endif /* _PPC64_IOCTL_H */
diff --git a/include/asm-ppc64/ioctls.h b/include/asm-ppc64/ioctls.h
deleted file mode 100644
index 48796bf3e4fc..000000000000
--- a/include/asm-ppc64/ioctls.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef _ASM_PPC64_IOCTLS_H
-#define _ASM_PPC64_IOCTLS_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/ioctl.h>
-
-#define FIOCLEX _IO('f', 1)
-#define FIONCLEX _IO('f', 2)
-#define FIOASYNC _IOW('f', 125, int)
-#define FIONBIO _IOW('f', 126, int)
-#define FIONREAD _IOR('f', 127, int)
-#define TIOCINQ FIONREAD
-#define FIOQSIZE _IOR('f', 128, loff_t)
-
-#define TIOCGETP _IOR('t', 8, struct sgttyb)
-#define TIOCSETP _IOW('t', 9, struct sgttyb)
-#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */
-
-#define TIOCSETC _IOW('t', 17, struct tchars)
-#define TIOCGETC _IOR('t', 18, struct tchars)
-#define TCGETS _IOR('t', 19, struct termios)
-#define TCSETS _IOW('t', 20, struct termios)
-#define TCSETSW _IOW('t', 21, struct termios)
-#define TCSETSF _IOW('t', 22, struct termios)
-
-#define TCGETA _IOR('t', 23, struct termio)
-#define TCSETA _IOW('t', 24, struct termio)
-#define TCSETAW _IOW('t', 25, struct termio)
-#define TCSETAF _IOW('t', 28, struct termio)
-
-#define TCSBRK _IO('t', 29)
-#define TCXONC _IO('t', 30)
-#define TCFLSH _IO('t', 31)
-
-#define TIOCSWINSZ _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ _IOR('t', 104, struct winsize)
-#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
-#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
-#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
-
-#define TIOCGLTC _IOR('t', 116, struct ltchars)
-#define TIOCSLTC _IOW('t', 117, struct ltchars)
-#define TIOCSPGRP _IOW('t', 118, int)
-#define TIOCGPGRP _IOR('t', 119, int)
-
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-
-#define TIOCSTI 0x5412
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-# define TIOCM_LE 0x001
-# define TIOCM_DTR 0x002
-# define TIOCM_RTS 0x004
-# define TIOCM_ST 0x008
-# define TIOCM_SR 0x010
-# define TIOCM_CTS 0x020
-# define TIOCM_CAR 0x040
-# define TIOCM_RNG 0x080
-# define TIOCM_DSR 0x100
-# define TIOCM_CD TIOCM_CAR
-# define TIOCM_RI TIOCM_RNG
-
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-# define TIOCPKT_DATA 0
-# define TIOCPKT_FLUSHREAD 1
-# define TIOCPKT_FLUSHWRITE 2
-# define TIOCPKT_STOP 4
-# define TIOCPKT_START 8
-# define TIOCPKT_NOSTOP 16
-# define TIOCPKT_DOSTOP 32
-
-
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
- /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-
-#endif /* _ASM_PPC64_IOCTLS_H */
diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
index 729de5cc21d9..72dcf8116b04 100644
--- a/include/asm-ppc64/iommu.h
+++ b/include/asm-ppc64/iommu.h
@@ -104,9 +104,6 @@ extern void iommu_devnode_init_pSeries(struct device_node *dn);
#ifdef CONFIG_PPC_ISERIES
-/* Initializes tables for bio buses */
-extern void __init iommu_vio_init(void);
-
struct iSeries_Device_Node;
/* Creates table for an individual device node */
extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn);
diff --git a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h
deleted file mode 100644
index a46e3d9c2a3f..000000000000
--- a/include/asm-ppc64/ipc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h
index 570678b1da95..99782afb4cde 100644
--- a/include/asm-ppc64/irq.h
+++ b/include/asm-ppc64/irq.h
@@ -33,6 +33,11 @@
#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
+/*
+ * IRQ line status macro IRQ_PER_CPU is used
+ */
+#define ARCH_HAS_IRQ_PER_CPU
+
#define get_irq_desc(irq) (&irq_desc[(irq)])
/* Define a way to iterate across irqs. */
diff --git a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h
index 0802919c3235..d9129d2b038e 100644
--- a/include/asm-ppc64/kprobes.h
+++ b/include/asm-ppc64/kprobes.h
@@ -42,6 +42,9 @@ typedef unsigned int kprobe_opcode_t;
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry)
+#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
+ IS_TWI(instr) || IS_TDI(instr))
+
#define ARCH_SUPPORTS_KRETPROBES
void kretprobe_trampoline(void);
diff --git a/include/asm-ppc64/linkage.h b/include/asm-ppc64/linkage.h
deleted file mode 100644
index 291c2d01c44f..000000000000
--- a/include/asm-ppc64/linkage.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-/* Nothing to see here... */
-
-#endif
diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
index a6cbca21ac1d..de91e034bd98 100644
--- a/include/asm-ppc64/lmb.h
+++ b/include/asm-ppc64/lmb.h
@@ -22,7 +22,6 @@
struct lmb_property {
unsigned long base;
- unsigned long physbase;
unsigned long size;
};
@@ -57,4 +56,26 @@ extern void lmb_dump_all(void);
extern unsigned long io_hole_start;
+static inline unsigned long
+lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
+{
+ return type->region[region_nr].size;
+}
+static inline unsigned long
+lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
+{
+ return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
+}
+static inline unsigned long
+lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
+{
+ return type->region[region_nr].base >> PAGE_SHIFT;
+}
+static inline unsigned long
+lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
+{
+ return lmb_start_pfn(type, region_nr) +
+ lmb_size_pages(type, region_nr);
+}
+
#endif /* _PPC64_LMB_H */
diff --git a/include/asm-ppc64/lppaca.h b/include/asm-ppc64/lppaca.h
index 70766b5f26c1..9e2a6c0649a0 100644
--- a/include/asm-ppc64/lppaca.h
+++ b/include/asm-ppc64/lppaca.h
@@ -108,7 +108,7 @@ struct lppaca
volatile u32 virtual_decr; // Virtual DECR for shared procsx78-x7B
u16 slb_count; // # of SLBs to maintain x7C-x7D
u8 idle; // Indicate OS is idle x7E
- u8 reserved5; // Reserved x7F
+ u8 vmxregs_in_use; // VMX registers in use x7F
//=============================================================================
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index f0ef06375947..8027160ec96d 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -88,6 +88,7 @@ struct machdep_calls {
/* PCI stuff */
void (*pcibios_fixup)(void);
+ int (*pci_probe_mode)(struct pci_bus *);
void (*restart)(char *cmd);
void (*power_off)(void);
@@ -103,11 +104,6 @@ struct machdep_calls {
void (*progress)(char *, unsigned short);
- /* Debug interface. Low level I/O to some terminal device */
- void (*udbg_putc)(unsigned char c);
- unsigned char (*udbg_getc)(void);
- int (*udbg_getc_poll)(void);
-
/* Interface for platform error logging */
void (*log_error)(char *buf, unsigned int err_type, int fatal);
@@ -140,6 +136,9 @@ struct machdep_calls {
/* Idle loop for this platform, leave empty for default idle loop */
int (*idle_loop)(void);
+
+ /* Function to enable pmcs for this platform, called once per cpu. */
+ void (*enable_pmcs)(void);
};
extern int default_idle(void);
@@ -175,10 +174,6 @@ extern sys_ctrler_t sys_ctrler;
void ppc64_boot_msg(unsigned int src, const char *msg);
/* Print a termination message (print only -- does not stop the kernel) */
void ppc64_terminate_msg(unsigned int src, const char *msg);
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg);
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg);
static inline void log_error(char *buf, unsigned int err_type, int fatal)
{
diff --git a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h
index 56e09face9a8..af53ffb55726 100644
--- a/include/asm-ppc64/memory.h
+++ b/include/asm-ppc64/memory.h
@@ -18,9 +18,11 @@
#ifdef CONFIG_SMP
#define EIEIO_ON_SMP "eieio\n"
#define ISYNC_ON_SMP "\n\tisync"
+#define SYNC_ON_SMP "lwsync\n\t"
#else
#define EIEIO_ON_SMP
#define ISYNC_ON_SMP
+#define SYNC_ON_SMP
#endif
static inline void eieio(void)
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
index 70348a851313..7bc42eb087ad 100644
--- a/include/asm-ppc64/mmu.h
+++ b/include/asm-ppc64/mmu.h
@@ -28,9 +28,12 @@
#define STE_VSID_SHIFT 12
/* Location of cpu0's segment table */
-#define STAB0_PAGE 0x9
+#define STAB0_PAGE 0x6
#define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT)
-#define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR)
+
+#ifndef __ASSEMBLY__
+extern char initial_stab[];
+#endif /* ! __ASSEMBLY */
/*
* SLB
@@ -51,8 +54,10 @@
#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
#define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */
-#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C)
-#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS)
+#define SLB_VSID_KERNEL (SLB_VSID_KP)
+#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
+
+#define SLBIE_C (0x08000000)
/*
* Hash table
@@ -259,8 +264,10 @@ extern void stabs_alloc(void);
#define VSID_BITS 36
#define VSID_MODULUS ((1UL<<VSID_BITS)-1)
-#define CONTEXT_BITS 20
-#define USER_ESID_BITS 15
+#define CONTEXT_BITS 19
+#define USER_ESID_BITS 16
+
+#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT))
/*
* This macro generates asm code to compute the VSID scramble
@@ -302,8 +309,7 @@ typedef unsigned long mm_context_id_t;
typedef struct {
mm_context_id_t id;
#ifdef CONFIG_HUGETLB_PAGE
- pgd_t *huge_pgdir;
- u16 htlb_segs; /* bitmask */
+ u16 low_htlb_areas, high_htlb_areas;
#endif
} mm_context_t;
diff --git a/include/asm-ppc64/module.h b/include/asm-ppc64/module.h
deleted file mode 100644
index 0581607826e8..000000000000
--- a/include/asm-ppc64/module.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _ASM_PPC64_MODULE_H
-#define _ASM_PPC64_MODULE_H
-
-#include <linux/list.h>
-#include <asm/bug.h>
-
-struct mod_arch_specific
-{
- /* Index of stubs section within module. */
- unsigned int stubs_section;
-
- /* What section is the TOC? */
- unsigned int toc_section;
-
- /* List of BUG addresses, source line numbers and filenames */
- struct list_head bug_list;
- struct bug_entry *bug_table;
- unsigned int num_bugs;
-};
-
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-
-/* Make empty section for module_frob_arch_sections to expand. */
-#ifdef MODULE
-asm(".section .stubs,\"ax\",@nobits; .align 3; .previous");
-#endif
-
-struct exception_table_entry;
-void sort_ex_table(struct exception_table_entry *start,
- struct exception_table_entry *finish);
-
-#endif /* _ASM_PPC64_MODULE_H */
diff --git a/include/asm-ppc64/msgbuf.h b/include/asm-ppc64/msgbuf.h
deleted file mode 100644
index 31c1cbf133cc..000000000000
--- a/include/asm-ppc64/msgbuf.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _PPC64_MSGBUF_H
-#define _PPC64_MSGBUF_H
-
-/*
- * The msqid64_ds structure for the PPC architecture.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
- __kernel_time_t msg_rtime; /* last msgrcv time */
- __kernel_time_t msg_ctime; /* last change time */
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* _PPC64_MSGBUF_H */
diff --git a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h
index bfb7caa32eaf..d2afe6447597 100644
--- a/include/asm-ppc64/naca.h
+++ b/include/asm-ppc64/naca.h
@@ -12,8 +12,6 @@
#include <asm/types.h>
-#ifndef __ASSEMBLY__
-
struct naca_struct {
/* Kernel only data - undefined for user space */
void *xItVpdAreas; /* VPD Data 0x00 */
@@ -23,9 +21,4 @@ struct naca_struct {
extern struct naca_struct naca;
-#endif /* __ASSEMBLY__ */
-
-#define NACA_PAGE 0x4
-#define NACA_PHYS_ADDR (NACA_PAGE<<PAGE_SHIFT)
-
#endif /* _NACA_H */
diff --git a/include/asm-ppc64/namei.h b/include/asm-ppc64/namei.h
deleted file mode 100644
index a1412a2d102a..000000000000
--- a/include/asm-ppc64/namei.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm-ppc/namei.h
- * Adapted from linux/include/asm-alpha/namei.h
- *
- * Included from linux/fs/namei.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.
- */
-
-#ifndef __PPC64_NAMEI_H
-#define __PPC64_NAMEI_H
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-
-#define __emul_prefix() NULL
-
-#endif /* __PPC64_NAMEI_H */
diff --git a/arch/ppc64/oprofile/op_impl.h b/include/asm-ppc64/oprofile_impl.h
index 7fa7eaabc035..b04f1dfb1421 100644
--- a/arch/ppc64/oprofile/op_impl.h
+++ b/include/asm-ppc64/oprofile_impl.h
@@ -49,6 +49,9 @@ struct op_ppc64_model {
int num_counters;
};
+extern struct op_ppc64_model op_model_rs64;
+extern struct op_ppc64_model op_model_power4;
+
static inline unsigned int ctr_read(unsigned int i)
{
switch(i) {
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index a5893a305a09..a15422bcf30d 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -37,39 +37,45 @@
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-/* For 64-bit processes the hugepage range is 1T-1.5T */
-#define TASK_HPAGE_BASE ASM_CONST(0x0000010000000000)
-#define TASK_HPAGE_END ASM_CONST(0x0000018000000000)
+#define HTLB_AREA_SHIFT 40
+#define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT)
+#define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT)
#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \
- (1U << GET_ESID(addr))) & 0xffff)
+#define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \
+ - (1U << GET_HTLB_AREA(addr))) & 0xffff)
#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
#define touches_hugepage_low_range(mm, addr, len) \
- (LOW_ESID_MASK((addr), (len)) & mm->context.htlb_segs)
-#define touches_hugepage_high_range(addr, len) \
- (((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END))
+ (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas)
+#define touches_hugepage_high_range(mm, addr, len) \
+ (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas)
#define __within_hugepage_low_range(addr, len, segmask) \
((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask))
#define within_hugepage_low_range(addr, len) \
__within_hugepage_low_range((addr), (len), \
- current->mm->context.htlb_segs)
-#define within_hugepage_high_range(addr, len) (((addr) >= TASK_HPAGE_BASE) \
- && ((addr)+(len) <= TASK_HPAGE_END) && ((addr)+(len) >= (addr)))
+ current->mm->context.low_htlb_areas)
+#define __within_hugepage_high_range(addr, len, zonemask) \
+ ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask))
+#define within_hugepage_high_range(addr, len) \
+ __within_hugepage_high_range((addr), (len), \
+ current->mm->context.high_htlb_areas)
#define is_hugepage_only_range(mm, addr, len) \
- (touches_hugepage_high_range((addr), (len)) || \
+ (touches_hugepage_high_range((mm), (addr), (len)) || \
touches_hugepage_low_range((mm), (addr), (len)))
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
#define in_hugepage_area(context, addr) \
(cpu_has_feature(CPU_FTR_16M_PAGE) && \
- ( (((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \
+ ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \
( ((addr) < 0x100000000L) && \
- ((1 << GET_ESID(addr)) & (context).htlb_segs) ) ) )
+ ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) )
#else /* !CONFIG_HUGETLB_PAGE */
@@ -125,55 +131,47 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag
* Entries in the pte table are 64b, while entries in the pgd & pmd are 32b.
*/
typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned int pmd; } pmd_t;
-typedef struct { unsigned int pgd; } pgd_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pud; } pud_t;
+typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte)
#define pmd_val(x) ((x).pmd)
+#define pud_val(x) ((x).pud)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
-#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 __pte(x) ((pte_t) { (x) })
+#define __pmd(x) ((pmd_t) { (x) })
+#define __pud(x) ((pud_t) { (x) })
+#define __pgd(x) ((pgd_t) { (x) })
+#define __pgprot(x) ((pgprot_t) { (x) })
#else
/*
* .. while these make it easier on the compiler
*/
typedef unsigned long pte_t;
-typedef unsigned int pmd_t;
-typedef unsigned int pgd_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pud_t;
+typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
#define pte_val(x) (x)
#define pmd_val(x) (x)
+#define pud_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
#define __pte(x) (x)
#define __pmd(x) (x)
+#define __pud(x) (x)
#define __pgd(x) (x)
#define __pgprot(x) (x)
#endif
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
extern int page_is_ram(unsigned long pfn);
@@ -208,9 +206,6 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
#define USER_REGION_ID (0UL)
#define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
-#define __bpn_to_ba(x) ((((unsigned long)(x)) << PAGE_SHIFT) + KERNELBASE)
-#define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
-
#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
#ifdef CONFIG_DISCONTIGMEM
@@ -261,4 +256,7 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
#endif /* __KERNEL__ */
+
+#include <asm-generic/page.h>
+
#endif /* _PPC64_PAGE_H */
diff --git a/include/asm-ppc64/param.h b/include/asm-ppc64/param.h
deleted file mode 100644
index 1fad38dcf707..000000000000
--- a/include/asm-ppc64/param.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _ASM_PPC64_PARAM_H
-#define _ASM_PPC64_PARAM_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifdef __KERNEL__
-# define HZ 1000 /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif /* _ASM_PPC64_PARAM_H */
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index c4f9023ea5ed..d8991389ab39 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -48,19 +48,52 @@ struct pci_controller {
unsigned long dma_window_size;
};
+/*
+ * PCI stuff, for nodes representing PCI devices, pointed to
+ * by device_node->data.
+ */
+struct pci_controller;
+struct iommu_table;
+
+struct pci_dn {
+ int busno; /* for pci devices */
+ int bussubno; /* for pci devices */
+ int devfn; /* for pci devices */
+ int eeh_mode; /* See eeh.h for possible EEH_MODEs */
+ int eeh_config_addr;
+ int eeh_capable; /* from firmware */
+ int eeh_check_count; /* # times driver ignored error */
+ int eeh_freeze_count; /* # times this device froze up. */
+ int eeh_is_bridge; /* device is pci-to-pci bridge */
+
+ int pci_ext_config_space; /* for pci devices */
+ struct pci_controller *phb; /* for pci devices */
+ struct iommu_table *iommu_table; /* for phb's or bridges */
+ struct pci_dev *pcidev; /* back-pointer to the pci device */
+ struct device_node *node; /* back-pointer to the device_node */
+ u32 config_space[16]; /* saved PCI config space */
+};
+
+/* Get the pointer to a device_node's pci_dn */
+#define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
+
struct device_node *fetch_dev_dn(struct pci_dev *dev);
-/* Get a device_node from a pci_dev. This code must be fast except in the case
- * where the sysdata is incorrect and needs to be fixed up (hopefully just once)
+/* Get a device_node from a pci_dev. This code must be fast except
+ * in the case where the sysdata is incorrect and needs to be fixed
+ * up (this will only happen once).
+ * In this case the sysdata will have been inherited from a PCI host
+ * bridge or a PCI-PCI bridge further up the tree, so it will point
+ * to a valid struct pci_dn, just not the one we want.
*/
static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
{
struct device_node *dn = dev->sysdata;
+ struct pci_dn *pdn = dn->data;
- if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
+ if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
return dn; /* fast path. sysdata is good */
- else
- return fetch_dev_dn(dev);
+ return fetch_dev_dn(dev);
}
static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
@@ -83,8 +116,13 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
struct device_node *busdn = bus->sysdata;
BUG_ON(busdn == NULL);
- return busdn->phb;
+ return PCI_DN(busdn)->phb;
}
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */
+
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
index 4d057452f59b..a88bbfc26967 100644
--- a/include/asm-ppc64/pci.h
+++ b/include/asm-ppc64/pci.h
@@ -138,6 +138,19 @@ extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+ struct resource *root = NULL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+
+ return root;
+}
+
extern int
unmap_bus_range(struct pci_bus *bus);
diff --git a/include/asm-ppc64/percpu.h b/include/asm-ppc64/percpu.h
deleted file mode 100644
index 60a659a4ce1f..000000000000
--- a/include/asm-ppc64/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARCH_PPC64_PERCPU__
-#define __ARCH_PPC64_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_PPC64_PERCPU__ */
diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
index 4fc4b739b380..26bc49c1108d 100644
--- a/include/asm-ppc64/pgalloc.h
+++ b/include/asm-ppc64/pgalloc.h
@@ -6,7 +6,12 @@
#include <linux/cpumask.h>
#include <linux/percpu.h>
-extern kmem_cache_t *zero_cache;
+extern kmem_cache_t *pgtable_cache[];
+
+#define PTE_CACHE_NUM 0
+#define PMD_CACHE_NUM 1
+#define PUD_CACHE_NUM 1
+#define PGD_CACHE_NUM 0
/*
* This program is free software; you can redistribute it and/or
@@ -15,30 +20,40 @@ extern kmem_cache_t *zero_cache;
* 2 of the License, or (at your option) any later version.
*/
-static inline pgd_t *
-pgd_alloc(struct mm_struct *mm)
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
- return kmem_cache_alloc(zero_cache, GFP_KERNEL);
+ return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
}
-static inline void
-pgd_free(pgd_t *pgd)
+static inline void pgd_free(pgd_t *pgd)
{
- kmem_cache_free(zero_cache, pgd);
+ kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
+}
+
+#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
+ GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pud_free(pud_t *pud)
+{
+ kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
}
#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
-static inline pmd_t *
-pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
+ return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
+ GFP_KERNEL|__GFP_REPEAT);
}
-static inline void
-pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
{
- kmem_cache_free(zero_cache, pmd);
+ kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
}
#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
@@ -47,44 +62,58 @@ pmd_free(pmd_t *pmd)
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
+ return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM],
+ GFP_KERNEL|__GFP_REPEAT);
}
static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
- if (pte)
- return virt_to_page(pte);
- return NULL;
+ return virt_to_page(pte_alloc_one_kernel(mm, address));
}
static inline void pte_free_kernel(pte_t *pte)
{
- kmem_cache_free(zero_cache, pte);
+ kmem_cache_free(pgtable_cache[PTE_CACHE_NUM], pte);
}
static inline void pte_free(struct page *ptepage)
{
- kmem_cache_free(zero_cache, page_address(ptepage));
+ pte_free_kernel(page_address(ptepage));
}
-struct pte_freelist_batch
+#define PGF_CACHENUM_MASK 0xf
+
+typedef struct pgtable_free {
+ unsigned long val;
+} pgtable_free_t;
+
+static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
+ unsigned long mask)
{
- struct rcu_head rcu;
- unsigned int index;
- struct page * pages[0];
-};
+ BUG_ON(cachenum > PGF_CACHENUM_MASK);
-#define PTE_FREELIST_SIZE ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) / \
- sizeof(struct page *))
+ return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
+}
-extern void pte_free_now(struct page *ptepage);
-extern void pte_free_submit(struct pte_freelist_batch *batch);
+static inline void pgtable_free(pgtable_free_t pgf)
+{
+ void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
+ int cachenum = pgf.val & PGF_CACHENUM_MASK;
-DECLARE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
+ kmem_cache_free(pgtable_cache[cachenum], p);
+}
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage);
-#define __pmd_free_tlb(tlb, pmd) __pte_free_tlb(tlb, virt_to_page(pmd))
+void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
+
+#define __pte_free_tlb(tlb, ptepage) \
+ pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
+ PTE_CACHE_NUM, PTE_TABLE_SIZE-1))
+#define __pmd_free_tlb(tlb, pmd) \
+ pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
+ PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
+#define __pud_free_tlb(tlb, pmd) \
+ pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
+ PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
#define check_pgt_cache() do { } while (0)
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 46cf61c2ff69..c83679c9d2b0 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -15,19 +15,24 @@
#include <asm/tlbflush.h>
#endif /* __ASSEMBLY__ */
-#include <asm-generic/pgtable-nopud.h>
-
/*
* Entries per page directory level. The PTE level must use a 64b record
* for each page table entry. The PMD and PGD level use a 32b record for
* each entry by assuming that each entry is page aligned.
*/
#define PTE_INDEX_SIZE 9
-#define PMD_INDEX_SIZE 10
-#define PGD_INDEX_SIZE 10
+#define PMD_INDEX_SIZE 7
+#define PUD_INDEX_SIZE 7
+#define PGD_INDEX_SIZE 9
+
+#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE)
+#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE)
+#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE)
+#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE)
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
/* PMD_SHIFT determines what a second-level page table entry can map */
@@ -35,8 +40,13 @@
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
+/* PUD_SHIFT determines what a third-level page table entry can map */
+#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
+#define PUD_SIZE (1UL << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
+#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE)
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
@@ -45,15 +55,23 @@
/*
* Size of EA range mapped by our pagetables.
*/
-#define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
- PGD_INDEX_SIZE + PAGE_SHIFT)
-#define EADDR_MASK ((1UL << EADDR_SIZE) - 1)
+#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
+ PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
+#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+
+#if TASK_SIZE_USER64 > PGTABLE_RANGE
+#error TASK_SIZE_USER64 exceeds pagetable range
+#endif
+
+#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#error TASK_SIZE_USER64 exceeds user VSID range
+#endif
/*
* Define the address range of the vmalloc VM area.
*/
#define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_SIZE (0x10000000000UL)
+#define VMALLOC_SIZE (0x80000000000UL)
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
/*
@@ -154,8 +172,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
#ifndef __ASSEMBLY__
int hash_huge_page(struct mm_struct *mm, unsigned long access,
unsigned long ea, unsigned long vsid, int local);
-
-void hugetlb_mm_free_pgd(struct mm_struct *mm);
#endif /* __ASSEMBLY__ */
#define HAVE_ARCH_UNMAPPED_AREA
@@ -163,7 +179,6 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm);
#else
#define hash_huge_page(mm,a,ea,vsid,local) -1
-#define hugetlb_mm_free_pgd(mm) do {} while (0)
#endif
@@ -197,39 +212,45 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
#define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT)))
#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pmd_set(pmdp, ptep) \
- (pmd_val(*(pmdp)) = __ba_to_bpn(ptep))
+#define pmd_set(pmdp, ptep) ({BUG_ON((u64)ptep < KERNELBASE); pmd_val(*(pmdp)) = (unsigned long)(ptep);})
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) == 0)
#define pmd_present(pmd) (pmd_val(pmd) != 0)
#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0)
-#define pmd_page_kernel(pmd) (__bpn_to_ba(pmd_val(pmd)))
+#define pmd_page_kernel(pmd) (pmd_val(pmd))
#define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd))
-#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp)))
+#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (unsigned long)(pmdp))
#define pud_none(pud) (!pud_val(pud))
-#define pud_bad(pud) ((pud_val(pud)) == 0UL)
-#define pud_present(pud) (pud_val(pud) != 0UL)
-#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
-#define pud_page(pud) (__bpn_to_ba(pud_val(pud)))
+#define pud_bad(pud) ((pud_val(pud)) == 0)
+#define pud_present(pud) (pud_val(pud) != 0)
+#define pud_clear(pudp) (pud_val(*(pudp)) = 0)
+#define pud_page(pud) (pud_val(pud))
+
+#define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
+#define pgd_none(pgd) (!pgd_val(pgd))
+#define pgd_bad(pgd) (pgd_val(pgd) == 0)
+#define pgd_present(pgd) (pgd_val(pgd) != 0)
+#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0)
+#define pgd_page(pgd) (pgd_val(pgd))
/*
* Find an entry in a page-table-directory. We combine the address region
* (the high order N bits) and the pgd portion of the address.
*/
/* to avoid overflow in free_pgtables we don't use PTRS_PER_PGD here */
-#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x7ff)
+#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x1ff)
#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
-/* Find an entry in the second-level page table.. */
+#define pud_offset(pgdp, addr) \
+ (((pud_t *) pgd_page(*(pgdp))) + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
+
#define pmd_offset(pudp,addr) \
- ((pmd_t *) pud_page(*(pudp)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
+ (((pmd_t *) pud_page(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
-/* Find an entry in the third-level page table.. */
#define pte_offset_kernel(dir,addr) \
- ((pte_t *) pmd_page_kernel(*(dir)) \
- + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+ (((pte_t *) pmd_page_kernel(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr))
#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr))
@@ -458,23 +479,20 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
#define pmd_ERROR(e) \
- printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pud_ERROR(e) \
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e))
#define pgd_ERROR(e) \
- printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
extern pgd_t swapper_pg_dir[];
extern void paging_init(void);
-/*
- * Because the huge pgtables are only 2 level, they can take
- * at most around 4M, much less than one hugepage which the
- * process is presumably entitled to use. So we don't bother
- * freeing up the pagetables on unmap, and wait until
- * destroy_context() to clean up the lot.
- */
+#ifdef CONFIG_HUGETLB_PAGE
#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
- do { } while (0)
+ free_pgd_range(tlb, addr, end, floor, ceiling)
+#endif
/*
* This gets called at the end of handling a page fault, when
diff --git a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h
index f4a5fb7d67c7..72dd2449ee76 100644
--- a/include/asm-ppc64/plpar_wrappers.h
+++ b/include/asm-ppc64/plpar_wrappers.h
@@ -107,5 +107,14 @@ static inline long plpar_put_term_char(unsigned long termno,
lbuf[1]);
}
+static inline long plpar_set_xdabr(unsigned long address, unsigned long flags)
+{
+ return plpar_hcall_norets(H_SET_XDABR, address, flags);
+}
+
+static inline long plpar_set_dabr(unsigned long val)
+{
+ return plpar_hcall_norets(H_SET_DABR, val);
+}
#endif /* _PPC64_PLPAR_WRAPPERS_H */
diff --git a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
index c924748c0bea..d1d297dbccfe 100644
--- a/include/asm-ppc64/pmc.h
+++ b/include/asm-ppc64/pmc.h
@@ -26,4 +26,6 @@ typedef void (*perf_irq_t)(struct pt_regs *);
int reserve_pmc_hardware(perf_irq_t new_perf_irq);
void release_pmc_hardware(void);
+void power4_enable_pmcs(void);
+
#endif /* _PPC64_PMC_H */
diff --git a/include/asm-ppc64/poll.h b/include/asm-ppc64/poll.h
deleted file mode 100644
index 370fa3ba0db4..000000000000
--- a/include/asm-ppc64/poll.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __PPC64_POLL_H
-#define __PPC64_POLL_H
-
-/*
- * Copyright (C) 2001 PPC64 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.
- */
-
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* __PPC64_POLL_H */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index 352306cfb579..4146189006e3 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -268,6 +268,7 @@
#define PV_970FX 0x003C
#define PV_630 0x0040
#define PV_630p 0x0041
+#define PV_970MP 0x0044
#define PV_BE 0x0070
/* Platforms supported by PPC64 */
@@ -310,6 +311,20 @@ name: \
.type GLUE(.,name),@function; \
GLUE(.,name):
+#define _KPROBE(name) \
+ .section ".kprobes.text","a"; \
+ .align 2 ; \
+ .globl name; \
+ .globl GLUE(.,name); \
+ .section ".opd","aw"; \
+name: \
+ .quad GLUE(.,name); \
+ .quad .TOC.@tocbase; \
+ .quad 0; \
+ .previous; \
+ .type GLUE(.,name),@function; \
+GLUE(.,name):
+
#define _STATIC(name) \
.section ".text"; \
.align 2 ; \
@@ -382,8 +397,8 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
extern struct task_struct *last_task_used_math;
extern struct task_struct *last_task_used_altivec;
-/* 64-bit user address space is 41-bits (2TBs user VM) */
-#define TASK_SIZE_USER64 (0x0000020000000000UL)
+/* 64-bit user address space is 44-bits (16TB user VM) */
+#define TASK_SIZE_USER64 (0x0000100000000000UL)
/*
* 32-bit user address space is 4GB - 1 page
@@ -418,6 +433,7 @@ struct thread_struct {
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
unsigned long vdso_base; /* base of the vDSO library */
+ unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
vector128 vr[32] __attribute((aligned(16)));
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
index 04b1a84f7ca3..c02ec1d6b909 100644
--- a/include/asm-ppc64/prom.h
+++ b/include/asm-ppc64/prom.h
@@ -22,13 +22,15 @@
#define RELOC(x) (*PTRRELOC(&(x)))
/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */
-#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */
+#define OF_DT_HEADER 0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
#define OF_DT_END_NODE 0x2 /* End node */
-#define OF_DT_PROP 0x3 /* Property: name off, size, content */
+#define OF_DT_PROP 0x3 /* Property: name off, size,
+ * content */
+#define OF_DT_NOP 0x4 /* nop */
#define OF_DT_END 0x9
-#define OF_DT_VERSION 1
+#define OF_DT_VERSION 0x10
/*
* This is what gets passed to the kernel by prom_init or kexec
@@ -54,7 +56,9 @@ struct boot_param_header
u32 version; /* format version */
u32 last_comp_version; /* last compatible version */
/* version 2 fields below */
- u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */
+ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
+ /* version 3 fields below */
+ u32 dt_strings_size; /* size of the DT strings block */
};
@@ -112,14 +116,6 @@ struct property {
struct property *next;
};
-/* NOTE: the device_node contains PCI specific info for pci devices.
- * This perhaps could be hung off the device_node with another struct,
- * but for now it is directly in the node. The phb ptr is a good
- * indication of a real PCI node. Other nodes leave these fields zeroed.
- */
-struct pci_controller;
-struct iommu_table;
-
struct device_node {
char *name;
char *type;
@@ -131,16 +127,6 @@ struct device_node {
struct interrupt_info *intrs;
char *full_name;
- /* PCI stuff probably doesn't belong here */
- int busno; /* for pci devices */
- int bussubno; /* for pci devices */
- int devfn; /* for pci devices */
- int eeh_mode; /* See eeh.h for possible EEH_MODEs */
- int eeh_config_addr;
- int pci_ext_config_space; /* for pci devices */
- struct pci_controller *phb; /* for pci devices */
- struct iommu_table *iommu_table; /* for phb's or bridges */
-
struct property *properties;
struct device_node *parent;
struct device_node *child;
@@ -150,6 +136,7 @@ struct device_node {
struct proc_dir_entry *pde; /* this node's proc directory */
struct kref kref;
unsigned long _flags;
+ void *data;
};
extern struct device_node *of_chosen;
diff --git a/include/asm-ppc64/ptrace-common.h b/include/asm-ppc64/ptrace-common.h
index af03547f9c7e..b1babb729673 100644
--- a/include/asm-ppc64/ptrace-common.h
+++ b/include/asm-ppc64/ptrace-common.h
@@ -11,6 +11,10 @@
#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H
+
+#include <linux/config.h>
+#include <asm/system.h>
+
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
@@ -69,4 +73,92 @@ static inline void clear_single_step(struct task_struct *task)
clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
}
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword. Quadwords 0-31 contain the
+ * corresponding vector registers. Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword. Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface. This allows signal handling and ptrace to use the
+ * same structures. This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long __user *data,
+ struct task_struct *task)
+{
+ unsigned long regsize;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ regsize = 32 * sizeof(vector128);
+ if (copy_to_user(data, task->thread.vr, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
+
+ /* copy VSCR */
+ regsize = 1 * sizeof(vector128);
+ if (copy_to_user(data, &task->thread.vscr, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
+
+ /* copy VRSAVE */
+ if (put_user(task->thread.vrsave, (u32 __user *)data))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task,
+ unsigned long __user *data)
+{
+ unsigned long regsize;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ regsize = 32 * sizeof(vector128);
+ if (copy_from_user(task->thread.vr, data, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
+
+ /* copy VSCR */
+ regsize = 1 * sizeof(vector128);
+ if (copy_from_user(&task->thread.vscr, data, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
+
+ /* copy VRSAVE */
+ if (get_user(task->thread.vrsave, (u32 __user *)data))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
+static inline int ptrace_set_debugreg(struct task_struct *task,
+ unsigned long addr, unsigned long data)
+{
+ /* We only support one DABR and no IABRS at the moment */
+ if (addr > 0)
+ return -EINVAL;
+
+ /* The bottom 3 bits are flags */
+ if ((data & ~0x7UL) >= TASK_SIZE)
+ return -EIO;
+
+ /* Ensure translation is on */
+ if (data && !(data & DABR_TRANSLATION))
+ return -EIO;
+
+ task->thread.dabr = data;
+ return 0;
+}
+
#endif /* _PPC64_PTRACE_COMMON_H */
diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h
index c96aad28fc08..3a55377f1fd3 100644
--- a/include/asm-ppc64/ptrace.h
+++ b/include/asm-ppc64/ptrace.h
@@ -25,56 +25,49 @@
*/
#ifndef __ASSEMBLY__
-#define PPC_REG unsigned long
+
struct pt_regs {
- PPC_REG gpr[32];
- PPC_REG nip;
- PPC_REG msr;
- PPC_REG orig_gpr3; /* Used for restarting system calls */
- PPC_REG ctr;
- PPC_REG link;
- PPC_REG xer;
- PPC_REG ccr;
- PPC_REG softe; /* Soft enabled/disabled */
- PPC_REG trap; /* Reason for being here */
- PPC_REG dar; /* Fault registers */
- PPC_REG dsisr;
- PPC_REG result; /* Result of a system call */
+ unsigned long gpr[32];
+ unsigned long nip;
+ unsigned long msr;
+ unsigned long orig_gpr3; /* Used for restarting system calls */
+ unsigned long ctr;
+ unsigned long link;
+ unsigned long xer;
+ unsigned long ccr;
+ unsigned long softe; /* Soft enabled/disabled */
+ unsigned long trap; /* Reason for being here */
+ unsigned long dar; /* Fault registers */
+ unsigned long dsisr;
+ unsigned long result; /* Result of a system call */
};
-#define PPC_REG_32 unsigned int
struct pt_regs32 {
- PPC_REG_32 gpr[32];
- PPC_REG_32 nip;
- PPC_REG_32 msr;
- PPC_REG_32 orig_gpr3; /* Used for restarting system calls */
- PPC_REG_32 ctr;
- PPC_REG_32 link;
- PPC_REG_32 xer;
- PPC_REG_32 ccr;
- PPC_REG_32 mq; /* 601 only (not used at present) */
- /* Used on APUS to hold IPL value. */
- PPC_REG_32 trap; /* Reason for being here */
- PPC_REG_32 dar; /* Fault registers */
- PPC_REG_32 dsisr;
- PPC_REG_32 result; /* Result of a system call */
+ unsigned int gpr[32];
+ unsigned int nip;
+ unsigned int msr;
+ unsigned int orig_gpr3; /* Used for restarting system calls */
+ unsigned int ctr;
+ unsigned int link;
+ unsigned int xer;
+ unsigned int ccr;
+ unsigned int mq; /* 601 only (not used at present) */
+ unsigned int trap; /* Reason for being here */
+ unsigned int dar; /* Fault registers */
+ unsigned int dsisr;
+ unsigned int result; /* Result of a system call */
};
+#ifdef __KERNEL__
+
#define instruction_pointer(regs) ((regs)->nip)
+
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *regs);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif
-#endif /* __ASSEMBLY__ */
-
-#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
-
-/* Size of dummy stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE 128
-#define __SIGNAL_FRAMESIZE32 64
-
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#define force_successful_syscall_return() \
@@ -89,6 +82,16 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define TRAP(regs) ((regs)->trap & ~0xF)
#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1)
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
+
+/* Size of dummy stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE 128
+#define __SIGNAL_FRAMESIZE32 64
+
/*
* Offsets used by 'ptrace' system call interface.
*/
@@ -135,17 +138,21 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define PT_XER 37
#define PT_CCR 38
#define PT_SOFTE 39
+#define PT_TRAP 40
+#define PT_DAR 41
+#define PT_DSISR 42
#define PT_RESULT 43
#define PT_FPR0 48
-/* Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have
- * visibility to the asm-ppc/ptrace.h header instead of this one.
+/*
+ * Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will
+ * have visibility to the asm-ppc/ptrace.h header instead of this one.
*/
-#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */
+#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */
#ifdef __KERNEL__
-#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */
+#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */
#endif
#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */
@@ -173,17 +180,34 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define PTRACE_GETVRREGS 18
#define PTRACE_SETVRREGS 19
-/* Additional PTRACE requests implemented on PowerPC. */
-#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */
-#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */
-#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */
-#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */
-#define PPC_PTRACE_PEEKTEXT_3264 0x95 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKDATA_3264 0x94 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKETEXT_3264 0x93 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEDATA_3264 0x92 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKUSR_3264 0x91 /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEUSR_3264 0x90 /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */
+/*
+ * While we dont have 64bit book E processors, we need to reserve the
+ * relevant ptrace calls for 32bit compatibility.
+ */
+#if 0
+#define PTRACE_GETEVRREGS 20
+#define PTRACE_SETEVRREGS 21
+#endif
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG 25
+#define PTRACE_SET_DEBUGREG 26
+
+/* Additional PTRACE requests implemented on PowerPC. */
+#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */
+#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */
+#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */
+#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */
+
+/* Calls to trace a 64bit program from a 32bit program */
+#define PPC_PTRACE_PEEKTEXT_3264 0x95
+#define PPC_PTRACE_PEEKDATA_3264 0x94
+#define PPC_PTRACE_POKETEXT_3264 0x93
+#define PPC_PTRACE_POKEDATA_3264 0x92
+#define PPC_PTRACE_PEEKUSR_3264 0x91
+#define PPC_PTRACE_POKEUSR_3264 0x90
#endif /* _PPC64_PTRACE_H */
diff --git a/include/asm-ppc64/resource.h b/include/asm-ppc64/resource.h
deleted file mode 100644
index add031b9dfd4..000000000000
--- a/include/asm-ppc64/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PPC64_RESOURCE_H
-#define _PPC64_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif /* _PPC64_RESOURCE_H */
diff --git a/include/asm-ppc64/segment.h b/include/asm-ppc64/segment.h
deleted file mode 100644
index d80fb68cc79e..000000000000
--- a/include/asm-ppc64/segment.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PPC64_SEGMENT_H
-#define __PPC64_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif /* __PPC64_SEGMENT_H */
diff --git a/include/asm-ppc64/setup.h b/include/asm-ppc64/setup.h
deleted file mode 100644
index b257b8348c73..000000000000
--- a/include/asm-ppc64/setup.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PPC_SETUP_H
-#define _PPC_SETUP_H
-
-#define COMMAND_LINE_SIZE 512
-
-#endif /* _PPC_SETUP_H */
diff --git a/include/asm-ppc64/shmparam.h b/include/asm-ppc64/shmparam.h
deleted file mode 100644
index b2825ceff05e..000000000000
--- a/include/asm-ppc64/shmparam.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _PPC64_SHMPARAM_H
-#define _PPC64_SHMPARAM_H
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _PPC64_SHMPARAM_H */
diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
index acd11564dd75..14cb895bb607 100644
--- a/include/asm-ppc64/spinlock.h
+++ b/include/asm-ppc64/spinlock.h
@@ -15,36 +15,42 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
*/
#include <linux/config.h>
#include <asm/paca.h>
#include <asm/hvcall.h>
#include <asm/iSeries/HvCall.h>
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
+#define __raw_spin_is_locked(x) ((x)->slock != 0)
-typedef struct {
- volatile signed int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
+/*
+ * This returns the old value in the lock, so we succeeded
+ * in getting the lock if the return value is 0.
+ */
+static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock)
+{
+ unsigned long tmp, tmp2;
-#ifdef __KERNEL__
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+ __asm__ __volatile__(
+" lwz %1,%3(13) # __spin_trylock\n\
+1: lwarx %0,0,%2\n\
+ cmpwi 0,%0,0\n\
+ bne- 2f\n\
+ stwcx. %1,0,%2\n\
+ bne- 1b\n\
+ isync\n\
+2:" : "=&r" (tmp), "=&r" (tmp2)
+ : "r" (&lock->slock), "i" (offsetof(struct paca_struct, lock_token))
+ : "cr0", "memory");
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+ return tmp;
+}
-static __inline__ void _raw_spin_unlock(spinlock_t *lock)
+static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock)
{
- __asm__ __volatile__("lwsync # spin_unlock": : :"memory");
- lock->lock = 0;
+ return __spin_trylock(lock) == 0;
}
/*
@@ -64,44 +70,15 @@ static __inline__ void _raw_spin_unlock(spinlock_t *lock)
#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
/* We only yield to the hypervisor if we are in shared processor mode */
#define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc)
-extern void __spin_yield(spinlock_t *lock);
-extern void __rw_yield(rwlock_t *lock);
+extern void __spin_yield(raw_spinlock_t *lock);
+extern void __rw_yield(raw_rwlock_t *lock);
#else /* SPLPAR || ISERIES */
#define __spin_yield(x) barrier()
#define __rw_yield(x) barrier()
#define SHARED_PROCESSOR 0
#endif
-extern void spin_unlock_wait(spinlock_t *lock);
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
-{
- unsigned long tmp, tmp2;
-
- __asm__ __volatile__(
-" lwz %1,%3(13) # __spin_trylock\n\
-1: lwarx %0,0,%2\n\
- cmpwi 0,%0,0\n\
- bne- 2f\n\
- stwcx. %1,0,%2\n\
- bne- 1b\n\
- isync\n\
-2:" : "=&r" (tmp), "=&r" (tmp2)
- : "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
- : "cr0", "memory");
-
- return tmp;
-}
-
-static int __inline__ _raw_spin_trylock(spinlock_t *lock)
-{
- return __spin_trylock(lock) == 0;
-}
-static void __inline__ _raw_spin_lock(spinlock_t *lock)
+static void __inline__ __raw_spin_lock(raw_spinlock_t *lock)
{
while (1) {
if (likely(__spin_trylock(lock) == 0))
@@ -110,12 +87,12 @@ static void __inline__ _raw_spin_lock(spinlock_t *lock)
HMT_low();
if (SHARED_PROCESSOR)
__spin_yield(lock);
- } while (unlikely(lock->lock != 0));
+ } while (unlikely(lock->slock != 0));
HMT_medium();
}
}
-static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
{
unsigned long flags_dis;
@@ -128,12 +105,20 @@ static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flag
HMT_low();
if (SHARED_PROCESSOR)
__spin_yield(lock);
- } while (unlikely(lock->lock != 0));
+ } while (unlikely(lock->slock != 0));
HMT_medium();
local_irq_restore(flags_dis);
}
}
+static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+ __asm__ __volatile__("lwsync # __raw_spin_unlock": : :"memory");
+ lock->slock = 0;
+}
+
+extern void __raw_spin_unlock_wait(raw_spinlock_t *lock);
+
/*
* Read-write spinlocks, allowing multiple readers
* but only one writer.
@@ -144,24 +129,15 @@ static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flag
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-#define read_can_lock(rw) ((rw)->lock >= 0)
-#define write_can_lock(rw) (!(rw)->lock)
-
-static __inline__ void _raw_write_unlock(rwlock_t *rw)
-{
- __asm__ __volatile__("lwsync # write_unlock": : :"memory");
- rw->lock = 0;
-}
+#define __raw_read_can_lock(rw) ((rw)->lock >= 0)
+#define __raw_write_can_lock(rw) (!(rw)->lock)
/*
* This returns the old value in the lock + 1,
* so we got a read lock if the return value is > 0.
*/
-static long __inline__ __read_trylock(rwlock_t *rw)
+static long __inline__ __read_trylock(raw_rwlock_t *rw)
{
long tmp;
@@ -180,45 +156,11 @@ static long __inline__ __read_trylock(rwlock_t *rw)
return tmp;
}
-static int __inline__ _raw_read_trylock(rwlock_t *rw)
-{
- return __read_trylock(rw) > 0;
-}
-
-static void __inline__ _raw_read_lock(rwlock_t *rw)
-{
- while (1) {
- if (likely(__read_trylock(rw) > 0))
- break;
- do {
- HMT_low();
- if (SHARED_PROCESSOR)
- __rw_yield(rw);
- } while (unlikely(rw->lock < 0));
- HMT_medium();
- }
-}
-
-static void __inline__ _raw_read_unlock(rwlock_t *rw)
-{
- long tmp;
-
- __asm__ __volatile__(
- "eieio # read_unlock\n\
-1: lwarx %0,0,%1\n\
- addic %0,%0,-1\n\
- stwcx. %0,0,%1\n\
- bne- 1b"
- : "=&r"(tmp)
- : "r"(&rw->lock)
- : "cr0", "memory");
-}
-
/*
* This returns the old value in the lock,
* so we got the write lock if the return value is 0.
*/
-static __inline__ long __write_trylock(rwlock_t *rw)
+static __inline__ long __write_trylock(raw_rwlock_t *rw)
{
long tmp, tmp2;
@@ -237,12 +179,21 @@ static __inline__ long __write_trylock(rwlock_t *rw)
return tmp;
}
-static int __inline__ _raw_write_trylock(rwlock_t *rw)
+static void __inline__ __raw_read_lock(raw_rwlock_t *rw)
{
- return __write_trylock(rw) == 0;
+ while (1) {
+ if (likely(__read_trylock(rw) > 0))
+ break;
+ do {
+ HMT_low();
+ if (SHARED_PROCESSOR)
+ __rw_yield(rw);
+ } while (unlikely(rw->lock < 0));
+ HMT_medium();
+ }
}
-static void __inline__ _raw_write_lock(rwlock_t *rw)
+static void __inline__ __raw_write_lock(raw_rwlock_t *rw)
{
while (1) {
if (likely(__write_trylock(rw) == 0))
@@ -256,5 +207,35 @@ static void __inline__ _raw_write_lock(rwlock_t *rw)
}
}
-#endif /* __KERNEL__ */
+static int __inline__ __raw_read_trylock(raw_rwlock_t *rw)
+{
+ return __read_trylock(rw) > 0;
+}
+
+static int __inline__ __raw_write_trylock(raw_rwlock_t *rw)
+{
+ return __write_trylock(rw) == 0;
+}
+
+static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
+{
+ long tmp;
+
+ __asm__ __volatile__(
+ "eieio # read_unlock\n\
+1: lwarx %0,0,%1\n\
+ addic %0,%0,-1\n\
+ stwcx. %0,0,%1\n\
+ bne- 1b"
+ : "=&r"(tmp)
+ : "r"(&rw->lock)
+ : "cr0", "memory");
+}
+
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
+{
+ __asm__ __volatile__("lwsync # write_unlock": : :"memory");
+ rw->lock = 0;
+}
+
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-ppc64/spinlock_types.h b/include/asm-ppc64/spinlock_types.h
new file mode 100644
index 000000000000..a37c8eabb9f2
--- /dev/null
+++ b/include/asm-ppc64/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile signed int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-ppc64/string.h b/include/asm-ppc64/string.h
deleted file mode 100644
index eeca68ef1e91..000000000000
--- a/include/asm-ppc64/string.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _PPC64_STRING_H_
-#define _PPC64_STRING_H_
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define __HAVE_ARCH_STRCPY
-#define __HAVE_ARCH_STRNCPY
-#define __HAVE_ARCH_STRLEN
-#define __HAVE_ARCH_STRCMP
-#define __HAVE_ARCH_STRCAT
-#define __HAVE_ARCH_MEMSET
-#define __HAVE_ARCH_MEMCPY
-#define __HAVE_ARCH_MEMMOVE
-#define __HAVE_ARCH_MEMCMP
-#define __HAVE_ARCH_MEMCHR
-
-extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, int);
-extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
-extern __kernel_size_t strlen(const char *);
-extern int strcmp(const char *,const char *);
-extern char * strcat(char *, const char *);
-extern void * memset(void *,int,__kernel_size_t);
-extern void * memcpy(void *,const void *,__kernel_size_t);
-extern void * memmove(void *,const void *,__kernel_size_t);
-extern int memcmp(const void *,const void *,__kernel_size_t);
-extern void * memchr(const void *,int,__kernel_size_t);
-
-#endif /* _PPC64_STRING_H_ */
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
index 98d120ca8a91..375015c62f20 100644
--- a/include/asm-ppc64/system.h
+++ b/include/asm-ppc64/system.h
@@ -88,7 +88,7 @@ DEBUGGER_BOILERPLATE(debugger_dabr_match)
DEBUGGER_BOILERPLATE(debugger_fault_handler)
#ifdef CONFIG_XMON
-extern void xmon_init(void);
+extern void xmon_init(int enable);
#endif
#else
@@ -101,6 +101,9 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
#endif
+extern int set_dabr(unsigned long dabr);
+extern void _exception(int signr, struct pt_regs *regs, int code,
+ unsigned long addr);
extern int fix_alignment(struct pt_regs *regs);
extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
int sig);
@@ -158,7 +161,7 @@ static inline int __is_processor(unsigned long pv)
* is more like most of the other architectures.
*/
static __inline__ unsigned long
-__xchg_u32(volatile int *m, unsigned long val)
+__xchg_u32(volatile unsigned int *m, unsigned long val)
{
unsigned long dummy;
@@ -200,7 +203,7 @@ __xchg_u64(volatile long *m, unsigned long val)
extern void __xchg_called_with_bad_pointer(void);
static __inline__ unsigned long
-__xchg(volatile void *ptr, unsigned long x, int size)
+__xchg(volatile void *ptr, unsigned long x, unsigned int size)
{
switch (size) {
case 4:
@@ -223,7 +226,7 @@ __xchg(volatile void *ptr, unsigned long x, int size)
#define __HAVE_ARCH_CMPXCHG 1
static __inline__ unsigned long
-__cmpxchg_u32(volatile int *p, int old, int new)
+__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
{
unsigned int prev;
@@ -271,7 +274,8 @@ __cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new)
extern void __cmpxchg_called_with_bad_pointer(void);
static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+ unsigned int size)
{
switch (size) {
case 4:
@@ -283,13 +287,9 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
return old;
}
-#define cmpxchg(ptr,o,n) \
- ({ \
- __typeof__(*(ptr)) _o_ = (o); \
- __typeof__(*(ptr)) _n_ = (n); \
- (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
- (unsigned long)_n_, sizeof(*(ptr))); \
- })
+#define cmpxchg(ptr,o,n)\
+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+ (unsigned long)(n),sizeof(*(ptr))))
/*
* We handle most unaligned accesses in hardware. On the other hand
@@ -302,5 +302,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#define arch_align_stack(x) (x)
+extern unsigned long reloc_offset(void);
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-ppc64/timex.h b/include/asm-ppc64/timex.h
deleted file mode 100644
index 8db4da4064cd..000000000000
--- a/include/asm-ppc64/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/include/asm-ppc/timex.h
- *
- * PPC64 architecture timex specifications
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 _ASMPPC64_TIMEX_H
-#define _ASMPPC64_TIMEX_H
-
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
-typedef unsigned long cycles_t;
-
-static inline cycles_t get_cycles(void)
-{
- cycles_t ret;
-
- __asm__ __volatile__("mftb %0" : "=r" (ret) : );
- return ret;
-}
-
-#endif
diff --git a/include/asm-ppc64/types.h b/include/asm-ppc64/types.h
index 5b8c2cfa1138..bf294c1761b2 100644
--- a/include/asm-ppc64/types.h
+++ b/include/asm-ppc64/types.h
@@ -72,7 +72,6 @@ typedef struct {
unsigned long env;
} func_descr_t;
-typedef unsigned int kmem_bufctl_t;
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h
index 05b5943ab1ee..c181a60d868c 100644
--- a/include/asm-ppc64/uaccess.h
+++ b/include/asm-ppc64/uaccess.h
@@ -56,13 +56,6 @@
#define access_ok(type,addr,size) \
__access_ok(((__force unsigned long)(addr)),(size),get_fs())
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h
index a6e04d014b2b..c786604aef02 100644
--- a/include/asm-ppc64/udbg.h
+++ b/include/asm-ppc64/udbg.h
@@ -2,6 +2,7 @@
#define __UDBG_HDR
#include <linux/compiler.h>
+#include <linux/init.h>
/*
* c 2001 PPC 64 Team, IBM Corp
@@ -12,17 +13,19 @@
* 2 of the License, or (at your option) any later version.
*/
-void udbg_init_uart(void __iomem *comport, unsigned int speed);
-void udbg_putc(unsigned char c);
-unsigned char udbg_getc(void);
-int udbg_getc_poll(void);
-void udbg_puts(const char *s);
-int udbg_write(const char *s, int n);
-int udbg_read(char *buf, int buflen);
-struct console;
-void udbg_console_write(struct console *con, const char *s, unsigned int n);
-void udbg_printf(const char *fmt, ...);
-void udbg_ppcdbg(unsigned long flags, const char *fmt, ...);
-unsigned long udbg_ifdebug(unsigned long flags);
+extern void (*udbg_putc)(unsigned char c);
+extern unsigned char (*udbg_getc)(void);
+extern int (*udbg_getc_poll)(void);
+extern void udbg_puts(const char *s);
+extern int udbg_write(const char *s, int n);
+extern int udbg_read(char *buf, int buflen);
+
+extern void register_early_udbg_console(void);
+extern void udbg_printf(const char *fmt, ...);
+extern void udbg_ppcdbg(unsigned long flags, const char *fmt, ...);
+extern unsigned long udbg_ifdebug(unsigned long flags);
+extern void __init ppcdbg_initialize(void);
+
+extern void udbg_init_uart(void __iomem *comport, unsigned int speed);
#endif
diff --git a/include/asm-ppc64/unaligned.h b/include/asm-ppc64/unaligned.h
deleted file mode 100644
index 636e93c4f379..000000000000
--- a/include/asm-ppc64/unaligned.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __PPC64_UNALIGNED_H
-#define __PPC64_UNALIGNED_H
-
-/*
- * The PowerPC can do unaligned accesses itself in big endian mode.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define get_unaligned(ptr) (*(ptr))
-
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-
-#endif /* __PPC64_UNALIGNED_H */
diff --git a/include/asm-ppc64/user.h b/include/asm-ppc64/user.h
deleted file mode 100644
index d7d6554a421f..000000000000
--- a/include/asm-ppc64/user.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _PPC_USER_H
-#define _PPC_USER_H
-
-/* Adapted from <asm-alpha/user.h>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/ptrace.h>
-#include <asm/page.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core). The file contents
- * are as follows:
- *
- * upage: 1 page consisting of a user struct that tells gdb
- * what is present in the file. Directly after this is a
- * copy of the task_struct, which is currently not used by gdb,
- * but it may come in handy at some point. All of the registers
- * are stored as part of the upage. The upage should always be
- * only one page long.
- * data: The data segment follows next. We use current->end_text to
- * current->brk to pick up all of the user variables, plus any memory
- * that may have been sbrk'ed. No attempt is made to determine if a
- * page is demand-zero or if a page is totally unused, we just cover
- * the entire range. All of the addresses are rounded in such a way
- * that an integral number of pages is written.
- * stack: We need the stack information in order to get a meaningful
- * backtrace. We need to write the data from usp to
- * current->start_stack, so we round each of these in order to be able
- * to write an integer number of pages.
- */
-struct user {
- struct pt_regs regs; /* entire machine state */
- size_t u_tsize; /* text size (pages) */
- size_t u_dsize; /* data size (pages) */
- size_t u_ssize; /* stack size (pages) */
- unsigned long start_code; /* text starting address */
- unsigned long start_data; /* data starting address */
- unsigned long start_stack; /* stack starting address */
- long int signal; /* signal causing core dump */
- struct regs * u_ar0; /* help gdb find registers */
- unsigned long magic; /* identifies a core file */
- char u_comm[32]; /* user command name */
-};
-
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_DATA_START_ADDR (u.start_data)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _PPC_USER_H */
diff --git a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h
index 20cd98ee6337..03f1b95f433b 100644
--- a/include/asm-ppc64/vio.h
+++ b/include/asm-ppc64/vio.h
@@ -19,13 +19,15 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/mod_devicetable.h>
+
#include <asm/hvcall.h>
-#include <asm/prom.h>
#include <asm/scatterlist.h>
-/*
+
+/*
* Architecture-specific constants for drivers to
* extract attributes of the device using vio_get_attribute()
-*/
+ */
#define VETH_MAC_ADDR "local-mac-address"
#define VETH_MCAST_FILTER_SIZE "ibm,mac-address-filters"
@@ -37,64 +39,65 @@
#define VIO_IRQ_DISABLE 0UL
#define VIO_IRQ_ENABLE 1UL
-struct vio_dev;
-struct vio_driver;
-struct vio_device_id;
struct iommu_table;
-int vio_register_driver(struct vio_driver *drv);
-void vio_unregister_driver(struct vio_driver *drv);
-
-#ifdef CONFIG_PPC_PSERIES
-struct vio_dev * __devinit vio_register_device_node(
- struct device_node *node_vdev);
-#endif
-void __devinit vio_unregister_device(struct vio_dev *dev);
-struct vio_dev *vio_find_node(struct device_node *vnode);
-
-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length);
-int vio_get_irq(struct vio_dev *dev);
-int vio_enable_interrupts(struct vio_dev *dev);
-int vio_disable_interrupts(struct vio_dev *dev);
-
-extern struct dma_mapping_ops vio_dma_ops;
-
-extern struct bus_type vio_bus_type;
-
-struct vio_device_id {
+/*
+ * The vio_dev structure is used to describe virtual I/O devices.
+ */
+struct vio_dev {
+ struct iommu_table *iommu_table; /* vio_map_* uses this */
+ char *name;
char *type;
- char *compat;
+ uint32_t unit_address;
+ unsigned int irq;
+ struct device dev;
};
struct vio_driver {
struct list_head node;
char *name;
- const struct vio_device_id *id_table; /* NULL if wants all devices */
- int (*probe) (struct vio_dev *dev, const struct vio_device_id *id); /* New device inserted */
- int (*remove) (struct vio_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
+ const struct vio_device_id *id_table;
+ int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+ int (*remove)(struct vio_dev *dev);
unsigned long driver_data;
-
struct device_driver driver;
};
+struct vio_bus_ops {
+ int (*match)(const struct vio_device_id *id, const struct vio_dev *dev);
+ void (*unregister_device)(struct vio_dev *);
+ void (*release_device)(struct device *);
+};
+
+extern struct dma_mapping_ops vio_dma_ops;
+extern struct bus_type vio_bus_type;
+extern struct vio_dev vio_bus_device;
+
+extern int vio_register_driver(struct vio_driver *drv);
+extern void vio_unregister_driver(struct vio_driver *drv);
+
+extern struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev);
+extern void __devinit vio_unregister_device(struct vio_dev *dev);
+
+extern int vio_bus_init(struct vio_bus_ops *);
+
+#ifdef CONFIG_PPC_PSERIES
+struct device_node;
+
+extern struct vio_dev * __devinit vio_register_device_node(
+ struct device_node *node_vdev);
+extern struct vio_dev *vio_find_node(struct device_node *vnode);
+extern const void *vio_get_attribute(struct vio_dev *vdev, void *which,
+ int *length);
+extern int vio_enable_interrupts(struct vio_dev *dev);
+extern int vio_disable_interrupts(struct vio_dev *dev);
+#endif
+
static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
{
return container_of(drv, struct vio_driver, driver);
}
-/*
- * The vio_dev structure is used to describe virtual I/O devices.
- */
-struct vio_dev {
- struct iommu_table *iommu_table; /* vio_map_* uses this */
- char *name;
- char *type;
- uint32_t unit_address;
- unsigned int irq;
-
- struct device dev;
-};
-
static inline struct vio_dev *to_vio_dev(struct device *dev)
{
return container_of(dev, struct vio_dev, dev);
diff --git a/include/asm-ppc64/xor.h b/include/asm-ppc64/xor.h
deleted file mode 100644
index c82eb12a5b18..000000000000
--- a/include/asm-ppc64/xor.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
diff --git a/include/asm-s390/auxvec.h b/include/asm-s390/auxvec.h
new file mode 100644
index 000000000000..0d340720fd99
--- /dev/null
+++ b/include/asm-s390/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMS390_AUXVEC_H
+#define __ASMS390_AUXVEC_H
+
+#endif
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index 7f8f544eb262..a007715f4aea 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -13,10 +13,10 @@ typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
-typedef u16 compat_uid_t;
-typedef u16 compat_gid_t;
-typedef u32 compat_uid32_t;
-typedef u32 compat_gid32_t;
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u16 compat_dev_t;
@@ -51,8 +51,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
compat_dev_t st_rdev;
u16 __pad2;
u32 st_size;
@@ -140,10 +140,10 @@ static inline void __user *compat_alloc_user_space(long len)
struct compat_ipc64_perm {
compat_key_t key;
- compat_uid32_t uid;
- compat_gid32_t gid;
- compat_uid32_t cuid;
- compat_gid32_t cgid;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
compat_mode_t mode;
unsigned short __pad1;
unsigned short seq;
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index 92360d90144b..7127030ae162 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -52,8 +52,6 @@ struct __debug_entry{
#define DEBUG_DATA(entry) (char*)(entry + 1) /* data is stored behind */
/* the entry information */
-#define STCK(x) asm volatile ("STCK 0(%1)" : "=m" (x) : "a" (&(x)) : "cc")
-
typedef struct __debug_entry debug_entry_t;
struct debug_view;
diff --git a/include/asm-s390/fcntl.h b/include/asm-s390/fcntl.h
index 48f692b45732..46ab12db5739 100644
--- a/include/asm-s390/fcntl.h
+++ b/include/asm-s390/fcntl.h
@@ -1,97 +1 @@
-/*
- * include/asm-s390/fcntl.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/fcntl.h"
- */
-#ifndef _S390_FCNTL_H
-#define _S390_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#ifndef __s390x__
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-#endif /* ! __s390x__ */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-#ifndef __s390x__
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-#endif
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-s390/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index afe6a9f9b0ae..c6f51c9ce3ff 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -68,6 +68,7 @@
#define __LC_SYSTEM_TIMER 0x270
#define __LC_LAST_UPDATE_CLOCK 0x278
#define __LC_STEAL_CLOCK 0x280
+#define __LC_RETURN_MCCK_PSW 0x288
#define __LC_KERNEL_STACK 0xC40
#define __LC_THREAD_INFO 0xC44
#define __LC_ASYNC_STACK 0xC48
@@ -90,6 +91,7 @@
#define __LC_SYSTEM_TIMER 0x278
#define __LC_LAST_UPDATE_CLOCK 0x280
#define __LC_STEAL_CLOCK 0x288
+#define __LC_RETURN_MCCK_PSW 0x290
#define __LC_KERNEL_STACK 0xD40
#define __LC_THREAD_INFO 0xD48
#define __LC_ASYNC_STACK 0xD50
@@ -196,7 +198,8 @@ struct _lowcore
__u64 system_timer; /* 0x270 */
__u64 last_update_clock; /* 0x278 */
__u64 steal_clock; /* 0x280 */
- __u8 pad8[0xc00-0x288]; /* 0x288 */
+ psw_t return_mcck_psw; /* 0x288 */
+ __u8 pad8[0xc00-0x290]; /* 0x290 */
/* System info area */
__u32 save_area[16]; /* 0xc00 */
@@ -285,7 +288,8 @@ struct _lowcore
__u64 system_timer; /* 0x278 */
__u64 last_update_clock; /* 0x280 */
__u64 steal_clock; /* 0x288 */
- __u8 pad8[0xc00-0x290]; /* 0x290 */
+ psw_t return_mcck_psw; /* 0x290 */
+ __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */
/* System info area */
__u64 save_area[16]; /* 0xc00 */
__u8 pad9[0xd40-0xc80]; /* 0xc80 */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 2be287b9df88..2430c561e021 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -111,20 +111,6 @@ static inline void copy_page(void *to, void *from)
#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
/*
* These are used to make use of C type-checking..
*/
@@ -207,4 +193,6 @@ page_get_storage_key(unsigned long addr)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h
index 0e96eeca4e6b..15a5298c8744 100644
--- a/include/asm-s390/socket.h
+++ b/include/asm-s390/socket.h
@@ -22,6 +22,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-s390/spinlock.h b/include/asm-s390/spinlock.h
index 8ff10300f7ee..273dbecf8ace 100644
--- a/include/asm-s390/spinlock.h
+++ b/include/asm-s390/spinlock.h
@@ -27,42 +27,36 @@ _raw_compare_and_swap(volatile unsigned int *lock,
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
*/
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} __attribute__ ((aligned (4))) spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
-#define spin_unlock_wait(lp) do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
-#define spin_is_locked(x) ((x)->lock != 0)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
-extern void _raw_spin_lock_wait(spinlock_t *lp, unsigned int pc);
-extern int _raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc);
+extern void _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc);
+extern int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc);
-static inline void _raw_spin_lock(spinlock_t *lp)
+static inline void __raw_spin_lock(raw_spinlock_t *lp)
{
- unsigned long pc = (unsigned long) __builtin_return_address(0);
+ unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
if (unlikely(_raw_compare_and_swap(&lp->lock, 0, pc) != 0))
_raw_spin_lock_wait(lp, pc);
}
-static inline int _raw_spin_trylock(spinlock_t *lp)
+static inline int __raw_spin_trylock(raw_spinlock_t *lp)
{
- unsigned long pc = (unsigned long) __builtin_return_address(0);
+ unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
if (likely(_raw_compare_and_swap(&lp->lock, 0, pc) == 0))
return 1;
return _raw_spin_trylock_retry(lp, pc);
}
-static inline void _raw_spin_unlock(spinlock_t *lp)
+static inline void __raw_spin_unlock(raw_spinlock_t *lp)
{
_raw_compare_and_swap(&lp->lock, lp->lock, 0);
}
@@ -77,36 +71,25 @@ static inline void _raw_spin_unlock(spinlock_t *lp)
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-typedef struct {
- volatile unsigned int lock;
- volatile unsigned long owner_pc;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
/**
* read_can_lock - would read_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define read_can_lock(x) ((int)(x)->lock >= 0)
+#define __raw_read_can_lock(x) ((int)(x)->lock >= 0)
/**
* write_can_lock - would write_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define write_can_lock(x) ((x)->lock == 0)
+#define __raw_write_can_lock(x) ((x)->lock == 0)
-extern void _raw_read_lock_wait(rwlock_t *lp);
-extern int _raw_read_trylock_retry(rwlock_t *lp);
-extern void _raw_write_lock_wait(rwlock_t *lp);
-extern int _raw_write_trylock_retry(rwlock_t *lp);
+extern void _raw_read_lock_wait(raw_rwlock_t *lp);
+extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
+extern void _raw_write_lock_wait(raw_rwlock_t *lp);
+extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned int old;
old = rw->lock & 0x7fffffffU;
@@ -114,7 +97,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
_raw_read_lock_wait(rw);
}
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned int old, cmp;
@@ -125,18 +108,18 @@ static inline void _raw_read_unlock(rwlock_t *rw)
} while (cmp != old);
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
_raw_write_lock_wait(rw);
}
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
_raw_compare_and_swap(&rw->lock, 0x80000000, 0);
}
-static inline int _raw_read_trylock(rwlock_t *rw)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
{
unsigned int old;
old = rw->lock & 0x7fffffffU;
@@ -145,7 +128,7 @@ static inline int _raw_read_trylock(rwlock_t *rw)
return _raw_read_trylock_retry(rw);
}
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
{
if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
return 1;
diff --git a/include/asm-s390/spinlock_types.h b/include/asm-s390/spinlock_types.h
new file mode 100644
index 000000000000..f79a2216204f
--- /dev/null
+++ b/include/asm-s390/spinlock_types.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} __attribute__ ((aligned (4))) raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+ volatile unsigned int owner_pc;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0, 0 }
+
+#endif
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index 3fefd61416a5..d0be3e477013 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -79,8 +79,6 @@ typedef unsigned long u64;
typedef u32 dma_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#ifndef __s390x__
typedef union {
unsigned long long pair;
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index 3e3bfe6a8fa8..38a5cf8ab9e3 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -65,13 +65,6 @@
#define access_ok(type,addr,size) __access_ok(addr,size)
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user *addr,
- unsigned long size)
-{
- return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-sh/auxvec.h b/include/asm-sh/auxvec.h
new file mode 100644
index 000000000000..fc21e4db5881
--- /dev/null
+++ b/include/asm-sh/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_SH_AUXVEC_H
+#define __ASM_SH_AUXVEC_H
+
+#endif /* __ASM_SH_AUXVEC_H */
diff --git a/include/asm-sh/fcntl.h b/include/asm-sh/fcntl.h
index 0b3ae524e34c..46ab12db5739 100644
--- a/include/asm-sh/fcntl.h
+++ b/include/asm-sh/fcntl.h
@@ -1,88 +1 @@
-#ifndef __ASM_SH_FCNTL_H
-#define __ASM_SH_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif /* __ASM_SH_FCNTL_H */
-
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-sh/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-sh/hdreg.h b/include/asm-sh/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-sh/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 831e52ee45b5..614a8c13b721 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -587,10 +587,6 @@ static inline int generic_irq_demux(int irq)
#define irq_canonicalize(irq) (irq)
#define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq))
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#if defined(CONFIG_CPU_SUBTYPE_SH73180)
#include <asm/irq-sh73180.h>
#endif
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 180467be8e7b..324e6cc5ecf7 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -122,24 +122,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#ifndef __ASSEMBLY__
-
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
-#endif
-
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index ecb909572d3f..0f4bcaae61bd 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -277,9 +277,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-sh/socket.h b/include/asm-sh/socket.h
index dde696c3b4c7..553904ff9336 100644
--- a/include/asm-sh/socket.h
+++ b/include/asm-sh/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_RCVBUFFORCE 32
+#define SO_SNDBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-sh/spinlock.h b/include/asm-sh/spinlock.h
index e770b55649eb..846322d4c35d 100644
--- a/include/asm-sh/spinlock.h
+++ b/include/asm-sh/spinlock.h
@@ -15,20 +15,11 @@
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
*/
-typedef struct {
- volatile unsigned long lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) do { barrier(); } while (spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+ do { cpu_relax(); } while (__raw_spin_is_locked(x))
/*
* Simple spin lock operations. There are two variants, one clears IRQ's
@@ -36,7 +27,7 @@ typedef struct {
*
* We make no fairness assumptions. They have a cost.
*/
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
__asm__ __volatile__ (
"1:\n\t"
@@ -49,14 +40,14 @@ static inline void _raw_spin_lock(spinlock_t *lock)
);
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
assert_spin_locked(lock);
lock->lock = 0;
}
-#define _raw_spin_trylock(x) (!test_and_set_bit(0, &(x)->lock))
+#define __raw_spin_trylock(x) (!test_and_set_bit(0, &(x)->lock))
/*
* Read-write spinlocks, allowing multiple readers but only one writer.
@@ -66,51 +57,40 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
* needs to get a irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-typedef struct {
- spinlock_t lock;
- atomic_t counter;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_BIAS 0x01000000
-#define RW_LOCK_UNLOCKED (rwlock_t) { { 0 }, { RW_LOCK_BIAS } }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while (0)
-
-static inline void _raw_read_lock(rwlock_t *rw)
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
atomic_inc(&rw->counter);
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
}
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
atomic_dec(&rw->counter);
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
- _raw_spin_lock(&rw->lock);
+ __raw_spin_lock(&rw->lock);
atomic_set(&rw->counter, -1);
}
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
atomic_set(&rw->counter, 0);
- _raw_spin_unlock(&rw->lock);
+ __raw_spin_unlock(&rw->lock);
}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
{
if (atomic_sub_and_test(RW_LOCK_BIAS, &rw->counter))
return 1;
@@ -121,4 +101,3 @@ static inline int _raw_write_trylock(rwlock_t *rw)
}
#endif /* __ASM_SH_SPINLOCK_H */
-
diff --git a/include/asm-sh/spinlock_types.h b/include/asm-sh/spinlock_types.h
new file mode 100644
index 000000000000..8c41b6c3aac8
--- /dev/null
+++ b/include/asm-sh/spinlock_types.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_SH_SPINLOCK_TYPES_H
+#define __ASM_SH_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned long lock;
+} raw_spinlock_t;
+
+#define __SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ raw_spinlock_t lock;
+ atomic_t counter;
+} raw_rwlock_t;
+
+#define RW_LOCK_BIAS 0x01000000
+#define __RAW_RW_LOCK_UNLOCKED { { 0 }, { RW_LOCK_BIAS } }
+
+#endif
diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h
index c4dc126c5621..cb7e183a0a6b 100644
--- a/include/asm-sh/types.h
+++ b/include/asm-sh/types.h
@@ -58,8 +58,6 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index fb9e334afa2b..2cb01861e7c5 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -146,12 +146,6 @@ static inline int access_ok(int type, const void __user *p, unsigned long size)
return __access_ok(addr, size);
}
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
/*
* Uh, these should become the main single-value transfer routines ...
* They automatically use the right size if we just have the right
diff --git a/include/asm-sh64/auxvec.h b/include/asm-sh64/auxvec.h
new file mode 100644
index 000000000000..1ad5a44bdc76
--- /dev/null
+++ b/include/asm-sh64/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_SH64_AUXVEC_H
+#define __ASM_SH64_AUXVEC_H
+
+#endif /* __ASM_SH64_AUXVEC_H */
diff --git a/include/asm-sh64/fcntl.h b/include/asm-sh64/fcntl.h
index ffcc36c64fa5..744dd79b9d5d 100644
--- a/include/asm-sh64/fcntl.h
+++ b/include/asm-sh64/fcntl.h
@@ -1,7 +1 @@
-#ifndef __ASM_SH64_FCNTL_H
-#define __ASM_SH64_FCNTL_H
-
#include <asm-sh/fcntl.h>
-
-#endif /* __ASM_SH64_FCNTL_H */
-
diff --git a/include/asm-sh64/futex.h b/include/asm-sh64/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-sh64/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-sh64/hdreg.h b/include/asm-sh64/hdreg.h
deleted file mode 100644
index 52d983635a27..000000000000
--- a/include/asm-sh64/hdreg.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_SH64_HDREG_H
-#define __ASM_SH64_HDREG_H
-
-#include <asm-generic/hdreg.h>
-
-#endif /* __ASM_SH64_HDREG_H */
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index d6167f1c0e99..c86df90f7cbd 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -115,24 +115,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#ifndef __ASSEMBLY__
-
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
-#endif
-
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* __ASM_SH64_PAGE_H */
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 78ac6be2d9ef..51db4307bfaf 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -482,9 +482,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-sh64/types.h b/include/asm-sh64/types.h
index 41d4d2f82aa9..8d41db2153b5 100644
--- a/include/asm-sh64/types.h
+++ b/include/asm-sh64/types.h
@@ -65,8 +65,6 @@ typedef u32 dma_addr_t;
#endif
typedef u64 dma64_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#define BITS_PER_LONG 32
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
index a33654d576a1..56aa3cf0f273 100644
--- a/include/asm-sh64/uaccess.h
+++ b/include/asm-sh64/uaccess.h
@@ -60,12 +60,6 @@
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
/*
* Uh, these should become the main single-value transfer routines ...
* They automatically use the right size if we just have the right
diff --git a/include/asm-sparc/auxvec.h b/include/asm-sparc/auxvec.h
new file mode 100644
index 000000000000..ad6f360261f6
--- /dev/null
+++ b/include/asm-sparc/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMSPARC_AUXVEC_H
+#define __ASMSPARC_AUXVEC_H
+
+#endif /* !(__ASMSPARC_AUXVEC_H) */
diff --git a/include/asm-sparc/fcntl.h b/include/asm-sparc/fcntl.h
index df9c75d41d68..5db60b5ae7b0 100644
--- a/include/asm-sparc/fcntl.h
+++ b/include/asm-sparc/fcntl.h
@@ -4,10 +4,6 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
-#define O_ACCMODE 0x0003
#define O_APPEND 0x0008
#define FASYNC 0x0040 /* fcntl, for BSD compatibility */
#define O_CREAT 0x0200 /* not fcntl */
@@ -17,73 +13,24 @@
#define O_NONBLOCK 0x4000
#define O_NDELAY (0x0004 | O_NONBLOCK)
#define O_NOCTTY 0x8000 /* not fcntl */
-#define O_DIRECTORY 0x10000 /* must be a directory */
-#define O_NOFOLLOW 0x20000 /* don't follow links */
#define O_LARGEFILE 0x40000
#define O_DIRECT 0x100000 /* direct disk access hint */
#define O_NOATIME 0x200000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
#define F_GETOWN 5 /* for sockets. */
#define F_SETOWN 6 /* for sockets. */
#define F_GETLK 7
#define F_SETLK 8
#define F_SETLKW 9
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* for posix fcntl() and lockf() */
#define F_RDLCK 1
#define F_WRLCK 2
#define F_UNLCK 3
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
- short __unused;
-};
+#define __ARCH_FLOCK_PAD short __unused;
+#define __ARCH_FLOCK64_PAD short __unused;
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
- short __unused;
-};
+#include <asm-generic/fcntl.h>
-#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-sparc/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-sparc/hdreg.h b/include/asm-sparc/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-sparc/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 383060e90d94..9122684f6c1e 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -132,20 +132,6 @@ BTFIXUPDEF_SETHI(sparc_unmapped_base)
#define TASK_UNMAPPED_BASE BTFIXUP_SETHI(sparc_unmapped_base)
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#else /* !(__ASSEMBLY__) */
#define __pgprot(x) (x)
@@ -178,4 +164,6 @@ extern unsigned long pfn_base;
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _SPARC_PAGE_H */
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 40ed30a2b7c6..8f4f6a959651 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -435,9 +435,6 @@ extern unsigned long *sparc_valid_addr_bitmap;
#define kern_addr_valid(addr) \
(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
-extern int io_remap_page_range(struct vm_area_struct *vma,
- unsigned long from, unsigned long to,
- unsigned long size, pgprot_t prot, int space);
extern int io_remap_pfn_range(struct vm_area_struct *vma,
unsigned long from, unsigned long pfn,
unsigned long size, pgprot_t prot);
diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
index 32c9699367cf..5a7a1a8d29ac 100644
--- a/include/asm-sparc/processor.h
+++ b/include/asm-sparc/processor.h
@@ -19,7 +19,6 @@
#include <asm/ptrace.h>
#include <asm/head.h>
#include <asm/signal.h>
-#include <asm/segment.h>
#include <asm/btfixup.h>
#include <asm/page.h>
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
index dd9d94d7e0ae..a8ecb2d6977a 100644
--- a/include/asm-sparc/ptrace.h
+++ b/include/asm-sparc/ptrace.h
@@ -73,11 +73,11 @@ extern void show_regs(struct pt_regs *);
#endif
/*
- * The asm_offsets.h is a generated file, so we cannot include it.
+ * The asm-offsets.h is a generated file, so we cannot include it.
* It may be OK for glibc headers, but it's utterly pointless for C code.
* The assembly code using those offsets has to include it explicitly.
*/
-/* #include <asm/asm_offsets.h> */
+/* #include <asm/asm-offsets.h> */
/* These are for pt_regs. */
#define PT_PSR 0x0
diff --git a/include/asm-sparc/segment.h b/include/asm-sparc/segment.h
deleted file mode 100644
index a1b7ffc9eec9..000000000000
--- a/include/asm-sparc/segment.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_SEGMENT_H
-#define __SPARC_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif
diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
index c1154e3ecfdf..09575b608adb 100644
--- a/include/asm-sparc/socket.h
+++ b/include/asm-sparc/socket.h
@@ -29,6 +29,8 @@
#define SO_SNDBUF 0x1001
#define SO_RCVBUF 0x1002
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h
index 0cbd87ad4912..111727a2bb4e 100644
--- a/include/asm-sparc/spinlock.h
+++ b/include/asm-sparc/spinlock.h
@@ -12,96 +12,12 @@
#include <asm/psr.h>
-#ifdef CONFIG_DEBUG_SPINLOCK
-struct _spinlock_debug {
- unsigned char lock;
- unsigned long owner_pc;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-};
-typedef struct _spinlock_debug spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0 }
-#define spin_lock_init(lp) do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(lp) (*((volatile unsigned char *)(&((lp)->lock))) != 0)
-#define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
-
-extern void _do_spin_lock(spinlock_t *lock, char *str);
-extern int _spin_trylock(spinlock_t *lock);
-extern void _do_spin_unlock(spinlock_t *lock);
-
-#define _raw_spin_trylock(lp) _spin_trylock(lp)
-#define _raw_spin_lock(lock) _do_spin_lock(lock, "spin_lock")
-#define _raw_spin_unlock(lock) _do_spin_unlock(lock)
-
-struct _rwlock_debug {
- volatile unsigned int lock;
- unsigned long owner_pc;
- unsigned long reader_pc[NR_CPUS];
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-};
-typedef struct _rwlock_debug rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
-
-#define rwlock_init(lp) do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
-
-extern void _do_read_lock(rwlock_t *rw, char *str);
-extern void _do_read_unlock(rwlock_t *rw, char *str);
-extern void _do_write_lock(rwlock_t *rw, char *str);
-extern void _do_write_unlock(rwlock_t *rw);
-
-#define _raw_read_lock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_read_lock(lock, "read_lock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_read_unlock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_read_unlock(lock, "read_unlock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_lock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_write_lock(lock, "write_lock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_unlock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_write_unlock(lock); \
- local_irq_restore(flags); \
-} while(0)
-
-#else /* !CONFIG_DEBUG_SPINLOCK */
-
-typedef struct {
- unsigned char lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-
-#define spin_lock_init(lock) (*((unsigned char *)(lock)) = 0)
-#define spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
+#define __raw_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
-#define spin_unlock_wait(lock) \
-do { \
- barrier(); \
-} while(*((volatile unsigned char *)lock))
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
-extern __inline__ void _raw_spin_lock(spinlock_t *lock)
+extern __inline__ void __raw_spin_lock(raw_spinlock_t *lock)
{
__asm__ __volatile__(
"\n1:\n\t"
@@ -121,7 +37,7 @@ extern __inline__ void _raw_spin_lock(spinlock_t *lock)
: "g2", "memory", "cc");
}
-extern __inline__ int _raw_spin_trylock(spinlock_t *lock)
+extern __inline__ int __raw_spin_trylock(raw_spinlock_t *lock)
{
unsigned int result;
__asm__ __volatile__("ldstub [%1], %0"
@@ -131,7 +47,7 @@ extern __inline__ int _raw_spin_trylock(spinlock_t *lock)
return (result == 0);
}
-extern __inline__ void _raw_spin_unlock(spinlock_t *lock)
+extern __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
{
__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
}
@@ -147,23 +63,11 @@ extern __inline__ void _raw_spin_unlock(spinlock_t *lock)
*
* XXX This might create some problems with my dual spinlock
* XXX scheme, deadlocks etc. -DaveM
- */
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-
-#define rwlock_init(lp) do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
-
-
-/* Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ * Sort of like atomic_t's on Sparc, but even more clever.
*
* ------------------------------------
- * | 24-bit counter | wlock | rwlock_t
+ * | 24-bit counter | wlock | raw_rwlock_t
* ------------------------------------
* 31 8 7 0
*
@@ -174,9 +78,9 @@ typedef struct {
*
* Unfortunately this scheme limits us to ~16,000,000 cpus.
*/
-extern __inline__ void _read_lock(rwlock_t *rw)
+extern __inline__ void __read_lock(raw_rwlock_t *rw)
{
- register rwlock_t *lp asm("g1");
+ register raw_rwlock_t *lp asm("g1");
lp = rw;
__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
@@ -187,16 +91,16 @@ extern __inline__ void _read_lock(rwlock_t *rw)
: "g2", "g4", "memory", "cc");
}
-#define _raw_read_lock(lock) \
+#define __raw_read_lock(lock) \
do { unsigned long flags; \
local_irq_save(flags); \
- _read_lock(lock); \
+ __raw_read_lock(lock); \
local_irq_restore(flags); \
} while(0)
-extern __inline__ void _read_unlock(rwlock_t *rw)
+extern __inline__ void __read_unlock(raw_rwlock_t *rw)
{
- register rwlock_t *lp asm("g1");
+ register raw_rwlock_t *lp asm("g1");
lp = rw;
__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
@@ -207,16 +111,16 @@ extern __inline__ void _read_unlock(rwlock_t *rw)
: "g2", "g4", "memory", "cc");
}
-#define _raw_read_unlock(lock) \
+#define __raw_read_unlock(lock) \
do { unsigned long flags; \
local_irq_save(flags); \
- _read_unlock(lock); \
+ __raw_read_unlock(lock); \
local_irq_restore(flags); \
} while(0)
-extern __inline__ void _raw_write_lock(rwlock_t *rw)
+extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
{
- register rwlock_t *lp asm("g1");
+ register raw_rwlock_t *lp asm("g1");
lp = rw;
__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
@@ -227,11 +131,9 @@ extern __inline__ void _raw_write_lock(rwlock_t *rw)
: "g2", "g4", "memory", "cc");
}
-#define _raw_write_unlock(rw) do { (rw)->lock = 0; } while(0)
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
+#define __raw_write_unlock(rw) do { (rw)->lock = 0; } while(0)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc/spinlock_types.h b/include/asm-sparc/spinlock_types.h
new file mode 100644
index 000000000000..0a0fb116c4ec
--- /dev/null
+++ b/include/asm-sparc/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __SPARC_SPINLOCK_TYPES_H
+#define __SPARC_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ unsigned char lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 898562ebe94c..3557781a4bfd 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -9,7 +9,6 @@
#include <linux/threads.h> /* NR_CPUS */
#include <linux/thread_info.h>
-#include <asm/segment.h>
#include <asm/page.h>
#include <asm/psr.h>
#include <asm/ptrace.h>
diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h
index 9eabf6e61ccc..42fc6ed98156 100644
--- a/include/asm-sparc/types.h
+++ b/include/asm-sparc/types.h
@@ -54,8 +54,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index 0a780e84a12b..f8f1ec1f06e6 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -47,12 +47,6 @@
#define access_ok(type, addr, size) \
({ (void)(type); __access_ok((unsigned long)(addr), size); })
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index d80f3379669b..e175afcf2cde 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -72,10 +72,10 @@ extern int atomic64_sub_ret(int, atomic64_t *);
/* Atomic operations are already serializing */
#ifdef CONFIG_SMP
-#define smp_mb__before_atomic_dec() membar("#StoreLoad | #LoadLoad")
-#define smp_mb__after_atomic_dec() membar("#StoreLoad | #StoreStore")
-#define smp_mb__before_atomic_inc() membar("#StoreLoad | #LoadLoad")
-#define smp_mb__after_atomic_inc() membar("#StoreLoad | #StoreStore")
+#define smp_mb__before_atomic_dec() membar_storeload_loadload();
+#define smp_mb__after_atomic_dec() membar_storeload_storestore();
+#define smp_mb__before_atomic_inc() membar_storeload_loadload();
+#define smp_mb__after_atomic_inc() membar_storeload_storestore();
#else
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
diff --git a/include/asm-sparc64/auxvec.h b/include/asm-sparc64/auxvec.h
new file mode 100644
index 000000000000..436a29129828
--- /dev/null
+++ b/include/asm-sparc64/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_SPARC64_AUXVEC_H
+#define __ASM_SPARC64_AUXVEC_H
+
+#endif /* !(__ASM_SPARC64_AUXVEC_H) */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 9c5e71970287..6388b8376c50 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -72,8 +72,8 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
}
#ifdef CONFIG_SMP
-#define smp_mb__before_clear_bit() membar("#StoreLoad | #LoadLoad")
-#define smp_mb__after_clear_bit() membar("#StoreLoad | #StoreStore")
+#define smp_mb__before_clear_bit() membar_storeload_loadload()
+#define smp_mb__after_clear_bit() membar_storeload_storestore()
#else
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index b59122dd176d..c73935dc7ba1 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -12,8 +12,10 @@ typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
-typedef u16 compat_uid_t;
-typedef u16 compat_gid_t;
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u16 compat_dev_t;
@@ -47,8 +49,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
compat_dev_t st_rdev;
compat_off_t st_size;
compat_time_t st_atime;
@@ -177,10 +179,10 @@ static __inline__ void __user *compat_alloc_user_space(long len)
struct compat_ipc64_perm {
compat_key_t key;
- __kernel_uid_t uid;
- __kernel_gid_t gid;
- __kernel_uid_t cuid;
- __kernel_gid_t cgid;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
unsigned short __pad1;
compat_mode_t mode;
unsigned short __pad2;
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index cc7198aaac50..9a3a81f1cc58 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -1,6 +1,6 @@
/* cpudata.h: Per-cpu parameters.
*
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2003, 2005 David S. Miller (davem@redhat.com)
*/
#ifndef _SPARC64_CPUDATA_H
@@ -10,7 +10,7 @@
typedef struct {
/* Dcache line 1 */
- unsigned int __pad0; /* bh_count moved to irq_stat for consistency. KAO */
+ unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
unsigned int multiplier;
unsigned int counter;
unsigned int idle_volume;
diff --git a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h
index e36def0d0d80..b2aecf0054bd 100644
--- a/include/asm-sparc64/fcntl.h
+++ b/include/asm-sparc64/fcntl.h
@@ -4,10 +4,6 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
-#define O_ACCMODE 0x0003
#define O_NDELAY 0x0004
#define O_APPEND 0x0008
#define FASYNC 0x0040 /* fcntl, for BSD compatibility */
@@ -17,62 +13,24 @@
#define O_SYNC 0x2000
#define O_NONBLOCK 0x4000
#define O_NOCTTY 0x8000 /* not fcntl */
-#define O_DIRECTORY 0x10000 /* must be a directory */
-#define O_NOFOLLOW 0x20000 /* don't follow links */
#define O_LARGEFILE 0x40000
#define O_DIRECT 0x100000 /* direct disk access hint */
#define O_NOATIME 0x200000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
#define F_GETOWN 5 /* for sockets. */
#define F_SETOWN 6 /* for sockets. */
#define F_GETLK 7
#define F_SETLK 8
#define F_SETLKW 9
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* for posix fcntl() and lockf() */
#define F_RDLCK 1
#define F_WRLCK 2
#define F_UNLCK 3
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
- short __unused;
-};
+#define __ARCH_FLOCK_PAD short __unused;
-#define F_LINUX_SPECIFIC_BASE 1024
+#include <asm-generic/fcntl.h>
#endif /* !(_SPARC64_FCNTL_H) */
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-sparc64/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
index d6db1aed7645..f0cf71376ec5 100644
--- a/include/asm-sparc64/hardirq.h
+++ b/include/asm-sparc64/hardirq.h
@@ -1,22 +1,16 @@
/* hardirq.h: 64-bit Sparc hard IRQ support.
*
- * Copyright (C) 1997, 1998 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1998, 2005 David S. Miller (davem@davemloft.net)
*/
#ifndef __SPARC64_HARDIRQ_H
#define __SPARC64_HARDIRQ_H
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/cache.h>
+#include <asm/cpudata.h>
-/* rtrap.S is sensitive to the offsets of these fields */
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#define __ARCH_IRQ_STAT
+#define local_softirq_pending() \
+ (local_cpu_data().__softirq_pending)
#define HARDIRQ_BITS 8
diff --git a/include/asm-sparc64/hdreg.h b/include/asm-sparc64/hdreg.h
deleted file mode 100644
index 7f7fd1af0af3..000000000000
--- a/include/asm-sparc64/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hdreg.h>
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index afdcea90707a..0056770e83ad 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -100,18 +100,41 @@ static __inline__ void _outl(u32 l, unsigned long addr)
#define inl_p(__addr) inl(__addr)
#define outl_p(__l, __addr) outl(__l, __addr)
-extern void outsb(void __iomem *addr, const void *src, unsigned long count);
-extern void outsw(void __iomem *addr, const void *src, unsigned long count);
-extern void outsl(void __iomem *addr, const void *src, unsigned long count);
-extern void insb(void __iomem *addr, void *dst, unsigned long count);
-extern void insw(void __iomem *addr, void *dst, unsigned long count);
-extern void insl(void __iomem *addr, void *dst, unsigned long count);
-#define ioread8_rep(a,d,c) insb(a,d,c)
-#define ioread16_rep(a,d,c) insw(a,d,c)
-#define ioread32_rep(a,d,c) insl(a,d,c)
-#define iowrite8_rep(a,s,c) outsb(a,s,c)
-#define iowrite16_rep(a,s,c) outsw(a,s,c)
-#define iowrite32_rep(a,s,c) outsl(a,s,c)
+extern void outsb(unsigned long, const void *, unsigned long);
+extern void outsw(unsigned long, const void *, unsigned long);
+extern void outsl(unsigned long, const void *, unsigned long);
+extern void insb(unsigned long, void *, unsigned long);
+extern void insw(unsigned long, void *, unsigned long);
+extern void insl(unsigned long, void *, unsigned long);
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insw((unsigned long __force)port, buf, count);
+}
+
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insl((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsb((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsw((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsl((unsigned long __force)port, buf, count);
+}
/* Memory functions, same as I/O accesses on Ultra. */
static inline u8 _readb(const volatile void __iomem *addr)
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index b87dbbd64bc9..c9f8ef208ea5 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -150,20 +150,6 @@ struct sparc_phys_banks {
extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#endif /* !(__ASSEMBLY__) */
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
@@ -171,4 +157,6 @@ static __inline__ int get_order(unsigned long size)
#endif /* !(__KERNEL__) */
+#include <asm-generic/page.h>
+
#endif /* !(_SPARC64_PAGE_H) */
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index a4ab0ec7143a..89bd71b1c0d8 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -269,6 +269,8 @@ extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
+extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
+
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
{
}
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 1ae00c5087f1..a2b4f5ed4625 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -410,9 +410,6 @@ extern unsigned long *sparc64_valid_addr_bitmap;
#define kern_addr_valid(addr) \
(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long offset,
- unsigned long size, pgprot_t prot, int space);
extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long pfn,
unsigned long size, pgprot_t prot);
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index d0bee2413560..3169f3e2237e 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -18,7 +18,6 @@
#include <asm/a.out.h>
#include <asm/pstate.h>
#include <asm/ptrace.h>
-#include <asm/segment.h>
#include <asm/page.h>
/* The sparc has no problems with write protection */
diff --git a/include/asm-sparc64/segment.h b/include/asm-sparc64/segment.h
deleted file mode 100644
index b03e709fc945..000000000000
--- a/include/asm-sparc64/segment.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC64_SEGMENT_H
-#define __SPARC64_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif
diff --git a/include/asm-sparc64/sfafsr.h b/include/asm-sparc64/sfafsr.h
new file mode 100644
index 000000000000..2f792c20b53c
--- /dev/null
+++ b/include/asm-sparc64/sfafsr.h
@@ -0,0 +1,82 @@
+#ifndef _SPARC64_SFAFSR_H
+#define _SPARC64_SFAFSR_H
+
+#include <asm/const.h>
+
+/* Spitfire Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+#define SFAFSR_ME (_AC(1,UL) << SFAFSR_ME_SHIFT)
+#define SFAFSR_ME_SHIFT 32
+#define SFAFSR_PRIV (_AC(1,UL) << SFAFSR_PRIV_SHIFT)
+#define SFAFSR_PRIV_SHIFT 31
+#define SFAFSR_ISAP (_AC(1,UL) << SFAFSR_ISAP_SHIFT)
+#define SFAFSR_ISAP_SHIFT 30
+#define SFAFSR_ETP (_AC(1,UL) << SFAFSR_ETP_SHIFT)
+#define SFAFSR_ETP_SHIFT 29
+#define SFAFSR_IVUE (_AC(1,UL) << SFAFSR_IVUE_SHIFT)
+#define SFAFSR_IVUE_SHIFT 28
+#define SFAFSR_TO (_AC(1,UL) << SFAFSR_TO_SHIFT)
+#define SFAFSR_TO_SHIFT 27
+#define SFAFSR_BERR (_AC(1,UL) << SFAFSR_BERR_SHIFT)
+#define SFAFSR_BERR_SHIFT 26
+#define SFAFSR_LDP (_AC(1,UL) << SFAFSR_LDP_SHIFT)
+#define SFAFSR_LDP_SHIFT 25
+#define SFAFSR_CP (_AC(1,UL) << SFAFSR_CP_SHIFT)
+#define SFAFSR_CP_SHIFT 24
+#define SFAFSR_WP (_AC(1,UL) << SFAFSR_WP_SHIFT)
+#define SFAFSR_WP_SHIFT 23
+#define SFAFSR_EDP (_AC(1,UL) << SFAFSR_EDP_SHIFT)
+#define SFAFSR_EDP_SHIFT 22
+#define SFAFSR_UE (_AC(1,UL) << SFAFSR_UE_SHIFT)
+#define SFAFSR_UE_SHIFT 21
+#define SFAFSR_CE (_AC(1,UL) << SFAFSR_CE_SHIFT)
+#define SFAFSR_CE_SHIFT 20
+#define SFAFSR_ETS (_AC(0xf,UL) << SFAFSR_ETS_SHIFT)
+#define SFAFSR_ETS_SHIFT 16
+#define SFAFSR_PSYND (_AC(0xffff,UL) << SFAFSR_PSYND_SHIFT)
+#define SFAFSR_PSYND_SHIFT 0
+
+/* UDB Error Register, ASI=0x7f VA<63:0>=0x0(High),0x18(Low) for read
+ * ASI=0x77 VA<63:0>=0x0(High),0x18(Low) for write
+ */
+
+#define UDBE_UE (_AC(1,UL) << 9)
+#define UDBE_CE (_AC(1,UL) << 8)
+#define UDBE_E_SYNDR (_AC(0xff,UL) << 0)
+
+/* The trap handlers for asynchronous errors encode the AFSR and
+ * other pieces of information into a 64-bit argument for C code
+ * encoded as follows:
+ *
+ * -----------------------------------------------
+ * | UDB_H | UDB_L | TL>1 | TT | AFSR |
+ * -----------------------------------------------
+ * 63 54 53 44 42 41 33 32 0
+ *
+ * The AFAR is passed in unchanged.
+ */
+#define SFSTAT_UDBH_MASK (_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBH_SHIFT 54
+#define SFSTAT_UDBL_MASK (_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBL_SHIFT 44
+#define SFSTAT_TL_GT_ONE (_AC(1,UL) << SFSTAT_TL_GT_ONE_SHIFT)
+#define SFSTAT_TL_GT_ONE_SHIFT 42
+#define SFSTAT_TRAP_TYPE (_AC(0x1FF,UL) << SFSTAT_TRAP_TYPE_SHIFT)
+#define SFSTAT_TRAP_TYPE_SHIFT 33
+#define SFSTAT_AFSR_MASK (_AC(0x1ffffffff,UL) << SFSTAT_AFSR_SHIFT)
+#define SFSTAT_AFSR_SHIFT 0
+
+/* ESTATE Error Enable Register, ASI=0x4b VA<63:0>=0x0 */
+#define ESTATE_ERR_CE 0x1 /* Correctable errors */
+#define ESTATE_ERR_NCE 0x2 /* TO, BERR, LDP, ETP, EDP, WP, UE, IVUE */
+#define ESTATE_ERR_ISAP 0x4 /* System address parity error */
+#define ESTATE_ERR_ALL (ESTATE_ERR_CE | \
+ ESTATE_ERR_NCE | \
+ ESTATE_ERR_ISAP)
+
+/* The various trap types that report using the above state. */
+#define TRAP_TYPE_IAE 0x09 /* Instruction Access Error */
+#define TRAP_TYPE_DAE 0x32 /* Data Access Error */
+#define TRAP_TYPE_CEE 0x63 /* Correctable ECC Error */
+
+#endif /* _SPARC64_SFAFSR_H */
diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
index 865547a23908..59987dad3359 100644
--- a/include/asm-sparc64/socket.h
+++ b/include/asm-sparc64/socket.h
@@ -29,6 +29,8 @@
#define SO_SNDBUF 0x1001
#define SO_RCVBUF 0x1002
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index 9cb93a5c2b4f..ec85d12d73b9 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -29,24 +29,13 @@
* must be pre-V9 branches.
*/
-#ifndef CONFIG_DEBUG_SPINLOCK
+#define __raw_spin_is_locked(lp) ((lp)->lock != 0)
-typedef struct {
- volatile unsigned char lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) {0,}
+#define __raw_spin_unlock_wait(lp) \
+ do { rmb(); \
+ } while((lp)->lock)
-#define spin_lock_init(lp) do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(lp) ((lp)->lock != 0)
-
-#define spin_unlock_wait(lp) \
-do { membar("#LoadLoad"); \
-} while((lp)->lock)
-
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
unsigned long tmp;
@@ -67,7 +56,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
: "memory");
}
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
unsigned long result;
@@ -81,7 +70,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
return (result == 0UL);
}
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
__asm__ __volatile__(
" membar #StoreStore | #LoadStore\n"
@@ -91,7 +80,7 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
: "memory");
}
-static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
{
unsigned long tmp1, tmp2;
@@ -115,48 +104,9 @@ static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
: "memory");
}
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-typedef struct {
- volatile unsigned char lock;
- unsigned int owner_pc, owner_cpu;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, 0xff }
-#define spin_lock_init(lp) do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(__lock) ((__lock)->lock != 0)
-#define spin_unlock_wait(__lock) \
-do { \
- membar("#LoadLoad"); \
-} while((__lock)->lock)
-
-extern void _do_spin_lock (spinlock_t *lock, char *str);
-extern void _do_spin_unlock (spinlock_t *lock);
-extern int _do_spin_trylock (spinlock_t *lock);
-
-#define _raw_spin_trylock(lp) _do_spin_trylock(lp)
-#define _raw_spin_lock(lock) _do_spin_lock(lock, "spin_lock")
-#define _raw_spin_unlock(lock) _do_spin_unlock(lock)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) {0,}
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
-
-static void inline __read_lock(rwlock_t *lock)
+static void inline __read_lock(raw_rwlock_t *lock)
{
unsigned long tmp1, tmp2;
@@ -181,7 +131,7 @@ static void inline __read_lock(rwlock_t *lock)
: "memory");
}
-static void inline __read_unlock(rwlock_t *lock)
+static void inline __read_unlock(raw_rwlock_t *lock)
{
unsigned long tmp1, tmp2;
@@ -198,7 +148,7 @@ static void inline __read_unlock(rwlock_t *lock)
: "memory");
}
-static void inline __write_lock(rwlock_t *lock)
+static void inline __write_lock(raw_rwlock_t *lock)
{
unsigned long mask, tmp1, tmp2;
@@ -225,7 +175,7 @@ static void inline __write_lock(rwlock_t *lock)
: "memory");
}
-static void inline __write_unlock(rwlock_t *lock)
+static void inline __write_unlock(raw_rwlock_t *lock)
{
__asm__ __volatile__(
" membar #LoadStore | #StoreStore\n"
@@ -235,7 +185,7 @@ static void inline __write_unlock(rwlock_t *lock)
: "memory");
}
-static int inline __write_trylock(rwlock_t *lock)
+static int inline __write_trylock(raw_rwlock_t *lock)
{
unsigned long mask, tmp1, tmp2, result;
@@ -260,73 +210,15 @@ static int inline __write_trylock(rwlock_t *lock)
return result;
}
-#define _raw_read_lock(p) __read_lock(p)
-#define _raw_read_unlock(p) __read_unlock(p)
-#define _raw_write_lock(p) __write_lock(p)
-#define _raw_write_unlock(p) __write_unlock(p)
-#define _raw_write_trylock(p) __write_trylock(p)
-
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-typedef struct {
- volatile unsigned long lock;
- unsigned int writer_pc, writer_cpu;
- unsigned int reader_pc[NR_CPUS];
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff, { } }
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
-
-extern void _do_read_lock(rwlock_t *rw, char *str);
-extern void _do_read_unlock(rwlock_t *rw, char *str);
-extern void _do_write_lock(rwlock_t *rw, char *str);
-extern void _do_write_unlock(rwlock_t *rw);
-extern int _do_write_trylock(rwlock_t *rw, char *str);
-
-#define _raw_read_lock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_read_lock(lock, "read_lock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_read_unlock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_read_unlock(lock, "read_unlock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_lock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_write_lock(lock, "write_lock"); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_unlock(lock) \
-do { unsigned long flags; \
- local_irq_save(flags); \
- _do_write_unlock(lock); \
- local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_trylock(lock) \
-({ unsigned long flags; \
- int val; \
- local_irq_save(flags); \
- val = _do_write_trylock(lock, "write_trylock"); \
- local_irq_restore(flags); \
- val; \
-})
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
-#define read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
-#define write_can_lock(rw) (!(rw)->lock)
+#define __raw_read_lock(p) __read_lock(p)
+#define __raw_read_unlock(p) __read_unlock(p)
+#define __raw_write_lock(p) __write_lock(p)
+#define __raw_write_unlock(p) __write_unlock(p)
+#define __raw_write_trylock(p) __write_trylock(p)
+
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+#define __raw_read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
+#define __raw_write_can_lock(rw) (!(rw)->lock)
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/spinlock_types.h b/include/asm-sparc64/spinlock_types.h
new file mode 100644
index 000000000000..e128112a0d7c
--- /dev/null
+++ b/include/asm-sparc64/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __SPARC64_SPINLOCK_TYPES_H
+#define __SPARC64_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned char lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index ee4bdfc6b88f..b5417529f6f1 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -28,6 +28,49 @@ enum sparc_cpu {
#define ARCH_SUN4C_SUN4 0
#define ARCH_SUN4 0
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51. Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ * call sym_ccb_from_dsa, 0
+ * movge %icc, 0, %l0
+ * brz,pn %o0, .LL1303
+ * mov %o0, %l2
+ * membar #LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur. Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
+ " membar " type "\n" \
+ "1:\n" \
+ : : : "memory"); \
+} while (0)
+
+#define mb() \
+ membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
+#define rmb() \
+ membar_safe("#LoadLoad")
+#define wmb() \
+ membar_safe("#StoreStore")
+#define membar_storeload() \
+ membar_safe("#StoreLoad")
+#define membar_storeload_storestore() \
+ membar_safe("#StoreLoad | #StoreStore")
+#define membar_storeload_loadload() \
+ membar_safe("#StoreLoad | #LoadLoad")
+#define membar_storestore_loadstore() \
+ membar_safe("#StoreStore | #LoadStore")
+
#endif
#define setipl(__new_ipl) \
@@ -78,16 +121,11 @@ enum sparc_cpu {
#define nop() __asm__ __volatile__ ("nop")
-#define membar(type) __asm__ __volatile__ ("membar " type : : : "memory")
-#define mb() \
- membar("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
-#define rmb() membar("#LoadLoad")
-#define wmb() membar("#StoreStore")
#define read_barrier_depends() do { } while(0)
#define set_mb(__var, __value) \
- do { __var = __value; membar("#StoreLoad | #StoreStore"); } while(0)
+ do { __var = __value; membar_storeload_storestore(); } while(0)
#define set_wmb(__var, __value) \
- do { __var = __value; membar("#StoreStore"); } while(0)
+ do { __var = __value; wmb(); } while(0)
#ifdef CONFIG_SMP
#define smp_mb() mb()
diff --git a/include/asm-sparc64/types.h b/include/asm-sparc64/types.h
index 6248ed1a9a7a..d0ee7f105838 100644
--- a/include/asm-sparc64/types.h
+++ b/include/asm-sparc64/types.h
@@ -56,8 +56,6 @@ typedef unsigned long u64;
typedef u32 dma_addr_t;
typedef u64 dma64_addr_t;
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index 5690142f82de..80a65d7e3dbf 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -59,12 +59,6 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
return 1;
}
-/* this function will go away soon - use access_ok() instead */
-static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return 0;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-um/auxvec.h b/include/asm-um/auxvec.h
new file mode 100644
index 000000000000..1e5e1c2fc9b1
--- /dev/null
+++ b/include/asm-um/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __UM_AUXVEC_H
+#define __UM_AUXVEC_H
+
+#endif
diff --git a/include/asm-um/futex.h b/include/asm-um/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-um/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-um/hdreg.h b/include/asm-um/hdreg.h
deleted file mode 100644
index cf6363abcab9..000000000000
--- a/include/asm-um/hdreg.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_HDREG_H
-#define __UM_HDREG_H
-
-#include "asm/arch/hdreg.h"
-
-#endif
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 095bb627b96a..2edb4f1f789c 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -20,7 +20,15 @@ extern void force_flush_all(void);
static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
{
- if (old != new)
+ /*
+ * This is called by fs/exec.c and fs/aio.c. In the first case, for an
+ * exec, we don't need to do anything as we're called from userspace
+ * and thus going to use a new host PID. In the second, we're called
+ * from a kernel thread, and thus need to go doing the mmap's on the
+ * host. Since they're very expensive, we want to avoid that as far as
+ * possible.
+ */
+ if (old != new && (current->flags & PF_BORROWED_MM))
force_flush_all();
}
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index f58aedadeb4e..2c192abe9aeb 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -96,8 +96,7 @@ extern unsigned long uml_physmem;
#define __va_space (8*1024*1024)
-extern unsigned long to_phys(void *virt);
-extern void *to_virt(unsigned long phys);
+#include "mem.h"
/* Cast to unsigned long before casting to void * to avoid a warning from
* mmap_kmem about cutting a long long down to a void *. Not sure that
@@ -116,24 +115,12 @@ extern void *to_virt(unsigned long phys);
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
-/* Pure 2^n version of get_order */
-static __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
extern struct page *arch_validate(struct page *page, int mask, int order);
#define HAVE_ARCH_VALIDATE
extern void arch_free_page(struct page *page, int order);
#define HAVE_ARCH_FREE_PAGE
+#include <asm-generic/page.h>
+
#endif
diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
index 8fcb2fc0a892..ea49411236dc 100644
--- a/include/asm-um/pgalloc.h
+++ b/include/asm-um/pgalloc.h
@@ -42,11 +42,13 @@ static inline void pte_free(struct page *pte)
#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
#ifdef CONFIG_3_LEVEL_PGTABLES
-/*
- * In the 3-level case we free the pmds as part of the pgd.
- */
-#define pmd_free(x) do { } while (0)
-#define __pmd_free_tlb(tlb,x) do { } while (0)
+
+extern __inline__ void pmd_free(pmd_t *pmd)
+{
+ free_page((unsigned long)pmd);
+}
+
+#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
#endif
#define check_pgt_cache() do { } while (0)
diff --git a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h
index 9b3abc01d60e..ffe017f6b64b 100644
--- a/include/asm-um/pgtable-2level.h
+++ b/include/asm-um/pgtable-2level.h
@@ -35,35 +35,8 @@
static inline int pgd_newpage(pgd_t pgd) { return 0; }
static inline void pgd_mkuptodate(pgd_t pgd) { }
-#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-
-static inline pte_t pte_mknewprot(pte_t pte)
-{
- pte_val(pte) |= _PAGE_NEWPROT;
- return(pte);
-}
-
-static inline pte_t pte_mknewpage(pte_t pte)
-{
- pte_val(pte) |= _PAGE_NEWPAGE;
- return(pte);
-}
-
-static inline void set_pte(pte_t *pteptr, pte_t pteval)
-{
- /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
- * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
- * mapped pages.
- */
- *pteptr = pte_mknewpage(pteval);
- if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
-}
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE)
#define pte_pfn(x) phys_to_pfn(pte_val(x))
#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
index 65e8bfc55fc4..786c25727289 100644
--- a/include/asm-um/pgtable-3level.h
+++ b/include/asm-um/pgtable-3level.h
@@ -57,35 +57,6 @@ static inline int pgd_newpage(pgd_t pgd)
static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
-
-#define pte_present(x) pte_get_bits(x, (_PAGE_PRESENT | _PAGE_PROTNONE))
-
-static inline pte_t pte_mknewprot(pte_t pte)
-{
- pte_set_bits(pte, _PAGE_NEWPROT);
- return(pte);
-}
-
-static inline pte_t pte_mknewpage(pte_t pte)
-{
- pte_set_bits(pte, _PAGE_NEWPAGE);
- return(pte);
-}
-
-static inline void set_pte(pte_t *pteptr, pte_t pteval)
-{
- pte_copy(*pteptr, pteval);
-
- /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
- * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
- * mapped pages.
- */
-
- *pteptr = pte_mknewpage(*pteptr);
- if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
-}
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
#define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval))
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -98,14 +69,11 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
return pmd;
}
-static inline void pmd_free(pmd_t *pmd){
- free_page((unsigned long) pmd);
+extern inline void pud_clear (pud_t *pud)
+{
+ set_pud(pud, __pud(0));
}
-#define __pmd_free_tlb(tlb,x) do { } while (0)
-
-static inline void pud_clear (pud_t * pud) { }
-
#define pud_page(pud) \
((struct page *) __va(pud_val(pud) & PAGE_MASK))
@@ -113,13 +81,6 @@ static inline void pud_clear (pud_t * pud) { }
#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
pmd_index(address))
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-
-static inline int pte_none(pte_t pte)
-{
- return pte_is_zero(pte);
-}
-
static inline unsigned long pte_pfn(pte_t pte)
{
return phys_to_pfn(pte_val(pte));
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index a88040920311..ed06170e0edd 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -16,13 +16,15 @@
#define _PAGE_PRESENT 0x001
#define _PAGE_NEWPAGE 0x002
-#define _PAGE_NEWPROT 0x004
-#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */
-#define _PAGE_PROTNONE 0x010 /* If not present */
+#define _PAGE_NEWPROT 0x004
#define _PAGE_RW 0x020
#define _PAGE_USER 0x040
#define _PAGE_ACCESSED 0x080
#define _PAGE_DIRTY 0x100
+/* If _PAGE_PRESENT is clear, we use these: */
+#define _PAGE_FILE 0x008 /* nonlinear file mapping, saved PTE; unset:swap */
+#define _PAGE_PROTNONE 0x010 /* if the user mapped it with PROT_NONE;
+ pte_present gives true */
#ifdef CONFIG_3_LEVEL_PGTABLES
#include "asm/pgtable-3level.h"
@@ -151,10 +153,24 @@ extern unsigned long pg0[1024];
#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
+#define pte_page(x) pfn_to_page(pte_pfn(x))
#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
#define mk_phys(a, r) ((a) + (((unsigned long) r) << REGION_SHIFT))
#define phys_addr(p) ((p) & ~REGION_MASK)
+#define pte_present(x) pte_get_bits(x, (_PAGE_PRESENT | _PAGE_PROTNONE))
+
+/*
+ * =================================
+ * Flags checking section.
+ * =================================
+ */
+
+static inline int pte_none(pte_t pte)
+{
+ return pte_is_zero(pte);
+}
+
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
@@ -210,6 +226,18 @@ static inline int pte_newprot(pte_t pte)
return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
}
+/*
+ * =================================
+ * Flags setting section.
+ * =================================
+ */
+
+static inline pte_t pte_mknewprot(pte_t pte)
+{
+ pte_set_bits(pte, _PAGE_NEWPROT);
+ return(pte);
+}
+
static inline pte_t pte_rdprotect(pte_t pte)
{
pte_clear_bits(pte, _PAGE_USER);
@@ -278,14 +306,42 @@ static inline pte_t pte_mkuptodate(pte_t pte)
return(pte);
}
-extern phys_t page_to_phys(struct page *page);
+static inline pte_t pte_mknewpage(pte_t pte)
+{
+ pte_set_bits(pte, _PAGE_NEWPAGE);
+ return(pte);
+}
+
+static inline void set_pte(pte_t *pteptr, pte_t pteval)
+{
+ pte_copy(*pteptr, pteval);
+
+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
+ * mapped pages.
+ */
+
+ *pteptr = pte_mknewpage(*pteptr);
+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
+}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
-extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
+#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
+#define __virt_to_page(virt) phys_to_page(__pa(virt))
+#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
+
+#define mk_pte(page, pgprot) \
+ ({ pte_t pte; \
+ \
+ pte_set_val(pte, page_to_phys(page), (pgprot)); \
+ if (pte_present(pte)) \
+ pte_mknewprot(pte_mknewpage(pte)); \
+ pte;})
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
@@ -362,8 +418,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#endif
#endif
-extern struct page *phys_to_page(const unsigned long phys);
-extern struct page *__virt_to_page(const unsigned long virt);
#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
/*
diff --git a/include/asm-um/spinlock_types.h b/include/asm-um/spinlock_types.h
new file mode 100644
index 000000000000..e5a94294bf82
--- /dev/null
+++ b/include/asm-um/spinlock_types.h
@@ -0,0 +1,6 @@
+#ifndef __UM_SPINLOCK_TYPES_H
+#define __UM_SPINLOCK_TYPES_H
+
+#include "asm/arch/spinlock_types.h"
+
+#endif
diff --git a/include/asm-v850/auxvec.h b/include/asm-v850/auxvec.h
new file mode 100644
index 000000000000..f493232d0224
--- /dev/null
+++ b/include/asm-v850/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __V850_AUXVEC_H__
+#define __V850_AUXVEC_H__
+
+#endif /* __V850_AUXVEC_H__ */
diff --git a/include/asm-v850/fcntl.h b/include/asm-v850/fcntl.h
index 31d4b5961221..3af4d56776dd 100644
--- a/include/asm-v850/fcntl.h
+++ b/include/asm-v850/fcntl.h
@@ -1,87 +1,11 @@
#ifndef __V850_FCNTL_H__
#define __V850_FCNTL_H__
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECTORY 040000 /* must be a directory */
#define O_NOFOLLOW 0100000 /* don't follow links */
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0400000
-#define O_NOATIME 01000000
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
+#include <asm-generic/fcntl.h>
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
#endif /* __V850_FCNTL_H__ */
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h
new file mode 100644
index 000000000000..2cac5ecd9d00
--- /dev/null
+++ b/include/asm-v850/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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:
+ case FUTEX_OP_ADD:
+ case FUTEX_OP_OR:
+ case FUTEX_OP_ANDN:
+ case FUTEX_OP_XOR:
+ 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
index d6091622935d..b4bc85e7b91a 100644
--- a/include/asm-v850/page.h
+++ b/include/asm-v850/page.h
@@ -98,25 +98,6 @@ typedef unsigned long pgprot_t;
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-#ifndef __ASSEMBLY__
-
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order (unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
-#endif /* !__ASSEMBLY__ */
-
-
/* No current v850 processor has virtual memory. */
#define __virt_to_phys(addr) (addr)
#define __phys_to_virt(addr) (addr)
@@ -144,4 +125,6 @@ extern __inline__ int get_order (unsigned long size)
#endif /* KERNEL */
+#include <asm-generic/page.h>
+
#endif /* __V850_PAGE_H__ */
diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
index 213b852af53e..0240d366a0a4 100644
--- a/include/asm-v850/socket.h
+++ b/include/asm-v850/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-v850/types.h b/include/asm-v850/types.h
index e7cfe5b33a10..dcef57196875 100644
--- a/include/asm-v850/types.h
+++ b/include/asm-v850/types.h
@@ -59,8 +59,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
index 4386cfc6a8dd..188b28597cf1 100644
--- a/include/asm-v850/uaccess.h
+++ b/include/asm-v850/uaccess.h
@@ -27,12 +27,6 @@ extern inline int access_ok (int type, const void *addr, unsigned long size)
return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
}
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area (int type, const void *addr, unsigned long size)
-{
- return access_ok (type, addr, size) ? 0 : -EFAULT;
-}
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index dc8c981af27f..aa1c7b2e438c 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -101,7 +101,7 @@ __acpi_release_global_lock (unsigned int *lock)
:"=r"(n_hi), "=r"(n_lo) \
:"0"(n_hi), "1"(n_lo))
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern int acpi_lapic;
extern int acpi_ioapic;
extern int acpi_noirq;
@@ -121,17 +121,6 @@ static inline void disable_acpi(void)
#define FIX_ACPI_PAGES 4
extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq);
-
-#else /* !CONFIG_ACPI_BOOT */
-#define acpi_lapic 0
-#define acpi_ioapic 0
-#endif /* !CONFIG_ACPI_BOOT */
-
-extern int acpi_numa;
-extern int acpi_scan_nodes(unsigned long start, unsigned long end);
-#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
-
-#ifdef CONFIG_ACPI_PCI
static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
static inline void acpi_disable_pci(void)
{
@@ -139,11 +128,19 @@ static inline void acpi_disable_pci(void)
acpi_noirq_set();
}
extern int acpi_irq_balance_set(char *str);
-#else
+
+#else /* !CONFIG_ACPI */
+
+#define acpi_lapic 0
+#define acpi_ioapic 0
static inline void acpi_noirq_set(void) { }
static inline void acpi_disable_pci(void) { }
-static inline int acpi_irq_balance_set(char *str) { return 0; }
-#endif
+
+#endif /* !CONFIG_ACPI */
+
+extern int acpi_numa;
+extern int acpi_scan_nodes(unsigned long start, unsigned long end);
+#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
#ifdef CONFIG_ACPI_SLEEP
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 16ec82e16b21..6c5d5ca8383a 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -109,9 +109,10 @@ extern unsigned int nmi_watchdog;
#define NMI_LOCAL_APIC 2
#define NMI_INVALID 3
+extern int disable_timer_pin_1;
+
#endif /* CONFIG_X86_LOCAL_APIC */
-#define esr_disable 0
extern unsigned boot_cpu_id;
#endif /* __ASM_APIC_H */
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 9388062c4f6e..fb1c99ac669f 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -113,6 +113,7 @@
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
#define MAX_IO_APICS 128
+#define MAX_LOCAL_APIC 256
/*
* All x86-64 systems are xAPIC compatible.
diff --git a/include/asm-x86_64/auxvec.h b/include/asm-x86_64/auxvec.h
new file mode 100644
index 000000000000..2403c4cfced2
--- /dev/null
+++ b/include/asm-x86_64/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_X86_64_AUXVEC_H
+#define __ASM_X86_64_AUXVEC_H
+
+#endif
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index eed785667289..80ac1fe966ac 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -9,10 +9,8 @@
*/
struct bug_frame {
unsigned char ud2[2];
- unsigned char mov;
- /* should use 32bit offset instead, but the assembler doesn't
- like it */
- char *filename;
+ unsigned char push;
+ signed int filename;
unsigned char ret;
unsigned short line;
} __attribute__((packed));
@@ -25,8 +23,8 @@ struct bug_frame {
The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
#define BUG() \
asm volatile( \
- "ud2 ; .byte 0xa3 ; .quad %c1 ; .byte 0xc2 ; .short %c0" :: \
- "i"(__LINE__), "i" (__stringify(__FILE__)))
+ "ud2 ; pushq $%c1 ; ret $%c0" :: \
+ "i"(__LINE__), "i" (__FILE__))
void out_of_line_bug(void);
#else
static inline void out_of_line_bug(void) { }
diff --git a/include/asm-x86_64/calling.h b/include/asm-x86_64/calling.h
index 0bc12655fa5b..fc2c5a6c262a 100644
--- a/include/asm-x86_64/calling.h
+++ b/include/asm-x86_64/calling.h
@@ -65,27 +65,36 @@
.if \skipr11
.else
movq (%rsp),%r11
+ CFI_RESTORE r11
.endif
.if \skipr8910
.else
movq 1*8(%rsp),%r10
+ CFI_RESTORE r10
movq 2*8(%rsp),%r9
+ CFI_RESTORE r9
movq 3*8(%rsp),%r8
+ CFI_RESTORE r8
.endif
.if \skiprax
.else
movq 4*8(%rsp),%rax
+ CFI_RESTORE rax
.endif
.if \skiprcx
.else
movq 5*8(%rsp),%rcx
+ CFI_RESTORE rcx
.endif
.if \skiprdx
.else
movq 6*8(%rsp),%rdx
+ CFI_RESTORE rdx
.endif
movq 7*8(%rsp),%rsi
+ CFI_RESTORE rsi
movq 8*8(%rsp),%rdi
+ CFI_RESTORE rdi
.if ARG_SKIP+\addskip > 0
addq $ARG_SKIP+\addskip,%rsp
CFI_ADJUST_CFA_OFFSET -(ARG_SKIP+\addskip)
@@ -124,11 +133,17 @@
.macro RESTORE_REST
movq (%rsp),%r15
+ CFI_RESTORE r15
movq 1*8(%rsp),%r14
+ CFI_RESTORE r14
movq 2*8(%rsp),%r13
+ CFI_RESTORE r13
movq 3*8(%rsp),%r12
+ CFI_RESTORE r12
movq 4*8(%rsp),%rbp
+ CFI_RESTORE rbp
movq 5*8(%rsp),%rbx
+ CFI_RESTORE rbx
addq $REST_SKIP,%rsp
CFI_ADJUST_CFA_OFFSET -(REST_SKIP)
.endm
@@ -146,11 +161,3 @@
.macro icebp
.byte 0xf1
.endm
-
-#ifdef CONFIG_FRAME_POINTER
-#define ENTER enter
-#define LEAVE leave
-#else
-#define ENTER
-#define LEAVE
-#endif
diff --git a/include/asm-x86_64/checksum.h b/include/asm-x86_64/checksum.h
index d01356f01448..989469e8e0b7 100644
--- a/include/asm-x86_64/checksum.h
+++ b/include/asm-x86_64/checksum.h
@@ -64,7 +64,7 @@ static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
" adcl $0, %0\n"
" notl %0\n"
"2:"
- /* Since the input registers which are loaded with iph and ipl
+ /* Since the input registers which are loaded with iph and ihl
are modified, we must also specify them as outputs, or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl)
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index d0f453c5adfc..f0155c38f639 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -14,10 +14,10 @@ typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
-typedef u16 compat_uid_t;
-typedef u16 compat_gid_t;
-typedef u32 compat_uid32_t;
-typedef u32 compat_gid32_t;
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u16 compat_dev_t;
@@ -52,8 +52,8 @@ struct compat_stat {
compat_ino_t st_ino;
compat_mode_t st_mode;
compat_nlink_t st_nlink;
- compat_uid_t st_uid;
- compat_gid_t st_gid;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
compat_dev_t st_rdev;
u16 __pad2;
u32 st_size;
@@ -122,10 +122,10 @@ typedef u32 compat_sigset_word;
struct compat_ipc64_perm {
compat_key_t key;
- compat_uid32_t uid;
- compat_gid32_t gid;
- compat_uid32_t cuid;
- compat_gid32_t cgid;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
unsigned short mode;
unsigned short __pad1;
unsigned short seq;
diff --git a/include/asm-x86_64/current.h b/include/asm-x86_64/current.h
index 7db560ee6f70..bc8adecee66d 100644
--- a/include/asm-x86_64/current.h
+++ b/include/asm-x86_64/current.h
@@ -17,7 +17,7 @@ static inline struct task_struct *get_current(void)
#else
#ifndef ASM_OFFSET_H
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
#endif
#define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index c89b58bebee2..594e610f4a1e 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -191,7 +191,7 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
/*
* load one particular LDT into the current CPU
*/
-extern inline void load_LDT_nolock (mm_context_t *pc, int cpu)
+static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
{
int count = pc->size;
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index a416dc31634a..e784fdc524f1 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -85,6 +85,11 @@ static inline void dma_sync_single_for_device(struct device *hwdev,
flush_write_buffers();
}
+#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir) \
+ dma_sync_single_for_cpu(dev, dma_handle, size, dir)
+#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir) \
+ dma_sync_single_for_device(dev, dma_handle, size, dir)
+
static inline void dma_sync_sg_for_cpu(struct device *hwdev,
struct scatterlist *sg,
int nelems, int direction)
diff --git a/include/asm-x86_64/dwarf2.h b/include/asm-x86_64/dwarf2.h
index afd4212e860b..582757fc0365 100644
--- a/include/asm-x86_64/dwarf2.h
+++ b/include/asm-x86_64/dwarf2.h
@@ -24,6 +24,10 @@
#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
#define CFI_OFFSET .cfi_offset
#define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
#else
@@ -36,6 +40,10 @@
#define CFI_ADJUST_CFA_OFFSET #
#define CFI_OFFSET #
#define CFI_REL_OFFSET #
+#define CFI_REGISTER #
+#define CFI_RESTORE #
+#define CFI_REMEMBER_STATE #
+#define CFI_RESTORE_STATE #
#endif
diff --git a/include/asm-x86_64/fcntl.h b/include/asm-x86_64/fcntl.h
index 4411f221c037..46ab12db5739 100644
--- a/include/asm-x86_64/fcntl.h
+++ b/include/asm-x86_64/fcntl.h
@@ -1,76 +1 @@
-#ifndef _X86_64_FCNTL_H
-#define _X86_64_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif /* !_X86_64_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index cf8b16cbe8db..a582cfcf2231 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void);
* directly without translation, we catch the bug with a NULL-deference
* kernel oops. Illegal ranges of incoming indices are caught too.
*/
-extern inline unsigned long fix_to_virt(const unsigned int idx)
+static inline unsigned long fix_to_virt(const unsigned int idx)
{
/*
* this branch gets completely eliminated after inlining,
diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h
new file mode 100644
index 000000000000..8602c09bf89e
--- /dev/null
+++ b/include/asm-x86_64/futex.h
@@ -0,0 +1,98 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile ( \
+"1: " insn "\n" \
+"2: .section .fixup,\"ax\"\n\
+3: mov %3, %1\n\
+ jmp 2b\n\
+ .previous\n\
+ .section __ex_table,\"a\"\n\
+ .align 8\n\
+ .quad 1b,3b\n\
+ .previous" \
+ : "=r" (oldval), "=r" (ret), "=m" (*uaddr) \
+ : "i" (-EFAULT), "m" (*uaddr), "0" (oparg), "1" (0))
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile ( \
+"1: movl %2, %0\n\
+ movl %0, %3\n" \
+ insn "\n" \
+"2: " LOCK_PREFIX "cmpxchgl %3, %2\n\
+ jnz 1b\n\
+3: .section .fixup,\"ax\"\n\
+4: mov %5, %1\n\
+ jmp 3b\n\
+ .previous\n\
+ .section __ex_table,\"a\"\n\
+ .align 8\n\
+ .quad 1b,4b,2b,4b\n\
+ .previous" \
+ : "=&a" (oldval), "=&r" (ret), "=m" (*uaddr), \
+ "=&r" (tem) \
+ : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0))
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+ 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_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
+ uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op2("orl %4, %3", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op2("andl %4, %3", ret, oldval, uaddr, ~oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op2("xorl %4, %3", ret, oldval, 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;
+}
+
+#endif
+#endif
diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
index 27c381fa1c9d..8661b476fb40 100644
--- a/include/asm-x86_64/hardirq.h
+++ b/include/asm-x86_64/hardirq.h
@@ -9,11 +9,12 @@
#define __ARCH_IRQ_STAT 1
-/* Generate a lvalue for a pda member. Should fix softirq.c instead to use
- special access macros. This would generate better code. */
-#define __IRQ_STAT(cpu,member) (read_pda(me)->member)
+#define local_softirq_pending() read_pda(__softirq_pending)
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#define __ARCH_SET_SOFTIRQ_PENDING 1
+
+#define set_softirq_pending(x) write_pda(__softirq_pending, (x))
+#define or_softirq_pending(x) or_pda(__softirq_pending, (x))
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
diff --git a/include/asm-x86_64/hdreg.h b/include/asm-x86_64/hdreg.h
deleted file mode 100644
index 5989bbc97cbf..000000000000
--- a/include/asm-x86_64/hdreg.h
+++ /dev/null
@@ -1 +0,0 @@
-#warning this file is obsolete, please do not use it
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 2b5cb2865d21..dc97668ea0f9 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -26,6 +26,7 @@
struct hw_interrupt_type;
#endif
+#define NMI_VECTOR 0x02
/*
* IDT vectors usable for external interrupt sources start
* at 0x20:
@@ -50,14 +51,15 @@ struct hw_interrupt_type;
*/
#define SPURIOUS_APIC_VECTOR 0xff
#define ERROR_APIC_VECTOR 0xfe
-#define INVALIDATE_TLB_VECTOR 0xfd
-#define RESCHEDULE_VECTOR 0xfc
-#define TASK_MIGRATION_VECTOR 0xfb
-#define CALL_FUNCTION_VECTOR 0xfa
-#define KDB_VECTOR 0xf9
-
-#define THERMAL_APIC_VECTOR 0xf0
-
+#define RESCHEDULE_VECTOR 0xfd
+#define CALL_FUNCTION_VECTOR 0xfc
+#define KDB_VECTOR 0xfb /* reserved for KDB */
+#define THERMAL_APIC_VECTOR 0xfa
+/* 0xf9 free */
+#define INVALIDATE_TLB_VECTOR_END 0xf8
+#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */
+
+#define NUM_INVALIDATE_TLB_VECTORS 8
/*
* Local APIC timer IRQ vector is on a different priority level,
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 37fc3f149a5a..52ff269fe054 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -48,7 +48,7 @@
* Talk about misusing macros..
*/
#define __OUT1(s,x) \
-extern inline void out##s(unsigned x value, unsigned short port) {
+static inline void out##s(unsigned x value, unsigned short port) {
#define __OUT2(s,s1,s2) \
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
@@ -58,7 +58,7 @@ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
#define __IN1(s) \
-extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
#define __IN2(s,s1,s2) \
__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
@@ -68,12 +68,12 @@ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
#define __INS(s) \
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
{ __asm__ __volatile__ ("rep ; ins" #s \
: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
#define __OUTS(s) \
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
{ __asm__ __volatile__ ("rep ; outs" #s \
: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
@@ -110,12 +110,12 @@ __OUTS(l)
* Change virtual addresses to physical addresses and vv.
* These are pretty trivial
*/
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
{
return __pa(address);
}
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
{
return __va(address);
}
@@ -130,7 +130,7 @@ extern inline void * phys_to_virt(unsigned long address)
extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, 0);
}
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index a8babd2bbe84..ee1bc69aec9c 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -201,7 +201,7 @@ extern int skip_ioapic_setup;
*/
#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
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);
diff --git a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h
index 5e166b9d3bde..022e9d340ad7 100644
--- a/include/asm-x86_64/ipi.h
+++ b/include/asm-x86_64/ipi.h
@@ -31,9 +31,20 @@
static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
{
- unsigned int icr = APIC_DM_FIXED | shortcut | vector | dest;
- if (vector == KDB_VECTOR)
- icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
+ unsigned int icr = shortcut | dest;
+
+ switch (vector) {
+ default:
+ icr |= APIC_DM_FIXED | vector;
+ break;
+ case NMI_VECTOR:
+ /*
+ * Setup KDB IPI to be delivered as an NMI
+ */
+ case KDB_VECTOR:
+ icr |= APIC_DM_NMI;
+ break;
+ }
return icr;
}
@@ -66,7 +77,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
- apic_write_around(APIC_ICR, cfg);
+ apic_write(APIC_ICR, cfg);
}
@@ -92,7 +103,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
* prepare target chip field
*/
cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
- apic_write_around(APIC_ICR2, cfg);
+ apic_write(APIC_ICR2, cfg);
/*
* program the ICR
@@ -102,7 +113,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
- apic_write_around(APIC_ICR, cfg);
+ apic_write(APIC_ICR, cfg);
}
local_irq_restore(flags);
}
diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
index 4482657777bb..fb724ba37ae6 100644
--- a/include/asm-x86_64/irq.h
+++ b/include/asm-x86_64/irq.h
@@ -48,10 +48,6 @@ static __inline__ int irq_canonicalize(int irq)
#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
#endif
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#ifdef CONFIG_HOTPLUG_CPU
#include <linux/cpumask.h>
extern void fixup_irqs(cpumask_t map);
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index b90341994d80..f604e84c5303 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -46,7 +46,7 @@ extern void die(const char *,struct pt_regs *,long);
extern void __die(const char *,struct pt_regs *,long);
extern void show_registers(struct pt_regs *regs);
extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
#endif
diff --git a/include/asm-x86_64/local.h b/include/asm-x86_64/local.h
index c954f15c1a75..3e72c41727c5 100644
--- a/include/asm-x86_64/local.h
+++ b/include/asm-x86_64/local.h
@@ -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(unsigned int 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(unsigned int i, local_t *v)
{
__asm__ __volatile__(
"subl %1,%0"
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 768413751b34..b40c661f111e 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -12,7 +12,7 @@
#include <asm/smp.h>
-#define NODEMAPSIZE 0xff
+#define NODEMAPSIZE 0xfff
/* Simple perfect hash to map physical addresses to node numbers */
extern int memnode_shift;
@@ -54,7 +54,7 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
#define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \
({ u8 nid__ = pfn_to_nid(pfn); \
- nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
+ nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); }))
#endif
#define local_mapnr(kvaddr) \
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
index 331f6a3c72a2..f267e10c023d 100644
--- a/include/asm-x86_64/mpspec.h
+++ b/include/asm-x86_64/mpspec.h
@@ -179,7 +179,7 @@ extern int mpc_default_type;
extern unsigned long mp_lapic_addr;
extern int pic_mode;
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
extern void mp_register_lapic (u8 id, u8 enabled);
extern void mp_register_lapic_address (u64 address);
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index ba15279a79d0..4d727f3f5550 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -29,22 +29,37 @@
#define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32)
/* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__; \
- asm volatile("2: wrmsr ; xorl %0,%0\n" \
- "1:\n\t" \
- ".section .fixup,\"ax\"\n\t" \
- "3: movl %4,%0 ; jmp 1b\n\t" \
- ".previous\n\t" \
- ".section __ex_table,\"a\"\n" \
- " .align 8\n\t" \
- " .quad 2b,3b\n\t" \
- ".previous" \
- : "=a" (ret__) \
- : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
+#define wrmsr_safe(msr,a,b) ({ int ret__; \
+ asm volatile("2: wrmsr ; xorl %0,%0\n" \
+ "1:\n\t" \
+ ".section .fixup,\"ax\"\n\t" \
+ "3: movl %4,%0 ; jmp 1b\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n\t" \
+ " .quad 2b,3b\n\t" \
+ ".previous" \
+ : "=a" (ret__) \
+ : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
ret__; })
#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
+#define rdmsr_safe(msr,a,b) \
+ ({ int ret__; \
+ asm volatile ("1: rdmsr\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: movl %4,%0\n" \
+ " jmp 2b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 1b,3b\n" \
+ ".previous":"=&bDS" (ret__), "=a"(a), "=d"(b)\
+ :"c"(msr), "i"(-EIO), "0"(0)); \
+ ret__; })
+
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
@@ -64,7 +79,7 @@
: "=a" (low), "=d" (high) \
: "c" (counter))
-extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
__asm__("cpuid"
@@ -90,7 +105,7 @@ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
/*
* CPUID functions returning a single datum
*/
-extern inline unsigned int cpuid_eax(unsigned int op)
+static inline unsigned int cpuid_eax(unsigned int op)
{
unsigned int eax;
@@ -100,7 +115,7 @@ extern inline unsigned int cpuid_eax(unsigned int op)
: "bx", "cx", "dx");
return eax;
}
-extern inline unsigned int cpuid_ebx(unsigned int op)
+static inline unsigned int cpuid_ebx(unsigned int op)
{
unsigned int eax, ebx;
@@ -110,7 +125,7 @@ extern inline unsigned int cpuid_ebx(unsigned int op)
: "cx", "dx" );
return ebx;
}
-extern inline unsigned int cpuid_ecx(unsigned int op)
+static inline unsigned int cpuid_ecx(unsigned int op)
{
unsigned int eax, ecx;
@@ -120,7 +135,7 @@ extern inline unsigned int cpuid_ecx(unsigned int op)
: "bx", "dx" );
return ecx;
}
-extern inline unsigned int cpuid_edx(unsigned int op)
+static inline unsigned int cpuid_edx(unsigned int op)
{
unsigned int eax, edx;
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index 5c363a1482e4..bcf55c3f7f7f 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -9,6 +9,7 @@ struct node {
};
extern int compute_hash_shift(struct node *nodes, int numnodes);
+extern int pxm_to_node(int nid);
#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
@@ -16,6 +17,8 @@ extern void numa_add_cpu(int cpu);
extern void numa_init_array(void);
extern int numa_off;
+extern unsigned char apicid_to_node[256];
+
#define NUMA_NO_NODE 0xff
#endif
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 431318764af6..e5ab4d231f2c 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -28,11 +28,12 @@
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
+extern unsigned long end_pfn;
+
void clear_page(void *);
void copy_page(void *, void *);
@@ -92,20 +93,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#include <asm/bug.h>
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
#endif /* __ASSEMBLY__ */
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
@@ -126,7 +113,7 @@ extern __inline__ int get_order(unsigned long size)
#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)
+#define pfn_valid(pfn) ((pfn) < end_pfn)
#endif
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
@@ -141,4 +128,6 @@ extern __inline__ int get_order(unsigned long size)
#endif /* __KERNEL__ */
+#include <asm-generic/page.h>
+
#endif /* _X86_64_PAGE_H */
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index eeb3088a1c9e..5a82a6762c21 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -50,10 +50,10 @@ extern int iommu_setup(char *opt);
* address space. The networking and block device layers use
* this boolean for bounce buffer decisions
*
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
+ * On x86-64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an hard or soft IOMMU is available.
*/
-#define PCI_DMA_BUS_IS_PHYS (no_iommu ? 1 : 0)
+#define PCI_DMA_BUS_IS_PHYS 0
/*
* x86-64 always supports DAC, but sometimes it is useful to force
diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h
index 36b766cfc4d5..bbf89aa8a1af 100644
--- a/include/asm-x86_64/pda.h
+++ b/include/asm-x86_64/pda.h
@@ -10,10 +10,8 @@
struct x8664_pda {
struct task_struct *pcurrent; /* Current process */
unsigned long data_offset; /* Per cpu data offset from linker address */
- struct x8664_pda *me; /* Pointer to itself */
unsigned long kernelstack; /* top of kernel stack for current */
unsigned long oldrsp; /* user rsp for system call */
- unsigned long irqrsp; /* Old rsp for interrupts. */
int irqcount; /* Irq nesting counter. Starts with -1 */
int cpunumber; /* Logical CPU number */
char *irqstackptr; /* top of irqstack */
@@ -22,7 +20,7 @@ struct x8664_pda {
struct mm_struct *active_mm;
int mmu_state;
unsigned apic_timer_irqs;
-} ____cacheline_aligned;
+} ____cacheline_aligned_in_smp;
#define IRQSTACK_ORDER 2
@@ -42,13 +40,14 @@ extern void __bad_pda_field(void);
#define pda_offset(field) offsetof(struct x8664_pda, field)
#define pda_to_op(op,field,val) do { \
+ typedef typeof_field(struct x8664_pda, field) T__; \
switch (sizeof_field(struct x8664_pda, field)) { \
case 2: \
-asm volatile(op "w %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
case 4: \
-asm volatile(op "l %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
case 8: \
-asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
default: __bad_pda_field(); \
} \
} while (0)
@@ -58,7 +57,7 @@ asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); bre
* Unfortunately removing them causes all hell to break lose currently.
*/
#define pda_from_op(op,field) ({ \
- typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \
+ typeof_field(struct x8664_pda, field) ret__; \
switch (sizeof_field(struct x8664_pda, field)) { \
case 2: \
asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
@@ -75,6 +74,7 @@ asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); b
#define write_pda(field,val) pda_to_op("mov",field,val)
#define add_pda(field,val) pda_to_op("add",field,val)
#define sub_pda(field,val) pda_to_op("sub",field,val)
+#define or_pda(field,val) pda_to_op("or",field,val)
#endif
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
index deadd146978b..08cad2482bcb 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -18,12 +18,12 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
}
-extern __inline__ pmd_t *get_pmd(void)
+static inline pmd_t *get_pmd(void)
{
return (pmd_t *)get_zeroed_page(GFP_KERNEL);
}
-extern __inline__ void pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
{
BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
free_page((unsigned long)pmd);
@@ -86,13 +86,13 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
/* Should really implement gc for free page table pages. This could be
done with a reference count in struct page. */
-extern __inline__ void pte_free_kernel(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
{
BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
free_page((unsigned long)pte);
}
-extern inline void pte_free(struct page *pte)
+static inline void pte_free(struct page *pte)
{
__free_page(pte);
}
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 4e167b5ea8f3..2cb483516459 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -85,7 +85,7 @@ static inline void set_pud(pud_t *dst, pud_t val)
pud_val(*dst) = pud_val(val);
}
-extern inline void pud_clear (pud_t *pud)
+static inline void pud_clear (pud_t *pud)
{
set_pud(pud, __pud(0));
}
@@ -95,7 +95,7 @@ static inline void set_pgd(pgd_t *dst, pgd_t val)
pgd_val(*dst) = pgd_val(val);
}
-extern inline void pgd_clear (pgd_t * pgd)
+static inline void pgd_clear (pgd_t * pgd)
{
set_pgd(pgd, __pgd(0));
}
@@ -104,6 +104,19 @@ extern inline void pgd_clear (pgd_t * pgd)
((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0))
+
+static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
+{
+ pte_t pte;
+ if (full) {
+ pte = *ptep;
+ *ptep = __pte(0);
+ } else {
+ pte = ptep_get_and_clear(mm, addr, ptep);
+ }
+ return pte;
+}
+
#define pte_same(a, b) ((a).pte == (b).pte)
#define PMD_SIZE (1UL << PMD_SHIFT)
@@ -143,7 +156,7 @@ extern inline void pgd_clear (pgd_t * pgd)
#define _PAGE_ACCESSED 0x020
#define _PAGE_DIRTY 0x040
#define _PAGE_PSE 0x080 /* 2MB page */
-#define _PAGE_FILE 0x040 /* set:pagecache, unset:swap */
+#define _PAGE_FILE 0x040 /* nonlinear file mapping, saved PTE; unset:swap */
#define _PAGE_GLOBAL 0x100 /* Global TLB entry */
#define _PAGE_PROTNONE 0x080 /* If not present */
@@ -247,6 +260,7 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
+#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
@@ -254,8 +268,8 @@ extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_huge(pte_t pte) { return (pte_val(pte) & __LARGE_PTE) == __LARGE_PTE; }
-#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
extern inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
extern inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
@@ -361,7 +375,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
}
/* Change flags of a PTE */
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
pte_val(pte) &= _PAGE_CHG_MASK;
pte_val(pte) |= pgprot_val(newprot);
@@ -407,9 +421,6 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
extern int kern_addr_valid(unsigned long addr);
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
@@ -433,6 +444,7 @@ extern int kern_addr_valid(unsigned long addr);
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 85549e656eeb..03837d34fba0 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -254,7 +254,13 @@ struct thread_struct {
u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
} __attribute__((aligned(16)));
-#define INIT_THREAD {}
+#define INIT_THREAD { \
+ .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+#define INIT_TSS { \
+ .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
#define INIT_MMAP \
{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
@@ -375,13 +381,13 @@ struct extended_sigtable {
#define ASM_NOP_MAX 8
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-extern inline void rep_nop(void)
+static inline void rep_nop(void)
{
__asm__ __volatile__("rep;nop": : :"memory");
}
/* Stop speculative execution */
-extern inline void sync_core(void)
+static inline void sync_core(void)
{
int tmp;
asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
@@ -398,7 +404,7 @@ static inline void prefetch(void *x)
#define ARCH_HAS_PREFETCHW 1
static inline void prefetchw(void *x)
{
- alternative_input(ASM_NOP5,
+ alternative_input("prefetcht0 (%1)",
"prefetchw (%1)",
X86_FEATURE_3DNOW,
"r" (x));
@@ -437,6 +443,11 @@ static inline void prefetchw(void *x)
outb((data), 0x23); \
} while (0)
+static inline void serialize_cpu(void)
+{
+ __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+}
+
static inline void __monitor(const void *eax, unsigned long ecx,
unsigned long edx)
{
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 6c813eb521f3..dbb37b0adb43 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -8,7 +8,6 @@
struct cpuinfo_x86;
struct pt_regs;
-extern void get_cpu_vendor(struct cpuinfo_x86*);
extern void start_kernel(void);
extern void pda_init(int);
@@ -75,9 +74,6 @@ extern void acpi_reserve_bootmem(void);
extern void swap_low_mappings(void);
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
extern void __show_regs(struct pt_regs * regs);
extern void show_regs(struct pt_regs * regs);
@@ -94,8 +90,6 @@ extern int unhandled_signal(struct task_struct *tsk, int sig);
extern void select_idle_routine(const struct cpuinfo_x86 *c);
extern void swiotlb_init(void);
-extern unsigned long max_mapnr;
-extern unsigned long end_pfn;
extern unsigned long table_start, table_end;
extern int exception_trace;
diff --git a/include/asm-x86_64/signal.h b/include/asm-x86_64/signal.h
index fe9b96d94815..f8d55798535a 100644
--- a/include/asm-x86_64/signal.h
+++ b/include/asm-x86_64/signal.h
@@ -143,23 +143,23 @@ typedef struct sigaltstack {
#undef __HAVE_ARCH_SIG_BITOPS
#if 0
-extern __inline__ void sigaddset(sigset_t *set, int _sig)
+static inline void sigaddset(sigset_t *set, int _sig)
{
__asm__("btsq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}
-extern __inline__ void sigdelset(sigset_t *set, int _sig)
+static inline void sigdelset(sigset_t *set, int _sig)
{
__asm__("btrq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}
-extern __inline__ int __const_sigismember(sigset_t *set, int _sig)
+static inline int __const_sigismember(sigset_t *set, int _sig)
{
unsigned long sig = _sig - 1;
return 1 & (set->sig[sig / _NSIG_BPW] >> (sig & ~(_NSIG_BPW-1)));
}
-extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
+static inline int __gen_sigismember(sigset_t *set, int _sig)
{
int ret;
__asm__("btq %2,%1\n\tsbbq %0,%0"
@@ -172,7 +172,7 @@ extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
__const_sigismember((set),(sig)) : \
__gen_sigismember((set),(sig)))
-extern __inline__ int sigfindinword(unsigned long word)
+static inline int sigfindinword(unsigned long word)
{
__asm__("bsfq %1,%0" : "=r"(word) : "rm"(word) : "cc");
return word;
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index de8b57b2b62b..24e32611f0bf 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -72,7 +72,7 @@ static inline int num_booting_cpus(void)
#define raw_smp_processor_id() read_pda(cpunumber)
-extern __inline int hard_smp_processor_id(void)
+static inline int hard_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
diff --git a/include/asm-x86_64/socket.h b/include/asm-x86_64/socket.h
index d9a252ea8210..f2cdbeae5d5b 100644
--- a/include/asm-x86_64/socket.h
+++ b/include/asm-x86_64/socket.h
@@ -14,6 +14,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 5aeb57a3baad..69636831ad2f 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -6,47 +6,21 @@
#include <asm/page.h>
#include <linux/config.h>
-extern int printk(const char * fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
*/
-#define spin_is_locked(x) (*(volatile signed char *)(&(x)->lock) <= 0)
-#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) \
+ (*(volatile signed char *)(&(x)->slock) <= 0)
-#define spin_lock_string \
+#define __raw_spin_lock_string \
"\n1:\t" \
"lock ; decb %0\n\t" \
"js 2f\n" \
@@ -58,74 +32,40 @@ typedef struct {
"jmp 1b\n" \
LOCK_SECTION_END
-/*
- * This works. Despite all the confusion.
- * (except on PPro SMP or if we are using OOSTORE)
- * (PPro errata 66, 92)
- */
-
-#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
-
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
"movb $1,%0" \
- :"=m" (lock->lock) : : "memory"
-
-
-static inline void _raw_spin_unlock(spinlock_t *lock)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(lock->magic != SPINLOCK_MAGIC);
- assert_spin_locked(lock);
-#endif
- __asm__ __volatile__(
- spin_unlock_string
- );
-}
-
-#else
-
-#define spin_unlock_string \
- "xchgb %b0, %1" \
- :"=q" (oldval), "=m" (lock->lock) \
- :"0" (oldval) : "memory"
+ :"=m" (lock->slock) : : "memory"
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
- char oldval = 1;
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(lock->magic != SPINLOCK_MAGIC);
- assert_spin_locked(lock);
-#endif
__asm__ __volatile__(
- spin_unlock_string
- );
+ __raw_spin_lock_string
+ :"=m" (lock->slock) : : "memory");
}
-#endif
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
char oldval;
+
__asm__ __volatile__(
"xchgb %b0,%1"
- :"=q" (oldval), "=m" (lock->lock)
+ :"=q" (oldval), "=m" (lock->slock)
:"0" (0) : "memory");
+
return oldval > 0;
}
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- if (lock->magic != SPINLOCK_MAGIC) {
- printk("eip: %p\n", __builtin_return_address(0));
- BUG();
- }
-#endif
__asm__ __volatile__(
- spin_lock_string
- :"=m" (lock->lock) : : "memory");
+ __raw_spin_unlock_string
+ );
}
+#define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
/*
* Read-write spinlocks, allowing multiple readers
@@ -136,33 +76,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
- */
-typedef struct {
- volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC 0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-#define read_can_lock(x) ((int)(x)->lock > 0)
-#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-
-/*
+ *
* On x86, we implement read-write locks as a 32-bit counter
* with the high bit (sign) being the "contended" bit.
*
@@ -170,29 +84,24 @@ typedef struct {
*
* Changed to use the same technique as rw semaphores. See
* semaphore.h for details. -ben
+ *
+ * the helpers are in arch/i386/kernel/semaphore.c
*/
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
-static inline void _raw_read_lock(rwlock_t *rw)
+#define __raw_read_can_lock(x) ((int)(x)->lock > 0)
+#define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
__build_read_lock(rw, "__read_lock_failed");
}
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
-#ifdef CONFIG_DEBUG_SPINLOCK
- BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
__build_write_lock(rw, "__write_lock_failed");
}
-#define _raw_read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
-#define _raw_write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
-
-static inline int _raw_read_trylock(rwlock_t *lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
atomic_dec(count);
@@ -202,7 +111,7 @@ static inline int _raw_read_trylock(rwlock_t *lock)
return 0;
}
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t *)lock;
if (atomic_sub_and_test(RW_LOCK_BIAS, count))
@@ -211,4 +120,15 @@ static inline int _raw_write_trylock(rwlock_t *lock)
return 0;
}
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+ asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+ asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0"
+ : "=m" (rw->lock) : : "memory");
+}
+
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-x86_64/spinlock_types.h b/include/asm-x86_64/spinlock_types.h
new file mode 100644
index 000000000000..59efe849f351
--- /dev/null
+++ b/include/asm-x86_64/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
+
+#endif
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 8606e170a7dc..85348e02ad2e 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -188,7 +188,7 @@ static inline void write_cr4(unsigned long val)
#define __xg(x) ((volatile long *)(x))
-extern inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
{
*ptr = val;
}
@@ -253,19 +253,19 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
case 2:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
: "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "r"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 4:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
: "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "r"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 8:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
: "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "r"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
}
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 24ecf6a637cb..f971f45d6d78 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -6,7 +6,6 @@
#ifndef _ASMx8664_TIMEX_H
#define _ASMx8664_TIMEX_H
-#include <linux/config.h>
#include <asm/8253pit.h>
#include <asm/msr.h>
#include <asm/vsyscall.h>
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h
index 505b0cf906de..4a9c20ea9b10 100644
--- a/include/asm-x86_64/tlbflush.h
+++ b/include/asm-x86_64/tlbflush.h
@@ -109,6 +109,10 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
#define TLBSTATE_OK 1
#define TLBSTATE_LAZY 2
+/* Roughly an IPI every 20MB with 4k pages for freeing page table
+ ranges. Cost is about 42k of memory for each CPU. */
+#define ARCH_FREE_PTE_NR 5350
+
#endif
#define flush_tlb_kernel_range(start, end) flush_tlb_all()
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index c1bc3fad482e..1c603cd7e4d0 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -13,7 +13,6 @@
extern cpumask_t cpu_online_map;
extern unsigned char cpu_to_node[];
-extern unsigned char pci_bus_to_node[];
extern cpumask_t node_to_cpumask[];
#ifdef CONFIG_ACPI_NUMA
@@ -26,7 +25,7 @@ extern int __node_distance(int, int);
#define parent_node(node) (node)
#define node_to_first_cpu(node) (__ffs(node_to_cpumask[node]))
#define node_to_cpumask(node) (node_to_cpumask[node])
-#define pcibus_to_node(bus) pci_bus_to_node[(bus)->number]
+#define pcibus_to_node(bus) ((long)(bus->sysdata))
#define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus));
/* sched_domains SD_NODE_INIT for x86_64 machines */
diff --git a/include/asm-x86_64/types.h b/include/asm-x86_64/types.h
index 32bd1426b523..c86c2e6793e2 100644
--- a/include/asm-x86_64/types.h
+++ b/include/asm-x86_64/types.h
@@ -51,8 +51,6 @@ typedef u64 dma_addr_t;
typedef u64 sector_t;
#define HAVE_SECTOR_T
-typedef unsigned short kmem_bufctl_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 48f292752c96..1bb8b8a24436 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -49,13 +49,6 @@
#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
-/* this function will go away soon - use access_ok() instead */
-extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
-{
- return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
-
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index 2872da23fc7e..438a3f52f839 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -29,7 +29,6 @@ enum vsyscall_num {
struct vxtime_data {
long hpet_address; /* HPET base address */
- unsigned long hz; /* HPET clocks / sec */
int last;
unsigned long last_tsc;
long quot;
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
index d72bcb32ba4f..24f86f0e43cf 100644
--- a/include/asm-xtensa/atomic.h
+++ b/include/asm-xtensa/atomic.h
@@ -66,7 +66,7 @@ typedef struct { volatile int counter; } atomic_t;
*
* Atomically adds @i to @v.
*/
-extern __inline__ void atomic_add(int i, atomic_t * v)
+static inline void atomic_add(int i, atomic_t * v)
{
unsigned int vval;
@@ -90,7 +90,7 @@ extern __inline__ void atomic_add(int i, atomic_t * v)
*
* Atomically subtracts @i from @v.
*/
-extern __inline__ void atomic_sub(int i, atomic_t *v)
+static inline void atomic_sub(int i, atomic_t *v)
{
unsigned int vval;
@@ -111,7 +111,7 @@ extern __inline__ void atomic_sub(int i, atomic_t *v)
* We use atomic_{add|sub}_return to define other functions.
*/
-extern __inline__ int atomic_add_return(int i, atomic_t * v)
+static inline int atomic_add_return(int i, atomic_t * v)
{
unsigned int vval;
@@ -130,7 +130,7 @@ extern __inline__ int atomic_add_return(int i, atomic_t * v)
return vval;
}
-extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+static inline int atomic_sub_return(int i, atomic_t * v)
{
unsigned int vval;
@@ -224,7 +224,7 @@ extern __inline__ int atomic_sub_return(int i, atomic_t * v)
#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
-extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
{
unsigned int all_f = -1;
unsigned int vval;
@@ -243,7 +243,7 @@ extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
);
}
-extern __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
{
unsigned int vval;
diff --git a/include/asm-xtensa/auxvec.h b/include/asm-xtensa/auxvec.h
new file mode 100644
index 000000000000..257dec75c5af
--- /dev/null
+++ b/include/asm-xtensa/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __XTENSA_AUXVEC_H
+#define __XTENSA_AUXVEC_H
+
+#endif
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
index 1a00fad19929..81a797ae3abe 100644
--- a/include/asm-xtensa/checksum.h
+++ b/include/asm-xtensa/checksum.h
@@ -47,14 +47,14 @@ asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, i
* If you use these functions directly please don't forget the
* verify_area().
*/
-extern __inline__
+static inline
unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
int len, int sum)
{
return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
}
-extern __inline__
+static inline
unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
int len, int sum, int *err_ptr)
{
diff --git a/include/asm-xtensa/delay.h b/include/asm-xtensa/delay.h
index 0a123d53a636..1bc601ec3621 100644
--- a/include/asm-xtensa/delay.h
+++ b/include/asm-xtensa/delay.h
@@ -18,7 +18,7 @@
extern unsigned long loops_per_jiffy;
-extern __inline__ void __delay(unsigned long loops)
+static inline void __delay(unsigned long loops)
{
/* 2 cycles per loop. */
__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
index 48876bb727d2..ec066ae96caf 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/include/asm-xtensa/fcntl.h
@@ -14,31 +14,17 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_ACCMODE 0x0003
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
#define O_APPEND 0x0008
#define O_SYNC 0x0010
#define O_NONBLOCK 0x0080
#define O_CREAT 0x0100 /* not fcntl */
-#define O_TRUNC 0x0200 /* not fcntl */
#define O_EXCL 0x0400 /* not fcntl */
#define O_NOCTTY 0x0800 /* not fcntl */
#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
#define O_LARGEFILE 0x2000 /* allow large file opens - currently ignored */
#define O_DIRECT 0x8000 /* direct disk access hint - currently ignored*/
-#define O_DIRECTORY 0x10000 /* must be a directory */
-#define O_NOFOLLOW 0x20000 /* don't follow links */
#define O_NOATIME 0x100000
-#define O_NDELAY O_NONBLOCK
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
#define F_GETLK 14
#define F_GETLK64 15
#define F_SETLK 6
@@ -48,35 +34,6 @@
#define F_SETOWN 24 /* for sockets. */
#define F_GETOWN 23 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock ... */
-#define LOCK_READ 64 /* which allows concurrent read operations */
-#define LOCK_WRITE 128 /* which allows concurrent write operations */
-#define LOCK_RW 192 /* which allows concurrent read & write ops */
typedef struct flock {
short l_type;
@@ -96,6 +53,9 @@ struct flock64 {
pid_t l_pid;
};
-#define F_LINUX_SPECIFIC_BASE 1024
+#define HAVE_ARCH_STRUCT_FLOCK
+#define HAVE_ARCH_STRUCT_FLOCK64
+
+#include <asm-generic/fcntl.h>
#endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/hdreg.h b/include/asm-xtensa/hdreg.h
deleted file mode 100644
index 64b80607b80d..000000000000
--- a/include/asm-xtensa/hdreg.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-xtensa/hdreg.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-#ifndef _XTENSA_HDREG_H
-#define _XTENSA_HDREG_H
-
-typedef unsigned int ide_ioreg_t;
-
-#endif
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
index 2c471c42ecfc..c5c13985bbe1 100644
--- a/include/asm-xtensa/io.h
+++ b/include/asm-xtensa/io.h
@@ -41,12 +41,12 @@ static inline unsigned int _swapl (unsigned int v)
* These are trivial on the 1:1 Linux/Xtensa mapping
*/
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
{
return PHYSADDR((unsigned long)address);
}
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
{
return (void*) CACHED_ADDR(address);
}
@@ -55,12 +55,12 @@ extern inline void * phys_to_virt(unsigned long address)
* IO bus memory addresses are also 1:1 with the physical address
*/
-extern inline unsigned long virt_to_bus(volatile void * address)
+static inline unsigned long virt_to_bus(volatile void * address)
{
return PHYSADDR((unsigned long)address);
}
-extern inline void * bus_to_virt (unsigned long address)
+static inline void * bus_to_virt (unsigned long address)
{
return (void *) CACHED_ADDR(address);
}
@@ -69,17 +69,17 @@ extern inline void * bus_to_virt (unsigned long address)
* Change "struct page" to physical address.
*/
-extern inline void *ioremap(unsigned long offset, unsigned long size)
+static inline void *ioremap(unsigned long offset, unsigned long size)
{
return (void *) CACHED_ADDR_IO(offset);
}
-extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
+static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
{
return (void *) BYPASS_ADDR_IO(offset);
}
-extern inline void iounmap(void *addr)
+static inline void iounmap(void *addr)
{
}
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index 1b0801548cd9..364a7b057bfa 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -199,13 +199,13 @@ extern pgd_t *current_pgd;
#define ASID_FIRST_VERSION \
((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
-extern inline void set_rasid_register (unsigned long val)
+static inline void set_rasid_register (unsigned long val)
{
__asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
" isync\n" : : "a" (val));
}
-extern inline unsigned long get_rasid_register (void)
+static inline unsigned long get_rasid_register (void)
{
unsigned long tmp;
__asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
@@ -215,7 +215,7 @@ extern inline unsigned long get_rasid_register (void)
#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
-extern inline void
+static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
{
extern void flush_tlb_all(void);
@@ -234,7 +234,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
really the best, but if you insist... */
-extern inline int validate_asid (unsigned long asid)
+static inline int validate_asid (unsigned long asid)
{
switch (asid) {
case XCHAL_MMU_ASID_INVALID:
@@ -247,7 +247,7 @@ extern inline int validate_asid (unsigned long asid)
return 1; /* valid */
}
-extern inline void
+static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
{
extern void flush_tlb_all(void);
@@ -274,14 +274,14 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
* instance.
*/
-extern inline int
+static inline int
init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
mm->context = NO_CONTEXT;
return 0;
}
-extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
unsigned long asid = asid_cache;
@@ -301,7 +301,7 @@ extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* Destroy context related info for an mm_struct that is about
* to be put to rest.
*/
-extern inline void destroy_context(struct mm_struct *mm)
+static inline void destroy_context(struct mm_struct *mm)
{
/* Nothing to do. */
}
@@ -310,7 +310,7 @@ extern inline void destroy_context(struct mm_struct *mm)
* After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings.
*/
-extern inline void
+static inline void
activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
/* Unconditionally get a new ASID. */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index b495e5b5a942..8ded36f255a2 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -55,7 +55,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
* Pure 2^n version of get_order
*/
-extern __inline__ int get_order(unsigned long size)
+static inline int get_order(unsigned long size)
{
int order;
#ifndef XCHAL_HAVE_NSU
diff --git a/include/asm-xtensa/page.h.n b/include/asm-xtensa/page.h.n
deleted file mode 100644
index 546cc6624f24..000000000000
--- a/include/asm-xtensa/page.h.n
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * linux/include/asm-xtensa/page.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version2 as
- * published by the Free Software Foundation.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_PAGE_H
-#define _XTENSA_PAGE_H
-
-#ifdef __KERNEL__
-
-#include <asm/processor.h>
-#include <linux/config.h>
-
-/*
- * PAGE_SHIFT determines the page size
- * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
- */
-#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
-
-#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
-#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
-
-#ifdef __ASSEMBLY__
-
-#define __pgprot(x) (x)
-
-#else
-
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t; /* page table entry */
-typedef struct { unsigned long pmd; } pmd_t; /* PMD table entry */
-typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((x).pmd)
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-/*
- * Pure 2^n version of get_order
- */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
-#ifndef XCHAL_HAVE_NSU
- unsigned long x1, x2, x4, x8, x16;
-
- size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- x1 = size & 0xAAAAAAAA;
- x2 = size & 0xCCCCCCCC;
- x4 = size & 0xF0F0F0F0;
- x8 = size & 0xFF00FF00;
- x16 = size & 0xFFFF0000;
- order = x2 ? 2 : 0;
- order += (x16 != 0) * 16;
- order += (x8 != 0) * 8;
- order += (x4 != 0) * 4;
- order += (x1 != 0);
-
- return order;
-#else
- size = (size - 1) >> PAGE_SHIFT;
- asm ("nsau %0, %1" : "=r" (order) : "r" (size));
- return 32 - order;
-#endif
-}
-
-
-struct page;
-extern void clear_page(void *page);
-extern void copy_page(void *to, void *from);
-
-/*
- * If we have cache aliasing and writeback caches, we might have to do
- * some extra work
- */
-
-#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
-void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
-void copy_user_page(void *to, void* from, unsigned long vaddr, struct page* page);
-#else
-# define clear_user_page(page,vaddr,pg) clear_page(page)
-# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#endif
-
-
-/*
- * This handles the memory map. We handle pages at
- * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
- * These macros are for conversion of kernel address, not user
- * addresses.
- */
-
-#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
-# error CONFIG_DISCONTIGMEM not supported
-#endif
-
-#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
-#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
-#define WANT_PAGE_VIRTUAL
-
-
-#endif /* __ASSEMBLY__ */
-
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
index 6817742301c2..24eb7fc25da8 100644
--- a/include/asm-xtensa/pci.h
+++ b/include/asm-xtensa/pci.h
@@ -22,12 +22,12 @@
extern struct pci_controller* pcibios_alloc_controller(void);
-extern inline void pcibios_set_master(struct pci_dev *dev)
+static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
-extern inline void pcibios_penalize_isa_irq(int irq)
+static inline void pcibios_penalize_isa_irq(int irq)
{
/* We don't do dynamic PCI IRQ allocation */
}
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 0bb6416ae266..987e3b802313 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -260,7 +260,7 @@ static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pt
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
}
@@ -278,14 +278,14 @@ static inline void update_pte(pte_t *ptep, pte_t pteval)
#endif
}
-extern inline void
+static inline void
set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
{
update_pte(ptep, pteval);
}
-extern inline void
+static inline void
set_pmd(pmd_t *pmdp, pmd_t pmdval)
{
*pmdp = pmdval;
@@ -441,11 +441,11 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ remap_pfn_range(vma, from, pfn, size, prot)
/* No page table caches to init */
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index 2848a5ff8349..aa4fd7fb3ce7 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -127,7 +127,7 @@ extern void show_regs(struct pt_regs *);
#else /* __ASSEMBLY__ */
#ifdef __KERNEL__
-# include <asm/offsets.h>
+# include <asm/asm-offsets.h>
#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
#endif
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
index c8a7574a9a57..db740b8bc6f0 100644
--- a/include/asm-xtensa/semaphore.h
+++ b/include/asm-xtensa/semaphore.h
@@ -47,7 +47,7 @@ struct semaphore {
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
/*
* *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
@@ -79,7 +79,7 @@ asmlinkage void __up(struct semaphore * sem);
extern spinlock_t semaphore_wake_lock;
-extern __inline__ void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
@@ -89,7 +89,7 @@ extern __inline__ void down(struct semaphore * sem)
__down(sem);
}
-extern __inline__ int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
{
int ret = 0;
#if WAITQUEUE_DEBUG
@@ -101,7 +101,7 @@ extern __inline__ int down_interruptible(struct semaphore * sem)
return ret;
}
-extern __inline__ int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
{
int ret = 0;
#if WAITQUEUE_DEBUG
@@ -117,7 +117,7 @@ extern __inline__ int down_trylock(struct semaphore * sem)
* Note! This is subtle. We jump to wake people up only if
* the semaphore was negative (== somebody was waiting on it).
*/
-extern __inline__ void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
{
#if WAITQUEUE_DEBUG
CHECK_MAGIC(sem->__magic);
diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
index daccd05a14cd..00f83f3a6d72 100644
--- a/include/asm-xtensa/socket.h
+++ b/include/asm-xtensa/socket.h
@@ -24,6 +24,8 @@
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
diff --git a/include/asm-xtensa/string.h b/include/asm-xtensa/string.h
index 3f81b27d9809..5fb8c27cbef5 100644
--- a/include/asm-xtensa/string.h
+++ b/include/asm-xtensa/string.h
@@ -16,7 +16,7 @@
#define _XTENSA_STRING_H
#define __HAVE_ARCH_STRCPY
-extern __inline__ char *strcpy(char *__dest, const char *__src)
+static inline char *strcpy(char *__dest, const char *__src)
{
register char *__xdest = __dest;
unsigned long __dummy;
@@ -35,7 +35,7 @@ extern __inline__ char *strcpy(char *__dest, const char *__src)
}
#define __HAVE_ARCH_STRNCPY
-extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
+static inline char *strncpy(char *__dest, const char *__src, size_t __n)
{
register char *__xdest = __dest;
unsigned long __dummy;
@@ -60,7 +60,7 @@ extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
}
#define __HAVE_ARCH_STRCMP
-extern __inline__ int strcmp(const char *__cs, const char *__ct)
+static inline int strcmp(const char *__cs, const char *__ct)
{
register int __res;
unsigned long __dummy;
@@ -82,7 +82,7 @@ extern __inline__ int strcmp(const char *__cs, const char *__ct)
}
#define __HAVE_ARCH_STRNCMP
-extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n)
+static inline int strncmp(const char *__cs, const char *__ct, size_t __n)
{
register int __res;
unsigned long __dummy;
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index 690fe325e671..f09393232e5e 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -56,7 +56,7 @@ static inline int irqs_disabled(void)
#define clear_cpenable() __clear_cpenable()
-extern __inline__ void __clear_cpenable(void)
+static inline void __clear_cpenable(void)
{
#if XCHAL_HAVE_CP
unsigned long i = 0;
@@ -64,7 +64,7 @@ extern __inline__ void __clear_cpenable(void)
#endif
}
-extern __inline__ void enable_coprocessor(int i)
+static inline void enable_coprocessor(int i)
{
#if XCHAL_HAVE_CP
int cp;
@@ -74,7 +74,7 @@ extern __inline__ void enable_coprocessor(int i)
#endif
}
-extern __inline__ void disable_coprocessor(int i)
+static inline void disable_coprocessor(int i)
{
#if XCHAL_HAVE_CP
int cp;
@@ -123,7 +123,7 @@ do { \
* cmpxchg
*/
-extern __inline__ unsigned long
+static inline unsigned long
__cmpxchg_u32(volatile int *p, int old, int new)
{
__asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
@@ -173,7 +173,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
* where no register reference will cause an overflow.
*/
-extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
{
unsigned long tmp;
__asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
index 23bfe9db45f5..43f6ec859af9 100644
--- a/include/asm-xtensa/tlbflush.h
+++ b/include/asm-xtensa/tlbflush.h
@@ -39,7 +39,7 @@ extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
* page-table pages.
*/
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
}
@@ -51,26 +51,26 @@ extern inline void flush_tlb_pgtables(struct mm_struct *mm,
#define ITLB_PROBE_SUCCESS (1 << ITLB_WAYS_LOG2)
#define DTLB_PROBE_SUCCESS (1 << DTLB_WAYS_LOG2)
-extern inline unsigned long itlb_probe(unsigned long addr)
+static inline unsigned long itlb_probe(unsigned long addr)
{
unsigned long tmp;
__asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
return tmp;
}
-extern inline unsigned long dtlb_probe(unsigned long addr)
+static inline unsigned long dtlb_probe(unsigned long addr)
{
unsigned long tmp;
__asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
return tmp;
}
-extern inline void invalidate_itlb_entry (unsigned long probe)
+static inline void invalidate_itlb_entry (unsigned long probe)
{
__asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe));
}
-extern inline void invalidate_dtlb_entry (unsigned long probe)
+static inline void invalidate_dtlb_entry (unsigned long probe)
{
__asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe));
}
@@ -80,68 +80,68 @@ extern inline void invalidate_dtlb_entry (unsigned long probe)
* caller must follow up with an 'isync', which can be relatively
* expensive on some Xtensa implementations.
*/
-extern inline void invalidate_itlb_entry_no_isync (unsigned entry)
+static inline void invalidate_itlb_entry_no_isync (unsigned entry)
{
/* Caller must follow up with 'isync'. */
__asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) );
}
-extern inline void invalidate_dtlb_entry_no_isync (unsigned entry)
+static inline void invalidate_dtlb_entry_no_isync (unsigned entry)
{
/* Caller must follow up with 'isync'. */
__asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) );
}
-extern inline void set_itlbcfg_register (unsigned long val)
+static inline void set_itlbcfg_register (unsigned long val)
{
__asm__ __volatile__("wsr %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
: : "a" (val));
}
-extern inline void set_dtlbcfg_register (unsigned long val)
+static inline void set_dtlbcfg_register (unsigned long val)
{
__asm__ __volatile__("wsr %0, "__stringify(DTLBCFG)"; dsync\n\t"
: : "a" (val));
}
-extern inline void set_ptevaddr_register (unsigned long val)
+static inline void set_ptevaddr_register (unsigned long val)
{
__asm__ __volatile__(" wsr %0, "__stringify(PTEVADDR)"; isync\n"
: : "a" (val));
}
-extern inline unsigned long read_ptevaddr_register (void)
+static inline unsigned long read_ptevaddr_register (void)
{
unsigned long tmp;
__asm__ __volatile__("rsr %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
return tmp;
}
-extern inline void write_dtlb_entry (pte_t entry, int way)
+static inline void write_dtlb_entry (pte_t entry, int way)
{
__asm__ __volatile__("wdtlb %1, %0; dsync\n\t"
: : "r" (way), "r" (entry) );
}
-extern inline void write_itlb_entry (pte_t entry, int way)
+static inline void write_itlb_entry (pte_t entry, int way)
{
__asm__ __volatile__("witlb %1, %0; isync\n\t"
: : "r" (way), "r" (entry) );
}
-extern inline void invalidate_page_directory (void)
+static inline void invalidate_page_directory (void)
{
invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
}
-extern inline void invalidate_itlb_mapping (unsigned address)
+static inline void invalidate_itlb_mapping (unsigned address)
{
unsigned long tlb_entry;
while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
invalidate_itlb_entry (tlb_entry);
}
-extern inline void invalidate_dtlb_mapping (unsigned address)
+static inline void invalidate_dtlb_mapping (unsigned address)
{
unsigned long tlb_entry;
while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
@@ -165,28 +165,28 @@ extern inline void invalidate_dtlb_mapping (unsigned address)
* as[07..00] contain the asid
*/
-extern inline unsigned long read_dtlb_virtual (int way)
+static inline unsigned long read_dtlb_virtual (int way)
{
unsigned long tmp;
__asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
return tmp;
}
-extern inline unsigned long read_dtlb_translation (int way)
+static inline unsigned long read_dtlb_translation (int way)
{
unsigned long tmp;
__asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
return tmp;
}
-extern inline unsigned long read_itlb_virtual (int way)
+static inline unsigned long read_itlb_virtual (int way)
{
unsigned long tmp;
__asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
return tmp;
}
-extern inline unsigned long read_itlb_translation (int way)
+static inline unsigned long read_itlb_translation (int way)
{
unsigned long tmp;
__asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
index ebac00469852..9d99a8e9e337 100644
--- a/include/asm-xtensa/types.h
+++ b/include/asm-xtensa/types.h
@@ -58,8 +58,6 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
-typedef unsigned int kmem_bufctl_t;
-
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
index 35576b25c7b2..06a22b83ba17 100644
--- a/include/asm-xtensa/uaccess.h
+++ b/include/asm-xtensa/uaccess.h
@@ -25,7 +25,7 @@
#define _ASMLANGUAGE
#include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/processor.h>
/*
@@ -211,7 +211,7 @@
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
-extern inline int verify_area(int type, const void * addr, unsigned long size)
+static inline int verify_area(int type, const void * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
@@ -464,7 +464,7 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
* success.
*/
-extern inline unsigned long
+static inline unsigned long
__xtensa_clear_user(void *addr, unsigned long size)
{
if ( ! memset(addr, 0, size) )
@@ -472,7 +472,7 @@ __xtensa_clear_user(void *addr, unsigned long size)
return 0;
}
-extern inline unsigned long
+static inline unsigned long
clear_user(void *addr, unsigned long size)
{
if (access_ok(VERIFY_WRITE, addr, size))
@@ -486,7 +486,7 @@ clear_user(void *addr, unsigned long size)
extern long __strncpy_user(char *, const char *, long);
#define __strncpy_from_user __strncpy_user
-extern inline long
+static inline long
strncpy_from_user(char *dst, const char *src, long count)
{
if (access_ok(VERIFY_READ, src, 1))
@@ -502,7 +502,7 @@ strncpy_from_user(char *dst, const char *src, long count)
*/
extern long __strnlen_user(const char *, long);
-extern inline long strnlen_user(const char *str, long len)
+static inline long strnlen_user(const char *str, long len)
{
unsigned long top = __kernel_ok ? ~0UL : TASK_SIZE - 1;
diff --git a/include/linux/8250_pci.h b/include/linux/8250_pci.h
index 5f3ab21b339b..3209dd46ea7d 100644
--- a/include/linux/8250_pci.h
+++ b/include/linux/8250_pci.h
@@ -1,2 +1,37 @@
-int pci_siig10x_fn(struct pci_dev *dev, int enable);
-int pci_siig20x_fn(struct pci_dev *dev, int enable);
+/*
+ * Definitions for PCI support.
+ */
+#define FL_BASE_MASK 0x0007
+#define FL_BASE0 0x0000
+#define FL_BASE1 0x0001
+#define FL_BASE2 0x0002
+#define FL_BASE3 0x0003
+#define FL_BASE4 0x0004
+#define FL_GET_BASE(x) (x & FL_BASE_MASK)
+
+/* Use successive BARs (PCI base address registers),
+ else use offset into some specified BAR */
+#define FL_BASE_BARS 0x0008
+
+/* do not assign an irq */
+#define FL_NOIRQ 0x0080
+
+/* Use the Base address register size to cap number of ports */
+#define FL_REGION_SZ_CAP 0x0100
+
+struct pciserial_board {
+ unsigned int flags;
+ unsigned int num_ports;
+ unsigned int base_baud;
+ unsigned int uart_offset;
+ unsigned int reg_shift;
+ unsigned int first_offset;
+};
+
+struct serial_private;
+
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board);
+void pciserial_remove_ports(struct serial_private *priv);
+void pciserial_suspend_ports(struct serial_private *priv);
+void pciserial_resume_ports(struct serial_private *priv);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index b46a5205ee7b..026c3c011dc0 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -41,7 +41,7 @@
#include <asm/acpi.h>
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
enum acpi_irq_model_id {
ACPI_IRQ_MODEL_PIC = 0,
@@ -429,23 +429,13 @@ extern int pci_mmcfg_config_num;
extern int sbf_port ;
-#else /*!CONFIG_ACPI_BOOT*/
+#else /* !CONFIG_ACPI */
#define acpi_mp_config 0
-static inline int acpi_boot_init(void)
-{
- return 0;
-}
-
-static inline int acpi_boot_table_init(void)
-{
- return 0;
-}
+#endif /* !CONFIG_ACPI */
-#endif /*!CONFIG_ACPI_BOOT*/
-
-unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
+int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
/*
@@ -455,7 +445,7 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
*/
void acpi_unregister_gsi (u32 gsi);
-#ifdef CONFIG_ACPI_PCI
+#ifdef CONFIG_ACPI
struct acpi_prt_entry {
struct list_head node;
@@ -489,7 +479,7 @@ struct acpi_pci_driver {
int acpi_pci_register_driver(struct acpi_pci_driver *driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
-#endif /*CONFIG_ACPI_PCI*/
+#endif /* CONFIG_ACPI */
#ifdef CONFIG_ACPI_EC
@@ -498,20 +488,9 @@ extern int ec_write(u8 addr, u8 val);
#endif /*CONFIG_ACPI_EC*/
-#ifdef CONFIG_ACPI_INTERPRETER
-
extern int acpi_blacklisted(void);
extern void acpi_bios_year(char *s);
-#else /*!CONFIG_ACPI_INTERPRETER*/
-
-static inline int acpi_blacklisted(void)
-{
- return 0;
-}
-
-#endif /*!CONFIG_ACPI_INTERPRETER*/
-
#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */
#ifdef CONFIG_ACPI
@@ -549,5 +528,17 @@ static inline int acpi_get_pxm(acpi_handle handle)
extern int pnpacpi_disabled;
+#else /* CONFIG_ACPI */
+
+static inline int acpi_boot_init(void)
+{
+ return 0;
+}
+
+static inline int acpi_boot_table_init(void)
+{
+ return 0;
+}
+
#endif /* CONFIG_ACPI */
#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ca5fcadf9981..a5b74efab067 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -1,24 +1,29 @@
/*
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from http://www.t13.org/
+ *
*/
#ifndef __LINUX_ATA_H__
@@ -108,6 +113,8 @@ enum {
/* ATA device commands */
ATA_CMD_CHK_POWER = 0xE5, /* check power mode */
+ ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */
+ ATA_CMD_IDLE = 0xE3, /* place in idle power mode */
ATA_CMD_EDD = 0x90, /* execute device diagnostic */
ATA_CMD_FLUSH = 0xE7,
ATA_CMD_FLUSH_EXT = 0xEA,
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index af1010b6dab7..93bfb0beb62a 100644
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -11,10 +11,12 @@
#include <linux/device.h>
#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
struct attribute_container {
struct list_head node;
- struct list_head containers;
+ struct klist containers;
struct class *class;
struct class_device_attribute **attrs;
int (*match)(struct attribute_container *, struct device *);
@@ -62,12 +64,8 @@ int attribute_container_add_class_device_adapter(struct attribute_container *con
struct class_device *classdev);
void attribute_container_remove_attrs(struct class_device *classdev);
void attribute_container_class_device_del(struct class_device *classdev);
-
-
-
-
-
-
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
#endif
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
new file mode 100644
index 000000000000..9a7b374c9fb4
--- /dev/null
+++ b/include/linux/auxvec.h
@@ -0,0 +1,31 @@
+#ifndef _LINUX_AUXVEC_H
+#define _LINUX_AUXVEC_H
+
+#include <asm/auxvec.h>
+
+/* Symbolic values for the entries in the auxiliary table
+ put on the initial stack */
+#define AT_NULL 0 /* end of vector */
+#define AT_IGNORE 1 /* entry should be ignored */
+#define AT_EXECFD 2 /* file descriptor of program */
+#define AT_PHDR 3 /* program headers for program */
+#define AT_PHENT 4 /* size of program header entry */
+#define AT_PHNUM 5 /* number of program headers */
+#define AT_PAGESZ 6 /* system page size */
+#define AT_BASE 7 /* base address of interpreter */
+#define AT_FLAGS 8 /* flags */
+#define AT_ENTRY 9 /* entry point of program */
+#define AT_NOTELF 10 /* program is not ELF */
+#define AT_UID 11 /* real uid */
+#define AT_EUID 12 /* effective uid */
+#define AT_GID 13 /* real gid */
+#define AT_EGID 14 /* effective gid */
+#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
+#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+#define AT_CLKTCK 17 /* frequency at which times() increments */
+
+#define AT_SECURE 23 /* secure mode boolean */
+
+#define AT_VECTOR_SIZE 42 /* Size of auxiliary table. */
+
+#endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h
index f7f0913cd110..c1237aa92e38 100644
--- a/include/linux/bfs_fs.h
+++ b/include/linux/bfs_fs.h
@@ -14,8 +14,9 @@
#define BFS_INODES_PER_BLOCK 8
/* SVR4 vnode type values (bfs_inode->i_vtype) */
-#define BFS_VDIR 2
-#define BFS_VREG 1
+#define BFS_VDIR 2L
+#define BFS_VREG 1L
+
/* BFS inode layout on disk */
struct bfs_inode {
@@ -58,22 +59,22 @@ struct bfs_super_block {
__u32 s_padding[118];
};
-#define BFS_NZFILESIZE(ip) \
- (((ip)->i_eoffset + 1) - (ip)->i_sblock * BFS_BSIZE)
-
-#define BFS_FILESIZE(ip) \
- ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
-
-#define BFS_FILEBLOCKS(ip) \
- ((ip)->i_sblock == 0 ? 0 : ((ip)->i_eblock + 1) - (ip)->i_sblock)
#define BFS_OFF2INO(offset) \
((((offset) - BFS_BSIZE) / sizeof(struct bfs_inode)) + BFS_ROOT_INO)
#define BFS_INO2OFF(ino) \
((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE)
+#define BFS_NZFILESIZE(ip) \
+ ((cpu_to_le32((ip)->i_eoffset) + 1) - cpu_to_le32((ip)->i_sblock) * BFS_BSIZE)
+
+#define BFS_FILESIZE(ip) \
+ ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
+#define BFS_FILEBLOCKS(ip) \
+ ((ip)->i_sblock == 0 ? 0 : (cpu_to_le32((ip)->i_eblock) + 1) - cpu_to_le32((ip)->i_sblock))
#define BFS_UNCLEAN(bfs_sb, sb) \
- ((bfs_sb->s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY))
+ ((cpu_to_le32(bfs_sb->s_from) != -1) && (cpu_to_le32(bfs_sb->s_to) != -1) && !(sb->s_flags & MS_RDONLY))
+
#endif /* _LINUX_BFS_FS_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 36ef29fa0d8b..6e1c79c8b6bf 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -111,7 +111,6 @@ struct bio {
void *bi_private;
bio_destructor_t *bi_destructor; /* destructor */
- struct bio_set *bi_set; /* memory pools set */
};
/*
@@ -280,6 +279,7 @@ extern void bioset_free(struct bio_set *);
extern struct bio *bio_alloc(unsigned int __nocast, int);
extern struct bio *bio_alloc_bioset(unsigned int __nocast, int, struct bio_set *);
extern void bio_put(struct bio *);
+extern void bio_free(struct bio *, struct bio_set *);
extern void bio_endio(struct bio *, unsigned int, int);
struct request_queue;
@@ -295,7 +295,13 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
extern int bio_get_nr_vecs(struct block_device *);
extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
unsigned long, unsigned int, int);
+struct sg_iovec;
+extern struct bio *bio_map_user_iov(struct request_queue *,
+ struct block_device *,
+ struct sg_iovec *, int, int);
extern void bio_unmap_user(struct bio *);
+extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+ unsigned int);
extern void bio_set_pages_dirty(struct bio *bio);
extern void bio_check_pages_dirty(struct bio *bio);
extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
@@ -308,9 +314,8 @@ void zero_fill_bio(struct bio *bio);
* bvec_kmap_irq and bvec_kunmap_irq!!
*
* This function MUST be inlined - it plays with the CPU interrupt flags.
- * Hence the `extern inline'.
*/
-extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
+static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
{
unsigned long addr;
@@ -326,7 +331,7 @@ extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
return (char *) addr + bvec->bv_offset;
}
-extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
+static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
{
unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
@@ -339,7 +344,7 @@ extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
#define bvec_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0)
#endif
-extern inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
+static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
unsigned long *flags)
{
return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
new file mode 100644
index 000000000000..6b20af0bbb79
--- /dev/null
+++ b/include/linux/bit_spinlock.h
@@ -0,0 +1,77 @@
+#ifndef __LINUX_BIT_SPINLOCK_H
+#define __LINUX_BIT_SPINLOCK_H
+
+/*
+ * bit-based spin_lock()
+ *
+ * Don't use this unless you really need to: spin_lock() and spin_unlock()
+ * are significantly faster.
+ */
+static inline void bit_spin_lock(int bitnum, unsigned long *addr)
+{
+ /*
+ * Assuming the lock is uncontended, this never enters
+ * the body of the outer loop. If it is contended, then
+ * within the inner loop a non-atomic test is used to
+ * busywait with less bus contention for a good time to
+ * attempt to acquire the lock bit.
+ */
+ preempt_disable();
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ while (test_and_set_bit(bitnum, addr)) {
+ while (test_bit(bitnum, addr)) {
+ preempt_enable();
+ cpu_relax();
+ preempt_disable();
+ }
+ }
+#endif
+ __acquire(bitlock);
+}
+
+/*
+ * Return true if it was acquired
+ */
+static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
+{
+ preempt_disable();
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ if (test_and_set_bit(bitnum, addr)) {
+ preempt_enable();
+ return 0;
+ }
+#endif
+ __acquire(bitlock);
+ return 1;
+}
+
+/*
+ * bit-based spin_unlock()
+ */
+static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ BUG_ON(!test_bit(bitnum, addr));
+ smp_mb__before_clear_bit();
+ clear_bit(bitnum, addr);
+#endif
+ preempt_enable();
+ __release(bitlock);
+}
+
+/*
+ * Return true if the lock is held.
+ */
+static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ return test_bit(bitnum, addr);
+#elif defined CONFIG_PREEMPT
+ return preempt_count();
+#else
+ return 1;
+#endif
+}
+
+#endif /* __LINUX_BIT_SPINLOCK_H */
+
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 19bd8e7e11bf..efdc9b5bc05c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -563,10 +563,12 @@ extern void blk_sync_queue(struct request_queue *q);
extern void __blk_stop_queue(request_queue_t *q);
extern void blk_run_queue(request_queue_t *);
extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
-extern struct request *blk_rq_map_user(request_queue_t *, int, void __user *, unsigned int);
-extern int blk_rq_unmap_user(struct request *, struct bio *, unsigned int);
-extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *);
-
+extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
+extern int blk_rq_unmap_user(struct bio *, unsigned int);
+extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
+extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
+extern int blk_execute_rq(request_queue_t *, struct gendisk *,
+ struct request *, int);
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{
return bdev->bd_disk->queue;
@@ -726,7 +728,7 @@ static inline unsigned int blksize_bits(unsigned int size)
return bits;
}
-extern inline unsigned int block_size(struct block_device *bdev)
+static inline unsigned int block_size(struct block_device *bdev)
{
return bdev->bd_block_size;
}
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 8d139f4acf23..6b4618902d3d 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -233,6 +233,7 @@ typedef __u32 kernel_cap_t;
/* Allow enabling/disabling tagged queuing on SCSI controllers and sending
arbitrary SCSI commands */
/* Allow setting encryption key on loopback filesystem */
+/* Allow setting zone reclaim policy */
#define CAP_SYS_ADMIN 21
diff --git a/include/linux/chio.h b/include/linux/chio.h
index 63035ae67e63..a404c111c937 100644
--- a/include/linux/chio.h
+++ b/include/linux/chio.h
@@ -96,7 +96,7 @@ struct changer_position {
*/
struct changer_element_status {
int ces_type;
- unsigned char *ces_data;
+ unsigned char __user *ces_data;
};
#define CESTATUS_FULL 0x01 /* full */
#define CESTATUS_IMPEXP 0x02 /* media was imported (inserted by sysop) */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index b58b7d6f2fdb..f9ca534787e2 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -18,6 +18,9 @@
#define compat_jiffies_to_clock_t(x) \
(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
+typedef __compat_uid32_t compat_uid_t;
+typedef __compat_gid32_t compat_gid_t;
+
struct rusage;
struct compat_itimerspec {
diff --git a/include/linux/connector.h b/include/linux/connector.h
new file mode 100644
index 000000000000..96de26301f84
--- /dev/null
+++ b/include/linux/connector.h
@@ -0,0 +1,158 @@
+/*
+ * connector.h
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __CONNECTOR_H
+#define __CONNECTOR_H
+
+#include <asm/types.h>
+
+#define CN_IDX_CONNECTOR 0xffffffff
+#define CN_VAL_CONNECTOR 0xffffffff
+
+#define CN_NETLINK_USERS 1
+
+/*
+ * Maximum connector's message size.
+ */
+#define CONNECTOR_MAX_MSG_SIZE 1024
+
+/*
+ * idx and val are unique identifiers which
+ * are used for message routing and
+ * must be registered in connector.h for in-kernel usage.
+ */
+
+struct cb_id {
+ __u32 idx;
+ __u32 val;
+};
+
+struct cn_msg {
+ struct cb_id id;
+
+ __u32 seq;
+ __u32 ack;
+
+ __u16 len; /* Length of the following data */
+ __u16 flags;
+ __u8 data[0];
+};
+
+/*
+ * Notify structure - requests notification about
+ * registering/unregistering idx/val in range [first, first+range].
+ */
+struct cn_notify_req {
+ __u32 first;
+ __u32 range;
+};
+
+/*
+ * Main notification control message
+ * *_notify_num - number of appropriate cn_notify_req structures after
+ * this struct.
+ * group - notification receiver's idx.
+ * len - total length of the attached data.
+ */
+struct cn_ctl_msg {
+ __u32 idx_notify_num;
+ __u32 val_notify_num;
+ __u32 group;
+ __u32 len;
+ __u8 data[0];
+};
+
+#ifdef __KERNEL__
+
+#include <asm/atomic.h>
+
+#include <linux/list.h>
+#include <linux/workqueue.h>
+
+#include <net/sock.h>
+
+#define CN_CBQ_NAMELEN 32
+
+struct cn_queue_dev {
+ atomic_t refcnt;
+ unsigned char name[CN_CBQ_NAMELEN];
+
+ struct workqueue_struct *cn_queue;
+
+ struct list_head queue_list;
+ spinlock_t queue_lock;
+
+ int netlink_groups;
+ struct sock *nls;
+};
+
+struct cn_callback {
+ unsigned char name[CN_CBQ_NAMELEN];
+
+ struct cb_id id;
+ void (*callback) (void *);
+ void *priv;
+};
+
+struct cn_callback_entry {
+ struct list_head callback_entry;
+ struct cn_callback *cb;
+ struct work_struct work;
+ struct cn_queue_dev *pdev;
+
+ void (*destruct_data) (void *);
+ void *ddata;
+
+ int seq, group;
+ struct sock *nls;
+};
+
+struct cn_ctl_entry {
+ struct list_head notify_entry;
+ struct cn_ctl_msg *msg;
+};
+
+struct cn_dev {
+ struct cb_id id;
+
+ u32 seq, groups;
+ struct sock *nls;
+ void (*input) (struct sock * sk, int len);
+
+ struct cn_queue_dev *cbdev;
+};
+
+int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
+void cn_del_callback(struct cb_id *);
+int cn_netlink_send(struct cn_msg *, u32, int);
+
+int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb);
+void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
+
+struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
+void cn_queue_free_dev(struct cn_queue_dev *dev);
+
+int cn_cb_equal(struct cb_id *, struct cb_id *);
+
+extern int cn_already_initialized;
+
+#endif /* __KERNEL__ */
+#endif /* __CONNECTOR_H */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index e8904c0da686..86980c68234a 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -8,7 +8,7 @@
* Basic handling of the devices is done in drivers/base/cpu.c
* and system devices are handled in drivers/base/sys.c.
*
- * CPUs are exported via driverfs in the class/cpu/devices/
+ * CPUs are exported via sysfs in the class/cpu/devices/
* directory.
*
* Per-cpu interfaces can be implemented using a struct device_interface.
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 3438233305a3..24062a1dbf61 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -23,7 +23,8 @@ void cpuset_init_current_mems_allowed(void);
void cpuset_update_current_mems_allowed(void);
void cpuset_restrict_to_mems_allowed(unsigned long *nodes);
int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
-int cpuset_zone_allowed(struct zone *z);
+extern int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask);
+extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
extern struct file_operations proc_cpuset_operations;
extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
@@ -48,7 +49,13 @@ static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
return 1;
}
-static inline int cpuset_zone_allowed(struct zone *z)
+static inline int cpuset_zone_allowed(struct zone *z,
+ unsigned int __nocast gfp_mask)
+{
+ return 1;
+}
+
+static inline int cpuset_excl_nodes_overlap(const struct task_struct *p)
{
return 1;
}
diff --git a/include/linux/crc16.h b/include/linux/crc16.h
new file mode 100644
index 000000000000..9443c084f881
--- /dev/null
+++ b/include/linux/crc16.h
@@ -0,0 +1,30 @@
+/*
+ * crc16.h - CRC-16 routine
+ *
+ * Implements the standard CRC-16:
+ * Width 16
+ * Poly 0x8005 (x^16 + x^15 + x^2 + 1)
+ * Init 0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef __CRC16_H
+#define __CRC16_H
+
+#include <linux/types.h>
+
+extern u16 const crc16_table[256];
+
+extern u16 crc16(u16 crc, const u8 *buffer, size_t len);
+
+static inline u16 crc16_byte(u16 crc, const u8 data)
+{
+ return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
+}
+
+#endif /* __CRC16_H */
+
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 5e2bcc636a02..3c89df6e7768 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -45,6 +45,7 @@
#define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
+#define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 50be290d24d2..ab04b4f9b0db 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -88,8 +88,9 @@ struct dentry {
* negative */
/*
* The next three fields are touched by __d_lookup. Place them here
- * so they all fit in a 16-byte range, with 16-byte alignment.
+ * so they all fit in a cache line.
*/
+ struct hlist_node d_hash; /* lookup hash list */
struct dentry *d_parent; /* parent directory */
struct qstr d_name;
@@ -103,7 +104,6 @@ struct dentry {
void *d_fsdata; /* fs-specific data */
struct rcu_head d_rcu;
struct dcookie_struct *d_cookie; /* cookie, if any */
- struct hlist_node d_hash; /* lookup hash list */
int d_mounted;
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
new file mode 100644
index 000000000000..8bf4bacb5051
--- /dev/null
+++ b/include/linux/dccp.h
@@ -0,0 +1,459 @@
+#ifndef _LINUX_DCCP_H
+#define _LINUX_DCCP_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/* Structure describing an Internet (DCCP) socket address. */
+struct sockaddr_dccp {
+ __u16 sdccp_family; /* Address family */
+ __u16 sdccp_port; /* Port number */
+ __u32 sdccp_addr; /* Internet address */
+ __u32 sdccp_service; /* Service */
+ /* Pad to size of `struct sockaddr': 16 bytes . */
+ __u32 sdccp_pad;
+};
+
+/**
+ * struct dccp_hdr - generic part of DCCP packet header
+ *
+ * @dccph_sport - Relevant port on the endpoint that sent this packet
+ * @dccph_dport - Relevant port on the other endpoint
+ * @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
+ * @dccph_ccval - Used by the HC-Sender CCID
+ * @dccph_cscov - Parts of the packet that are covered by the Checksum field
+ * @dccph_checksum - Internet checksum, depends on dccph_cscov
+ * @dccph_x - 0 = 24 bit sequence number, 1 = 48
+ * @dccph_type - packet type, see DCCP_PKT_ prefixed macros
+ * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x
+ */
+struct dccp_hdr {
+ __u16 dccph_sport,
+ dccph_dport;
+ __u8 dccph_doff;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 dccph_cscov:4,
+ dccph_ccval:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 dccph_ccval:4,
+ dccph_cscov:4;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ __u16 dccph_checksum;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u32 dccph_x:1,
+ dccph_type:4,
+ dccph_reserved:3,
+ dccph_seq:24;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u32 dccph_reserved:3,
+ dccph_type:4,
+ dccph_x:1,
+ dccph_seq:24;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+};
+
+/**
+ * struct dccp_hdr_ext - the low bits of a 48 bit seq packet
+ *
+ * @dccph_seq_low - low 24 bits of a 48 bit seq packet
+ */
+struct dccp_hdr_ext {
+ __u32 dccph_seq_low;
+};
+
+/**
+ * struct dccp_hdr_request - Conection initiation request header
+ *
+ * @dccph_req_service - Service to which the client app wants to connect
+ * @dccph_req_options - list of options (must be a multiple of 32 bits
+ */
+struct dccp_hdr_request {
+ __u32 dccph_req_service;
+};
+/**
+ * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets
+ *
+ * @dccph_resp_ack_nr_high - 48 bit ack number high order bits, contains GSR
+ * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR
+ */
+struct dccp_hdr_ack_bits {
+ __u32 dccph_reserved1:8,
+ dccph_ack_nr_high:24;
+ __u32 dccph_ack_nr_low;
+};
+/**
+ * struct dccp_hdr_response - Conection initiation response header
+ *
+ * @dccph_resp_ack_nr_high - 48 bit ack number high order bits, contains GSR
+ * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR
+ * @dccph_resp_service - Echoes the Service Code on a received DCCP-Request
+ * @dccph_resp_options - list of options (must be a multiple of 32 bits
+ */
+struct dccp_hdr_response {
+ struct dccp_hdr_ack_bits dccph_resp_ack;
+ __u32 dccph_resp_service;
+};
+
+/**
+ * struct dccp_hdr_reset - Unconditionally shut down a connection
+ *
+ * @dccph_reset_service - Echoes the Service Code on a received DCCP-Request
+ * @dccph_reset_options - list of options (must be a multiple of 32 bits
+ */
+struct dccp_hdr_reset {
+ struct dccp_hdr_ack_bits dccph_reset_ack;
+ __u8 dccph_reset_code,
+ dccph_reset_data[3];
+};
+
+enum dccp_pkt_type {
+ DCCP_PKT_REQUEST = 0,
+ DCCP_PKT_RESPONSE,
+ DCCP_PKT_DATA,
+ DCCP_PKT_ACK,
+ DCCP_PKT_DATAACK,
+ DCCP_PKT_CLOSEREQ,
+ DCCP_PKT_CLOSE,
+ DCCP_PKT_RESET,
+ DCCP_PKT_SYNC,
+ DCCP_PKT_SYNCACK,
+ DCCP_PKT_INVALID,
+};
+
+#define DCCP_NR_PKT_TYPES DCCP_PKT_INVALID
+
+static inline unsigned int dccp_packet_hdr_len(const __u8 type)
+{
+ if (type == DCCP_PKT_DATA)
+ return 0;
+ if (type == DCCP_PKT_DATAACK ||
+ type == DCCP_PKT_ACK ||
+ type == DCCP_PKT_SYNC ||
+ type == DCCP_PKT_SYNCACK ||
+ type == DCCP_PKT_CLOSE ||
+ type == DCCP_PKT_CLOSEREQ)
+ return sizeof(struct dccp_hdr_ack_bits);
+ if (type == DCCP_PKT_REQUEST)
+ return sizeof(struct dccp_hdr_request);
+ if (type == DCCP_PKT_RESPONSE)
+ return sizeof(struct dccp_hdr_response);
+ return sizeof(struct dccp_hdr_reset);
+}
+enum dccp_reset_codes {
+ DCCP_RESET_CODE_UNSPECIFIED = 0,
+ DCCP_RESET_CODE_CLOSED,
+ DCCP_RESET_CODE_ABORTED,
+ DCCP_RESET_CODE_NO_CONNECTION,
+ DCCP_RESET_CODE_PACKET_ERROR,
+ DCCP_RESET_CODE_OPTION_ERROR,
+ DCCP_RESET_CODE_MANDATORY_ERROR,
+ DCCP_RESET_CODE_CONNECTION_REFUSED,
+ DCCP_RESET_CODE_BAD_SERVICE_CODE,
+ DCCP_RESET_CODE_TOO_BUSY,
+ DCCP_RESET_CODE_BAD_INIT_COOKIE,
+ DCCP_RESET_CODE_AGGRESSION_PENALTY,
+};
+
+/* DCCP options */
+enum {
+ DCCPO_PADDING = 0,
+ DCCPO_MANDATORY = 1,
+ DCCPO_MIN_RESERVED = 3,
+ DCCPO_MAX_RESERVED = 31,
+ DCCPO_NDP_COUNT = 37,
+ DCCPO_ACK_VECTOR_0 = 38,
+ DCCPO_ACK_VECTOR_1 = 39,
+ DCCPO_TIMESTAMP = 41,
+ DCCPO_TIMESTAMP_ECHO = 42,
+ DCCPO_ELAPSED_TIME = 43,
+ DCCPO_MAX = 45,
+ DCCPO_MIN_CCID_SPECIFIC = 128,
+ DCCPO_MAX_CCID_SPECIFIC = 255,
+};
+
+/* DCCP features */
+enum {
+ DCCPF_RESERVED = 0,
+ DCCPF_SEQUENCE_WINDOW = 3,
+ DCCPF_SEND_ACK_VECTOR = 6,
+ DCCPF_SEND_NDP_COUNT = 7,
+ /* 10-127 reserved */
+ DCCPF_MIN_CCID_SPECIFIC = 128,
+ DCCPF_MAX_CCID_SPECIFIC = 255,
+};
+
+/* DCCP socket options */
+#define DCCP_SOCKOPT_PACKET_SIZE 1
+
+#ifdef __KERNEL__
+
+#include <linux/in.h>
+#include <linux/list.h>
+#include <linux/uio.h>
+#include <linux/workqueue.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_timewait_sock.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/tcp.h>
+
+enum dccp_state {
+ DCCP_OPEN = TCP_ESTABLISHED,
+ DCCP_REQUESTING = TCP_SYN_SENT,
+ DCCP_PARTOPEN = TCP_FIN_WAIT1, /* FIXME:
+ This mapping is horrible, but TCP has
+ no matching state for DCCP_PARTOPEN,
+ as TCP_SYN_RECV is already used by
+ DCCP_RESPOND, why don't stop using TCP
+ mapping of states? OK, now we don't use
+ sk_stream_sendmsg anymore, so doesn't
+ seem to exist any reason for us to
+ do the TCP mapping here */
+ DCCP_LISTEN = TCP_LISTEN,
+ DCCP_RESPOND = TCP_SYN_RECV,
+ DCCP_CLOSING = TCP_CLOSING,
+ DCCP_TIME_WAIT = TCP_TIME_WAIT,
+ DCCP_CLOSED = TCP_CLOSE,
+ DCCP_MAX_STATES = TCP_MAX_STATES,
+};
+
+#define DCCP_STATE_MASK 0xf
+#define DCCP_ACTION_FIN (1<<7)
+
+enum {
+ DCCPF_OPEN = TCPF_ESTABLISHED,
+ DCCPF_REQUESTING = TCPF_SYN_SENT,
+ DCCPF_PARTOPEN = TCPF_FIN_WAIT1,
+ DCCPF_LISTEN = TCPF_LISTEN,
+ DCCPF_RESPOND = TCPF_SYN_RECV,
+ DCCPF_CLOSING = TCPF_CLOSING,
+ DCCPF_TIME_WAIT = TCPF_TIME_WAIT,
+ DCCPF_CLOSED = TCPF_CLOSE,
+};
+
+static inline struct dccp_hdr *dccp_hdr(const struct sk_buff *skb)
+{
+ return (struct dccp_hdr *)skb->h.raw;
+}
+
+static inline struct dccp_hdr_ext *dccp_hdrx(const struct sk_buff *skb)
+{
+ return (struct dccp_hdr_ext *)(skb->h.raw + sizeof(struct dccp_hdr));
+}
+
+static inline unsigned int __dccp_basic_hdr_len(const struct dccp_hdr *dh)
+{
+ return sizeof(*dh) + (dh->dccph_x ? sizeof(struct dccp_hdr_ext) : 0);
+}
+
+static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+ return __dccp_basic_hdr_len(dh);
+}
+
+static inline __u64 dccp_hdr_seq(const struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u64 seq_nr = ntohl(dh->dccph_seq << 8);
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u64 seq_nr = ntohl(dh->dccph_seq);
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+
+ if (dh->dccph_x != 0)
+ seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low);
+
+ return seq_nr;
+}
+
+static inline struct dccp_hdr_request *dccp_hdr_request(struct sk_buff *skb)
+{
+ return (struct dccp_hdr_request *)(skb->h.raw + dccp_basic_hdr_len(skb));
+}
+
+static inline struct dccp_hdr_ack_bits *dccp_hdr_ack_bits(const struct sk_buff *skb)
+{
+ return (struct dccp_hdr_ack_bits *)(skb->h.raw + dccp_basic_hdr_len(skb));
+}
+
+static inline u64 dccp_hdr_ack_seq(const struct sk_buff *skb)
+{
+ const struct dccp_hdr_ack_bits *dhack = dccp_hdr_ack_bits(skb);
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ return (((u64)ntohl(dhack->dccph_ack_nr_high << 8)) << 32) + ntohl(dhack->dccph_ack_nr_low);
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ return (((u64)ntohl(dhack->dccph_ack_nr_high)) << 32) + ntohl(dhack->dccph_ack_nr_low);
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+}
+
+static inline struct dccp_hdr_response *dccp_hdr_response(struct sk_buff *skb)
+{
+ return (struct dccp_hdr_response *)(skb->h.raw + dccp_basic_hdr_len(skb));
+}
+
+static inline struct dccp_hdr_reset *dccp_hdr_reset(struct sk_buff *skb)
+{
+ return (struct dccp_hdr_reset *)(skb->h.raw + dccp_basic_hdr_len(skb));
+}
+
+static inline unsigned int __dccp_hdr_len(const struct dccp_hdr *dh)
+{
+ return __dccp_basic_hdr_len(dh) +
+ dccp_packet_hdr_len(dh->dccph_type);
+}
+
+static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
+{
+ return __dccp_hdr_len(dccp_hdr(skb));
+}
+
+
+/* initial values for each feature */
+#define DCCPF_INITIAL_SEQUENCE_WINDOW 100
+/* FIXME: for now we're using CCID 3 (TFRC) */
+#define DCCPF_INITIAL_CCID 3
+#define DCCPF_INITIAL_SEND_ACK_VECTOR 0
+/* FIXME: for now we're default to 1 but it should really be 0 */
+#define DCCPF_INITIAL_SEND_NDP_COUNT 1
+
+#define DCCP_NDP_LIMIT 0xFFFFFF
+
+/**
+ * struct dccp_options - option values for a DCCP connection
+ * @dccpo_sequence_window - Sequence Window Feature (section 7.5.2)
+ * @dccpo_ccid - Congestion Control Id (CCID) (section 10)
+ * @dccpo_send_ack_vector - Send Ack Vector Feature (section 11.5)
+ * @dccpo_send_ndp_count - Send NDP Count Feature (7.7.2)
+ */
+struct dccp_options {
+ __u64 dccpo_sequence_window;
+ __u8 dccpo_ccid;
+ __u8 dccpo_send_ack_vector;
+ __u8 dccpo_send_ndp_count;
+};
+
+extern void __dccp_options_init(struct dccp_options *dccpo);
+extern void dccp_options_init(struct dccp_options *dccpo);
+extern int dccp_parse_options(struct sock *sk, struct sk_buff *skb);
+
+struct dccp_request_sock {
+ struct inet_request_sock dreq_inet_rsk;
+ __u64 dreq_iss;
+ __u64 dreq_isr;
+ __u32 dreq_service;
+};
+
+static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req)
+{
+ return (struct dccp_request_sock *)req;
+}
+
+extern struct inet_timewait_death_row dccp_death_row;
+
+/* Read about the ECN nonce to see why it is 253 */
+#define DCCP_MAX_ACK_VECTOR_LEN 253
+
+struct dccp_options_received {
+ u32 dccpor_ndp:24,
+ dccpor_ack_vector_len:8;
+ u32 dccpor_ack_vector_idx:10;
+ /* 22 bits hole, try to pack */
+ u32 dccpor_timestamp;
+ u32 dccpor_timestamp_echo;
+ u32 dccpor_elapsed_time;
+};
+
+struct ccid;
+
+enum dccp_role {
+ DCCP_ROLE_UNDEFINED,
+ DCCP_ROLE_LISTEN,
+ DCCP_ROLE_CLIENT,
+ DCCP_ROLE_SERVER,
+};
+
+/**
+ * struct dccp_sock - DCCP socket state
+ *
+ * @dccps_swl - sequence number window low
+ * @dccps_swh - sequence number window high
+ * @dccps_awl - acknowledgement number window low
+ * @dccps_awh - acknowledgement number window high
+ * @dccps_iss - initial sequence number sent
+ * @dccps_isr - initial sequence number received
+ * @dccps_osr - first OPEN sequence number received
+ * @dccps_gss - greatest sequence number sent
+ * @dccps_gsr - greatest valid sequence number received
+ * @dccps_gar - greatest valid ack number received on a non-Sync; initialized to %dccps_iss
+ * @dccps_timestamp_time - time of latest TIMESTAMP option
+ * @dccps_timestamp_echo - latest timestamp received on a TIMESTAMP option
+ * @dccps_ext_header_len - network protocol overhead (IP/IPv6 options)
+ * @dccps_pmtu_cookie - Last pmtu seen by socket
+ * @dccps_packet_size - Set thru setsockopt
+ * @dccps_role - Role of this sock, one of %dccp_role
+ * @dccps_ndp_count - number of Non Data Packets since last data packet
+ * @dccps_hc_rx_ackpkts - receiver half connection acked packets
+ */
+struct dccp_sock {
+ /* inet_connection_sock has to be the first member of dccp_sock */
+ struct inet_connection_sock dccps_inet_connection;
+ __u64 dccps_swl;
+ __u64 dccps_swh;
+ __u64 dccps_awl;
+ __u64 dccps_awh;
+ __u64 dccps_iss;
+ __u64 dccps_isr;
+ __u64 dccps_osr;
+ __u64 dccps_gss;
+ __u64 dccps_gsr;
+ __u64 dccps_gar;
+ unsigned long dccps_service;
+ struct timeval dccps_timestamp_time;
+ __u32 dccps_timestamp_echo;
+ __u32 dccps_packet_size;
+ unsigned long dccps_ndp_count;
+ __u16 dccps_ext_header_len;
+ __u32 dccps_pmtu_cookie;
+ __u32 dccps_mss_cache;
+ struct dccp_options dccps_options;
+ struct dccp_ackpkts *dccps_hc_rx_ackpkts;
+ void *dccps_hc_rx_ccid_private;
+ void *dccps_hc_tx_ccid_private;
+ struct ccid *dccps_hc_rx_ccid;
+ struct ccid *dccps_hc_tx_ccid;
+ struct dccp_options_received dccps_options_received;
+ struct timeval dccps_epoch;
+ enum dccp_role dccps_role:2;
+ __u8 dccps_hc_rx_insert_options:1;
+ __u8 dccps_hc_tx_insert_options:1;
+};
+
+static inline struct dccp_sock *dccp_sk(const struct sock *sk)
+{
+ return (struct dccp_sock *)sk;
+}
+
+static inline const char *dccp_role(const struct sock *sk)
+{
+ switch (dccp_sk(sk)->dccps_role) {
+ case DCCP_ROLE_UNDEFINED: return "undefined";
+ case DCCP_ROLE_LISTEN: return "listen";
+ case DCCP_ROLE_SERVER: return "server";
+ case DCCP_ROLE_CLIENT: return "client";
+ }
+ return NULL;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_DCCP_H */
diff --git a/include/linux/dmapool.h b/include/linux/dmapool.h
index e60bfdac348d..4932ee5c77f0 100644
--- a/include/linux/dmapool.h
+++ b/include/linux/dmapool.h
@@ -19,7 +19,8 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
void dma_pool_destroy(struct dma_pool *pool);
-void *dma_pool_alloc(struct dma_pool *pool, int mem_flags, dma_addr_t *handle);
+void *dma_pool_alloc(struct dma_pool *pool, unsigned int __nocast mem_flags,
+ dma_addr_t *handle);
void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 5e93e6dce9a4..a415f1d93e9a 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -1,6 +1,8 @@
#ifndef __DMI_H__
#define __DMI_H__
+#include <linux/list.h>
+
enum dmi_field {
DMI_NONE,
DMI_BIOS_VENDOR,
@@ -16,6 +18,24 @@ enum dmi_field {
DMI_STRING_MAX,
};
+enum dmi_device_type {
+ DMI_DEV_TYPE_ANY = 0,
+ DMI_DEV_TYPE_OTHER,
+ DMI_DEV_TYPE_UNKNOWN,
+ DMI_DEV_TYPE_VIDEO,
+ DMI_DEV_TYPE_SCSI,
+ DMI_DEV_TYPE_ETHERNET,
+ DMI_DEV_TYPE_TOKENRING,
+ DMI_DEV_TYPE_SOUND,
+ DMI_DEV_TYPE_IPMI = -1
+};
+
+struct dmi_header {
+ u8 type;
+ u8 length;
+ u16 handle;
+};
+
/*
* DMI callbacks for problem boards
*/
@@ -26,22 +46,32 @@ struct dmi_strmatch {
struct dmi_system_id {
int (*callback)(struct dmi_system_id *);
- char *ident;
+ const char *ident;
struct dmi_strmatch matches[4];
void *driver_data;
};
-#define DMI_MATCH(a,b) { a, b }
+#define DMI_MATCH(a, b) { a, b }
+
+struct dmi_device {
+ struct list_head list;
+ int type;
+ const char *name;
+ void *device_data; /* Type specific data */
+};
#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
extern int dmi_check_system(struct dmi_system_id *list);
extern char * dmi_get_system_info(int field);
-
+extern struct dmi_device * dmi_find_device(int type, const char *name,
+ struct dmi_device *from);
#else
static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
static inline char * dmi_get_system_info(int field) { return NULL; }
+static inline struct dmi_device * dmi_find_device(int type, const char *name,
+ struct dmi_device *from) { return NULL; }
#endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 73781ec165b4..c7c5dd316182 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -91,11 +91,6 @@ typedef struct {
#define EFI_PAGE_SHIFT 12
-/*
- * For current x86 implementations of EFI, there is
- * additional padding in the mem descriptors. This is not
- * the case in ia64. Need to have this fixed in the f/w.
- */
typedef struct {
u32 type;
u32 pad;
@@ -103,9 +98,6 @@ typedef struct {
u64 virt_addr;
u64 num_pages;
u64 attribute;
-#if defined (__i386__)
- u64 pad1;
-#endif
} efi_memory_desc_t;
typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg);
@@ -240,10 +232,12 @@ typedef struct {
} efi_system_table_t;
struct efi_memory_map {
- efi_memory_desc_t *phys_map;
- efi_memory_desc_t *map;
+ void *phys_map;
+ void *map;
+ void *map_end;
int nr_map;
unsigned long desc_version;
+ unsigned long desc_size;
};
/*
diff --git a/include/linux/elf.h b/include/linux/elf.h
index f5b3ba5a317d..ff955dbf510d 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -2,6 +2,7 @@
#define _LINUX_ELF_H
#include <linux/types.h>
+#include <linux/auxvec.h>
#include <asm/elf.h>
#ifndef elf_read_implies_exec
@@ -158,29 +159,6 @@ typedef __s64 Elf64_Sxword;
#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x)
-/* Symbolic values for the entries in the auxiliary table
- put on the initial stack */
-#define AT_NULL 0 /* end of vector */
-#define AT_IGNORE 1 /* entry should be ignored */
-#define AT_EXECFD 2 /* file descriptor of program */
-#define AT_PHDR 3 /* program headers for program */
-#define AT_PHENT 4 /* size of program header entry */
-#define AT_PHNUM 5 /* number of program headers */
-#define AT_PAGESZ 6 /* system page size */
-#define AT_BASE 7 /* base address of interpreter */
-#define AT_FLAGS 8 /* flags */
-#define AT_ENTRY 9 /* entry point of program */
-#define AT_NOTELF 10 /* program is not ELF */
-#define AT_UID 11 /* real uid */
-#define AT_EUID 12 /* effective uid */
-#define AT_GID 13 /* real gid */
-#define AT_EGID 14 /* effective gid */
-#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
-#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
-#define AT_CLKTCK 17 /* frequency at which times() increments */
-
-#define AT_SECURE 23 /* secure mode boolean */
-
typedef struct dynamic{
Elf32_Sword d_tag;
union{
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index ce8518e658b6..4522c7186bf3 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -69,6 +69,12 @@ static inline int is_multicast_ether_addr(const u8 *addr)
return ((addr[0] != 0xff) && (0x01 & addr[0]));
}
+static inline int is_broadcast_ether_addr(const u8 *addr)
+{
+ return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
+ (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
+}
+
/**
* is_valid_ether_addr - Determine if the given Ethernet address is valid
* @addr: Pointer to a six-byte array containing the Ethernet address
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index a0ab26aab450..ed1440ea4c91 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -250,6 +250,12 @@ struct ethtool_stats {
u64 data[0];
};
+struct ethtool_perm_addr {
+ u32 cmd; /* ETHTOOL_GPERMADDR */
+ u32 size;
+ u8 data[0];
+};
+
struct net_device;
/* Some generic methods drivers may use in their ethtool_ops */
@@ -261,6 +267,8 @@ u32 ethtool_op_get_sg(struct net_device *dev);
int ethtool_op_set_sg(struct net_device *dev, u32 data);
u32 ethtool_op_get_tso(struct net_device *dev);
int ethtool_op_set_tso(struct net_device *dev, u32 data);
+int ethtool_op_get_perm_addr(struct net_device *dev,
+ struct ethtool_perm_addr *addr, u8 *data);
/**
* &ethtool_ops - Alter and report network device settings
@@ -294,7 +302,8 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data);
* get_strings: Return a set of strings that describe the requested objects
* phys_id: Identify the device
* get_stats: Return statistics about the device
- *
+ * get_perm_addr: Gets the permanent hardware address
+ *
* Description:
*
* get_settings:
@@ -352,6 +361,7 @@ struct ethtool_ops {
int (*phys_id)(struct net_device *, u32);
int (*get_stats_count)(struct net_device *);
void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
+ int (*get_perm_addr)(struct net_device *, struct ethtool_perm_addr *, u8 *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
};
@@ -389,6 +399,7 @@ struct ethtool_ops {
#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */
#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
@@ -408,6 +419,8 @@ struct ethtool_ops {
#define SUPPORTED_FIBRE (1 << 10)
#define SUPPORTED_BNC (1 << 11)
#define SUPPORTED_10000baseT_Full (1 << 12)
+#define SUPPORTED_Pause (1 << 13)
+#define SUPPORTED_Asym_Pause (1 << 14)
/* Indicates what features are advertised by the interface. */
#define ADVERTISED_10baseT_Half (1 << 0)
@@ -423,6 +436,8 @@ struct ethtool_ops {
#define ADVERTISED_FIBRE (1 << 10)
#define ADVERTISED_BNC (1 << 11)
#define ADVERTISED_10000baseT_Full (1 << 12)
+#define ADVERTISED_Pause (1 << 13)
+#define ADVERTISED_Asym_Pause (1 << 14)
/* The following are all involved in forcing a particular link
* mode for the device for setting things. When getting the
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index a657130ba03a..f7bd1c7ebefb 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -313,6 +313,9 @@ struct ext2_inode {
#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */
+#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */
+#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */
+
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index c16662836c58..c0272d73ab20 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -373,6 +373,8 @@ struct ext3_inode {
#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */
#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */
#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */
+#define EXT3_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
+#define EXT3_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/fb.h b/include/linux/fb.h
index bc24beeed971..c698055266d0 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -107,6 +107,8 @@
#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */
#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */
#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */
+#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */
+#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
@@ -495,6 +497,9 @@ struct fb_cursor_user {
#define FB_EVENT_BLANK 0x08
/* Private modelist is to be replaced */
#define FB_EVENT_NEW_MODELIST 0x09
+/* The resolution of the passed in fb_info about to change and
+ all vc's should be changed */
+#define FB_EVENT_MODE_CHANGE_ALL 0x0A
struct fb_event {
struct fb_info *info;
@@ -614,7 +619,7 @@ struct fb_tilemap {
__u32 height; /* height of each tile in scanlines */
__u32 depth; /* color depth of each tile */
__u32 length; /* number of tiles in the map */
- __u8 *data; /* actual tile map: a bitmap array, packed
+ const __u8 *data; /* actual tile map: a bitmap array, packed
to the nearest byte */
};
@@ -820,13 +825,29 @@ extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
u32 height, u32 shift_high, u32 shift_low, u32 mod);
extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
-extern int fb_get_color_depth(struct fb_var_screeninfo *var);
+extern int fb_get_color_depth(struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix);
extern int fb_get_options(char *name, char **option);
extern int fb_new_modelist(struct fb_info *info);
extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
+static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
+ u8 *src, u32 s_pitch, u32 height)
+{
+ int i, j;
+
+ d_pitch -= s_pitch;
+
+ for (i = height; i--; ) {
+ /* s_pitch is a few bytes at the most, memcpy is suboptimal */
+ for (j = 0; j < s_pitch; j++)
+ *dst++ = *src++;
+ dst += d_pitch;
+ }
+}
+
/* drivers/video/fbsysfs.c */
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info);
@@ -856,8 +877,11 @@ extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
extern int fb_validate_mode(const struct fb_var_screeninfo *var,
struct fb_info *info);
extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
-extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs);
+extern const unsigned char *fb_firmware_edid(struct device *device);
+extern void fb_edid_to_monspecs(unsigned char *edid,
+ struct fb_monspecs *specs);
extern void fb_destroy_modedb(struct fb_videomode *modedb);
+extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
/* drivers/video/modedb.c */
#define VESA_MODEDB_SIZE 34
diff --git a/include/linux/file.h b/include/linux/file.h
index 5206beb9a80e..f5bbd4c508b3 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -9,6 +9,7 @@
#include <linux/posix_types.h>
#include <linux/compiler.h>
#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
/*
* The default fd array needs to be at least BITS_PER_LONG,
@@ -16,23 +17,33 @@
*/
#define NR_OPEN_DEFAULT BITS_PER_LONG
+struct fdtable {
+ unsigned int max_fds;
+ int max_fdset;
+ int next_fd;
+ struct file ** fd; /* current fd array */
+ fd_set *close_on_exec;
+ fd_set *open_fds;
+ struct rcu_head rcu;
+ struct files_struct *free_files;
+ struct fdtable *next;
+};
+
/*
* Open file table structure
*/
struct files_struct {
atomic_t count;
spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */
- int max_fds;
- int max_fdset;
- int next_fd;
- struct file ** fd; /* current fd array */
- fd_set *close_on_exec;
- fd_set *open_fds;
+ struct fdtable *fdt;
+ struct fdtable fdtab;
fd_set close_on_exec_init;
fd_set open_fds_init;
struct file * fd_array[NR_OPEN_DEFAULT];
};
+#define files_fdtable(files) (rcu_dereference((files)->fdt))
+
extern void FASTCALL(__fput(struct file *));
extern void FASTCALL(fput(struct file *));
@@ -59,13 +70,16 @@ extern fd_set *alloc_fdset(int);
extern void free_fdset(fd_set *, int);
extern int expand_files(struct files_struct *, int nr);
+extern void free_fdtable(struct fdtable *fdt);
+extern void __init files_defer_init(void);
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
{
struct file * file = NULL;
+ struct fdtable *fdt = files_fdtable(files);
- if (fd < files->max_fds)
- file = files->fd[fd];
+ if (fd < fdt->max_fds)
+ file = rcu_dereference(fdt->fd[fd]);
return file;
}
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 886255b69bb9..2063c0839d4f 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -3,6 +3,9 @@
#include <linux/module.h>
#include <linux/types.h>
#define FIRMWARE_NAME_MAX 30
+#define FW_ACTION_NOHOTPLUG 0
+#define FW_ACTION_HOTPLUG 1
+
struct firmware {
size_t size;
u8 *data;
@@ -11,7 +14,7 @@ struct device;
int request_firmware(const struct firmware **fw, const char *name,
struct device *device);
int request_firmware_nowait(
- struct module *module,
+ struct module *module, int hotplug,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
diff --git a/include/linux/font.h b/include/linux/font.h
index 8fc80a7d78ac..53b129f07f6f 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -15,9 +15,9 @@
struct font_desc {
int idx;
- char *name;
+ const char *name;
int width, height;
- void *data;
+ const void *data;
int pref;
};
@@ -32,7 +32,7 @@ struct font_desc {
#define ACORN8x8_IDX 8
#define MINI4x6_IDX 9
-extern struct font_desc font_vga_8x8,
+extern const struct font_desc font_vga_8x8,
font_vga_8x16,
font_pearl_8x8,
font_vga_6x11,
@@ -45,11 +45,11 @@ extern struct font_desc font_vga_8x8,
/* Find a font with a specific name */
-extern struct font_desc *find_font(char *name);
+extern const struct font_desc *find_font(const char *name);
/* Get the default font for a specific screen size */
-extern struct font_desc *get_default_font(int xres, int yres);
+extern const struct font_desc *get_default_font(int xres, int yres);
/* Max. length for the name of a predefined font */
#define MAX_FONT_NAME 32
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 67e6732d4fdc..e0b77c5af9a0 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/limits.h>
#include <linux/ioctl.h>
+#include <linux/rcuref.h>
/*
* It's silly to have NR_OPEN bigger than NR_FILE, but you can change
@@ -69,6 +70,7 @@ extern int dir_notify_enable;
#define READ 0
#define WRITE 1
#define READA 2 /* read-ahead - don't block if no resources */
+#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */
#define SPECIAL 4 /* For non-blockdevice requests in request queue */
#define READ_SYNC (READ | (1 << BIO_RW_SYNC))
#define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC))
@@ -281,19 +283,9 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
- unsigned int ia_attr_flags;
};
/*
- * This is the inode attributes flag definitions
- */
-#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */
-#define ATTR_FLAG_NOATIME 2 /* Don't update atime */
-#define ATTR_FLAG_APPEND 4 /* Append-only file */
-#define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */
-#define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */
-
-/*
* Includes for diskquotas.
*/
#include <linux/quota.h>
@@ -594,7 +586,6 @@ struct file {
unsigned int f_uid, f_gid;
struct file_ra_state f_ra;
- size_t f_maxcount;
unsigned long f_version;
void *f_security;
@@ -607,12 +598,13 @@ struct file {
spinlock_t f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
+ struct rcu_head f_rcuhead;
};
extern spinlock_t files_lock;
#define file_list_lock() spin_lock(&files_lock);
#define file_list_unlock() spin_unlock(&files_lock);
-#define get_file(x) atomic_inc(&(x)->f_count)
+#define get_file(x) rcuref_inc(&(x)->f_count)
#define file_count(x) atomic_read(&(x)->f_count)
#define MAX_NON_LFS ((1UL<<31) - 1)
@@ -1291,6 +1283,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
/* fs/open.c */
extern int do_truncate(struct dentry *, loff_t start);
+extern long do_sys_open(const char __user *filename, int flags, int mode);
extern struct file *filp_open(const char *, int, int);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
extern int filp_close(struct file *, fl_owner_t id);
@@ -1516,8 +1509,6 @@ extern void do_generic_mapping_read(struct address_space *mapping,
loff_t *, read_descriptor_t *, read_actor_t);
extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
-extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs);
extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos);
ssize_t generic_file_writev(struct file *filp, const struct iovec *iov,
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
new file mode 100644
index 000000000000..acbeb96a3353
--- /dev/null
+++ b/include/linux/fuse.h
@@ -0,0 +1,259 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+/* This file defines the kernel interface of FUSE */
+
+#include <asm/types.h>
+
+/** Version number of this interface */
+#define FUSE_KERNEL_VERSION 7
+
+/** Minor version number of this interface */
+#define FUSE_KERNEL_MINOR_VERSION 2
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+/** The major number of the fuse character device */
+#define FUSE_MAJOR 10
+
+/** The minor number of the fuse character device */
+#define FUSE_MINOR 229
+
+/* Make sure all structures are padded to 64bit boundary, so 32bit
+ userspace works under 64bit kernels */
+
+struct fuse_attr {
+ __u64 ino;
+ __u64 size;
+ __u64 blocks;
+ __u64 atime;
+ __u64 mtime;
+ __u64 ctime;
+ __u32 atimensec;
+ __u32 mtimensec;
+ __u32 ctimensec;
+ __u32 mode;
+ __u32 nlink;
+ __u32 uid;
+ __u32 gid;
+ __u32 rdev;
+};
+
+struct fuse_kstatfs {
+ __u64 blocks;
+ __u64 bfree;
+ __u64 bavail;
+ __u64 files;
+ __u64 ffree;
+ __u32 bsize;
+ __u32 namelen;
+};
+
+#define FATTR_MODE (1 << 0)
+#define FATTR_UID (1 << 1)
+#define FATTR_GID (1 << 2)
+#define FATTR_SIZE (1 << 3)
+#define FATTR_ATIME (1 << 4)
+#define FATTR_MTIME (1 << 5)
+#define FATTR_CTIME (1 << 6)
+
+/**
+ * Flags returned by the OPEN request
+ *
+ * FOPEN_DIRECT_IO: bypass page cache for this open file
+ * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
+ */
+#define FOPEN_DIRECT_IO (1 << 0)
+#define FOPEN_KEEP_CACHE (1 << 1)
+
+enum fuse_opcode {
+ FUSE_LOOKUP = 1,
+ FUSE_FORGET = 2, /* no reply */
+ FUSE_GETATTR = 3,
+ FUSE_SETATTR = 4,
+ FUSE_READLINK = 5,
+ FUSE_SYMLINK = 6,
+ FUSE_MKNOD = 8,
+ FUSE_MKDIR = 9,
+ FUSE_UNLINK = 10,
+ FUSE_RMDIR = 11,
+ FUSE_RENAME = 12,
+ FUSE_LINK = 13,
+ FUSE_OPEN = 14,
+ FUSE_READ = 15,
+ FUSE_WRITE = 16,
+ FUSE_STATFS = 17,
+ FUSE_RELEASE = 18,
+ FUSE_FSYNC = 20,
+ FUSE_SETXATTR = 21,
+ FUSE_GETXATTR = 22,
+ FUSE_LISTXATTR = 23,
+ FUSE_REMOVEXATTR = 24,
+ FUSE_FLUSH = 25,
+ FUSE_INIT = 26,
+ FUSE_OPENDIR = 27,
+ FUSE_READDIR = 28,
+ FUSE_RELEASEDIR = 29,
+ FUSE_FSYNCDIR = 30
+};
+
+/* Conservative buffer size for the client */
+#define FUSE_MAX_IN 8192
+
+#define FUSE_NAME_MAX 1024
+#define FUSE_SYMLINK_MAX 4096
+#define FUSE_XATTR_SIZE_MAX 4096
+
+struct fuse_entry_out {
+ __u64 nodeid; /* Inode ID */
+ __u64 generation; /* Inode generation: nodeid:gen must
+ be unique for the fs's lifetime */
+ __u64 entry_valid; /* Cache timeout for the name */
+ __u64 attr_valid; /* Cache timeout for the attributes */
+ __u32 entry_valid_nsec;
+ __u32 attr_valid_nsec;
+ struct fuse_attr attr;
+};
+
+struct fuse_forget_in {
+ __u64 nlookup;
+};
+
+struct fuse_attr_out {
+ __u64 attr_valid; /* Cache timeout for the attributes */
+ __u32 attr_valid_nsec;
+ __u32 dummy;
+ struct fuse_attr attr;
+};
+
+struct fuse_mknod_in {
+ __u32 mode;
+ __u32 rdev;
+};
+
+struct fuse_mkdir_in {
+ __u32 mode;
+ __u32 padding;
+};
+
+struct fuse_rename_in {
+ __u64 newdir;
+};
+
+struct fuse_link_in {
+ __u64 oldnodeid;
+};
+
+struct fuse_setattr_in {
+ __u32 valid;
+ __u32 padding;
+ struct fuse_attr attr;
+};
+
+struct fuse_open_in {
+ __u32 flags;
+ __u32 padding;
+};
+
+struct fuse_open_out {
+ __u64 fh;
+ __u32 open_flags;
+ __u32 padding;
+};
+
+struct fuse_release_in {
+ __u64 fh;
+ __u32 flags;
+ __u32 padding;
+};
+
+struct fuse_flush_in {
+ __u64 fh;
+ __u32 flush_flags;
+ __u32 padding;
+};
+
+struct fuse_read_in {
+ __u64 fh;
+ __u64 offset;
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_write_in {
+ __u64 fh;
+ __u64 offset;
+ __u32 size;
+ __u32 write_flags;
+};
+
+struct fuse_write_out {
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_statfs_out {
+ struct fuse_kstatfs st;
+};
+
+struct fuse_fsync_in {
+ __u64 fh;
+ __u32 fsync_flags;
+ __u32 padding;
+};
+
+struct fuse_setxattr_in {
+ __u32 size;
+ __u32 flags;
+};
+
+struct fuse_getxattr_in {
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_getxattr_out {
+ __u32 size;
+ __u32 padding;
+};
+
+struct fuse_init_in_out {
+ __u32 major;
+ __u32 minor;
+};
+
+struct fuse_in_header {
+ __u32 len;
+ __u32 opcode;
+ __u64 unique;
+ __u64 nodeid;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+ __u32 padding;
+};
+
+struct fuse_out_header {
+ __u32 len;
+ __s32 error;
+ __u64 unique;
+};
+
+struct fuse_dirent {
+ __u64 ino;
+ __u64 off;
+ __u32 namelen;
+ __u32 type;
+ char name[0];
+};
+
+#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
+#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_SIZE(d) \
+ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 65d6cfdb6d39..10f96c31971e 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -4,14 +4,40 @@
/* Second argument to futex syscall */
-#define FUTEX_WAIT (0)
-#define FUTEX_WAKE (1)
-#define FUTEX_FD (2)
-#define FUTEX_REQUEUE (3)
-#define FUTEX_CMP_REQUEUE (4)
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_FD 2
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
long do_futex(unsigned long uaddr, int op, int val,
unsigned long timeout, unsigned long uaddr2, int val2,
int val3);
+#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
+#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
+#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
+#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
+#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
+
+#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
+
+#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
+#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
+#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
+#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
+#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
+#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
+
+/* FUTEX_WAKE_OP will perform atomically
+ int oldval = *(int *)UADDR2;
+ *(int *)UADDR2 = oldval OP OPARG;
+ if (oldval CMP CMPARG)
+ wake UADDR2; */
+
+#define FUTEX_OP(op, oparg, cmp, cmparg) \
+ (((op & 0xf) << 28) | ((cmp & 0xf) << 24) \
+ | ((oparg & 0xfff) << 12) | (cmparg & 0xfff))
+
#endif
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 7c7400137e97..4dc990f3b5cc 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -40,6 +40,7 @@ struct vm_area_struct;
#define __GFP_ZERO 0x8000u /* Return zeroed page on success */
#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
#define __GFP_NORECLAIM 0x20000u /* No realy zone reclaim during allocation */
+#define __GFP_HARDWALL 0x40000u /* Enforce hardwall cpuset memory allocs */
#define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */
#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -48,14 +49,15 @@ struct vm_area_struct;
#define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
- __GFP_NOMEMALLOC|__GFP_NORECLAIM)
+ __GFP_NOMEMALLOC|__GFP_NORECLAIM|__GFP_HARDWALL)
#define GFP_ATOMIC (__GFP_HIGH)
#define GFP_NOIO (__GFP_WAIT)
#define GFP_NOFS (__GFP_WAIT | __GFP_IO)
#define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS)
-#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS)
-#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM)
+#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
+#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
+ __GFP_HIGHMEM)
/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
platforms, used as appropriate on others */
diff --git a/include/linux/hippidevice.h b/include/linux/hippidevice.h
index 9debe6bbe5f0..bab303dafd6e 100644
--- a/include/linux/hippidevice.h
+++ b/include/linux/hippidevice.h
@@ -26,8 +26,12 @@
#include <linux/if_hippi.h>
#ifdef __KERNEL__
-extern unsigned short hippi_type_trans(struct sk_buff *skb,
- struct net_device *dev);
+
+struct hippi_cb {
+ __u32 ifield;
+};
+
+extern __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev);
extern struct net_device *alloc_hippi_dev(int sizeof_priv);
#endif
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index f529d1442815..e670b0d13fe0 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -70,12 +70,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
void hugetlb_prefault_arch_hook(struct mm_struct *mm);
#endif
-#ifndef ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
-#define hugetlb_clean_stale_pgtable(pte) BUG()
-#else
-void hugetlb_clean_stale_pgtable(pte_t *pte);
-#endif
-
#else /* !CONFIG_HUGETLB_PAGE */
static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h
index 1b5018a965f5..7eb4004b3601 100644
--- a/include/linux/hwmon-sysfs.h
+++ b/include/linux/hwmon-sysfs.h
@@ -33,4 +33,19 @@ struct sensor_device_attribute sensor_dev_attr_##_name = { \
.index = _index, \
}
+struct sensor_device_attribute_2 {
+ struct device_attribute dev_attr;
+ u8 index;
+ u8 nr;
+};
+#define to_sensor_dev_attr_2(_dev_attr) \
+ container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr)
+
+#define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \
+struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \
+ .dev_attr = __ATTR(_name,_mode,_show,_store), \
+ .index = _index, \
+ .nr = _nr, \
+}
+
#endif /* _LINUX_HWMON_SYSFS_H */
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
new file mode 100644
index 000000000000..cd4b7a042b86
--- /dev/null
+++ b/include/linux/hwmon-vid.h
@@ -0,0 +1,45 @@
+/*
+ hwmon-vid.h - VID/VRM/VRD voltage conversions
+
+ Originally part of lm_sensors
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_HWMON_VID_H
+#define _LINUX_HWMON_VID_H
+
+int vid_from_reg(int val, int vrm);
+int vid_which_vrm(void);
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+ val is in mV to avoid floating point in the kernel.
+ Returned value is the 4-, 5- or 6-bit VID code.
+ Note that only VRM 9.x is supported for now. */
+static inline int vid_to_reg(int val, int vrm)
+{
+ switch (vrm) {
+ case 91: /* VRM 9.1 */
+ case 90: /* VRM 9.0 */
+ return ((val >= 1100) && (val <= 1850) ?
+ ((18499 - val * 10) / 25 + 5) / 10 : -1);
+ default:
+ return -1;
+ }
+}
+
+#endif /* _LINUX_HWMON_VID_H */
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
new file mode 100644
index 000000000000..0efd994c37f1
--- /dev/null
+++ b/include/linux/hwmon.h
@@ -0,0 +1,35 @@
+/*
+ hwmon.h - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+ This file declares helper functions for the sysfs class "hwmon",
+ for use by sensors drivers.
+
+ Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+*/
+
+#ifndef _HWMON_H_
+#define _HWMON_H_
+
+#include <linux/device.h>
+
+struct class_device *hwmon_device_register(struct device *dev);
+
+void hwmon_device_unregister(struct class_device *cdev);
+
+/* Scale user input to sensible values */
+static inline int SENSORS_LIMIT(long value, long low, long high)
+{
+ if (value < low)
+ return low;
+ else if (value > high)
+ return high;
+ else
+ return value;
+}
+
+#endif
+
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 33f08258f22b..44f30876a1c9 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -1,6 +1,6 @@
/* ------------------------------------------------------------------------- */
/* */
-/* i2c.h - definitions for the i2c-bus interface */
+/* i2c-id.h - identifier values for i2c drivers and adapters */
/* */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-1999 Simon G. Vogl
@@ -24,16 +24,6 @@
#define LINUX_I2C_ID_H
/*
- * This file is part of the i2c-bus package and contains the identifier
- * values for drivers, adapters and other folk populating these serial
- * worlds.
- *
- * These will change often (i.e. additions) , therefore this has been
- * separated from the functional interface definitions of the i2c api.
- *
- */
-
-/*
* ---- Driver types -----------------------------------------------------
* device id name + number function description, i2c address(es)
*
@@ -170,151 +160,113 @@
/*
* ---- Adapter types ----------------------------------------------------
- *
- * First, we distinguish between several algorithms to access the hardware
- * interface types, as a PCF 8584 needs other care than a bit adapter.
- */
-
-#define I2C_ALGO_NONE 0x000000
-#define I2C_ALGO_BIT 0x010000 /* bit style adapters */
-#define I2C_ALGO_PCF 0x020000 /* PCF 8584 style adapters */
-#define I2C_ALGO_ATI 0x030000 /* ATI video card */
-#define I2C_ALGO_SMBUS 0x040000
-#define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
-#define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
-#define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
-#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
-#define I2C_ALGO_SAA7134 0x090000
-#define I2C_ALGO_MPC824X 0x0a0000 /* Motorola 8240 / 8245 */
-#define I2C_ALGO_IPMI 0x0b0000 /* IPMI dummy adapter */
-#define I2C_ALGO_IPMB 0x0c0000 /* IPMB adapter */
-#define I2C_ALGO_MPC107 0x0d0000
-#define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
-
-#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
-#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
-#define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */
-#define I2C_ALGO_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
-#define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */
-#define I2C_ALGO_SGI 0x160000 /* SGI algorithm */
-
-#define I2C_ALGO_USB 0x170000 /* USB algorithm */
-#define I2C_ALGO_VIRT 0x180000 /* Virtual bus adapter */
-
-#define I2C_ALGO_MV64XXX 0x190000 /* Marvell mv64xxx i2c ctlr */
-#define I2C_ALGO_PCA 0x1a0000 /* PCA 9564 style adapters */
-#define I2C_ALGO_AU1550 0x1b0000 /* Au1550 PSC algorithm */
-
-#define I2C_ALGO_EXP 0x800000 /* experimental */
-
-#define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
-#define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
-
-#define I2C_HW_ADAPS 0x10000 /* # adapter types */
-#define I2C_HW_MASK 0xffff
-
-
-/* hw specific modules that are defined per algorithm layer
*/
/* --- Bit algorithm adapters */
-#define I2C_HW_B_LP 0x00 /* Parallel port Philips style adapter */
-#define I2C_HW_B_LPC 0x01 /* Parallel port, over control reg. */
-#define I2C_HW_B_SER 0x02 /* Serial line interface */
-#define I2C_HW_B_ELV 0x03 /* ELV Card */
-#define I2C_HW_B_VELLE 0x04 /* Vellemann K8000 */
-#define I2C_HW_B_BT848 0x05 /* BT848 video boards */
-#define I2C_HW_B_WNV 0x06 /* Winnov Videums */
-#define I2C_HW_B_VIA 0x07 /* Via vt82c586b */
-#define I2C_HW_B_HYDRA 0x08 /* Apple Hydra Mac I/O */
-#define I2C_HW_B_G400 0x09 /* Matrox G400 */
-#define I2C_HW_B_I810 0x0a /* Intel I810 */
-#define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
-#define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
-#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
-#define I2C_HW_B_SCX200 0x0e /* Nat'l Semi SCx200 I2C */
-#define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
-#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
-#define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
-#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
-#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface (ARM) */
-#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
-#define I2C_HW_B_IXP2000 0x16 /* GPIO on IXP2000 systems */
-#define I2C_HW_B_IXP4XX 0x17 /* GPIO on IXP4XX systems */
-#define I2C_HW_B_S3VIA 0x18 /* S3Via ProSavage adapter */
-#define I2C_HW_B_ZR36067 0x19 /* Zoran-36057/36067 based boards */
-#define I2C_HW_B_PCILYNX 0x1a /* TI PCILynx I2C adapter */
-#define I2C_HW_B_CX2388x 0x1b /* connexant 2388x based tv cards */
+#define I2C_HW_B_LP 0x010000 /* Parallel port Philips style */
+#define I2C_HW_B_LPC 0x010001 /* Parallel port control reg. */
+#define I2C_HW_B_SER 0x010002 /* Serial line interface */
+#define I2C_HW_B_ELV 0x010003 /* ELV Card */
+#define I2C_HW_B_VELLE 0x010004 /* Vellemann K8000 */
+#define I2C_HW_B_BT848 0x010005 /* BT848 video boards */
+#define I2C_HW_B_WNV 0x010006 /* Winnov Videums */
+#define I2C_HW_B_VIA 0x010007 /* Via vt82c586b */
+#define I2C_HW_B_HYDRA 0x010008 /* Apple Hydra Mac I/O */
+#define I2C_HW_B_G400 0x010009 /* Matrox G400 */
+#define I2C_HW_B_I810 0x01000a /* Intel I810 */
+#define I2C_HW_B_VOO 0x01000b /* 3dfx Voodoo 3 / Banshee */
+#define I2C_HW_B_PPORT 0x01000c /* Primitive parallel port adapter */
+#define I2C_HW_B_SAVG 0x01000d /* Savage 4 */
+#define I2C_HW_B_SCX200 0x01000e /* Nat'l Semi SCx200 I2C */
+#define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */
+#define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */
+#define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */
+#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */
+#define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */
+#define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */
+#define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */
+#define I2C_HW_B_IXP4XX 0x010017 /* GPIO on IXP4XX systems */
+#define I2C_HW_B_S3VIA 0x010018 /* S3Via ProSavage adapter */
+#define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */
+#define I2C_HW_B_PCILYNX 0x01001a /* TI PCILynx I2C adapter */
+#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */
+#define I2C_HW_B_NVIDIA 0x01001c /* nvidia framebuffer driver */
+#define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */
+#define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */
/* --- PCF 8584 based algorithms */
-#define I2C_HW_P_LP 0x00 /* Parallel port interface */
-#define I2C_HW_P_ISA 0x01 /* generic ISA Bus inteface card */
-#define I2C_HW_P_ELEK 0x02 /* Elektor ISA Bus inteface card */
+#define I2C_HW_P_LP 0x020000 /* Parallel port interface */
+#define I2C_HW_P_ISA 0x020001 /* generic ISA Bus inteface card */
+#define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */
/* --- PCA 9564 based algorithms */
-#define I2C_HW_A_ISA 0x00 /* generic ISA Bus interface card */
+#define I2C_HW_A_ISA 0x1a0000 /* generic ISA Bus interface card */
/* --- ACPI Embedded controller algorithms */
-#define I2C_HW_ACPI_EC 0x00
+#define I2C_HW_ACPI_EC 0x1f0000
/* --- MPC824x PowerPC adapters */
-#define I2C_HW_MPC824X 0x00 /* Motorola 8240 / 8245 */
+#define I2C_HW_MPC824X 0x100001 /* Motorola 8240 / 8245 */
/* --- MPC8xx PowerPC adapters */
-#define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
+#define I2C_HW_MPC8XX_EPON 0x110000 /* Eponymous MPC8xx I2C adapter */
/* --- ITE based algorithms */
-#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
+#define I2C_HW_I_IIC 0x080000 /* controller on the ITE */
/* --- PowerPC on-chip adapters */
-#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
+#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
/* --- Broadcom SiByte adapters */
-#define I2C_HW_SIBYTE 0x00
+#define I2C_HW_SIBYTE 0x150000
/* --- SGI adapters */
-#define I2C_HW_SGI_VINO 0x00
-#define I2C_HW_SGI_MACE 0x01
+#define I2C_HW_SGI_VINO 0x160000
+#define I2C_HW_SGI_MACE 0x160001
/* --- XSCALE on-chip adapters */
-#define I2C_HW_IOP3XX 0x00
+#define I2C_HW_IOP3XX 0x140000
/* --- Au1550 PSC adapters adapters */
-#define I2C_HW_AU1550_PSC 0x00
+#define I2C_HW_AU1550_PSC 0x1b0000
/* --- SMBus only adapters */
-#define I2C_HW_SMBUS_PIIX4 0x00
-#define I2C_HW_SMBUS_ALI15X3 0x01
-#define I2C_HW_SMBUS_VIA2 0x02
-#define I2C_HW_SMBUS_VOODOO3 0x03
-#define I2C_HW_SMBUS_I801 0x04
-#define I2C_HW_SMBUS_AMD756 0x05
-#define I2C_HW_SMBUS_SIS5595 0x06
-#define I2C_HW_SMBUS_ALI1535 0x07
-#define I2C_HW_SMBUS_SIS630 0x08
-#define I2C_HW_SMBUS_SIS96X 0x09
-#define I2C_HW_SMBUS_AMD8111 0x0a
-#define I2C_HW_SMBUS_SCX200 0x0b
-#define I2C_HW_SMBUS_NFORCE2 0x0c
-#define I2C_HW_SMBUS_W9968CF 0x0d
-#define I2C_HW_SMBUS_OV511 0x0e /* OV511(+) USB 1.1 webcam ICs */
-#define I2C_HW_SMBUS_OV518 0x0f /* OV518(+) USB 1.1 webcam ICs */
-#define I2C_HW_SMBUS_OV519 0x10 /* OV519 USB 1.1 webcam IC */
-#define I2C_HW_SMBUS_OVFX2 0x11 /* Cypress/OmniVision FX2 webcam */
+#define I2C_HW_SMBUS_PIIX4 0x040000
+#define I2C_HW_SMBUS_ALI15X3 0x040001
+#define I2C_HW_SMBUS_VIA2 0x040002
+#define I2C_HW_SMBUS_VOODOO3 0x040003
+#define I2C_HW_SMBUS_I801 0x040004
+#define I2C_HW_SMBUS_AMD756 0x040005
+#define I2C_HW_SMBUS_SIS5595 0x040006
+#define I2C_HW_SMBUS_ALI1535 0x040007
+#define I2C_HW_SMBUS_SIS630 0x040008
+#define I2C_HW_SMBUS_SIS96X 0x040009
+#define I2C_HW_SMBUS_AMD8111 0x04000a
+#define I2C_HW_SMBUS_SCX200 0x04000b
+#define I2C_HW_SMBUS_NFORCE2 0x04000c
+#define I2C_HW_SMBUS_W9968CF 0x04000d
+#define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */
+#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */
+#define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */
+#define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */
/* --- ISA pseudo-adapter */
-#define I2C_HW_ISA 0x00
+#define I2C_HW_ISA 0x050000
/* --- IPMI pseudo-adapter */
-#define I2C_HW_IPMI 0x00
+#define I2C_HW_IPMI 0x0b0000
/* --- IPMB adapter */
-#define I2C_HW_IPMB 0x00
+#define I2C_HW_IPMB 0x0c0000
/* --- MCP107 adapter */
-#define I2C_HW_MPC107 0x00
+#define I2C_HW_MPC107 0x0d0000
/* --- Marvell mv64xxx i2c adapter */
-#define I2C_HW_MV64XXX 0x00
+#define I2C_HW_MV64XXX 0x190000
+
+/* --- Miscellaneous adapters */
+#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */
+#define I2C_HW_SAA7134 0x090000 /* SAA7134 video decoder bus */
#endif /* LINUX_I2C_ID_H */
diff --git a/include/linux/i2c-isa.h b/include/linux/i2c-isa.h
new file mode 100644
index 000000000000..67e3598c4cec
--- /dev/null
+++ b/include/linux/i2c-isa.h
@@ -0,0 +1,36 @@
+/*
+ * i2c-isa.h - definitions for the i2c-isa pseudo-i2c-adapter interface
+ *
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_I2C_ISA_H
+#define _LINUX_I2C_ISA_H
+
+#include <linux/i2c.h>
+
+extern int i2c_isa_add_driver(struct i2c_driver *driver);
+extern int i2c_isa_del_driver(struct i2c_driver *driver);
+
+/* Detect whether we are on the isa bus. This is only useful to hybrid
+ (i2c+isa) drivers. */
+#define i2c_is_isa_adapter(adapptr) \
+ ((adapptr)->id == I2C_HW_ISA)
+#define i2c_is_isa_client(clientptr) \
+ i2c_is_isa_adapter((clientptr)->adapter)
+
+#endif /* _LINUX_I2C_ISA_H */
diff --git a/include/linux/i2c-pxa.h b/include/linux/i2c-pxa.h
new file mode 100644
index 000000000000..5f3eaf802223
--- /dev/null
+++ b/include/linux/i2c-pxa.h
@@ -0,0 +1,48 @@
+#ifndef _LINUX_I2C_ALGO_PXA_H
+#define _LINUX_I2C_ALGO_PXA_H
+
+struct i2c_eeprom_emu_watcher {
+ void (*write)(void *, unsigned int addr, unsigned char newval);
+};
+
+struct i2c_eeprom_emu_watch {
+ struct list_head node;
+ unsigned int start;
+ unsigned int end;
+ struct i2c_eeprom_emu_watcher *ops;
+ void *data;
+};
+
+#define I2C_EEPROM_EMU_SIZE (256)
+
+struct i2c_eeprom_emu {
+ unsigned int size;
+ unsigned int ptr;
+ unsigned int seen_start;
+ struct list_head watch;
+
+ unsigned char bytes[I2C_EEPROM_EMU_SIZE];
+};
+
+typedef enum i2c_slave_event_e {
+ I2C_SLAVE_EVENT_START_READ,
+ I2C_SLAVE_EVENT_START_WRITE,
+ I2C_SLAVE_EVENT_STOP
+} i2c_slave_event_t;
+
+struct i2c_slave_client {
+ void *data;
+ void (*event)(void *ptr, i2c_slave_event_t event);
+ int (*read) (void *ptr);
+ void (*write)(void *ptr, unsigned int val);
+};
+
+extern int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *, void *data,
+ unsigned int addr, unsigned int size,
+ struct i2c_eeprom_emu_watcher *);
+
+extern void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *, void *data, struct i2c_eeprom_emu_watcher *watcher);
+
+extern struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void);
+
+#endif /* _LINUX_I2C_ALGO_PXA_H */
diff --git a/include/linux/i2c-sensor.h b/include/linux/i2c-sensor.h
deleted file mode 100644
index 21b625204956..000000000000
--- a/include/linux/i2c-sensor.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- i2c-sensor.h - Part of the i2c package
- was originally sensors.h - Part of lm_sensors, Linux kernel modules
- for hardware monitoring
- Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.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 _LINUX_I2C_SENSOR_H
-#define _LINUX_I2C_SENSOR_H
-
-/* A structure containing detect information.
- Force variables overrule all other variables; they force a detection on
- that place. If a specific chip is given, the module blindly assumes this
- chip type is present; if a general force (kind == 0) is given, the module
- will still try to figure out what type of chip is present. This is useful
- if for some reasons the detect for SMBus or ISA address space filled
- fails.
- probe: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
- A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the address.
- kind: The kind of chip. 0 equals any chip.
-*/
-struct i2c_force_data {
- unsigned short *force;
- unsigned short kind;
-};
-
-/* A structure containing the detect information.
- normal_i2c: filled in by the module writer. Terminated by I2C_CLIENT_ISA_END.
- A list of I2C addresses which should normally be examined.
- normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
- A list of ISA addresses which should normally be examined.
- probe: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
- A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the address. These
- addresses are also probed, as if they were in the 'normal' list.
- ignore: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
- A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the I2C address. These
- addresses are never probed. This parameter overrules 'normal' and
- 'probe', but not the 'force' lists.
- force_data: insmod parameters. A list, ending with an element of which
- the force field is NULL.
-*/
-struct i2c_address_data {
- unsigned short *normal_i2c;
- unsigned int *normal_isa;
- unsigned short *probe;
- unsigned short *ignore;
- struct i2c_force_data *forces;
-};
-
-#define SENSORS_MODULE_PARM_FORCE(name) \
- I2C_CLIENT_MODULE_PARM(force_ ## name, \
- "List of adapter,address pairs which are unquestionably" \
- " assumed to contain a `" # name "' chip")
-
-
-/* This defines several insmod variables, and the addr_data structure */
-#define SENSORS_INSMOD \
- I2C_CLIENT_MODULE_PARM(probe, \
- "List of adapter,address pairs to scan additionally"); \
- I2C_CLIENT_MODULE_PARM(ignore, \
- "List of adapter,address pairs not to scan"); \
- static struct i2c_address_data addr_data = { \
- .normal_i2c = normal_i2c, \
- .normal_isa = normal_isa, \
- .probe = probe, \
- .ignore = ignore, \
- .forces = forces, \
- }
-
-/* The following functions create an enum with the chip names as elements.
- The first element of the enum is any_chip. These are the only macros
- a module will want to use. */
-
-#define SENSORS_INSMOD_0 \
- enum chips { any_chip }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_1(chip1) \
- enum chips { any_chip, chip1 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- static struct i2c_force_data forces[] = {{force,any_chip},\
- {force_ ## chip1,chip1}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_2(chip1,chip2) \
- enum chips { any_chip, chip1, chip2 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
- enum chips { any_chip, chip1, chip2, chip3 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
- enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- SENSORS_MODULE_PARM_FORCE(chip7); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {force_ ## chip7,chip7}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
- I2C_CLIENT_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- SENSORS_MODULE_PARM_FORCE(chip7); \
- SENSORS_MODULE_PARM_FORCE(chip8); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {force_ ## chip7,chip7}, \
- {force_ ## chip8,chip8}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-/* Detect function. It iterates over all possible addresses itself. For
- SMBus addresses, it will only call found_proc if some client is connected
- to the SMBus (unless a 'force' matched); for ISA detections, this is not
- done. */
-extern int i2c_detect(struct i2c_adapter *adapter,
- struct i2c_address_data *address_data,
- int (*found_proc) (struct i2c_adapter *, int, int));
-
-
-/* This macro is used to scale user-input to sensible values in almost all
- chip drivers. */
-static inline int SENSORS_LIMIT(long value, long low, long high)
-{
- if (value < low)
- return low;
- else if (value > high)
- return high;
- else
- return value;
-}
-#endif /* def _LINUX_I2C_SENSOR_H */
diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
deleted file mode 100644
index 41d0635e0ba9..000000000000
--- a/include/linux/i2c-vid.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- i2c-vid.h - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
- Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
- With assistance from Trent Piepho <xyzzy@speakeasy.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*
- This file contains common code for decoding VID pins.
- This file is #included in various chip drivers in this directory.
- As the user is unlikely to load more than one driver which
- includes this code we don't worry about the wasted space.
- Reference: VRM x.y DC-DC Converter Design Guidelines,
- available at http://developer.intel.com
-*/
-
-/*
- AMD Opteron processors don't follow the Intel VRM spec.
- I'm going to "make up" 2.4 as the VRM spec for the Opterons.
- No good reason just a mnemonic for the 24x Opteron processor
- series
-
- Opteron VID encoding is:
-
- 00000 = 1.550 V
- 00001 = 1.525 V
- . . . .
- 11110 = 0.800 V
- 11111 = 0.000 V (off)
- */
-
-/*
- Legal val values 0x00 - 0x1f; except for VRD 10.0, 0x00 - 0x3f.
- vrm is the Intel VRM document version.
- Note: vrm version is scaled by 10 and the return value is scaled by 1000
- to avoid floating point in the kernel.
-*/
-
-int i2c_which_vrm(void);
-
-#define DEFAULT_VRM 82
-
-static inline int vid_from_reg(int val, int vrm)
-{
- int vid;
-
- switch(vrm) {
-
- case 0:
- return 0;
-
- case 100: /* VRD 10.0 */
- if((val & 0x1f) == 0x1f)
- return 0;
- if((val & 0x1f) <= 0x09 || val == 0x0a)
- vid = 10875 - (val & 0x1f) * 250;
- else
- vid = 18625 - (val & 0x1f) * 250;
- if(val & 0x20)
- vid -= 125;
- vid /= 10; /* only return 3 dec. places for now */
- return vid;
-
- case 24: /* Opteron processor */
- return(val == 0x1f ? 0 : 1550 - val * 25);
-
- case 91: /* VRM 9.1 */
- case 90: /* VRM 9.0 */
- return(val == 0x1f ? 0 :
- 1850 - val * 25);
-
- case 85: /* VRM 8.5 */
- return((val & 0x10 ? 25 : 0) +
- ((val & 0x0f) > 0x04 ? 2050 : 1250) -
- ((val & 0x0f) * 50));
-
- case 84: /* VRM 8.4 */
- val &= 0x0f;
- /* fall through */
- default: /* VRM 8.2 */
- return(val == 0x1f ? 0 :
- val & 0x10 ? 5100 - (val) * 100 :
- 2050 - (val) * 50);
- }
-}
-
-static inline int vid_to_reg(int val, int vrm)
-{
- switch (vrm) {
- case 91: /* VRM 9.1 */
- case 90: /* VRM 9.0 */
- return ((val >= 1100) && (val <= 1850) ?
- ((18499 - val * 10) / 25 + 5) / 10 : -1);
- default:
- return -1;
- }
-}
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index be837b13f297..be35332b67e6 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -34,6 +34,13 @@
#include <linux/device.h> /* for struct device */
#include <asm/semaphore.h>
+/* --- For i2c-isa ---------------------------------------------------- */
+
+extern void i2c_adapter_dev_release(struct device *dev);
+extern struct device_driver i2c_adapter_driver;
+extern struct class i2c_adapter_class;
+extern struct bus_type i2c_bus_type;
+
/* --- General options ------------------------------------------------ */
struct i2c_msg;
@@ -41,7 +48,6 @@ struct i2c_algorithm;
struct i2c_adapter;
struct i2c_client;
struct i2c_driver;
-struct i2c_client_address_data;
union i2c_smbus_data;
/*
@@ -143,12 +149,9 @@ struct i2c_driver {
*/
struct i2c_client {
unsigned int flags; /* div., see below */
- unsigned int addr; /* chip address - NOTE: 7bit */
+ unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
- /* _LOWER_ 7 bits of this char */
- /* addr: unsigned int to make lm_sensors i2c-isa adapter work
- more cleanly. It does not take any more memory space, due to
- alignment considerations */
+ /* _LOWER_ 7 bits */
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
int usage_count; /* How many accesses currently */
@@ -160,6 +163,11 @@ struct i2c_client {
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
+{
+ return to_i2c_client(container_of(kobj, struct device, kobj));
+}
+
static inline void *i2c_get_clientdata (struct i2c_client *dev)
{
return dev_get_drvdata (&dev->dev);
@@ -170,13 +178,6 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
dev_set_drvdata (&dev->dev, data);
}
-#define I2C_DEVNAME(str) .name = str
-
-static inline char *i2c_clientname(struct i2c_client *c)
-{
- return &c->name[0];
-}
-
/*
* The following structs are for those who like to implement new bus drivers:
* i2c_algorithm is the interface to a class of hardware solutions which can
@@ -184,9 +185,6 @@ static inline char *i2c_clientname(struct i2c_client *c)
* to name two of the most common.
*/
struct i2c_algorithm {
- char name[32]; /* textual description */
- unsigned int id;
-
/* If an adapter algorithm can't do I2C-level access, set master_xfer
to NULL. If an adapter algorithm can do SMBus access, set
smbus_xfer. If set to NULL, the SMBus protocol is simulated
@@ -214,8 +212,7 @@ struct i2c_algorithm {
*/
struct i2c_adapter {
struct module *owner;
- unsigned int id;/* == is algo->id | hwdep.struct->id, */
- /* for registered values see below */
+ unsigned int id;
unsigned int class;
struct i2c_algorithm *algo;/* the algorithm to access the bus */
void *algo_data;
@@ -292,12 +289,11 @@ struct i2c_client_address_data {
unsigned short *normal_i2c;
unsigned short *probe;
unsigned short *ignore;
- unsigned short *force;
+ unsigned short **forces;
};
/* Internal numbers to terminate lists */
#define I2C_CLIENT_END 0xfffeU
-#define I2C_CLIENT_ISA_END 0xfffefffeU
/* The numbers to use to set I2C bus address */
#define ANY_I2C_BUS 0xffff
@@ -356,10 +352,6 @@ extern int i2c_probe(struct i2c_adapter *adapter,
*/
extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
-/* This call returns a unique low identifier for each registered adapter,
- * or -1 if the adapter was not registered.
- */
-extern int i2c_adapter_id(struct i2c_adapter *adap);
extern struct i2c_adapter* i2c_get_adapter(int id);
extern void i2c_put_adapter(struct i2c_adapter *adap);
@@ -376,6 +368,12 @@ static inline int i2c_check_functionality(struct i2c_adapter *adap, u32 func)
return (func & i2c_get_functionality(adap)) == func;
}
+/* Return id number for a specific adapter */
+static inline int i2c_adapter_id(struct i2c_adapter *adap)
+{
+ return adap->nr;
+}
+
/*
* I2C Message - used for pure i2c transaction, also from /dev interface
*/
@@ -510,9 +508,6 @@ union i2c_smbus_data {
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
-#if 0
-#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */
-#endif
#define I2C_SMBUS 0x0720 /* SMBus-level access */
@@ -556,27 +551,148 @@ union i2c_smbus_data {
module_param_array(var, short, &var##_num, 0); \
MODULE_PARM_DESC(var,desc)
-/* This is the one you want to use in your own modules */
+#define I2C_CLIENT_MODULE_PARM_FORCE(name) \
+I2C_CLIENT_MODULE_PARM(force_##name, \
+ "List of adapter,address pairs which are " \
+ "unquestionably assumed to contain a `" \
+ # name "' chip")
+
+
+#define I2C_CLIENT_INSMOD_COMMON \
+I2C_CLIENT_MODULE_PARM(probe, "List of adapter,address pairs to scan " \
+ "additionally"); \
+I2C_CLIENT_MODULE_PARM(ignore, "List of adapter,address pairs not to " \
+ "scan"); \
+static struct i2c_client_address_data addr_data = { \
+ .normal_i2c = normal_i2c, \
+ .probe = probe, \
+ .ignore = ignore, \
+ .forces = forces, \
+}
+
+/* These are the ones you want to use in your own drivers. Pick the one
+ which matches the number of devices the driver differenciates between. */
#define I2C_CLIENT_INSMOD \
- I2C_CLIENT_MODULE_PARM(probe, \
- "List of adapter,address pairs to scan additionally"); \
- I2C_CLIENT_MODULE_PARM(ignore, \
- "List of adapter,address pairs not to scan"); \
I2C_CLIENT_MODULE_PARM(force, \
"List of adapter,address pairs to boldly assume " \
"to be present"); \
- static struct i2c_client_address_data addr_data = { \
- .normal_i2c = normal_i2c, \
- .probe = probe, \
- .ignore = ignore, \
- .force = force, \
- }
-
-/* Detect whether we are on the isa bus. If this returns true, all i2c
- access will fail! */
-#define i2c_is_isa_client(clientptr) \
- ((clientptr)->adapter->algo->id == I2C_ALGO_ISA)
-#define i2c_is_isa_adapter(adapptr) \
- ((adapptr)->algo->id == I2C_ALGO_ISA)
+ static unsigned short *forces[] = { \
+ force, \
+ NULL \
+ }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_1(chip1) \
+enum chips { any_chip, chip1 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+static unsigned short *forces[] = { force, force_##chip1, NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_2(chip1, chip2) \
+enum chips { any_chip, chip1, chip2 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3) \
+enum chips { any_chip, chip1, chip2, chip3 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4) \
+enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ force_##chip4, NULL}; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ force_##chip4, force_##chip5, \
+ NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ force_##chip4, force_##chip5, \
+ force_##chip6, NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \
+ chip7 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip7); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ force_##chip4, force_##chip5, \
+ force_##chip6, force_##chip7, \
+ NULL }; \
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \
+ chip7, chip8 }; \
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \
+ "boldly assume to be present"); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip7); \
+I2C_CLIENT_MODULE_PARM_FORCE(chip8); \
+static unsigned short *forces[] = { force, force_##chip1, \
+ force_##chip2, force_##chip3, \
+ force_##chip4, force_##chip5, \
+ force_##chip6, force_##chip7, \
+ force_##chip8, NULL }; \
+I2C_CLIENT_INSMOD_COMMON
#endif /* _LINUX_I2C_H */
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index b5b58e9c054c..fc2d4c8225aa 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -110,6 +110,8 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
{
return (struct ethhdr *)skb->mac.raw;
}
+
+extern struct ctl_table ether_table[];
#endif
#endif /* _LINUX_IF_ETHER_H */
diff --git a/include/linux/if_fc.h b/include/linux/if_fc.h
index 33330b458b95..376a34ea4723 100644
--- a/include/linux/if_fc.h
+++ b/include/linux/if_fc.h
@@ -44,7 +44,7 @@ struct fcllc {
__u8 ssap; /* source SAP */
__u8 llc; /* LLC control field */
__u8 protid[3]; /* protocol id */
- __u16 ethertype; /* ether type field */
+ __be16 ethertype; /* ether type field */
};
#endif /* _LINUX_IF_FC_H */
diff --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
index a912818e6361..1288a161bc0b 100644
--- a/include/linux/if_fddi.h
+++ b/include/linux/if_fddi.h
@@ -85,7 +85,7 @@ struct fddi_snap_hdr
__u8 ssap; /* always 0xAA */
__u8 ctrl; /* always 0x03 */
__u8 oui[FDDI_K_OUI_LEN]; /* organizational universal id */
- __u16 ethertype; /* packet type ID field */
+ __be16 ethertype; /* packet type ID field */
} __attribute__ ((packed));
/* Define FDDI LLC frame header */
diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h
index 3c94b1736570..511999c7eeda 100644
--- a/include/linux/if_frad.h
+++ b/include/linux/if_frad.h
@@ -191,10 +191,12 @@ struct frad_local
int buffer; /* current buffer for S508 firmware */
};
-extern void dlci_ioctl_set(int (*hook)(unsigned int, void __user *));
-
#endif /* __KERNEL__ */
#endif /* CONFIG_DLCI || CONFIG_DLCI_MODULE */
+#ifdef __KERNEL__
+extern void dlci_ioctl_set(int (*hook)(unsigned int, void __user *));
+#endif
+
#endif
diff --git a/include/linux/if_hippi.h b/include/linux/if_hippi.h
index c8ca72c46f76..94d31ca7d71a 100644
--- a/include/linux/if_hippi.h
+++ b/include/linux/if_hippi.h
@@ -102,9 +102,9 @@ struct hippi_fp_hdr
#error "Please fix <asm/byteorder.h>"
#endif
#else
- __u32 fixed;
+ __be32 fixed;
#endif
- __u32 d2_size;
+ __be32 d2_size;
} __attribute__ ((packed));
struct hippi_le_hdr
@@ -144,7 +144,7 @@ struct hippi_snap_hdr
__u8 ssap; /* always 0xAA */
__u8 ctrl; /* always 0x03 */
__u8 oui[HIPPI_OUI_LEN]; /* organizational universal id (zero)*/
- __u16 ethertype; /* packet type ID field */
+ __be16 ethertype; /* packet type ID field */
} __attribute__ ((packed));
struct hippi_hdr
diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h
index 3fba9e2f5427..5502f597cf0e 100644
--- a/include/linux/if_tr.h
+++ b/include/linux/if_tr.h
@@ -43,12 +43,16 @@ struct trh_hdr {
};
#ifdef __KERNEL__
+#include <linux/config.h>
#include <linux/skbuff.h>
static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
{
return (struct trh_hdr *)skb->mac.raw;
}
+#ifdef CONFIG_SYSCTL
+extern struct ctl_table tr_table[];
+#endif
#endif
/* This is an Token-Ring LLC structure */
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 096a85a58ae5..88aef7b86ef4 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -77,6 +77,7 @@ struct tun_struct {
#define TUNSETIFF _IOW('T', 202, int)
#define TUNSETPERSIST _IOW('T', 203, int)
#define TUNSETOWNER _IOW('T', 204, int)
+#define TUNSETLINK _IOW('T', 205, int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 62a9d89dfbe2..17d0c0d40b0e 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -155,7 +155,6 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
{
struct net_device_stats *stats;
- skb->real_dev = skb->dev;
skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
if (skb->dev == NULL) {
dev_kfree_skb_any(skb);
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 0c31ef0b5bad..28f4f3b36950 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -129,6 +129,9 @@ struct igmpv3_query {
#include <linux/skbuff.h>
#include <linux/in.h>
+extern int sysctl_igmp_max_memberships;
+extern int sysctl_igmp_max_msf;
+
struct ip_sf_socklist
{
unsigned int sl_max;
diff --git a/include/linux/in.h b/include/linux/in.h
index fb88c66d748d..ba355384016a 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -32,6 +32,7 @@ enum {
IPPROTO_PUP = 12, /* PUP protocol */
IPPROTO_UDP = 17, /* User Datagram Protocol */
IPPROTO_IDP = 22, /* XNS IDP protocol */
+ IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
IPPROTO_RSVP = 46, /* RSVP protocol */
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
diff --git a/include/linux/in6.h b/include/linux/in6.h
index dcf5720ffcbb..304aaedea305 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -148,13 +148,13 @@ struct in6_flowlabel_req
*/
#define IPV6_ADDRFORM 1
-#define IPV6_PKTINFO 2
-#define IPV6_HOPOPTS 3
-#define IPV6_DSTOPTS 4
-#define IPV6_RTHDR 5
-#define IPV6_PKTOPTIONS 6
+#define IPV6_2292PKTINFO 2
+#define IPV6_2292HOPOPTS 3
+#define IPV6_2292DSTOPTS 4
+#define IPV6_2292RTHDR 5
+#define IPV6_2292PKTOPTIONS 6
#define IPV6_CHECKSUM 7
-#define IPV6_HOPLIMIT 8
+#define IPV6_2292HOPLIMIT 8
#define IPV6_NEXTHOP 9
#define IPV6_AUTHHDR 10 /* obsolete */
#define IPV6_FLOWINFO 11
@@ -198,4 +198,44 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+/*
+ * Advanced API (RFC3542) (1)
+ *
+ * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c.
+ */
+
+#define IPV6_RECVPKTINFO 49
+#define IPV6_PKTINFO 50
+#define IPV6_RECVHOPLIMIT 51
+#define IPV6_HOPLIMIT 52
+#define IPV6_RECVHOPOPTS 53
+#define IPV6_HOPOPTS 54
+#define IPV6_RTHDRDSTOPTS 55
+#define IPV6_RECVRTHDR 56
+#define IPV6_RTHDR 57
+#define IPV6_RECVDSTOPTS 58
+#define IPV6_DSTOPTS 59
+#if 0 /* not yet */
+#define IPV6_RECVPATHMTU 60
+#define IPV6_PATHMTU 61
+#define IPV6_DONTFRAG 62
+#define IPV6_USE_MIN_MTU 63
+#endif
+
+/*
+ * Netfilter
+ *
+ * Following socket options are used in ip6_tables;
+ * see include/linux/netfilter_ipv6/ip6_tables.h.
+ *
+ * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO 64
+ * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES 65
+ */
+
+/*
+ * Advanced API (RFC3542) (2)
+ */
+#define IPV6_RECVTCLASS 66
+#define IPV6_TCLASS 67
+
#endif
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
new file mode 100644
index 000000000000..a4606e5810e5
--- /dev/null
+++ b/include/linux/inet_diag.h
@@ -0,0 +1,138 @@
+#ifndef _INET_DIAG_H_
+#define _INET_DIAG_H_ 1
+
+/* Just some random number */
+#define TCPDIAG_GETSOCK 18
+#define DCCPDIAG_GETSOCK 19
+
+#define INET_DIAG_GETSOCK_MAX 24
+
+/* Socket identity */
+struct inet_diag_sockid {
+ __u16 idiag_sport;
+ __u16 idiag_dport;
+ __u32 idiag_src[4];
+ __u32 idiag_dst[4];
+ __u32 idiag_if;
+ __u32 idiag_cookie[2];
+#define INET_DIAG_NOCOOKIE (~0U)
+};
+
+/* Request structure */
+
+struct inet_diag_req {
+ __u8 idiag_family; /* Family of addresses. */
+ __u8 idiag_src_len;
+ __u8 idiag_dst_len;
+ __u8 idiag_ext; /* Query extended information */
+
+ struct inet_diag_sockid id;
+
+ __u32 idiag_states; /* States to dump */
+ __u32 idiag_dbs; /* Tables to dump (NI) */
+};
+
+enum {
+ INET_DIAG_REQ_NONE,
+ INET_DIAG_REQ_BYTECODE,
+};
+
+#define INET_DIAG_REQ_MAX INET_DIAG_REQ_BYTECODE
+
+/* Bytecode is sequence of 4 byte commands followed by variable arguments.
+ * All the commands identified by "code" are conditional jumps forward:
+ * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be
+ * length of the command and its arguments.
+ */
+
+struct inet_diag_bc_op {
+ unsigned char code;
+ unsigned char yes;
+ unsigned short no;
+};
+
+enum {
+ INET_DIAG_BC_NOP,
+ INET_DIAG_BC_JMP,
+ INET_DIAG_BC_S_GE,
+ INET_DIAG_BC_S_LE,
+ INET_DIAG_BC_D_GE,
+ INET_DIAG_BC_D_LE,
+ INET_DIAG_BC_AUTO,
+ INET_DIAG_BC_S_COND,
+ INET_DIAG_BC_D_COND,
+};
+
+struct inet_diag_hostcond {
+ __u8 family;
+ __u8 prefix_len;
+ int port;
+ __u32 addr[0];
+};
+
+/* Base info structure. It contains socket identity (addrs/ports/cookie)
+ * and, alas, the information shown by netstat. */
+struct inet_diag_msg {
+ __u8 idiag_family;
+ __u8 idiag_state;
+ __u8 idiag_timer;
+ __u8 idiag_retrans;
+
+ struct inet_diag_sockid id;
+
+ __u32 idiag_expires;
+ __u32 idiag_rqueue;
+ __u32 idiag_wqueue;
+ __u32 idiag_uid;
+ __u32 idiag_inode;
+};
+
+/* Extensions */
+
+enum {
+ INET_DIAG_NONE,
+ INET_DIAG_MEMINFO,
+ INET_DIAG_INFO,
+ INET_DIAG_VEGASINFO,
+ INET_DIAG_CONG,
+};
+
+#define INET_DIAG_MAX INET_DIAG_CONG
+
+
+/* INET_DIAG_MEM */
+
+struct inet_diag_meminfo {
+ __u32 idiag_rmem;
+ __u32 idiag_wmem;
+ __u32 idiag_fmem;
+ __u32 idiag_tmem;
+};
+
+/* INET_DIAG_VEGASINFO */
+
+struct tcpvegas_info {
+ __u32 tcpv_enabled;
+ __u32 tcpv_rttcnt;
+ __u32 tcpv_rtt;
+ __u32 tcpv_minrtt;
+};
+
+#ifdef __KERNEL__
+struct sock;
+struct inet_hashinfo;
+
+struct inet_diag_handler {
+ struct inet_hashinfo *idiag_hashinfo;
+ void (*idiag_get_info)(struct sock *sk,
+ struct inet_diag_msg *r,
+ void *info);
+ __u16 idiag_info_size;
+ __u16 idiag_type;
+};
+
+extern int inet_diag_register(const struct inet_diag_handler *handler);
+extern void inet_diag_unregister(const struct inet_diag_handler *handler);
+#endif /* __KERNEL__ */
+
+#endif /* _INET_DIAG_H_ */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index c727c195a91a..68ab5f2ab9cd 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -2,17 +2,27 @@
#define _LINUX__INIT_TASK_H
#include <linux/file.h>
+#include <linux/rcupdate.h>
-#define INIT_FILES \
-{ \
- .count = ATOMIC_INIT(1), \
- .file_lock = SPIN_LOCK_UNLOCKED, \
+#define INIT_FDTABLE \
+{ \
.max_fds = NR_OPEN_DEFAULT, \
.max_fdset = __FD_SETSIZE, \
.next_fd = 0, \
.fd = &init_files.fd_array[0], \
.close_on_exec = &init_files.close_on_exec_init, \
.open_fds = &init_files.open_fds_init, \
+ .rcu = RCU_HEAD_INIT, \
+ .free_files = NULL, \
+ .next = NULL, \
+}
+
+#define INIT_FILES \
+{ \
+ .count = ATOMIC_INIT(1), \
+ .file_lock = SPIN_LOCK_UNLOCKED, \
+ .fdt = &init_files.fdtab, \
+ .fdtab = INIT_FDTABLE, \
.close_on_exec_init = { { 0, } }, \
.open_fds_init = { { 0, } }, \
.fd_array = { NULL, } \
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 93bb3afe646b..ee5b239092ed 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -47,6 +47,7 @@ struct inotify_event {
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
/* special flags */
+#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
#define IN_ISDIR 0x40000000 /* event occurred against dir */
#define IN_ONESHOT 0x80000000 /* only send event once */
diff --git a/include/linux/input.h b/include/linux/input.h
index bdc53c6cc962..e8c296ff6257 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -66,6 +66,7 @@ struct input_absinfo {
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
+#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */
#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */
@@ -86,6 +87,7 @@ struct input_absinfo {
#define EV_REL 0x02
#define EV_ABS 0x03
#define EV_MSC 0x04
+#define EV_SW 0x05
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
@@ -287,6 +289,8 @@ struct input_absinfo {
#define KEY_SCROLLDOWN 178
#define KEY_KPLEFTPAREN 179
#define KEY_KPRIGHTPAREN 180
+#define KEY_NEW 181
+#define KEY_REDO 182
#define KEY_F13 183
#define KEY_F14 184
@@ -333,6 +337,12 @@ struct input_absinfo {
#define KEY_KBDILLUMDOWN 229
#define KEY_KBDILLUMUP 230
+#define KEY_SEND 231
+#define KEY_REPLY 232
+#define KEY_FORWARDMAIL 233
+#define KEY_SAVE 234
+#define KEY_DOCUMENTS 235
+
#define KEY_UNKNOWN 240
#define BTN_MISC 0x100
@@ -551,6 +561,20 @@ struct input_absinfo {
#define ABS_MAX 0x3f
/*
+ * 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
+
+/*
* Misc events
*/
@@ -824,6 +848,7 @@ struct input_dev {
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
+ unsigned long swbit[NBITS(SW_MAX)];
int ff_effects_max;
unsigned int keycodemax;
@@ -844,6 +869,7 @@ struct input_dev {
unsigned long key[NBITS(KEY_MAX)];
unsigned long led[NBITS(LED_MAX)];
unsigned long snd[NBITS(SND_MAX)];
+ unsigned long sw[NBITS(SW_MAX)];
int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
@@ -886,6 +912,7 @@ struct input_dev {
#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
#define INPUT_DEVICE_ID_MATCH_DEVICE\
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
@@ -906,6 +933,7 @@ struct input_device_id {
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
+ unsigned long swbit[NBITS(SW_MAX)];
unsigned long driver_info;
};
@@ -998,6 +1026,11 @@ static inline void input_report_ff_status(struct input_dev *dev, unsigned int co
input_event(dev, EV_FF_STATUS, code, value);
}
+static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+ input_event(dev, EV_SW, code, !!value);
+}
+
static inline void input_regs(struct input_dev *dev, struct pt_regs *regs)
{
dev->regs = regs;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index d99e7aeb7d33..0a90205184b0 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -57,6 +57,11 @@ extern void disable_irq(unsigned int irq);
extern void enable_irq(unsigned int irq);
#endif
+#ifndef __ARCH_SET_SOFTIRQ_PENDING
+#define set_softirq_pending(x) (local_softirq_pending() = (x))
+#define or_softirq_pending(x) (local_softirq_pending() |= (x))
+#endif
+
/*
* Temporary defines for UP kernels, until all code gets fixed.
*/
@@ -123,7 +128,7 @@ struct softirq_action
asmlinkage void do_softirq(void);
extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
extern void FASTCALL(raise_softirq(unsigned int nr));
diff --git a/include/linux/ioctl32.h b/include/linux/ioctl32.h
index e8c4af32b3bb..948809d99917 100644
--- a/include/linux/ioctl32.h
+++ b/include/linux/ioctl32.h
@@ -14,26 +14,4 @@ struct ioctl_trans {
struct ioctl_trans *next;
};
-/*
- * Register an 32bit ioctl translation handler for ioctl cmd.
- *
- * handler == NULL: use 64bit ioctl handler.
- * arguments to handler: fd: file descriptor
- * cmd: ioctl command.
- * arg: ioctl argument
- * struct file *file: file descriptor pointer.
- */
-
-#ifdef CONFIG_COMPAT
-extern int __deprecated register_ioctl32_conversion(unsigned int cmd,
- ioctl_trans_handler_t handler);
-extern int __deprecated unregister_ioctl32_conversion(unsigned int cmd);
-
-#else
-
-#define register_ioctl32_conversion(cmd, handler) ({ 0; })
-#define unregister_ioctl32_conversion(cmd) ({ 0; })
-
-#endif
-
#endif
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 31e7cedd9f84..33e8a19a1a0f 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -196,6 +196,8 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
#endif
#endif
+extern int inet_sk_rebuild_header(struct sock *sk);
+
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 596ca6130159..938d55b813a5 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -35,6 +35,7 @@
#define __LINUX_IPMI_H
#include <linux/ipmi_msgdefs.h>
+#include <linux/compiler.h>
/*
* This file describes an interface to an IPMI driver. You have to
@@ -241,7 +242,8 @@ struct ipmi_recv_msg
/* The user_msg_data is the data supplied when a message was
sent, if this is a response to a sent message. If this is
not a response to a sent message, then user_msg_data will
- be NULL. */
+ be NULL. If the user above is NULL, then this will be the
+ intf. */
void *user_msg_data;
/* Call this when done with the message. It will presumably free
@@ -298,13 +300,19 @@ void ipmi_get_version(ipmi_user_t user,
this user, so it will affect all users of this interface. This is
so some initialization code can come in and do the OEM-specific
things it takes to determine your address (if not the BMC) and set
- it for everyone else. */
-void ipmi_set_my_address(ipmi_user_t user,
- unsigned char address);
-unsigned char ipmi_get_my_address(ipmi_user_t user);
-void ipmi_set_my_LUN(ipmi_user_t user,
- unsigned char LUN);
-unsigned char ipmi_get_my_LUN(ipmi_user_t user);
+ it for everyone else. Note that each channel can have its own address. */
+int ipmi_set_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char address);
+int ipmi_get_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *address);
+int ipmi_set_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char LUN);
+int ipmi_get_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *LUN);
/*
* Like ipmi_request, but lets you specify the number of retries and
@@ -585,6 +593,16 @@ struct ipmi_cmdspec
* things it takes to determine your address (if not the BMC) and set
* it for everyone else. You should probably leave the LUN alone.
*/
+struct ipmi_channel_lun_address_set
+{
+ unsigned short channel;
+ unsigned char value;
+};
+#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
+#define IPMICTL_SET_MY_CHANNEL_LUN_CMD _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_LUN_CMD _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
+/* Legacy interfaces, these only set IPMB 0. */
#define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 6fcd6a0ade24..bb6f88e14061 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -68,7 +68,7 @@ struct ipv6_opt_hdr {
struct rt0_hdr {
struct ipv6_rt_hdr rt_hdr;
- __u32 bitmap; /* strict/loose bit map */
+ __u32 reserved;
struct in6_addr addr[0];
#define rt0_type rt_hdr.type
@@ -189,10 +189,16 @@ struct inet6_skb_parm {
__u16 dst0;
__u16 srcrt;
__u16 dst1;
+ __u16 lastopt;
};
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
+static inline int inet6_iif(const struct sk_buff *skb)
+{
+ return IP6CB(skb)->iif;
+}
+
struct tcp6_request_sock {
struct tcp_request_sock req;
struct in6_addr loc_addr;
@@ -229,14 +235,20 @@ struct ipv6_pinfo {
/* pktoption flags */
union {
struct {
- __u8 srcrt:2,
+ __u16 srcrt:2,
+ osrcrt:2,
rxinfo:1,
+ rxoinfo:1,
rxhlim:1,
+ rxohlim:1,
hopopts:1,
+ ohopopts:1,
dstopts:1,
- rxflow:1;
+ odstopts:1,
+ rxflow:1,
+ rxtclass:1;
} bits;
- __u8 all;
+ __u16 all;
} rxopt;
/* sockopt flags */
@@ -245,6 +257,7 @@ struct ipv6_pinfo {
sndflow:1,
pmtudisc:2,
ipv6only:1;
+ __u8 tclass;
__u32 dst_cookie;
@@ -258,6 +271,7 @@ struct ipv6_pinfo {
struct ipv6_txoptions *opt;
struct rt6_info *rt;
int hop_limit;
+ int tclass;
} cork;
};
@@ -308,6 +322,36 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
#define __ipv6_only_sock(sk) (inet6_sk(sk)->ipv6only)
#define ipv6_only_sock(sk) ((sk)->sk_family == PF_INET6 && __ipv6_only_sock(sk))
+
+#include <linux/tcp.h>
+
+struct tcp6_timewait_sock {
+ struct tcp_timewait_sock tw_v6_sk;
+ struct in6_addr tw_v6_daddr;
+ struct in6_addr tw_v6_rcv_saddr;
+};
+
+static inline struct tcp6_timewait_sock *tcp6_twsk(const struct sock *sk)
+{
+ return (struct tcp6_timewait_sock *)sk;
+}
+
+static inline struct in6_addr *__tcp_v6_rcv_saddr(const struct sock *sk)
+{
+ return likely(sk->sk_state != TCP_TIME_WAIT) ?
+ &inet6_sk(sk)->rcv_saddr : &tcp6_twsk(sk)->tw_v6_rcv_saddr;
+}
+
+static inline struct in6_addr *tcp_v6_rcv_saddr(const struct sock *sk)
+{
+ return sk->sk_family == AF_INET6 ? __tcp_v6_rcv_saddr(sk) : NULL;
+}
+
+static inline int inet_v6_ipv6only(const struct sock *sk)
+{
+ return likely(sk->sk_state != TCP_TIME_WAIT) ?
+ ipv6_only_sock(sk) : inet_twsk(sk)->tw_ipv6only;
+}
#else
#define __ipv6_only_sock(sk) 0
#define ipv6_only_sock(sk) 0
@@ -322,8 +366,19 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
return NULL;
}
-#endif
+#define __tcp_v6_rcv_saddr(__sk) NULL
+#define tcp_v6_rcv_saddr(__sk) NULL
+#define tcp_twsk_ipv6only(__sk) 0
+#define inet_v6_ipv6only(__sk) 0
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
-#endif
+#define INET6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \
+ (((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ ((__sk)->sk_family == AF_INET6) && \
+ ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
+ ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#endif
+#endif /* __KERNEL__ */
+
+#endif /* _IPV6_H */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 069d3b84d311..69681c3b1f05 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -32,7 +32,12 @@
#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
#define IRQ_LEVEL 64 /* IRQ level triggered */
#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU 256 /* IRQ is per CPU */
+#if defined(ARCH_HAS_IRQ_PER_CPU)
+# define IRQ_PER_CPU 256 /* IRQ is per CPU */
+# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
+#else
+# define CHECK_IRQ_PER_CPU(var) 0
+#endif
/*
* Interrupt controller descriptor. This is all we need
@@ -71,16 +76,139 @@ typedef struct irq_desc {
unsigned int irq_count; /* For detecting broken interrupts */
unsigned int irqs_unhandled;
spinlock_t lock;
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+ unsigned int move_irq; /* Flag need to re-target intr dest*/
+#endif
} ____cacheline_aligned irq_desc_t;
extern irq_desc_t irq_desc [NR_IRQS];
+/* Return a pointer to the irq descriptor for IRQ. */
+static inline irq_desc_t *
+irq_descp (int irq)
+{
+ return irq_desc + irq;
+}
+
#include <asm/hw_irq.h> /* the arch dependent stuff */
extern int setup_irq(unsigned int irq, struct irqaction * new);
#ifdef CONFIG_GENERIC_HARDIRQS
extern cpumask_t irq_affinity[NR_IRQS];
+
+#ifdef CONFIG_SMP
+static inline void set_native_irq_info(int irq, cpumask_t mask)
+{
+ irq_affinity[irq] = mask;
+}
+#else
+static inline void set_native_irq_info(int irq, cpumask_t mask)
+{
+}
+#endif
+
+#ifdef CONFIG_SMP
+
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+extern cpumask_t pending_irq_cpumask[NR_IRQS];
+
+static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ desc->move_irq = 1;
+ pending_irq_cpumask[irq] = mask;
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+static inline void
+move_native_irq(int irq)
+{
+ cpumask_t tmp;
+ irq_desc_t *desc = irq_descp(irq);
+
+ if (likely (!desc->move_irq))
+ return;
+
+ desc->move_irq = 0;
+
+ if (likely(cpus_empty(pending_irq_cpumask[irq])))
+ return;
+
+ if (!desc->handler->set_affinity)
+ return;
+
+ /* note - we hold the desc->lock */
+ cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+
+ /*
+ * If there was a valid mask to work with, please
+ * do the disable, re-program, enable sequence.
+ * This is *not* particularly important for level triggered
+ * but in a edge trigger case, we might be setting rte
+ * when an active trigger is comming in. This could
+ * cause some ioapics to mal-function.
+ * Being paranoid i guess!
+ */
+ if (unlikely(!cpus_empty(tmp))) {
+ desc->handler->disable(irq);
+ desc->handler->set_affinity(irq,tmp);
+ desc->handler->enable(irq);
+ }
+ cpus_clear(pending_irq_cpumask[irq]);
+}
+
+#ifdef CONFIG_PCI_MSI
+/*
+ * Wonder why these are dummies?
+ * For e.g the set_ioapic_affinity_vector() calls the set_ioapic_affinity_irq()
+ * counter part after translating the vector to irq info. We need to perform
+ * this operation on the real irq, when we dont use vector, i.e when
+ * pci_use_vector() is false.
+ */
+static inline void move_irq(int irq)
+{
+}
+
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+}
+
+#else // CONFIG_PCI_MSI
+
+static inline void move_irq(int irq)
+{
+ move_native_irq(irq);
+}
+
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+ set_native_irq_info(irq, mask);
+}
+#endif // CONFIG_PCI_MSI
+
+#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE
+
+#define move_irq(x)
+#define move_native_irq(x)
+#define set_pending_irq(x,y)
+static inline void set_irq_info(int irq, cpumask_t mask)
+{
+ set_native_irq_info(irq, mask);
+}
+
+#endif // CONFIG_GENERIC_PENDING_IRQ
+
+#else // CONFIG_SMP
+
+#define move_irq(x)
+#define move_native_irq(x)
+
+#endif // CONFIG_SMP
+
extern int no_irq_affinity;
extern int noirqdebug_setup(char *str);
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 862083eb58ab..53eaee96065b 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -150,7 +150,6 @@ typedef struct {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 593407e865b1..de097269bd7f 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -28,6 +28,7 @@
#include <linux/buffer_head.h>
#include <linux/journal-head.h>
#include <linux/stddef.h>
+#include <linux/bit_spinlock.h>
#include <asm/semaphore.h>
#endif
@@ -914,7 +915,6 @@ extern int journal_wipe (journal_t *, int);
extern int journal_skip_recovery (journal_t *);
extern void journal_update_superblock (journal_t *, int);
extern void __journal_abort_hard (journal_t *);
-extern void __journal_abort_soft (journal_t *, int);
extern void journal_abort (journal_t *, int);
extern int journal_errno (journal_t *);
extern void journal_ack_err (journal_t *);
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index d7a2555a886c..6acfdbba734b 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -254,23 +254,23 @@ static inline u64 get_jiffies_64(void)
*/
static inline unsigned int jiffies_to_msecs(const unsigned long j)
{
-#if HZ <= 1000 && !(1000 % HZ)
- return (1000 / HZ) * j;
-#elif HZ > 1000 && !(HZ % 1000)
- return (j + (HZ / 1000) - 1)/(HZ / 1000);
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+ return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+ return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
#else
- return (j * 1000) / HZ;
+ return (j * MSEC_PER_SEC) / HZ;
#endif
}
static inline unsigned int jiffies_to_usecs(const unsigned long j)
{
-#if HZ <= 1000000 && !(1000000 % HZ)
- return (1000000 / HZ) * j;
-#elif HZ > 1000000 && !(HZ % 1000000)
- return (j + (HZ / 1000000) - 1)/(HZ / 1000000);
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+ return (USEC_PER_SEC / HZ) * j;
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+ return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
#else
- return (j * 1000000) / HZ;
+ return (j * USEC_PER_SEC) / HZ;
#endif
}
@@ -278,12 +278,12 @@ static inline unsigned long msecs_to_jiffies(const unsigned int m)
{
if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
return MAX_JIFFY_OFFSET;
-#if HZ <= 1000 && !(1000 % HZ)
- return (m + (1000 / HZ) - 1) / (1000 / HZ);
-#elif HZ > 1000 && !(HZ % 1000)
- return m * (HZ / 1000);
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+ return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+ return m * (HZ / MSEC_PER_SEC);
#else
- return (m * HZ + 999) / 1000;
+ return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
#endif
}
@@ -291,12 +291,12 @@ static inline unsigned long usecs_to_jiffies(const unsigned int u)
{
if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
return MAX_JIFFY_OFFSET;
-#if HZ <= 1000000 && !(1000000 % HZ)
- return (u + (1000000 / HZ) - 1) / (1000000 / HZ);
-#elif HZ > 1000000 && !(HZ % 1000000)
- return u * (HZ / 1000000);
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+ return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+ return u * (HZ / USEC_PER_SEC);
#else
- return (u * HZ + 999999) / 1000000;
+ return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
#endif
}
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 687ba8c9973d..4367ce4db52a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -307,8 +307,8 @@ struct sysinfo {
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};
-extern void BUILD_BUG(void);
-#define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
+/* Force a compilation error if condition is false */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#ifdef CONFIG_SYSCTL
extern int randomize_va_space;
diff --git a/include/linux/klist.h b/include/linux/klist.h
index eebf5e5696ec..74071254c9d3 100644
--- a/include/linux/klist.h
+++ b/include/linux/klist.h
@@ -9,20 +9,25 @@
* This file is rleased under the GPL v2.
*/
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/kref.h>
#include <linux/list.h>
-
+struct klist_node;
struct klist {
spinlock_t k_lock;
struct list_head k_list;
+ void (*get)(struct klist_node *);
+ void (*put)(struct klist_node *);
};
-extern void klist_init(struct klist * k);
-
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *));
struct klist_node {
struct klist * n_klist;
@@ -31,8 +36,8 @@ struct klist_node {
struct completion n_removed;
};
-extern void klist_add_tail(struct klist * k, struct klist_node * n);
-extern void klist_add_head(struct klist * k, struct klist_node * n);
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
extern void klist_del(struct klist_node * n);
extern void klist_remove(struct klist_node * n);
@@ -53,3 +58,4 @@ extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
extern void klist_iter_exit(struct klist_iter * i);
extern struct klist_node * klist_next(struct klist_iter * i);
+#endif
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index e050fc2d4c26..e30afdca7917 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -42,6 +42,9 @@
#define KPROBE_REENTER 0x00000004
#define KPROBE_HIT_SSDONE 0x00000008
+/* Attach to insert probes on any functions which should be ignored*/
+#define __kprobes __attribute__((__section__(".kprobes.text")))
+
struct kprobe;
struct pt_regs;
struct kretprobe;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6cd9ba63563b..022105c745fc 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1,23 +1,26 @@
/*
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, in which case the provisions of
- the GPL are applicable instead of the above. If you wish to allow
- the use of your version of this file only under the terms of the
- GPL and not to allow others to use your version of this file under
- the OSL, indicate your decision by deleting the provisions above and
- replace them with the notice and other provisions required by the GPL.
- If you do not delete the provisions above, a recipient may use your
- version of this file under either the OSL or the GPL.
-
+ * Copyright 2003-2005 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2005 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
*/
#ifndef __LINUX_LIBATA_H__
@@ -37,7 +40,6 @@
#undef ATA_VERBOSE_DEBUG /* yet more debugging output */
#undef ATA_IRQ_TRAP /* define to ack screaming irqs */
#undef ATA_NDEBUG /* define to disable quick runtime checks */
-#undef ATA_ENABLE_ATAPI /* define to enable ATAPI support */
#undef ATA_ENABLE_PATA /* define to enable PATA support in some
* low-level drivers */
#undef ATAPI_ENABLE_DMADIR /* enables ATAPI DMADIR bridge support */
@@ -113,6 +115,8 @@ enum {
ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */
ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */
ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */
+ ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once
+ * proper HSM is in place. */
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
@@ -363,7 +367,7 @@ struct ata_port_operations {
void (*host_stop) (struct ata_host_set *host_set);
- void (*bmdma_stop) (struct ata_port *ap);
+ void (*bmdma_stop) (struct ata_queued_cmd *qc);
u8 (*bmdma_status) (struct ata_port *ap);
};
@@ -424,7 +428,7 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s,
extern void ata_dev_config(struct ata_port *ap, unsigned int i);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
-extern void ata_bmdma_stop(struct ata_port *ap);
+extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -445,6 +449,7 @@ struct pci_bits {
unsigned long val;
};
+extern void ata_pci_host_stop (struct ata_host_set *host_set);
extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
@@ -644,7 +649,7 @@ static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
ap->ops->scr_write(ap, reg, val);
}
-static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
+static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
u32 val)
{
ap->ops->scr_write(ap, reg, val);
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 338f7795d8a0..147eb01e0d4b 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -33,6 +33,13 @@
ALIGN; \
name:
+#define KPROBE_ENTRY(name) \
+ .section .kprobes.text, "ax"; \
+ .globl name; \
+ ALIGN; \
+ name:
+
+
#endif
#define NORET_TYPE /**/
diff --git a/include/linux/list.h b/include/linux/list.h
index aab2db21b013..e6ec59682274 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -419,6 +419,20 @@ static inline void list_splice_init(struct list_head *list,
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
+ * list_for_each_entry_safe_continue - iterate over list of given type
+ * continuing after existing point safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
* list_for_each_rcu - iterate over an rcu-protected list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
@@ -620,6 +634,57 @@ static inline void hlist_add_after(struct hlist_node *n,
next->next->pprev = &next->next;
}
+/**
+ * hlist_add_before_rcu - adds the specified element to the specified hlist
+ * before the specified node while permitting racing traversals.
+ * @n: the new element to add to the hash list.
+ * @next: the existing element to add the new element before.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_add_head_rcu()
+ * or hlist_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_for_each_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.
+ */
+static inline void hlist_add_before_rcu(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ smp_wmb();
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+/**
+ * hlist_add_after_rcu - adds the specified element to the specified hlist
+ * after the specified node while permitting racing traversals.
+ * @prev: the existing element to add the new element after.
+ * @n: the new element to add to the hash list.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_add_head_rcu()
+ * or hlist_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_for_each_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.
+ */
+static inline void hlist_add_after_rcu(struct hlist_node *prev,
+ struct hlist_node *n)
+{
+ n->next = prev->next;
+ n->pprev = &prev->next;
+ smp_wmb();
+ prev->next = n;
+ if (n->next)
+ n->next->pprev = &n->next;
+}
+
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 8480aef10e62..58385ee1c0ac 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -150,8 +150,12 @@ void mpol_free_shared_policy(struct shared_policy *p);
struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
unsigned long idx);
+struct mempolicy *get_vma_policy(struct task_struct *task,
+ struct vm_area_struct *vma, unsigned long addr);
+
extern void numa_default_policy(void);
extern void numa_policy_init(void);
+extern struct mempolicy default_policy;
#else
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 374b615ea9ea..9b8d0476988a 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -22,6 +22,7 @@
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
@@ -54,7 +55,10 @@
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
-#define BMSR_RESV 0x07c0 /* Unused... */
+#define BMSR_RESV 0x00c0 /* Unused... */
+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
+#define BMSR_100FULL2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100HALF2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
@@ -114,6 +118,9 @@
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
+#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
+#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
+
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index aefedf04b9bb..18fc77f682de 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -33,6 +33,13 @@ struct mmc_csd {
unsigned int capacity;
};
+struct sd_scr {
+ unsigned char sda_vsn;
+ unsigned char bus_widths;
+#define SD_SCR_BUS_WIDTH_1 (1<<0)
+#define SD_SCR_BUS_WIDTH_4 (1<<2)
+};
+
struct mmc_host;
/*
@@ -47,19 +54,27 @@ struct mmc_card {
#define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
#define MMC_STATE_DEAD (1<<1) /* device no longer in stack */
#define MMC_STATE_BAD (1<<2) /* unrecognised device */
+#define MMC_STATE_SDCARD (1<<3) /* is an SD card */
+#define MMC_STATE_READONLY (1<<4) /* card is read-only */
u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */
+ u32 raw_scr[2]; /* raw card SCR */
struct mmc_cid cid; /* card identification */
struct mmc_csd csd; /* card specific */
+ struct sd_scr scr; /* extra SD information */
};
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD)
#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
+#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD)
+#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
+#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD)
+#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) ((c)->dev.bus_id)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index f90f674eb3b0..c1f021eddffa 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -46,16 +46,28 @@ struct mmc_ios {
#define MMC_BUSMODE_OPENDRAIN 1
#define MMC_BUSMODE_PUSHPULL 2
+ unsigned char chip_select; /* SPI chip select */
+
+#define MMC_CS_DONTCARE 0
+#define MMC_CS_HIGH 1
+#define MMC_CS_LOW 2
+
unsigned char power_mode; /* power supply mode */
#define MMC_POWER_OFF 0
#define MMC_POWER_UP 1
#define MMC_POWER_ON 2
+
+ unsigned char bus_width; /* data bus width */
+
+#define MMC_BUS_WIDTH_1 0
+#define MMC_BUS_WIDTH_4 2
};
struct mmc_host_ops {
void (*request)(struct mmc_host *host, struct mmc_request *req);
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
+ int (*get_ro)(struct mmc_host *host);
};
struct mmc_card;
@@ -63,11 +75,16 @@ struct device;
struct mmc_host {
struct device *dev;
+ struct class_device class_dev;
+ int index;
struct mmc_host_ops *ops;
unsigned int f_min;
unsigned int f_max;
u32 ocr_avail;
- char host_name[8];
+
+ unsigned long caps; /* Host capabilities */
+
+#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
/* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
@@ -80,6 +97,10 @@ struct mmc_host {
struct mmc_ios ios; /* current io bus settings */
u32 ocr; /* the current OCR setting */
+ unsigned int mode; /* current card mode of host */
+#define MMC_MODE_MMC 0
+#define MMC_MODE_SD 1
+
struct list_head cards; /* devices attached to this host */
wait_queue_head_t wq;
@@ -88,6 +109,8 @@ struct mmc_host {
struct mmc_card *card_selected; /* the selected MMC card */
struct work_struct detect;
+
+ unsigned long private[0] ____cacheline_aligned;
};
extern struct mmc_host *mmc_alloc_host(int extra, struct device *);
@@ -95,13 +118,18 @@ extern int mmc_add_host(struct mmc_host *);
extern void mmc_remove_host(struct mmc_host *);
extern void mmc_free_host(struct mmc_host *);
-#define mmc_priv(x) ((void *)((x) + 1))
+static inline void *mmc_priv(struct mmc_host *host)
+{
+ return (void *)host->private;
+}
+
#define mmc_dev(x) ((x)->dev)
+#define mmc_hostname(x) ((x)->class_dev.class_id)
extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
extern int mmc_resume_host(struct mmc_host *);
-extern void mmc_detect_change(struct mmc_host *);
+extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
#endif
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 0d35d4ffb360..1ab78e8d6c53 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -88,6 +88,8 @@ struct mmc_card;
extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
+ struct mmc_command *, int);
extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 896342817b97..f819cae92266 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -236,5 +236,12 @@ struct _mmc_csd {
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1 0
+#define SD_BUS_WIDTH_4 2
+
#endif /* MMC_MMC_PROTOCOL_H */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6c90461ed99f..5ed471b58f4f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -487,11 +487,27 @@ struct mem_section {
unsigned long section_mem_map;
};
-extern struct mem_section mem_section[NR_MEM_SECTIONS];
+#ifdef CONFIG_SPARSEMEM_EXTREME
+#define SECTIONS_PER_ROOT (PAGE_SIZE / sizeof (struct mem_section))
+#else
+#define SECTIONS_PER_ROOT 1
+#endif
+
+#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT)
+#define NR_SECTION_ROOTS (NR_MEM_SECTIONS / SECTIONS_PER_ROOT)
+#define SECTION_ROOT_MASK (SECTIONS_PER_ROOT - 1)
+
+#ifdef CONFIG_SPARSEMEM_EXTREME
+extern struct mem_section *mem_section[NR_SECTION_ROOTS];
+#else
+extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
+#endif
static inline struct mem_section *__nr_to_section(unsigned long nr)
{
- return &mem_section[nr];
+ if (!mem_section[SECTION_NR_TO_ROOT(nr)])
+ return NULL;
+ return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
}
/*
@@ -513,12 +529,12 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section)
static inline int valid_section(struct mem_section *section)
{
- return (section->section_mem_map & SECTION_MARKED_PRESENT);
+ return (section && (section->section_mem_map & SECTION_MARKED_PRESENT));
}
static inline int section_has_mem_map(struct mem_section *section)
{
- return (section->section_mem_map & SECTION_HAS_MEM_MAP);
+ return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
}
static inline int valid_section_nr(unsigned long nr)
@@ -572,6 +588,7 @@ static inline int pfn_valid(unsigned long pfn)
void sparse_init(void);
#else
#define sparse_init() do {} while (0)
+#define sparse_index_init(_sec, _nid) do {} while (0)
#endif /* CONFIG_SPARSEMEM */
#ifdef CONFIG_NODES_SPAN_OTHER_NODES
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index dce53ac1625d..47da39ba3f03 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -1,6 +1,6 @@
/*
* Device tables which are exported to userspace via
- * scripts/table2alias.c. You must keep that file in sync with this
+ * scripts/mod/file2alias.c. You must keep that file in sync with this
* header.
*/
@@ -33,7 +33,8 @@ struct ieee1394_device_id {
__u32 model_id;
__u32 specifier_id;
__u32 version;
- kernel_ulong_t driver_data;
+ kernel_ulong_t driver_data
+ __attribute__((aligned(sizeof(kernel_ulong_t))));
};
@@ -182,9 +183,18 @@ struct of_device_id
char name[32];
char type[32];
char compatible[128];
+#if __KERNEL__
void *data;
+#else
+ kernel_ulong_t data;
+#endif
};
+/* VIO */
+struct vio_device_id {
+ char type[32];
+ char compat[32];
+};
/* PCMCIA */
@@ -208,7 +218,8 @@ struct pcmcia_device_id {
#ifdef __KERNEL__
const char * prod_id[4];
#else
- kernel_ulong_t prod_id[4];
+ kernel_ulong_t prod_id[4]
+ __attribute__((aligned(sizeof(kernel_ulong_t))));
#endif
/* not matched against */
diff --git a/include/linux/msg.h b/include/linux/msg.h
index 2c4c6aa643ff..903e0ab8101f 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -77,6 +77,7 @@ struct msg_msg {
/* one msq_queue structure for each present queue on the system */
struct msg_queue {
struct kern_ipc_perm q_perm;
+ int q_id;
time_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index 5773ea42f6e4..0b08cd692201 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -980,7 +980,7 @@
/* I2C Registers */
/****************************************/
-#define MV64XXX_I2C_CTLR_NAME "mv64xxx i2c"
+#define MV64XXX_I2C_CTLR_NAME "mv64xxx_i2c"
#define MV64XXX_I2C_OFFSET 0xc000
#define MV64XXX_I2C_REG_BLOCK_SIZE 0x0020
diff --git a/include/linux/net.h b/include/linux/net.h
index 20cb226b2268..4e981585a89a 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -84,6 +84,7 @@ enum sock_type {
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
+ SOCK_DCCP = 6,
SOCK_PACKET = 10,
};
@@ -282,5 +283,15 @@ static struct proto_ops name##_ops = { \
#define MODULE_ALIAS_NETPROTO(proto) \
MODULE_ALIAS("net-pf-" __stringify(proto))
+#define MODULE_ALIAS_NET_PF_PROTO(pf, proto) \
+ MODULE_ALIAS("net-pf-" __stringify(pf) "-proto-" __stringify(proto))
+
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+extern ctl_table net_table[];
+extern int net_msg_cost;
+extern int net_msg_burst;
+#endif
+
#endif /* __KERNEL__ */
#endif /* _LINUX_NET_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3a0ed7f9e801..7c717907896d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -244,6 +244,7 @@ struct netdev_boot_setup {
};
#define NETDEV_BOOT_SETUP_MAX 8
+extern int __init netdev_boot_setup(char *str);
/*
* The DEVICE structure.
@@ -336,6 +337,7 @@ struct net_device
/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
+ unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
unsigned char addr_len; /* hardware address length */
unsigned short dev_id; /* for shared network cards */
@@ -497,10 +499,12 @@ static inline void *netdev_priv(struct net_device *dev)
#define SET_NETDEV_DEV(net, pdev) ((net)->class_dev.dev = (pdev))
struct packet_type {
- __be16 type; /* This is really htons(ether_type). */
- struct net_device *dev; /* NULL is wildcarded here */
- int (*func) (struct sk_buff *, struct net_device *,
- struct packet_type *);
+ __be16 type; /* This is really htons(ether_type). */
+ struct net_device *dev; /* NULL is wildcarded here */
+ int (*func) (struct sk_buff *,
+ struct net_device *,
+ struct packet_type *,
+ struct net_device *);
void *af_packet_priv;
struct list_head list;
};
@@ -671,6 +675,7 @@ extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
extern void dev_init(void);
extern int netdev_nit;
+extern int netdev_budget;
/* Called by rtnetlink.c:rtnl_unlock() */
extern void netdev_run_todo(void);
@@ -697,19 +702,9 @@ static inline int netif_carrier_ok(const struct net_device *dev)
extern void __netdev_watchdog_up(struct net_device *dev);
-static inline void netif_carrier_on(struct net_device *dev)
-{
- if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
- linkwatch_fire_event(dev);
- if (netif_running(dev))
- __netdev_watchdog_up(dev);
-}
+extern void netif_carrier_on(struct net_device *dev);
-static inline void netif_carrier_off(struct net_device *dev)
-{
- if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
- linkwatch_fire_event(dev);
-}
+extern void netif_carrier_off(struct net_device *dev);
/* Hot-plugging. */
static inline int netif_device_present(struct net_device *dev)
@@ -916,6 +911,14 @@ extern int skb_checksum_help(struct sk_buff *skb, int inward);
extern void net_enable_timestamp(void);
extern void net_disable_timestamp(void);
+#ifdef CONFIG_PROC_FS
+extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
+extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
+extern void dev_seq_stop(struct seq_file *seq, void *v);
+#endif
+
+extern void linkwatch_run_queue(void);
+
#endif /* __KERNEL__ */
#endif /* _LINUX_DEV_H */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 2e2045482cb1..be365e70ee99 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -21,10 +21,23 @@
#define NF_STOP 5
#define NF_MAX_VERDICT NF_STOP
+/* we overload the higher bits for encoding auxiliary data such as the queue
+ * number. Not nice, but better than additional function arguments. */
+#define NF_VERDICT_MASK 0x0000ffff
+#define NF_VERDICT_BITS 16
+
+#define NF_VERDICT_QMASK 0xffff0000
+#define NF_VERDICT_QBITS 16
+
+#define NF_QUEUE_NR(x) (((x << NF_VERDICT_QBITS) & NF_VERDICT_QMASK) | NF_QUEUE)
+
+/* only for userspace compatibility */
+#ifndef __KERNEL__
/* Generic cache responses from hook functions.
<= 0x2000 is used for protocol-flags. */
#define NFC_UNKNOWN 0x4000
#define NFC_ALTERED 0x8000
+#endif
#ifdef __KERNEL__
#include <linux/config.h>
@@ -101,15 +114,51 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
-typedef void nf_logfn(unsigned int hooknum,
+/* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
+ * disappear once iptables is replaced with pkttables. Please DO NOT use them
+ * for any new code! */
+#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
+#define NF_LOG_TCPOPT 0x02 /* Log TCP options */
+#define NF_LOG_IPOPT 0x04 /* Log IP options */
+#define NF_LOG_UID 0x08 /* Log UID owning local socket */
+#define NF_LOG_MASK 0x0f
+
+#define NF_LOG_TYPE_LOG 0x01
+#define NF_LOG_TYPE_ULOG 0x02
+
+struct nf_loginfo {
+ u_int8_t type;
+ union {
+ struct {
+ u_int32_t copy_len;
+ u_int16_t group;
+ u_int16_t qthreshold;
+ } ulog;
+ struct {
+ u_int8_t level;
+ u_int8_t logflags;
+ } log;
+ } u;
+};
+
+typedef void nf_logfn(unsigned int pf,
+ unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
+ const struct nf_loginfo *li,
const char *prefix);
+struct nf_logger {
+ struct module *me;
+ nf_logfn *logfn;
+ char *name;
+};
+
/* Function to register/unregister log function. */
-int nf_log_register(int pf, nf_logfn *logfn);
-void nf_log_unregister(int pf, nf_logfn *logfn);
+int nf_log_register(int pf, struct nf_logger *logger);
+int nf_log_unregister_pf(int pf);
+void nf_log_unregister_logger(struct nf_logger *logger);
/* Calls the registered backend logging function */
void nf_log_packet(int pf,
@@ -117,6 +166,7 @@ void nf_log_packet(int pf,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
+ struct nf_loginfo *li,
const char *fmt, ...);
/* Activate hook; either okfn or kfree_skb called, unless a hook
@@ -175,11 +225,16 @@ int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt,
int *len);
/* Packet queuing */
-typedef int (*nf_queue_outfn_t)(struct sk_buff *skb,
- struct nf_info *info, void *data);
+struct nf_queue_handler {
+ int (*outfn)(struct sk_buff *skb, struct nf_info *info,
+ unsigned int queuenum, void *data);
+ void *data;
+ char *name;
+};
extern int nf_register_queue_handler(int pf,
- nf_queue_outfn_t outfn, void *data);
+ struct nf_queue_handler *qh);
extern int nf_unregister_queue_handler(int pf);
+extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh);
extern void nf_reinject(struct sk_buff *skb,
struct nf_info *info,
unsigned int verdict);
@@ -190,6 +245,27 @@ extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
/* FIXME: Before cache is ever used, this must be implemented for real. */
extern void nf_invalidate_cache(int pf);
+/* Call this before modifying an existing packet: ensures it is
+ modifiable and linear to the point you care about (writable_len).
+ Returns true or false. */
+extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
+
+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;
+};
+
+#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
+
+extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
+extern int nf_unregister_queue_rerouter(int pf);
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+extern struct proc_dir_entry *proc_net_netfilter;
+#endif
+
#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
new file mode 100644
index 000000000000..1d5b10ae2399
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink.h
@@ -0,0 +1,169 @@
+#ifndef _NFNETLINK_H
+#define _NFNETLINK_H
+#include <linux/types.h>
+
+#ifndef __KERNEL__
+/* nfnetlink groups: Up to 32 maximum - backwards compatibility for userspace */
+#define NF_NETLINK_CONNTRACK_NEW 0x00000001
+#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002
+#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004
+#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008
+#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010
+#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020
+#endif
+
+enum nfnetlink_groups {
+ NFNLGRP_NONE,
+#define NFNLGRP_NONE NFNLGRP_NONE
+ NFNLGRP_CONNTRACK_NEW,
+#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW
+ NFNLGRP_CONNTRACK_UPDATE,
+#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE
+ NFNLGRP_CONNTRACK_DESTROY,
+#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY
+ NFNLGRP_CONNTRACK_EXP_NEW,
+#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW
+ NFNLGRP_CONNTRACK_EXP_UPDATE,
+#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE
+ NFNLGRP_CONNTRACK_EXP_DESTROY,
+#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY
+ __NFNLGRP_MAX,
+};
+#define NFNLGRP_MAX (__NFNLGRP_MAX - 1)
+
+/* Generic structure for encapsulation optional netfilter information.
+ * It is reminiscent of sockaddr, but with sa_family replaced
+ * with attribute type.
+ * ! This should someday be put somewhere generic as now rtnetlink and
+ * ! nfnetlink use the same attributes methods. - J. Schulist.
+ */
+
+struct nfattr
+{
+ u_int16_t nfa_len;
+ u_int16_t nfa_type;
+} __attribute__ ((packed));
+
+/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time
+ * to put this in a generic file */
+
+#define NFA_ALIGNTO 4
+#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
+#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
+ && (nfa)->nfa_len <= (len))
+#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
+ (struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
+#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len))
+#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
+#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
+#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
+#define NFA_NEST(skb, type) \
+({ struct nfattr *__start = (struct nfattr *) (skb)->tail; \
+ NFA_PUT(skb, type, 0, NULL); \
+ __start; })
+#define NFA_NEST_END(skb, start) \
+({ (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
+ (skb)->len; })
+#define NFA_NEST_CANCEL(skb, start) \
+({ if (start) \
+ skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+ -1; })
+
+/* General form of address family dependent message.
+ */
+struct nfgenmsg {
+ u_int8_t nfgen_family; /* AF_xxx */
+ u_int8_t version; /* nfnetlink version */
+ u_int16_t res_id; /* resource id */
+} __attribute__ ((packed));
+
+#define NFNETLINK_V0 0
+
+#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \
+ + NLMSG_ALIGN(sizeof(struct nfgenmsg))))
+#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
+
+/* netfilter netlink message types are split in two pieces:
+ * 8 bit subsystem, 8bit operation.
+ */
+
+#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8)
+#define NFNL_MSG_TYPE(x) (x & 0x00ff)
+
+/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS()
+ * won't work anymore */
+#define NFNL_SUBSYS_NONE 0
+#define NFNL_SUBSYS_CTNETLINK 1
+#define NFNL_SUBSYS_CTNETLINK_EXP 2
+#define NFNL_SUBSYS_QUEUE 3
+#define NFNL_SUBSYS_ULOG 4
+#define NFNL_SUBSYS_COUNT 5
+
+#ifdef __KERNEL__
+
+#include <linux/netlink.h>
+#include <linux/capability.h>
+
+struct nfnl_callback
+{
+ int (*call)(struct sock *nl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp);
+ kernel_cap_t cap_required; /* capabilities required for this msg */
+ u_int16_t attr_count; /* number of nfattr's */
+};
+
+struct nfnetlink_subsystem
+{
+ const char *name;
+ __u8 subsys_id; /* nfnetlink subsystem ID */
+ __u8 cb_count; /* number of callbacks */
+ struct nfnl_callback *cb; /* callback for individual types */
+};
+
+extern void __nfa_fill(struct sk_buff *skb, int attrtype,
+ int attrlen, const void *data);
+#define NFA_PUT(skb, attrtype, attrlen, data) \
+({ if (skb_tailroom(skb) < (int)NFA_SPACE(attrlen)) goto nfattr_failure; \
+ __nfa_fill(skb, attrtype, attrlen, data); })
+
+extern struct semaphore nfnl_sem;
+
+#define nfnl_shlock() down(&nfnl_sem)
+#define nfnl_shlock_nowait() down_trylock(&nfnl_sem)
+
+#define nfnl_shunlock() do { up(&nfnl_sem); \
+ if(nfnl && nfnl->sk_receive_queue.qlen) \
+ nfnl->sk_data_ready(nfnl, 0); \
+ } while(0)
+
+extern void nfnl_lock(void);
+extern void nfnl_unlock(void);
+
+extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n);
+extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n);
+
+extern int nfattr_parse(struct nfattr *tb[], int maxattr,
+ struct nfattr *nfa, int len);
+
+#define nfattr_parse_nested(tb, max, nfa) \
+ nfattr_parse((tb), (max), NFA_DATA((nfa)), NFA_PAYLOAD((nfa)))
+
+#define nfattr_bad_size(tb, max, cta_min) \
+({ int __i, __res = 0; \
+ for (__i=0; __i<max; __i++) \
+ if (tb[__i] && NFA_PAYLOAD(tb[__i]) < cta_min[__i]){ \
+ __res = 1; \
+ break; \
+ } \
+ __res; \
+})
+
+extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
+ int echo);
+extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
+
+#define MODULE_ALIAS_NFNL_SUBSYS(subsys) \
+ MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
+
+#endif /* __KERNEL__ */
+#endif /* _NFNETLINK_H */
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
new file mode 100644
index 000000000000..5c55751c78e4
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -0,0 +1,124 @@
+#ifndef _IPCONNTRACK_NETLINK_H
+#define _IPCONNTRACK_NETLINK_H
+#include <linux/netfilter/nfnetlink.h>
+
+enum cntl_msg_types {
+ IPCTNL_MSG_CT_NEW,
+ IPCTNL_MSG_CT_GET,
+ IPCTNL_MSG_CT_DELETE,
+ IPCTNL_MSG_CT_GET_CTRZERO,
+
+ IPCTNL_MSG_MAX
+};
+
+enum ctnl_exp_msg_types {
+ IPCTNL_MSG_EXP_NEW,
+ IPCTNL_MSG_EXP_GET,
+ IPCTNL_MSG_EXP_DELETE,
+
+ IPCTNL_MSG_EXP_MAX
+};
+
+
+enum ctattr_type {
+ CTA_UNSPEC,
+ CTA_TUPLE_ORIG,
+ CTA_TUPLE_REPLY,
+ CTA_STATUS,
+ CTA_PROTOINFO,
+ CTA_HELP,
+ CTA_NAT,
+ CTA_TIMEOUT,
+ CTA_MARK,
+ CTA_COUNTERS_ORIG,
+ CTA_COUNTERS_REPLY,
+ CTA_USE,
+ CTA_ID,
+ __CTA_MAX
+};
+#define CTA_MAX (__CTA_MAX - 1)
+
+enum ctattr_tuple {
+ CTA_TUPLE_UNSPEC,
+ CTA_TUPLE_IP,
+ CTA_TUPLE_PROTO,
+ __CTA_TUPLE_MAX
+};
+#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1)
+
+enum ctattr_ip {
+ CTA_IP_UNSPEC,
+ CTA_IP_V4_SRC,
+ CTA_IP_V4_DST,
+ CTA_IP_V6_SRC,
+ CTA_IP_V6_DST,
+ __CTA_IP_MAX
+};
+#define CTA_IP_MAX (__CTA_IP_MAX - 1)
+
+enum ctattr_l4proto {
+ CTA_PROTO_UNSPEC,
+ CTA_PROTO_NUM,
+ CTA_PROTO_SRC_PORT,
+ CTA_PROTO_DST_PORT,
+ CTA_PROTO_ICMP_ID,
+ CTA_PROTO_ICMP_TYPE,
+ CTA_PROTO_ICMP_CODE,
+ __CTA_PROTO_MAX
+};
+#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
+
+enum ctattr_protoinfo {
+ CTA_PROTOINFO_UNSPEC,
+ CTA_PROTOINFO_TCP_STATE,
+ __CTA_PROTOINFO_MAX
+};
+#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
+
+enum ctattr_counters {
+ CTA_COUNTERS_UNSPEC,
+ CTA_COUNTERS_PACKETS,
+ CTA_COUNTERS_BYTES,
+ __CTA_COUNTERS_MAX
+};
+#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
+
+enum ctattr_nat {
+ CTA_NAT_UNSPEC,
+ CTA_NAT_MINIP,
+ CTA_NAT_MAXIP,
+ CTA_NAT_PROTO,
+ __CTA_NAT_MAX
+};
+#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)
+
+enum ctattr_protonat {
+ CTA_PROTONAT_UNSPEC,
+ CTA_PROTONAT_PORT_MIN,
+ CTA_PROTONAT_PORT_MAX,
+ __CTA_PROTONAT_MAX
+};
+#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)
+
+enum ctattr_expect {
+ CTA_EXPECT_UNSPEC,
+ CTA_EXPECT_MASTER,
+ CTA_EXPECT_TUPLE,
+ CTA_EXPECT_MASK,
+ CTA_EXPECT_TIMEOUT,
+ CTA_EXPECT_ID,
+ CTA_EXPECT_HELP_NAME,
+ __CTA_EXPECT_MAX
+};
+#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
+
+enum ctattr_help {
+ CTA_HELP_UNSPEC,
+ CTA_HELP_NAME,
+ __CTA_HELP_MAX
+};
+#define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
+
+#define CTA_HELP_MAXNAMESIZE 32
+
+#endif /* _IPCONNTRACK_NETLINK_H */
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
new file mode 100644
index 000000000000..b04b03880595
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -0,0 +1,88 @@
+#ifndef _NFNETLINK_LOG_H
+#define _NFNETLINK_LOG_H
+
+/* This file describes the netlink messages (i.e. 'protocol packets'),
+ * and not any kind of function definitions. It is shared between kernel and
+ * userspace. Don't put kernel specific stuff in here */
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
+
+enum nfulnl_msg_types {
+ NFULNL_MSG_PACKET, /* packet from kernel to userspace */
+ NFULNL_MSG_CONFIG, /* connect to a particular queue */
+
+ NFULNL_MSG_MAX
+};
+
+struct nfulnl_msg_packet_hdr {
+ u_int16_t hw_protocol; /* hw protocol (network order) */
+ u_int8_t hook; /* netfilter hook */
+ u_int8_t _pad;
+} __attribute__ ((packed));
+
+struct nfulnl_msg_packet_hw {
+ u_int16_t hw_addrlen;
+ u_int16_t _pad;
+ u_int8_t hw_addr[8];
+} __attribute__ ((packed));
+
+struct nfulnl_msg_packet_timestamp {
+ aligned_u64 sec;
+ aligned_u64 usec;
+} __attribute__ ((packed));
+
+#define NFULNL_PREFIXLEN 30 /* just like old log target */
+
+enum nfulnl_attr_type {
+ NFULA_UNSPEC,
+ NFULA_PACKET_HDR,
+ NFULA_MARK, /* u_int32_t nfmark */
+ NFULA_TIMESTAMP, /* nfulnl_msg_packet_timestamp */
+ NFULA_IFINDEX_INDEV, /* u_int32_t ifindex */
+ NFULA_IFINDEX_OUTDEV, /* u_int32_t ifindex */
+ NFULA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */
+ NFULA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */
+ NFULA_HWADDR, /* nfulnl_msg_packet_hw */
+ NFULA_PAYLOAD, /* opaque data payload */
+ NFULA_PREFIX, /* string prefix */
+ NFULA_UID, /* user id of socket */
+
+ __NFULA_MAX
+};
+#define NFULA_MAX (__NFULA_MAX - 1)
+
+enum nfulnl_msg_config_cmds {
+ NFULNL_CFG_CMD_NONE,
+ NFULNL_CFG_CMD_BIND,
+ NFULNL_CFG_CMD_UNBIND,
+ NFULNL_CFG_CMD_PF_BIND,
+ NFULNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfulnl_msg_config_cmd {
+ u_int8_t command; /* nfulnl_msg_config_cmds */
+} __attribute__ ((packed));
+
+struct nfulnl_msg_config_mode {
+ u_int32_t copy_range;
+ u_int8_t copy_mode;
+ u_int8_t _pad;
+} __attribute__ ((packed));
+
+enum nfulnl_attr_config {
+ NFULA_CFG_UNSPEC,
+ NFULA_CFG_CMD, /* nfulnl_msg_config_cmd */
+ NFULA_CFG_MODE, /* nfulnl_msg_config_mode */
+ NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */
+ NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */
+ NFULA_CFG_QTHRESH, /* u_int32_t */
+ __NFULA_CFG_MAX
+};
+#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
+
+#define NFULNL_COPY_NONE 0x00
+#define NFULNL_COPY_META 0x01
+#define NFULNL_COPY_PACKET 0x02
+
+#endif /* _NFNETLINK_LOG_H */
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
new file mode 100644
index 000000000000..9e774373244c
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -0,0 +1,89 @@
+#ifndef _NFNETLINK_QUEUE_H
+#define _NFNETLINK_QUEUE_H
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
+
+enum nfqnl_msg_types {
+ NFQNL_MSG_PACKET, /* packet from kernel to userspace */
+ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
+ NFQNL_MSG_CONFIG, /* connect to a particular queue */
+
+ NFQNL_MSG_MAX
+};
+
+struct nfqnl_msg_packet_hdr {
+ u_int32_t packet_id; /* unique ID of packet in queue */
+ u_int16_t hw_protocol; /* hw protocol (network order) */
+ u_int8_t hook; /* netfilter hook */
+} __attribute__ ((packed));
+
+struct nfqnl_msg_packet_hw {
+ u_int16_t hw_addrlen;
+ u_int16_t _pad;
+ u_int8_t hw_addr[8];
+} __attribute__ ((packed));
+
+struct nfqnl_msg_packet_timestamp {
+ aligned_u64 sec;
+ aligned_u64 usec;
+} __attribute__ ((packed));
+
+enum nfqnl_attr_type {
+ NFQA_UNSPEC,
+ NFQA_PACKET_HDR,
+ NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */
+ NFQA_MARK, /* u_int32_t nfmark */
+ NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */
+ NFQA_IFINDEX_INDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_OUTDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */
+ NFQA_HWADDR, /* nfqnl_msg_packet_hw */
+ NFQA_PAYLOAD, /* opaque data payload */
+
+ __NFQA_MAX
+};
+#define NFQA_MAX (__NFQA_MAX - 1)
+
+struct nfqnl_msg_verdict_hdr {
+ u_int32_t verdict;
+ u_int32_t id;
+} __attribute__ ((packed));
+
+
+enum nfqnl_msg_config_cmds {
+ NFQNL_CFG_CMD_NONE,
+ NFQNL_CFG_CMD_BIND,
+ NFQNL_CFG_CMD_UNBIND,
+ NFQNL_CFG_CMD_PF_BIND,
+ NFQNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfqnl_msg_config_cmd {
+ u_int8_t command; /* nfqnl_msg_config_cmds */
+ u_int8_t _pad;
+ u_int16_t pf; /* AF_xxx for PF_[UN]BIND */
+} __attribute__ ((packed));
+
+enum nfqnl_config_mode {
+ NFQNL_COPY_NONE,
+ NFQNL_COPY_META,
+ NFQNL_COPY_PACKET,
+};
+
+struct nfqnl_msg_config_params {
+ u_int32_t copy_range;
+ u_int8_t copy_mode; /* enum nfqnl_config_mode */
+} __attribute__ ((packed));
+
+
+enum nfqnl_attr_config {
+ NFQA_CFG_UNSPEC,
+ NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
+ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
+ __NFQA_CFG_MAX
+};
+#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
+
+#endif /* _NFNETLINK_QUEUE_H */
diff --git a/include/linux/netfilter_decnet.h b/include/linux/netfilter_decnet.h
index 3064eec9cb8e..6f425369ee29 100644
--- a/include/linux/netfilter_decnet.h
+++ b/include/linux/netfilter_decnet.h
@@ -9,6 +9,8 @@
#include <linux/netfilter.h>
+/* only for userspace compatibility */
+#ifndef __KERNEL__
/* IP Cache bits. */
/* Src IP address. */
#define NFC_DN_SRC 0x0001
@@ -18,6 +20,7 @@
#define NFC_DN_IF_IN 0x0004
/* Output device. */
#define NFC_DN_IF_OUT 0x0008
+#endif /* ! __KERNEL__ */
/* DECnet Hooks */
/* After promisc drops, checksum checks. */
@@ -53,7 +56,21 @@ struct nf_dn_rtmsg {
#define NFDN_RTMSG(r) ((unsigned char *)(r) + NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)))
+#ifndef __KERNEL__
+/* backwards compatibility for userspace */
#define DNRMG_L1_GROUP 0x01
#define DNRMG_L2_GROUP 0x02
+#endif
+
+enum {
+ DNRNG_NLGRP_NONE,
+#define DNRNG_NLGRP_NONE DNRNG_NLGRP_NONE
+ DNRNG_NLGRP_L1,
+#define DNRNG_NLGRP_L1 DNRNG_NLGRP_L1
+ DNRNG_NLGRP_L2,
+#define DNRNG_NLGRP_L2 DNRNG_NLGRP_L2
+ __DNRNG_NLGRP_MAX
+};
+#define DNRNG_NLGRP_MAX (__DNRNG_NLGRP_MAX - 1)
#endif /*__LINUX_DECNET_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 3ebc36afae1a..fdc4a9527343 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -8,6 +8,8 @@
#include <linux/config.h>
#include <linux/netfilter.h>
+/* only for userspace compatibility */
+#ifndef __KERNEL__
/* IP Cache bits. */
/* Src IP address. */
#define NFC_IP_SRC 0x0001
@@ -35,6 +37,7 @@
#define NFC_IP_DST_PT 0x0400
/* Something else about the proto */
#define NFC_IP_PROTO_UNKNOWN 0x2000
+#endif /* ! __KERNEL__ */
/* IP Hooks */
/* After promisc drops, checksum checks. */
@@ -77,11 +80,6 @@ enum nf_ip_hook_priorities {
#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff **pskb);
-/* Call this before modifying an existing IP packet: ensures it is
- modifiable and linear to the point you care about (writable_len).
- Returns true or false. */
-extern int skb_ip_make_writable(struct sk_buff **pskb,
- unsigned int writable_len);
#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 08fe5f7d14a0..7e033e9271a8 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -65,6 +65,63 @@ enum ip_conntrack_status {
/* Both together */
IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
+
+ /* Connection is dying (removed from lists), can not be unset. */
+ IPS_DYING_BIT = 9,
+ IPS_DYING = (1 << IPS_DYING_BIT),
+};
+
+/* Connection tracking event bits */
+enum ip_conntrack_events
+{
+ /* New conntrack */
+ IPCT_NEW_BIT = 0,
+ IPCT_NEW = (1 << IPCT_NEW_BIT),
+
+ /* Expected connection */
+ IPCT_RELATED_BIT = 1,
+ IPCT_RELATED = (1 << IPCT_RELATED_BIT),
+
+ /* Destroyed conntrack */
+ IPCT_DESTROY_BIT = 2,
+ IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
+
+ /* Timer has been refreshed */
+ IPCT_REFRESH_BIT = 3,
+ IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
+
+ /* Status has changed */
+ IPCT_STATUS_BIT = 4,
+ IPCT_STATUS = (1 << IPCT_STATUS_BIT),
+
+ /* Update of protocol info */
+ IPCT_PROTOINFO_BIT = 5,
+ IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
+
+ /* Volatile protocol info */
+ IPCT_PROTOINFO_VOLATILE_BIT = 6,
+ IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
+
+ /* New helper for conntrack */
+ IPCT_HELPER_BIT = 7,
+ IPCT_HELPER = (1 << IPCT_HELPER_BIT),
+
+ /* Update of helper info */
+ IPCT_HELPINFO_BIT = 8,
+ IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
+
+ /* Volatile helper info */
+ IPCT_HELPINFO_VOLATILE_BIT = 9,
+ IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
+
+ /* NAT info */
+ IPCT_NATINFO_BIT = 10,
+ IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+};
+
+enum ip_conntrack_expect_events {
+ IPEXP_NEW_BIT = 0,
+ IPEXP_NEW = (1 << IPEXP_NEW_BIT),
};
#ifdef __KERNEL__
@@ -152,6 +209,9 @@ struct ip_conntrack
/* Current number of expected connections */
unsigned int expecting;
+ /* Unique ID that identifies this conntrack*/
+ unsigned int id;
+
/* Helper, if any. */
struct ip_conntrack_helper *helper;
@@ -171,7 +231,7 @@ struct ip_conntrack
#endif /* CONFIG_IP_NF_NAT_NEEDED */
#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
- unsigned long mark;
+ u_int32_t mark;
#endif
/* Traversed often, so hopefully in different cacheline to top */
@@ -200,6 +260,12 @@ struct ip_conntrack_expect
/* Usage count. */
atomic_t use;
+ /* Unique ID */
+ unsigned int id;
+
+ /* Flags */
+ unsigned int flags;
+
#ifdef CONFIG_IP_NF_NAT_NEEDED
/* This is the original per-proto part, used to map the
* expected connection the way the recipient expects. */
@@ -209,6 +275,8 @@ struct ip_conntrack_expect
#endif
};
+#define IP_CT_EXPECT_PERMANENT 0x1
+
static inline struct ip_conntrack *
tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
{
@@ -239,7 +307,12 @@ ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
}
/* decrement reference count on a conntrack */
-extern void ip_conntrack_put(struct ip_conntrack *ct);
+static inline void
+ip_conntrack_put(struct ip_conntrack *ct)
+{
+ IP_NF_ASSERT(ct);
+ nf_conntrack_put(&ct->ct_general);
+}
/* call to create an explicit dependency on ip_conntrack. */
extern void need_ip_conntrack(void);
@@ -274,12 +347,50 @@ extern void
ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data),
void *data);
+extern struct ip_conntrack_helper *
+__ip_conntrack_helper_find_byname(const char *);
+extern struct ip_conntrack_helper *
+ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple);
+extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper);
+
+extern struct ip_conntrack_protocol *
+__ip_conntrack_proto_find(u_int8_t protocol);
+extern struct ip_conntrack_protocol *
+ip_conntrack_proto_find_get(u_int8_t protocol);
+extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto);
+
+extern void ip_ct_remove_expectations(struct ip_conntrack *ct);
+
+extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *,
+ struct ip_conntrack_tuple *);
+
+extern void ip_conntrack_free(struct ip_conntrack *ct);
+
+extern void ip_conntrack_hash_insert(struct ip_conntrack *ct);
+
+extern struct ip_conntrack_expect *
+__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
+
+extern struct ip_conntrack_expect *
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
+
+extern struct ip_conntrack_tuple_hash *
+__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
+ const struct ip_conntrack *ignored_conntrack);
+
+extern void ip_conntrack_flush(void);
+
/* It's confirmed if it is, or has been in the hash table. */
static inline int is_confirmed(struct ip_conntrack *ct)
{
return test_bit(IPS_CONFIRMED_BIT, &ct->status);
}
+static inline int is_dying(struct ip_conntrack *ct)
+{
+ return test_bit(IPS_DYING_BIT, &ct->status);
+}
+
extern unsigned int ip_conntrack_htable_size;
struct ip_conntrack_stat
@@ -303,6 +414,85 @@ struct ip_conntrack_stat
#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+
+struct ip_conntrack_ecache {
+ struct ip_conntrack *ct;
+ unsigned int events;
+};
+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;
+
+static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
+{
+ return 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);
+}
+
+static inline int
+ip_conntrack_expect_register_notifier(struct notifier_block *nb)
+{
+ return 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);
+}
+
+extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
+extern void __ip_ct_event_cache_init(struct ip_conntrack *ct);
+
+static inline void
+ip_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb)
+{
+ struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct;
+ struct ip_conntrack_ecache *ecache;
+
+ local_bh_disable();
+ ecache = &__get_cpu_var(ip_conntrack_ecache);
+ if (ct != ecache->ct)
+ __ip_ct_event_cache_init(ct);
+ ecache->events |= event;
+ local_bh_enable();
+}
+
+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);
+}
+
+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);
+}
+#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb) {}
+static inline void ip_conntrack_event(enum ip_conntrack_events event,
+ struct ip_conntrack *ct) {}
+static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {}
+static inline void
+ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ struct ip_conntrack_expect *exp) {}
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+
#ifdef CONFIG_IP_NF_NAT_NEEDED
static inline int ip_nat_initialized(struct ip_conntrack *conntrack,
enum ip_nat_manip_type manip)
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
index 694aec9b4784..907d4f5ca5dc 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h
@@ -2,6 +2,9 @@
#define _IP_CONNTRACK_CORE_H
#include <linux/netfilter.h>
+#define MAX_IP_CT_PROTO 256
+extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
+
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
of connection tracking. */
@@ -38,12 +41,19 @@ extern int __ip_conntrack_confirm(struct sk_buff **pskb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
static inline int ip_conntrack_confirm(struct sk_buff **pskb)
{
- if ((*pskb)->nfct
- && !is_confirmed((struct ip_conntrack *)(*pskb)->nfct))
- return __ip_conntrack_confirm(pskb);
- return NF_ACCEPT;
+ struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct;
+ int ret = NF_ACCEPT;
+
+ if (ct) {
+ if (!is_confirmed(ct))
+ ret = __ip_conntrack_confirm(pskb);
+ ip_ct_deliver_cached_events(ct);
+ }
+ return ret;
}
+extern void ip_ct_unlink_expect(struct ip_conntrack_expect *exp);
+
extern struct list_head *ip_conntrack_hash;
extern struct list_head ip_conntrack_expect_list;
extern rwlock_t ip_conntrack_lock;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper.h b/include/linux/netfilter_ipv4/ip_conntrack_helper.h
index 3692daa93dec..8d69279ccfe4 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper.h
@@ -24,6 +24,8 @@ struct ip_conntrack_helper
int (*help)(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info conntrackinfo);
+
+ int (*to_nfattr)(struct sk_buff *skb, const struct ip_conntrack *ct);
};
extern int ip_conntrack_helper_register(struct ip_conntrack_helper *);
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
index e20b57c5e1b7..b6b99be8632a 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
@@ -2,6 +2,7 @@
#ifndef _IP_CONNTRACK_PROTOCOL_H
#define _IP_CONNTRACK_PROTOCOL_H
#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
struct seq_file;
@@ -47,22 +48,22 @@ struct ip_conntrack_protocol
int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
unsigned int hooknum);
+ /* convert protoinfo to nfnetink attributes */
+ int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
+ const struct ip_conntrack *ct);
+
+ int (*tuple_to_nfattr)(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *t);
+ int (*nfattr_to_tuple)(struct nfattr *tb[],
+ struct ip_conntrack_tuple *t);
+
/* Module (if any) which this is connected to. */
struct module *me;
};
-#define MAX_IP_CT_PROTO 256
-extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
-
/* Protocol registration. */
extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
-
-static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
-{
- return ip_ct_protos[protocol];
-}
-
/* Existing built-in protocols */
extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
@@ -73,6 +74,11 @@ extern int ip_conntrack_protocol_tcp_init(void);
/* Log invalid packets */
extern unsigned int ip_ct_log_invalid;
+extern int ip_ct_port_tuple_to_nfattr(struct sk_buff *,
+ const struct ip_conntrack_tuple *);
+extern int ip_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+ struct ip_conntrack_tuple *);
+
#ifdef CONFIG_SYSCTL
#ifdef DEBUG_INVALID_PACKETS
#define LOG_INVALID(proto) \
diff --git a/include/linux/netfilter_ipv4/ip_logging.h b/include/linux/netfilter_ipv4/ip_logging.h
deleted file mode 100644
index 0c5c52cb6589..000000000000
--- a/include/linux/netfilter_ipv4/ip_logging.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* IPv4 macros for the internal logging interface. */
-#ifndef __IP_LOGGING_H
-#define __IP_LOGGING_H
-
-#ifdef __KERNEL__
-#include <linux/socket.h>
-#include <linux/netfilter_logging.h>
-
-#define nf_log_ip_packet(pskb,hooknum,in,out,fmt,args...) \
- nf_log_packet(AF_INET,pskb,hooknum,in,out,fmt,##args)
-
-#define nf_log_ip(pfh,len,fmt,args...) \
- nf_log(AF_INET,pfh,len,fmt,##args)
-
-#define nf_ip_log_register(logging) nf_log_register(AF_INET,logging)
-#define nf_ip_log_unregister(logging) nf_log_unregister(AF_INET,logging)
-
-#endif /*__KERNEL__*/
-
-#endif /*__IP_LOGGING_H*/
diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
index 129708c22386..ef63aa991a06 100644
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h
+++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h
@@ -4,6 +4,9 @@
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
struct iphdr;
struct ip_nat_range;
@@ -15,6 +18,8 @@ struct ip_nat_protocol
/* Protocol number. */
unsigned int protonum;
+ struct module *me;
+
/* Translate a packet to the target according to manip type.
Return true if succeeded. */
int (*manip_pkt)(struct sk_buff **pskb,
@@ -43,19 +48,20 @@ struct ip_nat_protocol
unsigned int (*print_range)(char *buffer,
const struct ip_nat_range *range);
-};
-#define MAX_IP_NAT_PROTO 256
-extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+ int (*range_to_nfattr)(struct sk_buff *skb,
+ const struct ip_nat_range *range);
+
+ int (*nfattr_to_range)(struct nfattr *tb[],
+ struct ip_nat_range *range);
+};
/* Protocol registration. */
extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
-static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol)
-{
- return ip_nat_protos[protocol];
-}
+extern struct ip_nat_protocol *ip_nat_proto_find_get(u_int8_t protocol);
+extern void ip_nat_proto_put(struct ip_nat_protocol *proto);
/* Built-in protocols. */
extern struct ip_nat_protocol ip_nat_protocol_tcp;
@@ -67,4 +73,9 @@ extern int init_protocols(void) __init;
extern void cleanup_protocols(void);
extern struct ip_nat_protocol *find_nat_proto(u_int16_t protonum);
+extern int ip_nat_port_range_to_nfattr(struct sk_buff *skb,
+ const struct ip_nat_range *range);
+extern int ip_nat_port_nfattr_to_range(struct nfattr *tb[],
+ struct ip_nat_range *range);
+
#endif /*_IP_NAT_PROTO_H*/
diff --git a/include/linux/netfilter_ipv4/ip_nat_rule.h b/include/linux/netfilter_ipv4/ip_nat_rule.h
index fecd2a06dcd8..73b9552e6a89 100644
--- a/include/linux/netfilter_ipv4/ip_nat_rule.h
+++ b/include/linux/netfilter_ipv4/ip_nat_rule.h
@@ -19,5 +19,10 @@ extern unsigned int
alloc_null_binding(struct ip_conntrack *conntrack,
struct ip_nat_info *info,
unsigned int hooknum);
+
+extern unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+ struct ip_nat_info *info,
+ unsigned int hooknum);
#endif
#endif /* _IP_NAT_RULE_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 12ce47808e7d..d19d65cf4530 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -109,7 +109,8 @@ struct ipt_counters
/* Values for "flag" field in struct ipt_ip (general ip structure). */
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
-#define IPT_F_MASK 0x01 /* All possible flag bits mask. */
+#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
+#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
/* Values for "inv" field in struct ipt_ip. */
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index d25f782e57d1..22d16177319b 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -1,6 +1,7 @@
#ifndef _IPT_LOG_H
#define _IPT_LOG_H
+/* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
#define IPT_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */
#define IPT_LOG_IPOPT 0x04 /* Log IP options */
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
new file mode 100644
index 000000000000..b5b2943b0c66
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
@@ -0,0 +1,16 @@
+/* iptables module for using NFQUEUE mechanism
+ *
+ * (C) 2005 Harald Welte <laforge@netfilter.org>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ *
+*/
+#ifndef _IPT_NFQ_TARGET_H
+#define _IPT_NFQ_TARGET_H
+
+/* target info */
+struct ipt_NFQ_info {
+ u_int16_t queuenum;
+};
+
+#endif /* _IPT_DSCP_TARGET_H */
diff --git a/include/linux/netfilter_ipv4/ipt_TTL.h b/include/linux/netfilter_ipv4/ipt_TTL.h
new file mode 100644
index 000000000000..ee6611edc112
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_TTL.h
@@ -0,0 +1,21 @@
+/* TTL modification module for IP tables
+ * (C) 2000 by Harald Welte <laforge@netfilter.org> */
+
+#ifndef _IPT_TTL_H
+#define _IPT_TTL_H
+
+enum {
+ IPT_TTL_SET = 0,
+ IPT_TTL_INC,
+ IPT_TTL_DEC
+};
+
+#define IPT_TTL_MAXMODE IPT_TTL_DEC
+
+struct ipt_TTL_info {
+ u_int8_t mode;
+ u_int8_t ttl;
+};
+
+
+#endif
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h
new file mode 100644
index 000000000000..9e5532f8d8ac
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h
@@ -0,0 +1,25 @@
+#ifndef _IPT_CONNBYTES_H
+#define _IPT_CONNBYTES_H
+
+enum ipt_connbytes_what {
+ IPT_CONNBYTES_PKTS,
+ IPT_CONNBYTES_BYTES,
+ IPT_CONNBYTES_AVGPKT,
+};
+
+enum ipt_connbytes_direction {
+ IPT_CONNBYTES_DIR_ORIGINAL,
+ IPT_CONNBYTES_DIR_REPLY,
+ IPT_CONNBYTES_DIR_BOTH,
+};
+
+struct ipt_connbytes_info
+{
+ struct {
+ aligned_u64 from; /* count to be matched */
+ aligned_u64 to; /* count to be matched */
+ } count;
+ u_int8_t what; /* ipt_connbytes_what */
+ u_int8_t direction; /* ipt_connbytes_direction */
+};
+#endif
diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h
new file mode 100644
index 000000000000..3cb3a522e62b
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_dccp.h
@@ -0,0 +1,23 @@
+#ifndef _IPT_DCCP_H_
+#define _IPT_DCCP_H_
+
+#define IPT_DCCP_SRC_PORTS 0x01
+#define IPT_DCCP_DEST_PORTS 0x02
+#define IPT_DCCP_TYPE 0x04
+#define IPT_DCCP_OPTION 0x08
+
+#define IPT_DCCP_VALID_FLAGS 0x0f
+
+struct ipt_dccp_info {
+ u_int16_t dpts[2]; /* Min, Max */
+ u_int16_t spts[2]; /* Min, Max */
+
+ u_int16_t flags;
+ u_int16_t invflags;
+
+ u_int16_t typemask;
+ u_int8_t option;
+};
+
+#endif /* _IPT_DCCP_H_ */
+
diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h
new file mode 100644
index 000000000000..a265f6e44eab
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_string.h
@@ -0,0 +1,18 @@
+#ifndef _IPT_STRING_H
+#define _IPT_STRING_H
+
+#define IPT_STRING_MAX_PATTERN_SIZE 128
+#define IPT_STRING_MAX_ALGO_NAME_SIZE 16
+
+struct ipt_string_info
+{
+ u_int16_t from_offset;
+ u_int16_t to_offset;
+ char algo[IPT_STRING_MAX_ALGO_NAME_SIZE];
+ char pattern[IPT_STRING_MAX_PATTERN_SIZE];
+ u_int8_t patlen;
+ u_int8_t invert;
+ struct ts_config __attribute__((aligned(8))) *config;
+};
+
+#endif /*_IPT_STRING_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index bee7a5ec7c66..edcc2c6eb5c7 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -10,6 +10,8 @@
#include <linux/netfilter.h>
+/* only for userspace compatibility */
+#ifndef __KERNEL__
/* IP Cache bits. */
/* Src IP address. */
#define NFC_IP6_SRC 0x0001
@@ -38,6 +40,7 @@
#define NFC_IP6_DST_PT 0x0400
/* Something else about the proto */
#define NFC_IP6_PROTO_UNKNOWN 0x2000
+#endif /* ! __KERNEL__ */
/* IP6 Hooks */
@@ -68,4 +71,7 @@ enum nf_ip6_hook_priorities {
NF_IP6_PRI_LAST = INT_MAX,
};
+extern int ipv6_netfilter_init(void);
+extern void ipv6_netfilter_fini(void);
+
#endif /*__LINUX_IP6_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv6/ip6_logging.h b/include/linux/netfilter_ipv6/ip6_logging.h
deleted file mode 100644
index a0b2ee3043aa..000000000000
--- a/include/linux/netfilter_ipv6/ip6_logging.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* IPv6 macros for the nternal logging interface. */
-#ifndef __IP6_LOGGING_H
-#define __IP6_LOGGING_H
-
-#ifdef __KERNEL__
-#include <linux/socket.h>
-#include <linux/netfilter_logging.h>
-
-#define nf_log_ip6_packet(pskb,hooknum,in,out,fmt,args...) \
- nf_log_packet(AF_INET6,pskb,hooknum,in,out,fmt,##args)
-
-#define nf_log_ip6(pfh,len,fmt,args...) \
- nf_log(AF_INET6,pfh,len,fmt,##args)
-
-#define nf_ip6_log_register(logging) nf_log_register(AF_INET6,logging)
-#define nf_ip6_log_unregister(logging) nf_log_unregister(AF_INET6,logging)
-
-#endif /*__KERNEL__*/
-
-#endif /*__IP6_LOGGING_H*/
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f1ce3b009853..58c72a52dc65 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -111,7 +111,8 @@ struct ip6t_counters
#define IP6T_F_PROTO 0x01 /* Set if rule cares about upper
protocols */
#define IP6T_F_TOS 0x02 /* Match the TOS. */
-#define IP6T_F_MASK 0x03 /* All possible flag bits mask. */
+#define IP6T_F_GOTO 0x04 /* Set if jump is a goto */
+#define IP6T_F_MASK 0x07 /* All possible flag bits mask. */
/* Values for "inv" field in struct ip6t_ip6. */
#define IP6T_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
diff --git a/include/linux/netfilter_ipv6/ip6t_HL.h b/include/linux/netfilter_ipv6/ip6t_HL.h
new file mode 100644
index 000000000000..afb7813d45ab
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_HL.h
@@ -0,0 +1,22 @@
+/* Hop Limit modification module for ip6tables
+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
+ * Based on HW's TTL module */
+
+#ifndef _IP6T_HL_H
+#define _IP6T_HL_H
+
+enum {
+ IP6T_HL_SET = 0,
+ IP6T_HL_INC,
+ IP6T_HL_DEC
+};
+
+#define IP6T_HL_MAXMODE IP6T_HL_DEC
+
+struct ip6t_HL_info {
+ u_int8_t mode;
+ u_int8_t hop_limit;
+};
+
+
+#endif
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 42996a43bb39..9008ff5c40ae 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -1,6 +1,7 @@
#ifndef _IP6T_LOG_H
#define _IP6T_LOG_H
+/* make sure not to change this without changing netfilter.h:NF_LOG_* (!) */
#define IP6T_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */
#define IP6T_LOG_IPOPT 0x04 /* Log IP options */
diff --git a/include/linux/netfilter_ipv6/ip6t_REJECT.h b/include/linux/netfilter_ipv6/ip6t_REJECT.h
new file mode 100644
index 000000000000..6be6504162bb
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_REJECT.h
@@ -0,0 +1,18 @@
+#ifndef _IP6T_REJECT_H
+#define _IP6T_REJECT_H
+
+enum ip6t_reject_with {
+ IP6T_ICMP6_NO_ROUTE,
+ IP6T_ICMP6_ADM_PROHIBITED,
+ IP6T_ICMP6_NOT_NEIGHBOUR,
+ IP6T_ICMP6_ADDR_UNREACH,
+ IP6T_ICMP6_PORT_UNREACH,
+ IP6T_ICMP6_ECHOREPLY,
+ IP6T_TCP_RESET
+};
+
+struct ip6t_reject_info {
+ u_int32_t with; /* reject type */
+};
+
+#endif /*_IP6T_REJECT_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 6552b71bfa73..7bbd25970c9e 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -8,13 +8,14 @@
#define NETLINK_W1 1 /* 1-wire subsystem */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Firewalling hook */
-#define NETLINK_TCPDIAG 4 /* TCP socket monitoring */
+#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ISCSI 8 /* Open-iSCSI */
#define NETLINK_AUDIT 9 /* auditing */
#define NETLINK_FIB_LOOKUP 10
+#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
@@ -90,6 +91,15 @@ struct nlmsgerr
struct nlmsghdr msg;
};
+#define NETLINK_ADD_MEMBERSHIP 1
+#define NETLINK_DROP_MEMBERSHIP 2
+#define NETLINK_PKTINFO 3
+
+struct nl_pktinfo
+{
+ __u32 group;
+};
+
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
enum {
@@ -106,9 +116,8 @@ struct netlink_skb_parms
{
struct ucred creds; /* Skb credentials */
__u32 pid;
- __u32 groups;
__u32 dst_pid;
- __u32 dst_groups;
+ __u32 dst_group;
kernel_cap_t eff_cap;
__u32 loginuid; /* Login (audit) uid */
};
@@ -117,11 +126,11 @@ struct netlink_skb_parms
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
-extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
+extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
- __u32 group, int allocation);
+ __u32 group, unsigned int __nocast allocation);
extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
extern int netlink_register_notifier(struct notifier_block *nb);
extern int netlink_unregister_notifier(struct notifier_block *nb);
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 4d24d65c0e88..8903688890ce 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -438,17 +438,22 @@ extern int nfsd4_process_open1(struct nfsd4_open *open);
extern int nfsd4_process_open2(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open *open);
extern int nfsd4_open_confirm(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_confirm *oc);
+ struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
+ struct nfs4_stateowner **);
extern int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_close *close);
+ struct nfsd4_close *close,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_open_downgrade(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_downgrade *od);
+ struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_lock *lock);
+ struct nfsd4_lock *lock,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_lockt *lockt);
extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_locku *locku);
+ struct nfsd4_locku *locku,
+ struct nfs4_stateowner **replay_owner);
extern int
nfsd4_release_lockowner(struct svc_rqst *rqstp,
struct nfsd4_release_lockowner *rlockowner);
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index f5a6695d4d21..f34767c5fc79 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -134,6 +134,7 @@ struct page_state {
};
extern void get_page_state(struct page_state *ret);
+extern void get_page_state_node(struct page_state *ret, int node);
extern void get_full_page_state(struct page_state *ret);
extern unsigned long __read_page_state(unsigned long offset);
extern void __mod_page_state(unsigned long offset, unsigned long delta);
@@ -194,6 +195,7 @@ extern void __mod_page_state(unsigned long offset, unsigned long delta);
#define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags)
#define TestSetPageDirty(page) test_and_set_bit(PG_dirty, &(page)->flags)
#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags)
+#define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags)
#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)
#define SetPageLRU(page) set_bit(PG_lru, &(page)->flags)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index bc4c40000c0d..7349058ed778 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -19,436 +19,10 @@
#include <linux/mod_devicetable.h>
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_VENDOR_ID 0x00 /* 16 bits */
-#define PCI_DEVICE_ID 0x02 /* 16 bits */
-#define PCI_COMMAND 0x04 /* 16 bits */
-#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
-#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
-#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
-#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
-#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
-#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
-#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
-#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
-#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
-#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
-
-#define PCI_STATUS 0x06 /* 16 bits */
-#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
-#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
-#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
-#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
-#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
-#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
-#define PCI_STATUS_DEVSEL_FAST 0x000
-#define PCI_STATUS_DEVSEL_MEDIUM 0x200
-#define PCI_STATUS_DEVSEL_SLOW 0x400
-#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
-#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
-#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
-#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
-#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
- revision */
-#define PCI_REVISION_ID 0x08 /* Revision ID */
-#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE 0x0a /* Device class */
-
-#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
-#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
-#define PCI_HEADER_TYPE 0x0e /* 8 bits */
-#define PCI_HEADER_TYPE_NORMAL 0
-#define PCI_HEADER_TYPE_BRIDGE 1
-#define PCI_HEADER_TYPE_CARDBUS 2
-
-#define PCI_BIST 0x0f /* 8 bits */
-#define PCI_BIST_CODE_MASK 0x0f /* Return result */
-#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
-#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back. Only
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
-#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
-#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
-#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
-#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
-#define PCI_BASE_ADDRESS_SPACE_IO 0x01
-#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
-#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
-#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
-#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
-#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
-#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
-#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
-#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS 0x28
-#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
-#define PCI_SUBSYSTEM_ID 0x2e
-#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
-#define PCI_ROM_ADDRESS_ENABLE 0x01
-#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
-
-#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
-
-/* 0x35-0x3b are reserved */
-#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
-#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
-#define PCI_MIN_GNT 0x3e /* 8 bits */
-#define PCI_MAX_LAT 0x3f /* 8 bits */
-
-/* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
-#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
-#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
-#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
-#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
-#define PCI_IO_LIMIT 0x1d
-#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
-#define PCI_IO_RANGE_TYPE_16 0x00
-#define PCI_IO_RANGE_TYPE_32 0x01
-#define PCI_IO_RANGE_MASK (~0x0fUL)
-#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
-#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
-#define PCI_MEMORY_LIMIT 0x22
-#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
-#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT 0x26
-#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define PCI_PREF_RANGE_TYPE_32 0x00
-#define PCI_PREF_RANGE_TYPE_64 0x01
-#define PCI_PREF_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
-#define PCI_PREF_LIMIT_UPPER32 0x2c
-#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
-#define PCI_IO_LIMIT_UPPER16 0x32
-/* 0x34 same as for htype 0 */
-/* 0x35-0x3b is reserved */
-#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_BRIDGE_CONTROL 0x3e
-#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
-#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
-#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
-#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
-#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
-#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
-#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
-
-/* Header type 2 (CardBus bridges) */
-#define PCI_CB_CAPABILITY_LIST 0x14
-/* 0x15 reserved */
-#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
-#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
-#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
-#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
-#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
-#define PCI_CB_MEMORY_BASE_0 0x1c
-#define PCI_CB_MEMORY_LIMIT_0 0x20
-#define PCI_CB_MEMORY_BASE_1 0x24
-#define PCI_CB_MEMORY_LIMIT_1 0x28
-#define PCI_CB_IO_BASE_0 0x2c
-#define PCI_CB_IO_BASE_0_HI 0x2e
-#define PCI_CB_IO_LIMIT_0 0x30
-#define PCI_CB_IO_LIMIT_0_HI 0x32
-#define PCI_CB_IO_BASE_1 0x34
-#define PCI_CB_IO_BASE_1_HI 0x36
-#define PCI_CB_IO_LIMIT_1 0x38
-#define PCI_CB_IO_LIMIT_1_HI 0x3a
-#define PCI_CB_IO_RANGE_MASK (~0x03UL)
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_CB_BRIDGE_CONTROL 0x3e
-#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
-#define PCI_CB_BRIDGE_CTL_SERR 0x02
-#define PCI_CB_BRIDGE_CTL_ISA 0x04
-#define PCI_CB_BRIDGE_CTL_VGA 0x08
-#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
-#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
-#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
-#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
-#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
-#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
-#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
-#define PCI_CB_SUBSYSTEM_ID 0x42
-#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
-/* 0x48-0x7f reserved */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID 0 /* Capability ID */
-#define PCI_CAP_ID_PM 0x01 /* Power Management */
-#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
-#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
-#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
-#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
-#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
-#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
-#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
-#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
-#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
-#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
-#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF 4
-
-/* Power Management Registers */
-
-#define PCI_PM_PMC 2 /* PM Capabilities Register */
-#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
-#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
-#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
-#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
-#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
-#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
-#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
-#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
-#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
-#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
-#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
-#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
-#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
-#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
-#define PCI_PM_CTRL 4 /* PM control and status register */
-#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
-#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
-#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
-#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
-#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
-#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
-#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
-#define PCI_PM_DATA_REGISTER 7 /* (??) */
-#define PCI_PM_SIZEOF 8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION 2 /* BCD version number */
-#define PCI_AGP_RFU 3 /* Rest of capability flags */
-#define PCI_AGP_STATUS 4 /* Status register */
-#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
-#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
-#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
-#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
-#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
-#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
-#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
-#define PCI_AGP_COMMAND 8 /* Control register */
-#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
-#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
-#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
-#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
-#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
-#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
-#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
-#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
-#define PCI_AGP_SIZEOF 12
-
-/* Vital Product Data */
-
-#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */
-#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
-#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
-#define PCI_VPD_DATA 4 /* 32-bits of data returned here */
-
-/* Slot Identification */
-
-#define PCI_SID_ESR 2 /* Expansion Slot Register */
-#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
-#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS 2 /* Various flags */
-#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
-#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
-#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
-#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
-#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */
-#define PCI_MSI_RFU 3 /* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
-#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_BIT 16 /* Mask bits register */
-
-/* CompactPCI Hotswap Register */
-
-#define PCI_CHSWP_CSR 2 /* Control and Status Register */
-#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */
-#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */
-#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */
-#define PCI_CHSWP_LOO 0x08 /* LED On / Off */
-#define PCI_CHSWP_PI 0x30 /* Programming Interface */
-#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */
-#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */
-
-/* PCI-X registers */
-
-#define PCI_X_CMD 2 /* Modes & Features */
-#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
-#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
-#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
-#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
-#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */
-#define PCI_X_STATUS 4 /* PCI-X capabilities */
-#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */
-#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
-#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */
-#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
-#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
-#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
-#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */
-#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */
-#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
-#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
-#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
-#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
-#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
-
-/* PCI Express capability registers */
-
-#define PCI_EXP_FLAGS 2 /* Capabilities register */
-#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */
-#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
-#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
-#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
-#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
-#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
-#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
-#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
-#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
-#define PCI_EXP_DEVCAP 4 /* Device capabilities */
-#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */
-#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */
-#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */
-#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */
-#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */
-#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */
-#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */
-#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */
-#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
-#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
-#define PCI_EXP_DEVCTL 8 /* Device Control */
-#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
-#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
-#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */
-#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */
-#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
-#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
-#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
-#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
-#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
-#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
-#define PCI_EXP_DEVSTA 10 /* Device Status */
-#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
-#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
-#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */
-#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
-#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
-#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
-#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
-#define PCI_EXP_LNKCTL 16 /* Link Control */
-#define PCI_EXP_LNKSTA 18 /* Link Status */
-#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
-#define PCI_EXP_SLTCTL 24 /* Slot Control */
-#define PCI_EXP_SLTSTA 26 /* Slot Status */
-#define PCI_EXP_RTCTL 28 /* Root Control */
-#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */
-#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */
-#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */
-#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */
-#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
-#define PCI_EXP_RTCAP 30 /* Root Capabilities */
-#define PCI_EXP_RTSTA 32 /* Root Status */
-
-/* Extended Capabilities (PCI-X 2.0 and Express) */
-#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
-#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
-#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
-
-#define PCI_EXT_CAP_ID_ERR 1
-#define PCI_EXT_CAP_ID_VC 2
-#define PCI_EXT_CAP_ID_DSN 3
-#define PCI_EXT_CAP_ID_PWR 4
-
-/* Advanced Error Reporting */
-#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
-#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */
-#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
-#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
-#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
-#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
-#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */
-#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */
-#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */
-#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
-#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
-#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
-#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
- /* Same bits as above */
-#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
- /* Same bits as above */
-#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */
-#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */
-#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */
-#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
-#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
-#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
-#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
- /* Same bits as above */
-#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */
-#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */
-#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
-#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
-#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
-#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
-#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */
-#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */
-#define PCI_ERR_ROOT_STATUS 48
-#define PCI_ERR_ROOT_COR_SRC 52
-#define PCI_ERR_ROOT_SRC 54
-
-/* Virtual Channel */
-#define PCI_VC_PORT_REG1 4
-#define PCI_VC_PORT_REG2 8
-#define PCI_VC_PORT_CTRL 12
-#define PCI_VC_PORT_STATUS 14
-#define PCI_VC_RES_CAP 16
-#define PCI_VC_RES_CTRL 20
-#define PCI_VC_RES_STATUS 26
-
-/* Power Budgeting */
-#define PCI_PWR_DSR 4 /* Data Select Register */
-#define PCI_PWR_DATA 8 /* Data Register */
-#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */
-#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */
-#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */
-#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */
-#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
-#define PCI_PWR_CAP 12 /* Capability */
-#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
+/* Include the pci register defines */
+#include <linux/pci_regs.h>
/* Include the ID list */
-
#include <linux/pci_ids.h>
/*
@@ -496,11 +70,12 @@ enum pci_mmap_state {
typedef int __bitwise pci_power_t;
-#define PCI_D0 ((pci_power_t __force) 0)
-#define PCI_D1 ((pci_power_t __force) 1)
-#define PCI_D2 ((pci_power_t __force) 2)
+#define PCI_D0 ((pci_power_t __force) 0)
+#define PCI_D1 ((pci_power_t __force) 1)
+#define PCI_D2 ((pci_power_t __force) 2)
#define PCI_D3hot ((pci_power_t __force) 3)
#define PCI_D3cold ((pci_power_t __force) 4)
+#define PCI_UNKNOWN ((pci_power_t __force) 5)
#define PCI_POWER_ERROR ((pci_power_t __force) -1)
/*
@@ -562,11 +137,6 @@ struct pci_dev {
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 */
-#ifdef CONFIG_PCI_NAMES
-#define PCI_NAME_SIZE 255
-#define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */
- char pretty_name[PCI_NAME_SIZE]; /* pretty name for users to see */
-#endif
};
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
@@ -582,15 +152,15 @@ struct pci_dev {
* 7-10 bridges: address space assigned to buses behind the bridge
*/
-#define PCI_ROM_RESOURCE 6
-#define PCI_BRIDGE_RESOURCES 7
-#define PCI_NUM_RESOURCES 11
+#define PCI_ROM_RESOURCE 6
+#define PCI_BRIDGE_RESOURCES 7
+#define PCI_NUM_RESOURCES 11
#ifndef PCI_BUS_NUM_RESOURCES
-#define PCI_BUS_NUM_RESOURCES 8
+#define PCI_BUS_NUM_RESOURCES 8
#endif
-
-#define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */
+
+#define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */
struct pci_bus {
struct list_head node; /* node in list of buses */
@@ -699,7 +269,7 @@ struct pci_driver {
* @dev_class_mask: the class mask for this device
*
* This macro is used to create a struct pci_device_id that matches a
- * specific PCI class. The vendor, device, subvendor, and subdevice
+ * specific PCI class. The vendor, device, subvendor, and subdevice
* fields will be set to PCI_ANY_ID.
*/
#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \
@@ -707,7 +277,7 @@ struct pci_driver {
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
-/*
+/*
* pci_module_init is obsolete, this stays here till we fix up all usages of it
* in the tree.
*/
@@ -745,12 +315,13 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
pci_bus_add_devices(root_bus);
return root_bus;
}
+struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
+struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
int pci_scan_slot(struct pci_bus *bus, int devfn);
struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
+void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
unsigned int pci_scan_child_bus(struct pci_bus *bus);
void pci_bus_add_device(struct pci_dev *dev);
-void pci_name_device(struct pci_dev *dev);
-char *pci_class_name(u32 class);
void pci_read_bridge_bases(struct pci_bus *child);
struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
@@ -758,6 +329,7 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
extern void pci_dev_put(struct pci_dev *dev);
extern void pci_remove_bus(struct pci_bus *b);
extern void pci_remove_bus_device(struct pci_dev *dev);
+void pci_setup_cardbus(struct pci_bus *bus);
/* Generic PCI functions exported to card drivers */
@@ -815,13 +387,16 @@ void pci_set_master(struct pci_dev *dev);
#define HAVE_PCI_SET_MWI
int pci_set_mwi(struct pci_dev *dev);
void pci_clear_mwi(struct pci_dev *dev);
+void pci_intx(struct pci_dev *dev, int enable);
int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
+void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
int pci_assign_resource(struct pci_dev *dev, int i);
+void pci_restore_bars(struct pci_dev *dev);
/* ROM control related routines */
-void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size);
-void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
+void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
+void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
void pci_remove_rom(struct pci_dev *pdev);
@@ -865,6 +440,9 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv, struct pci_
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
+void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+ void *userdata);
+
/* kmem_cache style wrapper around pci_alloc_consistent() */
#include <linux/dmapool.h>
@@ -912,18 +490,26 @@ extern void pci_disable_msix(struct pci_dev *dev);
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
#endif
-#endif /* CONFIG_PCI */
-
-/* Include architecture-dependent settings and functions */
+/*
+ * PCI domain support. Sometimes called PCI segment (eg by ACPI),
+ * a PCI domain is defined to be a set of PCI busses which share
+ * configuration space.
+ */
+#ifndef CONFIG_PCI_DOMAINS
+static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+ return 0;
+}
+#endif
-#include <asm/pci.h>
+#else /* CONFIG_PCI is not enabled */
/*
* If the system does not have PCI, clearly these return errors. Define
* these as simple inline functions to avoid hair in drivers.
*/
-#ifndef CONFIG_PCI
#define _PCI_NOP(o,s,t) \
static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \
{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
@@ -974,21 +560,11 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en
#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
-#else
+#endif /* CONFIG_PCI */
-/*
- * PCI domain support. Sometimes called PCI segment (eg by ACPI),
- * a PCI domain is defined to be a set of PCI busses which share
- * configuration space.
- */
-#ifndef CONFIG_PCI_DOMAINS
-static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
- return 0;
-}
-#endif
-#endif /* !CONFIG_PCI */
+/* Include architecture-dependent settings and functions */
+
+#include <asm/pci.h>
/* these helpers provide future and backwards compatibility
* for accessing popular PCI BAR info */
@@ -1025,13 +601,6 @@ static inline char *pci_name(struct pci_dev *pdev)
return pdev->dev.bus_id;
}
-/* Some archs want to see the pretty pci name, so use this macro */
-#ifdef CONFIG_PCI_NAMES
-#define pci_pretty_name(dev) ((dev)->pretty_name)
-#else
-#define pci_pretty_name(dev) ""
-#endif
-
/* Some archs don't want to expose struct resource to userland as-is
* in sysfs and /proc
@@ -1067,7 +636,7 @@ enum pci_fixup_pass {
/* Anonymous variables would be nice... */
#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \
- static struct pci_fixup __pci_fixup_##name __attribute_used__ \
+ static const struct pci_fixup __pci_fixup_##name __attribute_used__ \
__attribute__((__section__(#section))) = { vendor, device, hook };
#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 927ed487630d..f6c1a142286a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -447,6 +447,10 @@
#define PCI_DEVICE_ID_CIRRUS_7542 0x1200
#define PCI_DEVICE_ID_CIRRUS_7543 0x1202
#define PCI_DEVICE_ID_CIRRUS_7541 0x1204
+#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
+#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
+#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
+#define PCI_DEVICE_ID_CIRRUS_4281 0x6005
#define PCI_VENDOR_ID_IBM 0x1014
#define PCI_DEVICE_ID_IBM_FIRE_CORAL 0x000a
@@ -682,7 +686,9 @@
#define PCI_DEVICE_ID_SI_6326 0x6326
#define PCI_DEVICE_ID_SI_7001 0x7001
#define PCI_DEVICE_ID_SI_7012 0x7012
+#define PCI_DEVICE_ID_SI_7013 0x7013
#define PCI_DEVICE_ID_SI_7016 0x7016
+#define PCI_DEVICE_ID_SI_7018 0x7018
#define PCI_VENDOR_ID_HP 0x103c
#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005
@@ -713,10 +719,12 @@
#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282
#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290
#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301
+#define PCI_DEVICE_ID_HP_CISS 0x3210
#define PCI_DEVICE_ID_HP_CISSA 0x3220
#define PCI_DEVICE_ID_HP_CISSB 0x3222
-#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_DEVICE_ID_HP_CISSC 0x3230
+#define PCI_DEVICE_ID_HP_CISSD 0x3238
+#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_VENDOR_ID_PCTECH 0x1042
#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
@@ -991,6 +999,7 @@
#define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
+#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
#define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
#define PCI_VENDOR_ID_SIERRA 0x10a8
@@ -1109,6 +1118,9 @@
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV 0x0005
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS 0x0083
+#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
+#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
+#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
#define PCI_VENDOR_ID_ASP 0x10cd
#define PCI_DEVICE_ID_ASP_ABP940 0x1200
@@ -1155,10 +1167,13 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065
#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069
#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085
#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a
#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e
#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0
@@ -1173,6 +1188,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5
#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9
#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1
@@ -1180,6 +1196,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5
#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
@@ -1230,6 +1247,7 @@
#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4
#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc
+#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1
#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3
#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200
@@ -1249,6 +1267,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x036F
#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268
#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269
#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B
@@ -1333,6 +1352,13 @@
#define PCI_DEVICE_ID_REALTEK_8169 0x8169
#define PCI_VENDOR_ID_XILINX 0x10ee
+#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0
+#define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1
+#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
+#define PCI_DEVICE_IDRME__DIGI96_8_PAD_OR_PST 0x3fc3
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
#define PCI_DEVICE_ID_TURBOPAM 0x4020
#define PCI_VENDOR_ID_TRUEVISION 0x10fa
@@ -1611,6 +1637,7 @@
#define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030
#define PCI_DEVICE_ID_TOSHIBA_TX4927 0x0180
#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108
+#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
#define PCI_VENDOR_ID_RICOH 0x1180
#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465
@@ -1807,6 +1834,14 @@
#define PCI_DEVICE_ID_ESS_ESS1968 0x1968
#define PCI_DEVICE_ID_ESS_AUDIOPCI 0x1969
#define PCI_DEVICE_ID_ESS_ESS1978 0x1978
+#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988
+#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989
+#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
+#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992
+#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998
+#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999
+#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a
+#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b
#define PCI_VENDOR_ID_SATSAGEM 0x1267
#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
@@ -1966,6 +2001,9 @@
#define PCI_DEVICE_ID_LMC_SSI 0x0005
#define PCI_DEVICE_ID_LMC_T1 0x0006
+#define PCI_VENDOR_ID_MARIAN 0x1382
+#define PCI_DEVICE_ID_MARIAN_PRODIF_PLUS 0x2048
+
#define PCI_VENDOR_ID_NETGEAR 0x1385
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
#define PCI_DEVICE_ID_NETGEAR_GA622 0x622a
@@ -2054,6 +2092,10 @@
#define PCI_VENDOR_ID_TIMEDIA 0x1409
#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168
+#define PCI_VENDOR_ID_ICE 0x1412
+#define PCI_DEVICE_ID_ICE_1712 0x1712
+#define PCI_DEVICE_ID_VT1724 0x1724
+
#define PCI_VENDOR_ID_OXSEMI 0x1415
#define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403
#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501
@@ -2144,6 +2186,10 @@
#define PCI_DEVICE_ID_ENE_1225 0x1225
#define PCI_DEVICE_ID_ENE_1410 0x1410
#define PCI_DEVICE_ID_ENE_1420 0x1420
+#define PCI_VENDOR_ID_CHELSIO 0x1425
+
+#define PCI_VENDOR_ID_MIPS 0x153f
+#define PCI_DEVICE_ID_SOC_IT 0x0001
#define PCI_VENDOR_ID_SYBA 0x1592
#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782
@@ -2530,6 +2576,7 @@
#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191
#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192
#define PCI_DEVICE_ID_INTEL_440MX 0x7195
+#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196
#define PCI_DEVICE_ID_INTEL_82443MX_0 0x7198
#define PCI_DEVICE_ID_INTEL_82443MX_1 0x7199
#define PCI_DEVICE_ID_INTEL_82443MX_2 0x719a
@@ -2636,6 +2683,11 @@
#define PCI_VENDOR_ID_TTTECH 0x0357
#define PCI_DEVICE_ID_TTTECH_MC322 0x000A
+#define PCI_VENDOR_ID_XILINX_RME 0xea60
+#define PCI_DEVICE_ID_RME_DIGI32 0x9896
+#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
+#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
+
#define PCI_VENDOR_ID_ARK 0xedd8
#define PCI_DEVICE_ID_ARK_STING 0xa091
#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
new file mode 100644
index 000000000000..e2a089b051ed
--- /dev/null
+++ b/include/linux/pci_regs.h
@@ -0,0 +1,448 @@
+/*
+ * pci_regs.h
+ *
+ * PCI standard defines
+ * Copyright 1994, Drew Eckhardt
+ * Copyright 1997--1999 Martin Mares <mj@ucw.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ */
+
+#ifndef LINUX_PCI_REGS_H
+#define LINUX_PCI_REGS_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK (~0x0fUL)
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST 0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
+#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
+#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0 0x1c
+#define PCI_CB_MEMORY_LIMIT_0 0x20
+#define PCI_CB_MEMORY_BASE_1 0x24
+#define PCI_CB_MEMORY_LIMIT_1 0x28
+#define PCI_CB_IO_BASE_0 0x2c
+#define PCI_CB_IO_BASE_0_HI 0x2e
+#define PCI_CB_IO_LIMIT_0 0x30
+#define PCI_CB_IO_LIMIT_0_HI 0x32
+#define PCI_CB_IO_BASE_1 0x34
+#define PCI_CB_IO_BASE_1_HI 0x36
+#define PCI_CB_IO_LIMIT_1 0x38
+#define PCI_CB_IO_LIMIT_1_HI 0x3a
+#define PCI_CB_IO_RANGE_MASK (~0x03UL)
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL 0x3e
+#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
+#define PCI_CB_BRIDGE_CTL_SERR 0x02
+#define PCI_CB_BRIDGE_CTL_ISA 0x04
+#define PCI_CB_BRIDGE_CTL_VGA 0x08
+#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
+#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
+#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
+#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF 4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC 2 /* PM Capabilities Register */
+#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
+#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
+#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
+#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
+#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
+#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
+#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
+#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
+#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
+#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
+#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
+#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
+#define PCI_PM_CTRL 4 /* PM control and status register */
+#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */
+#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
+#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
+#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
+#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
+#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER 7 /* (??) */
+#define PCI_PM_SIZEOF 8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION 2 /* BCD version number */
+#define PCI_AGP_RFU 3 /* Rest of capability flags */
+#define PCI_AGP_STATUS 4 /* Status register */
+#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
+#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
+#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
+#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
+#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
+#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
+#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND 8 /* Control register */
+#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
+#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
+#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
+#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
+#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
+#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
+#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
+#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
+#define PCI_AGP_SIZEOF 12
+
+/* Vital Product Data */
+
+#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */
+#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
+#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
+#define PCI_VPD_DATA 4 /* 32-bits of data returned here */
+
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+#define PCI_MSI_MASK_BIT 16 /* Mask bits register */
+
+/* CompactPCI Hotswap Register */
+
+#define PCI_CHSWP_CSR 2 /* Control and Status Register */
+#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */
+#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */
+#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */
+#define PCI_CHSWP_LOO 0x08 /* LED On / Off */
+#define PCI_CHSWP_PI 0x30 /* Programming Interface */
+#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */
+#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */
+
+/* PCI-X registers */
+
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
+#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
+#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */
+#define PCI_X_STATUS 4 /* PCI-X capabilities */
+#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */
+#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
+#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */
+#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
+#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
+#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
+#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */
+#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */
+#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
+#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
+#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
+#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
+#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
+
+/* PCI Express capability registers */
+
+#define PCI_EXP_FLAGS 2 /* Capabilities register */
+#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */
+#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
+#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
+#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
+#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
+#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
+#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
+#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
+#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
+#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
+#define PCI_EXP_DEVCAP 4 /* Device capabilities */
+#define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */
+#define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */
+#define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */
+#define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */
+#define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */
+#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */
+#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */
+#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */
+#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
+#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
+#define PCI_EXP_DEVCTL 8 /* Device Control */
+#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
+#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
+#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */
+#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */
+#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
+#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
+#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
+#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
+#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
+#define PCI_EXP_DEVSTA 10 /* Device Status */
+#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
+#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
+#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */
+#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
+#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
+#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
+#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
+#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKSTA 18 /* Link Status */
+#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
+#define PCI_EXP_SLTCTL 24 /* Slot Control */
+#define PCI_EXP_SLTSTA 26 /* Slot Status */
+#define PCI_EXP_RTCTL 28 /* Root Control */
+#define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */
+#define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */
+#define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */
+#define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */
+#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
+#define PCI_EXP_RTCAP 30 /* Root Capabilities */
+#define PCI_EXP_RTSTA 32 /* Root Status */
+
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
+#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
+#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
+
+#define PCI_EXT_CAP_ID_ERR 1
+#define PCI_EXT_CAP_ID_VC 2
+#define PCI_EXT_CAP_ID_DSN 3
+#define PCI_EXT_CAP_ID_PWR 4
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
+#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */
+#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
+#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
+#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
+#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
+#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */
+#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */
+#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */
+#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
+#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
+#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
+#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
+ /* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
+ /* Same bits as above */
+#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */
+#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */
+#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */
+#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
+#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
+#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
+#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
+ /* Same bits as above */
+#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */
+#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */
+#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
+#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
+#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
+#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
+#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */
+#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */
+#define PCI_ERR_ROOT_STATUS 48
+#define PCI_ERR_ROOT_COR_SRC 52
+#define PCI_ERR_ROOT_SRC 54
+
+/* Virtual Channel */
+#define PCI_VC_PORT_REG1 4
+#define PCI_VC_PORT_REG2 8
+#define PCI_VC_PORT_CTRL 12
+#define PCI_VC_PORT_STATUS 14
+#define PCI_VC_RES_CAP 16
+#define PCI_VC_RES_CTRL 20
+#define PCI_VC_RES_STATUS 26
+
+/* Power Budgeting */
+#define PCI_PWR_DSR 4 /* Data Select Register */
+#define PCI_PWR_DATA 8 /* Data Register */
+#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */
+#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */
+#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */
+#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
+#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */
+#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
+#define PCI_PWR_CAP 12 /* Capability */
+#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
+
+#endif /* LINUX_PCI_REGS_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
new file mode 100644
index 000000000000..72cb67b66e0c
--- /dev/null
+++ b/include/linux/phy.h
@@ -0,0 +1,377 @@
+/*
+ * include/linux/phy.h
+ *
+ * Framework and drivers for configuring and reading different PHYs
+ * Based on code in sungem_phy.c and gianfar_phy.c
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __PHY_H
+#define __PHY_H
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
+ SUPPORTED_10baseT_Full | \
+ SUPPORTED_100baseT_Half | \
+ SUPPORTED_100baseT_Full | \
+ SUPPORTED_Autoneg | \
+ SUPPORTED_TP | \
+ SUPPORTED_MII)
+
+#define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \
+ SUPPORTED_1000baseT_Half | \
+ SUPPORTED_1000baseT_Full)
+
+/* Set phydev->irq to PHY_POLL if interrupts are not supported,
+ * or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if
+ * the attached driver handles the interrupt
+ */
+#define PHY_POLL -1
+#define PHY_IGNORE_INTERRUPT -2
+
+#define PHY_HAS_INTERRUPT 0x00000001
+#define PHY_HAS_MAGICANEG 0x00000002
+
+#define MII_BUS_MAX 4
+
+
+#define PHY_INIT_TIMEOUT 100000
+#define PHY_STATE_TIME 1
+#define PHY_FORCE_TIMEOUT 10
+#define PHY_AN_TIMEOUT 10
+
+#define PHY_MAX_ADDR 32
+
+/* The Bus class for PHYs. Devices which provide access to
+ * PHYs should register using this structure */
+struct mii_bus {
+ const char *name;
+ int id;
+ void *priv;
+ int (*read)(struct mii_bus *bus, int phy_id, int regnum);
+ int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
+ int (*reset)(struct mii_bus *bus);
+
+ /* A lock to ensure that only one thing can read/write
+ * the MDIO bus at a time */
+ spinlock_t mdio_lock;
+
+ struct device *dev;
+
+ /* list of all PHYs on bus */
+ struct phy_device *phy_map[PHY_MAX_ADDR];
+
+ /* Pointer to an array of interrupts, each PHY's
+ * interrupt at the index matching its address */
+ int *irq;
+};
+
+#define PHY_INTERRUPT_DISABLED 0x0
+#define PHY_INTERRUPT_ENABLED 0x80000000
+
+/* PHY state machine states:
+ *
+ * DOWN: PHY device and driver are not ready for anything. probe
+ * should be called if and only if the PHY is in this state,
+ * given that the PHY device exists.
+ * - PHY driver probe function will, depending on the PHY, set
+ * the state to STARTING or READY
+ *
+ * STARTING: PHY device is coming up, and the ethernet driver is
+ * not ready. PHY drivers may set this in the probe function.
+ * If they do, they are responsible for making sure the state is
+ * eventually set to indicate whether the PHY is UP or READY,
+ * depending on the state when the PHY is done starting up.
+ * - PHY driver will set the state to READY
+ * - start will set the state to PENDING
+ *
+ * READY: PHY is ready to send and receive packets, but the
+ * controller is not. By default, PHYs which do not implement
+ * probe will be set to this state by phy_probe(). If the PHY
+ * driver knows the PHY is ready, and the PHY state is STARTING,
+ * then it sets this STATE.
+ * - start will set the state to UP
+ *
+ * PENDING: PHY device is coming up, but the ethernet driver is
+ * ready. phy_start will set this state if the PHY state is
+ * STARTING.
+ * - PHY driver will set the state to UP when the PHY is ready
+ *
+ * UP: The PHY and attached device are ready to do work.
+ * Interrupts should be started here.
+ * - timer moves to AN
+ *
+ * AN: The PHY is currently negotiating the link state. Link is
+ * therefore down for now. phy_timer will set this state when it
+ * detects the state is UP. config_aneg will set this state
+ * whenever called with phydev->autoneg set to AUTONEG_ENABLE.
+ * - If autonegotiation finishes, but there's no link, it sets
+ * the state to NOLINK.
+ * - If aneg finishes with link, it sets the state to RUNNING,
+ * and calls adjust_link
+ * - If autonegotiation did not finish after an arbitrary amount
+ * of time, autonegotiation should be tried again if the PHY
+ * supports "magic" autonegotiation (back to AN)
+ * - If it didn't finish, and no magic_aneg, move to FORCING.
+ *
+ * NOLINK: PHY is up, but not currently plugged in.
+ * - If the timer notes that the link comes back, we move to RUNNING
+ * - config_aneg moves to AN
+ * - phy_stop moves to HALTED
+ *
+ * FORCING: PHY is being configured with forced settings
+ * - if link is up, move to RUNNING
+ * - If link is down, we drop to the next highest setting, and
+ * retry (FORCING) after a timeout
+ * - phy_stop moves to HALTED
+ *
+ * RUNNING: PHY is currently up, running, and possibly sending
+ * and/or receiving packets
+ * - timer will set CHANGELINK if we're polling (this ensures the
+ * link state is polled every other cycle of this state machine,
+ * which makes it every other second)
+ * - irq will set CHANGELINK
+ * - config_aneg will set AN
+ * - phy_stop moves to HALTED
+ *
+ * CHANGELINK: PHY experienced a change in link state
+ * - timer moves to RUNNING if link
+ * - timer moves to NOLINK if the link is down
+ * - phy_stop moves to HALTED
+ *
+ * HALTED: PHY is up, but no polling or interrupts are done. Or
+ * PHY is in an error state.
+ *
+ * - phy_start moves to RESUMING
+ *
+ * RESUMING: PHY was halted, but now wants to run again.
+ * - If we are forcing, or aneg is done, timer moves to RUNNING
+ * - If aneg is not done, timer moves to AN
+ * - phy_stop moves to HALTED
+ */
+enum phy_state {
+ PHY_DOWN=0,
+ PHY_STARTING,
+ PHY_READY,
+ PHY_PENDING,
+ PHY_UP,
+ PHY_AN,
+ PHY_RUNNING,
+ PHY_NOLINK,
+ PHY_FORCING,
+ PHY_CHANGELINK,
+ PHY_HALTED,
+ PHY_RESUMING
+};
+
+/* phy_device: An instance of a PHY
+ *
+ * drv: Pointer to the driver for this PHY instance
+ * bus: Pointer to the bus this PHY is on
+ * dev: driver model device structure for this PHY
+ * phy_id: UID for this device found during discovery
+ * state: state of the PHY for management purposes
+ * dev_flags: Device-specific flags used by the PHY driver.
+ * addr: Bus address of PHY
+ * link_timeout: The number of timer firings to wait before the
+ * giving up on the current attempt at acquiring a link
+ * irq: IRQ number of the PHY's interrupt (-1 if none)
+ * phy_timer: The timer for handling the state machine
+ * phy_queue: A work_queue for the interrupt
+ * attached_dev: The attached enet driver's device instance ptr
+ * adjust_link: Callback for the enet controller to respond to
+ * changes in the link state.
+ * adjust_state: Callback for the enet driver to respond to
+ * changes in the state machine.
+ *
+ * speed, duplex, pause, supported, advertising, and
+ * autoneg are used like in mii_if_info
+ *
+ * interrupts currently only supports enabled or disabled,
+ * but could be changed in the future to support enabling
+ * and disabling specific interrupts
+ *
+ * Contains some infrastructure for polling and interrupt
+ * handling, as well as handling shifts in PHY hardware state
+ */
+struct phy_device {
+ /* Information about the PHY type */
+ /* And management functions */
+ struct phy_driver *drv;
+
+ struct mii_bus *bus;
+
+ struct device dev;
+
+ u32 phy_id;
+
+ enum phy_state state;
+
+ u32 dev_flags;
+
+ /* Bus address of the PHY (0-32) */
+ int addr;
+
+ /* forced speed & duplex (no autoneg)
+ * partner speed & duplex & pause (autoneg)
+ */
+ int speed;
+ int duplex;
+ int pause;
+ int asym_pause;
+
+ /* The most recently read link state */
+ int link;
+
+ /* Enabled Interrupts */
+ u32 interrupts;
+
+ /* Union of PHY and Attached devices' supported modes */
+ /* See mii.h for more info */
+ u32 supported;
+ u32 advertising;
+
+ int autoneg;
+
+ int link_timeout;
+
+ /* Interrupt number for this PHY
+ * -1 means no interrupt */
+ int irq;
+
+ /* private data pointer */
+ /* For use by PHYs to maintain extra state */
+ void *priv;
+
+ /* Interrupt and Polling infrastructure */
+ struct work_struct phy_queue;
+ struct timer_list phy_timer;
+
+ spinlock_t lock;
+
+ struct net_device *attached_dev;
+
+ void (*adjust_link)(struct net_device *dev);
+
+ void (*adjust_state)(struct net_device *dev);
+};
+#define to_phy_device(d) container_of(d, struct phy_device, dev)
+
+/* struct phy_driver: Driver structure for a particular PHY type
+ *
+ * phy_id: The result of reading the UID registers of this PHY
+ * type, and ANDing them with the phy_id_mask. This driver
+ * only works for PHYs with IDs which match this field
+ * name: The friendly name of this PHY type
+ * phy_id_mask: Defines the important bits of the phy_id
+ * features: A list of features (speed, duplex, etc) supported
+ * by this PHY
+ * flags: A bitfield defining certain other features this PHY
+ * supports (like interrupts)
+ *
+ * The drivers must implement config_aneg and read_status. All
+ * other functions are optional. Note that none of these
+ * functions should be called from interrupt time. The goal is
+ * for the bus read/write functions to be able to block when the
+ * bus transaction is happening, and be freed up by an interrupt
+ * (The MPC85xx has this ability, though it is not currently
+ * supported in the driver).
+ */
+struct phy_driver {
+ u32 phy_id;
+ char *name;
+ unsigned int phy_id_mask;
+ u32 features;
+ u32 flags;
+
+ /* Called to initialize the PHY,
+ * including after a reset */
+ int (*config_init)(struct phy_device *phydev);
+
+ /* Called during discovery. Used to set
+ * up device-specific structures, if any */
+ int (*probe)(struct phy_device *phydev);
+
+ /* PHY Power Management */
+ int (*suspend)(struct phy_device *phydev);
+ int (*resume)(struct phy_device *phydev);
+
+ /* Configures the advertisement and resets
+ * autonegotiation if phydev->autoneg is on,
+ * forces the speed to the current settings in phydev
+ * if phydev->autoneg is off */
+ int (*config_aneg)(struct phy_device *phydev);
+
+ /* Determines the negotiated speed and duplex */
+ int (*read_status)(struct phy_device *phydev);
+
+ /* Clears any pending interrupts */
+ int (*ack_interrupt)(struct phy_device *phydev);
+
+ /* Enables or disables interrupts */
+ int (*config_intr)(struct phy_device *phydev);
+
+ /* Clears up any memory if needed */
+ void (*remove)(struct phy_device *phydev);
+
+ struct device_driver driver;
+};
+#define to_phy_driver(d) container_of(d, struct phy_driver, driver)
+
+int phy_read(struct phy_device *phydev, u16 regnum);
+int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
+struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
+int phy_clear_interrupt(struct phy_device *phydev);
+int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+struct phy_device * phy_attach(struct net_device *dev,
+ const char *phy_id, u32 flags);
+struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+ void (*handler)(struct net_device *), u32 flags);
+void phy_disconnect(struct phy_device *phydev);
+void phy_detach(struct phy_device *phydev);
+void phy_start(struct phy_device *phydev);
+void phy_stop(struct phy_device *phydev);
+int phy_start_aneg(struct phy_device *phydev);
+
+int mdiobus_register(struct mii_bus *bus);
+void mdiobus_unregister(struct mii_bus *bus);
+void phy_sanitize_settings(struct phy_device *phydev);
+int phy_stop_interrupts(struct phy_device *phydev);
+
+static inline int phy_read_status(struct phy_device *phydev) {
+ return phydev->drv->read_status(phydev);
+}
+
+int genphy_config_advert(struct phy_device *phydev);
+int genphy_setup_forced(struct phy_device *phydev);
+int genphy_restart_aneg(struct phy_device *phydev);
+int genphy_config_aneg(struct phy_device *phydev);
+int genphy_update_link(struct phy_device *phydev);
+int genphy_read_status(struct phy_device *phydev);
+void phy_driver_unregister(struct phy_driver *drv);
+int phy_driver_register(struct phy_driver *new_driver);
+void phy_prepare_link(struct phy_device *phydev,
+ void (*adjust_link)(struct net_device *));
+void phy_start_machine(struct phy_device *phydev,
+ void (*handler)(struct net_device *));
+void phy_stop_machine(struct phy_device *phydev);
+int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+int phy_mii_ioctl(struct phy_device *phydev,
+ struct mii_ioctl_data *mii_data, int cmd);
+int phy_start_interrupts(struct phy_device *phydev);
+void phy_print_status(struct phy_device *phydev);
+
+extern struct bus_type mdio_bus_type;
+#endif /* __PHY_H */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 36725e7c02c6..1767073df26f 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -39,9 +39,6 @@ struct pipe_inode_info {
#define PIPE_SEM(inode) (&(inode).i_sem)
#define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
-#define PIPE_BASE(inode) ((inode).i_pipe->base)
-#define PIPE_START(inode) ((inode).i_pipe->start)
-#define PIPE_LEN(inode) ((inode).i_pipe->len)
#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)
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 4b32bce9a289..2c177e4c8f22 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -166,6 +166,9 @@ struct packet_iosched
/*
* 32 buffers of 2048 bytes
*/
+#if (PAGE_SIZE % CD_FRAMESIZE) != 0
+#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
+#endif
#define PACKET_MAX_SIZE 32
#define PAGES_PER_PACKET (PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE)
#define PACKET_MAX_SECTORS (PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 7aeb208ed713..5cfb07648eca 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -186,7 +186,9 @@ extern int pm_suspend(suspend_state_t state);
struct device;
-typedef u32 __bitwise pm_message_t;
+typedef struct pm_message {
+ int event;
+} pm_message_t;
/*
* There are 4 important states driver can be in:
@@ -207,9 +209,13 @@ typedef u32 __bitwise pm_message_t;
* or something similar soon.
*/
-#define PMSG_FREEZE ((__force pm_message_t) 3)
-#define PMSG_SUSPEND ((__force pm_message_t) 3)
-#define PMSG_ON ((__force pm_message_t) 0)
+#define PM_EVENT_ON 0
+#define PM_EVENT_FREEZE 1
+#define PM_EVENT_SUSPEND 2
+
+#define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, })
+#define PMSG_SUSPEND ((struct pm_message){ .event = PM_EVENT_SUSPEND, })
+#define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, })
struct dev_pm_info {
pm_message_t power_state;
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 5ec2bd0c2848..aadbac29103c 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -443,7 +443,7 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; }
#define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
#define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg)
-#ifdef DEBUG
+#ifdef CONFIG_PNP_DEBUG
#define pnp_dbg(format, arg...) printk(KERN_DEBUG "pnp: " format "\n" , ## arg)
#else
#define pnp_dbg(format, arg...) do {} while (0)
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index a373fc254df2..dc6f3647bfbc 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -20,6 +20,8 @@
#define PTRACE_DETACH 0x11
#define PTRACE_SYSCALL 24
+#define PTRACE_SYSEMU 31
+#define PTRACE_SYSEMU_SINGLESTEP 32
/* 0x4200-0x4300 are reserved for architecture-independent additions. */
#define PTRACE_SETOPTIONS 0x4200
@@ -88,6 +90,7 @@ extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child);
extern void ptrace_untrace(struct task_struct *child);
+extern int ptrace_may_attach(struct task_struct *task);
static inline void ptrace_link(struct task_struct *child,
struct task_struct *new_parent)
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 8081a281fa5e..9c51917b1cce 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -24,7 +24,7 @@
struct radix_tree_root {
unsigned int height;
- int gfp_mask;
+ unsigned int gfp_mask;
struct radix_tree_node *rnode;
};
@@ -50,7 +50,7 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items);
-int radix_tree_preload(int gfp_mask);
+int radix_tree_preload(unsigned int __nocast gfp_mask);
void radix_tree_init(void);
void *radix_tree_tag_set(struct radix_tree_root *root,
unsigned long index, int tag);
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 4bf1659f8aa8..9de99198caf1 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -7,7 +7,7 @@
#define BITMAP_H 1
#define BITMAP_MAJOR 3
-#define BITMAP_MINOR 38
+#define BITMAP_MINOR 39
/*
* in-memory bitmap:
@@ -147,8 +147,9 @@ typedef struct bitmap_super_s {
__u32 state; /* 48 bitmap state information */
__u32 chunksize; /* 52 the bitmap chunk size in bytes */
__u32 daemon_sleep; /* 56 seconds between disk flushes */
+ __u32 write_behind; /* 60 number of outstanding write-behind writes */
- __u8 pad[256 - 60]; /* set to zero */
+ __u8 pad[256 - 64]; /* set to zero */
} bitmap_super_t;
/* notes:
@@ -226,6 +227,9 @@ struct bitmap {
unsigned long flags;
+ unsigned long max_write_behind; /* write-behind mode */
+ atomic_t behind_writes;
+
/*
* the bitmap daemon - periodically wakes up and sweeps the bitmap
* file, cleaning up bits and flushing out pages to disk as necessary
@@ -260,9 +264,10 @@ int bitmap_setallbits(struct bitmap *bitmap);
void bitmap_write_all(struct bitmap *bitmap);
/* these are exported */
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
-void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
- int success);
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
+ unsigned long sectors, int behind);
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
+ unsigned long sectors, int success, int behind);
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int degraded);
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
void bitmap_close_sync(struct bitmap *bitmap);
diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h
index e04c4fe45b53..7eaf290e10e7 100644
--- a/include/linux/raid/linear.h
+++ b/include/linux/raid/linear.h
@@ -14,8 +14,8 @@ typedef struct dev_info dev_info_t;
struct linear_private_data
{
dev_info_t **hash_table;
- dev_info_t *smallest;
- int nr_zones;
+ sector_t hash_spacing;
+ int preshift; /* shift before dividing by hash_spacing */
dev_info_t disks[0];
};
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 8c14ba565a45..ebce949b1443 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -86,70 +86,6 @@ typedef struct mdk_rdev_s mdk_rdev_t;
#define MAX_CHUNK_SIZE (4096*1024)
/*
- * default readahead
- */
-
-static inline int disk_faulty(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_FAULTY);
-}
-
-static inline int disk_active(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_ACTIVE);
-}
-
-static inline int disk_sync(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_SYNC);
-}
-
-static inline int disk_spare(mdp_disk_t * d)
-{
- return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
-}
-
-static inline int disk_removed(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_faulty(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_FAULTY);
-}
-
-static inline void mark_disk_active(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_sync(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_SYNC);
-}
-
-static inline void mark_disk_spare(mdp_disk_t * d)
-{
- d->state = 0;
-}
-
-static inline void mark_disk_removed(mdp_disk_t * d)
-{
- d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_inactive(mdp_disk_t * d)
-{
- d->state &= ~(1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_nonsync(mdp_disk_t * d)
-{
- d->state &= ~(1 << MD_DISK_SYNC);
-}
-
-/*
* MD's 'extended' device
*/
struct mdk_rdev_s
@@ -166,6 +102,7 @@ struct mdk_rdev_s
int sb_loaded;
sector_t data_offset; /* start of data in array */
sector_t sb_offset;
+ int sb_size; /* bytes in the superblock */
int preferred_minor; /* autorun support */
/* A device can be in one of three states based on two flags:
@@ -181,6 +118,9 @@ struct mdk_rdev_s
int faulty; /* if faulty do not issue IO requests */
int in_sync; /* device is a full member of the array */
+ unsigned long flags; /* Should include faulty and in_sync here. */
+#define WriteMostly 4 /* Avoid reading if at all possible */
+
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
int saved_raid_disk; /* role that device used to have in the
@@ -272,12 +212,19 @@ struct mddev_s
atomic_t writes_pending;
request_queue_t *queue; /* for plugging ... */
+ atomic_t write_behind; /* outstanding async IO */
+ unsigned int max_write_behind; /* 0 = sync */
+
struct bitmap *bitmap; /* the bitmap for the device */
struct file *bitmap_file; /* the bitmap file */
long bitmap_offset; /* offset from superblock of
* start of bitmap. May be
* negative, but not '0'
*/
+ long default_bitmap_offset; /* this is the offset to use when
+ * hot-adding a bitmap. It should
+ * eventually be settable by sysfs.
+ */
struct list_head all_mddevs;
};
@@ -314,6 +261,12 @@ struct mdk_personality_s
int (*resize) (mddev_t *mddev, sector_t sectors);
int (*reshape) (mddev_t *mddev, int raid_disks);
int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
+ /* quiesce moves between quiescence states
+ * 0 - fully active
+ * 1 - no new requests allowed
+ * others - reserved
+ */
+ void (*quiesce) (mddev_t *mddev, int state);
};
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index dc65cd435494..c100fa5d4bfa 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -79,6 +79,11 @@
#define MD_DISK_SYNC 2 /* disk is in sync with the raid set */
#define MD_DISK_REMOVED 3 /* disk is in sync with the raid set */
+#define MD_DISK_WRITEMOSTLY 9 /* disk is "write-mostly" is RAID1 config.
+ * read requests will only be sent here in
+ * dire need
+ */
+
typedef struct mdp_device_descriptor_s {
__u32 number; /* 0 Device number in the entire set */
__u32 major; /* 1 Device major number */
@@ -193,7 +198,7 @@ struct mdp_superblock_1 {
__u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/
__u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */
- __u32 layout; /* only for raid5 currently */
+ __u32 layout; /* only for raid5 and raid10 currently */
__u64 size; /* used size of component devices, in 512byte sectors */
__u32 chunksize; /* in 512byte sectors */
@@ -212,7 +217,9 @@ struct mdp_superblock_1 {
__u32 dev_number; /* permanent identifier of this device - not role in raid */
__u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */
__u8 device_uuid[16]; /* user-space setable, ignored by kernel */
- __u8 pad2[64-56]; /* set to 0 when writing */
+ __u8 devflags; /* per-device flags. Only one defined...*/
+#define WriteMostly1 1 /* mask for writemostly flag in above */
+ __u8 pad2[64-57]; /* set to 0 when writing */
/* array state information - 64 bytes */
__u64 utime; /* 40 bits second, 24 btes microseconds */
@@ -231,5 +238,10 @@ struct mdp_superblock_1 {
__u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
};
+/* feature_map bits */
+#define MD_FEATURE_BITMAP_OFFSET 1
+
+#define MD_FEATURE_ALL 1
+
#endif
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
index 9d93cf12e890..60e19b667548 100644
--- a/include/linux/raid/raid1.h
+++ b/include/linux/raid/raid1.h
@@ -80,6 +80,9 @@ struct r1bio_s {
atomic_t remaining; /* 'have we finished' count,
* used from IRQ handlers
*/
+ atomic_t behind_remaining; /* number of write-behind ios remaining
+ * in this BehindIO request
+ */
sector_t sector;
int sectors;
unsigned long state;
@@ -107,4 +110,14 @@ struct r1bio_s {
#define R1BIO_Uptodate 0
#define R1BIO_IsSync 1
#define R1BIO_Degraded 2
+#define R1BIO_BehindIO 3
+/* For write-behind requests, we call bi_end_io when
+ * the last non-write-behind device completes, providing
+ * any write was successful. Otherwise we call when
+ * any write-behind write succeeds, otherwise we call
+ * with failure when last write completes (and all failed).
+ * Record that bi_end_io was called with this flag...
+ */
+#define R1BIO_Returned 4
+
#endif
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index d63ddcb4afad..176fc653c284 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -134,6 +134,7 @@ struct stripe_head {
unsigned long state; /* state flags */
atomic_t count; /* nr of active thread/requests */
spinlock_t lock;
+ int bm_seq; /* sequence number for bitmap flushes */
struct r5dev {
struct bio req;
struct bio_vec vec;
@@ -165,12 +166,13 @@ struct stripe_head {
/*
* Stripe state
*/
-#define STRIPE_ERROR 1
#define STRIPE_HANDLE 2
#define STRIPE_SYNCING 3
#define STRIPE_INSYNC 4
#define STRIPE_PREREAD_ACTIVE 5
#define STRIPE_DELAYED 6
+#define STRIPE_DEGRADED 7
+#define STRIPE_BIT_DELAY 8
/*
* Plugging:
@@ -210,10 +212,20 @@ struct raid5_private_data {
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];
kmem_cache_t *slab_cache; /* for allocating stripes */
+
+ int seq_flush, seq_write;
+ int quiesce;
+
+ int fullsync; /* set to 1 if a full sync is needed,
+ * (fresh device added).
+ * Cleared when a sync completes.
+ */
+
/*
* Free stripes pool
*/
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
new file mode 100644
index 000000000000..a71123c28272
--- /dev/null
+++ b/include/linux/raid_class.h
@@ -0,0 +1,59 @@
+/*
+ */
+#include <linux/transport_class.h>
+
+struct raid_template {
+ struct transport_container raid_attrs;
+};
+
+struct raid_function_template {
+ void *cookie;
+ int (*is_raid)(struct device *);
+ void (*get_resync)(struct device *);
+ void (*get_state)(struct device *);
+};
+
+enum raid_state {
+ RAID_ACTIVE = 1,
+ RAID_DEGRADED,
+ RAID_RESYNCING,
+ RAID_OFFLINE,
+};
+
+struct raid_data {
+ struct list_head component_list;
+ int component_count;
+ int level;
+ enum raid_state state;
+ int resync;
+};
+
+#define DEFINE_RAID_ATTRIBUTE(type, attr) \
+static inline void \
+raid_set_##attr(struct raid_template *r, struct device *dev, type value) { \
+ struct class_device *cdev = \
+ attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ struct raid_data *rd; \
+ BUG_ON(!cdev); \
+ rd = class_get_devdata(cdev); \
+ rd->attr = value; \
+} \
+static inline type \
+raid_get_##attr(struct raid_template *r, struct device *dev) { \
+ struct class_device *cdev = \
+ attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ struct raid_data *rd; \
+ BUG_ON(!cdev); \
+ rd = class_get_devdata(cdev); \
+ return rd->attr; \
+}
+
+DEFINE_RAID_ATTRIBUTE(int, level)
+DEFINE_RAID_ATTRIBUTE(int, resync)
+DEFINE_RAID_ATTRIBUTE(enum raid_state, state)
+
+struct raid_template *raid_class_attach(struct raid_function_template *);
+void raid_class_release(struct raid_template *);
+
+void raid_component_add(struct raid_template *, struct device *,
+ struct device *);
diff --git a/include/linux/random.h b/include/linux/random.h
index cc6703449916..7b2adb3322d5 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -59,6 +59,8 @@ extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport);
extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
__u16 sport, __u16 dport);
+extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport);
#ifndef MODULE
extern struct file_operations random_fops, urandom_fops;
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index fd276adf0fd5..4e65eb44adfd 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -52,8 +52,8 @@ struct rcu_head {
void (*func)(struct rcu_head *head);
};
-#define RCU_HEAD_INIT(head) { .next = NULL, .func = NULL }
-#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT(head)
+#define RCU_HEAD_INIT { .next = NULL, .func = NULL }
+#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT
#define INIT_RCU_HEAD(ptr) do { \
(ptr)->next = NULL; (ptr)->func = NULL; \
} while (0)
diff --git a/include/linux/rcuref.h b/include/linux/rcuref.h
new file mode 100644
index 000000000000..e1adbba14b67
--- /dev/null
+++ b/include/linux/rcuref.h
@@ -0,0 +1,220 @@
+/*
+ * rcuref.h
+ *
+ * Reference counting for elements of lists/arrays protected by
+ * RCU.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2005
+ *
+ * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ * Ravikiran Thirumalai <kiran_th@gmail.com>
+ *
+ * See Documentation/RCU/rcuref.txt for detailed user guide.
+ *
+ */
+
+#ifndef _RCUREF_H_
+#define _RCUREF_H_
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+/*
+ * These APIs work on traditional atomic_t counters used in the
+ * kernel for reference counting. Under special circumstances
+ * where a lock-free get() operation races with a put() operation
+ * these APIs can be used. See Documentation/RCU/rcuref.txt.
+ */
+
+#ifdef __HAVE_ARCH_CMPXCHG
+
+/**
+ * rcuref_inc - increment refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline void rcuref_inc(atomic_t *rcuref)
+{
+ atomic_inc(rcuref);
+}
+
+/**
+ * rcuref_dec - decrement refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline void rcuref_dec(atomic_t *rcuref)
+{
+ atomic_dec(rcuref);
+}
+
+/**
+ * rcuref_dec_and_test - decrement refcount for object and test
+ * @rcuref: reference counter in the object.
+ * @release: pointer to the function that will clean up the object
+ * when the last reference to the object is released.
+ * This pointer is required.
+ *
+ * Decrement the refcount, and if 0, return 1. Else return 0.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline int rcuref_dec_and_test(atomic_t *rcuref)
+{
+ return atomic_dec_and_test(rcuref);
+}
+
+/*
+ * cmpxchg is needed on UP too, if deletions to the list/array can happen
+ * in interrupt context.
+ */
+
+/**
+ * rcuref_inc_lf - Take reference to an object in a read-side
+ * critical section protected by RCU.
+ * @rcuref: reference counter in the object in question.
+ *
+ * Try and increment the refcount by 1. The increment might fail if
+ * the reference counter has been through a 1 to 0 transition and
+ * is no longer part of the lock-free list.
+ * Returns non-zero on successful increment and zero otherwise.
+ */
+static inline int rcuref_inc_lf(atomic_t *rcuref)
+{
+ int c, old;
+ c = atomic_read(rcuref);
+ while (c && (old = cmpxchg(&rcuref->counter, c, c + 1)) != c)
+ c = old;
+ return c;
+}
+
+#else /* !__HAVE_ARCH_CMPXCHG */
+
+extern spinlock_t __rcuref_hash[];
+
+/*
+ * Use a hash table of locks to protect the reference count
+ * since cmpxchg is not available in this arch.
+ */
+#ifdef CONFIG_SMP
+#define RCUREF_HASH_SIZE 4
+#define RCUREF_HASH(k) \
+ (&__rcuref_hash[(((unsigned long)k)>>8) & (RCUREF_HASH_SIZE-1)])
+#else
+#define RCUREF_HASH_SIZE 1
+#define RCUREF_HASH(k) &__rcuref_hash[0]
+#endif /* CONFIG_SMP */
+
+/**
+ * rcuref_inc - increment refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline void rcuref_inc(atomic_t *rcuref)
+{
+ unsigned long flags;
+ spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+ rcuref->counter += 1;
+ spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+}
+
+/**
+ * rcuref_dec - decrement refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline void rcuref_dec(atomic_t *rcuref)
+{
+ unsigned long flags;
+ spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+ rcuref->counter -= 1;
+ spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+}
+
+/**
+ * rcuref_dec_and_test - decrement refcount for object and test
+ * @rcuref: reference counter in the object.
+ * @release: pointer to the function that will clean up the object
+ * when the last reference to the object is released.
+ * This pointer is required.
+ *
+ * Decrement the refcount, and if 0, return 1. Else return 0.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline int rcuref_dec_and_test(atomic_t *rcuref)
+{
+ unsigned long flags;
+ spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+ rcuref->counter--;
+ if (!rcuref->counter) {
+ spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+ return 1;
+ } else {
+ spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+ return 0;
+ }
+}
+
+/**
+ * rcuref_inc_lf - Take reference to an object of a lock-free collection
+ * by traversing a lock-free list/array.
+ * @rcuref: reference counter in the object in question.
+ *
+ * Try and increment the refcount by 1. The increment might fail if
+ * the reference counter has been through a 1 to 0 transition and
+ * object is no longer part of the lock-free list.
+ * Returns non-zero on successful increment and zero otherwise.
+ */
+static inline int rcuref_inc_lf(atomic_t *rcuref)
+{
+ int ret;
+ unsigned long flags;
+ spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+ if (rcuref->counter)
+ ret = rcuref->counter++;
+ else
+ ret = 0;
+ spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+ return ret;
+}
+
+
+#endif /* !__HAVE_ARCH_CMPXCHG */
+
+#endif /* __KERNEL__ */
+#endif /* _RCUREF_H_ */
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 17e458e17e2b..af00b10294cd 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2097,7 +2097,7 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *,
b_blocknr_t, int for_unformatted);
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t *, int,
int);
-extern inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
+static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
b_blocknr_t * new_blocknrs,
int amount_needed)
{
@@ -2113,7 +2113,7 @@ extern inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
0);
}
-extern inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
+static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
struct path *path, long block)
@@ -2130,7 +2130,7 @@ extern inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
}
#ifdef REISERFS_PREALLOCATE
-extern inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
+static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
struct path *path, long block)
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
new file mode 100644
index 000000000000..cfafc3e76bc2
--- /dev/null
+++ b/include/linux/relayfs_fs.h
@@ -0,0 +1,255 @@
+/*
+ * 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_buf struct
+ */
+#define RELAYFS_CHANNEL_VERSION 5
+
+/*
+ * 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 */
+ struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
+};
+
+/*
+ * Relayfs inode
+ */
+struct relayfs_inode_info
+{
+ struct inode vfs_inode;
+ struct rchan_buf *buf;
+};
+
+static inline struct relayfs_inode_info *RELAYFS_I(struct inode *inode)
+{
+ return container_of(inode, struct relayfs_inode_info, vfs_inode);
+}
+
+/*
+ * 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);
+};
+
+/*
+ * 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);
+
+/**
+ * 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 relayfs file operations, fs/relayfs/inode.c
+ */
+
+extern struct file_operations relayfs_file_operations;
+
+#endif /* _LINUX_RELAYFS_FS_H */
+
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 657c05ab8f9e..c231e9a08f0b 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -826,9 +826,8 @@ enum
#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
-
-/* RTnetlink multicast groups */
-
+#ifndef __KERNEL__
+/* RTnetlink multicast groups - backwards compatibility for userspace */
#define RTMGRP_LINK 1
#define RTMGRP_NOTIFY 2
#define RTMGRP_NEIGH 4
@@ -847,6 +846,43 @@ enum
#define RTMGRP_DECnet_ROUTE 0x4000
#define RTMGRP_IPV6_PREFIX 0x20000
+#endif
+
+/* RTnetlink multicast groups */
+enum rtnetlink_groups {
+ RTNLGRP_NONE,
+#define RTNLGRP_NONE RTNLGRP_NONE
+ RTNLGRP_LINK,
+#define RTNLGRP_LINK RTNLGRP_LINK
+ RTNLGRP_NOTIFY,
+#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
+ RTNLGRP_NEIGH,
+#define RTNLGRP_NEIGH RTNLGRP_NEIGH
+ RTNLGRP_TC,
+#define RTNLGRP_TC RTNLGRP_TC
+ RTNLGRP_IPV4_IFADDR,
+#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
+ RTNLGRP_IPV4_MROUTE,
+#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE
+ RTNLGRP_IPV4_ROUTE,
+#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE
+ RTNLGRP_IPV6_IFADDR,
+#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR
+ RTNLGRP_IPV6_MROUTE,
+#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE
+ RTNLGRP_IPV6_ROUTE,
+#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE
+ RTNLGRP_IPV6_IFINFO,
+#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO
+ RTNLGRP_DECnet_IFADDR,
+#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR
+ RTNLGRP_DECnet_ROUTE,
+#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE
+ RTNLGRP_IPV6_PREFIX,
+#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX
+ __RTNLGRP_MAX
+};
+#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
/* TC action piece */
struct tcamsg
diff --git a/include/linux/sched.h b/include/linux/sched.h
index dec5827c7742..49e617fa0f66 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -35,6 +35,8 @@
#include <linux/topology.h>
#include <linux/seccomp.h>
+#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
+
struct exec_domain;
/*
@@ -112,12 +114,24 @@ extern unsigned long nr_iowait(void);
#define TASK_TRACED 8
#define EXIT_ZOMBIE 16
#define EXIT_DEAD 32
+#define TASK_NONINTERACTIVE 64
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
#define set_task_state(tsk, state_value) \
set_mb((tsk)->state, (state_value))
+/*
+ * set_current_state() includes a barrier so that the write of current->state
+ * is correctly serialised wrt the caller's subsequent test of whether to
+ * actually sleep:
+ *
+ * set_current_state(TASK_UNINTERRUPTIBLE);
+ * if (do_i_need_to_sleep())
+ * schedule();
+ *
+ * If the caller does not need such serialisation then use __set_current_state()
+ */
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
#define set_current_state(state_value) \
@@ -176,6 +190,23 @@ extern void trap_init(void);
extern void update_process_times(int user);
extern void scheduler_tick(void);
+#ifdef CONFIG_DETECT_SOFTLOCKUP
+extern void softlockup_tick(struct pt_regs *regs);
+extern void spawn_softlockup_task(void);
+extern void touch_softlockup_watchdog(void);
+#else
+static inline void softlockup_tick(struct pt_regs *regs)
+{
+}
+static inline void spawn_softlockup_task(void)
+{
+}
+static inline void touch_softlockup_watchdog(void)
+{
+}
+#endif
+
+
/* Attach to any functions which should be ignored in wchan output. */
#define __sched __attribute__((__section__(".sched.text")))
/* Is this address in the __sched functions? */
@@ -183,6 +214,8 @@ extern int in_sched_functions(unsigned long addr);
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
extern signed long FASTCALL(schedule_timeout(signed long timeout));
+extern signed long schedule_timeout_interruptible(signed long timeout);
+extern signed long schedule_timeout_uninterruptible(signed long timeout);
asmlinkage void schedule(void);
struct namespace;
@@ -244,7 +277,7 @@ struct mm_struct {
mm_counter_t _rss;
mm_counter_t _anon_rss;
- unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
+ unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
unsigned dumpable:2;
cpumask_t cpu_vm_mask;
@@ -545,13 +578,6 @@ struct sched_domain {
extern void partition_sched_domains(cpumask_t *partition1,
cpumask_t *partition2);
-#ifdef ARCH_HAS_SCHED_DOMAIN
-/* Useful helpers that arch setup code may use. Defined in kernel/sched.c */
-extern cpumask_t cpu_isolated_map;
-extern void init_sched_build_groups(struct sched_group groups[],
- cpumask_t span, int (*group_fn)(int cpu));
-extern void cpu_attach_domain(struct sched_domain *sd, int cpu);
-#endif /* ARCH_HAS_SCHED_DOMAIN */
#endif /* CONFIG_SMP */
@@ -592,6 +618,11 @@ extern int groups_search(struct group_info *group_info, gid_t grp);
#define GROUP_AT(gi, i) \
((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
+#ifdef ARCH_HAS_PREFETCH_SWITCH_STACK
+extern void prefetch_stack(struct task_struct*);
+#else
+static inline void prefetch_stack(struct task_struct *t) { }
+#endif
struct audit_context; /* See audit.c */
struct mempolicy;
@@ -883,6 +914,8 @@ extern int task_curr(const task_t *p);
extern int idle_cpu(int cpu);
extern int sched_setscheduler(struct task_struct *, int, struct sched_param *);
extern task_t *idle_task(int cpu);
+extern task_t *curr_task(int cpu);
+extern void set_curr_task(int cpu, task_t *p);
void yield(void);
diff --git a/include/linux/security.h b/include/linux/security.h
index b42095a68b1c..55b02e1c73f4 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -250,29 +250,37 @@ struct swap_info_struct;
* @inode contains the inode structure.
* Deallocate the inode security structure and set @inode->i_security to
* NULL.
+ * @inode_init_security:
+ * Obtain the security attribute name suffix and value to set on a newly
+ * created inode and set up the incore security field for the new inode.
+ * This hook is called by the fs code as part of the inode creation
+ * transaction and provides for atomic labeling of the inode, unlike
+ * the post_create/mkdir/... hooks called by the VFS. The hook function
+ * is expected to allocate the name and value via kmalloc, with the caller
+ * being responsible for calling kfree after using them.
+ * If the security module does not use security attributes or does
+ * not wish to put a security attribute on this particular inode,
+ * then it should return -EOPNOTSUPP to skip this processing.
+ * @inode contains the inode structure of the newly created inode.
+ * @dir contains the inode structure of the parent directory.
+ * @name will be set to the allocated name suffix (e.g. selinux).
+ * @value will be set to the allocated attribute value.
+ * @len will be set to the length of the value.
+ * Returns 0 if @name and @value have been successfully set,
+ * -EOPNOTSUPP if no security attribute is needed, or
+ * -ENOMEM on memory allocation failure.
* @inode_create:
* Check permission to create a regular file.
* @dir contains inode structure of the parent of the new file.
* @dentry contains the dentry structure for the file to be created.
* @mode contains the file mode of the file to be created.
* Return 0 if permission is granted.
- * @inode_post_create:
- * Set the security attributes on a newly created regular file. This hook
- * is called after a file has been successfully created.
- * @dir contains the inode structure of the parent directory of the new file.
- * @dentry contains the the dentry structure for the newly created file.
- * @mode contains the file mode.
* @inode_link:
* Check permission before creating a new hard link to a file.
* @old_dentry contains the dentry structure for an existing link to the file.
* @dir contains the inode structure of the parent directory of the new link.
* @new_dentry contains the dentry structure for the new link.
* Return 0 if permission is granted.
- * @inode_post_link:
- * Set security attributes for a new hard link to a file.
- * @old_dentry contains the dentry structure for the existing link.
- * @dir contains the inode structure of the parent directory of the new file.
- * @new_dentry contains the dentry structure for the new file link.
* @inode_unlink:
* Check the permission to remove a hard link to a file.
* @dir contains the inode structure of parent directory of the file.
@@ -284,13 +292,6 @@ struct swap_info_struct;
* @dentry contains the dentry structure of the symbolic link.
* @old_name contains the pathname of file.
* Return 0 if permission is granted.
- * @inode_post_symlink:
- * @dir contains the inode structure of the parent directory of the new link.
- * @dentry contains the dentry structure of new symbolic link.
- * @old_name contains the pathname of file.
- * Set security attributes for a newly created symbolic link. Note that
- * @dentry->d_inode may be NULL, since the filesystem might not
- * instantiate the dentry (e.g. NFS).
* @inode_mkdir:
* Check permissions to create a new directory in the existing directory
* associated with inode strcture @dir.
@@ -298,11 +299,6 @@ struct swap_info_struct;
* @dentry contains the dentry structure of new directory.
* @mode contains the mode of new directory.
* Return 0 if permission is granted.
- * @inode_post_mkdir:
- * Set security attributes on a newly created directory.
- * @dir contains the inode structure of parent of the directory to be created.
- * @dentry contains the dentry structure of new directory.
- * @mode contains the mode of new directory.
* @inode_rmdir:
* Check the permission to remove a directory.
* @dir contains the inode structure of parent of the directory to be removed.
@@ -318,13 +314,6 @@ struct swap_info_struct;
* @mode contains the mode of the new file.
* @dev contains the the device number.
* Return 0 if permission is granted.
- * @inode_post_mknod:
- * Set security attributes on a newly created special file (or socket or
- * fifo file created via the mknod system call).
- * @dir contains the inode structure of parent of the new node.
- * @dentry contains the dentry structure of the new node.
- * @mode contains the mode of the new node.
- * @dev contains the the device number.
* @inode_rename:
* Check for permission to rename a file or directory.
* @old_dir contains the inode structure for parent of the old link.
@@ -332,12 +321,6 @@ struct swap_info_struct;
* @new_dir contains the inode structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link.
* Return 0 if permission is granted.
- * @inode_post_rename:
- * Set security attributes on a renamed file or directory.
- * @old_dir contains the inode structure for parent of the old link.
- * @old_dentry contains the dentry structure of the old link.
- * @new_dir contains the inode structure for parent of the new link.
- * @new_dentry contains the dentry structure of the new link.
* @inode_readlink:
* Check the permission to read the symbolic link.
* @dentry contains the dentry structure for the file link.
@@ -1080,34 +1063,21 @@ struct security_operations {
int (*inode_alloc_security) (struct inode *inode);
void (*inode_free_security) (struct inode *inode);
+ int (*inode_init_security) (struct inode *inode, struct inode *dir,
+ char **name, void **value, size_t *len);
int (*inode_create) (struct inode *dir,
struct dentry *dentry, int mode);
- void (*inode_post_create) (struct inode *dir,
- struct dentry *dentry, int mode);
int (*inode_link) (struct dentry *old_dentry,
struct inode *dir, struct dentry *new_dentry);
- void (*inode_post_link) (struct dentry *old_dentry,
- struct inode *dir, struct dentry *new_dentry);
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
int (*inode_symlink) (struct inode *dir,
struct dentry *dentry, const char *old_name);
- void (*inode_post_symlink) (struct inode *dir,
- struct dentry *dentry,
- const char *old_name);
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
- void (*inode_post_mkdir) (struct inode *dir, struct dentry *dentry,
- int mode);
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
int mode, dev_t dev);
- void (*inode_post_mknod) (struct inode *dir, struct dentry *dentry,
- int mode, dev_t dev);
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
- void (*inode_post_rename) (struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry);
int (*inode_readlink) (struct dentry *dentry);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
@@ -1442,6 +1412,17 @@ static inline void security_inode_free (struct inode *inode)
return;
security_ops->inode_free_security (inode);
}
+
+static inline int security_inode_init_security (struct inode *inode,
+ struct inode *dir,
+ char **name,
+ void **value,
+ size_t *len)
+{
+ if (unlikely (IS_PRIVATE (inode)))
+ return -EOPNOTSUPP;
+ return security_ops->inode_init_security (inode, dir, name, value, len);
+}
static inline int security_inode_create (struct inode *dir,
struct dentry *dentry,
@@ -1452,15 +1433,6 @@ static inline int security_inode_create (struct inode *dir,
return security_ops->inode_create (dir, dentry, mode);
}
-static inline void security_inode_post_create (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{
- if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
- return;
- security_ops->inode_post_create (dir, dentry, mode);
-}
-
static inline int security_inode_link (struct dentry *old_dentry,
struct inode *dir,
struct dentry *new_dentry)
@@ -1470,15 +1442,6 @@ static inline int security_inode_link (struct dentry *old_dentry,
return security_ops->inode_link (old_dentry, dir, new_dentry);
}
-static inline void security_inode_post_link (struct dentry *old_dentry,
- struct inode *dir,
- struct dentry *new_dentry)
-{
- if (new_dentry->d_inode && unlikely (IS_PRIVATE (new_dentry->d_inode)))
- return;
- security_ops->inode_post_link (old_dentry, dir, new_dentry);
-}
-
static inline int security_inode_unlink (struct inode *dir,
struct dentry *dentry)
{
@@ -1496,15 +1459,6 @@ static inline int security_inode_symlink (struct inode *dir,
return security_ops->inode_symlink (dir, dentry, old_name);
}
-static inline void security_inode_post_symlink (struct inode *dir,
- struct dentry *dentry,
- const char *old_name)
-{
- if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
- return;
- security_ops->inode_post_symlink (dir, dentry, old_name);
-}
-
static inline int security_inode_mkdir (struct inode *dir,
struct dentry *dentry,
int mode)
@@ -1514,15 +1468,6 @@ static inline int security_inode_mkdir (struct inode *dir,
return security_ops->inode_mkdir (dir, dentry, mode);
}
-static inline void security_inode_post_mkdir (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{
- if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
- return;
- security_ops->inode_post_mkdir (dir, dentry, mode);
-}
-
static inline int security_inode_rmdir (struct inode *dir,
struct dentry *dentry)
{
@@ -1540,15 +1485,6 @@ static inline int security_inode_mknod (struct inode *dir,
return security_ops->inode_mknod (dir, dentry, mode, dev);
}
-static inline void security_inode_post_mknod (struct inode *dir,
- struct dentry *dentry,
- int mode, dev_t dev)
-{
- if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
- return;
- security_ops->inode_post_mknod (dir, dentry, mode, dev);
-}
-
static inline int security_inode_rename (struct inode *old_dir,
struct dentry *old_dentry,
struct inode *new_dir,
@@ -1561,18 +1497,6 @@ static inline int security_inode_rename (struct inode *old_dir,
new_dir, new_dentry);
}
-static inline void security_inode_post_rename (struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry)
-{
- if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
- (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
- return;
- security_ops->inode_post_rename (old_dir, old_dentry,
- new_dir, new_dentry);
-}
-
static inline int security_inode_readlink (struct dentry *dentry)
{
if (unlikely (IS_PRIVATE (dentry->d_inode)))
@@ -2171,6 +2095,15 @@ static inline int security_inode_alloc (struct inode *inode)
static inline void security_inode_free (struct inode *inode)
{ }
+
+static inline int security_inode_init_security (struct inode *inode,
+ struct inode *dir,
+ char **name,
+ void **value,
+ size_t *len)
+{
+ return -EOPNOTSUPP;
+}
static inline int security_inode_create (struct inode *dir,
struct dentry *dentry,
@@ -2179,11 +2112,6 @@ static inline int security_inode_create (struct inode *dir,
return 0;
}
-static inline void security_inode_post_create (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{ }
-
static inline int security_inode_link (struct dentry *old_dentry,
struct inode *dir,
struct dentry *new_dentry)
@@ -2191,11 +2119,6 @@ static inline int security_inode_link (struct dentry *old_dentry,
return 0;
}
-static inline void security_inode_post_link (struct dentry *old_dentry,
- struct inode *dir,
- struct dentry *new_dentry)
-{ }
-
static inline int security_inode_unlink (struct inode *dir,
struct dentry *dentry)
{
@@ -2209,11 +2132,6 @@ static inline int security_inode_symlink (struct inode *dir,
return 0;
}
-static inline void security_inode_post_symlink (struct inode *dir,
- struct dentry *dentry,
- const char *old_name)
-{ }
-
static inline int security_inode_mkdir (struct inode *dir,
struct dentry *dentry,
int mode)
@@ -2221,11 +2139,6 @@ static inline int security_inode_mkdir (struct inode *dir,
return 0;
}
-static inline void security_inode_post_mkdir (struct inode *dir,
- struct dentry *dentry,
- int mode)
-{ }
-
static inline int security_inode_rmdir (struct inode *dir,
struct dentry *dentry)
{
@@ -2239,11 +2152,6 @@ static inline int security_inode_mknod (struct inode *dir,
return 0;
}
-static inline void security_inode_post_mknod (struct inode *dir,
- struct dentry *dentry,
- int mode, dev_t dev)
-{ }
-
static inline int security_inode_rename (struct inode *old_dir,
struct dentry *old_dentry,
struct inode *new_dir,
@@ -2252,12 +2160,6 @@ static inline int security_inode_rename (struct inode *old_dir,
return 0;
}
-static inline void security_inode_post_rename (struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry)
-{ }
-
static inline int security_inode_readlink (struct dentry *dentry)
{
return 0;
@@ -2727,7 +2629,8 @@ static inline int security_socket_getpeersec(struct socket *sock, char __user *o
return security_ops->socket_getpeersec(sock, optval, optlen, len);
}
-static inline int security_sk_alloc(struct sock *sk, int family, int priority)
+static inline int security_sk_alloc(struct sock *sk, int family,
+ unsigned int __nocast priority)
{
return security_ops->sk_alloc_security(sk, family, priority);
}
@@ -2844,7 +2747,8 @@ static inline int security_socket_getpeersec(struct socket *sock, char __user *o
return -ENOPROTOOPT;
}
-static inline int security_sk_alloc(struct sock *sk, int family, int priority)
+static inline int security_sk_alloc(struct sock *sk, int family,
+ unsigned int __nocast priority)
{
return 0;
}
diff --git a/include/linux/selinux_netlink.h b/include/linux/selinux_netlink.h
index 957e6ebca4e6..bbf489decd84 100644
--- a/include/linux/selinux_netlink.h
+++ b/include/linux/selinux_netlink.h
@@ -20,10 +20,21 @@ enum {
SELNL_MSG_MAX
};
-/* Multicast groups */
+#ifndef __KERNEL__
+/* Multicast groups - backwards compatiblility for userspace */
#define SELNL_GRP_NONE 0x00000000
#define SELNL_GRP_AVC 0x00000001 /* AVC notifications */
#define SELNL_GRP_ALL 0xffffffff
+#endif
+
+enum selinux_nlgroups {
+ SELNLGRP_NONE,
+#define SELNLGRP_NONE SELNLGRP_NONE
+ SELNLGRP_AVC,
+#define SELNLGRP_AVC SELNLGRP_AVC
+ __SELNLGRP_MAX
+};
+#define SELNLGRP_MAX (__SELNLGRP_MAX - 1)
/* Message structures */
struct selnl_msg_setenforce {
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 2d8516be9fd7..106f9757339a 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -88,6 +88,7 @@ struct sem {
/* One sem_array data structure for each set of semaphores in the system. */
struct sem_array {
struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
+ int sem_id;
time_t sem_otime; /* last semop time */
time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 9f2d85284d0b..12cd9cf65e8f 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -176,10 +176,6 @@ struct serial_icounter_struct {
#ifdef __KERNEL__
#include <linux/compiler.h>
-/* Export to allow PCMCIA to use this - Dave Hinds */
-extern int __deprecated register_serial(struct serial_struct *req);
-extern void __deprecated unregister_serial(int line);
-
/* Allow architectures to override entries in serial8250_ports[] at run time: */
struct uart_port; /* forward declaration */
extern int early_serial_setup(struct uart_port *port);
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index 2b2f35a64d75..2b9e6b9554d5 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -140,44 +140,4 @@ struct rs_multiport_struct {
#define ALPHA_KLUDGE_MCR 0
#endif
-/*
- * Definitions for PCI support.
- */
-#define SPCI_FL_BASE_MASK 0x0007
-#define SPCI_FL_BASE0 0x0000
-#define SPCI_FL_BASE1 0x0001
-#define SPCI_FL_BASE2 0x0002
-#define SPCI_FL_BASE3 0x0003
-#define SPCI_FL_BASE4 0x0004
-#define SPCI_FL_GET_BASE(x) (x & SPCI_FL_BASE_MASK)
-
-#define SPCI_FL_IRQ_MASK (0x0007 << 4)
-#define SPCI_FL_IRQBASE0 (0x0000 << 4)
-#define SPCI_FL_IRQBASE1 (0x0001 << 4)
-#define SPCI_FL_IRQBASE2 (0x0002 << 4)
-#define SPCI_FL_IRQBASE3 (0x0003 << 4)
-#define SPCI_FL_IRQBASE4 (0x0004 << 4)
-#define SPCI_FL_GET_IRQBASE(x) ((x & SPCI_FL_IRQ_MASK) >> 4)
-
-/* Use successive BARs (PCI base address registers),
- else use offset into some specified BAR */
-#define SPCI_FL_BASE_TABLE 0x0100
-
-/* Use successive entries in the irq resource table */
-#define SPCI_FL_IRQ_TABLE 0x0200
-
-/* Use the irq resource table instead of dev->irq */
-#define SPCI_FL_IRQRESOURCE 0x0400
-
-/* Use the Base address register size to cap number of ports */
-#define SPCI_FL_REGION_SZ_CAP 0x0800
-
-/* Do not use irq sharing for this device */
-#define SPCI_FL_NO_SHIRQ 0x1000
-
-/* This is a PNP device */
-#define SPCI_FL_ISPNP 0x2000
-
-#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP)
-
#endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 3e3c1fa35b06..317a979b24de 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -14,6 +14,9 @@
#include <linux/serial_core.h>
#include <linux/device.h>
+/*
+ * This is the platform device platform_data structure
+ */
struct plat_serial8250_port {
unsigned long iobase; /* io base address */
void __iomem *membase; /* ioremap cookie or NULL */
@@ -26,4 +29,32 @@ struct plat_serial8250_port {
unsigned int flags; /* UPF_* flags */
};
+/*
+ * Allocate 8250 platform device IDs. Nothing is implied by
+ * the numbering here, except for the legacy entry being -1.
+ */
+enum {
+ PLAT8250_DEV_LEGACY = -1,
+ PLAT8250_DEV_PLATFORM,
+ PLAT8250_DEV_PLATFORM1,
+ PLAT8250_DEV_FOURPORT,
+ PLAT8250_DEV_ACCENT,
+ PLAT8250_DEV_BOCA,
+ PLAT8250_DEV_HUB6,
+ PLAT8250_DEV_MCA,
+};
+
+/*
+ * This should be used by drivers which want to register
+ * their own 8250 ports without registering their own
+ * platform device. Using these will make your driver
+ * dependent on the 8250 driver.
+ */
+struct uart_port;
+
+int serial8250_register_port(struct uart_port *);
+void serial8250_unregister_port(int line);
+void serial8250_suspend_port(int line);
+void serial8250_resume_port(int line);
+
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index f6fca8f2f3ca..27db8da43aa4 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -142,8 +142,8 @@ struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct uart_port *);
- void (*stop_tx)(struct uart_port *, unsigned int tty_stop);
- void (*start_tx)(struct uart_port *, unsigned int tty_start);
+ void (*stop_tx)(struct uart_port *);
+ void (*start_tx)(struct uart_port *);
void (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
@@ -360,8 +360,6 @@ struct tty_driver *uart_console_device(struct console *co, int *index);
*/
int uart_register_driver(struct uart_driver *uart);
void uart_unregister_driver(struct uart_driver *uart);
-void __deprecated uart_unregister_port(struct uart_driver *reg, int line);
-int __deprecated uart_register_port(struct uart_driver *reg, struct uart_port *port);
int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_match_port(struct uart_port *port1, struct uart_port *port2);
@@ -387,11 +385,11 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port);
/*
* The following are helper functions for the low level drivers.
*/
-#ifdef SUPPORT_SYSRQ
static inline int
uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
struct pt_regs *regs)
{
+#ifdef SUPPORT_SYSRQ
if (port->sysrq) {
if (ch && time_before(jiffies, port->sysrq)) {
handle_sysrq(ch, regs, NULL);
@@ -400,10 +398,11 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
}
port->sysrq = 0;
}
+#endif
return 0;
}
-#else
-#define uart_handle_sysrq_char(port,ch,regs) (0)
+#ifndef SUPPORT_SYSRQ
+#define uart_handle_sysrq_char(port,ch,regs) uart_handle_sysrq_char(port, 0, NULL)
#endif
/*
@@ -468,13 +467,13 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status)
if (tty->hw_stopped) {
if (status) {
tty->hw_stopped = 0;
- port->ops->start_tx(port, 0);
+ port->ops->start_tx(port);
uart_write_wakeup(port);
}
} else {
if (!status) {
tty->hw_stopped = 1;
- port->ops->stop_tx(port, 0);
+ port->ops->stop_tx(port);
}
}
}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 948527e42a60..2741c0c55e83 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -155,16 +155,29 @@ struct skb_shared_info {
#define SKB_DATAREF_SHIFT 16
#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
+extern struct timeval skb_tv_base;
+
+struct skb_timeval {
+ u32 off_sec;
+ u32 off_usec;
+};
+
+
+enum {
+ SKB_FCLONE_UNAVAILABLE,
+ SKB_FCLONE_ORIG,
+ SKB_FCLONE_CLONE,
+};
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
* @prev: Previous buffer in list
* @list: List we are on
* @sk: Socket we are owned by
- * @stamp: Time we arrived
+ * @tstamp: Time we arrived stored as offset to skb_tv_base
* @dev: Device we arrived on/are leaving by
* @input_dev: Device we arrived on
- * @real_dev: The real device we are using
* @h: Transport layer header
* @nh: Network layer header
* @mac: Link layer header
@@ -190,14 +203,11 @@ struct skb_shared_info {
* @end: End pointer
* @destructor: Destruct function
* @nfmark: Can be used for communication between hooks
- * @nfcache: Cache info
* @nfct: Associated connection, if any
* @nfctinfo: Relationship of this skb to the connection
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
- * @private: Data which is private to the HIPPI implementation
* @tc_index: Traffic control index
* @tc_verd: traffic control verdict
- * @tc_classid: traffic control classid
*/
struct sk_buff {
@@ -205,12 +215,10 @@ struct sk_buff {
struct sk_buff *next;
struct sk_buff *prev;
- struct sk_buff_head *list;
struct sock *sk;
- struct timeval stamp;
+ struct skb_timeval tstamp;
struct net_device *dev;
struct net_device *input_dev;
- struct net_device *real_dev;
union {
struct tcphdr *th;
@@ -252,33 +260,28 @@ struct sk_buff {
__u8 local_df:1,
cloned:1,
ip_summed:2,
- nohdr:1;
- /* 3 bits spare */
- __u8 pkt_type;
+ nohdr:1,
+ nfctinfo:3;
+ __u8 pkt_type:3,
+ fclone:2;
__be16 protocol;
void (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
- unsigned long nfmark;
- __u32 nfcache;
- __u32 nfctinfo;
+ __u32 nfmark;
struct nf_conntrack *nfct;
+#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
+ __u8 ipvs_property:1;
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
-#if defined(CONFIG_HIPPI)
- union {
- __u32 ifield;
- } private;
-#endif
#ifdef CONFIG_NET_SCHED
- __u32 tc_index; /* traffic control index */
+ __u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
- __u32 tc_verd; /* traffic control verdict */
- __u32 tc_classid; /* traffic control classid */
+ __u16 tc_verd; /* traffic control verdict */
#endif
-
#endif
@@ -300,8 +303,20 @@ struct sk_buff {
#include <asm/system.h>
extern void __kfree_skb(struct sk_buff *skb);
-extern struct sk_buff *alloc_skb(unsigned int size,
- unsigned int __nocast priority);
+extern struct sk_buff *__alloc_skb(unsigned int size,
+ unsigned int __nocast priority, int fclone);
+static inline struct sk_buff *alloc_skb(unsigned int size,
+ unsigned int __nocast priority)
+{
+ return __alloc_skb(size, priority, 0);
+}
+
+static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
+ unsigned int __nocast priority)
+{
+ return __alloc_skb(size, priority, 1);
+}
+
extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
unsigned int size,
unsigned int __nocast priority);
@@ -597,7 +612,6 @@ static inline void __skb_queue_head(struct sk_buff_head *list,
{
struct sk_buff *prev, *next;
- newsk->list = list;
list->qlen++;
prev = (struct sk_buff *)list;
next = prev->next;
@@ -622,7 +636,6 @@ static inline void __skb_queue_tail(struct sk_buff_head *list,
{
struct sk_buff *prev, *next;
- newsk->list = list;
list->qlen++;
next = (struct sk_buff *)list;
prev = next->prev;
@@ -655,7 +668,6 @@ static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
next->prev = prev;
prev->next = next;
result->next = result->prev = NULL;
- result->list = NULL;
}
return result;
}
@@ -664,7 +676,7 @@ static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
/*
* Insert a packet on a list.
*/
-extern void skb_insert(struct sk_buff *old, struct sk_buff *newsk);
+extern void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
static inline void __skb_insert(struct sk_buff *newsk,
struct sk_buff *prev, struct sk_buff *next,
struct sk_buff_head *list)
@@ -672,24 +684,23 @@ static inline void __skb_insert(struct sk_buff *newsk,
newsk->next = next;
newsk->prev = prev;
next->prev = prev->next = newsk;
- newsk->list = list;
list->qlen++;
}
/*
* Place a packet after a given packet in a list.
*/
-extern void skb_append(struct sk_buff *old, struct sk_buff *newsk);
-static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
+extern void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
{
- __skb_insert(newsk, old, old->next, old->list);
+ __skb_insert(newsk, old, old->next, list);
}
/*
* remove sk_buff from list. _Must_ be called atomically, and with
* the list known..
*/
-extern void skb_unlink(struct sk_buff *skb);
+extern void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list);
static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
struct sk_buff *next, *prev;
@@ -698,7 +709,6 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
next = skb->next;
prev = skb->prev;
skb->next = skb->prev = NULL;
- skb->list = NULL;
next->prev = prev;
prev->next = next;
}
@@ -1157,7 +1167,7 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
{
- if (len >= skb->len)
+ if (likely(len >= skb->len))
return 0;
if (skb->ip_summed == CHECKSUM_HW)
skb->ip_summed = CHECKSUM_NONE;
@@ -1213,6 +1223,8 @@ extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
extern void skb_split(struct sk_buff *skb,
struct sk_buff *skb1, const u32 len);
+extern void skb_release_data(struct sk_buff *skb);
+
static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
int len, void *buffer)
{
@@ -1230,6 +1242,42 @@ static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
extern void skb_init(void);
extern void skb_add_mtu(int mtu);
+/**
+ * skb_get_timestamp - get timestamp from a skb
+ * @skb: skb to get stamp from
+ * @stamp: pointer to struct timeval to store stamp in
+ *
+ * Timestamps are stored in the skb as offsets to a base timestamp.
+ * This function converts the offset back to a struct timeval and stores
+ * it in stamp.
+ */
+static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp)
+{
+ stamp->tv_sec = skb->tstamp.off_sec;
+ stamp->tv_usec = skb->tstamp.off_usec;
+ if (skb->tstamp.off_sec) {
+ stamp->tv_sec += skb_tv_base.tv_sec;
+ stamp->tv_usec += skb_tv_base.tv_usec;
+ }
+}
+
+/**
+ * skb_set_timestamp - set timestamp of a skb
+ * @skb: skb to set stamp of
+ * @stamp: pointer to struct timeval to get stamp from
+ *
+ * Timestamps are stored in the skb as offsets to a base timestamp.
+ * This function converts a struct timeval to an offset and stores
+ * it in the skb.
+ */
+static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
+{
+ skb->tstamp.off_sec = stamp->tv_sec - skb_tv_base.tv_sec;
+ skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec;
+}
+
+extern void __net_timestamp(struct sk_buff *skb);
+
#ifdef CONFIG_NETFILTER
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
{
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 80b2dfde2e80..1f356f3bbc64 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -99,12 +99,27 @@ found:
return __kmalloc(size, flags);
}
-extern void *kcalloc(size_t, size_t, unsigned int __nocast);
+extern void *kzalloc(size_t, unsigned int __nocast);
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+static inline void *kcalloc(size_t n, size_t size, unsigned int __nocast flags)
+{
+ if (n != 0 && size > INT_MAX / n)
+ return NULL;
+ return kzalloc(n * size, flags);
+}
+
extern void kfree(const void *);
extern unsigned int ksize(const void *);
#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node);
+extern void *kmem_cache_alloc_node(kmem_cache_t *,
+ unsigned int __nocast flags, int node);
extern void *kmalloc_node(size_t size, unsigned int __nocast flags, int node);
#else
static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index a5c7d96e4d2e..1739c2d5b95b 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -26,6 +26,13 @@ struct __kernel_sockaddr_storage {
#include <linux/types.h> /* pid_t */
#include <linux/compiler.h> /* __user */
+extern int sysctl_somaxconn;
+extern void sock_init(void);
+#ifdef CONFIG_PROC_FS
+struct seq_file;
+extern void socket_seq_show(struct seq_file *seq);
+#endif
+
typedef unsigned short sa_family_t;
/*
@@ -271,6 +278,8 @@ struct ucred {
#define SOL_IRDA 266
#define SOL_NETBEUI 267
#define SOL_LLC 268
+#define SOL_DCCP 269
+#define SOL_NETLINK 270
/* IPX options */
#define IPX_TYPE 1
diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h
index 768cbba617d0..f56d24734950 100644
--- a/include/linux/sonypi.h
+++ b/include/linux/sonypi.h
@@ -99,6 +99,8 @@
#define SONYPI_EVENT_BATTERY_INSERT 57
#define SONYPI_EVENT_BATTERY_REMOVE 58
#define SONYPI_EVENT_FNKEY_RELEASED 59
+#define SONYPI_EVENT_WIRELESS_ON 60
+#define SONYPI_EVENT_WIRELESS_OFF 61
/* get/set brightness */
#define SONYPI_IOCGBRT _IOR('v', 0, __u8)
diff --git a/include/linux/sound.h b/include/linux/sound.h
index 428f59794f48..72b9af4c3fd4 100644
--- a/include/linux/sound.h
+++ b/include/linux/sound.h
@@ -29,7 +29,9 @@
* Sound core interface functions
*/
+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);
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index d6ba068719b6..cdc99a27840d 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -2,7 +2,48 @@
#define __LINUX_SPINLOCK_H
/*
- * include/linux/spinlock.h - generic locking declarations
+ * include/linux/spinlock.h - generic spinlock/rwlock declarations
+ *
+ * here's the role of the various spinlock/rwlock related include files:
+ *
+ * on SMP builds:
+ *
+ * asm/spinlock_types.h: contains the raw_spinlock_t/raw_rwlock_t and the
+ * initializers
+ *
+ * linux/spinlock_types.h:
+ * defines the generic type and initializers
+ *
+ * asm/spinlock.h: contains the __raw_spin_*()/etc. lowlevel
+ * implementations, mostly inline assembly code
+ *
+ * (also included on UP-debug builds:)
+ *
+ * linux/spinlock_api_smp.h:
+ * contains the prototypes for the _spin_*() APIs.
+ *
+ * linux/spinlock.h: builds the final spin_*() APIs.
+ *
+ * on UP builds:
+ *
+ * linux/spinlock_type_up.h:
+ * contains the generic, simplified UP spinlock type.
+ * (which is an empty structure on non-debug builds)
+ *
+ * linux/spinlock_types.h:
+ * defines the generic type and initializers
+ *
+ * linux/spinlock_up.h:
+ * contains the __raw_spin_*()/etc. version of UP
+ * builds. (which are NOPs on non-debug, non-preempt
+ * builds)
+ *
+ * (included on UP-non-debug builds:)
+ *
+ * linux/spinlock_api_up.h:
+ * builds the _spin_*() APIs.
+ *
+ * linux/spinlock.h: builds the final spin_*() APIs.
*/
#include <linux/config.h>
@@ -13,7 +54,6 @@
#include <linux/kernel.h>
#include <linux/stringify.h>
-#include <asm/processor.h> /* for cpu relax */
#include <asm/system.h>
/*
@@ -35,423 +75,84 @@
#define __lockfunc fastcall __attribute__((section(".spinlock.text")))
/*
- * If CONFIG_SMP is set, pull in the _raw_* definitions
+ * Pull the raw_spinlock_t and raw_rwlock_t definitions:
*/
-#ifdef CONFIG_SMP
-
-#define assert_spin_locked(x) BUG_ON(!spin_is_locked(x))
-#include <asm/spinlock.h>
-
-int __lockfunc _spin_trylock(spinlock_t *lock);
-int __lockfunc _read_trylock(rwlock_t *lock);
-int __lockfunc _write_trylock(rwlock_t *lock);
-
-void __lockfunc _spin_lock(spinlock_t *lock) __acquires(spinlock_t);
-void __lockfunc _read_lock(rwlock_t *lock) __acquires(rwlock_t);
-void __lockfunc _write_lock(rwlock_t *lock) __acquires(rwlock_t);
-
-void __lockfunc _spin_unlock(spinlock_t *lock) __releases(spinlock_t);
-void __lockfunc _read_unlock(rwlock_t *lock) __releases(rwlock_t);
-void __lockfunc _write_unlock(rwlock_t *lock) __releases(rwlock_t);
-
-unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) __acquires(spinlock_t);
-unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) __acquires(rwlock_t);
-unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) __acquires(rwlock_t);
-
-void __lockfunc _spin_lock_irq(spinlock_t *lock) __acquires(spinlock_t);
-void __lockfunc _spin_lock_bh(spinlock_t *lock) __acquires(spinlock_t);
-void __lockfunc _read_lock_irq(rwlock_t *lock) __acquires(rwlock_t);
-void __lockfunc _read_lock_bh(rwlock_t *lock) __acquires(rwlock_t);
-void __lockfunc _write_lock_irq(rwlock_t *lock) __acquires(rwlock_t);
-void __lockfunc _write_lock_bh(rwlock_t *lock) __acquires(rwlock_t);
-
-void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) __releases(spinlock_t);
-void __lockfunc _spin_unlock_irq(spinlock_t *lock) __releases(spinlock_t);
-void __lockfunc _spin_unlock_bh(spinlock_t *lock) __releases(spinlock_t);
-void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) __releases(rwlock_t);
-void __lockfunc _read_unlock_irq(rwlock_t *lock) __releases(rwlock_t);
-void __lockfunc _read_unlock_bh(rwlock_t *lock) __releases(rwlock_t);
-void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) __releases(rwlock_t);
-void __lockfunc _write_unlock_irq(rwlock_t *lock) __releases(rwlock_t);
-void __lockfunc _write_unlock_bh(rwlock_t *lock) __releases(rwlock_t);
-
-int __lockfunc _spin_trylock_bh(spinlock_t *lock);
-int __lockfunc generic_raw_read_trylock(rwlock_t *lock);
-int in_lock_functions(unsigned long addr);
-
-#else
+#include <linux/spinlock_types.h>
-#define in_lock_functions(ADDR) 0
+extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock);
-#if !defined(CONFIG_PREEMPT) && !defined(CONFIG_DEBUG_SPINLOCK)
-# define _atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
-# define ATOMIC_DEC_AND_LOCK
-#endif
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-
-#define SPINLOCK_MAGIC 0x1D244B3C
-typedef struct {
- unsigned long magic;
- volatile unsigned long lock;
- volatile unsigned int babble;
- const char *module;
- char *owner;
- int oline;
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { SPINLOCK_MAGIC, 0, 10, __FILE__ , NULL, 0}
-
-#define spin_lock_init(x) \
- do { \
- (x)->magic = SPINLOCK_MAGIC; \
- (x)->lock = 0; \
- (x)->babble = 5; \
- (x)->module = __FILE__; \
- (x)->owner = NULL; \
- (x)->oline = 0; \
- } while (0)
-
-#define CHECK_LOCK(x) \
- do { \
- if ((x)->magic != SPINLOCK_MAGIC) { \
- printk(KERN_ERR "%s:%d: spin_is_locked on uninitialized spinlock %p.\n", \
- __FILE__, __LINE__, (x)); \
- } \
- } while(0)
-
-#define _raw_spin_lock(x) \
- do { \
- CHECK_LOCK(x); \
- if ((x)->lock&&(x)->babble) { \
- (x)->babble--; \
- printk("%s:%d: spin_lock(%s:%p) already locked by %s/%d\n", \
- __FILE__,__LINE__, (x)->module, \
- (x), (x)->owner, (x)->oline); \
- } \
- (x)->lock = 1; \
- (x)->owner = __FILE__; \
- (x)->oline = __LINE__; \
- } while (0)
-
-/* without debugging, spin_is_locked on UP always says
- * FALSE. --> printk if already locked. */
-#define spin_is_locked(x) \
- ({ \
- CHECK_LOCK(x); \
- if ((x)->lock&&(x)->babble) { \
- (x)->babble--; \
- printk("%s:%d: spin_is_locked(%s:%p) already locked by %s/%d\n", \
- __FILE__,__LINE__, (x)->module, \
- (x), (x)->owner, (x)->oline); \
- } \
- 0; \
- })
-
-/* with debugging, assert_spin_locked() on UP does check
- * the lock value properly */
-#define assert_spin_locked(x) \
- ({ \
- CHECK_LOCK(x); \
- BUG_ON(!(x)->lock); \
- })
-
-/* without debugging, spin_trylock on UP always says
- * TRUE. --> printk if already locked. */
-#define _raw_spin_trylock(x) \
- ({ \
- CHECK_LOCK(x); \
- if ((x)->lock&&(x)->babble) { \
- (x)->babble--; \
- printk("%s:%d: spin_trylock(%s:%p) already locked by %s/%d\n", \
- __FILE__,__LINE__, (x)->module, \
- (x), (x)->owner, (x)->oline); \
- } \
- (x)->lock = 1; \
- (x)->owner = __FILE__; \
- (x)->oline = __LINE__; \
- 1; \
- })
-
-#define spin_unlock_wait(x) \
- do { \
- CHECK_LOCK(x); \
- if ((x)->lock&&(x)->babble) { \
- (x)->babble--; \
- printk("%s:%d: spin_unlock_wait(%s:%p) owned by %s/%d\n", \
- __FILE__,__LINE__, (x)->module, (x), \
- (x)->owner, (x)->oline); \
- }\
- } while (0)
-
-#define _raw_spin_unlock(x) \
- do { \
- CHECK_LOCK(x); \
- if (!(x)->lock&&(x)->babble) { \
- (x)->babble--; \
- printk("%s:%d: spin_unlock(%s:%p) not locked\n", \
- __FILE__,__LINE__, (x)->module, (x));\
- } \
- (x)->lock = 0; \
- } while (0)
-#else
/*
- * gcc versions before ~2.95 have a nasty bug with empty initializers.
+ * Pull the __raw*() functions/declarations (UP-nondebug doesnt need them):
*/
-#if (__GNUC__ > 2)
- typedef struct { } spinlock_t;
- #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#if defined(CONFIG_SMP)
+# include <asm/spinlock.h>
#else
- typedef struct { int gcc_is_buggy; } spinlock_t;
- #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+# include <linux/spinlock_up.h>
#endif
+#define spin_lock_init(lock) do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0)
+#define rwlock_init(lock) do { *(lock) = RW_LOCK_UNLOCKED; } while (0)
+
+#define spin_is_locked(lock) __raw_spin_is_locked(&(lock)->raw_lock)
+
+/**
+ * spin_unlock_wait - wait until the spinlock gets unlocked
+ * @lock: the spinlock in question.
+ */
+#define spin_unlock_wait(lock) __raw_spin_unlock_wait(&(lock)->raw_lock)
+
/*
- * If CONFIG_SMP is unset, declare the _raw_* definitions as nops
+ * Pull the _spin_*()/_read_*()/_write_*() functions/declarations:
*/
-#define spin_lock_init(lock) do { (void)(lock); } while(0)
-#define _raw_spin_lock(lock) do { (void)(lock); } while(0)
-#define spin_is_locked(lock) ((void)(lock), 0)
-#define assert_spin_locked(lock) do { (void)(lock); } while(0)
-#define _raw_spin_trylock(lock) (((void)(lock), 1))
-#define spin_unlock_wait(lock) (void)(lock)
-#define _raw_spin_unlock(lock) do { (void)(lock); } while(0)
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-/* RW spinlocks: No debug version */
-
-#if (__GNUC__ > 2)
- typedef struct { } rwlock_t;
- #define RW_LOCK_UNLOCKED (rwlock_t) { }
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+# include <linux/spinlock_api_smp.h>
#else
- typedef struct { int gcc_is_buggy; } rwlock_t;
- #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+# include <linux/spinlock_api_up.h>
#endif
-#define rwlock_init(lock) do { (void)(lock); } while(0)
-#define _raw_read_lock(lock) do { (void)(lock); } while(0)
-#define _raw_read_unlock(lock) do { (void)(lock); } while(0)
-#define _raw_write_lock(lock) do { (void)(lock); } while(0)
-#define _raw_write_unlock(lock) do { (void)(lock); } while(0)
-#define read_can_lock(lock) (((void)(lock), 1))
-#define write_can_lock(lock) (((void)(lock), 1))
-#define _raw_read_trylock(lock) ({ (void)(lock); (1); })
-#define _raw_write_trylock(lock) ({ (void)(lock); (1); })
-
-#define _spin_trylock(lock) ({preempt_disable(); _raw_spin_trylock(lock) ? \
- 1 : ({preempt_enable(); 0;});})
-
-#define _read_trylock(lock) ({preempt_disable();_raw_read_trylock(lock) ? \
- 1 : ({preempt_enable(); 0;});})
-
-#define _write_trylock(lock) ({preempt_disable(); _raw_write_trylock(lock) ? \
- 1 : ({preempt_enable(); 0;});})
-
-#define _spin_trylock_bh(lock) ({preempt_disable(); local_bh_disable(); \
- _raw_spin_trylock(lock) ? \
- 1 : ({preempt_enable_no_resched(); local_bh_enable(); 0;});})
-
-#define _spin_lock(lock) \
-do { \
- preempt_disable(); \
- _raw_spin_lock(lock); \
- __acquire(lock); \
-} while(0)
-
-#define _write_lock(lock) \
-do { \
- preempt_disable(); \
- _raw_write_lock(lock); \
- __acquire(lock); \
-} while(0)
-
-#define _read_lock(lock) \
-do { \
- preempt_disable(); \
- _raw_read_lock(lock); \
- __acquire(lock); \
-} while(0)
-
-#define _spin_unlock(lock) \
-do { \
- _raw_spin_unlock(lock); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _write_unlock(lock) \
-do { \
- _raw_write_unlock(lock); \
- preempt_enable(); \
- __release(lock); \
-} while(0)
-
-#define _read_unlock(lock) \
-do { \
- _raw_read_unlock(lock); \
- preempt_enable(); \
- __release(lock); \
-} while(0)
-
-#define _spin_lock_irqsave(lock, flags) \
-do { \
- local_irq_save(flags); \
- preempt_disable(); \
- _raw_spin_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _spin_lock_irq(lock) \
-do { \
- local_irq_disable(); \
- preempt_disable(); \
- _raw_spin_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _spin_lock_bh(lock) \
-do { \
- local_bh_disable(); \
- preempt_disable(); \
- _raw_spin_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _read_lock_irqsave(lock, flags) \
-do { \
- local_irq_save(flags); \
- preempt_disable(); \
- _raw_read_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _read_lock_irq(lock) \
-do { \
- local_irq_disable(); \
- preempt_disable(); \
- _raw_read_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _read_lock_bh(lock) \
-do { \
- local_bh_disable(); \
- preempt_disable(); \
- _raw_read_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _write_lock_irqsave(lock, flags) \
-do { \
- local_irq_save(flags); \
- preempt_disable(); \
- _raw_write_lock(lock); \
- __acquire(lock); \
-} while (0)
+#ifdef CONFIG_DEBUG_SPINLOCK
+ extern void _raw_spin_lock(spinlock_t *lock);
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+ extern int _raw_spin_trylock(spinlock_t *lock);
+ extern void _raw_spin_unlock(spinlock_t *lock);
+
+ extern void _raw_read_lock(rwlock_t *lock);
+ extern int _raw_read_trylock(rwlock_t *lock);
+ extern void _raw_read_unlock(rwlock_t *lock);
+ extern void _raw_write_lock(rwlock_t *lock);
+ extern int _raw_write_trylock(rwlock_t *lock);
+ extern void _raw_write_unlock(rwlock_t *lock);
+#else
+# define _raw_spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock)
+# define _raw_spin_trylock(lock) __raw_spin_trylock(&(lock)->raw_lock)
+# define _raw_spin_lock(lock) __raw_spin_lock(&(lock)->raw_lock)
+# define _raw_spin_lock_flags(lock, flags) \
+ __raw_spin_lock_flags(&(lock)->raw_lock, *(flags))
+# define _raw_read_lock(rwlock) __raw_read_lock(&(rwlock)->raw_lock)
+# define _raw_write_lock(rwlock) __raw_write_lock(&(rwlock)->raw_lock)
+# define _raw_read_unlock(rwlock) __raw_read_unlock(&(rwlock)->raw_lock)
+# define _raw_write_unlock(rwlock) __raw_write_unlock(&(rwlock)->raw_lock)
+# define _raw_read_trylock(rwlock) __raw_read_trylock(&(rwlock)->raw_lock)
+# define _raw_write_trylock(rwlock) __raw_write_trylock(&(rwlock)->raw_lock)
+#endif
-#define _write_lock_irq(lock) \
-do { \
- local_irq_disable(); \
- preempt_disable(); \
- _raw_write_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _write_lock_bh(lock) \
-do { \
- local_bh_disable(); \
- preempt_disable(); \
- _raw_write_lock(lock); \
- __acquire(lock); \
-} while (0)
-
-#define _spin_unlock_irqrestore(lock, flags) \
-do { \
- _raw_spin_unlock(lock); \
- local_irq_restore(flags); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _spin_unlock_irq(lock) \
-do { \
- _raw_spin_unlock(lock); \
- local_irq_enable(); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _spin_unlock_bh(lock) \
-do { \
- _raw_spin_unlock(lock); \
- preempt_enable_no_resched(); \
- local_bh_enable(); \
- __release(lock); \
-} while (0)
-
-#define _write_unlock_bh(lock) \
-do { \
- _raw_write_unlock(lock); \
- preempt_enable_no_resched(); \
- local_bh_enable(); \
- __release(lock); \
-} while (0)
-
-#define _read_unlock_irqrestore(lock, flags) \
-do { \
- _raw_read_unlock(lock); \
- local_irq_restore(flags); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _write_unlock_irqrestore(lock, flags) \
-do { \
- _raw_write_unlock(lock); \
- local_irq_restore(flags); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _read_unlock_irq(lock) \
-do { \
- _raw_read_unlock(lock); \
- local_irq_enable(); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#define _read_unlock_bh(lock) \
-do { \
- _raw_read_unlock(lock); \
- preempt_enable_no_resched(); \
- local_bh_enable(); \
- __release(lock); \
-} while (0)
-
-#define _write_unlock_irq(lock) \
-do { \
- _raw_write_unlock(lock); \
- local_irq_enable(); \
- preempt_enable(); \
- __release(lock); \
-} while (0)
-
-#endif /* !SMP */
+#define read_can_lock(rwlock) __raw_read_can_lock(&(rwlock)->raw_lock)
+#define write_can_lock(rwlock) __raw_write_can_lock(&(rwlock)->raw_lock)
/*
* Define the various spin_lock and rw_lock methods. Note we define these
* regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
* methods are defined as nops in the case they are not required.
*/
-#define spin_trylock(lock) __cond_lock(_spin_trylock(lock))
-#define read_trylock(lock) __cond_lock(_read_trylock(lock))
-#define write_trylock(lock) __cond_lock(_write_trylock(lock))
+#define spin_trylock(lock) __cond_lock(_spin_trylock(lock))
+#define read_trylock(lock) __cond_lock(_read_trylock(lock))
+#define write_trylock(lock) __cond_lock(_write_trylock(lock))
-#define spin_lock(lock) _spin_lock(lock)
-#define write_lock(lock) _write_lock(lock)
-#define read_lock(lock) _read_lock(lock)
+#define spin_lock(lock) _spin_lock(lock)
+#define write_lock(lock) _write_lock(lock)
+#define read_lock(lock) _read_lock(lock)
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock)
#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock)
#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock)
@@ -470,137 +171,59 @@ do { \
#define write_lock_irq(lock) _write_lock_irq(lock)
#define write_lock_bh(lock) _write_lock_bh(lock)
-#define spin_unlock(lock) _spin_unlock(lock)
-#define write_unlock(lock) _write_unlock(lock)
-#define read_unlock(lock) _read_unlock(lock)
+#define spin_unlock(lock) _spin_unlock(lock)
+#define write_unlock(lock) _write_unlock(lock)
+#define read_unlock(lock) _read_unlock(lock)
-#define spin_unlock_irqrestore(lock, flags) _spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irqrestore(lock, flags) \
+ _spin_unlock_irqrestore(lock, flags)
#define spin_unlock_irq(lock) _spin_unlock_irq(lock)
#define spin_unlock_bh(lock) _spin_unlock_bh(lock)
-#define read_unlock_irqrestore(lock, flags) _read_unlock_irqrestore(lock, flags)
-#define read_unlock_irq(lock) _read_unlock_irq(lock)
-#define read_unlock_bh(lock) _read_unlock_bh(lock)
+#define read_unlock_irqrestore(lock, flags) \
+ _read_unlock_irqrestore(lock, flags)
+#define read_unlock_irq(lock) _read_unlock_irq(lock)
+#define read_unlock_bh(lock) _read_unlock_bh(lock)
-#define write_unlock_irqrestore(lock, flags) _write_unlock_irqrestore(lock, flags)
-#define write_unlock_irq(lock) _write_unlock_irq(lock)
-#define write_unlock_bh(lock) _write_unlock_bh(lock)
+#define write_unlock_irqrestore(lock, flags) \
+ _write_unlock_irqrestore(lock, flags)
+#define write_unlock_irq(lock) _write_unlock_irq(lock)
+#define write_unlock_bh(lock) _write_unlock_bh(lock)
-#define spin_trylock_bh(lock) __cond_lock(_spin_trylock_bh(lock))
+#define spin_trylock_bh(lock) __cond_lock(_spin_trylock_bh(lock))
#define spin_trylock_irq(lock) \
({ \
local_irq_disable(); \
_spin_trylock(lock) ? \
- 1 : ({local_irq_enable(); 0; }); \
+ 1 : ({ local_irq_enable(); 0; }); \
})
#define spin_trylock_irqsave(lock, flags) \
({ \
local_irq_save(flags); \
_spin_trylock(lock) ? \
- 1 : ({local_irq_restore(flags); 0;}); \
+ 1 : ({ local_irq_restore(flags); 0; }); \
})
-#ifdef CONFIG_LOCKMETER
-extern void _metered_spin_lock (spinlock_t *lock);
-extern void _metered_spin_unlock (spinlock_t *lock);
-extern int _metered_spin_trylock(spinlock_t *lock);
-extern void _metered_read_lock (rwlock_t *lock);
-extern void _metered_read_unlock (rwlock_t *lock);
-extern void _metered_write_lock (rwlock_t *lock);
-extern void _metered_write_unlock (rwlock_t *lock);
-extern int _metered_read_trylock (rwlock_t *lock);
-extern int _metered_write_trylock(rwlock_t *lock);
-#endif
-
-/* "lock on reference count zero" */
-#ifndef ATOMIC_DEC_AND_LOCK
-#include <asm/atomic.h>
-extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
-#endif
-
-#define atomic_dec_and_lock(atomic,lock) __cond_lock(_atomic_dec_and_lock(atomic,lock))
-
-/*
- * bit-based spin_lock()
- *
- * Don't use this unless you really need to: spin_lock() and spin_unlock()
- * are significantly faster.
- */
-static inline void bit_spin_lock(int bitnum, unsigned long *addr)
-{
- /*
- * Assuming the lock is uncontended, this never enters
- * the body of the outer loop. If it is contended, then
- * within the inner loop a non-atomic test is used to
- * busywait with less bus contention for a good time to
- * attempt to acquire the lock bit.
- */
- preempt_disable();
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- while (test_and_set_bit(bitnum, addr)) {
- while (test_bit(bitnum, addr)) {
- preempt_enable();
- cpu_relax();
- preempt_disable();
- }
- }
-#endif
- __acquire(bitlock);
-}
-
/*
- * Return true if it was acquired
+ * Pull the atomic_t declaration:
+ * (asm-mips/atomic.h needs above definitions)
*/
-static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
-{
- preempt_disable();
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- if (test_and_set_bit(bitnum, addr)) {
- preempt_enable();
- return 0;
- }
-#endif
- __acquire(bitlock);
- return 1;
-}
-
-/*
- * bit-based spin_unlock()
- */
-static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- BUG_ON(!test_bit(bitnum, addr));
- smp_mb__before_clear_bit();
- clear_bit(bitnum, addr);
-#endif
- preempt_enable();
- __release(bitlock);
-}
-
-/*
- * Return true if the lock is held.
+#include <asm/atomic.h>
+/**
+ * atomic_dec_and_lock - lock on reaching reference count zero
+ * @atomic: the atomic counter
+ * @lock: the spinlock in question
*/
-static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
- return test_bit(bitnum, addr);
-#elif defined CONFIG_PREEMPT
- return preempt_count();
-#else
- return 1;
-#endif
-}
-
-#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
-#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
+extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
+#define atomic_dec_and_lock(atomic, lock) \
+ __cond_lock(_atomic_dec_and_lock(atomic, lock))
/**
* spin_can_lock - would spin_trylock() succeed?
* @lock: the spinlock in question.
*/
-#define spin_can_lock(lock) (!spin_is_locked(lock))
+#define spin_can_lock(lock) (!spin_is_locked(lock))
#endif /* __LINUX_SPINLOCK_H */
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
new file mode 100644
index 000000000000..78e6989ffb54
--- /dev/null
+++ b/include/linux/spinlock_api_smp.h
@@ -0,0 +1,57 @@
+#ifndef __LINUX_SPINLOCK_API_SMP_H
+#define __LINUX_SPINLOCK_API_SMP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_api_smp.h
+ *
+ * spinlock API declarations on SMP (and debug)
+ * (implemented in kernel/spinlock.c)
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+int in_lock_functions(unsigned long addr);
+
+#define assert_spin_locked(x) BUG_ON(!spin_is_locked(x))
+
+void __lockfunc _spin_lock(spinlock_t *lock) __acquires(spinlock_t);
+void __lockfunc _read_lock(rwlock_t *lock) __acquires(rwlock_t);
+void __lockfunc _write_lock(rwlock_t *lock) __acquires(rwlock_t);
+void __lockfunc _spin_lock_bh(spinlock_t *lock) __acquires(spinlock_t);
+void __lockfunc _read_lock_bh(rwlock_t *lock) __acquires(rwlock_t);
+void __lockfunc _write_lock_bh(rwlock_t *lock) __acquires(rwlock_t);
+void __lockfunc _spin_lock_irq(spinlock_t *lock) __acquires(spinlock_t);
+void __lockfunc _read_lock_irq(rwlock_t *lock) __acquires(rwlock_t);
+void __lockfunc _write_lock_irq(rwlock_t *lock) __acquires(rwlock_t);
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
+ __acquires(spinlock_t);
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
+ __acquires(rwlock_t);
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
+ __acquires(rwlock_t);
+int __lockfunc _spin_trylock(spinlock_t *lock);
+int __lockfunc _read_trylock(rwlock_t *lock);
+int __lockfunc _write_trylock(rwlock_t *lock);
+int __lockfunc _spin_trylock_bh(spinlock_t *lock);
+void __lockfunc _spin_unlock(spinlock_t *lock) __releases(spinlock_t);
+void __lockfunc _read_unlock(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _write_unlock(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock) __releases(spinlock_t);
+void __lockfunc _read_unlock_bh(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _write_unlock_bh(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock) __releases(spinlock_t);
+void __lockfunc _read_unlock_irq(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _write_unlock_irq(rwlock_t *lock) __releases(rwlock_t);
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+ __releases(spinlock_t);
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+ __releases(rwlock_t);
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+ __releases(rwlock_t);
+
+#endif /* __LINUX_SPINLOCK_API_SMP_H */
diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_up.h
new file mode 100644
index 000000000000..cd81cee566f4
--- /dev/null
+++ b/include/linux/spinlock_api_up.h
@@ -0,0 +1,80 @@
+#ifndef __LINUX_SPINLOCK_API_UP_H
+#define __LINUX_SPINLOCK_API_UP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_api_up.h
+ *
+ * spinlock API implementation on UP-nondebug (inlined implementation)
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#define in_lock_functions(ADDR) 0
+
+#define assert_spin_locked(lock) do { (void)(lock); } while (0)
+
+/*
+ * In the UP-nondebug case there's no real locking going on, so the
+ * only thing we have to do is to keep the preempt counts and irq
+ * flags straight, to supress compiler warnings of unused lock
+ * variables, and to add the proper checker annotations:
+ */
+#define __LOCK(lock) \
+ do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
+
+#define __LOCK_BH(lock) \
+ do { local_bh_disable(); __LOCK(lock); } while (0)
+
+#define __LOCK_IRQ(lock) \
+ do { local_irq_disable(); __LOCK(lock); } while (0)
+
+#define __LOCK_IRQSAVE(lock, flags) \
+ do { local_irq_save(flags); __LOCK(lock); } while (0)
+
+#define __UNLOCK(lock) \
+ do { preempt_enable(); __release(lock); (void)(lock); } while (0)
+
+#define __UNLOCK_BH(lock) \
+ do { preempt_enable_no_resched(); local_bh_enable(); __release(lock); (void)(lock); } while (0)
+
+#define __UNLOCK_IRQ(lock) \
+ do { local_irq_enable(); __UNLOCK(lock); } while (0)
+
+#define __UNLOCK_IRQRESTORE(lock, flags) \
+ do { local_irq_restore(flags); __UNLOCK(lock); } while (0)
+
+#define _spin_lock(lock) __LOCK(lock)
+#define _read_lock(lock) __LOCK(lock)
+#define _write_lock(lock) __LOCK(lock)
+#define _spin_lock_bh(lock) __LOCK_BH(lock)
+#define _read_lock_bh(lock) __LOCK_BH(lock)
+#define _write_lock_bh(lock) __LOCK_BH(lock)
+#define _spin_lock_irq(lock) __LOCK_IRQ(lock)
+#define _read_lock_irq(lock) __LOCK_IRQ(lock)
+#define _write_lock_irq(lock) __LOCK_IRQ(lock)
+#define _spin_lock_irqsave(lock, flags) __LOCK_IRQSAVE(lock, flags)
+#define _read_lock_irqsave(lock, flags) __LOCK_IRQSAVE(lock, flags)
+#define _write_lock_irqsave(lock, flags) __LOCK_IRQSAVE(lock, flags)
+#define _spin_trylock(lock) ({ __LOCK(lock); 1; })
+#define _read_trylock(lock) ({ __LOCK(lock); 1; })
+#define _write_trylock(lock) ({ __LOCK(lock); 1; })
+#define _spin_trylock_bh(lock) ({ __LOCK_BH(lock); 1; })
+#define _spin_unlock(lock) __UNLOCK(lock)
+#define _read_unlock(lock) __UNLOCK(lock)
+#define _write_unlock(lock) __UNLOCK(lock)
+#define _spin_unlock_bh(lock) __UNLOCK_BH(lock)
+#define _write_unlock_bh(lock) __UNLOCK_BH(lock)
+#define _read_unlock_bh(lock) __UNLOCK_BH(lock)
+#define _spin_unlock_irq(lock) __UNLOCK_IRQ(lock)
+#define _read_unlock_irq(lock) __UNLOCK_IRQ(lock)
+#define _write_unlock_irq(lock) __UNLOCK_IRQ(lock)
+#define _spin_unlock_irqrestore(lock, flags) __UNLOCK_IRQRESTORE(lock, flags)
+#define _read_unlock_irqrestore(lock, flags) __UNLOCK_IRQRESTORE(lock, flags)
+#define _write_unlock_irqrestore(lock, flags) __UNLOCK_IRQRESTORE(lock, flags)
+
+#endif /* __LINUX_SPINLOCK_API_UP_H */
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
new file mode 100644
index 000000000000..9cb51e070390
--- /dev/null
+++ b/include/linux/spinlock_types.h
@@ -0,0 +1,67 @@
+#ifndef __LINUX_SPINLOCK_TYPES_H
+#define __LINUX_SPINLOCK_TYPES_H
+
+/*
+ * include/linux/spinlock_types.h - generic spinlock type definitions
+ * and initializers
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#if defined(CONFIG_SMP)
+# include <asm/spinlock_types.h>
+#else
+# include <linux/spinlock_types_up.h>
+#endif
+
+typedef struct {
+ raw_spinlock_t raw_lock;
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+ unsigned int break_lock;
+#endif
+#ifdef CONFIG_DEBUG_SPINLOCK
+ unsigned int magic, owner_cpu;
+ void *owner;
+#endif
+} spinlock_t;
+
+#define SPINLOCK_MAGIC 0xdead4ead
+
+typedef struct {
+ raw_rwlock_t raw_lock;
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+ unsigned int break_lock;
+#endif
+#ifdef CONFIG_DEBUG_SPINLOCK
+ unsigned int magic, owner_cpu;
+ void *owner;
+#endif
+} rwlock_t;
+
+#define RWLOCK_MAGIC 0xdeaf1eed
+
+#define SPINLOCK_OWNER_INIT ((void *)-1L)
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+# define SPIN_LOCK_UNLOCKED \
+ (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \
+ .magic = SPINLOCK_MAGIC, \
+ .owner = SPINLOCK_OWNER_INIT, \
+ .owner_cpu = -1 }
+#define RW_LOCK_UNLOCKED \
+ (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED, \
+ .magic = RWLOCK_MAGIC, \
+ .owner = SPINLOCK_OWNER_INIT, \
+ .owner_cpu = -1 }
+#else
+# define SPIN_LOCK_UNLOCKED \
+ (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED }
+#define RW_LOCK_UNLOCKED \
+ (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED }
+#endif
+
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
+
+#endif /* __LINUX_SPINLOCK_TYPES_H */
diff --git a/include/linux/spinlock_types_up.h b/include/linux/spinlock_types_up.h
new file mode 100644
index 000000000000..def2d173a8db
--- /dev/null
+++ b/include/linux/spinlock_types_up.h
@@ -0,0 +1,51 @@
+#ifndef __LINUX_SPINLOCK_TYPES_UP_H
+#define __LINUX_SPINLOCK_TYPES_UP_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_types_up.h - spinlock type definitions for UP
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+typedef struct {
+ volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+#else
+
+/*
+ * All gcc 2.95 versions and early versions of 2.96 have a nasty bug
+ * with empty initializers.
+ */
+#if (__GNUC__ > 2)
+typedef struct { } raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { }
+#else
+typedef struct { int gcc_is_buggy; } raw_spinlock_t;
+#define __RAW_SPIN_LOCK_UNLOCKED (raw_spinlock_t) { 0 }
+#endif
+
+#endif
+
+#if (__GNUC__ > 2)
+typedef struct {
+ /* no debug version on UP */
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { }
+#else
+typedef struct { int gcc_is_buggy; } raw_rwlock_t;
+#define __RAW_RW_LOCK_UNLOCKED (raw_rwlock_t) { 0 }
+#endif
+
+#endif /* __LINUX_SPINLOCK_TYPES_UP_H */
diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h
new file mode 100644
index 000000000000..31accf2f0b13
--- /dev/null
+++ b/include/linux/spinlock_up.h
@@ -0,0 +1,74 @@
+#ifndef __LINUX_SPINLOCK_UP_H
+#define __LINUX_SPINLOCK_UP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_up.h - UP-debug version of spinlocks.
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ *
+ * In the debug case, 1 means unlocked, 0 means locked. (the values
+ * are inverted, to catch initialization bugs)
+ *
+ * No atomicity anywhere, we are on UP.
+ */
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+#define __raw_spin_is_locked(x) ((x)->slock == 0)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+ lock->slock = 0;
+}
+
+static inline void
+__raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+ local_irq_save(flags);
+ lock->slock = 0;
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+ char oldval = lock->slock;
+
+ lock->slock = 0;
+
+ return oldval > 0;
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+ lock->slock = 1;
+}
+
+/*
+ * Read-write spinlocks. No debug version.
+ */
+#define __raw_read_lock(lock) do { (void)(lock); } while (0)
+#define __raw_write_lock(lock) do { (void)(lock); } while (0)
+#define __raw_read_trylock(lock) ({ (void)(lock); 1; })
+#define __raw_write_trylock(lock) ({ (void)(lock); 1; })
+#define __raw_read_unlock(lock) do { (void)(lock); } while (0)
+#define __raw_write_unlock(lock) do { (void)(lock); } while (0)
+
+#else /* DEBUG_SPINLOCK */
+#define __raw_spin_is_locked(lock) ((void)(lock), 0)
+/* for sched.c and kernel_lock.c: */
+# define __raw_spin_lock(lock) do { (void)(lock); } while (0)
+# define __raw_spin_unlock(lock) do { (void)(lock); } while (0)
+# define __raw_spin_trylock(lock) ({ (void)(lock); 1; })
+#endif /* DEBUG_SPINLOCK */
+
+#define __raw_read_can_lock(lock) (((void)(lock), 1))
+#define __raw_write_can_lock(lock) (((void)(lock), 1))
+
+#define __raw_spin_unlock_wait(lock) \
+ do { cpu_relax(); } while (__raw_spin_is_locked(lock))
+
+#endif /* __LINUX_SPINLOCK_UP_H */
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 6864063d1b9f..c4e3ea7cf154 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -60,6 +60,7 @@ struct cache_head {
#define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */
struct cache_detail {
+ struct module * owner;
int hash_size;
struct cache_head ** hash_table;
rwlock_t hash_lock;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index bfe3e763ccf2..3c9ff0048153 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -107,6 +107,8 @@ enum {
SWP_USED = (1 << 0), /* is slot in swap_info[] used? */
SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */
SWP_ACTIVE = (SWP_USED | SWP_WRITEOK),
+ /* add others here before... */
+ SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */
};
#define SWAP_CLUSTER_MAX 32
@@ -116,16 +118,13 @@ enum {
/*
* The in-memory structure used to track swap areas.
- * extent_list.prev points at the lowest-index extent. That list is
- * sorted.
*/
struct swap_info_struct {
unsigned int flags;
- spinlock_t sdev_lock;
+ int prio; /* swap priority */
struct file *swap_file;
struct block_device *bdev;
struct list_head extent_list;
- int nr_extents;
struct swap_extent *curr_swap_extent;
unsigned old_block_size;
unsigned short * swap_map;
@@ -133,10 +132,9 @@ struct swap_info_struct {
unsigned int highest_bit;
unsigned int cluster_next;
unsigned int cluster_nr;
- int prio; /* swap priority */
- int pages;
- unsigned long max;
- unsigned long inuse_pages;
+ unsigned int pages;
+ unsigned int max;
+ unsigned int inuse_pages;
int next; /* next entry on swap list */
};
@@ -222,13 +220,7 @@ extern int can_share_swap_page(struct page *);
extern int remove_exclusive_swap_page(struct page *);
struct backing_dev_info;
-extern struct swap_list_t swap_list;
-extern spinlock_t swaplock;
-
-#define swap_list_lock() spin_lock(&swaplock)
-#define swap_list_unlock() spin_unlock(&swaplock)
-#define swap_device_lock(p) spin_lock(&p->sdev_lock)
-#define swap_device_unlock(p) spin_unlock(&p->sdev_lock)
+extern spinlock_t swap_lock;
/* linux/mm/thrash.c */
extern struct mm_struct * swap_token_mm;
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index d4c7db35e708..87b9d14c710d 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -4,7 +4,7 @@
* the low-order bits.
*
* We arrange the `type' and `offset' fields so that `type' is at the five
- * high-order bits of the smp_entry_t and `offset' is right-aligned in the
+ * high-order bits of the swp_entry_t and `offset' is right-aligned in the
* remaining bits.
*
* swp_entry_t's are *never* stored anywhere in their arch-dependent format.
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index e82be96d4906..3a29a9f9b451 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -544,7 +544,8 @@ enum {
NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8,
NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9,
NET_NETROM_ROUTING_CONTROL=10,
- NET_NETROM_LINK_FAILS_COUNT=11
+ NET_NETROM_LINK_FAILS_COUNT=11,
+ NET_NETROM_RESET=12
};
/* /proc/sys/net/ax25 */
@@ -711,6 +712,7 @@ enum {
DEV_RAID=4,
DEV_MAC_HID=5,
DEV_SCSI=6,
+ DEV_IPMI=7,
};
/* /proc/sys/dev/cdrom */
@@ -776,6 +778,11 @@ enum {
DEV_SCSI_LOGGING_LEVEL=1,
};
+/* /proc/sys/dev/ipmi */
+enum {
+ DEV_IPMI_POWEROFF_POWERCYCLE=1,
+};
+
/* /proc/sys/abi */
enum
{
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index e4fd82e42104..ac4ca44c75ca 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -55,24 +55,6 @@ struct tcphdr {
__u16 urg_ptr;
};
-
-enum {
- TCP_ESTABLISHED = 1,
- TCP_SYN_SENT,
- TCP_SYN_RECV,
- TCP_FIN_WAIT1,
- TCP_FIN_WAIT2,
- TCP_TIME_WAIT,
- TCP_CLOSE,
- TCP_CLOSE_WAIT,
- TCP_LAST_ACK,
- TCP_LISTEN,
- TCP_CLOSING, /* now a valid state */
-
- TCP_MAX_STATES /* Leave at the end! */
-};
-
-#define TCP_STATE_MASK 0xF
#define TCP_ACTION_FIN (1 << 7)
enum {
@@ -195,8 +177,9 @@ struct tcp_info
#include <linux/config.h>
#include <linux/skbuff.h>
-#include <linux/ip.h>
#include <net/sock.h>
+#include <net/inet_connection_sock.h>
+#include <net/inet_timewait_sock.h>
/* This defines a selective acknowledgement block. */
struct tcp_sack_block {
@@ -236,8 +219,8 @@ static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
}
struct tcp_sock {
- /* inet_sock has to be the first member of tcp_sock */
- struct inet_sock inet;
+ /* inet_connection_sock has to be the first member of tcp_sock */
+ struct inet_connection_sock inet_conn;
int tcp_header_len; /* Bytes of tcp header to send */
/*
@@ -258,19 +241,6 @@ struct tcp_sock {
__u32 snd_sml; /* Last byte of the most recently transmitted small packet */
__u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
__u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
- struct tcp_bind_bucket *bind_hash;
- /* Delayed ACK control data */
- struct {
- __u8 pending; /* ACK is pending */
- __u8 quick; /* Scheduled number of quick acks */
- __u8 pingpong; /* The session is interactive */
- __u8 blocked; /* Delayed ACK was blocked by socket lock*/
- __u32 ato; /* Predicted tick of soft clock */
- unsigned long timeout; /* Currently scheduled timeout */
- __u32 lrcvtime; /* timestamp of last received data packet*/
- __u16 last_seg_size; /* Size of last incoming segment */
- __u16 rcv_mss; /* MSS used for delayed ACK decisions */
- } ack;
/* Data for direct copy to user */
struct {
@@ -288,19 +258,15 @@ struct tcp_sock {
__u32 mss_cache; /* Cached effective mss, not including SACKS */
__u16 xmit_size_goal; /* Goal for segmenting output packets */
__u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */
- __u8 ca_state; /* State of fast-retransmit machine */
- __u8 retransmits; /* Number of unrecovered RTO timeouts. */
- __u16 advmss; /* Advertised MSS */
__u32 window_clamp; /* Maximal window to advertise */
__u32 rcv_ssthresh; /* Current window clamp */
__u32 frto_highmark; /* snd_nxt when RTO occurred */
__u8 reordering; /* Packet reordering metric. */
__u8 frto_counter; /* Number of new acks after RTO */
-
- __u8 unused;
- __u8 defer_accept; /* User waits for some data after accept() */
+ __u8 nonagle; /* Disable Nagle algorithm? */
+ __u8 keepalive_probes; /* num of allowed keep alive probes */
/* RTT measurement */
__u32 srtt; /* smoothed round trip time << 3 */
@@ -308,19 +274,13 @@ struct tcp_sock {
__u32 mdev_max; /* maximal mdev for the last rtt period */
__u32 rttvar; /* smoothed mdev_max */
__u32 rtt_seq; /* sequence number to update rttvar */
- __u32 rto; /* retransmit timeout */
__u32 packets_out; /* Packets which are "in flight" */
__u32 left_out; /* Packets which leaved network */
__u32 retrans_out; /* Retransmitted packets out */
- __u8 backoff; /* backoff */
/*
* Options received (usually on last packet, some only on SYN packets).
*/
- __u8 nonagle; /* Disable Nagle algorithm? */
- __u8 keepalive_probes; /* num of allowed keep alive probes */
-
- __u8 probes_out; /* unanswered 0 window probes */
struct tcp_options_received rx_opt;
/*
@@ -333,11 +293,6 @@ struct tcp_sock {
__u32 snd_cwnd_used;
__u32 snd_cwnd_stamp;
- /* Two commonly used timers in both sender and receiver paths. */
- unsigned long timeout;
- struct timer_list retransmit_timer; /* Resend (no ack) */
- struct timer_list delack_timer; /* Ack delay */
-
struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */
@@ -352,8 +307,7 @@ struct tcp_sock {
struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
- __u8 syn_retries; /* num of allowed syn retries */
- __u8 ecn_flags; /* ECN status bits. */
+ __u16 advmss; /* Advertised MSS */
__u16 prior_ssthresh; /* ssthresh saved at recovery start */
__u32 lost_out; /* Lost packets */
__u32 sacked_out; /* SACK'd packets */
@@ -367,14 +321,12 @@ struct tcp_sock {
int undo_retrans; /* number of undoable retransmissions. */
__u32 urg_seq; /* Seq of received urgent pointer */
__u16 urg_data; /* Saved octet of OOB data and control flags */
- __u8 pending; /* Scheduled timer event */
__u8 urg_mode; /* In urgent mode */
+ __u8 ecn_flags; /* ECN status bits. */
__u32 snd_up; /* Urgent pointer */
__u32 total_retrans; /* Total retransmits for entire connection */
- struct request_sock_queue accept_queue; /* FIFO of established children */
-
unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */
int linger2;
@@ -394,11 +346,6 @@ struct tcp_sock {
__u32 seq;
__u32 time;
} rcvq_space;
-
- /* Pluggable TCP congestion control hook */
- struct tcp_congestion_ops *ca_ops;
- u32 ca_priv[16];
-#define TCP_CA_PRIV_SIZE (16*sizeof(u32))
};
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
@@ -406,9 +353,18 @@ static inline struct tcp_sock *tcp_sk(const struct sock *sk)
return (struct tcp_sock *)sk;
}
-static inline void *tcp_ca(const struct tcp_sock *tp)
+struct tcp_timewait_sock {
+ struct inet_timewait_sock tw_sk;
+ __u32 tw_rcv_nxt;
+ __u32 tw_snd_nxt;
+ __u32 tw_rcv_wnd;
+ __u32 tw_ts_recent;
+ long tw_ts_recent_stamp;
+};
+
+static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk)
{
- return (void *) tp->ca_priv;
+ return (struct tcp_timewait_sock *)sk;
}
#endif
diff --git a/include/linux/tcp_diag.h b/include/linux/tcp_diag.h
deleted file mode 100644
index 7a5996743946..000000000000
--- a/include/linux/tcp_diag.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef _TCP_DIAG_H_
-#define _TCP_DIAG_H_ 1
-
-/* Just some random number */
-#define TCPDIAG_GETSOCK 18
-
-/* Socket identity */
-struct tcpdiag_sockid
-{
- __u16 tcpdiag_sport;
- __u16 tcpdiag_dport;
- __u32 tcpdiag_src[4];
- __u32 tcpdiag_dst[4];
- __u32 tcpdiag_if;
- __u32 tcpdiag_cookie[2];
-#define TCPDIAG_NOCOOKIE (~0U)
-};
-
-/* Request structure */
-
-struct tcpdiagreq
-{
- __u8 tcpdiag_family; /* Family of addresses. */
- __u8 tcpdiag_src_len;
- __u8 tcpdiag_dst_len;
- __u8 tcpdiag_ext; /* Query extended information */
-
- struct tcpdiag_sockid id;
-
- __u32 tcpdiag_states; /* States to dump */
- __u32 tcpdiag_dbs; /* Tables to dump (NI) */
-};
-
-enum
-{
- TCPDIAG_REQ_NONE,
- TCPDIAG_REQ_BYTECODE,
-};
-
-#define TCPDIAG_REQ_MAX TCPDIAG_REQ_BYTECODE
-
-/* Bytecode is sequence of 4 byte commands followed by variable arguments.
- * All the commands identified by "code" are conditional jumps forward:
- * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be
- * length of the command and its arguments.
- */
-
-struct tcpdiag_bc_op
-{
- unsigned char code;
- unsigned char yes;
- unsigned short no;
-};
-
-enum
-{
- TCPDIAG_BC_NOP,
- TCPDIAG_BC_JMP,
- TCPDIAG_BC_S_GE,
- TCPDIAG_BC_S_LE,
- TCPDIAG_BC_D_GE,
- TCPDIAG_BC_D_LE,
- TCPDIAG_BC_AUTO,
- TCPDIAG_BC_S_COND,
- TCPDIAG_BC_D_COND,
-};
-
-struct tcpdiag_hostcond
-{
- __u8 family;
- __u8 prefix_len;
- int port;
- __u32 addr[0];
-};
-
-/* Base info structure. It contains socket identity (addrs/ports/cookie)
- * and, alas, the information shown by netstat. */
-struct tcpdiagmsg
-{
- __u8 tcpdiag_family;
- __u8 tcpdiag_state;
- __u8 tcpdiag_timer;
- __u8 tcpdiag_retrans;
-
- struct tcpdiag_sockid id;
-
- __u32 tcpdiag_expires;
- __u32 tcpdiag_rqueue;
- __u32 tcpdiag_wqueue;
- __u32 tcpdiag_uid;
- __u32 tcpdiag_inode;
-};
-
-/* Extensions */
-
-enum
-{
- TCPDIAG_NONE,
- TCPDIAG_MEMINFO,
- TCPDIAG_INFO,
- TCPDIAG_VEGASINFO,
- TCPDIAG_CONG,
-};
-
-#define TCPDIAG_MAX TCPDIAG_CONG
-
-
-/* TCPDIAG_MEM */
-
-struct tcpdiag_meminfo
-{
- __u32 tcpdiag_rmem;
- __u32 tcpdiag_wmem;
- __u32 tcpdiag_fmem;
- __u32 tcpdiag_tmem;
-};
-
-/* TCPDIAG_VEGASINFO */
-
-struct tcpvegas_info {
- __u32 tcpv_enabled;
- __u32 tcpv_rttcnt;
- __u32 tcpv_rtt;
- __u32 tcpv_minrtt;
-};
-
-#endif /* _TCP_DIAG_H_ */
diff --git a/include/linux/time.h b/include/linux/time.h
index 5634497ff5df..8e83f4e778bb 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -28,17 +28,10 @@ struct timezone {
#ifdef __KERNEL__
/* Parameters used to convert the timespec values */
-#ifndef USEC_PER_SEC
+#define MSEC_PER_SEC (1000L)
#define USEC_PER_SEC (1000000L)
-#endif
-
-#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC (1000000000L)
-#endif
-
-#ifndef NSEC_PER_USEC
#define NSEC_PER_USEC (1000L)
-#endif
static __inline__ int timespec_equal(struct timespec *a, struct timespec *b)
{
@@ -97,7 +90,6 @@ extern int do_settimeofday(struct timespec *tv);
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
extern void clock_was_set(void); // call when ever the clock is set
extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
-extern long do_nanosleep(struct timespec *t);
extern long do_utimes(char __user * filename, struct timeval * times);
struct itimerval;
extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 221f81ac2002..3340f3bd135d 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -32,6 +32,10 @@ extern struct timer_base_s __init_timer_base;
.magic = TIMER_MAGIC, \
}
+#define DEFINE_TIMER(_name, _function, _expires, _data) \
+ struct timer_list _name = \
+ TIMER_INITIALIZER(_function, _expires, _data)
+
void fastcall init_timer(struct timer_list * timer);
/***
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 74fdd07d3792..7e050a2cc35b 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -260,6 +260,29 @@ extern long pps_calcnt; /* calibration intervals */
extern long pps_errcnt; /* calibration errors */
extern long pps_stbcnt; /* stability limit exceeded */
+/**
+ * ntp_clear - Clears the NTP state variables
+ *
+ * Must be called while holding a write on the xtime_lock
+ */
+static inline void ntp_clear(void)
+{
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+}
+
+/**
+ * ntp_synced - Returns 1 if the NTP status is not UNSYNC
+ *
+ */
+static inline int ntp_synced(void)
+{
+ return !(time_status & STA_UNSYNC);
+}
+
+
#ifdef CONFIG_TIME_INTERPOLATION
#define TIME_SOURCE_CPU 0
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 0320225e96da..3df1d474e5c5 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -135,6 +135,29 @@
}
#endif
+/* sched_domains SD_ALLNODES_INIT for NUMA machines */
+#define SD_ALLNODES_INIT (struct sched_domain) { \
+ .span = CPU_MASK_NONE, \
+ .parent = NULL, \
+ .groups = NULL, \
+ .min_interval = 64, \
+ .max_interval = 64*num_online_cpus(), \
+ .busy_factor = 128, \
+ .imbalance_pct = 133, \
+ .cache_hot_time = (10*1000000), \
+ .cache_nice_tries = 1, \
+ .busy_idx = 3, \
+ .idle_idx = 3, \
+ .newidle_idx = 0, /* unused */ \
+ .wake_idx = 0, /* unused */ \
+ .forkexec_idx = 0, /* unused */ \
+ .per_cpu_gain = 100, \
+ .flags = SD_LOAD_BALANCE, \
+ .last_balance = jiffies, \
+ .balance_interval = 64, \
+ .nr_balance_failed = 0, \
+}
+
#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/transport_class.h b/include/linux/transport_class.h
index 87d98d1faefb..1d6cc22e5f42 100644
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -12,11 +12,16 @@
#include <linux/device.h>
#include <linux/attribute_container.h>
+struct transport_container;
+
struct transport_class {
struct class class;
- int (*setup)(struct device *);
- int (*configure)(struct device *);
- int (*remove)(struct device *);
+ int (*setup)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*configure)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*remove)(struct transport_container *, struct device *,
+ struct class_device *);
};
#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 59ff42c629ec..1267f88ece6e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -74,7 +74,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/types.h b/include/linux/types.h
index dcb13f865df9..2b678c22ca4a 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -123,6 +123,9 @@ typedef __u64 u_int64_t;
typedef __s64 int64_t;
#endif
+/* this is a special 64bit data type that is 8-byte aligned */
+#define aligned_u64 unsigned long long __attribute__((aligned(8)))
+
/*
* The type used for indexing onto a disc or disc partition.
* If required, asm/types.h can override it and define
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 724637792996..4dbe580f9335 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -5,6 +5,7 @@
#include <linux/usb_ch9.h>
#define USB_MAJOR 180
+#define USB_DEVICE_MAJOR 189
#ifdef __KERNEL__
@@ -349,6 +350,7 @@ struct usb_device {
char *manufacturer;
char *serial; /* static strings from the device */
struct list_head filelist;
+ struct class_device *class_dev;
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
/*
@@ -614,7 +616,6 @@ extern int usb_disabled(void);
#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */
#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
#define URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */
-#define URB_ASYNC_UNLINK 0x0010 /* usb_unlink_urb() returns asap */
#define URB_NO_FSBR 0x0020 /* UHCI-specific */
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
@@ -722,13 +723,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
* Initialization:
*
* All URBs submitted must initialize the dev, pipe, transfer_flags (may be
- * zero), and complete fields.
- * The URB_ASYNC_UNLINK transfer flag affects later invocations of
- * the usb_unlink_urb() routine. Note: Failure to set URB_ASYNC_UNLINK
- * with usb_unlink_urb() is deprecated. For synchronous unlinks use
- * usb_kill_urb() instead.
- *
- * All URBs must also initialize
+ * zero), and complete fields. All URBs must also initialize
* transfer_buffer and transfer_buffer_length. They may provide the
* URB_SHORT_NOT_OK transfer flag, indicating that short reads are
* to be treated as errors; that flag is invalid for write requests.
diff --git a/include/linux/usb_isp116x.h b/include/linux/usb_isp116x.h
index 5f5a9d9bd6c2..436dd8a2b64a 100644
--- a/include/linux/usb_isp116x.h
+++ b/include/linux/usb_isp116x.h
@@ -7,36 +7,18 @@
struct isp116x_platform_data {
/* Enable internal resistors on downstream ports */
unsigned sel15Kres:1;
- /* Chip's internal clock won't be stopped in suspended state.
- Setting/unsetting this bit takes effect only if
- 'remote_wakeup_enable' below is not set. */
- unsigned clknotstop:1;
- /* On-chip overcurrent protection */
+ /* On-chip overcurrent detection */
unsigned oc_enable:1;
/* INT output polarity */
unsigned int_act_high:1;
/* INT edge or level triggered */
unsigned int_edge_triggered:1;
- /* WAKEUP pin connected - NOT SUPPORTED */
- /* unsigned remote_wakeup_connected:1; */
- /* Wakeup by devices on usb bus enabled */
+ /* Enable wakeup by devices on usb bus (e.g. wakeup
+ by attachment/detachment or by device activity
+ such as moving a mouse). When chosen, this option
+ prevents stopping internal clock, increasing
+ thereby power consumption in suspended state. */
unsigned remote_wakeup_enable:1;
- /* Switch or not to switch (keep always powered) */
- unsigned no_power_switching:1;
- /* Ganged port power switching (0) or individual port
- power switching (1) */
- unsigned power_switching_mode:1;
- /* Given port_power, msec/2 after power on till power good */
- u8 potpg;
- /* Hardware reset set/clear. If implemented, this function must:
- if set == 0, deassert chip's HW reset pin
- otherwise, assert chip's HW reset pin */
- void (*reset) (struct device * dev, int set);
- /* Hardware clock start/stop. If implemented, this function must:
- if start == 0, stop the external clock
- otherwise, start the external clock
- */
- void (*clock) (struct device * dev, int start);
/* Inter-io delay (ns). The chip is picky about access timings; it
expects at least:
150ns delay between consecutive accesses to DATA_REG,
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index fb57c2217468..9facf733800c 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -32,7 +32,6 @@
#define _LINUX_USBDEVICE_FS_H
#include <linux/types.h>
-#include <linux/compat.h>
/* --------------------------------------------------------------------- */
@@ -125,6 +124,7 @@ struct usbdevfs_hub_portinfo {
};
#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
struct usbdevfs_urb32 {
unsigned char type;
unsigned char endpoint;
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 9d6fbde3d29c..1cc8c31b7988 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -3,7 +3,6 @@
#include <linux/compiler.h>
#include <linux/types.h>
-#include <linux/version.h>
#define HAVE_V4L2 1
#include <linux/videodev2.h>
@@ -29,7 +28,6 @@ struct video_device
void (*release)(struct video_device *vfd);
-#if 1 /* to be removed in 2.7.x */
/* obsolete -- fops->owner is used instead */
struct module *owner;
/* dev->driver_data will be used instead some day.
@@ -37,7 +35,6 @@ struct video_device
* so the switch over will be transparent for you.
* Or use {pci|usb}_{get|set}_drvdata() directly. */
void *priv;
-#endif
/* for videodev.c intenal usage -- please don't touch */
int users; /* video_exclusive_{open|close} ... */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index acbfc525576d..89a055761bed 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -60,12 +60,17 @@ enum v4l2_field {
(field) == V4L2_FIELD_SEQ_BT)
enum v4l2_buf_type {
- V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
- V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
- V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
- V4L2_BUF_TYPE_VBI_CAPTURE = 4,
- V4L2_BUF_TYPE_VBI_OUTPUT = 5,
- V4L2_BUF_TYPE_PRIVATE = 0x80,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
+ V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
+ V4L2_BUF_TYPE_VBI_CAPTURE = 4,
+ V4L2_BUF_TYPE_VBI_OUTPUT = 5,
+#if 1
+ /* Experimental Sliced VBI */
+ V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
+ V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
+#endif
+ V4L2_BUF_TYPE_PRIVATE = 0x80,
};
enum v4l2_ctrl_type {
@@ -149,20 +154,24 @@ struct v4l2_capability
};
/* Values for 'capabilities' field */
-#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
-#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
-#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
-#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a VBI capture device */
-#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a VBI output device */
-#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
+#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
+#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
+#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
+#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */
+#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */
+#if 1
+#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
+#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
+#endif
+#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
-#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
-#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
-#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
+#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
+#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
+#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
-#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
-#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
-#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
+#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
+#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
+#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
/*
* V I D E O I M A G E F O R M A T
@@ -270,7 +279,6 @@ struct v4l2_timecode
/* The above is based on SMPTE timecodes */
-#if 1
/*
* M P E G C O M P R E S S I O N P A R A M E T E R S
*
@@ -357,7 +365,6 @@ struct v4l2_mpeg_compression {
/* I don't expect the above being perfect yet ;) */
__u32 reserved_5[8];
};
-#endif
struct v4l2_jpegcompression
{
@@ -811,6 +818,8 @@ struct v4l2_audioout
* Data services API by Michael Schimek
*/
+/* Raw VBI */
+
struct v4l2_vbi_format
{
__u32 sampling_rate; /* in 1 Hz */
@@ -827,6 +836,54 @@ struct v4l2_vbi_format
#define V4L2_VBI_UNSYNC (1<< 0)
#define V4L2_VBI_INTERLACED (1<< 1)
+#if 1
+/* Sliced VBI
+ *
+ * This implements is a proposal V4L2 API to allow SLICED VBI
+ * required for some hardware encoders. It should change without
+ * notice in the definitive implementation.
+ */
+
+struct v4l2_sliced_vbi_format
+{
+ __u16 service_set;
+ /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+ service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+ (equals frame lines 313-336 for 625 line video
+ standards, 263-286 for 525 line standards) */
+ __u16 service_lines[2][24];
+ __u32 io_size;
+ __u32 reserved[2]; /* must be zero */
+};
+
+#define V4L2_SLICED_TELETEXT_B (0x0001)
+#define V4L2_SLICED_VPS (0x0400)
+#define V4L2_SLICED_CAPTION_525 (0x1000)
+#define V4L2_SLICED_WSS_625 (0x4000)
+
+#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)
+
+struct v4l2_sliced_vbi_cap
+{
+ __u16 service_set;
+ /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+ service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+ (equals frame lines 313-336 for 625 line video
+ standards, 263-286 for 525 line standards) */
+ __u16 service_lines[2][24];
+ __u32 reserved[4]; /* must be 0 */
+};
+
+struct v4l2_sliced_vbi_data
+{
+ __u32 id;
+ __u32 field; /* 0: first field, 1: second field */
+ __u32 line; /* 1-23 */
+ __u32 reserved; /* must be 0 */
+ __u8 data[48];
+};
+#endif
/*
* A G G R E G A T E S T R U C T U R E S
@@ -839,10 +896,13 @@ struct v4l2_format
enum v4l2_buf_type type;
union
{
- struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
- struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
- struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
- __u8 raw_data[200]; // user-defined
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+#if 1
+ struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
+#endif
+ __u8 raw_data[200]; // user-defined
} fmt;
};
@@ -871,10 +931,8 @@ struct v4l2_streamparm
#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc)
#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format)
#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format)
-#if 1 /* experimental */
#define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression)
#define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression)
-#endif
#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers)
#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer)
#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer)
@@ -920,6 +978,9 @@ struct v4l2_streamparm
#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout)
#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority)
#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority)
+#if 1
+#define VIDIOC_G_SLICED_VBI_CAP _IOR ('V', 69, struct v4l2_sliced_vbi_cap)
+#endif
/* for compatibility, will go away some day */
#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int)
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 6409d9cf5965..b244f69ef682 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -10,6 +10,14 @@
#define VM_MAP 0x00000004 /* vmap()ed pages */
/* bits [20..32] reserved for arch specific ioremap internals */
+/*
+ * Maximum alignment for ioremap() regions.
+ * Can be overriden by arch-specific value.
+ */
+#ifndef IOREMAP_MAX_ORDER
+#define IOREMAP_MAX_ORDER (7 + PAGE_SHIFT) /* 128 pages */
+#endif
+
struct vm_struct {
void *addr;
unsigned long size;
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index ae485f9c916e..a555a0f7a7b4 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1,7 +1,7 @@
/*
* This file define a set of standard wireless extensions
*
- * Version : 18 12.3.05
+ * Version : 19 18.3.05
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
@@ -69,8 +69,6 @@
/***************************** INCLUDES *****************************/
-/* To minimise problems in user space, I might remove those headers
- * at some point. Jean II */
#include <linux/types.h> /* for "caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/if.h> /* for IFNAMSIZ and co... */
@@ -82,7 +80,7 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 18
+#define WIRELESS_EXT 19
/*
* Changes :
@@ -197,6 +195,15 @@
* related parameters (extensible up to 4096 parameter values)
* - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
* IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
*/
/**************************** CONSTANTS ****************************/
@@ -322,6 +329,7 @@
/* The first and the last (range) */
#define SIOCIWFIRST 0x8B00
#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
/* Even : get (world access), odd : set (root access) */
#define IW_IS_SET(cmd) (!((cmd) & 0x1))
@@ -366,6 +374,7 @@
* (struct iw_pmkid_cand) */
#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
/* ------------------------- PRIVATE INFO ------------------------- */
/*
@@ -427,12 +436,15 @@
#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
/* Statistics flags (bitmask in updated) */
-#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */
-#define IW_QUAL_LEVEL_UPDATED 0x2
-#define IW_QUAL_NOISE_UPDATED 0x4
+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED 0x02
+#define IW_QUAL_NOISE_UPDATED 0x04
+#define IW_QUAL_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
#define IW_QUAL_LEVEL_INVALID 0x20
#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_ALL_INVALID 0x70
/* Frequency flags */
#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
@@ -443,7 +455,7 @@
#define IW_MAX_ENCODING_SIZES 8
/* Maximum size of the encoding token in bytes */
-#define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
/* Flags for encoding (along with the token) */
#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
@@ -1039,12 +1051,16 @@ struct iw_event
#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
-#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point))
#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
-/* Note : in the case of iw_point, the extra data will come at the
- * end of the event */
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
#endif /* _LINUX_WIRELESS_H */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 542dbaee6512..343d883d69c5 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -109,8 +109,6 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
int sync_page_range(struct inode *inode, struct address_space *mapping,
loff_t pos, size_t count);
-int sync_page_range_nolock(struct inode *inode, struct address_space
- *mapping, loff_t pos, size_t count);
/* pdflush.c */
extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index f0d423300d84..0fb077d68441 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -258,9 +258,27 @@ struct xfrm_usersa_flush {
__u8 proto;
};
+#ifndef __KERNEL__
+/* backwards compatibility for userspace */
#define XFRMGRP_ACQUIRE 1
#define XFRMGRP_EXPIRE 2
#define XFRMGRP_SA 4
#define XFRMGRP_POLICY 8
+#endif
+
+enum xfrm_nlgroups {
+ XFRMNLGRP_NONE,
+#define XFRMNLGRP_NONE XFRMNLGRP_NONE
+ XFRMNLGRP_ACQUIRE,
+#define XFRMNLGRP_ACQUIRE XFRMNLGRP_ACQUIRE
+ XFRMNLGRP_EXPIRE,
+#define XFRMNLGRP_EXPIRE XFRMNLGRP_EXPIRE
+ XFRMNLGRP_SA,
+#define XFRMNLGRP_SA XFRMNLGRP_SA
+ XFRMNLGRP_POLICY,
+#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
+ __XFRMNLGRP_MAX
+};
+#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
#endif /* _LINUX_XFRM_H */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index cd831168fdc1..a7ceee9fc5e9 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -1,5 +1,4 @@
/*
- * $Id: audiochip.h,v 1.5 2005/06/16 22:59:16 hhackmann Exp $
*/
#ifndef AUDIOCHIP_H
diff --git a/include/media/id.h b/include/media/id.h
index a39a6423914b..6d02c94cdc0d 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -1,5 +1,4 @@
/*
- * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
*/
/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
@@ -34,8 +33,3 @@
#ifndef I2C_DRIVERID_SAA6752HS
# define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8
#endif
-
-/* algorithms */
-#ifndef I2C_ALGO_SAA7134
-# define I2C_ALGO_SAA7134 0x090000
-#endif
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 698670547f16..01b56822df4d 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -1,5 +1,4 @@
/*
- * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -21,11 +20,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/version.h>
#include <linux/input.h>
#define IR_TYPE_RC5 1
+#define IR_TYPE_PD 2 /* Pulse distance encoded IR */
#define IR_TYPE_OTHER 99
#define IR_KEYTAB_TYPE u32
@@ -60,6 +59,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
u32 ir_extract_bits(u32 data, u32 mask);
int ir_dump_samples(u32 *samples, int count);
int ir_decode_biphase(u32 *samples, int count, int low, int high);
+int ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
/*
* Local variables:
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index 3dfb8d670eb7..2a897c3a6a9a 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -1,7 +1,6 @@
#ifndef __SAA7146__
#define __SAA7146__
-#include <linux/version.h> /* for version macros */
#include <linux/module.h> /* for module-version */
#include <linux/delay.h> /* for delay-stuff */
#include <linux/slab.h> /* for kmalloc/kfree */
@@ -15,12 +14,7 @@
#include <linux/vmalloc.h> /* for vmalloc() */
#include <linux/mm.h> /* for vmalloc_to_page() */
-/* ugly, but necessary to build the dvb stuff under 2.4. */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
- #include "dvb_functions.h"
-#endif
-
-#define SAA7146_VERSION_CODE KERNEL_VERSION(0,5,0)
+#define SAA7146_VERSION_CODE 0x000500 /* 0.5.0 */
#define saa7146_write(sxy,adr,dat) writel((dat),(sxy->mem+(adr)))
#define saa7146_read(sxy,adr) readl(sxy->mem+(adr))
@@ -33,13 +27,8 @@ extern unsigned int saa7146_debug;
#define DEBUG_VARIABLE saa7146_debug
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
-#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_BASENAME),__FUNCTION__)
-#define INFO(x) { printk("%s: ",__stringify(KBUILD_BASENAME)); printk x; }
-#else
#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_MODNAME),__FUNCTION__)
#define INFO(x) { printk("%s: ",__stringify(KBUILD_MODNAME)); printk x; }
-#endif
#define ERR(x) { DEBUG_PROLOG; printk x; }
diff --git a/include/media/tuner.h b/include/media/tuner.h
index eeaa15ddee85..4ad08e24a1aa 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -1,6 +1,4 @@
-
-/* $Id: tuner.h,v 1.45 2005/07/28 18:41:21 mchehab Exp $
- *
+/*
tuner.h - definition for different tuners
Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
@@ -28,88 +26,90 @@
#define ADDR_UNSET (255)
-#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
-#define TUNER_PHILIPS_PAL_I 1
-#define TUNER_PHILIPS_NTSC 2
-#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */
-
-#define TUNER_ABSENT 4
-#define TUNER_PHILIPS_PAL 5
-#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */
-#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */
-
-#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */
-#define TUNER_ALPS_TSBH1_NTSC 9
-#define TUNER_ALPS_TSBE1_PAL 10
-#define TUNER_ALPS_TSBB5_PAL_I 11
-
-#define TUNER_ALPS_TSBE5_PAL 12
-#define TUNER_ALPS_TSBC5_PAL 13
-#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */
-#define TUNER_ALPS_TSHC6_NTSC 15
-
-#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */
-#define TUNER_PHILIPS_NTSC_M 17
-#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */
-#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
-
-#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/
-#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/
-#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/
+#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
+#define TUNER_PHILIPS_PAL_I 1
+#define TUNER_PHILIPS_NTSC 2
+#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */
+
+#define TUNER_ABSENT 4
+#define TUNER_PHILIPS_PAL 5
+#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */
+#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */
+
+#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */
+#define TUNER_ALPS_TSBH1_NTSC 9
+#define TUNER_ALPS_TSBE1_PAL 10
+#define TUNER_ALPS_TSBB5_PAL_I 11
+
+#define TUNER_ALPS_TSBE5_PAL 12
+#define TUNER_ALPS_TSBC5_PAL 13
+#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */
+#define TUNER_ALPS_TSHC6_NTSC 15
+
+#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */
+#define TUNER_PHILIPS_NTSC_M 17
+#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */
+#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657) */
+
+#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711) */
+#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732) */
+#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104) */
#define TUNER_PHILIPS_PAL_DK 23
-#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */
-#define TUNER_LG_PAL_I_FM 25
-#define TUNER_LG_PAL_I 26
-#define TUNER_LG_NTSC_FM 27
+#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */
+#define TUNER_LG_PAL_I_FM 25
+#define TUNER_LG_PAL_I 26
+#define TUNER_LG_NTSC_FM 27
-#define TUNER_LG_PAL_FM 28
-#define TUNER_LG_PAL 29
-#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
-#define TUNER_SHARP_2U5JF5540_NTSC 31
+#define TUNER_LG_PAL_FM 28
+#define TUNER_LG_PAL 29
+#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163) */
+#define TUNER_SHARP_2U5JF5540_NTSC 31
-#define TUNER_Samsung_PAL_TCPM9091PD27 32
-#define TUNER_MT2032 33
-#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/
-#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/
+#define TUNER_Samsung_PAL_TCPM9091PD27 32
+#define TUNER_MT2032 33
+#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865) */
+#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099) */
-#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/
-#define TUNER_LG_PAL_NEW_TAPC 37
-#define TUNER_PHILIPS_FM1216ME_MK3 38
-#define TUNER_LG_NTSC_NEW_TAPC 39
+#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746) */
+#define TUNER_LG_PAL_NEW_TAPC 37
+#define TUNER_PHILIPS_FM1216ME_MK3 38
+#define TUNER_LG_NTSC_NEW_TAPC 39
-#define TUNER_HITACHI_NTSC 40
-#define TUNER_PHILIPS_PAL_MK 41
-#define TUNER_PHILIPS_ATSC 42
-#define TUNER_PHILIPS_FM1236_MK3 43
+#define TUNER_HITACHI_NTSC 40
+#define TUNER_PHILIPS_PAL_MK 41
+#define TUNER_PHILIPS_ATSC 42
+#define TUNER_PHILIPS_FM1236_MK3 43
-#define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */
+#define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */
/* Microtune mergeged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
-#define TUNER_MICROTUNE_4049FM5 45
-#define TUNER_LG_NTSC_TAPE 47
-
-#define TUNER_TNF_8831BGFF 48
-#define TUNER_MICROTUNE_4042FI5 49 /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */
-#define TUNER_TCL_2002N 50
-#define TUNER_PHILIPS_FM1256_IH3 51
-
-#define TUNER_THOMSON_DTT7610 52
-#define TUNER_PHILIPS_FQ1286 53
-#define TUNER_PHILIPS_TDA8290 54
-#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */
-
-#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
-#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */
-
-#define TUNER_YMEC_TVF_8531MF 58
-#define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */
-#define TUNER_THOMSON_DTT7611 60 /* DViCO FusionHDTV 3 Gold-T */
-#define TUNER_TENA_9533_DI 61
-
-#define TUNER_TEA5767 62 /* Only FM Radio Tuner */
-#define TUNER_PHILIPS_FMD1216ME_MK3 63
-#define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */
-#define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */
+#define TUNER_MICROTUNE_4049FM5 45
+#define TUNER_MICROTUNE_4042_FI5 46
+#define TUNER_LG_NTSC_TAPE 47
+
+#define TUNER_TNF_8831BGFF 48
+#define TUNER_MICROTUNE_4042FI5 49 /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */
+#define TUNER_TCL_2002N 50
+#define TUNER_PHILIPS_FM1256_IH3 51
+
+#define TUNER_THOMSON_DTT7610 52
+#define TUNER_PHILIPS_FQ1286 53
+#define TUNER_PHILIPS_TDA8290 54
+#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */
+
+#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
+#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */
+#define TUNER_YMEC_TVF_8531MF 58
+#define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */
+
+#define TUNER_THOMSON_DTT7611 60 /* DViCO FusionHDTV 3 Gold-T */
+#define TUNER_TENA_9533_DI 61
+#define TUNER_TEA5767 62 /* Only FM Radio Tuner */
+#define TUNER_PHILIPS_FMD1216ME_MK3 63
+
+#define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */
+#define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */
+#define TUNER_LG_NTSC_TALN_MINI 66
#define NOTUNER 0
#define PAL 1 /* PAL_BG */
@@ -117,7 +117,7 @@
#define NTSC 3
#define SECAM 4
#define ATSC 5
-#define RADIO 6
+#define RADIO 6
#define NoTuner 0
#define Philips 1
@@ -134,6 +134,7 @@
#define THOMSON 12
#define TUNER_SET_TYPE_ADDR _IOW('T',3,int)
+#define TUNER_SET_STANDBY _IOW('T',4,int)
#define TDA9887_SET_CONFIG _IOW('t',5,int)
/* tv card specific */
@@ -153,9 +154,6 @@
#ifdef __KERNEL__
-#define I2C_ADDR_TDA8290 0x4b
-#define I2C_ADDR_TDA8275 0x61
-
enum tuner_mode {
T_UNINITIALIZED = 0,
T_RADIO = 1 << V4L2_TUNER_RADIO,
@@ -165,21 +163,21 @@ enum tuner_mode {
};
struct tuner_setup {
- unsigned short addr;
- unsigned int type;
- unsigned int mode_mask;
+ unsigned short addr;
+ unsigned int type;
+ unsigned int mode_mask;
};
struct tuner {
/* device */
struct i2c_client i2c;
- unsigned int type; /* chip type */
+ unsigned int type; /* chip type */
- unsigned int mode;
- unsigned int mode_mask; /* Combination of allowable modes */
+ unsigned int mode;
+ unsigned int mode_mask; /* Combination of allowable modes */
- unsigned int freq; /* keep track of the current settings */
+ unsigned int freq; /* keep track of the current settings */
unsigned int audmode;
v4l2_std_id std;
@@ -198,6 +196,7 @@ struct tuner {
void (*radio_freq)(struct i2c_client *c, unsigned int freq);
int (*has_signal)(struct i2c_client *c);
int (*is_stereo)(struct i2c_client *c);
+ void (*standby)(struct i2c_client *c);
};
extern unsigned int tuner_debug;
@@ -209,16 +208,20 @@ extern int tea5767_tuner_init(struct i2c_client *c);
extern int default_tuner_init(struct i2c_client *c);
extern int tea5767_autodetection(struct i2c_client *c);
-#define tuner_warn(fmt, arg...) \
- dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg)
-#define tuner_info(fmt, arg...) \
- dev_printk(KERN_INFO , &t->i2c.dev , fmt , ## arg)
-#define tuner_dbg(fmt, arg...) \
- if (tuner_debug) dev_printk(KERN_DEBUG , &t->i2c.dev , fmt , ## arg)
+#define tuner_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \
+ t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
+#define tuner_info(fmt, arg...) do {\
+ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \
+ t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
+#define tuner_dbg(fmt, arg...) do {\
+ if (tuner_debug) \
+ printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \
+ t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
#endif /* __KERNEL__ */
-#endif
+#endif /* _TUNER_H */
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index 854a2c2f105b..e2035c7da094 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -1,18 +1,21 @@
/*
- * $Id: tveeprom.h,v 1.2 2005/06/12 04:19:19 mchehab Exp $
*/
struct tveeprom {
u32 has_radio;
+ u32 has_ir; /* 0: no IR, 1: IR present, 2: unknown */
u32 tuner_type;
u32 tuner_formats;
+ u32 tuner2_type;
+ u32 tuner2_formats;
+
u32 digitizer;
u32 digitizer_formats;
u32 audio_processor;
- /* a_p_fmts? */
+ u32 decoder_processor;
u32 model;
u32 revision;
@@ -20,7 +23,7 @@ struct tveeprom {
char rev_str[5];
};
-void tveeprom_hauppauge_analog(struct tveeprom *tvee,
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
unsigned char *eeprom_data);
int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len);
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index ae6da6de98de..ae8d7a000440 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -1,5 +1,4 @@
/*
- * $Id: video-buf.h,v 1.9 2004/11/07 13:17:15 kraxel Exp $
*
* generic helper functions for video4linux capture buffers, to handle
* memory management and PCI DMA. Right now bttv + saa7134 use it.
diff --git a/include/net/act_api.h b/include/net/act_api.h
index ed00a995f576..b55eb7c7f033 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -63,7 +63,7 @@ struct tc_action_ops
__u32 type; /* TBD to match kind */
__u32 capab; /* capabilities includes 4 bit version */
struct module *owner;
- int (*act)(struct sk_buff **, struct tc_action *);
+ int (*act)(struct sk_buff **, struct tc_action *, struct tcf_result *);
int (*get_stats)(struct sk_buff *, struct tc_action *);
int (*dump)(struct sk_buff *, struct tc_action *,int , int);
int (*cleanup)(struct tc_action *, int bind);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index a0ed93672176..750e2508dd90 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -45,6 +45,7 @@ struct prefix_info {
#ifdef __KERNEL__
+#include <linux/config.h>
#include <linux/netdevice.h>
#include <net/if_inet6.h>
#include <net/ipv6.h>
@@ -238,5 +239,10 @@ static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
addr->s6_addr32[3] == htonl(0x00000002));
}
+#ifdef CONFIG_PROC_FS
+extern int if6_proc_init(void);
+extern void if6_proc_exit(void);
+#endif
+
#endif
#endif
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index b60b3846b9d1..b5d785ab4a0e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -1,5 +1,11 @@
#ifndef __LINUX_NET_AFUNIX_H
#define __LINUX_NET_AFUNIX_H
+
+#include <linux/config.h>
+#include <linux/socket.h>
+#include <linux/un.h>
+#include <net/sock.h>
+
extern void unix_inflight(struct file *fp);
extern void unix_notinflight(struct file *fp);
extern void unix_gc(void);
@@ -74,5 +80,14 @@ struct unix_sock {
wait_queue_head_t peer_wait;
};
#define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+#ifdef CONFIG_SYSCTL
+extern int sysctl_unix_max_dgram_qlen;
+extern void unix_sysctl_register(void);
+extern void unix_sysctl_unregister(void);
+#else
+static inline void unix_sysctl_register(void) {}
+static inline void unix_sysctl_unregister(void) {}
+#endif
#endif
#endif
diff --git a/include/net/arp.h b/include/net/arp.h
index a1f09fad6a52..a13e30c35f42 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -11,7 +11,7 @@ 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 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 3696f988a9f1..9dbcd9e51c00 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -26,11 +26,20 @@
/* AX.25 Protocol IDs */
#define AX25_P_ROSE 0x01
-#define AX25_P_IP 0xCC
-#define AX25_P_ARP 0xCD
-#define AX25_P_TEXT 0xF0
-#define AX25_P_NETROM 0xCF
-#define AX25_P_SEGMENT 0x08
+#define AX25_P_VJCOMP 0x06 /* Compressed TCP/IP packet */
+ /* Van Jacobsen (RFC 1144) */
+#define AX25_P_VJUNCOMP 0x07 /* Uncompressed TCP/IP packet */
+ /* Van Jacobsen (RFC 1144) */
+#define AX25_P_SEGMENT 0x08 /* Segmentation fragment */
+#define AX25_P_TEXNET 0xc3 /* TEXTNET datagram protocol */
+#define AX25_P_LQ 0xc4 /* Link Quality Protocol */
+#define AX25_P_ATALK 0xca /* Appletalk */
+#define AX25_P_ATALK_ARP 0xcb /* Appletalk ARP */
+#define AX25_P_IP 0xcc /* ARPA Internet Protocol */
+#define AX25_P_ARP 0xcd /* ARPA Adress Resolution */
+#define AX25_P_FLEXNET 0xce /* FlexNet */
+#define AX25_P_NETROM 0xcf /* NET/ROM */
+#define AX25_P_TEXT 0xF0 /* No layer 3 protocol impl. */
/* AX.25 Segment control values */
#define AX25_SEG_REM 0x7F
@@ -88,11 +97,11 @@
/* Define Link State constants. */
enum {
- AX25_STATE_0,
- AX25_STATE_1,
- AX25_STATE_2,
- AX25_STATE_3,
- AX25_STATE_4
+ AX25_STATE_0, /* Listening */
+ AX25_STATE_1, /* SABM sent */
+ AX25_STATE_2, /* DISC sent */
+ AX25_STATE_3, /* Established */
+ AX25_STATE_4 /* Recovery */
};
#define AX25_MODULUS 8 /* Standard AX.25 modulus */
@@ -257,8 +266,8 @@ extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
/* ax25_addr.c */
extern ax25_address null_ax25_address;
-extern char *ax2asc(ax25_address *);
-extern ax25_address *asc2ax(char *);
+extern char *ax2asc(char *buf, ax25_address *);
+extern void asc2ax(ax25_address *addr, char *callsign);
extern int ax25cmp(ax25_address *, ax25_address *);
extern int ax25digicmp(ax25_digi *, ax25_digi *);
extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *);
@@ -316,10 +325,10 @@ extern int ax25_protocol_is_registered(unsigned int);
/* ax25_in.c */
extern int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
-extern int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
+extern int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
/* ax25_ip.c */
-extern int ax25_encapsulate(struct sk_buff *, struct net_device *, unsigned short, void *, void *, unsigned int);
+extern int ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short, void *, void *, unsigned int);
extern int ax25_rebuild_header(struct sk_buff *);
/* ax25_out.c */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 06b24f637026..6dfa4a61ffd0 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -131,11 +131,12 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
struct bt_skb_cb {
- int incoming;
+ __u8 pkt_type;
+ __u8 incoming;
};
#define bt_cb(skb) ((struct bt_skb_cb *)(skb->cb))
-static inline struct sk_buff *bt_skb_alloc(unsigned int len, int how)
+static inline struct sk_buff *bt_skb_alloc(unsigned int len, unsigned int __nocast how)
{
struct sk_buff *skb;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 6f0706f4af68..371e7d3f2e6f 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -453,6 +453,15 @@ struct inquiry_info_with_rssi {
__u16 clock_offset;
__s8 rssi;
} __attribute__ ((packed));
+struct inquiry_info_with_rssi_and_pscan_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 pscan_mode;
+ __u8 dev_class[3];
+ __u16 clock_offset;
+ __s8 rssi;
+} __attribute__ ((packed));
#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
@@ -584,6 +593,12 @@ struct hci_ev_clock_offset {
__u16 clock_offset;
} __attribute__ ((packed));
+#define HCI_EV_PSCAN_REP_MODE 0x20
+struct hci_ev_pscan_rep_mode {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+} __attribute__ ((packed));
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xFD
struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6d63a47c731b..7f933f302078 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -404,7 +404,7 @@ static inline int hci_recv_frame(struct sk_buff *skb)
bt_cb(skb)->incoming = 1;
/* Time stamp */
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
/* Queue frame for rx task */
skb_queue_tail(&hdev->rx_q, skb);
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 13669bad00b3..ffea9d54071f 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -80,9 +80,9 @@
#define RFCOMM_RPN_STOP_15 1
#define RFCOMM_RPN_PARITY_NONE 0x0
-#define RFCOMM_RPN_PARITY_ODD 0x4
-#define RFCOMM_RPN_PARITY_EVEN 0x5
-#define RFCOMM_RPN_PARITY_MARK 0x6
+#define RFCOMM_RPN_PARITY_ODD 0x1
+#define RFCOMM_RPN_PARITY_EVEN 0x3
+#define RFCOMM_RPN_PARITY_MARK 0x5
#define RFCOMM_RPN_PARITY_SPACE 0x7
#define RFCOMM_RPN_FLOW_NONE 0x00
@@ -223,8 +223,14 @@ struct rfcomm_dlc {
#define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
+/* ---- RFCOMM SEND RPN ---- */
+int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
+ u8 bit_rate, u8 data_bits, u8 stop_bits,
+ u8 parity, u8 flow_ctrl_settings,
+ u8 xon_char, u8 xoff_char, u16 param_mask);
+
/* ---- RFCOMM DLCs (channels) ---- */
-struct rfcomm_dlc *rfcomm_dlc_alloc(int prio);
+struct rfcomm_dlc *rfcomm_dlc_alloc(unsigned int __nocast prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
diff --git a/include/net/compat.h b/include/net/compat.h
index 9983fd857804..290bab46d457 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -33,7 +33,8 @@ extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsi
extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
-extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, unsigned char *,
- int);
+
+struct sock;
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
#endif /* NET_COMPAT_H */
diff --git a/include/net/datalink.h b/include/net/datalink.h
index 5797ba3d2eb5..deb7ca75db48 100644
--- a/include/net/datalink.h
+++ b/include/net/datalink.h
@@ -9,7 +9,7 @@ struct datalink_proto {
unsigned short header_length;
int (*rcvfunc)(struct sk_buff *, struct net_device *,
- struct packet_type *);
+ struct packet_type *, struct net_device *);
int (*request)(struct datalink_proto *, struct sk_buff *,
unsigned char *);
struct list_head node;
diff --git a/include/net/dn.h b/include/net/dn.h
index 5551c46db397..c1dbbd222793 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -3,6 +3,7 @@
#include <linux/dn.h>
#include <net/sock.h>
+#include <net/tcp.h>
#include <asm/byteorder.h>
typedef unsigned short dn_address;
diff --git a/include/net/icmp.h b/include/net/icmp.h
index e5ef0d15fb45..6cdebeee5f96 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -57,4 +57,11 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
return (struct raw_sock *)sk;
}
+extern int sysctl_icmp_echo_ignore_all;
+extern int sysctl_icmp_echo_ignore_broadcasts;
+extern int sysctl_icmp_ignore_bogus_error_responses;
+extern int sysctl_icmp_errors_use_inbound_ifaddr;
+extern int sysctl_icmp_ratelimit;
+extern int sysctl_icmp_ratemask;
+
#endif /* _ICMP_H */
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index db09580ad14b..dc36b1be6745 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -20,18 +20,9 @@
*/
#ifndef IEEE80211_H
#define IEEE80211_H
-
#include <linux/if_ether.h> /* ETH_ALEN */
#include <linux/kernel.h> /* ARRAY_SIZE */
-
-#if WIRELESS_EXT < 17
-#define IW_QUAL_QUAL_INVALID 0x10
-#define IW_QUAL_LEVEL_INVALID 0x20
-#define IW_QUAL_NOISE_INVALID 0x40
-#define IW_QUAL_QUAL_UPDATED 0x1
-#define IW_QUAL_LEVEL_UPDATED 0x2
-#define IW_QUAL_NOISE_UPDATED 0x4
-#endif
+#include <linux/wireless.h>
#define IEEE80211_DATA_LEN 2304
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
@@ -47,51 +38,22 @@
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
struct ieee80211_hdr {
- u16 frame_ctl;
- u16 duration_id;
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
+ __le16 seq_ctl;
u8 addr4[ETH_ALEN];
} __attribute__ ((packed));
struct ieee80211_hdr_3addr {
- u16 frame_ctl;
- u16 duration_id;
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
-} __attribute__ ((packed));
-
-enum eap_type {
- EAP_PACKET = 0,
- EAPOL_START,
- EAPOL_LOGOFF,
- EAPOL_KEY,
- EAPOL_ENCAP_ASF_ALERT
-};
-
-static const char *eap_types[] = {
- [EAP_PACKET] = "EAP-Packet",
- [EAPOL_START] = "EAPOL-Start",
- [EAPOL_LOGOFF] = "EAPOL-Logoff",
- [EAPOL_KEY] = "EAPOL-Key",
- [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
-};
-
-static inline const char *eap_get_type(int type)
-{
- return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
-}
-
-struct eapol {
- u8 snap[6];
- u16 ethertype;
- u8 version;
- u8 type;
- u16 length;
+ __le16 seq_ctl;
} __attribute__ ((packed));
#define IEEE80211_1ADDR_LEN 10
@@ -104,7 +66,7 @@ struct eapol {
#define MAX_FRAG_THRESHOLD 2346U
/* Frame control field constants */
-#define IEEE80211_FCTL_VERS 0x0002
+#define IEEE80211_FCTL_VERS 0x0003
#define IEEE80211_FCTL_FTYPE 0x000c
#define IEEE80211_FCTL_STYPE 0x00f0
#define IEEE80211_FCTL_TODS 0x0100
@@ -112,8 +74,8 @@ struct eapol {
#define IEEE80211_FCTL_MOREFRAGS 0x0400
#define IEEE80211_FCTL_RETRY 0x0800
#define IEEE80211_FCTL_PM 0x1000
-#define IEEE80211_FCTL_MOREDATA 0x2000
-#define IEEE80211_FCTL_WEP 0x4000
+#define IEEE80211_FCTL_MOREDATA 0x2000
+#define IEEE80211_FCTL_PROTECTED 0x4000
#define IEEE80211_FCTL_ORDER 0x8000
#define IEEE80211_FTYPE_MGMT 0x0000
@@ -132,6 +94,7 @@ struct eapol {
#define IEEE80211_STYPE_DISASSOC 0x00A0
#define IEEE80211_STYPE_AUTH 0x00B0
#define IEEE80211_STYPE_DEAUTH 0x00C0
+#define IEEE80211_STYPE_ACTION 0x00D0
/* control */
#define IEEE80211_STYPE_PSPOLL 0x00A0
@@ -167,8 +130,19 @@ do { if (ieee80211_debug_level & (level)) \
#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
#endif /* CONFIG_IEEE80211_DEBUG */
+
+/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
+
+/* escape_essid() is intended to be used in debug (and possibly error)
+ * messages. It should never be used for passing essid to user space. */
+const char *escape_essid(const char *essid, u8 essid_len);
+
+
/*
- * To use the debug system;
+ * To use the debug system:
*
* If you are defining a new debug classification, simply add it to the #define
* list here in the form of:
@@ -184,11 +158,11 @@ do { if (ieee80211_debug_level & (level)) \
*
* To add your debug level to the list of levels seen when you perform
*
- * % cat /proc/net/ipw/debug_level
+ * % cat /proc/net/ieee80211/debug_level
*
- * you simply need to add your entry to the ipw_debug_levels array.
+ * you simply need to add your entry to the ieee80211_debug_level array.
*
- * If you do not see debug_level in /proc/net/ipw then you do not have
+ * If you do not see debug_level in /proc/net/ieee80211 then you do not have
* CONFIG_IEEE80211_DEBUG defined in your kernel configuration
*
*/
@@ -199,7 +173,6 @@ do { if (ieee80211_debug_level & (level)) \
#define IEEE80211_DL_STATE (1<<3)
#define IEEE80211_DL_MGMT (1<<4)
#define IEEE80211_DL_FRAG (1<<5)
-#define IEEE80211_DL_EAP (1<<6)
#define IEEE80211_DL_DROP (1<<7)
#define IEEE80211_DL_TX (1<<8)
@@ -214,7 +187,6 @@ do { if (ieee80211_debug_level & (level)) \
#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
-#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
@@ -223,9 +195,9 @@ do { if (ieee80211_debug_level & (level)) \
#include <linux/if_arp.h> /* ARPHRD_ETHER */
#ifndef WIRELESS_SPY
-#define WIRELESS_SPY // enable iwspy support
+#define WIRELESS_SPY /* enable iwspy support */
#endif
-#include <net/iw_handler.h> // new driver API
+#include <net/iw_handler.h> /* new driver API */
#ifndef ETH_P_PAE
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
@@ -252,6 +224,7 @@ struct ieee80211_snap_hdr {
#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
@@ -264,7 +237,7 @@ struct ieee80211_snap_hdr {
#define WLAN_AUTH_CHALLENGE_LEN 128
-#define WLAN_CAPABILITY_BSS (1<<0)
+#define WLAN_CAPABILITY_ESS (1<<0)
#define WLAN_CAPABILITY_IBSS (1<<1)
#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
@@ -272,34 +245,72 @@ struct ieee80211_snap_hdr {
#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
#define WLAN_CAPABILITY_PBCC (1<<6)
#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
+#define WLAN_CAPABILITY_OSSS_OFDM (1<<13)
/* Status codes */
-#define WLAN_STATUS_SUCCESS 0
-#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
-#define WLAN_STATUS_CAPS_UNSUPPORTED 10
-#define WLAN_STATUS_REASSOC_NO_ASSOC 11
-#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
-#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
-#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
-#define WLAN_STATUS_CHALLENGE_FAIL 15
-#define WLAN_STATUS_AUTH_TIMEOUT 16
-#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
-#define WLAN_STATUS_ASSOC_DENIED_RATES 18
-/* 802.11b */
-#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
-#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
-#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+enum ieee80211_statuscode {
+ WLAN_STATUS_SUCCESS = 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
+ WLAN_STATUS_CAPS_UNSUPPORTED = 10,
+ WLAN_STATUS_REASSOC_NO_ASSOC = 11,
+ WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
+ WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
+ WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
+ WLAN_STATUS_CHALLENGE_FAIL = 15,
+ WLAN_STATUS_AUTH_TIMEOUT = 16,
+ WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+ WLAN_STATUS_ASSOC_DENIED_RATES = 18,
+ /* 802.11b */
+ WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
+ WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
+ WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
+ /* 802.11h */
+ WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
+ WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
+ WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
+ /* 802.11g */
+ WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
+ WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+ /* 802.11i */
+ WLAN_STATUS_INVALID_IE = 40,
+ WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
+ WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
+ WLAN_STATUS_INVALID_AKMP = 43,
+ WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
+ WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
+ WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
+};
/* Reason codes */
-#define WLAN_REASON_UNSPECIFIED 1
-#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
-#define WLAN_REASON_DEAUTH_LEAVING 3
-#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
-#define WLAN_REASON_DISASSOC_AP_BUSY 5
-#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
-#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
-#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
-#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+enum ieee80211_reasoncode {
+ WLAN_REASON_UNSPECIFIED = 1,
+ WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+ WLAN_REASON_DEAUTH_LEAVING = 3,
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
+ WLAN_REASON_DISASSOC_AP_BUSY = 5,
+ WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+ WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
+ WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+ /* 802.11h */
+ WLAN_REASON_DISASSOC_BAD_POWER = 10,
+ WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
+ /* 802.11i */
+ WLAN_REASON_INVALID_IE = 13,
+ WLAN_REASON_MIC_FAILURE = 14,
+ WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
+ WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
+ WLAN_REASON_IE_DIFFERENT = 17,
+ WLAN_REASON_INVALID_GROUP_CIPHER = 18,
+ WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
+ WLAN_REASON_INVALID_AKMP = 20,
+ WLAN_REASON_UNSUPP_RSN_VERSION = 21,
+ WLAN_REASON_INVALID_RSN_IE_CAP = 22,
+ WLAN_REASON_IEEE8021X_FAILED = 23,
+ WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
+};
#define IEEE80211_STATMASK_SIGNAL (1<<0)
@@ -426,9 +437,7 @@ struct ieee80211_stats {
struct ieee80211_device;
-#if 0 /* for later */
#include "ieee80211_crypt.h"
-#endif
#define SEC_KEY_1 (1<<0)
#define SEC_KEY_2 (1<<1)
@@ -480,17 +489,34 @@ Total: 28-2340 bytes
#define BEACON_PROBE_SSID_ID_POSITION 12
/* Management Frame Information Element Types */
-#define MFIE_TYPE_SSID 0
-#define MFIE_TYPE_RATES 1
-#define MFIE_TYPE_FH_SET 2
-#define MFIE_TYPE_DS_SET 3
-#define MFIE_TYPE_CF_SET 4
-#define MFIE_TYPE_TIM 5
-#define MFIE_TYPE_IBSS_SET 6
-#define MFIE_TYPE_CHALLENGE 16
-#define MFIE_TYPE_RSN 48
-#define MFIE_TYPE_RATES_EX 50
-#define MFIE_TYPE_GENERIC 221
+enum ieee80211_mfie {
+ MFIE_TYPE_SSID = 0,
+ MFIE_TYPE_RATES = 1,
+ MFIE_TYPE_FH_SET = 2,
+ MFIE_TYPE_DS_SET = 3,
+ MFIE_TYPE_CF_SET = 4,
+ MFIE_TYPE_TIM = 5,
+ MFIE_TYPE_IBSS_SET = 6,
+ MFIE_TYPE_COUNTRY = 7,
+ MFIE_TYPE_HOP_PARAMS = 8,
+ MFIE_TYPE_HOP_TABLE = 9,
+ MFIE_TYPE_REQUEST = 10,
+ MFIE_TYPE_CHALLENGE = 16,
+ MFIE_TYPE_POWER_CONSTRAINT = 32,
+ MFIE_TYPE_POWER_CAPABILITY = 33,
+ MFIE_TYPE_TPC_REQUEST = 34,
+ MFIE_TYPE_TPC_REPORT = 35,
+ MFIE_TYPE_SUPP_CHANNELS = 36,
+ MFIE_TYPE_CSA = 37,
+ MFIE_TYPE_MEASURE_REQUEST = 38,
+ MFIE_TYPE_MEASURE_REPORT = 39,
+ MFIE_TYPE_QUIET = 40,
+ MFIE_TYPE_IBSS_DFS = 41,
+ MFIE_TYPE_ERP_INFO = 42,
+ MFIE_TYPE_RSN = 48,
+ MFIE_TYPE_RATES_EX = 50,
+ MFIE_TYPE_GENERIC = 221,
+};
struct ieee80211_info_element_hdr {
u8 id;
@@ -522,9 +548,9 @@ struct ieee80211_info_element {
struct ieee80211_authentication {
struct ieee80211_hdr_3addr header;
- u16 algorithm;
- u16 transaction;
- u16 status;
+ __le16 algorithm;
+ __le16 transaction;
+ __le16 status;
struct ieee80211_info_element info_element;
} __attribute__ ((packed));
@@ -532,23 +558,23 @@ struct ieee80211_authentication {
struct ieee80211_probe_response {
struct ieee80211_hdr_3addr header;
u32 time_stamp[2];
- u16 beacon_interval;
- u16 capability;
+ __le16 beacon_interval;
+ __le16 capability;
struct ieee80211_info_element info_element;
} __attribute__ ((packed));
struct ieee80211_assoc_request_frame {
- u16 capability;
- u16 listen_interval;
+ __le16 capability;
+ __le16 listen_interval;
u8 current_ap[ETH_ALEN];
struct ieee80211_info_element info_element;
} __attribute__ ((packed));
struct ieee80211_assoc_response_frame {
struct ieee80211_hdr_3addr header;
- u16 capability;
- u16 status;
- u16 aid;
+ __le16 capability;
+ __le16 status;
+ __le16 aid;
struct ieee80211_info_element info_element; /* supported rates */
} __attribute__ ((packed));
@@ -563,7 +589,7 @@ struct ieee80211_txb {
};
-/* SWEEP TABLE ENTRIES NUMBER*/
+/* SWEEP TABLE ENTRIES NUMBER */
#define MAX_SWEEP_TAB_ENTRIES 42
#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
@@ -624,8 +650,6 @@ enum ieee80211_state {
#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
#define DEFAULT_FTS 2346
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
#define CFG_IEEE80211_RESERVE_FCS (1<<0)
@@ -793,8 +817,6 @@ extern struct net_device *alloc_ieee80211(int sizeof_priv);
extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
/* ieee80211_tx.c */
-
-
extern int ieee80211_xmit(struct sk_buff *skb,
struct net_device *dev);
extern void ieee80211_txb_free(struct ieee80211_txb *);
@@ -807,7 +829,7 @@ extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
struct ieee80211_hdr *header,
struct ieee80211_rx_stats *stats);
-/* iee80211_wx.c */
+/* ieee80211_wx.c */
extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *key);
@@ -829,28 +851,5 @@ extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
return ieee->scans;
}
-static inline const char *escape_essid(const char *essid, u8 essid_len) {
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (ieee80211_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
- return escaped;
-}
#endif /* IEEE80211_H */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
new file mode 100644
index 000000000000..b58a3bcc0dc0
--- /dev/null
+++ b/include/net/ieee80211_crypt.h
@@ -0,0 +1,86 @@
+/*
+ * Original code based on Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ *
+ * Copyright (c) 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. See README and COPYING for
+ * more details.
+ */
+
+/*
+ * This file defines the interface to the ieee80211 crypto module.
+ */
+#ifndef IEEE80211_CRYPT_H
+#define IEEE80211_CRYPT_H
+
+#include <linux/skbuff.h>
+
+struct ieee80211_crypto_ops {
+ const char *name;
+
+ /* init new crypto context (e.g., allocate private data space,
+ * select IV, etc.); returns NULL on failure or pointer to allocated
+ * private data on success */
+ void * (*init)(int keyidx);
+
+ /* deinitialize crypto context and free allocated private data */
+ void (*deinit)(void *priv);
+
+ /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
+ * value from decrypt_mpdu is passed as the keyidx value for
+ * decrypt_msdu. skb must have enough head and tail room for the
+ * encryption; if not, error will be returned; these functions are
+ * called for all MPDUs (i.e., fragments).
+ */
+ int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+ int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+
+ /* These functions are called for full MSDUs, i.e. full frames.
+ * These can be NULL if full MSDU operations are not needed. */
+ int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
+ int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
+ void *priv);
+
+ int (*set_key)(void *key, int len, u8 *seq, void *priv);
+ int (*get_key)(void *key, int len, u8 *seq, void *priv);
+
+ /* procfs handler for printing out key information and possible
+ * statistics */
+ char * (*print_stats)(char *p, void *priv);
+
+ /* maximum number of bytes added by encryption; encrypt buf is
+ * allocated with extra_prefix_len bytes, copy of in_buf, and
+ * extra_postfix_len; encrypt need not use all this space, but
+ * the result must start at the beginning of the buffer and correct
+ * length must be returned */
+ int extra_prefix_len, extra_postfix_len;
+
+ struct module *owner;
+};
+
+struct ieee80211_crypt_data {
+ struct list_head list; /* delayed deletion list */
+ struct ieee80211_crypto_ops *ops;
+ void *priv;
+ atomic_t refcnt;
+};
+
+int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
+int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
+struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
+void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
+void ieee80211_crypt_deinit_handler(unsigned long);
+void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
+ struct ieee80211_crypt_data **crypt);
+
+#endif
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
new file mode 100644
index 000000000000..03df3b157960
--- /dev/null
+++ b/include/net/inet6_hashtables.h
@@ -0,0 +1,130 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 _INET6_HASHTABLES_H
+#define _INET6_HASHTABLES_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/types.h>
+
+#include <net/ipv6.h>
+
+struct inet_hashinfo;
+
+/* I have no idea if this is a good hash for v6 or not. -DaveM */
+static inline int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
+ const struct in6_addr *faddr, const u16 fport,
+ const int ehash_size)
+{
+ int hashent = (lport ^ fport);
+
+ hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
+ hashent ^= hashent >> 16;
+ hashent ^= hashent >> 8;
+ return (hashent & (ehash_size - 1));
+}
+
+static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ const struct in6_addr *laddr = &np->rcv_saddr;
+ const struct in6_addr *faddr = &np->daddr;
+ const __u16 lport = inet->num;
+ const __u16 fport = inet->dport;
+ return inet6_ehashfn(laddr, lport, faddr, fport, ehash_size);
+}
+
+/*
+ * 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.
+ */
+static inline 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.
+ */
+ const int hash = inet6_ehashfn(daddr, hnum, saddr, sport,
+ hashinfo->ehash_size);
+ struct inet_ehash_bucket *head = &hashinfo->ehash[hash];
+
+ 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, 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 tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
+
+ if (ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tcp6tw->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;
+}
+
+extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *daddr,
+ const unsigned short hnum,
+ const int dif);
+
+static inline struct sock *__inet6_lookup(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 = __inet6_lookup_established(hashinfo, saddr, sport,
+ daddr, hnum, dif);
+ if (sk)
+ return sk;
+
+ return inet6_lookup_listener(hashinfo, daddr, hnum, dif);
+}
+
+extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr, const u16 sport,
+ const struct in6_addr *daddr, const u16 dport,
+ const int dif);
+#endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */
+#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index fbc1f4d140d8..f943306ce5ff 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -8,6 +8,11 @@ extern struct proto_ops inet_dgram_ops;
* INET4 prototypes used by INET6
*/
+struct msghdr;
+struct sock;
+struct sockaddr;
+struct socket;
+
extern void inet_remove_sock(struct sock *sk1);
extern void inet_put_sock(unsigned short num,
struct sock *sk);
@@ -29,7 +34,6 @@ extern unsigned int inet_poll(struct file * file, struct socket *sock, struct p
extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_destruct(struct sock *sk);
-extern atomic_t inet_sock_nr;
extern int inet_bind(struct socket *sock,
struct sockaddr *uaddr, int addr_len);
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
new file mode 100644
index 000000000000..651f824c1008
--- /dev/null
+++ b/include/net/inet_connection_sock.h
@@ -0,0 +1,276 @@
+/*
+ * NET Generic infrastructure for INET connection oriented protocols.
+ *
+ * Definitions for inet_connection_sock
+ *
+ * Authors: Many people, see the TCP sources
+ *
+ * From code originally in TCP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 _INET_CONNECTION_SOCK_H
+#define _INET_CONNECTION_SOCK_H
+
+#include <linux/ip.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <net/request_sock.h>
+
+#define INET_CSK_DEBUG 1
+
+/* Cancel timers, when they are not required. */
+#undef INET_CSK_CLEAR_TIMERS
+
+struct inet_bind_bucket;
+struct inet_hashinfo;
+struct tcp_congestion_ops;
+
+/** inet_connection_sock - INET connection oriented sock
+ *
+ * @icsk_accept_queue: FIFO of established children
+ * @icsk_bind_hash: Bind node
+ * @icsk_timeout: Timeout
+ * @icsk_retransmit_timer: Resend (no ack)
+ * @icsk_rto: Retransmit timeout
+ * @icsk_ca_ops Pluggable congestion control hook
+ * @icsk_ca_state: Congestion control state
+ * @icsk_retransmits: Number of unrecovered [RTO] timeouts
+ * @icsk_pending: Scheduled timer event
+ * @icsk_backoff: Backoff
+ * @icsk_syn_retries: Number of allowed SYN (or equivalent) retries
+ * @icsk_probes_out: unanswered 0 window probes
+ * @icsk_ack: Delayed ACK control data
+ */
+struct inet_connection_sock {
+ /* inet_sock has to be the first member! */
+ struct inet_sock icsk_inet;
+ struct request_sock_queue icsk_accept_queue;
+ struct inet_bind_bucket *icsk_bind_hash;
+ unsigned long icsk_timeout;
+ struct timer_list icsk_retransmit_timer;
+ struct timer_list icsk_delack_timer;
+ __u32 icsk_rto;
+ struct tcp_congestion_ops *icsk_ca_ops;
+ __u8 icsk_ca_state;
+ __u8 icsk_retransmits;
+ __u8 icsk_pending;
+ __u8 icsk_backoff;
+ __u8 icsk_syn_retries;
+ __u8 icsk_probes_out;
+ /* 2 BYTES HOLE, TRY TO PACK! */
+ struct {
+ __u8 pending; /* ACK is pending */
+ __u8 quick; /* Scheduled number of quick acks */
+ __u8 pingpong; /* The session is interactive */
+ __u8 blocked; /* Delayed ACK was blocked by socket lock */
+ __u32 ato; /* Predicted tick of soft clock */
+ unsigned long timeout; /* Currently scheduled timeout */
+ __u32 lrcvtime; /* timestamp of last received data packet */
+ __u16 last_seg_size; /* Size of last incoming segment */
+ __u16 rcv_mss; /* MSS used for delayed ACK decisions */
+ } icsk_ack;
+ u32 icsk_ca_priv[16];
+#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32))
+};
+
+#define ICSK_TIME_RETRANS 1 /* Retransmit timer */
+#define ICSK_TIME_DACK 2 /* Delayed ack timer */
+#define ICSK_TIME_PROBE0 3 /* Zero window probe timer */
+#define ICSK_TIME_KEEPOPEN 4 /* Keepalive timer */
+
+static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
+{
+ return (struct inet_connection_sock *)sk;
+}
+
+static inline void *inet_csk_ca(const struct sock *sk)
+{
+ return (void *)inet_csk(sk)->icsk_ca_priv;
+}
+
+extern struct sock *inet_csk_clone(struct sock *sk,
+ const struct request_sock *req,
+ const unsigned int __nocast priority);
+
+enum inet_csk_ack_state_t {
+ ICSK_ACK_SCHED = 1,
+ ICSK_ACK_TIMER = 2,
+ ICSK_ACK_PUSHED = 4
+};
+
+extern void inet_csk_init_xmit_timers(struct sock *sk,
+ void (*retransmit_handler)(unsigned long),
+ void (*delack_handler)(unsigned long),
+ void (*keepalive_handler)(unsigned long));
+extern void inet_csk_clear_xmit_timers(struct sock *sk);
+
+static inline void inet_csk_schedule_ack(struct sock *sk)
+{
+ inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_SCHED;
+}
+
+static inline int inet_csk_ack_scheduled(const struct sock *sk)
+{
+ return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
+}
+
+static inline void inet_csk_delack_init(struct sock *sk)
+{
+ memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
+}
+
+extern void inet_csk_delete_keepalive_timer(struct sock *sk);
+extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
+
+#ifdef INET_CSK_DEBUG
+extern const char inet_csk_timer_bug_msg[];
+#endif
+
+static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
+ icsk->icsk_pending = 0;
+#ifdef INET_CSK_CLEAR_TIMERS
+ sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
+#endif
+ } else if (what == ICSK_TIME_DACK) {
+ icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0;
+#ifdef INET_CSK_CLEAR_TIMERS
+ sk_stop_timer(sk, &icsk->icsk_delack_timer);
+#endif
+ }
+#ifdef INET_CSK_DEBUG
+ else {
+ pr_debug("%s", inet_csk_timer_bug_msg);
+ }
+#endif
+}
+
+/*
+ * Reset the retransmission timer
+ */
+static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
+ unsigned long when,
+ const unsigned long max_when)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (when > max_when) {
+#ifdef INET_CSK_DEBUG
+ pr_debug("reset_xmit_timer: sk=%p %d when=0x%lx, caller=%p\n",
+ sk, what, when, current_text_addr());
+#endif
+ when = max_when;
+ }
+
+ if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
+ icsk->icsk_pending = what;
+ icsk->icsk_timeout = jiffies + when;
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
+ } else if (what == ICSK_TIME_DACK) {
+ icsk->icsk_ack.pending |= ICSK_ACK_TIMER;
+ icsk->icsk_ack.timeout = jiffies + when;
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
+ }
+#ifdef INET_CSK_DEBUG
+ else {
+ pr_debug("%s", inet_csk_timer_bug_msg);
+ }
+#endif
+}
+
+extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
+
+extern struct request_sock *inet_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __u16 rport,
+ const __u32 raddr,
+ const __u32 laddr);
+extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+ struct sock *sk, unsigned short snum);
+
+extern struct dst_entry* inet_csk_route_req(struct sock *sk,
+ const struct request_sock *req);
+
+static inline void inet_csk_reqsk_queue_add(struct sock *sk,
+ struct request_sock *req,
+ struct sock *child)
+{
+ reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
+}
+
+extern void inet_csk_reqsk_queue_hash_add(struct sock *sk,
+ struct request_sock *req,
+ const unsigned timeout);
+
+static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
+ struct request_sock *req)
+{
+ if (reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req) == 0)
+ inet_csk_delete_keepalive_timer(sk);
+}
+
+static inline void inet_csk_reqsk_queue_added(struct sock *sk,
+ const unsigned long timeout)
+{
+ if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0)
+ inet_csk_reset_keepalive_timer(sk, timeout);
+}
+
+static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
+{
+ return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
+{
+ return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
+{
+ return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue);
+}
+
+static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
+ struct request_sock *req,
+ struct request_sock **prev)
+{
+ reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev);
+}
+
+static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
+ struct request_sock *req,
+ struct request_sock **prev)
+{
+ inet_csk_reqsk_queue_unlink(sk, req, prev);
+ inet_csk_reqsk_queue_removed(sk, req);
+ reqsk_free(req);
+}
+
+extern void inet_csk_reqsk_queue_prune(struct sock *parent,
+ const unsigned long interval,
+ const unsigned long timeout,
+ const unsigned long max_rto);
+
+extern void inet_csk_destroy_sock(struct sock *sk);
+
+/*
+ * LISTEN is a special case for poll..
+ */
+static inline unsigned int inet_csk_listen_poll(const struct sock *sk)
+{
+ return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ?
+ (POLLIN | POLLRDNORM) : 0;
+}
+
+extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
+extern void inet_csk_listen_stop(struct sock *sk);
+
+#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
new file mode 100644
index 000000000000..646b6ea7fe26
--- /dev/null
+++ b/include/net/inet_hashtables.h
@@ -0,0 +1,427 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 _INET_HASHTABLES_H
+#define _INET_HASHTABLES_H
+
+#include <linux/config.h>
+
+#include <linux/interrupt.h>
+#include <linux/ipv6.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/route.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+/* This is for all connections with a full identity, no wildcards.
+ * New scheme, half the table is for TIME_WAIT, the other half is
+ * for the rest. I'll experiment with dynamic table growth later.
+ */
+struct inet_ehash_bucket {
+ rwlock_t lock;
+ struct hlist_head chain;
+} __attribute__((__aligned__(8)));
+
+/* There are a few simple rules, which allow for local port reuse by
+ * an application. In essence:
+ *
+ * 1) Sockets bound to different interfaces may share a local port.
+ * Failing that, goto test 2.
+ * 2) If all sockets have sk->sk_reuse set, and none of them are in
+ * TCP_LISTEN state, the port may be shared.
+ * Failing that, goto test 3.
+ * 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local
+ * address, and none of them are the same, the port may be
+ * shared.
+ * Failing this, the port cannot be shared.
+ *
+ * The interesting point, is test #2. This is what an FTP server does
+ * all day. To optimize this case we use a specific flag bit defined
+ * below. As we add sockets to a bind bucket list, we perform a
+ * check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN))
+ * As long as all sockets added to a bind bucket pass this test,
+ * the flag bit will be set.
+ * The resulting situation is that tcp_v[46]_verify_bind() can just check
+ * for this flag bit, if it is set and the socket trying to bind has
+ * sk->sk_reuse set, we don't even have to walk the owners list at all,
+ * we return that it is ok to bind this socket to the requested local port.
+ *
+ * Sounds like a lot of work, but it is worth it. In a more naive
+ * implementation (ie. current FreeBSD etc.) the entire list of ports
+ * must be walked for each data port opened by an ftp server. Needless
+ * to say, this does not scale at all. With a couple thousand FTP
+ * users logged onto your box, isn't it nice to know that new data
+ * ports are created in O(1) time? I thought so. ;-) -DaveM
+ */
+struct inet_bind_bucket {
+ unsigned short port;
+ signed short fastreuse;
+ struct hlist_node node;
+ struct hlist_head owners;
+};
+
+#define inet_bind_bucket_for_each(tb, node, head) \
+ hlist_for_each_entry(tb, node, head, node)
+
+struct inet_bind_hashbucket {
+ spinlock_t lock;
+ struct hlist_head chain;
+};
+
+/* This is for listening sockets, thus all sockets which possess wildcards. */
+#define INET_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
+
+struct inet_hashinfo {
+ /* This is for sockets with full identity only. Sockets here will
+ * always be without wildcards and will have the following invariant:
+ *
+ * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
+ *
+ * First half of the table is for sockets not in TIME_WAIT, second half
+ * is for TIME_WAIT sockets only.
+ */
+ struct inet_ehash_bucket *ehash;
+
+ /* Ok, let's try this, I give up, we do need a local binding
+ * TCP hash as well as the others for fast bind/connect.
+ */
+ struct inet_bind_hashbucket *bhash;
+
+ int bhash_size;
+ int ehash_size;
+
+ /* All sockets in TCP_LISTEN state will be in here. This is the only
+ * table where wildcard'd TCP sockets can exist. Hash function here
+ * is just local port number.
+ */
+ struct hlist_head listening_hash[INET_LHTABLE_SIZE];
+
+ /* All the above members are written once at bootup and
+ * never written again _or_ are predominantly read-access.
+ *
+ * Now align to a new cache line as all the following members
+ * are often dirty.
+ */
+ rwlock_t lhash_lock ____cacheline_aligned;
+ atomic_t lhash_users;
+ wait_queue_head_t lhash_wait;
+ spinlock_t portalloc_lock;
+ kmem_cache_t *bind_bucket_cachep;
+ int port_rover;
+};
+
+static inline int inet_ehashfn(const __u32 laddr, const __u16 lport,
+ const __u32 faddr, const __u16 fport,
+ const int ehash_size)
+{
+ int h = (laddr ^ lport) ^ (faddr ^ fport);
+ h ^= h >> 16;
+ h ^= h >> 8;
+ return h & (ehash_size - 1);
+}
+
+static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const __u32 laddr = inet->rcv_saddr;
+ const __u16 lport = inet->num;
+ const __u32 faddr = inet->daddr;
+ const __u16 fport = inet->dport;
+
+ return inet_ehashfn(laddr, lport, faddr, fport, ehash_size);
+}
+
+extern struct inet_bind_bucket *
+ inet_bind_bucket_create(kmem_cache_t *cachep,
+ struct inet_bind_hashbucket *head,
+ const unsigned short snum);
+extern void inet_bind_bucket_destroy(kmem_cache_t *cachep,
+ struct inet_bind_bucket *tb);
+
+static inline int inet_bhashfn(const __u16 lport, const int bhash_size)
+{
+ return lport & (bhash_size - 1);
+}
+
+extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ const unsigned short snum);
+
+/* These can have wildcards, don't try too hard. */
+static inline int inet_lhashfn(const unsigned short num)
+{
+ return num & (INET_LHTABLE_SIZE - 1);
+}
+
+static inline int inet_sk_listen_hashfn(const struct sock *sk)
+{
+ return inet_lhashfn(inet_sk(sk)->num);
+}
+
+/* Caller must disable local BH processing. */
+static inline void __inet_inherit_port(struct inet_hashinfo *table,
+ struct sock *sk, struct sock *child)
+{
+ const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
+ struct inet_bind_hashbucket *head = &table->bhash[bhash];
+ struct inet_bind_bucket *tb;
+
+ spin_lock(&head->lock);
+ tb = inet_csk(sk)->icsk_bind_hash;
+ sk_add_bind_node(child, &tb->owners);
+ inet_csk(child)->icsk_bind_hash = tb;
+ spin_unlock(&head->lock);
+}
+
+static inline void inet_inherit_port(struct inet_hashinfo *table,
+ struct sock *sk, struct sock *child)
+{
+ local_bh_disable();
+ __inet_inherit_port(table, sk, child);
+ local_bh_enable();
+}
+
+extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
+
+extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
+
+/*
+ * - We may sleep inside this lock.
+ * - If sleeping is not required (or called from BH),
+ * use plain read_(un)lock(&inet_hashinfo.lhash_lock).
+ */
+static inline void inet_listen_lock(struct inet_hashinfo *hashinfo)
+{
+ /* read_lock synchronizes to candidates to writers */
+ read_lock(&hashinfo->lhash_lock);
+ atomic_inc(&hashinfo->lhash_users);
+ read_unlock(&hashinfo->lhash_lock);
+}
+
+static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
+{
+ if (atomic_dec_and_test(&hashinfo->lhash_users))
+ wake_up(&hashinfo->lhash_wait);
+}
+
+static inline void __inet_hash(struct inet_hashinfo *hashinfo,
+ struct sock *sk, const int listen_possible)
+{
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+ BUG_TRAP(sk_unhashed(sk));
+ if (listen_possible && sk->sk_state == TCP_LISTEN) {
+ list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+ lock = &hashinfo->lhash_lock;
+ inet_listen_wlock(hashinfo);
+ } else {
+ sk->sk_hashent = inet_sk_ehashfn(sk, hashinfo->ehash_size);
+ list = &hashinfo->ehash[sk->sk_hashent].chain;
+ lock = &hashinfo->ehash[sk->sk_hashent].lock;
+ write_lock(lock);
+ }
+ __sk_add_node(sk, list);
+ sock_prot_inc_use(sk->sk_prot);
+ write_unlock(lock);
+ if (listen_possible && sk->sk_state == TCP_LISTEN)
+ wake_up(&hashinfo->lhash_wait);
+}
+
+static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
+{
+ if (sk->sk_state != TCP_CLOSE) {
+ local_bh_disable();
+ __inet_hash(hashinfo, sk, 1);
+ local_bh_enable();
+ }
+}
+
+static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
+{
+ rwlock_t *lock;
+
+ if (sk_unhashed(sk))
+ goto out;
+
+ if (sk->sk_state == TCP_LISTEN) {
+ local_bh_disable();
+ inet_listen_wlock(hashinfo);
+ lock = &hashinfo->lhash_lock;
+ } else {
+ struct inet_ehash_bucket *head = &hashinfo->ehash[sk->sk_hashent];
+ lock = &head->lock;
+ write_lock_bh(&head->lock);
+ }
+
+ if (__sk_del_node_init(sk))
+ sock_prot_dec_use(sk->sk_prot);
+ write_unlock_bh(lock);
+out:
+ if (sk->sk_state == TCP_LISTEN)
+ wake_up(&hashinfo->lhash_wait);
+}
+
+static inline int inet_iif(const struct sk_buff *skb)
+{
+ return ((struct rtable *)skb->dst)->rt_iif;
+}
+
+extern struct sock *__inet_lookup_listener(const struct hlist_head *head,
+ const u32 daddr,
+ const unsigned short hnum,
+ const int dif);
+
+/* Optimize the common listener case. */
+static inline struct sock *
+ inet_lookup_listener(struct inet_hashinfo *hashinfo,
+ const u32 daddr,
+ const unsigned short hnum, const int dif)
+{
+ struct sock *sk = NULL;
+ const struct hlist_head *head;
+
+ read_lock(&hashinfo->lhash_lock);
+ head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
+ if (!hlist_empty(head)) {
+ const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
+
+ if (inet->num == hnum && !sk->sk_node.next &&
+ (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
+ (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+ !sk->sk_bound_dev_if)
+ goto sherry_cache;
+ sk = __inet_lookup_listener(head, daddr, hnum, dif);
+ }
+ if (sk) {
+sherry_cache:
+ sock_hold(sk);
+ }
+ read_unlock(&hashinfo->lhash_lock);
+ return sk;
+}
+
+/* Socket demux engine toys. */
+#ifdef __BIG_ENDIAN
+#define INET_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__sport) << 16) | (__u32)(__dport))
+#else /* __LITTLE_ENDIAN */
+#define INET_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__dport) << 16) | (__u32)(__sport))
+#endif
+
+#if (BITS_PER_LONG == 64)
+#ifdef __BIG_ENDIAN
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
+ const __u64 __name = (((__u64)(__saddr)) << 32) | ((__u64)(__daddr));
+#else /* __LITTLE_ENDIAN */
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
+ const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
+#endif /* __BIG_ENDIAN */
+#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \
+ ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
+ ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#else /* 32-bit arch */
+#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
+#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->daddr == (__saddr)) && \
+ (inet_sk(__sk)->rcv_saddr == (__daddr)) && \
+ ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_twsk(__sk)->tw_daddr == (__saddr)) && \
+ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
+ ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#endif /* 64-bit arch */
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need
+ * not check it for lookups anymore, thanks Alexey. -DaveM
+ *
+ * Local BH must be disabled here.
+ */
+static inline struct sock *
+ __inet_lookup_established(struct inet_hashinfo *hashinfo,
+ const u32 saddr, const u16 sport,
+ const u32 daddr, const u16 hnum,
+ const int dif)
+{
+ INET_ADDR_COOKIE(acookie, saddr, daddr)
+ const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+ struct sock *sk;
+ const struct hlist_node *node;
+ /* Optimize here for direct hit, only listening connections can
+ * have wildcards anyways.
+ */
+ const int hash = inet_ehashfn(daddr, hnum, saddr, sport, hashinfo->ehash_size);
+ struct inet_ehash_bucket *head = &hashinfo->ehash[hash];
+
+ read_lock(&head->lock);
+ sk_for_each(sk, node, &head->chain) {
+ if (INET_MATCH(sk, acookie, 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) {
+ if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif))
+ goto hit;
+ }
+ sk = NULL;
+out:
+ read_unlock(&head->lock);
+ return sk;
+hit:
+ sock_hold(sk);
+ goto out;
+}
+
+static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
+ const u32 saddr, const u16 sport,
+ const u32 daddr, const u16 hnum,
+ const int dif)
+{
+ struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
+ hnum, dif);
+ return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif);
+}
+
+static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
+ const u32 saddr, const u16 sport,
+ const u32 daddr, const u16 dport,
+ const int dif)
+{
+ struct sock *sk;
+
+ local_bh_disable();
+ sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
+ local_bh_enable();
+
+ return sk;
+}
+#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
new file mode 100644
index 000000000000..3b070352e869
--- /dev/null
+++ b/include/net/inet_timewait_sock.h
@@ -0,0 +1,219 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for a generic INET TIMEWAIT sock
+ *
+ * From code originally in net/tcp.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 _INET_TIMEWAIT_SOCK_
+#define _INET_TIMEWAIT_SOCK_
+
+#include <linux/config.h>
+
+#include <linux/ip.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include <net/sock.h>
+#include <net/tcp_states.h>
+
+#include <asm/atomic.h>
+
+struct inet_hashinfo;
+
+#define INET_TWDR_RECYCLE_SLOTS_LOG 5
+#define INET_TWDR_RECYCLE_SLOTS (1 << INET_TWDR_RECYCLE_SLOTS_LOG)
+
+/*
+ * If time > 4sec, it is "slow" path, no recycling is required,
+ * so that we select tick to get range about 4 seconds.
+ */
+#if HZ <= 16 || HZ > 4096
+# error Unsupported: HZ <= 16 or HZ > 4096
+#elif HZ <= 32
+# define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 64
+# define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 128
+# define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 256
+# define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 512
+# define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 1024
+# define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#elif HZ <= 2048
+# define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#else
+# define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
+#endif
+
+/* TIME_WAIT reaping mechanism. */
+#define INET_TWDR_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
+
+#define INET_TWDR_TWKILL_QUOTA 100
+
+struct inet_timewait_death_row {
+ /* Short-time timewait calendar */
+ int twcal_hand;
+ int twcal_jiffie;
+ struct timer_list twcal_timer;
+ struct hlist_head twcal_row[INET_TWDR_RECYCLE_SLOTS];
+
+ spinlock_t death_lock;
+ int tw_count;
+ int period;
+ u32 thread_slots;
+ struct work_struct twkill_work;
+ struct timer_list tw_timer;
+ int slot;
+ struct hlist_head cells[INET_TWDR_TWKILL_SLOTS];
+ struct inet_hashinfo *hashinfo;
+ int sysctl_tw_recycle;
+ int sysctl_max_tw_buckets;
+};
+
+extern void inet_twdr_hangman(unsigned long data);
+extern void inet_twdr_twkill_work(void *data);
+extern void inet_twdr_twcal_tick(unsigned long data);
+
+#if (BITS_PER_LONG == 64)
+#define INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES 8
+#else
+#define INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES 4
+#endif
+
+struct inet_bind_bucket;
+
+/*
+ * This is a TIME_WAIT sock. It works around the memory consumption
+ * problems of sockets in such a state on heavily loaded servers, but
+ * without violating the protocol specification.
+ */
+struct inet_timewait_sock {
+ /*
+ * Now struct sock also uses sock_common, so please just
+ * don't add nothing before this first member (__tw_common) --acme
+ */
+ struct sock_common __tw_common;
+#define tw_family __tw_common.skc_family
+#define tw_state __tw_common.skc_state
+#define tw_reuse __tw_common.skc_reuse
+#define tw_bound_dev_if __tw_common.skc_bound_dev_if
+#define tw_node __tw_common.skc_node
+#define tw_bind_node __tw_common.skc_bind_node
+#define tw_refcnt __tw_common.skc_refcnt
+#define tw_prot __tw_common.skc_prot
+ volatile unsigned char tw_substate;
+ /* 3 bits hole, try to pack */
+ unsigned char tw_rcv_wscale;
+ /* Socket demultiplex comparisons on incoming packets. */
+ /* these five are in inet_sock */
+ __u16 tw_sport;
+ __u32 tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES)));
+ __u32 tw_rcv_saddr;
+ __u16 tw_dport;
+ __u16 tw_num;
+ /* And these are ours. */
+ __u8 tw_ipv6only:1;
+ /* 31 bits hole, try to pack */
+ int tw_hashent;
+ int tw_timeout;
+ unsigned long tw_ttd;
+ struct inet_bind_bucket *tw_tb;
+ struct hlist_node tw_death_node;
+};
+
+static inline void inet_twsk_add_node(struct inet_timewait_sock *tw,
+ struct hlist_head *list)
+{
+ hlist_add_head(&tw->tw_node, list);
+}
+
+static inline void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
+ struct hlist_head *list)
+{
+ hlist_add_head(&tw->tw_bind_node, list);
+}
+
+static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw)
+{
+ return tw->tw_death_node.pprev != NULL;
+}
+
+static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw)
+{
+ tw->tw_death_node.pprev = NULL;
+}
+
+static inline void __inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
+{
+ __hlist_del(&tw->tw_death_node);
+ inet_twsk_dead_node_init(tw);
+}
+
+static inline int inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
+{
+ if (inet_twsk_dead_hashed(tw)) {
+ __inet_twsk_del_dead_node(tw);
+ return 1;
+ }
+ return 0;
+}
+
+#define inet_twsk_for_each(tw, node, head) \
+ hlist_for_each_entry(tw, node, head, tw_node)
+
+#define inet_twsk_for_each_inmate(tw, node, jail) \
+ hlist_for_each_entry(tw, node, jail, tw_death_node)
+
+#define inet_twsk_for_each_inmate_safe(tw, node, safe, jail) \
+ hlist_for_each_entry_safe(tw, node, safe, jail, tw_death_node)
+
+static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
+{
+ return (struct inet_timewait_sock *)sk;
+}
+
+static inline u32 inet_rcv_saddr(const struct sock *sk)
+{
+ return likely(sk->sk_state != TCP_TIME_WAIT) ?
+ inet_sk(sk)->rcv_saddr : inet_twsk(sk)->tw_rcv_saddr;
+}
+
+static inline void inet_twsk_put(struct inet_timewait_sock *tw)
+{
+ if (atomic_dec_and_test(&tw->tw_refcnt)) {
+#ifdef SOCK_REFCNT_DEBUG
+ printk(KERN_DEBUG "%s timewait_sock %p released\n",
+ tw->tw_prot->name, tw);
+#endif
+ kmem_cache_free(tw->tw_prot->twsk_slab, tw);
+ }
+}
+
+extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
+ const int state);
+
+extern void __inet_twsk_kill(struct inet_timewait_sock *tw,
+ struct inet_hashinfo *hashinfo);
+
+extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw,
+ struct sock *sk,
+ struct inet_hashinfo *hashinfo);
+
+extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr,
+ const int timeo, const int timewait_len);
+extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr);
+#endif /* _INET_TIMEWAIT_SOCK_ */
diff --git a/include/net/ip.h b/include/net/ip.h
index 32360bbe143f..e4563bbee6ea 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -86,7 +86,7 @@ extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
u32 saddr, u32 daddr,
struct ip_options *opt);
extern int ip_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt, struct net_device *orig_dev);
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);
@@ -140,8 +140,6 @@ struct ip_reply_arg {
void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
unsigned int len);
-extern int ip_finish_output(struct sk_buff *skb);
-
struct ipv4_config
{
int log_martians;
@@ -165,6 +163,24 @@ extern int sysctl_local_port_range[2];
extern int sysctl_ip_default_ttl;
extern int sysctl_ip_nonlocal_bind;
+/* From ip_fragment.c */
+extern int sysctl_ipfrag_high_thresh;
+extern int sysctl_ipfrag_low_thresh;
+extern int sysctl_ipfrag_time;
+extern int sysctl_ipfrag_secret_interval;
+
+/* From inetpeer.c */
+extern int inet_peer_threshold;
+extern int inet_peer_minttl;
+extern int inet_peer_maxttl;
+extern int inet_peer_gc_mintime;
+extern int inet_peer_gc_maxtime;
+
+/* From ip_output.c */
+extern int sysctl_ip_dynaddr;
+
+extern void ipfrag_init(void);
+
#ifdef CONFIG_INET
/* The function in 2.2 was invalid, producing wrong result for
* check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
@@ -319,7 +335,10 @@ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 da
extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
extern void ip_options_fragment(struct sk_buff *skb);
extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
-extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user);
+extern int ip_options_get(struct ip_options **optp,
+ unsigned char *data, int optlen);
+extern int ip_options_get_from_user(struct ip_options **optp,
+ unsigned char __user *data, int optlen);
extern void ip_options_undo(struct ip_options * opt);
extern void ip_forward_options(struct sk_buff *skb);
extern int ip_options_rcv_srr(struct sk_buff *skb);
@@ -350,5 +369,10 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen,
void **context);
+#ifdef CONFIG_PROC_FS
+extern int ip_misc_proc_init(void);
+#endif
+
+extern struct ctl_table ipv4_table[];
#endif /* _IP_H */
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index f920706d526b..1f2e428ca364 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -12,7 +12,6 @@
#include <net/flow.h>
#include <net/ip6_fib.h>
#include <net/sock.h>
-#include <linux/tcp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index a4208a336ac0..14de4ebd1211 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -295,4 +295,9 @@ static inline void fib_res_put(struct fib_result *res)
#endif
}
+#ifdef CONFIG_PROC_FS
+extern int fib_proc_init(void);
+extern void fib_proc_exit(void);
+#endif
+
#endif /* _NET_FIB_H */
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 52da5d26617a..e426641c519f 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -255,7 +255,6 @@ struct ip_vs_daemon_user {
#include <asm/atomic.h> /* for struct atomic_t */
#include <linux/netdevice.h> /* for struct neighbour */
#include <net/dst.h> /* for struct dst_entry */
-#include <net/tcp.h>
#include <net/udp.h>
#include <linux/compiler.h>
@@ -959,7 +958,7 @@ static __inline__ int ip_vs_todrop(void)
*/
#define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
-extern __inline__ char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
{
char fwd;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 69324465e8b3..65ec86678a08 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -104,6 +104,7 @@ struct frag_hdr {
#ifdef __KERNEL__
+#include <linux/config.h>
#include <net/sock.h>
/* sysctls */
@@ -145,7 +146,6 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field)
#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field)
#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
-extern atomic_t inet6_sock_nr;
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
@@ -233,6 +233,10 @@ extern int ip6_ra_control(struct sock *sk, int sel,
extern int ipv6_parse_hopopts(struct sk_buff *skb, int);
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,
+ int newtype,
+ struct ipv6_opt_hdr __user *newopt,
+ int newoptlen);
extern int ip6_frag_nqueues;
extern atomic_t ip6_frag_mem;
@@ -346,7 +350,8 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
extern int ipv6_rcv(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt,
+ struct net_device *orig_dev);
/*
* upper-layer output functions
@@ -372,6 +377,7 @@ extern int ip6_append_data(struct sock *sk,
int length,
int transhdrlen,
int hlimit,
+ int tclass,
struct ipv6_txoptions *opt,
struct flowi *fl,
struct rt6_info *rt,
@@ -464,8 +470,38 @@ extern int sysctl_ip6frag_low_thresh;
extern int sysctl_ip6frag_time;
extern int sysctl_ip6frag_secret_interval;
-#endif /* __KERNEL__ */
-#endif /* _NET_IPV6_H */
+extern struct proto_ops inet6_stream_ops;
+extern struct proto_ops inet6_dgram_ops;
+
+extern int ip6_mc_source(int add, int omode, struct sock *sk,
+ struct group_source_req *pgsr);
+extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
+extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ struct group_filter __user *optval,
+ int __user *optlen);
+
+#ifdef CONFIG_PROC_FS
+extern int ac6_proc_init(void);
+extern void ac6_proc_exit(void);
+extern int raw6_proc_init(void);
+extern void raw6_proc_exit(void);
+extern int tcp6_proc_init(void);
+extern void tcp6_proc_exit(void);
+extern int udp6_proc_init(void);
+extern void udp6_proc_exit(void);
+extern int ipv6_misc_proc_init(void);
+extern void ipv6_misc_proc_exit(void);
+
+extern struct rt6_statistics rt6_stats;
+#endif
+#ifdef CONFIG_SYSCTL
+extern ctl_table ipv6_route_table[];
+extern ctl_table ipv6_icmp_table[];
+extern void ipv6_sysctl_register(void);
+extern void ipv6_sysctl_unregister(void);
+#endif
+#endif /* __KERNEL__ */
+#endif /* _NET_IPV6_H */
diff --git a/include/net/irda/irlan_filter.h b/include/net/irda/irlan_filter.h
index 3afeb6c94ea4..492dedaa8ac1 100644
--- a/include/net/irda/irlan_filter.h
+++ b/include/net/irda/irlan_filter.h
@@ -28,6 +28,6 @@
void irlan_check_command_param(struct irlan_cb *self, char *param,
char *value);
void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb);
-int irlan_print_filter(struct seq_file *seq, int filter_type);
+void irlan_print_filter(struct seq_file *seq, int filter_type);
#endif /* IRLAN_FILTER_H */
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 44edd48f1234..d67c8393a343 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -1,10 +1,10 @@
/*
* This file define the new driver API for Wireless Extensions
*
- * Version : 6 21.6.04
+ * Version : 7 18.3.05
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved.
*/
#ifndef _IW_HANDLER_H
@@ -207,7 +207,7 @@
* will be needed...
* I just plan to increment with each new version.
*/
-#define IW_HANDLER_VERSION 6
+#define IW_HANDLER_VERSION 7
/*
* Changes :
@@ -232,6 +232,13 @@
* - Remove spy #ifdef, they are always on -> cleaner code
* - Add IW_DESCR_FLAG_NOMAX flag for very large requests
* - Start migrating get_wireless_stats to struct iw_handler_def
+ *
+ * V6 to V7
+ * --------
+ * - Add struct ieee80211_device pointer in struct iw_public_data
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove spy_offset from struct iw_handler_def
+ * - Add "check" version of event macros for ieee802.11 stack
*/
/**************************** CONSTANTS ****************************/
@@ -334,9 +341,6 @@ struct iw_handler_def
* We will automatically export that to user space... */
const struct iw_priv_args * private_args;
- /* This field will be *removed* in the next version of WE */
- long spy_offset; /* DO NOT USE */
-
/* New location of get_wireless_stats, to de-bloat struct net_device.
* The old pointer in struct net_device will be gradually phased
* out, and drivers are encouraged to use this one... */
@@ -400,16 +404,21 @@ struct iw_spy_data
/* --------------------- DEVICE WIRELESS DATA --------------------- */
/*
* This is all the wireless data specific to a device instance that
- * is managed by the core of Wireless Extensions.
+ * is managed by the core of Wireless Extensions or the 802.11 layer.
* We only keep pointer to those structures, so that a driver is free
* to share them between instances.
* This structure should be initialised before registering the device.
* Access to this data follow the same rules as any other struct net_device
* data (i.e. valid as long as struct net_device exist, same locking rules).
*/
+/* Forward declaration */
+struct ieee80211_device;
+/* The struct */
struct iw_public_data {
/* Driver enhanced spy support */
- struct iw_spy_data * spy_data;
+ struct iw_spy_data * spy_data;
+ /* Structure managed by the in-kernel IEEE 802.11 layer */
+ struct ieee80211_device * ieee80211;
};
/**************************** PROTOTYPES ****************************/
@@ -424,7 +433,7 @@ struct iw_public_data {
extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
int length);
-/* Handle IOCTLs, called in net/code/dev.c */
+/* Handle IOCTLs, called in net/core/dev.c */
extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
/* Second : functions that may be called by driver modules */
@@ -479,7 +488,7 @@ iwe_stream_add_event(char * stream, /* Stream of events */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
- if((stream + event_len) < ends) {
+ if(likely((stream + event_len) < ends)) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
@@ -495,14 +504,17 @@ iwe_stream_add_event(char * stream, /* Stream of events */
static inline char *
iwe_stream_add_point(char * stream, /* Stream of events */
char * ends, /* End of stream */
- struct iw_event *iwe, /* Payload */
- char * extra)
+ struct iw_event *iwe, /* Payload length + flags */
+ char * extra) /* More payload */
{
int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
/* Check if it's possible */
- if((stream + event_len) < ends) {
+ if(likely((stream + event_len) < ends)) {
iwe->len = event_len;
- memcpy(stream, (char *) iwe, IW_EV_POINT_LEN);
+ memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
+ memcpy(stream + IW_EV_LCP_LEN,
+ ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+ IW_EV_POINT_LEN - IW_EV_LCP_LEN);
memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
stream += event_len;
}
@@ -526,7 +538,7 @@ iwe_stream_add_value(char * event, /* Event in the stream */
event_len -= IW_EV_LCP_LEN;
/* Check if it's possible */
- if((value + event_len) < ends) {
+ if(likely((value + event_len) < ends)) {
/* Add new value */
memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
value += event_len;
@@ -537,4 +549,85 @@ iwe_stream_add_value(char * event, /* Event in the stream */
return value;
}
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an Wireless Event to a stream of events.
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_event(char * stream, /* Stream of events */
+ char * ends, /* End of stream */
+ struct iw_event *iwe, /* Payload */
+ int event_len, /* Size of payload */
+ int * perr) /* Error report */
+{
+ /* Check if it's possible, set error if not */
+ if(likely((stream + event_len) < ends)) {
+ iwe->len = event_len;
+ memcpy(stream, (char *) iwe, event_len);
+ stream += event_len;
+ } else
+ *perr = -E2BIG;
+ return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add an short Wireless Event containing a pointer to a
+ * stream of events.
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_point(char * stream, /* Stream of events */
+ char * ends, /* End of stream */
+ struct iw_event *iwe, /* Payload length + flags */
+ char * extra, /* More payload */
+ int * perr) /* Error report */
+{
+ int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
+ /* Check if it's possible */
+ if(likely((stream + event_len) < ends)) {
+ iwe->len = event_len;
+ memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
+ memcpy(stream + IW_EV_LCP_LEN,
+ ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+ IW_EV_POINT_LEN - IW_EV_LCP_LEN);
+ memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
+ stream += event_len;
+ } else
+ *perr = -E2BIG;
+ return stream;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wrapper to add a value to a Wireless Event in a stream of events.
+ * Be careful, this one is tricky to use properly :
+ * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
+ * Same as above, with explicit error check...
+ */
+static inline char *
+iwe_stream_check_add_value(char * event, /* Event in the stream */
+ char * value, /* Value in event */
+ char * ends, /* End of stream */
+ struct iw_event *iwe, /* Payload */
+ int event_len, /* Size of payload */
+ int * perr) /* Error report */
+{
+ /* Don't duplicate LCP */
+ event_len -= IW_EV_LCP_LEN;
+
+ /* Check if it's possible */
+ if(likely((value + event_len) < ends)) {
+ /* Add new value */
+ memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
+ value += event_len;
+ /* Patch LCP */
+ iwe->len = value - event;
+ memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
+ } else
+ *perr = -E2BIG;
+ return value;
+}
+
#endif /* _IW_HANDLER_H */
diff --git a/include/net/llc.h b/include/net/llc.h
index c9aed2a8b4e2..71769a5aeef3 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -46,7 +46,8 @@ struct llc_sap {
unsigned char f_bit;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt,
+ struct net_device *orig_dev);
struct llc_addr laddr;
struct list_head node;
struct {
@@ -64,7 +65,7 @@ extern rwlock_t llc_sap_list_lock;
extern unsigned char llc_station_mac_sa[ETH_ALEN];
extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt, struct net_device *orig_dev);
extern int llc_mac_hdr_init(struct sk_buff *skb,
unsigned char *sa, unsigned char *da);
@@ -78,7 +79,8 @@ extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
extern struct llc_sap *llc_sap_open(unsigned char lsap,
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt));
+ struct packet_type *pt,
+ struct net_device *orig_dev));
extern void llc_sap_close(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(unsigned char sap_value);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 89809891e5ab..34c07731933d 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -363,7 +363,14 @@ __neigh_lookup_errno(struct neigh_table *tbl, const void *pkey,
return neigh_create(tbl, pkey, dev);
}
-#define LOCALLY_ENQUEUED -2
+struct neighbour_cb {
+ unsigned long sched_next;
+ unsigned int flags;
+};
+
+#define LOCALLY_ENQUEUED 0x1
+
+#define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb)
#endif
#endif
diff --git a/include/net/netrom.h b/include/net/netrom.h
index 45f2c7616d8b..a6bf6e0f606a 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -6,6 +6,7 @@
#ifndef _NETROM_H
#define _NETROM_H
+
#include <linux/netrom.h>
#include <linux/list.h>
#include <net/sock.h>
@@ -22,6 +23,7 @@
#define NR_DISCACK 0x04
#define NR_INFO 0x05
#define NR_INFOACK 0x06
+#define NR_RESET 0x07
#define NR_CHOKE_FLAG 0x80
#define NR_NAK_FLAG 0x40
@@ -51,11 +53,16 @@ enum {
#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */
#define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */
#define NR_DEFAULT_FAILS 2 /* Link fails until route fails */
+#define NR_DEFAULT_RESET 0 /* Sent / accept reset cmds? */
#define NR_MODULUS 256
#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */
#define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */
+struct nr_private {
+ struct net_device_stats stats;
+};
+
struct nr_sock {
struct sock sock;
ax25_address user_addr, source_addr, dest_addr;
@@ -176,6 +183,8 @@ extern int sysctl_netrom_transport_requested_window_size;
extern int sysctl_netrom_transport_no_activity_timeout;
extern int sysctl_netrom_routing_control;
extern int sysctl_netrom_link_fails_count;
+extern int sysctl_netrom_reset_circuit;
+
extern int nr_rx_frame(struct sk_buff *, struct net_device *);
extern void nr_destroy_socket(struct sock *);
@@ -218,7 +227,28 @@ extern void nr_requeue_frames(struct sock *);
extern int nr_validate_nr(struct sock *, unsigned short);
extern int nr_in_rx_window(struct sock *, unsigned short);
extern void nr_write_internal(struct sock *, int);
-extern void nr_transmit_refusal(struct sk_buff *, int);
+
+extern void __nr_transmit_reply(struct sk_buff *skb, int mine,
+ unsigned char cmdflags);
+
+/*
+ * This routine is called when a Connect Acknowledge with the Choke Flag
+ * set is needed to refuse a connection.
+ */
+#define nr_transmit_refusal(skb, mine) \
+do { \
+ __nr_transmit_reply((skb), (mine), NR_CONNACK | NR_CHOKE_FLAG); \
+} while (0)
+
+/*
+ * This routine is called when we don't have a circuit matching an incoming
+ * NET/ROM packet. This is an G8PZT Xrouter extension.
+ */
+#define nr_transmit_reset(skb, mine) \
+do { \
+ __nr_transmit_reply((skb), (mine), NR_RESET); \
+} while (0)
+
extern void nr_disconnect(struct sock *, int);
/* nr_timer.c */
diff --git a/include/net/p8022.h b/include/net/p8022.h
index 3c99a86c3581..42e9fac51b31 100644
--- a/include/net/p8022.h
+++ b/include/net/p8022.h
@@ -4,7 +4,10 @@ extern struct datalink_proto *
register_8022_client(unsigned char type,
int (*func)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt));
+ struct packet_type *pt,
+ struct net_device *orig_dev));
extern void unregister_8022_client(struct datalink_proto *proto);
+extern struct datalink_proto *make_8023_client(void);
+extern void destroy_8023_client(struct datalink_proto *dl);
#endif
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4abda6aec05a..b902d24a3256 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -352,10 +352,10 @@ tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
static inline int
tcf_match_indev(struct sk_buff *skb, char *indev)
{
- if (0 != indev[0]) {
- if (NULL == skb->input_dev)
+ if (indev[0]) {
+ if (!skb->input_dev)
return 0;
- else if (0 != strcmp(indev, skb->input_dev->name))
+ if (strcmp(indev, skb->input_dev->name))
return 0;
}
diff --git a/include/net/psnap.h b/include/net/psnap.h
index 9c94e8f98b36..b2e01cc3fc8a 100644
--- a/include/net/psnap.h
+++ b/include/net/psnap.h
@@ -1,7 +1,7 @@
#ifndef _NET_PSNAP_H
#define _NET_PSNAP_H
-extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *));
+extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *orig_dev));
extern void unregister_snap_client(struct datalink_proto *proto);
#endif
diff --git a/include/net/raw.h b/include/net/raw.h
index 1c411c45587a..f47917469b12 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -17,10 +17,10 @@
#ifndef _RAW_H
#define _RAW_H
+#include <linux/config.h>
extern struct proto raw_prot;
-
extern void raw_err(struct sock *, struct sk_buff *, u32 info);
extern int raw_rcv(struct sock *, struct sk_buff *);
@@ -37,6 +37,11 @@ extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
unsigned long raddr, unsigned long laddr,
int dif);
-extern void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
+extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
+
+#ifdef CONFIG_PROC_FS
+extern int raw_proc_init(void);
+extern void raw_proc_exit(void);
+#endif
#endif /* _RAW_H */
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index 23fd9a6a221a..14476a71725e 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -7,10 +7,11 @@
extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
extern rwlock_t raw_v6_lock;
-extern void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr);
+extern int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr);
extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
- struct in6_addr *loc_addr, struct in6_addr *rmt_addr);
+ struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
+ int dif);
extern int rawv6_rcv(struct sock *sk,
struct sk_buff *skb);
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 72fd6f5e86b1..b52cc52ffe39 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -89,6 +89,7 @@ struct listen_sock {
int qlen_young;
int clock_hand;
u32 hash_rnd;
+ u32 nr_table_entries;
struct request_sock *syn_table[0];
};
@@ -96,6 +97,7 @@ struct listen_sock {
*
* @rskq_accept_head - FIFO head of established children
* @rskq_accept_tail - FIFO tail of established children
+ * @rskq_defer_accept - User waits for some data after accept()
* @syn_wait_lock - serializer
*
* %syn_wait_lock is necessary only to avoid proc interface having to grab the main
@@ -111,6 +113,8 @@ struct request_sock_queue {
struct request_sock *rskq_accept_head;
struct request_sock *rskq_accept_tail;
rwlock_t syn_wait_lock;
+ u8 rskq_defer_accept;
+ /* 3 bytes hole, try to pack */
struct listen_sock *listen_opt;
};
@@ -129,11 +133,13 @@ static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock
return lopt;
}
-static inline void reqsk_queue_destroy(struct request_sock_queue *queue)
+static inline void __reqsk_queue_destroy(struct request_sock_queue *queue)
{
kfree(reqsk_queue_yank_listen_sk(queue));
}
+extern void reqsk_queue_destroy(struct request_sock_queue *queue);
+
static inline struct request_sock *
reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
{
@@ -221,17 +227,17 @@ static inline int reqsk_queue_added(struct request_sock_queue *queue)
return prev_qlen;
}
-static inline int reqsk_queue_len(struct request_sock_queue *queue)
+static inline int reqsk_queue_len(const struct request_sock_queue *queue)
{
return queue->listen_opt != NULL ? queue->listen_opt->qlen : 0;
}
-static inline int reqsk_queue_len_young(struct request_sock_queue *queue)
+static inline int reqsk_queue_len_young(const struct request_sock_queue *queue)
{
return queue->listen_opt->qlen_young;
}
-static inline int reqsk_queue_is_full(struct request_sock_queue *queue)
+static inline int reqsk_queue_is_full(const struct request_sock_queue *queue)
{
return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
}
diff --git a/include/net/route.h b/include/net/route.h
index c3cd069a9aca..dbe79ca67d31 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -105,10 +105,6 @@ struct rt_cache_stat
unsigned int out_hlist_search;
};
-extern struct rt_cache_stat *rt_cache_stat;
-#define RT_CACHE_STAT_INC(field) \
- (per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++)
-
extern struct ip_rt_acct *ip_rt_acct;
struct in_device;
@@ -199,4 +195,6 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt)
return rt->peer;
}
+extern ctl_table ipv4_route_table[];
+
#endif /* _ROUTE_H */
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 5999e5684bbf..c51541ee0247 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -47,10 +47,10 @@
#ifndef __sctp_constants_h__
#define __sctp_constants_h__
-#include <linux/tcp.h> /* For TCP states used in sctp_sock_state_t */
#include <linux/sctp.h>
#include <linux/ipv6.h> /* For ipv6hdr. */
#include <net/sctp/user.h>
+#include <net/tcp_states.h> /* For TCP states used in sctp_sock_state_t */
/* Value used for stream negotiation. */
enum { SCTP_MAX_STREAM = 0xffff };
diff --git a/include/net/sock.h b/include/net/sock.h
index e9b1dbab90d0..8c48fbecb7cf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -88,6 +88,7 @@ do { spin_lock_init(&((__sk)->sk_lock.slock)); \
} while(0)
struct sock;
+struct proto;
/**
* struct sock_common - minimal network layer representation of sockets
@@ -98,10 +99,11 @@ struct sock;
* @skc_node: main hash linkage for various protocol lookup tables
* @skc_bind_node: bind hash linkage for various protocol lookup tables
* @skc_refcnt: reference count
+ * @skc_prot: protocol handlers inside a network family
*
* This is the minimal network layer representation of sockets, the header
- * for struct sock and struct tcp_tw_bucket.
- */
+ * for struct sock and struct inet_timewait_sock.
+ */
struct sock_common {
unsigned short skc_family;
volatile unsigned char skc_state;
@@ -110,11 +112,12 @@ struct sock_common {
struct hlist_node skc_node;
struct hlist_node skc_bind_node;
atomic_t skc_refcnt;
+ struct proto *skc_prot;
};
/**
* struct sock - network layer representation of sockets
- * @__sk_common: shared layout with tcp_tw_bucket
+ * @__sk_common: shared layout with inet_timewait_sock
* @sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
* @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
* @sk_lock: synchronizer
@@ -136,11 +139,10 @@ struct sock_common {
* @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
* @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
* @sk_lingertime: %SO_LINGER l_linger setting
- * @sk_hashent: hash entry in several tables (e.g. tcp_ehash)
+ * @sk_hashent: hash entry in several tables (e.g. inet_hashinfo.ehash)
* @sk_backlog: always used with the per-socket spinlock held
* @sk_callback_lock: used with the callbacks in the end of this struct
* @sk_error_queue: rarely used
- * @sk_prot: protocol handlers inside a network family
* @sk_prot_creator: sk_prot of original sock creator (see ipv6_setsockopt, IPV6_ADDRFORM for instance)
* @sk_err: last error
* @sk_err_soft: errors that don't cause failure but are the cause of a persistent failure not just 'timed out'
@@ -173,7 +175,7 @@ struct sock_common {
*/
struct sock {
/*
- * Now struct tcp_tw_bucket also uses sock_common, so please just
+ * Now struct inet_timewait_sock also uses sock_common, so please just
* don't add nothing before this first member (__sk_common) --acme
*/
struct sock_common __sk_common;
@@ -184,6 +186,7 @@ struct sock {
#define sk_node __sk_common.skc_node
#define sk_bind_node __sk_common.skc_bind_node
#define sk_refcnt __sk_common.skc_refcnt
+#define sk_prot __sk_common.skc_prot
unsigned char sk_shutdown : 2,
sk_no_check : 2,
sk_userlocks : 4;
@@ -218,7 +221,6 @@ struct sock {
struct sk_buff *tail;
} sk_backlog;
struct sk_buff_head sk_error_queue;
- struct proto *sk_prot;
struct proto *sk_prot_creator;
rwlock_t sk_callback_lock;
int sk_err,
@@ -253,28 +255,28 @@ struct sock {
/*
* Hashed lists helper routines
*/
-static inline struct sock *__sk_head(struct hlist_head *head)
+static inline struct sock *__sk_head(const struct hlist_head *head)
{
return hlist_entry(head->first, struct sock, sk_node);
}
-static inline struct sock *sk_head(struct hlist_head *head)
+static inline struct sock *sk_head(const struct hlist_head *head)
{
return hlist_empty(head) ? NULL : __sk_head(head);
}
-static inline struct sock *sk_next(struct sock *sk)
+static inline struct sock *sk_next(const struct sock *sk)
{
return sk->sk_node.next ?
hlist_entry(sk->sk_node.next, struct sock, sk_node) : NULL;
}
-static inline int sk_unhashed(struct sock *sk)
+static inline int sk_unhashed(const struct sock *sk)
{
return hlist_unhashed(&sk->sk_node);
}
-static inline int sk_hashed(struct sock *sk)
+static inline int sk_hashed(const struct sock *sk)
{
return sk->sk_node.pprev != NULL;
}
@@ -554,6 +556,10 @@ struct proto {
kmem_cache_t *slab;
unsigned int obj_size;
+ kmem_cache_t *twsk_slab;
+ unsigned int twsk_obj_size;
+ atomic_t *orphan_count;
+
struct request_sock_ops *rsk_prot;
struct module *owner;
@@ -561,7 +567,9 @@ struct proto {
char name[32];
struct list_head node;
-
+#ifdef SOCK_REFCNT_DEBUG
+ atomic_t socks;
+#endif
struct {
int inuse;
u8 __pad[SMP_CACHE_BYTES - sizeof(int)];
@@ -571,6 +579,31 @@ struct proto {
extern int proto_register(struct proto *prot, int alloc_slab);
extern void proto_unregister(struct proto *prot);
+#ifdef SOCK_REFCNT_DEBUG
+static inline void sk_refcnt_debug_inc(struct sock *sk)
+{
+ atomic_inc(&sk->sk_prot->socks);
+}
+
+static inline void sk_refcnt_debug_dec(struct sock *sk)
+{
+ atomic_dec(&sk->sk_prot->socks);
+ printk(KERN_DEBUG "%s socket %p released, %d are still alive\n",
+ sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks));
+}
+
+static inline void sk_refcnt_debug_release(const struct sock *sk)
+{
+ if (atomic_read(&sk->sk_refcnt) != 1)
+ printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
+ sk->sk_prot->name, sk, atomic_read(&sk->sk_refcnt));
+}
+#else /* SOCK_REFCNT_DEBUG */
+#define sk_refcnt_debug_inc(sk) do { } while (0)
+#define sk_refcnt_debug_dec(sk) do { } while (0)
+#define sk_refcnt_debug_release(sk) do { } while (0)
+#endif /* SOCK_REFCNT_DEBUG */
+
/* Called with local bh disabled */
static __inline__ void sock_prot_inc_use(struct proto *prot)
{
@@ -582,6 +615,15 @@ static __inline__ void sock_prot_dec_use(struct proto *prot)
prot->stats[smp_processor_id()].inuse--;
}
+/* With per-bucket locks this operation is not-atomic, so that
+ * this version is not worse.
+ */
+static inline void __sk_prot_rehash(struct sock *sk)
+{
+ sk->sk_prot->unhash(sk);
+ sk->sk_prot->hash(sk);
+}
+
/* About 10 seconds */
#define SOCK_DESTROY_TIME (10*HZ)
@@ -667,6 +709,12 @@ static inline int sk_stream_rmem_schedule(struct sock *sk, struct sk_buff *skb)
sk_stream_mem_schedule(sk, skb->truesize, 1);
}
+static inline int sk_stream_wmem_schedule(struct sock *sk, int size)
+{
+ return size <= sk->sk_forward_alloc ||
+ sk_stream_mem_schedule(sk, size, 0);
+}
+
/* Used by processes to "lock" a socket state, so that
* interrupts and bottom half handlers won't change it
* from under us. It essentially blocks any incoming
@@ -693,6 +741,8 @@ extern struct sock *sk_alloc(int family,
unsigned int __nocast priority,
struct proto *prot, int zero_it);
extern void sk_free(struct sock *sk);
+extern struct sock *sk_clone(const struct sock *sk,
+ const unsigned int __nocast priority);
extern struct sk_buff *sock_wmalloc(struct sock *sk,
unsigned long size, int force,
@@ -986,6 +1036,16 @@ sk_dst_check(struct sock *sk, u32 cookie)
return dst;
}
+static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
+{
+ __sk_dst_set(sk, dst);
+ sk->sk_route_caps = dst->dev->features;
+ if (sk->sk_route_caps & NETIF_F_TSO) {
+ if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
+ sk->sk_route_caps &= ~NETIF_F_TSO;
+ }
+}
+
static inline void sk_charge_skb(struct sock *sk, struct sk_buff *skb)
{
sk->sk_wmem_queued += skb->truesize;
@@ -1146,11 +1206,10 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
int hdr_len;
hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
- skb = alloc_skb(size + hdr_len, gfp);
+ skb = alloc_skb_fclone(size + hdr_len, gfp);
if (skb) {
skb->truesize += mem;
- if (sk->sk_forward_alloc >= (int)skb->truesize ||
- sk_stream_mem_schedule(sk, skb->truesize, 0)) {
+ if (sk_stream_wmem_schedule(sk, skb->truesize)) {
skb_reserve(skb, hdr_len);
return skb;
}
@@ -1173,10 +1232,8 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk)
{
struct page *page = NULL;
- if (sk->sk_forward_alloc >= (int)PAGE_SIZE ||
- sk_stream_mem_schedule(sk, PAGE_SIZE, 0))
- page = alloc_pages(sk->sk_allocation, 0);
- else {
+ page = alloc_pages(sk->sk_allocation, 0);
+ if (!page) {
sk->sk_prot->enter_memory_pressure();
sk_stream_moderate_sndbuf(sk);
}
@@ -1228,16 +1285,19 @@ static inline int sock_intr_errno(long timeo)
static __inline__ void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
{
- struct timeval *stamp = &skb->stamp;
+ struct timeval stamp;
+
+ skb_get_timestamp(skb, &stamp);
if (sock_flag(sk, SOCK_RCVTSTAMP)) {
/* Race occurred between timestamp enabling and packet
receiving. Fill in the current time for now. */
- if (stamp->tv_sec == 0)
- do_gettimeofday(stamp);
+ if (stamp.tv_sec == 0)
+ do_gettimeofday(&stamp);
+ skb_set_timestamp(skb, &stamp);
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(struct timeval),
- stamp);
+ &stamp);
} else
- sk->sk_stamp = *stamp;
+ sk->sk_stamp = stamp;
}
/**
@@ -1262,11 +1322,11 @@ extern int sock_get_timestamp(struct sock *, struct timeval __user *);
*/
#if 0
-#define NETDEBUG(x) do { } while (0)
-#define LIMIT_NETDEBUG(x) do {} while(0)
+#define NETDEBUG(fmt, args...) do { } while (0)
+#define LIMIT_NETDEBUG(fmt, args...) do { } while(0)
#else
-#define NETDEBUG(x) do { x; } while (0)
-#define LIMIT_NETDEBUG(x) do { if (net_ratelimit()) { x; } } while(0)
+#define NETDEBUG(fmt, args...) printk(fmt,##args)
+#define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0)
#endif
/*
@@ -1313,4 +1373,15 @@ static inline int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsign
}
#endif
+extern void sk_init(void);
+
+#ifdef CONFIG_SYSCTL
+extern struct ctl_table core_table[];
+#endif
+
+extern int sysctl_optmem_max;
+
+extern __u32 sysctl_wmem_default;
+extern __u32 sysctl_rmem_default;
+
#endif /* _SOCK_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5010f0c5a56e..97af77c4d096 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -21,360 +21,29 @@
#define TCP_DEBUG 1
#define FASTRETRANS_DEBUG 1
-/* Cancel timers, when they are not required. */
-#undef TCP_CLEAR_TIMERS
-
#include <linux/config.h>
#include <linux/list.h>
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/cache.h>
#include <linux/percpu.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_timewait_sock.h>
+#include <net/inet_hashtables.h>
#include <net/checksum.h>
#include <net/request_sock.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/ip.h>
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-#include <linux/ipv6.h>
-#endif
-#include <linux/seq_file.h>
-
-/* This is for all connections with a full identity, no wildcards.
- * New scheme, half the table is for TIME_WAIT, the other half is
- * for the rest. I'll experiment with dynamic table growth later.
- */
-struct tcp_ehash_bucket {
- rwlock_t lock;
- struct hlist_head chain;
-} __attribute__((__aligned__(8)));
-
-/* This is for listening sockets, thus all sockets which possess wildcards. */
-#define TCP_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
-
-/* There are a few simple rules, which allow for local port reuse by
- * an application. In essence:
- *
- * 1) Sockets bound to different interfaces may share a local port.
- * Failing that, goto test 2.
- * 2) If all sockets have sk->sk_reuse set, and none of them are in
- * TCP_LISTEN state, the port may be shared.
- * Failing that, goto test 3.
- * 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local
- * address, and none of them are the same, the port may be
- * shared.
- * Failing this, the port cannot be shared.
- *
- * The interesting point, is test #2. This is what an FTP server does
- * all day. To optimize this case we use a specific flag bit defined
- * below. As we add sockets to a bind bucket list, we perform a
- * check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN))
- * As long as all sockets added to a bind bucket pass this test,
- * the flag bit will be set.
- * The resulting situation is that tcp_v[46]_verify_bind() can just check
- * for this flag bit, if it is set and the socket trying to bind has
- * sk->sk_reuse set, we don't even have to walk the owners list at all,
- * we return that it is ok to bind this socket to the requested local port.
- *
- * Sounds like a lot of work, but it is worth it. In a more naive
- * implementation (ie. current FreeBSD etc.) the entire list of ports
- * must be walked for each data port opened by an ftp server. Needless
- * to say, this does not scale at all. With a couple thousand FTP
- * users logged onto your box, isn't it nice to know that new data
- * ports are created in O(1) time? I thought so. ;-) -DaveM
- */
-struct tcp_bind_bucket {
- unsigned short port;
- signed short fastreuse;
- struct hlist_node node;
- struct hlist_head owners;
-};
-
-#define tb_for_each(tb, node, head) hlist_for_each_entry(tb, node, head, node)
-
-struct tcp_bind_hashbucket {
- spinlock_t lock;
- struct hlist_head chain;
-};
-
-static inline struct tcp_bind_bucket *__tb_head(struct tcp_bind_hashbucket *head)
-{
- return hlist_entry(head->chain.first, struct tcp_bind_bucket, node);
-}
-
-static inline struct tcp_bind_bucket *tb_head(struct tcp_bind_hashbucket *head)
-{
- return hlist_empty(&head->chain) ? NULL : __tb_head(head);
-}
-
-extern struct tcp_hashinfo {
- /* This is for sockets with full identity only. Sockets here will
- * always be without wildcards and will have the following invariant:
- *
- * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
- *
- * First half of the table is for sockets not in TIME_WAIT, second half
- * is for TIME_WAIT sockets only.
- */
- struct tcp_ehash_bucket *__tcp_ehash;
-
- /* Ok, let's try this, I give up, we do need a local binding
- * TCP hash as well as the others for fast bind/connect.
- */
- struct tcp_bind_hashbucket *__tcp_bhash;
+#include <net/tcp_states.h>
- int __tcp_bhash_size;
- int __tcp_ehash_size;
-
- /* All sockets in TCP_LISTEN state will be in here. This is the only
- * table where wildcard'd TCP sockets can exist. Hash function here
- * is just local port number.
- */
- struct hlist_head __tcp_listening_hash[TCP_LHTABLE_SIZE];
-
- /* All the above members are written once at bootup and
- * never written again _or_ are predominantly read-access.
- *
- * Now align to a new cache line as all the following members
- * are often dirty.
- */
- rwlock_t __tcp_lhash_lock ____cacheline_aligned;
- atomic_t __tcp_lhash_users;
- wait_queue_head_t __tcp_lhash_wait;
- spinlock_t __tcp_portalloc_lock;
-} tcp_hashinfo;
-
-#define tcp_ehash (tcp_hashinfo.__tcp_ehash)
-#define tcp_bhash (tcp_hashinfo.__tcp_bhash)
-#define tcp_ehash_size (tcp_hashinfo.__tcp_ehash_size)
-#define tcp_bhash_size (tcp_hashinfo.__tcp_bhash_size)
-#define tcp_listening_hash (tcp_hashinfo.__tcp_listening_hash)
-#define tcp_lhash_lock (tcp_hashinfo.__tcp_lhash_lock)
-#define tcp_lhash_users (tcp_hashinfo.__tcp_lhash_users)
-#define tcp_lhash_wait (tcp_hashinfo.__tcp_lhash_wait)
-#define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock)
-
-extern kmem_cache_t *tcp_bucket_cachep;
-extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
- unsigned short snum);
-extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb);
-extern void tcp_bucket_unlock(struct sock *sk);
-extern int tcp_port_rover;
-
-/* These are AF independent. */
-static __inline__ int tcp_bhashfn(__u16 lport)
-{
- return (lport & (tcp_bhash_size - 1));
-}
-
-extern void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
- unsigned short snum);
-
-#if (BITS_PER_LONG == 64)
-#define TCP_ADDRCMP_ALIGN_BYTES 8
-#else
-#define TCP_ADDRCMP_ALIGN_BYTES 4
-#endif
-
-/* This is a TIME_WAIT bucket. It works around the memory consumption
- * problems of sockets in such a state on heavily loaded servers, but
- * without violating the protocol specification.
- */
-struct tcp_tw_bucket {
- /*
- * Now struct sock also uses sock_common, so please just
- * don't add nothing before this first member (__tw_common) --acme
- */
- struct sock_common __tw_common;
-#define tw_family __tw_common.skc_family
-#define tw_state __tw_common.skc_state
-#define tw_reuse __tw_common.skc_reuse
-#define tw_bound_dev_if __tw_common.skc_bound_dev_if
-#define tw_node __tw_common.skc_node
-#define tw_bind_node __tw_common.skc_bind_node
-#define tw_refcnt __tw_common.skc_refcnt
- volatile unsigned char tw_substate;
- unsigned char tw_rcv_wscale;
- __u16 tw_sport;
- /* Socket demultiplex comparisons on incoming packets. */
- /* these five are in inet_sock */
- __u32 tw_daddr
- __attribute__((aligned(TCP_ADDRCMP_ALIGN_BYTES)));
- __u32 tw_rcv_saddr;
- __u16 tw_dport;
- __u16 tw_num;
- /* And these are ours. */
- int tw_hashent;
- int tw_timeout;
- __u32 tw_rcv_nxt;
- __u32 tw_snd_nxt;
- __u32 tw_rcv_wnd;
- __u32 tw_ts_recent;
- long tw_ts_recent_stamp;
- unsigned long tw_ttd;
- struct tcp_bind_bucket *tw_tb;
- struct hlist_node tw_death_node;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct in6_addr tw_v6_daddr;
- struct in6_addr tw_v6_rcv_saddr;
- int tw_v6_ipv6only;
-#endif
-};
-
-static __inline__ void tw_add_node(struct tcp_tw_bucket *tw,
- struct hlist_head *list)
-{
- hlist_add_head(&tw->tw_node, list);
-}
-
-static __inline__ void tw_add_bind_node(struct tcp_tw_bucket *tw,
- struct hlist_head *list)
-{
- hlist_add_head(&tw->tw_bind_node, list);
-}
-
-static inline int tw_dead_hashed(struct tcp_tw_bucket *tw)
-{
- return tw->tw_death_node.pprev != NULL;
-}
-
-static __inline__ void tw_dead_node_init(struct tcp_tw_bucket *tw)
-{
- tw->tw_death_node.pprev = NULL;
-}
-
-static __inline__ void __tw_del_dead_node(struct tcp_tw_bucket *tw)
-{
- __hlist_del(&tw->tw_death_node);
- tw_dead_node_init(tw);
-}
-
-static __inline__ int tw_del_dead_node(struct tcp_tw_bucket *tw)
-{
- if (tw_dead_hashed(tw)) {
- __tw_del_dead_node(tw);
- return 1;
- }
- return 0;
-}
-
-#define tw_for_each(tw, node, head) \
- hlist_for_each_entry(tw, node, head, tw_node)
-
-#define tw_for_each_inmate(tw, node, jail) \
- hlist_for_each_entry(tw, node, jail, tw_death_node)
-
-#define tw_for_each_inmate_safe(tw, node, safe, jail) \
- hlist_for_each_entry_safe(tw, node, safe, jail, tw_death_node)
-
-#define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk))
-
-static inline u32 tcp_v4_rcv_saddr(const struct sock *sk)
-{
- return likely(sk->sk_state != TCP_TIME_WAIT) ?
- inet_sk(sk)->rcv_saddr : tcptw_sk(sk)->tw_rcv_saddr;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static inline struct in6_addr *__tcp_v6_rcv_saddr(const struct sock *sk)
-{
- return likely(sk->sk_state != TCP_TIME_WAIT) ?
- &inet6_sk(sk)->rcv_saddr : &tcptw_sk(sk)->tw_v6_rcv_saddr;
-}
-
-static inline struct in6_addr *tcp_v6_rcv_saddr(const struct sock *sk)
-{
- return sk->sk_family == AF_INET6 ? __tcp_v6_rcv_saddr(sk) : NULL;
-}
-
-#define tcptw_sk_ipv6only(__sk) (tcptw_sk(__sk)->tw_v6_ipv6only)
-
-static inline int tcp_v6_ipv6only(const struct sock *sk)
-{
- return likely(sk->sk_state != TCP_TIME_WAIT) ?
- ipv6_only_sock(sk) : tcptw_sk_ipv6only(sk);
-}
-#else
-# define __tcp_v6_rcv_saddr(__sk) NULL
-# define tcp_v6_rcv_saddr(__sk) NULL
-# define tcptw_sk_ipv6only(__sk) 0
-# define tcp_v6_ipv6only(__sk) 0
-#endif
+#include <linux/seq_file.h>
-extern kmem_cache_t *tcp_timewait_cachep;
-
-static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
-{
- if (atomic_dec_and_test(&tw->tw_refcnt)) {
-#ifdef INET_REFCNT_DEBUG
- printk(KERN_DEBUG "tw_bucket %p released\n", tw);
-#endif
- kmem_cache_free(tcp_timewait_cachep, tw);
- }
-}
+extern struct inet_hashinfo tcp_hashinfo;
extern atomic_t tcp_orphan_count;
-extern int tcp_tw_count;
extern void tcp_time_wait(struct sock *sk, int state, int timeo);
-extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
-
-
-/* Socket demux engine toys. */
-#ifdef __BIG_ENDIAN
-#define TCP_COMBINED_PORTS(__sport, __dport) \
- (((__u32)(__sport)<<16) | (__u32)(__dport))
-#else /* __LITTLE_ENDIAN */
-#define TCP_COMBINED_PORTS(__sport, __dport) \
- (((__u32)(__dport)<<16) | (__u32)(__sport))
-#endif
-
-#if (BITS_PER_LONG == 64)
-#ifdef __BIG_ENDIAN
-#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
- __u64 __name = (((__u64)(__saddr))<<32)|((__u64)(__daddr));
-#else /* __LITTLE_ENDIAN */
-#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
- __u64 __name = (((__u64)(__daddr))<<32)|((__u64)(__saddr));
-#endif /* __BIG_ENDIAN */
-#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
- (((*((__u64 *)&(inet_sk(__sk)->daddr)))== (__cookie)) && \
- ((*((__u32 *)&(inet_sk(__sk)->dport)))== (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define TCP_IPV4_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
- (((*((__u64 *)&(tcptw_sk(__sk)->tw_daddr))) == (__cookie)) && \
- ((*((__u32 *)&(tcptw_sk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#else /* 32-bit arch */
-#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr)
-#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
- ((inet_sk(__sk)->daddr == (__saddr)) && \
- (inet_sk(__sk)->rcv_saddr == (__daddr)) && \
- ((*((__u32 *)&(inet_sk(__sk)->dport)))== (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define TCP_IPV4_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
- ((tcptw_sk(__sk)->tw_daddr == (__saddr)) && \
- (tcptw_sk(__sk)->tw_rcv_saddr == (__daddr)) && \
- ((*((__u32 *)&(tcptw_sk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#endif /* 64-bit arch */
-
-#define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \
- (((*((__u32 *)&(inet_sk(__sk)->dport)))== (__ports)) && \
- ((__sk)->sk_family == AF_INET6) && \
- ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
- ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-
-/* These can have wildcards, don't try too hard. */
-static __inline__ int tcp_lhashfn(unsigned short num)
-{
- return num & (TCP_LHTABLE_SIZE - 1);
-}
-
-static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
-{
- return tcp_lhashfn(inet_sk(sk)->num);
-}
#define MAX_TCP_HEADER (128 + MAX_HEADER)
@@ -478,33 +147,6 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
* timestamps. It must be less than
* minimal timewait lifetime.
*/
-
-#define TCP_TW_RECYCLE_SLOTS_LOG 5
-#define TCP_TW_RECYCLE_SLOTS (1<<TCP_TW_RECYCLE_SLOTS_LOG)
-
-/* If time > 4sec, it is "slow" path, no recycling is required,
- so that we select tick to get range about 4 seconds.
- */
-
-#if HZ <= 16 || HZ > 4096
-# error Unsupported: HZ <= 16 or HZ > 4096
-#elif HZ <= 32
-# define TCP_TW_RECYCLE_TICK (5+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 64
-# define TCP_TW_RECYCLE_TICK (6+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 128
-# define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 256
-# define TCP_TW_RECYCLE_TICK (8+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 512
-# define TCP_TW_RECYCLE_TICK (9+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 1024
-# define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ <= 2048
-# define TCP_TW_RECYCLE_TICK (11+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#else
-# define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#endif
/*
* TCP option
*/
@@ -534,22 +176,18 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
#define TCPOLEN_SACK_BASE_ALIGNED 4
#define TCPOLEN_SACK_PERBLOCK 8
-#define TCP_TIME_RETRANS 1 /* Retransmit timer */
-#define TCP_TIME_DACK 2 /* Delayed ack timer */
-#define TCP_TIME_PROBE0 3 /* Zero window probe timer */
-#define TCP_TIME_KEEPOPEN 4 /* Keepalive timer */
-
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
#define TCP_NAGLE_CORK 2 /* Socket is corked */
#define TCP_NAGLE_PUSH 4 /* Cork is overriden for already queued data */
+extern struct inet_timewait_death_row tcp_death_row;
+
/* sysctl variables for tcp */
extern int sysctl_tcp_timestamps;
extern int sysctl_tcp_window_scaling;
extern int sysctl_tcp_sack;
extern int sysctl_tcp_fin_timeout;
-extern int sysctl_tcp_tw_recycle;
extern int sysctl_tcp_keepalive_time;
extern int sysctl_tcp_keepalive_probes;
extern int sysctl_tcp_keepalive_intvl;
@@ -564,7 +202,6 @@ extern int sysctl_tcp_stdurg;
extern int sysctl_tcp_rfc1337;
extern int sysctl_tcp_abort_on_overflow;
extern int sysctl_tcp_max_orphans;
-extern int sysctl_tcp_max_tw_buckets;
extern int sysctl_tcp_fack;
extern int sysctl_tcp_reordering;
extern int sysctl_tcp_ecn;
@@ -585,12 +222,6 @@ extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
extern int tcp_memory_pressure;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-#define TCP_INET_FAMILY(fam) ((fam) == AF_INET)
-#else
-#define TCP_INET_FAMILY(fam) 1
-#endif
-
/*
* Pointers to address related TCP functions
* (i.e. things that depend on the address family)
@@ -671,9 +302,6 @@ DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics);
#define TCP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(tcp_statistics, field, val)
#define TCP_ADD_STATS_USER(field, val) SNMP_ADD_STATS_USER(tcp_statistics, field, val)
-extern void tcp_put_port(struct sock *sk);
-extern void tcp_inherit_port(struct sock *sk, struct sock *child);
-
extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
@@ -682,7 +310,7 @@ extern int tcp_v4_rcv(struct sk_buff *skb);
extern int tcp_v4_remember_stamp(struct sock *sk);
-extern int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw);
+extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, size_t size);
@@ -704,42 +332,22 @@ extern int tcp_rcv_established(struct sock *sk,
extern void tcp_rcv_space_adjust(struct sock *sk);
-enum tcp_ack_state_t
-{
- TCP_ACK_SCHED = 1,
- TCP_ACK_TIMER = 2,
- TCP_ACK_PUSHED= 4
-};
-
-static inline void tcp_schedule_ack(struct tcp_sock *tp)
+static inline void tcp_dec_quickack_mode(struct sock *sk,
+ const unsigned int pkts)
{
- tp->ack.pending |= TCP_ACK_SCHED;
-}
-
-static inline int tcp_ack_scheduled(struct tcp_sock *tp)
-{
- return tp->ack.pending&TCP_ACK_SCHED;
-}
-
-static __inline__ void tcp_dec_quickack_mode(struct tcp_sock *tp, unsigned int pkts)
-{
- if (tp->ack.quick) {
- if (pkts >= tp->ack.quick) {
- tp->ack.quick = 0;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ if (icsk->icsk_ack.quick) {
+ if (pkts >= icsk->icsk_ack.quick) {
+ icsk->icsk_ack.quick = 0;
/* Leaving quickack mode we deflate ATO. */
- tp->ack.ato = TCP_ATO_MIN;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
} else
- tp->ack.quick -= pkts;
+ icsk->icsk_ack.quick -= pkts;
}
}
-extern void tcp_enter_quickack_mode(struct tcp_sock *tp);
-
-static __inline__ void tcp_delack_init(struct tcp_sock *tp)
-{
- memset(&tp->ack, 0, sizeof(tp->ack));
-}
+extern void tcp_enter_quickack_mode(struct sock *sk);
static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
{
@@ -755,10 +363,9 @@ enum tcp_tw_status
};
-extern enum tcp_tw_status tcp_timewait_state_process(struct tcp_tw_bucket *tw,
+extern enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
struct sk_buff *skb,
- struct tcphdr *th,
- unsigned len);
+ const struct tcphdr *th);
extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
struct request_sock *req,
@@ -773,7 +380,6 @@ extern void tcp_update_metrics(struct sock *sk);
extern void tcp_close(struct sock *sk,
long timeout);
-extern struct sock * tcp_accept(struct sock *sk, int flags, int *err);
extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int tcp_getsockopt(struct sock *sk, int level,
@@ -789,8 +395,6 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
size_t len, int nonblock,
int flags, int *addr_len);
-extern int tcp_listen_start(struct sock *sk);
-
extern void tcp_parse_options(struct sk_buff *skb,
struct tcp_options_received *opt_rx,
int estab);
@@ -799,11 +403,6 @@ extern void tcp_parse_options(struct sk_buff *skb,
* TCP v4 functions exported for the inet6 API
*/
-extern int tcp_v4_rebuild_header(struct sock *sk);
-
-extern int tcp_v4_build_header(struct sock *sk,
- struct sk_buff *skb);
-
extern void tcp_v4_send_check(struct sock *sk,
struct tcphdr *th, int len,
struct sk_buff *skb);
@@ -855,6 +454,7 @@ extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_xmit_retransmit_queue(struct sock *);
extern void tcp_simple_retransmit(struct sock *);
extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
+extern int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
extern void tcp_send_probe0(struct sock *);
extern void tcp_send_partial(struct sock *);
@@ -872,18 +472,15 @@ extern void tcp_cwnd_application_limited(struct sock *sk);
/* tcp_timer.c */
extern void tcp_init_xmit_timers(struct sock *);
-extern void tcp_clear_xmit_timers(struct sock *);
+static inline void tcp_clear_xmit_timers(struct sock *sk)
+{
+ inet_csk_clear_xmit_timers(sk);
+}
-extern void tcp_delete_keepalive_timer(struct sock *);
-extern void tcp_reset_keepalive_timer(struct sock *, unsigned long);
extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
extern unsigned int tcp_current_mss(struct sock *sk, int large);
-#ifdef TCP_DEBUG
-extern const char tcp_timer_bug_msg[];
-#endif
-
-/* tcp_diag.c */
+/* tcp.c */
extern void tcp_get_info(struct sock *, struct tcp_info *);
/* Read 'sendfile()'-style from a TCP socket */
@@ -892,72 +489,6 @@ typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
sk_read_actor_t recv_actor);
-static inline void tcp_clear_xmit_timer(struct sock *sk, int what)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- switch (what) {
- case TCP_TIME_RETRANS:
- case TCP_TIME_PROBE0:
- tp->pending = 0;
-
-#ifdef TCP_CLEAR_TIMERS
- sk_stop_timer(sk, &tp->retransmit_timer);
-#endif
- break;
- case TCP_TIME_DACK:
- tp->ack.blocked = 0;
- tp->ack.pending = 0;
-
-#ifdef TCP_CLEAR_TIMERS
- sk_stop_timer(sk, &tp->delack_timer);
-#endif
- break;
- default:
-#ifdef TCP_DEBUG
- printk(tcp_timer_bug_msg);
-#endif
- return;
- };
-
-}
-
-/*
- * Reset the retransmission timer
- */
-static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- if (when > TCP_RTO_MAX) {
-#ifdef TCP_DEBUG
- printk(KERN_DEBUG "reset_xmit_timer sk=%p %d when=0x%lx, caller=%p\n", sk, what, when, current_text_addr());
-#endif
- when = TCP_RTO_MAX;
- }
-
- switch (what) {
- case TCP_TIME_RETRANS:
- case TCP_TIME_PROBE0:
- tp->pending = what;
- tp->timeout = jiffies+when;
- sk_reset_timer(sk, &tp->retransmit_timer, tp->timeout);
- break;
-
- case TCP_TIME_DACK:
- tp->ack.pending |= TCP_ACK_TIMER;
- tp->ack.timeout = jiffies+when;
- sk_reset_timer(sk, &tp->delack_timer, tp->ack.timeout);
- break;
-
- default:
-#ifdef TCP_DEBUG
- printk(tcp_timer_bug_msg);
-#endif
- return;
- };
-}
-
/* Initialize RCV_MSS value.
* RCV_MSS is an our guess about MSS used by the peer.
* We haven't any direct information about the MSS.
@@ -975,7 +506,7 @@ static inline void tcp_initialize_rcv_mss(struct sock *sk)
hint = min(hint, TCP_MIN_RCVMSS);
hint = max(hint, TCP_MIN_MSS);
- tp->ack.rcv_mss = hint;
+ inet_csk(sk)->icsk_ack.rcv_mss = hint;
}
static __inline__ void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
@@ -1110,7 +641,8 @@ static inline void tcp_packets_out_inc(struct sock *sk,
tp->packets_out += tcp_skb_pcount(skb);
if (!orig)
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
}
static inline void tcp_packets_out_dec(struct tcp_sock *tp,
@@ -1138,29 +670,29 @@ struct tcp_congestion_ops {
struct list_head list;
/* initialize private data (optional) */
- void (*init)(struct tcp_sock *tp);
+ void (*init)(struct sock *sk);
/* cleanup private data (optional) */
- void (*release)(struct tcp_sock *tp);
+ void (*release)(struct sock *sk);
/* return slow start threshold (required) */
- u32 (*ssthresh)(struct tcp_sock *tp);
+ u32 (*ssthresh)(struct sock *sk);
/* lower bound for congestion window (optional) */
- u32 (*min_cwnd)(struct tcp_sock *tp);
+ u32 (*min_cwnd)(struct sock *sk);
/* do new cwnd calculation (required) */
- void (*cong_avoid)(struct tcp_sock *tp, u32 ack,
+ void (*cong_avoid)(struct sock *sk, u32 ack,
u32 rtt, u32 in_flight, int good_ack);
/* round trip time sample per acked packet (optional) */
- void (*rtt_sample)(struct tcp_sock *tp, u32 usrtt);
+ void (*rtt_sample)(struct sock *sk, u32 usrtt);
/* call before changing ca_state (optional) */
- void (*set_state)(struct tcp_sock *tp, u8 new_state);
+ void (*set_state)(struct sock *sk, u8 new_state);
/* call when cwnd event occurs (optional) */
- void (*cwnd_event)(struct tcp_sock *tp, enum tcp_ca_event ev);
+ void (*cwnd_event)(struct sock *sk, enum tcp_ca_event ev);
/* new value of cwnd after loss (optional) */
- u32 (*undo_cwnd)(struct tcp_sock *tp);
+ u32 (*undo_cwnd)(struct sock *sk);
/* hook for packet ack accounting (optional) */
- void (*pkts_acked)(struct tcp_sock *tp, u32 num_acked);
- /* get info for tcp_diag (optional) */
- void (*get_info)(struct tcp_sock *tp, u32 ext, struct sk_buff *skb);
+ void (*pkts_acked)(struct sock *sk, u32 num_acked);
+ /* get info for inet_diag (optional) */
+ void (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb);
char name[TCP_CA_NAME_MAX];
struct module *owner;
@@ -1169,30 +701,34 @@ struct tcp_congestion_ops {
extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
-extern void tcp_init_congestion_control(struct tcp_sock *tp);
-extern void tcp_cleanup_congestion_control(struct tcp_sock *tp);
+extern void tcp_init_congestion_control(struct sock *sk);
+extern void tcp_cleanup_congestion_control(struct sock *sk);
extern int tcp_set_default_congestion_control(const char *name);
extern void tcp_get_default_congestion_control(char *name);
-extern int tcp_set_congestion_control(struct tcp_sock *tp, const char *name);
+extern int tcp_set_congestion_control(struct sock *sk, const char *name);
extern struct tcp_congestion_ops tcp_init_congestion_ops;
-extern u32 tcp_reno_ssthresh(struct tcp_sock *tp);
-extern void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack,
+extern u32 tcp_reno_ssthresh(struct sock *sk);
+extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack,
u32 rtt, u32 in_flight, int flag);
-extern u32 tcp_reno_min_cwnd(struct tcp_sock *tp);
+extern u32 tcp_reno_min_cwnd(struct sock *sk);
extern struct tcp_congestion_ops tcp_reno;
-static inline void tcp_set_ca_state(struct tcp_sock *tp, u8 ca_state)
+static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
{
- if (tp->ca_ops->set_state)
- tp->ca_ops->set_state(tp, ca_state);
- tp->ca_state = ca_state;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->set_state)
+ icsk->icsk_ca_ops->set_state(sk, ca_state);
+ icsk->icsk_ca_state = ca_state;
}
-static inline void tcp_ca_event(struct tcp_sock *tp, enum tcp_ca_event event)
+static inline void tcp_ca_event(struct sock *sk, const enum tcp_ca_event event)
{
- if (tp->ca_ops->cwnd_event)
- tp->ca_ops->cwnd_event(tp, event);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->cwnd_event)
+ icsk->icsk_ca_ops->cwnd_event(sk, event);
}
/* This determines how many packets are "in the network" to the best
@@ -1218,9 +754,10 @@ static __inline__ unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
* The exception is rate halving phase, when cwnd is decreasing towards
* ssthresh.
*/
-static inline __u32 tcp_current_ssthresh(struct tcp_sock *tp)
+static inline __u32 tcp_current_ssthresh(const struct sock *sk)
{
- if ((1<<tp->ca_state)&(TCPF_CA_CWR|TCPF_CA_Recovery))
+ const struct tcp_sock *tp = tcp_sk(sk);
+ if ((1 << inet_csk(sk)->icsk_ca_state) & (TCPF_CA_CWR | TCPF_CA_Recovery))
return tp->snd_ssthresh;
else
return max(tp->snd_ssthresh,
@@ -1237,10 +774,13 @@ static inline void tcp_sync_left_out(struct tcp_sock *tp)
}
/* Set slow start threshold and cwnd not falling to slow start */
-static inline void __tcp_enter_cwr(struct tcp_sock *tp)
+static inline void __tcp_enter_cwr(struct sock *sk)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tcp_sock *tp = tcp_sk(sk);
+
tp->undo_marker = 0;
- tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+ tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
tp->snd_cwnd = min(tp->snd_cwnd,
tcp_packets_in_flight(tp) + 1U);
tp->snd_cwnd_cnt = 0;
@@ -1249,12 +789,14 @@ static inline void __tcp_enter_cwr(struct tcp_sock *tp)
TCP_ECN_queue_cwr(tp);
}
-static inline void tcp_enter_cwr(struct tcp_sock *tp)
+static inline void tcp_enter_cwr(struct sock *sk)
{
+ struct tcp_sock *tp = tcp_sk(sk);
+
tp->prior_ssthresh = 0;
- if (tp->ca_state < TCP_CA_CWR) {
- __tcp_enter_cwr(tp);
- tcp_set_ca_state(tp, TCP_CA_CWR);
+ if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {
+ __tcp_enter_cwr(sk);
+ tcp_set_ca_state(sk, TCP_CA_CWR);
}
}
@@ -1277,8 +819,10 @@ static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss,
static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp)
{
- if (!tp->packets_out && !tp->pending)
- tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ if (!tp->packets_out && !icsk->icsk_pending)
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+ icsk->icsk_rto, TCP_RTO_MAX);
}
static __inline__ void tcp_push_pending_frames(struct sock *sk,
@@ -1297,9 +841,6 @@ static __inline__ void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
tp->snd_wl1 = seq;
}
-extern void tcp_destroy_sock(struct sock *sk);
-
-
/*
* Calculate(/check) TCP checksum
*/
@@ -1359,8 +900,10 @@ static __inline__ int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
tp->ucopy.memory = 0;
} else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
wake_up_interruptible(sk->sk_sleep);
- if (!tcp_ack_scheduled(tp))
- tcp_reset_xmit_timer(sk, TCP_TIME_DACK, (3*TCP_RTO_MIN)/4);
+ if (!inet_csk_ack_scheduled(sk))
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ (3 * TCP_RTO_MIN) / 4,
+ TCP_RTO_MAX);
}
return 1;
}
@@ -1393,9 +936,9 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
TCP_INC_STATS(TCP_MIB_ESTABRESETS);
sk->sk_prot->unhash(sk);
- if (tcp_sk(sk)->bind_hash &&
+ if (inet_csk(sk)->icsk_bind_hash &&
!(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
- tcp_put_port(sk);
+ inet_put_port(&tcp_hashinfo, sk);
/* fall through */
default:
if (oldstate==TCP_ESTABLISHED)
@@ -1422,7 +965,7 @@ static __inline__ void tcp_done(struct sock *sk)
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
else
- tcp_destroy_sock(sk);
+ inet_csk_destroy_sock(sk);
}
static __inline__ void tcp_sack_reset(struct tcp_options_received *rx_opt)
@@ -1524,54 +1067,6 @@ static inline int tcp_full_space(const struct sock *sk)
return tcp_win_from_space(sk->sk_rcvbuf);
}
-static inline void tcp_acceptq_queue(struct sock *sk, struct request_sock *req,
- struct sock *child)
-{
- reqsk_queue_add(&tcp_sk(sk)->accept_queue, req, sk, child);
-}
-
-static inline void
-tcp_synq_removed(struct sock *sk, struct request_sock *req)
-{
- if (reqsk_queue_removed(&tcp_sk(sk)->accept_queue, req) == 0)
- tcp_delete_keepalive_timer(sk);
-}
-
-static inline void tcp_synq_added(struct sock *sk)
-{
- if (reqsk_queue_added(&tcp_sk(sk)->accept_queue) == 0)
- tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT);
-}
-
-static inline int tcp_synq_len(struct sock *sk)
-{
- return reqsk_queue_len(&tcp_sk(sk)->accept_queue);
-}
-
-static inline int tcp_synq_young(struct sock *sk)
-{
- return reqsk_queue_len_young(&tcp_sk(sk)->accept_queue);
-}
-
-static inline int tcp_synq_is_full(struct sock *sk)
-{
- return reqsk_queue_is_full(&tcp_sk(sk)->accept_queue);
-}
-
-static inline void tcp_synq_unlink(struct tcp_sock *tp, struct request_sock *req,
- struct request_sock **prev)
-{
- reqsk_queue_unlink(&tp->accept_queue, req, prev);
-}
-
-static inline void tcp_synq_drop(struct sock *sk, struct request_sock *req,
- struct request_sock **prev)
-{
- tcp_synq_unlink(tcp_sk(sk), req, prev);
- tcp_synq_removed(sk, req);
- reqsk_free(req);
-}
-
static __inline__ void tcp_openreq_init(struct request_sock *req,
struct tcp_options_received *rx_opt,
struct sk_buff *skb)
@@ -1593,27 +1088,6 @@ static __inline__ void tcp_openreq_init(struct request_sock *req,
extern void tcp_enter_memory_pressure(void);
-extern void tcp_listen_wlock(void);
-
-/* - We may sleep inside this lock.
- * - If sleeping is not required (or called from BH),
- * use plain read_(un)lock(&tcp_lhash_lock).
- */
-
-static inline void tcp_listen_lock(void)
-{
- /* read_lock synchronizes to candidates to writers */
- read_lock(&tcp_lhash_lock);
- atomic_inc(&tcp_lhash_users);
- read_unlock(&tcp_lhash_lock);
-}
-
-static inline void tcp_listen_unlock(void)
-{
- if (atomic_dec_and_test(&tcp_lhash_users))
- wake_up(&tcp_lhash_wait);
-}
-
static inline int keepalive_intvl_when(const struct tcp_sock *tp)
{
return tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl;
@@ -1624,12 +1098,13 @@ static inline int keepalive_time_when(const struct tcp_sock *tp)
return tp->keepalive_time ? : sysctl_tcp_keepalive_time;
}
-static inline int tcp_fin_time(const struct tcp_sock *tp)
+static inline int tcp_fin_time(const struct sock *sk)
{
- int fin_timeout = tp->linger2 ? : sysctl_tcp_fin_timeout;
+ int fin_timeout = tcp_sk(sk)->linger2 ? : sysctl_tcp_fin_timeout;
+ const int rto = inet_csk(sk)->icsk_rto;
- if (fin_timeout < (tp->rto<<2) - (tp->rto>>1))
- fin_timeout = (tp->rto<<2) - (tp->rto>>1);
+ if (fin_timeout < (rto << 2) - (rto >> 1))
+ fin_timeout = (rto << 2) - (rto >> 1);
return fin_timeout;
}
@@ -1658,15 +1133,6 @@ static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, int
return 1;
}
-static inline void tcp_v4_setup_caps(struct sock *sk, struct dst_entry *dst)
-{
- sk->sk_route_caps = dst->dev->features;
- if (sk->sk_route_caps & NETIF_F_TSO) {
- if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
- sk->sk_route_caps &= ~NETIF_F_TSO;
- }
-}
-
#define TCP_CHECK_TIMER(sk) do { } while (0)
static inline int tcp_use_frto(const struct sock *sk)
@@ -1718,4 +1184,16 @@ struct tcp_iter_state {
extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
+extern struct request_sock_ops tcp_request_sock_ops;
+
+extern int tcp_v4_destroy_sock(struct sock *sk);
+
+#ifdef CONFIG_PROC_FS
+extern int tcp4_proc_init(void);
+extern void tcp4_proc_exit(void);
+#endif
+
+extern void tcp_v4_init(struct net_proto_family *ops);
+extern void tcp_init(void);
+
#endif /* _TCP_H */
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index 64980ee8c92a..c6b84397448d 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -88,7 +88,7 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, struct sk_buff *skb)
* it is surely retransmit. It is not in ECN RFC,
* but Linux follows this rule. */
else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags)))
- tcp_enter_quickack_mode(tp);
+ tcp_enter_quickack_mode((struct sock *)tp);
}
}
diff --git a/include/net/tcp_states.h b/include/net/tcp_states.h
new file mode 100644
index 000000000000..b9d4176b2d15
--- /dev/null
+++ b/include/net/tcp_states.h
@@ -0,0 +1,34 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP protocol sk_state field.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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_TCP_STATES_H
+#define _LINUX_TCP_STATES_H
+
+enum {
+ TCP_ESTABLISHED = 1,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_TIME_WAIT,
+ TCP_CLOSE,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_LISTEN,
+ TCP_CLOSING, /* Now a valid state */
+
+ TCP_MAX_STATES /* Leave at the end! */
+};
+
+#define TCP_STATE_MASK 0xF
+
+#endif /* _LINUX_TCP_STATES_H */
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 8b075ab7a26c..4e86f2de6638 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct sock *sk,
extern int datagram_send_ctl(struct msghdr *msg,
struct flowi *fl,
struct ipv6_txoptions *opt,
- int *hlimit);
+ int *hlimit, int *tclass);
#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
diff --git a/include/net/udp.h b/include/net/udp.h
index ac229b761dbc..107b9d791a1f 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -94,6 +94,11 @@ struct udp_iter_state {
struct seq_operations seq_ops;
};
+#ifdef CONFIG_PROC_FS
extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
+
+extern int udp4_proc_init(void);
+extern void udp4_proc_exit(void);
+#endif
#endif /* _UDP_H */
diff --git a/include/net/x25.h b/include/net/x25.h
index 8b39b98876e8..fee62ff8c194 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -175,7 +175,7 @@ extern void x25_kill_by_neigh(struct x25_neigh *);
/* x25_dev.c */
extern void x25_send_frame(struct sk_buff *, struct x25_neigh *);
-extern int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *);
+extern int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
extern void x25_establish_link(struct x25_neigh *);
extern void x25_terminate_link(struct x25_neigh *);
diff --git a/include/net/x25device.h b/include/net/x25device.h
index d45ae883bd1d..1a318374faef 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -8,7 +8,6 @@
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->mac.raw = skb->data;
- skb->input_dev = 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 868ef88ef971..a9d0d8c5dfbf 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -818,7 +818,6 @@ extern void xfrm6_init(void);
extern void xfrm6_fini(void);
extern void xfrm_state_init(void);
extern void xfrm4_state_init(void);
-extern void xfrm4_state_fini(void);
extern void xfrm6_state_init(void);
extern void xfrm6_state_fini(void);
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index b707a603351b..cb8b6e6ce66c 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -151,6 +151,8 @@ struct pcmcia_device {
uniquely define a pcmcia_device */
struct pcmcia_socket *socket;
+ char *devname;
+
u8 device_no;
/* the hardware "function" device; certain subdevices can
diff --git a/drivers/infiniband/include/ib_cache.h b/include/rdma/ib_cache.h
index 44ef6bb9b9df..5bf9834f7dca 100644
--- a/drivers/infiniband/include/ib_cache.h
+++ b/include/rdma/ib_cache.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -35,7 +37,7 @@
#ifndef _IB_CACHE_H
#define _IB_CACHE_H
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
/**
* ib_get_cached_gid - Returns a cached GID table entry
diff --git a/drivers/infiniband/include/ib_cm.h b/include/rdma/ib_cm.h
index da650115e79a..5308683c8c41 100644
--- a/drivers/infiniband/include/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -37,8 +37,8 @@
#if !defined(IB_CM_H)
#define IB_CM_H
-#include <ib_mad.h>
-#include <ib_sa.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_sa.h>
enum ib_cm_state {
IB_CM_IDLE,
@@ -115,7 +115,7 @@ struct ib_cm_req_event_param {
struct ib_sa_path_rec *primary_path;
struct ib_sa_path_rec *alternate_path;
- u64 remote_ca_guid;
+ __be64 remote_ca_guid;
u32 remote_qkey;
u32 remote_qpn;
enum ib_qp_type qp_type;
@@ -132,7 +132,7 @@ struct ib_cm_req_event_param {
};
struct ib_cm_rep_event_param {
- u64 remote_ca_guid;
+ __be64 remote_ca_guid;
u32 remote_qkey;
u32 remote_qpn;
u32 starting_psn;
@@ -146,39 +146,39 @@ struct ib_cm_rep_event_param {
};
enum ib_cm_rej_reason {
- IB_CM_REJ_NO_QP = __constant_htons(1),
- IB_CM_REJ_NO_EEC = __constant_htons(2),
- IB_CM_REJ_NO_RESOURCES = __constant_htons(3),
- IB_CM_REJ_TIMEOUT = __constant_htons(4),
- IB_CM_REJ_UNSUPPORTED = __constant_htons(5),
- IB_CM_REJ_INVALID_COMM_ID = __constant_htons(6),
- IB_CM_REJ_INVALID_COMM_INSTANCE = __constant_htons(7),
- IB_CM_REJ_INVALID_SERVICE_ID = __constant_htons(8),
- IB_CM_REJ_INVALID_TRANSPORT_TYPE = __constant_htons(9),
- IB_CM_REJ_STALE_CONN = __constant_htons(10),
- IB_CM_REJ_RDC_NOT_EXIST = __constant_htons(11),
- IB_CM_REJ_INVALID_GID = __constant_htons(12),
- IB_CM_REJ_INVALID_LID = __constant_htons(13),
- IB_CM_REJ_INVALID_SL = __constant_htons(14),
- IB_CM_REJ_INVALID_TRAFFIC_CLASS = __constant_htons(15),
- IB_CM_REJ_INVALID_HOP_LIMIT = __constant_htons(16),
- IB_CM_REJ_INVALID_PACKET_RATE = __constant_htons(17),
- IB_CM_REJ_INVALID_ALT_GID = __constant_htons(18),
- IB_CM_REJ_INVALID_ALT_LID = __constant_htons(19),
- IB_CM_REJ_INVALID_ALT_SL = __constant_htons(20),
- IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21),
- IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22),
- IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23),
- IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24),
- IB_CM_REJ_PORT_REDIRECT = __constant_htons(25),
- IB_CM_REJ_INVALID_MTU = __constant_htons(26),
- IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27),
- IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28),
- IB_CM_REJ_INVALID_RNR_RETRY = __constant_htons(29),
- IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID = __constant_htons(30),
- IB_CM_REJ_INVALID_CLASS_VERSION = __constant_htons(31),
- IB_CM_REJ_INVALID_FLOW_LABEL = __constant_htons(32),
- IB_CM_REJ_INVALID_ALT_FLOW_LABEL = __constant_htons(33)
+ IB_CM_REJ_NO_QP = 1,
+ IB_CM_REJ_NO_EEC = 2,
+ IB_CM_REJ_NO_RESOURCES = 3,
+ IB_CM_REJ_TIMEOUT = 4,
+ IB_CM_REJ_UNSUPPORTED = 5,
+ IB_CM_REJ_INVALID_COMM_ID = 6,
+ IB_CM_REJ_INVALID_COMM_INSTANCE = 7,
+ IB_CM_REJ_INVALID_SERVICE_ID = 8,
+ IB_CM_REJ_INVALID_TRANSPORT_TYPE = 9,
+ IB_CM_REJ_STALE_CONN = 10,
+ IB_CM_REJ_RDC_NOT_EXIST = 11,
+ IB_CM_REJ_INVALID_GID = 12,
+ IB_CM_REJ_INVALID_LID = 13,
+ IB_CM_REJ_INVALID_SL = 14,
+ IB_CM_REJ_INVALID_TRAFFIC_CLASS = 15,
+ IB_CM_REJ_INVALID_HOP_LIMIT = 16,
+ IB_CM_REJ_INVALID_PACKET_RATE = 17,
+ IB_CM_REJ_INVALID_ALT_GID = 18,
+ IB_CM_REJ_INVALID_ALT_LID = 19,
+ IB_CM_REJ_INVALID_ALT_SL = 20,
+ IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = 21,
+ IB_CM_REJ_INVALID_ALT_HOP_LIMIT = 22,
+ IB_CM_REJ_INVALID_ALT_PACKET_RATE = 23,
+ IB_CM_REJ_PORT_CM_REDIRECT = 24,
+ IB_CM_REJ_PORT_REDIRECT = 25,
+ IB_CM_REJ_INVALID_MTU = 26,
+ IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = 27,
+ IB_CM_REJ_CONSUMER_DEFINED = 28,
+ IB_CM_REJ_INVALID_RNR_RETRY = 29,
+ IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID = 30,
+ IB_CM_REJ_INVALID_CLASS_VERSION = 31,
+ IB_CM_REJ_INVALID_FLOW_LABEL = 32,
+ IB_CM_REJ_INVALID_ALT_FLOW_LABEL = 33
};
struct ib_cm_rej_event_param {
@@ -222,8 +222,7 @@ struct ib_cm_sidr_req_event_param {
struct ib_cm_id *listen_id;
struct ib_device *device;
u8 port;
-
- u16 pkey;
+ u16 pkey;
};
enum ib_cm_sidr_status {
@@ -285,12 +284,13 @@ typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
struct ib_cm_id {
ib_cm_handler cm_handler;
void *context;
- u64 service_id;
- u64 service_mask;
+ __be64 service_id;
+ __be64 service_mask;
enum ib_cm_state state; /* internal CM/debug use */
enum ib_cm_lap_state lap_state; /* internal CM/debug use */
- u32 local_id;
- u32 remote_id;
+ __be32 local_id;
+ __be32 remote_id;
+ u32 remote_cm_qpn; /* 1 unless redirected */
};
/**
@@ -330,13 +330,13 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
* IB_CM_ASSIGN_SERVICE_ID.
*/
int ib_cm_listen(struct ib_cm_id *cm_id,
- u64 service_id,
- u64 service_mask);
+ __be64 service_id,
+ __be64 service_mask);
struct ib_cm_req_param {
struct ib_sa_path_rec *primary_path;
struct ib_sa_path_rec *alternate_path;
- u64 service_id;
+ __be64 service_id;
u32 qp_num;
enum ib_qp_type qp_type;
u32 starting_psn;
@@ -528,7 +528,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
struct ib_cm_sidr_req_param {
struct ib_sa_path_rec *path;
- u64 service_id;
+ __be64 service_id;
int timeout_ms;
const void *private_data;
u8 private_data_len;
diff --git a/drivers/infiniband/include/ib_fmr_pool.h b/include/rdma/ib_fmr_pool.h
index 6c9e24d6e144..86b7e93f198b 100644
--- a/drivers/infiniband/include/ib_fmr_pool.h
+++ b/include/rdma/ib_fmr_pool.h
@@ -36,7 +36,7 @@
#if !defined(IB_FMR_POOL_H)
#define IB_FMR_POOL_H
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
struct ib_fmr_pool;
diff --git a/drivers/infiniband/include/ib_mad.h b/include/rdma/ib_mad.h
index 491b6f25b3b8..53184a38fdf6 100644
--- a/drivers/infiniband/include/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -41,7 +41,7 @@
#include <linux/pci.h>
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
/* Management base version */
#define IB_MGMT_BASE_VERSION 1
@@ -90,6 +90,7 @@
#define IB_MGMT_RMPP_STATUS_SUCCESS 0
#define IB_MGMT_RMPP_STATUS_RESX 1
+#define IB_MGMT_RMPP_STATUS_ABORT_MIN 118
#define IB_MGMT_RMPP_STATUS_T2L 118
#define IB_MGMT_RMPP_STATUS_BAD_LEN 119
#define IB_MGMT_RMPP_STATUS_BAD_SEG 120
@@ -100,6 +101,7 @@
#define IB_MGMT_RMPP_STATUS_UNV 125
#define IB_MGMT_RMPP_STATUS_TMR 126
#define IB_MGMT_RMPP_STATUS_UNSPEC 127
+#define IB_MGMT_RMPP_STATUS_ABORT_MAX 127
#define IB_QP0 0
#define IB_QP1 __constant_htonl(1)
@@ -111,12 +113,12 @@ struct ib_mad_hdr {
u8 mgmt_class;
u8 class_version;
u8 method;
- u16 status;
- u16 class_specific;
- u64 tid;
- u16 attr_id;
- u16 resv;
- u32 attr_mod;
+ __be16 status;
+ __be16 class_specific;
+ __be64 tid;
+ __be16 attr_id;
+ __be16 resv;
+ __be32 attr_mod;
};
struct ib_rmpp_hdr {
@@ -124,8 +126,8 @@ struct ib_rmpp_hdr {
u8 rmpp_type;
u8 rmpp_rtime_flags;
u8 rmpp_status;
- u32 seg_num;
- u32 paylen_newwin;
+ __be32 seg_num;
+ __be32 paylen_newwin;
};
typedef u64 __bitwise ib_sa_comp_mask;
@@ -139,9 +141,9 @@ typedef u64 __bitwise ib_sa_comp_mask;
* the wire so we can't change the layout)
*/
struct ib_sa_hdr {
- u64 sm_key;
- u16 attr_offset;
- u16 reserved;
+ __be64 sm_key;
+ __be16 attr_offset;
+ __be16 reserved;
ib_sa_comp_mask comp_mask;
} __attribute__ ((packed));
@@ -171,6 +173,27 @@ struct ib_vendor_mad {
u8 data[216];
};
+struct ib_class_port_info
+{
+ u8 base_version;
+ u8 class_version;
+ __be16 capability_mask;
+ u8 reserved[3];
+ u8 resp_time_value;
+ u8 redirect_gid[16];
+ __be32 redirect_tcslfl;
+ __be16 redirect_lid;
+ __be16 redirect_pkey;
+ __be32 redirect_qp;
+ __be32 redirect_qkey;
+ u8 trap_gid[16];
+ __be32 trap_tcslfl;
+ __be16 trap_lid;
+ __be16 trap_pkey;
+ __be32 trap_hlqp;
+ __be32 trap_qkey;
+};
+
/**
* ib_mad_send_buf - MAD data buffer and work request for sends.
* @mad: References an allocated MAD data buffer. The size of the data
diff --git a/drivers/infiniband/include/ib_pack.h b/include/rdma/ib_pack.h
index fe480f3e8654..f926020d6331 100644
--- a/drivers/infiniband/include/ib_pack.h
+++ b/include/rdma/ib_pack.h
@@ -35,7 +35,7 @@
#ifndef IB_PACK_H
#define IB_PACK_H
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
enum {
IB_LRH_BYTES = 8,
diff --git a/drivers/infiniband/include/ib_sa.h b/include/rdma/ib_sa.h
index 6d999f7b5d93..a7555c800ecf 100644
--- a/drivers/infiniband/include/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -38,15 +38,44 @@
#include <linux/compiler.h>
-#include <ib_verbs.h>
-#include <ib_mad.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
enum {
IB_SA_CLASS_VERSION = 2, /* IB spec version 1.1/1.2 */
IB_SA_METHOD_GET_TABLE = 0x12,
IB_SA_METHOD_GET_TABLE_RESP = 0x92,
- IB_SA_METHOD_DELETE = 0x15
+ IB_SA_METHOD_DELETE = 0x15,
+ IB_SA_METHOD_DELETE_RESP = 0x95,
+ IB_SA_METHOD_GET_MULTI = 0x14,
+ IB_SA_METHOD_GET_MULTI_RESP = 0x94,
+ IB_SA_METHOD_GET_TRACE_TBL = 0x13
+};
+
+enum {
+ IB_SA_ATTR_CLASS_PORTINFO = 0x01,
+ IB_SA_ATTR_NOTICE = 0x02,
+ IB_SA_ATTR_INFORM_INFO = 0x03,
+ IB_SA_ATTR_NODE_REC = 0x11,
+ IB_SA_ATTR_PORT_INFO_REC = 0x12,
+ IB_SA_ATTR_SL2VL_REC = 0x13,
+ IB_SA_ATTR_SWITCH_REC = 0x14,
+ IB_SA_ATTR_LINEAR_FDB_REC = 0x15,
+ IB_SA_ATTR_RANDOM_FDB_REC = 0x16,
+ IB_SA_ATTR_MCAST_FDB_REC = 0x17,
+ IB_SA_ATTR_SM_INFO_REC = 0x18,
+ IB_SA_ATTR_LINK_REC = 0x20,
+ IB_SA_ATTR_GUID_INFO_REC = 0x30,
+ IB_SA_ATTR_SERVICE_REC = 0x31,
+ IB_SA_ATTR_PARTITION_REC = 0x33,
+ IB_SA_ATTR_PATH_REC = 0x35,
+ IB_SA_ATTR_VL_ARB_REC = 0x36,
+ IB_SA_ATTR_MC_MEMBER_REC = 0x38,
+ IB_SA_ATTR_TRACE_REC = 0x39,
+ IB_SA_ATTR_MULTI_PATH_REC = 0x3a,
+ IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b,
+ IB_SA_ATTR_INFORM_INFO_REC = 0xf3
};
enum ib_sa_selector {
@@ -133,16 +162,16 @@ struct ib_sa_path_rec {
/* reserved */
union ib_gid dgid;
union ib_gid sgid;
- u16 dlid;
- u16 slid;
+ __be16 dlid;
+ __be16 slid;
int raw_traffic;
/* reserved */
- u32 flow_label;
+ __be32 flow_label;
u8 hop_limit;
u8 traffic_class;
int reversible;
u8 numb_path;
- u16 pkey;
+ __be16 pkey;
/* reserved */
u8 sl;
u8 mtu_selector;
@@ -176,18 +205,18 @@ struct ib_sa_path_rec {
struct ib_sa_mcmember_rec {
union ib_gid mgid;
union ib_gid port_gid;
- u32 qkey;
- u16 mlid;
+ __be32 qkey;
+ __be16 mlid;
u8 mtu_selector;
u8 mtu;
u8 traffic_class;
- u16 pkey;
+ __be16 pkey;
u8 rate_selector;
u8 rate;
u8 packet_life_time_selector;
u8 packet_life_time;
u8 sl;
- u32 flow_label;
+ __be32 flow_label;
u8 hop_limit;
u8 scope;
u8 join_state;
@@ -238,7 +267,7 @@ struct ib_sa_mcmember_rec {
struct ib_sa_service_rec {
u64 id;
union ib_gid gid;
- u16 pkey;
+ __be16 pkey;
/* reserved */
u32 lease;
u8 key[16];
diff --git a/drivers/infiniband/include/ib_smi.h b/include/rdma/ib_smi.h
index ca8216514963..87f60737f695 100644
--- a/drivers/infiniband/include/ib_smi.h
+++ b/include/rdma/ib_smi.h
@@ -39,9 +39,7 @@
#if !defined( IB_SMI_H )
#define IB_SMI_H
-#include <ib_mad.h>
-
-#define IB_LID_PERMISSIVE 0xFFFF
+#include <rdma/ib_mad.h>
#define IB_SMP_DATA_SIZE 64
#define IB_SMP_MAX_PATH_HOPS 64
@@ -51,16 +49,16 @@ struct ib_smp {
u8 mgmt_class;
u8 class_version;
u8 method;
- u16 status;
+ __be16 status;
u8 hop_ptr;
u8 hop_cnt;
- u64 tid;
- u16 attr_id;
- u16 resv;
- u32 attr_mod;
- u64 mkey;
- u16 dr_slid;
- u16 dr_dlid;
+ __be64 tid;
+ __be16 attr_id;
+ __be16 resv;
+ __be32 attr_mod;
+ __be64 mkey;
+ __be16 dr_slid;
+ __be16 dr_dlid;
u8 reserved[28];
u8 data[IB_SMP_DATA_SIZE];
u8 initial_path[IB_SMP_MAX_PATH_HOPS];
diff --git a/drivers/infiniband/include/ib_user_cm.h b/include/rdma/ib_user_cm.h
index 500b1af6ff77..e4d1654276ad 100644
--- a/drivers/infiniband/include/ib_user_cm.h
+++ b/include/rdma/ib_user_cm.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel 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
@@ -37,7 +38,7 @@
#include <linux/types.h>
-#define IB_USER_CM_ABI_VERSION 1
+#define IB_USER_CM_ABI_VERSION 2
enum {
IB_USER_CM_CMD_CREATE_ID,
@@ -60,6 +61,7 @@ enum {
IB_USER_CM_CMD_SEND_SIDR_REP,
IB_USER_CM_CMD_EVENT,
+ IB_USER_CM_CMD_INIT_QP_ATTR,
};
/*
* command ABI structures.
@@ -71,6 +73,7 @@ struct ib_ucm_cmd_hdr {
};
struct ib_ucm_create_id {
+ __u64 uid;
__u64 response;
};
@@ -79,24 +82,87 @@ struct ib_ucm_create_id_resp {
};
struct ib_ucm_destroy_id {
+ __u64 response;
__u32 id;
};
+struct ib_ucm_destroy_id_resp {
+ __u32 events_reported;
+};
+
struct ib_ucm_attr_id {
__u64 response;
__u32 id;
};
struct ib_ucm_attr_id_resp {
- __u64 service_id;
- __u64 service_mask;
- __u32 local_id;
- __u32 remote_id;
+ __be64 service_id;
+ __be64 service_mask;
+ __be32 local_id;
+ __be32 remote_id;
+};
+
+struct ib_ucm_init_qp_attr {
+ __u64 response;
+ __u32 id;
+ __u32 qp_state;
+};
+
+struct ib_ucm_ah_attr {
+ __u8 grh_dgid[16];
+ __u32 grh_flow_label;
+ __u16 dlid;
+ __u16 reserved;
+ __u8 grh_sgid_index;
+ __u8 grh_hop_limit;
+ __u8 grh_traffic_class;
+ __u8 sl;
+ __u8 src_path_bits;
+ __u8 static_rate;
+ __u8 is_global;
+ __u8 port_num;
+};
+
+struct ib_ucm_init_qp_attr_resp {
+ __u32 qp_attr_mask;
+ __u32 qp_state;
+ __u32 cur_qp_state;
+ __u32 path_mtu;
+ __u32 path_mig_state;
+ __u32 qkey;
+ __u32 rq_psn;
+ __u32 sq_psn;
+ __u32 dest_qp_num;
+ __u32 qp_access_flags;
+
+ struct ib_ucm_ah_attr ah_attr;
+ struct ib_ucm_ah_attr alt_ah_attr;
+
+ /* ib_qp_cap */
+ __u32 max_send_wr;
+ __u32 max_recv_wr;
+ __u32 max_send_sge;
+ __u32 max_recv_sge;
+ __u32 max_inline_data;
+
+ __u16 pkey_index;
+ __u16 alt_pkey_index;
+ __u8 en_sqd_async_notify;
+ __u8 sq_draining;
+ __u8 max_rd_atomic;
+ __u8 max_dest_rd_atomic;
+ __u8 min_rnr_timer;
+ __u8 port_num;
+ __u8 timeout;
+ __u8 retry_cnt;
+ __u8 rnr_retry;
+ __u8 alt_port_num;
+ __u8 alt_timeout;
};
struct ib_ucm_listen {
- __u64 service_id;
- __u64 service_mask;
+ __be64 service_id;
+ __be64 service_mask;
__u32 id;
};
@@ -114,13 +180,13 @@ struct ib_ucm_private_data {
struct ib_ucm_path_rec {
__u8 dgid[16];
__u8 sgid[16];
- __u16 dlid;
- __u16 slid;
+ __be16 dlid;
+ __be16 slid;
__u32 raw_traffic;
- __u32 flow_label;
+ __be32 flow_label;
__u32 reversible;
__u32 mtu;
- __u16 pkey;
+ __be16 pkey;
__u8 hop_limit;
__u8 traffic_class;
__u8 numb_path;
@@ -138,7 +204,7 @@ struct ib_ucm_req {
__u32 qpn;
__u32 qp_type;
__u32 psn;
- __u64 sid;
+ __be64 sid;
__u64 data;
__u64 primary_path;
__u64 alternate_path;
@@ -157,6 +223,7 @@ struct ib_ucm_req {
};
struct ib_ucm_rep {
+ __u64 uid;
__u64 data;
__u32 id;
__u32 qpn;
@@ -200,7 +267,7 @@ struct ib_ucm_lap {
struct ib_ucm_sidr_req {
__u32 id;
__u32 timeout;
- __u64 sid;
+ __be64 sid;
__u64 data;
__u64 path;
__u16 pkey;
@@ -232,12 +299,11 @@ struct ib_ucm_event_get {
};
struct ib_ucm_req_event_resp {
- __u32 listen_id;
/* device */
/* port */
struct ib_ucm_path_rec primary_path;
struct ib_ucm_path_rec alternate_path;
- __u64 remote_ca_guid;
+ __be64 remote_ca_guid;
__u32 remote_qkey;
__u32 remote_qpn;
__u32 qp_type;
@@ -253,7 +319,7 @@ struct ib_ucm_req_event_resp {
};
struct ib_ucm_rep_event_resp {
- __u64 remote_ca_guid;
+ __be64 remote_ca_guid;
__u32 remote_qkey;
__u32 remote_qpn;
__u32 starting_psn;
@@ -287,7 +353,6 @@ struct ib_ucm_apr_event_resp {
};
struct ib_ucm_sidr_req_event_resp {
- __u32 listen_id;
/* device */
/* port */
__u16 pkey;
@@ -307,6 +372,7 @@ struct ib_ucm_sidr_rep_event_resp {
#define IB_UCM_PRES_ALTERNATE 0x08
struct ib_ucm_event_resp {
+ __u64 uid;
__u32 id;
__u32 event;
__u32 present;
diff --git a/drivers/infiniband/include/ib_user_mad.h b/include/rdma/ib_user_mad.h
index a9a56b50aacc..44537aa32e62 100644
--- a/drivers/infiniband/include/ib_user_mad.h
+++ b/include/rdma/ib_user_mad.h
@@ -70,8 +70,6 @@
* @traffic_class - Traffic class in GRH
* @gid - Remote GID in GRH
* @flow_label - Flow label in GRH
- *
- * All multi-byte quantities are stored in network (big endian) byte order.
*/
struct ib_user_mad_hdr {
__u32 id;
@@ -79,9 +77,9 @@ struct ib_user_mad_hdr {
__u32 timeout_ms;
__u32 retries;
__u32 length;
- __u32 qpn;
- __u32 qkey;
- __u16 lid;
+ __be32 qpn;
+ __be32 qkey;
+ __be16 lid;
__u8 sl;
__u8 path_bits;
__u8 grh_present;
@@ -89,7 +87,7 @@ struct ib_user_mad_hdr {
__u8 hop_limit;
__u8 traffic_class;
__u8 gid[16];
- __u32 flow_label;
+ __be32 flow_label;
};
/**
diff --git a/drivers/infiniband/include/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index 7c613706af72..fd85725391a4 100644
--- a/drivers/infiniband/include/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -42,7 +42,7 @@
* Increment this value if any changes that break userspace ABI
* compatibility are made.
*/
-#define IB_USER_VERBS_ABI_VERSION 1
+#define IB_USER_VERBS_ABI_VERSION 2
enum {
IB_USER_VERBS_CMD_QUERY_PARAMS,
@@ -78,7 +78,12 @@ enum {
IB_USER_VERBS_CMD_POST_SEND,
IB_USER_VERBS_CMD_POST_RECV,
IB_USER_VERBS_CMD_ATTACH_MCAST,
- IB_USER_VERBS_CMD_DETACH_MCAST
+ IB_USER_VERBS_CMD_DETACH_MCAST,
+ IB_USER_VERBS_CMD_CREATE_SRQ,
+ IB_USER_VERBS_CMD_MODIFY_SRQ,
+ IB_USER_VERBS_CMD_QUERY_SRQ,
+ IB_USER_VERBS_CMD_DESTROY_SRQ,
+ IB_USER_VERBS_CMD_POST_SRQ_RECV
};
/*
@@ -143,8 +148,8 @@ struct ib_uverbs_query_device {
struct ib_uverbs_query_device_resp {
__u64 fw_ver;
- __u64 node_guid;
- __u64 sys_image_guid;
+ __be64 node_guid;
+ __be64 sys_image_guid;
__u64 max_mr_size;
__u64 page_size_cap;
__u32 vendor_id;
@@ -287,7 +292,14 @@ struct ib_uverbs_create_cq_resp {
};
struct ib_uverbs_destroy_cq {
+ __u64 response;
__u32 cq_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_destroy_cq_resp {
+ __u32 comp_events_reported;
+ __u32 async_events_reported;
};
struct ib_uverbs_create_qp {
@@ -367,7 +379,13 @@ struct ib_uverbs_modify_qp_resp {
};
struct ib_uverbs_destroy_qp {
+ __u64 response;
__u32 qp_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_destroy_qp_resp {
+ __u32 events_reported;
};
struct ib_uverbs_attach_mcast {
@@ -386,4 +404,38 @@ struct ib_uverbs_detach_mcast {
__u64 driver_data[0];
};
+struct ib_uverbs_create_srq {
+ __u64 response;
+ __u64 user_handle;
+ __u32 pd_handle;
+ __u32 max_wr;
+ __u32 max_sge;
+ __u32 srq_limit;
+ __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq_resp {
+ __u32 srq_handle;
+};
+
+struct ib_uverbs_modify_srq {
+ __u32 srq_handle;
+ __u32 attr_mask;
+ __u32 max_wr;
+ __u32 max_sge;
+ __u32 srq_limit;
+ __u32 reserved;
+ __u64 driver_data[0];
+};
+
+struct ib_uverbs_destroy_srq {
+ __u64 response;
+ __u32 srq_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq_resp {
+ __u32 events_reported;
+};
+
#endif /* IB_USER_VERBS_H */
diff --git a/drivers/infiniband/include/ib_verbs.h b/include/rdma/ib_verbs.h
index 5d24edaa66e6..e16cf94870f2 100644
--- a/drivers/infiniband/include/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -4,6 +4,7 @@
* 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) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -50,8 +51,8 @@
union ib_gid {
u8 raw[16];
struct {
- u64 subnet_prefix;
- u64 interface_id;
+ __be64 subnet_prefix;
+ __be64 interface_id;
} global;
};
@@ -87,8 +88,8 @@ enum ib_atomic_cap {
struct ib_device_attr {
u64 fw_ver;
- u64 node_guid;
- u64 sys_image_guid;
+ __be64 node_guid;
+ __be64 sys_image_guid;
u64 max_mr_size;
u64 page_size_cap;
u32 vendor_id;
@@ -255,7 +256,10 @@ enum ib_event_type {
IB_EVENT_PORT_ERR,
IB_EVENT_LID_CHANGE,
IB_EVENT_PKEY_CHANGE,
- IB_EVENT_SM_CHANGE
+ IB_EVENT_SM_CHANGE,
+ IB_EVENT_SRQ_ERR,
+ IB_EVENT_SRQ_LIMIT_REACHED,
+ IB_EVENT_QP_LAST_WQE_REACHED
};
struct ib_event {
@@ -263,6 +267,7 @@ struct ib_event {
union {
struct ib_cq *cq;
struct ib_qp *qp;
+ struct ib_srq *srq;
u8 port_num;
} element;
enum ib_event_type event;
@@ -290,8 +295,8 @@ struct ib_global_route {
};
struct ib_grh {
- u32 version_tclass_flow;
- u16 paylen;
+ __be32 version_tclass_flow;
+ __be16 paylen;
u8 next_hdr;
u8 hop_limit;
union ib_gid sgid;
@@ -302,6 +307,8 @@ enum {
IB_MULTICAST_QPN = 0xffffff
};
+#define IB_LID_PERMISSIVE __constant_htons(0xFFFF)
+
enum ib_ah_flags {
IB_AH_GRH = 1
};
@@ -383,6 +390,23 @@ enum ib_cq_notify {
IB_CQ_NEXT_COMP
};
+enum ib_srq_attr_mask {
+ IB_SRQ_MAX_WR = 1 << 0,
+ IB_SRQ_LIMIT = 1 << 1,
+};
+
+struct ib_srq_attr {
+ u32 max_wr;
+ u32 max_sge;
+ u32 srq_limit;
+};
+
+struct ib_srq_init_attr {
+ void (*event_handler)(struct ib_event *, void *);
+ void *srq_context;
+ struct ib_srq_attr attr;
+};
+
struct ib_qp_cap {
u32 max_send_wr;
u32 max_recv_wr;
@@ -710,10 +734,11 @@ struct ib_cq {
};
struct ib_srq {
- struct ib_device *device;
- struct ib_uobject *uobject;
- struct ib_pd *pd;
- void *srq_context;
+ struct ib_device *device;
+ struct ib_pd *pd;
+ struct ib_uobject *uobject;
+ void (*event_handler)(struct ib_event *, void *);
+ void *srq_context;
atomic_t usecnt;
};
@@ -827,6 +852,18 @@ struct ib_device {
int (*query_ah)(struct ib_ah *ah,
struct ib_ah_attr *ah_attr);
int (*destroy_ah)(struct ib_ah *ah);
+ struct ib_srq * (*create_srq)(struct ib_pd *pd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata);
+ int (*modify_srq)(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask);
+ int (*query_srq)(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr);
+ int (*destroy_srq)(struct ib_srq *srq);
+ int (*post_srq_recv)(struct ib_srq *srq,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr);
struct ib_qp * (*create_qp)(struct ib_pd *pd,
struct ib_qp_init_attr *qp_init_attr,
struct ib_udata *udata);
@@ -1039,6 +1076,65 @@ int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
int ib_destroy_ah(struct ib_ah *ah);
/**
+ * ib_create_srq - Creates a SRQ associated with the specified protection
+ * domain.
+ * @pd: The protection domain associated with the SRQ.
+ * @srq_init_attr: A list of initial attributes required to create the SRQ.
+ *
+ * srq_attr->max_wr and srq_attr->max_sge are read the determine the
+ * requested size of the SRQ, and set to the actual values allocated
+ * on return. If ib_create_srq() succeeds, then max_wr and max_sge
+ * will always be at least as large as the requested values.
+ */
+struct ib_srq *ib_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *srq_init_attr);
+
+/**
+ * ib_modify_srq - Modifies the attributes for the specified SRQ.
+ * @srq: The SRQ to modify.
+ * @srq_attr: On input, specifies the SRQ attributes to modify. On output,
+ * the current values of selected SRQ attributes are returned.
+ * @srq_attr_mask: A bit-mask used to specify which attributes of the SRQ
+ * are being modified.
+ *
+ * The mask may contain IB_SRQ_MAX_WR to resize the SRQ and/or
+ * IB_SRQ_LIMIT to set the SRQ's limit and request notification when
+ * the number of receives queued drops below the limit.
+ */
+int ib_modify_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask);
+
+/**
+ * ib_query_srq - Returns the attribute list and current values for the
+ * specified SRQ.
+ * @srq: The SRQ to query.
+ * @srq_attr: The attributes of the specified SRQ.
+ */
+int ib_query_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr);
+
+/**
+ * ib_destroy_srq - Destroys the specified SRQ.
+ * @srq: The SRQ to destroy.
+ */
+int ib_destroy_srq(struct ib_srq *srq);
+
+/**
+ * ib_post_srq_recv - Posts a list of work requests to the specified SRQ.
+ * @srq: The SRQ to post the work request on.
+ * @recv_wr: A list of work requests to post on the receive queue.
+ * @bad_recv_wr: On an immediate failure, this parameter will reference
+ * the work request that failed to be posted on the QP.
+ */
+static inline int ib_post_srq_recv(struct ib_srq *srq,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr)
+{
+ return srq->device->post_srq_recv(srq, recv_wr, bad_recv_wr);
+}
+
+/**
* ib_create_qp - Creates a QP associated with the specified protection
* domain.
* @pd: The protection domain associated with the QP.
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 9957f16dcc5d..bed4b7c9be99 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -51,12 +51,16 @@ struct scsi_cmnd {
* printk's to use ->pid, so that we can kill this field.
*/
unsigned long serial_number;
+ /*
+ * This is set to jiffies as it was when the command was first
+ * allocated. It is used to time how long the command has
+ * been outstanding
+ */
+ unsigned long jiffies_at_alloc;
int retries;
int allowed;
int timeout_per_command;
- int timeout_total;
- int timeout;
unsigned char cmd_len;
unsigned char old_cmd_len;
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index 12e90934a7a8..b090a11d7e1c 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -3,8 +3,10 @@
struct scsi_cmnd;
struct scsi_request;
+struct scsi_sense_hdr;
extern void scsi_print_command(struct scsi_cmnd *);
+extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
extern void __scsi_print_command(unsigned char *);
extern void scsi_print_sense(const char *, struct scsi_cmnd *);
extern void scsi_print_req_sense(const char *, struct scsi_request *);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 835af8ecbb7c..c0e4c67d836f 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -8,8 +8,17 @@
struct request_queue;
struct scsi_cmnd;
-struct scsi_mode_data;
struct scsi_lun;
+struct scsi_sense_hdr;
+
+struct scsi_mode_data {
+ __u32 length;
+ __u16 block_descriptor_length;
+ __u8 medium_type;
+ __u8 device_specific;
+ __u8 header_length;
+ __u8 longlba:1;
+};
/*
* sdev state: If you alter this, you also need to alter scsi_sysfs.c
@@ -169,8 +178,8 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev)
extern struct scsi_device *__scsi_add_device(struct Scsi_Host *,
uint, uint, uint, void *hostdata);
-#define scsi_add_device(host, channel, target, lun) \
- __scsi_add_device(host, channel, target, lun, NULL)
+extern int scsi_add_device(struct Scsi_Host *host, uint channel,
+ uint target, uint lun);
extern void scsi_remove_device(struct scsi_device *);
extern int scsi_device_cancel(struct scsi_device *, int);
@@ -228,7 +237,8 @@ extern int scsi_set_medium_removal(struct scsi_device *, char);
extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout,
- int retries, struct scsi_mode_data *data);
+ int retries, struct scsi_mode_data *data,
+ struct scsi_sense_hdr *);
extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
int retries);
extern int scsi_device_set_state(struct scsi_device *sdev,
@@ -247,6 +257,14 @@ extern void int_to_scsilun(unsigned int, struct scsi_lun *);
extern const char *scsi_device_state_name(enum scsi_device_state);
extern int scsi_is_sdev_device(const struct device *);
extern int scsi_is_target_device(const struct device *);
+extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ unsigned char *sense, int timeout, int retries,
+ int flag);
+extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ struct scsi_sense_hdr *, int timeout, int retries);
+
static inline int scsi_device_online(struct scsi_device *sdev)
{
return sdev->sdev_state != SDEV_OFFLINE;
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 80557f879e3e..fabd879c2f2e 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -26,10 +26,15 @@ struct scsi_sense_hdr { /* See SPC-3 section 4.5 */
u8 additional_length; /* always 0 for fixed sense format */
};
+static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
+{
+ if (!sshdr)
+ return 0;
+
+ return (sshdr->response_code & 0x70) == 0x70;
+}
+
-extern void scsi_add_timer(struct scsi_cmnd *, int,
- void (*)(struct scsi_cmnd *));
-extern int scsi_delete_timer(struct scsi_cmnd *);
extern void scsi_report_bus_reset(struct Scsi_Host *, int);
extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
extern int scsi_block_when_processing_errors(struct scsi_device *);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 81d5234f6771..916144be208b 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -429,12 +429,15 @@ struct scsi_host_template {
};
/*
- * shost states
+ * shost state: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions) and the state model enforcer:
+ * scsi_host_set_state()
*/
-enum {
- SHOST_ADD,
- SHOST_DEL,
+enum scsi_host_state {
+ SHOST_CREATED = 1,
+ SHOST_RUNNING,
SHOST_CANCEL,
+ SHOST_DEL,
SHOST_RECOVERY,
};
@@ -464,12 +467,10 @@ struct Scsi_Host {
struct task_struct * ehandler; /* Error recovery thread. */
struct semaphore * eh_wait; /* The error recovery thread waits
on this. */
- struct completion * eh_notify; /* wait for eh to begin or end */
struct semaphore * eh_action; /* Wait for specific actions on the
host. */
unsigned int eh_active:1; /* Indicates the eh thread is awake and active if
this is true. */
- unsigned int eh_kill:1; /* set when killing the eh thread */
wait_queue_head_t host_wait;
struct scsi_host_template *hostt;
struct scsi_transport_template *transportt;
@@ -575,7 +576,7 @@ struct Scsi_Host {
unsigned int irq;
- unsigned long shost_state;
+ enum scsi_host_state shost_state;
/* ldm bits */
struct device shost_gendev;
@@ -633,6 +634,7 @@ extern void scsi_remove_host(struct Scsi_Host *);
extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
extern void scsi_host_put(struct Scsi_Host *t);
extern struct Scsi_Host *scsi_host_lookup(unsigned short);
+extern const char *scsi_host_state_name(enum scsi_host_state);
extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
@@ -646,6 +648,15 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost)
return shost->shost_gendev.parent;
}
+/**
+ * scsi_host_scan_allowed - Is scanning of this host allowed
+ * @shost: Pointer to Scsi_Host.
+ **/
+static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
+{
+ return shost->shost_state == SHOST_RUNNING;
+}
+
extern void scsi_unblock_requests(struct Scsi_Host *);
extern void scsi_block_requests(struct Scsi_Host *);
@@ -663,5 +674,6 @@ extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
/* legacy interfaces */
extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
extern void scsi_unregister(struct Scsi_Host *);
+extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
#endif /* _SCSI_SCSI_HOST_H */
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index 98719407d554..6a140020d7cb 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -54,20 +54,4 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd,
void *buffer, unsigned bufflen,
void (*done) (struct scsi_cmnd *),
int timeout, int retries);
-
-struct scsi_mode_data {
- __u32 length;
- __u16 block_descriptor_length;
- __u8 medium_type;
- __u8 device_specific;
- __u8 header_length;
- __u8 longlba:1;
-};
-
-extern int __scsi_mode_sense(struct scsi_request *SRpnt, int dbd,
- int modepage, unsigned char *buffer, int len,
- int timeout, int retries,
- struct scsi_mode_data *data);
-
-
#endif /* _SCSI_SCSI_REQUEST_H */
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 70ad16315a16..115db056dc6b 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -439,4 +439,12 @@ int fc_remote_port_block(struct fc_rport *rport);
void fc_remote_port_unblock(struct fc_rport *rport);
int scsi_is_fc_rport(const struct device *);
+static inline u64 wwn_to_u64(u8 *wwn)
+{
+ return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 |
+ (u64)wwn[2] << 40 | (u64)wwn[3] << 32 |
+ (u64)wwn[4] << 24 | (u64)wwn[5] << 16 |
+ (u64)wwn[6] << 8 | (u64)wwn[7];
+}
+
#endif /* SCSI_TRANSPORT_FC_H */
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
new file mode 100644
index 000000000000..bc4aeb660dd3
--- /dev/null
+++ b/include/scsi/scsi_transport_sas.h
@@ -0,0 +1,100 @@
+#ifndef SCSI_TRANSPORT_SAS_H
+#define SCSI_TRANSPORT_SAS_H
+
+#include <linux/transport_class.h>
+#include <linux/types.h>
+
+struct scsi_transport_template;
+struct sas_rphy;
+
+
+enum sas_device_type {
+ SAS_PHY_UNUSED,
+ SAS_END_DEVICE,
+ SAS_EDGE_EXPANDER_DEVICE,
+ SAS_FANOUT_EXPANDER_DEVICE,
+};
+
+enum sas_protocol {
+ SAS_PROTOCOL_SATA = 0x01,
+ SAS_PROTOCOL_SMP = 0x02,
+ SAS_PROTOCOL_STP = 0x04,
+ SAS_PROTOCOL_SSP = 0x08,
+};
+
+enum sas_linkrate {
+ SAS_LINK_RATE_UNKNOWN,
+ SAS_PHY_DISABLED,
+ SAS_LINK_RATE_FAILED,
+ SAS_SATA_SPINUP_HOLD,
+ SAS_SATA_PORT_SELECTOR,
+ SAS_LINK_RATE_1_5_GBPS,
+ SAS_LINK_RATE_3_0_GBPS,
+ SAS_LINK_VIRTUAL,
+};
+
+struct sas_identify {
+ enum sas_device_type device_type;
+ enum sas_protocol initiator_port_protocols;
+ enum sas_protocol target_port_protocols;
+ u64 sas_address;
+ u8 phy_identifier;
+};
+
+/* The functions by which the transport class and the driver communicate */
+struct sas_function_template {
+};
+
+struct sas_phy {
+ struct device dev;
+ int number;
+ struct sas_identify identify;
+ enum sas_linkrate negotiated_linkrate;
+ enum sas_linkrate minimum_linkrate_hw;
+ enum sas_linkrate minimum_linkrate;
+ enum sas_linkrate maximum_linkrate_hw;
+ enum sas_linkrate maximum_linkrate;
+ u8 port_identifier;
+ struct sas_rphy *rphy;
+};
+
+#define dev_to_phy(d) \
+ container_of((d), struct sas_phy, dev)
+#define transport_class_to_phy(cdev) \
+ dev_to_phy((cdev)->dev)
+#define phy_to_shost(phy) \
+ dev_to_shost((phy)->dev.parent)
+
+struct sas_rphy {
+ struct device dev;
+ struct sas_identify identify;
+ struct list_head list;
+ u32 scsi_target_id;
+};
+
+#define dev_to_rphy(d) \
+ container_of((d), struct sas_rphy, dev)
+#define transport_class_to_rphy(cdev) \
+ dev_to_rphy((cdev)->dev)
+#define rphy_to_shost(rphy) \
+ dev_to_shost((rphy)->dev.parent)
+
+extern void sas_remove_host(struct Scsi_Host *);
+
+extern struct sas_phy *sas_phy_alloc(struct device *, int);
+extern void sas_phy_free(struct sas_phy *);
+extern int sas_phy_add(struct sas_phy *);
+extern void sas_phy_delete(struct sas_phy *);
+extern int scsi_is_sas_phy(const struct device *);
+
+extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *);
+void sas_rphy_free(struct sas_rphy *);
+extern int sas_rphy_add(struct sas_rphy *);
+extern void sas_rphy_delete(struct sas_rphy *);
+extern int scsi_is_sas_rphy(const struct device *);
+
+extern struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *);
+extern void sas_release_transport(struct scsi_transport_template *);
+
+#endif /* SCSI_TRANSPORT_SAS_H */
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index a30d6cd4c0e8..6bdc4afb2483 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -39,6 +39,7 @@ struct spi_transport_attrs {
unsigned int rd_strm:1; /* Read streaming enabled */
unsigned int rti:1; /* Retain Training Information */
unsigned int pcomp_en:1;/* Precompensation enabled */
+ unsigned int hold_mcs:1;/* Hold Margin Control Settings */
unsigned int initial_dv:1; /* DV done to this target yet */
unsigned long flags; /* flags field for drivers to use */
/* Device Properties fields */
@@ -78,6 +79,7 @@ struct spi_host_attrs {
#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm)
#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rti)
#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
+#define spi_hold_mcs(x) (((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs)
#define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
#define spi_support_sync(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
@@ -114,8 +116,11 @@ struct spi_function_template {
void (*set_rti)(struct scsi_target *, int);
void (*get_pcomp_en)(struct scsi_target *);
void (*set_pcomp_en)(struct scsi_target *, int);
+ void (*get_hold_mcs)(struct scsi_target *);
+ void (*set_hold_mcs)(struct scsi_target *, int);
void (*get_signalling)(struct Scsi_Host *);
void (*set_signalling)(struct Scsi_Host *, enum spi_signal_type);
+ int (*deny_binding)(struct scsi_target *);
/* The driver sets these to tell the transport class it
* wants the attributes displayed in sysfs. If the show_ flag
* is not set, the attribute will be private to the transport
@@ -130,6 +135,7 @@ struct spi_function_template {
unsigned long show_rd_strm:1;
unsigned long show_rti:1;
unsigned long show_pcomp_en:1;
+ unsigned long show_hold_mcs:1;
};
struct scsi_transport_template *spi_attach_transport(struct spi_function_template *);
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 1309c12b8f71..2857cf0472df 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -26,6 +26,7 @@
*/
#include <linux/bitops.h>
+#include <linux/device.h>
#include "pcm.h"
#include "control.h"
#include "info.h"
@@ -374,6 +375,9 @@
#define AC97_HAS_NO_PC_BEEP (1<<12) /* no PC Beep volume */
#define AC97_HAS_NO_VIDEO (1<<13) /* no Video volume */
#define AC97_HAS_NO_CD (1<<14) /* no CD volume */
+#define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */
+#define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */
+#define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */
/* rates indexes */
#define AC97_RATES_FRONT_DAC 0
@@ -520,6 +524,7 @@ struct _snd_ac97 {
/* jack-sharing info */
unsigned char indep_surround;
unsigned char channel_mode;
+ struct device dev;
};
/* conditions */
@@ -599,4 +604,8 @@ struct ac97_enum {
unsigned short mask;
const char **texts;
};
+
+/* ad hoc AC97 device driver access */
+extern struct bus_type ac97_bus_type;
+
#endif /* __SOUND_AC97_CODEC_H */
diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h
index 395978e375cf..ca2e0e4fa937 100644
--- a/include/sound/ad1816a.h
+++ b/include/sound/ad1816a.h
@@ -138,6 +138,7 @@ struct _snd_ad1816a {
spinlock_t lock;
unsigned short mode;
+ unsigned int clock_freq;
snd_card_t *card;
snd_pcm_t *pcm;
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 9974f83cca44..8e552d627fa5 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -560,7 +560,7 @@ enum {
* Timer section - /dev/snd/timer
*/
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
enum sndrv_timer_class {
SNDRV_TIMER_CLASS_NONE = -1,
@@ -693,11 +693,15 @@ enum sndrv_timer_event {
SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
+ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
+ SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
/* master timer events for slave timer instances */
SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
};
struct sndrv_timer_tread {
diff --git a/include/sound/core.h b/include/sound/core.h
index f72b3ef515e2..26160adcdffc 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -168,6 +168,9 @@ struct _snd_card {
wait_queue_head_t shutdown_sleep;
struct work_struct free_workq; /* for free in workqueue */
struct device *dev;
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ struct snd_generic_device *generic_dev;
+#endif
#ifdef CONFIG_PM
int (*pm_suspend)(snd_card_t *card, pm_message_t state);
@@ -176,9 +179,6 @@ struct _snd_card {
unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep;
-#ifdef CONFIG_SND_GENERIC_PM
- struct snd_generic_device *pm_dev; /* for ISA */
-#endif
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -291,12 +291,14 @@ void snd_memory_done(void);
int snd_memory_info_init(void);
int snd_memory_info_done(void);
void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags);
+void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags);
void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags);
void snd_hidden_kfree(const void *obj);
void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj);
char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
+#define kzalloc(size, flags) snd_hidden_kzalloc(size, flags)
#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
#define kfree(obj) snd_hidden_kfree(obj)
#define vmalloc(size) snd_hidden_vmalloc(size)
@@ -346,6 +348,8 @@ int snd_card_file_remove(snd_card_t *card, struct file *file);
#ifndef snd_card_set_dev
#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
#endif
+/* register a generic device (for ISA, etc) */
+int snd_card_set_generic_dev(snd_card_t *card);
/* device.c */
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 182dd276ee74..b0c0e192eb56 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -29,19 +29,6 @@
#include "ac97_codec.h"
#include "cs46xx_dsp_spos.h"
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS 0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
-#endif
-
/*
* Direct registers
*/
@@ -1715,7 +1702,6 @@ struct _snd_cs46xx {
void (*active_ctrl)(cs46xx_t *, int);
void (*mixer_init)(cs46xx_t *);
- struct pci_dev *acpi_dev;
int acpi_port;
snd_kcontrol_t *eapd_switch; /* for amplifier hack */
int accept_valid; /* accept mmap valid (for OSS) */
@@ -1748,7 +1734,7 @@ int snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
-int snd_cs46xx_mixer(cs46xx_t *chip);
+int snd_cs46xx_mixer(cs46xx_t *chip, int spdif_device);
int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
int snd_cs46xx_start_dsp(cs46xx_t *chip);
int snd_cs46xx_gameport(cs46xx_t *chip);
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index c2ef3f023687..67bf3f18e96a 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -35,13 +35,6 @@
#include <linux/interrupt.h>
#include <asm/io.h>
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE 0x1102
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-#endif
-
/* ------------------- DEFINES -------------------- */
#define EMUPAGESIZE 4096
@@ -1178,7 +1171,7 @@ int snd_p16v_free(emu10k1_t * emu);
int snd_p16v_mixer(emu10k1_t * emu);
int snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
-int snd_emu10k1_mixer(emu10k1_t * emu);
+int snd_emu10k1_mixer(emu10k1_t * emu, int pcm_device, int multi_device);
int snd_emu10k1_timer(emu10k1_t * emu, int device);
int snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t ** rhwdep);
diff --git a/include/sound/gus.h b/include/sound/gus.h
index b4b461ca173d..7000d9d9199d 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -512,13 +512,13 @@ extern void snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
extern void snd_gf1_write8(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
extern unsigned char snd_gf1_look8(snd_gus_card_t * gus, unsigned char reg);
-extern inline unsigned char snd_gf1_read8(snd_gus_card_t * gus, unsigned char reg)
+static inline unsigned char snd_gf1_read8(snd_gus_card_t * gus, unsigned char reg)
{
return snd_gf1_look8(gus, reg | 0x80);
}
extern void snd_gf1_write16(snd_gus_card_t * gus, unsigned char reg, unsigned int data);
extern unsigned short snd_gf1_look16(snd_gus_card_t * gus, unsigned char reg);
-extern inline unsigned short snd_gf1_read16(snd_gus_card_t * gus, unsigned char reg)
+static inline unsigned short snd_gf1_read16(snd_gus_card_t * gus, unsigned char reg)
{
return snd_gf1_look16(gus, reg | 0x80);
}
@@ -532,12 +532,12 @@ extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
extern void snd_gf1_i_write8(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
extern unsigned char snd_gf1_i_look8(snd_gus_card_t * gus, unsigned char reg);
extern void snd_gf1_i_write16(snd_gus_card_t * gus, unsigned char reg, unsigned int data);
-extern inline unsigned char snd_gf1_i_read8(snd_gus_card_t * gus, unsigned char reg)
+static inline unsigned char snd_gf1_i_read8(snd_gus_card_t * gus, unsigned char reg)
{
return snd_gf1_i_look8(gus, reg | 0x80);
}
extern unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg);
-extern inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned char reg)
+static inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned char reg)
{
return snd_gf1_i_look16(gus, reg | 0x80);
}
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index d935417575b5..2b23a5967071 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -379,7 +379,6 @@ struct _snd_pcm_substream {
unsigned int dma_buf_id;
size_t dma_max;
/* -- hardware operations -- */
- unsigned int open_flag: 1; /* lowlevel device has been opened */
snd_pcm_ops_t *ops;
/* -- runtime information -- */
snd_pcm_runtime_t *runtime;
@@ -904,6 +903,7 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
int snd_pcm_format_linear(snd_pcm_format_t format);
int snd_pcm_format_little_endian(snd_pcm_format_t format);
int snd_pcm_format_big_endian(snd_pcm_format_t format);
+#if 0 /* just for DocBook */
/**
* snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
* @format: the format to check
@@ -911,11 +911,12 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format);
* Returns 1 if the given PCM format is CPU-endian, 0 if
* opposite, or a negative error code if endian not specified.
*/
-/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
+int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
+#endif /* DocBook */
#ifdef SNDRV_LITTLE_ENDIAN
-#define snd_pcm_format_cpu_endian snd_pcm_format_little_endian
+#define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format)
#else
-#define snd_pcm_format_cpu_endian snd_pcm_format_big_endian
+#define snd_pcm_format_cpu_endian(format) snd_pcm_format_big_endian(format)
#endif
int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */
int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 518728536bc6..0b67c9d105af 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -32,7 +32,8 @@ struct _snd_pcm_oss_setup {
block:1,
nonblock:1,
partialfrag:1,
- nosilence:1;
+ nosilence:1,
+ buggyptr:1;
unsigned int periods;
unsigned int period_size;
snd_pcm_oss_setup_t *next;
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index ad3c3be33c03..b82e408e758f 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -34,9 +34,7 @@ struct snd_tea575x_ops {
struct snd_tea575x {
snd_card_t *card;
struct video_device vd; /* video device */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
struct file_operations fops;
-#endif
int dev_nr; /* requested device number + 1 */
int vd_registered; /* video device is registered */
int tea5759; /* 5759 chip is present */
diff --git a/include/sound/trident.h b/include/sound/trident.h
index f5254ec36e6a..a408d3925050 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -33,23 +33,6 @@
//#include "ainstr_gf1.h"
#include "ainstr_simple.h"
-#ifndef PCI_VENDOR_ID_TRIDENT
-#define PCI_VENDOR_ID_TRIDENT 0x1023
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_DX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_NX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001
-#endif
-
-#ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI 0x1039
-#endif
-#ifndef PCI_DEVICE_ID_SI_7018
-#define PCI_DEVICE_ID_SI_7018 0x7018
-#endif
-
#define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX)
#define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX)
#define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018)
diff --git a/include/sound/version.h b/include/sound/version.h
index c085136f391f..ee32af20dba9 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "1.0.9b"
-#define CONFIG_SND_DATE " (Thu Jul 28 12:20:13 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.10rc1"
+#define CONFIG_SND_DATE " (Mon Sep 12 08:13:09 2005 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 4b570684a6aa..c3bccbfd8d4c 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -28,28 +28,6 @@
#include "timer.h"
#include <linux/gameport.h>
-#ifndef PCI_VENDOR_ID_YAMAHA
-#define PCI_VENDOR_ID_YAMAHA 0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724
-#define PCI_DEVICE_ID_YAMAHA_724 0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724F
-#define PCI_DEVICE_ID_YAMAHA_724F 0x000d
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740
-#define PCI_DEVICE_ID_YAMAHA_740 0x000a
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740C
-#define PCI_DEVICE_ID_YAMAHA_740C 0x000c
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_744
-#define PCI_DEVICE_ID_YAMAHA_744 0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_754
-#define PCI_DEVICE_ID_YAMAHA_754 0x0012
-#endif
-
/*
* Direct registers
*/
@@ -295,6 +273,7 @@ struct _snd_ymfpci_pcm {
unsigned int running: 1;
unsigned int output_front: 1;
unsigned int output_rear: 1;
+ unsigned int update_pcm_vol;
u32 period_size; /* cached from runtime->period_size */
u32 buffer_size; /* cached from runtime->buffer_size */
u32 period_pos;
@@ -367,6 +346,11 @@ struct _snd_ymfpci {
int mode_dup4ch;
int rear_opened;
int spdif_opened;
+ struct {
+ u16 left;
+ u16 right;
+ snd_kcontrol_t *ctl;
+ } pcm_mixer[32];
spinlock_t reg_lock;
spinlock_t voice_lock;
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
new file mode 100644
index 000000000000..a9948232b131
--- /dev/null
+++ b/include/video/cyblafb.h
@@ -0,0 +1,171 @@
+
+#ifndef CYBLAFB_DEBUG
+#define CYBLAFB_DEBUG 0
+#endif
+
+#if CYBLAFB_DEBUG
+#define debug(f,a...) printk("%s:" f, __FUNCTION__ , ## a);
+#else
+#define debug(f,a...)
+#endif
+
+#define output(f, a...) printk("cyblafb: " f, ## a)
+
+#define Kb (1024)
+#define Mb (Kb*Kb)
+
+/* PCI IDS of supported cards temporarily here */
+
+#define CYBERBLADEi1 0x8500
+
+/* these defines are for 'lcd' variable */
+#define LCD_STRETCH 0
+#define LCD_CENTER 1
+#define LCD_BIOS 2
+
+/* display types */
+#define DISPLAY_CRT 0
+#define DISPLAY_FP 1
+
+#define ROP_S 0xCC
+
+#define point(x,y) ((y)<<16|(x))
+
+//
+// Attribute Regs, ARxx, 3c0/3c1
+//
+#define AR00 0x00
+#define AR01 0x01
+#define AR02 0x02
+#define AR03 0x03
+#define AR04 0x04
+#define AR05 0x05
+#define AR06 0x06
+#define AR07 0x07
+#define AR08 0x08
+#define AR09 0x09
+#define AR0A 0x0A
+#define AR0B 0x0B
+#define AR0C 0x0C
+#define AR0D 0x0D
+#define AR0E 0x0E
+#define AR0F 0x0F
+#define AR10 0x10
+#define AR12 0x12
+#define AR13 0x13
+
+//
+// Sequencer Regs, SRxx, 3c4/3c5
+//
+#define SR00 0x00
+#define SR01 0x01
+#define SR02 0x02
+#define SR03 0x03
+#define SR04 0x04
+#define SR0D 0x0D
+#define SR0E 0x0E
+#define SR11 0x11
+#define SR18 0x18
+#define SR19 0x19
+
+//
+//
+//
+#define CR00 0x00
+#define CR01 0x01
+#define CR02 0x02
+#define CR03 0x03
+#define CR04 0x04
+#define CR05 0x05
+#define CR06 0x06
+#define CR07 0x07
+#define CR08 0x08
+#define CR09 0x09
+#define CR0A 0x0A
+#define CR0B 0x0B
+#define CR0C 0x0C
+#define CR0D 0x0D
+#define CR0E 0x0E
+#define CR0F 0x0F
+#define CR10 0x10
+#define CR11 0x11
+#define CR12 0x12
+#define CR13 0x13
+#define CR14 0x14
+#define CR15 0x15
+#define CR16 0x16
+#define CR17 0x17
+#define CR18 0x18
+#define CR19 0x19
+#define CR1A 0x1A
+#define CR1B 0x1B
+#define CR1C 0x1C
+#define CR1D 0x1D
+#define CR1E 0x1E
+#define CR1F 0x1F
+#define CR20 0x20
+#define CR21 0x21
+#define CR27 0x27
+#define CR29 0x29
+#define CR2A 0x2A
+#define CR2B 0x2B
+#define CR2D 0x2D
+#define CR2F 0x2F
+#define CR36 0x36
+#define CR38 0x38
+#define CR39 0x39
+#define CR3A 0x3A
+#define CR55 0x55
+#define CR56 0x56
+#define CR57 0x57
+#define CR58 0x58
+
+//
+//
+//
+
+#define GR00 0x01
+#define GR01 0x01
+#define GR02 0x02
+#define GR03 0x03
+#define GR04 0x04
+#define GR05 0x05
+#define GR06 0x06
+#define GR07 0x07
+#define GR08 0x08
+#define GR0F 0x0F
+#define GR20 0x20
+#define GR23 0x23
+#define GR2F 0x2F
+#define GR30 0x30
+#define GR31 0x31
+#define GR33 0x33
+#define GR52 0x52
+#define GR53 0x53
+#define GR5D 0x5d
+
+
+//
+// Graphics Engine
+//
+#define GEBase 0x2100 // could be mapped elsewhere if we like it
+#define GE00 (GEBase+0x00) // source 1, p 111
+#define GE04 (GEBase+0x04) // source 2, p 111
+#define GE08 (GEBase+0x08) // destination 1, p 111
+#define GE0C (GEBase+0x0C) // destination 2, p 112
+#define GE20 (GEBase+0x20) // engine status, p 113
+#define GE24 (GEBase+0x24) // reset all GE pointers
+#define GE44 (GEBase+0x44) // command register, p 126
+#define GE48 (GEBase+0x48) // raster operation, p 127
+#define GE60 (GEBase+0x60) // foreground color, p 128
+#define GE64 (GEBase+0x64) // background color, p 128
+#define GE6C (GEBase+0x6C) // Pattern and Style, p 129, ok
+#define GE9C (GEBase+0x9C) // pixel engine data port, p 125
+#define GEB8 (GEBase+0xB8) // Destination Stride / Buffer Base 0, p 133
+#define GEBC (GEBase+0xBC) // Destination Stride / Buffer Base 1, p 133
+#define GEC0 (GEBase+0xC0) // Destination Stride / Buffer Base 2, p 133
+#define GEC4 (GEBase+0xC4) // Destination Stride / Buffer Base 3, p 133
+#define GEC8 (GEBase+0xC8) // Source Stride / Buffer Base 0, p 133
+#define GECC (GEBase+0xCC) // Source Stride / Buffer Base 1, p 133
+#define GED0 (GEBase+0xD0) // Source Stride / Buffer Base 2, p 133
+#define GED4 (GEBase+0xD4) // Source Stride / Buffer Base 3, p 133
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 8d3cef5d87a2..6f4ea808cf74 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1142,9 +1142,6 @@
/* do we want accelerated console */
#define PM3FB_USE_ACCEL 1
-/* useful ? */
-#define CHAR_IS_NUM(a) ((((a) >= '0') && ((a) <= '9')) ? 1 : 0)
-
/* for driver debugging ONLY */
/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
/* define PM3FB_MASTER_DEBUG 1 */
diff --git a/include/video/pmag-ba-fb.h b/include/video/pmag-ba-fb.h
index cebef073b9a3..fceb6c0f6583 100644
--- a/include/video/pmag-ba-fb.h
+++ b/include/video/pmag-ba-fb.h
@@ -1,24 +1,27 @@
/*
- * linux/drivers/video/pmag-ba-fb.h
+ * linux/include/video/pmag-ba-fb.h
*
- * TurboChannel PMAG-BA framebuffer card support,
- * Copyright (C) 1999,2000,2001 by
- * Michael Engel <engel@unix-ag.org>,
- * Karsten Merker <merker@linuxtag.org>
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- */
-
-/*
- * Bt459 RAM DAC register base offset (rel. to TC slot base address)
+ * TURBOchannel PMAG-BA Color Frame Buffer (CFB) card support,
+ * Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org>,
+ * Karsten Merker <merker@linuxtag.org>
+ * Copyright (c) 2005 Maciej W. Rozycki
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
*/
-#define PMAG_BA_BT459_OFFSET 0x00200000
-
-/*
- * Begin of PMAG-BA framebuffer memory relative to TC slot address,
- * resolution is 1024x864x8
- */
+/* IOmem resource offsets. */
+#define PMAG_BA_FBMEM 0x000000 /* frame buffer */
+#define PMAG_BA_BT459 0x200000 /* Bt459 RAMDAC */
+#define PMAG_BA_IRQ 0x300000 /* IRQ acknowledge */
+#define PMAG_BA_ROM 0x380000 /* REX option ROM */
+#define PMAG_BA_BT438 0x380000 /* Bt438 clock chip reset */
+#define PMAG_BA_SIZE 0x400000 /* address space size */
-#define PMAG_BA_ONBOARD_FBMEM_OFFSET 0x00000000
+/* Bt459 register offsets, byte-wide registers. */
+#define BT459_ADDR_LO 0x0 /* address low */
+#define BT459_ADDR_HI 0x4 /* address high */
+#define BT459_DATA 0x8 /* data window register */
+#define BT459_CMAP 0xc /* color map window register */
diff --git a/include/video/pmagb-b-fb.h b/include/video/pmagb-b-fb.h
index 87b81a555139..7539b9087a80 100644
--- a/include/video/pmagb-b-fb.h
+++ b/include/video/pmagb-b-fb.h
@@ -1,32 +1,58 @@
/*
- * linux/drivers/video/pmagb-b-fb.h
+ * linux/include/video/pmagb-b-fb.h
*
- * TurboChannel PMAGB-B framebuffer card support,
- * Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org> and
- * Karsten Merker <merker@linuxtag.org>
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
+ * TURBOchannel PMAGB-B Smart Frame Buffer (SFB) card support,
+ * Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org> and
+ * Karsten Merker <merker@linuxtag.org>
+ * Copyright (c) 2005 Maciej W. Rozycki
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
*/
+/* IOmem resource offsets. */
+#define PMAGB_B_ROM 0x000000 /* REX option ROM */
+#define PMAGB_B_SFB 0x100000 /* SFB ASIC */
+#define PMAGB_B_GP0 0x140000 /* general purpose output 0 */
+#define PMAGB_B_GP1 0x180000 /* general purpose output 1 */
+#define PMAGB_B_BT459 0x1c0000 /* Bt459 RAMDAC */
+#define PMAGB_B_FBMEM 0x200000 /* frame buffer */
+#define PMAGB_B_SIZE 0x400000 /* address space size */
-/*
- * Bt459 RAM DAC register base offset (rel. to TC slot base address)
- */
-#define PMAGB_B_BT459_OFFSET 0x001C0000
+/* IOmem register offsets. */
+#define SFB_REG_VID_HOR 0x64 /* video horizontal setup */
+#define SFB_REG_VID_VER 0x68 /* video vertical setup */
+#define SFB_REG_VID_BASE 0x6c /* video base address */
+#define SFB_REG_TCCLK_COUNT 0x78 /* TURBOchannel clock count */
+#define SFB_REG_VIDCLK_COUNT 0x7c /* video clock count */
-/*
- * Begin of PMAGB-B framebuffer memory, resolution is configurable:
- * 1024x864x8 or 1280x1024x8, settable by jumper on the card
- */
-#define PMAGB_B_ONBOARD_FBMEM_OFFSET 0x00201000
+/* Video horizontal setup register constants. All bits are r/w. */
+#define SFB_VID_HOR_BP_SHIFT 0x15 /* back porch */
+#define SFB_VID_HOR_BP_MASK 0x7f
+#define SFB_VID_HOR_SYN_SHIFT 0x0e /* sync pulse */
+#define SFB_VID_HOR_SYN_MASK 0x7f
+#define SFB_VID_HOR_FP_SHIFT 0x09 /* front porch */
+#define SFB_VID_HOR_FP_MASK 0x1f
+#define SFB_VID_HOR_PIX_SHIFT 0x00 /* active video */
+#define SFB_VID_HOR_PIX_MASK 0x1ff
-/*
- * Bt459 register offsets, byte-wide registers
- */
+/* Video vertical setup register constants. All bits are r/w. */
+#define SFB_VID_VER_BP_SHIFT 0x16 /* back porch */
+#define SFB_VID_VER_BP_MASK 0x3f
+#define SFB_VID_VER_SYN_SHIFT 0x10 /* sync pulse */
+#define SFB_VID_VER_SYN_MASK 0x3f
+#define SFB_VID_VER_FP_SHIFT 0x0b /* front porch */
+#define SFB_VID_VER_FP_MASK 0x1f
+#define SFB_VID_VER_SL_SHIFT 0x00 /* active scan lines */
+#define SFB_VID_VER_SL_MASK 0x7ff
+
+/* Video base address register constants. All bits are r/w. */
+#define SFB_VID_BASE_MASK 0x1ff /* video base row address */
-#define BT459_ADR_LOW BT459_OFFSET + 0x00 /* addr. low */
-#define BT459_ADR_HIGH BT459_OFFSET + 0x04 /* addr. high */
-#define BT459_DATA BT459_OFFSET + 0x08 /* r/w data */
-#define BT459_CMAP BT459_OFFSET + 0x0C /* color map */
+/* Bt459 register offsets, byte-wide registers. */
+#define BT459_ADDR_LO 0x0 /* address low */
+#define BT459_ADDR_HI 0x4 /* address high */
+#define BT459_DATA 0x8 /* data window register */
+#define BT459_CMAP 0xc /* color map window register */
diff --git a/include/video/sisfb.h b/include/video/sisfb.h
index 136bf791643d..e402eb5b3c7a 100644
--- a/include/video/sisfb.h
+++ b/include/video/sisfb.h
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
+ * sisfb.h - definitions for the SiS framebuffer driver
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,8 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
-#ifndef _LINUX_SISFB
-#define _LINUX_SISFB
+#ifndef _LINUX_SISFB_H_
+#define _LINUX_SISFB_H_
#include <asm/ioctl.h>
#include <asm/types.h>
@@ -26,47 +28,35 @@
/* PUBLIC */
/**********************************************/
-/* vbflags */
-#define CRT2_DEFAULT 0x00000001
-#define CRT2_LCD 0x00000002 /* TW: Never change the order of the CRT2_XXX entries */
-#define CRT2_TV 0x00000004 /* (see SISCycleCRT2Type()) */
-#define CRT2_VGA 0x00000008
-#define TV_NTSC 0x00000010
-#define TV_PAL 0x00000020
-#define TV_HIVISION 0x00000040
-#define TV_YPBPR 0x00000080
-#define TV_AVIDEO 0x00000100
-#define TV_SVIDEO 0x00000200
-#define TV_SCART 0x00000400
-#define VB_CONEXANT 0x00000800 /* 661 series only */
-#define VB_TRUMPION VB_CONEXANT /* 300 series only */
-#define TV_PALM 0x00001000
-#define TV_PALN 0x00002000
+/* vbflags, public (others in sis.h) */
+#define CRT2_DEFAULT 0x00000001
+#define CRT2_LCD 0x00000002
+#define CRT2_TV 0x00000004
+#define CRT2_VGA 0x00000008
+#define TV_NTSC 0x00000010
+#define TV_PAL 0x00000020
+#define TV_HIVISION 0x00000040
+#define TV_YPBPR 0x00000080
+#define TV_AVIDEO 0x00000100
+#define TV_SVIDEO 0x00000200
+#define TV_SCART 0x00000400
+#define TV_PALM 0x00001000
+#define TV_PALN 0x00002000
#define TV_NTSCJ 0x00001000
-#define VB_302ELV 0x00004000
-#define TV_CHSCART 0x00008000
-#define TV_CHYPBPR525I 0x00010000
+#define TV_CHSCART 0x00008000
+#define TV_CHYPBPR525I 0x00010000
#define CRT1_VGA 0x00000000
#define CRT1_LCDA 0x00020000
#define VGA2_CONNECTED 0x00040000
-#define VB_DISPTYPE_CRT1 0x00080000 /* CRT1 connected and used */
-#define VB_301 0x00100000 /* Video bridge type */
-#define VB_301B 0x00200000
-#define VB_302B 0x00400000
-#define VB_30xBDH 0x00800000 /* 30xB DH version (w/o LCD support) */
-#define VB_LVDS 0x01000000
-#define VB_CHRONTEL 0x02000000
-#define VB_301LV 0x04000000
-#define VB_302LV 0x08000000
-#define VB_301C 0x10000000
-#define VB_SINGLE_MODE 0x20000000 /* CRT1 or CRT2; determined by DISPTYPE_CRTx */
-#define VB_MIRROR_MODE 0x40000000 /* CRT1 + CRT2 identical (mirror mode) */
-#define VB_DUALVIEW_MODE 0x80000000 /* CRT1 + CRT2 independent (dual head mode) */
+#define VB_DISPTYPE_CRT1 0x00080000 /* CRT1 connected and used */
+#define VB_SINGLE_MODE 0x20000000 /* CRT1 or CRT2; determined by DISPTYPE_CRTx */
+#define VB_MIRROR_MODE 0x40000000 /* CRT1 + CRT2 identical (mirror mode) */
+#define VB_DUALVIEW_MODE 0x80000000 /* CRT1 + CRT2 independent (dual head mode) */
/* Aliases: */
#define CRT2_ENABLE (CRT2_LCD | CRT2_TV | CRT2_VGA)
-#define TV_STANDARD (TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ)
-#define TV_INTERFACE (TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_CHSCART|TV_CHYPBPR525I)
+#define TV_STANDARD (TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ)
+#define TV_INTERFACE (TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_CHSCART|TV_CHYPBPR525I)
/* Only if TV_YPBPR is set: */
#define TV_YPBPR525I TV_NTSC
@@ -75,89 +65,118 @@
#define TV_YPBPR1080I TV_PALN
#define TV_YPBPRALL (TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P | TV_YPBPR1080I)
-#define VB_SISBRIDGE (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
-#define VB_SISTVBRIDGE (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)
-#define VB_VIDEOBRIDGE (VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
-
#define VB_DISPTYPE_DISP2 CRT2_ENABLE
#define VB_DISPTYPE_CRT2 CRT2_ENABLE
#define VB_DISPTYPE_DISP1 VB_DISPTYPE_CRT1
#define VB_DISPMODE_SINGLE VB_SINGLE_MODE
#define VB_DISPMODE_MIRROR VB_MIRROR_MODE
#define VB_DISPMODE_DUAL VB_DUALVIEW_MODE
-#define VB_DISPLAY_MODE (SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
+#define VB_DISPLAY_MODE (SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
/* Structure argument for SISFB_GET_INFO ioctl */
-typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
-
-struct _SISFB_INFO {
- __u32 sisfb_id; /* for identifying sisfb */
+struct sisfb_info {
+ __u32 sisfb_id; /* for identifying sisfb */
#ifndef SISFB_ID
#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */
#endif
- __u32 chip_id; /* PCI-ID of detected chip */
- __u32 memory; /* video memory in KB which sisfb manages */
- __u32 heapstart; /* heap start (= sisfb "mem" argument) in KB */
+ __u32 chip_id; /* PCI-ID of detected chip */
+ __u32 memory; /* total video memory in KB */
+ __u32 heapstart; /* heap start offset in KB */
__u8 fbvidmode; /* current sisfb mode */
- __u8 sisfb_version;
- __u8 sisfb_revision;
- __u8 sisfb_patchlevel;
+ __u8 sisfb_version;
+ __u8 sisfb_revision;
+ __u8 sisfb_patchlevel;
- __u8 sisfb_caps; /* sisfb capabilities */
+ __u8 sisfb_caps; /* sisfb capabilities */
__u32 sisfb_tqlen; /* turbo queue length (in KB) */
- __u32 sisfb_pcibus; /* The card's PCI ID */
- __u32 sisfb_pcislot;
- __u32 sisfb_pcifunc;
+ __u32 sisfb_pcibus; /* The card's PCI ID */
+ __u32 sisfb_pcislot;
+ __u32 sisfb_pcifunc;
+
+ __u8 sisfb_lcdpdc; /* PanelDelayCompensation */
+
+ __u8 sisfb_lcda; /* Detected status of LCDA for low res/text modes */
+
+ __u32 sisfb_vbflags;
+ __u32 sisfb_currentvbflags;
+
+ __u32 sisfb_scalelcd;
+ __u32 sisfb_specialtiming;
+
+ __u8 sisfb_haveemi;
+ __u8 sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+ __u8 sisfb_haveemilcd;
- __u8 sisfb_lcdpdc; /* PanelDelayCompensation */
+ __u8 sisfb_lcdpdca; /* PanelDelayCompensation for LCD-via-CRT1 */
- __u8 sisfb_lcda; /* Detected status of LCDA for low res/text modes */
+ __u16 sisfb_tvxpos, sisfb_tvypos; /* Warning: Values + 32 ! */
- __u32 sisfb_vbflags;
- __u32 sisfb_currentvbflags;
+ __u32 sisfb_heapsize; /* heap size (in KB) */
+ __u32 sisfb_videooffset; /* Offset of viewport in video memory (in bytes) */
- __u32 sisfb_scalelcd;
- __u32 sisfb_specialtiming;
+ __u32 sisfb_curfstn; /* currently running FSTN/DSTN mode */
+ __u32 sisfb_curdstn;
- __u8 sisfb_haveemi;
- __u8 sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
- __u8 sisfb_haveemilcd;
+ __u16 sisfb_pci_vendor; /* PCI vendor (SiS or XGI) */
- __u8 sisfb_lcdpdca; /* PanelDelayCompensation for LCD-via-CRT1 */
+ __u32 sisfb_vbflags2; /* ivideo->vbflags2 */
- __u16 sisfb_tvxpos, sisfb_tvypos; /* Warning: Values + 32 ! */
+ __u8 sisfb_can_post; /* sisfb can POST this card */
+ __u8 sisfb_card_posted; /* card is POSTED */
+ __u8 sisfb_was_boot_device; /* This card was the boot video device (ie is primary) */
- __u8 reserved[208]; /* for future use */
+ __u8 reserved[183]; /* for future use */
+};
+
+#define SISFB_CMD_GETVBFLAGS 0x55AA0001 /* no arg; result[1] = vbflags */
+#define SISFB_CMD_SWITCHCRT1 0x55AA0010 /* arg[0]: 99 = query, 0 = off, 1 = on */
+/* more to come */
+
+#define SISFB_CMD_ERR_OK 0x80000000 /* command succeeded */
+#define SISFB_CMD_ERR_LOCKED 0x80000001 /* sisfb is locked */
+#define SISFB_CMD_ERR_EARLY 0x80000002 /* request before sisfb took over gfx system */
+#define SISFB_CMD_ERR_NOVB 0x80000003 /* No video bridge */
+#define SISFB_CMD_ERR_NOCRT2 0x80000004 /* can't change CRT1 status, CRT2 disabled */
+/* more to come */
+#define SISFB_CMD_ERR_UNKNOWN 0x8000ffff /* Unknown command */
+#define SISFB_CMD_ERR_OTHER 0x80010000 /* Other error */
+
+/* Argument for SISFB_CMD ioctl */
+struct sisfb_cmd {
+ __u32 sisfb_cmd;
+ __u32 sisfb_arg[16];
+ __u32 sisfb_result[4];
};
/* Addtional IOCTLs for communication sisfb <> X driver */
/* If changing this, vgatypes.h must also be changed (for X driver) */
/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_SIZE _IOR(0xF3,0x00,__u32)
-#define SISFB_GET_INFO _IOR(0xF3,0x01,struct _SISFB_INFO)
+#define SISFB_GET_INFO_SIZE _IOR(0xF3,0x00,__u32)
+#define SISFB_GET_INFO _IOR(0xF3,0x01,struct sisfb_info)
/* ioctrl to get current vertical retrace status */
-#define SISFB_GET_VBRSTATUS _IOR(0xF3,0x02,__u32)
+#define SISFB_GET_VBRSTATUS _IOR(0xF3,0x02,__u32)
/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
-#define SISFB_GET_AUTOMAXIMIZE _IOR(0xF3,0x03,__u32)
-#define SISFB_SET_AUTOMAXIMIZE _IOW(0xF3,0x03,__u32)
+#define SISFB_GET_AUTOMAXIMIZE _IOR(0xF3,0x03,__u32)
+#define SISFB_SET_AUTOMAXIMIZE _IOW(0xF3,0x03,__u32)
/* ioctls to relocate TV output (x=D[31:16], y=D[15:0], + 32)*/
-#define SISFB_GET_TVPOSOFFSET _IOR(0xF3,0x04,__u32)
-#define SISFB_SET_TVPOSOFFSET _IOW(0xF3,0x04,__u32)
+#define SISFB_GET_TVPOSOFFSET _IOR(0xF3,0x04,__u32)
+#define SISFB_SET_TVPOSOFFSET _IOW(0xF3,0x04,__u32)
+
+/* ioctl for internal sisfb commands (sisfbctrl) */
+#define SISFB_COMMAND _IOWR(0xF3,0x05,struct sisfb_cmd)
/* ioctl for locking sisfb (no register access during lock) */
/* As of now, only used to avoid register access during
* the ioctls listed above.
*/
-#define SISFB_SET_LOCK _IOW(0xF3,0x06,__u32)
-
-/* more to come soon */
+#define SISFB_SET_LOCK _IOW(0xF3,0x06,__u32)
/* ioctls 0xF3 up to 0x3F reserved for sisfb */
@@ -165,7 +184,7 @@ struct _SISFB_INFO {
/* The following are deprecated and should not be used anymore: */
/****************************************************************/
/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_OLD _IOR('n',0xF8,__u32)
+#define SISFB_GET_INFO_OLD _IOR('n',0xF8,__u32)
/* ioctrl to get current vertical retrace status */
#define SISFB_GET_VBRSTATUS_OLD _IOR('n',0xF9,__u32)
/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
@@ -177,8 +196,8 @@ struct _SISFB_INFO {
/* For fb memory manager (FBIO_ALLOC, FBIO_FREE) */
struct sis_memreq {
- __u32 offset;
- __u32 size;
+ __u32 offset;
+ __u32 size;
};
/**********************************************/
@@ -187,12 +206,19 @@ struct sis_memreq {
/**********************************************/
#ifdef __KERNEL__
+
+#include <linux/pci.h>
+
#define UNKNOWN_VGA 0
#define SIS_300_VGA 1
#define SIS_315_VGA 2
+#define SISFB_HAVE_MALLOC_NEW
extern void sis_malloc(struct sis_memreq *req);
+extern void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+
extern void sis_free(u32 base);
+extern void sis_free_new(struct pci_dev *pdev, u32 base);
#endif
#endif
diff --git a/include/video/w100fb.h b/include/video/w100fb.h
index bd548c2b47c4..677d40326796 100644
--- a/include/video/w100fb.h
+++ b/include/video/w100fb.h
@@ -1,21 +1,150 @@
/*
* Support for the w100 frame buffer.
*
- * Copyright (c) 2004 Richard Purdie
+ * Copyright (c) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton
*
* 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 W100_GPIO_PORT_A 0
+#define W100_GPIO_PORT_B 1
+
+#define CLK_SRC_XTAL 0
+#define CLK_SRC_PLL 1
+
+struct w100fb_par;
+
+unsigned long w100fb_gpio_read(int port);
+void w100fb_gpio_write(int port, unsigned long value);
+unsigned long w100fb_get_hsynclen(struct device *dev);
+
+/* LCD Specific Routines and Config */
+struct w100_tg_info {
+ void (*change)(struct w100fb_par*);
+ void (*suspend)(struct w100fb_par*);
+ void (*resume)(struct w100fb_par*);
+};
+
+/* General Platform Specific w100 Register Values */
+struct w100_gen_regs {
+ unsigned long lcd_format;
+ unsigned long lcdd_cntl1;
+ unsigned long lcdd_cntl2;
+ unsigned long genlcd_cntl1;
+ unsigned long genlcd_cntl2;
+ unsigned long genlcd_cntl3;
+};
+
+struct w100_gpio_regs {
+ unsigned long init_data1;
+ unsigned long init_data2;
+ unsigned long gpio_dir1;
+ unsigned long gpio_oe1;
+ unsigned long gpio_dir2;
+ unsigned long gpio_oe2;
+};
+
+/* Optional External Memory Configuration */
+struct w100_mem_info {
+ unsigned long ext_cntl;
+ unsigned long sdram_mode_reg;
+ unsigned long ext_timing_cntl;
+ unsigned long io_cntl;
+ unsigned int size;
+};
+
+struct w100_bm_mem_info {
+ unsigned long ext_mem_bw;
+ unsigned long offset;
+ unsigned long ext_timing_ctl;
+ unsigned long ext_cntl;
+ unsigned long mode_reg;
+ unsigned long io_cntl;
+ unsigned long config;
+};
+
+/* LCD Mode definition */
+struct w100_mode {
+ unsigned int xres;
+ unsigned int yres;
+ unsigned short left_margin;
+ unsigned short right_margin;
+ unsigned short upper_margin;
+ unsigned short lower_margin;
+ unsigned long crtc_ss;
+ unsigned long crtc_ls;
+ unsigned long crtc_gs;
+ unsigned long crtc_vpos_gs;
+ unsigned long crtc_rev;
+ unsigned long crtc_dclk;
+ unsigned long crtc_gclk;
+ unsigned long crtc_goe;
+ unsigned long crtc_ps1_active;
+ char pll_freq;
+ char fast_pll_freq;
+ int sysclk_src;
+ int sysclk_divider;
+ int pixclk_src;
+ int pixclk_divider;
+ int pixclk_divider_rotated;
+};
+
+struct w100_pll_info {
+ uint16_t freq; /* desired Fout for PLL (Mhz) */
+ uint8_t M; /* input divider */
+ uint8_t N_int; /* VCO multiplier */
+ uint8_t N_fac; /* VCO multiplier fractional part */
+ uint8_t tfgoal;
+ uint8_t lock_time;
+};
+
+/* Initial Video mode orientation flags */
+#define INIT_MODE_ROTATED 0x1
+#define INIT_MODE_FLIPPED 0x2
+
/*
* This structure describes the machine which we are running on.
* It is set by machine specific code and used in the probe routine
* of drivers/video/w100fb.c
*/
-
struct w100fb_mach_info {
- void (*w100fb_ssp_send)(u8 adrs, u8 data);
- int comadj;
- int phadadj;
+ /* General Platform Specific Registers */
+ struct w100_gen_regs *regs;
+ /* Table of modes the LCD is capable of */
+ struct w100_mode *modelist;
+ unsigned int num_modes;
+ /* Hooks for any platform specific tg/lcd code (optional) */
+ struct w100_tg_info *tg;
+ /* External memory definition (if present) */
+ struct w100_mem_info *mem;
+ /* Additional External memory definition (if present) */
+ struct w100_bm_mem_info *bm_mem;
+ /* GPIO definitions (optional) */
+ struct w100_gpio_regs *gpio;
+ /* Initial Mode flags */
+ unsigned int init_mode;
+ /* Xtal Frequency */
+ unsigned int xtal_freq;
+ /* Enable Xtal input doubler (1 == enable) */
+ unsigned int xtal_dbl;
+};
+
+/* General frame buffer data structure */
+struct w100fb_par {
+ unsigned int chip_id;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned int extmem_active;
+ unsigned int flip;
+ unsigned int blanked;
+ unsigned int fastpll_mode;
+ unsigned long hsync_len;
+ struct w100_mode *mode;
+ struct w100_pll_info *pll_table;
+ struct w100fb_mach_info *mach;
+ uint32_t *saved_intmem;
+ uint32_t *saved_extmem;
};
diff --git a/init/Kconfig b/init/Kconfig
index 05a75c4f5ce2..d5a1a1228fab 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -77,6 +77,22 @@ config LOCALVERSION
object and source tree, in that order. Your total string can
be a maximum of 64 characters.
+config LOCALVERSION_AUTO
+ bool "Automatically append version information to the version string"
+ default y
+ help
+ This will try to automatically determine if the current tree is a
+ release tree by looking for git tags that
+ belong to the current top of tree revision.
+
+ A string of the format -gxxxxxxxx will be added to the localversion
+ if a git based tree is found. The string generated by this will be
+ appended after any matching localversion* files, and after the value
+ set in CONFIG_LOCALVERSION
+
+ Note: This requires Perl, and a git repository, but not necessarily
+ the git or cogito tools to be installed.
+
config SWAP
bool "Support for paging of anonymous memory (swap)"
depends on MMU
@@ -238,6 +254,8 @@ config CPUSETS
Say N if unsure.
+source "usr/Kconfig"
+
menuconfig EMBEDDED
bool "Configure standard kernel features (for small systems)"
help
@@ -260,8 +278,8 @@ config KALLSYMS_ALL
help
Normally kallsyms only contains the symbols of functions, for nicer
OOPS messages. Some debuggers can use kallsyms for other
- symbols too: say Y here to include all symbols, and you
- don't care about adding 300k to the size of your kernel.
+ symbols too: say Y here to include all symbols, if you need them
+ and you don't care about adding 300k to the size of your kernel.
Say N.
diff --git a/init/Makefile b/init/Makefile
index 93a53fbdbe79..a2300078f2b7 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -25,4 +25,5 @@ $(obj)/version.o: include/linux/compile.h
include/linux/compile.h: FORCE
@echo ' CHK $@'
- @$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 4e11a9aaf14a..b27c11064409 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -127,10 +127,10 @@ fail:
* used when disk name of partitioned disk ends on a digit.
*
* If name doesn't have fall into the categories above, we return 0.
- * Driverfs is used to check if something is a disk name - it has
+ * Sysfs is used to check if something is a disk name - it has
* all known disks under bus/block/devices. If the disk name
- * contains slashes, name of driverfs node has them replaced with
- * bangs. try_name() does the actual checks, assuming that driverfs
+ * contains slashes, name of sysfs node has them replaced with
+ * bangs. try_name() does the actual checks, assuming that sysfs
* is mounted on rootfs /sys.
*/
diff --git a/init/initramfs.c b/init/initramfs.c
index 02c5ce64990d..0c5d9a3f951b 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -466,6 +466,14 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
extern char __initramfs_start[], __initramfs_end[];
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/initrd.h>
+
+static void __init free_initrd(void)
+{
+ free_initrd_mem(initrd_start, initrd_end);
+ initrd_start = 0;
+ initrd_end = 0;
+}
+
#endif
void __init populate_rootfs(void)
@@ -484,7 +492,7 @@ void __init populate_rootfs(void)
printk(" it is\n");
unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 0);
- free_initrd_mem(initrd_start, initrd_end);
+ free_initrd();
return;
}
printk("it isn't (%s); looks like an initrd\n", err);
@@ -493,7 +501,7 @@ void __init populate_rootfs(void)
sys_write(fd, (char *)initrd_start,
initrd_end - initrd_start);
sys_close(fd);
- free_initrd_mem(initrd_start, initrd_end);
+ free_initrd();
}
}
#endif
diff --git a/init/main.c b/init/main.c
index c9c311cf1771..f142d4035341 100644
--- a/init/main.c
+++ b/init/main.c
@@ -47,6 +47,7 @@
#include <linux/rmap.h>
#include <linux/mempolicy.h>
#include <linux/key.h>
+#include <net/sock.h>
#include <asm/io.h>
#include <asm/bugs.h>
@@ -80,7 +81,6 @@
static int init(void *);
extern void init_IRQ(void);
-extern void sock_init(void);
extern void fork_init(unsigned long);
extern void mca_init(void);
extern void sbus_init(void);
@@ -123,6 +123,7 @@ extern void softirq_init(void);
char saved_command_line[COMMAND_LINE_SIZE];
static char *execute_command;
+static char *ramdisk_execute_command;
/* Setup configured maximum number of CPUs to activate */
static unsigned int max_cpus = NR_CPUS;
@@ -297,6 +298,18 @@ static int __init init_setup(char *str)
}
__setup("init=", init_setup);
+static int __init rdinit_setup(char *str)
+{
+ unsigned int i;
+
+ ramdisk_execute_command = str;
+ /* See "auto" comment in init_setup */
+ for (i = 1; i < MAX_INIT_ARGS; i++)
+ argv_init[i] = NULL;
+ return 1;
+}
+__setup("rdinit=", rdinit_setup);
+
extern void setup_arch(char **);
#ifndef CONFIG_SMP
@@ -614,6 +627,7 @@ static void do_pre_smp_initcalls(void)
migration_init();
#endif
spawn_ksoftirqd();
+ spawn_softlockup_task();
}
static void run_init_process(char *init_filename)
@@ -680,10 +694,14 @@ static int init(void * unused)
* check if there is an early userspace init. If yes, let it do all
* the work
*/
- if (sys_access((const char __user *) "/init", 0) == 0)
- execute_command = "/init";
- else
+
+ if (!ramdisk_execute_command)
+ ramdisk_execute_command = "/init";
+
+ if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
+ ramdisk_execute_command = NULL;
prepare_namespace();
+ }
/*
* Ok, we have completed the initial bootup, and
@@ -700,17 +718,24 @@ static int init(void * unused)
(void) sys_dup(0);
(void) sys_dup(0);
-
+
+ if (ramdisk_execute_command) {
+ run_init_process(ramdisk_execute_command);
+ printk(KERN_WARNING "Failed to execute %s\n",
+ ramdisk_execute_command);
+ }
+
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
-
- if (execute_command)
+ if (execute_command) {
run_init_process(execute_command);
-
+ printk(KERN_WARNING "Failed to execute %s. Attempting "
+ "defaults...\n", execute_command);
+ }
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
diff --git a/ipc/compat.c b/ipc/compat.c
index 3881d564c668..1fe95f6659dd 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -42,10 +42,10 @@ struct compat_msgbuf {
struct compat_ipc_perm {
key_t key;
- compat_uid_t uid;
- compat_gid_t gid;
- compat_uid_t cuid;
- compat_gid_t cgid;
+ __compat_uid_t uid;
+ __compat_gid_t gid;
+ __compat_uid_t cuid;
+ __compat_gid_t cgid;
compat_mode_t mode;
unsigned short seq;
};
@@ -174,8 +174,8 @@ static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
struct compat_ipc_perm __user *up)
{
int err;
- compat_uid_t u;
- compat_gid_t g;
+ __compat_uid_t u;
+ __compat_gid_t g;
err = __put_user(p->key, &up->key);
SET_UID(u, p->uid);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 0acf245f441d..3a926011507b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -69,7 +69,7 @@ struct mqueue_inode_info {
struct sigevent notify;
pid_t notify_owner;
- struct user_struct *user; /* user who created, for accouting */
+ struct user_struct *user; /* user who created, for accounting */
struct sock *notify_sock;
struct sk_buff *notify_cookie;
diff --git a/ipc/msg.c b/ipc/msg.c
index 27e516f96cdc..d035bd2aba96 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/seq_file.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -74,16 +75,16 @@ static struct ipc_ids msg_ids;
static void freeque (struct msg_queue *msq, int id);
static int newque (key_t key, int msgflg);
#ifdef CONFIG_PROC_FS
-static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
#endif
void __init msg_init (void)
{
ipc_init_ids(&msg_ids,msg_ctlmni);
-
-#ifdef CONFIG_PROC_FS
- create_proc_read_entry("sysvipc/msg", 0, NULL, sysvipc_msg_read_proc, NULL);
-#endif
+ ipc_init_proc_interface("sysvipc/msg",
+ " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
+ &msg_ids,
+ sysvipc_msg_proc_show);
}
static int newque (key_t key, int msgflg)
@@ -113,6 +114,7 @@ static int newque (key_t key, int msgflg)
return -ENOSPC;
}
+ msq->q_id = msg_buildid(id,msq->q_perm.seq);
msq->q_stime = msq->q_rtime = 0;
msq->q_ctime = get_seconds();
msq->q_cbytes = msq->q_qnum = 0;
@@ -123,7 +125,7 @@ static int newque (key_t key, int msgflg)
INIT_LIST_HEAD(&msq->q_senders);
msg_unlock(msq);
- return msg_buildid(id,msq->q_perm.seq);
+ return msq->q_id;
}
static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss)
@@ -808,55 +810,25 @@ out_unlock:
}
#ifdef CONFIG_PROC_FS
-static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
{
- off_t pos = 0;
- off_t begin = 0;
- int i, len = 0;
-
- down(&msg_ids.sem);
- len += sprintf(buffer, " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n");
-
- for(i = 0; i <= msg_ids.max_id; i++) {
- struct msg_queue * msq;
- msq = msg_lock(i);
- if(msq != NULL) {
- len += sprintf(buffer + len, "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
- msq->q_perm.key,
- msg_buildid(i,msq->q_perm.seq),
- msq->q_perm.mode,
- msq->q_cbytes,
- msq->q_qnum,
- msq->q_lspid,
- msq->q_lrpid,
- msq->q_perm.uid,
- msq->q_perm.gid,
- msq->q_perm.cuid,
- msq->q_perm.cgid,
- msq->q_stime,
- msq->q_rtime,
- msq->q_ctime);
- msg_unlock(msq);
-
- pos += len;
- if(pos < offset) {
- len = 0;
- begin = pos;
- }
- if(pos > offset + length)
- goto done;
- }
-
- }
- *eof = 1;
-done:
- up(&msg_ids.sem);
- *start = buffer + (offset - begin);
- len -= (offset - begin);
- if(len > length)
- len = length;
- if(len < 0)
- len = 0;
- return len;
+ struct msg_queue *msq = it;
+
+ return seq_printf(s,
+ "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
+ msq->q_perm.key,
+ msq->q_id,
+ msq->q_perm.mode,
+ msq->q_cbytes,
+ msq->q_qnum,
+ msq->q_lspid,
+ msq->q_lrpid,
+ msq->q_perm.uid,
+ msq->q_perm.gid,
+ msq->q_perm.cuid,
+ msq->q_perm.cgid,
+ msq->q_stime,
+ msq->q_rtime,
+ msq->q_ctime);
}
#endif
diff --git a/ipc/sem.c b/ipc/sem.c
index 70975ce0784a..19af028a3e38 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -73,6 +73,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -89,7 +90,7 @@ static struct ipc_ids sem_ids;
static int newary (key_t, int, int);
static void freeary (struct sem_array *sma, int id);
#ifdef CONFIG_PROC_FS
-static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
#endif
#define SEMMSL_FAST 256 /* 512 bytes on stack */
@@ -116,10 +117,10 @@ void __init sem_init (void)
{
used_sems = 0;
ipc_init_ids(&sem_ids,sc_semmni);
-
-#ifdef CONFIG_PROC_FS
- create_proc_read_entry("sysvipc/sem", 0, NULL, sysvipc_sem_read_proc, NULL);
-#endif
+ ipc_init_proc_interface("sysvipc/sem",
+ " key semid perms nsems uid gid cuid cgid otime ctime\n",
+ &sem_ids,
+ sysvipc_sem_proc_show);
}
/*
@@ -193,6 +194,7 @@ static int newary (key_t key, int nsems, int semflg)
}
used_sems += nsems;
+ sma->sem_id = sem_buildid(id, sma->sem_perm.seq);
sma->sem_base = (struct sem *) &sma[1];
/* sma->sem_pending = NULL; */
sma->sem_pending_last = &sma->sem_pending;
@@ -201,7 +203,7 @@ static int newary (key_t key, int nsems, int semflg)
sma->sem_ctime = get_seconds();
sem_unlock(sma);
- return sem_buildid(id, sma->sem_perm.seq);
+ return sma->sem_id;
}
asmlinkage long sys_semget (key_t key, int nsems, int semflg)
@@ -1328,50 +1330,21 @@ next_entry:
}
#ifdef CONFIG_PROC_FS
-static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
{
- off_t pos = 0;
- off_t begin = 0;
- int i, len = 0;
-
- len += sprintf(buffer, " key semid perms nsems uid gid cuid cgid otime ctime\n");
- down(&sem_ids.sem);
-
- for(i = 0; i <= sem_ids.max_id; i++) {
- struct sem_array *sma;
- sma = sem_lock(i);
- if(sma) {
- len += sprintf(buffer + len, "%10d %10d %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
- sma->sem_perm.key,
- sem_buildid(i,sma->sem_perm.seq),
- sma->sem_perm.mode,
- sma->sem_nsems,
- sma->sem_perm.uid,
- sma->sem_perm.gid,
- sma->sem_perm.cuid,
- sma->sem_perm.cgid,
- sma->sem_otime,
- sma->sem_ctime);
- sem_unlock(sma);
-
- pos += len;
- if(pos < offset) {
- len = 0;
- begin = pos;
- }
- if(pos > offset + length)
- goto done;
- }
- }
- *eof = 1;
-done:
- up(&sem_ids.sem);
- *start = buffer + (offset - begin);
- len -= (offset - begin);
- if(len > length)
- len = length;
- if(len < 0)
- len = 0;
- return len;
+ struct sem_array *sma = it;
+
+ return seq_printf(s,
+ "%10d %10d %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
+ sma->sem_perm.key,
+ sma->sem_id,
+ sma->sem_perm.mode,
+ sma->sem_nsems,
+ sma->sem_perm.uid,
+ sma->sem_perm.gid,
+ sma->sem_perm.cuid,
+ sma->sem_perm.cgid,
+ sma->sem_otime,
+ sma->sem_ctime);
}
#endif
diff --git a/ipc/shm.c b/ipc/shm.c
index 1d6cf08d950b..dca90489e3b0 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -23,12 +23,12 @@
#include <linux/init.h>
#include <linux/file.h>
#include <linux/mman.h>
-#include <linux/proc_fs.h>
#include <linux/shmem_fs.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/ptrace.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
@@ -51,7 +51,7 @@ static int newseg (key_t key, int shmflg, size_t size);
static void shm_open (struct vm_area_struct *shmd);
static void shm_close (struct vm_area_struct *shmd);
#ifdef CONFIG_PROC_FS
-static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
#endif
size_t shm_ctlmax = SHMMAX;
@@ -63,9 +63,10 @@ static int shm_tot; /* total number of shared memory pages */
void __init shm_init (void)
{
ipc_init_ids(&shm_ids, 1);
-#ifdef CONFIG_PROC_FS
- create_proc_read_entry("sysvipc/shm", 0, NULL, sysvipc_shm_read_proc, NULL);
-#endif
+ ipc_init_proc_interface("sysvipc/shm",
+ " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n",
+ &shm_ids,
+ sysvipc_shm_proc_show);
}
static inline int shm_checkid(struct shmid_kernel *s, int id)
@@ -869,63 +870,32 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
}
#ifdef CONFIG_PROC_FS
-static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
{
- off_t pos = 0;
- off_t begin = 0;
- int i, len = 0;
-
- down(&shm_ids.sem);
- len += sprintf(buffer, " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n");
+ struct shmid_kernel *shp = it;
+ char *format;
- for(i = 0; i <= shm_ids.max_id; i++) {
- struct shmid_kernel* shp;
-
- shp = shm_lock(i);
- if(shp!=NULL) {
#define SMALL_STRING "%10d %10d %4o %10u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
#define BIG_STRING "%10d %10d %4o %21u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
- char *format;
- if (sizeof(size_t) <= sizeof(int))
- format = SMALL_STRING;
- else
- format = BIG_STRING;
- len += sprintf(buffer + len, format,
- shp->shm_perm.key,
- shm_buildid(i, shp->shm_perm.seq),
- shp->shm_flags,
- shp->shm_segsz,
- shp->shm_cprid,
- shp->shm_lprid,
- is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
- shp->shm_perm.uid,
- shp->shm_perm.gid,
- shp->shm_perm.cuid,
- shp->shm_perm.cgid,
- shp->shm_atim,
- shp->shm_dtim,
- shp->shm_ctim);
- shm_unlock(shp);
-
- pos += len;
- if(pos < offset) {
- len = 0;
- begin = pos;
- }
- if(pos > offset + length)
- goto done;
- }
- }
- *eof = 1;
-done:
- up(&shm_ids.sem);
- *start = buffer + (offset - begin);
- len -= (offset - begin);
- if(len > length)
- len = length;
- if(len < 0)
- len = 0;
- return len;
+ if (sizeof(size_t) <= sizeof(int))
+ format = SMALL_STRING;
+ else
+ format = BIG_STRING;
+ return seq_printf(s, format,
+ shp->shm_perm.key,
+ shp->id,
+ shp->shm_flags,
+ shp->shm_segsz,
+ shp->shm_cprid,
+ shp->shm_lprid,
+ is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
+ shp->shm_perm.uid,
+ shp->shm_perm.gid,
+ shp->shm_perm.cuid,
+ shp->shm_perm.cgid,
+ shp->shm_atim,
+ shp->shm_dtim,
+ shp->shm_ctim);
}
#endif
diff --git a/ipc/util.c b/ipc/util.c
index e00c35f7b2b8..10e836d0d89e 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -24,11 +24,20 @@
#include <linux/security.h>
#include <linux/rcupdate.h>
#include <linux/workqueue.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#include <asm/unistd.h>
#include "util.h"
+struct ipc_proc_iface {
+ const char *path;
+ const char *header;
+ struct ipc_ids *ids;
+ int (*show)(struct seq_file *, void *);
+};
+
/**
* ipc_init - initialise IPC subsystem
*
@@ -86,6 +95,43 @@ void __init ipc_init_ids(struct ipc_ids* ids, int size)
ids->entries->p[i] = NULL;
}
+#ifdef CONFIG_PROC_FS
+static struct file_operations sysvipc_proc_fops;
+/**
+ * ipc_init_proc_interface - Create a proc interface for sysipc types
+ * using a seq_file interface.
+ * @path: Path in procfs
+ * @header: Banner to be printed at the beginning of the file.
+ * @ids: ipc id table to iterate.
+ * @show: show routine.
+ */
+void __init ipc_init_proc_interface(const char *path, const char *header,
+ struct ipc_ids *ids,
+ int (*show)(struct seq_file *, void *))
+{
+ struct proc_dir_entry *pde;
+ struct ipc_proc_iface *iface;
+
+ iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+ if (!iface)
+ return;
+ iface->path = path;
+ iface->header = header;
+ iface->ids = ids;
+ iface->show = show;
+
+ pde = create_proc_entry(path,
+ S_IRUGO, /* world readable */
+ NULL /* parent dir */);
+ if (pde) {
+ pde->data = iface;
+ pde->proc_fops = &sysvipc_proc_fops;
+ } else {
+ kfree(iface);
+ }
+}
+#endif
+
/**
* ipc_findkey - find a key in an ipc identifier set
* @ids: Identifier set
@@ -578,3 +624,113 @@ int ipc_parse_version (int *cmd)
}
#endif /* __ARCH_WANT_IPC_PARSE_VERSION */
+
+#ifdef CONFIG_PROC_FS
+static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
+{
+ struct ipc_proc_iface *iface = s->private;
+ struct kern_ipc_perm *ipc = it;
+ loff_t p;
+
+ /* If we had an ipc id locked before, unlock it */
+ if (ipc && ipc != SEQ_START_TOKEN)
+ ipc_unlock(ipc);
+
+ /*
+ * p = *pos - 1 (because id 0 starts at position 1)
+ * + 1 (because we increment the position by one)
+ */
+ for (p = *pos; p <= iface->ids->max_id; p++) {
+ if ((ipc = ipc_lock(iface->ids, p)) != NULL) {
+ *pos = p + 1;
+ return ipc;
+ }
+ }
+
+ /* Out of range - return NULL to terminate iteration */
+ return NULL;
+}
+
+/*
+ * File positions: pos 0 -> header, pos n -> ipc id + 1.
+ * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START.
+ */
+static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
+{
+ struct ipc_proc_iface *iface = s->private;
+ struct kern_ipc_perm *ipc;
+ loff_t p;
+
+ /*
+ * Take the lock - this will be released by the corresponding
+ * call to stop().
+ */
+ down(&iface->ids->sem);
+
+ /* pos < 0 is invalid */
+ if (*pos < 0)
+ return NULL;
+
+ /* pos == 0 means header */
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ /* Find the (pos-1)th ipc */
+ for (p = *pos - 1; p <= iface->ids->max_id; p++) {
+ if ((ipc = ipc_lock(iface->ids, p)) != NULL) {
+ *pos = p + 1;
+ return ipc;
+ }
+ }
+ return NULL;
+}
+
+static void sysvipc_proc_stop(struct seq_file *s, void *it)
+{
+ struct kern_ipc_perm *ipc = it;
+ struct ipc_proc_iface *iface = s->private;
+
+ /* If we had a locked segment, release it */
+ if (ipc && ipc != SEQ_START_TOKEN)
+ ipc_unlock(ipc);
+
+ /* Release the lock we took in start() */
+ up(&iface->ids->sem);
+}
+
+static int sysvipc_proc_show(struct seq_file *s, void *it)
+{
+ struct ipc_proc_iface *iface = s->private;
+
+ if (it == SEQ_START_TOKEN)
+ return seq_puts(s, iface->header);
+
+ return iface->show(s, it);
+}
+
+static struct seq_operations sysvipc_proc_seqops = {
+ .start = sysvipc_proc_start,
+ .stop = sysvipc_proc_stop,
+ .next = sysvipc_proc_next,
+ .show = sysvipc_proc_show,
+};
+
+static int sysvipc_proc_open(struct inode *inode, struct file *file) {
+ int ret;
+ struct seq_file *seq;
+
+ ret = seq_open(file, &sysvipc_proc_seqops);
+ if (!ret) {
+ seq = file->private_data;
+ seq->private = PDE(inode)->data;
+ }
+ return ret;
+}
+
+static struct file_operations sysvipc_proc_fops = {
+ .open = sysvipc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif /* CONFIG_PROC_FS */
diff --git a/ipc/util.h b/ipc/util.h
index 44348ca5a707..fc9a28be0797 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -30,7 +30,15 @@ struct ipc_ids {
struct ipc_id_ary* entries;
};
+struct seq_file;
void __init ipc_init_ids(struct ipc_ids* ids, int size);
+#ifdef CONFIG_PROC_FS
+void __init ipc_init_proc_interface(const char *path, const char *header,
+ struct ipc_ids *ids,
+ int (*show)(struct seq_file *, void *));
+#else
+#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
+#endif
/* must be called with ids->sem acquired.*/
int ipc_findkey(struct ipc_ids* ids, key_t key);
diff --git a/kernel/Makefile b/kernel/Makefile
index cb05cd05d237..ff4dc02ce170 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -12,6 +12,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o spinlock.o
+obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SYSFS) += ksysfs.o
+obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_SECCOMP) += seccomp.o
diff --git a/kernel/acct.c b/kernel/acct.c
index 4168f631868e..b756f527497e 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -165,7 +165,7 @@ out:
}
/*
- * Close the old accouting file (if currently open) and then replace
+ * Close the old accounting file (if currently open) and then replace
* it with file (if non-NULL).
*
* NOTE: acct_globals.lock MUST be held on entry and exit.
@@ -199,11 +199,16 @@ static void acct_file_reopen(struct file *file)
}
}
-/*
- * sys_acct() is the only system call needed to implement process
- * accounting. It takes the name of the file where accounting records
- * should be written. If the filename is NULL, accounting will be
- * shutdown.
+/**
+ * sys_acct - enable/disable process accounting
+ * @name: file name for accounting records or NULL to shutdown accounting
+ *
+ * Returns 0 for success or negative errno values for failure.
+ *
+ * sys_acct() is the only system call needed to implement process
+ * accounting. It takes the name of the file where accounting records
+ * should be written. If the filename is NULL, accounting will be
+ * shutdown.
*/
asmlinkage long sys_acct(const char __user *name)
{
@@ -220,7 +225,7 @@ asmlinkage long sys_acct(const char __user *name)
return (PTR_ERR(tmp));
}
/* Difference from BSD - they don't do O_APPEND */
- file = filp_open(tmp, O_WRONLY|O_APPEND, 0);
+ file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
putname(tmp);
if (IS_ERR(file)) {
return (PTR_ERR(file));
@@ -250,9 +255,12 @@ asmlinkage long sys_acct(const char __user *name)
return (0);
}
-/*
- * If the accouting is turned on for a file in the filesystem pointed
- * to by sb, turn accouting off.
+/**
+ * acct_auto_close - turn off a filesystem's accounting if it is on
+ * @sb: super block for the filesystem
+ *
+ * If the accounting is turned on for a file in the filesystem pointed
+ * to by sb, turn accounting off.
*/
void acct_auto_close(struct super_block *sb)
{
@@ -503,8 +511,11 @@ static void do_acct_process(long exitcode, struct file *file)
set_fs(fs);
}
-/*
+/**
* acct_process - now just a wrapper around do_acct_process
+ * @exitcode: task exit code
+ *
+ * handles process accounting for an exiting task
*/
void acct_process(long exitcode)
{
@@ -530,9 +541,9 @@ void acct_process(long exitcode)
}
-/*
- * acct_update_integrals
- * - update mm integral fields in task_struct
+/**
+ * acct_update_integrals - update mm integral fields in task_struct
+ * @tsk: task_struct for accounting
*/
void acct_update_integrals(struct task_struct *tsk)
{
@@ -547,9 +558,9 @@ void acct_update_integrals(struct task_struct *tsk)
}
}
-/*
- * acct_clear_integrals
- * - clear the mm integral fields in task_struct
+/**
+ * acct_clear_integrals - clear the mm integral fields in task_struct
+ * @tsk: task_struct whose accounting fields are cleared
*/
void acct_clear_integrals(struct task_struct *tsk)
{
diff --git a/kernel/audit.c b/kernel/audit.c
index 8376ec10cf24..83096b67510a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -513,7 +513,8 @@ static int __init audit_init(void)
{
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
audit_default ? "enabled" : "disabled");
- audit_sock = netlink_kernel_create(NETLINK_AUDIT, audit_receive);
+ audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
+ THIS_MODULE);
if (!audit_sock)
audit_panic("cannot initialize netlink socket");
diff --git a/kernel/compat.c b/kernel/compat.c
index ddfcaaa86623..102296e21ea8 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -48,8 +48,7 @@ static long compat_nanosleep_restart(struct restart_block *restart)
if (!time_after(expire, now))
return 0;
- current->state = TASK_INTERRUPTIBLE;
- expire = schedule_timeout(expire - now);
+ expire = schedule_timeout_interruptible(expire - now);
if (expire == 0)
return 0;
@@ -82,8 +81,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
return -EINVAL;
expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
- current->state = TASK_INTERRUPTIBLE;
- expire = schedule_timeout(expire);
+ expire = schedule_timeout_interruptible(expire);
if (expire == 0)
return 0;
@@ -795,8 +793,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- current->state = TASK_INTERRUPTIBLE;
- timeout = schedule_timeout(timeout);
+ timeout = schedule_timeout_interruptible(timeout);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &s, &info);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 8ab1b4e518b8..79866bc6b3a1 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -180,6 +180,42 @@ static struct super_block *cpuset_sb = NULL;
*/
static DECLARE_MUTEX(cpuset_sem);
+static struct task_struct *cpuset_sem_owner;
+static int cpuset_sem_depth;
+
+/*
+ * The global cpuset semaphore cpuset_sem can be needed by the
+ * memory allocator to update a tasks mems_allowed (see the calls
+ * to cpuset_update_current_mems_allowed()) or to walk up the
+ * cpuset hierarchy to find a mem_exclusive cpuset see the calls
+ * to cpuset_excl_nodes_overlap()).
+ *
+ * But if the memory allocation is being done by cpuset.c code, it
+ * usually already holds cpuset_sem. Double tripping on a kernel
+ * semaphore deadlocks the current task, and any other task that
+ * subsequently tries to obtain the lock.
+ *
+ * Run all up's and down's on cpuset_sem through the following
+ * wrappers, which will detect this nested locking, and avoid
+ * deadlocking.
+ */
+
+static inline void cpuset_down(struct semaphore *psem)
+{
+ if (cpuset_sem_owner != current) {
+ down(psem);
+ cpuset_sem_owner = current;
+ }
+ cpuset_sem_depth++;
+}
+
+static inline void cpuset_up(struct semaphore *psem)
+{
+ if (--cpuset_sem_depth == 0) {
+ cpuset_sem_owner = NULL;
+ up(psem);
+ }
+}
/*
* A couple of forward declarations required, due to cyclic reference loop:
@@ -522,19 +558,10 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
* Refresh current tasks mems_allowed and mems_generation from
* current tasks cpuset. Call with cpuset_sem held.
*
- * Be sure to call refresh_mems() on any cpuset operation which
- * (1) holds cpuset_sem, and (2) might possibly alloc memory.
- * Call after obtaining cpuset_sem lock, before any possible
- * allocation. Otherwise one risks trying to allocate memory
- * while the task cpuset_mems_generation is not the same as
- * the mems_generation in its cpuset, which would deadlock on
- * cpuset_sem in cpuset_update_current_mems_allowed().
- *
- * Since we hold cpuset_sem, once refresh_mems() is called, the
- * test (current->cpuset_mems_generation != cs->mems_generation)
- * in cpuset_update_current_mems_allowed() will remain false,
- * until we drop cpuset_sem. Anyone else who would change our
- * cpusets mems_generation needs to lock cpuset_sem first.
+ * This routine is needed to update the per-task mems_allowed
+ * data, within the tasks context, when it is trying to allocate
+ * memory (in various mm/mempolicy.c routines) and notices
+ * that some other task has been modifying its cpuset.
*/
static void refresh_mems(void)
@@ -628,13 +655,6 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
* lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
*/
-/*
- * Hack to avoid 2.6.13 partial node dynamic sched domain bug.
- * Disable letting 'cpu_exclusive' cpusets define dynamic sched
- * domains, until the sched domain can handle partial nodes.
- * Remove this #if hackery when sched domains fixed.
- */
-#if 0
static void update_cpu_domains(struct cpuset *cur)
{
struct cpuset *c, *par = cur->parent;
@@ -675,11 +695,6 @@ static void update_cpu_domains(struct cpuset *cur)
partition_sched_domains(&pspan, &cspan);
unlock_cpu_hotplug();
}
-#else
-static void update_cpu_domains(struct cpuset *cur)
-{
-}
-#endif
static int update_cpumask(struct cpuset *cs, char *buf)
{
@@ -852,7 +867,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
}
buffer[nbytes] = 0; /* nul-terminate */
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
if (is_removed(cs)) {
retval = -ENODEV;
@@ -886,7 +901,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
if (retval == 0)
retval = nbytes;
out2:
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
cpuset_release_agent(pathbuf);
out1:
kfree(buffer);
@@ -926,9 +941,9 @@ static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
{
cpumask_t mask;
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
mask = cs->cpus_allowed;
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
return cpulist_scnprintf(page, PAGE_SIZE, mask);
}
@@ -937,9 +952,9 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
{
nodemask_t mask;
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
mask = cs->mems_allowed;
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
return nodelist_scnprintf(page, PAGE_SIZE, mask);
}
@@ -984,6 +999,10 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
*s++ = '\n';
*s = '\0';
+ /* Do nothing if *ppos is at the eof or beyond the eof. */
+ if (s - page <= *ppos)
+ return 0;
+
start = page + *ppos;
n = s - start;
retval = n - copy_to_user(buf, start, min(n, nbytes));
@@ -1342,8 +1361,7 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
if (!cs)
return -ENOMEM;
- down(&cpuset_sem);
- refresh_mems();
+ cpuset_down(&cpuset_sem);
cs->flags = 0;
if (notify_on_release(parent))
set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
@@ -1368,14 +1386,14 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
* will down() this new directory's i_sem and if we race with
* another mkdir, we might deadlock.
*/
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
err = cpuset_populate_dir(cs->dentry);
/* If err < 0, we have a half-filled directory - oh well ;) */
return 0;
err:
list_del(&cs->sibling);
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
kfree(cs);
return err;
}
@@ -1397,14 +1415,13 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
/* the vfs holds both inode->i_sem already */
- down(&cpuset_sem);
- refresh_mems();
+ cpuset_down(&cpuset_sem);
if (atomic_read(&cs->count) > 0) {
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
return -EBUSY;
}
if (!list_empty(&cs->children)) {
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
return -EBUSY;
}
parent = cs->parent;
@@ -1420,7 +1437,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
spin_unlock(&d->d_lock);
cpuset_d_remove_dir(d);
dput(d);
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
cpuset_release_agent(pathbuf);
return 0;
}
@@ -1523,10 +1540,10 @@ void cpuset_exit(struct task_struct *tsk)
if (notify_on_release(cs)) {
char *pathbuf = NULL;
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
if (atomic_dec_and_test(&cs->count))
check_for_release(cs, &pathbuf);
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
cpuset_release_agent(pathbuf);
} else {
atomic_dec(&cs->count);
@@ -1547,11 +1564,11 @@ cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk)
{
cpumask_t mask;
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
task_lock((struct task_struct *)tsk);
guarantee_online_cpus(tsk->cpuset, &mask);
task_unlock((struct task_struct *)tsk);
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
return mask;
}
@@ -1576,9 +1593,9 @@ void cpuset_update_current_mems_allowed(void)
if (!cs)
return; /* task is exiting */
if (current->cpuset_mems_generation != cs->mems_generation) {
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
refresh_mems();
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
}
}
@@ -1611,17 +1628,114 @@ int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
return 0;
}
+/*
+ * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive
+ * ancestor to the specified cpuset. Call while holding cpuset_sem.
+ * If no ancestor is mem_exclusive (an unusual configuration), then
+ * returns the root cpuset.
+ */
+static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+{
+ while (!is_mem_exclusive(cs) && cs->parent)
+ cs = cs->parent;
+ return cs;
+}
+
/**
- * cpuset_zone_allowed - is zone z allowed in current->mems_allowed
- * @z: zone in question
+ * cpuset_zone_allowed - Can we allocate memory on zone z's memory node?
+ * @z: is this zone on an allowed node?
+ * @gfp_mask: memory allocation flags (we use __GFP_HARDWALL)
*
- * Is zone z allowed in current->mems_allowed, or is
- * the CPU in interrupt context? (zone is always allowed in this case)
- */
-int cpuset_zone_allowed(struct zone *z)
+ * If we're in interrupt, yes, we can always allocate. If zone
+ * z's node is in our tasks mems_allowed, yes. If it's not a
+ * __GFP_HARDWALL request and this zone's nodes is in the nearest
+ * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
+ * Otherwise, no.
+ *
+ * GFP_USER allocations are marked with the __GFP_HARDWALL bit,
+ * and do not allow allocations outside the current tasks cpuset.
+ * GFP_KERNEL allocations are not so marked, so can escape to the
+ * nearest mem_exclusive ancestor cpuset.
+ *
+ * Scanning up parent cpusets requires cpuset_sem. The __alloc_pages()
+ * routine only calls here with __GFP_HARDWALL bit _not_ set if
+ * it's a GFP_KERNEL allocation, and all nodes in the current tasks
+ * mems_allowed came up empty on the first pass over the zonelist.
+ * So only GFP_KERNEL allocations, if all nodes in the cpuset are
+ * short of memory, might require taking the cpuset_sem semaphore.
+ *
+ * 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 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:
+ * 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.
+ **/
+
+int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask)
+{
+ int node; /* node that zone z is on */
+ const struct cpuset *cs; /* current cpuset ancestors */
+ int allowed = 1; /* is allocation in zone z allowed? */
+
+ if (in_interrupt())
+ return 1;
+ node = z->zone_pgdat->node_id;
+ if (node_isset(node, current->mems_allowed))
+ return 1;
+ if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */
+ return 0;
+
+ /* Not hardwall and node outside mems_allowed: scan up cpusets */
+ cpuset_down(&cpuset_sem);
+ cs = current->cpuset;
+ if (!cs)
+ goto done; /* current task exiting */
+ cs = nearest_exclusive_ancestor(cs);
+ allowed = node_isset(node, cs->mems_allowed);
+done:
+ cpuset_up(&cpuset_sem);
+ return allowed;
+}
+
+/**
+ * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors?
+ * @p: pointer to task_struct of some other task.
+ *
+ * Description: Return true if the nearest mem_exclusive ancestor
+ * cpusets of tasks @p and current overlap. Used by oom killer to
+ * determine if task @p's memory usage might impact the memory
+ * available to the current task.
+ *
+ * Acquires cpuset_sem - not suitable for calling from a fast path.
+ **/
+
+int cpuset_excl_nodes_overlap(const struct task_struct *p)
{
- return in_interrupt() ||
- node_isset(z->zone_pgdat->node_id, current->mems_allowed);
+ const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
+ int overlap = 0; /* do cpusets overlap? */
+
+ cpuset_down(&cpuset_sem);
+ cs1 = current->cpuset;
+ if (!cs1)
+ goto done; /* current task exiting */
+ cs2 = p->cpuset;
+ if (!cs2)
+ goto done; /* task p is exiting */
+ cs1 = nearest_exclusive_ancestor(cs1);
+ cs2 = nearest_exclusive_ancestor(cs2);
+ overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
+done:
+ cpuset_up(&cpuset_sem);
+
+ return overlap;
}
/*
@@ -1642,7 +1756,7 @@ static int proc_cpuset_show(struct seq_file *m, void *v)
return -ENOMEM;
tsk = m->private;
- down(&cpuset_sem);
+ cpuset_down(&cpuset_sem);
task_lock(tsk);
cs = tsk->cpuset;
task_unlock(tsk);
@@ -1657,7 +1771,7 @@ static int proc_cpuset_show(struct seq_file *m, void *v)
seq_puts(m, buf);
seq_putc(m, '\n');
out:
- up(&cpuset_sem);
+ cpuset_up(&cpuset_sem);
kfree(buf);
return retval;
}
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b0fb9f09f21..6d2089a1bce7 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -368,17 +368,19 @@ EXPORT_SYMBOL(daemonize);
static inline void close_files(struct files_struct * files)
{
int i, j;
+ struct fdtable *fdt;
j = 0;
+ fdt = files_fdtable(files);
for (;;) {
unsigned long set;
i = j * __NFDBITS;
- if (i >= files->max_fdset || i >= files->max_fds)
+ if (i >= fdt->max_fdset || i >= fdt->max_fds)
break;
- set = files->open_fds->fds_bits[j++];
+ set = fdt->open_fds->fds_bits[j++];
while (set) {
if (set & 1) {
- struct file * file = xchg(&files->fd[i], NULL);
+ struct file * file = xchg(&fdt->fd[i], NULL);
if (file)
filp_close(file, files);
}
@@ -403,18 +405,22 @@ struct files_struct *get_files_struct(struct task_struct *task)
void fastcall put_files_struct(struct files_struct *files)
{
+ struct fdtable *fdt;
+
if (atomic_dec_and_test(&files->count)) {
close_files(files);
/*
* Free the fd and fdset arrays if we expanded them.
+ * If the fdtable was embedded, pass files for freeing
+ * at the end of the RCU grace period. Otherwise,
+ * you can free files immediately.
*/
- if (files->fd != &files->fd_array[0])
- free_fd_array(files->fd, files->max_fds);
- if (files->max_fdset > __FD_SETSIZE) {
- free_fdset(files->open_fds, files->max_fdset);
- free_fdset(files->close_on_exec, files->max_fdset);
- }
- kmem_cache_free(files_cachep, files);
+ fdt = files_fdtable(files);
+ if (fdt == &files->fdtab)
+ fdt->free_files = files;
+ else
+ kmem_cache_free(files_cachep, files);
+ free_fdtable(fdt);
}
}
diff --git a/kernel/fork.c b/kernel/fork.c
index b65187f0c74e..8149f3602881 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -35,6 +35,7 @@
#include <linux/syscalls.h>
#include <linux/jiffies.h>
#include <linux/futex.h>
+#include <linux/rcupdate.h>
#include <linux/ptrace.h>
#include <linux/mount.h>
#include <linux/audit.h>
@@ -176,6 +177,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
/* One for us, one for whoever does the "release_task()" (usually parent) */
atomic_set(&tsk->usage,2);
+ atomic_set(&tsk->fs_excl, 0);
return tsk;
}
@@ -564,24 +566,53 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
return 0;
}
-static int count_open_files(struct files_struct *files, int size)
+static int count_open_files(struct fdtable *fdt)
{
+ int size = fdt->max_fdset;
int i;
/* Find the last open fd */
for (i = size/(8*sizeof(long)); i > 0; ) {
- if (files->open_fds->fds_bits[--i])
+ if (fdt->open_fds->fds_bits[--i])
break;
}
i = (i+1) * 8 * sizeof(long);
return i;
}
+static struct files_struct *alloc_files(void)
+{
+ struct files_struct *newf;
+ struct fdtable *fdt;
+
+ newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
+ if (!newf)
+ goto out;
+
+ atomic_set(&newf->count, 1);
+
+ spin_lock_init(&newf->file_lock);
+ fdt = &newf->fdtab;
+ fdt->next_fd = 0;
+ fdt->max_fds = NR_OPEN_DEFAULT;
+ fdt->max_fdset = __FD_SETSIZE;
+ fdt->close_on_exec = &newf->close_on_exec_init;
+ fdt->open_fds = &newf->open_fds_init;
+ fdt->fd = &newf->fd_array[0];
+ INIT_RCU_HEAD(&fdt->rcu);
+ fdt->free_files = NULL;
+ fdt->next = NULL;
+ rcu_assign_pointer(newf->fdt, fdt);
+out:
+ return newf;
+}
+
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
{
struct files_struct *oldf, *newf;
struct file **old_fds, **new_fds;
int open_files, size, i, error = 0, expand;
+ struct fdtable *old_fdt, *new_fdt;
/*
* A background process may not have any files ...
@@ -602,35 +633,27 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
*/
tsk->files = NULL;
error = -ENOMEM;
- newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
- if (!newf)
+ newf = alloc_files();
+ if (!newf)
goto out;
- atomic_set(&newf->count, 1);
-
- spin_lock_init(&newf->file_lock);
- newf->next_fd = 0;
- newf->max_fds = NR_OPEN_DEFAULT;
- newf->max_fdset = __FD_SETSIZE;
- newf->close_on_exec = &newf->close_on_exec_init;
- newf->open_fds = &newf->open_fds_init;
- newf->fd = &newf->fd_array[0];
-
spin_lock(&oldf->file_lock);
-
- open_files = count_open_files(oldf, oldf->max_fdset);
+ old_fdt = files_fdtable(oldf);
+ new_fdt = files_fdtable(newf);
+ size = old_fdt->max_fdset;
+ open_files = count_open_files(old_fdt);
expand = 0;
/*
* Check whether we need to allocate a larger fd array or fd set.
* Note: we're not a clone task, so the open count won't change.
*/
- if (open_files > newf->max_fdset) {
- newf->max_fdset = 0;
+ if (open_files > new_fdt->max_fdset) {
+ new_fdt->max_fdset = 0;
expand = 1;
}
- if (open_files > newf->max_fds) {
- newf->max_fds = 0;
+ if (open_files > new_fdt->max_fds) {
+ new_fdt->max_fds = 0;
expand = 1;
}
@@ -642,14 +665,21 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
spin_unlock(&newf->file_lock);
if (error < 0)
goto out_release;
+ new_fdt = files_fdtable(newf);
+ /*
+ * Reacquire the oldf lock and a pointer to its fd table
+ * who knows it may have a new bigger fd table. We need
+ * the latest pointer.
+ */
spin_lock(&oldf->file_lock);
+ old_fdt = files_fdtable(oldf);
}
- old_fds = oldf->fd;
- new_fds = newf->fd;
+ old_fds = old_fdt->fd;
+ new_fds = new_fdt->fd;
- memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8);
- memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8);
+ memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
+ memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
for (i = open_files; i != 0; i--) {
struct file *f = *old_fds++;
@@ -662,24 +692,24 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
* is partway through open(). So make sure that this
* fd is available to the new process.
*/
- FD_CLR(open_files - i, newf->open_fds);
+ FD_CLR(open_files - i, new_fdt->open_fds);
}
- *new_fds++ = f;
+ rcu_assign_pointer(*new_fds++, f);
}
spin_unlock(&oldf->file_lock);
/* compute the remainder to be cleared */
- size = (newf->max_fds - open_files) * sizeof(struct file *);
+ size = (new_fdt->max_fds - open_files) * sizeof(struct file *);
/* This is long word aligned thus could use a optimized version */
memset(new_fds, 0, size);
- if (newf->max_fdset > open_files) {
- int left = (newf->max_fdset-open_files)/8;
+ if (new_fdt->max_fdset > open_files) {
+ int left = (new_fdt->max_fdset-open_files)/8;
int start = open_files / (8 * sizeof(unsigned long));
- memset(&newf->open_fds->fds_bits[start], 0, left);
- memset(&newf->close_on_exec->fds_bits[start], 0, left);
+ memset(&new_fdt->open_fds->fds_bits[start], 0, left);
+ memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
}
tsk->files = newf;
@@ -688,9 +718,9 @@ out:
return error;
out_release:
- free_fdset (newf->close_on_exec, newf->max_fdset);
- free_fdset (newf->open_fds, newf->max_fdset);
- free_fd_array(newf->fd, newf->max_fds);
+ free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
+ 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;
}
@@ -994,6 +1024,9 @@ static task_t *copy_process(unsigned long clone_flags,
* of CLONE_PTRACE.
*/
clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
+#ifdef TIF_SYSCALL_EMU
+ clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
+#endif
/* Our parent execution domain becomes current domain
These must match for thread signalling to apply */
@@ -1112,6 +1145,9 @@ static task_t *copy_process(unsigned long clone_flags,
__get_cpu_var(process_counts)++;
}
+ if (!current->signal->tty && p->signal->tty)
+ p->signal->tty = NULL;
+
nr_threads++;
total_forks++;
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/futex.c b/kernel/futex.c
index c7130f86106c..ca05fe6a70b2 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -40,6 +40,7 @@
#include <linux/pagemap.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
+#include <asm/futex.h>
#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
@@ -327,6 +328,118 @@ out:
}
/*
+ * Wake up all waiters hashed on the physical page that is mapped
+ * to this virtual address:
+ */
+static int futex_wake_op(unsigned long uaddr1, unsigned long uaddr2, int nr_wake, int nr_wake2, int op)
+{
+ union futex_key key1, key2;
+ struct futex_hash_bucket *bh1, *bh2;
+ struct list_head *head;
+ struct futex_q *this, *next;
+ int ret, op_ret, attempt = 0;
+
+retryfull:
+ down_read(&current->mm->mmap_sem);
+
+ ret = get_futex_key(uaddr1, &key1);
+ if (unlikely(ret != 0))
+ goto out;
+ ret = get_futex_key(uaddr2, &key2);
+ if (unlikely(ret != 0))
+ goto out;
+
+ bh1 = hash_futex(&key1);
+ bh2 = hash_futex(&key2);
+
+retry:
+ if (bh1 < bh2)
+ spin_lock(&bh1->lock);
+ spin_lock(&bh2->lock);
+ if (bh1 > bh2)
+ spin_lock(&bh1->lock);
+
+ op_ret = futex_atomic_op_inuser(op, (int __user *)uaddr2);
+ if (unlikely(op_ret < 0)) {
+ int dummy;
+
+ spin_unlock(&bh1->lock);
+ if (bh1 != bh2)
+ spin_unlock(&bh2->lock);
+
+ /* futex_atomic_op_inuser needs to both read and write
+ * *(int __user *)uaddr2, but we can't modify it
+ * non-atomically. Therefore, if get_user below is not
+ * enough, we need to handle the fault ourselves, while
+ * still holding the mmap_sem. */
+ if (attempt++) {
+ struct vm_area_struct * vma;
+ struct mm_struct *mm = current->mm;
+
+ ret = -EFAULT;
+ if (attempt >= 2 ||
+ !(vma = find_vma(mm, uaddr2)) ||
+ vma->vm_start > uaddr2 ||
+ !(vma->vm_flags & VM_WRITE))
+ goto out;
+
+ switch (handle_mm_fault(mm, vma, uaddr2, 1)) {
+ case VM_FAULT_MINOR:
+ current->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ current->maj_flt++;
+ break;
+ default:
+ goto out;
+ }
+ goto retry;
+ }
+
+ /* If we would have faulted, release mmap_sem,
+ * fault it in and start all over again. */
+ up_read(&current->mm->mmap_sem);
+
+ ret = get_user(dummy, (int __user *)uaddr2);
+ if (ret)
+ return ret;
+
+ goto retryfull;
+ }
+
+ head = &bh1->chain;
+
+ list_for_each_entry_safe(this, next, head, list) {
+ if (match_futex (&this->key, &key1)) {
+ wake_futex(this);
+ if (++ret >= nr_wake)
+ break;
+ }
+ }
+
+ if (op_ret > 0) {
+ head = &bh2->chain;
+
+ op_ret = 0;
+ list_for_each_entry_safe(this, next, head, list) {
+ if (match_futex (&this->key, &key2)) {
+ wake_futex(this);
+ if (++op_ret >= nr_wake2)
+ break;
+ }
+ }
+ ret += op_ret;
+ }
+
+ spin_unlock(&bh1->lock);
+ if (bh1 != bh2)
+ spin_unlock(&bh2->lock);
+out:
+ up_read(&current->mm->mmap_sem);
+ return ret;
+}
+
+/*
* Requeue all waiters hashed on one physical page to another
* physical page.
*/
@@ -673,23 +786,17 @@ static int futex_fd(unsigned long uaddr, int signal)
filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
if (signal) {
- int err;
err = f_setown(filp, current->pid, 1);
if (err < 0) {
- put_unused_fd(ret);
- put_filp(filp);
- ret = err;
- goto out;
+ goto error;
}
filp->f_owner.signum = signal;
}
q = kmalloc(sizeof(*q), GFP_KERNEL);
if (!q) {
- put_unused_fd(ret);
- put_filp(filp);
- ret = -ENOMEM;
- goto out;
+ err = -ENOMEM;
+ goto error;
}
down_read(&current->mm->mmap_sem);
@@ -697,10 +804,8 @@ static int futex_fd(unsigned long uaddr, int signal)
if (unlikely(err != 0)) {
up_read(&current->mm->mmap_sem);
- put_unused_fd(ret);
- put_filp(filp);
kfree(q);
- return err;
+ goto error;
}
/*
@@ -716,6 +821,11 @@ static int futex_fd(unsigned long uaddr, int signal)
fd_install(ret, filp);
out:
return ret;
+error:
+ put_unused_fd(ret);
+ put_filp(filp);
+ ret = err;
+ goto out;
}
long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
@@ -740,6 +850,9 @@ long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
case FUTEX_CMP_REQUEUE:
ret = futex_requeue(uaddr, uaddr2, val, val2, &val3);
break;
+ case FUTEX_WAKE_OP:
+ ret = futex_wake_op(uaddr, uaddr2, val, val2, val3);
+ break;
default:
ret = -ENOSYS;
}
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
index 388977f3e9b7..0cbe633420fb 100644
--- a/kernel/intermodule.c
+++ b/kernel/intermodule.c
@@ -39,7 +39,7 @@ void inter_module_register(const char *im_name, struct module *owner, const void
struct list_head *tmp;
struct inter_module_entry *ime, *ime_new;
- if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
+ if (!(ime_new = kzalloc(sizeof(*ime), GFP_KERNEL))) {
/* Overloaded kernel, not fatal */
printk(KERN_ERR
"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
@@ -47,7 +47,6 @@ void inter_module_register(const char *im_name, struct module *owner, const void
kmalloc_failed = 1;
return;
}
- memset(ime_new, 0, sizeof(*ime_new));
ime_new->im_name = im_name;
ime_new->owner = owner;
ime_new->userdata = userdata;
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index c29f83c16497..3ff7b925c387 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -111,7 +111,7 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
unsigned int status;
kstat_this_cpu.irqs[irq]++;
- if (desc->status & IRQ_PER_CPU) {
+ if (CHECK_IRQ_PER_CPU(desc->status)) {
irqreturn_t action_ret;
/*
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ac6700985705..1cfdb08ddf20 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -18,6 +18,10 @@
cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+#endif
+
/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
*
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 85d08daa6600..f26e534c6585 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -19,12 +19,22 @@ static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS];
*/
static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
-void __attribute__((weak))
-proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+{
+ /*
+ * Save these away for later use. Re-progam when the
+ * interrupt is pending
+ */
+ set_pending_irq(irq, mask_val);
+}
+#else
+void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
{
irq_affinity[irq] = mask_val;
irq_desc[irq].handler->set_affinity(irq, mask_val);
}
+#endif
static int irq_affinity_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index b0237122b24e..f3ea492ab44d 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleloader.h>
+#include <asm-generic/sections.h>
#include <asm/cacheflush.h>
#include <asm/errno.h>
#include <asm/kdebug.h>
@@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pages;
* get_insn_slot() - Find a slot on an executable page for an instruction.
* We allocate an executable page if there's no room on existing ones.
*/
-kprobe_opcode_t *get_insn_slot(void)
+kprobe_opcode_t __kprobes *get_insn_slot(void)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
@@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void)
return kip->insns;
}
-void free_insn_slot(kprobe_opcode_t *slot)
+void __kprobes free_insn_slot(kprobe_opcode_t *slot)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
@@ -152,20 +153,42 @@ void free_insn_slot(kprobe_opcode_t *slot)
}
/* Locks kprobe: irqs must be disabled */
-void lock_kprobes(void)
+void __kprobes lock_kprobes(void)
{
+ unsigned long flags = 0;
+
+ /* Avoiding local interrupts to happen right after we take the kprobe_lock
+ * and before we get a chance to update kprobe_cpu, this to prevent
+ * deadlock when we have a kprobe on ISR routine and a kprobe on task
+ * routine
+ */
+ local_irq_save(flags);
+
spin_lock(&kprobe_lock);
kprobe_cpu = smp_processor_id();
+
+ local_irq_restore(flags);
}
-void unlock_kprobes(void)
+void __kprobes unlock_kprobes(void)
{
+ unsigned long flags = 0;
+
+ /* Avoiding local interrupts to happen right after we update
+ * kprobe_cpu and before we get a a chance to release kprobe_lock,
+ * this to prevent deadlock when we have a kprobe on ISR routine and
+ * a kprobe on task routine
+ */
+ local_irq_save(flags);
+
kprobe_cpu = NR_CPUS;
spin_unlock(&kprobe_lock);
+
+ local_irq_restore(flags);
}
/* You have to be holding the kprobe_lock */
-struct kprobe *get_kprobe(void *addr)
+struct kprobe __kprobes *get_kprobe(void *addr)
{
struct hlist_head *head;
struct hlist_node *node;
@@ -183,7 +206,7 @@ struct kprobe *get_kprobe(void *addr)
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
*/
-static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;
@@ -198,8 +221,8 @@ static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
- unsigned long flags)
+static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
{
struct kprobe *kp;
@@ -213,8 +236,8 @@ static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
return;
}
-static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
- int trapnr)
+static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
+ int trapnr)
{
/*
* if we faulted "during" the execution of a user specified
@@ -227,7 +250,7 @@ static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
return 0;
}
-static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp = curr_kprobe;
if (curr_kprobe && kp->break_handler) {
@@ -240,7 +263,7 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
+struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
@@ -249,7 +272,8 @@ struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
return NULL;
}
-static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
+static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
+ *rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
@@ -258,7 +282,7 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
return NULL;
}
-void add_rp_inst(struct kretprobe_instance *ri)
+void __kprobes add_rp_inst(struct kretprobe_instance *ri)
{
/*
* Remove rp inst off the free list -
@@ -276,7 +300,7 @@ void add_rp_inst(struct kretprobe_instance *ri)
hlist_add_head(&ri->uflist, &ri->rp->used_instances);
}
-void recycle_rp_inst(struct kretprobe_instance *ri)
+void __kprobes recycle_rp_inst(struct kretprobe_instance *ri)
{
/* remove rp inst off the rprobe_inst_table */
hlist_del(&ri->hlist);
@@ -291,7 +315,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri)
kfree(ri);
}
-struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
+struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
{
return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
}
@@ -302,7 +326,7 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
* instances associated with this task. These left over instances represent
* probed functions that have been called but will never return.
*/
-void kprobe_flush_task(struct task_struct *tk)
+void __kprobes kprobe_flush_task(struct task_struct *tk)
{
struct kretprobe_instance *ri;
struct hlist_head *head;
@@ -322,7 +346,8 @@ void kprobe_flush_task(struct task_struct *tk)
* This kprobe pre_handler is registered with every kretprobe. When probe
* hits it will set up the return probe.
*/
-static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+ struct pt_regs *regs)
{
struct kretprobe *rp = container_of(p, struct kretprobe, kp);
@@ -353,7 +378,7 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
* Add the new probe to old_p->list. Fail if this is the
* second jprobe at the address - two jprobes can't coexist
*/
-static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
{
struct kprobe *kp;
@@ -395,7 +420,8 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
* the intricacies
* TODO: Move kcalloc outside the spinlock
*/
-static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
+ struct kprobe *p)
{
int ret = 0;
struct kprobe *ap;
@@ -434,15 +460,25 @@ static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
spin_unlock_irqrestore(&kprobe_lock, flags);
}
-int register_kprobe(struct kprobe *p)
+static int __kprobes in_kprobes_functions(unsigned long addr)
+{
+ if (addr >= (unsigned long)__kprobes_text_start
+ && addr < (unsigned long)__kprobes_text_end)
+ return -EINVAL;
+ return 0;
+}
+
+int __kprobes register_kprobe(struct kprobe *p)
{
int ret = 0;
unsigned long flags = 0;
struct kprobe *old_p;
- if ((ret = arch_prepare_kprobe(p)) != 0) {
+ if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
+ return ret;
+ if ((ret = arch_prepare_kprobe(p)) != 0)
goto rm_kprobe;
- }
+
spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
p->nmissed = 0;
@@ -466,7 +502,7 @@ rm_kprobe:
return ret;
}
-void unregister_kprobe(struct kprobe *p)
+void __kprobes unregister_kprobe(struct kprobe *p)
{
unsigned long flags;
struct kprobe *old_p;
@@ -487,7 +523,7 @@ static struct notifier_block kprobe_exceptions_nb = {
.priority = 0x7fffffff /* we need to notified first */
};
-int register_jprobe(struct jprobe *jp)
+int __kprobes register_jprobe(struct jprobe *jp)
{
/* Todo: Verify probepoint is a function entry point */
jp->kp.pre_handler = setjmp_pre_handler;
@@ -496,14 +532,14 @@ int register_jprobe(struct jprobe *jp)
return register_kprobe(&jp->kp);
}
-void unregister_jprobe(struct jprobe *jp)
+void __kprobes unregister_jprobe(struct jprobe *jp)
{
unregister_kprobe(&jp->kp);
}
#ifdef ARCH_SUPPORTS_KRETPROBES
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
{
int ret = 0;
struct kretprobe_instance *inst;
@@ -540,14 +576,14 @@ int register_kretprobe(struct kretprobe *rp)
#else /* ARCH_SUPPORTS_KRETPROBES */
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
{
return -ENOSYS;
}
#endif /* ARCH_SUPPORTS_KRETPROBES */
-void unregister_kretprobe(struct kretprobe *rp)
+void __kprobes unregister_kretprobe(struct kretprobe *rp)
{
unsigned long flags;
struct kretprobe_instance *ri;
diff --git a/kernel/module.c b/kernel/module.c
index c32995fbd8fd..ff5c500ab625 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/elf.h>
@@ -498,7 +499,7 @@ static inline int try_force(unsigned int flags)
{
int ret = (flags & O_TRUNC);
if (ret)
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
return ret;
}
#else
@@ -897,7 +898,7 @@ static int check_version(Elf_Shdr *sechdrs,
if (!(tainted & TAINT_FORCED_MODULE)) {
printk("%s: no version for \"%s\" found: kernel tainted.\n",
mod->name, symname);
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
}
return 1;
}
@@ -1352,7 +1353,7 @@ static void set_license(struct module *mod, const char *license)
if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
mod->name, license);
- tainted |= TAINT_PROPRIETARY_MODULE;
+ add_taint(TAINT_PROPRIETARY_MODULE);
}
}
@@ -1509,6 +1510,7 @@ static struct module *load_module(void __user *umod,
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
struct exception_table_entry *extable;
+ mm_segment_t old_fs;
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
umod, len, uargs);
@@ -1609,7 +1611,7 @@ static struct module *load_module(void __user *umod,
modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */
if (!modmagic) {
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name);
} else if (!same_magic(modmagic, vermagic)) {
@@ -1738,7 +1740,7 @@ static struct module *load_module(void __user *umod,
(mod->num_gpl_syms && !gplcrcindex)) {
printk(KERN_WARNING "%s: No versions for exported symbols."
" Tainting kernel.\n", mod->name);
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
}
#endif
@@ -1779,6 +1781,24 @@ static struct module *load_module(void __user *umod,
if (err < 0)
goto cleanup;
+ /* flush the icache in correct context */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ /*
+ * Flush the instruction cache, since we've played with text.
+ * Do it before processing of module parameters, so the module
+ * can provide parameter accessor functions of its own.
+ */
+ if (mod->module_init)
+ flush_icache_range((unsigned long)mod->module_init,
+ (unsigned long)mod->module_init
+ + mod->init_size);
+ flush_icache_range((unsigned long)mod->module_core,
+ (unsigned long)mod->module_core + mod->core_size);
+
+ set_fs(old_fs);
+
mod->args = args;
if (obsparmindex) {
err = obsolete_params(mod->name, mod->args,
@@ -1860,7 +1880,6 @@ sys_init_module(void __user *umod,
const char __user *uargs)
{
struct module *mod;
- mm_segment_t old_fs = get_fs();
int ret = 0;
/* Must have permission */
@@ -1878,19 +1897,6 @@ sys_init_module(void __user *umod,
return PTR_ERR(mod);
}
- /* flush the icache in correct context */
- set_fs(KERNEL_DS);
-
- /* Flush the instruction cache, since we've played with text */
- if (mod->module_init)
- flush_icache_range((unsigned long)mod->module_init,
- (unsigned long)mod->module_init
- + mod->init_size);
- flush_icache_range((unsigned long)mod->module_core,
- (unsigned long)mod->module_core + mod->core_size);
-
- set_fs(old_fs);
-
/* Now sew it into the lists. They won't access us, since
strong_try_module_get() will fail. */
stop_machine_run(__link_module, mod, NR_CPUS);
diff --git a/kernel/params.c b/kernel/params.c
index d586c35ef8fc..fbf173215fd2 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -542,8 +542,8 @@ static void __init kernel_param_sysfs_setup(const char *name,
{
struct module_kobject *mk;
- mk = kmalloc(sizeof(struct module_kobject), GFP_KERNEL);
- memset(mk, 0, sizeof(struct module_kobject));
+ mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
+ BUG_ON(!mk);
mk->mod = THIS_MODULE;
kobj_set_kset_s(mk, module_subsys);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 38798a2ff994..b7b532acd9fc 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -427,21 +427,23 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
timr->sigq->info.si_code = SI_TIMER;
timr->sigq->info.si_tid = timr->it_id;
timr->sigq->info.si_value = timr->it_sigev_value;
+
if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
- if (unlikely(timr->it_process->flags & PF_EXITING)) {
- timr->it_sigev_notify = SIGEV_SIGNAL;
- put_task_struct(timr->it_process);
- timr->it_process = timr->it_process->group_leader;
- goto group;
- }
- return send_sigqueue(timr->it_sigev_signo, timr->sigq,
- timr->it_process);
- }
- else {
- group:
- return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
- timr->it_process);
+ struct task_struct *leader;
+ int ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
+ timr->it_process);
+
+ if (likely(ret >= 0))
+ return ret;
+
+ timr->it_sigev_notify = SIGEV_SIGNAL;
+ leader = timr->it_process->group_leader;
+ put_task_struct(timr->it_process);
+ timr->it_process = leader;
}
+
+ return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
+ timr->it_process);
}
EXPORT_SYMBOL_GPL(posix_timer_event);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 2c7121d9bff1..396c7873e804 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -1,5 +1,6 @@
config PM
bool "Power Management support"
+ depends on !IA64_HP_SIM
---help---
"Power Management" means that parts of your computer are shut
off or put into a power conserving "sleep" mode if they are not
@@ -28,7 +29,7 @@ config PM_DEBUG
config SOFTWARE_SUSPEND
bool "Software Suspend"
- depends on EXPERIMENTAL && PM && SWAP && ((X86 && SMP) || ((FVR || PPC32 || X86) && !SMP))
+ depends on PM && SWAP && (X86 || ((FVR || PPC32) && !SMP))
---help---
Enable the possibility of suspending the machine.
It doesn't need APM.
@@ -72,6 +73,18 @@ config PM_STD_PARTITION
suspended image to. It will simply pick the first available swap
device.
+config SWSUSP_ENCRYPT
+ bool "Encrypt suspend image"
+ depends on SOFTWARE_SUSPEND && CRYPTO=y && (CRYPTO_AES=y || CRYPTO_AES_586=y || CRYPTO_AES_X86_64=y)
+ default ""
+ ---help---
+ To prevent data gathering from swap after resume you can encrypt
+ the suspend image with a temporary key that is deleted on
+ resume.
+
+ Note that the temporary key is stored unencrypted on disk while the
+ system is suspended.
+
config SUSPEND_SMP
bool
depends on HOTPLUG_CPU && X86 && PM
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 664eb0469b6e..2d8bf054d036 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -112,24 +112,12 @@ static inline void platform_finish(void)
}
}
-static void finish(void)
-{
- device_resume();
- platform_finish();
- thaw_processes();
- enable_nonboot_cpus();
- pm_restore_console();
-}
-
-
static int prepare_processes(void)
{
int error;
pm_prepare_console();
-
sys_sync();
-
disable_nonboot_cpus();
if (freeze_processes()) {
@@ -162,15 +150,6 @@ static void unprepare_processes(void)
pm_restore_console();
}
-static int prepare_devices(void)
-{
- int error;
-
- if ((error = device_suspend(PMSG_FREEZE)))
- printk("Some devices failed to suspend\n");
- return error;
-}
-
/**
* pm_suspend_disk - The granpappy of power management.
*
@@ -187,17 +166,14 @@ int pm_suspend_disk(void)
error = prepare_processes();
if (error)
return error;
- error = prepare_devices();
+ error = device_suspend(PMSG_FREEZE);
if (error) {
+ printk("Some devices failed to suspend\n");
unprepare_processes();
return error;
}
- pr_debug("PM: Attempting to suspend to disk.\n");
- if (pm_disk_mode == PM_DISK_FIRMWARE)
- return pm_ops->enter(PM_SUSPEND_DISK);
-
pr_debug("PM: snapshotting memory.\n");
in_suspend = 1;
if ((error = swsusp_suspend()))
@@ -208,11 +184,20 @@ int pm_suspend_disk(void)
error = swsusp_write();
if (!error)
power_down(pm_disk_mode);
+ else {
+ /* swsusp_write can not fail in device_resume,
+ no need to do second device_resume */
+ swsusp_free();
+ unprepare_processes();
+ return error;
+ }
} else
pr_debug("PM: Image restored successfully.\n");
+
swsusp_free();
Done:
- finish();
+ device_resume();
+ unprepare_processes();
return error;
}
@@ -233,9 +218,12 @@ static int software_resume(void)
{
int error;
+ down(&pm_sem);
if (!swsusp_resume_device) {
- if (!strlen(resume_file))
+ if (!strlen(resume_file)) {
+ up(&pm_sem);
return -ENOENT;
+ }
swsusp_resume_device = name_to_dev_t(resume_file);
pr_debug("swsusp: Resume From Partition %s\n", resume_file);
} else {
@@ -248,6 +236,7 @@ static int software_resume(void)
* FIXME: If noresume is specified, we need to find the partition
* and reset it back to normal swap space.
*/
+ up(&pm_sem);
return 0;
}
@@ -270,20 +259,24 @@ static int software_resume(void)
pr_debug("PM: Preparing devices for restore.\n");
- if ((error = prepare_devices()))
+ if ((error = device_suspend(PMSG_FREEZE))) {
+ printk("Some devices failed to suspend\n");
goto Free;
+ }
mb();
pr_debug("PM: Restoring saved image.\n");
swsusp_resume();
pr_debug("PM: Restore failed, recovering.n");
- finish();
+ device_resume();
Free:
swsusp_free();
Cleanup:
unprepare_processes();
Done:
+ /* For success case, the suspend path will release the lock */
+ up(&pm_sem);
pr_debug("PM: Resume from disk failed.\n");
return 0;
}
@@ -390,7 +383,9 @@ static ssize_t resume_store(struct subsystem * subsys, const char * buf, size_t
if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
res = MKDEV(maj,min);
if (maj == MAJOR(res) && min == MINOR(res)) {
+ down(&pm_sem);
swsusp_resume_device = res;
+ up(&pm_sem);
printk("Attempting manual resume\n");
noresume = 0;
software_resume();
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 71aa0fd22007..22bdc93cc038 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -143,11 +143,12 @@ static void suspend_finish(suspend_state_t state)
-static char * pm_states[] = {
+static char *pm_states[PM_SUSPEND_MAX] = {
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
+#ifdef CONFIG_SOFTWARE_SUSPEND
[PM_SUSPEND_DISK] = "disk",
- NULL,
+#endif
};
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 61deda04e39e..159149321b3c 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -60,9 +60,8 @@ struct pm_dev *pm_register(pm_dev_t type,
unsigned long id,
pm_callback callback)
{
- struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+ struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL);
if (dev) {
- memset(dev, 0, sizeof(*dev));
dev->type = type;
dev->id = id;
dev->callback = callback;
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 3bd0d261818f..28de118f7a0b 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -38,7 +38,6 @@ void refrigerator(void)
processes around? */
long save;
save = current->state;
- current->state = TASK_UNINTERRUPTIBLE;
pr_debug("%s entered refrigerator\n", current->comm);
printk("=");
@@ -47,8 +46,10 @@ void refrigerator(void)
recalc_sigpending(); /* We sent fake signal, clean it up */
spin_unlock_irq(&current->sighand->siglock);
- while (frozen(current))
+ while (frozen(current)) {
+ current->state = TASK_UNINTERRUPTIBLE;
schedule();
+ }
pr_debug("%s left refrigerator\n", current->comm);
current->state = save;
}
@@ -80,13 +81,33 @@ int freeze_processes(void)
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
yield(); /* Yield is okay here */
- if (time_after(jiffies, start_time + TIMEOUT)) {
+ if (todo && time_after(jiffies, start_time + TIMEOUT)) {
printk( "\n" );
printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
- return todo;
+ break;
}
} while(todo);
+ /* This does not unfreeze processes that are already frozen
+ * (we have slightly ugly calling convention in that respect,
+ * and caller must call thaw_processes() if something fails),
+ * but it cleans up leftover PF_FREEZE requests.
+ */
+ if (todo) {
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p)
+ if (freezing(p)) {
+ pr_debug(" clean up: %s\n", p->comm);
+ p->flags &= ~PF_FREEZE;
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ recalc_sigpending_tsk(p);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ }
+ while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+ return todo;
+ }
+
printk( "|\n" );
BUG_ON(in_atomic());
return 0;
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index f2bc71b9fe8b..d967e875ee82 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -31,6 +31,9 @@
* Alex Badea <vampire@go.ro>:
* Fixed runaway init
*
+ * Andreas Steinmetz <ast@domdv.de>:
+ * Added encrypted suspend option
+ *
* More state savers are welcome. Especially for the scsi layer...
*
* For TODOs,FIXMEs also look in Documentation/power/swsusp.txt
@@ -71,8 +74,16 @@
#include <asm/tlbflush.h>
#include <asm/io.h>
+#include <linux/random.h>
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+
#include "power.h"
+#define CIPHER "aes"
+#define MAXKEY 32
+#define MAXIV 32
+
/* References to section boundaries */
extern const void __nosave_begin, __nosave_end;
@@ -103,7 +114,8 @@ static suspend_pagedir_t *pagedir_save;
#define SWSUSP_SIG "S1SUSPEND"
static struct swsusp_header {
- char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
+ char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)];
+ u8 key_iv[MAXKEY+MAXIV];
swp_entry_t swsusp_info;
char orig_sig[10];
char sig[10];
@@ -129,6 +141,131 @@ static struct swsusp_info swsusp_info;
static unsigned short swapfile_used[MAX_SWAPFILES];
static unsigned short root_swap;
+static int write_page(unsigned long addr, swp_entry_t * loc);
+static int bio_read_page(pgoff_t page_off, void * page);
+
+static u8 key_iv[MAXKEY+MAXIV];
+
+#ifdef CONFIG_SWSUSP_ENCRYPT
+
+static int crypto_init(int mode, void **mem)
+{
+ int error = 0;
+ int len;
+ char *modemsg;
+ struct crypto_tfm *tfm;
+
+ modemsg = mode ? "suspend not possible" : "resume not possible";
+
+ tfm = crypto_alloc_tfm(CIPHER, CRYPTO_TFM_MODE_CBC);
+ if(!tfm) {
+ printk(KERN_ERR "swsusp: no tfm, %s\n", modemsg);
+ error = -EINVAL;
+ goto out;
+ }
+
+ if(MAXKEY < crypto_tfm_alg_min_keysize(tfm)) {
+ printk(KERN_ERR "swsusp: key buffer too small, %s\n", modemsg);
+ error = -ENOKEY;
+ goto fail;
+ }
+
+ if (mode)
+ get_random_bytes(key_iv, MAXKEY+MAXIV);
+
+ len = crypto_tfm_alg_max_keysize(tfm);
+ if (len > MAXKEY)
+ len = MAXKEY;
+
+ if (crypto_cipher_setkey(tfm, key_iv, len)) {
+ printk(KERN_ERR "swsusp: key setup failure, %s\n", modemsg);
+ error = -EKEYREJECTED;
+ goto fail;
+ }
+
+ len = crypto_tfm_alg_ivsize(tfm);
+
+ if (MAXIV < len) {
+ printk(KERN_ERR "swsusp: iv buffer too small, %s\n", modemsg);
+ error = -EOVERFLOW;
+ goto fail;
+ }
+
+ crypto_cipher_set_iv(tfm, key_iv+MAXKEY, len);
+
+ *mem=(void *)tfm;
+
+ goto out;
+
+fail: crypto_free_tfm(tfm);
+out: return error;
+}
+
+static __inline__ void crypto_exit(void *mem)
+{
+ crypto_free_tfm((struct crypto_tfm *)mem);
+}
+
+static __inline__ int crypto_write(struct pbe *p, void *mem)
+{
+ int error = 0;
+ struct scatterlist src, dst;
+
+ src.page = virt_to_page(p->address);
+ src.offset = 0;
+ src.length = PAGE_SIZE;
+ dst.page = virt_to_page((void *)&swsusp_header);
+ dst.offset = 0;
+ dst.length = PAGE_SIZE;
+
+ error = crypto_cipher_encrypt((struct crypto_tfm *)mem, &dst, &src,
+ PAGE_SIZE);
+
+ if (!error)
+ error = write_page((unsigned long)&swsusp_header,
+ &(p->swap_address));
+ return error;
+}
+
+static __inline__ int crypto_read(struct pbe *p, void *mem)
+{
+ int error = 0;
+ struct scatterlist src, dst;
+
+ error = bio_read_page(swp_offset(p->swap_address), (void *)p->address);
+ if (!error) {
+ src.offset = 0;
+ src.length = PAGE_SIZE;
+ dst.offset = 0;
+ dst.length = PAGE_SIZE;
+ src.page = dst.page = virt_to_page((void *)p->address);
+
+ error = crypto_cipher_decrypt((struct crypto_tfm *)mem, &dst,
+ &src, PAGE_SIZE);
+ }
+ return error;
+}
+#else
+static __inline__ int crypto_init(int mode, void *mem)
+{
+ return 0;
+}
+
+static __inline__ void crypto_exit(void *mem)
+{
+}
+
+static __inline__ int crypto_write(struct pbe *p, void *mem)
+{
+ return write_page(p->address, &(p->swap_address));
+}
+
+static __inline__ int crypto_read(struct pbe *p, void *mem)
+{
+ return bio_read_page(swp_offset(p->swap_address), (void *)p->address);
+}
+#endif
+
static int mark_swapfiles(swp_entry_t prev)
{
int error;
@@ -140,6 +277,7 @@ static int mark_swapfiles(swp_entry_t prev)
!memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
+ memcpy(swsusp_header.key_iv, key_iv, MAXKEY+MAXIV);
swsusp_header.swsusp_info = prev;
error = rw_swap_page_sync(WRITE,
swp_entry(root_swap, 0),
@@ -179,9 +317,9 @@ static int swsusp_swap_check(void) /* This is called before saving image */
len=strlen(resume_file);
root_swap = 0xFFFF;
- swap_list_lock();
+ spin_lock(&swap_lock);
for (i=0; i<MAX_SWAPFILES; i++) {
- if (swap_info[i].flags == 0) {
+ if (!(swap_info[i].flags & SWP_WRITEOK)) {
swapfile_used[i]=SWAPFILE_UNUSED;
} else {
if (!len) {
@@ -202,7 +340,7 @@ static int swsusp_swap_check(void) /* This is called before saving image */
}
}
}
- swap_list_unlock();
+ spin_unlock(&swap_lock);
return (root_swap != 0xffff) ? 0 : -ENODEV;
}
@@ -216,12 +354,12 @@ static void lock_swapdevices(void)
{
int i;
- swap_list_lock();
+ spin_lock(&swap_lock);
for (i = 0; i< MAX_SWAPFILES; i++)
if (swapfile_used[i] == SWAPFILE_IGNORED) {
- swap_info[i].flags ^= 0xFF;
+ swap_info[i].flags ^= SWP_WRITEOK;
}
- swap_list_unlock();
+ spin_unlock(&swap_lock);
}
/**
@@ -286,6 +424,10 @@ static int data_write(void)
int error = 0, i = 0;
unsigned int mod = nr_copy_pages / 100;
struct pbe *p;
+ void *tfm;
+
+ if ((error = crypto_init(1, &tfm)))
+ return error;
if (!mod)
mod = 1;
@@ -294,11 +436,14 @@ static int data_write(void)
for_each_pbe (p, pagedir_nosave) {
if (!(i%mod))
printk( "\b\b\b\b%3d%%", i / mod );
- if ((error = write_page(p->address, &(p->swap_address))))
+ if ((error = crypto_write(p, tfm))) {
+ crypto_exit(tfm);
return error;
+ }
i++;
}
printk("\b\b\b\bdone\n");
+ crypto_exit(tfm);
return error;
}
@@ -385,7 +530,6 @@ static int write_pagedir(void)
* write_suspend_image - Write entire image and metadata.
*
*/
-
static int write_suspend_image(void)
{
int error;
@@ -400,6 +544,7 @@ static int write_suspend_image(void)
if ((error = close_swap()))
goto FreePagedir;
Done:
+ memset(key_iv, 0, MAXKEY+MAXIV);
return error;
FreePagedir:
free_pagedir_entries();
@@ -591,18 +736,7 @@ static void copy_data_pages(void)
static int calc_nr(int nr_copy)
{
- int extra = 0;
- int mod = !!(nr_copy % PBES_PER_PAGE);
- int diff = (nr_copy / PBES_PER_PAGE) + mod;
-
- do {
- extra += diff;
- nr_copy += diff;
- mod = !!(nr_copy % PBES_PER_PAGE);
- diff = (nr_copy / PBES_PER_PAGE) + mod - extra;
- } while (diff > 0);
-
- return nr_copy;
+ return nr_copy + (nr_copy+PBES_PER_PAGE-2)/(PBES_PER_PAGE-1);
}
/**
@@ -886,20 +1020,21 @@ int swsusp_suspend(void)
* at resume time, and evil weirdness ensues.
*/
if ((error = device_power_down(PMSG_FREEZE))) {
+ printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
local_irq_enable();
return error;
}
if ((error = swsusp_swap_check())) {
- printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
- "swapon -a!\n");
+ printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
+ device_power_up();
local_irq_enable();
return error;
}
save_processor_state();
if ((error = swsusp_arch_suspend()))
- printk("Error %d suspending\n", error);
+ printk(KERN_ERR "Error %d suspending\n", error);
/* Restore control flow magically appears here */
restore_processor_state();
BUG_ON (nr_copy_pages_check != nr_copy_pages);
@@ -924,6 +1059,7 @@ int swsusp_resume(void)
BUG_ON(!error);
restore_processor_state();
restore_highmem();
+ touch_softlockup_watchdog();
device_power_up();
local_irq_enable();
return error;
@@ -1179,7 +1315,8 @@ static const char * sanity_check(void)
if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
return "machine";
#if 0
- if(swsusp_info.cpus != num_online_cpus())
+ /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */
+ if (swsusp_info.cpus != num_possible_cpus())
return "number of cpus";
#endif
return NULL;
@@ -1212,13 +1349,14 @@ static int check_sig(void)
return error;
if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
+ memcpy(key_iv, swsusp_header.key_iv, MAXKEY+MAXIV);
+ memset(swsusp_header.key_iv, 0, MAXKEY+MAXIV);
/*
* Reset swap signature now.
*/
error = bio_write_page(0, &swsusp_header);
} else {
- printk(KERN_ERR "swsusp: Suspend partition has wrong signature?\n");
return -EINVAL;
}
if (!error)
@@ -1239,6 +1377,10 @@ static int data_read(struct pbe *pblist)
int error = 0;
int i = 0;
int mod = swsusp_info.image_pages / 100;
+ void *tfm;
+
+ if ((error = crypto_init(0, &tfm)))
+ return error;
if (!mod)
mod = 1;
@@ -1250,14 +1392,15 @@ static int data_read(struct pbe *pblist)
if (!(i % mod))
printk("\b\b\b\b%3d%%", i / mod);
- error = bio_read_page(swp_offset(p->swap_address),
- (void *)p->address);
- if (error)
+ if ((error = crypto_read(p, tfm))) {
+ crypto_exit(tfm);
return error;
+ }
i++;
}
printk("\b\b\b\bdone\n");
+ crypto_exit(tfm);
return error;
}
@@ -1385,6 +1528,7 @@ int swsusp_read(void)
error = read_suspend_image();
blkdev_put(resume_bdev);
+ memset(key_iv, 0, MAXKEY+MAXIV);
if (!error)
pr_debug("swsusp: Reading resume file was successful\n");
diff --git a/kernel/printk.c b/kernel/printk.c
index 5092397fac29..a967605bc2e3 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -514,6 +514,9 @@ asmlinkage int printk(const char *fmt, ...)
return r;
}
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int printk_cpu = UINT_MAX;
+
asmlinkage int vprintk(const char *fmt, va_list args)
{
unsigned long flags;
@@ -522,11 +525,15 @@ asmlinkage int vprintk(const char *fmt, va_list args)
static char printk_buf[1024];
static int log_level_unknown = 1;
- if (unlikely(oops_in_progress))
+ preempt_disable();
+ if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
+ /* If a crash is occurring during printk() on this CPU,
+ * make sure we can't deadlock */
zap_locks();
/* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags);
+ printk_cpu = smp_processor_id();
/* Emit the output into the temporary buffer */
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
@@ -595,6 +602,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
* CPU until it is officially up. We shouldn't be calling into
* random console drivers on a CPU which doesn't exist yet..
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
goto out;
}
@@ -604,6 +612,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
* We own the drivers. We can drop the spinlock and let
* release_console_sem() print the text
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
console_may_schedule = 0;
release_console_sem();
@@ -613,9 +622,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
* allows the semaphore holder to proceed and to call the
* console drivers with the output which we just produced.
*/
+ printk_cpu = UINT_MAX;
spin_unlock_irqrestore(&logbuf_lock, flags);
}
out:
+ preempt_enable();
return printed_len;
}
EXPORT_SYMBOL(printk);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 8dcb8f6288bc..019e04ec065a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -118,6 +118,33 @@ int ptrace_check_attach(struct task_struct *child, int kill)
return ret;
}
+static int may_attach(struct task_struct *task)
+{
+ if (!task->mm)
+ return -EPERM;
+ if (((current->uid != task->euid) ||
+ (current->uid != task->suid) ||
+ (current->uid != task->uid) ||
+ (current->gid != task->egid) ||
+ (current->gid != task->sgid) ||
+ (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+ return -EPERM;
+ smp_rmb();
+ if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+ return -EPERM;
+
+ return security_ptrace(current, task);
+}
+
+int ptrace_may_attach(struct task_struct *task)
+{
+ int err;
+ task_lock(task);
+ err = may_attach(task);
+ task_unlock(task);
+ return !err;
+}
+
int ptrace_attach(struct task_struct *task)
{
int retval;
@@ -127,22 +154,10 @@ int ptrace_attach(struct task_struct *task)
goto bad;
if (task == current)
goto bad;
- if (!task->mm)
- goto bad;
- if(((current->uid != task->euid) ||
- (current->uid != task->suid) ||
- (current->uid != task->uid) ||
- (current->gid != task->egid) ||
- (current->gid != task->sgid) ||
- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
- goto bad;
- smp_rmb();
- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
- goto bad;
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
- retval = security_ptrace(current, task);
+ retval = may_attach(task);
if (retval)
goto bad;
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index f436993bd590..bef3b6901b76 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -45,6 +45,7 @@
#include <linux/percpu.h>
#include <linux/notifier.h>
#include <linux/rcupdate.h>
+#include <linux/rcuref.h>
#include <linux/cpu.h>
/* Definition for rcupdate control block. */
@@ -72,6 +73,19 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
static int maxbatch = 10;
+#ifndef __HAVE_ARCH_CMPXCHG
+/*
+ * We use an array of spinlocks for the rcurefs -- similar to ones in sparc
+ * 32 bit atomic_t implementations, and a hash function similar to that
+ * for our refcounting needs.
+ * Can't help multiprocessors which donot have cmpxchg :(
+ */
+
+spinlock_t __rcuref_hash[RCUREF_HASH_SIZE] = {
+ [0 ... (RCUREF_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+#endif
+
/**
* call_rcu - Queue an RCU callback for invocation after a grace period.
* @head: structure to be used for queueing the RCU updates.
diff --git a/kernel/resource.c b/kernel/resource.c
index 26967e042201..92285d822de6 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -430,10 +430,9 @@ EXPORT_SYMBOL(adjust_resource);
*/
struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
{
- struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+ struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) {
- memset(res, 0, sizeof(*res));
res->name = name;
res->start = start;
res->end = start + n - 1;
diff --git a/kernel/sched.c b/kernel/sched.c
index 5f889d0cbfcc..81b3a96ed2d0 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -875,7 +875,7 @@ static int migrate_task(task_t *p, int dest_cpu, migration_req_t *req)
* smp_call_function() if an IPI is sent by the same process we are
* waiting to become inactive.
*/
-void wait_task_inactive(task_t * p)
+void wait_task_inactive(task_t *p)
{
unsigned long flags;
runqueue_t *rq;
@@ -966,8 +966,11 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
int local_group;
int i;
+ /* Skip over this group if it has no CPUs allowed */
+ if (!cpus_intersects(group->cpumask, p->cpus_allowed))
+ goto nextgroup;
+
local_group = cpu_isset(this_cpu, group->cpumask);
- /* XXX: put a cpus allowed check */
/* Tally up the load of all CPUs in the group */
avg_load = 0;
@@ -992,6 +995,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
min_load = avg_load;
idlest = group;
}
+nextgroup:
group = group->next;
} while (group != sd->groups);
@@ -1003,13 +1007,18 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
/*
* find_idlest_queue - find the idlest runqueue among the cpus in group.
*/
-static int find_idlest_cpu(struct sched_group *group, int this_cpu)
+static int
+find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
{
+ cpumask_t tmp;
unsigned long load, min_load = ULONG_MAX;
int idlest = -1;
int i;
- for_each_cpu_mask(i, group->cpumask) {
+ /* Traverse only the allowed CPUs */
+ cpus_and(tmp, group->cpumask, p->cpus_allowed);
+
+ for_each_cpu_mask(i, tmp) {
load = source_load(i, 0);
if (load < min_load || (load == min_load && i == this_cpu)) {
@@ -1052,7 +1061,7 @@ static int sched_balance_self(int cpu, int flag)
if (!group)
goto nextlevel;
- new_cpu = find_idlest_cpu(group, cpu);
+ new_cpu = find_idlest_cpu(group, t, cpu);
if (new_cpu == -1 || new_cpu == cpu)
goto nextlevel;
@@ -1127,7 +1136,7 @@ static inline int wake_idle(int cpu, task_t *p)
*
* returns failure only if the task is already active.
*/
-static int try_to_wake_up(task_t * p, unsigned int state, int sync)
+static int try_to_wake_up(task_t *p, unsigned int state, int sync)
{
int cpu, this_cpu, success = 0;
unsigned long flags;
@@ -1252,6 +1261,16 @@ out_activate:
}
/*
+ * 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.)
+ */
+ if (old_state & TASK_NONINTERACTIVE)
+ __activate_task(p, rq);
+ else
+ 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)
* don't trigger a preemption, if the woken up task will run on
@@ -1259,7 +1278,6 @@ out_activate:
* the waker guarantees that the freshly woken up task is going
* to be considered on this CPU.)
*/
- activate_task(p, rq, cpu == this_cpu);
if (!sync || cpu != this_cpu) {
if (TASK_PREEMPTS_CURR(p, rq))
resched_task(rq->curr);
@@ -1274,7 +1292,7 @@ out:
return success;
}
-int fastcall wake_up_process(task_t * p)
+int fastcall wake_up_process(task_t *p)
{
return try_to_wake_up(p, TASK_STOPPED | TASK_TRACED |
TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0);
@@ -1353,7 +1371,7 @@ void fastcall sched_fork(task_t *p, int clone_flags)
* that must be done for every newly created context, then puts the task
* on the runqueue and wakes it.
*/
-void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
+void fastcall wake_up_new_task(task_t *p, unsigned long clone_flags)
{
unsigned long flags;
int this_cpu, cpu;
@@ -1436,7 +1454,7 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
* artificially, because any timeslice recovered here
* was given away by the parent in the first place.)
*/
-void fastcall sched_exit(task_t * p)
+void fastcall sched_exit(task_t *p)
{
unsigned long flags;
runqueue_t *rq;
@@ -1478,6 +1496,7 @@ static inline void prepare_task_switch(runqueue_t *rq, task_t *next)
/**
* finish_task_switch - clean up after a task-switch
+ * @rq: runqueue associated with task-switch
* @prev: the thread we just switched away from.
*
* finish_task_switch must be called after the context switch, paired
@@ -1510,6 +1529,10 @@ static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
* Manfred Spraul <manfred@colorfullife.com>
*/
prev_task_flags = prev->flags;
+#ifdef CONFIG_DEBUG_SPINLOCK
+ /* this is a valid case when another task releases the spinlock */
+ rq->lock.owner = current;
+#endif
finish_arch_switch(prev);
finish_lock_switch(rq, prev);
if (mm)
@@ -1752,7 +1775,8 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
*/
static inline
int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
- struct sched_domain *sd, enum idle_type idle, int *all_pinned)
+ struct sched_domain *sd, enum idle_type idle,
+ int *all_pinned)
{
/*
* We do not migrate tasks that are:
@@ -1882,10 +1906,11 @@ out:
*/
static struct sched_group *
find_busiest_group(struct sched_domain *sd, int this_cpu,
- unsigned long *imbalance, enum idle_type idle)
+ unsigned long *imbalance, enum idle_type idle, int *sd_idle)
{
struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+ unsigned long max_pull;
int load_idx;
max_load = this_load = total_load = total_pwr = 0;
@@ -1907,6 +1932,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
avg_load = 0;
for_each_cpu_mask(i, group->cpumask) {
+ if (*sd_idle && !idle_cpu(i))
+ *sd_idle = 0;
+
/* Bias balancing toward cpus of our domain */
if (local_group)
load = target_load(i, load_idx);
@@ -1932,7 +1960,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
group = group->next;
} while (group != sd->groups);
- if (!busiest || this_load >= max_load)
+ if (!busiest || this_load >= max_load || max_load <= SCHED_LOAD_SCALE)
goto out_balanced;
avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr;
@@ -1952,8 +1980,12 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
* by pulling tasks to us. Be careful of negative numbers as they'll
* appear as very large values with unsigned longs.
*/
+
+ /* Don't want to pull so many tasks that a group would go idle */
+ max_pull = min(max_load - avg_load, max_load - SCHED_LOAD_SCALE);
+
/* How much load to actually move to equalise the imbalance */
- *imbalance = min((max_load - avg_load) * busiest->cpu_power,
+ *imbalance = min(max_pull * busiest->cpu_power,
(avg_load - this_load) * this->cpu_power)
/ SCHED_LOAD_SCALE;
@@ -2050,11 +2082,14 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
unsigned long imbalance;
int nr_moved, all_pinned = 0;
int active_balance = 0;
+ int sd_idle = 0;
+
+ if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER)
+ sd_idle = 1;
- spin_lock(&this_rq->lock);
schedstat_inc(sd, lb_cnt[idle]);
- group = find_busiest_group(sd, this_cpu, &imbalance, idle);
+ group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle);
if (!group) {
schedstat_inc(sd, lb_nobusyg[idle]);
goto out_balanced;
@@ -2078,19 +2113,16 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
* still unbalanced. nr_moved simply stays zero, so it is
* correctly treated as an imbalance.
*/
- double_lock_balance(this_rq, busiest);
+ double_rq_lock(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
- imbalance, sd, idle,
- &all_pinned);
- spin_unlock(&busiest->lock);
+ imbalance, sd, idle, &all_pinned);
+ double_rq_unlock(this_rq, busiest);
/* All tasks on this runqueue were pinned by CPU affinity */
if (unlikely(all_pinned))
goto out_balanced;
}
- spin_unlock(&this_rq->lock);
-
if (!nr_moved) {
schedstat_inc(sd, lb_failed[idle]);
sd->nr_balance_failed++;
@@ -2098,6 +2130,16 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
spin_lock(&busiest->lock);
+
+ /* don't kick the migration_thread, if the curr
+ * task on busiest cpu can't be moved to this_cpu
+ */
+ if (!cpu_isset(this_cpu, busiest->curr->cpus_allowed)) {
+ spin_unlock(&busiest->lock);
+ all_pinned = 1;
+ goto out_one_pinned;
+ }
+
if (!busiest->active_balance) {
busiest->active_balance = 1;
busiest->push_cpu = this_cpu;
@@ -2130,19 +2172,23 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
sd->balance_interval *= 2;
}
+ if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+ return -1;
return nr_moved;
out_balanced:
- spin_unlock(&this_rq->lock);
-
schedstat_inc(sd, lb_balanced[idle]);
sd->nr_balance_failed = 0;
+
+out_one_pinned:
/* tune up the balancing interval */
if ((all_pinned && sd->balance_interval < MAX_PINNED_INTERVAL) ||
(sd->balance_interval < sd->max_interval))
sd->balance_interval *= 2;
+ if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+ return -1;
return 0;
}
@@ -2160,9 +2206,13 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
runqueue_t *busiest = NULL;
unsigned long imbalance;
int nr_moved = 0;
+ int sd_idle = 0;
+
+ if (sd->flags & SD_SHARE_CPUPOWER)
+ sd_idle = 1;
schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
- group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
+ group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE, &sd_idle);
if (!group) {
schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
goto out_balanced;
@@ -2176,22 +2226,30 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
BUG_ON(busiest == this_rq);
- /* Attempt to move tasks */
- double_lock_balance(this_rq, busiest);
-
schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
- nr_moved = move_tasks(this_rq, this_cpu, busiest,
+
+ nr_moved = 0;
+ if (busiest->nr_running > 1) {
+ /* Attempt to move tasks */
+ double_lock_balance(this_rq, busiest);
+ nr_moved = move_tasks(this_rq, this_cpu, busiest,
imbalance, sd, NEWLY_IDLE, NULL);
- if (!nr_moved)
+ spin_unlock(&busiest->lock);
+ }
+
+ if (!nr_moved) {
schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
- else
+ if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+ return -1;
+ } else
sd->nr_balance_failed = 0;
- spin_unlock(&busiest->lock);
return nr_moved;
out_balanced:
schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+ if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+ return -1;
sd->nr_balance_failed = 0;
return 0;
}
@@ -2316,7 +2374,11 @@ static void rebalance_tick(int this_cpu, runqueue_t *this_rq,
if (j - sd->last_balance >= interval) {
if (load_balance(this_cpu, this_rq, sd, idle)) {
- /* We've pulled tasks over so no longer idle */
+ /*
+ * We've pulled tasks over so either we're no
+ * longer idle, or one of our SMT siblings is
+ * not idle.
+ */
idle = NOT_IDLE;
}
sd->last_balance += interval;
@@ -2575,6 +2637,13 @@ out:
}
#ifdef CONFIG_SCHED_SMT
+static inline void wakeup_busy_runqueue(runqueue_t *rq)
+{
+ /* If an SMT runqueue is sleeping due to priority reasons wake it up */
+ if (rq->curr == rq->idle && rq->nr_running)
+ resched_task(rq->idle);
+}
+
static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
{
struct sched_domain *tmp, *sd = NULL;
@@ -2608,12 +2677,7 @@ static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
for_each_cpu_mask(i, sibling_map) {
runqueue_t *smt_rq = cpu_rq(i);
- /*
- * If an SMT sibling task is sleeping due to priority
- * reasons wake it up now.
- */
- if (smt_rq->curr == smt_rq->idle && smt_rq->nr_running)
- resched_task(smt_rq->idle);
+ wakeup_busy_runqueue(smt_rq);
}
for_each_cpu_mask(i, sibling_map)
@@ -2624,6 +2688,16 @@ static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
*/
}
+/*
+ * number of 'lost' timeslices this task wont be able to fully
+ * utilize, if another task runs on a sibling. This models the
+ * slowdown effect of other tasks running on siblings:
+ */
+static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd)
+{
+ return p->time_slice * (100 - sd->per_cpu_gain) / 100;
+}
+
static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
{
struct sched_domain *tmp, *sd = NULL;
@@ -2667,6 +2741,10 @@ static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
runqueue_t *smt_rq = cpu_rq(i);
task_t *smt_curr = smt_rq->curr;
+ /* Kernel threads do not participate in dependent sleeping */
+ if (!p->mm || !smt_curr->mm || rt_task(p))
+ goto check_smt_task;
+
/*
* If a user task with lower static priority than the
* running task on the SMT sibling is trying to schedule,
@@ -2675,21 +2753,45 @@ static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
* task from using an unfair proportion of the
* physical cpu's resources. -ck
*/
- if (((smt_curr->time_slice * (100 - sd->per_cpu_gain) / 100) >
- task_timeslice(p) || rt_task(smt_curr)) &&
- p->mm && smt_curr->mm && !rt_task(p))
- ret = 1;
+ if (rt_task(smt_curr)) {
+ /*
+ * With real time tasks we run non-rt tasks only
+ * per_cpu_gain% of the time.
+ */
+ if ((jiffies % DEF_TIMESLICE) >
+ (sd->per_cpu_gain * DEF_TIMESLICE / 100))
+ ret = 1;
+ } else
+ if (smt_curr->static_prio < p->static_prio &&
+ !TASK_PREEMPTS_CURR(p, smt_rq) &&
+ smt_slice(smt_curr, sd) > task_timeslice(p))
+ ret = 1;
+
+check_smt_task:
+ if ((!smt_curr->mm && smt_curr != smt_rq->idle) ||
+ rt_task(smt_curr))
+ continue;
+ if (!p->mm) {
+ wakeup_busy_runqueue(smt_rq);
+ continue;
+ }
/*
- * Reschedule a lower priority task on the SMT sibling,
- * or wake it up if it has been put to sleep for priority
- * reasons.
+ * Reschedule a lower priority task on the SMT sibling for
+ * it to be put to sleep, or wake it up if it has been put to
+ * sleep for priority reasons to see if it should run now.
*/
- if ((((p->time_slice * (100 - sd->per_cpu_gain) / 100) >
- task_timeslice(smt_curr) || rt_task(p)) &&
- smt_curr->mm && p->mm && !rt_task(smt_curr)) ||
- (smt_curr == smt_rq->idle && smt_rq->nr_running))
- resched_task(smt_curr);
+ if (rt_task(p)) {
+ if ((jiffies % DEF_TIMESLICE) >
+ (sd->per_cpu_gain * DEF_TIMESLICE / 100))
+ resched_task(smt_curr);
+ } else {
+ if (TASK_PREEMPTS_CURR(p, smt_rq) &&
+ smt_slice(p, sd) > task_timeslice(smt_curr))
+ resched_task(smt_curr);
+ else
+ wakeup_busy_runqueue(smt_rq);
+ }
}
out_unlock:
for_each_cpu_mask(i, sibling_map)
@@ -2887,6 +2989,7 @@ switch_tasks:
if (next == rq->idle)
schedstat_inc(rq, sched_goidle);
prefetch(next);
+ prefetch_stack(next);
clear_tsk_need_resched(prev);
rcu_qsctr_inc(task_cpu(prev));
@@ -3014,7 +3117,8 @@ need_resched:
#endif /* CONFIG_PREEMPT */
-int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, void *key)
+int default_wake_function(wait_queue_t *curr, unsigned mode, int sync,
+ void *key)
{
task_t *p = curr->private;
return try_to_wake_up(p, mode, sync);
@@ -3056,7 +3160,7 @@ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
* @key: is directly passed to the wakeup function
*/
void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
- int nr_exclusive, void *key)
+ int nr_exclusive, void *key)
{
unsigned long flags;
@@ -3088,7 +3192,8 @@ void fastcall __wake_up_locked(wait_queue_head_t *q, unsigned int mode)
*
* On UP it can prevent extra preemption.
*/
-void fastcall __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+void fastcall
+__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
{
unsigned long flags;
int sync = 1;
@@ -3279,7 +3384,8 @@ void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
EXPORT_SYMBOL(interruptible_sleep_on);
-long fastcall __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall __sched
+interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
SLEEP_ON_VAR
@@ -3498,7 +3604,8 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
* @policy: new policy.
* @param: structure containing the new RT priority.
*/
-int sched_setscheduler(struct task_struct *p, int policy, struct sched_param *param)
+int sched_setscheduler(struct task_struct *p, int policy,
+ struct sched_param *param)
{
int retval;
int oldprio, oldpolicy = -1;
@@ -3518,7 +3625,7 @@ recheck:
* 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0.
*/
if (param->sched_priority < 0 ||
- (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
+ (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
(!p->mm && param->sched_priority > MAX_RT_PRIO-1))
return -EINVAL;
if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
@@ -3581,7 +3688,8 @@ recheck:
}
EXPORT_SYMBOL_GPL(sched_setscheduler);
-static int do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
+static int
+do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
{
int retval;
struct sched_param lparam;
@@ -3848,7 +3956,7 @@ asmlinkage long sys_sched_yield(void)
if (rt_task(current))
target = rq->active;
- if (current->array->nr_active == 1) {
+ if (array->nr_active == 1) {
schedstat_inc(rq, yld_act_empty);
if (!rq->expired->nr_active)
schedstat_inc(rq, yld_both_empty);
@@ -3912,7 +4020,7 @@ EXPORT_SYMBOL(cond_resched);
* operations here to prevent schedule() from being called twice (once via
* spin_unlock(), once by hand).
*/
-int cond_resched_lock(spinlock_t * lock)
+int cond_resched_lock(spinlock_t *lock)
{
int ret = 0;
@@ -4095,7 +4203,7 @@ static inline struct task_struct *younger_sibling(struct task_struct *p)
return list_entry(p->sibling.next,struct task_struct,sibling);
}
-static void show_task(task_t * p)
+static void show_task(task_t *p)
{
task_t *relative;
unsigned state;
@@ -4121,7 +4229,7 @@ static void show_task(task_t * p)
#endif
#ifdef CONFIG_DEBUG_STACK_USAGE
{
- unsigned long * n = (unsigned long *) (p->thread_info+1);
+ unsigned long *n = (unsigned long *) (p->thread_info+1);
while (!*n)
n++;
free = (unsigned long) n - (unsigned long)(p->thread_info+1);
@@ -4330,7 +4438,7 @@ out:
* thread migration by bumping thread off CPU then 'pushing' onto
* another runqueue.
*/
-static int migration_thread(void * data)
+static int migration_thread(void *data)
{
runqueue_t *rq;
int cpu = (long)data;
@@ -4779,7 +4887,7 @@ static int sd_parent_degenerate(struct sched_domain *sd,
* Attach the domain 'sd' to 'cpu' as its base domain. Callers must
* hold the hotplug lock.
*/
-void cpu_attach_domain(struct sched_domain *sd, int cpu)
+static void cpu_attach_domain(struct sched_domain *sd, int cpu)
{
runqueue_t *rq = cpu_rq(cpu);
struct sched_domain *tmp;
@@ -4802,7 +4910,7 @@ void cpu_attach_domain(struct sched_domain *sd, int cpu)
}
/* cpus with isolated domains */
-cpumask_t __devinitdata cpu_isolated_map = CPU_MASK_NONE;
+static cpumask_t __devinitdata cpu_isolated_map = CPU_MASK_NONE;
/* Setup the mask of cpus configured for isolated domains */
static int __init isolated_cpu_setup(char *str)
@@ -4830,8 +4938,8 @@ __setup ("isolcpus=", isolated_cpu_setup);
* covered by the given span, and will set each group's ->cpumask correctly,
* and ->cpu_power to 0.
*/
-void init_sched_build_groups(struct sched_group groups[],
- cpumask_t span, int (*group_fn)(int cpu))
+static void init_sched_build_groups(struct sched_group groups[], cpumask_t span,
+ int (*group_fn)(int cpu))
{
struct sched_group *first = NULL, *last = NULL;
cpumask_t covered = CPU_MASK_NONE;
@@ -4864,12 +4972,85 @@ void init_sched_build_groups(struct sched_group groups[],
last->next = first;
}
+#define SD_NODES_PER_DOMAIN 16
-#ifdef ARCH_HAS_SCHED_DOMAIN
-extern void build_sched_domains(const cpumask_t *cpu_map);
-extern void arch_init_sched_domains(const cpumask_t *cpu_map);
-extern void arch_destroy_sched_domains(const cpumask_t *cpu_map);
-#else
+#ifdef CONFIG_NUMA
+/**
+ * find_next_best_node - find the next node to include in a sched_domain
+ * @node: node whose sched_domain we're building
+ * @used_nodes: nodes already in the sched_domain
+ *
+ * Find the next node to include in a given scheduling domain. Simply
+ * finds the closest node not already in the @used_nodes map.
+ *
+ * Should use nodemask_t.
+ */
+static int find_next_best_node(int node, unsigned long *used_nodes)
+{
+ int i, n, val, min_val, best_node = 0;
+
+ min_val = INT_MAX;
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ /* Start at @node */
+ n = (node + i) % MAX_NUMNODES;
+
+ if (!nr_cpus_node(n))
+ continue;
+
+ /* Skip already used nodes */
+ if (test_bit(n, used_nodes))
+ continue;
+
+ /* Simple min distance search */
+ val = node_distance(node, n);
+
+ if (val < min_val) {
+ min_val = val;
+ best_node = n;
+ }
+ }
+
+ set_bit(best_node, used_nodes);
+ return best_node;
+}
+
+/**
+ * sched_domain_node_span - get a cpumask for a node's sched_domain
+ * @node: node whose cpumask we're constructing
+ * @size: number of nodes to include in this span
+ *
+ * Given a node, construct a good cpumask for its sched_domain to span. It
+ * should be one that prevents unnecessary balancing, but also spreads tasks
+ * out optimally.
+ */
+static cpumask_t sched_domain_node_span(int node)
+{
+ int i;
+ cpumask_t span, nodemask;
+ DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+
+ cpus_clear(span);
+ bitmap_zero(used_nodes, MAX_NUMNODES);
+
+ nodemask = node_to_cpumask(node);
+ cpus_or(span, span, nodemask);
+ set_bit(node, used_nodes);
+
+ for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
+ int next_node = find_next_best_node(node, used_nodes);
+ nodemask = node_to_cpumask(next_node);
+ cpus_or(span, span, nodemask);
+ }
+
+ return span;
+}
+#endif
+
+/*
+ * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we
+ * can switch it on easily if needed.
+ */
#ifdef CONFIG_SCHED_SMT
static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
static struct sched_group sched_group_cpus[NR_CPUS];
@@ -4891,36 +5072,20 @@ static int cpu_to_phys_group(int cpu)
}
#ifdef CONFIG_NUMA
-
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static int cpu_to_node_group(int cpu)
-{
- return cpu_to_node(cpu);
-}
-#endif
-
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
/*
- * The domains setup code relies on siblings not spanning
- * multiple nodes. Make sure the architecture has a proper
- * siblings map:
+ * The init_sched_build_groups can't handle what we want to do with node
+ * groups, so roll our own. Now each node has its own list of groups which
+ * gets dynamically allocated.
*/
-static void check_sibling_maps(void)
-{
- int i, j;
+static DEFINE_PER_CPU(struct sched_domain, node_domains);
+static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
- for_each_online_cpu(i) {
- for_each_cpu_mask(j, cpu_sibling_map[i]) {
- if (cpu_to_node(i) != cpu_to_node(j)) {
- printk(KERN_INFO "warning: CPU %d siblings map "
- "to different node - isolating "
- "them.\n", i);
- cpu_sibling_map[i] = cpumask_of_cpu(i);
- break;
- }
- }
- }
+static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
+static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS];
+
+static int cpu_to_allnodes_group(int cpu)
+{
+ return cpu_to_node(cpu);
}
#endif
@@ -4928,9 +5093,24 @@ static void check_sibling_maps(void)
* Build sched domains for a given set of cpus and attach the sched domains
* to the individual cpus
*/
-static void build_sched_domains(const cpumask_t *cpu_map)
+void build_sched_domains(const cpumask_t *cpu_map)
{
int i;
+#ifdef CONFIG_NUMA
+ struct sched_group **sched_group_nodes = NULL;
+ struct sched_group *sched_group_allnodes = NULL;
+
+ /*
+ * Allocate the per-node list of sched groups
+ */
+ sched_group_nodes = kmalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+ GFP_ATOMIC);
+ if (!sched_group_nodes) {
+ printk(KERN_WARNING "Can not alloc sched group node list\n");
+ return;
+ }
+ sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
+#endif
/*
* Set up domains for cpus specified by the cpu_map.
@@ -4943,11 +5123,35 @@ static void build_sched_domains(const cpumask_t *cpu_map)
cpus_and(nodemask, nodemask, *cpu_map);
#ifdef CONFIG_NUMA
+ if (cpus_weight(*cpu_map)
+ > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+ if (!sched_group_allnodes) {
+ sched_group_allnodes
+ = kmalloc(sizeof(struct sched_group)
+ * MAX_NUMNODES,
+ GFP_KERNEL);
+ if (!sched_group_allnodes) {
+ printk(KERN_WARNING
+ "Can not alloc allnodes sched group\n");
+ break;
+ }
+ sched_group_allnodes_bycpu[i]
+ = sched_group_allnodes;
+ }
+ sd = &per_cpu(allnodes_domains, i);
+ *sd = SD_ALLNODES_INIT;
+ sd->span = *cpu_map;
+ group = cpu_to_allnodes_group(i);
+ sd->groups = &sched_group_allnodes[group];
+ p = sd;
+ } else
+ p = NULL;
+
sd = &per_cpu(node_domains, i);
- group = cpu_to_node_group(i);
*sd = SD_NODE_INIT;
- sd->span = *cpu_map;
- sd->groups = &sched_group_nodes[group];
+ sd->span = sched_domain_node_span(cpu_to_node(i));
+ sd->parent = p;
+ cpus_and(sd->span, sd->span, *cpu_map);
#endif
p = sd;
@@ -4972,7 +5176,7 @@ static void build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_SCHED_SMT
/* Set up CPU (sibling) groups */
- for_each_online_cpu(i) {
+ for_each_cpu_mask(i, *cpu_map) {
cpumask_t this_sibling_map = cpu_sibling_map[i];
cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
if (i != first_cpu(this_sibling_map))
@@ -4997,8 +5201,77 @@ static void build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_NUMA
/* Set up node groups */
- init_sched_build_groups(sched_group_nodes, *cpu_map,
- &cpu_to_node_group);
+ if (sched_group_allnodes)
+ init_sched_build_groups(sched_group_allnodes, *cpu_map,
+ &cpu_to_allnodes_group);
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ /* Set up node groups */
+ struct sched_group *sg, *prev;
+ cpumask_t nodemask = node_to_cpumask(i);
+ cpumask_t domainspan;
+ cpumask_t covered = CPU_MASK_NONE;
+ int j;
+
+ cpus_and(nodemask, nodemask, *cpu_map);
+ if (cpus_empty(nodemask)) {
+ sched_group_nodes[i] = NULL;
+ continue;
+ }
+
+ domainspan = sched_domain_node_span(i);
+ cpus_and(domainspan, domainspan, *cpu_map);
+
+ sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+ sched_group_nodes[i] = sg;
+ for_each_cpu_mask(j, nodemask) {
+ struct sched_domain *sd;
+ sd = &per_cpu(node_domains, j);
+ sd->groups = sg;
+ if (sd->groups == NULL) {
+ /* Turn off balancing if we have no groups */
+ sd->flags = 0;
+ }
+ }
+ if (!sg) {
+ printk(KERN_WARNING
+ "Can not alloc domain group for node %d\n", i);
+ continue;
+ }
+ sg->cpu_power = 0;
+ sg->cpumask = nodemask;
+ cpus_or(covered, covered, nodemask);
+ prev = sg;
+
+ for (j = 0; j < MAX_NUMNODES; j++) {
+ cpumask_t tmp, notcovered;
+ int n = (i + j) % MAX_NUMNODES;
+
+ cpus_complement(notcovered, covered);
+ cpus_and(tmp, notcovered, *cpu_map);
+ cpus_and(tmp, tmp, domainspan);
+ if (cpus_empty(tmp))
+ break;
+
+ nodemask = node_to_cpumask(n);
+ cpus_and(tmp, tmp, nodemask);
+ if (cpus_empty(tmp))
+ continue;
+
+ sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+ if (!sg) {
+ printk(KERN_WARNING
+ "Can not alloc domain group for node %d\n", j);
+ break;
+ }
+ sg->cpu_power = 0;
+ sg->cpumask = tmp;
+ cpus_or(covered, covered, tmp);
+ prev->next = sg;
+ prev = sg;
+ }
+ prev->next = sched_group_nodes[i];
+ }
#endif
/* Calculate CPU power for physical packages and nodes */
@@ -5017,14 +5290,46 @@ static void build_sched_domains(const cpumask_t *cpu_map)
sd->groups->cpu_power = power;
#ifdef CONFIG_NUMA
- if (i == first_cpu(sd->groups->cpumask)) {
- /* Only add "power" once for each physical package. */
- sd = &per_cpu(node_domains, i);
- sd->groups->cpu_power += power;
+ 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;
+
+ 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;
+ }
+#endif
+
/* Attach the domains */
for_each_cpu_mask(i, *cpu_map) {
struct sched_domain *sd;
@@ -5039,13 +5344,10 @@ static void build_sched_domains(const cpumask_t *cpu_map)
/*
* Set up scheduler domains and groups. Callers must hold the hotplug lock.
*/
-static void arch_init_sched_domains(cpumask_t *cpu_map)
+static void arch_init_sched_domains(const cpumask_t *cpu_map)
{
cpumask_t cpu_default_map;
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
- check_sibling_maps();
-#endif
/*
* Setup mask for cpus without special case scheduling requirements.
* For now this just excludes isolated cpus, but could be used to
@@ -5058,10 +5360,47 @@ static void arch_init_sched_domains(cpumask_t *cpu_map)
static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
{
- /* Do nothing: everything is statically allocated. */
-}
+#ifdef CONFIG_NUMA
+ int i;
+ int cpu;
-#endif /* ARCH_HAS_SCHED_DOMAIN */
+ for_each_cpu_mask(cpu, *cpu_map) {
+ struct sched_group *sched_group_allnodes
+ = sched_group_allnodes_bycpu[cpu];
+ struct sched_group **sched_group_nodes
+ = sched_group_nodes_bycpu[cpu];
+
+ if (sched_group_allnodes) {
+ kfree(sched_group_allnodes);
+ sched_group_allnodes_bycpu[cpu] = NULL;
+ }
+
+ if (!sched_group_nodes)
+ continue;
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ cpumask_t nodemask = node_to_cpumask(i);
+ struct sched_group *oldsg, *sg = sched_group_nodes[i];
+
+ cpus_and(nodemask, nodemask, *cpu_map);
+ if (cpus_empty(nodemask))
+ continue;
+
+ if (sg == NULL)
+ continue;
+ sg = sg->next;
+next_sg:
+ oldsg = sg;
+ sg = sg->next;
+ kfree(oldsg);
+ if (oldsg != sched_group_nodes[i])
+ goto next_sg;
+ }
+ kfree(sched_group_nodes);
+ sched_group_nodes_bycpu[cpu] = NULL;
+ }
+#endif
+}
/*
* Detach sched domains from a group of cpus specified in cpu_map
@@ -5263,3 +5602,47 @@ void normalize_rt_tasks(void)
}
#endif /* CONFIG_MAGIC_SYSRQ */
+
+#ifdef CONFIG_IA64
+/*
+ * These functions are only useful for the IA64 MCA handling.
+ *
+ * They can only be called when the whole system has been
+ * stopped - every CPU needs to be quiescent, and no scheduling
+ * activity can take place. Using them for anything else would
+ * be a serious bug, and as a result, they aren't even visible
+ * under any other configuration.
+ */
+
+/**
+ * curr_task - return the current task for a given cpu.
+ * @cpu: the processor in question.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+task_t *curr_task(int cpu)
+{
+ return cpu_curr(cpu);
+}
+
+/**
+ * set_curr_task - set the current task for a given cpu.
+ * @cpu: the processor in question.
+ * @p: the task pointer to set.
+ *
+ * Description: This function must only be used when non-maskable interrupts
+ * are serviced on a separate stack. It allows the architecture to switch the
+ * notion of the current task on a cpu in a non-blocking manner. This function
+ * must be called with all CPU's synchronized, and interrupts disabled, the
+ * and caller must save the original value of the current task (see
+ * curr_task() above) and restore that value before reenabling interrupts and
+ * re-starting the system.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+void set_curr_task(int cpu, task_t *p)
+{
+ cpu_curr(cpu) = p;
+}
+
+#endif
diff --git a/kernel/signal.c b/kernel/signal.c
index d282fea81138..b92c3c9f8b9a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -678,7 +678,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
/* forward decl */
static void do_notify_parent_cldstop(struct task_struct *tsk,
- struct task_struct *parent,
+ int to_self,
int why);
/*
@@ -729,14 +729,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);
- if (p->ptrace & PT_PTRACED)
- do_notify_parent_cldstop(p, p->parent,
- CLD_STOPPED);
- else
- do_notify_parent_cldstop(
- p->group_leader,
- p->group_leader->real_parent,
- CLD_STOPPED);
+ do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED);
spin_lock(&p->sighand->siglock);
}
rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
@@ -777,14 +770,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);
- if (p->ptrace & PT_PTRACED)
- do_notify_parent_cldstop(p, p->parent,
- CLD_CONTINUED);
- else
- do_notify_parent_cldstop(
- p->group_leader,
- p->group_leader->real_parent,
- CLD_CONTINUED);
+ do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED);
spin_lock(&p->sighand->siglock);
} else {
/*
@@ -1380,16 +1366,16 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
unsigned long flags;
int ret = 0;
- /*
- * We need the tasklist lock even for the specific
- * thread case (when we don't need to follow the group
- * lists) in order to avoid races with "p->sighand"
- * going away or changing from under us.
- */
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
- read_lock(&tasklist_lock);
+ read_lock(&tasklist_lock);
+
+ if (unlikely(p->flags & PF_EXITING)) {
+ ret = -1;
+ goto out_err;
+ }
+
spin_lock_irqsave(&p->sighand->siglock, flags);
-
+
if (unlikely(!list_empty(&q->list))) {
/*
* If an SI_TIMER entry is already queue just increment
@@ -1399,7 +1385,7 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
BUG();
q->info.si_overrun++;
goto out;
- }
+ }
/* Short-circuit ignored signals. */
if (sig_ignored(p, sig)) {
ret = 1;
@@ -1414,8 +1400,10 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
out:
spin_unlock_irqrestore(&p->sighand->siglock, flags);
+out_err:
read_unlock(&tasklist_lock);
- return(ret);
+
+ return ret;
}
int
@@ -1542,14 +1530,20 @@ 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, struct task_struct *parent,
- int why)
+static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why)
{
struct siginfo info;
unsigned long flags;
+ struct task_struct *parent;
struct sighand_struct *sighand;
+ if (to_self)
+ parent = tsk->parent;
+ else {
+ tsk = tsk->group_leader;
+ parent = tsk->real_parent;
+ }
+
info.si_signo = SIGCHLD;
info.si_errno = 0;
info.si_pid = tsk->pid;
@@ -1618,8 +1612,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
!(current->ptrace & PT_ATTACHED)) &&
(likely(current->parent->signal != current->signal) ||
!unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
- do_notify_parent_cldstop(current, current->parent,
- CLD_TRAPPED);
+ do_notify_parent_cldstop(current, 1, CLD_TRAPPED);
read_unlock(&tasklist_lock);
schedule();
} else {
@@ -1668,25 +1661,25 @@ 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)) {
- read_lock(&tasklist_lock);
- do_notify_parent_cldstop(current, current->parent,
- CLD_STOPPED);
- read_unlock(&tasklist_lock);
- }
- else if (stop_count == 0) {
- read_lock(&tasklist_lock);
- do_notify_parent_cldstop(current->group_leader,
- current->group_leader->real_parent,
- CLD_STOPPED);
- read_unlock(&tasklist_lock);
- }
+ 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);
+
+out:
schedule();
/*
* Now we don't run again until continued.
@@ -2228,8 +2221,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- current->state = TASK_INTERRUPTIBLE;
- timeout = schedule_timeout(timeout);
+ timeout = schedule_timeout_interruptible(timeout);
try_to_freeze();
spin_lock_irq(&current->sighand->siglock);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index b4ab6af1dea8..f766b2fc48be 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -84,7 +84,7 @@ asmlinkage void __do_softirq(void)
cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
- local_softirq_pending() = 0;
+ set_softirq_pending(0);
local_irq_enable();
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
new file mode 100644
index 000000000000..75976209cea7
--- /dev/null
+++ b/kernel/softlockup.c
@@ -0,0 +1,151 @@
+/*
+ * Detect Soft Lockups
+ *
+ * started by Ingo Molnar, (C) 2005, Red Hat
+ *
+ * this code detects soft lockups: incidents in where on a CPU
+ * the kernel does not reschedule for 10 seconds or more.
+ */
+
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/module.h>
+
+static DEFINE_SPINLOCK(print_lock);
+
+static DEFINE_PER_CPU(unsigned long, timestamp) = 0;
+static DEFINE_PER_CPU(unsigned long, print_timestamp) = 0;
+static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
+
+static int did_panic = 0;
+static int softlock_panic(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ did_panic = 1;
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ .notifier_call = softlock_panic,
+};
+
+void touch_softlockup_watchdog(void)
+{
+ per_cpu(timestamp, raw_smp_processor_id()) = jiffies;
+}
+EXPORT_SYMBOL(touch_softlockup_watchdog);
+
+/*
+ * This callback runs from the timer interrupt, and checks
+ * whether the watchdog thread has hung or not:
+ */
+void softlockup_tick(struct pt_regs *regs)
+{
+ int this_cpu = smp_processor_id();
+ unsigned long timestamp = per_cpu(timestamp, this_cpu);
+
+ if (per_cpu(print_timestamp, this_cpu) == timestamp)
+ return;
+
+ /* Do not cause a second panic when there already was one */
+ if (did_panic)
+ return;
+
+ if (time_after(jiffies, timestamp + 10*HZ)) {
+ per_cpu(print_timestamp, this_cpu) = timestamp;
+
+ spin_lock(&print_lock);
+ printk(KERN_ERR "BUG: soft lockup detected on CPU#%d!\n",
+ this_cpu);
+ show_regs(regs);
+ spin_unlock(&print_lock);
+ }
+}
+
+/*
+ * The watchdog thread - runs every second and touches the timestamp.
+ */
+static int watchdog(void * __bind_cpu)
+{
+ struct sched_param param = { .sched_priority = 99 };
+ int this_cpu = (long) __bind_cpu;
+
+ printk("softlockup thread %d started up.\n", this_cpu);
+
+ sched_setscheduler(current, SCHED_FIFO, &param);
+ current->flags |= PF_NOFREEZE;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /*
+ * Run briefly once per second - if this gets delayed for
+ * more than 10 seconds then the debug-printout triggers
+ * in softlockup_tick():
+ */
+ while (!kthread_should_stop()) {
+ msleep_interruptible(1000);
+ touch_softlockup_watchdog();
+ }
+ __set_current_state(TASK_RUNNING);
+
+ return 0;
+}
+
+/*
+ * Create/destroy watchdog threads as CPUs come and go:
+ */
+static int __devinit
+cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+ int hotcpu = (unsigned long)hcpu;
+ struct task_struct *p;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ BUG_ON(per_cpu(watchdog_task, hotcpu));
+ p = kthread_create(watchdog, hcpu, "watchdog/%d", hotcpu);
+ if (IS_ERR(p)) {
+ printk("watchdog for %i failed\n", hotcpu);
+ return NOTIFY_BAD;
+ }
+ per_cpu(watchdog_task, hotcpu) = p;
+ kthread_bind(p, hotcpu);
+ break;
+ case CPU_ONLINE:
+
+ wake_up_process(per_cpu(watchdog_task, hotcpu));
+ break;
+#ifdef CONFIG_HOTPLUG_CPU
+ case CPU_UP_CANCELED:
+ /* Unbind so it can run. Fall thru. */
+ kthread_bind(per_cpu(watchdog_task, hotcpu), smp_processor_id());
+ case CPU_DEAD:
+ p = per_cpu(watchdog_task, hotcpu);
+ per_cpu(watchdog_task, hotcpu) = NULL;
+ kthread_stop(p);
+ break;
+#endif /* CONFIG_HOTPLUG_CPU */
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata cpu_nfb = {
+ .notifier_call = cpu_callback
+};
+
+__init void spawn_softlockup_task(void)
+{
+ void *cpu = (void *)(long)smp_processor_id();
+
+ cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+ cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+ register_cpu_notifier(&cpu_nfb);
+
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+}
+
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index 0c3f9d8bbe17..0375fcd5921d 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -3,7 +3,10 @@
*
* Author: Zwane Mwaikambo <zwane@fsmlabs.com>
*
- * Copyright (2004) Ingo Molnar
+ * Copyright (2004, 2005) Ingo Molnar
+ *
+ * This file contains the spinlock/rwlock implementations for the
+ * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them)
*/
#include <linux/config.h>
@@ -17,12 +20,12 @@
* Generic declaration of the raw read_trylock() function,
* architectures are supposed to optimize this:
*/
-int __lockfunc generic_raw_read_trylock(rwlock_t *lock)
+int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock)
{
- _raw_read_lock(lock);
+ __raw_read_lock(lock);
return 1;
}
-EXPORT_SYMBOL(generic_raw_read_trylock);
+EXPORT_SYMBOL(generic__raw_read_trylock);
int __lockfunc _spin_trylock(spinlock_t *lock)
{
@@ -57,7 +60,7 @@ int __lockfunc _write_trylock(rwlock_t *lock)
}
EXPORT_SYMBOL(_write_trylock);
-#ifndef CONFIG_PREEMPT
+#if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP)
void __lockfunc _read_lock(rwlock_t *lock)
{
@@ -72,7 +75,7 @@ unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
local_irq_save(flags);
preempt_disable();
- _raw_spin_lock_flags(lock, flags);
+ _raw_spin_lock_flags(lock, &flags);
return flags;
}
EXPORT_SYMBOL(_spin_lock_irqsave);
diff --git a/kernel/sys.c b/kernel/sys.c
index 0bcaed6560ac..c80412be2302 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1711,7 +1711,6 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
long error;
- int sig;
error = security_task_prctl(option, arg2, arg3, arg4, arg5);
if (error)
@@ -1719,12 +1718,11 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
switch (option) {
case PR_SET_PDEATHSIG:
- sig = arg2;
- if (!valid_signal(sig)) {
+ if (!valid_signal(arg2)) {
error = -EINVAL;
break;
}
- current->pdeath_signal = sig;
+ current->pdeath_signal = arg2;
break;
case PR_GET_PDEATHSIG:
error = put_user(current->pdeath_signal, (int __user *)arg2);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3e0bbee549ea..8e56e2495542 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -31,6 +31,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/net.h>
#include <linux/sysrq.h>
#include <linux/highuid.h>
#include <linux/writeback.h>
@@ -136,9 +137,6 @@ static struct ctl_table_header root_table_header =
static ctl_table kern_table[];
static ctl_table vm_table[];
-#ifdef CONFIG_NET
-extern ctl_table net_table[];
-#endif
static ctl_table proc_table[];
static ctl_table fs_table[];
static ctl_table debug_table[];
diff --git a/kernel/timer.c b/kernel/timer.c
index 5377f40723ff..3ba10fa35b60 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -950,6 +950,7 @@ void do_timer(struct pt_regs *regs)
{
jiffies_64++;
update_times();
+ softlockup_tick(regs);
}
#ifdef __ARCH_WANT_SYS_ALARM
@@ -1150,9 +1151,26 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
out:
return timeout < 0 ? 0 : timeout;
}
-
EXPORT_SYMBOL(schedule_timeout);
+/*
+ * We can use __set_current_state() here because schedule_timeout() calls
+ * schedule() unconditionally.
+ */
+signed long __sched schedule_timeout_interruptible(signed long timeout)
+{
+ __set_current_state(TASK_INTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_interruptible);
+
+signed long __sched schedule_timeout_uninterruptible(signed long timeout)
+{
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_uninterruptible);
+
/* Thread ID - the internal kernel "pid" */
asmlinkage long sys_gettid(void)
{
@@ -1169,8 +1187,7 @@ static long __sched nanosleep_restart(struct restart_block *restart)
if (!time_after(expire, now))
return 0;
- current->state = TASK_INTERRUPTIBLE;
- expire = schedule_timeout(expire - now);
+ expire = schedule_timeout_interruptible(expire - now);
ret = 0;
if (expire) {
@@ -1198,8 +1215,7 @@ asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __us
return -EINVAL;
expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
- current->state = TASK_INTERRUPTIBLE;
- expire = schedule_timeout(expire);
+ expire = schedule_timeout_interruptible(expire);
ret = 0;
if (expire) {
@@ -1428,7 +1444,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
}
}
-static inline u64 time_interpolator_get_counter(void)
+static inline u64 time_interpolator_get_counter(int writelock)
{
unsigned int src = time_interpolator->source;
@@ -1442,6 +1458,15 @@ static inline u64 time_interpolator_get_counter(void)
now = time_interpolator_get_cycles(src);
if (lcycle && time_after(lcycle, now))
return lcycle;
+
+ /* When holding the xtime write lock, there's no need
+ * to add the overhead of the cmpxchg. Readers are
+ * force to retry until the write lock is released.
+ */
+ if (writelock) {
+ time_interpolator->last_cycle = now;
+ return now;
+ }
/* Keep track of the last timer value returned. The use of cmpxchg here
* will cause contention in an SMP environment.
*/
@@ -1455,7 +1480,7 @@ static inline u64 time_interpolator_get_counter(void)
void time_interpolator_reset(void)
{
time_interpolator->offset = 0;
- time_interpolator->last_counter = time_interpolator_get_counter();
+ time_interpolator->last_counter = time_interpolator_get_counter(1);
}
#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
@@ -1467,7 +1492,7 @@ unsigned long time_interpolator_get_offset(void)
return 0;
return time_interpolator->offset +
- GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
+ GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
}
#define INTERPOLATOR_ADJUST 65536
@@ -1490,7 +1515,7 @@ static void time_interpolator_update(long delta_nsec)
* and the tuning logic insures that.
*/
- counter = time_interpolator_get_counter();
+ counter = time_interpolator_get_counter(1);
offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
@@ -1588,10 +1613,8 @@ void msleep(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
- while (timeout) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
+ while (timeout)
+ timeout = schedule_timeout_uninterruptible(timeout);
}
EXPORT_SYMBOL(msleep);
@@ -1604,10 +1627,8 @@ unsigned long msleep_interruptible(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
- while (timeout && !signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
+ while (timeout && !signal_pending(current))
+ timeout = schedule_timeout_interruptible(timeout);
return jiffies_to_msecs(timeout);
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c7e36d4a70ca..91bacb13a7e2 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -308,10 +308,9 @@ struct workqueue_struct *__create_workqueue(const char *name,
struct workqueue_struct *wq;
struct task_struct *p;
- wq = kmalloc(sizeof(*wq), GFP_KERNEL);
+ wq = kzalloc(sizeof(*wq), GFP_KERNEL);
if (!wq)
return NULL;
- memset(wq, 0, sizeof(*wq));
wq->name = name;
/* We don't need the distraction of CPUs appearing and vanishing. */
@@ -499,7 +498,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
case CPU_UP_PREPARE:
/* Create a new workqueue thread for it. */
list_for_each_entry(wq, &workqueues, list) {
- if (create_workqueue_thread(wq, hotcpu) < 0) {
+ if (!create_workqueue_thread(wq, hotcpu)) {
printk("workqueue for %i failed\n", hotcpu);
return NOTIFY_BAD;
}
diff --git a/lib/Kconfig b/lib/Kconfig
index eeb429a52152..3de93357f5ab 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -12,6 +12,14 @@ config CRC_CCITT
the kernel tree does. Such modules that use library CRC-CCITT
functions require M here.
+config CRC16
+ tristate "CRC16 functions"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC16 functions, but a module built outside
+ the kernel tree does. Such modules that use library CRC16
+ functions require M here.
+
config CRC32
tristate "CRC32 functions"
default y
@@ -72,6 +80,9 @@ config TEXTSEARCH
config TEXTSEARCH_KMP
tristate
+config TEXTSEARCH_BM
+ tristate
+
config TEXTSEARCH_FSM
tristate
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 299f7f3b5b08..016e89a44ac8 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -46,6 +46,25 @@ config LOG_BUF_SHIFT
13 => 8 KB
12 => 4 KB
+config DETECT_SOFTLOCKUP
+ bool "Detect Soft Lockups"
+ depends on DEBUG_KERNEL
+ default y
+ help
+ Say Y here to enable the kernel to detect "soft lockups",
+ which are bugs that cause the kernel to loop in kernel
+ mode for more than 10 seconds, without giving other tasks a
+ chance to run.
+
+ When a soft-lockup is detected, the kernel will print the
+ current stack trace (which you should report), but the
+ system will stay locked up. This feature has negligible
+ overhead.
+
+ (Note that "hard lockups" are separate type of bugs that
+ can be detected via the NMI-watchdog, on platforms that
+ support it.)
+
config SCHEDSTATS
bool "Collect scheduler statistics"
depends on DEBUG_KERNEL && PROC_FS
@@ -151,11 +170,11 @@ config DEBUG_FS
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+ depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
default y if DEBUG_INFO && UML
help
If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
+ and slower, but it might give very useful debugging information
+ on some architectures or you use external debuggers.
+ If you don't debug the kernel, you can say N.
diff --git a/lib/Makefile b/lib/Makefile
index f28d9031303c..44a46750690a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -16,17 +16,20 @@ CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
+obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
-ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
+ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
lib-y += dec_and_lock.o
endif
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
+obj-$(CONFIG_CRC16) += crc16.o
obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
@@ -38,6 +41,7 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
hostprogs-y := gen_crc32table
diff --git a/lib/crc16.c b/lib/crc16.c
new file mode 100644
index 000000000000..011fe573c666
--- /dev/null
+++ b/lib/crc16.c
@@ -0,0 +1,67 @@
+/*
+ * crc16.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc16.h>
+
+/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
+u16 const crc16_table[256] = {
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+EXPORT_SYMBOL(crc16_table);
+
+/**
+ * Compute the CRC-16 for the data buffer
+ *
+ * @param crc previous CRC value
+ * @param buffer data pointer
+ * @param len number of bytes in the buffer
+ * @return the updated CRC value
+ */
+u16 crc16(u16 crc, u8 const *buffer, size_t len)
+{
+ while (len--)
+ crc = crc16_byte(crc, *buffer++);
+ return crc;
+}
+EXPORT_SYMBOL(crc16);
+
+MODULE_DESCRIPTION("CRC16 calculations");
+MODULE_LICENSE("GPL");
+
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 6658d81e1836..2377af057d09 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -25,8 +25,6 @@
* this is trivially done efficiently using a load-locked
* store-conditional approach, for example.
*/
-
-#ifndef ATOMIC_DEC_AND_LOCK
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
spin_lock(lock);
@@ -37,4 +35,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index bd2bc5d887b8..cb5490ec00f2 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -177,8 +177,7 @@ static inline void __lock_kernel(void)
static inline void __unlock_kernel(void)
{
- _raw_spin_unlock(&kernel_flag);
- preempt_enable();
+ spin_unlock(&kernel_flag);
}
/*
diff --git a/lib/klist.c b/lib/klist.c
index 738ab810160a..bb2f3551d50a 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -42,12 +42,23 @@
/**
* klist_init - Initialize a klist structure.
* @k: The klist we're initializing.
+ * @get: The get function for the embedding object (NULL if none)
+ * @put: The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure. If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
*/
-void klist_init(struct klist * k)
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *))
{
INIT_LIST_HEAD(&k->k_list);
spin_lock_init(&k->k_lock);
+ k->get = get;
+ k->put = put;
}
EXPORT_SYMBOL_GPL(klist_init);
@@ -74,16 +85,18 @@ static void klist_node_init(struct klist * k, struct klist_node * n)
init_completion(&n->n_removed);
kref_init(&n->n_ref);
n->n_klist = k;
+ if (k->get)
+ k->get(n);
}
/**
* klist_add_head - Initialize a klist_node and add it to front.
- * @k: klist it's going on.
* @n: node we're adding.
+ * @k: klist it's going on.
*/
-void klist_add_head(struct klist * k, struct klist_node * n)
+void klist_add_head(struct klist_node * n, struct klist * k)
{
klist_node_init(k, n);
add_head(k, n);
@@ -94,11 +107,11 @@ EXPORT_SYMBOL_GPL(klist_add_head);
/**
* klist_add_tail - Initialize a klist_node and add it to back.
- * @k: klist it's going on.
* @n: node we're adding.
+ * @k: klist it's going on.
*/
-void klist_add_tail(struct klist * k, struct klist_node * n)
+void klist_add_tail(struct klist_node * n, struct klist * k)
{
klist_node_init(k, n);
add_tail(k, n);
@@ -110,9 +123,12 @@ EXPORT_SYMBOL_GPL(klist_add_tail);
static void klist_release(struct kref * kref)
{
struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+ void (*put)(struct klist_node *) = n->n_klist->put;
list_del(&n->n_node);
complete(&n->n_removed);
n->n_klist = NULL;
+ if (put)
+ put(n);
}
static int klist_dec_and_del(struct klist_node * n)
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 8e49d21057e4..04ca4429ddfa 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -93,6 +93,7 @@ static int send_uevent(const char *signal, const char *obj,
}
}
+ NETLINK_CB(skb).dst_group = 1;
return netlink_broadcast(uevent_sock, skb, 0, 1, gfp_mask);
}
@@ -153,7 +154,8 @@ EXPORT_SYMBOL_GPL(kobject_uevent_atomic);
static int __init kobject_uevent_init(void)
{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, NULL);
+ uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
+ THIS_MODULE);
if (!uevent_sock) {
printk(KERN_ERR
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 10bed1c8c3c3..6a8bc6e06431 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2001 Momchil Velikov
* Portions Copyright (C) 2001 Christoph Hellwig
+ * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -51,7 +52,7 @@ struct radix_tree_node {
};
struct radix_tree_path {
- struct radix_tree_node *node, **slot;
+ struct radix_tree_node *node;
int offset;
};
@@ -109,7 +110,7 @@ radix_tree_node_free(struct radix_tree_node *node)
* success, return zero, with preemption disabled. On error, return -ENOMEM
* with preemption not disabled.
*/
-int radix_tree_preload(int gfp_mask)
+int radix_tree_preload(unsigned int __nocast gfp_mask)
{
struct radix_tree_preload *rtp;
struct radix_tree_node *node;
@@ -227,7 +228,7 @@ out:
int radix_tree_insert(struct radix_tree_root *root,
unsigned long index, void *item)
{
- struct radix_tree_node *node = NULL, *tmp, **slot;
+ struct radix_tree_node *node = NULL, *slot;
unsigned int height, shift;
int offset;
int error;
@@ -240,38 +241,42 @@ int radix_tree_insert(struct radix_tree_root *root,
return error;
}
- slot = &root->rnode;
+ slot = root->rnode;
height = root->height;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
offset = 0; /* uninitialised var warning */
while (height > 0) {
- if (*slot == NULL) {
+ if (slot == NULL) {
/* Have to add a child node. */
- if (!(tmp = radix_tree_node_alloc(root)))
+ if (!(slot = radix_tree_node_alloc(root)))
return -ENOMEM;
- *slot = tmp;
- if (node)
+ if (node) {
+ node->slots[offset] = slot;
node->count++;
+ } else
+ root->rnode = slot;
}
/* Go a level down */
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
- node = *slot;
- slot = (struct radix_tree_node **)(node->slots + offset);
+ node = slot;
+ slot = node->slots[offset];
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
- if (*slot != NULL)
+ if (slot != NULL)
return -EEXIST;
+
if (node) {
node->count++;
+ node->slots[offset] = item;
BUG_ON(tag_get(node, 0, offset));
BUG_ON(tag_get(node, 1, offset));
- }
+ } else
+ root->rnode = item;
- *slot = item;
return 0;
}
EXPORT_SYMBOL(radix_tree_insert);
@@ -286,27 +291,25 @@ EXPORT_SYMBOL(radix_tree_insert);
void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
{
unsigned int height, shift;
- struct radix_tree_node **slot;
+ struct radix_tree_node *slot;
height = root->height;
if (index > radix_tree_maxindex(height))
return NULL;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
- slot = &root->rnode;
+ slot = root->rnode;
while (height > 0) {
- if (*slot == NULL)
+ if (slot == NULL)
return NULL;
- slot = (struct radix_tree_node **)
- ((*slot)->slots +
- ((index >> shift) & RADIX_TREE_MAP_MASK));
+ slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK];
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
- return *slot;
+ return slot;
}
EXPORT_SYMBOL(radix_tree_lookup);
@@ -326,27 +329,27 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
unsigned long index, int tag)
{
unsigned int height, shift;
- struct radix_tree_node **slot;
+ struct radix_tree_node *slot;
height = root->height;
if (index > radix_tree_maxindex(height))
return NULL;
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
- slot = &root->rnode;
+ slot = root->rnode;
while (height > 0) {
int offset;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
- tag_set(*slot, tag, offset);
- slot = (struct radix_tree_node **)((*slot)->slots + offset);
- BUG_ON(*slot == NULL);
+ tag_set(slot, tag, offset);
+ slot = slot->slots[offset];
+ BUG_ON(slot == NULL);
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
- return *slot;
+ return slot;
}
EXPORT_SYMBOL(radix_tree_tag_set);
@@ -367,6 +370,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
unsigned long index, int tag)
{
struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
+ struct radix_tree_node *slot;
unsigned int height, shift;
void *ret = NULL;
@@ -376,38 +380,37 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
pathp->node = NULL;
- pathp->slot = &root->rnode;
+ slot = root->rnode;
while (height > 0) {
int offset;
- if (*pathp->slot == NULL)
+ if (slot == NULL)
goto out;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
pathp[1].offset = offset;
- pathp[1].node = *pathp[0].slot;
- pathp[1].slot = (struct radix_tree_node **)
- (pathp[1].node->slots + offset);
+ pathp[1].node = slot;
+ slot = slot->slots[offset];
pathp++;
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
- ret = *pathp[0].slot;
+ ret = slot;
if (ret == NULL)
goto out;
do {
int idx;
- tag_clear(pathp[0].node, tag, pathp[0].offset);
+ tag_clear(pathp->node, tag, pathp->offset);
for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (pathp[0].node->tags[tag][idx])
+ if (pathp->node->tags[tag][idx])
goto out;
}
pathp--;
- } while (pathp[0].node);
+ } while (pathp->node);
out:
return ret;
}
@@ -415,21 +418,22 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
#ifndef __KERNEL__ /* Only the test harness uses this at present */
/**
- * radix_tree_tag_get - get a tag on a radix tree node
- * @root: radix tree root
- * @index: index key
- * @tag: tag index
+ * radix_tree_tag_get - get a tag on a radix tree node
+ * @root: radix tree root
+ * @index: index key
+ * @tag: tag index
*
- * Return the search tag corresponging to @index in the radix tree.
+ * Return values:
*
- * Returns zero if the tag is unset, or if there is no corresponding item
- * in the tree.
+ * 0: tag not present
+ * 1: tag present, set
+ * -1: tag present, unset
*/
int radix_tree_tag_get(struct radix_tree_root *root,
unsigned long index, int tag)
{
unsigned int height, shift;
- struct radix_tree_node **slot;
+ struct radix_tree_node *slot;
int saw_unset_tag = 0;
height = root->height;
@@ -437,12 +441,12 @@ int radix_tree_tag_get(struct radix_tree_root *root,
return 0;
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
- slot = &root->rnode;
+ slot = root->rnode;
for ( ; ; ) {
int offset;
- if (*slot == NULL)
+ if (slot == NULL)
return 0;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
@@ -451,15 +455,15 @@ int radix_tree_tag_get(struct radix_tree_root *root,
* This is just a debug check. Later, we can bale as soon as
* we see an unset tag.
*/
- if (!tag_get(*slot, tag, offset))
+ if (!tag_get(slot, tag, offset))
saw_unset_tag = 1;
if (height == 1) {
- int ret = tag_get(*slot, tag, offset);
+ int ret = tag_get(slot, tag, offset);
BUG_ON(ret && saw_unset_tag);
- return ret;
+ return ret ? 1 : -1;
}
- slot = (struct radix_tree_node **)((*slot)->slots + offset);
+ slot = slot->slots[offset];
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
@@ -472,17 +476,21 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
unsigned int max_items, unsigned long *next_index)
{
unsigned int nr_found = 0;
- unsigned int shift;
- unsigned int height = root->height;
+ unsigned int shift, height;
struct radix_tree_node *slot;
+ unsigned long i;
+
+ height = root->height;
+ if (height == 0)
+ goto out;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
slot = root->rnode;
- while (height > 0) {
- unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK;
+ for ( ; height > 1; height--) {
- for ( ; i < RADIX_TREE_MAP_SIZE; i++) {
+ for (i = (index >> shift) & RADIX_TREE_MAP_MASK ;
+ i < RADIX_TREE_MAP_SIZE; i++) {
if (slot->slots[i] != NULL)
break;
index &= ~((1UL << shift) - 1);
@@ -492,22 +500,20 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
}
if (i == RADIX_TREE_MAP_SIZE)
goto out;
- height--;
- if (height == 0) { /* Bottom level: grab some items */
- unsigned long j = index & RADIX_TREE_MAP_MASK;
- for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
- index++;
- if (slot->slots[j]) {
- results[nr_found++] = slot->slots[j];
- if (nr_found == max_items)
- goto out;
- }
- }
- }
shift -= RADIX_TREE_MAP_SHIFT;
slot = slot->slots[i];
}
+
+ /* Bottom level: grab some items */
+ for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
+ index++;
+ if (slot->slots[i]) {
+ results[nr_found++] = slot->slots[i];
+ if (nr_found == max_items)
+ goto out;
+ }
+ }
out:
*next_index = index;
return nr_found;
@@ -655,6 +661,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
{
struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
struct radix_tree_path *orig_pathp;
+ struct radix_tree_node *slot;
unsigned int height, shift;
void *ret = NULL;
char tags[RADIX_TREE_TAGS];
@@ -666,25 +673,23 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
pathp->node = NULL;
- pathp->slot = &root->rnode;
+ slot = root->rnode;
- while (height > 0) {
+ for ( ; height > 0; height--) {
int offset;
- if (*pathp->slot == NULL)
+ if (slot == NULL)
goto out;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
pathp[1].offset = offset;
- pathp[1].node = *pathp[0].slot;
- pathp[1].slot = (struct radix_tree_node **)
- (pathp[1].node->slots + offset);
+ pathp[1].node = slot;
+ slot = slot->slots[offset];
pathp++;
shift -= RADIX_TREE_MAP_SHIFT;
- height--;
}
- ret = *pathp[0].slot;
+ ret = slot;
if (ret == NULL)
goto out;
@@ -704,10 +709,10 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
if (tags[tag])
continue;
- tag_clear(pathp[0].node, tag, pathp[0].offset);
+ tag_clear(pathp->node, tag, pathp->offset);
for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (pathp[0].node->tags[tag][idx]) {
+ if (pathp->node->tags[tag][idx]) {
tags[tag] = 1;
nr_cleared_tags--;
break;
@@ -715,18 +720,19 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
}
}
pathp--;
- } while (pathp[0].node && nr_cleared_tags);
+ } while (pathp->node && nr_cleared_tags);
- pathp = orig_pathp;
- *pathp[0].slot = NULL;
- while (pathp[0].node && --pathp[0].node->count == 0) {
- pathp--;
- BUG_ON(*pathp[0].slot == NULL);
- *pathp[0].slot = NULL;
- radix_tree_node_free(pathp[1].node);
+ /* Now free the nodes we do not need anymore */
+ for (pathp = orig_pathp; pathp->node; pathp--) {
+ pathp->node->slots[pathp->offset] = NULL;
+ if (--pathp->node->count)
+ goto out;
+
+ /* Node with zero slots in use so free it */
+ radix_tree_node_free(pathp->node);
}
- if (root->rnode == NULL)
- root->height = 0;
+ root->rnode = NULL;
+ root->height = 0;
out:
return ret;
}
diff --git a/arch/x86_64/kernel/semaphore.c b/lib/semaphore-sleepers.c
index 48f7c18172b9..4d5f18889fa5 100644
--- a/arch/x86_64/kernel/semaphore.c
+++ b/lib/semaphore-sleepers.c
@@ -1,5 +1,5 @@
/*
- * x86_64 semaphore implementation.
+ * i386 and x86-64 semaphore implementation.
*
* (C) Copyright 1999 Linus Torvalds
*
@@ -14,9 +14,8 @@
*/
#include <linux/config.h>
#include <linux/sched.h>
+#include <linux/err.h>
#include <linux/init.h>
-#include <asm/errno.h>
-
#include <asm/semaphore.h>
/*
@@ -50,12 +49,12 @@
* we cannot lose wakeup events.
*/
-void __up(struct semaphore *sem)
+fastcall void __up(struct semaphore *sem)
{
wake_up(&sem->wait);
}
-void __sched __down(struct semaphore * sem)
+fastcall void __sched __down(struct semaphore * sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
@@ -92,7 +91,7 @@ void __sched __down(struct semaphore * sem)
tsk->state = TASK_RUNNING;
}
-int __sched __down_interruptible(struct semaphore * sem)
+fastcall int __sched __down_interruptible(struct semaphore * sem)
{
int retval = 0;
struct task_struct *tsk = current;
@@ -155,7 +154,7 @@ int __sched __down_interruptible(struct semaphore * sem)
* single "cmpxchg" without failure cases,
* but then it wouldn't work on a 386.
*/
-int __down_trylock(struct semaphore * sem)
+fastcall int __down_trylock(struct semaphore * sem)
{
int sleepers;
unsigned long flags;
@@ -176,5 +175,3 @@ int __down_trylock(struct semaphore * sem)
spin_unlock_irqrestore(&sem->wait.lock, flags);
return 1;
}
-
-
diff --git a/lib/sort.c b/lib/sort.c
index b73dbb0e7c83..ddc4d35df289 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -6,15 +6,16 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/sort.h>
-void u32_swap(void *a, void *b, int size)
+static void u32_swap(void *a, void *b, int size)
{
u32 t = *(u32 *)a;
*(u32 *)a = *(u32 *)b;
*(u32 *)b = t;
}
-void generic_swap(void *a, void *b, int size)
+static void generic_swap(void *a, void *b, int size)
{
char t;
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
new file mode 100644
index 000000000000..906ad101eab3
--- /dev/null
+++ b/lib/spinlock_debug.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the spinlock/rwlock implementations for
+ * DEBUG_SPINLOCK.
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+static void spin_bug(spinlock_t *lock, const char *msg)
+{
+ static long print_once = 1;
+ struct task_struct *owner = NULL;
+
+ if (xchg(&print_once, 0)) {
+ if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
+ owner = lock->owner;
+ printk("BUG: spinlock %s on CPU#%d, %s/%d\n",
+ msg, smp_processor_id(), current->comm, current->pid);
+ printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n",
+ lock, lock->magic,
+ owner ? owner->comm : "<none>",
+ owner ? owner->pid : -1,
+ lock->owner_cpu);
+ dump_stack();
+#ifdef CONFIG_SMP
+ /*
+ * We cannot continue on SMP:
+ */
+// panic("bad locking");
+#endif
+ }
+}
+
+#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
+
+static inline void debug_spin_lock_before(spinlock_t *lock)
+{
+ SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+ SPIN_BUG_ON(lock->owner == current, lock, "recursion");
+ SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+ lock, "cpu recursion");
+}
+
+static inline void debug_spin_lock_after(spinlock_t *lock)
+{
+ lock->owner_cpu = raw_smp_processor_id();
+ lock->owner = current;
+}
+
+static inline void debug_spin_unlock(spinlock_t *lock)
+{
+ SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+ SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked");
+ SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
+ SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+ lock, "wrong CPU");
+ lock->owner = SPINLOCK_OWNER_INIT;
+ lock->owner_cpu = -1;
+}
+
+static void __spin_lock_debug(spinlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_spin_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_spin_lock(spinlock_t *lock)
+{
+ debug_spin_lock_before(lock);
+ if (unlikely(!__raw_spin_trylock(&lock->raw_lock)))
+ __spin_lock_debug(lock);
+ debug_spin_lock_after(lock);
+}
+
+int _raw_spin_trylock(spinlock_t *lock)
+{
+ int ret = __raw_spin_trylock(&lock->raw_lock);
+
+ if (ret)
+ debug_spin_lock_after(lock);
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_spin_unlock(spinlock_t *lock)
+{
+ debug_spin_unlock(lock);
+ __raw_spin_unlock(&lock->raw_lock);
+}
+
+static void rwlock_bug(rwlock_t *lock, const char *msg)
+{
+ static long print_once = 1;
+
+ if (xchg(&print_once, 0)) {
+ printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg,
+ smp_processor_id(), current->comm, current->pid, lock);
+ dump_stack();
+#ifdef CONFIG_SMP
+ /*
+ * We cannot continue on SMP:
+ */
+ panic("bad locking");
+#endif
+ }
+}
+
+#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
+
+static void __read_lock_debug(rwlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_read_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_read_lock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
+ __read_lock_debug(lock);
+}
+
+int _raw_read_trylock(rwlock_t *lock)
+{
+ int ret = __raw_read_trylock(&lock->raw_lock);
+
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_read_unlock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ __raw_read_unlock(&lock->raw_lock);
+}
+
+static inline void debug_write_lock_before(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
+ RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+ lock, "cpu recursion");
+}
+
+static inline void debug_write_lock_after(rwlock_t *lock)
+{
+ lock->owner_cpu = raw_smp_processor_id();
+ lock->owner = current;
+}
+
+static inline void debug_write_unlock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
+ RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+ lock, "wrong CPU");
+ lock->owner = SPINLOCK_OWNER_INIT;
+ lock->owner_cpu = -1;
+}
+
+static void __write_lock_debug(rwlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_write_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_write_lock(rwlock_t *lock)
+{
+ debug_write_lock_before(lock);
+ if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
+ __write_lock_debug(lock);
+ debug_write_lock_after(lock);
+}
+
+int _raw_write_trylock(rwlock_t *lock)
+{
+ int ret = __raw_write_trylock(&lock->raw_lock);
+
+ if (ret)
+ debug_write_lock_after(lock);
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_write_unlock(rwlock_t *lock)
+{
+ debug_write_unlock(lock);
+ __raw_write_unlock(&lock->raw_lock);
+}
diff --git a/lib/ts_bm.c b/lib/ts_bm.c
new file mode 100644
index 000000000000..2cc79112ecc3
--- /dev/null
+++ b/lib/ts_bm.c
@@ -0,0 +1,185 @@
+/*
+ * lib/ts_bm.c Boyer-Moore text search implementation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Pablo Neira Ayuso <pablo@eurodev.net>
+ *
+ * ==========================================================================
+ *
+ * Implements Boyer-Moore string matching algorithm:
+ *
+ * [1] A Fast String Searching Algorithm, R.S. Boyer and Moore.
+ * Communications of the Association for Computing Machinery,
+ * 20(10), 1977, pp. 762-772.
+ * http://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf
+ *
+ * [2] Handbook of Exact String Matching Algorithms, Thierry Lecroq, 2004
+ * http://www-igm.univ-mlv.fr/~lecroq/string/string.pdf
+ *
+ * Note: Since Boyer-Moore (BM) performs searches for matchings from right
+ * to left, it's still possible that a matching could be spread over
+ * multiple blocks, in that case this algorithm won't find any coincidence.
+ *
+ * If you're willing to ensure that such thing won't ever happen, use the
+ * Knuth-Pratt-Morris (KMP) implementation instead. In conclusion, choose
+ * the proper string search algorithm depending on your setting.
+ *
+ * Say you're using the textsearch infrastructure for filtering, NIDS or
+ * any similar security focused purpose, then go KMP. Otherwise, if you
+ * really care about performance, say you're classifying packets to apply
+ * Quality of Service (QoS) policies, and you don't mind about possible
+ * matchings spread over multiple fragments, then go BM.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/textsearch.h>
+
+/* Alphabet size, use ASCII */
+#define ASIZE 256
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(args, format...)
+#endif
+
+struct ts_bm
+{
+ u8 * pattern;
+ unsigned int patlen;
+ unsigned int bad_shift[ASIZE];
+ unsigned int good_shift[0];
+};
+
+static unsigned int bm_find(struct ts_config *conf, struct ts_state *state)
+{
+ struct ts_bm *bm = ts_config_priv(conf);
+ unsigned int i, text_len, consumed = state->offset;
+ const u8 *text;
+ int shift = bm->patlen, bs;
+
+ for (;;) {
+ text_len = conf->get_next_block(consumed, &text, conf, state);
+
+ if (unlikely(text_len == 0))
+ break;
+
+ while (shift < text_len) {
+ DEBUGP("Searching in position %d (%c)\n",
+ shift, text[shift]);
+ for (i = 0; i < bm->patlen; i++)
+ if (text[shift-i] != bm->pattern[bm->patlen-1-i])
+ goto next;
+
+ /* London calling... */
+ DEBUGP("found!\n");
+ return consumed += (shift-(bm->patlen-1));
+
+next: bs = bm->bad_shift[text[shift-i]];
+
+ /* Now jumping to... */
+ shift = max_t(int, shift-i+bs, shift+bm->good_shift[i]);
+ }
+ consumed += text_len;
+ }
+
+ return UINT_MAX;
+}
+
+static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern,
+ unsigned int len)
+{
+ int i, j, ended, l[ASIZE];
+
+ for (i = 0; i < ASIZE; i++)
+ bm->bad_shift[i] = len;
+ for (i = 0; i < len - 1; i++)
+ bm->bad_shift[pattern[i]] = len - 1 - i;
+
+ /* Compute the good shift array, used to match reocurrences
+ * of a subpattern */
+ for (i = 1; i < bm->patlen; i++) {
+ for (j = 0; j < bm->patlen && bm->pattern[bm->patlen - 1 - j]
+ == bm->pattern[bm->patlen - 1 - i - j]; j++);
+ l[i] = j;
+ }
+
+ bm->good_shift[0] = 1;
+ for (i = 1; i < bm->patlen; i++)
+ bm->good_shift[i] = bm->patlen;
+ for (i = bm->patlen - 1; i > 0; i--)
+ bm->good_shift[l[i]] = i;
+ ended = 0;
+ for (i = 0; i < bm->patlen; i++) {
+ if (l[i] == bm->patlen - 1 - i)
+ ended = i;
+ if (ended)
+ bm->good_shift[i] = ended;
+ }
+}
+
+static struct ts_config *bm_init(const void *pattern, unsigned int len,
+ int gfp_mask)
+{
+ struct ts_config *conf;
+ struct ts_bm *bm;
+ unsigned int prefix_tbl_len = len * sizeof(unsigned int);
+ size_t priv_size = sizeof(*bm) + len + prefix_tbl_len;
+
+ conf = alloc_ts_config(priv_size, gfp_mask);
+ if (IS_ERR(conf))
+ return conf;
+
+ bm = ts_config_priv(conf);
+ bm->patlen = len;
+ bm->pattern = (u8 *) bm->good_shift + prefix_tbl_len;
+ compute_prefix_tbl(bm, pattern, len);
+ memcpy(bm->pattern, pattern, len);
+
+ return conf;
+}
+
+static void *bm_get_pattern(struct ts_config *conf)
+{
+ struct ts_bm *bm = ts_config_priv(conf);
+ return bm->pattern;
+}
+
+static unsigned int bm_get_pattern_len(struct ts_config *conf)
+{
+ struct ts_bm *bm = ts_config_priv(conf);
+ return bm->patlen;
+}
+
+static struct ts_ops bm_ops = {
+ .name = "bm",
+ .find = bm_find,
+ .init = bm_init,
+ .get_pattern = bm_get_pattern,
+ .get_pattern_len = bm_get_pattern_len,
+ .owner = THIS_MODULE,
+ .list = LIST_HEAD_INIT(bm_ops.list)
+};
+
+static int __init init_bm(void)
+{
+ return textsearch_register(&bm_ops);
+}
+
+static void __exit exit_bm(void)
+{
+ textsearch_unregister(&bm_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_bm);
+module_exit(exit_bm);
diff --git a/mm/Kconfig b/mm/Kconfig
index cd379936cac6..4e9937ac3529 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -89,3 +89,25 @@ config NEED_MULTIPLE_NODES
config HAVE_MEMORY_PRESENT
def_bool y
depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM
+
+#
+# SPARSEMEM_EXTREME (which is the default) does some bootmem
+# allocations when memory_present() is called. If this can not
+# be done on your architecture, select this option. However,
+# statically allocating the mem_section[] array can potentially
+# consume vast quantities of .bss, so be careful.
+#
+# This option will also potentially produce smaller runtime code
+# with gcc 3.4 and later.
+#
+config SPARSEMEM_STATIC
+ def_bool n
+
+#
+# Architectecture platforms which require a two level mem_section in SPARSEMEM
+# must select this option. This is usually for architecture platforms with
+# an extremely sparse physical address space.
+#
+config SPARSEMEM_EXTREME
+ def_bool y
+ depends on SPARSEMEM && !SPARSEMEM_STATIC
diff --git a/mm/bootmem.c b/mm/bootmem.c
index c1330cc19783..8ec4e4c2a179 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -61,9 +61,17 @@ 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;
+ static struct pglist_data *pgdat_last;
+
+ pgdat->pgdat_next = NULL;
+ /* Add new nodes last so that bootmem always starts
+ searching in the first nodes, not the last ones */
+ if (pgdat_last)
+ pgdat_last->pgdat_next = pgdat;
+ else {
+ pgdat_list = pgdat;
+ pgdat_last = pgdat;
+ }
mapsize = ALIGN(mapsize, sizeof(long));
bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
diff --git a/mm/filemap.c b/mm/filemap.c
index c11418dd94e8..b5346576e58d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -37,6 +37,10 @@
#include <asm/uaccess.h>
#include <asm/mman.h>
+static ssize_t
+generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+
/*
* Shared mappings implemented 30.11.1994. It's not fully working yet,
* though.
@@ -54,9 +58,8 @@
*
* ->i_mmap_lock (vmtruncate)
* ->private_lock (__free_pte->__set_page_dirty_buffers)
- * ->swap_list_lock
- * ->swap_device_lock (exclusive_swap_page, others)
- * ->mapping->tree_lock
+ * ->swap_lock (exclusive_swap_page, others)
+ * ->mapping->tree_lock
*
* ->i_sem
* ->i_mmap_lock (truncate->unmap_mapping_range)
@@ -86,7 +89,7 @@
* ->page_table_lock (anon_vma_prepare and various)
*
* ->page_table_lock
- * ->swap_device_lock (try_to_unmap_one)
+ * ->swap_lock (try_to_unmap_one)
* ->private_lock (try_to_unmap_one)
* ->tree_lock (try_to_unmap_one)
* ->zone.lru_lock (follow_page->mark_page_accessed)
@@ -302,8 +305,9 @@ EXPORT_SYMBOL(sync_page_range);
* as it forces O_SYNC writers to different parts of the same file
* to be serialised right until io completion.
*/
-int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
- loff_t pos, size_t count)
+static int sync_page_range_nolock(struct inode *inode,
+ struct address_space *mapping,
+ loff_t pos, size_t count)
{
pgoff_t start = pos >> PAGE_CACHE_SHIFT;
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
@@ -318,7 +322,6 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
ret = wait_on_page_writeback_range(mapping, start, end);
return ret;
}
-EXPORT_SYMBOL(sync_page_range_nolock);
/**
* filemap_fdatawait - walk the list of under-writeback pages of the given
@@ -1505,8 +1508,12 @@ repeat:
return -EINVAL;
page = filemap_getpage(file, pgoff, nonblock);
+
+ /* XXX: This is wrong, a filesystem I/O error may have happened. Fix that as
+ * done in shmem_populate calling shmem_getpage */
if (!page && !nonblock)
return -ENOMEM;
+
if (page) {
err = install_page(mm, vma, addr, page, prot);
if (err) {
@@ -1514,6 +1521,9 @@ repeat:
return err;
}
} else {
+ /* No page was found just because we can't read it in now (being
+ * here implies nonblock != 0), but the page may exist, so set
+ * the PTE to fault it in later. */
err = install_file_pte(mm, vma, addr, pgoff, prot);
if (err)
return err;
@@ -2002,7 +2012,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
}
EXPORT_SYMBOL(generic_file_buffered_write);
-ssize_t
+static ssize_t
__generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos)
{
@@ -2102,7 +2112,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
return ret;
}
-ssize_t
+static ssize_t
__generic_file_write_nolock(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos)
{
@@ -2223,7 +2233,7 @@ EXPORT_SYMBOL(generic_file_writev);
* Called under i_sem for writes to S_ISREG files. Returns -EIO if something
* went wrong during pagecache shootdown.
*/
-ssize_t
+static ssize_t
generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
loff_t offset, unsigned long nr_segs)
{
@@ -2258,4 +2268,3 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
}
return retval;
}
-EXPORT_SYMBOL_GPL(generic_file_direct_IO);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 6bf720bc662c..901ac523a1c3 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -360,8 +360,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
ret = -ENOMEM;
goto out;
}
- if (! pte_none(*pte))
- hugetlb_clean_stale_pgtable(pte);
idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
diff --git a/mm/madvise.c b/mm/madvise.c
index c8c01a12fea4..4454936f87d1 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -37,7 +37,7 @@ static long madvise_behavior(struct vm_area_struct * vma,
if (new_flags == vma->vm_flags) {
*prev = vma;
- goto success;
+ goto out;
}
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
@@ -62,6 +62,7 @@ static long madvise_behavior(struct vm_area_struct * vma,
goto out;
}
+success:
/*
* vm_flags is protected by the mmap_sem held in write mode.
*/
@@ -70,7 +71,6 @@ static long madvise_behavior(struct vm_area_struct * vma,
out:
if (error == -ENOMEM)
error = -EAGAIN;
-success:
return error;
}
@@ -237,8 +237,9 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
* - different from the way of handling in mlock etc.
*/
vma = find_vma_prev(current->mm, start, &prev);
- if (!vma && prev)
- vma = prev->vm_next;
+ if (vma && start > vma->vm_start)
+ prev = vma;
+
for (;;) {
/* Still start < end. */
error = -ENOMEM;
diff --git a/mm/memory.c b/mm/memory.c
index e046b7e4b530..ae8161f1f459 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -498,6 +498,17 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
unsigned long addr = vma->vm_start;
unsigned long end = vma->vm_end;
+ /*
+ * Don't copy ptes where a page fault will fill them correctly.
+ * Fork becomes much lighter when there are big shared or private
+ * readonly mappings. The tradeoff is that copy_page_range is more
+ * efficient than faulting.
+ */
+ if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_RESERVED))) {
+ if (!vma->anon_vma)
+ return 0;
+ }
+
if (is_vm_hugetlb_page(vma))
return copy_hugetlb_page_range(dst_mm, src_mm, vma);
@@ -551,7 +562,8 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
page->index > details->last_index))
continue;
}
- ptent = ptep_get_and_clear(tlb->mm, addr, pte);
+ ptent = ptep_get_and_clear_full(tlb->mm, addr, pte,
+ tlb->fullmm);
tlb_remove_tlb_entry(tlb, pte, addr);
if (unlikely(!page))
continue;
@@ -579,7 +591,7 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
continue;
if (!pte_file(ptent))
free_swap_and_cache(pte_to_swp_entry(ptent));
- pte_clear(tlb->mm, addr, pte);
+ pte_clear_full(tlb->mm, addr, pte, tlb->fullmm);
} while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap(pte - 1);
}
@@ -1944,7 +1956,7 @@ static int do_file_page(struct mm_struct * mm, struct vm_area_struct * vma,
* Fall back to the linear mapping if the fs does not support
* ->populate:
*/
- if (!vma->vm_ops || !vma->vm_ops->populate ||
+ if (!vma->vm_ops->populate ||
(write_access && !(vma->vm_flags & VM_SHARED))) {
pte_clear(mm, address, pte);
return do_no_page(mm, vma, address, write_access, pte, pmd);
@@ -2213,7 +2225,7 @@ void update_mem_hiwater(struct task_struct *tsk)
#if !defined(__HAVE_ARCH_GATE_AREA)
#if defined(AT_SYSINFO_EHDR)
-struct vm_area_struct gate_vma;
+static struct vm_area_struct gate_vma;
static int __init gate_vma_init(void)
{
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index b4eababc8198..9033f0859aa8 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -88,7 +88,7 @@ static kmem_cache_t *sn_cache;
policied. */
static int policy_zone;
-static struct mempolicy default_policy = {
+struct mempolicy default_policy = {
.refcnt = ATOMIC_INIT(1), /* never free it */
.policy = MPOL_DEFAULT,
};
@@ -333,8 +333,13 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
if (prev && prev->vm_end < vma->vm_start)
return ERR_PTR(-EFAULT);
if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
+ unsigned long endvma = vma->vm_end;
+ if (endvma > end)
+ endvma = end;
+ if (vma->vm_start > start)
+ start = vma->vm_start;
err = check_pgd_range(vma->vm_mm,
- vma->vm_start, vma->vm_end, nodes);
+ start, endvma, nodes);
if (err) {
first = ERR_PTR(err);
break;
@@ -664,10 +669,10 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
#endif
/* Return effective policy for a VMA */
-static struct mempolicy *
-get_vma_policy(struct vm_area_struct *vma, unsigned long addr)
+struct mempolicy *
+get_vma_policy(struct task_struct *task, struct vm_area_struct *vma, unsigned long addr)
{
- struct mempolicy *pol = current->mempolicy;
+ struct mempolicy *pol = task->mempolicy;
if (vma) {
if (vma->vm_ops && vma->vm_ops->get_policy)
@@ -786,7 +791,7 @@ static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned or
struct page *
alloc_page_vma(unsigned int __nocast gfp, struct vm_area_struct *vma, unsigned long addr)
{
- struct mempolicy *pol = get_vma_policy(vma, addr);
+ struct mempolicy *pol = get_vma_policy(current, vma, addr);
cpuset_update_current_mems_allowed();
@@ -908,7 +913,7 @@ void __mpol_free(struct mempolicy *p)
/* Find first node suitable for an allocation */
int mpol_first_node(struct vm_area_struct *vma, unsigned long addr)
{
- struct mempolicy *pol = get_vma_policy(vma, addr);
+ struct mempolicy *pol = get_vma_policy(current, vma, addr);
switch (pol->policy) {
case MPOL_DEFAULT:
@@ -928,7 +933,7 @@ int mpol_first_node(struct vm_area_struct *vma, unsigned long addr)
/* Find secondary valid nodes for an allocation */
int mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long addr)
{
- struct mempolicy *pol = get_vma_policy(vma, addr);
+ struct mempolicy *pol = get_vma_policy(current, vma, addr);
switch (pol->policy) {
case MPOL_PREFERRED:
diff --git a/mm/mmap.c b/mm/mmap.c
index 404319477e71..12334aecf8ad 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -61,7 +61,7 @@ pgprot_t protection_map[16] = {
int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
-int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
+int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
atomic_t vm_committed_space = ATOMIC_INIT(0);
/*
@@ -203,13 +203,6 @@ static void remove_vm_struct(struct vm_area_struct *vma)
kmem_cache_free(vm_area_cachep, vma);
}
-/*
- * sys_brk() for the most part doesn't need the global kernel
- * lock, except when an application is doing something nasty
- * like trying to un-brk an area that has already been mapped
- * to a regular file. in this case, the unmapping will need
- * to invoke file system routines that need the global lock.
- */
asmlinkage unsigned long sys_brk(unsigned long brk)
{
unsigned long rlim, retval;
diff --git a/mm/mremap.c b/mm/mremap.c
index fc45dc9a617b..a32fed454bd7 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -141,6 +141,10 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
if (dst) {
pte_t pte;
pte = ptep_clear_flush(vma, old_addr, src);
+ /* ZERO_PAGE can be dependant on virtual addr */
+ if (pfn_valid(pte_pfn(pte)) &&
+ pte_page(pte) == ZERO_PAGE(old_addr))
+ pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot));
set_pte_at(mm, new_addr, dst, pte);
} else
error = -ENOMEM;
diff --git a/mm/nommu.c b/mm/nommu.c
index fd4e8df0f02d..064d70442895 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -57,6 +57,11 @@ DECLARE_RWSEM(nommu_vma_sem);
struct vm_operations_struct generic_file_vm_ops = {
};
+EXPORT_SYMBOL(vmalloc);
+EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_32);
+
/*
* Handle all mappings that got truncated by a "truncate()"
* system call.
@@ -142,6 +147,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
return(i);
}
+EXPORT_SYMBOL(get_user_pages);
+
DEFINE_RWLOCK(vmlist_lock);
struct vm_struct *vmlist;
@@ -852,7 +859,7 @@ unsigned long do_mmap_pgoff(struct file *file,
error_getting_vma:
up_write(&nommu_vma_sem);
kfree(vml);
- printk("Allocation of vml for %lu byte allocation from process %d failed\n",
+ printk("Allocation of vma for %lu byte allocation from process %d failed\n",
len, current->pid);
show_free_areas();
return -ENOMEM;
@@ -909,7 +916,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
if ((*parent)->vma->vm_start == addr &&
- (*parent)->vma->vm_end == end)
+ ((len == 0) || ((*parent)->vma->vm_end == end)))
goto found;
printk("munmap of non-mmaped memory by process %d (%s): %p\n",
@@ -1054,7 +1061,8 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long to, unsigned long size, pgprot_t prot)
{
- return -EPERM;
+ vma->vm_start = vma->vm_pgoff << PAGE_SHIFT;
+ return 0;
}
void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -1073,9 +1081,10 @@ void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
void update_mem_hiwater(struct task_struct *tsk)
{
- unsigned long rss = get_mm_counter(tsk->mm, rss);
+ unsigned long rss;
if (likely(tsk->mm)) {
+ rss = get_mm_counter(tsk->mm, rss);
if (tsk->mm->hiwater_rss < rss)
tsk->mm->hiwater_rss = rss;
if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 1e56076672f5..ac3bf33e5370 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -6,8 +6,8 @@
* for goading me into coding this file...
*
* The routines in this file are used to kill a process when
- * we're seriously out of memory. This gets called from kswapd()
- * in linux/mm/vmscan.c when we really run out of memory.
+ * we're seriously out of memory. This gets called from __alloc_pages()
+ * in mm/page_alloc.c when we really run out of memory.
*
* Since we won't call these routines often (on a well-configured
* machine) this file will double as a 'coding guide' and a signpost
@@ -20,13 +20,14 @@
#include <linux/swap.h>
#include <linux/timex.h>
#include <linux/jiffies.h>
+#include <linux/cpuset.h>
/* #define DEBUG */
/**
* oom_badness - calculate a numeric value for how bad this task has been
* @p: task struct of which task we should calculate
- * @p: current uptime in seconds
+ * @uptime: current uptime in seconds
*
* The formula used is relatively simple and documented inline in the
* function. The main rationale is that we want to select a good task
@@ -57,9 +58,9 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
/*
* Processes which fork a lot of child processes are likely
- * a good choice. We add the vmsize of the childs if they
+ * a good choice. We add the vmsize of the children if they
* have an own mm. This prevents forking servers to flood the
- * machine with an endless amount of childs
+ * machine with an endless amount of children
*/
list_for_each(tsk, &p->children) {
struct task_struct *chld;
@@ -143,28 +144,36 @@ static struct task_struct * select_bad_process(void)
struct timespec uptime;
do_posix_clock_monotonic_gettime(&uptime);
- do_each_thread(g, p)
+ do_each_thread(g, p) {
+ unsigned long points;
+ int releasing;
+
/* skip the init task with pid == 1 */
- if (p->pid > 1 && p->oomkilladj != OOM_DISABLE) {
- unsigned long points;
-
- /*
- * This is in the process of releasing memory so wait it
- * to finish before killing some other task by mistake.
- */
- if ((unlikely(test_tsk_thread_flag(p, TIF_MEMDIE)) || (p->flags & PF_EXITING)) &&
- !(p->flags & PF_DEAD))
- return ERR_PTR(-1UL);
- if (p->flags & PF_SWAPOFF)
- return p;
-
- points = badness(p, uptime.tv_sec);
- if (points > maxpoints || !chosen) {
- chosen = p;
- maxpoints = points;
- }
+ if (p->pid == 1)
+ continue;
+ if (p->oomkilladj == OOM_DISABLE)
+ continue;
+ /* If p's nodes don't overlap ours, it won't help to kill p. */
+ if (!cpuset_excl_nodes_overlap(p))
+ continue;
+
+ /*
+ * This is in the process of releasing memory so for wait it
+ * to finish before killing some other task by mistake.
+ */
+ releasing = test_tsk_thread_flag(p, TIF_MEMDIE) ||
+ p->flags & PF_EXITING;
+ if (releasing && !(p->flags & PF_DEAD))
+ return ERR_PTR(-1UL);
+ if (p->flags & PF_SWAPOFF)
+ return p;
+
+ points = badness(p, uptime.tv_sec);
+ if (points > maxpoints || !chosen) {
+ chosen = p;
+ maxpoints = points;
}
- while_each_thread(g, p);
+ } while_each_thread(g, p);
return chosen;
}
@@ -189,7 +198,8 @@ static void __oom_kill_task(task_t *p)
return;
}
task_unlock(p);
- printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
+ printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n",
+ p->pid, p->comm);
/*
* We give our sacrificial lamb high priority and access to
@@ -290,6 +300,5 @@ retry:
* Give "p" a good chance of killing itself before we
* retry to allocate memory.
*/
- __set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index a6329fa8f862..0166ea15c9ee 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -368,10 +368,8 @@ int wakeup_pdflush(long nr_pages)
static void wb_timer_fn(unsigned long unused);
static void laptop_timer_fn(unsigned long unused);
-static struct timer_list wb_timer =
- TIMER_INITIALIZER(wb_timer_fn, 0, 0);
-static struct timer_list laptop_mode_wb_timer =
- TIMER_INITIALIZER(laptop_timer_fn, 0, 0);
+static DEFINE_TIMER(wb_timer, wb_timer_fn, 0, 0);
+static DEFINE_TIMER(laptop_mode_wb_timer, laptop_timer_fn, 0, 0);
/*
* Periodic writeback of "old" data.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8d088371196a..ae2903339e71 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -22,6 +22,7 @@
#include <linux/pagemap.h>
#include <linux/bootmem.h>
#include <linux/compiler.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/suspend.h>
#include <linux/pagevec.h>
@@ -42,13 +43,13 @@
* MCD - HACK: Find somewhere to initialize this EARLY, or make this
* initializer cleaner
*/
-nodemask_t node_online_map = { { [0] = 1UL } };
+nodemask_t node_online_map __read_mostly = { { [0] = 1UL } };
EXPORT_SYMBOL(node_online_map);
-nodemask_t node_possible_map = NODE_MASK_ALL;
+nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
EXPORT_SYMBOL(node_possible_map);
-struct pglist_data *pgdat_list;
-unsigned long totalram_pages;
-unsigned long totalhigh_pages;
+struct pglist_data *pgdat_list __read_mostly;
+unsigned long totalram_pages __read_mostly;
+unsigned long totalhigh_pages __read_mostly;
long nr_swap_pages;
/*
@@ -68,7 +69,7 @@ EXPORT_SYMBOL(nr_swap_pages);
* Used by page_zone() to look up the address of the struct zone whose
* id is encoded in the upper bits of page->flags
*/
-struct zone *zone_table[1 << ZONETABLE_SHIFT];
+struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly;
EXPORT_SYMBOL(zone_table);
static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
@@ -117,7 +118,7 @@ static void bad_page(const char *function, struct page *page)
set_page_count(page, 0);
reset_page_mapcount(page);
page->mapping = NULL;
- tainted |= TAINT_BAD_PAGE;
+ add_taint(TAINT_BAD_PAGE);
}
#ifndef CONFIG_HUGETLB_PAGE
@@ -329,13 +330,13 @@ static inline void free_pages_check(const char *function, struct page *page)
1 << PG_writeback )))
bad_page(function, page);
if (PageDirty(page))
- ClearPageDirty(page);
+ __ClearPageDirty(page);
}
/*
* Frees a list of pages.
* Assumes all pages on list are in same zone, and of same order.
- * count is the number of pages to free, or 0 for all on the list.
+ * count is the number of pages to free.
*
* If the zone was previously in an "all pages pinned" state then look to
* see if this freeing clears that state.
@@ -806,11 +807,14 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
classzone_idx = zone_idx(zones[0]);
restart:
- /* Go through the zonelist once, looking for a zone with enough free */
+ /*
+ * Go through the zonelist once, looking for a zone with enough free.
+ * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
+ */
for (i = 0; (z = zones[i]) != NULL; i++) {
int do_reclaim = should_reclaim_zone(z, gfp_mask);
- if (!cpuset_zone_allowed(z))
+ if (!cpuset_zone_allowed(z, __GFP_HARDWALL))
continue;
/*
@@ -845,6 +849,7 @@ zone_reclaim_retry:
*
* This is the last chance, in general, before the goto nopage.
* Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
+ * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
*/
for (i = 0; (z = zones[i]) != NULL; i++) {
if (!zone_watermark_ok(z, order, z->pages_min,
@@ -852,7 +857,7 @@ zone_reclaim_retry:
gfp_mask & __GFP_HIGH))
continue;
- if (wait && !cpuset_zone_allowed(z))
+ if (wait && !cpuset_zone_allowed(z, gfp_mask))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
@@ -867,7 +872,7 @@ zone_reclaim_retry:
if (!(gfp_mask & __GFP_NOMEMALLOC)) {
/* go through the zonelist yet again, ignoring mins */
for (i = 0; (z = zones[i]) != NULL; i++) {
- if (!cpuset_zone_allowed(z))
+ if (!cpuset_zone_allowed(z, gfp_mask))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
@@ -903,7 +908,7 @@ rebalance:
gfp_mask & __GFP_HIGH))
continue;
- if (!cpuset_zone_allowed(z))
+ if (!cpuset_zone_allowed(z, gfp_mask))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
@@ -922,7 +927,7 @@ rebalance:
classzone_idx, 0, 0))
continue;
- if (!cpuset_zone_allowed(z))
+ if (!cpuset_zone_allowed(z, __GFP_HARDWALL))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
@@ -1130,19 +1135,20 @@ EXPORT_SYMBOL(nr_pagecache);
DEFINE_PER_CPU(long, nr_pagecache_local) = 0;
#endif
-void __get_page_state(struct page_state *ret, int nr)
+void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask)
{
int cpu = 0;
memset(ret, 0, sizeof(*ret));
+ cpus_and(*cpumask, *cpumask, cpu_online_map);
- cpu = first_cpu(cpu_online_map);
+ cpu = first_cpu(*cpumask);
while (cpu < NR_CPUS) {
unsigned long *in, *out, off;
in = (unsigned long *)&per_cpu(page_states, cpu);
- cpu = next_cpu(cpu, cpu_online_map);
+ cpu = next_cpu(cpu, *cpumask);
if (cpu < NR_CPUS)
prefetch(&per_cpu(page_states, cpu));
@@ -1153,19 +1159,33 @@ void __get_page_state(struct page_state *ret, int nr)
}
}
+void get_page_state_node(struct page_state *ret, int node)
+{
+ int nr;
+ cpumask_t mask = node_to_cpumask(node);
+
+ nr = offsetof(struct page_state, GET_PAGE_STATE_LAST);
+ nr /= sizeof(unsigned long);
+
+ __get_page_state(ret, nr+1, &mask);
+}
+
void get_page_state(struct page_state *ret)
{
int nr;
+ cpumask_t mask = CPU_MASK_ALL;
nr = offsetof(struct page_state, GET_PAGE_STATE_LAST);
nr /= sizeof(unsigned long);
- __get_page_state(ret, nr + 1);
+ __get_page_state(ret, nr + 1, &mask);
}
void get_full_page_state(struct page_state *ret)
{
- __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
+ cpumask_t mask = CPU_MASK_ALL;
+
+ __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask);
}
unsigned long __read_page_state(unsigned long offset)
@@ -1909,7 +1929,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
zone->nr_scan_inactive = 0;
zone->nr_active = 0;
zone->nr_inactive = 0;
- atomic_set(&zone->reclaim_in_progress, -1);
+ atomic_set(&zone->reclaim_in_progress, 0);
if (!size)
continue;
diff --git a/mm/readahead.c b/mm/readahead.c
index b840e7c6ea74..d0b50034e245 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -540,6 +540,7 @@ void handle_ra_miss(struct address_space *mapping,
{
ra->flags |= RA_FLAG_MISS;
ra->flags &= ~RA_FLAG_INCACHE;
+ ra->cache_hit = 0;
}
/*
diff --git a/mm/rmap.c b/mm/rmap.c
index 08ac5c7fa91f..450f5241b5a5 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -34,9 +34,8 @@
* anon_vma->lock
* mm->page_table_lock
* zone->lru_lock (in mark_page_accessed)
- * swap_list_lock (in swap_free etc's swap_info_get)
+ * swap_lock (in swap_duplicate, swap_info_get)
* mmlist_lock (in mmput, drain_mmlist and others)
- * swap_device_lock (in swap_duplicate, swap_info_get)
* mapping->private_lock (in __set_page_dirty_buffers)
* inode_lock (in set_page_dirty's __mark_inode_dirty)
* sb_lock (within inode_lock in fs/fs-writeback.c)
@@ -290,8 +289,6 @@ static int page_referenced_one(struct page *page,
pte_t *pte;
int referenced = 0;
- if (!get_mm_counter(mm, rss))
- goto out;
address = vma_address(page, vma);
if (address == -EFAULT)
goto out;
@@ -442,22 +439,19 @@ int page_referenced(struct page *page, int is_locked, int ignore_token)
void page_add_anon_rmap(struct page *page,
struct vm_area_struct *vma, unsigned long address)
{
- struct anon_vma *anon_vma = vma->anon_vma;
- pgoff_t index;
-
BUG_ON(PageReserved(page));
- BUG_ON(!anon_vma);
inc_mm_counter(vma->vm_mm, anon_rss);
- anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
- index = (address - vma->vm_start) >> PAGE_SHIFT;
- index += vma->vm_pgoff;
- index >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
-
if (atomic_inc_and_test(&page->_mapcount)) {
- page->index = index;
+ struct anon_vma *anon_vma = vma->anon_vma;
+
+ BUG_ON(!anon_vma);
+ anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
page->mapping = (struct address_space *) anon_vma;
+
+ page->index = linear_page_index(vma, address);
+
inc_page_state(nr_mapped);
}
/* else checking page index and mapping is racy */
@@ -518,8 +512,6 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
pte_t pteval;
int ret = SWAP_AGAIN;
- if (!get_mm_counter(mm, rss))
- goto out;
address = vma_address(page, vma);
if (address == -EFAULT)
goto out;
@@ -532,6 +524,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
* If the page is mlock()d, we cannot swap it out.
* If it's recently referenced (perhaps page_referenced
* skipped over this mm) then we should reactivate it.
+ *
+ * Pages belonging to VM_RESERVED regions should not happen here.
*/
if ((vma->vm_flags & (VM_LOCKED|VM_RESERVED)) ||
ptep_clear_flush_young(vma, address, pte)) {
@@ -767,8 +761,7 @@ static int try_to_unmap_file(struct page *page)
if (vma->vm_flags & (VM_LOCKED|VM_RESERVED))
continue;
cursor = (unsigned long) vma->vm_private_data;
- while (get_mm_counter(vma->vm_mm, rss) &&
- cursor < max_nl_cursor &&
+ while ( cursor < max_nl_cursor &&
cursor < vma->vm_end - vma->vm_start) {
try_to_unmap_cluster(cursor, &mapcount, vma);
cursor += CLUSTER_SIZE;
diff --git a/mm/shmem.c b/mm/shmem.c
index 5a81b1ee4f7a..1f7aeb210c7b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -45,7 +45,6 @@
#include <linux/swapops.h>
#include <linux/mempolicy.h>
#include <linux/namei.h>
-#include <linux/xattr.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/pgtable.h>
@@ -179,10 +178,9 @@ static struct address_space_operations shmem_aops;
static struct file_operations shmem_file_operations;
static struct inode_operations shmem_inode_operations;
static struct inode_operations shmem_dir_inode_operations;
-static struct inode_operations shmem_special_inode_operations;
static struct vm_operations_struct shmem_vm_ops;
-static struct backing_dev_info shmem_backing_dev_info = {
+static struct backing_dev_info shmem_backing_dev_info __read_mostly = {
.ra_pages = 0, /* No readahead */
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
.unplug_io_fn = default_unplug_io_fn,
@@ -668,6 +666,7 @@ static void shmem_delete_inode(struct inode *inode)
struct shmem_inode_info *info = SHMEM_I(inode);
if (inode->i_op->truncate == shmem_truncate) {
+ truncate_inode_pages(inode->i_mapping, 0);
shmem_unacct_size(info->flags, inode->i_size);
inode->i_size = 0;
shmem_truncate(inode);
@@ -1195,6 +1194,7 @@ static int shmem_populate(struct vm_area_struct *vma,
err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
if (err)
return err;
+ /* Page may still be null, but only if nonblock was set. */
if (page) {
mark_page_accessed(page);
err = install_page(mm, vma, addr, page, prot);
@@ -1202,7 +1202,10 @@ static int shmem_populate(struct vm_area_struct *vma,
page_cache_release(page);
return err;
}
- } else if (nonblock) {
+ } else {
+ /* No page was found just because we can't read it in
+ * now (being here implies nonblock != 0), but the page
+ * may exist, so set the PTE to fault it in later. */
err = install_file_pte(mm, vma, addr, pgoff, prot);
if (err)
return err;
@@ -1296,7 +1299,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
switch (mode & S_IFMT) {
default:
- inode->i_op = &shmem_special_inode_operations;
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
@@ -1606,6 +1608,15 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
int error = -ENOSPC;
if (inode) {
+ error = security_inode_init_security(inode, dir, NULL, NULL,
+ NULL);
+ if (error) {
+ if (error != -EOPNOTSUPP) {
+ iput(inode);
+ return error;
+ }
+ error = 0;
+ }
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
@@ -1615,7 +1626,6 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
- error = 0;
}
return error;
}
@@ -1745,6 +1755,16 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
if (!inode)
return -ENOSPC;
+ error = security_inode_init_security(inode, dir, NULL, NULL,
+ NULL);
+ if (error) {
+ if (error != -EOPNOTSUPP) {
+ iput(inode);
+ return error;
+ }
+ error = 0;
+ }
+
info = SHMEM_I(inode);
inode->i_size = len-1;
if (len <= (char *)inode - (char *)info) {
@@ -1800,12 +1820,6 @@ static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *co
static struct inode_operations shmem_symlink_inline_operations = {
.readlink = generic_readlink,
.follow_link = shmem_follow_link_inline,
-#ifdef CONFIG_TMPFS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-#endif
};
static struct inode_operations shmem_symlink_inode_operations = {
@@ -1813,12 +1827,6 @@ static struct inode_operations shmem_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = shmem_follow_link,
.put_link = shmem_put_link,
-#ifdef CONFIG_TMPFS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-#endif
};
static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes)
@@ -1938,12 +1946,6 @@ static void shmem_put_super(struct super_block *sb)
sb->s_fs_info = NULL;
}
-#ifdef CONFIG_TMPFS_XATTR
-static struct xattr_handler *shmem_xattr_handlers[];
-#else
-#define shmem_xattr_handlers NULL
-#endif
-
static int shmem_fill_super(struct super_block *sb,
void *data, int silent)
{
@@ -1994,7 +1996,6 @@ 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_xattr = shmem_xattr_handlers;
inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
if (!inode)
@@ -2083,12 +2084,6 @@ static struct file_operations shmem_file_operations = {
static struct inode_operations shmem_inode_operations = {
.truncate = shmem_truncate,
.setattr = shmem_notify_change,
-#ifdef CONFIG_TMPFS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-#endif
};
static struct inode_operations shmem_dir_inode_operations = {
@@ -2102,21 +2097,6 @@ static struct inode_operations shmem_dir_inode_operations = {
.rmdir = shmem_rmdir,
.mknod = shmem_mknod,
.rename = shmem_rename,
-#ifdef CONFIG_TMPFS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-#endif
-#endif
-};
-
-static struct inode_operations shmem_special_inode_operations = {
-#ifdef CONFIG_TMPFS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
#endif
};
@@ -2142,48 +2122,6 @@ static struct vm_operations_struct shmem_vm_ops = {
};
-#ifdef CONFIG_TMPFS_SECURITY
-
-static size_t shmem_xattr_security_list(struct inode *inode, char *list, size_t list_len,
- const char *name, size_t name_len)
-{
- return security_inode_listsecurity(inode, list, list_len);
-}
-
-static int shmem_xattr_security_get(struct inode *inode, const char *name, void *buffer, size_t size)
-{
- if (strcmp(name, "") == 0)
- return -EINVAL;
- return security_inode_getsecurity(inode, name, buffer, size);
-}
-
-static int shmem_xattr_security_set(struct inode *inode, const char *name, const void *value, size_t size, int flags)
-{
- if (strcmp(name, "") == 0)
- return -EINVAL;
- return security_inode_setsecurity(inode, name, value, size, flags);
-}
-
-static struct xattr_handler shmem_xattr_security_handler = {
- .prefix = XATTR_SECURITY_PREFIX,
- .list = shmem_xattr_security_list,
- .get = shmem_xattr_security_get,
- .set = shmem_xattr_security_set,
-};
-
-#endif /* CONFIG_TMPFS_SECURITY */
-
-#ifdef CONFIG_TMPFS_XATTR
-
-static struct xattr_handler *shmem_xattr_handlers[] = {
-#ifdef CONFIG_TMPFS_SECURITY
- &shmem_xattr_security_handler,
-#endif
- NULL
-};
-
-#endif /* CONFIG_TMPFS_XATTR */
-
static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
diff --git a/mm/slab.c b/mm/slab.c
index c9e706db4634..9e876d6dfad9 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -75,6 +75,15 @@
*
* At present, each engine can be growing a cache. This should be blocked.
*
+ * 15 March 2005. NUMA slab allocator.
+ * Shai Fultheim <shai@scalex86.org>.
+ * Shobhit Dayal <shobhit@calsoftinc.com>
+ * Alok N Kataria <alokk@calsoftinc.com>
+ * Christoph Lameter <christoph@lameter.com>
+ *
+ * Modified the slab allocator to be node aware on NUMA systems.
+ * Each node has its own list of partial, free and full slabs.
+ * All object allocations for a node occur from node specific slab lists.
*/
#include <linux/config.h>
@@ -93,6 +102,7 @@
#include <linux/module.h>
#include <linux/rcupdate.h>
#include <linux/string.h>
+#include <linux/nodemask.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
@@ -189,6 +199,7 @@
* is less than 512 (PAGE_SIZE<<3), but greater than 256.
*/
+typedef unsigned int kmem_bufctl_t;
#define BUFCTL_END (((kmem_bufctl_t)(~0U))-0)
#define BUFCTL_FREE (((kmem_bufctl_t)(~0U))-1)
#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-2)
@@ -211,6 +222,7 @@ struct slab {
void *s_mem; /* including colour offset */
unsigned int inuse; /* num of objs active in slab */
kmem_bufctl_t free;
+ unsigned short nodeid;
};
/*
@@ -238,7 +250,6 @@ struct slab_rcu {
/*
* struct array_cache
*
- * Per cpu structures
* Purpose:
* - LIFO ordering, to hand out cache-warm objects from _alloc
* - reduce the number of linked list operations
@@ -253,6 +264,13 @@ struct array_cache {
unsigned int limit;
unsigned int batchcount;
unsigned int touched;
+ spinlock_t lock;
+ void *entry[0]; /*
+ * Must have this definition in here for the proper
+ * alignment of array_cache. Also simplifies accessing
+ * the entries.
+ * [0] is for gcc 2.95. It should really be [].
+ */
};
/* bootstrap: The caches do not work without cpuarrays anymore,
@@ -265,34 +283,83 @@ struct arraycache_init {
};
/*
- * The slab lists of all objects.
- * Hopefully reduce the internal fragmentation
- * NUMA: The spinlock could be moved from the kmem_cache_t
- * into this structure, too. Figure out what causes
- * fewer cross-node spinlock operations.
+ * The slab lists for all objects.
*/
struct kmem_list3 {
struct list_head slabs_partial; /* partial list first, better asm code */
struct list_head slabs_full;
struct list_head slabs_free;
unsigned long free_objects;
- int free_touched;
unsigned long next_reap;
- struct array_cache *shared;
+ int free_touched;
+ unsigned int free_limit;
+ spinlock_t list_lock;
+ struct array_cache *shared; /* shared per node */
+ struct array_cache **alien; /* on other nodes */
};
-#define LIST3_INIT(parent) \
- { \
- .slabs_full = LIST_HEAD_INIT(parent.slabs_full), \
- .slabs_partial = LIST_HEAD_INIT(parent.slabs_partial), \
- .slabs_free = LIST_HEAD_INIT(parent.slabs_free) \
+/*
+ * Need this for bootstrapping a per node allocator.
+ */
+#define NUM_INIT_LISTS (2 * MAX_NUMNODES + 1)
+struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
+#define CACHE_CACHE 0
+#define SIZE_AC 1
+#define SIZE_L3 (1 + MAX_NUMNODES)
+
+/*
+ * This function may be completely optimized away if
+ * a constant is passed to it. Mostly the same as
+ * what is in linux/slab.h except it returns an
+ * index.
+ */
+static inline int index_of(const size_t size)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+
+#define CACHE(x) \
+ if (size <=x) \
+ return i; \
+ else \
+ i++;
+#include "linux/kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __bad_size(void);
+ __bad_size();
+ }
}
-#define list3_data(cachep) \
- (&(cachep)->lists)
+ return 0;
+}
+
+#define INDEX_AC index_of(sizeof(struct arraycache_init))
+#define INDEX_L3 index_of(sizeof(struct kmem_list3))
+
+static inline void kmem_list3_init(struct kmem_list3 *parent)
+{
+ INIT_LIST_HEAD(&parent->slabs_full);
+ INIT_LIST_HEAD(&parent->slabs_partial);
+ INIT_LIST_HEAD(&parent->slabs_free);
+ parent->shared = NULL;
+ parent->alien = NULL;
+ spin_lock_init(&parent->list_lock);
+ parent->free_objects = 0;
+ parent->free_touched = 0;
+}
-/* NUMA: per-node */
-#define list3_data_ptr(cachep, ptr) \
- list3_data(cachep)
+#define MAKE_LIST(cachep, listp, slab, nodeid) \
+ do { \
+ INIT_LIST_HEAD(listp); \
+ list_splice(&(cachep->nodelists[nodeid]->slab), listp); \
+ } while (0)
+
+#define MAKE_ALL_LISTS(cachep, ptr, nodeid) \
+ do { \
+ MAKE_LIST((cachep), (&(ptr)->slabs_full), slabs_full, nodeid); \
+ MAKE_LIST((cachep), (&(ptr)->slabs_partial), slabs_partial, nodeid); \
+ MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid); \
+ } while (0)
/*
* kmem_cache_t
@@ -305,13 +372,12 @@ struct kmem_cache_s {
struct array_cache *array[NR_CPUS];
unsigned int batchcount;
unsigned int limit;
-/* 2) touched by every alloc & free from the backend */
- struct kmem_list3 lists;
- /* NUMA: kmem_3list_t *nodelists[MAX_NUMNODES] */
+ unsigned int shared;
unsigned int objsize;
+/* 2) touched by every alloc & free from the backend */
+ struct kmem_list3 *nodelists[MAX_NUMNODES];
unsigned int flags; /* constant flags */
unsigned int num; /* # of objs per slab */
- unsigned int free_limit; /* upper limit of objects in the lists */
spinlock_t spinlock;
/* 3) cache_grow/shrink */
@@ -348,6 +414,7 @@ struct kmem_cache_s {
unsigned long errors;
unsigned long max_freeable;
unsigned long node_allocs;
+ unsigned long node_frees;
atomic_t allochit;
atomic_t allocmiss;
atomic_t freehit;
@@ -383,6 +450,7 @@ struct kmem_cache_s {
} while (0)
#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_SET_FREEABLE(x, i) \
do { if ((x)->max_freeable < i) \
(x)->max_freeable = i; \
@@ -401,6 +469,7 @@ struct kmem_cache_s {
#define STATS_SET_HIGH(x) do { } while (0)
#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_SET_FREEABLE(x, i) \
do { } while (0)
@@ -533,9 +602,9 @@ static struct arraycache_init initarray_generic =
/* internal cache of cache description objs */
static kmem_cache_t cache_cache = {
- .lists = LIST3_INIT(cache_cache.lists),
.batchcount = 1,
.limit = BOOT_CPUCACHE_ENTRIES,
+ .shared = 1,
.objsize = sizeof(kmem_cache_t),
.flags = SLAB_NO_REAP,
.spinlock = SPIN_LOCK_UNLOCKED,
@@ -556,7 +625,6 @@ static struct list_head cache_chain;
* SLAB_RECLAIM_ACCOUNT turns this on per-slab
*/
atomic_t slab_reclaim_pages;
-EXPORT_SYMBOL(slab_reclaim_pages);
/*
* chicken and egg problem: delay the per-cpu array allocation
@@ -564,7 +632,8 @@ EXPORT_SYMBOL(slab_reclaim_pages);
*/
static enum {
NONE,
- PARTIAL,
+ PARTIAL_AC,
+ PARTIAL_L3,
FULL
} g_cpucache_up;
@@ -573,11 +642,7 @@ static DEFINE_PER_CPU(struct work_struct, reap_work);
static void free_block(kmem_cache_t* cachep, void** objpp, int len);
static void enable_cpucache (kmem_cache_t *cachep);
static void cache_reap (void *unused);
-
-static inline void **ac_entry(struct array_cache *ac)
-{
- return (void**)(ac+1);
-}
+static int __node_shrink(kmem_cache_t *cachep, int node);
static inline struct array_cache *ac_data(kmem_cache_t *cachep)
{
@@ -600,7 +665,7 @@ static inline kmem_cache_t *__find_general_cachep(size_t size,
csizep++;
/*
- * Really subtile: The last entry with cs->cs_size==ULONG_MAX
+ * Really subtle: The last entry with cs->cs_size==ULONG_MAX
* has cs_{dma,}cachep==NULL. Thus no special case
* for large kmalloc calls required.
*/
@@ -675,48 +740,160 @@ static void __devinit start_cpu_timer(int cpu)
}
}
-static struct array_cache *alloc_arraycache(int cpu, int entries,
+static struct array_cache *alloc_arraycache(int node, int entries,
int batchcount)
{
int memsize = sizeof(void*)*entries+sizeof(struct array_cache);
struct array_cache *nc = NULL;
- if (cpu == -1)
- nc = kmalloc(memsize, GFP_KERNEL);
- else
- nc = kmalloc_node(memsize, GFP_KERNEL, cpu_to_node(cpu));
-
+ nc = kmalloc_node(memsize, GFP_KERNEL, node);
if (nc) {
nc->avail = 0;
nc->limit = entries;
nc->batchcount = batchcount;
nc->touched = 0;
+ spin_lock_init(&nc->lock);
}
return nc;
}
+#ifdef CONFIG_NUMA
+static inline struct array_cache **alloc_alien_cache(int node, int limit)
+{
+ struct array_cache **ac_ptr;
+ int memsize = sizeof(void*)*MAX_NUMNODES;
+ int i;
+
+ if (limit > 1)
+ limit = 12;
+ ac_ptr = kmalloc_node(memsize, GFP_KERNEL, node);
+ if (ac_ptr) {
+ for_each_node(i) {
+ if (i == node || !node_online(i)) {
+ ac_ptr[i] = NULL;
+ continue;
+ }
+ ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d);
+ if (!ac_ptr[i]) {
+ for (i--; i <=0; i--)
+ kfree(ac_ptr[i]);
+ kfree(ac_ptr);
+ return NULL;
+ }
+ }
+ }
+ return ac_ptr;
+}
+
+static inline void free_alien_cache(struct array_cache **ac_ptr)
+{
+ int i;
+
+ if (!ac_ptr)
+ return;
+
+ for_each_node(i)
+ kfree(ac_ptr[i]);
+
+ kfree(ac_ptr);
+}
+
+static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache *ac, int node)
+{
+ struct kmem_list3 *rl3 = cachep->nodelists[node];
+
+ if (ac->avail) {
+ spin_lock(&rl3->list_lock);
+ free_block(cachep, ac->entry, ac->avail);
+ ac->avail = 0;
+ spin_unlock(&rl3->list_lock);
+ }
+}
+
+static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
+{
+ int i=0;
+ struct array_cache *ac;
+ unsigned long flags;
+
+ for_each_online_node(i) {
+ ac = l3->alien[i];
+ if (ac) {
+ spin_lock_irqsave(&ac->lock, flags);
+ __drain_alien_cache(cachep, ac, i);
+ spin_unlock_irqrestore(&ac->lock, flags);
+ }
+ }
+}
+#else
+#define alloc_alien_cache(node, limit) do { } while (0)
+#define free_alien_cache(ac_ptr) do { } while (0)
+#define drain_alien_cache(cachep, l3) do { } while (0)
+#endif
+
static int __devinit cpuup_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
kmem_cache_t* cachep;
+ struct kmem_list3 *l3 = NULL;
+ int node = cpu_to_node(cpu);
+ int memsize = sizeof(struct kmem_list3);
+ struct array_cache *nc = NULL;
switch (action) {
case CPU_UP_PREPARE:
down(&cache_chain_sem);
+ /* we need to do this right in the beginning since
+ * alloc_arraycache's are going to use this list.
+ * kmalloc_node allows us to add the slab to the right
+ * kmem_list3 and not this cpu's kmem_list3
+ */
+
list_for_each_entry(cachep, &cache_chain, next) {
- struct array_cache *nc;
+ /* setup the size64 kmemlist for cpu before we can
+ * begin anything. Make sure some other cpu on this
+ * node has not already allocated this
+ */
+ if (!cachep->nodelists[node]) {
+ if (!(l3 = kmalloc_node(memsize,
+ GFP_KERNEL, node)))
+ goto bad;
+ kmem_list3_init(l3);
+ l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+
+ cachep->nodelists[node] = l3;
+ }
- nc = alloc_arraycache(cpu, cachep->limit, cachep->batchcount);
+ spin_lock_irq(&cachep->nodelists[node]->list_lock);
+ cachep->nodelists[node]->free_limit =
+ (1 + nr_cpus_node(node)) *
+ cachep->batchcount + cachep->num;
+ spin_unlock_irq(&cachep->nodelists[node]->list_lock);
+ }
+
+ /* Now we can go ahead with allocating the shared array's
+ & array cache's */
+ list_for_each_entry(cachep, &cache_chain, next) {
+ nc = alloc_arraycache(node, cachep->limit,
+ cachep->batchcount);
if (!nc)
goto bad;
-
- spin_lock_irq(&cachep->spinlock);
cachep->array[cpu] = nc;
- cachep->free_limit = (1+num_online_cpus())*cachep->batchcount
- + cachep->num;
- spin_unlock_irq(&cachep->spinlock);
+ l3 = cachep->nodelists[node];
+ BUG_ON(!l3);
+ if (!l3->shared) {
+ if (!(nc = alloc_arraycache(node,
+ cachep->shared*cachep->batchcount,
+ 0xbaadf00d)))
+ goto bad;
+
+ /* we are serialised from CPU_DEAD or
+ CPU_UP_CANCELLED by the cpucontrol lock */
+ l3->shared = nc;
+ }
}
up(&cache_chain_sem);
break;
@@ -731,13 +908,51 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
list_for_each_entry(cachep, &cache_chain, next) {
struct array_cache *nc;
+ cpumask_t mask;
+ mask = node_to_cpumask(node);
spin_lock_irq(&cachep->spinlock);
/* cpu is dead; no one can alloc from it. */
nc = cachep->array[cpu];
cachep->array[cpu] = NULL;
- cachep->free_limit -= cachep->batchcount;
- free_block(cachep, ac_entry(nc), nc->avail);
+ l3 = cachep->nodelists[node];
+
+ if (!l3)
+ goto unlock_cache;
+
+ spin_lock(&l3->list_lock);
+
+ /* Free limit for this kmem_list3 */
+ l3->free_limit -= cachep->batchcount;
+ if (nc)
+ free_block(cachep, nc->entry, nc->avail);
+
+ if (!cpus_empty(mask)) {
+ spin_unlock(&l3->list_lock);
+ goto unlock_cache;
+ }
+
+ if (l3->shared) {
+ free_block(cachep, l3->shared->entry,
+ l3->shared->avail);
+ kfree(l3->shared);
+ l3->shared = NULL;
+ }
+ if (l3->alien) {
+ drain_alien_cache(cachep, l3);
+ free_alien_cache(l3->alien);
+ l3->alien = NULL;
+ }
+
+ /* free slabs belonging to this node */
+ if (__node_shrink(cachep, node)) {
+ cachep->nodelists[node] = NULL;
+ spin_unlock(&l3->list_lock);
+ kfree(l3);
+ } else {
+ spin_unlock(&l3->list_lock);
+ }
+unlock_cache:
spin_unlock_irq(&cachep->spinlock);
kfree(nc);
}
@@ -753,6 +968,25 @@ bad:
static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 };
+/*
+ * swap the static kmem_list3 with kmalloced memory
+ */
+static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list,
+ int nodeid)
+{
+ struct kmem_list3 *ptr;
+
+ BUG_ON(cachep->nodelists[nodeid] != list);
+ ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, nodeid);
+ BUG_ON(!ptr);
+
+ local_irq_disable();
+ memcpy(ptr, list, sizeof(struct kmem_list3));
+ MAKE_ALL_LISTS(cachep, ptr, nodeid);
+ cachep->nodelists[nodeid] = ptr;
+ local_irq_enable();
+}
+
/* Initialisation.
* Called after the gfp() functions have been enabled, and before smp_init().
*/
@@ -761,6 +995,13 @@ void __init kmem_cache_init(void)
size_t left_over;
struct cache_sizes *sizes;
struct cache_names *names;
+ int i;
+
+ for (i = 0; i < NUM_INIT_LISTS; i++) {
+ kmem_list3_init(&initkmem_list3[i]);
+ if (i < MAX_NUMNODES)
+ cache_cache.nodelists[i] = NULL;
+ }
/*
* Fragmentation resistance on low memory - only use bigger
@@ -769,21 +1010,24 @@ void __init kmem_cache_init(void)
if (num_physpages > (32 << 20) >> PAGE_SHIFT)
slab_break_gfp_order = BREAK_GFP_ORDER_HI;
-
/* Bootstrap is tricky, because several objects are allocated
* from caches that do not exist yet:
* 1) initialize the cache_cache cache: it contains the kmem_cache_t
* structures of all caches, except cache_cache itself: cache_cache
* is statically allocated.
- * Initially an __init data area is used for the head array, it's
- * replaced with a kmalloc allocated array at the end of the bootstrap.
+ * Initially an __init data area is used for the head array and the
+ * kmem_list3 structures, it's replaced with a kmalloc allocated
+ * array at the end of the bootstrap.
* 2) Create the first kmalloc cache.
- * The kmem_cache_t for the new cache is allocated normally. An __init
- * data area is used for the head array.
- * 3) Create the remaining kmalloc caches, with minimally sized head arrays.
+ * The kmem_cache_t for the new cache is allocated normally.
+ * An __init data area is used for the head array.
+ * 3) Create the remaining kmalloc caches, with minimally sized
+ * head arrays.
* 4) Replace the __init data head arrays for cache_cache and the first
* kmalloc cache with kmalloc allocated arrays.
- * 5) Resize the head arrays of the kmalloc caches to their final sizes.
+ * 5) Replace the __init data for kmem_list3 for cache_cache and
+ * the other cache's with kmalloc allocated memory.
+ * 6) Resize the head arrays of the kmalloc caches to their final sizes.
*/
/* 1) create the cache_cache */
@@ -792,6 +1036,7 @@ void __init kmem_cache_init(void)
list_add(&cache_cache.next, &cache_chain);
cache_cache.colour_off = cache_line_size();
cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
+ cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size());
@@ -809,15 +1054,33 @@ void __init kmem_cache_init(void)
sizes = malloc_sizes;
names = cache_names;
+ /* Initialize the caches that provide memory for the array cache
+ * and the kmem_list3 structures first.
+ * Without this, further allocations will bug
+ */
+
+ sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
+ sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN,
+ (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+
+ if (INDEX_AC != INDEX_L3)
+ sizes[INDEX_L3].cs_cachep =
+ kmem_cache_create(names[INDEX_L3].name,
+ sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN,
+ (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+
while (sizes->cs_size != ULONG_MAX) {
- /* For performance, all the general caches are L1 aligned.
+ /*
+ * For performance, all the general caches are L1 aligned.
* This should be particularly beneficial on SMP boxes, as it
* eliminates "false sharing".
* Note for systems short on memory removing the alignment will
- * allow tighter packing of the smaller caches. */
- sizes->cs_cachep = kmem_cache_create(names->name,
- sizes->cs_size, ARCH_KMALLOC_MINALIGN,
- (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+ * allow tighter packing of the smaller caches.
+ */
+ if(!sizes->cs_cachep)
+ sizes->cs_cachep = kmem_cache_create(names->name,
+ sizes->cs_size, ARCH_KMALLOC_MINALIGN,
+ (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
/* Inc off-slab bufctl limit until the ceiling is hit. */
if (!(OFF_SLAB(sizes->cs_cachep))) {
@@ -836,24 +1099,47 @@ void __init kmem_cache_init(void)
/* 4) Replace the bootstrap head arrays */
{
void * ptr;
-
+
ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
+
local_irq_disable();
BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache);
- memcpy(ptr, ac_data(&cache_cache), sizeof(struct arraycache_init));
+ memcpy(ptr, ac_data(&cache_cache),
+ sizeof(struct arraycache_init));
cache_cache.array[smp_processor_id()] = ptr;
local_irq_enable();
-
+
ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
+
local_irq_disable();
- BUG_ON(ac_data(malloc_sizes[0].cs_cachep) != &initarray_generic.cache);
- memcpy(ptr, ac_data(malloc_sizes[0].cs_cachep),
+ BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep)
+ != &initarray_generic.cache);
+ memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep),
sizeof(struct arraycache_init));
- malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr;
+ malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
+ ptr;
local_irq_enable();
}
+ /* 5) Replace the bootstrap kmem_list3's */
+ {
+ int node;
+ /* Replace the static kmem_list3 structures for the boot cpu */
+ init_list(&cache_cache, &initkmem_list3[CACHE_CACHE],
+ numa_node_id());
+
+ for_each_online_node(node) {
+ init_list(malloc_sizes[INDEX_AC].cs_cachep,
+ &initkmem_list3[SIZE_AC+node], node);
+
+ if (INDEX_AC != INDEX_L3) {
+ init_list(malloc_sizes[INDEX_L3].cs_cachep,
+ &initkmem_list3[SIZE_L3+node],
+ node);
+ }
+ }
+ }
- /* 5) resize the head arrays to their final sizes */
+ /* 6) resize the head arrays to their final sizes */
{
kmem_cache_t *cachep;
down(&cache_chain_sem);
@@ -869,7 +1155,6 @@ void __init kmem_cache_init(void)
* that initializes ac_data for all new cpus
*/
register_cpu_notifier(&cpucache_notifier);
-
/* The reap timers are started later, with a module init call:
* That part of the kernel is not yet operational.
@@ -884,10 +1169,8 @@ static int __init cpucache_init(void)
* Register the timers that return unneeded
* pages to gfp.
*/
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- if (cpu_online(cpu))
- start_cpu_timer(cpu);
- }
+ for_each_online_cpu(cpu)
+ start_cpu_timer(cpu);
return 0;
}
@@ -1166,6 +1449,20 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
}
}
+/* For setting up all the kmem_list3s for cache whose objsize is same
+ as size of kmem_list3. */
+static inline void set_up_list3s(kmem_cache_t *cachep, int index)
+{
+ int node;
+
+ for_each_online_node(node) {
+ cachep->nodelists[node] = &initkmem_list3[index+node];
+ cachep->nodelists[node]->next_reap = jiffies +
+ REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+ }
+}
+
/**
* kmem_cache_create - Create a cache.
* @name: A string which is used in /proc/slabinfo to identify this cache.
@@ -1319,7 +1616,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
size += BYTES_PER_WORD;
}
#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
- if (size > 128 && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
+ if (size >= malloc_sizes[INDEX_L3+1].cs_size && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
cachep->dbghead += PAGE_SIZE - size;
size = PAGE_SIZE;
}
@@ -1421,13 +1718,9 @@ next:
cachep->gfpflags |= GFP_DMA;
spin_lock_init(&cachep->spinlock);
cachep->objsize = size;
- /* NUMA */
- INIT_LIST_HEAD(&cachep->lists.slabs_full);
- INIT_LIST_HEAD(&cachep->lists.slabs_partial);
- INIT_LIST_HEAD(&cachep->lists.slabs_free);
if (flags & CFLGS_OFF_SLAB)
- cachep->slabp_cache = kmem_find_general_cachep(slab_size,0);
+ cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
cachep->ctor = ctor;
cachep->dtor = dtor;
cachep->name = name;
@@ -1443,11 +1736,43 @@ next:
* the cache that's used by kmalloc(24), otherwise
* the creation of further caches will BUG().
*/
- cachep->array[smp_processor_id()] = &initarray_generic.cache;
- g_cpucache_up = PARTIAL;
+ cachep->array[smp_processor_id()] =
+ &initarray_generic.cache;
+
+ /* If the cache that's used by
+ * kmalloc(sizeof(kmem_list3)) is the first cache,
+ * then we need to set up all its list3s, otherwise
+ * the creation of further caches will BUG().
+ */
+ set_up_list3s(cachep, SIZE_AC);
+ if (INDEX_AC == INDEX_L3)
+ g_cpucache_up = PARTIAL_L3;
+ else
+ g_cpucache_up = PARTIAL_AC;
} else {
- cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init),GFP_KERNEL);
+ cachep->array[smp_processor_id()] =
+ kmalloc(sizeof(struct arraycache_init),
+ GFP_KERNEL);
+
+ if (g_cpucache_up == PARTIAL_AC) {
+ set_up_list3s(cachep, SIZE_L3);
+ g_cpucache_up = PARTIAL_L3;
+ } else {
+ int node;
+ for_each_online_node(node) {
+
+ cachep->nodelists[node] =
+ kmalloc_node(sizeof(struct kmem_list3),
+ GFP_KERNEL, node);
+ BUG_ON(!cachep->nodelists[node]);
+ kmem_list3_init(cachep->nodelists[node]);
+ }
+ }
}
+ cachep->nodelists[numa_node_id()]->next_reap =
+ jiffies + REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+
BUG_ON(!ac_data(cachep));
ac_data(cachep)->avail = 0;
ac_data(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
@@ -1455,13 +1780,8 @@ next:
ac_data(cachep)->touched = 0;
cachep->batchcount = 1;
cachep->limit = BOOT_CPUCACHE_ENTRIES;
- cachep->free_limit = (1+num_online_cpus())*cachep->batchcount
- + cachep->num;
}
- cachep->lists.next_reap = jiffies + REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
-
/* Need the semaphore to access the chain. */
down(&cache_chain_sem);
{
@@ -1518,13 +1838,23 @@ static void check_spinlock_acquired(kmem_cache_t *cachep)
{
#ifdef CONFIG_SMP
check_irq_off();
- BUG_ON(spin_trylock(&cachep->spinlock));
+ assert_spin_locked(&cachep->nodelists[numa_node_id()]->list_lock);
+#endif
+}
+
+static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node)
+{
+#ifdef CONFIG_SMP
+ check_irq_off();
+ assert_spin_locked(&cachep->nodelists[node]->list_lock);
#endif
}
+
#else
#define check_irq_off() do { } while(0)
#define check_irq_on() do { } while(0)
#define check_spinlock_acquired(x) do { } while(0)
+#define check_spinlock_acquired_node(x, y) do { } while(0)
#endif
/*
@@ -1546,7 +1876,7 @@ static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
}
static void drain_array_locked(kmem_cache_t* cachep,
- struct array_cache *ac, int force);
+ struct array_cache *ac, int force, int node);
static void do_drain(void *arg)
{
@@ -1555,59 +1885,82 @@ static void do_drain(void *arg)
check_irq_off();
ac = ac_data(cachep);
- spin_lock(&cachep->spinlock);
- free_block(cachep, &ac_entry(ac)[0], ac->avail);
- spin_unlock(&cachep->spinlock);
+ spin_lock(&cachep->nodelists[numa_node_id()]->list_lock);
+ free_block(cachep, ac->entry, ac->avail);
+ spin_unlock(&cachep->nodelists[numa_node_id()]->list_lock);
ac->avail = 0;
}
static void drain_cpu_caches(kmem_cache_t *cachep)
{
+ struct kmem_list3 *l3;
+ int node;
+
smp_call_function_all_cpus(do_drain, cachep);
check_irq_on();
spin_lock_irq(&cachep->spinlock);
- if (cachep->lists.shared)
- drain_array_locked(cachep, cachep->lists.shared, 1);
+ for_each_online_node(node) {
+ l3 = cachep->nodelists[node];
+ if (l3) {
+ spin_lock(&l3->list_lock);
+ drain_array_locked(cachep, l3->shared, 1, node);
+ spin_unlock(&l3->list_lock);
+ if (l3->alien)
+ drain_alien_cache(cachep, l3);
+ }
+ }
spin_unlock_irq(&cachep->spinlock);
}
-
-/* NUMA shrink all list3s */
-static int __cache_shrink(kmem_cache_t *cachep)
+static int __node_shrink(kmem_cache_t *cachep, int node)
{
struct slab *slabp;
+ struct kmem_list3 *l3 = cachep->nodelists[node];
int ret;
- drain_cpu_caches(cachep);
-
- check_irq_on();
- spin_lock_irq(&cachep->spinlock);
-
- for(;;) {
+ for (;;) {
struct list_head *p;
- p = cachep->lists.slabs_free.prev;
- if (p == &cachep->lists.slabs_free)
+ p = l3->slabs_free.prev;
+ if (p == &l3->slabs_free)
break;
- slabp = list_entry(cachep->lists.slabs_free.prev, struct slab, list);
+ slabp = list_entry(l3->slabs_free.prev, struct slab, list);
#if DEBUG
if (slabp->inuse)
BUG();
#endif
list_del(&slabp->list);
- cachep->lists.free_objects -= cachep->num;
- spin_unlock_irq(&cachep->spinlock);
+ l3->free_objects -= cachep->num;
+ spin_unlock_irq(&l3->list_lock);
slab_destroy(cachep, slabp);
- spin_lock_irq(&cachep->spinlock);
+ spin_lock_irq(&l3->list_lock);
}
- ret = !list_empty(&cachep->lists.slabs_full) ||
- !list_empty(&cachep->lists.slabs_partial);
- spin_unlock_irq(&cachep->spinlock);
+ ret = !list_empty(&l3->slabs_full) ||
+ !list_empty(&l3->slabs_partial);
return ret;
}
+static int __cache_shrink(kmem_cache_t *cachep)
+{
+ int ret = 0, i = 0;
+ struct kmem_list3 *l3;
+
+ drain_cpu_caches(cachep);
+
+ check_irq_on();
+ for_each_online_node(i) {
+ l3 = cachep->nodelists[i];
+ if (l3) {
+ spin_lock_irq(&l3->list_lock);
+ ret += __node_shrink(cachep, i);
+ spin_unlock_irq(&l3->list_lock);
+ }
+ }
+ return (ret ? 1 : 0);
+}
+
/**
* kmem_cache_shrink - Shrink a cache.
* @cachep: The cache to shrink.
@@ -1644,6 +1997,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
int kmem_cache_destroy(kmem_cache_t * cachep)
{
int i;
+ struct kmem_list3 *l3;
if (!cachep || in_interrupt())
BUG();
@@ -1671,15 +2025,17 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
synchronize_rcu();
- /* no cpu_online check required here since we clear the percpu
- * array on cpu offline and set this to NULL.
- */
- for (i = 0; i < NR_CPUS; i++)
+ for_each_online_cpu(i)
kfree(cachep->array[i]);
/* NUMA: free the list3 structures */
- kfree(cachep->lists.shared);
- cachep->lists.shared = NULL;
+ for_each_online_node(i) {
+ if ((l3 = cachep->nodelists[i])) {
+ kfree(l3->shared);
+ free_alien_cache(l3->alien);
+ kfree(l3);
+ }
+ }
kmem_cache_free(&cache_cache, cachep);
unlock_cpu_hotplug();
@@ -1689,8 +2045,8 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
EXPORT_SYMBOL(kmem_cache_destroy);
/* Get the memory for a slab management obj. */
-static struct slab* alloc_slabmgmt(kmem_cache_t *cachep,
- void *objp, int colour_off, unsigned int __nocast local_flags)
+static struct slab* alloc_slabmgmt(kmem_cache_t *cachep, void *objp,
+ int colour_off, unsigned int __nocast local_flags)
{
struct slab *slabp;
@@ -1721,7 +2077,7 @@ static void cache_init_objs(kmem_cache_t *cachep,
int i;
for (i = 0; i < cachep->num; i++) {
- void* objp = slabp->s_mem+cachep->objsize*i;
+ void *objp = slabp->s_mem+cachep->objsize*i;
#if DEBUG
/* need to poison the objs? */
if (cachep->flags & SLAB_POISON)
@@ -1798,6 +2154,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
size_t offset;
unsigned int local_flags;
unsigned long ctor_flags;
+ struct kmem_list3 *l3;
/* Be lazy and only check for valid flags here,
* keeping it out of the critical path in kmem_cache_alloc().
@@ -1829,6 +2186,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
spin_unlock(&cachep->spinlock);
+ check_irq_off();
if (local_flags & __GFP_WAIT)
local_irq_enable();
@@ -1840,8 +2198,9 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
*/
kmem_flagcheck(cachep, flags);
-
- /* Get mem for the objs. */
+ /* Get mem for the objs.
+ * Attempt to allocate a physical page from 'nodeid',
+ */
if (!(objp = kmem_getpages(cachep, flags, nodeid)))
goto failed;
@@ -1849,6 +2208,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
if (!(slabp = alloc_slabmgmt(cachep, objp, offset, local_flags)))
goto opps1;
+ slabp->nodeid = nodeid;
set_slab_attr(cachep, slabp, objp);
cache_init_objs(cachep, slabp, ctor_flags);
@@ -1856,13 +2216,14 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
if (local_flags & __GFP_WAIT)
local_irq_disable();
check_irq_off();
- spin_lock(&cachep->spinlock);
+ l3 = cachep->nodelists[nodeid];
+ spin_lock(&l3->list_lock);
/* Make slab active. */
- list_add_tail(&slabp->list, &(list3_data(cachep)->slabs_free));
+ list_add_tail(&slabp->list, &(l3->slabs_free));
STATS_INC_GROWN(cachep);
- list3_data(cachep)->free_objects += cachep->num;
- spin_unlock(&cachep->spinlock);
+ l3->free_objects += cachep->num;
+ spin_unlock(&l3->list_lock);
return 1;
opps1:
kmem_freepages(cachep, objp);
@@ -1968,7 +2329,6 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
kmem_bufctl_t i;
int entries = 0;
- check_spinlock_acquired(cachep);
/* Check slab's freelist to see if this obj is there. */
for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
entries++;
@@ -2011,10 +2371,11 @@ retry:
*/
batchcount = BATCHREFILL_LIMIT;
}
- l3 = list3_data(cachep);
+ l3 = cachep->nodelists[numa_node_id()];
+
+ BUG_ON(ac->avail > 0 || !l3);
+ spin_lock(&l3->list_lock);
- BUG_ON(ac->avail > 0);
- spin_lock(&cachep->spinlock);
if (l3->shared) {
struct array_cache *shared_array = l3->shared;
if (shared_array->avail) {
@@ -2022,8 +2383,9 @@ retry:
batchcount = shared_array->avail;
shared_array->avail -= batchcount;
ac->avail = batchcount;
- memcpy(ac_entry(ac), &ac_entry(shared_array)[shared_array->avail],
- sizeof(void*)*batchcount);
+ memcpy(ac->entry,
+ &(shared_array->entry[shared_array->avail]),
+ sizeof(void*)*batchcount);
shared_array->touched = 1;
goto alloc_done;
}
@@ -2050,7 +2412,8 @@ retry:
STATS_SET_HIGH(cachep);
/* get obj pointer */
- ac_entry(ac)[ac->avail++] = slabp->s_mem + slabp->free*cachep->objsize;
+ ac->entry[ac->avail++] = slabp->s_mem +
+ slabp->free*cachep->objsize;
slabp->inuse++;
next = slab_bufctl(slabp)[slabp->free];
@@ -2072,12 +2435,12 @@ retry:
must_grow:
l3->free_objects -= ac->avail;
alloc_done:
- spin_unlock(&cachep->spinlock);
+ spin_unlock(&l3->list_lock);
if (unlikely(!ac->avail)) {
int x;
- x = cache_grow(cachep, flags, -1);
-
+ x = cache_grow(cachep, flags, numa_node_id());
+
// cache_grow can reenable interrupts, then ac could change.
ac = ac_data(cachep);
if (!x && ac->avail == 0) // no objects in sight? abort
@@ -2087,7 +2450,7 @@ alloc_done:
goto retry;
}
ac->touched = 1;
- return ac_entry(ac)[--ac->avail];
+ return ac->entry[--ac->avail];
}
static inline void
@@ -2159,43 +2522,116 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl
if (likely(ac->avail)) {
STATS_INC_ALLOCHIT(cachep);
ac->touched = 1;
- objp = ac_entry(ac)[--ac->avail];
+ objp = ac->entry[--ac->avail];
} else {
STATS_INC_ALLOCMISS(cachep);
objp = cache_alloc_refill(cachep, flags);
}
local_irq_restore(save_flags);
- objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));
+ objp = cache_alloc_debugcheck_after(cachep, flags, objp,
+ __builtin_return_address(0));
+ prefetchw(objp);
return objp;
}
-/*
- * NUMA: different approach needed if the spinlock is moved into
- * the l3 structure
+#ifdef CONFIG_NUMA
+/*
+ * A interface to enable slab creation on nodeid
*/
+static void *__cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+{
+ struct list_head *entry;
+ struct slab *slabp;
+ struct kmem_list3 *l3;
+ void *obj;
+ kmem_bufctl_t next;
+ int x;
+ l3 = cachep->nodelists[nodeid];
+ BUG_ON(!l3);
+
+retry:
+ spin_lock(&l3->list_lock);
+ entry = l3->slabs_partial.next;
+ if (entry == &l3->slabs_partial) {
+ l3->free_touched = 1;
+ entry = l3->slabs_free.next;
+ if (entry == &l3->slabs_free)
+ goto must_grow;
+ }
+
+ slabp = list_entry(entry, struct slab, list);
+ check_spinlock_acquired_node(cachep, nodeid);
+ check_slabp(cachep, slabp);
+
+ STATS_INC_NODEALLOCS(cachep);
+ STATS_INC_ACTIVE(cachep);
+ STATS_SET_HIGH(cachep);
+
+ BUG_ON(slabp->inuse == cachep->num);
+
+ /* get obj pointer */
+ obj = slabp->s_mem + slabp->free*cachep->objsize;
+ slabp->inuse++;
+ next = slab_bufctl(slabp)[slabp->free];
+#if DEBUG
+ slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
+#endif
+ slabp->free = next;
+ check_slabp(cachep, slabp);
+ l3->free_objects--;
+ /* move slabp to correct slabp list: */
+ list_del(&slabp->list);
+
+ if (slabp->free == BUFCTL_END) {
+ list_add(&slabp->list, &l3->slabs_full);
+ } else {
+ list_add(&slabp->list, &l3->slabs_partial);
+ }
+
+ spin_unlock(&l3->list_lock);
+ goto done;
+
+must_grow:
+ spin_unlock(&l3->list_lock);
+ x = cache_grow(cachep, flags, nodeid);
+
+ if (!x)
+ return NULL;
+
+ goto retry;
+done:
+ return obj;
+}
+#endif
+
+/*
+ * Caller needs to acquire correct kmem_list's list_lock
+ */
static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
{
int i;
-
- check_spinlock_acquired(cachep);
-
- /* NUMA: move add into loop */
- cachep->lists.free_objects += nr_objects;
+ struct kmem_list3 *l3;
for (i = 0; i < nr_objects; i++) {
void *objp = objpp[i];
struct slab *slabp;
unsigned int objnr;
+ int nodeid = 0;
slabp = GET_PAGE_SLAB(virt_to_page(objp));
+ nodeid = slabp->nodeid;
+ l3 = cachep->nodelists[nodeid];
list_del(&slabp->list);
objnr = (objp - slabp->s_mem) / cachep->objsize;
+ check_spinlock_acquired_node(cachep, nodeid);
check_slabp(cachep, slabp);
+
+
#if DEBUG
if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
- printk(KERN_ERR "slab: double free detected in cache '%s', objp %p.\n",
- cachep->name, objp);
+ printk(KERN_ERR "slab: double free detected in cache "
+ "'%s', objp %p\n", cachep->name, objp);
BUG();
}
#endif
@@ -2203,24 +2639,23 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
slabp->free = objnr;
STATS_DEC_ACTIVE(cachep);
slabp->inuse--;
+ l3->free_objects++;
check_slabp(cachep, slabp);
/* fixup slab chains */
if (slabp->inuse == 0) {
- if (cachep->lists.free_objects > cachep->free_limit) {
- cachep->lists.free_objects -= cachep->num;
+ if (l3->free_objects > l3->free_limit) {
+ l3->free_objects -= cachep->num;
slab_destroy(cachep, slabp);
} else {
- list_add(&slabp->list,
- &list3_data_ptr(cachep, objp)->slabs_free);
+ list_add(&slabp->list, &l3->slabs_free);
}
} else {
/* Unconditionally move a slab to the end of the
* partial list on free - maximum time for the
* other objects to be freed, too.
*/
- list_add_tail(&slabp->list,
- &list3_data_ptr(cachep, objp)->slabs_partial);
+ list_add_tail(&slabp->list, &l3->slabs_partial);
}
}
}
@@ -2228,36 +2663,38 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
{
int batchcount;
+ struct kmem_list3 *l3;
batchcount = ac->batchcount;
#if DEBUG
BUG_ON(!batchcount || batchcount > ac->avail);
#endif
check_irq_off();
- spin_lock(&cachep->spinlock);
- if (cachep->lists.shared) {
- struct array_cache *shared_array = cachep->lists.shared;
+ l3 = cachep->nodelists[numa_node_id()];
+ spin_lock(&l3->list_lock);
+ if (l3->shared) {
+ struct array_cache *shared_array = l3->shared;
int max = shared_array->limit-shared_array->avail;
if (max) {
if (batchcount > max)
batchcount = max;
- memcpy(&ac_entry(shared_array)[shared_array->avail],
- &ac_entry(ac)[0],
+ memcpy(&(shared_array->entry[shared_array->avail]),
+ ac->entry,
sizeof(void*)*batchcount);
shared_array->avail += batchcount;
goto free_done;
}
}
- free_block(cachep, &ac_entry(ac)[0], batchcount);
+ free_block(cachep, ac->entry, batchcount);
free_done:
#if STATS
{
int i = 0;
struct list_head *p;
- p = list3_data(cachep)->slabs_free.next;
- while (p != &(list3_data(cachep)->slabs_free)) {
+ p = l3->slabs_free.next;
+ while (p != &(l3->slabs_free)) {
struct slab *slabp;
slabp = list_entry(p, struct slab, list);
@@ -2269,12 +2706,13 @@ free_done:
STATS_SET_FREEABLE(cachep, i);
}
#endif
- spin_unlock(&cachep->spinlock);
+ spin_unlock(&l3->list_lock);
ac->avail -= batchcount;
- memmove(&ac_entry(ac)[0], &ac_entry(ac)[batchcount],
+ memmove(ac->entry, &(ac->entry[batchcount]),
sizeof(void*)*ac->avail);
}
+
/*
* __cache_free
* Release an obj back to its cache. If the obj has a constructed
@@ -2289,14 +2727,46 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
check_irq_off();
objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
+ /* Make sure we are not freeing a object from another
+ * node to the array cache on this cpu.
+ */
+#ifdef CONFIG_NUMA
+ {
+ struct slab *slabp;
+ slabp = GET_PAGE_SLAB(virt_to_page(objp));
+ if (unlikely(slabp->nodeid != numa_node_id())) {
+ struct array_cache *alien = NULL;
+ int nodeid = slabp->nodeid;
+ struct kmem_list3 *l3 = cachep->nodelists[numa_node_id()];
+
+ STATS_INC_NODEFREES(cachep);
+ if (l3->alien && l3->alien[nodeid]) {
+ alien = l3->alien[nodeid];
+ spin_lock(&alien->lock);
+ if (unlikely(alien->avail == alien->limit))
+ __drain_alien_cache(cachep,
+ alien, nodeid);
+ alien->entry[alien->avail++] = objp;
+ spin_unlock(&alien->lock);
+ } else {
+ spin_lock(&(cachep->nodelists[nodeid])->
+ list_lock);
+ free_block(cachep, &objp, 1);
+ spin_unlock(&(cachep->nodelists[nodeid])->
+ list_lock);
+ }
+ return;
+ }
+ }
+#endif
if (likely(ac->avail < ac->limit)) {
STATS_INC_FREEHIT(cachep);
- ac_entry(ac)[ac->avail++] = objp;
+ ac->entry[ac->avail++] = objp;
return;
} else {
STATS_INC_FREEMISS(cachep);
cache_flusharray(cachep, ac);
- ac_entry(ac)[ac->avail++] = objp;
+ ac->entry[ac->avail++] = objp;
}
}
@@ -2366,81 +2836,30 @@ out:
* Identical to kmem_cache_alloc, except that this function is slow
* and can sleep. And it will allocate memory on the given node, which
* can improve the performance for cpu bound structures.
+ * New and improved: it will now make sure that the object gets
+ * put on the correct node list so that there is no false sharing.
*/
-void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid)
{
- int loop;
- void *objp;
- struct slab *slabp;
- kmem_bufctl_t next;
-
- if (nodeid == -1)
- return kmem_cache_alloc(cachep, flags);
-
- for (loop = 0;;loop++) {
- struct list_head *q;
-
- objp = NULL;
- check_irq_on();
- spin_lock_irq(&cachep->spinlock);
- /* walk through all partial and empty slab and find one
- * from the right node */
- list_for_each(q,&cachep->lists.slabs_partial) {
- slabp = list_entry(q, struct slab, list);
-
- if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid ||
- loop > 2)
- goto got_slabp;
- }
- list_for_each(q, &cachep->lists.slabs_free) {
- slabp = list_entry(q, struct slab, list);
+ unsigned long save_flags;
+ void *ptr;
- if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid ||
- loop > 2)
- goto got_slabp;
- }
- spin_unlock_irq(&cachep->spinlock);
+ if (nodeid == numa_node_id() || nodeid == -1)
+ return __cache_alloc(cachep, flags);
- local_irq_disable();
- if (!cache_grow(cachep, flags, nodeid)) {
- local_irq_enable();
- return NULL;
- }
- local_irq_enable();
+ if (unlikely(!cachep->nodelists[nodeid])) {
+ /* Fall back to __cache_alloc if we run into trouble */
+ printk(KERN_WARNING "slab: not allocating in inactive node %d for cache %s\n", nodeid, cachep->name);
+ return __cache_alloc(cachep,flags);
}
-got_slabp:
- /* found one: allocate object */
- check_slabp(cachep, slabp);
- check_spinlock_acquired(cachep);
-
- STATS_INC_ALLOCED(cachep);
- STATS_INC_ACTIVE(cachep);
- STATS_SET_HIGH(cachep);
- STATS_INC_NODEALLOCS(cachep);
-
- objp = slabp->s_mem + slabp->free*cachep->objsize;
-
- slabp->inuse++;
- next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
- slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-#endif
- slabp->free = next;
- check_slabp(cachep, slabp);
- /* move slabp to correct slabp list: */
- list_del(&slabp->list);
- if (slabp->free == BUFCTL_END)
- list_add(&slabp->list, &cachep->lists.slabs_full);
- else
- list_add(&slabp->list, &cachep->lists.slabs_partial);
-
- list3_data(cachep)->free_objects--;
- spin_unlock_irq(&cachep->spinlock);
+ cache_alloc_debugcheck_before(cachep, flags);
+ local_irq_save(save_flags);
+ ptr = __cache_alloc_node(cachep, flags, nodeid);
+ local_irq_restore(save_flags);
+ ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0));
- objp = cache_alloc_debugcheck_after(cachep, GFP_KERNEL, objp,
- __builtin_return_address(0));
- return objp;
+ return ptr;
}
EXPORT_SYMBOL(kmem_cache_alloc_node);
@@ -2510,11 +2929,18 @@ void *__alloc_percpu(size_t size, size_t align)
if (!pdata)
return NULL;
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
- pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL,
- cpu_to_node(i));
+ /*
+ * Cannot use for_each_online_cpu since a cpu may come online
+ * and we have no way of figuring out how to fix the array
+ * that we have allocated then....
+ */
+ for_each_cpu(i) {
+ int node = cpu_to_node(i);
+
+ if (node_online(node))
+ pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL, node);
+ else
+ pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
if (!pdata->ptrs[i])
goto unwind_oom;
@@ -2555,29 +2981,25 @@ void kmem_cache_free(kmem_cache_t *cachep, void *objp)
EXPORT_SYMBOL(kmem_cache_free);
/**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
* @flags: the type of memory to allocate.
*/
-void *kcalloc(size_t n, size_t size, unsigned int __nocast flags)
+void *kzalloc(size_t size, unsigned int __nocast flags)
{
- void *ret = NULL;
-
- if (n != 0 && size > INT_MAX / n)
- return ret;
-
- ret = kmalloc(n * size, flags);
+ void *ret = kmalloc(size, flags);
if (ret)
- memset(ret, 0, n * size);
+ memset(ret, 0, size);
return ret;
}
-EXPORT_SYMBOL(kcalloc);
+EXPORT_SYMBOL(kzalloc);
/**
* kfree - free previously allocated memory
* @objp: pointer returned by kmalloc.
*
+ * If @objp is NULL, no operation is performed.
+ *
* Don't free memory not originally allocated by kmalloc()
* or you will run into trouble.
*/
@@ -2610,11 +3032,11 @@ 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;
+ /*
+ * We allocate for all cpus so we cannot use for online cpu here.
+ */
+ for_each_cpu(i)
kfree(p->ptrs[i]);
- }
kfree(p);
}
EXPORT_SYMBOL(free_percpu);
@@ -2632,6 +3054,64 @@ const char *kmem_cache_name(kmem_cache_t *cachep)
}
EXPORT_SYMBOL_GPL(kmem_cache_name);
+/*
+ * This initializes kmem_list3 for all nodes.
+ */
+static int alloc_kmemlist(kmem_cache_t *cachep)
+{
+ int node;
+ struct kmem_list3 *l3;
+ int err = 0;
+
+ for_each_online_node(node) {
+ struct array_cache *nc = NULL, *new;
+ struct array_cache **new_alien = NULL;
+#ifdef CONFIG_NUMA
+ if (!(new_alien = alloc_alien_cache(node, cachep->limit)))
+ goto fail;
+#endif
+ if (!(new = alloc_arraycache(node, (cachep->shared*
+ cachep->batchcount), 0xbaadf00d)))
+ goto fail;
+ if ((l3 = cachep->nodelists[node])) {
+
+ spin_lock_irq(&l3->list_lock);
+
+ if ((nc = cachep->nodelists[node]->shared))
+ free_block(cachep, nc->entry,
+ nc->avail);
+
+ l3->shared = new;
+ if (!cachep->nodelists[node]->alien) {
+ l3->alien = new_alien;
+ new_alien = NULL;
+ }
+ l3->free_limit = (1 + nr_cpus_node(node))*
+ cachep->batchcount + cachep->num;
+ spin_unlock_irq(&l3->list_lock);
+ kfree(nc);
+ free_alien_cache(new_alien);
+ continue;
+ }
+ if (!(l3 = kmalloc_node(sizeof(struct kmem_list3),
+ GFP_KERNEL, node)))
+ goto fail;
+
+ kmem_list3_init(l3);
+ l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+ l3->shared = new;
+ l3->alien = new_alien;
+ l3->free_limit = (1 + nr_cpus_node(node))*
+ cachep->batchcount + cachep->num;
+ cachep->nodelists[node] = l3;
+ }
+ return err;
+fail:
+ err = -ENOMEM;
+ return err;
+}
+
struct ccupdate_struct {
kmem_cache_t *cachep;
struct array_cache *new[NR_CPUS];
@@ -2644,7 +3124,7 @@ static void do_ccupdate_local(void *info)
check_irq_off();
old = ac_data(new->cachep);
-
+
new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
new->new[smp_processor_id()] = old;
}
@@ -2654,54 +3134,43 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
int shared)
{
struct ccupdate_struct new;
- struct array_cache *new_shared;
- int i;
+ int i, err;
memset(&new.new,0,sizeof(new.new));
- for (i = 0; i < NR_CPUS; i++) {
- if (cpu_online(i)) {
- new.new[i] = alloc_arraycache(i, limit, batchcount);
- if (!new.new[i]) {
- for (i--; i >= 0; i--) kfree(new.new[i]);
- return -ENOMEM;
- }
- } else {
- new.new[i] = NULL;
+ for_each_online_cpu(i) {
+ new.new[i] = alloc_arraycache(cpu_to_node(i), limit, batchcount);
+ if (!new.new[i]) {
+ for (i--; i >= 0; i--) kfree(new.new[i]);
+ return -ENOMEM;
}
}
new.cachep = cachep;
smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
-
+
check_irq_on();
spin_lock_irq(&cachep->spinlock);
cachep->batchcount = batchcount;
cachep->limit = limit;
- cachep->free_limit = (1+num_online_cpus())*cachep->batchcount + cachep->num;
+ cachep->shared = shared;
spin_unlock_irq(&cachep->spinlock);
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_online_cpu(i) {
struct array_cache *ccold = new.new[i];
if (!ccold)
continue;
- spin_lock_irq(&cachep->spinlock);
- free_block(cachep, ac_entry(ccold), ccold->avail);
- spin_unlock_irq(&cachep->spinlock);
+ spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
+ free_block(cachep, ccold->entry, ccold->avail);
+ spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
kfree(ccold);
}
- new_shared = alloc_arraycache(-1, batchcount*shared, 0xbaadf00d);
- if (new_shared) {
- struct array_cache *old;
- spin_lock_irq(&cachep->spinlock);
- old = cachep->lists.shared;
- cachep->lists.shared = new_shared;
- if (old)
- free_block(cachep, ac_entry(old), old->avail);
- spin_unlock_irq(&cachep->spinlock);
- kfree(old);
+ err = alloc_kmemlist(cachep);
+ if (err) {
+ printk(KERN_ERR "alloc_kmemlist failed for %s, error %d.\n",
+ cachep->name, -err);
+ BUG();
}
-
return 0;
}
@@ -2759,11 +3228,11 @@ static void enable_cpucache(kmem_cache_t *cachep)
}
static void drain_array_locked(kmem_cache_t *cachep,
- struct array_cache *ac, int force)
+ struct array_cache *ac, int force, int node)
{
int tofree;
- check_spinlock_acquired(cachep);
+ check_spinlock_acquired_node(cachep, node);
if (ac->touched && !force) {
ac->touched = 0;
} else if (ac->avail) {
@@ -2771,9 +3240,9 @@ static void drain_array_locked(kmem_cache_t *cachep,
if (tofree > ac->avail) {
tofree = (ac->avail+1)/2;
}
- free_block(cachep, ac_entry(ac), tofree);
+ free_block(cachep, ac->entry, tofree);
ac->avail -= tofree;
- memmove(&ac_entry(ac)[0], &ac_entry(ac)[tofree],
+ memmove(ac->entry, &(ac->entry[tofree]),
sizeof(void*)*ac->avail);
}
}
@@ -2792,6 +3261,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
static void cache_reap(void *unused)
{
struct list_head *walk;
+ struct kmem_list3 *l3;
if (down_trylock(&cache_chain_sem)) {
/* Give up. Setup the next iteration. */
@@ -2812,27 +3282,32 @@ static void cache_reap(void *unused)
check_irq_on();
- spin_lock_irq(&searchp->spinlock);
+ l3 = searchp->nodelists[numa_node_id()];
+ if (l3->alien)
+ drain_alien_cache(searchp, l3);
+ spin_lock_irq(&l3->list_lock);
- drain_array_locked(searchp, ac_data(searchp), 0);
+ drain_array_locked(searchp, ac_data(searchp), 0,
+ numa_node_id());
- if(time_after(searchp->lists.next_reap, jiffies))
+ if (time_after(l3->next_reap, jiffies))
goto next_unlock;
- searchp->lists.next_reap = jiffies + REAPTIMEOUT_LIST3;
+ l3->next_reap = jiffies + REAPTIMEOUT_LIST3;
- if (searchp->lists.shared)
- drain_array_locked(searchp, searchp->lists.shared, 0);
+ if (l3->shared)
+ drain_array_locked(searchp, l3->shared, 0,
+ numa_node_id());
- if (searchp->lists.free_touched) {
- searchp->lists.free_touched = 0;
+ if (l3->free_touched) {
+ l3->free_touched = 0;
goto next_unlock;
}
- tofree = (searchp->free_limit+5*searchp->num-1)/(5*searchp->num);
+ tofree = (l3->free_limit+5*searchp->num-1)/(5*searchp->num);
do {
- p = list3_data(searchp)->slabs_free.next;
- if (p == &(list3_data(searchp)->slabs_free))
+ p = l3->slabs_free.next;
+ if (p == &(l3->slabs_free))
break;
slabp = list_entry(p, struct slab, list);
@@ -2845,13 +3320,13 @@ static void cache_reap(void *unused)
* searchp cannot disappear, we hold
* cache_chain_lock
*/
- searchp->lists.free_objects -= searchp->num;
- spin_unlock_irq(&searchp->spinlock);
+ l3->free_objects -= searchp->num;
+ spin_unlock_irq(&l3->list_lock);
slab_destroy(searchp, slabp);
- spin_lock_irq(&searchp->spinlock);
+ spin_lock_irq(&l3->list_lock);
} while(--tofree > 0);
next_unlock:
- spin_unlock_irq(&searchp->spinlock);
+ spin_unlock_irq(&l3->list_lock);
next:
cond_resched();
}
@@ -2885,7 +3360,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
#if STATS
seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped>"
- " <error> <maxfreeable> <freelimit> <nodeallocs>");
+ " <error> <maxfreeable> <nodeallocs> <remotefrees>");
seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
#endif
seq_putc(m, '\n');
@@ -2920,39 +3395,53 @@ static int s_show(struct seq_file *m, void *p)
unsigned long active_objs;
unsigned long num_objs;
unsigned long active_slabs = 0;
- unsigned long num_slabs;
- const char *name;
+ unsigned long num_slabs, free_objects = 0, shared_avail = 0;
+ const char *name;
char *error = NULL;
+ int node;
+ struct kmem_list3 *l3;
check_irq_on();
spin_lock_irq(&cachep->spinlock);
active_objs = 0;
num_slabs = 0;
- list_for_each(q,&cachep->lists.slabs_full) {
- slabp = list_entry(q, struct slab, list);
- if (slabp->inuse != cachep->num && !error)
- error = "slabs_full accounting error";
- active_objs += cachep->num;
- active_slabs++;
- }
- list_for_each(q,&cachep->lists.slabs_partial) {
- slabp = list_entry(q, struct slab, list);
- if (slabp->inuse == cachep->num && !error)
- error = "slabs_partial inuse accounting error";
- if (!slabp->inuse && !error)
- error = "slabs_partial/inuse accounting error";
- active_objs += slabp->inuse;
- active_slabs++;
- }
- list_for_each(q,&cachep->lists.slabs_free) {
- slabp = list_entry(q, struct slab, list);
- if (slabp->inuse && !error)
- error = "slabs_free/inuse accounting error";
- num_slabs++;
+ for_each_online_node(node) {
+ l3 = cachep->nodelists[node];
+ if (!l3)
+ continue;
+
+ spin_lock(&l3->list_lock);
+
+ list_for_each(q,&l3->slabs_full) {
+ slabp = list_entry(q, struct slab, list);
+ if (slabp->inuse != cachep->num && !error)
+ error = "slabs_full accounting error";
+ active_objs += cachep->num;
+ active_slabs++;
+ }
+ list_for_each(q,&l3->slabs_partial) {
+ slabp = list_entry(q, struct slab, list);
+ if (slabp->inuse == cachep->num && !error)
+ error = "slabs_partial inuse accounting error";
+ if (!slabp->inuse && !error)
+ error = "slabs_partial/inuse accounting error";
+ active_objs += slabp->inuse;
+ active_slabs++;
+ }
+ list_for_each(q,&l3->slabs_free) {
+ slabp = list_entry(q, struct slab, list);
+ if (slabp->inuse && !error)
+ error = "slabs_free/inuse accounting error";
+ num_slabs++;
+ }
+ free_objects += l3->free_objects;
+ shared_avail += l3->shared->avail;
+
+ spin_unlock(&l3->list_lock);
}
num_slabs+=active_slabs;
num_objs = num_slabs*cachep->num;
- if (num_objs - active_objs != cachep->lists.free_objects && !error)
+ if (num_objs - active_objs != free_objects && !error)
error = "free_objects accounting error";
name = cachep->name;
@@ -2964,9 +3453,9 @@ static int s_show(struct seq_file *m, void *p)
cachep->num, (1<<cachep->gfporder));
seq_printf(m, " : tunables %4u %4u %4u",
cachep->limit, cachep->batchcount,
- cachep->lists.shared->limit/cachep->batchcount);
- seq_printf(m, " : slabdata %6lu %6lu %6u",
- active_slabs, num_slabs, cachep->lists.shared->avail);
+ cachep->shared);
+ seq_printf(m, " : slabdata %6lu %6lu %6lu",
+ active_slabs, num_slabs, shared_avail);
#if STATS
{ /* list3 stats */
unsigned long high = cachep->high_mark;
@@ -2975,12 +3464,13 @@ static int s_show(struct seq_file *m, void *p)
unsigned long reaped = cachep->reaped;
unsigned long errors = cachep->errors;
unsigned long max_freeable = cachep->max_freeable;
- unsigned long free_limit = cachep->free_limit;
unsigned long node_allocs = cachep->node_allocs;
+ unsigned long node_frees = cachep->node_frees;
- seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu",
- allocs, high, grown, reaped, errors,
- max_freeable, free_limit, node_allocs);
+ seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
+ %4lu %4lu %4lu %4lu",
+ allocs, high, grown, reaped, errors,
+ max_freeable, node_allocs, node_frees);
}
/* cpu stats */
{
@@ -3059,9 +3549,10 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
batchcount < 1 ||
batchcount > limit ||
shared < 0) {
- res = -EINVAL;
+ res = 0;
} else {
- res = do_tune_cpucache(cachep, limit, batchcount, shared);
+ res = do_tune_cpucache(cachep, limit,
+ batchcount, shared);
}
break;
}
@@ -3073,20 +3564,24 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
}
#endif
+/**
+ * ksize - get the actual amount of memory allocated for a given object
+ * @objp: Pointer to the object
+ *
+ * kmalloc may internally round up allocations and return more memory
+ * than requested. ksize() can be used to determine the actual amount of
+ * memory allocated. The caller may use this additional memory, even though
+ * a smaller amount of memory was initially specified with the kmalloc call.
+ * The caller must guarantee that objp points to a valid object previously
+ * allocated with either kmalloc() or kmem_cache_alloc(). The object
+ * must not be freed during the duration of the call.
+ */
unsigned int ksize(const void *objp)
{
- kmem_cache_t *c;
- unsigned long flags;
- unsigned int size = 0;
-
- if (likely(objp != NULL)) {
- local_irq_save(flags);
- c = GET_PAGE_CACHE(virt_to_page(objp));
- size = kmem_cache_size(c);
- local_irq_restore(flags);
- }
+ if (unlikely(objp == NULL))
+ return 0;
- return size;
+ return obj_reallen(GET_PAGE_CACHE(virt_to_page(objp)));
}
diff --git a/mm/sparse.c b/mm/sparse.c
index b54e304df4a7..347249a4917a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -6,6 +6,7 @@
#include <linux/mmzone.h>
#include <linux/bootmem.h>
#include <linux/module.h>
+#include <linux/spinlock.h>
#include <asm/dma.h>
/*
@@ -13,9 +14,64 @@
*
* 1) mem_section - memory sections, mem_map's for valid memory
*/
-struct mem_section mem_section[NR_MEM_SECTIONS];
+#ifdef CONFIG_SPARSEMEM_EXTREME
+struct mem_section *mem_section[NR_SECTION_ROOTS]
+ ____cacheline_maxaligned_in_smp;
+#else
+struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
+ ____cacheline_maxaligned_in_smp;
+#endif
EXPORT_SYMBOL(mem_section);
+#ifdef CONFIG_SPARSEMEM_EXTREME
+static struct mem_section *sparse_index_alloc(int nid)
+{
+ struct mem_section *section = NULL;
+ unsigned long array_size = SECTIONS_PER_ROOT *
+ sizeof(struct mem_section);
+
+ section = alloc_bootmem_node(NODE_DATA(nid), array_size);
+
+ if (section)
+ memset(section, 0, array_size);
+
+ return section;
+}
+
+static int sparse_index_init(unsigned long section_nr, int nid)
+{
+ static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED;
+ unsigned long root = SECTION_NR_TO_ROOT(section_nr);
+ struct mem_section *section;
+ int ret = 0;
+
+ if (mem_section[root])
+ return -EEXIST;
+
+ section = sparse_index_alloc(nid);
+ /*
+ * This lock keeps two different sections from
+ * reallocating for the same index
+ */
+ spin_lock(&index_init_lock);
+
+ if (mem_section[root]) {
+ ret = -EEXIST;
+ goto out;
+ }
+
+ mem_section[root] = section;
+out:
+ spin_unlock(&index_init_lock);
+ return ret;
+}
+#else /* !SPARSEMEM_EXTREME */
+static inline int sparse_index_init(unsigned long section_nr, int nid)
+{
+ return 0;
+}
+#endif
+
/* Record a memory area against a node. */
void memory_present(int nid, unsigned long start, unsigned long end)
{
@@ -24,8 +80,13 @@ void memory_present(int nid, unsigned long start, unsigned long end)
start &= PAGE_SECTION_MASK;
for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
unsigned long section = pfn_to_section_nr(pfn);
- if (!mem_section[section].section_mem_map)
- mem_section[section].section_mem_map = SECTION_MARKED_PRESENT;
+ struct mem_section *ms;
+
+ sparse_index_init(section, nid);
+
+ ms = __nr_to_section(section);
+ if (!ms->section_mem_map)
+ ms->section_mem_map = SECTION_MARKED_PRESENT;
}
}
@@ -85,6 +146,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
{
struct page *map;
int nid = early_pfn_to_nid(section_nr_to_pfn(pnum));
+ struct mem_section *ms = __nr_to_section(pnum);
map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
if (map)
@@ -96,7 +158,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
return map;
printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
- mem_section[pnum].section_mem_map = 0;
+ ms->section_mem_map = 0;
return NULL;
}
@@ -114,8 +176,9 @@ void sparse_init(void)
continue;
map = sparse_early_mem_map_alloc(pnum);
- if (map)
- sparse_init_one_section(&mem_section[pnum], pnum, map);
+ if (!map)
+ continue;
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map);
}
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 4f251775ef90..adbc2b426c2f 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -67,8 +67,8 @@ void show_swap_cache_info(void)
* __add_to_swap_cache resembles add_to_page_cache on swapper_space,
* but sets SwapCache flag and private instead of mapping and index.
*/
-static int __add_to_swap_cache(struct page *page,
- swp_entry_t entry, int gfp_mask)
+static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
+ unsigned int __nocast gfp_mask)
{
int error;
@@ -124,6 +124,7 @@ void __delete_from_swap_cache(struct page *page)
BUG_ON(!PageLocked(page));
BUG_ON(!PageSwapCache(page));
BUG_ON(PageWriteback(page));
+ BUG_ON(PagePrivate(page));
radix_tree_delete(&swapper_space.page_tree, page->private);
page->private = 0;
@@ -196,11 +197,6 @@ void delete_from_swap_cache(struct page *page)
{
swp_entry_t entry;
- BUG_ON(!PageSwapCache(page));
- BUG_ON(!PageLocked(page));
- BUG_ON(PageWriteback(page));
- BUG_ON(PagePrivate(page));
-
entry.val = page->private;
write_lock_irq(&swapper_space.tree_lock);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 60cd24a55204..0184f510aace 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -31,7 +31,7 @@
#include <asm/tlbflush.h>
#include <linux/swapops.h>
-DEFINE_SPINLOCK(swaplock);
+DEFINE_SPINLOCK(swap_lock);
unsigned int nr_swapfiles;
long total_swap_pages;
static int swap_overflow;
@@ -51,13 +51,11 @@ static DECLARE_MUTEX(swapon_sem);
/*
* We need this because the bdev->unplug_fn can sleep and we cannot
- * hold swap_list_lock while calling the unplug_fn. And swap_list_lock
+ * hold swap_lock while calling the unplug_fn. And swap_lock
* cannot be turned into a semaphore.
*/
static DECLARE_RWSEM(swap_unplug_sem);
-#define SWAPFILE_CLUSTER 256
-
void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page)
{
swp_entry_t entry;
@@ -84,116 +82,135 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page)
up_read(&swap_unplug_sem);
}
-static inline int scan_swap_map(struct swap_info_struct *si)
+#define SWAPFILE_CLUSTER 256
+#define LATENCY_LIMIT 256
+
+static inline unsigned long scan_swap_map(struct swap_info_struct *si)
{
- unsigned long offset;
+ unsigned long offset, last_in_cluster;
+ int latency_ration = LATENCY_LIMIT;
+
/*
- * We try to cluster swap pages by allocating them
- * sequentially in swap. Once we've allocated
- * SWAPFILE_CLUSTER pages this way, however, we resort to
- * first-free allocation, starting a new cluster. This
- * prevents us from scattering swap pages all over the entire
- * swap partition, so that we reduce overall disk seek times
- * between swap pages. -- sct */
- if (si->cluster_nr) {
- while (si->cluster_next <= si->highest_bit) {
- offset = si->cluster_next++;
+ * We try to cluster swap pages by allocating them sequentially
+ * in swap. Once we've allocated SWAPFILE_CLUSTER pages this
+ * way, however, we resort to first-free allocation, starting
+ * a new cluster. This prevents us from scattering swap pages
+ * all over the entire swap partition, so that we reduce
+ * overall disk seek times between swap pages. -- sct
+ * But we do now try to find an empty cluster. -Andrea
+ */
+
+ si->flags += SWP_SCANNING;
+ if (unlikely(!si->cluster_nr)) {
+ si->cluster_nr = SWAPFILE_CLUSTER - 1;
+ if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER)
+ goto lowest;
+ spin_unlock(&swap_lock);
+
+ offset = si->lowest_bit;
+ last_in_cluster = offset + SWAPFILE_CLUSTER - 1;
+
+ /* Locate the first empty (unaligned) cluster */
+ for (; last_in_cluster <= si->highest_bit; offset++) {
if (si->swap_map[offset])
- continue;
- si->cluster_nr--;
- goto got_page;
- }
- }
- si->cluster_nr = SWAPFILE_CLUSTER;
-
- /* try to find an empty (even not aligned) cluster. */
- offset = si->lowest_bit;
- check_next_cluster:
- if (offset+SWAPFILE_CLUSTER-1 <= si->highest_bit)
- {
- unsigned long nr;
- for (nr = offset; nr < offset+SWAPFILE_CLUSTER; nr++)
- if (si->swap_map[nr])
- {
- offset = nr+1;
- goto check_next_cluster;
+ last_in_cluster = offset + SWAPFILE_CLUSTER;
+ else if (offset == last_in_cluster) {
+ spin_lock(&swap_lock);
+ si->cluster_next = offset-SWAPFILE_CLUSTER-1;
+ goto cluster;
}
- /* We found a completly empty cluster, so start
- * using it.
- */
- goto got_page;
+ if (unlikely(--latency_ration < 0)) {
+ cond_resched();
+ latency_ration = LATENCY_LIMIT;
+ }
+ }
+ spin_lock(&swap_lock);
+ goto lowest;
}
- /* No luck, so now go finegrined as usual. -Andrea */
- for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) {
- if (si->swap_map[offset])
- continue;
- si->lowest_bit = offset+1;
- got_page:
+
+ si->cluster_nr--;
+cluster:
+ offset = si->cluster_next;
+ if (offset > si->highest_bit)
+lowest: offset = si->lowest_bit;
+checks: if (!(si->flags & SWP_WRITEOK))
+ goto no_page;
+ if (!si->highest_bit)
+ goto no_page;
+ if (!si->swap_map[offset]) {
if (offset == si->lowest_bit)
si->lowest_bit++;
if (offset == si->highest_bit)
si->highest_bit--;
- if (si->lowest_bit > si->highest_bit) {
+ si->inuse_pages++;
+ if (si->inuse_pages == si->pages) {
si->lowest_bit = si->max;
si->highest_bit = 0;
}
si->swap_map[offset] = 1;
- si->inuse_pages++;
- nr_swap_pages--;
- si->cluster_next = offset+1;
+ si->cluster_next = offset + 1;
+ si->flags -= SWP_SCANNING;
return offset;
}
- si->lowest_bit = si->max;
- si->highest_bit = 0;
+
+ spin_unlock(&swap_lock);
+ while (++offset <= si->highest_bit) {
+ if (!si->swap_map[offset]) {
+ spin_lock(&swap_lock);
+ goto checks;
+ }
+ if (unlikely(--latency_ration < 0)) {
+ cond_resched();
+ latency_ration = LATENCY_LIMIT;
+ }
+ }
+ spin_lock(&swap_lock);
+ goto lowest;
+
+no_page:
+ si->flags -= SWP_SCANNING;
return 0;
}
swp_entry_t get_swap_page(void)
{
- struct swap_info_struct * p;
- unsigned long offset;
- swp_entry_t entry;
- int type, wrapped = 0;
+ struct swap_info_struct *si;
+ pgoff_t offset;
+ int type, next;
+ int wrapped = 0;
- entry.val = 0; /* Out of memory */
- swap_list_lock();
- type = swap_list.next;
- if (type < 0)
- goto out;
+ spin_lock(&swap_lock);
if (nr_swap_pages <= 0)
- goto out;
+ goto noswap;
+ nr_swap_pages--;
+
+ for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) {
+ si = swap_info + type;
+ next = si->next;
+ if (next < 0 ||
+ (!wrapped && si->prio != swap_info[next].prio)) {
+ next = swap_list.head;
+ wrapped++;
+ }
- while (1) {
- p = &swap_info[type];
- if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
- swap_device_lock(p);
- offset = scan_swap_map(p);
- swap_device_unlock(p);
- if (offset) {
- entry = swp_entry(type,offset);
- type = swap_info[type].next;
- if (type < 0 ||
- p->prio != swap_info[type].prio) {
- swap_list.next = swap_list.head;
- } else {
- swap_list.next = type;
- }
- goto out;
- }
+ if (!si->highest_bit)
+ continue;
+ if (!(si->flags & SWP_WRITEOK))
+ continue;
+
+ swap_list.next = next;
+ offset = scan_swap_map(si);
+ if (offset) {
+ spin_unlock(&swap_lock);
+ return swp_entry(type, offset);
}
- type = p->next;
- if (!wrapped) {
- if (type < 0 || p->prio != swap_info[type].prio) {
- type = swap_list.head;
- wrapped = 1;
- }
- } else
- if (type < 0)
- goto out; /* out of swap space */
+ next = swap_list.next;
}
-out:
- swap_list_unlock();
- return entry;
+
+ nr_swap_pages++;
+noswap:
+ spin_unlock(&swap_lock);
+ return (swp_entry_t) {0};
}
static struct swap_info_struct * swap_info_get(swp_entry_t entry)
@@ -214,10 +231,7 @@ static struct swap_info_struct * swap_info_get(swp_entry_t entry)
goto bad_offset;
if (!p->swap_map[offset])
goto bad_free;
- swap_list_lock();
- if (p->prio > swap_info[swap_list.next].prio)
- swap_list.next = type;
- swap_device_lock(p);
+ spin_lock(&swap_lock);
return p;
bad_free:
@@ -235,12 +249,6 @@ out:
return NULL;
}
-static void swap_info_put(struct swap_info_struct * p)
-{
- swap_device_unlock(p);
- swap_list_unlock();
-}
-
static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
{
int count = p->swap_map[offset];
@@ -253,6 +261,8 @@ static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
p->lowest_bit = offset;
if (offset > p->highest_bit)
p->highest_bit = offset;
+ if (p->prio > swap_info[swap_list.next].prio)
+ swap_list.next = p - swap_info;
nr_swap_pages++;
p->inuse_pages--;
}
@@ -271,7 +281,7 @@ void swap_free(swp_entry_t entry)
p = swap_info_get(entry);
if (p) {
swap_entry_free(p, swp_offset(entry));
- swap_info_put(p);
+ spin_unlock(&swap_lock);
}
}
@@ -289,7 +299,7 @@ static inline int page_swapcount(struct page *page)
if (p) {
/* Subtract the 1 for the swap cache itself */
count = p->swap_map[swp_offset(entry)] - 1;
- swap_info_put(p);
+ spin_unlock(&swap_lock);
}
return count;
}
@@ -346,7 +356,7 @@ int remove_exclusive_swap_page(struct page *page)
}
write_unlock_irq(&swapper_space.tree_lock);
}
- swap_info_put(p);
+ spin_unlock(&swap_lock);
if (retval) {
swap_free(entry);
@@ -369,7 +379,7 @@ void free_swap_and_cache(swp_entry_t entry)
if (p) {
if (swap_entry_free(p, swp_offset(entry)) == 1)
page = find_trylock_page(&swapper_space, entry.val);
- swap_info_put(p);
+ spin_unlock(&swap_lock);
}
if (page) {
int one_user;
@@ -531,17 +541,18 @@ static int unuse_mm(struct mm_struct *mm,
* Scan swap_map from current position to next entry still in use.
* Recycle to start on reaching the end, returning 0 when empty.
*/
-static int find_next_to_unuse(struct swap_info_struct *si, int prev)
+static unsigned int find_next_to_unuse(struct swap_info_struct *si,
+ unsigned int prev)
{
- int max = si->max;
- int i = prev;
+ unsigned int max = si->max;
+ unsigned int i = prev;
int count;
/*
- * No need for swap_device_lock(si) here: we're just looking
+ * No need for swap_lock here: we're just looking
* for whether an entry is in use, not modifying it; false
* hits are okay, and sys_swapoff() has already prevented new
- * allocations from this area (while holding swap_list_lock()).
+ * allocations from this area (while holding swap_lock).
*/
for (;;) {
if (++i >= max) {
@@ -577,7 +588,7 @@ static int try_to_unuse(unsigned int type)
unsigned short swcount;
struct page *page;
swp_entry_t entry;
- int i = 0;
+ unsigned int i = 0;
int retval = 0;
int reset_overflow = 0;
int shmem;
@@ -731,9 +742,9 @@ static int try_to_unuse(unsigned int type)
* report them; but do report if we reset SWAP_MAP_MAX.
*/
if (*swap_map == SWAP_MAP_MAX) {
- swap_device_lock(si);
+ spin_lock(&swap_lock);
*swap_map = 1;
- swap_device_unlock(si);
+ spin_unlock(&swap_lock);
reset_overflow = 1;
}
@@ -797,9 +808,9 @@ static int try_to_unuse(unsigned int type)
}
/*
- * After a successful try_to_unuse, if no swap is now in use, we know we
- * can empty the mmlist. swap_list_lock must be held on entry and exit.
- * Note that mmlist_lock nests inside swap_list_lock, and an mm must be
+ * After a successful try_to_unuse, if no swap is now in use, we know
+ * we can empty the mmlist. swap_lock must be held on entry and exit.
+ * Note that mmlist_lock nests inside swap_lock, and an mm must be
* added to the mmlist just after page_duplicate - before would be racy.
*/
static void drain_mmlist(void)
@@ -832,9 +843,9 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset)
offset < (se->start_page + se->nr_pages)) {
return se->start_block + (offset - se->start_page);
}
- lh = se->list.prev;
+ lh = se->list.next;
if (lh == &sis->extent_list)
- lh = lh->prev;
+ lh = lh->next;
se = list_entry(lh, struct swap_extent, list);
sis->curr_swap_extent = se;
BUG_ON(se == start_se); /* It *must* be present */
@@ -854,15 +865,13 @@ static void destroy_swap_extents(struct swap_info_struct *sis)
list_del(&se->list);
kfree(se);
}
- sis->nr_extents = 0;
}
/*
* Add a block range (and the corresponding page range) into this swapdev's
- * extent list. The extent list is kept sorted in block order.
+ * extent list. The extent list is kept sorted in page order.
*
- * This function rather assumes that it is called in ascending sector_t order.
- * It doesn't look for extent coalescing opportunities.
+ * This function rather assumes that it is called in ascending page order.
*/
static int
add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
@@ -872,16 +881,15 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
struct swap_extent *new_se;
struct list_head *lh;
- lh = sis->extent_list.next; /* The highest-addressed block */
- while (lh != &sis->extent_list) {
+ lh = sis->extent_list.prev; /* The highest page extent */
+ if (lh != &sis->extent_list) {
se = list_entry(lh, struct swap_extent, list);
- if (se->start_block + se->nr_pages == start_block &&
- se->start_page + se->nr_pages == start_page) {
+ BUG_ON(se->start_page + se->nr_pages != start_page);
+ if (se->start_block + se->nr_pages == start_block) {
/* Merge it */
se->nr_pages += nr_pages;
return 0;
}
- lh = lh->next;
}
/*
@@ -894,16 +902,8 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
new_se->nr_pages = nr_pages;
new_se->start_block = start_block;
- lh = sis->extent_list.prev; /* The lowest block */
- while (lh != &sis->extent_list) {
- se = list_entry(lh, struct swap_extent, list);
- if (se->start_block > start_block)
- break;
- lh = lh->prev;
- }
- list_add_tail(&new_se->list, lh);
- sis->nr_extents++;
- return 0;
+ list_add_tail(&new_se->list, &sis->extent_list);
+ return 1;
}
/*
@@ -926,7 +926,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
* requirements, they are simply tossed out - we will never use those blocks
* for swapping.
*
- * For S_ISREG swapfiles we hold i_sem across the life of the swapon. This
+ * For S_ISREG swapfiles we set S_SWAPFILE across the life of the swapon. This
* prevents root from shooting her foot off by ftruncating an in-use swapfile,
* which will scribble on the fs.
*
@@ -937,7 +937,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
* This is extremely effective. The average number of iterations in
* map_swap_page() has been measured at about 0.3 per page. - akpm.
*/
-static int setup_swap_extents(struct swap_info_struct *sis)
+static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
{
struct inode *inode;
unsigned blocks_per_page;
@@ -945,11 +945,15 @@ static int setup_swap_extents(struct swap_info_struct *sis)
unsigned blkbits;
sector_t probe_block;
sector_t last_block;
+ sector_t lowest_block = -1;
+ sector_t highest_block = 0;
+ int nr_extents = 0;
int ret;
inode = sis->swap_file->f_mapping->host;
if (S_ISBLK(inode->i_mode)) {
ret = add_swap_extent(sis, 0, sis->max, 0);
+ *span = sis->pages;
goto done;
}
@@ -994,22 +998,32 @@ static int setup_swap_extents(struct swap_info_struct *sis)
}
}
+ first_block >>= (PAGE_SHIFT - blkbits);
+ if (page_no) { /* exclude the header page */
+ if (first_block < lowest_block)
+ lowest_block = first_block;
+ if (first_block > highest_block)
+ highest_block = first_block;
+ }
+
/*
* We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
*/
- ret = add_swap_extent(sis, page_no, 1,
- first_block >> (PAGE_SHIFT - blkbits));
- if (ret)
+ ret = add_swap_extent(sis, page_no, 1, first_block);
+ if (ret < 0)
goto out;
+ nr_extents += ret;
page_no++;
probe_block += blocks_per_page;
reprobe:
continue;
}
- ret = 0;
+ ret = nr_extents;
+ *span = 1 + highest_block - lowest_block;
if (page_no == 0)
- ret = -EINVAL;
+ page_no = 1; /* force Empty message */
sis->max = page_no;
+ sis->pages = page_no - 1;
sis->highest_bit = page_no - 1;
done:
sis->curr_swap_extent = list_entry(sis->extent_list.prev,
@@ -1069,7 +1083,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
mapping = victim->f_mapping;
prev = -1;
- swap_list_lock();
+ spin_lock(&swap_lock);
for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
p = swap_info + type;
if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
@@ -1080,14 +1094,14 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
}
if (type < 0) {
err = -EINVAL;
- swap_list_unlock();
+ spin_unlock(&swap_lock);
goto out_dput;
}
if (!security_vm_enough_memory(p->pages))
vm_unacct_memory(p->pages);
else {
err = -ENOMEM;
- swap_list_unlock();
+ spin_unlock(&swap_lock);
goto out_dput;
}
if (prev < 0) {
@@ -1102,18 +1116,15 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
nr_swap_pages -= p->pages;
total_swap_pages -= p->pages;
p->flags &= ~SWP_WRITEOK;
- swap_list_unlock();
+ spin_unlock(&swap_lock);
+
current->flags |= PF_SWAPOFF;
err = try_to_unuse(type);
current->flags &= ~PF_SWAPOFF;
- /* wait for any unplug function to finish */
- down_write(&swap_unplug_sem);
- up_write(&swap_unplug_sem);
-
if (err) {
/* re-insert swap space back into swap_list */
- swap_list_lock();
+ spin_lock(&swap_lock);
for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next)
if (p->prio >= swap_info[i].prio)
break;
@@ -1125,22 +1136,34 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
nr_swap_pages += p->pages;
total_swap_pages += p->pages;
p->flags |= SWP_WRITEOK;
- swap_list_unlock();
+ spin_unlock(&swap_lock);
goto out_dput;
}
+
+ /* wait for any unplug function to finish */
+ down_write(&swap_unplug_sem);
+ up_write(&swap_unplug_sem);
+
+ destroy_swap_extents(p);
down(&swapon_sem);
- swap_list_lock();
+ spin_lock(&swap_lock);
drain_mmlist();
- swap_device_lock(p);
+
+ /* wait for anyone still in scan_swap_map */
+ p->highest_bit = 0; /* cuts scans short */
+ while (p->flags >= SWP_SCANNING) {
+ spin_unlock(&swap_lock);
+ schedule_timeout_uninterruptible(1);
+ spin_lock(&swap_lock);
+ }
+
swap_file = p->swap_file;
p->swap_file = NULL;
p->max = 0;
swap_map = p->swap_map;
p->swap_map = NULL;
p->flags = 0;
- destroy_swap_extents(p);
- swap_device_unlock(p);
- swap_list_unlock();
+ spin_unlock(&swap_lock);
up(&swapon_sem);
vfree(swap_map);
inode = mapping->host;
@@ -1213,7 +1236,7 @@ static int swap_show(struct seq_file *swap, void *v)
file = ptr->swap_file;
len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\");
- seq_printf(swap, "%*s%s\t%d\t%ld\t%d\n",
+ seq_printf(swap, "%*s%s\t%u\t%u\t%d\n",
len < 40 ? 40 - len : 1, " ",
S_ISBLK(file->f_dentry->d_inode->i_mode) ?
"partition" : "file\t",
@@ -1272,7 +1295,9 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
static int least_priority;
union swap_header *swap_header = NULL;
int swap_header_version;
- int nr_good_pages = 0;
+ unsigned int nr_good_pages = 0;
+ int nr_extents = 0;
+ sector_t span;
unsigned long maxpages = 1;
int swapfilesize;
unsigned short *swap_map;
@@ -1282,7 +1307,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- swap_list_lock();
+ spin_lock(&swap_lock);
p = swap_info;
for (type = 0 ; type < nr_swapfiles ; type++,p++)
if (!(p->flags & SWP_USED))
@@ -1301,14 +1326,13 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
* swp_entry_t or the architecture definition of a swap pte.
*/
if (type > swp_type(pte_to_swp_entry(swp_entry_to_pte(swp_entry(~0UL,0))))) {
- swap_list_unlock();
+ spin_unlock(&swap_lock);
goto out;
}
if (type >= nr_swapfiles)
nr_swapfiles = type+1;
INIT_LIST_HEAD(&p->extent_list);
p->flags = SWP_USED;
- p->nr_extents = 0;
p->swap_file = NULL;
p->old_block_size = 0;
p->swap_map = NULL;
@@ -1316,7 +1340,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
p->highest_bit = 0;
p->cluster_nr = 0;
p->inuse_pages = 0;
- spin_lock_init(&p->sdev_lock);
p->next = -1;
if (swap_flags & SWAP_FLAG_PREFER) {
p->prio =
@@ -1324,7 +1347,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
} else {
p->prio = --least_priority;
}
- swap_list_unlock();
+ spin_unlock(&swap_lock);
name = getname(specialfile);
error = PTR_ERR(name);
if (IS_ERR(name)) {
@@ -1426,6 +1449,8 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
}
p->lowest_bit = 1;
+ p->cluster_next = 1;
+
/*
* Find out how many pages are allowed for a single swap
* device. There are two limiting factors: 1) the number of
@@ -1446,6 +1471,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
p->highest_bit = maxpages - 1;
error = -EINVAL;
+ if (!maxpages)
+ goto bad_swap;
+ if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode))
+ goto bad_swap;
if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
goto bad_swap;
@@ -1470,35 +1499,40 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
if (error)
goto bad_swap;
}
-
+
if (swapfilesize && maxpages > swapfilesize) {
printk(KERN_WARNING
"Swap area shorter than signature indicates\n");
error = -EINVAL;
goto bad_swap;
}
+ if (nr_good_pages) {
+ p->swap_map[0] = SWAP_MAP_BAD;
+ p->max = maxpages;
+ p->pages = nr_good_pages;
+ nr_extents = setup_swap_extents(p, &span);
+ if (nr_extents < 0) {
+ error = nr_extents;
+ goto bad_swap;
+ }
+ nr_good_pages = p->pages;
+ }
if (!nr_good_pages) {
printk(KERN_WARNING "Empty swap-file\n");
error = -EINVAL;
goto bad_swap;
}
- p->swap_map[0] = SWAP_MAP_BAD;
- p->max = maxpages;
- p->pages = nr_good_pages;
-
- error = setup_swap_extents(p);
- if (error)
- goto bad_swap;
down(&swapon_sem);
- swap_list_lock();
- swap_device_lock(p);
+ spin_lock(&swap_lock);
p->flags = SWP_ACTIVE;
nr_swap_pages += nr_good_pages;
total_swap_pages += nr_good_pages;
- printk(KERN_INFO "Adding %dk swap on %s. Priority:%d extents:%d\n",
- nr_good_pages<<(PAGE_SHIFT-10), name,
- p->prio, p->nr_extents);
+
+ printk(KERN_INFO "Adding %uk swap on %s. "
+ "Priority:%d extents:%d across:%lluk\n",
+ nr_good_pages<<(PAGE_SHIFT-10), name, p->prio,
+ nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10));
/* insert swap space into swap_list: */
prev = -1;
@@ -1514,8 +1548,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
} else {
swap_info[prev].next = p - swap_info;
}
- swap_device_unlock(p);
- swap_list_unlock();
+ spin_unlock(&swap_lock);
up(&swapon_sem);
error = 0;
goto out;
@@ -1524,16 +1557,16 @@ bad_swap:
set_blocksize(bdev, p->old_block_size);
bd_release(bdev);
}
+ destroy_swap_extents(p);
bad_swap_2:
- swap_list_lock();
+ spin_lock(&swap_lock);
swap_map = p->swap_map;
p->swap_file = NULL;
p->swap_map = NULL;
p->flags = 0;
if (!(swap_flags & SWAP_FLAG_PREFER))
++least_priority;
- swap_list_unlock();
- destroy_swap_extents(p);
+ spin_unlock(&swap_lock);
vfree(swap_map);
if (swap_file)
filp_close(swap_file, NULL);
@@ -1557,7 +1590,7 @@ void si_swapinfo(struct sysinfo *val)
unsigned int i;
unsigned long nr_to_be_unused = 0;
- swap_list_lock();
+ spin_lock(&swap_lock);
for (i = 0; i < nr_swapfiles; i++) {
if (!(swap_info[i].flags & SWP_USED) ||
(swap_info[i].flags & SWP_WRITEOK))
@@ -1566,7 +1599,7 @@ void si_swapinfo(struct sysinfo *val)
}
val->freeswap = nr_swap_pages + nr_to_be_unused;
val->totalswap = total_swap_pages + nr_to_be_unused;
- swap_list_unlock();
+ spin_unlock(&swap_lock);
}
/*
@@ -1587,7 +1620,7 @@ int swap_duplicate(swp_entry_t entry)
p = type + swap_info;
offset = swp_offset(entry);
- swap_device_lock(p);
+ spin_lock(&swap_lock);
if (offset < p->max && p->swap_map[offset]) {
if (p->swap_map[offset] < SWAP_MAP_MAX - 1) {
p->swap_map[offset]++;
@@ -1599,7 +1632,7 @@ int swap_duplicate(swp_entry_t entry)
result = 1;
}
}
- swap_device_unlock(p);
+ spin_unlock(&swap_lock);
out:
return result;
@@ -1615,7 +1648,7 @@ get_swap_info_struct(unsigned type)
}
/*
- * swap_device_lock prevents swap_map being freed. Don't grab an extra
+ * swap_lock prevents swap_map being freed. Don't grab an extra
* reference on the swaphandle, it doesn't matter if it becomes unused.
*/
int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
@@ -1631,7 +1664,7 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
toff++, i--;
*offset = toff;
- swap_device_lock(swapdev);
+ spin_lock(&swap_lock);
do {
/* Don't read-ahead past the end of the swap area */
if (toff >= swapdev->max)
@@ -1644,6 +1677,6 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
toff++;
ret++;
} while (--i);
- swap_device_unlock(swapdev);
+ spin_unlock(&swap_lock);
return ret;
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 8ff16a1eee6a..13c3d82968ae 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -158,8 +158,6 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
return err;
}
-#define IOREMAP_MAX_ORDER (7 + PAGE_SHIFT) /* 128 pages */
-
struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end)
{
@@ -334,9 +332,10 @@ void __vunmap(void *addr, int deallocate_pages)
* @addr: memory base address
*
* Free the virtually contiguous memory area starting at @addr, as
- * obtained from vmalloc(), vmalloc_32() or __vmalloc().
+ * obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
+ * NULL, no operation is performed.
*
- * May not be called in interrupt context.
+ * Must not be called in interrupt context.
*/
void vfree(void *addr)
{
@@ -354,7 +353,7 @@ EXPORT_SYMBOL(vfree);
* Free the virtually contiguous memory area starting at @addr,
* which was created from the page array passed to vmap().
*
- * May not be called in interrupt context.
+ * Must not be called in interrupt context.
*/
void vunmap(void *addr)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index cfffe5098d53..0ea71e887bb6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -822,6 +822,8 @@ shrink_zone(struct zone *zone, struct scan_control *sc)
unsigned long nr_active;
unsigned long nr_inactive;
+ atomic_inc(&zone->reclaim_in_progress);
+
/*
* Add one to `nr_to_scan' just to make sure that the kernel will
* slowly sift through the active list.
@@ -861,6 +863,8 @@ shrink_zone(struct zone *zone, struct scan_control *sc)
}
throttle_vm_writeout();
+
+ atomic_dec(&zone->reclaim_in_progress);
}
/*
@@ -890,7 +894,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
if (zone->present_pages == 0)
continue;
- if (!cpuset_zone_allowed(zone))
+ if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
continue;
zone->temp_priority = sc->priority;
@@ -900,9 +904,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
if (zone->all_unreclaimable && sc->priority != DEF_PRIORITY)
continue; /* Let kswapd poll it */
- atomic_inc(&zone->reclaim_in_progress);
shrink_zone(zone, sc);
- atomic_dec(&zone->reclaim_in_progress);
}
}
@@ -938,7 +940,7 @@ int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone))
+ if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
continue;
zone->temp_priority = DEF_PRIORITY;
@@ -984,7 +986,7 @@ out:
for (i = 0; zones[i] != 0; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone))
+ if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
continue;
zone->prev_priority = zone->temp_priority;
@@ -1254,11 +1256,11 @@ void wakeup_kswapd(struct zone *zone, int order)
return;
if (pgdat->kswapd_max_order < order)
pgdat->kswapd_max_order = order;
- if (!cpuset_zone_allowed(zone))
+ if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
return;
- if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+ if (!waitqueue_active(&pgdat->kswapd_wait))
return;
- wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
+ wake_up_interruptible(&pgdat->kswapd_wait);
}
#ifdef CONFIG_PM
@@ -1358,14 +1360,13 @@ int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
sc.swap_cluster_max = SWAP_CLUSTER_MAX;
/* Don't reclaim the zone if there are other reclaimers active */
- if (!atomic_inc_and_test(&zone->reclaim_in_progress))
+ if (atomic_read(&zone->reclaim_in_progress) > 0)
goto out;
shrink_zone(zone, &sc);
total_reclaimed = sc.nr_reclaimed;
out:
- atomic_dec(&zone->reclaim_in_progress);
return total_reclaimed;
}
@@ -1375,6 +1376,9 @@ asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone,
struct zone *z;
int i;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
if (node >= MAX_NUMNODES || !node_online(node))
return -EINVAL;
diff --git a/net/802/fc.c b/net/802/fc.c
index 640d34e026c2..282c4ab1abe6 100644
--- a/net/802/fc.c
+++ b/net/802/fc.c
@@ -87,7 +87,7 @@ static int fc_rebuild_header(struct sk_buff *skb)
struct fch_hdr *fch=(struct fch_hdr *)skb->data;
struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
if(fcllc->ethertype != htons(ETH_P_IP)) {
- printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(fcllc->ethertype));
+ printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype));
return 0;
}
#ifdef CONFIG_INET
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 5ce24c4bb840..ac242a4bc346 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -108,8 +108,8 @@ static int fddi_rebuild_header(struct sk_buff *skb)
else
#endif
{
- printk("%s: Don't know how to resolve type %02X addresses.\n",
- skb->dev->name, htons(fddi->hdr.llc_snap.ethertype));
+ printk("%s: Don't know how to resolve type %04X addresses.\n",
+ skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype));
return(0);
}
}
diff --git a/net/802/hippi.c b/net/802/hippi.c
index 051e8af56a77..6d7fed3dd99a 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -51,6 +51,7 @@ static int hippi_header(struct sk_buff *skb, struct net_device *dev,
unsigned len)
{
struct hippi_hdr *hip = (struct hippi_hdr *)skb_push(skb, HIPPI_HLEN);
+ struct hippi_cb *hcb = (struct hippi_cb *) skb->cb;
if (!len){
len = skb->len - HIPPI_HLEN;
@@ -84,9 +85,10 @@ static int hippi_header(struct sk_buff *skb, struct net_device *dev,
if (daddr)
{
memcpy(hip->le.dest_switch_addr, daddr + 3, 3);
- memcpy(&skb->private.ifield, daddr + 2, 4);
+ memcpy(&hcb->ifield, daddr + 2, 4);
return HIPPI_HLEN;
}
+ hcb->ifield = 0;
return -((int)HIPPI_HLEN);
}
@@ -122,7 +124,7 @@ static int hippi_rebuild_header(struct sk_buff *skb)
* Determine the packet's protocol ID.
*/
-unsigned short hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
+__be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct hippi_hdr *hip;
diff --git a/net/802/p8022.c b/net/802/p8022.c
index 5ae63416df6d..b24817c63ca8 100644
--- a/net/802/p8022.c
+++ b/net/802/p8022.c
@@ -35,7 +35,8 @@ static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
struct datalink_proto *register_8022_client(unsigned char type,
int (*func)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt))
+ struct packet_type *pt,
+ struct net_device *orig_dev))
{
struct datalink_proto *proto;
diff --git a/net/802/p8023.c b/net/802/p8023.c
index a0b61b40225f..6368d3dce444 100644
--- a/net/802/p8023.c
+++ b/net/802/p8023.c
@@ -20,6 +20,7 @@
#include <linux/skbuff.h>
#include <net/datalink.h>
+#include <net/p8022.h>
/*
* Place an 802.3 header on a packet. The driver will do the mac
diff --git a/net/802/psnap.c b/net/802/psnap.c
index 1053821ddf93..ab80b1fab53c 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -47,7 +47,7 @@ static struct datalink_proto *find_snap_client(unsigned char *desc)
* A SNAP packet has arrived
*/
static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt, struct net_device *orig_dev)
{
int rc = 1;
struct datalink_proto *proto;
@@ -61,7 +61,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
/* Pass the frame on. */
skb->h.raw += 5;
skb_pull(skb, 5);
- rc = proto->rcvfunc(skb, dev, &snap_packet_type);
+ rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev);
} else {
skb->sk = NULL;
kfree_skb(skb);
@@ -118,7 +118,8 @@ module_exit(snap_exit);
struct datalink_proto *register_snap_client(unsigned char *desc,
int (*rcvfunc)(struct sk_buff *,
struct net_device *,
- struct packet_type *))
+ struct packet_type *,
+ struct net_device *))
{
struct datalink_proto *proto = NULL;
diff --git a/net/802/sysctl_net_802.c b/net/802/sysctl_net_802.c
index 36079630c49f..700129556c13 100644
--- a/net/802/sysctl_net_802.c
+++ b/net/802/sysctl_net_802.c
@@ -10,9 +10,10 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/config.h>
#include <linux/mm.h>
+#include <linux/if_tr.h>
#include <linux/sysctl.h>
-#include <linux/config.h>
#ifdef CONFIG_TR
extern int sysctl_tr_rif_timeout;
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 508b1fa14546..9ae3a14dd016 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -51,7 +51,7 @@ struct net_device *__find_vlan_dev(struct net_device* real_dev,
/* found in vlan_dev.c */
int vlan_dev_rebuild_header(struct sk_buff *skb);
int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type* ptype);
+ struct packet_type *ptype, struct net_device *orig_dev);
int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 49c487413518..145f5cde96cf 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -113,7 +113,7 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
*
*/
int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type* ptype)
+ struct packet_type* ptype, struct net_device *orig_dev)
{
unsigned char *rawp = NULL;
struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
diff --git a/net/Kconfig b/net/Kconfig
index 40a31ba86d2c..2bdd5623fdd5 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -147,6 +147,7 @@ source "net/bridge/netfilter/Kconfig"
endif
+source "net/dccp/Kconfig"
source "net/sctp/Kconfig"
source "net/atm/Kconfig"
source "net/bridge/Kconfig"
@@ -205,6 +206,8 @@ config NET_PKTGEN
To compile this code as a module, choose M here: the
module will be called pktgen.
+source "net/netfilter/Kconfig"
+
endmenu
endmenu
@@ -212,6 +215,7 @@ endmenu
source "net/ax25/Kconfig"
source "net/irda/Kconfig"
source "net/bluetooth/Kconfig"
+source "net/ieee80211/Kconfig"
endif # if NET
endmenu # Networking
diff --git a/net/Makefile b/net/Makefile
index 8e2bdc025ab8..4aa2f46d2a56 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_NET) += $(tmp-y)
obj-$(CONFIG_LLC) += llc/
obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/
obj-$(CONFIG_INET) += ipv4/
+obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
ifneq ($(CONFIG_IPV6),)
@@ -41,7 +42,9 @@ obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_DECNET) += decnet/
obj-$(CONFIG_ECONET) += econet/
obj-$(CONFIG_VLAN_8021Q) += 8021q/
+obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
+obj-$(CONFIG_IEEE80211) += ieee80211/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index c34614ea5fce..7076097debc2 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -698,7 +698,7 @@ static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a,
* frame. We currently only support Ethernet.
*/
static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct elapaarp *ea = aarp_hdr(skb);
int hash, ret = 0;
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 192b529f86a4..1d31b3a3f1e5 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -53,12 +53,12 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/tcp.h>
#include <linux/if_arp.h>
#include <linux/termios.h> /* For TIOCOUTQ/INQ */
#include <net/datalink.h>
#include <net/psnap.h>
#include <net/sock.h>
+#include <net/tcp_states.h>
#include <net/route.h>
#include <linux/atalk.h>
@@ -1390,7 +1390,7 @@ free_it:
* [ie ARPHRD_ETHERTALK]
*/
static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct ddpehdr *ddp;
struct sock *sock;
@@ -1482,7 +1482,7 @@ freeit:
* header and append a long one.
*/
static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt, struct net_device *orig_dev)
{
/* Expand any short form frames */
if (skb->mac.raw[2] == 1) {
@@ -1528,7 +1528,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
}
skb->h.raw = skb->data;
- return atalk_rcv(skb, dev, pt);
+ return atalk_rcv(skb, dev, pt, orig_dev);
freeit:
kfree_skb(skb);
return 0;
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 4dbb5af34a5e..d89056ec44d4 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -21,6 +21,7 @@
#include "resources.h"
#include "signaling.h" /* for WAITING and sigd_attach */
+#include "common.h"
static DECLARE_MUTEX(ioctl_mutex);
diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c
index 181a3002d8ad..4b1faca5013f 100644
--- a/net/atm/ipcommon.c
+++ b/net/atm/ipcommon.c
@@ -34,7 +34,6 @@
void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
{
- struct sk_buff *skb;
unsigned long flags;
struct sk_buff *skb_from = (struct sk_buff *) from;
struct sk_buff *skb_to = (struct sk_buff *) to;
@@ -47,8 +46,6 @@ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
prev->next = skb_to;
to->prev->next = from->next;
to->prev = from->prev;
- for (skb = from->next; skb != skb_to; skb = skb->next)
- skb->list = to;
to->qlen += from->qlen;
spin_unlock(&to->lock);
from->prev = skb_from;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 17a81ebe7e6e..526d9531411f 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -105,7 +105,7 @@ extern void mpc_proc_clean(void);
struct mpoa_client *mpcs = NULL; /* FIXME */
static struct atm_mpoa_qos *qos_head = NULL;
-static struct timer_list mpc_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mpc_timer, NULL, 0, 0);
static struct mpoa_client *find_mpc_by_itfnum(int itf)
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index a5c94f11547c..8e37e71e34ff 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -45,7 +45,7 @@
#include <linux/sysctl.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -1695,16 +1695,12 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
amount = skb->len;
- res = put_user(amount, (int __user *)argp);
+ res = put_user(amount, (int __user *) argp);
break;
}
case SIOCGSTAMP:
- if (sk != NULL) {
- res = sock_get_timestamp(sk, argp);
- break;
- }
- res = -EINVAL;
+ res = sock_get_timestamp(sk, argp);
break;
case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */
@@ -1874,6 +1870,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v)
static int ax25_info_show(struct seq_file *seq, void *v)
{
ax25_cb *ax25 = v;
+ char buf[11];
int k;
@@ -1885,13 +1882,13 @@ static int ax25_info_show(struct seq_file *seq, void *v)
seq_printf(seq, "%8.8lx %s %s%s ",
(long) ax25,
ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
- ax2asc(&ax25->source_addr),
+ ax2asc(buf, &ax25->source_addr),
ax25->iamdigi? "*":"");
- seq_printf(seq, "%s", ax2asc(&ax25->dest_addr));
+ seq_printf(seq, "%s", ax2asc(buf, &ax25->dest_addr));
for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
seq_printf(seq, ",%s%s",
- ax2asc(&ax25->digipeat->calls[k]),
+ ax2asc(buf, &ax25->digipeat->calls[k]),
ax25->digipeat->repeated[k]? "*":"");
}
@@ -1950,24 +1947,24 @@ static struct net_proto_family ax25_family_ops = {
};
static struct proto_ops ax25_proto_ops = {
- .family = PF_AX25,
- .owner = THIS_MODULE,
- .release = ax25_release,
- .bind = ax25_bind,
- .connect = ax25_connect,
- .socketpair = sock_no_socketpair,
- .accept = ax25_accept,
- .getname = ax25_getname,
- .poll = datagram_poll,
- .ioctl = ax25_ioctl,
- .listen = ax25_listen,
- .shutdown = ax25_shutdown,
- .setsockopt = ax25_setsockopt,
- .getsockopt = ax25_getsockopt,
- .sendmsg = ax25_sendmsg,
- .recvmsg = ax25_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
+ .family = PF_AX25,
+ .owner = THIS_MODULE,
+ .release = ax25_release,
+ .bind = ax25_bind,
+ .connect = ax25_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = ax25_accept,
+ .getname = ax25_getname,
+ .poll = datagram_poll,
+ .ioctl = ax25_ioctl,
+ .listen = ax25_listen,
+ .shutdown = ax25_shutdown,
+ .setsockopt = ax25_setsockopt,
+ .getsockopt = ax25_getsockopt,
+ .sendmsg = ax25_sendmsg,
+ .recvmsg = ax25_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
};
/*
@@ -1983,7 +1980,7 @@ static struct notifier_block ax25_dev_notifier = {
.notifier_call =ax25_device_event,
};
-EXPORT_SYMBOL(ax25_encapsulate);
+EXPORT_SYMBOL(ax25_hard_header);
EXPORT_SYMBOL(ax25_rebuild_header);
EXPORT_SYMBOL(ax25_findbyuid);
EXPORT_SYMBOL(ax25_find_cb);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index f4fa6dfb846e..0164a155b8c4 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -36,9 +36,8 @@ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
/*
* ax25 -> ascii conversion
*/
-char *ax2asc(ax25_address *a)
+char *ax2asc(char *buf, ax25_address *a)
{
- static char buf[11];
char c, *s;
int n;
@@ -68,37 +67,34 @@ char *ax2asc(ax25_address *a)
/*
* ascii -> ax25 conversion
*/
-ax25_address *asc2ax(char *callsign)
+void asc2ax(ax25_address *addr, char *callsign)
{
- static ax25_address addr;
char *s;
int n;
for (s = callsign, n = 0; n < 6; n++) {
if (*s != '\0' && *s != '-')
- addr.ax25_call[n] = *s++;
+ addr->ax25_call[n] = *s++;
else
- addr.ax25_call[n] = ' ';
- addr.ax25_call[n] <<= 1;
- addr.ax25_call[n] &= 0xFE;
+ addr->ax25_call[n] = ' ';
+ addr->ax25_call[n] <<= 1;
+ addr->ax25_call[n] &= 0xFE;
}
if (*s++ == '\0') {
- addr.ax25_call[6] = 0x00;
- return &addr;
+ addr->ax25_call[6] = 0x00;
+ return;
}
- addr.ax25_call[6] = *s++ - '0';
+ addr->ax25_call[6] = *s++ - '0';
if (*s != '\0') {
- addr.ax25_call[6] *= 10;
- addr.ax25_call[6] += *s++ - '0';
+ addr->ax25_call[6] *= 10;
+ addr->ax25_call[6] += *s++ - '0';
}
- addr.ax25_call[6] <<= 1;
- addr.ax25_call[6] &= 0x1E;
-
- return &addr;
+ addr->ax25_call[6] <<= 1;
+ addr->ax25_call[6] &= 0x1E;
}
/*
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index 8adc0022cf58..edcaa897027c 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -22,8 +22,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/ip.h> /* For ip_rcv */
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 3a8b67316fc3..061083efc1dc 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -18,7 +18,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index 3dc808fde33f..810c9c76c2e0 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -9,7 +9,6 @@
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
* Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -26,9 +25,7 @@
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <net/sock.h>
-#include <net/ip.h> /* For ip_rcv */
-#include <net/tcp.h>
-#include <net/arp.h> /* For arp_rcv */
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
@@ -114,7 +111,6 @@ int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
pid = *skb->data;
-#ifdef CONFIG_INET
if (pid == AX25_P_IP) {
/* working around a TCP bug to keep additional listeners
* happy. TCP re-uses the buffer and destroys the original
@@ -132,10 +128,9 @@ int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
skb->dev = ax25->ax25_dev->dev;
skb->pkt_type = PACKET_HOST;
skb->protocol = htons(ETH_P_IP);
- ip_rcv(skb, skb->dev, NULL); /* Wrong ptype */
+ netif_rx(skb);
return 1;
}
-#endif
if (pid == AX25_P_SEGMENT) {
skb_pull(skb, 1); /* Remove PID */
return ax25_rx_fragment(ax25, skb);
@@ -250,7 +245,6 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
/* Now we are pointing at the pid byte */
switch (skb->data[1]) {
-#ifdef CONFIG_INET
case AX25_P_IP:
skb_pull(skb,2); /* drop PID/CTRL */
skb->h.raw = skb->data;
@@ -258,7 +252,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
skb->protocol = htons(ETH_P_IP);
- ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */
+ netif_rx(skb);
break;
case AX25_P_ARP:
@@ -268,9 +262,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
skb->protocol = htons(ETH_P_ARP);
- arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */
+ netif_rx(skb);
break;
-#endif
case AX25_P_TEXT:
/* Now find a suitable dgram socket */
sk = ax25_get_socket(&dest, &src, SOCK_DGRAM);
@@ -454,7 +447,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
* Receive an AX.25 frame via a SLIP interface.
*/
int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype)
+ struct packet_type *ptype, struct net_device *orig_dev)
{
skb->sk = NULL; /* Initially we don't know who it's for */
skb->destructor = NULL; /* Who initializes this, dammit?! */
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index bba0173e2d65..d643dac3eccc 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -47,7 +47,7 @@
#ifdef CONFIG_INET
-int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
{
unsigned char *buff;
@@ -88,7 +88,7 @@ int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short
*buff++ = AX25_P_ARP;
break;
default:
- printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%2.2x\n", type);
+ printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
*buff++ = 0;
break;
}
@@ -209,7 +209,7 @@ put:
#else /* INET */
-int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
+int ax25_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
{
return -AX25_HEADER_LEN;
}
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index c288526da4ce..26b77d972220 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -298,6 +298,8 @@ static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
static int ax25_rt_seq_show(struct seq_file *seq, void *v)
{
+ char buf[11];
+
if (v == SEQ_START_TOKEN)
seq_puts(seq, "callsign dev mode digipeaters\n");
else {
@@ -308,7 +310,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
callsign = "default";
else
- callsign = ax2asc(&ax25_rt->callsign);
+ callsign = ax2asc(buf, &ax25_rt->callsign);
seq_printf(seq, "%-9s %-4s",
callsign,
@@ -328,7 +330,8 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
if (ax25_rt->digipeat != NULL)
for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
- seq_printf(seq, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
+ seq_printf(seq, " %s",
+ ax2asc(buf, &ax25_rt->digipeat->calls[i]));
seq_puts(seq, "\n");
}
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index 7131873322c4..f6ed283e9de8 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -29,8 +29,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/ip.h> /* For ip_rcv */
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index 066897bc0749..a29c480a4dc1 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -24,7 +24,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 99694b57f6f5..c41dbe5fadee 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -24,7 +24,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
@@ -76,7 +76,7 @@ void ax25_requeue_frames(ax25_cb *ax25)
if (skb_prev == NULL)
skb_queue_head(&ax25->write_queue, skb);
else
- skb_append(skb_prev, skb);
+ skb_append(skb_prev, skb, &ax25->write_queue);
skb_prev = skb;
}
}
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index a8b3822f3ee4..d53cc8615865 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -168,12 +168,14 @@ static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
static int ax25_uid_seq_show(struct seq_file *seq, void *v)
{
+ char buf[11];
+
if (v == SEQ_START_TOKEN)
seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
else {
struct ax25_uid_assoc *pt = v;
- seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(&pt->call));
+ seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call));
}
return 0;
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ffa26c10bfe8..55dc42eac92c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -191,7 +191,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Special commands */
while ((skb = skb_dequeue(&hdev->driver_init))) {
- skb->pkt_type = HCI_COMMAND_PKT;
+ bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
skb->dev = (void *) hdev;
skb_queue_tail(&hdev->cmd_q, skb);
hci_sched_cmd(hdev);
@@ -995,11 +995,11 @@ static int hci_send_frame(struct sk_buff *skb)
return -ENODEV;
}
- BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len);
+ BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
if (atomic_read(&hdev->promisc)) {
/* Time stamp */
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
hci_send_to_sock(hdev, skb);
}
@@ -1034,7 +1034,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
BT_DBG("skb len %d", skb->len);
- skb->pkt_type = HCI_COMMAND_PKT;
+ bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
skb->dev = (void *) hdev;
skb_queue_tail(&hdev->cmd_q, skb);
hci_sched_cmd(hdev);
@@ -1081,7 +1081,7 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
BT_DBG("%s conn %p flags 0x%x", hdev->name, conn, flags);
skb->dev = (void *) hdev;
- skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
hci_add_acl_hdr(skb, conn->handle, flags | ACL_START);
if (!(list = skb_shinfo(skb)->frag_list)) {
@@ -1103,7 +1103,7 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
skb = list; list = list->next;
skb->dev = (void *) hdev;
- skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT);
BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
@@ -1139,7 +1139,7 @@ int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
memcpy(skb->h.raw, &hdr, HCI_SCO_HDR_SIZE);
skb->dev = (void *) hdev;
- skb->pkt_type = HCI_SCODATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
skb_queue_tail(&conn->data_q, skb);
hci_sched_tx(hdev);
return 0;
@@ -1369,7 +1369,7 @@ void hci_rx_task(unsigned long arg)
if (test_bit(HCI_INIT, &hdev->flags)) {
/* Don't process data packets in this states. */
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
kfree_skb(skb);
@@ -1378,7 +1378,7 @@ void hci_rx_task(unsigned long arg)
}
/* Process frame */
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_EVENT_PKT:
hci_event_packet(hdev, skb);
break;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 46367bd129c3..d6da0939216d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -484,14 +484,18 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
/* Inquiry Result */
static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct inquiry_data data;
struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);
int num_rsp = *((__u8 *) skb->data);
BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ if (!num_rsp)
+ return;
+
hci_dev_lock(hdev);
+
for (; num_rsp; num_rsp--) {
- struct inquiry_data data;
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
@@ -502,30 +506,55 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
info++;
hci_inquiry_cache_update(hdev, &data);
}
+
hci_dev_unlock(hdev);
}
/* Inquiry Result With RSSI */
static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct inquiry_info_with_rssi *info = (struct inquiry_info_with_rssi *) (skb->data + 1);
+ struct inquiry_data data;
int num_rsp = *((__u8 *) skb->data);
BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ if (!num_rsp)
+ return;
+
hci_dev_lock(hdev);
- for (; num_rsp; num_rsp--) {
- struct inquiry_data data;
- bacpy(&data.bdaddr, &info->bdaddr);
- data.pscan_rep_mode = info->pscan_rep_mode;
- data.pscan_period_mode = info->pscan_period_mode;
- data.pscan_mode = 0x00;
- memcpy(data.dev_class, info->dev_class, 3);
- data.clock_offset = info->clock_offset;
- data.rssi = info->rssi;
- info++;
- hci_inquiry_cache_update(hdev, &data);
+
+ if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
+ struct inquiry_info_with_rssi_and_pscan_mode *info =
+ (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = info->pscan_mode;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
+ } else {
+ struct inquiry_info_with_rssi *info =
+ (struct inquiry_info_with_rssi *) (skb->data + 1);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = 0x00;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
}
+
hci_dev_unlock(hdev);
}
@@ -865,6 +894,24 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev);
}
+/* Page Scan Repetition Mode */
+static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data;
+ struct inquiry_entry *ie;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) {
+ ie->data.pscan_rep_mode = ev->pscan_rep_mode;
+ ie->timestamp = jiffies;
+ }
+
+ hci_dev_unlock(hdev);
+}
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
@@ -937,6 +984,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_clock_offset_evt(hdev, skb);
break;
+ case HCI_EV_PSCAN_REP_MODE:
+ hci_pscan_rep_mode_evt(hdev, skb);
+ break;
+
case HCI_EV_CMD_STATUS:
cs = (struct hci_ev_cmd_status *) skb->data;
skb_pull(skb, sizeof(cs));
@@ -1036,9 +1087,9 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
memcpy(ev->data, data, dlen);
bt_cb(skb)->incoming = 1;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
- skb->pkt_type = HCI_EVENT_PKT;
+ bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
skb->dev = (void *) hdev;
hci_send_to_sock(hdev, skb);
kfree_skb(skb);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index ebdcce5e7ca0..32ef7975a139 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -110,11 +110,11 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
/* Apply filter */
flt = &hci_pi(sk)->filter;
- if (!test_bit((skb->pkt_type == HCI_VENDOR_PKT) ?
- 0 : (skb->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
+ if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
+ 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
continue;
- if (skb->pkt_type == HCI_EVENT_PKT) {
+ if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
if (!hci_test_bit(evt, &flt->event_mask))
@@ -131,7 +131,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
continue;
/* Put type byte before the data */
- memcpy(skb_push(nskb, 1), &nskb->pkt_type, 1);
+ memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
if (sock_queue_rcv_skb(sk, nskb))
kfree_skb(nskb);
@@ -327,11 +327,17 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
{
__u32 mask = hci_pi(sk)->cmsg_mask;
- if (mask & HCI_CMSG_DIR)
- put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(int), &bt_cb(skb)->incoming);
+ if (mask & HCI_CMSG_DIR) {
+ int incoming = bt_cb(skb)->incoming;
+ put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
+ }
+
+ if (mask & HCI_CMSG_TSTAMP) {
+ struct timeval tv;
- if (mask & HCI_CMSG_TSTAMP)
- put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(skb->stamp), &skb->stamp);
+ skb_get_timestamp(skb, &tv);
+ put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(tv), &tv);
+ }
}
static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
@@ -405,11 +411,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop;
}
- skb->pkt_type = *((unsigned char *) skb->data);
+ bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
skb_pull(skb, 1);
skb->dev = (void *) hdev;
- if (skb->pkt_type == HCI_COMMAND_PKT) {
+ if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
u16 opcode = __le16_to_cpu(get_unaligned((u16 *)skb->data));
u16 ogf = hci_opcode_ogf(opcode);
u16 ocf = hci_opcode_ocf(opcode);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 32fccfb5bfa5..d3d6bc547212 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -372,7 +372,7 @@ static struct proto l2cap_proto = {
.obj_size = sizeof(struct l2cap_pinfo)
};
-static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
+static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio)
{
struct sock *sk;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 27bf5047cd33..173f46e8cdae 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -21,10 +21,6 @@
SOFTWARE IS DISCLAIMED.
*/
-/*
- RPN support - Dirk Husemann <hud@zurich.ibm.com>
-*/
-
/*
* Bluetooth RFCOMM core.
*
@@ -115,10 +111,10 @@ static void rfcomm_session_del(struct rfcomm_session *s);
#define __get_mcc_len(b) ((b & 0xfe) >> 1)
/* RPN macros */
-#define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x3) << 3))
+#define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x7) << 3))
#define __get_rpn_data_bits(line) ((line) & 0x3)
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
-#define __get_rpn_parity(line) (((line) >> 3) & 0x3)
+#define __get_rpn_parity(line) (((line) >> 3) & 0x7)
static inline void rfcomm_schedule(uint event)
{
@@ -233,7 +229,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
d->rx_credits = RFCOMM_DEFAULT_CREDITS;
}
-struct rfcomm_dlc *rfcomm_dlc_alloc(int prio)
+struct rfcomm_dlc *rfcomm_dlc_alloc(unsigned int __nocast prio)
{
struct rfcomm_dlc *d = kmalloc(sizeof(*d), prio);
if (!d)
@@ -780,10 +776,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
return rfcomm_send_frame(s, buf, ptr - buf);
}
-static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
- u8 bit_rate, u8 data_bits, u8 stop_bits,
- u8 parity, u8 flow_ctrl_settings,
- u8 xon_char, u8 xoff_char, u16 param_mask)
+int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
+ u8 bit_rate, u8 data_bits, u8 stop_bits,
+ u8 parity, u8 flow_ctrl_settings,
+ u8 xon_char, u8 xoff_char, u16 param_mask)
{
struct rfcomm_hdr *hdr;
struct rfcomm_mcc *mcc;
@@ -791,9 +787,9 @@ static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 buf[16], *ptr = buf;
BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x"
- "flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x",
- s, cr, dlci, bit_rate, data_bits, stop_bits, parity,
- flow_ctrl_settings, xon_char, xoff_char, param_mask);
+ " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x",
+ s, cr, dlci, bit_rate, data_bits, stop_bits, parity,
+ flow_ctrl_settings, xon_char, xoff_char, param_mask);
hdr = (void *) ptr; ptr += sizeof(*hdr);
hdr->addr = __addr(s->initiator, 0);
@@ -1265,16 +1261,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
u8 xon_char = 0;
u8 xoff_char = 0;
u16 rpn_mask = RFCOMM_RPN_PM_ALL;
-
- BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
- dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
- rpn->xon_char, rpn->xoff_char, rpn->param_mask);
-
- if (!cr)
+
+ BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+ dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+ rpn->xon_char, rpn->xoff_char, rpn->param_mask);
+
+ if (!cr)
return 0;
-
+
if (len == 1) {
- /* request: return default setting */
+ /* This is a request, return default settings */
bit_rate = RFCOMM_RPN_BR_115200;
data_bits = RFCOMM_RPN_DATA_8;
stop_bits = RFCOMM_RPN_STOP_1;
@@ -1282,11 +1278,12 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
flow_ctrl = RFCOMM_RPN_FLOW_NONE;
xon_char = RFCOMM_RPN_XON_CHAR;
xoff_char = RFCOMM_RPN_XOFF_CHAR;
-
goto rpn_out;
}
- /* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
- no flow control lines, normal XON/XOFF chars */
+
+ /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
+ * no parity, no flow control lines, normal XON/XOFF chars */
+
if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
bit_rate = rpn->bit_rate;
if (bit_rate != RFCOMM_RPN_BR_115200) {
@@ -1295,6 +1292,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) {
@@ -1303,6 +1301,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_DATA;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_STOP) {
stop_bits = __get_rpn_stop_bits(rpn->line_settings);
if (stop_bits != RFCOMM_RPN_STOP_1) {
@@ -1311,6 +1310,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_STOP;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) {
parity = __get_rpn_parity(rpn->line_settings);
if (parity != RFCOMM_RPN_PARITY_NONE) {
@@ -1319,6 +1319,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_PARITY;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
flow_ctrl = rpn->flow_ctrl;
if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
@@ -1327,6 +1328,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_FLOW;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
xon_char = rpn->xon_char;
if (xon_char != RFCOMM_RPN_XON_CHAR) {
@@ -1335,6 +1337,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_XON;
}
}
+
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
xoff_char = rpn->xoff_char;
if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
@@ -1345,9 +1348,8 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
rpn_out:
- rfcomm_send_rpn(s, 0, dlci,
- bit_rate, data_bits, stop_bits, parity, flow_ctrl,
- xon_char, xoff_char, rpn_mask);
+ rfcomm_send_rpn(s, 0, dlci, bit_rate, data_bits, stop_bits,
+ parity, flow_ctrl, xon_char, xoff_char, rpn_mask);
return 0;
}
@@ -1358,14 +1360,13 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
u8 dlci = __get_dlci(rls->dlci);
BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
-
+
if (!cr)
return 0;
- /* FIXME: We should probably do something with this
- information here. But for now it's sufficient just
- to reply -- Bluetooth 1.1 says it's mandatory to
- recognise and respond to RLS */
+ /* We should probably do something with this information here. But
+ * for now it's sufficient just to reply -- Bluetooth 1.1 says it's
+ * mandatory to recognise and respond to RLS */
rfcomm_send_rls(s, 0, dlci, rls->status);
@@ -1381,7 +1382,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
d = rfcomm_dlc_get(s, dlci);
- if (!d)
+ if (!d)
return 0;
if (cr) {
@@ -1389,7 +1390,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
set_bit(RFCOMM_TX_THROTTLED, &d->flags);
else
clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
-
+
rfcomm_dlc_lock(d);
if (d->modem_status)
d->modem_status(d, msc->v24_sig);
@@ -1398,7 +1399,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
d->mscex |= RFCOMM_MSCEX_RX;
- } else
+ } else
d->mscex |= RFCOMM_MSCEX_TX;
return 0;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 63a123c5c41b..90e19eb6d3cc 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -284,7 +284,7 @@ static struct proto rfcomm_proto = {
.obj_size = sizeof(struct rfcomm_pinfo)
};
-static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
+static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio)
{
struct rfcomm_dlc *d;
struct sock *sk;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 6304590fd36a..1bca860a6109 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -286,7 +286,7 @@ static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *de
skb->destructor = rfcomm_wfree;
}
-static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, int priority)
+static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, unsigned int __nocast priority)
{
if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
struct sk_buff *skb = alloc_skb(size, priority);
@@ -528,9 +528,14 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
struct rfcomm_dev *dev = dlc->owner;
if (!dev)
return;
-
+
BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
+ if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
+ if (dev->tty && !C_CLOCAL(dev->tty))
+ tty_hangup(dev->tty);
+ }
+
dev->modem_status =
((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |
@@ -740,20 +745,143 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
return -ENOIOCTLCMD;
}
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
{
- BT_DBG("tty %p", tty);
+ struct termios *new = (struct termios *) tty->termios;
+ int old_baud_rate = tty_termios_baud_rate(old);
+ int new_baud_rate = tty_termios_baud_rate(new);
- if ((tty->termios->c_cflag == old->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old->c_iflag)))
- return;
+ u8 baud, data_bits, stop_bits, parity, x_on, x_off;
+ u16 changes = 0;
+
+ struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
+
+ BT_DBG("tty %p termios %p", tty, old);
+
+ /* Handle turning off CRTSCTS */
+ if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
+ BT_DBG("Turning off CRTSCTS unsupported");
+
+ /* Parity on/off and when on, odd/even */
+ if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
+ ((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) {
+ changes |= RFCOMM_RPN_PM_PARITY;
+ BT_DBG("Parity change detected.");
+ }
+
+ /* Mark and space parity are not supported! */
+ if (new->c_cflag & PARENB) {
+ if (new->c_cflag & PARODD) {
+ BT_DBG("Parity is ODD");
+ parity = RFCOMM_RPN_PARITY_ODD;
+ } else {
+ BT_DBG("Parity is EVEN");
+ parity = RFCOMM_RPN_PARITY_EVEN;
+ }
+ } else {
+ BT_DBG("Parity is OFF");
+ parity = RFCOMM_RPN_PARITY_NONE;
+ }
+
+ /* Setting the x_on / x_off characters */
+ if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) {
+ BT_DBG("XOFF custom");
+ x_on = new->c_cc[VSTOP];
+ changes |= RFCOMM_RPN_PM_XON;
+ } else {
+ BT_DBG("XOFF default");
+ x_on = RFCOMM_RPN_XON_CHAR;
+ }
+
+ if (old->c_cc[VSTART] != new->c_cc[VSTART]) {
+ BT_DBG("XON custom");
+ x_off = new->c_cc[VSTART];
+ changes |= RFCOMM_RPN_PM_XOFF;
+ } else {
+ BT_DBG("XON default");
+ x_off = RFCOMM_RPN_XOFF_CHAR;
+ }
+
+ /* Handle setting of stop bits */
+ if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB))
+ changes |= RFCOMM_RPN_PM_STOP;
+
+ /* POSIX does not support 1.5 stop bits and RFCOMM does not
+ * support 2 stop bits. So a request for 2 stop bits gets
+ * translated to 1.5 stop bits */
+ if (new->c_cflag & CSTOPB) {
+ stop_bits = RFCOMM_RPN_STOP_15;
+ } else {
+ stop_bits = RFCOMM_RPN_STOP_1;
+ }
+
+ /* Handle number of data bits [5-8] */
+ if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
+ changes |= RFCOMM_RPN_PM_DATA;
+
+ switch (new->c_cflag & CSIZE) {
+ case CS5:
+ data_bits = RFCOMM_RPN_DATA_5;
+ break;
+ case CS6:
+ data_bits = RFCOMM_RPN_DATA_6;
+ break;
+ case CS7:
+ data_bits = RFCOMM_RPN_DATA_7;
+ break;
+ case CS8:
+ data_bits = RFCOMM_RPN_DATA_8;
+ break;
+ default:
+ data_bits = RFCOMM_RPN_DATA_8;
+ break;
+ }
+
+ /* Handle baudrate settings */
+ if (old_baud_rate != new_baud_rate)
+ changes |= RFCOMM_RPN_PM_BITRATE;
- /* handle turning off CRTSCTS */
- if ((old->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
- BT_DBG("turning off CRTSCTS");
+ switch (new_baud_rate) {
+ case 2400:
+ baud = RFCOMM_RPN_BR_2400;
+ break;
+ case 4800:
+ baud = RFCOMM_RPN_BR_4800;
+ break;
+ case 7200:
+ baud = RFCOMM_RPN_BR_7200;
+ break;
+ case 9600:
+ baud = RFCOMM_RPN_BR_9600;
+ break;
+ case 19200:
+ baud = RFCOMM_RPN_BR_19200;
+ break;
+ case 38400:
+ baud = RFCOMM_RPN_BR_38400;
+ break;
+ case 57600:
+ baud = RFCOMM_RPN_BR_57600;
+ break;
+ case 115200:
+ baud = RFCOMM_RPN_BR_115200;
+ break;
+ case 230400:
+ baud = RFCOMM_RPN_BR_230400;
+ break;
+ default:
+ /* 9600 is standard accordinag to the RFCOMM specification */
+ baud = RFCOMM_RPN_BR_9600;
+ break;
+
}
+
+ if (changes)
+ rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
+ data_bits, stop_bits, parity,
+ RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
+
+ return;
}
static void rfcomm_tty_throttle(struct tty_struct *tty)
@@ -761,7 +889,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty)
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p dev %p", tty, dev);
-
+
rfcomm_dlc_throttle(dev->dlc);
}
@@ -770,7 +898,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty)
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p dev %p", tty, dev);
-
+
rfcomm_dlc_unthrottle(dev->dlc);
}
@@ -841,35 +969,35 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
{
- struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
- struct rfcomm_dlc *dlc = dev->dlc;
- u8 v24_sig;
+ struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
+ struct rfcomm_dlc *dlc = dev->dlc;
+ u8 v24_sig;
BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
- rfcomm_dlc_get_modem_status(dlc, &v24_sig);
-
- if (set & TIOCM_DSR || set & TIOCM_DTR)
- v24_sig |= RFCOMM_V24_RTC;
- if (set & TIOCM_RTS || set & TIOCM_CTS)
- v24_sig |= RFCOMM_V24_RTR;
- if (set & TIOCM_RI)
- v24_sig |= RFCOMM_V24_IC;
- if (set & TIOCM_CD)
- v24_sig |= RFCOMM_V24_DV;
-
- if (clear & TIOCM_DSR || clear & TIOCM_DTR)
- v24_sig &= ~RFCOMM_V24_RTC;
- if (clear & TIOCM_RTS || clear & TIOCM_CTS)
- v24_sig &= ~RFCOMM_V24_RTR;
- if (clear & TIOCM_RI)
- v24_sig &= ~RFCOMM_V24_IC;
- if (clear & TIOCM_CD)
- v24_sig &= ~RFCOMM_V24_DV;
-
- rfcomm_dlc_set_modem_status(dlc, v24_sig);
-
- return 0;
+ rfcomm_dlc_get_modem_status(dlc, &v24_sig);
+
+ if (set & TIOCM_DSR || set & TIOCM_DTR)
+ v24_sig |= RFCOMM_V24_RTC;
+ if (set & TIOCM_RTS || set & TIOCM_CTS)
+ v24_sig |= RFCOMM_V24_RTR;
+ if (set & TIOCM_RI)
+ v24_sig |= RFCOMM_V24_IC;
+ if (set & TIOCM_CD)
+ v24_sig |= RFCOMM_V24_DV;
+
+ if (clear & TIOCM_DSR || clear & TIOCM_DTR)
+ v24_sig &= ~RFCOMM_V24_RTC;
+ if (clear & TIOCM_RTS || clear & TIOCM_CTS)
+ v24_sig &= ~RFCOMM_V24_RTR;
+ if (clear & TIOCM_RI)
+ v24_sig &= ~RFCOMM_V24_IC;
+ if (clear & TIOCM_CD)
+ v24_sig &= ~RFCOMM_V24_DV;
+
+ rfcomm_dlc_set_modem_status(dlc, v24_sig);
+
+ return 0;
}
/* ---- TTY structure ---- */
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 746c11fc017e..ce7ab7dfa0b2 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -418,7 +418,7 @@ static struct proto sco_proto = {
.obj_size = sizeof(struct sco_pinfo)
};
-static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
+static struct sock *sco_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio)
{
struct sock *sk;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e6c2200b7ca3..24396b914d11 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -23,7 +23,7 @@
#include <asm/atomic.h>
#include "br_private.h"
-static kmem_cache_t *br_fdb_cache;
+static kmem_cache_t *br_fdb_cache __read_mostly;
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr);
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 02c632b4d325..c93d35ab95c0 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -23,10 +23,9 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
{
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data;
- if ((*pskb)->nfmark != info->mark) {
+ if ((*pskb)->nfmark != info->mark)
(*pskb)->nfmark = info->mark;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
+
return info->target;
}
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 01af4fcef26d..aae26ae2e61f 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -78,8 +78,8 @@ static void ulog_send(unsigned int nlgroup)
if (ub->qlen > 1)
ub->lastnlh->nlmsg_type = NLMSG_DONE;
- NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup;
- netlink_broadcast(ebtulognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC);
+ NETLINK_CB(ub->skb).dst_group = nlgroup + 1;
+ netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC);
ub->qlen = 0;
ub->skb = NULL;
@@ -162,7 +162,7 @@ static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
pm->version = EBT_ULOG_VERSION;
do_gettimeofday(&pm->stamp);
if (ub->qlen == 1)
- ub->skb->stamp = pm->stamp;
+ skb_set_timestamp(ub->skb, &pm->stamp);
pm->data_len = copy_len;
pm->mark = skb->nfmark;
pm->hook = hooknr;
@@ -258,7 +258,8 @@ static int __init init(void)
spin_lock_init(&ulog_buffers[i].lock);
}
- ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
+ ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
+ NULL, THIS_MODULE);
if (!ebtulognl)
ret = -ENOMEM;
else if ((ret = ebt_register_watcher(&ulog)))
diff --git a/net/compat.c b/net/compat.c
index d99ab9695893..e593dace2fdb 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -135,13 +135,14 @@ static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *ms
* thus placement) of cmsg headers and length are different for
* 32-bit apps. -DaveM
*/
-int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
unsigned char *stackbuf, int stackbuf_size)
{
struct compat_cmsghdr __user *ucmsg;
struct cmsghdr *kcmsg, *kcmsg_base;
compat_size_t ucmlen;
__kernel_size_t kcmlen, tmp;
+ int err = -EFAULT;
kcmlen = 0;
kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
@@ -156,6 +157,7 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
CMSG_ALIGN(sizeof(struct cmsghdr)));
+ tmp = CMSG_ALIGN(tmp);
kcmlen += tmp;
ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
}
@@ -167,30 +169,34 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
* until we have successfully copied over all of the data
* from the user.
*/
- if(kcmlen > stackbuf_size)
- kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
- if(kcmsg == NULL)
+ if (kcmlen > stackbuf_size)
+ kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
+ if (kcmsg == NULL)
return -ENOBUFS;
/* Now copy them over neatly. */
memset(kcmsg, 0, kcmlen);
ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
while(ucmsg != NULL) {
- __get_user(ucmlen, &ucmsg->cmsg_len);
+ if (__get_user(ucmlen, &ucmsg->cmsg_len))
+ goto Efault;
+ if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
+ goto Einval;
tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
CMSG_ALIGN(sizeof(struct cmsghdr)));
+ if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
+ goto Einval;
kcmsg->cmsg_len = tmp;
- __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
- __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
- /* Copy over the data. */
- if(copy_from_user(CMSG_DATA(kcmsg),
- CMSG_COMPAT_DATA(ucmsg),
- (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
- goto out_free_efault;
+ tmp = CMSG_ALIGN(tmp);
+ if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
+ __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
+ copy_from_user(CMSG_DATA(kcmsg),
+ CMSG_COMPAT_DATA(ucmsg),
+ (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
+ goto Efault;
/* Advance. */
- kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+ kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
}
@@ -199,10 +205,12 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
kmsg->msg_controllen = kcmlen;
return 0;
-out_free_efault:
- if(kcmsg_base != (struct cmsghdr *)stackbuf)
- kfree(kcmsg_base);
- return -EFAULT;
+Einval:
+ err = -EINVAL;
+Efault:
+ if (kcmsg_base != (struct cmsghdr *)stackbuf)
+ sock_kfree_s(sk, kcmsg_base, kcmlen);
+ return err;
}
int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
diff --git a/net/core/Makefile b/net/core/Makefile
index f5f5e58943e8..630da0f0579e 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -12,7 +12,6 @@ obj-y += dev.o ethtool.o dev_mcast.o dst.o \
obj-$(CONFIG_XFRM) += flow.o
obj-$(CONFIG_SYSFS) += net-sysfs.o
-obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_NET_RADIO) += wireless.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index fcee054b6f75..da9bf71421a7 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -43,7 +43,6 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/inet.h>
-#include <linux/tcp.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/poll.h>
@@ -51,9 +50,10 @@
#include <net/protocol.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/checksum.h>
+#include <net/checksum.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
/*
* Is a socket 'connection oriented' ?
diff --git a/net/core/dev.c b/net/core/dev.c
index faf59b02c4bf..c01511e3d0c1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -267,10 +267,6 @@ void dev_add_pack(struct packet_type *pt)
spin_unlock_bh(&ptype_lock);
}
-extern void linkwatch_run_queue(void);
-
-
-
/**
* __dev_remove_pack - remove packet handler
* @pt: packet type declaration
@@ -1009,13 +1005,22 @@ void net_disable_timestamp(void)
atomic_dec(&netstamp_needed);
}
-static inline void net_timestamp(struct timeval *stamp)
+void __net_timestamp(struct sk_buff *skb)
+{
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ skb_set_timestamp(skb, &tv);
+}
+EXPORT_SYMBOL(__net_timestamp);
+
+static inline void net_timestamp(struct sk_buff *skb)
{
if (atomic_read(&netstamp_needed))
- do_gettimeofday(stamp);
+ __net_timestamp(skb);
else {
- stamp->tv_sec = 0;
- stamp->tv_usec = 0;
+ skb->tstamp.off_sec = 0;
+ skb->tstamp.off_usec = 0;
}
}
@@ -1027,7 +1032,8 @@ static inline void net_timestamp(struct timeval *stamp)
void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
{
struct packet_type *ptype;
- net_timestamp(&skb->stamp);
+
+ net_timestamp(skb);
rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_all, list) {
@@ -1058,7 +1064,7 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
skb2->h.raw = skb2->nh.raw;
skb2->pkt_type = PACKET_OUTGOING;
- ptype->func(skb2, skb->dev, ptype);
+ ptype->func(skb2, skb->dev, ptype, skb->dev);
}
}
rcu_read_unlock();
@@ -1123,8 +1129,6 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
#define illegal_highdma(dev, skb) (0)
#endif
-extern void skb_release_data(struct sk_buff *);
-
/* Keep head the same: replace data */
int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp_mask)
{
@@ -1379,8 +1383,8 @@ int netif_rx(struct sk_buff *skb)
if (netpoll_rx(skb))
return NET_RX_DROP;
- if (!skb->stamp.tv_sec)
- net_timestamp(&skb->stamp);
+ if (!skb->tstamp.off_sec)
+ net_timestamp(skb);
/*
* The code is rearranged so that the path is the most
@@ -1425,14 +1429,14 @@ int netif_rx_ni(struct sk_buff *skb)
EXPORT_SYMBOL(netif_rx_ni);
-static __inline__ void skb_bond(struct sk_buff *skb)
+static inline struct net_device *skb_bond(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- if (dev->master) {
- skb->real_dev = skb->dev;
+ if (dev->master)
skb->dev = dev->master;
- }
+
+ return dev;
}
static void net_tx_action(struct softirq_action *h)
@@ -1482,10 +1486,11 @@ static void net_tx_action(struct softirq_action *h)
}
static __inline__ int deliver_skb(struct sk_buff *skb,
- struct packet_type *pt_prev)
+ struct packet_type *pt_prev,
+ struct net_device *orig_dev)
{
atomic_inc(&skb->users);
- return pt_prev->func(skb, skb->dev, pt_prev);
+ return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
@@ -1496,7 +1501,8 @@ struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
static __inline__ int handle_bridge(struct sk_buff **pskb,
- struct packet_type **pt_prev, int *ret)
+ struct packet_type **pt_prev, int *ret,
+ struct net_device *orig_dev)
{
struct net_bridge_port *port;
@@ -1505,14 +1511,14 @@ static __inline__ int handle_bridge(struct sk_buff **pskb,
return 0;
if (*pt_prev) {
- *ret = deliver_skb(*pskb, *pt_prev);
+ *ret = deliver_skb(*pskb, *pt_prev, orig_dev);
*pt_prev = NULL;
}
return br_handle_frame_hook(port, pskb);
}
#else
-#define handle_bridge(skb, pt_prev, ret) (0)
+#define handle_bridge(skb, pt_prev, ret, orig_dev) (0)
#endif
#ifdef CONFIG_NET_CLS_ACT
@@ -1534,17 +1540,14 @@ static int ing_filter(struct sk_buff *skb)
__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
if (MAX_RED_LOOP < ttl++) {
printk("Redir loop detected Dropping packet (%s->%s)\n",
- skb->input_dev?skb->input_dev->name:"??",skb->dev->name);
+ skb->input_dev->name, skb->dev->name);
return TC_ACT_SHOT;
}
skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
- if (NULL == skb->input_dev) {
- skb->input_dev = skb->dev;
- printk("ing_filter: fixed %s out %s\n",skb->input_dev->name,skb->dev->name);
- }
+
spin_lock(&dev->ingress_lock);
if ((q = dev->qdisc_ingress) != NULL)
result = q->enqueue(skb, q);
@@ -1559,6 +1562,7 @@ static int ing_filter(struct sk_buff *skb)
int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
+ struct net_device *orig_dev;
int ret = NET_RX_DROP;
unsigned short type;
@@ -1566,10 +1570,13 @@ int netif_receive_skb(struct sk_buff *skb)
if (skb->dev->poll && netpoll_rx(skb))
return NET_RX_DROP;
- if (!skb->stamp.tv_sec)
- net_timestamp(&skb->stamp);
+ if (!skb->tstamp.off_sec)
+ net_timestamp(skb);
+
+ if (!skb->input_dev)
+ skb->input_dev = skb->dev;
- skb_bond(skb);
+ orig_dev = skb_bond(skb);
__get_cpu_var(netdev_rx_stat).total++;
@@ -1590,14 +1597,14 @@ int netif_receive_skb(struct sk_buff *skb)
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (!ptype->dev || ptype->dev == skb->dev) {
if (pt_prev)
- ret = deliver_skb(skb, pt_prev);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
#ifdef CONFIG_NET_CLS_ACT
if (pt_prev) {
- ret = deliver_skb(skb, pt_prev);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL; /* noone else should process this after*/
} else {
skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
@@ -1616,7 +1623,7 @@ ncls:
handle_diverter(skb);
- if (handle_bridge(&skb, &pt_prev, &ret))
+ if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
goto out;
type = skb->protocol;
@@ -1624,13 +1631,13 @@ ncls:
if (ptype->type == type &&
(!ptype->dev || ptype->dev == skb->dev)) {
if (pt_prev)
- ret = deliver_skb(skb, pt_prev);
+ ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
if (pt_prev) {
- ret = pt_prev->func(skb, skb->dev, pt_prev);
+ ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
} else {
kfree_skb(skb);
/* Jamal, now you will not able to escape explaining
diff --git a/net/core/dst.c b/net/core/dst.c
index 334790da9f16..470c05bc4cb2 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -39,8 +39,7 @@ static unsigned long dst_gc_timer_inc = DST_GC_MAX;
static void dst_run_gc(unsigned long);
static void ___dst_free(struct dst_entry * dst);
-static struct timer_list dst_gc_timer =
- TIMER_INITIALIZER(dst_run_gc, DST_GC_MIN, 0);
+static DEFINE_TIMER(dst_gc_timer, dst_run_gc, DST_GC_MIN, 0);
static void dst_run_gc(unsigned long dummy)
{
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index a3eeb88e1c81..404b761e82ce 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -81,6 +81,18 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data)
return 0;
}
+int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data)
+{
+ unsigned char len = dev->addr_len;
+ if ( addr->size < len )
+ return -ETOOSMALL;
+
+ addr->size = len;
+ memcpy(data, dev->perm_addr, len);
+ return 0;
+}
+
+
/* Handlers for each ethtool command */
static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -683,6 +695,39 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
return ret;
}
+static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
+{
+ struct ethtool_perm_addr epaddr;
+ u8 *data;
+ int ret;
+
+ if (!dev->ethtool_ops->get_perm_addr)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&epaddr,useraddr,sizeof(epaddr)))
+ return -EFAULT;
+
+ data = kmalloc(epaddr.size, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+
+ ret = dev->ethtool_ops->get_perm_addr(dev,&epaddr,data);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
+ goto out;
+ useraddr += sizeof(epaddr);
+ if (copy_to_user(useraddr, data, epaddr.size))
+ goto out;
+ ret = 0;
+
+ out:
+ kfree(data);
+ return ret;
+}
+
/* The main entry point in this file. Called from net/core/dev.c */
int dev_ethtool(struct ifreq *ifr)
@@ -806,6 +851,9 @@ int dev_ethtool(struct ifreq *ifr)
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
+ case ETHTOOL_GPERMADDR:
+ rc = ethtool_get_perm_addr(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
@@ -826,6 +874,7 @@ int dev_ethtool(struct ifreq *ifr)
EXPORT_SYMBOL(dev_ethtool);
EXPORT_SYMBOL(ethtool_op_get_link);
+EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr);
EXPORT_SYMBOL(ethtool_op_get_sg);
EXPORT_SYMBOL(ethtool_op_get_tso);
EXPORT_SYMBOL(ethtool_op_get_tx_csum);
diff --git a/net/core/filter.c b/net/core/filter.c
index cd91a24f9720..079c2edff789 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -182,7 +182,7 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
A = ntohl(*(u32 *)ptr);
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_H|BPF_ABS:
k = fentry->k;
load_h:
@@ -191,7 +191,7 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
A = ntohs(*(u16 *)ptr);
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_B|BPF_ABS:
k = fentry->k;
load_b:
@@ -200,7 +200,7 @@ load_b:
A = *(u8 *)ptr;
continue;
}
- return 0;
+ break;
case BPF_LD|BPF_W|BPF_LEN:
A = skb->len;
continue;
diff --git a/net/core/flow.c b/net/core/flow.c
index f289570b15a3..7e95b39de9fd 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL };
#define flow_table(cpu) (per_cpu(flow_tables, cpu))
-static kmem_cache_t *flow_cachep;
+static kmem_cache_t *flow_cachep __read_mostly;
static int flow_lwm, flow_hwm;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1beb782ac41b..39fc55edf691 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1217,7 +1217,7 @@ static void neigh_proxy_process(unsigned long arg)
while (skb != (struct sk_buff *)&tbl->proxy_queue) {
struct sk_buff *back = skb;
- long tdif = back->stamp.tv_usec - now;
+ long tdif = NEIGH_CB(back)->sched_next - now;
skb = skb->next;
if (tdif <= 0) {
@@ -1248,8 +1248,9 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
kfree_skb(skb);
return;
}
- skb->stamp.tv_sec = LOCALLY_ENQUEUED;
- skb->stamp.tv_usec = sched_next;
+
+ NEIGH_CB(skb)->sched_next = sched_next;
+ NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
spin_lock(&tbl->proxy_queue.lock);
if (del_timer(&tbl->proxy_timer)) {
@@ -2342,8 +2343,8 @@ void neigh_app_ns(struct neighbour *n)
}
nlh = (struct nlmsghdr *)skb->data;
nlh->nlmsg_flags = NLM_F_REQUEST;
- NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
}
static void neigh_app_notify(struct neighbour *n)
@@ -2360,8 +2361,8 @@ static void neigh_app_notify(struct neighbour *n)
return;
}
nlh = (struct nlmsghdr *)skb->data;
- NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
}
#endif /* CONFIG_ARPD */
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
deleted file mode 100644
index 076c156d5eda..000000000000
--- a/net/core/netfilter.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/* netfilter.c: look after the filters for various protocols.
- * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
- *
- * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
- * way.
- *
- * Rusty Russell (C)2000 -- This code is GPL.
- *
- * February 2000: Modified by James Morris to have 1 queue per protocol.
- * 15-Mar-2000: Added NF_REPEAT --RR.
- * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/netfilter.h>
-#include <net/protocol.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/if.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/icmp.h>
-#include <net/sock.h>
-#include <net/route.h>
-#include <linux/ip.h>
-
-/* 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
- * this is zero, but that sucks. Now, we simply check when the
- * packets come back: if the hook is gone, the packet is discarded. */
-#ifdef CONFIG_NETFILTER_DEBUG
-#define NFDEBUG(format, args...) printk(format , ## args)
-#else
-#define NFDEBUG(format, args...)
-#endif
-
-/* Sockopts only registered and called from user context, so
- net locking would be overkill. Also, [gs]etsockopt calls may
- sleep. */
-static DECLARE_MUTEX(nf_sockopt_mutex);
-
-struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
-static LIST_HEAD(nf_sockopts);
-static DEFINE_SPINLOCK(nf_hook_lock);
-
-/*
- * A queue handler may be registered for each protocol. Each is protected by
- * long term mutex. The handler must provide an an outfn() to accept packets
- * for queueing and must reinject all packets it receives, no matter what.
- */
-static struct nf_queue_handler_t {
- nf_queue_outfn_t outfn;
- void *data;
-} queue_handler[NPROTO];
-static DEFINE_RWLOCK(queue_handler_lock);
-
-int nf_register_hook(struct nf_hook_ops *reg)
-{
- struct list_head *i;
-
- spin_lock_bh(&nf_hook_lock);
- list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
- if (reg->priority < ((struct nf_hook_ops *)i)->priority)
- break;
- }
- list_add_rcu(&reg->list, i->prev);
- spin_unlock_bh(&nf_hook_lock);
-
- synchronize_net();
- return 0;
-}
-
-void nf_unregister_hook(struct nf_hook_ops *reg)
-{
- spin_lock_bh(&nf_hook_lock);
- list_del_rcu(&reg->list);
- spin_unlock_bh(&nf_hook_lock);
-
- synchronize_net();
-}
-
-/* Do exclusive ranges overlap? */
-static inline int overlap(int min1, int max1, int min2, int max2)
-{
- return max1 > min2 && min1 < max2;
-}
-
-/* Functions to register sockopt ranges (exclusive). */
-int nf_register_sockopt(struct nf_sockopt_ops *reg)
-{
- struct list_head *i;
- int ret = 0;
-
- if (down_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
-
- list_for_each(i, &nf_sockopts) {
- struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
- if (ops->pf == reg->pf
- && (overlap(ops->set_optmin, ops->set_optmax,
- reg->set_optmin, reg->set_optmax)
- || overlap(ops->get_optmin, ops->get_optmax,
- reg->get_optmin, reg->get_optmax))) {
- NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
- ops->set_optmin, ops->set_optmax,
- ops->get_optmin, ops->get_optmax,
- reg->set_optmin, reg->set_optmax,
- reg->get_optmin, reg->get_optmax);
- ret = -EBUSY;
- goto out;
- }
- }
-
- list_add(&reg->list, &nf_sockopts);
-out:
- up(&nf_sockopt_mutex);
- return ret;
-}
-
-void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
-{
- /* No point being interruptible: we're probably in cleanup_module() */
- restart:
- down(&nf_sockopt_mutex);
- if (reg->use != 0) {
- /* To be woken by nf_sockopt call... */
- /* FIXME: Stuart Young's name appears gratuitously. */
- set_current_state(TASK_UNINTERRUPTIBLE);
- reg->cleanup_task = current;
- up(&nf_sockopt_mutex);
- schedule();
- goto restart;
- }
- list_del(&reg->list);
- up(&nf_sockopt_mutex);
-}
-
-/* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val,
- char __user *opt, int *len, int get)
-{
- struct list_head *i;
- struct nf_sockopt_ops *ops;
- int ret;
-
- if (down_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
-
- list_for_each(i, &nf_sockopts) {
- ops = (struct nf_sockopt_ops *)i;
- if (ops->pf == pf) {
- if (get) {
- if (val >= ops->get_optmin
- && val < ops->get_optmax) {
- ops->use++;
- up(&nf_sockopt_mutex);
- ret = ops->get(sk, val, opt, len);
- goto out;
- }
- } else {
- if (val >= ops->set_optmin
- && val < ops->set_optmax) {
- ops->use++;
- up(&nf_sockopt_mutex);
- ret = ops->set(sk, val, opt, *len);
- goto out;
- }
- }
- }
- }
- up(&nf_sockopt_mutex);
- return -ENOPROTOOPT;
-
- out:
- down(&nf_sockopt_mutex);
- ops->use--;
- if (ops->cleanup_task)
- wake_up_process(ops->cleanup_task);
- up(&nf_sockopt_mutex);
- return ret;
-}
-
-int nf_setsockopt(struct sock *sk, int pf, int val, char __user *opt,
- int len)
-{
- return nf_sockopt(sk, pf, val, opt, &len, 0);
-}
-
-int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
-{
- return nf_sockopt(sk, pf, val, opt, len, 1);
-}
-
-static unsigned int nf_iterate(struct list_head *head,
- struct sk_buff **skb,
- int hook,
- const struct net_device *indev,
- const struct net_device *outdev,
- struct list_head **i,
- int (*okfn)(struct sk_buff *),
- int hook_thresh)
-{
- unsigned int verdict;
-
- /*
- * The caller must not block between calls to this
- * function because of risk of continuing from deleted element.
- */
- list_for_each_continue_rcu(*i, head) {
- struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
-
- if (hook_thresh > elem->priority)
- continue;
-
- /* Optimization: we don't need to hold module
- reference here, since function can't sleep. --RR */
- verdict = elem->hook(hook, skb, indev, outdev, okfn);
- if (verdict != NF_ACCEPT) {
-#ifdef CONFIG_NETFILTER_DEBUG
- if (unlikely(verdict > NF_MAX_VERDICT)) {
- NFDEBUG("Evil return from %p(%u).\n",
- elem->hook, hook);
- continue;
- }
-#endif
- if (verdict != NF_REPEAT)
- return verdict;
- *i = (*i)->prev;
- }
- }
- return NF_ACCEPT;
-}
-
-int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
-{
- int ret;
-
- write_lock_bh(&queue_handler_lock);
- if (queue_handler[pf].outfn)
- ret = -EBUSY;
- else {
- queue_handler[pf].outfn = outfn;
- queue_handler[pf].data = data;
- ret = 0;
- }
- write_unlock_bh(&queue_handler_lock);
-
- return ret;
-}
-
-/* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf)
-{
- write_lock_bh(&queue_handler_lock);
- queue_handler[pf].outfn = NULL;
- queue_handler[pf].data = NULL;
- write_unlock_bh(&queue_handler_lock);
-
- return 0;
-}
-
-/*
- * Any packet that leaves via this function must come back
- * through nf_reinject().
- */
-static int nf_queue(struct sk_buff *skb,
- struct list_head *elem,
- int pf, unsigned int hook,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct sk_buff *))
-{
- int status;
- struct nf_info *info;
-#ifdef CONFIG_BRIDGE_NETFILTER
- struct net_device *physindev = NULL;
- struct net_device *physoutdev = NULL;
-#endif
-
- /* QUEUE == DROP if noone is waiting, to be safe. */
- read_lock(&queue_handler_lock);
- if (!queue_handler[pf].outfn) {
- read_unlock(&queue_handler_lock);
- kfree_skb(skb);
- return 1;
- }
-
- info = kmalloc(sizeof(*info), GFP_ATOMIC);
- if (!info) {
- if (net_ratelimit())
- printk(KERN_ERR "OOM queueing packet %p\n",
- skb);
- read_unlock(&queue_handler_lock);
- kfree_skb(skb);
- return 1;
- }
-
- *info = (struct nf_info) {
- (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
-
- /* If it's going away, ignore hook. */
- if (!try_module_get(info->elem->owner)) {
- read_unlock(&queue_handler_lock);
- kfree(info);
- return 0;
- }
-
- /* Bump dev refs so they don't vanish while packet is out */
- if (indev) dev_hold(indev);
- if (outdev) dev_hold(outdev);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
- if (skb->nf_bridge) {
- physindev = skb->nf_bridge->physindev;
- if (physindev) dev_hold(physindev);
- physoutdev = skb->nf_bridge->physoutdev;
- if (physoutdev) dev_hold(physoutdev);
- }
-#endif
-
- status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
- read_unlock(&queue_handler_lock);
-
- if (status < 0) {
- /* James M doesn't say fuck enough. */
- if (indev) dev_put(indev);
- if (outdev) dev_put(outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
- if (physindev) dev_put(physindev);
- if (physoutdev) dev_put(physoutdev);
-#endif
- module_put(info->elem->owner);
- kfree(info);
- kfree_skb(skb);
- return 1;
- }
- return 1;
-}
-
-/* Returns 1 if okfn() needs to be executed by the caller,
- * -EPERM for NF_DROP, 0 otherwise. */
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct sk_buff *),
- int hook_thresh)
-{
- struct list_head *elem;
- unsigned int verdict;
- int ret = 0;
-
- /* We may already have this, but read-locks nest anyway */
- rcu_read_lock();
-
- elem = &nf_hooks[pf][hook];
-next_hook:
- verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
- outdev, &elem, okfn, hook_thresh);
- if (verdict == NF_ACCEPT || verdict == NF_STOP) {
- ret = 1;
- goto unlock;
- } else if (verdict == NF_DROP) {
- kfree_skb(*pskb);
- ret = -EPERM;
- } else if (verdict == NF_QUEUE) {
- NFDEBUG("nf_hook: Verdict = QUEUE.\n");
- if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn))
- goto next_hook;
- }
-unlock:
- rcu_read_unlock();
- return ret;
-}
-
-void nf_reinject(struct sk_buff *skb, struct nf_info *info,
- unsigned int verdict)
-{
- struct list_head *elem = &info->elem->list;
- struct list_head *i;
-
- rcu_read_lock();
-
- /* Release those devices we held, or Alexey will kill me. */
- if (info->indev) dev_put(info->indev);
- if (info->outdev) dev_put(info->outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
- if (skb->nf_bridge) {
- if (skb->nf_bridge->physindev)
- dev_put(skb->nf_bridge->physindev);
- if (skb->nf_bridge->physoutdev)
- dev_put(skb->nf_bridge->physoutdev);
- }
-#endif
-
- /* Drop reference to owner of hook which queued us. */
- module_put(info->elem->owner);
-
- list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
- if (i == elem)
- break;
- }
-
- if (elem == &nf_hooks[info->pf][info->hook]) {
- /* The module which sent it to userspace is gone. */
- NFDEBUG("%s: module disappeared, dropping packet.\n",
- __FUNCTION__);
- verdict = NF_DROP;
- }
-
- /* Continue traversal iff userspace said ok... */
- if (verdict == NF_REPEAT) {
- elem = elem->prev;
- verdict = NF_ACCEPT;
- }
-
- if (verdict == NF_ACCEPT) {
- next_hook:
- verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
- &skb, info->hook,
- info->indev, info->outdev, &elem,
- info->okfn, INT_MIN);
- }
-
- switch (verdict) {
- case NF_ACCEPT:
- info->okfn(skb);
- break;
-
- case NF_QUEUE:
- if (!nf_queue(skb, elem, info->pf, info->hook,
- info->indev, info->outdev, info->okfn))
- goto next_hook;
- break;
- }
- rcu_read_unlock();
-
- if (verdict == NF_DROP)
- kfree_skb(skb);
-
- kfree(info);
- return;
-}
-
-#ifdef CONFIG_INET
-/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
-int ip_route_me_harder(struct sk_buff **pskb)
-{
- struct iphdr *iph = (*pskb)->nh.iph;
- struct rtable *rt;
- struct flowi fl = {};
- struct dst_entry *odst;
- unsigned int hh_len;
-
- /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
- * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
- */
- if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
- fl.nl_u.ip4_u.daddr = iph->daddr;
- fl.nl_u.ip4_u.saddr = iph->saddr;
- fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
- fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
-#endif
- fl.proto = iph->protocol;
- if (ip_route_output_key(&rt, &fl) != 0)
- return -1;
-
- /* Drop old route. */
- dst_release((*pskb)->dst);
- (*pskb)->dst = &rt->u.dst;
- } else {
- /* non-local src, find valid iif to satisfy
- * rp-filter when calling ip_route_input. */
- fl.nl_u.ip4_u.daddr = iph->saddr;
- if (ip_route_output_key(&rt, &fl) != 0)
- return -1;
-
- odst = (*pskb)->dst;
- if (ip_route_input(*pskb, iph->daddr, iph->saddr,
- RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
- dst_release(&rt->u.dst);
- return -1;
- }
- dst_release(&rt->u.dst);
- dst_release(odst);
- }
-
- if ((*pskb)->dst->error)
- return -1;
-
- /* Change in oif may mean change in hh_len. */
- hh_len = (*pskb)->dst->dev->hard_header_len;
- if (skb_headroom(*pskb) < hh_len) {
- struct sk_buff *nskb;
-
- nskb = skb_realloc_headroom(*pskb, hh_len);
- if (!nskb)
- return -1;
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(ip_route_me_harder);
-
-int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
-{
- struct sk_buff *nskb;
-
- if (writable_len > (*pskb)->len)
- return 0;
-
- /* Not exclusive use of packet? Must copy. */
- if (skb_shared(*pskb) || skb_cloned(*pskb))
- goto copy_skb;
-
- return pskb_may_pull(*pskb, writable_len);
-
-copy_skb:
- nskb = skb_copy(*pskb, GFP_ATOMIC);
- if (!nskb)
- return 0;
- BUG_ON(skb_is_nonlinear(nskb));
-
- /* Rest of kernel will get very unhappy if we pass it a
- suddenly-orphaned skbuff */
- if ((*pskb)->sk)
- skb_set_owner_w(nskb, (*pskb)->sk);
- kfree_skb(*pskb);
- *pskb = nskb;
- return 1;
-}
-EXPORT_SYMBOL(skb_ip_make_writable);
-#endif /*CONFIG_INET*/
-
-/* Internal logging interface, which relies on the real
- LOG target modules */
-
-#define NF_LOG_PREFIXLEN 128
-
-static nf_logfn *nf_logging[NPROTO]; /* = NULL */
-static int reported = 0;
-static DEFINE_SPINLOCK(nf_log_lock);
-
-int nf_log_register(int pf, nf_logfn *logfn)
-{
- int ret = -EBUSY;
-
- /* Any setup of logging members must be done before
- * substituting pointer. */
- spin_lock(&nf_log_lock);
- if (!nf_logging[pf]) {
- rcu_assign_pointer(nf_logging[pf], logfn);
- ret = 0;
- }
- spin_unlock(&nf_log_lock);
- return ret;
-}
-
-void nf_log_unregister(int pf, nf_logfn *logfn)
-{
- spin_lock(&nf_log_lock);
- if (nf_logging[pf] == logfn)
- nf_logging[pf] = NULL;
- spin_unlock(&nf_log_lock);
-
- /* Give time to concurrent readers. */
- synchronize_net();
-}
-
-void nf_log_packet(int pf,
- unsigned int hooknum,
- const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const char *fmt, ...)
-{
- va_list args;
- char prefix[NF_LOG_PREFIXLEN];
- nf_logfn *logfn;
-
- rcu_read_lock();
- logfn = rcu_dereference(nf_logging[pf]);
- if (logfn) {
- va_start(args, fmt);
- vsnprintf(prefix, sizeof(prefix), fmt, args);
- va_end(args);
- /* We must read logging before nf_logfn[pf] */
- logfn(hooknum, skb, in, out, prefix);
- } else if (!reported) {
- printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
- "no backend logging module loaded in!\n");
- reported++;
- }
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(nf_log_register);
-EXPORT_SYMBOL(nf_log_unregister);
-EXPORT_SYMBOL(nf_log_packet);
-
-/* This does not belong here, but locally generated errors need it if connection
- tracking in use: without this, connection may not be in hash table, and hence
- manufactured ICMP or RST packets will not be associated with it. */
-void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
-
-void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
-{
- void (*attach)(struct sk_buff *, struct sk_buff *);
-
- if (skb->nfct && (attach = ip_ct_attach) != NULL) {
- mb(); /* Just to be sure: must be read before executing this */
- attach(new, skb);
- }
-}
-
-void __init netfilter_init(void)
-{
- int i, h;
-
- for (i = 0; i < NPROTO; i++) {
- for (h = 0; h < NF_MAX_HOOKS; h++)
- INIT_LIST_HEAD(&nf_hooks[i][h]);
- }
-}
-
-EXPORT_SYMBOL(ip_ct_attach);
-EXPORT_SYMBOL(nf_ct_attach);
-EXPORT_SYMBOL(nf_getsockopt);
-EXPORT_SYMBOL(nf_hook_slow);
-EXPORT_SYMBOL(nf_hooks);
-EXPORT_SYMBOL(nf_register_hook);
-EXPORT_SYMBOL(nf_register_queue_handler);
-EXPORT_SYMBOL(nf_register_sockopt);
-EXPORT_SYMBOL(nf_reinject);
-EXPORT_SYMBOL(nf_setsockopt);
-EXPORT_SYMBOL(nf_unregister_hook);
-EXPORT_SYMBOL(nf_unregister_queue_handler);
-EXPORT_SYMBOL(nf_unregister_sockopt);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a1a9a7abff50..5265dfd69928 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -645,10 +645,10 @@ int netpoll_setup(struct netpoll *np)
npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
- npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&npinfo->poll_lock);
npinfo->poll_owner = -1;
npinfo->tries = MAX_RETRIES;
- npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&npinfo->rx_lock);
} else
npinfo = ndev->npinfo;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8eb083b6041a..ef430b1e8e42 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -503,7 +503,7 @@ static int pg_delay_d = 0;
static int pg_clone_skb_d = 0;
static int debug = 0;
-static spinlock_t _thread_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(_thread_lock);
static struct pktgen_thread *pktgen_threads = NULL;
static char module_fname[128];
@@ -1452,8 +1452,7 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
thread_lock();
t->control |= T_REMDEV;
thread_unlock();
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/8); /* Propagate thread->control */
+ schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
ret = count;
sprintf(pg_result, "OK: rem_device_all");
goto out;
@@ -1716,10 +1715,9 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
while (now < spin_until_us) {
/* TODO: optimise sleeping behavior */
- if (spin_until_us - now > (1000000/HZ)+1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- } else if (spin_until_us - now > 100) {
+ if (spin_until_us - now > jiffies_to_usecs(1)+1)
+ schedule_timeout_interruptible(1);
+ else if (spin_until_us - now > 100) {
do_softirq();
if (!pkt_dev->running)
return;
@@ -2449,8 +2447,7 @@ static void pktgen_run_all_threads(void)
}
thread_unlock();
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/8); /* Propagate thread->control */
+ schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
pktgen_wait_all_threads_run();
}
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index bb55675f0685..b8203de5ff07 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -32,7 +32,6 @@
* Further increasing requires to change hash table size.
*/
int sysctl_max_syn_backlog = 256;
-EXPORT_SYMBOL(sysctl_max_syn_backlog);
int reqsk_queue_alloc(struct request_sock_queue *queue,
const int nr_table_entries)
@@ -53,6 +52,8 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
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_defer_accept = 0;
+ lopt->nr_table_entries = nr_table_entries;
write_lock_bh(&queue->syn_wait_lock);
queue->listen_opt = lopt;
@@ -62,3 +63,28 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
}
EXPORT_SYMBOL(reqsk_queue_alloc);
+
+void reqsk_queue_destroy(struct request_sock_queue *queue)
+{
+ /* make all the listen_opt local to us */
+ struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue);
+
+ if (lopt->qlen != 0) {
+ int i;
+
+ for (i = 0; i < lopt->nr_table_entries; i++) {
+ struct request_sock *req;
+
+ while ((req = lopt->syn_table[i]) != NULL) {
+ lopt->syn_table[i] = req->dl_next;
+ lopt->qlen--;
+ reqsk_free(req);
+ }
+ }
+ }
+
+ BUG_TRAP(lopt->qlen == 0);
+ kfree(lopt);
+}
+
+EXPORT_SYMBOL(reqsk_queue_destroy);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4b1bb30e6381..9bed7569ce3f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -148,7 +148,7 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
{
int err = 0;
- NETLINK_CB(skb).dst_groups = group;
+ NETLINK_CB(skb).dst_group = group;
if (echo)
atomic_inc(&skb->users);
netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
@@ -458,8 +458,8 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
kfree_skb(skb);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_KERNEL);
+ NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL);
}
static int rtnetlink_done(struct netlink_callback *cb)
@@ -708,7 +708,8 @@ void __init rtnetlink_init(void)
if (!rta_buf)
panic("rtnetlink_init: cannot allocate rta_buf\n");
- rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
+ rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
+ THIS_MODULE);
if (rtnl == NULL)
panic("rtnetlink_init: cannot initialize rtnetlink\n");
netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7eab867ede59..f80a28785610 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -68,7 +68,10 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-static kmem_cache_t *skbuff_head_cache;
+static kmem_cache_t *skbuff_head_cache __read_mostly;
+static kmem_cache_t *skbuff_fclone_cache __read_mostly;
+
+struct timeval __read_mostly skb_tv_base;
/*
* Keep out-of-line to prevent kernel bloat.
@@ -118,7 +121,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
*/
/**
- * alloc_skb - allocate a network buffer
+ * __alloc_skb - allocate a network buffer
* @size: size to allocate
* @gfp_mask: allocation mask
*
@@ -129,14 +132,20 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
* Buffers may only be allocated from interrupts using a @gfp_mask of
* %GFP_ATOMIC.
*/
-struct sk_buff *alloc_skb(unsigned int size, unsigned int __nocast gfp_mask)
+struct sk_buff *__alloc_skb(unsigned int size, unsigned int __nocast gfp_mask,
+ int fclone)
{
struct sk_buff *skb;
u8 *data;
/* Get the HEAD */
- skb = kmem_cache_alloc(skbuff_head_cache,
- gfp_mask & ~__GFP_DMA);
+ if (fclone)
+ skb = kmem_cache_alloc(skbuff_fclone_cache,
+ gfp_mask & ~__GFP_DMA);
+ else
+ skb = kmem_cache_alloc(skbuff_head_cache,
+ gfp_mask & ~__GFP_DMA);
+
if (!skb)
goto out;
@@ -153,7 +162,15 @@ struct sk_buff *alloc_skb(unsigned int size, unsigned int __nocast gfp_mask)
skb->data = data;
skb->tail = data;
skb->end = data + size;
+ if (fclone) {
+ struct sk_buff *child = skb + 1;
+ atomic_t *fclone_ref = (atomic_t *) (child + 1);
+ skb->fclone = SKB_FCLONE_ORIG;
+ atomic_set(fclone_ref, 1);
+
+ child->fclone = SKB_FCLONE_UNAVAILABLE;
+ }
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->tso_size = 0;
@@ -266,8 +283,34 @@ void skb_release_data(struct sk_buff *skb)
*/
void kfree_skbmem(struct sk_buff *skb)
{
+ struct sk_buff *other;
+ atomic_t *fclone_ref;
+
skb_release_data(skb);
- kmem_cache_free(skbuff_head_cache, skb);
+ switch (skb->fclone) {
+ case SKB_FCLONE_UNAVAILABLE:
+ kmem_cache_free(skbuff_head_cache, skb);
+ break;
+
+ case SKB_FCLONE_ORIG:
+ fclone_ref = (atomic_t *) (skb + 2);
+ if (atomic_dec_and_test(fclone_ref))
+ kmem_cache_free(skbuff_fclone_cache, skb);
+ break;
+
+ case SKB_FCLONE_CLONE:
+ fclone_ref = (atomic_t *) (skb + 1);
+ other = skb - 1;
+
+ /* The clone portion is available for
+ * fast-cloning again.
+ */
+ skb->fclone = SKB_FCLONE_UNAVAILABLE;
+
+ if (atomic_dec_and_test(fclone_ref))
+ kmem_cache_free(skbuff_fclone_cache, other);
+ break;
+ };
}
/**
@@ -281,8 +324,6 @@ void kfree_skbmem(struct sk_buff *skb)
void __kfree_skb(struct sk_buff *skb)
{
- BUG_ON(skb->list != NULL);
-
dst_release(skb->dst);
#ifdef CONFIG_XFRM
secpath_put(skb->sp);
@@ -302,7 +343,6 @@ void __kfree_skb(struct sk_buff *skb)
skb->tc_index = 0;
#ifdef CONFIG_NET_CLS_ACT
skb->tc_verd = 0;
- skb->tc_classid = 0;
#endif
#endif
@@ -325,19 +365,27 @@ void __kfree_skb(struct sk_buff *skb)
struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask)
{
- struct sk_buff *n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
-
- if (!n)
- return NULL;
+ struct sk_buff *n;
+
+ n = skb + 1;
+ if (skb->fclone == SKB_FCLONE_ORIG &&
+ n->fclone == SKB_FCLONE_UNAVAILABLE) {
+ atomic_t *fclone_ref = (atomic_t *) (n + 1);
+ n->fclone = SKB_FCLONE_CLONE;
+ atomic_inc(fclone_ref);
+ } else {
+ n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
+ if (!n)
+ return NULL;
+ n->fclone = SKB_FCLONE_UNAVAILABLE;
+ }
#define C(x) n->x = skb->x
n->next = n->prev = NULL;
- n->list = NULL;
n->sk = NULL;
- C(stamp);
+ C(tstamp);
C(dev);
- C(real_dev);
C(h);
C(nh);
C(mac);
@@ -361,7 +409,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask)
n->destructor = NULL;
#ifdef CONFIG_NETFILTER
C(nfmark);
- C(nfcache);
C(nfct);
nf_conntrack_get(skb->nfct);
C(nfctinfo);
@@ -370,9 +417,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask)
nf_bridge_get(skb->nf_bridge);
#endif
#endif /*CONFIG_NETFILTER*/
-#if defined(CONFIG_HIPPI)
- C(private);
-#endif
#ifdef CONFIG_NET_SCHED
C(tc_index);
#ifdef CONFIG_NET_CLS_ACT
@@ -380,7 +424,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask)
n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
C(input_dev);
- C(tc_classid);
#endif
#endif
@@ -404,10 +447,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
*/
unsigned long offset = new->data - old->data;
- new->list = NULL;
new->sk = NULL;
new->dev = old->dev;
- new->real_dev = old->real_dev;
new->priority = old->priority;
new->protocol = old->protocol;
new->dst = dst_clone(old->dst);
@@ -419,12 +460,12 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->mac.raw = old->mac.raw + offset;
memcpy(new->cb, old->cb, sizeof(old->cb));
new->local_df = old->local_df;
+ new->fclone = SKB_FCLONE_UNAVAILABLE;
new->pkt_type = old->pkt_type;
- new->stamp = old->stamp;
+ new->tstamp = old->tstamp;
new->destructor = NULL;
#ifdef CONFIG_NETFILTER
new->nfmark = old->nfmark;
- new->nfcache = old->nfcache;
new->nfct = old->nfct;
nf_conntrack_get(old->nfct);
new->nfctinfo = old->nfctinfo;
@@ -1344,50 +1385,43 @@ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
__skb_queue_tail(list, newsk);
spin_unlock_irqrestore(&list->lock, flags);
}
+
/**
* skb_unlink - remove a buffer from a list
* @skb: buffer to remove
+ * @list: list to use
*
- * Place a packet after a given packet in a list. The list locks are taken
- * and this function is atomic with respect to other list locked calls
+ * Remove a packet from a list. The list locks are taken and this
+ * function is atomic with respect to other list locked calls
*
- * Works even without knowing the list it is sitting on, which can be
- * handy at times. It also means that THE LIST MUST EXIST when you
- * unlink. Thus a list must have its contents unlinked before it is
- * destroyed.
+ * You must know what list the SKB is on.
*/
-void skb_unlink(struct sk_buff *skb)
+void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
- struct sk_buff_head *list = skb->list;
-
- if (list) {
- unsigned long flags;
+ unsigned long flags;
- spin_lock_irqsave(&list->lock, flags);
- if (skb->list == list)
- __skb_unlink(skb, skb->list);
- spin_unlock_irqrestore(&list->lock, flags);
- }
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_unlink(skb, list);
+ spin_unlock_irqrestore(&list->lock, flags);
}
-
/**
* skb_append - append a buffer
* @old: buffer to insert after
* @newsk: buffer to insert
+ * @list: list to use
*
* Place a packet after a given packet in a list. The list locks are taken
* and this function is atomic with respect to other list locked calls.
* A buffer cannot be placed on two lists at the same time.
*/
-
-void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
{
unsigned long flags;
- spin_lock_irqsave(&old->list->lock, flags);
- __skb_append(old, newsk);
- spin_unlock_irqrestore(&old->list->lock, flags);
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_append(old, newsk, list);
+ spin_unlock_irqrestore(&list->lock, flags);
}
@@ -1395,19 +1429,21 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
* skb_insert - insert a buffer
* @old: buffer to insert before
* @newsk: buffer to insert
+ * @list: list to use
+ *
+ * Place a packet before a given packet in a list. The list locks are
+ * taken and this function is atomic with respect to other list locked
+ * calls.
*
- * Place a packet before a given packet in a list. The list locks are taken
- * and this function is atomic with respect to other list locked calls
* A buffer cannot be placed on two lists at the same time.
*/
-
-void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
{
unsigned long flags;
- spin_lock_irqsave(&old->list->lock, flags);
- __skb_insert(newsk, old->prev, old, old->list);
- spin_unlock_irqrestore(&old->list->lock, flags);
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_insert(newsk, old->prev, old, list);
+ spin_unlock_irqrestore(&list->lock, flags);
}
#if 0
@@ -1663,12 +1699,23 @@ void __init skb_init(void)
NULL, NULL);
if (!skbuff_head_cache)
panic("cannot create skbuff cache");
+
+ skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
+ (2*sizeof(struct sk_buff)) +
+ sizeof(atomic_t),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!skbuff_fclone_cache)
+ panic("cannot create skbuff cache");
+
+ do_gettimeofday(&skb_tv_base);
}
EXPORT_SYMBOL(___pskb_trim);
EXPORT_SYMBOL(__kfree_skb);
EXPORT_SYMBOL(__pskb_pull_tail);
-EXPORT_SYMBOL(alloc_skb);
+EXPORT_SYMBOL(__alloc_skb);
EXPORT_SYMBOL(pskb_copy);
EXPORT_SYMBOL(pskb_expand_head);
EXPORT_SYMBOL(skb_checksum);
@@ -1696,3 +1743,4 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
EXPORT_SYMBOL(skb_seq_read);
EXPORT_SYMBOL(skb_abort_seq_read);
EXPORT_SYMBOL(skb_find_text);
+EXPORT_SYMBOL(skb_tv_base);
diff --git a/net/core/sock.c b/net/core/sock.c
index 12f6d9a2a522..ac63b56e23b2 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -260,7 +260,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
if (val > sysctl_wmem_max)
val = sysctl_wmem_max;
-
+set_sndbuf:
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
if ((val * 2) < SOCK_MIN_SNDBUF)
sk->sk_sndbuf = SOCK_MIN_SNDBUF;
@@ -274,6 +274,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sk->sk_write_space(sk);
break;
+ case SO_SNDBUFFORCE:
+ if (!capable(CAP_NET_ADMIN)) {
+ ret = -EPERM;
+ break;
+ }
+ goto set_sndbuf;
+
case SO_RCVBUF:
/* Don't error on this BSD doesn't and if you think
about it this is right. Otherwise apps have to
@@ -282,7 +289,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
if (val > sysctl_rmem_max)
val = sysctl_rmem_max;
-
+set_rcvbuf:
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
/* FIXME: is this lower bound the right one? */
if ((val * 2) < SOCK_MIN_RCVBUF)
@@ -291,6 +298,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sk->sk_rcvbuf = val * 2;
break;
+ case SO_RCVBUFFORCE:
+ if (!capable(CAP_NET_ADMIN)) {
+ ret = -EPERM;
+ break;
+ }
+ goto set_rcvbuf;
+
case SO_KEEPALIVE:
#ifdef CONFIG_INET
if (sk->sk_protocol == IPPROTO_TCP)
@@ -327,11 +341,11 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sock_reset_flag(sk, SOCK_LINGER);
else {
#if (BITS_PER_LONG == 32)
- if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
+ if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
else
#endif
- sk->sk_lingertime = ling.l_linger * HZ;
+ sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
sock_set_flag(sk, SOCK_LINGER);
}
break;
@@ -686,6 +700,80 @@ void sk_free(struct sock *sk)
module_put(owner);
}
+struct sock *sk_clone(const struct sock *sk, const unsigned int __nocast priority)
+{
+ struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0);
+
+ if (newsk != NULL) {
+ struct sk_filter *filter;
+
+ memcpy(newsk, sk, sk->sk_prot->obj_size);
+
+ /* SANITY */
+ sk_node_init(&newsk->sk_node);
+ sock_lock_init(newsk);
+ bh_lock_sock(newsk);
+
+ atomic_set(&newsk->sk_rmem_alloc, 0);
+ atomic_set(&newsk->sk_wmem_alloc, 0);
+ atomic_set(&newsk->sk_omem_alloc, 0);
+ skb_queue_head_init(&newsk->sk_receive_queue);
+ skb_queue_head_init(&newsk->sk_write_queue);
+
+ rwlock_init(&newsk->sk_dst_lock);
+ rwlock_init(&newsk->sk_callback_lock);
+
+ newsk->sk_dst_cache = NULL;
+ newsk->sk_wmem_queued = 0;
+ newsk->sk_forward_alloc = 0;
+ newsk->sk_send_head = NULL;
+ newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
+ newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
+
+ sock_reset_flag(newsk, SOCK_DONE);
+ skb_queue_head_init(&newsk->sk_error_queue);
+
+ filter = newsk->sk_filter;
+ if (filter != NULL)
+ sk_filter_charge(newsk, filter);
+
+ if (unlikely(xfrm_sk_clone_policy(newsk))) {
+ /* It is still raw copy of parent, so invalidate
+ * destructor and make plain sk_free() */
+ newsk->sk_destruct = NULL;
+ sk_free(newsk);
+ newsk = NULL;
+ goto out;
+ }
+
+ newsk->sk_err = 0;
+ newsk->sk_priority = 0;
+ atomic_set(&newsk->sk_refcnt, 2);
+
+ /*
+ * Increment the counter in the same struct proto as the master
+ * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that
+ * is the same as sk->sk_prot->socks, as this field was copied
+ * with memcpy).
+ *
+ * This _changes_ the previous behaviour, where
+ * tcp_create_openreq_child always was incrementing the
+ * equivalent to tcp_prot->socks (inet_sock_nr), so this have
+ * to be taken into account in all callers. -acme
+ */
+ sk_refcnt_debug_inc(newsk);
+ newsk->sk_socket = NULL;
+ newsk->sk_sleep = NULL;
+
+ if (newsk->sk_prot->sockets_allocated)
+ atomic_inc(newsk->sk_prot->sockets_allocated);
+ }
+out:
+ return newsk;
+}
+
+EXPORT_SYMBOL_GPL(sk_clone);
+
void __init sk_init(void)
{
if (num_physpages <= 4096) {
@@ -1353,11 +1441,7 @@ void sk_common_release(struct sock *sk)
xfrm_sk_free_policy(sk);
-#ifdef INET_REFCNT_DEBUG
- if (atomic_read(&sk->sk_refcnt) != 1)
- printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n",
- sk, atomic_read(&sk->sk_refcnt));
-#endif
+ sk_refcnt_debug_release(sk);
sock_put(sk);
}
@@ -1368,7 +1452,8 @@ static LIST_HEAD(proto_list);
int proto_register(struct proto *prot, int alloc_slab)
{
- char *request_sock_slab_name;
+ char *request_sock_slab_name = NULL;
+ char *timewait_sock_slab_name;
int rc = -ENOBUFS;
if (alloc_slab) {
@@ -1399,6 +1484,23 @@ int proto_register(struct proto *prot, int alloc_slab)
goto out_free_request_sock_slab_name;
}
}
+
+ if (prot->twsk_obj_size) {
+ static const char mask[] = "tw_sock_%s";
+
+ timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+
+ if (timewait_sock_slab_name == NULL)
+ goto out_free_request_sock_slab;
+
+ sprintf(timewait_sock_slab_name, mask, prot->name);
+ prot->twsk_slab = kmem_cache_create(timewait_sock_slab_name,
+ prot->twsk_obj_size,
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (prot->twsk_slab == NULL)
+ goto out_free_timewait_sock_slab_name;
+ }
}
write_lock(&proto_list_lock);
@@ -1407,6 +1509,13 @@ int proto_register(struct proto *prot, int alloc_slab)
rc = 0;
out:
return rc;
+out_free_timewait_sock_slab_name:
+ kfree(timewait_sock_slab_name);
+out_free_request_sock_slab:
+ if (prot->rsk_prot && prot->rsk_prot->slab) {
+ kmem_cache_destroy(prot->rsk_prot->slab);
+ prot->rsk_prot->slab = NULL;
+ }
out_free_request_sock_slab_name:
kfree(request_sock_slab_name);
out_free_sock_slab:
@@ -1420,6 +1529,8 @@ EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot)
{
write_lock(&proto_list_lock);
+ list_del(&prot->node);
+ write_unlock(&proto_list_lock);
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
@@ -1434,8 +1545,13 @@ void proto_unregister(struct proto *prot)
prot->rsk_prot->slab = NULL;
}
- list_del(&prot->node);
- write_unlock(&proto_list_lock);
+ if (prot->twsk_slab != NULL) {
+ const char *name = kmem_cache_name(prot->twsk_slab);
+
+ kmem_cache_destroy(prot->twsk_slab);
+ kfree(name);
+ prot->twsk_slab = NULL;
+ }
}
EXPORT_SYMBOL(proto_unregister);
@@ -1602,8 +1718,8 @@ EXPORT_SYMBOL(sock_wfree);
EXPORT_SYMBOL(sock_wmalloc);
EXPORT_SYMBOL(sock_i_uid);
EXPORT_SYMBOL(sock_i_ino);
-#ifdef CONFIG_SYSCTL
EXPORT_SYMBOL(sysctl_optmem_max);
+#ifdef CONFIG_SYSCTL
EXPORT_SYMBOL(sysctl_rmem_max);
EXPORT_SYMBOL(sysctl_wmem_max);
#endif
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 8f817ad9f546..2f278c8e4743 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -9,23 +9,18 @@
#include <linux/sysctl.h>
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/socket.h>
+#include <net/sock.h>
#ifdef CONFIG_SYSCTL
extern int netdev_max_backlog;
-extern int netdev_budget;
extern int weight_p;
-extern int net_msg_cost;
-extern int net_msg_burst;
extern __u32 sysctl_wmem_max;
extern __u32 sysctl_rmem_max;
-extern __u32 sysctl_wmem_default;
-extern __u32 sysctl_rmem_default;
extern int sysctl_core_destroy_delay;
-extern int sysctl_optmem_max;
-extern int sysctl_somaxconn;
#ifdef CONFIG_NET_DIVERT
extern char sysctl_divert_version[];
diff --git a/net/core/utils.c b/net/core/utils.c
index 88eb8b68e26b..7b5970fc9e40 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -16,7 +16,9 @@
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
+#include <linux/inet.h>
#include <linux/mm.h>
+#include <linux/net.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/random.h>
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 3ff5639c0b78..d17f1583ea3e 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -58,6 +58,13 @@
* o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
* Based on patch from Pavel Roskin <proski@gnu.org> :
* o Fix kernel data leak to user space in private handler handling
+ *
+ * v7 - 18.3.05 - Jean II
+ * o Remove (struct iw_point *)->pointer from events and streams
+ * o Remove spy_offset from struct iw_handler_def
+ * o Start deprecating dev->get_wireless_stats, output a warning
+ * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
+ * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
*/
/***************************** INCLUDES *****************************/
@@ -446,10 +453,14 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
(dev->wireless_handlers->get_wireless_stats != NULL))
return dev->wireless_handlers->get_wireless_stats(dev);
- /* Old location, will be phased out in next WE */
- return (dev->get_wireless_stats ?
- dev->get_wireless_stats(dev) :
- (struct iw_statistics *) NULL);
+ /* Old location, field to be removed in next WE */
+ if(dev->get_wireless_stats) {
+ printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
+ dev->name);
+ return dev->get_wireless_stats(dev);
+ }
+ /* Not found */
+ return (struct iw_statistics *) NULL;
}
/* ---------------------------------------------------------------- */
@@ -541,16 +552,18 @@ static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
dev->name, stats->status, stats->qual.qual,
stats->qual.updated & IW_QUAL_QUAL_UPDATED
? '.' : ' ',
- ((__u8) stats->qual.level),
+ ((__s32) stats->qual.level) -
+ ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
stats->qual.updated & IW_QUAL_LEVEL_UPDATED
? '.' : ' ',
- ((__u8) stats->qual.noise),
+ ((__s32) stats->qual.noise) -
+ ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
stats->qual.updated & IW_QUAL_NOISE_UPDATED
? '.' : ' ',
stats->discard.nwid, stats->discard.code,
stats->discard.fragment, stats->discard.retries,
stats->discard.misc, stats->miss.beacon);
- stats->qual.updated = 0;
+ stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
}
}
@@ -571,10 +584,6 @@ static int wireless_seq_show(struct seq_file *seq, void *v)
return 0;
}
-extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
-extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
-extern void dev_seq_stop(struct seq_file *seq, void *v);
-
static struct seq_operations wireless_seq_ops = {
.start = dev_seq_start,
.next = dev_seq_next,
@@ -597,6 +606,7 @@ static struct file_operations wireless_seq_fops = {
int __init wireless_proc_init(void)
{
+ /* Create /proc/net/wireless entry */
if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
return -ENOMEM;
@@ -631,9 +641,9 @@ static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
sizeof(struct iw_statistics)))
return -EFAULT;
- /* Check if we need to clear the update flag */
+ /* Check if we need to clear the updated flag */
if(wrq->u.data.flags != 0)
- stats->qual.updated = 0;
+ stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
return 0;
} else
return -EOPNOTSUPP;
@@ -1144,8 +1154,8 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
kfree_skb(skb);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
}
#endif /* WE_EVENT_NETLINK */
@@ -1165,10 +1175,11 @@ void wireless_send_event(struct net_device * dev,
struct iw_event *event; /* Mallocated whole event */
int event_len; /* Its size */
int hdr_len; /* Size of the event header */
+ int wrqu_off = 0; /* Offset in wrqu */
/* Don't "optimise" the following variable, it will crash */
unsigned cmd_index; /* *MUST* be unsigned */
- /* Get the description of the IOCTL */
+ /* Get the description of the Event */
if(cmd <= SIOCIWLAST) {
cmd_index = cmd - SIOCIWFIRST;
if(cmd_index < standard_ioctl_num)
@@ -1211,6 +1222,8 @@ void wireless_send_event(struct net_device * dev,
/* Calculate extra_len - extra is NULL for restricted events */
if(extra != NULL)
extra_len = wrqu->data.length * descr->token_size;
+ /* Always at an offset in wrqu */
+ wrqu_off = IW_EV_POINT_OFF;
#ifdef WE_EVENT_DEBUG
printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
#endif /* WE_EVENT_DEBUG */
@@ -1221,7 +1234,7 @@ void wireless_send_event(struct net_device * dev,
event_len = hdr_len + extra_len;
#ifdef WE_EVENT_DEBUG
- printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len);
+ printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, wrqu_off %d, event_len %d\n", dev->name, cmd, hdr_len, wrqu_off, event_len);
#endif /* WE_EVENT_DEBUG */
/* Create temporary buffer to hold the event */
@@ -1232,7 +1245,7 @@ void wireless_send_event(struct net_device * dev,
/* Fill event */
event->len = event_len;
event->cmd = cmd;
- memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN);
+ memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
if(extra != NULL)
memcpy(((char *) event) + hdr_len, extra, extra_len);
@@ -1253,7 +1266,7 @@ void wireless_send_event(struct net_device * dev,
* Now, the driver can delegate this task to Wireless Extensions.
* It needs to use those standard spy iw_handler in struct iw_handler_def,
* push data to us via wireless_spy_update() and include struct iw_spy_data
- * in its private part (and advertise it in iw_handler_def->spy_offset).
+ * in its private part (and export it in net_device->wireless_data->spy_data).
* One of the main advantage of centralising spy support here is that
* it becomes much easier to improve and extend it without having to touch
* the drivers. One example is the addition of the Spy-Threshold events.
@@ -1270,10 +1283,7 @@ static inline struct iw_spy_data * get_spydata(struct net_device *dev)
/* This is the new way */
if(dev->wireless_data)
return(dev->wireless_data->spy_data);
-
- /* This is the old way. Doesn't work for multi-headed drivers.
- * It will be removed in the next version of WE. */
- return (dev->priv + dev->wireless_handlers->spy_offset);
+ return NULL;
}
/*------------------------------------------------------------------*/
@@ -1288,10 +1298,6 @@ int iw_handler_set_spy(struct net_device * dev,
struct iw_spy_data * spydata = get_spydata(dev);
struct sockaddr * address = (struct sockaddr *) extra;
- if(!dev->wireless_data)
- /* Help user know that driver needs updating */
- printk(KERN_DEBUG "%s (WE) : Driver using old/buggy spy support, please fix driver !\n",
- dev->name);
/* Make sure driver is not buggy or using the old API */
if(!spydata)
return -EOPNOTSUPP;
@@ -1322,7 +1328,7 @@ int iw_handler_set_spy(struct net_device * dev,
sizeof(struct iw_quality) * IW_MAX_SPY);
#ifdef WE_SPY_DEBUG
- printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
+ printk(KERN_DEBUG "iw_handler_set_spy() : wireless_data %p, spydata %p, num %d\n", dev->wireless_data, spydata, wrqu->data.length);
for (i = 0; i < wrqu->data.length; i++)
printk(KERN_DEBUG
"%02X:%02X:%02X:%02X:%02X:%02X \n",
@@ -1375,7 +1381,7 @@ int iw_handler_get_spy(struct net_device * dev,
sizeof(struct iw_quality) * spydata->spy_number);
/* Reset updated flags. */
for(i = 0; i < spydata->spy_number; i++)
- spydata->spy_stat[i].updated = 0;
+ spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
return 0;
}
@@ -1490,7 +1496,7 @@ void wireless_spy_update(struct net_device * dev,
return;
#ifdef WE_SPY_DEBUG
- printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+ printk(KERN_DEBUG "wireless_spy_update() : wireless_data %p, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_data, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
#endif /* WE_SPY_DEBUG */
/* Update all records that match */
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
new file mode 100644
index 000000000000..187ac182e24b
--- /dev/null
+++ b/net/dccp/Kconfig
@@ -0,0 +1,50 @@
+menu "DCCP Configuration (EXPERIMENTAL)"
+ depends on INET && EXPERIMENTAL
+
+config IP_DCCP
+ tristate "The DCCP Protocol (EXPERIMENTAL)"
+ ---help---
+ Datagram Congestion Control Protocol
+
+ From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.
+
+ The Datagram Congestion Control Protocol (DCCP) is a transport
+ protocol that implements bidirectional, unicast connections of
+ congestion-controlled, unreliable datagrams. It should be suitable
+ for use by applications such as streaming media, Internet telephony,
+ and on-line games
+
+ To compile this protocol support as a module, choose M here: the
+ module will be called dccp.
+
+ If in doubt, say N.
+
+config INET_DCCP_DIAG
+ depends on IP_DCCP && INET_DIAG
+ def_tristate y if (IP_DCCP = y && INET_DIAG = y)
+ def_tristate m
+
+source "net/dccp/ccids/Kconfig"
+
+menu "DCCP Kernel Hacking"
+ depends on IP_DCCP && DEBUG_KERNEL=y
+
+config IP_DCCP_DEBUG
+ bool "DCCP debug messages"
+ ---help---
+ Only use this if you're hacking DCCP.
+
+ Just say N.
+
+config IP_DCCP_UNLOAD_HACK
+ depends on IP_DCCP=m && IP_DCCP_CCID3=m
+ bool "DCCP control sock unload hack"
+ ---help---
+ Enable this to be able to unload the dccp module when the it
+ has only one refcount held, the control sock one. Just execute
+ "rmmod dccp_ccid3 dccp"
+
+ Just say N.
+endmenu
+
+endmenu
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
new file mode 100644
index 000000000000..fb97bb042455
--- /dev/null
+++ b/net/dccp/Makefile
@@ -0,0 +1,10 @@
+obj-$(CONFIG_IP_DCCP) += dccp.o
+
+dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
+ timer.o
+
+obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
+
+dccp_diag-y := diag.o
+
+obj-y += ccids/
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
new file mode 100644
index 000000000000..9d8fc0e289ea
--- /dev/null
+++ b/net/dccp/ccid.c
@@ -0,0 +1,139 @@
+/*
+ * net/dccp/ccid.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * CCID infrastructure
+ *
+ * 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 "ccid.h"
+
+static struct ccid *ccids[CCID_MAX];
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+static atomic_t ccids_lockct = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(ccids_lock);
+
+/*
+ * The strategy is: modifications ccids vector are short, do not sleep and
+ * veeery rare, but read access should be free of any exclusive locks.
+ */
+static void ccids_write_lock(void)
+{
+ spin_lock(&ccids_lock);
+ while (atomic_read(&ccids_lockct) != 0) {
+ spin_unlock(&ccids_lock);
+ yield();
+ spin_lock(&ccids_lock);
+ }
+}
+
+static inline void ccids_write_unlock(void)
+{
+ spin_unlock(&ccids_lock);
+}
+
+static inline void ccids_read_lock(void)
+{
+ atomic_inc(&ccids_lockct);
+ spin_unlock_wait(&ccids_lock);
+}
+
+static inline void ccids_read_unlock(void)
+{
+ atomic_dec(&ccids_lockct);
+}
+
+#else
+#define ccids_write_lock() do { } while(0)
+#define ccids_write_unlock() do { } while(0)
+#define ccids_read_lock() do { } while(0)
+#define ccids_read_unlock() do { } while(0)
+#endif
+
+int ccid_register(struct ccid *ccid)
+{
+ int err;
+
+ if (ccid->ccid_init == NULL)
+ return -1;
+
+ ccids_write_lock();
+ err = -EEXIST;
+ if (ccids[ccid->ccid_id] == NULL) {
+ ccids[ccid->ccid_id] = ccid;
+ err = 0;
+ }
+ ccids_write_unlock();
+ if (err == 0)
+ pr_info("CCID: Registered CCID %d (%s)\n",
+ ccid->ccid_id, ccid->ccid_name);
+ return err;
+}
+
+EXPORT_SYMBOL_GPL(ccid_register);
+
+int ccid_unregister(struct ccid *ccid)
+{
+ ccids_write_lock();
+ ccids[ccid->ccid_id] = NULL;
+ ccids_write_unlock();
+ pr_info("CCID: Unregistered CCID %d (%s)\n",
+ ccid->ccid_id, ccid->ccid_name);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ccid_unregister);
+
+struct ccid *ccid_init(unsigned char id, struct sock *sk)
+{
+ struct ccid *ccid;
+
+#ifdef CONFIG_KMOD
+ if (ccids[id] == NULL)
+ request_module("net-dccp-ccid-%d", id);
+#endif
+ ccids_read_lock();
+
+ ccid = ccids[id];
+ if (ccid == NULL)
+ goto out;
+
+ if (!try_module_get(ccid->ccid_owner))
+ goto out_err;
+
+ if (ccid->ccid_init(sk) != 0)
+ goto out_module_put;
+out:
+ ccids_read_unlock();
+ return ccid;
+out_module_put:
+ module_put(ccid->ccid_owner);
+out_err:
+ ccid = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(ccid_init);
+
+void ccid_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid == NULL)
+ return;
+
+ ccids_read_lock();
+
+ if (ccids[ccid->ccid_id] != NULL) {
+ if (ccid->ccid_exit != NULL)
+ ccid->ccid_exit(sk);
+ module_put(ccid->ccid_owner);
+ }
+
+ ccids_read_unlock();
+}
+
+EXPORT_SYMBOL_GPL(ccid_exit);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
new file mode 100644
index 000000000000..962f1e9e2f7e
--- /dev/null
+++ b/net/dccp/ccid.h
@@ -0,0 +1,180 @@
+#ifndef _CCID_H
+#define _CCID_H
+/*
+ * net/dccp/ccid.h
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * CCID infrastructure
+ *
+ * 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 <net/sock.h>
+#include <linux/dccp.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#define CCID_MAX 255
+
+struct ccid {
+ unsigned char ccid_id;
+ const char *ccid_name;
+ struct module *ccid_owner;
+ int (*ccid_init)(struct sock *sk);
+ void (*ccid_exit)(struct sock *sk);
+ int (*ccid_hc_rx_init)(struct sock *sk);
+ int (*ccid_hc_tx_init)(struct sock *sk);
+ void (*ccid_hc_rx_exit)(struct sock *sk);
+ void (*ccid_hc_tx_exit)(struct sock *sk);
+ void (*ccid_hc_rx_packet_recv)(struct sock *sk,
+ struct sk_buff *skb);
+ int (*ccid_hc_rx_parse_options)(struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value);
+ void (*ccid_hc_rx_insert_options)(struct sock *sk,
+ struct sk_buff *skb);
+ void (*ccid_hc_tx_insert_options)(struct sock *sk,
+ struct sk_buff *skb);
+ void (*ccid_hc_tx_packet_recv)(struct sock *sk,
+ struct sk_buff *skb);
+ int (*ccid_hc_tx_parse_options)(struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value);
+ int (*ccid_hc_tx_send_packet)(struct sock *sk,
+ struct sk_buff *skb, int len);
+ void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more,
+ int len);
+ void (*ccid_hc_rx_get_info)(struct sock *sk,
+ struct tcp_info *info);
+ void (*ccid_hc_tx_get_info)(struct sock *sk,
+ struct tcp_info *info);
+};
+
+extern int ccid_register(struct ccid *ccid);
+extern int ccid_unregister(struct ccid *ccid);
+
+extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
+extern void ccid_exit(struct ccid *ccid, struct sock *sk);
+
+static inline void __ccid_get(struct ccid *ccid)
+{
+ __module_get(ccid->ccid_owner);
+}
+
+static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb, int len)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_send_packet != NULL)
+ rc = ccid->ccid_hc_tx_send_packet(sk, skb, len);
+ return rc;
+}
+
+static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
+ int more, int len)
+{
+ if (ccid->ccid_hc_tx_packet_sent != NULL)
+ ccid->ccid_hc_tx_packet_sent(sk, more, len);
+}
+
+static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_rx_init != NULL)
+ rc = ccid->ccid_hc_rx_init(sk);
+ return rc;
+}
+
+static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_init != NULL)
+ rc = ccid->ccid_hc_tx_init(sk);
+ return rc;
+}
+
+static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid->ccid_hc_rx_exit != NULL &&
+ dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
+ ccid->ccid_hc_rx_exit(sk);
+}
+
+static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid->ccid_hc_tx_exit != NULL &&
+ dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
+ ccid->ccid_hc_tx_exit(sk);
+}
+
+static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_rx_packet_recv != NULL)
+ ccid->ccid_hc_rx_packet_recv(sk, skb);
+}
+
+static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_tx_packet_recv != NULL)
+ ccid->ccid_hc_tx_packet_recv(sk, skb);
+}
+
+static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_parse_options != NULL)
+ rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx,
+ value);
+ return rc;
+}
+
+static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_rx_parse_options != NULL)
+ rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value);
+ return rc;
+}
+
+static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_tx_insert_options != NULL)
+ ccid->ccid_hc_tx_insert_options(sk, skb);
+}
+
+static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_rx_insert_options != NULL)
+ ccid->ccid_hc_rx_insert_options(sk, skb);
+}
+
+static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
+ struct tcp_info *info)
+{
+ if (ccid->ccid_hc_rx_get_info != NULL)
+ ccid->ccid_hc_rx_get_info(sk, info);
+}
+
+static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
+ struct tcp_info *info)
+{
+ if (ccid->ccid_hc_tx_get_info != NULL)
+ ccid->ccid_hc_tx_get_info(sk, info);
+}
+#endif /* _CCID_H */
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
new file mode 100644
index 000000000000..7684d83946a4
--- /dev/null
+++ b/net/dccp/ccids/Kconfig
@@ -0,0 +1,29 @@
+menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
+ depends on IP_DCCP && EXPERIMENTAL
+
+config IP_DCCP_CCID3
+ tristate "CCID3 (TFRC) (EXPERIMENTAL)"
+ depends on IP_DCCP
+ ---help---
+ CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
+ rate-controlled congestion control mechanism. TFRC is designed to
+ be reasonably fair when competing for bandwidth with TCP-like flows,
+ where a flow is "reasonably fair" if its sending rate is generally
+ within a factor of two of the sending rate of a TCP flow under the
+ same conditions. However, TFRC has a much lower variation of
+ throughput over time compared with TCP, which makes CCID 3 more
+ suitable than CCID 2 for applications such streaming media where a
+ relatively smooth sending rate is of importance.
+
+ CCID 3 is further described in [CCID 3 PROFILE]. The TFRC
+ congestion control algorithms were initially described in RFC 3448.
+
+ This text was extracted from draft-ietf-dccp-spec-11.txt.
+
+ If in doubt, say M.
+
+config IP_DCCP_TFRC_LIB
+ depends on IP_DCCP_CCID3
+ def_tristate IP_DCCP_CCID3
+
+endmenu
diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile
new file mode 100644
index 000000000000..956f79f50743
--- /dev/null
+++ b/net/dccp/ccids/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o
+
+dccp_ccid3-y := ccid3.o
+
+obj-y += lib/
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
new file mode 100644
index 000000000000..38aa84986118
--- /dev/null
+++ b/net/dccp/ccids/ccid3.c
@@ -0,0 +1,1214 @@
+/*
+ * net/dccp/ccids/ccid3.c
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *
+ * An implementation of the DCCP protocol
+ *
+ * This code has been developed by the University of Waikato WAND
+ * research group. For further information please see http://www.wand.net.nz/
+ *
+ * This code also uses code from Lulea University, rereleased as GPL by its
+ * authors:
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
+ * and to make it work as a loadable module in the DCCP stack written by
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
+ *
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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/config.h>
+#include "../ccid.h"
+#include "../dccp.h"
+#include "lib/packet_history.h"
+#include "lib/loss_interval.h"
+#include "lib/tfrc.h"
+#include "ccid3.h"
+
+/*
+ * Reason for maths here is to avoid 32 bit overflow when a is big.
+ * With this we get close to the limit.
+ */
+static inline u32 usecs_div(const u32 a, const u32 b)
+{
+ const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 :
+ a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 :
+ a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 :
+ a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 :
+ a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 :
+ a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 :
+ a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
+ a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
+ 100000;
+ const u32 tmp = a * (USEC_PER_SEC / div);
+ return (b >= 2 * div) ? tmp / (b / div) : tmp;
+}
+
+static int ccid3_debug;
+
+#ifdef CCID3_DEBUG
+#define ccid3_pr_debug(format, a...) \
+ do { if (ccid3_debug) \
+ printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
+ } while (0)
+#else
+#define ccid3_pr_debug(format, a...)
+#endif
+
+static struct dccp_tx_hist *ccid3_tx_hist;
+static struct dccp_rx_hist *ccid3_rx_hist;
+static struct dccp_li_hist *ccid3_li_hist;
+
+static int ccid3_init(struct sock *sk)
+{
+ return 0;
+}
+
+static void ccid3_exit(struct sock *sk)
+{
+}
+
+/* TFRC sender states */
+enum ccid3_hc_tx_states {
+ TFRC_SSTATE_NO_SENT = 1,
+ TFRC_SSTATE_NO_FBACK,
+ TFRC_SSTATE_FBACK,
+ TFRC_SSTATE_TERM,
+};
+
+#ifdef CCID3_DEBUG
+static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
+{
+ static char *ccid3_state_names[] = {
+ [TFRC_SSTATE_NO_SENT] = "NO_SENT",
+ [TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
+ [TFRC_SSTATE_FBACK] = "FBACK",
+ [TFRC_SSTATE_TERM] = "TERM",
+ };
+
+ return ccid3_state_names[state];
+}
+#endif
+
+static inline void ccid3_hc_tx_set_state(struct sock *sk,
+ enum ccid3_hc_tx_states state)
+{
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
+
+ ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
+ dccp_role(sk), sk, ccid3_tx_state_name(oldstate),
+ ccid3_tx_state_name(state));
+ WARN_ON(state == oldstate);
+ hctx->ccid3hctx_state = state;
+}
+
+/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
+static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
+{
+ /*
+ * If no feedback spec says t_ipi is 1 second (set elsewhere and then
+ * doubles after every no feedback timer (separate function)
+ */
+ if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
+ hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_x);
+}
+
+/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
+static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
+{
+ hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
+ TFRC_OPSYS_HALF_TIME_GRAN);
+}
+
+/*
+ * Update X by
+ * If (p > 0)
+ * x_calc = calcX(s, R, p);
+ * X = max(min(X_calc, 2 * X_recv), s / t_mbi);
+ * Else
+ * If (now - tld >= R)
+ * X = max(min(2 * X, 2 * X_recv), s / R);
+ * tld = now;
+ */
+static void ccid3_hc_tx_update_x(struct sock *sk)
+{
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+ /* To avoid large error in calcX */
+ if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
+ hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_rtt,
+ hctx->ccid3hctx_p);
+ hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc,
+ 2 * hctx->ccid3hctx_x_recv),
+ (hctx->ccid3hctx_s /
+ TFRC_MAX_BACK_OFF_TIME));
+ } else {
+ struct timeval now;
+
+ dccp_timestamp(sk, &now);
+ if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
+ hctx->ccid3hctx_rtt) {
+ hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
+ hctx->ccid3hctx_x) * 2,
+ usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_rtt));
+ hctx->ccid3hctx_t_ld = now;
+ }
+ }
+}
+
+static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+ unsigned long next_tmout = 0;
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later. */
+ /* XXX: set some sensible MIB */
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ jiffies + HZ / 5);
+ goto out;
+ }
+
+ ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
+ ccid3_tx_state_name(hctx->ccid3hctx_state));
+
+ switch (hctx->ccid3hctx_state) {
+ case TFRC_SSTATE_TERM:
+ goto out;
+ case TFRC_SSTATE_NO_FBACK:
+ /* Halve send rate */
+ hctx->ccid3hctx_x /= 2;
+ if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
+ TFRC_MAX_BACK_OFF_TIME))
+ hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
+ TFRC_MAX_BACK_OFF_TIME);
+
+ ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
+ "bytes/s\n",
+ dccp_role(sk), sk,
+ ccid3_tx_state_name(hctx->ccid3hctx_state),
+ hctx->ccid3hctx_x);
+ next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_x),
+ TFRC_INITIAL_TIMEOUT);
+ /*
+ * FIXME - not sure above calculation is correct. See section
+ * 5 of CCID3 11 should adjust tx_t_ipi and double that to
+ * achieve it really
+ */
+ break;
+ case TFRC_SSTATE_FBACK:
+ /*
+ * Check if IDLE since last timeout and recv rate is less than
+ * 4 packets per RTT
+ */
+ if (!hctx->ccid3hctx_idle ||
+ (hctx->ccid3hctx_x_recv >=
+ 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
+ ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
+ dccp_role(sk), sk,
+ ccid3_tx_state_name(hctx->ccid3hctx_state));
+ /* Halve sending rate */
+
+ /* If (X_calc > 2 * X_recv)
+ * X_recv = max(X_recv / 2, s / (2 * t_mbi));
+ * Else
+ * X_recv = X_calc / 4;
+ */
+ BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P &&
+ hctx->ccid3hctx_x_calc == 0);
+
+ /* check also if p is zero -> x_calc is infinity? */
+ if (hctx->ccid3hctx_p < TFRC_SMALLEST_P ||
+ hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
+ hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
+ hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME));
+ else
+ hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
+
+ /* Update sending rate */
+ ccid3_hc_tx_update_x(sk);
+ }
+ /*
+ * Schedule no feedback timer to expire in
+ * max(4 * R, 2 * s / X)
+ */
+ next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
+ 2 * usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_x));
+ break;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
+ dump_stack();
+ goto out;
+ }
+
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
+ hctx->ccid3hctx_idle = 1;
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+static int ccid3_hc_tx_send_packet(struct sock *sk,
+ struct sk_buff *skb, int len)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ struct dccp_tx_hist_entry *new_packet;
+ struct timeval now;
+ long delay;
+ int rc = -ENOTCONN;
+
+ BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+
+ /* Check if pure ACK or Terminating*/
+ /*
+ * XXX: We only call this function for DATA and DATAACK, on, these
+ * packets can have zero length, but why the comment about "pure ACK"?
+ */
+ if (unlikely(len == 0))
+ goto out;
+
+ /* See if last packet allocated was not sent */
+ new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+ if (new_packet == NULL || new_packet->dccphtx_sent) {
+ new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
+ SLAB_ATOMIC);
+
+ rc = -ENOBUFS;
+ if (unlikely(new_packet == NULL)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough "
+ "mem to add to history, send refused\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ goto out;
+ }
+
+ dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
+ }
+
+ dccp_timestamp(sk, &now);
+
+ switch (hctx->ccid3hctx_state) {
+ case TFRC_SSTATE_NO_SENT:
+ hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
+ hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk;
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
+ hctx->ccid3hctx_last_win_count = 0;
+ hctx->ccid3hctx_t_last_win_count = now;
+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
+ hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI;
+
+ /* Set nominal send time for initial packet */
+ hctx->ccid3hctx_t_nom = now;
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
+ ccid3_calc_new_delta(hctx);
+ rc = 0;
+ break;
+ case TFRC_SSTATE_NO_FBACK:
+ case TFRC_SSTATE_FBACK:
+ delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
+ hctx->ccid3hctx_delta);
+ delay /= -1000;
+ /* divide by -1000 is to convert to ms and get sign right */
+ rc = delay > 0 ? delay : 0;
+ break;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
+ dump_stack();
+ rc = -EINVAL;
+ break;
+ }
+
+ /* Can we send? if so add options and add to packet history */
+ if (rc == 0) {
+ dp->dccps_hc_tx_insert_options = 1;
+ new_packet->dccphtx_ccval =
+ DCCP_SKB_CB(skb)->dccpd_ccval =
+ hctx->ccid3hctx_last_win_count;
+ }
+out:
+ return rc;
+}
+
+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ struct timeval now;
+
+ BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+
+ dccp_timestamp(sk, &now);
+
+ /* check if we have sent a data packet */
+ if (len > 0) {
+ unsigned long quarter_rtt;
+ struct dccp_tx_hist_entry *packet;
+
+ packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+ if (unlikely(packet == NULL)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't "
+ "exists in history!\n", __FUNCTION__);
+ return;
+ }
+ if (unlikely(packet->dccphtx_sent)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in "
+ "history!\n", __FUNCTION__);
+ return;
+ }
+ packet->dccphtx_tstamp = now;
+ packet->dccphtx_seqno = dp->dccps_gss;
+ /*
+ * Check if win_count have changed
+ * Algorithm in "8.1. Window Counter Valuer" in
+ * draft-ietf-dccp-ccid3-11.txt
+ */
+ quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
+ if (likely(hctx->ccid3hctx_rtt > 8))
+ quarter_rtt /= hctx->ccid3hctx_rtt / 4;
+
+ if (quarter_rtt > 0) {
+ hctx->ccid3hctx_t_last_win_count = now;
+ hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
+ min_t(unsigned long, quarter_rtt, 5)) % 16;
+ ccid3_pr_debug("%s, sk=%p, window changed from "
+ "%u to %u!\n",
+ dccp_role(sk), sk,
+ packet->dccphtx_ccval,
+ hctx->ccid3hctx_last_win_count);
+ }
+
+ hctx->ccid3hctx_idle = 0;
+ packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
+ packet->dccphtx_sent = 1;
+ } else
+ ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
+ dccp_role(sk), sk, dp->dccps_gss);
+
+ switch (hctx->ccid3hctx_state) {
+ case TFRC_SSTATE_NO_SENT:
+ /* if first wasn't pure ack */
+ if (len != 0)
+ printk(KERN_CRIT "%s: %s, First packet sent is noted "
+ "as a data packet\n",
+ __FUNCTION__, dccp_role(sk));
+ return;
+ case TFRC_SSTATE_NO_FBACK:
+ case TFRC_SSTATE_FBACK:
+ if (len > 0) {
+ hctx->ccid3hctx_t_nom = now;
+ ccid3_calc_new_t_ipi(hctx);
+ ccid3_calc_new_delta(hctx);
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
+ }
+ break;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
+ dump_stack();
+ break;
+ }
+}
+
+static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ struct ccid3_options_received *opt_recv;
+ struct dccp_tx_hist_entry *packet;
+ struct timeval now;
+ unsigned long next_tmout;
+ u32 t_elapsed;
+ u32 pinv;
+ u32 x_recv;
+ u32 r_sample;
+
+ BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
+
+ /* we are only interested in ACKs */
+ if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
+ DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
+ return;
+
+ opt_recv = &hctx->ccid3hctx_options_received;
+
+ t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
+ x_recv = opt_recv->ccid3or_receive_rate;
+ pinv = opt_recv->ccid3or_loss_event_rate;
+
+ switch (hctx->ccid3hctx_state) {
+ case TFRC_SSTATE_NO_SENT:
+ /* FIXME: what to do here? */
+ return;
+ case TFRC_SSTATE_NO_FBACK:
+ case TFRC_SSTATE_FBACK:
+ /* Calculate new round trip sample by
+ * R_sample = (now - t_recvdata) - t_delay */
+ /* get t_recvdata from history */
+ packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ if (unlikely(packet == NULL)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno "
+ "%llu(%s) does't exist in history!\n",
+ __FUNCTION__, dccp_role(sk), sk,
+ (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+ return;
+ }
+
+ /* Update RTT */
+ dccp_timestamp(sk, &now);
+ r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
+ if (unlikely(r_sample <= t_elapsed))
+ LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
+ "t_elapsed=%uus\n",
+ __FUNCTION__, r_sample, t_elapsed);
+ else
+ r_sample -= t_elapsed;
+
+ /* Update RTT estimate by
+ * If (No feedback recv)
+ * R = R_sample;
+ * Else
+ * R = q * R + (1 - q) * R_sample;
+ *
+ * q is a constant, RFC 3448 recomments 0.9
+ */
+ if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
+ hctx->ccid3hctx_rtt = r_sample;
+ } else
+ hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
+ r_sample / 10;
+
+ ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
+ "r_sample=%us\n", dccp_role(sk), sk,
+ hctx->ccid3hctx_rtt, r_sample);
+
+ /* Update timeout interval */
+ hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
+ USEC_PER_SEC);
+
+ /* Update receive rate */
+ hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */
+
+ /* Update loss event rate */
+ if (pinv == ~0 || pinv == 0)
+ hctx->ccid3hctx_p = 0;
+ else {
+ hctx->ccid3hctx_p = 1000000 / pinv;
+
+ if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) {
+ hctx->ccid3hctx_p = TFRC_SMALLEST_P;
+ ccid3_pr_debug("%s, sk=%p, Smallest p used!\n",
+ dccp_role(sk), sk);
+ }
+ }
+
+ /* unschedule no feedback timer */
+ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
+
+ /* Update sending rate */
+ ccid3_hc_tx_update_x(sk);
+
+ /* Update next send time */
+ timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
+ ccid3_calc_new_t_ipi(hctx);
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
+ ccid3_calc_new_delta(hctx);
+
+ /* remove all packets older than the one acked from history */
+ dccp_tx_hist_purge_older(ccid3_tx_hist,
+ &hctx->ccid3hctx_hist, packet);
+ /*
+ * As we have calculated new ipi, delta, t_nom it is possible that
+ * we now can send a packet, so wake up dccp_wait_for_ccids.
+ */
+ sk->sk_write_space(sk);
+
+ /*
+ * Schedule no feedback timer to expire in
+ * max(4 * R, 2 * s / X)
+ */
+ next_tmout = max(hctx->ccid3hctx_t_rto,
+ 2 * usecs_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_x));
+
+ ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
+ "expire in %lu jiffies (%luus)\n",
+ dccp_role(sk), sk,
+ usecs_to_jiffies(next_tmout), next_tmout);
+
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
+
+ /* set idle flag */
+ hctx->ccid3hctx_idle = 1;
+ break;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
+ dump_stack();
+ break;
+ }
+}
+
+static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
+{
+ const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+ BUG_ON(hctx == NULL);
+
+ if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
+ return;
+
+ DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
+}
+
+static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char *value)
+{
+ int rc = 0;
+ const struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ struct ccid3_options_received *opt_recv;
+
+ BUG_ON(hctx == NULL);
+
+ opt_recv = &hctx->ccid3hctx_options_received;
+
+ if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
+ opt_recv->ccid3or_seqno = dp->dccps_gsr;
+ opt_recv->ccid3or_loss_event_rate = ~0;
+ opt_recv->ccid3or_loss_intervals_idx = 0;
+ opt_recv->ccid3or_loss_intervals_len = 0;
+ opt_recv->ccid3or_receive_rate = 0;
+ }
+
+ switch (option) {
+ case TFRC_OPT_LOSS_EVENT_RATE:
+ if (unlikely(len != 4)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
+ "len for TFRC_OPT_LOSS_EVENT_RATE\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ rc = -EINVAL;
+ } else {
+ opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value);
+ ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
+ dccp_role(sk), sk,
+ opt_recv->ccid3or_loss_event_rate);
+ }
+ break;
+ case TFRC_OPT_LOSS_INTERVALS:
+ opt_recv->ccid3or_loss_intervals_idx = idx;
+ opt_recv->ccid3or_loss_intervals_len = len;
+ ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
+ dccp_role(sk), sk,
+ opt_recv->ccid3or_loss_intervals_idx,
+ opt_recv->ccid3or_loss_intervals_len);
+ break;
+ case TFRC_OPT_RECEIVE_RATE:
+ if (unlikely(len != 4)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
+ "len for TFRC_OPT_RECEIVE_RATE\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ rc = -EINVAL;
+ } else {
+ opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value);
+ ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
+ dccp_role(sk), sk,
+ opt_recv->ccid3or_receive_rate);
+ }
+ break;
+ }
+
+ return rc;
+}
+
+static int ccid3_hc_tx_init(struct sock *sk)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx;
+
+ dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
+ if (dp->dccps_hc_tx_ccid_private == NULL)
+ return -ENOMEM;
+
+ hctx = ccid3_hc_tx_sk(sk);
+ memset(hctx, 0, sizeof(*hctx));
+
+ if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
+ dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
+ hctx->ccid3hctx_s = dp->dccps_packet_size;
+ else
+ hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;
+
+ /* Set transmission rate to 1 packet per second */
+ hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+ hctx->ccid3hctx_t_rto = USEC_PER_SEC;
+ hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
+ INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
+ init_timer(&hctx->ccid3hctx_no_feedback_timer);
+
+ return 0;
+}
+
+static void ccid3_hc_tx_exit(struct sock *sk)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+ BUG_ON(hctx == NULL);
+
+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
+ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
+
+ /* Empty packet history */
+ dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
+
+ kfree(dp->dccps_hc_tx_ccid_private);
+ dp->dccps_hc_tx_ccid_private = NULL;
+}
+
+/*
+ * RX Half Connection methods
+ */
+
+/* TFRC receiver states */
+enum ccid3_hc_rx_states {
+ TFRC_RSTATE_NO_DATA = 1,
+ TFRC_RSTATE_DATA,
+ TFRC_RSTATE_TERM = 127,
+};
+
+#ifdef CCID3_DEBUG
+static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
+{
+ static char *ccid3_rx_state_names[] = {
+ [TFRC_RSTATE_NO_DATA] = "NO_DATA",
+ [TFRC_RSTATE_DATA] = "DATA",
+ [TFRC_RSTATE_TERM] = "TERM",
+ };
+
+ return ccid3_rx_state_names[state];
+}
+#endif
+
+static inline void ccid3_hc_rx_set_state(struct sock *sk,
+ enum ccid3_hc_rx_states state)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
+
+ ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
+ dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
+ ccid3_rx_state_name(state));
+ WARN_ON(state == oldstate);
+ hcrx->ccid3hcrx_state = state;
+}
+
+static void ccid3_hc_rx_send_feedback(struct sock *sk)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct dccp_rx_hist_entry *packet;
+ struct timeval now;
+
+ ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+
+ dccp_timestamp(sk, &now);
+
+ switch (hcrx->ccid3hcrx_state) {
+ case TFRC_RSTATE_NO_DATA:
+ hcrx->ccid3hcrx_x_recv = 0;
+ break;
+ case TFRC_RSTATE_DATA: {
+ const u32 delta = timeval_delta(&now,
+ &hcrx->ccid3hcrx_tstamp_last_feedback);
+ hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
+ delta);
+ }
+ break;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
+ dump_stack();
+ return;
+ }
+
+ packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
+ if (unlikely(packet == NULL)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet "
+ "in history!\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ return;
+ }
+
+ hcrx->ccid3hcrx_tstamp_last_feedback = now;
+ hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval;
+ hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno;
+ hcrx->ccid3hcrx_bytes_recv = 0;
+
+ /* Convert to multiples of 10us */
+ hcrx->ccid3hcrx_elapsed_time =
+ timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
+ if (hcrx->ccid3hcrx_p == 0)
+ hcrx->ccid3hcrx_pinv = ~0;
+ else
+ hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+ dp->dccps_hc_rx_insert_options = 1;
+ dccp_send_ack(sk);
+}
+
+static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
+{
+ const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ u32 x_recv, pinv;
+
+ BUG_ON(hcrx == NULL);
+
+ if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
+ return;
+
+ DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
+
+ if (dccp_packet_without_ack(skb))
+ return;
+
+ if (hcrx->ccid3hcrx_elapsed_time != 0)
+ dccp_insert_option_elapsed_time(sk, skb,
+ hcrx->ccid3hcrx_elapsed_time);
+ dccp_insert_option_timestamp(sk, skb);
+ x_recv = htonl(hcrx->ccid3hcrx_x_recv);
+ pinv = htonl(hcrx->ccid3hcrx_pinv);
+ dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
+ &pinv, sizeof(pinv));
+ dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
+ &x_recv, sizeof(x_recv));
+}
+
+/* calculate first loss interval
+ *
+ * returns estimated loss interval in usecs */
+
+static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+ u32 rtt, delta, x_recv, fval, p, tmp2;
+ struct timeval tstamp = { 0, };
+ int interval = 0;
+ int win_count = 0;
+ int step = 0;
+ u64 tmp1;
+
+ list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
+ dccphrx_node) {
+ if (dccp_rx_hist_entry_data_packet(entry)) {
+ tail = entry;
+
+ switch (step) {
+ case 0:
+ tstamp = entry->dccphrx_tstamp;
+ win_count = entry->dccphrx_ccval;
+ step = 1;
+ break;
+ case 1:
+ interval = win_count - entry->dccphrx_ccval;
+ if (interval < 0)
+ interval += TFRC_WIN_COUNT_LIMIT;
+ if (interval > 4)
+ goto found;
+ break;
+ }
+ }
+ }
+
+ if (unlikely(step == 0)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history "
+ "contains no data packets!\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ return ~0;
+ }
+
+ if (unlikely(interval == 0)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a "
+ "win_count interval > 0. Defaulting to 1\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ interval = 1;
+ }
+found:
+ rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
+ ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
+ dccp_role(sk), sk, rtt);
+ if (rtt == 0)
+ rtt = 1;
+
+ dccp_timestamp(sk, &tstamp);
+ delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
+ x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
+
+ tmp1 = (u64)x_recv * (u64)rtt;
+ do_div(tmp1,10000000);
+ tmp2 = (u32)tmp1;
+ fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
+ /* do not alter order above or you will get overflow on 32 bit */
+ p = tfrc_calc_x_reverse_lookup(fval);
+ ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
+ "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+
+ if (p == 0)
+ return ~0;
+ else
+ return 1000000 / p;
+}
+
+static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+
+ if (seq_loss != DCCP_MAX_SEQNO + 1 &&
+ list_empty(&hcrx->ccid3hcrx_li_hist)) {
+ struct dccp_li_hist_entry *li_tail;
+
+ li_tail = dccp_li_hist_interval_new(ccid3_li_hist,
+ &hcrx->ccid3hcrx_li_hist,
+ seq_loss, win_loss);
+ if (li_tail == NULL)
+ return;
+ li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
+ } else
+ LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of "
+ "interval\n", __FUNCTION__);
+}
+
+static void ccid3_hc_rx_detect_loss(struct sock *sk)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ u8 win_loss;
+ const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_li_hist,
+ &win_loss);
+
+ ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
+}
+
+static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ const struct dccp_options_received *opt_recv;
+ struct dccp_rx_hist_entry *packet;
+ struct timeval now;
+ u8 win_count;
+ u32 p_prev, r_sample, t_elapsed;
+ int ins;
+
+ BUG_ON(hcrx == NULL ||
+ !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
+ hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
+
+ opt_recv = &dccp_sk(sk)->dccps_options_received;
+
+ switch (DCCP_SKB_CB(skb)->dccpd_type) {
+ case DCCP_PKT_ACK:
+ if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
+ return;
+ case DCCP_PKT_DATAACK:
+ if (opt_recv->dccpor_timestamp_echo == 0)
+ break;
+ p_prev = hcrx->ccid3hcrx_rtt;
+ dccp_timestamp(sk, &now);
+ timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
+ r_sample = timeval_usecs(&now);
+ t_elapsed = opt_recv->dccpor_elapsed_time * 10;
+
+ if (unlikely(r_sample <= t_elapsed))
+ LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
+ "t_elapsed=%uus\n",
+ __FUNCTION__, r_sample, t_elapsed);
+ else
+ r_sample -= t_elapsed;
+
+ if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
+ hcrx->ccid3hcrx_rtt = r_sample;
+ else
+ hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
+ r_sample / 10;
+
+ if (p_prev != hcrx->ccid3hcrx_rtt)
+ ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
+ dccp_role(sk), hcrx->ccid3hcrx_rtt,
+ opt_recv->dccpor_elapsed_time);
+ break;
+ case DCCP_PKT_DATA:
+ break;
+ default: /* We're not interested in other packet types, move along */
+ return;
+ }
+
+ packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
+ skb, SLAB_ATOMIC);
+ if (unlikely(packet == NULL)) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to "
+ "add rx packet to history, consider it lost!\n",
+ __FUNCTION__, dccp_role(sk), sk);
+ return;
+ }
+
+ win_count = packet->dccphrx_ccval;
+
+ ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_li_hist, packet);
+
+ if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
+ return;
+
+ switch (hcrx->ccid3hcrx_state) {
+ case TFRC_RSTATE_NO_DATA:
+ ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
+ "feedback\n",
+ dccp_role(sk), sk,
+ dccp_state_name(sk->sk_state), skb);
+ ccid3_hc_rx_send_feedback(sk);
+ ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
+ return;
+ case TFRC_RSTATE_DATA:
+ hcrx->ccid3hcrx_bytes_recv += skb->len -
+ dccp_hdr(skb)->dccph_doff * 4;
+ if (ins != 0)
+ break;
+
+ dccp_timestamp(sk, &now);
+ if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
+ hcrx->ccid3hcrx_rtt) {
+ hcrx->ccid3hcrx_tstamp_last_ack = now;
+ ccid3_hc_rx_send_feedback(sk);
+ }
+ return;
+ default:
+ printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
+ __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
+ dump_stack();
+ return;
+ }
+
+ /* Dealing with packet loss */
+ ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+ dccp_role(sk), sk, dccp_state_name(sk->sk_state));
+
+ ccid3_hc_rx_detect_loss(sk);
+ p_prev = hcrx->ccid3hcrx_p;
+
+ /* Calculate loss event rate */
+ if (!list_empty(&hcrx->ccid3hcrx_li_hist))
+ /* Scaling up by 1000000 as fixed decimal */
+ hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+
+ if (hcrx->ccid3hcrx_p > p_prev) {
+ ccid3_hc_rx_send_feedback(sk);
+ return;
+ }
+}
+
+static int ccid3_hc_rx_init(struct sock *sk)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_rx_sock *hcrx;
+
+ ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+
+ dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
+ if (dp->dccps_hc_rx_ccid_private == NULL)
+ return -ENOMEM;
+
+ hcrx = ccid3_hc_rx_sk(sk);
+ memset(hcrx, 0, sizeof(*hcrx));
+
+ if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
+ dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
+ hcrx->ccid3hcrx_s = dp->dccps_packet_size;
+ else
+ hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;
+
+ hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
+ INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
+ INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
+ dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
+ hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
+ hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
+ return 0;
+}
+
+static void ccid3_hc_rx_exit(struct sock *sk)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ BUG_ON(hcrx == NULL);
+
+ ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
+
+ /* Empty packet history */
+ dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
+
+ /* Empty loss interval history */
+ dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
+
+ kfree(dp->dccps_hc_rx_ccid_private);
+ dp->dccps_hc_rx_ccid_private = NULL;
+}
+
+static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
+{
+ const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+
+ /* Listen socks doesn't have a private CCID block */
+ if (sk->sk_state == DCCP_LISTEN)
+ return;
+
+ BUG_ON(hcrx == NULL);
+
+ info->tcpi_ca_state = hcrx->ccid3hcrx_state;
+ info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
+ info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
+}
+
+static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
+{
+ const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+ /* Listen socks doesn't have a private CCID block */
+ if (sk->sk_state == DCCP_LISTEN)
+ return;
+
+ BUG_ON(hctx == NULL);
+
+ info->tcpi_rto = hctx->ccid3hctx_t_rto;
+ info->tcpi_rtt = hctx->ccid3hctx_rtt;
+}
+
+static struct ccid ccid3 = {
+ .ccid_id = 3,
+ .ccid_name = "ccid3",
+ .ccid_owner = THIS_MODULE,
+ .ccid_init = ccid3_init,
+ .ccid_exit = ccid3_exit,
+ .ccid_hc_tx_init = ccid3_hc_tx_init,
+ .ccid_hc_tx_exit = ccid3_hc_tx_exit,
+ .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
+ .ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent,
+ .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
+ .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
+ .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
+ .ccid_hc_rx_init = ccid3_hc_rx_init,
+ .ccid_hc_rx_exit = ccid3_hc_rx_exit,
+ .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
+ .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
+ .ccid_hc_rx_get_info = ccid3_hc_rx_get_info,
+ .ccid_hc_tx_get_info = ccid3_hc_tx_get_info,
+};
+
+module_param(ccid3_debug, int, 0444);
+MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
+
+static __init int ccid3_module_init(void)
+{
+ int rc = -ENOBUFS;
+
+ ccid3_rx_hist = dccp_rx_hist_new("ccid3");
+ if (ccid3_rx_hist == NULL)
+ goto out;
+
+ ccid3_tx_hist = dccp_tx_hist_new("ccid3");
+ if (ccid3_tx_hist == NULL)
+ goto out_free_rx;
+
+ ccid3_li_hist = dccp_li_hist_new("ccid3");
+ if (ccid3_li_hist == NULL)
+ goto out_free_tx;
+
+ rc = ccid_register(&ccid3);
+ if (rc != 0)
+ goto out_free_loss_interval_history;
+out:
+ return rc;
+
+out_free_loss_interval_history:
+ dccp_li_hist_delete(ccid3_li_hist);
+ ccid3_li_hist = NULL;
+out_free_tx:
+ dccp_tx_hist_delete(ccid3_tx_hist);
+ ccid3_tx_hist = NULL;
+out_free_rx:
+ dccp_rx_hist_delete(ccid3_rx_hist);
+ ccid3_rx_hist = NULL;
+ goto out;
+}
+module_init(ccid3_module_init);
+
+static __exit void ccid3_module_exit(void)
+{
+#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
+ /*
+ * Hack to use while developing, so that we get rid of the control
+ * sock, that is what keeps a refcount on dccp.ko -acme
+ */
+ extern void dccp_ctl_sock_exit(void);
+
+ dccp_ctl_sock_exit();
+#endif
+ ccid_unregister(&ccid3);
+
+ if (ccid3_tx_hist != NULL) {
+ dccp_tx_hist_delete(ccid3_tx_hist);
+ ccid3_tx_hist = NULL;
+ }
+ if (ccid3_rx_hist != NULL) {
+ dccp_rx_hist_delete(ccid3_rx_hist);
+ ccid3_rx_hist = NULL;
+ }
+ if (ccid3_li_hist != NULL) {
+ dccp_li_hist_delete(ccid3_li_hist);
+ ccid3_li_hist = NULL;
+ }
+}
+module_exit(ccid3_module_exit);
+
+MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+ "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
+MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("net-dccp-ccid-3");
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
new file mode 100644
index 000000000000..eb248778eea3
--- /dev/null
+++ b/net/dccp/ccids/ccid3.h
@@ -0,0 +1,143 @@
+/*
+ * net/dccp/ccids/ccid3.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *
+ * An implementation of the DCCP protocol
+ *
+ * This code has been developed by the University of Waikato WAND
+ * research group. For further information please see http://www.wand.net.nz/
+ * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *
+ * This code also uses code from Lulea University, rereleased as GPL by its
+ * authors:
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
+ * and to make it work as a loadable module in the DCCP stack written by
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
+ *
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 _DCCP_CCID3_H_
+#define _DCCP_CCID3_H_
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+#define TFRC_MIN_PACKET_SIZE 16
+#define TFRC_STD_PACKET_SIZE 256
+#define TFRC_MAX_PACKET_SIZE 65535
+
+/* Two seconds as per CCID3 spec */
+#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC)
+
+#define TFRC_INITIAL_IPI (USEC_PER_SEC / 4)
+
+/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
+#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))
+
+/* In seconds */
+#define TFRC_MAX_BACK_OFF_TIME 64
+
+#define TFRC_SMALLEST_P 40
+
+enum ccid3_options {
+ TFRC_OPT_LOSS_EVENT_RATE = 192,
+ TFRC_OPT_LOSS_INTERVALS = 193,
+ TFRC_OPT_RECEIVE_RATE = 194,
+};
+
+struct ccid3_options_received {
+ u64 ccid3or_seqno:48,
+ ccid3or_loss_intervals_idx:16;
+ u16 ccid3or_loss_intervals_len;
+ u32 ccid3or_loss_event_rate;
+ u32 ccid3or_receive_rate;
+};
+
+/** struct ccid3_hc_tx_sock - CCID3 sender half connection sock
+ *
+ * @ccid3hctx_state - Sender state
+ * @ccid3hctx_x - Current sending rate
+ * @ccid3hctx_x_recv - Receive rate
+ * @ccid3hctx_x_calc - Calculated send (?) rate
+ * @ccid3hctx_s - Packet size
+ * @ccid3hctx_rtt - Estimate of current round trip time in usecs
+ * @@ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
+ * @ccid3hctx_last_win_count - Last window counter sent
+ * @ccid3hctx_t_last_win_count - Timestamp of earliest packet
+ * with last_win_count value sent
+ * @ccid3hctx_no_feedback_timer - Handle to no feedback timer
+ * @ccid3hctx_idle - FIXME
+ * @ccid3hctx_t_ld - Time last doubled during slow start
+ * @ccid3hctx_t_nom - Nominal send time of next packet
+ * @ccid3hctx_t_ipi - Interpacket (send) interval
+ * @ccid3hctx_delta - Send timer delta
+ * @ccid3hctx_hist - Packet history
+ */
+struct ccid3_hc_tx_sock {
+ u32 ccid3hctx_x;
+ u32 ccid3hctx_x_recv;
+ u32 ccid3hctx_x_calc;
+ u16 ccid3hctx_s;
+ u32 ccid3hctx_rtt;
+ u32 ccid3hctx_p;
+ u8 ccid3hctx_state;
+ u8 ccid3hctx_last_win_count;
+ u8 ccid3hctx_idle;
+ struct timeval ccid3hctx_t_last_win_count;
+ struct timer_list ccid3hctx_no_feedback_timer;
+ struct timeval ccid3hctx_t_ld;
+ struct timeval ccid3hctx_t_nom;
+ u32 ccid3hctx_t_rto;
+ u32 ccid3hctx_t_ipi;
+ u32 ccid3hctx_delta;
+ struct list_head ccid3hctx_hist;
+ struct ccid3_options_received ccid3hctx_options_received;
+};
+
+struct ccid3_hc_rx_sock {
+ u64 ccid3hcrx_seqno_last_counter:48,
+ ccid3hcrx_state:8,
+ ccid3hcrx_last_counter:4;
+ u32 ccid3hcrx_rtt;
+ u32 ccid3hcrx_p;
+ u32 ccid3hcrx_bytes_recv;
+ struct timeval ccid3hcrx_tstamp_last_feedback;
+ struct timeval ccid3hcrx_tstamp_last_ack;
+ struct list_head ccid3hcrx_hist;
+ struct list_head ccid3hcrx_li_hist;
+ u16 ccid3hcrx_s;
+ u32 ccid3hcrx_pinv;
+ u32 ccid3hcrx_elapsed_time;
+ u32 ccid3hcrx_x_recv;
+};
+
+static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
+{
+ return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+}
+
+static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
+{
+ return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+}
+
+#endif /* _DCCP_CCID3_H_ */
diff --git a/net/dccp/ccids/lib/Makefile b/net/dccp/ccids/lib/Makefile
new file mode 100644
index 000000000000..5f940a6cbaca
--- /dev/null
+++ b/net/dccp/ccids/lib/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_IP_DCCP_TFRC_LIB) += dccp_tfrc_lib.o
+
+dccp_tfrc_lib-y := loss_interval.o packet_history.o tfrc_equation.o
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
new file mode 100644
index 000000000000..4c01a54143ad
--- /dev/null
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -0,0 +1,144 @@
+/*
+ * net/dccp/ccids/lib/loss_interval.c
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include "loss_interval.h"
+
+struct dccp_li_hist *dccp_li_hist_new(const char *name)
+{
+ struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+ static const char dccp_li_hist_mask[] = "li_hist_%s";
+ char *slab_name;
+
+ if (hist == NULL)
+ goto out;
+
+ slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
+ GFP_ATOMIC);
+ if (slab_name == NULL)
+ goto out_free_hist;
+
+ sprintf(slab_name, dccp_li_hist_mask, name);
+ hist->dccplih_slab = kmem_cache_create(slab_name,
+ sizeof(struct dccp_li_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (hist->dccplih_slab == NULL)
+ goto out_free_slab_name;
+out:
+ return hist;
+out_free_slab_name:
+ kfree(slab_name);
+out_free_hist:
+ kfree(hist);
+ hist = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_hist_new);
+
+void dccp_li_hist_delete(struct dccp_li_hist *hist)
+{
+ const char* name = kmem_cache_name(hist->dccplih_slab);
+
+ kmem_cache_destroy(hist->dccplih_slab);
+ kfree(name);
+ kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
+
+void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
+{
+ struct dccp_li_hist_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, dccplih_node) {
+ list_del_init(&entry->dccplih_node);
+ kmem_cache_free(hist->dccplih_slab, entry);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_hist_purge);
+
+/* Weights used to calculate loss event rate */
+/*
+ * These are integers as per section 8 of RFC3448. We can then divide by 4 *
+ * when we use it.
+ */
+static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = {
+ 4, 4, 4, 4, 3, 2, 1, 1,
+};
+
+u32 dccp_li_hist_calc_i_mean(struct list_head *list)
+{
+ struct dccp_li_hist_entry *li_entry, *li_next;
+ int i = 0;
+ u32 i_tot;
+ u32 i_tot0 = 0;
+ u32 i_tot1 = 0;
+ u32 w_tot = 0;
+
+ list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
+ if (i < DCCP_LI_HIST_IVAL_F_LENGTH) {
+ i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
+ w_tot += dccp_li_hist_w[i];
+ }
+
+ if (i != 0)
+ i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
+
+ if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
+ break;
+ }
+
+ if (i != DCCP_LI_HIST_IVAL_F_LENGTH)
+ return 0;
+
+ i_tot = max(i_tot0, i_tot1);
+
+ /* FIXME: Why do we do this? -Ian McDonald */
+ if (i_tot * 4 < w_tot)
+ i_tot = w_tot * 4;
+
+ return i_tot * 4 / w_tot;
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
+
+struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+ struct list_head *list,
+ const u64 seq_loss,
+ const u8 win_loss)
+{
+ struct dccp_li_hist_entry *tail = NULL, *entry;
+ int i;
+
+ for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) {
+ entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
+ if (entry == NULL) {
+ dccp_li_hist_purge(hist, list);
+ return NULL;
+ }
+ if (tail == NULL)
+ tail = entry;
+ list_add(&entry->dccplih_node, list);
+ }
+
+ entry->dccplih_seqno = seq_loss;
+ entry->dccplih_win_count = win_loss;
+ return tail;
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
new file mode 100644
index 000000000000..13ad47ba1420
--- /dev/null
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -0,0 +1,61 @@
+#ifndef _DCCP_LI_HIST_
+#define _DCCP_LI_HIST_
+/*
+ * net/dccp/ccids/lib/loss_interval.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#define DCCP_LI_HIST_IVAL_F_LENGTH 8
+
+struct dccp_li_hist {
+ kmem_cache_t *dccplih_slab;
+};
+
+extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
+extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
+
+struct dccp_li_hist_entry {
+ struct list_head dccplih_node;
+ u64 dccplih_seqno:48,
+ dccplih_win_count:4;
+ u32 dccplih_interval;
+};
+
+static inline struct dccp_li_hist_entry *
+ dccp_li_hist_entry_new(struct dccp_li_hist *hist,
+ const unsigned int __nocast prio)
+{
+ return kmem_cache_alloc(hist->dccplih_slab, prio);
+}
+
+static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
+ struct dccp_li_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(hist->dccplih_slab, entry);
+}
+
+extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
+ struct list_head *list);
+
+extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
+
+extern struct dccp_li_hist_entry *
+ dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+ struct list_head *list,
+ const u64 seq_loss,
+ const u8 win_loss);
+#endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
new file mode 100644
index 000000000000..d3f9d2053830
--- /dev/null
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -0,0 +1,398 @@
+/*
+ * net/dccp/packet_history.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *
+ * An implementation of the DCCP protocol
+ *
+ * This code has been developed by the University of Waikato WAND
+ * research group. For further information please see http://www.wand.net.nz/
+ * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *
+ * This code also uses code from Lulea University, rereleased as GPL by its
+ * authors:
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
+ * and to make it work as a loadable module in the DCCP stack written by
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
+ *
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "packet_history.h"
+
+struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
+{
+ struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+ static const char dccp_rx_hist_mask[] = "rx_hist_%s";
+ char *slab_name;
+
+ if (hist == NULL)
+ goto out;
+
+ slab_name = kmalloc(strlen(name) + sizeof(dccp_rx_hist_mask) - 1,
+ GFP_ATOMIC);
+ if (slab_name == NULL)
+ goto out_free_hist;
+
+ sprintf(slab_name, dccp_rx_hist_mask, name);
+ hist->dccprxh_slab = kmem_cache_create(slab_name,
+ sizeof(struct dccp_rx_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (hist->dccprxh_slab == NULL)
+ goto out_free_slab_name;
+out:
+ return hist;
+out_free_slab_name:
+ kfree(slab_name);
+out_free_hist:
+ kfree(hist);
+ hist = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_new);
+
+void dccp_rx_hist_delete(struct dccp_rx_hist *hist)
+{
+ const char* name = kmem_cache_name(hist->dccprxh_slab);
+
+ kmem_cache_destroy(hist->dccprxh_slab);
+ kfree(name);
+ kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
+
+void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
+{
+ struct dccp_rx_hist_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, dccphrx_node) {
+ list_del_init(&entry->dccphrx_node);
+ kmem_cache_free(hist->dccprxh_slab, entry);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
+
+struct dccp_rx_hist_entry *
+ dccp_rx_hist_find_data_packet(const struct list_head *list)
+{
+ struct dccp_rx_hist_entry *entry, *packet = NULL;
+
+ list_for_each_entry(entry, list, dccphrx_node)
+ if (entry->dccphrx_type == DCCP_PKT_DATA ||
+ entry->dccphrx_type == DCCP_PKT_DATAACK) {
+ packet = entry;
+ break;
+ }
+
+ return packet;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
+
+int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+ struct list_head *rx_list,
+ struct list_head *li_list,
+ struct dccp_rx_hist_entry *packet)
+{
+ struct dccp_rx_hist_entry *entry, *next, *iter;
+ u8 num_later = 0;
+
+ iter = dccp_rx_hist_head(rx_list);
+ if (iter == NULL)
+ dccp_rx_hist_add_entry(rx_list, packet);
+ else {
+ const u64 seqno = packet->dccphrx_seqno;
+
+ if (after48(seqno, iter->dccphrx_seqno))
+ dccp_rx_hist_add_entry(rx_list, packet);
+ else {
+ if (dccp_rx_hist_entry_data_packet(iter))
+ num_later = 1;
+
+ list_for_each_entry_continue(iter, rx_list,
+ dccphrx_node) {
+ if (after48(seqno, iter->dccphrx_seqno)) {
+ dccp_rx_hist_add_entry(&iter->dccphrx_node,
+ packet);
+ goto trim_history;
+ }
+
+ if (dccp_rx_hist_entry_data_packet(iter))
+ num_later++;
+
+ if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
+ dccp_rx_hist_entry_delete(hist, packet);
+ return 1;
+ }
+ }
+
+ if (num_later < TFRC_RECV_NUM_LATE_LOSS)
+ dccp_rx_hist_add_entry(rx_list, packet);
+ /*
+ * FIXME: else what? should we destroy the packet
+ * like above?
+ */
+ }
+ }
+
+trim_history:
+ /*
+ * Trim history (remove all packets after the NUM_LATE_LOSS + 1
+ * data packets)
+ */
+ num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
+
+ if (!list_empty(li_list)) {
+ list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
+ if (num_later == 0) {
+ list_del_init(&entry->dccphrx_node);
+ dccp_rx_hist_entry_delete(hist, entry);
+ } else if (dccp_rx_hist_entry_data_packet(entry))
+ --num_later;
+ }
+ } else {
+ int step = 0;
+ u8 win_count = 0; /* Not needed, but lets shut up gcc */
+ int tmp;
+ /*
+ * We have no loss interval history so we need at least one
+ * rtt:s of data packets to approximate rtt.
+ */
+ list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
+ if (num_later == 0) {
+ switch (step) {
+ case 0:
+ step = 1;
+ /* OK, find next data packet */
+ num_later = 1;
+ break;
+ case 1:
+ step = 2;
+ /* OK, find next data packet */
+ num_later = 1;
+ win_count = entry->dccphrx_ccval;
+ break;
+ case 2:
+ tmp = win_count - entry->dccphrx_ccval;
+ if (tmp < 0)
+ tmp += TFRC_WIN_COUNT_LIMIT;
+ if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
+ /*
+ * We have found a packet older
+ * than one rtt remove the rest
+ */
+ step = 3;
+ } else /* OK, find next data packet */
+ num_later = 1;
+ break;
+ case 3:
+ list_del_init(&entry->dccphrx_node);
+ dccp_rx_hist_entry_delete(hist, entry);
+ break;
+ }
+ } else if (dccp_rx_hist_entry_data_packet(entry))
+ --num_later;
+ }
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
+
+u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
+ struct list_head *li_list, u8 *win_loss)
+{
+ struct dccp_rx_hist_entry *entry, *next, *packet;
+ struct dccp_rx_hist_entry *a_loss = NULL;
+ struct dccp_rx_hist_entry *b_loss = NULL;
+ u64 seq_loss = DCCP_MAX_SEQNO + 1;
+ u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
+
+ list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
+ if (num_later == 0) {
+ b_loss = entry;
+ break;
+ } else if (dccp_rx_hist_entry_data_packet(entry))
+ --num_later;
+ }
+
+ if (b_loss == NULL)
+ goto out;
+
+ num_later = 1;
+ list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
+ if (num_later == 0) {
+ a_loss = entry;
+ break;
+ } else if (dccp_rx_hist_entry_data_packet(entry))
+ --num_later;
+ }
+
+ if (a_loss == NULL) {
+ if (list_empty(li_list)) {
+ /* no loss event have occured yet */
+ LIMIT_NETDEBUG("%s: TODO: find a lost data packet by "
+ "comparing to initial seqno\n",
+ __FUNCTION__);
+ goto out;
+ } else {
+ LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!",
+ __FUNCTION__);
+ goto out;
+ }
+ }
+
+ /* Locate a lost data packet */
+ entry = packet = b_loss;
+ list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
+ u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
+ packet->dccphrx_seqno);
+
+ if (delta != 0) {
+ if (dccp_rx_hist_entry_data_packet(packet))
+ --delta;
+ /*
+ * FIXME: check this, probably this % usage is because
+ * in earlier drafts the ndp count was just 8 bits
+ * long, but now it cam be up to 24 bits long.
+ */
+#if 0
+ if (delta % DCCP_NDP_LIMIT !=
+ (packet->dccphrx_ndp -
+ entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
+#endif
+ if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) {
+ seq_loss = entry->dccphrx_seqno;
+ dccp_inc_seqno(&seq_loss);
+ }
+ }
+ packet = entry;
+ if (packet == a_loss)
+ break;
+ }
+out:
+ if (seq_loss != DCCP_MAX_SEQNO + 1)
+ *win_loss = a_loss->dccphrx_ccval;
+ else
+ *win_loss = 0; /* Paranoia */
+
+ return seq_loss;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss);
+
+struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
+{
+ struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+ static const char dccp_tx_hist_mask[] = "tx_hist_%s";
+ char *slab_name;
+
+ if (hist == NULL)
+ goto out;
+
+ slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
+ GFP_ATOMIC);
+ if (slab_name == NULL)
+ goto out_free_hist;
+
+ sprintf(slab_name, dccp_tx_hist_mask, name);
+ hist->dccptxh_slab = kmem_cache_create(slab_name,
+ sizeof(struct dccp_tx_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (hist->dccptxh_slab == NULL)
+ goto out_free_slab_name;
+out:
+ return hist;
+out_free_slab_name:
+ kfree(slab_name);
+out_free_hist:
+ kfree(hist);
+ hist = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
+
+void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
+{
+ const char* name = kmem_cache_name(hist->dccptxh_slab);
+
+ kmem_cache_destroy(hist->dccptxh_slab);
+ kfree(name);
+ kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
+
+struct dccp_tx_hist_entry *
+ dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
+{
+ struct dccp_tx_hist_entry *packet = NULL, *entry;
+
+ list_for_each_entry(entry, list, dccphtx_node)
+ if (entry->dccphtx_seqno == seq) {
+ packet = entry;
+ break;
+ }
+
+ return packet;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
+
+void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+ struct list_head *list,
+ struct dccp_tx_hist_entry *packet)
+{
+ struct dccp_tx_hist_entry *next;
+
+ list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
+ list_del_init(&packet->dccphtx_node);
+ dccp_tx_hist_entry_delete(hist, packet);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
+
+void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
+{
+ struct dccp_tx_hist_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, dccphtx_node) {
+ list_del_init(&entry->dccphtx_node);
+ dccp_tx_hist_entry_delete(hist, entry);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
+
+MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+ "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
+MODULE_DESCRIPTION("DCCP TFRC library");
+MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
new file mode 100644
index 000000000000..b375ebdb7dcf
--- /dev/null
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -0,0 +1,200 @@
+/*
+ * net/dccp/packet_history.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *
+ * An implementation of the DCCP protocol
+ *
+ * This code has been developed by the University of Waikato WAND
+ * research group. For further information please see http://www.wand.net.nz/
+ * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *
+ * This code also uses code from Lulea University, rereleased as GPL by its
+ * authors:
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
+ * and to make it work as a loadable module in the DCCP stack written by
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
+ *
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 _DCCP_PKT_HIST_
+#define _DCCP_PKT_HIST_
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#include "../../dccp.h"
+
+/* Number of later packets received before one is considered lost */
+#define TFRC_RECV_NUM_LATE_LOSS 3
+
+#define TFRC_WIN_COUNT_PER_RTT 4
+#define TFRC_WIN_COUNT_LIMIT 16
+
+struct dccp_tx_hist_entry {
+ struct list_head dccphtx_node;
+ u64 dccphtx_seqno:48,
+ dccphtx_ccval:4,
+ dccphtx_sent:1;
+ u32 dccphtx_rtt;
+ struct timeval dccphtx_tstamp;
+};
+
+struct dccp_rx_hist_entry {
+ struct list_head dccphrx_node;
+ u64 dccphrx_seqno:48,
+ dccphrx_ccval:4,
+ dccphrx_type:4;
+ u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
+ struct timeval dccphrx_tstamp;
+};
+
+struct dccp_tx_hist {
+ kmem_cache_t *dccptxh_slab;
+};
+
+extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name);
+extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
+
+struct dccp_rx_hist {
+ kmem_cache_t *dccprxh_slab;
+};
+
+extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
+extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
+extern struct dccp_rx_hist_entry *
+ dccp_rx_hist_find_data_packet(const struct list_head *list);
+
+static inline struct dccp_tx_hist_entry *
+ dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
+ const unsigned int __nocast prio)
+{
+ struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab,
+ prio);
+
+ if (entry != NULL)
+ entry->dccphtx_sent = 0;
+
+ return entry;
+}
+
+static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
+ struct dccp_tx_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(hist->dccptxh_slab, entry);
+}
+
+extern struct dccp_tx_hist_entry *
+ dccp_tx_hist_find_entry(const struct list_head *list,
+ const u64 seq);
+
+static inline void dccp_tx_hist_add_entry(struct list_head *list,
+ struct dccp_tx_hist_entry *entry)
+{
+ list_add(&entry->dccphtx_node, list);
+}
+
+extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+ struct list_head *list,
+ struct dccp_tx_hist_entry *next);
+
+extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
+ struct list_head *list);
+
+static inline struct dccp_tx_hist_entry *
+ dccp_tx_hist_head(struct list_head *list)
+{
+ struct dccp_tx_hist_entry *head = NULL;
+
+ if (!list_empty(list))
+ head = list_entry(list->next, struct dccp_tx_hist_entry,
+ dccphtx_node);
+ return head;
+}
+
+static inline struct dccp_rx_hist_entry *
+ dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+ const struct sock *sk,
+ const u32 ndp,
+ const struct sk_buff *skb,
+ const unsigned int __nocast prio)
+{
+ struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
+ prio);
+
+ if (entry != NULL) {
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+
+ entry->dccphrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+ entry->dccphrx_ccval = dh->dccph_ccval;
+ entry->dccphrx_type = dh->dccph_type;
+ entry->dccphrx_ndp = ndp;
+ dccp_timestamp(sk, &entry->dccphrx_tstamp);
+ }
+
+ return entry;
+}
+
+static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
+ struct dccp_rx_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(hist->dccprxh_slab, entry);
+}
+
+extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
+ struct list_head *list);
+
+static inline void dccp_rx_hist_add_entry(struct list_head *list,
+ struct dccp_rx_hist_entry *entry)
+{
+ list_add(&entry->dccphrx_node, list);
+}
+
+static inline struct dccp_rx_hist_entry *
+ dccp_rx_hist_head(struct list_head *list)
+{
+ struct dccp_rx_hist_entry *head = NULL;
+
+ if (!list_empty(list))
+ head = list_entry(list->next, struct dccp_rx_hist_entry,
+ dccphrx_node);
+ return head;
+}
+
+static inline int
+ dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
+{
+ return entry->dccphrx_type == DCCP_PKT_DATA ||
+ entry->dccphrx_type == DCCP_PKT_DATAACK;
+}
+
+extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+ struct list_head *rx_list,
+ struct list_head *li_list,
+ struct dccp_rx_hist_entry *packet);
+
+extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
+ struct list_head *li_list, u8 *win_loss);
+
+#endif /* _DCCP_PKT_HIST_ */
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
new file mode 100644
index 000000000000..130c4c40cfe3
--- /dev/null
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -0,0 +1,22 @@
+#ifndef _TFRC_H_
+#define _TFRC_H_
+/*
+ * net/dccp/ccids/lib/tfrc.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+
+extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
+extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
+
+#endif /* _TFRC_H_ */
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
new file mode 100644
index 000000000000..d2b5933b4510
--- /dev/null
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -0,0 +1,644 @@
+/*
+ * net/dccp/ccids/lib/tfrc_equation.c
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+
+#include <asm/bug.h>
+#include <asm/div64.h>
+
+#include "tfrc.h"
+
+#define TFRC_CALC_X_ARRSIZE 500
+
+#define TFRC_CALC_X_SPLIT 50000
+/* equivalent to 0.05 */
+
+static const u32 tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE][2] = {
+ { 37172, 8172 },
+ { 53499, 11567 },
+ { 66664, 14180 },
+ { 78298, 16388 },
+ { 89021, 18339 },
+ { 99147, 20108 },
+ { 108858, 21738 },
+ { 118273, 23260 },
+ { 127474, 24693 },
+ { 136520, 26052 },
+ { 145456, 27348 },
+ { 154316, 28589 },
+ { 163130, 29783 },
+ { 171919, 30935 },
+ { 180704, 32049 },
+ { 189502, 33130 },
+ { 198328, 34180 },
+ { 207194, 35202 },
+ { 216114, 36198 },
+ { 225097, 37172 },
+ { 234153, 38123 },
+ { 243294, 39055 },
+ { 252527, 39968 },
+ { 261861, 40864 },
+ { 271305, 41743 },
+ { 280866, 42607 },
+ { 290553, 43457 },
+ { 300372, 44293 },
+ { 310333, 45117 },
+ { 320441, 45929 },
+ { 330705, 46729 },
+ { 341131, 47518 },
+ { 351728, 48297 },
+ { 362501, 49066 },
+ { 373460, 49826 },
+ { 384609, 50577 },
+ { 395958, 51320 },
+ { 407513, 52054 },
+ { 419281, 52780 },
+ { 431270, 53499 },
+ { 443487, 54211 },
+ { 455940, 54916 },
+ { 468635, 55614 },
+ { 481581, 56306 },
+ { 494785, 56991 },
+ { 508254, 57671 },
+ { 521996, 58345 },
+ { 536019, 59014 },
+ { 550331, 59677 },
+ { 564939, 60335 },
+ { 579851, 60988 },
+ { 595075, 61636 },
+ { 610619, 62279 },
+ { 626491, 62918 },
+ { 642700, 63553 },
+ { 659253, 64183 },
+ { 676158, 64809 },
+ { 693424, 65431 },
+ { 711060, 66050 },
+ { 729073, 66664 },
+ { 747472, 67275 },
+ { 766266, 67882 },
+ { 785464, 68486 },
+ { 805073, 69087 },
+ { 825103, 69684 },
+ { 845562, 70278 },
+ { 866460, 70868 },
+ { 887805, 71456 },
+ { 909606, 72041 },
+ { 931873, 72623 },
+ { 954614, 73202 },
+ { 977839, 73778 },
+ { 1001557, 74352 },
+ { 1025777, 74923 },
+ { 1050508, 75492 },
+ { 1075761, 76058 },
+ { 1101544, 76621 },
+ { 1127867, 77183 },
+ { 1154739, 77741 },
+ { 1182172, 78298 },
+ { 1210173, 78852 },
+ { 1238753, 79405 },
+ { 1267922, 79955 },
+ { 1297689, 80503 },
+ { 1328066, 81049 },
+ { 1359060, 81593 },
+ { 1390684, 82135 },
+ { 1422947, 82675 },
+ { 1455859, 83213 },
+ { 1489430, 83750 },
+ { 1523671, 84284 },
+ { 1558593, 84817 },
+ { 1594205, 85348 },
+ { 1630518, 85878 },
+ { 1667543, 86406 },
+ { 1705290, 86932 },
+ { 1743770, 87457 },
+ { 1782994, 87980 },
+ { 1822973, 88501 },
+ { 1863717, 89021 },
+ { 1905237, 89540 },
+ { 1947545, 90057 },
+ { 1990650, 90573 },
+ { 2034566, 91087 },
+ { 2079301, 91600 },
+ { 2124869, 92111 },
+ { 2171279, 92622 },
+ { 2218543, 93131 },
+ { 2266673, 93639 },
+ { 2315680, 94145 },
+ { 2365575, 94650 },
+ { 2416371, 95154 },
+ { 2468077, 95657 },
+ { 2520707, 96159 },
+ { 2574271, 96660 },
+ { 2628782, 97159 },
+ { 2684250, 97658 },
+ { 2740689, 98155 },
+ { 2798110, 98651 },
+ { 2856524, 99147 },
+ { 2915944, 99641 },
+ { 2976382, 100134 },
+ { 3037850, 100626 },
+ { 3100360, 101117 },
+ { 3163924, 101608 },
+ { 3228554, 102097 },
+ { 3294263, 102586 },
+ { 3361063, 103073 },
+ { 3428966, 103560 },
+ { 3497984, 104045 },
+ { 3568131, 104530 },
+ { 3639419, 105014 },
+ { 3711860, 105498 },
+ { 3785467, 105980 },
+ { 3860253, 106462 },
+ { 3936229, 106942 },
+ { 4013410, 107422 },
+ { 4091808, 107902 },
+ { 4171435, 108380 },
+ { 4252306, 108858 },
+ { 4334431, 109335 },
+ { 4417825, 109811 },
+ { 4502501, 110287 },
+ { 4588472, 110762 },
+ { 4675750, 111236 },
+ { 4764349, 111709 },
+ { 4854283, 112182 },
+ { 4945564, 112654 },
+ { 5038206, 113126 },
+ { 5132223, 113597 },
+ { 5227627, 114067 },
+ { 5324432, 114537 },
+ { 5422652, 115006 },
+ { 5522299, 115474 },
+ { 5623389, 115942 },
+ { 5725934, 116409 },
+ { 5829948, 116876 },
+ { 5935446, 117342 },
+ { 6042439, 117808 },
+ { 6150943, 118273 },
+ { 6260972, 118738 },
+ { 6372538, 119202 },
+ { 6485657, 119665 },
+ { 6600342, 120128 },
+ { 6716607, 120591 },
+ { 6834467, 121053 },
+ { 6953935, 121514 },
+ { 7075025, 121976 },
+ { 7197752, 122436 },
+ { 7322131, 122896 },
+ { 7448175, 123356 },
+ { 7575898, 123815 },
+ { 7705316, 124274 },
+ { 7836442, 124733 },
+ { 7969291, 125191 },
+ { 8103877, 125648 },
+ { 8240216, 126105 },
+ { 8378321, 126562 },
+ { 8518208, 127018 },
+ { 8659890, 127474 },
+ { 8803384, 127930 },
+ { 8948702, 128385 },
+ { 9095861, 128840 },
+ { 9244875, 129294 },
+ { 9395760, 129748 },
+ { 9548529, 130202 },
+ { 9703198, 130655 },
+ { 9859782, 131108 },
+ { 10018296, 131561 },
+ { 10178755, 132014 },
+ { 10341174, 132466 },
+ { 10505569, 132917 },
+ { 10671954, 133369 },
+ { 10840345, 133820 },
+ { 11010757, 134271 },
+ { 11183206, 134721 },
+ { 11357706, 135171 },
+ { 11534274, 135621 },
+ { 11712924, 136071 },
+ { 11893673, 136520 },
+ { 12076536, 136969 },
+ { 12261527, 137418 },
+ { 12448664, 137867 },
+ { 12637961, 138315 },
+ { 12829435, 138763 },
+ { 13023101, 139211 },
+ { 13218974, 139658 },
+ { 13417071, 140106 },
+ { 13617407, 140553 },
+ { 13819999, 140999 },
+ { 14024862, 141446 },
+ { 14232012, 141892 },
+ { 14441465, 142339 },
+ { 14653238, 142785 },
+ { 14867346, 143230 },
+ { 15083805, 143676 },
+ { 15302632, 144121 },
+ { 15523842, 144566 },
+ { 15747453, 145011 },
+ { 15973479, 145456 },
+ { 16201939, 145900 },
+ { 16432847, 146345 },
+ { 16666221, 146789 },
+ { 16902076, 147233 },
+ { 17140429, 147677 },
+ { 17381297, 148121 },
+ { 17624696, 148564 },
+ { 17870643, 149007 },
+ { 18119154, 149451 },
+ { 18370247, 149894 },
+ { 18623936, 150336 },
+ { 18880241, 150779 },
+ { 19139176, 151222 },
+ { 19400759, 151664 },
+ { 19665007, 152107 },
+ { 19931936, 152549 },
+ { 20201564, 152991 },
+ { 20473907, 153433 },
+ { 20748982, 153875 },
+ { 21026807, 154316 },
+ { 21307399, 154758 },
+ { 21590773, 155199 },
+ { 21876949, 155641 },
+ { 22165941, 156082 },
+ { 22457769, 156523 },
+ { 22752449, 156964 },
+ { 23049999, 157405 },
+ { 23350435, 157846 },
+ { 23653774, 158287 },
+ { 23960036, 158727 },
+ { 24269236, 159168 },
+ { 24581392, 159608 },
+ { 24896521, 160049 },
+ { 25214642, 160489 },
+ { 25535772, 160929 },
+ { 25859927, 161370 },
+ { 26187127, 161810 },
+ { 26517388, 162250 },
+ { 26850728, 162690 },
+ { 27187165, 163130 },
+ { 27526716, 163569 },
+ { 27869400, 164009 },
+ { 28215234, 164449 },
+ { 28564236, 164889 },
+ { 28916423, 165328 },
+ { 29271815, 165768 },
+ { 29630428, 166208 },
+ { 29992281, 166647 },
+ { 30357392, 167087 },
+ { 30725779, 167526 },
+ { 31097459, 167965 },
+ { 31472452, 168405 },
+ { 31850774, 168844 },
+ { 32232445, 169283 },
+ { 32617482, 169723 },
+ { 33005904, 170162 },
+ { 33397730, 170601 },
+ { 33792976, 171041 },
+ { 34191663, 171480 },
+ { 34593807, 171919 },
+ { 34999428, 172358 },
+ { 35408544, 172797 },
+ { 35821174, 173237 },
+ { 36237335, 173676 },
+ { 36657047, 174115 },
+ { 37080329, 174554 },
+ { 37507197, 174993 },
+ { 37937673, 175433 },
+ { 38371773, 175872 },
+ { 38809517, 176311 },
+ { 39250924, 176750 },
+ { 39696012, 177190 },
+ { 40144800, 177629 },
+ { 40597308, 178068 },
+ { 41053553, 178507 },
+ { 41513554, 178947 },
+ { 41977332, 179386 },
+ { 42444904, 179825 },
+ { 42916290, 180265 },
+ { 43391509, 180704 },
+ { 43870579, 181144 },
+ { 44353520, 181583 },
+ { 44840352, 182023 },
+ { 45331092, 182462 },
+ { 45825761, 182902 },
+ { 46324378, 183342 },
+ { 46826961, 183781 },
+ { 47333531, 184221 },
+ { 47844106, 184661 },
+ { 48358706, 185101 },
+ { 48877350, 185541 },
+ { 49400058, 185981 },
+ { 49926849, 186421 },
+ { 50457743, 186861 },
+ { 50992759, 187301 },
+ { 51531916, 187741 },
+ { 52075235, 188181 },
+ { 52622735, 188622 },
+ { 53174435, 189062 },
+ { 53730355, 189502 },
+ { 54290515, 189943 },
+ { 54854935, 190383 },
+ { 55423634, 190824 },
+ { 55996633, 191265 },
+ { 56573950, 191706 },
+ { 57155606, 192146 },
+ { 57741621, 192587 },
+ { 58332014, 193028 },
+ { 58926806, 193470 },
+ { 59526017, 193911 },
+ { 60129666, 194352 },
+ { 60737774, 194793 },
+ { 61350361, 195235 },
+ { 61967446, 195677 },
+ { 62589050, 196118 },
+ { 63215194, 196560 },
+ { 63845897, 197002 },
+ { 64481179, 197444 },
+ { 65121061, 197886 },
+ { 65765563, 198328 },
+ { 66414705, 198770 },
+ { 67068508, 199213 },
+ { 67726992, 199655 },
+ { 68390177, 200098 },
+ { 69058085, 200540 },
+ { 69730735, 200983 },
+ { 70408147, 201426 },
+ { 71090343, 201869 },
+ { 71777343, 202312 },
+ { 72469168, 202755 },
+ { 73165837, 203199 },
+ { 73867373, 203642 },
+ { 74573795, 204086 },
+ { 75285124, 204529 },
+ { 76001380, 204973 },
+ { 76722586, 205417 },
+ { 77448761, 205861 },
+ { 78179926, 206306 },
+ { 78916102, 206750 },
+ { 79657310, 207194 },
+ { 80403571, 207639 },
+ { 81154906, 208084 },
+ { 81911335, 208529 },
+ { 82672880, 208974 },
+ { 83439562, 209419 },
+ { 84211402, 209864 },
+ { 84988421, 210309 },
+ { 85770640, 210755 },
+ { 86558080, 211201 },
+ { 87350762, 211647 },
+ { 88148708, 212093 },
+ { 88951938, 212539 },
+ { 89760475, 212985 },
+ { 90574339, 213432 },
+ { 91393551, 213878 },
+ { 92218133, 214325 },
+ { 93048107, 214772 },
+ { 93883493, 215219 },
+ { 94724314, 215666 },
+ { 95570590, 216114 },
+ { 96422343, 216561 },
+ { 97279594, 217009 },
+ { 98142366, 217457 },
+ { 99010679, 217905 },
+ { 99884556, 218353 },
+ { 100764018, 218801 },
+ { 101649086, 219250 },
+ { 102539782, 219698 },
+ { 103436128, 220147 },
+ { 104338146, 220596 },
+ { 105245857, 221046 },
+ { 106159284, 221495 },
+ { 107078448, 221945 },
+ { 108003370, 222394 },
+ { 108934074, 222844 },
+ { 109870580, 223294 },
+ { 110812910, 223745 },
+ { 111761087, 224195 },
+ { 112715133, 224646 },
+ { 113675069, 225097 },
+ { 114640918, 225548 },
+ { 115612702, 225999 },
+ { 116590442, 226450 },
+ { 117574162, 226902 },
+ { 118563882, 227353 },
+ { 119559626, 227805 },
+ { 120561415, 228258 },
+ { 121569272, 228710 },
+ { 122583219, 229162 },
+ { 123603278, 229615 },
+ { 124629471, 230068 },
+ { 125661822, 230521 },
+ { 126700352, 230974 },
+ { 127745083, 231428 },
+ { 128796039, 231882 },
+ { 129853241, 232336 },
+ { 130916713, 232790 },
+ { 131986475, 233244 },
+ { 133062553, 233699 },
+ { 134144966, 234153 },
+ { 135233739, 234608 },
+ { 136328894, 235064 },
+ { 137430453, 235519 },
+ { 138538440, 235975 },
+ { 139652876, 236430 },
+ { 140773786, 236886 },
+ { 141901190, 237343 },
+ { 143035113, 237799 },
+ { 144175576, 238256 },
+ { 145322604, 238713 },
+ { 146476218, 239170 },
+ { 147636442, 239627 },
+ { 148803298, 240085 },
+ { 149976809, 240542 },
+ { 151156999, 241000 },
+ { 152343890, 241459 },
+ { 153537506, 241917 },
+ { 154737869, 242376 },
+ { 155945002, 242835 },
+ { 157158929, 243294 },
+ { 158379673, 243753 },
+ { 159607257, 244213 },
+ { 160841704, 244673 },
+ { 162083037, 245133 },
+ { 163331279, 245593 },
+ { 164586455, 246054 },
+ { 165848586, 246514 },
+ { 167117696, 246975 },
+ { 168393810, 247437 },
+ { 169676949, 247898 },
+ { 170967138, 248360 },
+ { 172264399, 248822 },
+ { 173568757, 249284 },
+ { 174880235, 249747 },
+ { 176198856, 250209 },
+ { 177524643, 250672 },
+ { 178857621, 251136 },
+ { 180197813, 251599 },
+ { 181545242, 252063 },
+ { 182899933, 252527 },
+ { 184261908, 252991 },
+ { 185631191, 253456 },
+ { 187007807, 253920 },
+ { 188391778, 254385 },
+ { 189783129, 254851 },
+ { 191181884, 255316 },
+ { 192588065, 255782 },
+ { 194001698, 256248 },
+ { 195422805, 256714 },
+ { 196851411, 257181 },
+ { 198287540, 257648 },
+ { 199731215, 258115 },
+ { 201182461, 258582 },
+ { 202641302, 259050 },
+ { 204107760, 259518 },
+ { 205581862, 259986 },
+ { 207063630, 260454 },
+ { 208553088, 260923 },
+ { 210050262, 261392 },
+ { 211555174, 261861 },
+ { 213067849, 262331 },
+ { 214588312, 262800 },
+ { 216116586, 263270 },
+ { 217652696, 263741 },
+ { 219196666, 264211 },
+ { 220748520, 264682 },
+ { 222308282, 265153 },
+ { 223875978, 265625 },
+ { 225451630, 266097 },
+ { 227035265, 266569 },
+ { 228626905, 267041 },
+ { 230226576, 267514 },
+ { 231834302, 267986 },
+ { 233450107, 268460 },
+ { 235074016, 268933 },
+ { 236706054, 269407 },
+ { 238346244, 269881 },
+ { 239994613, 270355 },
+ { 241651183, 270830 },
+ { 243315981, 271305 }
+};
+
+/* Calculate the send rate as per section 3.1 of RFC3448
+
+Returns send rate in bytes per second
+
+Integer maths and lookups are used as not allowed floating point in kernel
+
+The function for Xcalc as per section 3.1 of RFC3448 is:
+
+X = s
+ -------------------------------------------------------------
+ R*sqrt(2*b*p/3) + (t_RTO * (3*sqrt(3*b*p/8) * p * (1+32*p^2)))
+
+where
+X is the trasmit rate in bytes/second
+s is the packet size in bytes
+R is the round trip time in seconds
+p is the loss event rate, between 0 and 1.0, of the number of loss events
+ as a fraction of the number of packets transmitted
+t_RTO is the TCP retransmission timeout value in seconds
+b is the number of packets acknowledged by a single TCP acknowledgement
+
+we can assume that b = 1 and t_RTO is 4 * R. With this the equation becomes:
+
+X = s
+ -----------------------------------------------------------------------
+ R * sqrt(2 * p / 3) + (12 * R * (sqrt(3 * p / 8) * p * (1 + 32 * p^2)))
+
+
+which we can break down into:
+
+X = s
+ --------
+ R * f(p)
+
+where f(p) = sqrt(2 * p / 3) + (12 * sqrt(3 * p / 8) * p * (1 + 32 * p * p))
+
+Function parameters:
+s - bytes
+R - RTT in usecs
+p - loss rate (decimal fraction multiplied by 1,000,000)
+
+Returns Xcalc in bytes per second
+
+DON'T alter this code unless you run test cases against it as the code
+has been manipulated to stop underflow/overlow.
+
+*/
+u32 tfrc_calc_x(u16 s, u32 R, u32 p)
+{
+ int index;
+ u32 f;
+ u64 tmp1, tmp2;
+
+ if (p < TFRC_CALC_X_SPLIT)
+ index = (p / (TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE)) - 1;
+ else
+ index = (p / (1000000 / TFRC_CALC_X_ARRSIZE)) - 1;
+
+ if (index < 0)
+ /* p should be 0 unless there is a bug in my code */
+ index = 0;
+
+ if (R == 0)
+ R = 1; /* RTT can't be zero or else divide by zero */
+
+ BUG_ON(index >= TFRC_CALC_X_ARRSIZE);
+
+ if (p >= TFRC_CALC_X_SPLIT)
+ f = tfrc_calc_x_lookup[index][0];
+ else
+ f = tfrc_calc_x_lookup[index][1];
+
+ tmp1 = ((u64)s * 100000000);
+ tmp2 = ((u64)R * (u64)f);
+ do_div(tmp2, 10000);
+ do_div(tmp1, tmp2);
+ /* Don't alter above math unless you test due to overflow on 32 bit */
+
+ return (u32)tmp1;
+}
+
+EXPORT_SYMBOL_GPL(tfrc_calc_x);
+
+/*
+ * args: fvalue - function value to match
+ * returns: p closest to that value
+ *
+ * both fvalue and p are multiplied by 1,000,000 to use ints
+ */
+u32 tfrc_calc_x_reverse_lookup(u32 fvalue)
+{
+ int ctr = 0;
+ int small;
+
+ if (fvalue < tfrc_calc_x_lookup[0][1])
+ return 0;
+
+ if (fvalue <= tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][1])
+ small = 1;
+ else if (fvalue > tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][0])
+ return 1000000;
+ else
+ small = 0;
+
+ while (fvalue > tfrc_calc_x_lookup[ctr][small])
+ ctr++;
+
+ if (small)
+ return TFRC_CALC_X_SPLIT * ctr / TFRC_CALC_X_ARRSIZE;
+ else
+ return 1000000 * ctr / TFRC_CALC_X_ARRSIZE;
+}
+
+EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
new file mode 100644
index 000000000000..95c4630b3b18
--- /dev/null
+++ b/net/dccp/dccp.h
@@ -0,0 +1,485 @@
+#ifndef _DCCP_H
+#define _DCCP_H
+/*
+ * net/dccp/dccp.h
+ *
+ * An implementation of the DCCP protocol
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *
+ * 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/dccp.h>
+#include <net/snmp.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+extern int dccp_debug;
+
+#define dccp_pr_debug(format, a...) \
+ do { if (dccp_debug) \
+ printk(KERN_DEBUG "%s: " format, __FUNCTION__ , ##a); \
+ } while (0)
+#define dccp_pr_debug_cat(format, a...) do { if (dccp_debug) \
+ printk(format, ##a); } while (0)
+#else
+#define dccp_pr_debug(format, a...)
+#define dccp_pr_debug_cat(format, a...)
+#endif
+
+extern struct inet_hashinfo dccp_hashinfo;
+
+extern atomic_t dccp_orphan_count;
+extern int dccp_tw_count;
+extern void dccp_tw_deschedule(struct inet_timewait_sock *tw);
+
+extern void dccp_time_wait(struct sock *sk, int state, int timeo);
+
+/* FIXME: Right size this */
+#define DCCP_MAX_OPT_LEN 128
+
+#define DCCP_MAX_PACKET_HDR 32
+
+#define MAX_DCCP_HEADER (DCCP_MAX_PACKET_HDR + DCCP_MAX_OPT_LEN + MAX_HEADER)
+
+#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT
+ * state, about 60 seconds */
+
+/* draft-ietf-dccp-spec-11.txt initial RTO value */
+#define DCCP_TIMEOUT_INIT ((unsigned)(3 * HZ))
+
+/* Maximal interval between probes for local resources. */
+#define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U))
+
+#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
+
+extern struct proto dccp_v4_prot;
+
+/* is seq1 < seq2 ? */
+static inline int before48(const u64 seq1, const u64 seq2)
+{
+ return (s64)((seq1 << 16) - (seq2 << 16)) < 0;
+}
+
+/* is seq1 > seq2 ? */
+static inline int after48(const u64 seq1, const u64 seq2)
+{
+ return (s64)((seq2 << 16) - (seq1 << 16)) < 0;
+}
+
+/* is seq2 <= seq1 <= seq3 ? */
+static inline int between48(const u64 seq1, const u64 seq2, const u64 seq3)
+{
+ return (seq3 << 16) - (seq2 << 16) >= (seq1 << 16) - (seq2 << 16);
+}
+
+static inline u64 max48(const u64 seq1, const u64 seq2)
+{
+ return after48(seq1, seq2) ? seq1 : seq2;
+}
+
+enum {
+ DCCP_MIB_NUM = 0,
+ DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */
+ DCCP_MIB_ESTABRESETS, /* EstabResets */
+ DCCP_MIB_CURRESTAB, /* CurrEstab */
+ DCCP_MIB_OUTSEGS, /* OutSegs */
+ DCCP_MIB_OUTRSTS,
+ DCCP_MIB_ABORTONTIMEOUT,
+ DCCP_MIB_TIMEOUTS,
+ DCCP_MIB_ABORTFAILED,
+ DCCP_MIB_PASSIVEOPENS,
+ DCCP_MIB_ATTEMPTFAILS,
+ DCCP_MIB_OUTDATAGRAMS,
+ DCCP_MIB_INERRS,
+ DCCP_MIB_OPTMANDATORYERROR,
+ DCCP_MIB_INVALIDOPT,
+ __DCCP_MIB_MAX
+};
+
+#define DCCP_MIB_MAX __DCCP_MIB_MAX
+struct dccp_mib {
+ unsigned long mibs[DCCP_MIB_MAX];
+} __SNMP_MIB_ALIGN__;
+
+DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
+#define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field)
+#define DCCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(dccp_statistics, field)
+#define DCCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(dccp_statistics, field)
+#define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field)
+#define DCCP_ADD_STATS_BH(field, val) \
+ SNMP_ADD_STATS_BH(dccp_statistics, field, val)
+#define DCCP_ADD_STATS_USER(field, val) \
+ SNMP_ADD_STATS_USER(dccp_statistics, field, val)
+
+extern int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb);
+extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
+
+extern int dccp_send_response(struct sock *sk);
+extern void dccp_send_ack(struct sock *sk);
+extern void dccp_send_delayed_ack(struct sock *sk);
+extern void dccp_send_sync(struct sock *sk, const u64 seq,
+ const enum dccp_pkt_type pkt_type);
+
+extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo);
+extern void dccp_write_space(struct sock *sk);
+
+extern void dccp_init_xmit_timers(struct sock *sk);
+static inline void dccp_clear_xmit_timers(struct sock *sk)
+{
+ inet_csk_clear_xmit_timers(sk);
+}
+
+extern unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu);
+
+extern const char *dccp_packet_name(const int type);
+extern const char *dccp_state_name(const int state);
+
+static inline void dccp_set_state(struct sock *sk, const int state)
+{
+ const int oldstate = sk->sk_state;
+
+ dccp_pr_debug("%s(%p) %-10.10s -> %s\n",
+ dccp_role(sk), sk,
+ dccp_state_name(oldstate), dccp_state_name(state));
+ WARN_ON(state == oldstate);
+
+ switch (state) {
+ case DCCP_OPEN:
+ if (oldstate != DCCP_OPEN)
+ DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
+ break;
+
+ case DCCP_CLOSED:
+ if (oldstate == DCCP_CLOSING || oldstate == DCCP_OPEN)
+ DCCP_INC_STATS(DCCP_MIB_ESTABRESETS);
+
+ sk->sk_prot->unhash(sk);
+ if (inet_csk(sk)->icsk_bind_hash != NULL &&
+ !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
+ inet_put_port(&dccp_hashinfo, sk);
+ /* fall through */
+ default:
+ if (oldstate == DCCP_OPEN)
+ DCCP_DEC_STATS(DCCP_MIB_CURRESTAB);
+ }
+
+ /* Change state AFTER socket is unhashed to avoid closed
+ * socket sitting in hash tables.
+ */
+ sk->sk_state = state;
+}
+
+static inline void dccp_done(struct sock *sk)
+{
+ dccp_set_state(sk, DCCP_CLOSED);
+ dccp_clear_xmit_timers(sk);
+
+ sk->sk_shutdown = SHUTDOWN_MASK;
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_state_change(sk);
+ else
+ inet_csk_destroy_sock(sk);
+}
+
+static inline void dccp_openreq_init(struct request_sock *req,
+ struct dccp_sock *dp,
+ struct sk_buff *skb)
+{
+ /*
+ * FIXME: fill in the other req fields from the DCCP options
+ * received
+ */
+ inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport;
+ inet_rsk(req)->acked = 0;
+ req->rcv_wnd = 0;
+}
+
+extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+
+extern struct sock *dccp_create_openreq_child(struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
+
+extern int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
+
+extern void dccp_v4_err(struct sk_buff *skb, u32);
+
+extern int dccp_v4_rcv(struct sk_buff *skb);
+
+extern struct sock *dccp_v4_request_recv_sock(struct sock *sk,
+ struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst);
+extern struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct request_sock **prev);
+
+extern int dccp_child_process(struct sock *parent, struct sock *child,
+ struct sk_buff *skb);
+extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ struct dccp_hdr *dh, unsigned len);
+extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ const struct dccp_hdr *dh, const unsigned len);
+
+extern void dccp_close(struct sock *sk, long timeout);
+extern struct sk_buff *dccp_make_response(struct sock *sk,
+ struct dst_entry *dst,
+ struct request_sock *req);
+extern struct sk_buff *dccp_make_reset(struct sock *sk,
+ struct dst_entry *dst,
+ enum dccp_reset_codes code);
+
+extern int dccp_connect(struct sock *sk);
+extern int dccp_disconnect(struct sock *sk, int flags);
+extern int dccp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+extern int dccp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+extern int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern int dccp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t size);
+extern int dccp_recvmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t len, int nonblock,
+ int flags, int *addr_len);
+extern void dccp_shutdown(struct sock *sk, int how);
+
+extern int dccp_v4_checksum(const struct sk_buff *skb,
+ const u32 saddr, const u32 daddr);
+
+extern int dccp_v4_send_reset(struct sock *sk,
+ enum dccp_reset_codes code);
+extern void dccp_send_close(struct sock *sk, const int active);
+
+struct dccp_skb_cb {
+ __u8 dccpd_type;
+ __u8 dccpd_reset_code;
+ __u8 dccpd_service;
+ __u8 dccpd_ccval;
+ __u64 dccpd_seq;
+ __u64 dccpd_ack_seq;
+ int dccpd_opt_len;
+};
+
+#define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
+
+static inline int dccp_non_data_packet(const struct sk_buff *skb)
+{
+ const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
+
+ return type == DCCP_PKT_ACK ||
+ type == DCCP_PKT_CLOSE ||
+ type == DCCP_PKT_CLOSEREQ ||
+ type == DCCP_PKT_RESET ||
+ type == DCCP_PKT_SYNC ||
+ type == DCCP_PKT_SYNCACK;
+}
+
+static inline int dccp_packet_without_ack(const struct sk_buff *skb)
+{
+ const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
+
+ return type == DCCP_PKT_DATA || type == DCCP_PKT_REQUEST;
+}
+
+#define DCCP_MAX_SEQNO ((((u64)1) << 48) - 1)
+#define DCCP_PKT_WITHOUT_ACK_SEQ (DCCP_MAX_SEQNO << 2)
+
+static inline void dccp_set_seqno(u64 *seqno, u64 value)
+{
+ if (value > DCCP_MAX_SEQNO)
+ value -= DCCP_MAX_SEQNO + 1;
+ *seqno = value;
+}
+
+static inline u64 dccp_delta_seqno(u64 seqno1, u64 seqno2)
+{
+ return ((seqno2 << 16) - (seqno1 << 16)) >> 16;
+}
+
+static inline void dccp_inc_seqno(u64 *seqno)
+{
+ if (++*seqno > DCCP_MAX_SEQNO)
+ *seqno = 0;
+}
+
+static inline void dccp_hdr_set_seq(struct dccp_hdr *dh, const u64 gss)
+{
+ struct dccp_hdr_ext *dhx = (struct dccp_hdr_ext *)((void *)dh +
+ sizeof(*dh));
+
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ dh->dccph_seq = htonl((gss >> 32)) >> 8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ dh->dccph_seq = htonl((gss >> 32));
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ dhx->dccph_seq_low = htonl(gss & 0xffffffff);
+}
+
+static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack,
+ const u64 gsr)
+{
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ dhack->dccph_ack_nr_high = htonl((gsr >> 32)) >> 8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ dhack->dccph_ack_nr_high = htonl((gsr >> 32));
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ dhack->dccph_ack_nr_low = htonl(gsr & 0xffffffff);
+}
+
+static inline void dccp_update_gsr(struct sock *sk, u64 seq)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ dp->dccps_gsr = seq;
+ dccp_set_seqno(&dp->dccps_swl,
+ (dp->dccps_gsr + 1 -
+ (dp->dccps_options.dccpo_sequence_window / 4)));
+ dccp_set_seqno(&dp->dccps_swh,
+ (dp->dccps_gsr +
+ (3 * dp->dccps_options.dccpo_sequence_window) / 4));
+}
+
+static inline void dccp_update_gss(struct sock *sk, u64 seq)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ dp->dccps_awh = dp->dccps_gss = seq;
+ dccp_set_seqno(&dp->dccps_awl,
+ (dp->dccps_gss -
+ dp->dccps_options.dccpo_sequence_window + 1));
+}
+
+extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb);
+extern void dccp_insert_option_elapsed_time(struct sock *sk,
+ struct sk_buff *skb,
+ u32 elapsed_time);
+extern void dccp_insert_option_timestamp(struct sock *sk,
+ struct sk_buff *skb);
+extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
+ unsigned char option,
+ const void *value, unsigned char len);
+
+extern struct socket *dccp_ctl_socket;
+
+#define DCCP_ACKPKTS_STATE_RECEIVED 0
+#define DCCP_ACKPKTS_STATE_ECN_MARKED (1 << 6)
+#define DCCP_ACKPKTS_STATE_NOT_RECEIVED (3 << 6)
+
+#define DCCP_ACKPKTS_STATE_MASK 0xC0 /* 11000000 */
+#define DCCP_ACKPKTS_LEN_MASK 0x3F /* 00111111 */
+
+/** struct dccp_ackpkts - acknowledgeable packets
+ *
+ * This data structure is the one defined in the DCCP draft
+ * Appendix A.
+ *
+ * @dccpap_buf_head - circular buffer head
+ * @dccpap_buf_tail - circular buffer tail
+ * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the
+ * buffer (i.e. %dccpap_buf_head)
+ * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked
+ * by the buffer with State 0
+ *
+ * Additionally, the HC-Receiver must keep some information about the
+ * Ack Vectors it has recently sent. For each packet sent carrying an
+ * Ack Vector, it remembers four variables:
+ *
+ * @dccpap_ack_seqno - the Sequence Number used for the packet
+ * (HC-Receiver seqno)
+ * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement.
+ * @dccpap_ack_ackno - the Acknowledgement Number used for the packet
+ * (HC-Sender seqno)
+ * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
+ *
+ * @dccpap_buf_len - circular buffer length
+ * @dccpap_time - the time in usecs
+ * @dccpap_buf - circular buffer of acknowledgeable packets
+ */
+struct dccp_ackpkts {
+ unsigned int dccpap_buf_head;
+ unsigned int dccpap_buf_tail;
+ u64 dccpap_buf_ackno;
+ u64 dccpap_ack_seqno;
+ u64 dccpap_ack_ackno;
+ unsigned int dccpap_ack_ptr;
+ unsigned int dccpap_buf_vector_len;
+ unsigned int dccpap_ack_vector_len;
+ unsigned int dccpap_buf_len;
+ struct timeval dccpap_time;
+ u8 dccpap_buf_nonce;
+ u8 dccpap_ack_nonce;
+ u8 dccpap_buf[0];
+};
+
+extern struct dccp_ackpkts *
+ dccp_ackpkts_alloc(unsigned int len,
+ const unsigned int __nocast priority);
+extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
+extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+ u64 ackno, u8 state);
+extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
+ struct sock *sk, u64 ackno);
+
+extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
+
+static inline suseconds_t timeval_usecs(const struct timeval *tv)
+{
+ return tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
+}
+
+static inline suseconds_t timeval_delta(const struct timeval *large,
+ const struct timeval *small)
+{
+ time_t secs = large->tv_sec - small->tv_sec;
+ suseconds_t usecs = large->tv_usec - small->tv_usec;
+
+ if (usecs < 0) {
+ secs--;
+ usecs += USEC_PER_SEC;
+ }
+ return secs * USEC_PER_SEC + usecs;
+}
+
+static inline void timeval_add_usecs(struct timeval *tv,
+ const suseconds_t usecs)
+{
+ tv->tv_usec += usecs;
+ while (tv->tv_usec >= USEC_PER_SEC) {
+ tv->tv_sec++;
+ tv->tv_usec -= USEC_PER_SEC;
+ }
+}
+
+static inline void timeval_sub_usecs(struct timeval *tv,
+ const suseconds_t usecs)
+{
+ tv->tv_usec -= usecs;
+ while (tv->tv_usec < 0) {
+ tv->tv_sec--;
+ tv->tv_usec += USEC_PER_SEC;
+ }
+}
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+extern void dccp_ackvector_print(const u64 ackno,
+ const unsigned char *vector, int len);
+extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap);
+#else
+static inline void dccp_ackvector_print(const u64 ackno,
+ const unsigned char *vector,
+ int len) { }
+static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { }
+#endif
+
+#endif /* _DCCP_H */
diff --git a/net/dccp/diag.c b/net/dccp/diag.c
new file mode 100644
index 000000000000..f675d8e642d3
--- /dev/null
+++ b/net/dccp/diag.c
@@ -0,0 +1,71 @@
+/*
+ * net/dccp/diag.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@mandriva.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/inet_diag.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+static void dccp_get_info(struct sock *sk, struct tcp_info *info)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ memset(info, 0, sizeof(*info));
+
+ info->tcpi_state = sk->sk_state;
+ info->tcpi_retransmits = icsk->icsk_retransmits;
+ info->tcpi_probes = icsk->icsk_probes_out;
+ info->tcpi_backoff = icsk->icsk_backoff;
+ info->tcpi_pmtu = dp->dccps_pmtu_cookie;
+
+ if (dp->dccps_options.dccpo_send_ack_vector)
+ info->tcpi_options |= TCPI_OPT_SACK;
+
+ ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info);
+ ccid_hc_tx_get_info(dp->dccps_hc_tx_ccid, sk, info);
+}
+
+static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+ void *_info)
+{
+ r->idiag_rqueue = r->idiag_wqueue = 0;
+
+ if (_info != NULL)
+ dccp_get_info(sk, _info);
+}
+
+static struct inet_diag_handler dccp_diag_handler = {
+ .idiag_hashinfo = &dccp_hashinfo,
+ .idiag_get_info = dccp_diag_get_info,
+ .idiag_type = DCCPDIAG_GETSOCK,
+ .idiag_info_size = sizeof(struct tcp_info),
+};
+
+static int __init dccp_diag_init(void)
+{
+ return inet_diag_register(&dccp_diag_handler);
+}
+
+static void __exit dccp_diag_fini(void)
+{
+ inet_diag_unregister(&dccp_diag_handler);
+}
+
+module_init(dccp_diag_init);
+module_exit(dccp_diag_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
+MODULE_DESCRIPTION("DCCP inet_diag handler");
diff --git a/net/dccp/input.c b/net/dccp/input.c
new file mode 100644
index 000000000000..c60bc3433f5e
--- /dev/null
+++ b/net/dccp/input.c
@@ -0,0 +1,600 @@
+/*
+ * net/dccp/input.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+
+#include <net/sock.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+static void dccp_fin(struct sock *sk, struct sk_buff *skb)
+{
+ sk->sk_shutdown |= RCV_SHUTDOWN;
+ sock_set_flag(sk, SOCK_DONE);
+ __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4);
+ __skb_queue_tail(&sk->sk_receive_queue, skb);
+ skb_set_owner_r(skb, sk);
+ sk->sk_data_ready(sk, 0);
+}
+
+static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb)
+{
+ dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED);
+ dccp_fin(sk, skb);
+ dccp_set_state(sk, DCCP_CLOSED);
+ sk_wake_async(sk, 1, POLL_HUP);
+}
+
+static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
+{
+ /*
+ * Step 7: Check for unexpected packet types
+ * If (S.is_server and P.type == CloseReq)
+ * Send Sync packet acknowledging P.seqno
+ * Drop packet and return
+ */
+ if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) {
+ dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC);
+ return;
+ }
+
+ dccp_set_state(sk, DCCP_CLOSING);
+ dccp_send_close(sk, 0);
+}
+
+static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ if (dp->dccps_options.dccpo_send_ack_vector)
+ dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk,
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+}
+
+static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+ struct dccp_sock *dp = dccp_sk(sk);
+ u64 lswl, lawl;
+
+ /*
+ * Step 5: Prepare sequence numbers for Sync
+ * If P.type == Sync or P.type == SyncAck,
+ * If S.AWL <= P.ackno <= S.AWH and P.seqno >= S.SWL,
+ * / * P is valid, so update sequence number variables
+ * accordingly. After this update, P will pass the tests
+ * in Step 6. A SyncAck is generated if necessary in
+ * Step 15 * /
+ * Update S.GSR, S.SWL, S.SWH
+ * Otherwise,
+ * Drop packet and return
+ */
+ if (dh->dccph_type == DCCP_PKT_SYNC ||
+ dh->dccph_type == DCCP_PKT_SYNCACK) {
+ if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ dp->dccps_awl, dp->dccps_awh) &&
+ !before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_swl))
+ dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq);
+ else
+ return -1;
+ }
+
+ /*
+ * Step 6: Check sequence numbers
+ * Let LSWL = S.SWL and LAWL = S.AWL
+ * If P.type == CloseReq or P.type == Close or P.type == Reset,
+ * LSWL := S.GSR + 1, LAWL := S.GAR
+ * If LSWL <= P.seqno <= S.SWH
+ * and (P.ackno does not exist or LAWL <= P.ackno <= S.AWH),
+ * Update S.GSR, S.SWL, S.SWH
+ * If P.type != Sync,
+ * Update S.GAR
+ * Otherwise,
+ * Send Sync packet acknowledging P.seqno
+ * Drop packet and return
+ */
+ lswl = dp->dccps_swl;
+ lawl = dp->dccps_awl;
+
+ if (dh->dccph_type == DCCP_PKT_CLOSEREQ ||
+ dh->dccph_type == DCCP_PKT_CLOSE ||
+ dh->dccph_type == DCCP_PKT_RESET) {
+ lswl = dp->dccps_gsr;
+ dccp_inc_seqno(&lswl);
+ lawl = dp->dccps_gar;
+ }
+
+ if (between48(DCCP_SKB_CB(skb)->dccpd_seq, lswl, dp->dccps_swh) &&
+ (DCCP_SKB_CB(skb)->dccpd_ack_seq == DCCP_PKT_WITHOUT_ACK_SEQ ||
+ between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ lawl, dp->dccps_awh))) {
+ dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq);
+
+ if (dh->dccph_type != DCCP_PKT_SYNC &&
+ (DCCP_SKB_CB(skb)->dccpd_ack_seq !=
+ DCCP_PKT_WITHOUT_ACK_SEQ))
+ dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq;
+ } else {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, "
+ "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "
+ "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "
+ "sending SYNC...\n",
+ dccp_packet_name(dh->dccph_type),
+ (unsigned long long) lswl,
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ (unsigned long long) dp->dccps_swh,
+ (DCCP_SKB_CB(skb)->dccpd_ack_seq ==
+ DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists",
+ (unsigned long long) lawl,
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ (unsigned long long) dp->dccps_awh);
+ dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC);
+ return -1;
+ }
+
+ return 0;
+}
+
+int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ const struct dccp_hdr *dh, const unsigned len)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ if (dccp_check_seqno(sk, skb))
+ goto discard;
+
+ if (dccp_parse_options(sk, skb))
+ goto discard;
+
+ if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
+ dccp_event_ack_recv(sk, skb);
+
+ /*
+ * FIXME: check ECN to see if we should use
+ * DCCP_ACKPKTS_STATE_ECN_MARKED
+ */
+ if (dp->dccps_options.dccpo_send_ack_vector) {
+ struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
+
+ if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKPKTS_STATE_RECEIVED)) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
+ "packets buffer full!\n");
+ ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
+ inet_csk_schedule_ack(sk);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ TCP_DELACK_MIN,
+ DCCP_RTO_MAX);
+ goto discard;
+ }
+
+ /*
+ * FIXME: this activation is probably wrong, have to study more
+ * TCP delack machinery and how it fits into DCCP draft, but
+ * for now it kinda "works" 8)
+ */
+ if (!inet_csk_ack_scheduled(sk)) {
+ inet_csk_schedule_ack(sk);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ,
+ DCCP_RTO_MAX);
+ }
+ }
+
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+
+ switch (dccp_hdr(skb)->dccph_type) {
+ case DCCP_PKT_DATAACK:
+ case DCCP_PKT_DATA:
+ /*
+ * FIXME: check if sk_receive_queue is full, schedule DATA_DROPPED
+ * option if it is.
+ */
+ __skb_pull(skb, dh->dccph_doff * 4);
+ __skb_queue_tail(&sk->sk_receive_queue, skb);
+ skb_set_owner_r(skb, sk);
+ sk->sk_data_ready(sk, 0);
+ return 0;
+ case DCCP_PKT_ACK:
+ goto discard;
+ case DCCP_PKT_RESET:
+ /*
+ * Step 9: Process Reset
+ * If P.type == Reset,
+ * Tear down connection
+ * S.state := TIMEWAIT
+ * Set TIMEWAIT timer
+ * Drop packet and return
+ */
+ dccp_fin(sk, skb);
+ dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
+ return 0;
+ case DCCP_PKT_CLOSEREQ:
+ dccp_rcv_closereq(sk, skb);
+ goto discard;
+ case DCCP_PKT_CLOSE:
+ dccp_rcv_close(sk, skb);
+ return 0;
+ case DCCP_PKT_REQUEST:
+ /* Step 7
+ * or (S.is_server and P.type == Response)
+ * or (S.is_client and P.type == Request)
+ * or (S.state >= OPEN and P.type == Request
+ * and P.seqno >= S.OSR)
+ * or (S.state >= OPEN and P.type == Response
+ * and P.seqno >= S.OSR)
+ * or (S.state == RESPOND and P.type == Data),
+ * Send Sync packet acknowledging P.seqno
+ * Drop packet and return
+ */
+ if (dp->dccps_role != DCCP_ROLE_LISTEN)
+ goto send_sync;
+ goto check_seq;
+ case DCCP_PKT_RESPONSE:
+ if (dp->dccps_role != DCCP_ROLE_CLIENT)
+ goto send_sync;
+check_seq:
+ if (!before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_osr)) {
+send_sync:
+ dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_PKT_SYNC);
+ }
+ break;
+ case DCCP_PKT_SYNC:
+ dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_PKT_SYNCACK);
+ /*
+ * From the draft:
+ *
+ * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets
+ * MAY have non-zero-length application data areas, whose
+ * contents * receivers MUST ignore.
+ */
+ goto discard;
+ }
+
+ DCCP_INC_STATS_BH(DCCP_MIB_INERRS);
+discard:
+ __kfree_skb(skb);
+ return 0;
+}
+
+static int dccp_rcv_request_sent_state_process(struct sock *sk,
+ struct sk_buff *skb,
+ const struct dccp_hdr *dh,
+ const unsigned len)
+{
+ /*
+ * Step 4: Prepare sequence numbers in REQUEST
+ * If S.state == REQUEST,
+ * If (P.type == Response or P.type == Reset)
+ * and S.AWL <= P.ackno <= S.AWH,
+ * / * Set sequence number variables corresponding to the
+ * other endpoint, so P will pass the tests in Step 6 * /
+ * Set S.GSR, S.ISR, S.SWL, S.SWH
+ * / * Response processing continues in Step 10; Reset
+ * processing continues in Step 9 * /
+ */
+ if (dh->dccph_type == DCCP_PKT_RESPONSE) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ /* Stop the REQUEST timer */
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
+ BUG_TRAP(sk->sk_send_head != NULL);
+ __kfree_skb(sk->sk_send_head);
+ sk->sk_send_head = NULL;
+
+ if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ dp->dccps_awl, dp->dccps_awh)) {
+ dccp_pr_debug("invalid ackno: S.AWL=%llu, "
+ "P.ackno=%llu, S.AWH=%llu \n",
+ (unsigned long long)dp->dccps_awl,
+ (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ (unsigned long long)dp->dccps_awh);
+ goto out_invalid_packet;
+ }
+
+ dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
+ dccp_update_gsr(sk, dp->dccps_isr);
+ /*
+ * SWL and AWL are initially adjusted so that they are not less than
+ * the initial Sequence Numbers received and sent, respectively:
+ * SWL := max(GSR + 1 - floor(W/4), ISR),
+ * AWL := max(GSS - W' + 1, ISS).
+ * These adjustments MUST be applied only at the beginning of the
+ * connection.
+ *
+ * AWL was adjusted in dccp_v4_connect -acme
+ */
+ dccp_set_seqno(&dp->dccps_swl,
+ max48(dp->dccps_swl, dp->dccps_isr));
+
+ if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
+ ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
+ ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
+ /* FIXME: send appropriate RESET code */
+ goto out_invalid_packet;
+ }
+
+ dccp_sync_mss(sk, dp->dccps_pmtu_cookie);
+
+ /*
+ * Step 10: Process REQUEST state (second part)
+ * If S.state == REQUEST,
+ * / * If we get here, P is a valid Response from the
+ * server (see Step 4), and we should move to
+ * PARTOPEN state. PARTOPEN means send an Ack,
+ * don't send Data packets, retransmit Acks
+ * periodically, and always include any Init Cookie
+ * from the Response * /
+ * S.state := PARTOPEN
+ * Set PARTOPEN timer
+ * Continue with S.state == PARTOPEN
+ * / * Step 12 will send the Ack completing the
+ * three-way handshake * /
+ */
+ dccp_set_state(sk, DCCP_PARTOPEN);
+
+ /* Make sure socket is routed, for correct metrics. */
+ inet_sk_rebuild_header(sk);
+
+ if (!sock_flag(sk, SOCK_DEAD)) {
+ sk->sk_state_change(sk);
+ sk_wake_async(sk, 0, POLL_OUT);
+ }
+
+ if (sk->sk_write_pending || icsk->icsk_ack.pingpong ||
+ icsk->icsk_accept_queue.rskq_defer_accept) {
+ /* Save one ACK. Data will be ready after
+ * several ticks, if write_pending is set.
+ *
+ * It may be deleted, but with this feature tcpdumps
+ * look so _wonderfully_ clever, that I was not able
+ * to stand against the temptation 8) --ANK
+ */
+ /*
+ * OK, in DCCP we can as well do a similar trick, its
+ * even in the draft, but there is no need for us to
+ * schedule an ack here, as dccp_sendmsg does this for
+ * us, also stated in the draft. -acme
+ */
+ __kfree_skb(skb);
+ return 0;
+ }
+ dccp_send_ack(sk);
+ return -1;
+ }
+
+out_invalid_packet:
+ return 1; /* dccp_v4_do_rcv will send a reset, but...
+ FIXME: the reset code should be
+ DCCP_RESET_CODE_PACKET_ERROR */
+}
+
+static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
+ struct sk_buff *skb,
+ const struct dccp_hdr *dh,
+ const unsigned len)
+{
+ int queued = 0;
+
+ switch (dh->dccph_type) {
+ case DCCP_PKT_RESET:
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
+ break;
+ case DCCP_PKT_DATAACK:
+ case DCCP_PKT_ACK:
+ /*
+ * FIXME: we should be reseting the PARTOPEN (DELACK) timer
+ * here but only if we haven't used the DELACK timer for
+ * something else, like sending a delayed ack for a TIMESTAMP
+ * echo, etc, for now were not clearing it, sending an extra
+ * ACK when there is nothing else to do in DELACK is not a big
+ * deal after all.
+ */
+
+ /* Stop the PARTOPEN timer */
+ if (sk->sk_state == DCCP_PARTOPEN)
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
+
+ dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq;
+ dccp_set_state(sk, DCCP_OPEN);
+
+ if (dh->dccph_type == DCCP_PKT_DATAACK) {
+ dccp_rcv_established(sk, skb, dh, len);
+ queued = 1; /* packet was queued
+ (by dccp_rcv_established) */
+ }
+ break;
+ }
+
+ return queued;
+}
+
+int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ struct dccp_hdr *dh, unsigned len)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ const int old_state = sk->sk_state;
+ int queued = 0;
+
+ /*
+ * Step 3: Process LISTEN state
+ * (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv)
+ *
+ * If S.state == LISTEN,
+ * If P.type == Request or P contains a valid Init Cookie
+ * option,
+ * * Must scan the packet's options to check for an Init
+ * Cookie. Only the Init Cookie is processed here,
+ * however; other options are processed in Step 8. This
+ * scan need only be performed if the endpoint uses Init
+ * Cookies *
+ * * Generate a new socket and switch to that socket *
+ * Set S := new socket for this port pair
+ * S.state = RESPOND
+ * Choose S.ISS (initial seqno) or set from Init Cookie
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ * Continue with S.state == RESPOND
+ * * A Response packet will be generated in Step 11 *
+ * Otherwise,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ *
+ * NOTE: the check for the packet types is done in
+ * dccp_rcv_state_process
+ */
+ if (sk->sk_state == DCCP_LISTEN) {
+ if (dh->dccph_type == DCCP_PKT_REQUEST) {
+ if (dccp_v4_conn_request(sk, skb) < 0)
+ return 1;
+
+ /* FIXME: do congestion control initialization */
+ goto discard;
+ }
+ if (dh->dccph_type == DCCP_PKT_RESET)
+ goto discard;
+
+ /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/
+ return 1;
+ }
+
+ if (sk->sk_state != DCCP_REQUESTING) {
+ if (dccp_check_seqno(sk, skb))
+ goto discard;
+
+ /*
+ * Step 8: Process options and mark acknowledgeable
+ */
+ if (dccp_parse_options(sk, skb))
+ goto discard;
+
+ if (DCCP_SKB_CB(skb)->dccpd_ack_seq !=
+ DCCP_PKT_WITHOUT_ACK_SEQ)
+ dccp_event_ack_recv(sk, skb);
+
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+
+ /*
+ * FIXME: check ECN to see if we should use
+ * DCCP_ACKPKTS_STATE_ECN_MARKED
+ */
+ if (dp->dccps_options.dccpo_send_ack_vector) {
+ if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKPKTS_STATE_RECEIVED))
+ goto discard;
+ /*
+ * FIXME: this activation is probably wrong, have to
+ * study more TCP delack machinery and how it fits into
+ * DCCP draft, but for now it kinda "works" 8)
+ */
+ if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno ==
+ DCCP_MAX_SEQNO + 1) &&
+ !inet_csk_ack_scheduled(sk)) {
+ inet_csk_schedule_ack(sk);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ TCP_DELACK_MIN,
+ DCCP_RTO_MAX);
+ }
+ }
+ }
+
+ /*
+ * Step 9: Process Reset
+ * If P.type == Reset,
+ * Tear down connection
+ * S.state := TIMEWAIT
+ * Set TIMEWAIT timer
+ * Drop packet and return
+ */
+ if (dh->dccph_type == DCCP_PKT_RESET) {
+ /*
+ * Queue the equivalent of TCP fin so that dccp_recvmsg
+ * exits the loop
+ */
+ dccp_fin(sk, skb);
+ dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
+ return 0;
+ /*
+ * Step 7: Check for unexpected packet types
+ * If (S.is_server and P.type == CloseReq)
+ * or (S.is_server and P.type == Response)
+ * or (S.is_client and P.type == Request)
+ * or (S.state == RESPOND and P.type == Data),
+ * Send Sync packet acknowledging P.seqno
+ * Drop packet and return
+ */
+ } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
+ (dh->dccph_type == DCCP_PKT_RESPONSE ||
+ dh->dccph_type == DCCP_PKT_CLOSEREQ)) ||
+ (dp->dccps_role == DCCP_ROLE_CLIENT &&
+ dh->dccph_type == DCCP_PKT_REQUEST) ||
+ (sk->sk_state == DCCP_RESPOND &&
+ dh->dccph_type == DCCP_PKT_DATA)) {
+ dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_PKT_SYNC);
+ goto discard;
+ } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
+ dccp_rcv_closereq(sk, skb);
+ goto discard;
+ } else if (dh->dccph_type == DCCP_PKT_CLOSE) {
+ dccp_rcv_close(sk, skb);
+ return 0;
+ }
+
+ switch (sk->sk_state) {
+ case DCCP_CLOSED:
+ return 1;
+
+ case DCCP_REQUESTING:
+ /* FIXME: do congestion control initialization */
+
+ queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
+ if (queued >= 0)
+ return queued;
+
+ __kfree_skb(skb);
+ return 0;
+
+ case DCCP_RESPOND:
+ case DCCP_PARTOPEN:
+ queued = dccp_rcv_respond_partopen_state_process(sk, skb,
+ dh, len);
+ break;
+ }
+
+ if (dh->dccph_type == DCCP_PKT_ACK ||
+ dh->dccph_type == DCCP_PKT_DATAACK) {
+ switch (old_state) {
+ case DCCP_PARTOPEN:
+ sk->sk_state_change(sk);
+ sk_wake_async(sk, 0, POLL_OUT);
+ break;
+ }
+ }
+
+ if (!queued) {
+discard:
+ __kfree_skb(skb);
+ }
+ return 0;
+}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
new file mode 100644
index 000000000000..2afaa464e7f0
--- /dev/null
+++ b/net/dccp/ipv4.c
@@ -0,0 +1,1353 @@
+/*
+ * net/dccp/ipv4.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/dccp.h>
+#include <linux/icmp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+
+#include <net/icmp.h>
+#include <net/inet_hashtables.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/xfrm.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
+ .lhash_lock = RW_LOCK_UNLOCKED,
+ .lhash_users = ATOMIC_INIT(0),
+ .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait),
+ .portalloc_lock = SPIN_LOCK_UNLOCKED,
+ .port_rover = 1024 - 1,
+};
+
+EXPORT_SYMBOL_GPL(dccp_hashinfo);
+
+static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
+{
+ return inet_csk_get_port(&dccp_hashinfo, sk, snum);
+}
+
+static void dccp_v4_hash(struct sock *sk)
+{
+ inet_hash(&dccp_hashinfo, sk);
+}
+
+static void dccp_v4_unhash(struct sock *sk)
+{
+ inet_unhash(&dccp_hashinfo, sk);
+}
+
+/* called with local bh disabled */
+static int __dccp_v4_check_established(struct sock *sk, const __u16 lport,
+ struct inet_timewait_sock **twp)
+{
+ struct inet_sock *inet = inet_sk(sk);
+ const u32 daddr = inet->rcv_saddr;
+ const u32 saddr = inet->daddr;
+ const int dif = sk->sk_bound_dev_if;
+ INET_ADDR_COOKIE(acookie, saddr, daddr)
+ const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+ const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport,
+ dccp_hashinfo.ehash_size);
+ struct inet_ehash_bucket *head = &dccp_hashinfo.ehash[hash];
+ const struct sock *sk2;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
+
+ write_lock(&head->lock);
+
+ /* Check TIME-WAIT sockets first. */
+ sk_for_each(sk2, node, &(head + dccp_hashinfo.ehash_size)->chain) {
+ tw = inet_twsk(sk2);
+
+ if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+ goto not_unique;
+ }
+ tw = NULL;
+
+ /* And established part... */
+ sk_for_each(sk2, node, &head->chain) {
+ if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+ goto not_unique;
+ }
+
+ /* Must record num and sport now. Otherwise we will see
+ * in hash table socket with a funny identity. */
+ inet->num = lport;
+ inet->sport = htons(lport);
+ sk->sk_hashent = hash;
+ BUG_TRAP(sk_unhashed(sk));
+ __sk_add_node(sk, &head->chain);
+ sock_prot_inc_use(sk->sk_prot);
+ write_unlock(&head->lock);
+
+ if (twp != NULL) {
+ *twp = tw;
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+ } else if (tw != NULL) {
+ /* Silly. Should hash-dance instead... */
+ inet_twsk_deschedule(tw, &dccp_death_row);
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+
+ inet_twsk_put(tw);
+ }
+
+ return 0;
+
+not_unique:
+ write_unlock(&head->lock);
+ return -EADDRNOTAVAIL;
+}
+
+/*
+ * Bind a port for a connect operation and hash it.
+ */
+static int dccp_v4_hash_connect(struct sock *sk)
+{
+ const unsigned short snum = inet_sk(sk)->num;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
+ int ret;
+
+ if (snum == 0) {
+ int rover;
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+ struct hlist_node *node;
+ struct inet_timewait_sock *tw = NULL;
+
+ local_bh_disable();
+
+ /* TODO. Actually it is not so bad idea to remove
+ * dccp_hashinfo.portalloc_lock before next submission to
+ * Linus.
+ * As soon as we touch this place at all it is time to think.
+ *
+ * Now it protects single _advisory_ variable
+ * dccp_hashinfo.port_rover, hence it is mostly useless.
+ * Code will work nicely if we just delete it, but
+ * I am afraid in contented case it will work not better or
+ * even worse: another cpu just will hit the same bucket
+ * and spin there.
+ * So some cpu salt could remove both contention and
+ * memory pingpong. Any ideas how to do this in a nice way?
+ */
+ spin_lock(&dccp_hashinfo.portalloc_lock);
+ rover = dccp_hashinfo.port_rover;
+
+ do {
+ rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ head = &dccp_hashinfo.bhash[inet_bhashfn(rover,
+ dccp_hashinfo.bhash_size)];
+ spin_lock(&head->lock);
+
+ /* Does not bother with rcv_saddr checks,
+ * because the established check is already
+ * unique enough.
+ */
+ inet_bind_bucket_for_each(tb, node, &head->chain) {
+ if (tb->port == rover) {
+ BUG_TRAP(!hlist_empty(&tb->owners));
+ if (tb->fastreuse >= 0)
+ goto next_port;
+ if (!__dccp_v4_check_established(sk,
+ rover,
+ &tw))
+ goto ok;
+ goto next_port;
+ }
+ }
+
+ tb = inet_bind_bucket_create(dccp_hashinfo.bind_bucket_cachep,
+ head, rover);
+ if (tb == NULL) {
+ spin_unlock(&head->lock);
+ break;
+ }
+ tb->fastreuse = -1;
+ goto ok;
+
+ next_port:
+ spin_unlock(&head->lock);
+ } while (--remaining > 0);
+ dccp_hashinfo.port_rover = rover;
+ spin_unlock(&dccp_hashinfo.portalloc_lock);
+
+ local_bh_enable();
+
+ return -EADDRNOTAVAIL;
+
+ok:
+ /* All locks still held and bhs disabled */
+ dccp_hashinfo.port_rover = rover;
+ spin_unlock(&dccp_hashinfo.portalloc_lock);
+
+ inet_bind_hash(sk, tb, rover);
+ if (sk_unhashed(sk)) {
+ inet_sk(sk)->sport = htons(rover);
+ __inet_hash(&dccp_hashinfo, sk, 0);
+ }
+ spin_unlock(&head->lock);
+
+ if (tw != NULL) {
+ inet_twsk_deschedule(tw, &dccp_death_row);
+ inet_twsk_put(tw);
+ }
+
+ ret = 0;
+ goto out;
+ }
+
+ head = &dccp_hashinfo.bhash[inet_bhashfn(snum,
+ dccp_hashinfo.bhash_size)];
+ tb = inet_csk(sk)->icsk_bind_hash;
+ spin_lock_bh(&head->lock);
+ if (sk_head(&tb->owners) == sk && sk->sk_bind_node.next == NULL) {
+ __inet_hash(&dccp_hashinfo, sk, 0);
+ spin_unlock_bh(&head->lock);
+ return 0;
+ } else {
+ spin_unlock(&head->lock);
+ /* No definite answer... Walk to established hash table */
+ ret = __dccp_v4_check_established(sk, snum, NULL);
+out:
+ local_bh_enable();
+ return ret;
+ }
+}
+
+static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len)
+{
+ struct inet_sock *inet = inet_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+ const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+ struct rtable *rt;
+ u32 daddr, nexthop;
+ int tmp;
+ int err;
+
+ dp->dccps_role = DCCP_ROLE_CLIENT;
+
+ if (addr_len < sizeof(struct sockaddr_in))
+ return -EINVAL;
+
+ if (usin->sin_family != AF_INET)
+ return -EAFNOSUPPORT;
+
+ nexthop = daddr = usin->sin_addr.s_addr;
+ if (inet->opt != NULL && inet->opt->srr) {
+ if (daddr == 0)
+ return -EINVAL;
+ nexthop = inet->opt->faddr;
+ }
+
+ tmp = ip_route_connect(&rt, nexthop, inet->saddr,
+ RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+ IPPROTO_DCCP,
+ inet->sport, usin->sin_port, sk);
+ if (tmp < 0)
+ return tmp;
+
+ if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+ ip_rt_put(rt);
+ return -ENETUNREACH;
+ }
+
+ if (inet->opt == NULL || !inet->opt->srr)
+ daddr = rt->rt_dst;
+
+ if (inet->saddr == 0)
+ inet->saddr = rt->rt_src;
+ inet->rcv_saddr = inet->saddr;
+
+ inet->dport = usin->sin_port;
+ inet->daddr = daddr;
+
+ dp->dccps_ext_header_len = 0;
+ if (inet->opt != NULL)
+ dp->dccps_ext_header_len = inet->opt->optlen;
+ /*
+ * Socket identity is still unknown (sport may be zero).
+ * However we set state to DCCP_REQUESTING and not releasing socket
+ * lock select source port, enter ourselves into the hash tables and
+ * complete initialization after this.
+ */
+ dccp_set_state(sk, DCCP_REQUESTING);
+ err = dccp_v4_hash_connect(sk);
+ if (err != 0)
+ goto failure;
+
+ err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+ if (err != 0)
+ goto failure;
+
+ /* OK, now commit destination to socket. */
+ sk_setup_caps(sk, &rt->u.dst);
+
+ dp->dccps_gar =
+ dp->dccps_iss = secure_dccp_sequence_number(inet->saddr,
+ inet->daddr,
+ inet->sport,
+ usin->sin_port);
+ dccp_update_gss(sk, dp->dccps_iss);
+
+ /*
+ * SWL and AWL are initially adjusted so that they are not less than
+ * the initial Sequence Numbers received and sent, respectively:
+ * SWL := max(GSR + 1 - floor(W/4), ISR),
+ * AWL := max(GSS - W' + 1, ISS).
+ * These adjustments MUST be applied only at the beginning of the
+ * connection.
+ */
+ dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
+
+ inet->id = dp->dccps_iss ^ jiffies;
+
+ err = dccp_connect(sk);
+ rt = NULL;
+ if (err != 0)
+ goto failure;
+out:
+ return err;
+failure:
+ /*
+ * This unhashes the socket and releases the local port, if necessary.
+ */
+ dccp_set_state(sk, DCCP_CLOSED);
+ ip_rt_put(rt);
+ sk->sk_route_caps = 0;
+ inet->dport = 0;
+ goto out;
+}
+
+/*
+ * This routine does path mtu discovery as defined in RFC1191.
+ */
+static inline void dccp_do_pmtu_discovery(struct sock *sk,
+ const struct iphdr *iph,
+ u32 mtu)
+{
+ struct dst_entry *dst;
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct dccp_sock *dp = dccp_sk(sk);
+
+ /* We are not interested in DCCP_LISTEN and request_socks (RESPONSEs
+ * send out by Linux are always < 576bytes so they should go through
+ * unfragmented).
+ */
+ if (sk->sk_state == DCCP_LISTEN)
+ return;
+
+ /* We don't check in the destentry if pmtu discovery is forbidden
+ * on this route. We just assume that no packet_to_big packets
+ * are send back when pmtu discovery is not active.
+ * There is a small race when the user changes this flag in the
+ * route, but I think that's acceptable.
+ */
+ if ((dst = __sk_dst_check(sk, 0)) == NULL)
+ return;
+
+ dst->ops->update_pmtu(dst, mtu);
+
+ /* Something is about to be wrong... Remember soft error
+ * for the case, if this connection will not able to recover.
+ */
+ if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
+ sk->sk_err_soft = EMSGSIZE;
+
+ mtu = dst_mtu(dst);
+
+ if (inet->pmtudisc != IP_PMTUDISC_DONT &&
+ dp->dccps_pmtu_cookie > mtu) {
+ dccp_sync_mss(sk, mtu);
+
+ /*
+ * From: draft-ietf-dccp-spec-11.txt
+ *
+ * DCCP-Sync packets are the best choice for upward
+ * probing, since DCCP-Sync probes do not risk application
+ * data loss.
+ */
+ dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC);
+ } /* else let the usual retransmit timer handle it */
+}
+
+static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb)
+{
+ int err;
+ struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
+ const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
+ sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_ack_bits);
+ struct sk_buff *skb;
+
+ if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
+ return;
+
+ skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_DCCP_HEADER);
+
+ skb->dst = dst_clone(rxskb->dst);
+
+ skb->h.raw = skb_push(skb, dccp_hdr_ack_len);
+ dh = dccp_hdr(skb);
+ memset(dh, 0, dccp_hdr_ack_len);
+
+ /* Build DCCP header and checksum it. */
+ dh->dccph_type = DCCP_PKT_ACK;
+ dh->dccph_sport = rxdh->dccph_dport;
+ dh->dccph_dport = rxdh->dccph_sport;
+ dh->dccph_doff = dccp_hdr_ack_len / 4;
+ dh->dccph_x = 1;
+
+ dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
+ DCCP_SKB_CB(rxskb)->dccpd_seq);
+
+ bh_lock_sock(dccp_ctl_socket->sk);
+ err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
+ rxskb->nh.iph->daddr,
+ rxskb->nh.iph->saddr, NULL);
+ bh_unlock_sock(dccp_ctl_socket->sk);
+
+ if (err == NET_XMIT_CN || err == 0) {
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+ }
+}
+
+static void dccp_v4_reqsk_send_ack(struct sk_buff *skb,
+ struct request_sock *req)
+{
+ dccp_v4_ctl_send_ack(skb);
+}
+
+static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
+ struct dst_entry *dst)
+{
+ int err = -1;
+ struct sk_buff *skb;
+
+ /* First, grab a route. */
+
+ if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
+ goto out;
+
+ skb = dccp_make_response(sk, dst, req);
+ if (skb != NULL) {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+
+ err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
+ ireq->rmt_addr,
+ ireq->opt);
+ if (err == NET_XMIT_CN)
+ err = 0;
+ }
+
+out:
+ dst_release(dst);
+ return err;
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some sort of error
+ * condition. If err < 0 then the socket should be closed and the error
+ * returned to the user. If err > 0 it's just the icmp type << 8 | icmp code.
+ * After adjustment header points to the first 8 bytes of the tcp header. We
+ * need to find the appropriate port.
+ *
+ * The locking strategy used here is very "optimistic". When someone else
+ * accesses the socket the ICMP is just dropped and for some paths there is no
+ * check at all. A more general error queue to queue errors for later handling
+ * is probably better.
+ */
+void dccp_v4_err(struct sk_buff *skb, u32 info)
+{
+ const struct iphdr *iph = (struct iphdr *)skb->data;
+ const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
+ (iph->ihl << 2));
+ struct dccp_sock *dp;
+ struct inet_sock *inet;
+ const int type = skb->h.icmph->type;
+ const int code = skb->h.icmph->code;
+ struct sock *sk;
+ __u64 seq;
+ int err;
+
+ if (skb->len < (iph->ihl << 2) + 8) {
+ ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+ return;
+ }
+
+ sk = inet_lookup(&dccp_hashinfo, iph->daddr, dh->dccph_dport,
+ iph->saddr, dh->dccph_sport, inet_iif(skb));
+ if (sk == NULL) {
+ ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+ return;
+ }
+
+ if (sk->sk_state == DCCP_TIME_WAIT) {
+ inet_twsk_put((struct inet_timewait_sock *)sk);
+ return;
+ }
+
+ bh_lock_sock(sk);
+ /* If too many ICMPs get dropped on busy
+ * servers this needs to be solved differently.
+ */
+ if (sock_owned_by_user(sk))
+ NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
+
+ if (sk->sk_state == DCCP_CLOSED)
+ goto out;
+
+ dp = dccp_sk(sk);
+ seq = dccp_hdr_seq(skb);
+ if (sk->sk_state != DCCP_LISTEN &&
+ !between48(seq, dp->dccps_swl, dp->dccps_swh)) {
+ NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS);
+ goto out;
+ }
+
+ switch (type) {
+ case ICMP_SOURCE_QUENCH:
+ /* Just silently ignore these. */
+ goto out;
+ case ICMP_PARAMETERPROB:
+ err = EPROTO;
+ break;
+ case ICMP_DEST_UNREACH:
+ if (code > NR_ICMP_UNREACH)
+ goto out;
+
+ if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+ if (!sock_owned_by_user(sk))
+ dccp_do_pmtu_discovery(sk, iph, info);
+ goto out;
+ }
+
+ err = icmp_err_convert[code].errno;
+ break;
+ case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
+ default:
+ goto out;
+ }
+
+ switch (sk->sk_state) {
+ struct request_sock *req , **prev;
+ case DCCP_LISTEN:
+ if (sock_owned_by_user(sk))
+ goto out;
+ req = inet_csk_search_req(sk, &prev, dh->dccph_dport,
+ iph->daddr, iph->saddr);
+ if (!req)
+ goto out;
+
+ /*
+ * ICMPs are not backlogged, hence we cannot get an established
+ * socket here.
+ */
+ BUG_TRAP(!req->sk);
+
+ if (seq != dccp_rsk(req)->dreq_iss) {
+ NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
+ goto out;
+ }
+ /*
+ * Still in RESPOND, just remove it silently.
+ * There is no good way to pass the error to the newly
+ * created socket, and POSIX does not want network
+ * errors returned from accept().
+ */
+ inet_csk_reqsk_queue_drop(sk, req, prev);
+ goto out;
+
+ case DCCP_REQUESTING:
+ case DCCP_RESPOND:
+ if (!sock_owned_by_user(sk)) {
+ DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ sk->sk_err = err;
+
+ sk->sk_error_report(sk);
+
+ dccp_done(sk);
+ } else
+ sk->sk_err_soft = err;
+ goto out;
+ }
+
+ /* If we've already connected we will keep trying
+ * until we time out, or the user gives up.
+ *
+ * rfc1122 4.2.3.9 allows to consider as hard errors
+ * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
+ * but it is obsoleted by pmtu discovery).
+ *
+ * Note, that in modern internet, where routing is unreliable
+ * and in each dark corner broken firewalls sit, sending random
+ * errors ordered by their masters even this two messages finally lose
+ * their original sense (even Linux sends invalid PORT_UNREACHs)
+ *
+ * Now we are in compliance with RFCs.
+ * --ANK (980905)
+ */
+
+ inet = inet_sk(sk);
+ if (!sock_owned_by_user(sk) && inet->recverr) {
+ sk->sk_err = err;
+ sk->sk_error_report(sk);
+ } else /* Only an error on timeout */
+ sk->sk_err_soft = err;
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
+{
+ struct sk_buff *skb;
+ /*
+ * FIXME: what if rebuild_header fails?
+ * Should we be doing a rebuild_header here?
+ */
+ int err = inet_sk_rebuild_header(sk);
+
+ if (err != 0)
+ return err;
+
+ skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
+ if (skb != NULL) {
+ const struct inet_sock *inet = inet_sk(sk);
+
+ err = ip_build_and_send_pkt(skb, sk,
+ inet->saddr, inet->daddr, NULL);
+ if (err == NET_XMIT_CN)
+ err = 0;
+ }
+
+ return err;
+}
+
+static inline u64 dccp_v4_init_sequence(const struct sock *sk,
+ const struct sk_buff *skb)
+{
+ return secure_dccp_sequence_number(skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ dccp_hdr(skb)->dccph_dport,
+ dccp_hdr(skb)->dccph_sport);
+}
+
+int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+{
+ struct inet_request_sock *ireq;
+ struct dccp_sock dp;
+ struct request_sock *req;
+ struct dccp_request_sock *dreq;
+ const __u32 saddr = skb->nh.iph->saddr;
+ const __u32 daddr = skb->nh.iph->daddr;
+ struct dst_entry *dst = NULL;
+
+ /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
+ if (((struct rtable *)skb->dst)->rt_flags &
+ (RTCF_BROADCAST | RTCF_MULTICAST))
+ goto drop;
+
+ /*
+ * TW buckets are converted to open requests without
+ * limitations, they conserve resources and peer is
+ * evidently real one.
+ */
+ if (inet_csk_reqsk_queue_is_full(sk))
+ goto drop;
+
+ /*
+ * Accept backlog is full. If we have already queued enough
+ * of warm entries in syn queue, drop request. It is better than
+ * clogging syn queue with openreqs with exponentially increasing
+ * timeout.
+ */
+ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+ goto drop;
+
+ req = reqsk_alloc(sk->sk_prot->rsk_prot);
+ if (req == NULL)
+ goto drop;
+
+ /* FIXME: process options */
+
+ dccp_openreq_init(req, &dp, skb);
+
+ ireq = inet_rsk(req);
+ ireq->loc_addr = daddr;
+ ireq->rmt_addr = saddr;
+ /* FIXME: Merge Aristeu's option parsing code when ready */
+ req->rcv_wnd = 100; /* Fake, option parsing will get the
+ right value */
+ ireq->opt = NULL;
+
+ /*
+ * Step 3: Process LISTEN state
+ *
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ *
+ * In fact we defer setting S.GSR, S.SWL, S.SWH to
+ * dccp_create_openreq_child.
+ */
+ dreq = dccp_rsk(req);
+ dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq;
+ dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
+ dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service;
+
+ if (dccp_v4_send_response(sk, req, dst))
+ goto drop_and_free;
+
+ inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+ return 0;
+
+drop_and_free:
+ /*
+ * FIXME: should be reqsk_free after implementing req->rsk_ops
+ */
+ __reqsk_free(req);
+drop:
+ DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ return -1;
+}
+
+/*
+ * The three way handshake has completed - we got a valid ACK or DATAACK -
+ * now create the new socket.
+ *
+ * This is the equivalent of TCP's tcp_v4_syn_recv_sock
+ */
+struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst)
+{
+ struct inet_request_sock *ireq;
+ struct inet_sock *newinet;
+ struct dccp_sock *newdp;
+ struct sock *newsk;
+
+ if (sk_acceptq_is_full(sk))
+ goto exit_overflow;
+
+ if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
+ goto exit;
+
+ newsk = dccp_create_openreq_child(sk, req, skb);
+ if (newsk == NULL)
+ goto exit;
+
+ sk_setup_caps(newsk, dst);
+
+ newdp = dccp_sk(newsk);
+ newinet = inet_sk(newsk);
+ ireq = inet_rsk(req);
+ newinet->daddr = ireq->rmt_addr;
+ newinet->rcv_saddr = ireq->loc_addr;
+ newinet->saddr = ireq->loc_addr;
+ newinet->opt = ireq->opt;
+ ireq->opt = NULL;
+ newinet->mc_index = inet_iif(skb);
+ newinet->mc_ttl = skb->nh.iph->ttl;
+ newinet->id = jiffies;
+
+ dccp_sync_mss(newsk, dst_mtu(dst));
+
+ __inet_hash(&dccp_hashinfo, newsk, 0);
+ __inet_inherit_port(&dccp_hashinfo, sk, newsk);
+
+ return newsk;
+
+exit_overflow:
+ NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
+exit:
+ NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
+ dst_release(dst);
+ return NULL;
+}
+
+static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+ const struct iphdr *iph = skb->nh.iph;
+ struct sock *nsk;
+ struct request_sock **prev;
+ /* Find possible connection requests. */
+ struct request_sock *req = inet_csk_search_req(sk, &prev,
+ dh->dccph_sport,
+ iph->saddr, iph->daddr);
+ if (req != NULL)
+ return dccp_check_req(sk, skb, req, prev);
+
+ nsk = __inet_lookup_established(&dccp_hashinfo,
+ iph->saddr, dh->dccph_sport,
+ iph->daddr, ntohs(dh->dccph_dport),
+ inet_iif(skb));
+ if (nsk != NULL) {
+ if (nsk->sk_state != DCCP_TIME_WAIT) {
+ bh_lock_sock(nsk);
+ return nsk;
+ }
+ inet_twsk_put((struct inet_timewait_sock *)nsk);
+ return NULL;
+ }
+
+ return sk;
+}
+
+int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr,
+ const u32 daddr)
+{
+ const struct dccp_hdr* dh = dccp_hdr(skb);
+ int checksum_len;
+ u32 tmp;
+
+ if (dh->dccph_cscov == 0)
+ checksum_len = skb->len;
+ else {
+ checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
+ checksum_len = checksum_len < skb->len ? checksum_len :
+ skb->len;
+ }
+
+ tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
+ return csum_tcpudp_magic(saddr, daddr, checksum_len,
+ IPPROTO_DCCP, tmp);
+}
+
+static int dccp_v4_verify_checksum(struct sk_buff *skb,
+ const u32 saddr, const u32 daddr)
+{
+ struct dccp_hdr *dh = dccp_hdr(skb);
+ int checksum_len;
+ u32 tmp;
+
+ if (dh->dccph_cscov == 0)
+ checksum_len = skb->len;
+ else {
+ checksum_len = (dh->dccph_cscov + dh->dccph_x) * sizeof(u32);
+ checksum_len = checksum_len < skb->len ? checksum_len :
+ skb->len;
+ }
+ tmp = csum_partial((unsigned char *)dh, checksum_len, 0);
+ return csum_tcpudp_magic(saddr, daddr, checksum_len,
+ IPPROTO_DCCP, tmp) == 0 ? 0 : -1;
+}
+
+static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct rtable *rt;
+ struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
+ .nl_u = { .ip4_u =
+ { .daddr = skb->nh.iph->saddr,
+ .saddr = skb->nh.iph->daddr,
+ .tos = RT_CONN_FLAGS(sk) } },
+ .proto = sk->sk_protocol,
+ .uli_u = { .ports =
+ { .sport = dccp_hdr(skb)->dccph_dport,
+ .dport = dccp_hdr(skb)->dccph_sport }
+ }
+ };
+
+ if (ip_route_output_flow(&rt, &fl, sk, 0)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ return NULL;
+ }
+
+ return &rt->u.dst;
+}
+
+static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb)
+{
+ int err;
+ struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
+ const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
+ sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_reset);
+ struct sk_buff *skb;
+ struct dst_entry *dst;
+ u64 seqno;
+
+ /* Never send a reset in response to a reset. */
+ if (rxdh->dccph_type == DCCP_PKT_RESET)
+ return;
+
+ if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
+ return;
+
+ dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb);
+ if (dst == NULL)
+ return;
+
+ skb = alloc_skb(MAX_DCCP_HEADER + 15, GFP_ATOMIC);
+ if (skb == NULL)
+ goto out;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_DCCP_HEADER);
+ skb->dst = dst_clone(dst);
+
+ skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
+ dh = dccp_hdr(skb);
+ memset(dh, 0, dccp_hdr_reset_len);
+
+ /* Build DCCP header and checksum it. */
+ dh->dccph_type = DCCP_PKT_RESET;
+ dh->dccph_sport = rxdh->dccph_dport;
+ dh->dccph_dport = rxdh->dccph_sport;
+ dh->dccph_doff = dccp_hdr_reset_len / 4;
+ dh->dccph_x = 1;
+ dccp_hdr_reset(skb)->dccph_reset_code =
+ DCCP_SKB_CB(rxskb)->dccpd_reset_code;
+
+ /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */
+ seqno = 0;
+ if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
+ dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
+
+ dccp_hdr_set_seq(dh, seqno);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
+ DCCP_SKB_CB(rxskb)->dccpd_seq);
+
+ dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
+ rxskb->nh.iph->daddr);
+
+ bh_lock_sock(dccp_ctl_socket->sk);
+ err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk,
+ rxskb->nh.iph->daddr,
+ rxskb->nh.iph->saddr, NULL);
+ bh_unlock_sock(dccp_ctl_socket->sk);
+
+ if (err == NET_XMIT_CN || err == 0) {
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+ }
+out:
+ dst_release(dst);
+}
+
+int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_hdr *dh = dccp_hdr(skb);
+
+ if (sk->sk_state == DCCP_OPEN) { /* Fast path */
+ if (dccp_rcv_established(sk, skb, dh, skb->len))
+ goto reset;
+ return 0;
+ }
+
+ /*
+ * Step 3: Process LISTEN state
+ * If S.state == LISTEN,
+ * If P.type == Request or P contains a valid Init Cookie
+ * option,
+ * * Must scan the packet's options to check for an Init
+ * Cookie. Only the Init Cookie is processed here,
+ * however; other options are processed in Step 8. This
+ * scan need only be performed if the endpoint uses Init
+ * Cookies *
+ * * Generate a new socket and switch to that socket *
+ * Set S := new socket for this port pair
+ * S.state = RESPOND
+ * Choose S.ISS (initial seqno) or set from Init Cookie
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ * Continue with S.state == RESPOND
+ * * A Response packet will be generated in Step 11 *
+ * Otherwise,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ *
+ * NOTE: the check for the packet types is done in
+ * dccp_rcv_state_process
+ */
+ if (sk->sk_state == DCCP_LISTEN) {
+ struct sock *nsk = dccp_v4_hnd_req(sk, skb);
+
+ if (nsk == NULL)
+ goto discard;
+
+ if (nsk != sk) {
+ if (dccp_child_process(sk, nsk, skb))
+ goto reset;
+ return 0;
+ }
+ }
+
+ if (dccp_rcv_state_process(sk, skb, dh, skb->len))
+ goto reset;
+ return 0;
+
+reset:
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
+ dccp_v4_ctl_send_reset(skb);
+discard:
+ kfree_skb(skb);
+ return 0;
+}
+
+static inline int dccp_invalid_packet(struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh;
+
+ if (skb->pkt_type != PACKET_HOST)
+ return 1;
+
+ if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: pskb_may_pull failed\n");
+ return 1;
+ }
+
+ dh = dccp_hdr(skb);
+
+ /* If the packet type is not understood, drop packet and return */
+ if (dh->dccph_type >= DCCP_PKT_INVALID) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: invalid packet type\n");
+ return 1;
+ }
+
+ /*
+ * If P.Data Offset is too small for packet type, or too large for
+ * packet, drop packet and return
+ */
+ if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) "
+ "too small 1\n",
+ dh->dccph_doff);
+ return 1;
+ }
+
+ if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.Data Offset(%u) "
+ "too small 2\n",
+ dh->dccph_doff);
+ return 1;
+ }
+
+ dh = dccp_hdr(skb);
+
+ /*
+ * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
+ * has short sequence numbers), drop packet and return
+ */
+ if (dh->dccph_x == 0 &&
+ dh->dccph_type != DCCP_PKT_DATA &&
+ dh->dccph_type != DCCP_PKT_ACK &&
+ dh->dccph_type != DCCP_PKT_DATAACK) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: P.type (%s) not Data, Ack "
+ "nor DataAck and P.X == 0\n",
+ dccp_packet_name(dh->dccph_type));
+ return 1;
+ }
+
+ /* If the header checksum is incorrect, drop packet and return */
+ if (dccp_v4_verify_checksum(skb, skb->nh.iph->saddr,
+ skb->nh.iph->daddr) < 0) {
+ LIMIT_NETDEBUG(KERN_WARNING "DCCP: header checksum is "
+ "incorrect\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* this is called when real data arrives */
+int dccp_v4_rcv(struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh;
+ struct sock *sk;
+ int rc;
+
+ /* Step 1: Check header basics: */
+
+ if (dccp_invalid_packet(skb))
+ goto discard_it;
+
+ dh = dccp_hdr(skb);
+#if 0
+ /*
+ * Use something like this to simulate some DATA/DATAACK loss to test
+ * dccp_ackpkts_add, you'll get something like this on a session that
+ * sends 10 DATA/DATAACK packets:
+ *
+ * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1|
+ *
+ * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet
+ * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets
+ * with the same state
+ * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet
+ *
+ * So...
+ *
+ * 281473596467422 was received
+ * 281473596467421 was not received
+ * 281473596467420 was received
+ * 281473596467419 was not received
+ * 281473596467418 was received
+ * 281473596467417 was not received
+ * 281473596467416 was received
+ * 281473596467415 was not received
+ * 281473596467414 was received
+ * 281473596467413 was received (this one was the 3way handshake
+ * RESPONSE)
+ *
+ */
+ if (dh->dccph_type == DCCP_PKT_DATA ||
+ dh->dccph_type == DCCP_PKT_DATAACK) {
+ static int discard = 0;
+
+ if (discard) {
+ discard = 0;
+ goto discard_it;
+ }
+ discard = 1;
+ }
+#endif
+ DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
+ DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
+
+ dccp_pr_debug("%8.8s "
+ "src=%u.%u.%u.%u@%-5d "
+ "dst=%u.%u.%u.%u@%-5d seq=%llu",
+ dccp_packet_name(dh->dccph_type),
+ NIPQUAD(skb->nh.iph->saddr), ntohs(dh->dccph_sport),
+ NIPQUAD(skb->nh.iph->daddr), ntohs(dh->dccph_dport),
+ (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
+
+ if (dccp_packet_without_ack(skb)) {
+ DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
+ dccp_pr_debug_cat("\n");
+ } else {
+ DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
+ dccp_pr_debug_cat(", ack=%llu\n",
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ }
+
+ /* Step 2:
+ * Look up flow ID in table and get corresponding socket */
+ sk = __inet_lookup(&dccp_hashinfo,
+ skb->nh.iph->saddr, dh->dccph_sport,
+ skb->nh.iph->daddr, ntohs(dh->dccph_dport),
+ inet_iif(skb));
+
+ /*
+ * Step 2:
+ * If no socket ...
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ */
+ if (sk == NULL) {
+ dccp_pr_debug("failed to look up flow ID in table and "
+ "get corresponding socket\n");
+ goto no_dccp_socket;
+ }
+
+ /*
+ * Step 2:
+ * ... or S.state == TIMEWAIT,
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ */
+
+ if (sk->sk_state == DCCP_TIME_WAIT) {
+ dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: "
+ "do_time_wait\n");
+ goto do_time_wait;
+ }
+
+ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
+ dccp_pr_debug("xfrm4_policy_check failed\n");
+ goto discard_and_relse;
+ }
+
+ if (sk_filter(sk, skb, 0)) {
+ dccp_pr_debug("sk_filter failed\n");
+ goto discard_and_relse;
+ }
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ rc = 0;
+ if (!sock_owned_by_user(sk))
+ rc = dccp_v4_do_rcv(sk, skb);
+ else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+
+ sock_put(sk);
+ return rc;
+
+no_dccp_socket:
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+ goto discard_it;
+ /*
+ * Step 2:
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ */
+ if (dh->dccph_type != DCCP_PKT_RESET) {
+ DCCP_SKB_CB(skb)->dccpd_reset_code =
+ DCCP_RESET_CODE_NO_CONNECTION;
+ dccp_v4_ctl_send_reset(skb);
+ }
+
+discard_it:
+ /* Discard frame. */
+ kfree_skb(skb);
+ return 0;
+
+discard_and_relse:
+ sock_put(sk);
+ goto discard_it;
+
+do_time_wait:
+ inet_twsk_put((struct inet_timewait_sock *)sk);
+ goto no_dccp_socket;
+}
+
+static int dccp_v4_init_sock(struct sock *sk)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ static int dccp_ctl_socket_init = 1;
+
+ dccp_options_init(&dp->dccps_options);
+ do_gettimeofday(&dp->dccps_epoch);
+
+ if (dp->dccps_options.dccpo_send_ack_vector) {
+ dp->dccps_hc_rx_ackpkts =
+ dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
+ GFP_KERNEL);
+
+ if (dp->dccps_hc_rx_ackpkts == NULL)
+ return -ENOMEM;
+ }
+
+ /*
+ * FIXME: We're hardcoding the CCID, and doing this at this point makes
+ * the listening (master) sock get CCID control blocks, which is not
+ * necessary, but for now, to not mess with the test userspace apps,
+ * lets leave it here, later the real solution is to do this in a
+ * setsockopt(CCIDs-I-want/accept). -acme
+ */
+ if (likely(!dccp_ctl_socket_init)) {
+ dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+ sk);
+ dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+ sk);
+ if (dp->dccps_hc_rx_ccid == NULL ||
+ dp->dccps_hc_tx_ccid == NULL) {
+ ccid_exit(dp->dccps_hc_rx_ccid, sk);
+ ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
+ dp->dccps_hc_rx_ackpkts = NULL;
+ dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
+ return -ENOMEM;
+ }
+ } else
+ dccp_ctl_socket_init = 0;
+
+ dccp_init_xmit_timers(sk);
+ inet_csk(sk)->icsk_rto = DCCP_TIMEOUT_INIT;
+ sk->sk_state = DCCP_CLOSED;
+ sk->sk_write_space = dccp_write_space;
+ dp->dccps_mss_cache = 536;
+ dp->dccps_role = DCCP_ROLE_UNDEFINED;
+
+ return 0;
+}
+
+static int dccp_v4_destroy_sock(struct sock *sk)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ /*
+ * DCCP doesn't use sk_qrite_queue, just sk_send_head
+ * for retransmissions
+ */
+ if (sk->sk_send_head != NULL) {
+ kfree_skb(sk->sk_send_head);
+ sk->sk_send_head = NULL;
+ }
+
+ /* Clean up a referenced DCCP bind bucket. */
+ if (inet_csk(sk)->icsk_bind_hash != NULL)
+ inet_put_port(&dccp_hashinfo, sk);
+
+ ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
+ dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
+ dp->dccps_hc_rx_ackpkts = NULL;
+ ccid_exit(dp->dccps_hc_rx_ccid, sk);
+ ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
+
+ return 0;
+}
+
+static void dccp_v4_reqsk_destructor(struct request_sock *req)
+{
+ kfree(inet_rsk(req)->opt);
+}
+
+static struct request_sock_ops dccp_request_sock_ops = {
+ .family = PF_INET,
+ .obj_size = sizeof(struct dccp_request_sock),
+ .rtx_syn_ack = dccp_v4_send_response,
+ .send_ack = dccp_v4_reqsk_send_ack,
+ .destructor = dccp_v4_reqsk_destructor,
+ .send_reset = dccp_v4_ctl_send_reset,
+};
+
+struct proto dccp_v4_prot = {
+ .name = "DCCP",
+ .owner = THIS_MODULE,
+ .close = dccp_close,
+ .connect = dccp_v4_connect,
+ .disconnect = dccp_disconnect,
+ .ioctl = dccp_ioctl,
+ .init = dccp_v4_init_sock,
+ .setsockopt = dccp_setsockopt,
+ .getsockopt = dccp_getsockopt,
+ .sendmsg = dccp_sendmsg,
+ .recvmsg = dccp_recvmsg,
+ .backlog_rcv = dccp_v4_do_rcv,
+ .hash = dccp_v4_hash,
+ .unhash = dccp_v4_unhash,
+ .accept = inet_csk_accept,
+ .get_port = dccp_v4_get_port,
+ .shutdown = dccp_shutdown,
+ .destroy = dccp_v4_destroy_sock,
+ .orphan_count = &dccp_orphan_count,
+ .max_header = MAX_DCCP_HEADER,
+ .obj_size = sizeof(struct dccp_sock),
+ .rsk_prot = &dccp_request_sock_ops,
+ .twsk_obj_size = sizeof(struct inet_timewait_sock),
+};
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
new file mode 100644
index 000000000000..18461bc04cbe
--- /dev/null
+++ b/net/dccp/minisocks.c
@@ -0,0 +1,265 @@
+/*
+ * net/dccp/minisocks.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+
+#include <net/sock.h>
+#include <net/xfrm.h>
+#include <net/inet_timewait_sock.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+struct inet_timewait_death_row dccp_death_row = {
+ .sysctl_max_tw_buckets = NR_FILE * 2,
+ .period = DCCP_TIMEWAIT_LEN / INET_TWDR_TWKILL_SLOTS,
+ .death_lock = SPIN_LOCK_UNLOCKED,
+ .hashinfo = &dccp_hashinfo,
+ .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0,
+ (unsigned long)&dccp_death_row),
+ .twkill_work = __WORK_INITIALIZER(dccp_death_row.twkill_work,
+ inet_twdr_twkill_work,
+ &dccp_death_row),
+/* Short-time timewait calendar */
+
+ .twcal_hand = -1,
+ .twcal_timer = TIMER_INITIALIZER(inet_twdr_twcal_tick, 0,
+ (unsigned long)&dccp_death_row),
+};
+
+void dccp_time_wait(struct sock *sk, int state, int timeo)
+{
+ struct inet_timewait_sock *tw = NULL;
+
+ if (dccp_death_row.tw_count < dccp_death_row.sysctl_max_tw_buckets)
+ tw = inet_twsk_alloc(sk, state);
+
+ if (tw != NULL) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
+
+ /* Linkage updates. */
+ __inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
+
+ /* Get the TIME_WAIT timeout firing. */
+ if (timeo < rto)
+ timeo = rto;
+
+ tw->tw_timeout = DCCP_TIMEWAIT_LEN;
+ if (state == DCCP_TIME_WAIT)
+ timeo = DCCP_TIMEWAIT_LEN;
+
+ inet_twsk_schedule(tw, &dccp_death_row, timeo,
+ DCCP_TIMEWAIT_LEN);
+ inet_twsk_put(tw);
+ } else {
+ /* Sorry, if we're out of memory, just CLOSE this
+ * socket up. We've got bigger problems than
+ * non-graceful socket closings.
+ */
+ LIMIT_NETDEBUG(KERN_INFO "DCCP: time wait bucket "
+ "table overflow\n");
+ }
+
+ dccp_done(sk);
+}
+
+struct sock *dccp_create_openreq_child(struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb)
+{
+ /*
+ * Step 3: Process LISTEN state
+ *
+ * // Generate a new socket and switch to that socket
+ * Set S := new socket for this port pair
+ */
+ struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);
+
+ if (newsk != NULL) {
+ const struct dccp_request_sock *dreq = dccp_rsk(req);
+ struct inet_connection_sock *newicsk = inet_csk(sk);
+ struct dccp_sock *newdp = dccp_sk(newsk);
+
+ newdp->dccps_hc_rx_ackpkts = NULL;
+ newdp->dccps_role = DCCP_ROLE_SERVER;
+ newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
+ do_gettimeofday(&newdp->dccps_epoch);
+
+ if (newdp->dccps_options.dccpo_send_ack_vector) {
+ newdp->dccps_hc_rx_ackpkts =
+ dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
+ GFP_ATOMIC);
+ /*
+ * XXX: We're using the same CCIDs set on the parent,
+ * i.e. sk_clone copied the master sock and left the
+ * CCID pointers for this child, that is why we do the
+ * __ccid_get calls.
+ */
+ if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL))
+ goto out_free;
+ }
+
+ if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid,
+ newsk) != 0 ||
+ ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
+ newsk) != 0)) {
+ dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts);
+ ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
+ ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
+out_free:
+ /* It is still raw copy of parent, so invalidate
+ * destructor and make plain sk_free() */
+ newsk->sk_destruct = NULL;
+ sk_free(newsk);
+ return NULL;
+ }
+
+ __ccid_get(newdp->dccps_hc_rx_ccid);
+ __ccid_get(newdp->dccps_hc_tx_ccid);
+
+ /*
+ * Step 3: Process LISTEN state
+ *
+ * Choose S.ISS (initial seqno) or set from Init Cookie
+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init
+ * Cookie
+ */
+
+ /* See dccp_v4_conn_request */
+ newdp->dccps_options.dccpo_sequence_window = req->rcv_wnd;
+
+ newdp->dccps_gar = newdp->dccps_isr = dreq->dreq_isr;
+ dccp_update_gsr(newsk, dreq->dreq_isr);
+
+ newdp->dccps_iss = dreq->dreq_iss;
+ dccp_update_gss(newsk, dreq->dreq_iss);
+
+ /*
+ * SWL and AWL are initially adjusted so that they are not less than
+ * the initial Sequence Numbers received and sent, respectively:
+ * SWL := max(GSR + 1 - floor(W/4), ISR),
+ * AWL := max(GSS - W' + 1, ISS).
+ * These adjustments MUST be applied only at the beginning of the
+ * connection.
+ */
+ dccp_set_seqno(&newdp->dccps_swl,
+ max48(newdp->dccps_swl, newdp->dccps_isr));
+ dccp_set_seqno(&newdp->dccps_awl,
+ max48(newdp->dccps_awl, newdp->dccps_iss));
+
+ dccp_init_xmit_timers(newsk);
+
+ DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS);
+ }
+ return newsk;
+}
+
+/*
+ * Process an incoming packet for RESPOND sockets represented
+ * as an request_sock.
+ */
+struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct request_sock **prev)
+{
+ struct sock *child = NULL;
+
+ /* Check for retransmitted REQUEST */
+ if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
+ if (after48(DCCP_SKB_CB(skb)->dccpd_seq,
+ dccp_rsk(req)->dreq_isr)) {
+ struct dccp_request_sock *dreq = dccp_rsk(req);
+
+ dccp_pr_debug("Retransmitted REQUEST\n");
+ /* Send another RESPONSE packet */
+ dccp_set_seqno(&dreq->dreq_iss, dreq->dreq_iss + 1);
+ dccp_set_seqno(&dreq->dreq_isr,
+ DCCP_SKB_CB(skb)->dccpd_seq);
+ req->rsk_ops->rtx_syn_ack(sk, req, NULL);
+ }
+ /* Network Duplicate, discard packet */
+ return NULL;
+ }
+
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
+
+ if (dccp_hdr(skb)->dccph_type != DCCP_PKT_ACK &&
+ dccp_hdr(skb)->dccph_type != DCCP_PKT_DATAACK)
+ goto drop;
+
+ /* Invalid ACK */
+ if (DCCP_SKB_CB(skb)->dccpd_ack_seq != dccp_rsk(req)->dreq_iss) {
+ dccp_pr_debug("Invalid ACK number: ack_seq=%llu, "
+ "dreq_iss=%llu\n",
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ (unsigned long long)
+ dccp_rsk(req)->dreq_iss);
+ goto drop;
+ }
+
+ child = dccp_v4_request_recv_sock(sk, skb, req, NULL);
+ if (child == NULL)
+ goto listen_overflow;
+
+ /* FIXME: deal with options */
+
+ inet_csk_reqsk_queue_unlink(sk, req, prev);
+ inet_csk_reqsk_queue_removed(sk, req);
+ inet_csk_reqsk_queue_add(sk, req, child);
+out:
+ return child;
+listen_overflow:
+ dccp_pr_debug("listen_overflow!\n");
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
+drop:
+ if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
+ req->rsk_ops->send_reset(skb);
+
+ inet_csk_reqsk_queue_drop(sk, req, prev);
+ goto out;
+}
+
+/*
+ * Queue segment on the new socket if the new socket is active,
+ * otherwise we just shortcircuit this and continue with
+ * the new socket.
+ */
+int dccp_child_process(struct sock *parent, struct sock *child,
+ struct sk_buff *skb)
+{
+ int ret = 0;
+ const int state = child->sk_state;
+
+ if (!sock_owned_by_user(child)) {
+ ret = dccp_rcv_state_process(child, skb, dccp_hdr(skb),
+ skb->len);
+
+ /* Wakeup parent, send SIGIO */
+ if (state == DCCP_RESPOND && child->sk_state != state)
+ parent->sk_data_ready(parent, 0);
+ } else {
+ /* Alas, it is possible again, because we do lookup
+ * in main socket hash table and lock on listening
+ * socket does not protect us more.
+ */
+ sk_add_backlog(child, skb);
+ }
+
+ bh_unlock_sock(child);
+ sock_put(child);
+ return ret;
+}
diff --git a/net/dccp/options.c b/net/dccp/options.c
new file mode 100644
index 000000000000..d4c4242d8dd7
--- /dev/null
+++ b/net/dccp/options.c
@@ -0,0 +1,887 @@
+/*
+ * net/dccp/options.c
+ *
+ * An implementation of the DCCP protocol
+ * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/dccp.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
+ struct sock *sk,
+ const u64 ackno,
+ const unsigned char len,
+ const unsigned char *vector);
+
+/* stores the default values for new connection. may be changed with sysctl */
+static const struct dccp_options dccpo_default_values = {
+ .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW,
+ .dccpo_ccid = DCCPF_INITIAL_CCID,
+ .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR,
+ .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT,
+};
+
+void dccp_options_init(struct dccp_options *dccpo)
+{
+ memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo));
+}
+
+static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
+{
+ u32 value = 0;
+
+ if (len > 3)
+ value += *bf++ << 24;
+ if (len > 2)
+ value += *bf++ << 16;
+ if (len > 1)
+ value += *bf++ << 8;
+ if (len > 0)
+ value += *bf;
+
+ return value;
+}
+
+int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+#ifdef CONFIG_IP_DCCP_DEBUG
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT rx opt: " : "server rx opt: ";
+#endif
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+ const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
+ unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
+ unsigned char *opt_ptr = options;
+ const unsigned char *opt_end = (unsigned char *)dh +
+ (dh->dccph_doff * 4);
+ struct dccp_options_received *opt_recv = &dp->dccps_options_received;
+ unsigned char opt, len;
+ unsigned char *value;
+ u32 elapsed_time;
+
+ memset(opt_recv, 0, sizeof(*opt_recv));
+
+ while (opt_ptr != opt_end) {
+ opt = *opt_ptr++;
+ len = 0;
+ value = NULL;
+
+ /* Check if this isn't a single byte option */
+ if (opt > DCCPO_MAX_RESERVED) {
+ if (opt_ptr == opt_end)
+ goto out_invalid_option;
+
+ len = *opt_ptr++;
+ if (len < 3)
+ goto out_invalid_option;
+ /*
+ * Remove the type and len fields, leaving
+ * just the value size
+ */
+ len -= 2;
+ value = opt_ptr;
+ opt_ptr += len;
+
+ if (opt_ptr > opt_end)
+ goto out_invalid_option;
+ }
+
+ switch (opt) {
+ case DCCPO_PADDING:
+ break;
+ case DCCPO_NDP_COUNT:
+ if (len > 3)
+ goto out_invalid_option;
+
+ opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
+ dccp_pr_debug("%sNDP count=%d\n", debug_prefix,
+ opt_recv->dccpor_ndp);
+ break;
+ case DCCPO_ACK_VECTOR_0:
+ if (len > DCCP_MAX_ACK_VECTOR_LEN)
+ goto out_invalid_option;
+
+ if (pkt_type == DCCP_PKT_DATA)
+ continue;
+
+ opt_recv->dccpor_ack_vector_len = len;
+ opt_recv->dccpor_ack_vector_idx = value - options;
+
+ dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n",
+ debug_prefix, len,
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ value, len);
+ dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts,
+ sk,
+ DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ len, value);
+ break;
+ case DCCPO_TIMESTAMP:
+ if (len != 4)
+ goto out_invalid_option;
+
+ opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
+
+ dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
+ dccp_timestamp(sk, &dp->dccps_timestamp_time);
+
+ dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
+ debug_prefix, opt_recv->dccpor_timestamp,
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ break;
+ case DCCPO_TIMESTAMP_ECHO:
+ if (len != 4 && len != 6 && len != 8)
+ goto out_invalid_option;
+
+ opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value);
+
+ dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
+ debug_prefix,
+ opt_recv->dccpor_timestamp_echo,
+ len + 2,
+ (unsigned long long)
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
+
+
+ if (len == 4)
+ break;
+
+ if (len == 6)
+ elapsed_time = ntohs(*(u16 *)(value + 4));
+ else
+ elapsed_time = ntohl(*(u32 *)(value + 4));
+
+ /* Give precedence to the biggest ELAPSED_TIME */
+ if (elapsed_time > opt_recv->dccpor_elapsed_time)
+ opt_recv->dccpor_elapsed_time = elapsed_time;
+ break;
+ case DCCPO_ELAPSED_TIME:
+ if (len != 2 && len != 4)
+ goto out_invalid_option;
+
+ if (pkt_type == DCCP_PKT_DATA)
+ continue;
+
+ if (len == 2)
+ elapsed_time = ntohs(*(u16 *)value);
+ else
+ elapsed_time = ntohl(*(u32 *)value);
+
+ if (elapsed_time > opt_recv->dccpor_elapsed_time)
+ opt_recv->dccpor_elapsed_time = elapsed_time;
+
+ dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
+ elapsed_time);
+ break;
+ /*
+ * From draft-ietf-dccp-spec-11.txt:
+ *
+ * Option numbers 128 through 191 are for
+ * options sent from the HC-Sender to the
+ * HC-Receiver; option numbers 192 through 255
+ * are for options sent from the HC-Receiver to
+ * the HC-Sender.
+ */
+ case 128 ... 191: {
+ const u16 idx = value - options;
+
+ if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
+ opt, len, idx,
+ value) != 0)
+ goto out_invalid_option;
+ }
+ break;
+ case 192 ... 255: {
+ const u16 idx = value - options;
+
+ if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
+ opt, len, idx,
+ value) != 0)
+ goto out_invalid_option;
+ }
+ break;
+ default:
+ pr_info("DCCP(%p): option %d(len=%d) not "
+ "implemented, ignoring\n",
+ sk, opt, len);
+ break;
+ }
+ }
+
+ return 0;
+
+out_invalid_option:
+ DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
+ pr_info("DCCP(%p): invalid option %d, len=%d\n", sk, opt, len);
+ return -1;
+}
+
+static void dccp_encode_value_var(const u32 value, unsigned char *to,
+ const unsigned int len)
+{
+ if (len > 3)
+ *to++ = (value & 0xFF000000) >> 24;
+ if (len > 2)
+ *to++ = (value & 0xFF0000) >> 16;
+ if (len > 1)
+ *to++ = (value & 0xFF00) >> 8;
+ if (len > 0)
+ *to++ = (value & 0xFF);
+}
+
+static inline int dccp_ndp_len(const int ndp)
+{
+ return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
+}
+
+void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
+ const unsigned char option,
+ const void *value, const unsigned char len)
+{
+ unsigned char *to;
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) {
+ LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
+ "%d option!\n", option);
+ return;
+ }
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
+
+ to = skb_push(skb, len + 2);
+ *to++ = option;
+ *to++ = len + 2;
+
+ memcpy(to, value, len);
+}
+
+EXPORT_SYMBOL_GPL(dccp_insert_option);
+
+static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ int ndp = dp->dccps_ndp_count;
+
+ if (dccp_non_data_packet(skb))
+ ++dp->dccps_ndp_count;
+ else
+ dp->dccps_ndp_count = 0;
+
+ if (ndp > 0) {
+ unsigned char *ptr;
+ const int ndp_len = dccp_ndp_len(ndp);
+ const int len = ndp_len + 2;
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
+ return;
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+ ptr = skb_push(skb, len);
+ *ptr++ = DCCPO_NDP_COUNT;
+ *ptr++ = len;
+ dccp_encode_value_var(ndp, ptr, ndp_len);
+ }
+}
+
+static inline int dccp_elapsed_time_len(const u32 elapsed_time)
+{
+ return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
+}
+
+void dccp_insert_option_elapsed_time(struct sock *sk,
+ struct sk_buff *skb,
+ u32 elapsed_time)
+{
+#ifdef CONFIG_IP_DCCP_DEBUG
+ struct dccp_sock *dp = dccp_sk(sk);
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT TX opt: " : "server TX opt: ";
+#endif
+ const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
+ const int len = 2 + elapsed_time_len;
+ unsigned char *to;
+
+ if (elapsed_time_len == 0)
+ return;
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
+ LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
+ "insert elapsed time!\n");
+ return;
+ }
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+ to = skb_push(skb, len);
+ *to++ = DCCPO_ELAPSED_TIME;
+ *to++ = len;
+
+ if (elapsed_time_len == 2) {
+ const u16 var16 = htons((u16)elapsed_time);
+ memcpy(to, &var16, 2);
+ } else {
+ const u32 var32 = htonl(elapsed_time);
+ memcpy(to, &var32, 4);
+ }
+
+ dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n",
+ debug_prefix, elapsed_time,
+ len,
+ (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
+}
+
+EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
+
+static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+#ifdef CONFIG_IP_DCCP_DEBUG
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT TX opt: " : "server TX opt: ";
+#endif
+ struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
+ int len = ap->dccpap_buf_vector_len + 2;
+ struct timeval now;
+ u32 elapsed_time;
+ unsigned char *to, *from;
+
+ dccp_timestamp(sk, &now);
+ elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
+
+ if (elapsed_time != 0)
+ dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
+ LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
+ "insert ACK Vector!\n");
+ return;
+ }
+
+ /*
+ * XXX: now we have just one ack vector sent record, so
+ * we have to wait for it to be cleared.
+ *
+ * Of course this is not acceptable, but this is just for
+ * basic testing now.
+ */
+ if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1)
+ return;
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+ to = skb_push(skb, len);
+ *to++ = DCCPO_ACK_VECTOR_0;
+ *to++ = len;
+
+ len = ap->dccpap_buf_vector_len;
+ from = ap->dccpap_buf + ap->dccpap_buf_head;
+
+ /* Check if buf_head wraps */
+ if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) {
+ const unsigned int tailsize = (ap->dccpap_buf_len -
+ ap->dccpap_buf_head);
+
+ memcpy(to, from, tailsize);
+ to += tailsize;
+ len -= tailsize;
+ from = ap->dccpap_buf;
+ }
+
+ memcpy(to, from, len);
+ /*
+ * From draft-ietf-dccp-spec-11.txt:
+ *
+ * For each acknowledgement it sends, the HC-Receiver will add an
+ * acknowledgement record. ack_seqno will equal the HC-Receiver
+ * sequence number it used for the ack packet; ack_ptr will equal
+ * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
+ * equal buf_nonce.
+ *
+ * This implemention uses just one ack record for now.
+ */
+ ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+ ap->dccpap_ack_ptr = ap->dccpap_buf_head;
+ ap->dccpap_ack_ackno = ap->dccpap_buf_ackno;
+ ap->dccpap_ack_nonce = ap->dccpap_buf_nonce;
+ ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len;
+
+ dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
+ "ack_ackno=%llu\n",
+ debug_prefix, ap->dccpap_ack_vector_len,
+ (unsigned long long) ap->dccpap_ack_seqno,
+ (unsigned long long) ap->dccpap_ack_ackno);
+}
+
+void dccp_timestamp(const struct sock *sk, struct timeval *tv)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+
+ do_gettimeofday(tv);
+ tv->tv_sec -= dp->dccps_epoch.tv_sec;
+ tv->tv_usec -= dp->dccps_epoch.tv_usec;
+
+ while (tv->tv_usec < 0) {
+ tv->tv_sec--;
+ tv->tv_usec += USEC_PER_SEC;
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_timestamp);
+
+void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
+{
+ struct timeval tv;
+ u32 now;
+
+ dccp_timestamp(sk, &tv);
+ now = timeval_usecs(&tv) / 10;
+ /* yes this will overflow but that is the point as we want a
+ * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
+
+ now = htonl(now);
+ dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
+}
+
+EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
+
+static void dccp_insert_option_timestamp_echo(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+#ifdef CONFIG_IP_DCCP_DEBUG
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT TX opt: " : "server TX opt: ";
+#endif
+ struct timeval now;
+ u32 tstamp_echo;
+ u32 elapsed_time;
+ int len, elapsed_time_len;
+ unsigned char *to;
+
+ dccp_timestamp(sk, &now);
+ elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10;
+ elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
+ len = 6 + elapsed_time_len;
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
+ LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
+ "timestamp echo!\n");
+ return;
+ }
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+ to = skb_push(skb, len);
+ *to++ = DCCPO_TIMESTAMP_ECHO;
+ *to++ = len;
+
+ tstamp_echo = htonl(dp->dccps_timestamp_echo);
+ memcpy(to, &tstamp_echo, 4);
+ to += 4;
+
+ if (elapsed_time_len == 2) {
+ const u16 var16 = htons((u16)elapsed_time);
+ memcpy(to, &var16, 2);
+ } else if (elapsed_time_len == 4) {
+ const u32 var32 = htonl(elapsed_time);
+ memcpy(to, &var32, 4);
+ }
+
+ dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
+ debug_prefix, dp->dccps_timestamp_echo,
+ len,
+ (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
+
+ dp->dccps_timestamp_echo = 0;
+ dp->dccps_timestamp_time.tv_sec = 0;
+ dp->dccps_timestamp_time.tv_usec = 0;
+}
+
+void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
+
+ if (dp->dccps_options.dccpo_send_ndp_count)
+ dccp_insert_option_ndp(sk, skb);
+
+ if (!dccp_packet_without_ack(skb)) {
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
+ DCCP_MAX_SEQNO + 1))
+ dccp_insert_option_ack_vector(sk, skb);
+ if (dp->dccps_timestamp_echo != 0)
+ dccp_insert_option_timestamp_echo(sk, skb);
+ }
+
+ if (dp->dccps_hc_rx_insert_options) {
+ ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
+ dp->dccps_hc_rx_insert_options = 0;
+ }
+ if (dp->dccps_hc_tx_insert_options) {
+ ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+ dp->dccps_hc_tx_insert_options = 0;
+ }
+
+ /* XXX: insert other options when appropriate */
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
+ /* The length of all options has to be a multiple of 4 */
+ int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
+
+ if (padding != 0) {
+ padding = 4 - padding;
+ memset(skb_push(skb, padding), 0, padding);
+ DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
+ }
+ }
+}
+
+struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len,
+ const unsigned int __nocast priority)
+{
+ struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority);
+
+ if (ap != NULL) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ memset(ap->dccpap_buf, 0xFF, len);
+#endif
+ ap->dccpap_buf_len = len;
+ ap->dccpap_buf_head =
+ ap->dccpap_buf_tail =
+ ap->dccpap_buf_len - 1;
+ ap->dccpap_buf_ackno =
+ ap->dccpap_ack_ackno =
+ ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
+ ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0;
+ ap->dccpap_ack_ptr = 0;
+ ap->dccpap_time.tv_sec = 0;
+ ap->dccpap_time.tv_usec = 0;
+ ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0;
+ }
+
+ return ap;
+}
+
+void dccp_ackpkts_free(struct dccp_ackpkts *ap)
+{
+ if (ap != NULL) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len);
+#endif
+ kfree(ap);
+ }
+}
+
+static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap,
+ const unsigned int index)
+{
+ return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK;
+}
+
+static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap,
+ const unsigned int index)
+{
+ return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK;
+}
+
+/*
+ * If several packets are missing, the HC-Receiver may prefer to enter multiple
+ * bytes with run length 0, rather than a single byte with a larger run length;
+ * this simplifies table updates if one of the missing packets arrives.
+ */
+static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
+ const unsigned int packets,
+ const unsigned char state)
+{
+ unsigned int gap;
+ signed long new_head;
+
+ if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len)
+ return -ENOBUFS;
+
+ gap = packets - 1;
+ new_head = ap->dccpap_buf_head - packets;
+
+ if (new_head < 0) {
+ if (gap > 0) {
+ memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED,
+ gap + new_head + 1);
+ gap = -new_head;
+ }
+ new_head += ap->dccpap_buf_len;
+ }
+
+ ap->dccpap_buf_head = new_head;
+
+ if (gap > 0)
+ memset(ap->dccpap_buf + ap->dccpap_buf_head + 1,
+ DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap);
+
+ ap->dccpap_buf[ap->dccpap_buf_head] = state;
+ ap->dccpap_buf_vector_len += packets;
+ return 0;
+}
+
+/*
+ * Implements the draft-ietf-dccp-spec-11.txt Appendix A
+ */
+int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+ u64 ackno, u8 state)
+{
+ /*
+ * Check at the right places if the buffer is full, if it is, tell the
+ * caller to start dropping packets till the HC-Sender acks our ACK
+ * vectors, when we will free up space in dccpap_buf.
+ *
+ * We may well decide to do buffer compression, etc, but for now lets
+ * just drop.
+ *
+ * From Appendix A:
+ *
+ * Of course, the circular buffer may overflow, either when the
+ * HC-Sender is sending data at a very high rate, when the
+ * HC-Receiver's acknowledgements are not reaching the HC-Sender,
+ * or when the HC-Sender is forgetting to acknowledge those acks
+ * (so the HC-Receiver is unable to clean up old state). In this
+ * case, the HC-Receiver should either compress the buffer (by
+ * increasing run lengths when possible), transfer its state to
+ * a larger buffer, or, as a last resort, drop all received
+ * packets, without processing them whatsoever, until its buffer
+ * shrinks again.
+ */
+
+ /* See if this is the first ackno being inserted */
+ if (ap->dccpap_buf_vector_len == 0) {
+ ap->dccpap_buf[ap->dccpap_buf_head] = state;
+ ap->dccpap_buf_vector_len = 1;
+ } else if (after48(ackno, ap->dccpap_buf_ackno)) {
+ const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno,
+ ackno);
+
+ /*
+ * Look if the state of this packet is the same as the
+ * previous ackno and if so if we can bump the head len.
+ */
+ if (delta == 1 &&
+ dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state &&
+ (dccp_ackpkts_len(ap, ap->dccpap_buf_head) <
+ DCCP_ACKPKTS_LEN_MASK))
+ ap->dccpap_buf[ap->dccpap_buf_head]++;
+ else if (dccp_ackpkts_set_buf_head_state(ap, delta, state))
+ return -ENOBUFS;
+ } else {
+ /*
+ * A.1.2. Old Packets
+ *
+ * When a packet with Sequence Number S arrives, and
+ * S <= buf_ackno, the HC-Receiver will scan the table
+ * for the byte corresponding to S. (Indexing structures
+ * could reduce the complexity of this scan.)
+ */
+ u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno);
+ unsigned int index = ap->dccpap_buf_head;
+
+ while (1) {
+ const u8 len = dccp_ackpkts_len(ap, index);
+ const u8 state = dccp_ackpkts_state(ap, index);
+ /*
+ * valid packets not yet in dccpap_buf have a reserved
+ * entry, with a len equal to 0.
+ */
+ if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED &&
+ len == 0 && delta == 0) { /* Found our
+ reserved seat! */
+ dccp_pr_debug("Found %llu reserved seat!\n",
+ (unsigned long long) ackno);
+ ap->dccpap_buf[index] = state;
+ goto out;
+ }
+ /* len == 0 means one packet */
+ if (delta < len + 1)
+ goto out_duplicate;
+
+ delta -= len + 1;
+ if (++index == ap->dccpap_buf_len)
+ index = 0;
+ }
+ }
+
+ ap->dccpap_buf_ackno = ackno;
+ dccp_timestamp(sk, &ap->dccpap_time);
+out:
+ dccp_pr_debug("");
+ dccp_ackpkts_print(ap);
+ return 0;
+
+out_duplicate:
+ /* Duplicate packet */
+ dccp_pr_debug("Received a dup or already considered lost "
+ "packet: %llu\n", (unsigned long long) ackno);
+ return -EILSEQ;
+}
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+void dccp_ackvector_print(const u64 ackno, const unsigned char *vector,
+ int len)
+{
+ if (!dccp_debug)
+ return;
+
+ printk("ACK vector len=%d, ackno=%llu |", len,
+ (unsigned long long) ackno);
+
+ while (len--) {
+ const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6;
+ const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
+
+ printk("%d,%d|", state, rl);
+ ++vector;
+ }
+
+ printk("\n");
+}
+
+void dccp_ackpkts_print(const struct dccp_ackpkts *ap)
+{
+ dccp_ackvector_print(ap->dccpap_buf_ackno,
+ ap->dccpap_buf + ap->dccpap_buf_head,
+ ap->dccpap_buf_vector_len);
+}
+#endif
+
+static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap)
+{
+ /*
+ * As we're keeping track of the ack vector size
+ * (dccpap_buf_vector_len) and the sent ack vector size
+ * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but
+ * keep this code here as in the future we'll implement a vector of
+ * ack records, as suggested in draft-ietf-dccp-spec-11.txt
+ * Appendix A. -acme
+ */
+#if 0
+ ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1;
+ if (ap->dccpap_buf_tail >= ap->dccpap_buf_len)
+ ap->dccpap_buf_tail -= ap->dccpap_buf_len;
+#endif
+ ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len;
+}
+
+void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk,
+ u64 ackno)
+{
+ /* Check if we actually sent an ACK vector */
+ if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
+ return;
+
+ if (ackno == ap->dccpap_ack_seqno) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ struct dccp_sock *dp = dccp_sk(sk);
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT rx ack: " : "server rx ack: ";
+#endif
+ dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
+ "ack_ackno=%llu, ACKED!\n",
+ debug_prefix, 1,
+ (unsigned long long) ap->dccpap_ack_seqno,
+ (unsigned long long) ap->dccpap_ack_ackno);
+ dccp_ackpkts_trow_away_ack_record(ap);
+ ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
+ }
+}
+
+static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
+ struct sock *sk, u64 ackno,
+ const unsigned char len,
+ const unsigned char *vector)
+{
+ unsigned char i;
+
+ /* Check if we actually sent an ACK vector */
+ if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
+ return;
+ /*
+ * We're in the receiver half connection, so if the received an ACK
+ * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're
+ * not interested.
+ *
+ * Extra explanation with example:
+ *
+ * if we received an ACK vector with ackno 50, it can only be acking
+ * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
+ */
+ /* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */
+ if (before48(ackno, ap->dccpap_ack_seqno)) {
+ /* dccp_pr_debug_cat("yes\n"); */
+ return;
+ }
+ /* dccp_pr_debug_cat("no\n"); */
+
+ i = len;
+ while (i--) {
+ const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
+ u64 ackno_end_rl;
+
+ dccp_set_seqno(&ackno_end_rl, ackno - rl);
+
+ /*
+ * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
+ * ap->dccpap_ack_seqno, ackno);
+ */
+ if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) {
+ const u8 state = (*vector &
+ DCCP_ACKPKTS_STATE_MASK) >> 6;
+ /* dccp_pr_debug_cat("yes\n"); */
+
+ if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ struct dccp_sock *dp = dccp_sk(sk);
+ const char *debug_prefix =
+ dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT rx ack: " : "server rx ack: ";
+#endif
+ dccp_pr_debug("%sACK vector 0, len=%d, "
+ "ack_seqno=%llu, ack_ackno=%llu, "
+ "ACKED!\n",
+ debug_prefix, len,
+ (unsigned long long)
+ ap->dccpap_ack_seqno,
+ (unsigned long long)
+ ap->dccpap_ack_ackno);
+ dccp_ackpkts_trow_away_ack_record(ap);
+ }
+ /*
+ * If dccpap_ack_seqno was not received, no problem
+ * we'll send another ACK vector.
+ */
+ ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
+ break;
+ }
+ /* dccp_pr_debug_cat("no\n"); */
+
+ dccp_set_seqno(&ackno, ackno_end_rl - 1);
+ ++vector;
+ }
+}
diff --git a/net/dccp/output.c b/net/dccp/output.c
new file mode 100644
index 000000000000..ea6d0e91e511
--- /dev/null
+++ b/net/dccp/output.c
@@ -0,0 +1,525 @@
+/*
+ * net/dccp/output.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+
+#include <net/sock.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+static inline void dccp_event_ack_sent(struct sock *sk)
+{
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
+}
+
+/*
+ * All SKB's seen here are completely headerless. It is our
+ * job to build the DCCP header, and pass the packet down to
+ * IP so it can do the same plus pass the packet off to the
+ * device.
+ */
+int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ if (likely(skb != NULL)) {
+ const struct inet_sock *inet = inet_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ struct dccp_hdr *dh;
+ /* XXX For now we're using only 48 bits sequence numbers */
+ const int dccp_header_size = sizeof(*dh) +
+ sizeof(struct dccp_hdr_ext) +
+ dccp_packet_hdr_len(dcb->dccpd_type);
+ int err, set_ack = 1;
+ u64 ackno = dp->dccps_gsr;
+
+ dccp_inc_seqno(&dp->dccps_gss);
+
+ switch (dcb->dccpd_type) {
+ case DCCP_PKT_DATA:
+ set_ack = 0;
+ break;
+ case DCCP_PKT_SYNC:
+ case DCCP_PKT_SYNCACK:
+ ackno = dcb->dccpd_seq;
+ break;
+ }
+
+ dcb->dccpd_seq = dp->dccps_gss;
+ dccp_insert_options(sk, skb);
+
+ skb->h.raw = skb_push(skb, dccp_header_size);
+ dh = dccp_hdr(skb);
+ /*
+ * Data packets are not cloned as they are never retransmitted
+ */
+ if (skb_cloned(skb))
+ skb_set_owner_w(skb, sk);
+
+ /* Build DCCP header and checksum it. */
+ memset(dh, 0, dccp_header_size);
+ dh->dccph_type = dcb->dccpd_type;
+ dh->dccph_sport = inet->sport;
+ dh->dccph_dport = inet->dport;
+ dh->dccph_doff = (dccp_header_size + dcb->dccpd_opt_len) / 4;
+ dh->dccph_ccval = dcb->dccpd_ccval;
+ /* XXX For now we're using only 48 bits sequence numbers */
+ dh->dccph_x = 1;
+
+ dp->dccps_awh = dp->dccps_gss;
+ dccp_hdr_set_seq(dh, dp->dccps_gss);
+ if (set_ack)
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
+
+ switch (dcb->dccpd_type) {
+ case DCCP_PKT_REQUEST:
+ dccp_hdr_request(skb)->dccph_req_service =
+ dcb->dccpd_service;
+ break;
+ case DCCP_PKT_RESET:
+ dccp_hdr_reset(skb)->dccph_reset_code =
+ dcb->dccpd_reset_code;
+ break;
+ }
+
+ dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr,
+ inet->daddr);
+
+ if (set_ack)
+ dccp_event_ack_sent(sk);
+
+ DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
+
+ err = ip_queue_xmit(skb, 0);
+ if (err <= 0)
+ return err;
+
+ /* NET_XMIT_CN is special. It does not guarantee,
+ * that this packet is lost. It tells that device
+ * is about to start to drop packets or already
+ * drops some packets of the same priority and
+ * invokes us to send less aggressively.
+ */
+ return err == NET_XMIT_CN ? 0 : err;
+ }
+ return -ENOBUFS;
+}
+
+unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ int mss_now;
+
+ /*
+ * FIXME: we really should be using the af_specific thing to support
+ * IPv6.
+ * mss_now = pmtu - tp->af_specific->net_header_len -
+ * sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext);
+ */
+ mss_now = pmtu - sizeof(struct iphdr) - sizeof(struct dccp_hdr) -
+ sizeof(struct dccp_hdr_ext);
+
+ /* Now subtract optional transport overhead */
+ mss_now -= dp->dccps_ext_header_len;
+
+ /*
+ * FIXME: this should come from the CCID infrastructure, where, say,
+ * TFRC will say it wants TIMESTAMPS, ELAPSED time, etc, for now lets
+ * put a rough estimate for NDP + TIMESTAMP + TIMESTAMP_ECHO + ELAPSED
+ * TIME + TFRC_OPT_LOSS_EVENT_RATE + TFRC_OPT_RECEIVE_RATE + padding to
+ * make it a multiple of 4
+ */
+
+ mss_now -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;
+
+ /* And store cached results */
+ dp->dccps_pmtu_cookie = pmtu;
+ dp->dccps_mss_cache = mss_now;
+
+ return mss_now;
+}
+
+void dccp_write_space(struct sock *sk)
+{
+ read_lock(&sk->sk_callback_lock);
+
+ if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+ wake_up_interruptible(sk->sk_sleep);
+ /* Should agree with poll, otherwise some programs break */
+ if (sock_writeable(sk))
+ sk_wake_async(sk, 2, POLL_OUT);
+
+ read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
+ * @sk: socket to wait for
+ * @timeo: for how long
+ */
+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
+ long *timeo)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ DEFINE_WAIT(wait);
+ long delay;
+ int rc;
+
+ while (1) {
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+
+ if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
+ goto do_error;
+ if (!*timeo)
+ goto do_nonblock;
+ if (signal_pending(current))
+ goto do_interrupted;
+
+ rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
+ skb->len);
+ if (rc <= 0)
+ break;
+ delay = msecs_to_jiffies(rc);
+ if (delay > *timeo || delay < 0)
+ goto do_nonblock;
+
+ sk->sk_write_pending++;
+ release_sock(sk);
+ *timeo -= schedule_timeout(delay);
+ lock_sock(sk);
+ sk->sk_write_pending--;
+ }
+out:
+ finish_wait(sk->sk_sleep, &wait);
+ return rc;
+
+do_error:
+ rc = -EPIPE;
+ goto out;
+do_nonblock:
+ rc = -EAGAIN;
+ goto out;
+do_interrupted:
+ rc = sock_intr_errno(*timeo);
+ goto out;
+}
+
+int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
+ skb->len);
+
+ if (err > 0)
+ err = dccp_wait_for_ccid(sk, skb, timeo);
+
+ if (err == 0) {
+ const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ const int len = skb->len;
+
+ if (sk->sk_state == DCCP_PARTOPEN) {
+ /* See 8.1.5. Handshake Completion */
+ inet_csk_schedule_ack(sk);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ inet_csk(sk)->icsk_rto,
+ DCCP_RTO_MAX);
+ dcb->dccpd_type = DCCP_PKT_DATAACK;
+ /*
+ * FIXME: we really should have a
+ * dccps_ack_pending or use icsk.
+ */
+ } else if (inet_csk_ack_scheduled(sk) ||
+ dp->dccps_timestamp_echo != 0 ||
+ (dp->dccps_options.dccpo_send_ack_vector &&
+ ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 &&
+ ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1))
+ dcb->dccpd_type = DCCP_PKT_DATAACK;
+ else
+ dcb->dccpd_type = DCCP_PKT_DATA;
+
+ err = dccp_transmit_skb(sk, skb);
+ ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
+ }
+
+ return err;
+}
+
+int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ if (inet_sk_rebuild_header(sk) != 0)
+ return -EHOSTUNREACH; /* Routing failure or similar. */
+
+ return dccp_transmit_skb(sk, (skb_cloned(skb) ?
+ pskb_copy(skb, GFP_ATOMIC):
+ skb_clone(skb, GFP_ATOMIC)));
+}
+
+struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
+ struct request_sock *req)
+{
+ struct dccp_hdr *dh;
+ const int dccp_header_size = sizeof(struct dccp_hdr) +
+ sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_response);
+ struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN +
+ dccp_header_size, 1,
+ GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size);
+
+ skb->dst = dst_clone(dst);
+ skb->csum = 0;
+
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
+ DCCP_SKB_CB(skb)->dccpd_seq = dccp_rsk(req)->dreq_iss;
+ dccp_insert_options(sk, skb);
+
+ skb->h.raw = skb_push(skb, dccp_header_size);
+
+ dh = dccp_hdr(skb);
+ memset(dh, 0, dccp_header_size);
+
+ dh->dccph_sport = inet_sk(sk)->sport;
+ dh->dccph_dport = inet_rsk(req)->rmt_port;
+ dh->dccph_doff = (dccp_header_size +
+ DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
+ dh->dccph_type = DCCP_PKT_RESPONSE;
+ dh->dccph_x = 1;
+ dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr);
+
+ dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
+ inet_rsk(req)->rmt_addr);
+
+ DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
+ return skb;
+}
+
+struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
+ const enum dccp_reset_codes code)
+
+{
+ struct dccp_hdr *dh;
+ struct dccp_sock *dp = dccp_sk(sk);
+ const int dccp_header_size = sizeof(struct dccp_hdr) +
+ sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_reset);
+ struct sk_buff *skb = sock_wmalloc(sk, MAX_HEADER + DCCP_MAX_OPT_LEN +
+ dccp_header_size, 1,
+ GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_HEADER + DCCP_MAX_OPT_LEN + dccp_header_size);
+
+ skb->dst = dst_clone(dst);
+ skb->csum = 0;
+
+ dccp_inc_seqno(&dp->dccps_gss);
+
+ DCCP_SKB_CB(skb)->dccpd_reset_code = code;
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET;
+ DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss;
+ dccp_insert_options(sk, skb);
+
+ skb->h.raw = skb_push(skb, dccp_header_size);
+
+ dh = dccp_hdr(skb);
+ memset(dh, 0, dccp_header_size);
+
+ dh->dccph_sport = inet_sk(sk)->sport;
+ dh->dccph_dport = inet_sk(sk)->dport;
+ dh->dccph_doff = (dccp_header_size +
+ DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
+ dh->dccph_type = DCCP_PKT_RESET;
+ dh->dccph_x = 1;
+ dccp_hdr_set_seq(dh, dp->dccps_gss);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
+
+ dccp_hdr_reset(skb)->dccph_reset_code = code;
+
+ dh->dccph_checksum = dccp_v4_checksum(skb, inet_sk(sk)->saddr,
+ inet_sk(sk)->daddr);
+
+ DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
+ return skb;
+}
+
+/*
+ * Do all connect socket setups that can be done AF independent.
+ */
+static inline void dccp_connect_init(struct sock *sk)
+{
+ struct dst_entry *dst = __sk_dst_get(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ sk->sk_err = 0;
+ sock_reset_flag(sk, SOCK_DONE);
+
+ dccp_sync_mss(sk, dst_mtu(dst));
+
+ /*
+ * FIXME: set dp->{dccps_swh,dccps_swl}, with
+ * something like dccp_inc_seq
+ */
+
+ icsk->icsk_retransmits = 0;
+}
+
+int dccp_connect(struct sock *sk)
+{
+ struct sk_buff *skb;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ dccp_connect_init(sk);
+
+ skb = alloc_skb(MAX_DCCP_HEADER + 15, sk->sk_allocation);
+ if (unlikely(skb == NULL))
+ return -ENOBUFS;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_DCCP_HEADER);
+
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
+ /* FIXME: set service to something meaningful, coming
+ * from userspace*/
+ DCCP_SKB_CB(skb)->dccpd_service = 0;
+ skb->csum = 0;
+ skb_set_owner_w(skb, sk);
+
+ BUG_TRAP(sk->sk_send_head == NULL);
+ sk->sk_send_head = skb;
+ dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
+ DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
+
+ /* Timer for repeating the REQUEST until an answer. */
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ icsk->icsk_rto, DCCP_RTO_MAX);
+ return 0;
+}
+
+void dccp_send_ack(struct sock *sk)
+{
+ /* If we have been reset, we may not send again. */
+ if (sk->sk_state != DCCP_CLOSED) {
+ struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC);
+
+ if (skb == NULL) {
+ inet_csk_schedule_ack(sk);
+ inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ TCP_DELACK_MAX,
+ DCCP_RTO_MAX);
+ return;
+ }
+
+ /* Reserve space for headers */
+ skb_reserve(skb, MAX_DCCP_HEADER);
+ skb->csum = 0;
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
+ skb_set_owner_w(skb, sk);
+ dccp_transmit_skb(sk, skb);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_send_ack);
+
+void dccp_send_delayed_ack(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ /*
+ * FIXME: tune this timer. elapsed time fixes the skew, so no problem
+ * with using 2s, and active senders also piggyback the ACK into a
+ * DATAACK packet, so this is really for quiescent senders.
+ */
+ unsigned long timeout = jiffies + 2 * HZ;
+
+ /* Use new timeout only if there wasn't a older one earlier. */
+ if (icsk->icsk_ack.pending & ICSK_ACK_TIMER) {
+ /* If delack timer was blocked or is about to expire,
+ * send ACK now.
+ *
+ * FIXME: check the "about to expire" part
+ */
+ if (icsk->icsk_ack.blocked) {
+ dccp_send_ack(sk);
+ return;
+ }
+
+ if (!time_before(timeout, icsk->icsk_ack.timeout))
+ timeout = icsk->icsk_ack.timeout;
+ }
+ icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
+ icsk->icsk_ack.timeout = timeout;
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
+}
+
+void dccp_send_sync(struct sock *sk, const u64 seq,
+ const enum dccp_pkt_type pkt_type)
+{
+ /*
+ * We are not putting this on the write queue, so
+ * dccp_transmit_skb() will set the ownership to this
+ * sock.
+ */
+ struct sk_buff *skb = alloc_skb(MAX_DCCP_HEADER, GFP_ATOMIC);
+
+ if (skb == NULL)
+ /* FIXME: how to make sure the sync is sent? */
+ return;
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_DCCP_HEADER);
+ skb->csum = 0;
+ DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
+ DCCP_SKB_CB(skb)->dccpd_seq = seq;
+
+ skb_set_owner_w(skb, sk);
+ dccp_transmit_skb(sk, skb);
+}
+
+/*
+ * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This
+ * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under
+ * any circumstances.
+ */
+void dccp_send_close(struct sock *sk, const int active)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct sk_buff *skb;
+ const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC;
+
+ skb = alloc_skb(sk->sk_prot->max_header, prio);
+ if (skb == NULL)
+ return;
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, sk->sk_prot->max_header);
+ skb->csum = 0;
+ DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
+
+ skb_set_owner_w(skb, sk);
+ if (active) {
+ BUG_TRAP(sk->sk_send_head == NULL);
+ sk->sk_send_head = skb;
+ dccp_transmit_skb(sk, skb_clone(skb, prio));
+ } else
+ dccp_transmit_skb(sk, skb);
+}
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
new file mode 100644
index 000000000000..18a0e69c9dc7
--- /dev/null
+++ b/net/dccp/proto.c
@@ -0,0 +1,826 @@
+/*
+ * net/dccp/proto.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * 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/dccp.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <net/checksum.h>
+
+#include <net/inet_common.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/sock.h>
+#include <net/xfrm.h>
+
+#include <asm/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/dccp.h>
+
+#include "ccid.h"
+#include "dccp.h"
+
+DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly;
+
+atomic_t dccp_orphan_count = ATOMIC_INIT(0);
+
+static struct net_protocol dccp_protocol = {
+ .handler = dccp_v4_rcv,
+ .err_handler = dccp_v4_err,
+};
+
+const char *dccp_packet_name(const int type)
+{
+ static const char *dccp_packet_names[] = {
+ [DCCP_PKT_REQUEST] = "REQUEST",
+ [DCCP_PKT_RESPONSE] = "RESPONSE",
+ [DCCP_PKT_DATA] = "DATA",
+ [DCCP_PKT_ACK] = "ACK",
+ [DCCP_PKT_DATAACK] = "DATAACK",
+ [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
+ [DCCP_PKT_CLOSE] = "CLOSE",
+ [DCCP_PKT_RESET] = "RESET",
+ [DCCP_PKT_SYNC] = "SYNC",
+ [DCCP_PKT_SYNCACK] = "SYNCACK",
+ };
+
+ if (type >= DCCP_NR_PKT_TYPES)
+ return "INVALID";
+ else
+ return dccp_packet_names[type];
+}
+
+EXPORT_SYMBOL_GPL(dccp_packet_name);
+
+const char *dccp_state_name(const int state)
+{
+ static char *dccp_state_names[] = {
+ [DCCP_OPEN] = "OPEN",
+ [DCCP_REQUESTING] = "REQUESTING",
+ [DCCP_PARTOPEN] = "PARTOPEN",
+ [DCCP_LISTEN] = "LISTEN",
+ [DCCP_RESPOND] = "RESPOND",
+ [DCCP_CLOSING] = "CLOSING",
+ [DCCP_TIME_WAIT] = "TIME_WAIT",
+ [DCCP_CLOSED] = "CLOSED",
+ };
+
+ if (state >= DCCP_MAX_STATES)
+ return "INVALID STATE!";
+ else
+ return dccp_state_names[state];
+}
+
+EXPORT_SYMBOL_GPL(dccp_state_name);
+
+static inline int dccp_listen_start(struct sock *sk)
+{
+ dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN;
+ return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
+}
+
+int dccp_disconnect(struct sock *sk, int flags)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct inet_sock *inet = inet_sk(sk);
+ int err = 0;
+ const int old_state = sk->sk_state;
+
+ if (old_state != DCCP_CLOSED)
+ dccp_set_state(sk, DCCP_CLOSED);
+
+ /* ABORT function of RFC793 */
+ if (old_state == DCCP_LISTEN) {
+ inet_csk_listen_stop(sk);
+ /* FIXME: do the active reset thing */
+ } else if (old_state == DCCP_REQUESTING)
+ sk->sk_err = ECONNRESET;
+
+ dccp_clear_xmit_timers(sk);
+ __skb_queue_purge(&sk->sk_receive_queue);
+ if (sk->sk_send_head != NULL) {
+ __kfree_skb(sk->sk_send_head);
+ sk->sk_send_head = NULL;
+ }
+
+ inet->dport = 0;
+
+ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
+ inet_reset_saddr(sk);
+
+ sk->sk_shutdown = 0;
+ sock_reset_flag(sk, SOCK_DONE);
+
+ icsk->icsk_backoff = 0;
+ inet_csk_delack_init(sk);
+ __sk_dst_reset(sk);
+
+ BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
+
+ sk->sk_error_report(sk);
+ return err;
+}
+
+/*
+ * Wait for a DCCP event.
+ *
+ * Note that we don't need to lock the socket, as the upper poll layers
+ * take care of normal races (between the test and the event) and we don't
+ * go look at any of the socket buffers directly.
+ */
+static unsigned int dccp_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ unsigned int mask;
+ struct sock *sk = sock->sk;
+
+ poll_wait(file, sk->sk_sleep, wait);
+ if (sk->sk_state == DCCP_LISTEN)
+ return inet_csk_listen_poll(sk);
+
+ /* Socket is not locked. We are protected from async events
+ by poll logic and correct handling of state changes
+ made by another threads is impossible in any case.
+ */
+
+ mask = 0;
+ if (sk->sk_err)
+ mask = POLLERR;
+
+ if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
+ mask |= POLLHUP;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLIN | POLLRDNORM;
+
+ /* Connected? */
+ if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
+ if (atomic_read(&sk->sk_rmem_alloc) > 0)
+ mask |= POLLIN | POLLRDNORM;
+
+ if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
+ if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+ mask |= POLLOUT | POLLWRNORM;
+ } else { /* send SIGIO later */
+ set_bit(SOCK_ASYNC_NOSPACE,
+ &sk->sk_socket->flags);
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+
+ /* Race breaker. If space is freed after
+ * wspace test but before the flags are set,
+ * IO signal will be lost.
+ */
+ if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ }
+ }
+ return mask;
+}
+
+int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ dccp_pr_debug("entry\n");
+ return -ENOIOCTLCMD;
+}
+
+int dccp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
+{
+ struct dccp_sock *dp;
+ int err;
+ int val;
+
+ if (level != SOL_DCCP)
+ return ip_setsockopt(sk, level, optname, optval, optlen);
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int __user *)optval))
+ return -EFAULT;
+
+ lock_sock(sk);
+
+ dp = dccp_sk(sk);
+ err = 0;
+
+ switch (optname) {
+ case DCCP_SOCKOPT_PACKET_SIZE:
+ dp->dccps_packet_size = val;
+ break;
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ release_sock(sk);
+ return err;
+}
+
+int dccp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct dccp_sock *dp;
+ int val, len;
+
+ if (level != SOL_DCCP)
+ return ip_getsockopt(sk, level, optname, optval, optlen);
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ len = min_t(unsigned int, len, sizeof(int));
+ if (len < 0)
+ return -EINVAL;
+
+ dp = dccp_sk(sk);
+
+ switch (optname) {
+ case DCCP_SOCKOPT_PACKET_SIZE:
+ val = dp->dccps_packet_size;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+ return -EFAULT;
+
+ return 0;
+}
+
+int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ const int flags = msg->msg_flags;
+ const int noblock = flags & MSG_DONTWAIT;
+ struct sk_buff *skb;
+ int rc, size;
+ long timeo;
+
+ if (len > dp->dccps_mss_cache)
+ return -EMSGSIZE;
+
+ lock_sock(sk);
+ timeo = sock_sndtimeo(sk, noblock);
+
+ /*
+ * We have to use sk_stream_wait_connect here to set sk_write_pending,
+ * so that the trick in dccp_rcv_request_sent_state_process.
+ */
+ /* Wait for a connection to finish. */
+ if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING))
+ if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0)
+ goto out_release;
+
+ size = sk->sk_prot->max_header + len;
+ release_sock(sk);
+ skb = sock_alloc_send_skb(sk, size, noblock, &rc);
+ lock_sock(sk);
+ if (skb == NULL)
+ goto out_release;
+
+ skb_reserve(skb, sk->sk_prot->max_header);
+ rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+ if (rc != 0)
+ goto out_discard;
+
+ rc = dccp_write_xmit(sk, skb, &timeo);
+ /*
+ * XXX we don't use sk_write_queue, so just discard the packet.
+ * Current plan however is to _use_ sk_write_queue with
+ * an algorith similar to tcp_sendmsg, where the main difference
+ * is that in DCCP we have to respect packet boundaries, so
+ * no coalescing of skbs.
+ *
+ * This bug was _quickly_ found & fixed by just looking at an OSTRA
+ * generated callgraph 8) -acme
+ */
+ if (rc != 0)
+ goto out_discard;
+out_release:
+ release_sock(sk);
+ return rc ? : len;
+out_discard:
+ kfree_skb(skb);
+ goto out_release;
+}
+
+int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int nonblock, int flags, int *addr_len)
+{
+ const struct dccp_hdr *dh;
+ long timeo;
+
+ lock_sock(sk);
+
+ if (sk->sk_state == DCCP_LISTEN) {
+ len = -ENOTCONN;
+ goto out;
+ }
+
+ timeo = sock_rcvtimeo(sk, nonblock);
+
+ do {
+ struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+
+ if (skb == NULL)
+ goto verify_sock_status;
+
+ dh = dccp_hdr(skb);
+
+ if (dh->dccph_type == DCCP_PKT_DATA ||
+ dh->dccph_type == DCCP_PKT_DATAACK)
+ goto found_ok_skb;
+
+ if (dh->dccph_type == DCCP_PKT_RESET ||
+ dh->dccph_type == DCCP_PKT_CLOSE) {
+ dccp_pr_debug("found fin ok!\n");
+ len = 0;
+ goto found_fin_ok;
+ }
+ dccp_pr_debug("packet_type=%s\n",
+ dccp_packet_name(dh->dccph_type));
+ sk_eat_skb(sk, skb);
+verify_sock_status:
+ if (sock_flag(sk, SOCK_DONE)) {
+ len = 0;
+ break;
+ }
+
+ if (sk->sk_err) {
+ len = sock_error(sk);
+ break;
+ }
+
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
+ len = 0;
+ break;
+ }
+
+ if (sk->sk_state == DCCP_CLOSED) {
+ if (!sock_flag(sk, SOCK_DONE)) {
+ /* This occurs when user tries to read
+ * from never connected socket.
+ */
+ len = -ENOTCONN;
+ break;
+ }
+ len = 0;
+ break;
+ }
+
+ if (!timeo) {
+ len = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ len = sock_intr_errno(timeo);
+ break;
+ }
+
+ sk_wait_data(sk, &timeo);
+ continue;
+ found_ok_skb:
+ if (len > skb->len)
+ len = skb->len;
+ else if (len < skb->len)
+ msg->msg_flags |= MSG_TRUNC;
+
+ if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
+ /* Exception. Bailout! */
+ len = -EFAULT;
+ break;
+ }
+ found_fin_ok:
+ if (!(flags & MSG_PEEK))
+ sk_eat_skb(sk, skb);
+ break;
+ } while (1);
+out:
+ release_sock(sk);
+ return len;
+}
+
+static int inet_dccp_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+ unsigned char old_state;
+ int err;
+
+ lock_sock(sk);
+
+ err = -EINVAL;
+ if (sock->state != SS_UNCONNECTED || sock->type != SOCK_DCCP)
+ goto out;
+
+ old_state = sk->sk_state;
+ if (!((1 << old_state) & (DCCPF_CLOSED | DCCPF_LISTEN)))
+ goto out;
+
+ /* Really, if the socket is already in listen state
+ * we can only allow the backlog to be adjusted.
+ */
+ if (old_state != DCCP_LISTEN) {
+ /*
+ * FIXME: here it probably should be sk->sk_prot->listen_start
+ * see tcp_listen_start
+ */
+ err = dccp_listen_start(sk);
+ if (err)
+ goto out;
+ }
+ sk->sk_max_ack_backlog = backlog;
+ err = 0;
+
+out:
+ release_sock(sk);
+ return err;
+}
+
+static const unsigned char dccp_new_state[] = {
+ /* current state: new state: action: */
+ [0] = DCCP_CLOSED,
+ [DCCP_OPEN] = DCCP_CLOSING | DCCP_ACTION_FIN,
+ [DCCP_REQUESTING] = DCCP_CLOSED,
+ [DCCP_PARTOPEN] = DCCP_CLOSING | DCCP_ACTION_FIN,
+ [DCCP_LISTEN] = DCCP_CLOSED,
+ [DCCP_RESPOND] = DCCP_CLOSED,
+ [DCCP_CLOSING] = DCCP_CLOSED,
+ [DCCP_TIME_WAIT] = DCCP_CLOSED,
+ [DCCP_CLOSED] = DCCP_CLOSED,
+};
+
+static int dccp_close_state(struct sock *sk)
+{
+ const int next = dccp_new_state[sk->sk_state];
+ const int ns = next & DCCP_STATE_MASK;
+
+ if (ns != sk->sk_state)
+ dccp_set_state(sk, ns);
+
+ return next & DCCP_ACTION_FIN;
+}
+
+void dccp_close(struct sock *sk, long timeout)
+{
+ struct sk_buff *skb;
+
+ lock_sock(sk);
+
+ sk->sk_shutdown = SHUTDOWN_MASK;
+
+ if (sk->sk_state == DCCP_LISTEN) {
+ dccp_set_state(sk, DCCP_CLOSED);
+
+ /* Special case. */
+ inet_csk_listen_stop(sk);
+
+ goto adjudge_to_death;
+ }
+
+ /*
+ * We need to flush the recv. buffs. We do this only on the
+ * descriptor close, not protocol-sourced closes, because the
+ *reader process may not have drained the data yet!
+ */
+ /* FIXME: check for unread data */
+ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ __kfree_skb(skb);
+ }
+
+ if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
+ /* Check zero linger _after_ checking for unread data. */
+ sk->sk_prot->disconnect(sk, 0);
+ } else if (dccp_close_state(sk)) {
+ dccp_send_close(sk, 1);
+ }
+
+ sk_stream_wait_close(sk, timeout);
+
+adjudge_to_death:
+ /*
+ * It is the last release_sock in its life. It will remove backlog.
+ */
+ release_sock(sk);
+ /*
+ * Now socket is owned by kernel and we acquire BH lock
+ * to finish close. No need to check for user refs.
+ */
+ local_bh_disable();
+ bh_lock_sock(sk);
+ BUG_TRAP(!sock_owned_by_user(sk));
+
+ sock_hold(sk);
+ sock_orphan(sk);
+
+ /*
+ * The last release_sock may have processed the CLOSE or RESET
+ * packet moving sock to CLOSED state, if not we have to fire
+ * the CLOSE/CLOSEREQ retransmission timer, see "8.3. Termination"
+ * in draft-ietf-dccp-spec-11. -acme
+ */
+ if (sk->sk_state == DCCP_CLOSING) {
+ /* FIXME: should start at 2 * RTT */
+ /* Timer for repeating the CLOSE/CLOSEREQ until an answer. */
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ inet_csk(sk)->icsk_rto,
+ DCCP_RTO_MAX);
+#if 0
+ /* Yeah, we should use sk->sk_prot->orphan_count, etc */
+ dccp_set_state(sk, DCCP_CLOSED);
+#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. */
+
+ bh_unlock_sock(sk);
+ local_bh_enable();
+ sock_put(sk);
+}
+
+void dccp_shutdown(struct sock *sk, int how)
+{
+ dccp_pr_debug("entry\n");
+}
+
+static struct proto_ops inet_dccp_ops = {
+ .family = PF_INET,
+ .owner = THIS_MODULE,
+ .release = inet_release,
+ .bind = inet_bind,
+ .connect = inet_stream_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = inet_accept,
+ .getname = inet_getname,
+ /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
+ .poll = dccp_poll,
+ .ioctl = inet_ioctl,
+ /* FIXME: work on inet_listen to rename it to sock_common_listen */
+ .listen = inet_dccp_listen,
+ .shutdown = inet_shutdown,
+ .setsockopt = sock_common_setsockopt,
+ .getsockopt = sock_common_getsockopt,
+ .sendmsg = inet_sendmsg,
+ .recvmsg = sock_common_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+extern struct net_proto_family inet_family_ops;
+
+static struct inet_protosw dccp_v4_protosw = {
+ .type = SOCK_DCCP,
+ .protocol = IPPROTO_DCCP,
+ .prot = &dccp_v4_prot,
+ .ops = &inet_dccp_ops,
+ .capability = -1,
+ .no_check = 0,
+ .flags = 0,
+};
+
+/*
+ * This is the global socket data structure used for responding to
+ * the Out-of-the-blue (OOTB) packets. A control sock will be created
+ * for this socket at the initialization time.
+ */
+struct socket *dccp_ctl_socket;
+
+static char dccp_ctl_socket_err_msg[] __initdata =
+ KERN_ERR "DCCP: Failed to create the control socket.\n";
+
+static int __init dccp_ctl_sock_init(void)
+{
+ int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP,
+ &dccp_ctl_socket);
+ if (rc < 0)
+ printk(dccp_ctl_socket_err_msg);
+ else {
+ dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+ inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1;
+
+ /* Unhash it so that IP input processing does not even
+ * see it, we do not wish this socket to see incoming
+ * packets.
+ */
+ dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk);
+ }
+
+ return rc;
+}
+
+#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
+void dccp_ctl_sock_exit(void)
+{
+ if (dccp_ctl_socket != NULL) {
+ sock_release(dccp_ctl_socket);
+ dccp_ctl_socket = NULL;
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
+#endif
+
+static int __init init_dccp_v4_mibs(void)
+{
+ int rc = -ENOMEM;
+
+ dccp_statistics[0] = alloc_percpu(struct dccp_mib);
+ if (dccp_statistics[0] == NULL)
+ goto out;
+
+ dccp_statistics[1] = alloc_percpu(struct dccp_mib);
+ if (dccp_statistics[1] == NULL)
+ goto out_free_one;
+
+ rc = 0;
+out:
+ return rc;
+out_free_one:
+ free_percpu(dccp_statistics[0]);
+ dccp_statistics[0] = NULL;
+ goto out;
+
+}
+
+static int thash_entries;
+module_param(thash_entries, int, 0444);
+MODULE_PARM_DESC(thash_entries, "Number of ehash buckets");
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+int dccp_debug;
+module_param(dccp_debug, int, 0444);
+MODULE_PARM_DESC(dccp_debug, "Enable debug messages");
+#endif
+
+static int __init dccp_init(void)
+{
+ unsigned long goal;
+ int ehash_order, bhash_order, i;
+ int rc = proto_register(&dccp_v4_prot, 1);
+
+ if (rc)
+ goto out;
+
+ dccp_hashinfo.bind_bucket_cachep =
+ kmem_cache_create("dccp_bind_bucket",
+ sizeof(struct inet_bind_bucket), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (!dccp_hashinfo.bind_bucket_cachep)
+ goto out_proto_unregister;
+
+ /*
+ * Size and allocate the main established and bind bucket
+ * hash tables.
+ *
+ * The methodology is similar to that of the buffer cache.
+ */
+ if (num_physpages >= (128 * 1024))
+ goal = num_physpages >> (21 - PAGE_SHIFT);
+ else
+ goal = num_physpages >> (23 - PAGE_SHIFT);
+
+ if (thash_entries)
+ goal = (thash_entries *
+ sizeof(struct inet_ehash_bucket)) >> PAGE_SHIFT;
+ for (ehash_order = 0; (1UL << ehash_order) < goal; ehash_order++)
+ ;
+ do {
+ dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
+ sizeof(struct inet_ehash_bucket);
+ dccp_hashinfo.ehash_size >>= 1;
+ while (dccp_hashinfo.ehash_size &
+ (dccp_hashinfo.ehash_size - 1))
+ dccp_hashinfo.ehash_size--;
+ dccp_hashinfo.ehash = (struct inet_ehash_bucket *)
+ __get_free_pages(GFP_ATOMIC, ehash_order);
+ } while (!dccp_hashinfo.ehash && --ehash_order > 0);
+
+ if (!dccp_hashinfo.ehash) {
+ printk(KERN_CRIT "Failed to allocate DCCP "
+ "established hash table\n");
+ goto out_free_bind_bucket_cachep;
+ }
+
+ for (i = 0; i < (dccp_hashinfo.ehash_size << 1); i++) {
+ rwlock_init(&dccp_hashinfo.ehash[i].lock);
+ INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
+ }
+
+ bhash_order = ehash_order;
+
+ do {
+ dccp_hashinfo.bhash_size = (1UL << bhash_order) * PAGE_SIZE /
+ sizeof(struct inet_bind_hashbucket);
+ if ((dccp_hashinfo.bhash_size > (64 * 1024)) &&
+ bhash_order > 0)
+ continue;
+ dccp_hashinfo.bhash = (struct inet_bind_hashbucket *)
+ __get_free_pages(GFP_ATOMIC, bhash_order);
+ } while (!dccp_hashinfo.bhash && --bhash_order >= 0);
+
+ if (!dccp_hashinfo.bhash) {
+ printk(KERN_CRIT "Failed to allocate DCCP bind hash table\n");
+ goto out_free_dccp_ehash;
+ }
+
+ for (i = 0; i < dccp_hashinfo.bhash_size; i++) {
+ spin_lock_init(&dccp_hashinfo.bhash[i].lock);
+ INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain);
+ }
+
+ if (init_dccp_v4_mibs())
+ goto out_free_dccp_bhash;
+
+ rc = -EAGAIN;
+ if (inet_add_protocol(&dccp_protocol, IPPROTO_DCCP))
+ goto out_free_dccp_v4_mibs;
+
+ inet_register_protosw(&dccp_v4_protosw);
+
+ rc = dccp_ctl_sock_init();
+ if (rc)
+ goto out_unregister_protosw;
+out:
+ return rc;
+out_unregister_protosw:
+ inet_unregister_protosw(&dccp_v4_protosw);
+ inet_del_protocol(&dccp_protocol, IPPROTO_DCCP);
+out_free_dccp_v4_mibs:
+ free_percpu(dccp_statistics[0]);
+ free_percpu(dccp_statistics[1]);
+ dccp_statistics[0] = dccp_statistics[1] = NULL;
+out_free_dccp_bhash:
+ free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
+ dccp_hashinfo.bhash = NULL;
+out_free_dccp_ehash:
+ free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
+ dccp_hashinfo.ehash = NULL;
+out_free_bind_bucket_cachep:
+ kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
+ dccp_hashinfo.bind_bucket_cachep = NULL;
+out_proto_unregister:
+ proto_unregister(&dccp_v4_prot);
+ goto out;
+}
+
+static const char dccp_del_proto_err_msg[] __exitdata =
+ KERN_ERR "can't remove dccp net_protocol\n";
+
+static void __exit dccp_fini(void)
+{
+ inet_unregister_protosw(&dccp_v4_protosw);
+
+ if (inet_del_protocol(&dccp_protocol, IPPROTO_DCCP) < 0)
+ printk(dccp_del_proto_err_msg);
+
+ free_percpu(dccp_statistics[0]);
+ free_percpu(dccp_statistics[1]);
+ free_pages((unsigned long)dccp_hashinfo.bhash,
+ get_order(dccp_hashinfo.bhash_size *
+ sizeof(struct inet_bind_hashbucket)));
+ free_pages((unsigned long)dccp_hashinfo.ehash,
+ get_order(dccp_hashinfo.ehash_size *
+ sizeof(struct inet_ehash_bucket)));
+ kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
+ proto_unregister(&dccp_v4_prot);
+}
+
+module_init(dccp_init);
+module_exit(dccp_fini);
+
+/*
+ * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
+ * values directly, Also cover the case where the protocol is not specified,
+ * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
+ */
+MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
+MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@conectiva.com.br>");
+MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
new file mode 100644
index 000000000000..aa34b576e228
--- /dev/null
+++ b/net/dccp/timer.c
@@ -0,0 +1,255 @@
+/*
+ * net/dccp/timer.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.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.
+ */
+
+#include <linux/config.h>
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+
+#include "dccp.h"
+
+static void dccp_write_timer(unsigned long data);
+static void dccp_keepalive_timer(unsigned long data);
+static void dccp_delack_timer(unsigned long data);
+
+void dccp_init_xmit_timers(struct sock *sk)
+{
+ inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
+ &dccp_keepalive_timer);
+}
+
+static void dccp_write_err(struct sock *sk)
+{
+ sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT;
+ sk->sk_error_report(sk);
+
+ dccp_v4_send_reset(sk, DCCP_RESET_CODE_ABORTED);
+ dccp_done(sk);
+ DCCP_INC_STATS_BH(DCCP_MIB_ABORTONTIMEOUT);
+}
+
+/* A write timeout has occurred. Process the after effects. */
+static int dccp_write_timeout(struct sock *sk)
+{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ int retry_until;
+
+ if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) {
+ if (icsk->icsk_retransmits != 0)
+ dst_negative_advice(&sk->sk_dst_cache);
+ retry_until = icsk->icsk_syn_retries ? :
+ /* FIXME! */ 3 /* FIXME! sysctl_tcp_syn_retries */;
+ } else {
+ if (icsk->icsk_retransmits >=
+ /* FIXME! sysctl_tcp_retries1 */ 5 /* FIXME! */) {
+ /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu
+ black hole detection. :-(
+
+ It is place to make it. It is not made. I do not want
+ to make it. It is disguisting. It does not work in any
+ case. Let me to cite the same draft, which requires for
+ us to implement this:
+
+ "The one security concern raised by this memo is that ICMP black holes
+ are often caused by over-zealous security administrators who block
+ all ICMP messages. It is vitally important that those who design and
+ deploy security systems understand the impact of strict filtering on
+ upper-layer protocols. The safest web site in the world is worthless
+ if most TCP implementations cannot transfer data from it. It would
+ be far nicer to have all of the black holes fixed rather than fixing
+ all of the TCP implementations."
+
+ Golden words :-).
+ */
+
+ dst_negative_advice(&sk->sk_dst_cache);
+ }
+
+ retry_until = /* FIXME! */ 15 /* FIXME! sysctl_tcp_retries2 */;
+ /*
+ * FIXME: see tcp_write_timout and tcp_out_of_resources
+ */
+ }
+
+ if (icsk->icsk_retransmits >= retry_until) {
+ /* Has it gone just too far? */
+ dccp_write_err(sk);
+ return 1;
+ }
+ return 0;
+}
+
+/* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */
+static void dccp_delack_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later. */
+ icsk->icsk_ack.blocked = 1;
+ NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED);
+ sk_reset_timer(sk, &icsk->icsk_delack_timer,
+ jiffies + TCP_DELACK_MIN);
+ goto out;
+ }
+
+ if (sk->sk_state == DCCP_CLOSED ||
+ !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+ goto out;
+ if (time_after(icsk->icsk_ack.timeout, jiffies)) {
+ sk_reset_timer(sk, &icsk->icsk_delack_timer,
+ icsk->icsk_ack.timeout);
+ goto out;
+ }
+
+ icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
+
+ if (inet_csk_ack_scheduled(sk)) {
+ if (!icsk->icsk_ack.pingpong) {
+ /* Delayed ACK missed: inflate ATO. */
+ icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1,
+ icsk->icsk_rto);
+ } else {
+ /* Delayed ACK missed: leave pingpong mode and
+ * deflate ATO.
+ */
+ icsk->icsk_ack.pingpong = 0;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
+ }
+ dccp_send_ack(sk);
+ NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS);
+ }
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+/*
+ * The DCCP retransmit timer.
+ */
+static void dccp_retransmit_timer(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ /*
+ * sk->sk_send_head has to have one skb with
+ * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
+ * packet types (REQUEST, RESPONSE, the ACK in the 3way handshake
+ * (PARTOPEN timer), etc).
+ */
+ BUG_TRAP(sk->sk_send_head != NULL);
+
+ /*
+ * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
+ * sent, no need to retransmit, this sock is dead.
+ */
+ if (dccp_write_timeout(sk))
+ goto out;
+
+ /*
+ * We want to know the number of packets retransmitted, not the
+ * total number of retransmissions of clones of original packets.
+ */
+ if (icsk->icsk_retransmits == 0)
+ DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
+
+ if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) {
+ /*
+ * Retransmission failed because of local congestion,
+ * do not backoff.
+ */
+ if (icsk->icsk_retransmits == 0)
+ icsk->icsk_retransmits = 1;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ min(icsk->icsk_rto,
+ TCP_RESOURCE_PROBE_INTERVAL),
+ DCCP_RTO_MAX);
+ goto out;
+ }
+
+ icsk->icsk_backoff++;
+ icsk->icsk_retransmits++;
+
+ icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
+ DCCP_RTO_MAX);
+ if (icsk->icsk_retransmits > 3 /* FIXME: sysctl_dccp_retries1 */)
+ __sk_dst_reset(sk);
+out:;
+}
+
+static void dccp_write_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ int event = 0;
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later */
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
+ jiffies + (HZ / 20));
+ goto out;
+ }
+
+ if (sk->sk_state == DCCP_CLOSED || !icsk->icsk_pending)
+ goto out;
+
+ if (time_after(icsk->icsk_timeout, jiffies)) {
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
+ icsk->icsk_timeout);
+ goto out;
+ }
+
+ event = icsk->icsk_pending;
+ icsk->icsk_pending = 0;
+
+ switch (event) {
+ case ICSK_TIME_RETRANS:
+ dccp_retransmit_timer(sk);
+ break;
+ }
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+/*
+ * Timer for listening sockets
+ */
+static void dccp_response_timer(struct sock *sk)
+{
+ inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL, DCCP_TIMEOUT_INIT,
+ DCCP_RTO_MAX);
+}
+
+static void dccp_keepalive_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+
+ /* Only process if socket is not in use. */
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later. */
+ inet_csk_reset_keepalive_timer(sk, HZ / 20);
+ goto out;
+ }
+
+ if (sk->sk_state == DCCP_LISTEN) {
+ dccp_response_timer(sk);
+ goto out;
+ }
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index acdd18e6adb2..348f36b529f7 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -118,7 +118,7 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <linux/netfilter.h>
#include <linux/seq_file.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/flow.h>
#include <asm/system.h>
#include <asm/ioctls.h>
@@ -1763,7 +1763,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
nskb = skb->next;
if (skb->len == 0) {
- skb_unlink(skb);
+ skb_unlink(skb, queue);
kfree_skb(skb);
/*
* N.B. Don't refer to skb or cb after this point
@@ -1876,8 +1876,27 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags)
return mss_now;
}
+/*
+ * N.B. We get the timeout wrong here, but then we always did get it
+ * wrong before and this is another step along the road to correcting
+ * it. It ought to get updated each time we pass through the routine,
+ * but in practise it probably doesn't matter too much for now.
+ */
+static inline struct sk_buff *dn_alloc_send_pskb(struct sock *sk,
+ unsigned long datalen, int noblock,
+ int *errcode)
+{
+ struct sk_buff *skb = sock_alloc_send_skb(sk, datalen,
+ noblock, errcode);
+ if (skb) {
+ skb->protocol = __constant_htons(ETH_P_DNA_RT);
+ skb->pkt_type = PACKET_OUTGOING;
+ }
+ return skb;
+}
+
static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t size)
+ struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
@@ -1892,7 +1911,7 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
struct dn_skb_cb *cb;
size_t len;
unsigned char fctype;
- long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+ long timeo;
if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|MSG_MORE|MSG_CMSG_COMPAT))
return -EOPNOTSUPP;
@@ -1900,18 +1919,21 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
return -EINVAL;
+ lock_sock(sk);
+ timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
/*
* The only difference between stream sockets and sequenced packet
* sockets is that the stream sockets always behave as if MSG_EOR
* has been set.
*/
if (sock->type == SOCK_STREAM) {
- if (flags & MSG_EOR)
- return -EINVAL;
+ if (flags & MSG_EOR) {
+ err = -EINVAL;
+ goto out;
+ }
flags |= MSG_EOR;
}
- lock_sock(sk);
err = dn_check_state(sk, addr, addr_len, &timeo, flags);
if (err)
@@ -1980,8 +2002,12 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
/*
* Get a suitably sized skb.
+ * 64 is a bit of a hack really, but its larger than any
+ * link-layer headers and has served us well as a good
+ * guess as to their real length.
*/
- skb = dn_alloc_send_skb(sk, &len, flags & MSG_DONTWAIT, timeo, &err);
+ skb = dn_alloc_send_pskb(sk, len + 64 + DN_MAX_NSP_DATA_HEADER,
+ flags & MSG_DONTWAIT, &err);
if (err)
break;
@@ -1991,7 +2017,7 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
cb = DN_SKB_CB(skb);
- skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
+ skb_reserve(skb, 64 + DN_MAX_NSP_DATA_HEADER);
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
err = -EFAULT;
@@ -2064,7 +2090,7 @@ static struct notifier_block dn_dev_notifier = {
.notifier_call = dn_device_event,
};
-extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
+extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
static struct packet_type dn_dix_packet_type = {
.type = __constant_htons(ETH_P_DNA_RT),
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 00233ecbc9cb..5610bb16dbf9 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -752,16 +752,16 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
skb = alloc_skb(size, GFP_KERNEL);
if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, ENOBUFS);
return;
}
if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, EINVAL);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_IFADDR;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
+ NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_IFADDR;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_DECnet_IFADDR, GFP_KERNEL);
}
static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 202dbde9850d..369f25b60f3f 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -60,7 +60,7 @@
#include <linux/inet.h>
#include <linux/route.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index 8cce1fdbda90..53633d352868 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -137,69 +137,6 @@ struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri)
}
/*
- * Wrapper for the above, for allocs of data skbs. We try and get the
- * whole size thats been asked for (plus 11 bytes of header). If this
- * fails, then we try for any size over 16 bytes for SOCK_STREAMS.
- */
-struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err)
-{
- int space;
- int len;
- struct sk_buff *skb = NULL;
-
- *err = 0;
-
- while(skb == NULL) {
- if (signal_pending(current)) {
- *err = sock_intr_errno(timeo);
- break;
- }
-
- if (sk->sk_shutdown & SEND_SHUTDOWN) {
- *err = EINVAL;
- break;
- }
-
- if (sk->sk_err)
- break;
-
- len = *size + 11;
- space = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
-
- if (space < len) {
- if ((sk->sk_socket->type == SOCK_STREAM) &&
- (space >= (16 + 11)))
- len = space;
- }
-
- if (space < len) {
- set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
- if (noblock) {
- *err = EWOULDBLOCK;
- break;
- }
-
- clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- SOCK_SLEEP_PRE(sk)
-
- if ((sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc)) <
- len)
- schedule();
-
- SOCK_SLEEP_POST(sk)
- continue;
- }
-
- if ((skb = dn_alloc_skb(sk, len, sk->sk_allocation)) == NULL)
- continue;
-
- *size = len - 11;
- }
-
- return skb;
-}
-
-/*
* Calculate persist timer based upon the smoothed round
* trip time and the variance. Backoff according to the
* nsp_backoff[] array.
@@ -479,7 +416,7 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff
xmit_count = cb2->xmit_count;
segnum = cb2->segnum;
/* Remove and drop ack'ed packet */
- skb_unlink(ack);
+ skb_unlink(ack, q);
kfree_skb(ack);
ack = NULL;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 2399fa8a3f86..3407f190afe8 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -117,8 +117,7 @@ static struct dn_rt_hash_bucket *dn_rt_hash_table;
static unsigned dn_rt_hash_mask;
static struct timer_list dn_route_timer;
-static struct timer_list dn_rt_flush_timer =
- TIMER_INITIALIZER(dn_run_flush, 0, 0);
+static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush, 0, 0);
int decnet_dst_gc_interval = 2;
static struct dst_ops dn_dst_ops = {
@@ -572,7 +571,7 @@ static int dn_route_ptp_hello(struct sk_buff *skb)
return NET_RX_SUCCESS;
}
-int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct dn_skb_cb *cb;
unsigned char flags = 0;
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 28ba5777a25a..eeba56f99323 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -79,7 +79,7 @@ for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_n
static DEFINE_RWLOCK(dn_fib_tables_lock);
struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1];
-static kmem_cache_t *dn_hash_kmem;
+static kmem_cache_t *dn_hash_kmem __read_mostly;
static int dn_fib_hash_zombies;
static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
@@ -349,10 +349,10 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,
kfree_skb(skb);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_ROUTE;
+ NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_ROUTE;
if (nlh->nlmsg_flags & NLM_F_ECHO)
atomic_inc(&skb->users);
- netlink_broadcast(rtnl, skb, pid, RTMGRP_DECnet_ROUTE, GFP_KERNEL);
+ netlink_broadcast(rtnl, skb, pid, RTNLGRP_DECnet_ROUTE, GFP_KERNEL);
if (nlh->nlmsg_flags & NLM_F_ECHO)
netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
}
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 284a9998e53d..1ab94c6e22ed 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -19,6 +19,7 @@
#include <linux/netfilter.h>
#include <linux/spinlock.h>
#include <linux/netlink.h>
+#include <linux/netfilter_decnet.h>
#include <net/sock.h>
#include <net/flow.h>
@@ -71,10 +72,10 @@ static void dnrmg_send_peer(struct sk_buff *skb)
switch(flags & DN_RT_CNTL_MSK) {
case DN_RT_PKT_L1RT:
- group = DNRMG_L1_GROUP;
+ group = DNRNG_NLGRP_L1;
break;
case DN_RT_PKT_L2RT:
- group = DNRMG_L2_GROUP;
+ group = DNRNG_NLGRP_L2;
break;
default:
return;
@@ -83,7 +84,7 @@ static void dnrmg_send_peer(struct sk_buff *skb)
skb2 = dnrmg_build_message(skb, &status);
if (skb2 == NULL)
return;
- NETLINK_CB(skb2).dst_groups = group;
+ NETLINK_CB(skb2).dst_group = group;
netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC);
}
@@ -138,7 +139,8 @@ static int __init init(void)
{
int rv = 0;
- dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk);
+ dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
+ dnrmg_receive_user_sk, THIS_MODULE);
if (dnrmg == NULL) {
printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
return -ENOMEM;
@@ -162,6 +164,7 @@ static void __exit fini(void)
MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
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);
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index de691e119e17..4a62093eb343 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -159,7 +159,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
if (err)
goto out_free;
- sk->sk_stamp = skb->stamp;
+ skb_get_timestamp(skb, &sk->sk_stamp);
if (msg->msg_name)
memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -869,7 +869,7 @@ static void aun_tx_ack(unsigned long seq, int result)
foundit:
tx_result(skb->sk, eb->cookie, result);
- skb_unlink(skb);
+ skb_unlink(skb, &aun_queue);
spin_unlock_irqrestore(&aun_queue_lock, flags);
kfree_skb(skb);
}
@@ -947,7 +947,7 @@ static void ab_cleanup(unsigned long h)
{
tx_result(skb->sk, eb->cookie,
ECTYPE_TRANSMIT_NOT_PRESENT);
- skb_unlink(skb);
+ skb_unlink(skb, &aun_queue);
kfree_skb(skb);
}
skb = newskb;
@@ -1009,7 +1009,7 @@ release:
* Receive an Econet frame from a device.
*/
-static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct ec_framehdr *hdr;
struct sock *sk;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index f6dbfb99b14d..87a052a9a84f 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -62,8 +62,6 @@
#include <asm/system.h>
#include <asm/checksum.h>
-extern int __init netdev_boot_setup(char *str);
-
__setup("ether=", netdev_boot_setup);
/*
@@ -163,7 +161,6 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
skb->mac.raw=skb->data;
skb_pull(skb,ETH_HLEN);
eth = eth_hdr(skb);
- skb->input_dev = dev;
if(*eth->h_dest&1)
{
diff --git a/net/ethernet/sysctl_net_ether.c b/net/ethernet/sysctl_net_ether.c
index b81a6d532342..66b39fc342d2 100644
--- a/net/ethernet/sysctl_net_ether.c
+++ b/net/ethernet/sysctl_net_ether.c
@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/sysctl.h>
+#include <linux/if_ether.h>
ctl_table ether_table[] = {
{0}
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
new file mode 100644
index 000000000000..91b16fbf91f0
--- /dev/null
+++ b/net/ieee80211/Kconfig
@@ -0,0 +1,68 @@
+config IEEE80211
+ tristate "Generic IEEE 802.11 Networking Stack"
+ ---help---
+ This option enables the hardware independent IEEE 802.11
+ networking stack.
+
+config IEEE80211_DEBUG
+ bool "Enable full debugging output"
+ depends on IEEE80211
+ ---help---
+ This option will enable debug tracing output for the
+ ieee80211 network stack.
+
+ This will result in the kernel module being ~70k larger. You
+ can control which debug output is sent to the kernel log by
+ setting the value in
+
+ /proc/net/ieee80211/debug_level
+
+ For example:
+
+ % echo 0x00000FFO > /proc/net/ieee80211/debug_level
+
+ For a list of values you can assign to debug_level, you
+ can look at the bit mask values in <net/ieee80211.h>
+
+ If you are not trying to debug or develop the ieee80211
+ subsystem, you most likely want to say N here.
+
+config IEEE80211_CRYPT_WEP
+ tristate "IEEE 802.11 WEP encryption (802.1x)"
+ depends on IEEE80211
+ select CRYPTO
+ select CRYPTO_ARC4
+ select CRC32
+ ---help---
+ Include software based cipher suites in support of IEEE
+ 802.11's WEP. This is needed for WEP as well as 802.1x.
+
+ This can be compiled as a modules and it will be called
+ "ieee80211_crypt_wep".
+
+config IEEE80211_CRYPT_CCMP
+ tristate "IEEE 802.11i CCMP support"
+ depends on IEEE80211
+ select CRYPTO
+ select CRYPTO_AES
+ ---help---
+ Include software based cipher suites in support of IEEE 802.11i
+ (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled
+ networks.
+
+ This can be compiled as a modules and it will be called
+ "ieee80211_crypt_ccmp".
+
+config IEEE80211_CRYPT_TKIP
+ tristate "IEEE 802.11i TKIP encryption"
+ depends on IEEE80211
+ select CRYPTO
+ select CRYPTO_MICHAEL_MIC
+ ---help---
+ Include software based cipher suites in support of IEEE 802.11i
+ (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
+ networks.
+
+ This can be compiled as a modules and it will be called
+ "ieee80211_crypt_tkip".
+
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
new file mode 100644
index 000000000000..a6ccac5baea8
--- /dev/null
+++ b/net/ieee80211/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_IEEE80211) += ieee80211.o
+obj-$(CONFIG_IEEE80211) += ieee80211_crypt.o
+obj-$(CONFIG_IEEE80211_CRYPT_WEP) += ieee80211_crypt_wep.o
+obj-$(CONFIG_IEEE80211_CRYPT_CCMP) += ieee80211_crypt_ccmp.o
+obj-$(CONFIG_IEEE80211_CRYPT_TKIP) += ieee80211_crypt_tkip.o
+ieee80211-objs := \
+ ieee80211_module.o \
+ ieee80211_tx.o \
+ ieee80211_rx.o \
+ ieee80211_wx.o
+
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
new file mode 100644
index 000000000000..61a9d92e455b
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -0,0 +1,258 @@
+/*
+ * Host AP crypto routines
+ *
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/string.h>
+#include <asm/errno.h>
+
+#include <net/ieee80211.h>
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("HostAP crypto");
+MODULE_LICENSE("GPL");
+
+struct ieee80211_crypto_alg {
+ struct list_head list;
+ struct ieee80211_crypto_ops *ops;
+};
+
+struct ieee80211_crypto {
+ struct list_head algs;
+ spinlock_t lock;
+};
+
+static struct ieee80211_crypto *hcrypt;
+
+void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
+{
+ struct list_head *ptr, *n;
+ struct ieee80211_crypt_data *entry;
+
+ for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
+ ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct ieee80211_crypt_data, list);
+
+ if (atomic_read(&entry->refcnt) != 0 && !force)
+ continue;
+
+ list_del(ptr);
+
+ if (entry->ops) {
+ entry->ops->deinit(entry->priv);
+ module_put(entry->ops->owner);
+ }
+ kfree(entry);
+ }
+}
+
+void ieee80211_crypt_deinit_handler(unsigned long data)
+{
+ struct ieee80211_device *ieee = (struct ieee80211_device *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+ ieee80211_crypt_deinit_entries(ieee, 0);
+ if (!list_empty(&ieee->crypt_deinit_list)) {
+ printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
+ "deletion list\n", ieee->dev->name);
+ ieee->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&ieee->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+}
+
+void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
+ struct ieee80211_crypt_data **crypt)
+{
+ struct ieee80211_crypt_data *tmp;
+ unsigned long flags;
+
+ if (*crypt == NULL)
+ return;
+
+ tmp = *crypt;
+ *crypt = NULL;
+
+ /* must not run ops->deinit() while there may be pending encrypt or
+ * decrypt operations. Use a list of delayed deinits to avoid needing
+ * locking. */
+
+ spin_lock_irqsave(&ieee->lock, flags);
+ list_add(&tmp->list, &ieee->crypt_deinit_list);
+ if (!timer_pending(&ieee->crypt_deinit_timer)) {
+ ieee->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&ieee->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
+{
+ unsigned long flags;
+ struct ieee80211_crypto_alg *alg;
+
+ if (hcrypt == NULL)
+ return -1;
+
+ alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+ if (alg == NULL)
+ return -ENOMEM;
+
+ memset(alg, 0, sizeof(*alg));
+ alg->ops = ops;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ list_add(&alg->list, &hcrypt->algs);
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
+ ops->name);
+
+ return 0;
+}
+
+int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct ieee80211_crypto_alg *del_alg = NULL;
+
+ if (hcrypt == NULL)
+ return -1;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+ struct ieee80211_crypto_alg *alg =
+ (struct ieee80211_crypto_alg *)ptr;
+ if (alg->ops == ops) {
+ list_del(&alg->list);
+ del_alg = alg;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ if (del_alg) {
+ printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
+ "'%s'\n", ops->name);
+ kfree(del_alg);
+ }
+
+ return del_alg ? 0 : -1;
+}
+
+struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct ieee80211_crypto_alg *found_alg = NULL;
+
+ if (hcrypt == NULL)
+ return NULL;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+ struct ieee80211_crypto_alg *alg =
+ (struct ieee80211_crypto_alg *)ptr;
+ if (strcmp(alg->ops->name, name) == 0) {
+ found_alg = alg;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ if (found_alg)
+ return found_alg->ops;
+ else
+ return NULL;
+}
+
+static void *ieee80211_crypt_null_init(int keyidx)
+{
+ return (void *)1;
+}
+static void ieee80211_crypt_null_deinit(void *priv)
+{
+}
+
+static struct ieee80211_crypto_ops ieee80211_crypt_null = {
+ .name = "NULL",
+ .init = ieee80211_crypt_null_init,
+ .deinit = ieee80211_crypt_null_deinit,
+ .encrypt_mpdu = NULL,
+ .decrypt_mpdu = NULL,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = NULL,
+ .get_key = NULL,
+ .extra_prefix_len = 0,
+ .extra_postfix_len = 0,
+ .owner = THIS_MODULE,
+};
+
+static int __init ieee80211_crypto_init(void)
+{
+ int ret = -ENOMEM;
+
+ hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
+ if (!hcrypt)
+ goto out;
+
+ memset(hcrypt, 0, sizeof(*hcrypt));
+ INIT_LIST_HEAD(&hcrypt->algs);
+ spin_lock_init(&hcrypt->lock);
+
+ ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
+ if (ret < 0) {
+ kfree(hcrypt);
+ hcrypt = NULL;
+ }
+ out:
+ return ret;
+}
+
+static void __exit ieee80211_crypto_deinit(void)
+{
+ struct list_head *ptr, *n;
+
+ if (hcrypt == NULL)
+ return;
+
+ for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
+ ptr = n, n = ptr->next) {
+ struct ieee80211_crypto_alg *alg =
+ (struct ieee80211_crypto_alg *)ptr;
+ list_del(ptr);
+ printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
+ "'%s' (deinit)\n", alg->ops->name);
+ kfree(alg);
+ }
+
+ kfree(hcrypt);
+}
+
+EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
+EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
+EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
+
+EXPORT_SYMBOL(ieee80211_register_crypto_ops);
+EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
+EXPORT_SYMBOL(ieee80211_get_crypto_ops);
+
+module_init(ieee80211_crypto_init);
+module_exit(ieee80211_crypto_deinit);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
new file mode 100644
index 000000000000..8fc13f45971e
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -0,0 +1,455 @@
+/*
+ * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <asm/string.h>
+#include <linux/wireless.h>
+
+#include <net/ieee80211.h>
+
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: CCMP");
+MODULE_LICENSE("GPL");
+
+#define AES_BLOCK_LEN 16
+#define CCMP_HDR_LEN 8
+#define CCMP_MIC_LEN 8
+#define CCMP_TK_LEN 16
+#define CCMP_PN_LEN 6
+
+struct ieee80211_ccmp_data {
+ u8 key[CCMP_TK_LEN];
+ int key_set;
+
+ u8 tx_pn[CCMP_PN_LEN];
+ u8 rx_pn[CCMP_PN_LEN];
+
+ u32 dot11RSNAStatsCCMPFormatErrors;
+ u32 dot11RSNAStatsCCMPReplays;
+ u32 dot11RSNAStatsCCMPDecryptErrors;
+
+ int key_idx;
+
+ struct crypto_tfm *tfm;
+
+ /* scratch buffers for virt_to_page() (crypto API) */
+ u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
+ tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
+ u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
+};
+
+static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
+ const u8 pt[16], u8 ct[16])
+{
+ struct scatterlist src, dst;
+
+ src.page = virt_to_page(pt);
+ src.offset = offset_in_page(pt);
+ src.length = AES_BLOCK_LEN;
+
+ dst.page = virt_to_page(ct);
+ dst.offset = offset_in_page(ct);
+ dst.length = AES_BLOCK_LEN;
+
+ crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
+}
+
+static void *ieee80211_ccmp_init(int key_idx)
+{
+ struct ieee80211_ccmp_data *priv;
+
+ priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ memset(priv, 0, sizeof(*priv));
+ priv->key_idx = key_idx;
+
+ priv->tfm = crypto_alloc_tfm("aes", 0);
+ if (priv->tfm == NULL) {
+ printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
+ "crypto API aes\n");
+ goto fail;
+ }
+
+ return priv;
+
+ fail:
+ if (priv) {
+ if (priv->tfm)
+ crypto_free_tfm(priv->tfm);
+ kfree(priv);
+ }
+
+ return NULL;
+}
+
+static void ieee80211_ccmp_deinit(void *priv)
+{
+ struct ieee80211_ccmp_data *_priv = priv;
+ if (_priv && _priv->tfm)
+ crypto_free_tfm(_priv->tfm);
+ kfree(priv);
+}
+
+static inline void xor_block(u8 * b, u8 * a, size_t len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ b[i] ^= a[i];
+}
+
+static void ccmp_init_blocks(struct crypto_tfm *tfm,
+ struct ieee80211_hdr *hdr,
+ u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
+{
+ u8 *pos, qc = 0;
+ size_t aad_len;
+ u16 fc;
+ int a4_included, qc_included;
+ u8 aad[2 * AES_BLOCK_LEN];
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
+ qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
+ (WLAN_FC_GET_STYPE(fc) & 0x08));
+ aad_len = 22;
+ if (a4_included)
+ aad_len += 6;
+ if (qc_included) {
+ pos = (u8 *) & hdr->addr4;
+ if (a4_included)
+ pos += 6;
+ qc = *pos & 0x0f;
+ aad_len += 2;
+ }
+
+ /* CCM Initial Block:
+ * Flag (Include authentication header, M=3 (8-octet MIC),
+ * L=1 (2-octet Dlen))
+ * Nonce: 0x00 | A2 | PN
+ * Dlen */
+ b0[0] = 0x59;
+ b0[1] = qc;
+ memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
+ memcpy(b0 + 8, pn, CCMP_PN_LEN);
+ b0[14] = (dlen >> 8) & 0xff;
+ b0[15] = dlen & 0xff;
+
+ /* AAD:
+ * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
+ * A1 | A2 | A3
+ * SC with bits 4..15 (seq#) masked to zero
+ * A4 (if present)
+ * QC (if present)
+ */
+ pos = (u8 *) hdr;
+ aad[0] = 0; /* aad_len >> 8 */
+ aad[1] = aad_len & 0xff;
+ aad[2] = pos[0] & 0x8f;
+ aad[3] = pos[1] & 0xc7;
+ memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
+ pos = (u8 *) & hdr->seq_ctl;
+ aad[22] = pos[0] & 0x0f;
+ aad[23] = 0; /* all bits masked */
+ memset(aad + 24, 0, 8);
+ if (a4_included)
+ memcpy(aad + 24, hdr->addr4, ETH_ALEN);
+ if (qc_included) {
+ aad[a4_included ? 30 : 24] = qc;
+ /* rest of QC masked */
+ }
+
+ /* Start with the first block and AAD */
+ ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
+ xor_block(auth, aad, AES_BLOCK_LEN);
+ ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
+ xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
+ ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
+ b0[0] &= 0x07;
+ b0[14] = b0[15] = 0;
+ ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
+}
+
+static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct ieee80211_ccmp_data *key = priv;
+ int data_len, i, blocks, last, len;
+ u8 *pos, *mic;
+ struct ieee80211_hdr *hdr;
+ u8 *b0 = key->tx_b0;
+ u8 *b = key->tx_b;
+ u8 *e = key->tx_e;
+ u8 *s0 = key->tx_s0;
+
+ if (skb_headroom(skb) < CCMP_HDR_LEN ||
+ skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+ return -1;
+
+ data_len = skb->len - hdr_len;
+ pos = skb_push(skb, CCMP_HDR_LEN);
+ memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
+ pos += hdr_len;
+ mic = skb_put(skb, CCMP_MIC_LEN);
+
+ i = CCMP_PN_LEN - 1;
+ while (i >= 0) {
+ key->tx_pn[i]++;
+ if (key->tx_pn[i] != 0)
+ break;
+ i--;
+ }
+
+ *pos++ = key->tx_pn[5];
+ *pos++ = key->tx_pn[4];
+ *pos++ = 0;
+ *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
+ *pos++ = key->tx_pn[3];
+ *pos++ = key->tx_pn[2];
+ *pos++ = key->tx_pn[1];
+ *pos++ = key->tx_pn[0];
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
+
+ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+ last = data_len % AES_BLOCK_LEN;
+
+ for (i = 1; i <= blocks; i++) {
+ len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+ /* Authentication */
+ xor_block(b, pos, len);
+ ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
+ /* Encryption, with counter */
+ b0[14] = (i >> 8) & 0xff;
+ b0[15] = i & 0xff;
+ ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
+ xor_block(pos, e, len);
+ pos += len;
+ }
+
+ for (i = 0; i < CCMP_MIC_LEN; i++)
+ mic[i] = b[i] ^ s0[i];
+
+ return 0;
+}
+
+static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct ieee80211_ccmp_data *key = priv;
+ u8 keyidx, *pos;
+ struct ieee80211_hdr *hdr;
+ u8 *b0 = key->rx_b0;
+ u8 *b = key->rx_b;
+ u8 *a = key->rx_a;
+ u8 pn[6];
+ int i, blocks, last, len;
+ size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
+ u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
+
+ if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
+ key->dot11RSNAStatsCCMPFormatErrors++;
+ return -1;
+ }
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ pos = skb->data + hdr_len;
+ keyidx = pos[3];
+ if (!(keyidx & (1 << 5))) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "CCMP: received packet without ExtIV"
+ " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ }
+ key->dot11RSNAStatsCCMPFormatErrors++;
+ return -2;
+ }
+ keyidx >>= 6;
+ if (key->key_idx != keyidx) {
+ printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
+ "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
+ return -6;
+ }
+ if (!key->key_set) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+ " with keyid=%d that does not have a configured"
+ " key\n", MAC_ARG(hdr->addr2), keyidx);
+ }
+ return -3;
+ }
+
+ pn[0] = pos[7];
+ pn[1] = pos[6];
+ pn[2] = pos[5];
+ pn[3] = pos[4];
+ pn[4] = pos[1];
+ pn[5] = pos[0];
+ pos += 8;
+
+ if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
+ " previous PN %02x%02x%02x%02x%02x%02x "
+ "received PN %02x%02x%02x%02x%02x%02x\n",
+ MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
+ MAC_ARG(pn));
+ }
+ key->dot11RSNAStatsCCMPReplays++;
+ return -4;
+ }
+
+ ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
+ xor_block(mic, b, CCMP_MIC_LEN);
+
+ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+ last = data_len % AES_BLOCK_LEN;
+
+ for (i = 1; i <= blocks; i++) {
+ len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+ /* Decrypt, with counter */
+ b0[14] = (i >> 8) & 0xff;
+ b0[15] = i & 0xff;
+ ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
+ xor_block(pos, b, len);
+ /* Authentication */
+ xor_block(a, pos, len);
+ ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
+ pos += len;
+ }
+
+ if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "CCMP: decrypt failed: STA="
+ MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ }
+ key->dot11RSNAStatsCCMPDecryptErrors++;
+ return -5;
+ }
+
+ memcpy(key->rx_pn, pn, CCMP_PN_LEN);
+
+ /* Remove hdr and MIC */
+ memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
+ skb_pull(skb, CCMP_HDR_LEN);
+ skb_trim(skb, skb->len - CCMP_MIC_LEN);
+
+ return keyidx;
+}
+
+static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct ieee80211_ccmp_data *data = priv;
+ int keyidx;
+ struct crypto_tfm *tfm = data->tfm;
+
+ keyidx = data->key_idx;
+ memset(data, 0, sizeof(*data));
+ data->key_idx = keyidx;
+ data->tfm = tfm;
+ if (len == CCMP_TK_LEN) {
+ memcpy(data->key, key, CCMP_TK_LEN);
+ data->key_set = 1;
+ if (seq) {
+ data->rx_pn[0] = seq[5];
+ data->rx_pn[1] = seq[4];
+ data->rx_pn[2] = seq[3];
+ data->rx_pn[3] = seq[2];
+ data->rx_pn[4] = seq[1];
+ data->rx_pn[5] = seq[0];
+ }
+ crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
+ } else if (len == 0)
+ data->key_set = 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct ieee80211_ccmp_data *data = priv;
+
+ if (len < CCMP_TK_LEN)
+ return -1;
+
+ if (!data->key_set)
+ return 0;
+ memcpy(key, data->key, CCMP_TK_LEN);
+
+ if (seq) {
+ seq[0] = data->tx_pn[5];
+ seq[1] = data->tx_pn[4];
+ seq[2] = data->tx_pn[3];
+ seq[3] = data->tx_pn[2];
+ seq[4] = data->tx_pn[1];
+ seq[5] = data->tx_pn[0];
+ }
+
+ return CCMP_TK_LEN;
+}
+
+static char *ieee80211_ccmp_print_stats(char *p, void *priv)
+{
+ struct ieee80211_ccmp_data *ccmp = priv;
+ p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
+ "tx_pn=%02x%02x%02x%02x%02x%02x "
+ "rx_pn=%02x%02x%02x%02x%02x%02x "
+ "format_errors=%d replays=%d decrypt_errors=%d\n",
+ ccmp->key_idx, ccmp->key_set,
+ MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+ ccmp->dot11RSNAStatsCCMPFormatErrors,
+ ccmp->dot11RSNAStatsCCMPReplays,
+ ccmp->dot11RSNAStatsCCMPDecryptErrors);
+
+ return p;
+}
+
+static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
+ .name = "CCMP",
+ .init = ieee80211_ccmp_init,
+ .deinit = ieee80211_ccmp_deinit,
+ .encrypt_mpdu = ieee80211_ccmp_encrypt,
+ .decrypt_mpdu = ieee80211_ccmp_decrypt,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = ieee80211_ccmp_set_key,
+ .get_key = ieee80211_ccmp_get_key,
+ .print_stats = ieee80211_ccmp_print_stats,
+ .extra_prefix_len = CCMP_HDR_LEN,
+ .extra_postfix_len = CCMP_MIC_LEN,
+ .owner = THIS_MODULE,
+};
+
+static int __init ieee80211_crypto_ccmp_init(void)
+{
+ return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
+}
+
+static void __exit ieee80211_crypto_ccmp_exit(void)
+{
+ ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
+}
+
+module_init(ieee80211_crypto_ccmp_init);
+module_exit(ieee80211_crypto_ccmp_exit);
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
new file mode 100644
index 000000000000..d4f9164be1a1
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -0,0 +1,683 @@
+/*
+ * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <asm/string.h>
+
+#include <net/ieee80211.h>
+
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+#include <linux/crc32.h>
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: TKIP");
+MODULE_LICENSE("GPL");
+
+struct ieee80211_tkip_data {
+#define TKIP_KEY_LEN 32
+ u8 key[TKIP_KEY_LEN];
+ int key_set;
+
+ u32 tx_iv32;
+ u16 tx_iv16;
+ u16 tx_ttak[5];
+ int tx_phase1_done;
+
+ u32 rx_iv32;
+ u16 rx_iv16;
+ u16 rx_ttak[5];
+ int rx_phase1_done;
+ u32 rx_iv32_new;
+ u16 rx_iv16_new;
+
+ u32 dot11RSNAStatsTKIPReplays;
+ u32 dot11RSNAStatsTKIPICVErrors;
+ u32 dot11RSNAStatsTKIPLocalMICFailures;
+
+ int key_idx;
+
+ struct crypto_tfm *tfm_arc4;
+ struct crypto_tfm *tfm_michael;
+
+ /* scratch buffers for virt_to_page() (crypto API) */
+ u8 rx_hdr[16], tx_hdr[16];
+};
+
+static void *ieee80211_tkip_init(int key_idx)
+{
+ struct ieee80211_tkip_data *priv;
+
+ priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ memset(priv, 0, sizeof(*priv));
+ priv->key_idx = key_idx;
+
+ priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
+ if (priv->tfm_arc4 == NULL) {
+ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
+ "crypto API arc4\n");
+ goto fail;
+ }
+
+ priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
+ if (priv->tfm_michael == NULL) {
+ printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
+ "crypto API michael_mic\n");
+ goto fail;
+ }
+
+ return priv;
+
+ fail:
+ if (priv) {
+ if (priv->tfm_michael)
+ crypto_free_tfm(priv->tfm_michael);
+ if (priv->tfm_arc4)
+ crypto_free_tfm(priv->tfm_arc4);
+ kfree(priv);
+ }
+
+ return NULL;
+}
+
+static void ieee80211_tkip_deinit(void *priv)
+{
+ struct ieee80211_tkip_data *_priv = priv;
+ if (_priv && _priv->tfm_michael)
+ crypto_free_tfm(_priv->tfm_michael);
+ if (_priv && _priv->tfm_arc4)
+ crypto_free_tfm(_priv->tfm_arc4);
+ kfree(priv);
+}
+
+static inline u16 RotR1(u16 val)
+{
+ return (val >> 1) | (val << 15);
+}
+
+static inline u8 Lo8(u16 val)
+{
+ return val & 0xff;
+}
+
+static inline u8 Hi8(u16 val)
+{
+ return val >> 8;
+}
+
+static inline u16 Lo16(u32 val)
+{
+ return val & 0xffff;
+}
+
+static inline u16 Hi16(u32 val)
+{
+ return val >> 16;
+}
+
+static inline u16 Mk16(u8 hi, u8 lo)
+{
+ return lo | (((u16) hi) << 8);
+}
+
+static inline u16 Mk16_le(u16 * v)
+{
+ return le16_to_cpu(*v);
+}
+
+static const u16 Sbox[256] = {
+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+static inline u16 _S_(u16 v)
+{
+ u16 t = Sbox[Hi8(v)];
+ return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
+}
+
+#define PHASE1_LOOP_COUNT 8
+
+static void tkip_mixing_phase1(u16 * TTAK, const u8 * TK, const u8 * TA,
+ u32 IV32)
+{
+ int i, j;
+
+ /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
+ TTAK[0] = Lo16(IV32);
+ TTAK[1] = Hi16(IV32);
+ TTAK[2] = Mk16(TA[1], TA[0]);
+ TTAK[3] = Mk16(TA[3], TA[2]);
+ TTAK[4] = Mk16(TA[5], TA[4]);
+
+ for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
+ j = 2 * (i & 1);
+ TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
+ TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
+ TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
+ TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
+ TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
+ }
+}
+
+static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
+ u16 IV16)
+{
+ /* Make temporary area overlap WEP seed so that the final copy can be
+ * avoided on little endian hosts. */
+ u16 *PPK = (u16 *) & WEPSeed[4];
+
+ /* Step 1 - make copy of TTAK and bring in TSC */
+ PPK[0] = TTAK[0];
+ PPK[1] = TTAK[1];
+ PPK[2] = TTAK[2];
+ PPK[3] = TTAK[3];
+ PPK[4] = TTAK[4];
+ PPK[5] = TTAK[4] + IV16;
+
+ /* Step 2 - 96-bit bijective mixing using S-box */
+ PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) & TK[0]));
+ PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) & TK[2]));
+ PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) & TK[4]));
+ PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) & TK[6]));
+ PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) & TK[8]));
+ PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) & TK[10]));
+
+ PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) & TK[12]));
+ PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) & TK[14]));
+ PPK[2] += RotR1(PPK[1]);
+ PPK[3] += RotR1(PPK[2]);
+ PPK[4] += RotR1(PPK[3]);
+ PPK[5] += RotR1(PPK[4]);
+
+ /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
+ * WEPSeed[0..2] is transmitted as WEP IV */
+ WEPSeed[0] = Hi8(IV16);
+ WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
+ WEPSeed[2] = Lo8(IV16);
+ WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) & TK[0])) >> 1);
+
+#ifdef __BIG_ENDIAN
+ {
+ int i;
+ for (i = 0; i < 6; i++)
+ PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
+ }
+#endif
+}
+
+static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+ int len;
+ u8 rc4key[16], *pos, *icv;
+ struct ieee80211_hdr *hdr;
+ u32 crc;
+ struct scatterlist sg;
+
+ if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
+ skb->len < hdr_len)
+ return -1;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (!tkey->tx_phase1_done) {
+ tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
+ tkey->tx_iv32);
+ tkey->tx_phase1_done = 1;
+ }
+ tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
+
+ len = skb->len - hdr_len;
+ pos = skb_push(skb, 8);
+ memmove(pos, pos + 8, hdr_len);
+ pos += hdr_len;
+ icv = skb_put(skb, 4);
+
+ *pos++ = rc4key[0];
+ *pos++ = rc4key[1];
+ *pos++ = rc4key[2];
+ *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
+ *pos++ = tkey->tx_iv32 & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
+
+ crc = ~crc32_le(~0, pos, len);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
+ sg.page = virt_to_page(pos);
+ sg.offset = offset_in_page(pos);
+ sg.length = len + 4;
+ crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
+
+ tkey->tx_iv16++;
+ if (tkey->tx_iv16 == 0) {
+ tkey->tx_phase1_done = 0;
+ tkey->tx_iv32++;
+ }
+
+ return 0;
+}
+
+static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+ u8 rc4key[16];
+ u8 keyidx, *pos;
+ u32 iv32;
+ u16 iv16;
+ struct ieee80211_hdr *hdr;
+ u8 icv[4];
+ u32 crc;
+ struct scatterlist sg;
+ int plen;
+
+ if (skb->len < hdr_len + 8 + 4)
+ return -1;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ pos = skb->data + hdr_len;
+ keyidx = pos[3];
+ if (!(keyidx & (1 << 5))) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "TKIP: received packet without ExtIV"
+ " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ }
+ return -2;
+ }
+ keyidx >>= 6;
+ if (tkey->key_idx != keyidx) {
+ printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
+ "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
+ return -6;
+ }
+ if (!tkey->key_set) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+ " with keyid=%d that does not have a configured"
+ " key\n", MAC_ARG(hdr->addr2), keyidx);
+ }
+ return -3;
+ }
+ iv16 = (pos[0] << 8) | pos[2];
+ iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+ pos += 8;
+
+ if (iv32 < tkey->rx_iv32 ||
+ (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+ " previous TSC %08x%04x received TSC "
+ "%08x%04x\n", MAC_ARG(hdr->addr2),
+ tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
+ }
+ tkey->dot11RSNAStatsTKIPReplays++;
+ return -4;
+ }
+
+ if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
+ tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
+ tkey->rx_phase1_done = 1;
+ }
+ tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
+
+ plen = skb->len - hdr_len - 12;
+
+ crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
+ sg.page = virt_to_page(pos);
+ sg.offset = offset_in_page(pos);
+ sg.length = plen + 4;
+ crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
+
+ crc = ~crc32_le(~0, pos, plen);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+ if (memcmp(icv, pos + plen, 4) != 0) {
+ if (iv32 != tkey->rx_iv32) {
+ /* Previously cached Phase1 result was already lost, so
+ * it needs to be recalculated for the next packet. */
+ tkey->rx_phase1_done = 0;
+ }
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "TKIP: ICV error detected: STA="
+ MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ }
+ tkey->dot11RSNAStatsTKIPICVErrors++;
+ return -5;
+ }
+
+ /* Update real counters only after Michael MIC verification has
+ * completed */
+ tkey->rx_iv32_new = iv32;
+ tkey->rx_iv16_new = iv16;
+
+ /* Remove IV and ICV */
+ memmove(skb->data + 8, skb->data, hdr_len);
+ skb_pull(skb, 8);
+ skb_trim(skb, skb->len - 4);
+
+ return keyidx;
+}
+
+static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
+ u8 * data, size_t data_len, u8 * mic)
+{
+ struct scatterlist sg[2];
+
+ if (tkey->tfm_michael == NULL) {
+ printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
+ return -1;
+ }
+ sg[0].page = virt_to_page(hdr);
+ sg[0].offset = offset_in_page(hdr);
+ sg[0].length = 16;
+
+ sg[1].page = virt_to_page(data);
+ sg[1].offset = offset_in_page(data);
+ sg[1].length = data_len;
+
+ crypto_digest_init(tkey->tfm_michael);
+ crypto_digest_setkey(tkey->tfm_michael, key, 8);
+ crypto_digest_update(tkey->tfm_michael, sg, 2);
+ crypto_digest_final(tkey->tfm_michael, mic);
+
+ return 0;
+}
+
+static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
+{
+ struct ieee80211_hdr *hdr11;
+
+ hdr11 = (struct ieee80211_hdr *)skb->data;
+ switch (le16_to_cpu(hdr11->frame_ctl) &
+ (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case IEEE80211_FCTL_TODS:
+ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+ break;
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
+ break;
+ case 0:
+ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+ break;
+ }
+
+ hdr[12] = 0; /* priority */
+ hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
+}
+
+static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
+ void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+ u8 *pos;
+
+ if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
+ printk(KERN_DEBUG "Invalid packet for Michael MIC add "
+ "(tailroom=%d hdr_len=%d skb->len=%d)\n",
+ skb_tailroom(skb), hdr_len, skb->len);
+ return -1;
+ }
+
+ michael_mic_hdr(skb, tkey->tx_hdr);
+ pos = skb_put(skb, 8);
+ if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
+ return -1;
+
+ return 0;
+}
+
+#if WIRELESS_EXT >= 18
+static void ieee80211_michael_mic_failure(struct net_device *dev,
+ struct ieee80211_hdr *hdr, int keyidx)
+{
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure ev;
+
+ /* TODO: needed parameters: count, keyid, key type, TSC */
+ memset(&ev, 0, sizeof(ev));
+ ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
+ if (hdr->addr1[0] & 0x01)
+ ev.flags |= IW_MICFAILURE_GROUP;
+ else
+ ev.flags |= IW_MICFAILURE_PAIRWISE;
+ ev.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(ev);
+ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
+}
+#elif WIRELESS_EXT >= 15
+static void ieee80211_michael_mic_failure(struct net_device *dev,
+ struct ieee80211_hdr *hdr, int keyidx)
+{
+ union iwreq_data wrqu;
+ char buf[128];
+
+ /* TODO: needed parameters: count, keyid, key type, TSC */
+ sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
+ MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+ MAC_ARG(hdr->addr2));
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+}
+#else /* WIRELESS_EXT >= 15 */
+static inline void ieee80211_michael_mic_failure(struct net_device *dev,
+ struct ieee80211_hdr *hdr,
+ int keyidx)
+{
+}
+#endif /* WIRELESS_EXT >= 15 */
+
+static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
+ int hdr_len, void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+ u8 mic[8];
+
+ if (!tkey->key_set)
+ return -1;
+
+ michael_mic_hdr(skb, tkey->rx_hdr);
+ if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
+ return -1;
+ if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
+ struct ieee80211_hdr *hdr;
+ hdr = (struct ieee80211_hdr *)skb->data;
+ printk(KERN_DEBUG "%s: Michael MIC verification failed for "
+ "MSDU from " MAC_FMT " keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+ keyidx);
+ if (skb->dev)
+ ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
+ tkey->dot11RSNAStatsTKIPLocalMICFailures++;
+ return -1;
+ }
+
+ /* Update TSC counters for RX now that the packet verification has
+ * completed. */
+ tkey->rx_iv32 = tkey->rx_iv32_new;
+ tkey->rx_iv16 = tkey->rx_iv16_new;
+
+ skb_trim(skb, skb->len - 8);
+
+ return 0;
+}
+
+static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+ int keyidx;
+ struct crypto_tfm *tfm = tkey->tfm_michael;
+ struct crypto_tfm *tfm2 = tkey->tfm_arc4;
+
+ keyidx = tkey->key_idx;
+ memset(tkey, 0, sizeof(*tkey));
+ tkey->key_idx = keyidx;
+ tkey->tfm_michael = tfm;
+ tkey->tfm_arc4 = tfm2;
+ if (len == TKIP_KEY_LEN) {
+ memcpy(tkey->key, key, TKIP_KEY_LEN);
+ tkey->key_set = 1;
+ tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
+ if (seq) {
+ tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
+ (seq[3] << 8) | seq[2];
+ tkey->rx_iv16 = (seq[1] << 8) | seq[0];
+ }
+ } else if (len == 0)
+ tkey->key_set = 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct ieee80211_tkip_data *tkey = priv;
+
+ if (len < TKIP_KEY_LEN)
+ return -1;
+
+ if (!tkey->key_set)
+ return 0;
+ memcpy(key, tkey->key, TKIP_KEY_LEN);
+
+ if (seq) {
+ /* Return the sequence number of the last transmitted frame. */
+ u16 iv16 = tkey->tx_iv16;
+ u32 iv32 = tkey->tx_iv32;
+ if (iv16 == 0)
+ iv32--;
+ iv16--;
+ seq[0] = tkey->tx_iv16;
+ seq[1] = tkey->tx_iv16 >> 8;
+ seq[2] = tkey->tx_iv32;
+ seq[3] = tkey->tx_iv32 >> 8;
+ seq[4] = tkey->tx_iv32 >> 16;
+ seq[5] = tkey->tx_iv32 >> 24;
+ }
+
+ return TKIP_KEY_LEN;
+}
+
+static char *ieee80211_tkip_print_stats(char *p, void *priv)
+{
+ struct ieee80211_tkip_data *tkip = priv;
+ p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
+ "tx_pn=%02x%02x%02x%02x%02x%02x "
+ "rx_pn=%02x%02x%02x%02x%02x%02x "
+ "replays=%d icv_errors=%d local_mic_failures=%d\n",
+ tkip->key_idx, tkip->key_set,
+ (tkip->tx_iv32 >> 24) & 0xff,
+ (tkip->tx_iv32 >> 16) & 0xff,
+ (tkip->tx_iv32 >> 8) & 0xff,
+ tkip->tx_iv32 & 0xff,
+ (tkip->tx_iv16 >> 8) & 0xff,
+ tkip->tx_iv16 & 0xff,
+ (tkip->rx_iv32 >> 24) & 0xff,
+ (tkip->rx_iv32 >> 16) & 0xff,
+ (tkip->rx_iv32 >> 8) & 0xff,
+ tkip->rx_iv32 & 0xff,
+ (tkip->rx_iv16 >> 8) & 0xff,
+ tkip->rx_iv16 & 0xff,
+ tkip->dot11RSNAStatsTKIPReplays,
+ tkip->dot11RSNAStatsTKIPICVErrors,
+ tkip->dot11RSNAStatsTKIPLocalMICFailures);
+ return p;
+}
+
+static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
+ .name = "TKIP",
+ .init = ieee80211_tkip_init,
+ .deinit = ieee80211_tkip_deinit,
+ .encrypt_mpdu = ieee80211_tkip_encrypt,
+ .decrypt_mpdu = ieee80211_tkip_decrypt,
+ .encrypt_msdu = ieee80211_michael_mic_add,
+ .decrypt_msdu = ieee80211_michael_mic_verify,
+ .set_key = ieee80211_tkip_set_key,
+ .get_key = ieee80211_tkip_get_key,
+ .print_stats = ieee80211_tkip_print_stats,
+ .extra_prefix_len = 4 + 4, /* IV + ExtIV */
+ .extra_postfix_len = 8 + 4, /* MIC + ICV */
+ .owner = THIS_MODULE,
+};
+
+static int __init ieee80211_crypto_tkip_init(void)
+{
+ return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
+}
+
+static void __exit ieee80211_crypto_tkip_exit(void)
+{
+ ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
+}
+
+module_init(ieee80211_crypto_tkip_init);
+module_exit(ieee80211_crypto_tkip_exit);
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
new file mode 100644
index 000000000000..b4d2514a0902
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -0,0 +1,258 @@
+/*
+ * Host AP crypt: host-based WEP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <asm/string.h>
+
+#include <net/ieee80211.h>
+
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+#include <linux/crc32.h>
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: WEP");
+MODULE_LICENSE("GPL");
+
+struct prism2_wep_data {
+ u32 iv;
+#define WEP_KEY_LEN 13
+ u8 key[WEP_KEY_LEN + 1];
+ u8 key_len;
+ u8 key_idx;
+ struct crypto_tfm *tfm;
+};
+
+static void *prism2_wep_init(int keyidx)
+{
+ struct prism2_wep_data *priv;
+
+ priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ memset(priv, 0, sizeof(*priv));
+ priv->key_idx = keyidx;
+
+ priv->tfm = crypto_alloc_tfm("arc4", 0);
+ if (priv->tfm == NULL) {
+ printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
+ "crypto API arc4\n");
+ goto fail;
+ }
+
+ /* start WEP IV from a random value */
+ get_random_bytes(&priv->iv, 4);
+
+ return priv;
+
+ fail:
+ if (priv) {
+ if (priv->tfm)
+ crypto_free_tfm(priv->tfm);
+ kfree(priv);
+ }
+ return NULL;
+}
+
+static void prism2_wep_deinit(void *priv)
+{
+ struct prism2_wep_data *_priv = priv;
+ if (_priv && _priv->tfm)
+ crypto_free_tfm(_priv->tfm);
+ kfree(priv);
+}
+
+/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
+ * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
+ * so the payload length increases with 8 bytes.
+ *
+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
+ */
+static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+ u32 crc, klen, len;
+ u8 key[WEP_KEY_LEN + 3];
+ u8 *pos, *icv;
+ struct scatterlist sg;
+
+ if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
+ skb->len < hdr_len)
+ return -1;
+
+ len = skb->len - hdr_len;
+ pos = skb_push(skb, 4);
+ memmove(pos, pos + 4, hdr_len);
+ pos += hdr_len;
+
+ klen = 3 + wep->key_len;
+
+ wep->iv++;
+
+ /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
+ * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
+ * can be used to speedup attacks, so avoid using them. */
+ if ((wep->iv & 0xff00) == 0xff00) {
+ u8 B = (wep->iv >> 16) & 0xff;
+ if (B >= 3 && B < klen)
+ wep->iv += 0x0100;
+ }
+
+ /* Prepend 24-bit IV to RC4 key and TX frame */
+ *pos++ = key[0] = (wep->iv >> 16) & 0xff;
+ *pos++ = key[1] = (wep->iv >> 8) & 0xff;
+ *pos++ = key[2] = wep->iv & 0xff;
+ *pos++ = wep->key_idx << 6;
+
+ /* Copy rest of the WEP key (the secret part) */
+ memcpy(key + 3, wep->key, wep->key_len);
+
+ /* Append little-endian CRC32 and encrypt it to produce ICV */
+ crc = ~crc32_le(~0, pos, len);
+ icv = skb_put(skb, 4);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ crypto_cipher_setkey(wep->tfm, key, klen);
+ sg.page = virt_to_page(pos);
+ sg.offset = offset_in_page(pos);
+ sg.length = len + 4;
+ crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
+
+ return 0;
+}
+
+/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
+ * the frame: IV (4 bytes), encrypted payload (including SNAP header),
+ * ICV (4 bytes). len includes both IV and ICV.
+ *
+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
+ * failure. If frame is OK, IV and ICV will be removed.
+ */
+static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+ u32 crc, klen, plen;
+ u8 key[WEP_KEY_LEN + 3];
+ u8 keyidx, *pos, icv[4];
+ struct scatterlist sg;
+
+ if (skb->len < hdr_len + 8)
+ return -1;
+
+ pos = skb->data + hdr_len;
+ key[0] = *pos++;
+ key[1] = *pos++;
+ key[2] = *pos++;
+ keyidx = *pos++ >> 6;
+ if (keyidx != wep->key_idx)
+ return -1;
+
+ klen = 3 + wep->key_len;
+
+ /* Copy rest of the WEP key (the secret part) */
+ memcpy(key + 3, wep->key, wep->key_len);
+
+ /* Apply RC4 to data and compute CRC32 over decrypted data */
+ plen = skb->len - hdr_len - 8;
+
+ crypto_cipher_setkey(wep->tfm, key, klen);
+ sg.page = virt_to_page(pos);
+ sg.offset = offset_in_page(pos);
+ sg.length = plen + 4;
+ crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
+
+ crc = ~crc32_le(~0, pos, plen);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+ if (memcmp(icv, pos + plen, 4) != 0) {
+ /* ICV mismatch - drop frame */
+ return -2;
+ }
+
+ /* Remove IV and ICV */
+ memmove(skb->data + 4, skb->data, hdr_len);
+ skb_pull(skb, 4);
+ skb_trim(skb, skb->len - 4);
+
+ return 0;
+}
+
+static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+
+ if (len < 0 || len > WEP_KEY_LEN)
+ return -1;
+
+ memcpy(wep->key, key, len);
+ wep->key_len = len;
+
+ return 0;
+}
+
+static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+
+ if (len < wep->key_len)
+ return -1;
+
+ memcpy(key, wep->key, wep->key_len);
+
+ return wep->key_len;
+}
+
+static char *prism2_wep_print_stats(char *p, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+ p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
+ return p;
+}
+
+static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
+ .name = "WEP",
+ .init = prism2_wep_init,
+ .deinit = prism2_wep_deinit,
+ .encrypt_mpdu = prism2_wep_encrypt,
+ .decrypt_mpdu = prism2_wep_decrypt,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = prism2_wep_set_key,
+ .get_key = prism2_wep_get_key,
+ .print_stats = prism2_wep_print_stats,
+ .extra_prefix_len = 4, /* IV */
+ .extra_postfix_len = 4, /* ICV */
+ .owner = THIS_MODULE,
+};
+
+static int __init ieee80211_crypto_wep_init(void)
+{
+ return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
+}
+
+static void __exit ieee80211_crypto_wep_exit(void)
+{
+ ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
+}
+
+module_init(ieee80211_crypto_wep_init);
+module_exit(ieee80211_crypto_wep_exit);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
new file mode 100644
index 000000000000..03a47343ddc7
--- /dev/null
+++ b/net/ieee80211/ieee80211_module.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+
+ Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <net/arp.h>
+
+#include <net/ieee80211.h>
+
+MODULE_DESCRIPTION("802.11 data/management/control stack");
+MODULE_AUTHOR
+ ("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
+MODULE_LICENSE("GPL");
+
+#define DRV_NAME "ieee80211"
+
+static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
+{
+ if (ieee->networks)
+ return 0;
+
+ ieee->networks =
+ kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
+ GFP_KERNEL);
+ if (!ieee->networks) {
+ printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
+ ieee->dev->name);
+ return -ENOMEM;
+ }
+
+ memset(ieee->networks, 0,
+ MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
+
+ return 0;
+}
+
+static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
+{
+ if (!ieee->networks)
+ return;
+ kfree(ieee->networks);
+ ieee->networks = NULL;
+}
+
+static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
+{
+ int i;
+
+ INIT_LIST_HEAD(&ieee->network_free_list);
+ INIT_LIST_HEAD(&ieee->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ list_add_tail(&ieee->networks[i].list,
+ &ieee->network_free_list);
+}
+
+struct net_device *alloc_ieee80211(int sizeof_priv)
+{
+ struct ieee80211_device *ieee;
+ struct net_device *dev;
+ int err;
+
+ IEEE80211_DEBUG_INFO("Initializing...\n");
+
+ dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
+ if (!dev) {
+ IEEE80211_ERROR("Unable to network device.\n");
+ goto failed;
+ }
+ ieee = netdev_priv(dev);
+ dev->hard_start_xmit = ieee80211_xmit;
+
+ ieee->dev = dev;
+
+ err = ieee80211_networks_allocate(ieee);
+ if (err) {
+ IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
+ goto failed;
+ }
+ ieee80211_networks_initialize(ieee);
+
+ /* Default fragmentation threshold is maximum payload size */
+ ieee->fts = DEFAULT_FTS;
+ ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
+ ieee->open_wep = 1;
+
+ /* Default to enabling full open WEP with host based encrypt/decrypt */
+ ieee->host_encrypt = 1;
+ ieee->host_decrypt = 1;
+ ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
+
+ INIT_LIST_HEAD(&ieee->crypt_deinit_list);
+ init_timer(&ieee->crypt_deinit_timer);
+ ieee->crypt_deinit_timer.data = (unsigned long)ieee;
+ ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
+
+ spin_lock_init(&ieee->lock);
+
+ ieee->wpa_enabled = 0;
+ ieee->tkip_countermeasures = 0;
+ ieee->drop_unencrypted = 0;
+ ieee->privacy_invoked = 0;
+ ieee->ieee802_1x = 1;
+
+ return dev;
+
+ failed:
+ if (dev)
+ free_netdev(dev);
+ return NULL;
+}
+
+void free_ieee80211(struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+
+ int i;
+
+ del_timer_sync(&ieee->crypt_deinit_timer);
+ ieee80211_crypt_deinit_entries(ieee, 1);
+
+ for (i = 0; i < WEP_KEYS; i++) {
+ struct ieee80211_crypt_data *crypt = ieee->crypt[i];
+ if (crypt) {
+ if (crypt->ops) {
+ crypt->ops->deinit(crypt->priv);
+ module_put(crypt->ops->owner);
+ }
+ kfree(crypt);
+ ieee->crypt[i] = NULL;
+ }
+ }
+
+ ieee80211_networks_free(ieee);
+ free_netdev(dev);
+}
+
+#ifdef CONFIG_IEEE80211_DEBUG
+
+static int debug = 0;
+u32 ieee80211_debug_level = 0;
+struct proc_dir_entry *ieee80211_proc = NULL;
+
+static int show_debug_level(char *page, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
+}
+
+static int store_debug_level(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
+{
+ char buf[] = "0x00000000";
+ char *p = (char *)buf;
+ unsigned long val;
+
+ if (count > sizeof(buf) - 1)
+ count = sizeof(buf) - 1;
+
+ if (copy_from_user(buf, buffer, count))
+ return count;
+ buf[count] = 0;
+ /*
+ * what a FPOS... What, sscanf(buf, "%i", &val) would be too
+ * scary?
+ */
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buf)
+ printk(KERN_INFO DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ieee80211_debug_level = val;
+
+ return strlen(buf);
+}
+
+static int __init ieee80211_init(void)
+{
+ struct proc_dir_entry *e;
+
+ ieee80211_debug_level = debug;
+ ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
+ if (ieee80211_proc == NULL) {
+ IEEE80211_ERROR("Unable to create " DRV_NAME
+ " proc directory\n");
+ return -EIO;
+ }
+ e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
+ ieee80211_proc);
+ if (!e) {
+ remove_proc_entry(DRV_NAME, proc_net);
+ ieee80211_proc = NULL;
+ return -EIO;
+ }
+ e->read_proc = show_debug_level;
+ e->write_proc = store_debug_level;
+ e->data = NULL;
+
+ return 0;
+}
+
+static void __exit ieee80211_exit(void)
+{
+ if (ieee80211_proc) {
+ remove_proc_entry("debug_level", ieee80211_proc);
+ remove_proc_entry(DRV_NAME, proc_net);
+ ieee80211_proc = NULL;
+ }
+}
+
+#include <linux/moduleparam.h>
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "debug output mask");
+
+module_exit(ieee80211_exit);
+module_init(ieee80211_init);
+#endif
+
+const char *escape_essid(const char *essid, u8 essid_len)
+{
+ static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+ const char *s = essid;
+ char *d = escaped;
+
+ if (ieee80211_is_empty_essid(essid, essid_len)) {
+ memcpy(escaped, "<hidden>", sizeof("<hidden>"));
+ return escaped;
+ }
+
+ essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
+ while (essid_len--) {
+ if (*s == '\0') {
+ *d++ = '\\';
+ *d++ = '0';
+ s++;
+ } else {
+ *d++ = *s++;
+ }
+ }
+ *d = '\0';
+ return escaped;
+}
+
+EXPORT_SYMBOL(alloc_ieee80211);
+EXPORT_SYMBOL(free_ieee80211);
+EXPORT_SYMBOL(escape_essid);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
new file mode 100644
index 000000000000..f7dcd854139e
--- /dev/null
+++ b/net/ieee80211/ieee80211_rx.c
@@ -0,0 +1,1193 @@
+/*
+ * Original code based Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
+
+#include <net/ieee80211.h>
+
+static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
+ struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+
+ skb->dev = ieee->dev;
+ skb->mac.raw = skb->data;
+ skb_pull(skb, ieee80211_get_hdrlen(fc));
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = __constant_htons(ETH_P_80211_RAW);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
+ ieee80211_device
+ *ieee,
+ unsigned int seq,
+ unsigned int frag,
+ u8 * src,
+ u8 * dst)
+{
+ struct ieee80211_frag_entry *entry;
+ int i;
+
+ for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
+ entry = &ieee->frag_cache[i];
+ if (entry->skb != NULL &&
+ time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ IEEE80211_DEBUG_FRAG("expiring fragment cache entry "
+ "seq=%u last_frag=%u\n",
+ entry->seq, entry->last_frag);
+ dev_kfree_skb_any(entry->skb);
+ entry->skb = NULL;
+ }
+
+ if (entry->skb != NULL && entry->seq == seq &&
+ (entry->last_frag + 1 == frag || frag == -1) &&
+ memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
+ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
+ return entry;
+ }
+
+ return NULL;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
+ struct ieee80211_hdr *hdr)
+{
+ struct sk_buff *skb = NULL;
+ u16 sc;
+ unsigned int frag, seq;
+ struct ieee80211_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ seq = WLAN_GET_SEQ_SEQ(sc);
+
+ if (frag == 0) {
+ /* Reserve enough space to fit maximum frame length */
+ skb = dev_alloc_skb(ieee->dev->mtu +
+ sizeof(struct ieee80211_hdr) +
+ 8 /* LLC */ +
+ 2 /* alignment */ +
+ 8 /* WEP */ + ETH_ALEN /* WDS */ );
+ if (skb == NULL)
+ return NULL;
+
+ entry = &ieee->frag_cache[ieee->frag_next_idx];
+ ieee->frag_next_idx++;
+ if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN)
+ ieee->frag_next_idx = 0;
+
+ if (entry->skb != NULL)
+ dev_kfree_skb_any(entry->skb);
+
+ entry->first_frag_time = jiffies;
+ entry->seq = seq;
+ entry->last_frag = frag;
+ entry->skb = skb;
+ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+ } else {
+ /* received a fragment of a frame for which the head fragment
+ * should have already been received */
+ entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2,
+ hdr->addr1);
+ if (entry != NULL) {
+ entry->last_frag = frag;
+ skb = entry->skb;
+ }
+ }
+
+ return skb;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
+ struct ieee80211_hdr *hdr)
+{
+ u16 sc;
+ unsigned int seq;
+ struct ieee80211_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ seq = WLAN_GET_SEQ_SEQ(sc);
+
+ entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2,
+ hdr->addr1);
+
+ if (entry == NULL) {
+ IEEE80211_DEBUG_FRAG("could not invalidate fragment cache "
+ "entry (seq=%u)\n", seq);
+ return -1;
+ }
+
+ entry->skb = NULL;
+ return 0;
+}
+
+#ifdef NOT_YET
+/* ieee80211_rx_frame_mgtmt
+ *
+ * Responsible for handling management control frames
+ *
+ * Called by ieee80211_rx */
+static inline int
+ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats, u16 type,
+ u16 stype)
+{
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
+ ieee->dev->name);
+ return 0;
+/*
+ hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
+ skb->data);*/
+ }
+
+ if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) {
+ if (stype == WLAN_FC_STYPE_BEACON &&
+ ieee->iw_mode == IW_MODE_MASTER) {
+ struct sk_buff *skb2;
+ /* Process beacon frames also in kernel driver to
+ * update STA(AP) table statistics */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2)
+ hostap_rx(skb2->dev, skb2, rx_stats);
+ }
+
+ /* send management frames to the user space daemon for
+ * processing */
+ ieee->apdevstats.rx_packets++;
+ ieee->apdevstats.rx_bytes += skb->len;
+ prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
+ return 0;
+ }
+
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
+ printk(KERN_DEBUG "%s: unknown management frame "
+ "(type=0x%02x, stype=0x%02x) dropped\n",
+ skb->dev->name, type, stype);
+ return -1;
+ }
+
+ hostap_rx(skb->dev, skb, rx_stats);
+ return 0;
+ }
+
+ printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
+ "received in non-Host AP mode\n", skb->dev->name);
+ return -1;
+}
+#endif
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
+/* Called by ieee80211_rx_frame_decrypt */
+static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
+ struct sk_buff *skb)
+{
+ struct net_device *dev = ieee->dev;
+ u16 fc, ethertype;
+ struct ieee80211_hdr *hdr;
+ u8 *pos;
+
+ if (skb->len < 24)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* check that the frame is unicast frame to us */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
+ memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ /* ToDS frame with own addr BSSID and DA */
+ } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ /* FromDS frame with own addr as DA */
+ } else
+ return 0;
+
+ if (skb->len < 24 + 8)
+ return 0;
+
+ /* check for port access entity Ethernet type */
+ pos = skb->data + 24;
+ ethertype = (pos[6] << 8) | pos[7];
+ if (ethertype == ETH_P_PAE)
+ return 1;
+
+ return 0;
+}
+
+/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+static inline int
+ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+#ifdef CONFIG_IEEE80211_CRYPT_TKIP
+ if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "received packet from " MAC_FMT "\n",
+ ieee->dev->name, MAC_ARG(hdr->addr2));
+ }
+ return -1;
+ }
+#endif
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ IEEE80211_DEBUG_DROP("decryption failed (SA=" MAC_FMT
+ ") res=%d\n", MAC_ARG(hdr->addr2), res);
+ if (res == -2)
+ IEEE80211_DEBUG_DROP("Decryption failed ICV "
+ "mismatch (key %d)\n",
+ skb->data[hdrlen + 3] >> 6);
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ return -1;
+ }
+
+ return res;
+}
+
+/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+static inline int
+ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
+ struct sk_buff *skb, int keyidx,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
+ " (SA=" MAC_FMT " keyidx=%d)\n",
+ ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ). */
+int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats)
+{
+ struct net_device *dev = ieee->dev;
+ struct ieee80211_hdr *hdr;
+ size_t hdrlen;
+ u16 fc, type, stype, sc;
+ struct net_device_stats *stats;
+ unsigned int frag;
+ u8 *payload;
+ u16 ethertype;
+#ifdef NOT_YET
+ struct net_device *wds = NULL;
+ struct sk_buff *skb2 = NULL;
+ struct net_device *wds = NULL;
+ int frame_authorized = 0;
+ int from_assoc_ap = 0;
+ void *sta = NULL;
+#endif
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ struct ieee80211_crypt_data *crypt = NULL;
+ int keyidx = 0;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ stats = &ieee->stats;
+
+ if (skb->len < 10) {
+ printk(KERN_INFO "%s: SKB length < 10\n", dev->name);
+ goto rx_dropped;
+ }
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ hdrlen = ieee80211_get_hdrlen(fc);
+
+#ifdef NOT_YET
+#if WIRELESS_EXT > 15
+ /* Put this code here so that we avoid duplicating it in all
+ * Rx paths. - Jean II */
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ /* If spy monitoring on */
+ if (iface->spy_data.spy_number > 0) {
+ struct iw_quality wstats;
+ wstats.level = rx_stats->signal;
+ wstats.noise = rx_stats->noise;
+ wstats.updated = 6; /* No qual value */
+ /* Update spy records */
+ wireless_spy_update(dev, hdr->addr2, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+#endif /* WIRELESS_EXT > 15 */
+ hostap_update_rx_stats(local->ap, hdr, rx_stats);
+#endif
+
+#if WIRELESS_EXT > 15
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ ieee80211_monitor_rx(ieee, skb, rx_stats);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ return 1;
+ }
+#endif
+
+ if (ieee->host_decrypt) {
+ int idx = 0;
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+ crypt = ieee->crypt[idx];
+#ifdef NOT_YET
+ sta = NULL;
+
+ /* Use station specific key to override default keys if the
+ * receiver address is a unicast address ("individual RA"). If
+ * bcrx_sta_key parameter is set, station specific key is used
+ * even with broad/multicast targets (this is against IEEE
+ * 802.11, but makes it easier to use different keys with
+ * stations that do not support WEP key mapping). */
+
+ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ (void)hostap_handle_sta_crypto(local, hdr, &crypt,
+ &sta);
+#endif
+
+ /* allow NULL decrypt to indicate an station specific override
+ * for default encryption */
+ if (crypt && (crypt->ops == NULL ||
+ crypt->ops->decrypt_mpdu == NULL))
+ crypt = NULL;
+
+ if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
+ /* This seems to be triggered by some (multicast?)
+ * frames from other than current BSS, so just drop the
+ * frames silently instead of filling system log with
+ * these reports. */
+ IEEE80211_DEBUG_DROP("Decryption failed (not set)"
+ " (SA=" MAC_FMT ")\n",
+ MAC_ARG(hdr->addr2));
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ goto rx_dropped;
+ }
+ }
+#ifdef NOT_YET
+ if (type != WLAN_FC_TYPE_DATA) {
+ if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
+ fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt &&
+ (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) {
+ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
+ "from " MAC_FMT "\n", dev->name,
+ MAC_ARG(hdr->addr2));
+ /* TODO: could inform hostapd about this so that it
+ * could send auth failure report */
+ goto rx_dropped;
+ }
+
+ if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
+ goto rx_dropped;
+ else
+ goto rx_exit;
+ }
+#endif
+
+ /* Data frame - extract src/dst addresses */
+ if (skb->len < IEEE80211_3ADDR_LEN)
+ goto rx_dropped;
+
+ switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr3, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ if (skb->len < IEEE80211_4ADDR_LEN)
+ goto rx_dropped;
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+ break;
+ case 0:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ }
+
+#ifdef NOT_YET
+ if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
+ goto rx_dropped;
+ if (wds) {
+ skb->dev = dev = wds;
+ stats = hostap_get_stats(dev);
+ }
+
+ if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
+ (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS && ieee->stadev
+ && memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
+ /* Frame from BSSID of the AP for which we are a client */
+ skb->dev = dev = ieee->stadev;
+ stats = hostap_get_stats(dev);
+ from_assoc_ap = 1;
+ }
+#endif
+
+ dev->last_rx = jiffies;
+
+#ifdef NOT_YET
+ if ((ieee->iw_mode == IW_MODE_MASTER ||
+ ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) {
+ switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
+ wds != NULL)) {
+ case AP_RX_CONTINUE_NOT_AUTHORIZED:
+ frame_authorized = 0;
+ break;
+ case AP_RX_CONTINUE:
+ frame_authorized = 1;
+ break;
+ case AP_RX_DROP:
+ goto rx_dropped;
+ case AP_RX_EXIT:
+ goto rx_exit;
+ }
+ }
+#endif
+
+ /* Nullfunc frames may have PS-bit set, so they must be passed to
+ * hostap_handle_sta_rx() before being dropped here. */
+ if (stype != IEEE80211_STYPE_DATA &&
+ stype != IEEE80211_STYPE_DATA_CFACK &&
+ stype != IEEE80211_STYPE_DATA_CFPOLL &&
+ stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
+ if (stype != IEEE80211_STYPE_NULLFUNC)
+ IEEE80211_DEBUG_DROP("RX: dropped data frame "
+ "with no data (type=0x%02x, "
+ "subtype=0x%02x, len=%d)\n",
+ type, stype, skb->len);
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
+
+ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ /* skb: hdr + (possibly fragmented) plaintext payload */
+ // PR: FIXME: hostap has additional conditions in the "if" below:
+ // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
+ int flen;
+ struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
+ IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
+
+ if (!frag_skb) {
+ IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
+ "Rx cannot get skb from fragment "
+ "cache (morefrag=%d seq=%u frag=%u)\n",
+ (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
+ WLAN_GET_SEQ_SEQ(sc), frag);
+ goto rx_dropped;
+ }
+
+ flen = skb->len;
+ if (frag != 0)
+ flen -= hdrlen;
+
+ if (frag_skb->tail + flen > frag_skb->end) {
+ printk(KERN_WARNING "%s: host decrypted and "
+ "reassembled frame did not fit skb\n",
+ dev->name);
+ ieee80211_frag_cache_invalidate(ieee, hdr);
+ goto rx_dropped;
+ }
+
+ if (frag == 0) {
+ /* copy first fragment (including full headers) into
+ * beginning of the fragment cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data, flen);
+ } else {
+ /* append frame payload to the end of the fragment
+ * cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+ flen);
+ }
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+
+ if (fc & IEEE80211_FCTL_MOREFRAGS) {
+ /* more fragments expected - leave the skb in fragment
+ * cache for now; it will be delivered to upper layers
+ * after all fragments have been received */
+ goto rx_exit;
+ }
+
+ /* this was the last fragment and the frame will be
+ * delivered, so remove skb from fragment cache */
+ skb = frag_skb;
+ hdr = (struct ieee80211_hdr *)skb->data;
+ ieee80211_frag_cache_invalidate(ieee, hdr);
+ }
+
+ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+ * encrypted/authenticated */
+ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
+ if ( /*ieee->ieee802_1x && */
+ ieee80211_is_eapol_frame(ieee, skb)) {
+ /* pass unencrypted EAPOL frames even if encryption is
+ * configured */
+ } else {
+ IEEE80211_DEBUG_DROP("encryption configured, but RX "
+ "frame not encrypted (SA=" MAC_FMT
+ ")\n", MAC_ARG(hdr->addr2));
+ goto rx_dropped;
+ }
+ }
+
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep &&
+ !ieee80211_is_eapol_frame(ieee, skb)) {
+ IEEE80211_DEBUG_DROP("dropped unencrypted RX data "
+ "frame from " MAC_FMT
+ " (drop_unencrypted=1)\n",
+ MAC_ARG(hdr->addr2));
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possible reassembled) full plaintext payload */
+
+ payload = skb->data + hdrlen;
+ ethertype = (payload[6] << 8) | payload[7];
+
+#ifdef NOT_YET
+ /* If IEEE 802.1X is used, check whether the port is authorized to send
+ * the received frame. */
+ if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) {
+ if (ethertype == ETH_P_PAE) {
+ printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
+ dev->name);
+ if (ieee->hostapd && ieee->apdev) {
+ /* Send IEEE 802.1X frames to the user
+ * space daemon for processing */
+ prism2_rx_80211(ieee->apdev, skb, rx_stats,
+ PRISM2_RX_MGMT);
+ ieee->apdevstats.rx_packets++;
+ ieee->apdevstats.rx_bytes += skb->len;
+ goto rx_exit;
+ }
+ } else if (!frame_authorized) {
+ printk(KERN_DEBUG "%s: dropped frame from "
+ "unauthorized port (IEEE 802.1X): "
+ "ethertype=0x%04x\n", dev->name, ethertype);
+ goto rx_dropped;
+ }
+ }
+#endif
+
+ /* convert hdr + possible LLC headers into Ethernet header */
+ if (skb->len - hdrlen >= 8 &&
+ ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+ * replace EtherType */
+ skb_pull(skb, hdrlen + SNAP_SIZE);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ u16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ skb_pull(skb, hdrlen);
+ len = htons(skb->len);
+ memcpy(skb_push(skb, 2), &len, 2);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ }
+
+#ifdef NOT_YET
+ if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) {
+ /* Non-standard frame: get addr4 from its bogus location after
+ * the payload */
+ memcpy(skb->data + ETH_ALEN,
+ skb->data + skb->len - ETH_ALEN, ETH_ALEN);
+ skb_trim(skb, skb->len - ETH_ALEN);
+ }
+#endif
+
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+
+#ifdef NOT_YET
+ if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
+ if (dst[0] & 0x01) {
+ /* copy multicast frame both to the higher layers and
+ * to the wireless media */
+ ieee->ap->bridged_multicast++;
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ printk(KERN_DEBUG "%s: skb_clone failed for "
+ "multicast frame\n", dev->name);
+ } else if (hostap_is_sta_assoc(ieee->ap, dst)) {
+ /* send frame directly to the associated STA using
+ * wireless media and not passing to higher layers */
+ ieee->ap->bridged_unicast++;
+ skb2 = skb;
+ skb = NULL;
+ }
+ }
+
+ if (skb2 != NULL) {
+ /* send to wireless media */
+ skb2->protocol = __constant_htons(ETH_P_802_3);
+ skb2->mac.raw = skb2->nh.raw = skb2->data;
+ /* skb2->nh.raw = skb2->data + ETH_HLEN; */
+ skb2->dev = dev;
+ dev_queue_xmit(skb2);
+ }
+#endif
+
+ if (skb) {
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->dev = dev;
+ skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+ netif_rx(skb);
+ }
+
+ rx_exit:
+#ifdef NOT_YET
+ if (sta)
+ hostap_handle_sta_release(sta);
+#endif
+ return 1;
+
+ rx_dropped:
+ stats->rx_dropped++;
+
+ /* Returning 0 indicates to caller that we have not handled the SKB--
+ * so it is still allocated and can be used again by underlying
+ * hardware as a DMA target */
+ return 0;
+}
+
+#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
+
+static inline int ieee80211_is_ofdm_rate(u8 rate)
+{
+ switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+ case IEEE80211_OFDM_RATE_6MB:
+ case IEEE80211_OFDM_RATE_9MB:
+ case IEEE80211_OFDM_RATE_12MB:
+ case IEEE80211_OFDM_RATE_18MB:
+ case IEEE80211_OFDM_RATE_24MB:
+ case IEEE80211_OFDM_RATE_36MB:
+ case IEEE80211_OFDM_RATE_48MB:
+ case IEEE80211_OFDM_RATE_54MB:
+ return 1;
+ }
+ return 0;
+}
+
+static inline int ieee80211_network_init(struct ieee80211_device *ieee,
+ struct ieee80211_probe_response
+ *beacon,
+ struct ieee80211_network *network,
+ struct ieee80211_rx_stats *stats)
+{
+#ifdef CONFIG_IEEE80211_DEBUG
+ char rates_str[64];
+ char *p;
+#endif
+ struct ieee80211_info_element *info_element;
+ u16 left;
+ u8 i;
+
+ /* Pull out fixed field data */
+ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+ network->capability = beacon->capability;
+ network->last_scanned = jiffies;
+ network->time_stamp[0] = beacon->time_stamp[0];
+ network->time_stamp[1] = beacon->time_stamp[1];
+ network->beacon_interval = beacon->beacon_interval;
+ /* Where to pull this? beacon->listen_interval; */
+ network->listen_interval = 0x0A;
+ network->rates_len = network->rates_ex_len = 0;
+ network->last_associate = 0;
+ network->ssid_len = 0;
+ network->flags = 0;
+ network->atim_window = 0;
+
+ if (stats->freq == IEEE80211_52GHZ_BAND) {
+ /* for A band (No DS info) */
+ network->channel = stats->received_channel;
+ } else
+ network->flags |= NETWORK_HAS_CCK;
+
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+
+ info_element = &beacon->info_element;
+ left = stats->len - ((void *)info_element - (void *)beacon);
+ while (left >= sizeof(struct ieee80211_info_element_hdr)) {
+ if (sizeof(struct ieee80211_info_element_hdr) +
+ info_element->len > left) {
+ IEEE80211_DEBUG_SCAN
+ ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
+ info_element->len +
+ sizeof(struct ieee80211_info_element), left);
+ return 1;
+ }
+
+ switch (info_element->id) {
+ case MFIE_TYPE_SSID:
+ if (ieee80211_is_empty_essid(info_element->data,
+ info_element->len)) {
+ network->flags |= NETWORK_EMPTY_ESSID;
+ break;
+ }
+
+ network->ssid_len = min(info_element->len,
+ (u8) IW_ESSID_MAX_SIZE);
+ memcpy(network->ssid, info_element->data,
+ network->ssid_len);
+ if (network->ssid_len < IW_ESSID_MAX_SIZE)
+ memset(network->ssid + network->ssid_len, 0,
+ IW_ESSID_MAX_SIZE - network->ssid_len);
+
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
+ network->ssid, network->ssid_len);
+ break;
+
+ case MFIE_TYPE_RATES:
+#ifdef CONFIG_IEEE80211_DEBUG
+ p = rates_str;
+#endif
+ network->rates_len =
+ min(info_element->len, MAX_RATES_LENGTH);
+ for (i = 0; i < network->rates_len; i++) {
+ network->rates[i] = info_element->data[i];
+#ifdef CONFIG_IEEE80211_DEBUG
+ p += snprintf(p,
+ sizeof(rates_str) - (p -
+ rates_str),
+ "%02X ", network->rates[i]);
+#endif
+ if (ieee80211_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ IEEE80211_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+ }
+
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
+ rates_str, network->rates_len);
+ break;
+
+ case MFIE_TYPE_RATES_EX:
+#ifdef CONFIG_IEEE80211_DEBUG
+ p = rates_str;
+#endif
+ network->rates_ex_len =
+ min(info_element->len, MAX_RATES_EX_LENGTH);
+ for (i = 0; i < network->rates_ex_len; i++) {
+ network->rates_ex[i] = info_element->data[i];
+#ifdef CONFIG_IEEE80211_DEBUG
+ p += snprintf(p,
+ sizeof(rates_str) - (p -
+ rates_str),
+ "%02X ", network->rates[i]);
+#endif
+ if (ieee80211_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ IEEE80211_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+ }
+
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+ rates_str, network->rates_ex_len);
+ break;
+
+ case MFIE_TYPE_DS_SET:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
+ info_element->data[0]);
+ if (stats->freq == IEEE80211_24GHZ_BAND)
+ network->channel = info_element->data[0];
+ break;
+
+ case MFIE_TYPE_FH_SET:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_CF_SET:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_TIM:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
+ break;
+
+ case MFIE_TYPE_IBSS_SET:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_CHALLENGE:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
+ break;
+
+ case MFIE_TYPE_GENERIC:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
+ info_element->len);
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0xf2 &&
+ info_element->data[3] == 0x01) {
+ network->wpa_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->wpa_ie, info_element,
+ network->wpa_ie_len);
+ }
+ break;
+
+ case MFIE_TYPE_RSN:
+ IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
+ info_element->len);
+ network->rsn_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->rsn_ie, info_element,
+ network->rsn_ie_len);
+ break;
+
+ default:
+ IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
+ info_element->id);
+ break;
+ }
+
+ left -= sizeof(struct ieee80211_info_element_hdr) +
+ info_element->len;
+ info_element = (struct ieee80211_info_element *)
+ &info_element->data[info_element->len];
+ }
+
+ network->mode = 0;
+ if (stats->freq == IEEE80211_52GHZ_BAND)
+ network->mode = IEEE_A;
+ else {
+ if (network->flags & NETWORK_HAS_OFDM)
+ network->mode |= IEEE_G;
+ if (network->flags & NETWORK_HAS_CCK)
+ network->mode |= IEEE_B;
+ }
+
+ if (network->mode == 0) {
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+ "network.\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 1;
+ }
+
+ if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
+ network->flags |= NETWORK_EMPTY_ESSID;
+
+ memcpy(&network->stats, stats, sizeof(network->stats));
+
+ return 0;
+}
+
+static inline int is_same_network(struct ieee80211_network *src,
+ struct ieee80211_network *dst)
+{
+ /* A network is only a duplicate if the channel, BSSID, and ESSID
+ * all match. We treat all <hidden> with the same BSSID and channel
+ * as one network */
+ return ((src->ssid_len == dst->ssid_len) &&
+ (src->channel == dst->channel) &&
+ !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
+ !memcmp(src->ssid, dst->ssid, src->ssid_len));
+}
+
+static inline void update_network(struct ieee80211_network *dst,
+ struct ieee80211_network *src)
+{
+ memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
+ dst->capability = src->capability;
+ memcpy(dst->rates, src->rates, src->rates_len);
+ dst->rates_len = src->rates_len;
+ memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
+ dst->rates_ex_len = src->rates_ex_len;
+
+ dst->mode = src->mode;
+ dst->flags = src->flags;
+ dst->time_stamp[0] = src->time_stamp[0];
+ dst->time_stamp[1] = src->time_stamp[1];
+
+ dst->beacon_interval = src->beacon_interval;
+ dst->listen_interval = src->listen_interval;
+ dst->atim_window = src->atim_window;
+
+ memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
+ dst->wpa_ie_len = src->wpa_ie_len;
+ memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
+ dst->rsn_ie_len = src->rsn_ie_len;
+
+ dst->last_scanned = jiffies;
+ /* dst->last_associate is not overwritten */
+}
+
+static inline void ieee80211_process_probe_response(struct ieee80211_device
+ *ieee,
+ struct
+ ieee80211_probe_response
+ *beacon,
+ struct ieee80211_rx_stats
+ *stats)
+{
+ struct ieee80211_network network;
+ struct ieee80211_network *target;
+ struct ieee80211_network *oldest = NULL;
+#ifdef CONFIG_IEEE80211_DEBUG
+ struct ieee80211_info_element *info_element = &beacon->info_element;
+#endif
+ unsigned long flags;
+
+ IEEE80211_DEBUG_SCAN("'%s' (" MAC_FMT
+ "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ escape_essid(info_element->data,
+ info_element->len),
+ MAC_ARG(beacon->header.addr3),
+ (beacon->capability & (1 << 0xf)) ? '1' : '0',
+ (beacon->capability & (1 << 0xe)) ? '1' : '0',
+ (beacon->capability & (1 << 0xd)) ? '1' : '0',
+ (beacon->capability & (1 << 0xc)) ? '1' : '0',
+ (beacon->capability & (1 << 0xb)) ? '1' : '0',
+ (beacon->capability & (1 << 0xa)) ? '1' : '0',
+ (beacon->capability & (1 << 0x9)) ? '1' : '0',
+ (beacon->capability & (1 << 0x8)) ? '1' : '0',
+ (beacon->capability & (1 << 0x7)) ? '1' : '0',
+ (beacon->capability & (1 << 0x6)) ? '1' : '0',
+ (beacon->capability & (1 << 0x5)) ? '1' : '0',
+ (beacon->capability & (1 << 0x4)) ? '1' : '0',
+ (beacon->capability & (1 << 0x3)) ? '1' : '0',
+ (beacon->capability & (1 << 0x2)) ? '1' : '0',
+ (beacon->capability & (1 << 0x1)) ? '1' : '0',
+ (beacon->capability & (1 << 0x0)) ? '1' : '0');
+
+ if (ieee80211_network_init(ieee, beacon, &network, stats)) {
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+ escape_essid(info_element->data,
+ info_element->len),
+ MAC_ARG(beacon->header.addr3),
+ WLAN_FC_GET_STYPE(beacon->header.
+ frame_ctl) ==
+ IEEE80211_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+ return;
+ }
+
+ /* The network parsed correctly -- so now we scan our known networks
+ * to see if we can find it in our list.
+ *
+ * NOTE: This search is definitely not optimized. Once its doing
+ * the "right thing" we'll optimize it for efficiency if
+ * necessary */
+
+ /* Search for this entry in the list and update it if it is
+ * already there. */
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(target, &ieee->network_list, list) {
+ if (is_same_network(target, &network))
+ break;
+
+ if ((oldest == NULL) ||
+ (target->last_scanned < oldest->last_scanned))
+ oldest = target;
+ }
+
+ /* If we didn't find a match, then get a new network slot to initialize
+ * with this beacon's information */
+ if (&target->list == &ieee->network_list) {
+ if (list_empty(&ieee->network_free_list)) {
+ /* If there are no more slots, expire the oldest */
+ list_del(&oldest->list);
+ target = oldest;
+ IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+ "network list.\n",
+ escape_essid(target->ssid,
+ target->ssid_len),
+ MAC_ARG(target->bssid));
+ } else {
+ /* Otherwise just pull from the free list */
+ target = list_entry(ieee->network_free_list.next,
+ struct ieee80211_network, list);
+ list_del(ieee->network_free_list.next);
+ }
+
+#ifdef CONFIG_IEEE80211_DEBUG
+ IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+ escape_essid(network.ssid,
+ network.ssid_len),
+ MAC_ARG(network.bssid),
+ WLAN_FC_GET_STYPE(beacon->header.
+ frame_ctl) ==
+ IEEE80211_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+#endif
+ memcpy(target, &network, sizeof(*target));
+ list_add_tail(&target->list, &ieee->network_list);
+ } else {
+ IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+ escape_essid(target->ssid,
+ target->ssid_len),
+ MAC_ARG(target->bssid),
+ WLAN_FC_GET_STYPE(beacon->header.
+ frame_ctl) ==
+ IEEE80211_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+ update_network(target, &network);
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+ struct ieee80211_hdr *header,
+ struct ieee80211_rx_stats *stats)
+{
+ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+ case IEEE80211_STYPE_ASSOC_RESP:
+ IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ break;
+
+ case IEEE80211_STYPE_REASSOC_RESP:
+ IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ break;
+
+ case IEEE80211_STYPE_PROBE_RESP:
+ IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ IEEE80211_DEBUG_SCAN("Probe response\n");
+ ieee80211_process_probe_response(ieee,
+ (struct
+ ieee80211_probe_response *)
+ header, stats);
+ break;
+
+ case IEEE80211_STYPE_BEACON:
+ IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ IEEE80211_DEBUG_SCAN("Beacon\n");
+ ieee80211_process_probe_response(ieee,
+ (struct
+ ieee80211_probe_response *)
+ header, stats);
+ break;
+
+ default:
+ IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ IEEE80211_WARNING("%s: Unknown management packet: %d\n",
+ ieee->dev->name,
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+ break;
+ }
+}
+
+EXPORT_SYMBOL(ieee80211_rx_mgt);
+EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
new file mode 100644
index 000000000000..c9aaff3fea1e
--- /dev/null
+++ b/net/ieee80211/ieee80211_tx.c
@@ -0,0 +1,428 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+/*
+
+802.11 Data Frame
+
+ ,-------------------------------------------------------------------.
+Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
+ |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
+ | | tion | (BSSID) | | | ence | data | |
+ `--------------------------------------------------| |------'
+Total: 28 non-data bytes `----.----'
+ |
+ .- 'Frame data' expands to <---------------------------'
+ |
+ V
+ ,---------------------------------------------------.
+Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
+ |------|------|---------|----------|------|---------|
+Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
+ | DSAP | SSAP | | | | Packet |
+ | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
+ `-----------------------------------------| |
+Total: 8 non-data bytes `----.----'
+ |
+ .- 'IP Packet' expands, if WEP enabled, to <--'
+ |
+ V
+ ,-----------------------.
+Bytes | 4 | 0-2296 | 4 |
+ |-----|-----------|-----|
+Desc. | IV | Encrypted | ICV |
+ | | IP Packet | |
+ `-----------------------'
+Total: 8 non-data bytes
+
+802.3 Ethernet Data Frame
+
+ ,-----------------------------------------.
+Bytes | 6 | 6 | 2 | Variable | 4 |
+ |-------|-------|------|-----------|------|
+Desc. | Dest. | Source| Type | IP Packet | fcs |
+ | MAC | MAC | | | |
+ `-----------------------------------------'
+Total: 18 non-data bytes
+
+In the event that fragmentation is required, the incoming payload is split into
+N parts of size ieee->fts. The first fragment contains the SNAP header and the
+remaining packets are just data.
+
+If encryption is enabled, each fragment payload size is reduced by enough space
+to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
+So if you have 1500 bytes of payload with ieee->fts set to 500 without
+encryption it will take 3 frames. With WEP it will take 4 frames as the
+payload of each frame is reduced to 492 bytes.
+
+* SKB visualization
+*
+* ,- skb->data
+* |
+* | ETHERNET HEADER ,-<-- PAYLOAD
+* | | 14 bytes from skb->data
+* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
+* | | | |
+* |,-Dest.--. ,--Src.---. | | |
+* | 6 bytes| | 6 bytes | | | |
+* v | | | | | |
+* 0 | v 1 | v | v 2
+* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+* ^ | ^ | ^ |
+* | | | | | |
+* | | | | `T' <---- 2 bytes for Type
+* | | | |
+* | | '---SNAP--' <-------- 6 bytes for SNAP
+* | |
+* `-IV--' <-------------------- 4 bytes for IV (WEP)
+*
+* SNAP HEADER
+*
+*/
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
+{
+ struct ieee80211_snap_hdr *snap;
+ u8 *oui;
+
+ snap = (struct ieee80211_snap_hdr *)data;
+ snap->dsap = 0xaa;
+ snap->ssap = 0xaa;
+ snap->ctrl = 0x03;
+
+ if (h_proto == 0x8137 || h_proto == 0x80f3)
+ oui = P802_1H_OUI;
+ else
+ oui = RFC1042_OUI;
+ snap->oui[0] = oui[0];
+ snap->oui[1] = oui[1];
+ snap->oui[2] = oui[2];
+
+ *(u16 *) (data + SNAP_SIZE) = htons(h_proto);
+
+ return SNAP_SIZE + sizeof(u16);
+}
+
+static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
+ struct sk_buff *frag, int hdr_len)
+{
+ struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
+ int res;
+
+#ifdef CONFIG_IEEE80211_CRYPT_TKIP
+ struct ieee80211_hdr *header;
+
+ if (ieee->tkip_countermeasures &&
+ crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+ header = (struct ieee80211_hdr *)frag->data;
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "TX packet to " MAC_FMT "\n",
+ ieee->dev->name, MAC_ARG(header->addr1));
+ }
+ return -1;
+ }
+#endif
+ /* To encrypt, frame format is:
+ * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
+
+ // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
+ /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+ * call both MSDU and MPDU encryption functions from here. */
+ atomic_inc(&crypt->refcnt);
+ res = 0;
+ if (crypt->ops->encrypt_msdu)
+ res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
+ if (res == 0 && crypt->ops->encrypt_mpdu)
+ res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
+
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
+ ieee->dev->name, frag->len);
+ ieee->ieee_stats.tx_discards++;
+ return -1;
+ }
+
+ return 0;
+}
+
+void ieee80211_txb_free(struct ieee80211_txb *txb)
+{
+ int i;
+ if (unlikely(!txb))
+ return;
+ for (i = 0; i < txb->nr_frags; i++)
+ if (txb->fragments[i])
+ dev_kfree_skb_any(txb->fragments[i]);
+ kfree(txb);
+}
+
+static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
+ int gfp_mask)
+{
+ struct ieee80211_txb *txb;
+ int i;
+ txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
+ gfp_mask);
+ if (!txb)
+ return NULL;
+
+ memset(txb, 0, sizeof(struct ieee80211_txb));
+ txb->nr_frags = nr_frags;
+ txb->frag_size = txb_size;
+
+ for (i = 0; i < nr_frags; i++) {
+ txb->fragments[i] = dev_alloc_skb(txb_size);
+ if (unlikely(!txb->fragments[i])) {
+ i--;
+ break;
+ }
+ }
+ if (unlikely(i != nr_frags)) {
+ while (i >= 0)
+ dev_kfree_skb_any(txb->fragments[i--]);
+ kfree(txb);
+ return NULL;
+ }
+ return txb;
+}
+
+/* SKBs are added to the ieee->tx_queue. */
+int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+ struct ieee80211_txb *txb = NULL;
+ struct ieee80211_hdr *frag_hdr;
+ int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
+ unsigned long flags;
+ struct net_device_stats *stats = &ieee->stats;
+ int ether_type, encrypt;
+ int bytes, fc, hdr_len;
+ struct sk_buff *skb_frag;
+ struct ieee80211_hdr header = { /* Ensure zero initialized */
+ .duration_id = 0,
+ .seq_ctl = 0
+ };
+ u8 dest[ETH_ALEN], src[ETH_ALEN];
+
+ struct ieee80211_crypt_data *crypt;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ /* If there is no driver handler to take the TXB, dont' bother
+ * creating it... */
+ if (!ieee->hard_start_xmit) {
+ printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
+ goto success;
+ }
+
+ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
+ printk(KERN_WARNING "%s: skb too small (%d).\n",
+ ieee->dev->name, skb->len);
+ goto success;
+ }
+
+ ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
+
+ crypt = ieee->crypt[ieee->tx_keyidx];
+
+ encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
+ ieee->host_encrypt && crypt && crypt->ops;
+
+ if (!encrypt && ieee->ieee802_1x &&
+ ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
+ stats->tx_dropped++;
+ goto success;
+ }
+
+ /* Save source and destination addresses */
+ memcpy(&dest, skb->data, ETH_ALEN);
+ memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
+
+ /* Advance the SKB to the start of the payload */
+ skb_pull(skb, sizeof(struct ethhdr));
+
+ /* Determine total amount of storage required for TXB packets */
+ bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
+ if (encrypt)
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
+ IEEE80211_FCTL_PROTECTED;
+ else
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ fc |= IEEE80211_FCTL_TODS;
+ /* To DS: Addr1 = BSSID, Addr2 = SA,
+ Addr3 = DA */
+ memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
+ memcpy(&header.addr2, &src, ETH_ALEN);
+ memcpy(&header.addr3, &dest, ETH_ALEN);
+ } else if (ieee->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA,
+ Addr3 = BSSID */
+ memcpy(&header.addr1, dest, ETH_ALEN);
+ memcpy(&header.addr2, src, ETH_ALEN);
+ memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
+ }
+ header.frame_ctl = cpu_to_le16(fc);
+ hdr_len = IEEE80211_3ADDR_LEN;
+
+ /* Determine fragmentation size based on destination (multicast
+ * and broadcast are not fragmented) */
+ if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
+ frag_size = MAX_FRAG_THRESHOLD;
+ else
+ frag_size = ieee->fts;
+
+ /* Determine amount of payload per fragment. Regardless of if
+ * this stack is providing the full 802.11 header, one will
+ * eventually be affixed to this fragment -- so we must account for
+ * it when determining the amount of payload space. */
+ bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
+ if (ieee->config &
+ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+ bytes_per_frag -= IEEE80211_FCS_LEN;
+
+ /* Each fragment may need to have room for encryptiong pre/postfix */
+ if (encrypt)
+ bytes_per_frag -= crypt->ops->extra_prefix_len +
+ crypt->ops->extra_postfix_len;
+
+ /* Number of fragments is the total bytes_per_frag /
+ * payload_per_fragment */
+ nr_frags = bytes / bytes_per_frag;
+ bytes_last_frag = bytes % bytes_per_frag;
+ if (bytes_last_frag)
+ nr_frags++;
+ else
+ bytes_last_frag = bytes_per_frag;
+
+ /* When we allocate the TXB we allocate enough space for the reserve
+ * and full fragment bytes (bytes_per_frag doesn't include prefix,
+ * postfix, header, FCS, etc.) */
+ txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
+ if (unlikely(!txb)) {
+ printk(KERN_WARNING "%s: Could not allocate TXB\n",
+ ieee->dev->name);
+ goto failed;
+ }
+ txb->encrypted = encrypt;
+ txb->payload_size = bytes;
+
+ for (i = 0; i < nr_frags; i++) {
+ skb_frag = txb->fragments[i];
+
+ if (encrypt)
+ skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
+
+ frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
+ memcpy(frag_hdr, &header, hdr_len);
+
+ /* If this is not the last fragment, then add the MOREFRAGS
+ * bit to the frame control */
+ if (i != nr_frags - 1) {
+ frag_hdr->frame_ctl =
+ cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
+ bytes = bytes_per_frag;
+ } else {
+ /* The last fragment takes the remaining length */
+ bytes = bytes_last_frag;
+ }
+
+ /* Put a SNAP header on the first fragment */
+ if (i == 0) {
+ ieee80211_put_snap(skb_put
+ (skb_frag, SNAP_SIZE + sizeof(u16)),
+ ether_type);
+ bytes -= SNAP_SIZE + sizeof(u16);
+ }
+
+ memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
+
+ /* Advance the SKB... */
+ skb_pull(skb, bytes);
+
+ /* Encryption routine will move the header forward in order
+ * to insert the IV between the header and the payload */
+ if (encrypt)
+ ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+ if (ieee->config &
+ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+ skb_put(skb_frag, 4);
+ }
+
+ success:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ dev_kfree_skb_any(skb);
+
+ if (txb) {
+ if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
+ stats->tx_packets++;
+ stats->tx_bytes += txb->payload_size;
+ return 0;
+ }
+ ieee80211_txb_free(txb);
+ }
+
+ return 0;
+
+ failed:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ netif_stop_queue(dev);
+ stats->tx_errors++;
+ return 1;
+
+}
+
+EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
new file mode 100644
index 000000000000..94882f39b072
--- /dev/null
+++ b/net/ieee80211/ieee80211_wx.c
@@ -0,0 +1,468 @@
+/******************************************************************************
+
+ Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#include <linux/kmod.h>
+#include <linux/module.h>
+
+#include <net/ieee80211.h>
+#include <linux/wireless.h>
+
+static const char *ieee80211_modes[] = {
+ "?", "a", "b", "ab", "g", "ag", "bg", "abg"
+};
+
+#define MAX_CUSTOM_LEN 64
+static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
+ char *start, char *stop,
+ struct ieee80211_network *network)
+{
+ char custom[MAX_CUSTOM_LEN];
+ char *p;
+ struct iw_event iwe;
+ int i, j;
+ u8 max_rate, rate;
+
+ /* First entry *MUST* be the AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* Remaining entries will be displayed in the order we provide them */
+
+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ if (network->flags & NETWORK_EMPTY_ESSID) {
+ iwe.u.data.length = sizeof("<hidden>");
+ start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
+ } else {
+ iwe.u.data.length = min(network->ssid_len, (u8) 32);
+ start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
+ }
+
+ /* Add the protocol name */
+ iwe.cmd = SIOCGIWNAME;
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
+ ieee80211_modes[network->mode]);
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
+
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+ if (network->capability & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Add frequency/channel */
+ iwe.cmd = SIOCGIWFREQ;
+/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
+ iwe.u.freq.e = 3; */
+ iwe.u.freq.m = network->channel;
+ iwe.u.freq.e = 0;
+ iwe.u.freq.i = 0;
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (network->capability & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
+
+ /* Add basic and extended rates */
+ max_rate = 0;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+ for (i = 0, j = 0; i < network->rates_len;) {
+ if (j < network->rates_ex_len &&
+ ((network->rates_ex[j] & 0x7F) <
+ (network->rates[i] & 0x7F)))
+ rate = network->rates_ex[j++] & 0x7F;
+ else
+ rate = network->rates[i++] & 0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ }
+ for (; j < network->rates_ex_len; j++) {
+ rate = network->rates_ex[j] & 0x7F;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ if (rate > max_rate)
+ max_rate = rate;
+ }
+
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ iwe.u.bitrate.value = max_rate * 500000;
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
+
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(start, stop, &iwe, custom);
+
+ /* Add quality statistics */
+ /* TODO: Fix these values... */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = network->stats.signal;
+ iwe.u.qual.level = network->stats.rssi;
+ iwe.u.qual.noise = network->stats.noise;
+ iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
+ if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
+ iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
+ if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
+ iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
+ if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
+ iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
+
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(start, stop, &iwe, custom);
+
+ if (ieee->wpa_enabled && network->wpa_ie_len) {
+ char buf[MAX_WPA_IE_LEN * 2 + 30];
+
+ u8 *p = buf;
+ p += sprintf(p, "wpa_ie=");
+ for (i = 0; i < network->wpa_ie_len; i++) {
+ p += sprintf(p, "%02x", network->wpa_ie[i]);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(start, stop, &iwe, buf);
+ }
+
+ if (ieee->wpa_enabled && network->rsn_ie_len) {
+ char buf[MAX_WPA_IE_LEN * 2 + 30];
+
+ u8 *p = buf;
+ p += sprintf(p, "rsn_ie=");
+ for (i = 0; i < network->rsn_ie_len; i++) {
+ p += sprintf(p, "%02x", network->rsn_ie[i]);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(start, stop, &iwe, buf);
+ }
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network. */
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ " Last beacon: %lums ago",
+ (jiffies - network->last_scanned) / (HZ / 100));
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(start, stop, &iwe, custom);
+
+ return start;
+}
+
+int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ieee80211_network *network;
+ unsigned long flags;
+
+ char *ev = extra;
+ char *stop = ev + IW_SCAN_MAX_DATA;
+ int i = 0;
+
+ IEEE80211_DEBUG_WX("Getting scan\n");
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(network, &ieee->network_list, list) {
+ i++;
+ if (ieee->scan_age == 0 ||
+ time_after(network->last_scanned + ieee->scan_age, jiffies))
+ ev = ipw2100_translate_scan(ieee, ev, stop, network);
+ else
+ IEEE80211_DEBUG_SCAN("Not showing network '%s ("
+ MAC_FMT ")' due to age (%lums).\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ MAC_ARG(network->bssid),
+ (jiffies -
+ network->last_scanned) / (HZ /
+ 100));
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ wrqu->data.length = ev - extra;
+ wrqu->data.flags = 0;
+
+ IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
+
+ return 0;
+}
+
+int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ struct net_device *dev = ieee->dev;
+ struct ieee80211_security sec = {
+ .flags = 0
+ };
+ int i, key, key_provided, len;
+ struct ieee80211_crypt_data **crypt;
+
+ IEEE80211_DEBUG_WX("SET_ENCODE\n");
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ key_provided = 1;
+ } else {
+ key_provided = 0;
+ key = ieee->tx_keyidx;
+ }
+
+ IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
+ "provided" : "default");
+
+ crypt = &ieee->crypt[key];
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ if (key_provided && *crypt) {
+ IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
+ key);
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+ } else
+ IEEE80211_DEBUG_WX("Disabling encryption.\n");
+
+ /* Check all the keys to see if any are still configured,
+ * and if no key index was provided, de-init them all */
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (ieee->crypt[i] != NULL) {
+ if (key_provided)
+ break;
+ ieee80211_crypt_delayed_deinit(ieee,
+ &ieee->crypt[i]);
+ }
+ }
+
+ if (i == WEP_KEYS) {
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL;
+ }
+
+ goto done;
+ }
+
+ sec.enabled = 1;
+ sec.flags |= SEC_ENABLED;
+
+ if (*crypt != NULL && (*crypt)->ops != NULL &&
+ strcmp((*crypt)->ops->name, "WEP") != 0) {
+ /* changing to use WEP; deinit previously used algorithm
+ * on this key */
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+ }
+
+ if (*crypt == NULL) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ /* take WEP into use */
+ new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL)
+ return -ENOMEM;
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ if (!new_crypt->ops) {
+ request_module("ieee80211_crypt_wep");
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ }
+
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(key);
+
+ if (!new_crypt->ops || !new_crypt->priv) {
+ kfree(new_crypt);
+ new_crypt = NULL;
+
+ printk(KERN_WARNING "%s: could not initialize WEP: "
+ "load module ieee80211_crypt_wep\n", dev->name);
+ return -EOPNOTSUPP;
+ }
+ *crypt = new_crypt;
+ }
+
+ /* If a new key was provided, set it up */
+ if (erq->length > 0) {
+ len = erq->length <= 5 ? 5 : 13;
+ memcpy(sec.keys[key], keybuf, erq->length);
+ if (len > erq->length)
+ memset(sec.keys[key] + erq->length, 0,
+ len - erq->length);
+ IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
+ key, escape_essid(sec.keys[key], len),
+ erq->length, len);
+ sec.key_sizes[key] = len;
+ (*crypt)->ops->set_key(sec.keys[key], len, NULL,
+ (*crypt)->priv);
+ sec.flags |= (1 << key);
+ /* This ensures a key will be activated if no key is
+ * explicitely set */
+ if (key == sec.active_key)
+ sec.flags |= SEC_ACTIVE_KEY;
+ } else {
+ len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+ NULL, (*crypt)->priv);
+ if (len == 0) {
+ /* Set a default key of all 0 */
+ IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
+ key);
+ memset(sec.keys[key], 0, 13);
+ (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+ (*crypt)->priv);
+ sec.key_sizes[key] = 13;
+ sec.flags |= (1 << key);
+ }
+
+ /* No key data - just set the default TX key index */
+ if (key_provided) {
+ IEEE80211_DEBUG_WX
+ ("Setting key %d to default Tx key.\n", key);
+ ieee->tx_keyidx = key;
+ sec.active_key = key;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+ }
+
+ done:
+ ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+ sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
+ sec.flags |= SEC_AUTH_MODE;
+ IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
+ "OPEN" : "SHARED KEY");
+
+ /* For now we just support WEP, so only set that security level...
+ * TODO: When WPA is added this is one place that needs to change */
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
+
+ if (ieee->set_security)
+ ieee->set_security(dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack. */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port && ieee->reset_port(dev)) {
+ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ int len, key;
+ struct ieee80211_crypt_data *crypt;
+
+ IEEE80211_DEBUG_WX("GET_ENCODE\n");
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ } else
+ key = ieee->tx_keyidx;
+
+ crypt = ieee->crypt[key];
+ erq->flags = key + 1;
+
+ if (crypt == NULL || crypt->ops == NULL) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+
+ if (strcmp(crypt->ops->name, "WEP") != 0) {
+ /* only WEP is supported with wireless extensions, so just
+ * report that encryption is used */
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_ENABLED;
+ return 0;
+ }
+
+ len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
+ erq->length = (len >= 0 ? len : 0);
+
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ if (ieee->open_wep)
+ erq->flags |= IW_ENCODE_OPEN;
+ else
+ erq->flags |= IW_ENCODE_RESTRICTED;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(ieee80211_wx_get_scan);
+EXPORT_SYMBOL(ieee80211_wx_set_encode);
+EXPORT_SYMBOL(ieee80211_wx_get_encode);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 0b3d9f1d8069..e55136ae09f4 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -413,20 +413,19 @@ config INET_TUNNEL
If unsure, say Y.
-config IP_TCPDIAG
- tristate "IP: TCP socket monitoring interface"
+config INET_DIAG
+ tristate "INET: socket monitoring interface"
default y
---help---
- Support for TCP socket monitoring interface used by native Linux
- tools such as ss. ss is included in iproute2, currently downloadable
- at <http://developer.osdl.org/dev/iproute2>. If you want IPv6 support
- and have selected IPv6 as a module, you need to build this as a
- module too.
+ Support for INET (TCP, DCCP, etc) socket monitoring interface used by
+ native Linux tools such as ss. ss is included in iproute2, currently
+ downloadable at <http://developer.osdl.org/dev/iproute2>.
If unsure, say Y.
-config IP_TCPDIAG_IPV6
- def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
+config INET_TCP_DIAG
+ depends on INET_DIAG
+ def_tristate INET_DIAG
config TCP_CONG_ADVANCED
bool "TCP: advanced congestion control"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 55dc6cca1e7b..f0435d00db6b 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -4,11 +4,12 @@
obj-y := route.o inetpeer.o protocol.o \
ip_input.o ip_fragment.o ip_forward.o ip_options.o \
- ip_output.o ip_sockglue.o \
+ ip_output.o ip_sockglue.o inet_hashtables.o \
+ inet_timewait_sock.o inet_connection_sock.o \
tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
tcp_minisocks.o tcp_cong.o \
datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \
- sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
+ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o netfilter.o
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
@@ -29,8 +30,9 @@ obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IP_VS) += ipvs/
-obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o
+obj-$(CONFIG_INET_DIAG) += inet_diag.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 163ae4068b5f..a9d84f93442c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -99,6 +99,7 @@
#include <net/arp.h>
#include <net/route.h>
#include <net/ip_fib.h>
+#include <net/inet_connection_sock.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <linux/skbuff.h>
@@ -112,11 +113,7 @@
#include <linux/mroute.h>
#endif
-DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
-
-#ifdef INET_REFCNT_DEBUG
-atomic_t inet_sock_nr;
-#endif
+DEFINE_SNMP_STAT(struct linux_mib, net_statistics) __read_mostly;
extern void ip_mc_drop_socket(struct sock *sk);
@@ -153,11 +150,7 @@ void inet_sock_destruct(struct sock *sk)
if (inet->opt)
kfree(inet->opt);
dst_release(sk->sk_dst_cache);
-#ifdef INET_REFCNT_DEBUG
- atomic_dec(&inet_sock_nr);
- printk(KERN_DEBUG "INET socket %p released, %d are still alive\n",
- sk, atomic_read(&inet_sock_nr));
-#endif
+ sk_refcnt_debug_dec(sk);
}
/*
@@ -210,7 +203,7 @@ int inet_listen(struct socket *sock, int backlog)
* we can only allow the backlog to be adjusted.
*/
if (old_state != TCP_LISTEN) {
- err = tcp_listen_start(sk);
+ err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
if (err)
goto out;
}
@@ -235,12 +228,14 @@ static int inet_create(struct socket *sock, int protocol)
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
- int err;
+ int try_loading_module = 0;
+ int err = -ESOCKTNOSUPPORT;
sock->state = SS_UNCONNECTED;
/* Look for the requested type/protocol pair. */
answer = NULL;
+lookup_protocol:
rcu_read_lock();
list_for_each_rcu(p, &inetsw[sock->type]) {
answer = list_entry(p, struct inet_protosw, list);
@@ -261,9 +256,28 @@ static int inet_create(struct socket *sock, int protocol)
answer = NULL;
}
- err = -ESOCKTNOSUPPORT;
- if (!answer)
- goto out_rcu_unlock;
+ if (unlikely(answer == NULL)) {
+ if (try_loading_module < 2) {
+ rcu_read_unlock();
+ /*
+ * Be more specific, e.g. net-pf-2-proto-132-type-1
+ * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM)
+ */
+ if (++try_loading_module == 1)
+ request_module("net-pf-%d-proto-%d-type-%d",
+ PF_INET, protocol, sock->type);
+ /*
+ * Fall back to generic, e.g. net-pf-2-proto-132
+ * (net-pf-PF_INET-proto-IPPROTO_SCTP)
+ */
+ else
+ request_module("net-pf-%d-proto-%d",
+ PF_INET, protocol);
+ goto lookup_protocol;
+ } else
+ goto out_rcu_unlock;
+ }
+
err = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
@@ -317,9 +331,7 @@ static int inet_create(struct socket *sock, int protocol)
inet->mc_index = 0;
inet->mc_list = NULL;
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet_sock_nr);
-#endif
+ sk_refcnt_debug_inc(sk);
if (inet->num) {
/* It assumes that any protocol which allows
@@ -847,10 +859,6 @@ static struct net_proto_family inet_family_ops = {
.owner = THIS_MODULE,
};
-
-extern void tcp_init(void);
-extern void tcp_v4_init(struct net_proto_family *);
-
/* Upon startup we insert all the elements in inetsw_array[] into
* the linked list inetsw.
*/
@@ -961,6 +969,119 @@ void inet_unregister_protosw(struct inet_protosw *p)
}
}
+/*
+ * Shall we try to damage output packets if routing dev changes?
+ */
+
+int sysctl_ip_dynaddr;
+
+static int inet_sk_reselect_saddr(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+ int err;
+ struct rtable *rt;
+ __u32 old_saddr = inet->saddr;
+ __u32 new_saddr;
+ __u32 daddr = inet->daddr;
+
+ if (inet->opt && inet->opt->srr)
+ daddr = inet->opt->faddr;
+
+ /* Query new route. */
+ err = ip_route_connect(&rt, daddr, 0,
+ RT_CONN_FLAGS(sk),
+ sk->sk_bound_dev_if,
+ sk->sk_protocol,
+ inet->sport, inet->dport, sk);
+ if (err)
+ return err;
+
+ sk_setup_caps(sk, &rt->u.dst);
+
+ new_saddr = rt->rt_src;
+
+ if (new_saddr == old_saddr)
+ return 0;
+
+ if (sysctl_ip_dynaddr > 1) {
+ printk(KERN_INFO "%s(): shifting inet->"
+ "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ __FUNCTION__,
+ NIPQUAD(old_saddr),
+ NIPQUAD(new_saddr));
+ }
+
+ inet->saddr = inet->rcv_saddr = new_saddr;
+
+ /*
+ * XXX The only one ugly spot where we need to
+ * XXX really change the sockets identity after
+ * XXX it has entered the hashes. -DaveM
+ *
+ * Besides that, it does not check for connection
+ * uniqueness. Wait for troubles.
+ */
+ __sk_prot_rehash(sk);
+ return 0;
+}
+
+int inet_sk_rebuild_header(struct sock *sk)
+{
+ struct inet_sock *inet = inet_sk(sk);
+ struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
+ u32 daddr;
+ int err;
+
+ /* Route is OK, nothing to do. */
+ if (rt)
+ return 0;
+
+ /* Reroute. */
+ daddr = inet->daddr;
+ if (inet->opt && inet->opt->srr)
+ daddr = inet->opt->faddr;
+{
+ struct flowi fl = {
+ .oif = sk->sk_bound_dev_if,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = daddr,
+ .saddr = inet->saddr,
+ .tos = RT_CONN_FLAGS(sk),
+ },
+ },
+ .proto = sk->sk_protocol,
+ .uli_u = {
+ .ports = {
+ .sport = inet->sport,
+ .dport = inet->dport,
+ },
+ },
+ };
+
+ err = ip_route_output_flow(&rt, &fl, sk, 0);
+}
+ if (!err)
+ sk_setup_caps(sk, &rt->u.dst);
+ else {
+ /* Routing failed... */
+ sk->sk_route_caps = 0;
+ /*
+ * Other protocols have to map its equivalent state to TCP_SYN_SENT.
+ * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
+ */
+ if (!sysctl_ip_dynaddr ||
+ sk->sk_state != TCP_SYN_SENT ||
+ (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
+ (err = inet_sk_reselect_saddr(sk)) != 0)
+ sk->sk_err_soft = -err;
+ }
+
+ return err;
+}
+
+EXPORT_SYMBOL(inet_sk_rebuild_header);
+
#ifdef CONFIG_IP_MULTICAST
static struct net_protocol igmp_protocol = {
.handler = igmp_rcv,
@@ -1007,7 +1128,6 @@ static int __init init_ipv4_mibs(void)
}
static int ipv4_proc_init(void);
-extern void ipfrag_init(void);
/*
* IP protocol layer initialiser
@@ -1128,20 +1248,6 @@ module_init(inet_init);
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
-extern int fib_proc_init(void);
-extern void fib_proc_exit(void);
-#ifdef CONFIG_IP_FIB_TRIE
-extern int fib_stat_proc_init(void);
-extern void fib_stat_proc_exit(void);
-#endif
-extern int ip_misc_proc_init(void);
-extern int raw_proc_init(void);
-extern void raw_proc_exit(void);
-extern int tcp4_proc_init(void);
-extern void tcp4_proc_exit(void);
-extern int udp4_proc_init(void);
-extern void udp4_proc_exit(void);
-
static int __init ipv4_proc_init(void)
{
int rc = 0;
@@ -1154,19 +1260,11 @@ static int __init ipv4_proc_init(void)
goto out_udp;
if (fib_proc_init())
goto out_fib;
-#ifdef CONFIG_IP_FIB_TRIE
- if (fib_stat_proc_init())
- goto out_fib_stat;
-#endif
if (ip_misc_proc_init())
goto out_misc;
out:
return rc;
out_misc:
-#ifdef CONFIG_IP_FIB_TRIE
- fib_stat_proc_exit();
-out_fib_stat:
-#endif
fib_proc_exit();
out_fib:
udp4_proc_exit();
@@ -1205,7 +1303,3 @@ EXPORT_SYMBOL(inet_stream_ops);
EXPORT_SYMBOL(inet_unregister_protosw);
EXPORT_SYMBOL(net_statistics);
EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
-
-#ifdef INET_REFCNT_DEBUG
-EXPORT_SYMBOL(inet_sock_nr);
-#endif
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 514c85b2631a..035ad2c9e1ba 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -263,10 +263,8 @@ static int ah_init_state(struct xfrm_state *x)
error:
if (ahp) {
- if (ahp->work_icv)
- kfree(ahp->work_icv);
- if (ahp->tfm)
- crypto_free_tfm(ahp->tfm);
+ kfree(ahp->work_icv);
+ crypto_free_tfm(ahp->tfm);
kfree(ahp);
}
return -EINVAL;
@@ -279,14 +277,10 @@ static void ah_destroy(struct xfrm_state *x)
if (!ahp)
return;
- if (ahp->work_icv) {
- kfree(ahp->work_icv);
- ahp->work_icv = NULL;
- }
- if (ahp->tfm) {
- crypto_free_tfm(ahp->tfm);
- ahp->tfm = NULL;
- }
+ kfree(ahp->work_icv);
+ ahp->work_icv = NULL;
+ crypto_free_tfm(ahp->tfm);
+ ahp->tfm = NULL;
kfree(ahp);
}
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index a642fd612853..8bf312bdea13 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -700,7 +700,7 @@ void arp_send(int type, int ptype, u32 dest_ip,
static void parp_redo(struct sk_buff *skb)
{
nf_reset(skb);
- arp_rcv(skb, skb->dev, NULL);
+ arp_rcv(skb, skb->dev, NULL, skb->dev);
}
/*
@@ -865,7 +865,7 @@ static int arp_process(struct sk_buff *skb)
if (n)
neigh_release(n);
- if (skb->stamp.tv_sec == LOCALLY_ENQUEUED ||
+ if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
skb->pkt_type == PACKET_HOST ||
in_dev->arp_parms->proxy_delay == 0) {
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
@@ -927,7 +927,7 @@ out:
* Receive an arp request from the device layer.
*/
-int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *arp;
@@ -948,6 +948,8 @@ int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
goto out_of_mem;
+ memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
+
return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
freeskb:
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index b1db561f2542..c1b42b5257f8 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -16,9 +16,10 @@
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/in.h>
+#include <net/ip.h>
#include <net/sock.h>
-#include <net/tcp.h>
#include <net/route.h>
+#include <net/tcp_states.h>
int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index d8a10e3dd77d..ba2895ae8151 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1111,13 +1111,12 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
- netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);
else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL);
} else {
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL);
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL);
}
}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index ba57446d5d1f..1b5a09d1b90b 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -331,8 +331,8 @@ static void esp4_err(struct sk_buff *skb, u32 info)
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
if (!x)
return;
- NETDEBUG(printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
- ntohl(esph->spi), ntohl(iph->daddr)));
+ NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
+ ntohl(esph->spi), ntohl(iph->daddr));
xfrm_state_put(x);
}
@@ -343,22 +343,14 @@ static void esp_destroy(struct xfrm_state *x)
if (!esp)
return;
- if (esp->conf.tfm) {
- crypto_free_tfm(esp->conf.tfm);
- esp->conf.tfm = NULL;
- }
- if (esp->conf.ivec) {
- kfree(esp->conf.ivec);
- esp->conf.ivec = NULL;
- }
- if (esp->auth.tfm) {
- crypto_free_tfm(esp->auth.tfm);
- esp->auth.tfm = NULL;
- }
- if (esp->auth.work_icv) {
- kfree(esp->auth.work_icv);
- esp->auth.work_icv = NULL;
- }
+ crypto_free_tfm(esp->conf.tfm);
+ esp->conf.tfm = NULL;
+ kfree(esp->conf.ivec);
+ esp->conf.ivec = NULL;
+ crypto_free_tfm(esp->auth.tfm);
+ esp->auth.tfm = NULL;
+ kfree(esp->auth.work_icv);
+ esp->auth.work_icv = NULL;
kfree(esp);
}
@@ -395,10 +387,10 @@ static int esp_init_state(struct xfrm_state *x)
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_tfm_alg_digestsize(esp->auth.tfm)) {
- NETDEBUG(printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
- x->aalg->alg_name,
- crypto_tfm_alg_digestsize(esp->auth.tfm),
- aalg_desc->uinfo.auth.icv_fullbits/8));
+ NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
+ x->aalg->alg_name,
+ crypto_tfm_alg_digestsize(esp->auth.tfm),
+ aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cd8e45ab9580..4e1379f71269 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -558,16 +558,15 @@ static void nl_fib_input(struct sock *sk, int len)
nl_fib_lookup(frn, tb);
pid = nlh->nlmsg_pid; /*pid of sending process */
- NETLINK_CB(skb).groups = 0; /* not in mcast group */
NETLINK_CB(skb).pid = 0; /* from kernel */
NETLINK_CB(skb).dst_pid = pid;
- NETLINK_CB(skb).dst_groups = 0; /* unicast */
+ NETLINK_CB(skb).dst_group = 0; /* unicast */
netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
}
static void nl_fib_lookup_init(void)
{
- netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+ netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, THIS_MODULE);
}
static void fib_disable_ip(struct net_device *dev, int force)
@@ -662,5 +661,4 @@ void __init ip_fib_init(void)
}
EXPORT_SYMBOL(inet_addr_type);
-EXPORT_SYMBOL(ip_dev_find);
EXPORT_SYMBOL(ip_rt_ioctl);
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index b10d6bb5ef3d..2a8c9afc3695 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -45,8 +45,8 @@
#include "fib_lookup.h"
-static kmem_cache_t *fn_hash_kmem;
-static kmem_cache_t *fn_alias_kmem;
+static kmem_cache_t *fn_hash_kmem __read_mostly;
+static kmem_cache_t *fn_alias_kmem __read_mostly;
struct fib_node {
struct hlist_node fn_hash;
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index b729d97cfa93..ef6609ea0eb7 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -7,6 +7,7 @@
struct fib_alias {
struct list_head fa_list;
+ struct rcu_head rcu;
struct fib_info *fa_info;
u8 fa_tos;
u8 fa_type;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e278cb9d0075..d41219e8037c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -290,10 +290,10 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
kfree_skb(skb);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_ROUTE;
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV4_ROUTE;
if (n->nlmsg_flags&NLM_F_ECHO)
atomic_inc(&skb->users);
- netlink_broadcast(rtnl, skb, pid, RTMGRP_IPV4_ROUTE, GFP_KERNEL);
+ netlink_broadcast(rtnl, skb, pid, RTNLGRP_IPV4_ROUTE, GFP_KERNEL);
if (n->nlmsg_flags&NLM_F_ECHO)
netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
}
@@ -854,6 +854,7 @@ failure:
return NULL;
}
+/* Note! fib_semantic_match intentionally uses RCU list functions. */
int fib_semantic_match(struct list_head *head, const struct flowi *flp,
struct fib_result *res, __u32 zone, __u32 mask,
int prefixlen)
@@ -861,7 +862,7 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp,
struct fib_alias *fa;
int nh_sel = 0;
- list_for_each_entry(fa, head, fa_list) {
+ list_for_each_entry_rcu(fa, head, fa_list) {
int err;
if (fa->fa_tos &&
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 45efd5f4741b..1b63b4824164 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#define VERSION "0.325"
+#define VERSION "0.403"
#include <linux/config.h>
#include <asm/uaccess.h>
@@ -62,6 +62,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
+#include <linux/rcupdate.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/init.h>
@@ -77,56 +78,55 @@
#undef CONFIG_IP_FIB_TRIE_STATS
#define MAX_CHILDS 16384
-#define EXTRACT(p, n, str) ((str)<<(p)>>(32-(n)))
#define KEYLENGTH (8*sizeof(t_key))
#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
-static DEFINE_RWLOCK(fib_lock);
-
typedef unsigned int t_key;
#define T_TNODE 0
#define T_LEAF 1
#define NODE_TYPE_MASK 0x1UL
-#define NODE_PARENT(_node) \
- ((struct tnode *)((_node)->_parent & ~NODE_TYPE_MASK))
-#define NODE_SET_PARENT(_node, _ptr) \
- ((_node)->_parent = (((unsigned long)(_ptr)) | \
- ((_node)->_parent & NODE_TYPE_MASK)))
-#define NODE_INIT_PARENT(_node, _type) \
- ((_node)->_parent = (_type))
-#define NODE_TYPE(_node) \
- ((_node)->_parent & NODE_TYPE_MASK)
-
-#define IS_TNODE(n) (!(n->_parent & T_LEAF))
-#define IS_LEAF(n) (n->_parent & T_LEAF)
+#define NODE_PARENT(node) \
+ ((struct tnode *)rcu_dereference(((node)->parent & ~NODE_TYPE_MASK)))
+
+#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK)
+
+#define NODE_SET_PARENT(node, ptr) \
+ rcu_assign_pointer((node)->parent, \
+ ((unsigned long)(ptr)) | NODE_TYPE(node))
+
+#define IS_TNODE(n) (!(n->parent & T_LEAF))
+#define IS_LEAF(n) (n->parent & T_LEAF)
struct node {
- t_key key;
- unsigned long _parent;
+ t_key key;
+ unsigned long parent;
};
struct leaf {
- t_key key;
- unsigned long _parent;
+ t_key key;
+ unsigned long parent;
struct hlist_head list;
+ struct rcu_head rcu;
};
struct leaf_info {
struct hlist_node hlist;
+ struct rcu_head rcu;
int plen;
struct list_head falh;
};
struct tnode {
- t_key key;
- unsigned long _parent;
- unsigned short pos:5; /* 2log(KEYLENGTH) bits needed */
- unsigned short bits:5; /* 2log(KEYLENGTH) bits needed */
- unsigned short full_children; /* KEYLENGTH bits needed */
- unsigned short empty_children; /* KEYLENGTH bits needed */
- struct node *child[0];
+ t_key key;
+ unsigned long parent;
+ unsigned short pos:5; /* 2log(KEYLENGTH) bits needed */
+ unsigned short bits:5; /* 2log(KEYLENGTH) bits needed */
+ unsigned short full_children; /* KEYLENGTH bits needed */
+ unsigned short empty_children; /* KEYLENGTH bits needed */
+ struct rcu_head rcu;
+ struct node *child[0];
};
#ifdef CONFIG_IP_FIB_TRIE_STATS
@@ -150,77 +150,44 @@ struct trie_stat {
};
struct trie {
- struct node *trie;
+ struct node *trie;
#ifdef CONFIG_IP_FIB_TRIE_STATS
struct trie_use_stats stats;
#endif
- int size;
+ int size;
unsigned int revision;
};
-static int trie_debug = 0;
-
-static int tnode_full(struct tnode *tn, struct node *n);
static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
-static int tnode_child_length(struct tnode *tn);
static struct node *resize(struct trie *t, struct tnode *tn);
-static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err);
-static struct tnode *halve(struct trie *t, struct tnode *tn, int *err);
+static struct tnode *inflate(struct trie *t, struct tnode *tn);
+static struct tnode *halve(struct trie *t, struct tnode *tn);
static void tnode_free(struct tnode *tn);
-static void trie_dump_seq(struct seq_file *seq, struct trie *t);
-extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio);
-extern int fib_detect_death(struct fib_info *fi, int order,
- struct fib_info **last_resort, int *last_idx, int *dflt);
-extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa, int z, int tb_id,
- struct nlmsghdr *n, struct netlink_skb_parms *req);
-
-static kmem_cache_t *fn_alias_kmem;
+static kmem_cache_t *fn_alias_kmem __read_mostly;
static struct trie *trie_local = NULL, *trie_main = NULL;
-static void trie_bug(char *err)
-{
- printk("Trie Bug: %s\n", err);
- BUG();
-}
+
+/* rcu_read_lock needs to be hold by caller from readside */
static inline struct node *tnode_get_child(struct tnode *tn, int i)
{
- if (i >= 1<<tn->bits)
- trie_bug("tnode_get_child");
+ BUG_ON(i >= 1 << tn->bits);
- return tn->child[i];
+ return rcu_dereference(tn->child[i]);
}
-static inline int tnode_child_length(struct tnode *tn)
+static inline int tnode_child_length(const struct tnode *tn)
{
- return 1<<tn->bits;
+ return 1 << tn->bits;
}
-/*
- _________________________________________________________________
- | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
- ----------------------------------------------------------------
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-
- _________________________________________________________________
- | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
- -----------------------------------------------------------------
- 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-
- tp->pos = 7
- tp->bits = 3
- n->pos = 15
- n->bits=4
- KEYLENGTH=32
-*/
-
static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
{
- if (offset < KEYLENGTH)
+ if (offset < KEYLENGTH)
return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
- else
+ else
return 0;
}
@@ -233,8 +200,8 @@ static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
{
if (bits == 0 || offset >= KEYLENGTH)
return 1;
- bits = bits > KEYLENGTH ? KEYLENGTH : bits;
- return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
+ bits = bits > KEYLENGTH ? KEYLENGTH : bits;
+ return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
}
static inline int tkey_mismatch(t_key a, int offset, t_key b)
@@ -249,14 +216,6 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b)
return i;
}
-/* Candiate for fib_semantics */
-
-static void fn_free_alias(struct fib_alias *fa)
-{
- fib_release_info(fa->fa_info);
- kmem_cache_free(fn_alias_kmem, fa);
-}
-
/*
To understand this stuff, an understanding of keys and all their bits is
necessary. Every node in the trie has a key associated with it, but not
@@ -295,7 +254,7 @@ static void fn_free_alias(struct fib_alias *fa)
tp->pos = 7
tp->bits = 3
n->pos = 15
- n->bits=4
+ n->bits = 4
First, let's just ignore the bits that come before the parent tp, that is
the bits from 0 to (tp->pos-1). They are *known* but at this point we do
@@ -320,60 +279,65 @@ static void fn_free_alias(struct fib_alias *fa)
*/
-static void check_tnode(struct tnode *tn)
+static inline void check_tnode(const struct tnode *tn)
{
- if (tn && tn->pos+tn->bits > 32) {
- printk("TNODE ERROR tn=%p, pos=%d, bits=%d\n", tn, tn->pos, tn->bits);
- }
+ WARN_ON(tn && tn->pos+tn->bits > 32);
}
static int halve_threshold = 25;
static int inflate_threshold = 50;
-static struct leaf *leaf_new(void)
+
+static void __alias_free_mem(struct rcu_head *head)
{
- struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL);
- if (l) {
- NODE_INIT_PARENT(l, T_LEAF);
- INIT_HLIST_HEAD(&l->list);
- }
- return l;
+ struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
+ kmem_cache_free(fn_alias_kmem, fa);
}
-static struct leaf_info *leaf_info_new(int plen)
+static inline void alias_free_mem_rcu(struct fib_alias *fa)
{
- struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
- if (li) {
- li->plen = plen;
- INIT_LIST_HEAD(&li->falh);
- }
- return li;
+ call_rcu(&fa->rcu, __alias_free_mem);
+}
+
+static void __leaf_free_rcu(struct rcu_head *head)
+{
+ kfree(container_of(head, struct leaf, rcu));
}
-static inline void free_leaf(struct leaf *l)
+static inline void free_leaf(struct leaf *leaf)
{
- kfree(l);
+ call_rcu(&leaf->rcu, __leaf_free_rcu);
}
-static inline void free_leaf_info(struct leaf_info *li)
+static void __leaf_info_free_rcu(struct rcu_head *head)
{
- kfree(li);
+ kfree(container_of(head, struct leaf_info, rcu));
+}
+
+static inline void free_leaf_info(struct leaf_info *leaf)
+{
+ call_rcu(&leaf->rcu, __leaf_info_free_rcu);
}
static struct tnode *tnode_alloc(unsigned int size)
{
- if (size <= PAGE_SIZE) {
- return kmalloc(size, GFP_KERNEL);
- } else {
- return (struct tnode *)
- __get_free_pages(GFP_KERNEL, get_order(size));
- }
+ struct page *pages;
+
+ if (size <= PAGE_SIZE)
+ return kcalloc(size, 1, GFP_KERNEL);
+
+ pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
+ if (!pages)
+ return NULL;
+
+ return page_address(pages);
}
-static void __tnode_free(struct tnode *tn)
+static void __tnode_free_rcu(struct rcu_head *head)
{
+ struct tnode *tn = container_of(head, struct tnode, rcu);
unsigned int size = sizeof(struct tnode) +
- (1<<tn->bits) * sizeof(struct node *);
+ (1 << tn->bits) * sizeof(struct node *);
if (size <= PAGE_SIZE)
kfree(tn);
@@ -381,15 +345,40 @@ static void __tnode_free(struct tnode *tn)
free_pages((unsigned long)tn, get_order(size));
}
+static inline void tnode_free(struct tnode *tn)
+{
+ call_rcu(&tn->rcu, __tnode_free_rcu);
+}
+
+static struct leaf *leaf_new(void)
+{
+ struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL);
+ if (l) {
+ l->parent = T_LEAF;
+ INIT_HLIST_HEAD(&l->list);
+ }
+ return l;
+}
+
+static struct leaf_info *leaf_info_new(int plen)
+{
+ struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
+ if (li) {
+ li->plen = plen;
+ INIT_LIST_HEAD(&li->falh);
+ }
+ return li;
+}
+
static struct tnode* tnode_new(t_key key, int pos, int bits)
{
int nchildren = 1<<bits;
int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
struct tnode *tn = tnode_alloc(sz);
- if (tn) {
+ if (tn) {
memset(tn, 0, sz);
- NODE_INIT_PARENT(tn, T_TNODE);
+ tn->parent = T_TNODE;
tn->pos = pos;
tn->bits = bits;
tn->key = key;
@@ -397,38 +386,17 @@ static struct tnode* tnode_new(t_key key, int pos, int bits)
tn->empty_children = 1<<bits;
}
- if (trie_debug > 0)
- printk("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
- (unsigned int) (sizeof(struct node) * 1<<bits));
+ pr_debug("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
+ (unsigned int) (sizeof(struct node) * 1<<bits));
return tn;
}
-static void tnode_free(struct tnode *tn)
-{
- if (!tn) {
- trie_bug("tnode_free\n");
- }
- if (IS_LEAF(tn)) {
- free_leaf((struct leaf *)tn);
- if (trie_debug > 0 )
- printk("FL %p \n", tn);
- }
- else if (IS_TNODE(tn)) {
- __tnode_free(tn);
- if (trie_debug > 0 )
- printk("FT %p \n", tn);
- }
- else {
- trie_bug("tnode_free\n");
- }
-}
-
/*
* Check whether a tnode 'n' is "full", i.e. it is an internal node
* and no bits are skipped. See discussion in dyntree paper p. 6
*/
-static inline int tnode_full(struct tnode *tn, struct node *n)
+static inline int tnode_full(const struct tnode *tn, const struct node *n)
{
if (n == NULL || IS_LEAF(n))
return 0;
@@ -448,15 +416,11 @@ static inline void put_child(struct trie *t, struct tnode *tn, int i, struct nod
static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull)
{
- struct node *chi;
+ struct node *chi = tn->child[i];
int isfull;
- if (i >= 1<<tn->bits) {
- printk("bits=%d, i=%d\n", tn->bits, i);
- trie_bug("tnode_put_child_reorg bits");
- }
- write_lock_bh(&fib_lock);
- chi = tn->child[i];
+ BUG_ON(i >= 1<<tn->bits);
+
/* update emptyChildren */
if (n == NULL && chi != NULL)
@@ -465,33 +429,32 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int w
tn->empty_children--;
/* update fullChildren */
- if (wasfull == -1)
+ if (wasfull == -1)
wasfull = tnode_full(tn, chi);
isfull = tnode_full(tn, n);
if (wasfull && !isfull)
tn->full_children--;
-
else if (!wasfull && isfull)
tn->full_children++;
+
if (n)
NODE_SET_PARENT(n, tn);
- tn->child[i] = n;
- write_unlock_bh(&fib_lock);
+ rcu_assign_pointer(tn->child[i], n);
}
static struct node *resize(struct trie *t, struct tnode *tn)
{
int i;
int err = 0;
+ struct tnode *old_tn;
if (!tn)
return NULL;
- if (trie_debug)
- printk("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
- tn, inflate_threshold, halve_threshold);
+ pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
+ tn, inflate_threshold, halve_threshold);
/* No children */
if (tn->empty_children == tnode_child_length(tn)) {
@@ -501,20 +464,16 @@ static struct node *resize(struct trie *t, struct tnode *tn)
/* One child */
if (tn->empty_children == tnode_child_length(tn) - 1)
for (i = 0; i < tnode_child_length(tn); i++) {
+ struct node *n;
- write_lock_bh(&fib_lock);
- if (tn->child[i] != NULL) {
-
- /* compress one level */
- struct node *n = tn->child[i];
- if (n)
- NODE_INIT_PARENT(n, NODE_TYPE(n));
+ n = tn->child[i];
+ if (!n)
+ continue;
- write_unlock_bh(&fib_lock);
- tnode_free(tn);
- return n;
- }
- write_unlock_bh(&fib_lock);
+ /* compress one level */
+ NODE_SET_PARENT(n, NULL);
+ tnode_free(tn);
+ return n;
}
/*
* Double as long as the resulting node has a number of
@@ -566,16 +525,16 @@ static struct node *resize(struct trie *t, struct tnode *tn)
*
* expand not_to_be_doubled and to_be_doubled, and shorten:
* 100 * (tnode_child_length(tn) - tn->empty_children +
- * tn->full_children ) >= inflate_threshold * new_child_length
+ * tn->full_children) >= inflate_threshold * new_child_length
*
* expand new_child_length:
* 100 * (tnode_child_length(tn) - tn->empty_children +
- * tn->full_children ) >=
+ * tn->full_children) >=
* inflate_threshold * tnode_child_length(tn) * 2
*
* shorten again:
* 50 * (tn->full_children + tnode_child_length(tn) -
- * tn->empty_children ) >= inflate_threshold *
+ * tn->empty_children) >= inflate_threshold *
* tnode_child_length(tn)
*
*/
@@ -587,9 +546,10 @@ static struct node *resize(struct trie *t, struct tnode *tn)
50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
inflate_threshold * tnode_child_length(tn))) {
- tn = inflate(t, tn, &err);
-
- if (err) {
+ old_tn = tn;
+ tn = inflate(t, tn);
+ if (IS_ERR(tn)) {
+ tn = old_tn;
#ifdef CONFIG_IP_FIB_TRIE_STATS
t->stats.resize_node_skipped++;
#endif
@@ -609,9 +569,10 @@ static struct node *resize(struct trie *t, struct tnode *tn)
100 * (tnode_child_length(tn) - tn->empty_children) <
halve_threshold * tnode_child_length(tn)) {
- tn = halve(t, tn, &err);
-
- if (err) {
+ old_tn = tn;
+ tn = halve(t, tn);
+ if (IS_ERR(tn)) {
+ tn = old_tn;
#ifdef CONFIG_IP_FIB_TRIE_STATS
t->stats.resize_node_skipped++;
#endif
@@ -621,44 +582,37 @@ static struct node *resize(struct trie *t, struct tnode *tn)
/* Only one child remains */
-
if (tn->empty_children == tnode_child_length(tn) - 1)
for (i = 0; i < tnode_child_length(tn); i++) {
-
- write_lock_bh(&fib_lock);
- if (tn->child[i] != NULL) {
- /* compress one level */
- struct node *n = tn->child[i];
-
- if (n)
- NODE_INIT_PARENT(n, NODE_TYPE(n));
-
- write_unlock_bh(&fib_lock);
- tnode_free(tn);
- return n;
- }
- write_unlock_bh(&fib_lock);
+ struct node *n;
+
+ n = tn->child[i];
+ if (!n)
+ continue;
+
+ /* compress one level */
+
+ NODE_SET_PARENT(n, NULL);
+ tnode_free(tn);
+ return n;
}
return (struct node *) tn;
}
-static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err)
+static struct tnode *inflate(struct trie *t, struct tnode *tn)
{
struct tnode *inode;
struct tnode *oldtnode = tn;
int olen = tnode_child_length(tn);
int i;
- if (trie_debug)
- printk("In inflate\n");
+ pr_debug("In inflate\n");
tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
- if (!tn) {
- *err = -ENOMEM;
- return oldtnode;
- }
+ if (!tn)
+ return ERR_PTR(-ENOMEM);
/*
* Preallocate and store tnodes before the actual work so we
@@ -666,8 +620,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err)
* fails. In case of failure we return the oldnode and inflate
* of tnode is ignored.
*/
-
- for(i = 0; i < olen; i++) {
+
+ for (i = 0; i < olen; i++) {
struct tnode *inode = (struct tnode *) tnode_get_child(oldtnode, i);
if (inode &&
@@ -675,46 +629,30 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err)
inode->pos == oldtnode->pos + oldtnode->bits &&
inode->bits > 1) {
struct tnode *left, *right;
-
t_key m = TKEY_GET_MASK(inode->pos, 1);
left = tnode_new(inode->key&(~m), inode->pos + 1,
inode->bits - 1);
+ if (!left)
+ goto nomem;
- if (!left) {
- *err = -ENOMEM;
- break;
- }
-
right = tnode_new(inode->key|m, inode->pos + 1,
inode->bits - 1);
- if (!right) {
- *err = -ENOMEM;
- break;
- }
+ if (!right) {
+ tnode_free(left);
+ goto nomem;
+ }
put_child(t, tn, 2*i, (struct node *) left);
put_child(t, tn, 2*i+1, (struct node *) right);
}
}
- if (*err) {
- int size = tnode_child_length(tn);
- int j;
-
- for(j = 0; j < size; j++)
- if (tn->child[j])
- tnode_free((struct tnode *)tn->child[j]);
-
- tnode_free(tn);
-
- *err = -ENOMEM;
- return oldtnode;
- }
-
- for(i = 0; i < olen; i++) {
+ for (i = 0; i < olen; i++) {
struct node *node = tnode_get_child(oldtnode, i);
+ struct tnode *left, *right;
+ int size, j;
/* An empty child */
if (node == NULL)
@@ -740,76 +678,82 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err)
put_child(t, tn, 2*i+1, inode->child[1]);
tnode_free(inode);
+ continue;
}
- /* An internal node with more than two children */
- else {
- struct tnode *left, *right;
- int size, j;
-
- /* We will replace this node 'inode' with two new
- * ones, 'left' and 'right', each with half of the
- * original children. The two new nodes will have
- * a position one bit further down the key and this
- * means that the "significant" part of their keys
- * (see the discussion near the top of this file)
- * will differ by one bit, which will be "0" in
- * left's key and "1" in right's key. Since we are
- * moving the key position by one step, the bit that
- * we are moving away from - the bit at position
- * (inode->pos) - is the one that will differ between
- * left and right. So... we synthesize that bit in the
- * two new keys.
- * The mask 'm' below will be a single "one" bit at
- * the position (inode->pos)
- */
-
- /* Use the old key, but set the new significant
- * bit to zero.
- */
-
- left = (struct tnode *) tnode_get_child(tn, 2*i);
- put_child(t, tn, 2*i, NULL);
+ /* An internal node with more than two children */
+
+ /* We will replace this node 'inode' with two new
+ * ones, 'left' and 'right', each with half of the
+ * original children. The two new nodes will have
+ * a position one bit further down the key and this
+ * means that the "significant" part of their keys
+ * (see the discussion near the top of this file)
+ * will differ by one bit, which will be "0" in
+ * left's key and "1" in right's key. Since we are
+ * moving the key position by one step, the bit that
+ * we are moving away from - the bit at position
+ * (inode->pos) - is the one that will differ between
+ * left and right. So... we synthesize that bit in the
+ * two new keys.
+ * The mask 'm' below will be a single "one" bit at
+ * the position (inode->pos)
+ */
- if (!left)
- BUG();
+ /* Use the old key, but set the new significant
+ * bit to zero.
+ */
- right = (struct tnode *) tnode_get_child(tn, 2*i+1);
- put_child(t, tn, 2*i+1, NULL);
+ left = (struct tnode *) tnode_get_child(tn, 2*i);
+ put_child(t, tn, 2*i, NULL);
- if (!right)
- BUG();
+ BUG_ON(!left);
- size = tnode_child_length(left);
- for(j = 0; j < size; j++) {
- put_child(t, left, j, inode->child[j]);
- put_child(t, right, j, inode->child[j + size]);
- }
- put_child(t, tn, 2*i, resize(t, left));
- put_child(t, tn, 2*i+1, resize(t, right));
+ right = (struct tnode *) tnode_get_child(tn, 2*i+1);
+ put_child(t, tn, 2*i+1, NULL);
- tnode_free(inode);
+ BUG_ON(!right);
+
+ size = tnode_child_length(left);
+ for (j = 0; j < size; j++) {
+ put_child(t, left, j, inode->child[j]);
+ put_child(t, right, j, inode->child[j + size]);
}
+ put_child(t, tn, 2*i, resize(t, left));
+ put_child(t, tn, 2*i+1, resize(t, right));
+
+ tnode_free(inode);
}
tnode_free(oldtnode);
return tn;
+nomem:
+ {
+ int size = tnode_child_length(tn);
+ int j;
+
+ for (j = 0; j < size; j++)
+ if (tn->child[j])
+ tnode_free((struct tnode *)tn->child[j]);
+
+ tnode_free(tn);
+
+ return ERR_PTR(-ENOMEM);
+ }
}
-static struct tnode *halve(struct trie *t, struct tnode *tn, int *err)
+static struct tnode *halve(struct trie *t, struct tnode *tn)
{
struct tnode *oldtnode = tn;
struct node *left, *right;
int i;
int olen = tnode_child_length(tn);
- if (trie_debug) printk("In halve\n");
+ pr_debug("In halve\n");
tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
- if (!tn) {
- *err = -ENOMEM;
- return oldtnode;
- }
+ if (!tn)
+ return ERR_PTR(-ENOMEM);
/*
* Preallocate and store tnodes before the actual work so we
@@ -818,38 +762,27 @@ static struct tnode *halve(struct trie *t, struct tnode *tn, int *err)
* of tnode is ignored.
*/
- for(i = 0; i < olen; i += 2) {
+ for (i = 0; i < olen; i += 2) {
left = tnode_get_child(oldtnode, i);
right = tnode_get_child(oldtnode, i+1);
/* Two nonempty children */
- if (left && right) {
- struct tnode *newBinNode =
- tnode_new(left->key, tn->pos + tn->bits, 1);
+ if (left && right) {
+ struct tnode *newn;
- if (!newBinNode) {
- *err = -ENOMEM;
- break;
- }
- put_child(t, tn, i/2, (struct node *)newBinNode);
- }
- }
+ newn = tnode_new(left->key, tn->pos + tn->bits, 1);
- if (*err) {
- int size = tnode_child_length(tn);
- int j;
+ if (!newn)
+ goto nomem;
- for(j = 0; j < size; j++)
- if (tn->child[j])
- tnode_free((struct tnode *)tn->child[j]);
+ put_child(t, tn, i/2, (struct node *)newn);
+ }
- tnode_free(tn);
-
- *err = -ENOMEM;
- return oldtnode;
}
- for(i = 0; i < olen; i += 2) {
+ for (i = 0; i < olen; i += 2) {
+ struct tnode *newBinNode;
+
left = tnode_get_child(oldtnode, i);
right = tnode_get_child(oldtnode, i+1);
@@ -858,88 +791,99 @@ static struct tnode *halve(struct trie *t, struct tnode *tn, int *err)
if (right == NULL) /* Both are empty */
continue;
put_child(t, tn, i/2, right);
- } else if (right == NULL)
+ continue;
+ }
+
+ if (right == NULL) {
put_child(t, tn, i/2, left);
+ continue;
+ }
/* Two nonempty children */
- else {
- struct tnode *newBinNode =
- (struct tnode *) tnode_get_child(tn, i/2);
- put_child(t, tn, i/2, NULL);
-
- if (!newBinNode)
- BUG();
-
- put_child(t, newBinNode, 0, left);
- put_child(t, newBinNode, 1, right);
- put_child(t, tn, i/2, resize(t, newBinNode));
- }
+ newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
+ put_child(t, tn, i/2, NULL);
+ put_child(t, newBinNode, 0, left);
+ put_child(t, newBinNode, 1, right);
+ put_child(t, tn, i/2, resize(t, newBinNode));
}
tnode_free(oldtnode);
return tn;
+nomem:
+ {
+ int size = tnode_child_length(tn);
+ int j;
+
+ for (j = 0; j < size; j++)
+ if (tn->child[j])
+ tnode_free((struct tnode *)tn->child[j]);
+
+ tnode_free(tn);
+
+ return ERR_PTR(-ENOMEM);
+ }
}
-static void *trie_init(struct trie *t)
+static void trie_init(struct trie *t)
{
- if (t) {
- t->size = 0;
- t->trie = NULL;
- t->revision = 0;
+ if (!t)
+ return;
+
+ t->size = 0;
+ rcu_assign_pointer(t->trie, NULL);
+ t->revision = 0;
#ifdef CONFIG_IP_FIB_TRIE_STATS
- memset(&t->stats, 0, sizeof(struct trie_use_stats));
+ memset(&t->stats, 0, sizeof(struct trie_use_stats));
#endif
- }
- return t;
}
+/* readside most use rcu_read_lock currently dump routines
+ via get_fa_head and dump */
+
static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
{
struct hlist_node *node;
struct leaf_info *li;
- hlist_for_each_entry(li, node, head, hlist) {
+ hlist_for_each_entry_rcu(li, node, head, hlist)
if (li->plen == plen)
return li;
- }
+
return NULL;
}
static inline struct list_head * get_fa_head(struct leaf *l, int plen)
{
- struct list_head *fa_head = NULL;
struct leaf_info *li = find_leaf_info(&l->list, plen);
- if (li)
- fa_head = &li->falh;
+ if (!li)
+ return NULL;
- return fa_head;
+ return &li->falh;
}
static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
{
- struct leaf_info *li = NULL, *last = NULL;
- struct hlist_node *node, *tmp;
-
- write_lock_bh(&fib_lock);
-
- if (hlist_empty(head))
- hlist_add_head(&new->hlist, head);
- else {
- hlist_for_each_entry_safe(li, node, tmp, head, hlist) {
-
- if (new->plen > li->plen)
- break;
-
- last = li;
- }
- if (last)
- hlist_add_after(&last->hlist, &new->hlist);
- else
- hlist_add_before(&new->hlist, &li->hlist);
- }
- write_unlock_bh(&fib_lock);
+ struct leaf_info *li = NULL, *last = NULL;
+ struct hlist_node *node;
+
+ if (hlist_empty(head)) {
+ hlist_add_head_rcu(&new->hlist, head);
+ } else {
+ hlist_for_each_entry(li, node, head, hlist) {
+ if (new->plen > li->plen)
+ break;
+
+ last = li;
+ }
+ if (last)
+ hlist_add_after_rcu(&last->hlist, &new->hlist);
+ else
+ hlist_add_before_rcu(&new->hlist, &li->hlist);
+ }
}
+/* rcu_read_lock needs to be hold by caller from readside */
+
static struct leaf *
fib_find_node(struct trie *t, u32 key)
{
@@ -948,61 +892,43 @@ fib_find_node(struct trie *t, u32 key)
struct node *n;
pos = 0;
- n = t->trie;
+ n = rcu_dereference(t->trie);
while (n != NULL && NODE_TYPE(n) == T_TNODE) {
tn = (struct tnode *) n;
-
+
check_tnode(tn);
-
+
if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
- pos=tn->pos + tn->bits;
+ pos = tn->pos + tn->bits;
n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
- }
- else
+ } else
break;
}
/* Case we have found a leaf. Compare prefixes */
- if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
- struct leaf *l = (struct leaf *) n;
- return l;
- }
+ if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
+ return (struct leaf *)n;
+
return NULL;
}
static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
{
- int i = 0;
int wasfull;
t_key cindex, key;
struct tnode *tp = NULL;
- if (!tn)
- BUG();
-
key = tn->key;
- i = 0;
while (tn != NULL && NODE_PARENT(tn) != NULL) {
- if (i > 10) {
- printk("Rebalance tn=%p \n", tn);
- if (tn) printk("tn->parent=%p \n", NODE_PARENT(tn));
-
- printk("Rebalance tp=%p \n", tp);
- if (tp) printk("tp->parent=%p \n", NODE_PARENT(tp));
- }
-
- if (i > 12) BUG();
- i++;
-
tp = NODE_PARENT(tn);
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
tn = (struct tnode *) resize (t, (struct tnode *)tn);
tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull);
-
+
if (!NODE_PARENT(tn))
break;
@@ -1015,6 +941,8 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
return (struct node*) tn;
}
+/* only used from updater-side */
+
static struct list_head *
fib_insert_node(struct trie *t, int *err, u32 key, int plen)
{
@@ -1050,20 +978,16 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
while (n != NULL && NODE_TYPE(n) == T_TNODE) {
tn = (struct tnode *) n;
-
+
check_tnode(tn);
-
+
if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
tp = tn;
- pos=tn->pos + tn->bits;
+ pos = tn->pos + tn->bits;
n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
- if (n && NODE_PARENT(n) != tn) {
- printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
- BUG();
- }
- }
- else
+ BUG_ON(n && NODE_PARENT(n) != tn);
+ } else
break;
}
@@ -1073,17 +997,15 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
* tp is n's (parent) ----> NULL or TNODE
*/
- if (tp && IS_LEAF(tp))
- BUG();
-
+ BUG_ON(tp && IS_LEAF(tp));
/* Case 1: n is a leaf. Compare prefixes */
if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
- struct leaf *l = ( struct leaf *) n;
-
+ struct leaf *l = (struct leaf *) n;
+
li = leaf_info_new(plen);
-
+
if (!li) {
*err = -ENOMEM;
goto err;
@@ -1113,35 +1035,29 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
fa_head = &li->falh;
insert_leaf_info(&l->list, li);
- /* Case 2: n is NULL, and will just insert a new leaf */
if (t->trie && n == NULL) {
+ /* Case 2: n is NULL, and will just insert a new leaf */
NODE_SET_PARENT(l, tp);
-
- if (!tp)
- BUG();
- else {
- cindex = tkey_extract_bits(key, tp->pos, tp->bits);
- put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
- }
- }
- /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
- else {
+ cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+ put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
+ } else {
+ /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
/*
* Add a new tnode here
* first tnode need some special handling
*/
if (tp)
- pos=tp->pos+tp->bits;
+ pos = tp->pos+tp->bits;
else
- pos=0;
+ pos = 0;
+
if (n) {
newpos = tkey_mismatch(key, pos, n->key);
tn = tnode_new(n->key, newpos, 1);
- }
- else {
+ } else {
newpos = 0;
tn = tnode_new(key, newpos, 1); /* First tnode */
}
@@ -1151,32 +1067,33 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
tnode_free((struct tnode *) l);
*err = -ENOMEM;
goto err;
- }
-
+ }
+
NODE_SET_PARENT(tn, tp);
- missbit=tkey_extract_bits(key, newpos, 1);
+ missbit = tkey_extract_bits(key, newpos, 1);
put_child(t, tn, missbit, (struct node *)l);
put_child(t, tn, 1-missbit, n);
if (tp) {
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
put_child(t, (struct tnode *)tp, cindex, (struct node *)tn);
- }
- else {
- t->trie = (struct node*) tn; /* First tnode */
+ } else {
+ rcu_assign_pointer(t->trie, (struct node *)tn); /* First tnode */
tp = tn;
}
}
- if (tp && tp->pos+tp->bits > 32) {
+
+ if (tp && tp->pos + tp->bits > 32)
printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
tp, tp->pos, tp->bits, key, plen);
- }
+
/* Rebalance the trie */
- t->trie = trie_rebalance(t, tp);
+
+ rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
done:
t->revision++;
-err:;
+err:
return fa_head;
}
@@ -1204,17 +1121,18 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
key = ntohl(key);
- if (trie_debug)
- printk("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
+ pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
- mask = ntohl( inet_make_mask(plen) );
+ mask = ntohl(inet_make_mask(plen));
if (key & ~mask)
return -EINVAL;
key = key & mask;
- if ((fi = fib_create_info(r, rta, nlhdr, &err)) == NULL)
+ fi = fib_create_info(r, rta, nlhdr, &err);
+
+ if (!fi)
goto err;
l = fib_find_node(t, key);
@@ -1236,8 +1154,7 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
* and we need to allocate a new one of those as well.
*/
- if (fa &&
- fa->fa_info->fib_priority == fi->fib_priority) {
+ if (fa && fa->fa_info->fib_priority == fi->fib_priority) {
struct fib_alias *fa_orig;
err = -EEXIST;
@@ -1248,22 +1165,27 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
struct fib_info *fi_drop;
u8 state;
- write_lock_bh(&fib_lock);
+ err = -ENOBUFS;
+ new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+ if (new_fa == NULL)
+ goto out;
fi_drop = fa->fa_info;
- fa->fa_info = fi;
- fa->fa_type = type;
- fa->fa_scope = r->rtm_scope;
+ new_fa->fa_tos = fa->fa_tos;
+ new_fa->fa_info = fi;
+ new_fa->fa_type = type;
+ new_fa->fa_scope = r->rtm_scope;
state = fa->fa_state;
- fa->fa_state &= ~FA_S_ACCESSED;
+ new_fa->fa_state &= ~FA_S_ACCESSED;
- write_unlock_bh(&fib_lock);
+ list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
+ alias_free_mem_rcu(fa);
fib_release_info(fi_drop);
if (state & FA_S_ACCESSED)
- rt_cache_flush(-1);
+ rt_cache_flush(-1);
- goto succeeded;
+ goto succeeded;
}
/* Error if we find a perfect match which
* uses the same scope, type, and nexthop
@@ -1285,7 +1207,7 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
fa = fa_orig;
}
err = -ENOENT;
- if (!(nlhdr->nlmsg_flags&NLM_F_CREATE))
+ if (!(nlhdr->nlmsg_flags & NLM_F_CREATE))
goto out;
err = -ENOBUFS;
@@ -1298,9 +1220,6 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
new_fa->fa_type = type;
new_fa->fa_scope = r->rtm_scope;
new_fa->fa_state = 0;
-#if 0
- new_fa->dst = NULL;
-#endif
/*
* Insert new entry to the list.
*/
@@ -1312,12 +1231,8 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
goto out_free_new_fa;
}
- write_lock_bh(&fib_lock);
-
- list_add_tail(&new_fa->fa_list,
- (fa ? &fa->fa_list : fa_head));
-
- write_unlock_bh(&fib_lock);
+ list_add_tail_rcu(&new_fa->fa_list,
+ (fa ? &fa->fa_list : fa_head));
rt_cache_flush(-1);
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
@@ -1328,11 +1243,14 @@ out_free_new_fa:
kmem_cache_free(fn_alias_kmem, new_fa);
out:
fib_release_info(fi);
-err:;
+err:
return err;
}
-static inline int check_leaf(struct trie *t, struct leaf *l, t_key key, int *plen, const struct flowi *flp,
+
+/* should be clalled with rcu_read_lock */
+static inline int check_leaf(struct trie *t, struct leaf *l,
+ t_key key, int *plen, const struct flowi *flp,
struct fib_result *res)
{
int err, i;
@@ -1341,8 +1259,7 @@ static inline int check_leaf(struct trie *t, struct leaf *l, t_key key, int *pl
struct hlist_head *hhead = &l->list;
struct hlist_node *node;
- hlist_for_each_entry(li, node, hhead, hlist) {
-
+ hlist_for_each_entry_rcu(li, node, hhead, hlist) {
i = li->plen;
mask = ntohl(inet_make_mask(i));
if (l->key != (key & mask))
@@ -1370,13 +1287,17 @@ fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
struct node *n;
struct tnode *pn;
int pos, bits;
- t_key key=ntohl(flp->fl4_dst);
+ t_key key = ntohl(flp->fl4_dst);
int chopped_off;
t_key cindex = 0;
int current_prefix_length = KEYLENGTH;
- n = t->trie;
+ struct tnode *cn;
+ t_key node_prefix, key_prefix, pref_mismatch;
+ int mp;
- read_lock(&fib_lock);
+ rcu_read_lock();
+
+ n = rcu_dereference(t->trie);
if (!n)
goto failed;
@@ -1393,8 +1314,7 @@ fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
pn = (struct tnode *) n;
chopped_off = 0;
- while (pn) {
-
+ while (pn) {
pos = pn->pos;
bits = pn->bits;
@@ -1410,130 +1330,129 @@ fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
goto backtrace;
}
- if (IS_TNODE(n)) {
+ if (IS_LEAF(n)) {
+ if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
+ goto found;
+ else
+ goto backtrace;
+ }
+
#define HL_OPTIMIZE
#ifdef HL_OPTIMIZE
- struct tnode *cn = (struct tnode *)n;
- t_key node_prefix, key_prefix, pref_mismatch;
- int mp;
-
- /*
- * It's a tnode, and we can do some extra checks here if we
- * like, to avoid descending into a dead-end branch.
- * This tnode is in the parent's child array at index
- * key[p_pos..p_pos+p_bits] but potentially with some bits
- * chopped off, so in reality the index may be just a
- * subprefix, padded with zero at the end.
- * We can also take a look at any skipped bits in this
- * tnode - everything up to p_pos is supposed to be ok,
- * and the non-chopped bits of the index (se previous
- * paragraph) are also guaranteed ok, but the rest is
- * considered unknown.
- *
- * The skipped bits are key[pos+bits..cn->pos].
- */
-
- /* If current_prefix_length < pos+bits, we are already doing
- * actual prefix matching, which means everything from
- * pos+(bits-chopped_off) onward must be zero along some
- * branch of this subtree - otherwise there is *no* valid
- * prefix present. Here we can only check the skipped
- * bits. Remember, since we have already indexed into the
- * parent's child array, we know that the bits we chopped of
- * *are* zero.
- */
-
- /* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
-
- if (current_prefix_length < pos+bits) {
- if (tkey_extract_bits(cn->key, current_prefix_length,
- cn->pos - current_prefix_length) != 0 ||
- !(cn->child[0]))
- goto backtrace;
+ cn = (struct tnode *)n;
+
+ /*
+ * It's a tnode, and we can do some extra checks here if we
+ * like, to avoid descending into a dead-end branch.
+ * This tnode is in the parent's child array at index
+ * key[p_pos..p_pos+p_bits] but potentially with some bits
+ * chopped off, so in reality the index may be just a
+ * subprefix, padded with zero at the end.
+ * We can also take a look at any skipped bits in this
+ * tnode - everything up to p_pos is supposed to be ok,
+ * and the non-chopped bits of the index (se previous
+ * paragraph) are also guaranteed ok, but the rest is
+ * considered unknown.
+ *
+ * The skipped bits are key[pos+bits..cn->pos].
+ */
+
+ /* If current_prefix_length < pos+bits, we are already doing
+ * actual prefix matching, which means everything from
+ * pos+(bits-chopped_off) onward must be zero along some
+ * branch of this subtree - otherwise there is *no* valid
+ * prefix present. Here we can only check the skipped
+ * bits. Remember, since we have already indexed into the
+ * parent's child array, we know that the bits we chopped of
+ * *are* zero.
+ */
+
+ /* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
+
+ if (current_prefix_length < pos+bits) {
+ if (tkey_extract_bits(cn->key, current_prefix_length,
+ cn->pos - current_prefix_length) != 0 ||
+ !(cn->child[0]))
+ goto backtrace;
+ }
+
+ /*
+ * If chopped_off=0, the index is fully validated and we
+ * only need to look at the skipped bits for this, the new,
+ * tnode. What we actually want to do is to find out if
+ * these skipped bits match our key perfectly, or if we will
+ * have to count on finding a matching prefix further down,
+ * because if we do, we would like to have some way of
+ * verifying the existence of such a prefix at this point.
+ */
+
+ /* The only thing we can do at this point is to verify that
+ * any such matching prefix can indeed be a prefix to our
+ * key, and if the bits in the node we are inspecting that
+ * do not match our key are not ZERO, this cannot be true.
+ * Thus, find out where there is a mismatch (before cn->pos)
+ * and verify that all the mismatching bits are zero in the
+ * new tnode's key.
+ */
+
+ /* Note: We aren't very concerned about the piece of the key
+ * that precede pn->pos+pn->bits, since these have already been
+ * checked. The bits after cn->pos aren't checked since these are
+ * by definition "unknown" at this point. Thus, what we want to
+ * see is if we are about to enter the "prefix matching" state,
+ * and in that case verify that the skipped bits that will prevail
+ * throughout this subtree are zero, as they have to be if we are
+ * to find a matching prefix.
+ */
+
+ node_prefix = MASK_PFX(cn->key, cn->pos);
+ key_prefix = MASK_PFX(key, cn->pos);
+ pref_mismatch = key_prefix^node_prefix;
+ mp = 0;
+
+ /* In short: If skipped bits in this node do not match the search
+ * key, enter the "prefix matching" state.directly.
+ */
+ if (pref_mismatch) {
+ while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
+ mp++;
+ pref_mismatch = pref_mismatch <<1;
}
+ key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
- /*
- * If chopped_off=0, the index is fully validated and we
- * only need to look at the skipped bits for this, the new,
- * tnode. What we actually want to do is to find out if
- * these skipped bits match our key perfectly, or if we will
- * have to count on finding a matching prefix further down,
- * because if we do, we would like to have some way of
- * verifying the existence of such a prefix at this point.
- */
-
- /* The only thing we can do at this point is to verify that
- * any such matching prefix can indeed be a prefix to our
- * key, and if the bits in the node we are inspecting that
- * do not match our key are not ZERO, this cannot be true.
- * Thus, find out where there is a mismatch (before cn->pos)
- * and verify that all the mismatching bits are zero in the
- * new tnode's key.
- */
-
- /* Note: We aren't very concerned about the piece of the key
- * that precede pn->pos+pn->bits, since these have already been
- * checked. The bits after cn->pos aren't checked since these are
- * by definition "unknown" at this point. Thus, what we want to
- * see is if we are about to enter the "prefix matching" state,
- * and in that case verify that the skipped bits that will prevail
- * throughout this subtree are zero, as they have to be if we are
- * to find a matching prefix.
- */
-
- node_prefix = MASK_PFX(cn->key, cn->pos);
- key_prefix = MASK_PFX(key, cn->pos);
- pref_mismatch = key_prefix^node_prefix;
- mp = 0;
-
- /* In short: If skipped bits in this node do not match the search
- * key, enter the "prefix matching" state.directly.
- */
- if (pref_mismatch) {
- while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
- mp++;
- pref_mismatch = pref_mismatch <<1;
- }
- key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
-
- if (key_prefix != 0)
- goto backtrace;
-
- if (current_prefix_length >= cn->pos)
- current_prefix_length=mp;
- }
-#endif
- pn = (struct tnode *)n; /* Descend */
- chopped_off = 0;
- continue;
+ if (key_prefix != 0)
+ goto backtrace;
+
+ if (current_prefix_length >= cn->pos)
+ current_prefix_length = mp;
}
- if (IS_LEAF(n)) {
- if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
- goto found;
- }
+#endif
+ pn = (struct tnode *)n; /* Descend */
+ chopped_off = 0;
+ continue;
+
backtrace:
chopped_off++;
/* As zero don't change the child key (cindex) */
- while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1)))) {
+ while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1))))
chopped_off++;
- }
/* Decrease current_... with bits chopped off */
if (current_prefix_length > pn->pos + pn->bits - chopped_off)
current_prefix_length = pn->pos + pn->bits - chopped_off;
-
+
/*
* Either we do the actual chop off according or if we have
* chopped off all bits in this tnode walk up to our parent.
*/
- if (chopped_off <= pn->bits)
+ if (chopped_off <= pn->bits) {
cindex &= ~(1 << (chopped_off-1));
- else {
+ } else {
if (NODE_PARENT(pn) == NULL)
goto failed;
-
+
/* Get Child's index */
cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits);
pn = NODE_PARENT(pn);
@@ -1548,10 +1467,11 @@ backtrace:
failed:
ret = 1;
found:
- read_unlock(&fib_lock);
+ rcu_read_unlock();
return ret;
}
+/* only called from updater side */
static int trie_leaf_remove(struct trie *t, t_key key)
{
t_key cindex;
@@ -1559,24 +1479,20 @@ static int trie_leaf_remove(struct trie *t, t_key key)
struct node *n = t->trie;
struct leaf *l;
- if (trie_debug)
- printk("entering trie_leaf_remove(%p)\n", n);
+ pr_debug("entering trie_leaf_remove(%p)\n", n);
/* Note that in the case skipped bits, those bits are *not* checked!
* When we finish this, we will have NULL or a T_LEAF, and the
* T_LEAF may or may not match our key.
*/
- while (n != NULL && IS_TNODE(n)) {
+ while (n != NULL && IS_TNODE(n)) {
struct tnode *tn = (struct tnode *) n;
check_tnode(tn);
n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits));
- if (n && NODE_PARENT(n) != tn) {
- printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
- BUG();
- }
- }
+ BUG_ON(n && NODE_PARENT(n) != tn);
+ }
l = (struct leaf *) n;
if (!n || !tkey_equals(l->key, key))
@@ -1590,23 +1506,24 @@ static int trie_leaf_remove(struct trie *t, t_key key)
t->revision++;
t->size--;
+ preempt_disable();
tp = NODE_PARENT(n);
tnode_free((struct tnode *) n);
if (tp) {
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
put_child(t, (struct tnode *)tp, cindex, NULL);
- t->trie = trie_rebalance(t, tp);
- }
- else
- t->trie = NULL;
+ rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
+ } else
+ rcu_assign_pointer(t->trie, NULL);
+ preempt_enable();
return 1;
}
static int
fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
- struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
+ struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
{
struct trie *t = (struct trie *) tb->tb_data;
u32 key, mask;
@@ -1615,6 +1532,8 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
struct fib_alias *fa, *fa_to_delete;
struct list_head *fa_head;
struct leaf *l;
+ struct leaf_info *li;
+
if (plen > 32)
return -EINVAL;
@@ -1624,7 +1543,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
memcpy(&key, rta->rta_dst, 4);
key = ntohl(key);
- mask = ntohl( inet_make_mask(plen) );
+ mask = ntohl(inet_make_mask(plen));
if (key & ~mask)
return -EINVAL;
@@ -1641,11 +1560,11 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
if (!fa)
return -ESRCH;
- if (trie_debug)
- printk("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
+ pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
fa_to_delete = NULL;
fa_head = fa->fa_list.prev;
+
list_for_each_entry(fa, fa_head, fa_list) {
struct fib_info *fi = fa->fa_info;
@@ -1664,39 +1583,31 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
}
}
- if (fa_to_delete) {
- int kill_li = 0;
- struct leaf_info *li;
-
- fa = fa_to_delete;
- rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
+ if (!fa_to_delete)
+ return -ESRCH;
- l = fib_find_node(t, key);
- li = find_leaf_info(&l->list, plen);
+ fa = fa_to_delete;
+ rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
- write_lock_bh(&fib_lock);
+ l = fib_find_node(t, key);
+ li = find_leaf_info(&l->list, plen);
- list_del(&fa->fa_list);
+ list_del_rcu(&fa->fa_list);
- if (list_empty(fa_head)) {
- hlist_del(&li->hlist);
- kill_li = 1;
- }
- write_unlock_bh(&fib_lock);
-
- if (kill_li)
- free_leaf_info(li);
+ if (list_empty(fa_head)) {
+ hlist_del_rcu(&li->hlist);
+ free_leaf_info(li);
+ }
- if (hlist_empty(&l->list))
- trie_leaf_remove(t, key);
+ if (hlist_empty(&l->list))
+ trie_leaf_remove(t, key);
- if (fa->fa_state & FA_S_ACCESSED)
- rt_cache_flush(-1);
+ if (fa->fa_state & FA_S_ACCESSED)
+ rt_cache_flush(-1);
- fn_free_alias(fa);
- return 0;
- }
- return -ESRCH;
+ fib_release_info(fa->fa_info);
+ alias_free_mem_rcu(fa);
+ return 0;
}
static int trie_flush_list(struct trie *t, struct list_head *head)
@@ -1706,14 +1617,11 @@ static int trie_flush_list(struct trie *t, struct list_head *head)
list_for_each_entry_safe(fa, fa_node, head, fa_list) {
struct fib_info *fi = fa->fa_info;
-
- if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
-
- write_lock_bh(&fib_lock);
- list_del(&fa->fa_list);
- write_unlock_bh(&fib_lock);
- fn_free_alias(fa);
+ if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
+ list_del_rcu(&fa->fa_list);
+ fib_release_info(fa->fa_info);
+ alias_free_mem_rcu(fa);
found++;
}
}
@@ -1728,37 +1636,34 @@ static int trie_flush_leaf(struct trie *t, struct leaf *l)
struct leaf_info *li = NULL;
hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
-
found += trie_flush_list(t, &li->falh);
if (list_empty(&li->falh)) {
-
- write_lock_bh(&fib_lock);
- hlist_del(&li->hlist);
- write_unlock_bh(&fib_lock);
-
+ hlist_del_rcu(&li->hlist);
free_leaf_info(li);
}
}
return found;
}
+/* rcu_read_lock needs to be hold by caller from readside */
+
static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
{
struct node *c = (struct node *) thisleaf;
struct tnode *p;
int idx;
+ struct node *trie = rcu_dereference(t->trie);
if (c == NULL) {
- if (t->trie == NULL)
+ if (trie == NULL)
return NULL;
- if (IS_LEAF(t->trie)) /* trie w. just a leaf */
- return (struct leaf *) t->trie;
+ if (IS_LEAF(trie)) /* trie w. just a leaf */
+ return (struct leaf *) trie;
- p = (struct tnode*) t->trie; /* Start */
- }
- else
+ p = (struct tnode*) trie; /* Start */
+ } else
p = (struct tnode *) NODE_PARENT(c);
while (p) {
@@ -1771,29 +1676,31 @@ static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
pos = 0;
last = 1 << p->bits;
- for(idx = pos; idx < last ; idx++) {
- if (p->child[idx]) {
-
- /* Decend if tnode */
-
- while (IS_TNODE(p->child[idx])) {
- p = (struct tnode*) p->child[idx];
- idx = 0;
-
- /* Rightmost non-NULL branch */
- if (p && IS_TNODE(p))
- while (p->child[idx] == NULL && idx < (1 << p->bits)) idx++;
-
- /* Done with this tnode? */
- if (idx >= (1 << p->bits) || p->child[idx] == NULL )
- goto up;
- }
- return (struct leaf*) p->child[idx];
+ for (idx = pos; idx < last ; idx++) {
+ c = rcu_dereference(p->child[idx]);
+
+ if (!c)
+ continue;
+
+ /* Decend if tnode */
+ while (IS_TNODE(c)) {
+ p = (struct tnode *) c;
+ idx = 0;
+
+ /* Rightmost non-NULL branch */
+ if (p && IS_TNODE(p))
+ while (!(c = rcu_dereference(p->child[idx]))
+ && idx < (1<<p->bits)) idx++;
+
+ /* Done with this tnode? */
+ if (idx >= (1 << p->bits) || !c)
+ goto up;
}
+ return (struct leaf *) c;
}
up:
/* No more children go up one step */
- c = (struct node*) p;
+ c = (struct node *) p;
p = (struct tnode *) NODE_PARENT(p);
}
return NULL; /* Ready. Root of trie */
@@ -1807,23 +1714,24 @@ static int fn_trie_flush(struct fib_table *tb)
t->revision++;
- for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+ rcu_read_lock();
+ for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
found += trie_flush_leaf(t, l);
if (ll && hlist_empty(&ll->list))
trie_leaf_remove(t, ll->key);
ll = l;
}
+ rcu_read_unlock();
if (ll && hlist_empty(&ll->list))
trie_leaf_remove(t, ll->key);
- if (trie_debug)
- printk("trie_flush found=%d\n", found);
+ pr_debug("trie_flush found=%d\n", found);
return found;
}
-static int trie_last_dflt=-1;
+static int trie_last_dflt = -1;
static void
fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
@@ -1840,7 +1748,7 @@ fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
last_resort = NULL;
order = -1;
- read_lock(&fib_lock);
+ rcu_read_lock();
l = fib_find_node(t, 0);
if (!l)
@@ -1853,20 +1761,20 @@ fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
if (list_empty(fa_head))
goto out;
- list_for_each_entry(fa, fa_head, fa_list) {
+ list_for_each_entry_rcu(fa, fa_head, fa_list) {
struct fib_info *next_fi = fa->fa_info;
-
+
if (fa->fa_scope != res->scope ||
fa->fa_type != RTN_UNICAST)
continue;
-
+
if (next_fi->fib_priority > res->fi->fib_priority)
break;
if (!next_fi->fib_nh[0].nh_gw ||
next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
continue;
fa->fa_state |= FA_S_ACCESSED;
-
+
if (fi == NULL) {
if (next_fi != res->fi)
break;
@@ -1904,7 +1812,7 @@ fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
}
trie_last_dflt = last_idx;
out:;
- read_unlock(&fib_lock);
+ rcu_read_unlock();
}
static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb,
@@ -1913,12 +1821,14 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
int i, s_i;
struct fib_alias *fa;
- u32 xkey=htonl(key);
+ u32 xkey = htonl(key);
- s_i=cb->args[3];
+ s_i = cb->args[3];
i = 0;
- list_for_each_entry(fa, fah, fa_list) {
+ /* rcu_read_lock is hold by caller */
+
+ list_for_each_entry_rcu(fa, fah, fa_list) {
if (i < s_i) {
i++;
continue;
@@ -1946,10 +1856,10 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
fa->fa_info, 0) < 0) {
cb->args[3] = i;
return -1;
- }
+ }
i++;
}
- cb->args[3]=i;
+ cb->args[3] = i;
return skb->len;
}
@@ -1959,10 +1869,10 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str
int h, s_h;
struct list_head *fa_head;
struct leaf *l = NULL;
- s_h=cb->args[2];
- for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+ s_h = cb->args[2];
+ for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
if (h < s_h)
continue;
if (h > s_h)
@@ -1970,7 +1880,7 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str
sizeof(cb->args) - 3*sizeof(cb->args[0]));
fa_head = get_fa_head(l, plen);
-
+
if (!fa_head)
continue;
@@ -1978,11 +1888,11 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str
continue;
if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
- cb->args[2]=h;
+ cb->args[2] = h;
return -1;
}
}
- cb->args[2]=h;
+ cb->args[2] = h;
return skb->len;
}
@@ -1993,25 +1903,24 @@ static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
s_m = cb->args[1];
- read_lock(&fib_lock);
- for (m=0; m<=32; m++) {
-
+ rcu_read_lock();
+ for (m = 0; m <= 32; m++) {
if (m < s_m)
continue;
if (m > s_m)
memset(&cb->args[2], 0,
- sizeof(cb->args) - 2*sizeof(cb->args[0]));
+ sizeof(cb->args) - 2*sizeof(cb->args[0]));
if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
cb->args[1] = m;
goto out;
}
}
- read_unlock(&fib_lock);
+ rcu_read_unlock();
cb->args[1] = m;
return skb->len;
- out:
- read_unlock(&fib_lock);
+out:
+ rcu_read_unlock();
return -1;
}
@@ -2051,9 +1960,9 @@ struct fib_table * __init fib_hash_init(int id)
trie_init(t);
if (id == RT_TABLE_LOCAL)
- trie_local = t;
+ trie_local = t;
else if (id == RT_TABLE_MAIN)
- trie_main = t;
+ trie_main = t;
if (id == RT_TABLE_LOCAL)
printk("IPv4 FIB: Using LC-trie version %s\n", VERSION);
@@ -2061,373 +1970,137 @@ struct fib_table * __init fib_hash_init(int id)
return tb;
}
-/* Trie dump functions */
-
-static void putspace_seq(struct seq_file *seq, int n)
-{
- while (n--) seq_printf(seq, " ");
-}
+#ifdef CONFIG_PROC_FS
+/* Depth first Trie walk iterator */
+struct fib_trie_iter {
+ struct tnode *tnode;
+ struct trie *trie;
+ unsigned index;
+ unsigned depth;
+};
-static void printbin_seq(struct seq_file *seq, unsigned int v, int bits)
+static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
{
- while (bits--)
- seq_printf(seq, "%s", (v & (1<<bits))?"1":"0");
-}
+ struct tnode *tn = iter->tnode;
+ unsigned cindex = iter->index;
+ struct tnode *p;
-static void printnode_seq(struct seq_file *seq, int indent, struct node *n,
- int pend, int cindex, int bits)
-{
- putspace_seq(seq, indent);
- if (IS_LEAF(n))
- seq_printf(seq, "|");
- else
- seq_printf(seq, "+");
- if (bits) {
- seq_printf(seq, "%d/", cindex);
- printbin_seq(seq, cindex, bits);
- seq_printf(seq, ": ");
- }
- else
- seq_printf(seq, "<root>: ");
- seq_printf(seq, "%s:%p ", IS_LEAF(n)?"Leaf":"Internal node", n);
-
- if (IS_LEAF(n))
- seq_printf(seq, "key=%d.%d.%d.%d\n",
- n->key >> 24, (n->key >> 16) % 256, (n->key >> 8) % 256, n->key % 256);
- else {
- int plen = ((struct tnode *)n)->pos;
- t_key prf=MASK_PFX(n->key, plen);
- seq_printf(seq, "key=%d.%d.%d.%d/%d\n",
- prf >> 24, (prf >> 16) % 256, (prf >> 8) % 256, prf % 256, plen);
- }
- if (IS_LEAF(n)) {
- struct leaf *l=(struct leaf *)n;
- struct fib_alias *fa;
- int i;
- for (i=32; i>=0; i--)
- if (find_leaf_info(&l->list, i)) {
-
- struct list_head *fa_head = get_fa_head(l, i);
-
- if (!fa_head)
- continue;
-
- if (list_empty(fa_head))
- continue;
-
- putspace_seq(seq, indent+2);
- seq_printf(seq, "{/%d...dumping}\n", i);
-
-
- list_for_each_entry(fa, fa_head, fa_list) {
- putspace_seq(seq, indent+2);
- if (fa->fa_info->fib_nh == NULL) {
- seq_printf(seq, "Error _fib_nh=NULL\n");
- continue;
- }
- if (fa->fa_info == NULL) {
- seq_printf(seq, "Error fa_info=NULL\n");
- continue;
- }
-
- seq_printf(seq, "{type=%d scope=%d TOS=%d}\n",
- fa->fa_type,
- fa->fa_scope,
- fa->fa_tos);
- }
- }
- }
- else if (IS_TNODE(n)) {
- struct tnode *tn = (struct tnode *)n;
- putspace_seq(seq, indent); seq_printf(seq, "| ");
- seq_printf(seq, "{key prefix=%08x/", tn->key&TKEY_GET_MASK(0, tn->pos));
- printbin_seq(seq, tkey_extract_bits(tn->key, 0, tn->pos), tn->pos);
- seq_printf(seq, "}\n");
- putspace_seq(seq, indent); seq_printf(seq, "| ");
- seq_printf(seq, "{pos=%d", tn->pos);
- seq_printf(seq, " (skip=%d bits)", tn->pos - pend);
- seq_printf(seq, " bits=%d (%u children)}\n", tn->bits, (1 << tn->bits));
- putspace_seq(seq, indent); seq_printf(seq, "| ");
- seq_printf(seq, "{empty=%d full=%d}\n", tn->empty_children, tn->full_children);
- }
-}
+ pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
+ iter->tnode, iter->index, iter->depth);
+rescan:
+ while (cindex < (1<<tn->bits)) {
+ struct node *n = tnode_get_child(tn, cindex);
-static void trie_dump_seq(struct seq_file *seq, struct trie *t)
-{
- struct node *n = t->trie;
- int cindex=0;
- int indent=1;
- int pend=0;
- int depth = 0;
-
- read_lock(&fib_lock);
-
- seq_printf(seq, "------ trie_dump of t=%p ------\n", t);
- if (n) {
- printnode_seq(seq, indent, n, pend, cindex, 0);
- if (IS_TNODE(n)) {
- struct tnode *tn = (struct tnode *)n;
- pend = tn->pos+tn->bits;
- putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
- indent += 3;
- depth++;
-
- while (tn && cindex < (1 << tn->bits)) {
- if (tn->child[cindex]) {
-
- /* Got a child */
-
- printnode_seq(seq, indent, tn->child[cindex], pend, cindex, tn->bits);
- if (IS_LEAF(tn->child[cindex])) {
- cindex++;
-
- }
- else {
- /*
- * New tnode. Decend one level
- */
-
- depth++;
- n = tn->child[cindex];
- tn = (struct tnode *)n;
- pend = tn->pos+tn->bits;
- putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
- indent+=3;
- cindex=0;
- }
- }
- else
- cindex++;
-
- /*
- * Test if we are done
- */
-
- while (cindex >= (1 << tn->bits)) {
-
- /*
- * Move upwards and test for root
- * pop off all traversed nodes
- */
-
- if (NODE_PARENT(tn) == NULL) {
- tn = NULL;
- n = NULL;
- break;
- }
- else {
- cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
- tn = NODE_PARENT(tn);
- cindex++;
- n = (struct node *)tn;
- pend = tn->pos+tn->bits;
- indent-=3;
- depth--;
- }
- }
+ if (n) {
+ if (IS_LEAF(n)) {
+ iter->tnode = tn;
+ iter->index = cindex + 1;
+ } else {
+ /* push down one level */
+ iter->tnode = (struct tnode *) n;
+ iter->index = 0;
+ ++iter->depth;
}
+ return n;
}
- else n = NULL;
- }
- else seq_printf(seq, "------ trie is empty\n");
-
- read_unlock(&fib_lock);
-}
-
-static struct trie_stat *trie_stat_new(void)
-{
- struct trie_stat *s = kmalloc(sizeof(struct trie_stat), GFP_KERNEL);
- int i;
- if (s) {
- s->totdepth = 0;
- s->maxdepth = 0;
- s->tnodes = 0;
- s->leaves = 0;
- s->nullpointers = 0;
-
- for(i=0; i< MAX_CHILDS; i++)
- s->nodesizes[i] = 0;
+ ++cindex;
}
- return s;
-}
-
-static struct trie_stat *trie_collect_stats(struct trie *t)
-{
- struct node *n = t->trie;
- struct trie_stat *s = trie_stat_new();
- int cindex = 0;
- int indent = 1;
- int pend = 0;
- int depth = 0;
- read_lock(&fib_lock);
-
- if (s) {
- if (n) {
- if (IS_TNODE(n)) {
- struct tnode *tn = (struct tnode *)n;
- pend = tn->pos+tn->bits;
- indent += 3;
- s->nodesizes[tn->bits]++;
- depth++;
-
- while (tn && cindex < (1 << tn->bits)) {
- if (tn->child[cindex]) {
- /* Got a child */
-
- if (IS_LEAF(tn->child[cindex])) {
- cindex++;
-
- /* stats */
- if (depth > s->maxdepth)
- s->maxdepth = depth;
- s->totdepth += depth;
- s->leaves++;
- }
-
- else {
- /*
- * New tnode. Decend one level
- */
-
- s->tnodes++;
- s->nodesizes[tn->bits]++;
- depth++;
-
- n = tn->child[cindex];
- tn = (struct tnode *)n;
- pend = tn->pos+tn->bits;
-
- indent += 3;
- cindex = 0;
- }
- }
- else {
- cindex++;
- s->nullpointers++;
- }
-
- /*
- * Test if we are done
- */
-
- while (cindex >= (1 << tn->bits)) {
-
- /*
- * Move upwards and test for root
- * pop off all traversed nodes
- */
-
-
- if (NODE_PARENT(tn) == NULL) {
- tn = NULL;
- n = NULL;
- break;
- }
- else {
- cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
- tn = NODE_PARENT(tn);
- cindex++;
- n = (struct node *)tn;
- pend = tn->pos+tn->bits;
- indent -= 3;
- depth--;
- }
- }
- }
- }
- else n = NULL;
- }
+ /* Current node exhausted, pop back up */
+ p = NODE_PARENT(tn);
+ if (p) {
+ cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
+ tn = p;
+ --iter->depth;
+ goto rescan;
}
- read_unlock(&fib_lock);
- return s;
-}
-
-#ifdef CONFIG_PROC_FS
-
-static struct fib_alias *fib_triestat_get_first(struct seq_file *seq)
-{
- return NULL;
-}
-
-static struct fib_alias *fib_triestat_get_next(struct seq_file *seq)
-{
+ /* got root? */
return NULL;
}
-static void *fib_triestat_seq_start(struct seq_file *seq, loff_t *pos)
+static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
+ struct trie *t)
{
- void *v = NULL;
+ struct node *n = rcu_dereference(t->trie);
- if (ip_fib_main_table)
- v = *pos ? fib_triestat_get_next(seq) : SEQ_START_TOKEN;
- return v;
+ if (n && IS_TNODE(n)) {
+ iter->tnode = (struct tnode *) n;
+ iter->trie = t;
+ iter->index = 0;
+ iter->depth = 0;
+ return n;
+ }
+ return NULL;
}
-static void *fib_triestat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void trie_collect_stats(struct trie *t, struct trie_stat *s)
{
- ++*pos;
- return v == SEQ_START_TOKEN ? fib_triestat_get_first(seq) : fib_triestat_get_next(seq);
-}
+ struct node *n;
+ struct fib_trie_iter iter;
-static void fib_triestat_seq_stop(struct seq_file *seq, void *v)
-{
+ memset(s, 0, sizeof(*s));
+ rcu_read_lock();
+ for (n = fib_trie_get_first(&iter, t); n;
+ n = fib_trie_get_next(&iter)) {
+ if (IS_LEAF(n)) {
+ s->leaves++;
+ s->totdepth += iter.depth;
+ if (iter.depth > s->maxdepth)
+ s->maxdepth = iter.depth;
+ } else {
+ const struct tnode *tn = (const struct tnode *) n;
+ int i;
+
+ s->tnodes++;
+ s->nodesizes[tn->bits]++;
+ for (i = 0; i < (1<<tn->bits); i++)
+ if (!tn->child[i])
+ s->nullpointers++;
+ }
+ }
+ rcu_read_unlock();
}
/*
* This outputs /proc/net/fib_triestats
- *
- * It always works in backward compatibility mode.
- * The format of the file is not supposed to be changed.
*/
-
-static void collect_and_show(struct trie *t, struct seq_file *seq)
+static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
{
- int bytes = 0; /* How many bytes are used, a ref is 4 bytes */
- int i, max, pointers;
- struct trie_stat *stat;
- int avdepth;
+ unsigned i, max, pointers, bytes, avdepth;
- stat = trie_collect_stats(t);
+ if (stat->leaves)
+ avdepth = stat->totdepth*100 / stat->leaves;
+ else
+ avdepth = 0;
- bytes=0;
- seq_printf(seq, "trie=%p\n", t);
+ seq_printf(seq, "\tAver depth: %d.%02d\n", avdepth / 100, avdepth % 100 );
+ seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
- if (stat) {
- if (stat->leaves)
- avdepth=stat->totdepth*100 / stat->leaves;
- else
- avdepth=0;
- seq_printf(seq, "Aver depth: %d.%02d\n", avdepth / 100, avdepth % 100 );
- seq_printf(seq, "Max depth: %4d\n", stat->maxdepth);
-
- seq_printf(seq, "Leaves: %d\n", stat->leaves);
- bytes += sizeof(struct leaf) * stat->leaves;
- seq_printf(seq, "Internal nodes: %d\n", stat->tnodes);
- bytes += sizeof(struct tnode) * stat->tnodes;
-
- max = MAX_CHILDS-1;
-
- while (max >= 0 && stat->nodesizes[max] == 0)
- max--;
- pointers = 0;
-
- for (i = 1; i <= max; i++)
- if (stat->nodesizes[i] != 0) {
- seq_printf(seq, " %d: %d", i, stat->nodesizes[i]);
- pointers += (1<<i) * stat->nodesizes[i];
- }
- seq_printf(seq, "\n");
- seq_printf(seq, "Pointers: %d\n", pointers);
- bytes += sizeof(struct node *) * pointers;
- seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
- seq_printf(seq, "Total size: %d kB\n", bytes / 1024);
+ seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
- kfree(stat);
- }
+ bytes = sizeof(struct leaf) * stat->leaves;
+ seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);
+ bytes += sizeof(struct tnode) * stat->tnodes;
+
+ max = MAX_CHILDS-1;
+ while (max >= 0 && stat->nodesizes[max] == 0)
+ max--;
+
+ pointers = 0;
+ for (i = 1; i <= max; i++)
+ if (stat->nodesizes[i] != 0) {
+ seq_printf(seq, " %d: %d", i, stat->nodesizes[i]);
+ pointers += (1<<i) * stat->nodesizes[i];
+ }
+ seq_putc(seq, '\n');
+ seq_printf(seq, "\tPointers: %d\n", pointers);
+
+ bytes += sizeof(struct node *) * pointers;
+ seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
+ seq_printf(seq, "Total size: %d kB\n", (bytes + 1023) / 1024);
#ifdef CONFIG_IP_FIB_TRIE_STATS
seq_printf(seq, "Counters:\n---------\n");
@@ -2445,168 +2118,377 @@ static void collect_and_show(struct trie *t, struct seq_file *seq)
static int fib_triestat_seq_show(struct seq_file *seq, void *v)
{
- char bf[128];
+ struct trie_stat *stat;
- if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
- sizeof(struct leaf), sizeof(struct tnode));
- if (trie_local)
- collect_and_show(trie_local, seq);
+ stat = kmalloc(sizeof(*stat), GFP_KERNEL);
+ if (!stat)
+ return -ENOMEM;
- if (trie_main)
- collect_and_show(trie_main, seq);
+ seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
+ sizeof(struct leaf), sizeof(struct tnode));
+
+ if (trie_local) {
+ seq_printf(seq, "Local:\n");
+ trie_collect_stats(trie_local, stat);
+ trie_show_stats(seq, stat);
}
- else {
- snprintf(bf, sizeof(bf),
- "*\t%08X\t%08X", 200, 400);
-
- seq_printf(seq, "%-127s\n", bf);
+
+ if (trie_main) {
+ seq_printf(seq, "Main:\n");
+ trie_collect_stats(trie_main, stat);
+ trie_show_stats(seq, stat);
}
+ kfree(stat);
+
return 0;
}
-static struct seq_operations fib_triestat_seq_ops = {
- .start = fib_triestat_seq_start,
- .next = fib_triestat_seq_next,
- .stop = fib_triestat_seq_stop,
- .show = fib_triestat_seq_show,
-};
-
static int fib_triestat_seq_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- int rc = -ENOMEM;
-
- rc = seq_open(file, &fib_triestat_seq_ops);
- if (rc)
- goto out_kfree;
-
- seq = file->private_data;
-out:
- return rc;
-out_kfree:
- goto out;
+ return single_open(file, fib_triestat_seq_show, NULL);
}
-static struct file_operations fib_triestat_seq_fops = {
+static struct file_operations fib_triestat_fops = {
.owner = THIS_MODULE,
.open = fib_triestat_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = single_release,
};
-int __init fib_stat_proc_init(void)
+static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
+ loff_t pos)
{
- if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_seq_fops))
- return -ENOMEM;
- return 0;
+ loff_t idx = 0;
+ struct node *n;
+
+ for (n = fib_trie_get_first(iter, trie_local);
+ n; ++idx, n = fib_trie_get_next(iter)) {
+ if (pos == idx)
+ return n;
+ }
+
+ for (n = fib_trie_get_first(iter, trie_main);
+ n; ++idx, n = fib_trie_get_next(iter)) {
+ if (pos == idx)
+ return n;
+ }
+ return NULL;
}
-void __init fib_stat_proc_exit(void)
+static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
{
- proc_net_remove("fib_triestat");
+ rcu_read_lock();
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+ return fib_trie_get_idx(seq->private, *pos - 1);
}
-static struct fib_alias *fib_trie_get_first(struct seq_file *seq)
+static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
+ struct fib_trie_iter *iter = seq->private;
+ void *l = v;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN)
+ return fib_trie_get_idx(iter, 0);
+
+ v = fib_trie_get_next(iter);
+ BUG_ON(v == l);
+ if (v)
+ return v;
+
+ /* continue scan in next trie */
+ if (iter->trie == trie_local)
+ return fib_trie_get_first(iter, trie_main);
+
return NULL;
}
-static struct fib_alias *fib_trie_get_next(struct seq_file *seq)
+static void fib_trie_seq_stop(struct seq_file *seq, void *v)
{
- return NULL;
+ rcu_read_unlock();
}
-static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+static void seq_indent(struct seq_file *seq, int n)
+{
+ while (n-- > 0) seq_puts(seq, " ");
+}
+
+static inline const char *rtn_scope(enum rt_scope_t s)
{
- void *v = NULL;
+ static char buf[32];
- if (ip_fib_main_table)
- v = *pos ? fib_trie_get_next(seq) : SEQ_START_TOKEN;
- return v;
+ switch(s) {
+ case RT_SCOPE_UNIVERSE: return "universe";
+ case RT_SCOPE_SITE: return "site";
+ case RT_SCOPE_LINK: return "link";
+ case RT_SCOPE_HOST: return "host";
+ case RT_SCOPE_NOWHERE: return "nowhere";
+ default:
+ snprintf(buf, sizeof(buf), "scope=%d", s);
+ return buf;
+ }
}
-static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static const char *rtn_type_names[__RTN_MAX] = {
+ [RTN_UNSPEC] = "UNSPEC",
+ [RTN_UNICAST] = "UNICAST",
+ [RTN_LOCAL] = "LOCAL",
+ [RTN_BROADCAST] = "BROADCAST",
+ [RTN_ANYCAST] = "ANYCAST",
+ [RTN_MULTICAST] = "MULTICAST",
+ [RTN_BLACKHOLE] = "BLACKHOLE",
+ [RTN_UNREACHABLE] = "UNREACHABLE",
+ [RTN_PROHIBIT] = "PROHIBIT",
+ [RTN_THROW] = "THROW",
+ [RTN_NAT] = "NAT",
+ [RTN_XRESOLVE] = "XRESOLVE",
+};
+
+static inline const char *rtn_type(unsigned t)
{
- ++*pos;
- return v == SEQ_START_TOKEN ? fib_trie_get_first(seq) : fib_trie_get_next(seq);
+ static char buf[32];
+
+ if (t < __RTN_MAX && rtn_type_names[t])
+ return rtn_type_names[t];
+ snprintf(buf, sizeof(buf), "type %d", t);
+ return buf;
}
-static void fib_trie_seq_stop(struct seq_file *seq, void *v)
+/* Pretty print the trie */
+static int fib_trie_seq_show(struct seq_file *seq, void *v)
+{
+ const struct fib_trie_iter *iter = seq->private;
+ struct node *n = v;
+
+ if (v == SEQ_START_TOKEN)
+ return 0;
+
+ if (IS_TNODE(n)) {
+ struct tnode *tn = (struct tnode *) n;
+ t_key prf = ntohl(MASK_PFX(tn->key, tn->pos));
+
+ if (!NODE_PARENT(n)) {
+ if (iter->trie == trie_local)
+ seq_puts(seq, "<local>:\n");
+ else
+ seq_puts(seq, "<main>:\n");
+ } else {
+ seq_indent(seq, iter->depth-1);
+ seq_printf(seq, " +-- %d.%d.%d.%d/%d\n",
+ NIPQUAD(prf), tn->pos);
+ }
+ } else {
+ struct leaf *l = (struct leaf *) n;
+ int i;
+ u32 val = ntohl(l->key);
+
+ seq_indent(seq, iter->depth);
+ seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val));
+ for (i = 32; i >= 0; i--) {
+ struct leaf_info *li = find_leaf_info(&l->list, i);
+ if (li) {
+ struct fib_alias *fa;
+ list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+ seq_indent(seq, iter->depth+1);
+ seq_printf(seq, " /%d %s %s", i,
+ rtn_scope(fa->fa_scope),
+ rtn_type(fa->fa_type));
+ if (fa->fa_tos)
+ seq_printf(seq, "tos =%d\n",
+ fa->fa_tos);
+ seq_putc(seq, '\n');
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct seq_operations fib_trie_seq_ops = {
+ .start = fib_trie_seq_start,
+ .next = fib_trie_seq_next,
+ .stop = fib_trie_seq_stop,
+ .show = fib_trie_seq_show,
+};
+
+static int fib_trie_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &fib_trie_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
+}
+
+static struct file_operations fib_trie_fops = {
+ .owner = THIS_MODULE,
+ .open = fib_trie_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
{
+ static unsigned type2flags[RTN_MAX + 1] = {
+ [7] = RTF_REJECT, [8] = RTF_REJECT,
+ };
+ unsigned flags = type2flags[type];
+ if (fi && fi->fib_nh->nh_gw)
+ flags |= RTF_GATEWAY;
+ if (mask == 0xFFFFFFFF)
+ flags |= RTF_HOST;
+ flags |= RTF_UP;
+ return flags;
}
/*
- * This outputs /proc/net/fib_trie.
- *
- * It always works in backward compatibility mode.
- * The format of the file is not supposed to be changed.
+ * This outputs /proc/net/route.
+ * The format of the file is not supposed to be changed
+ * and needs to be same as fib_hash output to avoid breaking
+ * legacy utilities
*/
-
-static int fib_trie_seq_show(struct seq_file *seq, void *v)
+static int fib_route_seq_show(struct seq_file *seq, void *v)
{
+ struct leaf *l = v;
+ int i;
char bf[128];
if (v == SEQ_START_TOKEN) {
- if (trie_local)
- trie_dump_seq(seq, trie_local);
-
- if (trie_main)
- trie_dump_seq(seq, trie_main);
+ seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
+ "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
+ "\tWindow\tIRTT");
+ return 0;
}
- else {
- snprintf(bf, sizeof(bf),
- "*\t%08X\t%08X", 200, 400);
- seq_printf(seq, "%-127s\n", bf);
+ if (IS_TNODE(l))
+ return 0;
+
+ for (i=32; i>=0; i--) {
+ struct leaf_info *li = find_leaf_info(&l->list, i);
+ struct fib_alias *fa;
+ u32 mask, prefix;
+
+ if (!li)
+ continue;
+
+ mask = inet_make_mask(li->plen);
+ prefix = htonl(l->key);
+
+ list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+ const struct fib_info *fi = rcu_dereference(fa->fa_info);
+ unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
+
+ if (fa->fa_type == RTN_BROADCAST
+ || fa->fa_type == RTN_MULTICAST)
+ continue;
+
+ if (fi)
+ snprintf(bf, sizeof(bf),
+ "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+ fi->fib_dev ? fi->fib_dev->name : "*",
+ prefix,
+ fi->fib_nh->nh_gw, flags, 0, 0,
+ fi->fib_priority,
+ mask,
+ (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
+ fi->fib_window,
+ fi->fib_rtt >> 3);
+ else
+ snprintf(bf, sizeof(bf),
+ "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+ prefix, 0, flags, 0, 0, 0,
+ mask, 0, 0, 0);
+
+ seq_printf(seq, "%-127s\n", bf);
+ }
}
return 0;
}
-static struct seq_operations fib_trie_seq_ops = {
- .start = fib_trie_seq_start,
- .next = fib_trie_seq_next,
- .stop = fib_trie_seq_stop,
- .show = fib_trie_seq_show,
+static struct seq_operations fib_route_seq_ops = {
+ .start = fib_trie_seq_start,
+ .next = fib_trie_seq_next,
+ .stop = fib_trie_seq_stop,
+ .show = fib_route_seq_show,
};
-static int fib_trie_seq_open(struct inode *inode, struct file *file)
+static int fib_route_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
+ struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
- rc = seq_open(file, &fib_trie_seq_ops);
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &fib_route_seq_ops);
if (rc)
goto out_kfree;
- seq = file->private_data;
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
+ kfree(s);
goto out;
}
-static struct file_operations fib_trie_seq_fops = {
- .owner = THIS_MODULE,
- .open = fib_trie_seq_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release= seq_release_private,
+static struct file_operations fib_route_fops = {
+ .owner = THIS_MODULE,
+ .open = fib_route_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
};
int __init fib_proc_init(void)
{
- if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_seq_fops))
- return -ENOMEM;
+ if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
+ goto out1;
+
+ if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
+ goto out2;
+
+ if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
+ goto out3;
+
return 0;
+
+out3:
+ proc_net_remove("fib_triestat");
+out2:
+ proc_net_remove("fib_trie");
+out1:
+ return -ENOMEM;
}
void __init fib_proc_exit(void)
{
proc_net_remove("fib_trie");
+ proc_net_remove("fib_triestat");
+ proc_net_remove("route");
}
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index badfc5849973..24eb56ae1b5a 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -114,7 +114,7 @@ struct icmp_bxm {
/*
* Statistics
*/
-DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
+DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics) __read_mostly;
/* An array of errno for error messages from dest unreach. */
/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
@@ -627,11 +627,10 @@ static void icmp_unreach(struct sk_buff *skb)
break;
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
- LIMIT_NETDEBUG(
- printk(KERN_INFO "ICMP: %u.%u.%u.%u: "
+ LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
"fragmentation needed "
"and DF set.\n",
- NIPQUAD(iph->daddr)));
+ NIPQUAD(iph->daddr));
} else {
info = ip_rt_frag_needed(iph,
ntohs(icmph->un.frag.mtu));
@@ -640,10 +639,9 @@ static void icmp_unreach(struct sk_buff *skb)
}
break;
case ICMP_SR_FAILED:
- LIMIT_NETDEBUG(
- printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
+ LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
"Route Failed.\n",
- NIPQUAD(iph->daddr)));
+ NIPQUAD(iph->daddr));
break;
default:
break;
@@ -936,7 +934,7 @@ int icmp_rcv(struct sk_buff *skb)
case CHECKSUM_HW:
if (!(u16)csum_fold(skb->csum))
break;
- LIMIT_NETDEBUG(printk(KERN_DEBUG "icmp v4 hw csum failure\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "icmp v4 hw csum failure\n");
case CHECKSUM_NONE:
if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0)))
goto error;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 5088f90835ae..44607f4767b8 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -904,7 +904,7 @@ int igmp_rcv(struct sk_buff *skb)
case IGMP_MTRACE_RESP:
break;
default:
- NETDEBUG(printk(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type));
+ NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type);
}
in_dev_put(in_dev);
kfree_skb(skb);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
new file mode 100644
index 000000000000..fe3c6d3d0c91
--- /dev/null
+++ b/net/ipv4/inet_connection_sock.c
@@ -0,0 +1,641 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Support for INET connection oriented protocols.
+ *
+ * Authors: See the TCP sources
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+#include <linux/jhash.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet_timewait_sock.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/tcp_states.h>
+#include <net/xfrm.h>
+
+#ifdef INET_CSK_DEBUG
+const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
+EXPORT_SYMBOL(inet_csk_timer_bug_msg);
+#endif
+
+/*
+ * This array holds the first and last local port number.
+ * For high-usage systems, use sysctl to change this to
+ * 32768-61000
+ */
+int sysctl_local_port_range[2] = { 1024, 4999 };
+
+static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucket *tb)
+{
+ const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
+ struct sock *sk2;
+ struct hlist_node *node;
+ int reuse = sk->sk_reuse;
+
+ sk_for_each_bound(sk2, node, &tb->owners) {
+ if (sk != sk2 &&
+ !inet_v6_ipv6only(sk2) &&
+ (!sk->sk_bound_dev_if ||
+ !sk2->sk_bound_dev_if ||
+ sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
+ if (!reuse || !sk2->sk_reuse ||
+ sk2->sk_state == TCP_LISTEN) {
+ const u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
+ if (!sk2_rcv_saddr || !sk_rcv_saddr ||
+ sk2_rcv_saddr == sk_rcv_saddr)
+ break;
+ }
+ }
+ }
+ return node != NULL;
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+ struct sock *sk, unsigned short snum)
+{
+ struct inet_bind_hashbucket *head;
+ struct hlist_node *node;
+ struct inet_bind_bucket *tb;
+ int ret;
+
+ local_bh_disable();
+ if (!snum) {
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+ int rover;
+
+ spin_lock(&hashinfo->portalloc_lock);
+ if (hashinfo->port_rover < low)
+ rover = low;
+ else
+ rover = hashinfo->port_rover;
+ do {
+ rover++;
+ if (rover > high)
+ rover = low;
+ head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)];
+ spin_lock(&head->lock);
+ inet_bind_bucket_for_each(tb, node, &head->chain)
+ if (tb->port == rover)
+ goto next;
+ break;
+ next:
+ spin_unlock(&head->lock);
+ } while (--remaining > 0);
+ hashinfo->port_rover = rover;
+ spin_unlock(&hashinfo->portalloc_lock);
+
+ /* Exhausted local port range during search? It is not
+ * possible for us to be holding one of the bind hash
+ * locks if this test triggers, because if 'remaining'
+ * drops to zero, we broke out of the do/while loop at
+ * the top level, not from the 'break;' statement.
+ */
+ ret = 1;
+ if (remaining <= 0)
+ goto fail;
+
+ /* OK, here is the one we will use. HEAD is
+ * non-NULL and we hold it's mutex.
+ */
+ snum = rover;
+ } else {
+ head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)];
+ spin_lock(&head->lock);
+ inet_bind_bucket_for_each(tb, node, &head->chain)
+ if (tb->port == snum)
+ goto tb_found;
+ }
+ tb = NULL;
+ goto tb_not_found;
+tb_found:
+ if (!hlist_empty(&tb->owners)) {
+ if (sk->sk_reuse > 1)
+ goto success;
+ if (tb->fastreuse > 0 &&
+ sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
+ goto success;
+ } else {
+ ret = 1;
+ if (inet_csk_bind_conflict(sk, tb))
+ goto fail_unlock;
+ }
+ }
+tb_not_found:
+ ret = 1;
+ if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL)
+ goto fail_unlock;
+ if (hlist_empty(&tb->owners)) {
+ if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
+ tb->fastreuse = 1;
+ else
+ tb->fastreuse = 0;
+ } else if (tb->fastreuse &&
+ (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
+ tb->fastreuse = 0;
+success:
+ if (!inet_csk(sk)->icsk_bind_hash)
+ inet_bind_hash(sk, tb, snum);
+ BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
+ ret = 0;
+
+fail_unlock:
+ spin_unlock(&head->lock);
+fail:
+ local_bh_enable();
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_get_port);
+
+/*
+ * Wait for an incoming connection, avoid race conditions. This must be called
+ * with the socket locked.
+ */
+static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ DEFINE_WAIT(wait);
+ int err;
+
+ /*
+ * True wake-one mechanism for incoming connections: only
+ * one process gets woken up, not the 'whole herd'.
+ * Since we do not 'race & poll' for established sockets
+ * anymore, the common case will execute the loop only once.
+ *
+ * Subtle issue: "add_wait_queue_exclusive()" will be added
+ * after any current non-exclusive waiters, and we know that
+ * it will always _stay_ after any new non-exclusive waiters
+ * because all non-exclusive waiters are added at the
+ * beginning of the wait-queue. As such, it's ok to "drop"
+ * our exclusiveness temporarily when we get woken up without
+ * having to remove and re-insert us on the wait queue.
+ */
+ for (;;) {
+ prepare_to_wait_exclusive(sk->sk_sleep, &wait,
+ TASK_INTERRUPTIBLE);
+ release_sock(sk);
+ if (reqsk_queue_empty(&icsk->icsk_accept_queue))
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ err = 0;
+ if (!reqsk_queue_empty(&icsk->icsk_accept_queue))
+ break;
+ err = -EINVAL;
+ if (sk->sk_state != TCP_LISTEN)
+ break;
+ err = sock_intr_errno(timeo);
+ if (signal_pending(current))
+ break;
+ err = -EAGAIN;
+ if (!timeo)
+ break;
+ }
+ finish_wait(sk->sk_sleep, &wait);
+ return err;
+}
+
+/*
+ * This will accept the next outstanding connection.
+ */
+struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct sock *newsk;
+ int error;
+
+ lock_sock(sk);
+
+ /* We need to make sure that this socket is listening,
+ * and that it has something pending.
+ */
+ error = -EINVAL;
+ if (sk->sk_state != TCP_LISTEN)
+ goto out_err;
+
+ /* Find already established connection */
+ if (reqsk_queue_empty(&icsk->icsk_accept_queue)) {
+ long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+ /* If this is a non blocking socket don't sleep */
+ error = -EAGAIN;
+ if (!timeo)
+ goto out_err;
+
+ error = inet_csk_wait_for_connect(sk, timeo);
+ if (error)
+ goto out_err;
+ }
+
+ newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);
+ BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
+out:
+ release_sock(sk);
+ return newsk;
+out_err:
+ newsk = NULL;
+ *err = error;
+ goto out;
+}
+
+EXPORT_SYMBOL(inet_csk_accept);
+
+/*
+ * Using different timers for retransmit, delayed acks and probes
+ * We may wish use just one timer maintaining a list of expire jiffies
+ * to optimize.
+ */
+void inet_csk_init_xmit_timers(struct sock *sk,
+ void (*retransmit_handler)(unsigned long),
+ void (*delack_handler)(unsigned long),
+ void (*keepalive_handler)(unsigned long))
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ init_timer(&icsk->icsk_retransmit_timer);
+ init_timer(&icsk->icsk_delack_timer);
+ init_timer(&sk->sk_timer);
+
+ icsk->icsk_retransmit_timer.function = retransmit_handler;
+ icsk->icsk_delack_timer.function = delack_handler;
+ sk->sk_timer.function = keepalive_handler;
+
+ icsk->icsk_retransmit_timer.data =
+ icsk->icsk_delack_timer.data =
+ sk->sk_timer.data = (unsigned long)sk;
+
+ icsk->icsk_pending = icsk->icsk_ack.pending = 0;
+}
+
+EXPORT_SYMBOL(inet_csk_init_xmit_timers);
+
+void inet_csk_clear_xmit_timers(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ icsk->icsk_pending = icsk->icsk_ack.pending = icsk->icsk_ack.blocked = 0;
+
+ sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
+ sk_stop_timer(sk, &icsk->icsk_delack_timer);
+ sk_stop_timer(sk, &sk->sk_timer);
+}
+
+EXPORT_SYMBOL(inet_csk_clear_xmit_timers);
+
+void inet_csk_delete_keepalive_timer(struct sock *sk)
+{
+ sk_stop_timer(sk, &sk->sk_timer);
+}
+
+EXPORT_SYMBOL(inet_csk_delete_keepalive_timer);
+
+void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long len)
+{
+ sk_reset_timer(sk, &sk->sk_timer, jiffies + len);
+}
+
+EXPORT_SYMBOL(inet_csk_reset_keepalive_timer);
+
+struct dst_entry* inet_csk_route_req(struct sock *sk,
+ const struct request_sock *req)
+{
+ struct rtable *rt;
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ struct ip_options *opt = inet_rsk(req)->opt;
+ struct flowi fl = { .oif = sk->sk_bound_dev_if,
+ .nl_u = { .ip4_u =
+ { .daddr = ((opt && opt->srr) ?
+ opt->faddr :
+ ireq->rmt_addr),
+ .saddr = ireq->loc_addr,
+ .tos = RT_CONN_FLAGS(sk) } },
+ .proto = sk->sk_protocol,
+ .uli_u = { .ports =
+ { .sport = inet_sk(sk)->sport,
+ .dport = ireq->rmt_port } } };
+
+ if (ip_route_output_flow(&rt, &fl, sk, 0)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ return NULL;
+ }
+ if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
+ ip_rt_put(rt);
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ return NULL;
+ }
+ return &rt->u.dst;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_route_req);
+
+static inline u32 inet_synq_hash(const u32 raddr, const u16 rport,
+ const u32 rnd, const u16 synq_hsize)
+{
+ return jhash_2words(raddr, (u32)rport, rnd) & (synq_hsize - 1);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#define AF_INET_FAMILY(fam) ((fam) == AF_INET)
+#else
+#define AF_INET_FAMILY(fam) 1
+#endif
+
+struct request_sock *inet_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __u16 rport, const __u32 raddr,
+ const __u32 laddr)
+{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+ struct request_sock *req, **prev;
+
+ for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
+ lopt->nr_table_entries)];
+ (req = *prev) != NULL;
+ prev = &req->dl_next) {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+
+ if (ireq->rmt_port == rport &&
+ ireq->rmt_addr == raddr &&
+ ireq->loc_addr == laddr &&
+ AF_INET_FAMILY(req->rsk_ops->family)) {
+ BUG_TRAP(!req->sk);
+ *prevp = prev;
+ break;
+ }
+ }
+
+ return req;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_search_req);
+
+void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
+ const unsigned timeout)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+ const u32 h = inet_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port,
+ lopt->hash_rnd, lopt->nr_table_entries);
+
+ reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, timeout);
+ inet_csk_reqsk_queue_added(sk, timeout);
+}
+
+/* Only thing we need from tcp.h */
+extern int sysctl_tcp_synack_retries;
+
+EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add);
+
+void inet_csk_reqsk_queue_prune(struct sock *parent,
+ const unsigned long interval,
+ const unsigned long timeout,
+ const unsigned long max_rto)
+{
+ struct inet_connection_sock *icsk = inet_csk(parent);
+ struct request_sock_queue *queue = &icsk->icsk_accept_queue;
+ struct listen_sock *lopt = queue->listen_opt;
+ int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+ int thresh = max_retries;
+ unsigned long now = jiffies;
+ struct request_sock **reqp, *req;
+ int i, budget;
+
+ if (lopt == NULL || lopt->qlen == 0)
+ return;
+
+ /* Normally all the openreqs are young and become mature
+ * (i.e. converted to established socket) for first timeout.
+ * If synack was not acknowledged for 3 seconds, it means
+ * one of the following things: synack was lost, ack was lost,
+ * rtt is high or nobody planned to ack (i.e. synflood).
+ * When server is a bit loaded, queue is populated with old
+ * open requests, reducing effective size of queue.
+ * When server is well loaded, queue size reduces to zero
+ * after several minutes of work. It is not synflood,
+ * it is normal operation. The solution is pruning
+ * too old entries overriding normal timeout, when
+ * situation becomes dangerous.
+ *
+ * Essentially, we reserve half of room for young
+ * embrions; and abort old ones without pity, if old
+ * ones are about to clog our table.
+ */
+ if (lopt->qlen>>(lopt->max_qlen_log-1)) {
+ int young = (lopt->qlen_young<<1);
+
+ while (thresh > 2) {
+ if (lopt->qlen < young)
+ break;
+ thresh--;
+ young <<= 1;
+ }
+ }
+
+ if (queue->rskq_defer_accept)
+ max_retries = queue->rskq_defer_accept;
+
+ budget = 2 * (lopt->nr_table_entries / (timeout / interval));
+ i = lopt->clock_hand;
+
+ do {
+ reqp=&lopt->syn_table[i];
+ while ((req = *reqp) != NULL) {
+ if (time_after_eq(now, req->expires)) {
+ if ((req->retrans < thresh ||
+ (inet_rsk(req)->acked && req->retrans < max_retries))
+ && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) {
+ unsigned long timeo;
+
+ if (req->retrans++ == 0)
+ lopt->qlen_young--;
+ timeo = min((timeout << req->retrans), max_rto);
+ req->expires = now + timeo;
+ reqp = &req->dl_next;
+ continue;
+ }
+
+ /* Drop this request */
+ inet_csk_reqsk_queue_unlink(parent, req, reqp);
+ reqsk_queue_removed(queue, req);
+ reqsk_free(req);
+ continue;
+ }
+ reqp = &req->dl_next;
+ }
+
+ i = (i + 1) & (lopt->nr_table_entries - 1);
+
+ } while (--budget > 0);
+
+ lopt->clock_hand = i;
+
+ if (lopt->qlen)
+ inet_csk_reset_keepalive_timer(parent, interval);
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_prune);
+
+struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req,
+ const unsigned int __nocast priority)
+{
+ struct sock *newsk = sk_clone(sk, priority);
+
+ if (newsk != NULL) {
+ struct inet_connection_sock *newicsk = inet_csk(newsk);
+
+ newsk->sk_state = TCP_SYN_RECV;
+ newicsk->icsk_bind_hash = NULL;
+
+ inet_sk(newsk)->dport = inet_rsk(req)->rmt_port;
+ newsk->sk_write_space = sk_stream_write_space;
+
+ newicsk->icsk_retransmits = 0;
+ newicsk->icsk_backoff = 0;
+ newicsk->icsk_probes_out = 0;
+
+ /* Deinitialize accept_queue to trap illegal accesses. */
+ memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue));
+ }
+ return newsk;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_clone);
+
+/*
+ * At this point, there should be no process reference to this
+ * socket, and thus no user references at all. Therefore we
+ * can assume the socket waitqueue is inactive and nobody will
+ * try to jump onto it.
+ */
+void inet_csk_destroy_sock(struct sock *sk)
+{
+ BUG_TRAP(sk->sk_state == TCP_CLOSE);
+ BUG_TRAP(sock_flag(sk, SOCK_DEAD));
+
+ /* It cannot be in hash table! */
+ BUG_TRAP(sk_unhashed(sk));
+
+ /* If it has not 0 inet_sk(sk)->num, it must be bound */
+ BUG_TRAP(!inet_sk(sk)->num || inet_csk(sk)->icsk_bind_hash);
+
+ sk->sk_prot->destroy(sk);
+
+ sk_stream_kill_queues(sk);
+
+ xfrm_sk_free_policy(sk);
+
+ sk_refcnt_debug_release(sk);
+
+ atomic_dec(sk->sk_prot->orphan_count);
+ sock_put(sk);
+}
+
+EXPORT_SYMBOL(inet_csk_destroy_sock);
+
+int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
+{
+ struct inet_sock *inet = inet_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ int rc = reqsk_queue_alloc(&icsk->icsk_accept_queue, nr_table_entries);
+
+ if (rc != 0)
+ return rc;
+
+ sk->sk_max_ack_backlog = 0;
+ sk->sk_ack_backlog = 0;
+ inet_csk_delack_init(sk);
+
+ /* There is race window here: we announce ourselves listening,
+ * but this transition is still not validated by get_port().
+ * It is OK, because this socket enters to hash table only
+ * after validation is complete.
+ */
+ sk->sk_state = TCP_LISTEN;
+ if (!sk->sk_prot->get_port(sk, inet->num)) {
+ inet->sport = htons(inet->num);
+
+ sk_dst_reset(sk);
+ sk->sk_prot->hash(sk);
+
+ return 0;
+ }
+
+ sk->sk_state = TCP_CLOSE;
+ __reqsk_queue_destroy(&icsk->icsk_accept_queue);
+ return -EADDRINUSE;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_listen_start);
+
+/*
+ * This routine closes sockets which have been at least partially
+ * opened, but not yet accepted.
+ */
+void inet_csk_listen_stop(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct request_sock *acc_req;
+ struct request_sock *req;
+
+ inet_csk_delete_keepalive_timer(sk);
+
+ /* make all the listen_opt local to us */
+ acc_req = reqsk_queue_yank_acceptq(&icsk->icsk_accept_queue);
+
+ /* Following specs, it would be better either to send FIN
+ * (and enter FIN-WAIT-1, it is normal close)
+ * or to send active reset (abort).
+ * Certainly, it is pretty dangerous while synflood, but it is
+ * bad justification for our negligence 8)
+ * To be honest, we are not able to make either
+ * of the variants now. --ANK
+ */
+ reqsk_queue_destroy(&icsk->icsk_accept_queue);
+
+ while ((req = acc_req) != NULL) {
+ struct sock *child = req->sk;
+
+ acc_req = req->dl_next;
+
+ local_bh_disable();
+ bh_lock_sock(child);
+ BUG_TRAP(!sock_owned_by_user(child));
+ sock_hold(child);
+
+ sk->sk_prot->disconnect(child, O_NONBLOCK);
+
+ sock_orphan(child);
+
+ atomic_inc(sk->sk_prot->orphan_count);
+
+ inet_csk_destroy_sock(child);
+
+ bh_unlock_sock(child);
+ local_bh_enable();
+ sock_put(child);
+
+ sk_acceptq_removed(sk);
+ __reqsk_free(req);
+ }
+ BUG_TRAP(!sk->sk_ack_backlog);
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_listen_stop);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
new file mode 100644
index 000000000000..71f3c7350c6e
--- /dev/null
+++ b/net/ipv4/inet_diag.c
@@ -0,0 +1,868 @@
+/*
+ * inet_diag.c Module for monitoring INET transport protocols sockets.
+ *
+ * Version: $Id: inet_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/random.h>
+#include <linux/cache.h>
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/ipv6.h>
+#include <net/inet_common.h>
+#include <net/inet_connection_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet_timewait_sock.h>
+#include <net/inet6_hashtables.h>
+
+#include <linux/inet.h>
+#include <linux/stddef.h>
+
+#include <linux/inet_diag.h>
+
+static const struct inet_diag_handler **inet_diag_table;
+
+struct inet_diag_entry {
+ u32 *saddr;
+ u32 *daddr;
+ u16 sport;
+ u16 dport;
+ u16 family;
+ u16 userlocks;
+};
+
+static struct sock *idiagnl;
+
+#define INET_DIAG_PUT(skb, attrtype, attrlen) \
+ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
+
+static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
+ int ext, u32 pid, u32 seq, u16 nlmsg_flags,
+ const struct nlmsghdr *unlh)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct inet_diag_msg *r;
+ struct nlmsghdr *nlh;
+ void *info = NULL;
+ struct inet_diag_meminfo *minfo = NULL;
+ unsigned char *b = skb->tail;
+ const struct inet_diag_handler *handler;
+
+ handler = inet_diag_table[unlh->nlmsg_type];
+ BUG_ON(handler == NULL);
+
+ nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r));
+ nlh->nlmsg_flags = nlmsg_flags;
+
+ r = NLMSG_DATA(nlh);
+ if (sk->sk_state != TCP_TIME_WAIT) {
+ if (ext & (1 << (INET_DIAG_MEMINFO - 1)))
+ minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO,
+ sizeof(*minfo));
+ if (ext & (1 << (INET_DIAG_INFO - 1)))
+ info = INET_DIAG_PUT(skb, INET_DIAG_INFO,
+ handler->idiag_info_size);
+
+ if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) {
+ size_t len = strlen(icsk->icsk_ca_ops->name);
+ strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1),
+ icsk->icsk_ca_ops->name);
+ }
+ }
+ r->idiag_family = sk->sk_family;
+ r->idiag_state = sk->sk_state;
+ r->idiag_timer = 0;
+ r->idiag_retrans = 0;
+
+ r->id.idiag_if = sk->sk_bound_dev_if;
+ r->id.idiag_cookie[0] = (u32)(unsigned long)sk;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1);
+
+ if (r->idiag_state == TCP_TIME_WAIT) {
+ const struct inet_timewait_sock *tw = inet_twsk(sk);
+ long tmo = tw->tw_ttd - jiffies;
+ if (tmo < 0)
+ tmo = 0;
+
+ r->id.idiag_sport = tw->tw_sport;
+ r->id.idiag_dport = tw->tw_dport;
+ r->id.idiag_src[0] = tw->tw_rcv_saddr;
+ r->id.idiag_dst[0] = tw->tw_daddr;
+ r->idiag_state = tw->tw_substate;
+ r->idiag_timer = 3;
+ r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ;
+ r->idiag_rqueue = 0;
+ r->idiag_wqueue = 0;
+ r->idiag_uid = 0;
+ r->idiag_inode = 0;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if (r->idiag_family == AF_INET6) {
+ const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
+
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
+ &tcp6tw->tw_v6_rcv_saddr);
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
+ &tcp6tw->tw_v6_daddr);
+ }
+#endif
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+ }
+
+ r->id.idiag_sport = inet->sport;
+ r->id.idiag_dport = inet->dport;
+ r->id.idiag_src[0] = inet->rcv_saddr;
+ r->id.idiag_dst[0] = inet->daddr;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if (r->idiag_family == AF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
+ &np->rcv_saddr);
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
+ &np->daddr);
+ }
+#endif
+
+#define EXPIRES_IN_MS(tmo) ((tmo - jiffies) * 1000 + HZ - 1) / HZ
+
+ if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+ r->idiag_timer = 1;
+ r->idiag_retrans = icsk->icsk_retransmits;
+ r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
+ } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
+ r->idiag_timer = 4;
+ r->idiag_retrans = icsk->icsk_probes_out;
+ r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
+ } else if (timer_pending(&sk->sk_timer)) {
+ r->idiag_timer = 2;
+ r->idiag_retrans = icsk->icsk_probes_out;
+ r->idiag_expires = EXPIRES_IN_MS(sk->sk_timer.expires);
+ } else {
+ r->idiag_timer = 0;
+ r->idiag_expires = 0;
+ }
+#undef EXPIRES_IN_MS
+
+ r->idiag_uid = sock_i_uid(sk);
+ r->idiag_inode = sock_i_ino(sk);
+
+ if (minfo) {
+ minfo->idiag_rmem = atomic_read(&sk->sk_rmem_alloc);
+ minfo->idiag_wmem = sk->sk_wmem_queued;
+ minfo->idiag_fmem = sk->sk_forward_alloc;
+ minfo->idiag_tmem = atomic_read(&sk->sk_wmem_alloc);
+ }
+
+ handler->idiag_get_info(sk, r, info);
+
+ if (sk->sk_state < TCP_TIME_WAIT &&
+ icsk->icsk_ca_ops && icsk->icsk_ca_ops->get_info)
+ icsk->icsk_ca_ops->get_info(sk, ext, skb);
+
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+rtattr_failure:
+nlmsg_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
+{
+ int err;
+ struct sock *sk;
+ struct inet_diag_req *req = NLMSG_DATA(nlh);
+ struct sk_buff *rep;
+ struct inet_hashinfo *hashinfo;
+ const struct inet_diag_handler *handler;
+
+ handler = inet_diag_table[nlh->nlmsg_type];
+ BUG_ON(handler == NULL);
+ hashinfo = handler->idiag_hashinfo;
+
+ if (req->idiag_family == AF_INET) {
+ sk = inet_lookup(hashinfo, req->id.idiag_dst[0],
+ req->id.idiag_dport, req->id.idiag_src[0],
+ req->id.idiag_sport, req->id.idiag_if);
+ }
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ else if (req->idiag_family == AF_INET6) {
+ sk = inet6_lookup(hashinfo,
+ (struct in6_addr *)req->id.idiag_dst,
+ req->id.idiag_dport,
+ (struct in6_addr *)req->id.idiag_src,
+ req->id.idiag_sport,
+ req->id.idiag_if);
+ }
+#endif
+ else {
+ return -EINVAL;
+ }
+
+ if (sk == NULL)
+ return -ENOENT;
+
+ err = -ESTALE;
+ if ((req->id.idiag_cookie[0] != INET_DIAG_NOCOOKIE ||
+ req->id.idiag_cookie[1] != INET_DIAG_NOCOOKIE) &&
+ ((u32)(unsigned long)sk != req->id.idiag_cookie[0] ||
+ (u32)((((unsigned long)sk) >> 31) >> 1) != req->id.idiag_cookie[1]))
+ goto out;
+
+ err = -ENOMEM;
+ rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) +
+ sizeof(struct inet_diag_meminfo) +
+ handler->idiag_info_size + 64)),
+ GFP_KERNEL);
+ if (!rep)
+ goto out;
+
+ if (inet_diag_fill(rep, sk, req->idiag_ext,
+ NETLINK_CB(in_skb).pid,
+ nlh->nlmsg_seq, 0, nlh) <= 0)
+ BUG();
+
+ err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
+ MSG_DONTWAIT);
+ if (err > 0)
+ err = 0;
+
+out:
+ if (sk) {
+ if (sk->sk_state == TCP_TIME_WAIT)
+ inet_twsk_put((struct inet_timewait_sock *)sk);
+ else
+ sock_put(sk);
+ }
+ return err;
+}
+
+static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
+{
+ int words = bits >> 5;
+
+ bits &= 0x1f;
+
+ if (words) {
+ if (memcmp(a1, a2, words << 2))
+ return 0;
+ }
+ if (bits) {
+ __u32 w1, w2;
+ __u32 mask;
+
+ w1 = a1[words];
+ w2 = a2[words];
+
+ mask = htonl((0xffffffff) << (32 - bits));
+
+ if ((w1 ^ w2) & mask)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int inet_diag_bc_run(const void *bc, int len,
+ const struct inet_diag_entry *entry)
+{
+ while (len > 0) {
+ int yes = 1;
+ const struct inet_diag_bc_op *op = bc;
+
+ switch (op->code) {
+ case INET_DIAG_BC_NOP:
+ break;
+ case INET_DIAG_BC_JMP:
+ yes = 0;
+ break;
+ case INET_DIAG_BC_S_GE:
+ yes = entry->sport >= op[1].no;
+ break;
+ case INET_DIAG_BC_S_LE:
+ yes = entry->dport <= op[1].no;
+ break;
+ case INET_DIAG_BC_D_GE:
+ yes = entry->dport >= op[1].no;
+ break;
+ case INET_DIAG_BC_D_LE:
+ yes = entry->dport <= op[1].no;
+ break;
+ case INET_DIAG_BC_AUTO:
+ yes = !(entry->userlocks & SOCK_BINDPORT_LOCK);
+ break;
+ case INET_DIAG_BC_S_COND:
+ case INET_DIAG_BC_D_COND: {
+ struct inet_diag_hostcond *cond;
+ u32 *addr;
+
+ cond = (struct inet_diag_hostcond *)(op + 1);
+ if (cond->port != -1 &&
+ cond->port != (op->code == INET_DIAG_BC_S_COND ?
+ entry->sport : entry->dport)) {
+ yes = 0;
+ break;
+ }
+
+ if (cond->prefix_len == 0)
+ break;
+
+ if (op->code == INET_DIAG_BC_S_COND)
+ addr = entry->saddr;
+ else
+ addr = entry->daddr;
+
+ if (bitstring_match(addr, cond->addr, cond->prefix_len))
+ break;
+ if (entry->family == AF_INET6 &&
+ cond->family == AF_INET) {
+ if (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == htonl(0xffff) &&
+ bitstring_match(addr + 3, cond->addr,
+ cond->prefix_len))
+ break;
+ }
+ yes = 0;
+ break;
+ }
+ }
+
+ if (yes) {
+ len -= op->yes;
+ bc += op->yes;
+ } else {
+ len -= op->no;
+ bc += op->no;
+ }
+ }
+ return (len == 0);
+}
+
+static int valid_cc(const void *bc, int len, int cc)
+{
+ while (len >= 0) {
+ const struct inet_diag_bc_op *op = bc;
+
+ if (cc > len)
+ return 0;
+ if (cc == len)
+ return 1;
+ if (op->yes < 4)
+ return 0;
+ len -= op->yes;
+ bc += op->yes;
+ }
+ return 0;
+}
+
+static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+{
+ const unsigned char *bc = bytecode;
+ int len = bytecode_len;
+
+ while (len > 0) {
+ struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc;
+
+//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
+ switch (op->code) {
+ case INET_DIAG_BC_AUTO:
+ case INET_DIAG_BC_S_COND:
+ case INET_DIAG_BC_D_COND:
+ case INET_DIAG_BC_S_GE:
+ case INET_DIAG_BC_S_LE:
+ case INET_DIAG_BC_D_GE:
+ case INET_DIAG_BC_D_LE:
+ if (op->yes < 4 || op->yes > len + 4)
+ return -EINVAL;
+ case INET_DIAG_BC_JMP:
+ if (op->no < 4 || op->no > len + 4)
+ return -EINVAL;
+ if (op->no < len &&
+ !valid_cc(bytecode, bytecode_len, len - op->no))
+ return -EINVAL;
+ break;
+ case INET_DIAG_BC_NOP:
+ if (op->yes < 4 || op->yes > len + 4)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ bc += op->yes;
+ len -= op->yes;
+ }
+ return len == 0 ? 0 : -EINVAL;
+}
+
+static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk,
+ struct netlink_callback *cb)
+{
+ struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
+
+ if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
+ struct inet_diag_entry entry;
+ struct rtattr *bc = (struct rtattr *)(r + 1);
+ struct inet_sock *inet = inet_sk(sk);
+
+ entry.family = sk->sk_family;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if (entry.family == AF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ entry.saddr = np->rcv_saddr.s6_addr32;
+ entry.daddr = np->daddr.s6_addr32;
+ } else
+#endif
+ {
+ entry.saddr = &inet->rcv_saddr;
+ entry.daddr = &inet->daddr;
+ }
+ entry.sport = inet->num;
+ entry.dport = ntohs(inet->dport);
+ entry.userlocks = sk->sk_userlocks;
+
+ if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
+ return 0;
+ }
+
+ return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+}
+
+static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
+ struct request_sock *req,
+ u32 pid, u32 seq,
+ const struct nlmsghdr *unlh)
+{
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ struct inet_sock *inet = inet_sk(sk);
+ unsigned char *b = skb->tail;
+ struct inet_diag_msg *r;
+ struct nlmsghdr *nlh;
+ long tmo;
+
+ nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r));
+ nlh->nlmsg_flags = NLM_F_MULTI;
+ r = NLMSG_DATA(nlh);
+
+ r->idiag_family = sk->sk_family;
+ r->idiag_state = TCP_SYN_RECV;
+ r->idiag_timer = 1;
+ r->idiag_retrans = req->retrans;
+
+ r->id.idiag_if = sk->sk_bound_dev_if;
+ r->id.idiag_cookie[0] = (u32)(unsigned long)req;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)req >> 31) >> 1);
+
+ tmo = req->expires - jiffies;
+ if (tmo < 0)
+ tmo = 0;
+
+ r->id.idiag_sport = inet->sport;
+ r->id.idiag_dport = ireq->rmt_port;
+ r->id.idiag_src[0] = ireq->loc_addr;
+ r->id.idiag_dst[0] = ireq->rmt_addr;
+ r->idiag_expires = jiffies_to_msecs(tmo);
+ r->idiag_rqueue = 0;
+ r->idiag_wqueue = 0;
+ r->idiag_uid = sock_i_uid(sk);
+ r->idiag_inode = 0;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if (r->idiag_family == AF_INET6) {
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
+ &tcp6_rsk(req)->loc_addr);
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
+ &tcp6_rsk(req)->rmt_addr);
+ }
+#endif
+ nlh->nlmsg_len = skb->tail - b;
+
+ return skb->len;
+
+nlmsg_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
+ struct netlink_callback *cb)
+{
+ struct inet_diag_entry entry;
+ struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt;
+ struct rtattr *bc = NULL;
+ struct inet_sock *inet = inet_sk(sk);
+ int j, s_j;
+ int reqnum, s_reqnum;
+ int err = 0;
+
+ s_j = cb->args[3];
+ s_reqnum = cb->args[4];
+
+ if (s_j > 0)
+ s_j--;
+
+ entry.family = sk->sk_family;
+
+ read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
+
+ lopt = icsk->icsk_accept_queue.listen_opt;
+ if (!lopt || !lopt->qlen)
+ goto out;
+
+ if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
+ bc = (struct rtattr *)(r + 1);
+ entry.sport = inet->num;
+ entry.userlocks = sk->sk_userlocks;
+ }
+
+ for (j = s_j; j < lopt->nr_table_entries; j++) {
+ struct request_sock *req, *head = lopt->syn_table[j];
+
+ reqnum = 0;
+ for (req = head; req; reqnum++, req = req->dl_next) {
+ struct inet_request_sock *ireq = inet_rsk(req);
+
+ if (reqnum < s_reqnum)
+ continue;
+ if (r->id.idiag_dport != ireq->rmt_port &&
+ r->id.idiag_dport)
+ continue;
+
+ if (bc) {
+ entry.saddr =
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ (entry.family == AF_INET6) ?
+ tcp6_rsk(req)->loc_addr.s6_addr32 :
+#endif
+ &ireq->loc_addr;
+ entry.daddr =
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ (entry.family == AF_INET6) ?
+ tcp6_rsk(req)->rmt_addr.s6_addr32 :
+#endif
+ &ireq->rmt_addr;
+ entry.dport = ntohs(ireq->rmt_port);
+
+ if (!inet_diag_bc_run(RTA_DATA(bc),
+ RTA_PAYLOAD(bc), &entry))
+ continue;
+ }
+
+ err = inet_diag_fill_req(skb, sk, req,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, cb->nlh);
+ if (err < 0) {
+ cb->args[3] = j + 1;
+ cb->args[4] = reqnum;
+ goto out;
+ }
+ }
+
+ s_reqnum = 0;
+ }
+
+out:
+ read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
+
+ return err;
+}
+
+static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int i, num;
+ int s_i, s_num;
+ struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
+ const struct inet_diag_handler *handler;
+ struct inet_hashinfo *hashinfo;
+
+ handler = inet_diag_table[cb->nlh->nlmsg_type];
+ BUG_ON(handler == NULL);
+ hashinfo = handler->idiag_hashinfo;
+
+ s_i = cb->args[1];
+ s_num = num = cb->args[2];
+
+ if (cb->args[0] == 0) {
+ if (!(r->idiag_states & (TCPF_LISTEN | TCPF_SYN_RECV)))
+ goto skip_listen_ht;
+
+ inet_listen_lock(hashinfo);
+ for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
+ struct sock *sk;
+ struct hlist_node *node;
+
+ num = 0;
+ sk_for_each(sk, node, &hashinfo->listening_hash[i]) {
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (num < s_num) {
+ num++;
+ continue;
+ }
+
+ if (r->id.idiag_sport != inet->sport &&
+ r->id.idiag_sport)
+ goto next_listen;
+
+ if (!(r->idiag_states & TCPF_LISTEN) ||
+ r->id.idiag_dport ||
+ cb->args[3] > 0)
+ goto syn_recv;
+
+ if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ inet_listen_unlock(hashinfo);
+ goto done;
+ }
+
+syn_recv:
+ if (!(r->idiag_states & TCPF_SYN_RECV))
+ goto next_listen;
+
+ if (inet_diag_dump_reqs(skb, sk, cb) < 0) {
+ inet_listen_unlock(hashinfo);
+ goto done;
+ }
+
+next_listen:
+ cb->args[3] = 0;
+ cb->args[4] = 0;
+ ++num;
+ }
+
+ s_num = 0;
+ cb->args[3] = 0;
+ cb->args[4] = 0;
+ }
+ inet_listen_unlock(hashinfo);
+skip_listen_ht:
+ cb->args[0] = 1;
+ s_i = num = s_num = 0;
+ }
+
+ if (!(r->idiag_states & ~(TCPF_LISTEN | TCPF_SYN_RECV)))
+ return skb->len;
+
+ for (i = s_i; i < hashinfo->ehash_size; i++) {
+ struct inet_ehash_bucket *head = &hashinfo->ehash[i];
+ struct sock *sk;
+ struct hlist_node *node;
+
+ if (i > s_i)
+ s_num = 0;
+
+ read_lock_bh(&head->lock);
+
+ num = 0;
+ sk_for_each(sk, node, &head->chain) {
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (num < s_num)
+ goto next_normal;
+ if (!(r->idiag_states & (1 << sk->sk_state)))
+ goto next_normal;
+ if (r->id.idiag_sport != inet->sport &&
+ r->id.idiag_sport)
+ goto next_normal;
+ if (r->id.idiag_dport != inet->dport && r->id.idiag_dport)
+ goto next_normal;
+ if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ read_unlock_bh(&head->lock);
+ goto done;
+ }
+next_normal:
+ ++num;
+ }
+
+ if (r->idiag_states & TCPF_TIME_WAIT) {
+ sk_for_each(sk, node,
+ &hashinfo->ehash[i + hashinfo->ehash_size].chain) {
+ struct inet_sock *inet = inet_sk(sk);
+
+ if (num < s_num)
+ goto next_dying;
+ if (r->id.idiag_sport != inet->sport &&
+ r->id.idiag_sport)
+ goto next_dying;
+ if (r->id.idiag_dport != inet->dport &&
+ r->id.idiag_dport)
+ goto next_dying;
+ if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ read_unlock_bh(&head->lock);
+ goto done;
+ }
+next_dying:
+ ++num;
+ }
+ }
+ read_unlock_bh(&head->lock);
+ }
+
+done:
+ cb->args[1] = i;
+ cb->args[2] = num;
+ return skb->len;
+}
+
+static int inet_diag_dump_done(struct netlink_callback *cb)
+{
+ return 0;
+}
+
+
+static __inline__ int
+inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
+ return 0;
+
+ if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX)
+ goto err_inval;
+
+ if (inet_diag_table[nlh->nlmsg_type] == NULL)
+ return -ENOENT;
+
+ if (NLMSG_LENGTH(sizeof(struct inet_diag_req)) > skb->len)
+ goto err_inval;
+
+ if (nlh->nlmsg_flags&NLM_F_DUMP) {
+ if (nlh->nlmsg_len >
+ (4 + NLMSG_SPACE(sizeof(struct inet_diag_req)))) {
+ struct rtattr *rta = (void *)(NLMSG_DATA(nlh) +
+ sizeof(struct inet_diag_req));
+ if (rta->rta_type != INET_DIAG_REQ_BYTECODE ||
+ rta->rta_len < 8 ||
+ rta->rta_len >
+ (nlh->nlmsg_len -
+ NLMSG_SPACE(sizeof(struct inet_diag_req))))
+ goto err_inval;
+ if (inet_diag_bc_audit(RTA_DATA(rta), RTA_PAYLOAD(rta)))
+ goto err_inval;
+ }
+ return netlink_dump_start(idiagnl, skb, nlh,
+ inet_diag_dump,
+ inet_diag_dump_done);
+ } else {
+ return inet_diag_get_exact(skb, nlh);
+ }
+
+err_inval:
+ return -EINVAL;
+}
+
+
+static inline void inet_diag_rcv_skb(struct sk_buff *skb)
+{
+ int err;
+ struct nlmsghdr * nlh;
+
+ if (skb->len >= NLMSG_SPACE(0)) {
+ nlh = (struct nlmsghdr *)skb->data;
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ return;
+ err = inet_diag_rcv_msg(skb, nlh);
+ if (err || nlh->nlmsg_flags & NLM_F_ACK)
+ netlink_ack(skb, nlh, err);
+ }
+}
+
+static void inet_diag_rcv(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+ unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+
+ while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) {
+ inet_diag_rcv_skb(skb);
+ kfree_skb(skb);
+ }
+}
+
+static DEFINE_SPINLOCK(inet_diag_register_lock);
+
+int inet_diag_register(const struct inet_diag_handler *h)
+{
+ const __u16 type = h->idiag_type;
+ int err = -EINVAL;
+
+ if (type >= INET_DIAG_GETSOCK_MAX)
+ goto out;
+
+ spin_lock(&inet_diag_register_lock);
+ err = -EEXIST;
+ if (inet_diag_table[type] == NULL) {
+ inet_diag_table[type] = h;
+ err = 0;
+ }
+ spin_unlock(&inet_diag_register_lock);
+out:
+ return err;
+}
+EXPORT_SYMBOL_GPL(inet_diag_register);
+
+void inet_diag_unregister(const struct inet_diag_handler *h)
+{
+ const __u16 type = h->idiag_type;
+
+ if (type >= INET_DIAG_GETSOCK_MAX)
+ return;
+
+ spin_lock(&inet_diag_register_lock);
+ inet_diag_table[type] = NULL;
+ spin_unlock(&inet_diag_register_lock);
+
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(inet_diag_unregister);
+
+static int __init inet_diag_init(void)
+{
+ const int inet_diag_table_size = (INET_DIAG_GETSOCK_MAX *
+ sizeof(struct inet_diag_handler *));
+ int err = -ENOMEM;
+
+ inet_diag_table = kmalloc(inet_diag_table_size, GFP_KERNEL);
+ if (!inet_diag_table)
+ goto out;
+
+ memset(inet_diag_table, 0, inet_diag_table_size);
+ idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
+ THIS_MODULE);
+ if (idiagnl == NULL)
+ goto out_free_table;
+ err = 0;
+out:
+ return err;
+out_free_table:
+ kfree(inet_diag_table);
+ goto out;
+}
+
+static void __exit inet_diag_exit(void)
+{
+ sock_release(idiagnl->sk_socket);
+ kfree(inet_diag_table);
+}
+
+module_init(inet_diag_init);
+module_exit(inet_diag_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
new file mode 100644
index 000000000000..e8d29fe736d2
--- /dev/null
+++ b/net/ipv4/inet_hashtables.c
@@ -0,0 +1,165 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Generic INET transport hashtables
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_hashtables.h>
+
+/*
+ * Allocate and initialize a new local port bind bucket.
+ * The bindhash mutex for snum's hash chain must be held here.
+ */
+struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
+ struct inet_bind_hashbucket *head,
+ const unsigned short snum)
+{
+ struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, SLAB_ATOMIC);
+
+ if (tb != NULL) {
+ tb->port = snum;
+ tb->fastreuse = 0;
+ INIT_HLIST_HEAD(&tb->owners);
+ hlist_add_head(&tb->node, &head->chain);
+ }
+ return tb;
+}
+
+EXPORT_SYMBOL(inet_bind_bucket_create);
+
+/*
+ * Caller must hold hashbucket lock for this tb with local BH disabled
+ */
+void inet_bind_bucket_destroy(kmem_cache_t *cachep, struct inet_bind_bucket *tb)
+{
+ if (hlist_empty(&tb->owners)) {
+ __hlist_del(&tb->node);
+ kmem_cache_free(cachep, tb);
+ }
+}
+
+void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ const unsigned short snum)
+{
+ inet_sk(sk)->num = snum;
+ sk_add_bind_node(sk, &tb->owners);
+ 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.
+ */
+static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+{
+ const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+ struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+ struct inet_bind_bucket *tb;
+
+ spin_lock(&head->lock);
+ tb = inet_csk(sk)->icsk_bind_hash;
+ __sk_del_bind_node(sk);
+ inet_csk(sk)->icsk_bind_hash = NULL;
+ inet_sk(sk)->num = 0;
+ inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+ spin_unlock(&head->lock);
+}
+
+void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+{
+ local_bh_disable();
+ __inet_put_port(hashinfo, sk);
+ local_bh_enable();
+}
+
+EXPORT_SYMBOL(inet_put_port);
+
+/*
+ * This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
+ * Look, when several writers sleep and reader wakes them up, all but one
+ * immediately hit write lock and grab all the cpus. Exclusive sleep solves
+ * this, _but_ remember, it adds useless work on UP machines (wake up each
+ * exclusive lock release). It should be ifdefed really.
+ */
+void inet_listen_wlock(struct inet_hashinfo *hashinfo)
+{
+ write_lock(&hashinfo->lhash_lock);
+
+ if (atomic_read(&hashinfo->lhash_users)) {
+ DEFINE_WAIT(wait);
+
+ for (;;) {
+ prepare_to_wait_exclusive(&hashinfo->lhash_wait,
+ &wait, TASK_UNINTERRUPTIBLE);
+ if (!atomic_read(&hashinfo->lhash_users))
+ break;
+ write_unlock_bh(&hashinfo->lhash_lock);
+ schedule();
+ write_lock_bh(&hashinfo->lhash_lock);
+ }
+
+ finish_wait(&hashinfo->lhash_wait, &wait);
+ }
+}
+
+EXPORT_SYMBOL(inet_listen_wlock);
+
+/*
+ * Don't inline this cruft. Here are some nice properties to exploit here. The
+ * BSD API does not allow a listening sock to specify the remote port nor the
+ * remote address for the connection. So always assume those are both
+ * wildcarded during the search since they can never be otherwise.
+ */
+struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr,
+ const unsigned short hnum, const int dif)
+{
+ struct sock *result = NULL, *sk;
+ const struct hlist_node *node;
+ int hiscore = -1;
+
+ sk_for_each(sk, node, head) {
+ const struct inet_sock *inet = inet_sk(sk);
+
+ if (inet->num == hnum && !ipv6_only_sock(sk)) {
+ const __u32 rcv_saddr = inet->rcv_saddr;
+ int score = sk->sk_family == PF_INET ? 1 : 0;
+
+ if (rcv_saddr) {
+ if (rcv_saddr != daddr)
+ continue;
+ score += 2;
+ }
+ if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if != dif)
+ continue;
+ score += 2;
+ }
+ if (score == 5)
+ return sk;
+ if (score > hiscore) {
+ hiscore = score;
+ result = sk;
+ }
+ }
+ }
+ return result;
+}
+
+EXPORT_SYMBOL_GPL(__inet_lookup_listener);
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
new file mode 100644
index 000000000000..4d1502a49852
--- /dev/null
+++ b/net/ipv4/inet_timewait_sock.c
@@ -0,0 +1,384 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Generic TIME_WAIT sockets functions
+ *
+ * From code orinally in TCP
+ */
+
+#include <linux/config.h>
+
+#include <net/inet_hashtables.h>
+#include <net/inet_timewait_sock.h>
+#include <net/ip.h>
+
+/* Must be called with locally disabled BHs. */
+void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo)
+{
+ struct inet_bind_hashbucket *bhead;
+ struct inet_bind_bucket *tb;
+ /* Unlink from established hashes. */
+ struct inet_ehash_bucket *ehead = &hashinfo->ehash[tw->tw_hashent];
+
+ write_lock(&ehead->lock);
+ if (hlist_unhashed(&tw->tw_node)) {
+ write_unlock(&ehead->lock);
+ return;
+ }
+ __hlist_del(&tw->tw_node);
+ sk_node_init(&tw->tw_node);
+ write_unlock(&ehead->lock);
+
+ /* Disassociate with bind bucket. */
+ bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
+ spin_lock(&bhead->lock);
+ tb = tw->tw_tb;
+ __hlist_del(&tw->tw_bind_node);
+ tw->tw_tb = NULL;
+ inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+ spin_unlock(&bhead->lock);
+#ifdef SOCK_REFCNT_DEBUG
+ if (atomic_read(&tw->tw_refcnt) != 1) {
+ printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n",
+ tw->tw_prot->name, tw, atomic_read(&tw->tw_refcnt));
+ }
+#endif
+ inet_twsk_put(tw);
+}
+
+EXPORT_SYMBOL_GPL(__inet_twsk_kill);
+
+/*
+ * Enter the time wait state. This is called with locally disabled BH.
+ * Essentially we whip up a timewait bucket, copy the relevant info into it
+ * from the SK, and mess with hash chains and list linkage.
+ */
+void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
+ struct inet_hashinfo *hashinfo)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct inet_ehash_bucket *ehead = &hashinfo->ehash[sk->sk_hashent];
+ struct inet_bind_hashbucket *bhead;
+ /* Step 1: Put TW into bind hash. Original socket stays there too.
+ Note, that any socket with inet->num != 0 MUST be bound in
+ binding cache, even if it is closed.
+ */
+ bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)];
+ spin_lock(&bhead->lock);
+ tw->tw_tb = icsk->icsk_bind_hash;
+ BUG_TRAP(icsk->icsk_bind_hash);
+ inet_twsk_add_bind_node(tw, &tw->tw_tb->owners);
+ spin_unlock(&bhead->lock);
+
+ write_lock(&ehead->lock);
+
+ /* Step 2: Remove SK from established hash. */
+ if (__sk_del_node_init(sk))
+ sock_prot_dec_use(sk->sk_prot);
+
+ /* Step 3: Hash TW into TIMEWAIT half of established hash table. */
+ inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain);
+ atomic_inc(&tw->tw_refcnt);
+
+ write_unlock(&ehead->lock);
+}
+
+EXPORT_SYMBOL_GPL(__inet_twsk_hashdance);
+
+struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state)
+{
+ struct inet_timewait_sock *tw = kmem_cache_alloc(sk->sk_prot_creator->twsk_slab,
+ SLAB_ATOMIC);
+ if (tw != NULL) {
+ const struct inet_sock *inet = inet_sk(sk);
+
+ /* Give us an identity. */
+ tw->tw_daddr = inet->daddr;
+ tw->tw_rcv_saddr = inet->rcv_saddr;
+ tw->tw_bound_dev_if = sk->sk_bound_dev_if;
+ tw->tw_num = inet->num;
+ tw->tw_state = TCP_TIME_WAIT;
+ tw->tw_substate = state;
+ tw->tw_sport = inet->sport;
+ tw->tw_dport = inet->dport;
+ tw->tw_family = sk->sk_family;
+ tw->tw_reuse = sk->sk_reuse;
+ tw->tw_hashent = sk->sk_hashent;
+ tw->tw_ipv6only = 0;
+ tw->tw_prot = sk->sk_prot_creator;
+ atomic_set(&tw->tw_refcnt, 1);
+ inet_twsk_dead_node_init(tw);
+ }
+
+ return tw;
+}
+
+EXPORT_SYMBOL_GPL(inet_twsk_alloc);
+
+/* Returns non-zero if quota exceeded. */
+static int inet_twdr_do_twkill_work(struct inet_timewait_death_row *twdr,
+ const int slot)
+{
+ struct inet_timewait_sock *tw;
+ struct hlist_node *node;
+ unsigned int killed;
+ int ret;
+
+ /* NOTE: compare this to previous version where lock
+ * was released after detaching chain. It was racy,
+ * because tw buckets are scheduled in not serialized context
+ * in 2.3 (with netfilter), and with softnet it is common, because
+ * soft irqs are not sequenced.
+ */
+ killed = 0;
+ ret = 0;
+rescan:
+ inet_twsk_for_each_inmate(tw, node, &twdr->cells[slot]) {
+ __inet_twsk_del_dead_node(tw);
+ spin_unlock(&twdr->death_lock);
+ __inet_twsk_kill(tw, twdr->hashinfo);
+ inet_twsk_put(tw);
+ killed++;
+ spin_lock(&twdr->death_lock);
+ if (killed > INET_TWDR_TWKILL_QUOTA) {
+ ret = 1;
+ break;
+ }
+
+ /* While we dropped twdr->death_lock, another cpu may have
+ * killed off the next TW bucket in the list, therefore
+ * do a fresh re-read of the hlist head node with the
+ * lock reacquired. We still use the hlist traversal
+ * macro in order to get the prefetches.
+ */
+ goto rescan;
+ }
+
+ twdr->tw_count -= killed;
+ NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITED, killed);
+
+ return ret;
+}
+
+void inet_twdr_hangman(unsigned long data)
+{
+ struct inet_timewait_death_row *twdr;
+ int unsigned need_timer;
+
+ twdr = (struct inet_timewait_death_row *)data;
+ spin_lock(&twdr->death_lock);
+
+ if (twdr->tw_count == 0)
+ goto out;
+
+ need_timer = 0;
+ if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
+ twdr->thread_slots |= (1 << twdr->slot);
+ mb();
+ schedule_work(&twdr->twkill_work);
+ need_timer = 1;
+ } else {
+ /* We purged the entire slot, anything left? */
+ if (twdr->tw_count)
+ need_timer = 1;
+ }
+ twdr->slot = ((twdr->slot + 1) & (INET_TWDR_TWKILL_SLOTS - 1));
+ if (need_timer)
+ mod_timer(&twdr->tw_timer, jiffies + twdr->period);
+out:
+ spin_unlock(&twdr->death_lock);
+}
+
+EXPORT_SYMBOL_GPL(inet_twdr_hangman);
+
+extern void twkill_slots_invalid(void);
+
+void inet_twdr_twkill_work(void *data)
+{
+ struct inet_timewait_death_row *twdr = data;
+ int i;
+
+ if ((INET_TWDR_TWKILL_SLOTS - 1) > (sizeof(twdr->thread_slots) * 8))
+ twkill_slots_invalid();
+
+ while (twdr->thread_slots) {
+ spin_lock_bh(&twdr->death_lock);
+ for (i = 0; i < INET_TWDR_TWKILL_SLOTS; i++) {
+ if (!(twdr->thread_slots & (1 << i)))
+ continue;
+
+ while (inet_twdr_do_twkill_work(twdr, i) != 0) {
+ if (need_resched()) {
+ spin_unlock_bh(&twdr->death_lock);
+ schedule();
+ spin_lock_bh(&twdr->death_lock);
+ }
+ }
+
+ twdr->thread_slots &= ~(1 << i);
+ }
+ spin_unlock_bh(&twdr->death_lock);
+ }
+}
+
+EXPORT_SYMBOL_GPL(inet_twdr_twkill_work);
+
+/* These are always called from BH context. See callers in
+ * tcp_input.c to verify this.
+ */
+
+/* This is for handling early-kills of TIME_WAIT sockets. */
+void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr)
+{
+ spin_lock(&twdr->death_lock);
+ if (inet_twsk_del_dead_node(tw)) {
+ inet_twsk_put(tw);
+ if (--twdr->tw_count == 0)
+ del_timer(&twdr->tw_timer);
+ }
+ spin_unlock(&twdr->death_lock);
+ __inet_twsk_kill(tw, twdr->hashinfo);
+}
+
+EXPORT_SYMBOL(inet_twsk_deschedule);
+
+void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr,
+ const int timeo, const int timewait_len)
+{
+ struct hlist_head *list;
+ int slot;
+
+ /* timeout := RTO * 3.5
+ *
+ * 3.5 = 1+2+0.5 to wait for two retransmits.
+ *
+ * RATIONALE: if FIN arrived and we entered TIME-WAIT state,
+ * our ACK acking that FIN can be lost. If N subsequent retransmitted
+ * FINs (or previous seqments) are lost (probability of such event
+ * is p^(N+1), where p is probability to lose single packet and
+ * time to detect the loss is about RTO*(2^N - 1) with exponential
+ * backoff). Normal timewait length is calculated so, that we
+ * waited at least for one retransmitted FIN (maximal RTO is 120sec).
+ * [ BTW Linux. following BSD, violates this requirement waiting
+ * only for 60sec, we should wait at least for 240 secs.
+ * Well, 240 consumes too much of resources 8)
+ * ]
+ * This interval is not reduced to catch old duplicate and
+ * responces to our wandering segments living for two MSLs.
+ * However, if we use PAWS to detect
+ * old duplicates, we can reduce the interval to bounds required
+ * by RTO, rather than MSL. So, if peer understands PAWS, we
+ * kill tw bucket after 3.5*RTO (it is important that this number
+ * is greater than TS tick!) and detect old duplicates with help
+ * of PAWS.
+ */
+ slot = (timeo + (1 << INET_TWDR_RECYCLE_TICK) - 1) >> INET_TWDR_RECYCLE_TICK;
+
+ spin_lock(&twdr->death_lock);
+
+ /* Unlink it, if it was scheduled */
+ if (inet_twsk_del_dead_node(tw))
+ twdr->tw_count--;
+ else
+ atomic_inc(&tw->tw_refcnt);
+
+ if (slot >= INET_TWDR_RECYCLE_SLOTS) {
+ /* Schedule to slow timer */
+ if (timeo >= timewait_len) {
+ slot = INET_TWDR_TWKILL_SLOTS - 1;
+ } else {
+ slot = (timeo + twdr->period - 1) / twdr->period;
+ if (slot >= INET_TWDR_TWKILL_SLOTS)
+ slot = INET_TWDR_TWKILL_SLOTS - 1;
+ }
+ tw->tw_ttd = jiffies + timeo;
+ slot = (twdr->slot + slot) & (INET_TWDR_TWKILL_SLOTS - 1);
+ list = &twdr->cells[slot];
+ } else {
+ tw->tw_ttd = jiffies + (slot << INET_TWDR_RECYCLE_TICK);
+
+ if (twdr->twcal_hand < 0) {
+ twdr->twcal_hand = 0;
+ twdr->twcal_jiffie = jiffies;
+ twdr->twcal_timer.expires = twdr->twcal_jiffie +
+ (slot << INET_TWDR_RECYCLE_TICK);
+ add_timer(&twdr->twcal_timer);
+ } else {
+ if (time_after(twdr->twcal_timer.expires,
+ jiffies + (slot << INET_TWDR_RECYCLE_TICK)))
+ mod_timer(&twdr->twcal_timer,
+ jiffies + (slot << INET_TWDR_RECYCLE_TICK));
+ slot = (twdr->twcal_hand + slot) & (INET_TWDR_RECYCLE_SLOTS - 1);
+ }
+ list = &twdr->twcal_row[slot];
+ }
+
+ hlist_add_head(&tw->tw_death_node, list);
+
+ if (twdr->tw_count++ == 0)
+ mod_timer(&twdr->tw_timer, jiffies + twdr->period);
+ spin_unlock(&twdr->death_lock);
+}
+
+EXPORT_SYMBOL_GPL(inet_twsk_schedule);
+
+void inet_twdr_twcal_tick(unsigned long data)
+{
+ struct inet_timewait_death_row *twdr;
+ int n, slot;
+ unsigned long j;
+ unsigned long now = jiffies;
+ int killed = 0;
+ int adv = 0;
+
+ twdr = (struct inet_timewait_death_row *)data;
+
+ spin_lock(&twdr->death_lock);
+ if (twdr->twcal_hand < 0)
+ goto out;
+
+ slot = twdr->twcal_hand;
+ j = twdr->twcal_jiffie;
+
+ for (n = 0; n < INET_TWDR_RECYCLE_SLOTS; n++) {
+ if (time_before_eq(j, now)) {
+ struct hlist_node *node, *safe;
+ struct inet_timewait_sock *tw;
+
+ inet_twsk_for_each_inmate_safe(tw, node, safe,
+ &twdr->twcal_row[slot]) {
+ __inet_twsk_del_dead_node(tw);
+ __inet_twsk_kill(tw, twdr->hashinfo);
+ inet_twsk_put(tw);
+ killed++;
+ }
+ } else {
+ if (!adv) {
+ adv = 1;
+ twdr->twcal_jiffie = j;
+ twdr->twcal_hand = slot;
+ }
+
+ if (!hlist_empty(&twdr->twcal_row[slot])) {
+ mod_timer(&twdr->twcal_timer, j);
+ goto out;
+ }
+ }
+ j += 1 << INET_TWDR_RECYCLE_TICK;
+ slot = (slot + 1) & (INET_TWDR_RECYCLE_SLOTS - 1);
+ }
+ twdr->twcal_hand = -1;
+
+out:
+ if ((twdr->tw_count -= killed) == 0)
+ del_timer(&twdr->tw_timer);
+ NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITKILLED, killed);
+ spin_unlock(&twdr->death_lock);
+}
+
+EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index ab18a853d7ce..2fc3fd38924f 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/net.h>
+#include <net/ip.h>
#include <net/inetpeer.h>
/*
@@ -72,7 +73,7 @@
/* Exported for inet_getid inline function. */
DEFINE_SPINLOCK(inet_peer_idlock);
-static kmem_cache_t *peer_cachep;
+static kmem_cache_t *peer_cachep __read_mostly;
#define node_height(x) x->avl_height
static struct inet_peer peer_fake_node = {
@@ -99,8 +100,7 @@ DEFINE_SPINLOCK(inet_peer_unused_lock);
#define PEER_MAX_CLEANUP_WORK 30
static void peer_check_expire(unsigned long dummy);
-static struct timer_list peer_periodic_timer =
- TIMER_INITIALIZER(peer_check_expire, 0, 0);
+static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
/* Exported for sysctl_net_ipv4. */
int inet_peer_gc_mintime = 10 * HZ,
@@ -459,5 +459,3 @@ static void peer_check_expire(unsigned long dummy)
peer_total / inet_peer_threshold * HZ;
add_timer(&peer_periodic_timer);
}
-
-EXPORT_SYMBOL(inet_peer_idlock);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 77094aac6c28..0923add122b4 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -76,16 +76,12 @@ int ip_forward(struct sk_buff *skb)
* that reaches zero, we must reply an ICMP control message telling
* that the packet's lifetime expired.
*/
-
- iph = skb->nh.iph;
-
- if (iph->ttl <= 1)
+ if (skb->nh.iph->ttl <= 1)
goto too_many_hops;
if (!xfrm4_route_forward(skb))
goto drop;
- iph = skb->nh.iph;
rt = (struct rtable*)skb->dst;
if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index eb377ae15305..e7d26d9943c2 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -377,7 +377,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
return ip_frag_intern(hash, qp);
out_nomem:
- LIMIT_NETDEBUG(printk(KERN_ERR "ip_frag_create: no memory left !\n"));
+ LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
return NULL;
}
@@ -457,7 +457,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (pskb_pull(skb, ihl) == NULL)
goto err;
- if (pskb_trim(skb, end-offset))
+ if (pskb_trim_rcsum(skb, end-offset))
goto err;
/* Find out which fragments are in front and at the back of us
@@ -533,7 +533,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (skb->dev)
qp->iif = skb->dev->ifindex;
skb->dev = NULL;
- qp->stamp = skb->stamp;
+ skb_get_timestamp(skb, &qp->stamp);
qp->meat += skb->len;
atomic_add(skb->truesize, &ip_frag_mem);
if (offset == 0)
@@ -615,7 +615,7 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
head->next = NULL;
head->dev = dev;
- head->stamp = qp->stamp;
+ skb_set_timestamp(head, &qp->stamp);
iph = head->nh.iph;
iph->frag_off = 0;
@@ -625,8 +625,8 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
return head;
out_nomem:
- LIMIT_NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing "
- "queue %p\n", qp));
+ LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
+ "queue %p\n", qp);
goto out_fail;
out_oversize:
if (net_ratelimit())
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c703528e0bcd..473d0f2b2e0d 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -150,7 +150,7 @@
* SNMP management statistics
*/
-DEFINE_SNMP_STAT(struct ipstats_mib, ip_statistics);
+DEFINE_SNMP_STAT(struct ipstats_mib, ip_statistics) __read_mostly;
/*
* Process Router Attention IP option
@@ -225,8 +225,8 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
/* If there maybe a raw socket we must check - if not we
* don't care less
*/
- if (raw_sk)
- raw_v4_input(skb, skb->nh.iph, hash);
+ if (raw_sk && !raw_v4_input(skb, skb->nh.iph, hash))
+ raw_sk = NULL;
if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
int ret;
@@ -279,18 +279,70 @@ int ip_local_deliver(struct sk_buff *skb)
ip_local_deliver_finish);
}
-static inline int ip_rcv_finish(struct sk_buff *skb)
+static inline int ip_rcv_options(struct sk_buff *skb)
{
+ struct ip_options *opt;
+ struct iphdr *iph;
struct net_device *dev = skb->dev;
+
+ /* It looks as overkill, because not all
+ IP options require packet mangling.
+ But it is the easiest for now, especially taking
+ into account that combination of IP options
+ and running sniffer is extremely rare condition.
+ --ANK (980813)
+ */
+ if (skb_cow(skb, skb_headroom(skb))) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ goto drop;
+ }
+
+ iph = skb->nh.iph;
+
+ if (ip_options_compile(NULL, skb)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ goto drop;
+ }
+
+ opt = &(IPCB(skb)->opt);
+ if (unlikely(opt->srr)) {
+ struct in_device *in_dev = in_dev_get(dev);
+ if (in_dev) {
+ if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
+ if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ net_ratelimit())
+ printk(KERN_INFO "source route option "
+ "%u.%u.%u.%u -> %u.%u.%u.%u\n",
+ NIPQUAD(iph->saddr),
+ NIPQUAD(iph->daddr));
+ in_dev_put(in_dev);
+ goto drop;
+ }
+
+ in_dev_put(in_dev);
+ }
+
+ if (ip_options_rcv_srr(skb))
+ goto drop;
+ }
+
+ return 0;
+drop:
+ return -1;
+}
+
+static inline int ip_rcv_finish(struct sk_buff *skb)
+{
struct iphdr *iph = skb->nh.iph;
- int err;
/*
* Initialise the virtual path cache for the packet. It describes
* how the packet travels inside Linux networking.
*/
- if (skb->dst == NULL) {
- if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
+ if (likely(skb->dst == NULL)) {
+ int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
+ skb->dev);
+ if (unlikely(err)) {
if (err == -EHOSTUNREACH)
IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
goto drop;
@@ -298,7 +350,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
}
#ifdef CONFIG_NET_CLS_ROUTE
- if (skb->dst->tclassid) {
+ if (unlikely(skb->dst->tclassid)) {
struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
u32 idx = skb->dst->tclassid;
st[idx&0xFF].o_packets++;
@@ -308,48 +360,11 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
}
#endif
- if (iph->ihl > 5) {
- struct ip_options *opt;
-
- /* It looks as overkill, because not all
- IP options require packet mangling.
- But it is the easiest for now, especially taking
- into account that combination of IP options
- and running sniffer is extremely rare condition.
- --ANK (980813)
- */
-
- if (skb_cow(skb, skb_headroom(skb))) {
- IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
- iph = skb->nh.iph;
-
- if (ip_options_compile(NULL, skb))
- goto inhdr_error;
-
- opt = &(IPCB(skb)->opt);
- if (opt->srr) {
- struct in_device *in_dev = in_dev_get(dev);
- if (in_dev) {
- if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
- if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
- NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
- in_dev_put(in_dev);
- goto drop;
- }
- in_dev_put(in_dev);
- }
- if (ip_options_rcv_srr(skb))
- goto drop;
- }
- }
+ if (iph->ihl > 5 && ip_rcv_options(skb))
+ goto drop;
return dst_input(skb);
-inhdr_error:
- IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
drop:
kfree_skb(skb);
return NET_RX_DROP;
@@ -358,9 +373,10 @@ drop:
/*
* Main IP Receive routine.
*/
-int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct iphdr *iph;
+ u32 len;
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
@@ -392,29 +408,27 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
*/
if (iph->ihl < 5 || iph->version != 4)
- goto inhdr_error;
+ goto inhdr_error;
if (!pskb_may_pull(skb, iph->ihl*4))
goto inhdr_error;
iph = skb->nh.iph;
- if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
- goto inhdr_error;
+ if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+ goto inhdr_error;
- {
- __u32 len = ntohs(iph->tot_len);
- if (skb->len < len || len < (iph->ihl<<2))
- goto inhdr_error;
+ len = ntohs(iph->tot_len);
+ if (skb->len < len || len < (iph->ihl*4))
+ goto inhdr_error;
- /* Our transport medium may have padded the buffer out. Now we know it
- * is IP we can trim to the true length of the frame.
- * Note this now means skb->len holds ntohs(iph->tot_len).
- */
- if (pskb_trim_rcsum(skb, len)) {
- IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
+ /* Our transport medium may have padded the buffer out. Now we know it
+ * is IP we can trim to the true length of the frame.
+ * Note this now means skb->len holds ntohs(iph->tot_len).
+ */
+ if (pskb_trim_rcsum(skb, len)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ goto drop;
}
return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
@@ -428,5 +442,4 @@ out:
return NET_RX_DROP;
}
-EXPORT_SYMBOL(ip_rcv);
EXPORT_SYMBOL(ip_statistics);
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 6d89f3f3e701..bce4e875193b 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -489,23 +489,18 @@ void ip_options_undo(struct ip_options * opt)
}
}
-int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user)
+static struct ip_options *ip_options_get_alloc(const int optlen)
{
- struct ip_options *opt;
+ struct ip_options *opt = kmalloc(sizeof(*opt) + ((optlen + 3) & ~3),
+ GFP_KERNEL);
+ if (opt)
+ memset(opt, 0, sizeof(*opt));
+ return opt;
+}
- opt = kmalloc(sizeof(struct ip_options)+((optlen+3)&~3), GFP_KERNEL);
- if (!opt)
- return -ENOMEM;
- memset(opt, 0, sizeof(struct ip_options));
- if (optlen) {
- if (user) {
- if (copy_from_user(opt->__data, data, optlen)) {
- kfree(opt);
- return -EFAULT;
- }
- } else
- memcpy(opt->__data, data, optlen);
- }
+static int ip_options_get_finish(struct ip_options **optp,
+ struct ip_options *opt, int optlen)
+{
while (optlen & 3)
opt->__data[optlen++] = IPOPT_END;
opt->optlen = optlen;
@@ -521,6 +516,30 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, in
return 0;
}
+int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen)
+{
+ struct ip_options *opt = ip_options_get_alloc(optlen);
+
+ if (!opt)
+ return -ENOMEM;
+ if (optlen && copy_from_user(opt->__data, data, optlen)) {
+ kfree(opt);
+ return -EFAULT;
+ }
+ return ip_options_get_finish(optp, opt, optlen);
+}
+
+int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)
+{
+ struct ip_options *opt = ip_options_get_alloc(optlen);
+
+ if (!opt)
+ return -ENOMEM;
+ if (optlen)
+ memcpy(opt->__data, data, optlen);
+ return ip_options_get_finish(optp, opt, optlen);
+}
+
void ip_forward_options(struct sk_buff *skb)
{
struct ip_options * opt = &(IPCB(skb)->opt);
@@ -620,6 +639,3 @@ int ip_options_rcv_srr(struct sk_buff *skb)
}
return 0;
}
-
-EXPORT_SYMBOL(ip_options_compile);
-EXPORT_SYMBOL(ip_options_undo);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 80d13103b2b0..3f1a263e1249 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -69,13 +69,10 @@
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
-#include <net/tcp.h>
-#include <net/udp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/arp.h>
#include <net/icmp.h>
-#include <net/raw.h>
#include <net/checksum.h>
#include <net/inetpeer.h>
#include <net/checksum.h>
@@ -84,12 +81,8 @@
#include <linux/netfilter_bridge.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
+#include <linux/tcp.h>
-/*
- * Shall we try to damage output packets if routing dev changes?
- */
-
-int sysctl_ip_dynaddr;
int sysctl_ip_default_ttl = IPDEFTTL;
/* Generate a checksum for an outgoing IP datagram. */
@@ -165,6 +158,8 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
dst_output);
}
+EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
+
static inline int ip_finish_output2(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
@@ -205,7 +200,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
return -EINVAL;
}
-int ip_finish_output(struct sk_buff *skb)
+static inline int ip_finish_output(struct sk_buff *skb)
{
struct net_device *dev = skb->dst->dev;
@@ -329,8 +324,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
if (ip_route_output_flow(&rt, &fl, sk, 0))
goto no_route;
}
- __sk_dst_set(sk, &rt->u.dst);
- tcp_v4_setup_caps(sk, &rt->u.dst);
+ sk_setup_caps(sk, &rt->u.dst);
}
skb->dst = dst_clone(&rt->u.dst);
@@ -392,7 +386,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
#endif
#ifdef CONFIG_NETFILTER
to->nfmark = from->nfmark;
- to->nfcache = from->nfcache;
/* Connection association is same as pre-frag packet */
nf_conntrack_put(to->nfct);
to->nfct = from->nfct;
@@ -580,7 +573,7 @@ slow_path:
*/
if ((skb2 = alloc_skb(len+hlen+ll_rs, GFP_ATOMIC)) == NULL) {
- NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
+ NETDEBUG(KERN_INFO "IP: frag: no memory for new fragment!\n");
err = -ENOMEM;
goto fail;
}
@@ -1329,12 +1322,7 @@ void __init ip_init(void)
#endif
}
-EXPORT_SYMBOL(ip_finish_output);
EXPORT_SYMBOL(ip_fragment);
EXPORT_SYMBOL(ip_generic_getfrag);
EXPORT_SYMBOL(ip_queue_xmit);
EXPORT_SYMBOL(ip_send_check);
-
-#ifdef CONFIG_SYSCTL
-EXPORT_SYMBOL(sysctl_ip_default_ttl);
-#endif
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index ff4bd067b397..2f0b47da5b37 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -153,7 +153,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
switch (cmsg->cmsg_type) {
case IP_RETOPTS:
err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
- err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40, 0);
+ err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40);
if (err)
return err;
break;
@@ -425,7 +425,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
struct ip_options * opt = NULL;
if (optlen > 40 || optlen < 0)
goto e_inval;
- err = ip_options_get(&opt, optval, optlen, 1);
+ err = ip_options_get_from_user(&opt, optval, optlen);
if (err)
break;
if (sk->sk_type == SOCK_STREAM) {
@@ -614,7 +614,6 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
}
case IP_MSFILTER:
{
- extern int sysctl_optmem_max;
extern int sysctl_igmp_max_msf;
struct ip_msfilter *msf;
@@ -769,7 +768,6 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
}
case MCAST_MSFILTER:
{
- extern int sysctl_optmem_max;
extern int sysctl_igmp_max_msf;
struct sockaddr_in *psin;
struct ip_msfilter *msf = NULL;
@@ -1090,7 +1088,5 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
EXPORT_SYMBOL(ip_cmsg_recv);
-#ifdef CONFIG_IP_SCTP_MODULE
EXPORT_SYMBOL(ip_getsockopt);
EXPORT_SYMBOL(ip_setsockopt);
-#endif
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 7ded6e60f43a..fc718df17b40 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -214,8 +214,8 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
spi, IPPROTO_COMP, AF_INET);
if (!x)
return;
- NETDEBUG(printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%u.%u.%u.%u\n",
- spi, NIPQUAD(iph->daddr)));
+ NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%u.%u.%u.%u\n",
+ spi, NIPQUAD(iph->daddr));
xfrm_state_put(x);
}
@@ -345,8 +345,7 @@ static void ipcomp_free_tfms(struct crypto_tfm **tfms)
for_each_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
- if (tfm)
- crypto_free_tfm(tfm);
+ crypto_free_tfm(tfm);
}
free_percpu(tfms);
}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index d2bf8e1930a3..e8674baaa8d9 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -54,6 +54,7 @@
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/delay.h>
+#include <linux/nfs_fs.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
@@ -393,7 +394,7 @@ static int __init ic_defaults(void)
#ifdef IPCONFIG_RARP
-static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
+static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
static struct packet_type rarp_packet_type __initdata = {
.type = __constant_htons(ETH_P_RARP),
@@ -414,7 +415,7 @@ static inline void ic_rarp_cleanup(void)
* Process received RARP packet.
*/
static int __init
-ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *rarp;
unsigned char *rarp_ptr;
@@ -555,7 +556,7 @@ struct bootp_pkt { /* BOOTP packet format */
#define DHCPRELEASE 7
#define DHCPINFORM 8
-static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
+static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
static struct packet_type bootp_packet_type __initdata = {
.type = __constant_htons(ETH_P_IP),
@@ -823,7 +824,7 @@ static void __init ic_do_bootp_ext(u8 *ext)
/*
* Receive BOOTP reply.
*/
-static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct bootp_pkt *b;
struct iphdr *h;
@@ -1102,10 +1103,8 @@ static int __init ic_dynamic(void)
#endif
jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
- while (time_before(jiffies, jiff) && !ic_got_reply) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (time_before(jiffies, jiff) && !ic_got_reply)
+ schedule_timeout_uninterruptible(1);
#ifdef IPCONFIG_DHCP
/* DHCP isn't done until we get a DHCPACK. */
if ((ic_got_reply & IC_BOOTP)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index dc806b578427..9dbf5909f3a6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -103,7 +103,7 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
In this case data path is free of exclusive locks at all.
*/
-static kmem_cache_t *mrt_cachep;
+static kmem_cache_t *mrt_cachep __read_mostly;
static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local);
static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert);
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index d9212addd193..6e092dadb388 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -26,6 +26,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <net/protocol.h>
+#include <net/tcp.h>
#include <asm/system.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index d0145a8b1551..e11952ea17af 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -40,7 +40,7 @@
static struct list_head *ip_vs_conn_tab;
/* SLAB cache for IPVS connections */
-static kmem_cache_t *ip_vs_conn_cachep;
+static kmem_cache_t *ip_vs_conn_cachep __read_mostly;
/* counter for current IPVS connections */
static atomic_t ip_vs_conn_count = ATOMIC_INIT(0);
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 5fb257dd07cb..3ac7eeca04ac 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -22,6 +22,7 @@
*
* Changes:
* Paul `Rusty' Russell properly handle non-linear skbs
+ * Harald Welte don't use nfcache
*
*/
@@ -529,7 +530,7 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- if (!((*pskb)->nfcache & NFC_IPVS_PROPERTY))
+ if (!((*pskb)->ipvs_property))
return NF_ACCEPT;
/* The packet was sent from IPVS, exit this chain */
@@ -701,7 +702,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
/* do the statistics and put it back */
ip_vs_out_stats(cp, skb);
- skb->nfcache |= NFC_IPVS_PROPERTY;
+ skb->ipvs_property = 1;
verdict = NF_ACCEPT;
out:
@@ -739,7 +740,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
EnterFunction(11);
- if (skb->nfcache & NFC_IPVS_PROPERTY)
+ if (skb->ipvs_property)
return NF_ACCEPT;
iph = skb->nh.iph;
@@ -821,7 +822,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
ip_vs_conn_put(cp);
- skb->nfcache |= NFC_IPVS_PROPERTY;
+ skb->ipvs_property = 1;
LeaveFunction(11);
return NF_ACCEPT;
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 7d99ede2ef79..2d66848e7aa0 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1598,7 +1598,7 @@ static ctl_table vs_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table ipv4_table[] = {
+static ctl_table ipvs_ipv4_table[] = {
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
@@ -1613,7 +1613,7 @@ static ctl_table vs_root_table[] = {
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
- .child = ipv4_table,
+ .child = ipvs_ipv4_table,
},
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c
index c035838b780a..561cda326fa8 100644
--- a/net/ipv4/ipvs/ip_vs_lblc.c
+++ b/net/ipv4/ipvs/ip_vs_lblc.c
@@ -131,7 +131,7 @@ static ctl_table vs_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table ipv4_table[] = {
+static ctl_table ipvs_ipv4_table[] = {
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
@@ -146,7 +146,7 @@ static ctl_table lblc_root_table[] = {
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
- .child = ipv4_table
+ .child = ipvs_ipv4_table
},
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index 22b5dd55d271..ce456dbf09a5 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -320,7 +320,7 @@ static ctl_table vs_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table ipv4_table[] = {
+static ctl_table ipvs_ipv4_table[] = {
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
@@ -335,7 +335,7 @@ static ctl_table lblcr_root_table[] = {
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
- .child = ipv4_table
+ .child = ipvs_ipv4_table
},
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index e65de675da74..c19408973c09 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -604,14 +604,14 @@ void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp)
}
-static void tcp_init(struct ip_vs_protocol *pp)
+static void ip_vs_tcp_init(struct ip_vs_protocol *pp)
{
IP_VS_INIT_HASH_TABLE(tcp_apps);
pp->timeout_table = tcp_timeouts;
}
-static void tcp_exit(struct ip_vs_protocol *pp)
+static void ip_vs_tcp_exit(struct ip_vs_protocol *pp)
{
}
@@ -621,8 +621,8 @@ struct ip_vs_protocol ip_vs_protocol_tcp = {
.protocol = IPPROTO_TCP,
.dont_defrag = 0,
.appcnt = ATOMIC_INIT(0),
- .init = tcp_init,
- .exit = tcp_exit,
+ .init = ip_vs_tcp_init,
+ .exit = ip_vs_tcp_exit,
.register_app = tcp_register_app,
.unregister_app = tcp_unregister_app,
.conn_schedule = tcp_conn_schedule,
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index a8512a3fd08a..3b87482049cf 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -127,7 +127,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
#define IP_VS_XMIT(skb, rt) \
do { \
- (skb)->nfcache |= NFC_IPVS_PROPERTY; \
+ (skb)->ipvs_property = 1; \
(skb)->ip_summed = CHECKSUM_NONE; \
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
(rt)->u.dst.dev, dst_output); \
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
index c9cf8726051d..db67373f9b34 100644
--- a/net/ipv4/multipath_drr.c
+++ b/net/ipv4/multipath_drr.c
@@ -107,7 +107,7 @@ static int drr_dev_event(struct notifier_block *this,
return NOTIFY_DONE;
}
-struct notifier_block drr_dev_notifier = {
+static struct notifier_block drr_dev_notifier = {
.notifier_call = drr_dev_event,
};
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
new file mode 100644
index 000000000000..ae0779d82c5d
--- /dev/null
+++ b/net/ipv4/netfilter.c
@@ -0,0 +1,139 @@
+/* IPv4 specific functions of netfilter core */
+
+#include <linux/config.h>
+#ifdef CONFIG_NETFILTER
+
+#include <linux/kernel.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
+#include <net/route.h>
+#include <linux/ip.h>
+
+/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
+int ip_route_me_harder(struct sk_buff **pskb)
+{
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct rtable *rt;
+ struct flowi fl = {};
+ struct dst_entry *odst;
+ unsigned int hh_len;
+
+ /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
+ * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
+ */
+ if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
+ fl.nl_u.ip4_u.daddr = iph->daddr;
+ fl.nl_u.ip4_u.saddr = iph->saddr;
+ fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+ fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
+#endif
+ fl.proto = iph->protocol;
+ if (ip_route_output_key(&rt, &fl) != 0)
+ return -1;
+
+ /* Drop old route. */
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = &rt->u.dst;
+ } else {
+ /* non-local src, find valid iif to satisfy
+ * rp-filter when calling ip_route_input. */
+ fl.nl_u.ip4_u.daddr = iph->saddr;
+ if (ip_route_output_key(&rt, &fl) != 0)
+ return -1;
+
+ odst = (*pskb)->dst;
+ if (ip_route_input(*pskb, iph->daddr, iph->saddr,
+ RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+ dst_release(&rt->u.dst);
+ return -1;
+ }
+ dst_release(&rt->u.dst);
+ dst_release(odst);
+ }
+
+ if ((*pskb)->dst->error)
+ return -1;
+
+ /* Change in oif may mean change in hh_len. */
+ hh_len = (*pskb)->dst->dev->hard_header_len;
+ if (skb_headroom(*pskb) < hh_len) {
+ struct sk_buff *nskb;
+
+ nskb = skb_realloc_headroom(*pskb, hh_len);
+ if (!nskb)
+ return -1;
+ if ((*pskb)->sk)
+ skb_set_owner_w(nskb, (*pskb)->sk);
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ip_route_me_harder);
+
+/*
+ * Extra routing may needed on local out, as the QUEUE target never
+ * returns control to the table.
+ */
+
+struct ip_rt_info {
+ u_int32_t daddr;
+ u_int32_t saddr;
+ u_int8_t tos;
+};
+
+static void queue_save(const struct sk_buff *skb, struct nf_info *info)
+{
+ struct ip_rt_info *rt_info = nf_info_reroute(info);
+
+ if (info->hook == NF_IP_LOCAL_OUT) {
+ const struct iphdr *iph = skb->nh.iph;
+
+ rt_info->tos = iph->tos;
+ rt_info->daddr = iph->daddr;
+ rt_info->saddr = iph->saddr;
+ }
+}
+
+static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
+{
+ const struct ip_rt_info *rt_info = nf_info_reroute(info);
+
+ if (info->hook == NF_IP_LOCAL_OUT) {
+ struct iphdr *iph = (*pskb)->nh.iph;
+
+ if (!(iph->tos == rt_info->tos
+ && iph->daddr == rt_info->daddr
+ && iph->saddr == rt_info->saddr))
+ return ip_route_me_harder(pskb);
+ }
+ return 0;
+}
+
+static struct nf_queue_rerouter ip_reroute = {
+ .rer_size = sizeof(struct ip_rt_info),
+ .save = queue_save,
+ .reroute = queue_reroute,
+};
+
+static int init(void)
+{
+ return nf_register_queue_rerouter(PF_INET, &ip_reroute);
+}
+
+static void fini(void)
+{
+ nf_unregister_queue_rerouter(PF_INET);
+}
+
+module_init(init);
+module_exit(fini);
+
+#endif /* CONFIG_NETFILTER */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 46d4cb1c06f0..30aa8e2ee214 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -34,12 +34,23 @@ config IP_NF_CT_ACCT
config IP_NF_CONNTRACK_MARK
bool 'Connection mark tracking support'
+ depends on IP_NF_CONNTRACK
help
This option enables support for connection marks, used by the
`CONNMARK' target and `connmark' match. Similar to the mark value
of packets, but this mark value is kept in the conntrack session
instead of the individual packets.
+config IP_NF_CONNTRACK_EVENTS
+ bool "Connection tracking events"
+ depends on IP_NF_CONNTRACK
+ help
+ If this option is enabled, the connection tracking code will
+ provide a notifier chain that can be used by other kernel code
+ to get notified about changes in the connection tracking state.
+
+ IF unsure, say `N'.
+
config IP_NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
depends on IP_NF_CONNTRACK && EXPERIMENTAL
@@ -75,6 +86,25 @@ config IP_NF_IRC
To compile it as a module, choose M here. If unsure, say Y.
+config IP_NF_NETBIOS_NS
+ tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
+ depends on IP_NF_CONNTRACK && EXPERIMENTAL
+ help
+ NetBIOS name service requests are sent as broadcast messages from an
+ unprivileged port and responded to with unicast messages to the
+ same port. This make them hard to firewall properly because connection
+ tracking doesn't deal with broadcasts. This helper tracks locally
+ originating NetBIOS name service requests and the corresponding
+ responses. It relies on correct IP address configuration, specifically
+ netmask and broadcast address. When properly configured, the output
+ of "ip address show" should look similar to this:
+
+ $ ip -4 address show eth0
+ 4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
+ inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_TFTP
tristate "TFTP protocol support"
depends on IP_NF_CONNTRACK
@@ -100,11 +130,15 @@ config IP_NF_AMANDA
To compile it as a module, choose M here. If unsure, say Y.
config IP_NF_QUEUE
- tristate "Userspace queueing via NETLINK"
+ tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
help
Netfilter has the ability to queue packets to user space: the
netlink device can be used to access them using this driver.
+ This option enables the old IPv4-only "ip_queue" implementation
+ which has been obsoleted by the new "nfnetlink_queue" code (see
+ CONFIG_NETFILTER_NETLINK_QUEUE).
+
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_IPTABLES
@@ -340,6 +374,17 @@ config IP_NF_MATCH_SCTP
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+config IP_NF_MATCH_DCCP
+ tristate 'DCCP protocol match support'
+ depends on IP_NF_IPTABLES
+ help
+ With this option enabled, you will be able to use the iptables
+ `dccp' match in order to match on DCCP source/destination ports
+ and DCCP flags.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
config IP_NF_MATCH_COMMENT
tristate 'comment match support'
depends on IP_NF_IPTABLES
@@ -361,6 +406,16 @@ config IP_NF_MATCH_CONNMARK
<file:Documentation/modules.txt>. The module will be called
ipt_connmark.o. If unsure, say `N'.
+config IP_NF_MATCH_CONNBYTES
+ tristate 'Connection byte/packet counter match support'
+ depends on IP_NF_CT_ACCT && IP_NF_IPTABLES
+ help
+ This option adds a `connbytes' match, which allows you to match the
+ number of bytes and/or packets for each direction within a connection.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
config IP_NF_MATCH_HASHLIMIT
tristate 'hashlimit match support'
depends on IP_NF_IPTABLES
@@ -375,6 +430,19 @@ config IP_NF_MATCH_HASHLIMIT
destination IP' or `500pps from any given source IP' with a single
IPtables rule.
+config IP_NF_MATCH_STRING
+ tristate 'string match support'
+ depends on IP_NF_IPTABLES
+ select TEXTSEARCH
+ select TEXTSEARCH_KMP
+ select TEXTSEARCH_BM
+ select TEXTSEARCH_FSM
+ help
+ This option adds a `string' match, which allows you to look for
+ pattern matchings in packets.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
# `filter', generic and specific targets
config IP_NF_FILTER
tristate "Packet filtering"
@@ -616,6 +684,20 @@ config IP_NF_TARGET_CLASSIFY
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_TARGET_TTL
+ tristate 'TTL target support'
+ depends on IP_NF_MANGLE
+ help
+ This option adds a `TTL' target, which enables the user to modify
+ the TTL value of the IP header.
+
+ While it is safe to decrement/lower the TTL, this target also enables
+ functionality to increment and set the TTL value of the IP header to
+ arbitrary values. This is EXTREMELY DANGEROUS since you can easily
+ create immortal packets that loop forever on the network.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_TARGET_CONNMARK
tristate 'CONNMARK target support'
depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
@@ -692,5 +774,11 @@ config IP_NF_ARP_MANGLE
Allows altering the ARP packet payload: source and destination
hardware and network addresses.
+config IP_NF_CONNTRACK_NETLINK
+ tristate 'Connection tracking netlink interface'
+ depends on IP_NF_CONNTRACK && NETFILTER_NETLINK
+ help
+ This option enables support for a netlink-based userspace interface
+
endmenu
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 45796d5924dd..1ba0db746817 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -9,6 +9,10 @@ iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helpe
# connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+# conntrack netlink interface
+obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
+
+
# SCTP protocol connection tracking
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
@@ -17,6 +21,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
# NAT helpers
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
@@ -38,6 +43,7 @@ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
+obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o
obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
@@ -54,11 +60,13 @@ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
@@ -78,6 +86,7 @@ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
+obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
@@ -87,3 +96,4 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
+obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ipt_NFQUEUE.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 01e1b58322a9..dc20881004bc 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
static char *conns[] = { "DATA ", "MESG ", "INDEX " };
/* This is slow, but it's simple. --RR */
-static char amanda_buffer[65536];
+static char *amanda_buffer;
static DEFINE_SPINLOCK(amanda_buffer_lock);
unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
@@ -108,6 +108,7 @@ static int help(struct sk_buff **pskb,
}
exp->expectfn = NULL;
+ exp->flags = 0;
exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
@@ -153,11 +154,25 @@ static struct ip_conntrack_helper amanda_helper = {
static void __exit fini(void)
{
ip_conntrack_helper_unregister(&amanda_helper);
+ kfree(amanda_buffer);
}
static int __init init(void)
{
- return ip_conntrack_helper_register(&amanda_helper);
+ int ret;
+
+ amanda_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!amanda_buffer)
+ return -ENOMEM;
+
+ ret = ip_conntrack_helper_register(&amanda_helper);
+ if (ret < 0) {
+ kfree(amanda_buffer);
+ return ret;
+ }
+ return 0;
+
+
}
module_init(init);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index a7f0c821a9b2..19cba16e6e1e 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -37,6 +37,7 @@
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/moduleparam.h>
+#include <linux/notifier.h>
/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
registrations, conntrack timers*/
@@ -49,7 +50,7 @@
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/listhelp.h>
-#define IP_CONNTRACK_VERSION "2.1"
+#define IP_CONNTRACK_VERSION "2.3"
#if 0
#define DEBUGP printk
@@ -69,22 +70,81 @@ static LIST_HEAD(helpers);
unsigned int ip_conntrack_htable_size = 0;
int ip_conntrack_max;
struct list_head *ip_conntrack_hash;
-static kmem_cache_t *ip_conntrack_cachep;
-static kmem_cache_t *ip_conntrack_expect_cachep;
+static kmem_cache_t *ip_conntrack_cachep __read_mostly;
+static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly;
struct ip_conntrack ip_conntrack_untracked;
unsigned int ip_ct_log_invalid;
static LIST_HEAD(unconfirmed);
static int ip_conntrack_vmalloc;
-DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+static unsigned int ip_conntrack_next_id = 1;
+static unsigned int ip_conntrack_expect_next_id = 1;
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+struct notifier_block *ip_conntrack_chain;
+struct notifier_block *ip_conntrack_expect_chain;
+
+DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
-void
-ip_conntrack_put(struct ip_conntrack *ct)
+/* deliver cached events and clear cache entry - must be called with locally
+ * disabled softirqs */
+static inline void
+__ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
{
- IP_NF_ASSERT(ct);
- nf_conntrack_put(&ct->ct_general);
+ 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,
+ ecache->ct);
+ ecache->events = 0;
+ ip_conntrack_put(ecache->ct);
+ ecache->ct = NULL;
}
+/* Deliver all cached events for a particular conntrack. This is called
+ * by code prior to async packet handling or freeing the skb */
+void ip_ct_deliver_cached_events(const struct ip_conntrack *ct)
+{
+ struct ip_conntrack_ecache *ecache;
+
+ local_bh_disable();
+ ecache = &__get_cpu_var(ip_conntrack_ecache);
+ if (ecache->ct == ct)
+ __ip_ct_deliver_cached_events(ecache);
+ local_bh_enable();
+}
+
+void __ip_ct_event_cache_init(struct ip_conntrack *ct)
+{
+ struct ip_conntrack_ecache *ecache;
+
+ /* take care of delivering potentially old events */
+ ecache = &__get_cpu_var(ip_conntrack_ecache);
+ BUG_ON(ecache->ct == ct);
+ if (ecache->ct)
+ __ip_ct_deliver_cached_events(ecache);
+ /* initialize for this conntrack/packet */
+ ecache->ct = ct;
+ nf_conntrack_get(&ct->ct_general);
+}
+
+/* flush the event cache - touches other CPU's data and must not be called while
+ * packets are still passing through the code */
+static void ip_ct_event_cache_flush(void)
+{
+ struct ip_conntrack_ecache *ecache;
+ int cpu;
+
+ for_each_cpu(cpu) {
+ ecache = &per_cpu(ip_conntrack_ecache, cpu);
+ if (ecache->ct)
+ ip_conntrack_put(ecache->ct);
+ }
+}
+#else
+static inline void ip_ct_event_cache_flush(void) {}
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+
+DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+
static int ip_conntrack_hash_rnd_initted;
static unsigned int ip_conntrack_hash_rnd;
@@ -137,13 +197,14 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
/* ip_conntrack_expect helper functions */
-static void unlink_expect(struct ip_conntrack_expect *exp)
+void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
{
ASSERT_WRITE_LOCK(&ip_conntrack_lock);
IP_NF_ASSERT(!timer_pending(&exp->timeout));
list_del(&exp->list);
CONNTRACK_STAT_INC(expect_delete);
exp->master->expecting--;
+ ip_conntrack_expect_put(exp);
}
static void expectation_timed_out(unsigned long ul_expect)
@@ -151,11 +212,38 @@ static void expectation_timed_out(unsigned long ul_expect)
struct ip_conntrack_expect *exp = (void *)ul_expect;
write_lock_bh(&ip_conntrack_lock);
- unlink_expect(exp);
+ ip_ct_unlink_expect(exp);
write_unlock_bh(&ip_conntrack_lock);
ip_conntrack_expect_put(exp);
}
+struct ip_conntrack_expect *
+__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
+{
+ struct ip_conntrack_expect *i;
+
+ list_for_each_entry(i, &ip_conntrack_expect_list, list) {
+ if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
+ atomic_inc(&i->use);
+ return i;
+ }
+ }
+ return NULL;
+}
+
+/* Just find a expectation corresponding to a tuple. */
+struct ip_conntrack_expect *
+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
+{
+ struct ip_conntrack_expect *i;
+
+ read_lock_bh(&ip_conntrack_lock);
+ i = __ip_conntrack_expect_find(tuple);
+ read_unlock_bh(&ip_conntrack_lock);
+
+ return i;
+}
+
/* If an expectation for this connection is found, it gets delete from
* global list then returned. */
static struct ip_conntrack_expect *
@@ -170,17 +258,21 @@ find_expectation(const struct ip_conntrack_tuple *tuple)
master ct never got confirmed, we'd hold a reference to it
and weird things would happen to future packets). */
if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
- && is_confirmed(i->master)
- && del_timer(&i->timeout)) {
- unlink_expect(i);
- return i;
+ && is_confirmed(i->master)) {
+ if (i->flags & IP_CT_EXPECT_PERMANENT) {
+ atomic_inc(&i->use);
+ return i;
+ } else if (del_timer(&i->timeout)) {
+ ip_ct_unlink_expect(i);
+ return i;
+ }
}
}
return NULL;
}
/* delete all expectations for this conntrack */
-static void remove_expectations(struct ip_conntrack *ct)
+void ip_ct_remove_expectations(struct ip_conntrack *ct)
{
struct ip_conntrack_expect *i, *tmp;
@@ -190,7 +282,7 @@ static void remove_expectations(struct ip_conntrack *ct)
list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) {
if (i->master == ct && del_timer(&i->timeout)) {
- unlink_expect(i);
+ ip_ct_unlink_expect(i);
ip_conntrack_expect_put(i);
}
}
@@ -210,7 +302,7 @@ clean_from_lists(struct ip_conntrack *ct)
LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
/* Destroy all pending expectations */
- remove_expectations(ct);
+ ip_ct_remove_expectations(ct);
}
static void
@@ -223,10 +315,13 @@ destroy_conntrack(struct nf_conntrack *nfct)
IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
IP_NF_ASSERT(!timer_pending(&ct->timeout));
+ ip_conntrack_event(IPCT_DESTROY, ct);
+ set_bit(IPS_DYING_BIT, &ct->status);
+
/* To make sure we don't get any weird locking issues here:
* destroy_conntrack() MUST NOT be called with a write lock
* to ip_conntrack_lock!!! -HW */
- proto = ip_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+ proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
if (proto && proto->destroy)
proto->destroy(ct);
@@ -238,7 +333,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
* except TFTP can create an expectation on the first packet,
* before connection is in the list, so we need to clean here,
* too. */
- remove_expectations(ct);
+ ip_ct_remove_expectations(ct);
/* We overload first tuple to link into unconfirmed list. */
if (!is_confirmed(ct)) {
@@ -253,8 +348,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
ip_conntrack_put(ct->master);
DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
- kmem_cache_free(ip_conntrack_cachep, ct);
- atomic_dec(&ip_conntrack_count);
+ ip_conntrack_free(ct);
}
static void death_by_timeout(unsigned long ul_conntrack)
@@ -280,7 +374,7 @@ conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i,
&& ip_ct_tuple_equal(tuple, &i->tuple);
}
-static struct ip_conntrack_tuple_hash *
+struct ip_conntrack_tuple_hash *
__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
const struct ip_conntrack *ignored_conntrack)
{
@@ -315,6 +409,29 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
return h;
}
+static void __ip_conntrack_hash_insert(struct ip_conntrack *ct,
+ unsigned int hash,
+ unsigned int repl_hash)
+{
+ ct->id = ++ip_conntrack_next_id;
+ list_prepend(&ip_conntrack_hash[hash],
+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ list_prepend(&ip_conntrack_hash[repl_hash],
+ &ct->tuplehash[IP_CT_DIR_REPLY].list);
+}
+
+void ip_conntrack_hash_insert(struct ip_conntrack *ct)
+{
+ unsigned int hash, repl_hash;
+
+ hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+
+ write_lock_bh(&ip_conntrack_lock);
+ __ip_conntrack_hash_insert(ct, hash, repl_hash);
+ write_unlock_bh(&ip_conntrack_lock);
+}
+
/* Confirm a connection given skb; places it in hash table */
int
__ip_conntrack_confirm(struct sk_buff **pskb)
@@ -361,10 +478,7 @@ __ip_conntrack_confirm(struct sk_buff **pskb)
/* Remove from unconfirmed list */
list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
- list_prepend(&ip_conntrack_hash[hash],
- &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- list_prepend(&ip_conntrack_hash[repl_hash],
- &ct->tuplehash[IP_CT_DIR_REPLY]);
+ __ip_conntrack_hash_insert(ct, hash, repl_hash);
/* Timer relative to confirmation time, not original
setting time, otherwise we'd get timer wrap in
weird delay cases. */
@@ -374,6 +488,16 @@ __ip_conntrack_confirm(struct sk_buff **pskb)
set_bit(IPS_CONFIRMED_BIT, &ct->status);
CONNTRACK_STAT_INC(insert);
write_unlock_bh(&ip_conntrack_lock);
+ if (ct->helper)
+ ip_conntrack_event_cache(IPCT_HELPER, *pskb);
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+ if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
+ test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
+ ip_conntrack_event_cache(IPCT_NATINFO, *pskb);
+#endif
+ ip_conntrack_event_cache(master_ct(ct) ?
+ IPCT_RELATED : IPCT_NEW, *pskb);
+
return NF_ACCEPT;
}
@@ -438,34 +562,84 @@ static inline int helper_cmp(const struct ip_conntrack_helper *i,
return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
}
-static struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
+static struct ip_conntrack_helper *
+__ip_conntrack_helper_find( const struct ip_conntrack_tuple *tuple)
{
return LIST_FIND(&helpers, helper_cmp,
struct ip_conntrack_helper *,
tuple);
}
-/* Allocate a new conntrack: we return -ENOMEM if classification
- failed due to stress. Otherwise it really is unclassifiable. */
-static struct ip_conntrack_tuple_hash *
-init_conntrack(const struct ip_conntrack_tuple *tuple,
- struct ip_conntrack_protocol *protocol,
- struct sk_buff *skb)
+struct ip_conntrack_helper *
+ip_conntrack_helper_find_get( const struct ip_conntrack_tuple *tuple)
+{
+ struct ip_conntrack_helper *helper;
+
+ /* need ip_conntrack_lock to assure that helper exists until
+ * try_module_get() is called */
+ read_lock_bh(&ip_conntrack_lock);
+
+ helper = __ip_conntrack_helper_find(tuple);
+ if (helper) {
+ /* need to increase module usage count to assure helper will
+ * not go away while the caller is e.g. busy putting a
+ * conntrack in the hash that uses the helper */
+ if (!try_module_get(helper->me))
+ helper = NULL;
+ }
+
+ read_unlock_bh(&ip_conntrack_lock);
+
+ return helper;
+}
+
+void ip_conntrack_helper_put(struct ip_conntrack_helper *helper)
+{
+ module_put(helper->me);
+}
+
+struct ip_conntrack_protocol *
+__ip_conntrack_proto_find(u_int8_t protocol)
+{
+ return ip_ct_protos[protocol];
+}
+
+/* this is guaranteed to always return a valid protocol helper, since
+ * it falls back to generic_protocol */
+struct ip_conntrack_protocol *
+ip_conntrack_proto_find_get(u_int8_t protocol)
+{
+ struct ip_conntrack_protocol *p;
+
+ preempt_disable();
+ p = __ip_conntrack_proto_find(protocol);
+ if (p) {
+ if (!try_module_get(p->me))
+ p = &ip_conntrack_generic_protocol;
+ }
+ preempt_enable();
+
+ return p;
+}
+
+void ip_conntrack_proto_put(struct ip_conntrack_protocol *p)
+{
+ module_put(p->me);
+}
+
+struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *orig,
+ struct ip_conntrack_tuple *repl)
{
struct ip_conntrack *conntrack;
- struct ip_conntrack_tuple repl_tuple;
- size_t hash;
- struct ip_conntrack_expect *exp;
if (!ip_conntrack_hash_rnd_initted) {
get_random_bytes(&ip_conntrack_hash_rnd, 4);
ip_conntrack_hash_rnd_initted = 1;
}
- hash = hash_conntrack(tuple);
-
if (ip_conntrack_max
&& atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
+ unsigned int hash = hash_conntrack(orig);
/* Try dropping from this hash chain. */
if (!early_drop(&ip_conntrack_hash[hash])) {
if (net_ratelimit())
@@ -476,11 +650,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
}
}
- if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
- DEBUGP("Can't invert tuple.\n");
- return NULL;
- }
-
conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
if (!conntrack) {
DEBUGP("Can't allocate conntrack.\n");
@@ -490,17 +659,50 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
memset(conntrack, 0, sizeof(*conntrack));
atomic_set(&conntrack->ct_general.use, 1);
conntrack->ct_general.destroy = destroy_conntrack;
- conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
- conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
- if (!protocol->new(conntrack, skb)) {
- kmem_cache_free(ip_conntrack_cachep, conntrack);
- return NULL;
- }
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
+ conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
/* Don't set timer yet: wait for confirmation */
init_timer(&conntrack->timeout);
conntrack->timeout.data = (unsigned long)conntrack;
conntrack->timeout.function = death_by_timeout;
+ atomic_inc(&ip_conntrack_count);
+
+ return conntrack;
+}
+
+void
+ip_conntrack_free(struct ip_conntrack *conntrack)
+{
+ atomic_dec(&ip_conntrack_count);
+ kmem_cache_free(ip_conntrack_cachep, conntrack);
+}
+
+/* Allocate a new conntrack: we return -ENOMEM if classification
+ * failed due to stress. Otherwise it really is unclassifiable */
+static struct ip_conntrack_tuple_hash *
+init_conntrack(struct ip_conntrack_tuple *tuple,
+ struct ip_conntrack_protocol *protocol,
+ struct sk_buff *skb)
+{
+ struct ip_conntrack *conntrack;
+ struct ip_conntrack_tuple repl_tuple;
+ struct ip_conntrack_expect *exp;
+
+ if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
+ DEBUGP("Can't invert tuple.\n");
+ return NULL;
+ }
+
+ conntrack = ip_conntrack_alloc(tuple, &repl_tuple);
+ if (conntrack == NULL || IS_ERR(conntrack))
+ return (struct ip_conntrack_tuple_hash *)conntrack;
+
+ if (!protocol->new(conntrack, skb)) {
+ ip_conntrack_free(conntrack);
+ return NULL;
+ }
+
write_lock_bh(&ip_conntrack_lock);
exp = find_expectation(tuple);
@@ -521,7 +723,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
nf_conntrack_get(&conntrack->master->ct_general);
CONNTRACK_STAT_INC(expect_new);
} else {
- conntrack->helper = ip_ct_find_helper(&repl_tuple);
+ conntrack->helper = __ip_conntrack_helper_find(&repl_tuple);
CONNTRACK_STAT_INC(new);
}
@@ -529,7 +731,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
/* Overload tuple linked list to put us in unconfirmed list. */
list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
- atomic_inc(&ip_conntrack_count);
write_unlock_bh(&ip_conntrack_lock);
if (exp) {
@@ -607,7 +808,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
struct ip_conntrack_protocol *proto;
- int set_reply;
+ int set_reply = 0;
int ret;
/* Previously seen (loopback or untracked)? Ignore. */
@@ -625,9 +826,6 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
return NF_DROP;
}
- /* FIXME: Do this right please. --RR */
- (*pskb)->nfcache |= NFC_UNKNOWN;
-
/* Doesn't cover locally-generated broadcast, so not worth it. */
#if 0
/* Ignore broadcast: no `connection'. */
@@ -643,7 +841,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
}
#endif
- proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
+ proto = __ip_conntrack_proto_find((*pskb)->nh.iph->protocol);
/* It may be an special packet, error, unclean...
* inverse of the return code tells to the netfilter
@@ -679,8 +877,8 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
return -ret;
}
- if (set_reply)
- set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
+ if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
+ ip_conntrack_event_cache(IPCT_STATUS, *pskb);
return ret;
}
@@ -689,7 +887,7 @@ int invert_tuplepr(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig)
{
return ip_ct_invert_tuple(inverse, orig,
- ip_ct_find_proto(orig->dst.protonum));
+ __ip_conntrack_proto_find(orig->dst.protonum));
}
/* Would two expected things clash? */
@@ -725,7 +923,7 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
/* choose the the oldest expectation to evict */
list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
if (expect_matches(i, exp) && del_timer(&i->timeout)) {
- unlink_expect(i);
+ ip_ct_unlink_expect(i);
write_unlock_bh(&ip_conntrack_lock);
ip_conntrack_expect_put(i);
return;
@@ -734,6 +932,9 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
write_unlock_bh(&ip_conntrack_lock);
}
+/* We don't increase the master conntrack refcount for non-fulfilled
+ * conntracks. During the conntrack destruction, the expectations are
+ * always killed before the conntrack itself */
struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
{
struct ip_conntrack_expect *new;
@@ -744,17 +945,14 @@ struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
return NULL;
}
new->master = me;
- atomic_inc(&new->master->ct_general.use);
atomic_set(&new->use, 1);
return new;
}
void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
{
- if (atomic_dec_and_test(&exp->use)) {
- ip_conntrack_put(exp->master);
+ if (atomic_dec_and_test(&exp->use))
kmem_cache_free(ip_conntrack_expect_cachep, exp);
- }
}
static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
@@ -769,6 +967,8 @@ static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
add_timer(&exp->timeout);
+ exp->id = ++ip_conntrack_expect_next_id;
+ atomic_inc(&exp->use);
CONNTRACK_STAT_INC(expect_create);
}
@@ -780,7 +980,7 @@ static void evict_oldest_expect(struct ip_conntrack *master)
list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
if (i->master == master) {
if (del_timer(&i->timeout)) {
- unlink_expect(i);
+ ip_ct_unlink_expect(i);
ip_conntrack_expect_put(i);
}
break;
@@ -827,6 +1027,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect)
evict_oldest_expect(expect->master);
ip_conntrack_expect_insert(expect);
+ ip_conntrack_expect_event(IPEXP_NEW, expect);
ret = 0;
out:
write_unlock_bh(&ip_conntrack_lock);
@@ -847,7 +1048,7 @@ void ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
if (!conntrack->master && conntrack->expecting == 0)
- conntrack->helper = ip_ct_find_helper(newreply);
+ conntrack->helper = __ip_conntrack_helper_find(newreply);
write_unlock_bh(&ip_conntrack_lock);
}
@@ -861,11 +1062,26 @@ int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
return 0;
}
+struct ip_conntrack_helper *
+__ip_conntrack_helper_find_byname(const char *name)
+{
+ struct ip_conntrack_helper *h;
+
+ list_for_each_entry(h, &helpers, list) {
+ if (!strcmp(h->name, name))
+ return h;
+ }
+
+ return NULL;
+}
+
static inline int unhelp(struct ip_conntrack_tuple_hash *i,
const struct ip_conntrack_helper *me)
{
- if (tuplehash_to_ctrack(i)->helper == me)
+ if (tuplehash_to_ctrack(i)->helper == me) {
+ ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i));
tuplehash_to_ctrack(i)->helper = NULL;
+ }
return 0;
}
@@ -881,7 +1097,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
/* Get rid of expectations */
list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
if (exp->master->helper == me && del_timer(&exp->timeout)) {
- unlink_expect(exp);
+ ip_ct_unlink_expect(exp);
ip_conntrack_expect_put(exp);
}
}
@@ -927,12 +1143,46 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct,
if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
add_timer(&ct->timeout);
+ ip_conntrack_event_cache(IPCT_REFRESH, skb);
}
ct_add_counters(ct, ctinfo, skb);
write_unlock_bh(&ip_conntrack_lock);
}
}
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
+ * in ip_conntrack_core, since we don't want the protocols to autoload
+ * or depend on ctnetlink */
+int ip_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple)
+{
+ NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
+ &tuple->src.u.tcp.port);
+ NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
+ &tuple->dst.u.tcp.port);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+int ip_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+ struct ip_conntrack_tuple *t)
+{
+ if (!tb[CTA_PROTO_SRC_PORT-1] || !tb[CTA_PROTO_DST_PORT-1])
+ return -EINVAL;
+
+ t->src.u.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
+ t->dst.u.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+
+ return 0;
+}
+#endif
+
/* Returns new sk_buff, or NULL */
struct sk_buff *
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
@@ -943,10 +1193,8 @@ ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
skb = ip_defrag(skb, user);
local_bh_enable();
- if (skb) {
+ if (skb)
ip_send_check(skb->nh.iph);
- skb->nfcache |= NFC_ALTERED;
- }
return skb;
}
@@ -1096,16 +1344,14 @@ static void free_conntrack_hash(void)
* ip_conntrack_htable_size));
}
-/* Mishearing the voices in his head, our hero wonders how he's
- supposed to kill the mall. */
-void ip_conntrack_cleanup(void)
+void ip_conntrack_flush()
{
- ip_ct_attach = NULL;
/* This makes sure all current packets have passed through
netfilter framework. Roll on, two-stage module
delete... */
synchronize_net();
-
+
+ ip_ct_event_cache_flush();
i_see_dead_people:
ip_ct_iterate_cleanup(kill_all, NULL);
if (atomic_read(&ip_conntrack_count) != 0) {
@@ -1115,7 +1361,14 @@ void ip_conntrack_cleanup(void)
/* wait until all references to ip_conntrack_untracked are dropped */
while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1)
schedule();
+}
+/* Mishearing the voices in his head, our hero wonders how he's
+ supposed to kill the mall. */
+void ip_conntrack_cleanup(void)
+{
+ ip_ct_attach = NULL;
+ ip_conntrack_flush();
kmem_cache_destroy(ip_conntrack_cachep);
kmem_cache_destroy(ip_conntrack_expect_cachep);
free_conntrack_hash();
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 7a3b773be3f9..1b79ec36085f 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -25,8 +25,7 @@ MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
MODULE_DESCRIPTION("ftp connection tracking helper");
/* This is slow, but it's simple. --RR */
-static char ftp_buffer[65536];
-
+static char *ftp_buffer;
static DEFINE_SPINLOCK(ip_ftp_lock);
#define MAX_PORTS 8
@@ -262,7 +261,8 @@ static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
}
/* We don't update if it's older than what we have. */
-static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir)
+static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir,
+ struct sk_buff *skb)
{
unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
@@ -276,10 +276,13 @@ static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir)
oldest = i;
}
- if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER)
+ if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
- else if (oldest != NUM_SEQ_TO_REMEMBER)
+ ip_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
+ } else if (oldest != NUM_SEQ_TO_REMEMBER) {
info->seq_aft_nl[dir][oldest] = nl_seq;
+ ip_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
+ }
}
static int help(struct sk_buff **pskb,
@@ -418,6 +421,7 @@ static int help(struct sk_buff **pskb,
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
exp->expectfn = NULL;
+ exp->flags = 0;
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
@@ -439,7 +443,7 @@ out_update_nl:
/* Now if this ends in \n, update ftp info. Seq may have been
* adjusted by NAT code. */
if (ends_in_nl)
- update_nl_seq(seq, ct_ftp_info,dir);
+ update_nl_seq(seq, ct_ftp_info,dir, *pskb);
out:
spin_unlock_bh(&ip_ftp_lock);
return ret;
@@ -457,6 +461,8 @@ static void fini(void)
ports[i]);
ip_conntrack_helper_unregister(&ftp[i]);
}
+
+ kfree(ftp_buffer);
}
static int __init init(void)
@@ -464,6 +470,10 @@ static int __init init(void)
int i, ret;
char *tmpname;
+ ftp_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!ftp_buffer)
+ return -ENOMEM;
+
if (ports_c == 0)
ports[ports_c++] = FTP_PORT;
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 4a28f297d502..d7a8a98c05e1 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -39,7 +39,7 @@ static int ports_c;
static int max_dcc_channels = 8;
static unsigned int dcc_timeout = 300;
/* This is slow, but it's simple. --RR */
-static char irc_buffer[65536];
+static char *irc_buffer;
static DEFINE_SPINLOCK(irc_buffer_lock);
unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
@@ -221,6 +221,7 @@ static int help(struct sk_buff **pskb,
{ { 0, { 0 } },
{ 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
exp->expectfn = NULL;
+ exp->flags = 0;
if (ip_nat_irc_hook)
ret = ip_nat_irc_hook(pskb, ctinfo,
addr_beg_p - ib_ptr,
@@ -257,6 +258,10 @@ static int __init init(void)
printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
return -EBUSY;
}
+
+ irc_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!irc_buffer)
+ return -ENOMEM;
/* If no port given, default to standard irc port */
if (ports_c == 0)
@@ -304,6 +309,7 @@ static void fini(void)
ports[i]);
ip_conntrack_helper_unregister(&irc_helpers[i]);
}
+ kfree(irc_buffer);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
new file mode 100644
index 000000000000..bb7246683b74
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -0,0 +1,147 @@
+/*
+ * NetBIOS name service broadcast connection tracking helper
+ *
+ * (c) 2005 Patrick McHardy <kaber@trash.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 helper tracks locally originating NetBIOS name service
+ * requests by issuing permanent expectations (valid until
+ * timing out) matching all reply connections from the
+ * destination network. The only NetBIOS specific thing is
+ * actually the port number.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/route.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
+MODULE_LICENSE("GPL");
+
+static unsigned int timeout = 3;
+module_param(timeout, int, 0600);
+MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
+
+static int help(struct sk_buff **pskb,
+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+ struct ip_conntrack_expect *exp;
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct udphdr _uh, *uh;
+ struct rtable *rt = (struct rtable *)(*pskb)->dst;
+ struct in_device *in_dev;
+ u_int32_t mask = 0;
+
+ /* we're only interested in locally generated packets */
+ if ((*pskb)->sk == NULL)
+ goto out;
+ if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
+ goto out;
+ if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+ goto out;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get(rt->u.dst.dev);
+ if (in_dev != NULL) {
+ for_primary_ifa(in_dev) {
+ if (ifa->ifa_broadcast == iph->daddr) {
+ mask = ifa->ifa_mask;
+ break;
+ }
+ } endfor_ifa(in_dev);
+ }
+ rcu_read_unlock();
+
+ if (mask == 0)
+ goto out;
+
+ uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh);
+ BUG_ON(uh == NULL);
+
+ exp = ip_conntrack_expect_alloc(ct);
+ if (exp == NULL)
+ goto out;
+ memset(&exp->tuple, 0, sizeof(exp->tuple));
+ exp->tuple.src.ip = iph->daddr & mask;
+ exp->tuple.dst.ip = iph->saddr;
+ exp->tuple.dst.u.udp.port = uh->source;
+ exp->tuple.dst.protonum = IPPROTO_UDP;
+
+ memset(&exp->mask, 0, sizeof(exp->mask));
+ exp->mask.src.ip = mask;
+ exp->mask.dst.ip = 0xFFFFFFFF;
+ exp->mask.dst.u.udp.port = 0xFFFF;
+ exp->mask.dst.protonum = 0xFF;
+
+ exp->expectfn = NULL;
+ exp->flags = IP_CT_EXPECT_PERMANENT;
+
+ ip_conntrack_expect_related(exp);
+ ip_conntrack_expect_put(exp);
+
+ ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ);
+out:
+ return NF_ACCEPT;
+}
+
+static struct ip_conntrack_helper helper = {
+ .name = "netbios-ns",
+ .tuple = {
+ .src = {
+ .u = {
+ .udp = {
+ .port = __constant_htons(137),
+ }
+ }
+ },
+ .dst = {
+ .protonum = IPPROTO_UDP,
+ },
+ },
+ .mask = {
+ .src = {
+ .u = {
+ .udp = {
+ .port = 0xFFFF,
+ }
+ }
+ },
+ .dst = {
+ .protonum = 0xFF,
+ },
+ },
+ .max_expected = 1,
+ .me = THIS_MODULE,
+ .help = help,
+};
+
+static int __init init(void)
+{
+ helper.timeout = timeout;
+ return ip_conntrack_helper_register(&helper);
+}
+
+static void __exit fini(void)
+{
+ ip_conntrack_helper_unregister(&helper);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
new file mode 100644
index 000000000000..15aef3564742
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -0,0 +1,1584 @@
+/* Connection tracking via netlink socket. Allows for user space
+ * protocol helpers and general trouble making from userspace.
+ *
+ * (C) 2001 by Jay Schulist <jschlst@samba.org>
+ * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2003 by Patrick Mchardy <kaber@trash.net>
+ * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ *
+ * I've reworked this stuff to use attributes instead of conntrack
+ * structures. 5.44 am. I need more tea. --pablo 05/07/11.
+ *
+ * Initial connection tracking via netlink development funded and
+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
+ *
+ * Further development of this code funded by Astaro AG (http://www.astaro.com)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/netlink.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <linux/rtnetlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/ip_nat_protocol.h>
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+MODULE_LICENSE("GPL");
+
+static char __initdata version[] = "0.90";
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+
+static inline int
+ctnetlink_dump_tuples_proto(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple)
+{
+ struct ip_conntrack_protocol *proto;
+
+ NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
+
+ proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+ if (proto && proto->tuple_to_nfattr)
+ return proto->tuple_to_nfattr(skb, tuple);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple)
+{
+ struct nfattr *nest_parms;
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+ NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
+ NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
+ NFA_NEST_END(skb, nest_parms);
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
+ ctnetlink_dump_tuples_proto(skb, tuple);
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ u_int32_t status = htonl((u_int32_t) ct->status);
+ NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_timeout(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ long timeout_l = ct->timeout.expires - jiffies;
+ u_int32_t timeout;
+
+ if (timeout_l < 0)
+ timeout = 0;
+ else
+ timeout = htonl(timeout_l / HZ);
+
+ NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ struct ip_conntrack_protocol *proto = ip_conntrack_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+
+ struct nfattr *nest_proto;
+ int ret;
+
+ if (!proto || !proto->to_nfattr)
+ return 0;
+
+ nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
+
+ ret = proto->to_nfattr(skb, nest_proto, ct);
+
+ ip_conntrack_proto_put(proto);
+
+ NFA_NEST_END(skb, nest_proto);
+
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ struct nfattr *nest_helper;
+
+ if (!ct->helper)
+ return 0;
+
+ nest_helper = NFA_NEST(skb, CTA_HELP);
+ NFA_PUT(skb, CTA_HELP_NAME, CTA_HELP_MAXNAMESIZE, &ct->helper->name);
+
+ if (ct->helper->to_nfattr)
+ ct->helper->to_nfattr(skb, ct);
+
+ NFA_NEST_END(skb, nest_helper);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+#ifdef CONFIG_IP_NF_CT_ACCT
+static inline int
+ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
+ enum ip_conntrack_dir dir)
+{
+ enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
+ struct nfattr *nest_count = NFA_NEST(skb, type);
+ u_int64_t tmp;
+
+ tmp = cpu_to_be64(ct->counters[dir].packets);
+ NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp);
+
+ tmp = cpu_to_be64(ct->counters[dir].bytes);
+ NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp);
+
+ NFA_NEST_END(skb, nest_count);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+#else
+#define ctnetlink_dump_counters(a, b, c) (0)
+#endif
+
+#ifdef CONFIG_IP_NF_CONNTRACK_MARK
+static inline int
+ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ u_int32_t mark = htonl(ct->mark);
+
+ NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+#else
+#define ctnetlink_dump_mark(a, b) (0)
+#endif
+
+static inline int
+ctnetlink_dump_id(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ u_int32_t id = htonl(ct->id);
+ NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
+{
+ unsigned int use = htonl(atomic_read(&ct->ct_general.use));
+
+ NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+#define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
+
+static int
+ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+ int event, int nowait,
+ const struct ip_conntrack *ct)
+{
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ struct nfattr *nest_parms;
+ unsigned char *b;
+
+ b = skb->tail;
+
+ event |= NFNL_SUBSYS_CTNETLINK << 8;
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
+ nfmsg->nfgen_family = AF_INET;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
+ if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
+ goto nfattr_failure;
+ NFA_NEST_END(skb, nest_parms);
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
+ if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
+ goto nfattr_failure;
+ NFA_NEST_END(skb, nest_parms);
+
+ if (ctnetlink_dump_status(skb, ct) < 0 ||
+ ctnetlink_dump_timeout(skb, ct) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
+ ctnetlink_dump_protoinfo(skb, ct) < 0 ||
+ ctnetlink_dump_helpinfo(skb, ct) < 0 ||
+ ctnetlink_dump_mark(skb, ct) < 0 ||
+ ctnetlink_dump_id(skb, ct) < 0 ||
+ ctnetlink_dump_use(skb, ct) < 0)
+ goto nfattr_failure;
+
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+nfattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+static int ctnetlink_conntrack_event(struct notifier_block *this,
+ unsigned long events, void *ptr)
+{
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ struct nfattr *nest_parms;
+ struct ip_conntrack *ct = (struct ip_conntrack *)ptr;
+ struct sk_buff *skb;
+ unsigned int type;
+ unsigned char *b;
+ unsigned int flags = 0, group;
+
+ /* ignore our fake conntrack entry */
+ if (ct == &ip_conntrack_untracked)
+ return NOTIFY_DONE;
+
+ if (events & IPCT_DESTROY) {
+ type = IPCTNL_MSG_CT_DELETE;
+ group = NFNLGRP_CONNTRACK_DESTROY;
+ goto alloc_skb;
+ }
+ if (events & (IPCT_NEW | IPCT_RELATED)) {
+ type = IPCTNL_MSG_CT_NEW;
+ flags = NLM_F_CREATE|NLM_F_EXCL;
+ /* dump everything */
+ events = ~0UL;
+ group = NFNLGRP_CONNTRACK_NEW;
+ goto alloc_skb;
+ }
+ if (events & (IPCT_STATUS |
+ IPCT_PROTOINFO |
+ IPCT_HELPER |
+ IPCT_HELPINFO |
+ IPCT_NATINFO)) {
+ type = IPCTNL_MSG_CT_NEW;
+ group = NFNLGRP_CONNTRACK_UPDATE;
+ goto alloc_skb;
+ }
+
+ return NOTIFY_DONE;
+
+alloc_skb:
+ /* FIXME: Check if there are any listeners before, don't hurt performance */
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return NOTIFY_DONE;
+
+ b = skb->tail;
+
+ type |= NFNL_SUBSYS_CTNETLINK << 8;
+ nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = flags;
+ nfmsg->nfgen_family = AF_INET;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
+ if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
+ goto nfattr_failure;
+ NFA_NEST_END(skb, nest_parms);
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
+ if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
+ goto nfattr_failure;
+ NFA_NEST_END(skb, nest_parms);
+
+ /* NAT stuff is now a status flag */
+ if ((events & IPCT_STATUS || events & IPCT_NATINFO)
+ && ctnetlink_dump_status(skb, ct) < 0)
+ goto nfattr_failure;
+ if (events & IPCT_REFRESH
+ && ctnetlink_dump_timeout(skb, ct) < 0)
+ goto nfattr_failure;
+ if (events & IPCT_PROTOINFO
+ && ctnetlink_dump_protoinfo(skb, ct) < 0)
+ goto nfattr_failure;
+ if (events & IPCT_HELPINFO
+ && ctnetlink_dump_helpinfo(skb, ct) < 0)
+ goto nfattr_failure;
+
+ if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+ goto nfattr_failure;
+
+ nlh->nlmsg_len = skb->tail - b;
+ nfnetlink_send(skb, 0, group, 0);
+ return NOTIFY_DONE;
+
+nlmsg_failure:
+nfattr_failure:
+ kfree_skb(skb);
+ return NOTIFY_DONE;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+
+static int ctnetlink_done(struct netlink_callback *cb)
+{
+ DEBUGP("entered %s\n", __FUNCTION__);
+ return 0;
+}
+
+static int
+ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct ip_conntrack *ct = NULL;
+ struct ip_conntrack_tuple_hash *h;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[1];
+
+ DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__,
+ cb->args[0], *id);
+
+ read_lock_bh(&ip_conntrack_lock);
+ for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) {
+ list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
+ h = (struct ip_conntrack_tuple_hash *) i;
+ if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+ continue;
+ ct = tuplehash_to_ctrack(h);
+ if (ct->id <= *id)
+ continue;
+ if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ IPCTNL_MSG_CT_NEW,
+ 1, ct) < 0)
+ goto out;
+ *id = ct->id;
+ }
+ }
+out:
+ read_unlock_bh(&ip_conntrack_lock);
+
+ DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
+
+ return skb->len;
+}
+
+#ifdef CONFIG_IP_NF_CT_ACCT
+static int
+ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct ip_conntrack *ct = NULL;
+ struct ip_conntrack_tuple_hash *h;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[1];
+
+ DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__,
+ cb->args[0], *id);
+
+ write_lock_bh(&ip_conntrack_lock);
+ for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) {
+ list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
+ h = (struct ip_conntrack_tuple_hash *) i;
+ if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+ continue;
+ ct = tuplehash_to_ctrack(h);
+ if (ct->id <= *id)
+ continue;
+ if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ IPCTNL_MSG_CT_NEW,
+ 1, ct) < 0)
+ goto out;
+ *id = ct->id;
+
+ memset(&ct->counters, 0, sizeof(ct->counters));
+ }
+ }
+out:
+ write_unlock_bh(&ip_conntrack_lock);
+
+ DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
+
+ return skb->len;
+}
+#endif
+
+static const int cta_min_ip[CTA_IP_MAX] = {
+ [CTA_IP_V4_SRC-1] = sizeof(u_int32_t),
+ [CTA_IP_V4_DST-1] = sizeof(u_int32_t),
+};
+
+static inline int
+ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
+{
+ struct nfattr *tb[CTA_IP_MAX];
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+
+ if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0)
+ goto nfattr_failure;
+
+ if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
+ return -EINVAL;
+
+ if (!tb[CTA_IP_V4_SRC-1])
+ return -EINVAL;
+ tuple->src.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+
+ if (!tb[CTA_IP_V4_DST-1])
+ return -EINVAL;
+ tuple->dst.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+
+ DEBUGP("leaving\n");
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static const int cta_min_proto[CTA_PROTO_MAX] = {
+ [CTA_PROTO_NUM-1] = sizeof(u_int16_t),
+ [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
+ [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t),
+ [CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t),
+ [CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t),
+ [CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t),
+};
+
+static inline int
+ctnetlink_parse_tuple_proto(struct nfattr *attr,
+ struct ip_conntrack_tuple *tuple)
+{
+ struct nfattr *tb[CTA_PROTO_MAX];
+ struct ip_conntrack_protocol *proto;
+ int ret = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0)
+ goto nfattr_failure;
+
+ if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+ return -EINVAL;
+
+ if (!tb[CTA_PROTO_NUM-1])
+ return -EINVAL;
+ tuple->dst.protonum = *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+
+ proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+
+ if (likely(proto && proto->nfattr_to_tuple)) {
+ ret = proto->nfattr_to_tuple(tb, tuple);
+ ip_conntrack_proto_put(proto);
+ }
+
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
+ enum ctattr_tuple type)
+{
+ struct nfattr *tb[CTA_TUPLE_MAX];
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ memset(tuple, 0, sizeof(*tuple));
+
+ if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0)
+ goto nfattr_failure;
+
+ if (!tb[CTA_TUPLE_IP-1])
+ return -EINVAL;
+
+ err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP-1], tuple);
+ if (err < 0)
+ return err;
+
+ if (!tb[CTA_TUPLE_PROTO-1])
+ return -EINVAL;
+
+ err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO-1], tuple);
+ if (err < 0)
+ return err;
+
+ /* orig and expect tuples get DIR_ORIGINAL */
+ if (type == CTA_TUPLE_REPLY)
+ tuple->dst.dir = IP_CT_DIR_REPLY;
+ else
+ tuple->dst.dir = IP_CT_DIR_ORIGINAL;
+
+ DUMP_TUPLE(tuple);
+
+ DEBUGP("leaving\n");
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+static const int cta_min_protonat[CTA_PROTONAT_MAX] = {
+ [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t),
+ [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t),
+};
+
+static int ctnetlink_parse_nat_proto(struct nfattr *attr,
+ const struct ip_conntrack *ct,
+ struct ip_nat_range *range)
+{
+ struct nfattr *tb[CTA_PROTONAT_MAX];
+ struct ip_nat_protocol *npt;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0)
+ goto nfattr_failure;
+
+ if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
+ goto nfattr_failure;
+
+ npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+ if (!npt)
+ return 0;
+
+ if (!npt->nfattr_to_range) {
+ ip_nat_proto_put(npt);
+ return 0;
+ }
+
+ /* nfattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
+ if (npt->nfattr_to_range(tb, range) > 0)
+ range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+
+ ip_nat_proto_put(npt);
+
+ DEBUGP("leaving\n");
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_parse_nat(struct nfattr *cda[],
+ const struct ip_conntrack *ct, struct ip_nat_range *range)
+{
+ struct nfattr *tb[CTA_NAT_MAX];
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ memset(range, 0, sizeof(*range));
+
+ if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0)
+ goto nfattr_failure;
+
+ if (tb[CTA_NAT_MINIP-1])
+ range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
+
+ if (!tb[CTA_NAT_MAXIP-1])
+ range->max_ip = range->min_ip;
+ else
+ range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
+
+ if (range->min_ip)
+ range->flags |= IP_NAT_RANGE_MAP_IPS;
+
+ if (!tb[CTA_NAT_PROTO-1])
+ return 0;
+
+ err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
+ if (err < 0)
+ return err;
+
+ DEBUGP("leaving\n");
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+#endif
+
+static inline int
+ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
+{
+ struct nfattr *tb[CTA_HELP_MAX];
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0)
+ goto nfattr_failure;
+
+ if (!tb[CTA_HELP_NAME-1])
+ return -EINVAL;
+
+ *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static int
+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_tuple_hash *h;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack *ct;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (cda[CTA_TUPLE_ORIG-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY);
+ else {
+ /* Flush the whole table */
+ ip_conntrack_flush();
+ return 0;
+ }
+
+ if (err < 0)
+ return err;
+
+ h = ip_conntrack_find_get(&tuple, NULL);
+ if (!h) {
+ DEBUGP("tuple not found in conntrack hash\n");
+ return -ENOENT;
+ }
+
+ ct = tuplehash_to_ctrack(h);
+
+ if (cda[CTA_ID-1]) {
+ u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+ if (ct->id != id) {
+ ip_conntrack_put(ct);
+ return -ENOENT;
+ }
+ }
+ if (del_timer(&ct->timeout)) {
+ ip_conntrack_put(ct);
+ ct->timeout.function((unsigned long)ct);
+ return 0;
+ }
+ ip_conntrack_put(ct);
+ DEBUGP("leaving\n");
+
+ return 0;
+}
+
+static int
+ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_tuple_hash *h;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack *ct;
+ struct sk_buff *skb2 = NULL;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct nfgenmsg *msg = NLMSG_DATA(nlh);
+ u32 rlen;
+
+ if (msg->nfgen_family != AF_INET)
+ return -EAFNOSUPPORT;
+
+ if (NFNL_MSG_TYPE(nlh->nlmsg_type) ==
+ IPCTNL_MSG_CT_GET_CTRZERO) {
+#ifdef CONFIG_IP_NF_CT_ACCT
+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
+ ctnetlink_dump_table_w,
+ ctnetlink_done)) != 0)
+ return -EINVAL;
+#else
+ return -ENOTSUPP;
+#endif
+ } else {
+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
+ ctnetlink_dump_table,
+ ctnetlink_done)) != 0)
+ return -EINVAL;
+ }
+
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+ skb_pull(skb, rlen);
+ return 0;
+ }
+
+ if (cda[CTA_TUPLE_ORIG-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY);
+ else
+ return -EINVAL;
+
+ if (err < 0)
+ return err;
+
+ h = ip_conntrack_find_get(&tuple, NULL);
+ if (!h) {
+ DEBUGP("tuple not found in conntrack hash");
+ return -ENOENT;
+ }
+ DEBUGP("tuple found\n");
+ ct = tuplehash_to_ctrack(h);
+
+ err = -ENOMEM;
+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb2) {
+ ip_conntrack_put(ct);
+ return -ENOMEM;
+ }
+ NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
+
+ err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
+ IPCTNL_MSG_CT_NEW, 1, ct);
+ ip_conntrack_put(ct);
+ if (err <= 0)
+ goto out;
+
+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+ if (err < 0)
+ goto out;
+
+ DEBUGP("leaving\n");
+ return 0;
+
+out:
+ if (skb2)
+ kfree_skb(skb2);
+ return -1;
+}
+
+static inline int
+ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+ unsigned long d, status = *(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]);
+ d = ct->status ^ status;
+
+ if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
+ /* unchangeable */
+ return -EINVAL;
+
+ if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
+ /* SEEN_REPLY bit can only be set */
+ return -EINVAL;
+
+
+ if (d & IPS_ASSURED && !(status & IPS_ASSURED))
+ /* ASSURED bit can only be set */
+ return -EINVAL;
+
+ if (cda[CTA_NAT-1]) {
+#ifndef CONFIG_IP_NF_NAT_NEEDED
+ return -EINVAL;
+#else
+ unsigned int hooknum;
+ struct ip_nat_range range;
+
+ if (ctnetlink_parse_nat(cda, ct, &range) < 0)
+ return -EINVAL;
+
+ DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n",
+ NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
+ htons(range.min.all), htons(range.max.all));
+
+ /* This is tricky but it works. ip_nat_setup_info needs the
+ * hook number as parameter, so let's do the correct
+ * conversion and run away */
+ if (status & IPS_SRC_NAT_DONE)
+ hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
+ else if (status & IPS_DST_NAT_DONE)
+ hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */
+ else
+ return -EINVAL; /* Missing NAT flags */
+
+ DEBUGP("NAT status: %lu\n",
+ status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+
+ if (ip_nat_initialized(ct, hooknum))
+ return -EEXIST;
+ ip_nat_setup_info(ct, &range, hooknum);
+
+ DEBUGP("NAT status after setup_info: %lu\n",
+ ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+#endif
+ }
+
+ /* Be careful here, modifying NAT bits can screw up things,
+ * so don't let users modify them directly if they don't pass
+ * ip_nat_range. */
+ ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
+ return 0;
+}
+
+
+static inline int
+ctnetlink_change_helper(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+ struct ip_conntrack_helper *helper;
+ char *helpname;
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ /* don't change helper of sibling connections */
+ if (ct->master)
+ return -EINVAL;
+
+ err = ctnetlink_parse_help(cda[CTA_HELP-1], &helpname);
+ if (err < 0)
+ return err;
+
+ helper = __ip_conntrack_helper_find_byname(helpname);
+ if (!helper) {
+ if (!strcmp(helpname, ""))
+ helper = NULL;
+ else
+ return -EINVAL;
+ }
+
+ if (ct->helper) {
+ if (!helper) {
+ /* we had a helper before ... */
+ ip_ct_remove_expectations(ct);
+ ct->helper = NULL;
+ } else {
+ /* need to zero data of old helper */
+ memset(&ct->help, 0, sizeof(ct->help));
+ }
+ }
+
+ ct->helper = helper;
+
+ return 0;
+}
+
+static inline int
+ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+ u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+
+ if (!del_timer(&ct->timeout))
+ return -ETIME;
+
+ ct->timeout.expires = jiffies + timeout * HZ;
+ add_timer(&ct->timeout);
+
+ return 0;
+}
+
+static int
+ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (cda[CTA_HELP-1]) {
+ err = ctnetlink_change_helper(ct, cda);
+ if (err < 0)
+ return err;
+ }
+
+ if (cda[CTA_TIMEOUT-1]) {
+ err = ctnetlink_change_timeout(ct, cda);
+ if (err < 0)
+ return err;
+ }
+
+ if (cda[CTA_STATUS-1]) {
+ err = ctnetlink_change_status(ct, cda);
+ if (err < 0)
+ return err;
+ }
+
+ DEBUGP("all done\n");
+ return 0;
+}
+
+static int
+ctnetlink_create_conntrack(struct nfattr *cda[],
+ struct ip_conntrack_tuple *otuple,
+ struct ip_conntrack_tuple *rtuple)
+{
+ struct ip_conntrack *ct;
+ int err = -EINVAL;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ ct = ip_conntrack_alloc(otuple, rtuple);
+ if (ct == NULL || IS_ERR(ct))
+ return -ENOMEM;
+
+ if (!cda[CTA_TIMEOUT-1])
+ goto err;
+ ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+
+ ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
+ ct->status |= IPS_CONFIRMED;
+
+ err = ctnetlink_change_status(ct, cda);
+ if (err < 0)
+ goto err;
+
+ ct->helper = ip_conntrack_helper_find_get(rtuple);
+
+ add_timer(&ct->timeout);
+ ip_conntrack_hash_insert(ct);
+
+ if (ct->helper)
+ ip_conntrack_helper_put(ct->helper);
+
+ DEBUGP("conntrack with id %u inserted\n", ct->id);
+ return 0;
+
+err:
+ ip_conntrack_free(ct);
+ return err;
+}
+
+static int
+ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_tuple otuple, rtuple;
+ struct ip_conntrack_tuple_hash *h = NULL;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (cda[CTA_TUPLE_ORIG-1]) {
+ err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG);
+ if (err < 0)
+ return err;
+ }
+
+ if (cda[CTA_TUPLE_REPLY-1]) {
+ err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY);
+ if (err < 0)
+ return err;
+ }
+
+ write_lock_bh(&ip_conntrack_lock);
+ if (cda[CTA_TUPLE_ORIG-1])
+ h = __ip_conntrack_find(&otuple, NULL);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ h = __ip_conntrack_find(&rtuple, NULL);
+
+ if (h == NULL) {
+ write_unlock_bh(&ip_conntrack_lock);
+ DEBUGP("no such conntrack, create new\n");
+ err = -ENOENT;
+ if (nlh->nlmsg_flags & NLM_F_CREATE)
+ err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
+ return err;
+ }
+ /* implicit 'else' */
+
+ /* we only allow nat config for new conntracks */
+ if (cda[CTA_NAT-1]) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
+ /* We manipulate the conntrack inside the global conntrack table lock,
+ * so there's no need to increase the refcount */
+ DEBUGP("conntrack found\n");
+ err = -EEXIST;
+ if (!(nlh->nlmsg_flags & NLM_F_EXCL))
+ err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda);
+
+out_unlock:
+ write_unlock_bh(&ip_conntrack_lock);
+ return err;
+}
+
+/***********************************************************************
+ * EXPECT
+ ***********************************************************************/
+
+static inline int
+ctnetlink_exp_dump_tuple(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple,
+ enum ctattr_expect type)
+{
+ struct nfattr *nest_parms = NFA_NEST(skb, type);
+
+ if (ctnetlink_dump_tuples(skb, tuple) < 0)
+ goto nfattr_failure;
+
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_exp_dump_expect(struct sk_buff *skb,
+ const struct ip_conntrack_expect *exp)
+{
+ struct ip_conntrack *master = exp->master;
+ u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
+ u_int32_t id = htonl(exp->id);
+
+ if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
+ goto nfattr_failure;
+ if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+ goto nfattr_failure;
+ if (ctnetlink_exp_dump_tuple(skb,
+ &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ CTA_EXPECT_MASTER) < 0)
+ goto nfattr_failure;
+
+ NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
+ NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static int
+ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+ int event,
+ int nowait,
+ const struct ip_conntrack_expect *exp)
+{
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ unsigned char *b;
+
+ b = skb->tail;
+
+ event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
+ nfmsg->nfgen_family = AF_INET;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+ if (ctnetlink_exp_dump_expect(skb, exp) < 0)
+ goto nfattr_failure;
+
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+nfattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+static int ctnetlink_expect_event(struct notifier_block *this,
+ unsigned long events, void *ptr)
+{
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ struct ip_conntrack_expect *exp = (struct ip_conntrack_expect *)ptr;
+ struct sk_buff *skb;
+ unsigned int type;
+ unsigned char *b;
+ int flags = 0;
+ u16 proto;
+
+ if (events & IPEXP_NEW) {
+ type = IPCTNL_MSG_EXP_NEW;
+ flags = NLM_F_CREATE|NLM_F_EXCL;
+ } else
+ return NOTIFY_DONE;
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return NOTIFY_DONE;
+
+ b = skb->tail;
+
+ type |= NFNL_SUBSYS_CTNETLINK << 8;
+ nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = flags;
+ nfmsg->nfgen_family = AF_INET;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+ if (ctnetlink_exp_dump_expect(skb, exp) < 0)
+ goto nfattr_failure;
+
+ nlh->nlmsg_len = skb->tail - b;
+ proto = exp->tuple.dst.protonum;
+ nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
+ return NOTIFY_DONE;
+
+nlmsg_failure:
+nfattr_failure:
+ kfree_skb(skb);
+ return NOTIFY_DONE;
+}
+#endif
+
+static int
+ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct ip_conntrack_expect *exp = NULL;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[0];
+
+ DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
+
+ read_lock_bh(&ip_conntrack_lock);
+ list_for_each_prev(i, &ip_conntrack_expect_list) {
+ exp = (struct ip_conntrack_expect *) i;
+ if (exp->id <= *id)
+ continue;
+ if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ IPCTNL_MSG_EXP_NEW,
+ 1, exp) < 0)
+ goto out;
+ *id = exp->id;
+ }
+out:
+ read_unlock_bh(&ip_conntrack_lock);
+
+ DEBUGP("leaving, last id=%llu\n", *id);
+
+ return skb->len;
+}
+
+static int
+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_expect *exp;
+ struct sk_buff *skb2;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct nfgenmsg *msg = NLMSG_DATA(nlh);
+ u32 rlen;
+
+ if (msg->nfgen_family != AF_INET)
+ return -EAFNOSUPPORT;
+
+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
+ ctnetlink_exp_dump_table,
+ ctnetlink_done)) != 0)
+ return -EINVAL;
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+ skb_pull(skb, rlen);
+ return 0;
+ }
+
+ if (cda[CTA_EXPECT_MASTER-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER);
+ else
+ return -EINVAL;
+
+ if (err < 0)
+ return err;
+
+ exp = ip_conntrack_expect_find_get(&tuple);
+ if (!exp)
+ return -ENOENT;
+
+ err = -ENOMEM;
+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!skb2)
+ goto out;
+ NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
+
+ err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
+ nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
+ 1, exp);
+ if (err <= 0)
+ goto out;
+
+ ip_conntrack_expect_put(exp);
+
+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+ if (err < 0)
+ goto free;
+
+ return err;
+
+out:
+ ip_conntrack_expect_put(exp);
+free:
+ if (skb2)
+ kfree_skb(skb2);
+ return err;
+}
+
+static int
+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_expect *exp, *tmp;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_helper *h;
+ int err;
+
+ if (cda[CTA_EXPECT_TUPLE-1]) {
+ /* delete a single expect by tuple */
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
+ if (err < 0)
+ return err;
+
+ /* bump usage count to 2 */
+ exp = ip_conntrack_expect_find_get(&tuple);
+ if (!exp)
+ return -ENOENT;
+
+ if (cda[CTA_EXPECT_ID-1]) {
+ u_int32_t id =
+ *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+ if (exp->id != ntohl(id)) {
+ ip_conntrack_expect_put(exp);
+ return -ENOENT;
+ }
+ }
+
+ /* after list removal, usage count == 1 */
+ ip_conntrack_unexpect_related(exp);
+ /* have to put what we 'get' above.
+ * after this line usage count == 0 */
+ ip_conntrack_expect_put(exp);
+ } else if (cda[CTA_EXPECT_HELP_NAME-1]) {
+ char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
+
+ /* delete all expectations for this helper */
+ write_lock_bh(&ip_conntrack_lock);
+ h = __ip_conntrack_helper_find_byname(name);
+ if (!h) {
+ write_unlock_bh(&ip_conntrack_lock);
+ return -EINVAL;
+ }
+ list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
+ list) {
+ if (exp->master->helper == h
+ && del_timer(&exp->timeout)) {
+ ip_ct_unlink_expect(exp);
+ ip_conntrack_expect_put(exp);
+ }
+ }
+ write_unlock(&ip_conntrack_lock);
+ } else {
+ /* This basically means we have to flush everything*/
+ write_lock_bh(&ip_conntrack_lock);
+ list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
+ list) {
+ if (del_timer(&exp->timeout)) {
+ ip_ct_unlink_expect(exp);
+ ip_conntrack_expect_put(exp);
+ }
+ }
+ write_unlock_bh(&ip_conntrack_lock);
+ }
+
+ return 0;
+}
+static int
+ctnetlink_change_expect(struct ip_conntrack_expect *x, struct nfattr *cda[])
+{
+ return -EOPNOTSUPP;
+}
+
+static int
+ctnetlink_create_expect(struct nfattr *cda[])
+{
+ struct ip_conntrack_tuple tuple, mask, master_tuple;
+ struct ip_conntrack_tuple_hash *h = NULL;
+ struct ip_conntrack_expect *exp;
+ struct ip_conntrack *ct;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ /* caller guarantees that those three CTA_EXPECT_* exist */
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
+ if (err < 0)
+ return err;
+ err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK);
+ if (err < 0)
+ return err;
+ err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER);
+ if (err < 0)
+ return err;
+
+ /* Look for master conntrack of this expectation */
+ h = ip_conntrack_find_get(&master_tuple, NULL);
+ if (!h)
+ return -ENOENT;
+ ct = tuplehash_to_ctrack(h);
+
+ if (!ct->helper) {
+ /* such conntrack hasn't got any helper, abort */
+ err = -EINVAL;
+ goto out;
+ }
+
+ exp = ip_conntrack_expect_alloc(ct);
+ if (!exp) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ exp->expectfn = NULL;
+ exp->flags = 0;
+ exp->master = ct;
+ memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple));
+ memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple));
+
+ err = ip_conntrack_expect_related(exp);
+ ip_conntrack_expect_put(exp);
+
+out:
+ ip_conntrack_put(tuplehash_to_ctrack(h));
+ return err;
+}
+
+static int
+ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_expect *exp;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (!cda[CTA_EXPECT_TUPLE-1]
+ || !cda[CTA_EXPECT_MASK-1]
+ || !cda[CTA_EXPECT_MASTER-1])
+ return -EINVAL;
+
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
+ if (err < 0)
+ return err;
+
+ write_lock_bh(&ip_conntrack_lock);
+ exp = __ip_conntrack_expect_find(&tuple);
+
+ if (!exp) {
+ write_unlock_bh(&ip_conntrack_lock);
+ err = -ENOENT;
+ if (nlh->nlmsg_flags & NLM_F_CREATE)
+ err = ctnetlink_create_expect(cda);
+ return err;
+ }
+
+ err = -EEXIST;
+ if (!(nlh->nlmsg_flags & NLM_F_EXCL))
+ err = ctnetlink_change_expect(exp, cda);
+ write_unlock_bh(&ip_conntrack_lock);
+
+ DEBUGP("leaving\n");
+
+ return err;
+}
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+static struct notifier_block ctnl_notifier = {
+ .notifier_call = ctnetlink_conntrack_event,
+};
+
+static struct notifier_block ctnl_notifier_exp = {
+ .notifier_call = ctnetlink_expect_event,
+};
+#endif
+
+static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
+ [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack,
+ .attr_count = CTA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack,
+ .attr_count = CTA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack,
+ .attr_count = CTA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
+ .attr_count = CTA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+};
+
+static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
+ [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect,
+ .attr_count = CTA_EXPECT_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect,
+ .attr_count = CTA_EXPECT_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
+ .attr_count = CTA_EXPECT_MAX,
+ .cap_required = CAP_NET_ADMIN },
+};
+
+static struct nfnetlink_subsystem ctnl_subsys = {
+ .name = "conntrack",
+ .subsys_id = NFNL_SUBSYS_CTNETLINK,
+ .cb_count = IPCTNL_MSG_MAX,
+ .cb = ctnl_cb,
+};
+
+static struct nfnetlink_subsystem ctnl_exp_subsys = {
+ .name = "conntrack_expect",
+ .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP,
+ .cb_count = IPCTNL_MSG_EXP_MAX,
+ .cb = ctnl_exp_cb,
+};
+
+static int __init ctnetlink_init(void)
+{
+ int ret;
+
+ printk("ctnetlink v%s: registering with nfnetlink.\n", version);
+ ret = nfnetlink_subsys_register(&ctnl_subsys);
+ if (ret < 0) {
+ printk("ctnetlink_init: cannot register with nfnetlink.\n");
+ goto err_out;
+ }
+
+ ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
+ if (ret < 0) {
+ printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
+ goto err_unreg_subsys;
+ }
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+ ret = ip_conntrack_register_notifier(&ctnl_notifier);
+ if (ret < 0) {
+ printk("ctnetlink_init: cannot register notifier.\n");
+ goto err_unreg_exp_subsys;
+ }
+
+ ret = ip_conntrack_expect_register_notifier(&ctnl_notifier_exp);
+ if (ret < 0) {
+ printk("ctnetlink_init: cannot expect register notifier.\n");
+ goto err_unreg_notifier;
+ }
+#endif
+
+ return 0;
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+err_unreg_notifier:
+ ip_conntrack_unregister_notifier(&ctnl_notifier);
+err_unreg_exp_subsys:
+ nfnetlink_subsys_unregister(&ctnl_exp_subsys);
+#endif
+err_unreg_subsys:
+ nfnetlink_subsys_unregister(&ctnl_subsys);
+err_out:
+ return ret;
+}
+
+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_unregister_notifier(&ctnl_notifier);
+#endif
+
+ nfnetlink_subsys_unregister(&ctnl_exp_subsys);
+ nfnetlink_subsys_unregister(&ctnl_subsys);
+ return;
+}
+
+module_init(ctnetlink_init);
+module_exit(ctnetlink_exit);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 602c74db3252..838d1d69b36e 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -102,22 +102,24 @@ static int icmp_packet(struct ip_conntrack *ct,
ct->timeout.function((unsigned long)ct);
} else {
atomic_inc(&ct->proto.icmp.count);
+ ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
}
return NF_ACCEPT;
}
+static u_int8_t valid_new[] = {
+ [ICMP_ECHO] = 1,
+ [ICMP_TIMESTAMP] = 1,
+ [ICMP_INFO_REQUEST] = 1,
+ [ICMP_ADDRESS] = 1
+};
+
/* Called when a new connection for this protocol found. */
static int icmp_new(struct ip_conntrack *conntrack,
const struct sk_buff *skb)
{
- static u_int8_t valid_new[]
- = { [ICMP_ECHO] = 1,
- [ICMP_TIMESTAMP] = 1,
- [ICMP_INFO_REQUEST] = 1,
- [ICMP_ADDRESS] = 1 };
-
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
/* Can't create a new ICMP `conn' with this. */
@@ -158,11 +160,12 @@ icmp_error_message(struct sk_buff *skb,
return NF_ACCEPT;
}
- innerproto = ip_ct_find_proto(inside->ip.protocol);
+ innerproto = ip_conntrack_proto_find_get(inside->ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp) + inside->ip.ihl*4;
/* Are they talking about one of our connections? */
if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) {
DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol);
+ ip_conntrack_proto_put(innerproto);
return NF_ACCEPT;
}
@@ -170,8 +173,10 @@ icmp_error_message(struct sk_buff *skb,
been preserved inside the ICMP. */
if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
DEBUGP("icmp_error_track: Can't invert tuple\n");
+ ip_conntrack_proto_put(innerproto);
return NF_ACCEPT;
}
+ ip_conntrack_proto_put(innerproto);
*ctinfo = IP_CT_RELATED;
@@ -212,7 +217,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih);
if (icmph == NULL) {
if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: short packet ");
return -NF_ACCEPT;
}
@@ -226,13 +231,13 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
if (!(u16)csum_fold(skb->csum))
break;
if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_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,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: bad ICMP checksum ");
return -NF_ACCEPT;
}
@@ -249,7 +254,7 @@ checksum_skipped:
*/
if (icmph->type > NR_ICMP_TYPES) {
if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_icmp: invalid ICMP type ");
return -NF_ACCEPT;
}
@@ -265,6 +270,47 @@ checksum_skipped:
return icmp_error_message(skb, ctinfo, hooknum);
}
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+static int icmp_tuple_to_nfattr(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *t)
+{
+ NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
+ &t->src.u.icmp.id);
+ NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
+ &t->dst.u.icmp.type);
+ NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
+ &t->dst.u.icmp.code);
+
+ if (t->dst.u.icmp.type >= sizeof(valid_new)
+ || !valid_new[t->dst.u.icmp.type])
+ return -EINVAL;
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static int icmp_nfattr_to_tuple(struct nfattr *tb[],
+ struct ip_conntrack_tuple *tuple)
+{
+ if (!tb[CTA_PROTO_ICMP_TYPE-1]
+ || !tb[CTA_PROTO_ICMP_CODE-1]
+ || !tb[CTA_PROTO_ICMP_ID-1])
+ return -1;
+
+ tuple->dst.u.icmp.type =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
+ tuple->dst.u.icmp.code =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
+ tuple->src.u.icmp.id =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+
+ return 0;
+}
+#endif
+
struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
{
.proto = IPPROTO_ICMP,
@@ -276,4 +322,9 @@ struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
.packet = icmp_packet,
.new = icmp_new,
.error = icmp_error,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .tuple_to_nfattr = icmp_tuple_to_nfattr,
+ .nfattr_to_tuple = icmp_nfattr_to_tuple,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 31d75390bf12..a875f35e576d 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -404,6 +404,8 @@ static int sctp_packet(struct ip_conntrack *conntrack,
}
conntrack->proto.sctp.state = newconntrack;
+ if (oldsctpstate != newconntrack)
+ ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
write_unlock_bh(&sctp_lock);
}
@@ -503,7 +505,12 @@ static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
.packet = sctp_packet,
.new = sctp_new,
.destroy = NULL,
- .me = THIS_MODULE
+ .me = THIS_MODULE,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
};
#ifdef CONFIG_SYSCTL
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 809dfed766d4..1985abc59d24 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -336,6 +336,24 @@ static int tcp_print_conntrack(struct seq_file *s,
return seq_printf(s, "%s ", tcp_conntrack_names[state]);
}
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
+ const struct ip_conntrack *ct)
+{
+ read_lock_bh(&tcp_lock);
+ NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
+ &ct->proto.tcp.state);
+ read_unlock_bh(&tcp_lock);
+
+ return 0;
+
+nfattr_failure:
+ read_unlock_bh(&tcp_lock);
+ return -1;
+}
+#endif
+
static unsigned int get_conntrack_index(const struct tcphdr *tcph)
{
if (tcph->rst) return TCP_RST_SET;
@@ -699,7 +717,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
res = 1;
} else {
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: %s ",
before(seq, sender->td_maxend + 1) ?
after(end, sender->td_end - receiver->td_maxwin - 1) ?
@@ -798,7 +816,7 @@ static int tcp_error(struct sk_buff *skb,
sizeof(_tcph), &_tcph);
if (th == NULL) {
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: short packet ");
return -NF_ACCEPT;
}
@@ -806,7 +824,7 @@ static int tcp_error(struct sk_buff *skb,
/* Not whole TCP header or malformed packet */
if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: truncated/malformed packet ");
return -NF_ACCEPT;
}
@@ -823,7 +841,7 @@ static int tcp_error(struct sk_buff *skb,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum ");
return -NF_ACCEPT;
}
@@ -832,7 +850,7 @@ static int tcp_error(struct sk_buff *skb,
tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
if (!tcp_valid_flags[tcpflags]) {
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid TCP flag combination ");
return -NF_ACCEPT;
}
@@ -880,8 +898,9 @@ static int tcp_packet(struct ip_conntrack *conntrack,
*/
write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- "ip_ct_tcp: killing out of sync session ");
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ NULL, "ip_ct_tcp: "
+ "killing out of sync session ");
if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)
conntrack);
@@ -895,7 +914,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid packet ignored ");
return NF_ACCEPT;
case TCP_CONNTRACK_MAX:
@@ -905,7 +924,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
old_state);
write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: invalid state ");
return -NF_ACCEPT;
case TCP_CONNTRACK_SYN_SENT:
@@ -926,7 +945,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- "ip_ct_tcp: invalid SYN");
+ NULL, "ip_ct_tcp: invalid SYN");
return -NF_ACCEPT;
}
case TCP_CONNTRACK_CLOSE:
@@ -973,6 +992,10 @@ static int tcp_packet(struct ip_conntrack *conntrack,
? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
write_unlock_bh(&tcp_lock);
+ ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
+ if (new_state != old_state)
+ ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
+
if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
/* If only reply is a RST, we can consider ourselves not to
have an established connection: this is a fairly common
@@ -1096,4 +1119,10 @@ struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
.packet = tcp_packet,
.new = tcp_new,
.error = tcp_error,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .to_nfattr = tcp_to_nfattr,
+ .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 8c1eaba098d4..f2dcac7c7660 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -73,7 +73,8 @@ static int udp_packet(struct ip_conntrack *conntrack,
ip_ct_refresh_acct(conntrack, ctinfo, skb,
ip_ct_udp_timeout_stream);
/* Also, more likely to be important, and not a probe */
- set_bit(IPS_ASSURED_BIT, &conntrack->status);
+ if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
+ ip_conntrack_event_cache(IPCT_STATUS, skb);
} else
ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
@@ -97,7 +98,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr);
if (hdr == NULL) {
if (LOG_INVALID(IPPROTO_UDP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: short packet ");
return -NF_ACCEPT;
}
@@ -105,7 +106,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
/* Truncated/malformed packets */
if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
if (LOG_INVALID(IPPROTO_UDP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: truncated/malformed packet ");
return -NF_ACCEPT;
}
@@ -125,7 +126,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, udplen, 0))) {
if (LOG_INVALID(IPPROTO_UDP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum ");
return -NF_ACCEPT;
}
@@ -144,4 +145,9 @@ struct ip_conntrack_protocol ip_conntrack_protocol_udp =
.packet = udp_packet,
.new = udp_new,
.error = udp_error,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 61798c46e91d..ae3e3e655db5 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -5,7 +5,7 @@
*/
/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2002-2005 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
@@ -147,8 +147,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (DIRECTION(hash))
return 0;
- proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.dst.protonum);
+ proto = __ip_conntrack_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
IP_NF_ASSERT(proto);
if (seq_printf(s, "%-8s %u %ld ",
@@ -185,7 +184,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
return -ENOSPC;
#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
- if (seq_printf(s, "mark=%lu ", conntrack->mark))
+ if (seq_printf(s, "mark=%u ", conntrack->mark))
return -ENOSPC;
#endif
@@ -283,7 +282,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
seq_printf(s, "proto=%u ", expect->tuple.dst.protonum);
print_tuple(s, &expect->tuple,
- ip_ct_find_proto(expect->tuple.dst.protonum));
+ __ip_conntrack_proto_find(expect->tuple.dst.protonum));
return seq_putc(s, '\n');
}
@@ -889,6 +888,7 @@ static int init_or_cleanup(int init)
return ret;
cleanup:
+ synchronize_net();
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(ip_ct_sysctl_header);
cleanup_localinops:
@@ -971,6 +971,14 @@ void need_ip_conntrack(void)
{
}
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+EXPORT_SYMBOL_GPL(ip_conntrack_chain);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_chain);
+EXPORT_SYMBOL_GPL(ip_conntrack_register_notifier);
+EXPORT_SYMBOL_GPL(ip_conntrack_unregister_notifier);
+EXPORT_SYMBOL_GPL(__ip_ct_event_cache_init);
+EXPORT_PER_CPU_SYMBOL_GPL(ip_conntrack_ecache);
+#endif
EXPORT_SYMBOL(ip_conntrack_protocol_register);
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
EXPORT_SYMBOL(ip_ct_get_tuple);
@@ -982,12 +990,16 @@ EXPORT_SYMBOL(ip_conntrack_helper_register);
EXPORT_SYMBOL(ip_conntrack_helper_unregister);
EXPORT_SYMBOL(ip_ct_iterate_cleanup);
EXPORT_SYMBOL(ip_ct_refresh_acct);
-EXPORT_SYMBOL(ip_ct_protos);
-EXPORT_SYMBOL(ip_ct_find_proto);
+
EXPORT_SYMBOL(ip_conntrack_expect_alloc);
EXPORT_SYMBOL(ip_conntrack_expect_put);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
EXPORT_SYMBOL(ip_conntrack_expect_related);
EXPORT_SYMBOL(ip_conntrack_unexpect_related);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
+EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
+
EXPORT_SYMBOL(ip_conntrack_tuple_taken);
EXPORT_SYMBOL(ip_ct_gather_frags);
EXPORT_SYMBOL(ip_conntrack_htable_size);
@@ -995,7 +1007,28 @@ EXPORT_SYMBOL(ip_conntrack_lock);
EXPORT_SYMBOL(ip_conntrack_hash);
EXPORT_SYMBOL(ip_conntrack_untracked);
EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
-EXPORT_SYMBOL_GPL(ip_conntrack_put);
#ifdef CONFIG_IP_NF_NAT_NEEDED
EXPORT_SYMBOL(ip_conntrack_tcp_update);
#endif
+
+EXPORT_SYMBOL_GPL(ip_conntrack_flush);
+EXPORT_SYMBOL_GPL(__ip_conntrack_find);
+
+EXPORT_SYMBOL_GPL(ip_conntrack_alloc);
+EXPORT_SYMBOL_GPL(ip_conntrack_free);
+EXPORT_SYMBOL_GPL(ip_conntrack_hash_insert);
+
+EXPORT_SYMBOL_GPL(ip_ct_remove_expectations);
+
+EXPORT_SYMBOL_GPL(ip_conntrack_helper_find_get);
+EXPORT_SYMBOL_GPL(ip_conntrack_helper_put);
+EXPORT_SYMBOL_GPL(__ip_conntrack_helper_find_byname);
+
+EXPORT_SYMBOL_GPL(ip_conntrack_proto_find_get);
+EXPORT_SYMBOL_GPL(ip_conntrack_proto_put);
+EXPORT_SYMBOL_GPL(__ip_conntrack_proto_find);
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+EXPORT_SYMBOL_GPL(ip_ct_port_tuple_to_nfattr);
+EXPORT_SYMBOL_GPL(ip_ct_port_nfattr_to_tuple);
+#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index f8ff170f390a..d2b590533452 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -75,6 +75,7 @@ static int tftp_help(struct sk_buff **pskb,
exp->mask.dst.u.udp.port = 0xffff;
exp->mask.dst.protonum = 0xff;
exp->expectfn = NULL;
+ exp->flags = 0;
DEBUGP("expect: ");
DUMP_TUPLE(&exp->tuple);
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 739b6dde1c82..1adedb743f60 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -47,8 +47,39 @@ DEFINE_RWLOCK(ip_nat_lock);
static unsigned int ip_nat_htable_size;
static struct list_head *bysource;
+
+#define MAX_IP_NAT_PROTO 256
struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+static inline struct ip_nat_protocol *
+__ip_nat_proto_find(u_int8_t protonum)
+{
+ return ip_nat_protos[protonum];
+}
+
+struct ip_nat_protocol *
+ip_nat_proto_find_get(u_int8_t protonum)
+{
+ struct ip_nat_protocol *p;
+
+ /* we need to disable preemption to make sure 'p' doesn't get
+ * removed until we've grabbed the reference */
+ preempt_disable();
+ p = __ip_nat_proto_find(protonum);
+ if (p) {
+ if (!try_module_get(p->me))
+ p = &ip_nat_unknown_protocol;
+ }
+ preempt_enable();
+
+ return p;
+}
+
+void
+ip_nat_proto_put(struct ip_nat_protocol *p)
+{
+ module_put(p->me);
+}
/* We keep an extra hash for each conntrack, for fast searching. */
static inline unsigned int
@@ -103,7 +134,8 @@ static int
in_range(const struct ip_conntrack_tuple *tuple,
const struct ip_nat_range *range)
{
- struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
+ struct ip_nat_protocol *proto =
+ __ip_nat_proto_find(tuple->dst.protonum);
/* If we are supposed to map IPs, then we must be in the
range specified, otherwise let this drag us onto a new src IP. */
@@ -216,8 +248,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
struct ip_conntrack *conntrack,
enum ip_nat_manip_type maniptype)
{
- struct ip_nat_protocol *proto
- = ip_nat_find_proto(orig_tuple->dst.protonum);
+ struct ip_nat_protocol *proto;
/* 1) If this srcip/proto/src-proto-part is currently mapped,
and that same mapping gives a unique tuple within the given
@@ -242,14 +273,20 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
/* 3) The per-protocol part of the manip is made to map into
the range to make a unique tuple. */
+ proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
+
/* Only bother mapping if it's not already in range and unique */
if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
|| proto->in_range(tuple, maniptype, &range->min, &range->max))
- && !ip_nat_used_tuple(tuple, conntrack))
+ && !ip_nat_used_tuple(tuple, conntrack)) {
+ ip_nat_proto_put(proto);
return;
+ }
/* Last change: get protocol to try to obtain unique tuple. */
proto->unique_tuple(tuple, range, maniptype, conntrack);
+
+ ip_nat_proto_put(proto);
}
unsigned int
@@ -320,17 +357,20 @@ manip_pkt(u_int16_t proto,
enum ip_nat_manip_type maniptype)
{
struct iphdr *iph;
+ struct ip_nat_protocol *p;
- (*pskb)->nfcache |= NFC_ALTERED;
- if (!skb_ip_make_writable(pskb, iphdroff + sizeof(*iph)))
+ if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
return 0;
iph = (void *)(*pskb)->data + iphdroff;
/* Manipulate protcol part. */
- if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff,
- target, maniptype))
+ p = ip_nat_proto_find_get(proto);
+ if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {
+ ip_nat_proto_put(p);
return 0;
+ }
+ ip_nat_proto_put(p);
iph = (void *)(*pskb)->data + iphdroff;
@@ -391,7 +431,7 @@ int icmp_reply_translation(struct sk_buff **pskb,
struct ip_conntrack_tuple inner, target;
int hdrlen = (*pskb)->nh.iph->ihl * 4;
- if (!skb_ip_make_writable(pskb, hdrlen + sizeof(*inside)))
+ if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
return 0;
inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
@@ -426,7 +466,8 @@ int icmp_reply_translation(struct sk_buff **pskb,
if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 +
sizeof(struct icmphdr) + inside->ip.ihl*4,
- &inner, ip_ct_find_proto(inside->ip.protocol)))
+ &inner,
+ __ip_conntrack_proto_find(inside->ip.protocol)))
return 0;
/* Change inner back to look like incoming packet. We do the
@@ -496,6 +537,49 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
synchronize_net();
}
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+int
+ip_nat_port_range_to_nfattr(struct sk_buff *skb,
+ const struct ip_nat_range *range)
+{
+ NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(u_int16_t),
+ &range->min.tcp.port);
+ NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(u_int16_t),
+ &range->max.tcp.port);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+int
+ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
+{
+ int ret = 0;
+
+ /* we have to return whether we actually parsed something or not */
+
+ if (tb[CTA_PROTONAT_PORT_MIN-1]) {
+ ret = 1;
+ range->min.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
+ }
+
+ if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
+ if (ret)
+ range->max.tcp.port = range->min.tcp.port;
+ } else {
+ ret = 1;
+ range->max.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
+ }
+
+ return ret;
+}
+#endif
+
int __init ip_nat_init(void)
{
size_t i;
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 158f34f32c04..d2dd5d313556 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -168,7 +168,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
struct tcphdr *tcph;
int datalen;
- if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(pskb, (*pskb)->len))
return 0;
if (rep_len > match_len
@@ -228,7 +228,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
match_offset + match_len)
return 0;
- if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(pskb, (*pskb)->len))
return 0;
if (rep_len > match_len
@@ -315,7 +315,7 @@ ip_nat_sack_adjust(struct sk_buff **pskb,
optoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct tcphdr);
optend = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
- if (!skb_ip_make_writable(pskb, optend))
+ if (!skb_make_writable(pskb, optend))
return 0;
dir = CTINFO2DIR(ctinfo);
@@ -363,7 +363,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
this_way = &ct->nat.info.seq[dir];
other_way = &ct->nat.info.seq[!dir];
- if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
+ if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
return 0;
tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index 6596c9ee1655..938719043999 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -62,7 +62,7 @@ icmp_manip_pkt(struct sk_buff **pskb,
struct icmphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4;
- if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
+ if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
return 0;
hdr = (struct icmphdr *)((*pskb)->data + hdroff);
@@ -106,11 +106,18 @@ icmp_print_range(char *buffer, const struct ip_nat_range *range)
else return 0;
}
-struct ip_nat_protocol ip_nat_protocol_icmp
-= { "ICMP", IPPROTO_ICMP,
- icmp_manip_pkt,
- icmp_in_range,
- icmp_unique_tuple,
- icmp_print,
- icmp_print_range
+struct ip_nat_protocol ip_nat_protocol_icmp = {
+ .name = "ICMP",
+ .protonum = IPPROTO_ICMP,
+ .me = THIS_MODULE,
+ .manip_pkt = icmp_manip_pkt,
+ .in_range = icmp_in_range,
+ .unique_tuple = icmp_unique_tuple,
+ .print = icmp_print,
+ .print_range = icmp_print_range,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = ip_nat_port_range_to_nfattr,
+ .nfattr_to_range = ip_nat_port_nfattr_to_range,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index a98e36d2b3c6..1d381bf68574 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -12,6 +12,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/if.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_nat_protocol.h>
@@ -102,7 +103,7 @@ tcp_manip_pkt(struct sk_buff **pskb,
if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
hdrsize = sizeof(struct tcphdr);
- if (!skb_ip_make_writable(pskb, hdroff + hdrsize))
+ if (!skb_make_writable(pskb, hdroff + hdrsize))
return 0;
iph = (struct iphdr *)((*pskb)->data + iphdroff);
@@ -169,11 +170,18 @@ tcp_print_range(char *buffer, const struct ip_nat_range *range)
else return 0;
}
-struct ip_nat_protocol ip_nat_protocol_tcp
-= { "TCP", IPPROTO_TCP,
- tcp_manip_pkt,
- tcp_in_range,
- tcp_unique_tuple,
- tcp_print,
- tcp_print_range
+struct ip_nat_protocol ip_nat_protocol_tcp = {
+ .name = "TCP",
+ .protonum = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ .manip_pkt = tcp_manip_pkt,
+ .in_range = tcp_in_range,
+ .unique_tuple = tcp_unique_tuple,
+ .print = tcp_print,
+ .print_range = tcp_print_range,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = ip_nat_port_range_to_nfattr,
+ .nfattr_to_range = ip_nat_port_nfattr_to_range,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 9f66e5625664..c4906e1aa24a 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -94,7 +94,7 @@ udp_manip_pkt(struct sk_buff **pskb,
u32 oldip, newip;
u16 *portptr, newport;
- if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
+ if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
return 0;
iph = (struct iphdr *)((*pskb)->data + iphdroff);
@@ -156,11 +156,18 @@ udp_print_range(char *buffer, const struct ip_nat_range *range)
else return 0;
}
-struct ip_nat_protocol ip_nat_protocol_udp
-= { "UDP", IPPROTO_UDP,
- udp_manip_pkt,
- udp_in_range,
- udp_unique_tuple,
- udp_print,
- udp_print_range
+struct ip_nat_protocol ip_nat_protocol_udp = {
+ .name = "UDP",
+ .protonum = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ .manip_pkt = udp_manip_pkt,
+ .in_range = udp_in_range,
+ .unique_tuple = udp_unique_tuple,
+ .print = udp_print,
+ .print_range = udp_print_range,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = ip_nat_port_range_to_nfattr,
+ .nfattr_to_range = ip_nat_port_nfattr_to_range,
+#endif
};
diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
index f5525bd58d16..99bbef56f84e 100644
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c
@@ -61,10 +61,11 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range)
}
struct ip_nat_protocol ip_nat_unknown_protocol = {
- "unknown", 0,
- unknown_manip_pkt,
- unknown_in_range,
- unknown_unique_tuple,
- unknown_print,
- unknown_print_range
+ .name = "unknown",
+ .me = THIS_MODULE,
+ .manip_pkt = unknown_manip_pkt,
+ .in_range = unknown_in_range,
+ .unique_tuple = unknown_unique_tuple,
+ .print = unknown_print,
+ .print_range = unknown_print_range
};
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 60d70fa41a15..cb66b8bddeb3 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -255,6 +255,27 @@ alloc_null_binding(struct ip_conntrack *conntrack,
return ip_nat_setup_info(conntrack, &range, hooknum);
}
+unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+ struct ip_nat_info *info,
+ unsigned int hooknum)
+{
+ u_int32_t ip
+ = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
+ : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
+ u_int16_t all
+ = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+ : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+ struct ip_nat_range range
+ = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
+
+ DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+ conntrack, NIPQUAD(ip));
+ return ip_nat_setup_info(conntrack, &range, hooknum);
+}
+
int ip_nat_rule_find(struct sk_buff **pskb,
unsigned int hooknum,
const struct net_device *in,
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 2a48b6e635ae..93b2c5111bb2 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -1275,7 +1275,7 @@ static int help(struct sk_buff **pskb,
return NF_DROP;
}
- if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(pskb, (*pskb)->len))
return NF_DROP;
spin_lock_bh(&snmp_lock);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 91d5ea1dbbc9..0ff368b131f6 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -73,8 +73,6 @@ ip_nat_fn(unsigned int hooknum,
IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
& htons(IP_MF|IP_OFFSET)));
- (*pskb)->nfcache |= NFC_UNKNOWN;
-
/* If we had a hardware checksum before, it's now invalid */
if ((*pskb)->ip_summed == CHECKSUM_HW)
if (skb_checksum_help(*pskb, (out == NULL)))
@@ -125,8 +123,12 @@ ip_nat_fn(unsigned int hooknum,
if (!ip_nat_initialized(ct, maniptype)) {
unsigned int ret;
- /* LOCAL_IN hook doesn't have a chain! */
- if (hooknum == NF_IP_LOCAL_IN)
+ if (unlikely(is_confirmed(ct)))
+ /* NAT module was loaded late */
+ ret = alloc_null_binding_confirmed(ct, info,
+ hooknum);
+ else if (hooknum == NF_IP_LOCAL_IN)
+ /* LOCAL_IN hook doesn't have a chain! */
ret = alloc_null_binding(ct, info, hooknum);
else
ret = ip_nat_rule_find(pskb, hooknum,
@@ -396,6 +398,8 @@ module_exit(fini);
EXPORT_SYMBOL(ip_nat_setup_info);
EXPORT_SYMBOL(ip_nat_protocol_register);
EXPORT_SYMBOL(ip_nat_protocol_unregister);
+EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
+EXPORT_SYMBOL_GPL(ip_nat_proto_put);
EXPORT_SYMBOL(ip_nat_cheat_check);
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index c6baa8174389..d54f14d926f6 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -43,17 +43,10 @@
#define NET_IPQ_QMAX 2088
#define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
-struct ipq_rt_info {
- __u8 tos;
- __u32 daddr;
- __u32 saddr;
-};
-
struct ipq_queue_entry {
struct list_head list;
struct nf_info *info;
struct sk_buff *skb;
- struct ipq_rt_info rt_info;
};
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
@@ -247,8 +240,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->packet_id = (unsigned long )entry;
pmsg->data_len = data_len;
- pmsg->timestamp_sec = entry->skb->stamp.tv_sec;
- pmsg->timestamp_usec = entry->skb->stamp.tv_usec;
+ pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec;
+ pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec;
pmsg->mark = entry->skb->nfmark;
pmsg->hook = entry->info->hook;
pmsg->hw_protocol = entry->skb->protocol;
@@ -287,7 +280,8 @@ nlmsg_failure:
}
static int
-ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
+ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
+ unsigned int queuenum, void *data)
{
int status = -EINVAL;
struct sk_buff *nskb;
@@ -305,14 +299,6 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
entry->info = info;
entry->skb = skb;
- if (entry->info->hook == NF_IP_LOCAL_OUT) {
- struct iphdr *iph = skb->nh.iph;
-
- entry->rt_info.tos = iph->tos;
- entry->rt_info.daddr = iph->daddr;
- entry->rt_info.saddr = iph->saddr;
- }
-
nskb = ipq_build_packet_message(entry, &status);
if (nskb == NULL)
goto err_out_free;
@@ -388,24 +374,11 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
}
skb_put(e->skb, diff);
}
- if (!skb_ip_make_writable(&e->skb, v->data_len))
+ if (!skb_make_writable(&e->skb, v->data_len))
return -ENOMEM;
memcpy(e->skb->data, v->payload, v->data_len);
e->skb->ip_summed = CHECKSUM_NONE;
- e->skb->nfcache |= NFC_ALTERED;
-
- /*
- * Extra routing may needed on local out, as the QUEUE target never
- * returns control to the table.
- */
- if (e->info->hook == NF_IP_LOCAL_OUT) {
- struct iphdr *iph = e->skb->nh.iph;
-
- if (!(iph->tos == e->rt_info.tos
- && iph->daddr == e->rt_info.daddr
- && iph->saddr == e->rt_info.saddr))
- return ip_route_me_harder(&e->skb);
- }
+
return 0;
}
@@ -683,6 +656,11 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
}
#endif /* CONFIG_PROC_FS */
+static struct nf_queue_handler nfqh = {
+ .name = "ip_queue",
+ .outfn = &ipq_enqueue_packet,
+};
+
static int
init_or_cleanup(int init)
{
@@ -693,7 +671,8 @@ init_or_cleanup(int init)
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
- ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk);
+ ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
+ THIS_MODULE);
if (ipqnl == NULL) {
printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
goto cleanup_netlink_notifier;
@@ -710,7 +689,7 @@ init_or_cleanup(int init)
register_netdevice_notifier(&ipq_dev_notifier);
ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
- status = nf_register_queue_handler(PF_INET, ipq_enqueue_packet, NULL);
+ status = nf_register_queue_handler(PF_INET, &nfqh);
if (status < 0) {
printk(KERN_ERR "ip_queue: failed to register queue handler\n");
goto cleanup_sysctl;
@@ -718,7 +697,7 @@ init_or_cleanup(int init)
return status;
cleanup:
- nf_unregister_queue_handler(PF_INET);
+ nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index c88dfcd38c56..eef99a1b5de6 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -312,7 +312,6 @@ ipt_do_table(struct sk_buff **pskb,
do {
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
- (*pskb)->nfcache |= e->nfcache;
if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
struct ipt_entry_target *t;
@@ -341,8 +340,8 @@ ipt_do_table(struct sk_buff **pskb,
back->comefrom);
continue;
}
- if (table_base + v
- != (void *)e + e->next_offset) {
+ if (table_base + v != (void *)e + e->next_offset
+ && !(e->ip.flags & IPT_F_GOTO)) {
/* Save old back ptr in next entry */
struct ipt_entry *next
= (void *)e + e->next_offset;
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/ipv4/netfilter/ipt_CLASSIFY.c
index 9842e6e23184..dab78d8bd494 100644
--- a/net/ipv4/netfilter/ipt_CLASSIFY.c
+++ b/net/ipv4/netfilter/ipt_CLASSIFY.c
@@ -32,10 +32,8 @@ target(struct sk_buff **pskb,
{
const struct ipt_classify_target_info *clinfo = targinfo;
- if((*pskb)->priority != clinfo->priority) {
+ if((*pskb)->priority != clinfo->priority)
(*pskb)->priority = clinfo->priority;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 6706d3a1bc4f..7d38913754b1 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -144,7 +144,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
memcpy(&c->clustermac, &i->clustermac, ETH_ALEN);
c->num_total_nodes = i->num_total_nodes;
c->num_local_nodes = i->num_local_nodes;
- memcpy(&c->local_nodes, &i->local_nodes, sizeof(&c->local_nodes));
+ memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes));
c->hash_mode = i->hash_mode;
c->hash_initval = i->hash_initval;
atomic_set(&c->refcount, 1);
@@ -367,7 +367,7 @@ target(struct sk_buff **pskb,
#ifdef DEBUG_CLUSTERP
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
#endif
- DEBUGP("hash=%u ct_hash=%lu ", hash, ct->mark);
+ DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark);
if (!clusterip_responsible(cipinfo->config, hash)) {
DEBUGP("not responsible\n");
return NF_DROP;
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c
index 30ddd3e18eb7..134638021339 100644
--- a/net/ipv4/netfilter/ipt_CONNMARK.c
+++ b/net/ipv4/netfilter/ipt_CONNMARK.c
@@ -40,9 +40,9 @@ target(struct sk_buff **pskb,
void *userinfo)
{
const struct ipt_connmark_target_info *markinfo = targinfo;
- unsigned long diff;
- unsigned long nfmark;
- unsigned long newmark;
+ u_int32_t diff;
+ u_int32_t nfmark;
+ u_int32_t newmark;
enum ip_conntrack_info ctinfo;
struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
@@ -61,10 +61,8 @@ target(struct sk_buff **pskb,
case IPT_CONNMARK_RESTORE:
nfmark = (*pskb)->nfmark;
diff = (ct->mark ^ nfmark) & markinfo->mask;
- if (diff != 0) {
+ if (diff != 0)
(*pskb)->nfmark = nfmark ^ diff;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
break;
}
}
@@ -94,6 +92,11 @@ checkentry(const char *tablename,
}
}
+ if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
+ printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
+ return 0;
+ }
+
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 3ea4509099f9..6e319570a28c 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -39,7 +39,7 @@ target(struct sk_buff **pskb,
if (((*pskb)->nh.iph->tos & IPT_DSCP_MASK) != sh_dscp) {
u_int16_t diffs[2];
- if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return NF_DROP;
diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
@@ -51,7 +51,6 @@ target(struct sk_buff **pskb,
sizeof(diffs),
(*pskb)->nh.iph->check
^ 0xFFFF));
- (*pskb)->nfcache |= NFC_ALTERED;
}
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 94a0ce1c1c9d..a1319693f648 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -31,7 +31,7 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
!= (einfo->ip_ect & IPT_ECN_IP_MASK)) {
u_int16_t diffs[2];
- if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return 0;
diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
@@ -43,7 +43,6 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
sizeof(diffs),
(*pskb)->nh.iph->check
^0xFFFF));
- (*pskb)->nfcache |= NFC_ALTERED;
}
return 1;
}
@@ -67,7 +66,7 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
tcph->cwr == einfo->proto.tcp.cwr)))
return 1;
- if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
+ if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
return 0;
tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4;
@@ -87,7 +86,6 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
tcph->check = csum_fold(csum_partial((char *)diffs,
sizeof(diffs),
tcph->check^0xFFFF));
- (*pskb)->nfcache |= NFC_ALTERED;
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index ef08733d26da..92ed050fac69 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -27,10 +27,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables syslog logging module");
-static unsigned int nflog = 1;
-module_param(nflog, int, 0400);
-MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
-
#if 0
#define DEBUGP printk
#else
@@ -41,11 +37,17 @@ MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */
-static void dump_packet(const struct ipt_log_info *info,
+static void dump_packet(const struct nf_loginfo *info,
const struct sk_buff *skb,
unsigned int iphoff)
{
struct iphdr _iph, *ih;
+ unsigned int logflags;
+
+ if (info->type == NF_LOG_TYPE_LOG)
+ logflags = info->u.log.logflags;
+ else
+ logflags = NF_LOG_MASK;
ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
if (ih == NULL) {
@@ -76,7 +78,7 @@ static void dump_packet(const struct ipt_log_info *info,
if (ntohs(ih->frag_off) & IP_OFFSET)
printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
- if ((info->logflags & IPT_LOG_IPOPT)
+ if ((logflags & IPT_LOG_IPOPT)
&& ih->ihl * 4 > sizeof(struct iphdr)) {
unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
unsigned int i, optsize;
@@ -119,7 +121,7 @@ static void dump_packet(const struct ipt_log_info *info,
printk("SPT=%u DPT=%u ",
ntohs(th->source), ntohs(th->dest));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
- if (info->logflags & IPT_LOG_TCPSEQ)
+ if (logflags & IPT_LOG_TCPSEQ)
printk("SEQ=%u ACK=%u ",
ntohl(th->seq), ntohl(th->ack_seq));
/* Max length: 13 "WINDOW=65535 " */
@@ -146,7 +148,7 @@ static void dump_packet(const struct ipt_log_info *info,
/* Max length: 11 "URGP=65535 " */
printk("URGP=%u ", ntohs(th->urg_ptr));
- if ((info->logflags & IPT_LOG_TCPOPT)
+ if ((logflags & IPT_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) {
unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
unsigned char *op;
@@ -328,7 +330,7 @@ static void dump_packet(const struct ipt_log_info *info,
}
/* Max length: 15 "UID=4294967295 " */
- if ((info->logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
+ if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file)
printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
@@ -349,19 +351,31 @@ static void dump_packet(const struct ipt_log_info *info,
/* maxlen = 230+ 91 + 230 + 252 = 803 */
}
+struct nf_loginfo default_loginfo = {
+ .type = NF_LOG_TYPE_LOG,
+ .u = {
+ .log = {
+ .level = 0,
+ .logflags = NF_LOG_MASK,
+ },
+ },
+};
+
static void
-ipt_log_packet(unsigned int hooknum,
+ipt_log_packet(unsigned int pf,
+ unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
- const struct ipt_log_info *loginfo,
- const char *level_string,
+ const struct nf_loginfo *loginfo,
const char *prefix)
{
+ if (!loginfo)
+ loginfo = &default_loginfo;
+
spin_lock_bh(&log_lock);
- printk(level_string);
- printk("%sIN=%s OUT=%s ",
- prefix == NULL ? loginfo->prefix : prefix,
+ printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+ prefix,
in ? in->name : "",
out ? out->name : "");
#ifdef CONFIG_BRIDGE_NETFILTER
@@ -405,28 +419,15 @@ ipt_log_target(struct sk_buff **pskb,
void *userinfo)
{
const struct ipt_log_info *loginfo = targinfo;
- char level_string[4] = "< >";
+ struct nf_loginfo li;
- level_string[1] = '0' + (loginfo->level % 8);
- ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+ li.type = NF_LOG_TYPE_LOG;
+ li.u.log.level = loginfo->level;
+ li.u.log.logflags = loginfo->logflags;
- return IPT_CONTINUE;
-}
+ nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix);
-static void
-ipt_logfn(unsigned int hooknum,
- const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const char *prefix)
-{
- struct ipt_log_info loginfo = {
- .level = 0,
- .logflags = IPT_LOG_MASK,
- .prefix = ""
- };
-
- ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
+ return IPT_CONTINUE;
}
static int ipt_log_checkentry(const char *tablename,
@@ -464,20 +465,29 @@ static struct ipt_target ipt_log_reg = {
.me = THIS_MODULE,
};
+static struct nf_logger ipt_log_logger ={
+ .name = "ipt_LOG",
+ .logfn = &ipt_log_packet,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
if (ipt_register_target(&ipt_log_reg))
return -EINVAL;
- if (nflog)
- nf_log_register(PF_INET, &ipt_logfn);
+ if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
+ printk(KERN_WARNING "ipt_LOG: not logging via system console "
+ "since somebody else already registered for PF_INET\n");
+ /* we cannot make module load fail here, since otherwise
+ * iptables userspace would abort */
+ }
return 0;
}
static void __exit fini(void)
{
- if (nflog)
- nf_log_unregister(PF_INET, &ipt_logfn);
+ nf_log_unregister_logger(&ipt_log_logger);
ipt_unregister_target(&ipt_log_reg);
}
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/ipv4/netfilter/ipt_MARK.c
index 33c6f9b63b8d..52b4f2c296bf 100644
--- a/net/ipv4/netfilter/ipt_MARK.c
+++ b/net/ipv4/netfilter/ipt_MARK.c
@@ -29,10 +29,9 @@ target_v0(struct sk_buff **pskb,
{
const struct ipt_mark_target_info *markinfo = targinfo;
- if((*pskb)->nfmark != markinfo->mark) {
+ if((*pskb)->nfmark != markinfo->mark)
(*pskb)->nfmark = markinfo->mark;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
+
return IPT_CONTINUE;
}
@@ -61,10 +60,9 @@ target_v1(struct sk_buff **pskb,
break;
}
- if((*pskb)->nfmark != mark) {
+ if((*pskb)->nfmark != mark)
(*pskb)->nfmark = mark;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
+
return IPT_CONTINUE;
}
@@ -76,6 +74,8 @@ checkentry_v0(const char *tablename,
unsigned int targinfosize,
unsigned int hook_mask)
{
+ struct ipt_mark_target_info *markinfo = targinfo;
+
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
targinfosize,
@@ -88,6 +88,11 @@ checkentry_v0(const char *tablename,
return 0;
}
+ if (markinfo->mark > 0xffffffff) {
+ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
+ return 0;
+ }
+
return 1;
}
@@ -120,6 +125,11 @@ checkentry_v1(const char *tablename,
return 0;
}
+ if (markinfo->mark > 0xffffffff) {
+ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
+ return 0;
+ }
+
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 91e74502c3d3..2f3e181c8e97 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -86,11 +86,6 @@ masquerade_target(struct sk_buff **pskb,
IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
- /* FIXME: For the moment, don't do local packets, breaks
- testsuite for 2.3.49 --RR */
- if ((*pskb)->sk)
- return NF_ACCEPT;
-
ct = ip_conntrack_get(*pskb, &ctinfo);
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 06254b29d034..e6e7b6095363 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -46,7 +46,8 @@ check(const char *tablename,
DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
return 0;
}
- if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING))) {
+ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
+ (1 << NF_IP_LOCAL_OUT))) {
DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
return 0;
}
@@ -76,12 +77,13 @@ target(struct sk_buff **pskb,
struct ip_nat_range newrange;
IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
- || hooknum == NF_IP_POST_ROUTING);
+ || hooknum == NF_IP_POST_ROUTING
+ || hooknum == NF_IP_LOCAL_OUT);
ct = ip_conntrack_get(*pskb, &ctinfo);
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
- if (hooknum == NF_IP_PRE_ROUTING)
+ if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)
new_ip = (*pskb)->nh.iph->daddr & ~netmask;
else
new_ip = (*pskb)->nh.iph->saddr & ~netmask;
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c
new file mode 100644
index 000000000000..3cedc9be8807
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_NFQUEUE.c
@@ -0,0 +1,70 @@
+/* iptables module for using new netfilter netlink queue
+ *
+ * (C) 2005 by Harald Welte <laforge@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/skbuff.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("iptables NFQUEUE target");
+MODULE_LICENSE("GPL");
+
+static unsigned int
+target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_NFQ_info *tinfo = targinfo;
+
+ return NF_QUEUE_NR(tinfo->queuenum);
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) {
+ printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_NFQ_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_NFQ_reg = {
+ .name = "NFQUEUE",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_NFQ_reg);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_NFQ_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 915696446020..f057025a719e 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
fl.fl_ip_sport = tcph->dest;
fl.fl_ip_dport = tcph->source;
- if (xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0)) {
- dst_release(&rt->u.dst);
- rt = NULL;
- }
+ xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
return rt;
}
@@ -156,7 +153,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
/* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb);
- nskb->nfcache = 0;
nskb->nfmark = 0;
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(nskb->nf_bridge);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 7b84a254440e..8db70d6908c3 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -58,7 +58,7 @@ ipt_tcpmss_target(struct sk_buff **pskb,
unsigned int i;
u_int8_t *opt;
- if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ if (!skb_make_writable(pskb, (*pskb)->len))
return NF_DROP;
if ((*pskb)->ip_summed == CHECKSUM_HW &&
@@ -190,7 +190,6 @@ ipt_tcpmss_target(struct sk_buff **pskb,
newmss);
retmodified:
- (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 85c70d240f8b..deadb36d4428 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -33,7 +33,7 @@ target(struct sk_buff **pskb,
if (((*pskb)->nh.iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
u_int16_t diffs[2];
- if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
+ if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return NF_DROP;
diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
@@ -46,7 +46,6 @@ target(struct sk_buff **pskb,
sizeof(diffs),
(*pskb)->nh.iph->check
^0xFFFF));
- (*pskb)->nfcache |= NFC_ALTERED;
}
return IPT_CONTINUE;
}
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
new file mode 100644
index 000000000000..b9ae6a9382f3
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -0,0 +1,119 @@
+/* TTL modification target for IP tables
+ * (C) 2000,2005 by Harald Welte <laforge@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/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_TTL.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("IP tables TTL modification module");
+MODULE_LICENSE("GPL");
+
+static unsigned int
+ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const void *targinfo, void *userinfo)
+{
+ struct iphdr *iph;
+ const struct ipt_TTL_info *info = targinfo;
+ u_int16_t diffs[2];
+ int new_ttl;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ iph = (*pskb)->nh.iph;
+
+ switch (info->mode) {
+ case IPT_TTL_SET:
+ new_ttl = info->ttl;
+ break;
+ case IPT_TTL_INC:
+ new_ttl = iph->ttl + info->ttl;
+ if (new_ttl > 255)
+ new_ttl = 255;
+ break;
+ case IPT_TTL_DEC:
+ new_ttl = iph->ttl - info->ttl;
+ if (new_ttl < 0)
+ new_ttl = 0;
+ break;
+ default:
+ new_ttl = iph->ttl;
+ break;
+ }
+
+ if (new_ttl != iph->ttl) {
+ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
+ iph->ttl = new_ttl;
+ diffs[1] = htons(((unsigned)iph->ttl) << 8);
+ iph->check = csum_fold(csum_partial((char *)diffs,
+ sizeof(diffs),
+ iph->check^0xFFFF));
+ }
+
+ return IPT_CONTINUE;
+}
+
+static int ipt_ttl_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ipt_TTL_info *info = targinfo;
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
+ printk(KERN_WARNING "ipt_TTL: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
+ return 0;
+ }
+
+ if (strcmp(tablename, "mangle")) {
+ printk(KERN_WARNING "ipt_TTL: can only be called from "
+ "\"mangle\" table, not \"%s\"\n", tablename);
+ return 0;
+ }
+
+ if (info->mode > IPT_TTL_MAXMODE) {
+ printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
+ info->mode);
+ return 0;
+ }
+
+ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
+ return 0;
+
+ return 1;
+}
+
+static struct ipt_target ipt_TTL = {
+ .name = "TTL",
+ .target = ipt_ttl_target,
+ .checkentry = ipt_ttl_checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_TTL);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_TTL);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 52a0076302a7..e2c14f3cb2fc 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -62,6 +62,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("iptables userspace logging module");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
#define ULOG_NL_EVENT 111 /* Harald's favorite number */
#define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */
@@ -115,10 +116,10 @@ static void ulog_send(unsigned int nlgroupnum)
if (ub->qlen > 1)
ub->lastnlh->nlmsg_type = NLMSG_DONE;
- NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
- DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n",
- ub->qlen, nlgroupnum);
- netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
+ NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1;
+ DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n",
+ ub->qlen, nlgroupnum + 1);
+ netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC);
ub->qlen = 0;
ub->skb = NULL;
@@ -219,13 +220,13 @@ static void ipt_ulog_packet(unsigned int hooknum,
pm = NLMSG_DATA(nlh);
/* We might not have a timestamp, get one */
- if (skb->stamp.tv_sec == 0)
- do_gettimeofday((struct timeval *)&skb->stamp);
+ if (skb->tstamp.off_sec == 0)
+ __net_timestamp((struct sk_buff *)skb);
/* copy hook, prefix, timestamp, payload, etc. */
pm->data_len = copy_len;
- pm->timestamp_sec = skb->stamp.tv_sec;
- pm->timestamp_usec = skb->stamp.tv_usec;
+ pm->timestamp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec;
+ pm->timestamp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec;
pm->mark = skb->nfmark;
pm->hook = hooknum;
if (prefix != NULL)
@@ -303,18 +304,27 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
return IPT_CONTINUE;
}
-static void ipt_logfn(unsigned int hooknum,
+static void ipt_logfn(unsigned int pf,
+ unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
+ const struct nf_loginfo *li,
const char *prefix)
{
- struct ipt_ulog_info loginfo = {
- .nl_group = ULOG_DEFAULT_NLGROUP,
- .copy_range = 0,
- .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
- .prefix = ""
- };
+ struct ipt_ulog_info loginfo;
+
+ if (!li || li->type != NF_LOG_TYPE_ULOG) {
+ loginfo.nl_group = ULOG_DEFAULT_NLGROUP;
+ loginfo.copy_range = 0;
+ loginfo.qthreshold = ULOG_DEFAULT_QTHRESHOLD;
+ loginfo.prefix[0] = '\0';
+ } else {
+ loginfo.nl_group = li->u.ulog.group;
+ loginfo.copy_range = li->u.ulog.copy_len;
+ loginfo.qthreshold = li->u.ulog.qthreshold;
+ strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
+ }
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
}
@@ -354,6 +364,12 @@ static struct ipt_target ipt_ulog_reg = {
.me = THIS_MODULE,
};
+static struct nf_logger ipt_ulog_logger = {
+ .name = "ipt_ULOG",
+ .logfn = &ipt_logfn,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
int i;
@@ -372,7 +388,8 @@ static int __init init(void)
ulog_buffers[i].timer.data = i;
}
- nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
+ nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
+ THIS_MODULE);
if (!nflognl)
return -ENOMEM;
@@ -381,7 +398,7 @@ static int __init init(void)
return -EINVAL;
}
if (nflog)
- nf_log_register(PF_INET, &ipt_logfn);
+ nf_log_register(PF_INET, &ipt_ulog_logger);
return 0;
}
@@ -394,7 +411,7 @@ static void __exit fini(void)
DEBUGP("ipt_ULOG: cleanup_module\n");
if (nflog)
- nf_log_unregister(PF_INET, &ipt_logfn);
+ nf_log_unregister_logger(&ipt_ulog_logger);
ipt_unregister_target(&ipt_ulog_reg);
sock_release(nflognl->sk_socket);
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/ipv4/netfilter/ipt_connbytes.c
new file mode 100644
index 000000000000..df4a42c6da22
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_connbytes.c
@@ -0,0 +1,162 @@
+/* Kernel module to match connection tracking byte counter.
+ * GPL (C) 2002 Martin Devera (devik@cdi.cz).
+ *
+ * 2004-07-20 Harald Welte <laforge@netfilter.org>
+ * - reimplemented to use per-connection accounting counters
+ * - add functionality to match number of packets
+ * - add functionality to match average packet size
+ * - add support to match directions seperately
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_connbytes.h>
+
+#include <asm/div64.h>
+#include <asm/bitops.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
+
+/* 64bit divisor, dividend and result. dynamic precision */
+static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
+{
+ u_int32_t d = divisor;
+
+ if (divisor > 0xffffffffULL) {
+ unsigned int shift = fls(divisor >> 32);
+
+ d = divisor >> shift;
+ dividend >>= shift;
+ }
+
+ do_div(dividend, d);
+ return dividend;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ int *hotdrop)
+{
+ const struct ipt_connbytes_info *sinfo = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct;
+ u_int64_t what = 0; /* initialize to make gcc happy */
+
+ if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)))
+ return 0; /* no match */
+
+ switch (sinfo->what) {
+ case IPT_CONNBYTES_PKTS:
+ switch (sinfo->direction) {
+ case IPT_CONNBYTES_DIR_ORIGINAL:
+ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
+ break;
+ case IPT_CONNBYTES_DIR_REPLY:
+ what = ct->counters[IP_CT_DIR_REPLY].packets;
+ break;
+ case IPT_CONNBYTES_DIR_BOTH:
+ what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
+ what += ct->counters[IP_CT_DIR_REPLY].packets;
+ break;
+ }
+ break;
+ case IPT_CONNBYTES_BYTES:
+ switch (sinfo->direction) {
+ case IPT_CONNBYTES_DIR_ORIGINAL:
+ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
+ break;
+ case IPT_CONNBYTES_DIR_REPLY:
+ what = ct->counters[IP_CT_DIR_REPLY].bytes;
+ break;
+ case IPT_CONNBYTES_DIR_BOTH:
+ what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
+ what += ct->counters[IP_CT_DIR_REPLY].bytes;
+ break;
+ }
+ break;
+ case IPT_CONNBYTES_AVGPKT:
+ switch (sinfo->direction) {
+ case IPT_CONNBYTES_DIR_ORIGINAL:
+ what = div64_64(ct->counters[IP_CT_DIR_ORIGINAL].bytes,
+ ct->counters[IP_CT_DIR_ORIGINAL].packets);
+ break;
+ case IPT_CONNBYTES_DIR_REPLY:
+ what = div64_64(ct->counters[IP_CT_DIR_REPLY].bytes,
+ ct->counters[IP_CT_DIR_REPLY].packets);
+ break;
+ case IPT_CONNBYTES_DIR_BOTH:
+ {
+ u_int64_t bytes;
+ u_int64_t pkts;
+ bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
+ ct->counters[IP_CT_DIR_REPLY].bytes;
+ pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets+
+ ct->counters[IP_CT_DIR_REPLY].packets;
+
+ /* FIXME_THEORETICAL: what to do if sum
+ * overflows ? */
+
+ what = div64_64(bytes, pkts);
+ }
+ break;
+ }
+ break;
+ }
+
+ if (sinfo->count.to)
+ return (what <= sinfo->count.to && what >= sinfo->count.from);
+ else
+ return (what >= sinfo->count.from);
+}
+
+static int check(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_connbytes_info *sinfo = matchinfo;
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
+ return 0;
+
+ if (sinfo->what != IPT_CONNBYTES_PKTS &&
+ sinfo->what != IPT_CONNBYTES_BYTES &&
+ sinfo->what != IPT_CONNBYTES_AVGPKT)
+ return 0;
+
+ if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
+ sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
+ sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
+ return 0;
+
+ return 1;
+}
+
+static struct ipt_match state_match = {
+ .name = "connbytes",
+ .match = &match,
+ .checkentry = &check,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&state_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&state_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/ipv4/netfilter/ipt_connmark.c
index 2706f96cea55..bf8de47ce004 100644
--- a/net/ipv4/netfilter/ipt_connmark.c
+++ b/net/ipv4/netfilter/ipt_connmark.c
@@ -54,9 +54,16 @@ checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
+ struct ipt_connmark_info *cm =
+ (struct ipt_connmark_info *)matchinfo;
if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
return 0;
+ if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
+ printk(KERN_WARNING "connmark: only support 32bit mark\n");
+ return 0;
+ }
+
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/ipv4/netfilter/ipt_dccp.c
new file mode 100644
index 000000000000..ad3278bba6c1
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_dccp.c
@@ -0,0 +1,176 @@
+/*
+ * iptables module for DCCP protocol header matching
+ *
+ * (C) 2005 by Harald Welte <laforge@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/skbuff.h>
+#include <linux/spinlock.h>
+#include <net/ip.h>
+#include <linux/dccp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_dccp.h>
+
+#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
+ || (!!((invflag) & (option)) ^ (cond)))
+
+static unsigned char *dccp_optbuf;
+static DEFINE_SPINLOCK(dccp_buflock);
+
+static inline int
+dccp_find_option(u_int8_t option,
+ const struct sk_buff *skb,
+ const struct dccp_hdr *dh,
+ int *hotdrop)
+{
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+ unsigned char *op;
+ unsigned int optoff = __dccp_hdr_len(dh);
+ unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
+ unsigned int i;
+
+ if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ if (!optlen)
+ return 0;
+
+ spin_lock_bh(&dccp_buflock);
+ op = skb_header_pointer(skb,
+ skb->nh.iph->ihl*4 + optoff,
+ optlen, dccp_optbuf);
+ if (op == NULL) {
+ /* If we don't have the whole header, drop packet. */
+ spin_unlock_bh(&dccp_buflock);
+ *hotdrop = 1;
+ return 0;
+ }
+
+ for (i = 0; i < optlen; ) {
+ if (op[i] == option) {
+ spin_unlock_bh(&dccp_buflock);
+ return 1;
+ }
+
+ if (op[i] < 2)
+ i++;
+ else
+ i += op[i+1]?:1;
+ }
+
+ spin_unlock_bh(&dccp_buflock);
+ return 0;
+}
+
+
+static inline int
+match_types(const struct dccp_hdr *dh, u_int16_t typemask)
+{
+ return (typemask & (1 << dh->dccph_type));
+}
+
+static inline int
+match_option(u_int8_t option, const struct sk_buff *skb,
+ const struct dccp_hdr *dh, int *hotdrop)
+{
+ return dccp_find_option(option, skb, dh, hotdrop);
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ int *hotdrop)
+{
+ const struct ipt_dccp_info *info =
+ (const struct ipt_dccp_info *)matchinfo;
+ struct dccp_hdr _dh, *dh;
+
+ if (offset)
+ return 0;
+
+ dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh);
+ if (dh == NULL) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
+ && (ntohs(dh->dccph_sport) <= info->spts[1])),
+ IPT_DCCP_SRC_PORTS, info->flags, info->invflags)
+ && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
+ && (ntohs(dh->dccph_dport) <= info->dpts[1])),
+ IPT_DCCP_DEST_PORTS, info->flags, info->invflags)
+ && DCCHECK(match_types(dh, info->typemask),
+ IPT_DCCP_TYPE, info->flags, info->invflags)
+ && DCCHECK(match_option(info->option, skb, dh, hotdrop),
+ IPT_DCCP_OPTION, info->flags, info->invflags);
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_dccp_info *info;
+
+ info = (const struct ipt_dccp_info *)matchinfo;
+
+ return ip->proto == IPPROTO_DCCP
+ && !(ip->invflags & IPT_INV_PROTO)
+ && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info))
+ && !(info->flags & ~IPT_DCCP_VALID_FLAGS)
+ && !(info->invflags & ~IPT_DCCP_VALID_FLAGS)
+ && !(info->invflags & ~info->flags);
+}
+
+static struct ipt_match dccp_match =
+{
+ .name = "dccp",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ int ret;
+
+ /* doff is 8 bits, so the maximum option size is (4*256). Don't put
+ * this in BSS since DaveM is worried about locked TLB's for kernel
+ * BSS. */
+ dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
+ if (!dccp_optbuf)
+ return -ENOMEM;
+ ret = ipt_register_match(&dccp_match);
+ if (ret)
+ kfree(dccp_optbuf);
+
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&dccp_match);
+ kfree(dccp_optbuf);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("Match for DCCP protocol packets");
+
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 564b49bfebcf..2dd1cccbdab9 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -94,7 +94,7 @@ struct ipt_hashlimit_htable {
static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */
static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static HLIST_HEAD(hashlimit_htables);
-static kmem_cache_t *hashlimit_cachep;
+static kmem_cache_t *hashlimit_cachep __read_mostly;
static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
{
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/ipv4/netfilter/ipt_mark.c
index 8955728127b9..00bef6cdd3f8 100644
--- a/net/ipv4/netfilter/ipt_mark.c
+++ b/net/ipv4/netfilter/ipt_mark.c
@@ -37,9 +37,16 @@ checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
+ struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo;
+
if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info)))
return 0;
+ if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
+ printk(KERN_WARNING "mark: only supports 32bit mark\n");
+ return 0;
+ }
+
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 3b9065e06381..0cee2862ed85 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/file.h>
+#include <linux/rcupdate.h>
#include <net/sock.h>
#include <linux/netfilter_ipv4/ipt_owner.h>
@@ -21,106 +22,6 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables owner match");
static int
-match_comm(const struct sk_buff *skb, const char *comm)
-{
- struct task_struct *g, *p;
- struct files_struct *files;
- int i;
-
- read_lock(&tasklist_lock);
- do_each_thread(g, p) {
- if(strncmp(p->comm, comm, sizeof(p->comm)))
- continue;
-
- task_lock(p);
- files = p->files;
- if(files) {
- spin_lock(&files->file_lock);
- for (i=0; i < files->max_fds; i++) {
- if (fcheck_files(files, i) ==
- skb->sk->sk_socket->file) {
- spin_unlock(&files->file_lock);
- task_unlock(p);
- read_unlock(&tasklist_lock);
- return 1;
- }
- }
- spin_unlock(&files->file_lock);
- }
- task_unlock(p);
- } while_each_thread(g, p);
- read_unlock(&tasklist_lock);
- return 0;
-}
-
-static int
-match_pid(const struct sk_buff *skb, pid_t pid)
-{
- struct task_struct *p;
- struct files_struct *files;
- int i;
-
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (!p)
- goto out;
- task_lock(p);
- files = p->files;
- if(files) {
- spin_lock(&files->file_lock);
- for (i=0; i < files->max_fds; i++) {
- if (fcheck_files(files, i) ==
- skb->sk->sk_socket->file) {
- spin_unlock(&files->file_lock);
- task_unlock(p);
- read_unlock(&tasklist_lock);
- return 1;
- }
- }
- spin_unlock(&files->file_lock);
- }
- task_unlock(p);
-out:
- read_unlock(&tasklist_lock);
- return 0;
-}
-
-static int
-match_sid(const struct sk_buff *skb, pid_t sid)
-{
- struct task_struct *g, *p;
- struct file *file = skb->sk->sk_socket->file;
- int i, found=0;
-
- read_lock(&tasklist_lock);
- do_each_thread(g, p) {
- struct files_struct *files;
- if (p->signal->session != sid)
- continue;
-
- task_lock(p);
- files = p->files;
- if (files) {
- spin_lock(&files->file_lock);
- for (i=0; i < files->max_fds; i++) {
- if (fcheck_files(files, i) == file) {
- found = 1;
- break;
- }
- }
- spin_unlock(&files->file_lock);
- }
- task_unlock(p);
- if (found)
- goto out;
- } while_each_thread(g, p);
-out:
- read_unlock(&tasklist_lock);
-
- return found;
-}
-
-static int
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -145,24 +46,6 @@ match(const struct sk_buff *skb,
return 0;
}
- if(info->match & IPT_OWNER_PID) {
- if (!match_pid(skb, info->pid) ^
- !!(info->invert & IPT_OWNER_PID))
- return 0;
- }
-
- if(info->match & IPT_OWNER_SID) {
- if (!match_sid(skb, info->sid) ^
- !!(info->invert & IPT_OWNER_SID))
- return 0;
- }
-
- if(info->match & IPT_OWNER_COMM) {
- if (!match_comm(skb, info->comm) ^
- !!(info->invert & IPT_OWNER_COMM))
- return 0;
- }
-
return 1;
}
@@ -173,6 +56,8 @@ checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ipt_owner_info *info = matchinfo;
+
if (hook_mask
& ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
@@ -184,15 +69,13 @@ checkentry(const char *tablename,
IPT_ALIGN(sizeof(struct ipt_owner_info)));
return 0;
}
-#ifdef CONFIG_SMP
- /* files->file_lock can not be used in a BH */
- if (((struct ipt_owner_info *)matchinfo)->match
- & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
- printk("ipt_owner: pid, sid and command matching is broken "
- "on SMP.\n");
+
+ if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
+ printk("ipt_owner: pid, sid and command matching "
+ "not supported anymore\n");
return 0;
}
-#endif
+
return 1;
}
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/ipv4/netfilter/ipt_string.c
new file mode 100644
index 000000000000..b5def204d798
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_string.c
@@ -0,0 +1,91 @@
+/* String matching match for iptables
+ *
+ * (C) 2005 Pablo Neira Ayuso <pablo@eurodev.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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_string.h>
+#include <linux/textsearch.h>
+
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
+MODULE_DESCRIPTION("IP tables string match module");
+MODULE_LICENSE("GPL");
+
+static int match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ int *hotdrop)
+{
+ struct ts_state state;
+ struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo;
+
+ memset(&state, 0, sizeof(struct ts_state));
+
+ return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
+ conf->to_offset, conf->config, &state)
+ != UINT_MAX) && !conf->invert;
+}
+
+#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m)
+
+static int checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_string_info *conf = matchinfo;
+ struct ts_config *ts_conf;
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
+ return 0;
+
+ /* Damn, can't handle this case properly with iptables... */
+ if (conf->from_offset > conf->to_offset)
+ return 0;
+
+ ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
+ GFP_KERNEL, TS_AUTOLOAD);
+ if (IS_ERR(ts_conf))
+ return 0;
+
+ conf->config = ts_conf;
+
+ return 1;
+}
+
+static void destroy(void *matchinfo, unsigned int matchsize)
+{
+ textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
+}
+
+static struct ipt_match string_match = {
+ .name = "string",
+ .match = match,
+ .checkentry = checkentry,
+ .destroy = destroy,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&string_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&string_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 912bbcc7f415..f7943ba1f43c 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -59,13 +59,10 @@ static int fold_prot_inuse(struct proto *proto)
*/
static int sockstat_seq_show(struct seq_file *seq, void *v)
{
- /* From net/socket.c */
- extern void socket_seq_show(struct seq_file *seq);
-
socket_seq_show(seq);
seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
- tcp_tw_count, atomic_read(&tcp_sockets_allocated),
+ tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
atomic_read(&tcp_memory_allocated));
seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index 0db405a869f2..291831e792af 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -40,7 +40,6 @@
#include <linux/timer.h>
#include <net/ip.h>
#include <net/protocol.h>
-#include <net/tcp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/icmp.h>
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index d1835b1bc8c4..304bb0a1d4f0 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -59,7 +59,6 @@
#include <linux/netdevice.h>
#include <linux/in_route.h>
#include <linux/route.h>
-#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <net/dst.h>
#include <net/sock.h>
@@ -71,6 +70,7 @@
#include <net/udp.h>
#include <net/raw.h>
#include <net/snmp.h>
+#include <net/tcp_states.h>
#include <net/inet_common.h>
#include <net/checksum.h>
#include <net/xfrm.h>
@@ -150,10 +150,11 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
* RFC 1122: SHOULD pass TOS value up to the transport layer.
* -> It does. And not only TOS, but all IP header.
*/
-void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
+int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
{
struct sock *sk;
struct hlist_head *head;
+ int delivered = 0;
read_lock(&raw_v4_lock);
head = &raw_v4_htable[hash];
@@ -164,6 +165,7 @@ void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
skb->dev->ifindex);
while (sk) {
+ delivered = 1;
if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) {
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
@@ -177,6 +179,7 @@ void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
}
out:
read_unlock(&raw_v4_lock);
+ return delivered;
}
void raw_err (struct sock *sk, struct sk_buff *skb, u32 info)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d675ff80b04d..8549f26e2495 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -240,7 +240,9 @@ static unsigned rt_hash_mask;
static int rt_hash_log;
static unsigned int rt_hash_rnd;
-struct rt_cache_stat *rt_cache_stat;
+static struct rt_cache_stat *rt_cache_stat;
+#define RT_CACHE_STAT_INC(field) \
+ (per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++)
static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res);
@@ -1758,6 +1760,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
goto cleanup;
}
+ atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
if (res->fi->fib_nhs > 1)
@@ -1818,7 +1821,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
if (err)
return err;
- atomic_set(&rth->u.dst.__refcnt, 1);
/* put it into the cache */
hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
@@ -1832,8 +1834,8 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
u32 daddr, u32 saddr, u32 tos)
{
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct rtable* rth = NULL;
- unsigned char hop, hopcount, lasthop;
+ struct rtable* rth = NULL, *rtres;
+ unsigned char hop, hopcount;
int err = -EINVAL;
unsigned int hash;
@@ -1842,8 +1844,6 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
else
hopcount = 1;
- lasthop = hopcount - 1;
-
/* distinguish between multipath and singlepath */
if (hopcount < 2)
return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
@@ -1853,6 +1853,10 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
for (hop = 0; hop < hopcount; hop++) {
res->nh_sel = hop;
+ /* put reference to previous result */
+ if (hop)
+ ip_rt_put(rtres);
+
/* create a routing cache entry */
err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
&rth);
@@ -1861,7 +1865,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
/* put it into the cache */
hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
- err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+ err = rt_intern_hash(hash, rth, &rtres);
if (err)
return err;
@@ -1871,13 +1875,8 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
FIB_RES_NETMASK(*res),
res->prefixlen,
&FIB_RES_NH(*res));
-
- /* only for the last hop the reference count is handled
- * outside
- */
- if (hop == lasthop)
- atomic_set(&(skb->dst->__refcnt), 1);
}
+ skb->dst = &rtres->u.dst;
return err;
#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
@@ -2206,6 +2205,7 @@ static inline int __mkroute_output(struct rtable **result,
goto cleanup;
}
+ atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
if (res->fi) {
@@ -2288,8 +2288,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
if (err == 0) {
u32 tos = RT_FL_TOS(oldflp);
- atomic_set(&rth->u.dst.__refcnt, 1);
-
hash = rt_hash_code(oldflp->fl4_dst,
oldflp->fl4_src ^ (oldflp->oif << 5), tos);
err = rt_intern_hash(hash, rth, rp);
@@ -2324,6 +2322,10 @@ static inline int ip_mkroute_output(struct rtable** rp,
dev2nexthop = FIB_RES_DEV(*res);
dev_hold(dev2nexthop);
+ /* put reference to previous result */
+ if (hop)
+ ip_rt_put(*rp);
+
err = __mkroute_output(&rth, res, fl, oldflp,
dev2nexthop, flags);
@@ -2348,7 +2350,6 @@ static inline int ip_mkroute_output(struct rtable** rp,
if (err != 0)
return err;
}
- atomic_set(&(*rp)->u.dst.__refcnt, 1);
return err;
} else {
return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
@@ -2600,6 +2601,8 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
return ip_route_output_slow(rp, flp);
}
+EXPORT_SYMBOL_GPL(__ip_route_output_key);
+
int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
{
int err;
@@ -2618,6 +2621,8 @@ int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk,
return 0;
}
+EXPORT_SYMBOL_GPL(ip_route_output_flow);
+
int ip_route_output_key(struct rtable **rp, struct flowi *flp)
{
return ip_route_output_flow(rp, flp, NULL, 0);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 72d014442185..a34e60ea48a1 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -169,8 +169,6 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
}
-extern struct request_sock_ops tcp_request_sock_ops;
-
static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
@@ -180,7 +178,7 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
child = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
if (child)
- tcp_acceptq_queue(sk, req, child);
+ inet_csk_reqsk_queue_add(sk, req, child);
else
reqsk_free(req);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index e32894532416..652685623519 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -11,7 +11,9 @@
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/config.h>
+#include <linux/igmp.h>
#include <net/snmp.h>
+#include <net/icmp.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/tcp.h>
@@ -19,36 +21,6 @@
/* From af_inet.c */
extern int sysctl_ip_nonlocal_bind;
-/* From icmp.c */
-extern int sysctl_icmp_echo_ignore_all;
-extern int sysctl_icmp_echo_ignore_broadcasts;
-extern int sysctl_icmp_ignore_bogus_error_responses;
-extern int sysctl_icmp_errors_use_inbound_ifaddr;
-
-/* From ip_fragment.c */
-extern int sysctl_ipfrag_low_thresh;
-extern int sysctl_ipfrag_high_thresh;
-extern int sysctl_ipfrag_time;
-extern int sysctl_ipfrag_secret_interval;
-
-/* From ip_output.c */
-extern int sysctl_ip_dynaddr;
-
-/* From icmp.c */
-extern int sysctl_icmp_ratelimit;
-extern int sysctl_icmp_ratemask;
-
-/* From igmp.c */
-extern int sysctl_igmp_max_memberships;
-extern int sysctl_igmp_max_msf;
-
-/* From inetpeer.c */
-extern int inet_peer_threshold;
-extern int inet_peer_minttl;
-extern int inet_peer_maxttl;
-extern int inet_peer_gc_mintime;
-extern int inet_peer_gc_maxtime;
-
#ifdef CONFIG_SYSCTL
static int tcp_retr1_max = 255;
static int ip_local_port_range_min[] = { 1, 1 };
@@ -57,8 +29,6 @@ static int ip_local_port_range_max[] = { 65535, 65535 };
struct ipv4_config ipv4_config;
-extern ctl_table ipv4_route_table[];
-
#ifdef CONFIG_SYSCTL
static
@@ -136,10 +106,11 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file *
return ret;
}
-int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
+ int nlen, void __user *oldval,
+ size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ void **context)
{
char val[TCP_CA_NAME_MAX];
ctl_table tbl = {
@@ -259,7 +230,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_TCP_MAX_TW_BUCKETS,
.procname = "tcp_max_tw_buckets",
- .data = &sysctl_tcp_max_tw_buckets,
+ .data = &tcp_death_row.sysctl_max_tw_buckets,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
@@ -363,7 +334,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_TCP_TW_RECYCLE,
.procname = "tcp_tw_recycle",
- .data = &sysctl_tcp_tw_recycle,
+ .data = &tcp_death_row.sysctl_tw_recycle,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 69b1fcf70077..f3f0013a9580 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -269,13 +269,12 @@
int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
-DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
-
-kmem_cache_t *tcp_bucket_cachep;
-kmem_cache_t *tcp_timewait_cachep;
+DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics) __read_mostly;
atomic_t tcp_orphan_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL_GPL(tcp_orphan_count);
+
int sysctl_tcp_mem[3];
int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
@@ -311,15 +310,6 @@ void tcp_enter_memory_pressure(void)
EXPORT_SYMBOL(tcp_enter_memory_pressure);
/*
- * LISTEN is a special case for poll..
- */
-static __inline__ unsigned int tcp_listen_poll(struct sock *sk,
- poll_table *wait)
-{
- return !reqsk_queue_empty(&tcp_sk(sk)->accept_queue) ? (POLLIN | POLLRDNORM) : 0;
-}
-
-/*
* Wait for a TCP event.
*
* Note that we don't need to lock the socket, as the upper poll layers
@@ -334,7 +324,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
poll_wait(file, sk->sk_sleep, wait);
if (sk->sk_state == TCP_LISTEN)
- return tcp_listen_poll(sk, wait);
+ return inet_csk_listen_poll(sk);
/* Socket is not locked. We are protected from async events
by poll logic and correct handling of state changes
@@ -457,109 +447,6 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return put_user(answ, (int __user *)arg);
}
-
-int tcp_listen_start(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- struct tcp_sock *tp = tcp_sk(sk);
- int rc = reqsk_queue_alloc(&tp->accept_queue, TCP_SYNQ_HSIZE);
-
- if (rc != 0)
- return rc;
-
- sk->sk_max_ack_backlog = 0;
- sk->sk_ack_backlog = 0;
- tcp_delack_init(tp);
-
- /* There is race window here: we announce ourselves listening,
- * but this transition is still not validated by get_port().
- * It is OK, because this socket enters to hash table only
- * after validation is complete.
- */
- sk->sk_state = TCP_LISTEN;
- if (!sk->sk_prot->get_port(sk, inet->num)) {
- inet->sport = htons(inet->num);
-
- sk_dst_reset(sk);
- sk->sk_prot->hash(sk);
-
- return 0;
- }
-
- sk->sk_state = TCP_CLOSE;
- reqsk_queue_destroy(&tp->accept_queue);
- return -EADDRINUSE;
-}
-
-/*
- * This routine closes sockets which have been at least partially
- * opened, but not yet accepted.
- */
-
-static void tcp_listen_stop (struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- struct listen_sock *lopt;
- struct request_sock *acc_req;
- struct request_sock *req;
- int i;
-
- tcp_delete_keepalive_timer(sk);
-
- /* make all the listen_opt local to us */
- lopt = reqsk_queue_yank_listen_sk(&tp->accept_queue);
- acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue);
-
- if (lopt->qlen) {
- for (i = 0; i < TCP_SYNQ_HSIZE; i++) {
- while ((req = lopt->syn_table[i]) != NULL) {
- lopt->syn_table[i] = req->dl_next;
- lopt->qlen--;
- reqsk_free(req);
-
- /* Following specs, it would be better either to send FIN
- * (and enter FIN-WAIT-1, it is normal close)
- * or to send active reset (abort).
- * Certainly, it is pretty dangerous while synflood, but it is
- * bad justification for our negligence 8)
- * To be honest, we are not able to make either
- * of the variants now. --ANK
- */
- }
- }
- }
- BUG_TRAP(!lopt->qlen);
-
- kfree(lopt);
-
- while ((req = acc_req) != NULL) {
- struct sock *child = req->sk;
-
- acc_req = req->dl_next;
-
- local_bh_disable();
- bh_lock_sock(child);
- BUG_TRAP(!sock_owned_by_user(child));
- sock_hold(child);
-
- tcp_disconnect(child, O_NONBLOCK);
-
- sock_orphan(child);
-
- atomic_inc(&tcp_orphan_count);
-
- tcp_destroy_sock(child);
-
- bh_unlock_sock(child);
- local_bh_enable();
- sock_put(child);
-
- sk_acceptq_removed(sk);
- __reqsk_free(req);
- }
- BUG_TRAP(!sk->sk_ack_backlog);
-}
-
static inline void tcp_mark_push(struct tcp_sock *tp, struct sk_buff *skb)
{
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
@@ -665,8 +552,7 @@ new_segment:
tcp_mark_push(tp, skb);
goto new_segment;
}
- if (sk->sk_forward_alloc < copy &&
- !sk_stream_mem_schedule(sk, copy, 0))
+ if (!sk_stream_wmem_schedule(sk, copy))
goto wait_for_memory;
if (can_coalesce) {
@@ -883,19 +769,23 @@ new_segment:
if (off == PAGE_SIZE) {
put_page(page);
TCP_PAGE(sk) = page = NULL;
+ off = 0;
}
- }
+ } else
+ off = 0;
+
+ if (copy > PAGE_SIZE - off)
+ copy = PAGE_SIZE - off;
+
+ if (!sk_stream_wmem_schedule(sk, copy))
+ goto wait_for_memory;
if (!page) {
/* Allocate new cache page. */
if (!(page = sk_stream_alloc_page(sk)))
goto wait_for_memory;
- off = 0;
}
- if (copy > PAGE_SIZE - off)
- copy = PAGE_SIZE - off;
-
/* Time to copy data. We are close to
* the end! */
err = skb_copy_to_page(sk, from, skb, page,
@@ -975,7 +865,7 @@ do_fault:
if (!skb->len) {
if (sk->sk_send_head == skb)
sk->sk_send_head = NULL;
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &sk->sk_write_queue);
sk_stream_free_skb(sk, skb);
}
@@ -1057,20 +947,21 @@ static void cleanup_rbuf(struct sock *sk, int copied)
BUG_TRAP(!skb || before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq));
#endif
- if (tcp_ack_scheduled(tp)) {
+ if (inet_csk_ack_scheduled(sk)) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
/* Delayed ACKs frequently hit locked sockets during bulk
* receive. */
- if (tp->ack.blocked ||
+ if (icsk->icsk_ack.blocked ||
/* Once-per-two-segments ACK was not sent by tcp_input.c */
- tp->rcv_nxt - tp->rcv_wup > tp->ack.rcv_mss ||
+ tp->rcv_nxt - tp->rcv_wup > icsk->icsk_ack.rcv_mss ||
/*
* If this read emptied read buffer, we send ACK, if
* connection is not bidirectional, user drained
* receive buffer and there was a small segment
* in queue.
*/
- (copied > 0 && (tp->ack.pending & TCP_ACK_PUSHED) &&
- !tp->ack.pingpong && !atomic_read(&sk->sk_rmem_alloc)))
+ (copied > 0 && (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
+ !icsk->icsk_ack.pingpong && !atomic_read(&sk->sk_rmem_alloc)))
time_to_ack = 1;
}
@@ -1572,40 +1463,6 @@ void tcp_shutdown(struct sock *sk, int how)
}
}
-/*
- * At this point, there should be no process reference to this
- * socket, and thus no user references at all. Therefore we
- * can assume the socket waitqueue is inactive and nobody will
- * try to jump onto it.
- */
-void tcp_destroy_sock(struct sock *sk)
-{
- BUG_TRAP(sk->sk_state == TCP_CLOSE);
- BUG_TRAP(sock_flag(sk, SOCK_DEAD));
-
- /* It cannot be in hash table! */
- BUG_TRAP(sk_unhashed(sk));
-
- /* If it has not 0 inet_sk(sk)->num, it must be bound */
- BUG_TRAP(!inet_sk(sk)->num || tcp_sk(sk)->bind_hash);
-
- sk->sk_prot->destroy(sk);
-
- sk_stream_kill_queues(sk);
-
- xfrm_sk_free_policy(sk);
-
-#ifdef INET_REFCNT_DEBUG
- if (atomic_read(&sk->sk_refcnt) != 1) {
- printk(KERN_DEBUG "Destruction TCP %p delayed, c=%d\n",
- sk, atomic_read(&sk->sk_refcnt));
- }
-#endif
-
- atomic_dec(&tcp_orphan_count);
- sock_put(sk);
-}
-
void tcp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
@@ -1618,7 +1475,7 @@ void tcp_close(struct sock *sk, long timeout)
tcp_set_state(sk, TCP_CLOSE);
/* Special case. */
- tcp_listen_stop(sk);
+ inet_csk_listen_stop(sk);
goto adjudge_to_death;
}
@@ -1721,12 +1578,12 @@ adjudge_to_death:
tcp_send_active_reset(sk, GFP_ATOMIC);
NET_INC_STATS_BH(LINUX_MIB_TCPABORTONLINGER);
} else {
- int tmo = tcp_fin_time(tp);
+ const int tmo = tcp_fin_time(sk);
if (tmo > TCP_TIMEWAIT_LEN) {
- tcp_reset_keepalive_timer(sk, tcp_fin_time(tp));
+ inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
} else {
- atomic_inc(&tcp_orphan_count);
+ atomic_inc(sk->sk_prot->orphan_count);
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto out;
}
@@ -1734,7 +1591,7 @@ adjudge_to_death:
}
if (sk->sk_state != TCP_CLOSE) {
sk_stream_mem_reclaim(sk);
- if (atomic_read(&tcp_orphan_count) > sysctl_tcp_max_orphans ||
+ if (atomic_read(sk->sk_prot->orphan_count) > sysctl_tcp_max_orphans ||
(sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
if (net_ratelimit())
@@ -1745,10 +1602,10 @@ adjudge_to_death:
NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY);
}
}
- atomic_inc(&tcp_orphan_count);
+ atomic_inc(sk->sk_prot->orphan_count);
if (sk->sk_state == TCP_CLOSE)
- tcp_destroy_sock(sk);
+ inet_csk_destroy_sock(sk);
/* Otherwise, socket is reprieved until protocol close. */
out:
@@ -1769,6 +1626,7 @@ static inline int tcp_need_reset(int state)
int tcp_disconnect(struct sock *sk, int flags)
{
struct inet_sock *inet = inet_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int err = 0;
int old_state = sk->sk_state;
@@ -1778,7 +1636,7 @@ int tcp_disconnect(struct sock *sk, int flags)
/* ABORT function of RFC793 */
if (old_state == TCP_LISTEN) {
- tcp_listen_stop(sk);
+ inet_csk_listen_stop(sk);
} else if (tcp_need_reset(old_state) ||
(tp->snd_nxt != tp->write_seq &&
(1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) {
@@ -1805,125 +1663,34 @@ int tcp_disconnect(struct sock *sk, int flags)
tp->srtt = 0;
if ((tp->write_seq += tp->max_window + 2) == 0)
tp->write_seq = 1;
- tp->backoff = 0;
+ icsk->icsk_backoff = 0;
tp->snd_cwnd = 2;
- tp->probes_out = 0;
+ icsk->icsk_probes_out = 0;
tp->packets_out = 0;
tp->snd_ssthresh = 0x7fffffff;
tp->snd_cwnd_cnt = 0;
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_set_ca_state(sk, TCP_CA_Open);
tcp_clear_retrans(tp);
- tcp_delack_init(tp);
+ inet_csk_delack_init(sk);
sk->sk_send_head = NULL;
tp->rx_opt.saw_tstamp = 0;
tcp_sack_reset(&tp->rx_opt);
__sk_dst_reset(sk);
- BUG_TRAP(!inet->num || tp->bind_hash);
+ BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
sk->sk_error_report(sk);
return err;
}
/*
- * Wait for an incoming connection, avoid race
- * conditions. This must be called with the socket locked.
- */
-static int wait_for_connect(struct sock *sk, long timeo)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- DEFINE_WAIT(wait);
- int err;
-
- /*
- * True wake-one mechanism for incoming connections: only
- * one process gets woken up, not the 'whole herd'.
- * Since we do not 'race & poll' for established sockets
- * anymore, the common case will execute the loop only once.
- *
- * Subtle issue: "add_wait_queue_exclusive()" will be added
- * after any current non-exclusive waiters, and we know that
- * it will always _stay_ after any new non-exclusive waiters
- * because all non-exclusive waiters are added at the
- * beginning of the wait-queue. As such, it's ok to "drop"
- * our exclusiveness temporarily when we get woken up without
- * having to remove and re-insert us on the wait queue.
- */
- for (;;) {
- prepare_to_wait_exclusive(sk->sk_sleep, &wait,
- TASK_INTERRUPTIBLE);
- release_sock(sk);
- if (reqsk_queue_empty(&tp->accept_queue))
- timeo = schedule_timeout(timeo);
- lock_sock(sk);
- err = 0;
- if (!reqsk_queue_empty(&tp->accept_queue))
- break;
- err = -EINVAL;
- if (sk->sk_state != TCP_LISTEN)
- break;
- err = sock_intr_errno(timeo);
- if (signal_pending(current))
- break;
- err = -EAGAIN;
- if (!timeo)
- break;
- }
- finish_wait(sk->sk_sleep, &wait);
- return err;
-}
-
-/*
- * This will accept the next outstanding connection.
- */
-
-struct sock *tcp_accept(struct sock *sk, int flags, int *err)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- struct sock *newsk;
- int error;
-
- lock_sock(sk);
-
- /* We need to make sure that this socket is listening,
- * and that it has something pending.
- */
- error = -EINVAL;
- if (sk->sk_state != TCP_LISTEN)
- goto out_err;
-
- /* Find already established connection */
- if (reqsk_queue_empty(&tp->accept_queue)) {
- long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-
- /* If this is a non blocking socket don't sleep */
- error = -EAGAIN;
- if (!timeo)
- goto out_err;
-
- error = wait_for_connect(sk, timeo);
- if (error)
- goto out_err;
- }
-
- newsk = reqsk_queue_get_child(&tp->accept_queue, sk);
- BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
-out:
- release_sock(sk);
- return newsk;
-out_err:
- newsk = NULL;
- *err = error;
- goto out;
-}
-
-/*
* Socket option code for TCP.
*/
int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
int optlen)
{
struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
int val;
int err = 0;
@@ -1945,7 +1712,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
name[val] = 0;
lock_sock(sk);
- err = tcp_set_congestion_control(tp, name);
+ err = tcp_set_congestion_control(sk, name);
release_sock(sk);
return err;
}
@@ -2022,7 +1789,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
elapsed = tp->keepalive_time - elapsed;
else
elapsed = 0;
- tcp_reset_keepalive_timer(sk, elapsed);
+ inet_csk_reset_keepalive_timer(sk, elapsed);
}
}
break;
@@ -2042,7 +1809,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
if (val < 1 || val > MAX_TCP_SYNCNT)
err = -EINVAL;
else
- tp->syn_retries = val;
+ icsk->icsk_syn_retries = val;
break;
case TCP_LINGER2:
@@ -2055,15 +1822,15 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
break;
case TCP_DEFER_ACCEPT:
- tp->defer_accept = 0;
+ icsk->icsk_accept_queue.rskq_defer_accept = 0;
if (val > 0) {
/* Translate value in seconds to number of
* retransmits */
- while (tp->defer_accept < 32 &&
+ while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
val > ((TCP_TIMEOUT_INIT / HZ) <<
- tp->defer_accept))
- tp->defer_accept++;
- tp->defer_accept++;
+ icsk->icsk_accept_queue.rskq_defer_accept))
+ icsk->icsk_accept_queue.rskq_defer_accept++;
+ icsk->icsk_accept_queue.rskq_defer_accept++;
}
break;
@@ -2081,16 +1848,16 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
case TCP_QUICKACK:
if (!val) {
- tp->ack.pingpong = 1;
+ icsk->icsk_ack.pingpong = 1;
} else {
- tp->ack.pingpong = 0;
+ icsk->icsk_ack.pingpong = 0;
if ((1 << sk->sk_state) &
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
- tcp_ack_scheduled(tp)) {
- tp->ack.pending |= TCP_ACK_PUSHED;
+ inet_csk_ack_scheduled(sk)) {
+ icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
cleanup_rbuf(sk, 1);
if (!(val & 1))
- tp->ack.pingpong = 1;
+ icsk->icsk_ack.pingpong = 1;
}
}
break;
@@ -2107,15 +1874,16 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
void tcp_get_info(struct sock *sk, struct tcp_info *info)
{
struct tcp_sock *tp = tcp_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
u32 now = tcp_time_stamp;
memset(info, 0, sizeof(*info));
info->tcpi_state = sk->sk_state;
- info->tcpi_ca_state = tp->ca_state;
- info->tcpi_retransmits = tp->retransmits;
- info->tcpi_probes = tp->probes_out;
- info->tcpi_backoff = tp->backoff;
+ info->tcpi_ca_state = icsk->icsk_ca_state;
+ info->tcpi_retransmits = icsk->icsk_retransmits;
+ info->tcpi_probes = icsk->icsk_probes_out;
+ info->tcpi_backoff = icsk->icsk_backoff;
if (tp->rx_opt.tstamp_ok)
info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
@@ -2130,10 +1898,10 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
if (tp->ecn_flags&TCP_ECN_OK)
info->tcpi_options |= TCPI_OPT_ECN;
- info->tcpi_rto = jiffies_to_usecs(tp->rto);
- info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
+ info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
+ info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
info->tcpi_snd_mss = tp->mss_cache;
- info->tcpi_rcv_mss = tp->ack.rcv_mss;
+ info->tcpi_rcv_mss = icsk->icsk_ack.rcv_mss;
info->tcpi_unacked = tp->packets_out;
info->tcpi_sacked = tp->sacked_out;
@@ -2142,7 +1910,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_fackets = tp->fackets_out;
info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
- info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
+ info->tcpi_last_data_recv = jiffies_to_msecs(now - icsk->icsk_ack.lrcvtime);
info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
info->tcpi_pmtu = tp->pmtu_cookie;
@@ -2165,6 +1933,7 @@ EXPORT_SYMBOL_GPL(tcp_get_info);
int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
int __user *optlen)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int val, len;
@@ -2202,7 +1971,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
val = tp->keepalive_probes ? : sysctl_tcp_keepalive_probes;
break;
case TCP_SYNCNT:
- val = tp->syn_retries ? : sysctl_tcp_syn_retries;
+ val = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
break;
case TCP_LINGER2:
val = tp->linger2;
@@ -2210,8 +1979,8 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
val = (val ? : sysctl_tcp_fin_timeout) / HZ;
break;
case TCP_DEFER_ACCEPT:
- val = !tp->defer_accept ? 0 : ((TCP_TIMEOUT_INIT / HZ) <<
- (tp->defer_accept - 1));
+ val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
+ ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
break;
case TCP_WINDOW_CLAMP:
val = tp->window_clamp;
@@ -2232,7 +2001,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
return 0;
}
case TCP_QUICKACK:
- val = !tp->ack.pingpong;
+ val = !icsk->icsk_ack.pingpong;
break;
case TCP_CONGESTION:
@@ -2241,7 +2010,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
len = min_t(unsigned int, len, TCP_CA_NAME_MAX);
if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, tp->ca_ops->name, len))
+ if (copy_to_user(optval, icsk->icsk_ca_ops->name, len))
return -EFAULT;
return 0;
default:
@@ -2278,79 +2047,72 @@ void __init tcp_init(void)
__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
sizeof(skb->cb));
- tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
- sizeof(struct tcp_bind_bucket),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (!tcp_bucket_cachep)
+ tcp_hashinfo.bind_bucket_cachep =
+ kmem_cache_create("tcp_bind_bucket",
+ sizeof(struct inet_bind_bucket), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (!tcp_hashinfo.bind_bucket_cachep)
panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
- tcp_timewait_cachep = kmem_cache_create("tcp_tw_bucket",
- sizeof(struct tcp_tw_bucket),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (!tcp_timewait_cachep)
- panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
-
/* Size and allocate the main established and bind bucket
* hash tables.
*
* The methodology is similar to that of the buffer cache.
*/
- tcp_ehash = (struct tcp_ehash_bucket *)
+ tcp_hashinfo.ehash =
alloc_large_system_hash("TCP established",
- sizeof(struct tcp_ehash_bucket),
+ sizeof(struct inet_ehash_bucket),
thash_entries,
(num_physpages >= 128 * 1024) ?
(25 - PAGE_SHIFT) :
(27 - PAGE_SHIFT),
HASH_HIGHMEM,
- &tcp_ehash_size,
+ &tcp_hashinfo.ehash_size,
NULL,
0);
- tcp_ehash_size = (1 << tcp_ehash_size) >> 1;
- for (i = 0; i < (tcp_ehash_size << 1); i++) {
- rwlock_init(&tcp_ehash[i].lock);
- INIT_HLIST_HEAD(&tcp_ehash[i].chain);
+ tcp_hashinfo.ehash_size = (1 << tcp_hashinfo.ehash_size) >> 1;
+ for (i = 0; i < (tcp_hashinfo.ehash_size << 1); i++) {
+ rwlock_init(&tcp_hashinfo.ehash[i].lock);
+ INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain);
}
- tcp_bhash = (struct tcp_bind_hashbucket *)
+ tcp_hashinfo.bhash =
alloc_large_system_hash("TCP bind",
- sizeof(struct tcp_bind_hashbucket),
- tcp_ehash_size,
+ sizeof(struct inet_bind_hashbucket),
+ tcp_hashinfo.ehash_size,
(num_physpages >= 128 * 1024) ?
(25 - PAGE_SHIFT) :
(27 - PAGE_SHIFT),
HASH_HIGHMEM,
- &tcp_bhash_size,
+ &tcp_hashinfo.bhash_size,
NULL,
64 * 1024);
- tcp_bhash_size = 1 << tcp_bhash_size;
- for (i = 0; i < tcp_bhash_size; i++) {
- spin_lock_init(&tcp_bhash[i].lock);
- INIT_HLIST_HEAD(&tcp_bhash[i].chain);
+ tcp_hashinfo.bhash_size = 1 << tcp_hashinfo.bhash_size;
+ for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
+ spin_lock_init(&tcp_hashinfo.bhash[i].lock);
+ INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
}
/* Try to be a bit smarter and adjust defaults depending
* on available memory.
*/
for (order = 0; ((1 << order) << PAGE_SHIFT) <
- (tcp_bhash_size * sizeof(struct tcp_bind_hashbucket));
+ (tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket));
order++)
;
if (order >= 4) {
sysctl_local_port_range[0] = 32768;
sysctl_local_port_range[1] = 61000;
- sysctl_tcp_max_tw_buckets = 180000;
+ tcp_death_row.sysctl_max_tw_buckets = 180000;
sysctl_tcp_max_orphans = 4096 << (order - 4);
sysctl_max_syn_backlog = 1024;
} else if (order < 3) {
sysctl_local_port_range[0] = 1024 * (3 - order);
- sysctl_tcp_max_tw_buckets >>= (3 - order);
+ tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
sysctl_tcp_max_orphans >>= (3 - order);
sysctl_max_syn_backlog = 128;
}
- tcp_port_rover = sysctl_local_port_range[0] - 1;
+ tcp_hashinfo.port_rover = sysctl_local_port_range[0] - 1;
sysctl_tcp_mem[0] = 768 << order;
sysctl_tcp_mem[1] = 1024 << order;
@@ -2365,14 +2127,12 @@ void __init tcp_init(void)
printk(KERN_INFO "TCP: Hash tables configured "
"(established %d bind %d)\n",
- tcp_ehash_size << 1, tcp_bhash_size);
+ tcp_hashinfo.ehash_size << 1, tcp_hashinfo.bhash_size);
tcp_register_congestion_control(&tcp_reno);
}
-EXPORT_SYMBOL(tcp_accept);
EXPORT_SYMBOL(tcp_close);
-EXPORT_SYMBOL(tcp_destroy_sock);
EXPORT_SYMBOL(tcp_disconnect);
EXPORT_SYMBOL(tcp_getsockopt);
EXPORT_SYMBOL(tcp_ioctl);
@@ -2384,4 +2144,3 @@ EXPORT_SYMBOL(tcp_sendpage);
EXPORT_SYMBOL(tcp_setsockopt);
EXPORT_SYMBOL(tcp_shutdown);
EXPORT_SYMBOL(tcp_statistics);
-EXPORT_SYMBOL(tcp_timewait_cachep);
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index ec38d45d6649..b940346de4e7 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -86,11 +86,11 @@ static inline void bictcp_reset(struct bictcp *ca)
ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
}
-static void bictcp_init(struct tcp_sock *tp)
+static void bictcp_init(struct sock *sk)
{
- bictcp_reset(tcp_ca(tp));
+ bictcp_reset(inet_csk_ca(sk));
if (initial_ssthresh)
- tp->snd_ssthresh = initial_ssthresh;
+ tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
}
/*
@@ -156,9 +156,10 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
/* Detect low utilization in congestion avoidance */
-static inline void bictcp_low_utilization(struct tcp_sock *tp, int flag)
+static inline void bictcp_low_utilization(struct sock *sk, int flag)
{
- struct bictcp *ca = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
u32 dist, delay;
/* No time stamp */
@@ -208,12 +209,13 @@ static inline void bictcp_low_utilization(struct tcp_sock *tp, int flag)
}
-static void bictcp_cong_avoid(struct tcp_sock *tp, u32 ack,
+static void bictcp_cong_avoid(struct sock *sk, u32 ack,
u32 seq_rtt, u32 in_flight, int data_acked)
{
- struct bictcp *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
- bictcp_low_utilization(tp, data_acked);
+ bictcp_low_utilization(sk, data_acked);
if (in_flight < tp->snd_cwnd)
return;
@@ -242,9 +244,10 @@ static void bictcp_cong_avoid(struct tcp_sock *tp, u32 ack,
* behave like Reno until low_window is reached,
* then increase congestion window slowly
*/
-static u32 bictcp_recalc_ssthresh(struct tcp_sock *tp)
+static u32 bictcp_recalc_ssthresh(struct sock *sk)
{
- struct bictcp *ca = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
ca->epoch_start = 0; /* end of epoch */
@@ -269,31 +272,34 @@ static u32 bictcp_recalc_ssthresh(struct tcp_sock *tp)
return max((tp->snd_cwnd * beta) / BICTCP_BETA_SCALE, 2U);
}
-static u32 bictcp_undo_cwnd(struct tcp_sock *tp)
+static u32 bictcp_undo_cwnd(struct sock *sk)
{
- struct bictcp *ca = tcp_ca(tp);
-
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct bictcp *ca = inet_csk_ca(sk);
return max(tp->snd_cwnd, ca->last_max_cwnd);
}
-static u32 bictcp_min_cwnd(struct tcp_sock *tp)
+static u32 bictcp_min_cwnd(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return tp->snd_ssthresh;
}
-static void bictcp_state(struct tcp_sock *tp, u8 new_state)
+static void bictcp_state(struct sock *sk, u8 new_state)
{
if (new_state == TCP_CA_Loss)
- bictcp_reset(tcp_ca(tp));
+ bictcp_reset(inet_csk_ca(sk));
}
/* Track delayed acknowledgement ratio using sliding window
* ratio = (15*ratio + sample) / 16
*/
-static void bictcp_acked(struct tcp_sock *tp, u32 cnt)
+static void bictcp_acked(struct sock *sk, u32 cnt)
{
- if (cnt > 0 && tp->ca_state == TCP_CA_Open) {
- struct bictcp *ca = tcp_ca(tp);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (cnt > 0 && icsk->icsk_ca_state == TCP_CA_Open) {
+ struct bictcp *ca = inet_csk_ca(sk);
cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT;
ca->delayed_ack += cnt;
}
@@ -314,7 +320,7 @@ static struct tcp_congestion_ops bictcp = {
static int __init bictcp_register(void)
{
- BUG_ON(sizeof(struct bictcp) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
return tcp_register_congestion_control(&bictcp);
}
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 4970d10a7785..bbf2d6624e89 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -73,33 +73,36 @@ void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca)
EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control);
/* Assign choice of congestion control. */
-void tcp_init_congestion_control(struct tcp_sock *tp)
+void tcp_init_congestion_control(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_congestion_ops *ca;
- if (tp->ca_ops != &tcp_init_congestion_ops)
+ if (icsk->icsk_ca_ops != &tcp_init_congestion_ops)
return;
rcu_read_lock();
list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
if (try_module_get(ca->owner)) {
- tp->ca_ops = ca;
+ icsk->icsk_ca_ops = ca;
break;
}
}
rcu_read_unlock();
- if (tp->ca_ops->init)
- tp->ca_ops->init(tp);
+ if (icsk->icsk_ca_ops->init)
+ icsk->icsk_ca_ops->init(sk);
}
/* Manage refcounts on socket close. */
-void tcp_cleanup_congestion_control(struct tcp_sock *tp)
+void tcp_cleanup_congestion_control(struct sock *sk)
{
- if (tp->ca_ops->release)
- tp->ca_ops->release(tp);
- module_put(tp->ca_ops->owner);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->release)
+ icsk->icsk_ca_ops->release(sk);
+ module_put(icsk->icsk_ca_ops->owner);
}
/* Used by sysctl to change default congestion control */
@@ -143,14 +146,15 @@ void tcp_get_default_congestion_control(char *name)
}
/* Change congestion control for socket */
-int tcp_set_congestion_control(struct tcp_sock *tp, const char *name)
+int tcp_set_congestion_control(struct sock *sk, const char *name)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_congestion_ops *ca;
int err = 0;
rcu_read_lock();
ca = tcp_ca_find(name);
- if (ca == tp->ca_ops)
+ if (ca == icsk->icsk_ca_ops)
goto out;
if (!ca)
@@ -160,10 +164,10 @@ int tcp_set_congestion_control(struct tcp_sock *tp, const char *name)
err = -EBUSY;
else {
- tcp_cleanup_congestion_control(tp);
- tp->ca_ops = ca;
- if (tp->ca_ops->init)
- tp->ca_ops->init(tp);
+ tcp_cleanup_congestion_control(sk);
+ icsk->icsk_ca_ops = ca;
+ if (icsk->icsk_ca_ops->init)
+ icsk->icsk_ca_ops->init(sk);
}
out:
rcu_read_unlock();
@@ -177,9 +181,11 @@ int tcp_set_congestion_control(struct tcp_sock *tp, const char *name)
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
-void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt, u32 in_flight,
+void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
int flag)
{
+ struct tcp_sock *tp = tcp_sk(sk);
+
if (in_flight < tp->snd_cwnd)
return;
@@ -202,15 +208,17 @@ void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt, u32 in_flight,
EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
/* Slow start threshold is half the congestion window (min 2) */
-u32 tcp_reno_ssthresh(struct tcp_sock *tp)
+u32 tcp_reno_ssthresh(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return max(tp->snd_cwnd >> 1U, 2U);
}
EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
/* Lower bound on congestion window. */
-u32 tcp_reno_min_cwnd(struct tcp_sock *tp)
+u32 tcp_reno_min_cwnd(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return tp->snd_ssthresh/2;
}
EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd);
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index f66945cb158f..c148c1081880 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -1,5 +1,5 @@
/*
- * tcp_diag.c Module for monitoring TCP sockets.
+ * tcp_diag.c Module for monitoring TCP transport protocols sockets.
*
* Version: $Id: tcp_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $
*
@@ -12,779 +12,43 @@
*/
#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/random.h>
-#include <linux/cache.h>
-#include <linux/init.h>
-#include <linux/time.h>
-
-#include <net/icmp.h>
-#include <net/tcp.h>
-#include <net/ipv6.h>
-#include <net/inet_common.h>
-
-#include <linux/inet.h>
-#include <linux/stddef.h>
-
-#include <linux/tcp_diag.h>
-struct tcpdiag_entry
-{
- u32 *saddr;
- u32 *daddr;
- u16 sport;
- u16 dport;
- u16 family;
- u16 userlocks;
-};
+#include <linux/module.h>
+#include <linux/inet_diag.h>
-static struct sock *tcpnl;
+#include <linux/tcp.h>
-#define TCPDIAG_PUT(skb, attrtype, attrlen) \
- RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
+#include <net/tcp.h>
-static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
- int ext, u32 pid, u32 seq, u16 nlmsg_flags)
+static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+ void *_info)
{
- struct inet_sock *inet = inet_sk(sk);
- struct tcp_sock *tp = tcp_sk(sk);
- struct tcpdiagmsg *r;
- struct nlmsghdr *nlh;
- struct tcp_info *info = NULL;
- struct tcpdiag_meminfo *minfo = NULL;
- unsigned char *b = skb->tail;
-
- nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
- nlh->nlmsg_flags = nlmsg_flags;
- r = NLMSG_DATA(nlh);
- if (sk->sk_state != TCP_TIME_WAIT) {
- if (ext & (1<<(TCPDIAG_MEMINFO-1)))
- minfo = TCPDIAG_PUT(skb, TCPDIAG_MEMINFO, sizeof(*minfo));
- if (ext & (1<<(TCPDIAG_INFO-1)))
- info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
-
- if (ext & (1<<(TCPDIAG_CONG-1))) {
- size_t len = strlen(tp->ca_ops->name);
- strcpy(TCPDIAG_PUT(skb, TCPDIAG_CONG, len+1),
- tp->ca_ops->name);
- }
- }
- r->tcpdiag_family = sk->sk_family;
- r->tcpdiag_state = sk->sk_state;
- r->tcpdiag_timer = 0;
- r->tcpdiag_retrans = 0;
-
- r->id.tcpdiag_if = sk->sk_bound_dev_if;
- r->id.tcpdiag_cookie[0] = (u32)(unsigned long)sk;
- r->id.tcpdiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1);
-
- if (r->tcpdiag_state == TCP_TIME_WAIT) {
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket*)sk;
- long tmo = tw->tw_ttd - jiffies;
- if (tmo < 0)
- tmo = 0;
-
- r->id.tcpdiag_sport = tw->tw_sport;
- r->id.tcpdiag_dport = tw->tw_dport;
- r->id.tcpdiag_src[0] = tw->tw_rcv_saddr;
- r->id.tcpdiag_dst[0] = tw->tw_daddr;
- r->tcpdiag_state = tw->tw_substate;
- r->tcpdiag_timer = 3;
- r->tcpdiag_expires = (tmo*1000+HZ-1)/HZ;
- r->tcpdiag_rqueue = 0;
- r->tcpdiag_wqueue = 0;
- r->tcpdiag_uid = 0;
- r->tcpdiag_inode = 0;
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- if (r->tcpdiag_family == AF_INET6) {
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
- &tw->tw_v6_rcv_saddr);
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
- &tw->tw_v6_daddr);
- }
-#endif
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
- }
-
- r->id.tcpdiag_sport = inet->sport;
- r->id.tcpdiag_dport = inet->dport;
- r->id.tcpdiag_src[0] = inet->rcv_saddr;
- r->id.tcpdiag_dst[0] = inet->daddr;
-
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- if (r->tcpdiag_family == AF_INET6) {
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
- &np->rcv_saddr);
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
- &np->daddr);
- }
-#endif
-
-#define EXPIRES_IN_MS(tmo) ((tmo-jiffies)*1000+HZ-1)/HZ
-
- if (tp->pending == TCP_TIME_RETRANS) {
- r->tcpdiag_timer = 1;
- r->tcpdiag_retrans = tp->retransmits;
- r->tcpdiag_expires = EXPIRES_IN_MS(tp->timeout);
- } else if (tp->pending == TCP_TIME_PROBE0) {
- r->tcpdiag_timer = 4;
- r->tcpdiag_retrans = tp->probes_out;
- r->tcpdiag_expires = EXPIRES_IN_MS(tp->timeout);
- } else if (timer_pending(&sk->sk_timer)) {
- r->tcpdiag_timer = 2;
- r->tcpdiag_retrans = tp->probes_out;
- r->tcpdiag_expires = EXPIRES_IN_MS(sk->sk_timer.expires);
- } else {
- r->tcpdiag_timer = 0;
- r->tcpdiag_expires = 0;
- }
-#undef EXPIRES_IN_MS
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_info *info = _info;
- r->tcpdiag_rqueue = tp->rcv_nxt - tp->copied_seq;
- r->tcpdiag_wqueue = tp->write_seq - tp->snd_una;
- r->tcpdiag_uid = sock_i_uid(sk);
- r->tcpdiag_inode = sock_i_ino(sk);
-
- if (minfo) {
- minfo->tcpdiag_rmem = atomic_read(&sk->sk_rmem_alloc);
- minfo->tcpdiag_wmem = sk->sk_wmem_queued;
- minfo->tcpdiag_fmem = sk->sk_forward_alloc;
- minfo->tcpdiag_tmem = atomic_read(&sk->sk_wmem_alloc);
- }
-
- if (info)
+ r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
+ r->idiag_wqueue = tp->write_seq - tp->snd_una;
+ if (info != NULL)
tcp_get_info(sk, info);
-
- if (sk->sk_state < TCP_TIME_WAIT && tp->ca_ops->get_info)
- tp->ca_ops->get_info(tp, ext, skb);
-
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
-
-rtattr_failure:
-nlmsg_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,
- int dif);
-#ifdef CONFIG_IP_TCPDIAG_IPV6
-extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 dport,
- int dif);
-#else
-static inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 dport,
- int dif)
-{
- return NULL;
-}
-#endif
-
-static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
-{
- int err;
- struct sock *sk;
- struct tcpdiagreq *req = NLMSG_DATA(nlh);
- struct sk_buff *rep;
-
- if (req->tcpdiag_family == AF_INET) {
- sk = tcp_v4_lookup(req->id.tcpdiag_dst[0], req->id.tcpdiag_dport,
- req->id.tcpdiag_src[0], req->id.tcpdiag_sport,
- req->id.tcpdiag_if);
- }
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- else if (req->tcpdiag_family == AF_INET6) {
- sk = tcp_v6_lookup((struct in6_addr*)req->id.tcpdiag_dst, req->id.tcpdiag_dport,
- (struct in6_addr*)req->id.tcpdiag_src, req->id.tcpdiag_sport,
- req->id.tcpdiag_if);
- }
-#endif
- else {
- return -EINVAL;
- }
-
- if (sk == NULL)
- return -ENOENT;
-
- err = -ESTALE;
- if ((req->id.tcpdiag_cookie[0] != TCPDIAG_NOCOOKIE ||
- req->id.tcpdiag_cookie[1] != TCPDIAG_NOCOOKIE) &&
- ((u32)(unsigned long)sk != req->id.tcpdiag_cookie[0] ||
- (u32)((((unsigned long)sk) >> 31) >> 1) != req->id.tcpdiag_cookie[1]))
- goto out;
-
- err = -ENOMEM;
- rep = alloc_skb(NLMSG_SPACE(sizeof(struct tcpdiagmsg)+
- sizeof(struct tcpdiag_meminfo)+
- sizeof(struct tcp_info)+64), GFP_KERNEL);
- if (!rep)
- goto out;
-
- if (tcpdiag_fill(rep, sk, req->tcpdiag_ext,
- NETLINK_CB(in_skb).pid,
- nlh->nlmsg_seq, 0) <= 0)
- BUG();
-
- err = netlink_unicast(tcpnl, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
- if (err > 0)
- err = 0;
-
-out:
- if (sk) {
- if (sk->sk_state == TCP_TIME_WAIT)
- tcp_tw_put((struct tcp_tw_bucket*)sk);
- else
- sock_put(sk);
- }
- return err;
-}
-
-static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
-{
- int words = bits >> 5;
-
- bits &= 0x1f;
-
- if (words) {
- if (memcmp(a1, a2, words << 2))
- return 0;
- }
- if (bits) {
- __u32 w1, w2;
- __u32 mask;
-
- w1 = a1[words];
- w2 = a2[words];
-
- mask = htonl((0xffffffff) << (32 - bits));
-
- if ((w1 ^ w2) & mask)
- return 0;
- }
-
- return 1;
-}
-
-
-static int tcpdiag_bc_run(const void *bc, int len,
- const struct tcpdiag_entry *entry)
-{
- while (len > 0) {
- int yes = 1;
- const struct tcpdiag_bc_op *op = bc;
-
- switch (op->code) {
- case TCPDIAG_BC_NOP:
- break;
- case TCPDIAG_BC_JMP:
- yes = 0;
- break;
- case TCPDIAG_BC_S_GE:
- yes = entry->sport >= op[1].no;
- break;
- case TCPDIAG_BC_S_LE:
- yes = entry->dport <= op[1].no;
- break;
- case TCPDIAG_BC_D_GE:
- yes = entry->dport >= op[1].no;
- break;
- case TCPDIAG_BC_D_LE:
- yes = entry->dport <= op[1].no;
- break;
- case TCPDIAG_BC_AUTO:
- yes = !(entry->userlocks & SOCK_BINDPORT_LOCK);
- break;
- case TCPDIAG_BC_S_COND:
- case TCPDIAG_BC_D_COND:
- {
- struct tcpdiag_hostcond *cond = (struct tcpdiag_hostcond*)(op+1);
- u32 *addr;
-
- if (cond->port != -1 &&
- cond->port != (op->code == TCPDIAG_BC_S_COND ?
- entry->sport : entry->dport)) {
- yes = 0;
- break;
- }
-
- if (cond->prefix_len == 0)
- break;
-
- if (op->code == TCPDIAG_BC_S_COND)
- addr = entry->saddr;
- else
- addr = entry->daddr;
-
- if (bitstring_match(addr, cond->addr, cond->prefix_len))
- break;
- if (entry->family == AF_INET6 &&
- cond->family == AF_INET) {
- if (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == htonl(0xffff) &&
- bitstring_match(addr+3, cond->addr, cond->prefix_len))
- break;
- }
- yes = 0;
- break;
- }
- }
-
- if (yes) {
- len -= op->yes;
- bc += op->yes;
- } else {
- len -= op->no;
- bc += op->no;
- }
- }
- return (len == 0);
-}
-
-static int valid_cc(const void *bc, int len, int cc)
-{
- while (len >= 0) {
- const struct tcpdiag_bc_op *op = bc;
-
- if (cc > len)
- return 0;
- if (cc == len)
- return 1;
- if (op->yes < 4)
- return 0;
- len -= op->yes;
- bc += op->yes;
- }
- return 0;
-}
-
-static int tcpdiag_bc_audit(const void *bytecode, int bytecode_len)
-{
- const unsigned char *bc = bytecode;
- int len = bytecode_len;
-
- while (len > 0) {
- struct tcpdiag_bc_op *op = (struct tcpdiag_bc_op*)bc;
-
-//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
- switch (op->code) {
- case TCPDIAG_BC_AUTO:
- case TCPDIAG_BC_S_COND:
- case TCPDIAG_BC_D_COND:
- case TCPDIAG_BC_S_GE:
- case TCPDIAG_BC_S_LE:
- case TCPDIAG_BC_D_GE:
- case TCPDIAG_BC_D_LE:
- if (op->yes < 4 || op->yes > len+4)
- return -EINVAL;
- case TCPDIAG_BC_JMP:
- if (op->no < 4 || op->no > len+4)
- return -EINVAL;
- if (op->no < len &&
- !valid_cc(bytecode, bytecode_len, len-op->no))
- return -EINVAL;
- break;
- case TCPDIAG_BC_NOP:
- if (op->yes < 4 || op->yes > len+4)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- bc += op->yes;
- len -= op->yes;
- }
- return len == 0 ? 0 : -EINVAL;
-}
-
-static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk,
- struct netlink_callback *cb)
-{
- struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
-
- if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
- struct tcpdiag_entry entry;
- struct rtattr *bc = (struct rtattr *)(r + 1);
- struct inet_sock *inet = inet_sk(sk);
-
- entry.family = sk->sk_family;
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- if (entry.family == AF_INET6) {
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- entry.saddr = np->rcv_saddr.s6_addr32;
- entry.daddr = np->daddr.s6_addr32;
- } else
-#endif
- {
- entry.saddr = &inet->rcv_saddr;
- entry.daddr = &inet->daddr;
- }
- entry.sport = inet->num;
- entry.dport = ntohs(inet->dport);
- entry.userlocks = sk->sk_userlocks;
-
- if (!tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
- return 0;
- }
-
- return tcpdiag_fill(skb, sk, r->tcpdiag_ext, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI);
}
-static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
- struct request_sock *req,
- u32 pid, u32 seq)
-{
- const struct inet_request_sock *ireq = inet_rsk(req);
- struct inet_sock *inet = inet_sk(sk);
- unsigned char *b = skb->tail;
- struct tcpdiagmsg *r;
- struct nlmsghdr *nlh;
- long tmo;
-
- nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
- nlh->nlmsg_flags = NLM_F_MULTI;
- r = NLMSG_DATA(nlh);
-
- r->tcpdiag_family = sk->sk_family;
- r->tcpdiag_state = TCP_SYN_RECV;
- r->tcpdiag_timer = 1;
- r->tcpdiag_retrans = req->retrans;
-
- r->id.tcpdiag_if = sk->sk_bound_dev_if;
- r->id.tcpdiag_cookie[0] = (u32)(unsigned long)req;
- r->id.tcpdiag_cookie[1] = (u32)(((unsigned long)req >> 31) >> 1);
-
- tmo = req->expires - jiffies;
- if (tmo < 0)
- tmo = 0;
-
- r->id.tcpdiag_sport = inet->sport;
- r->id.tcpdiag_dport = ireq->rmt_port;
- r->id.tcpdiag_src[0] = ireq->loc_addr;
- r->id.tcpdiag_dst[0] = ireq->rmt_addr;
- r->tcpdiag_expires = jiffies_to_msecs(tmo),
- r->tcpdiag_rqueue = 0;
- r->tcpdiag_wqueue = 0;
- r->tcpdiag_uid = sock_i_uid(sk);
- r->tcpdiag_inode = 0;
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- if (r->tcpdiag_family == AF_INET6) {
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
- &tcp6_rsk(req)->loc_addr);
- ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
- &tcp6_rsk(req)->rmt_addr);
- }
-#endif
- nlh->nlmsg_len = skb->tail - b;
-
- return skb->len;
-
-nlmsg_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
- struct netlink_callback *cb)
-{
- struct tcpdiag_entry entry;
- struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
- struct tcp_sock *tp = tcp_sk(sk);
- struct listen_sock *lopt;
- struct rtattr *bc = NULL;
- struct inet_sock *inet = inet_sk(sk);
- int j, s_j;
- int reqnum, s_reqnum;
- int err = 0;
-
- s_j = cb->args[3];
- s_reqnum = cb->args[4];
-
- if (s_j > 0)
- s_j--;
-
- entry.family = sk->sk_family;
-
- read_lock_bh(&tp->accept_queue.syn_wait_lock);
-
- lopt = tp->accept_queue.listen_opt;
- if (!lopt || !lopt->qlen)
- goto out;
-
- if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
- bc = (struct rtattr *)(r + 1);
- entry.sport = inet->num;
- entry.userlocks = sk->sk_userlocks;
- }
-
- for (j = s_j; j < TCP_SYNQ_HSIZE; j++) {
- struct request_sock *req, *head = lopt->syn_table[j];
-
- reqnum = 0;
- for (req = head; req; reqnum++, req = req->dl_next) {
- struct inet_request_sock *ireq = inet_rsk(req);
-
- if (reqnum < s_reqnum)
- continue;
- if (r->id.tcpdiag_dport != ireq->rmt_port &&
- r->id.tcpdiag_dport)
- continue;
-
- if (bc) {
- entry.saddr =
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- (entry.family == AF_INET6) ?
- tcp6_rsk(req)->loc_addr.s6_addr32 :
-#endif
- &ireq->loc_addr;
- entry.daddr =
-#ifdef CONFIG_IP_TCPDIAG_IPV6
- (entry.family == AF_INET6) ?
- tcp6_rsk(req)->rmt_addr.s6_addr32 :
-#endif
- &ireq->rmt_addr;
- entry.dport = ntohs(ireq->rmt_port);
-
- if (!tcpdiag_bc_run(RTA_DATA(bc),
- RTA_PAYLOAD(bc), &entry))
- continue;
- }
-
- err = tcpdiag_fill_req(skb, sk, req,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq);
- if (err < 0) {
- cb->args[3] = j + 1;
- cb->args[4] = reqnum;
- goto out;
- }
- }
-
- s_reqnum = 0;
- }
-
-out:
- read_unlock_bh(&tp->accept_queue.syn_wait_lock);
-
- return err;
-}
-
-static int tcpdiag_dump(struct sk_buff *skb, struct netlink_callback *cb)
-{
- int i, num;
- int s_i, s_num;
- struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
-
- s_i = cb->args[1];
- s_num = num = cb->args[2];
-
- if (cb->args[0] == 0) {
- if (!(r->tcpdiag_states&(TCPF_LISTEN|TCPF_SYN_RECV)))
- goto skip_listen_ht;
- tcp_listen_lock();
- for (i = s_i; i < TCP_LHTABLE_SIZE; i++) {
- struct sock *sk;
- struct hlist_node *node;
-
- num = 0;
- sk_for_each(sk, node, &tcp_listening_hash[i]) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (num < s_num) {
- num++;
- continue;
- }
-
- if (r->id.tcpdiag_sport != inet->sport &&
- r->id.tcpdiag_sport)
- goto next_listen;
-
- if (!(r->tcpdiag_states&TCPF_LISTEN) ||
- r->id.tcpdiag_dport ||
- cb->args[3] > 0)
- goto syn_recv;
-
- if (tcpdiag_dump_sock(skb, sk, cb) < 0) {
- tcp_listen_unlock();
- goto done;
- }
-
-syn_recv:
- if (!(r->tcpdiag_states&TCPF_SYN_RECV))
- goto next_listen;
-
- if (tcpdiag_dump_reqs(skb, sk, cb) < 0) {
- tcp_listen_unlock();
- goto done;
- }
-
-next_listen:
- cb->args[3] = 0;
- cb->args[4] = 0;
- ++num;
- }
-
- s_num = 0;
- cb->args[3] = 0;
- cb->args[4] = 0;
- }
- tcp_listen_unlock();
-skip_listen_ht:
- cb->args[0] = 1;
- s_i = num = s_num = 0;
- }
-
- if (!(r->tcpdiag_states&~(TCPF_LISTEN|TCPF_SYN_RECV)))
- return skb->len;
-
- for (i = s_i; i < tcp_ehash_size; i++) {
- struct tcp_ehash_bucket *head = &tcp_ehash[i];
- struct sock *sk;
- struct hlist_node *node;
-
- if (i > s_i)
- s_num = 0;
-
- read_lock_bh(&head->lock);
-
- num = 0;
- sk_for_each(sk, node, &head->chain) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (num < s_num)
- goto next_normal;
- if (!(r->tcpdiag_states & (1 << sk->sk_state)))
- goto next_normal;
- if (r->id.tcpdiag_sport != inet->sport &&
- r->id.tcpdiag_sport)
- goto next_normal;
- if (r->id.tcpdiag_dport != inet->dport && r->id.tcpdiag_dport)
- goto next_normal;
- if (tcpdiag_dump_sock(skb, sk, cb) < 0) {
- read_unlock_bh(&head->lock);
- goto done;
- }
-next_normal:
- ++num;
- }
-
- if (r->tcpdiag_states&TCPF_TIME_WAIT) {
- sk_for_each(sk, node,
- &tcp_ehash[i + tcp_ehash_size].chain) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (num < s_num)
- goto next_dying;
- if (r->id.tcpdiag_sport != inet->sport &&
- r->id.tcpdiag_sport)
- goto next_dying;
- if (r->id.tcpdiag_dport != inet->dport &&
- r->id.tcpdiag_dport)
- goto next_dying;
- if (tcpdiag_dump_sock(skb, sk, cb) < 0) {
- read_unlock_bh(&head->lock);
- goto done;
- }
-next_dying:
- ++num;
- }
- }
- read_unlock_bh(&head->lock);
- }
-
-done:
- cb->args[1] = i;
- cb->args[2] = num;
- return skb->len;
-}
-
-static int tcpdiag_dump_done(struct netlink_callback *cb)
-{
- return 0;
-}
-
-
-static __inline__ int
-tcpdiag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
-{
- if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
- return 0;
-
- if (nlh->nlmsg_type != TCPDIAG_GETSOCK)
- goto err_inval;
-
- if (NLMSG_LENGTH(sizeof(struct tcpdiagreq)) > skb->len)
- goto err_inval;
-
- if (nlh->nlmsg_flags&NLM_F_DUMP) {
- if (nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(struct tcpdiagreq))) {
- struct rtattr *rta = (struct rtattr*)(NLMSG_DATA(nlh) + sizeof(struct tcpdiagreq));
- if (rta->rta_type != TCPDIAG_REQ_BYTECODE ||
- rta->rta_len < 8 ||
- rta->rta_len > nlh->nlmsg_len - NLMSG_SPACE(sizeof(struct tcpdiagreq)))
- goto err_inval;
- if (tcpdiag_bc_audit(RTA_DATA(rta), RTA_PAYLOAD(rta)))
- goto err_inval;
- }
- return netlink_dump_start(tcpnl, skb, nlh,
- tcpdiag_dump,
- tcpdiag_dump_done);
- } else {
- return tcpdiag_get_exact(skb, nlh);
- }
-
-err_inval:
- return -EINVAL;
-}
-
-
-static inline void tcpdiag_rcv_skb(struct sk_buff *skb)
-{
- int err;
- struct nlmsghdr * nlh;
-
- if (skb->len >= NLMSG_SPACE(0)) {
- nlh = (struct nlmsghdr *)skb->data;
- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
- return;
- err = tcpdiag_rcv_msg(skb, nlh);
- if (err || nlh->nlmsg_flags & NLM_F_ACK)
- netlink_ack(skb, nlh, err);
- }
-}
-
-static void tcpdiag_rcv(struct sock *sk, int len)
-{
- struct sk_buff *skb;
- unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
-
- while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) {
- tcpdiag_rcv_skb(skb);
- kfree_skb(skb);
- }
-}
+static struct inet_diag_handler tcp_diag_handler = {
+ .idiag_hashinfo = &tcp_hashinfo,
+ .idiag_get_info = tcp_diag_get_info,
+ .idiag_type = TCPDIAG_GETSOCK,
+ .idiag_info_size = sizeof(struct tcp_info),
+};
-static int __init tcpdiag_init(void)
+static int __init tcp_diag_init(void)
{
- tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv);
- if (tcpnl == NULL)
- return -ENOMEM;
- return 0;
+ return inet_diag_register(&tcp_diag_handler);
}
-static void __exit tcpdiag_exit(void)
+static void __exit tcp_diag_exit(void)
{
- sock_release(tcpnl->sk_socket);
+ inet_diag_unregister(&tcp_diag_handler);
}
-module_init(tcpdiag_init);
-module_exit(tcpdiag_exit);
+module_init(tcp_diag_init);
+module_exit(tcp_diag_exit);
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index 36c51f8136bf..6acc04bde080 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -98,9 +98,10 @@ struct hstcp {
u32 ai;
};
-static void hstcp_init(struct tcp_sock *tp)
+static void hstcp_init(struct sock *sk)
{
- struct hstcp *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct hstcp *ca = inet_csk_ca(sk);
ca->ai = 0;
@@ -109,10 +110,11 @@ static void hstcp_init(struct tcp_sock *tp)
tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
}
-static void hstcp_cong_avoid(struct tcp_sock *tp, u32 adk, u32 rtt,
+static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
u32 in_flight, int good)
{
- struct hstcp *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct hstcp *ca = inet_csk_ca(sk);
if (in_flight < tp->snd_cwnd)
return;
@@ -143,9 +145,10 @@ static void hstcp_cong_avoid(struct tcp_sock *tp, u32 adk, u32 rtt,
}
}
-static u32 hstcp_ssthresh(struct tcp_sock *tp)
+static u32 hstcp_ssthresh(struct sock *sk)
{
- struct hstcp *ca = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct hstcp *ca = inet_csk_ca(sk);
/* Do multiplicative decrease */
return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
@@ -164,7 +167,7 @@ static struct tcp_congestion_ops tcp_highspeed = {
static int __init hstcp_register(void)
{
- BUG_ON(sizeof(struct hstcp) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
return tcp_register_congestion_control(&tcp_highspeed);
}
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 40168275acf9..e47b37984e95 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -55,18 +55,21 @@ static inline void htcp_reset(struct htcp *ca)
ca->snd_cwnd_cnt2 = 0;
}
-static u32 htcp_cwnd_undo(struct tcp_sock *tp)
+static u32 htcp_cwnd_undo(struct sock *sk)
{
- struct htcp *ca = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct htcp *ca = inet_csk_ca(sk);
ca->ccount = ca->undo_ccount;
ca->maxRTT = ca->undo_maxRTT;
ca->old_maxB = ca->undo_old_maxB;
return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
}
-static inline void measure_rtt(struct tcp_sock *tp)
+static inline void measure_rtt(struct sock *sk)
{
- struct htcp *ca = tcp_ca(tp);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct htcp *ca = inet_csk_ca(sk);
u32 srtt = tp->srtt>>3;
/* keep track of minimum RTT seen so far, minRTT is zero at first */
@@ -74,7 +77,7 @@ static inline void measure_rtt(struct tcp_sock *tp)
ca->minRTT = srtt;
/* max RTT */
- if (tp->ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) {
+ if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) {
if (ca->maxRTT < ca->minRTT)
ca->maxRTT = ca->minRTT;
if (ca->maxRTT < srtt && srtt <= ca->maxRTT+HZ/50)
@@ -82,13 +85,16 @@ static inline void measure_rtt(struct tcp_sock *tp)
}
}
-static void measure_achieved_throughput(struct tcp_sock *tp, u32 pkts_acked)
+static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked)
{
- struct htcp *ca = tcp_ca(tp);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct htcp *ca = inet_csk_ca(sk);
u32 now = tcp_time_stamp;
/* achieved throughput calculations */
- if (tp->ca_state != TCP_CA_Open && tp->ca_state != TCP_CA_Disorder) {
+ if (icsk->icsk_ca_state != TCP_CA_Open &&
+ icsk->icsk_ca_state != TCP_CA_Disorder) {
ca->packetcount = 0;
ca->lasttime = now;
return;
@@ -173,9 +179,9 @@ static inline void htcp_alpha_update(struct htcp *ca)
* that point do we really have a real sense of maxRTT (the queues en route
* were getting just too full now).
*/
-static void htcp_param_update(struct tcp_sock *tp)
+static void htcp_param_update(struct sock *sk)
{
- struct htcp *ca = tcp_ca(tp);
+ struct htcp *ca = inet_csk_ca(sk);
u32 minRTT = ca->minRTT;
u32 maxRTT = ca->maxRTT;
@@ -187,17 +193,19 @@ static void htcp_param_update(struct tcp_sock *tp)
ca->maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
}
-static u32 htcp_recalc_ssthresh(struct tcp_sock *tp)
+static u32 htcp_recalc_ssthresh(struct sock *sk)
{
- struct htcp *ca = tcp_ca(tp);
- htcp_param_update(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct htcp *ca = inet_csk_ca(sk);
+ htcp_param_update(sk);
return max((tp->snd_cwnd * ca->beta) >> 7, 2U);
}
-static void htcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
u32 in_flight, int data_acked)
{
- struct htcp *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct htcp *ca = inet_csk_ca(sk);
if (in_flight < tp->snd_cwnd)
return;
@@ -207,7 +215,7 @@ static void htcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
if (tp->snd_cwnd < tp->snd_cwnd_clamp)
tp->snd_cwnd++;
} else {
- measure_rtt(tp);
+ measure_rtt(sk);
/* keep track of number of round-trip times since last backoff event */
if (ca->snd_cwnd_cnt2++ > tp->snd_cwnd) {
@@ -229,28 +237,29 @@ static void htcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
}
/* Lower bound on congestion window. */
-static u32 htcp_min_cwnd(struct tcp_sock *tp)
+static u32 htcp_min_cwnd(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return tp->snd_ssthresh;
}
-static void htcp_init(struct tcp_sock *tp)
+static void htcp_init(struct sock *sk)
{
- struct htcp *ca = tcp_ca(tp);
+ struct htcp *ca = inet_csk_ca(sk);
memset(ca, 0, sizeof(struct htcp));
ca->alpha = ALPHA_BASE;
ca->beta = BETA_MIN;
}
-static void htcp_state(struct tcp_sock *tp, u8 new_state)
+static void htcp_state(struct sock *sk, u8 new_state)
{
switch (new_state) {
case TCP_CA_CWR:
case TCP_CA_Recovery:
case TCP_CA_Loss:
- htcp_reset(tcp_ca(tp));
+ htcp_reset(inet_csk_ca(sk));
break;
}
}
@@ -269,7 +278,7 @@ static struct tcp_congestion_ops htcp = {
static int __init htcp_register(void)
{
- BUG_ON(sizeof(struct htcp) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE);
BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
if (!use_bandwidth_switch)
htcp.pkts_acked = NULL;
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index 13a66342c304..77add63623df 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -33,19 +33,20 @@ MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)");
/* This is called to refresh values for hybla parameters */
-static inline void hybla_recalc_param (struct tcp_sock *tp)
+static inline void hybla_recalc_param (struct sock *sk)
{
- struct hybla *ca = tcp_ca(tp);
+ struct hybla *ca = inet_csk_ca(sk);
- ca->rho_3ls = max_t(u32, tp->srtt / msecs_to_jiffies(rtt0), 8);
+ ca->rho_3ls = max_t(u32, tcp_sk(sk)->srtt / msecs_to_jiffies(rtt0), 8);
ca->rho = ca->rho_3ls >> 3;
ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1;
ca->rho2 = ca->rho2_7ls >>7;
}
-static void hybla_init(struct tcp_sock *tp)
+static void hybla_init(struct sock *sk)
{
- struct hybla *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct hybla *ca = inet_csk_ca(sk);
ca->rho = 0;
ca->rho2 = 0;
@@ -57,17 +58,16 @@ static void hybla_init(struct tcp_sock *tp)
tp->snd_cwnd_clamp = 65535;
/* 1st Rho measurement based on initial srtt */
- hybla_recalc_param(tp);
+ hybla_recalc_param(sk);
/* set minimum rtt as this is the 1st ever seen */
ca->minrtt = tp->srtt;
tp->snd_cwnd = ca->rho;
}
-static void hybla_state(struct tcp_sock *tp, u8 ca_state)
+static void hybla_state(struct sock *sk, u8 ca_state)
{
- struct hybla *ca = tcp_ca(tp);
-
+ struct hybla *ca = inet_csk_ca(sk);
ca->hybla_en = (ca_state == TCP_CA_Open);
}
@@ -86,27 +86,28 @@ static inline u32 hybla_fraction(u32 odds)
* o Give cwnd a new value based on the model proposed
* o remember increments <1
*/
-static void hybla_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
u32 in_flight, int flag)
{
- struct hybla *ca = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct hybla *ca = inet_csk_ca(sk);
u32 increment, odd, rho_fractions;
int is_slowstart = 0;
/* Recalculate rho only if this srtt is the lowest */
if (tp->srtt < ca->minrtt){
- hybla_recalc_param(tp);
+ hybla_recalc_param(sk);
ca->minrtt = tp->srtt;
}
if (!ca->hybla_en)
- return tcp_reno_cong_avoid(tp, ack, rtt, in_flight, flag);
+ return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
if (in_flight < tp->snd_cwnd)
return;
if (ca->rho == 0)
- hybla_recalc_param(tp);
+ hybla_recalc_param(sk);
rho_fractions = ca->rho_3ls - (ca->rho << 3);
@@ -170,7 +171,7 @@ static struct tcp_congestion_ops tcp_hybla = {
static int __init hybla_register(void)
{
- BUG_ON(sizeof(struct hybla) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE);
return tcp_register_congestion_control(&tcp_hybla);
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 53a8a5399f1e..29222b964951 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -114,20 +114,21 @@ int sysctl_tcp_moderate_rcvbuf = 1;
/* Adapt the MSS value used to make delayed ack decision to the
* real world.
*/
-static inline void tcp_measure_rcv_mss(struct tcp_sock *tp,
- struct sk_buff *skb)
+static inline void tcp_measure_rcv_mss(struct sock *sk,
+ const struct sk_buff *skb)
{
- unsigned int len, lss;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ const unsigned int lss = icsk->icsk_ack.last_seg_size;
+ unsigned int len;
- lss = tp->ack.last_seg_size;
- tp->ack.last_seg_size = 0;
+ icsk->icsk_ack.last_seg_size = 0;
/* skb->len may jitter because of SACKs, even if peer
* sends good full-sized frames.
*/
len = skb->len;
- if (len >= tp->ack.rcv_mss) {
- tp->ack.rcv_mss = len;
+ if (len >= icsk->icsk_ack.rcv_mss) {
+ icsk->icsk_ack.rcv_mss = len;
} else {
/* Otherwise, we make more careful check taking into account,
* that SACKs block is variable.
@@ -147,41 +148,44 @@ static inline void tcp_measure_rcv_mss(struct tcp_sock *tp,
* tcp header plus fixed timestamp option length.
* Resulting "len" is MSS free of SACK jitter.
*/
- len -= tp->tcp_header_len;
- tp->ack.last_seg_size = len;
+ len -= tcp_sk(sk)->tcp_header_len;
+ icsk->icsk_ack.last_seg_size = len;
if (len == lss) {
- tp->ack.rcv_mss = len;
+ icsk->icsk_ack.rcv_mss = len;
return;
}
}
- tp->ack.pending |= TCP_ACK_PUSHED;
+ icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
}
}
-static void tcp_incr_quickack(struct tcp_sock *tp)
+static void tcp_incr_quickack(struct sock *sk)
{
- unsigned quickacks = tp->rcv_wnd/(2*tp->ack.rcv_mss);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ unsigned quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss);
if (quickacks==0)
quickacks=2;
- if (quickacks > tp->ack.quick)
- tp->ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
+ if (quickacks > icsk->icsk_ack.quick)
+ icsk->icsk_ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
}
-void tcp_enter_quickack_mode(struct tcp_sock *tp)
+void tcp_enter_quickack_mode(struct sock *sk)
{
- tcp_incr_quickack(tp);
- tp->ack.pingpong = 0;
- tp->ack.ato = TCP_ATO_MIN;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ tcp_incr_quickack(sk);
+ icsk->icsk_ack.pingpong = 0;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
}
/* Send ACKs quickly, if "quick" count is not exhausted
* and the session is not interactive.
*/
-static __inline__ int tcp_in_quickack_mode(struct tcp_sock *tp)
+static inline int tcp_in_quickack_mode(const struct sock *sk)
{
- return (tp->ack.quick && !tp->ack.pingpong);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ return icsk->icsk_ack.quick && !icsk->icsk_ack.pingpong;
}
/* Buffer size and advertised window tuning.
@@ -224,8 +228,8 @@ static void tcp_fixup_sndbuf(struct sock *sk)
*/
/* Slow part of check#2. */
-static int __tcp_grow_window(struct sock *sk, struct tcp_sock *tp,
- struct sk_buff *skb)
+static int __tcp_grow_window(const struct sock *sk, struct tcp_sock *tp,
+ const struct sk_buff *skb)
{
/* Optimize this! */
int truesize = tcp_win_from_space(skb->truesize)/2;
@@ -233,7 +237,7 @@ static int __tcp_grow_window(struct sock *sk, struct tcp_sock *tp,
while (tp->rcv_ssthresh <= window) {
if (truesize <= skb->len)
- return 2*tp->ack.rcv_mss;
+ return 2 * inet_csk(sk)->icsk_ack.rcv_mss;
truesize >>= 1;
window >>= 1;
@@ -260,7 +264,7 @@ static inline void tcp_grow_window(struct sock *sk, struct tcp_sock *tp,
if (incr) {
tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr, tp->window_clamp);
- tp->ack.quick |= 1;
+ inet_csk(sk)->icsk_ack.quick |= 1;
}
}
}
@@ -321,11 +325,12 @@ static void tcp_init_buffer_space(struct sock *sk)
/* 5. Recalculate window clamp after socket hit its memory bounds. */
static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct sk_buff *skb;
unsigned int app_win = tp->rcv_nxt - tp->copied_seq;
int ofo_win = 0;
- tp->ack.quick = 0;
+ icsk->icsk_ack.quick = 0;
skb_queue_walk(&tp->out_of_order_queue, skb) {
ofo_win += skb->len;
@@ -346,8 +351,8 @@ static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
app_win += ofo_win;
if (atomic_read(&sk->sk_rmem_alloc) >= 2 * sk->sk_rcvbuf)
app_win >>= 1;
- if (app_win > tp->ack.rcv_mss)
- app_win -= tp->ack.rcv_mss;
+ if (app_win > icsk->icsk_ack.rcv_mss)
+ app_win -= icsk->icsk_ack.rcv_mss;
app_win = max(app_win, 2U*tp->advmss);
if (!ofo_win)
@@ -415,11 +420,12 @@ new_measure:
tp->rcv_rtt_est.time = tcp_time_stamp;
}
-static inline void tcp_rcv_rtt_measure_ts(struct tcp_sock *tp, struct sk_buff *skb)
+static inline void tcp_rcv_rtt_measure_ts(struct sock *sk, const struct sk_buff *skb)
{
+ struct tcp_sock *tp = tcp_sk(sk);
if (tp->rx_opt.rcv_tsecr &&
(TCP_SKB_CB(skb)->end_seq -
- TCP_SKB_CB(skb)->seq >= tp->ack.rcv_mss))
+ TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss))
tcp_rcv_rtt_update(tp, tcp_time_stamp - tp->rx_opt.rcv_tsecr, 0);
}
@@ -492,41 +498,42 @@ new_measure:
*/
static void tcp_event_data_recv(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
u32 now;
- tcp_schedule_ack(tp);
+ inet_csk_schedule_ack(sk);
- tcp_measure_rcv_mss(tp, skb);
+ tcp_measure_rcv_mss(sk, skb);
tcp_rcv_rtt_measure(tp);
now = tcp_time_stamp;
- if (!tp->ack.ato) {
+ if (!icsk->icsk_ack.ato) {
/* The _first_ data packet received, initialize
* delayed ACK engine.
*/
- tcp_incr_quickack(tp);
- tp->ack.ato = TCP_ATO_MIN;
+ tcp_incr_quickack(sk);
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
} else {
- int m = now - tp->ack.lrcvtime;
+ int m = now - icsk->icsk_ack.lrcvtime;
if (m <= TCP_ATO_MIN/2) {
/* The fastest case is the first. */
- tp->ack.ato = (tp->ack.ato>>1) + TCP_ATO_MIN/2;
- } else if (m < tp->ack.ato) {
- tp->ack.ato = (tp->ack.ato>>1) + m;
- if (tp->ack.ato > tp->rto)
- tp->ack.ato = tp->rto;
- } else if (m > tp->rto) {
+ icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + TCP_ATO_MIN / 2;
+ } else if (m < icsk->icsk_ack.ato) {
+ icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + m;
+ if (icsk->icsk_ack.ato > icsk->icsk_rto)
+ icsk->icsk_ack.ato = icsk->icsk_rto;
+ } else if (m > icsk->icsk_rto) {
/* Too long gap. Apparently sender falled to
* restart window, so that we send ACKs quickly.
*/
- tcp_incr_quickack(tp);
+ tcp_incr_quickack(sk);
sk_stream_mem_reclaim(sk);
}
}
- tp->ack.lrcvtime = now;
+ icsk->icsk_ack.lrcvtime = now;
TCP_ECN_check_ce(tp, skb);
@@ -543,8 +550,10 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_sock *tp, struct sk_
* To save cycles in the RFC 1323 implementation it was better to break
* it up into three procedures. -- erics
*/
-static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt, u32 *usrtt)
+static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt, u32 *usrtt)
{
+ struct tcp_sock *tp = tcp_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
long m = mrtt; /* RTT */
/* The following amusing code comes from Jacobson's
@@ -604,15 +613,16 @@ static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt, u32 *usrtt)
tp->rtt_seq = tp->snd_nxt;
}
- if (tp->ca_ops->rtt_sample)
- tp->ca_ops->rtt_sample(tp, *usrtt);
+ if (icsk->icsk_ca_ops->rtt_sample)
+ icsk->icsk_ca_ops->rtt_sample(sk, *usrtt);
}
/* Calculate rto without backoff. This is the second half of Van Jacobson's
* routine referred to above.
*/
-static inline void tcp_set_rto(struct tcp_sock *tp)
+static inline void tcp_set_rto(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
/* Old crap is replaced with new one. 8)
*
* More seriously:
@@ -623,7 +633,7 @@ static inline void tcp_set_rto(struct tcp_sock *tp)
* is invisible. Actually, Linux-2.4 also generates erratic
* ACKs in some curcumstances.
*/
- tp->rto = (tp->srtt >> 3) + tp->rttvar;
+ inet_csk(sk)->icsk_rto = (tp->srtt >> 3) + tp->rttvar;
/* 2. Fixups made earlier cannot be right.
* If we do not estimate RTO correctly without them,
@@ -635,10 +645,10 @@ static inline void tcp_set_rto(struct tcp_sock *tp)
/* NOTE: clamping at TCP_RTO_MIN is not required, current algo
* guarantees that rto is higher.
*/
-static inline void tcp_bound_rto(struct tcp_sock *tp)
+static inline void tcp_bound_rto(struct sock *sk)
{
- if (tp->rto > TCP_RTO_MAX)
- tp->rto = TCP_RTO_MAX;
+ if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
+ inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
}
/* Save metrics learned by this TCP session.
@@ -656,9 +666,10 @@ void tcp_update_metrics(struct sock *sk)
dst_confirm(dst);
if (dst && (dst->flags&DST_HOST)) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
int m;
- if (tp->backoff || !tp->srtt) {
+ if (icsk->icsk_backoff || !tp->srtt) {
/* This session failed to estimate rtt. Why?
* Probably, no packets returned in time.
* Reset our results.
@@ -707,7 +718,7 @@ void tcp_update_metrics(struct sock *sk)
tp->snd_cwnd > dst_metric(dst, RTAX_CWND))
dst->metrics[RTAX_CWND-1] = tp->snd_cwnd;
} else if (tp->snd_cwnd > tp->snd_ssthresh &&
- tp->ca_state == TCP_CA_Open) {
+ icsk->icsk_ca_state == TCP_CA_Open) {
/* Cong. avoidance phase, cwnd is reliable. */
if (!dst_metric_locked(dst, RTAX_SSTHRESH))
dst->metrics[RTAX_SSTHRESH-1] =
@@ -801,9 +812,9 @@ static void tcp_init_metrics(struct sock *sk)
tp->mdev = dst_metric(dst, RTAX_RTTVAR);
tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
}
- tcp_set_rto(tp);
- tcp_bound_rto(tp);
- if (tp->rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp)
+ tcp_set_rto(sk);
+ tcp_bound_rto(sk);
+ if (inet_csk(sk)->icsk_rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp)
goto reset;
tp->snd_cwnd = tcp_init_cwnd(tp, dst);
tp->snd_cwnd_stamp = tcp_time_stamp;
@@ -817,12 +828,14 @@ reset:
if (!tp->rx_opt.saw_tstamp && tp->srtt) {
tp->srtt = 0;
tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
- tp->rto = TCP_TIMEOUT_INIT;
+ inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
}
}
-static void tcp_update_reordering(struct tcp_sock *tp, int metric, int ts)
+static void tcp_update_reordering(struct sock *sk, const int metric,
+ const int ts)
{
+ struct tcp_sock *tp = tcp_sk(sk);
if (metric > tp->reordering) {
tp->reordering = min(TCP_MAX_REORDERING, metric);
@@ -837,7 +850,7 @@ static void tcp_update_reordering(struct tcp_sock *tp, int metric, int ts)
NET_INC_STATS_BH(LINUX_MIB_TCPSACKREORDER);
#if FASTRETRANS_DEBUG > 1
printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n",
- tp->rx_opt.sack_ok, tp->ca_state,
+ tp->rx_opt.sack_ok, inet_csk(sk)->icsk_ca_state,
tp->reordering,
tp->fackets_out,
tp->sacked_out,
@@ -899,6 +912,7 @@ static void tcp_update_reordering(struct tcp_sock *tp, int metric, int ts)
static int
tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
@@ -909,14 +923,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
int flag = 0;
int i;
- /* So, SACKs for already sent large segments will be lost.
- * Not good, but alternative is to resegment the queue. */
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sk->sk_route_caps &= ~NETIF_F_TSO;
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- tp->mss_cache = tp->mss_cache;
- }
-
if (!tp->sacked_out)
tp->fackets_out = 0;
prior_fackets = tp->fackets_out;
@@ -964,20 +970,40 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
flag |= FLAG_DATA_LOST;
sk_stream_for_retrans_queue(skb, sk) {
- u8 sacked = TCP_SKB_CB(skb)->sacked;
- int in_sack;
+ int in_sack, pcount;
+ u8 sacked;
/* The retransmission queue is always in order, so
* we can short-circuit the walk early.
*/
- if(!before(TCP_SKB_CB(skb)->seq, end_seq))
+ if (!before(TCP_SKB_CB(skb)->seq, end_seq))
break;
- fack_count += tcp_skb_pcount(skb);
+ pcount = tcp_skb_pcount(skb);
+
+ if (pcount > 1 &&
+ (after(start_seq, TCP_SKB_CB(skb)->seq) ||
+ before(end_seq, TCP_SKB_CB(skb)->end_seq))) {
+ unsigned int pkt_len;
+
+ if (after(start_seq, TCP_SKB_CB(skb)->seq))
+ pkt_len = (start_seq -
+ TCP_SKB_CB(skb)->seq);
+ else
+ pkt_len = (end_seq -
+ TCP_SKB_CB(skb)->seq);
+ if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size))
+ break;
+ pcount = tcp_skb_pcount(skb);
+ }
+
+ fack_count += pcount;
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
!before(end_seq, TCP_SKB_CB(skb)->end_seq);
+ sacked = TCP_SKB_CB(skb)->sacked;
+
/* Account D-SACK for retransmitted packet. */
if ((dup_sack && in_sack) &&
(sacked & TCPCB_RETRANS) &&
@@ -1064,7 +1090,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
* we have to account for reordering! Ugly,
* but should help.
*/
- if (lost_retrans && tp->ca_state == TCP_CA_Recovery) {
+ if (lost_retrans && icsk->icsk_ca_state == TCP_CA_Recovery) {
struct sk_buff *skb;
sk_stream_for_retrans_queue(skb, sk) {
@@ -1093,8 +1119,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
tp->left_out = tp->sacked_out + tp->lost_out;
- if ((reord < tp->fackets_out) && tp->ca_state != TCP_CA_Loss)
- tcp_update_reordering(tp, ((tp->fackets_out + 1) - reord), 0);
+ if ((reord < tp->fackets_out) && icsk->icsk_ca_state != TCP_CA_Loss)
+ tcp_update_reordering(sk, ((tp->fackets_out + 1) - reord), 0);
#if FASTRETRANS_DEBUG > 0
BUG_TRAP((int)tp->sacked_out >= 0);
@@ -1111,17 +1137,18 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
*/
void tcp_enter_frto(struct sock *sk)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
tp->frto_counter = 1;
- if (tp->ca_state <= TCP_CA_Disorder ||
+ if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
tp->snd_una == tp->high_seq ||
- (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
- tp->prior_ssthresh = tcp_current_ssthresh(tp);
- tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
- tcp_ca_event(tp, CA_EVENT_FRTO);
+ (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
+ tp->prior_ssthresh = tcp_current_ssthresh(sk);
+ tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
+ tcp_ca_event(sk, CA_EVENT_FRTO);
}
/* Have to clear retransmission markers here to keep the bookkeeping
@@ -1138,7 +1165,7 @@ void tcp_enter_frto(struct sock *sk)
}
tcp_sync_left_out(tp);
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_set_ca_state(sk, TCP_CA_Open);
tp->frto_highmark = tp->snd_nxt;
}
@@ -1184,7 +1211,7 @@ static void tcp_enter_frto_loss(struct sock *sk)
tp->reordering = min_t(unsigned int, tp->reordering,
sysctl_tcp_reordering);
- tcp_set_ca_state(tp, TCP_CA_Loss);
+ tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->frto_highmark;
TCP_ECN_queue_cwr(tp);
}
@@ -1208,16 +1235,17 @@ void tcp_clear_retrans(struct tcp_sock *tp)
*/
void tcp_enter_loss(struct sock *sk, int how)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int cnt = 0;
/* Reduce ssthresh if it has not yet been made inside this window. */
- if (tp->ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
- (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
- tp->prior_ssthresh = tcp_current_ssthresh(tp);
- tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
- tcp_ca_event(tp, CA_EVENT_LOSS);
+ if (icsk->icsk_ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
+ (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
+ tp->prior_ssthresh = tcp_current_ssthresh(sk);
+ tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
+ tcp_ca_event(sk, CA_EVENT_LOSS);
}
tp->snd_cwnd = 1;
tp->snd_cwnd_cnt = 0;
@@ -1248,12 +1276,12 @@ void tcp_enter_loss(struct sock *sk, int how)
tp->reordering = min_t(unsigned int, tp->reordering,
sysctl_tcp_reordering);
- tcp_set_ca_state(tp, TCP_CA_Loss);
+ tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp);
}
-static int tcp_check_sack_reneging(struct sock *sk, struct tcp_sock *tp)
+static int tcp_check_sack_reneging(struct sock *sk)
{
struct sk_buff *skb;
@@ -1265,12 +1293,14 @@ static int tcp_check_sack_reneging(struct sock *sk, struct tcp_sock *tp)
*/
if ((skb = skb_peek(&sk->sk_write_queue)) != NULL &&
(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
+ struct inet_connection_sock *icsk = inet_csk(sk);
NET_INC_STATS_BH(LINUX_MIB_TCPSACKRENEGING);
tcp_enter_loss(sk, 1);
- tp->retransmits++;
+ icsk->icsk_retransmits++;
tcp_retransmit_skb(sk, skb_peek(&sk->sk_write_queue));
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ icsk->icsk_rto, TCP_RTO_MAX);
return 1;
}
return 0;
@@ -1281,15 +1311,15 @@ static inline int tcp_fackets_out(struct tcp_sock *tp)
return IsReno(tp) ? tp->sacked_out+1 : tp->fackets_out;
}
-static inline int tcp_skb_timedout(struct tcp_sock *tp, struct sk_buff *skb)
+static inline int tcp_skb_timedout(struct sock *sk, struct sk_buff *skb)
{
- return (tcp_time_stamp - TCP_SKB_CB(skb)->when > tp->rto);
+ return (tcp_time_stamp - TCP_SKB_CB(skb)->when > inet_csk(sk)->icsk_rto);
}
static inline int tcp_head_timedout(struct sock *sk, struct tcp_sock *tp)
{
return tp->packets_out &&
- tcp_skb_timedout(tp, skb_peek(&sk->sk_write_queue));
+ tcp_skb_timedout(sk, skb_peek(&sk->sk_write_queue));
}
/* Linux NewReno/SACK/FACK/ECN state machine.
@@ -1423,8 +1453,9 @@ static int tcp_time_to_recover(struct sock *sk, struct tcp_sock *tp)
* in assumption of absent reordering, interpret this as reordering.
* The only another reason could be bug in receiver TCP.
*/
-static void tcp_check_reno_reordering(struct tcp_sock *tp, int addend)
+static void tcp_check_reno_reordering(struct sock *sk, const int addend)
{
+ struct tcp_sock *tp = tcp_sk(sk);
u32 holes;
holes = max(tp->lost_out, 1U);
@@ -1432,16 +1463,17 @@ static void tcp_check_reno_reordering(struct tcp_sock *tp, int addend)
if ((tp->sacked_out + holes) > tp->packets_out) {
tp->sacked_out = tp->packets_out - holes;
- tcp_update_reordering(tp, tp->packets_out+addend, 0);
+ tcp_update_reordering(sk, tp->packets_out + addend, 0);
}
}
/* Emulate SACKs for SACKless connection: account for a new dupack. */
-static void tcp_add_reno_sack(struct tcp_sock *tp)
+static void tcp_add_reno_sack(struct sock *sk)
{
+ struct tcp_sock *tp = tcp_sk(sk);
tp->sacked_out++;
- tcp_check_reno_reordering(tp, 0);
+ tcp_check_reno_reordering(sk, 0);
tcp_sync_left_out(tp);
}
@@ -1456,7 +1488,7 @@ static void tcp_remove_reno_sacks(struct sock *sk, struct tcp_sock *tp, int acke
else
tp->sacked_out -= acked-1;
}
- tcp_check_reno_reordering(tp, acked);
+ tcp_check_reno_reordering(sk, acked);
tcp_sync_left_out(tp);
}
@@ -1509,7 +1541,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp)
struct sk_buff *skb;
sk_stream_for_retrans_queue(skb, sk) {
- if (tcp_skb_timedout(tp, skb) &&
+ if (tcp_skb_timedout(sk, skb) &&
!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
tp->lost_out += tcp_skb_pcount(skb);
@@ -1530,14 +1562,16 @@ static inline void tcp_moderate_cwnd(struct tcp_sock *tp)
}
/* Decrease cwnd each second ack. */
-static void tcp_cwnd_down(struct tcp_sock *tp)
+static void tcp_cwnd_down(struct sock *sk)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tcp_sock *tp = tcp_sk(sk);
int decr = tp->snd_cwnd_cnt + 1;
tp->snd_cwnd_cnt = decr&1;
decr >>= 1;
- if (decr && tp->snd_cwnd > tp->ca_ops->min_cwnd(tp))
+ if (decr && tp->snd_cwnd > icsk->icsk_ca_ops->min_cwnd(sk))
tp->snd_cwnd -= decr;
tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -1571,11 +1605,15 @@ static void DBGUNDO(struct sock *sk, struct tcp_sock *tp, const char *msg)
#define DBGUNDO(x...) do { } while (0)
#endif
-static void tcp_undo_cwr(struct tcp_sock *tp, int undo)
+static void tcp_undo_cwr(struct sock *sk, const int undo)
{
+ struct tcp_sock *tp = tcp_sk(sk);
+
if (tp->prior_ssthresh) {
- if (tp->ca_ops->undo_cwnd)
- tp->snd_cwnd = tp->ca_ops->undo_cwnd(tp);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (icsk->icsk_ca_ops->undo_cwnd)
+ tp->snd_cwnd = icsk->icsk_ca_ops->undo_cwnd(sk);
else
tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
@@ -1603,9 +1641,9 @@ static int tcp_try_undo_recovery(struct sock *sk, struct tcp_sock *tp)
/* Happy end! We did not retransmit anything
* or our original transmission succeeded.
*/
- DBGUNDO(sk, tp, tp->ca_state == TCP_CA_Loss ? "loss" : "retrans");
- tcp_undo_cwr(tp, 1);
- if (tp->ca_state == TCP_CA_Loss)
+ DBGUNDO(sk, tp, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans");
+ tcp_undo_cwr(sk, 1);
+ if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
NET_INC_STATS_BH(LINUX_MIB_TCPLOSSUNDO);
else
NET_INC_STATS_BH(LINUX_MIB_TCPFULLUNDO);
@@ -1618,7 +1656,7 @@ static int tcp_try_undo_recovery(struct sock *sk, struct tcp_sock *tp)
tcp_moderate_cwnd(tp);
return 1;
}
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_set_ca_state(sk, TCP_CA_Open);
return 0;
}
@@ -1627,7 +1665,7 @@ static void tcp_try_undo_dsack(struct sock *sk, struct tcp_sock *tp)
{
if (tp->undo_marker && !tp->undo_retrans) {
DBGUNDO(sk, tp, "D-SACK");
- tcp_undo_cwr(tp, 1);
+ tcp_undo_cwr(sk, 1);
tp->undo_marker = 0;
NET_INC_STATS_BH(LINUX_MIB_TCPDSACKUNDO);
}
@@ -1648,10 +1686,10 @@ static int tcp_try_undo_partial(struct sock *sk, struct tcp_sock *tp,
if (tp->retrans_out == 0)
tp->retrans_stamp = 0;
- tcp_update_reordering(tp, tcp_fackets_out(tp)+acked, 1);
+ tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1);
DBGUNDO(sk, tp, "Hoe");
- tcp_undo_cwr(tp, 0);
+ tcp_undo_cwr(sk, 0);
NET_INC_STATS_BH(LINUX_MIB_TCPPARTIALUNDO);
/* So... Do not make Hoe's retransmit yet.
@@ -1674,22 +1712,23 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_sock *tp)
DBGUNDO(sk, tp, "partial loss");
tp->lost_out = 0;
tp->left_out = tp->sacked_out;
- tcp_undo_cwr(tp, 1);
+ tcp_undo_cwr(sk, 1);
NET_INC_STATS_BH(LINUX_MIB_TCPLOSSUNDO);
- tp->retransmits = 0;
+ inet_csk(sk)->icsk_retransmits = 0;
tp->undo_marker = 0;
if (!IsReno(tp))
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_set_ca_state(sk, TCP_CA_Open);
return 1;
}
return 0;
}
-static inline void tcp_complete_cwr(struct tcp_sock *tp)
+static inline void tcp_complete_cwr(struct sock *sk)
{
+ struct tcp_sock *tp = tcp_sk(sk);
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
tp->snd_cwnd_stamp = tcp_time_stamp;
- tcp_ca_event(tp, CA_EVENT_COMPLETE_CWR);
+ tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
}
static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
@@ -1700,21 +1739,21 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
tp->retrans_stamp = 0;
if (flag&FLAG_ECE)
- tcp_enter_cwr(tp);
+ tcp_enter_cwr(sk);
- if (tp->ca_state != TCP_CA_CWR) {
+ if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) {
int state = TCP_CA_Open;
if (tp->left_out || tp->retrans_out || tp->undo_marker)
state = TCP_CA_Disorder;
- if (tp->ca_state != state) {
- tcp_set_ca_state(tp, state);
+ if (inet_csk(sk)->icsk_ca_state != state) {
+ tcp_set_ca_state(sk, state);
tp->high_seq = tp->snd_nxt;
}
tcp_moderate_cwnd(tp);
} else {
- tcp_cwnd_down(tp);
+ tcp_cwnd_down(sk);
}
}
@@ -1733,6 +1772,7 @@ static void
tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
int prior_packets, int flag)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP));
@@ -1750,13 +1790,13 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
tp->prior_ssthresh = 0;
/* B. In all the states check for reneging SACKs. */
- if (tp->sacked_out && tcp_check_sack_reneging(sk, tp))
+ if (tp->sacked_out && tcp_check_sack_reneging(sk))
return;
/* C. Process data loss notification, provided it is valid. */
if ((flag&FLAG_DATA_LOST) &&
before(tp->snd_una, tp->high_seq) &&
- tp->ca_state != TCP_CA_Open &&
+ icsk->icsk_ca_state != TCP_CA_Open &&
tp->fackets_out > tp->reordering) {
tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq);
NET_INC_STATS_BH(LINUX_MIB_TCPLOSS);
@@ -1767,14 +1807,14 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
/* E. Check state exit conditions. State can be terminated
* when high_seq is ACKed. */
- if (tp->ca_state == TCP_CA_Open) {
+ if (icsk->icsk_ca_state == TCP_CA_Open) {
if (!sysctl_tcp_frto)
BUG_TRAP(tp->retrans_out == 0);
tp->retrans_stamp = 0;
} else if (!before(tp->snd_una, tp->high_seq)) {
- switch (tp->ca_state) {
+ switch (icsk->icsk_ca_state) {
case TCP_CA_Loss:
- tp->retransmits = 0;
+ icsk->icsk_retransmits = 0;
if (tcp_try_undo_recovery(sk, tp))
return;
break;
@@ -1783,8 +1823,8 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
/* CWR is to be held something *above* high_seq
* is ACKed for CWR bit to reach receiver. */
if (tp->snd_una != tp->high_seq) {
- tcp_complete_cwr(tp);
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_complete_cwr(sk);
+ tcp_set_ca_state(sk, TCP_CA_Open);
}
break;
@@ -1795,7 +1835,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
* catching for all duplicate ACKs. */
IsReno(tp) || tp->snd_una != tp->high_seq) {
tp->undo_marker = 0;
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tcp_set_ca_state(sk, TCP_CA_Open);
}
break;
@@ -1804,17 +1844,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
tcp_reset_reno_sack(tp);
if (tcp_try_undo_recovery(sk, tp))
return;
- tcp_complete_cwr(tp);
+ tcp_complete_cwr(sk);
break;
}
}
/* F. Process state. */
- switch (tp->ca_state) {
+ switch (icsk->icsk_ca_state) {
case TCP_CA_Recovery:
if (prior_snd_una == tp->snd_una) {
if (IsReno(tp) && is_dupack)
- tcp_add_reno_sack(tp);
+ tcp_add_reno_sack(sk);
} else {
int acked = prior_packets - tp->packets_out;
if (IsReno(tp))
@@ -1824,13 +1864,13 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
break;
case TCP_CA_Loss:
if (flag&FLAG_DATA_ACKED)
- tp->retransmits = 0;
+ icsk->icsk_retransmits = 0;
if (!tcp_try_undo_loss(sk, tp)) {
tcp_moderate_cwnd(tp);
tcp_xmit_retransmit_queue(sk);
return;
}
- if (tp->ca_state != TCP_CA_Open)
+ if (icsk->icsk_ca_state != TCP_CA_Open)
return;
/* Loss is undone; fall through to processing in Open state. */
default:
@@ -1838,10 +1878,10 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
if (tp->snd_una != prior_snd_una)
tcp_reset_reno_sack(tp);
if (is_dupack)
- tcp_add_reno_sack(tp);
+ tcp_add_reno_sack(sk);
}
- if (tp->ca_state == TCP_CA_Disorder)
+ if (icsk->icsk_ca_state == TCP_CA_Disorder)
tcp_try_undo_dsack(sk, tp);
if (!tcp_time_to_recover(sk, tp)) {
@@ -1861,30 +1901,28 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
tp->undo_marker = tp->snd_una;
tp->undo_retrans = tp->retrans_out;
- if (tp->ca_state < TCP_CA_CWR) {
+ if (icsk->icsk_ca_state < TCP_CA_CWR) {
if (!(flag&FLAG_ECE))
- tp->prior_ssthresh = tcp_current_ssthresh(tp);
- tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+ tp->prior_ssthresh = tcp_current_ssthresh(sk);
+ tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
TCP_ECN_queue_cwr(tp);
}
tp->snd_cwnd_cnt = 0;
- tcp_set_ca_state(tp, TCP_CA_Recovery);
+ tcp_set_ca_state(sk, TCP_CA_Recovery);
}
if (is_dupack || tcp_head_timedout(sk, tp))
tcp_update_scoreboard(sk, tp);
- tcp_cwnd_down(tp);
+ tcp_cwnd_down(sk);
tcp_xmit_retransmit_queue(sk);
}
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Superceeds RFC1323)
*/
-static void tcp_ack_saw_tstamp(struct tcp_sock *tp, u32 *usrtt, int flag)
+static void tcp_ack_saw_tstamp(struct sock *sk, u32 *usrtt, int flag)
{
- __u32 seq_rtt;
-
/* RTTM Rule: A TSecr value received in a segment is used to
* update the averaged RTT measurement only if the segment
* acknowledges some new data, i.e., only if it advances the
@@ -1900,14 +1938,15 @@ static void tcp_ack_saw_tstamp(struct tcp_sock *tp, u32 *usrtt, int flag)
* answer arrives rto becomes 120 seconds! If at least one of segments
* in window is lost... Voila. --ANK (010210)
*/
- seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
- tcp_rtt_estimator(tp, seq_rtt, usrtt);
- tcp_set_rto(tp);
- tp->backoff = 0;
- tcp_bound_rto(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ const __u32 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+ tcp_rtt_estimator(sk, seq_rtt, usrtt);
+ tcp_set_rto(sk);
+ inet_csk(sk)->icsk_backoff = 0;
+ tcp_bound_rto(sk);
}
-static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, u32 *usrtt, int flag)
+static void tcp_ack_no_tstamp(struct sock *sk, u32 seq_rtt, u32 *usrtt, int flag)
{
/* We don't have a timestamp. Can only use
* packets that are not retransmitted to determine
@@ -1921,27 +1960,29 @@ static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, u32 *usrtt, int
if (flag & FLAG_RETRANS_DATA_ACKED)
return;
- tcp_rtt_estimator(tp, seq_rtt, usrtt);
- tcp_set_rto(tp);
- tp->backoff = 0;
- tcp_bound_rto(tp);
+ tcp_rtt_estimator(sk, seq_rtt, usrtt);
+ tcp_set_rto(sk);
+ inet_csk(sk)->icsk_backoff = 0;
+ tcp_bound_rto(sk);
}
-static inline void tcp_ack_update_rtt(struct tcp_sock *tp,
- int flag, s32 seq_rtt, u32 *usrtt)
+static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
+ const s32 seq_rtt, u32 *usrtt)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
/* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
- tcp_ack_saw_tstamp(tp, usrtt, flag);
+ tcp_ack_saw_tstamp(sk, usrtt, flag);
else if (seq_rtt >= 0)
- tcp_ack_no_tstamp(tp, seq_rtt, usrtt, flag);
+ tcp_ack_no_tstamp(sk, seq_rtt, usrtt, flag);
}
-static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+static inline void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
u32 in_flight, int good)
{
- tp->ca_ops->cong_avoid(tp, ack, rtt, in_flight, good);
- tp->snd_cwnd_stamp = tcp_time_stamp;
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ icsk->icsk_ca_ops->cong_avoid(sk, ack, rtt, in_flight, good);
+ tcp_sk(sk)->snd_cwnd_stamp = tcp_time_stamp;
}
/* Restart timer after forward progress on connection.
@@ -1951,9 +1992,9 @@ static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
static inline void tcp_ack_packets_out(struct sock *sk, struct tcp_sock *tp)
{
if (!tp->packets_out) {
- tcp_clear_xmit_timer(sk, TCP_TIME_RETRANS);
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
} else {
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
}
}
@@ -2068,9 +2109,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt
seq_rtt = -1;
} else if (seq_rtt < 0)
seq_rtt = now - scb->when;
- if (seq_usrtt)
- *seq_usrtt = (usnow.tv_sec - skb->stamp.tv_sec) * 1000000
- + (usnow.tv_usec - skb->stamp.tv_usec);
+ if (seq_usrtt) {
+ struct timeval tv;
+
+ skb_get_timestamp(skb, &tv);
+ *seq_usrtt = (usnow.tv_sec - tv.tv_sec) * 1000000
+ + (usnow.tv_usec - tv.tv_usec);
+ }
if (sacked & TCPCB_SACKED_ACKED)
tp->sacked_out -= tcp_skb_pcount(skb);
@@ -2085,16 +2130,17 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt
seq_rtt = now - scb->when;
tcp_dec_pcount_approx(&tp->fackets_out, skb);
tcp_packets_out_dec(tp, skb);
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &sk->sk_write_queue);
sk_stream_free_skb(sk, skb);
}
if (acked&FLAG_ACKED) {
- tcp_ack_update_rtt(tp, acked, seq_rtt, seq_usrtt);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ tcp_ack_update_rtt(sk, acked, seq_rtt, seq_usrtt);
tcp_ack_packets_out(sk, tp);
- if (tp->ca_ops->pkts_acked)
- tp->ca_ops->pkts_acked(tp, pkts_acked);
+ if (icsk->icsk_ca_ops->pkts_acked)
+ icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked);
}
#if FASTRETRANS_DEBUG > 0
@@ -2102,19 +2148,20 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt
BUG_TRAP((int)tp->lost_out >= 0);
BUG_TRAP((int)tp->retrans_out >= 0);
if (!tp->packets_out && tp->rx_opt.sack_ok) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
if (tp->lost_out) {
printk(KERN_DEBUG "Leak l=%u %d\n",
- tp->lost_out, tp->ca_state);
+ tp->lost_out, icsk->icsk_ca_state);
tp->lost_out = 0;
}
if (tp->sacked_out) {
printk(KERN_DEBUG "Leak s=%u %d\n",
- tp->sacked_out, tp->ca_state);
+ tp->sacked_out, icsk->icsk_ca_state);
tp->sacked_out = 0;
}
if (tp->retrans_out) {
printk(KERN_DEBUG "Leak r=%u %d\n",
- tp->retrans_out, tp->ca_state);
+ tp->retrans_out, icsk->icsk_ca_state);
tp->retrans_out = 0;
}
}
@@ -2125,40 +2172,43 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt
static void tcp_ack_probe(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
/* Was it a usable window open? */
if (!after(TCP_SKB_CB(sk->sk_send_head)->end_seq,
tp->snd_una + tp->snd_wnd)) {
- tp->backoff = 0;
- tcp_clear_xmit_timer(sk, TCP_TIME_PROBE0);
+ icsk->icsk_backoff = 0;
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_PROBE0);
/* Socket must be waked up by subsequent tcp_data_snd_check().
* This function is not for random using!
*/
} else {
- tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0,
- min(tp->rto << tp->backoff, TCP_RTO_MAX));
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+ min(icsk->icsk_rto << icsk->icsk_backoff, TCP_RTO_MAX),
+ TCP_RTO_MAX);
}
}
-static inline int tcp_ack_is_dubious(struct tcp_sock *tp, int flag)
+static inline int tcp_ack_is_dubious(const struct sock *sk, const int flag)
{
return (!(flag & FLAG_NOT_DUP) || (flag & FLAG_CA_ALERT) ||
- tp->ca_state != TCP_CA_Open);
+ inet_csk(sk)->icsk_ca_state != TCP_CA_Open);
}
-static inline int tcp_may_raise_cwnd(struct tcp_sock *tp, int flag)
+static inline int tcp_may_raise_cwnd(const struct sock *sk, const int flag)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return (!(flag & FLAG_ECE) || tp->snd_cwnd < tp->snd_ssthresh) &&
- !((1<<tp->ca_state)&(TCPF_CA_Recovery|TCPF_CA_CWR));
+ !((1 << inet_csk(sk)->icsk_ca_state) & (TCPF_CA_Recovery | TCPF_CA_CWR));
}
/* Check that window update is acceptable.
* The function assumes that snd_una<=ack<=snd_next.
*/
-static inline int tcp_may_update_window(struct tcp_sock *tp, u32 ack,
- u32 ack_seq, u32 nwin)
+static inline int tcp_may_update_window(const struct tcp_sock *tp, const u32 ack,
+ const u32 ack_seq, const u32 nwin)
{
return (after(ack, tp->snd_una) ||
after(ack_seq, tp->snd_wl1) ||
@@ -2241,6 +2291,7 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
u32 prior_snd_una = tp->snd_una;
u32 ack_seq = TCP_SKB_CB(skb)->seq;
@@ -2268,7 +2319,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
tp->snd_una = ack;
flag |= FLAG_WIN_UPDATE;
- tcp_ca_event(tp, CA_EVENT_FAST_ACK);
+ tcp_ca_event(sk, CA_EVENT_FAST_ACK);
NET_INC_STATS_BH(LINUX_MIB_TCPHPACKS);
} else {
@@ -2285,7 +2336,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
flag |= FLAG_ECE;
- tcp_ca_event(tp, CA_EVENT_SLOW_ACK);
+ tcp_ca_event(sk, CA_EVENT_SLOW_ACK);
}
/* We passed data and got it acked, remove any soft error
@@ -2301,19 +2352,19 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
/* See if we can take anything off of the retransmit queue. */
flag |= tcp_clean_rtx_queue(sk, &seq_rtt,
- tp->ca_ops->rtt_sample ? &seq_usrtt : NULL);
+ icsk->icsk_ca_ops->rtt_sample ? &seq_usrtt : NULL);
if (tp->frto_counter)
tcp_process_frto(sk, prior_snd_una);
- if (tcp_ack_is_dubious(tp, flag)) {
+ if (tcp_ack_is_dubious(sk, flag)) {
/* Advanve CWND, if state allows this. */
- if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(tp, flag))
- tcp_cong_avoid(tp, ack, seq_rtt, prior_in_flight, 0);
+ if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag))
+ tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 0);
tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
} else {
if ((flag & FLAG_DATA_ACKED))
- tcp_cong_avoid(tp, ack, seq_rtt, prior_in_flight, 1);
+ tcp_cong_avoid(sk, ack, seq_rtt, prior_in_flight, 1);
}
if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
@@ -2322,7 +2373,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
return 1;
no_queue:
- tp->probes_out = 0;
+ icsk->icsk_probes_out = 0;
/* If this ack opens up a zero window, clear backoff. It was
* being used to time the probes, and is probably far higher than
@@ -2500,8 +2551,9 @@ static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
* up to bandwidth of 18Gigabit/sec. 8) ]
*/
-static int tcp_disordered_ack(struct tcp_sock *tp, struct sk_buff *skb)
+static int tcp_disordered_ack(const struct sock *sk, const struct sk_buff *skb)
{
+ struct tcp_sock *tp = tcp_sk(sk);
struct tcphdr *th = skb->h.th;
u32 seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
@@ -2516,14 +2568,15 @@ static int tcp_disordered_ack(struct tcp_sock *tp, struct sk_buff *skb)
!tcp_may_update_window(tp, ack, seq, ntohs(th->window) << tp->rx_opt.snd_wscale) &&
/* 4. ... and sits in replay window. */
- (s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) <= (tp->rto*1024)/HZ);
+ (s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) <= (inet_csk(sk)->icsk_rto * 1024) / HZ);
}
-static inline int tcp_paws_discard(struct tcp_sock *tp, struct sk_buff *skb)
+static inline int tcp_paws_discard(const struct sock *sk, const struct sk_buff *skb)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return ((s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) > TCP_PAWS_WINDOW &&
xtime.tv_sec < tp->rx_opt.ts_recent_stamp + TCP_PAWS_24DAYS &&
- !tcp_disordered_ack(tp, skb));
+ !tcp_disordered_ack(sk, skb));
}
/* Check segment sequence number for validity.
@@ -2586,7 +2639,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
{
struct tcp_sock *tp = tcp_sk(sk);
- tcp_schedule_ack(tp);
+ inet_csk_schedule_ack(sk);
sk->sk_shutdown |= RCV_SHUTDOWN;
sock_set_flag(sk, SOCK_DONE);
@@ -2596,7 +2649,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
case TCP_ESTABLISHED:
/* Move to CLOSE_WAIT */
tcp_set_state(sk, TCP_CLOSE_WAIT);
- tp->ack.pingpong = 1;
+ inet_csk(sk)->icsk_ack.pingpong = 1;
break;
case TCP_CLOSE_WAIT:
@@ -2694,7 +2747,7 @@ static void tcp_send_dupack(struct sock *sk, struct sk_buff *skb)
if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOST);
- tcp_enter_quickack_mode(tp);
+ tcp_enter_quickack_mode(sk);
if (tp->rx_opt.sack_ok && sysctl_tcp_dsack) {
u32 end_seq = TCP_SKB_CB(skb)->end_seq;
@@ -2853,7 +2906,7 @@ static void tcp_ofo_queue(struct sock *sk)
if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
SOCK_DEBUG(sk, "ofo packet was already received \n");
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &tp->out_of_order_queue);
__kfree_skb(skb);
continue;
}
@@ -2861,7 +2914,7 @@ static void tcp_ofo_queue(struct sock *sk)
tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
TCP_SKB_CB(skb)->end_seq);
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &tp->out_of_order_queue);
__skb_queue_tail(&sk->sk_receive_queue, skb);
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
if(skb->h.th->fin)
@@ -2942,7 +2995,7 @@ queue_and_out:
* gap in queue is filled.
*/
if (skb_queue_empty(&tp->out_of_order_queue))
- tp->ack.pingpong = 0;
+ inet_csk(sk)->icsk_ack.pingpong = 0;
}
if (tp->rx_opt.num_sacks)
@@ -2963,8 +3016,8 @@ queue_and_out:
tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
out_of_window:
- tcp_enter_quickack_mode(tp);
- tcp_schedule_ack(tp);
+ tcp_enter_quickack_mode(sk);
+ inet_csk_schedule_ack(sk);
drop:
__kfree_skb(skb);
return;
@@ -2974,7 +3027,7 @@ drop:
if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp)))
goto out_of_window;
- tcp_enter_quickack_mode(tp);
+ tcp_enter_quickack_mode(sk);
if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
/* Partial packet, seq < rcv_next < end_seq */
@@ -3003,7 +3056,7 @@ drop:
/* Disable header prediction. */
tp->pred_flags = 0;
- tcp_schedule_ack(tp);
+ inet_csk_schedule_ack(sk);
SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
@@ -3027,7 +3080,7 @@ drop:
u32 end_seq = TCP_SKB_CB(skb)->end_seq;
if (seq == TCP_SKB_CB(skb1)->end_seq) {
- __skb_append(skb1, skb);
+ __skb_append(skb1, skb, &tp->out_of_order_queue);
if (!tp->rx_opt.num_sacks ||
tp->selective_acks[0].end_seq != seq)
@@ -3071,7 +3124,7 @@ drop:
tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, end_seq);
break;
}
- __skb_unlink(skb1, skb1->list);
+ __skb_unlink(skb1, &tp->out_of_order_queue);
tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq);
__kfree_skb(skb1);
}
@@ -3088,8 +3141,9 @@ add_sack:
* simplifies code)
*/
static void
-tcp_collapse(struct sock *sk, struct sk_buff *head,
- struct sk_buff *tail, u32 start, u32 end)
+tcp_collapse(struct sock *sk, struct sk_buff_head *list,
+ struct sk_buff *head, struct sk_buff *tail,
+ u32 start, u32 end)
{
struct sk_buff *skb;
@@ -3099,7 +3153,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head,
/* No new bits? It is possible on ofo queue. */
if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
struct sk_buff *next = skb->next;
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, list);
__kfree_skb(skb);
NET_INC_STATS_BH(LINUX_MIB_TCPRCVCOLLAPSED);
skb = next;
@@ -3145,7 +3199,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head,
nskb->mac.raw = nskb->head + (skb->mac.raw-skb->head);
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
- __skb_insert(nskb, skb->prev, skb, skb->list);
+ __skb_insert(nskb, skb->prev, skb, list);
sk_stream_set_owner_r(nskb, sk);
/* Copy data, releasing collapsed skbs. */
@@ -3164,7 +3218,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head,
}
if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
struct sk_buff *next = skb->next;
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, list);
__kfree_skb(skb);
NET_INC_STATS_BH(LINUX_MIB_TCPRCVCOLLAPSED);
skb = next;
@@ -3200,7 +3254,8 @@ static void tcp_collapse_ofo_queue(struct sock *sk)
if (skb == (struct sk_buff *)&tp->out_of_order_queue ||
after(TCP_SKB_CB(skb)->seq, end) ||
before(TCP_SKB_CB(skb)->end_seq, start)) {
- tcp_collapse(sk, head, skb, start, end);
+ tcp_collapse(sk, &tp->out_of_order_queue,
+ head, skb, start, end);
head = skb;
if (skb == (struct sk_buff *)&tp->out_of_order_queue)
break;
@@ -3237,7 +3292,8 @@ static int tcp_prune_queue(struct sock *sk)
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
tcp_collapse_ofo_queue(sk);
- tcp_collapse(sk, sk->sk_receive_queue.next,
+ tcp_collapse(sk, &sk->sk_receive_queue,
+ sk->sk_receive_queue.next,
(struct sk_buff*)&sk->sk_receive_queue,
tp->copied_seq, tp->rcv_nxt);
sk_stream_mem_reclaim(sk);
@@ -3286,12 +3342,12 @@ void tcp_cwnd_application_limited(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
- if (tp->ca_state == TCP_CA_Open &&
+ if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open &&
sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
/* Limited by application or receiver window. */
u32 win_used = max(tp->snd_cwnd_used, 2U);
if (win_used < tp->snd_cwnd) {
- tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_ssthresh = tcp_current_ssthresh(sk);
tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1;
}
tp->snd_cwnd_used = 0;
@@ -3370,13 +3426,13 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
struct tcp_sock *tp = tcp_sk(sk);
/* More than one full frame received... */
- if (((tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss
+ if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss
/* ... and right edge of window advances far enough.
* (tcp_recvmsg() will send ACK otherwise). Or...
*/
&& __tcp_select_window(sk) >= tp->rcv_wnd) ||
/* We ACK each frame or... */
- tcp_in_quickack_mode(tp) ||
+ tcp_in_quickack_mode(sk) ||
/* We have out of order data. */
(ofo_possible &&
skb_peek(&tp->out_of_order_queue))) {
@@ -3390,8 +3446,7 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
static __inline__ void tcp_ack_snd_check(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
- if (!tcp_ack_scheduled(tp)) {
+ if (!inet_csk_ack_scheduled(sk)) {
/* We sent a data segment already. */
return;
}
@@ -3462,7 +3517,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
tp->copied_seq++;
if (skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq)) {
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &sk->sk_receive_queue);
__kfree_skb(skb);
}
}
@@ -3645,7 +3700,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
- tcp_rcv_rtt_measure_ts(tp, skb);
+ tcp_rcv_rtt_measure_ts(sk, skb);
/* We know that such packets are checksummed
* on entry.
@@ -3678,7 +3733,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
- tcp_rcv_rtt_measure_ts(tp, skb);
+ tcp_rcv_rtt_measure_ts(sk, skb);
__skb_pull(skb, tcp_header_len);
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
@@ -3699,7 +3754,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
- tcp_rcv_rtt_measure_ts(tp, skb);
+ tcp_rcv_rtt_measure_ts(sk, skb);
if ((int)skb->truesize > sk->sk_forward_alloc)
goto step5;
@@ -3719,7 +3774,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
/* Well, only one small jumplet in fast path... */
tcp_ack(sk, skb, FLAG_DATA);
tcp_data_snd_check(sk, tp);
- if (!tcp_ack_scheduled(tp))
+ if (!inet_csk_ack_scheduled(sk))
goto no_ack;
}
@@ -3741,7 +3796,7 @@ slow_path:
* RFC1323: H1. Apply PAWS check first.
*/
if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
- tcp_paws_discard(tp, skb)) {
+ tcp_paws_discard(sk, skb)) {
if (!th->rst) {
NET_INC_STATS_BH(LINUX_MIB_PAWSESTABREJECTED);
tcp_send_dupack(sk, skb);
@@ -3788,7 +3843,7 @@ step5:
if(th->ack)
tcp_ack(sk, skb, FLAG_SLOWPATH);
- tcp_rcv_rtt_measure_ts(tp, skb);
+ tcp_rcv_rtt_measure_ts(sk, skb);
/* Process urgent data. */
tcp_urg(sk, skb, th);
@@ -3817,6 +3872,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_parse_options(skb, &tp->rx_opt, 0);
if (th->ack) {
+ struct inet_connection_sock *icsk;
/* rfc793:
* "If the state is SYN-SENT then
* first check the ACK bit
@@ -3920,7 +3976,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_metrics(sk);
- tcp_init_congestion_control(tp);
+ tcp_init_congestion_control(sk);
/* Prevent spurious tcp_cwnd_restart() on first data
* packet.
@@ -3930,7 +3986,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_buffer_space(sk);
if (sock_flag(sk, SOCK_KEEPOPEN))
- tcp_reset_keepalive_timer(sk, keepalive_time_when(tp));
+ inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tp));
if (!tp->rx_opt.snd_wscale)
__tcp_fast_path_on(tp, tp->snd_wnd);
@@ -3942,7 +3998,11 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
sk_wake_async(sk, 0, POLL_OUT);
}
- if (sk->sk_write_pending || tp->defer_accept || tp->ack.pingpong) {
+ icsk = inet_csk(sk);
+
+ if (sk->sk_write_pending ||
+ icsk->icsk_accept_queue.rskq_defer_accept ||
+ icsk->icsk_ack.pingpong) {
/* Save one ACK. Data will be ready after
* several ticks, if write_pending is set.
*
@@ -3950,12 +4010,13 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* look so _wonderfully_ clever, that I was not able
* to stand against the temptation 8) --ANK
*/
- tcp_schedule_ack(tp);
- tp->ack.lrcvtime = tcp_time_stamp;
- tp->ack.ato = TCP_ATO_MIN;
- tcp_incr_quickack(tp);
- tcp_enter_quickack_mode(tp);
- tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+ inet_csk_schedule_ack(sk);
+ icsk->icsk_ack.lrcvtime = tcp_time_stamp;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
+ tcp_incr_quickack(sk);
+ tcp_enter_quickack_mode(sk);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ TCP_DELACK_MAX, TCP_RTO_MAX);
discard:
__kfree_skb(skb);
@@ -4111,7 +4172,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
}
if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
- tcp_paws_discard(tp, skb)) {
+ tcp_paws_discard(sk, skb)) {
if (!th->rst) {
NET_INC_STATS_BH(LINUX_MIB_PAWSESTABREJECTED);
tcp_send_dupack(sk, skb);
@@ -4180,7 +4241,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
*/
if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
!tp->srtt)
- tcp_ack_saw_tstamp(tp, 0, 0);
+ tcp_ack_saw_tstamp(sk, NULL, 0);
if (tp->rx_opt.tstamp_ok)
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
@@ -4192,7 +4253,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_metrics(sk);
- tcp_init_congestion_control(tp);
+ tcp_init_congestion_control(sk);
/* Prevent spurious tcp_cwnd_restart() on
* first data packet.
@@ -4227,9 +4288,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
return 1;
}
- tmo = tcp_fin_time(tp);
+ tmo = tcp_fin_time(sk);
if (tmo > TCP_TIMEWAIT_LEN) {
- tcp_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
+ inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
} else if (th->fin || sock_owned_by_user(sk)) {
/* Bad case. We could lose such FIN otherwise.
* It is not a big problem, but it looks confusing
@@ -4237,7 +4298,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* if it spins in bh_lock_sock(), but it is really
* marginal case.
*/
- tcp_reset_keepalive_timer(sk, tmo);
+ inet_csk_reset_keepalive_timer(sk, tmo);
} else {
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto discard;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 67c670886c1f..13dfb391cdf1 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -64,7 +64,9 @@
#include <linux/times.h>
#include <net/icmp.h>
+#include <net/inet_hashtables.h>
#include <net/tcp.h>
+#include <net/transp_v6.h>
#include <net/ipv6.h>
#include <net/inet_common.h>
#include <net/xfrm.h>
@@ -75,7 +77,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-extern int sysctl_ip_dynaddr;
int sysctl_tcp_tw_reuse;
int sysctl_tcp_low_latency;
@@ -88,463 +89,29 @@ static struct socket *tcp_socket;
void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
struct sk_buff *skb);
-struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = {
- .__tcp_lhash_lock = RW_LOCK_UNLOCKED,
- .__tcp_lhash_users = ATOMIC_INIT(0),
- .__tcp_lhash_wait
- = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.__tcp_lhash_wait),
- .__tcp_portalloc_lock = SPIN_LOCK_UNLOCKED
+struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
+ .lhash_lock = RW_LOCK_UNLOCKED,
+ .lhash_users = ATOMIC_INIT(0),
+ .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
+ .portalloc_lock = SPIN_LOCK_UNLOCKED,
+ .port_rover = 1024 - 1,
};
-/*
- * This array holds the first and last local port number.
- * For high-usage systems, use sysctl to change this to
- * 32768-61000
- */
-int sysctl_local_port_range[2] = { 1024, 4999 };
-int tcp_port_rover = 1024 - 1;
-
-static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
- __u32 faddr, __u16 fport)
-{
- int h = (laddr ^ lport) ^ (faddr ^ fport);
- h ^= h >> 16;
- h ^= h >> 8;
- return h & (tcp_ehash_size - 1);
-}
-
-static __inline__ int tcp_sk_hashfn(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- __u32 laddr = inet->rcv_saddr;
- __u16 lport = inet->num;
- __u32 faddr = inet->daddr;
- __u16 fport = inet->dport;
-
- return tcp_hashfn(laddr, lport, faddr, fport);
-}
-
-/* Allocate and initialize a new TCP local port bind bucket.
- * The bindhash mutex for snum's hash chain must be held here.
- */
-struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
- unsigned short snum)
-{
- struct tcp_bind_bucket *tb = kmem_cache_alloc(tcp_bucket_cachep,
- SLAB_ATOMIC);
- if (tb) {
- tb->port = snum;
- tb->fastreuse = 0;
- INIT_HLIST_HEAD(&tb->owners);
- hlist_add_head(&tb->node, &head->chain);
- }
- return tb;
-}
-
-/* Caller must hold hashbucket lock for this tb with local BH disabled */
-void tcp_bucket_destroy(struct tcp_bind_bucket *tb)
-{
- if (hlist_empty(&tb->owners)) {
- __hlist_del(&tb->node);
- kmem_cache_free(tcp_bucket_cachep, tb);
- }
-}
-
-/* Caller must disable local BH processing. */
-static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
-{
- struct tcp_bind_hashbucket *head =
- &tcp_bhash[tcp_bhashfn(inet_sk(child)->num)];
- struct tcp_bind_bucket *tb;
-
- spin_lock(&head->lock);
- tb = tcp_sk(sk)->bind_hash;
- sk_add_bind_node(child, &tb->owners);
- tcp_sk(child)->bind_hash = tb;
- spin_unlock(&head->lock);
-}
-
-inline void tcp_inherit_port(struct sock *sk, struct sock *child)
-{
- local_bh_disable();
- __tcp_inherit_port(sk, child);
- local_bh_enable();
-}
-
-void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
- unsigned short snum)
-{
- inet_sk(sk)->num = snum;
- sk_add_bind_node(sk, &tb->owners);
- tcp_sk(sk)->bind_hash = tb;
-}
-
-static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
-{
- const u32 sk_rcv_saddr = tcp_v4_rcv_saddr(sk);
- struct sock *sk2;
- struct hlist_node *node;
- int reuse = sk->sk_reuse;
-
- sk_for_each_bound(sk2, node, &tb->owners) {
- if (sk != sk2 &&
- !tcp_v6_ipv6only(sk2) &&
- (!sk->sk_bound_dev_if ||
- !sk2->sk_bound_dev_if ||
- sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
- if (!reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) {
- const u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2);
- if (!sk2_rcv_saddr || !sk_rcv_saddr ||
- sk2_rcv_saddr == sk_rcv_saddr)
- break;
- }
- }
- }
- return node != NULL;
-}
-
-/* Obtain a reference to a local port for the given sock,
- * if snum is zero it means select any available local port.
- */
static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
{
- struct tcp_bind_hashbucket *head;
- struct hlist_node *node;
- struct tcp_bind_bucket *tb;
- int ret;
-
- local_bh_disable();
- if (!snum) {
- int low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int remaining = (high - low) + 1;
- int rover;
-
- spin_lock(&tcp_portalloc_lock);
- if (tcp_port_rover < low)
- rover = low;
- else
- rover = tcp_port_rover;
- do {
- rover++;
- if (rover > high)
- rover = low;
- head = &tcp_bhash[tcp_bhashfn(rover)];
- spin_lock(&head->lock);
- tb_for_each(tb, node, &head->chain)
- if (tb->port == rover)
- goto next;
- break;
- next:
- spin_unlock(&head->lock);
- } while (--remaining > 0);
- tcp_port_rover = rover;
- spin_unlock(&tcp_portalloc_lock);
-
- /* Exhausted local port range during search? It is not
- * possible for us to be holding one of the bind hash
- * locks if this test triggers, because if 'remaining'
- * drops to zero, we broke out of the do/while loop at
- * the top level, not from the 'break;' statement.
- */
- ret = 1;
- if (unlikely(remaining <= 0))
- goto fail;
-
- /* OK, here is the one we will use. HEAD is
- * non-NULL and we hold it's mutex.
- */
- snum = rover;
- } else {
- head = &tcp_bhash[tcp_bhashfn(snum)];
- spin_lock(&head->lock);
- tb_for_each(tb, node, &head->chain)
- if (tb->port == snum)
- goto tb_found;
- }
- tb = NULL;
- goto tb_not_found;
-tb_found:
- if (!hlist_empty(&tb->owners)) {
- if (sk->sk_reuse > 1)
- goto success;
- if (tb->fastreuse > 0 &&
- sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
- goto success;
- } else {
- ret = 1;
- if (tcp_bind_conflict(sk, tb))
- goto fail_unlock;
- }
- }
-tb_not_found:
- ret = 1;
- if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
- goto fail_unlock;
- if (hlist_empty(&tb->owners)) {
- if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
- tb->fastreuse = 1;
- else
- tb->fastreuse = 0;
- } else if (tb->fastreuse &&
- (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
- tb->fastreuse = 0;
-success:
- if (!tcp_sk(sk)->bind_hash)
- tcp_bind_hash(sk, tb, snum);
- BUG_TRAP(tcp_sk(sk)->bind_hash == tb);
- ret = 0;
-
-fail_unlock:
- spin_unlock(&head->lock);
-fail:
- local_bh_enable();
- return ret;
-}
-
-/* Get rid of any references to a local port held by the
- * given sock.
- */
-static void __tcp_put_port(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(inet->num)];
- struct tcp_bind_bucket *tb;
-
- spin_lock(&head->lock);
- tb = tcp_sk(sk)->bind_hash;
- __sk_del_bind_node(sk);
- tcp_sk(sk)->bind_hash = NULL;
- inet->num = 0;
- tcp_bucket_destroy(tb);
- spin_unlock(&head->lock);
-}
-
-void tcp_put_port(struct sock *sk)
-{
- local_bh_disable();
- __tcp_put_port(sk);
- local_bh_enable();
-}
-
-/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
- * Look, when several writers sleep and reader wakes them up, all but one
- * immediately hit write lock and grab all the cpus. Exclusive sleep solves
- * this, _but_ remember, it adds useless work on UP machines (wake up each
- * exclusive lock release). It should be ifdefed really.
- */
-
-void tcp_listen_wlock(void)
-{
- write_lock(&tcp_lhash_lock);
-
- if (atomic_read(&tcp_lhash_users)) {
- DEFINE_WAIT(wait);
-
- for (;;) {
- prepare_to_wait_exclusive(&tcp_lhash_wait,
- &wait, TASK_UNINTERRUPTIBLE);
- if (!atomic_read(&tcp_lhash_users))
- break;
- write_unlock_bh(&tcp_lhash_lock);
- schedule();
- write_lock_bh(&tcp_lhash_lock);
- }
-
- finish_wait(&tcp_lhash_wait, &wait);
- }
-}
-
-static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
-{
- struct hlist_head *list;
- rwlock_t *lock;
-
- BUG_TRAP(sk_unhashed(sk));
- if (listen_possible && sk->sk_state == TCP_LISTEN) {
- list = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
- lock = &tcp_lhash_lock;
- tcp_listen_wlock();
- } else {
- list = &tcp_ehash[(sk->sk_hashent = tcp_sk_hashfn(sk))].chain;
- lock = &tcp_ehash[sk->sk_hashent].lock;
- write_lock(lock);
- }
- __sk_add_node(sk, list);
- sock_prot_inc_use(sk->sk_prot);
- write_unlock(lock);
- if (listen_possible && sk->sk_state == TCP_LISTEN)
- wake_up(&tcp_lhash_wait);
+ return inet_csk_get_port(&tcp_hashinfo, sk, snum);
}
static void tcp_v4_hash(struct sock *sk)
{
- if (sk->sk_state != TCP_CLOSE) {
- local_bh_disable();
- __tcp_v4_hash(sk, 1);
- local_bh_enable();
- }
+ inet_hash(&tcp_hashinfo, sk);
}
void tcp_unhash(struct sock *sk)
{
- rwlock_t *lock;
-
- if (sk_unhashed(sk))
- goto ende;
-
- if (sk->sk_state == TCP_LISTEN) {
- local_bh_disable();
- tcp_listen_wlock();
- lock = &tcp_lhash_lock;
- } else {
- struct tcp_ehash_bucket *head = &tcp_ehash[sk->sk_hashent];
- lock = &head->lock;
- write_lock_bh(&head->lock);
- }
-
- if (__sk_del_node_init(sk))
- sock_prot_dec_use(sk->sk_prot);
- write_unlock_bh(lock);
-
- ende:
- if (sk->sk_state == TCP_LISTEN)
- wake_up(&tcp_lhash_wait);
-}
-
-/* Don't inline this cruft. Here are some nice properties to
- * exploit here. The BSD API does not allow a listening TCP
- * to specify the remote port nor the remote address for the
- * connection. So always assume those are both wildcarded
- * during the search since they can never be otherwise.
- */
-static struct sock *__tcp_v4_lookup_listener(struct hlist_head *head, u32 daddr,
- unsigned short hnum, int dif)
-{
- struct sock *result = NULL, *sk;
- struct hlist_node *node;
- int score, hiscore;
-
- hiscore=-1;
- sk_for_each(sk, node, head) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (inet->num == hnum && !ipv6_only_sock(sk)) {
- __u32 rcv_saddr = inet->rcv_saddr;
-
- score = (sk->sk_family == PF_INET ? 1 : 0);
- if (rcv_saddr) {
- if (rcv_saddr != daddr)
- continue;
- score+=2;
- }
- if (sk->sk_bound_dev_if) {
- if (sk->sk_bound_dev_if != dif)
- continue;
- score+=2;
- }
- if (score == 5)
- return sk;
- if (score > hiscore) {
- hiscore = score;
- result = sk;
- }
- }
- }
- return result;
-}
-
-/* Optimize the common listener case. */
-static inline struct sock *tcp_v4_lookup_listener(u32 daddr,
- unsigned short hnum, int dif)
-{
- struct sock *sk = NULL;
- struct hlist_head *head;
-
- read_lock(&tcp_lhash_lock);
- head = &tcp_listening_hash[tcp_lhashfn(hnum)];
- if (!hlist_empty(head)) {
- struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
-
- if (inet->num == hnum && !sk->sk_node.next &&
- (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
- (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
- !sk->sk_bound_dev_if)
- goto sherry_cache;
- sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
- }
- if (sk) {
-sherry_cache:
- sock_hold(sk);
- }
- read_unlock(&tcp_lhash_lock);
- return sk;
+ inet_unhash(&tcp_hashinfo, sk);
}
-/* 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
- *
- * Local BH must be disabled here.
- */
-
-static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport,
- u32 daddr, u16 hnum,
- int dif)
-{
- struct tcp_ehash_bucket *head;
- TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
- __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
- struct sock *sk;
- struct hlist_node *node;
- /* Optimize here for direct hit, only listening connections can
- * have wildcards anyways.
- */
- int hash = tcp_hashfn(daddr, hnum, saddr, sport);
- head = &tcp_ehash[hash];
- read_lock(&head->lock);
- sk_for_each(sk, node, &head->chain) {
- if (TCP_IPV4_MATCH(sk, acookie, 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 + tcp_ehash_size)->chain) {
- if (TCP_IPV4_TW_MATCH(sk, acookie, saddr, daddr, ports, dif))
- goto hit;
- }
- sk = NULL;
-out:
- read_unlock(&head->lock);
- return sk;
-hit:
- sock_hold(sk);
- goto out;
-}
-
-static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
- u32 daddr, u16 hnum, int dif)
-{
- struct sock *sk = __tcp_v4_lookup_established(saddr, sport,
- daddr, hnum, dif);
-
- return sk ? : tcp_v4_lookup_listener(daddr, hnum, dif);
-}
-
-inline struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr,
- u16 dport, int dif)
-{
- struct sock *sk;
-
- local_bh_disable();
- sk = __tcp_v4_lookup(saddr, sport, daddr, ntohs(dport), dif);
- local_bh_enable();
-
- return sk;
-}
-
-EXPORT_SYMBOL_GPL(tcp_v4_lookup);
-
static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
{
return secure_tcp_sequence_number(skb->nh.iph->daddr,
@@ -555,27 +122,28 @@ static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
/* called with local bh disabled */
static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
- struct tcp_tw_bucket **twp)
+ struct inet_timewait_sock **twp)
{
struct inet_sock *inet = inet_sk(sk);
u32 daddr = inet->rcv_saddr;
u32 saddr = inet->daddr;
int dif = sk->sk_bound_dev_if;
- TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
- __u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
- int hash = tcp_hashfn(daddr, lport, saddr, inet->dport);
- struct tcp_ehash_bucket *head = &tcp_ehash[hash];
+ INET_ADDR_COOKIE(acookie, saddr, daddr)
+ const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+ const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, tcp_hashinfo.ehash_size);
+ struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
struct sock *sk2;
- struct hlist_node *node;
- struct tcp_tw_bucket *tw;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
write_lock(&head->lock);
/* Check TIME-WAIT sockets first. */
- sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) {
- tw = (struct tcp_tw_bucket *)sk2;
+ sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
+ tw = inet_twsk(sk2);
- if (TCP_IPV4_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+ if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+ const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
struct tcp_sock *tp = tcp_sk(sk);
/* With PAWS, it is safe from the viewpoint
@@ -592,15 +160,15 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
fall back to VJ's scheme and use initial
timestamp retrieved from peer table.
*/
- if (tw->tw_ts_recent_stamp &&
+ if (tcptw->tw_ts_recent_stamp &&
(!twp || (sysctl_tcp_tw_reuse &&
xtime.tv_sec -
- tw->tw_ts_recent_stamp > 1))) {
- if ((tp->write_seq =
- tw->tw_snd_nxt + 65535 + 2) == 0)
+ tcptw->tw_ts_recent_stamp > 1))) {
+ tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
+ if (tp->write_seq == 0)
tp->write_seq = 1;
- tp->rx_opt.ts_recent = tw->tw_ts_recent;
- tp->rx_opt.ts_recent_stamp = tw->tw_ts_recent_stamp;
+ tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
+ tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
sock_hold(sk2);
goto unique;
} else
@@ -611,7 +179,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
/* And established part... */
sk_for_each(sk2, node, &head->chain) {
- if (TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+ if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif))
goto not_unique;
}
@@ -631,10 +199,10 @@ unique:
NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
} else if (tw) {
/* Silly. Should hash-dance instead... */
- tcp_tw_deschedule(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);
NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
}
return 0;
@@ -657,9 +225,9 @@ static inline u32 connect_port_offset(const struct sock *sk)
*/
static inline int tcp_v4_hash_connect(struct sock *sk)
{
- unsigned short snum = inet_sk(sk)->num;
- struct tcp_bind_hashbucket *head;
- struct tcp_bind_bucket *tb;
+ const unsigned short snum = inet_sk(sk)->num;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
int ret;
if (!snum) {
@@ -671,19 +239,19 @@ static inline int tcp_v4_hash_connect(struct sock *sk)
static u32 hint;
u32 offset = hint + connect_port_offset(sk);
struct hlist_node *node;
- struct tcp_tw_bucket *tw = NULL;
+ struct inet_timewait_sock *tw = NULL;
local_bh_disable();
for (i = 1; i <= range; i++) {
port = low + (i + offset) % range;
- head = &tcp_bhash[tcp_bhashfn(port)];
+ head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)];
spin_lock(&head->lock);
/* Does not bother with rcv_saddr checks,
* because the established check is already
* unique enough.
*/
- tb_for_each(tb, node, &head->chain) {
+ inet_bind_bucket_for_each(tb, node, &head->chain) {
if (tb->port == port) {
BUG_TRAP(!hlist_empty(&tb->owners));
if (tb->fastreuse >= 0)
@@ -696,7 +264,7 @@ static inline int tcp_v4_hash_connect(struct sock *sk)
}
}
- tb = tcp_bucket_create(head, port);
+ tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
if (!tb) {
spin_unlock(&head->lock);
break;
@@ -715,27 +283,27 @@ ok:
hint += i;
/* Head lock still held and bh's disabled */
- tcp_bind_hash(sk, tb, port);
+ inet_bind_hash(sk, tb, port);
if (sk_unhashed(sk)) {
inet_sk(sk)->sport = htons(port);
- __tcp_v4_hash(sk, 0);
+ __inet_hash(&tcp_hashinfo, sk, 0);
}
spin_unlock(&head->lock);
if (tw) {
- tcp_tw_deschedule(tw);
- tcp_tw_put(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);;
+ inet_twsk_put(tw);
}
ret = 0;
goto out;
}
- head = &tcp_bhash[tcp_bhashfn(snum)];
- tb = tcp_sk(sk)->bind_hash;
+ head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
+ tb = inet_csk(sk)->icsk_bind_hash;
spin_lock_bh(&head->lock);
if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
- __tcp_v4_hash(sk, 0);
+ __inet_hash(&tcp_hashinfo, sk, 0);
spin_unlock_bh(&head->lock);
return 0;
} else {
@@ -798,7 +366,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
tp->write_seq = 0;
}
- if (sysctl_tcp_tw_recycle &&
+ if (tcp_death_row.sysctl_tw_recycle &&
!tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
struct inet_peer *peer = rt_get_peer(rt);
@@ -837,8 +405,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
goto failure;
/* OK, now commit destination to socket. */
- __sk_dst_set(sk, &rt->u.dst);
- tcp_v4_setup_caps(sk, &rt->u.dst);
+ sk_setup_caps(sk, &rt->u.dst);
if (!tp->write_seq)
tp->write_seq = secure_tcp_sequence_number(inet->saddr,
@@ -864,53 +431,6 @@ failure:
return err;
}
-static __inline__ int tcp_v4_iif(struct sk_buff *skb)
-{
- return ((struct rtable *)skb->dst)->rt_iif;
-}
-
-static __inline__ u32 tcp_v4_synq_hash(u32 raddr, u16 rport, u32 rnd)
-{
- return (jhash_2words(raddr, (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1));
-}
-
-static struct request_sock *tcp_v4_search_req(struct tcp_sock *tp,
- struct request_sock ***prevp,
- __u16 rport,
- __u32 raddr, __u32 laddr)
-{
- struct listen_sock *lopt = tp->accept_queue.listen_opt;
- struct request_sock *req, **prev;
-
- for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)];
- (req = *prev) != NULL;
- prev = &req->dl_next) {
- const struct inet_request_sock *ireq = inet_rsk(req);
-
- if (ireq->rmt_port == rport &&
- ireq->rmt_addr == raddr &&
- ireq->loc_addr == laddr &&
- TCP_INET_FAMILY(req->rsk_ops->family)) {
- BUG_TRAP(!req->sk);
- *prevp = prev;
- break;
- }
- }
-
- return req;
-}
-
-static void tcp_v4_synq_add(struct sock *sk, struct request_sock *req)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- struct listen_sock *lopt = tp->accept_queue.listen_opt;
- u32 h = tcp_v4_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
-
- reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
- tcp_synq_added(sk);
-}
-
-
/*
* This routine does path mtu discovery as defined in RFC1191.
*/
@@ -993,14 +513,14 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
return;
}
- sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr,
- th->source, tcp_v4_iif(skb));
+ sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr,
+ th->source, inet_iif(skb));
if (!sk) {
ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
return;
}
if (sk->sk_state == TCP_TIME_WAIT) {
- tcp_tw_put((struct tcp_tw_bucket *)sk);
+ inet_twsk_put((struct inet_timewait_sock *)sk);
return;
}
@@ -1054,8 +574,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
if (sock_owned_by_user(sk))
goto out;
- req = tcp_v4_search_req(tp, &prev, th->dest,
- iph->daddr, iph->saddr);
+ req = inet_csk_search_req(sk, &prev, th->dest,
+ iph->daddr, iph->saddr);
if (!req)
goto out;
@@ -1075,7 +595,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
* created socket, and POSIX does not want network
* errors returned from accept().
*/
- tcp_synq_drop(sk, req, prev);
+ inet_csk_reqsk_queue_drop(sk, req, prev);
goto out;
case TCP_SYN_SENT:
@@ -1245,12 +765,13 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
{
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+ struct inet_timewait_sock *tw = inet_twsk(sk);
+ const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v4_send_ack(skb, tw->tw_snd_nxt, tw->tw_rcv_nxt,
- tw->tw_rcv_wnd >> tw->tw_rcv_wscale, tw->tw_ts_recent);
+ tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent);
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
}
static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
@@ -1259,36 +780,6 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
req->ts_recent);
}
-static struct dst_entry* tcp_v4_route_req(struct sock *sk,
- struct request_sock *req)
-{
- struct rtable *rt;
- const struct inet_request_sock *ireq = inet_rsk(req);
- struct ip_options *opt = inet_rsk(req)->opt;
- struct flowi fl = { .oif = sk->sk_bound_dev_if,
- .nl_u = { .ip4_u =
- { .daddr = ((opt && opt->srr) ?
- opt->faddr :
- ireq->rmt_addr),
- .saddr = ireq->loc_addr,
- .tos = RT_CONN_FLAGS(sk) } },
- .proto = IPPROTO_TCP,
- .uli_u = { .ports =
- { .sport = inet_sk(sk)->sport,
- .dport = ireq->rmt_port } } };
-
- if (ip_route_output_flow(&rt, &fl, sk, 0)) {
- IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
- return NULL;
- }
- if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
- ip_rt_put(rt);
- IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
- return NULL;
- }
- return &rt->u.dst;
-}
-
/*
* Send a SYN-ACK after having received an ACK.
* This still operates on a request_sock only, not on a big
@@ -1302,7 +793,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
struct sk_buff * skb;
/* First, grab a route. */
- if (!dst && (dst = tcp_v4_route_req(sk, req)) == NULL)
+ if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
goto out;
skb = tcp_make_synack(sk, dst, req);
@@ -1404,7 +895,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* limitations, they conserve resources and peer is
* evidently real one.
*/
- if (tcp_synq_is_full(sk) && !isn) {
+ if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
#ifdef CONFIG_SYN_COOKIES
if (sysctl_tcp_syncookies) {
want_cookie = 1;
@@ -1418,7 +909,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* clogging syn queue with openreqs with exponentially increasing
* timeout.
*/
- if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;
req = reqsk_alloc(&tcp_request_sock_ops);
@@ -1474,8 +965,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* are made in the function processing timewait state.
*/
if (tmp_opt.saw_tstamp &&
- sysctl_tcp_tw_recycle &&
- (dst = tcp_v4_route_req(sk, req)) != NULL &&
+ tcp_death_row.sysctl_tw_recycle &&
+ (dst = inet_csk_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) {
if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
@@ -1488,7 +979,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
}
/* Kill the following clause, if you dislike this way. */
else if (!sysctl_tcp_syncookies &&
- (sysctl_max_syn_backlog - tcp_synq_len(sk) <
+ (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
(sysctl_max_syn_backlog >> 2)) &&
(!peer || !peer->tcp_ts_stamp) &&
(!dst || !dst_metric(dst, RTAX_RTT))) {
@@ -1499,11 +990,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* to destinations, already remembered
* to the moment of synflood.
*/
- LIMIT_NETDEBUG(printk(KERN_DEBUG "TCP: drop open "
- "request from %u.%u."
- "%u.%u/%u\n",
- NIPQUAD(saddr),
- ntohs(skb->h.th->source)));
+ LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
+ "request from %u.%u.%u.%u/%u\n",
+ NIPQUAD(saddr),
+ ntohs(skb->h.th->source));
dst_release(dst);
goto drop_and_free;
}
@@ -1518,7 +1008,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (want_cookie) {
reqsk_free(req);
} else {
- tcp_v4_synq_add(sk, req);
+ inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
}
return 0;
@@ -1546,15 +1036,14 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (sk_acceptq_is_full(sk))
goto exit_overflow;
- if (!dst && (dst = tcp_v4_route_req(sk, req)) == NULL)
+ if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
goto exit;
newsk = tcp_create_openreq_child(sk, req, skb);
if (!newsk)
goto exit;
- newsk->sk_dst_cache = dst;
- tcp_v4_setup_caps(newsk, dst);
+ sk_setup_caps(newsk, dst);
newtp = tcp_sk(newsk);
newinet = inet_sk(newsk);
@@ -1564,7 +1053,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newinet->saddr = ireq->loc_addr;
newinet->opt = ireq->opt;
ireq->opt = NULL;
- newinet->mc_index = tcp_v4_iif(skb);
+ newinet->mc_index = inet_iif(skb);
newinet->mc_ttl = skb->nh.iph->ttl;
newtp->ext_header_len = 0;
if (newinet->opt)
@@ -1575,8 +1064,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(newsk);
- __tcp_v4_hash(newsk, 0);
- __tcp_inherit_port(sk, newsk);
+ __inet_hash(&tcp_hashinfo, newsk, 0);
+ __inet_inherit_port(&tcp_hashinfo, sk, newsk);
return newsk;
@@ -1592,27 +1081,24 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
{
struct tcphdr *th = skb->h.th;
struct iphdr *iph = skb->nh.iph;
- struct tcp_sock *tp = tcp_sk(sk);
struct sock *nsk;
struct request_sock **prev;
/* Find possible connection requests. */
- struct request_sock *req = tcp_v4_search_req(tp, &prev, th->source,
- iph->saddr, iph->daddr);
+ struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
+ iph->saddr, iph->daddr);
if (req)
return tcp_check_req(sk, skb, req, prev);
- nsk = __tcp_v4_lookup_established(skb->nh.iph->saddr,
- th->source,
- skb->nh.iph->daddr,
- ntohs(th->dest),
- tcp_v4_iif(skb));
+ nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
+ th->source, skb->nh.iph->daddr,
+ ntohs(th->dest), inet_iif(skb));
if (nsk) {
if (nsk->sk_state != TCP_TIME_WAIT) {
bh_lock_sock(nsk);
return nsk;
}
- tcp_tw_put((struct tcp_tw_bucket *)nsk);
+ inet_twsk_put((struct inet_timewait_sock *)nsk);
return NULL;
}
@@ -1631,7 +1117,7 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
skb->nh.iph->daddr, skb->csum))
return 0;
- LIMIT_NETDEBUG(printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v4 csum failed\n");
skb->ip_summed = CHECKSUM_NONE;
}
if (skb->len <= 76) {
@@ -1747,9 +1233,9 @@ int tcp_v4_rcv(struct sk_buff *skb)
TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
TCP_SKB_CB(skb)->sacked = 0;
- sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
- skb->nh.iph->daddr, ntohs(th->dest),
- tcp_v4_iif(skb));
+ sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source,
+ skb->nh.iph->daddr, ntohs(th->dest),
+ inet_iif(skb));
if (!sk)
goto no_tcp_socket;
@@ -1801,24 +1287,26 @@ discard_and_relse:
do_time_wait:
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- tcp_tw_put((struct tcp_tw_bucket *) sk);
+ inet_twsk_put((struct inet_timewait_sock *) sk);
goto discard_it;
}
if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TCP_MIB_INERRS);
- tcp_tw_put((struct tcp_tw_bucket *) sk);
+ inet_twsk_put((struct inet_timewait_sock *) sk);
goto discard_it;
}
- switch (tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
- skb, th, skb->len)) {
+ switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
+ skb, th)) {
case TCP_TW_SYN: {
- struct sock *sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr,
- ntohs(th->dest),
- tcp_v4_iif(skb));
+ struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
+ skb->nh.iph->daddr,
+ ntohs(th->dest),
+ inet_iif(skb));
if (sk2) {
- tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
- tcp_tw_put((struct tcp_tw_bucket *)sk);
+ inet_twsk_deschedule((struct inet_timewait_sock *)sk,
+ &tcp_death_row);
+ inet_twsk_put((struct inet_timewait_sock *)sk);
sk = sk2;
goto process;
}
@@ -1834,112 +1322,6 @@ do_time_wait:
goto discard_it;
}
-/* With per-bucket locks this operation is not-atomic, so that
- * this version is not worse.
- */
-static void __tcp_v4_rehash(struct sock *sk)
-{
- sk->sk_prot->unhash(sk);
- sk->sk_prot->hash(sk);
-}
-
-static int tcp_v4_reselect_saddr(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- int err;
- struct rtable *rt;
- __u32 old_saddr = inet->saddr;
- __u32 new_saddr;
- __u32 daddr = inet->daddr;
-
- if (inet->opt && inet->opt->srr)
- daddr = inet->opt->faddr;
-
- /* Query new route. */
- err = ip_route_connect(&rt, daddr, 0,
- RT_CONN_FLAGS(sk),
- sk->sk_bound_dev_if,
- IPPROTO_TCP,
- inet->sport, inet->dport, sk);
- if (err)
- return err;
-
- __sk_dst_set(sk, &rt->u.dst);
- tcp_v4_setup_caps(sk, &rt->u.dst);
-
- new_saddr = rt->rt_src;
-
- if (new_saddr == old_saddr)
- return 0;
-
- if (sysctl_ip_dynaddr > 1) {
- printk(KERN_INFO "tcp_v4_rebuild_header(): shifting inet->"
- "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
- NIPQUAD(old_saddr),
- NIPQUAD(new_saddr));
- }
-
- inet->saddr = new_saddr;
- inet->rcv_saddr = new_saddr;
-
- /* XXX The only one ugly spot where we need to
- * XXX really change the sockets identity after
- * XXX it has entered the hashes. -DaveM
- *
- * Besides that, it does not check for connection
- * uniqueness. Wait for troubles.
- */
- __tcp_v4_rehash(sk);
- return 0;
-}
-
-int tcp_v4_rebuild_header(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
- u32 daddr;
- int err;
-
- /* Route is OK, nothing to do. */
- if (rt)
- return 0;
-
- /* Reroute. */
- daddr = inet->daddr;
- if (inet->opt && inet->opt->srr)
- daddr = inet->opt->faddr;
-
- {
- struct flowi fl = { .oif = sk->sk_bound_dev_if,
- .nl_u = { .ip4_u =
- { .daddr = daddr,
- .saddr = inet->saddr,
- .tos = RT_CONN_FLAGS(sk) } },
- .proto = IPPROTO_TCP,
- .uli_u = { .ports =
- { .sport = inet->sport,
- .dport = inet->dport } } };
-
- err = ip_route_output_flow(&rt, &fl, sk, 0);
- }
- if (!err) {
- __sk_dst_set(sk, &rt->u.dst);
- tcp_v4_setup_caps(sk, &rt->u.dst);
- return 0;
- }
-
- /* Routing failed... */
- sk->sk_route_caps = 0;
-
- if (!sysctl_ip_dynaddr ||
- sk->sk_state != TCP_SYN_SENT ||
- (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
- (err = tcp_v4_reselect_saddr(sk)) != 0)
- sk->sk_err_soft = -err;
-
- return err;
-}
-
static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
{
struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
@@ -1988,18 +1370,18 @@ int tcp_v4_remember_stamp(struct sock *sk)
return 0;
}
-int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
+int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
{
- struct inet_peer *peer = NULL;
-
- peer = inet_getpeer(tw->tw_daddr, 1);
+ struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
if (peer) {
- if ((s32)(peer->tcp_ts - tw->tw_ts_recent) <= 0 ||
+ const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
+
+ if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
(peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
- peer->tcp_ts_stamp <= tw->tw_ts_recent_stamp)) {
- peer->tcp_ts_stamp = tw->tw_ts_recent_stamp;
- peer->tcp_ts = tw->tw_ts_recent;
+ peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {
+ peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;
+ peer->tcp_ts = tcptw->tw_ts_recent;
}
inet_putpeer(peer);
return 1;
@@ -2011,7 +1393,7 @@ int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
struct tcp_func ipv4_specific = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
- .rebuild_header = tcp_v4_rebuild_header,
+ .rebuild_header = inet_sk_rebuild_header,
.conn_request = tcp_v4_conn_request,
.syn_recv_sock = tcp_v4_syn_recv_sock,
.remember_stamp = tcp_v4_remember_stamp,
@@ -2027,13 +1409,14 @@ struct tcp_func ipv4_specific = {
*/
static int tcp_v4_init_sock(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
skb_queue_head_init(&tp->out_of_order_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);
- tp->rto = TCP_TIMEOUT_INIT;
+ icsk->icsk_rto = TCP_TIMEOUT_INIT;
tp->mdev = TCP_TIMEOUT_INIT;
/* So many TCP implementations out there (incorrectly) count the
@@ -2051,7 +1434,7 @@ static int tcp_v4_init_sock(struct sock *sk)
tp->mss_cache = 536;
tp->reordering = sysctl_tcp_reordering;
- tp->ca_ops = &tcp_init_congestion_ops;
+ icsk->icsk_ca_ops = &tcp_init_congestion_ops;
sk->sk_state = TCP_CLOSE;
@@ -2074,7 +1457,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
tcp_clear_xmit_timers(sk);
- tcp_cleanup_congestion_control(tp);
+ tcp_cleanup_congestion_control(sk);
/* Cleanup up the write buffer. */
sk_stream_writequeue_purge(sk);
@@ -2086,8 +1469,8 @@ int tcp_v4_destroy_sock(struct sock *sk)
__skb_queue_purge(&tp->ucopy.prequeue);
/* Clean up a referenced TCP bind bucket. */
- if (tp->bind_hash)
- tcp_put_port(sk);
+ if (inet_csk(sk)->icsk_bind_hash)
+ inet_put_port(&tcp_hashinfo, sk);
/*
* If sendmsg cached page exists, toss it.
@@ -2107,13 +1490,13 @@ EXPORT_SYMBOL(tcp_v4_destroy_sock);
#ifdef CONFIG_PROC_FS
/* Proc filesystem TCP sock list dumping. */
-static inline struct tcp_tw_bucket *tw_head(struct hlist_head *head)
+static inline struct inet_timewait_sock *tw_head(struct hlist_head *head)
{
return hlist_empty(head) ? NULL :
- list_entry(head->first, struct tcp_tw_bucket, tw_node);
+ list_entry(head->first, struct inet_timewait_sock, tw_node);
}
-static inline struct tcp_tw_bucket *tw_next(struct tcp_tw_bucket *tw)
+static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
{
return tw->tw_node.next ?
hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
@@ -2121,14 +1504,14 @@ static inline struct tcp_tw_bucket *tw_next(struct tcp_tw_bucket *tw)
static void *listening_get_next(struct seq_file *seq, void *cur)
{
- struct tcp_sock *tp;
+ struct inet_connection_sock *icsk;
struct hlist_node *node;
struct sock *sk = cur;
struct tcp_iter_state* st = seq->private;
if (!sk) {
st->bucket = 0;
- sk = sk_head(&tcp_listening_hash[0]);
+ sk = sk_head(&tcp_hashinfo.listening_hash[0]);
goto get_sk;
}
@@ -2137,7 +1520,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (st->state == TCP_SEQ_STATE_OPENREQ) {
struct request_sock *req = cur;
- tp = tcp_sk(st->syn_wait_sk);
+ icsk = inet_csk(st->syn_wait_sk);
req = req->dl_next;
while (1) {
while (req) {
@@ -2150,17 +1533,17 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (++st->sbucket >= TCP_SYNQ_HSIZE)
break;
get_req:
- req = tp->accept_queue.listen_opt->syn_table[st->sbucket];
+ req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
}
sk = sk_next(st->syn_wait_sk);
st->state = TCP_SEQ_STATE_LISTENING;
- read_unlock_bh(&tp->accept_queue.syn_wait_lock);
+ read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
} else {
- tp = tcp_sk(sk);
- read_lock_bh(&tp->accept_queue.syn_wait_lock);
- if (reqsk_queue_len(&tp->accept_queue))
+ icsk = inet_csk(sk);
+ read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
+ if (reqsk_queue_len(&icsk->icsk_accept_queue))
goto start_req;
- read_unlock_bh(&tp->accept_queue.syn_wait_lock);
+ read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
sk = sk_next(sk);
}
get_sk:
@@ -2169,9 +1552,9 @@ get_sk:
cur = sk;
goto out;
}
- tp = tcp_sk(sk);
- read_lock_bh(&tp->accept_queue.syn_wait_lock);
- if (reqsk_queue_len(&tp->accept_queue)) {
+ icsk = inet_csk(sk);
+ read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
+ if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
start_req:
st->uid = sock_i_uid(sk);
st->syn_wait_sk = sk;
@@ -2179,10 +1562,10 @@ start_req:
st->sbucket = 0;
goto get_req;
}
- read_unlock_bh(&tp->accept_queue.syn_wait_lock);
+ read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
}
- if (++st->bucket < TCP_LHTABLE_SIZE) {
- sk = sk_head(&tcp_listening_hash[st->bucket]);
+ if (++st->bucket < INET_LHTABLE_SIZE) {
+ sk = sk_head(&tcp_hashinfo.listening_hash[st->bucket]);
goto get_sk;
}
cur = NULL;
@@ -2206,16 +1589,16 @@ static void *established_get_first(struct seq_file *seq)
struct tcp_iter_state* st = seq->private;
void *rc = NULL;
- for (st->bucket = 0; st->bucket < tcp_ehash_size; ++st->bucket) {
+ for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
struct sock *sk;
struct hlist_node *node;
- struct tcp_tw_bucket *tw;
+ struct inet_timewait_sock *tw;
/* We can reschedule _before_ having picked the target: */
cond_resched_softirq();
- read_lock(&tcp_ehash[st->bucket].lock);
- sk_for_each(sk, node, &tcp_ehash[st->bucket].chain) {
+ read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+ sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
if (sk->sk_family != st->family) {
continue;
}
@@ -2223,15 +1606,15 @@ static void *established_get_first(struct seq_file *seq)
goto out;
}
st->state = TCP_SEQ_STATE_TIME_WAIT;
- tw_for_each(tw, node,
- &tcp_ehash[st->bucket + tcp_ehash_size].chain) {
+ inet_twsk_for_each(tw, node,
+ &tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain) {
if (tw->tw_family != st->family) {
continue;
}
rc = tw;
goto out;
}
- read_unlock(&tcp_ehash[st->bucket].lock);
+ read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
st->state = TCP_SEQ_STATE_ESTABLISHED;
}
out:
@@ -2241,7 +1624,7 @@ out:
static void *established_get_next(struct seq_file *seq, void *cur)
{
struct sock *sk = cur;
- struct tcp_tw_bucket *tw;
+ struct inet_timewait_sock *tw;
struct hlist_node *node;
struct tcp_iter_state* st = seq->private;
@@ -2258,15 +1641,15 @@ get_tw:
cur = tw;
goto out;
}
- read_unlock(&tcp_ehash[st->bucket].lock);
+ read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
st->state = TCP_SEQ_STATE_ESTABLISHED;
/* We can reschedule between buckets: */
cond_resched_softirq();
- if (++st->bucket < tcp_ehash_size) {
- read_lock(&tcp_ehash[st->bucket].lock);
- sk = sk_head(&tcp_ehash[st->bucket].chain);
+ if (++st->bucket < tcp_hashinfo.ehash_size) {
+ read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+ sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
} else {
cur = NULL;
goto out;
@@ -2280,7 +1663,7 @@ get_tw:
}
st->state = TCP_SEQ_STATE_TIME_WAIT;
- tw = tw_head(&tcp_ehash[st->bucket + tcp_ehash_size].chain);
+ tw = tw_head(&tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain);
goto get_tw;
found:
cur = sk;
@@ -2304,12 +1687,12 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
void *rc;
struct tcp_iter_state* st = seq->private;
- tcp_listen_lock();
+ inet_listen_lock(&tcp_hashinfo);
st->state = TCP_SEQ_STATE_LISTENING;
rc = listening_get_idx(seq, &pos);
if (!rc) {
- tcp_listen_unlock();
+ inet_listen_unlock(&tcp_hashinfo);
local_bh_disable();
st->state = TCP_SEQ_STATE_ESTABLISHED;
rc = established_get_idx(seq, pos);
@@ -2342,7 +1725,7 @@ static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
case TCP_SEQ_STATE_LISTENING:
rc = listening_get_next(seq, v);
if (!rc) {
- tcp_listen_unlock();
+ inet_listen_unlock(&tcp_hashinfo);
local_bh_disable();
st->state = TCP_SEQ_STATE_ESTABLISHED;
rc = established_get_first(seq);
@@ -2365,17 +1748,17 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
switch (st->state) {
case TCP_SEQ_STATE_OPENREQ:
if (v) {
- struct tcp_sock *tp = tcp_sk(st->syn_wait_sk);
- read_unlock_bh(&tp->accept_queue.syn_wait_lock);
+ struct inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);
+ read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
}
case TCP_SEQ_STATE_LISTENING:
if (v != SEQ_START_TOKEN)
- tcp_listen_unlock();
+ inet_listen_unlock(&tcp_hashinfo);
break;
case TCP_SEQ_STATE_TIME_WAIT:
case TCP_SEQ_STATE_ESTABLISHED:
if (v)
- read_unlock(&tcp_ehash[st->bucket].lock);
+ read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
local_bh_enable();
break;
}
@@ -2472,18 +1855,19 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
int timer_active;
unsigned long timer_expires;
struct tcp_sock *tp = tcp_sk(sp);
+ const struct inet_connection_sock *icsk = inet_csk(sp);
struct inet_sock *inet = inet_sk(sp);
unsigned int dest = inet->daddr;
unsigned int src = inet->rcv_saddr;
__u16 destp = ntohs(inet->dport);
__u16 srcp = ntohs(inet->sport);
- if (tp->pending == TCP_TIME_RETRANS) {
+ if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
timer_active = 1;
- timer_expires = tp->timeout;
- } else if (tp->pending == TCP_TIME_PROBE0) {
+ timer_expires = icsk->icsk_timeout;
+ } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
timer_active = 4;
- timer_expires = tp->timeout;
+ timer_expires = icsk->icsk_timeout;
} else if (timer_pending(&sp->sk_timer)) {
timer_active = 2;
timer_expires = sp->sk_timer.expires;
@@ -2498,17 +1882,19 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
tp->write_seq - tp->snd_una, tp->rcv_nxt - tp->copied_seq,
timer_active,
jiffies_to_clock_t(timer_expires - jiffies),
- tp->retransmits,
+ icsk->icsk_retransmits,
sock_i_uid(sp),
- tp->probes_out,
+ icsk->icsk_probes_out,
sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- tp->rto, tp->ack.ato, (tp->ack.quick << 1) | tp->ack.pingpong,
+ icsk->icsk_rto,
+ icsk->icsk_ack.ato,
+ (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
tp->snd_cwnd,
tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
}
-static void get_timewait4_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i)
{
unsigned int dest, src;
__u16 destp, srcp;
@@ -2588,7 +1974,7 @@ struct proto tcp_prot = {
.close = tcp_close,
.connect = tcp_v4_connect,
.disconnect = tcp_disconnect,
- .accept = tcp_accept,
+ .accept = inet_csk_accept,
.ioctl = tcp_ioctl,
.init = tcp_v4_init_sock,
.destroy = tcp_v4_destroy_sock,
@@ -2603,6 +1989,7 @@ struct proto tcp_prot = {
.get_port = tcp_v4_get_port,
.enter_memory_pressure = tcp_enter_memory_pressure,
.sockets_allocated = &tcp_sockets_allocated,
+ .orphan_count = &tcp_orphan_count,
.memory_allocated = &tcp_memory_allocated,
.memory_pressure = &tcp_memory_pressure,
.sysctl_mem = sysctl_tcp_mem,
@@ -2610,6 +1997,7 @@ struct proto tcp_prot = {
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp_sock),
+ .twsk_obj_size = sizeof(struct tcp_timewait_sock),
.rsk_prot = &tcp_request_sock_ops,
};
@@ -2631,19 +2019,13 @@ void __init tcp_v4_init(struct net_proto_family *ops)
}
EXPORT_SYMBOL(ipv4_specific);
-EXPORT_SYMBOL(tcp_bind_hash);
-EXPORT_SYMBOL(tcp_bucket_create);
+EXPORT_SYMBOL(inet_bind_bucket_create);
EXPORT_SYMBOL(tcp_hashinfo);
-EXPORT_SYMBOL(tcp_inherit_port);
-EXPORT_SYMBOL(tcp_listen_wlock);
-EXPORT_SYMBOL(tcp_port_rover);
EXPORT_SYMBOL(tcp_prot);
-EXPORT_SYMBOL(tcp_put_port);
EXPORT_SYMBOL(tcp_unhash);
EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_v4_connect);
EXPORT_SYMBOL(tcp_v4_do_rcv);
-EXPORT_SYMBOL(tcp_v4_rebuild_header);
EXPORT_SYMBOL(tcp_v4_remember_stamp);
EXPORT_SYMBOL(tcp_v4_send_check);
EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index f42a284164b7..a88db28b0af7 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -35,13 +35,27 @@
#define SYNC_INIT 1
#endif
-int sysctl_tcp_tw_recycle;
-int sysctl_tcp_max_tw_buckets = NR_FILE*2;
-
int sysctl_tcp_syncookies = SYNC_INIT;
int sysctl_tcp_abort_on_overflow;
-static void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo);
+struct inet_timewait_death_row tcp_death_row = {
+ .sysctl_max_tw_buckets = NR_FILE * 2,
+ .period = TCP_TIMEWAIT_LEN / INET_TWDR_TWKILL_SLOTS,
+ .death_lock = SPIN_LOCK_UNLOCKED,
+ .hashinfo = &tcp_hashinfo,
+ .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0,
+ (unsigned long)&tcp_death_row),
+ .twkill_work = __WORK_INITIALIZER(tcp_death_row.twkill_work,
+ inet_twdr_twkill_work,
+ &tcp_death_row),
+/* Short-time timewait calendar */
+
+ .twcal_hand = -1,
+ .twcal_timer = TIMER_INITIALIZER(inet_twdr_twcal_tick, 0,
+ (unsigned long)&tcp_death_row),
+};
+
+EXPORT_SYMBOL_GPL(tcp_death_row);
static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
{
@@ -52,47 +66,6 @@ static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
return (seq == e_win && seq == end_seq);
}
-/* New-style handling of TIME_WAIT sockets. */
-
-int tcp_tw_count;
-
-
-/* Must be called with locally disabled BHs. */
-static void tcp_timewait_kill(struct tcp_tw_bucket *tw)
-{
- struct tcp_ehash_bucket *ehead;
- struct tcp_bind_hashbucket *bhead;
- struct tcp_bind_bucket *tb;
-
- /* Unlink from established hashes. */
- ehead = &tcp_ehash[tw->tw_hashent];
- write_lock(&ehead->lock);
- if (hlist_unhashed(&tw->tw_node)) {
- write_unlock(&ehead->lock);
- return;
- }
- __hlist_del(&tw->tw_node);
- sk_node_init(&tw->tw_node);
- write_unlock(&ehead->lock);
-
- /* Disassociate with bind bucket. */
- bhead = &tcp_bhash[tcp_bhashfn(tw->tw_num)];
- spin_lock(&bhead->lock);
- tb = tw->tw_tb;
- __hlist_del(&tw->tw_bind_node);
- tw->tw_tb = NULL;
- tcp_bucket_destroy(tb);
- spin_unlock(&bhead->lock);
-
-#ifdef INET_REFCNT_DEBUG
- if (atomic_read(&tw->tw_refcnt) != 1) {
- printk(KERN_DEBUG "tw_bucket %p refcnt=%d\n", tw,
- atomic_read(&tw->tw_refcnt));
- }
-#endif
- tcp_tw_put(tw);
-}
-
/*
* * Main purpose of TIME-WAIT state is to close connection gracefully,
* when one of ends sits in LAST-ACK or CLOSING retransmitting FIN
@@ -122,19 +95,20 @@ static void tcp_timewait_kill(struct tcp_tw_bucket *tw)
* to avoid misread sequence numbers, states etc. --ANK
*/
enum tcp_tw_status
-tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
- struct tcphdr *th, unsigned len)
+tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
+ const struct tcphdr *th)
{
+ struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
struct tcp_options_received tmp_opt;
int paws_reject = 0;
tmp_opt.saw_tstamp = 0;
- if (th->doff > (sizeof(struct tcphdr) >> 2) && tw->tw_ts_recent_stamp) {
+ if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
tcp_parse_options(skb, &tmp_opt, 0);
if (tmp_opt.saw_tstamp) {
- tmp_opt.ts_recent = tw->tw_ts_recent;
- tmp_opt.ts_recent_stamp = tw->tw_ts_recent_stamp;
+ tmp_opt.ts_recent = tcptw->tw_ts_recent;
+ tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
paws_reject = tcp_paws_check(&tmp_opt, th->rst);
}
}
@@ -145,20 +119,20 @@ tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
/* Out of window, send ACK */
if (paws_reject ||
!tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
- tw->tw_rcv_nxt,
- tw->tw_rcv_nxt + tw->tw_rcv_wnd))
+ tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd))
return TCP_TW_ACK;
if (th->rst)
goto kill;
- if (th->syn && !before(TCP_SKB_CB(skb)->seq, tw->tw_rcv_nxt))
+ if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt))
goto kill_with_rst;
/* Dup ACK? */
- if (!after(TCP_SKB_CB(skb)->end_seq, tw->tw_rcv_nxt) ||
+ if (!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
return TCP_TW_SUCCESS;
}
@@ -166,19 +140,19 @@ tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
* reset.
*/
if (!th->fin ||
- TCP_SKB_CB(skb)->end_seq != tw->tw_rcv_nxt + 1) {
+ TCP_SKB_CB(skb)->end_seq != tcptw->tw_rcv_nxt + 1) {
kill_with_rst:
- tcp_tw_deschedule(tw);
- tcp_tw_put(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);
+ inet_twsk_put(tw);
return TCP_TW_RST;
}
/* FIN arrived, enter true time-wait state. */
- tw->tw_substate = TCP_TIME_WAIT;
- tw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tw->tw_substate = TCP_TIME_WAIT;
+ tcptw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq;
if (tmp_opt.saw_tstamp) {
- tw->tw_ts_recent_stamp = xtime.tv_sec;
- tw->tw_ts_recent = tmp_opt.rcv_tsval;
+ tcptw->tw_ts_recent_stamp = xtime.tv_sec;
+ tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
}
/* I am shamed, but failed to make it more elegant.
@@ -187,11 +161,13 @@ kill_with_rst:
* do not undertsnad recycling in any case, it not
* a big problem in practice. --ANK */
if (tw->tw_family == AF_INET &&
- sysctl_tcp_tw_recycle && tw->tw_ts_recent_stamp &&
+ tcp_death_row.sysctl_tw_recycle && tcptw->tw_ts_recent_stamp &&
tcp_v4_tw_remember_stamp(tw))
- tcp_tw_schedule(tw, tw->tw_timeout);
+ inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
+ TCP_TIMEWAIT_LEN);
else
- tcp_tw_schedule(tw, TCP_TIMEWAIT_LEN);
+ inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
+ TCP_TIMEWAIT_LEN);
return TCP_TW_ACK;
}
@@ -213,7 +189,7 @@ kill_with_rst:
*/
if (!paws_reject &&
- (TCP_SKB_CB(skb)->seq == tw->tw_rcv_nxt &&
+ (TCP_SKB_CB(skb)->seq == tcptw->tw_rcv_nxt &&
(TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq || th->rst))) {
/* In window segment, it may be only reset or bare ack. */
@@ -224,19 +200,20 @@ kill_with_rst:
*/
if (sysctl_tcp_rfc1337 == 0) {
kill:
- tcp_tw_deschedule(tw);
- tcp_tw_put(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);
+ inet_twsk_put(tw);
return TCP_TW_SUCCESS;
}
}
- tcp_tw_schedule(tw, TCP_TIMEWAIT_LEN);
+ inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
+ TCP_TIMEWAIT_LEN);
if (tmp_opt.saw_tstamp) {
- tw->tw_ts_recent = tmp_opt.rcv_tsval;
- tw->tw_ts_recent_stamp = xtime.tv_sec;
+ tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
+ tcptw->tw_ts_recent_stamp = xtime.tv_sec;
}
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
return TCP_TW_SUCCESS;
}
@@ -258,9 +235,10 @@ kill:
*/
if (th->syn && !th->rst && !th->ack && !paws_reject &&
- (after(TCP_SKB_CB(skb)->seq, tw->tw_rcv_nxt) ||
- (tmp_opt.saw_tstamp && (s32)(tw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) {
- u32 isn = tw->tw_snd_nxt + 65535 + 2;
+ (after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) ||
+ (tmp_opt.saw_tstamp &&
+ (s32)(tcptw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) {
+ u32 isn = tcptw->tw_snd_nxt + 65535 + 2;
if (isn == 0)
isn++;
TCP_SKB_CB(skb)->when = isn;
@@ -278,107 +256,57 @@ kill:
* Do not reschedule in the last case.
*/
if (paws_reject || th->ack)
- tcp_tw_schedule(tw, TCP_TIMEWAIT_LEN);
+ inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
+ TCP_TIMEWAIT_LEN);
/* Send ACK. Note, we do not put the bucket,
* it will be released by caller.
*/
return TCP_TW_ACK;
}
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
return TCP_TW_SUCCESS;
}
-/* Enter the time wait state. This is called with locally disabled BH.
- * Essentially we whip up a timewait bucket, copy the
- * relevant info into it from the SK, and mess with hash chains
- * and list linkage.
- */
-static void __tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *tw)
-{
- struct tcp_ehash_bucket *ehead = &tcp_ehash[sk->sk_hashent];
- struct tcp_bind_hashbucket *bhead;
-
- /* Step 1: Put TW into bind hash. Original socket stays there too.
- Note, that any socket with inet_sk(sk)->num != 0 MUST be bound in
- binding cache, even if it is closed.
- */
- bhead = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)];
- spin_lock(&bhead->lock);
- tw->tw_tb = tcp_sk(sk)->bind_hash;
- BUG_TRAP(tcp_sk(sk)->bind_hash);
- tw_add_bind_node(tw, &tw->tw_tb->owners);
- spin_unlock(&bhead->lock);
-
- write_lock(&ehead->lock);
-
- /* Step 2: Remove SK from established hash. */
- if (__sk_del_node_init(sk))
- sock_prot_dec_use(sk->sk_prot);
-
- /* Step 3: Hash TW into TIMEWAIT half of established hash table. */
- tw_add_node(tw, &(ehead + tcp_ehash_size)->chain);
- atomic_inc(&tw->tw_refcnt);
-
- write_unlock(&ehead->lock);
-}
-
/*
* Move a socket to time-wait or dead fin-wait-2 state.
*/
void tcp_time_wait(struct sock *sk, int state, int timeo)
{
- struct tcp_tw_bucket *tw = NULL;
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_timewait_sock *tw = NULL;
+ const struct tcp_sock *tp = tcp_sk(sk);
int recycle_ok = 0;
- if (sysctl_tcp_tw_recycle && tp->rx_opt.ts_recent_stamp)
+ if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
recycle_ok = tp->af_specific->remember_stamp(sk);
- if (tcp_tw_count < sysctl_tcp_max_tw_buckets)
- tw = kmem_cache_alloc(tcp_timewait_cachep, SLAB_ATOMIC);
-
- if(tw != NULL) {
- struct inet_sock *inet = inet_sk(sk);
- int rto = (tp->rto<<2) - (tp->rto>>1);
-
- /* Give us an identity. */
- tw->tw_daddr = inet->daddr;
- tw->tw_rcv_saddr = inet->rcv_saddr;
- tw->tw_bound_dev_if = sk->sk_bound_dev_if;
- tw->tw_num = inet->num;
- tw->tw_state = TCP_TIME_WAIT;
- tw->tw_substate = state;
- tw->tw_sport = inet->sport;
- tw->tw_dport = inet->dport;
- tw->tw_family = sk->sk_family;
- tw->tw_reuse = sk->sk_reuse;
- tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
- atomic_set(&tw->tw_refcnt, 1);
+ if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
+ tw = inet_twsk_alloc(sk, state);
- tw->tw_hashent = sk->sk_hashent;
- tw->tw_rcv_nxt = tp->rcv_nxt;
- tw->tw_snd_nxt = tp->snd_nxt;
- tw->tw_rcv_wnd = tcp_receive_window(tp);
- tw->tw_ts_recent = tp->rx_opt.ts_recent;
- tw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
- tw_dead_node_init(tw);
+ if (tw != NULL) {
+ struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
+
+ tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
+ tcptw->tw_rcv_nxt = tp->rcv_nxt;
+ tcptw->tw_snd_nxt = tp->snd_nxt;
+ tcptw->tw_rcv_wnd = tcp_receive_window(tp);
+ tcptw->tw_ts_recent = tp->rx_opt.ts_recent;
+ tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (tw->tw_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
+ struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
- ipv6_addr_copy(&tw->tw_v6_daddr, &np->daddr);
- ipv6_addr_copy(&tw->tw_v6_rcv_saddr, &np->rcv_saddr);
- tw->tw_v6_ipv6only = np->ipv6only;
- } else {
- memset(&tw->tw_v6_daddr, 0, sizeof(tw->tw_v6_daddr));
- memset(&tw->tw_v6_rcv_saddr, 0, sizeof(tw->tw_v6_rcv_saddr));
- tw->tw_v6_ipv6only = 0;
+ ipv6_addr_copy(&tcp6tw->tw_v6_daddr, &np->daddr);
+ ipv6_addr_copy(&tcp6tw->tw_v6_rcv_saddr, &np->rcv_saddr);
+ tw->tw_ipv6only = np->ipv6only;
}
#endif
/* Linkage updates. */
- __tcp_tw_hashdance(sk, tw);
+ __inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
/* Get the TIME_WAIT timeout firing. */
if (timeo < rto)
@@ -392,8 +320,9 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
timeo = TCP_TIMEWAIT_LEN;
}
- tcp_tw_schedule(tw, timeo);
- tcp_tw_put(tw);
+ inet_twsk_schedule(tw, &tcp_death_row, timeo,
+ TCP_TIMEWAIT_LEN);
+ inet_twsk_put(tw);
} else {
/* Sorry, if we're out of memory, just CLOSE this
* socket up. We've got bigger problems than
@@ -407,277 +336,6 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tcp_done(sk);
}
-/* Kill off TIME_WAIT sockets once their lifetime has expired. */
-static int tcp_tw_death_row_slot;
-
-static void tcp_twkill(unsigned long);
-
-/* TIME_WAIT reaping mechanism. */
-#define TCP_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
-#define TCP_TWKILL_PERIOD (TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
-
-#define TCP_TWKILL_QUOTA 100
-
-static struct hlist_head tcp_tw_death_row[TCP_TWKILL_SLOTS];
-static DEFINE_SPINLOCK(tw_death_lock);
-static struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0);
-static void twkill_work(void *);
-static DECLARE_WORK(tcp_twkill_work, twkill_work, NULL);
-static u32 twkill_thread_slots;
-
-/* Returns non-zero if quota exceeded. */
-static int tcp_do_twkill_work(int slot, unsigned int quota)
-{
- struct tcp_tw_bucket *tw;
- struct hlist_node *node;
- unsigned int killed;
- int ret;
-
- /* NOTE: compare this to previous version where lock
- * was released after detaching chain. It was racy,
- * because tw buckets are scheduled in not serialized context
- * in 2.3 (with netfilter), and with softnet it is common, because
- * soft irqs are not sequenced.
- */
- killed = 0;
- ret = 0;
-rescan:
- tw_for_each_inmate(tw, node, &tcp_tw_death_row[slot]) {
- __tw_del_dead_node(tw);
- spin_unlock(&tw_death_lock);
- tcp_timewait_kill(tw);
- tcp_tw_put(tw);
- killed++;
- spin_lock(&tw_death_lock);
- if (killed > quota) {
- ret = 1;
- break;
- }
-
- /* While we dropped tw_death_lock, another cpu may have
- * killed off the next TW bucket in the list, therefore
- * do a fresh re-read of the hlist head node with the
- * lock reacquired. We still use the hlist traversal
- * macro in order to get the prefetches.
- */
- goto rescan;
- }
-
- tcp_tw_count -= killed;
- NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITED, killed);
-
- return ret;
-}
-
-static void tcp_twkill(unsigned long dummy)
-{
- int need_timer, ret;
-
- spin_lock(&tw_death_lock);
-
- if (tcp_tw_count == 0)
- goto out;
-
- need_timer = 0;
- ret = tcp_do_twkill_work(tcp_tw_death_row_slot, TCP_TWKILL_QUOTA);
- if (ret) {
- twkill_thread_slots |= (1 << tcp_tw_death_row_slot);
- mb();
- schedule_work(&tcp_twkill_work);
- need_timer = 1;
- } else {
- /* We purged the entire slot, anything left? */
- if (tcp_tw_count)
- need_timer = 1;
- }
- tcp_tw_death_row_slot =
- ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1));
- if (need_timer)
- mod_timer(&tcp_tw_timer, jiffies + TCP_TWKILL_PERIOD);
-out:
- spin_unlock(&tw_death_lock);
-}
-
-extern void twkill_slots_invalid(void);
-
-static void twkill_work(void *dummy)
-{
- int i;
-
- if ((TCP_TWKILL_SLOTS - 1) > (sizeof(twkill_thread_slots) * 8))
- twkill_slots_invalid();
-
- while (twkill_thread_slots) {
- spin_lock_bh(&tw_death_lock);
- for (i = 0; i < TCP_TWKILL_SLOTS; i++) {
- if (!(twkill_thread_slots & (1 << i)))
- continue;
-
- while (tcp_do_twkill_work(i, TCP_TWKILL_QUOTA) != 0) {
- if (need_resched()) {
- spin_unlock_bh(&tw_death_lock);
- schedule();
- spin_lock_bh(&tw_death_lock);
- }
- }
-
- twkill_thread_slots &= ~(1 << i);
- }
- spin_unlock_bh(&tw_death_lock);
- }
-}
-
-/* These are always called from BH context. See callers in
- * tcp_input.c to verify this.
- */
-
-/* This is for handling early-kills of TIME_WAIT sockets. */
-void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
-{
- spin_lock(&tw_death_lock);
- if (tw_del_dead_node(tw)) {
- tcp_tw_put(tw);
- if (--tcp_tw_count == 0)
- del_timer(&tcp_tw_timer);
- }
- spin_unlock(&tw_death_lock);
- tcp_timewait_kill(tw);
-}
-
-/* Short-time timewait calendar */
-
-static int tcp_twcal_hand = -1;
-static int tcp_twcal_jiffie;
-static void tcp_twcal_tick(unsigned long);
-static struct timer_list tcp_twcal_timer =
- TIMER_INITIALIZER(tcp_twcal_tick, 0, 0);
-static struct hlist_head tcp_twcal_row[TCP_TW_RECYCLE_SLOTS];
-
-static void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
-{
- struct hlist_head *list;
- int slot;
-
- /* timeout := RTO * 3.5
- *
- * 3.5 = 1+2+0.5 to wait for two retransmits.
- *
- * RATIONALE: if FIN arrived and we entered TIME-WAIT state,
- * our ACK acking that FIN can be lost. If N subsequent retransmitted
- * FINs (or previous seqments) are lost (probability of such event
- * is p^(N+1), where p is probability to lose single packet and
- * time to detect the loss is about RTO*(2^N - 1) with exponential
- * backoff). Normal timewait length is calculated so, that we
- * waited at least for one retransmitted FIN (maximal RTO is 120sec).
- * [ BTW Linux. following BSD, violates this requirement waiting
- * only for 60sec, we should wait at least for 240 secs.
- * Well, 240 consumes too much of resources 8)
- * ]
- * This interval is not reduced to catch old duplicate and
- * responces to our wandering segments living for two MSLs.
- * However, if we use PAWS to detect
- * old duplicates, we can reduce the interval to bounds required
- * by RTO, rather than MSL. So, if peer understands PAWS, we
- * kill tw bucket after 3.5*RTO (it is important that this number
- * is greater than TS tick!) and detect old duplicates with help
- * of PAWS.
- */
- slot = (timeo + (1<<TCP_TW_RECYCLE_TICK) - 1) >> TCP_TW_RECYCLE_TICK;
-
- spin_lock(&tw_death_lock);
-
- /* Unlink it, if it was scheduled */
- if (tw_del_dead_node(tw))
- tcp_tw_count--;
- else
- atomic_inc(&tw->tw_refcnt);
-
- if (slot >= TCP_TW_RECYCLE_SLOTS) {
- /* Schedule to slow timer */
- if (timeo >= TCP_TIMEWAIT_LEN) {
- slot = TCP_TWKILL_SLOTS-1;
- } else {
- slot = (timeo + TCP_TWKILL_PERIOD-1) / TCP_TWKILL_PERIOD;
- if (slot >= TCP_TWKILL_SLOTS)
- slot = TCP_TWKILL_SLOTS-1;
- }
- tw->tw_ttd = jiffies + timeo;
- slot = (tcp_tw_death_row_slot + slot) & (TCP_TWKILL_SLOTS - 1);
- list = &tcp_tw_death_row[slot];
- } else {
- tw->tw_ttd = jiffies + (slot << TCP_TW_RECYCLE_TICK);
-
- if (tcp_twcal_hand < 0) {
- tcp_twcal_hand = 0;
- tcp_twcal_jiffie = jiffies;
- tcp_twcal_timer.expires = tcp_twcal_jiffie + (slot<<TCP_TW_RECYCLE_TICK);
- add_timer(&tcp_twcal_timer);
- } else {
- if (time_after(tcp_twcal_timer.expires, jiffies + (slot<<TCP_TW_RECYCLE_TICK)))
- mod_timer(&tcp_twcal_timer, jiffies + (slot<<TCP_TW_RECYCLE_TICK));
- slot = (tcp_twcal_hand + slot)&(TCP_TW_RECYCLE_SLOTS-1);
- }
- list = &tcp_twcal_row[slot];
- }
-
- hlist_add_head(&tw->tw_death_node, list);
-
- if (tcp_tw_count++ == 0)
- mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD);
- spin_unlock(&tw_death_lock);
-}
-
-void tcp_twcal_tick(unsigned long dummy)
-{
- int n, slot;
- unsigned long j;
- unsigned long now = jiffies;
- int killed = 0;
- int adv = 0;
-
- spin_lock(&tw_death_lock);
- if (tcp_twcal_hand < 0)
- goto out;
-
- slot = tcp_twcal_hand;
- j = tcp_twcal_jiffie;
-
- for (n=0; n<TCP_TW_RECYCLE_SLOTS; n++) {
- if (time_before_eq(j, now)) {
- struct hlist_node *node, *safe;
- struct tcp_tw_bucket *tw;
-
- tw_for_each_inmate_safe(tw, node, safe,
- &tcp_twcal_row[slot]) {
- __tw_del_dead_node(tw);
- tcp_timewait_kill(tw);
- tcp_tw_put(tw);
- killed++;
- }
- } else {
- if (!adv) {
- adv = 1;
- tcp_twcal_jiffie = j;
- tcp_twcal_hand = slot;
- }
-
- if (!hlist_empty(&tcp_twcal_row[slot])) {
- mod_timer(&tcp_twcal_timer, j);
- goto out;
- }
- }
- j += (1<<TCP_TW_RECYCLE_TICK);
- slot = (slot+1)&(TCP_TW_RECYCLE_SLOTS-1);
- }
- tcp_twcal_hand = -1;
-
-out:
- if ((tcp_tw_count -= killed) == 0)
- del_timer(&tcp_tw_timer);
- NET_ADD_STATS_BH(LINUX_MIB_TIMEWAITKILLED, killed);
- spin_unlock(&tw_death_lock);
-}
-
/* This is not only more efficient than what we used to do, it eliminates
* a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
*
@@ -686,75 +344,27 @@ out:
*/
struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb)
{
- /* allocate the newsk from the same slab of the master sock,
- * if not, at sk_free time we'll try to free it from the wrong
- * slabcache (i.e. is it TCPv4 or v6?), this is handled thru sk->sk_prot -acme */
- struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, sk->sk_prot, 0);
+ struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);
- if(newsk != NULL) {
- struct inet_request_sock *ireq = inet_rsk(req);
+ if (newsk != NULL) {
+ const struct inet_request_sock *ireq = inet_rsk(req);
struct tcp_request_sock *treq = tcp_rsk(req);
+ struct inet_connection_sock *newicsk = inet_csk(sk);
struct tcp_sock *newtp;
- struct sk_filter *filter;
-
- memcpy(newsk, sk, sizeof(struct tcp_sock));
- newsk->sk_state = TCP_SYN_RECV;
-
- /* SANITY */
- sk_node_init(&newsk->sk_node);
- tcp_sk(newsk)->bind_hash = NULL;
-
- /* Clone the TCP header template */
- inet_sk(newsk)->dport = ireq->rmt_port;
-
- sock_lock_init(newsk);
- bh_lock_sock(newsk);
-
- rwlock_init(&newsk->sk_dst_lock);
- atomic_set(&newsk->sk_rmem_alloc, 0);
- skb_queue_head_init(&newsk->sk_receive_queue);
- atomic_set(&newsk->sk_wmem_alloc, 0);
- skb_queue_head_init(&newsk->sk_write_queue);
- atomic_set(&newsk->sk_omem_alloc, 0);
- newsk->sk_wmem_queued = 0;
- newsk->sk_forward_alloc = 0;
-
- sock_reset_flag(newsk, SOCK_DONE);
- newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
- newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
- newsk->sk_send_head = NULL;
- rwlock_init(&newsk->sk_callback_lock);
- skb_queue_head_init(&newsk->sk_error_queue);
- newsk->sk_write_space = sk_stream_write_space;
-
- if ((filter = newsk->sk_filter) != NULL)
- sk_filter_charge(newsk, filter);
-
- if (unlikely(xfrm_sk_clone_policy(newsk))) {
- /* It is still raw copy of parent, so invalidate
- * destructor and make plain sk_free() */
- newsk->sk_destruct = NULL;
- sk_free(newsk);
- return NULL;
- }
/* Now setup tcp_sock */
newtp = tcp_sk(newsk);
newtp->pred_flags = 0;
newtp->rcv_nxt = treq->rcv_isn + 1;
- newtp->snd_nxt = treq->snt_isn + 1;
- newtp->snd_una = treq->snt_isn + 1;
- newtp->snd_sml = treq->snt_isn + 1;
+ newtp->snd_nxt = newtp->snd_una = newtp->snd_sml = treq->snt_isn + 1;
tcp_prequeue_init(newtp);
tcp_init_wl(newtp, treq->snt_isn, treq->rcv_isn);
- newtp->retransmits = 0;
- newtp->backoff = 0;
newtp->srtt = 0;
newtp->mdev = TCP_TIMEOUT_INIT;
- newtp->rto = TCP_TIMEOUT_INIT;
+ newicsk->icsk_rto = TCP_TIMEOUT_INIT;
newtp->packets_out = 0;
newtp->left_out = 0;
@@ -774,9 +384,9 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
newtp->frto_counter = 0;
newtp->frto_highmark = 0;
- newtp->ca_ops = &tcp_reno;
+ newicsk->icsk_ca_ops = &tcp_reno;
- tcp_set_ca_state(newtp, TCP_CA_Open);
+ tcp_set_ca_state(newsk, TCP_CA_Open);
tcp_init_xmit_timers(newsk);
skb_queue_head_init(&newtp->out_of_order_queue);
newtp->rcv_wup = treq->rcv_isn + 1;
@@ -789,26 +399,12 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
newtp->rx_opt.dsack = 0;
newtp->rx_opt.eff_sacks = 0;
- newtp->probes_out = 0;
newtp->rx_opt.num_sacks = 0;
newtp->urg_data = 0;
- /* Deinitialize accept_queue to trap illegal accesses. */
- memset(&newtp->accept_queue, 0, sizeof(newtp->accept_queue));
-
- /* Back to base struct sock members. */
- newsk->sk_err = 0;
- newsk->sk_priority = 0;
- atomic_set(&newsk->sk_refcnt, 2);
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet_sock_nr);
-#endif
- atomic_inc(&tcp_sockets_allocated);
if (sock_flag(newsk, SOCK_KEEPOPEN))
- tcp_reset_keepalive_timer(newsk,
- keepalive_time_when(newtp));
- newsk->sk_socket = NULL;
- newsk->sk_sleep = NULL;
+ inet_csk_reset_keepalive_timer(newsk,
+ keepalive_time_when(newtp));
newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
if((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {
@@ -838,7 +434,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
newtp->tcp_header_len = sizeof(struct tcphdr);
}
if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len)
- newtp->ack.last_seg_size = skb->len-newtp->tcp_header_len;
+ newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
newtp->rx_opt.mss_clamp = req->mss;
TCP_ECN_openreq_child(newtp, req);
if (newtp->ecn_flags&TCP_ECN_OK)
@@ -934,9 +530,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
does sequence test, SYN is truncated, and thus we consider
it a bare ACK.
- If tp->defer_accept, we silently drop this bare ACK. Otherwise,
- we create an established connection. Both ends (listening sockets)
- accept the new incoming connection and try to talk to each other. 8-)
+ If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
+ bare ACK. Otherwise, we create an established connection. Both
+ ends (listening sockets) accept the new incoming connection and try
+ to talk to each other. 8-)
Note: This case is both harmless, and rare. Possibility is about the
same as us discovering intelligent life on another plant tomorrow.
@@ -1003,7 +600,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
return NULL;
/* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
- if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+ if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+ TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
inet_rsk(req)->acked = 1;
return NULL;
}
@@ -1018,10 +616,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
if (child == NULL)
goto listen_overflow;
- tcp_synq_unlink(tp, req, prev);
- tcp_synq_removed(sk, req);
+ inet_csk_reqsk_queue_unlink(sk, req, prev);
+ inet_csk_reqsk_queue_removed(sk, req);
- tcp_acceptq_queue(sk, req, child);
+ inet_csk_reqsk_queue_add(sk, req, child);
return child;
listen_overflow:
@@ -1035,7 +633,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
if (!(flg & TCP_FLAG_RST))
req->rsk_ops->send_reset(skb);
- tcp_synq_drop(sk, req, prev);
+ inet_csk_reqsk_queue_drop(sk, req, prev);
return NULL;
}
@@ -1074,4 +672,3 @@ EXPORT_SYMBOL(tcp_check_req);
EXPORT_SYMBOL(tcp_child_process);
EXPORT_SYMBOL(tcp_create_openreq_child);
EXPORT_SYMBOL(tcp_timewait_state_process);
-EXPORT_SYMBOL(tcp_tw_deschedule);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index dd30dd137b74..c10e4435e3b1 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -105,18 +105,19 @@ static __u16 tcp_advertise_mss(struct sock *sk)
/* RFC2861. Reset CWND after idle period longer RTO to "restart window".
* This is the first part of cwnd validation mechanism. */
-static void tcp_cwnd_restart(struct tcp_sock *tp, struct dst_entry *dst)
+static void tcp_cwnd_restart(struct sock *sk, struct dst_entry *dst)
{
+ struct tcp_sock *tp = tcp_sk(sk);
s32 delta = tcp_time_stamp - tp->lsndtime;
u32 restart_cwnd = tcp_init_cwnd(tp, dst);
u32 cwnd = tp->snd_cwnd;
- tcp_ca_event(tp, CA_EVENT_CWND_RESTART);
+ tcp_ca_event(sk, CA_EVENT_CWND_RESTART);
- tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_ssthresh = tcp_current_ssthresh(sk);
restart_cwnd = min(restart_cwnd, cwnd);
- while ((delta -= tp->rto) > 0 && cwnd > restart_cwnd)
+ while ((delta -= inet_csk(sk)->icsk_rto) > 0 && cwnd > restart_cwnd)
cwnd >>= 1;
tp->snd_cwnd = max(cwnd, restart_cwnd);
tp->snd_cwnd_stamp = tcp_time_stamp;
@@ -126,26 +127,25 @@ static void tcp_cwnd_restart(struct tcp_sock *tp, struct dst_entry *dst)
static inline void tcp_event_data_sent(struct tcp_sock *tp,
struct sk_buff *skb, struct sock *sk)
{
- u32 now = tcp_time_stamp;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ const u32 now = tcp_time_stamp;
- if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
- tcp_cwnd_restart(tp, __sk_dst_get(sk));
+ if (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)
+ tcp_cwnd_restart(sk, __sk_dst_get(sk));
tp->lsndtime = now;
/* If it is a reply for ato after last received
* packet, enter pingpong mode.
*/
- if ((u32)(now - tp->ack.lrcvtime) < tp->ack.ato)
- tp->ack.pingpong = 1;
+ if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
+ icsk->icsk_ack.pingpong = 1;
}
static __inline__ void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tcp_dec_quickack_mode(tp, pkts);
- tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
+ tcp_dec_quickack_mode(sk, pkts);
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
}
/* Determine a window scaling and initial window to offer.
@@ -265,6 +265,7 @@ static __inline__ u16 tcp_select_window(struct sock *sk)
static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
{
if (skb != NULL) {
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_sock *inet = inet_sk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
@@ -280,8 +281,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
#define SYSCTL_FLAG_SACK 0x4
/* If congestion control is doing timestamping */
- if (tp->ca_ops->rtt_sample)
- do_gettimeofday(&skb->stamp);
+ if (icsk->icsk_ca_ops->rtt_sample)
+ __net_timestamp(skb);
sysctl_flags = 0;
if (tcb->flags & TCPCB_FLAG_SYN) {
@@ -308,7 +309,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
}
if (tcp_packets_in_flight(tp) == 0)
- tcp_ca_event(tp, CA_EVENT_TX_START);
+ tcp_ca_event(sk, CA_EVENT_TX_START);
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
@@ -366,7 +367,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
if (err <= 0)
return err;
- tcp_enter_cwr(tp);
+ tcp_enter_cwr(sk);
/* NET_XMIT_CN is special. It does not guarantee,
* that this packet is lost. It tells that device
@@ -427,11 +428,11 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned
* packet to the list. This won't be called frequently, I hope.
* Remember, these are still headerless SKBs at this point.
*/
-static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now)
+int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *buff;
- int nsize;
+ int nsize, old_factor;
u16 flags;
nsize = skb_headlen(skb) - len;
@@ -482,30 +483,36 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned
* skbs, which it never sent before. --ANK
*/
TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
- buff->stamp = skb->stamp;
+ buff->tstamp = skb->tstamp;
- if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
- tp->lost_out -= tcp_skb_pcount(skb);
- tp->left_out -= tcp_skb_pcount(skb);
- }
+ old_factor = tcp_skb_pcount(skb);
/* Fix up tso_factor for both original and new SKB. */
tcp_set_skb_tso_segs(sk, skb, mss_now);
tcp_set_skb_tso_segs(sk, buff, mss_now);
- if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
- tp->lost_out += tcp_skb_pcount(skb);
- tp->left_out += tcp_skb_pcount(skb);
- }
+ /* If this packet has been sent out already, we must
+ * adjust the various packet counters.
+ */
+ if (!before(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq)) {
+ int diff = old_factor - tcp_skb_pcount(skb) -
+ tcp_skb_pcount(buff);
- if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
- tp->lost_out += tcp_skb_pcount(buff);
- tp->left_out += tcp_skb_pcount(buff);
+ tp->packets_out -= diff;
+ if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+ tp->lost_out -= diff;
+ tp->left_out -= diff;
+ }
+ if (diff > 0) {
+ tp->fackets_out -= diff;
+ if ((int)tp->fackets_out < 0)
+ tp->fackets_out = 0;
+ }
}
/* Link BUFF into the send queue. */
skb_header_release(buff);
- __skb_append(skb, buff);
+ __skb_append(skb, buff, &sk->sk_write_queue);
return 0;
}
@@ -696,7 +703,7 @@ static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp)
if (tp->packets_out > tp->snd_cwnd_used)
tp->snd_cwnd_used = tp->packets_out;
- if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= tp->rto)
+ if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto)
tcp_cwnd_application_limited(sk);
}
}
@@ -893,7 +900,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
/* Link BUFF into the send queue. */
skb_header_release(buff);
- __skb_append(skb, buff);
+ __skb_append(skb, buff, &sk->sk_write_queue);
return 0;
}
@@ -905,12 +912,13 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
*/
static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
u32 send_win, cong_win, limit, in_flight;
if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
return 0;
- if (tp->ca_state != TCP_CA_Open)
+ if (icsk->icsk_ca_state != TCP_CA_Open)
return 0;
in_flight = tcp_packets_in_flight(tp);
@@ -1147,6 +1155,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
*/
u32 __tcp_select_window(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
/* MSS for the peer's data. Previous verions used mss_clamp
* here. I don't know if the value based on our guesses
@@ -1154,7 +1163,7 @@ u32 __tcp_select_window(struct sock *sk)
* but may be worse for the performance because of rcv_mss
* fluctuations. --SAW 1998/11/1
*/
- int mss = tp->ack.rcv_mss;
+ int mss = icsk->icsk_ack.rcv_mss;
int free_space = tcp_space(sk);
int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
int window;
@@ -1163,7 +1172,7 @@ u32 __tcp_select_window(struct sock *sk)
mss = full_space;
if (free_space < full_space/2) {
- tp->ack.quick = 0;
+ icsk->icsk_ack.quick = 0;
if (tcp_memory_pressure)
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
@@ -1238,7 +1247,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
tcp_skb_pcount(next_skb) != 1);
/* Ok. We will be able to collapse the packet. */
- __skb_unlink(next_skb, next_skb->list);
+ __skb_unlink(next_skb, &sk->sk_write_queue);
memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
@@ -1286,6 +1295,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
*/
void tcp_simple_retransmit(struct sock *sk)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
unsigned int mss = tcp_current_mss(sk, 0);
@@ -1316,12 +1326,12 @@ void tcp_simple_retransmit(struct sock *sk)
* in network, but units changed and effective
* cwnd/ssthresh really reduced now.
*/
- if (tp->ca_state != TCP_CA_Loss) {
+ if (icsk->icsk_ca_state != TCP_CA_Loss) {
tp->high_seq = tp->snd_nxt;
- tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_ssthresh = tcp_current_ssthresh(sk);
tp->prior_ssthresh = 0;
tp->undo_marker = 0;
- tcp_set_ca_state(tp, TCP_CA_Loss);
+ tcp_set_ca_state(sk, TCP_CA_Loss);
}
tcp_xmit_retransmit_queue(sk);
}
@@ -1346,12 +1356,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
BUG();
-
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sk->sk_route_caps &= ~NETIF_F_TSO;
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- }
-
if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
return -ENOMEM;
}
@@ -1366,22 +1370,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
return -EAGAIN;
if (skb->len > cur_mss) {
- int old_factor = tcp_skb_pcount(skb);
- int diff;
-
if (tcp_fragment(sk, skb, cur_mss, cur_mss))
return -ENOMEM; /* We'll try again later. */
-
- /* New SKB created, account for it. */
- diff = old_factor - tcp_skb_pcount(skb) -
- tcp_skb_pcount(skb->next);
- tp->packets_out -= diff;
-
- if (diff > 0) {
- tp->fackets_out -= diff;
- if ((int)tp->fackets_out < 0)
- tp->fackets_out = 0;
- }
}
/* Collapse two adjacent packets if worthwhile and we can. */
@@ -1461,6 +1451,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
*/
void tcp_xmit_retransmit_queue(struct sock *sk)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int packet_cnt = tp->lost_out;
@@ -1484,14 +1475,16 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
if (!(sacked&(TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) {
if (tcp_retransmit_skb(sk, skb))
return;
- if (tp->ca_state != TCP_CA_Loss)
+ if (icsk->icsk_ca_state != TCP_CA_Loss)
NET_INC_STATS_BH(LINUX_MIB_TCPFASTRETRANS);
else
NET_INC_STATS_BH(LINUX_MIB_TCPSLOWSTARTRETRANS);
if (skb ==
skb_peek(&sk->sk_write_queue))
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ inet_csk(sk)->icsk_rto,
+ TCP_RTO_MAX);
}
packet_cnt -= tcp_skb_pcount(skb);
@@ -1504,7 +1497,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
/* OK, demanded retransmission is finished. */
/* Forward retransmissions are possible only during Recovery. */
- if (tp->ca_state != TCP_CA_Recovery)
+ if (icsk->icsk_ca_state != TCP_CA_Recovery)
return;
/* No forward retransmissions in Reno are possible. */
@@ -1544,7 +1537,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
break;
if (skb == skb_peek(&sk->sk_write_queue))
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ inet_csk(sk)->icsk_rto,
+ TCP_RTO_MAX);
NET_INC_STATS_BH(LINUX_MIB_TCPFORWARDRETRANS);
}
@@ -1573,7 +1568,7 @@ void tcp_send_fin(struct sock *sk)
} else {
/* Socket is locked, keep trying until memory is available. */
for (;;) {
- skb = alloc_skb(MAX_TCP_HEADER, GFP_KERNEL);
+ skb = alloc_skb_fclone(MAX_TCP_HEADER, GFP_KERNEL);
if (skb)
break;
yield();
@@ -1780,8 +1775,8 @@ static inline void tcp_connect_init(struct sock *sk)
tp->rcv_wup = 0;
tp->copied_seq = 0;
- tp->rto = TCP_TIMEOUT_INIT;
- tp->retransmits = 0;
+ inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
+ inet_csk(sk)->icsk_retransmits = 0;
tcp_clear_retrans(tp);
}
@@ -1795,7 +1790,7 @@ int tcp_connect(struct sock *sk)
tcp_connect_init(sk);
- buff = alloc_skb(MAX_TCP_HEADER + 15, sk->sk_allocation);
+ buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
if (unlikely(buff == NULL))
return -ENOBUFS;
@@ -1824,7 +1819,8 @@ int tcp_connect(struct sock *sk)
TCP_INC_STATS(TCP_MIB_ACTIVEOPENS);
/* Timer for repeating the SYN until an answer. */
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
return 0;
}
@@ -1834,20 +1830,21 @@ int tcp_connect(struct sock *sk)
*/
void tcp_send_delayed_ack(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
- int ato = tp->ack.ato;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ int ato = icsk->icsk_ack.ato;
unsigned long timeout;
if (ato > TCP_DELACK_MIN) {
+ const struct tcp_sock *tp = tcp_sk(sk);
int max_ato = HZ/2;
- if (tp->ack.pingpong || (tp->ack.pending&TCP_ACK_PUSHED))
+ if (icsk->icsk_ack.pingpong || (icsk->icsk_ack.pending & ICSK_ACK_PUSHED))
max_ato = TCP_DELACK_MAX;
/* Slow path, intersegment interval is "high". */
/* If some rtt estimate is known, use it to bound delayed ack.
- * Do not use tp->rto here, use results of rtt measurements
+ * Do not use inet_csk(sk)->icsk_rto here, use results of rtt measurements
* directly.
*/
if (tp->srtt) {
@@ -1864,21 +1861,22 @@ void tcp_send_delayed_ack(struct sock *sk)
timeout = jiffies + ato;
/* Use new timeout only if there wasn't a older one earlier. */
- if (tp->ack.pending&TCP_ACK_TIMER) {
+ if (icsk->icsk_ack.pending & ICSK_ACK_TIMER) {
/* If delack timer was blocked or is about to expire,
* send ACK now.
*/
- if (tp->ack.blocked || time_before_eq(tp->ack.timeout, jiffies+(ato>>2))) {
+ if (icsk->icsk_ack.blocked ||
+ time_before_eq(icsk->icsk_ack.timeout, jiffies + (ato >> 2))) {
tcp_send_ack(sk);
return;
}
- if (!time_before(timeout, tp->ack.timeout))
- timeout = tp->ack.timeout;
+ if (!time_before(timeout, icsk->icsk_ack.timeout))
+ timeout = icsk->icsk_ack.timeout;
}
- tp->ack.pending |= TCP_ACK_SCHED|TCP_ACK_TIMER;
- tp->ack.timeout = timeout;
- sk_reset_timer(sk, &tp->delack_timer, timeout);
+ icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
+ icsk->icsk_ack.timeout = timeout;
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
}
/* This routine sends an ack and also updates the window. */
@@ -1895,9 +1893,10 @@ void tcp_send_ack(struct sock *sk)
*/
buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
if (buff == NULL) {
- tcp_schedule_ack(tp);
- tp->ack.ato = TCP_ATO_MIN;
- tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+ inet_csk_schedule_ack(sk);
+ inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+ TCP_DELACK_MAX, TCP_RTO_MAX);
return;
}
@@ -1980,12 +1979,6 @@ int tcp_write_wakeup(struct sock *sk)
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
if (tcp_fragment(sk, skb, seg_size, mss))
return -1;
- /* SWS override triggered forced fragmentation.
- * Disable TSO, the connection is too sick. */
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- sk->sk_route_caps &= ~NETIF_F_TSO;
- }
} else if (!tcp_skb_pcount(skb))
tcp_set_skb_tso_segs(sk, skb, mss);
@@ -2011,6 +2004,7 @@ int tcp_write_wakeup(struct sock *sk)
*/
void tcp_send_probe0(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int err;
@@ -2018,28 +2012,31 @@ void tcp_send_probe0(struct sock *sk)
if (tp->packets_out || !sk->sk_send_head) {
/* Cancel probe timer, if it is not required. */
- tp->probes_out = 0;
- tp->backoff = 0;
+ icsk->icsk_probes_out = 0;
+ icsk->icsk_backoff = 0;
return;
}
if (err <= 0) {
- if (tp->backoff < sysctl_tcp_retries2)
- tp->backoff++;
- tp->probes_out++;
- tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0,
- min(tp->rto << tp->backoff, TCP_RTO_MAX));
+ if (icsk->icsk_backoff < sysctl_tcp_retries2)
+ icsk->icsk_backoff++;
+ icsk->icsk_probes_out++;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+ min(icsk->icsk_rto << icsk->icsk_backoff, TCP_RTO_MAX),
+ TCP_RTO_MAX);
} else {
/* If packet was not sent due to local congestion,
- * do not backoff and do not remember probes_out.
+ * do not backoff and do not remember icsk_probes_out.
* Let local senders to fight for local resources.
*
* Use accumulated backoff yet.
*/
- if (!tp->probes_out)
- tp->probes_out=1;
- tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0,
- min(tp->rto << tp->backoff, TCP_RESOURCE_PROBE_INTERVAL));
+ if (!icsk->icsk_probes_out)
+ icsk->icsk_probes_out = 1;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+ min(icsk->icsk_rto << icsk->icsk_backoff,
+ TCP_RESOURCE_PROBE_INTERVAL),
+ TCP_RTO_MAX);
}
}
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
index 70e108e15c71..327770bf5522 100644
--- a/net/ipv4/tcp_scalable.c
+++ b/net/ipv4/tcp_scalable.c
@@ -16,9 +16,10 @@
#define TCP_SCALABLE_AI_CNT 50U
#define TCP_SCALABLE_MD_SCALE 3
-static void tcp_scalable_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
u32 in_flight, int flag)
{
+ struct tcp_sock *tp = tcp_sk(sk);
if (in_flight < tp->snd_cwnd)
return;
@@ -35,8 +36,9 @@ static void tcp_scalable_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
tp->snd_cwnd_stamp = tcp_time_stamp;
}
-static u32 tcp_scalable_ssthresh(struct tcp_sock *tp)
+static u32 tcp_scalable_ssthresh(struct sock *sk)
{
+ const struct tcp_sock *tp = tcp_sk(sk);
return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
}
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 0084227438c2..415ee47ac1c5 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -36,49 +36,13 @@ static void tcp_write_timer(unsigned long);
static void tcp_delack_timer(unsigned long);
static void tcp_keepalive_timer (unsigned long data);
-#ifdef TCP_DEBUG
-const char tcp_timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
-EXPORT_SYMBOL(tcp_timer_bug_msg);
-#endif
-
-/*
- * Using different timers for retransmit, delayed acks and probes
- * We may wish use just one timer maintaining a list of expire jiffies
- * to optimize.
- */
-
void tcp_init_xmit_timers(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
-
- init_timer(&tp->retransmit_timer);
- tp->retransmit_timer.function=&tcp_write_timer;
- tp->retransmit_timer.data = (unsigned long) sk;
- tp->pending = 0;
-
- init_timer(&tp->delack_timer);
- tp->delack_timer.function=&tcp_delack_timer;
- tp->delack_timer.data = (unsigned long) sk;
- tp->ack.pending = 0;
-
- init_timer(&sk->sk_timer);
- sk->sk_timer.function = &tcp_keepalive_timer;
- sk->sk_timer.data = (unsigned long)sk;
+ inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
+ &tcp_keepalive_timer);
}
-void tcp_clear_xmit_timers(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->pending = 0;
- sk_stop_timer(sk, &tp->retransmit_timer);
-
- tp->ack.pending = 0;
- tp->ack.blocked = 0;
- sk_stop_timer(sk, &tp->delack_timer);
-
- sk_stop_timer(sk, &sk->sk_timer);
-}
+EXPORT_SYMBOL(tcp_init_xmit_timers);
static void tcp_write_err(struct sock *sk)
{
@@ -155,15 +119,15 @@ static int tcp_orphan_retries(struct sock *sk, int alive)
/* A write timeout has occurred. Process the after effects. */
static int tcp_write_timeout(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
int retry_until;
if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
- if (tp->retransmits)
+ if (icsk->icsk_retransmits)
dst_negative_advice(&sk->sk_dst_cache);
- retry_until = tp->syn_retries ? : sysctl_tcp_syn_retries;
+ retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
} else {
- if (tp->retransmits >= sysctl_tcp_retries1) {
+ if (icsk->icsk_retransmits >= sysctl_tcp_retries1) {
/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
hole detection. :-(
@@ -189,16 +153,16 @@ static int tcp_write_timeout(struct sock *sk)
retry_until = sysctl_tcp_retries2;
if (sock_flag(sk, SOCK_DEAD)) {
- int alive = (tp->rto < TCP_RTO_MAX);
+ const int alive = (icsk->icsk_rto < TCP_RTO_MAX);
retry_until = tcp_orphan_retries(sk, alive);
- if (tcp_out_of_resources(sk, alive || tp->retransmits < retry_until))
+ if (tcp_out_of_resources(sk, alive || icsk->icsk_retransmits < retry_until))
return 1;
}
}
- if (tp->retransmits >= retry_until) {
+ if (icsk->icsk_retransmits >= retry_until) {
/* Has it gone just too far? */
tcp_write_err(sk);
return 1;
@@ -210,26 +174,27 @@ static void tcp_delack_timer(unsigned long data)
{
struct sock *sk = (struct sock*)data;
struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* Try again later. */
- tp->ack.blocked = 1;
+ icsk->icsk_ack.blocked = 1;
NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED);
- sk_reset_timer(sk, &tp->delack_timer, jiffies + TCP_DELACK_MIN);
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, jiffies + TCP_DELACK_MIN);
goto out_unlock;
}
sk_stream_mem_reclaim(sk);
- if (sk->sk_state == TCP_CLOSE || !(tp->ack.pending & TCP_ACK_TIMER))
+ if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
goto out;
- if (time_after(tp->ack.timeout, jiffies)) {
- sk_reset_timer(sk, &tp->delack_timer, tp->ack.timeout);
+ if (time_after(icsk->icsk_ack.timeout, jiffies)) {
+ sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
goto out;
}
- tp->ack.pending &= ~TCP_ACK_TIMER;
+ icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
if (!skb_queue_empty(&tp->ucopy.prequeue)) {
struct sk_buff *skb;
@@ -242,16 +207,16 @@ static void tcp_delack_timer(unsigned long data)
tp->ucopy.memory = 0;
}
- if (tcp_ack_scheduled(tp)) {
- if (!tp->ack.pingpong) {
+ if (inet_csk_ack_scheduled(sk)) {
+ if (!icsk->icsk_ack.pingpong) {
/* Delayed ACK missed: inflate ATO. */
- tp->ack.ato = min(tp->ack.ato << 1, tp->rto);
+ icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, icsk->icsk_rto);
} else {
/* Delayed ACK missed: leave pingpong mode and
* deflate ATO.
*/
- tp->ack.pingpong = 0;
- tp->ack.ato = TCP_ATO_MIN;
+ icsk->icsk_ack.pingpong = 0;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
}
tcp_send_ack(sk);
NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS);
@@ -268,11 +233,12 @@ out_unlock:
static void tcp_probe_timer(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int max_probes;
if (tp->packets_out || !sk->sk_send_head) {
- tp->probes_out = 0;
+ icsk->icsk_probes_out = 0;
return;
}
@@ -283,7 +249,7 @@ static void tcp_probe_timer(struct sock *sk)
* FIXME: We ought not to do it, Solaris 2.5 actually has fixing
* this behaviour in Solaris down as a bug fix. [AC]
*
- * Let me to explain. probes_out is zeroed by incoming ACKs
+ * Let me to explain. icsk_probes_out is zeroed by incoming ACKs
* even if they advertise zero window. Hence, connection is killed only
* if we received no ACKs for normal connection timeout. It is not killed
* only because window stays zero for some time, window may be zero
@@ -294,15 +260,15 @@ static void tcp_probe_timer(struct sock *sk)
max_probes = sysctl_tcp_retries2;
if (sock_flag(sk, SOCK_DEAD)) {
- int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
+ const int alive = ((icsk->icsk_rto << icsk->icsk_backoff) < TCP_RTO_MAX);
max_probes = tcp_orphan_retries(sk, alive);
- if (tcp_out_of_resources(sk, alive || tp->probes_out <= max_probes))
+ if (tcp_out_of_resources(sk, alive || icsk->icsk_probes_out <= max_probes))
return;
}
- if (tp->probes_out > max_probes) {
+ if (icsk->icsk_probes_out > max_probes) {
tcp_write_err(sk);
} else {
/* Only send another probe if we didn't close things up. */
@@ -317,6 +283,7 @@ static void tcp_probe_timer(struct sock *sk)
static void tcp_retransmit_timer(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
if (!tp->packets_out)
goto out;
@@ -351,20 +318,21 @@ static void tcp_retransmit_timer(struct sock *sk)
if (tcp_write_timeout(sk))
goto out;
- if (tp->retransmits == 0) {
- if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
+ if (icsk->icsk_retransmits == 0) {
+ if (icsk->icsk_ca_state == TCP_CA_Disorder ||
+ icsk->icsk_ca_state == TCP_CA_Recovery) {
if (tp->rx_opt.sack_ok) {
- if (tp->ca_state == TCP_CA_Recovery)
+ if (icsk->icsk_ca_state == TCP_CA_Recovery)
NET_INC_STATS_BH(LINUX_MIB_TCPSACKRECOVERYFAIL);
else
NET_INC_STATS_BH(LINUX_MIB_TCPSACKFAILURES);
} else {
- if (tp->ca_state == TCP_CA_Recovery)
+ if (icsk->icsk_ca_state == TCP_CA_Recovery)
NET_INC_STATS_BH(LINUX_MIB_TCPRENORECOVERYFAIL);
else
NET_INC_STATS_BH(LINUX_MIB_TCPRENOFAILURES);
}
- } else if (tp->ca_state == TCP_CA_Loss) {
+ } else if (icsk->icsk_ca_state == TCP_CA_Loss) {
NET_INC_STATS_BH(LINUX_MIB_TCPLOSSFAILURES);
} else {
NET_INC_STATS_BH(LINUX_MIB_TCPTIMEOUTS);
@@ -381,10 +349,11 @@ static void tcp_retransmit_timer(struct sock *sk)
/* Retransmission failed because of local congestion,
* do not backoff.
*/
- if (!tp->retransmits)
- tp->retransmits=1;
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,
- min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));
+ if (!icsk->icsk_retransmits)
+ icsk->icsk_retransmits = 1;
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+ min(icsk->icsk_rto, TCP_RESOURCE_PROBE_INTERVAL),
+ TCP_RTO_MAX);
goto out;
}
@@ -403,13 +372,13 @@ static void tcp_retransmit_timer(struct sock *sk)
* implemented ftp to mars will work nicely. We will have to fix
* the 120 second clamps though!
*/
- tp->backoff++;
- tp->retransmits++;
+ icsk->icsk_backoff++;
+ icsk->icsk_retransmits++;
out_reset_timer:
- tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
- tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
- if (tp->retransmits > sysctl_tcp_retries1)
+ icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX);
+ if (icsk->icsk_retransmits > sysctl_tcp_retries1)
__sk_dst_reset(sk);
out:;
@@ -418,32 +387,32 @@ out:;
static void tcp_write_timer(unsigned long data)
{
struct sock *sk = (struct sock*)data;
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
int event;
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* Try again later */
- sk_reset_timer(sk, &tp->retransmit_timer, jiffies + (HZ / 20));
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + (HZ / 20));
goto out_unlock;
}
- if (sk->sk_state == TCP_CLOSE || !tp->pending)
+ if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending)
goto out;
- if (time_after(tp->timeout, jiffies)) {
- sk_reset_timer(sk, &tp->retransmit_timer, tp->timeout);
+ if (time_after(icsk->icsk_timeout, jiffies)) {
+ sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
goto out;
}
- event = tp->pending;
- tp->pending = 0;
+ event = icsk->icsk_pending;
+ icsk->icsk_pending = 0;
switch (event) {
- case TCP_TIME_RETRANS:
+ case ICSK_TIME_RETRANS:
tcp_retransmit_timer(sk);
break;
- case TCP_TIME_PROBE0:
+ case ICSK_TIME_PROBE0:
tcp_probe_timer(sk);
break;
}
@@ -462,96 +431,8 @@ out_unlock:
static void tcp_synack_timer(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
- struct listen_sock *lopt = tp->accept_queue.listen_opt;
- int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
- int thresh = max_retries;
- unsigned long now = jiffies;
- struct request_sock **reqp, *req;
- int i, budget;
-
- if (lopt == NULL || lopt->qlen == 0)
- return;
-
- /* Normally all the openreqs are young and become mature
- * (i.e. converted to established socket) for first timeout.
- * If synack was not acknowledged for 3 seconds, it means
- * one of the following things: synack was lost, ack was lost,
- * rtt is high or nobody planned to ack (i.e. synflood).
- * When server is a bit loaded, queue is populated with old
- * open requests, reducing effective size of queue.
- * When server is well loaded, queue size reduces to zero
- * after several minutes of work. It is not synflood,
- * it is normal operation. The solution is pruning
- * too old entries overriding normal timeout, when
- * situation becomes dangerous.
- *
- * Essentially, we reserve half of room for young
- * embrions; and abort old ones without pity, if old
- * ones are about to clog our table.
- */
- if (lopt->qlen>>(lopt->max_qlen_log-1)) {
- int young = (lopt->qlen_young<<1);
-
- while (thresh > 2) {
- if (lopt->qlen < young)
- break;
- thresh--;
- young <<= 1;
- }
- }
-
- if (tp->defer_accept)
- max_retries = tp->defer_accept;
-
- budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
- i = lopt->clock_hand;
-
- do {
- reqp=&lopt->syn_table[i];
- while ((req = *reqp) != NULL) {
- if (time_after_eq(now, req->expires)) {
- if ((req->retrans < thresh ||
- (inet_rsk(req)->acked && req->retrans < max_retries))
- && !req->rsk_ops->rtx_syn_ack(sk, req, NULL)) {
- unsigned long timeo;
-
- if (req->retrans++ == 0)
- lopt->qlen_young--;
- timeo = min((TCP_TIMEOUT_INIT << req->retrans),
- TCP_RTO_MAX);
- req->expires = now + timeo;
- reqp = &req->dl_next;
- continue;
- }
-
- /* Drop this request */
- tcp_synq_unlink(tp, req, reqp);
- reqsk_queue_removed(&tp->accept_queue, req);
- reqsk_free(req);
- continue;
- }
- reqp = &req->dl_next;
- }
-
- i = (i+1)&(TCP_SYNQ_HSIZE-1);
-
- } while (--budget > 0);
-
- lopt->clock_hand = i;
-
- if (lopt->qlen)
- tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
-}
-
-void tcp_delete_keepalive_timer (struct sock *sk)
-{
- sk_stop_timer(sk, &sk->sk_timer);
-}
-
-void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
-{
- sk_reset_timer(sk, &sk->sk_timer, jiffies + len);
+ inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL,
+ TCP_TIMEOUT_INIT, TCP_RTO_MAX);
}
void tcp_set_keepalive(struct sock *sk, int val)
@@ -560,15 +441,16 @@ void tcp_set_keepalive(struct sock *sk, int val)
return;
if (val && !sock_flag(sk, SOCK_KEEPOPEN))
- tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
+ inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
else if (!val)
- tcp_delete_keepalive_timer(sk);
+ inet_csk_delete_keepalive_timer(sk);
}
static void tcp_keepalive_timer (unsigned long data)
{
struct sock *sk = (struct sock *) data;
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
__u32 elapsed;
@@ -576,7 +458,7 @@ static void tcp_keepalive_timer (unsigned long data)
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* Try again later. */
- tcp_reset_keepalive_timer (sk, HZ/20);
+ inet_csk_reset_keepalive_timer (sk, HZ/20);
goto out;
}
@@ -587,7 +469,7 @@ static void tcp_keepalive_timer (unsigned long data)
if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {
if (tp->linger2 >= 0) {
- int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
+ const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN;
if (tmo > 0) {
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
@@ -610,14 +492,14 @@ static void tcp_keepalive_timer (unsigned long data)
elapsed = tcp_time_stamp - tp->rcv_tstamp;
if (elapsed >= keepalive_time_when(tp)) {
- if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||
- (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {
+ if ((!tp->keepalive_probes && icsk->icsk_probes_out >= sysctl_tcp_keepalive_probes) ||
+ (tp->keepalive_probes && icsk->icsk_probes_out >= tp->keepalive_probes)) {
tcp_send_active_reset(sk, GFP_ATOMIC);
tcp_write_err(sk);
goto out;
}
if (tcp_write_wakeup(sk) <= 0) {
- tp->probes_out++;
+ icsk->icsk_probes_out++;
elapsed = keepalive_intvl_when(tp);
} else {
/* If keepalive was lost due to local congestion,
@@ -634,7 +516,7 @@ static void tcp_keepalive_timer (unsigned long data)
sk_stream_mem_reclaim(sk);
resched:
- tcp_reset_keepalive_timer (sk, elapsed);
+ inet_csk_reset_keepalive_timer (sk, elapsed);
goto out;
death:
@@ -644,8 +526,3 @@ out:
bh_unlock_sock(sk);
sock_put(sk);
}
-
-EXPORT_SYMBOL(tcp_clear_xmit_timers);
-EXPORT_SYMBOL(tcp_delete_keepalive_timer);
-EXPORT_SYMBOL(tcp_init_xmit_timers);
-EXPORT_SYMBOL(tcp_reset_keepalive_timer);
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 9bd443db5193..93c5f92070f9 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -35,7 +35,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/tcp_diag.h>
+#include <linux/inet_diag.h>
#include <net/tcp.h>
@@ -82,9 +82,10 @@ struct vegas {
* Instead we must wait until the completion of an RTT during
* which we actually receive ACKs.
*/
-static inline void vegas_enable(struct tcp_sock *tp)
+static inline void vegas_enable(struct sock *sk)
{
- struct vegas *vegas = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct vegas *vegas = inet_csk_ca(sk);
/* Begin taking Vegas samples next time we send something. */
vegas->doing_vegas_now = 1;
@@ -97,19 +98,19 @@ static inline void vegas_enable(struct tcp_sock *tp)
}
/* Stop taking Vegas samples for now. */
-static inline void vegas_disable(struct tcp_sock *tp)
+static inline void vegas_disable(struct sock *sk)
{
- struct vegas *vegas = tcp_ca(tp);
+ struct vegas *vegas = inet_csk_ca(sk);
vegas->doing_vegas_now = 0;
}
-static void tcp_vegas_init(struct tcp_sock *tp)
+static void tcp_vegas_init(struct sock *sk)
{
- struct vegas *vegas = tcp_ca(tp);
+ struct vegas *vegas = inet_csk_ca(sk);
vegas->baseRTT = 0x7fffffff;
- vegas_enable(tp);
+ vegas_enable(sk);
}
/* Do RTT sampling needed for Vegas.
@@ -120,9 +121,9 @@ static void tcp_vegas_init(struct tcp_sock *tp)
* o min-filter RTT samples from a much longer window (forever for now)
* to find the propagation delay (baseRTT)
*/
-static void tcp_vegas_rtt_calc(struct tcp_sock *tp, u32 usrtt)
+static void tcp_vegas_rtt_calc(struct sock *sk, u32 usrtt)
{
- struct vegas *vegas = tcp_ca(tp);
+ struct vegas *vegas = inet_csk_ca(sk);
u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
/* Filter to find propagation delay: */
@@ -136,13 +137,13 @@ static void tcp_vegas_rtt_calc(struct tcp_sock *tp, u32 usrtt)
vegas->cntRTT++;
}
-static void tcp_vegas_state(struct tcp_sock *tp, u8 ca_state)
+static void tcp_vegas_state(struct sock *sk, u8 ca_state)
{
if (ca_state == TCP_CA_Open)
- vegas_enable(tp);
+ vegas_enable(sk);
else
- vegas_disable(tp);
+ vegas_disable(sk);
}
/*
@@ -154,20 +155,21 @@ static void tcp_vegas_state(struct tcp_sock *tp, u8 ca_state)
* packets, _then_ we can make Vegas calculations
* again.
*/
-static void tcp_vegas_cwnd_event(struct tcp_sock *tp, enum tcp_ca_event event)
+static void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event)
{
if (event == CA_EVENT_CWND_RESTART ||
event == CA_EVENT_TX_START)
- tcp_vegas_init(tp);
+ tcp_vegas_init(sk);
}
-static void tcp_vegas_cong_avoid(struct tcp_sock *tp, u32 ack,
+static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack,
u32 seq_rtt, u32 in_flight, int flag)
{
- struct vegas *vegas = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct vegas *vegas = inet_csk_ca(sk);
if (!vegas->doing_vegas_now)
- return tcp_reno_cong_avoid(tp, ack, seq_rtt, in_flight, flag);
+ return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
/* The key players are v_beg_snd_una and v_beg_snd_nxt.
*
@@ -219,7 +221,7 @@ static void tcp_vegas_cong_avoid(struct tcp_sock *tp, u32 ack,
* but that's not too awful, since we're taking the min,
* rather than averaging.
*/
- tcp_vegas_rtt_calc(tp, seq_rtt*1000);
+ tcp_vegas_rtt_calc(sk, seq_rtt * 1000);
/* We do the Vegas calculations only if we got enough RTT
* samples that we can be reasonably sure that we got
@@ -359,14 +361,14 @@ static void tcp_vegas_cong_avoid(struct tcp_sock *tp, u32 ack,
}
/* Extract info for Tcp socket info provided via netlink. */
-static void tcp_vegas_get_info(struct tcp_sock *tp, u32 ext,
+static void tcp_vegas_get_info(struct sock *sk, u32 ext,
struct sk_buff *skb)
{
- const struct vegas *ca = tcp_ca(tp);
- if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+ const struct vegas *ca = inet_csk_ca(sk);
+ if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
struct tcpvegas_info *info;
- info = RTA_DATA(__RTA_PUT(skb, TCPDIAG_VEGASINFO,
+ info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
sizeof(*info)));
info->tcpv_enabled = ca->doing_vegas_now;
@@ -393,7 +395,7 @@ static struct tcp_congestion_ops tcp_vegas = {
static int __init tcp_vegas_register(void)
{
- BUG_ON(sizeof(struct vegas) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct vegas) > ICSK_CA_PRIV_SIZE);
tcp_register_congestion_control(&tcp_vegas);
return 0;
}
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index ef827242c940..0c340c3756c2 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -8,7 +8,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/tcp_diag.h>
+#include <linux/inet_diag.h>
#include <net/tcp.h>
/* TCP Westwood structure */
@@ -40,9 +40,9 @@ struct westwood {
* way as soon as possible. It will reasonably happen within the first
* RTT period of the connection lifetime.
*/
-static void tcp_westwood_init(struct tcp_sock *tp)
+static void tcp_westwood_init(struct sock *sk)
{
- struct westwood *w = tcp_ca(tp);
+ struct westwood *w = inet_csk_ca(sk);
w->bk = 0;
w->bw_ns_est = 0;
@@ -51,7 +51,7 @@ static void tcp_westwood_init(struct tcp_sock *tp)
w->cumul_ack = 0;
w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
w->rtt_win_sx = tcp_time_stamp;
- w->snd_una = tp->snd_una;
+ w->snd_una = tcp_sk(sk)->snd_una;
}
/*
@@ -74,11 +74,11 @@ static inline void westwood_filter(struct westwood *w, u32 delta)
* Called after processing group of packets.
* but all westwood needs is the last sample of srtt.
*/
-static void tcp_westwood_pkts_acked(struct tcp_sock *tp, u32 cnt)
+static void tcp_westwood_pkts_acked(struct sock *sk, u32 cnt)
{
- struct westwood *w = tcp_ca(tp);
+ struct westwood *w = inet_csk_ca(sk);
if (cnt > 0)
- w->rtt = tp->srtt >> 3;
+ w->rtt = tcp_sk(sk)->srtt >> 3;
}
/*
@@ -86,9 +86,9 @@ static void tcp_westwood_pkts_acked(struct tcp_sock *tp, u32 cnt)
* It updates RTT evaluation window if it is the right moment to do
* it. If so it calls filter for evaluating bandwidth.
*/
-static void westwood_update_window(struct tcp_sock *tp)
+static void westwood_update_window(struct sock *sk)
{
- struct westwood *w = tcp_ca(tp);
+ struct westwood *w = inet_csk_ca(sk);
s32 delta = tcp_time_stamp - w->rtt_win_sx;
/*
@@ -114,11 +114,12 @@ static void westwood_update_window(struct tcp_sock *tp)
* header prediction is successful. In such case in fact update is
* straight forward and doesn't need any particular care.
*/
-static inline void westwood_fast_bw(struct tcp_sock *tp)
+static inline void westwood_fast_bw(struct sock *sk)
{
- struct westwood *w = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct westwood *w = inet_csk_ca(sk);
- westwood_update_window(tp);
+ westwood_update_window(sk);
w->bk += tp->snd_una - w->snd_una;
w->snd_una = tp->snd_una;
@@ -130,9 +131,10 @@ static inline void westwood_fast_bw(struct tcp_sock *tp)
* This function evaluates cumul_ack for evaluating bk in case of
* delayed or partial acks.
*/
-static inline u32 westwood_acked_count(struct tcp_sock *tp)
+static inline u32 westwood_acked_count(struct sock *sk)
{
- struct westwood *w = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct westwood *w = inet_csk_ca(sk);
w->cumul_ack = tp->snd_una - w->snd_una;
@@ -160,9 +162,10 @@ static inline u32 westwood_acked_count(struct tcp_sock *tp)
return w->cumul_ack;
}
-static inline u32 westwood_bw_rttmin(const struct tcp_sock *tp)
+static inline u32 westwood_bw_rttmin(const struct sock *sk)
{
- struct westwood *w = tcp_ca(tp);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct westwood *w = inet_csk_ca(sk);
return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
}
@@ -172,31 +175,32 @@ static inline u32 westwood_bw_rttmin(const struct tcp_sock *tp)
* in packets we use mss_cache). Rttmin is guaranteed to be >= 2
* so avoids ever returning 0.
*/
-static u32 tcp_westwood_cwnd_min(struct tcp_sock *tp)
+static u32 tcp_westwood_cwnd_min(struct sock *sk)
{
- return westwood_bw_rttmin(tp);
+ return westwood_bw_rttmin(sk);
}
-static void tcp_westwood_event(struct tcp_sock *tp, enum tcp_ca_event event)
+static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
{
- struct westwood *w = tcp_ca(tp);
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct westwood *w = inet_csk_ca(sk);
switch(event) {
case CA_EVENT_FAST_ACK:
- westwood_fast_bw(tp);
+ westwood_fast_bw(sk);
break;
case CA_EVENT_COMPLETE_CWR:
- tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(tp);
+ tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(sk);
break;
case CA_EVENT_FRTO:
- tp->snd_ssthresh = westwood_bw_rttmin(tp);
+ tp->snd_ssthresh = westwood_bw_rttmin(sk);
break;
case CA_EVENT_SLOW_ACK:
- westwood_update_window(tp);
- w->bk += westwood_acked_count(tp);
+ westwood_update_window(sk);
+ w->bk += westwood_acked_count(sk);
w->rtt_min = min(w->rtt, w->rtt_min);
break;
@@ -208,15 +212,15 @@ static void tcp_westwood_event(struct tcp_sock *tp, enum tcp_ca_event event)
/* Extract info for Tcp socket info provided via netlink. */
-static void tcp_westwood_info(struct tcp_sock *tp, u32 ext,
+static void tcp_westwood_info(struct sock *sk, u32 ext,
struct sk_buff *skb)
{
- const struct westwood *ca = tcp_ca(tp);
- if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+ const struct westwood *ca = inet_csk_ca(sk);
+ if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
struct rtattr *rta;
struct tcpvegas_info *info;
- rta = __RTA_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*info));
+ rta = __RTA_PUT(skb, INET_DIAG_VEGASINFO, sizeof(*info));
info = RTA_DATA(rta);
info->tcpv_enabled = 1;
info->tcpv_rttcnt = 0;
@@ -242,7 +246,7 @@ static struct tcp_congestion_ops tcp_westwood = {
static int __init tcp_westwood_register(void)
{
- BUG_ON(sizeof(struct westwood) > TCP_CA_PRIV_SIZE);
+ BUG_ON(sizeof(struct westwood) > ICSK_CA_PRIV_SIZE);
return tcp_register_congestion_control(&tcp_westwood);
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index dc4d07357e3a..e0bd1013cb0d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -95,7 +95,8 @@
#include <linux/ipv6.h>
#include <linux/netdevice.h>
#include <net/snmp.h>
-#include <net/tcp.h>
+#include <net/ip.h>
+#include <net/tcp_states.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
@@ -112,7 +113,7 @@
* Snmp MIB for the UDP layer
*/
-DEFINE_SNMP_STAT(struct udp_mib, udp_statistics);
+DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
struct hlist_head udp_hash[UDP_HTABLE_SIZE];
DEFINE_RWLOCK(udp_hash_lock);
@@ -628,7 +629,7 @@ back_from_confirm:
/* ... which is an evident application bug. --ANK */
release_sock(sk);
- LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 2\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");
err = -EINVAL;
goto out;
}
@@ -693,7 +694,7 @@ static int udp_sendpage(struct sock *sk, struct page *page, int offset,
if (unlikely(!up->pending)) {
release_sock(sk);
- LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 3\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 3\n");
return -EINVAL;
}
@@ -1102,7 +1103,7 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
return 0;
- LIMIT_NETDEBUG(printk(KERN_DEBUG "udp v4 hw csum failure.\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "udp v4 hw csum failure.\n");
skb->ip_summed = CHECKSUM_NONE;
}
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -1140,7 +1141,7 @@ int udp_rcv(struct sk_buff *skb)
if (ulen > len || ulen < sizeof(*uh))
goto short_packet;
- if (pskb_trim(skb, ulen))
+ if (pskb_trim_rcsum(skb, ulen))
goto short_packet;
if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
@@ -1181,13 +1182,13 @@ int udp_rcv(struct sk_buff *skb)
return(0);
short_packet:
- LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
- NIPQUAD(saddr),
- ntohs(uh->source),
- ulen,
- len,
- NIPQUAD(daddr),
- ntohs(uh->dest)));
+ LIMIT_NETDEBUG(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+ ulen,
+ len,
+ NIPQUAD(daddr),
+ ntohs(uh->dest));
no_header:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
kfree_skb(skb);
@@ -1198,12 +1199,12 @@ csum_error:
* RFC1122: OK. Discards the bad packet silently (as far as
* the network is concerned, anyway) as per 4.1.3.4 (MUST).
*/
- LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
- NIPQUAD(saddr),
- ntohs(uh->source),
- NIPQUAD(daddr),
- ntohs(uh->dest),
- ulen));
+ LIMIT_NETDEBUG(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+ NIPQUAD(daddr),
+ ntohs(uh->dest),
+ ulen);
drop:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
kfree_skb(skb);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 050611d7a967..d23e07fc81fa 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -128,8 +128,10 @@ void __init xfrm4_state_init(void)
xfrm_state_register_afinfo(&xfrm4_state_afinfo);
}
+#if 0
void __exit xfrm4_state_fini(void)
{
xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
}
+#endif /* 0 */
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index b39e04940590..6460eec834b7 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -8,7 +8,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
- ip6_flowlabel.o ipv6_syms.o
+ ip6_flowlabel.o ipv6_syms.o netfilter.o
ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
xfrm6_output.o
@@ -23,3 +23,5 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
obj-y += exthdrs_core.o
+
+obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 77004b9456c0..2fea3f4402a0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -123,8 +123,7 @@ DEFINE_RWLOCK(addrconf_lock);
static void addrconf_verify(unsigned long);
-static struct timer_list addr_chk_timer =
- TIMER_INITIALIZER(addrconf_verify, 0, 0);
+static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
static DEFINE_SPINLOCK(addrconf_verify_lock);
static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
@@ -1041,9 +1040,9 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
const struct in6_addr *sk2_rcv_saddr6 = tcp_v6_rcv_saddr(sk2);
u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
- u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2);
+ u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
int sk_ipv6only = ipv6_only_sock(sk);
- int sk2_ipv6only = tcp_v6_ipv6only(sk2);
+ int sk2_ipv6only = inet_v6_ipv6only(sk2);
int addr_type = ipv6_addr_type(sk_rcv_saddr6);
int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
@@ -1126,7 +1125,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr)
__ipv6_dev_mc_dec(idev, &maddr);
}
-void addrconf_join_anycast(struct inet6_ifaddr *ifp)
+static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
{
struct in6_addr addr;
ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -1135,7 +1134,7 @@ void addrconf_join_anycast(struct inet6_ifaddr *ifp)
ipv6_dev_ac_inc(ifp->idev->dev, &addr);
}
-void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
+static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
{
struct in6_addr addr;
ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -2858,16 +2857,16 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, ENOBUFS);
return;
}
if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, EINVAL);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFADDR;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFADDR, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFADDR;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFADDR, GFP_ATOMIC);
}
static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
@@ -2994,16 +2993,16 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, ENOBUFS);
return;
}
if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, EINVAL);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFINFO;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFINFO, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFINFO;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
}
static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
@@ -3054,16 +3053,16 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, ENOBUFS);
return;
}
if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, EINVAL);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_PREFIX;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_PREFIX;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_PREFIX, GFP_ATOMIC);
}
static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
@@ -3593,10 +3592,8 @@ void __exit addrconf_cleanup(void)
rtnl_unlock();
#ifdef CONFIG_IPV6_PRIVACY
- if (likely(md5_tfm != NULL)) {
- crypto_free_tfm(md5_tfm);
- md5_tfm = NULL;
- }
+ crypto_free_tfm(md5_tfm);
+ md5_tfm = NULL;
#endif
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 28d9bcab0970..4f8795af2edb 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -44,6 +44,7 @@
#include <linux/netdevice.h>
#include <linux/icmpv6.h>
#include <linux/smp_lock.h>
+#include <linux/netfilter_ipv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -66,45 +67,14 @@ MODULE_AUTHOR("Cast of dozens");
MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
MODULE_LICENSE("GPL");
-/* IPv6 procfs goodies... */
-
-#ifdef CONFIG_PROC_FS
-extern int raw6_proc_init(void);
-extern void raw6_proc_exit(void);
-extern int tcp6_proc_init(void);
-extern void tcp6_proc_exit(void);
-extern int udp6_proc_init(void);
-extern void udp6_proc_exit(void);
-extern int ipv6_misc_proc_init(void);
-extern void ipv6_misc_proc_exit(void);
-extern int ac6_proc_init(void);
-extern void ac6_proc_exit(void);
-extern int if6_proc_init(void);
-extern void if6_proc_exit(void);
-#endif
-
int sysctl_ipv6_bindv6only;
-#ifdef INET_REFCNT_DEBUG
-atomic_t inet6_sock_nr;
-EXPORT_SYMBOL(inet6_sock_nr);
-#endif
-
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
*/
static struct list_head inetsw6[SOCK_MAX];
static DEFINE_SPINLOCK(inetsw6_lock);
-static void inet6_sock_destruct(struct sock *sk)
-{
- inet_sock_destruct(sk);
-
-#ifdef INET_REFCNT_DEBUG
- atomic_dec(&inet6_sock_nr);
-#endif
-}
-
static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
{
const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
@@ -185,7 +155,7 @@ static int inet6_create(struct socket *sock, int protocol)
inet->hdrincl = 1;
}
- sk->sk_destruct = inet6_sock_destruct;
+ sk->sk_destruct = inet_sock_destruct;
sk->sk_family = PF_INET6;
sk->sk_protocol = protocol;
@@ -212,12 +182,17 @@ static int inet6_create(struct socket *sock, int protocol)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;
+ /*
+ * Increment only the relevant sk_prot->socks debug field, this changes
+ * the previous behaviour of incrementing both the equivalent to
+ * answer->prot->socks (inet6_sock_nr) and inet_sock_nr.
+ *
+ * This allows better debug granularity as we'll know exactly how many
+ * UDPv6, TCPv6, etc socks were allocated, not the sum of all IPv6
+ * transport protocol socks. -acme
+ */
+ sk_refcnt_debug_inc(sk);
-
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet6_sock_nr);
- atomic_inc(&inet_sock_nr);
-#endif
if (inet->num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
@@ -513,11 +488,6 @@ static struct net_proto_family inet6_family_ops = {
.owner = THIS_MODULE,
};
-#ifdef CONFIG_SYSCTL
-extern void ipv6_sysctl_register(void);
-extern void ipv6_sysctl_unregister(void);
-#endif
-
/* Same as inet6_dgram_ops, sans udp_poll. */
static struct proto_ops inet6_sockraw_ops = {
.family = PF_INET6,
@@ -684,8 +654,6 @@ static void cleanup_ipv6_mibs(void)
snmp6_mib_free((void **)udp_stats_in6);
}
-extern int ipv6_misc_proc_init(void);
-
static int __init inet6_init(void)
{
struct sk_buff *dummy_skb;
@@ -757,6 +725,9 @@ static int __init inet6_init(void)
err = igmp6_init(&inet6_family_ops);
if (err)
goto igmp_fail;
+ err = ipv6_netfilter_init();
+ if (err)
+ goto netfilter_fail;
/* Create /proc/foo6 entries. */
#ifdef CONFIG_PROC_FS
err = -ENOMEM;
@@ -813,6 +784,8 @@ proc_tcp6_fail:
raw6_proc_exit();
proc_raw6_fail:
#endif
+ ipv6_netfilter_fini();
+netfilter_fail:
igmp6_cleanup();
igmp_fail:
ndisc_cleanup();
@@ -852,6 +825,7 @@ static void __exit inet6_exit(void)
ip6_route_cleanup();
ipv6_packet_cleanup();
igmp6_cleanup();
+ ipv6_netfilter_fini();
ndisc_cleanup();
icmpv6_cleanup();
#ifdef CONFIG_SYSCTL
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 986fdfdccbcd..f3629730eb15 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -131,10 +131,10 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
case NEXTHDR_HOP:
case NEXTHDR_DEST:
if (!zero_out_mutable_opts(exthdr.opth)) {
- LIMIT_NETDEBUG(printk(
+ LIMIT_NETDEBUG(
KERN_WARNING "overrun %sopts\n",
nexthdr == NEXTHDR_HOP ?
- "hop" : "dest"));
+ "hop" : "dest");
return -EINVAL;
}
break;
@@ -293,8 +293,7 @@ static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
skb_push(skb, skb->data - skb->nh.raw);
ahp->icv(ahp, skb, ah->auth_data);
if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
- LIMIT_NETDEBUG(
- printk(KERN_WARNING "ipsec ah authentication error\n"));
+ LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
x->stats.integrity_failed++;
goto free_out;
}
@@ -332,9 +331,9 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (!x)
return;
- NETDEBUG(printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/"
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
- ntohl(ah->spi), NIP6(iph->daddr)));
+ NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/"
+ "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ ntohl(ah->spi), NIP6(iph->daddr));
xfrm_state_put(x);
}
@@ -402,10 +401,8 @@ static int ah6_init_state(struct xfrm_state *x)
error:
if (ahp) {
- if (ahp->work_icv)
- kfree(ahp->work_icv);
- if (ahp->tfm)
- crypto_free_tfm(ahp->tfm);
+ kfree(ahp->work_icv);
+ crypto_free_tfm(ahp->tfm);
kfree(ahp);
}
return -EINVAL;
@@ -418,14 +415,10 @@ static void ah6_destroy(struct xfrm_state *x)
if (!ahp)
return;
- if (ahp->work_icv) {
- kfree(ahp->work_icv);
- ahp->work_icv = NULL;
- }
- if (ahp->tfm) {
- crypto_free_tfm(ahp->tfm);
- ahp->tfm = NULL;
- }
+ kfree(ahp->work_icv);
+ ahp->work_icv = NULL;
+ crypto_free_tfm(ahp->tfm);
+ ahp->tfm = NULL;
kfree(ahp);
}
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 5229365cd8b4..cc518405b3e1 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -29,6 +29,7 @@
#include <net/addrconf.h>
#include <net/transp_v6.h>
#include <net/ip6_route.h>
+#include <net/tcp_states.h>
#include <linux/errqueue.h>
#include <asm/uaccess.h>
@@ -174,10 +175,8 @@ ipv4_connected:
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
- dst_release(dst);
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto out;
- }
/* source address lookup done in ip6_dst_lookup */
@@ -389,32 +388,101 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
}
+ if (np->rxopt.bits.rxtclass) {
+ int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff;
+ put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
+ }
+
if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
}
+
+ /* HbH is allowed only once */
if (np->rxopt.bits.hopopts && opt->hop) {
u8 *ptr = skb->nh.raw + opt->hop;
put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
}
- if (np->rxopt.bits.dstopts && opt->dst0) {
+
+ if (opt->lastopt &&
+ (np->rxopt.bits.dstopts || np->rxopt.bits.srcrt)) {
+ /*
+ * Silly enough, but we need to reparse in order to
+ * report extension headers (except for HbH)
+ * in order.
+ *
+ * Also note that IPV6_RECVRTHDRDSTOPTS is NOT
+ * (and WILL NOT be) defined because
+ * IPV6_RECVDSTOPTS is more generic. --yoshfuji
+ */
+ unsigned int off = sizeof(struct ipv6hdr);
+ u8 nexthdr = skb->nh.ipv6h->nexthdr;
+
+ while (off <= opt->lastopt) {
+ unsigned len;
+ u8 *ptr = skb->nh.raw + off;
+
+ switch(nexthdr) {
+ case IPPROTO_DSTOPTS:
+ nexthdr = ptr[0];
+ len = (ptr[1] + 1) << 3;
+ if (np->rxopt.bits.dstopts)
+ put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, len, ptr);
+ break;
+ case IPPROTO_ROUTING:
+ nexthdr = ptr[0];
+ len = (ptr[1] + 1) << 3;
+ if (np->rxopt.bits.srcrt)
+ put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, len, ptr);
+ break;
+ case IPPROTO_AH:
+ nexthdr = ptr[0];
+ len = (ptr[1] + 1) << 2;
+ break;
+ default:
+ nexthdr = ptr[0];
+ len = (ptr[1] + 1) << 3;
+ break;
+ }
+
+ off += len;
+ }
+ }
+
+ /* socket options in old style */
+ if (np->rxopt.bits.rxoinfo) {
+ struct in6_pktinfo src_info;
+
+ src_info.ipi6_ifindex = opt->iif;
+ ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr);
+ put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
+ }
+ if (np->rxopt.bits.rxohlim) {
+ int hlim = skb->nh.ipv6h->hop_limit;
+ put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
+ }
+ if (np->rxopt.bits.ohopopts && opt->hop) {
+ u8 *ptr = skb->nh.raw + opt->hop;
+ put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr);
+ }
+ if (np->rxopt.bits.odstopts && opt->dst0) {
u8 *ptr = skb->nh.raw + opt->dst0;
- put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
+ put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
}
- if (np->rxopt.bits.srcrt && opt->srcrt) {
+ if (np->rxopt.bits.osrcrt && opt->srcrt) {
struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt);
- put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr);
+ put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr);
}
- if (np->rxopt.bits.dstopts && opt->dst1) {
+ if (np->rxopt.bits.odstopts && opt->dst1) {
u8 *ptr = skb->nh.raw + opt->dst1;
- put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
+ put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
}
return 0;
}
int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
struct ipv6_txoptions *opt,
- int *hlimit)
+ int *hlimit, int *tclass)
{
struct in6_pktinfo *src_info;
struct cmsghdr *cmsg;
@@ -437,6 +505,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
switch (cmsg->cmsg_type) {
case IPV6_PKTINFO:
+ case IPV6_2292PKTINFO:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
err = -EINVAL;
goto exit_f;
@@ -491,6 +560,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg);
break;
+ case IPV6_2292HOPOPTS:
case IPV6_HOPOPTS:
if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
err = -EINVAL;
@@ -511,7 +581,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt->hopopt = hdr;
break;
- case IPV6_DSTOPTS:
+ case IPV6_2292DSTOPTS:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
err = -EINVAL;
goto exit_f;
@@ -535,6 +605,33 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt->dst1opt = hdr;
break;
+ case IPV6_DSTOPTS:
+ case IPV6_RTHDRDSTOPTS:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+
+ hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg);
+ len = ((hdr->hdrlen + 1) << 3);
+ if (cmsg->cmsg_len < CMSG_LEN(len)) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+ if (!capable(CAP_NET_RAW)) {
+ err = -EPERM;
+ goto exit_f;
+ }
+ if (cmsg->cmsg_type == IPV6_DSTOPTS) {
+ opt->opt_flen += len;
+ opt->dst1opt = hdr;
+ } else {
+ opt->opt_nflen += len;
+ opt->dst0opt = hdr;
+ }
+ break;
+
+ case IPV6_2292RTHDR:
case IPV6_RTHDR:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) {
err = -EINVAL;
@@ -567,7 +664,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt->opt_nflen += len;
opt->srcrt = rthdr;
- if (opt->dst1opt) {
+ if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) {
int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3);
opt->opt_nflen += dsthdrlen;
@@ -578,6 +675,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
break;
+ case IPV6_2292HOPLIMIT:
case IPV6_HOPLIMIT:
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
err = -EINVAL;
@@ -587,9 +685,27 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
*hlimit = *(int *)CMSG_DATA(cmsg);
break;
+ case IPV6_TCLASS:
+ {
+ int tc;
+
+ err = -EINVAL;
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+ goto exit_f;
+ }
+
+ tc = *(int *)CMSG_DATA(cmsg);
+ if (tc < 0 || tc > 0xff)
+ goto exit_f;
+
+ err = 0;
+ *tclass = tc;
+
+ break;
+ }
default:
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "invalid cmsg type: %d\n", cmsg->cmsg_type));
+ LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n",
+ cmsg->cmsg_type);
err = -EINVAL;
break;
};
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 324db62515a2..9b27460f0cc7 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -212,8 +212,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
padlen = nexthdr[0];
if (padlen+2 >= elen) {
- LIMIT_NETDEBUG(
- printk(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen));
+ LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen);
ret = -EINVAL;
goto out;
}
@@ -277,22 +276,14 @@ static void esp6_destroy(struct xfrm_state *x)
if (!esp)
return;
- if (esp->conf.tfm) {
- crypto_free_tfm(esp->conf.tfm);
- esp->conf.tfm = NULL;
- }
- if (esp->conf.ivec) {
- kfree(esp->conf.ivec);
- esp->conf.ivec = NULL;
- }
- if (esp->auth.tfm) {
- crypto_free_tfm(esp->auth.tfm);
- esp->auth.tfm = NULL;
- }
- if (esp->auth.work_icv) {
- kfree(esp->auth.work_icv);
- esp->auth.work_icv = NULL;
- }
+ crypto_free_tfm(esp->conf.tfm);
+ esp->conf.tfm = NULL;
+ kfree(esp->conf.ivec);
+ esp->conf.ivec = NULL;
+ crypto_free_tfm(esp->auth.tfm);
+ esp->auth.tfm = NULL;
+ kfree(esp->auth.work_icv);
+ esp->auth.work_icv = NULL;
kfree(esp);
}
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index e0839eafc3a9..922549581abc 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -164,6 +164,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
return -1;
}
+ opt->lastopt = skb->h.raw - skb->nh.raw;
opt->dst1 = skb->h.raw - skb->nh.raw;
if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
@@ -243,6 +244,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
looped_back:
if (hdr->segments_left == 0) {
+ opt->lastopt = skb->h.raw - skb->nh.raw;
opt->srcrt = skb->h.raw - skb->nh.raw;
skb->h.raw += (hdr->hdrlen + 1) << 3;
opt->dst0 = opt->dst1;
@@ -404,8 +406,7 @@ ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
memcpy(opt->srcrt, hdr, sizeof(*hdr));
irthdr = (struct rt0_hdr*)opt->srcrt;
- /* Obsolete field, MBZ, when originated by us */
- irthdr->bitmap = 0;
+ irthdr->reserved = 0;
opt->srcrt->segments_left = n;
for (i=0; i<n; i++)
memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
@@ -424,8 +425,8 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
IP6CB(skb)->ra = optoff;
return 1;
}
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]));
+ LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
+ skb->nh.raw[optoff+1]);
kfree_skb(skb);
return 0;
}
@@ -437,8 +438,8 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
u32 pkt_len;
if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]));
+ LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
+ skb->nh.raw[optoff+1]);
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
goto drop;
}
@@ -459,11 +460,10 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
}
- if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
- __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
- }
+
+ if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
+ goto drop;
+
return 1;
drop:
@@ -539,10 +539,15 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto,
struct in6_addr **daddr)
{
- if (opt->srcrt)
+ if (opt->srcrt) {
ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
- if (opt->dst0opt)
- ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
+ /*
+ * IPV6_RTHDRDSTOPTS is ignored
+ * unless IPV6_RTHDR is set (RFC3542).
+ */
+ if (opt->dst0opt)
+ ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
+ }
if (opt->hopopt)
ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
}
@@ -573,3 +578,97 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
}
return opt2;
}
+
+static int ipv6_renew_option(void *ohdr,
+ struct ipv6_opt_hdr __user *newopt, int newoptlen,
+ int inherit,
+ struct ipv6_opt_hdr **hdr,
+ char **p)
+{
+ if (inherit) {
+ if (ohdr) {
+ memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
+ *hdr = (struct ipv6_opt_hdr *)*p;
+ *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
+ }
+ } else {
+ if (newopt) {
+ if (copy_from_user(*p, newopt, newoptlen))
+ return -EFAULT;
+ *hdr = (struct ipv6_opt_hdr *)*p;
+ if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
+ return -EINVAL;
+ *p += CMSG_ALIGN(newoptlen);
+ }
+ }
+ return 0;
+}
+
+struct ipv6_txoptions *
+ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
+ int newtype,
+ struct ipv6_opt_hdr __user *newopt, int newoptlen)
+{
+ int tot_len = 0;
+ char *p;
+ struct ipv6_txoptions *opt2;
+ int err;
+
+ if (newtype != IPV6_HOPOPTS && opt->hopopt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
+ if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
+ if (newtype != IPV6_RTHDR && opt->srcrt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
+ if (newtype != IPV6_DSTOPTS && opt->dst1opt)
+ tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
+ if (newopt && newoptlen)
+ tot_len += CMSG_ALIGN(newoptlen);
+
+ if (!tot_len)
+ return NULL;
+
+ opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
+ if (!opt2)
+ return ERR_PTR(-ENOBUFS);
+
+ memset(opt2, 0, tot_len);
+
+ opt2->tot_len = tot_len;
+ p = (char *)(opt2 + 1);
+
+ err = ipv6_renew_option(opt->hopopt, newopt, newoptlen,
+ newtype != IPV6_HOPOPTS,
+ &opt2->hopopt, &p);
+ if (err)
+ goto out;
+
+ err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen,
+ newtype != IPV6_RTHDRDSTOPTS,
+ &opt2->dst0opt, &p);
+ if (err)
+ goto out;
+
+ err = ipv6_renew_option(opt->srcrt, newopt, newoptlen,
+ newtype != IPV6_RTHDR,
+ (struct ipv6_opt_hdr **)opt2->srcrt, &p);
+ if (err)
+ goto out;
+
+ err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen,
+ newtype != IPV6_DSTOPTS,
+ &opt2->dst1opt, &p);
+ if (err)
+ goto out;
+
+ opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
+ (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
+ (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
+ opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
+
+ return opt2;
+out:
+ sock_kfree_s(sk, p, tot_len);
+ return ERR_PTR(err);
+}
+
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index ff3ec9822e36..b7185fb3377c 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -67,7 +67,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
+DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly;
/*
* The ICMP socket(s). This is the most convenient way to flow control
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
int iif = 0;
int addr_type = 0;
int len;
- int hlimit;
+ int hlimit, tclass;
int err = 0;
if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
@@ -332,8 +332,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
* for now we don't know that.
*/
if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
return;
}
@@ -341,8 +340,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
* Never answer to a ICMP packet.
*/
if (is_ineligible(skb)) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n");
return;
}
@@ -376,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (err)
goto out;
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
- goto out_dst_release;
+ goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops;
@@ -387,14 +385,17 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (hlimit < 0)
hlimit = ipv6_get_hoplimit(dst->dev);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
len = skb->len - msg.offset;
len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr));
if (len < 0) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "icmp: len problem\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "icmp: len problem\n");
goto out_dst_release;
}
@@ -403,7 +404,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr),
- hlimit, NULL, &fl, (struct rt6_info*)dst,
+ hlimit, tclass, NULL, &fl, (struct rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -437,6 +438,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
struct dst_entry *dst;
int err = 0;
int hlimit;
+ int tclass;
saddr = &skb->nh.ipv6h->daddr;
@@ -467,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (err)
goto out;
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
- goto out_dst_release;
+ goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops;
@@ -478,13 +480,17 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (hlimit < 0)
hlimit = ipv6_get_hoplimit(dst->dev);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+
idev = in6_dev_get(skb->dev);
msg.skb = skb;
msg.offset = 0;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, NULL, &fl,
+ sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl,
(struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
@@ -499,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
out_put:
if (likely(idev != NULL))
in6_dev_put(idev);
-out_dst_release:
dst_release(dst);
out:
icmpv6_xmit_unlock();
@@ -551,7 +556,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
read_lock(&raw_v6_lock);
if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
- while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
+ while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr,
+ IP6CB(skb)->iif))) {
rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
sk = sk_next(sk);
}
@@ -583,17 +589,15 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
skb->csum)) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "ICMPv6 hw checksum failed\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 hw checksum failed\n");
skb->ip_summed = CHECKSUM_NONE;
}
}
if (skb->ip_summed == CHECKSUM_NONE) {
if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
skb_checksum(skb, 0, skb->len, 0))) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
- NIP6(*saddr), NIP6(*daddr)));
+ LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
+ NIP6(*saddr), NIP6(*daddr));
goto discard_it;
}
}
@@ -669,8 +673,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
break;
default:
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "icmpv6: msg of unknown type\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "icmpv6: msg of unknown type\n");
/* informational */
if (type & ICMPV6_INFOMSG_MASK)
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
new file mode 100644
index 000000000000..01d5f46d4e40
--- /dev/null
+++ b/net/ipv6/inet6_hashtables.c
@@ -0,0 +1,81 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Generic INET6 transport hashtables
+ *
+ * Authors: Lotsa people, from code originally in tcp
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+
+#include <net/inet_connection_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet6_hashtables.h>
+
+struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *daddr,
+ const unsigned short hnum, const int dif)
+{
+ struct sock *sk;
+ const struct hlist_node *node;
+ struct sock *result = NULL;
+ int score, hiscore = 0;
+
+ read_lock(&hashinfo->lhash_lock);
+ sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
+ if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+
+ score = 1;
+ if (!ipv6_addr_any(&np->rcv_saddr)) {
+ if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
+ continue;
+ score++;
+ }
+ if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if (score == 3) {
+ result = sk;
+ break;
+ }
+ if (score > hiscore) {
+ hiscore = score;
+ result = sk;
+ }
+ }
+ }
+ if (result)
+ sock_hold(result);
+ read_unlock(&hashinfo->lhash_lock);
+ return result;
+}
+
+EXPORT_SYMBOL_GPL(inet6_lookup_listener);
+
+struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr, const u16 sport,
+ const struct in6_addr *daddr, const u16 dport,
+ const int dif)
+{
+ struct sock *sk;
+
+ local_bh_disable();
+ sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
+ local_bh_enable();
+
+ return sk;
+}
+
+EXPORT_SYMBOL_GPL(inet6_lookup);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1b354aa97934..4fcc5a7acf6e 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -49,7 +49,7 @@
struct rt6_statistics rt6_stats;
-static kmem_cache_t * fib6_node_kmem;
+static kmem_cache_t * fib6_node_kmem __read_mostly;
enum fib_walk_state_t
{
@@ -92,7 +92,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
static __u32 rt_sernum;
-static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0);
+static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
struct fib6_walker_t fib6_walker_list = {
.prev = &fib6_walker_list,
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index b6c73da5ff35..f841bde30c18 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -50,7 +50,7 @@ static atomic_t fl_size = ATOMIC_INIT(0);
static struct ip6_flowlabel *fl_ht[FL_HASH_MASK+1];
static void ip6_fl_gc(unsigned long dummy);
-static struct timer_list ip6_fl_gc_timer = TIMER_INITIALIZER(ip6_fl_gc, 0, 0);
+static DEFINE_TIMER(ip6_fl_gc_timer, ip6_fl_gc, 0, 0);
/* FL hash table lock: it protects only of GC */
@@ -225,16 +225,20 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
struct ip6_flowlabel * fl,
struct ipv6_txoptions * fopt)
{
- struct ipv6_txoptions * fl_opt = fl->opt;
+ struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL;
- if (fopt == NULL || fopt->opt_flen == 0)
- return fl_opt;
+ if (fopt == NULL || fopt->opt_flen == 0) {
+ if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt)
+ return fl_opt;
+ }
if (fl_opt != NULL) {
opt_space->hopopt = fl_opt->hopopt;
- opt_space->dst0opt = fl_opt->dst0opt;
+ opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL;
opt_space->srcrt = fl_opt->srcrt;
opt_space->opt_nflen = fl_opt->opt_nflen;
+ if (fl_opt->dst0opt && !fl_opt->srcrt)
+ opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt);
} else {
if (fopt->opt_nflen == 0)
return fopt;
@@ -310,7 +314,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
msg.msg_control = (void*)(fl->opt+1);
flowi.oif = 0;
- err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+ err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
if (err)
goto done;
err = -EINVAL;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 10fbb50daea4..6e3480426939 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -56,7 +56,7 @@ static inline int ip6_rcv_finish( struct sk_buff *skb)
return dst_input(skb);
}
-int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct ipv6hdr *hdr;
u32 pkt_len;
@@ -166,8 +166,8 @@ resubmit:
nexthdr = skb->nh.raw[nhoff];
raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
- if (raw_sk)
- ipv6_raw_deliver(skb, nexthdr);
+ if (raw_sk && !ipv6_raw_deliver(skb, nexthdr))
+ raw_sk = NULL;
hash = nexthdr & (MAX_INET_PROTOS - 1);
if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ae652ca14bc9..2f589f24c093 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -153,51 +153,6 @@ int ip6_output(struct sk_buff *skb)
return ip6_output2(skb);
}
-#ifdef CONFIG_NETFILTER
-int ip6_route_me_harder(struct sk_buff *skb)
-{
- struct ipv6hdr *iph = skb->nh.ipv6h;
- struct dst_entry *dst;
- struct flowi fl = {
- .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
- .nl_u =
- { .ip6_u =
- { .daddr = iph->daddr,
- .saddr = iph->saddr, } },
- .proto = iph->nexthdr,
- };
-
- dst = ip6_route_output(skb->sk, &fl);
-
- if (dst->error) {
- IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n"));
- dst_release(dst);
- return -EINVAL;
- }
-
- /* Drop old route. */
- dst_release(skb->dst);
-
- skb->dst = dst;
- return 0;
-}
-#endif
-
-static inline int ip6_maybe_reroute(struct sk_buff *skb)
-{
-#ifdef CONFIG_NETFILTER
- if (skb->nfcache & NFC_ALTERED){
- if (ip6_route_me_harder(skb) != 0){
- kfree_skb(skb);
- return -EINVAL;
- }
- }
-#endif /* CONFIG_NETFILTER */
- return dst_output(skb);
-}
-
/*
* xmit an sk_buff (used by TCP)
*/
@@ -211,7 +166,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit;
+ int hlimit, tclass;
u32 mtu;
if (opt) {
@@ -247,7 +202,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
* Fill in the IPv6 header
*/
- *(u32*)hdr = htonl(0x60000000) | fl->fl6_flowlabel;
hlimit = -1;
if (np)
hlimit = np->hop_limit;
@@ -256,6 +210,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
if (hlimit < 0)
hlimit = ipv6_get_hoplimit(dst->dev);
+ tclass = -1;
+ if (np)
+ tclass = np->tclass;
+ if (tclass < 0)
+ tclass = 0;
+
+ *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
+
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
hdr->hop_limit = hlimit;
@@ -266,7 +228,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
mtu = dst_mtu(dst);
if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
+ return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
+ dst_output);
}
if (net_ratelimit())
@@ -321,7 +284,9 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
read_lock(&ip6_ra_lock);
for (ra = ip6_ra_chain; ra; ra = ra->next) {
struct sock *sk = ra->sk;
- if (sk && ra->sel == sel) {
+ if (sk && ra->sel == sel &&
+ (!sk->sk_bound_dev_if ||
+ sk->sk_bound_dev_if == skb->dev->ifindex)) {
if (last) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2)
@@ -667,7 +632,7 @@ slow_path:
*/
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
- NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n"));
+ NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
err = -ENOMEM;
goto fail;
@@ -804,10 +769,11 @@ out_err_release:
return err;
}
-int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
- void *from, int length, int transhdrlen,
- int hlimit, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt,
- unsigned int flags)
+int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ int offset, int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
+ struct rt6_info *rt, unsigned int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -845,6 +811,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
if (dst_allfrag(rt->u.dst.path))
inet->cork.flags |= IPCORK_ALLFRAG;
@@ -1126,7 +1093,8 @@ int ip6_push_pending_frames(struct sock *sk)
skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr));
- *(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
+ *(u32*)hdr = fl->fl6_flowlabel |
+ htonl(0x60000000 | ((int)np->cork.tclass << 20));
if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 09613729404c..cf94372d1af3 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -673,11 +673,12 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
if ((dst = ip6_tnl_dst_check(t)) != NULL)
dst_hold(dst);
- else
+ else {
dst = ip6_route_output(NULL, &fl);
- if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0) < 0)
- goto tx_err_link_failure;
+ if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0) < 0)
+ goto tx_err_link_failure;
+ }
tdev = dst->dev;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 135383ef538f..85bfbc69b2c3 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -341,8 +341,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
for_each_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
- if (tfm)
- crypto_free_tfm(tfm);
+ crypto_free_tfm(tfm);
}
free_percpu(tfms);
}
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 3bc144a79fa5..8567873d0dd8 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -55,7 +55,7 @@
#include <asm/uaccess.h>
-DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
+DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
static struct packet_type ipv6_packet_type = {
.type = __constant_htons(ETH_P_IPV6),
@@ -109,13 +109,6 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
return 0;
}
-extern int ip6_mc_source(int add, int omode, struct sock *sk,
- struct group_source_req *pgsr);
-extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
-extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
- struct group_filter __user *optval, int __user *optlen);
-
-
int ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
@@ -163,6 +156,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
fl6_free_socklist(sk);
ipv6_sock_mc_close(sk);
+ /*
+ * Sock is moving from IPv6 to IPv4 (sk_prot), so
+ * remove it from the refcnt debug socks count in the
+ * original family...
+ */
+ sk_refcnt_debug_dec(sk);
+
if (sk->sk_protocol == IPPROTO_TCP) {
struct tcp_sock *tp = tcp_sk(sk);
@@ -192,9 +192,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
kfree_skb(pktopt);
sk->sk_destruct = inet_sock_destruct;
-#ifdef INET_REFCNT_DEBUG
- atomic_dec(&inet6_sock_nr);
-#endif
+ /*
+ * ... and add it to the refcnt debug socks count
+ * in the new family. -acme
+ */
+ sk_refcnt_debug_inc(sk);
module_put(THIS_MODULE);
retv = 0;
break;
@@ -208,39 +210,139 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
+
+ case IPV6_2292PKTINFO:
+ np->rxopt.bits.rxoinfo = valbool;
+ retv = 0;
+ break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_2292HOPLIMIT:
+ np->rxopt.bits.rxohlim = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_2292RTHDR:
+ if (val < 0 || val > 2)
+ goto e_inval;
+ np->rxopt.bits.osrcrt = val;
+ retv = 0;
+ break;
+
+ case IPV6_RECVHOPOPTS:
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_2292HOPOPTS:
+ np->rxopt.bits.ohopopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVDSTOPTS:
np->rxopt.bits.dstopts = valbool;
retv = 0;
break;
+ case IPV6_2292DSTOPTS:
+ np->rxopt.bits.odstopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_TCLASS:
+ if (val < 0 || val > 0xff)
+ goto e_inval;
+ np->tclass = val;
+ retv = 0;
+ break;
+
+ case IPV6_RECVTCLASS:
+ np->rxopt.bits.rxtclass = valbool;
+ retv = 0;
+ break;
+
case IPV6_FLOWINFO:
np->rxopt.bits.rxflow = valbool;
retv = 0;
break;
- case IPV6_PKTOPTIONS:
+ case IPV6_HOPOPTS:
+ case IPV6_RTHDRDSTOPTS:
+ case IPV6_RTHDR:
+ case IPV6_DSTOPTS:
+ {
+ struct ipv6_txoptions *opt;
+ if (optlen == 0)
+ optval = 0;
+
+ /* hop-by-hop / destination options are privileged option */
+ retv = -EPERM;
+ if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
+ break;
+
+ retv = -EINVAL;
+ if (optlen & 0x7 || optlen > 8 * 255)
+ break;
+
+ opt = ipv6_renew_options(sk, np->opt, optname,
+ (struct ipv6_opt_hdr __user *)optval,
+ optlen);
+ if (IS_ERR(opt)) {
+ retv = PTR_ERR(opt);
+ break;
+ }
+
+ /* routing header option needs extra check */
+ if (optname == IPV6_RTHDR && opt->srcrt) {
+ struct ipv6_rt_hdr *rthdr = opt->srcrt;
+ if (rthdr->type)
+ goto sticky_done;
+ if ((rthdr->hdrlen & 1) ||
+ (rthdr->hdrlen >> 1) != rthdr->segments_left)
+ goto sticky_done;
+ }
+
+ retv = 0;
+ if (sk->sk_type == SOCK_STREAM) {
+ if (opt) {
+ struct tcp_sock *tp = tcp_sk(sk);
+ if (!((1 << sk->sk_state) &
+ (TCPF_LISTEN | TCPF_CLOSE))
+ && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
+ tp->ext_header_len = opt->opt_flen + opt->opt_nflen;
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+ }
+ }
+ opt = xchg(&np->opt, opt);
+ sk_dst_reset(sk);
+ } else {
+ write_lock(&sk->sk_dst_lock);
+ opt = xchg(&np->opt, opt);
+ write_unlock(&sk->sk_dst_lock);
+ sk_dst_reset(sk);
+ }
+sticky_done:
+ if (opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+ break;
+ }
+
+ case IPV6_2292PKTOPTIONS:
{
struct ipv6_txoptions *opt = NULL;
struct msghdr msg;
@@ -274,7 +376,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
msg.msg_controllen = optlen;
msg.msg_control = (void*)(opt+1);
- retv = datagram_send_ctl(&msg, &fl, opt, &junk);
+ retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk);
if (retv)
goto done;
update:
@@ -437,7 +539,6 @@ done:
}
case MCAST_MSFILTER:
{
- extern int sysctl_optmem_max;
extern int sysctl_mld_max_msf;
struct group_filter *gsf;
@@ -528,6 +629,17 @@ e_inval:
return -EINVAL;
}
+int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
+ char __user *optval, int len)
+{
+ if (!hdr)
+ return 0;
+ len = min_t(int, len, ipv6_optlen(hdr));
+ if (copy_to_user(optval, hdr, ipv6_optlen(hdr)))
+ return -EFAULT;
+ return len;
+}
+
int ipv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -566,7 +678,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
return err;
}
- case IPV6_PKTOPTIONS:
+ case IPV6_2292PKTOPTIONS:
{
struct msghdr msg;
struct sk_buff *skb;
@@ -600,6 +712,16 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
int hlim = np->mcast_hops;
put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
}
+ if (np->rxopt.bits.rxoinfo) {
+ struct in6_pktinfo src_info;
+ src_info.ipi6_ifindex = np->mcast_oif;
+ ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr);
+ put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
+ }
+ if (np->rxopt.bits.rxohlim) {
+ int hlim = np->mcast_hops;
+ put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
+ }
}
len -= msg.msg_controllen;
return put_user(len, optlen);
@@ -624,26 +746,67 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
val = np->rxopt.bits.rxinfo;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_2292PKTINFO:
+ val = np->rxopt.bits.rxoinfo;
+ break;
+
+ case IPV6_RECVHOPLIMIT:
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_2292HOPLIMIT:
+ val = np->rxopt.bits.rxohlim;
+ break;
+
+ case IPV6_RECVRTHDR:
val = np->rxopt.bits.srcrt;
break;
+ case IPV6_2292RTHDR:
+ val = np->rxopt.bits.osrcrt;
+ break;
+
case IPV6_HOPOPTS:
+ case IPV6_RTHDRDSTOPTS:
+ case IPV6_RTHDR:
+ case IPV6_DSTOPTS:
+ {
+
+ lock_sock(sk);
+ len = ipv6_getsockopt_sticky(sk, np->opt->hopopt,
+ optval, len);
+ release_sock(sk);
+ return put_user(len, optlen);
+ }
+
+ case IPV6_RECVHOPOPTS:
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_2292HOPOPTS:
+ val = np->rxopt.bits.ohopopts;
+ break;
+
+ case IPV6_RECVDSTOPTS:
val = np->rxopt.bits.dstopts;
break;
+ case IPV6_2292DSTOPTS:
+ val = np->rxopt.bits.odstopts;
+ break;
+
+ case IPV6_TCLASS:
+ val = np->tclass;
+ break;
+
+ case IPV6_RECVTCLASS:
+ val = np->rxopt.bits.rxtclass;
+ break;
+
case IPV6_FLOWINFO:
val = np->rxopt.bits.rxflow;
break;
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 5ade5a5d1990..37a4a99c9fe9 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -15,9 +15,6 @@ EXPORT_SYMBOL(ndisc_mc_map);
EXPORT_SYMBOL(register_inet6addr_notifier);
EXPORT_SYMBOL(unregister_inet6addr_notifier);
EXPORT_SYMBOL(ip6_route_output);
-#ifdef CONFIG_NETFILTER
-EXPORT_SYMBOL(ip6_route_me_harder);
-#endif
EXPORT_SYMBOL(addrconf_lock);
EXPORT_SYMBOL(ipv6_setsockopt);
EXPORT_SYMBOL(ipv6_getsockopt);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7ae72d4c9bd2..555a31347eda 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -447,10 +447,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
return;
err = xfrm_lookup(&dst, &fl, NULL, 0);
- if (err < 0) {
- dst_release(dst);
+ if (err < 0)
return;
- }
if (inc_opt) {
if (dev->addr_len)
@@ -539,10 +537,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
return;
err = xfrm_lookup(&dst, &fl, NULL, 0);
- if (err < 0) {
- dst_release(dst);
+ if (err < 0)
return;
- }
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
@@ -616,10 +612,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
return;
err = xfrm_lookup(&dst, &fl, NULL, 0);
- if (err < 0) {
- dst_release(dst);
+ if (err < 0)
return;
- }
len = sizeof(struct icmp6hdr);
if (dev->addr_len)
@@ -812,7 +806,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
if (ipv6_chk_acast_addr(dev, &msg->target) ||
(idev->cnf.forwarding &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
- if (skb->stamp.tv_sec != LOCALLY_ENQUEUED &&
+ if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
skb->pkt_type != PACKET_HOST &&
inc != 0 &&
idev->nd_parms->proxy_delay != 0) {
@@ -1353,10 +1347,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
return;
err = xfrm_lookup(&dst, &fl, NULL, 0);
- if (err) {
- dst_release(dst);
+ if (err)
return;
- }
rt = (struct rt6_info *) dst;
@@ -1487,6 +1479,8 @@ int ndisc_rcv(struct sk_buff *skb)
return 0;
}
+ memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
+
switch (msg->icmph.icmp6_type) {
case NDISC_NEIGHBOUR_SOLICITATION:
ndisc_recv_ns(skb);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
new file mode 100644
index 000000000000..f8626ebf90fd
--- /dev/null
+++ b/net/ipv6/netfilter.c
@@ -0,0 +1,104 @@
+#include <linux/config.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_NETFILTER
+
+#include <linux/kernel.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+
+int ip6_route_me_harder(struct sk_buff *skb)
+{
+ struct ipv6hdr *iph = skb->nh.ipv6h;
+ struct dst_entry *dst;
+ struct flowi fl = {
+ .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+ .nl_u =
+ { .ip6_u =
+ { .daddr = iph->daddr,
+ .saddr = iph->saddr, } },
+ .proto = iph->nexthdr,
+ };
+
+ dst = ip6_route_output(skb->sk, &fl);
+
+ if (dst->error) {
+ IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
+ LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
+ dst_release(dst);
+ return -EINVAL;
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+
+ skb->dst = dst;
+ return 0;
+}
+EXPORT_SYMBOL(ip6_route_me_harder);
+
+/*
+ * Extra routing may needed on local out, as the QUEUE target never
+ * returns control to the table.
+ */
+
+struct ip6_rt_info {
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+};
+
+static void save(const struct sk_buff *skb, struct nf_info *info)
+{
+ struct ip6_rt_info *rt_info = nf_info_reroute(info);
+
+ if (info->hook == NF_IP6_LOCAL_OUT) {
+ struct ipv6hdr *iph = skb->nh.ipv6h;
+
+ rt_info->daddr = iph->daddr;
+ rt_info->saddr = iph->saddr;
+ }
+}
+
+static int reroute(struct sk_buff **pskb, const struct nf_info *info)
+{
+ struct ip6_rt_info *rt_info = nf_info_reroute(info);
+
+ if (info->hook == NF_IP6_LOCAL_OUT) {
+ struct ipv6hdr *iph = (*pskb)->nh.ipv6h;
+ if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
+ !ipv6_addr_equal(&iph->saddr, &rt_info->saddr))
+ return ip6_route_me_harder(*pskb);
+ }
+ return 0;
+}
+
+static struct nf_queue_rerouter ip6_reroute = {
+ .rer_size = sizeof(struct ip6_rt_info),
+ .save = &save,
+ .reroute = &reroute,
+};
+
+int __init ipv6_netfilter_init(void)
+{
+ return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
+}
+
+void ipv6_netfilter_fini(void)
+{
+ nf_unregister_queue_rerouter(PF_INET6);
+}
+
+#else /* CONFIG_NETFILTER */
+int __init ipv6_netfilter_init(void)
+{
+ return 0;
+}
+
+void ipv6_netfilter_fini(void)
+{
+}
+#endif /* CONFIG_NETFILTER */
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 77ec704c9ee3..216fbe1ac65c 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -10,13 +10,16 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
# dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
#fi
config IP6_NF_QUEUE
- tristate "Userspace queueing via NETLINK"
+ tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)"
---help---
This option adds a queue handler to the kernel for IPv6
- packets which lets us to receive the filtered packets
- with QUEUE target using libiptc as we can do with
- the IPv4 now.
+ packets which enables users to receive the filtered packets
+ with QUEUE target using libipq.
+
+ THis option enables the old IPv6-only "ip6_queue" implementation
+ which has been obsoleted by the new "nfnetlink_queue" code (see
+ CONFIG_NETFILTER_NETLINK_QUEUE).
(C) Fernando Anton 2001
IPv64 Project - Work based in IPv64 draft by Arturo Azcorra.
@@ -196,6 +199,16 @@ config IP6_NF_TARGET_LOG
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_TARGET_REJECT
+ tristate "REJECT target support"
+ depends on IP6_NF_FILTER
+ help
+ The REJECT target allows a filtering rule to specify that an ICMPv6
+ error should be issued in response to an incoming packet, rather
+ than silently being dropped.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
# if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
# dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
# if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -226,6 +239,22 @@ config IP6_NF_TARGET_MARK
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_TARGET_HL
+ tristate 'HL (hoplimit) target support'
+ depends on IP6_NF_MANGLE
+ help
+ This option adds a `HL' target, which enables the user to decrement
+ the hoplimit value of the IPv6 header or set it to a given (lower)
+ value.
+
+ While it is safe to decrement the hoplimit value, this option also
+ enables functionality to increment and set the hoplimit value of the
+ IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since
+ you can easily create immortal packets that loop forever on the
+ network.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
#dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
config IP6_NF_RAW
tristate 'raw table support (required for TRACE)'
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 2e51714953b6..bd9a16a5cbba 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -20,7 +20,10 @@ obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
+obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
+obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ip6t_NFQUEUE.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index a16df5b27c84..aa11cf366efa 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -47,16 +47,10 @@
#define NET_IPQ_QMAX 2088
#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
-struct ipq_rt_info {
- struct in6_addr daddr;
- struct in6_addr saddr;
-};
-
struct ipq_queue_entry {
struct list_head list;
struct nf_info *info;
struct sk_buff *skb;
- struct ipq_rt_info rt_info;
};
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
@@ -244,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
pmsg->packet_id = (unsigned long )entry;
pmsg->data_len = data_len;
- pmsg->timestamp_sec = entry->skb->stamp.tv_sec;
- pmsg->timestamp_usec = entry->skb->stamp.tv_usec;
+ pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec;
+ pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec;
pmsg->mark = entry->skb->nfmark;
pmsg->hook = entry->info->hook;
pmsg->hw_protocol = entry->skb->protocol;
@@ -284,7 +278,8 @@ nlmsg_failure:
}
static int
-ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
+ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
+ unsigned int queuenum, void *data)
{
int status = -EINVAL;
struct sk_buff *nskb;
@@ -302,13 +297,6 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
entry->info = info;
entry->skb = skb;
- if (entry->info->hook == NF_IP_LOCAL_OUT) {
- struct ipv6hdr *iph = skb->nh.ipv6h;
-
- entry->rt_info.daddr = iph->daddr;
- entry->rt_info.saddr = iph->saddr;
- }
-
nskb = ipq_build_packet_message(entry, &status);
if (nskb == NULL)
goto err_out_free;
@@ -384,23 +372,11 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
}
skb_put(e->skb, diff);
}
- if (!skb_ip_make_writable(&e->skb, v->data_len))
+ if (!skb_make_writable(&e->skb, v->data_len))
return -ENOMEM;
memcpy(e->skb->data, v->payload, v->data_len);
e->skb->ip_summed = CHECKSUM_NONE;
- e->skb->nfcache |= NFC_ALTERED;
-
- /*
- * Extra routing may needed on local out, as the QUEUE target never
- * returns control to the table.
- * Not a nice way to cmp, but works
- */
- if (e->info->hook == NF_IP_LOCAL_OUT) {
- struct ipv6hdr *iph = e->skb->nh.ipv6h;
- if (!ipv6_addr_equal(&iph->daddr, &e->rt_info.daddr) ||
- !ipv6_addr_equal(&iph->saddr, &e->rt_info.saddr))
- return ip6_route_me_harder(e->skb);
- }
+
return 0;
}
@@ -676,6 +652,11 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
return len;
}
+static struct nf_queue_handler nfqh = {
+ .name = "ip6_queue",
+ .outfn = &ipq_enqueue_packet,
+};
+
static int
init_or_cleanup(int init)
{
@@ -686,7 +667,8 @@ init_or_cleanup(int init)
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
- ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk);
+ ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
+ THIS_MODULE);
if (ipqnl == NULL) {
printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
goto cleanup_netlink_notifier;
@@ -703,7 +685,7 @@ init_or_cleanup(int init)
register_netdevice_notifier(&ipq_dev_notifier);
ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
- status = nf_register_queue_handler(PF_INET6, ipq_enqueue_packet, NULL);
+ status = nf_register_queue_handler(PF_INET6, &nfqh);
if (status < 0) {
printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
goto cleanup_sysctl;
@@ -711,7 +693,7 @@ init_or_cleanup(int init)
return status;
cleanup:
- nf_unregister_queue_handler(PF_INET6);
+ nf_unregister_queue_handlers(&nfqh);
synchronize_net();
ipq_flush(NF_DROP);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 73034511c8db..1cb8adb2787f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -401,7 +401,6 @@ ip6t_do_table(struct sk_buff **pskb,
do {
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
- (*pskb)->nfcache |= e->nfcache;
if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
&protoff, &offset)) {
struct ip6t_entry_target *t;
@@ -434,8 +433,8 @@ ip6t_do_table(struct sk_buff **pskb,
back->comefrom);
continue;
}
- if (table_base + v
- != (void *)e + e->next_offset) {
+ if (table_base + v != (void *)e + e->next_offset
+ && !(e->ipv6.flags & IP6T_F_GOTO)) {
/* Save old back ptr in next entry */
struct ip6t_entry *next
= (void *)e + e->next_offset;
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
new file mode 100644
index 000000000000..8f5549b72720
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -0,0 +1,118 @@
+/*
+ * Hop Limit modification target for ip6tables
+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
+ * Based on HW's TTL module
+ *
+ * This software is distributed under the terms of GNU GPL
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_HL.h>
+
+MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
+MODULE_DESCRIPTION("IP tables Hop Limit modification module");
+MODULE_LICENSE("GPL");
+
+static unsigned int ip6t_hl_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo, void *userinfo)
+{
+ struct ipv6hdr *ip6h;
+ const struct ip6t_HL_info *info = targinfo;
+ u_int16_t diffs[2];
+ int new_hl;
+
+ if (!skb_make_writable(pskb, (*pskb)->len))
+ return NF_DROP;
+
+ ip6h = (*pskb)->nh.ipv6h;
+
+ switch (info->mode) {
+ case IP6T_HL_SET:
+ new_hl = info->hop_limit;
+ break;
+ case IP6T_HL_INC:
+ new_hl = ip6h->hop_limit + info->hop_limit;
+ if (new_hl > 255)
+ new_hl = 255;
+ break;
+ case IP6T_HL_DEC:
+ new_hl = ip6h->hop_limit - info->hop_limit;
+ if (new_hl < 0)
+ new_hl = 0;
+ break;
+ default:
+ new_hl = ip6h->hop_limit;
+ break;
+ }
+
+ if (new_hl != ip6h->hop_limit) {
+ diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
+ ip6h->hop_limit = new_hl;
+ diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
+ }
+
+ return IP6T_CONTINUE;
+}
+
+static int ip6t_hl_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ip6t_HL_info *info = targinfo;
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
+ printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
+ return 0;
+ }
+
+ if (strcmp(tablename, "mangle")) {
+ printk(KERN_WARNING "ip6t_HL: can only be called from "
+ "\"mangle\" table, not \"%s\"\n", tablename);
+ return 0;
+ }
+
+ if (info->mode > IP6T_HL_MAXMODE) {
+ printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
+ info->mode);
+ return 0;
+ }
+
+ if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
+ printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
+ "make sense with value 0\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ip6t_target ip6t_HL = {
+ .name = "HL",
+ .target = ip6t_hl_target,
+ .checkentry = ip6t_hl_checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ip6t_register_target(&ip6t_HL);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_HL);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index a692e26a4fa3..0cd1d1bd9033 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -26,10 +26,6 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
MODULE_DESCRIPTION("IP6 tables LOG target module");
MODULE_LICENSE("GPL");
-static unsigned int nflog = 1;
-module_param(nflog, int, 0400);
-MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
-
struct in_device;
#include <net/route.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h>
@@ -44,7 +40,7 @@ struct in_device;
static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */
-static void dump_packet(const struct ip6t_log_info *info,
+static void dump_packet(const struct nf_loginfo *info,
const struct sk_buff *skb, unsigned int ip6hoff,
int recurse)
{
@@ -53,6 +49,12 @@ static void dump_packet(const struct ip6t_log_info *info,
struct ipv6hdr _ip6h, *ih;
unsigned int ptr;
unsigned int hdrlen = 0;
+ unsigned int logflags;
+
+ if (info->type == NF_LOG_TYPE_LOG)
+ logflags = info->u.log.logflags;
+ else
+ logflags = NF_LOG_MASK;
ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
if (ih == NULL) {
@@ -84,7 +86,7 @@ static void dump_packet(const struct ip6t_log_info *info,
}
/* Max length: 48 "OPT (...) " */
- if (info->logflags & IP6T_LOG_IPOPT)
+ if (logflags & IP6T_LOG_IPOPT)
printk("OPT ( ");
switch (currenthdr) {
@@ -119,7 +121,7 @@ static void dump_packet(const struct ip6t_log_info *info,
case IPPROTO_ROUTING:
case IPPROTO_HOPOPTS:
if (fragment) {
- if (info->logflags & IP6T_LOG_IPOPT)
+ if (logflags & IP6T_LOG_IPOPT)
printk(")");
return;
}
@@ -127,7 +129,7 @@ static void dump_packet(const struct ip6t_log_info *info,
break;
/* Max Length */
case IPPROTO_AH:
- if (info->logflags & IP6T_LOG_IPOPT) {
+ if (logflags & IP6T_LOG_IPOPT) {
struct ip_auth_hdr _ahdr, *ah;
/* Max length: 3 "AH " */
@@ -158,7 +160,7 @@ static void dump_packet(const struct ip6t_log_info *info,
hdrlen = (hp->hdrlen+2)<<2;
break;
case IPPROTO_ESP:
- if (info->logflags & IP6T_LOG_IPOPT) {
+ if (logflags & IP6T_LOG_IPOPT) {
struct ip_esp_hdr _esph, *eh;
/* Max length: 4 "ESP " */
@@ -190,7 +192,7 @@ static void dump_packet(const struct ip6t_log_info *info,
printk("Unknown Ext Hdr %u", currenthdr);
return;
}
- if (info->logflags & IP6T_LOG_IPOPT)
+ if (logflags & IP6T_LOG_IPOPT)
printk(") ");
currenthdr = hp->nexthdr;
@@ -218,7 +220,7 @@ static void dump_packet(const struct ip6t_log_info *info,
printk("SPT=%u DPT=%u ",
ntohs(th->source), ntohs(th->dest));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
- if (info->logflags & IP6T_LOG_TCPSEQ)
+ if (logflags & IP6T_LOG_TCPSEQ)
printk("SEQ=%u ACK=%u ",
ntohl(th->seq), ntohl(th->ack_seq));
/* Max length: 13 "WINDOW=65535 " */
@@ -245,7 +247,7 @@ static void dump_packet(const struct ip6t_log_info *info,
/* Max length: 11 "URGP=65535 " */
printk("URGP=%u ", ntohs(th->urg_ptr));
- if ((info->logflags & IP6T_LOG_TCPOPT)
+ if ((logflags & IP6T_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) {
u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
unsigned int i;
@@ -349,7 +351,7 @@ static void dump_packet(const struct ip6t_log_info *info,
}
/* Max length: 15 "UID=4294967295 " */
- if ((info->logflags & IP6T_LOG_UID) && recurse && skb->sk) {
+ if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file)
printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
@@ -357,19 +359,31 @@ static void dump_packet(const struct ip6t_log_info *info,
}
}
+static struct nf_loginfo default_loginfo = {
+ .type = NF_LOG_TYPE_LOG,
+ .u = {
+ .log = {
+ .level = 0,
+ .logflags = NF_LOG_MASK,
+ },
+ },
+};
+
static void
-ip6t_log_packet(unsigned int hooknum,
+ip6t_log_packet(unsigned int pf,
+ unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
- const struct ip6t_log_info *loginfo,
- const char *level_string,
+ const struct nf_loginfo *loginfo,
const char *prefix)
{
+ if (!loginfo)
+ loginfo = &default_loginfo;
+
spin_lock_bh(&log_lock);
- printk(level_string);
- printk("%sIN=%s OUT=%s ",
- prefix == NULL ? loginfo->prefix : prefix,
+ printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+ prefix,
in ? in->name : "",
out ? out->name : "");
if (in && !out) {
@@ -416,29 +430,17 @@ ip6t_log_target(struct sk_buff **pskb,
void *userinfo)
{
const struct ip6t_log_info *loginfo = targinfo;
- char level_string[4] = "< >";
+ struct nf_loginfo li;
+
+ li.type = NF_LOG_TYPE_LOG;
+ li.u.log.level = loginfo->level;
+ li.u.log.logflags = loginfo->logflags;
- level_string[1] = '0' + (loginfo->level % 8);
- ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+ nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix);
return IP6T_CONTINUE;
}
-static void
-ip6t_logfn(unsigned int hooknum,
- const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const char *prefix)
-{
- struct ip6t_log_info loginfo = {
- .level = 0,
- .logflags = IP6T_LOG_MASK,
- .prefix = ""
- };
-
- ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
-}
static int ip6t_log_checkentry(const char *tablename,
const struct ip6t_entry *e,
@@ -475,20 +477,29 @@ static struct ip6t_target ip6t_log_reg = {
.me = THIS_MODULE,
};
+static struct nf_logger ip6t_logger = {
+ .name = "ip6t_LOG",
+ .logfn = &ip6t_log_packet,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
if (ip6t_register_target(&ip6t_log_reg))
return -EINVAL;
- if (nflog)
- nf_log_register(PF_INET6, &ip6t_logfn);
+ if (nf_log_register(PF_INET6, &ip6t_logger) < 0) {
+ printk(KERN_WARNING "ip6t_LOG: not logging via system console "
+ "since somebody else already registered for PF_INET6\n");
+ /* we cannot make module load fail here, since otherwise
+ * ip6tables userspace would abort */
+ }
return 0;
}
static void __exit fini(void)
{
- if (nflog)
- nf_log_unregister(PF_INET6, &ip6t_logfn);
+ nf_log_unregister_logger(&ip6t_logger);
ip6t_unregister_target(&ip6t_log_reg);
}
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
index d09ceb05013a..81924fcc5857 100644
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ b/net/ipv6/netfilter/ip6t_MARK.c
@@ -28,10 +28,9 @@ target(struct sk_buff **pskb,
{
const struct ip6t_mark_target_info *markinfo = targinfo;
- if((*pskb)->nfmark != markinfo->mark) {
+ if((*pskb)->nfmark != markinfo->mark)
(*pskb)->nfmark = markinfo->mark;
- (*pskb)->nfcache |= NFC_ALTERED;
- }
+
return IP6T_CONTINUE;
}
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c
new file mode 100644
index 000000000000..c6e3730e7409
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_NFQUEUE.c
@@ -0,0 +1,70 @@
+/* ip6tables module for using new netfilter netlink queue
+ *
+ * (C) 2005 by Harald Welte <laforge@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/skbuff.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("ip6tables NFQUEUE target");
+MODULE_LICENSE("GPL");
+
+static unsigned int
+target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_NFQ_info *tinfo = targinfo;
+
+ return NF_QUEUE_NR(tinfo->queuenum);
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) {
+ printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ipt_NFQ_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ip6t_target ipt_NFQ_reg = {
+ .name = "NFQUEUE",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ip6t_register_target(&ipt_NFQ_reg);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ipt_NFQ_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
new file mode 100644
index 000000000000..b03e87adca93
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -0,0 +1,281 @@
+/*
+ * IP6 tables REJECT target module
+ * Linux INET6 implementation
+ *
+ * Copyright (C)2003 USAGI/WIDE Project
+ *
+ * Authors:
+ * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
+ *
+ * Based on net/ipv4/netfilter/ipt_REJECT.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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/icmpv6.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+#include <net/icmp.h>
+#include <net/ip6_checksum.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+#include <net/flow.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_REJECT.h>
+
+MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
+MODULE_DESCRIPTION("IP6 tables REJECT target module");
+MODULE_LICENSE("GPL");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Send RST reply */
+static void send_reset(struct sk_buff *oldskb)
+{
+ struct sk_buff *nskb;
+ struct tcphdr otcph, *tcph;
+ unsigned int otcplen, hh_len;
+ int tcphoff, needs_ack;
+ struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
+ struct dst_entry *dst = NULL;
+ u8 proto;
+ struct flowi fl;
+
+ if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
+ (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
+ DEBUGP("ip6t_REJECT: addr is not unicast.\n");
+ return;
+ }
+
+ proto = oip6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto);
+
+ if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
+ DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
+ return;
+ }
+
+ otcplen = oldskb->len - tcphoff;
+
+ /* IP header checks: fragment, too short. */
+ if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
+ DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
+ proto, otcplen);
+ return;
+ }
+
+ if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
+ BUG();
+
+ /* No RST for RST. */
+ if (otcph.rst) {
+ DEBUGP("ip6t_REJECT: RST is set\n");
+ return;
+ }
+
+ /* Check checksum. */
+ if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
+ skb_checksum(oldskb, tcphoff, otcplen, 0))) {
+ DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
+ return;
+ }
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = IPPROTO_TCP;
+ ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
+ ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
+ fl.fl_ip_sport = otcph.dest;
+ fl.fl_ip_dport = otcph.source;
+ dst = ip6_route_output(NULL, &fl);
+ if (dst == NULL)
+ return;
+ if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0))
+ return;
+
+ hh_len = (dst->dev->hard_header_len + 15)&~15;
+ nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
+ + sizeof(struct tcphdr) + dst->trailer_len,
+ GFP_ATOMIC);
+
+ if (!nskb) {
+ if (net_ratelimit())
+ printk("ip6t_REJECT: Can't alloc skb\n");
+ dst_release(dst);
+ return;
+ }
+
+ nskb->dst = dst;
+
+ skb_reserve(nskb, hh_len + dst->header_len);
+
+ ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
+ skb_put(nskb, sizeof(struct ipv6hdr));
+ ip6h->version = 6;
+ ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
+ ip6h->nexthdr = IPPROTO_TCP;
+ ip6h->payload_len = htons(sizeof(struct tcphdr));
+ ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
+ ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
+
+ tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
+ /* Truncate to length (no data) */
+ tcph->doff = sizeof(struct tcphdr)/4;
+ tcph->source = otcph.dest;
+ tcph->dest = otcph.source;
+
+ if (otcph.ack) {
+ needs_ack = 0;
+ tcph->seq = otcph.ack_seq;
+ tcph->ack_seq = 0;
+ } else {
+ needs_ack = 1;
+ tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
+ + otcplen - (otcph.doff<<2));
+ tcph->seq = 0;
+ }
+
+ /* Reset flags */
+ ((u_int8_t *)tcph)[13] = 0;
+ tcph->rst = 1;
+ tcph->ack = needs_ack;
+ tcph->window = 0;
+ tcph->urg_ptr = 0;
+ tcph->check = 0;
+
+ /* Adjust TCP checksum */
+ tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
+ &nskb->nh.ipv6h->daddr,
+ sizeof(struct tcphdr), IPPROTO_TCP,
+ csum_partial((char *)tcph,
+ sizeof(struct tcphdr), 0));
+
+ NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
+ dst_output);
+}
+
+static inline void
+send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum)
+{
+ if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL)
+ skb_in->dev = &loopback_dev;
+
+ icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
+}
+
+static unsigned int reject6_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ip6t_reject_info *reject = targinfo;
+
+ DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
+ /* WARNING: This code causes reentry within ip6tables.
+ This means that the ip6tables jump stack is now crap. We
+ must return an absolute verdict. --RR */
+ switch (reject->with) {
+ case IP6T_ICMP6_NO_ROUTE:
+ send_unreach(*pskb, ICMPV6_NOROUTE, hooknum);
+ break;
+ case IP6T_ICMP6_ADM_PROHIBITED:
+ send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum);
+ break;
+ case IP6T_ICMP6_NOT_NEIGHBOUR:
+ send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum);
+ break;
+ case IP6T_ICMP6_ADDR_UNREACH:
+ send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum);
+ break;
+ case IP6T_ICMP6_PORT_UNREACH:
+ send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum);
+ break;
+ case IP6T_ICMP6_ECHOREPLY:
+ /* Do nothing */
+ break;
+ case IP6T_TCP_RESET:
+ send_reset(*pskb);
+ break;
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
+ break;
+ }
+
+ return NF_DROP;
+}
+
+static int check(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_reject_info *rejinfo = targinfo;
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
+ DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
+ return 0;
+ }
+
+ /* Only allow these for packet filtering. */
+ if (strcmp(tablename, "filter") != 0) {
+ DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
+ return 0;
+ }
+
+ if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
+ | (1 << NF_IP6_FORWARD)
+ | (1 << NF_IP6_LOCAL_OUT))) != 0) {
+ DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
+ return 0;
+ }
+
+ if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
+ printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
+ return 0;
+ } else if (rejinfo->with == IP6T_TCP_RESET) {
+ /* Must specify that it's a TCP packet */
+ if (e->ipv6.proto != IPPROTO_TCP
+ || (e->ipv6.invflags & IP6T_INV_PROTO)) {
+ DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static struct ip6t_target ip6t_reject_reg = {
+ .name = "REJECT",
+ .target = reject6_target,
+ .checkentry = check,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ if (ip6t_register_target(&ip6t_reject_reg))
+ return -EINVAL;
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_reject_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index ab0e32d3de46..4de4cdad4b7d 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/file.h>
+#include <linux/rcupdate.h>
#include <net/sock.h>
#include <linux/netfilter_ipv6/ip6t_owner.h>
@@ -20,71 +21,6 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("IP6 tables owner matching module");
MODULE_LICENSE("GPL");
-static int
-match_pid(const struct sk_buff *skb, pid_t pid)
-{
- struct task_struct *p;
- struct files_struct *files;
- int i;
-
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (!p)
- goto out;
- task_lock(p);
- files = p->files;
- if(files) {
- spin_lock(&files->file_lock);
- for (i=0; i < files->max_fds; i++) {
- if (fcheck_files(files, i) == skb->sk->sk_socket->file) {
- spin_unlock(&files->file_lock);
- task_unlock(p);
- read_unlock(&tasklist_lock);
- return 1;
- }
- }
- spin_unlock(&files->file_lock);
- }
- task_unlock(p);
-out:
- read_unlock(&tasklist_lock);
- return 0;
-}
-
-static int
-match_sid(const struct sk_buff *skb, pid_t sid)
-{
- struct task_struct *g, *p;
- struct file *file = skb->sk->sk_socket->file;
- int i, found=0;
-
- read_lock(&tasklist_lock);
- do_each_thread(g, p) {
- struct files_struct *files;
- if (p->signal->session != sid)
- continue;
-
- task_lock(p);
- files = p->files;
- if (files) {
- spin_lock(&files->file_lock);
- for (i=0; i < files->max_fds; i++) {
- if (fcheck_files(files, i) == file) {
- found = 1;
- break;
- }
- }
- spin_unlock(&files->file_lock);
- }
- task_unlock(p);
- if (found)
- goto out;
- } while_each_thread(g, p);
-out:
- read_unlock(&tasklist_lock);
-
- return found;
-}
static int
match(const struct sk_buff *skb,
@@ -112,18 +48,6 @@ match(const struct sk_buff *skb,
return 0;
}
- if(info->match & IP6T_OWNER_PID) {
- if (!match_pid(skb, info->pid) ^
- !!(info->invert & IP6T_OWNER_PID))
- return 0;
- }
-
- if(info->match & IP6T_OWNER_SID) {
- if (!match_sid(skb, info->sid) ^
- !!(info->invert & IP6T_OWNER_SID))
- return 0;
- }
-
return 1;
}
@@ -134,6 +58,8 @@ checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ip6t_owner_info *info = matchinfo;
+
if (hook_mask
& ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
@@ -142,14 +68,13 @@ checkentry(const char *tablename,
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
return 0;
-#ifdef CONFIG_SMP
- /* files->file_lock can not be used in a BH */
- if (((struct ip6t_owner_info *)matchinfo)->match
- & (IP6T_OWNER_PID|IP6T_OWNER_SID)) {
- printk("ip6t_owner: pid and sid matching is broken on SMP.\n");
+
+ if (info->match & (IP6T_OWNER_PID|IP6T_OWNER_SID)) {
+ printk("ipt_owner: pid and sid matching "
+ "not supported anymore\n");
return 0;
}
-#endif
+
return 1;
}
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index a9526b773d28..2bb670037df3 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -161,8 +161,8 @@ match(const struct sk_buff *skb,
((rtinfo->hdrlen == hdrlen) ^
!!(rtinfo->invflags & IP6T_RT_INV_LEN))));
DEBUGP("res %02X %02X %02X ",
- (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->bitmap,
- !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->bitmap)));
+ (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->reserved,
+ !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->reserved)));
ret = (rh != NULL)
&&
@@ -179,12 +179,12 @@ match(const struct sk_buff *skb,
!!(rtinfo->invflags & IP6T_RT_INV_TYP)));
if (ret && (rtinfo->flags & IP6T_RT_RES)) {
- u_int32_t *bp, _bitmap;
- bp = skb_header_pointer(skb,
- ptr + offsetof(struct rt0_hdr, bitmap),
- sizeof(_bitmap), &_bitmap);
+ u_int32_t *rp, _reserved;
+ rp = skb_header_pointer(skb,
+ ptr + offsetof(struct rt0_hdr, reserved),
+ sizeof(_reserved), &_reserved);
- ret = (*bp == 0);
+ ret = (*rp == 0);
}
DEBUGP("#%d ",rtinfo->addrnr);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1d4d75b34d32..5aa3691c578d 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,6 +49,7 @@
#include <net/transp_v6.h>
#include <net/udp.h>
#include <net/inet_common.h>
+#include <net/tcp_states.h>
#include <net/rawv6.h>
#include <net/xfrm.h>
@@ -81,7 +82,8 @@ static void raw_v6_unhash(struct sock *sk)
/* Grumble... icmp and ip_input want to get at this... */
struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
- struct in6_addr *loc_addr, struct in6_addr *rmt_addr)
+ struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
+ int dif)
{
struct hlist_node *node;
int is_multicast = ipv6_addr_is_multicast(loc_addr);
@@ -94,6 +96,9 @@ struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
!ipv6_addr_equal(&np->daddr, rmt_addr))
continue;
+ if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+ continue;
+
if (!ipv6_addr_any(&np->rcv_saddr)) {
if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
goto found;
@@ -137,11 +142,12 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
*
* Caller owns SKB so we must make clones.
*/
-void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
+int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{
struct in6_addr *saddr;
struct in6_addr *daddr;
struct sock *sk;
+ int delivered = 0;
__u8 hash;
saddr = &skb->nh.ipv6h->saddr;
@@ -160,9 +166,10 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
if (sk == NULL)
goto out;
- sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr);
+ sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
while (sk) {
+ delivered = 1;
if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
@@ -170,10 +177,12 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
if (clone)
rawv6_rcv(sk, clone);
}
- sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr);
+ sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
+ IP6CB(skb)->iif);
}
out:
read_unlock(&raw_v6_lock);
+ return delivered;
}
/* This cleans up af_inet6 a bit. -DaveM */
@@ -334,8 +343,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
&skb->nh.ipv6h->daddr,
skb->len, inet->num, skb->csum)) {
- LIMIT_NETDEBUG(
- printk(KERN_DEBUG "raw v6 hw csum failure.\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n");
skb->ip_summed = CHECKSUM_NONE;
}
}
@@ -647,6 +655,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
struct flowi fl;
int addr_len = msg->msg_namelen;
int hlimit = -1;
+ int tclass = -1;
u16 proto;
int err;
@@ -732,7 +741,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(struct ipv6_txoptions);
- err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -747,8 +756,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
}
if (opt == NULL)
opt = np->opt;
- if (flowlabel)
- opt = fl6_merge_options(&opt_space, flowlabel, opt);
+ opt = fl6_merge_options(&opt_space, flowlabel, opt);
fl.proto = proto;
rawv6_probe_proto_opt(&fl, msg);
@@ -774,10 +782,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
- dst_release(dst);
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto out;
- }
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -790,6 +796,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
hlimit = ipv6_get_hoplimit(dst->dev);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
+
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -798,8 +810,9 @@ back_from_confirm:
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags);
} else {
lock_sock(sk);
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0,
- hlimit, opt, &fl, (struct rt6_info*)dst, msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
+ len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
+ msg->msg_flags);
if (err)
ip6_flush_pending_frames(sk);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 59e7c6317872..e4fe9ee484dd 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -479,12 +479,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
/* Point into the IP datagram 'data' part. */
if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data))
goto err;
- if (end-offset < skb->len) {
- if (pskb_trim(skb, end - offset))
- goto err;
- if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->ip_summed = CHECKSUM_NONE;
- }
+
+ if (pskb_trim_rcsum(skb, end - offset))
+ goto err;
/* Find out which fragments are in front and at the back of us
* in the chain of fragments so far. We must know where to put
@@ -562,7 +559,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if (skb->dev)
fq->iif = skb->dev->ifindex;
skb->dev = NULL;
- fq->stamp = skb->stamp;
+ skb_get_timestamp(skb, &fq->stamp);
fq->meat += skb->len;
atomic_add(skb->truesize, &ip6_frag_mem);
@@ -664,7 +661,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
head->next = NULL;
head->dev = dev;
- head->stamp = fq->stamp;
+ skb_set_timestamp(head, &fq->stamp);
head->nh.ipv6h->payload_len = htons(payload_len);
*skb_in = head;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 878789b3122d..5d5bbb49ec78 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1372,7 +1372,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
* Drop the packet on the floor
*/
-int ip6_pkt_discard(struct sk_buff *skb)
+static int ip6_pkt_discard(struct sk_buff *skb)
{
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
@@ -1380,7 +1380,7 @@ int ip6_pkt_discard(struct sk_buff *skb)
return 0;
}
-int ip6_pkt_discard_out(struct sk_buff *skb)
+static int ip6_pkt_discard_out(struct sk_buff *skb)
{
skb->dev = skb->dst->dev;
return ip6_pkt_discard(skb);
@@ -1850,16 +1850,16 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh,
skb = alloc_skb(size, gfp_any());
if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, ENOBUFS);
return;
}
if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) {
kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
+ netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, EINVAL);
return;
}
- NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_ROUTE;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_ROUTE, gfp_any());
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, gfp_any());
}
/*
@@ -1960,8 +1960,6 @@ static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
return arg.len;
}
-extern struct rt6_statistics rt6_stats;
-
static int rt6_stats_seq_show(struct seq_file *seq, void *v)
{
seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index e553e5b80d6e..c3123c9e1a8e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -770,7 +770,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
return 0;
}
-int __init ipip6_fb_tunnel_init(struct net_device *dev)
+static int __init ipip6_fb_tunnel_init(struct net_device *dev)
{
struct ip_tunnel *tunnel = dev->priv;
struct iphdr *iph = &tunnel->parms.iph;
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 3a18e0e6ffed..8eff9fa1e983 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -14,9 +14,6 @@
#include <net/ipv6.h>
#include <net/addrconf.h>
-extern ctl_table ipv6_route_table[];
-extern ctl_table ipv6_icmp_table[];
-
#ifdef CONFIG_SYSCTL
static ctl_table ipv6_table[] = {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ef29cfd936d3..80643e6b346b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -47,6 +47,7 @@
#include <net/tcp.h>
#include <net/ndisc.h>
+#include <net/inet6_hashtables.h>
#include <net/ipv6.h>
#include <net/transp_v6.h>
#include <net/addrconf.h>
@@ -75,34 +76,11 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok);
static struct tcp_func ipv6_mapped;
static struct tcp_func ipv6_specific;
-/* I have no idea if this is a good hash for v6 or not. -DaveM */
-static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport,
- struct in6_addr *faddr, u16 fport)
+static inline int tcp_v6_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb)
{
- int hashent = (lport ^ fport);
-
- hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
- hashent ^= hashent>>16;
- hashent ^= hashent>>8;
- return (hashent & (tcp_ehash_size - 1));
-}
-
-static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
-{
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct in6_addr *laddr = &np->rcv_saddr;
- struct in6_addr *faddr = &np->daddr;
- __u16 lport = inet->num;
- __u16 fport = inet->dport;
- return tcp_v6_hashfn(laddr, lport, faddr, fport);
-}
-
-static inline int tcp_v6_bind_conflict(struct sock *sk,
- struct tcp_bind_bucket *tb)
-{
- struct sock *sk2;
- struct hlist_node *node;
+ const struct sock *sk2;
+ const struct hlist_node *node;
/* We must walk the whole port owner list in this case. -DaveM */
sk_for_each_bound(sk2, node, &tb->owners) {
@@ -126,8 +104,8 @@ static inline int tcp_v6_bind_conflict(struct sock *sk,
*/
static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
{
- struct tcp_bind_hashbucket *head;
- struct tcp_bind_bucket *tb;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
struct hlist_node *node;
int ret;
@@ -138,25 +116,25 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
int remaining = (high - low) + 1;
int rover;
- spin_lock(&tcp_portalloc_lock);
- if (tcp_port_rover < low)
+ spin_lock(&tcp_hashinfo.portalloc_lock);
+ if (tcp_hashinfo.port_rover < low)
rover = low;
else
- rover = tcp_port_rover;
+ rover = tcp_hashinfo.port_rover;
do { rover++;
if (rover > high)
rover = low;
- head = &tcp_bhash[tcp_bhashfn(rover)];
+ head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)];
spin_lock(&head->lock);
- tb_for_each(tb, node, &head->chain)
+ inet_bind_bucket_for_each(tb, node, &head->chain)
if (tb->port == rover)
goto next;
break;
next:
spin_unlock(&head->lock);
} while (--remaining > 0);
- tcp_port_rover = rover;
- spin_unlock(&tcp_portalloc_lock);
+ tcp_hashinfo.port_rover = rover;
+ spin_unlock(&tcp_hashinfo.portalloc_lock);
/* Exhausted local port range during search? It is not
* possible for us to be holding one of the bind hash
@@ -171,9 +149,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
/* OK, here is the one we will use. */
snum = rover;
} else {
- head = &tcp_bhash[tcp_bhashfn(snum)];
+ head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
spin_lock(&head->lock);
- tb_for_each(tb, node, &head->chain)
+ inet_bind_bucket_for_each(tb, node, &head->chain)
if (tb->port == snum)
goto tb_found;
}
@@ -192,8 +170,11 @@ tb_found:
}
tb_not_found:
ret = 1;
- if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
- goto fail_unlock;
+ if (tb == NULL) {
+ tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, snum);
+ if (tb == NULL)
+ goto fail_unlock;
+ }
if (hlist_empty(&tb->owners)) {
if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
tb->fastreuse = 1;
@@ -204,9 +185,9 @@ tb_not_found:
tb->fastreuse = 0;
success:
- if (!tcp_sk(sk)->bind_hash)
- tcp_bind_hash(sk, tb, snum);
- BUG_TRAP(tcp_sk(sk)->bind_hash == tb);
+ if (!inet_csk(sk)->icsk_bind_hash)
+ inet_bind_hash(sk, tb, snum);
+ BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
ret = 0;
fail_unlock:
@@ -224,13 +205,13 @@ static __inline__ void __tcp_v6_hash(struct sock *sk)
BUG_TRAP(sk_unhashed(sk));
if (sk->sk_state == TCP_LISTEN) {
- list = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
- lock = &tcp_lhash_lock;
- tcp_listen_wlock();
+ list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)];
+ lock = &tcp_hashinfo.lhash_lock;
+ inet_listen_wlock(&tcp_hashinfo);
} else {
- sk->sk_hashent = tcp_v6_sk_hashfn(sk);
- list = &tcp_ehash[sk->sk_hashent].chain;
- lock = &tcp_ehash[sk->sk_hashent].lock;
+ sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size);
+ list = &tcp_hashinfo.ehash[sk->sk_hashent].chain;
+ lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock;
write_lock(lock);
}
@@ -255,131 +236,11 @@ static void tcp_v6_hash(struct sock *sk)
}
}
-static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif)
-{
- struct sock *sk;
- struct hlist_node *node;
- struct sock *result = NULL;
- int score, hiscore;
-
- hiscore=0;
- read_lock(&tcp_lhash_lock);
- sk_for_each(sk, node, &tcp_listening_hash[tcp_lhashfn(hnum)]) {
- if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- score = 1;
- if (!ipv6_addr_any(&np->rcv_saddr)) {
- if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
- continue;
- score++;
- }
- if (sk->sk_bound_dev_if) {
- if (sk->sk_bound_dev_if != dif)
- continue;
- score++;
- }
- if (score == 3) {
- result = sk;
- break;
- }
- if (score > hiscore) {
- hiscore = score;
- result = sk;
- }
- }
- }
- if (result)
- sock_hold(result);
- read_unlock(&tcp_lhash_lock);
- return result;
-}
-
-/* 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.
- */
-
-static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 hnum,
- int dif)
-{
- struct tcp_ehash_bucket *head;
- struct sock *sk;
- struct hlist_node *node;
- __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
- int hash;
-
- /* Optimize here for direct hit, only listening connections can
- * have wildcards anyways.
- */
- hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
- head = &tcp_ehash[hash];
- read_lock(&head->lock);
- sk_for_each(sk, node, &head->chain) {
- /* For IPV6 do the cheaper port and family tests first. */
- if(TCP_IPV6_MATCH(sk, 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 + tcp_ehash_size)->chain) {
- /* FIXME: acme: check this... */
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
-
- if(*((__u32 *)&(tw->tw_dport)) == ports &&
- sk->sk_family == PF_INET6) {
- if(ipv6_addr_equal(&tw->tw_v6_daddr, saddr) &&
- ipv6_addr_equal(&tw->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;
-}
-
-
-static inline struct sock *__tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 hnum,
- int dif)
-{
- struct sock *sk;
-
- sk = __tcp_v6_lookup_established(saddr, sport, daddr, hnum, dif);
-
- if (sk)
- return sk;
-
- return tcp_v6_lookup_listener(daddr, hnum, dif);
-}
-
-inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
- struct in6_addr *daddr, u16 dport,
- int dif)
-{
- struct sock *sk;
-
- local_bh_disable();
- sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif);
- local_bh_enable();
-
- return sk;
-}
-
-EXPORT_SYMBOL_GPL(tcp_v6_lookup);
-
-
/*
* Open request hash tables.
*/
-static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
+static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd)
{
u32 a, b, c;
@@ -399,14 +260,15 @@ static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
return c & (TCP_SYNQ_HSIZE - 1);
}
-static struct request_sock *tcp_v6_search_req(struct tcp_sock *tp,
+static struct request_sock *tcp_v6_search_req(const struct sock *sk,
struct request_sock ***prevp,
__u16 rport,
struct in6_addr *raddr,
struct in6_addr *laddr,
int iif)
{
- struct listen_sock *lopt = tp->accept_queue.listen_opt;
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
struct request_sock *req, **prev;
for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
@@ -451,44 +313,48 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
}
}
-static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
- struct tcp_tw_bucket **twp)
+static int __tcp_v6_check_established(struct sock *sk, const __u16 lport,
+ struct inet_timewait_sock **twp)
{
struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct in6_addr *daddr = &np->rcv_saddr;
- struct in6_addr *saddr = &np->daddr;
- int dif = sk->sk_bound_dev_if;
- u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
- int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport);
- struct tcp_ehash_bucket *head = &tcp_ehash[hash];
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ const struct in6_addr *daddr = &np->rcv_saddr;
+ const struct in6_addr *saddr = &np->daddr;
+ const int dif = sk->sk_bound_dev_if;
+ const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+ const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport,
+ tcp_hashinfo.ehash_size);
+ struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
struct sock *sk2;
- struct hlist_node *node;
- struct tcp_tw_bucket *tw;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
write_lock(&head->lock);
/* Check TIME-WAIT sockets first. */
- sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) {
- tw = (struct tcp_tw_bucket*)sk2;
+ sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
+ const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk2);
+
+ tw = inet_twsk(sk2);
if(*((__u32 *)&(tw->tw_dport)) == ports &&
sk2->sk_family == PF_INET6 &&
- ipv6_addr_equal(&tw->tw_v6_daddr, saddr) &&
- ipv6_addr_equal(&tw->tw_v6_rcv_saddr, daddr) &&
+ ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr) &&
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
+ const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
struct tcp_sock *tp = tcp_sk(sk);
- if (tw->tw_ts_recent_stamp &&
- (!twp || (sysctl_tcp_tw_reuse &&
- xtime.tv_sec -
- tw->tw_ts_recent_stamp > 1))) {
+ if (tcptw->tw_ts_recent_stamp &&
+ (!twp ||
+ (sysctl_tcp_tw_reuse &&
+ xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
/* See comment in tcp_ipv4.c */
- tp->write_seq = tw->tw_snd_nxt + 65535 + 2;
+ tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
if (!tp->write_seq)
tp->write_seq = 1;
- tp->rx_opt.ts_recent = tw->tw_ts_recent;
- tp->rx_opt.ts_recent_stamp = tw->tw_ts_recent_stamp;
+ tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
+ tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
sock_hold(sk2);
goto unique;
} else
@@ -499,7 +365,7 @@ static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
/* And established part... */
sk_for_each(sk2, node, &head->chain) {
- if(TCP_IPV6_MATCH(sk2, saddr, daddr, ports, dif))
+ if (INET6_MATCH(sk2, saddr, daddr, ports, dif))
goto not_unique;
}
@@ -515,10 +381,10 @@ unique:
NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
} else if (tw) {
/* Silly. Should hash-dance instead... */
- tcp_tw_deschedule(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);
NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
}
return 0;
@@ -540,8 +406,8 @@ static inline u32 tcpv6_port_offset(const struct sock *sk)
static int tcp_v6_hash_connect(struct sock *sk)
{
unsigned short snum = inet_sk(sk)->num;
- struct tcp_bind_hashbucket *head;
- struct tcp_bind_bucket *tb;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
int ret;
if (!snum) {
@@ -553,19 +419,19 @@ static int tcp_v6_hash_connect(struct sock *sk)
static u32 hint;
u32 offset = hint + tcpv6_port_offset(sk);
struct hlist_node *node;
- struct tcp_tw_bucket *tw = NULL;
+ struct inet_timewait_sock *tw = NULL;
local_bh_disable();
for (i = 1; i <= range; i++) {
port = low + (i + offset) % range;
- head = &tcp_bhash[tcp_bhashfn(port)];
+ head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)];
spin_lock(&head->lock);
/* Does not bother with rcv_saddr checks,
* because the established check is already
* unique enough.
*/
- tb_for_each(tb, node, &head->chain) {
+ inet_bind_bucket_for_each(tb, node, &head->chain) {
if (tb->port == port) {
BUG_TRAP(!hlist_empty(&tb->owners));
if (tb->fastreuse >= 0)
@@ -578,7 +444,7 @@ static int tcp_v6_hash_connect(struct sock *sk)
}
}
- tb = tcp_bucket_create(head, port);
+ tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
if (!tb) {
spin_unlock(&head->lock);
break;
@@ -597,7 +463,7 @@ ok:
hint += i;
/* Head lock still held and bh's disabled */
- tcp_bind_hash(sk, tb, port);
+ inet_bind_hash(sk, tb, port);
if (sk_unhashed(sk)) {
inet_sk(sk)->sport = htons(port);
__tcp_v6_hash(sk);
@@ -605,16 +471,16 @@ ok:
spin_unlock(&head->lock);
if (tw) {
- tcp_tw_deschedule(tw);
- tcp_tw_put(tw);
+ inet_twsk_deschedule(tw, &tcp_death_row);
+ inet_twsk_put(tw);
}
ret = 0;
goto out;
}
- head = &tcp_bhash[tcp_bhashfn(snum)];
- tb = tcp_sk(sk)->bind_hash;
+ head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
+ tb = inet_csk(sk)->icsk_bind_hash;
spin_lock_bh(&head->lock);
if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
@@ -631,11 +497,6 @@ out:
}
}
-static __inline__ int tcp_v6_iif(struct sk_buff *skb)
-{
- return IP6CB(skb)->iif;
-}
-
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_len)
{
@@ -771,10 +632,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p);
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
- dst_release(dst);
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto failure;
- }
if (saddr == NULL) {
saddr = &fl.fl6_src;
@@ -827,14 +686,15 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info)
{
struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
- struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
+ const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
struct ipv6_pinfo *np;
struct sock *sk;
int err;
struct tcp_sock *tp;
__u32 seq;
- sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
+ sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
+ th->source, skb->dev->ifindex);
if (sk == NULL) {
ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
@@ -842,7 +702,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
if (sk->sk_state == TCP_TIME_WAIT) {
- tcp_tw_put((struct tcp_tw_bucket*)sk);
+ inet_twsk_put((struct inet_timewait_sock *)sk);
return;
}
@@ -920,8 +780,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (sock_owned_by_user(sk))
goto out;
- req = tcp_v6_search_req(tp, &prev, th->dest, &hdr->daddr,
- &hdr->saddr, tcp_v6_iif(skb));
+ req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr,
+ &hdr->saddr, inet6_iif(skb));
if (!req)
goto out;
@@ -935,7 +795,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
goto out;
}
- tcp_synq_drop(sk, req, prev);
+ inet_csk_reqsk_queue_drop(sk, req, prev);
goto out;
case TCP_SYN_SENT:
@@ -987,7 +847,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
if (dst == NULL) {
opt = np->opt;
if (opt == NULL &&
- np->rxopt.bits.srcrt == 2 &&
+ np->rxopt.bits.osrcrt == 2 &&
treq->pktopts) {
struct sk_buff *pktopts = treq->pktopts;
struct inet6_skb_parm *rxopt = IP6CB(pktopts);
@@ -1026,7 +886,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
}
done:
- dst_release(dst);
if (opt && opt != np->opt)
sock_kfree_s(sk, opt, opt->tot_len);
return err;
@@ -1053,11 +912,10 @@ static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
struct inet6_skb_parm *opt = IP6CB(skb);
if (np->rxopt.all) {
- if ((opt->hop && np->rxopt.bits.hopopts) ||
- ((IPV6_FLOWINFO_MASK&*(u32*)skb->nh.raw) &&
- np->rxopt.bits.rxflow) ||
- (opt->srcrt && np->rxopt.bits.srcrt) ||
- ((opt->dst1 || opt->dst0) && np->rxopt.bits.dstopts))
+ if ((opt->hop && (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) ||
+ ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && np->rxopt.bits.rxflow) ||
+ (opt->srcrt && (np->rxopt.bits.srcrt || np->rxopt.bits.osrcrt)) ||
+ ((opt->dst1 || opt->dst0) && (np->rxopt.bits.dstopts || np->rxopt.bits.odstopts)))
return 1;
}
return 0;
@@ -1132,17 +990,15 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
buff->csum);
fl.proto = IPPROTO_TCP;
- fl.oif = tcp_v6_iif(skb);
+ fl.oif = inet6_iif(skb);
fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source;
/* sk = NULL, but it is safe for now. RST socket required. */
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
- if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
- dst_release(buff->dst);
+ if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
return;
- }
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
@@ -1201,15 +1057,13 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
buff->csum);
fl.proto = IPPROTO_TCP;
- fl.oif = tcp_v6_iif(skb);
+ fl.oif = inet6_iif(skb);
fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source;
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
- if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
- dst_release(buff->dst);
+ if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
return;
- }
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return;
@@ -1220,12 +1074,14 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
{
- struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+ struct inet_timewait_sock *tw = inet_twsk(sk);
+ const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v6_send_ack(skb, tw->tw_snd_nxt, tw->tw_rcv_nxt,
- tw->tw_rcv_wnd >> tw->tw_rcv_wscale, tw->tw_ts_recent);
+ tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+ tcptw->tw_ts_recent);
- tcp_tw_put(tw);
+ inet_twsk_put(tw);
}
static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
@@ -1237,28 +1093,25 @@ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
{
struct request_sock *req, **prev;
- struct tcphdr *th = skb->h.th;
- struct tcp_sock *tp = tcp_sk(sk);
+ const struct tcphdr *th = skb->h.th;
struct sock *nsk;
/* Find possible connection requests. */
- req = tcp_v6_search_req(tp, &prev, th->source, &skb->nh.ipv6h->saddr,
- &skb->nh.ipv6h->daddr, tcp_v6_iif(skb));
+ req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr, inet6_iif(skb));
if (req)
return tcp_check_req(sk, skb, req, prev);
- nsk = __tcp_v6_lookup_established(&skb->nh.ipv6h->saddr,
- th->source,
- &skb->nh.ipv6h->daddr,
- ntohs(th->dest),
- tcp_v6_iif(skb));
+ nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr,
+ th->source, &skb->nh.ipv6h->daddr,
+ ntohs(th->dest), inet6_iif(skb));
if (nsk) {
if (nsk->sk_state != TCP_TIME_WAIT) {
bh_lock_sock(nsk);
return nsk;
}
- tcp_tw_put((struct tcp_tw_bucket*)nsk);
+ inet_twsk_put((struct inet_timewait_sock *)nsk);
return NULL;
}
@@ -1271,12 +1124,12 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
{
- struct tcp_sock *tp = tcp_sk(sk);
- struct listen_sock *lopt = tp->accept_queue.listen_opt;
- u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+ const u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
- reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
- tcp_synq_added(sk);
+ reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT);
+ inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT);
}
@@ -1301,13 +1154,13 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
/*
* There are no SYN attacks on IPv6, yet...
*/
- if (tcp_synq_is_full(sk) && !isn) {
+ if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
if (net_ratelimit())
printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
goto drop;
}
- if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;
req = reqsk_alloc(&tcp6_request_sock_ops);
@@ -1329,8 +1182,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
TCP_ECN_create_request(req, skb->h.th);
treq->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
- np->rxopt.bits.rxinfo ||
- np->rxopt.bits.rxhlim) {
+ np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
+ np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
atomic_inc(&skb->users);
treq->pktopts = skb;
}
@@ -1339,7 +1192,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
/* So that link locals have meaning */
if (!sk->sk_bound_dev_if &&
ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
- treq->iif = tcp_v6_iif(skb);
+ treq->iif = inet6_iif(skb);
if (isn == 0)
isn = tcp_v6_init_sequence(sk,skb);
@@ -1404,15 +1257,14 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newsk->sk_backlog_rcv = tcp_v4_do_rcv;
newnp->pktoptions = NULL;
newnp->opt = NULL;
- newnp->mcast_oif = tcp_v6_iif(skb);
+ newnp->mcast_oif = inet6_iif(skb);
newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
- /* Charge newly allocated IPv6 socket. Though it is mapped,
- * it is IPv6 yet.
+ /*
+ * No need to charge this sock to the relevant IPv6 refcnt debug socks count
+ * here, tcp_create_openreq_child now does this for us, see the comment in
+ * that function for the gory details. -acme
*/
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet6_sock_nr);
-#endif
/* It is tricky place. Until this moment IPv4 tcp
worked with IPv6 af_tcp.af_specific.
@@ -1428,7 +1280,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (sk_acceptq_is_full(sk))
goto out_overflow;
- if (np->rxopt.bits.srcrt == 2 &&
+ if (np->rxopt.bits.osrcrt == 2 &&
opt == NULL && treq->pktopts) {
struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
if (rxopt->srcrt)
@@ -1467,10 +1319,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (newsk == NULL)
goto out;
- /* Charge newly allocated IPv6 socket */
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet6_sock_nr);
-#endif
+ /*
+ * No need to charge this sock to the relevant IPv6 refcnt debug socks
+ * count here, tcp_create_openreq_child now does this for us, see the
+ * comment in that function for the gory details. -acme
+ */
ip6_dst_store(newsk, dst, NULL);
newsk->sk_route_caps = dst->dev->features &
@@ -1509,7 +1362,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
skb_set_owner_r(newnp->pktoptions, newsk);
}
newnp->opt = NULL;
- newnp->mcast_oif = tcp_v6_iif(skb);
+ newnp->mcast_oif = inet6_iif(skb);
newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
/* Clone native IPv6 options from listening socket (if any)
@@ -1536,7 +1389,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
__tcp_v6_hash(newsk);
- tcp_inherit_port(sk, newsk);
+ inet_inherit_port(&tcp_hashinfo, sk, newsk);
return newsk;
@@ -1557,7 +1410,7 @@ static int tcp_v6_checksum_init(struct sk_buff *skb)
if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
&skb->nh.ipv6h->daddr,skb->csum))
return 0;
- LIMIT_NETDEBUG(printk(KERN_DEBUG "hw tcp v6 csum failed\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v6 csum failed\n");
}
if (skb->len <= 76) {
if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
@@ -1683,9 +1536,9 @@ ipv6_pktoptions:
tp = tcp_sk(sk);
if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
- if (np->rxopt.bits.rxinfo)
- np->mcast_oif = tcp_v6_iif(opt_skb);
- if (np->rxopt.bits.rxhlim)
+ if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
+ np->mcast_oif = inet6_iif(opt_skb);
+ if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
np->mcast_hops = opt_skb->nh.ipv6h->hop_limit;
if (ipv6_opt_accepted(sk, opt_skb)) {
skb_set_owner_r(opt_skb, sk);
@@ -1739,8 +1592,9 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
TCP_SKB_CB(skb)->sacked = 0;
- sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source,
- &skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb));
+ sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source,
+ &skb->nh.ipv6h->daddr, ntohs(th->dest),
+ inet6_iif(skb));
if (!sk)
goto no_tcp_socket;
@@ -1795,26 +1649,29 @@ discard_and_relse:
do_time_wait:
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- tcp_tw_put((struct tcp_tw_bucket *) sk);
+ inet_twsk_put((struct inet_timewait_sock *)sk);
goto discard_it;
}
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
TCP_INC_STATS_BH(TCP_MIB_INERRS);
- tcp_tw_put((struct tcp_tw_bucket *) sk);
+ inet_twsk_put((struct inet_timewait_sock *)sk);
goto discard_it;
}
- switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
- skb, th, skb->len)) {
+ switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
+ skb, th)) {
case TCP_TW_SYN:
{
struct sock *sk2;
- sk2 = tcp_v6_lookup_listener(&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb));
+ sk2 = inet6_lookup_listener(&tcp_hashinfo,
+ &skb->nh.ipv6h->daddr,
+ ntohs(th->dest), inet6_iif(skb));
if (sk2 != NULL) {
- tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
- tcp_tw_put((struct tcp_tw_bucket *)sk);
+ struct inet_timewait_sock *tw = inet_twsk(sk);
+ inet_twsk_deschedule(tw, &tcp_death_row);
+ inet_twsk_put(tw);
sk = sk2;
goto process;
}
@@ -1869,7 +1726,6 @@ static int tcp_v6_rebuild_header(struct sock *sk)
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_err_soft = -err;
- dst_release(dst);
return err;
}
@@ -1922,7 +1778,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_route_caps = 0;
- dst_release(dst);
return err;
}
@@ -1983,7 +1838,7 @@ static struct tcp_func ipv6_specific = {
static struct tcp_func ipv6_mapped = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
- .rebuild_header = tcp_v4_rebuild_header,
+ .rebuild_header = inet_sk_rebuild_header,
.conn_request = tcp_v6_conn_request,
.syn_recv_sock = tcp_v6_syn_recv_sock,
.remember_stamp = tcp_v4_remember_stamp,
@@ -2002,13 +1857,14 @@ static struct tcp_func ipv6_mapped = {
*/
static int tcp_v6_init_sock(struct sock *sk)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
skb_queue_head_init(&tp->out_of_order_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);
- tp->rto = TCP_TIMEOUT_INIT;
+ icsk->icsk_rto = TCP_TIMEOUT_INIT;
tp->mdev = TCP_TIMEOUT_INIT;
/* So many TCP implementations out there (incorrectly) count the
@@ -2030,7 +1886,7 @@ static int tcp_v6_init_sock(struct sock *sk)
sk->sk_state = TCP_CLOSE;
tp->af_specific = &ipv6_specific;
- tp->ca_ops = &tcp_init_congestion_ops;
+ icsk->icsk_ca_ops = &tcp_init_congestion_ops;
sk->sk_write_space = sk_stream_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
@@ -2044,8 +1900,6 @@ static int tcp_v6_init_sock(struct sock *sk)
static int tcp_v6_destroy_sock(struct sock *sk)
{
- extern int tcp_v4_destroy_sock(struct sock *sk);
-
tcp_v4_destroy_sock(sk);
return inet6_destroy_sock(sk);
}
@@ -2091,18 +1945,20 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
unsigned long timer_expires;
struct inet_sock *inet = inet_sk(sp);
struct tcp_sock *tp = tcp_sk(sp);
+ const struct inet_connection_sock *icsk = inet_csk(sp);
struct ipv6_pinfo *np = inet6_sk(sp);
dest = &np->daddr;
src = &np->rcv_saddr;
destp = ntohs(inet->dport);
srcp = ntohs(inet->sport);
- if (tp->pending == TCP_TIME_RETRANS) {
+
+ if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
timer_active = 1;
- timer_expires = tp->timeout;
- } else if (tp->pending == TCP_TIME_PROBE0) {
+ timer_expires = icsk->icsk_timeout;
+ } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
timer_active = 4;
- timer_expires = tp->timeout;
+ timer_expires = icsk->icsk_timeout;
} else if (timer_pending(&sp->sk_timer)) {
timer_active = 2;
timer_expires = sp->sk_timer.expires;
@@ -2123,28 +1979,31 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
timer_active,
jiffies_to_clock_t(timer_expires - jiffies),
- tp->retransmits,
+ icsk->icsk_retransmits,
sock_i_uid(sp),
- tp->probes_out,
+ icsk->icsk_probes_out,
sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+ icsk->icsk_rto,
+ icsk->icsk_ack.ato,
+ (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
);
}
static void get_timewait6_sock(struct seq_file *seq,
- struct tcp_tw_bucket *tw, int i)
+ struct inet_timewait_sock *tw, int i)
{
struct in6_addr *dest, *src;
__u16 destp, srcp;
+ struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
int ttd = tw->tw_ttd - jiffies;
if (ttd < 0)
ttd = 0;
- dest = &tw->tw_v6_daddr;
- src = &tw->tw_v6_rcv_saddr;
+ dest = &tcp6tw->tw_v6_daddr;
+ src = &tcp6tw->tw_v6_rcv_saddr;
destp = ntohs(tw->tw_dport);
srcp = ntohs(tw->tw_sport);
@@ -2219,7 +2078,7 @@ struct proto tcpv6_prot = {
.close = tcp_close,
.connect = tcp_v6_connect,
.disconnect = tcp_disconnect,
- .accept = tcp_accept,
+ .accept = inet_csk_accept,
.ioctl = tcp_ioctl,
.init = tcp_v6_init_sock,
.destroy = tcp_v6_destroy_sock,
@@ -2236,11 +2095,13 @@ struct proto tcpv6_prot = {
.sockets_allocated = &tcp_sockets_allocated,
.memory_allocated = &tcp_memory_allocated,
.memory_pressure = &tcp_memory_pressure,
+ .orphan_count = &tcp_orphan_count,
.sysctl_mem = sysctl_tcp_mem,
.sysctl_wmem = sysctl_tcp_wmem,
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp6_sock),
+ .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
.rsk_prot = &tcp6_request_sock_ops,
};
@@ -2250,8 +2111,6 @@ static struct inet6_protocol tcpv6_protocol = {
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
-extern struct proto_ops inet6_stream_ops;
-
static struct inet_protosw tcpv6_protosw = {
.type = SOCK_STREAM,
.protocol = IPPROTO_TCP,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index eff050ac7049..69b146843a20 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -51,6 +51,7 @@
#include <net/udp.h>
#include <net/raw.h>
#include <net/inet_common.h>
+#include <net/tcp_states.h>
#include <net/ip6_checksum.h>
#include <net/xfrm.h>
@@ -58,7 +59,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
+DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
/* Grrr, addr_type already calculated by caller, but I don't want
* to add some silly "cookie" argument to this method just for that.
@@ -477,13 +478,12 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
/* RFC 2460 section 8.1 says that we SHOULD log
this error. Well, it is reasonable.
*/
- LIMIT_NETDEBUG(
- printk(KERN_INFO "IPv6: udp checksum is 0\n"));
+ LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
goto discard;
}
if (ulen < skb->len) {
- if (__pskb_trim(skb, ulen))
+ if (pskb_trim_rcsum(skb, ulen))
goto discard;
saddr = &skb->nh.ipv6h->saddr;
daddr = &skb->nh.ipv6h->daddr;
@@ -493,7 +493,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
if (skb->ip_summed==CHECKSUM_HW) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) {
- LIMIT_NETDEBUG(printk(KERN_DEBUG "udp v6 hw csum failure.\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "udp v6 hw csum failure.\n");
skb->ip_summed = CHECKSUM_NONE;
}
}
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
int addr_len = msg->msg_namelen;
int ulen = len;
int hlimit = -1;
+ int tclass = -1;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
@@ -758,7 +759,7 @@ do_udp_sendmsg:
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(*opt);
- err = datagram_send_ctl(msg, fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -773,8 +774,7 @@ do_udp_sendmsg:
}
if (opt == NULL)
opt = np->opt;
- if (flowlabel)
- opt = fl6_merge_options(&opt_space, flowlabel, opt);
+ opt = fl6_merge_options(&opt_space, flowlabel, opt);
fl->proto = IPPROTO_UDP;
ipv6_addr_copy(&fl->fl6_dst, daddr);
@@ -799,10 +799,8 @@ do_udp_sendmsg:
if (final_p)
ipv6_addr_copy(&fl->fl6_dst, final_p);
- if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
- dst_release(dst);
+ if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0)
goto out;
- }
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -815,6 +813,12 @@ do_udp_sendmsg:
hlimit = ipv6_get_hoplimit(dst->dev);
}
+ if (tclass < 0) {
+ tclass = np->tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
+
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
back_from_confirm:
@@ -825,7 +829,7 @@ back_from_confirm:
/* ... which is an evident application bug. --ANK */
release_sock(sk);
- LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 2\n"));
+ LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");
err = -EINVAL;
goto out;
}
@@ -834,9 +838,10 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, sizeof(struct udphdr),
- hlimit, opt, fl, (struct rt6_info*)dst,
- corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+ sizeof(struct udphdr), hlimit, tclass, opt, fl,
+ (struct rt6_info*)dst,
+ corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
else if (!corkreq)
@@ -1054,8 +1059,6 @@ struct proto udpv6_prot = {
.obj_size = sizeof(struct udp6_sock),
};
-extern struct proto_ops inet6_dgram_ops;
-
static struct inet_protosw udpv6_protosw = {
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 60c26c87277e..fbef7826a74f 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -79,7 +79,7 @@ static u32 xfrm6_tunnel_spi;
#define XFRM6_TUNNEL_SPI_MIN 1
#define XFRM6_TUNNEL_SPI_MAX 0xffffffff
-static kmem_cache_t *xfrm6_tunnel_spi_kmem;
+static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly;
#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256
#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 5a27e5df5886..34b3bb868409 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -44,7 +44,6 @@
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/string.h>
-#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/termios.h>
@@ -52,6 +51,7 @@
#include <net/p8022.h>
#include <net/psnap.h>
#include <net/sock.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
@@ -1627,7 +1627,7 @@ out:
return rc;
}
-static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/* NULL here for pt means the packet was looped back */
struct ipx_interface *intrfc;
@@ -1796,8 +1796,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
copied);
if (rc)
goto out_free;
- if (skb->stamp.tv_sec)
- sk->sk_stamp = skb->stamp;
+ if (skb->tstamp.off_sec)
+ skb_get_timestamp(skb, &sk->sk_stamp);
msg->msg_namelen = sizeof(*sipx);
@@ -1940,9 +1940,7 @@ static struct notifier_block ipx_dev_notifier = {
};
extern struct datalink_proto *make_EII_client(void);
-extern struct datalink_proto *make_8023_client(void);
extern void destroy_EII_client(struct datalink_proto *);
-extern void destroy_8023_client(struct datalink_proto *);
static unsigned char ipx_8022_type = 0xE0;
static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index b6761913445a..1f73d9ea434d 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -10,7 +10,7 @@
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>
-#include <linux/tcp.h>
+#include <net/tcp_states.h>
#include <net/ipx.h>
static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 92c6e8d4e731..6f92f9c62990 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -56,7 +56,7 @@
#include <asm/uaccess.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/irda/af_irda.h>
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 5d1e61168eb7..6f20b4206e08 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -567,10 +567,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
self->tty = NULL;
if (self->blocked_open) {
- if (self->close_delay) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(self->close_delay);
- }
+ if (self->close_delay)
+ schedule_timeout_interruptible(self->close_delay);
wake_up_interruptible(&self->open_wait);
}
@@ -863,8 +861,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
spin_lock_irqsave(&self->spinlock, flags);
while (self->tx_skb && self->tx_skb->len) {
spin_unlock_irqrestore(&self->spinlock, flags);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(poll_time);
+ schedule_timeout_interruptible(poll_time);
spin_lock_irqsave(&self->spinlock, flags);
if (signal_pending(current))
break;
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
index 343c5d4a1a1d..ca7d358dab52 100644
--- a/net/irda/irlan/irlan_filter.c
+++ b/net/irda/irlan/irlan_filter.c
@@ -27,6 +27,7 @@
#include <linux/seq_file.h>
#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_filter.h>
/*
* Function irlan_filter_request (self, skb)
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 6dafbb43b529..3e9a06abbdd0 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -988,9 +988,6 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
return;
}
- /* Unlink tx_skb from list */
- tx_skb->next = tx_skb->prev = NULL;
- tx_skb->list = NULL;
/* Clear old Nr field + poll bit */
tx_skb->data[1] &= 0x0f;
@@ -1063,9 +1060,6 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
return;
}
- /* Unlink tx_skb from list */
- tx_skb->next = tx_skb->prev = NULL;
- tx_skb->list = NULL;
/* Clear old Nr field + poll bit */
tx_skb->data[1] &= 0x0f;
@@ -1309,7 +1303,7 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
* Jean II
*/
int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype)
+ struct packet_type *ptype, struct net_device *orig_dev)
{
struct irlap_info info;
struct irlap_cb *self;
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 7a4a4d7fbe66..c19e9ce05a3a 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -53,7 +53,6 @@ struct irlmp_cb *irlmp = NULL;
/* These can be altered by the sysctl interface */
int sysctl_discovery = 0;
int sysctl_discovery_timeout = 3; /* 3 seconds by default */
-EXPORT_SYMBOL(sysctl_discovery_timeout);
int sysctl_discovery_slots = 6; /* 6 slots by default */
int sysctl_lap_keepalive_time = LM_IDLE_TIMEOUT * 1000 / HZ;
char sysctl_devname[65];
@@ -67,7 +66,6 @@ const char *irlmp_reasons[] = {
"LM_INIT_DISCONNECT",
"ERROR, NOT USED",
};
-EXPORT_SYMBOL(irlmp_reasons);
/*
* Function irlmp_init (void)
@@ -675,7 +673,6 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
return new;
}
-EXPORT_SYMBOL(irlmp_dup);
/*
* Function irlmp_disconnect_request (handle, userdata)
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index 6ffaed4544e9..634901dd156f 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -54,7 +54,7 @@ extern int irsock_init(void);
extern void irsock_cleanup(void);
/* irlap_frame.c */
extern int irlap_driver_rcv(struct sk_buff *, struct net_device *,
- struct packet_type *);
+ struct packet_type *, struct net_device *);
/*
* Module parameters
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index 9004f7349a76..b391cb3893d4 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -517,9 +517,6 @@ extern int
irda_irnet_init(void); /* Initialise IrDA part of IrNET */
extern void
irda_irnet_cleanup(void); /* Teardown IrDA part of IrNET */
-/* ---------------------------- MODULE ---------------------------- */
-extern int
- irnet_init(void); /* Initialise IrNET module */
/**************************** VARIABLES ****************************/
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index f8f984bb9922..e53bf9e0053e 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -1107,7 +1107,7 @@ ppp_irnet_cleanup(void)
/*
* Module main entry point
*/
-int __init
+static int __init
irnet_init(void)
{
int err;
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index b0dd3ea35999..1ba8c7106639 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -822,7 +822,6 @@ void* hashbin_find_next( hashbin_t* hashbin, long hashv, const char* name,
return entry;
}
-EXPORT_SYMBOL(hashbin_find_next);
/*
* Function hashbin_get_first (hashbin)
diff --git a/net/irda/qos.c b/net/irda/qos.c
index df732d56cc57..ddfb5c502a90 100644
--- a/net/irda/qos.c
+++ b/net/irda/qos.c
@@ -37,6 +37,7 @@
#include <net/irda/parameters.h>
#include <net/irda/qos.h>
#include <net/irda/irlap.h>
+#include <net/irda/irlap_frame.h>
/*
* Maximum values of the baud rate we negociate with the other end.
diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c
index 5de05a0bc0ff..8b5eefd70f03 100644
--- a/net/lapb/lapb_subr.c
+++ b/net/lapb/lapb_subr.c
@@ -78,7 +78,7 @@ void lapb_requeue_frames(struct lapb_cb *lapb)
if (!skb_prev)
skb_queue_head(&lapb->write_queue, skb);
else
- skb_append(skb_prev, skb);
+ skb_append(skb_prev, skb, &lapb->write_queue);
skb_prev = skb;
}
}
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 20b4cfebd74c..66f55e514b56 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -23,13 +23,13 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/tcp.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <net/llc.h>
#include <net/llc_sap.h>
#include <net/llc_pdu.h>
#include <net/llc_conn.h>
+#include <net/tcp_states.h>
/* remember: uninitialized global data is zeroed because its in .bss */
static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
@@ -714,7 +714,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
if (uaddr)
memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
msg->msg_namelen = sizeof(*uaddr);
- if (!skb->list) {
+ if (!skb->next) {
dgram_free:
kfree_skb(skb);
}
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index eba812a9c69c..4c644bc70eae 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -16,7 +16,7 @@
#include <net/llc_sap.h>
#include <net/llc_conn.h>
#include <net/sock.h>
-#include <linux/tcp.h>
+#include <net/tcp_states.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_st.h>
@@ -71,7 +71,11 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
if (!ev->ind_prim && !ev->cfm_prim) {
/* indicate or confirm not required */
- if (!skb->list)
+ /* XXX this is not very pretty, perhaps we should store
+ * XXX indicate/confirm-needed state in the llc_conn_state_ev
+ * XXX control block of the SKB instead? -DaveM
+ */
+ if (!skb->next)
goto out_kfree_skb;
goto out_skb_put;
}
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
index 5ff02c080a0b..9727455bf0e7 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -103,7 +103,8 @@ out:
struct llc_sap *llc_sap_open(unsigned char lsap,
int (*func)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt))
+ struct packet_type *pt,
+ struct net_device *orig_dev))
{
struct llc_sap *sap = llc_sap_find(lsap);
diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
index 0f9fc48aeaf9..0f84f66018e4 100644
--- a/net/llc/llc_if.c
+++ b/net/llc/llc_if.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
-#include <linux/tcp.h>
#include <asm/errno.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
@@ -25,6 +24,7 @@
#include <net/llc_c_ev.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_st.h>
+#include <net/tcp_states.h>
u8 llc_mac_null_var[IFHWADDRLEN];
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 4da6976efc9c..13b46240b7a1 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -132,7 +132,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
* data now), it queues this frame in the connection's backlog.
*/
int llc_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct llc_sap *sap;
struct llc_pdu_sn *pdu;
@@ -165,7 +165,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
* LLC functionality
*/
if (sap->rcv_func) {
- sap->rcv_func(skb, dev, pt);
+ sap->rcv_func(skb, dev, pt, orig_dev);
goto out;
}
dest = llc_pdu_type(skb);
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 965c94eb4bbc..34228ef14985 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -21,7 +21,7 @@
#include <net/llc_s_ev.h>
#include <net/llc_s_st.h>
#include <net/sock.h>
-#include <linux/tcp.h>
+#include <net/tcp_states.h>
#include <linux/llc.h>
/**
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
new file mode 100644
index 000000000000..8296b38bf270
--- /dev/null
+++ b/net/netfilter/Kconfig
@@ -0,0 +1,24 @@
+config NETFILTER_NETLINK
+ tristate "Netfilter netlink interface"
+ help
+ If this option is enabled, the kernel will include support
+ for the new netfilter netlink interface.
+
+config NETFILTER_NETLINK_QUEUE
+ tristate "Netfilter NFQUEUE over NFNETLINK interface"
+ depends on NETFILTER_NETLINK
+ help
+ If this option isenabled, the kernel will include support
+ for queueing packets via NFNETLINK.
+
+config NETFILTER_NETLINK_LOG
+ tristate "Netfilter LOG over NFNETLINK interface"
+ depends on NETFILTER_NETLINK
+ help
+ If this option is enabled, the kernel will include support
+ for logging packets via NFNETLINK.
+
+ This obsoletes the existing ipt_ULOG and ebg_ulog mechanisms,
+ and is also scheduled to replace the old syslog-based ipt_LOG
+ and ip6t_LOG modules.
+
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
new file mode 100644
index 000000000000..b3b44f8b415a
--- /dev/null
+++ b/net/netfilter/Makefile
@@ -0,0 +1,7 @@
+netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
+
+obj-$(CONFIG_NETFILTER) = netfilter.o
+
+obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
+obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
+obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
new file mode 100644
index 000000000000..1ceb1a6c254b
--- /dev/null
+++ b/net/netfilter/core.c
@@ -0,0 +1,216 @@
+/* netfilter.c: look after the filters for various protocols.
+ * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
+ *
+ * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
+ * way.
+ *
+ * Rusty Russell (C)2000 -- This code is GPL.
+ *
+ * February 2000: Modified by James Morris to have 1 queue per protocol.
+ * 15-Mar-2000: Added NF_REPEAT --RR.
+ * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/netfilter.h>
+#include <net/protocol.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+
+#include "nf_internals.h"
+
+/* 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
+ * this is zero, but that sucks. Now, we simply check when the
+ * packets come back: if the hook is gone, the packet is discarded. */
+struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
+EXPORT_SYMBOL(nf_hooks);
+static DEFINE_SPINLOCK(nf_hook_lock);
+
+int nf_register_hook(struct nf_hook_ops *reg)
+{
+ struct list_head *i;
+
+ spin_lock_bh(&nf_hook_lock);
+ list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
+ if (reg->priority < ((struct nf_hook_ops *)i)->priority)
+ break;
+ }
+ list_add_rcu(&reg->list, i->prev);
+ spin_unlock_bh(&nf_hook_lock);
+
+ synchronize_net();
+ return 0;
+}
+EXPORT_SYMBOL(nf_register_hook);
+
+void nf_unregister_hook(struct nf_hook_ops *reg)
+{
+ spin_lock_bh(&nf_hook_lock);
+ list_del_rcu(&reg->list);
+ spin_unlock_bh(&nf_hook_lock);
+
+ synchronize_net();
+}
+EXPORT_SYMBOL(nf_unregister_hook);
+
+unsigned int nf_iterate(struct list_head *head,
+ struct sk_buff **skb,
+ int hook,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ struct list_head **i,
+ int (*okfn)(struct sk_buff *),
+ int hook_thresh)
+{
+ unsigned int verdict;
+
+ /*
+ * The caller must not block between calls to this
+ * function because of risk of continuing from deleted element.
+ */
+ list_for_each_continue_rcu(*i, head) {
+ struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
+
+ if (hook_thresh > elem->priority)
+ continue;
+
+ /* Optimization: we don't need to hold module
+ reference here, since function can't sleep. --RR */
+ verdict = elem->hook(hook, skb, indev, outdev, okfn);
+ if (verdict != NF_ACCEPT) {
+#ifdef CONFIG_NETFILTER_DEBUG
+ if (unlikely((verdict & NF_VERDICT_MASK)
+ > NF_MAX_VERDICT)) {
+ NFDEBUG("Evil return from %p(%u).\n",
+ elem->hook, hook);
+ continue;
+ }
+#endif
+ if (verdict != NF_REPEAT)
+ return verdict;
+ *i = (*i)->prev;
+ }
+ }
+ return NF_ACCEPT;
+}
+
+
+/* Returns 1 if okfn() needs to be executed by the caller,
+ * -EPERM for NF_DROP, 0 otherwise. */
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *),
+ int hook_thresh)
+{
+ struct list_head *elem;
+ unsigned int verdict;
+ int ret = 0;
+
+ /* We may already have this, but read-locks nest anyway */
+ rcu_read_lock();
+
+ elem = &nf_hooks[pf][hook];
+next_hook:
+ verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
+ outdev, &elem, okfn, hook_thresh);
+ if (verdict == NF_ACCEPT || verdict == NF_STOP) {
+ ret = 1;
+ goto unlock;
+ } else if (verdict == NF_DROP) {
+ kfree_skb(*pskb);
+ ret = -EPERM;
+ } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
+ NFDEBUG("nf_hook: Verdict = QUEUE.\n");
+ if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
+ verdict >> NF_VERDICT_BITS))
+ goto next_hook;
+ }
+unlock:
+ rcu_read_unlock();
+ return ret;
+}
+EXPORT_SYMBOL(nf_hook_slow);
+
+
+int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+{
+ struct sk_buff *nskb;
+
+ if (writable_len > (*pskb)->len)
+ return 0;
+
+ /* Not exclusive use of packet? Must copy. */
+ if (skb_shared(*pskb) || skb_cloned(*pskb))
+ goto copy_skb;
+
+ return pskb_may_pull(*pskb, writable_len);
+
+copy_skb:
+ nskb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!nskb)
+ return 0;
+ BUG_ON(skb_is_nonlinear(nskb));
+
+ /* Rest of kernel will get very unhappy if we pass it a
+ suddenly-orphaned skbuff */
+ if ((*pskb)->sk)
+ skb_set_owner_w(nskb, (*pskb)->sk);
+ kfree_skb(*pskb);
+ *pskb = nskb;
+ return 1;
+}
+EXPORT_SYMBOL(skb_make_writable);
+
+
+/* This does not belong here, but locally generated errors need it if connection
+ tracking in use: without this, connection may not be in hash table, and hence
+ manufactured ICMP or RST packets will not be associated with it. */
+void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
+EXPORT_SYMBOL(ip_ct_attach);
+
+void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
+{
+ void (*attach)(struct sk_buff *, struct sk_buff *);
+
+ if (skb->nfct && (attach = ip_ct_attach) != NULL) {
+ mb(); /* Just to be sure: must be read before executing this */
+ attach(new, skb);
+ }
+}
+EXPORT_SYMBOL(nf_ct_attach);
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_net_netfilter;
+EXPORT_SYMBOL(proc_net_netfilter);
+#endif
+
+void __init netfilter_init(void)
+{
+ int i, h;
+ for (i = 0; i < NPROTO; i++) {
+ for (h = 0; h < NF_MAX_HOOKS; h++)
+ INIT_LIST_HEAD(&nf_hooks[i][h]);
+ }
+
+#ifdef CONFIG_PROC_FS
+ proc_net_netfilter = proc_mkdir("netfilter", proc_net);
+ if (!proc_net_netfilter)
+ panic("cannot create netfilter proc entry");
+#endif
+
+ if (netfilter_queue_init() < 0)
+ panic("cannot initialize nf_queue");
+ if (netfilter_log_init() < 0)
+ panic("cannot initialize nf_log");
+}
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
new file mode 100644
index 000000000000..6bdee2910617
--- /dev/null
+++ b/net/netfilter/nf_internals.h
@@ -0,0 +1,39 @@
+#ifndef _NF_INTERNALS_H
+#define _NF_INTERNALS_H
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define NFDEBUG(format, args...) printk(format , ## args)
+#else
+#define NFDEBUG(format, args...)
+#endif
+
+
+/* core.c */
+extern unsigned int nf_iterate(struct list_head *head,
+ struct sk_buff **skb,
+ int hook,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ struct list_head **i,
+ int (*okfn)(struct sk_buff *),
+ int hook_thresh);
+
+/* nf_queue.c */
+extern int nf_queue(struct sk_buff **skb,
+ struct list_head *elem,
+ int pf, unsigned int hook,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *),
+ unsigned int queuenum);
+extern int __init netfilter_queue_init(void);
+
+/* nf_log.c */
+extern int __init netfilter_log_init(void);
+
+#endif
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
new file mode 100644
index 000000000000..3e76bd0824a2
--- /dev/null
+++ b/net/netfilter/nf_log.c
@@ -0,0 +1,178 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <linux/seq_file.h>
+#include <net/protocol.h>
+
+#include "nf_internals.h"
+
+/* Internal logging interface, which relies on the real
+ LOG target modules */
+
+#define NF_LOG_PREFIXLEN 128
+
+static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
+static DEFINE_SPINLOCK(nf_log_lock);
+
+/* return EBUSY if somebody else is registered, EEXIST if the same logger
+ * is registred, 0 on success. */
+int nf_log_register(int pf, struct nf_logger *logger)
+{
+ int ret = -EBUSY;
+
+ if (pf >= NPROTO)
+ return -EINVAL;
+
+ /* Any setup of logging members must be done before
+ * substituting pointer. */
+ spin_lock(&nf_log_lock);
+ if (!nf_logging[pf]) {
+ rcu_assign_pointer(nf_logging[pf], logger);
+ ret = 0;
+ } else if (nf_logging[pf] == logger)
+ ret = -EEXIST;
+
+ spin_unlock(&nf_log_lock);
+ return ret;
+}
+EXPORT_SYMBOL(nf_log_register);
+
+int nf_log_unregister_pf(int pf)
+{
+ if (pf >= NPROTO)
+ return -EINVAL;
+
+ spin_lock(&nf_log_lock);
+ nf_logging[pf] = NULL;
+ spin_unlock(&nf_log_lock);
+
+ /* Give time to concurrent readers. */
+ synchronize_net();
+
+ return 0;
+}
+EXPORT_SYMBOL(nf_log_unregister_pf);
+
+void nf_log_unregister_logger(struct nf_logger *logger)
+{
+ int i;
+
+ spin_lock(&nf_log_lock);
+ for (i = 0; i < NPROTO; i++) {
+ if (nf_logging[i] == logger)
+ nf_logging[i] = NULL;
+ }
+ spin_unlock(&nf_log_lock);
+
+ synchronize_net();
+}
+EXPORT_SYMBOL(nf_log_unregister_logger);
+
+void nf_log_packet(int pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct nf_loginfo *loginfo,
+ const char *fmt, ...)
+{
+ va_list args;
+ char prefix[NF_LOG_PREFIXLEN];
+ struct nf_logger *logger;
+
+ rcu_read_lock();
+ logger = rcu_dereference(nf_logging[pf]);
+ if (logger) {
+ va_start(args, fmt);
+ vsnprintf(prefix, sizeof(prefix), fmt, args);
+ va_end(args);
+ /* We must read logging before nf_logfn[pf] */
+ logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
+ } else if (net_ratelimit()) {
+ printk(KERN_WARNING "nf_log_packet: can\'t log since "
+ "no backend logging module loaded in! Please either "
+ "load one, or disable logging explicitly\n");
+ }
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL(nf_log_packet);
+
+#ifdef CONFIG_PROC_FS
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+ rcu_read_lock();
+
+ if (*pos >= NPROTO)
+ return NULL;
+
+ return pos;
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ if (*pos >= NPROTO)
+ return NULL;
+
+ return pos;
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+ rcu_read_unlock();
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+ loff_t *pos = v;
+ const struct nf_logger *logger;
+
+ logger = rcu_dereference(nf_logging[*pos]);
+
+ if (!logger)
+ return seq_printf(s, "%2lld NONE\n", *pos);
+
+ return seq_printf(s, "%2lld %s\n", *pos, logger->name);
+}
+
+static struct seq_operations nflog_seq_ops = {
+ .start = seq_start,
+ .next = seq_next,
+ .stop = seq_stop,
+ .show = seq_show,
+};
+
+static int nflog_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &nflog_seq_ops);
+}
+
+static struct file_operations nflog_file_ops = {
+ .owner = THIS_MODULE,
+ .open = nflog_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+#endif /* PROC_FS */
+
+
+int __init netfilter_log_init(void)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *pde;
+
+ pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
+ if (!pde)
+ return -1;
+
+ pde->proc_fops = &nflog_file_ops;
+#endif
+ return 0;
+}
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
new file mode 100644
index 000000000000..d10d552d9c40
--- /dev/null
+++ b/net/netfilter/nf_queue.c
@@ -0,0 +1,343 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <linux/seq_file.h>
+#include <net/protocol.h>
+
+#include "nf_internals.h"
+
+/*
+ * A queue handler may be registered for each protocol. Each is protected by
+ * long term mutex. The handler must provide an an outfn() to accept packets
+ * 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;
+
+static DEFINE_RWLOCK(queue_handler_lock);
+
+/* return EBUSY when somebody else is registered, return EEXIST if the
+ * same handler is registered, return 0 in case of success. */
+int nf_register_queue_handler(int pf, struct nf_queue_handler *qh)
+{
+ int ret;
+
+ if (pf >= NPROTO)
+ return -EINVAL;
+
+ write_lock_bh(&queue_handler_lock);
+ if (queue_handler[pf] == qh)
+ ret = -EEXIST;
+ else if (queue_handler[pf])
+ ret = -EBUSY;
+ else {
+ queue_handler[pf] = qh;
+ ret = 0;
+ }
+ write_unlock_bh(&queue_handler_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(nf_register_queue_handler);
+
+/* The caller must flush their queue before this */
+int nf_unregister_queue_handler(int pf)
+{
+ if (pf >= NPROTO)
+ return -EINVAL;
+
+ write_lock_bh(&queue_handler_lock);
+ queue_handler[pf] = NULL;
+ write_unlock_bh(&queue_handler_lock);
+
+ return 0;
+}
+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);
+ memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf]));
+ 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);
+ memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf]));
+ write_unlock_bh(&queue_handler_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
+
+void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
+{
+ int pf;
+
+ write_lock_bh(&queue_handler_lock);
+ for (pf = 0; pf < NPROTO; pf++) {
+ if (queue_handler[pf] == qh)
+ queue_handler[pf] = NULL;
+ }
+ write_unlock_bh(&queue_handler_lock);
+}
+EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
+
+/*
+ * Any packet that leaves via this function must come back
+ * through nf_reinject().
+ */
+int nf_queue(struct sk_buff **skb,
+ struct list_head *elem,
+ int pf, unsigned int hook,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *),
+ unsigned int queuenum)
+{
+ int status;
+ struct nf_info *info;
+#ifdef CONFIG_BRIDGE_NETFILTER
+ struct net_device *physindev = NULL;
+ struct net_device *physoutdev = NULL;
+#endif
+
+ /* QUEUE == DROP if noone is waiting, to be safe. */
+ read_lock(&queue_handler_lock);
+ if (!queue_handler[pf]->outfn) {
+ read_unlock(&queue_handler_lock);
+ kfree_skb(*skb);
+ return 1;
+ }
+
+ info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC);
+ if (!info) {
+ if (net_ratelimit())
+ printk(KERN_ERR "OOM queueing packet %p\n",
+ *skb);
+ read_unlock(&queue_handler_lock);
+ kfree_skb(*skb);
+ return 1;
+ }
+
+ *info = (struct nf_info) {
+ (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
+
+ /* If it's going away, ignore hook. */
+ if (!try_module_get(info->elem->owner)) {
+ read_unlock(&queue_handler_lock);
+ kfree(info);
+ return 0;
+ }
+
+ /* Bump dev refs so they don't vanish while packet is out */
+ if (indev) dev_hold(indev);
+ if (outdev) dev_hold(outdev);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+ if ((*skb)->nf_bridge) {
+ physindev = (*skb)->nf_bridge->physindev;
+ if (physindev) dev_hold(physindev);
+ physoutdev = (*skb)->nf_bridge->physoutdev;
+ if (physoutdev) dev_hold(physoutdev);
+ }
+#endif
+ if (queue_rerouter[pf].save)
+ queue_rerouter[pf].save(*skb, info);
+
+ status = queue_handler[pf]->outfn(*skb, info, queuenum,
+ queue_handler[pf]->data);
+
+ if (status >= 0 && queue_rerouter[pf].reroute)
+ status = queue_rerouter[pf].reroute(skb, info);
+
+ read_unlock(&queue_handler_lock);
+
+ if (status < 0) {
+ /* James M doesn't say fuck enough. */
+ if (indev) dev_put(indev);
+ if (outdev) dev_put(outdev);
+#ifdef CONFIG_BRIDGE_NETFILTER
+ if (physindev) dev_put(physindev);
+ if (physoutdev) dev_put(physoutdev);
+#endif
+ module_put(info->elem->owner);
+ kfree(info);
+ kfree_skb(*skb);
+
+ return 1;
+ }
+
+ return 1;
+}
+
+void nf_reinject(struct sk_buff *skb, struct nf_info *info,
+ unsigned int verdict)
+{
+ struct list_head *elem = &info->elem->list;
+ struct list_head *i;
+
+ rcu_read_lock();
+
+ /* Release those devices we held, or Alexey will kill me. */
+ if (info->indev) dev_put(info->indev);
+ if (info->outdev) dev_put(info->outdev);
+#ifdef CONFIG_BRIDGE_NETFILTER
+ if (skb->nf_bridge) {
+ if (skb->nf_bridge->physindev)
+ dev_put(skb->nf_bridge->physindev);
+ if (skb->nf_bridge->physoutdev)
+ dev_put(skb->nf_bridge->physoutdev);
+ }
+#endif
+
+ /* Drop reference to owner of hook which queued us. */
+ module_put(info->elem->owner);
+
+ list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
+ if (i == elem)
+ break;
+ }
+
+ if (elem == &nf_hooks[info->pf][info->hook]) {
+ /* The module which sent it to userspace is gone. */
+ NFDEBUG("%s: module disappeared, dropping packet.\n",
+ __FUNCTION__);
+ verdict = NF_DROP;
+ }
+
+ /* Continue traversal iff userspace said ok... */
+ if (verdict == NF_REPEAT) {
+ elem = elem->prev;
+ verdict = NF_ACCEPT;
+ }
+
+ if (verdict == NF_ACCEPT) {
+ next_hook:
+ verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
+ &skb, info->hook,
+ info->indev, info->outdev, &elem,
+ info->okfn, INT_MIN);
+ }
+
+ switch (verdict & NF_VERDICT_MASK) {
+ case NF_ACCEPT:
+ info->okfn(skb);
+ break;
+
+ case NF_QUEUE:
+ if (!nf_queue(&skb, elem, info->pf, info->hook,
+ info->indev, info->outdev, info->okfn,
+ verdict >> NF_VERDICT_BITS))
+ goto next_hook;
+ break;
+ }
+ rcu_read_unlock();
+
+ if (verdict == NF_DROP)
+ kfree_skb(skb);
+
+ kfree(info);
+ return;
+}
+EXPORT_SYMBOL(nf_reinject);
+
+#ifdef CONFIG_PROC_FS
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos >= NPROTO)
+ return NULL;
+
+ return pos;
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ if (*pos >= NPROTO)
+ return NULL;
+
+ return pos;
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+ int ret;
+ loff_t *pos = v;
+ struct nf_queue_handler *qh;
+
+ read_lock_bh(&queue_handler_lock);
+ qh = queue_handler[*pos];
+ if (!qh)
+ ret = seq_printf(s, "%2lld NONE\n", *pos);
+ else
+ ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
+ read_unlock_bh(&queue_handler_lock);
+
+ return ret;
+}
+
+static struct seq_operations nfqueue_seq_ops = {
+ .start = seq_start,
+ .next = seq_next,
+ .stop = seq_stop,
+ .show = seq_show,
+};
+
+static int nfqueue_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &nfqueue_seq_ops);
+}
+
+static struct file_operations nfqueue_file_ops = {
+ .owner = THIS_MODULE,
+ .open = nfqueue_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif /* PROC_FS */
+
+
+int __init netfilter_queue_init(void)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *pde;
+#endif
+ queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
+ GFP_KERNEL);
+ if (!queue_rerouter)
+ return -ENOMEM;
+
+#ifdef CONFIG_PROC_FS
+ pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
+ if (!pde) {
+ kfree(queue_rerouter);
+ return -1;
+ }
+ pde->proc_fops = &nfqueue_file_ops;
+#endif
+ memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
+
+ return 0;
+}
+
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
new file mode 100644
index 000000000000..61a833a9caa6
--- /dev/null
+++ b/net/netfilter/nf_sockopt.c
@@ -0,0 +1,132 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/sock.h>
+
+#include "nf_internals.h"
+
+/* Sockopts only registered and called from user context, so
+ net locking would be overkill. Also, [gs]etsockopt calls may
+ sleep. */
+static DECLARE_MUTEX(nf_sockopt_mutex);
+static LIST_HEAD(nf_sockopts);
+
+/* Do exclusive ranges overlap? */
+static inline int overlap(int min1, int max1, int min2, int max2)
+{
+ return max1 > min2 && min1 < max2;
+}
+
+/* Functions to register sockopt ranges (exclusive). */
+int nf_register_sockopt(struct nf_sockopt_ops *reg)
+{
+ struct list_head *i;
+ int ret = 0;
+
+ if (down_interruptible(&nf_sockopt_mutex) != 0)
+ return -EINTR;
+
+ list_for_each(i, &nf_sockopts) {
+ struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
+ if (ops->pf == reg->pf
+ && (overlap(ops->set_optmin, ops->set_optmax,
+ reg->set_optmin, reg->set_optmax)
+ || overlap(ops->get_optmin, ops->get_optmax,
+ reg->get_optmin, reg->get_optmax))) {
+ NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
+ ops->set_optmin, ops->set_optmax,
+ ops->get_optmin, ops->get_optmax,
+ reg->set_optmin, reg->set_optmax,
+ reg->get_optmin, reg->get_optmax);
+ ret = -EBUSY;
+ goto out;
+ }
+ }
+
+ list_add(&reg->list, &nf_sockopts);
+out:
+ up(&nf_sockopt_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(nf_register_sockopt);
+
+void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
+{
+ /* No point being interruptible: we're probably in cleanup_module() */
+ restart:
+ down(&nf_sockopt_mutex);
+ if (reg->use != 0) {
+ /* To be woken by nf_sockopt call... */
+ /* FIXME: Stuart Young's name appears gratuitously. */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ reg->cleanup_task = current;
+ up(&nf_sockopt_mutex);
+ schedule();
+ goto restart;
+ }
+ list_del(&reg->list);
+ up(&nf_sockopt_mutex);
+}
+EXPORT_SYMBOL(nf_unregister_sockopt);
+
+/* Call get/setsockopt() */
+static int nf_sockopt(struct sock *sk, int pf, int val,
+ char __user *opt, int *len, int get)
+{
+ struct list_head *i;
+ struct nf_sockopt_ops *ops;
+ int ret;
+
+ if (down_interruptible(&nf_sockopt_mutex) != 0)
+ return -EINTR;
+
+ list_for_each(i, &nf_sockopts) {
+ ops = (struct nf_sockopt_ops *)i;
+ if (ops->pf == pf) {
+ if (get) {
+ if (val >= ops->get_optmin
+ && val < ops->get_optmax) {
+ ops->use++;
+ up(&nf_sockopt_mutex);
+ ret = ops->get(sk, val, opt, len);
+ goto out;
+ }
+ } else {
+ if (val >= ops->set_optmin
+ && val < ops->set_optmax) {
+ ops->use++;
+ up(&nf_sockopt_mutex);
+ ret = ops->set(sk, val, opt, *len);
+ goto out;
+ }
+ }
+ }
+ }
+ up(&nf_sockopt_mutex);
+ return -ENOPROTOOPT;
+
+ out:
+ down(&nf_sockopt_mutex);
+ ops->use--;
+ if (ops->cleanup_task)
+ wake_up_process(ops->cleanup_task);
+ up(&nf_sockopt_mutex);
+ return ret;
+}
+
+int nf_setsockopt(struct sock *sk, int pf, int val, char __user *opt,
+ int len)
+{
+ return nf_sockopt(sk, pf, val, opt, &len, 0);
+}
+EXPORT_SYMBOL(nf_setsockopt);
+
+int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
+{
+ return nf_sockopt(sk, pf, val, opt, len, 1);
+}
+EXPORT_SYMBOL(nf_getsockopt);
+
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
new file mode 100644
index 000000000000..49a3900e3d32
--- /dev/null
+++ b/net/netfilter/nfnetlink.c
@@ -0,0 +1,376 @@
+/* Netfilter messages via netlink socket. Allows for user space
+ * protocol helpers and general trouble making from userspace.
+ *
+ * (C) 2001 by Jay Schulist <jschlst@samba.org>,
+ * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ *
+ * Initial netfilter messages via netlink development funded and
+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
+ *
+ * Further development of this code funded by Astaro AG (http://www.astaro.com)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/fcntl.h>
+#include <linux/skbuff.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <net/sock.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <linux/netfilter.h>
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
+
+static char __initdata nfversion[] = "0.30";
+
+#if 0
+#define DEBUGP(format, args...) \
+ printk(KERN_DEBUG "%s(%d):%s(): " format, __FILE__, \
+ __LINE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static struct sock *nfnl = NULL;
+static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
+DECLARE_MUTEX(nfnl_sem);
+
+void nfnl_lock(void)
+{
+ nfnl_shlock();
+}
+
+void nfnl_unlock(void)
+{
+ nfnl_shunlock();
+}
+
+int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
+{
+ DEBUGP("registering subsystem ID %u\n", n->subsys_id);
+
+ nfnl_lock();
+ if (subsys_table[n->subsys_id]) {
+ nfnl_unlock();
+ return -EBUSY;
+ }
+ subsys_table[n->subsys_id] = n;
+ nfnl_unlock();
+
+ return 0;
+}
+
+int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
+{
+ DEBUGP("unregistering subsystem ID %u\n", n->subsys_id);
+
+ nfnl_lock();
+ subsys_table[n->subsys_id] = NULL;
+ nfnl_unlock();
+
+ return 0;
+}
+
+static inline struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
+{
+ u_int8_t subsys_id = NFNL_SUBSYS_ID(type);
+
+ if (subsys_id >= NFNL_SUBSYS_COUNT
+ || subsys_table[subsys_id] == NULL)
+ return NULL;
+
+ return subsys_table[subsys_id];
+}
+
+static inline struct nfnl_callback *
+nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
+{
+ u_int8_t cb_id = NFNL_MSG_TYPE(type);
+
+ if (cb_id >= ss->cb_count) {
+ DEBUGP("msgtype %u >= %u, returning\n", type, ss->cb_count);
+ return NULL;
+ }
+
+ return &ss->cb[cb_id];
+}
+
+void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
+ const void *data)
+{
+ struct nfattr *nfa;
+ int size = NFA_LENGTH(attrlen);
+
+ nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
+ nfa->nfa_type = attrtype;
+ nfa->nfa_len = size;
+ memcpy(NFA_DATA(nfa), data, attrlen);
+ memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size);
+}
+
+int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
+{
+ memset(tb, 0, sizeof(struct nfattr *) * maxattr);
+
+ while (NFA_OK(nfa, len)) {
+ unsigned flavor = nfa->nfa_type;
+ if (flavor && flavor <= maxattr)
+ tb[flavor-1] = nfa;
+ nfa = NFA_NEXT(nfa, len);
+ }
+
+ return 0;
+}
+
+/**
+ * nfnetlink_check_attributes - check and parse nfnetlink attributes
+ *
+ * subsys: nfnl subsystem for which this message is to be parsed
+ * nlmsghdr: netlink message to be checked/parsed
+ * cda: array of pointers, needs to be at least subsys->attr_count big
+ *
+ */
+static int
+nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
+ struct nlmsghdr *nlh, struct nfattr *cda[])
+{
+ int min_len;
+ u_int16_t attr_count;
+ u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
+
+ if (unlikely(cb_id >= subsys->cb_count)) {
+ DEBUGP("msgtype %u >= %u, returning\n",
+ cb_id, subsys->cb_count);
+ return -EINVAL;
+ }
+
+ min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
+ if (unlikely(nlh->nlmsg_len < min_len))
+ return -EINVAL;
+
+ attr_count = subsys->cb[cb_id].attr_count;
+ memset(cda, 0, sizeof(struct nfattr *) * attr_count);
+
+ /* check attribute lengths. */
+ if (likely(nlh->nlmsg_len > min_len)) {
+ struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
+ int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
+
+ while (NFA_OK(attr, attrlen)) {
+ unsigned flavor = attr->nfa_type;
+ if (flavor) {
+ if (flavor > attr_count)
+ return -EINVAL;
+ cda[flavor - 1] = attr;
+ }
+ attr = NFA_NEXT(attr, attrlen);
+ }
+ }
+
+ /* implicit: if nlmsg_len == min_len, we return 0, and an empty
+ * (zeroed) cda[] array. The message is valid, but empty. */
+
+ return 0;
+}
+
+int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
+{
+ int allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ int err = 0;
+
+ NETLINK_CB(skb).dst_group = group;
+ if (echo)
+ atomic_inc(&skb->users);
+ netlink_broadcast(nfnl, skb, pid, group, allocation);
+ if (echo)
+ err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
+
+ return err;
+}
+
+int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags)
+{
+ return netlink_unicast(nfnl, skb, pid, flags);
+}
+
+/* Process one complete nfnetlink message. */
+static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
+ struct nlmsghdr *nlh, int *errp)
+{
+ struct nfnl_callback *nc;
+ struct nfnetlink_subsystem *ss;
+ int type, err = 0;
+
+ DEBUGP("entered; subsys=%u, msgtype=%u\n",
+ NFNL_SUBSYS_ID(nlh->nlmsg_type),
+ NFNL_MSG_TYPE(nlh->nlmsg_type));
+
+ /* Only requests are handled by kernel now. */
+ if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
+ DEBUGP("received non-request message\n");
+ return 0;
+ }
+
+ /* All the messages must at least contain nfgenmsg */
+ if (nlh->nlmsg_len <
+ NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) {
+ DEBUGP("received message was too short\n");
+ return 0;
+ }
+
+ type = nlh->nlmsg_type;
+ ss = nfnetlink_get_subsys(type);
+ if (!ss) {
+#ifdef CONFIG_KMOD
+ /* don't call nfnl_shunlock, since it would reenter
+ * with further packet processing */
+ up(&nfnl_sem);
+ request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
+ nfnl_shlock();
+ ss = nfnetlink_get_subsys(type);
+ if (!ss)
+#endif
+ goto err_inval;
+ }
+
+ nc = nfnetlink_find_client(type, ss);
+ if (!nc) {
+ DEBUGP("unable to find client for type %d\n", type);
+ goto err_inval;
+ }
+
+ if (nc->cap_required &&
+ !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) {
+ DEBUGP("permission denied for type %d\n", type);
+ *errp = -EPERM;
+ return -1;
+ }
+
+ {
+ u_int16_t attr_count =
+ ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
+ struct nfattr *cda[attr_count];
+
+ memset(cda, 0, sizeof(struct nfattr *) * attr_count);
+
+ err = nfnetlink_check_attributes(ss, nlh, cda);
+ if (err < 0)
+ goto err_inval;
+
+ DEBUGP("calling handler\n");
+ err = nc->call(nfnl, skb, nlh, cda, errp);
+ *errp = err;
+ return err;
+ }
+
+err_inval:
+ DEBUGP("returning -EINVAL\n");
+ *errp = -EINVAL;
+ return -1;
+}
+
+/* Process one packet of messages. */
+static inline int nfnetlink_rcv_skb(struct sk_buff *skb)
+{
+ int err;
+ struct nlmsghdr *nlh;
+
+ while (skb->len >= NLMSG_SPACE(0)) {
+ u32 rlen;
+
+ nlh = (struct nlmsghdr *)skb->data;
+ if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
+ || skb->len < nlh->nlmsg_len)
+ return 0;
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+ if (nfnetlink_rcv_msg(skb, nlh, &err)) {
+ if (!err)
+ return -1;
+ netlink_ack(skb, nlh, err);
+ } else
+ if (nlh->nlmsg_flags & NLM_F_ACK)
+ netlink_ack(skb, nlh, 0);
+ skb_pull(skb, rlen);
+ }
+
+ return 0;
+}
+
+static void nfnetlink_rcv(struct sock *sk, int len)
+{
+ do {
+ struct sk_buff *skb;
+
+ if (nfnl_shlock_nowait())
+ return;
+
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (nfnetlink_rcv_skb(skb)) {
+ if (skb->len)
+ skb_queue_head(&sk->sk_receive_queue,
+ skb);
+ else
+ kfree_skb(skb);
+ break;
+ }
+ kfree_skb(skb);
+ }
+
+ /* don't call nfnl_shunlock, since it would reenter
+ * with further packet processing */
+ up(&nfnl_sem);
+ } while(nfnl && nfnl->sk_receive_queue.qlen);
+}
+
+static void __exit nfnetlink_exit(void)
+{
+ printk("Removing netfilter NETLINK layer.\n");
+ sock_release(nfnl->sk_socket);
+ return;
+}
+
+static int __init nfnetlink_init(void)
+{
+ printk("Netfilter messages via NETLINK v%s.\n", nfversion);
+
+ nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
+ nfnetlink_rcv, THIS_MODULE);
+ if (!nfnl) {
+ printk(KERN_ERR "cannot initialize nfnetlink!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+module_init(nfnetlink_init);
+module_exit(nfnetlink_exit);
+
+EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
+EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
+EXPORT_SYMBOL_GPL(nfnetlink_send);
+EXPORT_SYMBOL_GPL(nfnetlink_unicast);
+EXPORT_SYMBOL_GPL(nfattr_parse);
+EXPORT_SYMBOL_GPL(__nfa_fill);
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
new file mode 100644
index 000000000000..ff5601ceedcb
--- /dev/null
+++ b/net/netfilter/nfnetlink_log.c
@@ -0,0 +1,1055 @@
+/*
+ * This is a module which is used for logging packets to userspace via
+ * nfetlink.
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * Based on the old ipv4-only ipt_ULOG.c:
+ * (C) 2000-2004 by Harald Welte <laforge@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/skbuff.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/spinlock.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/random.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+#include "../bridge/br_private.h"
+#endif
+
+#define NFULNL_NLBUFSIZ_DEFAULT 4096
+#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
+#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
+
+#define PRINTR(x, args...) do { if (net_ratelimit()) \
+ printk(x, ## args); } while (0);
+
+#if 0
+#define UDEBUG(x, args ...) printk(KERN_DEBUG "%s(%d):%s(): " x, \
+ __FILE__, __LINE__, __FUNCTION__, \
+ ## args)
+#else
+#define UDEBUG(x, ...)
+#endif
+
+struct nfulnl_instance {
+ struct hlist_node hlist; /* global list of instances */
+ spinlock_t lock;
+ atomic_t use; /* use count */
+
+ unsigned int qlen; /* number of nlmsgs in skb */
+ struct sk_buff *skb; /* pre-allocatd skb */
+ struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */
+ struct timer_list timer;
+ int peer_pid; /* PID of the peer process */
+
+ /* configurable parameters */
+ unsigned int flushtimeout; /* timeout until queue flush */
+ unsigned int nlbufsiz; /* netlink buffer allocation size */
+ unsigned int qthreshold; /* threshold of the queue */
+ u_int32_t copy_range;
+ u_int16_t group_num; /* number of this queue */
+ u_int8_t copy_mode;
+};
+
+static DEFINE_RWLOCK(instances_lock);
+
+#define INSTANCE_BUCKETS 16
+static struct hlist_head instance_table[INSTANCE_BUCKETS];
+static unsigned int hash_init;
+
+static inline u_int8_t instance_hashfn(u_int16_t group_num)
+{
+ return ((group_num & 0xff) % INSTANCE_BUCKETS);
+}
+
+static struct nfulnl_instance *
+__instance_lookup(u_int16_t group_num)
+{
+ struct hlist_head *head;
+ struct hlist_node *pos;
+ struct nfulnl_instance *inst;
+
+ UDEBUG("entering (group_num=%u)\n", group_num);
+
+ head = &instance_table[instance_hashfn(group_num)];
+ hlist_for_each_entry(inst, pos, head, hlist) {
+ if (inst->group_num == group_num)
+ return inst;
+ }
+ return NULL;
+}
+
+static inline void
+instance_get(struct nfulnl_instance *inst)
+{
+ atomic_inc(&inst->use);
+}
+
+static struct nfulnl_instance *
+instance_lookup_get(u_int16_t group_num)
+{
+ struct nfulnl_instance *inst;
+
+ read_lock_bh(&instances_lock);
+ inst = __instance_lookup(group_num);
+ if (inst)
+ instance_get(inst);
+ read_unlock_bh(&instances_lock);
+
+ return inst;
+}
+
+static void
+instance_put(struct nfulnl_instance *inst)
+{
+ if (inst && atomic_dec_and_test(&inst->use)) {
+ UDEBUG("kfree(inst=%p)\n", inst);
+ kfree(inst);
+ }
+}
+
+static void nfulnl_timer(unsigned long data);
+
+static struct nfulnl_instance *
+instance_create(u_int16_t group_num, int pid)
+{
+ struct nfulnl_instance *inst;
+
+ UDEBUG("entering (group_num=%u, pid=%d)\n", group_num,
+ pid);
+
+ write_lock_bh(&instances_lock);
+ if (__instance_lookup(group_num)) {
+ inst = NULL;
+ UDEBUG("aborting, instance already exists\n");
+ goto out_unlock;
+ }
+
+ inst = kmalloc(sizeof(*inst), GFP_ATOMIC);
+ if (!inst)
+ goto out_unlock;
+
+ memset(inst, 0, sizeof(*inst));
+ INIT_HLIST_NODE(&inst->hlist);
+ inst->lock = SPIN_LOCK_UNLOCKED;
+ /* needs to be two, since we _put() after creation */
+ atomic_set(&inst->use, 2);
+
+ init_timer(&inst->timer);
+ inst->timer.function = nfulnl_timer;
+ inst->timer.data = (unsigned long)inst;
+ /* don't start timer yet. (re)start it with every packet */
+
+ inst->peer_pid = pid;
+ inst->group_num = group_num;
+
+ inst->qthreshold = NFULNL_QTHRESH_DEFAULT;
+ inst->flushtimeout = NFULNL_TIMEOUT_DEFAULT;
+ inst->nlbufsiz = NFULNL_NLBUFSIZ_DEFAULT;
+ inst->copy_mode = NFULNL_COPY_PACKET;
+ inst->copy_range = 0xffff;
+
+ if (!try_module_get(THIS_MODULE))
+ goto out_free;
+
+ hlist_add_head(&inst->hlist,
+ &instance_table[instance_hashfn(group_num)]);
+
+ UDEBUG("newly added node: %p, next=%p\n", &inst->hlist,
+ inst->hlist.next);
+
+ write_unlock_bh(&instances_lock);
+
+ return inst;
+
+out_free:
+ instance_put(inst);
+out_unlock:
+ write_unlock_bh(&instances_lock);
+ return NULL;
+}
+
+static int __nfulnl_send(struct nfulnl_instance *inst);
+
+static void
+_instance_destroy2(struct nfulnl_instance *inst, int lock)
+{
+ /* first pull it out of the global list */
+ if (lock)
+ write_lock_bh(&instances_lock);
+
+ UDEBUG("removing instance %p (queuenum=%u) from hash\n",
+ inst, inst->group_num);
+
+ hlist_del(&inst->hlist);
+
+ if (lock)
+ write_unlock_bh(&instances_lock);
+
+ /* then flush all pending packets from skb */
+
+ spin_lock_bh(&inst->lock);
+ if (inst->skb) {
+ if (inst->qlen)
+ __nfulnl_send(inst);
+ if (inst->skb) {
+ kfree_skb(inst->skb);
+ inst->skb = NULL;
+ }
+ }
+ spin_unlock_bh(&inst->lock);
+
+ /* and finally put the refcount */
+ instance_put(inst);
+
+ module_put(THIS_MODULE);
+}
+
+static inline void
+__instance_destroy(struct nfulnl_instance *inst)
+{
+ _instance_destroy2(inst, 0);
+}
+
+static inline void
+instance_destroy(struct nfulnl_instance *inst)
+{
+ _instance_destroy2(inst, 1);
+}
+
+static int
+nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
+ unsigned int range)
+{
+ int status = 0;
+
+ spin_lock_bh(&inst->lock);
+
+ switch (mode) {
+ case NFULNL_COPY_NONE:
+ case NFULNL_COPY_META:
+ inst->copy_mode = mode;
+ inst->copy_range = 0;
+ break;
+
+ case NFULNL_COPY_PACKET:
+ inst->copy_mode = mode;
+ /* we're using struct nfattr which has 16bit nfa_len */
+ if (range > 0xffff)
+ inst->copy_range = 0xffff;
+ else
+ inst->copy_range = range;
+ break;
+
+ default:
+ status = -EINVAL;
+ break;
+ }
+
+ spin_unlock_bh(&inst->lock);
+
+ return status;
+}
+
+static int
+nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz)
+{
+ int status;
+
+ spin_lock_bh(&inst->lock);
+ if (nlbufsiz < NFULNL_NLBUFSIZ_DEFAULT)
+ status = -ERANGE;
+ else if (nlbufsiz > 131072)
+ status = -ERANGE;
+ else {
+ inst->nlbufsiz = nlbufsiz;
+ status = 0;
+ }
+ spin_unlock_bh(&inst->lock);
+
+ return status;
+}
+
+static int
+nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout)
+{
+ spin_lock_bh(&inst->lock);
+ inst->flushtimeout = timeout;
+ spin_unlock_bh(&inst->lock);
+
+ return 0;
+}
+
+static int
+nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
+{
+ spin_lock_bh(&inst->lock);
+ inst->qthreshold = qthresh;
+ spin_unlock_bh(&inst->lock);
+
+ return 0;
+}
+
+static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
+ unsigned int pkt_size)
+{
+ struct sk_buff *skb;
+
+ UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
+
+ /* alloc skb which should be big enough for a whole multipart
+ * message. WARNING: has to be <= 128k due to slab restrictions */
+
+ skb = alloc_skb(inst_size, GFP_ATOMIC);
+ if (!skb) {
+ PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n",
+ inst_size);
+
+ /* try to allocate only as much as we need for current
+ * packet */
+
+ skb = alloc_skb(pkt_size, GFP_ATOMIC);
+ if (!skb)
+ PRINTR("nfnetlink_log: can't even alloc %u bytes\n",
+ pkt_size);
+ }
+
+ return skb;
+}
+
+static int
+__nfulnl_send(struct nfulnl_instance *inst)
+{
+ int status;
+
+ if (timer_pending(&inst->timer))
+ del_timer(&inst->timer);
+
+ if (inst->qlen > 1)
+ inst->lastnlh->nlmsg_type = NLMSG_DONE;
+
+ status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
+ if (status < 0) {
+ UDEBUG("netlink_unicast() failed\n");
+ /* FIXME: statistics */
+ }
+
+ inst->qlen = 0;
+ inst->skb = NULL;
+ inst->lastnlh = NULL;
+
+ return status;
+}
+
+static void nfulnl_timer(unsigned long data)
+{
+ struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
+
+ UDEBUG("timer function called, flushing buffer\n");
+
+ spin_lock_bh(&inst->lock);
+ __nfulnl_send(inst);
+ instance_put(inst);
+ spin_unlock_bh(&inst->lock);
+}
+
+static inline int
+__build_packet_message(struct nfulnl_instance *inst,
+ const struct sk_buff *skb,
+ unsigned int data_len,
+ unsigned int pf,
+ unsigned int hooknum,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ const struct nf_loginfo *li,
+ const char *prefix)
+{
+ unsigned char *old_tail;
+ struct nfulnl_msg_packet_hdr pmsg;
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ u_int32_t tmp_uint;
+
+ UDEBUG("entered\n");
+
+ old_tail = inst->skb->tail;
+ nlh = NLMSG_PUT(inst->skb, 0, 0,
+ NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
+ sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+ nfmsg->nfgen_family = pf;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = htons(inst->group_num);
+
+ pmsg.hw_protocol = htons(skb->protocol);
+ pmsg.hook = hooknum;
+
+ NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
+
+ if (prefix) {
+ int slen = strlen(prefix);
+ if (slen > NFULNL_PREFIXLEN)
+ slen = NFULNL_PREFIXLEN;
+ NFA_PUT(inst->skb, NFULA_PREFIX, slen, prefix);
+ }
+
+ if (indev) {
+ tmp_uint = htonl(indev->ifindex);
+#ifndef CONFIG_BRIDGE_NETFILTER
+ NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
+ &tmp_uint);
+#else
+ if (pf == PF_BRIDGE) {
+ /* Case 1: outdev is physical input device, we need to
+ * look for bridge group (when called from
+ * netfilter_bridge) */
+ NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ /* this is the bridge group "brX" */
+ tmp_uint = htonl(indev->br_port->br->dev->ifindex);
+ NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ } else {
+ /* Case 2: indev is bridge group, we need to look for
+ * physical device (when called from ipv4) */
+ NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ if (skb->nf_bridge && skb->nf_bridge->physindev) {
+ tmp_uint =
+ htonl(skb->nf_bridge->physindev->ifindex);
+ NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ }
+ }
+#endif
+ }
+
+ if (outdev) {
+ tmp_uint = htonl(outdev->ifindex);
+#ifndef CONFIG_BRIDGE_NETFILTER
+ NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ &tmp_uint);
+#else
+ if (pf == PF_BRIDGE) {
+ /* Case 1: outdev is physical output device, we need to
+ * look for bridge group (when called from
+ * netfilter_bridge) */
+ NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ /* this is the bridge group "brX" */
+ tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
+ NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ } else {
+ /* Case 2: indev is a bridge group, we need to look
+ * for physical device (when called from ipv4) */
+ NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ if (skb->nf_bridge) {
+ tmp_uint =
+ htonl(skb->nf_bridge->physoutdev->ifindex);
+ NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ }
+ }
+#endif
+ }
+
+ if (skb->nfmark) {
+ tmp_uint = htonl(skb->nfmark);
+ NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
+ }
+
+ if (indev && skb->dev && skb->dev->hard_header_parse) {
+ struct nfulnl_msg_packet_hw phw;
+
+ phw.hw_addrlen =
+ skb->dev->hard_header_parse((struct sk_buff *)skb,
+ phw.hw_addr);
+ phw.hw_addrlen = htons(phw.hw_addrlen);
+ NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+ }
+
+ if (skb->tstamp.off_sec) {
+ struct nfulnl_msg_packet_timestamp ts;
+
+ ts.sec = cpu_to_be64(skb_tv_base.tv_sec + skb->tstamp.off_sec);
+ ts.usec = cpu_to_be64(skb_tv_base.tv_usec + skb->tstamp.off_usec);
+
+ NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
+ }
+
+ /* UID */
+ if (skb->sk) {
+ read_lock_bh(&skb->sk->sk_callback_lock);
+ if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
+ u_int32_t uid = htonl(skb->sk->sk_socket->file->f_uid);
+ /* need to unlock here since NFA_PUT may goto */
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ NFA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
+ } else
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ }
+
+ if (data_len) {
+ struct nfattr *nfa;
+ int size = NFA_LENGTH(data_len);
+
+ if (skb_tailroom(inst->skb) < (int)NFA_SPACE(data_len)) {
+ printk(KERN_WARNING "nfnetlink_log: no tailroom!\n");
+ goto nlmsg_failure;
+ }
+
+ nfa = (struct nfattr *)skb_put(inst->skb, NFA_ALIGN(size));
+ nfa->nfa_type = NFULA_PAYLOAD;
+ nfa->nfa_len = size;
+
+ if (skb_copy_bits(skb, 0, NFA_DATA(nfa), data_len))
+ BUG();
+ }
+
+ nlh->nlmsg_len = inst->skb->tail - old_tail;
+ return 0;
+
+nlmsg_failure:
+ UDEBUG("nlmsg_failure\n");
+nfattr_failure:
+ PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
+ return -1;
+}
+
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
+
+static struct nf_loginfo default_loginfo = {
+ .type = NF_LOG_TYPE_ULOG,
+ .u = {
+ .ulog = {
+ .copy_len = 0xffff,
+ .group = 0,
+ .qthreshold = 1,
+ },
+ },
+};
+
+/* log handler for internal netfilter logging api */
+static void
+nfulnl_log_packet(unsigned int pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li_user,
+ const char *prefix)
+{
+ unsigned int size, data_len;
+ struct nfulnl_instance *inst;
+ const struct nf_loginfo *li;
+ unsigned int qthreshold;
+ unsigned int nlbufsiz;
+
+ if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
+ li = li_user;
+ else
+ li = &default_loginfo;
+
+ inst = instance_lookup_get(li->u.ulog.group);
+ if (!inst)
+ inst = instance_lookup_get(0);
+ if (!inst) {
+ PRINTR("nfnetlink_log: trying to log packet, "
+ "but no instance for group %u\n", li->u.ulog.group);
+ return;
+ }
+
+ /* all macros expand to constant values at compile time */
+ /* FIXME: do we want to make the size calculation conditional based on
+ * what is actually present? way more branches and checks, but more
+ * memory efficient... */
+ size = NLMSG_SPACE(sizeof(struct nfgenmsg))
+ + NFA_SPACE(sizeof(struct nfulnl_msg_packet_hdr))
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+#ifdef CONFIG_BRIDGE_NETFILTER
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+#endif
+ + NFA_SPACE(sizeof(u_int32_t)) /* mark */
+ + NFA_SPACE(sizeof(u_int32_t)) /* uid */
+ + NFA_SPACE(NFULNL_PREFIXLEN) /* prefix */
+ + NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw))
+ + NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp));
+
+ UDEBUG("initial size=%u\n", size);
+
+ spin_lock_bh(&inst->lock);
+
+ qthreshold = inst->qthreshold;
+ /* per-rule qthreshold overrides per-instance */
+ if (qthreshold > li->u.ulog.qthreshold)
+ qthreshold = li->u.ulog.qthreshold;
+
+ switch (inst->copy_mode) {
+ case NFULNL_COPY_META:
+ case NFULNL_COPY_NONE:
+ data_len = 0;
+ break;
+
+ case NFULNL_COPY_PACKET:
+ if (inst->copy_range == 0
+ || inst->copy_range > skb->len)
+ data_len = skb->len;
+ else
+ data_len = inst->copy_range;
+
+ size += NFA_SPACE(data_len);
+ UDEBUG("copy_packet, therefore size now %u\n", size);
+ break;
+
+ default:
+ spin_unlock_bh(&inst->lock);
+ instance_put(inst);
+ return;
+ }
+
+ if (size > inst->nlbufsiz)
+ nlbufsiz = size;
+ else
+ nlbufsiz = inst->nlbufsiz;
+
+ if (!inst->skb) {
+ if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) {
+ UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n",
+ inst->nlbufsiz, size);
+ goto alloc_failure;
+ }
+ } else if (inst->qlen >= qthreshold ||
+ size > skb_tailroom(inst->skb)) {
+ /* either the queue len is too high or we don't have
+ * enough room in the skb left. flush to userspace. */
+ UDEBUG("flushing old skb\n");
+
+ __nfulnl_send(inst);
+
+ if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) {
+ UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n",
+ inst->nlbufsiz, size);
+ goto alloc_failure;
+ }
+ }
+
+ UDEBUG("qlen %d, qthreshold %d\n", inst->qlen, qthreshold);
+ inst->qlen++;
+
+ __build_packet_message(inst, skb, data_len, pf,
+ hooknum, in, out, li, prefix);
+
+ /* timer_pending always called within inst->lock, so there
+ * is no chance of a race here */
+ if (!timer_pending(&inst->timer)) {
+ instance_get(inst);
+ inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
+ add_timer(&inst->timer);
+ }
+ spin_unlock_bh(&inst->lock);
+
+ return;
+
+alloc_failure:
+ spin_unlock_bh(&inst->lock);
+ instance_put(inst);
+ UDEBUG("error allocating skb\n");
+ /* FIXME: statistics */
+}
+
+static int
+nfulnl_rcv_nl_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netlink_notify *n = ptr;
+
+ if (event == NETLINK_URELEASE &&
+ n->protocol == NETLINK_NETFILTER && n->pid) {
+ int i;
+
+ /* destroy all instances for this pid */
+ write_lock_bh(&instances_lock);
+ for (i = 0; i < INSTANCE_BUCKETS; i++) {
+ struct hlist_node *tmp, *t2;
+ struct nfulnl_instance *inst;
+ struct hlist_head *head = &instance_table[i];
+
+ hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
+ UDEBUG("node = %p\n", inst);
+ if (n->pid == inst->peer_pid)
+ __instance_destroy(inst);
+ }
+ }
+ write_unlock_bh(&instances_lock);
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nfulnl_rtnl_notifier = {
+ .notifier_call = nfulnl_rcv_nl_event,
+};
+
+static int
+nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
+{
+ return -ENOTSUPP;
+}
+
+static struct nf_logger nfulnl_logger = {
+ .name = "nfnetlink_log",
+ .logfn = &nfulnl_log_packet,
+ .me = THIS_MODULE,
+};
+
+static const int nfula_min[NFULA_MAX] = {
+ [NFULA_PACKET_HDR-1] = sizeof(struct nfulnl_msg_packet_hdr),
+ [NFULA_MARK-1] = sizeof(u_int32_t),
+ [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp),
+ [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t),
+ [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t),
+ [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw),
+ [NFULA_PAYLOAD-1] = 0,
+ [NFULA_PREFIX-1] = 0,
+ [NFULA_UID-1] = sizeof(u_int32_t),
+};
+
+static const int nfula_cfg_min[NFULA_CFG_MAX] = {
+ [NFULA_CFG_CMD-1] = sizeof(struct nfulnl_msg_config_cmd),
+ [NFULA_CFG_MODE-1] = sizeof(struct nfulnl_msg_config_mode),
+ [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t),
+ [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t),
+ [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t),
+};
+
+static int
+nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *nfula[], int *errp)
+{
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int16_t group_num = ntohs(nfmsg->res_id);
+ struct nfulnl_instance *inst;
+ int ret = 0;
+
+ UDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
+
+ if (nfattr_bad_size(nfula, NFULA_CFG_MAX, nfula_cfg_min)) {
+ UDEBUG("bad attribute size\n");
+ return -EINVAL;
+ }
+
+ inst = instance_lookup_get(group_num);
+ if (nfula[NFULA_CFG_CMD-1]) {
+ u_int8_t pf = nfmsg->nfgen_family;
+ struct nfulnl_msg_config_cmd *cmd;
+ cmd = NFA_DATA(nfula[NFULA_CFG_CMD-1]);
+ UDEBUG("found CFG_CMD for\n");
+
+ switch (cmd->command) {
+ case NFULNL_CFG_CMD_BIND:
+ if (inst) {
+ ret = -EBUSY;
+ goto out_put;
+ }
+
+ inst = instance_create(group_num,
+ NETLINK_CB(skb).pid);
+ if (!inst) {
+ ret = -EINVAL;
+ goto out_put;
+ }
+ break;
+ case NFULNL_CFG_CMD_UNBIND:
+ if (!inst) {
+ ret = -ENODEV;
+ goto out_put;
+ }
+
+ if (inst->peer_pid != NETLINK_CB(skb).pid) {
+ ret = -EPERM;
+ goto out_put;
+ }
+
+ instance_destroy(inst);
+ break;
+ case NFULNL_CFG_CMD_PF_BIND:
+ UDEBUG("registering log handler for pf=%u\n", pf);
+ ret = nf_log_register(pf, &nfulnl_logger);
+ break;
+ case NFULNL_CFG_CMD_PF_UNBIND:
+ UDEBUG("unregistering log handler for pf=%u\n", pf);
+ /* This is a bug and a feature. We cannot unregister
+ * other handlers, like nfnetlink_inst can */
+ nf_log_unregister_pf(pf);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ if (!inst) {
+ UDEBUG("no config command, and no instance for "
+ "group=%u pid=%u =>ENOENT\n",
+ group_num, NETLINK_CB(skb).pid);
+ ret = -ENOENT;
+ goto out_put;
+ }
+
+ if (inst->peer_pid != NETLINK_CB(skb).pid) {
+ UDEBUG("no config command, and wrong pid\n");
+ ret = -EPERM;
+ goto out_put;
+ }
+ }
+
+ if (nfula[NFULA_CFG_MODE-1]) {
+ struct nfulnl_msg_config_mode *params;
+ params = NFA_DATA(nfula[NFULA_CFG_MODE-1]);
+
+ nfulnl_set_mode(inst, params->copy_mode,
+ ntohs(params->copy_range));
+ }
+
+ if (nfula[NFULA_CFG_TIMEOUT-1]) {
+ u_int32_t timeout =
+ *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]);
+
+ nfulnl_set_timeout(inst, ntohl(timeout));
+ }
+
+ if (nfula[NFULA_CFG_NLBUFSIZ-1]) {
+ u_int32_t nlbufsiz =
+ *(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]);
+
+ nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
+ }
+
+ if (nfula[NFULA_CFG_QTHRESH-1]) {
+ u_int32_t qthresh =
+ *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]);
+
+ nfulnl_set_qthresh(inst, ntohl(qthresh));
+ }
+
+out_put:
+ instance_put(inst);
+ return ret;
+}
+
+static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
+ [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp,
+ .attr_count = NFULA_MAX,
+ .cap_required = CAP_NET_ADMIN, },
+ [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config,
+ .attr_count = NFULA_CFG_MAX,
+ .cap_required = CAP_NET_ADMIN },
+};
+
+static struct nfnetlink_subsystem nfulnl_subsys = {
+ .name = "log",
+ .subsys_id = NFNL_SUBSYS_ULOG,
+ .cb_count = NFULNL_MSG_MAX,
+ .cb = nfulnl_cb,
+};
+
+#ifdef CONFIG_PROC_FS
+struct iter_state {
+ unsigned int bucket;
+};
+
+static struct hlist_node *get_first(struct seq_file *seq)
+{
+ struct iter_state *st = seq->private;
+
+ if (!st)
+ return NULL;
+
+ for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
+ if (!hlist_empty(&instance_table[st->bucket]))
+ return instance_table[st->bucket].first;
+ }
+ return NULL;
+}
+
+static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
+{
+ struct iter_state *st = seq->private;
+
+ h = h->next;
+ while (!h) {
+ if (++st->bucket >= INSTANCE_BUCKETS)
+ return NULL;
+
+ h = instance_table[st->bucket].first;
+ }
+ return h;
+}
+
+static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct hlist_node *head;
+ head = get_first(seq);
+
+ if (head)
+ while (pos && (head = get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
+
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock_bh(&instances_lock);
+ return get_idx(seq, *pos);
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return get_next(s, v);
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+ read_unlock_bh(&instances_lock);
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+ const struct nfulnl_instance *inst = v;
+
+ return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n",
+ inst->group_num,
+ inst->peer_pid, inst->qlen,
+ inst->copy_mode, inst->copy_range,
+ inst->flushtimeout, atomic_read(&inst->use));
+}
+
+static struct seq_operations nful_seq_ops = {
+ .start = seq_start,
+ .next = seq_next,
+ .stop = seq_stop,
+ .show = seq_show,
+};
+
+static int nful_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct iter_state *is;
+ int ret;
+
+ is = kmalloc(sizeof(*is), GFP_KERNEL);
+ if (!is)
+ return -ENOMEM;
+ memset(is, 0, sizeof(*is));
+ ret = seq_open(file, &nful_seq_ops);
+ if (ret < 0)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = is;
+ return ret;
+out_free:
+ kfree(is);
+ return ret;
+}
+
+static struct file_operations nful_file_ops = {
+ .owner = THIS_MODULE,
+ .open = nful_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+#endif /* PROC_FS */
+
+static int
+init_or_cleanup(int init)
+{
+ 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]);
+
+ /* it's not really all that important to have a random value, so
+ * we can do this from the init function, even if there hasn't
+ * been that much entropy yet */
+ get_random_bytes(&hash_init, sizeof(hash_init));
+
+ netlink_register_notifier(&nfulnl_rtnl_notifier);
+ status = nfnetlink_subsys_register(&nfulnl_subsys);
+ if (status < 0) {
+ printk(KERN_ERR "log: failed to create netlink socket\n");
+ goto cleanup_netlink_notifier;
+ }
+
+#ifdef CONFIG_PROC_FS
+ proc_nful = create_proc_entry("nfnetlink_log", 0440,
+ proc_net_netfilter);
+ if (!proc_nful)
+ 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);
+cleanup_netlink_notifier:
+ netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+ return status;
+}
+
+static int __init init(void)
+{
+
+ return init_or_cleanup(1);
+}
+
+static void __exit fini(void)
+{
+ init_or_cleanup(0);
+}
+
+MODULE_DESCRIPTION("netfilter userspace logging");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
+
+module_init(init);
+module_exit(fini);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
new file mode 100644
index 000000000000..f81fe8c52e99
--- /dev/null
+++ b/net/netfilter/nfnetlink_queue.c
@@ -0,0 +1,1127 @@
+/*
+ * This is a module which is used for queueing packets and communicating with
+ * userspace via nfetlink.
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * Based on the old ipv4-only ip_queue.c:
+ * (C) 2000-2002 James Morris <jmorris@intercode.com.au>
+ * (C) 2003-2005 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/skbuff.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/proc_fs.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+#include <linux/list.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+#include "../bridge/br_private.h"
+#endif
+
+#define NFQNL_QMAX_DEFAULT 1024
+
+#if 0
+#define QDEBUG(x, args ...) printk(KERN_DEBUG "%s(%d):%s(): " x, \
+ __FILE__, __LINE__, __FUNCTION__, \
+ ## args)
+#else
+#define QDEBUG(x, ...)
+#endif
+
+struct nfqnl_queue_entry {
+ struct list_head list;
+ struct nf_info *info;
+ struct sk_buff *skb;
+ unsigned int id;
+};
+
+struct nfqnl_instance {
+ struct hlist_node hlist; /* global list of queues */
+ atomic_t use;
+
+ int peer_pid;
+ unsigned int queue_maxlen;
+ unsigned int copy_range;
+ unsigned int queue_total;
+ unsigned int queue_dropped;
+ unsigned int queue_user_dropped;
+
+ atomic_t id_sequence; /* 'sequence' of pkt ids */
+
+ u_int16_t queue_num; /* number of this queue */
+ u_int8_t copy_mode;
+
+ spinlock_t lock;
+
+ struct list_head queue_list; /* packets in queue */
+};
+
+typedef int (*nfqnl_cmpfn)(struct nfqnl_queue_entry *, unsigned long);
+
+static DEFINE_RWLOCK(instances_lock);
+
+#define INSTANCE_BUCKETS 16
+static struct hlist_head instance_table[INSTANCE_BUCKETS];
+
+static inline u_int8_t instance_hashfn(u_int16_t queue_num)
+{
+ return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
+}
+
+static struct nfqnl_instance *
+__instance_lookup(u_int16_t queue_num)
+{
+ struct hlist_head *head;
+ struct hlist_node *pos;
+ struct nfqnl_instance *inst;
+
+ head = &instance_table[instance_hashfn(queue_num)];
+ hlist_for_each_entry(inst, pos, head, hlist) {
+ if (inst->queue_num == queue_num)
+ return inst;
+ }
+ return NULL;
+}
+
+static struct nfqnl_instance *
+instance_lookup_get(u_int16_t queue_num)
+{
+ struct nfqnl_instance *inst;
+
+ read_lock_bh(&instances_lock);
+ inst = __instance_lookup(queue_num);
+ if (inst)
+ atomic_inc(&inst->use);
+ read_unlock_bh(&instances_lock);
+
+ return inst;
+}
+
+static void
+instance_put(struct nfqnl_instance *inst)
+{
+ if (inst && atomic_dec_and_test(&inst->use)) {
+ QDEBUG("kfree(inst=%p)\n", inst);
+ kfree(inst);
+ }
+}
+
+static struct nfqnl_instance *
+instance_create(u_int16_t queue_num, int pid)
+{
+ struct nfqnl_instance *inst;
+
+ QDEBUG("entering for queue_num=%u, pid=%d\n", queue_num, pid);
+
+ write_lock_bh(&instances_lock);
+ if (__instance_lookup(queue_num)) {
+ inst = NULL;
+ QDEBUG("aborting, instance already exists\n");
+ goto out_unlock;
+ }
+
+ inst = kmalloc(sizeof(*inst), GFP_ATOMIC);
+ if (!inst)
+ goto out_unlock;
+
+ memset(inst, 0, sizeof(*inst));
+ inst->queue_num = queue_num;
+ inst->peer_pid = pid;
+ inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
+ inst->copy_range = 0xfffff;
+ inst->copy_mode = NFQNL_COPY_NONE;
+ atomic_set(&inst->id_sequence, 0);
+ /* needs to be two, since we _put() after creation */
+ atomic_set(&inst->use, 2);
+ inst->lock = SPIN_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&inst->queue_list);
+
+ if (!try_module_get(THIS_MODULE))
+ goto out_free;
+
+ hlist_add_head(&inst->hlist,
+ &instance_table[instance_hashfn(queue_num)]);
+
+ write_unlock_bh(&instances_lock);
+
+ QDEBUG("successfully created new instance\n");
+
+ return inst;
+
+out_free:
+ kfree(inst);
+out_unlock:
+ write_unlock_bh(&instances_lock);
+ return NULL;
+}
+
+static void nfqnl_flush(struct nfqnl_instance *queue, int verdict);
+
+static void
+_instance_destroy2(struct nfqnl_instance *inst, int lock)
+{
+ /* first pull it out of the global list */
+ if (lock)
+ write_lock_bh(&instances_lock);
+
+ QDEBUG("removing instance %p (queuenum=%u) from hash\n",
+ inst, inst->queue_num);
+ hlist_del(&inst->hlist);
+
+ if (lock)
+ write_unlock_bh(&instances_lock);
+
+ /* then flush all pending skbs from the queue */
+ nfqnl_flush(inst, NF_DROP);
+
+ /* and finally put the refcount */
+ instance_put(inst);
+
+ module_put(THIS_MODULE);
+}
+
+static inline void
+__instance_destroy(struct nfqnl_instance *inst)
+{
+ _instance_destroy2(inst, 0);
+}
+
+static inline void
+instance_destroy(struct nfqnl_instance *inst)
+{
+ _instance_destroy2(inst, 1);
+}
+
+
+
+static void
+issue_verdict(struct nfqnl_queue_entry *entry, int verdict)
+{
+ QDEBUG("entering for entry %p, verdict %u\n", entry, verdict);
+
+ /* TCP input path (and probably other bits) assume to be called
+ * from softirq context, not from syscall, like issue_verdict is
+ * called. TCP input path deadlocks with locks taken from timer
+ * softirq, e.g. We therefore emulate this by local_bh_disable() */
+
+ local_bh_disable();
+ nf_reinject(entry->skb, entry->info, verdict);
+ local_bh_enable();
+
+ kfree(entry);
+}
+
+static inline void
+__enqueue_entry(struct nfqnl_instance *queue,
+ struct nfqnl_queue_entry *entry)
+{
+ list_add(&entry->list, &queue->queue_list);
+ queue->queue_total++;
+}
+
+/*
+ * Find and return a queued entry matched by cmpfn, or return the last
+ * entry if cmpfn is NULL.
+ */
+static inline struct nfqnl_queue_entry *
+__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
+ unsigned long data)
+{
+ struct list_head *p;
+
+ list_for_each_prev(p, &queue->queue_list) {
+ struct nfqnl_queue_entry *entry = (struct nfqnl_queue_entry *)p;
+
+ if (!cmpfn || cmpfn(entry, data))
+ return entry;
+ }
+ return NULL;
+}
+
+static inline void
+__dequeue_entry(struct nfqnl_instance *q, struct nfqnl_queue_entry *entry)
+{
+ list_del(&entry->list);
+ q->queue_total--;
+}
+
+static inline struct nfqnl_queue_entry *
+__find_dequeue_entry(struct nfqnl_instance *queue,
+ nfqnl_cmpfn cmpfn, unsigned long data)
+{
+ struct nfqnl_queue_entry *entry;
+
+ entry = __find_entry(queue, cmpfn, data);
+ if (entry == NULL)
+ return NULL;
+
+ __dequeue_entry(queue, entry);
+ return entry;
+}
+
+
+static inline void
+__nfqnl_flush(struct nfqnl_instance *queue, int verdict)
+{
+ struct nfqnl_queue_entry *entry;
+
+ while ((entry = __find_dequeue_entry(queue, NULL, 0)))
+ issue_verdict(entry, verdict);
+}
+
+static inline int
+__nfqnl_set_mode(struct nfqnl_instance *queue,
+ unsigned char mode, unsigned int range)
+{
+ int status = 0;
+
+ switch (mode) {
+ case NFQNL_COPY_NONE:
+ case NFQNL_COPY_META:
+ queue->copy_mode = mode;
+ queue->copy_range = 0;
+ break;
+
+ case NFQNL_COPY_PACKET:
+ queue->copy_mode = mode;
+ /* we're using struct nfattr which has 16bit nfa_len */
+ if (range > 0xffff)
+ queue->copy_range = 0xffff;
+ else
+ queue->copy_range = range;
+ break;
+
+ default:
+ status = -EINVAL;
+
+ }
+ return status;
+}
+
+static struct nfqnl_queue_entry *
+find_dequeue_entry(struct nfqnl_instance *queue,
+ nfqnl_cmpfn cmpfn, unsigned long data)
+{
+ struct nfqnl_queue_entry *entry;
+
+ spin_lock_bh(&queue->lock);
+ entry = __find_dequeue_entry(queue, cmpfn, data);
+ spin_unlock_bh(&queue->lock);
+
+ return entry;
+}
+
+static void
+nfqnl_flush(struct nfqnl_instance *queue, int verdict)
+{
+ spin_lock_bh(&queue->lock);
+ __nfqnl_flush(queue, verdict);
+ spin_unlock_bh(&queue->lock);
+}
+
+static struct sk_buff *
+nfqnl_build_packet_message(struct nfqnl_instance *queue,
+ struct nfqnl_queue_entry *entry, int *errp)
+{
+ unsigned char *old_tail;
+ size_t size;
+ size_t data_len = 0;
+ struct sk_buff *skb;
+ struct nfqnl_msg_packet_hdr pmsg;
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ unsigned int tmp_uint;
+
+ QDEBUG("entered\n");
+
+ /* all macros expand to constant values at compile time */
+ size = NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
+ + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+#ifdef CONFIG_BRIDGE_NETFILTER
+ + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+#endif
+ + NLMSG_SPACE(sizeof(u_int32_t)) /* mark */
+ + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hw))
+ + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
+
+ spin_lock_bh(&queue->lock);
+
+ switch (queue->copy_mode) {
+ case NFQNL_COPY_META:
+ case NFQNL_COPY_NONE:
+ data_len = 0;
+ break;
+
+ case NFQNL_COPY_PACKET:
+ if (entry->skb->ip_summed == CHECKSUM_HW &&
+ (*errp = skb_checksum_help(entry->skb,
+ entry->info->outdev == NULL))) {
+ spin_unlock_bh(&queue->lock);
+ return NULL;
+ }
+ if (queue->copy_range == 0
+ || queue->copy_range > entry->skb->len)
+ data_len = entry->skb->len;
+ else
+ data_len = queue->copy_range;
+
+ size += NLMSG_SPACE(data_len);
+ break;
+
+ default:
+ *errp = -EINVAL;
+ spin_unlock_bh(&queue->lock);
+ return NULL;
+ }
+
+ spin_unlock_bh(&queue->lock);
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ goto nlmsg_failure;
+
+ old_tail= skb->tail;
+ nlh = NLMSG_PUT(skb, 0, 0,
+ NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
+ sizeof(struct nfgenmsg));
+ nfmsg = NLMSG_DATA(nlh);
+ nfmsg->nfgen_family = entry->info->pf;
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = htons(queue->queue_num);
+
+ pmsg.packet_id = htonl(entry->id);
+ pmsg.hw_protocol = htons(entry->skb->protocol);
+ pmsg.hook = entry->info->hook;
+
+ NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
+
+ if (entry->info->indev) {
+ tmp_uint = htonl(entry->info->indev->ifindex);
+#ifndef CONFIG_BRIDGE_NETFILTER
+ NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
+#else
+ if (entry->info->pf == PF_BRIDGE) {
+ /* Case 1: indev is physical input device, we need to
+ * look for bridge group (when called from
+ * netfilter_bridge) */
+ NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ /* this is the bridge group "brX" */
+ tmp_uint = htonl(entry->info->indev->br_port->br->dev->ifindex);
+ NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ } else {
+ /* Case 2: indev is bridge group, we need to look for
+ * physical device (when called from ipv4) */
+ NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ if (entry->skb->nf_bridge
+ && entry->skb->nf_bridge->physindev) {
+ tmp_uint = htonl(entry->skb->nf_bridge->physindev->ifindex);
+ NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ }
+ }
+#endif
+ }
+
+ if (entry->info->outdev) {
+ tmp_uint = htonl(entry->info->outdev->ifindex);
+#ifndef CONFIG_BRIDGE_NETFILTER
+ NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
+#else
+ if (entry->info->pf == PF_BRIDGE) {
+ /* Case 1: outdev is physical output device, we need to
+ * look for bridge group (when called from
+ * netfilter_bridge) */
+ NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ /* this is the bridge group "brX" */
+ tmp_uint = htonl(entry->info->outdev->br_port->br->dev->ifindex);
+ NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ } else {
+ /* Case 2: outdev is bridge group, we need to look for
+ * physical output device (when called from ipv4) */
+ NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ &tmp_uint);
+ if (entry->skb->nf_bridge
+ && entry->skb->nf_bridge->physoutdev) {
+ tmp_uint = htonl(entry->skb->nf_bridge->physoutdev->ifindex);
+ NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
+ sizeof(tmp_uint), &tmp_uint);
+ }
+ }
+#endif
+ }
+
+ if (entry->skb->nfmark) {
+ tmp_uint = htonl(entry->skb->nfmark);
+ NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
+ }
+
+ if (entry->info->indev && entry->skb->dev
+ && entry->skb->dev->hard_header_parse) {
+ struct nfqnl_msg_packet_hw phw;
+
+ phw.hw_addrlen =
+ entry->skb->dev->hard_header_parse(entry->skb,
+ phw.hw_addr);
+ phw.hw_addrlen = htons(phw.hw_addrlen);
+ NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
+ }
+
+ if (entry->skb->tstamp.off_sec) {
+ struct nfqnl_msg_packet_timestamp ts;
+
+ ts.sec = cpu_to_be64(skb_tv_base.tv_sec + entry->skb->tstamp.off_sec);
+ ts.usec = cpu_to_be64(skb_tv_base.tv_usec + entry->skb->tstamp.off_usec);
+
+ NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
+ }
+
+ if (data_len) {
+ struct nfattr *nfa;
+ int size = NFA_LENGTH(data_len);
+
+ if (skb_tailroom(skb) < (int)NFA_SPACE(data_len)) {
+ printk(KERN_WARNING "nf_queue: no tailroom!\n");
+ goto nlmsg_failure;
+ }
+
+ nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
+ nfa->nfa_type = NFQA_PAYLOAD;
+ nfa->nfa_len = size;
+
+ if (skb_copy_bits(entry->skb, 0, NFA_DATA(nfa), data_len))
+ BUG();
+ }
+
+ nlh->nlmsg_len = skb->tail - old_tail;
+ return skb;
+
+nlmsg_failure:
+nfattr_failure:
+ if (skb)
+ kfree_skb(skb);
+ *errp = -EINVAL;
+ if (net_ratelimit())
+ printk(KERN_ERR "nf_queue: error creating packet message\n");
+ return NULL;
+}
+
+static int
+nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
+ unsigned int queuenum, void *data)
+{
+ int status = -EINVAL;
+ struct sk_buff *nskb;
+ struct nfqnl_instance *queue;
+ struct nfqnl_queue_entry *entry;
+
+ QDEBUG("entered\n");
+
+ queue = instance_lookup_get(queuenum);
+ if (!queue) {
+ QDEBUG("no queue instance matching\n");
+ return -EINVAL;
+ }
+
+ if (queue->copy_mode == NFQNL_COPY_NONE) {
+ QDEBUG("mode COPY_NONE, aborting\n");
+ status = -EAGAIN;
+ goto err_out_put;
+ }
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL) {
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "nf_queue: OOM in nfqnl_enqueue_packet()\n");
+ status = -ENOMEM;
+ goto err_out_put;
+ }
+
+ entry->info = info;
+ entry->skb = skb;
+ entry->id = atomic_inc_return(&queue->id_sequence);
+
+ nskb = nfqnl_build_packet_message(queue, entry, &status);
+ if (nskb == NULL)
+ goto err_out_free;
+
+ spin_lock_bh(&queue->lock);
+
+ if (!queue->peer_pid)
+ goto err_out_free_nskb;
+
+ if (queue->queue_total >= queue->queue_maxlen) {
+ queue->queue_dropped++;
+ status = -ENOSPC;
+ if (net_ratelimit())
+ printk(KERN_WARNING "ip_queue: full at %d entries, "
+ "dropping packets(s). Dropped: %d\n",
+ queue->queue_total, queue->queue_dropped);
+ goto err_out_free_nskb;
+ }
+
+ /* nfnetlink_unicast will either free the nskb or add it to a socket */
+ status = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT);
+ if (status < 0) {
+ queue->queue_user_dropped++;
+ goto err_out_unlock;
+ }
+
+ __enqueue_entry(queue, entry);
+
+ spin_unlock_bh(&queue->lock);
+ instance_put(queue);
+ return status;
+
+err_out_free_nskb:
+ kfree_skb(nskb);
+
+err_out_unlock:
+ spin_unlock_bh(&queue->lock);
+
+err_out_free:
+ kfree(entry);
+err_out_put:
+ instance_put(queue);
+ return status;
+}
+
+static int
+nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
+{
+ int diff;
+
+ diff = data_len - e->skb->len;
+ if (diff < 0)
+ skb_trim(e->skb, data_len);
+ else if (diff > 0) {
+ if (data_len > 0xFFFF)
+ return -EINVAL;
+ if (diff > skb_tailroom(e->skb)) {
+ struct sk_buff *newskb;
+
+ newskb = skb_copy_expand(e->skb,
+ skb_headroom(e->skb),
+ diff,
+ GFP_ATOMIC);
+ if (newskb == NULL) {
+ printk(KERN_WARNING "ip_queue: OOM "
+ "in mangle, dropping packet\n");
+ return -ENOMEM;
+ }
+ if (e->skb->sk)
+ skb_set_owner_w(newskb, e->skb->sk);
+ kfree_skb(e->skb);
+ e->skb = newskb;
+ }
+ skb_put(e->skb, diff);
+ }
+ if (!skb_make_writable(&e->skb, data_len))
+ return -ENOMEM;
+ memcpy(e->skb->data, data, data_len);
+ e->skb->ip_summed = CHECKSUM_NONE;
+ return 0;
+}
+
+static inline int
+id_cmp(struct nfqnl_queue_entry *e, unsigned long id)
+{
+ return (id == e->id);
+}
+
+static int
+nfqnl_set_mode(struct nfqnl_instance *queue,
+ unsigned char mode, unsigned int range)
+{
+ int status;
+
+ spin_lock_bh(&queue->lock);
+ status = __nfqnl_set_mode(queue, mode, range);
+ spin_unlock_bh(&queue->lock);
+
+ return status;
+}
+
+static int
+dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex)
+{
+ if (entry->info->indev)
+ if (entry->info->indev->ifindex == ifindex)
+ return 1;
+
+ if (entry->info->outdev)
+ if (entry->info->outdev->ifindex == ifindex)
+ return 1;
+
+ return 0;
+}
+
+/* drop all packets with either indev or outdev == ifindex from all queue
+ * instances */
+static void
+nfqnl_dev_drop(int ifindex)
+{
+ int i;
+
+ QDEBUG("entering for ifindex %u\n", ifindex);
+
+ /* this only looks like we have to hold the readlock for a way too long
+ * time, issue_verdict(), nf_reinject(), ... - but we always only
+ * issue NF_DROP, which is processed directly in nf_reinject() */
+ read_lock_bh(&instances_lock);
+
+ for (i = 0; i < INSTANCE_BUCKETS; i++) {
+ struct hlist_node *tmp;
+ struct nfqnl_instance *inst;
+ struct hlist_head *head = &instance_table[i];
+
+ hlist_for_each_entry(inst, tmp, head, hlist) {
+ struct nfqnl_queue_entry *entry;
+ while ((entry = find_dequeue_entry(inst, dev_cmp,
+ ifindex)) != NULL)
+ issue_verdict(entry, NF_DROP);
+ }
+ }
+
+ read_unlock_bh(&instances_lock);
+}
+
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
+
+static int
+nfqnl_rcv_dev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+
+ /* Drop any packets associated with the downed device */
+ if (event == NETDEV_DOWN)
+ nfqnl_dev_drop(dev->ifindex);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nfqnl_dev_notifier = {
+ .notifier_call = nfqnl_rcv_dev_event,
+};
+
+static int
+nfqnl_rcv_nl_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netlink_notify *n = ptr;
+
+ if (event == NETLINK_URELEASE &&
+ n->protocol == NETLINK_NETFILTER && n->pid) {
+ int i;
+
+ /* destroy all instances for this pid */
+ write_lock_bh(&instances_lock);
+ for (i = 0; i < INSTANCE_BUCKETS; i++) {
+ struct hlist_node *tmp, *t2;
+ struct nfqnl_instance *inst;
+ struct hlist_head *head = &instance_table[i];
+
+ hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
+ if (n->pid == inst->peer_pid)
+ __instance_destroy(inst);
+ }
+ }
+ write_unlock_bh(&instances_lock);
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nfqnl_rtnl_notifier = {
+ .notifier_call = nfqnl_rcv_nl_event,
+};
+
+static const int nfqa_verdict_min[NFQA_MAX] = {
+ [NFQA_VERDICT_HDR-1] = sizeof(struct nfqnl_msg_verdict_hdr),
+ [NFQA_MARK-1] = sizeof(u_int32_t),
+ [NFQA_PAYLOAD-1] = 0,
+};
+
+static int
+nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
+{
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int16_t queue_num = ntohs(nfmsg->res_id);
+
+ struct nfqnl_msg_verdict_hdr *vhdr;
+ struct nfqnl_instance *queue;
+ unsigned int verdict;
+ struct nfqnl_queue_entry *entry;
+ int err;
+
+ if (nfattr_bad_size(nfqa, NFQA_MAX, nfqa_verdict_min)) {
+ QDEBUG("bad attribute size\n");
+ return -EINVAL;
+ }
+
+ queue = instance_lookup_get(queue_num);
+ if (!queue)
+ return -ENODEV;
+
+ if (queue->peer_pid != NETLINK_CB(skb).pid) {
+ err = -EPERM;
+ goto err_out_put;
+ }
+
+ if (!nfqa[NFQA_VERDICT_HDR-1]) {
+ err = -EINVAL;
+ goto err_out_put;
+ }
+
+ vhdr = NFA_DATA(nfqa[NFQA_VERDICT_HDR-1]);
+ verdict = ntohl(vhdr->verdict);
+
+ if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
+ err = -EINVAL;
+ goto err_out_put;
+ }
+
+ entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id));
+ if (entry == NULL) {
+ err = -ENOENT;
+ goto err_out_put;
+ }
+
+ if (nfqa[NFQA_PAYLOAD-1]) {
+ if (nfqnl_mangle(NFA_DATA(nfqa[NFQA_PAYLOAD-1]),
+ NFA_PAYLOAD(nfqa[NFQA_PAYLOAD-1]), entry) < 0)
+ verdict = NF_DROP;
+ }
+
+ if (nfqa[NFQA_MARK-1])
+ skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1]));
+
+ issue_verdict(entry, verdict);
+ instance_put(queue);
+ return 0;
+
+err_out_put:
+ instance_put(queue);
+ return err;
+}
+
+static int
+nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
+{
+ return -ENOTSUPP;
+}
+
+static const int nfqa_cfg_min[NFQA_CFG_MAX] = {
+ [NFQA_CFG_CMD-1] = sizeof(struct nfqnl_msg_config_cmd),
+ [NFQA_CFG_PARAMS-1] = sizeof(struct nfqnl_msg_config_params),
+};
+
+static struct nf_queue_handler nfqh = {
+ .name = "nf_queue",
+ .outfn = &nfqnl_enqueue_packet,
+};
+
+static int
+nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
+{
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int16_t queue_num = ntohs(nfmsg->res_id);
+ struct nfqnl_instance *queue;
+ int ret = 0;
+
+ QDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
+
+ if (nfattr_bad_size(nfqa, NFQA_CFG_MAX, nfqa_cfg_min)) {
+ QDEBUG("bad attribute size\n");
+ return -EINVAL;
+ }
+
+ queue = instance_lookup_get(queue_num);
+ if (nfqa[NFQA_CFG_CMD-1]) {
+ struct nfqnl_msg_config_cmd *cmd;
+ cmd = NFA_DATA(nfqa[NFQA_CFG_CMD-1]);
+ QDEBUG("found CFG_CMD\n");
+
+ switch (cmd->command) {
+ case NFQNL_CFG_CMD_BIND:
+ if (queue)
+ return -EBUSY;
+
+ queue = instance_create(queue_num, NETLINK_CB(skb).pid);
+ if (!queue)
+ return -EINVAL;
+ break;
+ case NFQNL_CFG_CMD_UNBIND:
+ if (!queue)
+ return -ENODEV;
+
+ if (queue->peer_pid != NETLINK_CB(skb).pid) {
+ ret = -EPERM;
+ goto out_put;
+ }
+
+ instance_destroy(queue);
+ break;
+ case NFQNL_CFG_CMD_PF_BIND:
+ QDEBUG("registering queue handler for pf=%u\n",
+ ntohs(cmd->pf));
+ ret = nf_register_queue_handler(ntohs(cmd->pf), &nfqh);
+ break;
+ case NFQNL_CFG_CMD_PF_UNBIND:
+ QDEBUG("unregistering queue handler for pf=%u\n",
+ ntohs(cmd->pf));
+ /* This is a bug and a feature. We can unregister
+ * other handlers(!) */
+ ret = nf_unregister_queue_handler(ntohs(cmd->pf));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ if (!queue) {
+ QDEBUG("no config command, and no instance ENOENT\n");
+ ret = -ENOENT;
+ goto out_put;
+ }
+
+ if (queue->peer_pid != NETLINK_CB(skb).pid) {
+ QDEBUG("no config command, and wrong pid\n");
+ ret = -EPERM;
+ goto out_put;
+ }
+ }
+
+ if (nfqa[NFQA_CFG_PARAMS-1]) {
+ struct nfqnl_msg_config_params *params;
+ params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]);
+
+ nfqnl_set_mode(queue, params->copy_mode,
+ ntohl(params->copy_range));
+ }
+
+out_put:
+ instance_put(queue);
+ return ret;
+}
+
+static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
+ [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp,
+ .attr_count = NFQA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict,
+ .attr_count = NFQA_MAX,
+ .cap_required = CAP_NET_ADMIN },
+ [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
+ .attr_count = NFQA_CFG_MAX,
+ .cap_required = CAP_NET_ADMIN },
+};
+
+static struct nfnetlink_subsystem nfqnl_subsys = {
+ .name = "nf_queue",
+ .subsys_id = NFNL_SUBSYS_QUEUE,
+ .cb_count = NFQNL_MSG_MAX,
+ .cb = nfqnl_cb,
+};
+
+#ifdef CONFIG_PROC_FS
+struct iter_state {
+ unsigned int bucket;
+};
+
+static struct hlist_node *get_first(struct seq_file *seq)
+{
+ struct iter_state *st = seq->private;
+
+ if (!st)
+ return NULL;
+
+ for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
+ if (!hlist_empty(&instance_table[st->bucket]))
+ return instance_table[st->bucket].first;
+ }
+ return NULL;
+}
+
+static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
+{
+ struct iter_state *st = seq->private;
+
+ h = h->next;
+ while (!h) {
+ if (++st->bucket >= INSTANCE_BUCKETS)
+ return NULL;
+
+ h = instance_table[st->bucket].first;
+ }
+ return h;
+}
+
+static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct hlist_node *head;
+ head = get_first(seq);
+
+ if (head)
+ while (pos && (head = get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
+
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock_bh(&instances_lock);
+ return get_idx(seq, *pos);
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return get_next(s, v);
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+ read_unlock_bh(&instances_lock);
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+ const struct nfqnl_instance *inst = v;
+
+ return seq_printf(s, "%5d %6d %5d %1d %5d %5d %5d %8d %2d\n",
+ inst->queue_num,
+ inst->peer_pid, inst->queue_total,
+ inst->copy_mode, inst->copy_range,
+ inst->queue_dropped, inst->queue_user_dropped,
+ atomic_read(&inst->id_sequence),
+ atomic_read(&inst->use));
+}
+
+static struct seq_operations nfqnl_seq_ops = {
+ .start = seq_start,
+ .next = seq_next,
+ .stop = seq_stop,
+ .show = seq_show,
+};
+
+static int nfqnl_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct iter_state *is;
+ int ret;
+
+ is = kmalloc(sizeof(*is), GFP_KERNEL);
+ if (!is)
+ return -ENOMEM;
+ memset(is, 0, sizeof(*is));
+ ret = seq_open(file, &nfqnl_seq_ops);
+ if (ret < 0)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = is;
+ return ret;
+out_free:
+ kfree(is);
+ return ret;
+}
+
+static struct file_operations nfqnl_file_ops = {
+ .owner = THIS_MODULE,
+ .open = nfqnl_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+#endif /* PROC_FS */
+
+static int
+init_or_cleanup(int init)
+{
+ 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]);
+
+ netlink_register_notifier(&nfqnl_rtnl_notifier);
+ status = nfnetlink_subsys_register(&nfqnl_subsys);
+ if (status < 0) {
+ printk(KERN_ERR "nf_queue: failed to create netlink socket\n");
+ goto cleanup_netlink_notifier;
+ }
+
+#ifdef CONFIG_PROC_FS
+ proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440,
+ proc_net_netfilter);
+ if (!proc_nfqueue)
+ goto cleanup_subsys;
+ proc_nfqueue->proc_fops = &nfqnl_file_ops;
+#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);
+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)
+{
+ init_or_cleanup(0);
+}
+
+MODULE_DESCRIPTION("netfilter packet queue handler");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_QUEUE);
+
+module_init(init);
+module_exit(fini);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index ff774a06c89d..a64e1d5ce3ca 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -13,7 +13,12 @@
* added netlink_proto_exit
* Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br>
* use nlk_sk, as sk->protinfo is on a diet 8)
- *
+ * Fri Jul 22 19:51:12 MEST 2005 Harald Welte <laforge@gnumonks.org>
+ * - inc module use count of module that owns
+ * the kernel socket in case userspace opens
+ * socket of same protocol
+ * - remove all module support, since netlink is
+ * mandatory if CONFIG_NET=y these days
*/
#include <linux/config.h>
@@ -55,21 +60,29 @@
#include <net/scm.h>
#define Nprintk(a...)
+#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
struct netlink_sock {
/* struct sock has to be the first member of netlink_sock */
struct sock sk;
u32 pid;
- unsigned int groups;
u32 dst_pid;
- unsigned int dst_groups;
+ u32 dst_group;
+ u32 flags;
+ u32 subscriptions;
+ u32 ngroups;
+ unsigned long *groups;
unsigned long state;
wait_queue_head_t wait;
struct netlink_callback *cb;
spinlock_t cb_lock;
void (*data_ready)(struct sock *sk, int bytes);
+ struct module *module;
};
+#define NETLINK_KERNEL_SOCKET 0x1
+#define NETLINK_RECV_PKTINFO 0x2
+
static inline struct netlink_sock *nlk_sk(struct sock *sk)
{
return (struct netlink_sock *)sk;
@@ -92,6 +105,9 @@ struct netlink_table {
struct nl_pid_hash hash;
struct hlist_head mc_list;
unsigned int nl_nonroot;
+ unsigned int groups;
+ struct module *module;
+ int registered;
};
static struct netlink_table *nl_table;
@@ -106,6 +122,11 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
static struct notifier_block *netlink_chain;
+static u32 netlink_group_mask(u32 group)
+{
+ return group ? 1 << (group - 1) : 0;
+}
+
static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
{
return &hash->table[jhash_1word(pid, hash->rnd) & hash->mask];
@@ -122,6 +143,7 @@ static void netlink_sock_destruct(struct sock *sk)
BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
BUG_TRAP(!nlk_sk(sk)->cb);
+ BUG_TRAP(!nlk_sk(sk)->groups);
}
/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on SMP.
@@ -317,7 +339,7 @@ static void netlink_remove(struct sock *sk)
netlink_table_grab();
if (sk_del_node_init(sk))
nl_table[sk->sk_protocol].hash.entries--;
- if (nlk_sk(sk)->groups)
+ if (nlk_sk(sk)->subscriptions)
__sk_del_bind_node(sk);
netlink_table_ungrab();
}
@@ -328,19 +350,11 @@ static struct proto netlink_proto = {
.obj_size = sizeof(struct netlink_sock),
};
-static int netlink_create(struct socket *sock, int protocol)
+static int __netlink_create(struct socket *sock, int protocol)
{
struct sock *sk;
struct netlink_sock *nlk;
- sock->state = SS_UNCONNECTED;
-
- if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
- return -ESOCKTNOSUPPORT;
-
- if (protocol<0 || protocol >= MAX_LINKS)
- return -EPROTONOSUPPORT;
-
sock->ops = &netlink_ops;
sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
@@ -350,15 +364,56 @@ static int netlink_create(struct socket *sock, int protocol)
sock_init_data(sock, sk);
nlk = nlk_sk(sk);
-
spin_lock_init(&nlk->cb_lock);
init_waitqueue_head(&nlk->wait);
- sk->sk_destruct = netlink_sock_destruct;
+ sk->sk_destruct = netlink_sock_destruct;
sk->sk_protocol = protocol;
return 0;
}
+static int netlink_create(struct socket *sock, int protocol)
+{
+ struct module *module = NULL;
+ struct netlink_sock *nlk;
+ unsigned int groups;
+ int err = 0;
+
+ sock->state = SS_UNCONNECTED;
+
+ if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
+ return -ESOCKTNOSUPPORT;
+
+ if (protocol<0 || protocol >= MAX_LINKS)
+ return -EPROTONOSUPPORT;
+
+ netlink_lock_table();
+#ifdef CONFIG_KMOD
+ if (!nl_table[protocol].registered) {
+ netlink_unlock_table();
+ request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
+ netlink_lock_table();
+ }
+#endif
+ if (nl_table[protocol].registered &&
+ try_module_get(nl_table[protocol].module))
+ module = nl_table[protocol].module;
+ groups = nl_table[protocol].groups;
+ netlink_unlock_table();
+
+ if ((err = __netlink_create(sock, protocol) < 0))
+ goto out_module;
+
+ nlk = nlk_sk(sock->sk);
+ nlk->module = module;
+out:
+ return err;
+
+out_module:
+ module_put(module);
+ goto out;
+}
+
static int netlink_release(struct socket *sock)
{
struct sock *sk = sock->sk;
@@ -387,14 +442,27 @@ static int netlink_release(struct socket *sock)
skb_queue_purge(&sk->sk_write_queue);
- if (nlk->pid && !nlk->groups) {
+ if (nlk->pid && !nlk->subscriptions) {
struct netlink_notify n = {
.protocol = sk->sk_protocol,
.pid = nlk->pid,
};
notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
}
-
+
+ if (nlk->module)
+ module_put(nlk->module);
+
+ if (nlk->flags & NETLINK_KERNEL_SOCKET) {
+ netlink_table_grab();
+ nl_table[sk->sk_protocol].module = NULL;
+ nl_table[sk->sk_protocol].registered = 0;
+ netlink_table_ungrab();
+ }
+
+ kfree(nlk->groups);
+ nlk->groups = NULL;
+
sock_put(sk);
return 0;
}
@@ -443,6 +511,41 @@ static inline int netlink_capable(struct socket *sock, unsigned int flag)
capable(CAP_NET_ADMIN);
}
+static void
+netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
+{
+ struct netlink_sock *nlk = nlk_sk(sk);
+
+ if (nlk->subscriptions && !subscriptions)
+ __sk_del_bind_node(sk);
+ else if (!nlk->subscriptions && subscriptions)
+ sk_add_bind_node(sk, &nl_table[sk->sk_protocol].mc_list);
+ nlk->subscriptions = subscriptions;
+}
+
+static int netlink_alloc_groups(struct sock *sk)
+{
+ struct netlink_sock *nlk = nlk_sk(sk);
+ unsigned int groups;
+ int err = 0;
+
+ netlink_lock_table();
+ groups = nl_table[sk->sk_protocol].groups;
+ if (!nl_table[sk->sk_protocol].registered)
+ err = -ENOENT;
+ netlink_unlock_table();
+
+ if (err)
+ return err;
+
+ nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
+ if (nlk->groups == NULL)
+ return -ENOMEM;
+ memset(nlk->groups, 0, NLGRPSZ(groups));
+ nlk->ngroups = groups;
+ return 0;
+}
+
static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
struct sock *sk = sock->sk;
@@ -454,8 +557,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return -EINVAL;
/* Only superuser is allowed to listen multicasts */
- if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_RECV))
- return -EPERM;
+ if (nladdr->nl_groups) {
+ if (!netlink_capable(sock, NL_NONROOT_RECV))
+ return -EPERM;
+ if (nlk->groups == NULL) {
+ err = netlink_alloc_groups(sk);
+ if (err)
+ return err;
+ }
+ }
if (nlk->pid) {
if (nladdr->nl_pid != nlk->pid)
@@ -468,15 +578,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len
return err;
}
- if (!nladdr->nl_groups && !nlk->groups)
+ if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
return 0;
netlink_table_grab();
- if (nlk->groups && !nladdr->nl_groups)
- __sk_del_bind_node(sk);
- else if (!nlk->groups && nladdr->nl_groups)
- sk_add_bind_node(sk, &nl_table[sk->sk_protocol].mc_list);
- nlk->groups = nladdr->nl_groups;
+ netlink_update_subscriptions(sk, nlk->subscriptions +
+ hweight32(nladdr->nl_groups) -
+ hweight32(nlk->groups[0]));
+ nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups;
netlink_table_ungrab();
return 0;
@@ -493,7 +602,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
if (addr->sa_family == AF_UNSPEC) {
sk->sk_state = NETLINK_UNCONNECTED;
nlk->dst_pid = 0;
- nlk->dst_groups = 0;
+ nlk->dst_group = 0;
return 0;
}
if (addr->sa_family != AF_NETLINK)
@@ -509,7 +618,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
if (err == 0) {
sk->sk_state = NETLINK_CONNECTED;
nlk->dst_pid = nladdr->nl_pid;
- nlk->dst_groups = nladdr->nl_groups;
+ nlk->dst_group = ffs(nladdr->nl_groups);
}
return err;
@@ -527,10 +636,10 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr
if (peer) {
nladdr->nl_pid = nlk->dst_pid;
- nladdr->nl_groups = nlk->dst_groups;
+ nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
} else {
nladdr->nl_pid = nlk->pid;
- nladdr->nl_groups = nlk->groups;
+ nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
}
return 0;
}
@@ -731,7 +840,8 @@ static inline int do_one_broadcast(struct sock *sk,
if (p->exclude_sk == sk)
goto out;
- if (nlk->pid == p->pid || !(nlk->groups & p->group))
+ if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
+ !test_bit(p->group - 1, nlk->groups))
goto out;
if (p->failure) {
@@ -770,7 +880,7 @@ out:
}
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
- u32 group, int allocation)
+ u32 group, unsigned int __nocast allocation)
{
struct netlink_broadcast_data info;
struct hlist_node *node;
@@ -827,7 +937,8 @@ static inline int do_one_set_err(struct sock *sk,
if (sk == p->exclude_sk)
goto out;
- if (nlk->pid == p->pid || !(nlk->groups & p->group))
+ if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
+ !test_bit(p->group - 1, nlk->groups))
goto out;
sk->sk_err = p->code;
@@ -855,6 +966,99 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
read_unlock(&nl_table_lock);
}
+static int netlink_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct netlink_sock *nlk = nlk_sk(sk);
+ int val = 0, err;
+
+ if (level != SOL_NETLINK)
+ return -ENOPROTOOPT;
+
+ if (optlen >= sizeof(int) &&
+ get_user(val, (int __user *)optval))
+ return -EFAULT;
+
+ switch (optname) {
+ case NETLINK_PKTINFO:
+ if (val)
+ nlk->flags |= NETLINK_RECV_PKTINFO;
+ else
+ nlk->flags &= ~NETLINK_RECV_PKTINFO;
+ err = 0;
+ break;
+ case NETLINK_ADD_MEMBERSHIP:
+ case NETLINK_DROP_MEMBERSHIP: {
+ unsigned int subscriptions;
+ int old, new = optname == NETLINK_ADD_MEMBERSHIP ? 1 : 0;
+
+ if (!netlink_capable(sock, NL_NONROOT_RECV))
+ return -EPERM;
+ if (nlk->groups == NULL) {
+ err = netlink_alloc_groups(sk);
+ if (err)
+ return err;
+ }
+ if (!val || val - 1 >= nlk->ngroups)
+ return -EINVAL;
+ netlink_table_grab();
+ old = test_bit(val - 1, nlk->groups);
+ subscriptions = nlk->subscriptions - old + new;
+ if (new)
+ __set_bit(val - 1, nlk->groups);
+ else
+ __clear_bit(val - 1, nlk->groups);
+ netlink_update_subscriptions(sk, subscriptions);
+ netlink_table_ungrab();
+ err = 0;
+ break;
+ }
+ default:
+ err = -ENOPROTOOPT;
+ }
+ return err;
+}
+
+static int netlink_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct netlink_sock *nlk = nlk_sk(sk);
+ int len, val, err;
+
+ if (level != SOL_NETLINK)
+ return -ENOPROTOOPT;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+ if (len < 0)
+ return -EINVAL;
+
+ switch (optname) {
+ case NETLINK_PKTINFO:
+ if (len < sizeof(int))
+ return -EINVAL;
+ len = sizeof(int);
+ val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0;
+ put_user(len, optlen);
+ put_user(val, optval);
+ err = 0;
+ break;
+ default:
+ err = -ENOPROTOOPT;
+ }
+ return err;
+}
+
+static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
+{
+ struct nl_pktinfo info;
+
+ info.group = NETLINK_CB(skb).dst_group;
+ put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info);
+}
+
static inline void netlink_rcv_wake(struct sock *sk)
{
struct netlink_sock *nlk = nlk_sk(sk);
@@ -873,7 +1077,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct netlink_sock *nlk = nlk_sk(sk);
struct sockaddr_nl *addr=msg->msg_name;
u32 dst_pid;
- u32 dst_groups;
+ u32 dst_group;
struct sk_buff *skb;
int err;
struct scm_cookie scm;
@@ -891,12 +1095,12 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (addr->nl_family != AF_NETLINK)
return -EINVAL;
dst_pid = addr->nl_pid;
- dst_groups = addr->nl_groups;
- if (dst_groups && !netlink_capable(sock, NL_NONROOT_SEND))
+ dst_group = ffs(addr->nl_groups);
+ if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
return -EPERM;
} else {
dst_pid = nlk->dst_pid;
- dst_groups = nlk->dst_groups;
+ dst_group = nlk->dst_group;
}
if (!nlk->pid) {
@@ -914,9 +1118,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out;
NETLINK_CB(skb).pid = nlk->pid;
- NETLINK_CB(skb).groups = nlk->groups;
NETLINK_CB(skb).dst_pid = dst_pid;
- NETLINK_CB(skb).dst_groups = dst_groups;
+ NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
@@ -938,9 +1141,9 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out;
}
- if (dst_groups) {
+ if (dst_group) {
atomic_inc(&skb->users);
- netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL);
+ netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL);
}
err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
@@ -986,7 +1189,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
addr->nl_family = AF_NETLINK;
addr->nl_pad = 0;
addr->nl_pid = NETLINK_CB(skb).pid;
- addr->nl_groups = NETLINK_CB(skb).dst_groups;
+ addr->nl_groups = netlink_group_mask(NETLINK_CB(skb).dst_group);
msg->msg_namelen = sizeof(*addr);
}
@@ -1001,6 +1204,8 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
netlink_dump(sk);
scm_recv(sock, msg, siocb->scm, flags);
+ if (nlk->flags & NETLINK_RECV_PKTINFO)
+ netlink_cmsg_recv_pktinfo(msg, skb);
out:
netlink_rcv_wake(sk);
@@ -1023,10 +1228,13 @@ static void netlink_data_ready(struct sock *sk, int len)
*/
struct sock *
-netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
+netlink_kernel_create(int unit, unsigned int groups,
+ void (*input)(struct sock *sk, int len),
+ struct module *module)
{
struct socket *sock;
struct sock *sk;
+ struct netlink_sock *nlk;
if (!nl_table)
return NULL;
@@ -1037,20 +1245,31 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
return NULL;
- if (netlink_create(sock, unit) < 0) {
- sock_release(sock);
- return NULL;
- }
+ if (__netlink_create(sock, unit) < 0)
+ goto out_sock_release;
+
sk = sock->sk;
sk->sk_data_ready = netlink_data_ready;
if (input)
nlk_sk(sk)->data_ready = input;
- if (netlink_insert(sk, 0)) {
- sock_release(sock);
- return NULL;
- }
+ if (netlink_insert(sk, 0))
+ goto out_sock_release;
+
+ nlk = nlk_sk(sk);
+ nlk->flags |= NETLINK_KERNEL_SOCKET;
+
+ netlink_table_grab();
+ nl_table[unit].groups = groups < 32 ? 32 : groups;
+ nl_table[unit].module = module;
+ nl_table[unit].registered = 1;
+ netlink_table_ungrab();
+
return sk;
+
+out_sock_release:
+ sock_release(sock);
+ return NULL;
}
void netlink_set_nonroot(int protocol, unsigned int flags)
@@ -1288,7 +1507,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
s,
s->sk_protocol,
nlk->pid,
- nlk->groups,
+ nlk->groups ? (u32)nlk->groups[0] : 0,
atomic_read(&s->sk_rmem_alloc),
atomic_read(&s->sk_wmem_alloc),
nlk->cb,
@@ -1362,8 +1581,8 @@ static struct proto_ops netlink_ops = {
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
+ .setsockopt = netlink_setsockopt,
+ .getsockopt = netlink_getsockopt,
.sendmsg = netlink_sendmsg,
.recvmsg = netlink_recvmsg,
.mmap = sock_no_mmap,
@@ -1438,21 +1657,7 @@ out:
return err;
}
-static void __exit netlink_proto_exit(void)
-{
- sock_unregister(PF_NETLINK);
- proc_net_remove("netlink");
- kfree(nl_table);
- nl_table = NULL;
- proto_unregister(&netlink_proto);
-}
-
core_initcall(netlink_proto_init);
-module_exit(netlink_proto_exit);
-
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_NETPROTO(PF_NETLINK);
EXPORT_SYMBOL(netlink_ack);
EXPORT_SYMBOL(netlink_broadcast);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 162a85fed150..e5d82d711cae 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -39,7 +39,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/ip.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/arp.h>
#include <linux/init.h>
@@ -56,6 +56,7 @@ int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW;
int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE;
int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING;
int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS;
+int sysctl_netrom_reset_circuit = NR_DEFAULT_RESET;
static unsigned short circuit = 0x101;
@@ -858,17 +859,16 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
frametype = skb->data[19] & 0x0F;
flags = skb->data[19] & 0xF0;
-#ifdef CONFIG_INET
/*
* Check for an incoming IP over NET/ROM frame.
*/
- if (frametype == NR_PROTOEXT && circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
+ if (frametype == NR_PROTOEXT &&
+ circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
skb->h.raw = skb->data;
return nr_rx_ip(skb, dev);
}
-#endif
/*
* Find an existing socket connection, based on circuit ID, if it's
@@ -909,17 +909,17 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
if (frametype != NR_CONNREQ) {
/*
* Here it would be nice to be able to send a reset but
- * NET/ROM doesn't have one. The following hack would
- * have been a way to extend the protocol but apparently
- * it kills BPQ boxes... :-(
- */
-#if 0
- /*
- * Never reply to a CONNACK/CHOKE.
+ * NET/ROM doesn't have one. We've tried to extend the protocol
+ * by sending NR_CONNACK | NR_CHOKE_FLAGS replies but that
+ * apparently kills BPQ boxes... :-(
+ * So now we try to follow the established behaviour of
+ * G8PZT's Xrouter which is sending packets with command type 7
+ * as an extension of the protocol.
*/
- if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG)
- nr_transmit_refusal(skb, 1);
-#endif
+ if (sysctl_netrom_reset_circuit &&
+ (frametype != NR_RESET || flags != 0))
+ nr_transmit_reset(skb, 1);
+
return 0;
}
@@ -1188,9 +1188,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
case SIOCGSTAMP:
- ret = -EINVAL;
- if (sk != NULL)
- ret = sock_get_timestamp(sk, argp);
+ ret = sock_get_timestamp(sk, argp);
release_sock(sk);
return ret;
@@ -1262,6 +1260,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
struct net_device *dev;
struct nr_sock *nr;
const char *devname;
+ char buf[11];
if (v == SEQ_START_TOKEN)
seq_puts(seq,
@@ -1277,11 +1276,11 @@ static int nr_info_show(struct seq_file *seq, void *v)
else
devname = dev->name;
- seq_printf(seq, "%-9s ", ax2asc(&nr->user_addr));
- seq_printf(seq, "%-9s ", ax2asc(&nr->dest_addr));
+ seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));
+ seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));
seq_printf(seq,
"%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n",
- ax2asc(&nr->source_addr),
+ ax2asc(buf, &nr->source_addr),
devname,
nr->my_index,
nr->my_id,
@@ -1393,8 +1392,7 @@ static int __init nr_proto_init(void)
struct net_device *dev;
sprintf(name, "nr%d", i);
- dev = alloc_netdev(sizeof(struct net_device_stats), name,
- nr_setup);
+ dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup);
if (!dev) {
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
goto fail;
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 220bf7494f71..4e66eef9a034 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -38,8 +38,6 @@
#include <net/ax25.h>
#include <net/netrom.h>
-#ifdef CONFIG_INET
-
/*
* Only allow IP over NET/ROM frames through if the netrom device is up.
*/
@@ -49,7 +47,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
struct net_device_stats *stats = netdev_priv(dev);
if (!netif_running(dev)) {
- stats->rx_errors++;
+ stats->rx_dropped++;
return 0;
}
@@ -64,23 +62,19 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
skb->nh.raw = skb->data;
skb->pkt_type = PACKET_HOST;
- ip_rcv(skb, skb->dev, NULL);
+ netif_rx(skb);
return 1;
}
+#ifdef CONFIG_INET
static int nr_rebuild_header(struct sk_buff *skb)
{
- struct net_device *dev = skb->dev;
- struct net_device_stats *stats = netdev_priv(dev);
- struct sk_buff *skbn;
unsigned char *bp = skb->data;
- int len;
- if (arp_find(bp + 7, skb)) {
+ if (arp_find(bp + 7, skb))
return 1;
- }
bp[6] &= ~AX25_CBIT;
bp[6] &= ~AX25_EBIT;
@@ -91,27 +85,7 @@ static int nr_rebuild_header(struct sk_buff *skb)
bp[6] |= AX25_EBIT;
bp[6] |= AX25_SSSID_SPARE;
- if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
- kfree_skb(skb);
- return 1;
- }
-
- if (skb->sk != NULL)
- skb_set_owner_w(skbn, skb->sk);
-
- kfree_skb(skb);
-
- len = skbn->len;
-
- if (!nr_route_frame(skbn, NULL)) {
- kfree_skb(skbn);
- stats->tx_errors++;
- }
-
- stats->tx_packets++;
- stats->tx_bytes += len;
-
- return 1;
+ return 0;
}
#else
@@ -186,15 +160,27 @@ static int nr_close(struct net_device *dev)
static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device_stats *stats = netdev_priv(dev);
- dev_kfree_skb(skb);
- stats->tx_errors++;
+ struct nr_private *nr = netdev_priv(dev);
+ struct net_device_stats *stats = &nr->stats;
+ unsigned int len = skb->len;
+
+ if (!nr_route_frame(skb, NULL)) {
+ kfree_skb(skb);
+ stats->tx_errors++;
+ return 0;
+ }
+
+ stats->tx_packets++;
+ stats->tx_bytes += len;
+
return 0;
}
static struct net_device_stats *nr_get_stats(struct net_device *dev)
{
- return netdev_priv(dev);
+ struct nr_private *nr = netdev_priv(dev);
+
+ return &nr->stats;
}
void nr_setup(struct net_device *dev)
@@ -209,12 +195,11 @@ void nr_setup(struct net_device *dev)
dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN;
dev->addr_len = AX25_ADDR_LEN;
dev->type = ARPHRD_NETROM;
- dev->tx_queue_len = 40;
dev->rebuild_header = nr_rebuild_header;
dev->set_mac_address = nr_set_mac_address;
/* New-style flags. */
- dev->flags = 0;
+ dev->flags = IFF_NOARP;
dev->get_stats = nr_get_stats;
}
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index 9c44b3794126..004e8599b8fe 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -22,8 +22,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
-#include <net/ip.h> /* For ip_rcv */
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
@@ -99,6 +98,11 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
nr_disconnect(sk, ECONNREFUSED);
break;
+ case NR_RESET:
+ if (sysctl_netrom_reset_circuit);
+ nr_disconnect(sk, ECONNRESET);
+ break;
+
default:
break;
}
@@ -125,6 +129,11 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
nr_disconnect(sk, 0);
break;
+ case NR_RESET:
+ if (sysctl_netrom_reset_circuit);
+ nr_disconnect(sk, ECONNRESET);
+ break;
+
default:
break;
}
@@ -255,6 +264,11 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
}
break;
+ case NR_RESET:
+ if (sysctl_netrom_reset_circuit);
+ nr_disconnect(sk, ECONNRESET);
+ break;
+
default:
break;
}
diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c
index 165b2abce110..e856ae1b360a 100644
--- a/net/netrom/nr_loopback.c
+++ b/net/netrom/nr_loopback.c
@@ -17,7 +17,7 @@
static void nr_loopback_timer(unsigned long);
static struct sk_buff_head loopback_queue;
-static struct timer_list loopback_timer = TIMER_INITIALIZER(nr_loopback_timer, 0, 0);
+static DEFINE_TIMER(loopback_timer, nr_loopback_timer, 0, 0);
void __init nr_loopback_init(void)
{
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 7a86b36cba50..b3b9097c87c7 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -881,6 +881,7 @@ static void nr_node_stop(struct seq_file *seq, void *v)
static int nr_node_show(struct seq_file *seq, void *v)
{
+ char buf[11];
int i;
if (v == SEQ_START_TOKEN)
@@ -890,7 +891,7 @@ static int nr_node_show(struct seq_file *seq, void *v)
struct nr_node *nr_node = v;
nr_node_lock(nr_node);
seq_printf(seq, "%-9s %-7s %d %d",
- ax2asc(&nr_node->callsign),
+ ax2asc(buf, &nr_node->callsign),
(nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
nr_node->which + 1,
nr_node->count);
@@ -964,6 +965,7 @@ static void nr_neigh_stop(struct seq_file *seq, void *v)
static int nr_neigh_show(struct seq_file *seq, void *v)
{
+ char buf[11];
int i;
if (v == SEQ_START_TOKEN)
@@ -973,7 +975,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",
nr_neigh->number,
- ax2asc(&nr_neigh->callsign),
+ ax2asc(buf, &nr_neigh->callsign),
nr_neigh->dev ? nr_neigh->dev->name : "???",
nr_neigh->quality,
nr_neigh->locked,
@@ -983,7 +985,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
if (nr_neigh->digipeat != NULL) {
for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
seq_printf(seq, " %s",
- ax2asc(&nr_neigh->digipeat->calls[i]));
+ ax2asc(buf, &nr_neigh->digipeat->calls[i]));
}
seq_puts(seq, "\n");
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
index 0627347b14b8..bcb9946b4f56 100644
--- a/net/netrom/nr_subr.c
+++ b/net/netrom/nr_subr.c
@@ -21,7 +21,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
@@ -77,7 +77,7 @@ void nr_requeue_frames(struct sock *sk)
if (skb_prev == NULL)
skb_queue_head(&sk->sk_write_queue, skb);
else
- skb_append(skb_prev, skb);
+ skb_append(skb_prev, skb, &sk->sk_write_queue);
skb_prev = skb;
}
}
@@ -210,10 +210,9 @@ void nr_write_internal(struct sock *sk, int frametype)
}
/*
- * This routine is called when a Connect Acknowledge with the Choke Flag
- * set is needed to refuse a connection.
+ * This routine is called to send an error reply.
*/
-void nr_transmit_refusal(struct sk_buff *skb, int mine)
+void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags)
{
struct sk_buff *skbn;
unsigned char *dptr;
@@ -254,7 +253,7 @@ void nr_transmit_refusal(struct sk_buff *skb, int mine)
*dptr++ = 0;
}
- *dptr++ = NR_CONNACK | NR_CHOKE_FLAG;
+ *dptr++ = cmdflags;
*dptr++ = 0;
if (!nr_route_frame(skbn, NULL))
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
index faabda8088be..75b72d389ba9 100644
--- a/net/netrom/nr_timer.c
+++ b/net/netrom/nr_timer.c
@@ -22,7 +22,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/fcntl.h>
diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c
index c9ed50382ea7..6bb8dda849dc 100644
--- a/net/netrom/sysctl_net_netrom.c
+++ b/net/netrom/sysctl_net_netrom.c
@@ -30,6 +30,7 @@ static int min_idle[] = {0 * HZ};
static int max_idle[] = {65535 * HZ};
static int min_route[] = {0}, max_route[] = {1};
static int min_fails[] = {1}, max_fails[] = {10};
+static int min_reset[] = {0}, max_reset[] = {1};
static struct ctl_table_header *nr_table_header;
@@ -155,6 +156,17 @@ static ctl_table nr_table[] = {
.extra1 = &min_fails,
.extra2 = &max_fails
},
+ {
+ .ctl_name = NET_NETROM_RESET,
+ .procname = "reset",
+ .data = &sysctl_netrom_reset_circuit,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_reset,
+ .extra2 = &max_reset
+ },
{ .ctl_name = 0 }
};
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c9d5980aa4de..8690f171c1ef 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -241,7 +241,7 @@ static struct proto_ops packet_ops;
#ifdef CONFIG_SOCK_PACKET
static struct proto_ops packet_ops_spkt;
-static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct sockaddr_pkt *spkt;
@@ -441,7 +441,7 @@ static inline unsigned run_filter(struct sk_buff *skb, struct sock *sk, unsigned
we will not harm anyone.
*/
-static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct sockaddr_ll *sll;
@@ -546,7 +546,7 @@ drop:
}
#ifdef CONFIG_PACKET_MMAP
-static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct packet_sock *po;
@@ -635,12 +635,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
h->tp_snaplen = snaplen;
h->tp_mac = macoff;
h->tp_net = netoff;
- if (skb->stamp.tv_sec == 0) {
- do_gettimeofday(&skb->stamp);
+ if (skb->tstamp.off_sec == 0) {
+ __net_timestamp(skb);
sock_enable_timestamp(sk);
}
- h->tp_sec = skb->stamp.tv_sec;
- h->tp_usec = skb->stamp.tv_usec;
+ h->tp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec;
+ h->tp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec;
sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h)));
sll->sll_halen = 0;
@@ -1535,8 +1535,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
static void packet_mm_open(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
- struct inode *inode = file->f_dentry->d_inode;
- struct socket * sock = SOCKET_I(inode);
+ struct socket * sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
@@ -1546,8 +1545,7 @@ static void packet_mm_open(struct vm_area_struct *vma)
static void packet_mm_close(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
- struct inode *inode = file->f_dentry->d_inode;
- struct socket * sock = SOCKET_I(inode);
+ struct socket * sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 5480caf8ccc2..5acb1680524a 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -41,7 +41,7 @@
#include <net/rose.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -1243,7 +1243,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
if (amount < 0)
amount = 0;
- return put_user(amount, (unsigned int __user *)argp);
+ return put_user(amount, (unsigned int __user *) argp);
}
case TIOCINQ: {
@@ -1252,13 +1252,11 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
amount = skb->len;
- return put_user(amount, (unsigned int __user *)argp);
+ return put_user(amount, (unsigned int __user *) argp);
}
case SIOCGSTAMP:
- if (sk != NULL)
- return sock_get_timestamp(sk, (struct timeval __user *)argp);
- return -EINVAL;
+ return sock_get_timestamp(sk, (struct timeval __user *) argp);
case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1363,6 +1361,8 @@ static void rose_info_stop(struct seq_file *seq, void *v)
static int rose_info_show(struct seq_file *seq, void *v)
{
+ char buf[11];
+
if (v == SEQ_START_TOKEN)
seq_puts(seq,
"dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n");
@@ -1380,12 +1380,12 @@ static int rose_info_show(struct seq_file *seq, void *v)
seq_printf(seq, "%-10s %-9s ",
rose2asc(&rose->dest_addr),
- ax2asc(&rose->dest_call));
+ ax2asc(buf, &rose->dest_call));
if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
callsign = "??????-?";
else
- callsign = ax2asc(&rose->source_call);
+ callsign = ax2asc(buf, &rose->source_call);
seq_printf(seq,
"%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index a8ed9a1d09f9..d297af737d10 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -149,6 +149,6 @@ void rose_setup(struct net_device *dev)
dev->set_mac_address = rose_set_mac_address;
/* New-style flags. */
- dev->flags = 0;
+ dev->flags = IFF_NOARP;
dev->get_stats = rose_get_stats;
}
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index ef475a1bb1ba..8348d33f1efe 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -26,8 +26,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/ip.h> /* For ip_rcv */
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 25da6f699fd0..e556d92c0bc4 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -24,7 +24,7 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
@@ -851,6 +851,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
unsigned char cause, diagnostic;
struct net_device *dev;
int len, res = 0;
+ char buf[11];
#if 0
if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
@@ -876,7 +877,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
if (rose_neigh == NULL) {
printk("rose_route : unknown neighbour or device %s\n",
- ax2asc(&ax25->dest_addr));
+ ax2asc(buf, &ax25->dest_addr));
goto out;
}
@@ -1178,6 +1179,7 @@ static void rose_neigh_stop(struct seq_file *seq, void *v)
static int rose_neigh_show(struct seq_file *seq, void *v)
{
+ char buf[11];
int i;
if (v == SEQ_START_TOKEN)
@@ -1189,7 +1191,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
/* if (!rose_neigh->loopback) { */
seq_printf(seq, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu",
rose_neigh->number,
- (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign),
+ (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),
rose_neigh->dev ? rose_neigh->dev->name : "???",
rose_neigh->count,
rose_neigh->use,
@@ -1200,7 +1202,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
if (rose_neigh->digipeat != NULL) {
for (i = 0; i < rose_neigh->digipeat->ndigi; i++)
- seq_printf(seq, " %s", ax2asc(&rose_neigh->digipeat->calls[i]));
+ seq_printf(seq, " %s", ax2asc(buf, &rose_neigh->digipeat->calls[i]));
}
seq_puts(seq, "\n");
@@ -1260,6 +1262,8 @@ static void rose_route_stop(struct seq_file *seq, void *v)
static int rose_route_show(struct seq_file *seq, void *v)
{
+ char buf[11];
+
if (v == SEQ_START_TOKEN)
seq_puts(seq,
"lci address callsign neigh <-> lci address callsign neigh\n");
@@ -1271,7 +1275,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
"%3.3X %-10s %-9s %05d ",
rose_route->lci1,
rose2asc(&rose_route->src_addr),
- ax2asc(&rose_route->src_call),
+ ax2asc(buf, &rose_route->src_call),
rose_route->neigh1->number);
else
seq_puts(seq,
@@ -1282,7 +1286,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
"%3.3X %-10s %-9s %05d\n",
rose_route->lci2,
rose2asc(&rose_route->dest_addr),
- ax2asc(&rose_route->dest_call),
+ ax2asc(buf, &rose_route->dest_call),
rose_route->neigh2->number);
else
seq_puts(seq,
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
index 7db7e1cedc3a..36a77944622b 100644
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -21,7 +21,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
@@ -74,7 +74,7 @@ void rose_requeue_frames(struct sock *sk)
if (skb_prev == NULL)
skb_queue_head(&sk->sk_write_queue, skb);
else
- skb_append(skb_prev, skb);
+ skb_append(skb_prev, skb, &sk->sk_write_queue);
skb_prev = skb;
}
}
@@ -337,13 +337,13 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
memcpy(callsign, p + 12, l - 10);
callsign[l - 10] = '\0';
- facilities->source_call = *asc2ax(callsign);
+ asc2ax(&facilities->source_call, callsign);
}
if (*p == FAC_CCITT_SRC_NSAP) {
memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN);
memcpy(callsign, p + 12, l - 10);
callsign[l - 10] = '\0';
- facilities->dest_call = *asc2ax(callsign);
+ asc2ax(&facilities->dest_call, callsign);
}
p += l + 2;
n += l + 2;
@@ -400,6 +400,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
{
unsigned char *p = buffer + 1;
char *callsign;
+ char buf[11];
int len, nb;
/* National Facilities */
@@ -456,7 +457,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
*p++ = FAC_CCITT_DEST_NSAP;
- callsign = ax2asc(&rose->dest_call);
+ callsign = ax2asc(buf, &rose->dest_call);
*p++ = strlen(callsign) + 10;
*p++ = (strlen(callsign) + 9) * 2; /* ??? */
@@ -471,7 +472,7 @@ static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
*p++ = FAC_CCITT_SRC_NSAP;
- callsign = ax2asc(&rose->source_call);
+ callsign = ax2asc(buf, &rose->source_call);
*p++ = strlen(callsign) + 10;
*p++ = (strlen(callsign) + 9) * 2; /* ??? */
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 84dd4403f792..50ae0371dab8 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -22,7 +22,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index 9bce7794130a..122c086ee2db 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -330,7 +330,7 @@ static int rxrpc_incoming_msg(struct rxrpc_transport *trans,
msg->trans = trans;
msg->state = RXRPC_MSG_RECEIVED;
- msg->stamp = pkt->stamp;
+ skb_get_timestamp(pkt, &msg->stamp);
if (msg->stamp.tv_sec == 0) {
do_gettimeofday(&msg->stamp);
if (pkt->sk)
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 59d3e71f8b85..45d3bc0812c8 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -491,6 +491,7 @@ config NET_EMATCH_TEXT
depends on NET_EMATCH
select TEXTSEARCH
select TEXTSEARCH_KMP
+ select TEXTSEARCH_BM
select TEXTSEARCH_FSM
---help---
Say Y here if you want to be ablt to classify packets based on
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 249c61936ea0..8aebe8f6d271 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -165,7 +165,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action *act,
while ((a = act) != NULL) {
repeat:
if (a->ops && a->ops->act) {
- ret = a->ops->act(&skb, a);
+ ret = a->ops->act(&skb, a, res);
if (TC_MUNGED & skb->tc_verd) {
/* copied already, allow trampling */
skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
@@ -179,11 +179,6 @@ repeat:
act = a->next;
}
exec_done:
- if (skb->tc_classid > 0) {
- res->classid = skb->tc_classid;
- res->class = 0;
- skb->tc_classid = 0;
- }
return ret;
}
@@ -598,7 +593,7 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
nlh->nlmsg_flags |= NLM_F_ROOT;
module_put(a->ops->owner);
kfree(a);
- err = rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ err = rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
if (err > 0)
return 0;
@@ -661,7 +656,7 @@ tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event)
/* now do the delete */
tcf_action_destroy(head, 0);
- ret = rtnetlink_send(skb, pid, RTMGRP_TC,
+ ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
n->nlmsg_flags&NLM_F_ECHO);
if (ret > 0)
return 0;
@@ -703,9 +698,9 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
x->rta_len = skb->tail - (u8*)x;
nlh->nlmsg_len = skb->tail - b;
- NETLINK_CB(skb).dst_groups = RTMGRP_TC;
+ NETLINK_CB(skb).dst_group = RTNLGRP_TC;
- err = rtnetlink_send(skb, pid, RTMGRP_TC, flags&NLM_F_ECHO);
+ err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
if (err > 0)
err = 0;
return err;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 3b5714ef4d1a..b4d89fbb3782 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -367,7 +367,7 @@ static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n,
return -EINVAL;
}
- return rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
}
struct tcf_dump_args
diff --git a/net/sched/gact.c b/net/sched/gact.c
index a811c89fef7f..d1c6d542912a 100644
--- a/net/sched/gact.c
+++ b/net/sched/gact.c
@@ -135,7 +135,7 @@ tcf_gact_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_gact(struct sk_buff **pskb, struct tc_action *a)
+tcf_gact(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_gact *p = PRIV(a, gact);
struct sk_buff *skb = *pskb;
diff --git a/net/sched/ipt.c b/net/sched/ipt.c
index b114d994d523..f50136eed211 100644
--- a/net/sched/ipt.c
+++ b/net/sched/ipt.c
@@ -201,7 +201,7 @@ tcf_ipt_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_ipt(struct sk_buff **pskb, struct tc_action *a)
+tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
{
int ret = 0, result = 0;
struct tcf_ipt *p = PRIV(a, ipt);
diff --git a/net/sched/mirred.c b/net/sched/mirred.c
index f309ce336803..20d06916dc0b 100644
--- a/net/sched/mirred.c
+++ b/net/sched/mirred.c
@@ -158,7 +158,7 @@ tcf_mirred_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_mirred(struct sk_buff **pskb, struct tc_action *a)
+tcf_mirred(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_mirred *p = PRIV(a, mirred);
struct net_device *dev;
diff --git a/net/sched/pedit.c b/net/sched/pedit.c
index 678be6a645fb..767d24f4610e 100644
--- a/net/sched/pedit.c
+++ b/net/sched/pedit.c
@@ -130,7 +130,7 @@ tcf_pedit_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_pedit(struct sk_buff **pskb, struct tc_action *a)
+tcf_pedit(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_pedit *p = PRIV(a, pedit);
struct sk_buff *skb = *pskb;
diff --git a/net/sched/police.c b/net/sched/police.c
index c03545faf523..eb39fb2f39b6 100644
--- a/net/sched/police.c
+++ b/net/sched/police.c
@@ -284,7 +284,8 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind)
return 0;
}
-static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a)
+static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a,
+ struct tcf_result *res)
{
psched_time_t now;
struct sk_buff *skb = *pskb;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index b9a069af4a02..31570b9a6e9a 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -816,7 +816,7 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,
}
if (skb->len)
- return rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
err_out:
kfree_skb(skb);
@@ -1040,7 +1040,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
return -EINVAL;
}
- return rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
}
struct qdisc_dump_args
@@ -1194,7 +1194,7 @@ EXPORT_SYMBOL(psched_time_base);
* with 32-bit get_cycles(). Safe up to 4GHz CPU.
*/
static void psched_tick(unsigned long);
-static struct timer_list psched_timer = TIMER_INITIALIZER(psched_tick, 0, 0);
+static DEFINE_TIMER(psched_timer, psched_tick, 0, 0);
static void psched_tick(unsigned long dummy)
{
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 0d066c965342..99ceb91f0150 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -238,6 +238,20 @@ static void dev_watchdog_down(struct net_device *dev)
spin_unlock_bh(&dev->xmit_lock);
}
+void netif_carrier_on(struct net_device *dev)
+{
+ if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
+ linkwatch_fire_event(dev);
+ if (netif_running(dev))
+ __netdev_watchdog_up(dev);
+}
+
+void netif_carrier_off(struct net_device *dev)
+{
+ if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
+ linkwatch_fire_event(dev);
+}
+
/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
under all circumstances. It is difficult to invent anything faster or
cheaper.
@@ -600,6 +614,8 @@ void dev_shutdown(struct net_device *dev)
}
EXPORT_SYMBOL(__netdev_watchdog_up);
+EXPORT_SYMBOL(netif_carrier_on);
+EXPORT_SYMBOL(netif_carrier_off);
EXPORT_SYMBOL(noop_qdisc);
EXPORT_SYMBOL(noop_qdisc_ops);
EXPORT_SYMBOL(qdisc_create_dflt);
diff --git a/net/sched/simple.c b/net/sched/simple.c
index 3ab4c675ab5d..8a6ae4f491e8 100644
--- a/net/sched/simple.c
+++ b/net/sched/simple.c
@@ -44,7 +44,7 @@ static DEFINE_RWLOCK(simp_lock);
#include <net/pkt_act.h>
#include <net/act_generic.h>
-static int tcf_simp(struct sk_buff **pskb, struct tc_action *a)
+static int tcf_simp(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
{
struct sk_buff *skb = *pskb;
struct tcf_defact *p = PRIV(a, defact);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index e47ac0d1a6d6..e22ccd655965 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -193,8 +193,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
sctp_unhash_endpoint(ep);
/* Free up the HMAC transform. */
- if (sctp_sk(ep->base.sk)->hmac)
- sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
+ sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 742be9171b7d..28f32243397f 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -236,8 +236,8 @@ int sctp_rcv(struct sk_buff *skb)
}
/* SCTP seems to always need a timestamp right now (FIXME) */
- if (skb->stamp.tv_sec == 0) {
- do_gettimeofday(&skb->stamp);
+ if (skb->tstamp.off_sec == 0) {
+ __net_timestamp(skb);
sock_enable_timestamp(sk);
}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e9b2fd480d61..fa3be2b8fb5f 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -66,8 +66,8 @@
#include <linux/seq_file.h>
#include <net/protocol.h>
-#include <net/tcp.h>
#include <net/ndisc.h>
+#include <net/ip.h>
#include <net/ipv6.h>
#include <net/transp_v6.h>
#include <net/addrconf.h>
@@ -641,10 +641,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
else
newinet->pmtudisc = IP_PMTUDISC_WANT;
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet6_sock_nr);
- atomic_inc(&inet_sock_nr);
-#endif
+ sk_refcnt_debug_inc(newsk);
if (newsk->sk_prot->init(newsk)) {
sk_common_release(newsk);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index ce9245e71fca..e7025be77691 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -62,7 +62,7 @@
/* Global data structures. */
struct sctp_globals sctp_globals;
struct proc_dir_entry *proc_net_sctp;
-DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
+DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
struct idr sctp_assocs_id;
DEFINE_SPINLOCK(sctp_assocs_id_lock);
@@ -78,8 +78,8 @@ static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific;
static struct sctp_af *sctp_af_v6_specific;
-kmem_cache_t *sctp_chunk_cachep;
-kmem_cache_t *sctp_bucket_cachep;
+kmem_cache_t *sctp_chunk_cachep __read_mostly;
+kmem_cache_t *sctp_bucket_cachep __read_mostly;
extern int sctp_snmp_proc_init(void);
extern int sctp_snmp_proc_exit(void);
@@ -593,9 +593,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newinet->mc_index = 0;
newinet->mc_list = NULL;
-#ifdef INET_REFCNT_DEBUG
- atomic_inc(&inet_sock_nr);
-#endif
+ sk_refcnt_debug_inc(newsk);
if (newsk->sk_prot->init(newsk)) {
sk_common_release(newsk);
@@ -1244,6 +1242,10 @@ SCTP_STATIC __exit void sctp_exit(void)
module_init(sctp_init);
module_exit(sctp_exit);
+/*
+ * __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly.
+ */
+MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
MODULE_LICENSE("GPL");
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 00d32b7c8266..3868a8d70cc0 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1362,6 +1362,7 @@ struct sctp_association *sctp_unpack_cookie(
char *key;
sctp_scope_t scope;
struct sk_buff *skb = chunk->skb;
+ struct timeval tv;
headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
@@ -1434,7 +1435,8 @@ no_hmac:
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
*/
- if (!asoc && tv_lt(bear_cookie->expiration, skb->stamp)) {
+ skb_get_timestamp(skb, &tv);
+ if (!asoc && tv_lt(bear_cookie->expiration, tv)) {
__u16 len;
/*
* Section 3.3.10.3 Stale Cookie Error (3)
@@ -1447,10 +1449,9 @@ no_hmac:
len = ntohs(chunk->chunk_hdr->length);
*errp = sctp_make_op_error_space(asoc, chunk, len);
if (*errp) {
- suseconds_t usecs = (skb->stamp.tv_sec -
+ suseconds_t usecs = (tv.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
- skb->stamp.tv_usec -
- bear_cookie->expiration.tv_usec;
+ tv.tv_usec - bear_cookie->expiration.tv_usec;
usecs = htonl(usecs);
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 091a66f06a35..91ec8c936913 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4194,8 +4194,7 @@ out:
sctp_release_sock(sk);
return err;
cleanup:
- if (tfm)
- sctp_crypto_free_tfm(tfm);
+ sctp_crypto_free_tfm(tfm);
goto out;
}
@@ -4892,7 +4891,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &oldsk->sk_receive_queue);
__skb_queue_tail(&newsk->sk_receive_queue, skb);
}
}
@@ -4921,7 +4920,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &oldsp->pd_lobby);
__skb_queue_tail(queue, skb);
}
}
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index dc4893474f18..75b28dd634fe 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -42,6 +42,7 @@
*/
#include <net/sctp/structs.h>
+#include <net/sctp/sctp.h>
#include <linux/sysctl.h>
static ctl_handler sctp_sysctl_jiffies_ms;
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 8bbc279d6c99..ec2c857eae7f 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -50,9 +50,9 @@
/* Forward declarations for internal helpers. */
static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
- struct sctp_ulpevent *);
+ struct sctp_ulpevent *);
static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
- struct sctp_ulpevent *);
+ struct sctp_ulpevent *);
/* 1st Level Abstractions */
@@ -125,7 +125,9 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
event = sctp_ulpq_order(ulpq, event);
}
- /* Send event to the ULP. */
+ /* Send event to the ULP. 'event' is the sctp_ulpevent for
+ * very first SKB on the 'temp' list.
+ */
if (event)
sctp_ulpq_tail_event(ulpq, event);
@@ -158,14 +160,18 @@ static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq)
return sctp_clear_pd(ulpq->asoc->base.sk);
}
-
-
+/* If the SKB of 'event' is on a list, it is the first such member
+ * of that list.
+ */
int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
{
struct sock *sk = ulpq->asoc->base.sk;
- struct sk_buff_head *queue;
+ struct sk_buff_head *queue, *skb_list;
+ struct sk_buff *skb = sctp_event2skb(event);
int clear_pd = 0;
+ skb_list = (struct sk_buff_head *) skb->prev;
+
/* If the socket is just going to throw this away, do not
* even try to deliver it.
*/
@@ -197,10 +203,10 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
/* If we are harvesting multiple skbs they will be
* collected on a list.
*/
- if (sctp_event2skb(event)->list)
- sctp_skb_list_tail(sctp_event2skb(event)->list, queue);
+ if (skb_list)
+ sctp_skb_list_tail(skb_list, queue);
else
- __skb_queue_tail(queue, sctp_event2skb(event));
+ __skb_queue_tail(queue, skb);
/* Did we just complete partial delivery and need to get
* rolling again? Move pending data to the receive
@@ -214,10 +220,11 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
return 1;
out_free:
- if (sctp_event2skb(event)->list)
- sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
+ if (skb_list)
+ sctp_queue_purge_ulpevents(skb_list);
else
sctp_ulpevent_free(event);
+
return 0;
}
@@ -269,7 +276,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/
-static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag)
+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 sctp_ulpevent *event;
@@ -294,7 +301,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag,
skb_shinfo(f_frag)->frag_list = pos;
/* Remove the first fragment from the reassembly queue. */
- __skb_unlink(f_frag, f_frag->list);
+ __skb_unlink(f_frag, queue);
while (pos) {
pnext = pos->next;
@@ -304,7 +311,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag,
f_frag->data_len += pos->len;
/* Remove the fragment from the reassembly queue. */
- __skb_unlink(pos, pos->list);
+ __skb_unlink(pos, queue);
/* Break if we have reached the last fragment. */
if (pos == l_frag)
@@ -375,7 +382,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u
done:
return retval;
found:
- retval = sctp_make_reassembled_event(first_frag, pos);
+ retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
if (retval)
retval->msg_flags |= MSG_EOR;
goto done;
@@ -435,7 +442,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq
* further.
*/
done:
- retval = sctp_make_reassembled_event(first_frag, last_frag);
+ retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
if (retval && is_last)
retval->msg_flags |= MSG_EOR;
@@ -527,7 +534,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *u
* further.
*/
done:
- retval = sctp_make_reassembled_event(first_frag, last_frag);
+ retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
return retval;
}
@@ -537,6 +544,7 @@ done:
static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
struct sctp_ulpevent *event)
{
+ struct sk_buff_head *event_list;
struct sk_buff *pos, *tmp;
struct sctp_ulpevent *cevent;
struct sctp_stream *in;
@@ -547,6 +555,8 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
ssn = event->ssn;
in = &ulpq->asoc->ssnmap->in;
+ event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev;
+
/* We are holding the chunks by stream, by SSN. */
sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
cevent = (struct sctp_ulpevent *) pos->cb;
@@ -567,10 +577,10 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
/* Found it, so mark in the ssnmap. */
sctp_ssn_next(in, sid);
- __skb_unlink(pos, pos->list);
+ __skb_unlink(pos, &ulpq->lobby);
/* Attach all gathered skbs to the event. */
- __skb_queue_tail(sctp_event2skb(event)->list, pos);
+ __skb_queue_tail(event_list, pos);
}
}
@@ -626,7 +636,7 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
}
static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
- struct sctp_ulpevent *event)
+ struct sctp_ulpevent *event)
{
__u16 sid, ssn;
struct sctp_stream *in;
@@ -667,7 +677,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq)
{
struct sk_buff *pos, *tmp;
struct sctp_ulpevent *cevent;
- struct sctp_ulpevent *event = NULL;
+ struct sctp_ulpevent *event;
struct sctp_stream *in;
struct sk_buff_head temp;
__u16 csid, cssn;
@@ -675,6 +685,8 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq)
in = &ulpq->asoc->ssnmap->in;
/* We are holding the chunks by stream, by SSN. */
+ skb_queue_head_init(&temp);
+ event = NULL;
sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
cevent = (struct sctp_ulpevent *) pos->cb;
csid = cevent->stream;
@@ -686,19 +698,20 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq)
/* Found it, so mark in the ssnmap. */
sctp_ssn_next(in, csid);
- __skb_unlink(pos, pos->list);
+ __skb_unlink(pos, &ulpq->lobby);
if (!event) {
/* Create a temporary list to collect chunks on. */
event = sctp_skb2event(pos);
- skb_queue_head_init(&temp);
__skb_queue_tail(&temp, sctp_event2skb(event));
} else {
/* Attach all gathered skbs to the event. */
- __skb_queue_tail(sctp_event2skb(event)->list, pos);
+ __skb_queue_tail(&temp, pos);
}
}
- /* Send event to the ULP. */
+ /* Send event to the ULP. 'event' is the sctp_ulpevent for
+ * very first SKB on the 'temp' list.
+ */
if (event)
sctp_ulpq_tail_event(ulpq, event);
}
diff --git a/net/socket.c b/net/socket.c
index 6f2a17881972..c699e93c33d7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -70,6 +70,8 @@
#include <linux/seq_file.h>
#include <linux/wanrouter.h>
#include <linux/if_bridge.h>
+#include <linux/if_frad.h>
+#include <linux/if_vlan.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/cache.h>
@@ -272,7 +274,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ule
#define SOCKFS_MAGIC 0x534F434B
-static kmem_cache_t * sock_inode_cachep;
+static kmem_cache_t * sock_inode_cachep __read_mostly;
static struct inode *sock_alloc_inode(struct super_block *sb)
{
@@ -331,7 +333,7 @@ static struct super_block *sockfs_get_sb(struct file_system_type *fs_type,
return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
}
-static struct vfsmount *sock_mnt;
+static struct vfsmount *sock_mnt __read_mostly;
static struct file_system_type sock_fs_type = {
.name = "sockfs",
@@ -404,6 +406,7 @@ int sock_map_fd(struct socket *sock)
file->f_mode = FMODE_READ | FMODE_WRITE;
file->f_flags = O_RDWR;
file->f_pos = 0;
+ file->private_data = sock;
fd_install(fd, file);
}
@@ -436,6 +439,9 @@ struct socket *sockfd_lookup(int fd, int *err)
return NULL;
}
+ if (file->f_op == &socket_file_ops)
+ return file->private_data; /* set in sock_map_fd */
+
inode = file->f_dentry->d_inode;
if (!S_ISSOCK(inode->i_mode)) {
*err = -ENOTSOCK;
@@ -661,7 +667,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
}
iocb->private = x;
x->kiocb = iocb;
- sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
+ sock = iocb->ki_filp->private_data;
x->async_msg.msg_name = NULL;
x->async_msg.msg_namelen = 0;
@@ -703,7 +709,7 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
}
iocb->private = x;
x->kiocb = iocb;
- sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
+ sock = iocb->ki_filp->private_data;
x->async_msg.msg_name = NULL;
x->async_msg.msg_namelen = 0;
@@ -720,13 +726,13 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
return __sock_sendmsg(iocb, sock, &x->async_msg, size);
}
-ssize_t sock_sendpage(struct file *file, struct page *page,
- int offset, size_t size, loff_t *ppos, int more)
+static ssize_t sock_sendpage(struct file *file, struct page *page,
+ int offset, size_t size, loff_t *ppos, int more)
{
struct socket *sock;
int flags;
- sock = SOCKET_I(file->f_dentry->d_inode);
+ sock = file->private_data;
flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
if (more)
@@ -735,14 +741,14 @@ ssize_t sock_sendpage(struct file *file, struct page *page,
return sock->ops->sendpage(sock, page, offset, size, flags);
}
-static int sock_readv_writev(int type, struct inode * inode,
+static int sock_readv_writev(int type,
struct file * file, const struct iovec * iov,
long count, size_t size)
{
struct msghdr msg;
struct socket *sock;
- sock = SOCKET_I(inode);
+ sock = file->private_data;
msg.msg_name = NULL;
msg.msg_namelen = 0;
@@ -769,7 +775,7 @@ static ssize_t sock_readv(struct file *file, const struct iovec *vector,
int i;
for (i = 0 ; i < count ; i++)
tot_len += vector[i].iov_len;
- return sock_readv_writev(VERIFY_WRITE, file->f_dentry->d_inode,
+ return sock_readv_writev(VERIFY_WRITE,
file, vector, count, tot_len);
}
@@ -780,7 +786,7 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
int i;
for (i = 0 ; i < count ; i++)
tot_len += vector[i].iov_len;
- return sock_readv_writev(VERIFY_READ, file->f_dentry->d_inode,
+ return sock_readv_writev(VERIFY_READ,
file, vector, count, tot_len);
}
@@ -834,7 +840,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int pid, err;
- sock = SOCKET_I(file->f_dentry->d_inode);
+ sock = file->private_data;
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
err = dev_ioctl(cmd, argp);
} else
@@ -933,18 +939,18 @@ static unsigned int sock_poll(struct file *file, poll_table * wait)
/*
* We can't return errors to poll, so it's either yes or no.
*/
- sock = SOCKET_I(file->f_dentry->d_inode);
+ sock = file->private_data;
return sock->ops->poll(file, sock, wait);
}
static int sock_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct socket *sock = SOCKET_I(file->f_dentry->d_inode);
+ struct socket *sock = file->private_data;
return sock->ops->mmap(file, sock, vma);
}
-int sock_close(struct inode *inode, struct file *filp)
+static int sock_close(struct inode *inode, struct file *filp)
{
/*
* It was possible the inode is NULL we were
@@ -989,7 +995,7 @@ static int sock_fasync(int fd, struct file *filp, int on)
return -ENOMEM;
}
- sock = SOCKET_I(filp->f_dentry->d_inode);
+ sock = filp->private_data;
if ((sk=sock->sk) == NULL) {
kfree(fna);
@@ -1739,10 +1745,11 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
goto out_freeiov;
ctl_len = msg_sys.msg_controllen;
if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
- err = cmsghdr_from_user_compat_to_kern(&msg_sys, ctl, sizeof(ctl));
+ err = cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, sizeof(ctl));
if (err)
goto out_freeiov;
ctl_buf = msg_sys.msg_control;
+ ctl_len = msg_sys.msg_controllen;
} else if (ctl_len) {
if (ctl_len > sizeof(ctl))
{
@@ -2023,9 +2030,6 @@ int sock_unregister(int family)
return 0;
}
-
-extern void sk_init(void);
-
void __init sock_init(void)
{
/*
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 5a7265aeaf83..ee6ae74cd1b2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -160,7 +160,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
" unsupported checksum %d", cksumtype);
goto out;
}
- if (!(tfm = crypto_alloc_tfm(cksumname, 0)))
+ if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
goto out;
cksum->len = crypto_tfm_alg_digestsize(tfm);
if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
@@ -199,8 +199,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
crypto_digest_final(tfm, cksum->data);
code = 0;
out:
- if (tfm)
- crypto_free_tfm(tfm);
+ crypto_free_tfm(tfm);
return code;
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index cf726510df8e..606a8a82cafb 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -185,12 +185,9 @@ static void
gss_delete_sec_context_kerberos(void *internal_ctx) {
struct krb5_ctx *kctx = internal_ctx;
- if (kctx->seq)
- crypto_free_tfm(kctx->seq);
- if (kctx->enc)
- crypto_free_tfm(kctx->enc);
- if (kctx->mech_used.data)
- kfree(kctx->mech_used.data);
+ crypto_free_tfm(kctx->seq);
+ crypto_free_tfm(kctx->enc);
+ kfree(kctx->mech_used.data);
kfree(kctx);
}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index dad05994c3eb..6c97d61baa9b 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -214,14 +214,10 @@ static void
gss_delete_sec_context_spkm3(void *internal_ctx) {
struct spkm3_ctx *sctx = internal_ctx;
- if(sctx->derived_integ_key)
- crypto_free_tfm(sctx->derived_integ_key);
- if(sctx->derived_conf_key)
- crypto_free_tfm(sctx->derived_conf_key);
- if(sctx->share_key.data)
- kfree(sctx->share_key.data);
- if(sctx->mech_used.data)
- kfree(sctx->mech_used.data);
+ crypto_free_tfm(sctx->derived_integ_key);
+ crypto_free_tfm(sctx->derived_conf_key);
+ kfree(sctx->share_key.data);
+ kfree(sctx->mech_used.data);
kfree(sctx);
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 5c8fe3bfc494..e3308195374e 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -250,6 +250,7 @@ out:
}
static struct cache_detail rsi_cache = {
+ .owner = THIS_MODULE,
.hash_size = RSI_HASHMAX,
.hash_table = rsi_table,
.name = "auth.rpcsec.init",
@@ -436,6 +437,7 @@ out:
}
static struct cache_detail rsc_cache = {
+ .owner = THIS_MODULE,
.hash_size = RSC_HASHMAX,
.hash_table = rsc_table,
.name = "auth.rpcsec.context",
@@ -1074,7 +1076,9 @@ gss_svc_init(void)
void
gss_svc_shutdown(void)
{
- cache_unregister(&rsc_cache);
- cache_unregister(&rsi_cache);
+ if (cache_unregister(&rsc_cache))
+ printk(KERN_ERR "auth_rpcgss: failed to unregister rsc cache\n");
+ if (cache_unregister(&rsi_cache))
+ printk(KERN_ERR "auth_rpcgss: failed to unregister rsi cache\n");
svc_auth_unregister(RPC_AUTH_GSS);
}
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 900f5bc7e336..f509e9992767 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -177,7 +177,7 @@ void cache_register(struct cache_detail *cd)
cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
if (cd->proc_ent) {
struct proc_dir_entry *p;
- cd->proc_ent->owner = THIS_MODULE;
+ cd->proc_ent->owner = cd->owner;
cd->channel_ent = cd->content_ent = NULL;
p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
@@ -185,7 +185,7 @@ void cache_register(struct cache_detail *cd)
cd->flush_ent = p;
if (p) {
p->proc_fops = &cache_flush_operations;
- p->owner = THIS_MODULE;
+ p->owner = cd->owner;
p->data = cd;
}
@@ -195,7 +195,7 @@ void cache_register(struct cache_detail *cd)
cd->channel_ent = p;
if (p) {
p->proc_fops = &cache_file_operations;
- p->owner = THIS_MODULE;
+ p->owner = cd->owner;
p->data = cd;
}
}
@@ -205,7 +205,7 @@ void cache_register(struct cache_detail *cd)
cd->content_ent = p;
if (p) {
p->proc_fops = &content_file_operations;
- p->owner = THIS_MODULE;
+ p->owner = cd->owner;
p->data = cd;
}
}
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 554f224c0445..ded6c63f11ec 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -3,7 +3,7 @@
*
* Userland/kernel interface for rpcauth_gss.
* Code shamelessly plagiarized from fs/nfsd/nfsctl.c
- * and fs/driverfs/inode.c
+ * and fs/sysfs/inode.c
*
* Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
*
@@ -28,13 +28,13 @@
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
-static struct vfsmount *rpc_mount;
+static struct vfsmount *rpc_mount __read_mostly;
static int rpc_mount_count;
static struct file_system_type rpc_pipe_fs_type;
-static kmem_cache_t *rpc_inode_cachep;
+static kmem_cache_t *rpc_inode_cachep __read_mostly;
#define RPC_UPCALL_TIMEOUT (30*HZ)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 2d9eb7fbd521..f3104035e35d 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -34,10 +34,10 @@ static int rpc_task_id;
#define RPC_BUFFER_MAXSIZE (2048)
#define RPC_BUFFER_POOLSIZE (8)
#define RPC_TASK_POOLSIZE (8)
-static kmem_cache_t *rpc_task_slabp;
-static kmem_cache_t *rpc_buffer_slabp;
-static mempool_t *rpc_task_mempool;
-static mempool_t *rpc_buffer_mempool;
+static kmem_cache_t *rpc_task_slabp __read_mostly;
+static kmem_cache_t *rpc_buffer_slabp __read_mostly;
+static mempool_t *rpc_task_mempool __read_mostly;
+static mempool_t *rpc_buffer_mempool __read_mostly;
static void __rpc_default_timer(struct rpc_task *task);
static void rpciod_killall(void);
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 9b67dc19944c..4979f226e285 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -35,13 +35,13 @@ static int rpc_proc_show(struct seq_file *seq, void *v) {
int i, j;
seq_printf(seq,
- "net %d %d %d %d\n",
+ "net %u %u %u %u\n",
statp->netcnt,
statp->netudpcnt,
statp->nettcpcnt,
statp->nettcpconn);
seq_printf(seq,
- "rpc %d %d %d\n",
+ "rpc %u %u %u\n",
statp->rpccnt,
statp->rpcretrans,
statp->rpcauthrefresh);
@@ -50,10 +50,10 @@ static int rpc_proc_show(struct seq_file *seq, void *v) {
const struct rpc_version *vers = prog->version[i];
if (!vers)
continue;
- seq_printf(seq, "proc%d %d",
+ seq_printf(seq, "proc%u %u",
vers->number, vers->nrprocs);
for (j = 0; j < vers->nrprocs; j++)
- seq_printf(seq, " %d",
+ seq_printf(seq, " %u",
vers->procs[j].p_count);
seq_putc(seq, '\n');
}
@@ -83,13 +83,13 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
int i, j;
seq_printf(seq,
- "net %d %d %d %d\n",
+ "net %u %u %u %u\n",
statp->netcnt,
statp->netudpcnt,
statp->nettcpcnt,
statp->nettcpconn);
seq_printf(seq,
- "rpc %d %d %d %d %d\n",
+ "rpc %u %u %u %u %u\n",
statp->rpccnt,
statp->rpcbadfmt+statp->rpcbadauth+statp->rpcbadclnt,
statp->rpcbadfmt,
@@ -99,9 +99,9 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
for (i = 0; i < prog->pg_nvers; i++) {
if (!(vers = prog->pg_vers[i]) || !(proc = vers->vs_proc))
continue;
- seq_printf(seq, "proc%d %d", i, vers->vs_nproc);
+ seq_printf(seq, "proc%d %u", i, vers->vs_nproc);
for (j = 0; j < vers->vs_nproc; j++, proc++)
- seq_printf(seq, " %d", proc->pc_count);
+ seq_printf(seq, " %u", proc->pc_count);
seq_putc(seq, '\n');
}
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 62a073495276..ed48ff022d35 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -176,8 +176,10 @@ cleanup_sunrpc(void)
{
unregister_rpc_pipefs();
rpc_destroy_mempool();
- cache_unregister(&auth_domain_cache);
- cache_unregister(&ip_map_cache);
+ 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
rpc_unregister_sysctl();
#endif
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index bde8147ef2db..dda4f0c63511 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -143,6 +143,7 @@ static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
struct cache_detail auth_domain_cache = {
+ .owner = THIS_MODULE,
.hash_size = DN_HASHMAX,
.hash_table = auth_domain_table,
.name = "auth.domain",
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index d6baf6fdf8a9..cac2e774dd81 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -242,6 +242,7 @@ static int ip_map_show(struct seq_file *m,
struct cache_detail ip_map_cache = {
+ .owner = THIS_MODULE,
.hash_size = IP_HASHMAX,
.hash_table = ip_table,
.name = "auth.unix.ip",
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d0c3120d0233..30ec3efc48a6 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -34,7 +34,7 @@
#include <net/sock.h>
#include <net/checksum.h>
#include <net/ip.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -512,15 +512,14 @@ svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv)
static void
svc_udp_data_ready(struct sock *sk, int count)
{
- struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- if (!svsk)
- goto out;
- dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
- svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
- set_bit(SK_DATA, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+ if (svsk) {
+ dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
+ svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
+ set_bit(SK_DATA, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ }
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible(sk->sk_sleep);
}
@@ -540,7 +539,7 @@ svc_write_space(struct sock *sk)
}
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) {
- printk(KERN_WARNING "RPC svc_write_space: some sleeping on %p\n",
+ dprintk("RPC svc_write_space: someone sleeping on %p\n",
svsk);
wake_up_interruptible(sk->sk_sleep);
}
@@ -584,13 +583,16 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
/* possibly an icmp error */
dprintk("svc: recvfrom returned error %d\n", -err);
}
- if (skb->stamp.tv_sec == 0) {
- skb->stamp.tv_sec = xtime.tv_sec;
- skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC;
+ if (skb->tstamp.off_sec == 0) {
+ struct timeval tv;
+
+ tv.tv_sec = xtime.tv_sec;
+ tv.tv_usec = xtime.tv_nsec * 1000;
+ skb_set_timestamp(skb, &tv);
/* Don't enable netstamp, sunrpc doesn't
need that much accuracy */
}
- svsk->sk_sk->sk_stamp = skb->stamp;
+ skb_get_timestamp(skb, &svsk->sk_sk->sk_stamp);
set_bit(SK_DATA, &svsk->sk_flags); /* there may be more data... */
/*
@@ -689,31 +691,29 @@ svc_udp_init(struct svc_sock *svsk)
static void
svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
{
- struct svc_sock *svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP (listen) state change %d\n",
- sk, sk->sk_state);
+ sk, sk->sk_state);
- if (sk->sk_state != TCP_LISTEN) {
- /*
- * This callback may called twice when a new connection
- * is established as a child socket inherits everything
- * from a parent LISTEN socket.
- * 1) data_ready method of the parent socket will be called
- * when one of child sockets become ESTABLISHED.
- * 2) data_ready method of the child socket may be called
- * when it receives data before the socket is accepted.
- * In case of 2, we should ignore it silently.
- */
- goto out;
- }
- if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
- printk("svc: socket %p: no user data\n", sk);
- goto out;
+ /*
+ * This callback may called twice when a new connection
+ * is established as a child socket inherits everything
+ * from a parent LISTEN socket.
+ * 1) data_ready method of the parent socket will be called
+ * when one of child sockets become ESTABLISHED.
+ * 2) data_ready method of the child socket may be called
+ * when it receives data before the socket is accepted.
+ * In case of 2, we should ignore it silently.
+ */
+ if (sk->sk_state == TCP_LISTEN) {
+ if (svsk) {
+ set_bit(SK_CONN, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ } else
+ printk("svc: socket %p: no user data\n", sk);
}
- set_bit(SK_CONN, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible_all(sk->sk_sleep);
}
@@ -724,18 +724,17 @@ svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
static void
svc_tcp_state_change(struct sock *sk)
{
- struct svc_sock *svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
- sk, sk->sk_state, sk->sk_user_data);
+ sk, sk->sk_state, sk->sk_user_data);
- if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
+ if (!svsk)
printk("svc: socket %p: no user data\n", sk);
- goto out;
+ else {
+ set_bit(SK_CLOSE, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
}
- set_bit(SK_CLOSE, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible_all(sk->sk_sleep);
}
@@ -743,15 +742,14 @@ svc_tcp_state_change(struct sock *sk)
static void
svc_tcp_data_ready(struct sock *sk, int count)
{
- struct svc_sock * svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP data ready (svsk %p)\n",
- sk, sk->sk_user_data);
- if (!(svsk = (struct svc_sock *)(sk->sk_user_data)))
- goto out;
- set_bit(SK_DATA, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+ sk, sk->sk_user_data);
+ if (svsk) {
+ set_bit(SK_DATA, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ }
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible(sk->sk_sleep);
}
@@ -1167,8 +1165,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
while (rqstp->rq_arghi < pages) {
struct page *p = alloc_page(GFP_KERNEL);
if (!p) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/2);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(500));
continue;
}
rqstp->rq_argpages[rqstp->rq_arghi++] = p;
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 3f6e31069c54..c5241fcbb966 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -17,17 +17,15 @@
#include <linux/sysctl.h>
#ifdef CONFIG_INET
-extern struct ctl_table ipv4_table[];
+#include <net/ip.h>
#endif
-extern struct ctl_table core_table[];
-
#ifdef CONFIG_NET
-extern struct ctl_table ether_table[];
+#include <linux/if_ether.h>
#endif
#ifdef CONFIG_TR
-extern struct ctl_table tr_table[];
+#include <linux/if_tr.h>
#endif
struct ctl_table net_table[] = {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d403e34088ad..41feca3bef86 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -105,7 +105,7 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <net/sock.h>
-#include <linux/tcp.h>
+#include <net/tcp_states.h>
#include <net/af_unix.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -2026,14 +2026,6 @@ static struct net_proto_family unix_family_ops = {
.owner = THIS_MODULE,
};
-#ifdef CONFIG_SYSCTL
-extern void unix_sysctl_register(void);
-extern void unix_sysctl_unregister(void);
-#else
-static inline void unix_sysctl_register(void) {}
-static inline void unix_sysctl_unregister(void) {}
-#endif
-
static int __init af_unix_init(void)
{
int rc = -1;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 4bd95c8f5934..6ffc64e1712d 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -76,11 +76,11 @@
#include <linux/netdevice.h>
#include <linux/file.h>
#include <linux/proc_fs.h>
-#include <linux/tcp.h>
#include <net/sock.h>
#include <net/af_unix.h>
#include <net/scm.h>
+#include <net/tcp_states.h>
/* Internal data structures and random procedures: */
@@ -286,16 +286,16 @@ void unix_gc(void)
skb = skb_peek(&s->sk_receive_queue);
while (skb &&
skb != (struct sk_buff *)&s->sk_receive_queue) {
- nextsk=skb->next;
+ nextsk = skb->next;
/*
* Do we have file descriptors ?
*/
- if(UNIXCB(skb).fp)
- {
- __skb_unlink(skb, skb->list);
- __skb_queue_tail(&hitlist,skb);
+ if (UNIXCB(skb).fp) {
+ __skb_unlink(skb,
+ &s->sk_receive_queue);
+ __skb_queue_tail(&hitlist, skb);
}
- skb=nextsk;
+ skb = nextsk;
}
spin_unlock(&s->sk_receive_queue.lock);
}
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index c974dac4580a..690ffa5d5bfb 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -12,7 +12,7 @@
#include <linux/mm.h>
#include <linux/sysctl.h>
-extern int sysctl_unix_max_dgram_qlen;
+#include <net/af_unix.h>
static ctl_table unix_table[] = {
{
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index d93b19faaab7..596cb96e5f47 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -57,7 +57,7 @@
#include <linux/wanpipe.h>
#include <linux/if_wanpipe.h>
#include <linux/pkt_sched.h>
-#include <linux/tcp.h>
+#include <linux/tcp_states.h>
#include <linux/if_wanpipe_common.h>
#include <linux/sdla_x25.h>
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 04bec047fa9a..020d73cc8414 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -47,7 +47,7 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 36fc3bf6d882..adfe7b8df355 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -81,7 +81,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)
}
int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype)
+ struct packet_type *ptype, struct net_device *orig_dev)
{
struct sk_buff *nskb;
struct x25_neigh *nb;
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index b0197c70a9fc..26146874b839 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -28,7 +28,7 @@
#include <linux/string.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/x25.h>
static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 7fd872ad0c20..8be9b8fbc24d 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -27,7 +27,7 @@
#include <linux/string.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/x25.h>
/*
@@ -80,7 +80,7 @@ void x25_requeue_frames(struct sock *sk)
if (!skb_prev)
skb_queue_head(&sk->sk_write_queue, skb);
else
- skb_append(skb_prev, skb);
+ skb_append(skb_prev, skb, &sk->sk_write_queue);
skb_prev = skb;
}
}
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index d6a21a3ad80e..0a92e1da3922 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -23,7 +23,7 @@
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/x25.h>
static void x25_heartbeat_expiry(unsigned long);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index c58a6f05a0b6..2407a7072327 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -12,7 +12,7 @@
#include <net/ip.h>
#include <net/xfrm.h>
-static kmem_cache_t *secpath_cachep;
+static kmem_cache_t *secpath_cachep __read_mostly;
void __secpath_destroy(struct sec_path *sp)
{
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d65ed8684fc1..fda737d77edc 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -37,7 +37,7 @@ EXPORT_SYMBOL(xfrm_policy_list);
static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
-static kmem_cache_t *xfrm_dst_cache;
+static kmem_cache_t *xfrm_dst_cache __read_mostly;
static struct work_struct xfrm_policy_gc_work;
static struct list_head xfrm_policy_gc_list =
@@ -765,8 +765,8 @@ restart:
switch (policy->action) {
case XFRM_POLICY_BLOCK:
/* Prohibit the flow */
- xfrm_pol_put(policy);
- return -EPERM;
+ err = -EPERM;
+ goto error;
case XFRM_POLICY_ALLOW:
if (policy->xfrm_nr == 0) {
@@ -782,8 +782,8 @@ restart:
*/
dst = xfrm_find_bundle(fl, policy, family);
if (IS_ERR(dst)) {
- xfrm_pol_put(policy);
- return PTR_ERR(dst);
+ err = PTR_ERR(dst);
+ goto error;
}
if (dst)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8da3e25b2c4c..c35336a0f71b 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1125,9 +1125,8 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
if (build_expire(skb, x, c->data.hard) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
}
static int xfrm_notify_sa_flush(struct km_event *c)
@@ -1152,7 +1151,8 @@ static int xfrm_notify_sa_flush(struct km_event *c)
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
nlmsg_failure:
kfree_skb(skb);
@@ -1226,7 +1226,8 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
nlmsg_failure:
rtattr_failure:
@@ -1304,9 +1305,8 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
if (build_acquire(skb, x, xt, xp, dir) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_ACQUIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_ACQUIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
}
/* User gives us xfrm_user_policy_info followed by an array of 0
@@ -1405,9 +1405,8 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
}
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
@@ -1455,7 +1454,8 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
rtattr_failure:
@@ -1480,7 +1480,8 @@ static int xfrm_notify_policy_flush(struct km_event *c)
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
kfree_skb(skb);
@@ -1519,7 +1520,8 @@ static int __init xfrm_user_init(void)
{
printk(KERN_INFO "Initializing IPsec netlink socket\n");
- xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
+ xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
+ xfrm_netlink_rcv, THIS_MODULE);
if (xfrm_nl == NULL)
return -ENOMEM;
@@ -1537,3 +1539,4 @@ static void __exit xfrm_user_exit(void)
module_init(xfrm_user_init);
module_exit(xfrm_user_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
new file mode 100644
index 000000000000..db3c708e546b
--- /dev/null
+++ b/scripts/Kbuild.include
@@ -0,0 +1,99 @@
+####
+# kbuild: Generic definitions
+
+# Convinient variables
+comma := ,
+empty :=
+space := $(empty) $(empty)
+
+###
+# The temporary file to save gcc -MD generated dependencies must not
+# contain a comma
+depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
+
+###
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+# define filechk_sample
+# echo $KERNELRELEASE
+# endef
+# version.h : Makefile
+# $(call filechk,sample)
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+# - stdin is piped in from the first prerequisite ($<) so one has
+# to specify a valid file as first prerequisite (often the kbuild file)
+define filechk
+ $(Q)set -e; \
+ echo ' CHK $@'; \
+ mkdir -p $(dir $@); \
+ $(filechk_$(1)) < $< > $@.tmp; \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ echo ' UPD $@'; \
+ mv -f $@.tmp $@; \
+ fi
+endef
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
+# Usage:
+# $(Q)$(MAKE) $(build)=dir
+build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+
+# If quiet is set, only print short version of command
+cmd = @$(if $($(quiet)cmd_$(1)),\
+ echo ' $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
+
+# Add $(obj)/ for paths that is not absolute
+objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+
+###
+# if_changed - execute command if any prerequisite is newer than
+# target, or command line has changed
+# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies
+# including used config symbols
+# if_changed_rule - as if_changed but execute rule instead
+# See Documentation/kbuild/makefiles.txt for more info
+
+ifneq ($(KBUILD_NOCMDDEP),1)
+# Check if both arguments has same arguments. Result in empty string if equal
+# User may override this check using make KBUILD_NOCMDDEP=1
+arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
+endif
+
+# echo command. Short version is $(quiet) equals quiet, otherwise full command
+echo-cmd = $(if $($(quiet)cmd_$(1)), \
+ echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';)
+
+# function to only execute the passed command if necessary
+# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
+# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
+#
+if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+ @set -e; \
+ $(echo-cmd) \
+ $(cmd_$(1)); \
+ echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+
+# execute the command and also postprocess generated .d dependencies
+# file
+if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
+ $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+ @set -e; \
+ $(echo-cmd) \
+ $(cmd_$(1)); \
+ scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+ rm -f $(depfile); \
+ mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
+
+# Usage: $(call if_changed_rule,foo)
+# will check if $(cmd_foo) changed, or any of the prequisites changed,
+# and if so will execute $(rule_foo)
+if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
+ @set -e; \
+ $(rule_$(1)))
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 76ba6be3dfc9..506e3f3befe3 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -10,8 +10,11 @@ __build:
# Read .config if it exist, otherwise ignore
-include .config
-include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
+include scripts/Kbuild.include
include scripts/Makefile.lib
ifdef host-progs
@@ -169,7 +172,7 @@ cmd_modversions = \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
else \
- mv $(@D)/.tmp_$(@F) $@; \
+ mv -f $(@D)/.tmp_$(@F) $@; \
fi;
endif
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index ff3e87dbf387..8974ea5fc878 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -7,7 +7,14 @@ src := $(obj)
.PHONY: __clean
__clean:
-include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
+# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
+# Usage:
+# $(Q)$(MAKE) $(clean)=dir
+clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
# Figure out what we need to build from the various variables
# ==========================================================================
@@ -87,8 +94,3 @@ $(subdir-ymn):
# If quiet is set, only print short version of command
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
-
-# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
-# Usage:
-# $(Q)$(MAKE) $(clean)=dir
-clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 2821a2b83bbb..2d519704b8fd 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -98,7 +98,8 @@ hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags)
# Create executable from a single .c file
# host-csingle -> Executable
quiet_cmd_host-csingle = HOSTCC $@
- cmd_host-csingle = $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
+ cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
+ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-csingle): %: %.c FORCE
$(call if_changed_dep,host-csingle)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 7cf75cc4f849..0f81dcfd6909 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -1,13 +1,3 @@
-# ===========================================================================
-# kbuild: Generic definitions
-# ===========================================================================
-
-# Standard vars
-
-comma := ,
-empty :=
-space := $(empty) $(empty)
-
# Backward compatibility - to be removed...
extra-y += $(EXTRA_TARGETS)
# Figure out what we need to build from the various variables
@@ -84,10 +74,6 @@ multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
-# The temporary file to save gcc -MD generated dependencies must not
-# contain a comma
-depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-
# These flags are needed for modversions and compiling, so we define them here
# already
# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will
@@ -179,89 +165,4 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
quiet_cmd_gzip = GZIP $@
cmd_gzip = gzip -f -9 < $< > $@
-# ===========================================================================
-# Generic stuff
-# ===========================================================================
-
-ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result in empty string if equal
-# User may override this check using make KBUILD_NOCMDDEP=1
-arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
-
-endif
-
-# echo command. Short version is $(quiet) equals quiet, otherwise full command
-echo-cmd = $(if $($(quiet)cmd_$(1)), \
- echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';)
-
-# function to only execute the passed command if necessary
-# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
-# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
-#
-if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
- @set -e; \
- $(echo-cmd) \
- $(cmd_$(1)); \
- echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
-
-
-# execute the command and also postprocess generated .d dependencies
-# file
-
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
- $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
- @set -e; \
- $(echo-cmd) \
- $(cmd_$(1)); \
- scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
- rm -f $(depfile); \
- mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
-
-# Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
-
-if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
- @set -e; \
- $(rule_$(1)))
-
-# If quiet is set, only print short version of command
-
-cmd = @$(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
-
-# $(call descend,<dir>,<target>)
-# Recursively call a sub-make in <dir> with target <target>
-# Usage is deprecated, because make do not see this as an invocation of make.
-descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
-
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
-# Usage:
-# $(Q)$(MAKE) $(build)=dir
-build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
-
-# filechk is used to check if the content of a generated file is updated.
-# Sample usage:
-# define filechk_sample
-# echo $KERNELRELEASE
-# endef
-# version.h : Makefile
-# $(call filechk,sample)
-# The rule defined shall write to stdout the content of the new file.
-# The existing file will be compared with the new one.
-# - If no file exist it is created
-# - If the content differ the new file is used
-# - If they are equal no change, and no timestamp update
-
-define filechk
- $(Q)set -e; \
- echo ' CHK $@'; \
- mkdir -p $(dir $@); \
- $(filechk_$(1)) $(2) > $@.tmp; \
- if [ -r $@ ] && cmp -s $@ $@.tmp; then \
- rm -f $@.tmp; \
- else \
- echo ' UPD $@'; \
- mv -f $@.tmp $@; \
- fi
-endef
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 85d6494e3c24..23fd1bdc25ce 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -5,7 +5,7 @@
.PHONY: __modinst
__modinst:
-include scripts/Makefile.lib
+include scripts/Kbuild.include
#
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 94b550e21be8..0c4f3a9f2ea9 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -36,6 +36,7 @@
_modpost: __modpost
include .config
+include scripts/Kbuild.include
include scripts/Makefile.lib
symverfile := $(objtree)/Module.symvers
diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c
index 93dd23f21ec9..e0c6891a9ad4 100644
--- a/scripts/conmakehash.c
+++ b/scripts/conmakehash.c
@@ -33,7 +33,7 @@ void usage(char *argv0)
int getunicode(char **p0)
{
- unsigned char *p = *p0;
+ char *p = *p0;
while (*p == ' ' || *p == '\t')
p++;
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index d3d2e5341051..d591578bd3b2 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -24,75 +24,37 @@
*
*/
+#define _GNU_SOURCE
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-/* maximum token length used. It doesn't pay to increase it a lot, because
- * very long substrings probably don't repeat themselves too often. */
-#define MAX_TOK_SIZE 11
#define KSYM_NAME_LEN 127
-/* we use only a subset of the complete symbol table to gather the token count,
- * to speed up compression, at the expense of a little compression ratio */
-#define WORKING_SET 1024
-
-/* first find the best token only on the list of tokens that would profit more
- * than GOOD_BAD_THRESHOLD. Only if this list is empty go to the "bad" list.
- * Increasing this value will put less tokens on the "good" list, so the search
- * is faster. However, if the good list runs out of tokens, we must painfully
- * search the bad list. */
-#define GOOD_BAD_THRESHOLD 10
-
-/* token hash parameters */
-#define HASH_BITS 18
-#define HASH_TABLE_SIZE (1 << HASH_BITS)
-#define HASH_MASK (HASH_TABLE_SIZE - 1)
-#define HASH_BASE_OFFSET 2166136261U
-#define HASH_FOLD(a) ((a)&(HASH_MASK))
-
-/* flags to mark symbols */
-#define SYM_FLAG_VALID 1
-#define SYM_FLAG_SAMPLED 2
struct sym_entry {
unsigned long long addr;
- char type;
- unsigned char flags;
- unsigned char len;
+ unsigned int len;
unsigned char *sym;
};
static struct sym_entry *table;
-static int size, cnt;
+static unsigned int table_size, table_cnt;
static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
static int all_symbols = 0;
static char symbol_prefix_char = '\0';
-struct token {
- unsigned char data[MAX_TOK_SIZE];
- unsigned char len;
- /* profit: the number of bytes that could be saved by inserting this
- * token into the table */
- int profit;
- struct token *next; /* next token on the hash list */
- struct token *right; /* next token on the good/bad list */
- struct token *left; /* previous token on the good/bad list */
- struct token *smaller; /* token that is less one letter than this one */
- };
-
-struct token bad_head, good_head;
-struct token *hash_table[HASH_TABLE_SIZE];
+int token_profit[0x10000];
/* the table that holds the result of the compression */
-unsigned char best_table[256][MAX_TOK_SIZE+1];
+unsigned char best_table[256][2];
unsigned char best_table_len[256];
-static void
-usage(void)
+static void usage(void)
{
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
exit(1);
@@ -102,21 +64,19 @@ usage(void)
* This ignores the intensely annoying "mapping symbols" found
* in ARM ELF files: $a, $t and $d.
*/
-static inline int
-is_arm_mapping_symbol(const char *str)
+static inline int is_arm_mapping_symbol(const char *str)
{
return str[0] == '$' && strchr("atd", str[1])
&& (str[2] == '\0' || str[2] == '.');
}
-static int
-read_symbol(FILE *in, struct sym_entry *s)
+static int read_symbol(FILE *in, struct sym_entry *s)
{
char str[500];
- char *sym;
+ char *sym, stype;
int rc;
- rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
+ rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
if (rc != 3) {
if (rc != EOF) {
/* skip line */
@@ -143,7 +103,7 @@ read_symbol(FILE *in, struct sym_entry *s)
_sextratext = s->addr;
else if (strcmp(sym, "_eextratext") == 0)
_eextratext = s->addr;
- else if (toupper(s->type) == 'A')
+ else if (toupper(stype) == 'A')
{
/* Keep these useful absolute symbols */
if (strcmp(sym, "__kernel_syscall_via_break") &&
@@ -153,22 +113,24 @@ read_symbol(FILE *in, struct sym_entry *s)
return -1;
}
- else if (toupper(s->type) == 'U' ||
+ else if (toupper(stype) == 'U' ||
is_arm_mapping_symbol(sym))
return -1;
+ /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
+ else if (str[0] == '$')
+ return -1;
/* include the type field in the symbol name, so that it gets
* compressed together */
s->len = strlen(str) + 1;
- s->sym = (char *) malloc(s->len + 1);
- strcpy(s->sym + 1, str);
- s->sym[0] = s->type;
+ s->sym = malloc(s->len + 1);
+ strcpy((char *)s->sym + 1, str);
+ s->sym[0] = stype;
return 0;
}
-static int
-symbol_valid(struct sym_entry *s)
+static int symbol_valid(struct sym_entry *s)
{
/* Symbols which vary between passes. Passes 1 and 2 must have
* identical symbol lists. The kallsyms_* symbols below are only added
@@ -207,37 +169,36 @@ symbol_valid(struct sym_entry *s)
* move then they may get dropped in pass 2, which breaks the
* kallsyms rules.
*/
- if ((s->addr == _etext && strcmp(s->sym + offset, "_etext")) ||
- (s->addr == _einittext && strcmp(s->sym + offset, "_einittext")) ||
- (s->addr == _eextratext && strcmp(s->sym + offset, "_eextratext")))
+ if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
+ (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
+ (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
return 0;
}
/* Exclude symbols which vary between passes. */
- if (strstr(s->sym + offset, "_compiled."))
+ if (strstr((char *)s->sym + offset, "_compiled."))
return 0;
for (i = 0; special_symbols[i]; i++)
- if( strcmp(s->sym + offset, special_symbols[i]) == 0 )
+ if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
return 0;
return 1;
}
-static void
-read_map(FILE *in)
+static void read_map(FILE *in)
{
while (!feof(in)) {
- if (cnt >= size) {
- size += 10000;
- table = realloc(table, sizeof(*table) * size);
+ if (table_cnt >= table_size) {
+ table_size += 10000;
+ table = realloc(table, sizeof(*table) * table_size);
if (!table) {
fprintf(stderr, "out of memory\n");
exit (1);
}
}
- if (read_symbol(in, &table[cnt]) == 0)
- cnt++;
+ if (read_symbol(in, &table[table_cnt]) == 0)
+ table_cnt++;
}
}
@@ -281,10 +242,9 @@ static int expand_symbol(unsigned char *data, int len, char *result)
return total;
}
-static void
-write_src(void)
+static void write_src(void)
{
- int i, k, off, valid;
+ unsigned int i, k, off;
unsigned int best_idx[256];
unsigned int *markers;
char buf[KSYM_NAME_LEN+1];
@@ -301,33 +261,24 @@ write_src(void)
printf(".data\n");
output_label("kallsyms_addresses");
- valid = 0;
- for (i = 0; i < cnt; i++) {
- if (table[i].flags & SYM_FLAG_VALID) {
- printf("\tPTR\t%#llx\n", table[i].addr);
- valid++;
- }
+ for (i = 0; i < table_cnt; i++) {
+ printf("\tPTR\t%#llx\n", table[i].addr);
}
printf("\n");
output_label("kallsyms_num_syms");
- printf("\tPTR\t%d\n", valid);
+ printf("\tPTR\t%d\n", table_cnt);
printf("\n");
/* table of offset markers, that give the offset in the compressed stream
* every 256 symbols */
- markers = (unsigned int *) malloc(sizeof(unsigned int)*((valid + 255) / 256));
+ markers = (unsigned int *) malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
output_label("kallsyms_names");
- valid = 0;
off = 0;
- for (i = 0; i < cnt; i++) {
-
- if (!table[i].flags & SYM_FLAG_VALID)
- continue;
-
- if ((valid & 0xFF) == 0)
- markers[valid >> 8] = off;
+ for (i = 0; i < table_cnt; i++) {
+ if ((i & 0xFF) == 0)
+ markers[i >> 8] = off;
printf("\t.byte 0x%02x", table[i].len);
for (k = 0; k < table[i].len; k++)
@@ -335,12 +286,11 @@ write_src(void)
printf("\n");
off += table[i].len + 1;
- valid++;
}
printf("\n");
output_label("kallsyms_markers");
- for (i = 0; i < ((valid + 255) >> 8); i++)
+ for (i = 0; i < ((table_cnt + 255) >> 8); i++)
printf("\tPTR\t%d\n", markers[i]);
printf("\n");
@@ -350,7 +300,7 @@ write_src(void)
off = 0;
for (i = 0; i < 256; i++) {
best_idx[i] = off;
- expand_symbol(best_table[i],best_table_len[i],buf);
+ expand_symbol(best_table[i], best_table_len[i], buf);
printf("\t.asciz\t\"%s\"\n", buf);
off += strlen(buf) + 1;
}
@@ -365,153 +315,13 @@ write_src(void)
/* table lookup compression functions */
-static inline unsigned int rehash_token(unsigned int hash, unsigned char data)
-{
- return ((hash * 16777619) ^ data);
-}
-
-static unsigned int hash_token(unsigned char *data, int len)
-{
- unsigned int hash=HASH_BASE_OFFSET;
- int i;
-
- for (i = 0; i < len; i++)
- hash = rehash_token(hash, data[i]);
-
- return HASH_FOLD(hash);
-}
-
-/* find a token given its data and hash value */
-static struct token *find_token_hash(unsigned char *data, int len, unsigned int hash)
-{
- struct token *ptr;
-
- ptr = hash_table[hash];
-
- while (ptr) {
- if ((ptr->len == len) && (memcmp(ptr->data, data, len) == 0))
- return ptr;
- ptr=ptr->next;
- }
-
- return NULL;
-}
-
-static inline void insert_token_in_group(struct token *head, struct token *ptr)
-{
- ptr->right = head->right;
- ptr->right->left = ptr;
- head->right = ptr;
- ptr->left = head;
-}
-
-static inline void remove_token_from_group(struct token *ptr)
-{
- ptr->left->right = ptr->right;
- ptr->right->left = ptr->left;
-}
-
-
-/* build the counts for all the tokens that start with "data", and have lenghts
- * from 2 to "len" */
-static void learn_token(unsigned char *data, int len)
-{
- struct token *ptr,*last_ptr;
- int i, newprofit;
- unsigned int hash = HASH_BASE_OFFSET;
- unsigned int hashes[MAX_TOK_SIZE + 1];
-
- if (len > MAX_TOK_SIZE)
- len = MAX_TOK_SIZE;
-
- /* calculate and store the hash values for all the sub-tokens */
- hash = rehash_token(hash, data[0]);
- for (i = 2; i <= len; i++) {
- hash = rehash_token(hash, data[i-1]);
- hashes[i] = HASH_FOLD(hash);
- }
-
- last_ptr = NULL;
- ptr = NULL;
-
- for (i = len; i >= 2; i--) {
- hash = hashes[i];
-
- if (!ptr) ptr = find_token_hash(data, i, hash);
-
- if (!ptr) {
- /* create a new token entry */
- ptr = (struct token *) malloc(sizeof(*ptr));
-
- memcpy(ptr->data, data, i);
- ptr->len = i;
-
- /* when we create an entry, it's profit is 0 because
- * we also take into account the size of the token on
- * the compressed table. We then subtract GOOD_BAD_THRESHOLD
- * so that the test to see if this token belongs to
- * the good or bad list, is a comparison to zero */
- ptr->profit = -GOOD_BAD_THRESHOLD;
-
- ptr->next = hash_table[hash];
- hash_table[hash] = ptr;
-
- insert_token_in_group(&bad_head, ptr);
-
- ptr->smaller = NULL;
- } else {
- newprofit = ptr->profit + (ptr->len - 1);
- /* check to see if this token needs to be moved to a
- * different list */
- if((ptr->profit < 0) && (newprofit >= 0)) {
- remove_token_from_group(ptr);
- insert_token_in_group(&good_head,ptr);
- }
- ptr->profit = newprofit;
- }
-
- if (last_ptr) last_ptr->smaller = ptr;
- last_ptr = ptr;
-
- ptr = ptr->smaller;
- }
-}
-
-/* decrease the counts for all the tokens that start with "data", and have lenghts
- * from 2 to "len". This function is much simpler than learn_token because we have
- * more guarantees (tho tokens exist, the ->smaller pointer is set, etc.)
- * The two separate functions exist only because of compression performance */
-static void forget_token(unsigned char *data, int len)
-{
- struct token *ptr;
- int i, newprofit;
- unsigned int hash=0;
-
- if (len > MAX_TOK_SIZE) len = MAX_TOK_SIZE;
-
- hash = hash_token(data, len);
- ptr = find_token_hash(data, len, hash);
-
- for (i = len; i >= 2; i--) {
-
- newprofit = ptr->profit - (ptr->len - 1);
- if ((ptr->profit >= 0) && (newprofit < 0)) {
- remove_token_from_group(ptr);
- insert_token_in_group(&bad_head, ptr);
- }
- ptr->profit=newprofit;
-
- ptr=ptr->smaller;
- }
-}
-
/* count all the possible tokens in a symbol */
static void learn_symbol(unsigned char *symbol, int len)
{
int i;
for (i = 0; i < len - 1; i++)
- learn_token(symbol + i, len - i);
+ token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
}
/* decrease the count for all the possible tokens in a symbol */
@@ -520,117 +330,90 @@ static void forget_symbol(unsigned char *symbol, int len)
int i;
for (i = 0; i < len - 1; i++)
- forget_token(symbol + i, len - i);
+ token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
}
-/* set all the symbol flags and do the initial token count */
+/* remove all the invalid symbols from the table and do the initial token count */
static void build_initial_tok_table(void)
{
- int i, use_it, valid;
+ unsigned int i, pos;
- valid = 0;
- for (i = 0; i < cnt; i++) {
- table[i].flags = 0;
+ pos = 0;
+ for (i = 0; i < table_cnt; i++) {
if ( symbol_valid(&table[i]) ) {
- table[i].flags |= SYM_FLAG_VALID;
- valid++;
+ if (pos != i)
+ table[pos] = table[i];
+ learn_symbol(table[pos].sym, table[pos].len);
+ pos++;
}
}
-
- use_it = 0;
- for (i = 0; i < cnt; i++) {
-
- /* subsample the available symbols. This method is almost like
- * a Bresenham's algorithm to get uniformly distributed samples
- * across the symbol table */
- if (table[i].flags & SYM_FLAG_VALID) {
-
- use_it += WORKING_SET;
-
- if (use_it >= valid) {
- table[i].flags |= SYM_FLAG_SAMPLED;
- use_it -= valid;
- }
- }
- if (table[i].flags & SYM_FLAG_SAMPLED)
- learn_symbol(table[i].sym, table[i].len);
- }
+ table_cnt = pos;
}
/* replace a given token in all the valid symbols. Use the sampled symbols
* to update the counts */
-static void compress_symbols(unsigned char *str, int tlen, int idx)
+static void compress_symbols(unsigned char *str, int idx)
{
- int i, len, learn, size;
- unsigned char *p;
+ unsigned int i, len, size;
+ unsigned char *p1, *p2;
- for (i = 0; i < cnt; i++) {
-
- if (!(table[i].flags & SYM_FLAG_VALID)) continue;
+ for (i = 0; i < table_cnt; i++) {
len = table[i].len;
- learn = 0;
- p = table[i].sym;
+ p1 = table[i].sym;
+
+ /* find the token on the symbol */
+ p2 = memmem(p1, len, str, 2);
+ if (!p2) continue;
+
+ /* decrease the counts for this symbol's tokens */
+ forget_symbol(table[i].sym, len);
+
+ size = len;
do {
+ *p2 = idx;
+ p2++;
+ size -= (p2 - p1);
+ memmove(p2, p2 + 1, size);
+ p1 = p2;
+ len--;
+
+ if (size < 2) break;
+
/* find the token on the symbol */
- p = (unsigned char *) strstr((char *) p, (char *) str);
- if (!p) break;
-
- if (!learn) {
- /* if this symbol was used to count, decrease it */
- if (table[i].flags & SYM_FLAG_SAMPLED)
- forget_symbol(table[i].sym, len);
- learn = 1;
- }
+ p2 = memmem(p1, size, str, 2);
- *p = idx;
- size = (len - (p - table[i].sym)) - tlen + 1;
- memmove(p + 1, p + tlen, size);
- p++;
- len -= tlen - 1;
+ } while (p2);
- } while (size >= tlen);
+ table[i].len = len;
- if(learn) {
- table[i].len = len;
- /* if this symbol was used to count, learn it again */
- if(table[i].flags & SYM_FLAG_SAMPLED)
- learn_symbol(table[i].sym, len);
- }
+ /* increase the counts for this symbol's new tokens */
+ learn_symbol(table[i].sym, len);
}
}
/* search the token with the maximum profit */
-static struct token *find_best_token(void)
+static int find_best_token(void)
{
- struct token *ptr,*best,*head;
- int bestprofit;
+ int i, best, bestprofit;
bestprofit=-10000;
+ best = 0;
- /* failsafe: if the "good" list is empty search from the "bad" list */
- if(good_head.right == &good_head) head = &bad_head;
- else head = &good_head;
-
- ptr = head->right;
- best = NULL;
- while (ptr != head) {
- if (ptr->profit > bestprofit) {
- bestprofit = ptr->profit;
- best = ptr;
+ for (i = 0; i < 0x10000; i++) {
+ if (token_profit[i] > bestprofit) {
+ best = i;
+ bestprofit = token_profit[i];
}
- ptr = ptr->right;
}
-
return best;
}
/* this is the core of the algorithm: calculate the "best" table */
static void optimize_result(void)
{
- struct token *best;
- int i;
+ int i, best;
/* using the '\0' symbol last allows compress_symbols to use standard
* fast string functions */
@@ -644,14 +427,12 @@ static void optimize_result(void)
best = find_best_token();
/* place it in the "best" table */
- best_table_len[i] = best->len;
- memcpy(best_table[i], best->data, best_table_len[i]);
- /* zero terminate the token so that we can use strstr
- in compress_symbols */
- best_table[i][best_table_len[i]]='\0';
+ best_table_len[i] = 2;
+ best_table[i][0] = best & 0xFF;
+ best_table[i][1] = (best >> 8) & 0xFF;
/* replace this token in all the valid symbols */
- compress_symbols(best_table[i], best_table_len[i], i);
+ compress_symbols(best_table[i], i);
}
}
}
@@ -659,39 +440,28 @@ static void optimize_result(void)
/* start by placing the symbols that are actually used on the table */
static void insert_real_symbols_in_table(void)
{
- int i, j, c;
+ unsigned int i, j, c;
memset(best_table, 0, sizeof(best_table));
memset(best_table_len, 0, sizeof(best_table_len));
- for (i = 0; i < cnt; i++) {
- if (table[i].flags & SYM_FLAG_VALID) {
- for (j = 0; j < table[i].len; j++) {
- c = table[i].sym[j];
- best_table[c][0]=c;
- best_table_len[c]=1;
- }
+ for (i = 0; i < table_cnt; i++) {
+ for (j = 0; j < table[i].len; j++) {
+ c = table[i].sym[j];
+ best_table[c][0]=c;
+ best_table_len[c]=1;
}
}
}
static void optimize_token_table(void)
{
- memset(hash_table, 0, sizeof(hash_table));
-
- good_head.left = &good_head;
- good_head.right = &good_head;
-
- bad_head.left = &bad_head;
- bad_head.right = &bad_head;
-
build_initial_tok_table();
insert_real_symbols_in_table();
/* When valid symbol is not registered, exit to error */
- if (good_head.left == good_head.right &&
- bad_head.left == bad_head.right) {
+ if (!table_cnt) {
fprintf(stderr, "No valid symbol.\n");
exit(1);
}
@@ -700,8 +470,7 @@ static void optimize_token_table(void)
}
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
if (argc >= 2) {
int i;
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 09abb891d11f..2fcb244a9e18 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -27,8 +27,20 @@ update-po-config: $(obj)/kxgettext
xgettext --default-domain=linux \
--add-comments --keyword=_ --keyword=N_ \
--files-from=scripts/kconfig/POTFILES.in \
- -o scripts/kconfig/linux.pot
- scripts/kconfig/kxgettext arch/$(ARCH)/Kconfig >> scripts/kconfig/linux.pot
+ --output scripts/kconfig/config.pot
+ $(Q)ln -fs Kconfig_i386 arch/um/Kconfig_arch
+ $(Q)for i in `ls arch/`; \
+ do \
+ scripts/kconfig/kxgettext arch/$$i/Kconfig \
+ | msguniq -o scripts/kconfig/linux_$${i}.pot; \
+ done
+ $(Q)msgcat scripts/kconfig/config.pot \
+ `find scripts/kconfig/ -type f -name linux_*.pot` \
+ --output scripts/kconfig/linux_raw.pot
+ $(Q)msguniq --sort-by-file scripts/kconfig/linux_raw.pot \
+ --output scripts/kconfig/linux.pot
+ $(Q)rm -f arch/um/Kconfig_arch
+ $(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot
.PHONY: randconfig allyesconfig allnoconfig allmodconfig defconfig
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
index 1c88d7c6d5a7..abee55ca6174 100644
--- a/scripts/kconfig/kxgettext.c
+++ b/scripts/kconfig/kxgettext.c
@@ -14,6 +14,11 @@ static char *escape(const char* text, char *bf, int len)
{
char *bfp = bf;
int multiline = strchr(text, '\n') != NULL;
+ int eol = 0;
+ int textlen = strlen(text);
+
+ if ((textlen > 0) && (text[textlen-1] == '\n'))
+ eol = 1;
*bfp++ = '"';
--len;
@@ -43,7 +48,7 @@ next:
--len;
}
- if (multiline)
+ if (multiline && eol)
bfp -= 3;
*bfp++ = '"';
@@ -179,7 +184,11 @@ static void message__print_file_lineno(struct message *self)
{
struct file_line *fl = self->files;
- printf("\n#: %s:%d", fl->file, fl->lineno);
+ putchar('\n');
+ if (self->option != NULL)
+ printf("# %s:00000\n", self->option);
+
+ printf("#: %s:%d", fl->file, fl->lineno);
fl = fl->next;
while (fl != NULL) {
@@ -187,9 +196,6 @@ static void message__print_file_lineno(struct message *self)
fl = fl->next;
}
- if (self->option != NULL)
- printf(", %s:00000", self->option);
-
putchar('\n');
}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 8b84c42b49b5..c3d25786a64d 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -59,7 +59,7 @@ void menu_add_entry(struct symbol *sym);
void menu_end_entry(void);
void menu_add_dep(struct expr *dep);
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
void menu_finalize(struct menu *parent);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c59b212722d..5cfa6c405cf0 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -136,9 +136,9 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
return prop;
}
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
{
- menu_add_prop(type, prompt, NULL, dep);
+ return menu_add_prop(type, prompt, NULL, dep);
}
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index f163d8d2d9ef..ff4fcc09720e 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1531,7 +1531,7 @@ yyreduce:
{
menu_add_entry(NULL);
- menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL);
+ menu_add_prompt(P_MENU, yyvsp[-1].string, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1586,7 +1586,7 @@ yyreduce:
{
menu_add_entry(NULL);
- menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL);
+ menu_add_prompt(P_COMMENT, yyvsp[-1].string, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
;}
break;
@@ -1640,7 +1640,7 @@ yyreduce:
case 86:
{
- menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
+ menu_add_prompt(P_PROMPT, yyvsp[-1].string, yyvsp[0].expr);
;}
break;
@@ -1925,7 +1925,7 @@ void conf_parse(const char *name)
sym_init();
menu_init();
modules_sym = sym_lookup("MODULES", 0);
- rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
+ rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
//zconfdebug = 1;
zconfparse();
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 54460f8d3696..e1a0f455d4a8 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -342,7 +342,7 @@ if_block:
menu: T_MENU prompt T_EOL
{
menu_add_entry(NULL);
- menu_add_prop(P_MENU, $2, NULL, NULL);
+ menu_add_prompt(P_MENU, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
};
@@ -392,7 +392,7 @@ source_stmt: source
comment: T_COMMENT prompt T_EOL
{
menu_add_entry(NULL);
- menu_add_prop(P_COMMENT, $2, NULL, NULL);
+ menu_add_prompt(P_COMMENT, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
};
@@ -443,7 +443,7 @@ prompt_stmt_opt:
/* empty */
| prompt if_expr
{
- menu_add_prop(P_PROMPT, $1, NULL, $2);
+ menu_add_prompt(P_PROMPT, $1, $2);
};
prompt: T_WORD
@@ -487,7 +487,7 @@ void conf_parse(const char *name)
sym_init();
menu_init();
modules_sym = sym_lookup("MODULES", 0);
- rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
+ rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
//zconfdebug = 1;
zconfparse();
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 0835dc2a8aa9..8aaf74e64183 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1665,11 +1665,17 @@ sub xml_escape($) {
}
sub process_file($) {
- my ($file) = "$ENV{'SRCTREE'}@_";
+ my $file;
my $identifier;
my $func;
my $initial_section_counter = $section_counter;
+ if (defined($ENV{'SRCTREE'})) {
+ $file = "$ENV{'SRCTREE'}" . "/" . "@_";
+ }
+ else {
+ $file = "@_";
+ }
if (defined($source_map{$file})) {
$file = $source_map{$file};
}
diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h
index c571548daa82..eb63e1bb63a3 100644
--- a/scripts/lxdialog/dialog.h
+++ b/scripts/lxdialog/dialog.h
@@ -163,7 +163,7 @@ int dialog_menu (const char *title, const char *prompt, int height, int width,
int dialog_checklist (const char *title, const char *prompt, int height,
int width, int list_height, int item_no,
const char * const * items, int flag);
-extern unsigned char dialog_input_result[];
+extern char dialog_input_result[];
int dialog_inputbox (const char *title, const char *prompt, int height,
int width, const char *init);
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
index fa7bebc693b9..074d2d68bd31 100644
--- a/scripts/lxdialog/inputbox.c
+++ b/scripts/lxdialog/inputbox.c
@@ -21,7 +21,7 @@
#include "dialog.h"
-unsigned char dialog_input_result[MAX_LEN + 1];
+char dialog_input_result[MAX_LEN + 1];
/*
* Print the termination buttons
@@ -48,7 +48,7 @@ dialog_inputbox (const char *title, const char *prompt, int height, int width,
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1;
- unsigned char *instr = dialog_input_result;
+ char *instr = dialog_input_result;
WINDOW *dialog;
/* center dialog box on screen */
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 8d118d181950..d7b8a384b4a7 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -1,7 +1,8 @@
TARGET=$1
ARCH=$2
SMP=$3
-CC=$4
+PREEMPT=$4
+CC=$5
# If compile.h exists already and we don't own autoconf.h
# (i.e. we're not the same user who did make *config), don't
@@ -26,8 +27,10 @@ fi
UTS_VERSION="#$VERSION"
-if [ -n "$SMP" ] ; then UTS_VERSION="$UTS_VERSION SMP"; fi
-UTS_VERSION="$UTS_VERSION `LC_ALL=C LANG=C date`"
+CONFIG_FLAGS=""
+if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
+if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
+UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS `LC_ALL=C LANG=C date`"
# Truncate to maximum length
@@ -37,7 +40,8 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
# Generate a temporary compile.h
( echo /\* This file is auto generated, version $VERSION \*/
-
+ if [ -n "$CONFIG_FLAGS" ] ; then echo "/* $CONFIG_FLAGS */"; fi
+
echo \#define UTS_MACHINE \"$ARCH\"
echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5180405c1a84..d8ee38aede26 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -341,6 +341,22 @@ static int do_of_entry (const char *filename, struct of_device_id *of, char *ali
return 1;
}
+static int do_vio_entry(const char *filename, struct vio_device_id *vio,
+ char *alias)
+{
+ char *tmp;
+
+ sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
+ vio->compat[0] ? vio->compat : "*");
+
+ /* Replace all whitespace with underscores */
+ for (tmp = alias; tmp && *tmp; tmp++)
+ if (isspace (*tmp))
+ *tmp = '_';
+
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -422,6 +438,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
else if (sym_is(symname, "__mod_of_device_table"))
do_table(symval, sym->st_size, sizeof(struct of_device_id),
do_of_entry, mod);
+ else if (sym_is(symname, "__mod_vio_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct vio_device_id),
+ do_vio_entry, mod);
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 09ffca54b373..3bed09e625c0 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -370,6 +370,12 @@ handle_modversions(struct module *mod, struct elf_info *info,
/* Ignore register directives. */
if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
break;
+ if (symname[0] == '.') {
+ char *munged = strdup(symname);
+ munged[0] = '_';
+ munged[1] = toupper(munged[1]);
+ symname = munged;
+ }
}
#endif
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 1112347245c0..43271a1ca01e 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -252,9 +252,9 @@ static int parse_comment(const char *file, unsigned long len)
}
/* FIXME: Handle .s files differently (eg. # starts comments) --RR */
-static int parse_file(const signed char *fname, struct md4_ctx *md)
+static int parse_file(const char *fname, struct md4_ctx *md)
{
- signed char *file;
+ char *file;
unsigned long i, len;
file = grab_file(fname, &len);
@@ -332,7 +332,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
Sum all files in the same dir or subdirs.
*/
while ((line = get_next_line(&pos, file, flen)) != NULL) {
- signed char* p = line;
+ char* p = line;
if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
check_files = 1;
continue;
@@ -458,7 +458,7 @@ out:
close(fd);
}
-static int strip_rcs_crap(signed char *version)
+static int strip_rcs_crap(char *version)
{
unsigned int len, full_len;
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 3b1f2eff2584..f3e7e8e4a500 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -59,7 +59,7 @@ $(objtree)/binkernel.spec: $(MKSPEC) $(srctree)/Makefile
$(CONFIG_SHELL) $(MKSPEC) prebuilt > $@
binrpm-pkg: $(objtree)/binkernel.spec
- $(MAKE)
+ $(MAKE) KBUILD_SRC=
set -e; \
$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
set -e; \
@@ -74,16 +74,30 @@ clean-files += $(objtree)/binkernel.spec
#
.PHONY: deb-pkg
deb-pkg:
- $(MAKE)
+ $(MAKE) KBUILD_SRC=
$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
clean-dirs += $(objtree)/debian/
+# tarball targets
+# ---------------------------------------------------------------------------
+.PHONY: tar%pkg
+tar%pkg:
+ $(MAKE)
+ $(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
+
+clean-dirs += $(objtree)/tar-install/
+
+
# Help text displayed when executing 'make help'
# ---------------------------------------------------------------------------
help:
- @echo ' rpm-pkg - Build the kernel as an RPM package'
- @echo ' binrpm-pkg - Build an rpm package containing the compiled kernel & modules'
- @echo ' deb-pkg - Build the kernel as an deb package'
+ @echo ' rpm-pkg - Build the kernel as an RPM package'
+ @echo ' binrpm-pkg - Build an rpm package containing the compiled kernel'
+ @echo ' and modules'
+ @echo ' deb-pkg - Build the kernel as an deb package'
+ @echo ' tar-pkg - Build the kernel as an uncompressed tarball'
+ @echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
+ @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index c279b6310f02..6edb29f2b4a6 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -14,18 +14,38 @@ set -e
# Some variables and settings used throughout the script
version=$KERNELRELEASE
tmpdir="$objtree/debian/tmp"
+packagename=linux-$version
+
+if [ "$ARCH" == "um" ] ; then
+ packagename=user-mode-linux-$version
+fi
# Setup the directory structure
rm -rf "$tmpdir"
mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
+if [ "$ARCH" == "um" ] ; then
+ mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/share/doc/$packagename" "$tmpdir/usr/bin"
+fi
# Build and install the kernel
-cp System.map "$tmpdir/boot/System.map-$version"
-cp .config "$tmpdir/boot/config-$version"
-cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+if [ "$ARCH" == "um" ] ; then
+ $MAKE linux
+ cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
+ cp .config "$tmpdir/usr/share/doc/$packagename/config"
+ gzip "$tmpdir/usr/share/doc/$packagename/config"
+ cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version"
+else
+ cp System.map "$tmpdir/boot/System.map-$version"
+ cp .config "$tmpdir/boot/config-$version"
+ cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+fi
if grep -q '^CONFIG_MODULES=y' .config ; then
- INSTALL_MOD_PATH="$tmpdir" make modules_install
+ INSTALL_MOD_PATH="$tmpdir" make KBUILD_SRC= modules_install
+ if [ "$ARCH" == "um" ] ; then
+ mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
+ rmdir "$tmpdir/lib/modules/$version"
+ fi
fi
# Install the maintainer scripts
@@ -53,6 +73,8 @@ linux ($version) unstable; urgency=low
EOF
# Generate a control file
+if [ "$ARCH" == "um" ]; then
+
cat <<EOF > debian/control
Source: linux
Section: base
@@ -60,12 +82,34 @@ Priority: optional
Maintainer: $name
Standards-Version: 3.6.1
-Package: linux-$version
+Package: $packagename
+Architecture: any
+Description: User Mode Linux kernel, version $version
+ User-mode Linux is a port of the Linux kernel to its own system call
+ interface. It provides a kind of virtual machine, which runs Linux
+ as a user process under another Linux kernel. This is useful for
+ kernel development, sandboxes, jails, experimentation, and
+ many other things.
+ .
+ This package contains the Linux kernel, modules and corresponding other
+ files version $version
+EOF
+
+else
+cat <<EOF > debian/control
+Source: linux
+Section: base
+Priority: optional
+Maintainer: $name
+Standards-Version: 3.6.1
+
+Package: $packagename
Architecture: any
Description: Linux kernel, version $version
This package contains the Linux kernel, modules and corresponding other
- files version $version.
+ files version $version
EOF
+fi
# Fix some ownership and permissions
chown -R root:root "$tmpdir"
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
new file mode 100644
index 000000000000..d8fffe6f8906
--- /dev/null
+++ b/scripts/package/buildtar
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+#
+# buildtar 0.0.3
+#
+# (C) 2004-2005 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
+#
+# This script is used to compile a tarball from the currently
+# prepared kernel. Based upon the builddeb script from
+# Wichert Akkerman <wichert@wiggy.net>.
+#
+
+set -e
+
+#
+# Some variables and settings used throughout the script
+#
+version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}${EXTRANAME}"
+tmpdir="${objtree}/tar-install"
+tarball="${objtree}/linux-${version}.tar"
+
+
+#
+# Figure out how to compress, if requested at all
+#
+case "${1}" in
+ tar-pkg)
+ compress="cat"
+ file_ext=""
+ ;;
+ targz-pkg)
+ compress="gzip -c9"
+ file_ext=".gz"
+ ;;
+ tarbz2-pkg)
+ compress="bzip2 -c9"
+ file_ext=".bz2"
+ ;;
+ *)
+ echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2
+ exit 1
+ ;;
+esac
+
+
+#
+# Clean-up and re-create the temporary directory
+#
+rm -rf -- "${tmpdir}"
+mkdir -p -- "${tmpdir}/boot"
+
+
+#
+# Try to install modules
+#
+if ! make INSTALL_MOD_PATH="${tmpdir}" modules_install; then
+ echo "" >&2
+ echo "Ignoring error at module_install time, since that could be" >&2
+ echo "a result of missing local modutils/module-init-tools," >&2
+ echo "or you just didn't compile in module support at all..." >&2
+ echo "" >&2
+fi
+
+
+#
+# Install basic kernel files
+#
+cp -v -- System.map "${tmpdir}/boot/System.map-${version}"
+cp -v -- .config "${tmpdir}/boot/config-${version}"
+cp -v -- vmlinux "${tmpdir}/boot/vmlinux-${version}"
+
+
+#
+# Install arch-specific kernel image(s)
+#
+case "${ARCH}" in
+ i386)
+ [ -f arch/i386/boot/bzImage ] && cp -v -- arch/i386/boot/bzImage "${tmpdir}/boot/vmlinuz-${version}"
+ ;;
+ alpha)
+ [ -f arch/alpha/boot/vmlinux.gz ] && cp -v -- arch/alpha/boot/vmlinux.gz "${tmpdir}/boot/vmlinuz-${version}"
+ ;;
+ vax)
+ [ -f vmlinux.SYS ] && cp -v -- vmlinux.SYS "${tmpdir}/boot/vmlinux-${version}.SYS"
+ [ -f vmlinux.dsk ] && cp -v -- vmlinux.dsk "${tmpdir}/boot/vmlinux-${version}.dsk"
+ ;;
+ *)
+ [ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${version}"
+ echo "" >&2
+ echo '** ** ** WARNING ** ** **' >&2
+ echo "" >&2
+ echo "Your architecture did not define any architecture-dependant files" >&2
+ echo "to be placed into the tarball. Please add those to ${0} ..." >&2
+ echo "" >&2
+ sleep 5
+ ;;
+esac
+
+
+#
+# Create the tarball
+#
+(
+ cd "${tmpdir}"
+ tar cf - . | ${compress} > "${tarball}${file_ext}"
+)
+
+echo "Tarball successfully created in ${tarball}${file_ext}"
+
+exit 0
+
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 6e7a58f145ad..0b1038737548 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -62,10 +62,19 @@ echo ""
fi
echo "%install"
+echo "%ifarch ia64"
+echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+echo "%else"
echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+echo "%endif"
echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo "%ifarch ia64"
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
+echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
+echo "%else"
echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
+echo "%endif"
echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl
index d5cabb81bd1b..c2d54148a91f 100644
--- a/scripts/reference_discarded.pl
+++ b/scripts/reference_discarded.pl
@@ -91,11 +91,7 @@ foreach $object (keys(%object)) {
$from !~ /\.exit\.data$/ &&
$from !~ /\.altinstructions$/ &&
$from !~ /\.pdr$/ &&
- $from !~ /\.debug_info$/ &&
- $from !~ /\.debug_aranges$/ &&
- $from !~ /\.debug_ranges$/ &&
- $from !~ /\.debug_line$/ &&
- $from !~ /\.debug_frame$/ &&
+ $from !~ /\.debug_.*$/ &&
$from !~ /\.exitcall\.exit$/ &&
$from !~ /\.eh_frame$/ &&
$from !~ /\.stab$/)) {
diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl
index 9a2408453869..7f6960b175a2 100644
--- a/scripts/reference_init.pl
+++ b/scripts/reference_init.pl
@@ -98,6 +98,7 @@ foreach $object (sort(keys(%object))) {
$from !~ /\.pdr$/ &&
$from !~ /\__param$/ &&
$from !~ /\.altinstructions/ &&
+ $from !~ /\.eh_frame/ &&
$from !~ /\.debug_/)) {
printf("Error: %s %s refers to %s\n", $object, $from, $line);
}
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
new file mode 100644
index 000000000000..7c805c8fccd2
--- /dev/null
+++ b/scripts/setlocalversion
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+# Copyright 2004 - Ryan Anderson <ryan@michonline.com> GPL v2
+
+use strict;
+use warnings;
+use Digest::MD5;
+require 5.006;
+
+if (@ARGV != 1) {
+ print <<EOT;
+Usage: setlocalversion <srctree>
+EOT
+ exit(1);
+}
+
+my ($srctree) = @ARGV;
+chdir($srctree);
+
+my @LOCALVERSIONS = ();
+
+# We are going to use the following commands to try and determine if this
+# repository is at a Version boundary (i.e, 2.6.10 vs 2.6.10 + some patches) We
+# currently assume that all meaningful version boundaries are marked by a tag.
+# We don't care what the tag is, just that something exists.
+
+# Git/Cogito store the top-of-tree "commit" in .git/HEAD
+# A list of known tags sits in .git/refs/tags/
+#
+# The simple trick here is to just compare the two of these, and if we get a
+# match, return nothing, otherwise, return a subset of the SHA-1 hash in
+# .git/HEAD
+
+sub do_git_checks {
+ open(H,"<.git/HEAD") or return;
+ my $head = <H>;
+ chomp $head;
+ close(H);
+
+ opendir(D,".git/refs/tags") or return;
+ foreach my $tagfile (grep !/^\.{1,2}$/, readdir(D)) {
+ open(F,"<.git/refs/tags/" . $tagfile) or return;
+ my $tag = <F>;
+ chomp $tag;
+ close(F);
+ return if ($tag eq $head);
+ }
+ closedir(D);
+
+ push @LOCALVERSIONS, "g" . substr($head,0,8);
+}
+
+if ( -d ".git") {
+ do_git_checks();
+}
+
+printf "-%s\n", join("-",@LOCALVERSIONS) if (scalar @LOCALVERSIONS > 0);
diff --git a/scripts/ver_linux b/scripts/ver_linux
index a28c279c49dd..beb43ef7f761 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -25,9 +25,11 @@ ld -v | awk -F\) '{print $1}' | awk \
'/BFD/{print "binutils ",$NF} \
/^GNU/{print "binutils ",$4}'
-fdformat --version | awk -F\- '{print "util-linux ", $NF}'
+echo -n "util-linux "
+fdformat --version | awk '{print $NF}' | sed -e s/^util-linux-// -e s/\)$//
-mount --version | awk -F\- '{print "mount ", $NF}'
+echo -n "mount "
+mount --version | awk '{print $NF}' | sed -e s/^mount-// -e s/\)$//
depmod -V 2>&1 | awk 'NR==1 {print "module-init-tools ",$NF}'
diff --git a/security/dummy.c b/security/dummy.c
index 6ff887586479..9623a61dfc76 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -258,16 +258,16 @@ static void dummy_inode_free_security (struct inode *inode)
return;
}
-static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
- int mask)
+static int dummy_inode_init_security (struct inode *inode, struct inode *dir,
+ char **name, void **value, size_t *len)
{
- return 0;
+ return -EOPNOTSUPP;
}
-static void dummy_inode_post_create (struct inode *inode, struct dentry *dentry,
- int mask)
+static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
+ int mask)
{
- return;
+ return 0;
}
static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
@@ -276,13 +276,6 @@ static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
return 0;
}
-static void dummy_inode_post_link (struct dentry *old_dentry,
- struct inode *inode,
- struct dentry *new_dentry)
-{
- return;
-}
-
static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
{
return 0;
@@ -294,24 +287,12 @@ static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
return 0;
}
-static void dummy_inode_post_symlink (struct inode *inode,
- struct dentry *dentry, const char *name)
-{
- return;
-}
-
static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
int mask)
{
return 0;
}
-static void dummy_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
- int mask)
-{
- return;
-}
-
static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
{
return 0;
@@ -323,12 +304,6 @@ static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
return 0;
}
-static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry,
- int mode, dev_t dev)
-{
- return;
-}
-
static int dummy_inode_rename (struct inode *old_inode,
struct dentry *old_dentry,
struct inode *new_inode,
@@ -337,14 +312,6 @@ static int dummy_inode_rename (struct inode *old_inode,
return 0;
}
-static void dummy_inode_post_rename (struct inode *old_inode,
- struct dentry *old_dentry,
- struct inode *new_inode,
- struct dentry *new_dentry)
-{
- return;
-}
-
static int dummy_inode_readlink (struct dentry *dentry)
{
return 0;
@@ -886,20 +853,15 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sb_post_pivotroot);
set_to_dummy_if_null(ops, inode_alloc_security);
set_to_dummy_if_null(ops, inode_free_security);
+ set_to_dummy_if_null(ops, inode_init_security);
set_to_dummy_if_null(ops, inode_create);
- set_to_dummy_if_null(ops, inode_post_create);
set_to_dummy_if_null(ops, inode_link);
- set_to_dummy_if_null(ops, inode_post_link);
set_to_dummy_if_null(ops, inode_unlink);
set_to_dummy_if_null(ops, inode_symlink);
- set_to_dummy_if_null(ops, inode_post_symlink);
set_to_dummy_if_null(ops, inode_mkdir);
- set_to_dummy_if_null(ops, inode_post_mkdir);
set_to_dummy_if_null(ops, inode_rmdir);
set_to_dummy_if_null(ops, inode_mknod);
- set_to_dummy_if_null(ops, inode_post_mknod);
set_to_dummy_if_null(ops, inode_rename);
- set_to_dummy_if_null(ops, inode_post_rename);
set_to_dummy_if_null(ops, inode_readlink);
set_to_dummy_if_null(ops, inode_follow_link);
set_to_dummy_if_null(ops, inode_permission);
diff --git a/security/seclvl.c b/security/seclvl.c
index c8e87b22c9bd..96b1f2122f67 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -321,7 +321,7 @@ plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len)
"bytes.\n", len, PAGE_SIZE);
return -ENOMEM;
}
- tfm = crypto_alloc_tfm("sha1", 0);
+ tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL) {
seclvl_printk(0, KERN_ERR,
"Failed to load transform for SHA1\n");
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 2d088bb65ee8..12e4fb72bf0f 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -490,7 +490,7 @@ out:
}
static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
- struct in6_addr *addr, u16 port,
+ struct in6_addr *addr, __be16 port,
char *name1, char *name2)
{
if (!ipv6_addr_any(addr))
@@ -501,7 +501,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
}
static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr,
- u16 port, char *name1, char *name2)
+ __be16 port, char *name1, char *name2)
{
if (addr)
audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr));
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9f9463000683..6e4937fe062b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -659,7 +659,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_NETLINK_ROUTE_SOCKET;
case NETLINK_FIREWALL:
return SECCLASS_NETLINK_FIREWALL_SOCKET;
- case NETLINK_TCPDIAG:
+ case NETLINK_INET_DIAG:
return SECCLASS_NETLINK_TCPDIAG_SOCKET;
case NETLINK_NFLOG:
return SECCLASS_NETLINK_NFLOG_SOCKET;
@@ -1265,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid)
return 0;
}
-/* Set the security attributes on a newly created file. */
-static int post_create(struct inode *dir,
- struct dentry *dentry)
-{
-
- struct task_security_struct *tsec;
- struct inode *inode;
- struct inode_security_struct *dsec;
- struct superblock_security_struct *sbsec;
- u32 newsid;
- char *context;
- unsigned int len;
- int rc;
-
- tsec = current->security;
- dsec = dir->i_security;
- sbsec = dir->i_sb->s_security;
-
- inode = dentry->d_inode;
- if (!inode) {
- /* Some file system types (e.g. NFS) may not instantiate
- a dentry for all create operations (e.g. symlink),
- so we have to check to see if the inode is non-NULL. */
- printk(KERN_WARNING "post_create: no inode, dir (dev=%s, "
- "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino);
- return 0;
- }
-
- if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
- newsid = tsec->create_sid;
- } else {
- rc = security_transition_sid(tsec->sid, dsec->sid,
- inode_mode_to_security_class(inode->i_mode),
- &newsid);
- if (rc) {
- printk(KERN_WARNING "post_create: "
- "security_transition_sid failed, rc=%d (dev=%s "
- "ino=%ld)\n",
- -rc, inode->i_sb->s_id, inode->i_ino);
- return rc;
- }
- }
-
- rc = inode_security_set_sid(inode, newsid);
- if (rc) {
- printk(KERN_WARNING "post_create: inode_security_set_sid "
- "failed, rc=%d (dev=%s ino=%ld)\n",
- -rc, inode->i_sb->s_id, inode->i_ino);
- return rc;
- }
-
- if (sbsec->behavior == SECURITY_FS_USE_XATTR &&
- inode->i_op->setxattr) {
- /* Use extended attributes. */
- rc = security_sid_to_context(newsid, &context, &len);
- if (rc) {
- printk(KERN_WARNING "post_create: sid_to_context "
- "failed, rc=%d (dev=%s ino=%ld)\n",
- -rc, inode->i_sb->s_id, inode->i_ino);
- return rc;
- }
- down(&inode->i_sem);
- rc = inode->i_op->setxattr(dentry,
- XATTR_NAME_SELINUX,
- context, len, 0);
- up(&inode->i_sem);
- kfree(context);
- if (rc < 0) {
- printk(KERN_WARNING "post_create: setxattr failed, "
- "rc=%d (dev=%s ino=%ld)\n",
- -rc, inode->i_sb->s_id, inode->i_ino);
- return rc;
- }
- }
-
- return 0;
-}
-
-
/* Hook functions begin here. */
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
@@ -1673,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
struct avc_audit_data ad;
struct file *file, *devnull = NULL;
struct tty_struct *tty = current->signal->tty;
+ struct fdtable *fdt;
long j = -1;
if (tty) {
@@ -1706,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files)
j++;
i = j * __NFDBITS;
- if (i >= files->max_fds || i >= files->max_fdset)
+ fdt = files_fdtable(files);
+ if (i >= fdt->max_fds || i >= fdt->max_fdset)
break;
- set = files->open_fds->fds_bits[j];
+ set = fdt->open_fds->fds_bits[j];
if (!set)
continue;
spin_unlock(&files->file_lock);
@@ -1729,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
continue;
}
if (devnull) {
- atomic_inc(&devnull->f_count);
+ rcuref_inc(&devnull->f_count);
} else {
devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
if (!devnull) {
@@ -2018,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode)
inode_free_security(inode);
}
-static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ char **name, void **value,
+ size_t *len)
{
- return may_create(dir, dentry, SECCLASS_FILE);
+ struct task_security_struct *tsec;
+ struct inode_security_struct *dsec;
+ struct superblock_security_struct *sbsec;
+ struct inode_security_struct *isec;
+ u32 newsid, clen;
+ int rc;
+ char *namep = NULL, *context;
+
+ tsec = current->security;
+ dsec = dir->i_security;
+ sbsec = dir->i_sb->s_security;
+ isec = inode->i_security;
+
+ if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
+ newsid = tsec->create_sid;
+ } else {
+ rc = security_transition_sid(tsec->sid, dsec->sid,
+ inode_mode_to_security_class(inode->i_mode),
+ &newsid);
+ if (rc) {
+ printk(KERN_WARNING "%s: "
+ "security_transition_sid failed, rc=%d (dev=%s "
+ "ino=%ld)\n",
+ __FUNCTION__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ return rc;
+ }
+ }
+
+ inode_security_set_sid(inode, newsid);
+
+ if (name) {
+ namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
+ if (!namep)
+ return -ENOMEM;
+ *name = namep;
+ }
+
+ if (value && len) {
+ rc = security_sid_to_context(newsid, &context, &clen);
+ if (rc) {
+ kfree(namep);
+ return rc;
+ }
+ *value = context;
+ *len = clen;
+ }
+
+ return 0;
}
-static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
{
- post_create(dir, dentry);
+ return may_create(dir, dentry, SECCLASS_FILE);
}
static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
@@ -2038,11 +2011,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru
return may_link(dir, old_dentry, MAY_LINK);
}
-static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry)
-{
- return;
-}
-
static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
{
int rc;
@@ -2058,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const
return may_create(dir, dentry, SECCLASS_LNK_FILE);
}
-static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name)
-{
- post_create(dir, dentry);
-}
-
static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
{
return may_create(dir, dentry, SECCLASS_DIR);
}
-static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask)
-{
- post_create(dir, dentry);
-}
-
static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
return may_link(dir, dentry, MAY_RMDIR);
@@ -2089,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}
-static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
- post_create(dir, dentry);
-}
-
static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry)
{
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}
-static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry,
- struct inode *new_inode, struct dentry *new_dentry)
-{
- return;
-}
-
static int selinux_inode_readlink(struct dentry *dentry)
{
return dentry_has_perm(current, NULL, dentry, FILE__READ);
@@ -4298,20 +4245,15 @@ static struct security_operations selinux_ops = {
.inode_alloc_security = selinux_inode_alloc_security,
.inode_free_security = selinux_inode_free_security,
+ .inode_init_security = selinux_inode_init_security,
.inode_create = selinux_inode_create,
- .inode_post_create = selinux_inode_post_create,
.inode_link = selinux_inode_link,
- .inode_post_link = selinux_inode_post_link,
.inode_unlink = selinux_inode_unlink,
.inode_symlink = selinux_inode_symlink,
- .inode_post_symlink = selinux_inode_post_symlink,
.inode_mkdir = selinux_inode_mkdir,
- .inode_post_mkdir = selinux_inode_post_mkdir,
.inode_rmdir = selinux_inode_rmdir,
.inode_mknod = selinux_inode_mknod,
- .inode_post_mknod = selinux_inode_post_mknod,
.inode_rename = selinux_inode_rename,
- .inode_post_rename = selinux_inode_post_rename,
.inode_readlink = selinux_inode_readlink,
.inode_follow_link = selinux_inode_follow_link,
.inode_permission = selinux_inode_permission,
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 71c0a19c9753..5f016c98056f 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -23,10 +23,11 @@
#define POLICYDB_VERSION_NLCLASS 18
#define POLICYDB_VERSION_VALIDATETRANS 19
#define POLICYDB_VERSION_MLS 19
+#define POLICYDB_VERSION_AVTAB 20
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
extern int selinux_enabled;
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index 18d08acafa78..e203883406dd 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -80,7 +80,8 @@ static void selnl_notify(int msgtype, void *data)
nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
selnl_add_payload(nlh, len, msgtype, data);
nlh->nlmsg_len = skb->tail - tmp;
- netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER);
+ NETLINK_CB(skb).dst_group = SELNLGRP_AVC;
+ netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
out:
return;
@@ -103,7 +104,8 @@ void selnl_notify_policyload(u32 seqno)
static int __init selnl_init(void)
{
- selnl = netlink_kernel_create(NETLINK_SELINUX, NULL);
+ selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL,
+ THIS_MODULE);
if (selnl == NULL)
panic("SELinux: Cannot create netlink socket.");
netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 92b057becb4b..69b9329b2054 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -16,7 +16,7 @@
#include <linux/rtnetlink.h>
#include <linux/if.h>
#include <linux/netfilter_ipv4/ip_queue.h>
-#include <linux/tcp_diag.h>
+#include <linux/inet_diag.h>
#include <linux/xfrm.h>
#include <linux/audit.h>
@@ -76,6 +76,7 @@ static struct nlmsg_perm nlmsg_firewall_perms[] =
static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
{
{ TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
+ { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
};
static struct nlmsg_perm nlmsg_xfrm_perms[] =
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index f238c034c44e..dde094feb20d 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -58,6 +58,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
{
int hvalue;
struct avtab_node *prev, *cur, *newnode;
+ u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
if (!h)
return -EINVAL;
@@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
- (datum->specified & cur->datum.specified))
+ (specified & cur->key.specified))
return -EEXIST;
if (key->source_type < cur->key.source_type)
break;
@@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
{
int hvalue;
struct avtab_node *prev, *cur, *newnode;
+ u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
if (!h)
return NULL;
@@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
- (datum->specified & cur->datum.specified))
+ (specified & cur->key.specified))
break;
if (key->source_type < cur->key.source_type)
break;
@@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
return newnode;
}
-struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
+struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
{
int hvalue;
struct avtab_node *cur;
+ u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
if (!h)
return NULL;
@@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
- (specified & cur->datum.specified))
+ (specified & cur->key.specified))
return &cur->datum;
if (key->source_type < cur->key.source_type)
@@ -159,10 +162,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
* conjunction with avtab_search_next_node()
*/
struct avtab_node*
-avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
+avtab_search_node(struct avtab *h, struct avtab_key *key)
{
int hvalue;
struct avtab_node *cur;
+ u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
if (!h)
return NULL;
@@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
if (key->source_type == cur->key.source_type &&
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
- (specified & cur->datum.specified))
+ (specified & cur->key.specified))
return cur;
if (key->source_type < cur->key.source_type)
@@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified)
if (!node)
return NULL;
+ specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
for (cur = node->next; cur; cur = cur->next) {
if (node->key.source_type == cur->key.source_type &&
node->key.target_type == cur->key.target_type &&
node->key.target_class == cur->key.target_class &&
- (specified & cur->datum.specified))
+ (specified & cur->key.specified))
return cur;
if (node->key.source_type < cur->key.source_type)
@@ -278,76 +283,129 @@ void avtab_hash_eval(struct avtab *h, char *tag)
max_chain_len);
}
-int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
+static uint16_t spec_order[] = {
+ AVTAB_ALLOWED,
+ AVTAB_AUDITDENY,
+ AVTAB_AUDITALLOW,
+ AVTAB_TRANSITION,
+ AVTAB_CHANGE,
+ AVTAB_MEMBER
+};
+
+int avtab_read_item(void *fp, u32 vers, struct avtab *a,
+ int (*insertf)(struct avtab *a, struct avtab_key *k,
+ struct avtab_datum *d, void *p),
+ void *p)
{
- u32 buf[7];
- u32 items, items2;
- int rc;
+ __le16 buf16[4];
+ u16 enabled;
+ __le32 buf32[7];
+ u32 items, items2, val;
+ struct avtab_key key;
+ struct avtab_datum datum;
+ int i, rc;
+
+ memset(&key, 0, sizeof(struct avtab_key));
+ memset(&datum, 0, sizeof(struct avtab_datum));
+
+ if (vers < POLICYDB_VERSION_AVTAB) {
+ rc = next_entry(buf32, fp, sizeof(u32));
+ if (rc < 0) {
+ printk(KERN_ERR "security: avtab: truncated entry\n");
+ return -1;
+ }
+ items2 = le32_to_cpu(buf32[0]);
+ if (items2 > ARRAY_SIZE(buf32)) {
+ printk(KERN_ERR "security: avtab: entry overflow\n");
+ return -1;
- memset(avkey, 0, sizeof(struct avtab_key));
- memset(avdatum, 0, sizeof(struct avtab_datum));
+ }
+ rc = next_entry(buf32, fp, sizeof(u32)*items2);
+ if (rc < 0) {
+ printk(KERN_ERR "security: avtab: truncated entry\n");
+ return -1;
+ }
+ items = 0;
- rc = next_entry(buf, fp, sizeof(u32));
- if (rc < 0) {
- printk(KERN_ERR "security: avtab: truncated entry\n");
- goto bad;
- }
- items2 = le32_to_cpu(buf[0]);
- if (items2 > ARRAY_SIZE(buf)) {
- printk(KERN_ERR "security: avtab: entry overflow\n");
- goto bad;
+ val = le32_to_cpu(buf32[items++]);
+ key.source_type = (u16)val;
+ if (key.source_type != val) {
+ printk("security: avtab: truncated source type\n");
+ return -1;
+ }
+ val = le32_to_cpu(buf32[items++]);
+ key.target_type = (u16)val;
+ if (key.target_type != val) {
+ printk("security: avtab: truncated target type\n");
+ return -1;
+ }
+ val = le32_to_cpu(buf32[items++]);
+ key.target_class = (u16)val;
+ if (key.target_class != val) {
+ printk("security: avtab: truncated target class\n");
+ return -1;
+ }
+
+ val = le32_to_cpu(buf32[items++]);
+ enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
+
+ if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
+ printk("security: avtab: null entry\n");
+ return -1;
+ }
+ if ((val & AVTAB_AV) &&
+ (val & AVTAB_TYPE)) {
+ printk("security: avtab: entry has both access vectors and types\n");
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) {
+ if (val & spec_order[i]) {
+ key.specified = spec_order[i] | enabled;
+ datum.data = le32_to_cpu(buf32[items++]);
+ rc = insertf(a, &key, &datum, p);
+ if (rc) return rc;
+ }
+ }
+
+ if (items != items2) {
+ printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
+ return -1;
+ }
+ return 0;
}
- rc = next_entry(buf, fp, sizeof(u32)*items2);
+
+ rc = next_entry(buf16, fp, sizeof(u16)*4);
if (rc < 0) {
- printk(KERN_ERR "security: avtab: truncated entry\n");
- goto bad;
+ printk("security: avtab: truncated entry\n");
+ return -1;
}
+
items = 0;
- avkey->source_type = le32_to_cpu(buf[items++]);
- avkey->target_type = le32_to_cpu(buf[items++]);
- avkey->target_class = le32_to_cpu(buf[items++]);
- avdatum->specified = le32_to_cpu(buf[items++]);
- if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) {
- printk(KERN_ERR "security: avtab: null entry\n");
- goto bad;
- }
- if ((avdatum->specified & AVTAB_AV) &&
- (avdatum->specified & AVTAB_TYPE)) {
- printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
- goto bad;
- }
- if (avdatum->specified & AVTAB_AV) {
- if (avdatum->specified & AVTAB_ALLOWED)
- avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
- if (avdatum->specified & AVTAB_AUDITDENY)
- avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
- if (avdatum->specified & AVTAB_AUDITALLOW)
- avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
- } else {
- if (avdatum->specified & AVTAB_TRANSITION)
- avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
- if (avdatum->specified & AVTAB_CHANGE)
- avtab_change(avdatum) = le32_to_cpu(buf[items++]);
- if (avdatum->specified & AVTAB_MEMBER)
- avtab_member(avdatum) = le32_to_cpu(buf[items++]);
- }
- if (items != items2) {
- printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
- items2, items);
- goto bad;
+ key.source_type = le16_to_cpu(buf16[items++]);
+ key.target_type = le16_to_cpu(buf16[items++]);
+ key.target_class = le16_to_cpu(buf16[items++]);
+ key.specified = le16_to_cpu(buf16[items++]);
+
+ rc = next_entry(buf32, fp, sizeof(u32));
+ if (rc < 0) {
+ printk("security: avtab: truncated entry\n");
+ return -1;
}
+ datum.data = le32_to_cpu(*buf32);
+ return insertf(a, &key, &datum, p);
+}
- return 0;
-bad:
- return -1;
+static int avtab_insertf(struct avtab *a, struct avtab_key *k,
+ struct avtab_datum *d, void *p)
+{
+ return avtab_insert(a, k, d);
}
-int avtab_read(struct avtab *a, void *fp, u32 config)
+int avtab_read(struct avtab *a, void *fp, u32 vers)
{
int rc;
- struct avtab_key avkey;
- struct avtab_datum avdatum;
- u32 buf[1];
+ __le32 buf[1];
u32 nel, i;
@@ -363,16 +421,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config)
goto bad;
}
for (i = 0; i < nel; i++) {
- if (avtab_read_item(fp, &avdatum, &avkey)) {
- rc = -EINVAL;
- goto bad;
- }
- rc = avtab_insert(a, &avkey, &avdatum);
+ rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
if (rc) {
if (rc == -ENOMEM)
printk(KERN_ERR "security: avtab: out of memory\n");
- if (rc == -EEXIST)
+ else if (rc == -EEXIST)
printk(KERN_ERR "security: avtab: duplicate entry\n");
+ else
+ rc = -EINVAL;
goto bad;
}
}
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 519d4f6dc655..0a90d939af93 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -21,12 +21,9 @@
#define _SS_AVTAB_H_
struct avtab_key {
- u32 source_type; /* source type */
- u32 target_type; /* target type */
- u32 target_class; /* target object class */
-};
-
-struct avtab_datum {
+ u16 source_type; /* source type */
+ u16 target_type; /* target type */
+ u16 target_class; /* target object class */
#define AVTAB_ALLOWED 1
#define AVTAB_AUDITALLOW 2
#define AVTAB_AUDITDENY 4
@@ -35,15 +32,13 @@ struct avtab_datum {
#define AVTAB_MEMBER 32
#define AVTAB_CHANGE 64
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
-#define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */
- u32 specified; /* what fields are specified */
- u32 data[3]; /* access vectors or types */
-#define avtab_allowed(x) (x)->data[0]
-#define avtab_auditdeny(x) (x)->data[1]
-#define avtab_auditallow(x) (x)->data[2]
-#define avtab_transition(x) (x)->data[0]
-#define avtab_change(x) (x)->data[1]
-#define avtab_member(x) (x)->data[2]
+#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
+#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
+ u16 specified; /* what field is specified */
+};
+
+struct avtab_datum {
+ u32 data; /* access vector or type value */
};
struct avtab_node {
@@ -58,17 +53,21 @@ struct avtab {
};
int avtab_init(struct avtab *);
-struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified);
+struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
void avtab_destroy(struct avtab *h);
void avtab_hash_eval(struct avtab *h, char *tag);
-int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey);
-int avtab_read(struct avtab *a, void *fp, u32 config);
+int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
+ int (*insert)(struct avtab *a, struct avtab_key *k,
+ struct avtab_datum *d, void *p),
+ void *p);
+
+int avtab_read(struct avtab *a, void *fp, u32 vers);
struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
struct avtab_datum *datum);
-struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified);
+struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key);
struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index e2057f5a411a..daf288007460 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -100,18 +100,18 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
/* turn the rules on or off */
for (cur = node->true_list; cur != NULL; cur = cur->next) {
if (new_state <= 0) {
- cur->node->datum.specified &= ~AVTAB_ENABLED;
+ cur->node->key.specified &= ~AVTAB_ENABLED;
} else {
- cur->node->datum.specified |= AVTAB_ENABLED;
+ cur->node->key.specified |= AVTAB_ENABLED;
}
}
for (cur = node->false_list; cur != NULL; cur = cur->next) {
/* -1 or 1 */
if (new_state) {
- cur->node->datum.specified &= ~AVTAB_ENABLED;
+ cur->node->key.specified &= ~AVTAB_ENABLED;
} else {
- cur->node->datum.specified |= AVTAB_ENABLED;
+ cur->node->key.specified |= AVTAB_ENABLED;
}
}
}
@@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
struct cond_bool_datum *booldatum;
- u32 buf[3], len;
+ __le32 buf[3];
+ u32 len;
int rc;
booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
@@ -252,104 +253,127 @@ err:
return -1;
}
-static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list,
- struct cond_av_list *other)
+struct cond_insertf_data
{
- struct cond_av_list *list, *last = NULL, *cur;
- struct avtab_key key;
- struct avtab_datum datum;
+ struct policydb *p;
+ struct cond_av_list *other;
+ struct cond_av_list *head;
+ struct cond_av_list *tail;
+};
+
+static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
+{
+ struct cond_insertf_data *data = ptr;
+ struct policydb *p = data->p;
+ struct cond_av_list *other = data->other, *list, *cur;
struct avtab_node *node_ptr;
- int rc;
- u32 buf[1], i, len;
u8 found;
- *ret_list = NULL;
-
- len = 0;
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- return -1;
-
- len = le32_to_cpu(buf[0]);
- if (len == 0) {
- return 0;
- }
- for (i = 0; i < len; i++) {
- if (avtab_read_item(fp, &datum, &key))
+ /*
+ * For type rules we have to make certain there aren't any
+ * conflicting rules by searching the te_avtab and the
+ * cond_te_avtab.
+ */
+ if (k->specified & AVTAB_TYPE) {
+ if (avtab_search(&p->te_avtab, k)) {
+ printk("security: type rule already exists outside of a conditional.");
goto err;
-
+ }
/*
- * For type rules we have to make certain there aren't any
- * conflicting rules by searching the te_avtab and the
- * cond_te_avtab.
+ * If we are reading the false list other will be a pointer to
+ * the true list. We can have duplicate entries if there is only
+ * 1 other entry and it is in our true list.
+ *
+ * If we are reading the true list (other == NULL) there shouldn't
+ * be any other entries.
*/
- if (datum.specified & AVTAB_TYPE) {
- if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
- printk("security: type rule already exists outside of a conditional.");
- goto err;
- }
- /*
- * If we are reading the false list other will be a pointer to
- * the true list. We can have duplicate entries if there is only
- * 1 other entry and it is in our true list.
- *
- * If we are reading the true list (other == NULL) there shouldn't
- * be any other entries.
- */
- if (other) {
- node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
- if (node_ptr) {
- if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
- printk("security: too many conflicting type rules.");
- goto err;
- }
- found = 0;
- for (cur = other; cur != NULL; cur = cur->next) {
- if (cur->node == node_ptr) {
- found = 1;
- break;
- }
- }
- if (!found) {
- printk("security: conflicting type rules.");
- goto err;
+ if (other) {
+ node_ptr = avtab_search_node(&p->te_cond_avtab, k);
+ if (node_ptr) {
+ if (avtab_search_node_next(node_ptr, k->specified)) {
+ printk("security: too many conflicting type rules.");
+ goto err;
+ }
+ found = 0;
+ for (cur = other; cur != NULL; cur = cur->next) {
+ if (cur->node == node_ptr) {
+ found = 1;
+ break;
}
}
- } else {
- if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
- printk("security: conflicting type rules when adding type rule for true.");
+ if (!found) {
+ printk("security: conflicting type rules.\n");
goto err;
}
}
+ } else {
+ if (avtab_search(&p->te_cond_avtab, k)) {
+ printk("security: conflicting type rules when adding type rule for true.\n");
+ goto err;
+ }
}
- node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
- if (!node_ptr) {
- printk("security: could not insert rule.");
- goto err;
- }
-
- list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
- if (!list)
- goto err;
- memset(list, 0, sizeof(struct cond_av_list));
-
- list->node = node_ptr;
- if (i == 0)
- *ret_list = list;
- else
- last->next = list;
- last = list;
+ }
+ node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
+ if (!node_ptr) {
+ printk("security: could not insert rule.");
+ goto err;
}
+ list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+ if (!list)
+ goto err;
+ memset(list, 0, sizeof(*list));
+
+ list->node = node_ptr;
+ if (!data->head)
+ data->head = list;
+ else
+ data->tail->next = list;
+ data->tail = list;
return 0;
+
err:
- cond_av_list_destroy(*ret_list);
- *ret_list = NULL;
+ cond_av_list_destroy(data->head);
+ data->head = NULL;
return -1;
}
+static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
+{
+ int i, rc;
+ __le32 buf[1];
+ u32 len;
+ struct cond_insertf_data data;
+
+ *ret_list = NULL;
+
+ len = 0;
+ rc = next_entry(buf, fp, sizeof(u32));
+ if (rc < 0)
+ return -1;
+
+ len = le32_to_cpu(buf[0]);
+ if (len == 0) {
+ return 0;
+ }
+
+ data.p = p;
+ data.other = other;
+ data.head = NULL;
+ data.tail = NULL;
+ for (i = 0; i < len; i++) {
+ rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data);
+ if (rc)
+ return rc;
+
+ }
+
+ *ret_list = data.head;
+ return 0;
+}
+
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
{
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
@@ -366,7 +390,8 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
{
- u32 buf[2], len, i;
+ __le32 buf[2];
+ u32 len, i;
int rc;
struct cond_expr *expr = NULL, *last = NULL;
@@ -424,7 +449,8 @@ err:
int cond_read_list(struct policydb *p, void *fp)
{
struct cond_node *node, *last = NULL;
- u32 buf[1], i, len;
+ __le32 buf[1];
+ u32 i, len;
int rc;
rc = next_entry(buf, fp, sizeof buf);
@@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp)
return 0;
err:
cond_list_destroy(p->cond_list);
+ p->cond_list = NULL;
return -1;
}
@@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
if(!ctab || !key || !avd)
return;
- for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
- node = avtab_search_node_next(node, AVTAB_AV)) {
- if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
- avd->allowed |= avtab_allowed(&node->datum);
- if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
+ for(node = avtab_search_node(ctab, key); node != NULL;
+ node = avtab_search_node_next(node, key->specified)) {
+ if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
+ (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
+ avd->allowed |= node->datum.data;
+ if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
+ (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
/* Since a '0' in an auditdeny mask represents a
* permission we do NOT want to audit (dontaudit), we use
* the '&' operand to ensure that all '0's in the mask
* are retained (much unlike the allow and auditallow cases).
*/
- avd->auditdeny &= avtab_auditdeny(&node->datum);
- if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
- (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
- avd->auditallow |= avtab_auditallow(&node->datum);
+ avd->auditdeny &= node->datum.data;
+ if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
+ (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
+ avd->auditallow |= node->datum.data;
}
return;
}
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d8ce9cc0b9f1..d515154128cc 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -196,8 +196,9 @@ int ebitmap_read(struct ebitmap *e, void *fp)
{
int rc;
struct ebitmap_node *n, *l;
- u32 buf[3], mapsize, count, i;
- u64 map;
+ __le32 buf[3];
+ u32 mapsize, count, i;
+ __le64 map;
ebitmap_init(e);
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 471370233fd9..8bf41055a6cb 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -32,11 +32,41 @@ struct ebitmap {
#define ebitmap_length(e) ((e)->highbit)
#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
+static inline unsigned int ebitmap_start(struct ebitmap *e,
+ struct ebitmap_node **n)
+{
+ *n = e->node;
+ return ebitmap_startbit(e);
+}
+
static inline void ebitmap_init(struct ebitmap *e)
{
memset(e, 0, sizeof(*e));
}
+static inline unsigned int ebitmap_next(struct ebitmap_node **n,
+ unsigned int bit)
+{
+ if ((bit == ((*n)->startbit + MAPSIZE - 1)) &&
+ (*n)->next) {
+ *n = (*n)->next;
+ return (*n)->startbit;
+ }
+
+ return (bit+1);
+}
+
+static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
+ unsigned int bit)
+{
+ if (n->map & (MAPBIT << (bit - n->startbit)))
+ return 1;
+ return 0;
+}
+
+#define ebitmap_for_each_bit(e, n, bit) \
+ for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \
+
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index d4c32c39ccc9..aaefac2921f1 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -27,6 +27,7 @@
int mls_compute_context_len(struct context * context)
{
int i, l, len, range;
+ struct ebitmap_node *node;
if (!selinux_mls_enabled)
return 0;
@@ -36,24 +37,24 @@ int mls_compute_context_len(struct context * context)
range = 0;
len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
- if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+ ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
if (range) {
range++;
continue;
}
- len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+ len += strlen(policydb.p_cat_val_to_name[i]) + 1;
range++;
} else {
if (range > 1)
- len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+ len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
range = 0;
}
}
/* Handle case where last category is the end of range */
if (range > 1)
- len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+ len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
if (l == 0) {
if (mls_level_eq(&context->range.level[0],
@@ -77,6 +78,7 @@ void mls_sid_to_context(struct context *context,
{
char *scontextp;
int i, l, range, wrote_sep;
+ struct ebitmap_node *node;
if (!selinux_mls_enabled)
return;
@@ -94,8 +96,8 @@ void mls_sid_to_context(struct context *context,
scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
/* categories */
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
- if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+ ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
if (range) {
range++;
continue;
@@ -106,8 +108,8 @@ void mls_sid_to_context(struct context *context,
wrote_sep = 1;
} else
*scontextp++ = ',';
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+ strcpy(scontextp, policydb.p_cat_val_to_name[i]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i]);
range++;
} else {
if (range > 1) {
@@ -116,8 +118,8 @@ void mls_sid_to_context(struct context *context,
else
*scontextp++ = ',';
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
}
range = 0;
}
@@ -130,8 +132,8 @@ void mls_sid_to_context(struct context *context,
else
*scontextp++ = ',';
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
}
if (l == 0) {
@@ -157,6 +159,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
{
struct level_datum *levdatum;
struct user_datum *usrdatum;
+ struct ebitmap_node *node;
int i, l;
if (!selinux_mls_enabled)
@@ -179,11 +182,11 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
if (!levdatum)
return 0;
- for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
- if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
+ ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
if (i > p->p_cats.nprim)
return 0;
- if (!ebitmap_get_bit(&levdatum->level->cat, i - 1))
+ if (!ebitmap_get_bit(&levdatum->level->cat, i))
/*
* Category may not be associated with
* sensitivity in low level.
@@ -468,6 +471,7 @@ int mls_convert_context(struct policydb *oldp,
struct level_datum *levdatum;
struct cat_datum *catdatum;
struct ebitmap bitmap;
+ struct ebitmap_node *node;
int l, i;
if (!selinux_mls_enabled)
@@ -482,12 +486,12 @@ int mls_convert_context(struct policydb *oldp,
c->range.level[l].sens = levdatum->level->sens;
ebitmap_init(&bitmap);
- for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
- if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
+ ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
int rc;
catdatum = hashtab_search(newp->p_cats.table,
- oldp->p_cat_val_to_name[i - 1]);
+ oldp->p_cat_val_to_name[i]);
if (!catdatum)
return -EINVAL;
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 785c33cf4864..0a758323a9cf 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -91,6 +91,11 @@ static struct policydb_compat_info policydb_compat[] = {
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
+ {
+ .version = POLICYDB_VERSION_AVTAB,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
+ },
};
static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -584,6 +589,9 @@ void policydb_destroy(struct policydb *p)
struct ocontext *c, *ctmp;
struct genfs *g, *gtmp;
int i;
+ struct role_allow *ra, *lra = NULL;
+ struct role_trans *tr, *ltr = NULL;
+ struct range_trans *rt, *lrt = NULL;
for (i = 0; i < SYM_NUM; i++) {
hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
@@ -624,6 +632,28 @@ void policydb_destroy(struct policydb *p)
cond_policydb_destroy(p);
+ for (tr = p->role_tr; tr; tr = tr->next) {
+ if (ltr) kfree(ltr);
+ ltr = tr;
+ }
+ if (ltr) kfree(ltr);
+
+ for (ra = p->role_allow; ra; ra = ra -> next) {
+ if (lra) kfree(lra);
+ lra = ra;
+ }
+ if (lra) kfree(lra);
+
+ for (rt = p->range_tr; rt; rt = rt -> next) {
+ if (lrt) kfree(lrt);
+ lrt = rt;
+ }
+ if (lrt) kfree(lrt);
+
+ for (i = 0; i < p->p_types.nprim; i++)
+ ebitmap_destroy(&p->type_attr_map[i]);
+ kfree(p->type_attr_map);
+
return;
}
@@ -714,7 +744,8 @@ int policydb_context_isvalid(struct policydb *p, struct context *c)
*/
static int mls_read_range_helper(struct mls_range *r, void *fp)
{
- u32 buf[2], items;
+ __le32 buf[2];
+ u32 items;
int rc;
rc = next_entry(buf, fp, sizeof(u32));
@@ -775,7 +806,7 @@ static int context_read_and_validate(struct context *c,
struct policydb *p,
void *fp)
{
- u32 buf[3];
+ __le32 buf[3];
int rc;
rc = next_entry(buf, fp, sizeof buf);
@@ -815,7 +846,8 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct perm_datum *perdatum;
int rc;
- u32 buf[2], len;
+ __le32 buf[2];
+ u32 len;
perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
if (!perdatum) {
@@ -855,7 +887,8 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
struct common_datum *comdatum;
- u32 buf[4], len, nel;
+ __le32 buf[4];
+ u32 len, nel;
int i, rc;
comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
@@ -909,7 +942,8 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
{
struct constraint_node *c, *lc;
struct constraint_expr *e, *le;
- u32 buf[3], nexpr;
+ __le32 buf[3];
+ u32 nexpr;
int rc, i, j, depth;
lc = NULL;
@@ -993,7 +1027,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
struct class_datum *cladatum;
- u32 buf[6], len, len2, ncons, nel;
+ __le32 buf[6];
+ u32 len, len2, ncons, nel;
int i, rc;
cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
@@ -1087,7 +1122,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct role_datum *role;
int rc;
- u32 buf[2], len;
+ __le32 buf[2];
+ u32 len;
role = kmalloc(sizeof(*role), GFP_KERNEL);
if (!role) {
@@ -1147,7 +1183,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct type_datum *typdatum;
int rc;
- u32 buf[3], len;
+ __le32 buf[3];
+ u32 len;
typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
if (!typdatum) {
@@ -1191,7 +1228,7 @@ bad:
*/
static int mls_read_level(struct mls_level *lp, void *fp)
{
- u32 buf[1];
+ __le32 buf[1];
int rc;
memset(lp, 0, sizeof(*lp));
@@ -1219,7 +1256,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct user_datum *usrdatum;
int rc;
- u32 buf[2], len;
+ __le32 buf[2];
+ u32 len;
usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
if (!usrdatum) {
@@ -1273,7 +1311,8 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct level_datum *levdatum;
int rc;
- u32 buf[2], len;
+ __le32 buf[2];
+ u32 len;
levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
if (!levdatum) {
@@ -1324,7 +1363,8 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL;
struct cat_datum *catdatum;
int rc;
- u32 buf[3], len;
+ __le32 buf[3];
+ u32 len;
catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
if (!catdatum) {
@@ -1387,7 +1427,8 @@ int policydb_read(struct policydb *p, void *fp)
struct ocontext *l, *c, *newc;
struct genfs *genfs_p, *genfs, *newgenfs;
int i, j, rc;
- u32 buf[8], len, len2, config, nprim, nel, nel2;
+ __le32 buf[8];
+ u32 len, len2, config, nprim, nel, nel2;
char *policydb_str;
struct policydb_compat_info *info;
struct range_trans *rt, *lrt;
@@ -1403,17 +1444,14 @@ int policydb_read(struct policydb *p, void *fp)
if (rc < 0)
goto bad;
- for (i = 0; i < 2; i++)
- buf[i] = le32_to_cpu(buf[i]);
-
- if (buf[0] != POLICYDB_MAGIC) {
+ if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
printk(KERN_ERR "security: policydb magic number 0x%x does "
"not match expected magic number 0x%x\n",
- buf[0], POLICYDB_MAGIC);
+ le32_to_cpu(buf[0]), POLICYDB_MAGIC);
goto bad;
}
- len = buf[1];
+ len = le32_to_cpu(buf[1]);
if (len != strlen(POLICYDB_STRING)) {
printk(KERN_ERR "security: policydb string length %d does not "
"match expected length %Zu\n",
@@ -1448,19 +1486,17 @@ int policydb_read(struct policydb *p, void *fp)
rc = next_entry(buf, fp, sizeof(u32)*4);
if (rc < 0)
goto bad;
- for (i = 0; i < 4; i++)
- buf[i] = le32_to_cpu(buf[i]);
- p->policyvers = buf[0];
+ p->policyvers = le32_to_cpu(buf[0]);
if (p->policyvers < POLICYDB_VERSION_MIN ||
p->policyvers > POLICYDB_VERSION_MAX) {
printk(KERN_ERR "security: policydb version %d does not match "
"my version range %d-%d\n",
- buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+ le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
goto bad;
}
- if ((buf[1] & POLICYDB_CONFIG_MLS)) {
+ if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
if (ss_initialized && !selinux_mls_enabled) {
printk(KERN_ERR "Cannot switch between non-MLS and MLS "
"policies\n");
@@ -1489,9 +1525,11 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
}
- if (buf[2] != info->sym_num || buf[3] != info->ocon_num) {
+ if (le32_to_cpu(buf[2]) != info->sym_num ||
+ le32_to_cpu(buf[3]) != info->ocon_num) {
printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
- "not match mine (%d,%d)\n", buf[2], buf[3],
+ "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
+ le32_to_cpu(buf[3]),
info->sym_num, info->ocon_num);
goto bad;
}
@@ -1511,7 +1549,7 @@ int policydb_read(struct policydb *p, void *fp)
p->symtab[i].nprim = nprim;
}
- rc = avtab_read(&p->te_avtab, fp, config);
+ rc = avtab_read(&p->te_avtab, fp, p->policyvers);
if (rc)
goto bad;
@@ -1825,6 +1863,21 @@ int policydb_read(struct policydb *p, void *fp)
}
}
+ p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
+ if (!p->type_attr_map)
+ goto bad;
+
+ for (i = 0; i < p->p_types.nprim; i++) {
+ ebitmap_init(&p->type_attr_map[i]);
+ if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
+ if (ebitmap_read(&p->type_attr_map[i], fp))
+ goto bad;
+ }
+ /* add the type itself as the degenerate case */
+ if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
+ goto bad;
+ }
+
rc = 0;
out:
return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 2470e2a1a1c3..b1340711f721 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -237,6 +237,9 @@ struct policydb {
/* range transitions */
struct range_trans *range_tr;
+ /* type -> attribute reverse mapping */
+ struct ebitmap *type_attr_map;
+
unsigned int policyvers;
};
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 45d317044cb2..aecdded55e74 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext,
struct constraint_node *constraint;
struct role_allow *ra;
struct avtab_key avkey;
- struct avtab_datum *avdatum;
+ struct avtab_node *node;
struct class_datum *tclass_datum;
+ struct ebitmap *sattr, *tattr;
+ struct ebitmap_node *snode, *tnode;
+ unsigned int i, j;
/*
* Remap extended Netlink classes for old policy versions.
@@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext,
* If a specific type enforcement rule was defined for
* this permission check, then use it.
*/
- avkey.source_type = scontext->type;
- avkey.target_type = tcontext->type;
avkey.target_class = tclass;
- avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
- if (avdatum) {
- if (avdatum->specified & AVTAB_ALLOWED)
- avd->allowed = avtab_allowed(avdatum);
- if (avdatum->specified & AVTAB_AUDITDENY)
- avd->auditdeny = avtab_auditdeny(avdatum);
- if (avdatum->specified & AVTAB_AUDITALLOW)
- avd->auditallow = avtab_auditallow(avdatum);
- }
+ avkey.specified = AVTAB_AV;
+ sattr = &policydb.type_attr_map[scontext->type - 1];
+ tattr = &policydb.type_attr_map[tcontext->type - 1];
+ ebitmap_for_each_bit(sattr, snode, i) {
+ if (!ebitmap_node_get_bit(snode, i))
+ continue;
+ ebitmap_for_each_bit(tattr, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
+ continue;
+ avkey.source_type = i + 1;
+ avkey.target_type = j + 1;
+ for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+ node != NULL;
+ node = avtab_search_node_next(node, avkey.specified)) {
+ if (node->key.specified == AVTAB_ALLOWED)
+ avd->allowed |= node->datum.data;
+ else if (node->key.specified == AVTAB_AUDITALLOW)
+ avd->auditallow |= node->datum.data;
+ else if (node->key.specified == AVTAB_AUDITDENY)
+ avd->auditdeny &= node->datum.data;
+ }
- /* Check conditional av table for additional permissions */
- cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
+ /* Check conditional av table for additional permissions */
+ cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
+
+ }
+ }
/*
* Remove any permissions prohibited by a constraint (this includes
@@ -797,7 +813,6 @@ static int security_compute_sid(u32 ssid,
struct avtab_key avkey;
struct avtab_datum *avdatum;
struct avtab_node *node;
- unsigned int type_change = 0;
int rc = 0;
if (!ss_initialized) {
@@ -862,33 +877,23 @@ static int security_compute_sid(u32 ssid,
avkey.source_type = scontext->type;
avkey.target_type = tcontext->type;
avkey.target_class = tclass;
- avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
+ avkey.specified = specified;
+ avdatum = avtab_search(&policydb.te_avtab, &avkey);
/* If no permanent rule, also check for enabled conditional rules */
if(!avdatum) {
- node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified);
+ node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
for (; node != NULL; node = avtab_search_node_next(node, specified)) {
- if (node->datum.specified & AVTAB_ENABLED) {
+ if (node->key.specified & AVTAB_ENABLED) {
avdatum = &node->datum;
break;
}
}
}
- type_change = (avdatum && (avdatum->specified & specified));
- if (type_change) {
+ if (avdatum) {
/* Use the type from the type transition/member/change rule. */
- switch (specified) {
- case AVTAB_TRANSITION:
- newcontext.type = avtab_transition(avdatum);
- break;
- case AVTAB_MEMBER:
- newcontext.type = avtab_member(avdatum);
- break;
- case AVTAB_CHANGE:
- newcontext.type = avtab_change(avdatum);
- break;
- }
+ newcontext.type = avdatum->data;
}
/* Check for class-specific changes. */
@@ -1502,6 +1507,7 @@ int security_get_user_sids(u32 fromsid,
struct user_datum *user;
struct role_datum *role;
struct av_decision avd;
+ struct ebitmap_node *rnode, *tnode;
int rc = 0, i, j;
if (!ss_initialized) {
@@ -1532,13 +1538,13 @@ int security_get_user_sids(u32 fromsid,
}
memset(mysids, 0, maxnel*sizeof(*mysids));
- for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) {
- if (!ebitmap_get_bit(&user->roles, i))
+ ebitmap_for_each_bit(&user->roles, rnode, i) {
+ if (!ebitmap_node_get_bit(rnode, i))
continue;
role = policydb.role_val_to_struct[i];
usercon.role = i+1;
- for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) {
- if (!ebitmap_get_bit(&role->types, j))
+ ebitmap_for_each_bit(&role->types, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
continue;
usercon.type = j+1;
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 2e4a5e0d16db..0864a7ce414d 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -7,6 +7,7 @@ config SND_SA11XX_UDA1341
tristate "SA11xx UDA1341TS driver (iPaq H3600)"
depends on ARCH_SA1100 && SND && L3
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here if you have a Compaq iPaq H3x00 handheld computer
and want to use its Philips UDA 1341 audio chip.
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index 103f136926d9..4ef6dd00c6ee 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -2,12 +2,14 @@
# Makefile for ALSA
#
-snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
-snd-aaci-objs := aaci.o devdma.o
-snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
-snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
-
obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o
+snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
+
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
-obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
-obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
+snd-aaci-objs := aaci.o devdma.o
+
+obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
+snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
+
+obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
+snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 08cc3ddca96f..34195b748608 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -821,7 +821,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
{
- void *base = aaci->base + AACI_CSCH1;
+ void __iomem *base = aaci->base + AACI_CSCH1;
int i;
writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
@@ -877,7 +877,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
aaci->playback.fifo = aaci->base + AACI_DR1;
for (i = 0; i < 4; i++) {
- void *base = aaci->base + i * 0x14;
+ void __iomem *base = aaci->base + i * 0x14;
writel(0, base + AACI_IE);
writel(0, base + AACI_TXCR);
@@ -900,6 +900,8 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
if (ret)
goto out;
+ snd_card_set_dev(aaci->card, &dev->dev);
+
ret = snd_card_register(aaci->card);
if (ret == 0) {
dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index d752e6426894..b2f969bc7845 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -200,8 +200,8 @@
struct aaci_runtime {
- void *base;
- void *fifo;
+ void __iomem *base;
+ void __iomem *fifo;
struct ac97_pcm *pcm;
int pcm_open;
@@ -223,7 +223,7 @@ struct aaci_runtime {
struct aaci {
struct amba_device *dev;
snd_card_t *card;
- void *base;
+ void __iomem *base;
unsigned int fifosize;
/* AC'97 */
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 46052304e230..29450befb5da 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -132,9 +132,9 @@ static void pxa2xx_ac97_reset(ac97_t *ac97)
udelay(10);
GCR |= GCR_WARM_RST;
pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
- udelay(50);
+ udelay(500);
#else
- GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;;
+ GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
#endif
@@ -261,7 +261,7 @@ static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state)
+static int pxa2xx_ac97_do_resume(snd_card_t *card)
{
if (card->power_state != SNDRV_CTL_POWER_D0) {
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
@@ -275,13 +275,13 @@ static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state)
return 0;
}
-static int pxa2xx_ac97_suspend(struct device *_dev, u32 state, u32 level)
+static int pxa2xx_ac97_suspend(struct device *_dev, pm_message_t state, u32 level)
{
snd_card_t *card = dev_get_drvdata(_dev);
int ret = 0;
if (card && level == SUSPEND_DISABLE)
- ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
+ ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND);
return ret;
}
@@ -292,7 +292,7 @@ static int pxa2xx_ac97_resume(struct device *_dev, u32 level)
int ret = 0;
if (card && level == RESUME_ENABLE)
- ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
+ ret = pxa2xx_ac97_do_resume(card);
return ret;
}
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 174bc032d1ad..6ee912259cc5 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -21,7 +21,7 @@
* merged HAL layer (patches from Brian)
*/
-/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.23 2005/09/09 13:22:34 tiwai Exp $ */
/***************************************************************************************************
*
@@ -918,7 +918,7 @@ static int __init sa11xx_uda1341_init(void)
if (card == NULL)
return -ENOMEM;
- sa11xx_uda1341 = kcalloc(1, sizeof(*sa11xx_uda1341), GFP_KERNEL);
+ sa11xx_uda1341 = kzalloc(sizeof(*sa11xx_uda1341), GFP_KERNEL);
if (sa11xx_uda1341 == NULL)
return -ENOMEM;
spin_lock_init(&chip->s[0].dma_lock);
@@ -946,6 +946,9 @@ static int __init sa11xx_uda1341_init(void)
strcpy(card->shortname, "H3600 UDA1341TS");
sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS");
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto nodev;
+
if ((err = snd_card_register(card)) == 0) {
printk( KERN_INFO "iPAQ audio support initialized\n" );
return 0;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index d1e800b9866d..48cf45cfd0b7 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -99,6 +99,18 @@ config SND_RTCTIMER
To compile this driver as a module, choose M here: the module
will be called snd-rtctimer.
+config SND_SEQ_RTCTIMER_DEFAULT
+ bool "Use RTC as default sequencer timer"
+ depends on SND_RTCTIMER && SND_SEQUENCER
+ default y
+ help
+ Say Y here to use the RTC timer as the default sequencer
+ timer. This is strongly recommended because it ensures
+ precise MIDI timing even when the system timer runs at less
+ than 1000 Hz.
+
+ If in doubt, say Y.
+
config SND_VERBOSE_PRINTK
bool "Verbose printk"
depends on SND
@@ -128,6 +140,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when
detecting devices.
-config SND_GENERIC_PM
+config SND_GENERIC_DRIVER
bool
depends on SND
diff --git a/sound/core/control.c b/sound/core/control.c
index 227f3cf02771..736edf358e05 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -69,7 +69,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
err = -EFAULT;
goto __error2;
}
- ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
+ ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
if (ctl == NULL) {
err = -ENOMEM;
goto __error;
@@ -162,7 +162,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
goto _found;
}
}
- ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (ev) {
ev->id = *id;
ev->mask = mask;
@@ -195,7 +195,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
snd_runtime_check(control != NULL, return NULL);
snd_runtime_check(control->count > 0, return NULL);
- kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
+ kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
if (kctl == NULL)
return NULL;
*kctl = *control;
@@ -521,7 +521,7 @@ static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
{
snd_ctl_card_info_t *info;
- info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
down_read(&snd_ioctl_rwsem);
@@ -929,7 +929,7 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int
return -EINVAL;
}
private_size *= info->count;
- ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL);
+ ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
if (ue == NULL)
return -ENOMEM;
ue->info = *info;
@@ -1185,7 +1185,7 @@ static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *
{
snd_kctl_ioctl_t *pn;
- pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+ pn = kzalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 7fdabea4bfc8..207c7de5129c 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -92,7 +92,7 @@ static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_i
struct sndrv_ctl_elem_info *data;
int err;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
@@ -271,7 +271,7 @@ static int snd_ctl_elem_read_user_compat(snd_card_t *card,
struct sndrv_ctl_elem_value *data;
int err, type, count;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -291,7 +291,7 @@ static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
struct sndrv_ctl_elem_value *data;
int err, type, count;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -313,7 +313,7 @@ static int snd_ctl_elem_add_compat(snd_ctl_file_t *file,
struct sndrv_ctl_elem_info *data;
int err;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
diff --git a/sound/core/device.c b/sound/core/device.c
index ca00ad7740c9..1f509f56e60c 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -49,7 +49,7 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
snd_assert(ops != NULL, return -ENXIO);
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
dev->card = card;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 997dd41c584e..9383f1294fb5 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -359,7 +359,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
snd_assert(rhwdep != NULL, return -EINVAL);
*rhwdep = NULL;
snd_assert(card != NULL, return -ENXIO);
- hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
+ hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
if (hwdep == NULL)
return -ENOMEM;
hwdep->card = card;
diff --git a/sound/core/info.c b/sound/core/info.c
index 7f8bdf7b0058..37024d68a26e 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -295,7 +295,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
goto __error;
}
}
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL) {
err = -ENOMEM;
goto __error;
@@ -304,7 +304,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
switch (entry->content) {
case SNDRV_INFO_CONTENT_TEXT:
if (mode == O_RDONLY || mode == O_RDWR) {
- buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
kfree(data);
err = -ENOMEM;
@@ -323,7 +323,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
data->rbuffer = buffer;
}
if (mode == O_WRONLY || mode == O_RDWR) {
- buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
if (mode == O_RDWR) {
vfree(data->rbuffer->buffer);
@@ -752,7 +752,7 @@ char *snd_info_get_str(char *dest, char *src, int len)
static snd_info_entry_t *snd_info_create_entry(const char *name)
{
snd_info_entry_t *entry;
- entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
return NULL;
entry->name = kstrdup(name, GFP_KERNEL);
diff --git a/sound/core/init.c b/sound/core/init.c
index d72f58f450ce..a5702014a704 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -72,7 +72,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
if (extra_size < 0)
extra_size = 0;
- card = kcalloc(1, sizeof(*card) + extra_size, GFP_KERNEL);
+ card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
if (card == NULL)
return NULL;
if (xid) {
@@ -226,8 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
return 0;
}
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
-static void snd_generic_device_unregister(struct snd_generic_device *dev);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+static void snd_generic_device_unregister(snd_card_t *card);
+#else
+#define snd_generic_device_unregister(x) /*NOP*/
#endif
/**
@@ -253,14 +255,7 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
-#ifdef CONFIG_SND_GENERIC_PM
- if (card->pm_dev) {
- snd_generic_device_unregister(card->pm_dev);
- card->pm_dev = NULL;
- }
-#endif
#endif
-
/* wait, until all devices are ready for the free operation */
wait_event(card->shutdown_sleep, card->files == NULL);
@@ -288,6 +283,7 @@ int snd_card_free(snd_card_t * card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
+ snd_generic_device_unregister(card);
while (card->s_f_ops) {
s_f_ops = card->s_f_ops;
card->s_f_ops = s_f_ops->next;
@@ -665,6 +661,96 @@ int snd_card_file_remove(snd_card_t *card, struct file *file)
return 0;
}
+#ifdef CONFIG_SND_GENERIC_DRIVER
+/*
+ * generic device without a proper bus using platform_device
+ * (e.g. ISA)
+ */
+struct snd_generic_device {
+ struct platform_device pdev;
+ snd_card_t *card;
+};
+
+#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
+
+#define SND_GENERIC_NAME "snd_generic"
+
+#ifdef CONFIG_PM
+static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
+static int snd_generic_resume(struct device *dev, u32 level);
+#endif
+
+/* initialized in sound.c */
+struct device_driver snd_generic_driver = {
+ .name = SND_GENERIC_NAME,
+ .bus = &platform_bus_type,
+#ifdef CONFIG_PM
+ .suspend = snd_generic_suspend,
+ .resume = snd_generic_resume,
+#endif
+};
+
+void snd_generic_device_release(struct device *dev)
+{
+}
+
+static int snd_generic_device_register(snd_card_t *card)
+{
+ struct snd_generic_device *dev;
+ int err;
+
+ if (card->generic_dev)
+ return 0; /* already registered */
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (! dev) {
+ snd_printk(KERN_ERR "can't allocate generic_device\n");
+ return -ENOMEM;
+ }
+
+ dev->pdev.name = SND_GENERIC_NAME;
+ dev->pdev.id = card->number;
+ dev->pdev.dev.release = snd_generic_device_release;
+ dev->card = card;
+ if ((err = platform_device_register(&dev->pdev)) < 0) {
+ kfree(dev);
+ return err;
+ }
+ card->generic_dev = dev;
+ return 0;
+}
+
+static void snd_generic_device_unregister(snd_card_t *card)
+{
+ struct snd_generic_device *dev = card->generic_dev;
+ if (dev) {
+ platform_device_unregister(&dev->pdev);
+ kfree(dev);
+ card->generic_dev = NULL;
+ }
+}
+
+/**
+ * snd_card_set_generic_dev - assign the generic device to the card
+ * @card: soundcard structure
+ *
+ * Assigns a generic device to the card. This function is provided as the
+ * last resort, for devices without any proper bus. Thus this won't override
+ * the device already assigned to the card.
+ *
+ * Returns zero if successful, or a negative error code.
+ */
+int snd_card_set_generic_dev(snd_card_t *card)
+{
+ int err;
+ if ((err = snd_generic_device_register(card)) < 0)
+ return err;
+ if (! card->dev)
+ snd_card_set_dev(card, &card->generic_dev->pdev.dev);
+ return 0;
+}
+#endif /* CONFIG_SND_GENERIC_DRIVER */
+
#ifdef CONFIG_PM
/**
* snd_power_wait - wait until the power-state is changed.
@@ -730,75 +816,7 @@ int snd_card_set_pm_callback(snd_card_t *card,
return 0;
}
-#ifdef CONFIG_SND_GENERIC_PM
-/*
- * use platform_device for generic power-management without a proper bus
- * (e.g. ISA)
- */
-struct snd_generic_device {
- struct platform_device pdev;
- snd_card_t *card;
-};
-
-#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
-
-#define SND_GENERIC_NAME "snd_generic_pm"
-
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
-static int snd_generic_resume(struct device *dev, u32 level);
-
-static struct device_driver snd_generic_driver = {
- .name = SND_GENERIC_NAME,
- .bus = &platform_bus_type,
- .suspend = snd_generic_suspend,
- .resume = snd_generic_resume,
-};
-
-static int generic_driver_registered;
-
-static void generic_driver_unregister(void)
-{
- if (generic_driver_registered) {
- generic_driver_registered--;
- if (! generic_driver_registered)
- driver_unregister(&snd_generic_driver);
- }
-}
-
-static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
-{
- struct snd_generic_device *dev;
-
- if (! generic_driver_registered) {
- if (driver_register(&snd_generic_driver) < 0)
- return NULL;
- }
- generic_driver_registered++;
-
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
- if (! dev) {
- generic_driver_unregister();
- return NULL;
- }
-
- dev->pdev.name = SND_GENERIC_NAME;
- dev->pdev.id = card->number;
- dev->card = card;
- if (platform_device_register(&dev->pdev) < 0) {
- kfree(dev);
- generic_driver_unregister();
- return NULL;
- }
- return dev;
-}
-
-static void snd_generic_device_unregister(struct snd_generic_device *dev)
-{
- platform_device_unregister(&dev->pdev);
- kfree(dev);
- generic_driver_unregister();
-}
-
+#ifdef CONFIG_SND_GENERIC_DRIVER
/* suspend/resume callbacks for snd_generic platform device */
static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
{
@@ -846,13 +864,12 @@ int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*resume)(snd_card_t *),
void *private_data)
{
- card->pm_dev = snd_generic_device_register(card);
- if (! card->pm_dev)
- return -ENOMEM;
- snd_card_set_pm_callback(card, suspend, resume, private_data);
- return 0;
+ int err;
+ if ((err = snd_generic_device_register(card)) < 0)
+ return err;
+ return snd_card_set_pm_callback(card, suspend, resume, private_data);
}
-#endif /* CONFIG_SND_GENERIC_PM */
+#endif /* CONFIG_SND_GENERIC_DRIVER */
#ifdef CONFIG_PCI
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 02132561c3f8..91124ddbdda9 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -512,7 +512,7 @@ static void free_all_reserved_pages(void)
* proc file interface
*/
#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
-struct proc_dir_entry *snd_mem_proc;
+static struct proc_dir_entry *snd_mem_proc;
static int snd_mem_proc_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
@@ -590,7 +590,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
alloced = 0;
pci = NULL;
- while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+ while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
if (mask > 0 && mask < 0xffffffff) {
if (pci_set_dma_mask(pci, mask) < 0 ||
pci_set_consistent_dma_mask(pci, mask) < 0) {
@@ -604,6 +604,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+ pci_dev_put(pci);
return (int)count;
}
snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
@@ -655,8 +656,7 @@ static int __init snd_mem_init(void)
static void __exit snd_mem_exit(void)
{
- if (snd_mem_proc)
- remove_proc_entry(SND_MEM_PROC_FILE, NULL);
+ remove_proc_entry(SND_MEM_PROC_FILE, NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index f6895577bf86..8fa888fc53a0 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -56,7 +56,7 @@ static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
#define VMALLOC_MAGIC 0x87654320
static snd_info_entry_t *snd_memory_info_entry;
-void snd_memory_init(void)
+void __init snd_memory_init(void)
{
snd_alloc_kmalloc = 0;
snd_alloc_vmalloc = 0;
@@ -116,15 +116,21 @@ void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags)
return _snd_kmalloc(size, flags);
}
+void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags)
+{
+ void *ret = _snd_kmalloc(size, flags);
+ if (ret)
+ memset(ret, 0, size);
+ return ret;
+}
+EXPORT_SYMBOL(snd_hidden_kzalloc);
+
void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags)
{
void *ret = NULL;
if (n != 0 && size > INT_MAX / n)
return ret;
- ret = _snd_kmalloc(n * size, flags);
- if (ret)
- memset(ret, 0, n * size);
- return ret;
+ return snd_hidden_kzalloc(n * size, flags);
}
void snd_hidden_kfree(const void *obj)
@@ -243,7 +249,7 @@ int __exit snd_memory_info_done(void)
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
+ return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
#else
char buf[256];
while (count) {
@@ -274,7 +280,7 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
+ return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
#else
char buf[256];
while (count) {
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 98fc0766f885..69e1059112d1 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -53,7 +53,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
err = snd_card_file_add(card, file);
if (err < 0)
return err;
- fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
+ fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
if (fmixer == NULL) {
snd_card_file_remove(card, file);
return -ENOMEM;
@@ -517,8 +517,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
up_read(&card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -551,8 +551,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
up_read(&card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -612,8 +612,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
return;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -649,8 +649,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
up_read(&fmixer->card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -768,8 +768,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
snd_ctl_elem_value_t *uctl;
int err, idx;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
@@ -813,8 +813,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
int err;
unsigned int idx;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index de7444c586f9..842c28b2ed55 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -850,7 +850,9 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN;
}
} else {
- tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
+ tmp = snd_pcm_oss_write2(substream,
+ (const char __force *)buf,
+ runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -926,7 +928,8 @@ static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *bu
xfer += tmp;
runtime->oss.buffer_used -= tmp;
} else {
- tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0);
+ tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
+ runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -1540,7 +1543,11 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
} else {
delay = snd_pcm_oss_bytes(substream, delay);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+ snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ if (setup && setup->buggyptr)
+ info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+ else
+ info.blocks = (delay + fixup) / runtime->oss.period_bytes;
info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
} else {
delay += fixup;
@@ -1705,13 +1712,12 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
snd_pcm_stream_unlock_irq(substream);
- if (substream->open_flag) {
+ if (substream->ffile != NULL) {
if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream);
substream->ops->close(substream);
- substream->open_flag = 0;
+ substream->ffile = NULL;
}
- substream->ffile = NULL;
snd_pcm_oss_release_substream(substream);
snd_pcm_release_substream(substream);
}
@@ -1734,7 +1740,7 @@ static int snd_pcm_oss_open_file(struct file *file,
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
*rpcm_oss_file = NULL;
- pcm_oss_file = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL);
+ pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
if (pcm_oss_file == NULL)
return -ENOMEM;
@@ -1778,14 +1784,13 @@ static int snd_pcm_oss_open_file(struct file *file,
snd_pcm_oss_release_file(pcm_oss_file);
return err;
}
- psubstream->open_flag = 1;
+ 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;
}
- psubstream->ffile = file;
snd_pcm_oss_init_substream(psubstream, psetup, minor);
}
if (csubstream != NULL) {
@@ -1800,14 +1805,13 @@ static int snd_pcm_oss_open_file(struct file *file,
snd_pcm_oss_release_file(pcm_oss_file);
return err;
}
- csubstream->open_flag = 1;
+ 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;
}
- csubstream->ffile = file;
snd_pcm_oss_init_substream(csubstream, csetup, minor);
}
@@ -2350,6 +2354,8 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
template.partialfrag = 1;
} else if (!strcmp(str, "no-silence")) {
template.nosilence = 1;
+ } else if (!strcmp(str, "buggy-ptr")) {
+ template.buggyptr = 1;
}
} while (*str);
if (setup == NULL) {
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6430410c6c04..fc23373c000d 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -171,7 +171,7 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
snd_assert(plug != NULL, return -ENXIO);
snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
- plugin = kcalloc(1, sizeof(*plugin) + extra, GFP_KERNEL);
+ plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
if (plugin == NULL)
return -ENOMEM;
plugin->name = name;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9f4c9209b271..1be470e942ef 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -597,7 +597,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
}
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
- substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (substream == NULL)
return -ENOMEM;
substream->pcm = pcm;
@@ -657,7 +657,7 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
snd_assert(rpcm != NULL, return -EINVAL);
*rpcm = NULL;
snd_assert(card != NULL, return -ENXIO);
- pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
+ pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (pcm == NULL)
return -ENOMEM;
pcm->card = card;
@@ -795,7 +795,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
if (substream == NULL)
return -EAGAIN;
- runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
if (runtime == NULL)
return -ENOMEM;
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 3920bf0eebbf..4b6307df846d 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 {
unsigned char reserved[64];
};
+/* recalcuate the boundary within 32bit */
+static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
+{
+ snd_pcm_uframes_t boundary;
+
+ if (! runtime->buffer_size)
+ return 0;
+ boundary = runtime->buffer_size;
+ while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+ boundary *= 2;
+ return boundary;
+}
+
static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
struct sndrv_pcm_sw_params32 __user *src)
{
snd_pcm_sw_params_t params;
+ snd_pcm_uframes_t boundary;
int err;
memset(&params, 0, sizeof(params));
@@ -120,10 +134,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
get_user(params.silence_threshold, &src->silence_threshold) ||
get_user(params.silence_size, &src->silence_size))
return -EFAULT;
+ /*
+ * Check silent_size parameter. Since we have 64bit boundary,
+ * silence_size must be compared with the 32bit boundary.
+ */
+ boundary = recalculate_boundary(substream->runtime);
+ if (boundary && params.silence_size >= boundary)
+ params.silence_size = substream->runtime->boundary;
err = snd_pcm_sw_params(substream, &params);
if (err < 0)
return err;
- if (put_user(params.boundary, &src->boundary))
+ if (boundary && put_user(boundary, &src->boundary))
return -EFAULT;
return err;
}
@@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
return err;
}
-/* recalcuate the boundary within 32bit */
-static void recalculate_boundary(snd_pcm_runtime_t *runtime)
-{
- if (! runtime->buffer_size)
- return;
- runtime->boundary = runtime->buffer_size;
- while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
- runtime->boundary *= 2;
-}
-
/* both for HW_PARAMS and HW_REFINE */
static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
int refine,
@@ -241,8 +252,11 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
goto error;
}
- if (! refine)
- recalculate_boundary(runtime);
+ if (! refine) {
+ unsigned int new_boundary = recalculate_boundary(runtime);
+ if (new_boundary)
+ runtime->boundary = new_boundary;
+ }
error:
kfree(data);
return err;
@@ -380,6 +394,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
u32 sflags;
struct sndrv_pcm_mmap_control scontrol;
struct sndrv_pcm_mmap_status sstatus;
+ snd_pcm_uframes_t boundary;
int err;
snd_assert(runtime, return -EINVAL);
@@ -395,17 +410,21 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
}
status = runtime->status;
control = runtime->control;
+ boundary = recalculate_boundary(runtime);
+ if (! boundary)
+ boundary = 0x7fffffff;
snd_pcm_stream_lock_irq(substream);
+ /* FIXME: we should consider the boundary for the sync from app */
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
control->appl_ptr = scontrol.appl_ptr;
else
- scontrol.appl_ptr = control->appl_ptr;
+ scontrol.appl_ptr = control->appl_ptr % boundary;
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = scontrol.avail_min;
else
scontrol.avail_min = control->avail_min;
sstatus.state = status->state;
- sstatus.hw_ptr = status->hw_ptr;
+ sstatus.hw_ptr = status->hw_ptr % boundary;
sstatus.tstamp = status->tstamp;
sstatus.suspended_state = status->suspended_state;
snd_pcm_stream_unlock_irq(substream);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index c5bfd0918cff..0503980c23d9 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -524,6 +524,9 @@ void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_inte
/**
* snd_interval_div - refine the interval value with division
+ * @a: dividend
+ * @b: divisor
+ * @c: quotient
*
* c = a / b
*
@@ -555,7 +558,11 @@ void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_inte
/**
* snd_interval_muldivk - refine the interval value
- *
+ * @a: dividend 1
+ * @b: dividend 2
+ * @k: divisor (as integer)
+ * @c: result
+ *
* c = a * b / k
*
* Returns non-zero if the value is changed, zero if not changed.
@@ -582,6 +589,10 @@ void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
/**
* snd_interval_mulkdiv - refine the interval value
+ * @a: dividend 1
+ * @k: dividend 2 (as integer)
+ * @b: divisor
+ * @c: result
*
* c = a * k / b
*
@@ -618,6 +629,11 @@ void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
/**
* snd_interval_ratnum - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratnum_t
+ * @rats: ratnum_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
*
* Returns non-zero if the value is changed, zero if not changed.
*/
@@ -715,6 +731,11 @@ int snd_interval_ratnum(snd_interval_t *i,
/**
* snd_interval_ratden - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratden_t
+ * @rats: ratden_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
*
* Returns non-zero if the value is changed, zero if not changed.
*/
@@ -936,6 +957,11 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
/**
* snd_pcm_hw_constraint_mask
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
*/
int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int32_t mask)
@@ -951,6 +977,11 @@ int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t va
/**
* snd_pcm_hw_constraint_mask64
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the 64bit bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
*/
int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int64_t mask)
@@ -967,6 +998,10 @@ int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
/**
* snd_pcm_hw_constraint_integer
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the integer constraint
+ *
+ * Apply the constraint of integer to an interval parameter.
*/
int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var)
{
@@ -976,6 +1011,12 @@ int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
/**
* snd_pcm_hw_constraint_minmax
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the range
+ * @min: the minimal value
+ * @max: the maximal value
+ *
+ * Apply the min/max range constraint to an interval parameter.
*/
int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max)
@@ -999,6 +1040,12 @@ static int snd_pcm_hw_rule_list(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_list
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the list constraint
+ * @l: list
+ *
+ * Apply the list of constraints to an interval parameter.
*/
int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1027,6 +1074,10 @@ static int snd_pcm_hw_rule_ratnums(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_ratnums
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratnums constraint
+ * @r: ratnums_t constriants
*/
int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1054,6 +1105,10 @@ static int snd_pcm_hw_rule_ratdens(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_ratdens
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratdens constraint
+ * @r: ratdens_t constriants
*/
int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1079,6 +1134,10 @@ static int snd_pcm_hw_rule_msbits(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_msbits
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @width: sample bits width
+ * @msbits: msbits width
*/
int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1101,6 +1160,10 @@ static int snd_pcm_hw_rule_step(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_step
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the step constraint
+ * @step: step size
*/
int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1126,6 +1189,9 @@ static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *
/**
* snd_pcm_hw_constraint_pow2
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the power-of-2 constraint
*/
int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1162,7 +1228,7 @@ static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
}
#if 0
-/**
+/*
* snd_pcm_hw_param_any
*/
int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
@@ -1185,7 +1251,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
}
#if 0
-/**
+/*
* snd_pcm_hw_params_any
*
* Fill PARAMS with full configuration space boundaries
@@ -1199,6 +1265,9 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
/**
* snd_pcm_hw_param_value
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the value for field PAR if it's fixed in configuration space
* defined by PARAMS. Return -EINVAL otherwise
@@ -1228,6 +1297,9 @@ static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_value_min
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the minimum value for field PAR.
*/
@@ -1251,6 +1323,9 @@ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_value_max
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the maximum value for field PAR.
*/
@@ -1302,7 +1377,7 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
}
#if 0
-/**
+/*
* snd_pcm_hw_param_setinteger
*
* Inside configuration space defined by PARAMS remove from PAR all
@@ -1347,6 +1422,10 @@ static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_first
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values > minimum. Reduce configuration space accordingly.
@@ -1388,6 +1467,10 @@ static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_last
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values < maximum. Reduce configuration space accordingly.
@@ -1439,6 +1522,11 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_min
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: minimal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values < VAL. Reduce configuration space accordingly.
@@ -1494,6 +1582,11 @@ static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_max
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: maximal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values >= VAL + 1. Reduce configuration space accordingly.
@@ -1565,6 +1658,11 @@ int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_set
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values != VAL. Reduce configuration space accordingly.
@@ -1584,8 +1682,8 @@ int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
return snd_pcm_hw_param_value(params, var, NULL);
}
-int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, const snd_mask_t *val)
+static int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, const snd_mask_t *val)
{
int changed;
assert(hw_is_mask(var));
@@ -1599,6 +1697,10 @@ int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_mask
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: mask to apply
*
* Inside configuration space defined by PARAMS remove from PAR all values
* not contained in MASK. Reduce configuration space accordingly.
@@ -1671,6 +1773,11 @@ static int boundary_nearer(int min, int mindir,
/**
* snd_pcm_hw_param_near
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @best: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS set PAR to the available value
* nearest to VAL. Reduce configuration space accordingly.
@@ -1747,6 +1854,8 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_choose
+ * @pcm: PCM instance
+ * @params: the hw_params instance
*
* Choose one configuration from configuration space defined by PARAMS
* The configuration chosen is that obtained fixing in this order:
@@ -2063,7 +2172,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
wait_queue_t wait;
- enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
+ enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
long tout;
if (nonblock) {
@@ -2097,6 +2206,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
case SNDRV_PCM_STATE_SUSPENDED:
state = SUSPENDED;
goto _end_loop;
+ case SNDRV_PCM_STATE_SETUP:
+ state = DROPPED;
+ goto _end_loop;
default:
break;
}
@@ -2123,6 +2235,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
snd_printd("playback write error (DMA or IRQ trouble?)\n");
err = -EIO;
goto _end_unlock;
+ case DROPPED:
+ err = -EBADFD;
+ goto _end_unlock;
default:
break;
}
@@ -2359,7 +2474,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
} else if ((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align)) {
wait_queue_t wait;
- enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
+ enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
long tout;
if (nonblock) {
@@ -2394,6 +2509,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
goto _end_loop;
case SNDRV_PCM_STATE_DRAINING:
goto __draining;
+ case SNDRV_PCM_STATE_SETUP:
+ state = DROPPED;
+ goto _end_loop;
default:
break;
}
@@ -2420,6 +2538,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
snd_printd("capture read error (DMA or IRQ trouble?)\n");
err = -EIO;
goto _end_unlock;
+ case DROPPED:
+ err = -EBADFD;
+ goto _end_unlock;
default:
break;
}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 9a174fb96565..b3f5344f60be 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -244,7 +244,7 @@ int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
/**
* snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
- * @substream: the pcm substream instance
+ * @pcm: the pcm instance
* @type: DMA type (SNDRV_DMA_TYPE_*)
* @data: DMA type dependant data
* @size: the requested pre-allocation size in bytes
@@ -321,7 +321,7 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
} else {
- dmab = kcalloc(1, sizeof(*dmab), GFP_KERNEL);
+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
if (! dmab)
return -ENOMEM;
dmab->dev = substream->dma_buffer.dev;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 10c2c9832649..67abebabf83e 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -859,6 +859,7 @@ static struct action_ops snd_pcm_action_start = {
/**
* snd_pcm_start
+ * @substream: the PCM substream instance
*
* Start all linked streams.
*/
@@ -908,6 +909,8 @@ static struct action_ops snd_pcm_action_stop = {
/**
* snd_pcm_stop
+ * @substream: the PCM substream instance
+ * @state: PCM state after stopping the stream
*
* Try to stop all running streams in the substream group.
* The state of each stream is changed to the given value after that unconditionally.
@@ -919,6 +922,7 @@ int snd_pcm_stop(snd_pcm_substream_t *substream, int state)
/**
* snd_pcm_drain_done
+ * @substream: the PCM substream
*
* Stop the DMA only when the given stream is playback.
* The state is changed to SETUP.
@@ -1025,7 +1029,7 @@ static void snd_pcm_post_suspend(snd_pcm_substream_t *substream, int state)
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MPAUSE, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND, &runtime->trigger_tstamp);
runtime->status->suspended_state = runtime->status->state;
runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
snd_pcm_tick_set(substream, 0);
@@ -1040,6 +1044,7 @@ static struct action_ops snd_pcm_action_suspend = {
/**
* snd_pcm_suspend
+ * @substream: the PCM substream
*
* Trigger SUSPEND to all linked streams.
* After this call, all streams are changed to SUSPENDED state.
@@ -1057,6 +1062,7 @@ int snd_pcm_suspend(snd_pcm_substream_t *substream)
/**
* snd_pcm_suspend_all
+ * @pcm: the PCM instance
*
* Trigger SUSPEND to all substreams in the given pcm.
* After this call, all streams are changed to SUSPENDED state.
@@ -1115,7 +1121,7 @@ static void snd_pcm_post_resume(snd_pcm_substream_t *substream, int state)
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MCONTINUE, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME, &runtime->trigger_tstamp);
runtime->status->state = runtime->status->suspended_state;
if (runtime->sleep_min)
snd_pcm_tick_prepare(substream);
@@ -1272,6 +1278,9 @@ static struct action_ops snd_pcm_action_prepare = {
/**
* snd_pcm_prepare
+ * @substream: the PCM substream instance
+ *
+ * Prepare the PCM substream to be triggerable.
*/
int snd_pcm_prepare(snd_pcm_substream_t *substream)
{
@@ -1967,13 +1976,12 @@ static int snd_pcm_release_file(snd_pcm_file_t * pcm_file)
runtime = substream->runtime;
str = substream->pstr;
snd_pcm_unlink(substream);
- if (substream->open_flag) {
+ if (substream->ffile != NULL) {
if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream);
substream->ops->close(substream);
- substream->open_flag = 0;
+ substream->ffile = NULL;
}
- substream->ffile = NULL;
snd_pcm_remove_file(str, pcm_file);
snd_pcm_release_substream(substream);
kfree(pcm_file);
@@ -1993,7 +2001,7 @@ static int snd_pcm_open_file(struct file *file,
snd_assert(rpcm_file != NULL, return -EINVAL);
*rpcm_file = NULL;
- pcm_file = kcalloc(1, sizeof(*pcm_file), GFP_KERNEL);
+ pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
if (pcm_file == NULL) {
return -ENOMEM;
}
@@ -2022,18 +2030,15 @@ static int snd_pcm_open_file(struct file *file,
snd_pcm_release_file(pcm_file);
return err;
}
- substream->open_flag = 1;
+ substream->ffile = file;
err = snd_pcm_hw_constraints_complete(substream);
if (err < 0) {
snd_printd("snd_pcm_hw_constraints_complete failed\n");
- substream->ops->close(substream);
snd_pcm_release_file(pcm_file);
return err;
}
- substream->ffile = file;
-
file->private_data = pcm_file;
*rpcm_file = pcm_file;
return 0;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index edba4118271c..7c20eafecb8a 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -101,7 +101,7 @@ static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
{
snd_rawmidi_runtime_t *runtime;
- if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL)
+ if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
return -ENOMEM;
spin_lock_init(&runtime->lock);
init_waitqueue_head(&runtime->sleep);
@@ -984,7 +984,9 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
+ count1 = snd_rawmidi_kernel_read1(substream,
+ (unsigned char __force *)buf,
+ count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1107,7 +1109,7 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
/**
* snd_rawmidi_transmit - copy from the buffer to the device
* @substream: the rawmidi substream
- * @buf: the buffer pointer
+ * @buffer: the buffer pointer
* @count: the data size to transfer
*
* Copies data from the buffer to the device and advances the pointer.
@@ -1213,7 +1215,9 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
+ count1 = snd_rawmidi_kernel_write1(substream,
+ (unsigned char __force *)buf,
+ count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1370,7 +1374,7 @@ static int snd_rawmidi_alloc_substreams(snd_rawmidi_t *rmidi,
INIT_LIST_HEAD(&stream->substreams);
for (idx = 0; idx < count; idx++) {
- substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (substream == NULL)
return -ENOMEM;
substream->stream = direction;
@@ -1413,7 +1417,7 @@ int snd_rawmidi_new(snd_card_t * card, char *id, int device,
snd_assert(rrawmidi != NULL, return -EINVAL);
*rrawmidi = NULL;
snd_assert(card != NULL, return -ENXIO);
- rmidi = kcalloc(1, sizeof(*rmidi), GFP_KERNEL);
+ rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
if (rmidi == NULL)
return -ENOMEM;
rmidi->card = card;
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 32e91c6b25fe..207c2c54bf1d 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -61,7 +61,7 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
return -EFAULT;
*data += sizeof(xp);
*len -= sizeof(xp);
- wp = kcalloc(1, sizeof(*wp), gfp_mask);
+ wp = kzalloc(sizeof(*wp), gfp_mask);
if (wp == NULL)
return -ENOMEM;
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 2622b8679ca7..b3cee092b1a4 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -92,7 +92,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
if (points_size > *len)
return -EINVAL;
- rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
+ rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
if (rp == NULL)
return -ENOMEM;
rp->nattack = le16_to_cpu(rx.nattack);
@@ -139,7 +139,7 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
return -EFAULT;
*data += sizeof(xp);
*len -= sizeof(xp);
- wp = kcalloc(1, sizeof(*wp), gfp_mask);
+ wp = kzalloc(sizeof(*wp), gfp_mask);
if (wp == NULL)
return -ENOMEM;
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -273,7 +273,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
snd_seq_iwffff_instr_free(ops, ip, atomic);
return -EINVAL;
}
- lp = kcalloc(1, sizeof(*lp), gfp_mask);
+ lp = kzalloc(sizeof(*lp), gfp_mask);
if (lp == NULL) {
snd_seq_iwffff_instr_free(ops, ip, atomic);
return -ENOMEM;
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index bac4b4f1a94e..1ab1cf8158c8 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -193,7 +193,7 @@ snd_seq_oss_open(struct file *file, int level)
int i, rc;
seq_oss_devinfo_t *dp;
- if ((dp = kcalloc(1, sizeof(*dp), GFP_KERNEL)) == NULL) {
+ if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc device info\n");
return -ENOMEM;
}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 9aece6c65dbc..f0e95c8f2eef 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -76,8 +76,8 @@ snd_seq_oss_midi_lookup_ports(int client)
snd_seq_client_info_t *clinfo;
snd_seq_port_info_t *pinfo;
- clinfo = kcalloc(1, sizeof(*clinfo), GFP_KERNEL);
- pinfo = kcalloc(1, sizeof(*pinfo), GFP_KERNEL);
+ clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
+ pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
if (! clinfo || ! pinfo) {
kfree(clinfo);
kfree(pinfo);
@@ -172,7 +172,7 @@ snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
/*
* allocate midi info record
*/
- if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
+ if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc midi info\n");
return -ENOMEM;
}
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 0a6f2a64f692..55571e15cd38 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -46,7 +46,7 @@ snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
{
seq_oss_readq_t *q;
- if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
+ if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc read queue\n");
return NULL;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 1a7736cbf3a4..8257fce2ca1b 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -103,7 +103,7 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
unsigned long flags;
- if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
+ if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc synth info\n");
return -ENOMEM;
}
@@ -499,7 +499,7 @@ snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_
sysex = dp->synths[dev].sysex;
if (sysex == NULL) {
- sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
+ sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
if (sysex == NULL)
return -ENOMEM;
dp->synths[dev].sysex = sysex;
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index 42ca9493fa60..64d594b3170f 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -46,7 +46,7 @@ snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
{
seq_oss_timer_t *rec;
- rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (rec == NULL)
return NULL;
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 87f85f7ee814..b20378024547 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -38,7 +38,7 @@ snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
seq_oss_writeq_t *q;
snd_seq_client_pool_t pool;
- if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
+ if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
return NULL;
q->dp = dp;
q->maxlen = maxlen;
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 7449d2a62629..24644150f24b 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -43,7 +43,13 @@ int seq_client_load[64] = {[0 ... 63] = -1};
int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
int seq_default_timer_card = -1;
-int seq_default_timer_device = SNDRV_TIMER_GLOBAL_SYSTEM;
+int seq_default_timer_device =
+#ifdef CONFIG_SND_SEQ_RTCTIMER_DEFAULT
+ SNDRV_TIMER_GLOBAL_RTC
+#else
+ SNDRV_TIMER_GLOBAL_SYSTEM
+#endif
+ ;
int seq_default_timer_subdevice = 0;
int seq_default_timer_resolution = 0; /* Hz */
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index d8f76afd284b..a886db94b1fa 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -203,7 +203,7 @@ static client_t *seq_create_client1(int client_index, int poolsize)
client_t *client;
/* init client data */
- client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL)
return NULL;
client->pool = snd_seq_pool_new(poolsize);
@@ -413,7 +413,9 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
}
count -= sizeof(snd_seq_event_t);
buf += sizeof(snd_seq_event_t);
- err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t));
+ err = snd_seq_expand_var_event(&cell->event, count,
+ (char __force *)buf, 0,
+ sizeof(snd_seq_event_t));
if (err < 0)
break;
result += err;
@@ -1009,7 +1011,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c
}
/* set user space pointer */
event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
- event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);
+ event.data.ext.ptr = (char __force *)buf
+ + sizeof(snd_seq_event_t);
len += extlen; /* increment data length */
} else {
#ifdef CONFIG_COMPAT
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4d80f39612e8..252b52731003 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -200,7 +200,7 @@ int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
if (ops == NULL)
return -ENOMEM;
- dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
if (dev == NULL) {
unlock_driver(ops);
return -ENOMEM;
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ea945a5d2a0b..5dd0e6a19e50 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -153,7 +153,7 @@ create_port(int idx, int type)
snd_seq_port_callback_t pcb;
snd_seq_dummy_port_t *rec;
- if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL)
+ if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
return NULL;
rec->client = my_client;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 3b7647ca7ad9..4767cfdc361f 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -33,7 +33,7 @@ fifo_t *snd_seq_fifo_new(int poolsize)
{
fifo_t *f;
- f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
snd_printd("malloc failed for snd_seq_fifo_new() \n");
return NULL;
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 5b40ea2ba8f4..019d43a462d7 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -53,7 +53,7 @@ static snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic)
{
snd_seq_kinstr_t *instr;
- instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+ instr = kzalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
if (instr == NULL)
return NULL;
instr->add_len = add_len;
@@ -77,7 +77,7 @@ snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
{
snd_seq_kinstr_list_t *list;
- list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+ list = kzalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
if (list == NULL)
return NULL;
spin_lock_init(&list->lock);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 03acb2d519ba..d4d7d326c4b1 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -452,7 +452,7 @@ pool_t *snd_seq_pool_new(int poolsize)
pool_t *pool;
/* create pool block */
- pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
if (pool == NULL) {
snd_printd("seq: malloc failed for pool\n");
return NULL;
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 4374829ea770..b4674ae3bc30 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -322,7 +322,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
client = synths[card->number];
if (client == NULL) {
newclient = 1;
- client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL) {
up(&register_mutex);
kfree(info);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 603b63716db6..2dc1aecfb426 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -118,7 +118,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
snd_midi_event_t *dev;
*rdev = NULL;
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
if (bufsize > 0) {
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index b976951fc100..57ec31df0d15 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -141,7 +141,7 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
}
/* create a new port */
- new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
+ new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
if (! new_port) {
snd_printd("malloc failed for registering client port\n");
return NULL; /* failure, out of memory */
@@ -488,7 +488,7 @@ int snd_seq_port_connect(client_t *connector,
unsigned long flags;
int exclusive;
- subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
+ subs = kzalloc(sizeof(*subs), GFP_KERNEL);
if (! subs)
return -ENOMEM;
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index a519732ed833..cd641bca9945 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -59,7 +59,7 @@ prioq_t *snd_seq_prioq_new(void)
{
prioq_t *f;
- f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
return NULL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 98de2e711fde..5f5c3cb37cbf 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -111,7 +111,7 @@ static queue_t *queue_new(int owner, int locked)
{
queue_t *q;
- q = kcalloc(1, sizeof(*q), GFP_KERNEL);
+ q = kzalloc(sizeof(*q), GFP_KERNEL);
if (q == NULL) {
snd_printd("malloc failed for snd_seq_queue_new()\n");
return NULL;
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index e8f0a6683d50..0d9eff85ab88 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -126,8 +126,8 @@ int __init snd_seq_system_client_init(void)
snd_seq_client_info_t *inf;
snd_seq_port_info_t *port;
- inf = kcalloc(1, sizeof(*inf), GFP_KERNEL);
- port = kcalloc(1, sizeof(*port), GFP_KERNEL);
+ inf = kzalloc(sizeof(*inf), GFP_KERNEL);
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
if (! inf || ! port) {
kfree(inf);
kfree(port);
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index a7f76fc95280..b57a3c07ff6f 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -60,7 +60,7 @@ seq_timer_t *snd_seq_timer_new(void)
{
seq_timer_t *tmr;
- tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
+ tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
if (tmr == NULL) {
snd_printd("malloc failed for snd_seq_timer_new() \n");
return NULL;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index a66484b5cf0e..e4f512aa7426 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -205,7 +205,7 @@ static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
snd_virmidi_t *vmidi;
unsigned long flags;
- vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+ vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
return -ENOMEM;
vmidi->substream = substream;
@@ -233,7 +233,7 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
snd_rawmidi_runtime_t *runtime = substream->runtime;
snd_virmidi_t *vmidi;
- vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+ vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
return -ENOMEM;
vmidi->substream = substream;
@@ -508,7 +508,7 @@ int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
&rmidi)) < 0)
return err;
strcpy(rmidi->name, rmidi->id);
- rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (rdev == NULL) {
snd_device_free(card, rmidi);
return -ENOMEM;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 3271e9245490..9e76bddb2c0b 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -328,6 +328,10 @@ int __exit snd_minor_info_done(void)
* INIT PART
*/
+#ifdef CONFIG_SND_GENERIC_DRIVER
+extern struct device_driver snd_generic_driver;
+#endif
+
static int __init alsa_sound_init(void)
{
short controlnum;
@@ -354,6 +358,9 @@ static int __init alsa_sound_init(void)
return -ENOMEM;
}
snd_info_minor_register();
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ driver_register(&snd_generic_driver);
+#endif
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
#ifndef MODULE
@@ -369,6 +376,9 @@ static void __exit alsa_sound_exit(void)
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_remove("snd/controlC%d", controlnum);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ driver_unregister(&snd_generic_driver);
+#endif
snd_info_minor_unregister();
snd_info_done();
snd_memory_done();
@@ -416,10 +426,13 @@ EXPORT_SYMBOL(snd_card_register);
EXPORT_SYMBOL(snd_component_add);
EXPORT_SYMBOL(snd_card_file_add);
EXPORT_SYMBOL(snd_card_file_remove);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+EXPORT_SYMBOL(snd_card_set_generic_dev);
+#endif
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_power_wait);
EXPORT_SYMBOL(snd_card_set_pm_callback);
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+#ifdef CONFIG_SND_GENERIC_DRIVER
EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
#endif
#ifdef CONFIG_PCI
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index de39d212bc15..e401c6703297 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -98,6 +98,7 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
int cidx = SNDRV_MINOR_OSS_CARD(minor);
int track2 = -1;
int register1 = -1, register2 = -1;
+ struct device *carddev = NULL;
if (minor < 0)
return minor;
@@ -121,11 +122,13 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break;
}
- register1 = register_sound_special(reg->f_ops, minor);
+ if (card)
+ carddev = card->dev;
+ register1 = register_sound_special_device(reg->f_ops, minor, carddev);
if (register1 != minor)
goto __end;
if (track2 >= 0) {
- register2 = register_sound_special(reg->f_ops, track2);
+ register2 = register_sound_special_device(reg->f_ops, track2, carddev);
if (register2 != track2)
goto __end;
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index cfaccd415b3b..22b104624084 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -98,7 +98,7 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left);
static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer)
{
snd_timer_instance_t *timeri;
- timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
+ timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
if (timeri == NULL)
return NULL;
timeri->owner = kstrdup(owner, GFP_KERNEL);
@@ -764,7 +764,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t *
snd_assert(tid != NULL, return -EINVAL);
snd_assert(rtimer != NULL, return -EINVAL);
*rtimer = NULL;
- timer = kcalloc(1, sizeof(*timer), GFP_KERNEL);
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
if (timer == NULL)
return -ENOMEM;
timer->tmr_class = tid->dev_class;
@@ -799,13 +799,13 @@ static int snd_timer_free(snd_timer_t *timer)
return 0;
}
-int snd_timer_dev_free(snd_device_t *device)
+static int snd_timer_dev_free(snd_device_t *device)
{
snd_timer_t *timer = device->device_data;
return snd_timer_free(timer);
}
-int snd_timer_dev_register(snd_device_t *dev)
+static int snd_timer_dev_register(snd_device_t *dev)
{
snd_timer_t *timer = dev->device_data;
snd_timer_t *timer1;
@@ -880,9 +880,11 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t
struct list_head *p, *n;
snd_runtime_check(timer->hw.flags & SNDRV_TIMER_HW_SLAVE, return);
- snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MPAUSE, return);
+ snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MRESUME, return);
spin_lock_irqsave(&timer->lock, flags);
- if (event == SNDRV_TIMER_EVENT_MSTART || event == SNDRV_TIMER_EVENT_MCONTINUE) {
+ if (event == SNDRV_TIMER_EVENT_MSTART ||
+ event == SNDRV_TIMER_EVENT_MCONTINUE ||
+ event == SNDRV_TIMER_EVENT_MRESUME) {
if (timer->hw.c_resolution)
resolution = timer->hw.c_resolution(timer);
else
@@ -1015,7 +1017,7 @@ static int snd_timer_register_system(void)
return err;
strcpy(timer->name, "system timer");
timer->hw = snd_timer_system;
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL) {
snd_timer_free(timer);
return -ENOMEM;
@@ -1200,7 +1202,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
{
snd_timer_user_t *tu;
- tu = kcalloc(1, sizeof(*tu), GFP_KERNEL);
+ tu = kzalloc(sizeof(*tu), GFP_KERNEL);
if (tu == NULL)
return -ENOMEM;
spin_lock_init(&tu->qlock);
@@ -1511,7 +1513,7 @@ static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info
t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO);
- info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
info->card = t->card ? t->card->number : -1;
@@ -1555,10 +1557,14 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_
(1<<SNDRV_TIMER_EVENT_STOP)|
(1<<SNDRV_TIMER_EVENT_CONTINUE)|
(1<<SNDRV_TIMER_EVENT_PAUSE)|
+ (1<<SNDRV_TIMER_EVENT_SUSPEND)|
+ (1<<SNDRV_TIMER_EVENT_RESUME)|
(1<<SNDRV_TIMER_EVENT_MSTART)|
(1<<SNDRV_TIMER_EVENT_MSTOP)|
(1<<SNDRV_TIMER_EVENT_MCONTINUE)|
- (1<<SNDRV_TIMER_EVENT_MPAUSE))) {
+ (1<<SNDRV_TIMER_EVENT_MPAUSE)|
+ (1<<SNDRV_TIMER_EVENT_MSUSPEND)|
+ (1<<SNDRV_TIMER_EVENT_MRESUME))) {
err = -EINVAL;
goto _end;
}
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 3b2bee19e2c0..efcb4eb2d1a0 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -29,6 +29,7 @@ config SND_DUMMY
tristate "Dummy (/dev/null) soundcard"
depends on SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include the dummy driver. This driver does
nothing, but emulates various mixer controls and PCM devices.
@@ -44,6 +45,7 @@ config SND_VIRMIDI
depends on SND_SEQUENCER
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
Say Y here to include the virtual MIDI driver. This driver
allows to connect applications using raw MIDI devices to
@@ -59,6 +61,7 @@ config SND_MTPAV
depends on SND
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
To use a MOTU MidiTimePiece AV multiport MIDI adapter
connected to the parallel port, say Y here and make sure that
@@ -72,6 +75,7 @@ config SND_SERIAL_U16550
depends on SND
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
To include support for MIDI serial port interfaces, say Y here
and read <file:Documentation/sound/alsa/serial-u16550.txt>.
@@ -88,6 +92,7 @@ config SND_MPU401
tristate "Generic MPU-401 UART driver"
depends on SND
select SND_MPU401_UART
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for MIDI ports compatible with
the Roland MPU-401 interface in UART mode.
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a61640cf7ae7..64ef7f62851d 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -337,7 +337,7 @@ static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
snd_card_dummy_pcm_t *dpcm;
int err;
- dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+ dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (dpcm == NULL)
return -ENOMEM;
init_timer(&dpcm->timer);
@@ -368,7 +368,7 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
snd_card_dummy_pcm_t *dpcm;
int err;
- dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+ dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (dpcm == NULL)
return -ENOMEM;
init_timer(&dpcm->timer);
@@ -600,6 +600,10 @@ static int __init snd_card_dummy_probe(int dev)
strcpy(card->driver, "Dummy");
strcpy(card->shortname, "Dummy");
sprintf(card->longname, "Dummy %i", dev + 1);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __nodev;
+
if ((err = snd_card_register(card)) == 0) {
snd_dummy_cards[dev] = card;
return 0;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index cb36ecb78697..54e2ff9b5ca1 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -77,20 +77,26 @@ static int snd_mpu401_create(int dev, snd_card_t **rcard)
strcat(card->longname, "polled");
}
- if (snd_mpu401_uart_new(card, 0,
- MPU401_HW_MPU401,
- port[dev], 0,
- irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
+ if ((err = snd_mpu401_uart_new(card, 0,
+ MPU401_HW_MPU401,
+ port[dev], 0,
+ irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL)) < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
- snd_card_free(card);
- return -ENODEV;
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ goto _err;
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
*rcard = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_mpu401_probe(int dev)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 0f83c5241b6b..fe3f921ffbe3 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -463,7 +463,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
*rrawmidi = NULL;
if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
return err;
- mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
+ mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
if (mpu == NULL) {
snd_device_free(card, rmidi);
return -ENOMEM;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 1280a57c49eb..3a25c89d2983 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -688,7 +688,7 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
static mtpav_t *new_mtpav(void)
{
- mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
+ mtpav_t *ncrd = kzalloc(sizeof(*ncrd), GFP_KERNEL);
if (ncrd != NULL) {
spin_lock_init(&ncrd->spinlock);
@@ -757,6 +757,9 @@ static int __init alsa_card_mtpav_init(void)
if (err < 0)
goto __error;
+ if ((err = snd_card_set_generic_dev(mtp_card->card)) < 0)
+ goto __error;
+
err = snd_card_register(mtp_card->card); // don't snd_card_register until AFTER all cards reources done!
//printk("snd_card_register returned %d\n", err);
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index c313e5205cb8..1f84d78260de 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -354,7 +354,7 @@ int snd_opl3_new(snd_card_t *card,
int err;
*ropl3 = NULL;
- opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
+ opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
if (opl3 == NULL)
return -ENOMEM;
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 33da334ae981..21a2b409d6d3 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -241,7 +241,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
}
size = sizeof(*put) + sizeof(fm_xinstrument_t);
- put = kcalloc(1, size, GFP_KERNEL);
+ put = kzalloc(size, GFP_KERNEL);
if (put == NULL)
return -ENOMEM;
/* build header */
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 8261464dade8..380c2c704c54 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -204,7 +204,7 @@ int snd_opl4_create(snd_card_t *card,
if (ropl4)
*ropl4 = NULL;
- opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
+ opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL);
if (!opl4)
return -ENOMEM;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 986df35fb829..416172ea1f47 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -779,7 +779,7 @@ static int __init snd_uart16550_create(snd_card_t * card,
int err;
- if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
+ if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL)
return -ENOMEM;
uart->adaptor = adaptor;
uart->card = card;
@@ -928,15 +928,11 @@ static int __init snd_serial_probe(int dev)
base[dev],
adaptor[dev],
droponfull[dev],
- &uart)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &uart)) < 0)
+ goto _err;
- if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0)
+ goto _err;
sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
card->shortname,
@@ -949,12 +945,18 @@ static int __init snd_serial_probe(int dev)
adaptor_names[uart->adaptor],
uart->drop_on_full);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_serial_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_serial_init(void)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 5937711e9505..af12185ab8a2 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -116,6 +116,10 @@ static int __init snd_card_virmidi_probe(int dev)
strcpy(card->driver, "VirMIDI");
strcpy(card->shortname, "VirMIDI");
sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __nodev;
+
if ((err = snd_card_register(card)) == 0) {
snd_virmidi_cards[dev] = card;
return 0;
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index c6fa5afa3e9a..4697b1d75cbb 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -782,7 +782,7 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
snd_assert(card && hw && ops, return NULL);
- chip = kcalloc(1, sizeof(*chip) + extra_size, GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "vx_core: no memory\n");
return NULL;
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index f00c88886460..19fc68c23378 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -796,14 +796,14 @@ static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro
static snd_kcontrol_new_t vx_control_iec958_mask = {
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
.info = vx_iec958_info, /* shared */
.get = vx_iec958_mask_get,
};
static snd_kcontrol_new_t vx_control_iec958 = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.info = vx_iec958_info,
.get = vx_iec958_get,
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index af381b15fe5c..c2312d912fc7 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -473,7 +473,7 @@ static int vx_alloc_pipe(vx_core_t *chip, int capture,
return err;
/* initialize the pipe record */
- pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
+ pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
if (! pipe) {
/* release the pipe */
vx_init_rmh(&rmh, CMD_FREE_PIPE);
@@ -549,8 +549,8 @@ static int vx_stop_stream(vx_core_t *chip, vx_pipe_t *pipe)
static snd_pcm_hardware_t vx_pcm_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
+ /*SNDRV_PCM_INFO_RESUME*/),
.formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5000,
@@ -949,8 +949,8 @@ static snd_pcm_ops_t vx_pcm_playback_ops = {
static snd_pcm_hardware_t vx_pcm_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/
+ /*SNDRV_PCM_INFO_RESUME*/),
.formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5000,
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index a3fda859dd15..a21f7d541f86 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -200,7 +200,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
return err;
- chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
snd_i2c_device_free(device);
return -ENOMEM;
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index e8fa7e1a68e8..e4e505b9d88b 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -81,7 +81,7 @@ int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master
};
*ri2c = NULL;
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL)
return -ENOMEM;
init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char ad
*rdevice = NULL;
snd_assert(bus != NULL, return -EINVAL);
- device = kcalloc(1, sizeof(*device), GFP_KERNEL);
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL)
return -ENOMEM;
device->addr = addr;
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index e13122f3fc50..103a7dcd0dde 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -17,7 +17,7 @@
* 2002-05-12 Tomas Kasparek another code cleanup
*/
-/* $Id: uda1341.c,v 1.15 2005/01/03 12:05:20 tiwai Exp $ */
+/* $Id: uda1341.c,v 1.16 2005/09/09 13:22:34 tiwai Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
@@ -670,7 +670,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
snd_assert(card != NULL, return -EINVAL);
- uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
+ uda1341 = kzalloc(sizeof(*uda1341), GFP_KERNEL);
if (uda1341 == NULL)
return -ENOMEM;
@@ -707,7 +707,7 @@ static int uda1341_attach(struct l3_client *clnt)
{
struct uda1341 *uda;
- uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
+ uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);
if (!uda)
return -ENOMEM;
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 5adde308a00f..af5eadcddd92 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -92,7 +92,7 @@ int snd_ak4114_create(snd_card_t *card,
.dev_free = snd_ak4114_dev_free,
};
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->lock);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 0419c4336a55..d51b51dd86d6 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -83,7 +83,7 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *wri
.dev_free = snd_ak4117_dev_free,
};
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->lock);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 2da8d7f157f4..fd65da654267 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -281,7 +281,7 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
u8 default_treble, default_bass;
unsigned char bytes[7];
- tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
+ tea = kzalloc(sizeof(*tea), GFP_KERNEL);
if (tea == NULL)
return -ENOMEM;
if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index be4ea60a3679..5d6c300ac0d5 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -6,16 +6,17 @@ menu "ISA devices"
config SND_AD1848_LIB
tristate
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
config SND_CS4231_LIB
tristate
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
- depends on SND && ISAPNP
+ depends on SND && PNP && ISA
+ select ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
@@ -80,7 +81,8 @@ config SND_CS4236
config SND_ES968
tristate "Generic ESS ES968 driver"
- depends on SND && ISAPNP
+ depends on SND && PNP && ISA
+ select ISAPNP
select SND_MPU401_UART
select SND_PCM
help
@@ -95,6 +97,7 @@ config SND_ES1688
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for ESS AudioDrive ES688 or
ES1688 chips.
@@ -108,7 +111,7 @@ config SND_ES18XX
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for ESS AudioDrive ES18xx chips.
@@ -124,6 +127,7 @@ config SND_GUSCLASSIC
select SND_RAWMIDI
select SND_PCM
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound Classic
soundcards.
@@ -138,6 +142,7 @@ config SND_GUSEXTREME
select SND_MPU401_UART
select SND_PCM
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound Extreme
soundcards.
@@ -151,6 +156,7 @@ config SND_GUSMAX
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound MAX
soundcards.
@@ -160,11 +166,11 @@ config SND_GUSMAX
config SND_INTERWAVE
tristate "AMD InterWave, Gravis UltraSound PnP"
- depends on SND
+ depends on SND && PNP && ISA
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select ISAPNP
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -175,11 +181,11 @@ config SND_INTERWAVE
config SND_INTERWAVE_STB
tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
- depends on SND
+ depends on SND && PNP && ISA
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select ISAPNP
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
@@ -222,6 +228,7 @@ config SND_OPTI93X
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for soundcards based on Opti
82C93x chips.
@@ -235,6 +242,7 @@ config SND_SB8
select SND_OPL3_LIB
select SND_RAWMIDI
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Creative Sound Blaster 1.0/
2.0/Pro (8-bit) or 100% compatible soundcards.
@@ -248,6 +256,7 @@ config SND_SB16
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Sound Blaster 16 soundcards
(including the Plug and Play version).
@@ -261,6 +270,7 @@ config SND_SBAWE
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Sound Blaster AWE soundcards
(including the Plug and Play version).
@@ -291,7 +301,8 @@ config SND_WAVEFRONT
config SND_ALS100
tristate "Avance Logic ALS100/ALS120"
- depends on SND && ISAPNP
+ depends on SND && PNP && ISA
+ select ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
@@ -304,7 +315,8 @@ config SND_ALS100
config SND_AZT2320
tristate "Aztech Systems AZT2320"
- depends on SND && ISAPNP
+ depends on SND && PNP && ISA
+ select ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_CS4231_LIB
@@ -328,7 +340,8 @@ config SND_CMI8330
config SND_DT019X
tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
- depends on SND && ISAPNP
+ depends on SND && PNP && ISA
+ select ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 563296d02894..0eb442ca23d6 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -53,6 +53,7 @@ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
+static int clockfreq[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard.");
@@ -74,6 +75,8 @@ module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "1st DMA # for ad1816a driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "2nd DMA # for ad1816a driver.");
+module_param_array(clockfreq, int, NULL, 0444);
+MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0).");
struct snd_card_ad1816a {
struct pnp_dev *dev;
@@ -209,6 +212,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
snd_card_free(card);
return error;
}
+ if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000)
+ chip->clock_freq = clockfreq[dev];
strcpy(card->driver, "AD1816A");
strcpy(card->shortname, "ADI SoundPort AD1816A");
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 625b2eff14a1..27a9dcfbba00 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -234,7 +234,7 @@ static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
ad1816a_t *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
snd_pcm_runtime_t *runtime = substream->runtime;
- unsigned int size;
+ unsigned int size, rate;
spin_lock_irqsave(&chip->lock, flags);
@@ -245,7 +245,10 @@ static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
snd_dma_program(chip->dma1, runtime->dma_addr, size,
DMA_MODE_WRITE | DMA_AUTOINIT);
- snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, runtime->rate);
+ rate = runtime->rate;
+ if (chip->clock_freq)
+ rate = (rate * 33000) / chip->clock_freq;
+ snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, rate);
snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
snd_ad1816a_get_format(chip, runtime->format,
@@ -263,7 +266,7 @@ static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
ad1816a_t *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
snd_pcm_runtime_t *runtime = substream->runtime;
- unsigned int size;
+ unsigned int size, rate;
spin_lock_irqsave(&chip->lock, flags);
@@ -274,7 +277,10 @@ static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
snd_dma_program(chip->dma2, runtime->dma_addr, size,
DMA_MODE_READ | DMA_AUTOINIT);
- snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, runtime->rate);
+ rate = runtime->rate;
+ if (chip->clock_freq)
+ rate = (rate * 33000) / chip->clock_freq;
+ snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, rate);
snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
snd_ad1816a_get_format(chip, runtime->format,
@@ -585,7 +591,7 @@ int snd_ad1816a_create(snd_card_t *card,
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->irq = -1;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 8c399340cd72..3ebcc482b07a 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -91,35 +91,36 @@ static int __init snd_card_ad1848_probe(int dev)
irq[dev],
dma1[dev],
thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_ad1848_mixer(chip)) < 0)
+ goto _err;
- if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
strcpy(card->driver, "AD1848");
strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]);
- if (thinkpad[dev]) {
+ if (thinkpad[dev])
strcat(card->longname, " [Thinkpad]");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_ad1848_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_ad1848_init(void)
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 8fb3db103e48..303861cd03cd 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -890,7 +890,7 @@ int snd_ad1848_create(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
@@ -1196,6 +1196,7 @@ int snd_ad1848_add_ctl(ad1848_t *chip, const char *name, int index, int type, un
.put = snd_ad1848_put_double,
},
[AD1848_MIX_CAPTURE] = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ad1848_info_mux,
.get = snd_ad1848_get_mux,
.put = snd_ad1848_put_mux,
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 46776cc0c157..5252206ea388 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -194,8 +194,8 @@ AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4
AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1),
AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0),
AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1),
-AD1848_SINGLE("IEC958 Input Capture Switch", 0, CMI8330_RMUX3D, 7, 1, 1),
-AD1848_SINGLE("IEC958 Input Playback Switch", 0, CMI8330_MUTEMUX, 7, 1, 1),
+AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",CAPTURE,SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1),
+AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMUX, 7, 1, 1),
};
#ifdef ENABLE_SB_MIXER
@@ -438,33 +438,37 @@ static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
/*
*/
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
+#define PFX "cmi8330: "
+
static int __devinit snd_cmi8330_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
snd_card_t *card;
struct snd_cmi8330 *acard;
- unsigned long flags;
int i, err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify wssport\n");
+ snd_printk(KERN_ERR PFX "specify wssport\n");
return -EINVAL;
}
if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify sbport\n");
+ snd_printk(KERN_ERR PFX "specify sbport\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
+
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_cmi8330));
if (card == NULL) {
- snd_printk("could not get a new card\n");
+ snd_printk(KERN_ERR PFX "could not get a new card\n");
return -ENOMEM;
}
acard = (struct snd_cmi8330 *)card->private_data;
@@ -473,9 +477,8 @@ static int __devinit snd_cmi8330_probe(int dev,
#ifdef CONFIG_PNP
if (isapnp[dev]) {
if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) {
- snd_printk("PnP detection failed\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "PnP detection failed\n");
+ goto _err;
}
snd_card_set_dev(card, &pcard->card->dev);
}
@@ -487,14 +490,13 @@ static int __devinit snd_cmi8330_probe(int dev,
wssdma[dev],
AD1848_HW_DETECT,
&acard->wss)) < 0) {
- snd_printk("(AD1848) device busy??\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
+ goto _err;
}
if (acard->wss->hardware != AD1848_HW_CMI8330) {
- snd_printk("(AD1848) not found during probe\n");
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
+ err = -ENODEV;
+ goto _err;
}
if ((err = snd_sbdsp_create(card, sbport[dev],
@@ -503,32 +505,26 @@ static int __devinit snd_cmi8330_probe(int dev,
sbdma8[dev],
sbdma16[dev],
SB_HW_AUTO, &acard->sb)) < 0) {
- snd_printk("(SB16) device busy??\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
+ goto _err;
}
if (acard->sb->hardware != SB_HW_16) {
- snd_printk("(SB16) not found during probe\n");
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
+ goto _err;
}
- spin_lock_irqsave(&acard->wss->reg_lock, flags);
snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
- spin_unlock_irqrestore(&acard->wss->reg_lock, flags);
if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
- snd_printk("failed to create mixers\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "failed to create mixers\n");
+ goto _err;
}
if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
- snd_printk("failed to create pcms\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "failed to create pcms\n");
+ goto _err;
}
strcpy(card->driver, "CMI8330/C3D");
@@ -539,16 +535,21 @@ static int __devinit snd_cmi8330_probe(int dev,
wssirq[dev],
wssdma[dev]);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_cmi8330_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
#ifdef CONFIG_PNP
@@ -594,10 +595,8 @@ static int __init alsa_card_cmi8330_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev])
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_cmi8330_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 7640837659ea..9be5416bcb92 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -76,15 +76,15 @@ static int __init snd_card_cs4231_probe(int dev)
int err;
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR "specify port\n");
return -EINVAL;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
- snd_printk("specify irq\n");
+ snd_printk(KERN_ERR "specify irq\n");
return -EINVAL;
}
if (dma1[dev] == SNDRV_AUTO_DMA) {
- snd_printk("specify dma1\n");
+ snd_printk(KERN_ERR "specify dma1\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -96,15 +96,11 @@ static int __init snd_card_cs4231_probe(int dev)
dma1[dev],
dma2[dev],
CS4231_HW_DETECT,
- 0, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &chip)) < 0)
+ goto _err;
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
strcpy(card->driver, "CS4231");
strcpy(card->shortname, pcm->name);
@@ -113,14 +109,10 @@ static int __init snd_card_cs4231_probe(int dev)
if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
- if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_mixer(chip)) < 0)
+ goto _err;
+ if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+ goto _err;
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -130,14 +122,20 @@ static int __init snd_card_cs4231_probe(int dev)
mpu_irq[dev],
mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
NULL) < 0)
- printk(KERN_ERR "cs4231: MPU401 not detected\n");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ printk(KERN_WARNING "cs4231: MPU401 not detected\n");
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
snd_cs4231_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_cs4231_init(void)
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 3e7a2a33a5ca..32318258cd8e 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -1346,6 +1346,8 @@ static void snd_cs4231_suspend(cs4231_t *chip)
int reg;
unsigned long flags;
+ if (chip->pcm)
+ snd_pcm_suspend_all(chip->pcm);
spin_lock_irqsave(&chip->reg_lock, flags);
for (reg = 0; reg < 32; reg++)
chip->image[reg] = snd_cs4231_in(chip, reg);
@@ -1478,7 +1480,7 @@ static int snd_cs4231_new(snd_card_t * card,
cs4231_t *chip;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->hardware = hardware;
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 39f4eff44f5c..d28315dc72f7 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -387,6 +387,12 @@ static void snd_card_cs4236_free(snd_card_t *card)
}
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -397,20 +403,16 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
opl3_t *opl3;
int err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR "specify port\n");
return -EINVAL;
}
if (cport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify cport\n");
+ snd_printk(KERN_ERR "specify cport\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_cs4236));
if (card == NULL)
@@ -421,8 +423,7 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (isapnp[dev]) {
if ((err = snd_card_cs4236_pnp(dev, acard, pcard, pid))<0) {
printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n");
- snd_card_free(card);
- return -ENXIO;
+ goto _err;
}
snd_card_set_dev(card, &pcard->card->dev);
}
@@ -430,8 +431,8 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT)
if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) {
printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
- snd_card_free(card);
- return -ENOMEM;
+ err = -EBUSY;
+ goto _err;
}
#ifdef CS4232
@@ -443,18 +444,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
dma2[dev],
CS4231_HW_DETECT,
0,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(chip)) < 0)
+ goto _err;
#else /* CS4236 */
if ((err = snd_cs4236_create(card,
@@ -465,18 +462,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
dma2[dev],
CS4231_HW_DETECT,
0,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4236_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4236_mixer(chip)) < 0)
+ goto _err;
#endif
strcpy(card->driver, pcm->name);
strcpy(card->shortname, pcm->name);
@@ -488,21 +481,17 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
- if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+ goto _err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card,
fm_port[dev], fm_port[dev] + 2,
OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
- printk(KERN_ERR IDENT ": OPL3 not detected\n");
+ printk(KERN_WARNING IDENT ": OPL3 not detected\n");
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
}
@@ -513,17 +502,23 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
mpu_port[dev], 0,
mpu_irq[dev],
mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0)
- printk(KERN_ERR IDENT ": MPU401 not detected\n");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ printk(KERN_WARNING IDENT ": MPU401 not detected\n");
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_cs4236_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
#ifdef CONFIG_PNP
@@ -569,10 +564,8 @@ static int __init alsa_card_cs423x_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev])
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_card_cs423x_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index c5eaec087b46..26a7d335ed8e 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -70,6 +70,7 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "es1688: "
static int __init snd_audiodrive_probe(int dev)
{
@@ -89,47 +90,41 @@ static int __init snd_audiodrive_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xmpu_irq = mpu_irq[dev];
xdma = dma8[dev];
if (xdma == SNDRV_AUTO_DMA) {
if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto _err;
}
}
if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
xirq, xmpu_irq, xdma,
- ES1688_HW_AUTO, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es1688_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ ES1688_HW_AUTO, &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_es1688_mixer(chip)) < 0)
+ goto _err;
strcpy(card->driver, "ES1688");
strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma);
if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
- printk(KERN_ERR "es1688: opl3 not detected at 0x%lx\n", chip->port);
+ printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port);
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) {
@@ -137,18 +132,22 @@ static int __init snd_audiodrive_probe(int dev)
chip->mpu_port, 0,
xmpu_irq,
SA_INTERRUPT,
- NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ NULL)) < 0)
+ goto _err;
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_audiodrive_cards[dev] = card;
return 0;
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 17f68d07d9b2..aac898765c02 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -649,7 +649,7 @@ int snd_es1688_create(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->irq = -1;
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1d832b2adb7c..d0ea19f42703 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1686,7 +1686,7 @@ static int __devinit snd_es18xx_new_device(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
@@ -1988,6 +1988,12 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
}
#endif /* CONFIG_PNP */
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -1996,7 +2002,6 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
int xirq, xdma1, xdma2;
snd_card_t *card;
struct snd_audiodrive *acard;
- snd_rawmidi_t *rmidi = NULL;
es18xx_t *chip;
opl3_t *opl3;
int err;
@@ -2019,25 +2024,25 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -2046,10 +2051,8 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
mpu_port[dev],
fm_port[dev],
xirq, xdma1, xdma2,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
sprintf(card->driver, "ES%x", chip->version);
sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
@@ -2064,23 +2067,18 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
chip->port,
xirq, xdma1);
- if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es18xx_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_es18xx_mixer(chip)) < 0)
+ goto _err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
- snd_printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
+ snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
}
@@ -2088,25 +2086,28 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
chip->mpu_port, 0,
xirq, 0,
- &rmidi)) < 0) {
- snd_card_free(card);
- return err;
- }
- chip->rmidi = rmidi;
+ &chip->rmidi)) < 0)
+ goto _err;
}
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
/* Power Management */
snd_card_set_isa_pm_callback(card, snd_es18xx_suspend, snd_es18xx_resume, chip);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_audiodrive_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
@@ -2117,10 +2118,8 @@ static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
port[dev] = xport;
res = snd_audiodrive_probe(dev, NULL, NULL);
if (res < 0)
@@ -2177,10 +2176,8 @@ static int __init alsa_card_es18xx_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_audiodrive_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index 337b0e2a8a36..23e1b5f19e1a 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -269,8 +269,9 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
#endif /* 0 */
-unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
- unsigned char reg, short w_16bit)
+#ifdef CONFIG_SND_DEBUG
+static unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
+ unsigned char reg, short w_16bit)
{
unsigned int res;
unsigned long flags;
@@ -280,6 +281,7 @@ unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
spin_unlock_irqrestore(&gus->reg_lock, flags);
return res;
}
+#endif
/*
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index a636d9ce3502..8f2872f8e8f6 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -157,7 +157,7 @@ int snd_gus_create(snd_card_t * card,
};
*rgus = NULL;
- gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
+ gus = kzalloc(sizeof(*gus), GFP_KERNEL);
if (gus == NULL)
return -ENOMEM;
gus->gf1.irq = -1;
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 886763f12132..7f96ac237f3c 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -98,7 +98,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
for (idx = 0; idx < 4; idx++) {
if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
priv->gus = gus;
@@ -115,7 +115,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
}
for (idx = 0; idx < 4; idx++) {
if (gus->gf1.rom_present & (1 << idx)) {
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
priv->rom = 1;
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index b75066ab46fc..beb01365dc46 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -666,7 +666,7 @@ static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
+ pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL);
if (pcmp == NULL)
return -ENOMEM;
pcmp->gus = gus;
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index a99fa5040b46..39cef38835ca 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -72,40 +72,24 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusclassic: "
static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
{
- snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
+ unsigned char d;
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
-
+ }
return 0;
}
@@ -137,25 +121,25 @@ static int __init snd_gusclassic_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -164,47 +148,48 @@ static int __init snd_gusclassic_probe(int dev)
port[dev],
xirq, xdma1, xdma2,
0, channels[dev], pcm_channels[dev],
- 0, &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gusclassic_detect(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gusclassic_detect(gus)) < 0)
+ goto _err;
+
snd_gusclassic_init(dev, gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
+
if (gus->max_flag || gus->ess_flag) {
- snd_printdd("GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
- snd_card_free(card);
- return -ENODEV;
- }
- if ((err = snd_gf1_new_mixer(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ err = -ENODEV;
+ goto _err;
}
+
+ if ((err = snd_gf1_new_mixer(gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0)
+ goto _err;
+
if (!gus->ace_flag) {
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
}
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
if (dma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_gusclassic_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index bc6fecb18dcf..d2e7cb1df537 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -87,6 +87,7 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusextreme: "
static int __init snd_gusextreme_detect(int dev,
snd_card_t * card,
@@ -94,6 +95,7 @@ static int __init snd_gusextreme_detect(int dev,
es1688_t *es1688)
{
unsigned long flags;
+ unsigned char d;
/*
* This is main stuff - enable access to GF1 chip...
@@ -123,36 +125,17 @@ static int __init snd_gusextreme_detect(int dev,
udelay(100);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -EIO;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -EIO;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -EIO;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -EIO;
-#endif
-
+ }
return 0;
}
@@ -205,7 +188,7 @@ static int __init snd_gusextreme_probe(int dev)
xgf1_irq = gf1_irq[dev];
if (xgf1_irq == SNDRV_AUTO_IRQ) {
if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
- snd_printk("unable to find a free IRQ for GF1\n");
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n");
err = -EBUSY;
goto out;
}
@@ -213,7 +196,7 @@ static int __init snd_gusextreme_probe(int dev)
xess_irq = irq[dev];
if (xess_irq == SNDRV_AUTO_IRQ) {
if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
- snd_printk("unable to find a free IRQ for ES1688\n");
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n");
err = -EBUSY;
goto out;
}
@@ -226,7 +209,7 @@ static int __init snd_gusextreme_probe(int dev)
xgf1_dma = dma1[dev];
if (xgf1_dma == SNDRV_AUTO_DMA) {
if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
- snd_printk("unable to find a free DMA for GF1\n");
+ snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n");
err = -EBUSY;
goto out;
}
@@ -234,7 +217,7 @@ static int __init snd_gusextreme_probe(int dev)
xess_dma = dma8[dev];
if (xess_dma == SNDRV_AUTO_DMA) {
if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
- snd_printk("unable to find a free DMA for ES1688\n");
+ snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n");
err = -EBUSY;
goto out;
}
@@ -264,7 +247,7 @@ static int __init snd_gusextreme_probe(int dev)
goto out;
if (!gus->ess_flag) {
- snd_printdd("GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
err = -ENODEV;
goto out;
}
@@ -287,7 +270,7 @@ static int __init snd_gusextreme_probe(int dev)
if (snd_opl3_create(card, es1688->port, es1688->port + 2,
OPL3_HW_OPL3, 0, &opl3) < 0) {
- printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
+ printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0)
goto out;
@@ -303,6 +286,10 @@ static int __init snd_gusextreme_probe(int dev)
sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i",
es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out;
+
if ((err = snd_card_register(card)) < 0)
goto out;
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 400ff34710fb..0bb44b519340 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -82,39 +82,25 @@ struct snd_gusmax {
static snd_card_t *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusmax: "
static int __init snd_gusmax_detect(snd_gus_card_t * gus)
{
- snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
+ unsigned char d;
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
+
return 0;
}
@@ -239,25 +225,25 @@ static int __init snd_gusmax_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -266,31 +252,28 @@ static int __init snd_gusmax_probe(int dev)
-xirq, xdma1, xdma2,
0, channels[dev],
pcm_channels[dev],
- 0, &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gusmax_detect(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gusmax_detect(gus)) < 0)
+ goto _err;
+
maxcard->gus_status_reg = gus->gf1.reg_irqstat;
maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
snd_gusmax_init(dev, card, gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
+
if (!gus->max_flag) {
- printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ err = -ENODEV;
+ goto _err;
}
if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) {
- snd_card_free(card);
- printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", xirq);
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+ err = -EBUSY;
+ goto _err;
}
maxcard->irq = xirq;
@@ -301,50 +284,46 @@ static int __init snd_gusmax_probe(int dev)
CS4231_HWSHARE_IRQ |
CS4231_HWSHARE_DMA1 |
CS4231_HWSHARE_DMA2,
- &cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ goto _err;
+
if (pcm_channels[dev] > 0) {
- if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_gusmax_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
+ if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+ goto _err;
}
+ if ((err = snd_gusmax_mixer(cs4231)) < 0)
+ goto _err;
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
maxcard->gus = gus;
maxcard->cs4231 = cs4231;
snd_gusmax_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_gusmax_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 46e867daba6a..358cba9d738f 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -73,6 +73,12 @@ static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+#ifdef SNDRV_STB
+#define PFX "interwave-stb: "
+#else
+#define PFX "interwave: "
+#endif
+
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
module_param_array(id, charp, NULL, 0444);
@@ -249,38 +255,20 @@ static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
{
unsigned long flags;
unsigned char rev1, rev2;
+ int d;
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- int d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- int d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
-
+ }
spin_lock_irqsave(&gus->reg_lock, flags);
rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1);
@@ -686,35 +674,33 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
card->private_free = snd_interwave_free;
#ifdef CONFIG_PNP
if (isapnp[dev]) {
- if (snd_interwave_pnp(dev, iwcard, pcard, pid)) {
- snd_card_free(card);
- return -ENODEV;
- }
+ if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0)
+ goto _err;
snd_card_set_dev(card, &pcard->card->dev);
}
#endif
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -722,32 +708,28 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
port[dev],
-xirq, xdma1, xdma2,
0, 32,
- pcm_channels[dev], effect[dev], &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ pcm_channels[dev], effect[dev], &gus)) < 0)
+ goto _err;
+
if ((err = snd_interwave_detect(iwcard, gus, dev
#ifdef SNDRV_STB
, &i2c_bus
#endif
- )) < 0) {
- snd_card_free(card);
- return err;
- }
+ )) < 0)
+ goto _err;
+
iwcard->gus_status_reg = gus->gf1.reg_irqstat;
iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
snd_interwave_init(dev, gus);
snd_interwave_detect_memory(gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
- snd_card_free(card);
- snd_printk("unable to grab IRQ %d\n", xirq);
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+ err = -EBUSY;
+ goto _err;
}
iwcard->irq = xirq;
@@ -758,34 +740,28 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
CS4231_HWSHARE_IRQ |
CS4231_HWSHARE_DMA1 |
CS4231_HWSHARE_DMA2,
- &cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)
+ goto _err;
+
sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
strcat(pcm->name, " (codec)");
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ goto _err;
+
if (pcm_channels[dev] > 0) {
- if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_interwave_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
+ if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+ goto _err;
}
+ if ((err = snd_interwave_mixer(cs4231)) < 0)
+ goto _err;
+
#ifdef SNDRV_STB
{
snd_ctl_elem_id_t id1, id2;
@@ -795,28 +771,20 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
strcpy(id1.name, "Master Playback Switch");
strcpy(id2.name, id1.name);
id2.index = 1;
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ goto _err;
strcpy(id1.name, "Master Playback Volume");
strcpy(id2.name, id1.name);
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ goto _err;
+ if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0)
+ goto _err;
}
#endif
gus->uart_enable = midi[dev];
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
#ifndef SNDRV_STB
str = "AMD InterWave";
@@ -835,10 +803,11 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
iwcard->cs4231 = cs4231;
iwcard->gus = gus;
@@ -847,6 +816,10 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
else
snd_interwave_legacy[dev++] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_interwave_probe_legacy_port(unsigned long xport)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 95c7b3e53407..e2d2babcd20b 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -143,8 +143,18 @@ struct snd_opl3sa2 {
static snd_card_t *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "opl3sa2: "
+
#ifdef CONFIG_PNP
+static struct pnp_device_id snd_opl3sa2_pnpbiosids[] = {
+ { .id = "YMH0021" },
+ { .id = "NMX2210" }, /* Gateway Solo 2500 */
+ { .id = "" } /* end */
+};
+
+MODULE_DEVICE_TABLE(pnp, snd_opl3sa2_pnpbiosids);
+
static struct pnp_card_device_id snd_opl3sa2_pnpids[] = {
/* Yamaha YMF719E-S (Genius Sound Maker 3DX) */
{ .id = "YMH0020", .devs = { { "YMH0021" } } },
@@ -223,7 +233,7 @@ static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
card = chip->card;
port = chip->port;
if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
- snd_printk(KERN_ERR "opl3sa2: can't grab port 0x%lx\n", port);
+ snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
return -EBUSY;
}
// snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a));
@@ -568,20 +578,18 @@ static int snd_opl3sa2_resume(snd_card_t *card)
#ifdef CONFIG_PNP
static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+ struct pnp_dev *pdev,
+ int isapnp)
{
- struct pnp_dev *pdev;
- struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
+ struct pnp_resource_table * cfg;
int err;
+ if (!isapnp && pnp_device_is_isapnp(pdev))
+ return -ENOENT; /* we have another procedure - card */
+
+ cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
- pdev = chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
- if (chip->dev == NULL) {
- kfree(cfg);
- return -EBUSY;
- }
/* PnP initialization */
pnp_init_resource_table(cfg);
if (sb_port[dev] != SNDRV_AUTO_PORT)
@@ -601,7 +609,7 @@ static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
if (irq[dev] != SNDRV_AUTO_IRQ)
pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
err = pnp_manual_config_dev(pdev, cfg, 0);
- if (err < 0)
+ if (err < 0 && isapnp)
snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
@@ -617,13 +625,31 @@ static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
dma1[dev] = pnp_dma(pdev, 0);
dma2[dev] = pnp_dma(pdev, 1);
irq[dev] = pnp_irq(pdev, 0);
- snd_printdd("PnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n",
- sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]);
- snd_printdd("PnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n",
- port[dev], dma1[dev], dma2[dev], irq[dev]);
+ snd_printdd("%sPnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n",
+ pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]);
+ snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n",
+ pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]);
kfree(cfg);
+ chip->dev = pdev;
return 0;
}
+
+static int __init snd_opl3sa2_cpnp(int dev, opl3sa2_t *chip,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
+{
+ struct pnp_dev *pdev;
+ struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
+
+ if (!cfg)
+ return -ENOMEM;
+ pdev = pnp_request_card_device(card, id->devs[0].id, NULL);
+ if (pdev == NULL) {
+ kfree(cfg);
+ return -EBUSY;
+ }
+ return snd_opl3sa2_pnp(dev, chip, pdev, 1);
+}
#endif /* CONFIG_PNP */
static int snd_opl3sa2_free(opl3sa2_t *chip)
@@ -644,7 +670,14 @@ static int snd_opl3sa2_dev_free(snd_device_t *device)
return snd_opl3sa2_free(chip);
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_opl3sa2_probe(int dev,
+ struct pnp_dev *pdev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -658,34 +691,31 @@ static int __devinit snd_opl3sa2_probe(int dev,
};
int err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR PFX "specify port\n");
return -EINVAL;
}
if (wss_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify wss_port\n");
+ snd_printk(KERN_ERR PFX "specify wss_port\n");
return -EINVAL;
}
if (fm_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify fm_port\n");
+ snd_printk(KERN_ERR PFX "specify fm_port\n");
return -EINVAL;
}
if (midi_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify midi_port\n");
+ snd_printk(KERN_ERR PFX "specify midi_port\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
+
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
strcpy(card->driver, "OPL3SA2");
strcpy(card->shortname, "Yamaha OPL3-SA2");
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
err = -ENOMEM;
goto __error;
@@ -695,8 +725,13 @@ static int __devinit snd_opl3sa2_probe(int dev,
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
goto __error;
#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if ((err = snd_opl3sa2_pnp(dev, chip, pcard, pid)) < 0)
+ if (pdev) {
+ if ((err = snd_opl3sa2_pnp(dev, chip, pdev, 0)) < 0)
+ goto __error;
+ snd_card_set_dev(card, &pdev->dev);
+ }
+ if (pcard) {
+ if ((err = snd_opl3sa2_cpnp(dev, chip, pcard, pid)) < 0)
goto __error;
snd_card_set_dev(card, &pcard->card->dev);
}
@@ -712,7 +747,7 @@ static int __devinit snd_opl3sa2_probe(int dev,
if ((err = snd_opl3sa2_detect(chip)) < 0)
goto __error;
if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) {
- snd_printk(KERN_ERR "opl3sa2: can't grab IRQ %d\n", xirq);
+ snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
err = -ENODEV;
goto __error;
}
@@ -765,10 +800,15 @@ static int __devinit snd_opl3sa2_probe(int dev,
if (dma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __error;
+
if ((err = snd_card_register(card)) < 0)
goto __error;
- if (pcard)
+ if (pdev)
+ pnp_set_drvdata(pdev, card);
+ else if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_opl3sa2_legacy[dev] = card;
@@ -780,8 +820,8 @@ static int __devinit snd_opl3sa2_probe(int dev,
}
#ifdef CONFIG_PNP
-static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
+ const struct pnp_device_id *id)
{
static int dev;
int res;
@@ -789,7 +829,42 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card,
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || !isapnp[dev])
continue;
- res = snd_opl3sa2_probe(dev, card, id);
+ res = snd_opl3sa2_probe(dev, pdev, NULL, NULL);
+ if (res < 0)
+ return res;
+ dev++;
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev)
+{
+ snd_card_t *card = (snd_card_t *) pnp_get_drvdata(pdev);
+
+ snd_card_disconnect(card);
+ snd_card_free_in_thread(card);
+}
+
+static struct pnp_driver opl3sa2_pnp_driver = {
+ .name = "opl3sa2-pnpbios",
+ .id_table = snd_opl3sa2_pnpbiosids,
+ .probe = snd_opl3sa2_pnp_detect,
+ .remove = __devexit_p(snd_opl3sa2_pnp_remove),
+};
+
+static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
+{
+ static int dev;
+ int res;
+
+ for ( ; dev < SNDRV_CARDS; dev++) {
+ if (!enable[dev])
+ continue;
+ if (is_isapnp_selected(dev))
+ continue;
+ res = snd_opl3sa2_probe(dev, NULL, card, id);
if (res < 0)
return res;
dev++;
@@ -798,7 +873,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void __devexit snd_opl3sa2_pnp_remove(struct pnp_card_link * pcard)
+static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard)
{
snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
@@ -810,8 +885,8 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "opl3sa2",
.id_table = snd_opl3sa2_pnpids,
- .probe = snd_opl3sa2_pnp_detect,
- .remove = __devexit_p(snd_opl3sa2_pnp_remove),
+ .probe = snd_opl3sa2_pnp_cdetect,
+ .remove = __devexit_p(snd_opl3sa2_pnp_cremove),
};
#endif /* CONFIG_PNP */
@@ -826,10 +901,11 @@ static int __init alsa_card_opl3sa2_init(void)
if (isapnp[dev])
continue;
#endif
- if (snd_opl3sa2_probe(dev, NULL, NULL) >= 0)
+ if (snd_opl3sa2_probe(dev, NULL, NULL, NULL) >= 0)
cards++;
}
#ifdef CONFIG_PNP
+ cards += pnp_register_driver(&opl3sa2_pnp_driver);
cards += pnp_register_card_driver(&opl3sa2_pnpc_driver);
#endif
if (!cards) {
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 411a702d85ba..73573cb1db6a 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1038,8 +1038,7 @@ static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream)
chip->c_dma_size = size;
snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
- OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO,
- (unsigned char)~(OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO));
+ OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);
snd_dma_program(chip->dma2, runtime->dma_addr, size,
DMA_MODE_READ | DMA_AUTOINIT);
@@ -1274,7 +1273,7 @@ static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
opti93x_t *codec;
*rcodec = NULL;
- codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+ codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
codec->irq = -1;
@@ -1895,8 +1894,8 @@ static void snd_card_opti9xx_free(snd_card_t *card)
}
}
-static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
@@ -1966,6 +1965,10 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
+ if ((error = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
#ifdef CONFIG_PNP
}
#endif /* CONFIG_PNP */
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 028af4066595..5375705c054b 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1097,7 +1097,7 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
if (seq_ports <= 0)
return 0;
- hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (hw == NULL)
return -ENOMEM;
spin_lock_init(&hw->reg_lock);
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index db5eb8b55058..0209790dc4b5 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -233,7 +233,7 @@ static int emu8k_pcm_open(snd_pcm_substream_t *subs)
emu8k_pcm_t *rec;
snd_pcm_runtime_t *runtime = subs->runtime;
- rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (! rec)
return -ENOMEM;
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 60e2c53c49fc..7888783d68f5 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -351,6 +351,12 @@ static void snd_sb16_free(snd_card_t *card)
}
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __init snd_sb16_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -378,10 +384,8 @@ static int __init snd_sb16_probe(int dev,
card->private_free = snd_sb16_free;
#ifdef CONFIG_PNP
if (isapnp[dev]) {
- if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid)))
+ goto _err;
snd_card_set_dev(card, &pcard->card->dev);
}
#endif
@@ -389,41 +393,37 @@ static int __init snd_sb16_probe(int dev,
xirq = irq[dev];
xdma8 = dma8[dev];
xdma16 = dma16[dev];
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
- if (xirq == SNDRV_AUTO_IRQ) {
- if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
- return -EBUSY;
+ if (! is_isapnp_selected(dev)) {
+ if (xirq == SNDRV_AUTO_IRQ) {
+ if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- if (xdma8 == SNDRV_AUTO_DMA) {
- if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
- return -EBUSY;
+ if (xdma8 == SNDRV_AUTO_DMA) {
+ if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- if (xdma16 == SNDRV_AUTO_DMA) {
- if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
- return -EBUSY;
+ if (xdma16 == SNDRV_AUTO_DMA) {
+ if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- /* non-PnP FM port address is hardwired with base port address */
- fm_port[dev] = port[dev];
- /* block the 0x388 port to avoid PnP conflicts */
- acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+ /* non-PnP FM port address is hardwired with base port address */
+ fm_port[dev] = port[dev];
+ /* block the 0x388 port to avoid PnP conflicts */
+ acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
#ifdef SNDRV_SBAWE_EMU8000
- /* non-PnP AWE port address is hardwired with base port address */
- awe_port[dev] = port[dev] + 0x400;
+ /* non-PnP AWE port address is hardwired with base port address */
+ awe_port[dev] = port[dev] + 0x400;
#endif
-#ifdef CONFIG_PNP
}
-#endif
if ((err = snd_sbdsp_create(card,
port[dev],
@@ -432,28 +432,20 @@ static int __init snd_sb16_probe(int dev,
xdma8,
xdma16,
SB_HW_AUTO,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
if (chip->hardware != SB_HW_16) {
- snd_card_free(card);
- snd_printdd("SB 16 chip was not detected at 0x%lx\n", port[dev]);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]);
+ err = -ENODEV;
+ goto _err;
}
chip->mpu_port = mpu_port[dev];
-#ifdef CONFIG_PNP
- if (!isapnp[dev] && (err = snd_sb16dsp_configure(chip)) < 0) {
-#else
- if ((err = snd_sb16dsp_configure(chip)) < 0) {
-#endif
- snd_card_free(card);
- return -ENXIO;
- }
- if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
+ goto _err;
+
+ if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0)
+ goto _err;
strcpy(card->driver,
#ifdef SNDRV_SBAWE_EMU8000
@@ -474,10 +466,8 @@ static int __init snd_sb16_probe(int dev,
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
chip->mpu_port, 0,
- xirq, 0, &chip->rmidi)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ xirq, 0, &chip->rmidi)) < 0)
+ goto _err;
chip->rmidi_callback = snd_mpu401_uart_interrupt;
}
@@ -499,17 +489,13 @@ static int __init snd_sb16_probe(int dev,
#else
int seqdev = 1;
#endif
- if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0)
+ goto _err;
}
}
- if ((err = snd_sbmixer_new(chip)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if ((err = snd_sbmixer_new(chip)) < 0)
+ goto _err;
#ifdef CONFIG_SND_SB16_CSP
/* CSP chip on SB16ASP/AWE32 */
@@ -525,11 +511,11 @@ static int __init snd_sb16_probe(int dev,
#endif
#ifdef SNDRV_SBAWE_EMU8000
if (awe_port[dev] > 0) {
- if (snd_emu8000_new(card, 1, awe_port[dev],
- seq_ports[dev], NULL) < 0) {
+ if ((err = snd_emu8000_new(card, 1, awe_port[dev],
+ seq_ports[dev], NULL)) < 0) {
snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]);
- snd_card_free(card);
- return -ENXIO;
+
+ goto _err;
}
}
#endif
@@ -541,15 +527,21 @@ static int __init snd_sb16_probe(int dev,
(mic_agc[dev] ? 0x00 : 0x01));
spin_unlock_irqrestore(&chip->mixer_lock, flags);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_sb16_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_sb16_probe_legacy_port(unsigned long xport)
@@ -560,10 +552,8 @@ static int __init snd_sb16_probe_legacy_port(unsigned long xport)
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
port[dev] = xport;
res = snd_sb16_probe(dev, NULL, NULL);
if (res < 0)
@@ -621,10 +611,8 @@ static int __init alsa_card_sb16_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (!snd_sb16_probe(dev, NULL, NULL)) {
cards++;
continue;
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index b62920eead3d..7192d4c758e6 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -42,8 +42,6 @@ MODULE_LICENSE("GPL");
#else
#define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
#endif
-#define LE_SHORT(v) le16_to_cpu(v)
-#define LE_INT(v) le32_to_cpu(v)
#define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F')
#define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ')
@@ -56,20 +54,20 @@ MODULE_LICENSE("GPL");
/*
* RIFF data format
*/
-typedef struct riff_header {
+struct riff_header {
__u32 name;
__u32 len;
-} riff_header_t;
+};
-typedef struct desc_header {
- riff_header_t info;
+struct desc_header {
+ struct riff_header info;
__u16 func_nr;
__u16 VOC_type;
__u16 flags_play_rec;
__u16 flags_16bit_8bit;
__u16 flags_stereo_mono;
__u16 flags_rates;
-} desc_header_t;
+};
/*
* prototypes
@@ -124,7 +122,7 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
return err;
- if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+ if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
snd_device_free(chip->card, hw);
return -ENOMEM;
}
@@ -302,9 +300,9 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
unsigned char __user *data_end;
unsigned short func_nr = 0;
- riff_header_t file_h, item_h, code_h;
+ struct riff_header file_h, item_h, code_h;
__u32 item_type;
- desc_header_t funcdesc_h;
+ struct desc_header funcdesc_h;
unsigned long flags;
int err;
@@ -316,12 +314,12 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
if (copy_from_user(&file_h, data_ptr, sizeof(file_h)))
return -EFAULT;
if ((file_h.name != RIFF_HEADER) ||
- (LE_INT(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
+ (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
return -EINVAL;
}
data_ptr += sizeof(file_h);
- data_end = data_ptr + LE_INT(file_h.len);
+ data_end = data_ptr + le32_to_cpu(file_h.len);
if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
return -EFAULT;
@@ -331,7 +329,7 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
}
data_ptr += sizeof (item_type);
- for (; data_ptr < data_end; data_ptr += LE_INT(item_h.len)) {
+ for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) {
if (copy_from_user(&item_h, data_ptr, sizeof(item_h)))
return -EFAULT;
data_ptr += sizeof(item_h);
@@ -344,7 +342,7 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
case FUNC_HEADER:
if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h)))
return -EFAULT;
- func_nr = LE_SHORT(funcdesc_h.func_nr);
+ func_nr = le16_to_cpu(funcdesc_h.func_nr);
break;
case CODE_HEADER:
if (func_nr != info.func_req)
@@ -370,11 +368,11 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
if (code_h.name != INIT_HEADER)
break;
data_ptr += sizeof(code_h);
- err = snd_sb_csp_load_user(p, data_ptr, LE_INT(code_h.len),
+ err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len),
SNDRV_SB_CSP_LOAD_INITBLOCK);
if (err)
return err;
- data_ptr += LE_INT(code_h.len);
+ data_ptr += le32_to_cpu(code_h.len);
}
/* main microcode block */
if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
@@ -386,17 +384,17 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
}
data_ptr += sizeof(code_h);
err = snd_sb_csp_load_user(p, data_ptr,
- LE_INT(code_h.len), 0);
+ le32_to_cpu(code_h.len), 0);
if (err)
return err;
/* fill in codec header */
strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
p->func_nr = func_nr;
- p->mode = LE_SHORT(funcdesc_h.flags_play_rec);
- switch (LE_SHORT(funcdesc_h.VOC_type)) {
+ p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
+ switch (le16_to_cpu(funcdesc_h.VOC_type)) {
case 0x0001: /* QSound decoder */
- if (LE_SHORT(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
+ if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
if (snd_sb_qsound_build(p) == 0)
/* set QSound flag and clear all other mode flags */
p->mode = SNDRV_SB_CSP_MODE_QSOUND;
@@ -426,12 +424,12 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
p->mode = 0;
snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
__FUNCTION__,
- LE_SHORT(funcdesc_h.VOC_type));
+ le16_to_cpu(funcdesc_h.VOC_type));
return -EINVAL;
}
- p->acc_channels = LE_SHORT(funcdesc_h.flags_stereo_mono);
- p->acc_width = LE_SHORT(funcdesc_h.flags_16bit_8bit);
- p->acc_rates = LE_SHORT(funcdesc_h.flags_rates);
+ p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono);
+ p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit);
+ p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates);
/* Decouple CSP from IRQ and DMAREQ lines */
spin_lock_irqsave(&p->chip->reg_lock, flags);
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index a6a0fa516268..a99e642a68b5 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -729,7 +729,7 @@ static int snd_sb16_dma_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
}
static snd_kcontrol_new_t snd_sb16_dma_control = {
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "16-bit DMA Allocation",
.info = snd_sb16_dma_control_info,
.get = snd_sb16_dma_control_get,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index e2cbc4202b3d..c41ac25e85ca 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -107,54 +107,47 @@ static int __init snd_sb8_probe(int dev)
dma8[dev],
-1,
SB_HW_AUTO,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
if (chip->hardware >= SB_HW_16) {
- snd_card_free(card);
if (chip->hardware == SB_HW_ALS100)
- snd_printdd("ALS100 chip detected at 0x%lx, try snd-als100 module\n",
+ snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n",
port[dev]);
else
- snd_printdd("SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
- port[dev]);
- return -ENODEV;
+ snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
+ port[dev]);
+ err = -ENODEV;
+ goto _err;
}
- if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_sbmixer_new(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_sbmixer_new(chip)) < 0)
+ goto _err;
+
if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
if ((err = snd_opl3_create(card, chip->port + 8, 0,
OPL3_HW_AUTO, 1,
&opl3)) < 0) {
- snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8);
+ snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8);
}
} else {
if ((err = snd_opl3_create(card, chip->port, chip->port + 2,
OPL3_HW_AUTO, 1,
&opl3)) < 0) {
- snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n",
+ snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n",
chip->port, chip->port + 2);
}
}
if (err >= 0) {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
- if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0)
+ goto _err;
strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
strcpy(card->shortname, chip->name);
@@ -162,12 +155,19 @@ static int __init snd_sb8_probe(int dev)
chip->name,
chip->port,
irq[dev], dma8[dev]);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_sb8_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 5b6bde213ea0..f0f205ae425f 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -221,7 +221,7 @@ int snd_sbdsp_create(snd_card_t *card,
snd_assert(r_chip != NULL, return -EINVAL);
*r_chip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 17f585b0ddc1..52f2294da62b 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -67,6 +67,8 @@ MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "sgalaxy: "
+
/*
*/
@@ -135,7 +137,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
}
#if 0
- snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n");
+ snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
#endif
/* initialize IRQ for WSS codec */
@@ -160,7 +162,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
{
#if 0
- snd_printdd("sgalaxy - switching to WSS mode\n");
+ snd_printdd(PFX "switching to WSS mode\n");
#endif
/* switch to WSS mode */
@@ -223,11 +225,11 @@ static int __init snd_sgalaxy_probe(int dev)
ad1848_t *chip;
if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify SB port\n");
+ snd_printk(KERN_ERR PFX "specify SB port\n");
return -EINVAL;
}
if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify WSS port\n");
+ snd_printk(KERN_ERR PFX "specify WSS port\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -237,46 +239,39 @@ static int __init snd_sgalaxy_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto _err;
}
}
- if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
+ goto _err;
if ((err = snd_ad1848_create(card, wssport[dev] + 4,
xirq, xdma1,
- AD1848_HW_DETECT, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ AD1848_HW_DETECT, &chip)) < 0)
+ goto _err;
if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 PCM device\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 PCM device\n");
+ goto _err;
}
if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 mixer\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 mixer\n");
+ goto _err;
}
- if (snd_sgalaxy_mixer(chip) < 0) {
- snd_printdd("sgalaxy - the mixer rewrite failed\n");
- snd_card_free(card);
- return err;
+ if ((err = snd_sgalaxy_mixer(chip)) < 0) {
+ snd_printdd(PFX "the mixer rewrite failed\n");
+ goto _err;
}
strcpy(card->driver, "Sound Galaxy");
@@ -284,12 +279,18 @@ static int __init snd_sgalaxy_probe(int dev)
sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
wssport[dev], xirq, xdma1);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_sgalaxy_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_sgalaxy_init(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 3959ed694eec..9f6b58c79209 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1262,11 +1262,6 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
*/
sscape_write(sscape, GA_INTENA_REG, 0x80);
- if ((err = snd_card_register(card)) < 0) {
- printk(KERN_ERR "sscape: Failed to register sound card\n");
- goto _release_card;
- }
-
/*
* Initialize mixer
*/
@@ -1396,6 +1391,13 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
if (ret < 0)
return ret;
snd_card_set_dev(card, &pcard->card->dev);
+
+ if ((ret = snd_card_register(card)) < 0) {
+ printk(KERN_ERR "sscape: Failed to register sound card\n");
+ snd_card_free(card);
+ return ret;
+ }
+
pnp_set_card_drvdata(pcard, card);
++sscape_cards;
++idx;
@@ -1460,6 +1462,16 @@ static int __init sscape_manual_probe(struct params *params)
if (ret < 0)
return ret;
+ if ((ret = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return ret;
+ }
+ if ((ret = snd_card_register(card)) < 0) {
+ printk(KERN_ERR "sscape: Failed to register sound card\n");
+ snd_card_free(card);
+ return ret;
+ }
+
sscape_card[sscape_cards] = card;
params++;
sscape_cards++;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 79b022070ba3..0a572e0a47e6 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -622,6 +622,11 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
ics2115_port[dev],
ics2115_irq[dev]);
+ if ((err = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
index 531f8ba96a71..2433b7727404 100644
--- a/sound/mips/Kconfig
+++ b/sound/mips/Kconfig
@@ -8,6 +8,7 @@ config SND_AU1X00
depends on (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SND
select SND_PCM
select SND_AC97_CODEC
+ select SND_GENERIC_DRIVER
help
ALSA Sound driver for the Au1x00's AC97 port.
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index c20522b02134..3f9684f1d1d2 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -667,6 +667,11 @@ au1000_init(void)
strcpy(au1000->card->shortname, "Au1000-AC97");
sprintf(au1000->card->longname, "AMD Au1000--AC97 ALSA Driver");
+ if ((err = snd_card_set_generic_dev(au1000->card)) < 0) {
+ snd_card_free(au1000->card);
+ return err;
+ }
+
if ((err = snd_card_register(au1000->card)) < 0) {
snd_card_free(au1000->card);
return err;
diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c
index b2676fa34630..6982556ded56 100644
--- a/sound/oss/midibuf.c
+++ b/sound/oss/midibuf.c
@@ -50,7 +50,7 @@ static struct midi_parms parms[MAX_MIDI_DEV];
static void midi_poll(unsigned long dummy);
-static struct timer_list poll_timer = TIMER_INITIALIZER(midi_poll, 0, 0);
+static DEFINE_TIMER(poll_timer, midi_poll, 0, 0);
static volatile int open_devs;
static DEFINE_SPINLOCK(lock);
diff --git a/sound/oss/os.h b/sound/oss/os.h
index d6b96297835c..80dce329cc3a 100644
--- a/sound/oss/os.h
+++ b/sound/oss/os.h
@@ -19,9 +19,6 @@
#include <linux/ioport.h>
#include <asm/page.h>
#include <asm/system.h>
-#ifdef __alpha__
-#include <asm/segment.h>
-#endif
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
diff --git a/sound/oss/skeleton.c b/sound/oss/skeleton.c
deleted file mode 100644
index 8fea783dd0cb..000000000000
--- a/sound/oss/skeleton.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * PCI sound skeleton example
- *
- * (c) 1998 Red Hat Software
- *
- * This software may be used and distributed according to the
- * terms of the GNU General Public License, incorporated herein by
- * reference.
- *
- * This example is designed to be built in the linux/drivers/sound
- * directory as part of a kernel build. The example is modular only
- * drop me a note once you have a working modular driver and want
- * to integrate it with the main code.
- * -- Alan <alan@redhat.com>
- *
- * This is a first draft. Please report any errors, corrections or
- * improvements to me.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-
-/*
- * Define our PCI vendor ID here
- */
-
-#ifndef PCI_VENDOR_MYIDENT
-#define PCI_VENDOR_MYIDENT 0x125D
-
-/*
- * PCI identity for the card.
- */
-
-#define PCI_DEVICE_ID_MYIDENT_MYCARD1 0x1969
-#endif
-
-#define CARD_NAME "ExampleWave 3D Pro Ultra ThingyWotsit"
-
-#define MAX_CARDS 8
-
-/*
- * Each address_info object holds the information about one of
- * our card resources. In this case the MSS emulation of our
- * ficticious card. Its used to manage and attach things.
- */
-
-static struct address_info mss_data[MAX_CARDS];
-static int cards;
-
-/*
- * Install the actual card. This is an example
- */
-
-static int mycard_install(struct pci_dev *pcidev)
-{
- int iobase;
- int mssbase;
- int mpubase;
- u8 x;
- u16 w;
- u32 v;
- int i;
- int dma;
-
- /*
- * Our imaginary code has its I/O on PCI address 0, a
- * MSS on PCI address 1 and an MPU on address 2
- *
- * For the example we will only initialise the MSS
- */
-
- iobase = pci_resource_start(pcidev, 0);
- mssbase = pci_resource_start(pcidev, 1);
- mpubase = pci_resource_start(pcidev, 2);
-
- /*
- * Reset the board
- */
-
- /*
- * Wait for completion. udelay() waits in microseconds
- */
-
- udelay(100);
-
- /*
- * Ok card ready. Begin setup proper. You might for example
- * load the firmware here
- */
-
- dma = card_specific_magic(ioaddr);
-
- /*
- * Turn on legacy mode (example), There are also byte and
- * dword (32bit) PCI configuration function calls
- */
-
- pci_read_config_word(pcidev, 0x40, &w);
- w&=~(1<<15); /* legacy decode on */
- w|=(1<<14); /* Reserved write as 1 in this case */
- w|=(1<<3)|(1<<1)|(1<<0); /* SB on , FM on, MPU on */
- pci_write_config_word(pcidev, 0x40, w);
-
- /*
- * Let the user know we found his toy.
- */
-
- printk(KERN_INFO "Programmed "CARD_NAME" at 0x%X to legacy mode.\n",
- iobase);
-
- /*
- * Now set it up the description of the card
- */
-
- mss_data[cards].io_base = mssbase;
- mss_data[cards].irq = pcidev->irq;
- mss_data[cards].dma = dma;
-
- /*
- * Check there is an MSS present
- */
-
- if(ad1848_detect(mssbase, NULL, mss_data[cards].osp)==0)
- return 0;
-
- /*
- * Initialize it
- */
-
- mss_data[cards].slots[3] = ad1848_init("MyCard MSS 16bit",
- mssbase,
- mss_data[cards].irq,
- mss_data[cards].dma,
- mss_data[cards].dma,
- 0,
- 0,
- THIS_MODULE);
-
- cards++;
- return 1;
-}
-
-
-/*
- * This loop walks the PCI configuration database and finds where
- * the sound cards are.
- */
-
-int init_mycard(void)
-{
- struct pci_dev *pcidev=NULL;
- int count=0;
-
- while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL)
- {
- if (pci_enable_device(pcidev))
- continue;
- count+=mycard_install(pcidev);
- if(count)
- return 0;
- if(count==MAX_CARDS)
- break;
- }
-
- if(count==0)
- return -ENODEV;
- return 0;
-}
-
-/*
- * This function is called when the user or kernel loads the
- * module into memory.
- */
-
-
-int init_module(void)
-{
- if(init_mycard()<0)
- {
- printk(KERN_ERR "No "CARD_NAME" cards found.\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-/*
- * This is called when it is removed. It will only be removed
- * when its use count is 0.
- */
-
-void cleanup_module(void)
-{
- for(i=0;i< cards; i++)
- {
- /*
- * Free attached resources
- */
-
- ad1848_unload(mss_data[i].io_base,
- mss_data[i].irq,
- mss_data[i].dma,
- mss_data[i].dma,
- 0);
- /*
- * And disconnect the device from the kernel
- */
- sound_unload_audiodevice(mss_data[i].slots[3]);
- }
-}
-
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index a686be936aff..95fa81e26de2 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -681,8 +681,7 @@ static void do_sequencer_timer(unsigned long dummy)
}
-static struct timer_list seq_timer =
- TIMER_INITIALIZER(do_sequencer_timer, 0, 0);
+static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0);
void request_sound_timer(int count)
{
diff --git a/sound/oss/sys_timer.c b/sound/oss/sys_timer.c
index 6afe29b763b7..c9d04518b172 100644
--- a/sound/oss/sys_timer.c
+++ b/sound/oss/sys_timer.c
@@ -28,8 +28,7 @@ static unsigned long prev_event_time;
static void poll_def_tmr(unsigned long dummy);
static DEFINE_SPINLOCK(lock);
-
-static struct timer_list def_tmr = TIMER_INITIALIZER(poll_def_tmr, 0, 0);
+static DEFINE_TIMER(def_tmr, poll_def_tmr, 0, 0);
static unsigned long
tmr2ticks(int tmr_value)
diff --git a/sound/oss/uart6850.c b/sound/oss/uart6850.c
index be00cf128651..74ae75f9e2dc 100644
--- a/sound/oss/uart6850.c
+++ b/sound/oss/uart6850.c
@@ -78,8 +78,7 @@ static void (*midi_input_intr) (int dev, unsigned char data);
static void poll_uart6850(unsigned long dummy);
-static struct timer_list uart6850_timer =
- TIMER_INITIALIZER(poll_uart6850, 0, 0);
+static DEFINE_TIMER(uart6850_timer, poll_uart6850, 0, 0);
static void uart6850_input_loop(void)
{
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index d7a8f9f5896f..f560dd8cdb90 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -880,6 +880,8 @@ snd_harmony_create(snd_card_t *card,
goto free_and_ret;
}
+ snd_card_set_dev(card, &padev->dev);
+
*rchip = h;
return 0;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 26b42bb20a0a..a5d593c66f9f 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -1,11 +1,15 @@
# ALSA PCI drivers
-menu "PCI devices"
- depends on SND!=n && PCI
-
config SND_AC97_CODEC
tristate
select SND_PCM
+ select SND_AC97_BUS
+
+config SND_AC97_BUS
+ tristate
+
+menu "PCI devices"
+ depends on SND!=n && PCI
config SND_ALI5451
tristate "ALi M5451 PCI Audio Controller"
@@ -312,6 +316,18 @@ config SND_YMFPCI
To compile this driver as a module, choose M here: the module
will be called snd-ymfpci.
+config SND_AD1889
+ tristate "Analog Devices AD1889"
+ depends on SND
+ select SND_AC97_CODEC
+ help
+ Say Y here to include support for the integrated AC97 sound
+ device found in particular on the Hewlett-Packard [BCJ]-xxx0
+ class PA-RISC workstations, using the AD1819 codec.
+
+ To compile this as a module, choose M here: the module
+ will be called snd-ad1889.
+
config SND_ALS4000
tristate "Avance Logic ALS4000"
depends on SND && ISA_DMA_API
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index b40575c3349a..42fabfcfc2a9 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
+snd-ad1889-objs := ad1889.o
snd-als4000-objs := als4000.o
snd-atiixp-objs := atiixp.o
snd-atiixp-modem-objs := atiixp_modem.o
@@ -25,6 +26,7 @@ snd-via82xx-objs := via82xx.o
snd-via82xx-modem-objs := via82xx_modem.o
# Toplevel Module Dependency
+obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index 3c3222122d8b..77b3482cb133 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -10,9 +10,11 @@ snd-ac97-codec-objs += ac97_proc.o
endif
snd-ak4531-codec-objs := ak4531_codec.o
+snd-ac97-bus-objs := ac97_bus.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
+obj-$(CONFIG_SND_AC97_BUS) += snd-ac97-bus.o
obj-m := $(sort $(obj-m))
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c
new file mode 100644
index 000000000000..227f8b9f67ce
--- /dev/null
+++ b/sound/pci/ac97/ac97_bus.c
@@ -0,0 +1,79 @@
+/*
+ * Linux driver model AC97 bus interface
+ *
+ * Author: Nicolas Pitre
+ * Created: Jan 14, 2005
+ * Copyright: (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 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/device.h>
+#include <linux/string.h>
+
+/*
+ * Codec families have names seperated by commas, so we search for an
+ * individual codec name within the family string.
+ */
+static int ac97_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return (strstr(dev->bus_id, drv->name) != NULL);
+}
+
+static int ac97_bus_suspend(struct device *dev, pm_message_t state)
+{
+ int ret = 0;
+
+ if (dev->driver && dev->driver->suspend) {
+ ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
+ if (ret == 0)
+ ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
+ if (ret == 0)
+ ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
+ }
+ return ret;
+}
+
+static int ac97_bus_resume(struct device *dev)
+{
+ int ret = 0;
+
+ if (dev->driver && dev->driver->resume) {
+ ret = dev->driver->resume(dev, RESUME_POWER_ON);
+ if (ret == 0)
+ ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
+ if (ret == 0)
+ ret = dev->driver->resume(dev, RESUME_ENABLE);
+ }
+ return ret;
+}
+
+struct bus_type ac97_bus_type = {
+ .name = "ac97",
+ .match = ac97_bus_match,
+ .suspend = ac97_bus_suspend,
+ .resume = ac97_bus_resume,
+};
+
+static int __init ac97_bus_init(void)
+{
+ return bus_register(&ac97_bus_type);
+}
+
+subsys_initcall(ac97_bus_init);
+
+static void __exit ac97_bus_exit(void)
+{
+ bus_unregister(&ac97_bus_type);
+}
+
+module_exit(ac97_bus_exit);
+
+EXPORT_SYMBOL(ac97_bus_type);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 6983eea226da..e64cb07a39c2 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -112,6 +112,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */
{ 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL },
{ 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL },
+{ 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */
{ 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL },
{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL },
{ 0x414c4730, 0xffffffff, "ALC101", NULL, NULL },
@@ -157,6 +158,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x54524123, 0xffffffff, "TR28602", NULL, NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
{ 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
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
@@ -1307,16 +1309,18 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build master tone controls */
- if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {
- for (idx = 0; idx < 2; idx++) {
- if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
- return err;
- if (ac97->id == AC97_ID_YMF753) {
- kctl->private_value &= ~(0xff << 16);
- kctl->private_value |= 7 << 16;
+ if (!(ac97->flags & AC97_HAS_NO_TONE)) {
+ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) {
+ for (idx = 0; idx < 2; idx++) {
+ if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0)
+ return err;
+ if (ac97->id == AC97_ID_YMF753) {
+ kctl->private_value &= ~(0xff << 16);
+ kctl->private_value |= 7 << 16;
+ }
}
+ snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);
}
- snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f);
}
/* build PC Speaker controls */
@@ -1339,11 +1343,13 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build MIC controls */
- if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {
- if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0)
- return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)
- return err;
+ if (!(ac97->flags & AC97_HAS_NO_MIC)) {
+ if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) {
+ if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0)
+ return err;
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0)
+ return err;
+ }
}
/* build Line controls */
@@ -1402,12 +1408,14 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
snd_ac97_write_cache(ac97, AC97_PCM, init_val);
} else {
- if (ac97->flags & AC97_HAS_NO_PCM_VOL)
- err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97);
- else
- err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97);
- if (err < 0)
- return err;
+ if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) {
+ if (ac97->flags & AC97_HAS_NO_PCM_VOL)
+ err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97);
+ else
+ err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97);
+ if (err < 0)
+ return err;
+ }
}
/* build Capture controls */
@@ -1789,7 +1797,7 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
snd_assert(card != NULL, return -EINVAL);
snd_assert(rbus != NULL, return -EINVAL);
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL)
return -ENOMEM;
bus->card = card;
@@ -1807,6 +1815,39 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
return 0;
}
+/* stop no dev release warning */
+static void ac97_device_release(struct device * dev)
+{
+}
+
+/* register ac97 codec to bus */
+static int snd_ac97_dev_register(snd_device_t *device)
+{
+ ac97_t *ac97 = device->device_data;
+ int err;
+
+ ac97->dev.bus = &ac97_bus_type;
+ ac97->dev.parent = ac97->bus->card->dev;
+ ac97->dev.platform_data = ac97;
+ ac97->dev.release = ac97_device_release;
+ snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "card%d-%d", ac97->bus->card->number, ac97->num);
+ if ((err = device_register(&ac97->dev)) < 0) {
+ snd_printk(KERN_ERR "Can't register ac97 bus\n");
+ ac97->dev.bus = NULL;
+ return err;
+ }
+ return 0;
+}
+
+/* unregister ac97 codec */
+static int snd_ac97_dev_unregister(snd_device_t *device)
+{
+ ac97_t *ac97 = device->device_data;
+ if (ac97->dev.bus)
+ device_unregister(&ac97->dev);
+ return snd_ac97_free(ac97);
+}
+
/* build_ops to do nothing */
static struct snd_ac97_build_ops null_build_ops;
@@ -1840,6 +1881,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
const ac97_codec_id_t *pid;
static snd_device_ops_t ops = {
.dev_free = snd_ac97_dev_free,
+ .dev_register = snd_ac97_dev_register,
+ .dev_unregister = snd_ac97_dev_unregister,
};
snd_assert(rac97 != NULL, return -EINVAL);
@@ -1863,7 +1906,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
}
card = bus->card;
- ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
+ ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL);
if (ac97 == NULL)
return -ENOMEM;
ac97->private_data = template->private_data;
@@ -2539,8 +2582,6 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
{
int result;
- snd_assert(quirk, return -EINVAL);
-
/* quirk overriden? */
if (override && strcmp(override, "-1") && strcmp(override, "default")) {
result = apply_quirk_str(ac97, override);
@@ -2549,6 +2590,9 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
return result;
}
+ if (! quirk)
+ return -EINVAL;
+
for (; quirk->subvendor; quirk++) {
if (quirk->subvendor != ac97->subsystem_vendor)
continue;
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index dadf387ad0b8..6d73514dc49e 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -52,6 +52,7 @@
#define AC97_ID_ALC650F 0x414c4723
#define AC97_ID_ALC655 0x414c4760
#define AC97_ID_ALC658 0x414c4780
+#define AC97_ID_ALC658D 0x414c4781
#define AC97_ID_ALC850 0x414c4790
#define AC97_ID_YMF753 0x594d4803
#define AC97_ID_VT1616 0x49434551
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 66edc857d3e6..045ddc743edc 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -370,141 +370,387 @@ int patch_yamaha_ymf753(ac97_t * ac97)
* added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
*/
-int patch_wolfson03(ac97_t * ac97)
+static const snd_kcontrol_new_t wm97xx_snd_ac97_controls[] = {
+AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
+AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
+};
+
+static int patch_wolfson_wm9703_specific(ac97_t * ac97)
{
/* This is known to work for the ViewSonic ViewPad 1000
- Randolph Bentson <bentson@holmsjoen.com> */
+ * Randolph Bentson <bentson@holmsjoen.com>
+ * WM9703/9707/9708/9717
+ */
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
+ .build_specific = patch_wolfson_wm9703_specific,
+};
- // WM9703/9707/9708/9717
- snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
- snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x8000);
+int patch_wolfson03(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_wolfson_wm9703_ops;
return 0;
}
-
-int patch_wolfson04(ac97_t * ac97)
+
+static const snd_kcontrol_new_t wm9704_snd_ac97_controls[] = {
+AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
+AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
+AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
+AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
+AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
+AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
+};
+
+static int patch_wolfson_wm9704_specific(ac97_t * ac97)
{
- // WM9704M/9704Q
- // set front and rear mixer volume
- snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
- snd_ac97_write_cache(ac97, AC97_WM9704_RMIXER_VOL, 0x0808);
-
- // patch for DVD noise
+ int err, i;
+ for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0)
+ return err;
+ }
+ /* patch for DVD noise */
snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
-
- // init vol
- snd_ac97_write_cache(ac97, AC97_WM9704_RPCM_VOL, 0x0808);
-
- // set rear surround volume
- snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
return 0;
}
-
+
+static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
+ .build_specific = patch_wolfson_wm9704_specific,
+};
+
+int patch_wolfson04(ac97_t * ac97)
+{
+ /* WM9704M/9704Q */
+ ac97->build_ops = &patch_wolfson_wm9704_ops;
+ return 0;
+}
+
+static int patch_wolfson_wm9705_specific(ac97_t * ac97)
+{
+ int err, i;
+ for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, 0x72, 0x0808);
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = {
+ .build_specific = patch_wolfson_wm9705_specific,
+};
+
int patch_wolfson05(ac97_t * ac97)
{
- // WM9705, WM9710
- // set front mixer volume
- snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
+ /* WM9705, WM9710 */
+ ac97->build_ops = &patch_wolfson_wm9705_ops;
+ return 0;
+}
+
+static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
+static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
+static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
+static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
+static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
+static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
+static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
+static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
+static const char* wm9711_rec_sel[] =
+ {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
+static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
+
+static const struct ac97_enum wm9711_enum[] = {
+AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
+AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
+AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
+AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
+AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
+AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
+AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
+AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
+AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
+AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
+};
+
+static const snd_kcontrol_new_t wm9711_snd_ac97_controls[] = {
+AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
+AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
+AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
+AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
+AC97_ENUM("ALC Function", wm9711_enum[0]),
+AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
+AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
+AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
+AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
+AC97_ENUM("ALC NG Type", wm9711_enum[9]),
+AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
+
+AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
+AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
+AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
+AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
+
+AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
+AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
+AC97_ENUM("Out3 Mux", wm9711_enum[2]),
+AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
+AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
+
+AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
+AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
+AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
+AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
+AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
+AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
+
+AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
+AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
+AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
+AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
+AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
+AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
+
+AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
+AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
+
+AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
+AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
+AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
+
+AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
+AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
+AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
+
+AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
+AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
+AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
+AC97_ENUM("Capture Select", wm9711_enum[8]),
+
+AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
+AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
+
+AC97_ENUM("Bass Control", wm9711_enum[5]),
+AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
+AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
+AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
+
+AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
+AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
+AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 1),
+AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
+
+AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
+AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
+AC97_ENUM("Mic Select Source", wm9711_enum[7]),
+AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1),
+AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+
+AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
+AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
+AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
+};
+
+static int patch_wolfson_wm9711_specific(ac97_t * ac97)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_AUX, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_CD, 0x0000);
return 0;
}
+static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
+ .build_specific = patch_wolfson_wm9711_specific,
+};
+
int patch_wolfson11(ac97_t * ac97)
{
- // WM9711, WM9712
- // set out3 volume
- snd_ac97_write_cache(ac97, AC97_WM9711_OUT3VOL, 0x0808);
+ /* WM9711, WM9712 */
+ ac97->build_ops = &patch_wolfson_wm9711_ops;
+
+ ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
+ AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
+
return 0;
}
-static const char* wm9713_mic_mixer[] = {"Stereo", "Mic1", "Mic2", "Mute"};
+static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
-static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"};
-static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"};
+static const char* wm9713_rec_src[] =
+ {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix",
+ "Mono Mix", "Zh"};
+static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
+static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
+static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
+static const char* wm9713_spk_pga[] =
+ {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
+static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
+static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
+static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
+static const char* wm9713_dac_inv[] =
+ {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R",
+ "Headphone Mix Mono", "NC", "Vmid"};
+static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
+static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
static const struct ac97_enum wm9713_enum[] = {
AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
-AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l),
-AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r),
+AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
+AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
+AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
+AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
+AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
+AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
+AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
+AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
+AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
+AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
+AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
};
-static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = {
+static const snd_kcontrol_new_t wm13_snd_ac97_controls[] = {
AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
-AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1),
-AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1),
-AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1),
+AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
+AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
+AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
+
+AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
+AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
+AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
+AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
+
+AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
+AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
+AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
+AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
+AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
+AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
+AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
+
+AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
+AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
+AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
+AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
+
+AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
+AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
+AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
+AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
+AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
+AC97_ENUM("Capture Select", wm9713_enum[3]),
+
+AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
+AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
+AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
+AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
+AC97_ENUM("ALC Function", wm9713_enum[5]),
+AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
+AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
+AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
+AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
+AC97_ENUM("ALC NG Type", wm9713_enum[13]),
+AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
+
+AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
+AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
+AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
+AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
+AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
+AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
+
+AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
+AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
+AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
+AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
+AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
+AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
+
+AC97_SINGLE("PC Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
+AC97_SINGLE("PC Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
+AC97_SINGLE("PC Beep to Master Switch", AC97_AUX, 11, 1, 1),
+AC97_SINGLE("PC Beep to Master Volume", AC97_AUX, 8, 7, 1),
+AC97_SINGLE("PC Beep to Mono Switch", AC97_AUX, 7, 1, 1),
+AC97_SINGLE("PC Beep to Mono Volume", AC97_AUX, 4, 7, 1),
+
+AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
+AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
+AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
+AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
+AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
+AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
+
+AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
+AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
+AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
+AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
+AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
+AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
+
+AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
+AC97_ENUM("Master Input Mux", wm9713_enum[7]),
+AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
+AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
+AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
+
+AC97_ENUM("Bass Control", wm9713_enum[12]),
+AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
+AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
+AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
+AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
+AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
};
-static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = {
-AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1),
-AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1),
-AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1),
-AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1),
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_3d[] = {
+AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
+AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
+AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
+AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
};
-static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = {
-AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1),
-AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1),
-AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1),
-AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1),
-AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1),
-AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]),
-AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1)
-};
-
-static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = {
-AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1),
-AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1),
-AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0),
-AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1),
-};
-
-static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = {
-AC97_ENUM("Record to Headphone Path", wm9713_enum[1]),
-AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0),
-AC97_ENUM("Record to Mono Path", wm9713_enum[2]),
-AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0),
-AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0),
-AC97_ENUM("Record Select Left", wm9713_enum[3]),
-AC97_ENUM("Record Select Right", wm9713_enum[4]),
-};
+static int patch_wolfson_wm9713_3d (ac97_t * ac97)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0)
+ return err;
+ }
+ return 0;
+}
static int patch_wolfson_wm9713_specific(ac97_t * ac97)
{
int err, i;
- for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) {
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0)
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0)
return err;
}
snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
-
- for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) {
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0)
- return err;
- }
snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
-
- for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) {
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0)
- return err;
- }
snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
-
- for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) {
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0)
- return err;
- }
snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
-
- for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) {
- if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0)
- return err;
- }
snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
-
return 0;
}
@@ -525,6 +771,7 @@ static void patch_wolfson_wm9713_resume (ac97_t * ac97)
static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
.build_specific = patch_wolfson_wm9713_specific,
+ .build_3d = patch_wolfson_wm9713_3d,
#ifdef CONFIG_PM
.suspend = patch_wolfson_wm9713_suspend,
.resume = patch_wolfson_wm9713_resume
@@ -533,10 +780,13 @@ static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
int patch_wolfson13(ac97_t * ac97)
{
+ /* WM9713, WM9714 */
ac97->build_ops = &patch_wolfson_wm9713_ops;
ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
- AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
+ AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
+ AC97_HAS_NO_STD_PCM;
+ ac97->scaps &= ~AC97_SCAP_MODEM;
snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
@@ -1379,6 +1629,7 @@ static void check_ad1981_hp_jack_sense(ac97_t *ac97)
u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
switch (subid) {
case 0x103c0890: /* HP nc6000 */
+ case 0x103c099c: /* HP nx6110 */
case 0x103c006d: /* HP nx9105 */
case 0x17340088: /* FSC Scenic-W */
/* enable headphone jack sense */
@@ -1706,7 +1957,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
- AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
/* disable this controls since it doesn't work as expected */
/* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
@@ -1849,12 +2100,12 @@ static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
}
static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
- AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0),
+ AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
/* disable this controls since it doesn't work as expected */
/* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = alc655_iec958_route_info,
.get = alc655_iec958_route_get,
.put = alc655_iec958_route_put,
@@ -1883,7 +2134,13 @@ int patch_alc655(ac97_t * ac97)
{
unsigned int val;
- ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
+ if (ac97->id == AC97_ID_ALC658) {
+ ac97->spec.dev_flags = 1; /* ALC658 */
+ if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
+ ac97->id = AC97_ID_ALC658D;
+ ac97->spec.dev_flags = 2;
+ }
+ }
ac97->build_ops = &patch_alc655_ops;
@@ -1892,10 +2149,15 @@ int patch_alc655(ac97_t * ac97)
/* adjust default values */
val = snd_ac97_read(ac97, 0x7a); /* misc control */
- if (ac97->id == 0x414c4780) /* ALC658 */
+ if (ac97->spec.dev_flags) /* ALC658 */
val &= ~(1 << 1); /* Pin 47 is spdif input pin */
- else /* ALC655 */
- val |= (1 << 1); /* Pin 47 is spdif input pin */
+ else { /* ALC655 */
+ if (ac97->subsystem_vendor == 0x1462 &&
+ ac97->subsystem_device == 0x0131) /* MSI S270 laptop */
+ val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
+ else
+ val |= (1 << 1); /* Pin 47 is spdif input pin */
+ }
val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val);
/* set default: spdif-in enabled,
@@ -1908,6 +2170,11 @@ int patch_alc655(ac97_t * ac97)
/* full DAC volume */
snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+
+ /* update undocumented bit... */
+ if (ac97->id == AC97_ID_ALC658D)
+ snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
+
return 0;
}
@@ -2416,6 +2683,16 @@ int patch_vt1616(ac97_t * ac97)
}
/*
+ * VT1617A codec
+ */
+int patch_vt1617a(ac97_t * ac97)
+{
+ ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
+ ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+ return 0;
+}
+
+/*
*/
static void it2646_update_jacks(ac97_t *ac97)
{
@@ -2433,7 +2710,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
- AC97_SINGLE("IEC958 Capture Switch", 0x76, 11, 1, 0),
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
};
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 7b7377d0f2ae..ec1811320106 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -56,5 +56,6 @@ int patch_cm9739(ac97_t * ac97);
int patch_cm9761(ac97_t * ac97);
int patch_cm9780(ac97_t * ac97);
int patch_vt1616(ac97_t * ac97);
+int patch_vt1617a(ac97_t * ac97);
int patch_it2646(ac97_t * ac97);
int mpatch_si3036(ac97_t * ac97);
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index f9ce0fd2f52f..4032c5748370 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -357,7 +357,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
snd_assert(rak4531 != NULL, return -EINVAL);
*rak4531 = NULL;
snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
- ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
+ ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
if (ak4531 == NULL)
return -ENOMEM;
*ak4531 = *_ak4531;
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
new file mode 100644
index 000000000000..d7d99a25c5e5
--- /dev/null
+++ b/sound/pci/ad1889.c
@@ -0,0 +1,1090 @@
+/* Analog Devices 1889 audio driver
+ *
+ * This is a driver for the AD1889 PCI audio chipset found
+ * on the HP PA-RISC [BCJ]-xxx0 workstations.
+ *
+ * Copyright (C) 2004-2005, Kyle McMartin <kyle@parisc-linux.org>
+ * Copyright (C) 2005, Thibaut Varene <varenet@parisc-linux.org>
+ * Based on the OSS AD1889 driver by Randolph Chung <tausq@debian.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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.
+ *
+ * TODO:
+ * Do we need to take care of CCS register?
+ * Maybe we could use finer grained locking (separate locks for pb/cap)?
+ * Wishlist:
+ * Control Interface (mixer) support
+ * Better AC97 support (VSR...)?
+ * PM support
+ * MIDI support
+ * Game Port support
+ * SG DMA support (this will need *alot* of work)
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include <asm/io.h>
+
+#include "ad1889.h"
+#include "ac97/ac97_id.h"
+
+#define AD1889_DRVVER "$Revision: 1.3 $"
+
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>");
+MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1889}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable AD1889 soundcard.");
+
+static char *ac97_quirk[SNDRV_CARDS];
+module_param_array(ac97_quirk, charp, NULL, 0444);
+MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+
+#define DEVNAME "ad1889"
+#define PFX DEVNAME ": "
+
+/* let's use the global sound debug interfaces */
+#define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg)
+
+/* keep track of some hw registers */
+struct ad1889_register_state {
+ u16 reg; /* reg setup */
+ u32 addr; /* dma base address */
+ unsigned long size; /* DMA buffer size */
+};
+
+struct snd_ad1889 {
+ snd_card_t *card;
+ struct pci_dev *pci;
+
+ int irq;
+ unsigned long bar;
+ void __iomem *iobase;
+
+ ac97_t *ac97;
+ ac97_bus_t *ac97_bus;
+ snd_pcm_t *pcm;
+ snd_info_entry_t *proc;
+
+ snd_pcm_substream_t *psubs;
+ snd_pcm_substream_t *csubs;
+
+ /* playback register state */
+ struct ad1889_register_state wave;
+ struct ad1889_register_state ramc;
+
+ spinlock_t lock;
+};
+
+static inline u16
+ad1889_readw(struct snd_ad1889 *chip, unsigned reg)
+{
+ return readw(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val)
+{
+ writew(val, chip->iobase + reg);
+}
+
+static inline u32
+ad1889_readl(struct snd_ad1889 *chip, unsigned reg)
+{
+ return readl(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val)
+{
+ writel(val, chip->iobase + reg);
+}
+
+static inline void
+ad1889_unmute(struct snd_ad1889 *chip)
+{
+ u16 st;
+ st = ad1889_readw(chip, AD_DS_WADA) &
+ ~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM);
+ ad1889_writew(chip, AD_DS_WADA, st);
+ ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_mute(struct snd_ad1889 *chip)
+{
+ u16 st;
+ st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM;
+ ad1889_writew(chip, AD_DS_WADA, st);
+ ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+ ad1889_writel(chip, AD_DMA_ADCBA, address);
+ ad1889_writel(chip, AD_DMA_ADCCA, address);
+}
+
+static inline void
+ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_ADCBC, count);
+ ad1889_writel(chip, AD_DMA_ADCCC, count);
+}
+
+static inline void
+ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_ADCIB, count);
+ ad1889_writel(chip, AD_DMA_ADCIC, count);
+}
+
+static inline void
+ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+ ad1889_writel(chip, AD_DMA_WAVBA, address);
+ ad1889_writel(chip, AD_DMA_WAVCA, address);
+}
+
+static inline void
+ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_WAVBC, count);
+ ad1889_writel(chip, AD_DMA_WAVCC, count);
+}
+
+static inline void
+ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_WAVIB, count);
+ ad1889_writel(chip, AD_DMA_WAVIC, count);
+}
+
+static void
+ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel)
+{
+ u16 reg;
+
+ if (channel & AD_CHAN_WAV) {
+ /* Disable wave channel */
+ reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN;
+ ad1889_writew(chip, AD_DS_WSMC, reg);
+ chip->wave.reg = reg;
+
+ /* disable IRQs */
+ reg = ad1889_readw(chip, AD_DMA_WAV);
+ reg &= AD_DMA_IM_DIS;
+ reg &= ~AD_DMA_LOOP;
+ ad1889_writew(chip, AD_DMA_WAV, reg);
+
+ /* clear IRQ and address counters and pointers */
+ ad1889_load_wave_buffer_address(chip, 0x0);
+ ad1889_load_wave_buffer_count(chip, 0x0);
+ ad1889_load_wave_interrupt_count(chip, 0x0);
+
+ /* flush */
+ ad1889_readw(chip, AD_DMA_WAV);
+ }
+
+ if (channel & AD_CHAN_ADC) {
+ /* Disable ADC channel */
+ reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN;
+ ad1889_writew(chip, AD_DS_RAMC, reg);
+ chip->ramc.reg = reg;
+
+ reg = ad1889_readw(chip, AD_DMA_ADC);
+ reg &= AD_DMA_IM_DIS;
+ reg &= ~AD_DMA_LOOP;
+ ad1889_writew(chip, AD_DMA_ADC, reg);
+
+ ad1889_load_adc_buffer_address(chip, 0x0);
+ ad1889_load_adc_buffer_count(chip, 0x0);
+ ad1889_load_adc_interrupt_count(chip, 0x0);
+
+ /* flush */
+ ad1889_readw(chip, AD_DMA_ADC);
+ }
+}
+
+static inline u16
+snd_ad1889_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ return ad1889_readw(chip, AD_AC97_BASE + reg);
+}
+
+static inline void
+snd_ad1889_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ ad1889_writew(chip, AD_AC97_BASE + reg, val);
+}
+
+static int
+snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
+{
+ int retry = 400; /* average needs 352 msec */
+
+ while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY)
+ && --retry)
+ mdelay(1);
+ if (!retry) {
+ snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
+ __FUNCTION__);
+ return -EIO;
+ }
+ ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
+
+ return 0;
+}
+
+static int
+snd_ad1889_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int
+snd_ad1889_hw_free(snd_pcm_substream_t *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static snd_pcm_hardware_t snd_ad1889_playback_hw = {
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000, /* docs say 7000, but we're lazy */
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = PERIOD_BYTES_MAX,
+ .periods_min = PERIODS_MIN,
+ .periods_max = PERIODS_MAX,
+ /*.fifo_size = 0,*/
+};
+
+static snd_pcm_hardware_t snd_ad1889_capture_hw = {
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000, /* docs say we could to VSR, but we're lazy */
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = PERIOD_BYTES_MAX,
+ .periods_min = PERIODS_MIN,
+ .periods_max = PERIODS_MAX,
+ /*.fifo_size = 0,*/
+};
+
+static int
+snd_ad1889_playback_open(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+
+ chip->psubs = ss;
+ rt->hw = snd_ad1889_playback_hw;
+
+ return 0;
+}
+
+static int
+snd_ad1889_capture_open(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+
+ chip->csubs = ss;
+ rt->hw = snd_ad1889_capture_hw;
+
+ return 0;
+}
+
+static int
+snd_ad1889_playback_close(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ chip->psubs = NULL;
+ return 0;
+}
+
+static int
+snd_ad1889_capture_close(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ chip->csubs = NULL;
+ return 0;
+}
+
+static int
+snd_ad1889_playback_prepare(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+ unsigned int count = snd_pcm_lib_period_bytes(ss);
+ u16 reg;
+
+ ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+ reg = ad1889_readw(chip, AD_DS_WSMC);
+
+ /* Mask out 16-bit / Stereo */
+ reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST);
+
+ if (snd_pcm_format_width(rt->format) == 16)
+ reg |= AD_DS_WSMC_WA16;
+
+ if (rt->channels > 1)
+ reg |= AD_DS_WSMC_WAST;
+
+ /* let's make sure we don't clobber ourselves */
+ spin_lock_irq(&chip->lock);
+
+ chip->wave.size = size;
+ chip->wave.reg = reg;
+ chip->wave.addr = rt->dma_addr;
+
+ ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg);
+
+ /* Set sample rates on the codec */
+ ad1889_writew(chip, AD_DS_WAS, rt->rate);
+
+ /* Set up DMA */
+ ad1889_load_wave_buffer_address(chip, chip->wave.addr);
+ ad1889_load_wave_buffer_count(chip, size);
+ ad1889_load_wave_interrupt_count(chip, count);
+
+ /* writes flush */
+ ad1889_readw(chip, AD_DS_WSMC);
+
+ spin_unlock_irq(&chip->lock);
+
+ ad1889_debug("prepare playback: addr = 0x%x, count = %u, "
+ "size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr,
+ count, size, reg, rt->rate);
+ return 0;
+}
+
+static int
+snd_ad1889_capture_prepare(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+ unsigned int count = snd_pcm_lib_period_bytes(ss);
+ u16 reg;
+
+ ad1889_channel_reset(chip, AD_CHAN_ADC);
+
+ reg = ad1889_readw(chip, AD_DS_RAMC);
+
+ /* Mask out 16-bit / Stereo */
+ reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);
+
+ if (snd_pcm_format_width(rt->format) == 16)
+ reg |= AD_DS_RAMC_AD16;
+
+ if (rt->channels > 1)
+ reg |= AD_DS_RAMC_ADST;
+
+ /* let's make sure we don't clobber ourselves */
+ spin_lock_irq(&chip->lock);
+
+ chip->ramc.size = size;
+ chip->ramc.reg = reg;
+ chip->ramc.addr = rt->dma_addr;
+
+ ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);
+
+ /* Set up DMA */
+ ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
+ ad1889_load_adc_buffer_count(chip, size);
+ ad1889_load_adc_interrupt_count(chip, count);
+
+ /* writes flush */
+ ad1889_readw(chip, AD_DS_RAMC);
+
+ spin_unlock_irq(&chip->lock);
+
+ ad1889_debug("prepare capture: addr = 0x%x, count = %u, "
+ "size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr,
+ count, size, reg, rt->rate);
+ return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+ Must be as fast as possible and not sleep.
+ DMA should be *triggered* by this call.
+ The WSMC "WAEN" bit triggers DMA Wave On/Off */
+static int
+snd_ad1889_playback_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+ u16 wsmc;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ wsmc = ad1889_readw(chip, AD_DS_WSMC);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* enable DMA loop & interrupts */
+ ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT);
+ wsmc |= AD_DS_WSMC_WAEN;
+ /* 1 to clear CHSS bit */
+ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS);
+ ad1889_unmute(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ad1889_mute(chip);
+ wsmc &= ~AD_DS_WSMC_WAEN;
+ break;
+ default:
+ snd_BUG();
+ return -EINVAL;
+ }
+
+ chip->wave.reg = wsmc;
+ ad1889_writew(chip, AD_DS_WSMC, wsmc);
+ ad1889_readw(chip, AD_DS_WSMC); /* flush */
+
+ /* reset the chip when STOP - will disable IRQs */
+ if (cmd == SNDRV_PCM_TRIGGER_STOP)
+ ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+ return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+ Must be as fast as possible and not sleep.
+ DMA should be *triggered* by this call.
+ The RAMC "ADEN" bit triggers DMA ADC On/Off */
+static int
+snd_ad1889_capture_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+ u16 ramc;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ ramc = ad1889_readw(chip, AD_DS_RAMC);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* enable DMA loop & interrupts */
+ ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT);
+ ramc |= AD_DS_RAMC_ADEN;
+ /* 1 to clear CHSS bit */
+ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ramc &= ~AD_DS_RAMC_ADEN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ chip->ramc.reg = ramc;
+ ad1889_writew(chip, AD_DS_RAMC, ramc);
+ ad1889_readw(chip, AD_DS_RAMC); /* flush */
+
+ /* reset the chip when STOP - will disable IRQs */
+ if (cmd == SNDRV_PCM_TRIGGER_STOP)
+ ad1889_channel_reset(chip, AD_CHAN_ADC);
+
+ return 0;
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_playback_pointer(snd_pcm_substream_t *ss)
+{
+ size_t ptr = 0;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN)))
+ return 0;
+
+ ptr = ad1889_readl(chip, AD_DMA_WAVCA);
+ ptr -= chip->wave.addr;
+
+ snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0);
+
+ return bytes_to_frames(ss->runtime, ptr);
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_capture_pointer(snd_pcm_substream_t *ss)
+{
+ size_t ptr = 0;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN)))
+ return 0;
+
+ ptr = ad1889_readl(chip, AD_DMA_ADCCA);
+ ptr -= chip->ramc.addr;
+
+ snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0);
+
+ return bytes_to_frames(ss->runtime, ptr);
+}
+
+static snd_pcm_ops_t snd_ad1889_playback_ops = {
+ .open = snd_ad1889_playback_open,
+ .close = snd_ad1889_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ad1889_hw_params,
+ .hw_free = snd_ad1889_hw_free,
+ .prepare = snd_ad1889_playback_prepare,
+ .trigger = snd_ad1889_playback_trigger,
+ .pointer = snd_ad1889_playback_pointer,
+};
+
+static snd_pcm_ops_t snd_ad1889_capture_ops = {
+ .open = snd_ad1889_capture_open,
+ .close = snd_ad1889_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ad1889_hw_params,
+ .hw_free = snd_ad1889_hw_free,
+ .prepare = snd_ad1889_capture_prepare,
+ .trigger = snd_ad1889_capture_trigger,
+ .pointer = snd_ad1889_capture_pointer,
+};
+
+static irqreturn_t
+snd_ad1889_interrupt(int irq,
+ void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long st;
+ struct snd_ad1889 *chip = dev_id;
+
+ st = ad1889_readl(chip, AD_DMA_DISR);
+
+ /* clear ISR */
+ ad1889_writel(chip, AD_DMA_DISR, st);
+
+ st &= AD_INTR_MASK;
+
+ if (unlikely(!st))
+ return IRQ_NONE;
+
+ if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI))
+ ad1889_debug("Unexpected master or target abort interrupt!\n");
+
+ if ((st & AD_DMA_DISR_WAVI) && chip->psubs)
+ snd_pcm_period_elapsed(chip->psubs);
+ if ((st & AD_DMA_DISR_ADCI) && chip->csubs)
+ snd_pcm_period_elapsed(chip->csubs);
+
+ return IRQ_HANDLED;
+}
+
+static void
+snd_ad1889_pcm_free(snd_pcm_t *pcm)
+{
+ struct snd_ad1889 *chip = pcm->private_data;
+ chip->pcm = NULL;
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int __devinit
+snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, snd_pcm_t **rpcm)
+{
+ int err;
+ snd_pcm_t *pcm;
+
+ if (rpcm)
+ *rpcm = NULL;
+
+ err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_ad1889_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_ad1889_capture_ops);
+
+ pcm->private_data = chip;
+ pcm->private_free = snd_ad1889_pcm_free;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, chip->card->shortname);
+
+ chip->pcm = pcm;
+ chip->psubs = NULL;
+ chip->csubs = NULL;
+
+ err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ BUFFER_BYTES_MAX / 2,
+ BUFFER_BYTES_MAX);
+
+ if (err < 0) {
+ snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
+ return err;
+ }
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+
+static void
+snd_ad1889_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+ struct snd_ad1889 *chip = entry->private_data;
+ u16 reg;
+ int tmp;
+
+ reg = ad1889_readw(chip, AD_DS_WSMC);
+ snd_iprintf(buffer, "Wave output: %s\n",
+ (reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled");
+ snd_iprintf(buffer, "Wave Channels: %s\n",
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+ snd_iprintf(buffer, "Wave Quality: %d-bit linear\n",
+ (reg & AD_DS_WSMC_WA16) ? 16 : 8);
+
+ /* WARQ is at offset 12 */
+ tmp = (reg & AD_DS_WSMC_WARQ) ?
+ (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+
+ snd_iprintf(buffer, "Synthesis output: %s\n",
+ reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled");
+
+ /* SYRQ is at offset 4 */
+ tmp = (reg & AD_DS_WSMC_SYRQ) ?
+ (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+ reg = ad1889_readw(chip, AD_DS_RAMC);
+ snd_iprintf(buffer, "ADC input: %s\n",
+ (reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled");
+ snd_iprintf(buffer, "ADC Channels: %s\n",
+ (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+ snd_iprintf(buffer, "ADC Quality: %d-bit linear\n",
+ (reg & AD_DS_RAMC_AD16) ? 16 : 8);
+
+ /* ACRQ is at offset 4 */
+ tmp = (reg & AD_DS_RAMC_ACRQ) ?
+ (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+
+ snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+
+ snd_iprintf(buffer, "Resampler input: %s\n",
+ reg & AD_DS_RAMC_REEN ? "enabled" : "disabled");
+
+ /* RERQ is at offset 12 */
+ tmp = (reg & AD_DS_RAMC_RERQ) ?
+ (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+
+ /* doc says LSB represents -1.5dB, but the max value (-94.5dB)
+ suggests that LSB is -3dB, which is more coherent with the logarithmic
+ nature of the dB scale */
+ reg = ad1889_readw(chip, AD_DS_WADA);
+ snd_iprintf(buffer, "Left: %s, -%d dB\n",
+ (reg & AD_DS_WADA_LWAM) ? "mute" : "unmute",
+ ((reg & AD_DS_WADA_LWAA) >> 8) * 3);
+ reg = ad1889_readw(chip, AD_DS_WADA);
+ snd_iprintf(buffer, "Right: %s, -%d dB\n",
+ (reg & AD_DS_WADA_RWAM) ? "mute" : "unmute",
+ ((reg & AD_DS_WADA_RWAA) >> 8) * 3);
+
+ reg = ad1889_readw(chip, AD_DS_WAS);
+ snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg);
+ reg = ad1889_readw(chip, AD_DS_RES);
+ snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
+}
+
+static void __devinit
+snd_ad1889_proc_init(struct snd_ad1889 *chip)
+{
+ snd_info_entry_t *entry;
+
+ if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
+ snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read);
+}
+
+static struct ac97_quirk ac97_quirks[] = {
+ {
+ .subvendor = 0x11d4, /* AD */
+ .subdevice = 0x1889, /* AD1889 */
+ .codec_id = AC97_ID_AD1819,
+ .name = "AD1889",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ { } /* terminator */
+};
+
+static void __devinit
+snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
+{
+ u16 reg;
+
+ reg = ad1889_readw(chip, AD_AC97_ACIC);
+ reg |= AD_AC97_ACIC_ACRD; /* Reset Disable */
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+ ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
+ udelay(10);
+ /* Interface Enable */
+ reg |= AD_AC97_ACIC_ACIE;
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+
+ snd_ad1889_ac97_ready(chip);
+
+ /* Audio Stream Output | Variable Sample Rate Mode */
+ reg = ad1889_readw(chip, AD_AC97_ACIC);
+ reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM;
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+ ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
+
+}
+
+static void
+snd_ad1889_ac97_bus_free(ac97_bus_t *bus)
+{
+ struct snd_ad1889 *chip = bus->private_data;
+ chip->ac97_bus = NULL;
+}
+
+static void
+snd_ad1889_ac97_free(ac97_t *ac97)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ chip->ac97 = NULL;
+}
+
+static int __devinit
+snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
+{
+ int err;
+ ac97_template_t ac97;
+ static ac97_bus_ops_t ops = {
+ .write = snd_ad1889_ac97_write,
+ .read = snd_ad1889_ac97_read,
+ };
+
+ /* doing that here, it works. */
+ snd_ad1889_ac97_xinit(chip);
+
+ err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
+ if (err < 0)
+ return err;
+
+ chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ ac97.private_free = snd_ad1889_ac97_free;
+ ac97.pci = chip->pci;
+
+ err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
+ if (err < 0)
+ return err;
+
+ snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);
+
+ return 0;
+}
+
+static int
+snd_ad1889_free(struct snd_ad1889 *chip)
+{
+ if (chip->irq < 0)
+ goto skip_hw;
+
+ spin_lock_irq(&chip->lock);
+
+ ad1889_mute(chip);
+
+ /* Turn off interrupt on count and zero DMA registers */
+ ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC);
+
+ /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */
+ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI);
+ ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */
+
+ spin_unlock_irq(&chip->lock);
+
+ synchronize_irq(chip->irq);
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void*)chip);
+
+skip_hw:
+ if (chip->iobase)
+ iounmap(chip->iobase);
+
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+
+ kfree(chip);
+ return 0;
+}
+
+static inline int
+snd_ad1889_dev_free(snd_device_t *device)
+{
+ struct snd_ad1889 *chip = device->device_data;
+ return snd_ad1889_free(chip);
+}
+
+static int __devinit
+snd_ad1889_init(struct snd_ad1889 *chip)
+{
+ ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+ ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
+
+ mdelay(10);
+
+ /* enable Master and Target abort interrupts */
+ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
+
+ return 0;
+}
+
+static int __devinit
+snd_ad1889_create(snd_card_t *card,
+ struct pci_dev *pci,
+ struct snd_ad1889 **rchip)
+{
+ int err;
+
+ struct snd_ad1889 *chip;
+ static snd_device_ops_t ops = {
+ .dev_free = snd_ad1889_dev_free,
+ };
+
+ *rchip = NULL;
+
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ /* check PCI availability (32bit DMA) */
+ if (pci_set_dma_mask(pci, 0xffffffff) < 0 ||
+ pci_set_consistent_dma_mask(pci, 0xffffffff) < 0) {
+ printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ /* allocate chip specific data with zero-filled memory */
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ card->private_data = chip;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ /* (1) PCI resource allocation */
+ if ((err = pci_request_regions(pci, card->driver)) < 0)
+ goto free_and_ret;
+
+ chip->bar = pci_resource_start(pci, 0);
+ chip->iobase = ioremap_nocache(chip->bar, pci_resource_len(pci, 0));
+ if (chip->iobase == NULL) {
+ printk(KERN_ERR PFX "unable to reserve region.\n");
+ err = -EBUSY;
+ goto free_and_ret;
+ }
+
+ pci_set_master(pci);
+
+ spin_lock_init(&chip->lock); /* only now can we call ad1889_free */
+
+ if (request_irq(pci->irq, snd_ad1889_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, card->driver, (void*)chip)) {
+ printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq);
+ snd_ad1889_free(chip);
+ return -EBUSY;
+ }
+
+ chip->irq = pci->irq;
+ synchronize_irq(chip->irq);
+
+ /* (2) initialization of the chip hardware */
+ if ((err = snd_ad1889_init(chip)) < 0) {
+ snd_ad1889_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ snd_ad1889_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+
+ return 0;
+
+free_and_ret:
+ if (chip)
+ kfree(chip);
+ pci_disable_device(pci);
+
+ return err;
+}
+
+static int __devinit
+snd_ad1889_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ int err;
+ static int devno;
+ snd_card_t *card;
+ struct snd_ad1889 *chip;
+
+ /* (1) */
+ if (devno >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[devno]) {
+ devno++;
+ return -ENOENT;
+ }
+
+ /* (2) */
+ card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0);
+ /* XXX REVISIT: we can probably allocate chip in this call */
+ if (card == NULL)
+ return -ENOMEM;
+
+ strcpy(card->driver, "AD1889");
+ strcpy(card->shortname, "Analog Devices AD1889");
+
+ /* (3) */
+ err = snd_ad1889_create(card, pci, &chip);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* (4) */
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->bar, chip->irq);
+
+ /* (5) */
+ /* register AC97 mixer */
+ err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
+ if (err < 0)
+ goto free_and_ret;
+
+ err = snd_ad1889_pcm_init(chip, 0, NULL);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* register proc interface */
+ snd_ad1889_proc_init(chip);
+
+ /* (6) */
+ err = snd_card_register(card);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* (7) */
+ pci_set_drvdata(pci, card);
+
+ devno++;
+ return 0;
+
+free_and_ret:
+ snd_card_free(card);
+ return err;
+}
+
+static void __devexit
+snd_ad1889_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_device_id snd_ad1889_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
+
+static struct pci_driver ad1889_pci = {
+ .name = "AD1889 Audio",
+ .owner = THIS_MODULE,
+ .id_table = snd_ad1889_ids,
+ .probe = snd_ad1889_probe,
+ .remove = __devexit_p(snd_ad1889_remove),
+};
+
+static int __init
+alsa_ad1889_init(void)
+{
+ return pci_register_driver(&ad1889_pci);
+}
+
+static void __exit
+alsa_ad1889_fini(void)
+{
+ pci_unregister_driver(&ad1889_pci);
+}
+
+module_init(alsa_ad1889_init);
+module_exit(alsa_ad1889_fini);
diff --git a/sound/pci/ad1889.h b/sound/pci/ad1889.h
new file mode 100644
index 000000000000..5e6dad5341a1
--- /dev/null
+++ b/sound/pci/ad1889.h
@@ -0,0 +1,189 @@
+/* Analog Devices 1889 audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __AD1889_H__
+#define __AD1889_H__
+
+#define AD_DS_WSMC 0x00 /* wave/synthesis channel mixer control */
+#define AD_DS_WSMC_SYEN 0x0004 /* synthesis channel enable */
+#define AD_DS_WSMC_SYRQ 0x0030 /* synth. fifo request point */
+#define AD_DS_WSMC_WA16 0x0100 /* wave channel 16bit select */
+#define AD_DS_WSMC_WAST 0x0200 /* wave channel stereo select */
+#define AD_DS_WSMC_WAEN 0x0400 /* wave channel enable */
+#define AD_DS_WSMC_WARQ 0x3000 /* wave fifo request point */
+
+#define AD_DS_RAMC 0x02 /* resampler/ADC channel mixer control */
+#define AD_DS_RAMC_AD16 0x0001 /* ADC channel 16bit select */
+#define AD_DS_RAMC_ADST 0x0002 /* ADC channel stereo select */
+#define AD_DS_RAMC_ADEN 0x0004 /* ADC channel enable */
+#define AD_DS_RAMC_ACRQ 0x0030 /* ADC fifo request point */
+#define AD_DS_RAMC_REEN 0x0400 /* resampler channel enable */
+#define AD_DS_RAMC_RERQ 0x3000 /* res. fifo request point */
+
+#define AD_DS_WADA 0x04 /* wave channel mix attenuation */
+#define AD_DS_WADA_RWAM 0x0080 /* right wave mute */
+#define AD_DS_WADA_RWAA 0x001f /* right wave attenuation */
+#define AD_DS_WADA_LWAM 0x8000 /* left wave mute */
+#define AD_DS_WADA_LWAA 0x3e00 /* left wave attenuation */
+
+#define AD_DS_SYDA 0x06 /* synthesis channel mix attenuation */
+#define AD_DS_SYDA_RSYM 0x0080 /* right synthesis mute */
+#define AD_DS_SYDA_RSYA 0x001f /* right synthesis attenuation */
+#define AD_DS_SYDA_LSYM 0x8000 /* left synthesis mute */
+#define AD_DS_SYDA_LSYA 0x3e00 /* left synthesis attenuation */
+
+#define AD_DS_WAS 0x08 /* wave channel sample rate */
+#define AD_DS_WAS_WAS 0xffff /* sample rate mask */
+
+#define AD_DS_RES 0x0a /* resampler channel sample rate */
+#define AD_DS_RES_RES 0xffff /* sample rate mask */
+
+#define AD_DS_CCS 0x0c /* chip control/status */
+#define AD_DS_CCS_ADO 0x0001 /* ADC channel overflow */
+#define AD_DS_CCS_REO 0x0002 /* resampler channel overflow */
+#define AD_DS_CCS_SYU 0x0004 /* synthesis channel underflow */
+#define AD_DS_CCS_WAU 0x0008 /* wave channel underflow */
+/* bits 4 -> 7, 9, 11 -> 14 reserved */
+#define AD_DS_CCS_XTD 0x0100 /* xtd delay control (4096 clock cycles) */
+#define AD_DS_CCS_PDALL 0x0400 /* power */
+#define AD_DS_CCS_CLKEN 0x8000 /* clock */
+
+#define AD_DMA_RESBA 0x40 /* RES base address */
+#define AD_DMA_RESCA 0x44 /* RES current address */
+#define AD_DMA_RESBC 0x48 /* RES base count */
+#define AD_DMA_RESCC 0x4c /* RES current count */
+
+#define AD_DMA_ADCBA 0x50 /* ADC base address */
+#define AD_DMA_ADCCA 0x54 /* ADC current address */
+#define AD_DMA_ADCBC 0x58 /* ADC base count */
+#define AD_DMA_ADCCC 0x5c /* ADC current count */
+
+#define AD_DMA_SYNBA 0x60 /* synth base address */
+#define AD_DMA_SYNCA 0x64 /* synth current address */
+#define AD_DMA_SYNBC 0x68 /* synth base count */
+#define AD_DMA_SYNCC 0x6c /* synth current count */
+
+#define AD_DMA_WAVBA 0x70 /* wave base address */
+#define AD_DMA_WAVCA 0x74 /* wave current address */
+#define AD_DMA_WAVBC 0x78 /* wave base count */
+#define AD_DMA_WAVCC 0x7c /* wave current count */
+
+#define AD_DMA_RESIC 0x80 /* RES dma interrupt current byte count */
+#define AD_DMA_RESIB 0x84 /* RES dma interrupt base byte count */
+
+#define AD_DMA_ADCIC 0x88 /* ADC dma interrupt current byte count */
+#define AD_DMA_ADCIB 0x8c /* ADC dma interrupt base byte count */
+
+#define AD_DMA_SYNIC 0x90 /* synth dma interrupt current byte count */
+#define AD_DMA_SYNIB 0x94 /* synth dma interrupt base byte count */
+
+#define AD_DMA_WAVIC 0x98 /* wave dma interrupt current byte count */
+#define AD_DMA_WAVIB 0x9c /* wave dma interrupt base byte count */
+
+#define AD_DMA_ICC 0xffffff /* current byte count mask */
+#define AD_DMA_IBC 0xffffff /* base byte count mask */
+/* bits 24 -> 31 reserved */
+
+/* 4 bytes pad */
+#define AD_DMA_ADC 0xa8 /* ADC dma control and status */
+#define AD_DMA_SYNTH 0xb0 /* Synth dma control and status */
+#define AD_DMA_WAV 0xb8 /* wave dma control and status */
+#define AD_DMA_RES 0xa0 /* Resample dma control and status */
+
+#define AD_DMA_SGDE 0x0001 /* SGD mode enable */
+#define AD_DMA_LOOP 0x0002 /* loop enable */
+#define AD_DMA_IM 0x000c /* interrupt mode mask */
+#define AD_DMA_IM_DIS (~AD_DMA_IM) /* disable */
+#define AD_DMA_IM_CNT 0x0004 /* interrupt on count */
+#define AD_DMA_IM_SGD 0x0008 /* interrupt on SGD flag */
+#define AD_DMA_IM_EOL 0x000c /* interrupt on End of Linked List */
+#define AD_DMA_SGDS 0x0030 /* SGD status */
+#define AD_DMA_SFLG 0x0040 /* SGD flag */
+#define AD_DMA_EOL 0x0080 /* SGD end of list */
+/* bits 8 -> 15 reserved */
+
+#define AD_DMA_DISR 0xc0 /* dma interrupt status */
+#define AD_DMA_DISR_RESI 0x000001 /* resampler channel interrupt */
+#define AD_DMA_DISR_ADCI 0x000002 /* ADC channel interrupt */
+#define AD_DMA_DISR_SYNI 0x000004 /* synthesis channel interrupt */
+#define AD_DMA_DISR_WAVI 0x000008 /* wave channel interrupt */
+/* bits 4, 5 reserved */
+#define AD_DMA_DISR_SEPS 0x000040 /* serial eeprom status */
+/* bits 7 -> 13 reserved */
+#define AD_DMA_DISR_PMAI 0x004000 /* pci master abort interrupt */
+#define AD_DMA_DISR_PTAI 0x008000 /* pci target abort interrupt */
+#define AD_DMA_DISR_PTAE 0x010000 /* pci target abort interrupt enable */
+#define AD_DMA_DISR_PMAE 0x020000 /* pci master abort interrupt enable */
+/* bits 19 -> 31 reserved */
+
+/* interrupt mask */
+#define AD_INTR_MASK (AD_DMA_DISR_RESI|AD_DMA_DISR_ADCI| \
+ AD_DMA_DISR_WAVI|AD_DMA_DISR_SYNI| \
+ AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)
+
+#define AD_DMA_CHSS 0xc4 /* dma channel stop status */
+#define AD_DMA_CHSS_RESS 0x000001 /* resampler channel stopped */
+#define AD_DMA_CHSS_ADCS 0x000002 /* ADC channel stopped */
+#define AD_DMA_CHSS_SYNS 0x000004 /* synthesis channel stopped */
+#define AD_DMA_CHSS_WAVS 0x000008 /* wave channel stopped */
+
+#define AD_GPIO_IPC 0xc8 /* gpio port control */
+#define AD_GPIO_OP 0xca /* gpio output port status */
+#define AD_GPIO_IP 0xcc /* gpio input port status */
+
+#define AD_AC97_BASE 0x100 /* ac97 base register */
+
+#define AD_AC97_RESET 0x100 /* reset */
+
+#define AD_AC97_PWR_CTL 0x126 /* == AC97_POWERDOWN */
+#define AD_AC97_PWR_ADC 0x0001 /* ADC ready status */
+#define AD_AC97_PWR_DAC 0x0002 /* DAC ready status */
+#define AD_AC97_PWR_PR0 0x0100 /* PR0 (ADC) powerdown */
+#define AD_AC97_PWR_PR1 0x0200 /* PR1 (DAC) powerdown */
+
+#define AD_MISC_CTL 0x176 /* misc control */
+#define AD_MISC_CTL_DACZ 0x8000 /* set for zero fill, unset for repeat */
+#define AD_MISC_CTL_ARSR 0x0001 /* set for SR1, unset for SR0 */
+#define AD_MISC_CTL_ALSR 0x0100
+#define AD_MISC_CTL_DLSR 0x0400
+#define AD_MISC_CTL_DRSR 0x0004
+
+#define AD_AC97_SR0 0x178 /* sample rate 0, 0xbb80 == 48K */
+#define AD_AC97_SR0_48K 0xbb80 /* 48KHz */
+#define AD_AC97_SR1 0x17a /* sample rate 1 */
+
+#define AD_AC97_ACIC 0x180 /* ac97 codec interface control */
+#define AD_AC97_ACIC_ACIE 0x0001 /* analog codec interface enable */
+#define AD_AC97_ACIC_ACRD 0x0002 /* analog codec reset disable */
+#define AD_AC97_ACIC_ASOE 0x0004 /* audio stream output enable */
+#define AD_AC97_ACIC_VSRM 0x0008 /* variable sample rate mode */
+#define AD_AC97_ACIC_FSDH 0x0100 /* force SDATA_OUT high */
+#define AD_AC97_ACIC_FSYH 0x0200 /* force sync high */
+#define AD_AC97_ACIC_ACRDY 0x8000 /* analog codec ready status */
+/* bits 10 -> 14 reserved */
+
+
+#define AD_DS_MEMSIZE 512
+#define AD_OPL_MEMSIZE 16
+#define AD_MIDI_MEMSIZE 16
+
+#define AD_WAV_STATE 0
+#define AD_ADC_STATE 1
+#define AD_MAX_STATES 2
+
+#define AD_CHAN_WAV 0x0001
+#define AD_CHAN_ADC 0x0002
+#define AD_CHAN_RES 0x0004
+#define AD_CHAN_SYN 0x0008
+
+
+/* The chip would support 4 GB buffers and 16 MB periods,
+ * but let's not overdo it ... */
+#define BUFFER_BYTES_MAX (256 * 1024)
+#define PERIOD_BYTES_MIN 32
+#define PERIOD_BYTES_MAX (BUFFER_BYTES_MAX / 2)
+#define PERIODS_MIN 2
+#define PERIODS_MAX (BUFFER_BYTES_MAX / PERIOD_BYTES_MIN)
+
+#endif /* __AD1889_H__ */
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index f08ae71f902d..d683f7736a63 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -78,15 +78,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
* Constants definition
*/
-#ifndef PCI_VENDOR_ID_ALI
-#define PCI_VENDOR_ID_ALI 0x10b9
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_5451
-#define PCI_DEVICE_ID_ALI_5451 0x5451
-#endif
-
-#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_ALI<<16)|PCI_DEVICE_ID_ALI_5451)
+#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451)
#define ALI_CHANNELS 32
@@ -326,13 +318,12 @@ static void ali_read_regs(ali_t *codec, int channel)
static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
{
unsigned int dwVal;
- struct pci_dev *pci_dev = NULL;
+ struct pci_dev *pci_dev;
int i,j;
-
- pci_dev = pci_find_device(vendor, deviceid, pci_dev);
- if (pci_dev == NULL)
- return ;
+ pci_dev = pci_get_device(vendor, deviceid, NULL);
+ if (pci_dev == NULL)
+ return ;
printk("\nM%x PCI CFG\n", deviceid);
printk(" ");
@@ -349,6 +340,7 @@ static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
}
printk("\n");
}
+ pci_dev_put(pci_dev);
}
static void ali_read_ac97regs(ali_t *codec, int secondary)
{
@@ -1842,7 +1834,7 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr
return 0;
}
-struct ali_pcm_description ali_pcms[] = {
+static struct ali_pcm_description ali_pcms[] = {
{ "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
{ "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops }
};
@@ -1959,9 +1951,9 @@ static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
static snd_kcontrol_new_t snd_ali5451_mixer_spdif[] __devinitdata = {
/* spdif aplayback switch */
/* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
- ALI5451_SPDIF("IEC958 Output switch", 0, 0),
+ ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
/* spdif out to spdif channel */
- ALI5451_SPDIF("IEC958 Channel Output Switch", 0, 1),
+ ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Channel Output ",NONE,SWITCH), 0, 1),
/* spdif in from spdif channel */
ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
};
@@ -2116,6 +2108,8 @@ static int snd_ali_free(ali_t * codec)
#ifdef CONFIG_PM
kfree(codec->image);
#endif
+ pci_dev_put(codec->pci_m1533);
+ pci_dev_put(codec->pci_m7101);
kfree(codec);
return 0;
}
@@ -2249,7 +2243,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
return -ENXIO;
}
- if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL) {
+ if ((codec = kzalloc(sizeof(*codec), GFP_KERNEL)) == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
@@ -2305,7 +2299,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
codec->chregs.data.ainten = 0x00;
/* M1533: southbridge */
- pci_dev = pci_find_device(0x10b9, 0x1533, NULL);
+ pci_dev = pci_get_device(0x10b9, 0x1533, NULL);
codec->pci_m1533 = pci_dev;
if (! codec->pci_m1533) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n");
@@ -2313,7 +2307,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
return -ENODEV;
}
/* M7101: power management */
- pci_dev = pci_find_device(0x10b9, 0x7101, NULL);
+ pci_dev = pci_get_device(0x10b9, 0x7101, NULL);
codec->pci_m7101 = pci_dev;
if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
@@ -2417,6 +2411,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ALI 5451",
+ .owner = THIS_MODULE,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
.remove = __devexit_p(snd_ali_remove),
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index ca28b229c704..196ec1c61bb4 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -770,6 +770,7 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ALS4000",
+ .owner = THIS_MODULE,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
.remove = __devexit_p(snd_card_als4000_remove),
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index cafab4af5c57..241eacf1e652 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -248,6 +248,7 @@ struct snd_atiixp_dma {
unsigned int period_bytes, periods;
int opened;
int running;
+ int suspended;
int pcm_open_flag;
int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */
unsigned int saved_curptr;
@@ -699,12 +700,18 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
dma->ops->enable_transfer(chip, 1);
dma->running = 1;
+ dma->suspended = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
dma->ops->enable_transfer(chip, 0);
dma->running = 0;
+ dma->suspended = cmd == SNDRV_PCM_TRIGGER_SUSPEND;
break;
default:
err = -EINVAL;
@@ -975,6 +982,7 @@ static snd_pcm_hardware_t snd_atiixp_pcm_hw =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
@@ -1419,7 +1427,7 @@ static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
snd_atiixp_aclink_down(chip);
snd_atiixp_chip_stop(chip);
- pci_set_power_state(chip->pci, 3);
+ pci_set_power_state(chip->pci, PCI_D3hot);
pci_disable_device(chip->pci);
return 0;
}
@@ -1430,7 +1438,7 @@ static int snd_atiixp_resume(snd_card_t *card)
int i;
pci_enable_device(chip->pci);
- pci_set_power_state(chip->pci, 0);
+ pci_set_power_state(chip->pci, PCI_D0);
pci_set_master(chip->pci);
snd_atiixp_aclink_reset(chip);
@@ -1443,8 +1451,9 @@ static int snd_atiixp_resume(snd_card_t *card)
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
if (chip->pcmdevs[i]) {
atiixp_dma_t *dma = &chip->dmas[i];
- if (dma->substream && dma->running) {
+ if (dma->substream && dma->suspended) {
dma->ops->enable_dma(chip, 1);
+ dma->substream->ops->prepare(dma->substream);
writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
chip->remap_addr + dma->ops->llp_offset);
writel(dma->saved_curptr, chip->remap_addr + dma->ops->dt_cur);
@@ -1522,7 +1531,7 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1636,6 +1645,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ATI IXP AC97 controller",
+ .owner = THIS_MODULE,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 8d2002951bd7..8a59598167f9 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1208,7 +1208,7 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1318,6 +1318,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ATI IXP MC97 controller",
+ .owner = THIS_MODULE,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index f6236c63aaaa..04b695d6fd48 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -79,19 +79,21 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
{
- struct pci_dev *via;
+ struct pci_dev *via = NULL;
/* autodetect if workarounds are required */
if (fix == 255) {
/* VIA KT133 */
- via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL);
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL);
/* VIA Apollo */
if (via == NULL) {
- via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL);
- }
- /* AMD Irongate */
- if (via == NULL) {
- via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL);
+ /* AMD Irongate */
+ if (via == NULL)
+ via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
}
if (via) {
printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n");
@@ -101,13 +103,17 @@ static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
} else {
if (fix & 0x1)
vortex_fix_latency(vortex);
- if ((fix & 0x2) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL)))
+ if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL)))
vortex_fix_agp_bridge(via);
- if ((fix & 0x4) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL)))
+ if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL)))
vortex_fix_agp_bridge(via);
- if ((fix & 0x8) && (via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
+ if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
vortex_fix_agp_bridge(via);
}
+ pci_dev_put(via);
}
// component-destructor
@@ -150,7 +156,7 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
}
pci_set_dma_mask(pci, VORTEX_DMA_MASK);
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -367,6 +373,7 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
// pci_driver definition
static struct pci_driver driver = {
.name = CARD_NAME_SHORT,
+ .owner = THIS_MODULE,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
.remove = __devexit_p(snd_vortex_remove),
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 04dcefd8b8ff..38bd2b5dd434 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -33,7 +33,7 @@
/* hardware definition */
static snd_pcm_hardware_t snd_vortex_playback_hw_adb = {
.info =
- (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_RESUME |
+ (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats =
@@ -58,7 +58,7 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_adb = {
#ifndef CHIP_AU8820
static snd_pcm_hardware_t snd_vortex_playback_hw_a3d = {
.info =
- (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_RESUME |
+ (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats =
@@ -78,7 +78,7 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_a3d = {
#endif
static snd_pcm_hardware_t snd_vortex_playback_hw_spdif = {
.info =
- (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_RESUME |
+ (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats =
@@ -220,8 +220,10 @@ snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
vortex_adb_allocroute(chip, -1,
params_channels(hw_params),
substream->stream, type);
- if (dma < 0)
+ if (dma < 0) {
+ spin_unlock_irq(&chip->lock);
return dma;
+ }
stream = substream->runtime->private_data = &chip->dma_adb[dma];
stream->substream = substream;
/* Setup Buffers. */
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 72bba7b2d983..d5261bdec583 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1345,7 +1345,7 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1511,6 +1511,7 @@ static void __devexit snd_azf3328_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "AZF3328",
+ .owner = THIS_MODULE,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
.remove = __devexit_p(snd_azf3328_remove),
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index c5557eaf3e2e..2236c958aec0 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -59,16 +59,6 @@ module_param(load_all, bool, 0444);
MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards");
-#ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_878
-#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_879
-#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
-#endif
-
/* register offsets */
#define REG_INT_STAT 0x100 /* interrupt status */
#define REG_INT_MASK 0x104 /* interrupt mask */
@@ -720,7 +710,7 @@ static int __devinit snd_bt87x_create(snd_card_t *card,
if (err < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) {
pci_disable_device(pci);
return -ENOMEM;
@@ -911,6 +901,7 @@ static struct pci_device_id snd_bt87x_default_ids[] = {
static struct pci_driver driver = {
.name = "Bt87x",
+ .owner = THIS_MODULE,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
.remove = __devexit_p(snd_bt87x_remove),
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 95c289284267..ba07960921d8 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -188,6 +188,14 @@ static ca0106_details_t ca0106_chip_details[] = {
.name = "MSI K8N Diamond MB [SB0438]",
.gpio_type = 1,
.i2c_adc = 1 } ,
+ /* Shuttle XPC SD31P which has an onboard Creative Labs Sound Blaster Live! 24-bit EAX
+ * high-definition 7.1 audio processor".
+ * Added using info from andrewvegan in alsa bug #1298
+ */
+ { .serial = 0x30381297,
+ .name = "Shuttle XPC SD31P [SD31P]",
+ .gpio_type = 1,
+ .i2c_adc = 1 } ,
{ .serial = 0,
.name = "AudigyLS [Unknown]" }
};
@@ -344,7 +352,7 @@ static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
@@ -411,7 +419,7 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL) {
snd_printk("open_capture_channel: failed epcm alloc\n");
return -ENOMEM;
@@ -1136,7 +1144,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1382,6 +1390,7 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
// pci_driver definition
static struct pci_driver driver = {
.name = "CA0106",
+ .owner = THIS_MODULE,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
.remove = __devexit_p(snd_ca0106_remove),
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 0e5e9ce0ff28..c10e4a54301b 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -297,7 +297,7 @@ static int snd_ca0106_spdif_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ca0106_spdif_mask_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
.count = 4,
.info = snd_ca0106_spdif_info,
@@ -306,7 +306,7 @@ static snd_kcontrol_new_t snd_ca0106_spdif_mask_control =
static snd_kcontrol_new_t snd_ca0106_spdif_control =
{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.count = 4,
.info = snd_ca0106_spdif_info,
@@ -482,7 +482,7 @@ static int snd_ca0106_volume_put_feedback(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Front Volume",
+ .name = "Analog Front Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_front,
.put = snd_ca0106_volume_put_analog_front
@@ -490,7 +490,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Center/LFE Volume",
+ .name = "Analog Center/LFE Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_center_lfe,
.put = snd_ca0106_volume_put_analog_center_lfe
@@ -498,7 +498,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Side Volume",
+ .name = "Analog Side Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_unknown,
.put = snd_ca0106_volume_put_analog_unknown
@@ -506,7 +506,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Rear Volume",
+ .name = "Analog Rear Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_rear,
.put = snd_ca0106_volume_put_analog_rear
@@ -514,7 +514,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Front Volume",
+ .name = "SPDIF Front Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_front,
.put = snd_ca0106_volume_put_spdif_front
@@ -522,7 +522,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Center/LFE Volume",
+ .name = "SPDIF Center/LFE Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_center_lfe,
.put = snd_ca0106_volume_put_spdif_center_lfe
@@ -530,7 +530,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Unknown Volume",
+ .name = "SPDIF Unknown Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_unknown,
.put = snd_ca0106_volume_put_spdif_unknown
@@ -538,7 +538,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Rear Volume",
+ .name = "SPDIF Rear Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_rear,
.put = snd_ca0106_volume_put_spdif_rear
@@ -547,7 +547,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
static snd_kcontrol_new_t snd_ca0106_volume_control_feedback =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "CAPTURE feedback into PLAYBACK",
+ .name = "CAPTURE feedback Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_feedback,
.put = snd_ca0106_volume_put_feedback
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index f5a4ac1ceef9..1eb3315d136d 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -79,13 +79,6 @@ module_param_array(joystick_port, int, NULL, 0444);
MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
-#endif
-
/*
* CM8x38 registers definition
*/
@@ -348,25 +341,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
/*
- * pci ids
- */
-#ifndef PCI_VENDOR_ID_CMEDIA
-#define PCI_VENDOR_ID_CMEDIA 0x13F6
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A
-#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B
-#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
-#endif
-
-/*
* channels for playback / capture
*/
#define CM_CH_PLAY 0
@@ -1029,7 +1003,7 @@ static int snd_cmipci_spdif_mask_get(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_cmipci_spdif_mask __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_cmipci_spdif_mask_info,
.get = snd_cmipci_spdif_mask_get,
@@ -2801,7 +2775,7 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- cm = kcalloc(1, sizeof(*cm), GFP_KERNEL);
+ cm = kzalloc(sizeof(*cm), GFP_KERNEL);
if (cm == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -3063,6 +3037,7 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "C-Media PCI",
+ .owner = THIS_MODULE,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
.remove = __devexit_p(snd_cmipci_remove),
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index c7a370d4f923..dc87e0144b5a 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -57,17 +57,6 @@ module_param_array(dual_codec, bool, NULL, 0444);
MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
/*
- *
- */
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS 0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4281
-#define PCI_DEVICE_ID_CIRRUS_4281 0x6005
-#endif
-
-/*
* Direct registers
*/
@@ -1394,7 +1383,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2119,6 +2108,7 @@ static int cs4281_resume(snd_card_t *card)
static struct pci_driver driver = {
.name = "CS4281",
+ .owner = THIS_MODULE,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
.remove = __devexit_p(snd_cs4281_remove),
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index db212ecd792a..32b4f8465cef 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -113,7 +113,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
return err;
}
#endif
- if ((err = snd_cs46xx_mixer(chip)) < 0) {
+ if ((err = snd_cs46xx_mixer(chip, 2)) < 0) {
snd_card_free(card);
return err;
}
@@ -163,6 +163,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Sound Fusion CS46xx",
+ .owner = THIS_MODULE,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
.remove = __devexit_p(snd_card_cs46xx_remove),
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index ff28af1f658e..6e3855b8b33d 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1243,8 +1243,8 @@ static snd_pcm_hardware_t snd_cs46xx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
+ /*SNDRV_PCM_INFO_RESUME*/),
.formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
@@ -1265,8 +1265,8 @@ static snd_pcm_hardware_t snd_cs46xx_capture =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
+ /*SNDRV_PCM_INFO_RESUME*/),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5500,
@@ -1304,7 +1304,7 @@ static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pc
cs46xx_pcm_t * cpcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
+ cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
if (cpcm == NULL)
return -ENOMEM;
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
@@ -2231,7 +2231,7 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Output Switch",
+ .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
.info = snd_mixer_boolean_info,
.get = snd_cs46xx_iec958_get,
.put = snd_cs46xx_iec958_put,
@@ -2239,7 +2239,7 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Input Switch",
+ .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH),
.info = snd_mixer_boolean_info,
.get = snd_cs46xx_iec958_get,
.put = snd_cs46xx_iec958_put,
@@ -2249,7 +2249,7 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
/* Input IEC958 volume does not work for the moment. (Benny) */
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Input Volume",
+ .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME),
.info = snd_cs46xx_vol_info,
.get = snd_cs46xx_vol_iec958_get,
.put = snd_cs46xx_vol_iec958_put,
@@ -2440,7 +2440,7 @@ static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
return -ENXIO;
}
-int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
+int __devinit snd_cs46xx_mixer(cs46xx_t *chip, int spdif_device)
{
snd_card_t *card = chip->card;
snd_ctl_elem_id_t id;
@@ -2476,6 +2476,8 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
snd_kcontrol_t *kctl;
kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
+ if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM)
+ kctl->id.device = spdif_device;
if ((err = snd_ctl_add(card, kctl)) < 0)
return err;
}
@@ -3523,17 +3525,6 @@ static void amp_voyetra_4294(cs46xx_t *chip, int change)
/*
- * piix4 pci ids
- */
-#ifndef PCI_VENDOR_ID_INTEL
-#define PCI_VENDOR_ID_INTEL 0x8086
-#endif /* PCI_VENDOR_ID_INTEL */
-
-#ifndef PCI_DEVICE_ID_INTEL_82371AB_3
-#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
-#endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */
-
-/*
* Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
* whenever we need to beat on the chip.
*
@@ -3546,7 +3537,7 @@ static void clkrun_hack(cs46xx_t *chip, int change)
{
u16 control, nval;
- if (chip->acpi_dev == NULL)
+ if (!chip->acpi_port)
return;
chip->amplifier += change;
@@ -3569,15 +3560,20 @@ static void clkrun_hack(cs46xx_t *chip, int change)
*/
static void clkrun_init(cs46xx_t *chip)
{
+ struct pci_dev *pdev;
u8 pp;
- chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
- if (chip->acpi_dev == NULL)
+ chip->acpi_port = 0;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if (pdev == NULL)
return; /* Not a thinkpad thats for sure */
/* Find the control port */
- pci_read_config_byte(chip->acpi_dev, 0x41, &pp);
+ pci_read_config_byte(pdev, 0x41, &pp);
chip->acpi_port = pp << 8;
+ pci_dev_put(pdev);
}
@@ -3778,7 +3774,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index b17142cabead..b0e00f0a7c2f 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -149,7 +149,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
}
}
- if ((err = snd_emu10k1_mixer(emu)) < 0) {
+ if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) {
snd_card_free(card);
return err;
}
@@ -223,6 +223,7 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "EMU10K1_Audigy",
+ .owner = THIS_MODULE,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
.remove = __devexit_p(snd_card_emu10k1_remove),
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 746b51ef3966..e87e8427f25f 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -741,17 +741,24 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
+ /* Tested by Thomas Zehetbauer 27th Aug 2005 */
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102,
+ .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
.driver = "EMU10K1", .name = "SB Live 5.1",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
+ /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
+ .driver = "EMU10K1", .name = "SBLive! Platinum 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
- .ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
@@ -857,7 +864,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(*emu), GFP_KERNEL);
if (emu == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index e90c5ddd1d17..ad15755a63c3 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -395,7 +395,7 @@ static int snd_emu10k1x_playback_open(snd_pcm_substream_t *substream)
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
return err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = chip;
@@ -571,7 +571,7 @@ static int snd_emu10k1x_pcm_open_capture(snd_pcm_substream_t *substream)
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
return err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
@@ -920,7 +920,7 @@ static int __devinit snd_emu10k1x_create(snd_card_t *card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1183,7 +1183,7 @@ static int snd_emu10k1x_spdif_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_emu10k1x_spdif_mask_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
.count = 3,
.info = snd_emu10k1x_spdif_info,
@@ -1192,7 +1192,7 @@ static snd_kcontrol_new_t snd_emu10k1x_spdif_mask_control =
static snd_kcontrol_new_t snd_emu10k1x_spdif_control =
{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.count = 3,
.info = snd_emu10k1x_spdif_info,
@@ -1615,6 +1615,7 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
// pci_driver definition
static struct pci_driver driver = {
.name = "EMU10K1X",
+ .owner = THIS_MODULE,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
.remove = __devexit_p(snd_emu10k1x_remove),
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 0529fb281125..646b5d972e6f 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -470,7 +470,7 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr
{
u_int32_t *code;
snd_assert(*ptr < 512, return);
- code = (u_int32_t *)icode->code + (*ptr) * 2;
+ code = (u_int32_t __force *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
@@ -485,7 +485,7 @@ static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned i
{
u_int32_t *code;
snd_assert(*ptr < 1024, return);
- code = (u_int32_t *)icode->code + (*ptr) * 2;
+ code = (u_int32_t __force *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
@@ -1036,13 +1036,13 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
spin_lock_init(&emu->fx8010.irq_lock);
INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
- if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
+ if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
(icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
(controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
- gpr_map = (u32 *)icode->gpr_map;
+ gpr_map = (u32 __force *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 512;
icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1159,12 +1159,12 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* Optical SPDIF Playback Volume */
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
- snd_emu10k1_init_stereo_control(&controls[nctl++], "IEC958 Optical Playback Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0);
gpr += 2;
/* Optical SPDIF Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
- snd_emu10k1_init_stereo_control(&controls[nctl++], "IEC958 Optical Capture Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0);
gpr += 2;
/* Line2 Playback Volume */
@@ -1389,7 +1389,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
}
}
- snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "IEC958 Optical Raw Playback Switch", gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + nctl++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0);
gpr += 2;
A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -1431,7 +1431,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
__err:
kfree(controls);
if (icode != NULL) {
- kfree((void *)icode->gpr_map);
+ kfree((void __force *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -1503,15 +1503,15 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
spin_lock_init(&emu->fx8010.irq_lock);
INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
- if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
+ if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
return -ENOMEM;
if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
(controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
- (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
+ (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
- gpr_map = (u32 *)icode->gpr_map;
+ gpr_map = (u32 __force *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 256;
icode->tram_addr_map = icode->tram_data_map + 160;
@@ -1716,7 +1716,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
/* IEC958 TTL Playback Volume */
for (z = 0; z < 2; z++)
VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z);
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 TTL Playback Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0);
gpr += 2;
/* IEC958 TTL Capture Volume + Switch */
@@ -1724,8 +1724,8 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z);
VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
}
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 TTL Capture Volume", gpr, 0);
- snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 TTL Capture Switch", gpr + 2, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,SWITCH), gpr + 2, 0);
gpr += 4;
}
@@ -1750,7 +1750,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
/* IEC958 Optical Playback Volume */
for (z = 0; z < 2; z++)
VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z);
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 LiveDrive Playback Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0);
gpr += 2;
/* IEC958 Optical Capture Volume */
@@ -1758,8 +1758,8 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z);
VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
}
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 LiveDrive Capture Volume", gpr, 0);
- snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 LiveDrive Capture Switch", gpr + 2, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,SWITCH), gpr + 2, 0);
gpr += 4;
}
@@ -1784,7 +1784,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
/* IEC958 Coax Playback Volume */
for (z = 0; z < 2; z++)
VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z);
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 Coaxial Playback Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0);
gpr += 2;
/* IEC958 Coax Capture Volume + Switch */
@@ -1792,8 +1792,8 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z);
VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
}
- snd_emu10k1_init_stereo_control(controls + i++, "IEC958 Coaxial Capture Volume", gpr, 0);
- snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 Coaxial Capture Switch", gpr + 2, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,SWITCH), gpr + 2, 0);
gpr += 4;
}
@@ -1920,7 +1920,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
#endif
}
- snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 Optical Raw Playback Switch", gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0);
gpr += 2;
}
@@ -2032,7 +2032,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
kfree(ipcm);
kfree(controls);
if (icode != NULL) {
- kfree((void *)icode->gpr_map);
+ kfree((void __force *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -2217,7 +2217,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
kfree(ipcm);
return res;
case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
- ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
+ ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
if (ipcm == NULL)
return -ENOMEM;
if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 6be82c5fe138..d71a72e84bcc 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -181,7 +181,7 @@ static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
.count = 4,
.info = snd_emu10k1_spdif_info,
@@ -190,7 +190,7 @@ static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control =
static snd_kcontrol_new_t snd_emu10k1_spdif_control =
{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.count = 4,
.info = snd_emu10k1_spdif_info,
@@ -295,7 +295,7 @@ static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_emu10k1_send_routing_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "EMU10K1 PCM Send Routing",
.count = 32,
.info = snd_emu10k1_send_routing_info,
@@ -364,7 +364,7 @@ static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_emu10k1_send_volume_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "EMU10K1 PCM Send Volume",
.count = 32,
.info = snd_emu10k1_send_volume_info,
@@ -427,7 +427,7 @@ static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_emu10k1_attn_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "EMU10K1 PCM Volume",
.count = 32,
.info = snd_emu10k1_attn_info,
@@ -737,7 +737,8 @@ static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
return -ENOENT;
}
-int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
+int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
+ int pcm_device, int multi_device)
{
int err, pcm;
snd_kcontrol_t *kctl;
@@ -852,29 +853,35 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = pcm_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = pcm_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = pcm_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = multi_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = multi_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
return -ENOMEM;
+ kctl->id.device = multi_device;
if ((err = snd_ctl_add(card, kctl)))
return err;
@@ -924,10 +931,14 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
/* sb live! and audigy */
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
return -ENOMEM;
+ if (!emu->audigy)
+ kctl->id.device = emu->pcm_efx->device;
if ((err = snd_ctl_add(card, kctl)))
return err;
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
return -ENOMEM;
+ if (!emu->audigy)
+ kctl->id.device = emu->pcm_efx->device;
if ((err = snd_ctl_add(card, kctl)))
return err;
}
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 520b99af5f55..66ba27afe962 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1016,7 +1016,7 @@ static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int i;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1049,7 +1049,7 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int i, err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1094,7 +1094,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1130,7 +1130,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
emu10k1_pcm_t *epcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1170,7 +1170,7 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
int nefx = emu->audigy ? 64 : 32;
int idx;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1682,6 +1682,7 @@ static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
{
snd_pcm_t *pcm;
+ snd_kcontrol_t *kctl;
int err;
if (rpcm)
@@ -1714,7 +1715,11 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
emu->efx_voices_mask[0] = 0xffff0000;
emu->efx_voices_mask[1] = 0;
}
- snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
+ kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu);
+ if (!kctl)
+ return -ENOMEM;
+ kctl->id.device = device;
+ snd_ctl_add(emu->card, kctl);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index a1691330d3b6..d59c7f345ad6 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -178,7 +178,7 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
//snd_printk("epcm kcalloc: %p\n", epcm);
if (epcm == NULL)
@@ -214,7 +214,7 @@ static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
//snd_printk("epcm kcalloc: %p\n", epcm);
if (epcm == NULL)
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 78a81f3912a1..bef9a59f46d7 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -100,13 +100,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
#endif /* SUPPORT_JOYSTICK */
-#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
-#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
-#endif
-#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
-#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
-#endif
-
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -1444,7 +1437,7 @@ static int snd_es1371_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/* spdif controls */
static snd_kcontrol_new_t snd_es1371_mixer_spdif[] __devinitdata = {
- ES1371_SPDIF("IEC958 Playback Switch"),
+ ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1950,7 +1943,7 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
*rensoniq = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
+ ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
if (ensoniq == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2394,6 +2387,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = DRIVER_NAME,
+ .owner = THIS_MODULE,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
.remove = __devexit_p(snd_audiopci_remove),
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index b492777bc30f..17fa80c23870 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -76,13 +76,6 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
#define SUPPORT_JOYSTICK 1
#endif
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125d
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ES1938
-#define PCI_DEVICE_ID_ESS_ES1938 0x1969
-#endif
-
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
@@ -1501,7 +1494,7 @@ static int __devinit snd_es1938_create(snd_card_t * card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1753,6 +1746,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ESS ES1938 (Solo-1)",
+ .owner = THIS_MODULE,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
.remove = __devexit_p(snd_es1938_remove),
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 9d7a28783930..ecdcada90ca2 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -160,25 +160,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
-/* PCI Dev ID's */
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125D
-#endif
-
-#define PCI_VENDOR_ID_ESS_OLD 0x1285 /* Platform Tech, the people the ESS
- was bought form */
-
-#ifndef PCI_DEVICE_ID_ESS_M2E
-#define PCI_DEVICE_ID_ESS_M2E 0x1978
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M2
-#define PCI_DEVICE_ID_ESS_M2 0x1968
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M1
-#define PCI_DEVICE_ID_ESS_M1 0x0100
-#endif
-
#define NR_APUS 64
#define NR_APU_REGS 16
@@ -1596,7 +1577,7 @@ static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
if (apu1 < 0)
return apu1;
- es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+ es = kzalloc(sizeof(*es), GFP_KERNEL);
if (!es) {
snd_es1968_free_apu_pair(chip, apu1);
return -ENOMEM;
@@ -1641,7 +1622,7 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
return apu2;
}
- es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+ es = kzalloc(sizeof(*es), GFP_KERNEL);
if (!es) {
snd_es1968_free_apu_pair(chip, apu1);
snd_es1968_free_apu_pair(chip, apu2);
@@ -2588,7 +2569,7 @@ static int __devinit snd_es1968_create(snd_card_t * card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2782,6 +2763,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ES1968 (ESS Maestro)",
+ .owner = THIS_MODULE,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
.remove = __devexit_p(snd_es1968_remove),
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index ff10e637a95e..e5cfa2a0c246 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1155,10 +1155,10 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
static snd_kcontrol_new_t snd_fm801_controls_multi[] __devinitdata = {
FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0),
FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0),
-FM801_SINGLE("IEC958 Capture Switch", FM801_I2S_MODE, 8, 1, 0),
-FM801_SINGLE("IEC958 Raw Data Playback Switch", FM801_I2S_MODE, 9, 1, 0),
-FM801_SINGLE("IEC958 Raw Data Capture Switch", FM801_I2S_MODE, 10, 1, 0),
-FM801_SINGLE("IEC958 Playback Switch", FM801_GEN_CTRL, 2, 1, 0),
+FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
+FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",PLAYBACK,SWITCH), FM801_I2S_MODE, 9, 1, 0),
+FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE, 10, 1, 0),
+FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0),
};
static void snd_fm801_mixer_free_ac97_bus(ac97_bus_t *bus)
@@ -1263,7 +1263,7 @@ static int __devinit snd_fm801_create(snd_card_t * card,
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1462,6 +1462,7 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "FM801",
+ .owner = THIS_MODULE,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
.remove = __devexit_p(snd_card_fm801_remove),
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index bd8cb33c4fb4..ddfb5ff7fb8f 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o
ifdef CONFIG_PROC_FS
snd-hda-codec-objs += hda_proc.o
endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e2cf02387289..3815403ed095 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -288,7 +288,7 @@ static int init_unsol_queue(struct hda_bus *bus)
{
struct hda_bus_unsolicited *unsol;
- unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL);
+ unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
if (! unsol) {
snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
return -ENOMEM;
@@ -358,7 +358,7 @@ int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
if (busp)
*busp = NULL;
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL) {
snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
return -ENOMEM;
@@ -432,22 +432,26 @@ void snd_hda_get_codec_name(struct hda_codec *codec,
}
/*
- * look for an AFG node
- *
- * return 0 if not found
+ * look for an AFG and MFG nodes
*/
-static int look_for_afg_node(struct hda_codec *codec)
+static void setup_fg_nodes(struct hda_codec *codec)
{
int i, total_nodes;
hda_nid_t nid;
total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
for (i = 0; i < total_nodes; i++, nid++) {
- if ((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff) ==
- AC_GRP_AUDIO_FUNCTION)
- return nid;
+ switch((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff)) {
+ case AC_GRP_AUDIO_FUNCTION:
+ codec->afg = nid;
+ break;
+ case AC_GRP_MODEM_FUNCTION:
+ codec->mfg = nid;
+ break;
+ default:
+ break;
+ }
}
- return 0;
}
/*
@@ -489,7 +493,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
return -EBUSY;
}
- codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+ codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (codec == NULL) {
snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
return -ENOMEM;
@@ -507,10 +511,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID);
codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID);
- /* FIXME: support for multiple AFGs? */
- codec->afg = look_for_afg_node(codec);
- if (! codec->afg) {
- snd_printdd("hda_codec: no AFG node found\n");
+ setup_fg_nodes(codec);
+ if (! codec->afg && ! codec->mfg) {
+ snd_printdd("hda_codec: no AFG or MFG node found\n");
snd_hda_codec_free(codec);
return -ENODEV;
}
@@ -749,12 +752,14 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1)
+ if (chs & 1) {
change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
0x7f, *valp);
+ valp++;
+ }
if (chs & 2)
change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- 0x7f, valp[1]);
+ 0x7f, *valp);
return change;
}
@@ -796,12 +801,15 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1)
+ if (chs & 1) {
change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
0x80, *valp ? 0 : 0x80);
+ valp++;
+ }
if (chs & 2)
change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- 0x80, valp[1] ? 0 : 0x80);
+ 0x80, *valp ? 0 : 0x80);
+
return change;
}
@@ -1155,8 +1163,16 @@ int snd_hda_build_controls(struct hda_bus *bus)
/*
* stream formats
*/
-static unsigned int rate_bits[][3] = {
+struct hda_rate_tbl {
+ unsigned int hz;
+ unsigned int alsa_bits;
+ unsigned int hda_fmt;
+};
+
+static struct hda_rate_tbl rate_bits[] = {
/* rate in Hz, ALSA rate bitmask, HDA format value */
+
+ /* autodetected value used in snd_hda_query_supported_pcm */
{ 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
{ 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
{ 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
@@ -1168,7 +1184,11 @@ static unsigned int rate_bits[][3] = {
{ 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
- { 0 }
+
+ /* not autodetected value */
+ { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
+
+ { 0 } /* terminator */
};
/**
@@ -1190,12 +1210,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
int i;
unsigned int val = 0;
- for (i = 0; rate_bits[i][0]; i++)
- if (rate_bits[i][0] == rate) {
- val = rate_bits[i][2];
+ for (i = 0; rate_bits[i].hz; i++)
+ if (rate_bits[i].hz == rate) {
+ val = rate_bits[i].hda_fmt;
break;
}
- if (! rate_bits[i][0]) {
+ if (! rate_bits[i].hz) {
snd_printdd("invalid rate %d\n", rate);
return 0;
}
@@ -1258,9 +1278,9 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
if (ratesp) {
u32 rates = 0;
- for (i = 0; rate_bits[i][0]; i++) {
+ for (i = 0; rate_bits[i].hz; i++) {
if (val & (1 << i))
- rates |= rate_bits[i][1];
+ rates |= rate_bits[i].alsa_bits;
}
*ratesp = rates;
}
@@ -1352,13 +1372,13 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
}
rate = format & 0xff00;
- for (i = 0; rate_bits[i][0]; i++)
- if (rate_bits[i][2] == rate) {
+ for (i = 0; rate_bits[i].hz; i++)
+ if (rate_bits[i].hda_fmt == rate) {
if (val & (1 << i))
break;
return 0;
}
- if (! rate_bits[i][0])
+ if (! rate_bits[i].hz)
return 0;
stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
@@ -1541,8 +1561,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_c
for (c = tbl; c->modelname || c->pci_subvendor; c++) {
if (c->pci_subvendor == subsystem_vendor &&
(! c->pci_subdevice /* all match */||
- (c->pci_subdevice == subsystem_device)))
+ (c->pci_subdevice == subsystem_device))) {
+ snd_printdd(KERN_INFO "hda_codec: PCI %x:%x, codec config %d is selected\n",
+ subsystem_vendor, subsystem_device, c->config);
return c->config;
+ }
}
}
return -1;
@@ -1803,11 +1826,25 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
cfg->line_out_pins[j] = nid;
}
- /* Swap surround and CLFE: the association order is front/CLFE/surr/back */
- if (cfg->line_outs >= 3) {
+ /* Reorder the surround channels
+ * ALSA sequence is front/surr/clfe/side
+ * HDA sequence is:
+ * 4-ch: front/surr => OK as it is
+ * 6-ch: front/clfe/surr
+ * 8-ch: front/clfe/side/surr
+ */
+ switch (cfg->line_outs) {
+ case 3:
nid = cfg->line_out_pins[1];
cfg->line_out_pins[1] = cfg->line_out_pins[2];
cfg->line_out_pins[2] = nid;
+ break;
+ case 4:
+ nid = cfg->line_out_pins[1];
+ cfg->line_out_pins[1] = cfg->line_out_pins[3];
+ cfg->line_out_pins[3] = cfg->line_out_pins[2];
+ cfg->line_out_pins[2] = nid;
+ break;
}
return 0;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index dd0d99d2ad27..bb53bcf76742 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -505,6 +505,7 @@ struct hda_pcm_stream {
struct hda_pcm {
char *name;
struct hda_pcm_stream stream[2];
+ unsigned int is_modem; /* modem codec? */
};
/* codec information */
@@ -514,6 +515,7 @@ struct hda_codec {
struct list_head list; /* list point */
hda_nid_t afg; /* AFG node id */
+ hda_nid_t mfg; /* MFG node id */
/* ids */
u32 vendor_id;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 2d046abb5911..5b829a1a4c60 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -98,7 +98,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
struct hda_gnode *node;
int nconns;
- node = kcalloc(1, sizeof(*node), GFP_KERNEL);
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
node->nid = nid;
@@ -881,7 +881,12 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
struct hda_gspec *spec;
int err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if(!codec->afg) {
+ snd_printdd("hda_generic: no generic modem yet\n");
+ return -ENODEV;
+ }
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) {
printk(KERN_ERR "hda_generic: can't allocate spec\n");
return -ENOMEM;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 288ab0764830..9590ece2099d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -71,7 +71,9 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ESB2},"
"{ATI, SB450},"
"{VIA, VT8251},"
- "{VIA, VT8237A}}");
+ "{VIA, VT8237A},"
+ "{SiS, SIS966},"
+ "{ULI, M5461}}");
MODULE_DESCRIPTION("Intel HDA driver");
#define SFX "hda-intel: "
@@ -141,13 +143,30 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
*/
/* max number of SDs */
-#define MAX_ICH6_DEV 8
+/* ICH, ATI and VIA have 4 playback and 4 capture */
+#define ICH6_CAPTURE_INDEX 0
+#define ICH6_NUM_CAPTURE 4
+#define ICH6_PLAYBACK_INDEX 4
+#define ICH6_NUM_PLAYBACK 4
+
+/* ULI has 6 playback and 5 capture */
+#define ULI_CAPTURE_INDEX 0
+#define ULI_NUM_CAPTURE 5
+#define ULI_PLAYBACK_INDEX 5
+#define ULI_NUM_PLAYBACK 6
+
+/* this number is statically defined for simplicity */
+#define MAX_AZX_DEV 16
+
/* max number of fragments - we may use more if allocating more pages for BDL */
-#define AZX_MAX_FRAG (PAGE_SIZE / (MAX_ICH6_DEV * 16))
+#define BDL_SIZE PAGE_ALIGN(8192)
+#define AZX_MAX_FRAG (BDL_SIZE / (MAX_AZX_DEV * 16))
/* max buffer size - no h/w limit, you can increase as you like */
#define AZX_MAX_BUF_SIZE (1024*1024*1024)
/* max number of PCM devics per card */
-#define AZX_MAX_PCMS 8
+#define AZX_MAX_AUDIO_PCMS 6
+#define AZX_MAX_MODEM_PCMS 2
+#define AZX_MAX_PCMS (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
/* RIRB int mask: overrun[2], response[0] */
#define RIRB_INT_RESPONSE 0x01
@@ -194,13 +213,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* position fix mode */
enum {
- POS_FIX_FIFO,
+ POS_FIX_AUTO,
POS_FIX_NONE,
- POS_FIX_POSBUF
+ POS_FIX_POSBUF,
+ POS_FIX_FIFO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
-#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
@@ -227,6 +246,7 @@ struct snd_azx_dev {
unsigned int fragsize; /* size of each period in bytes */
unsigned int frags; /* number for period in the play buffer */
unsigned int fifo_size; /* FIFO size */
+ unsigned int last_pos; /* last updated period position */
void __iomem *sd_addr; /* stream descriptor pointer */
@@ -240,6 +260,7 @@ struct snd_azx_dev {
unsigned int opened: 1;
unsigned int running: 1;
+ unsigned int period_updating: 1;
};
/* CORB/RIRB */
@@ -258,6 +279,14 @@ struct snd_azx {
snd_card_t *card;
struct pci_dev *pci;
+ /* chip type specific */
+ int driver_type;
+ int playback_streams;
+ int playback_index_offset;
+ int capture_streams;
+ int capture_index_offset;
+ int num_streams;
+
/* pci resources */
unsigned long addr;
void __iomem *remap_addr;
@@ -267,8 +296,8 @@ struct snd_azx {
spinlock_t reg_lock;
struct semaphore open_mutex;
- /* streams */
- azx_dev_t azx_dev[MAX_ICH6_DEV];
+ /* streams (x num_streams) */
+ azx_dev_t *azx_dev;
/* PCM */
unsigned int pcm_devs;
@@ -292,6 +321,23 @@ struct snd_azx {
unsigned int initialized: 1;
};
+/* driver types */
+enum {
+ AZX_DRIVER_ICH,
+ AZX_DRIVER_ATI,
+ AZX_DRIVER_VIA,
+ AZX_DRIVER_SIS,
+ AZX_DRIVER_ULI,
+};
+
+static char *driver_short_names[] __devinitdata = {
+ [AZX_DRIVER_ICH] = "HDA Intel",
+ [AZX_DRIVER_ATI] = "HDA ATI SB",
+ [AZX_DRIVER_VIA] = "HDA VIA VT82xx",
+ [AZX_DRIVER_SIS] = "HDA SIS966",
+ [AZX_DRIVER_ULI] = "HDA ULI M5461"
+};
+
/*
* macros for easy use
*/
@@ -360,6 +406,8 @@ static void azx_init_cmd_io(azx_t *chip)
azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
+ /* set the corb size to 256 entries (ULI requires explicitly) */
+ azx_writeb(chip, CORBSIZE, 0x02);
/* set the corb write pointer to 0 */
azx_writew(chip, CORBWP, 0);
/* reset the corb hw read pointer */
@@ -373,6 +421,8 @@ static void azx_init_cmd_io(azx_t *chip)
azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
+ /* set the rirb size to 256 entries (ULI requires explicitly) */
+ azx_writeb(chip, RIRBSIZE, 0x02);
/* reset the rirb hw write pointer */
azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR);
/* set N=1, get RIRB response interrupt for new entry */
@@ -596,7 +646,7 @@ static void azx_int_disable(azx_t *chip)
int i;
/* disable interrupts in stream descriptor */
- for (i = 0; i < MAX_ICH6_DEV; i++) {
+ for (i = 0; i < chip->num_streams; i++) {
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_CTL,
azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK);
@@ -616,7 +666,7 @@ static void azx_int_clear(azx_t *chip)
int i;
/* clear stream status */
- for (i = 0; i < MAX_ICH6_DEV; i++) {
+ for (i = 0; i < chip->num_streams; i++) {
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
}
@@ -679,15 +729,12 @@ static void azx_init_chip(azx_t *chip)
/* initialize the codec command I/O */
azx_init_cmd_io(chip);
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* program the position buffer */
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
- azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
- }
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
/* For ATI SB450 azalia HD audio, we need to enable snoop */
- if (chip->pci->vendor == PCI_VENDOR_ID_ATI &&
- chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
+ if (chip->driver_type == AZX_DRIVER_ATI) {
pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
&ati_misc_cntl2);
pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
@@ -714,14 +761,16 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
- for (i = 0; i < MAX_ICH6_DEV; i++) {
+ for (i = 0; i < chip->num_streams; i++) {
azx_dev = &chip->azx_dev[i];
if (status & azx_dev->sd_int_sta_mask) {
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
if (azx_dev->substream && azx_dev->running) {
+ azx_dev->period_updating = 1;
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(azx_dev->substream);
spin_lock(&chip->reg_lock);
+ azx_dev->period_updating = 0;
}
}
}
@@ -822,11 +871,9 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
- }
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -879,9 +926,15 @@ static int __devinit azx_codec_create(azx_t *chip, const char *model)
/* assign a stream for the PCM */
static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream)
{
- int dev, i;
- dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0;
- for (i = 0; i < 4; i++, dev++)
+ int dev, i, nums;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dev = chip->playback_index_offset;
+ nums = chip->playback_streams;
+ } else {
+ dev = chip->capture_index_offset;
+ nums = chip->capture_streams;
+ }
+ for (i = 0; i < nums; i++, dev++)
if (! chip->azx_dev[dev].opened) {
chip->azx_dev[dev].opened = 1;
return &chip->azx_dev[dev];
@@ -899,8 +952,8 @@ static snd_pcm_hardware_t azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /*|*/
+ /*SNDRV_PCM_INFO_RESUME*/),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
@@ -1028,6 +1081,7 @@ static int azx_pcm_prepare(snd_pcm_substream_t *substream)
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
else
azx_dev->fifo_size = 0;
+ azx_dev->last_pos = 0;
return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
azx_dev->format_val, substream);
@@ -1049,6 +1103,7 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
azx_dev->running = 1;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
azx_stream_stop(chip, azx_dev);
azx_dev->running = 0;
@@ -1058,6 +1113,7 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
}
spin_unlock(&chip->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
+ cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
cmd == SNDRV_PCM_TRIGGER_STOP) {
int timeout = 5000;
while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout)
@@ -1081,6 +1137,26 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
pos = azx_sd_readl(azx_dev, SD_LPIB);
if (chip->position_fix == POS_FIX_FIFO)
pos += azx_dev->fifo_size;
+ else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) {
+ /* check the validity of DMA position */
+ unsigned int diff = 0;
+ azx_dev->last_pos += azx_dev->fragsize;
+ if (azx_dev->last_pos > pos)
+ diff = azx_dev->last_pos - pos;
+ if (azx_dev->last_pos >= azx_dev->bufsize) {
+ if (pos < azx_dev->fragsize)
+ diff = 0;
+ azx_dev->last_pos = 0;
+ }
+ if (diff > 0 && diff <= azx_dev->fifo_size)
+ pos += azx_dev->fifo_size;
+ else {
+ snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff);
+ chip->position_fix = POS_FIX_POSBUF;
+ pos = *azx_dev->posbuf;
+ }
+ azx_dev->period_updating = 0;
+ }
}
if (pos >= azx_dev->bufsize)
pos = 0;
@@ -1136,6 +1212,7 @@ static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec,
snd_dma_pci_data(chip->pci),
1024 * 64, 1024 * 128);
chip->pcm[pcm_dev] = pcm;
+ chip->pcm_devs = pcm_dev + 1;
return 0;
}
@@ -1150,12 +1227,33 @@ static int __devinit azx_pcm_create(azx_t *chip)
if ((err = snd_hda_build_pcms(chip->bus)) < 0)
return err;
+ /* create audio PCMs */
pcm_dev = 0;
list_for_each(p, &chip->bus->codec_list) {
codec = list_entry(p, struct hda_codec, list);
for (c = 0; c < codec->num_pcms; c++) {
+ if (codec->pcm_info[c].is_modem)
+ continue; /* create later */
+ if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+ snd_printk(KERN_ERR SFX "Too many audio PCMs\n");
+ return -EINVAL;
+ }
+ err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+ if (err < 0)
+ return err;
+ pcm_dev++;
+ }
+ }
+
+ /* create modem PCMs */
+ pcm_dev = AZX_MAX_AUDIO_PCMS;
+ list_for_each(p, &chip->bus->codec_list) {
+ codec = list_entry(p, struct hda_codec, list);
+ for (c = 0; c < codec->num_pcms; c++) {
+ if (! codec->pcm_info[c].is_modem)
+ continue; /* already created */
if (pcm_dev >= AZX_MAX_PCMS) {
- snd_printk(KERN_ERR SFX "Too many PCMs\n");
+ snd_printk(KERN_ERR SFX "Too many modem PCMs\n");
return -EINVAL;
}
err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
@@ -1186,13 +1284,12 @@ static int __devinit azx_init_stream(azx_t *chip)
/* initialize each stream (aka device)
* assign the starting bdl address to each stream (device) and initialize
*/
- for (i = 0; i < MAX_ICH6_DEV; i++) {
+ for (i = 0; i < chip->num_streams; i++) {
unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
- if (chip->position_fix == POS_FIX_POSBUF)
- azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1245,7 +1342,7 @@ static int azx_free(azx_t *chip)
if (chip->initialized) {
int i;
- for (i = 0; i < MAX_ICH6_DEV; i++)
+ for (i = 0; i < chip->num_streams; i++)
azx_stream_stop(chip, &chip->azx_dev[i]);
/* disable interrupts */
@@ -1261,10 +1358,10 @@ static int azx_free(azx_t *chip)
/* wait a little for interrupts to finish */
msleep(1);
-
- iounmap(chip->remap_addr);
}
+ if (chip->remap_addr)
+ iounmap(chip->remap_addr);
if (chip->irq >= 0)
free_irq(chip->irq, (void*)chip);
@@ -1276,6 +1373,7 @@ static int azx_free(azx_t *chip)
snd_dma_free_pages(&chip->posbuf);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
+ kfree(chip->azx_dev);
kfree(chip);
return 0;
@@ -1290,7 +1388,8 @@ static int azx_dev_free(snd_device_t *device)
* constructor
*/
static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
- int posfix, azx_t **rchip)
+ int posfix, int driver_type,
+ azx_t **rchip)
{
azx_t *chip;
int err = 0;
@@ -1303,7 +1402,7 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (NULL == chip) {
snd_printk(KERN_ERR SFX "cannot allocate chip\n");
@@ -1316,9 +1415,20 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+ chip->driver_type = driver_type;
chip->position_fix = posfix;
+#if BITS_PER_LONG != 64
+ /* Fix up base address on ULI M5461 */
+ if (chip->driver_type == AZX_DRIVER_ULI) {
+ u16 tmp3;
+ pci_read_config_word(pci, 0x40, &tmp3);
+ pci_write_config_word(pci, 0x40, tmp3 | 0x10);
+ pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0);
+ }
+#endif
+
if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
kfree(chip);
pci_disable_device(pci);
@@ -1344,19 +1454,38 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
pci_set_master(pci);
synchronize_irq(chip->irq);
+ switch (chip->driver_type) {
+ case AZX_DRIVER_ULI:
+ chip->playback_streams = ULI_NUM_PLAYBACK;
+ chip->capture_streams = ULI_NUM_CAPTURE;
+ chip->playback_index_offset = ULI_PLAYBACK_INDEX;
+ chip->capture_index_offset = ULI_CAPTURE_INDEX;
+ break;
+ default:
+ chip->playback_streams = ICH6_NUM_PLAYBACK;
+ chip->capture_streams = ICH6_NUM_CAPTURE;
+ chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
+ chip->capture_index_offset = ICH6_CAPTURE_INDEX;
+ break;
+ }
+ chip->num_streams = chip->playback_streams + chip->capture_streams;
+ chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL);
+ if (! chip->azx_dev) {
+ snd_printk(KERN_ERR "cannot malloc azx_dev\n");
+ goto errout;
+ }
+
/* allocate memory for the BDL for each stream */
if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- PAGE_SIZE, &chip->bdl)) < 0) {
+ BDL_SIZE, &chip->bdl)) < 0) {
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
- goto errout;
- }
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ chip->num_streams * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
}
/* allocate CORB/RIRB */
if ((err = azx_alloc_cmd_io(chip)) < 0)
@@ -1382,6 +1511,10 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
goto errout;
}
+ strcpy(card->driver, "HDA-Intel");
+ strcpy(card->shortname, driver_short_names[chip->driver_type]);
+ sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
+
*rchip = chip;
return 0;
@@ -1410,15 +1543,12 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
return -ENOMEM;
}
- if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
+ if ((err = azx_create(card, pci, position_fix[dev], pci_id->driver_data,
+ &chip)) < 0) {
snd_card_free(card);
return err;
}
- strcpy(card->driver, "HDA-Intel");
- strcpy(card->shortname, "HDA Intel");
- sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
-
/* create codec instances */
if ((err = azx_codec_create(chip, model[dev])) < 0) {
snd_card_free(card);
@@ -1459,12 +1589,13 @@ static void __devexit azx_remove(struct pci_dev *pci)
/* PCI IDs */
static struct pci_device_id azx_ids[] = {
- { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
- { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
- { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
- { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
- { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
- { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
+ { 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 */
+ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+ { 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 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -1472,6 +1603,7 @@ MODULE_DEVICE_TABLE(pci, azx_ids);
/* pci_driver definition */
static struct pci_driver driver = {
.name = "HDA Intel",
+ .owner = THIS_MODULE,
.id_table = azx_ids,
.probe = azx_probe,
.remove = __devexit_p(azx_remove),
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index a5de684b6944..acaef3c811b8 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -10,11 +10,14 @@ extern struct hda_codec_preset snd_hda_preset_cmedia[];
extern struct hda_codec_preset snd_hda_preset_analog[];
/* SigmaTel codecs */
extern struct hda_codec_preset snd_hda_preset_sigmatel[];
+/* SiLabs 3054/3055 modem codecs */
+extern struct hda_codec_preset snd_hda_preset_si3054[];
static const struct hda_codec_preset *hda_preset_tables[] = {
snd_hda_preset_realtek,
snd_hda_preset_cmedia,
snd_hda_preset_analog,
snd_hda_preset_sigmatel,
+ snd_hda_preset_si3054,
NULL
};
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index de1217bd8e68..08f6a6efc5e6 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -207,6 +207,8 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+ if (! codec->afg)
+ return;
snd_iprintf(buffer, "Default PCM: ");
print_pcm_caps(buffer, codec, codec->afg);
snd_iprintf(buffer, "Default Amp-In caps: ");
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2fd05bb84136..da6874d3988c 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -465,7 +465,7 @@ static int patch_ad1986a(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -572,7 +572,7 @@ static snd_kcontrol_new_t ad1983_mixers[] = {
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = ad1983_spdif_route_info,
.get = ad1983_spdif_route_get,
.put = ad1983_spdif_route_put,
@@ -623,7 +623,7 @@ static int patch_ad1983(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -705,7 +705,7 @@ static snd_kcontrol_new_t ad1981_mixers[] = {
/* identical with AD1983 */
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = ad1983_spdif_route_info,
.get = ad1983_spdif_route_get,
.put = ad1983_spdif_route_put,
@@ -764,7 +764,7 @@ static int patch_ad1981(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 86f195f19eef..523c362ec44d 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -647,6 +647,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = {
{ .modelname = "min_fp", .config = CMI_MIN_FP },
{ .modelname = "full", .config = CMI_FULL },
{ .modelname = "full_dig", .config = CMI_FULL_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x813d, .config = CMI_FULL_DIG }, /* ASUS P5AD2 */
{ .modelname = "allout", .config = CMI_ALLOUT },
{ .modelname = "auto", .config = CMI_AUTO },
{} /* terminator */
@@ -666,7 +667,7 @@ static int patch_cmi9880(struct hda_codec *codec)
{
struct cmi_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9b8569900787..849b5b50c921 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -687,6 +687,12 @@ static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
{ } /* end */
};
+/* additional mixers to alc880_asus_mixer */
+static snd_kcontrol_new_t alc880_pcbeep_mixer[] = {
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ { } /* end */
+};
/*
* build control elements
@@ -1520,10 +1526,12 @@ static struct hda_board_config alc880_cfg_tbl[] = {
/* Back 3 jack, front 2 jack (Internal add Aux-In) */
{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
+ { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
@@ -1574,6 +1582,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
@@ -1734,7 +1743,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_capture_source,
},
[ALC880_UNIWILL_DIG] = {
- .mixers = { alc880_asus_mixer },
+ .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
.dac_nids = alc880_asus_dac_nids,
@@ -2086,7 +2095,7 @@ static int patch_alc880(struct hda_codec *codec)
int board_config;
int i, err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -2358,7 +2367,7 @@ static int patch_alc260(struct hda_codec *codec)
struct alc_spec *spec;
int board_config;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -2608,7 +2617,7 @@ static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
new file mode 100644
index 000000000000..d014b7bb70df
--- /dev/null
+++ b/sound/pci/hda/patch_si3054.c
@@ -0,0 +1,301 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for Silicon Labs 3054/5 modem codec
+ *
+ * Copyright (c) 2005 Sasha Khapyorsky <sashak@smlink.com>
+ * Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* si3054 verbs */
+#define SI3054_VERB_READ_NODE 0x900
+#define SI3054_VERB_WRITE_NODE 0x100
+
+/* si3054 nodes (registers) */
+#define SI3054_EXTENDED_MID 2
+#define SI3054_LINE_RATE 3
+#define SI3054_LINE_LEVEL 4
+#define SI3054_GPIO_CFG 5
+#define SI3054_GPIO_POLARITY 6
+#define SI3054_GPIO_STICKY 7
+#define SI3054_GPIO_WAKEUP 8
+#define SI3054_GPIO_STATUS 9
+#define SI3054_GPIO_CONTROL 10
+#define SI3054_MISC_AFE 11
+#define SI3054_CHIPID 12
+#define SI3054_LINE_CFG1 13
+#define SI3054_LINE_STATUS 14
+#define SI3054_DC_TERMINATION 15
+#define SI3054_LINE_CONFIG 16
+#define SI3054_CALLPROG_ATT 17
+#define SI3054_SQ_CONTROL 18
+#define SI3054_MISC_CONTROL 19
+#define SI3054_RING_CTRL1 20
+#define SI3054_RING_CTRL2 21
+
+/* extended MID */
+#define SI3054_MEI_READY 0xf
+
+/* line level */
+#define SI3054_ATAG_MASK 0x00f0
+#define SI3054_DTAG_MASK 0xf000
+
+/* GPIO bits */
+#define SI3054_GPIO_OH 0x0001
+#define SI3054_GPIO_CID 0x0002
+
+/* chipid and revisions */
+#define SI3054_CHIPID_CODEC_REV_MASK 0x000f
+#define SI3054_CHIPID_DAA_REV_MASK 0x00f0
+#define SI3054_CHIPID_INTERNATIONAL 0x0100
+#define SI3054_CHIPID_DAA_ID 0x0f00
+#define SI3054_CHIPID_CODEC_ID (1<<12)
+
+/* si3054 codec registers (nodes) access macros */
+#define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0))
+#define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val))
+
+
+struct si3054_spec {
+ unsigned international;
+ struct hda_pcm pcm;
+};
+
+
+/*
+ * Modem mixer
+ */
+
+#define PRIVATE_VALUE(reg,mask) ((reg<<16)|(mask&0xffff))
+#define PRIVATE_REG(val) ((val>>16)&0xffff)
+#define PRIVATE_MASK(val) (val&0xffff)
+
+static int si3054_switch_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int si3054_switch_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *uvalue)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 reg = PRIVATE_REG(kcontrol->private_value);
+ u16 mask = PRIVATE_MASK(kcontrol->private_value);
+ uvalue->value.integer.value[0] = (GET_REG(codec, reg)) & mask ? 1 : 0 ;
+ return 0;
+}
+
+static int si3054_switch_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *uvalue)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 reg = PRIVATE_REG(kcontrol->private_value);
+ u16 mask = PRIVATE_MASK(kcontrol->private_value);
+ if (uvalue->value.integer.value[0])
+ SET_REG(codec, reg, (GET_REG(codec, reg)) | mask);
+ else
+ SET_REG(codec, reg, (GET_REG(codec, reg)) & ~mask);
+ return 0;
+}
+
+#define SI3054_KCONTROL(kname,reg,mask) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = kname, \
+ .info = si3054_switch_info, \
+ .get = si3054_switch_get, \
+ .put = si3054_switch_put, \
+ .private_value = PRIVATE_VALUE(reg,mask), \
+}
+
+
+static snd_kcontrol_new_t si3054_modem_mixer[] = {
+ SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH),
+ SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID),
+ {}
+};
+
+static int si3054_build_controls(struct hda_codec *codec)
+{
+ return snd_hda_add_new_ctls(codec, si3054_modem_mixer);
+}
+
+
+/*
+ * PCM callbacks
+ */
+
+static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ u16 val;
+
+ SET_REG(codec, SI3054_LINE_RATE, substream->runtime->rate);
+ val = GET_REG(codec, SI3054_LINE_LEVEL);
+ val &= 0xff << (8 * (substream->stream != SNDRV_PCM_STREAM_PLAYBACK));
+ val |= ((stream_tag & 0xf) << 4) << (8 * (substream->stream == SNDRV_PCM_STREAM_PLAYBACK));
+ SET_REG(codec, SI3054_LINE_LEVEL, val);
+
+ snd_hda_codec_setup_stream(codec, hinfo->nid,
+ stream_tag, 0, format);
+ return 0;
+}
+
+static int si3054_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ static unsigned int rates[] = { 8000, 9600, 16000 };
+ static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ substream->runtime->hw.period_bytes_min = 80;
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+}
+
+
+static struct hda_pcm_stream si3054_pcm = {
+ .substreams = 1,
+ .channels_min = 1,
+ .channels_max = 1,
+ .nid = 0x1,
+ .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_KNOT,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .maxbps = 16,
+ .ops = {
+ .open = si3054_pcm_open,
+ .prepare = si3054_pcm_prepare,
+ },
+};
+
+
+static int si3054_build_pcms(struct hda_codec *codec)
+{
+ struct si3054_spec *spec = codec->spec;
+ struct hda_pcm *info = &spec->pcm;
+ si3054_pcm.nid = codec->mfg;
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+ info->name = "Si3054 Modem";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
+ info->is_modem = 1;
+ return 0;
+}
+
+
+/*
+ * Init part
+ */
+
+static int si3054_init(struct hda_codec *codec)
+{
+ struct si3054_spec *spec = codec->spec;
+ unsigned wait_count;
+ u16 val;
+
+ snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
+ snd_hda_codec_write(codec, codec->mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0);
+ SET_REG(codec, SI3054_LINE_RATE, 9600);
+ SET_REG(codec, SI3054_LINE_LEVEL, SI3054_DTAG_MASK|SI3054_ATAG_MASK);
+ SET_REG(codec, SI3054_EXTENDED_MID, 0);
+
+ wait_count = 10;
+ do {
+ msleep(2);
+ val = GET_REG(codec, SI3054_EXTENDED_MID);
+ } while ((val & SI3054_MEI_READY) != SI3054_MEI_READY && wait_count--);
+
+ if((val&SI3054_MEI_READY) != SI3054_MEI_READY) {
+ snd_printk(KERN_ERR "si3054: cannot initialize. EXT MID = %04x\n", val);
+ return -EACCES;
+ }
+
+ SET_REG(codec, SI3054_GPIO_POLARITY, 0xffff);
+ SET_REG(codec, SI3054_GPIO_CFG, 0x0);
+ SET_REG(codec, SI3054_MISC_AFE, 0);
+ SET_REG(codec, SI3054_LINE_CFG1,0x200);
+
+ if((GET_REG(codec,SI3054_LINE_STATUS) & (1<<6)) == 0) {
+ snd_printd("Link Frame Detect(FDT) is not ready (line status: %04x)\n",
+ GET_REG(codec,SI3054_LINE_STATUS));
+ }
+
+ spec->international = GET_REG(codec, SI3054_CHIPID) & SI3054_CHIPID_INTERNATIONAL;
+
+ return 0;
+}
+
+static void si3054_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+
+/*
+ */
+
+static struct hda_codec_ops si3054_patch_ops = {
+ .build_controls = si3054_build_controls,
+ .build_pcms = si3054_build_pcms,
+ .init = si3054_init,
+ .free = si3054_free,
+#ifdef CONFIG_PM
+ //.suspend = si3054_suspend,
+ .resume = si3054_init,
+#endif
+};
+
+static int patch_si3054(struct hda_codec *codec)
+{
+ struct si3054_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+ codec->spec = spec;
+ codec->patch_ops = si3054_patch_ops;
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_si3054[] = {
+ { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
+ {}
+};
+
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9d503da7320d..33a8adaea768 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -919,7 +919,7 @@ static int patch_stac9200(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -957,7 +957,7 @@ static int patch_stac922x(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 4405d96cbedf..2e0a31613ee6 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1796,7 +1796,7 @@ static int __devinit aureon_init(ice1712_t *ice)
}
/* to remeber the register values of CS8415 */
- ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ice->akm)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index eb20f73be61a..39fbe662965d 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -618,15 +618,15 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
*/
static snd_kcontrol_new_t snd_ice1712_delta1010_wordclock_select __devinitdata =
-ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
+ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
static snd_kcontrol_new_t snd_ice1712_delta1010lt_wordclock_select __devinitdata =
-ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 1, 0);
+ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 1, 0);
static snd_kcontrol_new_t snd_ice1712_delta1010_wordclock_status __devinitdata =
-ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
+ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
static snd_kcontrol_new_t snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
-ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
+ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
static snd_kcontrol_new_t snd_ice1712_delta_spdif_in_status __devinitdata =
-ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
+ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index a2545a5b26c4..a6d98013c331 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -100,12 +100,6 @@ MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec r
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE 0x1412
-#endif
-#ifndef PCI_DEVICE_ID_ICE_1712
-#define PCI_DEVICE_ID_ICE_1712 0x1712
-#endif
static struct pci_device_id snd_ice1712_ids[] = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */
@@ -1422,7 +1416,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_switch __devinitdata
static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_switch __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Multi Capture Switch",
+ .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH),
.info = snd_ice1712_pro_mixer_switch_info,
.get = snd_ice1712_pro_mixer_switch_get,
.put = snd_ice1712_pro_mixer_switch_put,
@@ -1441,7 +1435,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_volume __devinitdata
static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_volume __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Multi Capture Volume",
+ .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME),
.info = snd_ice1712_pro_mixer_volume_info,
.get = snd_ice1712_pro_mixer_volume_get,
.put = snd_ice1712_pro_mixer_volume_put,
@@ -1715,7 +1709,7 @@ static int snd_ice1712_spdif_maskp_get(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskc_get,
@@ -1724,7 +1718,7 @@ static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
static snd_kcontrol_new_t snd_ice1712_spdif_maskp __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskp_get,
@@ -2203,7 +2197,7 @@ static snd_kcontrol_new_t snd_ice1712_mixer_pro_analog_route __devinitdata = {
static snd_kcontrol_new_t snd_ice1712_mixer_pro_spdif_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = snd_ice1712_pro_route_info,
.get = snd_ice1712_pro_route_spdif_get,
.put = snd_ice1712_pro_route_spdif_put,
@@ -2535,7 +2529,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
return -ENXIO;
}
- ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+ ice = kzalloc(sizeof(*ice), GFP_KERNEL);
if (ice == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2741,6 +2735,7 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ICE1712",
+ .owner = THIS_MODULE,
.id_table = snd_ice1712_ids,
.probe = snd_ice1712_probe,
.remove = __devexit_p(snd_ice1712_remove),
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 79b5f12e06fc..c3ce8f93740b 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -83,12 +83,6 @@ MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE 0x1412
-#endif
-#ifndef PCI_DEVICE_ID_VT1724
-#define PCI_DEVICE_ID_VT1724 0x1724
-#endif
/* Both VT1720 and VT1724 have the same PCI IDs */
static struct pci_device_id snd_vt1724_ids[] = {
@@ -1414,7 +1408,7 @@ static int snd_vt1724_spdif_maskp_get(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_vt1724_spdif_maskc __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_vt1724_spdif_info,
.get = snd_vt1724_spdif_maskc_get,
@@ -1423,7 +1417,7 @@ static snd_kcontrol_new_t snd_vt1724_spdif_maskc __devinitdata =
static snd_kcontrol_new_t snd_vt1724_spdif_maskp __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_vt1724_spdif_info,
.get = snd_vt1724_spdif_maskp_get,
@@ -1466,7 +1460,7 @@ static snd_kcontrol_new_t snd_vt1724_spdif_switch __devinitdata =
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* FIXME: the following conflict with IEC958 Playback Route */
// .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
- .name = "IEC958 Output Switch",
+ .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
.info = snd_vt1724_spdif_sw_info,
.get = snd_vt1724_spdif_sw_get,
.put = snd_vt1724_spdif_sw_put
@@ -2130,7 +2124,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+ ice = kzalloc(sizeof(*ice), GFP_KERNEL);
if (ice == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2321,6 +2315,7 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ICE1724",
+ .owner = THIS_MODULE,
.id_table = snd_vt1724_ids,
.probe = snd_vt1724_probe,
.remove = __devexit_p(snd_vt1724_remove),
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 3fb297b969cd..2437876a44e4 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -182,7 +182,7 @@ static int __devinit juli_init(ice1712_t *ice)
ice->num_total_dacs = 2;
ice->num_total_adcs = 2;
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index 5bf734b04fa0..dcf1e8ca3f66 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -122,7 +122,7 @@ static int __devinit phase22_init(ice1712_t *ice)
}
// Initialize analog chips
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -386,7 +386,7 @@ static int __devinit phase28_init(ice1712_t *ice)
ice->num_total_adcs = 2;
// Initialize analog chips
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (!ak)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 25f827d8fbd9..a5f852b1f575 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -781,7 +781,7 @@ static int __devinit pontis_init(ice1712_t *ice)
ice->num_total_adcs = 2;
/* to remeber the register values */
- ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ice->akm)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index d7af3e474432..1a96198a17ae 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -69,6 +69,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static char *ac97_quirk[SNDRV_CARDS];
+static int buggy_semaphore[SNDRV_CARDS];
static int buggy_irq[SNDRV_CARDS];
static int xbox[SNDRV_CARDS];
@@ -86,6 +87,8 @@ module_param_array(ac97_clock, int, NULL, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+module_param_array(buggy_semaphore, bool, NULL, 0444);
+MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores.");
module_param_array(buggy_irq, bool, NULL, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
module_param_array(xbox, bool, NULL, 0444);
@@ -94,62 +97,6 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c
/*
* Direct registers
*/
-
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801 0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901 0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA
-#define PCI_DEVICE_ID_INTEL_82801BA 0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX 0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3 0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4 0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5 0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
-#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
-#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB2_14
-#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012 0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO 0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea
-#endif
-
enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
#define ICHREG(x) ICH_REG_##x
@@ -389,6 +336,7 @@ typedef struct {
struct ac97_pcm *pcm;
int pcm_open_flag;
unsigned int page_attr_changed: 1;
+ unsigned int suspended: 1;
} ichdev_t;
typedef struct _snd_intel8x0 intel8x0_t;
@@ -422,6 +370,7 @@ struct _snd_intel8x0 {
unsigned fix_nocache: 1; /* workaround for 440MX */
unsigned buggy_irq: 1; /* workaround for buggy mobos */
unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
+ unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
unsigned int sdm_saved; /* SDM reg value */
@@ -576,6 +525,9 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0)
return -EIO;
+ if (chip->buggy_semaphore)
+ return 0; /* just ignore ... */
+
/* Anyone holding a semaphore for 1 msec should be shot... */
time = 100;
do {
@@ -862,12 +814,16 @@ static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
unsigned long port = ichdev->reg_offset;
switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
+ ichdev->suspended = 0;
+ /* fallthru */
+ case SNDRV_PCM_TRIGGER_START:
val = ICH_IOCE | ICH_STARTBM;
break;
- case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
+ ichdev->suspended = 1;
+ /* fallthru */
+ case SNDRV_PCM_TRIGGER_STOP:
val = 0;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -899,9 +855,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
val = igetdword(chip, ICHREG(ALI_DMACR));
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ ichdev->suspended = 0;
+ /* fallthru */
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* clear FIFO for synchronization of channels */
fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]);
@@ -913,9 +871,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */
iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */
break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ ichdev->suspended = 1;
+ /* fallthru */
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */
iputbyte(chip, port + ICH_REG_OFF_CR, 0);
while (igetbyte(chip, port + ICH_REG_OFF_CR))
@@ -994,6 +954,8 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
{
unsigned int cnt;
int dbl = runtime->rate > 48000;
+
+ spin_lock_irq(&chip->reg_lock);
switch (chip->device_type) {
case DEVICE_ALI:
cnt = igetdword(chip, ICHREG(ALI_SCR));
@@ -1037,6 +999,7 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
iputdword(chip, ICHREG(GLOB_CNT), cnt);
break;
}
+ spin_unlock_irq(&chip->reg_lock);
}
static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
@@ -1048,15 +1011,12 @@ static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
ichdev->physbuf = runtime->dma_addr;
ichdev->size = snd_pcm_lib_buffer_bytes(substream);
ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
- spin_lock_irq(&chip->reg_lock);
if (ichdev->ichd == ICHD_PCMOUT) {
snd_intel8x0_setup_pcm_out(chip, runtime);
- if (chip->device_type == DEVICE_INTEL_ICH4) {
+ if (chip->device_type == DEVICE_INTEL_ICH4)
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
- }
}
snd_intel8x0_setup_periods(chip, ichdev);
- spin_unlock_irq(&chip->reg_lock);
return 0;
}
@@ -1750,6 +1710,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_ALC_JACK
},
{
+ .subvendor = 0x1014,
+ .subdevice = 0x0267,
+ .name = "IBM NetVista A30p", /* AD1981B */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
.subvendor = 0x1028,
.subdevice = 0x00d8,
.name = "Dell Precision 530", /* AD1885 */
@@ -1817,6 +1783,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x103c,
+ .subdevice = 0x0934,
+ .name = "HP nx8220",
+ .type = AC97_TUNE_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x099c,
+ .name = "HP nx6110", /* AD1981B */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .subvendor = 0x103c,
.subdevice = 0x129d,
.name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
@@ -1870,6 +1848,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_HP_ONLY
},
{
+ .subvendor = 0x10cf,
+ .subdevice = 0x12ec,
+ .name = "Fujitsu-Siemens 4010",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
.subvendor = 0x10f1,
.subdevice = 0x2665,
.name = "Fujitsu-Siemens Celsius", /* AD1981? */
@@ -2424,6 +2408,20 @@ static int intel8x0_resume(snd_card_t *card)
}
}
+ /* resume status */
+ for (i = 0; i < chip->bdbars_count; i++) {
+ ichdev_t *ichdev = &chip->ichd[i];
+ unsigned long port = ichdev->reg_offset;
+ if (! ichdev->substream || ! ichdev->suspended)
+ continue;
+ if (ichdev->ichd == ICHD_PCMOUT)
+ snd_intel8x0_setup_pcm_out(chip, ichdev->substream->runtime);
+ iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr);
+ iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
+ iputbyte(chip, port + ICH_REG_OFF_CIV, ichdev->civ);
+ iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
+ }
+
return 0;
}
#endif /* CONFIG_PM */
@@ -2558,6 +2556,7 @@ struct ich_reg_info {
static int __devinit snd_intel8x0_create(snd_card_t * card,
struct pci_dev *pci,
unsigned long device_type,
+ int buggy_sem,
intel8x0_t ** r_intel8x0)
{
intel8x0_t *chip;
@@ -2605,7 +2604,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2615,6 +2614,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+ chip->buggy_semaphore = buggy_sem;
if (pci->vendor == PCI_VENDOR_ID_INTEL &&
pci->device == PCI_DEVICE_ID_INTEL_440MX)
@@ -2754,19 +2754,19 @@ static struct shortname_table {
unsigned int id;
const char *s;
} shortnames[] __devinitdata = {
- { PCI_DEVICE_ID_INTEL_82801, "Intel 82801AA-ICH" },
- { PCI_DEVICE_ID_INTEL_82901, "Intel 82901AB-ICH0" },
- { PCI_DEVICE_ID_INTEL_82801BA, "Intel 82801BA-ICH2" },
+ { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
+ { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
+ { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
{ PCI_DEVICE_ID_INTEL_440MX, "Intel 440MX" },
- { PCI_DEVICE_ID_INTEL_ICH3, "Intel 82801CA-ICH3" },
- { PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
- { PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
+ { PCI_DEVICE_ID_INTEL_82801CA_5, "Intel 82801CA-ICH3" },
+ { PCI_DEVICE_ID_INTEL_82801DB_5, "Intel 82801DB-ICH4" },
+ { PCI_DEVICE_ID_INTEL_82801EB_5, "Intel ICH5" },
{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
{ PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
{ PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" },
{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
- { PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
+ { PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, "NVidia nForce" },
{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
@@ -2819,7 +2819,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
}
}
- if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip)) < 0) {
+ if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
+ buggy_semaphore[dev], &chip)) < 0) {
snd_card_free(card);
return err;
}
@@ -2863,6 +2864,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Intel ICH",
+ .owner = THIS_MODULE,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
.remove = __devexit_p(snd_intel8x0_remove),
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index bb758c77d211..9e2060d56c24 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -73,51 +73,6 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
/*
* Direct registers
*/
-
-#ifndef PCI_DEVICE_ID_INTEL_82801_6
-#define PCI_DEVICE_ID_INTEL_82801_6 0x2416
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901_6
-#define PCI_DEVICE_ID_INTEL_82901_6 0x2426
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA_6
-#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2446
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX_6
-#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3_6
-#define PCI_DEVICE_ID_INTEL_ICH3_6 0x2486
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4_6
-#define PCI_DEVICE_ID_INTEL_ICH4_6 0x24c6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5_6
-#define PCI_DEVICE_ID_INTEL_ICH5_6 0x24d6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_6
-#define PCI_DEVICE_ID_INTEL_ICH6_6 0x266d
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_6
-#define PCI_DEVICE_ID_INTEL_ICH7_6 0x27dd
-#endif
-#ifndef PCI_DEVICE_ID_SI_7013
-#define PCI_DEVICE_ID_SI_7013 0x7013
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP_MODEM 0x01c1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9
-#endif
-
-
enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
#define ICHREG(x) ICH_REG_##x
@@ -1158,7 +1113,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1283,18 +1238,18 @@ static struct shortname_table {
unsigned int id;
const char *s;
} shortnames[] __devinitdata = {
- { PCI_DEVICE_ID_INTEL_82801_6, "Intel 82801AA-ICH" },
- { PCI_DEVICE_ID_INTEL_82901_6, "Intel 82901AB-ICH0" },
+ { PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
+ { PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
{ PCI_DEVICE_ID_INTEL_440MX_6, "Intel 440MX" },
- { PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" },
- { PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
- { PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
- { PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" },
- { PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" },
+ { PCI_DEVICE_ID_INTEL_82801CA_6, "Intel 82801CA-ICH3" },
+ { PCI_DEVICE_ID_INTEL_82801DB_6, "Intel 82801DB-ICH4" },
+ { PCI_DEVICE_ID_INTEL_82801EB_6, "Intel ICH5" },
+ { PCI_DEVICE_ID_INTEL_ICH6_17, "Intel ICH6" },
+ { PCI_DEVICE_ID_INTEL_ICH7_19, "Intel ICH7" },
{ 0x7446, "AMD AMD768" },
{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
- { PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
+ { PCI_DEVICE_ID_NVIDIA_MCP1_MODEM, "NVidia nForce" },
{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
@@ -1371,6 +1326,7 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Intel ICH Modem",
+ .owner = THIS_MODULE,
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
.remove = __devexit_p(snd_intel8x0m_remove),
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 79d8eda54f0d..09f9cbe116a3 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2067,7 +2067,7 @@ static int snd_korg1212_control_sync_put(snd_kcontrol_t * kcontrol, snd_ctl_elem
}, \
{ \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \
- .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = c_name " Monitor Phase Invert", \
.info = snd_korg1212_control_phase_info, \
.get = snd_korg1212_control_phase_get, \
@@ -2082,7 +2082,7 @@ static snd_kcontrol_new_t snd_korg1212_controls[] = {
MON_MIXER(4, "ADAT-5"), MON_MIXER(5, "ADAT-6"), MON_MIXER(6, "ADAT-7"), MON_MIXER(7, "ADAT-8"),
{
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Sync Source",
.info = snd_korg1212_control_sync_info,
.get = snd_korg1212_control_sync_get,
@@ -2220,7 +2220,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL);
+ korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
if (korg1212 == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2534,6 +2534,7 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "korg1212",
+ .owner = THIS_MODULE,
.id_table = snd_korg1212_ids,
.probe = snd_korg1212_probe,
.remove = __devexit_p(snd_korg1212_remove),
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 39b5e7db1543..2693b6f731f3 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -872,35 +872,6 @@ struct snd_m3 {
/*
* pci ids
*/
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125D
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO_1
-#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO
-#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2LE
-#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2
-#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3
-#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_1
-#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_HW
-#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_2
-#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b
-#endif
-
static struct pci_device_id snd_m3_ids[] = {
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
@@ -2689,7 +2660,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2890,6 +2861,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Maestro3",
+ .owner = THIS_MODULE,
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
.remove = __devexit_p(snd_m3_remove),
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 6c868d913634..1a62c7f6c52b 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1004,7 +1004,7 @@ static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int
.dev_free = snd_mixart_chip_dev_free,
};
- mgr->chip[idx] = chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1292,7 +1292,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
/*
*/
- mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL);
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
if (! mgr) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1424,6 +1424,7 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Digigram miXart",
+ .owner = THIS_MODULE,
.id_table = snd_mixart_ids,
.probe = snd_mixart_probe,
.remove = __devexit_p(snd_mixart_remove),
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 7eb20b8f89f6..5c55a3b1d121 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -189,6 +189,7 @@ struct snd_nm256_stream {
nm256_t *chip;
snd_pcm_substream_t *substream;
int running;
+ int suspended;
u32 buf; /* offset from chip->buffer */
int bufsize; /* buffer size in bytes */
@@ -231,8 +232,10 @@ struct snd_nm256 {
int mixer_status_mask; /* bit mask to test the mixer status */
int irq;
+ int irq_acks;
irqreturn_t (*interrupt)(int, void *, struct pt_regs *);
int badintrcount; /* counter to check bogus interrupts */
+ struct semaphore irq_mutex;
nm256_stream_t streams[2];
@@ -256,21 +259,6 @@ struct snd_nm256 {
/*
* PCI ids
*/
-
-#ifndef PCI_VENDOR_ID_NEOMAGIC
-#define PCI_VENDOR_ID_NEOMEGIC 0x10c8
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-#endif
-
-
static struct pci_device_id snd_nm256_ids[] = {
{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},
@@ -464,6 +452,37 @@ snd_nm256_set_format(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *subs
}
}
+/* acquire interrupt */
+static int snd_nm256_acquire_irq(nm256_t *chip)
+{
+ down(&chip->irq_mutex);
+ if (chip->irq < 0) {
+ if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ,
+ chip->card->driver, (void*)chip)) {
+ snd_printk("unable to grab IRQ %d\n", chip->pci->irq);
+ up(&chip->irq_mutex);
+ return -EBUSY;
+ }
+ chip->irq = chip->pci->irq;
+ }
+ chip->irq_acks++;
+ up(&chip->irq_mutex);
+ return 0;
+}
+
+/* release interrupt */
+static void snd_nm256_release_irq(nm256_t *chip)
+{
+ down(&chip->irq_mutex);
+ if (chip->irq_acks > 0)
+ chip->irq_acks--;
+ if (chip->irq_acks == 0 && chip->irq >= 0) {
+ free_irq(chip->irq, (void*)chip);
+ chip->irq = -1;
+ }
+ up(&chip->irq_mutex);
+}
+
/*
* start / stop
*/
@@ -538,15 +557,19 @@ snd_nm256_playback_trigger(snd_pcm_substream_t *substream, int cmd)
spin_lock(&chip->reg_lock);
switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
+ s->suspended = 0;
+ /* fallthru */
+ case SNDRV_PCM_TRIGGER_START:
if (! s->running) {
snd_nm256_playback_start(chip, s, substream);
s->running = 1;
}
break;
- case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
+ s->suspended = 1;
+ /* fallthru */
+ case SNDRV_PCM_TRIGGER_STOP:
if (s->running) {
snd_nm256_playback_stop(chip);
s->running = 0;
@@ -802,7 +825,7 @@ static void snd_nm256_setup_stream(nm256_t *chip, nm256_stream_t *s,
runtime->hw = *hw_ptr;
runtime->hw.buffer_bytes_max = s->bufsize;
runtime->hw.period_bytes_max = s->bufsize / 2;
- runtime->dma_area = (void*) s->bufptr;
+ runtime->dma_area = (void __force *) s->bufptr;
runtime->dma_addr = s->bufptr_addr;
runtime->dma_bytes = s->bufsize;
runtime->private_data = s;
@@ -818,6 +841,8 @@ snd_nm256_playback_open(snd_pcm_substream_t *substream)
{
nm256_t *chip = snd_pcm_substream_chip(substream);
+ if (snd_nm256_acquire_irq(chip) < 0)
+ return -EBUSY;
snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK],
substream, &snd_nm256_playback);
return 0;
@@ -828,6 +853,8 @@ snd_nm256_capture_open(snd_pcm_substream_t *substream)
{
nm256_t *chip = snd_pcm_substream_chip(substream);
+ if (snd_nm256_acquire_irq(chip) < 0)
+ return -EBUSY;
snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_CAPTURE],
substream, &snd_nm256_capture);
return 0;
@@ -839,6 +866,9 @@ snd_nm256_capture_open(snd_pcm_substream_t *substream)
static int
snd_nm256_playback_close(snd_pcm_substream_t *substream)
{
+ nm256_t *chip = snd_pcm_substream_chip(substream);
+
+ snd_nm256_release_irq(chip);
return 0;
}
@@ -846,6 +876,9 @@ snd_nm256_playback_close(snd_pcm_substream_t *substream)
static int
snd_nm256_capture_close(snd_pcm_substream_t *substream)
{
+ nm256_t *chip = snd_pcm_substream_chip(substream);
+
+ snd_nm256_release_irq(chip);
return 0;
}
@@ -915,18 +948,16 @@ snd_nm256_pcm(nm256_t *chip, int device)
static void
snd_nm256_init_chip(nm256_t *chip)
{
- spin_lock_irq(&chip->reg_lock);
/* Reset everything. */
snd_nm256_writeb(chip, 0x0, 0x11);
snd_nm256_writew(chip, 0x214, 0);
/* stop sounds.. */
//snd_nm256_playback_stop(chip);
//snd_nm256_capture_stop(chip);
- spin_unlock_irq(&chip->reg_lock);
}
-static inline void
+static irqreturn_t
snd_nm256_intr_check(nm256_t *chip)
{
if (chip->badintrcount++ > 1000) {
@@ -947,7 +978,9 @@ snd_nm256_intr_check(nm256_t *chip)
if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)
snd_nm256_capture_stop(chip);
chip->badintrcount = 0;
+ return IRQ_HANDLED;
}
+ return IRQ_NONE;
}
/*
@@ -969,10 +1002,8 @@ snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
status = snd_nm256_readw(chip, NM_INT_REG);
/* Not ours. */
- if (status == 0) {
- snd_nm256_intr_check(chip);
- return IRQ_NONE;
- }
+ if (status == 0)
+ return snd_nm256_intr_check(chip);
chip->badintrcount = 0;
@@ -1036,10 +1067,8 @@ snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
status = snd_nm256_readl(chip, NM_INT_REG);
/* Not ours. */
- if (status == 0) {
- snd_nm256_intr_check(chip);
- return IRQ_NONE;
- }
+ if (status == 0)
+ return snd_nm256_intr_check(chip);
chip->badintrcount = 0;
@@ -1192,7 +1221,7 @@ snd_nm256_mixer(nm256_t *chip)
AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_CD,
AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL,
AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL,
- AC97_EXTENDED_ID,
+ /*AC97_EXTENDED_ID,*/
AC97_VENDOR_ID1, AC97_VENDOR_ID2,
-1
};
@@ -1206,6 +1235,7 @@ snd_nm256_mixer(nm256_t *chip)
for (i = 0; mixer_regs[i] >= 0; i++)
set_bit(mixer_regs[i], ac97.reg_accessed);
ac97.private_data = chip;
+ pbus->no_vra = 1;
err = snd_ac97_mixer(pbus, &ac97, &chip->ac97);
if (err < 0)
return err;
@@ -1281,6 +1311,7 @@ static int nm256_suspend(snd_card_t *card, pm_message_t state)
static int nm256_resume(snd_card_t *card)
{
nm256_t *chip = card->pm_private_data;
+ int i;
/* Perform a full reset on the hardware */
pci_enable_device(chip->pci);
@@ -1289,6 +1320,15 @@ static int nm256_resume(snd_card_t *card)
/* restore ac97 */
snd_ac97_resume(chip->ac97);
+ for (i = 0; i < 2; i++) {
+ nm256_stream_t *s = &chip->streams[i];
+ if (s->substream && s->suspended) {
+ spin_lock_irq(&chip->reg_lock);
+ snd_nm256_set_format(chip, s, s->substream);
+ spin_unlock_irq(&chip->reg_lock);
+ }
+ }
+
return 0;
}
#endif /* CONFIG_PM */
@@ -1349,7 +1389,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1360,6 +1400,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->use_cache = usecache;
spin_lock_init(&chip->reg_lock);
chip->irq = -1;
+ init_MUTEX(&chip->irq_mutex);
chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = play_bufsize;
chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize = capt_bufsize;
@@ -1470,15 +1511,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->coeff_buf[SNDRV_PCM_STREAM_CAPTURE] = addr;
}
- /* acquire interrupt */
- if (request_irq(pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ,
- card->driver, (void*)chip)) {
- err = -EBUSY;
- snd_printk("unable to grab IRQ %d\n", pci->irq);
- goto __error;
- }
- chip->irq = pci->irq;
-
/* Fixed setting. */
chip->mixer_base = NM_MIXER_OFFSET;
@@ -1636,6 +1668,7 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "NeoMagic 256",
+ .owner = THIS_MODULE,
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
.remove = __devexit_p(snd_nm256_remove),
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b7b554df6705..3daeecb9eb0e 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -192,20 +192,6 @@ MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
#define RME32_PRO_REVISION_WITH_8414 150
-/* PCI vendor/device ID's */
-#ifndef PCI_VENDOR_ID_XILINX_RME
-# define PCI_VENDOR_ID_XILINX_RME 0xea60
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32
-# define PCI_DEVICE_ID_DIGI32 0x9896
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_PRO
-# define PCI_DEVICE_ID_DIGI32_PRO 0x9897
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_8
-# define PCI_DEVICE_ID_DIGI32_8 0x9898
-#endif
-
typedef struct snd_rme32 {
spinlock_t lock;
int irq;
@@ -692,7 +678,8 @@ snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
if (err < 0)
return err;
} else {
- runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+ runtime->dma_area = (void __force *)(rme32->iobase +
+ RME32_IO_DATA_BUFFER);
runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
runtime->dma_bytes = RME32_BUFFER_SIZE;
}
@@ -746,7 +733,8 @@ snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
if (err < 0)
return err;
} else {
- runtime->dma_area = (void *)rme32->iobase + RME32_IO_DATA_BUFFER;
+ runtime->dma_area = (void __force *)rme32->iobase +
+ RME32_IO_DATA_BUFFER;
runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
runtime->dma_bytes = RME32_BUFFER_SIZE;
}
@@ -1900,7 +1888,7 @@ static snd_kcontrol_new_t snd_rme32_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
.info = snd_rme32_control_spdif_mask_info,
.get = snd_rme32_control_spdif_mask_get,
@@ -1908,7 +1896,7 @@ static snd_kcontrol_new_t snd_rme32_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
.info = snd_rme32_control_spdif_mask_info,
.get = snd_rme32_control_spdif_mask_get,
@@ -2024,6 +2012,7 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi32",
+ .owner = THIS_MODULE,
.id_table = snd_rme32_ids,
.probe = snd_rme32_probe,
.remove = __devexit_p(snd_rme32_remove),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 10c4f45a913c..9983b66dc564 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -200,25 +200,6 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
#define RME96_AD1852_VOL_BITS 14
#define RME96_AD1855_VOL_BITS 10
-/*
- * PCI vendor/device ids, could in the future be defined in <linux/pci.h>,
- * therefore #ifndef is used.
- */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96
-#define PCI_DEVICE_ID_DIGI96 0x3fc0
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8
-#define PCI_DEVICE_ID_DIGI96_8 0x3fc1
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PRO
-#define PCI_DEVICE_ID_DIGI96_8_PRO 0x3fc2
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST
-#define PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST 0x3fc3
-#endif
typedef struct snd_rme96 {
spinlock_t lock;
@@ -985,7 +966,8 @@ snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err, rate, dummy;
- runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+ runtime->dma_area = (void __force *)(rme96->iobase +
+ RME96_IO_PLAY_BUFFER);
runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
runtime->dma_bytes = RME96_BUFFER_SIZE;
@@ -1037,7 +1019,8 @@ snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err, isadat, rate;
- runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+ runtime->dma_area = (void __force *)(rme96->iobase +
+ RME96_IO_REC_BUFFER);
runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
runtime->dma_bytes = RME96_BUFFER_SIZE;
@@ -2266,7 +2249,7 @@ static snd_kcontrol_new_t snd_rme96_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_rme96_control_spdif_mask_info,
.get = snd_rme96_control_spdif_mask_get,
@@ -2276,7 +2259,7 @@ static snd_kcontrol_new_t snd_rme96_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_rme96_control_spdif_mask_info,
.get = snd_rme96_control_spdif_mask_get,
@@ -2430,6 +2413,7 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi96",
+ .owner = THIS_MODULE,
.id_table = snd_rme96_ids,
.probe = snd_rme96_probe,
.remove = __devexit_p(snd_rme96_remove),
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 796621de5009..52525eb198c7 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -370,13 +370,6 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
#define UNITY_GAIN 32768
#define MINUS_INFINITY_GAIN 0
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-
/* the size of a substream (1 mono data stream) */
#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
@@ -1524,7 +1517,7 @@ static int snd_hdsp_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_el
}
#define HDSP_SPDIF_IN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_spdif_in, \
@@ -1584,7 +1577,7 @@ static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
#define HDSP_SPDIF_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
@@ -1638,7 +1631,7 @@ static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
}
#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
@@ -1683,7 +1676,7 @@ static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_el
}
#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
@@ -1728,7 +1721,7 @@ static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
}
#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
@@ -1773,7 +1766,7 @@ static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
}
#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1834,7 +1827,7 @@ static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_ele
}
#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1858,7 +1851,7 @@ static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_el
}
#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1918,7 +1911,7 @@ static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_
}
#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1958,7 +1951,7 @@ static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_ele
}
#define HDSP_CLOCK_SOURCE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_clock_source, \
@@ -2124,7 +2117,7 @@ static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_ele
}
#define HDSP_DA_GAIN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_da_gain, \
@@ -2210,7 +2203,7 @@ static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
#define HDSP_AD_GAIN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_ad_gain, \
@@ -2296,7 +2289,7 @@ static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
#define HDSP_PHONE_GAIN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_phone_gain, \
@@ -2382,7 +2375,7 @@ static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
}
#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_xlr_breakout_cable, \
@@ -2447,7 +2440,7 @@ static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_el
Switching this on desactivates external ADAT
*/
#define HDSP_AEB(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_aeb, \
@@ -2508,7 +2501,7 @@ static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uc
}
#define HDSP_PREF_SYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_pref_sync_ref, \
@@ -2641,7 +2634,7 @@ static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
}
#define HDSP_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -2697,7 +2690,7 @@ static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
}
#define HDSP_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_line_out, \
@@ -2757,7 +2750,7 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
#define HDSP_PRECISE_POINTER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_precise_pointer, \
@@ -2811,7 +2804,7 @@ static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_
}
#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_use_midi_tasklet, \
@@ -2868,6 +2861,7 @@ static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
.name = xname, \
.index = xindex, \
+ .device = 0, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdsp_info_mixer, \
@@ -2939,7 +2933,7 @@ static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
}
#define HDSP_WC_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
@@ -2983,7 +2977,7 @@ static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
}
#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
@@ -3015,7 +3009,7 @@ static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem
}
#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
@@ -3046,7 +3040,7 @@ static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_e
}
#define HDSP_ADAT_SYNC_CHECK \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdsp_info_sync_check, \
.get = snd_hdsp_get_adat_sync_check \
@@ -3119,7 +3113,7 @@ static snd_kcontrol_new_t snd_hdsp_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_hdsp_control_spdif_mask_info,
.get = snd_hdsp_control_spdif_mask_get,
@@ -3129,7 +3123,7 @@ static snd_kcontrol_new_t snd_hdsp_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_hdsp_control_spdif_mask_info,
.get = snd_hdsp_control_spdif_mask_get,
@@ -3146,8 +3140,6 @@ HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
/* 'Sample Clock Source' complies with the alsa control naming scheme */
HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
{
- /* FIXME: should be PCM or MIXER? */
- /* .iface = SNDRV_CTL_ELEM_IFACE_PCM, */
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Sample Clock Source Locking",
.info = snd_hdsp_info_clock_source_lock,
@@ -4900,6 +4892,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
}
if (!(hdsp->state & HDSP_InitializationComplete)) {
+ strcpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
@@ -5223,6 +5216,7 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Hammerfall DSP",
+ .owner = THIS_MODULE,
.id_table = snd_hdsp_ids,
.probe = snd_hdsp_probe,
.remove = __devexit_p(snd_hdsp_remove),
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 9e86d0eb41ce..fc3f3283ff37 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -65,7 +65,7 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable.");
+MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
module_param_array(line_outs_monitor, bool, NULL, 0444);
MODULE_PARM_DESC(line_outs_monitor,
@@ -301,18 +301,6 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define UNITY_GAIN 32768 /* = 65536/2 */
#define MINUS_INFINITY_GAIN 0
-/* PCI info */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#endif
-
-
/* Number of channels for different Speed Modes */
#define MADI_SS_CHANNELS 64
#define MADI_DS_CHANNELS 32
@@ -1104,14 +1092,14 @@ static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-snd_rawmidi_ops_t snd_hdspm_midi_output =
+static snd_rawmidi_ops_t snd_hdspm_midi_output =
{
.open = snd_hdspm_midi_output_open,
.close = snd_hdspm_midi_output_close,
.trigger = snd_hdspm_midi_output_trigger,
};
-snd_rawmidi_ops_t snd_hdspm_midi_input =
+static snd_rawmidi_ops_t snd_hdspm_midi_input =
{
.open = snd_hdspm_midi_input_open,
.close = snd_hdspm_midi_input_close,
@@ -1168,7 +1156,7 @@ static void hdspm_midi_tasklet(unsigned long arg)
/* get the system sample rate which is set */
#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1195,7 +1183,7 @@ static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
}
#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1264,7 +1252,7 @@ static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
}
#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1310,7 +1298,7 @@ static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
}
#define HDSPM_CLOCK_SOURCE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_clock_source, \
@@ -1457,7 +1445,7 @@ static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
}
#define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_pref_sync_ref, \
@@ -1547,7 +1535,7 @@ static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
}
#define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ, \
@@ -1604,7 +1592,7 @@ static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
}
#define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_line_out, \
@@ -1668,7 +1656,7 @@ static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
}
#define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_tx_64, \
@@ -1731,7 +1719,7 @@ static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
}
#define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_c_tms, \
@@ -1794,7 +1782,7 @@ static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
}
#define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_safe_mode, \
@@ -1857,7 +1845,7 @@ static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
}
#define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdspm_info_input_select, \
@@ -1941,6 +1929,7 @@ static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
.name = xname, \
.index = xindex, \
+ .device = 0, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_hdspm_info_mixer, \
@@ -2124,7 +2113,7 @@ static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
}
#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
@@ -2170,7 +2159,7 @@ static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
@@ -3651,6 +3640,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Hammerfall DSP MADI",
+ .owner = THIS_MODULE,
.id_table = snd_hdspm_ids,
.probe = snd_hdspm_probe,
.remove = __devexit_p(snd_hdspm_remove),
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 1bc9d0df8516..b600f45e1834 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -120,13 +120,6 @@ MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall},"
#define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos))
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4
-#endif
-
/* amount of io space we remap for register access. i'm not sure we
even need this much, but 1K is nice round number :)
*/
@@ -893,7 +886,7 @@ static int snd_rme9652_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl
}
#define RME9652_ADAT1_IN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_adat1_in, \
.get = snd_rme9652_get_adat1_in, \
.put = snd_rme9652_put_adat1_in }
@@ -971,7 +964,7 @@ static int snd_rme9652_put_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
}
#define RME9652_SPDIF_IN(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_spdif_in, \
.get = snd_rme9652_get_spdif_in, .put = snd_rme9652_put_spdif_in }
@@ -1042,7 +1035,7 @@ static int snd_rme9652_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
}
#define RME9652_SPDIF_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_spdif_out, \
.get = snd_rme9652_get_spdif_out, .put = snd_rme9652_put_spdif_out }
@@ -1110,7 +1103,7 @@ static int snd_rme9652_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
}
#define RME9652_SYNC_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_sync_mode, \
.get = snd_rme9652_get_sync_mode, .put = snd_rme9652_put_sync_mode }
@@ -1195,7 +1188,7 @@ static int snd_rme9652_put_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
}
#define RME9652_SYNC_PREF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_sync_pref, \
.get = snd_rme9652_get_sync_pref, .put = snd_rme9652_put_sync_pref }
@@ -1340,7 +1333,7 @@ static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
#define RME9652_PASSTHRU(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_rme9652_info_passthru, \
.put = snd_rme9652_put_passthru, \
.get = snd_rme9652_get_passthru }
@@ -1386,7 +1379,7 @@ static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
/* Read-only switches */
#define RME9652_SPDIF_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_rme9652_info_spdif_rate, \
.get = snd_rme9652_get_spdif_rate }
@@ -1411,7 +1404,7 @@ static int snd_rme9652_get_spdif_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
}
#define RME9652_ADAT_SYNC(xname, xindex, xidx) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_rme9652_info_adat_sync, \
.get = snd_rme9652_get_adat_sync, .private_value = xidx }
@@ -1447,7 +1440,7 @@ static int snd_rme9652_get_adat_sync(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
}
#define RME9652_TC_VALID(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, .index = xindex, \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
.info = snd_rme9652_info_tc_valid, \
.get = snd_rme9652_get_tc_valid }
@@ -1545,7 +1538,7 @@ static snd_kcontrol_new_t snd_rme9652_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_rme9652_control_spdif_mask_info,
.get = snd_rme9652_control_spdif_mask_get,
@@ -1555,7 +1548,7 @@ static snd_kcontrol_new_t snd_rme9652_controls[] = {
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_rme9652_control_spdif_mask_info,
.get = snd_rme9652_control_spdif_mask_get,
@@ -1568,7 +1561,7 @@ RME9652_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
RME9652_SYNC_MODE("Sync Mode", 0),
RME9652_SYNC_PREF("Preferred Sync Source", 0),
{
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channels Thru",
.index = 0,
.info = snd_rme9652_info_thru,
@@ -2661,6 +2654,7 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi9652 (Hammerfall)",
+ .owner = THIS_MODULE,
.id_table = snd_rme9652_ids,
.probe = snd_rme9652_probe,
.remove = __devexit_p(snd_rme9652_remove),
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 60ecb2bdb65e..1f6c2bfd43fd 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -50,13 +50,6 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
#define SUPPORT_JOYSTICK 1
#endif
-#ifndef PCI_VENDOR_ID_S3
-#define PCI_VENDOR_ID_S3 0x5333
-#endif
-#ifndef PCI_DEVICE_ID_S3_SONICVIBES
-#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
-#endif
-
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
@@ -1257,7 +1250,7 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
return -ENXIO;
}
- sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL);
+ sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
if (sonic == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1515,6 +1508,7 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "S3 SonicVibes",
+ .owner = THIS_MODULE,
.id_table = snd_sonic_ids,
.probe = snd_sonic_probe,
.remove = __devexit_p(snd_sonic_remove),
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 940d531575c0..a8ca8e17853f 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -177,6 +177,7 @@ static void __devexit snd_trident_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Trident4DWaveAudio",
+ .owner = THIS_MODULE,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
.remove = __devexit_p(snd_trident_remove),
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 29d89bfba0a4..777da9a7298b 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -1689,7 +1689,7 @@ static snd_pcm_hardware_t snd_trident_playback =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
.formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
@@ -1714,7 +1714,7 @@ static snd_pcm_hardware_t snd_trident_capture =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
.formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
@@ -1739,7 +1739,7 @@ static snd_pcm_hardware_t snd_trident_foldback =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
@@ -1763,7 +1763,7 @@ static snd_pcm_hardware_t snd_trident_spdif =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
@@ -1784,7 +1784,7 @@ static snd_pcm_hardware_t snd_trident_spdif_7018 =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
@@ -2960,7 +2960,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
.read = snd_trident_codec_read,
};
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return -ENOMEM;
@@ -3546,7 +3546,7 @@ int __devinit snd_trident_create(snd_card_t * card,
return -ENXIO;
}
- trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
+ trident = kzalloc(sizeof(*trident), GFP_KERNEL);
if (trident == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 4889600387c8..6db7de6b9719 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -104,14 +104,6 @@ module_param_array(dxs_support, int, NULL, 0444);
MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
-/* pci ids */
-#ifndef PCI_DEVICE_ID_VIA_82C686_5
-#define PCI_DEVICE_ID_VIA_82C686_5 0x3058
-#endif
-#ifndef PCI_DEVICE_ID_VIA_8233_5
-#define PCI_DEVICE_ID_VIA_8233_5 0x3059
-#endif
-
/* revision numbers for via686 */
#define VIA_REV_686_A 0x10
#define VIA_REV_686_B 0x11
@@ -663,10 +655,12 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
val = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
val |= VIA_REG_CTRL_START;
viadev->running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
val = VIA_REG_CTRL_TERMINATE;
viadev->running = 0;
break;
@@ -929,12 +923,12 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
return rate_changed;
- if (rate_changed) {
+ if (rate_changed)
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
chip->no_vra ? 48000 : runtime->rate);
- snd_ac97_set_rate(chip->ac97, AC97_SPDIF,
- chip->no_vra ? 48000 : runtime->rate);
- }
+ if (chip->spdif_on && viadev->reg_offset == 0x30)
+ snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
+
if (runtime->rate == 48000)
rbits = 0xfffff;
else
@@ -1035,7 +1029,7 @@ static snd_pcm_hardware_t snd_via82xx_hw =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
+ /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
@@ -1484,7 +1478,7 @@ static int snd_via8233_dxs3_spdif_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
}
static snd_kcontrol_new_t snd_via8233_dxs3_spdif_control __devinitdata = {
- .name = "IEC958 Output Switch",
+ .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_dxs3_spdif_info,
.get = snd_via8233_dxs3_spdif_get,
@@ -1933,11 +1927,12 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
* DXS channels don't work properly with VRA if MC97 is disabled.
*/
struct pci_dev *pci;
- pci = pci_find_device(0x1106, 0x3068, NULL); /* MC97 */
+ pci = pci_get_device(0x1106, 0x3068, NULL); /* MC97 */
if (pci) {
unsigned char data;
pci_read_config_byte(pci, 0x44, &data);
pci_write_config_byte(pci, 0x44, data | 0x40);
+ pci_dev_put(pci);
}
}
@@ -2063,7 +2058,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
@@ -2153,6 +2148,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 = 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?)*/
{ .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
{ .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
@@ -2168,10 +2164,12 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
{ .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
{ .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
+ { .subvendor = 0x1462, .subdevice = 0x0430, .action = VIA_DXS_SRC }, /* MSI 7142 (K8MM-V) */
{ .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
{ .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
{ .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
{ .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+ { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
{ .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
{ .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
{ .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
@@ -2345,6 +2343,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "VIA 82xx Audio",
+ .owner = THIS_MODULE,
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 4a9779cc9733..7eac6f6ac737 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -521,6 +521,7 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
val |= VIA_REG_CTRL_START;
viadev->running = 1;
break;
@@ -697,7 +698,7 @@ static snd_pcm_hardware_t snd_via82xx_hw =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
+ /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,
@@ -1082,7 +1083,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
@@ -1206,6 +1207,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "VIA 82xx Modem",
+ .owner = THIS_MODULE,
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index dca6bd2c7580..2a7ad9dec021 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -252,6 +252,7 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Digigram VX222",
+ .owner = THIS_MODULE,
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
.remove = __devexit_p(snd_vx222_remove),
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 5b5b624b47d0..2e69abe51aa9 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -352,6 +352,7 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Yamaha DS-XG PCI",
+ .owner = THIS_MODULE,
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
.remove = __devexit_p(snd_card_ymfpci_remove),
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index d54f88a1b525..27fa523639ae 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -321,6 +321,26 @@ static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
snd_pcm_period_elapsed(ypcm->substream);
spin_lock(&chip->reg_lock);
}
+
+ if (unlikely(ypcm->update_pcm_vol)) {
+ unsigned int subs = ypcm->substream->number;
+ unsigned int next_bank = 1 - chip->active_bank;
+ snd_ymfpci_playback_bank_t *bank;
+ u32 volume;
+
+ bank = &voice->bank[next_bank];
+ volume = cpu_to_le32(chip->pcm_mixer[subs].left << 15);
+ bank->left_gain_end = volume;
+ if (ypcm->output_rear)
+ bank->eff2_gain_end = volume;
+ if (ypcm->voices[1])
+ bank = &ypcm->voices[1]->bank[next_bank];
+ volume = cpu_to_le32(chip->pcm_mixer[subs].right << 15);
+ bank->right_gain_end = volume;
+ if (ypcm->output_rear)
+ bank->eff3_gain_end = volume;
+ ypcm->update_pcm_vol--;
+ }
}
spin_unlock(&chip->reg_lock);
}
@@ -451,87 +471,74 @@ static int snd_ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
return 0;
}
-static void snd_ymfpci_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
- int rate, int w_16, unsigned long addr,
- unsigned int end,
- int output_front, int output_rear)
+static void snd_ymfpci_pcm_init_voice(ymfpci_pcm_t *ypcm, unsigned int voiceidx,
+ snd_pcm_runtime_t *runtime,
+ int has_pcm_volume)
{
+ ymfpci_voice_t *voice = ypcm->voices[voiceidx];
u32 format;
- u32 delta = snd_ymfpci_calc_delta(rate);
- u32 lpfQ = snd_ymfpci_calc_lpfQ(rate);
- u32 lpfK = snd_ymfpci_calc_lpfK(rate);
+ u32 delta = snd_ymfpci_calc_delta(runtime->rate);
+ u32 lpfQ = snd_ymfpci_calc_lpfQ(runtime->rate);
+ u32 lpfK = snd_ymfpci_calc_lpfK(runtime->rate);
snd_ymfpci_playback_bank_t *bank;
unsigned int nbank;
+ u32 vol_left, vol_right;
+ u8 use_left, use_right;
snd_assert(voice != NULL, return);
- format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000);
+ if (runtime->channels == 1) {
+ use_left = 1;
+ use_right = 1;
+ } else {
+ use_left = (voiceidx & 1) == 0;
+ use_right = !use_left;
+ }
+ if (has_pcm_volume) {
+ vol_left = cpu_to_le32(ypcm->chip->pcm_mixer
+ [ypcm->substream->number].left << 15);
+ vol_right = cpu_to_le32(ypcm->chip->pcm_mixer
+ [ypcm->substream->number].right << 15);
+ } else {
+ vol_left = cpu_to_le32(0x40000000);
+ vol_right = cpu_to_le32(0x40000000);
+ }
+ format = runtime->channels == 2 ? 0x00010000 : 0;
+ if (snd_pcm_format_width(runtime->format) == 8)
+ format |= 0x80000000;
+ if (runtime->channels == 2 && (voiceidx & 1) != 0)
+ format |= 1;
for (nbank = 0; nbank < 2; nbank++) {
bank = &voice->bank[nbank];
+ memset(bank, 0, sizeof(*bank));
bank->format = cpu_to_le32(format);
- bank->loop_default = 0;
- bank->base = cpu_to_le32(addr);
- bank->loop_start = 0;
- bank->loop_end = cpu_to_le32(end);
- bank->loop_frac = 0;
- bank->eg_gain_end = cpu_to_le32(0x40000000);
+ bank->base = cpu_to_le32(runtime->dma_addr);
+ bank->loop_end = cpu_to_le32(ypcm->buffer_size);
bank->lpfQ = cpu_to_le32(lpfQ);
- bank->status = 0;
- bank->num_of_frames = 0;
- bank->loop_count = 0;
- bank->start = 0;
- bank->start_frac = 0;
bank->delta =
bank->delta_end = cpu_to_le32(delta);
bank->lpfK =
bank->lpfK_end = cpu_to_le32(lpfK);
- bank->eg_gain = cpu_to_le32(0x40000000);
- bank->lpfD1 =
- bank->lpfD2 = 0;
-
- bank->left_gain =
- bank->right_gain =
- bank->left_gain_end =
- bank->right_gain_end =
- bank->eff1_gain =
- bank->eff2_gain =
- bank->eff3_gain =
- bank->eff1_gain_end =
- bank->eff2_gain_end =
- bank->eff3_gain_end = 0;
-
- if (!stereo) {
- if (output_front) {
- bank->left_gain =
+ bank->eg_gain =
+ bank->eg_gain_end = cpu_to_le32(0x40000000);
+
+ if (ypcm->output_front) {
+ if (use_left) {
+ bank->left_gain =
+ bank->left_gain_end = vol_left;
+ }
+ if (use_right) {
bank->right_gain =
- bank->left_gain_end =
- bank->right_gain_end = cpu_to_le32(0x40000000);
+ bank->right_gain_end = vol_right;
}
- if (output_rear) {
+ }
+ if (ypcm->output_rear) {
+ if (use_left) {
bank->eff2_gain =
- bank->eff2_gain_end =
- bank->eff3_gain =
- bank->eff3_gain_end = cpu_to_le32(0x40000000);
- }
- } else {
- if (output_front) {
- if ((voice->number & 1) == 0) {
- bank->left_gain =
- bank->left_gain_end = cpu_to_le32(0x40000000);
- } else {
- bank->format |= cpu_to_le32(1);
- bank->right_gain =
- bank->right_gain_end = cpu_to_le32(0x40000000);
- }
+ bank->eff2_gain_end = vol_left;
}
- if (output_rear) {
- if ((voice->number & 1) == 0) {
- bank->eff3_gain =
- bank->eff3_gain_end = cpu_to_le32(0x40000000);
- } else {
- bank->format |= cpu_to_le32(1);
- bank->eff2_gain =
- bank->eff2_gain_end = cpu_to_le32(0x40000000);
- }
+ if (use_right) {
+ bank->eff3_gain =
+ bank->eff3_gain_end = vol_right;
}
}
}
@@ -613,7 +620,7 @@ static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream)
static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
{
- // ymfpci_t *chip = snd_pcm_substream_chip(substream);
+ ymfpci_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm = runtime->private_data;
unsigned int nvoice;
@@ -623,14 +630,8 @@ static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
ypcm->period_pos = 0;
ypcm->last_pos = 0;
for (nvoice = 0; nvoice < runtime->channels; nvoice++)
- snd_ymfpci_pcm_init_voice(ypcm->voices[nvoice],
- runtime->channels == 2,
- runtime->rate,
- snd_pcm_format_width(runtime->format) == 16,
- runtime->dma_addr,
- ypcm->buffer_size,
- ypcm->output_front,
- ypcm->output_rear);
+ snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime,
+ substream->pcm == chip->pcm);
return 0;
}
@@ -838,7 +839,7 @@ static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
- ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+ ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
return -ENOMEM;
ypcm->chip = chip;
@@ -882,6 +883,7 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
ymfpci_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
+ snd_kcontrol_t *kctl;
int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -895,6 +897,10 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
chip->rear_opened++;
}
spin_unlock_irq(&chip->reg_lock);
+
+ kctl = chip->pcm_mixer[substream->number].ctl;
+ kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return 0;
}
@@ -951,7 +957,7 @@ static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
- ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+ ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
return -ENOMEM;
ypcm->chip = chip;
@@ -987,6 +993,7 @@ static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
{
ymfpci_t *chip = snd_pcm_substream_chip(substream);
ymfpci_pcm_t *ypcm = substream->runtime->private_data;
+ snd_kcontrol_t *kctl;
spin_lock_irq(&chip->reg_lock);
if (ypcm->output_rear && chip->rear_opened > 0) {
@@ -994,6 +1001,9 @@ static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
ymfpci_close_extension(chip);
}
spin_unlock_irq(&chip->reg_lock);
+ kctl = chip->pcm_mixer[substream->number].ctl;
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return snd_ymfpci_playback_close_1(substream);
}
@@ -1665,6 +1675,66 @@ static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {
.private_value = 2,
};
+/*
+ * PCM voice volume
+ */
+
+static int snd_ymfpci_pcm_vol_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0x8000;
+ return 0;
+}
+
+static int snd_ymfpci_pcm_vol_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int subs = kcontrol->id.subdevice;
+
+ ucontrol->value.integer.value[0] = chip->pcm_mixer[subs].left;
+ ucontrol->value.integer.value[1] = chip->pcm_mixer[subs].right;
+ return 0;
+}
+
+static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int subs = kcontrol->id.subdevice;
+ snd_pcm_substream_t *substream;
+ unsigned long flags;
+
+ if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left ||
+ ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) {
+ chip->pcm_mixer[subs].left = ucontrol->value.integer.value[0];
+ chip->pcm_mixer[subs].right = ucontrol->value.integer.value[1];
+
+ substream = (snd_pcm_substream_t *)kcontrol->private_value;
+ spin_lock_irqsave(&chip->voice_lock, flags);
+ if (substream->runtime && substream->runtime->private_data) {
+ ymfpci_pcm_t *ypcm = substream->runtime->private_data;
+ ypcm->update_pcm_vol = 2;
+ }
+ spin_unlock_irqrestore(&chip->voice_lock, flags);
+ return 1;
+ }
+ return 0;
+}
+
+static snd_kcontrol_new_t snd_ymfpci_pcm_volume __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "PCM Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .info = snd_ymfpci_pcm_vol_info,
+ .get = snd_ymfpci_pcm_vol_get,
+ .put = snd_ymfpci_pcm_vol_put,
+};
+
/*
* Mixer routines
@@ -1686,6 +1756,7 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
{
ac97_template_t ac97;
snd_kcontrol_t *kctl;
+ snd_pcm_substream_t *substream;
unsigned int idx;
int err;
static ac97_bus_ops_t ops = {
@@ -1739,6 +1810,23 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
return err;
}
+ /* per-voice volume */
+ substream = chip->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ for (idx = 0; idx < 32; ++idx) {
+ kctl = snd_ctl_new1(&snd_ymfpci_pcm_volume, chip);
+ if (!kctl)
+ return -ENOMEM;
+ kctl->id.device = chip->pcm->device;
+ kctl->id.subdevice = idx;
+ kctl->private_value = (unsigned long)substream;
+ if ((err = snd_ctl_add(chip->card, kctl)) < 0)
+ return err;
+ chip->pcm_mixer[idx].left = 0x8000;
+ chip->pcm_mixer[idx].right = 0x8000;
+ chip->pcm_mixer[idx].ctl = kctl;
+ substream = substream->next;
+ }
+
return 0;
}
@@ -2182,7 +2270,7 @@ int __devinit snd_ymfpci_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index a2132e3763dd..0208c54896b3 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -151,7 +151,7 @@ pdacf_t *snd_pdacf_create(snd_card_t *card)
{
pdacf_t *chip;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return NULL;
chip->card = card;
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 3a82161d3b24..1e8f16b4c073 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -297,6 +297,7 @@ static void vxpocket_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
chip->dev = &handle_to_dev(link->handle);
+ snd_card_set_dev(chip->card, chip->dev);
if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
@@ -376,7 +377,7 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar
/*
*/
-static dev_link_t *vxp_attach(void)
+static dev_link_t *vxpocket_attach(void)
{
snd_card_t *card;
struct snd_vxpocket *vxp;
@@ -407,7 +408,7 @@ static dev_link_t *vxp_attach(void)
return NULL;
}
- vxp->index = index[i];
+ vxp->index = i;
card_alloc |= 1 << i;
/* Chain drivers */
@@ -417,7 +418,7 @@ static dev_link_t *vxp_attach(void)
return &vxp->link;
}
-static void vxp_detach(dev_link_t *link)
+static void vxpocket_detach(dev_link_t *link)
{
struct snd_vxpocket *vxp;
vx_core_t *chip;
@@ -458,8 +459,9 @@ static struct pcmcia_driver vxp_cs_driver = {
.drv = {
.name = "snd-vxpocket",
},
- .attach = vxp_attach,
- .detach = vxp_detach,
+ .attach = vxpocket_attach,
+ .detach = vxpocket_detach,
+ .event = vxpocket_event,
.id_table = vxp_ids,
};
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 75213bf4d567..206b9333f91f 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -13,11 +13,24 @@ config SND_POWERMAC
tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
depends on SND && I2C && INPUT && PPC_PMAC
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for the integrated sound device.
To compile this driver as a module, choose M here: the module
will be called snd-powermac.
-endmenu
+config SND_POWERMAC_AUTO_DRC
+ bool "Toggle DRC automatically at headphone/line plug-in"
+ depends on SND_POWERMAC
+ default y
+ help
+ Say Y here to enable the automatic toggle of DRC (dynamic
+ range compression) on Tumbler/Snapper.
+ If this feature is enabled, DRC is turned off when the
+ headphone/line jack is plugged, and turned on when unplugged.
+ Note that you can turn on/off DRC manually even without this
+ option.
+
+endmenu
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index c89e82eb06a6..e35b48d29c45 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -988,6 +988,7 @@ static int __init snd_pmac_detect(pmac_t *chip)
case 0x33:
case 0x29:
case 0x24:
+ case 0x5c:
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
chip->model = PMAC_SNAPPER;
chip->can_byte_swap = 0; /* FIXME: check this */
@@ -1159,7 +1160,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
snd_runtime_check(chip_return, return -EINVAL);
*chip_return = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->card = card;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 231f6432ea6d..a6d8cbf4064f 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -131,6 +131,9 @@ static int __init snd_pmac_probe(void)
if (enable_beep)
snd_pmac_attach_beep(chip);
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __error;
+
if ((err = snd_card_register(card)) < 0)
goto __error;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index b94437c024b1..65384afcfc3f 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -948,7 +948,6 @@ static void device_change_handler(void *self)
msleep(10);
check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
chip->speaker_sw_ctl);
- mix->drc_enable = 0;
} else {
/* unmute speaker, mute others */
check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
@@ -960,20 +959,21 @@ static void device_change_handler(void *self)
if (mix->line_mute.addr != 0)
check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
chip->lineout_sw_ctl);
- mix->drc_enable = 1;
}
- if (mix->auto_mute_notify) {
+ if (mix->auto_mute_notify)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->hp_detect_ctl->id);
+
+#ifdef CONFIG_SND_POWERMAC_AUTO_DRC
+ mix->drc_enable = ! (headphone || lineout);
+ if (mix->auto_mute_notify)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->drc_sw_ctl->id);
- }
-
- /* first set the DRC so the speaker do not explode -ReneR */
if (chip->model == PMAC_TUMBLER)
tumbler_set_drc(mix);
else
snapper_set_drc(mix);
+#endif
/* reset the master volume so the correct amplification is applied */
tumbler_set_master_volume(mix);
@@ -1370,6 +1370,17 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
return err;
+ /* set initial DRC range to 60% */
+ if (chip->model == PMAC_TUMBLER)
+ mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;
+ else
+ mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;
+ mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */
+ if (chip->model == PMAC_TUMBLER)
+ tumbler_set_drc(mix);
+ else
+ snapper_set_drc(mix);
+
#ifdef CONFIG_PM
chip->suspend = tumbler_suspend;
chip->resume = tumbler_resume;
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 21a69e096225..954f994592ab 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -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)
+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)
{
struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
int r;
@@ -175,7 +175,7 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
S_IFCHR | mode, s->name);
class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
- NULL, s->name+6);
+ dev, s->name+6);
return r;
fail:
@@ -227,16 +227,18 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
static struct sound_unit *chains[SOUND_STEP];
/**
- * register_sound_special - register a special sound node
+ * register_sound_special_device - register a special sound node
* @fops: File operations for the driver
* @unit: Unit number to allocate
+ * @dev: device pointer
*
* Allocate a special sound device by minor number from the sound
* subsystem. The allocated number is returned on succes. On failure
* a negative error code is returned.
*/
-int register_sound_special(struct file_operations *fops, int unit)
+int register_sound_special_device(struct file_operations *fops, int unit,
+ struct device *dev)
{
const int chain = unit % SOUND_STEP;
int max_unit = 128 + chain;
@@ -294,9 +296,16 @@ int register_sound_special(struct file_operations *fops, int unit)
break;
}
return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
- name, S_IRUSR | S_IWUSR);
+ name, S_IRUSR | S_IWUSR, dev);
}
+EXPORT_SYMBOL(register_sound_special_device);
+
+int register_sound_special(struct file_operations *fops, int unit)
+{
+ return register_sound_special_device(fops, unit, NULL);
+}
+
EXPORT_SYMBOL(register_sound_special);
/**
@@ -312,7 +321,7 @@ EXPORT_SYMBOL(register_sound_special);
int register_sound_mixer(struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[0], fops, dev, 0, 128,
- "mixer", S_IRUSR | S_IWUSR);
+ "mixer", S_IRUSR | S_IWUSR, NULL);
}
EXPORT_SYMBOL(register_sound_mixer);
@@ -330,7 +339,7 @@ EXPORT_SYMBOL(register_sound_mixer);
int register_sound_midi(struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[2], fops, dev, 2, 130,
- "midi", S_IRUSR | S_IWUSR);
+ "midi", S_IRUSR | S_IWUSR, NULL);
}
EXPORT_SYMBOL(register_sound_midi);
@@ -356,7 +365,7 @@ EXPORT_SYMBOL(register_sound_midi);
int register_sound_dsp(struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[3], fops, dev, 3, 131,
- "dsp", S_IWUSR | S_IRUSR);
+ "dsp", S_IWUSR | S_IRUSR, NULL);
}
EXPORT_SYMBOL(register_sound_dsp);
@@ -375,7 +384,7 @@ EXPORT_SYMBOL(register_sound_dsp);
int register_sound_synth(struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[9], fops, dev, 9, 137,
- "synth", S_IRUSR | S_IWUSR);
+ "synth", S_IRUSR | S_IWUSR, NULL);
}
EXPORT_SYMBOL(register_sound_synth);
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
index 25a8a558ef92..09ab138646a6 100644
--- a/sound/sparc/Kconfig
+++ b/sound/sparc/Kconfig
@@ -7,6 +7,7 @@ config SND_SUN_AMD7930
tristate "Sun AMD7930"
depends on SBUS && SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD7930 sound device on Sun.
@@ -17,6 +18,7 @@ config SND_SUN_CS4231
tristate "Sun CS4231"
depends on SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for CS4231 sound device on Sun.
@@ -27,6 +29,7 @@ config SND_SUN_DBRI
tristate "Sun DBRI"
depends on SND && SBUS
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for DBRI sound device on Sun.
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index bd8a850e93ea..46d504ba7e03 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -967,7 +967,7 @@ static int __init snd_amd7930_create(snd_card_t *card,
int err;
*ramd = NULL;
- amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
+ amd = kzalloc(sizeof(*amd), GFP_KERNEL);
if (amd == NULL)
return -ENOMEM;
@@ -1088,6 +1088,9 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
if ((err = snd_amd7930_mixer(amd)) < 0)
goto out_err;
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out_err;
+
if ((err = snd_card_register(card)) < 0)
goto out_err;
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 36f9fe4d7bea..2fb27c4e951f 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1915,6 +1915,9 @@ static int cs4231_attach_finish(snd_card_t *card, cs4231_t *chip)
if ((err = snd_cs4231_timer(chip)) < 0)
goto out_err;
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out_err;
+
if ((err = snd_card_register(card)) < 0)
goto out_err;
@@ -1966,7 +1969,7 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -2080,7 +2083,7 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 941c7b1e7ebb..b5c4c15ae7f0 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -1,6 +1,6 @@
/*
* Driver for DBRI sound chip found on Sparcs.
- * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net)
+ * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net)
*
* Based entirely upon drivers/sbus/audio/dbri.c which is:
* Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -43,6 +43,12 @@
* audio devices. But the SUN HW group decided against it, at least on my
* LX the speakerbox connector has at least 1 pin missing and 1 wrongly
* connected.
+ *
+ * I've tried to stick to the following function naming conventions:
+ * snd_* ALSA stuff
+ * cs4215_* CS4215 codec specfic stuff
+ * dbri_* DBRI high-level stuff
+ * other DBRI low-level stuff
*/
#include <sound/driver.h>
@@ -87,7 +93,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");
#define D_DESC (1<<5)
static int dbri_debug = 0;
-module_param(dbri_debug, int, 0444);
+module_param(dbri_debug, int, 0644);
MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
#ifdef DBRI_DEBUG
@@ -320,7 +326,8 @@ typedef struct snd_dbri {
void __iomem *regs; /* dbri HW regs */
int dbri_version; /* 'e' and up is OK */
int dbri_irqp; /* intr queue pointer */
- int wait_seen;
+ int wait_send; /* sequence of command buffers send */
+ int wait_ackd; /* sequence of command buffers acknowledged */
struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */
struct dbri_desc descs[DBRI_NO_DESCS];
@@ -625,16 +632,13 @@ static __u32 reverse_bytes(__u32 b, int len)
Commands are sent to the DBRI by building a list of them in memory,
then writing the address of the first list item to DBRI register 8.
-The list is terminated with a WAIT command, which can generate a
-CPU interrupt if required.
+The list is terminated with a WAIT command, which generates a
+CPU interrupt to signal completion.
Since the DBRI can run in parallel with the CPU, several means of
-synchronization present themselves. The original scheme (Rudolf's)
-was to set a flag when we "cmdlock"ed the DBRI, clear the flag when
-an interrupt signaled completion, and wait on a wait_queue if a routine
-attempted to cmdlock while the flag was set. The problems arose when
-we tried to cmdlock from inside an interrupt handler, which might
-cause scheduling in an interrupt (if we waited), etc, etc
+synchronization present themselves. The method implemented here is close
+to the original scheme (Rudolf's), and uses 2 counters (wait_send and
+wait_ackd) to synchronize the command buffer between the CPU and the DBRI.
A more sophisticated scheme might involve a circular command buffer
or an array of command buffers. A routine could fill one with
@@ -642,70 +646,75 @@ commands and link it onto a list. When a interrupt signaled
completion of the current command buffer, look on the list for
the next one.
-I've decided to implement something much simpler - after each command,
-the CPU waits for the DBRI to finish the command by polling the P bit
-in DBRI register 0. I've tried to implement this in such a way
-that might make implementing a more sophisticated scheme easier.
-
Every time a routine wants to write commands to the DBRI, it must
first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd
-in return. After the commands have been writen, dbri_cmdsend() is
-called with the final pointer value.
+in return. dbri_cmdlock() will block if the previous commands have not
+been completed yet. After this the commands can be written to the buffer,
+and dbri_cmdsend() is called with the final pointer value to send them
+to the DBRI.
*/
+static void dbri_process_interrupt_buffer(snd_dbri_t * dbri);
+
enum dbri_lock_t { NoGetLock, GetLock };
+#define MAXLOOPS 10
static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
{
+ int maxloops = MAXLOOPS;
+
#ifndef SMP
if ((get == GetLock) && spin_is_locked(&dbri->lock)) {
printk(KERN_ERR "DBRI: cmdlock called while in spinlock.");
}
#endif
+ /* Delay if previous commands are still being processed */
+ while ((--maxloops) > 0 && (dbri->wait_send != dbri->wait_ackd)) {
+ msleep_interruptible(1);
+ /* If dbri_cmdlock() got called from inside the
+ * interrupt handler, this will do the processing.
+ */
+ dbri_process_interrupt_buffer(dbri);
+ }
+ if (maxloops == 0) {
+ printk(KERN_ERR "DBRI: Chip never completed command buffer %d\n",
+ dbri->wait_send);
+ } else {
+ dprintk(D_CMD, "Chip completed command buffer (%d)\n",
+ MAXLOOPS - maxloops - 1);
+ }
+
/*if (get == GetLock) spin_lock(&dbri->lock); */
return &dbri->dma->cmd[0];
}
-static void dbri_process_interrupt_buffer(snd_dbri_t *);
-
static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
{
- int MAXLOOPS = 1000000;
- int maxloops = MAXLOOPS;
volatile s32 *ptr;
+ u32 reg;
for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) {
dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
}
if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) {
- printk("DBRI: Command buffer overflow! (bug in driver)\n");
+ printk(KERN_ERR "DBRI: Command buffer overflow! (bug in driver)\n");
/* Ignore the last part. */
cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3];
}
+ dbri->wait_send++;
+ dbri->wait_send &= 0xffff; /* restrict it to a 16 bit counter. */
*(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
- *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
- dbri->wait_seen = 0;
+ *(cmd++) = DBRI_CMD(D_WAIT, 1, dbri->wait_send);
+
+ /* Set command pointer and signal it is valid. */
sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
- while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P))
- barrier();
- if (maxloops == 0) {
- printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
- dprintk(D_CMD, "DBRI: Chip never completed command buffer\n");
- } else {
- while ((--maxloops) > 0 && (!dbri->wait_seen))
- dbri_process_interrupt_buffer(dbri);
- if (maxloops == 0) {
- printk(KERN_ERR "DBRI: Chip never acked WAIT\n");
- dprintk(D_CMD, "DBRI: Chip never acked WAIT\n");
- } else {
- dprintk(D_CMD, "Chip completed command "
- "buffer (%d)\n", MAXLOOPS - maxloops);
- }
- }
+ reg = sbus_readl(dbri->regs + REG0);
+ reg |= D_P;
+ sbus_writel(reg, dbri->regs + REG0);
/*spin_unlock(&dbri->lock); */
}
@@ -757,10 +766,11 @@ static void dbri_initialize(snd_dbri_t * dbri)
for (n = 0; n < DBRI_NO_PIPES; n++)
dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1;
- /* We should query the openprom to see what burst sizes this
- * SBus supports. For now, just disable all SBus bursts */
+ /* A brute approach - DBRI falls back to working burst size by itself
+ * On SS20 D_S does not work, so do not try so high. */
tmp = sbus_readl(dbri->regs + REG0);
- tmp &= ~(D_G | D_S | D_E);
+ tmp |= D_G | D_E;
+ tmp &= ~D_S;
sbus_writel(tmp, dbri->regs + REG0);
/*
@@ -805,13 +815,13 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
volatile int *cmd;
if (pipe < 0 || pipe > 31) {
- printk("DBRI: reset_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n");
return;
}
sdp = dbri->pipes[pipe].sdp;
if (sdp == 0) {
- printk("DBRI: reset_pipe called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n");
return;
}
@@ -834,12 +844,12 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
{
if (pipe < 0 || pipe > 31) {
- printk("DBRI: setup_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
return;
}
if ((sdp & 0xf800) != sdp) {
- printk("DBRI: setup_pipe called with strange SDP value\n");
+ printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n");
/* sdp &= 0xf800; */
}
@@ -872,13 +882,13 @@ static void link_time_slot(snd_dbri_t * dbri, int pipe,
int nextpipe;
if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) {
- printk
- ("DBRI: link_time_slot called with illegal pipe number\n");
+ printk(KERN_ERR
+ "DBRI: link_time_slot called with illegal pipe number\n");
return;
}
if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) {
- printk("DBRI: link_time_slot called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n");
return;
}
@@ -960,8 +970,8 @@ static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
int val;
if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) {
- printk
- ("DBRI: unlink_time_slot called with illegal pipe number\n");
+ printk(KERN_ERR
+ "DBRI: unlink_time_slot called with illegal pipe number\n");
return;
}
@@ -1001,22 +1011,22 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
volatile s32 *cmd;
if (pipe < 16 || pipe > 31) {
- printk("DBRI: xmit_fixed: Illegal pipe number\n");
+ printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
- printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
- printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
return;
}
if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
- printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
return;
}
@@ -1036,17 +1046,17 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
{
if (pipe < 16 || pipe > 31) {
- printk("DBRI: recv_fixed called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
- printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
return;
}
if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
- printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe);
return;
}
@@ -1075,12 +1085,12 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
int last_desc = -1;
if (info->pipe < 0 || info->pipe > 15) {
- printk("DBRI: setup_descs: Illegal pipe number\n");
+ printk(KERN_ERR "DBRI: setup_descs: Illegal pipe number\n");
return -2;
}
if (dbri->pipes[info->pipe].sdp == 0) {
- printk("DBRI: setup_descs: Uninitialized pipe %d\n",
+ printk(KERN_ERR "DBRI: setup_descs: Uninitialized pipe %d\n",
info->pipe);
return -2;
}
@@ -1090,20 +1100,20 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
if (streamno == DBRI_PLAY) {
if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
- printk("DBRI: setup_descs: Called on receive pipe %d\n",
+ printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n",
info->pipe);
return -2;
}
} else {
if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
- printk
- ("DBRI: setup_descs: Called on transmit pipe %d\n",
+ printk(KERN_ERR
+ "DBRI: setup_descs: Called on transmit pipe %d\n",
info->pipe);
return -2;
}
/* Should be able to queue multiple buffers to receive on a pipe */
if (pipe_active(dbri, info->pipe)) {
- printk("DBRI: recv_on_pipe: Called on active pipe %d\n",
+ printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n",
info->pipe);
return -2;
}
@@ -1120,7 +1130,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
break;
}
if (desc == DBRI_NO_DESCS) {
- printk("DBRI: setup_descs: No descriptors\n");
+ printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
return -1;
}
@@ -1165,7 +1175,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
}
if (first_desc == -1 || last_desc == -1) {
- printk("DBRI: setup_descs: Not enough descriptors available\n");
+ printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n");
return -1;
}
@@ -1270,7 +1280,7 @@ static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave,
int divisor = 12288 / clockrate;
if (divisor > 255 || divisor * clockrate != 12288)
- printk("DBRI: illegal bits_per_frame in setup_chi\n");
+ printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n");
*(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
| D_CHI_BPF(bits_per_frame));
@@ -1474,7 +1484,6 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
/* Temporarily mute outputs, and wait 1/8000 sec (125 us)
* to make sure this takes. This avoids clicking noises.
*/
-
cs4215_setdata(dbri, 1);
udelay(125);
@@ -1530,8 +1539,8 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
tmp |= D_C; /* Enable CHI */
sbus_writel(tmp, dbri->regs + REG0);
- for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) {
- udelay(125);
+ for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
+ msleep_interruptible(1);
}
if (i == 0) {
dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
@@ -1678,8 +1687,8 @@ buffer and calls dbri_process_one_interrupt() for each interrupt word.
Complicated interrupts are handled by dedicated functions (which
appear first in this file). Any pending interrupts can be serviced by
calling dbri_process_interrupt_buffer(), which works even if the CPU's
-interrupts are disabled. This function is used by dbri_cmdsend()
-to make sure we're synced up with the chip after each command sequence,
+interrupts are disabled. This function is used by dbri_cmdlock()
+to make sure we're synced up with the chip before each command sequence,
even if we're running cli'ed.
*/
@@ -1765,11 +1774,13 @@ DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0);
* Called by main interrupt handler when DBRI signals transmission complete
* on a pipe (interrupt triggered by the B bit in a transmit descriptor).
*
- * Walks through the pipe's list of transmit buffer descriptors, releasing
- * each one's DMA buffer (if present), flagging the descriptor available,
- * and signaling its callback routine (if present), before proceeding
- * to the next one. Stops when the first descriptor is found without
+ * Walks through the pipe's list of transmit buffer descriptors and marks
+ * them as available. Stops when the first descriptor is found without
* TBC (Transmit Buffer Complete) set, or we've run through them all.
+ *
+ * The DMA buffers are not released, but re-used. Since the transmit buffer
+ * descriptors are not clobbered, they can be re-submitted as is. This is
+ * done by the xmit_descs() tasklet above since that could take longer.
*/
static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
@@ -1885,7 +1896,11 @@ static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
}
if (channel == D_INTR_CMD && command == D_WAIT) {
- dbri->wait_seen++;
+ dbri->wait_ackd = val;
+ if (dbri->wait_send != val) {
+ printk(KERN_ERR "Processing wait command %d when %d was send.\n",
+ val, dbri->wait_send);
+ }
return;
}
@@ -1994,8 +2009,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
* The only one I've seen is MRR, which will be triggered
* if you let a transmit pipe underrun, then try to CDP it.
*
- * If these things persist, we should probably reset
- * and re-init the chip.
+ * If these things persist, we reset the chip.
*/
if ((++errcnt) % 10 == 0) {
dprintk(D_INT, "Interrupt errors exceeded.\n");
@@ -2094,7 +2108,7 @@ static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
if ((ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params))) < 0) {
- snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret);
+ printk(KERN_ERR "malloc_pages failed with %d\n", ret);
return ret;
}
@@ -2455,8 +2469,7 @@ static int __init snd_dbri_mixer(snd_dbri_t * dbri)
for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
if ((err = snd_ctl_add(card,
- snd_ctl_new1(&dbri_controls[idx],
- dbri))) < 0)
+ snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
return err;
}
@@ -2490,8 +2503,6 @@ static void dbri_debug_read(snd_info_entry_t * entry,
int pipe;
snd_iprintf(buffer, "debug=%d\n", dbri_debug);
- snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n",
- dbri->chi_in_pipe, dbri->chi_out_pipe);
for (pipe = 0; pipe < 32; pipe++) {
if (pipe_active(dbri, pipe)) {
struct dbri_pipe *pptr = &dbri->pipes[pipe];
@@ -2506,18 +2517,6 @@ static void dbri_debug_read(snd_info_entry_t * entry,
}
}
}
-
-static void dbri_debug_write(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
-{
- char line[80];
- int i;
-
- if (snd_info_get_line(buffer, line, 80) == 0) {
- sscanf(line, "%d\n", &i);
- dbri_debug = i & 0x3f;
- }
-}
#endif
void snd_dbri_proc(snd_dbri_t * dbri)
@@ -2531,9 +2530,7 @@ void snd_dbri_proc(snd_dbri_t * dbri)
#ifdef DBRI_DEBUG
err = snd_card_proc_new(dbri->card, "debug", &entry);
snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */
- entry->c.text.write_size = 256;
- entry->c.text.write = dbri_debug_write;
+ entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
#endif
}
@@ -2637,7 +2634,11 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
return -ENOENT;
}
- prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+ err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+ if (err < 0) {
+ printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev);
+ return -ENODEV;
+ }
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(snd_dbri_t));
@@ -2657,26 +2658,20 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
}
dbri = (snd_dbri_t *) card->private_data;
- if ((err = snd_dbri_pcm(dbri)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_dbri_pcm(dbri)) < 0)
+ goto _err;
- if ((err = snd_dbri_mixer(dbri)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_dbri_mixer(dbri)) < 0)
+ goto _err;
/* /proc file handling */
snd_dbri_proc(dbri);
- if ((err = snd_card_register(card)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
dev, dbri->regs,
@@ -2684,6 +2679,11 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
dev++;
return 0;
+
+ _err:
+ snd_dbri_free(dbri);
+ snd_card_free(card);
+ return err;
}
/* Probe for the dbri chip and then attach the driver. */
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 60d0b2c66698..9e2b4c0c8a8a 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -40,7 +40,7 @@ int snd_emux_new(snd_emux_t **remu)
snd_emux_t *emu;
*remu = NULL;
- emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(*emu), GFP_KERNEL);
if (emu == NULL)
return -ENOMEM;
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index e41b28d9bf52..8ccd33f4aa57 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -146,7 +146,7 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
int i, type, cap;
/* Allocate structures for this channel */
- if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+ if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
snd_printk("no memory\n");
return NULL;
}
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index f13b038329eb..751bf1272af3 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -98,7 +98,6 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
vp = emu->ops.get_voice(emu, port);
if (vp == NULL || vp->ch < 0)
continue;
- snd_assert(vp->emu != NULL && vp->hw != NULL, return);
if (STATE_IS_PLAYING(vp->state))
emu->ops.terminate(vp);
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 901a7db05bde..d0925ea50838 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -266,7 +266,7 @@ newsf(snd_sf_list_t *sflist, int type, char *name)
}
/* not found -- create a new one */
- sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
+ sf = kzalloc(sizeof(*sf), GFP_KERNEL);
if (sf == NULL)
return NULL;
sf->id = sflist->fonts_size;
@@ -346,7 +346,7 @@ sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
{
snd_sf_zone_t *zp;
- if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
+ if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
return NULL;
zp->next = sf->zones;
sf->zones = zp;
@@ -377,7 +377,7 @@ sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
{
snd_sf_sample_t *sp;
- if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
+ if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
return NULL;
sp->next = sf->samples;
@@ -1362,7 +1362,7 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
{
snd_sf_list_t *sflist;
- if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
+ if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
return NULL;
init_MUTEX(&sflist->presets_mutex);
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 8b131a11e549..5f75bf31bc36 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -38,7 +38,7 @@ snd_util_memhdr_new(int memsize)
{
snd_util_memhdr_t *hdr;
- hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
+ hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
if (hdr == NULL)
return NULL;
hdr->size = memsize;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 8298c462c291..d5ae2055b896 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -41,10 +41,12 @@
#include <sound/driver.h>
#include <linux/bitops.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/usb.h>
+#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -79,7 +81,7 @@ module_param_array(vid, int, NULL, 0444);
MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
module_param_array(pid, int, NULL, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-module_param(nrpacks, int, 0444);
+module_param(nrpacks, int, 0644);
MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
module_param(async_unlink, bool, 0444);
MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
@@ -97,7 +99,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
#define MAX_PACKS 10
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
-#define MAX_URBS 5 /* max. 20ms long packets */
+#define MAX_URBS 8
#define SYNC_URBS 4 /* always four urbs for sync */
#define MIN_PACKS_URB 1 /* minimum 1 packet per urb */
@@ -126,11 +128,10 @@ struct audioformat {
struct snd_urb_ctx {
struct urb *urb;
+ unsigned int buffer_size; /* size of data buffer, if data URB */
snd_usb_substream_t *subs;
int index; /* index for urb array */
int packets; /* number of packets per urb */
- int transfer; /* transferred size */
- char *buf; /* buffer for capture */
};
struct snd_urb_ops {
@@ -165,12 +166,11 @@ struct snd_usb_substream {
unsigned int curframesize; /* current packet size in frames (for capture) */
unsigned int fill_max: 1; /* fill max packet size always */
unsigned int fmt_type; /* USB audio format type (1-3) */
+ unsigned int packs_per_ms; /* packets per millisecond (for playback) */
unsigned int running: 1; /* running status */
- unsigned int hwptr; /* free frame position in the buffer (only for playback) */
unsigned int hwptr_done; /* processed frame position in the buffer */
- unsigned int transfer_sched; /* scheduled frames since last period (for playback) */
unsigned int transfer_done; /* processed frames since last period update */
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
@@ -178,13 +178,14 @@ struct snd_usb_substream {
unsigned int nurbs; /* # urbs */
snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */
- char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */
- char *tmpbuf; /* temporary buffer for playback */
+ char *syncbuf; /* sync buffer for all sync URBs */
+ dma_addr_t sync_dma; /* DMA address of syncbuf */
u64 formats; /* format bitmasks (all or'ed) */
unsigned int num_formats; /* number of supported audio formats (list) */
struct list_head fmt_list; /* format list */
spinlock_t lock;
+ struct tasklet_struct start_period_elapsed; /* for start trigger */
struct snd_urb_ops ops; /* callbacks (must be filled at init) */
};
@@ -311,27 +312,17 @@ static int prepare_capture_urb(snd_usb_substream_t *subs,
struct urb *urb)
{
int i, offs;
- unsigned long flags;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
offs = 0;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->number_of_packets = 0;
- spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) {
urb->iso_frame_desc[i].offset = offs;
urb->iso_frame_desc[i].length = subs->curpacksize;
offs += subs->curpacksize;
- urb->number_of_packets++;
- subs->transfer_sched += subs->curframesize;
- if (subs->transfer_sched >= runtime->period_size) {
- subs->transfer_sched -= runtime->period_size;
- break;
- }
}
- spin_unlock_irqrestore(&subs->lock, flags);
- urb->transfer_buffer = ctx->buf;
urb->transfer_buffer_length = offs;
+ urb->number_of_packets = ctx->packets;
#if 0 // for check
if (! urb->bandwidth) {
int bustime;
@@ -359,6 +350,7 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
unsigned char *cp;
int i;
unsigned int stride, len, oldptr;
+ int period_elapsed = 0;
stride = runtime->frame_bits >> 3;
@@ -378,6 +370,10 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
if (subs->hwptr_done >= runtime->buffer_size)
subs->hwptr_done -= runtime->buffer_size;
subs->transfer_done += len;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
+ }
spin_unlock_irqrestore(&subs->lock, flags);
/* copy a data chunk */
if (oldptr + len > runtime->buffer_size) {
@@ -388,15 +384,9 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
} else {
memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
}
- /* update the pointer, call callback if necessary */
- spin_lock_irqsave(&subs->lock, flags);
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- spin_unlock_irqrestore(&subs->lock, flags);
- snd_pcm_period_elapsed(subs->pcm_substream);
- } else
- spin_unlock_irqrestore(&subs->lock, flags);
}
+ if (period_elapsed)
+ snd_pcm_period_elapsed(subs->pcm_substream);
return 0;
}
@@ -492,12 +482,10 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
/*
* prepare urb for playback data pipe
*
- * we copy the data directly from the pcm buffer.
- * the current position to be copied is held in hwptr field.
- * since a urb can handle only a single linear buffer, if the total
- * transferred area overflows the buffer boundary, we cannot send
- * it directly from the buffer. thus the data is once copied to
- * a temporary buffer and urb points to that.
+ * Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
*/
static int prepare_playback_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
@@ -506,6 +494,7 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
int i, stride, offs;
unsigned int counts;
unsigned long flags;
+ int period_elapsed = 0;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
stride = runtime->frame_bits >> 3;
@@ -530,80 +519,85 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
urb->iso_frame_desc[i].length = counts * stride;
offs += counts;
urb->number_of_packets++;
- subs->transfer_sched += counts;
- if (subs->transfer_sched >= runtime->period_size) {
- subs->transfer_sched -= runtime->period_size;
+ subs->transfer_done += counts;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
if (subs->fmt_type == USB_FORMAT_TYPE_II) {
- if (subs->transfer_sched > 0) {
- /* FIXME: fill-max mode is not supported yet */
- offs -= subs->transfer_sched;
- counts -= subs->transfer_sched;
- urb->iso_frame_desc[i].length = counts * stride;
- subs->transfer_sched = 0;
+ if (subs->transfer_done > 0) {
+ /* FIXME: fill-max mode is not
+ * supported yet */
+ offs -= subs->transfer_done;
+ counts -= subs->transfer_done;
+ urb->iso_frame_desc[i].length =
+ counts * stride;
+ subs->transfer_done = 0;
}
i++;
if (i < ctx->packets) {
/* add a transfer delimiter */
- urb->iso_frame_desc[i].offset = offs * stride;
+ urb->iso_frame_desc[i].offset =
+ offs * stride;
urb->iso_frame_desc[i].length = 0;
urb->number_of_packets++;
}
+ break;
}
- break;
}
+ /* finish at the frame boundary at/after the period boundary */
+ if (period_elapsed &&
+ (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1)
+ break;
}
- if (subs->hwptr + offs > runtime->buffer_size) {
- /* err, the transferred area goes over buffer boundary.
- * copy the data to the temp buffer.
- */
- int len;
- len = runtime->buffer_size - subs->hwptr;
- urb->transfer_buffer = subs->tmpbuf;
- memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * stride, len * stride);
- memcpy(subs->tmpbuf + len * stride, runtime->dma_area, (offs - len) * stride);
- subs->hwptr += offs;
- subs->hwptr -= runtime->buffer_size;
+ if (subs->hwptr_done + offs > runtime->buffer_size) {
+ /* err, the transferred area goes over buffer boundary. */
+ unsigned int len = runtime->buffer_size - subs->hwptr_done;
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done * stride,
+ len * stride);
+ memcpy(urb->transfer_buffer + len * stride,
+ runtime->dma_area,
+ (offs - len) * stride);
} else {
- /* set the buffer pointer */
- urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride;
- subs->hwptr += offs;
- if (subs->hwptr == runtime->buffer_size)
- subs->hwptr = 0;
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done * stride,
+ offs * stride);
}
+ subs->hwptr_done += offs;
+ if (subs->hwptr_done >= runtime->buffer_size)
+ subs->hwptr_done -= runtime->buffer_size;
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
- ctx->transfer = offs;
-
+ if (period_elapsed) {
+ if (likely(subs->running))
+ snd_pcm_period_elapsed(subs->pcm_substream);
+ else
+ tasklet_hi_schedule(&subs->start_period_elapsed);
+ }
return 0;
}
/*
* process after playback data complete
- *
- * update the current position and call callback if a period is processed.
+ * - nothing to do
*/
static int retire_playback_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- unsigned long flags;
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
-
- spin_lock_irqsave(&subs->lock, flags);
- subs->transfer_done += ctx->transfer;
- subs->hwptr_done += ctx->transfer;
- ctx->transfer = 0;
- if (subs->hwptr_done >= runtime->buffer_size)
- subs->hwptr_done -= runtime->buffer_size;
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- spin_unlock_irqrestore(&subs->lock, flags);
- snd_pcm_period_elapsed(subs->pcm_substream);
- } else
- spin_unlock_irqrestore(&subs->lock, flags);
return 0;
}
+/*
+ * Delay the snd_pcm_period_elapsed() call until after the start trigger
+ * callback so that we're not longer in the substream's lock.
+ */
+static void start_period_elapsed(unsigned long data)
+{
+ snd_usb_substream_t *subs = (snd_usb_substream_t *)data;
+ snd_pcm_period_elapsed(subs->pcm_substream);
+}
+
/*
*/
@@ -683,6 +677,42 @@ static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs)
}
+/* get the physical page pointer at the given offset */
+static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs,
+ unsigned long offset)
+{
+ void *pageptr = subs->runtime->dma_area + offset;
+ return vmalloc_to_page(pageptr);
+}
+
+/* allocate virtual buffer; may be called more than once */
+static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
+{
+ snd_pcm_runtime_t *runtime = subs->runtime;
+ if (runtime->dma_area) {
+ if (runtime->dma_bytes >= size)
+ return 0; /* already large enough */
+ vfree_nocheck(runtime->dma_area);
+ }
+ runtime->dma_area = vmalloc_nocheck(size);
+ if (! runtime->dma_area)
+ return -ENOMEM;
+ runtime->dma_bytes = size;
+ return 0;
+}
+
+/* free virtual buffer; may be called more than once */
+static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
+{
+ snd_pcm_runtime_t *runtime = subs->runtime;
+ if (runtime->dma_area) {
+ vfree_nocheck(runtime->dma_area);
+ runtime->dma_area = NULL;
+ }
+ return 0;
+}
+
+
/*
* unlink active urbs.
*/
@@ -705,10 +735,9 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
if (test_bit(i, &subs->active_mask)) {
if (! test_and_set_bit(i, &subs->unlink_mask)) {
struct urb *u = subs->dataurb[i].urb;
- if (async) {
- u->transfer_flags |= URB_ASYNC_UNLINK;
+ if (async)
usb_unlink_urb(u);
- } else
+ else
usb_kill_urb(u);
}
}
@@ -718,10 +747,9 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
if (test_bit(i+16, &subs->active_mask)) {
if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
struct urb *u = subs->syncurb[i].urb;
- if (async) {
- u->transfer_flags |= URB_ASYNC_UNLINK;
+ if (async)
usb_unlink_urb(u);
- } else
+ else
usb_kill_urb(u);
}
}
@@ -824,8 +852,14 @@ static int wait_clear_urbs(snd_usb_substream_t *subs)
*/
static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream)
{
- snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data;
- return subs->hwptr_done;
+ snd_usb_substream_t *subs;
+ snd_pcm_uframes_t hwptr_done;
+
+ subs = (snd_usb_substream_t *)substream->runtime->private_data;
+ spin_lock(&subs->lock);
+ hwptr_done = subs->hwptr_done;
+ spin_unlock(&subs->lock);
+ return hwptr_done;
}
@@ -858,11 +892,13 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static void release_urb_ctx(snd_urb_ctx_t *u)
{
if (u->urb) {
+ if (u->buffer_size)
+ usb_buffer_free(u->subs->dev, u->buffer_size,
+ u->urb->transfer_buffer,
+ u->urb->transfer_dma);
usb_free_urb(u->urb);
u->urb = NULL;
}
- kfree(u->buf);
- u->buf = NULL;
}
/*
@@ -880,8 +916,9 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
release_urb_ctx(&subs->dataurb[i]);
for (i = 0; i < SYNC_URBS; i++)
release_urb_ctx(&subs->syncurb[i]);
- kfree(subs->tmpbuf);
- subs->tmpbuf = NULL;
+ usb_buffer_free(subs->dev, SYNC_URBS * 4,
+ subs->syncbuf, subs->sync_dma);
+ subs->syncbuf = NULL;
subs->nurbs = 0;
}
@@ -893,7 +930,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
{
unsigned int maxsize, n, i;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
- unsigned int npacks[MAX_URBS], urb_packs, total_packs;
+ unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
/* calculate the frequency in 16.16 format */
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -920,24 +957,40 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
else
subs->curpacksize = maxsize;
- if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
- urb_packs = nrpacks;
+ if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
+ packs_per_ms = 8 >> subs->datainterval;
else
- urb_packs = (nrpacks * 8) >> subs->datainterval;
+ packs_per_ms = 1;
+ subs->packs_per_ms = packs_per_ms;
- /* allocate a temporary buffer for playback */
if (is_playback) {
- subs->tmpbuf = kmalloc(maxsize * urb_packs, GFP_KERNEL);
- if (! subs->tmpbuf) {
- snd_printk(KERN_ERR "cannot malloc tmpbuf\n");
- return -ENOMEM;
- }
- }
+ urb_packs = nrpacks;
+ urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
+ urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
+ } else
+ urb_packs = 1;
+ urb_packs *= packs_per_ms;
/* decide how many packets to be used */
- total_packs = (period_bytes + maxsize - 1) / maxsize;
- if (total_packs < 2 * MIN_PACKS_URB)
- total_packs = 2 * MIN_PACKS_URB;
+ if (is_playback) {
+ unsigned int minsize;
+ /* determine how small a packet can be */
+ minsize = (subs->freqn >> (16 - subs->datainterval))
+ * (frame_bits >> 3);
+ /* with sync from device, assume it can be 12% lower */
+ if (subs->syncpipe)
+ minsize -= minsize >> 3;
+ minsize = max(minsize, 1u);
+ total_packs = (period_bytes + minsize - 1) / minsize;
+ /* round up to multiple of packs_per_ms */
+ total_packs = (total_packs + packs_per_ms - 1)
+ & ~(packs_per_ms - 1);
+ /* we need at least two URBs for queueing */
+ if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
+ total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
+ } else {
+ total_packs = MAX_URBS * urb_packs;
+ }
subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
if (subs->nurbs > MAX_URBS) {
/* too much... */
@@ -956,7 +1009,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
subs->nurbs = 2;
npacks[0] = (total_packs + 1) / 2;
npacks[1] = total_packs - npacks[0];
- } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB) {
+ } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
/* the last packet is too small.. */
if (subs->nurbs > 2) {
/* merge to the first one */
@@ -975,27 +1028,20 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
snd_urb_ctx_t *u = &subs->dataurb[i];
u->index = i;
u->subs = subs;
- u->transfer = 0;
u->packets = npacks[i];
+ u->buffer_size = maxsize * u->packets;
if (subs->fmt_type == USB_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */
- if (! is_playback) {
- /* allocate a capture buffer per urb */
- u->buf = kmalloc(maxsize * u->packets, GFP_KERNEL);
- if (! u->buf) {
- release_substream_urbs(subs, 0);
- return -ENOMEM;
- }
- }
u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
- if (! u->urb) {
- release_substream_urbs(subs, 0);
- return -ENOMEM;
- }
- u->urb->dev = subs->dev;
+ if (! u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer =
+ usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
+ &u->urb->transfer_dma);
+ if (! u->urb->transfer_buffer)
+ goto out_of_memory;
u->urb->pipe = subs->datapipe;
- u->urb->transfer_flags = URB_ISO_ASAP;
- u->urb->number_of_packets = u->packets;
+ u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
u->urb->interval = 1 << subs->datainterval;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
@@ -1003,21 +1049,24 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
if (subs->syncpipe) {
/* allocate and initialize sync urbs */
+ subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
+ GFP_KERNEL, &subs->sync_dma);
+ if (! subs->syncbuf)
+ goto out_of_memory;
for (i = 0; i < SYNC_URBS; i++) {
snd_urb_ctx_t *u = &subs->syncurb[i];
u->index = i;
u->subs = subs;
u->packets = 1;
u->urb = usb_alloc_urb(1, GFP_KERNEL);
- if (! u->urb) {
- release_substream_urbs(subs, 0);
- return -ENOMEM;
- }
+ if (! u->urb)
+ goto out_of_memory;
u->urb->transfer_buffer = subs->syncbuf + i * 4;
+ u->urb->transfer_dma = subs->sync_dma + i * 4;
u->urb->transfer_buffer_length = 4;
- u->urb->dev = subs->dev;
u->urb->pipe = subs->syncpipe;
- u->urb->transfer_flags = URB_ISO_ASAP;
+ u->urb->transfer_flags = URB_ISO_ASAP |
+ URB_NO_TRANSFER_DMA_MAP;
u->urb->number_of_packets = 1;
u->urb->interval = 1 << subs->syncinterval;
u->urb->context = u;
@@ -1025,6 +1074,10 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
}
}
return 0;
+
+out_of_memory:
+ release_substream_urbs(subs, 0);
+ return -ENOMEM;
}
@@ -1293,7 +1346,8 @@ static int snd_usb_hw_params(snd_pcm_substream_t *substream,
unsigned int channels, rate, format;
int ret, changed;
- ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+ ret = snd_pcm_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(hw_params));
if (ret < 0)
return ret;
@@ -1349,7 +1403,7 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream)
subs->cur_rate = 0;
subs->period_bytes = 0;
release_substream_urbs(subs, 0);
- return snd_pcm_lib_free_pages(substream);
+ return snd_pcm_free_vmalloc_buffer(substream);
}
/*
@@ -1372,9 +1426,7 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
/* reset the pointer */
- subs->hwptr = 0;
subs->hwptr_done = 0;
- subs->transfer_sched = 0;
subs->transfer_done = 0;
subs->phase = 0;
@@ -1387,10 +1439,12 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
static snd_pcm_hardware_t snd_usb_playback =
{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .buffer_bytes_max = (128*1024),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .buffer_bytes_max = (256*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
.periods_min = 2,
@@ -1399,10 +1453,12 @@ static snd_pcm_hardware_t snd_usb_playback =
static snd_pcm_hardware_t snd_usb_capture =
{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .buffer_bytes_max = (128*1024),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .buffer_bytes_max = (256*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
.periods_min = 2,
@@ -1794,6 +1850,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = {
.prepare = snd_usb_pcm_prepare,
.trigger = snd_usb_pcm_trigger,
.pointer = snd_usb_pcm_pointer,
+ .page = snd_pcm_get_vmalloc_page,
};
static snd_pcm_ops_t snd_usb_capture_ops = {
@@ -1805,6 +1862,7 @@ static snd_pcm_ops_t snd_usb_capture_ops = {
.prepare = snd_usb_pcm_prepare,
.trigger = snd_usb_pcm_trigger,
.pointer = snd_usb_pcm_pointer,
+ .page = snd_pcm_get_vmalloc_page,
};
@@ -2021,6 +2079,9 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
INIT_LIST_HEAD(&subs->fmt_list);
spin_lock_init(&subs->lock);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tasklet_init(&subs->start_period_elapsed, start_period_elapsed,
+ (unsigned long)subs);
subs->stream = as;
subs->direction = stream;
@@ -2029,10 +2090,6 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
subs->ops = audio_urb_ops[stream];
else
subs->ops = audio_urb_ops_high_speed[stream];
- snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream,
- SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 64 * 1024, 128 * 1024);
snd_pcm_set_ops(as->pcm, stream,
stream == SNDRV_PCM_STREAM_PLAYBACK ?
&snd_usb_playback_ops : &snd_usb_capture_ops);
@@ -2078,7 +2135,6 @@ static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
snd_usb_stream_t *stream = pcm->private_data;
if (stream) {
stream->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
snd_usb_audio_stream_free(stream);
}
}
@@ -3080,7 +3136,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
return -ENOMEM;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_card_free(card);
return -ENOMEM;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 5778a9b725ec..e0d0365453b3 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -44,6 +44,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/timer.h>
#include <linux/usb.h>
#include <sound/core.h>
#include <sound/minors.h>
@@ -56,6 +57,12 @@
*/
/* #define DUMP_PACKETS */
+/*
+ * how long to wait after some USB errors, so that khubd can disconnect() us
+ * without too many spurious errors
+ */
+#define ERROR_DELAY_JIFFIES (HZ / 10)
+
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("USB Audio/MIDI helper module");
@@ -100,6 +107,7 @@ struct snd_usb_midi {
snd_rawmidi_t* rmidi;
struct usb_protocol_ops* usb_protocol_ops;
struct list_head list;
+ struct timer_list error_timer;
struct snd_usb_midi_endpoint {
snd_usb_midi_out_endpoint_t *out;
@@ -141,7 +149,8 @@ struct snd_usb_midi_in_endpoint {
struct usbmidi_in_port {
snd_rawmidi_substream_t* substream;
} ports[0x10];
- int seen_f5;
+ u8 seen_f5;
+ u8 error_resubmit;
int current_port;
};
@@ -167,14 +176,22 @@ static int snd_usbmidi_submit_urb(struct urb* urb, int flags)
*/
static int snd_usbmidi_urb_error(int status)
{
- if (status == -ENOENT)
- return status; /* killed */
- if (status == -EILSEQ ||
- status == -ECONNRESET ||
- status == -ETIMEDOUT)
- return -ENODEV; /* device removed/shutdown */
- snd_printk(KERN_ERR "urb status %d\n", status);
- return 0; /* continue */
+ switch (status) {
+ /* manually unlinked, or device gone */
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case -ENODEV:
+ return -ENODEV;
+ /* errors that might occur during unplugging */
+ case -EPROTO: /* EHCI */
+ case -ETIMEDOUT: /* OHCI */
+ case -EILSEQ: /* UHCI */
+ return -EIO;
+ default:
+ snd_printk(KERN_ERR "urb status %d\n", status);
+ return 0; /* continue */
+ }
}
/*
@@ -218,8 +235,15 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
urb->actual_length);
} else {
- if (snd_usbmidi_urb_error(urb->status) < 0)
+ int err = snd_usbmidi_urb_error(urb->status);
+ if (err < 0) {
+ if (err != -ENODEV) {
+ ep->error_resubmit = 1;
+ mod_timer(&ep->umidi->error_timer,
+ jiffies + ERROR_DELAY_JIFFIES);
+ }
return;
+ }
}
if (usb_pipe_needs_resubmit(urb->pipe)) {
@@ -236,8 +260,13 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
ep->urb_active = 0;
spin_unlock(&ep->buffer_lock);
if (urb->status < 0) {
- if (snd_usbmidi_urb_error(urb->status) < 0)
+ int err = snd_usbmidi_urb_error(urb->status);
+ if (err < 0) {
+ if (err != -ENODEV)
+ mod_timer(&ep->umidi->error_timer,
+ jiffies + ERROR_DELAY_JIFFIES);
return;
+ }
}
snd_usbmidi_do_output(ep);
}
@@ -276,6 +305,24 @@ static void snd_usbmidi_out_tasklet(unsigned long data)
snd_usbmidi_do_output(ep);
}
+/* called after transfers had been interrupted due to some USB error */
+static void snd_usbmidi_error_timer(unsigned long data)
+{
+ snd_usb_midi_t *umidi = (snd_usb_midi_t *)data;
+ int i;
+
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+ snd_usb_midi_in_endpoint_t *in = umidi->endpoints[i].in;
+ if (in && in->error_resubmit) {
+ in->error_resubmit = 0;
+ in->urb->dev = umidi->chip->dev;
+ snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC);
+ }
+ if (umidi->endpoints[i].out)
+ snd_usbmidi_do_output(umidi->endpoints[i].out);
+ }
+}
+
/* helper function to send static data that may not DMA-able */
static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
const void *data, int len)
@@ -594,17 +641,20 @@ static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep)
static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep,
uint8_t* buffer, int buffer_length)
{
- /* ignore padding bytes at end of buffer */
- while (buffer_length > 0 && buffer[buffer_length - 1] == 0xff)
- --buffer_length;
+ int i;
+
+ /* FF indicates end of valid data */
+ for (i = 0; i < buffer_length; ++i)
+ if (buffer[i] == 0xff) {
+ buffer_length = i;
+ break;
+ }
/* handle F5 at end of last buffer */
if (ep->seen_f5)
goto switch_port;
while (buffer_length > 0) {
- int i;
-
/* determine size of data until next F5 */
for (i = 0; i < buffer_length; ++i)
if (buffer[i] == 0xf5)
@@ -671,6 +721,10 @@ static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep)
break;
}
}
+ if (buf_free < ep->max_transfer && buf_free > 0) {
+ *buf = 0xff;
+ --buf_free;
+ }
ep->urb->transfer_buffer_length = ep->max_transfer - buf_free;
}
@@ -765,7 +819,10 @@ static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
{
if (ep->urb) {
- kfree(ep->urb->transfer_buffer);
+ usb_buffer_free(ep->umidi->chip->dev,
+ ep->urb->transfer_buffer_length,
+ ep->urb->transfer_buffer,
+ ep->urb->transfer_dma);
usb_free_urb(ep->urb);
}
kfree(ep);
@@ -784,7 +841,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
int length;
rep->in = NULL;
- ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
if (!ep)
return -ENOMEM;
ep->umidi = umidi;
@@ -799,7 +856,8 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
else
pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
length = usb_maxpacket(umidi->chip->dev, pipe, 0);
- buffer = kmalloc(length, GFP_KERNEL);
+ buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
+ &ep->urb->transfer_dma);
if (!buffer) {
snd_usbmidi_in_endpoint_delete(ep);
return -ENOMEM;
@@ -812,6 +870,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
ep);
+ ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
rep->in = ep;
return 0;
@@ -832,10 +891,10 @@ static unsigned int snd_usbmidi_count_bits(unsigned int x)
*/
static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
{
- if (ep->tasklet.func)
- tasklet_kill(&ep->tasklet);
if (ep->urb) {
- kfree(ep->urb->transfer_buffer);
+ usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer,
+ ep->urb->transfer_buffer,
+ ep->urb->transfer_dma);
usb_free_urb(ep->urb);
}
kfree(ep);
@@ -854,7 +913,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
void* buffer;
rep->out = NULL;
- ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
if (!ep)
return -ENOMEM;
ep->umidi = umidi;
@@ -867,7 +926,8 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
/* we never use interrupt output pipes */
pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
- buffer = kmalloc(ep->max_transfer, GFP_KERNEL);
+ buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer,
+ GFP_KERNEL, &ep->urb->transfer_dma);
if (!buffer) {
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
@@ -875,6 +935,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
ep->max_transfer,
snd_usb_complete_callback(snd_usbmidi_out_urb_complete), ep);
+ ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
spin_lock_init(&ep->buffer_lock);
tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);
@@ -918,8 +979,11 @@ void snd_usbmidi_disconnect(struct list_head* p)
int i;
umidi = list_entry(p, snd_usb_midi_t, list);
+ del_timer_sync(&umidi->error_timer);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+ if (ep->out)
+ tasklet_kill(&ep->out->tasklet);
if (ep->out && ep->out->urb) {
usb_kill_urb(ep->out->urb);
if (umidi->usb_protocol_ops->finish_out_endpoint)
@@ -1473,13 +1537,16 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
int out_ports, in_ports;
int i, err;
- umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
+ umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
if (!umidi)
return -ENOMEM;
umidi->chip = chip;
umidi->iface = iface;
umidi->quirk = quirk;
umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
+ init_timer(&umidi->error_timer);
+ umidi->error_timer.function = snd_usbmidi_error_timer;
+ umidi->error_timer.data = (unsigned long)umidi;
/* detect the endpoint(s) to use */
memset(endpoints, 0, sizeof(endpoints));
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index fa7056f5caaf..c3c08c9cb46e 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -824,7 +824,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
if (check_ignored_ctl(state, unitid, control))
return;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return;
@@ -997,7 +997,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
if (check_ignored_ctl(state, unitid, 0))
return;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval)
return;
@@ -1244,7 +1244,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
continue;
if (check_ignored_ctl(state, unitid, valinfo->control))
continue;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
@@ -1430,7 +1430,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
if (check_ignored_ctl(state, unitid, 0))
return 0;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
@@ -1945,7 +1945,7 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
strcpy(chip->card->mixername, "USB Mixer");
- mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+ mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
if (!mixer)
return -ENOMEM;
mixer->chip = chip;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 62dfd28b3b07..0f09e0de52dd 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -957,7 +957,7 @@ static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int c
for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
- usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+ usX2Y_substream[i] = kzalloc(sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
if (NULL == usX2Y_substream[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
return -ENOMEM;
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index ef28061287f2..d0199c4e5551 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -624,7 +624,7 @@ static int usX2Y_pcms_lock_check(snd_card_t *card)
for (s = 0; s < 2; ++s) {
snd_pcm_substream_t *substream;
substream = pcm->streams[s].substream;
- if (substream && substream->open_flag)
+ if (substream && substream->ffile != NULL)
err = -EBUSY;
}
}
diff --git a/usr/Kconfig b/usr/Kconfig
new file mode 100644
index 000000000000..07727f3c7cea
--- /dev/null
+++ b/usr/Kconfig
@@ -0,0 +1,46 @@
+#
+# Configuration for initramfs
+#
+
+config INITRAMFS_SOURCE
+ string "Initramfs source file(s)"
+ default ""
+ help
+ This can be either a single cpio archive with a .cpio suffix or a
+ space-separated list of directories and files for building the
+ initramfs image. A cpio archive should contain a filesystem archive
+ to be used as an initramfs image. Directories should contain a
+ filesystem layout to be included in the initramfs image. Files
+ should contain entries according to the format described by the
+ "usr/gen_init_cpio" program in the kernel tree.
+
+ When multiple directories and files are specified then the
+ initramfs image will be the aggregate of all of them.
+
+ See <file:Documentation/early-userspace/README for more details.
+
+ If you are not sure, leave it blank.
+
+config INITRAMFS_ROOT_UID
+ int "User ID to map to 0 (user root)"
+ depends on INITRAMFS_SOURCE!=""
+ default "0"
+ help
+ This setting is only meaningful if the INITRAMFS_SOURCE is
+ contains a directory. Setting this user ID (UID) to something
+ other than "0" will cause all files owned by that UID to be
+ owned by user root in the initial ramdisk image.
+
+ If you are not sure, leave it set to "0".
+
+config INITRAMFS_ROOT_GID
+ int "Group ID to map to 0 (group root)"
+ depends on INITRAMFS_SOURCE!=""
+ default "0"
+ help
+ This setting is only meaningful if the INITRAMFS_SOURCE is
+ contains a directory. Setting this group ID (GID) to something
+ other than "0" will cause all files owned by that GID to be
+ owned by group root in the initial ramdisk image.
+
+ If you are not sure, leave it set to "0".
diff --git a/usr/Makefile b/usr/Makefile
index 248d5551029d..e2129cb570bb 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -27,7 +27,7 @@ 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: FORCE
+$(obj)/initramfs_list: $(obj)/Makefile FORCE
$(call filechk,initramfs_list)
quiet_cmd_cpio = CPIO $@